diff --git a/.clang-format b/.clang-format index 0d1ed87767337e358799bfa9aa36137f46a9fe37..0bbb1991defead96a8beb762f692c4ed229b1f20 100644 --- a/.clang-format +++ b/.clang-format @@ -254,6 +254,7 @@ ForEachMacros: - 'for_each_free_mem_range' - 'for_each_free_mem_range_reverse' - 'for_each_func_rsrc' + - 'for_each_group_device' - 'for_each_group_evsel' - 'for_each_group_member' - 'for_each_hstate' diff --git a/.gitattributes b/.gitattributes index c9ba5bfc403600a8c9418fd4503574bcb69dc87e..2325c529e1854545a1b611b72ad156bdbc4319cf 100644 --- a/.gitattributes +++ b/.gitattributes @@ -2,3 +2,4 @@ *.[ch] diff=cpp *.dts diff=dts *.dts[io] diff=dts +*.rs diff=rust diff --git a/.gitignore b/.gitignore index 7f86e0837909446b5a619b0c4aa6175af13451e9..9fd4c9533b3dcc8ebf3363c3faa523db1f56bc90 100644 --- a/.gitignore +++ b/.gitignore @@ -16,7 +16,6 @@ *.bin *.bz2 *.c.[012]*.* -*.cover *.dt.yaml *.dtb *.dtbo @@ -34,7 +33,6 @@ *.lz4 *.lzma *.lzo -*.mbx *.mod *.mod.c *.o @@ -51,7 +49,6 @@ *.symversions *.tab.[ch] *.tar -*.usyms *.xz *.zst Module.symvers @@ -112,7 +109,6 @@ modules.order # /include/config/ /include/generated/ -/include/ksym/ /arch/*/include/generated/ # stgit generated dirs diff --git a/.mailmap b/.mailmap index 033955129e454c6f6f61cd0b174f55e97d6e53f6..89b7f33cd33036bb35b84c02ced0e63f223a74b5 100644 --- a/.mailmap +++ b/.mailmap @@ -5,7 +5,8 @@ # same person appearing not to be so or badly displayed. Also allows for # old email addresses to map to new email addresses. # -# For format details, see "MAPPING AUTHORS" in "man git-shortlog". +# For format details, see "man gitmailmap" or "MAPPING AUTHORS" in +# "man git-shortlog" on older systems. # # Please keep this list dictionary sorted. # @@ -70,6 +71,8 @@ Baolin Wang Baolin Wang Bart Van Assche Bart Van Assche +Ben Dooks +Ben Dooks Ben Gardner Ben M Cahill Ben Widawsky @@ -175,12 +178,17 @@ Gustavo Padovan Hanjun Guo Heiko Carstens Heiko Carstens +Heiko Stuebner +Heiko Stuebner +Heiko Stuebner Henk Vergonet Henrik Kretzschmar Henrik Rydberg Herbert Xu Huacai Chen Huacai Chen +J. Bruce Fields +J. Bruce Fields Jacob Shin Jaegeuk Kim Jaegeuk Kim @@ -238,6 +246,7 @@ John Paul Adrian Glaubitz John Stultz +Jonas Gorski Jordan Crouse @@ -271,6 +280,10 @@ Krzysztof Kozlowski Krzysztof Kozlowski Kuninori Morimoto Kuogee Hsieh +Lee Jones +Lee Jones +Lee Jones +Lee Jones Leonard Crestez Leonard Crestez Leonardo Bras Leonard Göhrs @@ -297,6 +310,7 @@ Marek Behún Marek Behún Marek Behun Mark Brown Mark Starovoytov +Markus Schneider-Pargmann Mark Yao Martin Kepplinger Martin Kepplinger diff --git a/CREDITS b/CREDITS index de7e4dbbc5991194ce9bcaeb94a368e79d79832a..8b4882024635dca60f05684699add61a935b58ea 100644 --- a/CREDITS +++ b/CREDITS @@ -383,6 +383,12 @@ E: tomas@nocrew.org W: http://tomas.nocrew.org/ D: dsp56k device driver +N: Srivatsa S. Bhat +E: srivatsa@csail.mit.edu +D: Maintainer of Generic Paravirt-Ops subsystem +D: Maintainer of VMware hypervisor interface +D: Maintainer of VMware virtual PTP clock driver (ptp_vmw) + N: Ross Biro E: ross.biro@gmail.com D: Original author of the Linux networking code diff --git a/Documentation/ABI/obsolete/o2cb b/Documentation/ABI/obsolete/o2cb index fe7e45e17bc79369a4d9cde1d8d33ae00be7f387..8f39b596731d235eddc9ed562b5a37099a3eb709 100644 --- a/Documentation/ABI/obsolete/o2cb +++ b/Documentation/ABI/obsolete/o2cb @@ -1,11 +1,11 @@ What: /sys/o2cb Date: Dec 2005 KernelVersion: 2.6.16 -Contact: ocfs2-devel@oss.oracle.com +Contact: ocfs2-devel@lists.linux.dev Description: Ocfs2-tools looks at 'interface-revision' for versioning information. Each logmask/ file controls a set of debug prints and can be written into with the strings "allow", "deny", or "off". Reading the file returns the current state. Was renamed to /sys/fs/u2cb/ Users: ocfs2-tools. It's sufficient to mail proposed changes to - ocfs2-devel@oss.oracle.com. + ocfs2-devel@lists.linux.dev. diff --git a/Documentation/ABI/removed/o2cb b/Documentation/ABI/removed/o2cb index 20c91adca6d412102dabf73d6b6f387a60d888ec..61cff238fbe8a1baa0ca0ec956d19f89f7a3ae61 100644 --- a/Documentation/ABI/removed/o2cb +++ b/Documentation/ABI/removed/o2cb @@ -1,10 +1,10 @@ What: /sys/o2cb symlink Date: May 2011 KernelVersion: 3.0 -Contact: ocfs2-devel@oss.oracle.com +Contact: ocfs2-devel@lists.linux.dev Description: This is a symlink: /sys/o2cb to /sys/fs/o2cb. The symlink is removed when new versions of ocfs2-tools which know to look in /sys/fs/o2cb are sufficiently prevalent. Don't code new software to look here, it should try /sys/fs/o2cb instead. Users: ocfs2-tools. It's sufficient to mail proposed changes to - ocfs2-devel@oss.oracle.com. + ocfs2-devel@lists.linux.dev. diff --git a/Documentation/ABI/stable/o2cb b/Documentation/ABI/stable/o2cb index b62a967f01a061cd80c1d6670f82dc04bb1a140e..3a83b5c54e93b3ff026b591480e60210801d4457 100644 --- a/Documentation/ABI/stable/o2cb +++ b/Documentation/ABI/stable/o2cb @@ -1,10 +1,10 @@ What: /sys/fs/o2cb/ Date: Dec 2005 KernelVersion: 2.6.16 -Contact: ocfs2-devel@oss.oracle.com +Contact: ocfs2-devel@lists.linux.dev Description: Ocfs2-tools looks at 'interface-revision' for versioning information. Each logmask/ file controls a set of debug prints and can be written into with the strings "allow", "deny", or "off". Reading the file returns the current state. Users: ocfs2-tools. It's sufficient to mail proposed changes to - ocfs2-devel@oss.oracle.com. + ocfs2-devel@lists.linux.dev. diff --git a/Documentation/ABI/stable/sysfs-platform-wmi-bmof b/Documentation/ABI/stable/sysfs-platform-wmi-bmof new file mode 100644 index 0000000000000000000000000000000000000000..a786504b6027e259d796646f81a58936fb0e50a1 --- /dev/null +++ b/Documentation/ABI/stable/sysfs-platform-wmi-bmof @@ -0,0 +1,7 @@ +What: /sys/bus/wmi/devices/05901221-D566-11D1-B2F0-00A0C9062910[-X]/bmof +Date: Jun 2017 +KernelVersion: 4.13 +Description: + Binary MOF metadata used to decribe the details of available ACPI WMI interfaces. + + See Documentation/wmi/devices/wmi-bmof.rst for details. diff --git a/Documentation/ABI/testing/debugfs-dell-wmi-ddv b/Documentation/ABI/testing/debugfs-dell-wmi-ddv index fbcc5d6f7388541637364b933d6fd1686e639d08..81cfc788be15e94ab403164217c79164d04ffa7c 100644 --- a/Documentation/ABI/testing/debugfs-dell-wmi-ddv +++ b/Documentation/ABI/testing/debugfs-dell-wmi-ddv @@ -3,19 +3,32 @@ Date: September 2022 KernelVersion: 6.1 Contact: Armin Wolf Description: - This file contains the contents of the fan sensor information buffer, - which contains fan sensor entries and a terminating character (0xFF). + This file contains the contents of the fan sensor information + buffer, which contains fan sensor entries and a terminating + character (0xFF). - Each fan sensor entry consists of three bytes with an unknown meaning, - interested people may use this file for reverse-engineering. + Each fan sensor entry contains: + + - fan type (single byte) + - fan speed in RPM (two bytes, little endian) + + See Documentation/wmi/devices/dell-wmi-ddv.rst for details. What: /sys/kernel/debug/dell-wmi-ddv-/thermal_sensor_information Date: September 2022 KernelVersion: 6.1 Contact: Armin Wolf Description: - This file contains the contents of the thermal sensor information buffer, - which contains thermal sensor entries and a terminating character (0xFF). + This file contains the contents of the thermal sensor information + buffer, which contains thermal sensor entries and a terminating + character (0xFF). + + Each thermal sensor entry contains: + + - thermal type (single byte) + - current temperature (single byte) + - min. temperature (single byte) + - max. temperature (single byte) + - unknown field (single byte) - Each thermal sensor entry consists of five bytes with an unknown meaning, - interested people may use this file for reverse-engineering. + See Documentation/wmi/devices/dell-wmi-ddv.rst for details. diff --git a/Documentation/ABI/testing/sysfs-block-device b/Documentation/ABI/testing/sysfs-block-device index 7ac7b19b2f7224572652bf850e51f575757fd0ee..2d543cfa4079af03909d25a29f8ab0ad7416f6fd 100644 --- a/Documentation/ABI/testing/sysfs-block-device +++ b/Documentation/ABI/testing/sysfs-block-device @@ -95,3 +95,25 @@ Description: This file does not exist if the HBA driver does not implement support for the SATA NCQ priority feature, regardless of the device support for this feature. + + +What: /sys/block/*/device/cdl_supported +Date: May, 2023 +KernelVersion: v6.5 +Contact: linux-scsi@vger.kernel.org +Description: + (RO) Indicates if the device supports the command duration + limits feature found in some ATA and SCSI devices. + + +What: /sys/block/*/device/cdl_enable +Date: May, 2023 +KernelVersion: v6.5 +Contact: linux-scsi@vger.kernel.org +Description: + (RW) For a device supporting the command duration limits + feature, write to the file to turn on or off the feature. + By default this feature is turned off. + Writing "1" to this file enables the use of command duration + limits for read and write commands in the kernel and turns on + the feature on the device. Writing "0" disables the feature. diff --git a/Documentation/ABI/testing/sysfs-bus-counter b/Documentation/ABI/testing/sysfs-bus-counter index 1417c4272c6ca4e9a2a0c560e0211a89571fd3ef..dc3b3a5c876b2591aae58f6df61f96a9e121bc3c 100644 --- a/Documentation/ABI/testing/sysfs-bus-counter +++ b/Documentation/ABI/testing/sysfs-bus-counter @@ -90,6 +90,60 @@ Description: counter does not freeze at the boundary points, but counts continuously throughout. + interrupt on terminal count: + The output signal is initially low, and will remain low + until the counter reaches zero. The output signal then + goes high and remains high until a new preset value is + set. + + hardware retriggerable one-shot: + The output signal is initially high. The output signal + will go low by a trigger input signal, and will remain + low until the counter reaches zero. The output will then + go high and remain high until the next trigger. A + trigger results in loading the counter to the preset + value and setting the output signal low, thus starting + the one-shot pulse. + + rate generator: + The output signal is initially high. When the counter + has decremented to 1, the output signal goes low for one + clock pulse. The output signal then goes high again, the + counter is reloaded to the preset value, and the process + repeats in a periodic manner as such. + + square wave mode: + The output signal is initially high. + + If the initial count is even, the counter is decremented + by two on succeeding clock pulses. When the count + expires, the output signal changes value and the + counter is reloaded to the preset value. The process + repeats in periodic manner as such. + + If the initial count is odd, the initial count minus one + (an even number) is loaded and then is decremented by + two on succeeding clock pulses. One clock pulse after + the count expires, the output signal goes low and the + counter is reloaded to the preset value minus one. + Succeeding clock pulses decrement the count by two. When + the count expires, the output goes high again and the + counter is reloaded to the preset value minus one. The + process repeats in a periodic manner as such. + + software triggered strobe: + The output signal is initially high. When the count + expires, the output will go low for one clock pulse and + then go high again. The counting sequence is "triggered" + by setting the preset value. + + hardware triggered strobe: + The output signal is initially high. Counting is started + by a trigger input signal. When the count expires, the + output signal will go low for one clock pulse and then + go high again. A trigger results in loading the counter + to the preset value. + What: /sys/bus/counter/devices/counterX/countY/count_mode_available What: /sys/bus/counter/devices/counterX/countY/error_noise_available What: /sys/bus/counter/devices/counterX/countY/function_available diff --git a/Documentation/ABI/testing/sysfs-bus-cxl b/Documentation/ABI/testing/sysfs-bus-cxl index 48ac0d911801ade392f89e76daea4d77be6fdebb..6350dd82b9a9ceb028eaa7a5145a9dcce3413a12 100644 --- a/Documentation/ABI/testing/sysfs-bus-cxl +++ b/Documentation/ABI/testing/sysfs-bus-cxl @@ -58,6 +58,54 @@ Description: affinity for this device. +What: /sys/bus/cxl/devices/memX/security/state +Date: June, 2023 +KernelVersion: v6.5 +Contact: linux-cxl@vger.kernel.org +Description: + (RO) Reading this file will display the CXL security state for + that device. Such states can be: 'disabled', 'sanitize', when + a sanitization is currently underway; or those available only + for persistent memory: 'locked', 'unlocked' or 'frozen'. This + sysfs entry is select/poll capable from userspace to notify + upon completion of a sanitize operation. + + +What: /sys/bus/cxl/devices/memX/security/sanitize +Date: June, 2023 +KernelVersion: v6.5 +Contact: linux-cxl@vger.kernel.org +Description: + (WO) Write a boolean 'true' string value to this attribute to + sanitize the device to securely re-purpose or decommission it. + This is done by ensuring that all user data and meta-data, + whether it resides in persistent capacity, volatile capacity, + or the LSA, is made permanently unavailable by whatever means + is appropriate for the media type. This functionality requires + the device to be not be actively decoding any HPA ranges. + + +What /sys/bus/cxl/devices/memX/security/erase +Date: June, 2023 +KernelVersion: v6.5 +Contact: linux-cxl@vger.kernel.org +Description: + (WO) Write a boolean 'true' string value to this attribute to + secure erase user data by changing the media encryption keys for + all user data areas of the device. + + +What: /sys/bus/cxl/devices/memX/firmware/ +Date: April, 2023 +KernelVersion: v6.5 +Contact: linux-cxl@vger.kernel.org +Description: + (RW) Firmware uploader mechanism. The different files under + this directory can be used to upload and activate new + firmware for CXL devices. The interfaces under this are + documented in sysfs-class-firmware. + + What: /sys/bus/cxl/devices/*/devtype Date: June, 2021 KernelVersion: v5.14 diff --git a/Documentation/ABI/testing/sysfs-bus-usb b/Documentation/ABI/testing/sysfs-bus-usb index cb172db41b34bff0d1eaf04d42792e1847fa2023..be663258b9b792a9397a2f65b74b2ed9ccdbf671 100644 --- a/Documentation/ABI/testing/sysfs-bus-usb +++ b/Documentation/ABI/testing/sysfs-bus-usb @@ -292,6 +292,16 @@ Description: which is marked with early_stop has failed to initialize, it will ignore all future connections until this attribute is clear. +What: /sys/bus/usb/devices/...//port/state +Date: June 2023 +Contact: Roy Luo +Description: + Indicates current state of the USB device attached to the port. + Valid states are: 'not-attached', 'attached', 'powered', + 'reconnecting', 'unauthenticated', 'default', 'addressed', + 'configured', and 'suspended'. This file supports poll() to + monitor the state change from user space. + What: /sys/bus/usb/devices/.../power/usb2_lpm_l1_timeout Date: May 2013 Contact: Mathias Nyman diff --git a/Documentation/ABI/testing/sysfs-class-firmware-attributes b/Documentation/ABI/testing/sysfs-class-firmware-attributes index 4cdba3477176fd89d8e03e67595843d6f7091aef..1b3ecae80b3dd02e0ecdddef8796fb40f81bfc07 100644 --- a/Documentation/ABI/testing/sysfs-class-firmware-attributes +++ b/Documentation/ABI/testing/sysfs-class-firmware-attributes @@ -243,8 +243,8 @@ Description: index: Used with HDD and NVME authentication to set the drive index - that is being referenced (e.g hdd0, hdd1 etc) - This attribute defaults to device 0. + that is being referenced (e.g hdd1, hdd2 etc) + This attribute defaults to device 1. certificate, signature, save_signature: These attributes are used for certificate based authentication. This is diff --git a/Documentation/ABI/testing/sysfs-class-led-driver-aw200xx b/Documentation/ABI/testing/sysfs-class-led-driver-aw200xx new file mode 100644 index 0000000000000000000000000000000000000000..6d4449cf9d71feb7c7f4bfc71c6988f92820c3c3 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-class-led-driver-aw200xx @@ -0,0 +1,5 @@ +What: /sys/class/leds//dim +Date: May 2023 +Description: 64-level DIM current. If you write a negative value or + "auto", the dim will be calculated according to the + brightness. diff --git a/Documentation/ABI/testing/sysfs-class-led-trigger-netdev b/Documentation/ABI/testing/sysfs-class-led-trigger-netdev index 646540950e381ad021eaec6745035896ccd6e7b3..78b62a23b14a0074e0220a87d861bcd3c714a543 100644 --- a/Documentation/ABI/testing/sysfs-class-led-trigger-netdev +++ b/Documentation/ABI/testing/sysfs-class-led-trigger-netdev @@ -13,6 +13,11 @@ Description: Specifies the duration of the LED blink in milliseconds. Defaults to 50 ms. + With hw_control ON, the interval value MUST be set to the + default value and cannot be changed. + Trying to set any value in this specific mode will return + an EINVAL error. + What: /sys/class/leds//link Date: Dec 2017 KernelVersion: 4.16 @@ -39,6 +44,9 @@ Description: If set to 1, the LED will blink for the milliseconds specified in interval to signal transmission. + With hw_control ON, the blink interval is controlled by hardware + and won't reflect the value set in interval. + What: /sys/class/leds//rx Date: Dec 2017 KernelVersion: 4.16 @@ -50,3 +58,84 @@ Description: If set to 1, the LED will blink for the milliseconds specified in interval to signal reception. + + With hw_control ON, the blink interval is controlled by hardware + and won't reflect the value set in interval. + +What: /sys/class/leds//hw_control +Date: Jun 2023 +KernelVersion: 6.5 +Contact: linux-leds@vger.kernel.org +Description: + Communicate whether the LED trigger modes are driven by hardware + or software fallback is used. + + If 0, the LED is using software fallback to blink. + + If 1, the LED is using hardware control to blink and signal the + requested modes. + +What: /sys/class/leds//link_10 +Date: Jun 2023 +KernelVersion: 6.5 +Contact: linux-leds@vger.kernel.org +Description: + Signal the link speed state of 10Mbps of the named network device. + + If set to 0 (default), the LED's normal state is off. + + If set to 1, the LED's normal state reflects the link state + speed of 10MBps of the named network device. + Setting this value also immediately changes the LED state. + +What: /sys/class/leds//link_100 +Date: Jun 2023 +KernelVersion: 6.5 +Contact: linux-leds@vger.kernel.org +Description: + Signal the link speed state of 100Mbps of the named network device. + + If set to 0 (default), the LED's normal state is off. + + If set to 1, the LED's normal state reflects the link state + speed of 100Mbps of the named network device. + Setting this value also immediately changes the LED state. + +What: /sys/class/leds//link_1000 +Date: Jun 2023 +KernelVersion: 6.5 +Contact: linux-leds@vger.kernel.org +Description: + Signal the link speed state of 1000Mbps of the named network device. + + If set to 0 (default), the LED's normal state is off. + + If set to 1, the LED's normal state reflects the link state + speed of 1000Mbps of the named network device. + Setting this value also immediately changes the LED state. + +What: /sys/class/leds//half_duplex +Date: Jun 2023 +KernelVersion: 6.5 +Contact: linux-leds@vger.kernel.org +Description: + Signal the link half duplex state of the named network device. + + If set to 0 (default), the LED's normal state is off. + + If set to 1, the LED's normal state reflects the link half + duplex state of the named network device. + Setting this value also immediately changes the LED state. + +What: /sys/class/leds//full_duplex +Date: Jun 2023 +KernelVersion: 6.5 +Contact: linux-leds@vger.kernel.org +Description: + Signal the link full duplex state of the named network device. + + If set to 0 (default), the LED's normal state is off. + + If set to 1, the LED's normal state reflects the link full + duplex state of the named network device. + Setting this value also immediately changes the LED state. diff --git a/Documentation/ABI/testing/sysfs-class-net-qmi b/Documentation/ABI/testing/sysfs-class-net-qmi index 47e6b97323379bab558ea393e5c3c3623cdcd0c2..b028f5bc86db56895aad708b01dddfff16e1c5ef 100644 --- a/Documentation/ABI/testing/sysfs-class-net-qmi +++ b/Documentation/ABI/testing/sysfs-class-net-qmi @@ -62,7 +62,7 @@ Description: What: /sys/class/net//qmi/pass_through Date: January 2021 KernelVersion: 5.12 -Contact: Subash Abhinov Kasiviswanathan +Contact: Subash Abhinov Kasiviswanathan Description: Boolean. Default: 'N' diff --git a/Documentation/ABI/testing/sysfs-devices-hisi_ptt b/Documentation/ABI/testing/sysfs-devices-hisi_ptt index 82de6d7102660273e941857ea4cce26024117cc1..d7e206b4901c092babc3ca87e2b13df6c51207b3 100644 --- a/Documentation/ABI/testing/sysfs-devices-hisi_ptt +++ b/Documentation/ABI/testing/sysfs-devices-hisi_ptt @@ -59,3 +59,55 @@ Description: (RW) Control the allocated buffer watermark of outbound packets. The available tune data is [0, 1, 2]. Writing a negative value will return an error, and out of range values will be converted to 2. The value indicates a probable level of the event. + +What: /sys/devices/hisi_ptt_/root_port_filters +Date: May 2023 +KernelVersion: 6.5 +Contact: Yicong Yang +Description: This directory contains the files providing the PCIe Root Port filters + information used for PTT trace. Each file is named after the supported + Root Port device name ::.. + + See the description of the "filter" in Documentation/trace/hisi-ptt.rst + for more information. + +What: /sys/devices/hisi_ptt_/root_port_filters/multiselect +Date: May 2023 +KernelVersion: 6.5 +Contact: Yicong Yang +Description: (Read) Indicates if this kind of filter can be selected at the same + time as others filters, or must be used on it's own. 1 indicates + the former case and 0 indicates the latter. + +What: /sys/devices/hisi_ptt_/root_port_filters/ +Date: May 2023 +KernelVersion: 6.5 +Contact: Yicong Yang +Description: (Read) Indicates the filter value of this Root Port filter, which + can be used to control the TLP headers to trace by the PTT trace. + +What: /sys/devices/hisi_ptt_/requester_filters +Date: May 2023 +KernelVersion: 6.5 +Contact: Yicong Yang +Description: This directory contains the files providing the PCIe Requester filters + information used for PTT trace. Each file is named after the supported + Endpoint device name ::.. + + See the description of the "filter" in Documentation/trace/hisi-ptt.rst + for more information. + +What: /sys/devices/hisi_ptt_/requester_filters/multiselect +Date: May 2023 +KernelVersion: 6.5 +Contact: Yicong Yang +Description: (Read) Indicates if this kind of filter can be selected at the same + time as others filters, or must be used on it's own. 1 indicates + the former case and 0 indicates the latter. + +What: /sys/devices/hisi_ptt_/requester_filters/ +Date: May 2023 +KernelVersion: 6.5 +Contact: Yicong Yang +Description: (Read) Indicates the filter value of this Requester filter, which + can be used to control the TLP headers to trace by the PTT trace. diff --git a/Documentation/ABI/testing/sysfs-devices-system-cpu b/Documentation/ABI/testing/sysfs-devices-system-cpu index f54867cadb0f68a80151cf6a59706119b6119047..ecd585ca2d503853e3c2e8cdfa61551be999044e 100644 --- a/Documentation/ABI/testing/sysfs-devices-system-cpu +++ b/Documentation/ABI/testing/sysfs-devices-system-cpu @@ -670,7 +670,7 @@ Description: Preferred MTE tag checking mode "async" Prefer asynchronous mode ================ ============================================== - See also: Documentation/arm64/memory-tagging-extension.rst + See also: Documentation/arch/arm64/memory-tagging-extension.rst What: /sys/devices/system/cpu/nohz_full Date: Apr 2015 diff --git a/Documentation/ABI/testing/sysfs-driver-eud b/Documentation/ABI/testing/sysfs-driver-eud index 83f3872182a4098b634160eab6bea514c0342239..2bab0db2d2f0f257085a870a58a259dc828f4087 100644 --- a/Documentation/ABI/testing/sysfs-driver-eud +++ b/Documentation/ABI/testing/sysfs-driver-eud @@ -1,4 +1,4 @@ -What: /sys/bus/platform/drivers/eud/.../enable +What: /sys/bus/platform/drivers/qcom_eud/.../enable Date: February 2022 Contact: Souradeep Chowdhury Description: diff --git a/Documentation/ABI/testing/sysfs-driver-qat b/Documentation/ABI/testing/sysfs-driver-qat index 087842b1969e7d5d785750f4d310cf0cd3b28927..ef6d6c57105efbf199495f3c9718a2ae9e0eb68f 100644 --- a/Documentation/ABI/testing/sysfs-driver-qat +++ b/Documentation/ABI/testing/sysfs-driver-qat @@ -27,7 +27,18 @@ Description: (RW) Reports the current configuration of the QAT device. * sym;asym: the device is configured for running crypto services + * asym;sym: identical to sym;asym * dc: the device is configured for running compression services + * sym: the device is configured for running symmetric crypto + services + * asym: the device is configured for running asymmetric crypto + services + * asym;dc: the device is configured for running asymmetric + crypto services and compression services + * dc;asym: identical to asym;dc + * sym;dc: the device is configured for running symmetric crypto + services and compression services + * dc;sym: identical to sym;dc It is possible to set the configuration only if the device is in the `down` state (see /sys/bus/pci/devices//qat/state) @@ -47,3 +58,38 @@ Description: (RW) Reports the current configuration of the QAT device. dc This attribute is only available for qat_4xxx devices. + +What: /sys/bus/pci/devices//qat/pm_idle_enabled +Date: June 2023 +KernelVersion: 6.5 +Contact: qat-linux@intel.com +Description: (RW) This configuration option provides a way to force the device into remaining in + the MAX power state. + If idle support is enabled the device will transition to the `MIN` power state when + idle, otherwise will stay in the MAX power state. + Write to the file to enable or disable idle support. + + The values are: + + * 0: idle support is disabled + * 1: idle support is enabled + + Default value is 1. + + It is possible to set the pm_idle_enabled value only if the device + is in the `down` state (see /sys/bus/pci/devices//qat/state) + + The following example shows how to change the pm_idle_enabled of + a device:: + + # cat /sys/bus/pci/devices//qat/state + up + # cat /sys/bus/pci/devices//qat/pm_idle_enabled + 1 + # echo down > /sys/bus/pci/devices//qat/state + # echo 0 > /sys/bus/pci/devices//qat/pm_idle_enabled + # echo up > /sys/bus/pci/devices//qat/state + # cat /sys/bus/pci/devices//qat/pm_idle_enabled + 0 + + This attribute is only available for qat_4xxx devices. diff --git a/Documentation/ABI/testing/sysfs-driver-ufs b/Documentation/ABI/testing/sysfs-driver-ufs index 228aa43e14ed5d38cf01af24c42d821dbbe15c94..e487f969a15ea937ee17d58959afd0f65fa44af7 100644 --- a/Documentation/ABI/testing/sysfs-driver-ufs +++ b/Documentation/ABI/testing/sysfs-driver-ufs @@ -994,7 +994,7 @@ Description: This file shows the amount of physical memory needed What: /sys/bus/platform/drivers/ufshcd/*/rpm_lvl What: /sys/bus/platform/devices/*.ufs/rpm_lvl Date: September 2014 -Contact: Subhash Jadavani +Contact: Can Guo Description: This entry could be used to set or show the UFS device runtime power management level. The current driver implementation supports 7 levels with next target states: @@ -1021,7 +1021,7 @@ Description: This entry could be used to set or show the UFS device What: /sys/bus/platform/drivers/ufshcd/*/rpm_target_dev_state What: /sys/bus/platform/devices/*.ufs/rpm_target_dev_state Date: February 2018 -Contact: Subhash Jadavani +Contact: Can Guo Description: This entry shows the target power mode of an UFS device for the chosen runtime power management level. @@ -1030,7 +1030,7 @@ Description: This entry shows the target power mode of an UFS device What: /sys/bus/platform/drivers/ufshcd/*/rpm_target_link_state What: /sys/bus/platform/devices/*.ufs/rpm_target_link_state Date: February 2018 -Contact: Subhash Jadavani +Contact: Can Guo Description: This entry shows the target state of an UFS UIC link for the chosen runtime power management level. @@ -1039,7 +1039,7 @@ Description: This entry shows the target state of an UFS UIC link What: /sys/bus/platform/drivers/ufshcd/*/spm_lvl What: /sys/bus/platform/devices/*.ufs/spm_lvl Date: September 2014 -Contact: Subhash Jadavani +Contact: Can Guo Description: This entry could be used to set or show the UFS device system power management level. The current driver implementation supports 7 levels with next target states: @@ -1066,7 +1066,7 @@ Description: This entry could be used to set or show the UFS device What: /sys/bus/platform/drivers/ufshcd/*/spm_target_dev_state What: /sys/bus/platform/devices/*.ufs/spm_target_dev_state Date: February 2018 -Contact: Subhash Jadavani +Contact: Can Guo Description: This entry shows the target power mode of an UFS device for the chosen system power management level. @@ -1075,7 +1075,7 @@ Description: This entry shows the target power mode of an UFS device What: /sys/bus/platform/drivers/ufshcd/*/spm_target_link_state What: /sys/bus/platform/devices/*.ufs/spm_target_link_state Date: February 2018 -Contact: Subhash Jadavani +Contact: Can Guo Description: This entry shows the target state of an UFS UIC link for the chosen system power management level. @@ -1084,7 +1084,7 @@ Description: This entry shows the target state of an UFS UIC link What: /sys/bus/platform/drivers/ufshcd/*/monitor/monitor_enable What: /sys/bus/platform/devices/*.ufs/monitor/monitor_enable Date: January 2021 -Contact: Can Guo +Contact: Can Guo Description: This file shows the status of performance monitor enablement and it can be used to start/stop the monitor. When the monitor is stopped, the performance data collected is also cleared. @@ -1092,7 +1092,7 @@ Description: This file shows the status of performance monitor enablement What: /sys/bus/platform/drivers/ufshcd/*/monitor/monitor_chunk_size What: /sys/bus/platform/devices/*.ufs/monitor/monitor_chunk_size Date: January 2021 -Contact: Can Guo +Contact: Can Guo Description: This file tells the monitor to focus on requests transferring data of specific chunk size (in Bytes). 0 means any chunk size. It can only be changed when monitor is disabled. @@ -1100,7 +1100,7 @@ Description: This file tells the monitor to focus on requests transferring What: /sys/bus/platform/drivers/ufshcd/*/monitor/read_total_sectors What: /sys/bus/platform/devices/*.ufs/monitor/read_total_sectors Date: January 2021 -Contact: Can Guo +Contact: Can Guo Description: This file shows how many sectors (in 512 Bytes) have been sent from device to host after monitor gets started. @@ -1109,7 +1109,7 @@ Description: This file shows how many sectors (in 512 Bytes) have been What: /sys/bus/platform/drivers/ufshcd/*/monitor/read_total_busy What: /sys/bus/platform/devices/*.ufs/monitor/read_total_busy Date: January 2021 -Contact: Can Guo +Contact: Can Guo Description: This file shows how long (in micro seconds) has been spent sending data from device to host after monitor gets started. @@ -1118,7 +1118,7 @@ Description: This file shows how long (in micro seconds) has been spent What: /sys/bus/platform/drivers/ufshcd/*/monitor/read_nr_requests What: /sys/bus/platform/devices/*.ufs/monitor/read_nr_requests Date: January 2021 -Contact: Can Guo +Contact: Can Guo Description: This file shows how many read requests have been sent after monitor gets started. @@ -1127,7 +1127,7 @@ Description: This file shows how many read requests have been sent after What: /sys/bus/platform/drivers/ufshcd/*/monitor/read_req_latency_max What: /sys/bus/platform/devices/*.ufs/monitor/read_req_latency_max Date: January 2021 -Contact: Can Guo +Contact: Can Guo Description: This file shows the maximum latency (in micro seconds) of read requests after monitor gets started. @@ -1136,7 +1136,7 @@ Description: This file shows the maximum latency (in micro seconds) of What: /sys/bus/platform/drivers/ufshcd/*/monitor/read_req_latency_min What: /sys/bus/platform/devices/*.ufs/monitor/read_req_latency_min Date: January 2021 -Contact: Can Guo +Contact: Can Guo Description: This file shows the minimum latency (in micro seconds) of read requests after monitor gets started. @@ -1145,7 +1145,7 @@ Description: This file shows the minimum latency (in micro seconds) of What: /sys/bus/platform/drivers/ufshcd/*/monitor/read_req_latency_avg What: /sys/bus/platform/devices/*.ufs/monitor/read_req_latency_avg Date: January 2021 -Contact: Can Guo +Contact: Can Guo Description: This file shows the average latency (in micro seconds) of read requests after monitor gets started. @@ -1154,7 +1154,7 @@ Description: This file shows the average latency (in micro seconds) of What: /sys/bus/platform/drivers/ufshcd/*/monitor/read_req_latency_sum What: /sys/bus/platform/devices/*.ufs/monitor/read_req_latency_sum Date: January 2021 -Contact: Can Guo +Contact: Can Guo Description: This file shows the total latency (in micro seconds) of read requests sent after monitor gets started. @@ -1163,7 +1163,7 @@ Description: This file shows the total latency (in micro seconds) of What: /sys/bus/platform/drivers/ufshcd/*/monitor/write_total_sectors What: /sys/bus/platform/devices/*.ufs/monitor/write_total_sectors Date: January 2021 -Contact: Can Guo +Contact: Can Guo Description: This file shows how many sectors (in 512 Bytes) have been sent from host to device after monitor gets started. @@ -1172,7 +1172,7 @@ Description: This file shows how many sectors (in 512 Bytes) have been sent What: /sys/bus/platform/drivers/ufshcd/*/monitor/write_total_busy What: /sys/bus/platform/devices/*.ufs/monitor/write_total_busy Date: January 2021 -Contact: Can Guo +Contact: Can Guo Description: This file shows how long (in micro seconds) has been spent sending data from host to device after monitor gets started. @@ -1181,7 +1181,7 @@ Description: This file shows how long (in micro seconds) has been spent What: /sys/bus/platform/drivers/ufshcd/*/monitor/write_nr_requests What: /sys/bus/platform/devices/*.ufs/monitor/write_nr_requests Date: January 2021 -Contact: Can Guo +Contact: Can Guo Description: This file shows how many write requests have been sent after monitor gets started. @@ -1190,7 +1190,7 @@ Description: This file shows how many write requests have been sent after What: /sys/bus/platform/drivers/ufshcd/*/monitor/write_req_latency_max What: /sys/bus/platform/devices/*.ufs/monitor/write_req_latency_max Date: January 2021 -Contact: Can Guo +Contact: Can Guo Description: This file shows the maximum latency (in micro seconds) of write requests after monitor gets started. @@ -1199,7 +1199,7 @@ Description: This file shows the maximum latency (in micro seconds) of write What: /sys/bus/platform/drivers/ufshcd/*/monitor/write_req_latency_min What: /sys/bus/platform/devices/*.ufs/monitor/write_req_latency_min Date: January 2021 -Contact: Can Guo +Contact: Can Guo Description: This file shows the minimum latency (in micro seconds) of write requests after monitor gets started. @@ -1208,7 +1208,7 @@ Description: This file shows the minimum latency (in micro seconds) of write What: /sys/bus/platform/drivers/ufshcd/*/monitor/write_req_latency_avg What: /sys/bus/platform/devices/*.ufs/monitor/write_req_latency_avg Date: January 2021 -Contact: Can Guo +Contact: Can Guo Description: This file shows the average latency (in micro seconds) of write requests after monitor gets started. @@ -1217,7 +1217,7 @@ Description: This file shows the average latency (in micro seconds) of write What: /sys/bus/platform/drivers/ufshcd/*/monitor/write_req_latency_sum What: /sys/bus/platform/devices/*.ufs/monitor/write_req_latency_sum Date: January 2021 -Contact: Can Guo +Contact: Can Guo Description: This file shows the total latency (in micro seconds) of write requests after monitor gets started. @@ -1226,7 +1226,7 @@ Description: This file shows the total latency (in micro seconds) of write What: /sys/bus/platform/drivers/ufshcd/*/device_descriptor/wb_presv_us_en What: /sys/bus/platform/devices/*.ufs/device_descriptor/wb_presv_us_en Date: June 2020 -Contact: Asutosh Das +Contact: Asutosh Das Description: This entry shows if preserve user-space was configured The file is read only. @@ -1234,7 +1234,7 @@ Description: This entry shows if preserve user-space was configured What: /sys/bus/platform/drivers/ufshcd/*/device_descriptor/wb_shared_alloc_units What: /sys/bus/platform/devices/*.ufs/device_descriptor/wb_shared_alloc_units Date: June 2020 -Contact: Asutosh Das +Contact: Asutosh Das Description: This entry shows the shared allocated units of WB buffer The file is read only. @@ -1242,7 +1242,7 @@ Description: This entry shows the shared allocated units of WB buffer What: /sys/bus/platform/drivers/ufshcd/*/device_descriptor/wb_type What: /sys/bus/platform/devices/*.ufs/device_descriptor/wb_type Date: June 2020 -Contact: Asutosh Das +Contact: Asutosh Das Description: This entry shows the configured WB type. 0x1 for shared buffer mode. 0x0 for dedicated buffer mode. @@ -1251,7 +1251,7 @@ Description: This entry shows the configured WB type. What: /sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/wb_buff_cap_adj What: /sys/bus/platform/devices/*.ufs/geometry_descriptor/wb_buff_cap_adj Date: June 2020 -Contact: Asutosh Das +Contact: Asutosh Das Description: This entry shows the total user-space decrease in shared buffer mode. The value of this parameter is 3 for TLC NAND when SLC mode @@ -1262,7 +1262,7 @@ Description: This entry shows the total user-space decrease in shared What: /sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/wb_max_alloc_units What: /sys/bus/platform/devices/*.ufs/geometry_descriptor/wb_max_alloc_units Date: June 2020 -Contact: Asutosh Das +Contact: Asutosh Das Description: This entry shows the Maximum total WriteBooster Buffer size which is supported by the entire device. @@ -1271,7 +1271,7 @@ Description: This entry shows the Maximum total WriteBooster Buffer size What: /sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/wb_max_wb_luns What: /sys/bus/platform/devices/*.ufs/geometry_descriptor/wb_max_wb_luns Date: June 2020 -Contact: Asutosh Das +Contact: Asutosh Das Description: This entry shows the maximum number of luns that can support WriteBooster. @@ -1280,7 +1280,7 @@ Description: This entry shows the maximum number of luns that can support What: /sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/wb_sup_red_type What: /sys/bus/platform/devices/*.ufs/geometry_descriptor/wb_sup_red_type Date: June 2020 -Contact: Asutosh Das +Contact: Asutosh Das Description: The supportability of user space reduction mode and preserve user space mode. 00h: WriteBooster Buffer can be configured only in @@ -1295,7 +1295,7 @@ Description: The supportability of user space reduction mode What: /sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/wb_sup_wb_type What: /sys/bus/platform/devices/*.ufs/geometry_descriptor/wb_sup_wb_type Date: June 2020 -Contact: Asutosh Das +Contact: Asutosh Das Description: The supportability of WriteBooster Buffer type. === ========================================================== @@ -1310,7 +1310,7 @@ Description: The supportability of WriteBooster Buffer type. What: /sys/bus/platform/drivers/ufshcd/*/flags/wb_enable What: /sys/bus/platform/devices/*.ufs/flags/wb_enable Date: June 2020 -Contact: Asutosh Das +Contact: Asutosh Das Description: This entry shows the status of WriteBooster. == ============================ @@ -1323,7 +1323,7 @@ Description: This entry shows the status of WriteBooster. What: /sys/bus/platform/drivers/ufshcd/*/flags/wb_flush_en What: /sys/bus/platform/devices/*.ufs/flags/wb_flush_en Date: June 2020 -Contact: Asutosh Das +Contact: Asutosh Das Description: This entry shows if flush is enabled. == ================================= @@ -1336,7 +1336,7 @@ Description: This entry shows if flush is enabled. What: /sys/bus/platform/drivers/ufshcd/*/flags/wb_flush_during_h8 What: /sys/bus/platform/devices/*.ufs/flags/wb_flush_during_h8 Date: June 2020 -Contact: Asutosh Das +Contact: Asutosh Das Description: Flush WriteBooster Buffer during hibernate state. == ================================================= @@ -1351,7 +1351,7 @@ Description: Flush WriteBooster Buffer during hibernate state. What: /sys/bus/platform/drivers/ufshcd/*/attributes/wb_avail_buf What: /sys/bus/platform/devices/*.ufs/attributes/wb_avail_buf Date: June 2020 -Contact: Asutosh Das +Contact: Asutosh Das Description: This entry shows the amount of unused WriteBooster buffer available. @@ -1360,7 +1360,7 @@ Description: This entry shows the amount of unused WriteBooster buffer What: /sys/bus/platform/drivers/ufshcd/*/attributes/wb_cur_buf What: /sys/bus/platform/devices/*.ufs/attributes/wb_cur_buf Date: June 2020 -Contact: Asutosh Das +Contact: Asutosh Das Description: This entry shows the amount of unused current buffer. The file is read only. @@ -1368,7 +1368,7 @@ Description: This entry shows the amount of unused current buffer. What: /sys/bus/platform/drivers/ufshcd/*/attributes/wb_flush_status What: /sys/bus/platform/devices/*.ufs/attributes/wb_flush_status Date: June 2020 -Contact: Asutosh Das +Contact: Asutosh Das Description: This entry shows the flush operation status. @@ -1385,7 +1385,7 @@ Description: This entry shows the flush operation status. What: /sys/bus/platform/drivers/ufshcd/*/attributes/wb_life_time_est What: /sys/bus/platform/devices/*.ufs/attributes/wb_life_time_est Date: June 2020 -Contact: Asutosh Das +Contact: Asutosh Das Description: This entry shows an indication of the WriteBooster Buffer lifetime based on the amount of performed program/erase cycles @@ -1399,7 +1399,7 @@ Description: This entry shows an indication of the WriteBooster Buffer What: /sys/class/scsi_device/*/device/unit_descriptor/wb_buf_alloc_units Date: June 2020 -Contact: Asutosh Das +Contact: Asutosh Das Description: This entry shows the configured size of WriteBooster buffer. 0400h corresponds to 4GB. @@ -1426,6 +1426,17 @@ Description: This entry shows the status of WriteBooster buffer flushing If flushing is enabled, the device executes the flush operation when the command queue is empty. +What: /sys/bus/platform/drivers/ufshcd/*/wb_flush_threshold +What: /sys/bus/platform/devices/*.ufs/wb_flush_threshold +Date: June 2023 +Contact: Lu Hongfei +Description: + wb_flush_threshold represents the threshold for flushing WriteBooster buffer, + whose value expressed in unit of 10% granularity, such as '1' representing 10%, + '2' representing 20%, and so on. + If avail_wb_buff < wb_flush_threshold, it indicates that WriteBooster buffer needs to + be flushed, otherwise it is not necessary. + What: /sys/bus/platform/drivers/ufshcd/*/device_descriptor/hpb_version What: /sys/bus/platform/devices/*.ufs/device_descriptor/hpb_version Date: June 2021 diff --git a/Documentation/ABI/testing/sysfs-ocfs2 b/Documentation/ABI/testing/sysfs-ocfs2 index b7cc516a8a8a747e2ca0491535d53e99cf262d18..494d7c1ac7107d3817cee75f7b0816b9fc00ec58 100644 --- a/Documentation/ABI/testing/sysfs-ocfs2 +++ b/Documentation/ABI/testing/sysfs-ocfs2 @@ -1,13 +1,13 @@ What: /sys/fs/ocfs2/ Date: April 2008 -Contact: ocfs2-devel@oss.oracle.com +Contact: ocfs2-devel@lists.linux.dev Description: The /sys/fs/ocfs2 directory contains knobs used by the ocfs2-tools to interact with the filesystem. What: /sys/fs/ocfs2/max_locking_protocol Date: April 2008 -Contact: ocfs2-devel@oss.oracle.com +Contact: ocfs2-devel@lists.linux.dev Description: The /sys/fs/ocfs2/max_locking_protocol file displays version of ocfs2 locking supported by the filesystem. This version @@ -28,7 +28,7 @@ Description: What: /sys/fs/ocfs2/loaded_cluster_plugins Date: April 2008 -Contact: ocfs2-devel@oss.oracle.com +Contact: ocfs2-devel@lists.linux.dev Description: The /sys/fs/ocfs2/loaded_cluster_plugins file describes the available plugins to support ocfs2 cluster operation. @@ -48,7 +48,7 @@ Description: What: /sys/fs/ocfs2/active_cluster_plugin Date: April 2008 -Contact: ocfs2-devel@oss.oracle.com +Contact: ocfs2-devel@lists.linux.dev Description: The /sys/fs/ocfs2/active_cluster_plugin displays which cluster plugin is currently in use by the filesystem. @@ -65,7 +65,7 @@ Description: What: /sys/fs/ocfs2/cluster_stack Date: April 2008 -Contact: ocfs2-devel@oss.oracle.com +Contact: ocfs2-devel@lists.linux.dev Description: The /sys/fs/ocfs2/cluster_stack file contains the name of current ocfs2 cluster stack. This value is set by @@ -86,4 +86,4 @@ Description: stack return an error. Users: - ocfs2-tools + ocfs2-tools diff --git a/Documentation/ABI/testing/sysfs-platform-dell-wmi-ddv b/Documentation/ABI/testing/sysfs-platform-dell-wmi-ddv index 1d97ad615c66c6a5f4a201f70d9a158e27574608..a9d39d9e8865c745455518e6be9157bc1838ac7e 100644 --- a/Documentation/ABI/testing/sysfs-platform-dell-wmi-ddv +++ b/Documentation/ABI/testing/sysfs-platform-dell-wmi-ddv @@ -3,5 +3,7 @@ Date: September 2022 KernelVersion: 6.1 Contact: Armin Wolf Description: - Reports the Dell ePPID (electronic Dell Piece Part Identification) + Reports the Dell ePPID (electronic Piece Part Identification) of the ACPI battery. + + See Documentation/wmi/devices/dell-wmi-ddv.rst for details. diff --git a/Documentation/ABI/testing/sysfs-platform-mellanox-bootctl b/Documentation/ABI/testing/sysfs-platform-mellanox-bootctl index 9b99a81babb1c9ed3bd61c5ea72c0693ac41db85..4c5c02d8f870ef053a9ea004e9f7c917198906e2 100644 --- a/Documentation/ABI/testing/sysfs-platform-mellanox-bootctl +++ b/Documentation/ABI/testing/sysfs-platform-mellanox-bootctl @@ -75,3 +75,12 @@ KernelVersion: 6.4 Contact: "Liming Sun " Description: The file used to access the BlueField boot fifo. + +What: /sys/bus/platform/devices/MLNXBF04:00/rsh_log +Date: May 2023 +KernelVersion: 6.4 +Contact: "Liming Sun " +Description: + The file used to write BlueField boot log with the format + "[INFO|WARN|ERR|ASSERT ]". Log level 'INFO' is used by + default if not specified. diff --git a/Documentation/PCI/endpoint/pci-ntb-howto.rst b/Documentation/PCI/endpoint/pci-ntb-howto.rst index 1884bf29caba4bf178ce53b0abf372074576ec18..4261e7157ef1ca3b2a7c873825dd305e6f68d605 100644 --- a/Documentation/PCI/endpoint/pci-ntb-howto.rst +++ b/Documentation/PCI/endpoint/pci-ntb-howto.rst @@ -88,13 +88,10 @@ commands can be used:: # echo 0x104c > functions/pci_epf_ntb/func1/vendorid # echo 0xb00d > functions/pci_epf_ntb/func1/deviceid -In order to configure NTB specific attributes, a new sub-directory to func1 -should be created:: - - # mkdir functions/pci_epf_ntb/func1/pci_epf_ntb.0/ - -The NTB function driver will populate this directory with various attributes -that can be configured by the user:: +The PCI endpoint framework also automatically creates a sub-directory in the +function attribute directory. This sub-directory has the same name as the name +of the function device and is populated with the following NTB specific +attributes that can be configured by the user:: # ls functions/pci_epf_ntb/func1/pci_epf_ntb.0/ db_count mw1 mw2 mw3 mw4 num_mws diff --git a/Documentation/PCI/endpoint/pci-vntb-howto.rst b/Documentation/PCI/endpoint/pci-vntb-howto.rst index 4ab8e4a26d4bed4048c0212cf2d1df8dd732d846..70d3bc90893f3315a7dff394d57e45c8378e2a54 100644 --- a/Documentation/PCI/endpoint/pci-vntb-howto.rst +++ b/Documentation/PCI/endpoint/pci-vntb-howto.rst @@ -84,13 +84,10 @@ commands can be used:: # echo 0x1957 > functions/pci_epf_vntb/func1/vendorid # echo 0x0809 > functions/pci_epf_vntb/func1/deviceid -In order to configure NTB specific attributes, a new sub-directory to func1 -should be created:: - - # mkdir functions/pci_epf_vntb/func1/pci_epf_vntb.0/ - -The NTB function driver will populate this directory with various attributes -that can be configured by the user:: +The PCI endpoint framework also automatically creates a sub-directory in the +function attribute directory. This sub-directory has the same name as the name +of the function device and is populated with the following NTB specific +attributes that can be configured by the user:: # ls functions/pci_epf_vntb/func1/pci_epf_vntb.0/ db_count mw1 mw2 mw3 mw4 num_mws @@ -103,7 +100,7 @@ A sample configuration for NTB function is given below:: # echo 1 > functions/pci_epf_vntb/func1/pci_epf_vntb.0/num_mws # echo 0x100000 > functions/pci_epf_vntb/func1/pci_epf_vntb.0/mw1 -A sample configuration for virtual NTB driver for virutal PCI bus:: +A sample configuration for virtual NTB driver for virtual PCI bus:: # echo 0x1957 > functions/pci_epf_vntb/func1/pci_epf_vntb.0/vntb_vid # echo 0x080A > functions/pci_epf_vntb/func1/pci_epf_vntb.0/vntb_pid diff --git a/Documentation/PCI/msi-howto.rst b/Documentation/PCI/msi-howto.rst index 8ae461e97c54ef663217eace0793d9cd4fb55216..c9400f02333bf1be27675eb82a20f7bbb272ca92 100644 --- a/Documentation/PCI/msi-howto.rst +++ b/Documentation/PCI/msi-howto.rst @@ -290,7 +290,7 @@ PCI_IRQ_MSI or PCI_IRQ_MSIX flags. List of device drivers MSI(-X) APIs =================================== -The PCI/MSI subystem has a dedicated C file for its exported device driver +The PCI/MSI subsystem has a dedicated C file for its exported device driver APIs — `drivers/pci/msi/api.c`. The following functions are exported: .. kernel-doc:: drivers/pci/msi/api.c diff --git a/Documentation/PCI/pci-error-recovery.rst b/Documentation/PCI/pci-error-recovery.rst index 9981d330da8f0cff8a9b018ad1f6e2d91fb1d6c3..c237596f67e396aebea3eadeefd5a850eb697092 100644 --- a/Documentation/PCI/pci-error-recovery.rst +++ b/Documentation/PCI/pci-error-recovery.rst @@ -364,7 +364,7 @@ Note, however, not all failures are truly "permanent". Some are caused by over-heating, some by a poorly seated card. Many PCI error events are caused by software bugs, e.g. DMA's to wild addresses or bogus split transactions due to programming -errors. See the discussion in powerpc/eeh-pci-error-recovery.txt +errors. See the discussion in Documentation/powerpc/eeh-pci-error-recovery.rst for additional detail on real-life experience of the causes of software errors. diff --git a/Documentation/PCI/pcieaer-howto.rst b/Documentation/PCI/pcieaer-howto.rst index 0b36b9ebfa4b4296ec1a4fc55ac9b443a7bdea3c..e00d63971695ed33a656bbd79c98d2514ea078bb 100644 --- a/Documentation/PCI/pcieaer-howto.rst +++ b/Documentation/PCI/pcieaer-howto.rst @@ -16,62 +16,61 @@ Overview About this guide ---------------- -This guide describes the basics of the PCI Express Advanced Error +This guide describes the basics of the PCI Express (PCIe) Advanced Error Reporting (AER) driver and provides information on how to use it, as -well as how to enable the drivers of endpoint devices to conform with -PCI Express AER driver. +well as how to enable the drivers of Endpoint devices to conform with +the PCIe AER driver. -What is the PCI Express AER Driver? ------------------------------------ +What is the PCIe AER Driver? +---------------------------- -PCI Express error signaling can occur on the PCI Express link itself -or on behalf of transactions initiated on the link. PCI Express +PCIe error signaling can occur on the PCIe link itself +or on behalf of transactions initiated on the link. PCIe defines two error reporting paradigms: the baseline capability and the Advanced Error Reporting capability. The baseline capability is -required of all PCI Express components providing a minimum defined +required of all PCIe components providing a minimum defined set of error reporting requirements. Advanced Error Reporting -capability is implemented with a PCI Express advanced error reporting +capability is implemented with a PCIe Advanced Error Reporting extended capability structure providing more robust error reporting. -The PCI Express AER driver provides the infrastructure to support PCI -Express Advanced Error Reporting capability. The PCI Express AER -driver provides three basic functions: +The PCIe AER driver provides the infrastructure to support PCIe Advanced +Error Reporting capability. The PCIe AER driver provides three basic +functions: - Gathers the comprehensive error information if errors occurred. - Reports error to the users. - Performs error recovery actions. -AER driver only attaches root ports which support PCI-Express AER -capability. +The AER driver only attaches to Root Ports and RCECs that support the PCIe +AER capability. User Guide ========== -Include the PCI Express AER Root Driver into the Linux Kernel -------------------------------------------------------------- +Include the PCIe AER Root Driver into the Linux Kernel +------------------------------------------------------ -The PCI Express AER Root driver is a Root Port service driver attached -to the PCI Express Port Bus driver. If a user wants to use it, the driver -has to be compiled. Option CONFIG_PCIEAER supports this capability. It -depends on CONFIG_PCIEPORTBUS, so pls. set CONFIG_PCIEPORTBUS=y and -CONFIG_PCIEAER = y. +The PCIe AER driver is a Root Port service driver attached +via the PCIe Port Bus driver. If a user wants to use it, the driver +must be compiled. It is enabled with CONFIG_PCIEAER, which +depends on CONFIG_PCIEPORTBUS. -Load PCI Express AER Root Driver --------------------------------- +Load PCIe AER Root Driver +------------------------- Some systems have AER support in firmware. Enabling Linux AER support at -the same time the firmware handles AER may result in unpredictable +the same time the firmware handles AER would result in unpredictable behavior. Therefore, Linux does not handle AER events unless the firmware -grants AER control to the OS via the ACPI _OSC method. See the PCI FW 3.0 +grants AER control to the OS via the ACPI _OSC method. See the PCI Firmware Specification for details regarding _OSC usage. AER error output ---------------- When a PCIe AER error is captured, an error message will be output to -console. If it's a correctable error, it is output as a warning. +console. If it's a correctable error, it is output as an info message. Otherwise, it is printed as an error. So users could choose different log level to filter out correctable error messages. @@ -82,9 +81,9 @@ Below shows an example:: 0000:50:00.0: [20] Unsupported Request (First) 0000:50:00.0: TLP Header: 04000001 00200a03 05010000 00050100 -In the example, 'Requester ID' means the ID of the device who sends -the error message to root port. Pls. refer to pci express specs for -other fields. +In the example, 'Requester ID' means the ID of the device that sent +the error message to the Root Port. Please refer to PCIe specs for other +fields. AER Statistics / Counters ------------------------- @@ -96,65 +95,56 @@ Documentation/ABI/testing/sysfs-bus-pci-devices-aer_stats Developer Guide =============== -To enable AER aware support requires a software driver to configure -the AER capability structure within its device and to provide callbacks. +To enable error recovery, a software driver must provide callbacks. -To support AER better, developers need understand how AER does work -firstly. +To support AER better, developers need to understand how AER works. -PCI Express errors are classified into two types: correctable errors -and uncorrectable errors. This classification is based on the impacts +PCIe errors are classified into two types: correctable errors +and uncorrectable errors. This classification is based on the impact of those errors, which may result in degraded performance or function failure. Correctable errors pose no impacts on the functionality of the -interface. The PCI Express protocol can recover without any software +interface. The PCIe protocol can recover without any software intervention or any loss of data. These errors are detected and -corrected by hardware. Unlike correctable errors, uncorrectable +corrected by hardware. + +Unlike correctable errors, uncorrectable errors impact functionality of the interface. Uncorrectable errors -can cause a particular transaction or a particular PCI Express link +can cause a particular transaction or a particular PCIe link to be unreliable. Depending on those error conditions, uncorrectable errors are further classified into non-fatal errors and fatal errors. Non-fatal errors cause the particular transaction to be unreliable, -but the PCI Express link itself is fully functional. Fatal errors, on +but the PCIe link itself is fully functional. Fatal errors, on the other hand, cause the link to be unreliable. -When AER is enabled, a PCI Express device will automatically send an -error message to the PCIe root port above it when the device captures +When PCIe error reporting is enabled, a device will automatically send an +error message to the Root Port above it when it captures an error. The Root Port, upon receiving an error reporting message, -internally processes and logs the error message in its PCI Express -capability structure. Error information being logged includes storing +internally processes and logs the error message in its AER +Capability structure. Error information being logged includes storing the error reporting agent's requestor ID into the Error Source Identification Registers and setting the error bits of the Root Error -Status Register accordingly. If AER error reporting is enabled in Root -Error Command Register, the Root Port generates an interrupt if an +Status Register accordingly. If AER error reporting is enabled in the Root +Error Command Register, the Root Port generates an interrupt when an error is detected. -Note that the errors as described above are related to the PCI Express +Note that the errors as described above are related to the PCIe hierarchy and links. These errors do not include any device specific errors because device specific errors will still get sent directly to the device driver. -Configure the AER capability structure --------------------------------------- - -AER aware drivers of PCI Express component need change the device -control registers to enable AER. They also could change AER registers, -including mask and severity registers. Helper function -pci_enable_pcie_error_reporting could be used to enable AER. See -section 3.3. - Provide callbacks ----------------- -callback reset_link to reset pci express link -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +callback reset_link to reset PCIe link +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -This callback is used to reset the pci express physical link when a -fatal error happens. The root port aer service driver provides a -default reset_link function, but different upstream ports might -have different specifications to reset pci express link, so all -upstream ports should provide their own reset_link functions. +This callback is used to reset the PCIe physical link when a +fatal error happens. The Root Port AER service driver provides a +default reset_link function, but different Upstream Ports might +have different specifications to reset the PCIe link, so +Upstream Port drivers may provide their own reset_link functions. Section 3.2.2.2 provides more detailed info on when to call reset_link. @@ -162,24 +152,24 @@ reset_link. PCI error-recovery callbacks ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -The PCI Express AER Root driver uses error callbacks to coordinate +The PCIe AER Root driver uses error callbacks to coordinate with downstream device drivers associated with a hierarchy in question when performing error recovery actions. Data struct pci_driver has a pointer, err_handler, to point to pci_error_handlers who consists of a couple of callback function -pointers. AER driver follows the rules defined in -pci-error-recovery.txt except pci express specific parts (e.g. -reset_link). Pls. refer to pci-error-recovery.txt for detailed +pointers. The AER driver follows the rules defined in +pci-error-recovery.rst except PCIe-specific parts (e.g. +reset_link). Please refer to pci-error-recovery.rst for detailed definitions of the callbacks. -Below sections specify when to call the error callback functions. +The sections below specify when to call the error callback functions. Correctable errors ~~~~~~~~~~~~~~~~~~ Correctable errors pose no impacts on the functionality of -the interface. The PCI Express protocol can recover without any +the interface. The PCIe protocol can recover without any software intervention or any loss of data. These errors do not require any recovery actions. The AER driver clears the device's correctable error status register accordingly and logs these errors. @@ -190,12 +180,12 @@ Non-correctable (non-fatal and fatal) errors If an error message indicates a non-fatal error, performing link reset at upstream is not required. The AER driver calls error_detected(dev, pci_channel_io_normal) to all drivers associated within a hierarchy in -question. for example:: +question. For example:: - EndPoint<==>DownstreamPort B<==>UpstreamPort A<==>RootPort + Endpoint <==> Downstream Port B <==> Upstream Port A <==> Root Port -If Upstream port A captures an AER error, the hierarchy consists of -Downstream port B and EndPoint. +If Upstream Port A captures an AER error, the hierarchy consists of +Downstream Port B and Endpoint. A driver may return PCI_ERS_RESULT_CAN_RECOVER, PCI_ERS_RESULT_DISCONNECT, or PCI_ERS_RESULT_NEED_RESET, depending on @@ -212,36 +202,11 @@ to reset the link. If error_detected returns PCI_ERS_RESULT_CAN_RECOVER and reset_link returns PCI_ERS_RESULT_RECOVERED, the error handling goes to mmio_enabled. -helper functions ----------------- -:: - - int pci_enable_pcie_error_reporting(struct pci_dev *dev); - -pci_enable_pcie_error_reporting enables the device to send error -messages to root port when an error is detected. Note that devices -don't enable the error reporting by default, so device drivers need -call this function to enable it. - -:: - - int pci_disable_pcie_error_reporting(struct pci_dev *dev); - -pci_disable_pcie_error_reporting disables the device to send error -messages to root port when an error is detected. - -:: - - int pci_aer_clear_nonfatal_status(struct pci_dev *dev);` - -pci_aer_clear_nonfatal_status clears non-fatal errors in the uncorrectable -error status register. - Frequent Asked Questions ------------------------ Q: - What happens if a PCI Express device driver does not provide an + What happens if a PCIe device driver does not provide an error recovery handler (pci_driver->err_handler is equal to NULL)? A: @@ -257,24 +222,6 @@ A: Fatal error recovery will fail if the errors are reported by the upstream ports who are attached by the service driver. -Q: - How does this infrastructure deal with driver that is not PCI - Express aware? - -A: - This infrastructure calls the error callback functions of the - driver when an error happens. But if the driver is not aware of - PCI Express, the device might not report its own errors to root - port. - -Q: - What modifications will that driver need to make it compatible - with the PCI Express AER Root driver? - -A: - It could call the helper functions to enable AER in devices and - cleanup uncorrectable status register. Pls. refer to section 3.3. - Software error injection ======================== @@ -296,5 +243,5 @@ from: https://git.kernel.org/cgit/linux/kernel/git/gong.chen/aer-inject.git/ -More information about aer-inject can be found in the document comes -with its source code. +More information about aer-inject can be found in the document in +its source code. diff --git a/Documentation/RCU/Design/Requirements/Requirements.rst b/Documentation/RCU/Design/Requirements/Requirements.rst index 49387d8236196c3abdbe2df939eee80946f30cab..f3b605285a87160f6471b5068f1e5de96c3b0e9a 100644 --- a/Documentation/RCU/Design/Requirements/Requirements.rst +++ b/Documentation/RCU/Design/Requirements/Requirements.rst @@ -2071,41 +2071,7 @@ call. Because RCU avoids interrupting idle CPUs, it is illegal to execute an RCU read-side critical section on an idle CPU. (Kernels built with -``CONFIG_PROVE_RCU=y`` will splat if you try it.) The RCU_NONIDLE() -macro and ``_rcuidle`` event tracing is provided to work around this -restriction. In addition, rcu_is_watching() may be used to test -whether or not it is currently legal to run RCU read-side critical -sections on this CPU. I learned of the need for diagnostics on the one -hand and RCU_NONIDLE() on the other while inspecting idle-loop code. -Steven Rostedt supplied ``_rcuidle`` event tracing, which is used quite -heavily in the idle loop. However, there are some restrictions on the -code placed within RCU_NONIDLE(): - -#. Blocking is prohibited. In practice, this is not a serious - restriction given that idle tasks are prohibited from blocking to - begin with. -#. Although nesting RCU_NONIDLE() is permitted, they cannot nest - indefinitely deeply. However, given that they can be nested on the - order of a million deep, even on 32-bit systems, this should not be a - serious restriction. This nesting limit would probably be reached - long after the compiler OOMed or the stack overflowed. -#. Any code path that enters RCU_NONIDLE() must sequence out of that - same RCU_NONIDLE(). For example, the following is grossly - illegal: - - :: - - 1 RCU_NONIDLE({ - 2 do_something(); - 3 goto bad_idea; /* BUG!!! */ - 4 do_something_else();}); - 5 bad_idea: - - - It is just as illegal to transfer control into the middle of - RCU_NONIDLE()'s argument. Yes, in theory, you could transfer in - as long as you also transferred out, but in practice you could also - expect to get sharply worded review comments. +``CONFIG_PROVE_RCU=y`` will splat if you try it.) It is similarly socially unacceptable to interrupt an ``nohz_full`` CPU running in userspace. RCU must therefore track ``nohz_full`` userspace diff --git a/Documentation/RCU/whatisRCU.rst b/Documentation/RCU/whatisRCU.rst index 8eddef28d3a1102a1442d9393d0120b81e3c44b3..e488c8e557a9c3215ae430c8d4765ce38a03c8c5 100644 --- a/Documentation/RCU/whatisRCU.rst +++ b/Documentation/RCU/whatisRCU.rst @@ -1117,7 +1117,6 @@ All: lockdep-checked RCU utility APIs:: RCU_LOCKDEP_WARN rcu_sleep_check - RCU_NONIDLE All: Unchecked RCU-protected pointer access:: diff --git a/Documentation/admin-guide/acpi/ssdt-overlays.rst b/Documentation/admin-guide/acpi/ssdt-overlays.rst index b5fbf54dca19bed8a7a252b5274b06470ef5d560..5ea9f4a3b76e3c3b720814451a6853c5a5d8bf06 100644 --- a/Documentation/admin-guide/acpi/ssdt-overlays.rst +++ b/Documentation/admin-guide/acpi/ssdt-overlays.rst @@ -103,7 +103,7 @@ allows a persistent, OS independent way of storing the user defined SSDTs. There is also work underway to implement EFI support for loading user defined SSDTs and using this method will make it easier to convert to the EFI loading mechanism when that will arrive. To enable it, the -CONFIG_EFI_CUSTOM_SSDT_OVERLAYS shoyld be chosen to y. +CONFIG_EFI_CUSTOM_SSDT_OVERLAYS should be chosen to y. In order to load SSDTs from an EFI variable the ``"efivar_ssdt=..."`` kernel command line parameter can be used (the name has a limitation of 16 characters). diff --git a/Documentation/admin-guide/bcache.rst b/Documentation/admin-guide/bcache.rst index bb5032a99234737f4a61fc242f98796f499542a5..6fdb495ac46652ac75f39ee8d3fd595a335f316e 100644 --- a/Documentation/admin-guide/bcache.rst +++ b/Documentation/admin-guide/bcache.rst @@ -508,9 +508,6 @@ cache_miss_collisions cache miss, but raced with a write and data was already present (usually 0 since the synchronization for cache misses was rewritten) -cache_readaheads - Count of times readahead occurred. - Sysfs - cache set ~~~~~~~~~~~~~~~~~ diff --git a/Documentation/admin-guide/cgroup-v1/memory.rst b/Documentation/admin-guide/cgroup-v1/memory.rst index 47d1d7d932a82be09b072854ee8de609823e4fe0..fabaad3fd9c212ddbbf9ca665ca79b61f3bd0d09 100644 --- a/Documentation/admin-guide/cgroup-v1/memory.rst +++ b/Documentation/admin-guide/cgroup-v1/memory.rst @@ -297,7 +297,7 @@ Lock order is as follows:: Page lock (PG_locked bit of page->flags) mm->page_table_lock or split pte_lock - lock_page_memcg (memcg->move_lock) + folio_memcg_lock (memcg->move_lock) mapping->i_pages lock lruvec->lru_lock. diff --git a/Documentation/admin-guide/cgroup-v2.rst b/Documentation/admin-guide/cgroup-v2.rst index e592a93644739f0b1812fa5754c2f93e8b2bf08d..4ef8901911961fff9727df7d0716c3a6a9eccd7b 100644 --- a/Documentation/admin-guide/cgroup-v2.rst +++ b/Documentation/admin-guide/cgroup-v2.rst @@ -1580,6 +1580,13 @@ PAGE_SIZE multiple when read back. Healthy workloads are not expected to reach this limit. + memory.swap.peak + A read-only single value file which exists on non-root + cgroups. + + The max swap usage recorded for the cgroup and its + descendants since the creation of the cgroup. + memory.swap.max A read-write single value file which exists on non-root cgroups. The default is "max". @@ -2022,31 +2029,33 @@ that attribute: no-change Do not modify the I/O priority class. - none-to-rt - For requests that do not have an I/O priority class (NONE), - change the I/O priority class into RT. Do not modify - the I/O priority class of other requests. + promote-to-rt + For requests that have a non-RT I/O priority class, change it into RT. + Also change the priority level of these requests to 4. Do not modify + the I/O priority of requests that have priority class RT. restrict-to-be For requests that do not have an I/O priority class or that have I/O - priority class RT, change it into BE. Do not modify the I/O priority - class of requests that have priority class IDLE. + priority class RT, change it into BE. Also change the priority level + of these requests to 0. Do not modify the I/O priority class of + requests that have priority class IDLE. idle Change the I/O priority class of all requests into IDLE, the lowest I/O priority class. + none-to-rt + Deprecated. Just an alias for promote-to-rt. + The following numerical values are associated with the I/O priority policies: -+-------------+---+ -| no-change | 0 | -+-------------+---+ -| none-to-rt | 1 | -+-------------+---+ -| rt-to-be | 2 | -+-------------+---+ -| all-to-idle | 3 | -+-------------+---+ ++----------------+---+ +| no-change | 0 | ++----------------+---+ +| rt-to-be | 2 | ++----------------+---+ +| all-to-idle | 3 | ++----------------+---+ The numerical value that corresponds to each I/O priority class is as follows: @@ -2062,9 +2071,13 @@ The numerical value that corresponds to each I/O priority class is as follows: The algorithm to set the I/O priority class for a request is as follows: -- Translate the I/O priority class policy into a number. -- Change the request I/O priority class into the maximum of the I/O priority - class policy number and the numerical I/O priority class. +- If I/O priority class policy is promote-to-rt, change the request I/O + priority class to IOPRIO_CLASS_RT and change the request I/O priority + level to 4. +- If I/O priorityt class is not promote-to-rt, translate the I/O priority + class policy into a number, then change the request I/O priority class + into the maximum of the I/O priority class policy number and the numerical + I/O priority class. PID --- @@ -2437,7 +2450,7 @@ Miscellaneous controller provides 3 interface files. If two misc resources (res_ res_b 10 misc.current - A read-only flat-keyed file shown in the non-root cgroups. It shows + A read-only flat-keyed file shown in the all cgroups. It shows the current usage of the resources in the cgroup and its children.:: $ cat misc.current diff --git a/Documentation/admin-guide/device-mapper/dm-flakey.rst b/Documentation/admin-guide/device-mapper/dm-flakey.rst index f7104c01b0f7425f99bd035a2310169175861e55..f967c5fea219b9c3cbe1fd81bc83cef42e564336 100644 --- a/Documentation/admin-guide/device-mapper/dm-flakey.rst +++ b/Documentation/admin-guide/device-mapper/dm-flakey.rst @@ -67,6 +67,16 @@ Optional feature parameters: Perform the replacement only if bio->bi_opf has all the selected flags set. + random_read_corrupt + During , replace random byte in a read bio + with a random value. probability is an integer between + 0 and 1000000000 meaning 0% to 100% probability of corruption. + + random_write_corrupt + During , replace random byte in a write bio + with a random value. probability is an integer between + 0 and 1000000000 meaning 0% to 100% probability of corruption. + Examples: Replaces the 32nd byte of READ bios with the value 1:: diff --git a/Documentation/admin-guide/device-mapper/dm-integrity.rst b/Documentation/admin-guide/device-mapper/dm-integrity.rst index 8db172efa272936501e788680fe0362d238dcb32..d8a5f14d0e3c41a78d77678519bd2513b04dc009 100644 --- a/Documentation/admin-guide/device-mapper/dm-integrity.rst +++ b/Documentation/admin-guide/device-mapper/dm-integrity.rst @@ -25,7 +25,7 @@ mode it calculates and verifies the integrity tag internally. In this mode, the dm-integrity target can be used to detect silent data corruption on the disk or in the I/O path. -There's an alternate mode of operation where dm-integrity uses bitmap +There's an alternate mode of operation where dm-integrity uses a bitmap instead of a journal. If a bit in the bitmap is 1, the corresponding region's data and integrity tags are not synchronized - if the machine crashes, the unsynchronized regions will be recalculated. The bitmap mode @@ -38,6 +38,15 @@ the device. But it will only format the device if the superblock contains zeroes. If the superblock is neither valid nor zeroed, the dm-integrity target can't be loaded. +Accesses to the on-disk metadata area containing checksums (aka tags) are +buffered using dm-bufio. When an access to any given metadata area +occurs, each unique metadata area gets its own buffer(s). The buffer size +is capped at the size of the metadata area, but may be smaller, thereby +requiring multiple buffers to represent the full metadata area. A smaller +buffer size will produce a smaller resulting read/write operation to the +metadata area for small reads/writes. The metadata is still read even in +a full write to the data covered by a single buffer. + To use the target for the first time: 1. overwrite the superblock with zeroes @@ -93,7 +102,7 @@ journal_sectors:number device. If the device is already formatted, the value from the superblock is used. -interleave_sectors:number +interleave_sectors:number (default 32768) The number of interleaved sectors. This values is rounded down to a power of two. If the device is already formatted, the value from the superblock is used. @@ -102,20 +111,16 @@ meta_device:device Don't interleave the data and metadata on the device. Use a separate device for metadata. -buffer_sectors:number - The number of sectors in one buffer. The value is rounded down to - a power of two. - - The tag area is accessed using buffers, the buffer size is - configurable. The large buffer size means that the I/O size will - be larger, but there could be less I/Os issued. +buffer_sectors:number (default 128) + The number of sectors in one metadata buffer. The value is rounded + down to a power of two. -journal_watermark:number +journal_watermark:number (default 50) The journal watermark in percents. When the size of the journal exceeds this watermark, the thread that flushes the journal will be started. -commit_time:number +commit_time:number (default 10000) Commit time in milliseconds. When this time passes, the journal is written. The journal is also written immediately if the FLUSH request is received. @@ -163,11 +168,10 @@ journal_mac:algorithm(:key) (the key is optional) the journal. Thus, modified sector number would be detected at this stage. -block_size:number - The size of a data block in bytes. The larger the block size the +block_size:number (default 512) + The size of a data block in bytes. The larger the block size the less overhead there is for per-block integrity metadata. - Supported values are 512, 1024, 2048 and 4096 bytes. If not - specified the default block size is 512 bytes. + Supported values are 512, 1024, 2048 and 4096 bytes. sectors_per_bit:number In the bitmap mode, this parameter specifies the number of @@ -209,6 +213,12 @@ table and swap the tables with suspend and resume). The other arguments should not be changed when reloading the target because the layout of disk data depend on them and the reloaded target would be non-functional. +For example, on a device using the default interleave_sectors of 32768, a +block_size of 512, and an internal_hash of crc32c with a tag size of 4 +bytes, it will take 128 KiB of tags to track a full data area, requiring +256 sectors of metadata per data area. With the default buffer_sectors of +128, that means there will be 2 buffers per metadata area, or 2 buffers +per 16 MiB of data. Status line: @@ -286,7 +296,8 @@ The layout of the formatted block device: Each run contains: * tag area - it contains integrity tags. There is one tag for each - sector in the data area + sector in the data area. The size of this area is always 4KiB or + greater. * data area - it contains data sectors. The number of data sectors in one run must be a power of two. log2 of this value is stored in the superblock. diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index 9e5bab29685ff0534fe82714dda5e20804c38ead..a1457995fd41cfb7db6cfa0cbb816fb9bbcd7fc0 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -1,17 +1,17 @@ - acpi= [HW,ACPI,X86,ARM64] + acpi= [HW,ACPI,X86,ARM64,RISCV64] Advanced Configuration and Power Interface Format: { force | on | off | strict | noirq | rsdt | copy_dsdt } force -- enable ACPI if default was off - on -- enable ACPI but allow fallback to DT [arm64] + on -- enable ACPI but allow fallback to DT [arm64,riscv64] off -- disable ACPI if default was on noirq -- do not use ACPI for IRQ routing strict -- Be less tolerant of platforms that are not strictly ACPI specification compliant. rsdt -- prefer RSDT over (default) XSDT copy_dsdt -- copy DSDT to memory - For ARM64, ONLY "acpi=off", "acpi=on" or "acpi=force" - are available + For ARM64 and RISCV64, ONLY "acpi=off", "acpi=on" or + "acpi=force" are available See also Documentation/power/runtime_pm.rst, pci=noacpi @@ -304,7 +304,7 @@ EL0 is indicated by /sys/devices/system/cpu/aarch32_el0 and hot-unplug operations may be restricted. - See Documentation/arm64/asymmetric-32bit.rst for more + See Documentation/arch/arm64/asymmetric-32bit.rst for more information. amd_iommu= [HW,X86-64] @@ -323,6 +323,7 @@ option with care. pgtbl_v1 - Use v1 page table for DMA-API (Default). pgtbl_v2 - Use v2 page table for DMA-API. + irtcachedis - Disable Interrupt Remapping Table (IRT) caching. amd_iommu_dump= [HW,X86-64] Enable AMD IOMMU driver option to dump the ACPI table @@ -429,6 +430,9 @@ arm64.nosme [ARM64] Unconditionally disable Scalable Matrix Extension support + arm64.nomops [ARM64] Unconditionally disable Memory Copy and Memory + Set instructions support + ataflop= [HW,M68k] atarimouse= [HW,MOUSE] Atari Mouse @@ -818,20 +822,6 @@ Format: ,,,[,] - cpu0_hotplug [X86] Turn on CPU0 hotplug feature when - CONFIG_BOOTPARAM_HOTPLUG_CPU0 is off. - Some features depend on CPU0. Known dependencies are: - 1. Resume from suspend/hibernate depends on CPU0. - Suspend/hibernate will fail if CPU0 is offline and you - need to online CPU0 before suspend/hibernate. - 2. PIC interrupts also depend on CPU0. CPU0 can't be - removed if a PIC interrupt is detected. - It's said poweroff/reboot may depend on CPU0 on some - machines although I haven't seen such issues so far - after CPU0 is offline on a few tested machines. - If the dependencies are under your control, you can - turn on cpu0_hotplug. - cpuidle.off=1 [CPU_IDLE] disable the cpuidle sub-system @@ -852,6 +842,12 @@ on every CPU online, such as boot, and resume from suspend. Default: 10000 + cpuhp.parallel= + [SMP] Enable/disable parallel bringup of secondary CPUs + Format: + Default is enabled if CONFIG_HOTPLUG_PARALLEL=y. Otherwise + the parameter has no effect. + crash_kexec_post_notifiers Run kdump after running panic-notifiers and dumping kmsg. This only for the users who doubt kdump always @@ -2117,6 +2113,16 @@ disable Do not enable intel_pstate as the default scaling driver for the supported processors + active + Use intel_pstate driver to bypass the scaling + governors layer of cpufreq and provides it own + algorithms for p-state selection. There are two + P-state selection algorithms provided by + intel_pstate in the active mode: powersave and + performance. The way they both operate depends + on whether or not the hardware managed P-states + (HWP) feature has been enabled in the processor + and possibly on the processor model. passive Use intel_pstate as a scaling driver, but configure it to work with generic cpufreq governors (instead of @@ -2551,12 +2557,13 @@ If the value is 0 (the default), KVM will pick a period based on the ratio, such that a page is zapped after 1 hour on average. - kvm-amd.nested= [KVM,AMD] Allow nested virtualization in KVM/SVM. - Default is 1 (enabled) + kvm-amd.nested= [KVM,AMD] Control nested virtualization feature in + KVM/SVM. Default is 1 (enabled). - kvm-amd.npt= [KVM,AMD] Disable nested paging (virtualized MMU) - for all guests. - Default is 1 (enabled) if in 64-bit or 32-bit PAE mode. + kvm-amd.npt= [KVM,AMD] Control KVM's use of Nested Page Tables, + a.k.a. Two-Dimensional Page Tables. Default is 1 + (enabled). Disable by KVM if hardware lacks support + for NPT. kvm-arm.mode= [KVM,ARM] Select one of KVM/arm64's modes of operation. @@ -2602,30 +2609,33 @@ Format: Default: 5 - kvm-intel.ept= [KVM,Intel] Disable extended page tables - (virtualized MMU) support on capable Intel chips. - Default is 1 (enabled) + kvm-intel.ept= [KVM,Intel] Control KVM's use of Extended Page Tables, + a.k.a. Two-Dimensional Page Tables. Default is 1 + (enabled). Disable by KVM if hardware lacks support + for EPT. kvm-intel.emulate_invalid_guest_state= - [KVM,Intel] Disable emulation of invalid guest state. - Ignored if kvm-intel.enable_unrestricted_guest=1, as - guest state is never invalid for unrestricted guests. - This param doesn't apply to nested guests (L2), as KVM - never emulates invalid L2 guest state. - Default is 1 (enabled) + [KVM,Intel] Control whether to emulate invalid guest + state. Ignored if kvm-intel.enable_unrestricted_guest=1, + as guest state is never invalid for unrestricted + guests. This param doesn't apply to nested guests (L2), + as KVM never emulates invalid L2 guest state. + Default is 1 (enabled). kvm-intel.flexpriority= - [KVM,Intel] Disable FlexPriority feature (TPR shadow). - Default is 1 (enabled) + [KVM,Intel] Control KVM's use of FlexPriority feature + (TPR shadow). Default is 1 (enabled). Disalbe by KVM if + hardware lacks support for it. kvm-intel.nested= - [KVM,Intel] Enable VMX nesting (nVMX). - Default is 0 (disabled) + [KVM,Intel] Control nested virtualization feature in + KVM/VMX. Default is 1 (enabled). kvm-intel.unrestricted_guest= - [KVM,Intel] Disable unrestricted guest feature - (virtualized real and unpaged mode) on capable - Intel chips. Default is 1 (enabled) + [KVM,Intel] Control KVM's use of unrestricted guest + feature (virtualized real and unpaged mode). Default + is 1 (enabled). Disable by KVM if EPT is disabled or + hardware lacks support for it. kvm-intel.vmentry_l1d_flush=[KVM,Intel] Mitigation for L1 Terminal Fault CVE-2018-3620. @@ -2639,9 +2649,10 @@ Default is cond (do L1 cache flush in specific instances) - kvm-intel.vpid= [KVM,Intel] Disable Virtual Processor Identification - feature (tagged TLBs) on capable Intel chips. - Default is 1 (enabled) + kvm-intel.vpid= [KVM,Intel] Control KVM's use of Virtual Processor + Identification feature (tagged TLBs). Default is 1 + (enabled). Disable by KVM if hardware lacks support + for it. l1d_flush= [X86,INTEL] Control mitigation for L1D based snooping vulnerability. @@ -3423,6 +3434,10 @@ [HW] Make the MicroTouch USB driver use raw coordinates ('y', default) or cooked coordinates ('n') + mtrr=debug [X86] + Enable printing debug information related to MTRR + registers at boot time. + mtrr_chunk_size=nn[KMG] [X86] used for mtrr cleanup. It is largest continuous chunk that could hold holes aka. UC entries. @@ -3702,8 +3717,8 @@ nohibernate [HIBERNATION] Disable hibernation and resume. - nohlt [ARM,ARM64,MICROBLAZE,SH] Forces the kernel to busy wait - in do_idle() and not use the arch_cpu_idle() + nohlt [ARM,ARM64,MICROBLAZE,MIPS,SH] Forces the kernel to + busy wait in do_idle() and not use the arch_cpu_idle() implementation; requires CONFIG_GENERIC_IDLE_POLL_SETUP to be effective. This is useful on platforms where the sleep(SH) or wfi(ARM,ARM64) instructions do not work @@ -3838,7 +3853,7 @@ nosmp [SMP] Tells an SMP kernel to act as a UP kernel, and disable the IO APIC. legacy for "maxcpus=0". - nosmt [KNL,S390] Disable symmetric multithreading (SMT). + nosmt [KNL,MIPS,S390] Disable symmetric multithreading (SMT). Equivalent to smt=1. [KNL,X86] Disable symmetric multithreading (SMT). @@ -4049,7 +4064,7 @@ extra details on the taint flags that users can pick to compose the bitmask to assign to panic_on_taint. - panic_on_warn panic() instead of WARN(). Useful to cause kdump + panic_on_warn=1 panic() instead of WARN(). Useful to cause kdump on a WARN(). parkbd.port= [HW] Parallel port number the keyboard adapter is @@ -4736,43 +4751,6 @@ the propagation of recent CPU-hotplug changes up the rcu_node combining tree. - rcutree.use_softirq= [KNL] - If set to zero, move all RCU_SOFTIRQ processing to - per-CPU rcuc kthreads. Defaults to a non-zero - value, meaning that RCU_SOFTIRQ is used by default. - Specify rcutree.use_softirq=0 to use rcuc kthreads. - - But note that CONFIG_PREEMPT_RT=y kernels disable - this kernel boot parameter, forcibly setting it - to zero. - - rcutree.rcu_fanout_exact= [KNL] - Disable autobalancing of the rcu_node combining - tree. This is used by rcutorture, and might - possibly be useful for architectures having high - cache-to-cache transfer latencies. - - rcutree.rcu_fanout_leaf= [KNL] - Change the number of CPUs assigned to each - leaf rcu_node structure. Useful for very - large systems, which will choose the value 64, - and for NUMA systems with large remote-access - latencies, which will choose a value aligned - with the appropriate hardware boundaries. - - rcutree.rcu_min_cached_objs= [KNL] - Minimum number of objects which are cached and - maintained per one CPU. Object size is equal - to PAGE_SIZE. The cache allows to reduce the - pressure to page allocator, also it makes the - whole algorithm to behave better in low memory - condition. - - rcutree.rcu_delay_page_cache_fill_msec= [KNL] - Set the page-cache refill delay (in milliseconds) - in response to low-memory conditions. The range - of permitted values is in the range 0:100000. - rcutree.jiffies_till_first_fqs= [KNL] Set delay from grace-period initialization to first attempt to force quiescent states. @@ -4811,21 +4789,6 @@ When RCU_NOCB_CPU is set, also adjust the priority of NOCB callback kthreads. - rcutree.rcu_divisor= [KNL] - Set the shift-right count to use to compute - the callback-invocation batch limit bl from - the number of callbacks queued on this CPU. - The result will be bounded below by the value of - the rcutree.blimit kernel parameter. Every bl - callbacks, the softirq handler will exit in - order to allow the CPU to do other work. - - Please note that this callback-invocation batch - limit applies only to non-offloaded callback - invocation. Offloaded callbacks are instead - invoked in the context of an rcuoc kthread, which - scheduler will preempt as it does any other task. - rcutree.nocb_nobypass_lim_per_jiffy= [KNL] On callback-offloaded (rcu_nocbs) CPUs, RCU reduces the lock contention that would @@ -4839,14 +4802,6 @@ the ->nocb_bypass queue. The definition of "too many" is supplied by this kernel boot parameter. - rcutree.rcu_nocb_gp_stride= [KNL] - Set the number of NOCB callback kthreads in - each group, which defaults to the square root - of the number of CPUs. Larger numbers reduce - the wakeup overhead on the global grace-period - kthread, but increases that same overhead on - each group's NOCB grace-period kthread. - rcutree.qhimark= [KNL] Set threshold of queued RCU callbacks beyond which batch limiting is disabled. @@ -4864,6 +4819,56 @@ on rcutree.qhimark at boot time and to zero to disable more aggressive help enlistment. + rcutree.rcu_delay_page_cache_fill_msec= [KNL] + Set the page-cache refill delay (in milliseconds) + in response to low-memory conditions. The range + of permitted values is in the range 0:100000. + + rcutree.rcu_divisor= [KNL] + Set the shift-right count to use to compute + the callback-invocation batch limit bl from + the number of callbacks queued on this CPU. + The result will be bounded below by the value of + the rcutree.blimit kernel parameter. Every bl + callbacks, the softirq handler will exit in + order to allow the CPU to do other work. + + Please note that this callback-invocation batch + limit applies only to non-offloaded callback + invocation. Offloaded callbacks are instead + invoked in the context of an rcuoc kthread, which + scheduler will preempt as it does any other task. + + rcutree.rcu_fanout_exact= [KNL] + Disable autobalancing of the rcu_node combining + tree. This is used by rcutorture, and might + possibly be useful for architectures having high + cache-to-cache transfer latencies. + + rcutree.rcu_fanout_leaf= [KNL] + Change the number of CPUs assigned to each + leaf rcu_node structure. Useful for very + large systems, which will choose the value 64, + and for NUMA systems with large remote-access + latencies, which will choose a value aligned + with the appropriate hardware boundaries. + + rcutree.rcu_min_cached_objs= [KNL] + Minimum number of objects which are cached and + maintained per one CPU. Object size is equal + to PAGE_SIZE. The cache allows to reduce the + pressure to page allocator, also it makes the + whole algorithm to behave better in low memory + condition. + + rcutree.rcu_nocb_gp_stride= [KNL] + Set the number of NOCB callback kthreads in + each group, which defaults to the square root + of the number of CPUs. Larger numbers reduce + the wakeup overhead on the global grace-period + kthread, but increases that same overhead on + each group's NOCB grace-period kthread. + rcutree.rcu_kick_kthreads= [KNL] Cause the grace-period kthread to get an extra wake_up() if it sleeps three times longer than @@ -4871,6 +4876,13 @@ This wake_up() will be accompanied by a WARN_ONCE() splat and an ftrace_dump(). + rcutree.rcu_resched_ns= [KNL] + Limit the time spend invoking a batch of RCU + callbacks to the specified number of nanoseconds. + By default, this limit is checked only once + every 32 callbacks in order to limit the pain + inflicted by local_clock() overhead. + rcutree.rcu_unlock_delay= [KNL] In CONFIG_RCU_STRICT_GRACE_PERIOD=y kernels, this specifies an rcu_read_unlock()-time delay @@ -4885,6 +4897,16 @@ rcu_node tree with an eye towards determining why a new grace period has not yet started. + rcutree.use_softirq= [KNL] + If set to zero, move all RCU_SOFTIRQ processing to + per-CPU rcuc kthreads. Defaults to a non-zero + value, meaning that RCU_SOFTIRQ is used by default. + Specify rcutree.use_softirq=0 to use rcuc kthreads. + + But note that CONFIG_PREEMPT_RT=y kernels disable + this kernel boot parameter, forcibly setting it + to zero. + rcuscale.gp_async= [KNL] Measure performance of asynchronous grace-period primitives such as call_rcu(). @@ -5087,8 +5109,17 @@ rcutorture.stall_cpu_block= [KNL] Sleep while stalling if set. This will result - in warnings from preemptible RCU in addition - to any other stall-related activity. + in warnings from preemptible RCU in addition to + any other stall-related activity. Note that + in kernels built with CONFIG_PREEMPTION=n and + CONFIG_PREEMPT_COUNT=y, this parameter will + cause the CPU to pass through a quiescent state. + Given CONFIG_PREEMPTION=n, this will suppress + RCU CPU stall warnings, but will instead result + in scheduling-while-atomic splats. + + Use of this module parameter results in splats. + rcutorture.stall_cpu_holdoff= [KNL] Time to wait (s) after boot before inducing stall. @@ -5452,7 +5483,12 @@ port and the regular usb controller gets disabled. root= [KNL] Root filesystem - See name_to_dev_t comment in init/do_mounts.c. + Usually this a a block device specifier of some kind, + see the early_lookup_bdev comment in + block/early-lookup.c for details. + Alternatively this can be "ram" for the legacy initial + ramdisk, "nfs" and "cifs" for root on a network file + system, or "mtd" and "ubi" for mounting from raw flash. rootdelay= [KNL] Delay (in seconds) to pause before attempting to mount the root filesystem @@ -5735,7 +5771,7 @@ 1: Fast pin select (default) 2: ATC IRMode - smt= [KNL,S390] Set the maximum number of threads (logical + smt= [KNL,MIPS,S390] Set the maximum number of threads (logical CPUs) to use per physical CPU on systems capable of symmetric multithreading (SMT). Will be capped to the actual hardware limit. @@ -6563,6 +6599,12 @@ unknown_nmi_panic [X86] Cause panic on unknown NMI. + unwind_debug [X86-64] + Enable unwinder debug output. This can be + useful for debugging certain unwinder error + conditions, including corrupt stacks and + bad/missing unwinder metadata. + usbcore.authorized_default= [USB] Default USB device authorization: (default -1 = authorized except for wireless USB, @@ -6931,6 +6973,18 @@ it can be updated at runtime by writing to the corresponding sysfs file. + workqueue.cpu_intensive_thresh_us= + Per-cpu work items which run for longer than this + threshold are automatically considered CPU intensive + and excluded from concurrency management to prevent + them from noticeably delaying other per-cpu work + items. Default is 10000 (10ms). + + If CONFIG_WQ_CPU_INTENSIVE_REPORT is set, the kernel + will report the work functions which violate this + threshold repeatedly. They are likely good + candidates for using WQ_UNBOUND workqueues instead. + workqueue.disable_numa By default, all work items queued to unbound workqueues are affine to the NUMA nodes they're diff --git a/Documentation/admin-guide/media/rkisp1.rst b/Documentation/admin-guide/media/rkisp1.rst index ccf418713623b676935cb422956c7418a15bd23c..6f14d9561fa5b715b3351ffee7f1a05dd78e927b 100644 --- a/Documentation/admin-guide/media/rkisp1.rst +++ b/Documentation/admin-guide/media/rkisp1.rst @@ -10,8 +10,8 @@ Introduction ============ This file documents the driver for the Rockchip ISP1 that is part of RK3288 -and RK3399 SoCs. The driver is located under drivers/staging/media/rkisp1 -and uses the Media-Controller API. +and RK3399 SoCs. The driver is located under drivers/media/platform/rockchip/ +rkisp1 and uses the Media-Controller API. Revisions ========= diff --git a/Documentation/admin-guide/mm/damon/start.rst b/Documentation/admin-guide/mm/damon/start.rst index 9f88afc734da47d6073aba43fe4939d5d61c5793..7aa0071ff1c365496a7142f3363abb1f89cb3234 100644 --- a/Documentation/admin-guide/mm/damon/start.rst +++ b/Documentation/admin-guide/mm/damon/start.rst @@ -119,9 +119,9 @@ set size has chronologically changed.:: Data Access Pattern Aware Memory Management =========================================== -Below three commands make every memory region of size >=4K that doesn't -accessed for >=60 seconds in your workload to be swapped out. :: +Below command makes every memory region of size >=4K that has not accessed for +>=60 seconds in your workload to be swapped out. :: - $ echo "#min-size max-size min-acc max-acc min-age max-age action" > test_scheme - $ echo "4K max 0 0 60s max pageout" >> test_scheme - $ damo schemes -c test_scheme + $ sudo damo schemes --damos_access_rate 0 0 --damos_sz_region 4K max \ + --damos_age 60s max --damos_action pageout \ + diff --git a/Documentation/admin-guide/mm/damon/usage.rst b/Documentation/admin-guide/mm/damon/usage.rst index 9b823fec974dd06a33e53ccdcfe82c5567771dbc..2d495fa85a0ee9ea6f3e87b242de98e75c3d5e07 100644 --- a/Documentation/admin-guide/mm/damon/usage.rst +++ b/Documentation/admin-guide/mm/damon/usage.rst @@ -10,9 +10,8 @@ DAMON provides below interfaces for different users. `This `_ is for privileged people such as system administrators who want a just-working human-friendly interface. Using this, users can use the DAMON’s major features in a human-friendly way. - It may not be highly tuned for special cases, though. It supports both - virtual and physical address spaces monitoring. For more detail, please - refer to its `usage document + It may not be highly tuned for special cases, though. For more detail, + please refer to its `usage document `_. - *sysfs interface.* :ref:`This ` is for privileged user space programmers who @@ -20,11 +19,7 @@ DAMON provides below interfaces for different users. features by reading from and writing to special sysfs files. Therefore, you can write and use your personalized DAMON sysfs wrapper programs that reads/writes the sysfs files instead of you. The `DAMON user space tool - `_ is one example of such programs. It - supports both virtual and physical address spaces monitoring. Note that this - interface provides only simple :ref:`statistics ` for the - monitoring results. For detailed monitoring results, DAMON provides a - :ref:`tracepoint `. + `_ is one example of such programs. - *debugfs interface. (DEPRECATED!)* :ref:`This ` is almost identical to :ref:`sysfs interface `. This is deprecated, so users should move to the @@ -139,7 +134,7 @@ scheme of the kdamond. Writing ``clear_schemes_tried_regions`` to ``state`` file clears the DAMON-based operating scheme action tried regions directory for each DAMON-based operation scheme of the kdamond. For details of the DAMON-based operation scheme action tried regions directory, please refer to -:ref:tried_regions section `. +:ref:`tried_regions section `. If the state is ``on``, reading ``pid`` shows the pid of the kdamond thread. @@ -259,12 +254,9 @@ be equal or smaller than ``start`` of directory ``N+1``. contexts//schemes/ --------------------- -For usual DAMON-based data access aware memory management optimizations, users -would normally want the system to apply a memory management action to a memory -region of a specific access pattern. DAMON receives such formalized operation -schemes from the user and applies those to the target memory regions. Users -can get and set the schemes by reading from and writing to files under this -directory. +The directory for DAMON-based Operation Schemes (:ref:`DAMOS +`). Users can get and set the schemes by reading from and +writing to files under this directory. In the beginning, this directory has only one file, ``nr_schemes``. Writing a number (``N``) to the file creates the number of child directories named ``0`` @@ -277,12 +269,12 @@ In each scheme directory, five directories (``access_pattern``, ``quotas``, ``watermarks``, ``filters``, ``stats``, and ``tried_regions``) and one file (``action``) exist. -The ``action`` file is for setting and getting what action you want to apply to -memory regions having specific access pattern of the interest. The keywords -that can be written to and read from the file and their meaning are as below. +The ``action`` file is for setting and getting the scheme's :ref:`action +`. The keywords that can be written to and read +from the file and their meaning are as below. Note that support of each action depends on the running DAMON operations set -`implementation `. +:ref:`implementation `. - ``willneed``: Call ``madvise()`` for the region with ``MADV_WILLNEED``. Supported by ``vaddr`` and ``fvaddr`` operations set. @@ -304,32 +296,21 @@ Note that support of each action depends on the running DAMON operations set schemes//access_pattern/ --------------------------- -The target access pattern of each DAMON-based operation scheme is constructed -with three ranges including the size of the region in bytes, number of -monitored accesses per aggregate interval, and number of aggregated intervals -for the age of the region. +The directory for the target access :ref:`pattern +` of the given DAMON-based operation scheme. Under the ``access_pattern`` directory, three directories (``sz``, ``nr_accesses``, and ``age``) each having two files (``min`` and ``max``) exist. You can set and get the access pattern for the given scheme by writing to and reading from the ``min`` and ``max`` files under ``sz``, -``nr_accesses``, and ``age`` directories, respectively. +``nr_accesses``, and ``age`` directories, respectively. Note that the ``min`` +and the ``max`` form a closed interval. schemes//quotas/ ------------------- -Optimal ``target access pattern`` for each ``action`` is workload dependent, so -not easy to find. Worse yet, setting a scheme of some action too aggressive -can cause severe overhead. To avoid such overhead, users can limit time and -size quota for each scheme. In detail, users can ask DAMON to try to use only -up to specific time (``time quota``) for applying the action, and to apply the -action to only up to specific amount (``size quota``) of memory regions having -the target access pattern within a given time interval (``reset interval``). - -When the quota limit is expected to be exceeded, DAMON prioritizes found memory -regions of the ``target access pattern`` based on their size, access frequency, -and age. For personalized prioritization, users can set the weights for the -three properties. +The directory for the :ref:`quotas ` of the given +DAMON-based operation scheme. Under ``quotas`` directory, three files (``ms``, ``bytes``, ``reset_interval_ms``) and one directory (``weights``) having three files @@ -337,23 +318,26 @@ Under ``quotas`` directory, three files (``ms``, ``bytes``, You can set the ``time quota`` in milliseconds, ``size quota`` in bytes, and ``reset interval`` in milliseconds by writing the values to the three files, -respectively. You can also set the prioritization weights for size, access -frequency, and age in per-thousand unit by writing the values to the three -files under the ``weights`` directory. +respectively. Then, DAMON tries to use only up to ``time quota`` milliseconds +for applying the ``action`` to memory regions of the ``access_pattern``, and to +apply the action to only up to ``bytes`` bytes of memory regions within the +``reset_interval_ms``. Setting both ``ms`` and ``bytes`` zero disables the +quota limits. + +You can also set the :ref:`prioritization weights +` for size, access frequency, and age +in per-thousand unit by writing the values to the three files under the +``weights`` directory. schemes//watermarks/ ----------------------- -To allow easy activation and deactivation of each scheme based on system -status, DAMON provides a feature called watermarks. The feature receives five -values called ``metric``, ``interval``, ``high``, ``mid``, and ``low``. The -``metric`` is the system metric such as free memory ratio that can be measured. -If the metric value of the system is higher than the value in ``high`` or lower -than ``low`` at the memoent, the scheme is deactivated. If the value is lower -than ``mid``, the scheme is activated. +The directory for the :ref:`watermarks ` of the +given DAMON-based operation scheme. Under the watermarks directory, five files (``metric``, ``interval_us``, -``high``, ``mid``, and ``low``) for setting each value exist. You can set and +``high``, ``mid``, and ``low``) for setting the metric, the time interval +between check of the metric, and the three watermarks exist. You can set and get the five values by writing to the files, respectively. Keywords and meanings of those that can be written to the ``metric`` file are @@ -367,12 +351,8 @@ The ``interval`` should written in microseconds unit. schemes//filters/ -------------------- -Users could know something more than the kernel for specific types of memory. -In the case, users could do their own management for the memory and hence -doesn't want DAMOS bothers that. Users could limit DAMOS by setting the access -pattern of the scheme and/or the monitoring regions for the purpose, but that -can be inefficient in some cases. In such cases, users could set non-access -pattern driven filters using files in this directory. +The directory for the :ref:`filters ` of the given +DAMON-based operation scheme. In the beginning, this directory has only one file, ``nr_filters``. Writing a number (``N``) to the file creates the number of child directories named ``0`` @@ -432,13 +412,17 @@ starting from ``0`` under this directory. Each directory contains files exposing detailed information about each of the memory region that the corresponding scheme's ``action`` has tried to be applied under this directory, during next :ref:`aggregation interval `. The -information includes address range, ``nr_accesses``, , and ``age`` of the -region. +information includes address range, ``nr_accesses``, and ``age`` of the region. The directories will be removed when another special keyword, ``clear_schemes_tried_regions``, is written to the relevant ``kdamonds//state`` file. +The expected usage of this directory is investigations of schemes' behaviors, +and query-like efficient data access monitoring results retrievals. For the +latter use case, in particular, users can set the ``action`` as ``stat`` and +set the ``access pattern`` as their interested pattern that they want to query. + tried_regions// ------------------ @@ -600,15 +584,10 @@ update. Schemes ------- -For usual DAMON-based data access aware memory management optimizations, users -would simply want the system to apply a memory management action to a memory -region of a specific access pattern. DAMON receives such formalized operation -schemes from the user and applies those to the target processes. - -Users can get and set the schemes by reading from and writing to ``schemes`` -debugfs file. Reading the file also shows the statistics of each scheme. To -the file, each of the schemes should be represented in each line in below -form:: +Users can get and set the DAMON-based operation :ref:`schemes +` by reading from and writing to ``schemes`` debugfs file. +Reading the file also shows the statistics of each scheme. To the file, each +of the schemes should be represented in each line in below form:: @@ -617,8 +596,9 @@ You can disable schemes by simply writing an empty string to the file. Target Access Pattern ~~~~~~~~~~~~~~~~~~~~~ -The ```` is constructed with three ranges in below -form:: +The target access :ref:`pattern ` of the +scheme. The ```` is constructed with three ranges in +below form:: min-size max-size min-acc max-acc min-age max-age @@ -631,9 +611,9 @@ closed interval. Action ~~~~~~ -The ```` is a predefined integer for memory management actions, which -DAMON will apply to the regions having the target access pattern. The -supported numbers and their meanings are as below. +The ```` is a predefined integer for memory management :ref:`actions +`. The supported numbers and their meanings are as +below. - 0: Call ``madvise()`` for the region with ``MADV_WILLNEED``. Ignored if ``target`` is ``paddr``. @@ -649,10 +629,8 @@ supported numbers and their meanings are as below. Quota ~~~~~ -Optimal ``target access pattern`` for each ``action`` is workload dependent, so -not easy to find. Worse yet, setting a scheme of some action too aggressive -can cause severe overhead. To avoid such overhead, users can limit time and -size quota for the scheme via the ```` in below form:: +Users can set the :ref:`quotas ` of the given scheme +via the ```` in below form:: @@ -662,19 +640,17 @@ the action to memory regions of the ``target access pattern`` within the ```` bytes of memory regions within the ````. Setting both ```` and ```` zero disables the quota limits. -When the quota limit is expected to be exceeded, DAMON prioritizes found memory -regions of the ``target access pattern`` based on their size, access frequency, -and age. For personalized prioritization, users can set the weights for the -three properties in ```` in below form:: +For the :ref:`prioritization `, users +can set the weights for the three properties in ```` in below +form:: Watermarks ~~~~~~~~~~ -Some schemes would need to run based on current value of the system's specific -metrics like free memory ratio. For such cases, users can specify watermarks -for the condition.:: +Users can specify :ref:`watermarks ` of the +given scheme via ```` in below form:: @@ -797,10 +773,12 @@ root directory only. Tracepoint for Monitoring Results ================================= -DAMON provides the monitoring results via a tracepoint, -``damon:damon_aggregated``. While the monitoring is turned on, you could -record the tracepoint events and show results using tracepoint supporting tools -like ``perf``. For example:: +Users can get the monitoring results via the :ref:`tried_regions +` or a tracepoint, ``damon:damon_aggregated``. +While the tried regions directory is useful for getting a snapshot, the +tracepoint is useful for getting a full record of the results. While the +monitoring is turned on, you could record the tracepoint events and show +results using tracepoint supporting tools like ``perf``. For example:: # echo on > monitor_on # perf record -e damon:damon_aggregated & diff --git a/Documentation/admin-guide/perf/cxl.rst b/Documentation/admin-guide/perf/cxl.rst new file mode 100644 index 0000000000000000000000000000000000000000..9233ea0d0b1042ea076b4913063f82a3369f7efe --- /dev/null +++ b/Documentation/admin-guide/perf/cxl.rst @@ -0,0 +1,68 @@ +.. SPDX-License-Identifier: GPL-2.0 + +====================================== +CXL Performance Monitoring Unit (CPMU) +====================================== + +The CXL rev 3.0 specification provides a definition of CXL Performance +Monitoring Unit in section 13.2: Performance Monitoring. + +CXL components (e.g. Root Port, Switch Upstream Port, End Point) may have +any number of CPMU instances. CPMU capabilities are fully discoverable from +the devices. The specification provides event definitions for all CXL protocol +message types and a set of additional events for things commonly counted on +CXL devices (e.g. DRAM events). + +CPMU driver +=========== + +The CPMU driver registers a perf PMU with the name pmu_mem. on the CXL bus +representing the Yth CPMU for memX. + + /sys/bus/cxl/device/pmu_mem. + +The associated PMU is registered as + + /sys/bus/event_sources/devices/cxl_pmu_mem. + +In common with other CXL bus devices, the id has no specific meaning and the +relationship to specific CXL device should be established via the device parent +of the device on the CXL bus. + +PMU driver provides description of available events and filter options in sysfs. + +The "format" directory describes all formats of the config (event vendor id, +group id and mask) config1 (threshold, filter enables) and config2 (filter +parameters) fields of the perf_event_attr structure. The "events" directory +describes all documented events show in perf list. + +The events shown in perf list are the most fine grained events with a single +bit of the event mask set. More general events may be enable by setting +multiple mask bits in config. For example, all Device to Host Read Requests +may be captured on a single counter by setting the bits for all of + +* d2h_req_rdcurr +* d2h_req_rdown +* d2h_req_rdshared +* d2h_req_rdany +* d2h_req_rdownnodata + +Example of usage:: + + $#perf list + cxl_pmu_mem0.0/clock_ticks/ [Kernel PMU event] + cxl_pmu_mem0.0/d2h_req_rdshared/ [Kernel PMU event] + cxl_pmu_mem0.0/h2d_req_snpcur/ [Kernel PMU event] + cxl_pmu_mem0.0/h2d_req_snpdata/ [Kernel PMU event] + cxl_pmu_mem0.0/h2d_req_snpinv/ [Kernel PMU event] + ----------------------------------------------------------- + + $# perf stat -a -e cxl_pmu_mem0.0/clock_ticks/ -e cxl_pmu_mem0.0/d2h_req_rdshared/ + +Vendor specific events may also be available and if so can be used via + + $# perf stat -a -e cxl_pmu_mem0.0/vid=VID,gid=GID,mask=MASK/ + +The driver does not support sampling so "perf record" is unsupported. +It only supports system-wide counting so attaching to a task is +unsupported. diff --git a/Documentation/admin-guide/perf/hisi-pmu.rst b/Documentation/admin-guide/perf/hisi-pmu.rst index 546979360513154824e221ae2739f25c59bbc4d1..e0174d20809a18470ab5809c4bd7336247826b15 100644 --- a/Documentation/admin-guide/perf/hisi-pmu.rst +++ b/Documentation/admin-guide/perf/hisi-pmu.rst @@ -56,14 +56,14 @@ Example usage of perf:: For HiSilicon uncore PMU v2 whose identifier is 0x30, the topology is the same as PMU v1, but some new functions are added to the hardware. -(a) L3C PMU supports filtering by core/thread within the cluster which can be +1. L3C PMU supports filtering by core/thread within the cluster which can be specified as a bitmap:: $# perf stat -a -e hisi_sccl3_l3c0/config=0x02,tt_core=0x3/ sleep 5 This will only count the operations from core/thread 0 and 1 in this cluster. -(b) Tracetag allow the user to chose to count only read, write or atomic +2. Tracetag allow the user to chose to count only read, write or atomic operations via the tt_req parameeter in perf. The default value counts all operations. tt_req is 3bits, 3'b100 represents read operations, 3'b101 represents write operations, 3'b110 represents atomic store operations and @@ -73,14 +73,16 @@ represents write operations, 3'b110 represents atomic store operations and This will only count the read operations in this cluster. -(c) Datasrc allows the user to check where the data comes from. It is 5 bits. +3. Datasrc allows the user to check where the data comes from. It is 5 bits. Some important codes are as follows: -5'b00001: comes from L3C in this die; -5'b01000: comes from L3C in the cross-die; -5'b01001: comes from L3C which is in another socket; -5'b01110: comes from the local DDR; -5'b01111: comes from the cross-die DDR; -5'b10000: comes from cross-socket DDR; + +- 5'b00001: comes from L3C in this die; +- 5'b01000: comes from L3C in the cross-die; +- 5'b01001: comes from L3C which is in another socket; +- 5'b01110: comes from the local DDR; +- 5'b01111: comes from the cross-die DDR; +- 5'b10000: comes from cross-socket DDR; + etc, it is mainly helpful to find that the data source is nearest from the CPU cores. If datasrc_cfg is used in the multi-chips, the datasrc_skt shall be configured in perf command:: @@ -88,15 +90,25 @@ configured in perf command:: $# perf stat -a -e hisi_sccl3_l3c0/config=0xb9,datasrc_cfg=0xE/, hisi_sccl3_l3c0/config=0xb9,datasrc_cfg=0xF/ sleep 5 -(d)Some HiSilicon SoCs encapsulate multiple CPU and IO dies. Each CPU die +4. Some HiSilicon SoCs encapsulate multiple CPU and IO dies. Each CPU die contains several Compute Clusters (CCLs). The I/O dies are called Super I/O clusters (SICL) containing multiple I/O clusters (ICLs). Each CCL/ICL in the SoC has a unique ID. Each ID is 11bits, include a 6-bit SCCL-ID and 5-bit CCL/ICL-ID. For I/O die, the ICL-ID is followed by: -5'b00000: I/O_MGMT_ICL; -5'b00001: Network_ICL; -5'b00011: HAC_ICL; -5'b10000: PCIe_ICL; + +- 5'b00000: I/O_MGMT_ICL; +- 5'b00001: Network_ICL; +- 5'b00011: HAC_ICL; +- 5'b10000: PCIe_ICL; + +5. uring_channel: UC PMU events 0x47~0x59 supports filtering by tx request +uring channel. It is 2 bits. Some important codes are as follows: + +- 2'b11: count the events which sent to the uring_ext (MATA) channel; +- 2'b01: is the same as 2'b11; +- 2'b10: count the events which sent to the uring (non-MATA) channel; +- 2'b00: default value, count the events which sent to the both uring and + uring_ext channel; Users could configure IDs to count data come from specific CCL/ICL, by setting srcid_cmd & srcid_msk, and data desitined for specific CCL/ICL by setting diff --git a/Documentation/admin-guide/perf/index.rst b/Documentation/admin-guide/perf/index.rst index 9de64a40adab9abf6ccf11bc45bcb0a1c5bb4a00..f60be04e4e336ecfc3d00eca73b609c3d20a909d 100644 --- a/Documentation/admin-guide/perf/index.rst +++ b/Documentation/admin-guide/perf/index.rst @@ -21,3 +21,4 @@ Performance monitor support alibaba_pmu nvidia-pmu meson-ddr-pmu + cxl diff --git a/Documentation/admin-guide/pm/intel_uncore_frequency_scaling.rst b/Documentation/admin-guide/pm/intel_uncore_frequency_scaling.rst index 09169d9358356163c54ad5214d010385ddecd1cf..5ab3440e6cee06b5ad7fd76371a1da53390df42f 100644 --- a/Documentation/admin-guide/pm/intel_uncore_frequency_scaling.rst +++ b/Documentation/admin-guide/pm/intel_uncore_frequency_scaling.rst @@ -5,7 +5,7 @@ Intel Uncore Frequency Scaling ============================== -:Copyright: |copy| 2022 Intel Corporation +:Copyright: |copy| 2022-2023 Intel Corporation :Author: Srinivas Pandruvada @@ -58,3 +58,58 @@ Each package_*_die_* contains the following attributes: ``current_freq_khz`` This attribute is used to get the current uncore frequency. + +SoCs with TPMI (Topology Aware Register and PM Capsule Interface) +----------------------------------------------------------------- + +An SoC can contain multiple power domains with individual or collection +of mesh partitions. This partition is called fabric cluster. + +Certain type of meshes will need to run at the same frequency, they will +be placed in the same fabric cluster. Benefit of fabric cluster is that it +offers a scalable mechanism to deal with partitioned fabrics in a SoC. + +The current sysfs interface supports controls at package and die level. +This interface is not enough to support more granular control at +fabric cluster level. + +SoCs with the support of TPMI (Topology Aware Register and PM Capsule +Interface), can have multiple power domains. Each power domain can +contain one or more fabric clusters. + +To represent controls at fabric cluster level in addition to the +controls at package and die level (like systems without TPMI +support), sysfs is enhanced. This granular interface is presented in the +sysfs with directories names prefixed with "uncore". For example: +uncore00, uncore01 etc. + +The scope of control is specified by attributes "package_id", "domain_id" +and "fabric_cluster_id" in the directory. + +Attributes in each directory: + +``domain_id`` + This attribute is used to get the power domain id of this instance. + +``fabric_cluster_id`` + This attribute is used to get the fabric cluster id of this instance. + +``package_id`` + This attribute is used to get the package id of this instance. + +The other attributes are same as presented at package_*_die_* level. + +In most of current use cases, the "max_freq_khz" and "min_freq_khz" +is updated at "package_*_die_*" level. This model will be still supported +with the following approach: + +When user uses controls at "package_*_die_*" level, then every fabric +cluster is affected in that package and die. For example: user changes +"max_freq_khz" in the package_00_die_00, then "max_freq_khz" for uncore* +directory with the same package id will be updated. In this case user can +still update "max_freq_khz" at each uncore* level, which is more restrictive. +Similarly, user can update "min_freq_khz" at "package_*_die_*" level +to apply at each uncore* level. + +Support for "current_freq_khz" is available only at each fabric cluster +level (i.e., in uncore* directory). diff --git a/Documentation/admin-guide/sysctl/kernel.rst b/Documentation/admin-guide/sysctl/kernel.rst index d85d90f5d000d863ebd6dc17c8f6422a333899ea..3800fab1619b22a540f6a2acf9970650edd86ae7 100644 --- a/Documentation/admin-guide/sysctl/kernel.rst +++ b/Documentation/admin-guide/sysctl/kernel.rst @@ -949,7 +949,7 @@ user space can read performance monitor counter registers directly. The default value is 0 (access disabled). -See Documentation/arm64/perf.rst for more information. +See Documentation/arch/arm64/perf.rst for more information. pid_max diff --git a/Documentation/admin-guide/sysctl/net.rst b/Documentation/admin-guide/sysctl/net.rst index 466c560b0c3044ddc5509c9cc13b80ca3905bbbc..4877563241f3bda508320a28e30275590cdba31d 100644 --- a/Documentation/admin-guide/sysctl/net.rst +++ b/Documentation/admin-guide/sysctl/net.rst @@ -386,8 +386,8 @@ Default : 0 (for compatibility reasons) txrehash -------- -Controls default hash rethink behaviour on listening socket when SO_TXREHASH -option is set to SOCK_TXREHASH_DEFAULT (i. e. not overridden by setsockopt). +Controls default hash rethink behaviour on socket when SO_TXREHASH option is set +to SOCK_TXREHASH_DEFAULT (i. e. not overridden by setsockopt). If set to 1 (default), hash rethink is performed on listening socket. If set to 0, hash rethink is not performed. diff --git a/Documentation/arm/arm.rst b/Documentation/arch/arm/arm.rst similarity index 100% rename from Documentation/arm/arm.rst rename to Documentation/arch/arm/arm.rst diff --git a/Documentation/arm/booting.rst b/Documentation/arch/arm/booting.rst similarity index 100% rename from Documentation/arm/booting.rst rename to Documentation/arch/arm/booting.rst diff --git a/Documentation/arm/cluster-pm-race-avoidance.rst b/Documentation/arch/arm/cluster-pm-race-avoidance.rst similarity index 100% rename from Documentation/arm/cluster-pm-race-avoidance.rst rename to Documentation/arch/arm/cluster-pm-race-avoidance.rst diff --git a/Documentation/arm/features.rst b/Documentation/arch/arm/features.rst similarity index 100% rename from Documentation/arm/features.rst rename to Documentation/arch/arm/features.rst diff --git a/Documentation/arm/firmware.rst b/Documentation/arch/arm/firmware.rst similarity index 100% rename from Documentation/arm/firmware.rst rename to Documentation/arch/arm/firmware.rst diff --git a/Documentation/arm/google/chromebook-boot-flow.rst b/Documentation/arch/arm/google/chromebook-boot-flow.rst similarity index 100% rename from Documentation/arm/google/chromebook-boot-flow.rst rename to Documentation/arch/arm/google/chromebook-boot-flow.rst diff --git a/Documentation/arm/index.rst b/Documentation/arch/arm/index.rst similarity index 100% rename from Documentation/arm/index.rst rename to Documentation/arch/arm/index.rst diff --git a/Documentation/arm/interrupts.rst b/Documentation/arch/arm/interrupts.rst similarity index 100% rename from Documentation/arm/interrupts.rst rename to Documentation/arch/arm/interrupts.rst diff --git a/Documentation/arm/ixp4xx.rst b/Documentation/arch/arm/ixp4xx.rst similarity index 100% rename from Documentation/arm/ixp4xx.rst rename to Documentation/arch/arm/ixp4xx.rst diff --git a/Documentation/arm/kernel_mode_neon.rst b/Documentation/arch/arm/kernel_mode_neon.rst similarity index 100% rename from Documentation/arm/kernel_mode_neon.rst rename to Documentation/arch/arm/kernel_mode_neon.rst diff --git a/Documentation/arm/kernel_user_helpers.rst b/Documentation/arch/arm/kernel_user_helpers.rst similarity index 100% rename from Documentation/arm/kernel_user_helpers.rst rename to Documentation/arch/arm/kernel_user_helpers.rst diff --git a/Documentation/arm/keystone/knav-qmss.rst b/Documentation/arch/arm/keystone/knav-qmss.rst similarity index 100% rename from Documentation/arm/keystone/knav-qmss.rst rename to Documentation/arch/arm/keystone/knav-qmss.rst diff --git a/Documentation/arm/keystone/overview.rst b/Documentation/arch/arm/keystone/overview.rst similarity index 100% rename from Documentation/arm/keystone/overview.rst rename to Documentation/arch/arm/keystone/overview.rst diff --git a/Documentation/arm/marvell.rst b/Documentation/arch/arm/marvell.rst similarity index 100% rename from Documentation/arm/marvell.rst rename to Documentation/arch/arm/marvell.rst diff --git a/Documentation/arm/mem_alignment.rst b/Documentation/arch/arm/mem_alignment.rst similarity index 100% rename from Documentation/arm/mem_alignment.rst rename to Documentation/arch/arm/mem_alignment.rst diff --git a/Documentation/arm/memory.rst b/Documentation/arch/arm/memory.rst similarity index 100% rename from Documentation/arm/memory.rst rename to Documentation/arch/arm/memory.rst diff --git a/Documentation/arm/microchip.rst b/Documentation/arch/arm/microchip.rst similarity index 100% rename from Documentation/arm/microchip.rst rename to Documentation/arch/arm/microchip.rst diff --git a/Documentation/arm/netwinder.rst b/Documentation/arch/arm/netwinder.rst similarity index 100% rename from Documentation/arm/netwinder.rst rename to Documentation/arch/arm/netwinder.rst diff --git a/Documentation/arm/nwfpe/index.rst b/Documentation/arch/arm/nwfpe/index.rst similarity index 100% rename from Documentation/arm/nwfpe/index.rst rename to Documentation/arch/arm/nwfpe/index.rst diff --git a/Documentation/arm/nwfpe/netwinder-fpe.rst b/Documentation/arch/arm/nwfpe/netwinder-fpe.rst similarity index 100% rename from Documentation/arm/nwfpe/netwinder-fpe.rst rename to Documentation/arch/arm/nwfpe/netwinder-fpe.rst diff --git a/Documentation/arm/nwfpe/notes.rst b/Documentation/arch/arm/nwfpe/notes.rst similarity index 100% rename from Documentation/arm/nwfpe/notes.rst rename to Documentation/arch/arm/nwfpe/notes.rst diff --git a/Documentation/arm/nwfpe/nwfpe.rst b/Documentation/arch/arm/nwfpe/nwfpe.rst similarity index 100% rename from Documentation/arm/nwfpe/nwfpe.rst rename to Documentation/arch/arm/nwfpe/nwfpe.rst diff --git a/Documentation/arm/nwfpe/todo.rst b/Documentation/arch/arm/nwfpe/todo.rst similarity index 100% rename from Documentation/arm/nwfpe/todo.rst rename to Documentation/arch/arm/nwfpe/todo.rst diff --git a/Documentation/arm/omap/dss.rst b/Documentation/arch/arm/omap/dss.rst similarity index 100% rename from Documentation/arm/omap/dss.rst rename to Documentation/arch/arm/omap/dss.rst diff --git a/Documentation/arm/omap/index.rst b/Documentation/arch/arm/omap/index.rst similarity index 100% rename from Documentation/arm/omap/index.rst rename to Documentation/arch/arm/omap/index.rst diff --git a/Documentation/arm/omap/omap.rst b/Documentation/arch/arm/omap/omap.rst similarity index 100% rename from Documentation/arm/omap/omap.rst rename to Documentation/arch/arm/omap/omap.rst diff --git a/Documentation/arm/omap/omap_pm.rst b/Documentation/arch/arm/omap/omap_pm.rst similarity index 100% rename from Documentation/arm/omap/omap_pm.rst rename to Documentation/arch/arm/omap/omap_pm.rst diff --git a/Documentation/arm/porting.rst b/Documentation/arch/arm/porting.rst similarity index 100% rename from Documentation/arm/porting.rst rename to Documentation/arch/arm/porting.rst diff --git a/Documentation/arm/pxa/mfp.rst b/Documentation/arch/arm/pxa/mfp.rst similarity index 100% rename from Documentation/arm/pxa/mfp.rst rename to Documentation/arch/arm/pxa/mfp.rst diff --git a/Documentation/arm/sa1100/assabet.rst b/Documentation/arch/arm/sa1100/assabet.rst similarity index 100% rename from Documentation/arm/sa1100/assabet.rst rename to Documentation/arch/arm/sa1100/assabet.rst diff --git a/Documentation/arm/sa1100/cerf.rst b/Documentation/arch/arm/sa1100/cerf.rst similarity index 100% rename from Documentation/arm/sa1100/cerf.rst rename to Documentation/arch/arm/sa1100/cerf.rst diff --git a/Documentation/arm/sa1100/index.rst b/Documentation/arch/arm/sa1100/index.rst similarity index 100% rename from Documentation/arm/sa1100/index.rst rename to Documentation/arch/arm/sa1100/index.rst diff --git a/Documentation/arm/sa1100/lart.rst b/Documentation/arch/arm/sa1100/lart.rst similarity index 100% rename from Documentation/arm/sa1100/lart.rst rename to Documentation/arch/arm/sa1100/lart.rst diff --git a/Documentation/arm/sa1100/serial_uart.rst b/Documentation/arch/arm/sa1100/serial_uart.rst similarity index 100% rename from Documentation/arm/sa1100/serial_uart.rst rename to Documentation/arch/arm/sa1100/serial_uart.rst diff --git a/Documentation/arm/samsung/bootloader-interface.rst b/Documentation/arch/arm/samsung/bootloader-interface.rst similarity index 100% rename from Documentation/arm/samsung/bootloader-interface.rst rename to Documentation/arch/arm/samsung/bootloader-interface.rst diff --git a/Documentation/arm/samsung/clksrc-change-registers.awk b/Documentation/arch/arm/samsung/clksrc-change-registers.awk similarity index 100% rename from Documentation/arm/samsung/clksrc-change-registers.awk rename to Documentation/arch/arm/samsung/clksrc-change-registers.awk diff --git a/Documentation/arm/samsung/gpio.rst b/Documentation/arch/arm/samsung/gpio.rst similarity index 100% rename from Documentation/arm/samsung/gpio.rst rename to Documentation/arch/arm/samsung/gpio.rst diff --git a/Documentation/arm/samsung/index.rst b/Documentation/arch/arm/samsung/index.rst similarity index 100% rename from Documentation/arm/samsung/index.rst rename to Documentation/arch/arm/samsung/index.rst diff --git a/Documentation/arm/samsung/overview.rst b/Documentation/arch/arm/samsung/overview.rst similarity index 100% rename from Documentation/arm/samsung/overview.rst rename to Documentation/arch/arm/samsung/overview.rst diff --git a/Documentation/arm/setup.rst b/Documentation/arch/arm/setup.rst similarity index 100% rename from Documentation/arm/setup.rst rename to Documentation/arch/arm/setup.rst diff --git a/Documentation/arm/spear/overview.rst b/Documentation/arch/arm/spear/overview.rst similarity index 100% rename from Documentation/arm/spear/overview.rst rename to Documentation/arch/arm/spear/overview.rst diff --git a/Documentation/arm/sti/overview.rst b/Documentation/arch/arm/sti/overview.rst similarity index 100% rename from Documentation/arm/sti/overview.rst rename to Documentation/arch/arm/sti/overview.rst diff --git a/Documentation/arm/sti/stih407-overview.rst b/Documentation/arch/arm/sti/stih407-overview.rst similarity index 100% rename from Documentation/arm/sti/stih407-overview.rst rename to Documentation/arch/arm/sti/stih407-overview.rst diff --git a/Documentation/arm/sti/stih418-overview.rst b/Documentation/arch/arm/sti/stih418-overview.rst similarity index 100% rename from Documentation/arm/sti/stih418-overview.rst rename to Documentation/arch/arm/sti/stih418-overview.rst diff --git a/Documentation/arm/stm32/overview.rst b/Documentation/arch/arm/stm32/overview.rst similarity index 100% rename from Documentation/arm/stm32/overview.rst rename to Documentation/arch/arm/stm32/overview.rst diff --git a/Documentation/arm/stm32/stm32-dma-mdma-chaining.rst b/Documentation/arch/arm/stm32/stm32-dma-mdma-chaining.rst similarity index 100% rename from Documentation/arm/stm32/stm32-dma-mdma-chaining.rst rename to Documentation/arch/arm/stm32/stm32-dma-mdma-chaining.rst diff --git a/Documentation/arm/stm32/stm32f429-overview.rst b/Documentation/arch/arm/stm32/stm32f429-overview.rst similarity index 100% rename from Documentation/arm/stm32/stm32f429-overview.rst rename to Documentation/arch/arm/stm32/stm32f429-overview.rst diff --git a/Documentation/arm/stm32/stm32f746-overview.rst b/Documentation/arch/arm/stm32/stm32f746-overview.rst similarity index 100% rename from Documentation/arm/stm32/stm32f746-overview.rst rename to Documentation/arch/arm/stm32/stm32f746-overview.rst diff --git a/Documentation/arm/stm32/stm32f769-overview.rst b/Documentation/arch/arm/stm32/stm32f769-overview.rst similarity index 100% rename from Documentation/arm/stm32/stm32f769-overview.rst rename to Documentation/arch/arm/stm32/stm32f769-overview.rst diff --git a/Documentation/arm/stm32/stm32h743-overview.rst b/Documentation/arch/arm/stm32/stm32h743-overview.rst similarity index 100% rename from Documentation/arm/stm32/stm32h743-overview.rst rename to Documentation/arch/arm/stm32/stm32h743-overview.rst diff --git a/Documentation/arm/stm32/stm32h750-overview.rst b/Documentation/arch/arm/stm32/stm32h750-overview.rst similarity index 100% rename from Documentation/arm/stm32/stm32h750-overview.rst rename to Documentation/arch/arm/stm32/stm32h750-overview.rst diff --git a/Documentation/arm/stm32/stm32mp13-overview.rst b/Documentation/arch/arm/stm32/stm32mp13-overview.rst similarity index 100% rename from Documentation/arm/stm32/stm32mp13-overview.rst rename to Documentation/arch/arm/stm32/stm32mp13-overview.rst diff --git a/Documentation/arm/stm32/stm32mp151-overview.rst b/Documentation/arch/arm/stm32/stm32mp151-overview.rst similarity index 100% rename from Documentation/arm/stm32/stm32mp151-overview.rst rename to Documentation/arch/arm/stm32/stm32mp151-overview.rst diff --git a/Documentation/arm/stm32/stm32mp157-overview.rst b/Documentation/arch/arm/stm32/stm32mp157-overview.rst similarity index 100% rename from Documentation/arm/stm32/stm32mp157-overview.rst rename to Documentation/arch/arm/stm32/stm32mp157-overview.rst diff --git a/Documentation/arm/sunxi.rst b/Documentation/arch/arm/sunxi.rst similarity index 100% rename from Documentation/arm/sunxi.rst rename to Documentation/arch/arm/sunxi.rst diff --git a/Documentation/arm/sunxi/clocks.rst b/Documentation/arch/arm/sunxi/clocks.rst similarity index 100% rename from Documentation/arm/sunxi/clocks.rst rename to Documentation/arch/arm/sunxi/clocks.rst diff --git a/Documentation/arm/swp_emulation.rst b/Documentation/arch/arm/swp_emulation.rst similarity index 100% rename from Documentation/arm/swp_emulation.rst rename to Documentation/arch/arm/swp_emulation.rst diff --git a/Documentation/arm/tcm.rst b/Documentation/arch/arm/tcm.rst similarity index 100% rename from Documentation/arm/tcm.rst rename to Documentation/arch/arm/tcm.rst diff --git a/Documentation/arm/uefi.rst b/Documentation/arch/arm/uefi.rst similarity index 100% rename from Documentation/arm/uefi.rst rename to Documentation/arch/arm/uefi.rst diff --git a/Documentation/arm/vfp/release-notes.rst b/Documentation/arch/arm/vfp/release-notes.rst similarity index 100% rename from Documentation/arm/vfp/release-notes.rst rename to Documentation/arch/arm/vfp/release-notes.rst diff --git a/Documentation/arm/vlocks.rst b/Documentation/arch/arm/vlocks.rst similarity index 100% rename from Documentation/arm/vlocks.rst rename to Documentation/arch/arm/vlocks.rst diff --git a/Documentation/arm64/acpi_object_usage.rst b/Documentation/arch/arm64/acpi_object_usage.rst similarity index 91% rename from Documentation/arm64/acpi_object_usage.rst rename to Documentation/arch/arm64/acpi_object_usage.rst index 484ef9676653e257f1ae3b4709ba4f1630ebd0de..1da22200fdf8fe6cc1a8e006e37c9d978525a545 100644 --- a/Documentation/arm64/acpi_object_usage.rst +++ b/Documentation/arch/arm64/acpi_object_usage.rst @@ -17,16 +17,37 @@ For ACPI on arm64, tables also fall into the following categories: - Recommended: BERT, EINJ, ERST, HEST, PCCT, SSDT - - Optional: BGRT, CPEP, CSRT, DBG2, DRTM, ECDT, FACS, FPDT, IBFT, - IORT, MCHI, MPST, MSCT, NFIT, PMTT, RASF, SBST, SLIT, SPMI, SRAT, - STAO, TCPA, TPM2, UEFI, XENV + - Optional: AGDI, BGRT, CEDT, CPEP, CSRT, DBG2, DRTM, ECDT, FACS, FPDT, + HMAT, IBFT, IORT, MCHI, MPAM, MPST, MSCT, NFIT, PMTT, PPTT, RASF, SBST, + SDEI, SLIT, SPMI, SRAT, STAO, TCPA, TPM2, UEFI, XENV - - Not supported: BOOT, DBGP, DMAR, ETDT, HPET, IVRS, LPIT, MSDM, OEMx, - PSDT, RSDT, SLIC, WAET, WDAT, WDRT, WPBT + - Not supported: AEST, APMT, BOOT, DBGP, DMAR, ETDT, HPET, IVRS, LPIT, + MSDM, OEMx, PDTT, PSDT, RAS2, RSDT, SLIC, WAET, WDAT, WDRT, WPBT ====== ======================================================================== Table Usage for ARMv8 Linux ====== ======================================================================== +AEST Signature Reserved (signature == "AEST") + + **Arm Error Source Table** + + This table informs the OS of any error nodes in the system that are + compliant with the Arm RAS architecture. + +AGDI Signature Reserved (signature == "AGDI") + + **Arm Generic diagnostic Dump and Reset Device Interface Table** + + This table describes a non-maskable event, that is used by the platform + firmware, to request the OS to generate a diagnostic dump and reset the device. + +APMT Signature Reserved (signature == "APMT") + + **Arm Performance Monitoring Table** + + This table describes the properties of PMU support implmented by + components in the system. + BERT Section 18.3 (signature == "BERT") **Boot Error Record Table** @@ -47,6 +68,13 @@ BGRT Section 5.2.22 (signature == "BGRT") Optional, not currently supported, with no real use-case for an ARM server. +CEDT Signature Reserved (signature == "CEDT") + + **CXL Early Discovery Table** + + This table allows the OS to discover any CXL Host Bridges and the Host + Bridge registers. + CPEP Section 5.2.18 (signature == "CPEP") **Corrected Platform Error Polling table** @@ -184,6 +212,15 @@ HEST Section 18.3.2 (signature == "HEST") Must be supplied if RAS support is provided by the platform. It is recommended this table be supplied. +HMAT Section 5.2.28 (signature == "HMAT") + + **Heterogeneous Memory Attribute Table** + + This table describes the memory attributes, such as memory side cache + attributes and bandwidth and latency details, related to Memory Proximity + Domains. The OS uses this information to optimize the system memory + configuration. + HPET Signature Reserved (signature == "HPET") **High Precision Event timer Table** @@ -241,6 +278,13 @@ MCHI Signature Reserved (signature == "MCHI") Optional, not currently supported. +MPAM Signature Reserved (signature == "MPAM") + + **Memory Partitioning And Monitoring table** + + This table allows the OS to discover the MPAM controls implemented by + the subsystems. + MPST Section 5.2.21 (signature == "MPST") **Memory Power State Table** @@ -281,18 +325,39 @@ PCCT Section 14.1 (signature == "PCCT) Recommend for use on arm64; use of PCC is recommended when using CPPC to control performance and power for platform processors. +PDTT Section 5.2.29 (signature == "PDTT") + + **Platform Debug Trigger Table** + + This table describes PCC channels used to gather debug logs of + non-architectural features. + + PMTT Section 5.2.21.12 (signature == "PMTT") **Platform Memory Topology Table** Optional, not currently supported. +PPTT Section 5.2.30 (signature == "PPTT") + + **Processor Properties Topology Table** + + This table provides the processor and cache topology. + PSDT Section 5.2.11.3 (signature == "PSDT") **Persistent System Description Table** Obsolete table, will not be supported. +RAS2 Section 5.2.21 (signature == "RAS2") + + **RAS Features 2 table** + + This table provides interfaces for the RAS capabilities implemented in + the platform. + RASF Section 5.2.20 (signature == "RASF") **RAS Feature table** @@ -318,6 +383,12 @@ SBST Section 5.2.14 (signature == "SBST") Optional, not currently supported. +SDEI Signature Reserved (signature == "SDEI") + + **Software Delegated Exception Interface table** + + This table advertises the presence of the SDEI interface. + SLIC Signature Reserved (signature == "SLIC") **Software LIcensing table** diff --git a/Documentation/arm64/amu.rst b/Documentation/arch/arm64/amu.rst similarity index 100% rename from Documentation/arm64/amu.rst rename to Documentation/arch/arm64/amu.rst diff --git a/Documentation/arm64/arm-acpi.rst b/Documentation/arch/arm64/arm-acpi.rst similarity index 82% rename from Documentation/arm64/arm-acpi.rst rename to Documentation/arch/arm64/arm-acpi.rst index 47ecb9930ddef06a343da2caa18545768ee21df0..94274a8d84cf0af3dc5f0bb2df68c7da4b1a4d9a 100644 --- a/Documentation/arm64/arm-acpi.rst +++ b/Documentation/arch/arm64/arm-acpi.rst @@ -1,40 +1,41 @@ -===================== -ACPI on ARMv8 Servers -===================== - -ACPI can be used for ARMv8 general purpose servers designed to follow -the ARM SBSA (Server Base System Architecture) [0] and SBBR (Server -Base Boot Requirements) [1] specifications. Please note that the SBBR -can be retrieved simply by visiting [1], but the SBSA is currently only -available to those with an ARM login due to ARM IP licensing concerns. - -The ARMv8 kernel implements the reduced hardware model of ACPI version +=================== +ACPI on Arm systems +=================== + +ACPI can be used for Armv8 and Armv9 systems designed to follow +the BSA (Arm Base System Architecture) [0] and BBR (Arm +Base Boot Requirements) [1] specifications. Both BSA and BBR are publicly +accessible documents. +Arm Servers, in addition to being BSA compliant, comply with a set +of rules defined in SBSA (Server Base System Architecture) [2]. + +The Arm kernel implements the reduced hardware model of ACPI version 5.1 or later. Links to the specification and all external documents it refers to are managed by the UEFI Forum. The specification is available at http://www.uefi.org/specifications and documents referenced by the specification can be found via http://www.uefi.org/acpi. -If an ARMv8 system does not meet the requirements of the SBSA and SBBR, +If an Arm system does not meet the requirements of the BSA and BBR, or cannot be described using the mechanisms defined in the required ACPI specifications, then ACPI may not be a good fit for the hardware. While the documents mentioned above set out the requirements for building -industry-standard ARMv8 servers, they also apply to more than one operating +industry-standard Arm systems, they also apply to more than one operating system. The purpose of this document is to describe the interaction between -ACPI and Linux only, on an ARMv8 system -- that is, what Linux expects of +ACPI and Linux only, on an Arm system -- that is, what Linux expects of ACPI and what ACPI can expect of Linux. -Why ACPI on ARM? +Why ACPI on Arm? ---------------- Before examining the details of the interface between ACPI and Linux, it is useful to understand why ACPI is being used. Several technologies already exist in Linux for describing non-enumerable hardware, after all. In this -section we summarize a blog post [2] from Grant Likely that outlines the -reasoning behind ACPI on ARMv8 servers. Actually, we snitch a good portion +section we summarize a blog post [3] from Grant Likely that outlines the +reasoning behind ACPI on Arm systems. Actually, we snitch a good portion of the summary text almost directly, to be honest. -The short form of the rationale for ACPI on ARM is: +The short form of the rationale for ACPI on Arm is: - ACPI’s byte code (AML) allows the platform to encode hardware behavior, while DT explicitly does not support this. For hardware vendors, being @@ -47,7 +48,7 @@ The short form of the rationale for ACPI on ARM is: - In the enterprise server environment, ACPI has established bindings (such as for RAS) which are currently used in production systems. DT does not. - Such bindings could be defined in DT at some point, but doing so means ARM + Such bindings could be defined in DT at some point, but doing so means Arm and x86 would end up using completely different code paths in both firmware and the kernel. @@ -108,7 +109,7 @@ recent version of the kernel. Relationship with Device Tree ----------------------------- -ACPI support in drivers and subsystems for ARMv8 should never be mutually +ACPI support in drivers and subsystems for Arm should never be mutually exclusive with DT support at compile time. At boot time the kernel will only use one description method depending on @@ -121,11 +122,11 @@ time). Booting using ACPI tables ------------------------- -The only defined method for passing ACPI tables to the kernel on ARMv8 +The only defined method for passing ACPI tables to the kernel on Arm is via the UEFI system configuration table. Just so it is explicit, this means that ACPI is only supported on platforms that boot via UEFI. -When an ARMv8 system boots, it can either have DT information, ACPI tables, +When an Arm system boots, it can either have DT information, ACPI tables, or in some very unusual cases, both. If no command line parameters are used, the kernel will try to use DT for device enumeration; if there is no DT present, the kernel will try to use ACPI tables, but only if they are present. @@ -169,7 +170,7 @@ hardware reduced mode must be set to zero. For the ACPI core to operate properly, and in turn provide the information the kernel needs to configure devices, it expects to find the following -tables (all section numbers refer to the ACPI 6.1 specification): +tables (all section numbers refer to the ACPI 6.5 specification): - RSDP (Root System Description Pointer), section 5.2.5 @@ -184,20 +185,76 @@ tables (all section numbers refer to the ACPI 6.1 specification): - GTDT (Generic Timer Description Table), section 5.2.24 + - PPTT (Processor Properties Topology Table), section 5.2.30 + + - DBG2 (DeBuG port table 2), section 5.2.6, specifically Table 5-6. + + - APMT (Arm Performance Monitoring unit Table), section 5.2.6, specifically Table 5-6. + + - AGDI (Arm Generic diagnostic Dump and Reset Device Interface Table), section 5.2.6, specifically Table 5-6. + - If PCI is supported, the MCFG (Memory mapped ConFiGuration - Table), section 5.2.6, specifically Table 5-31. + Table), section 5.2.6, specifically Table 5-6. - If booting without a console= kernel parameter is supported, the SPCR (Serial Port Console Redirection table), - section 5.2.6, specifically Table 5-31. + section 5.2.6, specifically Table 5-6. - If necessary to describe the I/O topology, SMMUs and GIC ITSs, the IORT (Input Output Remapping Table, section 5.2.6, specifically - Table 5-31). + Table 5-6). + + - If NUMA is supported, the following tables are required: + + - SRAT (System Resource Affinity Table), section 5.2.16 + + - SLIT (System Locality distance Information Table), section 5.2.17 + + - If NUMA is supported, and the system contains heterogeneous memory, + the HMAT (Heterogeneous Memory Attribute Table), section 5.2.28. + + - If the ACPI Platform Error Interfaces are required, the following + tables are conditionally required: + + - BERT (Boot Error Record Table, section 18.3.1) + + - EINJ (Error INJection table, section 18.6.1) + + - ERST (Error Record Serialization Table, section 18.5) + + - HEST (Hardware Error Source Table, section 18.3.2) + + - SDEI (Software Delegated Exception Interface table, section 5.2.6, + specifically Table 5-6) + + - AEST (Arm Error Source Table, section 5.2.6, + specifically Table 5-6) + + - RAS2 (ACPI RAS2 feature table, section 5.2.21) + + - If the system contains controllers using PCC channel, the + PCCT (Platform Communications Channel Table), section 14.1 + + - If the system contains a controller to capture board-level system state, + and communicates with the host via PCC, the PDTT (Platform Debug Trigger + Table), section 5.2.29. + + - If NVDIMM is supported, the NFIT (NVDIMM Firmware Interface Table), section 5.2.26 + + - If video framebuffer is present, the BGRT (Boot Graphics Resource Table), section 5.2.23 + + - If IPMI is implemented, the SPMI (Server Platform Management Interface), + section 5.2.6, specifically Table 5-6. + + - If the system contains a CXL Host Bridge, the CEDT (CXL Early Discovery + Table), section 5.2.6, specifically Table 5-6. + + - If the system supports MPAM, the MPAM (Memory Partitioning And Monitoring table), section 5.2.6, + specifically Table 5-6. + + - If the system lacks persistent storage, the IBFT (ISCSI Boot Firmware + Table), section 5.2.6, specifically Table 5-6. - - If NUMA is supported, the SRAT (System Resource Affinity Table) - and SLIT (System Locality distance Information Table), sections - 5.2.16 and 5.2.17, respectively. If the above tables are not all present, the kernel may or may not be able to boot properly since it may not be able to configure all of the @@ -269,16 +326,14 @@ Drivers should look for device properties in the _DSD object ONLY; the _DSD object is described in the ACPI specification section 6.2.5, but this only describes how to define the structure of an object returned via _DSD, and how specific data structures are defined by specific UUIDs. Linux should -only use the _DSD Device Properties UUID [5]: +only use the _DSD Device Properties UUID [4]: - UUID: daffd814-6eba-4d8c-8a91-bc9bbf4aa301 - - https://www.uefi.org/sites/default/files/resources/_DSD-device-properties-UUID.pdf - -The UEFI Forum provides a mechanism for registering device properties [4] -so that they may be used across all operating systems supporting ACPI. -Device properties that have not been registered with the UEFI Forum should -not be used. +Common device properties can be registered by creating a pull request to [4] so +that they may be used across all operating systems supporting ACPI. +Device properties that have not been registered with the UEFI Forum can be used +but not as "uefi-" common properties. Before creating new device properties, check to be sure that they have not been defined before and either registered in the Linux kernel documentation @@ -306,7 +361,7 @@ process. Once registration and review have been completed, the kernel provides an interface for looking up device properties in a manner independent of -whether DT or ACPI is being used. This API should be used [6]; it can +whether DT or ACPI is being used. This API should be used [5]; it can eliminate some duplication of code paths in driver probing functions and discourage divergence between DT bindings and ACPI device properties. @@ -448,15 +503,15 @@ ASWG ---- The ACPI specification changes regularly. During the year 2014, for instance, version 5.1 was released and version 6.0 substantially completed, with most of -the changes being driven by ARM-specific requirements. Proposed changes are +the changes being driven by Arm-specific requirements. Proposed changes are presented and discussed in the ASWG (ACPI Specification Working Group) which is a part of the UEFI Forum. The current version of the ACPI specification -is 6.1 release in January 2016. +is 6.5 release in August 2022. Participation in this group is open to all UEFI members. Please see http://www.uefi.org/workinggroup for details on group membership. -It is the intent of the ARMv8 ACPI kernel code to follow the ACPI specification +It is the intent of the Arm ACPI kernel code to follow the ACPI specification as closely as possible, and to only implement functionality that complies with the released standards from UEFI ASWG. As a practical matter, there will be vendors that provide bad ACPI tables or violate the standards in some way. @@ -470,12 +525,12 @@ likely be willing to assist in submitting ECRs. Linux Code ---------- -Individual items specific to Linux on ARM, contained in the Linux +Individual items specific to Linux on Arm, contained in the Linux source code, are in the list that follows: ACPI_OS_NAME This macro defines the string to be returned when - an ACPI method invokes the _OS method. On ARM64 + an ACPI method invokes the _OS method. On Arm systems, this macro will be "Linux" by default. The command line parameter acpi_os= can be used to set it to some other value. The @@ -485,36 +540,28 @@ ACPI_OS_NAME ACPI Objects ------------ Detailed expectations for ACPI tables and object are listed in the file -Documentation/arm64/acpi_object_usage.rst. +Documentation/arch/arm64/acpi_object_usage.rst. References ---------- -[0] http://silver.arm.com - document ARM-DEN-0029, or newer: - "Server Base System Architecture", version 2.3, dated 27 Mar 2014 +[0] https://developer.arm.com/documentation/den0094/latest + document Arm-DEN-0094: "Arm Base System Architecture", version 1.0C, dated 6 Oct 2022 + +[1] https://developer.arm.com/documentation/den0044/latest + Document Arm-DEN-0044: "Arm Base Boot Requirements", version 2.0G, dated 15 Apr 2022 -[1] http://infocenter.arm.com/help/topic/com.arm.doc.den0044a/Server_Base_Boot_Requirements.pdf - Document ARM-DEN-0044A, or newer: "Server Base Boot Requirements, System - Software on ARM Platforms", dated 16 Aug 2014 +[2] https://developer.arm.com/documentation/den0029/latest + Document Arm-DEN-0029: "Arm Server Base System Architecture", version 7.1, dated 06 Oct 2022 -[2] http://www.secretlab.ca/archives/151, +[3] http://www.secretlab.ca/archives/151, 10 Jan 2015, Copyright (c) 2015, Linaro Ltd., written by Grant Likely. -[3] AMD ACPI for Seattle platform documentation - http://amd-dev.wpengine.netdna-cdn.com/wordpress/media/2012/10/Seattle_ACPI_Guide.pdf - - -[4] http://www.uefi.org/acpi - please see the link for the "ACPI _DSD Device - Property Registry Instructions" - -[5] http://www.uefi.org/acpi - please see the link for the "_DSD (Device - Specific Data) Implementation Guide" +[4] _DSD (Device Specific Data) Implementation Guide + https://github.com/UEFI/DSD-Guide/blob/main/dsd-guide.pdf -[6] Kernel code for the unified device +[5] Kernel code for the unified device property interface can be found in include/linux/property.h and drivers/base/property.c. diff --git a/Documentation/arm64/asymmetric-32bit.rst b/Documentation/arch/arm64/asymmetric-32bit.rst similarity index 100% rename from Documentation/arm64/asymmetric-32bit.rst rename to Documentation/arch/arm64/asymmetric-32bit.rst diff --git a/Documentation/arm64/booting.rst b/Documentation/arch/arm64/booting.rst similarity index 94% rename from Documentation/arm64/booting.rst rename to Documentation/arch/arm64/booting.rst index ffeccdd6bdac94420d2839c6f1966faa6d253fd3..b57776a68f156d0be28a73c6036073494f3961e0 100644 --- a/Documentation/arm64/booting.rst +++ b/Documentation/arch/arm64/booting.rst @@ -379,6 +379,38 @@ Before jumping into the kernel, the following conditions must be met: - SMCR_EL2.EZT0 (bit 30) must be initialised to 0b1. + For CPUs with Memory Copy and Memory Set instructions (FEAT_MOPS): + + - If the kernel is entered at EL1 and EL2 is present: + + - HCRX_EL2.MSCEn (bit 11) must be initialised to 0b1. + + For CPUs with the Extended Translation Control Register feature (FEAT_TCR2): + + - If EL3 is present: + + - SCR_EL3.TCR2En (bit 43) must be initialised to 0b1. + + - If the kernel is entered at EL1 and EL2 is present: + + - HCRX_EL2.TCR2En (bit 14) must be initialised to 0b1. + + For CPUs with the Stage 1 Permission Indirection Extension feature (FEAT_S1PIE): + + - If EL3 is present: + + - SCR_EL3.PIEn (bit 45) must be initialised to 0b1. + + - If the kernel is entered at EL1 and EL2 is present: + + - HFGRTR_EL2.nPIR_EL1 (bit 58) must be initialised to 0b1. + + - HFGWTR_EL2.nPIR_EL1 (bit 58) must be initialised to 0b1. + + - HFGRTR_EL2.nPIRE0_EL1 (bit 57) must be initialised to 0b1. + + - HFGRWR_EL2.nPIRE0_EL1 (bit 57) must be initialised to 0b1. + The requirements described above for CPU mode, caches, MMUs, architected timers, coherency and system registers apply to all CPUs. All CPUs must enter the kernel in the same exception level. Where the values documented diff --git a/Documentation/arm64/cpu-feature-registers.rst b/Documentation/arch/arm64/cpu-feature-registers.rst similarity index 99% rename from Documentation/arm64/cpu-feature-registers.rst rename to Documentation/arch/arm64/cpu-feature-registers.rst index c7adc7897df606a6ed07114e42e7480bddf70f91..4e4625f2455fe92552365fc1c088d497bdef5a55 100644 --- a/Documentation/arm64/cpu-feature-registers.rst +++ b/Documentation/arch/arm64/cpu-feature-registers.rst @@ -288,6 +288,8 @@ infrastructure: +------------------------------+---------+---------+ | Name | bits | visible | +------------------------------+---------+---------+ + | MOPS | [19-16] | y | + +------------------------------+---------+---------+ | RPRES | [7-4] | y | +------------------------------+---------+---------+ | WFXT | [3-0] | y | diff --git a/Documentation/arm64/elf_hwcaps.rst b/Documentation/arch/arm64/elf_hwcaps.rst similarity index 95% rename from Documentation/arm64/elf_hwcaps.rst rename to Documentation/arch/arm64/elf_hwcaps.rst index 83e57e4d38e2a49d5bf63748c8b6e6dcfe10e8c5..8c8addb4194c93446936e60af3b9e7c744e75575 100644 --- a/Documentation/arm64/elf_hwcaps.rst +++ b/Documentation/arch/arm64/elf_hwcaps.rst @@ -102,7 +102,7 @@ HWCAP_ASIMDHP HWCAP_CPUID EL0 access to certain ID registers is available, to the extent - described by Documentation/arm64/cpu-feature-registers.rst. + described by Documentation/arch/arm64/cpu-feature-registers.rst. These ID registers may imply the availability of features. @@ -163,12 +163,12 @@ HWCAP_SB HWCAP_PACA Functionality implied by ID_AA64ISAR1_EL1.APA == 0b0001 or ID_AA64ISAR1_EL1.API == 0b0001, as described by - Documentation/arm64/pointer-authentication.rst. + Documentation/arch/arm64/pointer-authentication.rst. HWCAP_PACG Functionality implied by ID_AA64ISAR1_EL1.GPA == 0b0001 or ID_AA64ISAR1_EL1.GPI == 0b0001, as described by - Documentation/arm64/pointer-authentication.rst. + Documentation/arch/arm64/pointer-authentication.rst. HWCAP2_DCPODP Functionality implied by ID_AA64ISAR1_EL1.DPB == 0b0010. @@ -226,7 +226,7 @@ HWCAP2_BTI HWCAP2_MTE Functionality implied by ID_AA64PFR1_EL1.MTE == 0b0010, as described - by Documentation/arm64/memory-tagging-extension.rst. + by Documentation/arch/arm64/memory-tagging-extension.rst. HWCAP2_ECV Functionality implied by ID_AA64MMFR0_EL1.ECV == 0b0001. @@ -239,11 +239,11 @@ HWCAP2_RPRES HWCAP2_MTE3 Functionality implied by ID_AA64PFR1_EL1.MTE == 0b0011, as described - by Documentation/arm64/memory-tagging-extension.rst. + by Documentation/arch/arm64/memory-tagging-extension.rst. HWCAP2_SME Functionality implied by ID_AA64PFR1_EL1.SME == 0b0001, as described - by Documentation/arm64/sme.rst. + by Documentation/arch/arm64/sme.rst. HWCAP2_SME_I16I64 Functionality implied by ID_AA64SMFR0_EL1.I16I64 == 0b1111. @@ -302,6 +302,9 @@ HWCAP2_SMEB16B16 HWCAP2_SMEF16F16 Functionality implied by ID_AA64SMFR0_EL1.F16F16 == 0b1 +HWCAP2_MOPS + Functionality implied by ID_AA64ISAR2_EL1.MOPS == 0b0001. + 4. Unused AT_HWCAP bits ----------------------- diff --git a/Documentation/arm64/features.rst b/Documentation/arch/arm64/features.rst similarity index 100% rename from Documentation/arm64/features.rst rename to Documentation/arch/arm64/features.rst diff --git a/Documentation/arm64/hugetlbpage.rst b/Documentation/arch/arm64/hugetlbpage.rst similarity index 100% rename from Documentation/arm64/hugetlbpage.rst rename to Documentation/arch/arm64/hugetlbpage.rst diff --git a/Documentation/arm64/index.rst b/Documentation/arch/arm64/index.rst similarity index 96% rename from Documentation/arm64/index.rst rename to Documentation/arch/arm64/index.rst index ae21f811883022a4990a4bcd2a0f0226d5410a60..d08e924204bf15a6528e4b20ff046e74e11c04aa 100644 --- a/Documentation/arm64/index.rst +++ b/Documentation/arch/arm64/index.rst @@ -15,11 +15,13 @@ ARM64 Architecture cpu-feature-registers elf_hwcaps hugetlbpage + kdump legacy_instructions memory memory-tagging-extension perf pointer-authentication + ptdump silicon-errata sme sve diff --git a/Documentation/arm64/kasan-offsets.sh b/Documentation/arch/arm64/kasan-offsets.sh similarity index 100% rename from Documentation/arm64/kasan-offsets.sh rename to Documentation/arch/arm64/kasan-offsets.sh diff --git a/Documentation/arch/arm64/kdump.rst b/Documentation/arch/arm64/kdump.rst new file mode 100644 index 0000000000000000000000000000000000000000..56a89f45df28c4837465ec47a6b196977174884d --- /dev/null +++ b/Documentation/arch/arm64/kdump.rst @@ -0,0 +1,92 @@ +======================================= +crashkernel memory reservation on arm64 +======================================= + +Author: Baoquan He + +Kdump mechanism is used to capture a corrupted kernel vmcore so that +it can be subsequently analyzed. In order to do this, a preliminarily +reserved memory is needed to pre-load the kdump kernel and boot such +kernel if corruption happens. + +That reserved memory for kdump is adapted to be able to minimally +accommodate the kdump kernel and the user space programs needed for the +vmcore collection. + +Kernel parameter +================ + +Through the kernel parameters below, memory can be reserved accordingly +during the early stage of the first kernel booting so that a continuous +large chunk of memomy can be found. The low memory reservation needs to +be considered if the crashkernel is reserved from the high memory area. + +- crashkernel=size@offset +- crashkernel=size +- crashkernel=size,high crashkernel=size,low + +Low memory and high memory +========================== + +For kdump reservations, low memory is the memory area under a specific +limit, usually decided by the accessible address bits of the DMA-capable +devices needed by the kdump kernel to run. Those devices not related to +vmcore dumping can be ignored. On arm64, the low memory upper bound is +not fixed: it is 1G on the RPi4 platform but 4G on most other systems. +On special kernels built with CONFIG_ZONE_(DMA|DMA32) disabled, the +whole system RAM is low memory. Outside of the low memory described +above, the rest of system RAM is considered high memory. + +Implementation +============== + +1) crashkernel=size@offset +-------------------------- + +The crashkernel memory must be reserved at the user-specified region or +fail if already occupied. + + +2) crashkernel=size +------------------- + +The crashkernel memory region will be reserved in any available position +according to the search order: + +Firstly, the kernel searches the low memory area for an available region +with the specified size. + +If searching for low memory fails, the kernel falls back to searching +the high memory area for an available region of the specified size. If +the reservation in high memory succeeds, a default size reservation in +the low memory will be done. Currently the default size is 128M, +sufficient for the low memory needs of the kdump kernel. + +Note: crashkernel=size is the recommended option for crashkernel kernel +reservations. The user would not need to know the system memory layout +for a specific platform. + +3) crashkernel=size,high crashkernel=size,low +--------------------------------------------- + +crashkernel=size,(high|low) are an important supplement to +crashkernel=size. They allows the user to specify how much memory needs +to be allocated from the high memory and low memory respectively. On +many systems the low memory is precious and crashkernel reservations +from this area should be kept to a minimum. + +To reserve memory for crashkernel=size,high, searching is first +attempted from the high memory region. If the reservation succeeds, the +low memory reservation will be done subsequently. + +If reservation from the high memory failed, the kernel falls back to +searching the low memory with the specified size in crashkernel=,high. +If it succeeds, no further reservation for low memory is needed. + +Notes: + +- If crashkernel=,low is not specified, the default low memory + reservation will be done automatically. + +- if crashkernel=0,low is specified, it means that the low memory + reservation is omitted intentionally. diff --git a/Documentation/arm64/legacy_instructions.rst b/Documentation/arch/arm64/legacy_instructions.rst similarity index 100% rename from Documentation/arm64/legacy_instructions.rst rename to Documentation/arch/arm64/legacy_instructions.rst diff --git a/Documentation/arm64/memory-tagging-extension.rst b/Documentation/arch/arm64/memory-tagging-extension.rst similarity index 99% rename from Documentation/arm64/memory-tagging-extension.rst rename to Documentation/arch/arm64/memory-tagging-extension.rst index dbae47bba25ec7f5b84b11bc62f7ff6ef2122d75..679725030731d00682c6cf74ffbfb9827efc561d 100644 --- a/Documentation/arm64/memory-tagging-extension.rst +++ b/Documentation/arch/arm64/memory-tagging-extension.rst @@ -221,7 +221,7 @@ programs should not retry in case of a non-zero system call return. ``NT_ARM_TAGGED_ADDR_CTRL`` allow ``ptrace()`` access to the tagged address ABI control and MTE configuration of a process as per the ``prctl()`` options described in -Documentation/arm64/tagged-address-abi.rst and above. The corresponding +Documentation/arch/arm64/tagged-address-abi.rst and above. The corresponding ``regset`` is 1 element of 8 bytes (``sizeof(long))``). Core dump support diff --git a/Documentation/arm64/memory.rst b/Documentation/arch/arm64/memory.rst similarity index 97% rename from Documentation/arm64/memory.rst rename to Documentation/arch/arm64/memory.rst index 2a641ba7be3b717aa2f9343fe94e05f5e6700e79..55a55f30eed8a6ce3ab651819ffea2ac63d41e89 100644 --- a/Documentation/arm64/memory.rst +++ b/Documentation/arch/arm64/memory.rst @@ -33,8 +33,8 @@ AArch64 Linux memory layout with 4KB pages + 4 levels (48-bit):: 0000000000000000 0000ffffffffffff 256TB user ffff000000000000 ffff7fffffffffff 128TB kernel logical memory map [ffff600000000000 ffff7fffffffffff] 32TB [kasan shadow region] - ffff800000000000 ffff800007ffffff 128MB modules - ffff800008000000 fffffbffefffffff 124TB vmalloc + ffff800000000000 ffff80007fffffff 2GB modules + ffff800080000000 fffffbffefffffff 124TB vmalloc fffffbfff0000000 fffffbfffdffffff 224MB fixed mappings (top down) fffffbfffe000000 fffffbfffe7fffff 8MB [guard region] fffffbfffe800000 fffffbffff7fffff 16MB PCI I/O space @@ -50,8 +50,8 @@ AArch64 Linux memory layout with 64KB pages + 3 levels (52-bit with HW support): 0000000000000000 000fffffffffffff 4PB user fff0000000000000 ffff7fffffffffff ~4PB kernel logical memory map [fffd800000000000 ffff7fffffffffff] 512TB [kasan shadow region] - ffff800000000000 ffff800007ffffff 128MB modules - ffff800008000000 fffffbffefffffff 124TB vmalloc + ffff800000000000 ffff80007fffffff 2GB modules + ffff800080000000 fffffbffefffffff 124TB vmalloc fffffbfff0000000 fffffbfffdffffff 224MB fixed mappings (top down) fffffbfffe000000 fffffbfffe7fffff 8MB [guard region] fffffbfffe800000 fffffbffff7fffff 16MB PCI I/O space diff --git a/Documentation/arm64/perf.rst b/Documentation/arch/arm64/perf.rst similarity index 100% rename from Documentation/arm64/perf.rst rename to Documentation/arch/arm64/perf.rst diff --git a/Documentation/arm64/pointer-authentication.rst b/Documentation/arch/arm64/pointer-authentication.rst similarity index 100% rename from Documentation/arm64/pointer-authentication.rst rename to Documentation/arch/arm64/pointer-authentication.rst diff --git a/Documentation/arch/arm64/ptdump.rst b/Documentation/arch/arm64/ptdump.rst new file mode 100644 index 0000000000000000000000000000000000000000..5dcfc5d7cddfb96d33eafd3e0b07f3c9a029fb63 --- /dev/null +++ b/Documentation/arch/arm64/ptdump.rst @@ -0,0 +1,96 @@ +====================== +Kernel page table dump +====================== + +ptdump is a debugfs interface that provides a detailed dump of the +kernel page tables. It offers a comprehensive overview of the kernel +virtual memory layout as well as the attributes associated with the +various regions in a human-readable format. It is useful to dump the +kernel page tables to verify permissions and memory types. Examining the +page table entries and permissions helps identify potential security +vulnerabilities such as mappings with overly permissive access rights or +improper memory protections. + +Memory hotplug allows dynamic expansion or contraction of available +memory without requiring a system reboot. To maintain the consistency +and integrity of the memory management data structures, arm64 makes use +of the ``mem_hotplug_lock`` semaphore in write mode. Additionally, in +read mode, ``mem_hotplug_lock`` supports an efficient implementation of +``get_online_mems()`` and ``put_online_mems()``. These protect the +offlining of memory being accessed by the ptdump code. + +In order to dump the kernel page tables, enable the following +configurations and mount debugfs:: + + CONFIG_GENERIC_PTDUMP=y + CONFIG_PTDUMP_CORE=y + CONFIG_PTDUMP_DEBUGFS=y + + mount -t debugfs nodev /sys/kernel/debug + cat /sys/kernel/debug/kernel_page_tables + +On analysing the output of ``cat /sys/kernel/debug/kernel_page_tables`` +one can derive information about the virtual address range of the entry, +followed by size of the memory region covered by this entry, the +hierarchical structure of the page tables and finally the attributes +associated with each page. The page attributes provide information about +access permissions, execution capability, type of mapping such as leaf +level PTE or block level PGD, PMD and PUD, and access status of a page +within the kernel memory. Assessing these attributes can assist in +understanding the memory layout, access patterns and security +characteristics of the kernel pages. + +Kernel virtual memory layout example:: + + start address end address size attributes + +---------------------------------------------------------------------------------------+ + | ---[ Linear Mapping start ]---------------------------------------------------------- | + | .................. | + | 0xfff0000000000000-0xfff0000000210000 2112K PTE RW NX SHD AF UXN MEM/NORMAL-TAGGED | + | 0xfff0000000210000-0xfff0000001c00000 26560K PTE ro NX SHD AF UXN MEM/NORMAL | + | .................. | + | ---[ Linear Mapping end ]------------------------------------------------------------ | + +---------------------------------------------------------------------------------------+ + | ---[ Modules start ]----------------------------------------------------------------- | + | .................. | + | 0xffff800000000000-0xffff800008000000 128M PTE | + | .................. | + | ---[ Modules end ]------------------------------------------------------------------- | + +---------------------------------------------------------------------------------------+ + | ---[ vmalloc() area ]---------------------------------------------------------------- | + | .................. | + | 0xffff800008010000-0xffff800008200000 1984K PTE ro x SHD AF UXN MEM/NORMAL | + | 0xffff800008200000-0xffff800008e00000 12M PTE ro x SHD AF CON UXN MEM/NORMAL | + | .................. | + | ---[ vmalloc() end ]----------------------------------------------------------------- | + +---------------------------------------------------------------------------------------+ + | ---[ Fixmap start ]------------------------------------------------------------------ | + | .................. | + | 0xfffffbfffdb80000-0xfffffbfffdb90000 64K PTE ro x SHD AF UXN MEM/NORMAL | + | 0xfffffbfffdb90000-0xfffffbfffdba0000 64K PTE ro NX SHD AF UXN MEM/NORMAL | + | .................. | + | ---[ Fixmap end ]-------------------------------------------------------------------- | + +---------------------------------------------------------------------------------------+ + | ---[ PCI I/O start ]----------------------------------------------------------------- | + | .................. | + | 0xfffffbfffe800000-0xfffffbffff800000 16M PTE | + | .................. | + | ---[ PCI I/O end ]------------------------------------------------------------------- | + +---------------------------------------------------------------------------------------+ + | ---[ vmemmap start ]----------------------------------------------------------------- | + | .................. | + | 0xfffffc0002000000-0xfffffc0002200000 2M PTE RW NX SHD AF UXN MEM/NORMAL | + | 0xfffffc0002200000-0xfffffc0020000000 478M PTE | + | .................. | + | ---[ vmemmap end ]------------------------------------------------------------------- | + +---------------------------------------------------------------------------------------+ + +``cat /sys/kernel/debug/kernel_page_tables`` output:: + + 0xfff0000001c00000-0xfff0000080000000 2020M PTE RW NX SHD AF UXN MEM/NORMAL-TAGGED + 0xfff0000080000000-0xfff0000800000000 30G PMD + 0xfff0000800000000-0xfff0000800700000 7M PTE RW NX SHD AF UXN MEM/NORMAL-TAGGED + 0xfff0000800700000-0xfff0000800710000 64K PTE ro NX SHD AF UXN MEM/NORMAL-TAGGED + 0xfff0000800710000-0xfff0000880000000 2089920K PTE RW NX SHD AF UXN MEM/NORMAL-TAGGED + 0xfff0000880000000-0xfff0040000000000 4062G PMD + 0xfff0040000000000-0xffff800000000000 3964T PGD diff --git a/Documentation/arm64/silicon-errata.rst b/Documentation/arch/arm64/silicon-errata.rst similarity index 95% rename from Documentation/arm64/silicon-errata.rst rename to Documentation/arch/arm64/silicon-errata.rst index 9e311bc43e05eaac3c36ffb50edb6750a14a6bbe..496cdca5cb99002837a87b83834bce0d9fc0d60a 100644 --- a/Documentation/arm64/silicon-errata.rst +++ b/Documentation/arch/arm64/silicon-errata.rst @@ -52,6 +52,9 @@ stable kernels. | Allwinner | A64/R18 | UNKNOWN1 | SUN50I_ERRATUM_UNKNOWN1 | +----------------+-----------------+-----------------+-----------------------------+ +----------------+-----------------+-----------------+-----------------------------+ +| Ampere | AmpereOne | AC03_CPU_38 | AMPERE_ERRATUM_AC03_CPU_38 | ++----------------+-----------------+-----------------+-----------------------------+ ++----------------+-----------------+-----------------+-----------------------------+ | ARM | Cortex-A510 | #2457168 | ARM64_ERRATUM_2457168 | +----------------+-----------------+-----------------+-----------------------------+ | ARM | Cortex-A510 | #2064142 | ARM64_ERRATUM_2064142 | @@ -140,6 +143,10 @@ stable kernels. +----------------+-----------------+-----------------+-----------------------------+ | ARM | MMU-500 | #841119,826419 | N/A | +----------------+-----------------+-----------------+-----------------------------+ +| ARM | MMU-600 | #1076982,1209401| N/A | ++----------------+-----------------+-----------------+-----------------------------+ +| ARM | MMU-700 | #2268618,2812531| N/A | ++----------------+-----------------+-----------------+-----------------------------+ +----------------+-----------------+-----------------+-----------------------------+ | Broadcom | Brahma-B53 | N/A | ARM64_ERRATUM_845719 | +----------------+-----------------+-----------------+-----------------------------+ @@ -214,3 +221,7 @@ stable kernels. +----------------+-----------------+-----------------+-----------------------------+ | Fujitsu | A64FX | E#010001 | FUJITSU_ERRATUM_010001 | +----------------+-----------------+-----------------+-----------------------------+ + ++----------------+-----------------+-----------------+-----------------------------+ +| ASR | ASR8601 | #8601001 | N/A | ++----------------+-----------------+-----------------+-----------------------------+ diff --git a/Documentation/arm64/sme.rst b/Documentation/arch/arm64/sme.rst similarity index 99% rename from Documentation/arm64/sme.rst rename to Documentation/arch/arm64/sme.rst index 1c43ea12eb4fdfb1682aa1d02bdae56e5931c410..ba529a1dc6065e01575277b27bb7e1d1674fd2bf 100644 --- a/Documentation/arm64/sme.rst +++ b/Documentation/arch/arm64/sme.rst @@ -465,4 +465,4 @@ References [2] arch/arm64/include/uapi/asm/ptrace.h AArch64 Linux ptrace ABI definitions -[3] Documentation/arm64/cpu-feature-registers.rst +[3] Documentation/arch/arm64/cpu-feature-registers.rst diff --git a/Documentation/arm64/sve.rst b/Documentation/arch/arm64/sve.rst similarity index 99% rename from Documentation/arm64/sve.rst rename to Documentation/arch/arm64/sve.rst index 1b90a30382ac04e46b75061dd3ea8a4432eb76a5..0d9a426e9f858d92a934840a015dd87b237af3ab 100644 --- a/Documentation/arm64/sve.rst +++ b/Documentation/arch/arm64/sve.rst @@ -606,7 +606,7 @@ References [2] arch/arm64/include/uapi/asm/ptrace.h AArch64 Linux ptrace ABI definitions -[3] Documentation/arm64/cpu-feature-registers.rst +[3] Documentation/arch/arm64/cpu-feature-registers.rst [4] ARM IHI0055C http://infocenter.arm.com/help/topic/com.arm.doc.ihi0055c/IHI0055C_beta_aapcs64.pdf diff --git a/Documentation/arm64/tagged-address-abi.rst b/Documentation/arch/arm64/tagged-address-abi.rst similarity index 99% rename from Documentation/arm64/tagged-address-abi.rst rename to Documentation/arch/arm64/tagged-address-abi.rst index 540a1d4fc6c9efd3c9f5e75609c425bb63d879fe..fe24a3f158c57637982e61d89d670fbe255b5bef 100644 --- a/Documentation/arm64/tagged-address-abi.rst +++ b/Documentation/arch/arm64/tagged-address-abi.rst @@ -107,7 +107,7 @@ following behaviours are guaranteed: A definition of the meaning of tagged pointers on AArch64 can be found -in Documentation/arm64/tagged-pointers.rst. +in Documentation/arch/arm64/tagged-pointers.rst. 3. AArch64 Tagged Address ABI Exceptions ----------------------------------------- diff --git a/Documentation/arm64/tagged-pointers.rst b/Documentation/arch/arm64/tagged-pointers.rst similarity index 98% rename from Documentation/arm64/tagged-pointers.rst rename to Documentation/arch/arm64/tagged-pointers.rst index 19d284b7038487a5af95807362c4c3799781c58f..81b6c2a770dd6dc7a71c9af2e557c9f8b6281bb8 100644 --- a/Documentation/arm64/tagged-pointers.rst +++ b/Documentation/arch/arm64/tagged-pointers.rst @@ -22,7 +22,7 @@ Passing tagged addresses to the kernel All interpretation of userspace memory addresses by the kernel assumes an address tag of 0x00, unless the application enables the AArch64 Tagged Address ABI explicitly -(Documentation/arm64/tagged-address-abi.rst). +(Documentation/arch/arm64/tagged-address-abi.rst). This includes, but is not limited to, addresses found in: diff --git a/Documentation/arch/index.rst b/Documentation/arch/index.rst index 80ee310165843304adb1bdae0ff5bbbee124ba04..8458b88e9b79ebffb7a3ff2283021156ab2ec363 100644 --- a/Documentation/arch/index.rst +++ b/Documentation/arch/index.rst @@ -10,8 +10,8 @@ implementation. :maxdepth: 2 arc/index - ../arm/index - ../arm64/index + arm/index + arm64/index ia64/index ../loongarch/index m68k/index diff --git a/Documentation/arch/x86/resctrl.rst b/Documentation/arch/x86/resctrl.rst index 387ccbcb558fbdc4d8a597163fbc5573691571ba..cb05d90111b4f5d8380f9a858d5b6d7c4ffb698c 100644 --- a/Documentation/arch/x86/resctrl.rst +++ b/Documentation/arch/x86/resctrl.rst @@ -287,6 +287,13 @@ Removing a directory will move all tasks and cpus owned by the group it represents to the parent. Removing one of the created CTRL_MON groups will automatically remove all MON groups below it. +Moving MON group directories to a new parent CTRL_MON group is supported +for the purpose of changing the resource allocations of a MON group +without impacting its monitoring data or assigned tasks. This operation +is not allowed for MON groups which monitor CPUs. No other move +operation is currently allowed other than simply renaming a CTRL_MON or +MON group. + All groups contain the following files: "tasks": diff --git a/Documentation/bpf/bpf_iterators.rst b/Documentation/bpf/bpf_iterators.rst index 6d7770793fab70ab5c825fd6c8d2fb00a1efe5c6..07433915aa414d6369d2a189170fd6cf3d437b51 100644 --- a/Documentation/bpf/bpf_iterators.rst +++ b/Documentation/bpf/bpf_iterators.rst @@ -238,11 +238,8 @@ The following is the breakdown for each field in struct ``bpf_iter_reg``. that the kernel function cond_resched() is called to avoid other kernel subsystem (e.g., rcu) misbehaving. * - seq_info - - Specifies certain action requests in the kernel BPF iterator - infrastructure. Currently, only BPF_ITER_RESCHED is supported. This means - that the kernel function cond_resched() is called to avoid other kernel - subsystem (e.g., rcu) misbehaving. - + - Specifies the set of seq operations for the BPF iterator and helpers to + initialize/free the private data for the corresponding ``seq_file``. `Click here `_ diff --git a/Documentation/bpf/cpumasks.rst b/Documentation/bpf/cpumasks.rst index 41efd8874eebc71423511c845e9f3def4c01e8e1..3139c7c02e795fbc1b7f4fa3952f50e58046ed29 100644 --- a/Documentation/bpf/cpumasks.rst +++ b/Documentation/bpf/cpumasks.rst @@ -351,14 +351,15 @@ In addition to the above kfuncs, there is also a set of read-only kfuncs that can be used to query the contents of cpumasks. .. kernel-doc:: kernel/bpf/cpumask.c - :identifiers: bpf_cpumask_first bpf_cpumask_first_zero bpf_cpumask_test_cpu + :identifiers: bpf_cpumask_first bpf_cpumask_first_zero bpf_cpumask_first_and + bpf_cpumask_test_cpu .. kernel-doc:: kernel/bpf/cpumask.c :identifiers: bpf_cpumask_equal bpf_cpumask_intersects bpf_cpumask_subset bpf_cpumask_empty bpf_cpumask_full .. kernel-doc:: kernel/bpf/cpumask.c - :identifiers: bpf_cpumask_any bpf_cpumask_any_and + :identifiers: bpf_cpumask_any_distribute bpf_cpumask_any_and_distribute ---- diff --git a/Documentation/bpf/instruction-set.rst b/Documentation/bpf/instruction-set.rst index 492980ece1abe9dd21c482cfce371eae95f328ed..6644842cd3ea1adb249216fb3658e4cfb6dd80a9 100644 --- a/Documentation/bpf/instruction-set.rst +++ b/Documentation/bpf/instruction-set.rst @@ -163,13 +163,13 @@ BPF_MUL 0x20 dst \*= src BPF_DIV 0x30 dst = (src != 0) ? (dst / src) : 0 BPF_OR 0x40 dst \|= src BPF_AND 0x50 dst &= src -BPF_LSH 0x60 dst <<= src -BPF_RSH 0x70 dst >>= src +BPF_LSH 0x60 dst <<= (src & mask) +BPF_RSH 0x70 dst >>= (src & mask) BPF_NEG 0x80 dst = ~src BPF_MOD 0x90 dst = (src != 0) ? (dst % src) : dst BPF_XOR 0xa0 dst ^= src BPF_MOV 0xb0 dst = src -BPF_ARSH 0xc0 sign extending shift right +BPF_ARSH 0xc0 sign extending dst >>= (src & mask) BPF_END 0xd0 byte swap operations (see `Byte swap instructions`_ below) ======== ===== ========================================================== @@ -204,6 +204,9 @@ for ``BPF_ALU64``, 'imm' is first sign extended to 64 bits and the result interpreted as an unsigned 64-bit value. There are no instructions for signed division or modulo. +Shift operations use a mask of 0x3F (63) for 64-bit operations and 0x1F (31) +for 32-bit operations. + Byte swap instructions ~~~~~~~~~~~~~~~~~~~~~~ diff --git a/Documentation/bpf/kfuncs.rst b/Documentation/bpf/kfuncs.rst index ea2516374d92ec2a4139cb0902defde74886ad81..0d2647fb358d7ce1a4a85bd994d9b05e8ea0cec9 100644 --- a/Documentation/bpf/kfuncs.rst +++ b/Documentation/bpf/kfuncs.rst @@ -100,7 +100,7 @@ Hence, whenever a constant scalar argument is accepted by a kfunc which is not a size parameter, and the value of the constant matters for program safety, __k suffix should be used. -2.2.2 __uninit Annotation +2.2.3 __uninit Annotation ------------------------- This annotation is used to indicate that the argument will be treated as @@ -117,6 +117,27 @@ Here, the dynptr will be treated as an uninitialized dynptr. Without this annotation, the verifier will reject the program if the dynptr passed in is not initialized. +2.2.4 __opt Annotation +------------------------- + +This annotation is used to indicate that the buffer associated with an __sz or __szk +argument may be null. If the function is passed a nullptr in place of the buffer, +the verifier will not check that length is appropriate for the buffer. The kfunc is +responsible for checking if this buffer is null before using it. + +An example is given below:: + + __bpf_kfunc void *bpf_dynptr_slice(..., void *buffer__opt, u32 buffer__szk) + { + ... + } + +Here, the buffer may be null. If buffer is not null, it at least of size buffer_szk. +Either way, the returned buffer is either NULL, or of size buffer_szk. Without this +annotation, the verifier will reject the program if a null pointer is passed in with +a nonzero size. + + .. _BPF_kfunc_nodef: 2.3 Using an existing kernel function @@ -206,23 +227,49 @@ absolutely no ABI stability guarantees. As mentioned above, a nested pointer obtained from walking a trusted pointer is no longer trusted, with one exception. If a struct type has a field that is -guaranteed to be valid as long as its parent pointer is trusted, the -``BTF_TYPE_SAFE_NESTED`` macro can be used to express that to the verifier as -follows: +guaranteed to be valid (trusted or rcu, as in KF_RCU description below) as long +as its parent pointer is valid, the following macros can be used to express +that to the verifier: + +* ``BTF_TYPE_SAFE_TRUSTED`` +* ``BTF_TYPE_SAFE_RCU`` +* ``BTF_TYPE_SAFE_RCU_OR_NULL`` + +For example, + +.. code-block:: c + + BTF_TYPE_SAFE_TRUSTED(struct socket) { + struct sock *sk; + }; + +or .. code-block:: c - BTF_TYPE_SAFE_NESTED(struct task_struct) { + BTF_TYPE_SAFE_RCU(struct task_struct) { const cpumask_t *cpus_ptr; + struct css_set __rcu *cgroups; + struct task_struct __rcu *real_parent; + struct task_struct *group_leader; }; In other words, you must: -1. Wrap the trusted pointer type in the ``BTF_TYPE_SAFE_NESTED`` macro. +1. Wrap the valid pointer type in a ``BTF_TYPE_SAFE_*`` macro. -2. Specify the type and name of the trusted nested field. This field must match +2. Specify the type and name of the valid nested field. This field must match the field in the original type definition exactly. +A new type declared by a ``BTF_TYPE_SAFE_*`` macro also needs to be emitted so +that it appears in BTF. For example, ``BTF_TYPE_SAFE_TRUSTED(struct socket)`` +is emitted in the ``type_is_trusted()`` function as follows: + +.. code-block:: c + + BTF_TYPE_EMIT(BTF_TYPE_SAFE_TRUSTED(struct socket)); + + 2.4.5 KF_SLEEPABLE flag ----------------------- diff --git a/Documentation/bpf/llvm_reloc.rst b/Documentation/bpf/llvm_reloc.rst index ca8957d5b67183e45965c40e65d2ae9eb1edf73a..e4a777a6a3a24ba977e0100cb6d53db6a294d28d 100644 --- a/Documentation/bpf/llvm_reloc.rst +++ b/Documentation/bpf/llvm_reloc.rst @@ -48,7 +48,7 @@ the code with ``llvm-objdump -dr test.o``:: 14: 0f 10 00 00 00 00 00 00 r0 += r1 15: 95 00 00 00 00 00 00 00 exit -There are four relations in the above for four ``LD_imm64`` instructions. +There are four relocations in the above for four ``LD_imm64`` instructions. The following ``llvm-readelf -r test.o`` shows the binary values of the four relocations:: @@ -79,14 +79,16 @@ The following is the symbol table with ``llvm-readelf -s test.o``:: The 6th entry is global variable ``g1`` with value 0. Similarly, the second relocation is at ``.text`` offset ``0x18``, instruction 3, -for global variable ``g2`` which has a symbol value 4, the offset -from the start of ``.data`` section. - -The third and fourth relocations refers to static variables ``l1`` -and ``l2``. From ``.rel.text`` section above, it is not clear -which symbols they really refers to as they both refers to +has a type of ``R_BPF_64_64`` and refers to entry 7 in the symbol table. +The second relocation resolves to global variable ``g2`` which has a symbol +value 4. The symbol value represents the offset from the start of ``.data`` +section where the initial value of the global variable ``g2`` is stored. + +The third and fourth relocations refer to static variables ``l1`` +and ``l2``. From the ``.rel.text`` section above, it is not clear +to which symbols they really refer as they both refer to symbol table entry 4, symbol ``sec``, which has ``STT_SECTION`` type -and represents a section. So for static variable or function, +and represents a section. So for a static variable or function, the section offset is written to the original insn buffer, which is called ``A`` (addend). Looking at above insn ``7`` and ``11``, they have section offset ``8`` and ``12``. diff --git a/Documentation/bpf/map_hash.rst b/Documentation/bpf/map_hash.rst index 8669426264c676b5001dd7eefe4de829f69b96fd..d2343952f2cbd3138e8a3a0034718609f376d2ba 100644 --- a/Documentation/bpf/map_hash.rst +++ b/Documentation/bpf/map_hash.rst @@ -1,5 +1,6 @@ .. SPDX-License-Identifier: GPL-2.0-only .. Copyright (C) 2022 Red Hat, Inc. +.. Copyright (C) 2022-2023 Isovalent, Inc. =============================================== BPF_MAP_TYPE_HASH, with PERCPU and LRU Variants @@ -29,7 +30,16 @@ will automatically evict the least recently used entries when the hash table reaches capacity. An LRU hash maintains an internal LRU list that is used to select elements for eviction. This internal LRU list is shared across CPUs but it is possible to request a per CPU LRU list with -the ``BPF_F_NO_COMMON_LRU`` flag when calling ``bpf_map_create``. +the ``BPF_F_NO_COMMON_LRU`` flag when calling ``bpf_map_create``. The +following table outlines the properties of LRU maps depending on the a +map type and the flags used to create the map. + +======================== ========================= ================================ +Flag ``BPF_MAP_TYPE_LRU_HASH`` ``BPF_MAP_TYPE_LRU_PERCPU_HASH`` +======================== ========================= ================================ +**BPF_F_NO_COMMON_LRU** Per-CPU LRU, global map Per-CPU LRU, per-cpu map +**!BPF_F_NO_COMMON_LRU** Global LRU, global map Global LRU, per-cpu map +======================== ========================= ================================ Usage ===== @@ -206,3 +216,44 @@ Userspace walking the map elements from the map declared above: cur_key = &next_key; } } + +Internals +========= + +This section of the document is targeted at Linux developers and describes +aspects of the map implementations that are not considered stable ABI. The +following details are subject to change in future versions of the kernel. + +``BPF_MAP_TYPE_LRU_HASH`` and variants +-------------------------------------- + +Updating elements in LRU maps may trigger eviction behaviour when the capacity +of the map is reached. There are various steps that the update algorithm +attempts in order to enforce the LRU property which have increasing impacts on +other CPUs involved in the following operation attempts: + +- Attempt to use CPU-local state to batch operations +- Attempt to fetch free nodes from global lists +- Attempt to pull any node from a global list and remove it from the hashmap +- Attempt to pull any node from any CPU's list and remove it from the hashmap + +This algorithm is described visually in the following diagram. See the +description in commit 3a08c2fd7634 ("bpf: LRU List") for a full explanation of +the corresponding operations: + +.. kernel-figure:: map_lru_hash_update.dot + :alt: Diagram outlining the LRU eviction steps taken during map update. + + LRU hash eviction during map update for ``BPF_MAP_TYPE_LRU_HASH`` and + variants. See the dot file source for kernel function name code references. + +Map updates start from the oval in the top right "begin ``bpf_map_update()``" +and progress through the graph towards the bottom where the result may be +either a successful update or a failure with various error codes. The key in +the top right provides indicators for which locks may be involved in specific +operations. This is intended as a visual hint for reasoning about how map +contention may impact update operations, though the map type and flags may +impact the actual contention on those locks, based on the logic described in +the table above. For instance, if the map is created with type +``BPF_MAP_TYPE_LRU_PERCPU_HASH`` and flags ``BPF_F_NO_COMMON_LRU`` then all map +properties would be per-cpu. diff --git a/Documentation/bpf/map_lru_hash_update.dot b/Documentation/bpf/map_lru_hash_update.dot new file mode 100644 index 0000000000000000000000000000000000000000..a0fee349d29c27b6e9016807df56c27f62070c0f --- /dev/null +++ b/Documentation/bpf/map_lru_hash_update.dot @@ -0,0 +1,172 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Copyright (C) 2022-2023 Isovalent, Inc. +digraph { + node [colorscheme=accent4,style=filled] # Apply colorscheme to all nodes + graph [splines=ortho, nodesep=1] + + subgraph cluster_key { + label = "Key\n(locks held during operation)"; + rankdir = TB; + + remote_lock [shape=rectangle,fillcolor=4,label="remote CPU LRU lock"] + hash_lock [shape=rectangle,fillcolor=3,label="hashtab lock"] + lru_lock [shape=rectangle,fillcolor=2,label="LRU lock"] + local_lock [shape=rectangle,fillcolor=1,label="local CPU LRU lock"] + no_lock [shape=rectangle,label="no locks held"] + } + + begin [shape=oval,label="begin\nbpf_map_update()"] + + // Nodes below with an 'fn_' prefix are roughly labeled by the C function + // names that initiate the corresponding logic in kernel/bpf/bpf_lru_list.c. + // Number suffixes and errno suffixes handle subsections of the corresponding + // logic in the function as of the writing of this dot. + + // cf. __local_list_pop_free() / bpf_percpu_lru_pop_free() + local_freelist_check [shape=diamond,fillcolor=1, + label="Local freelist\nnode available?"]; + use_local_node [shape=rectangle, + label="Use node owned\nby this CPU"] + + // cf. bpf_lru_pop_free() + common_lru_check [shape=diamond, + label="Map created with\ncommon LRU?\n(!BPF_F_NO_COMMON_LRU)"]; + + fn_bpf_lru_list_pop_free_to_local [shape=rectangle,fillcolor=2, + label="Flush local pending, + Rotate Global list, move + LOCAL_FREE_TARGET + from global -> local"] + // Also corresponds to: + // fn__local_list_flush() + // fn_bpf_lru_list_rotate() + fn___bpf_lru_node_move_to_free[shape=diamond,fillcolor=2, + label="Able to free\nLOCAL_FREE_TARGET\nnodes?"] + + fn___bpf_lru_list_shrink_inactive [shape=rectangle,fillcolor=3, + label="Shrink inactive list + up to remaining + LOCAL_FREE_TARGET + (global LRU -> local)"] + fn___bpf_lru_list_shrink [shape=diamond,fillcolor=2, + label="> 0 entries in\nlocal free list?"] + fn___bpf_lru_list_shrink2 [shape=rectangle,fillcolor=2, + label="Steal one node from + inactive, or if empty, + from active global list"] + fn___bpf_lru_list_shrink3 [shape=rectangle,fillcolor=3, + label="Try to remove\nnode from hashtab"] + + local_freelist_check2 [shape=diamond,label="Htab removal\nsuccessful?"] + common_lru_check2 [shape=diamond, + label="Map created with\ncommon LRU?\n(!BPF_F_NO_COMMON_LRU)"]; + + subgraph cluster_remote_lock { + label = "Iterate through CPUs\n(start from current)"; + style = dashed; + rankdir=LR; + + local_freelist_check5 [shape=diamond,fillcolor=4, + label="Steal a node from\nper-cpu freelist?"] + local_freelist_check6 [shape=rectangle,fillcolor=4, + label="Steal a node from + (1) Unreferenced pending, or + (2) Any pending node"] + local_freelist_check7 [shape=rectangle,fillcolor=3, + label="Try to remove\nnode from hashtab"] + fn_htab_lru_map_update_elem [shape=diamond, + label="Stole node\nfrom remote\nCPU?"] + fn_htab_lru_map_update_elem2 [shape=diamond,label="Iterated\nall CPUs?"] + // Also corresponds to: + // use_local_node() + // fn__local_list_pop_pending() + } + + fn_bpf_lru_list_pop_free_to_local2 [shape=rectangle, + label="Use node that was\nnot recently referenced"] + local_freelist_check4 [shape=rectangle, + label="Use node that was\nactively referenced\nin global list"] + fn_htab_lru_map_update_elem_ENOMEM [shape=oval,label="return -ENOMEM"] + fn_htab_lru_map_update_elem3 [shape=rectangle, + label="Use node that was\nactively referenced\nin (another?) CPU's cache"] + fn_htab_lru_map_update_elem4 [shape=rectangle,fillcolor=3, + label="Update hashmap\nwith new element"] + fn_htab_lru_map_update_elem5 [shape=oval,label="return 0"] + fn_htab_lru_map_update_elem_EBUSY [shape=oval,label="return -EBUSY"] + fn_htab_lru_map_update_elem_EEXIST [shape=oval,label="return -EEXIST"] + fn_htab_lru_map_update_elem_ENOENT [shape=oval,label="return -ENOENT"] + + begin -> local_freelist_check + local_freelist_check -> use_local_node [xlabel="Y"] + local_freelist_check -> common_lru_check [xlabel="N"] + common_lru_check -> fn_bpf_lru_list_pop_free_to_local [xlabel="Y"] + common_lru_check -> fn___bpf_lru_list_shrink_inactive [xlabel="N"] + fn_bpf_lru_list_pop_free_to_local -> fn___bpf_lru_node_move_to_free + fn___bpf_lru_node_move_to_free -> + fn_bpf_lru_list_pop_free_to_local2 [xlabel="Y"] + fn___bpf_lru_node_move_to_free -> + fn___bpf_lru_list_shrink_inactive [xlabel="N"] + fn___bpf_lru_list_shrink_inactive -> fn___bpf_lru_list_shrink + fn___bpf_lru_list_shrink -> fn_bpf_lru_list_pop_free_to_local2 [xlabel = "Y"] + fn___bpf_lru_list_shrink -> fn___bpf_lru_list_shrink2 [xlabel="N"] + fn___bpf_lru_list_shrink2 -> fn___bpf_lru_list_shrink3 + fn___bpf_lru_list_shrink3 -> local_freelist_check2 + local_freelist_check2 -> local_freelist_check4 [xlabel = "Y"] + local_freelist_check2 -> common_lru_check2 [xlabel = "N"] + common_lru_check2 -> local_freelist_check5 [xlabel = "Y"] + common_lru_check2 -> fn_htab_lru_map_update_elem_ENOMEM [xlabel = "N"] + local_freelist_check5 -> fn_htab_lru_map_update_elem [xlabel = "Y"] + local_freelist_check5 -> local_freelist_check6 [xlabel = "N"] + local_freelist_check6 -> local_freelist_check7 + local_freelist_check7 -> fn_htab_lru_map_update_elem + + fn_htab_lru_map_update_elem -> fn_htab_lru_map_update_elem3 [xlabel = "Y"] + fn_htab_lru_map_update_elem -> fn_htab_lru_map_update_elem2 [xlabel = "N"] + fn_htab_lru_map_update_elem2 -> + fn_htab_lru_map_update_elem_ENOMEM [xlabel = "Y"] + fn_htab_lru_map_update_elem2 -> local_freelist_check5 [xlabel = "N"] + fn_htab_lru_map_update_elem3 -> fn_htab_lru_map_update_elem4 + + use_local_node -> fn_htab_lru_map_update_elem4 + fn_bpf_lru_list_pop_free_to_local2 -> fn_htab_lru_map_update_elem4 + local_freelist_check4 -> fn_htab_lru_map_update_elem4 + + fn_htab_lru_map_update_elem4 -> fn_htab_lru_map_update_elem5 [headlabel="Success"] + fn_htab_lru_map_update_elem4 -> + fn_htab_lru_map_update_elem_EBUSY [xlabel="Hashtab lock failed"] + fn_htab_lru_map_update_elem4 -> + fn_htab_lru_map_update_elem_EEXIST [xlabel="BPF_EXIST set and\nkey already exists"] + fn_htab_lru_map_update_elem4 -> + fn_htab_lru_map_update_elem_ENOENT [headlabel="BPF_NOEXIST set\nand no such entry"] + + // Create invisible pad nodes to line up various nodes + pad0 [style=invis] + pad1 [style=invis] + pad2 [style=invis] + pad3 [style=invis] + pad4 [style=invis] + + // Line up the key with the top of the graph + no_lock -> local_lock [style=invis] + local_lock -> lru_lock [style=invis] + lru_lock -> hash_lock [style=invis] + hash_lock -> remote_lock [style=invis] + remote_lock -> local_freelist_check5 [style=invis] + remote_lock -> fn___bpf_lru_list_shrink [style=invis] + + // Line up return code nodes at the bottom of the graph + fn_htab_lru_map_update_elem -> pad0 [style=invis] + pad0 -> pad1 [style=invis] + pad1 -> pad2 [style=invis] + //pad2-> fn_htab_lru_map_update_elem_ENOMEM [style=invis] + fn_htab_lru_map_update_elem4 -> pad3 [style=invis] + pad3 -> fn_htab_lru_map_update_elem5 [style=invis] + pad3 -> fn_htab_lru_map_update_elem_EBUSY [style=invis] + pad3 -> fn_htab_lru_map_update_elem_EEXIST [style=invis] + pad3 -> fn_htab_lru_map_update_elem_ENOENT [style=invis] + + // Reduce diagram width by forcing some nodes to appear above others + local_freelist_check4 -> fn_htab_lru_map_update_elem3 [style=invis] + common_lru_check2 -> pad4 [style=invis] + pad4 -> local_freelist_check5 [style=invis] +} diff --git a/Documentation/bpf/map_sockmap.rst b/Documentation/bpf/map_sockmap.rst index cc92047c66300fce4bcf98a609633147786a3036..2d630686a00baa141bb7557098117f0eb236455b 100644 --- a/Documentation/bpf/map_sockmap.rst +++ b/Documentation/bpf/map_sockmap.rst @@ -240,11 +240,11 @@ offsets into ``msg``, respectively. If a program of type ``BPF_PROG_TYPE_SK_MSG`` is run on a ``msg`` it can only parse data that the (``data``, ``data_end``) pointers have already consumed. For ``sendmsg()`` hooks this is likely the first scatterlist element. But for -calls relying on the ``sendpage`` handler (e.g., ``sendfile()``) this will be -the range (**0**, **0**) because the data is shared with user space and by -default the objective is to avoid allowing user space to modify data while (or -after) BPF verdict is being decided. This helper can be used to pull in data -and to set the start and end pointers to given values. Data will be copied if +calls relying on MSG_SPLICE_PAGES (e.g., ``sendfile()``) this will be the +range (**0**, **0**) because the data is shared with user space and by default +the objective is to avoid allowing user space to modify data while (or after) +BPF verdict is being decided. This helper can be used to pull in data and to +set the start and end pointers to given values. Data will be copied if necessary (i.e., if data was not linear and if start and end pointers do not point to the same chunk). diff --git a/Documentation/bpf/prog_cgroup_sockopt.rst b/Documentation/bpf/prog_cgroup_sockopt.rst index 172f957204bf45b1666d23686b03c51d5acfa9d5..1226a94af07a886b8d562ee2241c2bfc43ef2f54 100644 --- a/Documentation/bpf/prog_cgroup_sockopt.rst +++ b/Documentation/bpf/prog_cgroup_sockopt.rst @@ -98,10 +98,65 @@ can access only the first ``PAGE_SIZE`` of that data. So it has to options: indicates that the kernel should use BPF's trimmed ``optval``. When the BPF program returns with the ``optlen`` greater than -``PAGE_SIZE``, the userspace will receive ``EFAULT`` errno. +``PAGE_SIZE``, the userspace will receive original kernel +buffers without any modifications that the BPF program might have +applied. Example ======= +Recommended way to handle BPF programs is as follows: + +.. code-block:: c + + SEC("cgroup/getsockopt") + int getsockopt(struct bpf_sockopt *ctx) + { + /* Custom socket option. */ + if (ctx->level == MY_SOL && ctx->optname == MY_OPTNAME) { + ctx->retval = 0; + optval[0] = ...; + ctx->optlen = 1; + return 1; + } + + /* Modify kernel's socket option. */ + if (ctx->level == SOL_IP && ctx->optname == IP_FREEBIND) { + ctx->retval = 0; + optval[0] = ...; + ctx->optlen = 1; + return 1; + } + + /* optval larger than PAGE_SIZE use kernel's buffer. */ + if (ctx->optlen > PAGE_SIZE) + ctx->optlen = 0; + + return 1; + } + + SEC("cgroup/setsockopt") + int setsockopt(struct bpf_sockopt *ctx) + { + /* Custom socket option. */ + if (ctx->level == MY_SOL && ctx->optname == MY_OPTNAME) { + /* do something */ + ctx->optlen = -1; + return 1; + } + + /* Modify kernel's socket option. */ + if (ctx->level == SOL_IP && ctx->optname == IP_FREEBIND) { + optval[0] = ...; + return 1; + } + + /* optval larger than PAGE_SIZE use kernel's buffer. */ + if (ctx->optlen > PAGE_SIZE) + ctx->optlen = 0; + + return 1; + } + See ``tools/testing/selftests/bpf/progs/sockopt_sk.c`` for an example of BPF program that handles socket options. diff --git a/Documentation/conf.py b/Documentation/conf.py index 37314afd1ac8aa6aed755612b45c5e9ad0ecabd0..d4fdf6a3875a83ae5c456d11c4ae53b9716b5390 100644 --- a/Documentation/conf.py +++ b/Documentation/conf.py @@ -74,6 +74,7 @@ if major >= 3: "__percpu", "__rcu", "__user", + "__force", # include/linux/compiler_attributes.h: "__alias", diff --git a/Documentation/core-api/cpu_hotplug.rst b/Documentation/core-api/cpu_hotplug.rst index f75778d374884810eaa1aae0bceb02351976dedb..e6f5bc39cf5c632a220a7614d26e97f4ca57efe9 100644 --- a/Documentation/core-api/cpu_hotplug.rst +++ b/Documentation/core-api/cpu_hotplug.rst @@ -127,17 +127,8 @@ bring CPU4 back online:: $ echo 1 > /sys/devices/system/cpu/cpu4/online smpboot: Booting Node 0 Processor 4 APIC 0x1 -The CPU is usable again. This should work on all CPUs. CPU0 is often special -and excluded from CPU hotplug. On X86 the kernel option -*CONFIG_BOOTPARAM_HOTPLUG_CPU0* has to be enabled in order to be able to -shutdown CPU0. Alternatively the kernel command option *cpu0_hotplug* can be -used. Some known dependencies of CPU0: - -* Resume from hibernate/suspend. Hibernate/suspend will fail if CPU0 is offline. -* PIC interrupts. CPU0 can't be removed if a PIC interrupt is detected. - -Please let Fenghua Yu know if you find any dependencies -on CPU0. +The CPU is usable again. This should work on all CPUs, but CPU0 is often special +and excluded from CPU hotplug. The CPU hotplug coordination ============================ diff --git a/Documentation/core-api/kernel-api.rst b/Documentation/core-api/kernel-api.rst index 9b3f3e5f5a9599bb2a8b044935adce7a0048880f..f2bcc5a7ea432d8da0f0dad5105241df8494211e 100644 --- a/Documentation/core-api/kernel-api.rst +++ b/Documentation/core-api/kernel-api.rst @@ -96,6 +96,12 @@ Command-line Parsing .. kernel-doc:: lib/cmdline.c :export: +Error Pointers +-------------- + +.. kernel-doc:: include/linux/err.h + :internal: + Sorting ------- @@ -412,3 +418,15 @@ Read-Copy Update (RCU) .. kernel-doc:: include/linux/rcu_sync.h .. kernel-doc:: kernel/rcu/sync.c + +.. kernel-doc:: kernel/rcu/tasks.h + +.. kernel-doc:: kernel/rcu/tree_stall.h + +.. kernel-doc:: include/linux/rcupdate_trace.h + +.. kernel-doc:: include/linux/rcupdate_wait.h + +.. kernel-doc:: include/linux/rcuref.h + +.. kernel-doc:: include/linux/rcutree.h diff --git a/Documentation/core-api/pin_user_pages.rst b/Documentation/core-api/pin_user_pages.rst index 9fb0b1080d3b8cc7ae142fda425ebd01fe64ed0c..d3c1f6d8c0e0ec819843ad11bea22cad9614e657 100644 --- a/Documentation/core-api/pin_user_pages.rst +++ b/Documentation/core-api/pin_user_pages.rst @@ -112,6 +112,12 @@ pages: This also leads to limitations: there are only 31-10==21 bits available for a counter that increments 10 bits at a time. +* Because of that limitation, special handling is applied to the zero pages + when using FOLL_PIN. We only pretend to pin a zero page - we don't alter its + refcount or pincount at all (it is permanent, so there's no need). The + unpinning functions also don't do anything to a zero page. This is + transparent to the caller. + * Callers must specifically request "dma-pinned tracking of pages". In other words, just calling get_user_pages() will not suffice; a new set of functions, pin_user_page() and related, must be used. diff --git a/Documentation/core-api/this_cpu_ops.rst b/Documentation/core-api/this_cpu_ops.rst index 5cb8b883ae83221ace183c463d0232ea9d556980..91acbcf30e9bd777ab7b64f18a3f4c701ff65dd7 100644 --- a/Documentation/core-api/this_cpu_ops.rst +++ b/Documentation/core-api/this_cpu_ops.rst @@ -53,7 +53,6 @@ preemption and interrupts:: this_cpu_add_return(pcp, val) this_cpu_xchg(pcp, nval) this_cpu_cmpxchg(pcp, oval, nval) - this_cpu_cmpxchg_double(pcp1, pcp2, oval1, oval2, nval1, nval2) this_cpu_sub(pcp, val) this_cpu_inc(pcp) this_cpu_dec(pcp) @@ -242,7 +241,6 @@ safe:: __this_cpu_add_return(pcp, val) __this_cpu_xchg(pcp, nval) __this_cpu_cmpxchg(pcp, oval, nval) - __this_cpu_cmpxchg_double(pcp1, pcp2, oval1, oval2, nval1, nval2) __this_cpu_sub(pcp, val) __this_cpu_inc(pcp) __this_cpu_dec(pcp) diff --git a/Documentation/core-api/workqueue.rst b/Documentation/core-api/workqueue.rst index 8ec4d6270b24e82c4fce3f6088dd334a6286dbbe..a4c9b9d1905f473dc4d01aa2a5db37c32ad4e4d2 100644 --- a/Documentation/core-api/workqueue.rst +++ b/Documentation/core-api/workqueue.rst @@ -348,6 +348,37 @@ Guidelines level of locality in wq operations and work item execution. +Monitoring +========== + +Use tools/workqueue/wq_monitor.py to monitor workqueue operations: :: + + $ tools/workqueue/wq_monitor.py events + total infl CPUtime CPUhog CMwake mayday rescued + events 18545 0 6.1 0 5 - - + events_highpri 8 0 0.0 0 0 - - + events_long 3 0 0.0 0 0 - - + events_unbound 38306 0 0.1 - - - - + events_freezable 0 0 0.0 0 0 - - + events_power_efficient 29598 0 0.2 0 0 - - + events_freezable_power_ 10 0 0.0 0 0 - - + sock_diag_events 0 0 0.0 0 0 - - + + total infl CPUtime CPUhog CMwake mayday rescued + events 18548 0 6.1 0 5 - - + events_highpri 8 0 0.0 0 0 - - + events_long 3 0 0.0 0 0 - - + events_unbound 38322 0 0.1 - - - - + events_freezable 0 0 0.0 0 0 - - + events_power_efficient 29603 0 0.2 0 0 - - + events_freezable_power_ 10 0 0.0 0 0 - - + sock_diag_events 0 0 0.0 0 0 - - + + ... + +See the command's help message for more info. + + Debugging ========= @@ -387,6 +418,7 @@ the stack trace of the offending worker thread. :: The work item's function should be trivially visible in the stack trace. + Non-reentrance Conditions ========================= diff --git a/Documentation/crypto/async-tx-api.rst b/Documentation/crypto/async-tx-api.rst index bfc773991bdc59b7c1c1a9fe7d50d840725b8b35..27c146b54d713dcabfd307a689d7de6ed7443047 100644 --- a/Documentation/crypto/async-tx-api.rst +++ b/Documentation/crypto/async-tx-api.rst @@ -66,7 +66,7 @@ features surfaced as a result: :: struct dma_async_tx_descriptor * - async_(, struct async_submit ctl *submit) + async_(, struct async_submit_ctl *submit) 3.2 Supported operations ------------------------ diff --git a/Documentation/dev-tools/kasan.rst b/Documentation/dev-tools/kasan.rst index e66916a483cdb0a6db3ffd26a6de9cf0214f823a..f4acf9c2e90f6e3c3416546227db1a734f3b34b2 100644 --- a/Documentation/dev-tools/kasan.rst +++ b/Documentation/dev-tools/kasan.rst @@ -107,9 +107,12 @@ effectively disables ``panic_on_warn`` for KASAN reports. Alternatively, independent of ``panic_on_warn``, the ``kasan.fault=`` boot parameter can be used to control panic and reporting behaviour: -- ``kasan.fault=report`` or ``=panic`` controls whether to only print a KASAN - report or also panic the kernel (default: ``report``). The panic happens even - if ``kasan_multi_shot`` is enabled. +- ``kasan.fault=report``, ``=panic``, or ``=panic_on_write`` controls whether + to only print a KASAN report, panic the kernel, or panic the kernel on + invalid writes only (default: ``report``). The panic happens even if + ``kasan_multi_shot`` is enabled. Note that when using asynchronous mode of + Hardware Tag-Based KASAN, ``kasan.fault=panic_on_write`` always panics on + asynchronously checked accesses (including reads). Software and Hardware Tag-Based KASAN modes (see the section about various modes below) support altering stack trace collection behavior: diff --git a/Documentation/dev-tools/kselftest.rst b/Documentation/dev-tools/kselftest.rst index 12b575b76b20b1ded2f33b28746f32244a16ac44..deede972f254797302adf023d93e0af4f7fe703c 100644 --- a/Documentation/dev-tools/kselftest.rst +++ b/Documentation/dev-tools/kselftest.rst @@ -36,6 +36,7 @@ Running the selftests (hotplug tests are run in limited mode) To build the tests:: + $ make headers $ make -C tools/testing/selftests To run the tests:: @@ -168,6 +169,28 @@ the `-t` option for specific single tests. Either can be used multiple times:: For other features see the script usage output, seen with the `-h` option. +Timeout for selftests +===================== + +Selftests are designed to be quick and so a default timeout is used of 45 +seconds for each test. Tests can override the default timeout by adding +a settings file in their directory and set a timeout variable there to the +configured a desired upper timeout for the test. Only a few tests override +the timeout with a value higher than 45 seconds, selftests strives to keep +it that way. Timeouts in selftests are not considered fatal because the +system under which a test runs may change and this can also modify the +expected time it takes to run a test. If you have control over the systems +which will run the tests you can configure a test runner on those systems to +use a greater or lower timeout on the command line as with the `-o` or +the `--override-timeout` argument. For example to use 165 seconds instead +one would use: + + $ ./run_kselftest.sh --override-timeout 165 + +You can look at the TAP output to see if you ran into the timeout. Test +runners which know a test must run under a specific time can then optionally +treat these timeouts then as fatal. + Packaging selftests =================== diff --git a/Documentation/dev-tools/kunit/architecture.rst b/Documentation/dev-tools/kunit/architecture.rst index e95ab05342bb968d7923c8fac5cf4316f7c13ed8..f335f883f8f69bc8f569b15c4a4da8f17b852b8c 100644 --- a/Documentation/dev-tools/kunit/architecture.rst +++ b/Documentation/dev-tools/kunit/architecture.rst @@ -119,9 +119,9 @@ All expectations/assertions are formatted as: terminated immediately. - Assertions call the function: - ``void __noreturn kunit_abort(struct kunit *)``. + ``void __noreturn __kunit_abort(struct kunit *)``. - - ``kunit_abort`` calls the function: + - ``__kunit_abort`` calls the function: ``void __noreturn kunit_try_catch_throw(struct kunit_try_catch *try_catch)``. - ``kunit_try_catch_throw`` calls the function: diff --git a/Documentation/dev-tools/kunit/start.rst b/Documentation/dev-tools/kunit/start.rst index c736613c9b199bff7b68e742935cd04447b8552f..a98235326bab0080df909365a185d4c9570ab8ab 100644 --- a/Documentation/dev-tools/kunit/start.rst +++ b/Documentation/dev-tools/kunit/start.rst @@ -250,15 +250,20 @@ Now we are ready to write the test cases. }; kunit_test_suite(misc_example_test_suite); + MODULE_LICENSE("GPL"); + 2. Add the following lines to ``drivers/misc/Kconfig``: .. code-block:: kconfig config MISC_EXAMPLE_TEST tristate "Test for my example" if !KUNIT_ALL_TESTS - depends on MISC_EXAMPLE && KUNIT=y + depends on MISC_EXAMPLE && KUNIT default KUNIT_ALL_TESTS +Note: If your test does not support being built as a loadable module (which is +discouraged), replace tristate by bool, and depend on KUNIT=y instead of KUNIT. + 3. Add the following lines to ``drivers/misc/Makefile``: .. code-block:: make diff --git a/Documentation/dev-tools/kunit/usage.rst b/Documentation/dev-tools/kunit/usage.rst index 9faf2b4153fc3a2f4cb8e17c04c090fb51506f0c..c27e1646ecd9caf60faeda70a0d2be1a0d395d00 100644 --- a/Documentation/dev-tools/kunit/usage.rst +++ b/Documentation/dev-tools/kunit/usage.rst @@ -121,6 +121,12 @@ there's an allocation error. ``return`` so they only work from the test function. In KUnit, we stop the current kthread on failure, so you can call them from anywhere. +.. note:: + Warning: There is an exception to the above rule. You shouldn't use assertions + in the suite's exit() function, or in the free function for a resource. These + run when a test is shutting down, and an assertion here prevents further + cleanup code from running, potentially leading to a memory leak. + Customizing error messages -------------------------- @@ -160,7 +166,12 @@ many similar tests. In order to reduce duplication in these closely related tests, most unit testing frameworks (including KUnit) provide the concept of a *test suite*. A test suite is a collection of test cases for a unit of code with optional setup and teardown functions that run before/after the whole -suite and/or every test case. For example: +suite and/or every test case. + +.. note:: + A test case will only run if it is associated with a test suite. + +For example: .. code-block:: c @@ -190,7 +201,10 @@ after everything else. ``kunit_test_suite(example_test_suite)`` registers the test suite with the KUnit test framework. .. note:: - A test case will only run if it is associated with a test suite. + The ``exit`` and ``suite_exit`` functions will run even if ``init`` or + ``suite_init`` fail. Make sure that they can handle any inconsistent + state which may result from ``init`` or ``suite_init`` encountering errors + or exiting early. ``kunit_test_suite(...)`` is a macro which tells the linker to put the specified test suite in a special linker section so that it can be run by KUnit @@ -601,6 +615,57 @@ For example: KUNIT_ASSERT_STREQ(test, buffer, ""); } +Registering Cleanup Actions +--------------------------- + +If you need to perform some cleanup beyond simple use of ``kunit_kzalloc``, +you can register a custom "deferred action", which is a cleanup function +run when the test exits (whether cleanly, or via a failed assertion). + +Actions are simple functions with no return value, and a single ``void*`` +context argument, and fulfill the same role as "cleanup" functions in Python +and Go tests, "defer" statements in languages which support them, and +(in some cases) destructors in RAII languages. + +These are very useful for unregistering things from global lists, closing +files or other resources, or freeing resources. + +For example: + +.. code-block:: C + + static void cleanup_device(void *ctx) + { + struct device *dev = (struct device *)ctx; + + device_unregister(dev); + } + + void example_device_test(struct kunit *test) + { + struct my_device dev; + + device_register(&dev); + + kunit_add_action(test, &cleanup_device, &dev); + } + +Note that, for functions like device_unregister which only accept a single +pointer-sized argument, it's possible to directly cast that function to +a ``kunit_action_t`` rather than writing a wrapper function, for example: + +.. code-block:: C + + kunit_add_action(test, (kunit_action_t *)&device_unregister, &dev); + +``kunit_add_action`` can fail if, for example, the system is out of memory. +You can use ``kunit_add_action_or_reset`` instead which runs the action +immediately if it cannot be deferred. + +If you need more control over when the cleanup function is called, you +can trigger it early using ``kunit_release_action``, or cancel it entirely +with ``kunit_remove_action``. + Testing Static Functions ------------------------ diff --git a/Documentation/devicetree/bindings/arm/amlogic.yaml b/Documentation/devicetree/bindings/arm/amlogic.yaml index 274ee0890312eacf354f2348c5a75d1bc44a5dc1..08d59842655c7052dddb9d3ae5666b6ca73d757f 100644 --- a/Documentation/devicetree/bindings/arm/amlogic.yaml +++ b/Documentation/devicetree/bindings/arm/amlogic.yaml @@ -4,7 +4,7 @@ $id: http://devicetree.org/schemas/arm/amlogic.yaml# $schema: http://devicetree.org/meta-schemas/core.yaml# -title: Amlogic MesonX +title: Amlogic SoC based Platforms maintainers: - Kevin Hilman @@ -205,6 +205,13 @@ properties: - amlogic,ad401 - const: amlogic,a1 + - description: Boards with the Amlogic C3 C302X/C308L SoC + items: + - enum: + - amlogic,aw409 + - amlogic,aw419 + - const: amlogic,c3 + - description: Boards with the Amlogic Meson S4 S805X2 SoC items: - enum: diff --git a/Documentation/devicetree/bindings/arm/arm,coresight-cti.yaml b/Documentation/devicetree/bindings/arm/arm,coresight-cti.yaml index 0c5b875cb654bc286edd75981d46946e7b6db421..d6c84b6e7fe69a5cf1246e9757a7924ef59f5ba8 100644 --- a/Documentation/devicetree/bindings/arm/arm,coresight-cti.yaml +++ b/Documentation/devicetree/bindings/arm/arm,coresight-cti.yaml @@ -287,7 +287,7 @@ examples: arm,trig-in-sigs = <0 1>; arm,trig-in-types = ; - arm,trig-out-sigs=<0 1 2 >; + arm,trig-out-sigs = <0 1 2 >; arm,trig-out-types = ; @@ -309,24 +309,24 @@ examples: trig-conns@0 { reg = <0>; - arm,trig-in-sigs=<0>; - arm,trig-in-types=; - arm,trig-out-sigs=<0>; - arm,trig-out-types=; + arm,trig-in-sigs = <0>; + arm,trig-in-types = ; + arm,trig-out-sigs = <0>; + arm,trig-out-types = ; arm,trig-conn-name = "sys_profiler"; }; trig-conns@1 { reg = <1>; - arm,trig-out-sigs=<2 3>; - arm,trig-out-types=; + arm,trig-out-sigs = <2 3>; + arm,trig-out-types = ; arm,trig-conn-name = "watchdog"; }; trig-conns@2 { reg = <2>; - arm,trig-in-sigs=<1 6>; - arm,trig-in-types=; + arm,trig-in-sigs = <1 6>; + arm,trig-in-types = ; arm,trig-conn-name = "g_counter"; }; }; diff --git a/Documentation/devicetree/bindings/arm/arm,coresight-dummy-sink.yaml b/Documentation/devicetree/bindings/arm/arm,coresight-dummy-sink.yaml new file mode 100644 index 0000000000000000000000000000000000000000..cb78cfa56702eed4eb0f92b7fef3460f9a926bbc --- /dev/null +++ b/Documentation/devicetree/bindings/arm/arm,coresight-dummy-sink.yaml @@ -0,0 +1,73 @@ +# SPDX-License-Identifier: GPL-2.0-only or BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/arm/arm,coresight-dummy-sink.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: ARM Coresight Dummy sink component + +description: | + CoreSight components are compliant with the ARM CoreSight architecture + specification and can be connected in various topologies to suit a particular + SoCs tracing needs. These trace components can generally be classified as + sinks, links and sources. Trace data produced by one or more sources flows + through the intermediate links connecting the source to the currently selected + sink. + + The Coresight dummy sink component is for the specific coresight sink devices + kernel don't have permission to access or configure, e.g., CoreSight EUD on + Qualcomm platforms. It is a mini-USB hub implemented to support the USB-based + debug and trace capabilities. For this device, a dummy driver is needed to + register it as Coresight sink device in kernel side, so that path can be + created in the driver. Then the trace flow would be transferred to EUD via + coresight link of AP processor. It provides Coresight API for operations on + dummy source devices, such as enabling and disabling them. It also provides + the Coresight dummy source paths for debugging. + + The primary use case of the coresight dummy sink is to build path in kernel + side for dummy sink component. + +maintainers: + - Mike Leach + - Suzuki K Poulose + - James Clark + - Mao Jinlong + - Hao Zhang + +properties: + compatible: + enum: + - arm,coresight-dummy-sink + + in-ports: + $ref: /schemas/graph.yaml#/properties/ports + + properties: + port: + description: Input connection from the Coresight Trace bus to + dummy sink, such as Embedded USB debugger(EUD). + + $ref: /schemas/graph.yaml#/properties/port + +required: + - compatible + - in-ports + +additionalProperties: false + +examples: + # Minimum dummy sink definition. Dummy sink connect to coresight replicator. + - | + sink { + compatible = "arm,coresight-dummy-sink"; + + in-ports { + port { + eud_in_replicator_swao: endpoint { + remote-endpoint = <&replicator_swao_out_eud>; + }; + }; + }; + }; + +... diff --git a/Documentation/devicetree/bindings/arm/arm,coresight-dummy-source.yaml b/Documentation/devicetree/bindings/arm/arm,coresight-dummy-source.yaml new file mode 100644 index 0000000000000000000000000000000000000000..5fedaed49a1f5413889f03a8602f31d76a0a5e0e --- /dev/null +++ b/Documentation/devicetree/bindings/arm/arm,coresight-dummy-source.yaml @@ -0,0 +1,71 @@ +# SPDX-License-Identifier: GPL-2.0-only or BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/arm/arm,coresight-dummy-source.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: ARM Coresight Dummy source component + +description: | + CoreSight components are compliant with the ARM CoreSight architecture + specification and can be connected in various topologies to suit a particular + SoCs tracing needs. These trace components can generally be classified as + sinks, links and sources. Trace data produced by one or more sources flows + through the intermediate links connecting the source to the currently selected + sink. + + The Coresight dummy source component is for the specific coresight source + devices kernel don't have permission to access or configure. For some SOCs, + there would be Coresight source trace components on sub-processor which + are conneted to AP processor via debug bus. For these devices, a dummy driver + is needed to register them as Coresight source devices, so that paths can be + created in the driver. It provides Coresight API for operations on dummy + source devices, such as enabling and disabling them. It also provides the + Coresight dummy source paths for debugging. + + The primary use case of the coresight dummy source is to build path in kernel + side for dummy source component. + +maintainers: + - Mike Leach + - Suzuki K Poulose + - James Clark + - Mao Jinlong + - Hao Zhang + +properties: + compatible: + enum: + - arm,coresight-dummy-source + + out-ports: + $ref: /schemas/graph.yaml#/properties/ports + + properties: + port: + description: Output connection from the source to Coresight + Trace bus. + $ref: /schemas/graph.yaml#/properties/port + +required: + - compatible + - out-ports + +additionalProperties: false + +examples: + # Minimum dummy source definition. Dummy source connect to coresight funnel. + - | + source { + compatible = "arm,coresight-dummy-source"; + + out-ports { + port { + dummy_riscv_out_funnel_swao: endpoint { + remote-endpoint = <&funnel_swao_in_dummy_riscv>; + }; + }; + }; + }; + +... diff --git a/Documentation/devicetree/bindings/arm/arm,vexpress-juno.yaml b/Documentation/devicetree/bindings/arm/arm,vexpress-juno.yaml index 09c319f803ba43817bf8fc6e0ab9a195dff4ea29..cdd65881fcdd85094ccc3effa6da2ff69cd1bc01 100644 --- a/Documentation/devicetree/bindings/arm/arm,vexpress-juno.yaml +++ b/Documentation/devicetree/bindings/arm/arm,vexpress-juno.yaml @@ -122,14 +122,14 @@ properties: arm,vexpress,position: description: When daughterboards are stacked on one site, their position in the stack be be described this attribute. - $ref: '/schemas/types.yaml#/definitions/uint32' + $ref: /schemas/types.yaml#/definitions/uint32 minimum: 0 maximum: 3 arm,vexpress,dcc: description: When describing tiles consisting of more than one DCC, its number can be specified with this attribute. - $ref: '/schemas/types.yaml#/definitions/uint32' + $ref: /schemas/types.yaml#/definitions/uint32 minimum: 0 maximum: 3 @@ -180,13 +180,13 @@ patternProperties: - const: simple-bus arm,v2m-memory-map: description: This describes the memory map type. - $ref: '/schemas/types.yaml#/definitions/string' + $ref: /schemas/types.yaml#/definitions/string enum: - rs1 - rs2 arm,hbi: - $ref: '/schemas/types.yaml#/definitions/uint32' + $ref: /schemas/types.yaml#/definitions/uint32 description: This indicates the ARM HBI (Hardware Board ID), this is ARM's unique board model ID, visible on the PCB's silkscreen. @@ -197,7 +197,7 @@ patternProperties: property, describing the physical location of the children nodes. 0 means motherboard site, while 1 and 2 are daughterboard sites, and 0xf means "sisterboard" which is the site containing the main CPU tile. - $ref: '/schemas/types.yaml#/definitions/uint32' + $ref: /schemas/types.yaml#/definitions/uint32 minimum: 0 maximum: 15 diff --git a/Documentation/devicetree/bindings/arm/atmel-sysregs.txt b/Documentation/devicetree/bindings/arm/atmel-sysregs.txt index ab1b352344ae1717bc249be582e61e450af862d9..67a66bf7489579a9be9ae457c161542e6e59ac06 100644 --- a/Documentation/devicetree/bindings/arm/atmel-sysregs.txt +++ b/Documentation/devicetree/bindings/arm/atmel-sysregs.txt @@ -52,100 +52,6 @@ Example: reg = <0xe3804000 0x1000>; }; -SHDWC Shutdown Controller - -required properties: -- compatible: Should be "atmel,-shdwc". - can be "at91sam9260", "at91sam9rl" or "at91sam9x5". -- reg: Should contain registers location and length -- clocks: phandle to input clock. - -optional properties: -- atmel,wakeup-mode: String, operation mode of the wakeup mode. - Supported values are: "none", "high", "low", "any". -- atmel,wakeup-counter: Counter on Wake-up 0 (between 0x0 and 0xf). - -optional at91sam9260 properties: -- atmel,wakeup-rtt-timer: boolean to enable Real-time Timer Wake-up. - -optional at91sam9rl properties: -- atmel,wakeup-rtc-timer: boolean to enable Real-time Clock Wake-up. -- atmel,wakeup-rtt-timer: boolean to enable Real-time Timer Wake-up. - -optional at91sam9x5 properties: -- atmel,wakeup-rtc-timer: boolean to enable Real-time Clock Wake-up. - -Example: - - shdwc@fffffd10 { - compatible = "atmel,at91sam9260-shdwc"; - reg = <0xfffffd10 0x10>; - clocks = <&clk32k>; - }; - -SHDWC SAMA5D2-Compatible Shutdown Controller - -1) shdwc node - -required properties: -- compatible: should be "atmel,sama5d2-shdwc", "microchip,sam9x60-shdwc" or - "microchip,sama7g5-shdwc" -- reg: should contain registers location and length -- clocks: phandle to input clock. -- #address-cells: should be one. The cell is the wake-up input index. -- #size-cells: should be zero. - -optional properties: - -- debounce-delay-us: minimum wake-up inputs debouncer period in - microseconds. It's usually a board-related property. -- atmel,wakeup-rtc-timer: boolean to enable Real-Time Clock wake-up. - -optional microchip,sam9x60-shdwc or microchip,sama7g5-shdwc properties: -- atmel,wakeup-rtt-timer: boolean to enable Real-time Timer Wake-up. - -The node contains child nodes for each wake-up input that the platform uses. - -2) input nodes - -Wake-up input nodes are usually described in the "board" part of the Device -Tree. Note also that input 0 is linked to the wake-up pin and is frequently -used. - -Required properties: -- reg: should contain the wake-up input index [0 - 15]. - -Optional properties: -- atmel,wakeup-active-high: boolean, the corresponding wake-up input described - by the child, forces the wake-up of the core power supply on a high level. - The default is to be active low. - -Example: - -On the SoC side: - shdwc@f8048010 { - compatible = "atmel,sama5d2-shdwc"; - reg = <0xf8048010 0x10>; - clocks = <&clk32k>; - #address-cells = <1>; - #size-cells = <0>; - atmel,wakeup-rtc-timer; - }; - -On the board side: - shdwc@f8048010 { - debounce-delay-us = <976>; - - input@0 { - reg = <0>; - }; - - input@1 { - reg = <1>; - atmel,wakeup-active-high; - }; - }; - Special Function Registers (SFR) Special Function Registers (SFR) manage specific aspects of the integrated diff --git a/Documentation/devicetree/bindings/arm/bcm/brcm,bcm4708.yaml b/Documentation/devicetree/bindings/arm/bcm/brcm,bcm4708.yaml index 454b0e93245d824ace4f01568506bf2d2410fabc..5c3ac97e8728664a98b6381d67418b47e66b4b72 100644 --- a/Documentation/devicetree/bindings/arm/bcm/brcm,bcm4708.yaml +++ b/Documentation/devicetree/bindings/arm/bcm/brcm,bcm4708.yaml @@ -25,13 +25,15 @@ properties: - enum: - asus,rt-ac56u - asus,rt-ac68u + - buffalo,wzr-1166dhp + - buffalo,wzr-1166dhp2 - buffalo,wzr-1750dhp - linksys,ea6300-v1 - linksys,ea6500-v2 - - luxul,xap-1510v1 + - luxul,xap-1510-v1 - luxul,xwc-1000 - - netgear,r6250v1 - - netgear,r6300v2 + - netgear,r6250-v1 + - netgear,r6300-v2 - smartrg,sr400ac - brcm,bcm94708 - const: brcm,bcm4708 @@ -42,8 +44,8 @@ properties: - asus,rt-n18u - buffalo,wzr-600dhp2 - buffalo,wzr-900dhp - - luxul,xap-1410v1 - - luxul,xwr-1200v1 + - luxul,xap-1410-v1 + - luxul,xwr-1200-v1 - tplink,archer-c5-v2 - const: brcm,bcm47081 - const: brcm,bcm4708 @@ -72,7 +74,7 @@ properties: - luxul,xap-1610-v1 - luxul,xbr-4500-v1 - luxul,xwc-2000-v1 - - luxul,xwr-3100v1 + - luxul,xwr-3100-v1 - luxul,xwr-3150-v1 - netgear,r8500 - phicomm,k3 diff --git a/Documentation/devicetree/bindings/arm/cpus.yaml b/Documentation/devicetree/bindings/arm/cpus.yaml index ff272e517d574d3f91e96e47953e676b6ec07495..9e6a45eea4e5ed3ac12ad683d1819cd2e9646bf7 100644 --- a/Documentation/devicetree/bindings/arm/cpus.yaml +++ b/Documentation/devicetree/bindings/arm/cpus.yaml @@ -153,6 +153,7 @@ properties: - arm,cortex-r4 - arm,cortex-r5 - arm,cortex-r7 + - arm,cortex-r52 - arm,cortex-x1 - arm,cortex-x1c - arm,cortex-x2 @@ -196,7 +197,7 @@ properties: - qcom,scorpion enable-method: - $ref: '/schemas/types.yaml#/definitions/string' + $ref: /schemas/types.yaml#/definitions/string oneOf: # On ARM v8 64-bit this property is required - enum: @@ -245,8 +246,8 @@ properties: cpu-release-addr: oneOf: - - $ref: '/schemas/types.yaml#/definitions/uint32' - - $ref: '/schemas/types.yaml#/definitions/uint64' + - $ref: /schemas/types.yaml#/definitions/uint32 + - $ref: /schemas/types.yaml#/definitions/uint64 description: The DT specification defines this as 64-bit always, but some 32-bit Arm systems have used a 32-bit value which must be supported. @@ -254,7 +255,7 @@ properties: property value of "spin-table". cpu-idle-states: - $ref: '/schemas/types.yaml#/definitions/phandle-array' + $ref: /schemas/types.yaml#/definitions/phandle-array items: maxItems: 1 description: | @@ -270,7 +271,7 @@ properties: cci-control-port: true dynamic-power-coefficient: - $ref: '/schemas/types.yaml#/definitions/uint32' + $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 @@ -307,7 +308,7 @@ properties: PM domain provider, must be "psci". qcom,saw: - $ref: '/schemas/types.yaml#/definitions/phandle' + $ref: /schemas/types.yaml#/definitions/phandle description: | Specifies the SAW* node associated with this CPU. @@ -317,7 +318,7 @@ properties: * arm/msm/qcom,saw2.txt qcom,acc: - $ref: '/schemas/types.yaml#/definitions/phandle' + $ref: /schemas/types.yaml#/definitions/phandle description: | Specifies the ACC* node associated with this CPU. @@ -328,7 +329,7 @@ properties: * arm/msm/qcom,kpss-acc.txt rockchip,pmu: - $ref: '/schemas/types.yaml#/definitions/phandle' + $ref: /schemas/types.yaml#/definitions/phandle description: | Specifies the syscon node controlling the cpu core power domains. @@ -338,7 +339,7 @@ properties: the cpu-core power-domains. secondary-boot-reg: - $ref: '/schemas/types.yaml#/definitions/uint32' + $ref: /schemas/types.yaml#/definitions/uint32 description: | Required for systems that have an "enable-method" property value of "brcm,bcm11351-cpu-method", "brcm,bcm23550" or "brcm,bcm-nsp-smp". diff --git a/Documentation/devicetree/bindings/arm/fsl.yaml b/Documentation/devicetree/bindings/arm/fsl.yaml index 15d4110840654a0fc383b3f8fcbbe086ac15b0f5..2510eaa8906dd4a001abddf04b8a26a63aecb414 100644 --- a/Documentation/devicetree/bindings/arm/fsl.yaml +++ b/Documentation/devicetree/bindings/arm/fsl.yaml @@ -726,6 +726,12 @@ properties: - const: dh,imx6ull-dhcor-som - const: fsl,imx6ull + - description: i.MX6ULL DHCOR SoM based Boards + items: + - const: marantec,imx6ull-dhcor-maveo-box + - const: dh,imx6ull-dhcor-som + - const: fsl,imx6ull + - description: i.MX6ULL PHYTEC phyBOARD-Segin items: - enum: @@ -901,6 +907,7 @@ properties: - emtrion,emcon-mx8mm-avari # emCON-MX8MM SoM on Avari Base - fsl,imx8mm-ddr4-evk # i.MX8MM DDR4 EVK Board - fsl,imx8mm-evk # i.MX8MM EVK Board + - fsl,imx8mm-evkb # i.MX8MM EVKB Board - gateworks,imx8mm-gw7904 - gw,imx8mm-gw71xx-0x # i.MX8MM Gateworks Development Kit - gw,imx8mm-gw72xx-0x # i.MX8MM Gateworks Development Kit @@ -918,6 +925,12 @@ properties: - prt,prt8mm # i.MX8MM Protonic PRT8MM Board - const: fsl,imx8mm + - description: Emtop i.MX8MM based Boards + items: + - const: ees,imx8mm-emtop-baseboard # i.MX8MM Emtop SoM on i.MX8M Mini Baseboard V1 + - const: ees,imx8mm-emtop-som # i.MX8MM Emtop SOM-IMX8MMLPD4 module + - const: fsl,imx8mm + - description: Engicam i.Core MX8M Mini SoM based boards items: - enum: @@ -1019,6 +1032,7 @@ properties: - dmo,imx8mp-data-modul-edm-sbc # i.MX8MP eDM SBC - fsl,imx8mp-evk # i.MX8MP EVK Board - gateworks,imx8mp-gw74xx # i.MX8MP Gateworks Board + - gateworks,imx8mp-gw7905-2x # i.MX8MP Gateworks Board - polyhex,imx8mp-debix # Polyhex Debix boards - polyhex,imx8mp-debix-model-a # Polyhex Debix Model A Board - toradex,verdin-imx8mp # Verdin iMX8M Plus Modules diff --git a/Documentation/devicetree/bindings/arm/keystone/ti,sci.yaml b/Documentation/devicetree/bindings/arm/keystone/ti,sci.yaml index 91b96065f7dfc2a2e8e61f4a1ab8b898fff90afe..86b59de7707ee46fb1d9849d728c4d508e5d21a9 100644 --- a/Documentation/devicetree/bindings/arm/keystone/ti,sci.yaml +++ b/Documentation/devicetree/bindings/arm/keystone/ti,sci.yaml @@ -96,8 +96,8 @@ examples: compatible = "ti,k2g-sci"; ti,system-reboot-controller; mbox-names = "rx", "tx"; - mboxes= <&msgmgr 5 2>, - <&msgmgr 0 0>; + mboxes = <&msgmgr 5 2>, + <&msgmgr 0 0>; reg-names = "debug_messages"; reg = <0x02921800 0x800>; }; @@ -107,8 +107,8 @@ examples: compatible = "ti,k2g-sci"; ti,host-id = <12>; mbox-names = "rx", "tx"; - mboxes= <&secure_proxy_main 11>, - <&secure_proxy_main 13>; + mboxes = <&secure_proxy_main 11>, + <&secure_proxy_main 13>; reg-names = "debug_messages"; reg = <0x44083000 0x1000>; diff --git a/Documentation/devicetree/bindings/arm/nuvoton/nuvoton,ma35d1.yaml b/Documentation/devicetree/bindings/arm/nuvoton/nuvoton,ma35d1.yaml new file mode 100644 index 0000000000000000000000000000000000000000..fb190db615250cf125c39ce1144eadb1fadc0fab --- /dev/null +++ b/Documentation/devicetree/bindings/arm/nuvoton/nuvoton,ma35d1.yaml @@ -0,0 +1,30 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/arm/nuvoton/nuvoton,ma35d1.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Nuvoton MA35 series SoC based platforms + +maintainers: + - Jacky Huang + +description: | + Boards with an ARMv8 based Nuvoton MA35 series SoC shall have + the following properties. + +properties: + $nodename: + const: '/' + compatible: + oneOf: + + - description: MA35D1 based boards + items: + - enum: + - nuvoton,ma35d1-iot + - nuvoton,ma35d1-som + - const: nuvoton,ma35d1 + +additionalProperties: true +... diff --git a/Documentation/devicetree/bindings/arm/npcm/npcm.yaml b/Documentation/devicetree/bindings/arm/nuvoton/nuvoton,npcm.yaml similarity index 93% rename from Documentation/devicetree/bindings/arm/npcm/npcm.yaml rename to Documentation/devicetree/bindings/arm/nuvoton/nuvoton,npcm.yaml index 6871483947c51910b0e6d80180d0cec38ecba68b..d386744c881519eb4b12ffb4128f54dea507e16d 100644 --- a/Documentation/devicetree/bindings/arm/npcm/npcm.yaml +++ b/Documentation/devicetree/bindings/arm/nuvoton/nuvoton,npcm.yaml @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause %YAML 1.2 --- -$id: http://devicetree.org/schemas/arm/npcm/npcm.yaml# +$id: http://devicetree.org/schemas/arm/nuvoton/nuvoton,npcm.yaml# $schema: http://devicetree.org/meta-schemas/core.yaml# title: NPCM Platforms diff --git a/Documentation/devicetree/bindings/arm/psci.yaml b/Documentation/devicetree/bindings/arm/psci.yaml index 3a2c908ff28200f004a392238951319ed7ae8595..0c5381e081bd299ec373380faf44a6e52c774b6d 100644 --- a/Documentation/devicetree/bindings/arm/psci.yaml +++ b/Documentation/devicetree/bindings/arm/psci.yaml @@ -100,7 +100,7 @@ properties: patternProperties: "^power-domain-": - $ref: "../power/power-domain.yaml#" + $ref: /schemas/power/power-domain.yaml# type: object description: | diff --git a/Documentation/devicetree/bindings/arm/qcom.yaml b/Documentation/devicetree/bindings/arm/qcom.yaml index d9dd25695c3ddea303784025fdd0e1e032fb6404..450f616774e09706f04fda786ce1a798b14bea6d 100644 --- a/Documentation/devicetree/bindings/arm/qcom.yaml +++ b/Documentation/devicetree/bindings/arm/qcom.yaml @@ -40,6 +40,7 @@ description: | msm8939 msm8953 msm8956 + msm8960 msm8974 msm8976 msm8992 @@ -69,6 +70,7 @@ description: | sdm845 sdx55 sdx65 + sdx75 sm4250 sm6115 sm6115p @@ -85,9 +87,15 @@ description: | The 'board' element must be one of the following strings: adp + ap-al02-c2 + ap-al02-c6 ap-al02-c7 + ap-al02-c8 + ap-al02-c9 ap-mi01.2 + ap-mi01.3 ap-mi01.6 + ap-mi01.9 cdp cp01-c1 dragonboard @@ -191,6 +199,7 @@ properties: - items: - enum: - qcom,msm8960-cdp + - samsung,expressatt - const: qcom,msm8960 - items: @@ -333,7 +342,9 @@ properties: - items: - enum: - qcom,ipq5332-ap-mi01.2 + - qcom,ipq5332-ap-mi01.3 - qcom,ipq5332-ap-mi01.6 + - qcom,ipq5332-ap-mi01.9 - const: qcom,ipq5332 - items: @@ -351,7 +362,11 @@ properties: - items: - enum: + - qcom,ipq9574-ap-al02-c2 + - qcom,ipq9574-ap-al02-c6 - qcom,ipq9574-ap-al02-c7 + - qcom,ipq9574-ap-al02-c8 + - qcom,ipq9574-ap-al02-c9 - const: qcom,ipq9574 - description: Sierra Wireless MangOH Green with WP8548 Module @@ -380,9 +395,9 @@ properties: - qcom,qru1000-idp - const: qcom,qru1000 - - description: Qualcomm Technologies, Inc. SC7180 IDP - items: + - items: - enum: + - acer,aspire1 - qcom,sc7180-idp - const: qcom,sc7180 @@ -819,6 +834,11 @@ properties: - qcom,sdx65-mtp - const: qcom,sdx65 + - items: + - enum: + - qcom,sdx75-idp + - const: qcom,sdx75 + - items: - enum: - qcom,ipq6018-cp01 @@ -882,6 +902,11 @@ properties: - const: qcom,qrb4210 - const: qcom,sm4250 + - items: + - enum: + - fxtec,pro1x + - const: qcom,sm6115 + - items: - enum: - lenovo,j606f @@ -1042,6 +1067,7 @@ allOf: - qcom,sdm845 - qcom,sdx55 - qcom,sdx65 + - qcom,sdx75 - qcom,sm4250 - qcom,sm6115 - qcom,sm6125 diff --git a/Documentation/devicetree/bindings/arm/rockchip.yaml b/Documentation/devicetree/bindings/arm/rockchip.yaml index ec141c937b8b9f41719473ed5f83c23ea79aed75..ecdb72a519cbb586fd5054f3accaa1bc8c61cb86 100644 --- a/Documentation/devicetree/bindings/arm/rockchip.yaml +++ b/Documentation/devicetree/bindings/arm/rockchip.yaml @@ -40,6 +40,11 @@ properties: - const: anbernic,rg353p - const: rockchip,rk3566 + - description: Anbernic RG353PS + items: + - const: anbernic,rg353ps + - const: rockchip,rk3566 + - description: Anbernic RG353V items: - const: anbernic,rg353v @@ -102,6 +107,12 @@ properties: - const: edgeble,neural-compute-module-6a # Edgeble Neural Compute Module 6A SoM - const: rockchip,rk3588 + - description: Edgeble Neural Compute Module 6(Neu6) Model B SoM based boards + items: + - const: edgeble,neural-compute-module-6b-io # Edgeble Neural Compute Module 6B IO Board + - const: edgeble,neural-compute-module-6b # Edgeble Neural Compute Module 6B SoM + - const: rockchip,rk3588 + - description: Elgin RV1108 R1 items: - const: elgin,rv1108-r1 @@ -189,6 +200,7 @@ properties: items: - enum: - friendlyarm,nanopi-r2c + - friendlyarm,nanopi-r2c-plus - friendlyarm,nanopi-r2s - const: rockchip,rk3328 @@ -534,6 +546,11 @@ properties: - const: hugsun,x99 - const: rockchip,rk3399 + - description: Indiedroid Nova SBC + items: + - const: indiedroid,nova + - const: rockchip,rk3588s + - description: Khadas Edge series boards items: - enum: @@ -562,6 +579,13 @@ properties: - const: leez,p710 - const: rockchip,rk3399 + - description: Lunzn FastRhino R66S / R68S + items: + - enum: + - lunzn,fastrhino-r66s + - lunzn,fastrhino-r68s + - const: rockchip,rk3568 + - description: mqmaker MiQi items: - const: mqmaker,miqi diff --git a/Documentation/devicetree/bindings/arm/samsung/samsung-boards.yaml b/Documentation/devicetree/bindings/arm/samsung/samsung-boards.yaml index deb2cf97187188d3a969d8ae1cb48a07504224b5..e3ffd8159ab6c65f9575c60d4a4ca5137ae64e2d 100644 --- a/Documentation/devicetree/bindings/arm/samsung/samsung-boards.yaml +++ b/Documentation/devicetree/bindings/arm/samsung/samsung-boards.yaml @@ -72,6 +72,16 @@ properties: - const: samsung,exynos4210 - const: samsung,exynos4 + - description: Samsung Galaxy Tab3 family boards + items: + - enum: + - samsung,t310 # Samsung Galaxy Tab 3 8.0 WiFi (SM-T310) + - samsung,t311 # Samsung Galaxy Tab 3 8.0 3G (SM-T311) + - samsung,t315 # Samsung Galaxy Tab 3 8.0 LTE (SM-T315) + - const: samsung,tab3 + - const: samsung,exynos4212 + - const: samsung,exynos4 + - description: Exynos4412 based boards items: - enum: diff --git a/Documentation/devicetree/bindings/arm/socionext/synquacer.yaml b/Documentation/devicetree/bindings/arm/socionext/synquacer.yaml new file mode 100644 index 0000000000000000000000000000000000000000..72554a4f1c92e43b69a3c692a1ff8b1ce409ceef --- /dev/null +++ b/Documentation/devicetree/bindings/arm/socionext/synquacer.yaml @@ -0,0 +1,28 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/arm/socionext/synquacer.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Socionext Synquacer platform + +maintainers: + - Masahisa Kojima + - Jassi Brar + +description: + Socionext SC2A11B (Synquacer) SoC based boards + +properties: + $nodename: + const: '/' + compatible: + oneOf: + - items: + - enum: + - socionext,developer-box + - const: socionext,synquacer + +additionalProperties: true + +... diff --git a/Documentation/devicetree/bindings/arm/stm32/st,stm32-syscon.yaml b/Documentation/devicetree/bindings/arm/stm32/st,stm32-syscon.yaml index ad8e51aa01b0cb20cd78a731091e27f7d85fbed1..b63ff591ef8f7a6d55ef5537d5d5fd3c3d1a3a08 100644 --- a/Documentation/devicetree/bindings/arm/stm32/st,stm32-syscon.yaml +++ b/Documentation/devicetree/bindings/arm/stm32/st,stm32-syscon.yaml @@ -15,12 +15,13 @@ properties: oneOf: - items: - enum: - - st,stm32mp157-syscfg - - st,stm32mp151-pwr-mcu - - st,stm32-syscfg - st,stm32-power-config + - st,stm32-syscfg - st,stm32-tamp - st,stm32f4-gcan + - st,stm32mp151-pwr-mcu + - st,stm32mp157-syscfg + - st,stm32mp25-syscfg - const: syscon - items: - const: st,stm32-tamp diff --git a/Documentation/devicetree/bindings/arm/stm32/stm32.yaml b/Documentation/devicetree/bindings/arm/stm32/stm32.yaml index 13e34241145b43c07ae31adc5d4edf5a41d01792..4466b455bffad8465324f3a2d6ff8b56d0ba6585 100644 --- a/Documentation/devicetree/bindings/arm/stm32/stm32.yaml +++ b/Documentation/devicetree/bindings/arm/stm32/stm32.yaml @@ -155,6 +155,18 @@ properties: - const: seeed,stm32mp157c-odyssey-som - const: st,stm32mp157 + - description: Phytec STM32MP1 SoM based Boards + items: + - const: phytec,phycore-stm32mp1-3 + - const: phytec,phycore-stm32mp157c-som + - const: st,stm32mp157 + + - description: ST STM32MP257 based Boards + items: + - enum: + - st,stm32mp257f-ev1 + - const: st,stm32mp257 + additionalProperties: true ... diff --git a/Documentation/devicetree/bindings/arm/sunxi.yaml b/Documentation/devicetree/bindings/arm/sunxi.yaml index 013821f4a7b8d2f3432eaa6e8df5fc9e17ed5cae..ee8fdd2da869aeb92843bd2731cac282dac338c5 100644 --- a/Documentation/devicetree/bindings/arm/sunxi.yaml +++ b/Documentation/devicetree/bindings/arm/sunxi.yaml @@ -305,6 +305,12 @@ properties: - const: allwinner,i12-tvbox - const: allwinner,sun7i-a20 + - description: ICnova A20 ADB4006 + items: + - const: incircuit,icnova-a20-adb4006 + - const: incircuit,icnova-a20 + - const: allwinner,sun7i-a20 + - description: ICNova A20 SWAC items: - const: incircuit,icnova-a20-swac diff --git a/Documentation/devicetree/bindings/arm/tegra.yaml b/Documentation/devicetree/bindings/arm/tegra.yaml index 0df41f5b7e2a377d7cacced5e3d7b58ad7f9c86d..fcf956406168e7100d54070a46b96ea3febe6dca 100644 --- a/Documentation/devicetree/bindings/arm/tegra.yaml +++ b/Documentation/devicetree/bindings/arm/tegra.yaml @@ -167,6 +167,11 @@ properties: - const: nvidia,p3737-0000+p3701-0000 - const: nvidia,p3701-0000 - const: nvidia,tegra234 + - description: NVIDIA IGX Orin Development Kit + items: + - const: nvidia,p3740-0002+p3701-0008 + - const: nvidia,p3701-0008 + - const: nvidia,tegra234 - description: Jetson Orin NX items: - const: nvidia,p3767-0000 @@ -176,5 +181,14 @@ properties: - const: nvidia,p3768-0000+p3767-0000 - const: nvidia,p3767-0000 - const: nvidia,tegra234 + - description: Jetson Orin Nano + items: + - const: nvidia,p3767-0005 + - const: nvidia,tegra234 + - description: Jetson Orin Nano Developer Kit + items: + - const: nvidia,p3768-0000+p3767-0005 + - const: nvidia,p3767-0005 + - const: nvidia,tegra234 additionalProperties: true diff --git a/Documentation/devicetree/bindings/arm/ti/k3.yaml b/Documentation/devicetree/bindings/arm/ti/k3.yaml index e1183f90bb0682a87027a6a13830612a4bc29b64..577eee95c8932b5de0ac58669f992e6eed70bd00 100644 --- a/Documentation/devicetree/bindings/arm/ti/k3.yaml +++ b/Documentation/devicetree/bindings/arm/ti/k3.yaml @@ -25,6 +25,12 @@ properties: - ti,am62a7-sk - const: ti,am62a7 + - description: K3 AM625 SoC PHYTEC phyBOARD-Lyra + items: + - const: phytec,am625-phyboard-lyra-rdk + - const: phytec,am62-phycore-som + - const: ti,am625 + - description: K3 AM625 SoC items: - enum: @@ -33,6 +39,26 @@ properties: - ti,am62-lp-sk - const: ti,am625 + - description: K3 AM62x SoC Toradex Verdin Modules and Carrier Boards + items: + - enum: + - toradex,verdin-am62-nonwifi-dahlia # Verdin AM62 Module on Dahlia + - toradex,verdin-am62-nonwifi-dev # Verdin AM62 Module on Verdin Development Board + - toradex,verdin-am62-nonwifi-yavia # Verdin AM62 Module on Yavia + - const: toradex,verdin-am62-nonwifi # Verdin AM62 Module without Wi-Fi / BT + - const: toradex,verdin-am62 # Verdin AM62 Module + - const: ti,am625 + + - description: K3 AM62x SoC Toradex Verdin Modules and Carrier Boards with Wi-Fi / BT + items: + - enum: + - toradex,verdin-am62-wifi-dahlia # Verdin AM62 Wi-Fi / BT Module on Dahlia + - toradex,verdin-am62-wifi-dev # Verdin AM62 Wi-Fi / BT M. on Verdin Development B. + - toradex,verdin-am62-wifi-yavia # Verdin AM62 Wi-Fi / BT Module on Yavia + - const: toradex,verdin-am62-wifi # Verdin AM62 Wi-Fi / BT Module + - const: toradex,verdin-am62 # Verdin AM62 Module + - const: ti,am625 + - description: K3 AM642 SoC items: - enum: diff --git a/Documentation/devicetree/bindings/arm/xen.txt b/Documentation/devicetree/bindings/arm/xen.txt index 61d77acbeb5ed0da34b992ab7540ca43c25c39d1..f925290d464155b8939af47992ca97ca0cc02d31 100644 --- a/Documentation/devicetree/bindings/arm/xen.txt +++ b/Documentation/devicetree/bindings/arm/xen.txt @@ -56,7 +56,7 @@ hypervisor { }; The format and meaning of the "xen,uefi-*" parameters are similar to those in -Documentation/arm/uefi.rst, which are provided by the regular UEFI stub. However +Documentation/arch/arm/uefi.rst, which are provided by the regular UEFI stub. However they differ because they are provided by the Xen hypervisor, together with a set of UEFI runtime services implemented via hypercalls, see http://xenbits.xen.org/docs/unstable/hypercall/x86_64/include,public,platform.h.html. diff --git a/Documentation/devicetree/bindings/arm/xilinx.yaml b/Documentation/devicetree/bindings/arm/xilinx.yaml index 969cfe6dc43480cfd741ba78560d67fb4bc4c140..f57ed0347894bac7d0b08981766ff719d7236e00 100644 --- a/Documentation/devicetree/bindings/arm/xilinx.yaml +++ b/Documentation/devicetree/bindings/arm/xilinx.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Xilinx Zynq Platforms maintainers: - - Michal Simek + - Michal Simek description: | Xilinx boards with Zynq-7000 SOC or Zynq UltraScale+ MPSoC @@ -61,10 +61,10 @@ properties: - const: xlnx,zynqmp-zc1254 - const: xlnx,zynqmp - - description: Xilinx internal board zc1275 + - description: Xilinx evaluation board zcu1275 items: - - const: xlnx,zynqmp-zc1275-revA - - const: xlnx,zynqmp-zc1275 + - const: xlnx,zynqmp-zcu1275-revA + - const: xlnx,zynqmp-zcu1275 - const: xlnx,zynqmp - description: Xilinx 96boards compatible board zcu100 diff --git a/Documentation/devicetree/bindings/ata/ceva,ahci-1v84.yaml b/Documentation/devicetree/bindings/ata/ceva,ahci-1v84.yaml index 71364c6081ff50d9573102aa48c9bbaa4ea75f1e..b29ce598f9aaea327bcd177dc6bf143ee8693ebf 100644 --- a/Documentation/devicetree/bindings/ata/ceva,ahci-1v84.yaml +++ b/Documentation/devicetree/bindings/ata/ceva,ahci-1v84.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Ceva AHCI SATA Controller maintainers: - - Piyush Mehta + - Piyush Mehta description: | The Ceva SATA controller mostly conforms to the AHCI interface with some diff --git a/Documentation/devicetree/bindings/ata/rockchip,dwc-ahci.yaml b/Documentation/devicetree/bindings/ata/rockchip,dwc-ahci.yaml new file mode 100644 index 0000000000000000000000000000000000000000..b5e5767d86988d3a9b44501e960fd484509a3e82 --- /dev/null +++ b/Documentation/devicetree/bindings/ata/rockchip,dwc-ahci.yaml @@ -0,0 +1,124 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/ata/rockchip,dwc-ahci.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Synopsys DWC AHCI SATA controller for Rockchip devices + +maintainers: + - Serge Semin + +description: + This document defines device tree bindings for the Synopsys DWC + implementation of the AHCI SATA controller found in Rockchip + devices. + +select: + properties: + compatible: + contains: + enum: + - rockchip,rk3568-dwc-ahci + - rockchip,rk3588-dwc-ahci + required: + - compatible + +properties: + compatible: + items: + - enum: + - rockchip,rk3568-dwc-ahci + - rockchip,rk3588-dwc-ahci + - const: snps,dwc-ahci + + ports-implemented: + const: 1 + + sata-port@0: + $ref: /schemas/ata/snps,dwc-ahci-common.yaml#/$defs/dwc-ahci-port + + properties: + reg: + const: 0 + + unevaluatedProperties: false + +patternProperties: + "^sata-port@[1-9a-e]$": false + +required: + - compatible + - reg + - interrupts + - clocks + - clock-names + - ports-implemented + +allOf: + - $ref: snps,dwc-ahci-common.yaml# + - if: + properties: + compatible: + contains: + enum: + - rockchip,rk3588-dwc-ahci + then: + properties: + clocks: + maxItems: 5 + clock-names: + items: + - const: sata + - const: pmalive + - const: rxoob + - const: ref + - const: asic + - if: + properties: + compatible: + contains: + enum: + - rockchip,rk3568-dwc-ahci + then: + properties: + clocks: + maxItems: 3 + clock-names: + items: + - const: sata + - const: pmalive + - const: rxoob + +unevaluatedProperties: false + +examples: + - | + #include + #include + #include + #include + + sata@fe210000 { + compatible = "rockchip,rk3588-dwc-ahci", "snps,dwc-ahci"; + reg = <0xfe210000 0x1000>; + clocks = <&cru ACLK_SATA0>, <&cru CLK_PMALIVE0>, + <&cru CLK_RXOOB0>, <&cru CLK_PIPEPHY0_REF>, + <&cru CLK_PIPEPHY0_PIPE_ASIC_G>; + clock-names = "sata", "pmalive", "rxoob", "ref", "asic"; + interrupts = ; + ports-implemented = <0x1>; + #address-cells = <1>; + #size-cells = <0>; + + sata-port@0 { + reg = <0>; + hba-port-cap = ; + phys = <&combphy0_ps PHY_TYPE_SATA>; + phy-names = "sata-phy"; + snps,rx-ts-max = <32>; + snps,tx-ts-max = <32>; + }; + }; + +... diff --git a/Documentation/devicetree/bindings/ata/snps,dwc-ahci-common.yaml b/Documentation/devicetree/bindings/ata/snps,dwc-ahci-common.yaml index c1457910520bf952784ddaf040f4790c6faece3d..34c5bf65b02d9a301790af884aa2c74afc14a94e 100644 --- a/Documentation/devicetree/bindings/ata/snps,dwc-ahci-common.yaml +++ b/Documentation/devicetree/bindings/ata/snps,dwc-ahci-common.yaml @@ -31,11 +31,11 @@ properties: PM-alive clock, RxOOB detection clock, embedded PHYs reference (Rx/Tx) clock, etc. minItems: 1 - maxItems: 4 + maxItems: 6 clock-names: minItems: 1 - maxItems: 4 + maxItems: 6 items: oneOf: - description: Application APB/AHB/AXI BIU clock @@ -48,6 +48,10 @@ properties: const: pmalive - description: RxOOB detection clock const: rxoob + - description: PHY Transmit Clock + const: asic + - description: PHY Receive Clock + const: rbc - description: SATA Ports reference clock const: ref diff --git a/Documentation/devicetree/bindings/ata/snps,dwc-ahci.yaml b/Documentation/devicetree/bindings/ata/snps,dwc-ahci.yaml index 5afa4b57ce20cb5fc82f408857ac9a40ff9e85e8..4c848fcb5a5d2f56dee36d5bff72fd5c36e7013f 100644 --- a/Documentation/devicetree/bindings/ata/snps,dwc-ahci.yaml +++ b/Documentation/devicetree/bindings/ata/snps,dwc-ahci.yaml @@ -13,6 +13,15 @@ description: This document defines device tree bindings for the generic Synopsys DWC implementation of the AHCI SATA controller. +select: + properties: + compatible: + enum: + - snps,dwc-ahci + - snps,spear-ahci + required: + - compatible + allOf: - $ref: snps,dwc-ahci-common.yaml# @@ -23,10 +32,6 @@ properties: const: snps,dwc-ahci - description: SPEAr1340 AHCI SATA device const: snps,spear-ahci - - description: Rockhip RK3568 AHCI controller - items: - - const: rockchip,rk3568-dwc-ahci - - const: snps,dwc-ahci patternProperties: "^sata-port@[0-9a-e]$": diff --git a/Documentation/devicetree/bindings/auxdisplay/holtek,ht16k33.yaml b/Documentation/devicetree/bindings/auxdisplay/holtek,ht16k33.yaml index 49304a1476abfa182e5d5daae3e07e56d9992251..be95f6b97b41a57a0ff7b1d7980a47be701d1780 100644 --- a/Documentation/devicetree/bindings/auxdisplay/holtek,ht16k33.yaml +++ b/Documentation/devicetree/bindings/auxdisplay/holtek,ht16k33.yaml @@ -40,6 +40,7 @@ properties: linux,keymap: true linux,no-autorepeat: + type: boolean description: Disable keyrepeat default-brightness-level: diff --git a/Documentation/devicetree/bindings/bus/ti-sysc.yaml b/Documentation/devicetree/bindings/bus/ti-sysc.yaml index f089634f9466a5f2b62485b5042bfb78d93ef51a..6d7bca6c138ebca978f9a5e8c7f96c84f733f4b7 100644 --- a/Documentation/devicetree/bindings/bus/ti-sysc.yaml +++ b/Documentation/devicetree/bindings/bus/ti-sysc.yaml @@ -97,7 +97,7 @@ properties: - enum: [ ick, fck, sys_clk ] - items: - const: fck - - enum: [ ick. dbclk, osc, sys_clk, dss_clk, ahclkx ] + - enum: [ ick, dbclk, osc, sys_clk, dss_clk, ahclkx ] - items: - const: fck - const: phy-clk diff --git a/Documentation/devicetree/bindings/clock/amlogic,a1-peripherals-clkc.yaml b/Documentation/devicetree/bindings/clock/amlogic,a1-peripherals-clkc.yaml new file mode 100644 index 0000000000000000000000000000000000000000..6d84cee1bd756ebd15d6c1737eab62530fc27648 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/amlogic,a1-peripherals-clkc.yaml @@ -0,0 +1,73 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/amlogic,a1-peripherals-clkc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Amlogic A1 Peripherals Clock Control Unit + +maintainers: + - Neil Armstrong + - Jerome Brunet + - Jian Hu + - Dmitry Rokosov + +properties: + compatible: + const: amlogic,a1-peripherals-clkc + + '#clock-cells': + const: 1 + + reg: + maxItems: 1 + + clocks: + items: + - description: input fixed pll div2 + - description: input fixed pll div3 + - description: input fixed pll div5 + - description: input fixed pll div7 + - description: input hifi pll + - description: input oscillator (usually at 24MHz) + + clock-names: + items: + - const: fclk_div2 + - const: fclk_div3 + - const: fclk_div5 + - const: fclk_div7 + - const: hifi_pll + - const: xtal + +required: + - compatible + - '#clock-cells' + - reg + - clocks + - clock-names + +additionalProperties: false + +examples: + - | + #include + apb { + #address-cells = <2>; + #size-cells = <2>; + + clock-controller@800 { + compatible = "amlogic,a1-peripherals-clkc"; + reg = <0 0x800 0 0x104>; + #clock-cells = <1>; + clocks = <&clkc_pll CLKID_FCLK_DIV2>, + <&clkc_pll CLKID_FCLK_DIV3>, + <&clkc_pll CLKID_FCLK_DIV5>, + <&clkc_pll CLKID_FCLK_DIV7>, + <&clkc_pll CLKID_HIFI_PLL>, + <&xtal>; + clock-names = "fclk_div2", "fclk_div3", + "fclk_div5", "fclk_div7", + "hifi_pll", "xtal"; + }; + }; diff --git a/Documentation/devicetree/bindings/clock/amlogic,a1-pll-clkc.yaml b/Documentation/devicetree/bindings/clock/amlogic,a1-pll-clkc.yaml new file mode 100644 index 0000000000000000000000000000000000000000..a59b188a8bf554b029cf815dca98ac0efa49f540 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/amlogic,a1-pll-clkc.yaml @@ -0,0 +1,59 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/amlogic,a1-pll-clkc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Amlogic A1 PLL Clock Control Unit + +maintainers: + - Neil Armstrong + - Jerome Brunet + - Jian Hu + - Dmitry Rokosov + +properties: + compatible: + const: amlogic,a1-pll-clkc + + '#clock-cells': + const: 1 + + reg: + maxItems: 1 + + clocks: + items: + - description: input fixpll_in + - description: input hifipll_in + + clock-names: + items: + - const: fixpll_in + - const: hifipll_in + +required: + - compatible + - '#clock-cells' + - reg + - clocks + - clock-names + +additionalProperties: false + +examples: + - | + #include + apb { + #address-cells = <2>; + #size-cells = <2>; + + clock-controller@7c80 { + compatible = "amlogic,a1-pll-clkc"; + reg = <0 0x7c80 0 0x18c>; + #clock-cells = <1>; + clocks = <&clkc_periphs CLKID_FIXPLL_IN>, + <&clkc_periphs CLKID_HIFIPLL_IN>; + clock-names = "fixpll_in", "hifipll_in"; + }; + }; diff --git a/Documentation/devicetree/bindings/clock/at91-clock.txt b/Documentation/devicetree/bindings/clock/at91-clock.txt deleted file mode 100644 index 13f45db3b66d1a107a28f5253f0ec955defa3e52..0000000000000000000000000000000000000000 --- a/Documentation/devicetree/bindings/clock/at91-clock.txt +++ /dev/null @@ -1,58 +0,0 @@ -Device Tree Clock bindings for arch-at91 - -This binding uses the common clock binding[1]. - -[1] Documentation/devicetree/bindings/clock/clock-bindings.txt - -Slow Clock controller: - -Required properties: -- compatible : shall be one of the following: - "atmel,at91sam9x5-sckc", - "atmel,sama5d3-sckc", - "atmel,sama5d4-sckc" or - "microchip,sam9x60-sckc": - at91 SCKC (Slow Clock Controller) -- #clock-cells : shall be 1 for "microchip,sam9x60-sckc" otherwise shall be 0. -- clocks : shall be the input parent clock phandle for the clock. - -Optional properties: -- atmel,osc-bypass : boolean property. Set this when a clock signal is directly - provided on XIN. - -For example: - sckc@fffffe50 { - compatible = "atmel,at91sam9x5-sckc"; - reg = <0xfffffe50 0x4>; - clocks = <&slow_xtal>; - #clock-cells = <0>; - }; - -Power Management Controller (PMC): - -Required properties: -- compatible : shall be "atmel,-pmc", "syscon" or - "microchip,sam9x60-pmc" - can be: at91rm9200, at91sam9260, at91sam9261, - at91sam9263, at91sam9g45, at91sam9n12, at91sam9rl, at91sam9g15, - at91sam9g25, at91sam9g35, at91sam9x25, at91sam9x35, at91sam9x5, - sama5d2, sama5d3 or sama5d4. -- #clock-cells : from common clock binding; shall be set to 2. The first entry - is the type of the clock (core, system, peripheral or generated) and the - second entry its index as provided by the datasheet -- clocks : Must contain an entry for each entry in clock-names. -- clock-names: Must include the following entries: "slow_clk", "main_xtal" - -Optional properties: -- atmel,osc-bypass : boolean property. Set this when a clock signal is directly - provided on XIN. - -For example: - pmc: pmc@f0018000 { - compatible = "atmel,sama5d4-pmc", "syscon"; - reg = <0xf0018000 0x120>; - interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>; - #clock-cells = <2>; - clocks = <&clk32k>, <&main_xtal>; - clock-names = "slow_clk", "main_xtal"; - }; diff --git a/Documentation/devicetree/bindings/clock/atmel,at91rm9200-pmc.yaml b/Documentation/devicetree/bindings/clock/atmel,at91rm9200-pmc.yaml new file mode 100644 index 0000000000000000000000000000000000000000..c1bdcd9058edf0fb4f49df1178fd87665714b63f --- /dev/null +++ b/Documentation/devicetree/bindings/clock/atmel,at91rm9200-pmc.yaml @@ -0,0 +1,154 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/atmel,at91rm9200-pmc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Atmel Power Management Controller (PMC) + +maintainers: + - Claudiu Beznea + +description: + The power management controller optimizes power consumption by controlling all + system and user peripheral clocks. The PMC enables/disables the clock inputs + to many of the peripherals and to the processor. + +properties: + compatible: + oneOf: + - items: + - const: atmel,at91sam9g20-pmc + - const: atmel,at91sam9260-pmc + - const: syscon + - items: + - enum: + - atmel,at91sam9g15-pmc + - atmel,at91sam9g25-pmc + - atmel,at91sam9g35-pmc + - atmel,at91sam9x25-pmc + - atmel,at91sam9x35-pmc + - const: atmel,at91sam9x5-pmc + - const: syscon + - items: + - enum: + - atmel,at91rm9200-pmc + - atmel,at91sam9260-pmc + - atmel,at91sam9g45-pmc + - atmel,at91sam9n12-pmc + - atmel,at91sam9rl-pmc + - atmel,at91sam9x5-pmc + - atmel,sama5d2-pmc + - atmel,sama5d3-pmc + - atmel,sama5d4-pmc + - microchip,sam9x60-pmc + - microchip,sama7g5-pmc + - const: syscon + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + "#clock-cells": + description: | + - 1st cell is the clock type, one of PMC_TYPE_CORE, PMC_TYPE_SYSTEM, + PMC_TYPE_PERIPHERAL, PMC_TYPE_GCK, PMC_TYPE_PROGRAMMABLE (as defined + in ) + - 2nd cell is the clock identifier as defined in + + pmc: clock-controller@f0018000 { + compatible = "atmel,sama5d4-pmc", "syscon"; + reg = <0xf0018000 0x120>; + interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>; + #clock-cells = <2>; + clocks = <&clk32k>, <&main_xtal>; + clock-names = "slow_clk", "main_xtal"; + }; + +... diff --git a/Documentation/devicetree/bindings/clock/atmel,at91sam9x5-sckc.yaml b/Documentation/devicetree/bindings/clock/atmel,at91sam9x5-sckc.yaml new file mode 100644 index 0000000000000000000000000000000000000000..7be29877e6d27f614d2685d24fd29df7d9b7f198 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/atmel,at91sam9x5-sckc.yaml @@ -0,0 +1,70 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/atmel,at91sam9x5-sckc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Atmel Slow Clock Controller (SCKC) + +maintainers: + - Claudiu Beznea + +properties: + compatible: + oneOf: + - enum: + - atmel,at91sam9x5-sckc + - atmel,sama5d3-sckc + - atmel,sama5d4-sckc + - microchip,sam9x60-sckc + - items: + - const: microchip,sama7g5-sckc + - const: microchip,sam9x60-sckc + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + + "#clock-cells": + enum: [0, 1] + + atmel,osc-bypass: + type: boolean + description: set when a clock signal is directly provided on XIN + +required: + - compatible + - reg + - clocks + - "#clock-cells" + +allOf: + - if: + properties: + compatible: + contains: + enum: + - microchip,sam9x60-sckc + then: + properties: + "#clock-cells": + const: 1 + else: + properties: + "#clock-cells": + const: 0 + +additionalProperties: false + +examples: + - | + clk32k: clock-controller@fffffe50 { + compatible = "microchip,sam9x60-sckc"; + reg = <0xfffffe50 0x4>; + clocks = <&slow_xtal>; + #clock-cells = <1>; + }; + +... diff --git a/Documentation/devicetree/bindings/clock/brcm,bcm63268-timer-clocks.yaml b/Documentation/devicetree/bindings/clock/brcm,bcm63268-timer-clocks.yaml index 199818b2fb6dff942bc78933bf3926f8a5e21d70..cd0d763ce2f3e64eb0575ca9189fc88fff23957e 100644 --- a/Documentation/devicetree/bindings/clock/brcm,bcm63268-timer-clocks.yaml +++ b/Documentation/devicetree/bindings/clock/brcm,bcm63268-timer-clocks.yaml @@ -4,7 +4,7 @@ $id: http://devicetree.org/schemas/clock/brcm,bcm63268-timer-clocks.yaml# $schema: http://devicetree.org/meta-schemas/core.yaml# -title: Broadcom BCM63268 Timer Clock and Reset Device Tree Bindings +title: Broadcom BCM63268 Timer Clock and Reset maintainers: - Álvaro Fernández Rojas diff --git a/Documentation/devicetree/bindings/clock/imx8m-clock.yaml b/Documentation/devicetree/bindings/clock/imx8m-clock.yaml index 0dbc1433fedee788aebd7df45dd7e779fc05dc5e..80539f88bc27078a561bd0ef8d3ddb6a78dbb0ba 100644 --- a/Documentation/devicetree/bindings/clock/imx8m-clock.yaml +++ b/Documentation/devicetree/bindings/clock/imx8m-clock.yaml @@ -24,6 +24,9 @@ properties: reg: maxItems: 1 + interrupts: + maxItems: 2 + clocks: minItems: 6 maxItems: 7 diff --git a/Documentation/devicetree/bindings/clock/imx8mp-audiomix.yaml b/Documentation/devicetree/bindings/clock/imx8mp-audiomix.yaml index ff9600474df200338bd7663526ae377a84f0c7c1..0a6dc1a6e122f7cc62c5cc1e5aebc580bc26e036 100644 --- a/Documentation/devicetree/bindings/clock/imx8mp-audiomix.yaml +++ b/Documentation/devicetree/bindings/clock/imx8mp-audiomix.yaml @@ -4,7 +4,7 @@ $id: http://devicetree.org/schemas/clock/imx8mp-audiomix.yaml# $schema: http://devicetree.org/meta-schemas/core.yaml# -title: NXP i.MX8MP AudioMIX Block Control Binding +title: NXP i.MX8MP AudioMIX Block Control maintainers: - Marek Vasut diff --git a/Documentation/devicetree/bindings/clock/ingenic,cgu.yaml b/Documentation/devicetree/bindings/clock/ingenic,cgu.yaml index 9e733b10c392f4998311bebc59a7c8b405e73e2b..509df06b9c9d8dd5d33973b050fe23a0667fc94e 100644 --- a/Documentation/devicetree/bindings/clock/ingenic,cgu.yaml +++ b/Documentation/devicetree/bindings/clock/ingenic,cgu.yaml @@ -98,9 +98,9 @@ required: patternProperties: "^usb-phy@[a-f0-9]+$": - allOf: [ $ref: "../phy/ingenic,phy-usb.yaml#" ] + $ref: /schemas/phy/ingenic,phy-usb.yaml# "^mac-phy-ctrl@[a-f0-9]+$": - allOf: [ $ref: "../net/ingenic,mac.yaml#" ] + $ref: /schemas/net/ingenic,mac.yaml# additionalProperties: false diff --git a/Documentation/devicetree/bindings/clock/mediatek,mtmips-sysc.yaml b/Documentation/devicetree/bindings/clock/mediatek,mtmips-sysc.yaml new file mode 100644 index 0000000000000000000000000000000000000000..ba7ffc5b16a0f974f17db8fbf5d434d3fba580c6 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/mediatek,mtmips-sysc.yaml @@ -0,0 +1,64 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/mediatek,mtmips-sysc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: MTMIPS SoCs System Controller + +maintainers: + - Sergio Paracuellos + +description: | + MediaTek MIPS and Ralink SoCs provides a system controller to allow + to access to system control registers. These registers include clock + and reset related ones so this node is both clock and reset provider + for the rest of the world. + + These SoCs have an XTAL from where the cpu clock is + provided as well as derived clocks for the bus and the peripherals. + +properties: + compatible: + items: + - enum: + - ralink,mt7620-sysc + - ralink,mt7628-sysc + - ralink,mt7688-sysc + - ralink,rt2880-sysc + - ralink,rt3050-sysc + - ralink,rt3052-sysc + - ralink,rt3352-sysc + - ralink,rt3883-sysc + - ralink,rt5350-sysc + - const: syscon + + reg: + maxItems: 1 + + '#clock-cells': + description: + The first cell indicates the clock number. + const: 1 + + '#reset-cells': + description: + The first cell indicates the reset bit within the register. + const: 1 + +required: + - compatible + - reg + - '#clock-cells' + - '#reset-cells' + +additionalProperties: false + +examples: + - | + syscon@0 { + compatible = "ralink,rt5350-sysc", "syscon"; + reg = <0x0 0x100>; + #clock-cells = <1>; + #reset-cells = <1>; + }; diff --git a/Documentation/devicetree/bindings/clock/nuvoton,ma35d1-clk.yaml b/Documentation/devicetree/bindings/clock/nuvoton,ma35d1-clk.yaml new file mode 100644 index 0000000000000000000000000000000000000000..8f0c43683729b36914aa66e1e5f1694fab96c263 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/nuvoton,ma35d1-clk.yaml @@ -0,0 +1,63 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/nuvoton,ma35d1-clk.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Nuvoton MA35D1 Clock Controller Module + +maintainers: + - Chi-Fang Li + - Jacky Huang + +description: | + The MA35D1 clock controller generates clocks for the whole chip, + including system clocks and all peripheral clocks. + + See also: + include/dt-bindings/clock/ma35d1-clk.h + +properties: + compatible: + items: + - const: nuvoton,ma35d1-clk + + reg: + maxItems: 1 + + "#clock-cells": + const: 1 + + clocks: + maxItems: 1 + + nuvoton,pll-mode: + description: + A list of PLL operation mode corresponding to CAPLL, DDRPLL, APLL, + EPLL, and VPLL in sequential. + maxItems: 5 + items: + enum: + - integer + - fractional + - spread-spectrum + $ref: /schemas/types.yaml#/definitions/non-unique-string-array + +required: + - compatible + - reg + - "#clock-cells" + - clocks + +additionalProperties: false + +examples: + - | + + clock-controller@40460200 { + compatible = "nuvoton,ma35d1-clk"; + reg = <0x40460200 0x100>; + #clock-cells = <1>; + clocks = <&clk_hxt>; + }; +... diff --git a/Documentation/devicetree/bindings/clock/qcom,a53pll.yaml b/Documentation/devicetree/bindings/clock/qcom,a53pll.yaml index 659669bf224bdcc23379fd1e73a50cbbc1e4b882..9436266828afaf42f4fd2a05f4ba6d147cd2e72a 100644 --- a/Documentation/devicetree/bindings/clock/qcom,a53pll.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,a53pll.yaml @@ -19,6 +19,7 @@ properties: - qcom,ipq5332-a53pll - qcom,ipq6018-a53pll - qcom,ipq8074-a53pll + - qcom,ipq9574-a73pll - qcom,msm8916-a53pll - qcom,msm8939-a53pll diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc-msm8953.yaml b/Documentation/devicetree/bindings/clock/qcom,gcc-msm8953.yaml new file mode 100644 index 0000000000000000000000000000000000000000..fe9fd4cb185f11bd8a5fb2e23855fbb25d2c9c8c --- /dev/null +++ b/Documentation/devicetree/bindings/clock/qcom,gcc-msm8953.yaml @@ -0,0 +1,73 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/qcom,gcc-msm8953.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm Global Clock & Reset Controller on MSM8953 + +maintainers: + - Adam Skladowski + - Sireesh Kodali + +description: | + Qualcomm global clock control module provides the clocks, resets and power + domains on MSM8953. + + See also: include/dt-bindings/clock/qcom,gcc-msm8953.h + +properties: + compatible: + const: qcom,gcc-msm8953 + + clocks: + items: + - description: Board XO source + - description: Sleep clock source + - description: Byte clock from DSI PHY0 + - description: Pixel clock from DSI PHY0 + - description: Byte clock from DSI PHY1 + - description: Pixel clock from DSI PHY1 + + clock-names: + items: + - const: xo + - const: sleep + - const: dsi0pll + - const: dsi0pllbyte + - const: dsi1pll + - const: dsi1pllbyte + +required: + - compatible + - clocks + - clock-names + +allOf: + - $ref: qcom,gcc.yaml# + +unevaluatedProperties: false + +examples: + - | + #include + + clock-controller@1800000 { + compatible = "qcom,gcc-msm8953"; + reg = <0x01800000 0x80000>; + clocks = <&rpmcc RPM_SMD_XO_CLK_SRC>, + <&sleep_clk>, + <&dsi0_phy 1>, + <&dsi0_phy 0>, + <&dsi1_phy 1>, + <&dsi1_phy 0>; + clock-names = "xo", + "sleep", + "dsi0pll", + "dsi0pllbyte", + "dsi1pll", + "dsi1pllbyte"; + #clock-cells = <1>; + #reset-cells = <1>; + #power-domain-cells = <1>; + }; diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc-other.yaml b/Documentation/devicetree/bindings/clock/qcom,gcc-other.yaml index ae01e7749534244ac4d8a8fed8c92371a0b56f4d..ba969e7a57bfd19d6d5cb9a6d2ac5272b590a71a 100644 --- a/Documentation/devicetree/bindings/clock/qcom,gcc-other.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,gcc-other.yaml @@ -30,7 +30,6 @@ properties: enum: - qcom,gcc-ipq6018 - qcom,gcc-mdm9607 - - qcom,gcc-msm8953 - qcom,gcc-mdm9615 required: diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc-sc7180.yaml b/Documentation/devicetree/bindings/clock/qcom,gcc-sc7180.yaml index 06dce0c6b7d029aa72a4cdcb5311d9f945bf4835..8bf9b6f495505e5f92688d63df1da297df100475 100644 --- a/Documentation/devicetree/bindings/clock/qcom,gcc-sc7180.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,gcc-sc7180.yaml @@ -32,6 +32,10 @@ properties: - const: bi_tcxo_ao - const: sleep_clk + power-domains: + items: + - description: CX domain + required: - compatible - clocks @@ -45,6 +49,8 @@ unevaluatedProperties: false examples: - | #include + #include + clock-controller@100000 { compatible = "qcom,gcc-sc7180"; reg = <0x00100000 0x1f0000>; @@ -52,6 +58,7 @@ examples: <&rpmhcc RPMH_CXO_CLK_A>, <&sleep_clk>; clock-names = "bi_tcxo", "bi_tcxo_ao", "sleep_clk"; + power-domains = <&rpmhpd SC7180_CX>; #clock-cells = <1>; #reset-cells = <1>; #power-domain-cells = <1>; diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc-sc7280.yaml b/Documentation/devicetree/bindings/clock/qcom,gcc-sc7280.yaml index 947b47168cecc0accd4fb9b1329fd1e1960e0ee8..ff0b18bbb0fcbf48098eceb8604e2d8169975582 100644 --- a/Documentation/devicetree/bindings/clock/qcom,gcc-sc7280.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,gcc-sc7280.yaml @@ -43,6 +43,10 @@ properties: - const: ufs_phy_tx_symbol_0_clk - const: usb3_phy_wrapper_gcc_usb30_pipe_clk + power-domains: + items: + - description: CX domain + required: - compatible - clocks @@ -56,6 +60,8 @@ unevaluatedProperties: false examples: - | #include + #include + clock-controller@100000 { compatible = "qcom,gcc-sc7280"; reg = <0x00100000 0x1f0000>; @@ -71,6 +77,7 @@ examples: "pcie_1_pipe_clk", "ufs_phy_rx_symbol_0_clk", "ufs_phy_rx_symbol_1_clk", "ufs_phy_tx_symbol_0_clk", "usb3_phy_wrapper_gcc_usb30_pipe_clk"; + power-domains = <&rpmhpd SC7280_CX>; #clock-cells = <1>; #reset-cells = <1>; #power-domain-cells = <1>; diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc-sm8250.yaml b/Documentation/devicetree/bindings/clock/qcom,gcc-sm8250.yaml index b752542ee20caf65212c2a395f1e384bb65d45a2..ead6665b9a45df011f105e7926553015bfaea8cc 100644 --- a/Documentation/devicetree/bindings/clock/qcom,gcc-sm8250.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,gcc-sm8250.yaml @@ -23,11 +23,13 @@ properties: clocks: items: - description: Board XO source + - description: Board active XO source - description: Sleep clock source clock-names: items: - const: bi_tcxo + - const: bi_tcxo_ao - const: sleep_clk required: @@ -47,8 +49,9 @@ examples: compatible = "qcom,gcc-sm8250"; reg = <0x00100000 0x1f0000>; clocks = <&rpmhcc RPMH_CXO_CLK>, + <&rpmhcc RPMH_CXO_CLK_A>, <&sleep_clk>; - clock-names = "bi_tcxo", "sleep_clk"; + clock-names = "bi_tcxo", "bi_tcxo_ao", "sleep_clk"; #clock-cells = <1>; #reset-cells = <1>; #power-domain-cells = <1>; diff --git a/Documentation/devicetree/bindings/clock/qcom,gpucc.yaml b/Documentation/devicetree/bindings/clock/qcom,gpucc.yaml index 1e3dc9deded96a8c328782deea0c4d075af9611f..a00216b3b15a3e0182335970a457b6bb6609ea74 100644 --- a/Documentation/devicetree/bindings/clock/qcom,gpucc.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,gpucc.yaml @@ -50,6 +50,9 @@ properties: - const: gcc_gpu_gpll0_clk_src - const: gcc_gpu_gpll0_div_clk_src + power-domains: + maxItems: 1 + '#clock-cells': const: 1 diff --git a/Documentation/devicetree/bindings/clock/qcom,ipq9574-gcc.yaml b/Documentation/devicetree/bindings/clock/qcom,ipq9574-gcc.yaml index afc68eb9d7cc24c6ae06e1a5570922a666733aed..944a0ea79cd6b5243d11190d2c1629372f03b789 100644 --- a/Documentation/devicetree/bindings/clock/qcom,ipq9574-gcc.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,ipq9574-gcc.yaml @@ -7,6 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Qualcomm Global Clock & Reset Controller on IPQ9574 maintainers: + - Bjorn Andersson - Anusha Rao description: | diff --git a/Documentation/devicetree/bindings/clock/qcom,mmcc.yaml b/Documentation/devicetree/bindings/clock/qcom,mmcc.yaml index acf0c923c24f85a0b2d6df8e736e4f84bb29538d..422f5776a7711eb374c771ed44bdb8702c396236 100644 --- a/Documentation/devicetree/bindings/clock/qcom,mmcc.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,mmcc.yaml @@ -31,11 +31,11 @@ properties: - qcom,mmcc-sdm660 clocks: - minItems: 8 + minItems: 7 maxItems: 13 clock-names: - minItems: 8 + minItems: 7 maxItems: 13 '#clock-cells': @@ -99,6 +99,34 @@ allOf: - const: dsi2pllbyte - const: hdmipll + - if: + properties: + compatible: + contains: + enum: + - qcom,mmcc-msm8226 + then: + properties: + clocks: + items: + - description: Board XO source + - description: MMSS GPLL0 voted clock + - description: GPLL0 voted clock + - description: GPLL1 voted clock + - description: GFX3D clock source + - description: DSI phy instance 0 dsi clock + - description: DSI phy instance 0 byte clock + + clock-names: + items: + - const: xo + - const: mmss_gpll0_vote + - const: gpll0_vote + - const: gpll1_vote + - const: gfx3d_clk_src + - const: dsi0pll + - const: dsi0pllbyte + - if: properties: compatible: diff --git a/Documentation/devicetree/bindings/clock/qcom,rpmhcc.yaml b/Documentation/devicetree/bindings/clock/qcom,rpmhcc.yaml index d5a250b7c2af37c04771259be84b0c53e5dcdf4e..267cf8c268233ea6f1144064f0b20c2863031f6d 100644 --- a/Documentation/devicetree/bindings/clock/qcom,rpmhcc.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,rpmhcc.yaml @@ -27,6 +27,7 @@ properties: - qcom,sdm845-rpmh-clk - qcom,sdx55-rpmh-clk - qcom,sdx65-rpmh-clk + - qcom,sdx75-rpmh-clk - qcom,sm6350-rpmh-clk - qcom,sm8150-rpmh-clk - qcom,sm8250-rpmh-clk diff --git a/Documentation/devicetree/bindings/clock/qcom,sc8280xp-lpasscc.yaml b/Documentation/devicetree/bindings/clock/qcom,sc8280xp-lpasscc.yaml new file mode 100644 index 0000000000000000000000000000000000000000..3326dcd6766c3407aeb7d3028bc95e5392653066 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/qcom,sc8280xp-lpasscc.yaml @@ -0,0 +1,60 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/qcom,sc8280xp-lpasscc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm LPASS Core & Audio Clock Controller on SC8280XP + +maintainers: + - Srinivas Kandagatla + +description: | + Qualcomm LPASS core and audio clock control module provides the clocks, + and reset on SC8280XP. + + See also:: + include/dt-bindings/clock/qcom,lpasscc-sc8280xp.h + +properties: + compatible: + enum: + - qcom,sc8280xp-lpassaudiocc + - qcom,sc8280xp-lpasscc + + reg: + maxItems: 1 + + '#clock-cells': + const: 1 + + '#reset-cells': + const: 1 + +required: + - compatible + - reg + - '#clock-cells' + - '#reset-cells' + +additionalProperties: false + +examples: + - | + #include + lpass_audiocc: clock-controller@32a9000 { + compatible = "qcom,sc8280xp-lpassaudiocc"; + reg = <0x032a9000 0x1000>; + #clock-cells = <1>; + #reset-cells = <1>; + }; + + - | + #include + lpasscc: clock-controller@33e0000 { + compatible = "qcom,sc8280xp-lpasscc"; + reg = <0x033e0000 0x12000>; + #clock-cells = <1>; + #reset-cells = <1>; + }; +... diff --git a/Documentation/devicetree/bindings/clock/qcom,sdx75-gcc.yaml b/Documentation/devicetree/bindings/clock/qcom,sdx75-gcc.yaml new file mode 100644 index 0000000000000000000000000000000000000000..98921fa236b18e54aa6f0a8655dac896e0939e40 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/qcom,sdx75-gcc.yaml @@ -0,0 +1,65 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/qcom,sdx75-gcc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm Global Clock & Reset Controller on SDX75 + +maintainers: + - Imran Shaik + - Taniya Das + +description: | + Qualcomm global clock control module provides the clocks, resets and power + domains on SDX75 + + See also:: include/dt-bindings/clock/qcom,sdx75-gcc.h + +properties: + compatible: + const: qcom,sdx75-gcc + + clocks: + items: + - description: Board XO source + - description: Sleep clock source + - description: EMAC0 sgmiiphy mac rclk source + - description: EMAC0 sgmiiphy mac tclk source + - description: EMAC0 sgmiiphy rclk source + - description: EMAC0 sgmiiphy tclk source + - description: EMAC1 sgmiiphy mac rclk source + - description: EMAC1 sgmiiphy mac tclk source + - description: EMAC1 sgmiiphy rclk source + - description: EMAC1 sgmiiphy tclk source + - description: PCIE20 phy aux clock source + - description: PCIE_1 Pipe clock source + - description: PCIE_2 Pipe clock source + - description: PCIE Pipe clock source + - description: USB3 phy wrapper pipe clock source + +required: + - compatible + - clocks + +allOf: + - $ref: qcom,gcc.yaml# + +unevaluatedProperties: false + +examples: + - | + #include + clock-controller@80000 { + compatible = "qcom,sdx75-gcc"; + reg = <0x80000 0x1f7400>; + clocks = <&rpmhcc RPMH_CXO_CLK>, <&sleep_clk>, <&emac0_sgmiiphy_mac_rclk>, + <&emac0_sgmiiphy_mac_tclk>, <&emac0_sgmiiphy_rclk>, <&emac0_sgmiiphy_tclk>, + <&emac1_sgmiiphy_mac_rclk>, <&emac1_sgmiiphy_mac_tclk>, <&emac1_sgmiiphy_rclk>, + <&emac1_sgmiiphy_tclk>, <&pcie20_phy_aux_clk>, <&pcie_1_pipe_clk>, + <&pcie_2_pipe_clk>, <&pcie_pipe_clk>, <&usb3_phy_wrapper_gcc_usb30_pipe_clk>; + #clock-cells = <1>; + #reset-cells = <1>; + #power-domain-cells = <1>; + }; +... diff --git a/Documentation/devicetree/bindings/clock/qcom,sm6375-gpucc.yaml b/Documentation/devicetree/bindings/clock/qcom,sm6375-gpucc.yaml index b480ead5bd6950649bb57ce15e260ea739a3000b..cf4cad76f6c9517ac244d72297c90cd747a8b24e 100644 --- a/Documentation/devicetree/bindings/clock/qcom,sm6375-gpucc.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,sm6375-gpucc.yaml @@ -27,9 +27,21 @@ properties: - description: GPLL0 div branch source - description: SNoC DVM GFX source + power-domains: + description: + A phandle and PM domain specifier for the VDD_GX power rail + maxItems: 1 + + required-opps: + description: + A phandle to an OPP node describing required VDD_GX performance point. + maxItems: 1 + required: - compatible - clocks + - power-domains + - required-opps allOf: - $ref: qcom,gcc.yaml# @@ -40,6 +52,7 @@ examples: - | #include #include + #include soc { #address-cells = <2>; @@ -52,6 +65,8 @@ examples: <&gcc GCC_GPU_GPLL0_CLK_SRC>, <&gcc GCC_GPU_GPLL0_DIV_CLK_SRC>, <&gcc GCC_GPU_SNOC_DVM_GFX_CLK>; + power-domains = <&rpmpd SM6375_VDDGX>; + required-opps = <&rpmpd_opp_low_svs>; #clock-cells = <1>; #reset-cells = <1>; #power-domain-cells = <1>; diff --git a/Documentation/devicetree/bindings/clock/qcom,sm8350-videocc.yaml b/Documentation/devicetree/bindings/clock/qcom,sm8350-videocc.yaml new file mode 100644 index 0000000000000000000000000000000000000000..23505c8c3dbd9a33d5b5bf1bb6837d1b45202fc4 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/qcom,sm8350-videocc.yaml @@ -0,0 +1,68 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/qcom,sm8350-videocc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm SM8350 Video Clock & Reset Controller + +maintainers: + - Konrad Dybcio + +description: | + Qualcomm video clock control module provides the clocks, resets and power + domains on Qualcomm SoCs. + + See also:: + include/dt-bindings/clock/qcom,videocc-sm8350.h + include/dt-bindings/reset/qcom,videocc-sm8350.h + +properties: + compatible: + const: qcom,sm8350-videocc + + clocks: + items: + - description: Board XO source + - description: Board active XO source + - description: Board sleep clock + + power-domains: + description: + A phandle and PM domain specifier for the MMCX power domain. + maxItems: 1 + + required-opps: + description: + A phandle to an OPP node describing required MMCX performance point. + maxItems: 1 + +required: + - compatible + - clocks + - power-domains + - required-opps + +allOf: + - $ref: qcom,gcc.yaml# + +unevaluatedProperties: false + +examples: + - | + #include + #include + + clock-controller@abf0000 { + compatible = "qcom,sm8350-videocc"; + reg = <0x0abf0000 0x10000>; + clocks = <&rpmhcc RPMH_CXO_CLK>, + <&rpmhcc RPMH_CXO_CLK_A>, + <&sleep_clk>; + power-domains = <&rpmhpd SM8350_MMCX>; + required-opps = <&rpmhpd_opp_low_svs>; + #clock-cells = <1>; + #reset-cells = <1>; + #power-domain-cells = <1>; + }; +... diff --git a/Documentation/devicetree/bindings/clock/qcom,sm8450-gpucc.yaml b/Documentation/devicetree/bindings/clock/qcom,sm8450-gpucc.yaml new file mode 100644 index 0000000000000000000000000000000000000000..2320be920a5f76d9675de6038971d13eabafd1f4 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/qcom,sm8450-gpucc.yaml @@ -0,0 +1,75 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/qcom,sm8450-gpucc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm Graphics Clock & Reset Controller on SM8450 + +maintainers: + - Konrad Dybcio + +description: | + Qualcomm graphics clock control module provides the clocks, resets and power + domains on Qualcomm SoCs. + + See also:: + include/dt-bindings/clock/qcom,sm8450-gpucc.h + include/dt-bindings/clock/qcom,sm8550-gpucc.h + include/dt-bindings/reset/qcom,sm8450-gpucc.h + +properties: + compatible: + enum: + - qcom,sm8450-gpucc + - qcom,sm8550-gpucc + + clocks: + items: + - description: Board XO source + - description: GPLL0 main branch source + - description: GPLL0 div branch source + + '#clock-cells': + const: 1 + + '#reset-cells': + const: 1 + + '#power-domain-cells': + const: 1 + + reg: + maxItems: 1 + +required: + - compatible + - reg + - clocks + - '#clock-cells' + - '#reset-cells' + - '#power-domain-cells' + +additionalProperties: false + +examples: + - | + #include + #include + + soc { + #address-cells = <2>; + #size-cells = <2>; + + clock-controller@3d90000 { + compatible = "qcom,sm8450-gpucc"; + reg = <0 0x03d90000 0 0xa000>; + clocks = <&rpmhcc RPMH_CXO_CLK>, + <&gcc GCC_GPU_GPLL0_CLK_SRC>, + <&gcc GCC_GPU_GPLL0_DIV_CLK_SRC>; + #clock-cells = <1>; + #reset-cells = <1>; + #power-domain-cells = <1>; + }; + }; +... diff --git a/Documentation/devicetree/bindings/clock/qcom,sm8450-videocc.yaml b/Documentation/devicetree/bindings/clock/qcom,sm8450-videocc.yaml new file mode 100644 index 0000000000000000000000000000000000000000..f1c6dd50f18412cb187559613f5e0c1c5600953f --- /dev/null +++ b/Documentation/devicetree/bindings/clock/qcom,sm8450-videocc.yaml @@ -0,0 +1,79 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/qcom,sm8450-videocc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm Video Clock & Reset Controller on SM8450 + +maintainers: + - Taniya Das + +description: | + Qualcomm video clock control module provides the clocks, resets and power + domains on SM8450. + + See also:: include/dt-bindings/clock/qcom,videocc-sm8450.h + +properties: + compatible: + enum: + - qcom,sm8450-videocc + - qcom,sm8550-videocc + + reg: + maxItems: 1 + + clocks: + items: + - description: Board XO source + - description: Video AHB clock from GCC + + power-domains: + maxItems: 1 + description: + MMCX power domain. + + required-opps: + maxItems: 1 + description: + A phandle to an OPP node describing required MMCX performance point. + + '#clock-cells': + const: 1 + + '#reset-cells': + const: 1 + + '#power-domain-cells': + const: 1 + +required: + - compatible + - reg + - clocks + - power-domains + - required-opps + - '#clock-cells' + - '#reset-cells' + - '#power-domain-cells' + +additionalProperties: false + +examples: + - | + #include + #include + #include + videocc: clock-controller@aaf0000 { + compatible = "qcom,sm8450-videocc"; + reg = <0x0aaf0000 0x10000>; + clocks = <&rpmhcc RPMH_CXO_CLK>, + <&gcc GCC_VIDEO_AHB_CLK>; + power-domains = <&rpmhpd SM8450_MMCX>; + required-opps = <&rpmhpd_opp_low_svs>; + #clock-cells = <1>; + #reset-cells = <1>; + #power-domain-cells = <1>; + }; +... diff --git a/Documentation/devicetree/bindings/clock/renesas,r9a06g032-sysctrl.yaml b/Documentation/devicetree/bindings/clock/renesas,r9a06g032-sysctrl.yaml index 99686085f751362552951c2cfafb2a71970ae12b..26d94cedc871d539b6141c8a6587068ec0d67f90 100644 --- a/Documentation/devicetree/bindings/clock/renesas,r9a06g032-sysctrl.yaml +++ b/Documentation/devicetree/bindings/clock/renesas,r9a06g032-sysctrl.yaml @@ -48,7 +48,7 @@ properties: patternProperties: "^dma-router@[a-f0-9]+$": type: object - $ref: "../dma/renesas,rzn1-dmamux.yaml#" + $ref: /schemas/dma/renesas,rzn1-dmamux.yaml# required: - compatible diff --git a/Documentation/devicetree/bindings/clock/samsung,exynos-clock.yaml b/Documentation/devicetree/bindings/clock/samsung,exynos-clock.yaml index 0589a63e273a126935eaffb54b0fffd6605380a6..a36781a455b65adc7a0b7abe1919cfd5de3c2ea6 100644 --- a/Documentation/devicetree/bindings/clock/samsung,exynos-clock.yaml +++ b/Documentation/devicetree/bindings/clock/samsung,exynos-clock.yaml @@ -24,6 +24,7 @@ properties: - samsung,exynos3250-cmu-dmc - samsung,exynos3250-cmu-isp - samsung,exynos4210-clock + - samsung,exynos4212-clock - samsung,exynos4412-clock - samsung,exynos5250-clock - items: diff --git a/Documentation/devicetree/bindings/clock/ti,am62-audio-refclk.yaml b/Documentation/devicetree/bindings/clock/ti,am62-audio-refclk.yaml new file mode 100644 index 0000000000000000000000000000000000000000..b2e40bd39a3af4d0498f455269b805986ab49a84 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/ti,am62-audio-refclk.yaml @@ -0,0 +1,43 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/ti,am62-audio-refclk.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: TI Audio Reference Clock + +maintainers: + - Jai Luthra + +properties: + compatible: + items: + - const: ti,am62-audio-refclk + + reg: + maxItems: 1 + + "#clock-cells": + const: 0 + + clocks: + maxItems: 1 + +required: + - compatible + - reg + - "#clock-cells" + - clocks + +additionalProperties: false + +examples: + - | + audio_refclk0: clock@82e0 { + compatible = "ti,am62-audio-refclk"; + reg = <0x82e0 0x4>; + clocks = <&k3_clks 157 0>; + assigned-clocks = <&k3_clks 157 0>; + assigned-clock-parents = <&k3_clks 157 8>; + #clock-cells = <0>; + }; diff --git a/Documentation/devicetree/bindings/clock/ti,am654-ehrpwm-tbclk.yaml b/Documentation/devicetree/bindings/clock/ti,am654-ehrpwm-tbclk.yaml index 66765116aff5d847f07ebc0e8106ef466a8a29c2..64b8bce5962c2bc35134c2c4b0cd13b02abcc406 100644 --- a/Documentation/devicetree/bindings/clock/ti,am654-ehrpwm-tbclk.yaml +++ b/Documentation/devicetree/bindings/clock/ti,am654-ehrpwm-tbclk.yaml @@ -16,7 +16,6 @@ properties: - ti,am654-ehrpwm-tbclk - ti,am64-epwm-tbclk - ti,am62-epwm-tbclk - - const: syscon "#clock-cells": const: 1 @@ -33,8 +32,8 @@ additionalProperties: false examples: - | - ehrpwm_tbclk: syscon@4140 { - compatible = "ti,am654-ehrpwm-tbclk", "syscon"; + ehrpwm_tbclk: clock@4140 { + compatible = "ti,am654-ehrpwm-tbclk"; reg = <0x4140 0x18>; #clock-cells = <1>; }; diff --git a/Documentation/devicetree/bindings/clock/xlnx,clocking-wizard.yaml b/Documentation/devicetree/bindings/clock/xlnx,clocking-wizard.yaml index c1f04830a83297d2e5ec70c133b324fe0a6d1cbc..02bd556bd91a66ab55ef3dc0208a79f3c18f6615 100644 --- a/Documentation/devicetree/bindings/clock/xlnx,clocking-wizard.yaml +++ b/Documentation/devicetree/bindings/clock/xlnx,clocking-wizard.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Xilinx clocking wizard maintainers: - - Shubhrajyoti Datta + - Shubhrajyoti Datta description: The clocking wizard is a soft ip clocking block of Xilinx versal. It diff --git a/Documentation/devicetree/bindings/clock/xlnx,versal-clk.yaml b/Documentation/devicetree/bindings/clock/xlnx,versal-clk.yaml index 229af98b1d3054ae78c8525823188f7386d4789e..5cbb34d0b61b3951bd318648aaf66f1f4d969272 100644 --- a/Documentation/devicetree/bindings/clock/xlnx,versal-clk.yaml +++ b/Documentation/devicetree/bindings/clock/xlnx,versal-clk.yaml @@ -7,9 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Xilinx Versal clock controller maintainers: - - Michal Simek - - Jolly Shah - - Rajan Vaja + - Michal Simek description: | The clock controller is a hardware block of Xilinx versal clock tree. It diff --git a/Documentation/devicetree/bindings/connector/usb-connector.yaml b/Documentation/devicetree/bindings/connector/usb-connector.yaml index ae515651fc6bb96857a764bcab06c3b546271ebb..1c4d3eb877635e005ed2607e3841ba611020fa73 100644 --- a/Documentation/devicetree/bindings/connector/usb-connector.yaml +++ b/Documentation/devicetree/bindings/connector/usb-connector.yaml @@ -168,6 +168,13 @@ properties: offer the power, Capability Mismatch is set. Required for power sink and power dual role. + port: + $ref: /schemas/graph.yaml#/properties/port + description: OF graph bindings modeling a data bus to the connector, e.g. + there is a single High Speed (HS) port present in this connector. If there + is more than one bus (several port, with 'reg' property), they can be grouped + under 'ports'. + ports: $ref: /schemas/graph.yaml#/properties/ports description: OF graph bindings modeling any data bus to the connector @@ -322,6 +329,19 @@ examples: }; }; + # USB-C connector attached to SoC with a single High-Speed controller + - | + connector { + compatible = "usb-c-connector"; + label = "USB-C"; + + port { + high_speed_ep: endpoint { + remote-endpoint = <&usb_hs_ep>; + }; + }; + }; + # USB-C connector attached to SoC and USB3 typec port controller(hd3ss3220) # with SS 2:1 MUX. HS lines routed to SoC, SS lines routed to the MUX and # the output of MUX is connected to the SoC. diff --git a/Documentation/devicetree/bindings/cpu/idle-states.yaml b/Documentation/devicetree/bindings/cpu/idle-states.yaml index b8cc826c95013dcecd5eb63e1f1636e2ddd314c2..b3a5356f9916e92bb6a04f10c94fb136699c7239 100644 --- a/Documentation/devicetree/bindings/cpu/idle-states.yaml +++ b/Documentation/devicetree/bindings/cpu/idle-states.yaml @@ -259,7 +259,7 @@ description: |+ http://infocenter.arm.com/help/index.jsp [5] ARM Linux Kernel documentation - Booting AArch64 Linux - Documentation/arm64/booting.rst + Documentation/arch/arm64/booting.rst [6] RISC-V Linux Kernel documentation - CPUs bindings Documentation/devicetree/bindings/riscv/cpus.yaml diff --git a/Documentation/devicetree/bindings/cpufreq/qcom-cpufreq-nvmem.yaml b/Documentation/devicetree/bindings/cpufreq/qcom-cpufreq-nvmem.yaml index 6f5e7904181f1d31309f78fbfbebf4ba4c65a1c5..7e1bb992ce9096efaf6f00bd06d2b9c88d6cf942 100644 --- a/Documentation/devicetree/bindings/cpufreq/qcom-cpufreq-nvmem.yaml +++ b/Documentation/devicetree/bindings/cpufreq/qcom-cpufreq-nvmem.yaml @@ -28,6 +28,7 @@ select: - qcom,apq8064 - qcom,apq8096 - qcom,ipq8064 + - qcom,ipq8074 - qcom,msm8939 - qcom,msm8960 - qcom,msm8974 diff --git a/Documentation/devicetree/bindings/crypto/amlogic,gxl-crypto.yaml b/Documentation/devicetree/bindings/crypto/amlogic,gxl-crypto.yaml index ecf98a9e72b287dcc28e8a31dd8d08468a750ad1..948e11ebe4eeb9f8fca60705a47410cfd81b9f1c 100644 --- a/Documentation/devicetree/bindings/crypto/amlogic,gxl-crypto.yaml +++ b/Documentation/devicetree/bindings/crypto/amlogic,gxl-crypto.yaml @@ -19,8 +19,8 @@ properties: interrupts: items: - - description: "Interrupt for flow 0" - - description: "Interrupt for flow 1" + - description: Interrupt for flow 0 + - description: Interrupt for flow 1 clocks: maxItems: 1 diff --git a/Documentation/devicetree/bindings/crypto/fsl,sec-v4.0-mon.yaml b/Documentation/devicetree/bindings/crypto/fsl,sec-v4.0-mon.yaml index 286dffa0671b34808d22cf0866018fafad84619e..e879bc0be8e221266bf8a5fb46f66fad4512b791 100644 --- a/Documentation/devicetree/bindings/crypto/fsl,sec-v4.0-mon.yaml +++ b/Documentation/devicetree/bindings/crypto/fsl,sec-v4.0-mon.yaml @@ -103,6 +103,12 @@ properties: wakeup-source: true linux,keycode: + $ref: /schemas/types.yaml#/definitions/uint32 + default: 116 + deprecated: true + + linux,keycodes: + maxItems: 1 default: 116 required: diff --git a/Documentation/devicetree/bindings/crypto/fsl-dcp.yaml b/Documentation/devicetree/bindings/crypto/fsl-dcp.yaml index 99be01539fcd07c9d6de36ee4b3f3ebdcc5d25a1..8dd36c2f76fd270cc86cb105a591f9a5ee552c84 100644 --- a/Documentation/devicetree/bindings/crypto/fsl-dcp.yaml +++ b/Documentation/devicetree/bindings/crypto/fsl-dcp.yaml @@ -11,9 +11,15 @@ maintainers: properties: compatible: - enum: - - fsl,imx23-dcp - - fsl,imx28-dcp + oneOf: + - enum: + - fsl,imx23-dcp + - fsl,imx28-dcp + - items: + - enum: + - fsl,imx6sl-dcp + - fsl,imx6ull-dcp + - const: fsl,imx28-dcp reg: maxItems: 1 diff --git a/Documentation/devicetree/bindings/crypto/intel,ixp4xx-crypto.yaml b/Documentation/devicetree/bindings/crypto/intel,ixp4xx-crypto.yaml index e0fe63957888eaf8d626bfa1446a2b60948d1100..a4006237aa89fd6f0725597c5a9c59a5d910826b 100644 --- a/Documentation/devicetree/bindings/crypto/intel,ixp4xx-crypto.yaml +++ b/Documentation/devicetree/bindings/crypto/intel,ixp4xx-crypto.yaml @@ -2,8 +2,8 @@ # Copyright 2018 Linaro Ltd. %YAML 1.2 --- -$id: "http://devicetree.org/schemas/crypto/intel,ixp4xx-crypto.yaml#" -$schema: "http://devicetree.org/meta-schemas/core.yaml#" +$id: http://devicetree.org/schemas/crypto/intel,ixp4xx-crypto.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# title: Intel IXP4xx cryptographic engine @@ -21,7 +21,7 @@ properties: const: intel,ixp4xx-crypto intel,npe-handle: - $ref: '/schemas/types.yaml#/definitions/phandle-array' + $ref: /schemas/types.yaml#/definitions/phandle-array items: - items: - description: phandle to the NPE this crypto engine diff --git a/Documentation/devicetree/bindings/crypto/qcom-qce.yaml b/Documentation/devicetree/bindings/crypto/qcom-qce.yaml index e375bd981300997da7ede1a1c296bcf4ea4a4922..bb828068c3b88855d61f17f259fc6faf8e739f45 100644 --- a/Documentation/devicetree/bindings/crypto/qcom-qce.yaml +++ b/Documentation/devicetree/bindings/crypto/qcom-qce.yaml @@ -24,12 +24,20 @@ properties: deprecated: true description: Kept only for ABI backward compatibility + - items: + - enum: + - qcom,ipq4019-qce + - qcom,sm8150-qce + - const: qcom,qce + - items: - enum: - qcom,ipq6018-qce - qcom,ipq8074-qce - qcom,msm8996-qce + - qcom,qcm2290-qce - qcom,sdm845-qce + - qcom,sm6115-qce - const: qcom,ipq4019-qce - const: qcom,qce @@ -46,16 +54,12 @@ properties: maxItems: 1 clocks: - items: - - description: iface clocks register interface. - - description: bus clocks data transfer interface. - - description: core clocks rest of the crypto block. + minItems: 1 + maxItems: 3 clock-names: - items: - - const: iface - - const: bus - - const: core + minItems: 1 + maxItems: 3 iommus: minItems: 1 @@ -89,9 +93,37 @@ allOf: enum: - qcom,crypto-v5.1 - qcom,crypto-v5.4 - - qcom,ipq4019-qce + - qcom,ipq6018-qce + - qcom,ipq8074-qce + - qcom,msm8996-qce + - qcom,sdm845-qce + then: + properties: + clocks: + maxItems: 3 + clock-names: + items: + - const: iface + - const: bus + - const: core + required: + - clocks + - clock-names + - if: + properties: + compatible: + contains: + enum: + - qcom,qcm2290-qce + - qcom,sm6115-qce then: + properties: + clocks: + maxItems: 1 + clock-names: + items: + - const: core required: - clocks - clock-names diff --git a/Documentation/devicetree/bindings/crypto/starfive,jh7110-crypto.yaml b/Documentation/devicetree/bindings/crypto/starfive,jh7110-crypto.yaml new file mode 100644 index 0000000000000000000000000000000000000000..71a2876bd6e491d10ede14cb9d17f96307c85b7b --- /dev/null +++ b/Documentation/devicetree/bindings/crypto/starfive,jh7110-crypto.yaml @@ -0,0 +1,70 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/crypto/starfive,jh7110-crypto.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: StarFive Cryptographic Module + +maintainers: + - Jia Jie Ho + - William Qiu + +properties: + compatible: + const: starfive,jh7110-crypto + + reg: + maxItems: 1 + + clocks: + items: + - description: Hardware reference clock + - description: AHB reference clock + + clock-names: + items: + - const: hclk + - const: ahb + + interrupts: + maxItems: 1 + + resets: + maxItems: 1 + + dmas: + items: + - description: TX DMA channel + - description: RX DMA channel + + dma-names: + items: + - const: tx + - const: rx + +required: + - compatible + - reg + - clocks + - clock-names + - resets + - dmas + - dma-names + +additionalProperties: false + +examples: + - | + crypto: crypto@16000000 { + compatible = "starfive,jh7110-crypto"; + reg = <0x16000000 0x4000>; + clocks = <&clk 15>, <&clk 16>; + clock-names = "hclk", "ahb"; + interrupts = <28>; + resets = <&reset 3>; + dmas = <&dma 1 2>, + <&dma 0 2>; + dma-names = "tx", "rx"; + }; +... diff --git a/Documentation/devicetree/bindings/crypto/xlnx,zynqmp-aes.yaml b/Documentation/devicetree/bindings/crypto/xlnx,zynqmp-aes.yaml index 9e8fbd02b150e6665ff26ee989f9c6938b34d764..8aead97a585b15ba648a573d1125efde19fd2e10 100644 --- a/Documentation/devicetree/bindings/crypto/xlnx,zynqmp-aes.yaml +++ b/Documentation/devicetree/bindings/crypto/xlnx,zynqmp-aes.yaml @@ -7,8 +7,8 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Xilinx ZynqMP AES-GCM Hardware Accelerator maintainers: - - Kalyani Akula - - Michal Simek + - Kalyani Akula + - Michal Simek description: | The ZynqMP AES-GCM hardened cryptographic accelerator is used to diff --git a/Documentation/devicetree/bindings/display/bridge/analogix,dp.yaml b/Documentation/devicetree/bindings/display/bridge/analogix,dp.yaml index c9b06885cc63b78e454d3258c2b0208a28c80505..62f0521b09245bbe53a360725b07bd1be57e72dd 100644 --- a/Documentation/devicetree/bindings/display/bridge/analogix,dp.yaml +++ b/Documentation/devicetree/bindings/display/bridge/analogix,dp.yaml @@ -26,6 +26,7 @@ properties: const: dp force-hpd: + type: boolean description: Indicate driver need force hpd when hpd detect failed, this is used for some eDP screen which don not have a hpd signal. diff --git a/Documentation/devicetree/bindings/display/bridge/nxp,tda998x.yaml b/Documentation/devicetree/bindings/display/bridge/nxp,tda998x.yaml index c4bf543974737b5ce6a23eff854b7ed81e307d77..21d995f29a1e3068be328506cf01d8f0f5d3d383 100644 --- a/Documentation/devicetree/bindings/display/bridge/nxp,tda998x.yaml +++ b/Documentation/devicetree/bindings/display/bridge/nxp,tda998x.yaml @@ -20,6 +20,7 @@ properties: maxItems: 1 video-ports: + $ref: /schemas/types.yaml#/definitions/uint32 default: 0x230145 maximum: 0xffffff description: diff --git a/Documentation/devicetree/bindings/display/msm/gmu.yaml b/Documentation/devicetree/bindings/display/msm/gmu.yaml index 5fc4106110ad270a85e564476e2c827f945dfa14..d65926b4f05479019e54a8697bc997c7c5e465e3 100644 --- a/Documentation/devicetree/bindings/display/msm/gmu.yaml +++ b/Documentation/devicetree/bindings/display/msm/gmu.yaml @@ -243,7 +243,7 @@ examples: #include gmu: gmu@506a000 { - compatible="qcom,adreno-gmu-630.2", "qcom,adreno-gmu"; + compatible = "qcom,adreno-gmu-630.2", "qcom,adreno-gmu"; reg = <0x506a000 0x30000>, <0xb280000 0x10000>, diff --git a/Documentation/devicetree/bindings/display/panel/panel-mipi-dbi-spi.yaml b/Documentation/devicetree/bindings/display/panel/panel-mipi-dbi-spi.yaml index 9b701df5e9d28ff0f50b02bdcca952ded4fbda4b..2f0238b770ebabdca3092dfc3c414c64272bc673 100644 --- a/Documentation/devicetree/bindings/display/panel/panel-mipi-dbi-spi.yaml +++ b/Documentation/devicetree/bindings/display/panel/panel-mipi-dbi-spi.yaml @@ -67,6 +67,7 @@ properties: items: - enum: - sainsmart18 + - shineworld,lh133k - const: panel-mipi-dbi-spi write-only: @@ -86,6 +87,8 @@ properties: Logic level supply for interface signals (Vddi). No need to set if this is the same as power-supply. + spi-3wire: true + required: - compatible - reg diff --git a/Documentation/devicetree/bindings/display/panel/samsung,s6e8aa0.yaml b/Documentation/devicetree/bindings/display/panel/samsung,s6e8aa0.yaml index 1cdc91b3439f3f622aab4328faa060b72f0ff3a8..200fbf1c74a0bf1adadf7f85571608103354b30b 100644 --- a/Documentation/devicetree/bindings/display/panel/samsung,s6e8aa0.yaml +++ b/Documentation/devicetree/bindings/display/panel/samsung,s6e8aa0.yaml @@ -74,7 +74,7 @@ examples: vdd3-supply = <&vcclcd_reg>; vci-supply = <&vlcd_reg>; reset-gpios = <&gpy4 5 0>; - power-on-delay= <50>; + power-on-delay = <50>; reset-delay = <100>; init-delay = <100>; panel-width-mm = <58>; diff --git a/Documentation/devicetree/bindings/display/rockchip/rockchip-vop.yaml b/Documentation/devicetree/bindings/display/rockchip/rockchip-vop.yaml index 6f43d885c9b30892ccdd7d3414fc7224f577962f..df61cb5f5c54ba30d7c9e25eac172ee42ef080e4 100644 --- a/Documentation/devicetree/bindings/display/rockchip/rockchip-vop.yaml +++ b/Documentation/devicetree/bindings/display/rockchip/rockchip-vop.yaml @@ -121,11 +121,11 @@ examples: #size-cells = <0>; vopb_out_edp: endpoint@0 { reg = <0>; - remote-endpoint=<&edp_in_vopb>; + remote-endpoint = <&edp_in_vopb>; }; vopb_out_hdmi: endpoint@1 { reg = <1>; - remote-endpoint=<&hdmi_in_vopb>; + remote-endpoint = <&hdmi_in_vopb>; }; }; }; diff --git a/Documentation/devicetree/bindings/display/st,stm32-dsi.yaml b/Documentation/devicetree/bindings/display/st,stm32-dsi.yaml index c488308d7be132ecb7acdb384cf559858b2103f9..53560052aaf00df3c6c365470d6437f2ed8470bf 100644 --- a/Documentation/devicetree/bindings/display/st,stm32-dsi.yaml +++ b/Documentation/devicetree/bindings/display/st,stm32-dsi.yaml @@ -74,8 +74,6 @@ properties: - const: 2 required: - - "#address-cells" - - "#size-cells" - compatible - reg - clocks diff --git a/Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-vi.yaml b/Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-vi.yaml index a42bf33d1e7da1050002ca8727d48426bd628957..2181855a0920ea2d5decc842e45f2a4a1615ff6e 100644 --- a/Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-vi.yaml +++ b/Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-vi.yaml @@ -73,6 +73,18 @@ properties: avdd-dsi-csi-supply: description: DSI/CSI power supply. Must supply 1.2 V. + vip: + $ref: /schemas/display/tegra/nvidia,tegra20-vip.yaml + + ports: + $ref: /schemas/graph.yaml#/properties/ports + + properties: + port@0: + $ref: /schemas/graph.yaml#/properties/port + description: + Input from the VIP (parallel input capture) module + patternProperties: "^csi@[0-9a-f]+$": type: object @@ -108,6 +120,22 @@ examples: #include #include + i2c { + #address-cells = <1>; + #size-cells = <0>; + camera@48 { + compatible = "aptina,mt9v111"; + reg = <0x48>; + clocks = <&camera_clk>; + + port { + mt9v111_out: endpoint { + remote-endpoint = <&vi_vip_in>; + }; + }; + }; + }; + vi@54080000 { compatible = "nvidia,tegra20-vi"; reg = <0x54080000 0x00040000>; @@ -115,6 +143,37 @@ examples: clocks = <&tegra_car TEGRA20_CLK_VI>; resets = <&tegra_car 100>; reset-names = "vi"; + + vip { + compatible = "nvidia,tegra20-vip"; + ports { + #address-cells = <1>; + #size-cells = <0>; + port@0 { + reg = <0>; + vi_vip_in: endpoint { + remote-endpoint = <&mt9v111_out>; + }; + }; + port@1 { + reg = <1>; + vi_vip_out: endpoint { + remote-endpoint = <&vi_in>; + }; + }; + }; + }; + + ports { + #address-cells = <1>; + #size-cells = <0>; + port@0 { + reg = <0>; + vi_in: endpoint { + remote-endpoint = <&vi_vip_out>; + }; + }; + }; }; - | diff --git a/Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-vip.yaml b/Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-vip.yaml new file mode 100644 index 0000000000000000000000000000000000000000..14294edb8d8cfaf8f6b51f74744b89795d931e41 --- /dev/null +++ b/Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-vip.yaml @@ -0,0 +1,41 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/display/tegra/nvidia,tegra20-vip.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: NVIDIA Tegra VIP (parallel video capture) controller + +maintainers: + - Luca Ceresoli + +properties: + compatible: + enum: + - nvidia,tegra20-vip + + ports: + $ref: /schemas/graph.yaml#/properties/ports + + properties: + port@0: + $ref: /schemas/graph.yaml#/properties/port + description: + Port receiving the video stream from the sensor + + port@1: + $ref: /schemas/graph.yaml#/properties/port + description: + Port sending the video stream to the VI + + required: + - port@0 + - port@1 + +unevaluatedProperties: false + +required: + - compatible + - ports + +# see nvidia,tegra20-vi.yaml for an example diff --git a/Documentation/devicetree/bindings/dma/stericsson,dma40.yaml b/Documentation/devicetree/bindings/dma/stericsson,dma40.yaml index 64845347f44de08a324710d43fb60714082447a2..1e5752b19a49ab63a8a21d96277164030720ec93 100644 --- a/Documentation/devicetree/bindings/dma/stericsson,dma40.yaml +++ b/Documentation/devicetree/bindings/dma/stericsson,dma40.yaml @@ -112,14 +112,23 @@ properties: - const: stericsson,dma40 reg: - items: - - description: DMA40 memory base - - description: LCPA memory base + oneOf: + - items: + - description: DMA40 memory base + - items: + - description: DMA40 memory base + - description: LCPA memory base, deprecated, use eSRAM pool instead + deprecated: true + reg-names: - items: - - const: base - - const: lcpa + oneOf: + - items: + - const: base + - items: + - const: base + - const: lcpa + deprecated: true interrupts: maxItems: 1 @@ -127,6 +136,15 @@ properties: clocks: maxItems: 1 + sram: + $ref: /schemas/types.yaml#/definitions/phandle-array + description: A phandle array with inner size 1 (no arg cells). + First phandle is the LCPA (Logical Channel Parameter Address) memory. + Second phandle is the LCLA (Logical Channel Link base Address) memory. + maxItems: 2 + items: + maxItems: 1 + memcpy-channels: $ref: /schemas/types.yaml#/definitions/uint32-array description: Array of u32 elements indicating which channels on the DMA @@ -138,6 +156,7 @@ required: - reg - interrupts - clocks + - sram - memcpy-channels additionalProperties: false @@ -149,8 +168,9 @@ examples: #include dma-controller@801c0000 { compatible = "stericsson,db8500-dma40", "stericsson,dma40"; - reg = <0x801c0000 0x1000>, <0x40010000 0x800>; - reg-names = "base", "lcpa"; + reg = <0x801c0000 0x1000>; + reg-names = "base"; + sram = <&lcpa>, <&lcla>; interrupts = ; #dma-cells = <3>; memcpy-channels = <56 57 58 59 60>; diff --git a/Documentation/devicetree/bindings/dma/ti/k3-bcdma.yaml b/Documentation/devicetree/bindings/dma/ti/k3-bcdma.yaml index beecfe7a1732ae472528c98716f07f1fb877a37c..4ca300a42a99c2f60184318d9b7e8d5906872e44 100644 --- a/Documentation/devicetree/bindings/dma/ti/k3-bcdma.yaml +++ b/Documentation/devicetree/bindings/dma/ti/k3-bcdma.yaml @@ -33,6 +33,7 @@ properties: enum: - ti,am62a-dmss-bcdma-csirx - ti,am64-dmss-bcdma + - ti,j721s2-dmss-bcdma-csi reg: minItems: 3 @@ -151,7 +152,12 @@ allOf: required: - power-domains - else: + - if: + properties: + compatible: + contains: + const: ti,am64-dmss-bcdma + then: properties: reg: minItems: 5 @@ -168,6 +174,28 @@ allOf: - ti,sci-rm-range-bchan - ti,sci-rm-range-tchan + - if: + properties: + compatible: + contains: + const: ti,j721s2-dmss-bcdma-csi + then: + properties: + ti,sci-rm-range-bchan: false + + reg: + maxItems: 4 + + reg-names: + items: + - const: gcfg + - const: rchanrt + - const: tchanrt + - const: ringrt + + required: + - ti,sci-rm-range-tchan + unevaluatedProperties: false examples: diff --git a/Documentation/devicetree/bindings/dma/xilinx/xlnx,zynqmp-dpdma.yaml b/Documentation/devicetree/bindings/dma/xilinx/xlnx,zynqmp-dpdma.yaml index d6cbd95ec26daaf58d3871d0c58c7357819fac39..2128f4645c98d70556559d6321169b429832cbc7 100644 --- a/Documentation/devicetree/bindings/dma/xilinx/xlnx,zynqmp-dpdma.yaml +++ b/Documentation/devicetree/bindings/dma/xilinx/xlnx,zynqmp-dpdma.yaml @@ -41,6 +41,9 @@ properties: clock-names: const: axi_clk + power-domains: + maxItems: 1 + required: - "#dma-cells" - compatible @@ -48,12 +51,14 @@ required: - interrupts - clocks - clock-names + - power-domains additionalProperties: false examples: - | #include + #include dma: dma-controller@fd4c0000 { compatible = "xlnx,zynqmp-dpdma"; @@ -63,6 +68,7 @@ examples: clocks = <&dpdma_clk>; clock-names = "axi_clk"; #dma-cells = <1>; + power-domains = <&zynqmp_firmware PD_DP>; }; ... diff --git a/Documentation/devicetree/bindings/dvfs/performance-domain.yaml b/Documentation/devicetree/bindings/dvfs/performance-domain.yaml index 1dcb85a02a76942deb6f78e6a63b91f8b202ced1..cc930660b7945822b46f2e6f7cd5f84a619d1729 100644 --- a/Documentation/devicetree/bindings/dvfs/performance-domain.yaml +++ b/Documentation/devicetree/bindings/dvfs/performance-domain.yaml @@ -42,7 +42,7 @@ properties: enum: [ 0, 1 ] performance-domains: - $ref: '/schemas/types.yaml#/definitions/phandle-array' + $ref: /schemas/types.yaml#/definitions/phandle-array description: A phandle and performance domain specifier as defined by bindings of the performance controller/provider specified by phandle. diff --git a/Documentation/devicetree/bindings/eeprom/at25.yaml b/Documentation/devicetree/bindings/eeprom/at25.yaml index 11e2a95a7bcb916461f62e1df43304b6c6945009..0e31bb36ebb11006b240b90a271835810e97d032 100644 --- a/Documentation/devicetree/bindings/eeprom/at25.yaml +++ b/Documentation/devicetree/bindings/eeprom/at25.yaml @@ -33,6 +33,7 @@ properties: - microchip,25lc040 - st,m95m02 - st,m95256 + - st,m95640 - cypress,fm25 - const: atmel,at25 diff --git a/Documentation/devicetree/bindings/example-schema.yaml b/Documentation/devicetree/bindings/example-schema.yaml index f4eec4c42fb3e432f226da2170a002b4ab6b4d98..a41f9b9a196bbcbf50281a810a401f3ad1208728 100644 --- a/Documentation/devicetree/bindings/example-schema.yaml +++ b/Documentation/devicetree/bindings/example-schema.yaml @@ -52,8 +52,7 @@ properties: - vendor,soc4-ip - vendor,soc3-ip - vendor,soc2-ip - - enum: - - vendor,soc1-ip + - const: vendor,soc1-ip # additionalItems being false is implied # minItems/maxItems equal to 2 is implied - items: @@ -85,6 +84,9 @@ properties: discouraged. clock-names: + # For single-entry lists in clocks, resets etc., the xxx-names often do not + # bring any value, especially if they copy the IP block name. In such case + # just skip the xxx-names. items: - const: bus diff --git a/Documentation/devicetree/bindings/extcon/qcom,pm8941-misc.yaml b/Documentation/devicetree/bindings/extcon/qcom,pm8941-misc.yaml index 6a9c96f0352ac3b781a56eefa6c2d282a0483a4a..2c8cf6aab19a20cc8c80bee989b634567330b0b9 100644 --- a/Documentation/devicetree/bindings/extcon/qcom,pm8941-misc.yaml +++ b/Documentation/devicetree/bindings/extcon/qcom,pm8941-misc.yaml @@ -27,10 +27,14 @@ properties: interrupt-names: minItems: 1 - items: - - const: usb_id - - const: usb_vbus - + anyOf: + - items: + - const: usb_id + - const: usb_vbus + - items: + - const: usb_id + - items: + - const: usb_vbus required: - compatible - reg @@ -49,7 +53,7 @@ examples: interrupt-controller; #interrupt-cells = <4>; - usb_id: misc@900 { + usb_id: usb-detect@900 { compatible = "qcom,pm8941-misc"; reg = <0x900>; interrupts = <0x0 0x9 0 IRQ_TYPE_EDGE_BOTH>; diff --git a/Documentation/devicetree/bindings/extcon/wlf,arizona.yaml b/Documentation/devicetree/bindings/extcon/wlf,arizona.yaml index efdf59abb2e18b454f194c4e2bb4401ee725d187..351b202d0e10f0f23a60b57564c797baac4c6ba7 100644 --- a/Documentation/devicetree/bindings/extcon/wlf,arizona.yaml +++ b/Documentation/devicetree/bindings/extcon/wlf,arizona.yaml @@ -23,7 +23,7 @@ properties: headphone detect mode to HPDETL, ARIZONA_ACCDET_MODE_HPR/2 sets it to HPDETR. If this node is not included or if the value is unknown, then headphone detection mode is set to HPDETL. - $ref: "/schemas/types.yaml#/definitions/uint32" + $ref: /schemas/types.yaml#/definitions/uint32 minimum: 1 maximum: 2 @@ -51,7 +51,7 @@ properties: description: Additional software microphone detection debounce specified in milliseconds. - $ref: "/schemas/types.yaml#/definitions/uint32" + $ref: /schemas/types.yaml#/definitions/uint32 wlf,micd-pol-gpio: description: @@ -63,7 +63,7 @@ properties: description: Time allowed for MICBIAS to startup prior to performing microphone detection, specified as per the ARIZONA_MICD_TIME_XXX defines. - $ref: "/schemas/types.yaml#/definitions/uint32" + $ref: /schemas/types.yaml#/definitions/uint32 minimum: 0 maximum: 12 @@ -71,7 +71,7 @@ properties: description: Delay between successive microphone detection measurements, specified as per the ARIZONA_MICD_TIME_XXX defines. - $ref: "/schemas/types.yaml#/definitions/uint32" + $ref: /schemas/types.yaml#/definitions/uint32 minimum: 0 maximum: 12 @@ -79,7 +79,7 @@ properties: description: Microphone detection hardware debounces specified as the number of measurements to take. - $ref: "/schemas/types.yaml#/definitions/uint32" + $ref: /schemas/types.yaml#/definitions/uint32 enum: [2, 4] wlf,micd-timeout-ms: @@ -97,7 +97,7 @@ properties: CTIA / OMTP headsets), the field can be of variable length but should always be a multiple of 3 cells long, each three cell group represents one polarity configuration. - $ref: "/schemas/types.yaml#/definitions/uint32-matrix" + $ref: /schemas/types.yaml#/definitions/uint32-matrix items: items: - description: @@ -119,7 +119,7 @@ properties: description: Settings for the general purpose switch, set as one of the ARIZONA_GPSW_XXX defines. - $ref: "/schemas/types.yaml#/definitions/uint32" + $ref: /schemas/types.yaml#/definitions/uint32 minimum: 0 maximum: 3 diff --git a/Documentation/devicetree/bindings/firmware/arm,scmi.yaml b/Documentation/devicetree/bindings/firmware/arm,scmi.yaml index 5824c43e9893133f8a38cbf9bfb56e71eb768f48..b138f3d23df8c90030c064049955fe4517e76207 100644 --- a/Documentation/devicetree/bindings/firmware/arm,scmi.yaml +++ b/Documentation/devicetree/bindings/firmware/arm,scmi.yaml @@ -34,6 +34,10 @@ properties: - description: SCMI compliant firmware with ARM SMC/HVC transport items: - const: arm,scmi-smc + - description: SCMI compliant firmware with ARM SMC/HVC transport + with shmem address(4KB-page, offset) as parameters + items: + - const: arm,scmi-smc-param - description: SCMI compliant firmware with SCMI Virtio transport. The virtio transport only supports a single device. items: @@ -214,7 +218,7 @@ properties: patternProperties: '^regulator@[0-9a-f]+$': type: object - $ref: "../regulator/regulator.yaml#" + $ref: /schemas/regulator/regulator.yaml# unevaluatedProperties: false properties: @@ -299,7 +303,9 @@ else: properties: compatible: contains: - const: arm,scmi-smc + enum: + - arm,scmi-smc + - arm,scmi-smc-param then: required: - arm,smc-id diff --git a/Documentation/devicetree/bindings/firmware/brcm,kona-smc.yaml b/Documentation/devicetree/bindings/firmware/brcm,kona-smc.yaml new file mode 100644 index 0000000000000000000000000000000000000000..684b15ba9ad099140ca453815c050a1b2ddbdab0 --- /dev/null +++ b/Documentation/devicetree/bindings/firmware/brcm,kona-smc.yaml @@ -0,0 +1,39 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/firmware/brcm,kona-smc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Broadcom Kona family Secure Monitor bounce buffer + +description: + A bounce buffer used for non-secure to secure communications. + +maintainers: + - Florian Fainelli + +properties: + compatible: + items: + - enum: + - brcm,bcm11351-smc + - brcm,bcm21664-smc + - brcm,bcm23550-smc + - const: brcm,kona-smc + + reg: + maxItems: 1 + +required: + - compatible + - reg + +additionalProperties: false + +examples: + - | + smc@3404c000 { + compatible = "brcm,bcm11351-smc", "brcm,kona-smc"; + reg = <0x3404c000 0x400>; /* 1 KiB in SRAM */ + }; +... diff --git a/Documentation/devicetree/bindings/firmware/qcom,scm.yaml b/Documentation/devicetree/bindings/firmware/qcom,scm.yaml index 367d04ad19236242d4c05bc88a43931964588cc6..bdbee58a542b37a16198572121b536c5a7bc3fcf 100644 --- a/Documentation/devicetree/bindings/firmware/qcom,scm.yaml +++ b/Documentation/devicetree/bindings/firmware/qcom,scm.yaml @@ -51,6 +51,7 @@ properties: - qcom,scm-sdm845 - qcom,scm-sdx55 - qcom,scm-sdx65 + - qcom,scm-sdx75 - qcom,scm-sm6115 - qcom,scm-sm6125 - qcom,scm-sm6350 @@ -71,6 +72,8 @@ properties: minItems: 1 maxItems: 3 + dma-coherent: true + interconnects: maxItems: 1 diff --git a/Documentation/devicetree/bindings/firmware/xilinx/xlnx,zynqmp-firmware.yaml b/Documentation/devicetree/bindings/firmware/xilinx/xlnx,zynqmp-firmware.yaml index f14f7b454f07cd063889b045bcea091876874bc2..910bebe6cfa804c15a17952c3b135d14cfaf8a4c 100644 --- a/Documentation/devicetree/bindings/firmware/xilinx/xlnx,zynqmp-firmware.yaml +++ b/Documentation/devicetree/bindings/firmware/xilinx/xlnx,zynqmp-firmware.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Xilinx firmware driver maintainers: - - Nava kishore Manne + - Nava kishore Manne description: The zynqmp-firmware node describes the interface to platform firmware. ZynqMP has an interface to communicate with secure firmware. diff --git a/Documentation/devicetree/bindings/fpga/xilinx-zynq-fpga-mgr.yaml b/Documentation/devicetree/bindings/fpga/xilinx-zynq-fpga-mgr.yaml index f47b6140a7429797a01b13bafb22e6d6589febbd..04dcadc2c20e9c1d8a3491025d4485ae0e664f38 100644 --- a/Documentation/devicetree/bindings/fpga/xilinx-zynq-fpga-mgr.yaml +++ b/Documentation/devicetree/bindings/fpga/xilinx-zynq-fpga-mgr.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Xilinx Zynq FPGA Manager maintainers: - - Michal Simek + - Michal Simek properties: compatible: diff --git a/Documentation/devicetree/bindings/fpga/xlnx,versal-fpga.yaml b/Documentation/devicetree/bindings/fpga/xlnx,versal-fpga.yaml index ac6a207278d591832d41d8ff28fbdd64370a2123..26f18834caa3aeaeea769cb4d193fc0b3755cf61 100644 --- a/Documentation/devicetree/bindings/fpga/xlnx,versal-fpga.yaml +++ b/Documentation/devicetree/bindings/fpga/xlnx,versal-fpga.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Xilinx Versal FPGA driver. maintainers: - - Nava kishore Manne + - Nava kishore Manne description: | Device Tree Versal FPGA bindings for the Versal SoC, controlled diff --git a/Documentation/devicetree/bindings/fpga/xlnx,zynqmp-pcap-fpga.yaml b/Documentation/devicetree/bindings/fpga/xlnx,zynqmp-pcap-fpga.yaml index 00a8d92ff73680a45755d84b60414273b57cf929..1390ae103b0b2378cc4ecebd5b694a5c7d4cb3d4 100644 --- a/Documentation/devicetree/bindings/fpga/xlnx,zynqmp-pcap-fpga.yaml +++ b/Documentation/devicetree/bindings/fpga/xlnx,zynqmp-pcap-fpga.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Xilinx Zynq Ultrascale MPSoC FPGA Manager maintainers: - - Nava kishore Manne + - Nava kishore Manne description: | Device Tree Bindings for Zynq Ultrascale MPSoC FPGA Manager. diff --git a/Documentation/devicetree/bindings/gpio/brcm,bcm6345-gpio.yaml b/Documentation/devicetree/bindings/gpio/brcm,bcm63xx-gpio.yaml similarity index 75% rename from Documentation/devicetree/bindings/gpio/brcm,bcm6345-gpio.yaml rename to Documentation/devicetree/bindings/gpio/brcm,bcm63xx-gpio.yaml index 4d69f79df85904c8fc5a3e870b80d23c289a9328..62fcc2bd5d805990b7566191fa61ecea1bbdd01e 100644 --- a/Documentation/devicetree/bindings/gpio/brcm,bcm6345-gpio.yaml +++ b/Documentation/devicetree/bindings/gpio/brcm,bcm63xx-gpio.yaml @@ -1,10 +1,10 @@ # SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause %YAML 1.2 --- -$id: http://devicetree.org/schemas/gpio/brcm,bcm6345-gpio.yaml# +$id: http://devicetree.org/schemas/gpio/brcm,bcm63xx-gpio.yaml# $schema: http://devicetree.org/meta-schemas/core.yaml# -title: Broadcom BCM6345 GPIO controller +title: Broadcom BCM63xx GPIO controller maintainers: - Álvaro Fernández Rojas @@ -18,8 +18,6 @@ description: |+ BCM6338 have 8-bit data and dirout registers, where GPIO state can be read and/or written, and the direction changed from input to output. - BCM6345 have 16-bit data and dirout registers, where GPIO state can be read - and/or written, and the direction changed from input to output. BCM6318, BCM6328, BCM6358, BCM6362, BCM6368 and BCM63268 have 32-bit data and dirout registers, where GPIO state can be read and/or written, and the direction changed from input to output. @@ -29,7 +27,6 @@ properties: enum: - brcm,bcm6318-gpio - brcm,bcm6328-gpio - - brcm,bcm6345-gpio - brcm,bcm6358-gpio - brcm,bcm6362-gpio - brcm,bcm6368-gpio @@ -63,17 +60,6 @@ required: additionalProperties: false examples: - - | - gpio@fffe0406 { - compatible = "brcm,bcm6345-gpio"; - reg-names = "dirout", "dat"; - reg = <0xfffe0406 2>, <0xfffe040a 2>; - native-endian; - - gpio-controller; - #gpio-cells = <2>; - }; - - | gpio@0 { compatible = "brcm,bcm63268-gpio"; diff --git a/Documentation/devicetree/bindings/gpio/gpio-delay.yaml b/Documentation/devicetree/bindings/gpio/gpio-delay.yaml new file mode 100644 index 0000000000000000000000000000000000000000..1cebc4058e2726600b252e80ecc7f015030782cb --- /dev/null +++ b/Documentation/devicetree/bindings/gpio/gpio-delay.yaml @@ -0,0 +1,79 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/gpio/gpio-delay.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: GPIO delay controller + +maintainers: + - Alexander Stein + +description: | + This binding describes an electrical setup where setting an GPIO output + is delayed by some external setup, e.g. RC circuit. + + +----------+ +-----------+ + | | VCC_B | | + | | | | | + | | VCC_A _ | | + | GPIO | | | R | Consumer | + |controller| ___ |_| | | + | | | | | | | + | [IOx|-------| |--+-----|-----+ | + | | |___| | | input | + | | | | | + +----------+ --- C +-----------+ + --- + | + - + GND + + If the input on the consumer is controlled by an open-drain signal + attached to an RC circuit the ramp-up delay is not under control + of the GPIO controller. + +properties: + compatible: + const: gpio-delay + + "#gpio-cells": + description: | + Specifies the pin, ramp-up and ramp-down delays. The + delays are specified in microseconds. + const: 3 + + gpios: + description: Array of GPIOs which output signal change is delayed + minItems: 1 + maxItems: 32 + + gpio-controller: true + + gpio-line-names: + minItems: 1 + maxItems: 32 + +required: + - compatible + - "#gpio-cells" + - gpio-controller + - gpios + +additionalProperties: false + +examples: + - | + #include + + enable_delay: enable-delay { + compatible = "gpio-delay"; + #gpio-cells = <3>; + gpio-controller; + gpios = <&gpio0 3 GPIO_ACTIVE_LOW>, + <&gpio3 1 GPIO_ACTIVE_HIGH>; + }; + + consumer { + enable-gpios = <&enable_delay 0 130000 30000>; + }; diff --git a/Documentation/devicetree/bindings/gpio/gpio-ep9301.yaml b/Documentation/devicetree/bindings/gpio/gpio-ep9301.yaml new file mode 100644 index 0000000000000000000000000000000000000000..daadfb4926c319636e84a62099bac3b7c845bade --- /dev/null +++ b/Documentation/devicetree/bindings/gpio/gpio-ep9301.yaml @@ -0,0 +1,154 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/gpio/gpio-ep9301.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: EP93xx GPIO controller + +maintainers: + - Linus Walleij + - Bartosz Golaszewski + - Nikita Shubin + +properties: + compatible: + oneOf: + - const: cirrus,ep9301-gpio + - items: + - enum: + - cirrus,ep9302-gpio + - cirrus,ep9307-gpio + - cirrus,ep9312-gpio + - cirrus,ep9315-gpio + - const: cirrus,ep9301-gpio + + reg: + minItems: 2 + items: + - description: data register + - description: direction register + - description: interrupt registers base + + reg-names: + minItems: 2 + items: + - const: data + - const: dir + - const: intr + + gpio-controller: true + + gpio-ranges: true + + "#gpio-cells": + const: 2 + + interrupt-controller: true + + "#interrupt-cells": + const: 2 + + interrupts: + oneOf: + - maxItems: 1 + - description: port F has dedicated irq line for each gpio line + maxItems: 8 + +required: + - compatible + - reg + - gpio-controller + - "#gpio-cells" + +additionalProperties: false + +examples: + - | + gpio@80840000 { + compatible = "cirrus,ep9301-gpio"; + reg = <0x80840000 0x04>, + <0x80840010 0x04>, + <0x80840090 0x1c>; + reg-names = "data", "dir", "intr"; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + interrupt-parent = <&vic1>; + interrupts = <27>; + }; + + gpio@80840004 { + compatible = "cirrus,ep9301-gpio"; + reg = <0x80840004 0x04>, + <0x80840014 0x04>, + <0x808400ac 0x1c>; + reg-names = "data", "dir", "intr"; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + interrupt-parent = <&vic1>; + interrupts = <27>; + }; + + gpio@80840008 { + compatible = "cirrus,ep9301-gpio"; + reg = <0x80840008 0x04>, + <0x80840018 0x04>; + reg-names = "data", "dir"; + gpio-controller; + #gpio-cells = <2>; + }; + + gpio@8084000c { + compatible = "cirrus,ep9301-gpio"; + reg = <0x8084000c 0x04>, + <0x8084001c 0x04>; + reg-names = "data", "dir"; + gpio-controller; + #gpio-cells = <2>; + }; + + gpio@80840020 { + compatible = "cirrus,ep9301-gpio"; + reg = <0x80840020 0x04>, + <0x80840024 0x04>; + reg-names = "data", "dir"; + gpio-controller; + #gpio-cells = <2>; + }; + + gpio@80840030 { + compatible = "cirrus,ep9301-gpio"; + reg = <0x80840030 0x04>, + <0x80840034 0x04>, + <0x8084004c 0x1c>; + reg-names = "data", "dir", "intr"; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + interrupts-extended = <&vic0 19>, <&vic0 20>, + <&vic0 21>, <&vic0 22>, + <&vic1 15>, <&vic1 16>, + <&vic1 17>, <&vic1 18>; + }; + + gpio@80840038 { + compatible = "cirrus,ep9301-gpio"; + reg = <0x80840038 0x04>, + <0x8084003c 0x04>; + reg-names = "data", "dir"; + gpio-controller; + #gpio-cells = <2>; + }; + + gpio@80840040 { + compatible = "cirrus,ep9301-gpio"; + reg = <0x80840040 0x04>, + <0x80840044 0x04>; + reg-names = "data", "dir"; + gpio-controller; + #gpio-cells = <2>; + }; + +... diff --git a/Documentation/devicetree/bindings/gpio/gpio-mmio.yaml b/Documentation/devicetree/bindings/gpio/gpio-mmio.yaml new file mode 100644 index 0000000000000000000000000000000000000000..b394e058256e0d805f705e3334c4df8b007c6455 --- /dev/null +++ b/Documentation/devicetree/bindings/gpio/gpio-mmio.yaml @@ -0,0 +1,117 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/gpio/gpio-mmio.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Generic MMIO GPIO + +maintainers: + - Linus Walleij + - Bartosz Golaszewski + +description: + Some simple GPIO controllers may consist of a single data register or a pair + of set/clear-bit registers. Such controllers are common for glue logic in + FPGAs or ASICs. Commonly, these controllers are accessed over memory-mapped + NAND-style parallel busses. + +properties: + compatible: + enum: + - brcm,bcm6345-gpio + - ni,169445-nand-gpio + - wd,mbl-gpio # Western Digital MyBook Live memory-mapped GPIO controller + + big-endian: true + + '#gpio-cells': + const: 2 + + gpio-controller: true + + little-endian: true + + reg: + minItems: 1 + description: + A list of registers in the controller. The width of each register is + determined by its size. All registers must have the same width. The number + of GPIOs is set by the width, with bit 0 corresponding to GPIO 0. + items: + - description: + Register to READ the value of the GPIO lines. If GPIO line is high, + the bit will be set. If the GPIO line is low, the bit will be cleared. + This register may also be used to drive GPIOs if the SET register is + omitted. + - description: + Register to SET the value of the GPIO lines. Setting a bit in this + register will drive the GPIO line high. + - description: + Register to CLEAR the value of the GPIO lines. Setting a bit in this + register will drive the GPIO line low. If this register is omitted, + the SET register will be used to clear the GPIO lines as well, by + actively writing the line with 0. + - description: + Register to set the line as OUTPUT. Setting a bit in this register + will turn that line into an output line. Conversely, clearing a bit + will turn that line into an input. + - description: + Register to set this line as INPUT. Setting a bit in this register + will turn that line into an input line. Conversely, clearing a bit + will turn that line into an output. + + reg-names: + minItems: 1 + maxItems: 5 + items: + enum: + - dat + - set + - clr + - dirout + - dirin + + native-endian: true + + no-output: + $ref: /schemas/types.yaml#/definitions/flag + description: + If this property is present, the controller cannot drive the GPIO lines. + +required: + - compatible + - reg + - reg-names + - '#gpio-cells' + - gpio-controller + +additionalProperties: false + +examples: + - | + gpio@1f300010 { + compatible = "ni,169445-nand-gpio"; + reg = <0x1f300010 0x4>; + reg-names = "dat"; + gpio-controller; + #gpio-cells = <2>; + }; + + gpio@e0100000 { + compatible = "wd,mbl-gpio"; + reg-names = "dat"; + reg = <0xe0100000 0x1>; + #gpio-cells = <2>; + gpio-controller; + no-output; + }; + + gpio@fffe0406 { + compatible = "brcm,bcm6345-gpio"; + reg-names = "dirout", "dat"; + reg = <0xfffe0406 2>, <0xfffe040a 2>; + native-endian; + gpio-controller; + #gpio-cells = <2>; + }; diff --git a/Documentation/devicetree/bindings/gpio/gpio-pca9570.yaml b/Documentation/devicetree/bindings/gpio/gpio-pca9570.yaml index 5b0134304e51c357fdec92a66ccd4398a21350c4..452f8972a96590731207d67217b8590471864d10 100644 --- a/Documentation/devicetree/bindings/gpio/gpio-pca9570.yaml +++ b/Documentation/devicetree/bindings/gpio/gpio-pca9570.yaml @@ -24,6 +24,10 @@ properties: '#gpio-cells': const: 2 + gpio-line-names: + minItems: 4 + maxItems: 8 + required: - compatible - reg diff --git a/Documentation/devicetree/bindings/gpio/gpio-stmpe.txt b/Documentation/devicetree/bindings/gpio/gpio-stmpe.txt deleted file mode 100644 index b33f8f02c0d729c5871c4e5790f18e621d6ac95b..0000000000000000000000000000000000000000 --- a/Documentation/devicetree/bindings/gpio/gpio-stmpe.txt +++ /dev/null @@ -1,17 +0,0 @@ -STMPE gpio ----------- - -Required properties: - - compatible: "st,stmpe-gpio" - -Optional properties: - - st,norequest-mask: bitmask specifying which GPIOs should _not_ be requestable - due to different usage (e.g. touch, keypad) - -Node should be child node of stmpe node to which it belongs. - -Example: - stmpe_gpio { - compatible = "st,stmpe-gpio"; - st,norequest-mask = <0x20>; //gpio 5 can't be used - }; diff --git a/Documentation/devicetree/bindings/gpio/gpio-vf610.yaml b/Documentation/devicetree/bindings/gpio/gpio-vf610.yaml index d2c39dba56add844e3eb65f20e74889f58a1d1ac..7c2d152e8617053fe8cce11177319f18e48276f6 100644 --- a/Documentation/devicetree/bindings/gpio/gpio-vf610.yaml +++ b/Documentation/devicetree/bindings/gpio/gpio-vf610.yaml @@ -61,6 +61,13 @@ properties: gpio-ranges: maxItems: 1 +patternProperties: + "^.+-hog(-[0-9]+)?$": + type: object + + required: + - gpio-hog + required: - compatible - reg diff --git a/Documentation/devicetree/bindings/gpio/gpio-zynq.yaml b/Documentation/devicetree/bindings/gpio/gpio-zynq.yaml index 572e1718f5015243ead10ad282b20a0ce38c29ef..5e2496379a3c863ce75a8d6d3a0bf722d0953d12 100644 --- a/Documentation/devicetree/bindings/gpio/gpio-zynq.yaml +++ b/Documentation/devicetree/bindings/gpio/gpio-zynq.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Xilinx Zynq GPIO controller maintainers: - - Michal Simek + - Michal Simek properties: compatible: diff --git a/Documentation/devicetree/bindings/gpio/ni,169445-nand-gpio.txt b/Documentation/devicetree/bindings/gpio/ni,169445-nand-gpio.txt deleted file mode 100644 index ca2f8c745a279cfea1375dc68dceff29a63f8de5..0000000000000000000000000000000000000000 --- a/Documentation/devicetree/bindings/gpio/ni,169445-nand-gpio.txt +++ /dev/null @@ -1,38 +0,0 @@ -Bindings for the National Instruments 169445 GPIO NAND controller - -The 169445 GPIO NAND controller has two memory mapped GPIO registers, one -for input (the ready signal) and one for output (control signals). It is -intended to be used with the GPIO NAND driver. - -Required properties: - - compatible: should be "ni,169445-nand-gpio" - - reg-names: must contain - "dat" - data register - - reg: address + size pairs describing the GPIO register sets; - order must correspond with the order of entries in reg-names - - #gpio-cells: must be set to 2. The first cell is the pin number and - the second cell is used to specify the gpio polarity: - 0 = active high - 1 = active low - - gpio-controller: Marks the device node as a gpio controller. - -Optional properties: - - no-output: disables driving output on the pins - -Examples: - gpio1: nand-gpio-out@1f300010 { - compatible = "ni,169445-nand-gpio"; - reg = <0x1f300010 0x4>; - reg-names = "dat"; - gpio-controller; - #gpio-cells = <2>; - }; - - gpio2: nand-gpio-in@1f300014 { - compatible = "ni,169445-nand-gpio"; - reg = <0x1f300014 0x4>; - reg-names = "dat"; - gpio-controller; - #gpio-cells = <2>; - no-output; - }; diff --git a/Documentation/devicetree/bindings/gpio/st,stmpe-gpio.yaml b/Documentation/devicetree/bindings/gpio/st,stmpe-gpio.yaml new file mode 100644 index 0000000000000000000000000000000000000000..22c0cae734251ea134ba04182b271528dc90fab2 --- /dev/null +++ b/Documentation/devicetree/bindings/gpio/st,stmpe-gpio.yaml @@ -0,0 +1,53 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/gpio/st,stmpe-gpio.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: STMicroelectonics Port Expander (STMPE) GPIO Block + +description: + STMicroelectronics Port Expander (STMPE) is a series of slow + bus controllers for various expanded peripherals such as GPIO, keypad, + touchscreen, ADC, PWM or rotator. It can contain one or several different + peripherals connected to SPI or I2C. These bindings pertain to the + GPIO portions of these expanders. + +maintainers: + - Linus Walleij + +properties: + compatible: + const: st,stmpe-gpio + + "#gpio-cells": + const: 2 + + "#interrupt-cells": + const: 2 + + gpio-controller: true + + interrupt-controller: true + + st,norequest-mask: + description: + A bitmask of GPIO lines that cannot be requested because for + for example not being connected to anything on the system + $ref: /schemas/types.yaml#/definitions/uint32 + +patternProperties: + "^.+-hog(-[0-9]+)?$": + type: object + + required: + - gpio-hog + +additionalProperties: false + +required: + - compatible + - "#gpio-cells" + - "#interrupt-cells" + - gpio-controller + - interrupt-controller diff --git a/Documentation/devicetree/bindings/gpio/wd,mbl-gpio.txt b/Documentation/devicetree/bindings/gpio/wd,mbl-gpio.txt deleted file mode 100644 index 038c3a6a1f4d180408ed1f0ad89f97ffea7f2eb2..0000000000000000000000000000000000000000 --- a/Documentation/devicetree/bindings/gpio/wd,mbl-gpio.txt +++ /dev/null @@ -1,38 +0,0 @@ -Bindings for the Western Digital's MyBook Live memory-mapped GPIO controllers. - -The Western Digital MyBook Live has two memory-mapped GPIO controllers. -Both GPIO controller only have a single 8-bit data register, where GPIO -state can be read and/or written. - -Required properties: - - compatible: should be "wd,mbl-gpio" - - reg-names: must contain - "dat" - data register - - reg: address + size pairs describing the GPIO register sets; - order must correspond with the order of entries in reg-names - - #gpio-cells: must be set to 2. The first cell is the pin number and - the second cell is used to specify the gpio polarity: - 0 = active high - 1 = active low - - gpio-controller: Marks the device node as a gpio controller. - -Optional properties: - - no-output: GPIOs are read-only. - -Examples: - gpio0: gpio0@e0000000 { - compatible = "wd,mbl-gpio"; - reg-names = "dat"; - reg = <0xe0000000 0x1>; - #gpio-cells = <2>; - gpio-controller; - }; - - gpio1: gpio1@e0100000 { - compatible = "wd,mbl-gpio"; - reg-names = "dat"; - reg = <0xe0100000 0x1>; - #gpio-cells = <2>; - gpio-controller; - no-output; - }; diff --git a/Documentation/devicetree/bindings/gpio/x-powers,axp209-gpio.yaml b/Documentation/devicetree/bindings/gpio/x-powers,axp209-gpio.yaml index 31906c25394099469a2456af80e89fef36ba5187..1638cfe90f1c2ced83e800cd23406813fd6e551a 100644 --- a/Documentation/devicetree/bindings/gpio/x-powers,axp209-gpio.yaml +++ b/Documentation/devicetree/bindings/gpio/x-powers,axp209-gpio.yaml @@ -44,6 +44,7 @@ patternProperties: - GPIO0 - GPIO1 - GPIO2 + - GPIO3 function: enum: diff --git a/Documentation/devicetree/bindings/gpio/xlnx,gpio-xilinx.yaml b/Documentation/devicetree/bindings/gpio/xlnx,gpio-xilinx.yaml index f333ee2288e7683f00a379dfe7618aa8682bc2cf..c1060e5fcef3a95c4bf2ef55e897c6c09b790d03 100644 --- a/Documentation/devicetree/bindings/gpio/xlnx,gpio-xilinx.yaml +++ b/Documentation/devicetree/bindings/gpio/xlnx,gpio-xilinx.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Xilinx AXI GPIO controller maintainers: - - Neeli Srinivas + - Neeli Srinivas description: The AXI GPIO design provides a general purpose input/output interface diff --git a/Documentation/devicetree/bindings/gpio/xlnx,zynqmp-gpio-modepin.yaml b/Documentation/devicetree/bindings/gpio/xlnx,zynqmp-gpio-modepin.yaml index 31c0fc3459035e985f1aacc0fd153a1a880354ad..18e61aff21857ff5861caa30148eb042f757de0c 100644 --- a/Documentation/devicetree/bindings/gpio/xlnx,zynqmp-gpio-modepin.yaml +++ b/Documentation/devicetree/bindings/gpio/xlnx,zynqmp-gpio-modepin.yaml @@ -12,7 +12,7 @@ description: PS_MODE). Every pin can be configured as input/output. maintainers: - - Piyush Mehta + - Piyush Mehta properties: compatible: diff --git a/Documentation/devicetree/bindings/gpu/arm,mali-bifrost.yaml b/Documentation/devicetree/bindings/gpu/arm,mali-bifrost.yaml index 0400a361875d67ec0efe1bb5157e112ea0afe635..e796a1ff8c82485ff1ee949ad9517fb83a03ad78 100644 --- a/Documentation/devicetree/bindings/gpu/arm,mali-bifrost.yaml +++ b/Documentation/devicetree/bindings/gpu/arm,mali-bifrost.yaml @@ -86,7 +86,7 @@ properties: const: 2 dynamic-power-coefficient: - $ref: '/schemas/types.yaml#/definitions/uint32' + $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 diff --git a/Documentation/devicetree/bindings/gpu/arm,mali-midgard.yaml b/Documentation/devicetree/bindings/gpu/arm,mali-midgard.yaml index 2a25384ca3ef1e5fba1ee03d801e996f850c1adb..ca02baba5526de12d77a4651f7cff47e5936d574 100644 --- a/Documentation/devicetree/bindings/gpu/arm,mali-midgard.yaml +++ b/Documentation/devicetree/bindings/gpu/arm,mali-midgard.yaml @@ -92,7 +92,7 @@ properties: dma-coherent: true dynamic-power-coefficient: - $ref: '/schemas/types.yaml#/definitions/uint32' + $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 diff --git a/Documentation/devicetree/bindings/gpu/arm,mali-utgard.yaml b/Documentation/devicetree/bindings/gpu/arm,mali-utgard.yaml index 318122d95eb5bde41083a48cf4a8d8bfd498bc59..0fae1ef013be8b6853c60f71e42e9cdfee412ff4 100644 --- a/Documentation/devicetree/bindings/gpu/arm,mali-utgard.yaml +++ b/Documentation/devicetree/bindings/gpu/arm,mali-utgard.yaml @@ -33,6 +33,7 @@ properties: - rockchip,rk3228-mali - samsung,exynos4210-mali - stericsson,db8500-mali + - xlnx,zynqmp-mali - const: arm,mali-400 - items: - enum: diff --git a/Documentation/devicetree/bindings/hwmon/adi,max31827.yaml b/Documentation/devicetree/bindings/hwmon/adi,max31827.yaml new file mode 100644 index 0000000000000000000000000000000000000000..2dc8b07b4d3b2072e6259f3e5d6a1c0385493639 --- /dev/null +++ b/Documentation/devicetree/bindings/hwmon/adi,max31827.yaml @@ -0,0 +1,54 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/hwmon/adi,max31827.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Analog Devices MAX31827, MAX31828, MAX31829 Low-Power Temperature Switch + +maintainers: + - Daniel Matyas + +description: | + Analog Devices MAX31827, MAX31828, MAX31829 Low-Power Temperature Switch with + I2C Interface + https://www.analog.com/media/en/technical-documentation/data-sheets/MAX31827-MAX31829.pdf + +properties: + compatible: + oneOf: + - const: adi,max31827 + - items: + - enum: + - adi,max31828 + - adi,max31829 + - const: adi,max31827 + + reg: + maxItems: 1 + + vref-supply: + description: + Must have values in the interval (1.6V; 3.6V) in order for the device to + function correctly. + +required: + - compatible + - reg + - vref-supply + +additionalProperties: false + +examples: + - | + i2c { + #address-cells = <1>; + #size-cells = <0>; + + temperature-sensor@42 { + compatible = "adi,max31827"; + reg = <0x42>; + vref-supply = <®_vdd>; + }; + }; +... diff --git a/Documentation/devicetree/bindings/i2c/cdns,i2c-r1p10.yaml b/Documentation/devicetree/bindings/i2c/cdns,i2c-r1p10.yaml index cb24d7b3221c826ef88c8287b95892c43f558e1d..ff57c5416ebcb732cb1765738bc3bcdb8ef6ccc9 100644 --- a/Documentation/devicetree/bindings/i2c/cdns,i2c-r1p10.yaml +++ b/Documentation/devicetree/bindings/i2c/cdns,i2c-r1p10.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Cadence I2C controller maintainers: - - Michal Simek + - Michal Simek allOf: - $ref: /schemas/i2c/i2c-controller.yaml# diff --git a/Documentation/devicetree/bindings/i2c/opencores,i2c-ocores.yaml b/Documentation/devicetree/bindings/i2c/opencores,i2c-ocores.yaml index 85d9efb743eefcbc067e2b5d1008680049285c1c..d9ef8672901125b33a64a7f8143878823781fbda 100644 --- a/Documentation/devicetree/bindings/i2c/opencores,i2c-ocores.yaml +++ b/Documentation/devicetree/bindings/i2c/opencores,i2c-ocores.yaml @@ -60,6 +60,7 @@ properties: default: 0 regstep: + $ref: /schemas/types.yaml#/definitions/uint32 description: | deprecated, use reg-shift above deprecated: true diff --git a/Documentation/devicetree/bindings/i3c/silvaco,i3c-master.yaml b/Documentation/devicetree/bindings/i3c/silvaco,i3c-master.yaml index 32c821f97779b7ea95ae2e16ab68698eff8ac8d2..133855f11b4f5d34ccd8d3c7fb32ef4cff5aa29c 100644 --- a/Documentation/devicetree/bindings/i3c/silvaco,i3c-master.yaml +++ b/Documentation/devicetree/bindings/i3c/silvaco,i3c-master.yaml @@ -10,7 +10,7 @@ maintainers: - Conor Culhane allOf: - - $ref: "i3c.yaml#" + - $ref: i3c.yaml# properties: compatible: diff --git a/Documentation/devicetree/bindings/iio/adc/adi,ad7192.yaml b/Documentation/devicetree/bindings/iio/adc/adi,ad7192.yaml index d521d516088be733a797ad151128bb4f2052f03f..16def2985ab4fe507e86d1fbc18cb603c479f9d3 100644 --- a/Documentation/devicetree/bindings/iio/adc/adi,ad7192.yaml +++ b/Documentation/devicetree/bindings/iio/adc/adi,ad7192.yaml @@ -47,6 +47,9 @@ properties: avdd-supply: description: AVdd voltage supply + vref-supply: + description: VRef voltage supply + adi,rejection-60-Hz-enable: description: | This bit enables a notch at 60 Hz when the first notch of the sinc @@ -89,6 +92,7 @@ required: - interrupts - dvdd-supply - avdd-supply + - vref-supply - spi-cpol - spi-cpha @@ -115,6 +119,7 @@ examples: interrupt-parent = <&gpio>; dvdd-supply = <&dvdd>; avdd-supply = <&avdd>; + vref-supply = <&vref>; adi,refin2-pins-enable; adi,rejection-60-Hz-enable; diff --git a/Documentation/devicetree/bindings/iio/adc/mediatek,mt2701-auxadc.yaml b/Documentation/devicetree/bindings/iio/adc/mediatek,mt2701-auxadc.yaml index 7f79a06e76f59614a6cc2a8414bc48761dac5d9d..6168b44ea72cf6eedde042dc9c61c15f1cf54b19 100644 --- a/Documentation/devicetree/bindings/iio/adc/mediatek,mt2701-auxadc.yaml +++ b/Documentation/devicetree/bindings/iio/adc/mediatek,mt2701-auxadc.yaml @@ -26,6 +26,7 @@ properties: - mediatek,mt2712-auxadc - mediatek,mt6765-auxadc - mediatek,mt7622-auxadc + - mediatek,mt7986-auxadc - mediatek,mt8173-auxadc - items: - enum: diff --git a/Documentation/devicetree/bindings/iio/adc/qcom,spmi-vadc.yaml b/Documentation/devicetree/bindings/iio/adc/qcom,spmi-vadc.yaml index bd6e0d6f6e0ce8a3114a4d75d363c691c1484a42..ad7d6fc49de58ea1ed6ed9f55ba11d97ae6c721b 100644 --- a/Documentation/devicetree/bindings/iio/adc/qcom,spmi-vadc.yaml +++ b/Documentation/devicetree/bindings/iio/adc/qcom,spmi-vadc.yaml @@ -54,7 +54,7 @@ required: - '#io-channel-cells' patternProperties: - "^.*@[0-9a-f]+$": + "^channel@[0-9a-f]+$": type: object additionalProperties: false description: | @@ -101,7 +101,7 @@ patternProperties: oneOf: - items: - const: 1 - - enum: [ 1, 3, 4, 6, 20, 8, 10 ] + - enum: [ 1, 3, 4, 6, 20, 8, 10, 16 ] - items: - const: 10 - const: 81 @@ -148,7 +148,7 @@ allOf: then: patternProperties: - "^.*@[0-9a-f]+$": + "^channel@[0-9a-f]+$": properties: qcom,decimation: enum: [ 512, 1024, 2048, 4096 ] @@ -171,7 +171,7 @@ allOf: then: patternProperties: - "^.*@[0-9a-f]+$": + "^channel@[0-9a-f]+$": properties: qcom,decimation: enum: [ 256, 512, 1024 ] @@ -194,7 +194,7 @@ allOf: then: patternProperties: - "^.*@[0-9a-f]+$": + "^channel@[0-9a-f]+$": properties: qcom,decimation: enum: [ 250, 420, 840 ] @@ -217,7 +217,7 @@ allOf: then: patternProperties: - "^.*@[0-9a-f]+$": + "^channel@[0-9a-f]+$": properties: qcom,decimation: enum: [ 85, 340, 1360 ] @@ -249,7 +249,7 @@ examples: #io-channel-cells = <1>; /* Channel node */ - adc-chan@39 { + channel@39 { reg = <0x39>; qcom,decimation = <512>; qcom,ratiometric; @@ -258,19 +258,19 @@ examples: qcom,pre-scaling = <1 3>; }; - adc-chan@9 { + channel@9 { reg = <0x9>; }; - adc-chan@a { + channel@a { reg = <0xa>; }; - adc-chan@e { + channel@e { reg = <0xe>; }; - adc-chan@f { + channel@f { reg = <0xf>; }; }; @@ -292,16 +292,18 @@ examples: #io-channel-cells = <1>; /* Other properties are omitted */ - xo-therm@44 { + channel@44 { reg = ; qcom,ratiometric; qcom,hw-settle-time = <200>; + label = "xo_therm"; }; - conn-therm@47 { + channel@47 { reg = ; qcom,ratiometric; qcom,hw-settle-time = <200>; + label = "conn_therm"; }; }; }; diff --git a/Documentation/devicetree/bindings/iio/adc/rockchip-saradc.yaml b/Documentation/devicetree/bindings/iio/adc/rockchip-saradc.yaml index da50b529c1576bfcf7f83cbc21048fa9498731da..aa24b841393c0223c818723def339ba2f10d2aab 100644 --- a/Documentation/devicetree/bindings/iio/adc/rockchip-saradc.yaml +++ b/Documentation/devicetree/bindings/iio/adc/rockchip-saradc.yaml @@ -15,6 +15,7 @@ properties: - const: rockchip,saradc - const: rockchip,rk3066-tsadc - const: rockchip,rk3399-saradc + - const: rockchip,rk3588-saradc - items: - enum: - rockchip,px30-saradc diff --git a/Documentation/devicetree/bindings/iio/adc/ti,adc108s102.yaml b/Documentation/devicetree/bindings/iio/adc/ti,adc108s102.yaml index 9b072b057f164e0a7cdb47e793da14ba45739b1f..a60b1e100ee40f0c76717038f0608d2acf53b1bd 100644 --- a/Documentation/devicetree/bindings/iio/adc/ti,adc108s102.yaml +++ b/Documentation/devicetree/bindings/iio/adc/ti,adc108s102.yaml @@ -35,7 +35,7 @@ unevaluatedProperties: false examples: - | spi { - #address-cells= <1>; + #address-cells = <1>; #size-cells = <0>; adc@0 { diff --git a/Documentation/devicetree/bindings/iio/afe/voltage-divider.yaml b/Documentation/devicetree/bindings/iio/afe/voltage-divider.yaml index df2589f214e18b50d585e520be88a7a83f82863c..dddf97b50549f0012697c60c484c0a2917f49c83 100644 --- a/Documentation/devicetree/bindings/iio/afe/voltage-divider.yaml +++ b/Documentation/devicetree/bindings/iio/afe/voltage-divider.yaml @@ -13,7 +13,7 @@ description: | When an io-channel measures the midpoint of a voltage divider, the interesting voltage is often the voltage over the full resistance of the divider. This binding describes the voltage divider in such - a curcuit. + a circuit. Vin ----. | diff --git a/Documentation/devicetree/bindings/iio/imu/invensense,mpu6050.yaml b/Documentation/devicetree/bindings/iio/imu/invensense,mpu6050.yaml index ec64d7877fe5b39ba6586a75fe9dcb890dd30d79..1db6952ddca5e118ffcced78e4b9cf0ba9e0179c 100644 --- a/Documentation/devicetree/bindings/iio/imu/invensense,mpu6050.yaml +++ b/Documentation/devicetree/bindings/iio/imu/invensense,mpu6050.yaml @@ -30,6 +30,9 @@ properties: - invensense,mpu9150 - invensense,mpu9250 - invensense,mpu9255 + - items: + - const: invensense,icm20600 + - const: invensense,icm20602 - items: - const: invensense,icm20608d - const: invensense,icm20608 diff --git a/Documentation/devicetree/bindings/iio/imu/st,lsm6dsx.yaml b/Documentation/devicetree/bindings/iio/imu/st,lsm6dsx.yaml index b39f5217d8ff3ced8375d8eebd0cc92871f122f8..ee8724ad33ab382cdafc6415cc0af6f239e1831d 100644 --- a/Documentation/devicetree/bindings/iio/imu/st,lsm6dsx.yaml +++ b/Documentation/devicetree/bindings/iio/imu/st,lsm6dsx.yaml @@ -98,6 +98,7 @@ required: - reg allOf: + - $ref: /schemas/iio/iio.yaml# - $ref: /schemas/spi/spi-peripheral-props.yaml# unevaluatedProperties: false diff --git a/Documentation/devicetree/bindings/iio/light/rohm,bu27008.yaml b/Documentation/devicetree/bindings/iio/light/rohm,bu27008.yaml new file mode 100644 index 0000000000000000000000000000000000000000..4f66fd47b016812fecf447aa71ede149e1099bd9 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/light/rohm,bu27008.yaml @@ -0,0 +1,49 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/iio/light/rohm,bu27008.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: ROHM BU27008 color sensor + +maintainers: + - Matti Vaittinen + +description: + The ROHM BU27008 is a sensor with 5 photodiodes (red, green, blue, clear + and IR) with four configurable channels. Red and green being always + available and two out of the rest three (blue, clear, IR) can be + selected to be simultaneously measured. Typical application is adjusting + LCD backlight of TVs, mobile phones and tablet PCs. + +properties: + compatible: + const: rohm,bu27008 + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + vdd-supply: true + +required: + - compatible + - reg + +additionalProperties: false + +examples: + - | + i2c { + #address-cells = <1>; + #size-cells = <0>; + + light-sensor@38 { + compatible = "rohm,bu27008"; + reg = <0x38>; + }; + }; + +... diff --git a/Documentation/devicetree/bindings/iio/light/ti,opt4001.yaml b/Documentation/devicetree/bindings/iio/light/ti,opt4001.yaml new file mode 100644 index 0000000000000000000000000000000000000000..12b0c7ed5d7271b281556b4cb84e2b618fd8b9d8 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/light/ti,opt4001.yaml @@ -0,0 +1,68 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/iio/light/ti,opt4001.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Texas Instruments OPT4001 Ambient Light Sensor + +maintainers: + - Stefan Windfeldt-Prytz + +description: + Ambient light sensor with an i2c interface. + Last part of compatible is for the packaging used. + Picostar is a 4 pinned SMT and sot-5x3 is a 8 pinned SOT. + https://www.ti.com/lit/gpn/opt4001 + +properties: + compatible: + enum: + - ti,opt4001-picostar + - ti,opt4001-sot-5x3 + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + vdd-supply: + description: Regulator that provides power to the sensor + +required: + - compatible + - reg + +allOf: + - if: + properties: + compatible: + contains: + const: ti,opt4001-sot-5x3 + then: + properties: + interrupts: + maxItems: 1 + else: + properties: + interrupts: false + +additionalProperties: false + +examples: + - | + #include + i2c { + #address-cells = <1>; + #size-cells = <0>; + + light-sensor@44 { + compatible = "ti,opt4001-sot-5x3"; + reg = <0x44>; + vdd-supply = <&vdd_reg>; + interrupt-parent = <&gpio1>; + interrupts = <28 IRQ_TYPE_EDGE_FALLING>; + }; + }; +... diff --git a/Documentation/devicetree/bindings/iio/potentiometer/renesas,x9250.yaml b/Documentation/devicetree/bindings/iio/potentiometer/renesas,x9250.yaml new file mode 100644 index 0000000000000000000000000000000000000000..ab5c09c00ff469648467cbab58e96f4909d3458f --- /dev/null +++ b/Documentation/devicetree/bindings/iio/potentiometer/renesas,x9250.yaml @@ -0,0 +1,78 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/iio/potentiometer/renesas,x9250.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Renesas X9250 quad potentiometers + +maintainers: + - Herve Codina + +description: + The Renesas X9250 integrates four digitally controlled potentiometers. + On each potentiometer, the X9250T has a 100 kOhms total resistance and the + X9250U has a 50 kOhms total resistance. + +allOf: + - $ref: /schemas/spi/spi-peripheral-props.yaml + +properties: + compatible: + enum: + - renesas,x9250t + - renesas,x9250u + + reg: + maxItems: 1 + + vcc-supply: + description: + Regulator for the VCC power supply. + + avp-supply: + description: + Regulator for the analog V+ power supply. + + avn-supply: + description: + Regulator for the analog V- power supply. + + '#io-channel-cells': + const: 1 + + spi-max-frequency: + maximum: 2000000 + + wp-gpios: + maxItems: 1 + description: + GPIO connected to the write-protect pin. + +required: + - compatible + - reg + - vcc-supply + - avp-supply + - avn-supply + - '#io-channel-cells' + +unevaluatedProperties: false + +examples: + - | + #include + spi { + #address-cells = <1>; + #size-cells = <0>; + potentiometer@0 { + compatible = "renesas,x9250t"; + reg = <0>; + vcc-supply = <&vcc_regulator>; + avp-supply = <&avp_regulator>; + avn-supply = <&avp_regulator>; + wp-gpios = <&gpio 1 GPIO_ACTIVE_LOW>; + spi-max-frequency = <2000000>; + #io-channel-cells = <1>; + }; + }; diff --git a/Documentation/devicetree/bindings/iio/pressure/honeywell,mprls0025pa.yaml b/Documentation/devicetree/bindings/iio/pressure/honeywell,mprls0025pa.yaml new file mode 100644 index 0000000000000000000000000000000000000000..c0a923febf13a42bd0448d57cffe9e3d689d5c9a --- /dev/null +++ b/Documentation/devicetree/bindings/iio/pressure/honeywell,mprls0025pa.yaml @@ -0,0 +1,104 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/iio/pressure/honeywell,mprls0025pa.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Honeywell mprls0025pa pressure sensor + +maintainers: + - Andreas Klinger + +description: | + Honeywell pressure sensor of model mprls0025pa. + + This sensor has an I2C and SPI interface. Only the I2C interface is + implemented. + + There are many models with different pressure ranges available. The vendor + calls them "mpr series". All of them have the identical programming model and + differ in the pressure range, unit and transfer function. + + To support different models one need to specify the pressure range as well as + the transfer function. Pressure range needs to be converted from its unit to + pascal. + + The transfer function defines the ranges of numerical values delivered by the + sensor. The minimal range value stands for the minimum pressure and the + maximum value also for the maximum pressure with linear relation inside the + range. + + Specifications about the devices can be found at: + https://prod-edam.honeywell.com/content/dam/honeywell-edam/sps/siot/en-us/ + products/sensors/pressure-sensors/board-mount-pressure-sensors/ + micropressure-mpr-series/documents/ + sps-siot-mpr-series-datasheet-32332628-ciid-172626.pdf + +properties: + compatible: + const: honeywell,mprls0025pa + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + reset-gpios: + description: + Optional GPIO for resetting the device. + If not present the device is not resetted during the probe. + maxItems: 1 + + honeywell,pmin-pascal: + description: + Minimum pressure value the sensor can measure in pascal. + $ref: /schemas/types.yaml#/definitions/uint32 + + honeywell,pmax-pascal: + description: + Maximum pressure value the sensor can measure in pascal. + $ref: /schemas/types.yaml#/definitions/uint32 + + honeywell,transfer-function: + description: | + Transfer function which defines the range of valid values delivered by the + sensor. + 1 - A, 10% to 90% of 2^24 (1677722 .. 15099494) + 2 - B, 2.5% to 22.5% of 2^24 (419430 .. 3774874) + 3 - C, 20% to 80% of 2^24 (3355443 .. 13421773) + $ref: /schemas/types.yaml#/definitions/uint32 + + vdd-supply: + description: provide VDD power to the sensor. + +required: + - compatible + - reg + - honeywell,pmin-pascal + - honeywell,pmax-pascal + - honeywell,transfer-function + - vdd-supply + +additionalProperties: false + +examples: + - | + #include + #include + i2c { + #address-cells = <1>; + #size-cells = <0>; + + pressure@18 { + compatible = "honeywell,mprls0025pa"; + reg = <0x18>; + reset-gpios = <&gpio3 19 GPIO_ACTIVE_HIGH>; + interrupt-parent = <&gpio3>; + interrupts = <21 IRQ_TYPE_EDGE_FALLING>; + honeywell,pmin-pascal = <0>; + honeywell,pmax-pascal = <172369>; + honeywell,transfer-function = <1>; + vdd-supply = <&vcc_3v3>; + }; + }; diff --git a/Documentation/devicetree/bindings/iio/st,st-sensors.yaml b/Documentation/devicetree/bindings/iio/st,st-sensors.yaml index 1ff3afca91494e20c195b5325096fae93bf003cb..e450821a741da0c3412cc1d83ce329ea5852a272 100644 --- a/Documentation/devicetree/bindings/iio/st,st-sensors.yaml +++ b/Documentation/devicetree/bindings/iio/st,st-sensors.yaml @@ -84,6 +84,7 @@ properties: - st,lps35hw - description: IMUs enum: + - st,lsm303d-imu - st,lsm9ds0-imu - description: Deprecated bindings enum: diff --git a/Documentation/devicetree/bindings/iio/temperature/melexis,mlx90614.yaml b/Documentation/devicetree/bindings/iio/temperature/melexis,mlx90614.yaml index d6965a0c1cf30ca0c25867e2d3a4a04003b48712..654d31f65d3602e6e91d9c3ec2005ab08adbe0fa 100644 --- a/Documentation/devicetree/bindings/iio/temperature/melexis,mlx90614.yaml +++ b/Documentation/devicetree/bindings/iio/temperature/melexis,mlx90614.yaml @@ -4,7 +4,7 @@ $id: http://devicetree.org/schemas/iio/temperature/melexis,mlx90614.yaml# $schema: http://devicetree.org/meta-schemas/core.yaml# -title: Melexis MLX90614 contactless IR temperature sensor +title: Melexis MLX90614/MLX90615 contactless IR temperature sensor maintainers: - Peter Meerwald @@ -15,7 +15,9 @@ description: | properties: compatible: - const: melexis,mlx90614 + enum: + - melexis,mlx90614 + - melexis,mlx90615 reg: maxItems: 1 diff --git a/Documentation/devicetree/bindings/iio/temperature/ti,tmp006.yaml b/Documentation/devicetree/bindings/iio/temperature/ti,tmp006.yaml new file mode 100644 index 0000000000000000000000000000000000000000..d43002b9bfdc0239772b735bd560ace8ad9d94c3 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/temperature/ti,tmp006.yaml @@ -0,0 +1,42 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/iio/temperature/ti,tmp006.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: TI TMP006 IR thermopile sensor + +maintainers: + - Peter Meerwald + +description: | + TI TMP006 - Infrared Thermopile Sensor in Chip-Scale Package. + https://cdn.sparkfun.com/datasheets/Sensors/Temp/tmp006.pdf + +properties: + compatible: + const: ti,tmp006 + + reg: + maxItems: 1 + + vdd-supply: + description: provide VDD power to the sensor. + +required: + - compatible + - reg + +additionalProperties: false + +examples: + - | + i2c { + #address-cells = <1>; + #size-cells = <0>; + temperature-sensor@40 { + compatible = "ti,tmp006"; + reg = <0x40>; + vdd-supply = <&ldo4_reg>; + }; + }; diff --git a/Documentation/devicetree/bindings/input/atmel,maxtouch.yaml b/Documentation/devicetree/bindings/input/atmel,maxtouch.yaml index 3ec579d635704cf19c23975a8cf8e48a93717b05..c40799355ed75910d43c22d287c64b00a405872a 100644 --- a/Documentation/devicetree/bindings/input/atmel,maxtouch.yaml +++ b/Documentation/devicetree/bindings/input/atmel,maxtouch.yaml @@ -14,6 +14,9 @@ description: | Atmel maXTouch touchscreen or touchpads such as the mXT244 and similar devices. +allOf: + - $ref: input.yaml# + properties: compatible: const: atmel,maxtouch @@ -60,6 +63,10 @@ properties: or experiment to determine which bit corresponds to which input. Use KEY_RESERVED for unused padding values. + linux,keycodes: + minItems: 1 + maxItems: 8 + atmel,wakeup-method: $ref: /schemas/types.yaml#/definitions/uint32 description: | diff --git a/Documentation/devicetree/bindings/input/cypress,cyapa.txt b/Documentation/devicetree/bindings/input/cypress,cyapa.txt deleted file mode 100644 index d3db65916a36393d561749a2ec076d03348083ce..0000000000000000000000000000000000000000 --- a/Documentation/devicetree/bindings/input/cypress,cyapa.txt +++ /dev/null @@ -1,42 +0,0 @@ -Cypress I2C Touchpad - -Required properties: -- compatible: must be "cypress,cyapa". -- reg: I2C address of the chip. -- interrupts: interrupt to which the chip is connected (see interrupt - binding[0]). - -Optional properties: -- wakeup-source: touchpad can be used as a wakeup source. -- pinctrl-names: should be "default" (see pinctrl binding [1]). -- pinctrl-0: a phandle pointing to the pin settings for the device (see - pinctrl binding [1]). -- vcc-supply: a phandle for the regulator supplying 3.3V power. - -[0]: Documentation/devicetree/bindings/interrupt-controller/interrupts.txt -[1]: Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt - -Example: - &i2c0 { - /* ... */ - - /* Cypress Gen3 touchpad */ - touchpad@67 { - compatible = "cypress,cyapa"; - reg = <0x67>; - interrupt-parent = <&gpio>; - interrupts = <2 IRQ_TYPE_EDGE_FALLING>; /* GPIO 2 */ - wakeup-source; - }; - - /* Cypress Gen5 and later touchpad */ - touchpad@24 { - compatible = "cypress,cyapa"; - reg = <0x24>; - interrupt-parent = <&gpio>; - interrupts = <2 IRQ_TYPE_EDGE_FALLING>; /* GPIO 2 */ - wakeup-source; - }; - - /* ... */ - }; diff --git a/Documentation/devicetree/bindings/input/cypress,cyapa.yaml b/Documentation/devicetree/bindings/input/cypress,cyapa.yaml new file mode 100644 index 0000000000000000000000000000000000000000..29515151abe98e2d09884d59a01cc7767236a8f7 --- /dev/null +++ b/Documentation/devicetree/bindings/input/cypress,cyapa.yaml @@ -0,0 +1,49 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/input/cypress,cyapa.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Cypress All Points Addressable (APA) I2C Touchpad / Trackpad + +maintainers: + - Krzysztof Kozlowski + +properties: + compatible: + const: cypress,cyapa + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + wakeup-source: true + + vcc-supply: + description: 3.3V power + +required: + - compatible + - reg + - interrupts + +additionalProperties: false + +examples: + - | + #include + + i2c { + #address-cells = <1>; + #size-cells = <0>; + + trackpad@67 { + reg = <0x67>; + compatible = "cypress,cyapa"; + interrupts = <2 IRQ_TYPE_EDGE_FALLING>; + interrupt-parent = <&gpx1>; + wakeup-source; + }; + }; diff --git a/Documentation/devicetree/bindings/input/goodix,gt7375p.yaml b/Documentation/devicetree/bindings/input/goodix,gt7375p.yaml index ce18d7dadae23d1dd170254742bc1ea2dd8f1c5b..1edad1da1196d043e571fd4ed64425187c03b618 100644 --- a/Documentation/devicetree/bindings/input/goodix,gt7375p.yaml +++ b/Documentation/devicetree/bindings/input/goodix,gt7375p.yaml @@ -43,6 +43,15 @@ properties: itself as long as it allows the main board to make signals compatible with what the touchscreen is expecting for its IO rails. + goodix,no-reset-during-suspend: + description: + Set this to true to enforce the driver to not assert the reset GPIO + during suspend. + Due to potential touchscreen hardware flaw, back-powering could happen in + suspend if the power supply is on and with active-low reset GPIO asserted. + This property is used to avoid the back-powering issue. + type: boolean + required: - compatible - reg diff --git a/Documentation/devicetree/bindings/input/mediatek,pmic-keys.yaml b/Documentation/devicetree/bindings/input/mediatek,pmic-keys.yaml index 037c3ae9f1c33748c8a6fa506afc05419ea2fd7b..e34c9e78d38d8c0d65043ec24438681fe59119ef 100644 --- a/Documentation/devicetree/bindings/input/mediatek,pmic-keys.yaml +++ b/Documentation/devicetree/bindings/input/mediatek,pmic-keys.yaml @@ -55,7 +55,7 @@ patternProperties: interrupt-names: true - linux-keycodes: + linux,keycodes: maxItems: 1 wakeup-source: true diff --git a/Documentation/devicetree/bindings/input/pwm-vibrator.yaml b/Documentation/devicetree/bindings/input/pwm-vibrator.yaml index d32716c604feee2d1d10f4bc5031d49773e81c73..6398534b43c3eb2a8a39124374728e1f6ebb331e 100644 --- a/Documentation/devicetree/bindings/input/pwm-vibrator.yaml +++ b/Documentation/devicetree/bindings/input/pwm-vibrator.yaml @@ -32,6 +32,8 @@ properties: minItems: 1 maxItems: 2 + enable-gpios: true + vcc-supply: true direction-duty-cycle-ns: diff --git a/Documentation/devicetree/bindings/input/touchscreen/cypress,tt21000.yaml b/Documentation/devicetree/bindings/input/touchscreen/cypress,tt21000.yaml index 1959ec3947685e712b01260b96849b13a886a364..4080422a9eb5c2fe26116217e346480323a784ee 100644 --- a/Documentation/devicetree/bindings/input/touchscreen/cypress,tt21000.yaml +++ b/Documentation/devicetree/bindings/input/touchscreen/cypress,tt21000.yaml @@ -40,6 +40,8 @@ properties: linux,keycodes: description: EV_ABS specific event code generated by the axis. + wakeup-source: true + patternProperties: "^button@[0-9]+$": type: object diff --git a/Documentation/devicetree/bindings/interconnect/fsl,imx8m-noc.yaml b/Documentation/devicetree/bindings/interconnect/fsl,imx8m-noc.yaml index f7a5e31c506ee439283b380a5599e3575dbdeeec..fc21fe3e7b37ca89283c76ad1eb3d8e41f9ed719 100644 --- a/Documentation/devicetree/bindings/interconnect/fsl,imx8m-noc.yaml +++ b/Documentation/devicetree/bindings/interconnect/fsl,imx8m-noc.yaml @@ -51,7 +51,7 @@ properties: type: object fsl,ddrc: - $ref: "/schemas/types.yaml#/definitions/phandle" + $ref: /schemas/types.yaml#/definitions/phandle description: Phandle to DDR Controller. diff --git a/Documentation/devicetree/bindings/interrupt-controller/amlogic,meson-gpio-intc.txt b/Documentation/devicetree/bindings/interrupt-controller/amlogic,meson-gpio-intc.txt deleted file mode 100644 index bde63f8f090e965b3a49d0001c8600227384183d..0000000000000000000000000000000000000000 --- a/Documentation/devicetree/bindings/interrupt-controller/amlogic,meson-gpio-intc.txt +++ /dev/null @@ -1,38 +0,0 @@ -Amlogic meson GPIO interrupt controller - -Meson SoCs contains an interrupt controller which is able to watch the SoC -pads and generate an interrupt on edge or level. The controller is essentially -a 256 pads to 8 GIC interrupt multiplexer, with a filter block to select edge -or level and polarity. It does not expose all 256 mux inputs because the -documentation shows that the upper part is not mapped to any pad. The actual -number of interrupt exposed depends on the SoC. - -Required properties: - -- compatible : must have "amlogic,meson8-gpio-intc" and either - "amlogic,meson8-gpio-intc" for meson8 SoCs (S802) or - "amlogic,meson8b-gpio-intc" for meson8b SoCs (S805) or - "amlogic,meson-gxbb-gpio-intc" for GXBB SoCs (S905) or - "amlogic,meson-gxl-gpio-intc" for GXL SoCs (S905X, S912) - "amlogic,meson-axg-gpio-intc" for AXG SoCs (A113D, A113X) - "amlogic,meson-g12a-gpio-intc" for G12A SoCs (S905D2, S905X2, S905Y2) - "amlogic,meson-sm1-gpio-intc" for SM1 SoCs (S905D3, S905X3, S905Y3) - "amlogic,meson-a1-gpio-intc" for A1 SoCs (A113L) - "amlogic,meson-s4-gpio-intc" for S4 SoCs (S802X2, S905Y4, S805X2G, S905W2) -- reg : Specifies base physical address and size of the registers. -- interrupt-controller : Identifies the node as an interrupt controller. -- #interrupt-cells : Specifies the number of cells needed to encode an - interrupt source. The value must be 2. -- meson,channel-interrupts: Array with the 8 upstream hwirq numbers. These - are the hwirqs used on the parent interrupt controller. - -Example: - -gpio_interrupt: interrupt-controller@9880 { - compatible = "amlogic,meson-gxbb-gpio-intc", - "amlogic,meson-gpio-intc"; - reg = <0x0 0x9880 0x0 0x10>; - interrupt-controller; - #interrupt-cells = <2>; - meson,channel-interrupts = <64 65 66 67 68 69 70 71>; -}; diff --git a/Documentation/devicetree/bindings/interrupt-controller/amlogic,meson-gpio-intc.yaml b/Documentation/devicetree/bindings/interrupt-controller/amlogic,meson-gpio-intc.yaml new file mode 100644 index 0000000000000000000000000000000000000000..e84e4f33b3588cddce5293d44596547eaff45044 --- /dev/null +++ b/Documentation/devicetree/bindings/interrupt-controller/amlogic,meson-gpio-intc.yaml @@ -0,0 +1,72 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/interrupt-controller/amlogic,meson-gpio-intc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Amlogic Meson GPIO interrupt controller + +maintainers: + - Heiner Kallweit + +description: | + Meson SoCs contains an interrupt controller which is able to watch the SoC + pads and generate an interrupt on edge or level. The controller is essentially + a 256 pads to 8 or 12 GIC interrupt multiplexer, with a filter block to select + edge or level and polarity. It does not expose all 256 mux inputs because the + documentation shows that the upper part is not mapped to any pad. The actual + number of interrupts exposed depends on the SoC. + +allOf: + - $ref: /schemas/interrupt-controller.yaml# + +properties: + compatible: + oneOf: + - const: amlogic,meson-gpio-intc + - items: + - enum: + - amlogic,meson8-gpio-intc + - amlogic,meson8b-gpio-intc + - amlogic,meson-gxbb-gpio-intc + - amlogic,meson-gxl-gpio-intc + - amlogic,meson-axg-gpio-intc + - amlogic,meson-g12a-gpio-intc + - amlogic,meson-sm1-gpio-intc + - amlogic,meson-a1-gpio-intc + - amlogic,meson-s4-gpio-intc + - const: amlogic,meson-gpio-intc + + reg: + maxItems: 1 + + interrupt-controller: true + + "#interrupt-cells": + const: 2 + + amlogic,channel-interrupts: + description: Array with the upstream hwirq numbers + minItems: 8 + maxItems: 12 + $ref: /schemas/types.yaml#/definitions/uint32-array + +required: + - compatible + - reg + - interrupt-controller + - "#interrupt-cells" + - amlogic,channel-interrupts + +additionalProperties: false + +examples: + - | + interrupt-controller@9880 { + compatible = "amlogic,meson-gxbb-gpio-intc", + "amlogic,meson-gpio-intc"; + reg = <0x9880 0x10>; + interrupt-controller; + #interrupt-cells = <2>; + amlogic,channel-interrupts = <64 65 66 67 68 69 70 71>; + }; diff --git a/Documentation/devicetree/bindings/interrupt-controller/loongson,eiointc.yaml b/Documentation/devicetree/bindings/interrupt-controller/loongson,eiointc.yaml new file mode 100644 index 0000000000000000000000000000000000000000..393c128a41d860ec71ce55822aa2f064d5961643 --- /dev/null +++ b/Documentation/devicetree/bindings/interrupt-controller/loongson,eiointc.yaml @@ -0,0 +1,59 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/interrupt-controller/loongson,eiointc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Loongson Extended I/O Interrupt Controller + +maintainers: + - Binbin Zhou + +description: | + This interrupt controller is found on the Loongson-3 family chips and + Loongson-2K series chips and is used to distribute interrupts directly to + individual cores without forwarding them through the HT's interrupt line. + +allOf: + - $ref: /schemas/interrupt-controller.yaml# + +properties: + compatible: + enum: + - loongson,ls2k0500-eiointc + - loongson,ls2k2000-eiointc + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + interrupt-controller: true + + '#interrupt-cells': + const: 1 + +required: + - compatible + - reg + - interrupts + - interrupt-controller + - '#interrupt-cells' + +unevaluatedProperties: false + +examples: + - | + eiointc: interrupt-controller@1fe11600 { + compatible = "loongson,ls2k0500-eiointc"; + reg = <0x1fe10000 0x10000>; + + interrupt-controller; + #interrupt-cells = <1>; + + interrupt-parent = <&cpuintc>; + interrupts = <3>; + }; + +... diff --git a/Documentation/devicetree/bindings/interrupt-controller/microchip,eic.yaml b/Documentation/devicetree/bindings/interrupt-controller/microchip,sama7g5-eic.yaml similarity index 98% rename from Documentation/devicetree/bindings/interrupt-controller/microchip,eic.yaml rename to Documentation/devicetree/bindings/interrupt-controller/microchip,sama7g5-eic.yaml index 50003880ee6fd9e6ef2b3b7eb887674269efab29..d56ba65b17d1b008221a93970355f916bb5c9c38 100644 --- a/Documentation/devicetree/bindings/interrupt-controller/microchip,eic.yaml +++ b/Documentation/devicetree/bindings/interrupt-controller/microchip,sama7g5-eic.yaml @@ -1,7 +1,7 @@ # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) %YAML 1.2 --- -$id: http://devicetree.org/schemas/interrupt-controller/microchip,eic.yaml# +$id: http://devicetree.org/schemas/interrupt-controller/microchip,sama7g5-eic.yaml# $schema: http://devicetree.org/meta-schemas/core.yaml# title: Microchip External Interrupt Controller diff --git a/Documentation/devicetree/bindings/interrupt-controller/ralink,rt2880-intc.yaml b/Documentation/devicetree/bindings/interrupt-controller/ralink,rt2880-intc.yaml new file mode 100644 index 0000000000000000000000000000000000000000..0fa952a9edfd4c0fc01c802fe125517f4e603930 --- /dev/null +++ b/Documentation/devicetree/bindings/interrupt-controller/ralink,rt2880-intc.yaml @@ -0,0 +1,54 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/interrupt-controller/ralink,rt2880-intc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Ralink SoCs Interrupt Controller + +maintainers: + - Sergio Paracuellos + +allOf: + - $ref: /schemas/interrupt-controller.yaml# + +description: + This interrupt controller support a central point for interrupt aggregation + for platform related blocks. + +properties: + compatible: + const: ralink,rt2880-intc + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + interrupt-controller: true + + '#interrupt-cells': + const: 1 + +required: + - compatible + - reg + - interrupts + - interrupt-controller + - '#interrupt-cells' + +additionalProperties: false + +examples: + - | + interrupt-controller@200 { + compatible = "ralink,rt2880-intc"; + reg = <0x200 0x100>; + interrupt-controller; + #interrupt-cells = <1>; + + interrupt-parent = <&cpuintc>; + interrupts = <2>; + }; +... diff --git a/Documentation/devicetree/bindings/interrupt-controller/sifive,plic-1.0.0.yaml b/Documentation/devicetree/bindings/interrupt-controller/sifive,plic-1.0.0.yaml index f75736a061af7778b86505f9a5696adc6d29a0c1..dc1f28e552660c83ad1cafabf999662a336ed85d 100644 --- a/Documentation/devicetree/bindings/interrupt-controller/sifive,plic-1.0.0.yaml +++ b/Documentation/devicetree/bindings/interrupt-controller/sifive,plic-1.0.0.yaml @@ -57,14 +57,15 @@ properties: - const: andestech,nceplic100 - items: - enum: + - canaan,k210-plic - sifive,fu540-c000-plic - starfive,jh7100-plic - starfive,jh7110-plic - - canaan,k210-plic - const: sifive,plic-1.0.0 - items: - enum: - allwinner,sun20i-d1-plic + - thead,th1520-plic - const: thead,c900-plic - items: - const: sifive,plic-1.0.0 diff --git a/Documentation/devicetree/bindings/iommu/arm,smmu.yaml b/Documentation/devicetree/bindings/iommu/arm,smmu.yaml index ba677d401e24000ae70520898581c20122fa7ac9..3a31a979709b6588ac990a8e69dd920cd20bc49e 100644 --- a/Documentation/devicetree/bindings/iommu/arm,smmu.yaml +++ b/Documentation/devicetree/bindings/iommu/arm,smmu.yaml @@ -29,6 +29,7 @@ properties: - qcom,msm8996-smmu-v2 - qcom,msm8998-smmu-v2 - qcom,sdm630-smmu-v2 + - qcom,sm6375-smmu-v2 - const: qcom,smmu-v2 - description: Qcom SoCs implementing "qcom,smmu-500" and "arm,mmu-500" @@ -45,6 +46,7 @@ properties: - qcom,sdm845-smmu-500 - qcom,sdx55-smmu-500 - qcom,sdx65-smmu-500 + - qcom,sdx75-smmu-500 - qcom,sm6115-smmu-500 - qcom,sm6125-smmu-500 - qcom,sm6350-smmu-500 @@ -79,7 +81,9 @@ properties: - description: Qcom Adreno GPUs implementing "qcom,smmu-500" and "arm,mmu-500" items: - enum: + - qcom,sa8775p-smmu-500 - qcom,sc7280-smmu-500 + - qcom,sc8280xp-smmu-500 - qcom,sm6115-smmu-500 - qcom,sm6125-smmu-500 - qcom,sm8150-smmu-500 @@ -267,6 +271,7 @@ allOf: enum: - qcom,msm8998-smmu-v2 - qcom,sdm630-smmu-v2 + - qcom,sm6375-smmu-v2 then: anyOf: - properties: @@ -331,7 +336,10 @@ allOf: properties: compatible: contains: - const: qcom,sc7280-smmu-500 + enum: + - qcom,sa8775p-smmu-500 + - qcom,sc7280-smmu-500 + - qcom,sc8280xp-smmu-500 then: properties: clock-names: @@ -413,10 +421,8 @@ allOf: - nvidia,smmu-500 - qcom,qcm2290-smmu-500 - qcom,qdu1000-smmu-500 - - qcom,sa8775p-smmu-500 - qcom,sc7180-smmu-500 - qcom,sc8180x-smmu-500 - - qcom,sc8280xp-smmu-500 - qcom,sdm670-smmu-500 - qcom,sdm845-smmu-500 - qcom,sdx55-smmu-500 diff --git a/Documentation/devicetree/bindings/leds/awinic,aw200xx.yaml b/Documentation/devicetree/bindings/leds/awinic,aw200xx.yaml new file mode 100644 index 0000000000000000000000000000000000000000..feb5febaf361aef71a2b419d0fe50adc21c67c62 --- /dev/null +++ b/Documentation/devicetree/bindings/leds/awinic,aw200xx.yaml @@ -0,0 +1,126 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/leds/awinic,aw200xx.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: AWINIC AW200XX LED + +maintainers: + - Martin Kurbanov + +description: | + This controller is present on AW20036/AW20054/AW20072. + It is a 3x12/6x9/6x12 matrix LED programmed via + an I2C interface, up to 36/54/72 LEDs or 12/18/24 RGBs, + 3 pattern controllers for auto breathing or group dimming control. + + For more product information please see the link below: + aw20036 - https://www.awinic.com/en/productDetail/AW20036QNR#tech-docs + aw20054 - https://www.awinic.com/en/productDetail/AW20054QNR#tech-docs + aw20072 - https://www.awinic.com/en/productDetail/AW20072QNR#tech-docs + +properties: + compatible: + enum: + - awinic,aw20036 + - awinic,aw20054 + - awinic,aw20072 + + reg: + maxItems: 1 + + "#address-cells": + const: 1 + + "#size-cells": + const: 0 + + awinic,display-rows: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + Leds matrix size + +patternProperties: + "^led@[0-9a-f]$": + type: object + $ref: common.yaml# + unevaluatedProperties: false + + properties: + reg: + description: + LED number + maxItems: 1 + + led-max-microamp: + default: 9780 + description: | + Note that a driver will take the minimum of all LED limits + since the chip has a single global setting. + The maximum output current of each LED is calculated by the + following formula: + IMAXled = 160000 * (592 / 600.5) * (1 / display-rows) + And the minimum output current formula: + IMINled = 3300 * (592 / 600.5) * (1 / display-rows) + +required: + - compatible + - reg + - "#address-cells" + - "#size-cells" + - awinic,display-rows + +allOf: + - if: + properties: + compatible: + contains: + const: awinic,aw20036 + then: + properties: + awinic,display-rows: + enum: [1, 2, 3] + else: + properties: + awinic,display-rows: + enum: [1, 2, 3, 4, 5, 6, 7] + +additionalProperties: false + +examples: + - | + #include + + i2c { + #address-cells = <1>; + #size-cells = <0>; + + led-controller@3a { + compatible = "awinic,aw20036"; + reg = <0x3a>; + #address-cells = <1>; + #size-cells = <0>; + awinic,display-rows = <3>; + + led@0 { + reg = <0x0>; + color = ; + led-max-microamp = <9780>; + }; + + led@1 { + reg = <0x1>; + color = ; + led-max-microamp = <9780>; + }; + + led@2 { + reg = <0x2>; + color = ; + led-max-microamp = <9780>; + }; + }; + }; + +... diff --git a/Documentation/devicetree/bindings/leds/backlight/kinetic,ktz8866.yaml b/Documentation/devicetree/bindings/leds/backlight/kinetic,ktz8866.yaml index e1191453c2f0c0facf016af10b1e2e84a550b690..c914e12769825f9436657c8f9153cbee32ecc5cf 100644 --- a/Documentation/devicetree/bindings/leds/backlight/kinetic,ktz8866.yaml +++ b/Documentation/devicetree/bindings/leds/backlight/kinetic,ktz8866.yaml @@ -21,6 +21,9 @@ properties: compatible: const: kinetic,ktz8866 + reg: + maxItems: 1 + vddpos-supply: description: positive boost supply regulator. @@ -33,6 +36,7 @@ properties: current-num-sinks: description: number of the LED current sinks' channels. + $ref: /schemas/types.yaml#/definitions/uint32 enum: [1, 2, 3, 4, 5, 6] kinetic,current-ramp-delay-ms: @@ -53,6 +57,7 @@ properties: required: - compatible + - reg - vddpos-supply - vddneg-supply - enable-gpios @@ -63,14 +68,19 @@ examples: - | #include - backlight { - compatible = "kinetic,ktz8866"; - - vddpos-supply = <&bl_vddpos_5p5>; - vddneg-supply = <&bl_vddneg_5p5>; - enable-gpios = <&tlmm 139 GPIO_ACTIVE_HIGH>; - current-num-sinks = <5>; - kinetic,current-ramp-delay-ms = <128>; - kinetic,led-enable-ramp-delay-ms = <1>; - kinetic,enable-lcd-bias; + i2c { + #address-cells = <1>; + #size-cells = <0>; + + backlight@11 { + compatible = "kinetic,ktz8866"; + reg = <0x11>; + vddpos-supply = <&bl_vddpos_5p5>; + vddneg-supply = <&bl_vddneg_5p5>; + enable-gpios = <&tlmm 139 GPIO_ACTIVE_HIGH>; + current-num-sinks = <5>; + kinetic,current-ramp-delay-ms = <128>; + kinetic,led-enable-ramp-delay-ms = <1>; + kinetic,enable-lcd-bias; + }; }; diff --git a/Documentation/devicetree/bindings/leds/backlight/lp855x-backlight.yaml b/Documentation/devicetree/bindings/leds/backlight/lp855x-backlight.yaml new file mode 100644 index 0000000000000000000000000000000000000000..9416e1bfab92c10cfe48ae65fbd5fab95e3548c8 --- /dev/null +++ b/Documentation/devicetree/bindings/leds/backlight/lp855x-backlight.yaml @@ -0,0 +1,149 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/leds/backlight/lp855x-backlight.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Texas Instruments LP855X backlight controllers + +maintainers: + - Artur Weber + +properties: + compatible: + enum: + - ti,lp8550 + - ti,lp8551 + - ti,lp8552 + - ti,lp8553 + - ti,lp8555 + - ti,lp8556 + - ti,lp8557 + + reg: + maxItems: 1 + + dev-ctrl: + $ref: /schemas/types.yaml#/definitions/uint8 + description: + Value of device control register. This is a device-specific value. + + bl-name: + $ref: /schemas/types.yaml#/definitions/string + description: Backlight device name. + + init-brt: + $ref: /schemas/types.yaml#/definitions/uint8 + description: Initial value of backlight brightness. + + power-supply: + description: Regulator which controls the 3V rail. + + enable-supply: + description: Regulator which controls the EN/VDDIO input. + + pwms: + maxItems: 1 + description: | + PWM channel to use for controlling the backlight; setting this + enables the PWM-based backlight control mode. + + pwm-names: true + + pwm-period: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + PWM period value. Deprecated; set the period value in the pwms + property instead. + deprecated: true + +patternProperties: + "^rom-[0-9a-f]{2}h$": + type: object + description: Nodes containing the values of configuration registers. + additionalProperties: false + properties: + rom-addr: + $ref: /schemas/types.yaml#/definitions/uint8 + description: Register address of ROM area to be updated. + + rom-val: + $ref: /schemas/types.yaml#/definitions/uint8 + description: Value to write to the ROM register. + +required: + - compatible + - reg + - dev-ctrl + +unevaluatedProperties: false + +examples: + - | + i2c { + #address-cells = <1>; + #size-cells = <0>; + + backlight@2c { + compatible = "ti,lp8555"; + reg = <0x2c>; + + dev-ctrl = /bits/ 8 <0x00>; + + pwms = <&pwm 0 10000>; + pwm-names = "lp8555"; + + /* 4V OV, 4 output LED0 string enabled */ + rom-14h { + rom-addr = /bits/ 8 <0x14>; + rom-val = /bits/ 8 <0xcf>; + }; + + /* Heavy smoothing, 24ms ramp time step */ + rom-15h { + rom-addr = /bits/ 8 <0x15>; + rom-val = /bits/ 8 <0xc7>; + }; + + /* 4 output LED1 string enabled */ + rom-19h { + rom-addr = /bits/ 8 <0x19>; + rom-val = /bits/ 8 <0x0f>; + }; + }; + }; + - | + i2c { + #address-cells = <1>; + #size-cells = <0>; + + backlight@2c { + compatible = "ti,lp8556"; + reg = <0x2c>; + + bl-name = "lcd-bl"; + dev-ctrl = /bits/ 8 <0x85>; + init-brt = /bits/ 8 <0x10>; + }; + }; + - | + i2c { + #address-cells = <1>; + #size-cells = <0>; + + backlight@2c { + compatible = "ti,lp8557"; + reg = <0x2c>; + enable-supply = <&backlight_vddio>; + power-supply = <&backlight_vdd>; + + dev-ctrl = /bits/ 8 <0x41>; + init-brt = /bits/ 8 <0x0a>; + + /* 4V OV, 4 output LED string enabled */ + rom-14h { + rom-addr = /bits/ 8 <0x14>; + rom-val = /bits/ 8 <0xcf>; + }; + }; + }; diff --git a/Documentation/devicetree/bindings/leds/backlight/lp855x.txt b/Documentation/devicetree/bindings/leds/backlight/lp855x.txt deleted file mode 100644 index 88f56641fc2858addfba1c7ebba2e6b6ef141789..0000000000000000000000000000000000000000 --- a/Documentation/devicetree/bindings/leds/backlight/lp855x.txt +++ /dev/null @@ -1,72 +0,0 @@ -lp855x bindings - -Required properties: - - compatible: "ti,lp8550", "ti,lp8551", "ti,lp8552", "ti,lp8553", - "ti,lp8555", "ti,lp8556", "ti,lp8557" - - reg: I2C slave address (u8) - - dev-ctrl: Value of DEVICE CONTROL register (u8). It depends on the device. - -Optional properties: - - bl-name: Backlight device name (string) - - init-brt: Initial value of backlight brightness (u8) - - pwm-period: PWM period value. Set only PWM input mode used (u32) - - rom-addr: Register address of ROM area to be updated (u8) - - rom-val: Register value to be updated (u8) - - power-supply: Regulator which controls the 3V rail - - enable-supply: Regulator which controls the EN/VDDIO input - -Example: - - /* LP8555 */ - backlight@2c { - compatible = "ti,lp8555"; - reg = <0x2c>; - - dev-ctrl = /bits/ 8 <0x00>; - pwm-period = <10000>; - - /* 4V OV, 4 output LED0 string enabled */ - rom_14h { - rom-addr = /bits/ 8 <0x14>; - rom-val = /bits/ 8 <0xcf>; - }; - - /* Heavy smoothing, 24ms ramp time step */ - rom_15h { - rom-addr = /bits/ 8 <0x15>; - rom-val = /bits/ 8 <0xc7>; - }; - - /* 4 output LED1 string enabled */ - rom_19h { - rom-addr = /bits/ 8 <0x19>; - rom-val = /bits/ 8 <0x0f>; - }; - }; - - /* LP8556 */ - backlight@2c { - compatible = "ti,lp8556"; - reg = <0x2c>; - - bl-name = "lcd-bl"; - dev-ctrl = /bits/ 8 <0x85>; - init-brt = /bits/ 8 <0x10>; - }; - - /* LP8557 */ - backlight@2c { - compatible = "ti,lp8557"; - reg = <0x2c>; - enable-supply = <&backlight_vddio>; - power-supply = <&backlight_vdd>; - - dev-ctrl = /bits/ 8 <0x41>; - init-brt = /bits/ 8 <0x0a>; - - /* 4V OV, 4 output LED string enabled */ - rom_14h { - rom-addr = /bits/ 8 <0x14>; - rom-val = /bits/ 8 <0xcf>; - }; - }; diff --git a/Documentation/devicetree/bindings/leds/backlight/pwm-backlight.yaml b/Documentation/devicetree/bindings/leds/backlight/pwm-backlight.yaml index 5ec47a8c6568b60e617bd9deacbb149ccd3447de..53569028899020d67b22f32b124e466ad92504c4 100644 --- a/Documentation/devicetree/bindings/leds/backlight/pwm-backlight.yaml +++ b/Documentation/devicetree/bindings/leds/backlight/pwm-backlight.yaml @@ -68,7 +68,6 @@ dependencies: required: - compatible - pwms - - power-supply additionalProperties: false diff --git a/Documentation/devicetree/bindings/leds/common.yaml b/Documentation/devicetree/bindings/leds/common.yaml index 11aedf1650a1263bebe66b2ad1194699c2f16124..58b492d002464dc2363facacaeea7b1b627dba21 100644 --- a/Documentation/devicetree/bindings/leds/common.yaml +++ b/Documentation/devicetree/bindings/leds/common.yaml @@ -105,8 +105,6 @@ properties: - audio-mute # LED indicates bluetooth power state - bluetooth-power - # LED indicates activity of all CPUs - - cpu # LED indicates camera flash state - flash # LED indicated keyboard capslock diff --git a/Documentation/devicetree/bindings/leds/leds-class-multicolor.yaml b/Documentation/devicetree/bindings/leds/leds-class-multicolor.yaml index 31840e33dcf55220062b45401433a50ded57515a..e850a8894758df1b8520ee768c4465b493c48ecf 100644 --- a/Documentation/devicetree/bindings/leds/leds-class-multicolor.yaml +++ b/Documentation/devicetree/bindings/leds/leds-class-multicolor.yaml @@ -34,7 +34,7 @@ required: - color allOf: - - $ref: "common.yaml#" + - $ref: common.yaml# additionalProperties: true diff --git a/Documentation/devicetree/bindings/leds/leds-lp55xx.yaml b/Documentation/devicetree/bindings/leds/leds-lp55xx.yaml index ae607911f1dbdb5bbb76761d15ca08a575f597e1..058be1fedbc88160a7b05e26336cafc9607f22ea 100644 --- a/Documentation/devicetree/bindings/leds/leds-lp55xx.yaml +++ b/Documentation/devicetree/bindings/leds/leds-lp55xx.yaml @@ -66,6 +66,14 @@ properties: '#size-cells': const: 0 + ti,charge-pump-mode: + description: + Set the operating mode of the internal charge pump as defined in + . + $ref: /schemas/types.yaml#/definitions/uint32 + default: 3 # auto + maximum: 3 + patternProperties: '^multi-led@[0-8]$': type: object @@ -152,6 +160,7 @@ additionalProperties: false examples: - | #include + #include i2c { #address-cells = <1>; @@ -164,6 +173,7 @@ examples: reg = <0x32>; clock-mode = /bits/ 8 <2>; pwr-sel = /bits/ 8 <3>; /* D1~9 connected to VOUT */ + ti,charge-pump-mode = ; led@0 { reg = <0>; diff --git a/Documentation/devicetree/bindings/leds/leds-mt6323.txt b/Documentation/devicetree/bindings/leds/leds-mt6323.txt index 73353692efa1c57c606d6c9116c5bc9e23a4175b..052dccb8f2ce0fddc4329f42877a9fb2a94488d0 100644 --- a/Documentation/devicetree/bindings/leds/leds-mt6323.txt +++ b/Documentation/devicetree/bindings/leds/leds-mt6323.txt @@ -12,7 +12,10 @@ For MediaTek PMIC wrapper bindings see: Documentation/devicetree/bindings/soc/mediatek/mediatek,pwrap.yaml Required properties: -- compatible : Must be "mediatek,mt6323-led" +- compatible : Must be one of + - "mediatek,mt6323-led" + - "mediatek,mt6331-led" + - "mediatek,mt6332-led" - address-cells : Must be 1 - size-cells : Must be 0 diff --git a/Documentation/devicetree/bindings/leds/leds-qcom-lpg.yaml b/Documentation/devicetree/bindings/leds/leds-qcom-lpg.yaml index 6295c91f43e84c704b476445d223432f93610563..e6f1999cb22f53cc71ad615df95445b69679d513 100644 --- a/Documentation/devicetree/bindings/leds/leds-qcom-lpg.yaml +++ b/Documentation/devicetree/bindings/leds/leds-qcom-lpg.yaml @@ -16,18 +16,24 @@ description: > properties: compatible: - enum: - - qcom,pm660l-lpg - - qcom,pm8150b-lpg - - qcom,pm8150l-lpg - - qcom,pm8350c-pwm - - qcom,pm8916-pwm - - qcom,pm8941-lpg - - qcom,pm8994-lpg - - qcom,pmc8180c-lpg - - qcom,pmi8994-lpg - - qcom,pmi8998-lpg - - qcom,pmk8550-pwm + oneOf: + - enum: + - qcom,pm660l-lpg + - qcom,pm8150b-lpg + - qcom,pm8150l-lpg + - qcom,pm8350c-pwm + - qcom,pm8916-pwm + - qcom,pm8941-lpg + - qcom,pm8994-lpg + - qcom,pmc8180c-lpg + - qcom,pmi632-lpg + - qcom,pmi8994-lpg + - qcom,pmi8998-lpg + - qcom,pmk8550-pwm + - items: + - enum: + - qcom,pm8550-pwm + - const: qcom,pm8350c-pwm "#pwm-cells": const: 2 diff --git a/Documentation/devicetree/bindings/leds/leds-sgm3140.yaml b/Documentation/devicetree/bindings/leds/leds-sgm3140.yaml index 4d2ffe5fcfc79045faac9ef13e43950ecd028d5b..37d2a93780abb97dd71b849b6d3f3c55ef82453e 100644 --- a/Documentation/devicetree/bindings/leds/leds-sgm3140.yaml +++ b/Documentation/devicetree/bindings/leds/leds-sgm3140.yaml @@ -20,6 +20,7 @@ properties: compatible: enum: - ocs,ocp8110 + - richtek,rt5033-led - sgmicro,sgm3140 enable-gpios: diff --git a/Documentation/devicetree/bindings/leds/qcom,spmi-flash-led.yaml b/Documentation/devicetree/bindings/leds/qcom,spmi-flash-led.yaml index ffacf703d9f97139a909149f14ae22e91f1eaf03..a8736fd5a5390e5bd45f64d944dfd5e291a9b85e 100644 --- a/Documentation/devicetree/bindings/leds/qcom,spmi-flash-led.yaml +++ b/Documentation/devicetree/bindings/leds/qcom,spmi-flash-led.yaml @@ -26,6 +26,8 @@ properties: - qcom,pm8150c-flash-led - qcom,pm8150l-flash-led - qcom,pm8350c-flash-led + - qcom,pm8550-flash-led + - qcom,pmi8998-flash-led - const: qcom,spmi-flash-led reg: diff --git a/Documentation/devicetree/bindings/leds/rohm,bd71828-leds.yaml b/Documentation/devicetree/bindings/leds/rohm,bd71828-leds.yaml index 64b0be9cf70bce3eb1a65e095a324c35f1f5e372..58f0d94c6d7168e03995b4f4e264e512fb9114b8 100644 --- a/Documentation/devicetree/bindings/leds/rohm,bd71828-leds.yaml +++ b/Documentation/devicetree/bindings/leds/rohm,bd71828-leds.yaml @@ -32,7 +32,7 @@ patternProperties: properties: rohm,led-compatible: description: LED identification string - $ref: "/schemas/types.yaml#/definitions/string" + $ref: /schemas/types.yaml#/definitions/string enum: - bd71828-ambled - bd71828-grnled diff --git a/Documentation/devicetree/bindings/mailbox/brcm,bcm2835-mbox.txt b/Documentation/devicetree/bindings/mailbox/brcm,bcm2835-mbox.txt deleted file mode 100644 index b48d7d30012cbc000aea6536065fd3e24dc846d9..0000000000000000000000000000000000000000 --- a/Documentation/devicetree/bindings/mailbox/brcm,bcm2835-mbox.txt +++ /dev/null @@ -1,26 +0,0 @@ -Broadcom BCM2835 VideoCore mailbox IPC - -Required properties: - -- compatible: Should be "brcm,bcm2835-mbox" -- reg: Specifies base physical address and size of the registers -- interrupts: The interrupt number - See bindings/interrupt-controller/brcm,bcm2835-armctrl-ic.txt -- #mbox-cells: Specifies the number of cells needed to encode a mailbox - channel. The value shall be 0, since there is only one - mailbox channel implemented by the device. - -Example: - -mailbox: mailbox@7e00b880 { - compatible = "brcm,bcm2835-mbox"; - reg = <0x7e00b880 0x40>; - interrupts = <0 1>; - #mbox-cells = <0>; -}; - -firmware: firmware { - compatible = "raspberrypi,firmware"; - mboxes = <&mailbox>; - #power-domain-cells = <1>; -}; diff --git a/Documentation/devicetree/bindings/mailbox/brcm,bcm2835-mbox.yaml b/Documentation/devicetree/bindings/mailbox/brcm,bcm2835-mbox.yaml new file mode 100644 index 0000000000000000000000000000000000000000..9588817f4511507fa2d7e278f9f05db552d24c8b --- /dev/null +++ b/Documentation/devicetree/bindings/mailbox/brcm,bcm2835-mbox.yaml @@ -0,0 +1,40 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/mailbox/brcm,bcm2835-mbox.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Broadcom BCM2835 VideoCore mailbox IPC + +maintainers: + - Stefan Wahren + +properties: + compatible: + const: brcm,bcm2835-mbox + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + "#mbox-cells": + const: 0 + +required: + - compatible + - reg + - interrupts + - "#mbox-cells" + +additionalProperties: false + +examples: + - | + mailbox@7e00b880 { + compatible = "brcm,bcm2835-mbox"; + reg = <0x7e00b880 0x40>; + interrupts = <0 1>; + #mbox-cells = <0>; + }; diff --git a/Documentation/devicetree/bindings/mailbox/nvidia,tegra186-hsp.yaml b/Documentation/devicetree/bindings/mailbox/nvidia,tegra186-hsp.yaml index a3e87516d637d8f9596bd41b68f10db543ea97ff..2d14fc9489998a8dbe5356e2422748a228693d7a 100644 --- a/Documentation/devicetree/bindings/mailbox/nvidia,tegra186-hsp.yaml +++ b/Documentation/devicetree/bindings/mailbox/nvidia,tegra186-hsp.yaml @@ -66,6 +66,7 @@ properties: oneOf: - const: nvidia,tegra186-hsp - const: nvidia,tegra194-hsp + - const: nvidia,tegra264-hsp - items: - const: nvidia,tegra234-hsp - const: nvidia,tegra194-hsp diff --git a/Documentation/devicetree/bindings/mailbox/qcom,apcs-kpss-global.yaml b/Documentation/devicetree/bindings/mailbox/qcom,apcs-kpss-global.yaml index 32d7bbc98cace83d2b4272580ab1feb5b22f40d4..d2e25ff6db7f66af7b509afb75d510ce0bff1980 100644 --- a/Documentation/devicetree/bindings/mailbox/qcom,apcs-kpss-global.yaml +++ b/Documentation/devicetree/bindings/mailbox/qcom,apcs-kpss-global.yaml @@ -18,6 +18,7 @@ properties: oneOf: - items: - enum: + - qcom,ipq5018-apcs-apps-global - qcom,ipq5332-apcs-apps-global - qcom,ipq8074-apcs-apps-global - qcom,ipq9574-apcs-apps-global diff --git a/Documentation/devicetree/bindings/mailbox/xlnx,zynqmp-ipi-mailbox.yaml b/Documentation/devicetree/bindings/mailbox/xlnx,zynqmp-ipi-mailbox.yaml index 374ffe64016f3f5059320918f5058fb544f832b4..aeaddbf574b0b1207a1caadfa8dd46c134cb8350 100644 --- a/Documentation/devicetree/bindings/mailbox/xlnx,zynqmp-ipi-mailbox.yaml +++ b/Documentation/devicetree/bindings/mailbox/xlnx,zynqmp-ipi-mailbox.yaml @@ -33,7 +33,7 @@ description: | +------------------------------------------+ maintainers: - - Shubhrajyoti Datta + - Shubhrajyoti Datta properties: compatible: diff --git a/Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml b/Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml index 444f24838d3d8992d96b6c56d8e040adb99dcc8d..6c72e77b927c0d5917063b87464b5c109694b463 100644 --- a/Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml +++ b/Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml @@ -65,9 +65,14 @@ properties: properties: data-lanes: true + bus-type: + enum: + - 1 # MEDIA_BUS_TYPE_CSI2_CPHY + - 4 # MEDIA_BUS_TYPE_CSI2_DPHY required: - data-lanes + - bus-type required: - port@4 @@ -82,6 +87,7 @@ additionalProperties: false examples: - | #include + #include i2c@e6508000 { #address-cells = <1>; @@ -101,6 +107,7 @@ examples: port@4 { reg = <4>; max96712_out0: endpoint { + bus-type = ; clock-lanes = <0>; data-lanes = <1 2 3 4>; remote-endpoint = <&csi40_in>; diff --git a/Documentation/devicetree/bindings/media/qcom,msm8916-camss.yaml b/Documentation/devicetree/bindings/media/qcom,msm8916-camss.yaml index eb1499912c58415093371dded1dc12c4103c94fd..9cc0a968a401836814560c1af3ee84d946500b4f 100644 --- a/Documentation/devicetree/bindings/media/qcom,msm8916-camss.yaml +++ b/Documentation/devicetree/bindings/media/qcom,msm8916-camss.yaml @@ -155,7 +155,7 @@ examples: #include #include - camss: camss@1b00000 { + camss: camss@1b0ac00 { compatible = "qcom,msm8916-camss"; clocks = <&gcc GCC_CAMSS_TOP_AHB_CLK>, diff --git a/Documentation/devicetree/bindings/media/qcom,msm8996-camss.yaml b/Documentation/devicetree/bindings/media/qcom,msm8996-camss.yaml index 8a10aa1cafc50308d92f9d159651d422542d4565..5cb0e337ea6e4274dbb75b7b25a9b4ac44069cfd 100644 --- a/Documentation/devicetree/bindings/media/qcom,msm8996-camss.yaml +++ b/Documentation/devicetree/bindings/media/qcom,msm8996-camss.yaml @@ -221,7 +221,7 @@ examples: #include #include - camss: camss@a00000 { + camss: camss@a34000 { compatible = "qcom,msm8996-camss"; clocks = <&mmcc CAMSS_TOP_AHB_CLK>, diff --git a/Documentation/devicetree/bindings/media/qcom,sdm660-camss.yaml b/Documentation/devicetree/bindings/media/qcom,sdm660-camss.yaml index 0a109e126064d8e105cea9edee9fca650b393554..584106e275f67aca814de5dd70563d395305399c 100644 --- a/Documentation/devicetree/bindings/media/qcom,sdm660-camss.yaml +++ b/Documentation/devicetree/bindings/media/qcom,sdm660-camss.yaml @@ -227,7 +227,7 @@ examples: #include #include - camss: camss@ca00000 { + camss: camss@ca00020 { compatible = "qcom,sdm660-camss"; clocks = <&mmcc CAMSS_AHB_CLK>, diff --git a/Documentation/devicetree/bindings/media/qcom,sdm845-camss.yaml b/Documentation/devicetree/bindings/media/qcom,sdm845-camss.yaml index 1530ad0d80bdcacd44408b901b370fda18f7e8f3..ec4380a0a03f7dce2539085e24d9d9ec7205e825 100644 --- a/Documentation/devicetree/bindings/media/qcom,sdm845-camss.yaml +++ b/Documentation/devicetree/bindings/media/qcom,sdm845-camss.yaml @@ -219,7 +219,7 @@ examples: #address-cells = <2>; #size-cells = <2>; - camss: camss@a00000 { + camss: camss@acb3000 { compatible = "qcom,sdm845-camss"; clocks = <&clock_camcc CAM_CC_CAMNOC_AXI_CLK>, diff --git a/Documentation/devicetree/bindings/media/renesas,rzg2l-cru.yaml b/Documentation/devicetree/bindings/media/renesas,rzg2l-cru.yaml index 7dde7967c8869dfd5ffae6d343d2667f69a89533..1e72b8808d2485b7d560cee06d09ee2447e84e1d 100644 --- a/Documentation/devicetree/bindings/media/renesas,rzg2l-cru.yaml +++ b/Documentation/devicetree/bindings/media/renesas,rzg2l-cru.yaml @@ -137,7 +137,7 @@ examples: cru_parallel_in: endpoint@0 { reg = <0>; - remote-endpoint= <&ov5642>; + remote-endpoint = <&ov5642>; hsync-active = <1>; vsync-active = <1>; }; @@ -150,7 +150,7 @@ examples: cru_csi_in: endpoint@0 { reg = <0>; - remote-endpoint= <&csi_cru_in>; + remote-endpoint = <&csi_cru_in>; }; }; }; diff --git a/Documentation/devicetree/bindings/media/renesas,vin.yaml b/Documentation/devicetree/bindings/media/renesas,vin.yaml index 91e8f368fb520a3d6b1be2196dbba9cf49a8ebf1..324703bfb1bded3ad28ded83202b8f5293935dbb 100644 --- a/Documentation/devicetree/bindings/media/renesas,vin.yaml +++ b/Documentation/devicetree/bindings/media/renesas,vin.yaml @@ -303,11 +303,11 @@ examples: vin0csi20: endpoint@0 { reg = <0>; - remote-endpoint= <&csi20vin0>; + remote-endpoint = <&csi20vin0>; }; vin0csi40: endpoint@2 { reg = <2>; - remote-endpoint= <&csi40vin0>; + remote-endpoint = <&csi40vin0>; }; }; }; diff --git a/Documentation/devicetree/bindings/media/rockchip-rga.yaml b/Documentation/devicetree/bindings/media/rockchip-rga.yaml index dd645ddccb075af90b8355a1a1f2ca69053bdd57..ea234222240864ecfb74f6d320cef9135edcc6dc 100644 --- a/Documentation/devicetree/bindings/media/rockchip-rga.yaml +++ b/Documentation/devicetree/bindings/media/rockchip-rga.yaml @@ -21,7 +21,9 @@ properties: - const: rockchip,rk3288-rga - const: rockchip,rk3399-rga - items: - - const: rockchip,rk3228-rga + - enum: + - rockchip,rk3228-rga + - rockchip,rk3568-rga - const: rockchip,rk3288-rga reg: diff --git a/Documentation/devicetree/bindings/media/rockchip-vpu.yaml b/Documentation/devicetree/bindings/media/rockchip-vpu.yaml index ee622a8ee1ccb6b2e99894996d735dee20f5ea13..772ec3283bc6ce29dd77aa0bcff5dc5c8ed4cf32 100644 --- a/Documentation/devicetree/bindings/media/rockchip-vpu.yaml +++ b/Documentation/devicetree/bindings/media/rockchip-vpu.yaml @@ -24,6 +24,7 @@ properties: - rockchip,rk3399-vpu - rockchip,px30-vpu - rockchip,rk3568-vpu + - rockchip,rk3588-av1-vpu - items: - const: rockchip,rk3188-vpu - const: rockchip,rk3066-vpu diff --git a/Documentation/devicetree/bindings/media/s5p-mfc.txt b/Documentation/devicetree/bindings/media/s5p-mfc.txt index 8eb90c043d5d80e58ec5a6177dc1caa39ae0022a..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 --- a/Documentation/devicetree/bindings/media/s5p-mfc.txt +++ b/Documentation/devicetree/bindings/media/s5p-mfc.txt @@ -1,78 +0,0 @@ -* Samsung Multi Format Codec (MFC) - -Multi Format Codec (MFC) is the IP present in Samsung SoCs which -supports high resolution decoding and encoding functionalities. -The MFC device driver is a v4l2 driver which can encode/decode -video raw/elementary streams and has support for all popular -video codecs. - -Required properties: - - compatible : value should be either one among the following - (a) "samsung,mfc-v5" for MFC v5 present in Exynos4 SoCs - (b) "samsung,mfc-v6" for MFC v6 present in Exynos5 SoCs - (c) "samsung,exynos3250-mfc", "samsung,mfc-v7" for MFC v7 - present in Exynos3250 SoC - (d) "samsung,mfc-v7" for MFC v7 present in Exynos5420 SoC - (e) "samsung,mfc-v8" for MFC v8 present in Exynos5800 SoC - (f) "samsung,exynos5433-mfc" for MFC v8 present in Exynos5433 SoC - (g) "samsung,mfc-v10" for MFC v10 present in Exynos7880 SoC - - - reg : Physical base address of the IP registers and length of memory - mapped region. - - - interrupts : MFC interrupt number to the CPU. - - clocks : from common clock binding: handle to mfc clock. - - clock-names : from common clock binding: must contain "mfc", - corresponding to entry in the clocks property. - -Optional properties: - - power-domains : power-domain property defined with a phandle - to respective power domain. - - memory-region : from reserved memory binding: phandles to two reserved - memory regions, first is for "left" mfc memory bus interfaces, - second if for the "right" mfc memory bus, used when no SYSMMU - support is available; used only by MFC v5 present in Exynos4 SoCs - -Obsolete properties: - - samsung,mfc-r, samsung,mfc-l : support removed, please use memory-region - property instead - - -Example: -SoC specific DT entry: - -mfc: codec@13400000 { - compatible = "samsung,mfc-v5"; - reg = <0x13400000 0x10000>; - interrupts = <0 94 0>; - power-domains = <&pd_mfc>; - clocks = <&clock 273>; - clock-names = "mfc"; -}; - -Reserved memory specific DT entry for given board (see reserved memory binding -for more information): - -reserved-memory { - #address-cells = <1>; - #size-cells = <1>; - ranges; - - mfc_left: region@51000000 { - compatible = "shared-dma-pool"; - no-map; - reg = <0x51000000 0x800000>; - }; - - mfc_right: region@43000000 { - compatible = "shared-dma-pool"; - no-map; - reg = <0x43000000 0x800000>; - }; -}; - -Board specific DT entry: - -codec@13400000 { - memory-region = <&mfc_left>, <&mfc_right>; -}; diff --git a/Documentation/devicetree/bindings/media/samsung,s5p-mfc.yaml b/Documentation/devicetree/bindings/media/samsung,s5p-mfc.yaml new file mode 100644 index 0000000000000000000000000000000000000000..084b44582a434d7ad5e4d6b236d7cc5e4ac7b96d --- /dev/null +++ b/Documentation/devicetree/bindings/media/samsung,s5p-mfc.yaml @@ -0,0 +1,184 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/media/samsung,s5p-mfc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Samsung Exynos Multi Format Codec (MFC) + +maintainers: + - Marek Szyprowski + - Aakarsh Jain + +description: + Multi Format Codec (MFC) is the IP present in Samsung SoCs which + supports high resolution decoding and encoding functionalities. + +properties: + compatible: + oneOf: + - enum: + - samsung,exynos5433-mfc # Exynos5433 + - samsung,mfc-v5 # Exynos4 + - samsung,mfc-v6 # Exynos5 + - samsung,mfc-v7 # Exynos5420 + - samsung,mfc-v8 # Exynos5800 + - samsung,mfc-v10 # Exynos7880 + - items: + - enum: + - samsung,exynos3250-mfc # Exynos3250 + - const: samsung,mfc-v7 # Fall back for Exynos3250 + + reg: + maxItems: 1 + + clocks: + minItems: 1 + maxItems: 3 + + clock-names: + minItems: 1 + maxItems: 3 + + interrupts: + maxItems: 1 + + iommus: + minItems: 1 + maxItems: 2 + + iommu-names: + minItems: 1 + maxItems: 2 + + power-domains: + maxItems: 1 + + memory-region: + minItems: 1 + maxItems: 2 + +required: + - compatible + - reg + - clocks + - clock-names + - interrupts + +additionalProperties: false + +allOf: + - if: + properties: + compatible: + contains: + enum: + - samsung,exynos3250-mfc + then: + properties: + clocks: + maxItems: 2 + clock-names: + items: + - const: mfc + - const: sclk_mfc + iommus: + maxItems: 1 + iommus-names: false + + - if: + properties: + compatible: + contains: + enum: + - samsung,exynos5433-mfc + then: + properties: + clocks: + maxItems: 3 + clock-names: + items: + - const: pclk + - const: aclk + - const: aclk_xiu + iommus: + maxItems: 2 + iommus-names: + items: + - const: left + - const: right + + - if: + properties: + compatible: + contains: + enum: + - samsung,mfc-v5 + then: + properties: + clocks: + maxItems: 2 + clock-names: + items: + - const: mfc + - const: sclk_mfc + iommus: + maxItems: 2 + iommus-names: + items: + - const: left + - const: right + + - if: + properties: + compatible: + contains: + enum: + - samsung,mfc-v6 + - samsung,mfc-v8 + then: + properties: + clocks: + maxItems: 1 + clock-names: + items: + - const: mfc + iommus: + maxItems: 2 + iommus-names: + items: + - const: left + - const: right + + - if: + properties: + compatible: + contains: + enum: + - samsung,mfc-v7 + then: + properties: + clocks: + minItems: 1 + maxItems: 2 + iommus: + minItems: 1 + maxItems: 2 + +examples: + - | + #include + #include + #include + #include + + codec@13400000 { + compatible = "samsung,mfc-v5"; + reg = <0x13400000 0x10000>; + interrupts = ; + power-domains = <&pd_mfc>; + clocks = <&clock CLK_MFC>, <&clock CLK_SCLK_MFC>; + clock-names = "mfc", "sclk_mfc"; + iommus = <&sysmmu_mfc_l>, <&sysmmu_mfc_r>; + iommu-names = "left", "right"; + }; diff --git a/Documentation/devicetree/bindings/media/xilinx/xlnx,csi2rxss.yaml b/Documentation/devicetree/bindings/media/xilinx/xlnx,csi2rxss.yaml index 7d77823dbb7a18bf52dabc093cda6e7206b2c7e2..43daf837fc9f08e36f1f4a8a12c63140b214a5ee 100644 --- a/Documentation/devicetree/bindings/media/xilinx/xlnx,csi2rxss.yaml +++ b/Documentation/devicetree/bindings/media/xilinx/xlnx,csi2rxss.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Xilinx MIPI CSI-2 Receiver Subsystem maintainers: - - Vishal Sagar + - Vishal Sagar description: | The Xilinx MIPI CSI-2 Receiver Subsystem is used to capture MIPI CSI-2 diff --git a/Documentation/devicetree/bindings/memory-controllers/nuvoton,npcm-memory-controller.yaml b/Documentation/devicetree/bindings/memory-controllers/nuvoton,npcm-memory-controller.yaml new file mode 100644 index 0000000000000000000000000000000000000000..ac1a5a17749d4ac5e5d0e9e4048b616c41f048fc --- /dev/null +++ b/Documentation/devicetree/bindings/memory-controllers/nuvoton,npcm-memory-controller.yaml @@ -0,0 +1,50 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/memory-controllers/nuvoton,npcm-memory-controller.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Nuvoton NPCM Memory Controller + +maintainers: + - Marvin Lin + - Stanley Chu + +description: | + The Nuvoton BMC SoC supports DDR4 memory with or without ECC (error correction + check). + + The memory controller supports single bit error correction, double bit error + detection (in-line ECC in which a section (1/8th) of the memory device used to + store data is used for ECC storage). + + Note, the bootloader must configure ECC mode for the memory controller. + +properties: + compatible: + enum: + - nuvoton,npcm750-memory-controller + - nuvoton,npcm845-memory-controller + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + +required: + - compatible + - reg + - interrupts + +additionalProperties: false + +examples: + - | + #include + + mc: memory-controller@f0824000 { + compatible = "nuvoton,npcm750-memory-controller"; + reg = <0xf0824000 0x1000>; + interrupts = ; + }; diff --git a/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra20-emc.yaml b/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra20-emc.yaml index 2fa44951cfde0ca711e61fc01aaa883fefb1202e..f54e553e6c0e6a6e4c0d56e485f567f814dcaf12 100644 --- a/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra20-emc.yaml +++ b/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra20-emc.yaml @@ -165,7 +165,7 @@ patternProperties: const: 0 lpddr2: - $ref: "ddr/jedec,lpddr2.yaml#" + $ref: ddr/jedec,lpddr2.yaml# type: object patternProperties: diff --git a/Documentation/devicetree/bindings/memory-controllers/snps,dw-umctl2-ddrc.yaml b/Documentation/devicetree/bindings/memory-controllers/snps,dw-umctl2-ddrc.yaml index e68c4306025a17a2100447c814fb66b913c68b35..87ff9ee098f5e4f929bb113118cc22ec654f16ff 100644 --- a/Documentation/devicetree/bindings/memory-controllers/snps,dw-umctl2-ddrc.yaml +++ b/Documentation/devicetree/bindings/memory-controllers/snps,dw-umctl2-ddrc.yaml @@ -8,8 +8,7 @@ title: Synopsys DesignWare Universal Multi-Protocol Memory Controller maintainers: - Krzysztof Kozlowski - - Manish Narani - - Michal Simek + - Michal Simek description: | Synopsys DesignWare Enhanced uMCTL2 DDR Memory Controller is capable of diff --git a/Documentation/devicetree/bindings/memory-controllers/ti,gpmc.yaml b/Documentation/devicetree/bindings/memory-controllers/ti,gpmc.yaml index bc9406929f6cd2dc6d970230378efb521204e961..b049837ee66949a17a8d2c6c66fab88019f13fd7 100644 --- a/Documentation/devicetree/bindings/memory-controllers/ti,gpmc.yaml +++ b/Documentation/devicetree/bindings/memory-controllers/ti,gpmc.yaml @@ -129,7 +129,7 @@ patternProperties: The child device node represents the device connected to the GPMC bus. The device can be a NAND chip, SRAM device, NOR device or an ASIC. - $ref: "ti,gpmc-child.yaml" + $ref: ti,gpmc-child.yaml required: diff --git a/Documentation/devicetree/bindings/memory-controllers/xlnx,zynq-ddrc-a05.yaml b/Documentation/devicetree/bindings/memory-controllers/xlnx,zynq-ddrc-a05.yaml index 8f72e2f8588abdc02dddf36eaa79a8bf51724d96..75143db5141199e343d2d115925438489e5aa0e3 100644 --- a/Documentation/devicetree/bindings/memory-controllers/xlnx,zynq-ddrc-a05.yaml +++ b/Documentation/devicetree/bindings/memory-controllers/xlnx,zynq-ddrc-a05.yaml @@ -8,8 +8,7 @@ title: Zynq A05 DDR Memory Controller maintainers: - Krzysztof Kozlowski - - Manish Narani - - Michal Simek + - Michal Simek description: The Zynq DDR ECC controller has an optional ECC support in half-bus width diff --git a/Documentation/devicetree/bindings/mfd/adi,max77541.yaml b/Documentation/devicetree/bindings/mfd/adi,max77541.yaml new file mode 100644 index 0000000000000000000000000000000000000000..c7895b2c38c9001ec39fbadc028319fa96852728 --- /dev/null +++ b/Documentation/devicetree/bindings/mfd/adi,max77541.yaml @@ -0,0 +1,68 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/mfd/adi,max77541.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: MAX77540/MAX77541 PMIC from ADI + +maintainers: + - Okan Sahin + +description: | + MAX77540 is a Power Management IC with 2 buck regulators. + + MAX77541 is a Power Management IC with 2 buck regulators and 1 ADC. + +properties: + compatible: + enum: + - adi,max77540 + - adi,max77541 + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + regulators: + $ref: /schemas/regulator/adi,max77541-regulator.yaml# + +required: + - compatible + - reg + - interrupts + +additionalProperties: false + +examples: + - | + #include + + i2c { + #address-cells = <1>; + #size-cells = <0>; + + pmic@69 { + compatible = "adi,max77541"; + reg = <0x69>; + interrupt-parent = <&gpio>; + interrupts = <16 IRQ_TYPE_EDGE_FALLING>; + + regulators { + buck1 { + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <5200000>; + regulator-boot-on; + regulator-always-on; + }; + buck2 { + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <5200000>; + regulator-boot-on; + regulator-always-on; + }; + }; + }; + }; diff --git a/Documentation/devicetree/bindings/mfd/brcm,bcm6318-gpio-sysctl.yaml b/Documentation/devicetree/bindings/mfd/brcm,bcm6318-gpio-sysctl.yaml index 148f1da476031f540a673d7d760b00143e9f6497..9f9a14af875ee43301365609fb8aeaa381153a31 100644 --- a/Documentation/devicetree/bindings/mfd/brcm,bcm6318-gpio-sysctl.yaml +++ b/Documentation/devicetree/bindings/mfd/brcm,bcm6318-gpio-sysctl.yaml @@ -35,11 +35,11 @@ patternProperties: "^gpio@[0-9a-f]+$": # Child node type: object - $ref: "../gpio/brcm,bcm6345-gpio.yaml" + $ref: "../gpio/brcm,bcm63xx-gpio.yaml" description: GPIO controller for the SoC GPIOs. This child node definition should follow the bindings specified in - Documentation/devicetree/bindings/gpio/brcm,bcm6345-gpio.yaml. + Documentation/devicetree/bindings/gpio/brcm,bcm63xx-gpio.yaml. "^pinctrl@[0-9a-f]+$": # Child node diff --git a/Documentation/devicetree/bindings/mfd/brcm,bcm63268-gpio-sysctl.yaml b/Documentation/devicetree/bindings/mfd/brcm,bcm63268-gpio-sysctl.yaml index 7e582243ea7659152912540616509d5eff6c226b..803277dd27250dd50fe7004ac1f8a96502433de4 100644 --- a/Documentation/devicetree/bindings/mfd/brcm,bcm63268-gpio-sysctl.yaml +++ b/Documentation/devicetree/bindings/mfd/brcm,bcm63268-gpio-sysctl.yaml @@ -35,11 +35,11 @@ patternProperties: "^gpio@[0-9a-f]+$": # Child node type: object - $ref: "../gpio/brcm,bcm6345-gpio.yaml" + $ref: "../gpio/brcm,bcm63xx-gpio.yaml" description: GPIO controller for the SoC GPIOs. This child node definition should follow the bindings specified in - Documentation/devicetree/bindings/gpio/brcm,bcm6345-gpio.yaml. + Documentation/devicetree/bindings/gpio/brcm,bcm63xx-gpio.yaml. "^pinctrl@[0-9a-f]+$": # Child node diff --git a/Documentation/devicetree/bindings/mfd/brcm,bcm6328-gpio-sysctl.yaml b/Documentation/devicetree/bindings/mfd/brcm,bcm6328-gpio-sysctl.yaml index 2230848e11c3a177dbd5f775fe03b69f02eab8fe..b9a6856ce970bda8c295e398b7fe03f1b434ce62 100644 --- a/Documentation/devicetree/bindings/mfd/brcm,bcm6328-gpio-sysctl.yaml +++ b/Documentation/devicetree/bindings/mfd/brcm,bcm6328-gpio-sysctl.yaml @@ -35,11 +35,11 @@ patternProperties: "^gpio@[0-9a-f]+$": # Child node type: object - $ref: "../gpio/brcm,bcm6345-gpio.yaml" + $ref: "../gpio/brcm,bcm63xx-gpio.yaml" description: GPIO controller for the SoC GPIOs. This child node definition should follow the bindings specified in - Documentation/devicetree/bindings/gpio/brcm,bcm6345-gpio.yaml. + Documentation/devicetree/bindings/gpio/brcm,bcm63xx-gpio.yaml. "^pinctrl@[0-9a-f]+$": # Child node diff --git a/Documentation/devicetree/bindings/mfd/brcm,bcm6358-gpio-sysctl.yaml b/Documentation/devicetree/bindings/mfd/brcm,bcm6358-gpio-sysctl.yaml index c06693b6f7aa025fa1771477261067eac870323c..4651fe4dde079b8f5a77a034d52d4aa66e271c4d 100644 --- a/Documentation/devicetree/bindings/mfd/brcm,bcm6358-gpio-sysctl.yaml +++ b/Documentation/devicetree/bindings/mfd/brcm,bcm6358-gpio-sysctl.yaml @@ -35,11 +35,11 @@ patternProperties: "^gpio@[0-9a-f]+$": # Child node type: object - $ref: "../gpio/brcm,bcm6345-gpio.yaml" + $ref: "../gpio/brcm,bcm63xx-gpio.yaml" description: GPIO controller for the SoC GPIOs. This child node definition should follow the bindings specified in - Documentation/devicetree/bindings/gpio/brcm,bcm6345-gpio.yaml. + Documentation/devicetree/bindings/gpio/brcm,bcm63xx-gpio.yaml. "^pinctrl@[0-9a-f]+$": # Child node diff --git a/Documentation/devicetree/bindings/mfd/brcm,bcm6362-gpio-sysctl.yaml b/Documentation/devicetree/bindings/mfd/brcm,bcm6362-gpio-sysctl.yaml index c560bede0e37a36d84995b2c0a3132b1f6c63acc..0330b621fd3814938430e44fcc880c55a31fdf47 100644 --- a/Documentation/devicetree/bindings/mfd/brcm,bcm6362-gpio-sysctl.yaml +++ b/Documentation/devicetree/bindings/mfd/brcm,bcm6362-gpio-sysctl.yaml @@ -35,11 +35,11 @@ patternProperties: "^gpio@[0-9a-f]+$": # Child node type: object - $ref: "../gpio/brcm,bcm6345-gpio.yaml" + $ref: "../gpio/brcm,bcm63xx-gpio.yaml" description: GPIO controller for the SoC GPIOs. This child node definition should follow the bindings specified in - Documentation/devicetree/bindings/gpio/brcm,bcm6345-gpio.yaml. + Documentation/devicetree/bindings/gpio/brcm,bcm63xx-gpio.yaml. "^pinctrl@[0-9a-f]+$": # Child node diff --git a/Documentation/devicetree/bindings/mfd/brcm,bcm6368-gpio-sysctl.yaml b/Documentation/devicetree/bindings/mfd/brcm,bcm6368-gpio-sysctl.yaml index c534f5f2404e3ed369d9bec689800f282b124a7c..82d3e4415bda9634d5e34070f108d8ac73adcb22 100644 --- a/Documentation/devicetree/bindings/mfd/brcm,bcm6368-gpio-sysctl.yaml +++ b/Documentation/devicetree/bindings/mfd/brcm,bcm6368-gpio-sysctl.yaml @@ -35,11 +35,11 @@ patternProperties: "^gpio@[0-9a-f]+$": # Child node type: object - $ref: "../gpio/brcm,bcm6345-gpio.yaml" + $ref: "../gpio/brcm,bcm63xx-gpio.yaml" description: GPIO controller for the SoC GPIOs. This child node definition should follow the bindings specified in - Documentation/devicetree/bindings/gpio/brcm,bcm6345-gpio.yaml. + Documentation/devicetree/bindings/gpio/brcm,bcm63xx-gpio.yaml. "^pinctrl@[0-9a-f]+$": # Child node diff --git a/Documentation/devicetree/bindings/mfd/gateworks-gsc.yaml b/Documentation/devicetree/bindings/mfd/gateworks-gsc.yaml index acb9c54942d9cc4b6fc70e61fda4c28ee0fb5430..dc379f3ebf24ff04a19a0f28663d6afe1fcaa75d 100644 --- a/Documentation/devicetree/bindings/mfd/gateworks-gsc.yaml +++ b/Documentation/devicetree/bindings/mfd/gateworks-gsc.yaml @@ -122,12 +122,6 @@ patternProperties: compatible: const: gw,gsc-fan - "#address-cells": - const: 1 - - "#size-cells": - const: 0 - reg: description: The fan controller base address maxItems: 1 @@ -135,8 +129,6 @@ patternProperties: required: - compatible - reg - - "#address-cells" - - "#size-cells" required: - compatible @@ -194,8 +186,6 @@ examples: }; fan-controller@2c { - #address-cells = <1>; - #size-cells = <0>; compatible = "gw,gsc-fan"; reg = <0x2c>; }; diff --git a/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml b/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml index 36de335a33aa81c78980053d514d062975a52d32..8b9a2008a354e0de31a88137ef2f97a5f793ab12 100644 --- a/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml +++ b/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml @@ -71,6 +71,7 @@ properties: - qcom,pm8998 - qcom,pma8084 - qcom,pmd9635 + - qcom,pmi632 - qcom,pmi8950 - qcom,pmi8962 - qcom,pmi8994 @@ -133,6 +134,7 @@ patternProperties: oneOf: - $ref: /schemas/power/supply/qcom,pm8941-charger.yaml# - $ref: /schemas/power/supply/qcom,pm8941-coincell.yaml# + - $ref: /schemas/power/supply/qcom,pmi8998-charger.yaml# "gpio@[0-9a-f]+$": type: object @@ -146,6 +148,10 @@ patternProperties: type: object $ref: /schemas/nvmem/qcom,spmi-sdam.yaml# + "phy@[0-9a-f]+$": + type: object + $ref: /schemas/phy/qcom,snps-eusb2-repeater.yaml# + "pon@[0-9a-f]+$": type: object $ref: /schemas/power/reset/qcom,pon.yaml# diff --git a/Documentation/devicetree/bindings/mfd/qcom,tcsr.yaml b/Documentation/devicetree/bindings/mfd/qcom,tcsr.yaml index fe790af7b4fbe2e13823016b871a15c39f9c4b11..5ad9d5deaaf8ac5ff19be4c1444c7929fe4a7adc 100644 --- a/Documentation/devicetree/bindings/mfd/qcom,tcsr.yaml +++ b/Documentation/devicetree/bindings/mfd/qcom,tcsr.yaml @@ -34,6 +34,7 @@ properties: - qcom,tcsr-ipq5332 - qcom,tcsr-ipq6018 - qcom,tcsr-ipq8064 + - qcom,tcsr-ipq8074 - qcom,tcsr-ipq9574 - qcom,tcsr-mdm9615 - qcom,tcsr-msm8226 diff --git a/Documentation/devicetree/bindings/mfd/richtek,rt5033.yaml b/Documentation/devicetree/bindings/mfd/richtek,rt5033.yaml new file mode 100644 index 0000000000000000000000000000000000000000..386b1a50158a6125ba083d3d9b706077d460c48b --- /dev/null +++ b/Documentation/devicetree/bindings/mfd/richtek,rt5033.yaml @@ -0,0 +1,138 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/mfd/richtek,rt5033.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Richtek RT5033 Power Management Integrated Circuit + +maintainers: + - Jakob Hauser + +description: + RT5033 is a multifunction device which includes battery charger, fuel gauge, + flash LED current source, LDO and synchronous Buck converter for portable + applications. It is interfaced to host controller using I2C interface. The + battery fuel gauge uses a separate I2C bus. + +properties: + compatible: + const: richtek,rt5033 + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + regulators: + description: + The regulators of RT5033 have to be instantiated under a sub-node named + "regulators". For SAFE_LDO voltage there is only one value of 4.9 V. LDO + voltage ranges from 1.2 V to 3.0 V in 0.1 V steps. BUCK voltage ranges + from 1.0 V to 3.0 V in 0.1 V steps. + type: object + patternProperties: + "^(SAFE_LDO|LDO|BUCK)$": + type: object + $ref: /schemas/regulator/regulator.yaml# + unevaluatedProperties: false + additionalProperties: false + + charger: + type: object + $ref: /schemas/power/supply/richtek,rt5033-charger.yaml# + +required: + - compatible + - reg + - interrupts + +additionalProperties: false + +examples: + - | + #include + + battery: battery { + compatible = "simple-battery"; + precharge-current-microamp = <450000>; + constant-charge-current-max-microamp = <1000000>; + charge-term-current-microamp = <150000>; + precharge-upper-limit-microvolt = <3500000>; + constant-charge-voltage-max-microvolt = <4350000>; + }; + + extcon { + usb_con: connector { + compatible = "usb-b-connector"; + label = "micro-USB"; + type = "micro"; + }; + }; + + i2c { + #address-cells = <1>; + #size-cells = <0>; + + i2c@0 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0>; + + fuel-gauge@35 { + compatible = "richtek,rt5033-battery"; + reg = <0x35>; + + interrupt-parent = <&msmgpio>; + interrupts = <121 IRQ_TYPE_EDGE_FALLING>; + + pinctrl-names = "default"; + pinctrl-0 = <&fg_alert_default>; + + power-supplies = <&rt5033_charger>; + }; + }; + + i2c@1 { + #address-cells = <1>; + #size-cells = <0>; + reg = <1>; + + pmic@34 { + compatible = "richtek,rt5033"; + reg = <0x34>; + + interrupt-parent = <&msmgpio>; + interrupts = <62 IRQ_TYPE_EDGE_FALLING>; + + pinctrl-names = "default"; + pinctrl-0 = <&pmic_int_default>; + + regulators { + safe_ldo_reg: SAFE_LDO { + regulator-name = "SAFE_LDO"; + regulator-min-microvolt = <4900000>; + regulator-max-microvolt = <4900000>; + regulator-always-on; + }; + ldo_reg: LDO { + regulator-name = "LDO"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + }; + buck_reg: BUCK { + regulator-name = "BUCK"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + }; + }; + + rt5033_charger: charger { + compatible = "richtek,rt5033-charger"; + monitored-battery = <&battery>; + richtek,usb-connector = <&usb_con>; + }; + }; + }; + }; diff --git a/Documentation/devicetree/bindings/mfd/rockchip,rk806.yaml b/Documentation/devicetree/bindings/mfd/rockchip,rk806.yaml new file mode 100644 index 0000000000000000000000000000000000000000..cf2500f2e9a0d9e4248089997d27a1c84d9e6e3b --- /dev/null +++ b/Documentation/devicetree/bindings/mfd/rockchip,rk806.yaml @@ -0,0 +1,406 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/mfd/rockchip,rk806.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: RK806 Power Management Integrated Circuit + +maintainers: + - Sebastian Reichel + +description: + Rockchip RK806 series PMIC. This device consists of an spi or + i2c controlled MFD that includes multiple switchable regulators. + +properties: + compatible: + enum: + - rockchip,rk806 + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + gpio-controller: true + + '#gpio-cells': + const: 2 + + vcc1-supply: + description: + The input supply for dcdc-reg1. + + vcc2-supply: + description: + The input supply for dcdc-reg2. + + vcc3-supply: + description: + The input supply for dcdc-reg3. + + vcc4-supply: + description: + The input supply for dcdc-reg4. + + vcc5-supply: + description: + The input supply for dcdc-reg5. + + vcc6-supply: + description: + The input supply for dcdc-reg6. + + vcc7-supply: + description: + The input supply for dcdc-reg7. + + vcc8-supply: + description: + The input supply for dcdc-reg8. + + vcc9-supply: + description: + The input supply for dcdc-reg9. + + vcc10-supply: + description: + The input supply for dcdc-reg10. + + vcc11-supply: + description: + The input supply for pldo-reg1, pldo-reg2 and pldo-reg3. + + vcc12-supply: + description: + The input supply for pldo-reg4 and pldo-reg5. + + vcc13-supply: + description: + The input supply for nldo-reg1, nldo-reg2 and nldo-reg3. + + vcc14-supply: + description: + The input supply for nldo-reg4 and nldo-reg5. + + vcca-supply: + description: + The input supply for pldo-reg6. + + regulators: + type: object + additionalProperties: false + patternProperties: + "^(dcdc-reg([1-9]|10)|pldo-reg[1-6]|nldo-reg[1-5])$": + type: object + $ref: /schemas/regulator/regulator.yaml# + unevaluatedProperties: false + +patternProperties: + '-pins$': + type: object + additionalProperties: false + $ref: /schemas/pinctrl/pinmux-node.yaml + + properties: + function: + enum: [pin_fun0, pin_fun1, pin_fun2, pin_fun3, pin_fun4, pin_fun5] + + pins: + $ref: /schemas/types.yaml#/definitions/string + enum: [gpio_pwrctrl1, gpio_pwrctrl2, gpio_pwrctrl3] + +allOf: + - $ref: /schemas/spi/spi-peripheral-props.yaml + +required: + - compatible + - reg + - interrupts + +unevaluatedProperties: false + +examples: + - | + #include + #include + #include + spi { + #address-cells = <1>; + #size-cells = <0>; + + pmic@0 { + compatible = "rockchip,rk806"; + reg = <0x0>; + + interrupts = <7 IRQ_TYPE_LEVEL_LOW>; + + 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 = <&vcc5v0_sys>; + vcc14-supply = <&vcc_1v1_nldo_s3>; + vcca-supply = <&vcc5v0_sys>; + + regulators { + vdd_gpu_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-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_npu_s0: dcdc-reg2 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <950000>; + regulator-ramp-delay = <12500>; + regulator-name = "vdd_npu_s0"; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_log_s0: dcdc-reg3 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <750000>; + regulator-max-microvolt = <750000>; + regulator-ramp-delay = <12500>; + regulator-name = "vdd_log_s0"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <750000>; + }; + }; + + vdd_vdenc_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_gpu_mem_s0: dcdc-reg5 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <675000>; + regulator-max-microvolt = <950000>; + regulator-ramp-delay = <12500>; + regulator-name = "vdd_gpu_mem_s0"; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_npu_mem_s0: dcdc-reg6 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <675000>; + regulator-max-microvolt = <950000>; + regulator-ramp-delay = <12500>; + regulator-name = "vdd_npu_mem_s0"; + regulator-state-mem { + regulator-off-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>; + }; + }; + + vdd_vdenc_mem_s0: dcdc-reg8 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <675000>; + regulator-max-microvolt = <950000>; + regulator-ramp-delay = <12500>; + regulator-name = "vdd_vdenc_mem_s0"; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd2_ddr_s3: dcdc-reg9 { + regulator-always-on; + regulator-boot-on; + regulator-name = "vdd2_ddr_s3"; + regulator-state-mem { + regulator-on-in-suspend; + }; + }; + + vcc_1v1_nldo_s3: dcdc-reg10 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1100000>; + regulator-max-microvolt = <1100000>; + regulator-ramp-delay = <12500>; + regulator-name = "vcc_1v1_nldo_s3"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1100000>; + }; + }; + + avcc_1v8_s0: pldo-reg1 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-ramp-delay = <12500>; + regulator-name = "avcc_1v8_s0"; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd1_1v8_ddr_s3: pldo-reg2 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-ramp-delay = <12500>; + regulator-name = "vdd1_1v8_ddr_s3"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vcc_1v8_s3: pldo-reg3 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-ramp-delay = <12500>; + regulator-name = "vcc_1v8_s3"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + 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; + }; + }; + + master_pldo6_s3: pldo-reg6 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-name = "master_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-ramp-delay = <12500>; + regulator-name = "vdd_0v75_s3"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <750000>; + }; + }; + + vdd2l_0v9_ddr_s3: nldo-reg2 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <900000>; + regulator-name = "vdd2l_0v9_ddr_s3"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <900000>; + }; + }; + + master_nldo3: nldo-reg3 { + regulator-name = "master_nldo3"; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + avdd_0v75_s0: nldo-reg4 { + 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-reg5 { + 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; + }; + }; + }; + }; + }; diff --git a/Documentation/devicetree/bindings/mfd/samsung,s5m8767.yaml b/Documentation/devicetree/bindings/mfd/samsung,s5m8767.yaml index 10c7b408f33aa3d815578fcf1134ed5a9a94eec6..aea0b7d57d04e044036403dbe820548dda96b647 100644 --- a/Documentation/devicetree/bindings/mfd/samsung,s5m8767.yaml +++ b/Documentation/devicetree/bindings/mfd/samsung,s5m8767.yaml @@ -153,29 +153,18 @@ dependencies: additionalProperties: false allOf: - - if: + - not: required: - s5m8767,pmic-buck2-uses-gpio-dvs - then: - properties: - s5m8767,pmic-buck3-uses-gpio-dvs: false - s5m8767,pmic-buck4-uses-gpio-dvs: false - - - if: - required: - s5m8767,pmic-buck3-uses-gpio-dvs - then: - properties: - s5m8767,pmic-buck2-uses-gpio-dvs: false - s5m8767,pmic-buck4-uses-gpio-dvs: false - - - if: + - not: required: + - s5m8767,pmic-buck2-uses-gpio-dvs + - s5m8767,pmic-buck4-uses-gpio-dvs + - not: + required: + - s5m8767,pmic-buck3-uses-gpio-dvs - s5m8767,pmic-buck4-uses-gpio-dvs - then: - properties: - s5m8767,pmic-buck2-uses-gpio-dvs: false - s5m8767,pmic-buck3-uses-gpio-dvs: false examples: - | diff --git a/Documentation/devicetree/bindings/mfd/st,stpmic1.yaml b/Documentation/devicetree/bindings/mfd/st,stpmic1.yaml index 9573e4af949ee5d2ad3b7d6f5e056c4a3c587a27..97c61097f9e2661eed4eb382ee05ed8c9ba9e160 100644 --- a/Documentation/devicetree/bindings/mfd/st,stpmic1.yaml +++ b/Documentation/devicetree/bindings/mfd/st,stpmic1.yaml @@ -184,7 +184,7 @@ properties: additionalProperties: false patternProperties: - "^(buck[1-4]|ldo[1-6]|boost|pwr_sw[1-2])-supply$": + "^(buck[1-4]|ldo[1-6]|vref_ddr|boost|pwr_sw[1-2])-supply$": description: STPMIC1 voltage regulators supplies "^(buck[1-4]|ldo[1-6]|boost|vref_ddr|pwr_sw[1-2])$": diff --git a/Documentation/devicetree/bindings/mfd/ti,j721e-system-controller.yaml b/Documentation/devicetree/bindings/mfd/ti,j721e-system-controller.yaml index 0c98d913747bb69f982ab1c5f0b0dac7c53dd739..e6289fbe69070689c7914ddc37a579c01fb17347 100644 --- a/Documentation/devicetree/bindings/mfd/ti,j721e-system-controller.yaml +++ b/Documentation/devicetree/bindings/mfd/ti,j721e-system-controller.yaml @@ -101,7 +101,7 @@ examples: }; clock-controller@4140 { - compatible = "ti,am654-ehrpwm-tbclk", "syscon"; + compatible = "ti,am654-ehrpwm-tbclk"; reg = <0x4140 0x18>; #clock-cells = <1>; }; diff --git a/Documentation/devicetree/bindings/mfd/ti,tps6594.yaml b/Documentation/devicetree/bindings/mfd/ti,tps6594.yaml new file mode 100644 index 0000000000000000000000000000000000000000..9d43376bebed1a0f066cab14360003b8f2cf5491 --- /dev/null +++ b/Documentation/devicetree/bindings/mfd/ti,tps6594.yaml @@ -0,0 +1,193 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/mfd/ti,tps6594.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: TI TPS6594 Power Management Integrated Circuit + +maintainers: + - Julien Panis + +description: + TPS6594 is a Power Management IC which provides regulators and others + features like GPIOs, RTC, watchdog, ESMs (Error Signal Monitor), and + PFSM (Pre-configurable Finite State Machine) managing the state of the device. + TPS6594 is the super-set device while TPS6593 and LP8764 are derivatives. + +properties: + compatible: + enum: + - ti,lp8764-q1 + - ti,tps6593-q1 + - ti,tps6594-q1 + + reg: + description: I2C slave address or SPI chip select number. + maxItems: 1 + + ti,primary-pmic: + type: boolean + description: | + Identify the primary PMIC on SPMI bus. + A multi-PMIC synchronization scheme is implemented in the PMIC device + to synchronize the power state changes with other PMIC devices. This is + accomplished through a SPMI bus: the primary PMIC is the controller + device on the SPMI bus, and the secondary PMICs are the target devices + on the SPMI bus. + + system-power-controller: true + + gpio-controller: true + + '#gpio-cells': + const: 2 + description: | + The first cell is the pin number, the second cell is used to specify flags. + See ../gpio/gpio.txt for more information. + + interrupts: + maxItems: 1 + + regulators: + type: object + description: List of regulators provided by this controller. + + patternProperties: + "^buck([1-5]|12|34|123|1234)$": + type: object + $ref: /schemas/regulator/regulator.yaml# + + unevaluatedProperties: false + + "^ldo[1-4]$": + type: object + $ref: /schemas/regulator/regulator.yaml# + + unevaluatedProperties: false + + allOf: + - if: + required: + - buck12 + then: + properties: + buck123: false + buck1234: false + - if: + required: + - buck123 + then: + properties: + buck34: false + - if: + required: + - buck1234 + then: + properties: + buck34: false + + additionalProperties: false + +patternProperties: + "^buck([1-5]|12|34|123|1234)-supply$": + description: Input supply phandle for each buck. + + "^ldo[1-4]-supply$": + description: Input supply phandle for each ldo. + +required: + - compatible + - reg + - interrupts + +additionalProperties: false + +examples: + - | + #include + i2c { + #address-cells = <1>; + #size-cells = <0>; + + tps6593: pmic@48 { + compatible = "ti,tps6593-q1"; + reg = <0x48>; + ti,primary-pmic; + system-power-controller; + + gpio-controller; + #gpio-cells = <2>; + + pinctrl-names = "default"; + pinctrl-0 = <&pmic_irq_pins_default>; + interrupt-parent = <&mcu_gpio0>; + interrupts = <0 IRQ_TYPE_EDGE_FALLING>; + + buck123-supply = <&vcc_3v3_sys>; + buck4-supply = <&vcc_3v3_sys>; + buck5-supply = <&vcc_3v3_sys>; + ldo1-supply = <&vcc_3v3_sys>; + ldo2-supply = <&vcc_3v3_sys>; + ldo3-supply = <&buck5>; + ldo4-supply = <&vcc_3v3_sys>; + + regulators { + buck123: buck123 { + regulator-name = "vcc_core"; + regulator-min-microvolt = <750000>; + regulator-max-microvolt = <850000>; + regulator-boot-on; + regulator-always-on; + }; + + buck4: buck4 { + regulator-name = "vcc_1v1"; + regulator-min-microvolt = <1100000>; + regulator-max-microvolt = <1100000>; + regulator-boot-on; + regulator-always-on; + }; + + buck5: buck5 { + regulator-name = "vcc_1v8_sys"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-boot-on; + regulator-always-on; + }; + + ldo1: ldo1 { + regulator-name = "vddshv5_sdio"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + regulator-always-on; + }; + + ldo2: ldo2 { + regulator-name = "vpp_1v8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-boot-on; + regulator-always-on; + }; + + ldo3: ldo3 { + regulator-name = "vcc_0v85"; + regulator-min-microvolt = <850000>; + regulator-max-microvolt = <850000>; + regulator-boot-on; + regulator-always-on; + }; + + ldo4: ldo4 { + regulator-name = "vdda_1v8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-boot-on; + regulator-always-on; + }; + }; + }; + }; diff --git a/Documentation/devicetree/bindings/mfd/x-powers,axp152.yaml b/Documentation/devicetree/bindings/mfd/x-powers,axp152.yaml index f7f0f2c0421ace739c61d061f0c6ef5b1a81db6d..9ad55746133b5ea5041244fe86d181365dc4f6d9 100644 --- a/Documentation/devicetree/bindings/mfd/x-powers,axp152.yaml +++ b/Documentation/devicetree/bindings/mfd/x-powers,axp152.yaml @@ -90,6 +90,7 @@ properties: oneOf: - enum: - x-powers,axp152 + - x-powers,axp192 - x-powers,axp202 - x-powers,axp209 - x-powers,axp221 diff --git a/Documentation/devicetree/bindings/mips/ralink.yaml b/Documentation/devicetree/bindings/mips/ralink.yaml index 704b5b59512718ba9076b583e6de876e5159e92e..53c1f66353770075ae8013240c83df5bda4b6ea1 100644 --- a/Documentation/devicetree/bindings/mips/ralink.yaml +++ b/Documentation/devicetree/bindings/mips/ralink.yaml @@ -80,6 +80,7 @@ properties: - enum: - gnubee,gb-pc1 - gnubee,gb-pc2 + - tplink,hc220-g5-v1 - const: mediatek,mt7621-soc additionalProperties: true diff --git a/Documentation/devicetree/bindings/misc/brcm,kona-smc.txt b/Documentation/devicetree/bindings/misc/brcm,kona-smc.txt deleted file mode 100644 index 05b47232ed9ed647a97df99e7b4c175352748fb6..0000000000000000000000000000000000000000 --- a/Documentation/devicetree/bindings/misc/brcm,kona-smc.txt +++ /dev/null @@ -1,15 +0,0 @@ -Broadcom Secure Monitor Bounce buffer ------------------------------------------------------ -This binding defines the location of the bounce buffer -used for non-secure to secure communications. - -Required properties: -- compatible : "brcm,kona-smc" -- DEPRECATED: compatible : "bcm,kona-smc" -- reg : Location and size of bounce buffer - -Example: - smc@3404c000 { - compatible = "brcm,bcm11351-smc", "brcm,kona-smc"; - reg = <0x3404c000 0x400>; //1 KiB in SRAM - }; diff --git a/Documentation/devicetree/bindings/misc/qcom,fastrpc.yaml b/Documentation/devicetree/bindings/misc/qcom,fastrpc.yaml index 1ab9588cdd896786c74077063a2fa6af7be014d8..2dc3e245fa5d342f4aa8ca550b29e979732dbb05 100644 --- a/Documentation/devicetree/bindings/misc/qcom,fastrpc.yaml +++ b/Documentation/devicetree/bindings/misc/qcom,fastrpc.yaml @@ -36,7 +36,7 @@ properties: description: A list of channels tied to this function, used for matching the function to a set of virtual channels. - $ref: "/schemas/types.yaml#/definitions/string-array" + $ref: /schemas/types.yaml#/definitions/string-array items: - const: fastrpcglink-apps-dsp @@ -48,14 +48,14 @@ properties: qcom,smd-channels: description: Channel name used for the RPM communication - $ref: "/schemas/types.yaml#/definitions/string-array" + $ref: /schemas/types.yaml#/definitions/string-array items: - const: fastrpcsmd-apps-dsp qcom,vmids: description: Virtual machine IDs for remote processor. - $ref: "/schemas/types.yaml#/definitions/uint32-array" + $ref: /schemas/types.yaml#/definitions/uint32-array "#address-cells": const: 1 diff --git a/Documentation/devicetree/bindings/misc/ti,j721e-esm.yaml b/Documentation/devicetree/bindings/misc/ti,j721e-esm.yaml new file mode 100644 index 0000000000000000000000000000000000000000..0c9a8444844c564396a79ce6b19369c236f506af --- /dev/null +++ b/Documentation/devicetree/bindings/misc/ti,j721e-esm.yaml @@ -0,0 +1,53 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +# Copyright (C) 2022 Texas Instruments Incorporated +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/misc/ti,j721e-esm.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Texas Instruments K3 ESM + +maintainers: + - Neha Malcom Francis + +description: + The ESM (Error Signaling Module) is an IP block on TI K3 devices + that allows handling of safety events somewhat similar to what interrupt + controller would do. The safety signals have their separate paths within + the SoC, and they are handled by the ESM, which routes them to the proper + destination, which can be system reset, interrupt controller, etc. In the + simplest configuration the signals are just routed to reset the SoC. + +properties: + compatible: + const: ti,j721e-esm + + reg: + maxItems: 1 + + ti,esm-pins: + $ref: /schemas/types.yaml#/definitions/uint32-array + description: + integer array of ESM interrupt pins to route to external event pin + which can be used to reset the SoC. + minItems: 1 + maxItems: 255 + +required: + - compatible + - reg + - ti,esm-pins + +additionalProperties: false + +examples: + - | + bus { + #address-cells = <2>; + #size-cells = <2>; + esm@700000 { + compatible = "ti,j721e-esm"; + reg = <0x0 0x700000 0x0 0x1000>; + ti,esm-pins = <344>, <345>; + }; + }; diff --git a/Documentation/devicetree/bindings/mmc/arm,pl18x.yaml b/Documentation/devicetree/bindings/mmc/arm,pl18x.yaml index 1c96da04f0e53b73b60f52212ba63b47ec4e4787..2459a55ed540b85a1920e06456a7faac938c6836 100644 --- a/Documentation/devicetree/bindings/mmc/arm,pl18x.yaml +++ b/Documentation/devicetree/bindings/mmc/arm,pl18x.yaml @@ -53,10 +53,11 @@ properties: items: - const: arm,pl18x - const: arm,primecell - - description: Entry for STMicroelectronics variant of PL18x. - This dedicated compatible is used by bootloaders. + - description: Entries for STMicroelectronics variant of PL18x. items: - - const: st,stm32-sdmmc2 + - enum: + - st,stm32-sdmmc2 + - st,stm32mp25-sdmmc2 - const: arm,pl18x - const: arm,primecell diff --git a/Documentation/devicetree/bindings/mmc/brcm,bcm2835-sdhost.txt b/Documentation/devicetree/bindings/mmc/brcm,bcm2835-sdhost.txt deleted file mode 100644 index d876580ae3b837a9174e454d223c6fa4df7ce94e..0000000000000000000000000000000000000000 --- a/Documentation/devicetree/bindings/mmc/brcm,bcm2835-sdhost.txt +++ /dev/null @@ -1,23 +0,0 @@ -Broadcom BCM2835 SDHOST controller - -This file documents differences between the core properties described -by mmc.txt and the properties that represent the BCM2835 controller. - -Required properties: -- compatible: Should be "brcm,bcm2835-sdhost". -- clocks: The clock feeding the SDHOST controller. - -Optional properties: -- dmas: DMA channel for read and write. - See Documentation/devicetree/bindings/dma/dma.txt for details - -Example: - -sdhost: mmc@7e202000 { - compatible = "brcm,bcm2835-sdhost"; - reg = <0x7e202000 0x100>; - interrupts = <2 24>; - clocks = <&clocks BCM2835_CLOCK_VPU>; - dmas = <&dma 13>; - dma-names = "rx-tx"; -}; diff --git a/Documentation/devicetree/bindings/mmc/brcm,bcm2835-sdhost.yaml b/Documentation/devicetree/bindings/mmc/brcm,bcm2835-sdhost.yaml new file mode 100644 index 0000000000000000000000000000000000000000..3a5a44800675191a765fe234d98dda426a9e7454 --- /dev/null +++ b/Documentation/devicetree/bindings/mmc/brcm,bcm2835-sdhost.yaml @@ -0,0 +1,54 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/mmc/brcm,bcm2835-sdhost.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Broadcom BCM2835 SDHOST controller + +maintainers: + - Stefan Wahren + +allOf: + - $ref: mmc-controller.yaml + +properties: + compatible: + const: brcm,bcm2835-sdhost + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + clocks: + maxItems: 1 + + dmas: + maxItems: 1 + + dma-names: + const: rx-tx + +required: + - compatible + - reg + - interrupts + - clocks + +unevaluatedProperties: false + +examples: + - | + #include + + sdhost: mmc@7e202000 { + compatible = "brcm,bcm2835-sdhost"; + reg = <0x7e202000 0x100>; + interrupts = <2 24>; + clocks = <&clocks BCM2835_CLOCK_VPU>; + dmas = <&dma 13>; + dma-names = "rx-tx"; + bus-width = <4>; + }; diff --git a/Documentation/devicetree/bindings/mmc/brcm,kona-sdhci.txt b/Documentation/devicetree/bindings/mmc/brcm,kona-sdhci.txt deleted file mode 100644 index 7f5dd83f5bd95afd1b696e186681caae75c268b1..0000000000000000000000000000000000000000 --- a/Documentation/devicetree/bindings/mmc/brcm,kona-sdhci.txt +++ /dev/null @@ -1,21 +0,0 @@ -Broadcom BCM281xx SDHCI - -This file documents differences between the core properties in mmc.txt -and the properties present in the bcm281xx SDHCI - -Required properties: -- compatible : Should be "brcm,kona-sdhci" -- DEPRECATED: compatible : Should be "bcm,kona-sdhci" -- clocks: phandle + clock specifier pair of the external clock - -Refer to clocks/clock-bindings.txt for generic clock consumer properties. - -Example: - -sdio2: sdio@3f1a0000 { - compatible = "brcm,kona-sdhci"; - reg = <0x3f1a0000 0x10000>; - clocks = <&sdio3_clk>; - interrupts = <0x0 74 0x4>; -}; - diff --git a/Documentation/devicetree/bindings/mmc/brcm,kona-sdhci.yaml b/Documentation/devicetree/bindings/mmc/brcm,kona-sdhci.yaml new file mode 100644 index 0000000000000000000000000000000000000000..12eb3988f8247263a13243241a643435f877c4c6 --- /dev/null +++ b/Documentation/devicetree/bindings/mmc/brcm,kona-sdhci.yaml @@ -0,0 +1,48 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/mmc/brcm,kona-sdhci.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Broadcom Kona family SDHCI controller + +maintainers: + - Florian Fainelli + +allOf: + - $ref: sdhci-common.yaml# + +properties: + compatible: + const: brcm,kona-sdhci + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + + interrupts: + maxItems: 1 + +required: + - compatible + - reg + - clocks + - interrupts + +unevaluatedProperties: false + +examples: + - | + #include + #include + #include + + mmc@3f1a0000 { + compatible = "brcm,kona-sdhci"; + reg = <0x3f1a0000 0x10000>; + clocks = <&master_ccu BCM281XX_MASTER_CCU_SDIO3>; + interrupts = ; + }; +... diff --git a/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.yaml b/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.yaml index fbfd822b927071434fbfbbada9b761f938b9cd69..82eb7a24c857828845f4640d5f913ec9abb87126 100644 --- a/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.yaml +++ b/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.yaml @@ -42,6 +42,7 @@ properties: - enum: - fsl,imx6sll-usdhc - fsl,imx6ull-usdhc + - fsl,imx6ul-usdhc - const: fsl,imx6sx-usdhc - items: - const: fsl,imx7d-usdhc diff --git a/Documentation/devicetree/bindings/mmc/sdhci-msm.yaml b/Documentation/devicetree/bindings/mmc/sdhci-msm.yaml index 4f2d9e8127dd3b94a486d2ee6aeeb4dbce2b14aa..6da28e630577848f910cc5dac0c0c34218c1d1c5 100644 --- a/Documentation/devicetree/bindings/mmc/sdhci-msm.yaml +++ b/Documentation/devicetree/bindings/mmc/sdhci-msm.yaml @@ -36,11 +36,14 @@ properties: - enum: - qcom,ipq5018-sdhci - qcom,ipq5332-sdhci + - qcom,ipq6018-sdhci - qcom,ipq9574-sdhci - qcom,qcm2290-sdhci - qcom,qcs404-sdhci + - qcom,qdu1000-sdhci - qcom,sc7180-sdhci - qcom,sc7280-sdhci + - qcom,sc8280xp-sdhci - qcom,sdm630-sdhci - qcom,sdm670-sdhci - qcom,sdm845-sdhci diff --git a/Documentation/devicetree/bindings/mtd/allwinner,sun4i-a10-nand.yaml b/Documentation/devicetree/bindings/mtd/allwinner,sun4i-a10-nand.yaml index 9a88870cd8655a9d5d3ae5c63f50c1d7e8e40302..054b6b8bf9b911dad4ed071a366fc8af79caace2 100644 --- a/Documentation/devicetree/bindings/mtd/allwinner,sun4i-a10-nand.yaml +++ b/Documentation/devicetree/bindings/mtd/allwinner,sun4i-a10-nand.yaml @@ -49,13 +49,12 @@ properties: patternProperties: "^nand@[a-f0-9]$": type: object + $ref: raw-nand-chip.yaml properties: reg: minimum: 0 maximum: 7 - nand-ecc-mode: true - nand-ecc-algo: const: bch @@ -75,7 +74,7 @@ patternProperties: minimum: 0 maximum: 1 - additionalProperties: false + unevaluatedProperties: false required: - compatible diff --git a/Documentation/devicetree/bindings/mtd/amlogic,meson-nand.yaml b/Documentation/devicetree/bindings/mtd/amlogic,meson-nand.yaml index 28fb9a7dd70f1ec6707378dc8dba51a4f706f8fd..787ef488dd5b125b61bac74cce648f92ccd0249e 100644 --- a/Documentation/devicetree/bindings/mtd/amlogic,meson-nand.yaml +++ b/Documentation/devicetree/bindings/mtd/amlogic,meson-nand.yaml @@ -40,6 +40,7 @@ properties: patternProperties: "^nand@[0-7]$": type: object + $ref: raw-nand-chip.yaml properties: reg: minimum: 0 @@ -58,6 +59,14 @@ patternProperties: meson-gxl-nfc 8, 16, 24, 30, 40, 50, 60 meson-axg-nfc 8 + nand-rb: + maxItems: 1 + items: + maximum: 0 + + unevaluatedProperties: false + + required: - compatible - reg @@ -87,6 +96,7 @@ examples: nand@0 { reg = <0>; + nand-rb = <0>; }; }; diff --git a/Documentation/devicetree/bindings/mtd/brcm,brcmnand.yaml b/Documentation/devicetree/bindings/mtd/brcm,brcmnand.yaml index 1571024aa11903a0cc2c192eaf455707ad0f0f7e..f57e96374e67184e7013f88d3121fef9a72c689f 100644 --- a/Documentation/devicetree/bindings/mtd/brcm,brcmnand.yaml +++ b/Documentation/devicetree/bindings/mtd/brcm,brcmnand.yaml @@ -114,6 +114,7 @@ properties: patternProperties: "^nand@[a-f0-9]$": type: object + $ref: raw-nand-chip.yaml properties: compatible: const: brcm,nandcs @@ -136,6 +137,8 @@ patternProperties: layout. $ref: /schemas/types.yaml#/definitions/uint32 + unevaluatedProperties: false + allOf: - $ref: nand-controller.yaml# - if: diff --git a/Documentation/devicetree/bindings/mtd/denali,nand.yaml b/Documentation/devicetree/bindings/mtd/denali,nand.yaml index 0be83ad429705f4533fb0722d4507550d2bd9fed..81f95538d415a6c25cb5a51788634daa95159f0a 100644 --- a/Documentation/devicetree/bindings/mtd/denali,nand.yaml +++ b/Documentation/devicetree/bindings/mtd/denali,nand.yaml @@ -63,6 +63,12 @@ properties: minItems: 1 maxItems: 2 +patternProperties: + "^nand@[a-f0-9]$": + type: object + $ref: raw-nand-chip.yaml + unevaluatedProperties: false + allOf: - $ref: nand-controller.yaml @@ -74,7 +80,6 @@ allOf: then: patternProperties: "^nand@[a-f0-9]$": - type: object properties: nand-ecc-strength: enum: @@ -92,7 +97,6 @@ allOf: then: patternProperties: "^nand@[a-f0-9]$": - type: object properties: nand-ecc-strength: enum: @@ -111,7 +115,6 @@ allOf: then: patternProperties: "^nand@[a-f0-9]$": - type: object properties: nand-ecc-strength: enum: diff --git a/Documentation/devicetree/bindings/mtd/ingenic,nand.yaml b/Documentation/devicetree/bindings/mtd/ingenic,nand.yaml index a7bdb5d3675cfaa73bdad8809bdff5a6ba0130a5..b9312ebefeb960e6dbdcd7e9831d6a702ee73821 100644 --- a/Documentation/devicetree/bindings/mtd/ingenic,nand.yaml +++ b/Documentation/devicetree/bindings/mtd/ingenic,nand.yaml @@ -39,7 +39,9 @@ properties: patternProperties: "^nand@[a-f0-9]$": type: object + $ref: raw-nand-chip.yaml properties: + rb-gpios: description: GPIO specifier for the busy pin. maxItems: 1 @@ -48,6 +50,8 @@ patternProperties: description: GPIO specifier for the write-protect pin. maxItems: 1 + unevaluatedProperties: false + required: - compatible - reg diff --git a/Documentation/devicetree/bindings/mtd/intel,lgm-ebunand.yaml b/Documentation/devicetree/bindings/mtd/intel,lgm-ebunand.yaml index cc3def758e001425dc48eecc896861c7decc1cbb..07bc7e3efd3a89f440baf98539671e8adefb3997 100644 --- a/Documentation/devicetree/bindings/mtd/intel,lgm-ebunand.yaml +++ b/Documentation/devicetree/bindings/mtd/intel,lgm-ebunand.yaml @@ -42,17 +42,16 @@ properties: patternProperties: "^nand@[a-f0-9]$": type: object + $ref: raw-nand-chip.yaml properties: reg: minimum: 0 maximum: 1 - nand-ecc-mode: true - nand-ecc-algo: const: hw - additionalProperties: false + unevaluatedProperties: false required: - compatible diff --git a/Documentation/devicetree/bindings/mtd/marvell,nand-controller.yaml b/Documentation/devicetree/bindings/mtd/marvell,nand-controller.yaml new file mode 100644 index 0000000000000000000000000000000000000000..a10729bb18400347b502a1bf4426d7e4fdfe55a9 --- /dev/null +++ b/Documentation/devicetree/bindings/mtd/marvell,nand-controller.yaml @@ -0,0 +1,226 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/mtd/marvell,nand-controller.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Marvell NAND Flash Controller (NFC) + +maintainers: + - Miquel Raynal + +properties: + compatible: + oneOf: + - items: + - const: marvell,armada-8k-nand-controller + - const: marvell,armada370-nand-controller + - enum: + - marvell,armada370-nand-controller + - marvell,pxa3xx-nand-controller + - description: legacy bindings + deprecated: true + enum: + - marvell,armada-8k-nand + - marvell,armada370-nand + - marvell,pxa3xx-nand + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + clocks: + description: + Shall reference the NAND controller clocks, the second one is + is only needed for the Armada 7K/8K SoCs + minItems: 1 + maxItems: 2 + + clock-names: + minItems: 1 + items: + - const: core + - const: reg + + dmas: + maxItems: 1 + + dma-names: + items: + - const: data + + marvell,system-controller: + $ref: /schemas/types.yaml#/definitions/phandle + description: Syscon node that handles NAND controller related registers + +patternProperties: + "^nand@[a-f0-9]$": + type: object + $ref: raw-nand-chip.yaml + + properties: + reg: + minimum: 0 + maximum: 3 + + nand-rb: + items: + - minimum: 0 + maximum: 1 + + nand-ecc-step-size: + const: 512 + + nand-ecc-strength: + enum: [1, 4, 8, 12, 16] + + nand-ecc-mode: + const: hw + + marvell,nand-keep-config: + $ref: /schemas/types.yaml#/definitions/flag + description: + Orders the driver not to take the timings from the core and + leaving them completely untouched. Bootloader timings will then + be used. + + marvell,nand-enable-arbiter: + $ref: /schemas/types.yaml#/definitions/flag + description: + To enable the arbiter, all boards blindly used it, + this bit was set by the bootloader for many boards and even if + it is marked reserved in several datasheets, it might be needed to set + it (otherwise it is harmless). + deprecated: true + + required: + - reg + - nand-rb + + unevaluatedProperties: false + +required: + - compatible + - reg + - interrupts + - clocks + +allOf: + - $ref: nand-controller.yaml# + + - if: + properties: + compatible: + contains: + const: marvell,pxa3xx-nand-controller + then: + required: + - dmas + - dma-names + + - if: + properties: + compatible: + contains: + const: marvell,armada-8k-nand-controller + then: + properties: + clocks: + minItems: 2 + + clock-names: + minItems: 2 + + required: + - marvell,system-controller + + else: + properties: + clocks: + minItems: 1 + + clock-names: + minItems: 1 + + +unevaluatedProperties: false + +examples: + - | + #include + nand_controller: nand-controller@d0000 { + compatible = "marvell,armada370-nand-controller"; + reg = <0xd0000 0x54>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = ; + clocks = <&coredivclk 0>; + + nand@0 { + reg = <0>; + label = "main-storage"; + nand-rb = <0>; + nand-ecc-mode = "hw"; + marvell,nand-keep-config; + nand-on-flash-bbt; + nand-ecc-strength = <4>; + nand-ecc-step-size = <512>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "Rootfs"; + reg = <0x00000000 0x40000000>; + }; + }; + }; + }; + + - | + cp0_nand_controller: nand-controller@720000 { + compatible = "marvell,armada-8k-nand-controller", + "marvell,armada370-nand-controller"; + reg = <0x720000 0x54>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = <115 IRQ_TYPE_LEVEL_HIGH>; + clock-names = "core", "reg"; + clocks = <&cp0_clk 1 2>, + <&cp0_clk 1 17>; + marvell,system-controller = <&cp0_syscon0>; + + nand@0 { + reg = <0>; + label = "main-storage"; + nand-rb = <0>; + nand-ecc-mode = "hw"; + nand-ecc-strength = <8>; + nand-ecc-step-size = <512>; + }; + }; + + - | + nand-controller@43100000 { + compatible = "marvell,pxa3xx-nand-controller"; + reg = <0x43100000 90>; + interrupts = <45>; + clocks = <&clks 1>; + clock-names = "core"; + dmas = <&pdma 97 3>; + dma-names = "data"; + #address-cells = <1>; + #size-cells = <0>; + nand@0 { + reg = <0>; + nand-rb = <0>; + nand-ecc-mode = "hw"; + marvell,nand-keep-config; + }; + }; + +... diff --git a/Documentation/devicetree/bindings/mtd/marvell-nand.txt b/Documentation/devicetree/bindings/mtd/marvell-nand.txt deleted file mode 100644 index a2d9a0f2b683a6881e93e4a4b535ceef7eaa10b3..0000000000000000000000000000000000000000 --- a/Documentation/devicetree/bindings/mtd/marvell-nand.txt +++ /dev/null @@ -1,126 +0,0 @@ -Marvell NAND Flash Controller (NFC) - -Required properties: -- compatible: can be one of the following: - * "marvell,armada-8k-nand-controller" - * "marvell,armada370-nand-controller" - * "marvell,pxa3xx-nand-controller" - * "marvell,armada-8k-nand" (deprecated) - * "marvell,armada370-nand" (deprecated) - * "marvell,pxa3xx-nand" (deprecated) - Compatibles marked deprecated support only the old bindings described - at the bottom. -- reg: NAND flash controller memory area. -- #address-cells: shall be set to 1. Encode the NAND CS. -- #size-cells: shall be set to 0. -- interrupts: shall define the NAND controller interrupt. -- clocks: shall reference the NAND controller clocks, the second one is - is only needed for the Armada 7K/8K SoCs -- clock-names: mandatory if there is a second clock, in this case there - should be one clock named "core" and another one named "reg" -- marvell,system-controller: Set to retrieve the syscon node that handles - NAND controller related registers (only required with the - "marvell,armada-8k-nand[-controller]" compatibles). - -Optional properties: -- label: see partition.txt. New platforms shall omit this property. -- dmas: shall reference DMA channel associated to the NAND controller. - This property is only used with "marvell,pxa3xx-nand[-controller]" - compatible strings. -- dma-names: shall be "rxtx". - This property is only used with "marvell,pxa3xx-nand[-controller]" - compatible strings. - -Optional children nodes: -Children nodes represent the available NAND chips. - -Required properties: -- reg: shall contain the native Chip Select ids (0-3). -- nand-rb: see nand-controller.yaml (0-1). - -Optional properties: -- marvell,nand-keep-config: orders the driver not to take the timings - from the core and leaving them completely untouched. Bootloader - timings will then be used. -- label: MTD name. -- nand-on-flash-bbt: see nand-controller.yaml. -- nand-ecc-mode: see nand-controller.yaml. Will use hardware ECC if not specified. -- nand-ecc-algo: see nand-controller.yaml. This property is essentially useful when - not using hardware ECC. Howerver, it may be added when using hardware - ECC for clarification but will be ignored by the driver because ECC - mode is chosen depending on the page size and the strength required by - the NAND chip. This value may be overwritten with nand-ecc-strength - property. -- nand-ecc-strength: see nand-controller.yaml. -- nand-ecc-step-size: see nand-controller.yaml. Marvell's NAND flash controller does - use fixed strength (1-bit for Hamming, 16-bit for BCH), so the actual - step size will shrink or grow in order to fit the required strength. - Step sizes are not completely random for all and follow certain - patterns described in AN-379, "Marvell SoC NFC ECC". - -See Documentation/devicetree/bindings/mtd/nand-controller.yaml for more details on -generic bindings. - - -Example: -nand_controller: nand-controller@d0000 { - compatible = "marvell,armada370-nand-controller"; - reg = <0xd0000 0x54>; - #address-cells = <1>; - #size-cells = <0>; - interrupts = ; - clocks = <&coredivclk 0>; - - nand@0 { - reg = <0>; - label = "main-storage"; - nand-rb = <0>; - nand-ecc-mode = "hw"; - marvell,nand-keep-config; - nand-on-flash-bbt; - nand-ecc-strength = <4>; - nand-ecc-step-size = <512>; - - partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - partition@0 { - label = "Rootfs"; - reg = <0x00000000 0x40000000>; - }; - }; - }; -}; - - -Note on legacy bindings: One can find, in not-updated device trees, -bindings slightly different than described above with other properties -described below as well as the partitions node at the root of a so -called "nand" node (without clear controller/chip separation). - -Legacy properties: -- marvell,nand-enable-arbiter: To enable the arbiter, all boards blindly - used it, this bit was set by the bootloader for many boards and even if - it is marked reserved in several datasheets, it might be needed to set - it (otherwise it is harmless) so whether or not this property is set, - the bit is selected by the driver. -- num-cs: Number of chip-select lines to use, all boards blindly set 1 - to this and for a reason, other values would have failed. The value of - this property is ignored. - -Example: - - nand0: nand@43100000 { - compatible = "marvell,pxa3xx-nand"; - reg = <0x43100000 90>; - interrupts = <45>; - dmas = <&pdma 97 0>; - dma-names = "rxtx"; - #address-cells = <1>; - marvell,nand-keep-config; - marvell,nand-enable-arbiter; - num-cs = <1>; - /* Partitions (optional) */ - }; diff --git a/Documentation/devicetree/bindings/mtd/mediatek,mtk-nfc.yaml b/Documentation/devicetree/bindings/mtd/mediatek,mtk-nfc.yaml index a6e7f123eda7eef9e30a2cee17053d04b828616d..ab503a33a2698539081e61048ca9623ef697403f 100644 --- a/Documentation/devicetree/bindings/mtd/mediatek,mtk-nfc.yaml +++ b/Documentation/devicetree/bindings/mtd/mediatek,mtk-nfc.yaml @@ -40,12 +40,11 @@ properties: patternProperties: "^nand@[a-f0-9]$": - $ref: nand-chip.yaml# + $ref: raw-nand-chip.yaml# unevaluatedProperties: false properties: reg: maximum: 1 - nand-on-flash-bbt: true nand-ecc-mode: const: hw diff --git a/Documentation/devicetree/bindings/mtd/mtd-physmap.yaml b/Documentation/devicetree/bindings/mtd/mtd-physmap.yaml index f8c976898a95827659d17b5a6ebb3078f441a7e2..18f6733408b493bb53351d6e0560ab0a0a435cad 100644 --- a/Documentation/devicetree/bindings/mtd/mtd-physmap.yaml +++ b/Documentation/devicetree/bindings/mtd/mtd-physmap.yaml @@ -164,7 +164,7 @@ examples: reg = <0 0xf80000>; }; firmware@f80000 { - label ="firmware"; + label = "firmware"; reg = <0xf80000 0x80000>; read-only; }; diff --git a/Documentation/devicetree/bindings/mtd/mtd.yaml b/Documentation/devicetree/bindings/mtd/mtd.yaml index da3d488c335f75c272d74c6400d31f0bb7b37fc9..b82ca03e969c2affea40954e1a6384860792cbb3 100644 --- a/Documentation/devicetree/bindings/mtd/mtd.yaml +++ b/Documentation/devicetree/bindings/mtd/mtd.yaml @@ -12,7 +12,7 @@ maintainers: properties: $nodename: - pattern: "^(flash|.*sram)(@.*)?$" + pattern: "^(flash|.*sram|nand)(@.*)?$" label: description: diff --git a/Documentation/devicetree/bindings/mtd/nand-controller.yaml b/Documentation/devicetree/bindings/mtd/nand-controller.yaml index f70a32d2d9d4d9775dfdef4b433cb9fcf9f8b98a..83a4fe4cc29d3f8a920baaa4f8ddb5116cdb7a9b 100644 --- a/Documentation/devicetree/bindings/mtd/nand-controller.yaml +++ b/Documentation/devicetree/bindings/mtd/nand-controller.yaml @@ -16,16 +16,6 @@ description: | children nodes of the NAND controller. This representation should be enforced even for simple controllers supporting only one chip. - The ECC strength and ECC step size properties define the user - desires in terms of correction capability of a controller. Together, - they request the ECC engine to correct {strength} bit errors per - {size} bytes. - - The interpretation of these parameters is implementation-defined, so - not all implementations must support all possible - combinations. However, implementations are encouraged to further - specify the value(s) they support. - properties: $nodename: pattern: "^nand-controller(@.*)?" @@ -51,79 +41,8 @@ properties: patternProperties: "^nand@[a-f0-9]$": - $ref: nand-chip.yaml# - - properties: - reg: - description: - Contains the chip-select IDs. - - nand-ecc-placement: - description: - Location of the ECC bytes. This location is unknown by default - but can be explicitly set to "oob", if all ECC bytes are - known to be stored in the OOB area, or "interleaved" if ECC - bytes will be interleaved with regular data in the main area. - $ref: /schemas/types.yaml#/definitions/string - enum: [ oob, interleaved ] - - nand-bus-width: - description: - Bus width to the NAND chip - $ref: /schemas/types.yaml#/definitions/uint32 - enum: [8, 16] - default: 8 - - nand-on-flash-bbt: - description: - With this property, the OS will search the device for a Bad - Block Table (BBT). If not found, it will create one, reserve - a few blocks at the end of the device to store it and update - it as the device ages. Otherwise, the out-of-band area of a - few pages of all the blocks will be scanned at boot time to - find Bad Block Markers (BBM). These markers will help to - build a volatile BBT in RAM. - $ref: /schemas/types.yaml#/definitions/flag - - nand-ecc-maximize: - description: - Whether or not the ECC strength should be maximized. The - maximum ECC strength is both controller and chip - dependent. The ECC engine has to select the ECC config - providing the best strength and taking the OOB area size - constraint into account. This is particularly useful when - only the in-band area is used by the upper layers, and you - want to make your NAND as reliable as possible. - $ref: /schemas/types.yaml#/definitions/flag - - nand-is-boot-medium: - description: - Whether or not the NAND chip is a boot medium. Drivers might - use this information to select ECC algorithms supported by - the boot ROM or similar restrictions. - $ref: /schemas/types.yaml#/definitions/flag - - nand-rb: - description: - Contains the native Ready/Busy IDs. - $ref: /schemas/types.yaml#/definitions/uint32-array - - rb-gpios: - description: - Contains one or more GPIO descriptor (the numper of descriptor - depends on the number of R/B pins exposed by the flash) for the - Ready/Busy pins. Active state refers to the NAND ready state and - should be set to GPIOD_ACTIVE_HIGH unless the signal is inverted. - - wp-gpios: - description: - Contains one GPIO descriptor for the Write Protect pin. - Active state refers to the NAND Write Protect state and should be - set to GPIOD_ACTIVE_LOW unless the signal is inverted. - maxItems: 1 - - required: - - reg + type: object + $ref: raw-nand-chip.yaml# required: - "#address-cells" diff --git a/Documentation/devicetree/bindings/mtd/partitions/partition.yaml b/Documentation/devicetree/bindings/mtd/partitions/partition.yaml index cdffbb9cedc2d7cbb7e7557189922d49bc83fb8a..1ebe9e2347eaf7d7d1eac1c958ca3211112a414f 100644 --- a/Documentation/devicetree/bindings/mtd/partitions/partition.yaml +++ b/Documentation/devicetree/bindings/mtd/partitions/partition.yaml @@ -55,6 +55,7 @@ properties: linux,rootfs: description: Marks partition that contains root filesystem to mount and boot user space from + type: boolean if: not: diff --git a/Documentation/devicetree/bindings/mtd/partitions/partitions.yaml b/Documentation/devicetree/bindings/mtd/partitions/partitions.yaml index 2edc65e0e3610d2034532d8701971364e5238125..1dda2c80747bd72d46a33bd9fd550627b63c0c2c 100644 --- a/Documentation/devicetree/bindings/mtd/partitions/partitions.yaml +++ b/Documentation/devicetree/bindings/mtd/partitions/partitions.yaml @@ -21,6 +21,7 @@ oneOf: - $ref: linksys,ns-partitions.yaml - $ref: qcom,smem-part.yaml - $ref: redboot-fis.yaml + - $ref: tplink,safeloader-partitions.yaml properties: compatible: true diff --git a/Documentation/devicetree/bindings/mtd/qcom,nandc.yaml b/Documentation/devicetree/bindings/mtd/qcom,nandc.yaml index 00c991ffa6c4518a48b5375fddb9aae79189555d..4ada60fbf81de40070f4f92838b4dcb4b200a928 100644 --- a/Documentation/devicetree/bindings/mtd/qcom,nandc.yaml +++ b/Documentation/devicetree/bindings/mtd/qcom,nandc.yaml @@ -34,7 +34,9 @@ properties: patternProperties: "^nand@[a-f0-9]$": type: object + $ref: raw-nand-chip.yaml properties: + nand-bus-width: const: 8 @@ -45,6 +47,24 @@ patternProperties: enum: - 512 + qcom,boot-partitions: + $ref: /schemas/types.yaml#/definitions/uint32-matrix + items: + items: + - description: offset + - description: size + description: + Boot partition use a different layout where the 4 bytes of spare + data are not protected by ECC. Use this to declare these special + partitions by defining first the offset and then the size. + + It's in the form of + and should be declared in ascending order. + + Refer to the ipq8064 example on how to use this special binding. + + unevaluatedProperties: false + allOf: - $ref: nand-controller.yaml# @@ -107,22 +127,15 @@ allOf: - qcom,ipq806x-nand then: - properties: - qcom,boot-partitions: - $ref: /schemas/types.yaml#/definitions/uint32-matrix - items: - items: - - description: offset - - description: size - description: - Boot partition use a different layout where the 4 bytes of spare - data are not protected by ECC. Use this to declare these special - partitions by defining first the offset and then the size. - - It's in the form of - and should be declared in ascending order. - - Refer to the ipq8064 example on how to use this special binding. + patternProperties: + "^nand@[a-f0-9]$": + properties: + qcom,boot-partitions: true + else: + patternProperties: + "^nand@[a-f0-9]$": + properties: + qcom,boot-partitions: false required: - compatible diff --git a/Documentation/devicetree/bindings/mtd/raw-nand-chip.yaml b/Documentation/devicetree/bindings/mtd/raw-nand-chip.yaml new file mode 100644 index 0000000000000000000000000000000000000000..092448d7bfc5ccd246ca4b2341464e18722a2d51 --- /dev/null +++ b/Documentation/devicetree/bindings/mtd/raw-nand-chip.yaml @@ -0,0 +1,111 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/mtd/raw-nand-chip.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Raw NAND Chip Common Properties + +maintainers: + - Miquel Raynal + +allOf: + - $ref: nand-chip.yaml# + +description: | + The ECC strength and ECC step size properties define the user + desires in terms of correction capability of a controller. Together, + they request the ECC engine to correct {strength} bit errors per + {size} bytes for a particular raw NAND chip. + + The interpretation of these parameters is implementation-defined, so + not all implementations must support all possible + combinations. However, implementations are encouraged to further + specify the value(s) they support. + +properties: + $nodename: + pattern: "^nand@[a-f0-9]$" + + reg: + description: + Contains the chip-select IDs. + + nand-ecc-placement: + description: + Location of the ECC bytes. This location is unknown by default + but can be explicitly set to "oob", if all ECC bytes are + known to be stored in the OOB area, or "interleaved" if ECC + bytes will be interleaved with regular data in the main area. + $ref: /schemas/types.yaml#/definitions/string + enum: [ oob, interleaved ] + deprecated: true + + nand-ecc-mode: + description: + Legacy ECC configuration mixing the ECC engine choice and + configuration. + $ref: /schemas/types.yaml#/definitions/string + enum: [none, soft, soft_bch, hw, hw_syndrome, on-die] + deprecated: true + + nand-bus-width: + description: + Bus width to the NAND chip + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [8, 16] + default: 8 + + nand-on-flash-bbt: + description: + With this property, the OS will search the device for a Bad + Block Table (BBT). If not found, it will create one, reserve + a few blocks at the end of the device to store it and update + it as the device ages. Otherwise, the out-of-band area of a + few pages of all the blocks will be scanned at boot time to + find Bad Block Markers (BBM). These markers will help to + build a volatile BBT in RAM. + $ref: /schemas/types.yaml#/definitions/flag + + nand-ecc-maximize: + description: + Whether or not the ECC strength should be maximized. The + maximum ECC strength is both controller and chip + dependent. The ECC engine has to select the ECC config + providing the best strength and taking the OOB area size + constraint into account. This is particularly useful when + only the in-band area is used by the upper layers, and you + want to make your NAND as reliable as possible. + $ref: /schemas/types.yaml#/definitions/flag + + nand-is-boot-medium: + description: + Whether or not the NAND chip is a boot medium. Drivers might + use this information to select ECC algorithms supported by + the boot ROM or similar restrictions. + $ref: /schemas/types.yaml#/definitions/flag + + nand-rb: + description: + Contains the native Ready/Busy IDs. + $ref: /schemas/types.yaml#/definitions/uint32-array + + rb-gpios: + description: + Contains one or more GPIO descriptor (the numper of descriptor + depends on the number of R/B pins exposed by the flash) for the + Ready/Busy pins. Active state refers to the NAND ready state and + should be set to GPIOD_ACTIVE_HIGH unless the signal is inverted. + + wp-gpios: + description: + Contains one GPIO descriptor for the Write Protect pin. + Active state refers to the NAND Write Protect state and should be + set to GPIOD_ACTIVE_LOW unless the signal is inverted. + maxItems: 1 + +required: + - reg + +# This is a generic file other binding inherit from and extend +additionalProperties: true diff --git a/Documentation/devicetree/bindings/mtd/rockchip,nand-controller.yaml b/Documentation/devicetree/bindings/mtd/rockchip,nand-controller.yaml index 7eb1d0a385653cb0d45d1234015189d7270e4988..ee53715ffdca3e38808bd81377c9ab7a29742877 100644 --- a/Documentation/devicetree/bindings/mtd/rockchip,nand-controller.yaml +++ b/Documentation/devicetree/bindings/mtd/rockchip,nand-controller.yaml @@ -57,6 +57,7 @@ properties: patternProperties: "^nand@[0-7]$": type: object + $ref: raw-nand-chip.yaml properties: reg: minimum: 0 @@ -116,6 +117,8 @@ patternProperties: Only used in combination with 'nand-is-boot-medium'. + unevaluatedProperties: false + required: - compatible - reg diff --git a/Documentation/devicetree/bindings/mtd/st,stm32-fmc2-nand.yaml b/Documentation/devicetree/bindings/mtd/st,stm32-fmc2-nand.yaml index 986e85ccebc7b55e8969dc63e3657bb187fe2b5a..e72cb5bacaf0a983033b734a4e84a5b3a226b58f 100644 --- a/Documentation/devicetree/bindings/mtd/st,stm32-fmc2-nand.yaml +++ b/Documentation/devicetree/bindings/mtd/st,stm32-fmc2-nand.yaml @@ -37,6 +37,7 @@ properties: patternProperties: "^nand@[a-f0-9]$": type: object + $ref: raw-nand-chip.yaml properties: nand-ecc-step-size: const: 512 @@ -44,6 +45,8 @@ patternProperties: nand-ecc-strength: enum: [1, 4, 8] + unevaluatedProperties: false + allOf: - $ref: nand-controller.yaml# diff --git a/Documentation/devicetree/bindings/mtd/ti,am654-hbmc.yaml b/Documentation/devicetree/bindings/mtd/ti,am654-hbmc.yaml index 4774c92e7fc4d988c925dcab2f7dd03dd261c004..df4fdc02456ddf0cd084e2a9f515559c3b78c735 100644 --- a/Documentation/devicetree/bindings/mtd/ti,am654-hbmc.yaml +++ b/Documentation/devicetree/bindings/mtd/ti,am654-hbmc.yaml @@ -30,6 +30,8 @@ properties: patternProperties: "^flash@[0-1],[0-9a-f]+$": type: object + $ref: mtd-physmap.yaml + unevaluatedProperties: false required: - compatible diff --git a/Documentation/devicetree/bindings/net/allwinner,sun7i-a20-gmac.yaml b/Documentation/devicetree/bindings/net/allwinner,sun7i-a20-gmac.yaml index 3bd912ed7c7ead993346eadf3523156cc04d3cd2..23e92be33ac8609a16db530782989caed22a5730 100644 --- a/Documentation/devicetree/bindings/net/allwinner,sun7i-a20-gmac.yaml +++ b/Documentation/devicetree/bindings/net/allwinner,sun7i-a20-gmac.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Allwinner A20 GMAC allOf: - - $ref: "snps,dwmac.yaml#" + - $ref: snps,dwmac.yaml# maintainers: - Chen-Yu Tsai diff --git a/Documentation/devicetree/bindings/net/allwinner,sun8i-a83t-emac.yaml b/Documentation/devicetree/bindings/net/allwinner,sun8i-a83t-emac.yaml index 47bc2057e6292a829dc25b2ef5e2f70ea6a3efa8..4bfac91868863fb587e303ae32c08f83d6cbce72 100644 --- a/Documentation/devicetree/bindings/net/allwinner,sun8i-a83t-emac.yaml +++ b/Documentation/devicetree/bindings/net/allwinner,sun8i-a83t-emac.yaml @@ -63,7 +63,7 @@ required: - syscon allOf: - - $ref: "snps,dwmac.yaml#" + - $ref: snps,dwmac.yaml# - if: properties: compatible: diff --git a/Documentation/devicetree/bindings/net/altr,tse.yaml b/Documentation/devicetree/bindings/net/altr,tse.yaml index 9d02af46890613a901e75ba38402d84f5ca11409..f5d3b70af07a6fbc4bab13ebf52fb9d6e9747cfc 100644 --- a/Documentation/devicetree/bindings/net/altr,tse.yaml +++ b/Documentation/devicetree/bindings/net/altr,tse.yaml @@ -72,8 +72,8 @@ allOf: compatible: contains: enum: - - const: altr,tse-1.0 - - const: ALTR,tse-1.0 + - altr,tse-1.0 + - ALTR,tse-1.0 then: properties: reg: diff --git a/Documentation/devicetree/bindings/net/amlogic,meson-dwmac.yaml b/Documentation/devicetree/bindings/net/amlogic,meson-dwmac.yaml index a2c51a84efa55592b47fdd1019d1a3415b0e58a9..ee7a65b528cdac79af1b2031d2d0bcc758fa2773 100644 --- a/Documentation/devicetree/bindings/net/amlogic,meson-dwmac.yaml +++ b/Documentation/devicetree/bindings/net/amlogic,meson-dwmac.yaml @@ -27,7 +27,7 @@ select: - compatible allOf: - - $ref: "snps,dwmac.yaml#" + - $ref: snps,dwmac.yaml# - if: properties: compatible: diff --git a/Documentation/devicetree/bindings/net/bluetooth/nxp,88w8987-bt.yaml b/Documentation/devicetree/bindings/net/bluetooth/nxp,88w8987-bt.yaml index 57e4c87cb00b45feebc4e4119625434b36d99e83..f01a3988538c74daeacd74a8735d57228d46cec5 100644 --- a/Documentation/devicetree/bindings/net/bluetooth/nxp,88w8987-bt.yaml +++ b/Documentation/devicetree/bindings/net/bluetooth/nxp,88w8987-bt.yaml @@ -24,11 +24,12 @@ properties: - nxp,88w8997-bt fw-init-baudrate: + $ref: /schemas/types.yaml#/definitions/uint32 + default: 115200 description: Chip baudrate after FW is downloaded and initialized. This property depends on the module vendor's - configuration. If this property is not specified, - 115200 is set as default. + configuration. required: - compatible diff --git a/Documentation/devicetree/bindings/net/bluetooth/qualcomm-bluetooth.yaml b/Documentation/devicetree/bindings/net/bluetooth/qualcomm-bluetooth.yaml index 68f78b90d23a3d90379f70b34798bd7bbd140e3e..56cbb42b5aeaa0de71408065b85279a06888e058 100644 --- a/Documentation/devicetree/bindings/net/bluetooth/qualcomm-bluetooth.yaml +++ b/Documentation/devicetree/bindings/net/bluetooth/qualcomm-bluetooth.yaml @@ -16,6 +16,7 @@ description: properties: compatible: enum: + - qcom,qca2066-bt - qcom,qca6174-bt - qcom,qca9377-bt - qcom,wcn3990-bt @@ -50,6 +51,9 @@ properties: vddch0-supply: description: VDD_CH0 supply regulator handle + vddch1-supply: + description: VDD_CH1 supply regulator handle + vddaon-supply: description: VDD_AON supply regulator handle @@ -95,6 +99,7 @@ allOf: compatible: contains: enum: + - qcom,qca2066-bt - qcom,qca6174-bt then: required: diff --git a/Documentation/devicetree/bindings/net/brcm,bcmgenet.yaml b/Documentation/devicetree/bindings/net/brcm,bcmgenet.yaml index 0e5e5db32fafddedea4af3e6f84e3ce1606e48aa..7c90a43905319b9ec48914add537f6eea889a7e9 100644 --- a/Documentation/devicetree/bindings/net/brcm,bcmgenet.yaml +++ b/Documentation/devicetree/bindings/net/brcm,bcmgenet.yaml @@ -55,7 +55,7 @@ properties: patternProperties: "^mdio@[0-9a-f]+$": type: object - $ref: "brcm,unimac-mdio.yaml" + $ref: brcm,unimac-mdio.yaml description: GENET internal UniMAC MDIO bus diff --git a/Documentation/devicetree/bindings/net/cdns,macb.yaml b/Documentation/devicetree/bindings/net/cdns,macb.yaml index bef5e0f895be87a7ec69e39100cde05173582c34..bf8894a0257e9d051b605c3b015f453f5280f37b 100644 --- a/Documentation/devicetree/bindings/net/cdns,macb.yaml +++ b/Documentation/devicetree/bindings/net/cdns,macb.yaml @@ -109,6 +109,16 @@ properties: power-domains: maxItems: 1 + cdns,rx-watermark: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + When the receive partial store and forward mode is activated, + the receiver will only begin to forward the packet to the external + AHB or AXI slave when enough packet data is stored in the SRAM packet buffer. + rx-watermark corresponds to the number of SRAM buffer locations, + that need to be filled, before the forwarding process is activated. + Width of the SRAM is platform dependent, and can be 4, 8 or 16 bytes. + '#address-cells': const: 1 @@ -166,6 +176,7 @@ examples: compatible = "cdns,macb"; reg = <0xfffc4000 0x4000>; interrupts = <21>; + cdns,rx-watermark = <0x44>; phy-mode = "rmii"; local-mac-address = [3a 0e 03 04 05 06]; clock-names = "pclk", "hclk", "tx_clk"; diff --git a/Documentation/devicetree/bindings/net/dsa/marvell.txt b/Documentation/devicetree/bindings/net/dsa/marvell.txt index 2363b412410c3714285fb0259c56c2e20816412a..33726134f5c9697f80439b4c5c37e58ee677dd05 100644 --- a/Documentation/devicetree/bindings/net/dsa/marvell.txt +++ b/Documentation/devicetree/bindings/net/dsa/marvell.txt @@ -20,7 +20,7 @@ which is at a different MDIO base address in different switch families. 6171, 6172, 6175, 6176, 6185, 6240, 6320, 6321, 6341, 6350, 6351, 6352 - "marvell,mv88e6190" : Switch has base address 0x00. Use with models: - 6190, 6190X, 6191, 6290, 6390, 6390X + 6163, 6190, 6190X, 6191, 6290, 6390, 6390X - "marvell,mv88e6250" : Switch has base address 0x08 or 0x18. Use with model: 6220, 6250 diff --git a/Documentation/devicetree/bindings/net/dsa/nxp,sja1105.yaml b/Documentation/devicetree/bindings/net/dsa/nxp,sja1105.yaml index 9a64ed65874542a9729e572315fd09f752d309ab..4d5f5cc6d031e280d9c04831346acee6b574a638 100644 --- a/Documentation/devicetree/bindings/net/dsa/nxp,sja1105.yaml +++ b/Documentation/devicetree/bindings/net/dsa/nxp,sja1105.yaml @@ -12,10 +12,6 @@ description: cs_sck_delay of 500ns. Ensuring that this SPI timing requirement is observed depends on the SPI bus master driver. -allOf: - - $ref: dsa.yaml#/$defs/ethernet-ports - - $ref: /schemas/spi/spi-peripheral-props.yaml# - maintainers: - Vladimir Oltean @@ -36,6 +32,9 @@ properties: reg: maxItems: 1 + spi-cpha: true + spi-cpol: true + # Optional container node for the 2 internal MDIO buses of the SJA1110 # (one for the internal 100base-T1 PHYs and the other for the single # 100base-TX PHY). The "reg" property does not have physical significance. @@ -109,6 +108,30 @@ $defs: 1860, 1880, 1900, 1920, 1940, 1960, 1980, 2000, 2020, 2040, 2060, 2080, 2100, 2120, 2140, 2160, 2180, 2200, 2220, 2240, 2260] +allOf: + - $ref: dsa.yaml#/$defs/ethernet-ports + - $ref: /schemas/spi/spi-peripheral-props.yaml# + - if: + properties: + compatible: + enum: + - nxp,sja1105e + - nxp,sja1105p + - nxp,sja1105q + - nxp,sja1105r + - nxp,sja1105s + - nxp,sja1105t + then: + properties: + spi-cpol: false + required: + - spi-cpha + else: + properties: + spi-cpha: false + required: + - spi-cpol + unevaluatedProperties: false examples: @@ -120,6 +143,7 @@ examples: ethernet-switch@1 { reg = <0x1>; compatible = "nxp,sja1105t"; + spi-cpha; ethernet-ports { #address-cells = <1>; diff --git a/Documentation/devicetree/bindings/net/ethernet-phy.yaml b/Documentation/devicetree/bindings/net/ethernet-phy.yaml index 4f574532ee13ccf5e7050d660b3854d3af47c108..c1241c8a3b779f63fe16d3cf59e01f0cfcd58f86 100644 --- a/Documentation/devicetree/bindings/net/ethernet-phy.yaml +++ b/Documentation/devicetree/bindings/net/ethernet-phy.yaml @@ -93,6 +93,12 @@ properties: the turn around line low at end of the control phase of the MDIO transaction. + clocks: + maxItems: 1 + description: + External clock connected to the PHY. If not specified it is assumed + that the PHY uses a fixed crystal or an internal oscillator. + enet-phy-lane-swap: $ref: /schemas/types.yaml#/definitions/flag description: diff --git a/Documentation/devicetree/bindings/net/intel,dwmac-plat.yaml b/Documentation/devicetree/bindings/net/intel,dwmac-plat.yaml index d23fa3771210a0b5475bc190769c815aadbf14b2..42a0bc94312c3cb25acf36fe397403d055b61483 100644 --- a/Documentation/devicetree/bindings/net/intel,dwmac-plat.yaml +++ b/Documentation/devicetree/bindings/net/intel,dwmac-plat.yaml @@ -19,7 +19,7 @@ select: - compatible allOf: - - $ref: "snps,dwmac.yaml#" + - $ref: snps,dwmac.yaml# properties: compatible: diff --git a/Documentation/devicetree/bindings/net/maxlinear,gpy2xx.yaml b/Documentation/devicetree/bindings/net/maxlinear,gpy2xx.yaml index d71fa9de2b64dbc74ffbb86d958f03ebbf1dc03a..8a3713abd1ca9f8972a4356143cbf24ad9b36bb0 100644 --- a/Documentation/devicetree/bindings/net/maxlinear,gpy2xx.yaml +++ b/Documentation/devicetree/bindings/net/maxlinear,gpy2xx.yaml @@ -17,11 +17,12 @@ properties: maxlinear,use-broken-interrupts: description: | Interrupts are broken on some GPY2xx PHYs in that they keep the - interrupt line asserted even after the interrupt status register is - cleared. Thus it is blocking the interrupt line which is usually bad - for shared lines. By default interrupts are disabled for this PHY and - polling mode is used. If one can live with the consequences, this - property can be used to enable interrupt handling. + interrupt line asserted for a random amount of time even after the + interrupt status register is cleared. Thus it is blocking the + interrupt line which is usually bad for shared lines. By default, + interrupts are disabled for this PHY and polling mode is used. If one + can live with the consequences, this property can be used to enable + interrupt handling. Affected PHYs (as far as known) are GPY215B and GPY215C. type: boolean diff --git a/Documentation/devicetree/bindings/net/mediatek-dwmac.yaml b/Documentation/devicetree/bindings/net/mediatek-dwmac.yaml index 0fa2132fa4f4d16207f290153b4af6c5236b79d3..5aa320c8af5aa955ceb16413f6909938c4619ff7 100644 --- a/Documentation/devicetree/bindings/net/mediatek-dwmac.yaml +++ b/Documentation/devicetree/bindings/net/mediatek-dwmac.yaml @@ -25,7 +25,7 @@ select: - compatible allOf: - - $ref: "snps,dwmac.yaml#" + - $ref: snps,dwmac.yaml# properties: compatible: @@ -156,7 +156,7 @@ examples: reg = <0x1101c000 0x1300>; interrupts = ; interrupt-names = "macirq"; - phy-mode ="rgmii-rxid"; + phy-mode = "rgmii-rxid"; mac-address = [00 55 7b b5 7d f7]; clock-names = "axi", "apb", diff --git a/Documentation/devicetree/bindings/net/micrel,ks8851.yaml b/Documentation/devicetree/bindings/net/micrel,ks8851.yaml index b44d83554ef57a7d24346c3de75a95a4e4baa806..b726c6e146333e750585bf2794cd763d4c5535b1 100644 --- a/Documentation/devicetree/bindings/net/micrel,ks8851.yaml +++ b/Documentation/devicetree/bindings/net/micrel,ks8851.yaml @@ -44,13 +44,13 @@ required: allOf: - $ref: ethernet-controller.yaml# - - $ref: /schemas/memory-controllers/mc-peripheral-props.yaml# - if: properties: compatible: contains: const: micrel,ks8851 then: + $ref: /schemas/spi/spi-peripheral-props.yaml# properties: reg: maxItems: 1 @@ -60,6 +60,7 @@ allOf: contains: const: micrel,ks8851-mll then: + $ref: /schemas/memory-controllers/mc-peripheral-props.yaml# properties: reg: minItems: 2 diff --git a/Documentation/devicetree/bindings/net/nxp,dwmac-imx.yaml b/Documentation/devicetree/bindings/net/nxp,dwmac-imx.yaml index 63409cbff5ad1dfa6e306a780aa1abb86554e957..4c01cae7c93a7776a1f1fbff0057c0337ac4b83f 100644 --- a/Documentation/devicetree/bindings/net/nxp,dwmac-imx.yaml +++ b/Documentation/devicetree/bindings/net/nxp,dwmac-imx.yaml @@ -24,7 +24,7 @@ select: - compatible allOf: - - $ref: "snps,dwmac.yaml#" + - $ref: snps,dwmac.yaml# properties: compatible: diff --git a/Documentation/devicetree/bindings/net/pse-pd/pse-controller.yaml b/Documentation/devicetree/bindings/net/pse-pd/pse-controller.yaml index b110abb42597e64a43584f1c9c3c0a39a96f6999..2d382faca0e6d16ff0bff5e1f5915110d722e1ed 100644 --- a/Documentation/devicetree/bindings/net/pse-pd/pse-controller.yaml +++ b/Documentation/devicetree/bindings/net/pse-pd/pse-controller.yaml @@ -16,7 +16,7 @@ maintainers: properties: $nodename: - pattern: "^ethernet-pse(@.*)?$" + pattern: "^ethernet-pse(@.*|-([0-9]|[1-9][0-9]+))?$" "#pse-cells": description: diff --git a/Documentation/devicetree/bindings/net/qcom,ethqos.yaml b/Documentation/devicetree/bindings/net/qcom,ethqos.yaml index 60a38044fb1995c7c43d8fa66a78deea06044794..7bdb412a018553decc06f8991cb7d5d552d20df9 100644 --- a/Documentation/devicetree/bindings/net/qcom,ethqos.yaml +++ b/Documentation/devicetree/bindings/net/qcom,ethqos.yaml @@ -20,6 +20,7 @@ properties: compatible: enum: - qcom,qcs404-ethqos + - qcom,sa8775p-ethqos - qcom,sc8280xp-ethqos - qcom,sm8150-ethqos @@ -32,11 +33,13 @@ properties: - const: rgmii interrupts: + minItems: 1 items: - description: Combined signal for various interrupt events - description: The interrupt that occurs when Rx exits the LPI state interrupt-names: + minItems: 1 items: - const: macirq - const: eth_lpi @@ -49,11 +52,18 @@ properties: - const: stmmaceth - const: pclk - const: ptp_ref - - const: rgmii + - enum: + - rgmii + - phyaux iommus: maxItems: 1 + phys: true + + phy-names: + const: serdes + required: - compatible - clocks diff --git a/Documentation/devicetree/bindings/net/rockchip-dwmac.yaml b/Documentation/devicetree/bindings/net/rockchip-dwmac.yaml index 2a21bbe0289216928f3614ef2c98821a7fb2d7d5..176ea5f90251af1ffd6ee2cc3c3dc458d04b67b9 100644 --- a/Documentation/devicetree/bindings/net/rockchip-dwmac.yaml +++ b/Documentation/devicetree/bindings/net/rockchip-dwmac.yaml @@ -32,7 +32,7 @@ select: - compatible allOf: - - $ref: "snps,dwmac.yaml#" + - $ref: snps,dwmac.yaml# properties: compatible: diff --git a/Documentation/devicetree/bindings/net/snps,dwmac.yaml b/Documentation/devicetree/bindings/net/snps,dwmac.yaml index 363b3e3ea3a60ad8d33937971888aa4ddae5830d..ddf9522a5dc2303ab8ea656005918d464dd054c1 100644 --- a/Documentation/devicetree/bindings/net/snps,dwmac.yaml +++ b/Documentation/devicetree/bindings/net/snps,dwmac.yaml @@ -67,6 +67,7 @@ properties: - loongson,ls2k-dwmac - loongson,ls7a-dwmac - qcom,qcs404-ethqos + - qcom,sa8775p-ethqos - qcom,sc8280xp-ethqos - qcom,sm8150-ethqos - renesas,r9a06g032-gmac @@ -582,6 +583,7 @@ allOf: - ingenic,x1600-mac - ingenic,x1830-mac - ingenic,x2000-mac + - qcom,sa8775p-ethqos - qcom,sc8280xp-ethqos - snps,dwmac-3.50a - snps,dwmac-4.10a @@ -638,6 +640,7 @@ allOf: - ingenic,x1830-mac - ingenic,x2000-mac - qcom,qcs404-ethqos + - qcom,sa8775p-ethqos - qcom,sc8280xp-ethqos - qcom,sm8150-ethqos - snps,dwmac-4.00 diff --git a/Documentation/devicetree/bindings/net/ti,k3-am654-cpsw-nuss.yaml b/Documentation/devicetree/bindings/net/ti,k3-am654-cpsw-nuss.yaml index 395a4650e285286966d1c695c8ae65a0a36a25c5..c9c25132d1544a537aceb438b65a2c79934b0679 100644 --- a/Documentation/devicetree/bindings/net/ti,k3-am654-cpsw-nuss.yaml +++ b/Documentation/devicetree/bindings/net/ti,k3-am654-cpsw-nuss.yaml @@ -168,14 +168,14 @@ properties: patternProperties: "^mdio@[0-9a-f]+$": type: object - $ref: "ti,davinci-mdio.yaml#" + $ref: ti,davinci-mdio.yaml# description: CPSW MDIO bus. "^cpts@[0-9a-f]+": type: object - $ref: "ti,k3-am654-cpts.yaml#" + $ref: ti,k3-am654-cpts.yaml# description: CPSW Common Platform Time Sync (CPTS) module. diff --git a/Documentation/devicetree/bindings/net/toshiba,visconti-dwmac.yaml b/Documentation/devicetree/bindings/net/toshiba,visconti-dwmac.yaml index 474fa8bcf302ca14bb690b82caec7df1f0fa3f63..052f636158b3f16087c83b90ad7132d6712c4c42 100644 --- a/Documentation/devicetree/bindings/net/toshiba,visconti-dwmac.yaml +++ b/Documentation/devicetree/bindings/net/toshiba,visconti-dwmac.yaml @@ -19,7 +19,7 @@ select: - compatible allOf: - - $ref: "snps,dwmac.yaml#" + - $ref: snps,dwmac.yaml# properties: compatible: diff --git a/Documentation/devicetree/bindings/net/wireless/brcm,bcm4329-fmac.yaml b/Documentation/devicetree/bindings/net/wireless/brcm,bcm4329-fmac.yaml index fec1cc9b9a085184cf4200e0489fea0c6bae489e..4aa521f1be8cdd18032be89a9daeba9b40aa1a2c 100644 --- a/Documentation/devicetree/bindings/net/wireless/brcm,bcm4329-fmac.yaml +++ b/Documentation/devicetree/bindings/net/wireless/brcm,bcm4329-fmac.yaml @@ -15,6 +15,9 @@ description: These chips also have a Bluetooth portion described in a separate binding. +allOf: + - $ref: ieee80211.yaml# + properties: compatible: oneOf: @@ -38,6 +41,7 @@ properties: - brcm,bcm4354-fmac - brcm,bcm4356-fmac - brcm,bcm4359-fmac + - brcm,bcm4366-fmac - cypress,cyw4373-fmac - cypress,cyw43012-fmac - const: brcm,bcm4329-fmac @@ -120,7 +124,7 @@ required: - compatible - reg -additionalProperties: false +unevaluatedProperties: false examples: - | diff --git a/Documentation/devicetree/bindings/net/wireless/qcom,ath10k.yaml b/Documentation/devicetree/bindings/net/wireless/qcom,ath10k.yaml index c85ed330426d4ea02a76843bec7e3c27aee441a1..7758a55dd32866355071291c427062f86a30efc8 100644 --- a/Documentation/devicetree/bindings/net/wireless/qcom,ath10k.yaml +++ b/Documentation/devicetree/bindings/net/wireless/qcom,ath10k.yaml @@ -84,6 +84,8 @@ properties: required: - iommus + ieee80211-freq-limit: true + qcom,ath10k-calibration-data: $ref: /schemas/types.yaml#/definitions/uint8-array description: @@ -164,6 +166,7 @@ required: additionalProperties: false allOf: + - $ref: ieee80211.yaml# - if: properties: compatible: @@ -355,4 +358,5 @@ examples: "msi14", "msi15", "legacy"; + ieee80211-freq-limit = <5470000 5875000>; }; diff --git a/Documentation/devicetree/bindings/net/xilinx_axienet.txt b/Documentation/devicetree/bindings/net/xilinx_axienet.txt deleted file mode 100644 index 80e505a2fda162055b6f9cfd6749b5ac855836f1..0000000000000000000000000000000000000000 --- a/Documentation/devicetree/bindings/net/xilinx_axienet.txt +++ /dev/null @@ -1,101 +0,0 @@ -XILINX AXI ETHERNET Device Tree Bindings --------------------------------------------------------- - -Also called AXI 1G/2.5G Ethernet Subsystem, the xilinx axi ethernet IP core -provides connectivity to an external ethernet PHY supporting different -interfaces: MII, GMII, RGMII, SGMII, 1000BaseX. It also includes two -segments of memory for buffering TX and RX, as well as the capability of -offloading TX/RX checksum calculation off the processor. - -Management configuration is done through the AXI interface, while payload is -sent and received through means of an AXI DMA controller. This driver -includes the DMA driver code, so this driver is incompatible with AXI DMA -driver. - -For more details about mdio please refer phy.txt file in the same directory. - -Required properties: -- compatible : Must be one of "xlnx,axi-ethernet-1.00.a", - "xlnx,axi-ethernet-1.01.a", "xlnx,axi-ethernet-2.01.a" -- reg : Address and length of the IO space, as well as the address - and length of the AXI DMA controller IO space, unless - axistream-connected is specified, in which case the reg - attribute of the node referenced by it is used. -- interrupts : Should be a list of 2 or 3 interrupts: TX DMA, RX DMA, - and optionally Ethernet core. If axistream-connected is - specified, the TX/RX DMA interrupts should be on that node - instead, and only the Ethernet core interrupt is optionally - specified here. -- phy-handle : Should point to the external phy device if exists. Pointing - this to the PCS/PMA PHY is deprecated and should be avoided. - See ethernet.txt file in the same directory. -- xlnx,rxmem : Set to allocated memory buffer for Rx/Tx in the hardware - -Optional properties: -- phy-mode : See ethernet.txt -- xlnx,phy-type : Deprecated, do not use, but still accepted in preference - to phy-mode. -- xlnx,txcsum : 0 or empty for disabling TX checksum offload, - 1 to enable partial TX checksum offload, - 2 to enable full TX checksum offload -- xlnx,rxcsum : Same values as xlnx,txcsum but for RX checksum offload -- xlnx,switch-x-sgmii : Boolean to indicate the Ethernet core is configured to - support both 1000BaseX and SGMII modes. If set, the phy-mode - should be set to match the mode selected on core reset (i.e. - by the basex_or_sgmii core input line). -- clock-names: Tuple listing input clock names. Possible clocks: - s_axi_lite_clk: Clock for AXI register slave interface - axis_clk: AXI4-Stream clock for TXD RXD TXC and RXS interfaces - ref_clk: Ethernet reference clock, used by signal delay - primitives and transceivers - mgt_clk: MGT reference clock (used by optional internal - PCS/PMA PHY) - - Note that if s_axi_lite_clk is not specified by name, the - first clock of any name is used for this. If that is also not - specified, the clock rate is auto-detected from the CPU clock - (but only on platforms where this is possible). New device - trees should specify all applicable clocks by name - the - fallbacks to an unnamed clock or to CPU clock are only for - backward compatibility. -- clocks: Phandles to input clocks matching clock-names. Refer to common - clock bindings. -- axistream-connected: Reference to another node which contains the resources - for the AXI DMA controller used by this device. - If this is specified, the DMA-related resources from that - device (DMA registers and DMA TX/RX interrupts) rather - than this one will be used. - - mdio : Child node for MDIO bus. Must be defined if PHY access is - required through the core's MDIO interface (i.e. always, - unless the PHY is accessed through a different bus). - Non-standard MDIO bus frequency is supported via - "clock-frequency", see mdio.yaml. - - - pcs-handle: Phandle to the internal PCS/PMA PHY in SGMII or 1000Base-X - modes, where "pcs-handle" should be used to point - to the PCS/PMA PHY, and "phy-handle" should point to an - external PHY if exists. - -Example: - axi_ethernet_eth: ethernet@40c00000 { - compatible = "xlnx,axi-ethernet-1.00.a"; - device_type = "network"; - interrupt-parent = <µblaze_0_axi_intc>; - interrupts = <2 0 1>; - clock-names = "s_axi_lite_clk", "axis_clk", "ref_clk", "mgt_clk"; - clocks = <&axi_clk>, <&axi_clk>, <&pl_enet_ref_clk>, <&mgt_clk>; - phy-mode = "mii"; - reg = <0x40c00000 0x40000 0x50c00000 0x40000>; - xlnx,rxcsum = <0x2>; - xlnx,rxmem = <0x800>; - xlnx,txcsum = <0x2>; - phy-handle = <&phy0>; - axi_ethernetlite_0_mdio: mdio { - #address-cells = <1>; - #size-cells = <0>; - phy0: phy@0 { - device_type = "ethernet-phy"; - reg = <1>; - }; - }; - }; diff --git a/Documentation/devicetree/bindings/net/xlnx,axi-ethernet.yaml b/Documentation/devicetree/bindings/net/xlnx,axi-ethernet.yaml new file mode 100644 index 0000000000000000000000000000000000000000..1d33d80af11c3c8d2fb1d7f9fc04b630d2a047bb --- /dev/null +++ b/Documentation/devicetree/bindings/net/xlnx,axi-ethernet.yaml @@ -0,0 +1,183 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/net/xlnx,axi-ethernet.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: AXI 1G/2.5G Ethernet Subsystem + +description: | + Also called AXI 1G/2.5G Ethernet Subsystem, the xilinx axi ethernet IP core + provides connectivity to an external ethernet PHY supporting different + interfaces: MII, GMII, RGMII, SGMII, 1000BaseX. It also includes two + segments of memory for buffering TX and RX, as well as the capability of + offloading TX/RX checksum calculation off the processor. + + Management configuration is done through the AXI interface, while payload is + sent and received through means of an AXI DMA controller. This driver + includes the DMA driver code, so this driver is incompatible with AXI DMA + driver. + +maintainers: + - Radhey Shyam Pandey + +properties: + compatible: + enum: + - xlnx,axi-ethernet-1.00.a + - xlnx,axi-ethernet-1.01.a + - xlnx,axi-ethernet-2.01.a + + reg: + description: + Address and length of the IO space, as well as the address + and length of the AXI DMA controller IO space, unless + axistream-connected is specified, in which case the reg + attribute of the node referenced by it is used. + maxItems: 2 + + interrupts: + items: + - description: Ethernet core interrupt + - description: Tx DMA interrupt + - description: Rx DMA interrupt + description: + Ethernet core interrupt is optional. If axistream-connected property is + present DMA node should contains TX/RX DMA interrupts else DMA interrupt + resources are mentioned on ethernet node. + minItems: 1 + + phy-handle: true + + xlnx,rxmem: + description: + Set to allocated memory buffer for Rx/Tx in the hardware. + $ref: /schemas/types.yaml#/definitions/uint32 + + phy-mode: + enum: + - mii + - gmii + - rgmii + - sgmii + - 1000BaseX + + xlnx,phy-type: + description: + Do not use, but still accepted in preference to phy-mode. + deprecated: true + $ref: /schemas/types.yaml#/definitions/uint32 + + xlnx,txcsum: + description: + TX checksum offload. 0 or empty for disabling TX checksum offload, + 1 to enable partial TX checksum offload and 2 to enable full TX + checksum offload. + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [0, 1, 2] + + xlnx,rxcsum: + description: + RX checksum offload. 0 or empty for disabling RX checksum offload, + 1 to enable partial RX checksum offload and 2 to enable full RX + checksum offload. + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [0, 1, 2] + + xlnx,switch-x-sgmii: + type: boolean + description: + Indicate the Ethernet core is configured to support both 1000BaseX and + SGMII modes. If set, the phy-mode should be set to match the mode + selected on core reset (i.e. by the basex_or_sgmii core input line). + + clocks: + items: + - description: Clock for AXI register slave interface. + - description: AXI4-Stream clock for TXD RXD TXC and RXS interfaces. + - description: Ethernet reference clock, used by signal delay primitives + and transceivers. + - description: MGT reference clock (used by optional internal PCS/PMA PHY) + + clock-names: + items: + - const: s_axi_lite_clk + - const: axis_clk + - const: ref_clk + - const: mgt_clk + + axistream-connected: + $ref: /schemas/types.yaml#/definitions/phandle + description: Phandle of AXI DMA controller which contains the resources + used by this device. If this is specified, the DMA-related resources + from that device (DMA registers and DMA TX/RX interrupts) rather than + this one will be used. + + mdio: + type: object + + pcs-handle: + description: Phandle to the internal PCS/PMA PHY in SGMII or 1000Base-X + modes, where "pcs-handle" should be used to point to the PCS/PMA PHY, + and "phy-handle" should point to an external PHY if exists. + maxItems: 1 + +required: + - compatible + - interrupts + - reg + - xlnx,rxmem + - phy-handle + +allOf: + - $ref: /schemas/net/ethernet-controller.yaml# + +additionalProperties: false + +examples: + - | + axi_ethernet_eth: ethernet@40c00000 { + compatible = "xlnx,axi-ethernet-1.00.a"; + interrupts = <2 0 1>; + clock-names = "s_axi_lite_clk", "axis_clk", "ref_clk", "mgt_clk"; + clocks = <&axi_clk>, <&axi_clk>, <&pl_enet_ref_clk>, <&mgt_clk>; + phy-mode = "mii"; + reg = <0x40c00000 0x40000>,<0x50c00000 0x40000>; + xlnx,rxcsum = <0x2>; + xlnx,rxmem = <0x800>; + xlnx,txcsum = <0x2>; + phy-handle = <&phy0>; + + mdio { + #address-cells = <1>; + #size-cells = <0>; + phy0: ethernet-phy@1 { + device_type = "ethernet-phy"; + reg = <1>; + }; + }; + }; + + - | + axi_ethernet_eth1: ethernet@40000000 { + compatible = "xlnx,axi-ethernet-1.00.a"; + interrupts = <0>; + clock-names = "s_axi_lite_clk", "axis_clk", "ref_clk", "mgt_clk"; + clocks = <&axi_clk>, <&axi_clk>, <&pl_enet_ref_clk>, <&mgt_clk>; + phy-mode = "mii"; + reg = <0x00 0x40000000 0x00 0x40000>; + xlnx,rxcsum = <0x2>; + xlnx,rxmem = <0x800>; + xlnx,txcsum = <0x2>; + phy-handle = <&phy1>; + axistream-connected = <&dma>; + + mdio { + #address-cells = <1>; + #size-cells = <0>; + phy1: ethernet-phy@1 { + device_type = "ethernet-phy"; + reg = <1>; + }; + }; + }; diff --git a/Documentation/devicetree/bindings/nvmem/brcm,nvram.yaml b/Documentation/devicetree/bindings/nvmem/brcm,nvram.yaml index 36def7128fca8c2e65c3c323b1a09f663376d6f6..13412af7f046640926f7b3d93716beec102af14a 100644 --- a/Documentation/devicetree/bindings/nvmem/brcm,nvram.yaml +++ b/Documentation/devicetree/bindings/nvmem/brcm,nvram.yaml @@ -36,14 +36,29 @@ properties: et0macaddr: type: object description: First Ethernet interface's MAC address + properties: + "#nvmem-cell-cells": + description: The first argument is a MAC address offset. + const: 1 + additionalProperties: false et1macaddr: type: object description: Second Ethernet interface's MAC address + properties: + "#nvmem-cell-cells": + description: The first argument is a MAC address offset. + const: 1 + additionalProperties: false et2macaddr: type: object description: Third Ethernet interface's MAC address + properties: + "#nvmem-cell-cells": + description: The first argument is a MAC address offset. + const: 1 + additionalProperties: false unevaluatedProperties: false diff --git a/Documentation/devicetree/bindings/nvmem/imx-ocotp.yaml b/Documentation/devicetree/bindings/nvmem/imx-ocotp.yaml index 9876243ff1e85fa403579a61b8838c9f76a7d7c2..99e60d713dace749407ddd4fbb9a85e4c759ee1f 100644 --- a/Documentation/devicetree/bindings/nvmem/imx-ocotp.yaml +++ b/Documentation/devicetree/bindings/nvmem/imx-ocotp.yaml @@ -4,7 +4,7 @@ $id: http://devicetree.org/schemas/nvmem/imx-ocotp.yaml# $schema: http://devicetree.org/meta-schemas/core.yaml# -title: Freescale i.MX6 On-Chip OTP Controller (OCOTP) +title: Freescale i.MX On-Chip OTP Controller (OCOTP) maintainers: - Anson Huang @@ -12,7 +12,7 @@ maintainers: description: | This binding represents the on-chip eFuse OTP controller found on i.MX6Q/D, i.MX6DL/S, i.MX6SL, i.MX6SX, i.MX6UL, i.MX6ULL/ULZ, i.MX6SLL, - i.MX7D/S, i.MX7ULP, i.MX8MQ, i.MX8MM, i.MX8MN and i.MX8MP SoCs. + i.MX7D/S, i.MX7ULP, i.MX8MQ, i.MX8MM, i.MX8MN i.MX8MP and i.MX93 SoCs. allOf: - $ref: nvmem.yaml# @@ -32,6 +32,7 @@ properties: - fsl,imx7ulp-ocotp - fsl,imx8mq-ocotp - fsl,imx8mm-ocotp + - fsl,imx93-ocotp - const: syscon - items: - enum: @@ -46,12 +47,6 @@ properties: reg: maxItems: 1 - "#address-cells": - const: 1 - - "#size-cells": - const: 1 - clocks: maxItems: 1 @@ -61,21 +56,6 @@ required: - compatible - reg -patternProperties: - "^.*@[0-9a-f]+$": - type: object - - properties: - reg: - maxItems: 1 - description: - Offset and size in bytes within the storage device. - - required: - - reg - - additionalProperties: false - unevaluatedProperties: false examples: diff --git a/Documentation/devicetree/bindings/nvmem/layouts/fixed-cell.yaml b/Documentation/devicetree/bindings/nvmem/layouts/fixed-cell.yaml new file mode 100644 index 0000000000000000000000000000000000000000..e698098450e1127b6111b275aa5d23b071120cab --- /dev/null +++ b/Documentation/devicetree/bindings/nvmem/layouts/fixed-cell.yaml @@ -0,0 +1,31 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/nvmem/layouts/fixed-cell.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Fixed offset & size NVMEM cell + +maintainers: + - Rafał Miłecki + - Srinivas Kandagatla + +properties: + reg: + maxItems: 1 + + bits: + $ref: /schemas/types.yaml#/definitions/uint32-array + items: + - minimum: 0 + maximum: 7 + description: + Offset in bit within the address range specified by reg. + - minimum: 1 + description: + Size in bit within the address range specified by reg. + +required: + - reg + +additionalProperties: true diff --git a/Documentation/devicetree/bindings/nvmem/layouts/fixed-layout.yaml b/Documentation/devicetree/bindings/nvmem/layouts/fixed-layout.yaml new file mode 100644 index 0000000000000000000000000000000000000000..c271537d0714faadfc6550c4183597247aa8b928 --- /dev/null +++ b/Documentation/devicetree/bindings/nvmem/layouts/fixed-layout.yaml @@ -0,0 +1,50 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/nvmem/layouts/fixed-layout.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: NVMEM layout for fixed NVMEM cells + +description: + Many NVMEM devices have hardcoded cells layout (offset and size of defined + NVMEM content doesn't change). + + This binding allows defining such NVMEM layout with its cells. It can be used + on top of any NVMEM device. + +maintainers: + - Rafał Miłecki + +properties: + compatible: + const: fixed-layout + + "#address-cells": + const: 1 + + "#size-cells": + const: 1 + +patternProperties: + "@[a-f0-9]+$": + type: object + $ref: fixed-cell.yaml + unevaluatedProperties: false + +required: + - compatible + +additionalProperties: false + +examples: + - | + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + calibration@4000 { + reg = <0x4000 0x100>; + }; + }; diff --git a/Documentation/devicetree/bindings/nvmem/layouts/nvmem-layout.yaml b/Documentation/devicetree/bindings/nvmem/layouts/nvmem-layout.yaml index 8512ee538c4c1602f9ff1e094b97ea9b08c817b8..3b40f7880774694aec189213a932f8606ab81f0d 100644 --- a/Documentation/devicetree/bindings/nvmem/layouts/nvmem-layout.yaml +++ b/Documentation/devicetree/bindings/nvmem/layouts/nvmem-layout.yaml @@ -18,16 +18,13 @@ description: | perform their parsing. The nvmem-layout container is here to describe these. oneOf: + - $ref: fixed-layout.yaml - $ref: kontron,sl28-vpd.yaml - $ref: onie,tlv-layout.yaml properties: compatible: true - '#address-cells': false - - '#size-cells': false - required: - compatible diff --git a/Documentation/devicetree/bindings/nvmem/mediatek,efuse.yaml b/Documentation/devicetree/bindings/nvmem/mediatek,efuse.yaml index d16d42fb98b6a64cb76253355999e90d0f082854..7ec2988b597e8d9b2a73114476b8f20c721c014c 100644 --- a/Documentation/devicetree/bindings/nvmem/mediatek,efuse.yaml +++ b/Documentation/devicetree/bindings/nvmem/mediatek,efuse.yaml @@ -27,6 +27,7 @@ properties: - enum: - mediatek,mt7622-efuse - mediatek,mt7623-efuse + - mediatek,mt7986-efuse - mediatek,mt8173-efuse - mediatek,mt8183-efuse - mediatek,mt8186-efuse diff --git a/Documentation/devicetree/bindings/nvmem/mxs-ocotp.yaml b/Documentation/devicetree/bindings/nvmem/mxs-ocotp.yaml index 8938eec22b52d2436354d3857c2b91dc89943c3c..a9b822aeaa7edb2737c0ca68358cb8cf3daaa578 100644 --- a/Documentation/devicetree/bindings/nvmem/mxs-ocotp.yaml +++ b/Documentation/devicetree/bindings/nvmem/mxs-ocotp.yaml @@ -18,12 +18,6 @@ properties: - fsl,imx23-ocotp - fsl,imx28-ocotp - "#address-cells": - const: 1 - - "#size-cells": - const: 1 - reg: maxItems: 1 @@ -35,7 +29,7 @@ required: - reg - clocks -additionalProperties: false +unevaluatedProperties: false examples: - | diff --git a/Documentation/devicetree/bindings/nvmem/nvmem.yaml b/Documentation/devicetree/bindings/nvmem/nvmem.yaml index 75bb93dda9df1ddf81a2e1dd45cec57440e3fd53..9802441006906638acffa30f527606859aba82bd 100644 --- a/Documentation/devicetree/bindings/nvmem/nvmem.yaml +++ b/Documentation/devicetree/bindings/nvmem/nvmem.yaml @@ -49,23 +49,8 @@ properties: patternProperties: "@[0-9a-f]+(,[0-7])?$": type: object - - properties: - reg: - maxItems: 1 - description: - Offset and size in bytes within the storage device. - - bits: - $ref: /schemas/types.yaml#/definitions/uint32-array - items: - - minimum: 0 - maximum: 7 - description: - Offset in bit within the address range specified by reg. - - minimum: 1 - description: - Size in bit within the address range specified by reg. + $ref: layouts/fixed-cell.yaml + deprecated: true additionalProperties: true @@ -83,24 +68,30 @@ examples: /* ... */ - /* Data cells */ - tsens_calibration: calib@404 { - reg = <0x404 0x10>; - }; - - tsens_calibration_bckp: calib_bckp@504 { - reg = <0x504 0x11>; - bits = <6 128>; - }; - - pvs_version: pvs-version@6 { - reg = <0x6 0x2>; - bits = <7 2>; - }; - - speed_bin: speed-bin@c{ - reg = <0xc 0x1>; - bits = <2 3>; + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + /* Data cells */ + tsens_calibration: calib@404 { + reg = <0x404 0x10>; + }; + + tsens_calibration_bckp: calib_bckp@504 { + reg = <0x504 0x11>; + bits = <6 128>; + }; + + pvs_version: pvs-version@6 { + reg = <0x6 0x2>; + bits = <7 2>; + }; + + speed_bin: speed-bin@c{ + reg = <0xc 0x1>; + bits = <2 3>; + }; }; }; diff --git a/Documentation/devicetree/bindings/nvmem/qcom,qfprom.yaml b/Documentation/devicetree/bindings/nvmem/qcom,qfprom.yaml index 8d8503dd934b821cec4fa50b8a0e67d68b6ac7f7..6cd4682a167ddc41eed39c6318484d23b483b027 100644 --- a/Documentation/devicetree/bindings/nvmem/qcom,qfprom.yaml +++ b/Documentation/devicetree/bindings/nvmem/qcom,qfprom.yaml @@ -18,8 +18,11 @@ properties: - enum: - qcom,apq8064-qfprom - qcom,apq8084-qfprom + - qcom,ipq5332-qfprom + - qcom,ipq6018-qfprom - qcom,ipq8064-qfprom - qcom,ipq8074-qfprom + - qcom,ipq9574-qfprom - qcom,msm8916-qfprom - qcom,msm8974-qfprom - qcom,msm8976-qfprom @@ -64,12 +67,6 @@ properties: power-domains: maxItems: 1 - # Needed if any child nodes are present. - "#address-cells": - const: 1 - "#size-cells": - const: 1 - required: - compatible - reg diff --git a/Documentation/devicetree/bindings/nvmem/qcom,spmi-sdam.yaml b/Documentation/devicetree/bindings/nvmem/qcom,spmi-sdam.yaml index dce0c7d84ce76b9c21d76fd1ff0149fbea842025..cd980def97b8c36b15a1c45ebfe4c49b99eaea02 100644 --- a/Documentation/devicetree/bindings/nvmem/qcom,spmi-sdam.yaml +++ b/Documentation/devicetree/bindings/nvmem/qcom,spmi-sdam.yaml @@ -25,12 +25,6 @@ properties: reg: maxItems: 1 - "#address-cells": - const: 1 - - "#size-cells": - const: 1 - ranges: true required: diff --git a/Documentation/devicetree/bindings/nvmem/rmem.yaml b/Documentation/devicetree/bindings/nvmem/rmem.yaml index 38a39c9b8c1cecdba5eb807e6d6a330a6203c29c..1ec0d09bcafa857c05ae722834c9e13bf63ee851 100644 --- a/Documentation/devicetree/bindings/nvmem/rmem.yaml +++ b/Documentation/devicetree/bindings/nvmem/rmem.yaml @@ -17,6 +17,7 @@ properties: items: - enum: - raspberrypi,bootloader-config + - raspberrypi,bootloader-public-key - const: nvmem-rmem reg: diff --git a/Documentation/devicetree/bindings/nvmem/rockchip,otp.yaml b/Documentation/devicetree/bindings/nvmem/rockchip,otp.yaml new file mode 100644 index 0000000000000000000000000000000000000000..9c6eff7889282be7ad0f872cc650356379e57b3d --- /dev/null +++ b/Documentation/devicetree/bindings/nvmem/rockchip,otp.yaml @@ -0,0 +1,122 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/nvmem/rockchip,otp.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Rockchip internal OTP (One Time Programmable) memory + +maintainers: + - Heiko Stuebner + +properties: + compatible: + enum: + - rockchip,px30-otp + - rockchip,rk3308-otp + - rockchip,rk3588-otp + + reg: + maxItems: 1 + + clocks: + minItems: 3 + maxItems: 4 + + clock-names: + minItems: 3 + items: + - const: otp + - const: apb_pclk + - const: phy + - const: arb + + resets: + minItems: 1 + maxItems: 3 + + reset-names: + minItems: 1 + maxItems: 3 + +required: + - compatible + - reg + - clocks + - clock-names + - resets + - reset-names + +allOf: + - $ref: nvmem.yaml# + + - if: + properties: + compatible: + contains: + enum: + - rockchip,px30-otp + - rockchip,rk3308-otp + then: + properties: + clocks: + maxItems: 3 + resets: + maxItems: 1 + reset-names: + items: + - const: phy + + - if: + properties: + compatible: + contains: + enum: + - rockchip,rk3588-otp + then: + properties: + clocks: + minItems: 4 + resets: + minItems: 3 + reset-names: + items: + - const: otp + - const: apb + - const: arb + +unevaluatedProperties: false + +examples: + - | + #include + + soc { + #address-cells = <2>; + #size-cells = <2>; + + otp: efuse@ff290000 { + compatible = "rockchip,px30-otp"; + reg = <0x0 0xff290000 0x0 0x4000>; + clocks = <&cru SCLK_OTP_USR>, <&cru PCLK_OTP_NS>, + <&cru PCLK_OTP_PHY>; + clock-names = "otp", "apb_pclk", "phy"; + resets = <&cru SRST_OTP_PHY>; + reset-names = "phy"; + #address-cells = <1>; + #size-cells = <1>; + + cpu_id: id@7 { + reg = <0x07 0x10>; + }; + + cpu_leakage: cpu-leakage@17 { + reg = <0x17 0x1>; + }; + + performance: performance@1e { + reg = <0x1e 0x1>; + bits = <4 3>; + }; + }; + }; diff --git a/Documentation/devicetree/bindings/nvmem/rockchip-otp.txt b/Documentation/devicetree/bindings/nvmem/rockchip-otp.txt deleted file mode 100644 index 40f649f7c2e5ea40e54123e715233693c4c18121..0000000000000000000000000000000000000000 --- a/Documentation/devicetree/bindings/nvmem/rockchip-otp.txt +++ /dev/null @@ -1,25 +0,0 @@ -Rockchip internal OTP (One Time Programmable) memory device tree bindings - -Required properties: -- compatible: Should be one of the following. - - "rockchip,px30-otp" - for PX30 SoCs. - - "rockchip,rk3308-otp" - for RK3308 SoCs. -- reg: Should contain the registers location and size -- clocks: Must contain an entry for each entry in clock-names. -- clock-names: Should be "otp", "apb_pclk" and "phy". -- resets: Must contain an entry for each entry in reset-names. - See ../../reset/reset.txt for details. -- reset-names: Should be "phy". - -See nvmem.txt for more information. - -Example: - otp: otp@ff290000 { - compatible = "rockchip,px30-otp"; - reg = <0x0 0xff290000 0x0 0x4000>; - #address-cells = <1>; - #size-cells = <1>; - clocks = <&cru SCLK_OTP_USR>, <&cru PCLK_OTP_NS>, - <&cru PCLK_OTP_PHY>; - clock-names = "otp", "apb_pclk", "phy"; - }; diff --git a/Documentation/devicetree/bindings/nvmem/socionext,uniphier-efuse.yaml b/Documentation/devicetree/bindings/nvmem/socionext,uniphier-efuse.yaml index b8bca0599c452c813a3786d4aba953497c0a0075..efccc5aacbe0cd605c9efb8eac48588a95ba9670 100644 --- a/Documentation/devicetree/bindings/nvmem/socionext,uniphier-efuse.yaml +++ b/Documentation/devicetree/bindings/nvmem/socionext,uniphier-efuse.yaml @@ -14,9 +14,6 @@ allOf: - $ref: nvmem.yaml# properties: - "#address-cells": true - "#size-cells": true - compatible: const: socionext,uniphier-efuse diff --git a/Documentation/devicetree/bindings/nvmem/sunplus,sp7021-ocotp.yaml b/Documentation/devicetree/bindings/nvmem/sunplus,sp7021-ocotp.yaml index 8877c2283e9ea3730675373b3e08a613d2661417..da3f1de7d281740b9e2a02f2e1e68645e1208114 100644 --- a/Documentation/devicetree/bindings/nvmem/sunplus,sp7021-ocotp.yaml +++ b/Documentation/devicetree/bindings/nvmem/sunplus,sp7021-ocotp.yaml @@ -28,12 +28,6 @@ properties: clocks: maxItems: 1 - "#address-cells": - const: 1 - - "#size-cells": - const: 1 - thermal-calibration: type: object description: thermal calibration values diff --git a/Documentation/devicetree/bindings/pci/qcom,pcie-ep.yaml b/Documentation/devicetree/bindings/pci/qcom,pcie-ep.yaml index b3c22ebd156c0bac9c1f945406c9bf5959b532c9..811112255d7d28ffa4a895f065479dc440b5cc99 100644 --- a/Documentation/devicetree/bindings/pci/qcom,pcie-ep.yaml +++ b/Documentation/devicetree/bindings/pci/qcom,pcie-ep.yaml @@ -13,6 +13,7 @@ properties: compatible: enum: - qcom,sdx55-pcie-ep + - qcom,sdx65-pcie-ep - qcom,sm8450-pcie-ep reg: @@ -109,6 +110,7 @@ allOf: contains: enum: - qcom,sdx55-pcie-ep + - qcom,sdx65-pcie-ep then: properties: clocks: diff --git a/Documentation/devicetree/bindings/pci/rockchip,rk3399-pcie-ep.yaml b/Documentation/devicetree/bindings/pci/rockchip,rk3399-pcie-ep.yaml index 88386a6d70119e9702d55e58db71b9c0206ac0da..6b62f6f58efecf63d8ffa55dc1a3b2bf8a372af4 100644 --- a/Documentation/devicetree/bindings/pci/rockchip,rk3399-pcie-ep.yaml +++ b/Documentation/devicetree/bindings/pci/rockchip,rk3399-pcie-ep.yaml @@ -47,7 +47,7 @@ examples: pcie-ep@f8000000 { compatible = "rockchip,rk3399-pcie-ep"; - reg = <0x0 0xfd000000 0x0 0x1000000>, <0x0 0x80000000 0x0 0x20000>; + reg = <0x0 0xfd000000 0x0 0x1000000>, <0x0 0xfa000000 0x0 0x2000000>; reg-names = "apb-base", "mem-base"; clocks = <&cru ACLK_PCIE>, <&cru ACLK_PERF_PCIE>, <&cru PCLK_PCIE>, <&cru SCLK_PCIE_PM>; @@ -63,6 +63,8 @@ examples: phys = <&pcie_phy 0>, <&pcie_phy 1>, <&pcie_phy 2>, <&pcie_phy 3>; phy-names = "pcie-phy-0", "pcie-phy-1", "pcie-phy-2", "pcie-phy-3"; rockchip,max-outbound-regions = <16>; + pinctrl-names = "default"; + pinctrl-0 = <&pcie_clkreqnb_cpm>; }; }; ... diff --git a/Documentation/devicetree/bindings/pci/rockchip-dw-pcie.yaml b/Documentation/devicetree/bindings/pci/rockchip-dw-pcie.yaml index 24c88942e59e0a1a30fc296d121c04e00057ab5b..a4f61ced5e885db103bd0f974d2df58cbef9ca6b 100644 --- a/Documentation/devicetree/bindings/pci/rockchip-dw-pcie.yaml +++ b/Documentation/devicetree/bindings/pci/rockchip-dw-pcie.yaml @@ -41,20 +41,24 @@ properties: - const: config clocks: + minItems: 5 items: - description: AHB clock for PCIe master - description: AHB clock for PCIe slave - description: AHB clock for PCIe dbi - description: APB clock for PCIe - description: Auxiliary clock for PCIe + - description: PIPE clock clock-names: + minItems: 5 items: - const: aclk_mst - const: aclk_slv - const: aclk_dbi - const: pclk - const: aux + - const: pipe msi-map: true @@ -70,13 +74,19 @@ properties: maxItems: 1 ranges: - maxItems: 2 + minItems: 2 + maxItems: 3 resets: - maxItems: 1 + minItems: 1 + maxItems: 2 reset-names: - const: pipe + oneOf: + - const: pipe + - items: + - const: pwr + - const: pipe vpcie3v3-supply: true diff --git a/Documentation/devicetree/bindings/pci/xilinx-versal-cpm.yaml b/Documentation/devicetree/bindings/pci/xilinx-versal-cpm.yaml index 24ddc2855b94620a462725d582461010afcc8a5b..4734be456bde6c6c4b2c567e0ac6ccc7d518e6cc 100644 --- a/Documentation/devicetree/bindings/pci/xilinx-versal-cpm.yaml +++ b/Documentation/devicetree/bindings/pci/xilinx-versal-cpm.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: CPM Host Controller device tree for Xilinx Versal SoCs maintainers: - - Bharat Kumar Gogada + - Bharat Kumar Gogada allOf: - $ref: /schemas/pci/pci-bus.yaml# diff --git a/Documentation/devicetree/bindings/perf/amlogic,g12-ddr-pmu.yaml b/Documentation/devicetree/bindings/perf/amlogic,g12-ddr-pmu.yaml index 50f46a6898b1ea8abc442fbcb6dd10f31a714ccc..4adab01491082cd379f177009f3bde945f2c8750 100644 --- a/Documentation/devicetree/bindings/perf/amlogic,g12-ddr-pmu.yaml +++ b/Documentation/devicetree/bindings/perf/amlogic,g12-ddr-pmu.yaml @@ -42,8 +42,8 @@ examples: - | #include pmu { - #address-cells=<2>; - #size-cells=<2>; + #address-cells = <2>; + #size-cells = <2>; pmu@ff638000 { compatible = "amlogic,g12a-ddr-pmu"; diff --git a/Documentation/devicetree/bindings/perf/fsl-imx-ddr.yaml b/Documentation/devicetree/bindings/perf/fsl-imx-ddr.yaml index 80a92385367ee82f3adc6a0cb942edda4f1f2c2d..e9fad4b3de68405198e8a3c32b4334ea57b135dc 100644 --- a/Documentation/devicetree/bindings/perf/fsl-imx-ddr.yaml +++ b/Documentation/devicetree/bindings/perf/fsl-imx-ddr.yaml @@ -4,7 +4,7 @@ $id: http://devicetree.org/schemas/perf/fsl-imx-ddr.yaml# $schema: http://devicetree.org/meta-schemas/core.yaml# -title: Freescale(NXP) IMX8 DDR performance monitor +title: Freescale(NXP) IMX8/9 DDR performance monitor maintainers: - Frank Li @@ -19,6 +19,7 @@ properties: - fsl,imx8mm-ddr-pmu - fsl,imx8mn-ddr-pmu - fsl,imx8mp-ddr-pmu + - fsl,imx93-ddr-pmu - items: - enum: - fsl,imx8mm-ddr-pmu diff --git a/Documentation/devicetree/bindings/phy/brcm,brcmstb-usb-phy.yaml b/Documentation/devicetree/bindings/phy/brcm,brcmstb-usb-phy.yaml index 43a4b880534c8d60d18e6a058222ba4943c37f93..580fbe37b37fa630e734d8257671eb3aff8ff064 100644 --- a/Documentation/devicetree/bindings/phy/brcm,brcmstb-usb-phy.yaml +++ b/Documentation/devicetree/bindings/phy/brcm,brcmstb-usb-phy.yaml @@ -115,8 +115,8 @@ allOf: compatible: contains: enum: - - const: brcm,bcm4908-usb-phy - - const: brcm,brcmstb-usb-phy + - brcm,bcm4908-usb-phy + - brcm,brcmstb-usb-phy then: properties: reg: diff --git a/Documentation/devicetree/bindings/phy/brcm,kona-usb2-phy.txt b/Documentation/devicetree/bindings/phy/brcm,kona-usb2-phy.txt deleted file mode 100644 index 3dc8b3d2ffbbeed6e6afeba5d3ee04c803efbaab..0000000000000000000000000000000000000000 --- a/Documentation/devicetree/bindings/phy/brcm,kona-usb2-phy.txt +++ /dev/null @@ -1,15 +0,0 @@ -BROADCOM KONA USB2 PHY - -Required properties: - - compatible: brcm,kona-usb2-phy - - reg: offset and length of the PHY registers - - #phy-cells: must be 0 -Refer to phy/phy-bindings.txt for the generic PHY binding properties - -Example: - - usbphy: usb-phy@3f130000 { - compatible = "brcm,kona-usb2-phy"; - reg = <0x3f130000 0x28>; - #phy-cells = <0>; - }; diff --git a/Documentation/devicetree/bindings/phy/brcm,kona-usb2-phy.yaml b/Documentation/devicetree/bindings/phy/brcm,kona-usb2-phy.yaml new file mode 100644 index 0000000000000000000000000000000000000000..d7faeb81f7a76cd28f1702bf65bfbc666ec00692 --- /dev/null +++ b/Documentation/devicetree/bindings/phy/brcm,kona-usb2-phy.yaml @@ -0,0 +1,36 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/phy/brcm,kona-usb2-phy.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Broadcom Kona family USB 2.0 PHY + +maintainers: + - Florian Fainelli + +properties: + compatible: + const: brcm,kona-usb2-phy + + reg: + maxItems: 1 + + '#phy-cells': + const: 0 + +required: + - compatible + - reg + - '#phy-cells' + +additionalProperties: false + +examples: + - | + usb-phy@3f130000 { + compatible = "brcm,kona-usb2-phy"; + reg = <0x3f130000 0x28>; + #phy-cells = <0>; + }; +... diff --git a/Documentation/devicetree/bindings/phy/cdns,salvo-phy.yaml b/Documentation/devicetree/bindings/phy/cdns,salvo-phy.yaml index c9e65a2facd55c97d20354ebe4a879d4f4c18bd2..c7281a7c824454d0053bf91a4bd9f5c1b46df78f 100644 --- a/Documentation/devicetree/bindings/phy/cdns,salvo-phy.yaml +++ b/Documentation/devicetree/bindings/phy/cdns,salvo-phy.yaml @@ -31,6 +31,12 @@ properties: "#phy-cells": const: 0 + cdns,usb2-disconnect-threshold-microvolt: + description: The microvolt threshold value utilized for detecting + USB disconnection event. + enum: [575, 610, 645] + default: 575 + required: - compatible - reg diff --git a/Documentation/devicetree/bindings/phy/fsl,imx8mq-usb-phy.yaml b/Documentation/devicetree/bindings/phy/fsl,imx8mq-usb-phy.yaml index e6f9f5540cc3f9143ee9ce4d4b28ac8f60b32aef..dc3a3f709feaa693a05dc69fa718facada78461b 100644 --- a/Documentation/devicetree/bindings/phy/fsl,imx8mq-usb-phy.yaml +++ b/Documentation/devicetree/bindings/phy/fsl,imx8mq-usb-phy.yaml @@ -35,6 +35,53 @@ properties: description: A phandle to the regulator for USB VBUS. + fsl,phy-tx-vref-tune-percent: + description: + Tunes the HS DC level relative to the nominal level + minimum: 94 + maximum: 124 + + fsl,phy-tx-rise-tune-percent: + description: + Adjusts the rise/fall time duration of the HS waveform relative to + its nominal value + minimum: 97 + maximum: 103 + + fsl,phy-tx-preemp-amp-tune-microamp: + description: + Adjust amount of current sourced to DPn and DMn after a J-to-K + or K-to-J transition. Default is 0 (disabled). + minimum: 0 + maximum: 1800 + + fsl,phy-tx-vboost-level-microvolt: + description: + Adjust the boosted transmit launch pk-pk differential amplitude + minimum: 880 + maximum: 1120 + + fsl,phy-comp-dis-tune-percent: + description: + Adjust the voltage level used to detect a disconnect event at the host + relative to the nominal value + minimum: 91 + maximum: 115 + + fsl,phy-pcs-tx-deemph-3p5db-attenuation-db: + description: + Adjust TX de-emphasis attenuation in dB at nominal + 3.5dB point as per USB specification + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0 + maximum: 36 + + fsl,phy-pcs-tx-swing-full-percent: + description: + Scaling of the voltage defined by fsl,phy-tx-vboost-level-microvolt + minimum: 0 + maximum: 100 + required: - compatible - reg diff --git a/Documentation/devicetree/bindings/phy/fsl,mxs-usbphy.yaml b/Documentation/devicetree/bindings/phy/fsl,mxs-usbphy.yaml new file mode 100644 index 0000000000000000000000000000000000000000..f4b1ca2fb56253f221e41ea54a576836aae58dae --- /dev/null +++ b/Documentation/devicetree/bindings/phy/fsl,mxs-usbphy.yaml @@ -0,0 +1,128 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/phy/fsl,mxs-usbphy.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Freescale MXS USB Phy Device + +maintainers: + - Xu Yang + +properties: + compatible: + oneOf: + - enum: + - fsl,imx23-usbphy + - fsl,imx7ulp-usbphy + - fsl,vf610-usbphy + - items: + - enum: + - fsl,imx28-usbphy + - fsl,imx6ul-usbphy + - fsl,imx6sl-usbphy + - fsl,imx6sx-usbphy + - fsl,imx6q-usbphy + - const: fsl,imx23-usbphy + - items: + - const: fsl,imx6sll-usbphy + - const: fsl,imx6ul-usbphy + - const: fsl,imx23-usbphy + - items: + - enum: + - fsl,imx8dxl-usbphy + - fsl,imx8qm-usbphy + - fsl,imx8ulp-usbphy + - const: fsl,imx7ulp-usbphy + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + clocks: + maxItems: 1 + + '#phy-cells': + const: 0 + + power-domains: + maxItems: 1 + + fsl,anatop: + description: + phandle for anatop register, it is only for imx6 SoC series. + $ref: /schemas/types.yaml#/definitions/phandle + + phy-3p0-supply: + description: + One of USB PHY's power supply. Can be used to keep a good signal + quality. + + fsl,tx-cal-45-dn-ohms: + description: + Resistance (in ohms) of switchable high-speed trimming resistor + connected in parallel with the 45 ohm resistor that terminates + the DN output signal. + minimum: 35 + maximum: 54 + default: 45 + + fsl,tx-cal-45-dp-ohms: + description: + Resistance (in ohms) of switchable high-speed trimming resistor + connected in parallel with the 45 ohm resistor that terminates + the DP output signal. + minimum: 35 + maximum: 54 + default: 45 + + fsl,tx-d-cal: + description: + Current trimming value (as a percentage) of the 17.78 mA TX + reference current. + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 79 + maximum: 119 + default: 100 + +required: + - compatible + - reg + - clocks + +allOf: + - if: + properties: + compatible: + oneOf: + - enum: + - fsl,imx6q-usbphy + - fsl,imx6sl-usbphy + - fsl,imx6sx-usbphy + - fsl,imx6sll-usbphy + - fsl,vf610-usbphy + - items: + - const: fsl,imx6ul-usbphy + - const: fsl,imx23-usbphy + then: + required: + - fsl,anatop + +additionalProperties: false + +examples: + - | + #include + #include + + usbphy1: usb-phy@20c9000 { + compatible = "fsl,imx6q-usbphy", "fsl,imx23-usbphy"; + reg = <0x020c9000 0x1000>; + clocks = <&clks IMX6QDL_CLK_USBPHY1>; + interrupts = ; + fsl,anatop = <&anatop>; + }; + +... diff --git a/Documentation/devicetree/bindings/phy/intel,combo-phy.yaml b/Documentation/devicetree/bindings/phy/intel,combo-phy.yaml index 5d54b0a0e8739d818773a7176ed72280058d0805..7dd6a4d94b4880755a8193095c5687737c742485 100644 --- a/Documentation/devicetree/bindings/phy/intel,combo-phy.yaml +++ b/Documentation/devicetree/bindings/phy/intel,combo-phy.yaml @@ -15,7 +15,7 @@ description: | properties: $nodename: - pattern: "combophy(@.*|-[0-9a-f])*$" + pattern: "combophy(@.*|-([0-9]|[1-9][0-9]+))?$" compatible: items: diff --git a/Documentation/devicetree/bindings/phy/mediatek,dsi-phy.yaml b/Documentation/devicetree/bindings/phy/mediatek,dsi-phy.yaml index 26f2b887cfc1ec319697781a493268b30dab4310..a63b20dfa4a53240d90d46ed94d265c00b24dae7 100644 --- a/Documentation/devicetree/bindings/phy/mediatek,dsi-phy.yaml +++ b/Documentation/devicetree/bindings/phy/mediatek,dsi-phy.yaml @@ -24,6 +24,10 @@ properties: - enum: - mediatek,mt7623-mipi-tx - const: mediatek,mt2701-mipi-tx + - items: + - enum: + - mediatek,mt6795-mipi-tx + - const: mediatek,mt8173-mipi-tx - items: - enum: - mediatek,mt8365-mipi-tx @@ -83,7 +87,7 @@ examples: clocks = <&clk26m>; clock-output-names = "mipi_tx0_pll"; drive-strength-microamp = <4000>; - nvmem-cells= <&mipi_tx_calibration>; + nvmem-cells = <&mipi_tx_calibration>; nvmem-cell-names = "calibration-data"; #clock-cells = <0>; #phy-cells = <0>; diff --git a/Documentation/devicetree/bindings/phy/mixel,mipi-dsi-phy.yaml b/Documentation/devicetree/bindings/phy/mixel,mipi-dsi-phy.yaml index 786cfd71cb7eb6e4da9ba579e149e6a747dbb4a8..3c28ec50f09794b4df31c5b7f5e64eae92937a25 100644 --- a/Documentation/devicetree/bindings/phy/mixel,mipi-dsi-phy.yaml +++ b/Documentation/devicetree/bindings/phy/mixel,mipi-dsi-phy.yaml @@ -32,15 +32,6 @@ properties: clock-names: const: phy_ref - assigned-clocks: - maxItems: 1 - - assigned-clock-parents: - maxItems: 1 - - assigned-clock-rates: - maxItems: 1 - "#phy-cells": const: 0 diff --git a/Documentation/devicetree/bindings/phy/mxs-usb-phy.txt b/Documentation/devicetree/bindings/phy/mxs-usb-phy.txt deleted file mode 100644 index 70c813b0755f971b5eecffeecfa084255d7f860e..0000000000000000000000000000000000000000 --- a/Documentation/devicetree/bindings/phy/mxs-usb-phy.txt +++ /dev/null @@ -1,33 +0,0 @@ -* Freescale MXS USB Phy Device - -Required properties: -- compatible: should contain: - * "fsl,imx23-usbphy" for imx23 and imx28 - * "fsl,imx6q-usbphy" for imx6dq and imx6dl - * "fsl,imx6sl-usbphy" for imx6sl - * "fsl,vf610-usbphy" for Vybrid vf610 - * "fsl,imx6sx-usbphy" for imx6sx - * "fsl,imx7ulp-usbphy" for imx7ulp - * "fsl,imx8dxl-usbphy" for imx8dxl - "fsl,imx23-usbphy" is still a fallback for other strings -- reg: Should contain registers location and length -- interrupts: Should contain phy interrupt -- fsl,anatop: phandle for anatop register, it is only for imx6 SoC series - -Optional properties: -- fsl,tx-cal-45-dn-ohms: Integer [35-54]. Resistance (in ohms) of switchable - high-speed trimming resistor connected in parallel with the 45 ohm resistor - that terminates the DN output signal. Default: 45 -- fsl,tx-cal-45-dp-ohms: Integer [35-54]. Resistance (in ohms) of switchable - high-speed trimming resistor connected in parallel with the 45 ohm resistor - that terminates the DP output signal. Default: 45 -- fsl,tx-d-cal: Integer [79-119]. Current trimming value (as a percentage) of - the 17.78mA TX reference current. Default: 100 - -Example: -usbphy1: usb-phy@20c9000 { - compatible = "fsl,imx6q-usbphy", "fsl,imx23-usbphy"; - reg = <0x020c9000 0x1000>; - interrupts = <0 44 0x04>; - fsl,anatop = <&anatop>; -}; diff --git a/Documentation/devicetree/bindings/phy/phy-rockchip-naneng-combphy.yaml b/Documentation/devicetree/bindings/phy/phy-rockchip-naneng-combphy.yaml index 9ae514fa753319dc7411238917f491751092937d..d3cd7997879f7f2d0d66bea07486b0a921bef334 100644 --- a/Documentation/devicetree/bindings/phy/phy-rockchip-naneng-combphy.yaml +++ b/Documentation/devicetree/bindings/phy/phy-rockchip-naneng-combphy.yaml @@ -31,8 +31,14 @@ properties: - const: pipe resets: + minItems: 1 + maxItems: 2 + + reset-names: + minItems: 1 items: - - description: exclusive PHY reset line + - const: phy + - const: apb rockchip,enable-ssc: type: boolean @@ -78,6 +84,32 @@ required: - rockchip,pipe-phy-grf - "#phy-cells" +allOf: + - if: + properties: + compatible: + contains: + const: rockchip,rk3568-naneng-combphy + then: + properties: + resets: + maxItems: 1 + reset-names: + maxItems: 1 + - if: + properties: + compatible: + contains: + const: rockchip,rk3588-naneng-combphy + then: + properties: + resets: + minItems: 2 + reset-names: + minItems: 2 + required: + - reset-names + additionalProperties: false examples: diff --git a/Documentation/devicetree/bindings/phy/qcom,edp-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,edp-phy.yaml index c4f8e6ffa5c32461170ee126371208cc9f4337e2..6566353f1a0262a732d41510a8616361a75a9dd4 100644 --- a/Documentation/devicetree/bindings/phy/qcom,edp-phy.yaml +++ b/Documentation/devicetree/bindings/phy/qcom,edp-phy.yaml @@ -43,6 +43,9 @@ properties: "#phy-cells": const: 0 + power-domains: + maxItems: 1 + vdda-phy-supply: true vdda-pll-supply: true diff --git a/Documentation/devicetree/bindings/phy/qcom,ipq8074-qmp-pcie-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,ipq8074-qmp-pcie-phy.yaml index 62045dcfb20c5d121591c59cb032981192f6740e..3d42ee3901a170d1e5065727861addc54b7b0128 100644 --- a/Documentation/devicetree/bindings/phy/qcom,ipq8074-qmp-pcie-phy.yaml +++ b/Documentation/devicetree/bindings/phy/qcom,ipq8074-qmp-pcie-phy.yaml @@ -203,6 +203,7 @@ allOf: compatible: contains: enum: + - qcom,sc8180x-qmp-pcie-phy - qcom,sm8250-qmp-gen3x2-pcie-phy - qcom,sm8250-qmp-modem-pcie-phy - qcom,sm8450-qmp-gen4x2-pcie-phy @@ -224,7 +225,6 @@ allOf: compatible: contains: enum: - - qcom,sc8180x-qmp-pcie-phy - qcom,sdm845-qmp-pcie-phy - qcom,sdx55-qmp-pcie-phy - qcom,sm8250-qmp-gen3x1-pcie-phy diff --git a/Documentation/devicetree/bindings/phy/qcom,msm8996-qmp-ufs-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,msm8996-qmp-ufs-phy.yaml index 80a5348dbfdec6a82c8dde3abc9851a3198abce2..881ba543fd465e914a75e23cb93bb5c02bce1dbc 100644 --- a/Documentation/devicetree/bindings/phy/qcom,msm8996-qmp-ufs-phy.yaml +++ b/Documentation/devicetree/bindings/phy/qcom,msm8996-qmp-ufs-phy.yaml @@ -160,6 +160,7 @@ allOf: contains: enum: - qcom,msm8998-qmp-ufs-phy + - qcom,sc8180x-qmp-ufs-phy - qcom,sdm845-qmp-ufs-phy - qcom,sm6350-qmp-ufs-phy - qcom,sm8150-qmp-ufs-phy @@ -178,23 +179,6 @@ allOf: - description: TX lane 2 - description: RX lane 2 - - if: - properties: - compatible: - contains: - enum: - - qcom,sc8180x-qmp-ufs-phy - then: - patternProperties: - "^phy@[0-9a-f]+$": - properties: - reg: - items: - - description: TX - - description: RX - - description: PCS - - description: PCS_MISC - - if: properties: compatible: diff --git a/Documentation/devicetree/bindings/phy/qcom,msm8996-qmp-usb3-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,msm8996-qmp-usb3-phy.yaml index e81a38281f8c5e1d18c88f3ad44f41386b705553..4c96dab5b9e3635c35d83f395c776e7c46094da8 100644 --- a/Documentation/devicetree/bindings/phy/qcom,msm8996-qmp-usb3-phy.yaml +++ b/Documentation/devicetree/bindings/phy/qcom,msm8996-qmp-usb3-phy.yaml @@ -23,14 +23,12 @@ properties: - qcom,ipq8074-qmp-usb3-phy - qcom,msm8996-qmp-usb3-phy - qcom,msm8998-qmp-usb3-phy - - qcom,qcm2290-qmp-usb3-phy - qcom,sc7180-qmp-usb3-phy - qcom,sc8180x-qmp-usb3-phy - qcom,sdm845-qmp-usb3-phy - qcom,sdm845-qmp-usb3-uni-phy - qcom,sdx55-qmp-usb3-uni-phy - qcom,sdx65-qmp-usb3-uni-phy - - qcom,sm6115-qmp-usb3-phy - qcom,sm8150-qmp-usb3-phy - qcom,sm8150-qmp-usb3-uni-phy - qcom,sm8250-qmp-usb3-phy @@ -248,29 +246,6 @@ allOf: - const: phy - const: common - - if: - properties: - compatible: - contains: - enum: - - qcom,qcm2290-qmp-usb3-phy - - qcom,sm6115-qmp-usb3-phy - then: - properties: - clocks: - maxItems: 3 - clock-names: - items: - - const: cfg_ahb - - const: ref - - const: com_aux - resets: - maxItems: 2 - reset-names: - items: - - const: phy_phy - - const: phy - - if: properties: compatible: @@ -318,12 +293,10 @@ allOf: enum: - qcom,ipq6018-qmp-usb3-phy - qcom,ipq8074-qmp-usb3-phy - - qcom,qcm2290-qmp-usb3-phy - qcom,sc7180-qmp-usb3-phy - qcom,sc8180x-qmp-usb3-phy - qcom,sdx55-qmp-usb3-uni-phy - qcom,sdx65-qmp-usb3-uni-phy - - qcom,sm6115-qmp-usb3-phy - qcom,sm8150-qmp-usb3-uni-phy - qcom,sm8250-qmp-usb3-phy then: diff --git a/Documentation/devicetree/bindings/phy/qcom,qusb2-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,qusb2-phy.yaml index 543c1a2811a579c2d5c832bdfaab38b216518646..95eecbaef05c0e410308a6c3ca2b360a8167a93c 100644 --- a/Documentation/devicetree/bindings/phy/qcom,qusb2-phy.yaml +++ b/Documentation/devicetree/bindings/phy/qcom,qusb2-phy.yaml @@ -18,13 +18,14 @@ properties: oneOf: - items: - enum: + - qcom,ipq6018-qusb2-phy - qcom,ipq8074-qusb2-phy + - qcom,ipq9574-qusb2-phy - qcom,msm8953-qusb2-phy - qcom,msm8996-qusb2-phy - qcom,msm8998-qusb2-phy - qcom,qcm2290-qusb2-phy - qcom,sdm660-qusb2-phy - - qcom,ipq6018-qusb2-phy - qcom,sm4250-qusb2-phy - qcom,sm6115-qusb2-phy - items: diff --git a/Documentation/devicetree/bindings/phy/qcom,sa8775p-dwmac-sgmii-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,sa8775p-dwmac-sgmii-phy.yaml new file mode 100644 index 0000000000000000000000000000000000000000..b9107759b2a51738d884f6bdce16bf0bff644056 --- /dev/null +++ b/Documentation/devicetree/bindings/phy/qcom,sa8775p-dwmac-sgmii-phy.yaml @@ -0,0 +1,55 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/phy/qcom,sa8775p-dwmac-sgmii-phy.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm SerDes/SGMII ethernet PHY controller + +maintainers: + - Bartosz Golaszewski + +description: + The SerDes PHY sits between the MAC and the external PHY and provides + separate Rx Tx lines. + +properties: + compatible: + const: qcom,sa8775p-dwmac-sgmii-phy + + reg: + items: + - description: serdes + + clocks: + maxItems: 1 + + clock-names: + const: sgmi_ref + + phy-supply: + description: + Phandle to a regulator that provides power to the PHY. + + "#phy-cells": + const: 0 + +required: + - compatible + - reg + - "#phy-cells" + - clocks + - clock-names + +additionalProperties: false + +examples: + - | + #include + serdes_phy: phy@8901000 { + compatible = "qcom,sa8775p-dwmac-sgmii-phy"; + reg = <0x08901000 0xe10>; + clocks = <&gcc GCC_SGMI_CLKREF_EN>; + clock-names = "sgmi_ref"; + #phy-cells = <0>; + }; diff --git a/Documentation/devicetree/bindings/phy/qcom,sc7180-qmp-usb3-dp-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,sc7180-qmp-usb3-dp-phy.yaml index 0ef2c9b9d4669c637528f6307b264946f9a323d5..d307343388888e96a52b41979aeedee806992b15 100644 --- a/Documentation/devicetree/bindings/phy/qcom,sc7180-qmp-usb3-dp-phy.yaml +++ b/Documentation/devicetree/bindings/phy/qcom,sc7180-qmp-usb3-dp-phy.yaml @@ -61,6 +61,10 @@ properties: power-domains: maxItems: 1 + orientation-switch: + description: Flag the port as possible handler of orientation switching + type: boolean + resets: items: - description: reset of phy block. @@ -251,6 +255,8 @@ examples: vdda-phy-supply = <&vdda_usb2_ss_1p2>; vdda-pll-supply = <&vdda_usb2_ss_core>; + orientation-switch; + usb3-phy@200 { reg = <0x200 0x128>, <0x400 0x200>, diff --git a/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-ufs-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-ufs-phy.yaml index 94c0fab065a8bac4caa2b628fdb1054855758ec9..a1897a7606df489666db860d2e6784dafa1d74ab 100644 --- a/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-ufs-phy.yaml +++ b/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-ufs-phy.yaml @@ -78,9 +78,9 @@ allOf: then: properties: clocks: - maxItems: 3 + minItems: 3 clock-names: - maxItems: 3 + minItems: 3 else: properties: clocks: diff --git a/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-usb3-uni-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-usb3-uni-phy.yaml index 16fce10382852e640f844305f20329b4691046f2..f99fbbcd68fba1fd1c446e73a6d9fe2025f8cd15 100644 --- a/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-usb3-uni-phy.yaml +++ b/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-usb3-uni-phy.yaml @@ -16,7 +16,11 @@ description: properties: compatible: enum: + - qcom,ipq9574-qmp-usb3-phy + - qcom,qcm2290-qmp-usb3-phy + - qcom,sa8775p-qmp-usb3-uni-phy - qcom,sc8280xp-qmp-usb3-uni-phy + - qcom,sm6115-qmp-usb3-phy reg: maxItems: 1 @@ -25,11 +29,7 @@ properties: maxItems: 4 clock-names: - items: - - const: aux - - const: ref - - const: com_aux - - const: pipe + maxItems: 4 power-domains: maxItems: 1 @@ -60,7 +60,6 @@ required: - reg - clocks - clock-names - - power-domains - resets - reset-names - vdda-phy-supply @@ -69,6 +68,60 @@ required: - clock-output-names - "#phy-cells" +allOf: + - if: + properties: + compatible: + contains: + enum: + - qcom,ipq9574-qmp-usb3-phy + then: + properties: + clock-names: + items: + - const: aux + - const: ref + - const: cfg_ahb + - const: pipe + + - if: + properties: + compatible: + contains: + enum: + - qcom,qcm2290-qmp-usb3-phy + - qcom,sm6115-qmp-usb3-phy + then: + properties: + clocks: + maxItems: 4 + clock-names: + items: + - const: cfg_ahb + - const: ref + - const: com_aux + - const: pipe + + - if: + properties: + compatible: + contains: + enum: + - qcom,sa8775p-qmp-usb3-uni-phy + - qcom,sc8280xp-qmp-usb3-uni-phy + then: + properties: + clocks: + maxItems: 4 + clock-names: + items: + - const: aux + - const: ref + - const: com_aux + - const: pipe + required: + - power-domains + additionalProperties: false examples: diff --git a/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-usb43dp-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-usb43dp-phy.yaml index 3cd5fc3e8fab80dea436bf17261a6a598f003373..ef1c02d8ac88e055176ece483fefc3fe6bab19a1 100644 --- a/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-usb43dp-phy.yaml +++ b/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-usb43dp-phy.yaml @@ -60,6 +60,26 @@ properties: description: See include/dt-bindings/dt-bindings/phy/phy-qcom-qmp.h + orientation-switch: + description: + Flag the PHY as possible handler of USB Type-C orientation switching + type: boolean + + ports: + $ref: /schemas/graph.yaml#/properties/ports + properties: + port@0: + $ref: /schemas/graph.yaml#/properties/port + description: Output endpoint of the PHY + + port@1: + $ref: /schemas/graph.yaml#/properties/port + description: Incoming endpoint from the USB controller + + port@2: + $ref: /schemas/graph.yaml#/properties/port + description: Incoming endpoint from the DisplayPort controller + required: - compatible - reg @@ -98,6 +118,37 @@ examples: vdda-phy-supply = <&vreg_l9d>; vdda-pll-supply = <&vreg_l4d>; + orientation-switch; + #clock-cells = <1>; #phy-cells = <1>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + endpoint { + remote-endpoint = <&typec_connector_ss>; + }; + }; + + port@1 { + reg = <1>; + + endpoint { + remote-endpoint = <&dwc3_ss_out>; + }; + }; + + port@2 { + reg = <2>; + + endpoint { + remote-endpoint = <&mdss_dp_out>; + }; + }; + }; }; diff --git a/Documentation/devicetree/bindings/phy/qcom,usb-hs-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,usb-hs-phy.yaml index aa97478dd01611ead27be7a6ae5b71ffff02b0bd..f042d6af15949fb6ab4476d56c0e25c25f9d2c91 100644 --- a/Documentation/devicetree/bindings/phy/qcom,usb-hs-phy.yaml +++ b/Documentation/devicetree/bindings/phy/qcom,usb-hs-phy.yaml @@ -13,7 +13,9 @@ if: properties: compatible: contains: - const: qcom,usb-hs-phy-apq8064 + enum: + - qcom,usb-hs-phy-apq8064 + - qcom,usb-hs-phy-msm8960 then: properties: resets: @@ -40,6 +42,7 @@ properties: - qcom,usb-hs-phy-apq8064 - qcom,usb-hs-phy-msm8226 - qcom,usb-hs-phy-msm8916 + - qcom,usb-hs-phy-msm8960 - qcom,usb-hs-phy-msm8974 - const: qcom,usb-hs-phy diff --git a/Documentation/devicetree/bindings/phy/qcom,usb-snps-femto-v2.yaml b/Documentation/devicetree/bindings/phy/qcom,usb-snps-femto-v2.yaml index a26524b7e7b7a99de30a68b838ab4fa62fdadad5..0f200e3f97a9a39c40738ee0f607aa1ceb8480cc 100644 --- a/Documentation/devicetree/bindings/phy/qcom,usb-snps-femto-v2.yaml +++ b/Documentation/devicetree/bindings/phy/qcom,usb-snps-femto-v2.yaml @@ -20,6 +20,7 @@ properties: - qcom,usb-snps-femto-v2-phy - items: - enum: + - qcom,sa8775p-usb-hs-phy - qcom,sc8280xp-usb-hs-phy - const: qcom,usb-snps-hs-5nm-phy - items: diff --git a/Documentation/devicetree/bindings/pinctrl/atmel,at91-pio4-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/atmel,at91-pio4-pinctrl.txt index e2b861ce16d81725175eca5a491fdd3a7fbd4888..774c3c269c403e08d1bd0a086b0c7a6bec395bc8 100644 --- a/Documentation/devicetree/bindings/pinctrl/atmel,at91-pio4-pinctrl.txt +++ b/Documentation/devicetree/bindings/pinctrl/atmel,at91-pio4-pinctrl.txt @@ -37,7 +37,8 @@ right representation of the pin. Optional properties: - GENERIC_PINCONFIG: generic pinconfig options to use: - bias-disable, bias-pull-down, bias-pull-up, drive-open-drain, - input-schmitt-enable, input-debounce, output-low, output-high. + drive-push-pull input-schmitt-enable, input-debounce, output-low, + output-high. - for microchip,sama7g5-pinctrl only: - slew-rate: 0 - disabled, 1 - enabled (default) - atmel,drive-strength: 0 or 1 for low drive, 2 for medium drive and 3 for diff --git a/Documentation/devicetree/bindings/pinctrl/nvidia,tegra234-pinmux-aon.yaml b/Documentation/devicetree/bindings/pinctrl/nvidia,tegra234-pinmux-aon.yaml new file mode 100644 index 0000000000000000000000000000000000000000..f3deda9f7127fd53b04c2e8f29064d780a338799 --- /dev/null +++ b/Documentation/devicetree/bindings/pinctrl/nvidia,tegra234-pinmux-aon.yaml @@ -0,0 +1,78 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/pinctrl/nvidia,tegra234-pinmux-aon.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: NVIDIA Tegra234 AON Pinmux Controller + +maintainers: + - Thierry Reding + - Jon Hunter + +$ref: nvidia,tegra234-pinmux-common.yaml + +properties: + compatible: + const: nvidia,tegra234-pinmux-aon + +patternProperties: + "^pinmux(-[a-z0-9-]+)?$": + type: object + + # pin groups + additionalProperties: + properties: + nvidia,pins: + items: + enum: [ can0_dout_paa0, can0_din_paa1, can1_dout_paa2, + can1_din_paa3, can0_stb_paa4, can0_en_paa5, + soc_gpio49_paa6, can0_err_paa7, can1_stb_pbb0, + can1_en_pbb1, soc_gpio50_pbb2, can1_err_pbb3, + spi2_sck_pcc0, spi2_miso_pcc1, spi2_mosi_pcc2, + spi2_cs0_pcc3, touch_clk_pcc4, uart3_tx_pcc5, + uart3_rx_pcc6, gen2_i2c_scl_pcc7, gen2_i2c_sda_pdd0, + gen8_i2c_scl_pdd1, gen8_i2c_sda_pdd2, + sce_error_pee0, vcomp_alert_pee1, + ao_retention_n_pee2, batt_oc_pee3, power_on_pee4, + soc_gpio26_pee5, soc_gpio27_pee6, bootv_ctl_n_pee7, + hdmi_cec_pgg0, + # drive groups + drive_touch_clk_pcc4, drive_uart3_rx_pcc6, + drive_uart3_tx_pcc5, drive_gen8_i2c_sda_pdd2, + drive_gen8_i2c_scl_pdd1, drive_spi2_mosi_pcc2, + drive_gen2_i2c_scl_pcc7, drive_spi2_cs0_pcc3, + drive_gen2_i2c_sda_pdd0, drive_spi2_sck_pcc0, + drive_spi2_miso_pcc1, drive_can1_dout_paa2, + drive_can1_din_paa3, drive_can0_dout_paa0, + drive_can0_din_paa1, drive_can0_stb_paa4, + drive_can0_en_paa5, drive_soc_gpio49_paa6, + drive_can0_err_paa7, drive_can1_stb_pbb0, + drive_can1_en_pbb1, drive_soc_gpio50_pbb2, + drive_can1_err_pbb3, drive_sce_error_pee0, + drive_batt_oc_pee3, drive_bootv_ctl_n_pee7, + drive_power_on_pee4, drive_soc_gpio26_pee5, + drive_soc_gpio27_pee6, drive_ao_retention_n_pee2, + drive_vcomp_alert_pee1, drive_hdmi_cec_pgg0 ] + +unevaluatedProperties: false + +examples: + - | + #include + + pinmux@c300000 { + compatible = "nvidia,tegra234-pinmux-aon"; + reg = <0xc300000 0x4000>; + + pinctrl-names = "cec"; + pinctrl-0 = <&cec_state>; + + cec_state: pinmux-cec { + cec { + nvidia,pins = "hdmi_cec_pgg0"; + nvidia,function = "gp"; + }; + }; + }; +... diff --git a/Documentation/devicetree/bindings/pinctrl/nvidia,tegra234-pinmux-common.yaml b/Documentation/devicetree/bindings/pinctrl/nvidia,tegra234-pinmux-common.yaml new file mode 100644 index 0000000000000000000000000000000000000000..4f9de78085e50fc02900cf3536659ae09f53a6fb --- /dev/null +++ b/Documentation/devicetree/bindings/pinctrl/nvidia,tegra234-pinmux-common.yaml @@ -0,0 +1,66 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/pinctrl/nvidia,tegra234-pinmux-common.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: NVIDIA Tegra234 Pinmux Controller + +maintainers: + - Thierry Reding + - Jon Hunter + +properties: + reg: + items: + - description: pinmux registers + +patternProperties: + "^pinmux(-[a-z0-9-]+)?$": + type: object + + # pin groups + additionalProperties: + $ref: nvidia,tegra-pinmux-common.yaml + # We would typically use unevaluatedProperties here but that has the + # downside that all the properties in the common bindings become valid + # for all chip generations. In this case, however, we want the per-SoC + # bindings to be able to override which of the common properties are + # allowed, since not all pinmux generations support the same sets of + # properties. This way, the common bindings define the format of the + # properties but the per-SoC bindings define which of them apply to a + # given chip. + additionalProperties: false + properties: + nvidia,function: + enum: [ gp, uartc, i2c8, spi2, i2c2, can1, can0, rsvd0, eth0, eth2, + eth1, dp, eth3, i2c4, i2c7, i2c9, eqos, pe2, pe1, pe0, pe3, + pe4, pe5, pe6, pe7, pe8, pe9, pe10, qspi0, qspi1, qpsi, + sdmmc1, sce, soc, gpio, hdmi, ufs0, spi3, spi1, uartb, uarte, + usb, extperiph2, extperiph1, i2c3, vi0, i2c5, uarta, uartd, + i2c1, i2s4, i2s6, aud, spi5, touch, uartj, rsvd1, wdt, tsc, + dmic3, led, vi0_alt, i2s5, nv, extperiph3, extperiph4, spi4, + ccla, i2s1, i2s2, i2s3, i2s8, rsvd2, dmic5, dca, displayb, + displaya, vi1, dcb, dmic1, dmic4, i2s7, dmic2, dspk0, rsvd3, + tsc_alt, istctrl, vi1_alt, dspk1, igpu ] + + # out of the common properties, only these are allowed for Tegra234 + nvidia,pins: true + nvidia,pull: true + nvidia,tristate: true + nvidia,schmitt: true + nvidia,enable-input: true + nvidia,open-drain: true + nvidia,lock: true + nvidia,drive-type: true + nvidia,io-hv: true + + required: + - nvidia,pins + +required: + - compatible + - reg + +additionalProperties: true +... diff --git a/Documentation/devicetree/bindings/pinctrl/nvidia,tegra234-pinmux.yaml b/Documentation/devicetree/bindings/pinctrl/nvidia,tegra234-pinmux.yaml new file mode 100644 index 0000000000000000000000000000000000000000..17b865ecfcdaa0410c8c8f0358946ceee64b4505 --- /dev/null +++ b/Documentation/devicetree/bindings/pinctrl/nvidia,tegra234-pinmux.yaml @@ -0,0 +1,139 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/pinctrl/nvidia,tegra234-pinmux.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: NVIDIA Tegra234 Pinmux Controller + +maintainers: + - Thierry Reding + - Jon Hunter + +$ref: nvidia,tegra234-pinmux-common.yaml + +properties: + compatible: + const: nvidia,tegra234-pinmux + +patternProperties: + "^pinmux(-[a-z0-9-]+)?$": + type: object + + # pin groups + additionalProperties: + properties: + nvidia,pins: + items: + enum: [ dap6_sclk_pa0, dap6_dout_pa1, dap6_din_pa2, + dap6_fs_pa3, dap4_sclk_pa4, dap4_dout_pa5, + dap4_din_pa6, dap4_fs_pa7, soc_gpio08_pb0, + qspi0_sck_pc0, qspi0_cs_n_pc1, + qspi0_io0_pc2, qspi0_io1_pc3, qspi0_io2_pc4, + qspi0_io3_pc5, qspi1_sck_pc6, qspi1_cs_n_pc7, + qspi1_io0_pd0, qspi1_io1_pd1, qspi1_io2_pd2, + qspi1_io3_pd3, eqos_txc_pe0, eqos_td0_pe1, + eqos_td1_pe2, eqos_td2_pe3, eqos_td3_pe4, + eqos_tx_ctl_pe5, eqos_rd0_pe6, eqos_rd1_pe7, + eqos_rd2_pf0, eqos_rd3_pf1, eqos_rx_ctl_pf2, + eqos_rxc_pf3, eqos_sma_mdio_pf4, eqos_sma_mdc_pf5, + soc_gpio13_pg0, soc_gpio14_pg1, soc_gpio15_pg2, + soc_gpio16_pg3, soc_gpio17_pg4, soc_gpio18_pg5, + soc_gpio19_pg6, soc_gpio20_pg7, soc_gpio21_ph0, + soc_gpio22_ph1, soc_gpio06_ph2, uart4_tx_ph3, + uart4_rx_ph4, uart4_rts_ph5, uart4_cts_ph6, + soc_gpio41_ph7, soc_gpio42_pi0, soc_gpio43_pi1, + soc_gpio44_pi2, gen1_i2c_scl_pi3, gen1_i2c_sda_pi4, + cpu_pwr_req_pi5, soc_gpio07_pi6, + sdmmc1_clk_pj0, sdmmc1_cmd_pj1, sdmmc1_dat0_pj2, + sdmmc1_dat1_pj3, sdmmc1_dat2_pj4, sdmmc1_dat3_pj5, + pex_l0_clkreq_n_pk0, pex_l0_rst_n_pk1, + pex_l1_clkreq_n_pk2, pex_l1_rst_n_pk3, + pex_l2_clkreq_n_pk4, pex_l2_rst_n_pk5, + pex_l3_clkreq_n_pk6, pex_l3_rst_n_pk7, + pex_l4_clkreq_n_pl0, pex_l4_rst_n_pl1, + pex_wake_n_pl2, soc_gpio34_pl3, dp_aux_ch0_hpd_pm0, + dp_aux_ch1_hpd_pm1, dp_aux_ch2_hpd_pm2, + dp_aux_ch3_hpd_pm3, soc_gpio55_pm4, soc_gpio36_pm5, + soc_gpio53_pm6, soc_gpio38_pm7, dp_aux_ch3_n_pn0, + soc_gpio39_pn1, soc_gpio40_pn2, dp_aux_ch1_p_pn3, + dp_aux_ch1_n_pn4, dp_aux_ch2_p_pn5, dp_aux_ch2_n_pn6, + dp_aux_ch3_p_pn7, extperiph1_clk_pp0, + extperiph2_clk_pp1, cam_i2c_scl_pp2, cam_i2c_sda_pp3, + soc_gpio23_pp4, soc_gpio24_pp5, soc_gpio25_pp6, + pwr_i2c_scl_pp7, pwr_i2c_sda_pq0, soc_gpio28_pq1, + soc_gpio29_pq2, soc_gpio30_pq3, soc_gpio31_pq4, + soc_gpio32_pq5, soc_gpio33_pq6, soc_gpio35_pq7, + soc_gpio37_pr0, soc_gpio56_pr1, uart1_tx_pr2, + uart1_rx_pr3, uart1_rts_pr4, uart1_cts_pr5, + soc_gpio61_pw0, soc_gpio62_pw1, gpu_pwr_req_px0, + cv_pwr_req_px1, gp_pwm2_px2, gp_pwm3_px3, uart2_tx_px4, + uart2_rx_px5, uart2_rts_px6, uart2_cts_px7, spi3_sck_py0, + spi3_miso_py1, spi3_mosi_py2, spi3_cs0_py3, + spi3_cs1_py4, uart5_tx_py5, uart5_rx_py6, + uart5_rts_py7, uart5_cts_pz0, usb_vbus_en0_pz1, + usb_vbus_en1_pz2, spi1_sck_pz3, spi1_miso_pz4, + spi1_mosi_pz5, spi1_cs0_pz6, spi1_cs1_pz7, + spi5_sck_pac0, spi5_miso_pac1, spi5_mosi_pac2, + spi5_cs0_pac3, soc_gpio57_pac4, soc_gpio58_pac5, + soc_gpio59_pac6, soc_gpio60_pac7, soc_gpio45_pad0, + soc_gpio46_pad1, soc_gpio47_pad2, soc_gpio48_pad3, + ufs0_ref_clk_pae0, ufs0_rst_n_pae1, + pex_l5_clkreq_n_paf0, pex_l5_rst_n_paf1, + pex_l6_clkreq_n_paf2, pex_l6_rst_n_paf3, + pex_l7_clkreq_n_pag0, pex_l7_rst_n_pag1, + pex_l8_clkreq_n_pag2, pex_l8_rst_n_pag3, + pex_l9_clkreq_n_pag4, pex_l9_rst_n_pag5, + pex_l10_clkreq_n_pag6, pex_l10_rst_n_pag7, + sdmmc1_comp, eqos_comp, qspi_comp, + # drive groups + drive_soc_gpio08_pb0, drive_soc_gpio36_pm5, + drive_soc_gpio53_pm6, drive_soc_gpio55_pm4, + drive_soc_gpio38_pm7, drive_soc_gpio39_pn1, + drive_soc_gpio40_pn2, drive_dp_aux_ch0_hpd_pm0, + drive_dp_aux_ch1_hpd_pm1, drive_dp_aux_ch2_hpd_pm2, + drive_dp_aux_ch3_hpd_pm3, drive_dp_aux_ch1_p_pn3, + drive_dp_aux_ch1_n_pn4, drive_dp_aux_ch2_p_pn5, + drive_dp_aux_ch2_n_pn6, drive_dp_aux_ch3_p_pn7, + drive_dp_aux_ch3_n_pn0, drive_pex_l2_clkreq_n_pk4, + drive_pex_wake_n_pl2, drive_pex_l1_clkreq_n_pk2, + drive_pex_l1_rst_n_pk3, drive_pex_l0_clkreq_n_pk0, + drive_pex_l0_rst_n_pk1, drive_pex_l2_rst_n_pk5, + drive_pex_l3_clkreq_n_pk6, drive_pex_l3_rst_n_pk7, + drive_pex_l4_clkreq_n_pl0, drive_pex_l4_rst_n_pl1, + drive_soc_gpio34_pl3, drive_pex_l5_clkreq_n_paf0, + drive_pex_l5_rst_n_paf1, drive_pex_l6_clkreq_n_paf2, + drive_pex_l6_rst_n_paf3, drive_pex_l10_clkreq_n_pag6, + drive_pex_l10_rst_n_pag7, drive_pex_l7_clkreq_n_pag0, + drive_pex_l7_rst_n_pag1, drive_pex_l8_clkreq_n_pag2, + drive_pex_l8_rst_n_pag3, drive_pex_l9_clkreq_n_pag4, + drive_pex_l9_rst_n_pag5, drive_sdmmc1_clk_pj0, + drive_sdmmc1_cmd_pj1, drive_sdmmc1_dat3_pj5, + drive_sdmmc1_dat2_pj4, drive_sdmmc1_dat1_pj3, + drive_sdmmc1_dat0_pj2 ] + +unevaluatedProperties: false + +examples: + - | + #include + + pinmux@2430000 { + compatible = "nvidia,tegra234-pinmux"; + reg = <0x2430000 0x17000>; + + pinctrl-names = "pex_rst"; + pinctrl-0 = <&pex_rst_c5_out_state>; + + pex_rst_c5_out_state: pinmux-pex-rst-c5-out { + pexrst { + nvidia,pins = "pex_l5_rst_n_paf1"; + nvidia,schmitt = ; + nvidia,enable-input = ; + nvidia,io-hv = ; + nvidia,tristate = ; + nvidia,pull = ; + }; + }; + }; +... diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,ipq5018-tlmm.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,ipq5018-tlmm.yaml new file mode 100644 index 0000000000000000000000000000000000000000..fad0118fd5219c86d8a1342379dc8a9960a746bb --- /dev/null +++ b/Documentation/devicetree/bindings/pinctrl/qcom,ipq5018-tlmm.yaml @@ -0,0 +1,127 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/pinctrl/qcom,ipq5018-tlmm.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm IPQ5018 TLMM pin controller + +maintainers: + - Bjorn Andersson + - Krzysztof Kozlowski + +description: + Top Level Mode Multiplexer pin controller in Qualcomm IPQ5018 SoC. + +properties: + compatible: + const: qcom,ipq5018-tlmm + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + interrupt-controller: true + "#interrupt-cells": true + gpio-controller: true + "#gpio-cells": true + gpio-ranges: true + wakeup-parent: true + + gpio-reserved-ranges: + minItems: 1 + maxItems: 24 + + gpio-line-names: + maxItems: 47 + +patternProperties: + "-state$": + oneOf: + - $ref: "#/$defs/qcom-ipq5018-tlmm-state" + - patternProperties: + "-pins$": + $ref: "#/$defs/qcom-ipq5018-tlmm-state" + additionalProperties: false + +$defs: + qcom-ipq5018-tlmm-state: + type: object + description: + Pinctrl node's client devices use subnodes for desired pin configuration. + Client device subnodes use below standard properties. + $ref: qcom,tlmm-common.yaml#/$defs/qcom-tlmm-state + unevaluatedProperties: false + + properties: + pins: + description: + List of gpio pins affected by the properties specified in this + subnode. + items: + pattern: "^gpio([0-9]|[1-3][0-9]|4[0-6])$" + minItems: 1 + maxItems: 8 + + function: + description: + Specify the alternative function to be configured for the specified + pins. + + enum: [ atest_char, audio_pdm0, audio_pdm1, audio_rxbclk, audio_rxd, + audio_rxfsync, audio_rxmclk, audio_txbclk, audio_txd, + audio_txfsync, audio_txmclk, blsp0_i2c, blsp0_spi, blsp0_uart0, + blsp0_uart1, blsp1_i2c0, blsp1_i2c1, blsp1_spi0, blsp1_spi1, + blsp1_uart0, blsp1_uart1, blsp1_uart2, blsp2_i2c0, blsp2_i2c1, + blsp2_spi, blsp2_spi0, blsp2_spi1, btss, burn0, burn1, cri_trng, + cri_trng0, cri_trng1, cxc_clk, cxc_data, dbg_out, eud_gpio, + gcc_plltest, gcc_tlmm, gpio, led0, led2, mac0, mac1, mdc, mdio, + pcie0_clk, pcie0_wake, pcie1_clk, pcie1_wake, pll_test, + prng_rosc, pwm0, pwm1, pwm2, pwm3, qdss_cti_trig_in_a0, + qdss_cti_trig_in_a1, qdss_cti_trig_in_b0, qdss_cti_trig_in_b1, + qdss_cti_trig_out_a0, qdss_cti_trig_out_a1, + qdss_cti_trig_out_b0, qdss_cti_trig_out_b1, qdss_traceclk_a, + qdss_traceclk_b, qdss_tracectl_a, qdss_tracectl_b, + qdss_tracedata_a, qdss_tracedata_b, qspi_clk, qspi_cs, + qspi_data, reset_out, sdc1_clk, sdc1_cmd, sdc1_data, wci_txd, + wci_rxd, wsa_swrm, wsi_clk3, wsi_data3, wsis_reset, xfem ] + + required: + - pins + +required: + - compatible + - reg + +additionalProperties: false + +examples: + - | + #include + tlmm: pinctrl@1000000 { + compatible = "qcom,ipq5018-tlmm"; + reg = <0x01000000 0x300000>; + gpio-controller; + #gpio-cells = <2>; + gpio-ranges = <&tlmm 0 0 47>; + interrupt-controller; + #interrupt-cells = <2>; + interrupts = ; + + uart-w-state { + rx-pins { + pins = "gpio33"; + function = "blsp1_uart1"; + bias-pull-down; + }; + + tx-pins { + pins = "gpio34"; + function = "blsp1_uart1"; + bias-pull-down; + }; + }; + }; +... diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,ipq9574-tlmm.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,ipq9574-tlmm.yaml index 673713debac2892db5b80b1fd8c5d372db75d7a0..e5e9962b2174fd68b9adc55a01698ee4fcdb53b3 100644 --- a/Documentation/devicetree/bindings/pinctrl/qcom,ipq9574-tlmm.yaml +++ b/Documentation/devicetree/bindings/pinctrl/qcom,ipq9574-tlmm.yaml @@ -53,6 +53,7 @@ $defs: Pinctrl node's client devices use subnodes for desired pin configuration. Client device subnodes use below standard properties. $ref: qcom,tlmm-common.yaml#/$defs/qcom-tlmm-state + unevaluatedProperties: false properties: pins: @@ -86,19 +87,9 @@ $defs: rx0, rx1, sdc_clk, sdc_cmd, sdc_data, sdc_rclk, tsens_max, wci20, wci21, wsa_swrm ] - bias-pull-down: true - bias-pull-up: true - bias-disable: true - drive-strength: true - input-enable: true - output-high: true - output-low: true - required: - pins - additionalProperties: false - allOf: - $ref: /schemas/pinctrl/qcom,tlmm-common.yaml# diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,pmic-gpio.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,pmic-gpio.yaml index eaadd5a9a44532dfd988f7b58250d78d354d4c35..8aaf50181cefcc43f586d063fa4c0f9597985faf 100644 --- a/Documentation/devicetree/bindings/pinctrl/qcom,pmic-gpio.yaml +++ b/Documentation/devicetree/bindings/pinctrl/qcom,pmic-gpio.yaml @@ -49,6 +49,7 @@ properties: - qcom,pm8921-gpio - qcom,pm8941-gpio - qcom,pm8950-gpio + - qcom,pm8953-gpio - qcom,pm8994-gpio - qcom,pm8998-gpio - qcom,pma8084-gpio @@ -175,6 +176,7 @@ allOf: - qcom,pm8350b-gpio - qcom,pm8550ve-gpio - qcom,pm8950-gpio + - qcom,pm8953-gpio - qcom,pmi632-gpio then: properties: @@ -434,6 +436,7 @@ $defs: - gpio1-gpio44 for pm8921 - gpio1-gpio36 for pm8941 - gpio1-gpio8 for pm8950 (hole on gpio3) + - gpio1-gpio8 for pm8953 (hole on gpio3 and gpio6) - gpio1-gpio22 for pm8994 - gpio1-gpio26 for pm8998 - gpio1-gpio22 for pma8084 diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,qcm2290-tlmm.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,qcm2290-tlmm.yaml index 03276364933664387fb4b67e584412cd87add40c..c323f6d495a4495635ad0de9b7353315f28fa86c 100644 --- a/Documentation/devicetree/bindings/pinctrl/qcom,qcm2290-tlmm.yaml +++ b/Documentation/devicetree/bindings/pinctrl/qcom,qcm2290-tlmm.yaml @@ -45,6 +45,7 @@ $defs: Pinctrl node's client devices use subnodes for desired pin configuration. Client device subnodes use below standard properties. $ref: qcom,tlmm-common.yaml#/$defs/qcom-tlmm-state + unevaluatedProperties: false properties: pins: @@ -81,19 +82,9 @@ $defs: uim2_data, uim2_present, uim2_reset, usb_phy, vfr_1, vsense_trigger, wlan1_adc0, wlan1_adc1 ] - bias-pull-down: true - bias-pull-up: true - bias-disable: true - drive-strength: true - input-enable: true - output-high: true - output-low: true - required: - pins - additionalProperties: false - allOf: - $ref: /schemas/pinctrl/qcom,tlmm-common.yaml# diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,sc8280xp-tlmm.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,sc8280xp-tlmm.yaml index 4ae39fc7894a2e6763c4cc6d4529b05e1fb32f0e..4bd6d7977d3e873a866e72ac6a388f4a3f2ae9b7 100644 --- a/Documentation/devicetree/bindings/pinctrl/qcom,sc8280xp-tlmm.yaml +++ b/Documentation/devicetree/bindings/pinctrl/qcom,sc8280xp-tlmm.yaml @@ -55,6 +55,7 @@ $defs: Pinctrl node's client devices use subnodes for desired pin configuration. Client device subnodes use below standard properties. $ref: qcom,tlmm-common.yaml#/$defs/qcom-tlmm-state + unevaluatedProperties: false properties: pins: @@ -104,20 +105,9 @@ $defs: usb1_phy, usb1_sbrx, usb1_sbtx, usb1_usb4, usb2phy_ac, vsense_trigger ] - bias-bus-hold: true - bias-disable: true - bias-pull-down: true - bias-pull-up: true - drive-strength: true - input-enable: true - output-high: true - output-low: true - required: - pins - additionalProperties: false - examples: - | #include diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,sdx65-tlmm.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,sdx65-tlmm.yaml index 2ef793ae40387957a57086f2642c035764f1d929..27319782d94be59fae12e8dfb49ec16ef73a271f 100644 --- a/Documentation/devicetree/bindings/pinctrl/qcom,sdx65-tlmm.yaml +++ b/Documentation/devicetree/bindings/pinctrl/qcom,sdx65-tlmm.yaml @@ -85,7 +85,7 @@ $defs: qdss_tracectl_a, dac_calib13, qdss_traceclk_a, dac_calib14, dac_calib15, hdmi_rcv, dac_calib16, hdmi_cec, pwr_modem, dac_calib17, hdmi_ddc, pwr_nav, dac_calib18, pwr_crypto, - dac_calib19, hdmi_hot, dac_calib20, dac_calib21, pci_e0, + dac_calib19, hdmi_hot, dac_calib20, dac_calib21, pci_e0, pcie_clkreq, dac_calib22, dac_calib23, dac_calib24, tsif1_sync, dac_calib25, sd_write, tsif1_error, blsp_spi2, blsp_uart2, blsp_uim2, qdss_cti, blsp_i2c2, blsp_spi3, blsp_uart3, blsp_uim3, blsp_i2c3, diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,sdx75-tlmm.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,sdx75-tlmm.yaml new file mode 100644 index 0000000000000000000000000000000000000000..7cb96aa75b08bd92c335974d82e9586baf4b2d49 --- /dev/null +++ b/Documentation/devicetree/bindings/pinctrl/qcom,sdx75-tlmm.yaml @@ -0,0 +1,137 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/pinctrl/qcom,sdx75-tlmm.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm Technologies, Inc. SDX75 TLMM block + +maintainers: + - Rohit Agarwal + +description: + Top Level Mode Multiplexer pin controller in Qualcomm SDX75 SoC. + +allOf: + - $ref: /schemas/pinctrl/qcom,tlmm-common.yaml# + +properties: + compatible: + const: qcom,sdx75-tlmm + + reg: + maxItems: 1 + + interrupts: true + interrupt-controller: true + "#interrupt-cells": true + gpio-controller: true + + gpio-reserved-ranges: + minItems: 1 + maxItems: 67 + + gpio-line-names: + maxItems: 133 + + "#gpio-cells": true + gpio-ranges: true + wakeup-parent: true + +patternProperties: + "-state$": + oneOf: + - $ref: "#/$defs/qcom-sdx75-tlmm-state" + - patternProperties: + "-pins$": + $ref: "#/$defs/qcom-sdx75-tlmm-state" + additionalProperties: false + +$defs: + qcom-sdx75-tlmm-state: + type: object + description: + Pinctrl node's client devices use subnodes for desired pin configuration. + Client device subnodes use below standard properties. + $ref: qcom,tlmm-common.yaml#/$defs/qcom-tlmm-state + unevaluatedProperties: false + + properties: + pins: + description: + List of gpio pins affected by the properties specified in this + subnode. + items: + oneOf: + - pattern: "^gpio([0-9]|[1-9][0-9]|1[0-2][0-9]|13[0-2])$" + - enum: [ sdc1_clk, sdc1_cmd, sdc1_data, sdc1_rclk, sdc2_clk, sdc2_cmd, sdc2_data ] + minItems: 1 + maxItems: 36 + + function: + description: + Specify the alternative function to be configured for the specified + pins. + enum: [ adsp_ext, atest_char, audio_ref_clk, bimc_dte, char_exec, coex_uart2, + coex_uart, cri_trng, cri_trng0, cri_trng1, dbg_out_clk, ddr_bist, + ddr_pxi0, ebi0_wrcdc, ebi2_a, ebi2_lcd, ebi2_lcd_te, emac0_mcg, + emac0_ptp, emac1_mcg, emac1_ptp, emac_cdc, emac_pps_in, eth0_mdc, + eth0_mdio, eth1_mdc, eth1_mdio, ext_dbg, gcc_125_clk, gcc_gp1_clk, + gcc_gp2_clk, gcc_gp3_clk, gcc_plltest, gpio, i2s_mclk, jitter_bist, + ldo_en, ldo_update, m_voc, mgpi_clk, native_char, native_tsens, + native_tsense, nav_dr_sync, nav_gpio, pa_indicator, pci_e, + pcie0_clkreq_n, pcie1_clkreq_n, pcie2_clkreq_n, pll_bist_sync, + pll_clk_aux, pll_ref_clk, pri_mi2s, prng_rosc, qdss_cti, qdss_gpio, + qlink0_b_en, qlink0_b_req, qlink0_l_en, qlink0_l_req, qlink0_wmss, + qlink1_l_en, qlink1_l_req, qlink1_wmss, qup_se0, qup_se1_l2_mira, + qup_se1_l2_mirb, qup_se1_l3_mira, qup_se1_l3_mirb, qup_se2, qup_se3, + qup_se4, qup_se5, qup_se6, qup_se7, qup_se8, rgmii_rx_ctl, rgmii_rxc, + rgmii_rxd, rgmii_tx_ctl, rgmii_txc, rgmii_txd, sd_card, sdc1_tb, + sdc2_tb_trig, sec_mi2s, sgmii_phy_intr0_n, sgmii_phy_intr1_n, + spmi_coex, spmi_vgi, tgu_ch0_trigout, tmess_prng0, tmess_prng1, + tmess_prng2, tmess_prng3, tri_mi2s, uim1_clk, uim1_data, uim1_present, + uim1_reset, uim2_clk, uim2_data, uim2_present, uim2_reset, + usb2phy_ac_en, vsense_trigger_mirnat] + + required: + - pins + +required: + - compatible + - reg + +additionalProperties: false + +examples: + - | + #include + tlmm: pinctrl@f100000 { + compatible = "qcom,sdx75-tlmm"; + reg = <0x0f100000 0x300000>; + gpio-controller; + #gpio-cells = <2>; + gpio-ranges = <&tlmm 0 0 133>; + interrupt-controller; + #interrupt-cells = <2>; + interrupts = ; + + gpio-wo-state { + pins = "gpio1"; + function = "gpio"; + }; + + uart-w-state { + rx-pins { + pins = "gpio12"; + function = "qup_se1_l2_mira"; + bias-disable; + }; + + tx-pins { + pins = "gpio13"; + function = "qup_se1_l3_mira"; + bias-disable; + }; + }; + }; +... diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,sm7150-tlmm.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,sm7150-tlmm.yaml index a57d44efe5bd9a610b8183e1d8226811fcba49b1..ede0f3acad9c4f046728b179a2ce5fda63233a78 100644 --- a/Documentation/devicetree/bindings/pinctrl/qcom,sm7150-tlmm.yaml +++ b/Documentation/devicetree/bindings/pinctrl/qcom,sm7150-tlmm.yaml @@ -62,6 +62,7 @@ $defs: Pinctrl node's client devices use subnodes for desired pin configuration. Client device subnodes use below standard properties. $ref: qcom,tlmm-common.yaml#/$defs/qcom-tlmm-state + unevaluatedProperties: false properties: pins: @@ -102,19 +103,9 @@ $defs: wlan1_adc0, wlan1_adc1, wlan2_adc0, wlan2_adc1, wsa_clk, wsa_data ] - bias-pull-down: true - bias-pull-up: true - bias-disable: true - drive-strength: true - input-enable: true - output-high: true - output-low: true - required: - pins - additionalProperties: false - required: - compatible - reg diff --git a/Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.yaml index 1ab0f8dde4770ce636ea0ee7f722fc8f61c3d3bb..2120ef71a78d908f9ea82b3dbd81d492616abea3 100644 --- a/Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.yaml +++ b/Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.yaml @@ -27,6 +27,8 @@ properties: - st,stm32mp135-pinctrl - st,stm32mp157-pinctrl - st,stm32mp157-z-pinctrl + - st,stm32mp257-pinctrl + - st,stm32mp257-z-pinctrl '#address-cells': const: 1 @@ -56,7 +58,7 @@ properties: Indicates the SOC package used. More details in include/dt-bindings/pinctrl/stm32-pinfunc.h $ref: /schemas/types.yaml#/definitions/uint32 - enum: [1, 2, 4, 8] + enum: [0x1, 0x2, 0x4, 0x8, 0x100, 0x400, 0x800] patternProperties: '^gpio@[0-9a-f]*$': diff --git a/Documentation/devicetree/bindings/pinctrl/xlnx,zynq-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/xlnx,zynq-pinctrl.yaml index 598a042850b8974e60d40e2b34657f1a071a094a..b85f9e36ce4b77fb084d648e56d96dac67bece9e 100644 --- a/Documentation/devicetree/bindings/pinctrl/xlnx,zynq-pinctrl.yaml +++ b/Documentation/devicetree/bindings/pinctrl/xlnx,zynq-pinctrl.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Xilinx Zynq Pinctrl maintainers: - - Sai Krishna Potthuri + - Sai Krishna Potthuri description: | Please refer to pinctrl-bindings.txt in this directory for details of the diff --git a/Documentation/devicetree/bindings/pinctrl/xlnx,zynqmp-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/xlnx,zynqmp-pinctrl.yaml index 2722dc7bb03daaf05e4b66a13395a51acda92427..24ad0614e61b66065152f8c74c5583c887852959 100644 --- a/Documentation/devicetree/bindings/pinctrl/xlnx,zynqmp-pinctrl.yaml +++ b/Documentation/devicetree/bindings/pinctrl/xlnx,zynqmp-pinctrl.yaml @@ -7,8 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Xilinx ZynqMP Pinctrl maintainers: - - Sai Krishna Potthuri - - Rajan Vaja + - Sai Krishna Potthuri description: | Please refer to pinctrl-bindings.txt in this directory for details of the diff --git a/Documentation/devicetree/bindings/power/reset/atmel,at91sam9260-shdwc.yaml b/Documentation/devicetree/bindings/power/reset/atmel,at91sam9260-shdwc.yaml new file mode 100644 index 0000000000000000000000000000000000000000..f559a2cfd82ea2d732660cb67a22c32640cc9a60 --- /dev/null +++ b/Documentation/devicetree/bindings/power/reset/atmel,at91sam9260-shdwc.yaml @@ -0,0 +1,82 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/power/reset/atmel,at91sam9260-shdwc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Microchip AT91 SHDWC Shutdown Controller + +maintainers: + - Claudiu Beznea + +description: | + Microchip AT91 SHDWC shutdown controller controls the power supplies VDDIO + and VDDCORE and the wake-up detection on debounced input lines. + +properties: + compatible: + enum: + - atmel,at91sam9260-shdwc + - atmel,at91sam9rl-shdwc + - atmel,at91sam9x5-shdwc + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + + atmel,wakeup-mode: + description: operation mode of the wakeup mode + $ref: /schemas/types.yaml#/definitions/string + enum: [ none, high, low, any ] + + atmel,wakeup-counter: + description: counter on wake-up 0 + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0 + maximum: 15 + + atmel,wakeup-rtt-timer: + description: enable real-time timer wake-up + type: boolean + + atmel,wakeup-rtc-timer: + description: enable real-time clock wake-up + type: boolean + +required: + - compatible + - reg + - clocks + +allOf: + - if: + properties: + compatible: + contains: + const: atmel,at91sam9x5-shdwc + then: + properties: + atmel,wakeup-rtt-timer: false + + - if: + properties: + compatible: + contains: + const: atmel,at91sam9260-shdwc + then: + properties: + atmel,wakeup-rtc-timer: false + +additionalProperties: false + +examples: + - | + shdwc: poweroff@fffffd10 { + compatible = "atmel,at91sam9260-shdwc"; + reg = <0xfffffd10 0x10>; + clocks = <&clk32k>; + }; + +... diff --git a/Documentation/devicetree/bindings/power/reset/atmel,sama5d2-shdwc.yaml b/Documentation/devicetree/bindings/power/reset/atmel,sama5d2-shdwc.yaml new file mode 100644 index 0000000000000000000000000000000000000000..8c58e12cdb600e2f948921d50fa641dd52e9bb6e --- /dev/null +++ b/Documentation/devicetree/bindings/power/reset/atmel,sama5d2-shdwc.yaml @@ -0,0 +1,114 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/power/reset/atmel,sama5d2-shdwc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Microchip AT91 SAMA5D2 SHDWC Shutdown Controller + +maintainers: + - Claudiu Beznea + +description: | + Microchip AT91 SHDWC shutdown controller controls the power supplies VDDIO + and VDDCORE and the wake-up detection on debounced input lines. + +properties: + compatible: + oneOf: + - items: + - const: microchip,sama7g5-shdwc + - const: syscon + - enum: + - atmel,sama5d2-shdwc + - microchip,sam9x60-shdwc + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + + "#address-cells": + const: 1 + + "#size-cells": + const: 0 + + debounce-delay-us: + description: + Minimum wake-up inputs debouncer period in microseconds. It is usually a + board-related property. + + atmel,wakeup-rtc-timer: + description: enable real-time clock wake-up + type: boolean + + atmel,wakeup-rtt-timer: + description: enable real-time timer wake-up + type: boolean + +patternProperties: + "^input@[0-15]$": + description: + Wake-up input nodes. These are usually described in the "board" part of + the Device Tree. Note also that input 0 is linked to the wake-up pin and + is frequently used. + type: object + properties: + reg: + description: contains the wake-up input index + minimum: 0 + maximum: 15 + + atmel,wakeup-active-high: + description: + The corresponding wake-up input described by the child forces the + wake-up of the core power supply on a high level. The default is to + be active low. + type: boolean + + required: + - reg + + additionalProperties: false + +required: + - compatible + - reg + - clocks + +allOf: + - if: + properties: + compatible: + contains: + const: atmel,sama5d2-shdwc + then: + properties: + atmel,wakeup-rtt-timer: false + +additionalProperties: false + +examples: + - | + shdwc: poweroff@f8048010 { + compatible = "atmel,sama5d2-shdwc"; + reg = <0xf8048010 0x10>; + clocks = <&clk32k>; + #address-cells = <1>; + #size-cells = <0>; + atmel,wakeup-rtc-timer; + debounce-delay-us = <976>; + + input@0 { + reg = <0>; + }; + + input@1 { + reg = <1>; + atmel,wakeup-active-high; + }; + }; + +... diff --git a/Documentation/devicetree/bindings/power/reset/brcm,bcm21664-resetmgr.txt b/Documentation/devicetree/bindings/power/reset/brcm,bcm21664-resetmgr.txt deleted file mode 100644 index 93f31ca1ef4b30db647a4341a8d8181ace8c2dc3..0000000000000000000000000000000000000000 --- a/Documentation/devicetree/bindings/power/reset/brcm,bcm21664-resetmgr.txt +++ /dev/null @@ -1,14 +0,0 @@ -Broadcom Kona Family Reset Manager ----------------------------------- - -The reset manager is used on the Broadcom BCM21664 SoC. - -Required properties: - - compatible: brcm,bcm21664-resetmgr - - reg: memory address & range - -Example: - brcm,resetmgr@35001f00 { - compatible = "brcm,bcm21664-resetmgr"; - reg = <0x35001f00 0x24>; - }; diff --git a/Documentation/devicetree/bindings/power/reset/brcm,bcm21664-resetmgr.yaml b/Documentation/devicetree/bindings/power/reset/brcm,bcm21664-resetmgr.yaml new file mode 100644 index 0000000000000000000000000000000000000000..3e28a59d718fc6afbc93e0782ef566551ca19d3f --- /dev/null +++ b/Documentation/devicetree/bindings/power/reset/brcm,bcm21664-resetmgr.yaml @@ -0,0 +1,31 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/power/reset/brcm,bcm21664-resetmgr.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Broadcom Kona family reset manager + +maintainers: + - Florian Fainelli + +properties: + compatible: + const: brcm,bcm21664-resetmgr + + reg: + maxItems: 1 + +required: + - compatible + - reg + +additionalProperties: false + +examples: + - | + reset-controller@35001f00 { + compatible = "brcm,bcm21664-resetmgr"; + reg = <0x35001f00 0x24>; + }; +... diff --git a/Documentation/devicetree/bindings/power/reset/nvmem-reboot-mode.txt b/Documentation/devicetree/bindings/power/reset/nvmem-reboot-mode.txt deleted file mode 100644 index 752d6126d5dab44c18e8c91200196d76b410c608..0000000000000000000000000000000000000000 --- a/Documentation/devicetree/bindings/power/reset/nvmem-reboot-mode.txt +++ /dev/null @@ -1,26 +0,0 @@ -NVMEM reboot mode driver - -This driver gets reboot mode magic value from reboot-mode driver -and stores it in a NVMEM cell named "reboot-mode". Then the bootloader -can read it and take different action according to the magic -value stored. - -Required properties: -- compatible: should be "nvmem-reboot-mode". -- nvmem-cells: A phandle to the reboot mode provided by a nvmem device. -- nvmem-cell-names: Should be "reboot-mode". - -The rest of the properties should follow the generic reboot-mode description -found in reboot-mode.txt - -Example: - reboot-mode { - compatible = "nvmem-reboot-mode"; - nvmem-cells = <&reboot_mode>; - nvmem-cell-names = "reboot-mode"; - - mode-normal = <0xAAAA5501>; - mode-bootloader = <0xBBBB5500>; - mode-recovery = <0xCCCC5502>; - mode-test = <0xDDDD5503>; - }; diff --git a/Documentation/devicetree/bindings/power/reset/nvmem-reboot-mode.yaml b/Documentation/devicetree/bindings/power/reset/nvmem-reboot-mode.yaml new file mode 100644 index 0000000000000000000000000000000000000000..14a262bcbf7cd21ebf62ee02f738bf82cbde80e1 --- /dev/null +++ b/Documentation/devicetree/bindings/power/reset/nvmem-reboot-mode.yaml @@ -0,0 +1,52 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/power/reset/nvmem-reboot-mode.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Generic NVMEM reboot mode + +maintainers: + - Bartosz Golaszewski + +description: + This driver gets the reboot mode magic value from the reboot-mode driver + and stores it in the NVMEM cell named "reboot-mode". The bootloader can + then read it and take different action according to the value. + +properties: + compatible: + const: nvmem-reboot-mode + + nvmem-cells: + description: + A phandle pointing to the nvmem-cells node where the vendor-specific + magic value representing the reboot mode is stored. + maxItems: 1 + + nvmem-cell-names: + items: + - const: reboot-mode + +patternProperties: + "^mode-.+": + $ref: /schemas/types.yaml#/definitions/uint32 + description: Vendor-specific mode value written to the mode register + +required: + - compatible + - nvmem-cells + - nvmem-cell-names + +additionalProperties: false + +examples: + - | + reboot-mode { + compatible = "nvmem-reboot-mode"; + nvmem-cells = <&reboot_reason>; + nvmem-cell-names = "reboot-mode"; + mode-recovery = <0x01>; + mode-bootloader = <0x02>; + }; +... diff --git a/Documentation/devicetree/bindings/power/reset/qcom,pon.yaml b/Documentation/devicetree/bindings/power/reset/qcom,pon.yaml index d96170eecbd228bd95e6957bb8187af2a4b2e57a..5e460128b0d10911a541c959a9581efcb8b4d393 100644 --- a/Documentation/devicetree/bindings/power/reset/qcom,pon.yaml +++ b/Documentation/devicetree/bindings/power/reset/qcom,pon.yaml @@ -19,6 +19,7 @@ properties: compatible: enum: - qcom,pm8916-pon + - qcom,pm8941-pon - qcom,pms405-pon - qcom,pm8998-pon - qcom,pmk8350-pon @@ -56,7 +57,6 @@ required: unevaluatedProperties: false allOf: - - $ref: reboot-mode.yaml# - if: properties: compatible: @@ -65,6 +65,23 @@ allOf: - qcom,pm8916-pon - qcom,pms405-pon - qcom,pm8998-pon + then: + allOf: + - $ref: reboot-mode.yaml# + + properties: + reg: + maxItems: 1 + reg-names: + items: + - const: pon + + # Special case for pm8941, which doesn't store reset mode + - if: + properties: + compatible: + contains: + const: qcom,pm8941-pon then: properties: reg: @@ -72,6 +89,7 @@ allOf: reg-names: items: - const: pon + - if: properties: compatible: diff --git a/Documentation/devicetree/bindings/power/reset/restart-handler.yaml b/Documentation/devicetree/bindings/power/reset/restart-handler.yaml index 1f9a2aac53c08176c91227604af5b35c4f17dc0e..f2ffdd29d52ac50d4f603363a04f3ab6632a7f74 100644 --- a/Documentation/devicetree/bindings/power/reset/restart-handler.yaml +++ b/Documentation/devicetree/bindings/power/reset/restart-handler.yaml @@ -4,7 +4,7 @@ $id: http://devicetree.org/schemas/power/reset/restart-handler.yaml# $schema: http://devicetree.org/meta-schemas/core.yaml# -title: Restart and shutdown handler generic binding +title: Restart and shutdown handler Common Properties maintainers: - Sebastian Reichel diff --git a/Documentation/devicetree/bindings/power/reset/xlnx,zynqmp-power.yaml b/Documentation/devicetree/bindings/power/reset/xlnx,zynqmp-power.yaml index 11f1f98c1cdc1bd9c357306aa3f794819be39825..45792e216981a99de457cc99ea2d8f2dfd130136 100644 --- a/Documentation/devicetree/bindings/power/reset/xlnx,zynqmp-power.yaml +++ b/Documentation/devicetree/bindings/power/reset/xlnx,zynqmp-power.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Xilinx Zynq MPSoC Power Management maintainers: - - Michal Simek + - Michal Simek description: | The zynqmp-power node describes the power management configurations. diff --git a/Documentation/devicetree/bindings/power/supply/bq256xx.yaml b/Documentation/devicetree/bindings/power/supply/bq256xx.yaml index 82f382a7ffb36fd23a6b9939c684562cec851d4d..4fe9c37052652c93e91ad5f0cd9f6f33807e517b 100644 --- a/Documentation/devicetree/bindings/power/supply/bq256xx.yaml +++ b/Documentation/devicetree/bindings/power/supply/bq256xx.yaml @@ -68,11 +68,29 @@ properties: Interrupt sends an active low, 256 μs pulse to host to report the charger device status and faults. + ti,no-thermistor: + type: boolean + description: Indicates that no thermistor is connected to the TS pin + required: - compatible - reg - monitored-battery +allOf: + - if: + properties: + compatible: + contains: + enum: + - ti,bq25600 + - ti,bq25601 + - ti,bq25600d + - ti,bq25601d + then: + properties: + ti,no-thermistor: false + additionalProperties: false examples: diff --git a/Documentation/devicetree/bindings/power/supply/qcom,pmi8998-charger.yaml b/Documentation/devicetree/bindings/power/supply/qcom,pmi8998-charger.yaml new file mode 100644 index 0000000000000000000000000000000000000000..277c47e048b654a01c7e8b8080cb0644fee8bd82 --- /dev/null +++ b/Documentation/devicetree/bindings/power/supply/qcom,pmi8998-charger.yaml @@ -0,0 +1,82 @@ +# SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/power/supply/qcom,pmi8998-charger.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm PMI8998/PM660 Switch-Mode Battery Charger "2" + +maintainers: + - Caleb Connolly + +properties: + compatible: + enum: + - qcom,pmi8998-charger + - qcom,pm660-charger + + reg: + maxItems: 1 + + interrupts: + maxItems: 4 + + interrupt-names: + items: + - const: usb-plugin + - const: bat-ov + - const: wdog-bark + - const: usbin-icl-change + + io-channels: + items: + - description: USB in current in uA + - description: USB in voltage in uV + + io-channel-names: + items: + - const: usbin_i + - const: usbin_v + + monitored-battery: + description: phandle to the simple-battery node + $ref: /schemas/types.yaml#/definitions/phandle + +required: + - compatible + - reg + - interrupts + - interrupt-names + - io-channels + - io-channel-names + - monitored-battery + +additionalProperties: false + +examples: + - | + #include + + pmic { + #address-cells = <1>; + #size-cells = <0>; + #interrupt-cells = <4>; + + charger@1000 { + compatible = "qcom,pmi8998-charger"; + reg = <0x1000>; + + interrupts = <0x2 0x12 0x2 IRQ_TYPE_EDGE_BOTH>, + <0x2 0x13 0x4 IRQ_TYPE_EDGE_BOTH>, + <0x2 0x13 0x6 IRQ_TYPE_EDGE_RISING>, + <0x2 0x16 0x1 IRQ_TYPE_EDGE_RISING>; + interrupt-names = "usb-plugin", "bat-ov", "wdog-bark", "usbin-icl-change"; + + io-channels = <&pmi8998_rradc 3>, + <&pmi8998_rradc 4>; + io-channel-names = "usbin_i", + "usbin_v"; + + monitored-battery = <&battery>; + }; + }; diff --git a/Documentation/devicetree/bindings/power/supply/richtek,rt5033-battery.yaml b/Documentation/devicetree/bindings/power/supply/richtek,rt5033-battery.yaml index 756c16d1727dbb953bff22368bb329ae77f09f8e..b5d8888d03d20aeb3c9585e3cb4db114c65a9bd4 100644 --- a/Documentation/devicetree/bindings/power/supply/richtek,rt5033-battery.yaml +++ b/Documentation/devicetree/bindings/power/supply/richtek,rt5033-battery.yaml @@ -26,7 +26,7 @@ required: - compatible - reg -additionalProperties: false +unevaluatedProperties: false examples: - | diff --git a/Documentation/devicetree/bindings/power/supply/richtek,rt5033-charger.yaml b/Documentation/devicetree/bindings/power/supply/richtek,rt5033-charger.yaml new file mode 100644 index 0000000000000000000000000000000000000000..5b3edd79a523ff7f8f04cadc425c208a63cd8f85 --- /dev/null +++ b/Documentation/devicetree/bindings/power/supply/richtek,rt5033-charger.yaml @@ -0,0 +1,65 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/power/supply/richtek,rt5033-charger.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Richtek RT5033 PMIC Battery Charger + +maintainers: + - Jakob Hauser + +description: + The battery charger of the multifunction device RT5033 has to be instantiated + under sub-node named "charger" using the following format. + +properties: + compatible: + const: richtek,rt5033-charger + + monitored-battery: + $ref: /schemas/types.yaml#/definitions/phandle + description: | + Phandle to the monitored battery according to battery.yaml. The battery + node needs to contain five parameters. + + precharge-current-microamp: + Current of pre-charge mode. The pre-charge current levels are 350 mA + to 650 mA programmed by I2C per 100 mA. + + constant-charge-current-max-microamp: + Current of fast-charge mode. The fast-charge current levels are 700 mA + to 2000 mA programmed by I2C per 100 mA. + + charge-term-current-microamp: + This property is end of charge current. Its level ranges from 150 mA + to 600 mA. Between 150 mA and 300 mA in 50 mA steps, between 300 mA and + 600 mA in 100 mA steps. + + precharge-upper-limit-microvolt: + Voltage of pre-charge mode. If the battery voltage is below the pre-charge + threshold voltage, the charger is in pre-charge mode with pre-charge + current. Its levels are 2.3 V to 3.8 V programmed by I2C per 0.1 V. + + constant-charge-voltage-max-microvolt: + Battery regulation voltage of constant voltage mode. This voltage levels + from 3.65 V to 4.4 V by I2C per 0.025 V. + + richtek,usb-connector: + $ref: /schemas/types.yaml#/definitions/phandle + description: + Phandle to a USB connector according to usb-connector.yaml. The connector + should be a child of the extcon device. + +required: + - monitored-battery + +additionalProperties: false + +examples: + - | + charger { + compatible = "richtek,rt5033-charger"; + monitored-battery = <&battery>; + richtek,usb-connector = <&usb_con>; + }; diff --git a/Documentation/devicetree/bindings/power/supply/x-powers,axp20x-usb-power-supply.yaml b/Documentation/devicetree/bindings/power/supply/x-powers,axp20x-usb-power-supply.yaml index 3ce648dd91bd334853737d2b896c27415a9e911c..34b7959d6772f0efadb93d8b86217f9020ee5a54 100644 --- a/Documentation/devicetree/bindings/power/supply/x-powers,axp20x-usb-power-supply.yaml +++ b/Documentation/devicetree/bindings/power/supply/x-powers,axp20x-usb-power-supply.yaml @@ -22,6 +22,7 @@ properties: compatible: oneOf: - enum: + - x-powers,axp192-usb-power-supply - x-powers,axp202-usb-power-supply - x-powers,axp221-usb-power-supply - x-powers,axp223-usb-power-supply diff --git a/Documentation/devicetree/bindings/pwm/atmel,at91sam-pwm.yaml b/Documentation/devicetree/bindings/pwm/atmel,at91sam-pwm.yaml index ab45df80345de710b0af7e942f591c0571f5943b..d84268b59784ff8c3036d9fc593b82e1984424e6 100644 --- a/Documentation/devicetree/bindings/pwm/atmel,at91sam-pwm.yaml +++ b/Documentation/devicetree/bindings/pwm/atmel,at91sam-pwm.yaml @@ -11,7 +11,7 @@ maintainers: - Claudiu Beznea allOf: - - $ref: "pwm.yaml#" + - $ref: pwm.yaml# properties: compatible: diff --git a/Documentation/devicetree/bindings/pwm/imx-pwm.yaml b/Documentation/devicetree/bindings/pwm/imx-pwm.yaml index b3da4e629341c03960896f5b7542ec7bcdc1d111..c01dff3b7f843eba22f21d556f9f316bbffa757a 100644 --- a/Documentation/devicetree/bindings/pwm/imx-pwm.yaml +++ b/Documentation/devicetree/bindings/pwm/imx-pwm.yaml @@ -43,6 +43,7 @@ properties: - fsl,imx8mn-pwm - fsl,imx8mp-pwm - fsl,imx8mq-pwm + - fsl,imx8qxp-pwm - const: fsl,imx27-pwm reg: @@ -61,6 +62,9 @@ properties: interrupts: maxItems: 1 + power-domains: + maxItems: 1 + required: - compatible - reg diff --git a/Documentation/devicetree/bindings/pwm/mediatek,mt2712-pwm.yaml b/Documentation/devicetree/bindings/pwm/mediatek,mt2712-pwm.yaml index 8e176ba7a525fcd0795e0c40c96b6615e00bc197..0fbe8a6469eb22a6c609e5b7b01edd6078fcee7a 100644 --- a/Documentation/devicetree/bindings/pwm/mediatek,mt2712-pwm.yaml +++ b/Documentation/devicetree/bindings/pwm/mediatek,mt2712-pwm.yaml @@ -22,6 +22,7 @@ properties: - mediatek,mt7623-pwm - mediatek,mt7628-pwm - mediatek,mt7629-pwm + - mediatek,mt7981-pwm - mediatek,mt7986-pwm - mediatek,mt8183-pwm - mediatek,mt8365-pwm diff --git a/Documentation/devicetree/bindings/pwm/mediatek,pwm-disp.yaml b/Documentation/devicetree/bindings/pwm/mediatek,pwm-disp.yaml index 0088bc8e7c541a3c6ba7001c06e93bb88a6586ac..153e146df7d4b24af4de004369f372585b9d93ff 100644 --- a/Documentation/devicetree/bindings/pwm/mediatek,pwm-disp.yaml +++ b/Documentation/devicetree/bindings/pwm/mediatek,pwm-disp.yaml @@ -22,7 +22,9 @@ properties: - mediatek,mt8173-disp-pwm - mediatek,mt8183-disp-pwm - items: - - const: mediatek,mt8167-disp-pwm + - enum: + - mediatek,mt6795-disp-pwm + - mediatek,mt8167-disp-pwm - const: mediatek,mt8173-disp-pwm - items: - enum: diff --git a/Documentation/devicetree/bindings/pwm/mxs-pwm.yaml b/Documentation/devicetree/bindings/pwm/mxs-pwm.yaml index a34cbc13f691c5765577fba1311d060ed2c1c72c..6ffbed204c259def8204c7c7a7a837c99190b3b6 100644 --- a/Documentation/devicetree/bindings/pwm/mxs-pwm.yaml +++ b/Documentation/devicetree/bindings/pwm/mxs-pwm.yaml @@ -25,7 +25,7 @@ properties: const: 3 fsl,pwm-number: - $ref: '/schemas/types.yaml#/definitions/uint32' + $ref: /schemas/types.yaml#/definitions/uint32 description: u32 value representing the number of PWM devices required: diff --git a/Documentation/devicetree/bindings/pwm/pwm-bcm2835.txt b/Documentation/devicetree/bindings/pwm/pwm-bcm2835.txt deleted file mode 100644 index f5753b3f79df1303bee184c0fb03fd4841d45ad4..0000000000000000000000000000000000000000 --- a/Documentation/devicetree/bindings/pwm/pwm-bcm2835.txt +++ /dev/null @@ -1,30 +0,0 @@ -BCM2835 PWM controller (Raspberry Pi controller) - -Required properties: -- compatible: should be "brcm,bcm2835-pwm" -- reg: physical base address and length of the controller's registers -- clocks: This clock defines the base clock frequency of the PWM hardware - system, the period and the duty_cycle of the PWM signal is a multiple of - the base period. -- #pwm-cells: Should be 3. See pwm.yaml in this directory for a description of - the cells format. - -Examples: - -pwm@2020c000 { - compatible = "brcm,bcm2835-pwm"; - reg = <0x2020c000 0x28>; - clocks = <&clk_pwm>; - #pwm-cells = <3>; -}; - -clocks { - .... - clk_pwm: pwm { - compatible = "fixed-clock"; - reg = <3>; - #clock-cells = <0>; - clock-frequency = <9200000>; - }; - .... -}; diff --git a/Documentation/devicetree/bindings/pwm/pwm-bcm2835.yaml b/Documentation/devicetree/bindings/pwm/pwm-bcm2835.yaml new file mode 100644 index 0000000000000000000000000000000000000000..15e7fd98defc842ed29620ee8f8c51cfe187a9ea --- /dev/null +++ b/Documentation/devicetree/bindings/pwm/pwm-bcm2835.yaml @@ -0,0 +1,43 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/pwm/pwm-bcm2835.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: BCM2835 PWM controller (Raspberry Pi controller) + +maintainers: + - Stefan Wahren + +allOf: + - $ref: pwm.yaml# + +properties: + compatible: + const: brcm,bcm2835-pwm + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + + "#pwm-cells": + const: 3 + +required: + - compatible + - reg + - clocks + - "#pwm-cells" + +additionalProperties: false + +examples: + - | + pwm@2020c000 { + compatible = "brcm,bcm2835-pwm"; + reg = <0x2020c000 0x28>; + clocks = <&clk_pwm>; + #pwm-cells = <3>; + }; diff --git a/Documentation/devicetree/bindings/pwm/pwm.yaml b/Documentation/devicetree/bindings/pwm/pwm.yaml index 3c01f85029e559350c5505e0b44c86ddf2f7afc8..abd9fa873354e2d7b3768279b08037482a3eaae3 100644 --- a/Documentation/devicetree/bindings/pwm/pwm.yaml +++ b/Documentation/devicetree/bindings/pwm/pwm.yaml @@ -13,7 +13,7 @@ select: false properties: $nodename: - pattern: "^pwm(@.*|-[0-9a-f])*$" + pattern: "^pwm(@.*|-([0-9]|[1-9][0-9]+))?$" "#pwm-cells": description: diff --git a/Documentation/devicetree/bindings/pwm/renesas,pwm-rcar.yaml b/Documentation/devicetree/bindings/pwm/renesas,pwm-rcar.yaml index 4c80970106877e55bad9b61ad84231177b495b45..6b6a302a175ceb1040ac9fe8b60365776c26fb8f 100644 --- a/Documentation/devicetree/bindings/pwm/renesas,pwm-rcar.yaml +++ b/Documentation/devicetree/bindings/pwm/renesas,pwm-rcar.yaml @@ -35,6 +35,7 @@ properties: - renesas,pwm-r8a77980 # R-Car V3H - renesas,pwm-r8a77990 # R-Car E3 - renesas,pwm-r8a77995 # R-Car D3 + - renesas,pwm-r8a779a0 # R-Car V3U - renesas,pwm-r8a779g0 # R-Car V4H - const: renesas,pwm-rcar diff --git a/Documentation/devicetree/bindings/regulator/adi,max77541-regulator.yaml b/Documentation/devicetree/bindings/regulator/adi,max77541-regulator.yaml new file mode 100644 index 0000000000000000000000000000000000000000..9e36d5467b569a5563c79ecc31eee764b36945df --- /dev/null +++ b/Documentation/devicetree/bindings/regulator/adi,max77541-regulator.yaml @@ -0,0 +1,38 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/regulator/adi,max77541-regulator.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Buck Converter for MAX77540/MAX77541 + +maintainers: + - Okan Sahin + +description: | + This is a part of device tree bindings for ADI MAX77540/MAX77541 + + The buck converter is represented as a sub-node of the PMIC node on the device tree. + + The device has two buck regulators. + See also Documentation/devicetree/bindings/mfd/adi,max77541.yaml for + additional information and example. + +patternProperties: + "^buck[12]$": + type: object + $ref: regulator.yaml# + additionalProperties: false + description: | + Buck regulator. + + properties: + regulator-name: true + regulator-always-on: true + regulator-boot-on: true + regulator-min-microvolt: + minimum: 300000 + regulator-max-microvolt: + maximum: 5200000 + +additionalProperties: false diff --git a/Documentation/devicetree/bindings/regulator/mt6358-regulator.txt b/Documentation/devicetree/bindings/regulator/mt6358-regulator.txt index 7034cdca54e04f0e29228ef456f1456799c71f68..b6384306db5c689a471397a9428bc40d69f44cf3 100644 --- a/Documentation/devicetree/bindings/regulator/mt6358-regulator.txt +++ b/Documentation/devicetree/bindings/regulator/mt6358-regulator.txt @@ -8,15 +8,14 @@ Documentation/devicetree/bindings/regulator/regulator.txt. The valid names for regulators are:: BUCK: - buck_vdram1, buck_vcore, buck_vcore_sshub, buck_vpa, buck_vproc11, - buck_vproc12, buck_vgpu, buck_vs2, buck_vmodem, buck_vs1 + buck_vdram1, buck_vcore, buck_vpa, buck_vproc11, buck_vproc12, buck_vgpu, + buck_vs2, buck_vmodem, buck_vs1 LDO: ldo_vdram2, ldo_vsim1, ldo_vibr, ldo_vrf12, ldo_vio18, ldo_vusb, ldo_vcamio, ldo_vcamd, ldo_vcn18, ldo_vfe28, ldo_vsram_proc11, ldo_vcn28, ldo_vsram_others, - ldo_vsram_others_sshub, ldo_vsram_gpu, ldo_vxo22, ldo_vefuse, ldo_vaux18, - ldo_vmch, ldo_vbif28, ldo_vsram_proc12, ldo_vcama1, ldo_vemc, ldo_vio28, ldo_va12, - ldo_vrf18, ldo_vcn33_bt, ldo_vcn33_wifi, ldo_vcama2, ldo_vmc, ldo_vldo28, ldo_vaud28, - ldo_vsim2 + ldo_vsram_gpu, ldo_vxo22, ldo_vefuse, ldo_vaux18, ldo_vmch, ldo_vbif28, + ldo_vsram_proc12, ldo_vcama1, ldo_vemc, ldo_vio28, ldo_va12, ldo_vrf18, + ldo_vcn33, ldo_vcama2, ldo_vmc, ldo_vldo28, ldo_vaud28, ldo_vsim2 Example: @@ -305,15 +304,8 @@ Example: regulator-enable-ramp-delay = <120>; }; - mt6358_vcn33_bt_reg: ldo_vcn33_bt { - regulator-name = "vcn33_bt"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3500000>; - regulator-enable-ramp-delay = <270>; - }; - - mt6358_vcn33_wifi_reg: ldo_vcn33_wifi { - regulator-name = "vcn33_wifi"; + mt6358_vcn33_reg: ldo_vcn33 { + regulator-name = "vcn33"; regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3500000>; regulator-enable-ramp-delay = <270>; @@ -354,17 +346,5 @@ Example: regulator-max-microvolt = <3100000>; regulator-enable-ramp-delay = <540>; }; - - mt6358_vcore_sshub_reg: buck_vcore_sshub { - regulator-name = "vcore_sshub"; - regulator-min-microvolt = <500000>; - regulator-max-microvolt = <1293750>; - }; - - mt6358_vsram_others_sshub_reg: ldo_vsram_others_sshub { - regulator-name = "vsram_others_sshub"; - regulator-min-microvolt = <500000>; - regulator-max-microvolt = <1293750>; - }; }; }; diff --git a/Documentation/devicetree/bindings/regulator/pfuze100.yaml b/Documentation/devicetree/bindings/regulator/pfuze100.yaml index 67a30b23b92c6a6721d67252a121b5b5709a7aa0..e384e4953f0a71643c585cded806e05a369319ed 100644 --- a/Documentation/devicetree/bindings/regulator/pfuze100.yaml +++ b/Documentation/devicetree/bindings/regulator/pfuze100.yaml @@ -36,6 +36,9 @@ properties: reg: maxItems: 1 + interrupts: + maxItems: 1 + fsl,pfuze-support-disable-sw: $ref: /schemas/types.yaml#/definitions/flag description: | diff --git a/Documentation/devicetree/bindings/regulator/pwm-regulator.yaml b/Documentation/devicetree/bindings/regulator/pwm-regulator.yaml index 7e58471097f8c70e2b6e8d806f533e7530cff8e7..80ecf938b74933fd836c9bab0d5e75cf039ebbf3 100644 --- a/Documentation/devicetree/bindings/regulator/pwm-regulator.yaml +++ b/Documentation/devicetree/bindings/regulator/pwm-regulator.yaml @@ -64,6 +64,7 @@ properties: defined, <100> is assumed, meaning that pwm-dutycycle-range contains values expressed in percent. + $ref: /schemas/types.yaml#/definitions/uint32 default: 100 pwm-dutycycle-range: diff --git a/Documentation/devicetree/bindings/regulator/qcom,usb-vbus-regulator.yaml b/Documentation/devicetree/bindings/regulator/qcom,usb-vbus-regulator.yaml index b1cff3adb21b5bd776a9f3e028cdda364cc6361c..89c564dfa5db5a93acaa8ac3b013acd564cd5202 100644 --- a/Documentation/devicetree/bindings/regulator/qcom,usb-vbus-regulator.yaml +++ b/Documentation/devicetree/bindings/regulator/qcom,usb-vbus-regulator.yaml @@ -14,6 +14,9 @@ description: | regulator will be enabled in situations where the device is required to provide power to the connected peripheral. +allOf: + - $ref: regulator.yaml# + properties: compatible: enum: @@ -25,8 +28,11 @@ properties: required: - compatible + - reg + - regulator-min-microamp + - regulator-max-microamp -additionalProperties: false +unevaluatedProperties: false examples: - | @@ -36,6 +42,8 @@ examples: pm8150b_vbus: usb-vbus-regulator@1100 { compatible = "qcom,pm8150b-vbus-reg"; reg = <0x1100>; + regulator-min-microamp = <500000>; + regulator-max-microamp = <3000000>; }; }; ... diff --git a/Documentation/devicetree/bindings/regulator/renesas,raa215300.yaml b/Documentation/devicetree/bindings/regulator/renesas,raa215300.yaml new file mode 100644 index 0000000000000000000000000000000000000000..97cff71d29677f3ffa3e80aa75e5409bfcb90408 --- /dev/null +++ b/Documentation/devicetree/bindings/regulator/renesas,raa215300.yaml @@ -0,0 +1,85 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/regulator/renesas,raa215300.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Renesas RAA215300 Power Management Integrated Circuit (PMIC) + +maintainers: + - Biju Das + +description: | + The RAA215300 is a high-performance, low-cost 9-channel PMIC designed for + 32-bit and 64-bit MCU and MPU applications. It supports DDR3, DDR3L, DDR4, + and LPDDR4 memory power requirements. The internally compensated regulators, + built-in Real-Time Clock (RTC), 32kHz crystal oscillator, and coin cell + battery charger provide a highly integrated, small footprint power solution + ideal for System-On-Module (SOM) applications. A spread spectrum feature + provides an ease-of-use solution for noise-sensitive audio or RF applications. + + This device exposes two devices via I2C. One for the integrated RTC IP, and + one for everything else. + + Link to datasheet: + https://www.renesas.com/in/en/products/power-power-management/multi-channel-power-management-ics-pmics/ssdsoc-power-management-ics-pmic-and-pmus/raa215300-high-performance-9-channel-pmic-supporting-ddr-memory-built-charger-and-rtc + +properties: + compatible: + enum: + - renesas,raa215300 + + reg: + maxItems: 2 + + reg-names: + items: + - const: main + - const: rtc + + interrupts: + maxItems: 1 + + clocks: + description: | + The clocks are optional. The RTC is disabled, if no clocks are + provided(either xin or clkin). + maxItems: 1 + + clock-names: + description: | + Use xin, if connected to an external crystal. + Use clkin, if connected to an external clock signal. + enum: + - xin + - clkin + +required: + - compatible + - reg + - reg-names + +additionalProperties: false + +examples: + - | + /* 32.768kHz crystal */ + x2: x2-clock { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <32768>; + }; + + i2c { + #address-cells = <1>; + #size-cells = <0>; + + raa215300: pmic@12 { + compatible = "renesas,raa215300"; + reg = <0x12>, <0x6f>; + reg-names = "main", "rtc"; + + clocks = <&x2>; + clock-names = "xin"; + }; + }; diff --git a/Documentation/devicetree/bindings/regulator/ti,tps62870.yaml b/Documentation/devicetree/bindings/regulator/ti,tps62870.yaml new file mode 100644 index 0000000000000000000000000000000000000000..386989544dac99456820b7a5dfccfbf4804e7958 --- /dev/null +++ b/Documentation/devicetree/bindings/regulator/ti,tps62870.yaml @@ -0,0 +1,52 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/regulator/ti,tps62870.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: TI TPS62870/TPS62871/TPS62872/TPS62873 voltage regulator + +maintainers: + - Mårten Lindahl + +allOf: + - $ref: regulator.yaml# + +properties: + compatible: + enum: + - ti,tps62870 + - ti,tps62871 + - ti,tps62872 + - ti,tps62873 + + reg: + maxItems: 1 + + regulator-initial-mode: + enum: [ 1, 2 ] + description: 1 - Forced PWM mode, 2 - Low power mode + +required: + - compatible + - reg + +unevaluatedProperties: false + +examples: + - | + i2c { + #address-cells = <1>; + #size-cells = <0>; + + regulator@41 { + compatible = "ti,tps62873"; + reg = <0x41>; + regulator-name = "+0.75V"; + regulator-min-microvolt = <400000>; + regulator-max-microvolt = <1675000>; + regulator-initial-mode = <1>; + }; + }; + +... diff --git a/Documentation/devicetree/bindings/remoteproc/amlogic,meson-mx-ao-arc.yaml b/Documentation/devicetree/bindings/remoteproc/amlogic,meson-mx-ao-arc.yaml index 3100cb870170cecca564bd626d96000b503f1914..76e8ca44906ac24558cd38f9b7e58dcaf809d1d9 100644 --- a/Documentation/devicetree/bindings/remoteproc/amlogic,meson-mx-ao-arc.yaml +++ b/Documentation/devicetree/bindings/remoteproc/amlogic,meson-mx-ao-arc.yaml @@ -75,7 +75,7 @@ additionalProperties: false examples: - | remoteproc@1c { - compatible= "amlogic,meson8-ao-arc", "amlogic,meson-mx-ao-arc"; + compatible = "amlogic,meson8-ao-arc", "amlogic,meson-mx-ao-arc"; reg = <0x1c 0x8>, <0x38 0x8>; reg-names = "remap", "cpu"; resets = <&media_cpu_reset>; diff --git a/Documentation/devicetree/bindings/remoteproc/st,stm32-rproc.yaml b/Documentation/devicetree/bindings/remoteproc/st,stm32-rproc.yaml index 959a56f1b6c78e8e1d61cac5a29be450f27d140b..370af61d8f28033bfa25b690c786380ad8bfad97 100644 --- a/Documentation/devicetree/bindings/remoteproc/st,stm32-rproc.yaml +++ b/Documentation/devicetree/bindings/remoteproc/st,stm32-rproc.yaml @@ -25,7 +25,14 @@ properties: maxItems: 3 resets: - maxItems: 1 + minItems: 1 + maxItems: 2 + + reset-names: + items: + - const: mcu_rst + - const: hold_boot + minItems: 1 st,syscfg-holdboot: description: remote processor reset hold boot @@ -37,6 +44,7 @@ properties: - description: The field mask of the hold boot st,syscfg-tz: + deprecated: true description: Reference to the system configuration which holds the RCC trust zone mode $ref: /schemas/types.yaml#/definitions/phandle-array @@ -135,22 +143,48 @@ required: - compatible - reg - resets - - st,syscfg-holdboot - - st,syscfg-tz + +allOf: + - if: + properties: + reset-names: + not: + contains: + const: hold_boot + then: + required: + - st,syscfg-holdboot + else: + properties: + st,syscfg-holdboot: false additionalProperties: false examples: - | #include - m4_rproc: m4@10000000 { + m4@10000000 { compatible = "st,stm32mp1-m4"; reg = <0x10000000 0x40000>, <0x30000000 0x40000>, <0x38000000 0x10000>; resets = <&rcc MCU_R>; + reset-names = "mcu_rst"; + /* Hold boot managed using system config*/ st,syscfg-holdboot = <&rcc 0x10C 0x1>; - st,syscfg-tz = <&rcc 0x000 0x1>; + st,syscfg-rsc-tbl = <&tamp 0x144 0xFFFFFFFF>; + st,syscfg-m4-state = <&tamp 0x148 0xFFFFFFFF>; + }; + - | + #include + m4@10000000 { + compatible = "st,stm32mp1-m4"; + reg = <0x10000000 0x40000>, + <0x30000000 0x40000>, + <0x38000000 0x10000>; + /* Hold boot managed using SCMI reset controller */ + resets = <&scmi MCU_R>, <&scmi MCU_HOLD_BOOT_R>; + reset-names = "mcu_rst", "hold_boot"; st,syscfg-rsc-tbl = <&tamp 0x144 0xFFFFFFFF>; st,syscfg-m4-state = <&tamp 0x148 0xFFFFFFFF>; }; diff --git a/Documentation/devicetree/bindings/remoteproc/ti,pru-consumer.yaml b/Documentation/devicetree/bindings/remoteproc/ti,pru-consumer.yaml index c6d86964b72a35e5092d2c872932d390b72ea32f..35f0bb38f7b2297173633319b8c0729ec9d2c6e7 100644 --- a/Documentation/devicetree/bindings/remoteproc/ti,pru-consumer.yaml +++ b/Documentation/devicetree/bindings/remoteproc/ti,pru-consumer.yaml @@ -4,7 +4,7 @@ $id: http://devicetree.org/schemas/remoteproc/ti,pru-consumer.yaml# $schema: http://devicetree.org/meta-schemas/core.yaml# -title: Common TI PRU Consumer Binding +title: TI PRU Consumer Common Properties maintainers: - Suman Anna diff --git a/Documentation/devicetree/bindings/reserved-memory/framebuffer.yaml b/Documentation/devicetree/bindings/reserved-memory/framebuffer.yaml index 05b6648b3458e63eae0c0f256253b64d3fcbbfe6..851ec24d6142aaad10916bfdb92e0eda39b0cb08 100644 --- a/Documentation/devicetree/bindings/reserved-memory/framebuffer.yaml +++ b/Documentation/devicetree/bindings/reserved-memory/framebuffer.yaml @@ -4,7 +4,7 @@ $id: http://devicetree.org/schemas/reserved-memory/framebuffer.yaml# $schema: http://devicetree.org/meta-schemas/core.yaml# -title: /reserved-memory framebuffer node bindings +title: /reserved-memory framebuffer node maintainers: - devicetree-spec@vger.kernel.org diff --git a/Documentation/devicetree/bindings/reset/nuvoton,ma35d1-reset.yaml b/Documentation/devicetree/bindings/reset/nuvoton,ma35d1-reset.yaml new file mode 100644 index 0000000000000000000000000000000000000000..34c5c1c08ec17ec4ab7e663b92678066ca80d724 --- /dev/null +++ b/Documentation/devicetree/bindings/reset/nuvoton,ma35d1-reset.yaml @@ -0,0 +1,45 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/reset/nuvoton,ma35d1-reset.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Nuvoton MA35D1 Reset Controller + +maintainers: + - Chi-Fang Li + - Jacky Huang + +description: + The system reset controller can be used to reset various peripheral + controllers in MA35D1 SoC. + +properties: + compatible: + items: + - const: nuvoton,ma35d1-reset + + reg: + maxItems: 1 + + '#reset-cells': + const: 1 + +required: + - compatible + - reg + - '#reset-cells' + +additionalProperties: false + +examples: + # system reset controller node: + - | + + system-management@40460000 { + compatible = "nuvoton,ma35d1-reset"; + reg = <0x40460000 0x200>; + #reset-cells = <1>; + }; +... + diff --git a/Documentation/devicetree/bindings/reset/oxnas,reset.txt b/Documentation/devicetree/bindings/reset/oxnas,reset.txt deleted file mode 100644 index d27ccb5d04fc362352bbbdc1762b2a34f1bce54c..0000000000000000000000000000000000000000 --- a/Documentation/devicetree/bindings/reset/oxnas,reset.txt +++ /dev/null @@ -1,32 +0,0 @@ -Oxford Semiconductor OXNAS SoC Family RESET Controller -================================================ - -Please also refer to reset.txt in this directory for common reset -controller binding usage. - -Required properties: -- compatible: For OX810SE, should be "oxsemi,ox810se-reset" - For OX820, should be "oxsemi,ox820-reset" -- #reset-cells: 1, see below - -Parent node should have the following properties : -- compatible: For OX810SE, should be : - "oxsemi,ox810se-sys-ctrl", "syscon", "simple-mfd" - For OX820, should be : - "oxsemi,ox820-sys-ctrl", "syscon", "simple-mfd" - -Reset indices are in dt-bindings include files : -- For OX810SE: include/dt-bindings/reset/oxsemi,ox810se.h -- For OX820: include/dt-bindings/reset/oxsemi,ox820.h - -example: - -sys: sys-ctrl@000000 { - compatible = "oxsemi,ox810se-sys-ctrl", "syscon", "simple-mfd"; - reg = <0x000000 0x100000>; - - reset: reset-controller { - compatible = "oxsemi,ox810se-reset"; - #reset-cells = <1>; - }; -}; diff --git a/Documentation/devicetree/bindings/reset/xlnx,zynqmp-reset.txt b/Documentation/devicetree/bindings/reset/xlnx,zynqmp-reset.txt deleted file mode 100644 index ed836868dbf18a938b4863f36bb81695563c5a7a..0000000000000000000000000000000000000000 --- a/Documentation/devicetree/bindings/reset/xlnx,zynqmp-reset.txt +++ /dev/null @@ -1,55 +0,0 @@ --------------------------------------------------------------------------- - = Zynq UltraScale+ MPSoC and Versal reset driver binding = --------------------------------------------------------------------------- -The Zynq UltraScale+ MPSoC and Versal has several different resets. - -See Chapter 36 of the Zynq UltraScale+ MPSoC TRM (UG) for more information -about zynqmp resets. - -Please also refer to reset.txt in this directory for common reset -controller binding usage. - -Required Properties: -- compatible: "xlnx,zynqmp-reset" for Zynq UltraScale+ MPSoC platform - "xlnx,versal-reset" for Versal platform -- #reset-cells: Specifies the number of cells needed to encode reset - line, should be 1 - -------- -Example -------- - -firmware { - zynqmp_firmware: zynqmp-firmware { - compatible = "xlnx,zynqmp-firmware"; - method = "smc"; - - zynqmp_reset: reset-controller { - compatible = "xlnx,zynqmp-reset"; - #reset-cells = <1>; - }; - }; -}; - -Specifying reset lines connected to IP modules -============================================== - -Device nodes that need access to reset lines should -specify them as a reset phandle in their corresponding node as -specified in reset.txt. - -For list of all valid reset indices for Zynq UltraScale+ MPSoC see - -For list of all valid reset indices for Versal see - - -Example: - -serdes: zynqmp_phy@fd400000 { - ... - - resets = <&zynqmp_reset ZYNQMP_RESET_SATA>; - reset-names = "sata_rst"; - - ... -}; diff --git a/Documentation/devicetree/bindings/reset/xlnx,zynqmp-reset.yaml b/Documentation/devicetree/bindings/reset/xlnx,zynqmp-reset.yaml new file mode 100644 index 0000000000000000000000000000000000000000..0d50f6a54af3c7dcdd63567efa86acac9da7e0c8 --- /dev/null +++ b/Documentation/devicetree/bindings/reset/xlnx,zynqmp-reset.yaml @@ -0,0 +1,52 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/reset/xlnx,zynqmp-reset.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Zynq UltraScale+ MPSoC and Versal reset + +maintainers: + - Piyush Mehta + +description: | + The Zynq UltraScale+ MPSoC and Versal has several different resets. + + The PS reset subsystem is responsible for handling the external reset + input to the device and that all internal reset requirements are met + for the system (as a whole) and for the functional units. + + Please also refer to reset.txt in this directory for common reset + controller binding usage. Device nodes that need access to reset + lines should specify them as a reset phandle in their corresponding + node as specified in reset.txt. + + For list of all valid reset indices for Zynq UltraScale+ MPSoC + + + For list of all valid reset indices for Versal + + +properties: + compatible: + enum: + - xlnx,zynqmp-reset + - xlnx,versal-reset + + "#reset-cells": + const: 1 + +required: + - compatible + - "#reset-cells" + +additionalProperties: false + +examples: + - | + zynqmp_reset: reset-controller { + compatible = "xlnx,zynqmp-reset"; + #reset-cells = <1>; + }; + +... diff --git a/Documentation/devicetree/bindings/riscv/cpus.yaml b/Documentation/devicetree/bindings/riscv/cpus.yaml index 3d2934b15e804eb0ae54e63dee7de7d2f8bd873e..38c0b5213736a463626ab7b1ad69f69e218c0605 100644 --- a/Documentation/devicetree/bindings/riscv/cpus.yaml +++ b/Documentation/devicetree/bindings/riscv/cpus.yaml @@ -23,6 +23,10 @@ description: | two cores, each of which has two hyperthreads, could be described as having four harts. +allOf: + - $ref: /schemas/cpu.yaml# + - $ref: extensions.yaml + properties: compatible: oneOf: @@ -61,7 +65,7 @@ properties: hart. These values originate from the RISC-V Privileged Specification document, available from https://riscv.org/specifications/ - $ref: "/schemas/types.yaml#/definitions/string" + $ref: /schemas/types.yaml#/definitions/string enum: - riscv,sv32 - riscv,sv39 @@ -79,25 +83,9 @@ properties: description: The blocksize in bytes for the Zicboz cache operations. - riscv,isa: - description: - Identifies the specific RISC-V instruction set architecture - supported by the hart. These are documented in the RISC-V - User-Level ISA document, available from - https://riscv.org/specifications/ - - Due to revisions of the ISA specification, some deviations - have arisen over time. - Notably, riscv,isa was defined prior to the creation of the - Zicsr and Zifencei extensions and thus "i" implies - "zicsr_zifencei". - - While the isa strings in ISA specification are case - insensitive, letters in the riscv,isa string must be all - lowercase to simplify parsing. - $ref: "/schemas/types.yaml#/definitions/string" - pattern: ^rv(?:64|32)imaf?d?q?c?b?k?j?p?v?h?(?:[hsxz](?:[a-z])+)?(?:_[hsxz](?:[a-z])+)*$ - + # RISC-V has multiple properties for cache op block sizes as the sizes + # differ between individual CBO extensions + cache-op-block-size: false # RISC-V requires 'timebase-frequency' in /cpus, so disallow it here timebase-frequency: false @@ -120,7 +108,7 @@ properties: - interrupt-controller cpu-idle-states: - $ref: '/schemas/types.yaml#/definitions/phandle-array' + $ref: /schemas/types.yaml#/definitions/phandle-array items: maxItems: 1 description: | @@ -133,11 +121,20 @@ properties: DMIPS/MHz, relative to highest capacity-dmips-mhz in the system. +anyOf: + - required: + - riscv,isa + - required: + - riscv,isa-base + +dependencies: + riscv,isa-base: [ "riscv,isa-extensions" ] + riscv,isa-extensions: [ "riscv,isa-base" ] + required: - - riscv,isa - interrupt-controller -additionalProperties: true +unevaluatedProperties: false examples: - | @@ -154,7 +151,9 @@ examples: i-cache-sets = <128>; i-cache-size = <16384>; reg = <0>; - riscv,isa = "rv64imac"; + riscv,isa-base = "rv64i"; + riscv,isa-extensions = "i", "m", "a", "c"; + cpu_intc0: interrupt-controller { #interrupt-cells = <1>; compatible = "riscv,cpu-intc"; @@ -177,8 +176,10 @@ examples: i-tlb-size = <32>; mmu-type = "riscv,sv39"; reg = <1>; - riscv,isa = "rv64imafdc"; tlb-split; + riscv,isa-base = "rv64i"; + riscv,isa-extensions = "i", "m", "a", "f", "d", "c"; + cpu_intc1: interrupt-controller { #interrupt-cells = <1>; compatible = "riscv,cpu-intc"; @@ -196,8 +197,10 @@ examples: device_type = "cpu"; reg = <0>; compatible = "riscv"; - riscv,isa = "rv64imafdc"; mmu-type = "riscv,sv48"; + riscv,isa-base = "rv64i"; + riscv,isa-extensions = "i", "m", "a", "f", "d", "c"; + interrupt-controller { #interrupt-cells = <1>; interrupt-controller; diff --git a/Documentation/devicetree/bindings/riscv/extensions.yaml b/Documentation/devicetree/bindings/riscv/extensions.yaml new file mode 100644 index 0000000000000000000000000000000000000000..cc1f546fdbdcbaf5103b485517725e68cd1032e3 --- /dev/null +++ b/Documentation/devicetree/bindings/riscv/extensions.yaml @@ -0,0 +1,250 @@ +# SPDX-License-Identifier: (GPL-2.0 OR MIT) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/riscv/extensions.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: RISC-V ISA extensions + +maintainers: + - Paul Walmsley + - Palmer Dabbelt + - Conor Dooley + +description: | + RISC-V has a large number of extensions, some of which are "standard" + extensions, meaning they are ratified by RISC-V International, and others + are "vendor" extensions. + This document defines properties that indicate whether a hart supports a + given extension. + + Once a standard extension has been ratified, no changes in behaviour can be + made without the creation of a new extension. + The properties for standard extensions therefore map to their originally + ratified states, with the exception of the I, Zicntr & Zihpm extensions. + See the "i" property for more information. + +select: + properties: + compatible: + contains: + const: riscv + +properties: + riscv,isa: + description: + Identifies the specific RISC-V instruction set architecture + supported by the hart. These are documented in the RISC-V + User-Level ISA document, available from + https://riscv.org/specifications/ + + Due to revisions of the ISA specification, some deviations + have arisen over time. + Notably, riscv,isa was defined prior to the creation of the + Zicntr, Zicsr, Zifencei and Zihpm extensions and thus "i" + implies "zicntr_zicsr_zifencei_zihpm". + + While the isa strings in ISA specification are case + insensitive, letters in the riscv,isa string must be all + lowercase. + $ref: /schemas/types.yaml#/definitions/string + pattern: ^rv(?:64|32)imaf?d?q?c?b?k?j?p?v?h?(?:[hsxz](?:[a-z])+)?(?:_[hsxz](?:[a-z])+)*$ + deprecated: true + + riscv,isa-base: + description: + The base ISA implemented by this hart, as described by the 20191213 + version of the unprivileged ISA specification. + enum: + - rv32i + - rv64i + + riscv,isa-extensions: + $ref: /schemas/types.yaml#/definitions/string-array + minItems: 1 + description: Extensions supported by the hart. + items: + anyOf: + # single letter extensions, in canonical order + - const: i + description: | + The base integer instruction set, as ratified in the 20191213 + version of the unprivileged ISA specification. + + This does not include Chapter 10, "Counters", which was moved into + the Zicntr and Zihpm extensions after the ratification of the + 20191213 version of the unprivileged specification. + + - const: m + description: + The standard M extension for integer multiplication and division, as + ratified in the 20191213 version of the unprivileged ISA + specification. + + - const: a + description: + The standard A extension for atomic instructions, as ratified in the + 20191213 version of the unprivileged ISA specification. + + - const: f + description: + The standard F extension for single-precision floating point, as + ratified in the 20191213 version of the unprivileged ISA + specification. + + - const: d + description: + The standard D extension for double-precision floating-point, as + ratified in the 20191213 version of the unprivileged ISA + specification. + + - const: q + description: + The standard Q extension for quad-precision floating-point, as + ratified in the 20191213 version of the unprivileged ISA + specification. + + - const: c + description: + The standard C extension for compressed instructions, as ratified in + the 20191213 version of the unprivileged ISA specification. + + - const: v + description: + The standard V extension for vector operations, as ratified + in-and-around commit 7a6c8ae ("Fix text that describes vfmv.v.f + encoding") of the riscv-v-spec. + + - const: h + description: + The standard H extension for hypervisors as ratified in the 20191213 + version of the privileged ISA specification. + + # multi-letter extensions, sorted alphanumerically + - const: smaia + description: | + The standard Smaia supervisor-level extension for the advanced + interrupt architecture for machine-mode-visible csr and behavioural + changes to interrupts as frozen at commit ccbddab ("Merge pull + request #42 from riscv/jhauser-2023-RC4") of riscv-aia. + + - const: ssaia + description: | + The standard Ssaia supervisor-level extension for the advanced + interrupt architecture for supervisor-mode-visible csr and + behavioural changes to interrupts as frozen at commit ccbddab + ("Merge pull request #42 from riscv/jhauser-2023-RC4") of riscv-aia. + + - const: sscofpmf + description: | + The standard Sscofpmf supervisor-level extension for count overflow + and mode-based filtering as ratified at commit 01d1df0 ("Add ability + to manually trigger workflow. (#2)") of riscv-count-overflow. + + - const: sstc + description: | + The standard Sstc supervisor-level extension for time compare as + ratified at commit 3f9ed34 ("Add ability to manually trigger + workflow. (#2)") of riscv-time-compare. + + - const: svinval + description: + The standard Svinval supervisor-level extension for fine-grained + address-translation cache invalidation as ratified in the 20191213 + version of the privileged ISA specification. + + - const: svnapot + description: + The standard Svnapot supervisor-level extensions for napot + translation contiguity as ratified in the 20191213 version of the + privileged ISA specification. + + - const: svpbmt + description: + The standard Svpbmt supervisor-level extensions for page-based + memory types as ratified in the 20191213 version of the privileged + ISA specification. + + - const: zba + description: | + The standard Zba bit-manipulation extension for address generation + acceleration instructions as ratified at commit 6d33919 ("Merge pull + request #158 from hirooih/clmul-fix-loop-end-condition") of + riscv-bitmanip. + + - const: zbb + description: | + The standard Zbb bit-manipulation extension for basic bit-manipulation + as ratified at commit 6d33919 ("Merge pull request #158 from + hirooih/clmul-fix-loop-end-condition") of riscv-bitmanip. + + - const: zbc + description: | + The standard Zbc bit-manipulation extension for carry-less + multiplication as ratified at commit 6d33919 ("Merge pull request + #158 from hirooih/clmul-fix-loop-end-condition") of riscv-bitmanip. + + - const: zbs + description: | + The standard Zbs bit-manipulation extension for single-bit + instructions as ratified at commit 6d33919 ("Merge pull request #158 + from hirooih/clmul-fix-loop-end-condition") of riscv-bitmanip. + + - const: zicbom + description: + The standard Zicbom extension for base cache management operations as + ratified in commit 3dd606f ("Create cmobase-v1.0.pdf") of riscv-CMOs. + + - const: zicbop + description: + The standard Zicbop extension for cache-block prefetch instructions + as ratified in commit 3dd606f ("Create cmobase-v1.0.pdf") of + riscv-CMOs. + + - const: zicboz + description: + The standard Zicboz extension for cache-block zeroing as ratified + in commit 3dd606f ("Create cmobase-v1.0.pdf") of riscv-CMOs. + + - const: zicntr + description: + The standard Zicntr extension for base counters and timers, as + ratified in the 20191213 version of the unprivileged ISA + specification. + + - const: zicsr + description: | + The standard Zicsr extension for control and status register + instructions, as ratified in the 20191213 version of the + unprivileged ISA specification. + + This does not include Chapter 10, "Counters", which documents + special case read-only CSRs, that were moved into the Zicntr and + Zihpm extensions after the ratification of the 20191213 version of + the unprivileged specification. + + - const: zifencei + description: + The standard Zifencei extension for instruction-fetch fence, as + ratified in the 20191213 version of the unprivileged ISA + specification. + + - const: zihintpause + description: + The standard Zihintpause extension for pause hints, as ratified in + commit d8ab5c7 ("Zihintpause is ratified") of the riscv-isa-manual. + + - const: zihpm + description: + The standard Zihpm extension for hardware performance counters, as + ratified in the 20191213 version of the unprivileged ISA + specification. + + - const: ztso + description: + The standard Ztso extension for total store ordering, as ratified + in commit 2e5236 ("Ztso is now ratified.") of the + riscv-isa-manual. + +additionalProperties: true +... diff --git a/Documentation/devicetree/bindings/riscv/thead.yaml b/Documentation/devicetree/bindings/riscv/thead.yaml new file mode 100644 index 0000000000000000000000000000000000000000..e62f6821372e4852f4863a3701fcc984c6f561d3 --- /dev/null +++ b/Documentation/devicetree/bindings/riscv/thead.yaml @@ -0,0 +1,29 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/riscv/thead.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: T-HEAD SoC-based boards + +maintainers: + - Jisheng Zhang + +description: + T-HEAD SoC-based boards + +properties: + $nodename: + const: '/' + compatible: + oneOf: + - description: Sipeed Lichee Pi 4A board for the Sipeed Lichee Module 4A + items: + - enum: + - sipeed,lichee-pi-4a + - const: sipeed,lichee-module-4a + - const: thead,th1520 + +additionalProperties: true + +... diff --git a/Documentation/devicetree/bindings/rtc/isil,isl1208.txt b/Documentation/devicetree/bindings/rtc/isil,isl1208.txt deleted file mode 100644 index 51f003006f0449909fbafd9b0ccb89ae49ea898f..0000000000000000000000000000000000000000 --- a/Documentation/devicetree/bindings/rtc/isil,isl1208.txt +++ /dev/null @@ -1,38 +0,0 @@ -Intersil ISL1209/19 I2C RTC/Alarm chip with event in - -ISL12X9 have additional pins EVIN and #EVDET for tamper detection, while the -ISL1208 and ISL1218 do not. They are all use the same driver with the bindings -described here, with chip specific properties as noted. - -Required properties supported by the device: - - "compatible": Should be one of the following: - - "isil,isl1208" - - "isil,isl1209" - - "isil,isl1218" - - "isil,isl1219" - - "reg": I2C bus address of the device - -Optional properties: - - "interrupt-names": list which may contains "irq" and "evdet" - evdet applies to isl1209 and isl1219 only - - "interrupts": list of interrupts for "irq" and "evdet" - evdet applies to isl1209 and isl1219 only - - "isil,ev-evienb": Enable or disable internal pull on EVIN pin - Applies to isl1209 and isl1219 only - Possible values are 0 and 1 - Value 0 enables internal pull-up on evin pin, 1 disables it. - Default will leave the non-volatile configuration of the pullup - as is. - -Example isl1219 node with #IRQ pin connected to SoC gpio1 pin12 and #EVDET pin -connected to SoC gpio2 pin 24 and internal pull-up enabled in EVIN pin. - - isl1219: rtc@68 { - compatible = "isil,isl1219"; - reg = <0x68>; - interrupt-names = "irq", "evdet"; - interrupts-extended = <&gpio1 12 IRQ_TYPE_EDGE_FALLING>, - <&gpio2 24 IRQ_TYPE_EDGE_FALLING>; - isil,ev-evienb = <1>; - }; - diff --git a/Documentation/devicetree/bindings/rtc/isil,isl1208.yaml b/Documentation/devicetree/bindings/rtc/isil,isl1208.yaml new file mode 100644 index 0000000000000000000000000000000000000000..11f7378d4997ae1cb538158ba0842712b6e8a15b --- /dev/null +++ b/Documentation/devicetree/bindings/rtc/isil,isl1208.yaml @@ -0,0 +1,100 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/rtc/isil,isl1208.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Intersil ISL1209/19 I2C RTC/Alarm chip with event in + +maintainers: + - Biju Das + - Trent Piepho + +description: + ISL12X9 have additional pins EVIN and EVDET for tamper detection, while the + ISL1208 and ISL1218 do not. + +properties: + compatible: + enum: + - isil,isl1208 + - isil,isl1209 + - isil,isl1218 + - isil,isl1219 + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + + clock-names: + description: | + Use xin, if connected to an external crystal. + Use clkin, if connected to an external clock signal. + enum: + - xin + - clkin + + interrupts: + minItems: 1 + maxItems: 2 + + interrupt-names: + minItems: 1 + items: + - const: irq + - const: evdet + + isil,ev-evienb: + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [ 0, 1 ] + description: | + Enable or disable internal pull on EVIN pin + Default will leave the non-volatile configuration of the pullup + as is. + <0> : Enables internal pull-up on evin pin + <1> : Disables internal pull-up on evin pin + +required: + - compatible + - reg + +allOf: + - $ref: rtc.yaml# + - if: + properties: + compatible: + contains: + enum: + - isil,isl1209 + - isil,isl1219 + then: + properties: + interrupts: + maxItems: 2 + interrupt-names: + items: + - const: irq + - const: evdet + else: + properties: + interrupts: + maxItems: 1 + interrupt-names: + items: + - const: irq + +unevaluatedProperties: false + +examples: + - | + i2c { + #address-cells = <1>; + #size-cells = <0>; + + rtc_twi: rtc@6f { + compatible = "isil,isl1208"; + reg = <0x6f>; + }; + }; diff --git a/Documentation/devicetree/bindings/rtc/loongson,rtc.yaml b/Documentation/devicetree/bindings/rtc/loongson,rtc.yaml new file mode 100644 index 0000000000000000000000000000000000000000..f89c1f660aeee5a9f0fd4b4490a58198fecd5cd2 --- /dev/null +++ b/Documentation/devicetree/bindings/rtc/loongson,rtc.yaml @@ -0,0 +1,57 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/rtc/loongson,rtc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Loongson Real-Time Clock + +description: + The Loongson family chips use an on-chip counter 0 (Time Of Year + counter) as the RTC. + +maintainers: + - Binbin Zhou + +allOf: + - $ref: rtc.yaml# + +properties: + compatible: + oneOf: + - enum: + - loongson,ls1b-rtc + - loongson,ls1c-rtc + - loongson,ls7a-rtc + - loongson,ls2k1000-rtc + - items: + - enum: + - loongson,ls2k2000-rtc + - loongson,ls2k0500-rtc + - const: loongson,ls7a-rtc + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + +required: + - compatible + - reg + +unevaluatedProperties: false + +examples: + - | + #include + + rtc@1fe27800 { + compatible = "loongson,ls2k1000-rtc"; + reg = <0x1fe27800 0x100>; + + interrupt-parent = <&liointc1>; + interrupts = <8 IRQ_TYPE_LEVEL_HIGH>; + }; + +... diff --git a/Documentation/devicetree/bindings/rtc/rtc.yaml b/Documentation/devicetree/bindings/rtc/rtc.yaml index c6fff5486fe67b398d928b8c67b81a80295d4117..efb66df82782f6b21a01fdd0e1c8a90d75032edb 100644 --- a/Documentation/devicetree/bindings/rtc/rtc.yaml +++ b/Documentation/devicetree/bindings/rtc/rtc.yaml @@ -15,7 +15,7 @@ description: | properties: $nodename: - pattern: "^rtc(@.*|-[0-9a-f])*$" + pattern: "^rtc(@.*|-([0-9]|[1-9][0-9]+))?$" aux-voltage-chargeable: $ref: /schemas/types.yaml#/definitions/uint32 diff --git a/Documentation/devicetree/bindings/rtc/trivial-rtc.yaml b/Documentation/devicetree/bindings/rtc/trivial-rtc.yaml index a3603e638c3739dd9d365a6809c4b27aa711c4c9..9af77f21bb7f487b30233bdb4369f3bd96ca62ca 100644 --- a/Documentation/devicetree/bindings/rtc/trivial-rtc.yaml +++ b/Documentation/devicetree/bindings/rtc/trivial-rtc.yaml @@ -47,8 +47,6 @@ properties: - isil,isl1218 # Intersil ISL12022 Real-time Clock - isil,isl12022 - # Loongson-2K Socs/LS7A bridge Real-time Clock - - loongson,ls2x-rtc # Real Time Clock Module with I2C-Bus - microcrystal,rv3029 # Real Time Clock diff --git a/Documentation/devicetree/bindings/rtc/xlnx,zynqmp-rtc.yaml b/Documentation/devicetree/bindings/rtc/xlnx,zynqmp-rtc.yaml index 7ed0230f6c6775a31f1eafa5ba448b4e0084c95b..d1f5eb996dba06d177fa5dfdcca389344497f3fb 100644 --- a/Documentation/devicetree/bindings/rtc/xlnx,zynqmp-rtc.yaml +++ b/Documentation/devicetree/bindings/rtc/xlnx,zynqmp-rtc.yaml @@ -11,7 +11,7 @@ description: The RTC controller has separate IRQ lines for seconds and alarm. maintainers: - - Michal Simek + - Michal Simek allOf: - $ref: rtc.yaml# diff --git a/Documentation/devicetree/bindings/serial/cdns,uart.yaml b/Documentation/devicetree/bindings/serial/cdns,uart.yaml index a8b323d7bf945f63c4c889820331932b5f7723a1..e35ad1109efc8b7b13211e5795c5668111e3f5c1 100644 --- a/Documentation/devicetree/bindings/serial/cdns,uart.yaml +++ b/Documentation/devicetree/bindings/serial/cdns,uart.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Cadence UART Controller maintainers: - - Michal Simek + - Michal Simek properties: compatible: diff --git a/Documentation/devicetree/bindings/serial/nuvoton,ma35d1-serial.yaml b/Documentation/devicetree/bindings/serial/nuvoton,ma35d1-serial.yaml new file mode 100644 index 0000000000000000000000000000000000000000..a76af0f6009b1f4350a528fb48dfb923d02369c0 --- /dev/null +++ b/Documentation/devicetree/bindings/serial/nuvoton,ma35d1-serial.yaml @@ -0,0 +1,48 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/serial/nuvoton,ma35d1-serial.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Nuvoton MA35D1 Universal Asynchronous Receiver/Transmitter (UART) + +maintainers: + - Min-Jen Chen + - Jacky Huang + +allOf: + - $ref: serial.yaml + +properties: + compatible: + const: nuvoton,ma35d1-uart + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + clocks: + maxItems: 1 + +required: + - compatible + - reg + - interrupts + - clocks + +unevaluatedProperties: false + +examples: + - | + #include + #include + + serial@40700000 { + compatible = "nuvoton,ma35d1-uart"; + reg = <0x40700000 0x100>; + interrupts = ; + clocks = <&clk UART0_GATE>; + }; +... diff --git a/Documentation/devicetree/bindings/slimbus/slimbus.yaml b/Documentation/devicetree/bindings/slimbus/slimbus.yaml index 22513fb7c59a8be950816c900dba0450fa47f2ab..3b8cae9d1016bf824f2933e80ed0364f96bb21bd 100644 --- a/Documentation/devicetree/bindings/slimbus/slimbus.yaml +++ b/Documentation/devicetree/bindings/slimbus/slimbus.yaml @@ -15,7 +15,7 @@ description: properties: $nodename: - pattern: "^slim(@.*|-[0-9a-f])*$" + pattern: "^slim(@.*|-([0-9]|[1-9][0-9]+))?$" "#address-cells": const: 2 diff --git a/Documentation/devicetree/bindings/soc/bcm/brcm,bcm23550-cdc.yaml b/Documentation/devicetree/bindings/soc/bcm/brcm,bcm23550-cdc.yaml new file mode 100644 index 0000000000000000000000000000000000000000..1a952f5698032912ce2fd0948150f6db12c151be --- /dev/null +++ b/Documentation/devicetree/bindings/soc/bcm/brcm,bcm23550-cdc.yaml @@ -0,0 +1,35 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/soc/bcm/brcm,bcm23550-cdc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Broadcom BCM23550 Cluster Dormant Control + +description: + The Cluster Dormant Control block keeps the CPU in idle state. A command + needs to be sent to this block to bring the CPU into running state. + +maintainers: + - Florian Fainelli + +properties: + compatible: + const: brcm,bcm23550-cdc + + reg: + maxItems: 1 + +required: + - compatible + - reg + +additionalProperties: false + +examples: + - | + cdc@3fe0e000 { + compatible = "brcm,bcm23550-cdc"; + reg = <0x3fe0e000 0x78>; + }; +... diff --git a/Documentation/devicetree/bindings/soc/mediatek/mediatek,pwrap.yaml b/Documentation/devicetree/bindings/soc/mediatek/mediatek,pwrap.yaml index 3fefd634bc698074536749ef88761240551838cb..a06ac2177444ebda93a3c696a539f46e96083938 100644 --- a/Documentation/devicetree/bindings/soc/mediatek/mediatek,pwrap.yaml +++ b/Documentation/devicetree/bindings/soc/mediatek/mediatek,pwrap.yaml @@ -33,6 +33,7 @@ properties: - mediatek,mt2701-pwrap - mediatek,mt6765-pwrap - mediatek,mt6779-pwrap + - mediatek,mt6795-pwrap - mediatek,mt6797-pwrap - mediatek,mt6873-pwrap - mediatek,mt7622-pwrap diff --git a/Documentation/devicetree/bindings/arm/npcm/nuvoton,gcr.yaml b/Documentation/devicetree/bindings/soc/nuvoton/nuvoton,npcm-gcr.yaml similarity index 93% rename from Documentation/devicetree/bindings/arm/npcm/nuvoton,gcr.yaml rename to Documentation/devicetree/bindings/soc/nuvoton/nuvoton,npcm-gcr.yaml index 94e72f25b33116e02898cebe0486d8e0c68166ab..23e7e4ea01ff737afc5559adb281f2a674c9003c 100644 --- a/Documentation/devicetree/bindings/arm/npcm/nuvoton,gcr.yaml +++ b/Documentation/devicetree/bindings/soc/nuvoton/nuvoton,npcm-gcr.yaml @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause %YAML 1.2 --- -$id: http://devicetree.org/schemas/arm/npcm/nuvoton,gcr.yaml# +$id: http://devicetree.org/schemas/soc/nuvoton/nuvoton,npcm-gcr.yaml# $schema: http://devicetree.org/meta-schemas/core.yaml# title: Global Control Registers block in Nuvoton SoCs diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.yaml b/Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.yaml index 798f15588ee259dd60e39077c99cd9f2b9c9fff3..9dc8e48c8af4ecf870c8cb33e0ab040d36371b96 100644 --- a/Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.yaml +++ b/Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.yaml @@ -26,6 +26,7 @@ properties: items: - enum: - qcom,qdu1000-aoss-qmp + - qcom,sa8775p-aoss-qmp - qcom,sc7180-aoss-qmp - qcom,sc7280-aoss-qmp - qcom,sc8180x-aoss-qmp diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,eud.yaml b/Documentation/devicetree/bindings/soc/qcom/qcom,eud.yaml index 14dd29471c803a52c43730590414941ad4793b8f..f2c5ec7e6437b475525008efdd5a89af8ce50964 100644 --- a/Documentation/devicetree/bindings/soc/qcom/qcom,eud.yaml +++ b/Documentation/devicetree/bindings/soc/qcom/qcom,eud.yaml @@ -55,9 +55,10 @@ additionalProperties: false examples: - | eud@88e0000 { - compatible = "qcom,sc7280-eud","qcom,eud"; + compatible = "qcom,sc7280-eud", "qcom,eud"; reg = <0x88e0000 0x2000>, <0x88e2000 0x1000>; + ports { #address-cells = <1>; #size-cells = <0>; @@ -67,6 +68,7 @@ examples: remote-endpoint = <&usb2_role_switch>; }; }; + port@1 { reg = <1>; eud_con: endpoint { diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,rpm-master-stats.yaml b/Documentation/devicetree/bindings/soc/qcom/qcom,rpm-master-stats.yaml new file mode 100644 index 0000000000000000000000000000000000000000..031800985b5ebf7ef6bd9b775327097e78b38ecc --- /dev/null +++ b/Documentation/devicetree/bindings/soc/qcom/qcom,rpm-master-stats.yaml @@ -0,0 +1,69 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/soc/qcom/qcom,rpm-master-stats.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm Technologies, Inc. (QTI) RPM Master Stats + +maintainers: + - Konrad Dybcio + +description: | + The Qualcomm RPM (Resource Power Manager) architecture includes a concept + of "RPM Masters". They can be thought of as "the local gang leaders", usually + spanning a single subsystem (e.g. APSS, ADSP, CDSP). All of the RPM decisions + (particularly around entering hardware-driven low power modes: XO shutdown + and total system-wide power collapse) are first made at Master-level, and + only then aggregated for the entire system. + + The Master Stats provide a few useful bits that can be used to assess whether + our device has entered the desired low-power mode, how long it took to do so, + the duration of that residence, how long it took to come back online, + how many times a given sleep state was entered and which cores are actively + voting for staying awake. + + This scheme has been used on various SoCs in the 2013-2023 era, with some + newer or higher-end designs providing this information through an SMEM query. + +properties: + compatible: + const: qcom,rpm-master-stats + + qcom,rpm-msg-ram: + $ref: /schemas/types.yaml#/definitions/phandle-array + description: Phandle to an RPM MSG RAM slice containing the master stats + minItems: 1 + maxItems: 5 + + qcom,master-names: + $ref: /schemas/types.yaml#/definitions/string-array + description: + The name of the RPM Master which owns the MSG RAM slice where this + instance of Master Stats resides + minItems: 1 + maxItems: 5 + +required: + - compatible + - qcom,rpm-msg-ram + - qcom,master-names + +additionalProperties: false + +examples: + - | + stats { + compatible = "qcom,rpm-master-stats"; + qcom,rpm-msg-ram = <&apss_master_stats>, + <&mpss_master_stats>, + <&adsp_master_stats>, + <&cdsp_master_stats>, + <&tz_master_stats>; + qcom,master-names = "APSS", + "MPSS", + "ADSP", + "CDSP", + "TZ"; + }; +... diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,rpmh-rsc.yaml b/Documentation/devicetree/bindings/soc/qcom/qcom,rpmh-rsc.yaml index a4046ba608466ae7dea969b58c1835bcabc5a90b..af632d0e0355c56748ecac24f528dc2eec7d1193 100644 --- a/Documentation/devicetree/bindings/soc/qcom/qcom,rpmh-rsc.yaml +++ b/Documentation/devicetree/bindings/soc/qcom/qcom,rpmh-rsc.yaml @@ -124,6 +124,7 @@ required: - qcom,tcs-offset - reg - reg-names + - power-domains additionalProperties: false @@ -179,6 +180,7 @@ examples: , , ; + power-domains = <&CLUSTER_PD>; }; - | diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,smd-rpm.yaml b/Documentation/devicetree/bindings/soc/qcom/qcom,smd-rpm.yaml index ea86569a40d3cb2e72da2831f49f3e09828db103..65c02a7fef809fe012c924b3d85cf3a1b7767cab 100644 --- a/Documentation/devicetree/bindings/soc/qcom/qcom,smd-rpm.yaml +++ b/Documentation/devicetree/bindings/soc/qcom/qcom,smd-rpm.yaml @@ -81,6 +81,7 @@ if: contains: enum: - qcom,rpm-apq8084 + - qcom,rpm-msm8226 - qcom,rpm-msm8916 - qcom,rpm-msm8936 - qcom,rpm-msm8974 diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom-stats.yaml b/Documentation/devicetree/bindings/soc/qcom/qcom-stats.yaml index 7ab8cfff18c196ed4ced3604464d506ed86062f1..96a7f18220225a7034786c359825facca4a8b3e3 100644 --- a/Documentation/devicetree/bindings/soc/qcom/qcom-stats.yaml +++ b/Documentation/devicetree/bindings/soc/qcom/qcom-stats.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Qualcomm Technologies, Inc. (QTI) Stats maintainers: - - Maulik Shah + - Maulik Shah description: Always On Processor/Resource Power Manager maintains statistics of the SoC diff --git a/Documentation/devicetree/bindings/soc/rockchip/grf.yaml b/Documentation/devicetree/bindings/soc/rockchip/grf.yaml index 65a2d5a4f28d82afbd33eaae7f62dbf9d1484f5a..e4fa6a07b4fa2c6fc5f2d94d15e0c57b1bf51783 100644 --- a/Documentation/devicetree/bindings/soc/rockchip/grf.yaml +++ b/Documentation/devicetree/bindings/soc/rockchip/grf.yaml @@ -24,6 +24,7 @@ properties: - rockchip,rk3588-bigcore1-grf - rockchip,rk3588-ioc - rockchip,rk3588-php-grf + - rockchip,rk3588-pipe-phy-grf - rockchip,rk3588-sys-grf - rockchip,rk3588-pcie3-phy-grf - rockchip,rk3588-pcie3-pipe-grf @@ -52,6 +53,7 @@ properties: - rockchip,rk3399-pmugrf - rockchip,rk3568-grf - rockchip,rk3568-pmugrf + - rockchip,rk3588-usb2phy-grf - rockchip,rv1108-grf - rockchip,rv1108-pmugrf - rockchip,rv1126-grf @@ -119,7 +121,7 @@ allOf: usbphy: type: object - $ref: "/schemas/phy/rockchip-usb-phy.yaml#" + $ref: /schemas/phy/rockchip-usb-phy.yaml# unevaluatedProperties: false @@ -134,14 +136,14 @@ allOf: gpio: type: object - $ref: "/schemas/gpio/rockchip,rk3328-grf-gpio.yaml#" + $ref: /schemas/gpio/rockchip,rk3328-grf-gpio.yaml# unevaluatedProperties: false power-controller: type: object - $ref: "/schemas/power/rockchip,power-controller.yaml#" + $ref: /schemas/power/rockchip,power-controller.yaml# unevaluatedProperties: false @@ -156,7 +158,7 @@ allOf: mipi-dphy-rx0: type: object - $ref: "/schemas/phy/rockchip-mipi-dphy-rx0.yaml#" + $ref: /schemas/phy/rockchip-mipi-dphy-rx0.yaml# unevaluatedProperties: false @@ -184,7 +186,7 @@ allOf: reboot-mode: type: object - $ref: "/schemas/power/reset/syscon-reboot-mode.yaml#" + $ref: /schemas/power/reset/syscon-reboot-mode.yaml# unevaluatedProperties: false @@ -199,6 +201,7 @@ allOf: - rockchip,rk3308-usb2phy-grf - rockchip,rk3328-usb2phy-grf - rockchip,rk3399-grf + - rockchip,rk3588-usb2phy-grf - rockchip,rv1108-grf then: @@ -238,7 +241,7 @@ allOf: io-domains: type: object - $ref: "/schemas/power/rockchip-io-domain.yaml#" + $ref: /schemas/power/rockchip-io-domain.yaml# unevaluatedProperties: false diff --git a/Documentation/devicetree/bindings/soc/samsung/exynos-pmu.yaml b/Documentation/devicetree/bindings/soc/samsung/exynos-pmu.yaml index 5d8d9497f18e8587ca0fbe6b8717bb491d90b6be..e1d716df5dfa6679304fb6459cfc32354f368ebd 100644 --- a/Documentation/devicetree/bindings/soc/samsung/exynos-pmu.yaml +++ b/Documentation/devicetree/bindings/soc/samsung/exynos-pmu.yaml @@ -17,6 +17,7 @@ select: enum: - samsung,exynos3250-pmu - samsung,exynos4210-pmu + - samsung,exynos4212-pmu - samsung,exynos4412-pmu - samsung,exynos5250-pmu - samsung,exynos5260-pmu @@ -36,6 +37,7 @@ properties: - enum: - samsung,exynos3250-pmu - samsung,exynos4210-pmu + - samsung,exynos4212-pmu - samsung,exynos4412-pmu - samsung,exynos5250-pmu - samsung,exynos5260-pmu @@ -50,6 +52,7 @@ properties: - enum: - samsung,exynos3250-pmu - samsung,exynos4210-pmu + - samsung,exynos4212-pmu - samsung,exynos4412-pmu - samsung,exynos5250-pmu - samsung,exynos5420-pmu @@ -125,6 +128,7 @@ allOf: enum: - samsung,exynos3250-pmu - samsung,exynos4210-pmu + - samsung,exynos4212-pmu - samsung,exynos4412-pmu - samsung,exynos5250-pmu - samsung,exynos5410-pmu @@ -143,6 +147,7 @@ allOf: enum: - samsung,exynos3250-pmu - samsung,exynos4210-pmu + - samsung,exynos4212-pmu - samsung,exynos4412-pmu - samsung,exynos5250-pmu - samsung,exynos5420-pmu diff --git a/Documentation/devicetree/bindings/sound/adi,max98388.yaml b/Documentation/devicetree/bindings/sound/adi,max98388.yaml new file mode 100644 index 0000000000000000000000000000000000000000..93ccd590573614a12f61ed57bb3895d99076c4ab --- /dev/null +++ b/Documentation/devicetree/bindings/sound/adi,max98388.yaml @@ -0,0 +1,79 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/adi,max98388.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Analog Devices MAX98388 Speaker Amplifier + +maintainers: + - Ryan Lee + +description: + The MAX98388 is a mono Class-D speaker amplifier with I/V feedback. + The device provides a PCM interface for audio data and a standard + I2C interface for control data communication. + +allOf: + - $ref: dai-common.yaml# + +properties: + compatible: + enum: + - adi,max98388 + + reg: + maxItems: 1 + + '#sound-dai-cells': + const: 0 + + adi,vmon-slot-no: + description: slot number of the voltage feedback monitor + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0 + maximum: 15 + default: 0 + + adi,imon-slot-no: + description: slot number of the current feedback monitor + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0 + maximum: 15 + default: 1 + + adi,interleave-mode: + description: + For cases where a single combined channel for the I/V feedback data + is not sufficient, the device can also be configured to share + a single data output channel on alternating frames. + In this configuration, the current and voltage data will be frame + interleaved on a single output channel. + type: boolean + + reset-gpios: + maxItems: 1 + +required: + - compatible + - reg + - '#sound-dai-cells' + +unevaluatedProperties: false + +examples: + - | + #include + i2c { + #address-cells = <1>; + #size-cells = <0>; + max98388: amplifier@39 { + compatible = "adi,max98388"; + reg = <0x39>; + #sound-dai-cells = <0>; + adi,vmon-slot-no = <0>; + adi,imon-slot-no = <1>; + adi,interleave-mode; + reset-gpios = <&gpio 4 GPIO_ACTIVE_LOW>; + }; + }; diff --git a/Documentation/devicetree/bindings/sound/adi,ssm2518.yaml b/Documentation/devicetree/bindings/sound/adi,ssm2518.yaml new file mode 100644 index 0000000000000000000000000000000000000000..f3f32540779c60197fee6a00fbaeabbf41ecb7fd --- /dev/null +++ b/Documentation/devicetree/bindings/sound/adi,ssm2518.yaml @@ -0,0 +1,47 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/adi,ssm2518.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Analog Devices SSM2518 audio amplifier + +maintainers: + - Lars-Peter Clausen + +allOf: + - $ref: dai-common.yaml# + +properties: + compatible: + const: adi,ssm2518 + + reg: + maxItems: 1 + description: | + I2C address of the device. This will either be 0x34 (ADDR pin low) + or 0x35 (ADDR pin high) + + gpios: + maxItems: 1 + description: | + GPIO connected to the nSD pin. If the property is not present + it is assumed that the nSD pin is hardwired to always on. + +required: + - compatible + - reg + +unevaluatedProperties: false + +examples: + - | + i2c { + #address-cells = <1>; + #size-cells = <0>; + codec@34 { + compatible = "adi,ssm2518"; + reg = <0x34>; + gpios = <&gpio 5 0>; + }; + }; diff --git a/Documentation/devicetree/bindings/sound/adi,ssm3515.yaml b/Documentation/devicetree/bindings/sound/adi,ssm3515.yaml new file mode 100644 index 0000000000000000000000000000000000000000..144450df586955e1975cff13eb38f72db36863b1 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/adi,ssm3515.yaml @@ -0,0 +1,49 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/adi,ssm3515.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Analog Devices SSM3515 Audio Amplifier + +maintainers: + - Martin Povišer + +description: | + SSM3515 is a mono Class-D audio amplifier with digital input. + + https://www.analog.com/media/en/technical-documentation/data-sheets/SSM3515.pdf + +allOf: + - $ref: dai-common.yaml# + +properties: + compatible: + enum: + - adi,ssm3515 + + reg: + maxItems: 1 + + '#sound-dai-cells': + const: 0 + +required: + - compatible + - reg + +unevaluatedProperties: false + +examples: + - | + i2c { + #address-cells = <1>; + #size-cells = <0>; + + codec@14 { + compatible = "adi,ssm3515"; + reg = <0x14>; + #sound-dai-cells = <0>; + sound-name-prefix = "Left Tweeter"; + }; + }; diff --git a/Documentation/devicetree/bindings/sound/audio-graph.yaml b/Documentation/devicetree/bindings/sound/audio-graph.yaml index c87eb91de159324b032f4c00078b2172021d9d80..ed31e04ff6a681d279946f64f749a61a54599698 100644 --- a/Documentation/devicetree/bindings/sound/audio-graph.yaml +++ b/Documentation/devicetree/bindings/sound/audio-graph.yaml @@ -24,7 +24,11 @@ properties: connection's sink, the second being the connection's source. $ref: /schemas/types.yaml#/definitions/non-unique-string-array widgets: - description: User specified audio sound widgets. + description: | + User specified audio sound widgets. + Each entry is a pair of strings, the first being the type of + widget ("Microphone", "Line", "Headphone", "Speaker"), the + second being the machine specific name for the widget. $ref: /schemas/types.yaml#/definitions/non-unique-string-array convert-rate: $ref: /schemas/sound/dai-params.yaml#/$defs/dai-sample-rate diff --git a/Documentation/devicetree/bindings/sound/cirrus,cs35l45.yaml b/Documentation/devicetree/bindings/sound/cirrus,cs35l45.yaml index 2ab74f99568529eefa94044d13e66e401280ef82..4c9acb8d4c4c6174a0b4f84f05e36550c5c92792 100644 --- a/Documentation/devicetree/bindings/sound/cirrus,cs35l45.yaml +++ b/Documentation/devicetree/bindings/sound/cirrus,cs35l45.yaml @@ -62,7 +62,7 @@ patternProperties: GPIO pin direction. Valid only when 'gpio-ctrl' is 1 0 = Output 1 = Input - $ref: "/schemas/types.yaml#/definitions/uint32" + $ref: /schemas/types.yaml#/definitions/uint32 minimum: 0 maximum: 1 default: 1 @@ -71,7 +71,7 @@ patternProperties: GPIO level. Valid only when 'gpio-ctrl' is 1 and 'gpio-dir' is 0 0 = Low 1 = High - $ref: "/schemas/types.yaml#/definitions/uint32" + $ref: /schemas/types.yaml#/definitions/uint32 minimum: 0 maximum: 1 default: 0 @@ -80,7 +80,7 @@ patternProperties: GPIO level. Valid only when 'gpio-ctrl' is 1 and 'gpio-dir' is 0 0 = CMOS 1 = Open Drain - $ref: "/schemas/types.yaml#/definitions/uint32" + $ref: /schemas/types.yaml#/definitions/uint32 minimum: 0 maximum: 1 default: 0 @@ -90,7 +90,7 @@ patternProperties: and 'gpio-dir' is 0 0 = Non-inverted, Active High 1 = Inverted, Active Low - $ref: "/schemas/types.yaml#/definitions/uint32" + $ref: /schemas/types.yaml#/definitions/uint32 minimum: 0 maximum: 1 default: 0 @@ -114,7 +114,7 @@ patternProperties: 0 = High impedance input 1 = Pin acts as a GPIO, direction controlled by 'gpio-dir' 2-7 = Reserved - $ref: "/schemas/types.yaml#/definitions/uint32" + $ref: /schemas/types.yaml#/definitions/uint32 minimum: 0 maximum: 7 default: 0 diff --git a/Documentation/devicetree/bindings/sound/cirrus,cs42l51.yaml b/Documentation/devicetree/bindings/sound/cirrus,cs42l51.yaml index 670b67ec0b617938a5e936e4b4f23eb5486b3eeb..f7bafbd4f1c2d5e7ccb6551296bde3f8fd4faca9 100644 --- a/Documentation/devicetree/bindings/sound/cirrus,cs42l51.yaml +++ b/Documentation/devicetree/bindings/sound/cirrus,cs42l51.yaml @@ -44,6 +44,10 @@ properties: VAHP-supply: description: phandle to voltage regulator of headphone + port: + $ref: audio-graph-port.yaml# + unevaluatedProperties: false + required: - compatible - reg @@ -69,6 +73,13 @@ examples: VA-supply = <®_audio>; VAHP-supply = <®_audio>; reset-gpios = <&gpiog 9 GPIO_ACTIVE_LOW>; + + /* assume audio-graph */ + port { + cpu_endpoint: endpoint { + remote-endpoint = <&cpu_endpoint>; + }; + }; }; }; ... diff --git a/Documentation/devicetree/bindings/sound/da7219.txt b/Documentation/devicetree/bindings/sound/da7219.txt deleted file mode 100644 index add1caf26ac27049c87f8805d8f7ae9507545628..0000000000000000000000000000000000000000 --- a/Documentation/devicetree/bindings/sound/da7219.txt +++ /dev/null @@ -1,112 +0,0 @@ -Dialog Semiconductor DA7219 Audio Codec bindings - -DA7219 is an audio codec with advanced accessory detect features. - -====== - -Required properties: -- compatible : Should be "dlg,da7219" -- reg: Specifies the I2C slave address - -- interrupts : IRQ line info for DA7219. - (See Documentation/devicetree/bindings/interrupt-controller/interrupts.txt for - further information relating to interrupt properties) - -- VDD-supply: VDD power supply for the device -- VDDMIC-supply: VDDMIC power supply for the device -- VDDIO-supply: VDDIO power supply for the device - (See Documentation/devicetree/bindings/regulator/regulator.txt for further - information relating to regulators) - -Optional properties: -- interrupt-names : Name associated with interrupt line. Should be "wakeup" if - interrupt is to be used to wake system, otherwise "irq" should be used. -- wakeup-source: Flag to indicate this device can wake system (suspend/resume). - -- #clock-cells : Should be set to '<1>', two clock sources provided; -- clock-output-names : Names given for DAI clock outputs (WCLK & BCLK); - -- clocks : phandle and clock specifier for codec MCLK. -- clock-names : Clock name string for 'clocks' attribute, should be "mclk". - -- dlg,micbias-lvl : Voltage (mV) for Mic Bias - [<1600>, <1800>, <2000>, <2200>, <2400>, <2600>] -- dlg,mic-amp-in-sel : Mic input source type - ["diff", "se_p", "se_n"] - -Deprecated properties: -- dlg,ldo-lvl : Required internal LDO voltage (mV) level for digital engine - (LDO unavailable in production HW so property no longer required). - -====== - -Child node - 'da7219_aad': - -Optional properties: -- dlg,micbias-pulse-lvl : Mic bias higher voltage pulse level (mV). - [<2800>, <2900>] -- dlg,micbias-pulse-time : Mic bias higher voltage pulse duration (ms) -- dlg,btn-cfg : Periodic button press measurements for 4-pole jack (ms) - [<2>, <5>, <10>, <50>, <100>, <200>, <500>] -- dlg,mic-det-thr : Impedance threshold for mic detection measurement (Ohms) - [<200>, <500>, <750>, <1000>] -- dlg,jack-ins-deb : Debounce time for jack insertion (ms) - [<5>, <10>, <20>, <50>, <100>, <200>, <500>, <1000>] -- dlg,jack-det-rate: Jack type detection latency (3/4 pole) - ["32ms_64ms", "64ms_128ms", "128ms_256ms", "256ms_512ms"] -- dlg,jack-rem-deb : Debounce time for jack removal (ms) - [<1>, <5>, <10>, <20>] -- dlg,a-d-btn-thr : Impedance threshold between buttons A and D - [0x0 - 0xFF] -- dlg,d-b-btn-thr : Impedance threshold between buttons D and B - [0x0 - 0xFF] -- dlg,b-c-btn-thr : Impedance threshold between buttons B and C - [0x0 - 0xFF] -- dlg,c-mic-btn-thr : Impedance threshold between button C and Mic - [0x0 - 0xFF] -- dlg,btn-avg : Number of 8-bit readings for averaged button measurement - [<1>, <2>, <4>, <8>] -- dlg,adc-1bit-rpt : Repeat count for 1-bit button measurement - [<1>, <2>, <4>, <8>] - -====== - -Example: - - codec: da7219@1a { - compatible = "dlg,da7219"; - reg = <0x1a>; - - interrupt-parent = <&gpio6>; - interrupts = <11 IRQ_TYPE_LEVEL_LOW>; - - VDD-supply = <®_audio>; - VDDMIC-supply = <®_audio>; - VDDIO-supply = <®_audio>; - - #clock-cells = <1>; - clock-output-names = "dai-wclk", "dai-bclk"; - - clocks = <&clks 201>; - clock-names = "mclk"; - - dlg,ldo-lvl = <1200>; - dlg,micbias-lvl = <2600>; - dlg,mic-amp-in-sel = "diff"; - - da7219_aad { - dlg,btn-cfg = <50>; - dlg,mic-det-thr = <500>; - dlg,jack-ins-deb = <20>; - dlg,jack-det-rate = "32ms_64ms"; - dlg,jack-rem-deb = <1>; - - dlg,a-d-btn-thr = <0xa>; - dlg,d-b-btn-thr = <0x16>; - dlg,b-c-btn-thr = <0x21>; - dlg,c-mic-btn-thr = <0x3E>; - - dlg,btn-avg = <4>; - dlg,adc-1bit-rpt = <1>; - }; - }; diff --git a/Documentation/devicetree/bindings/sound/dialog,da7219.yaml b/Documentation/devicetree/bindings/sound/dialog,da7219.yaml new file mode 100644 index 0000000000000000000000000000000000000000..bb5af48ab1e19a527f41243ee75061e362eb09db --- /dev/null +++ b/Documentation/devicetree/bindings/sound/dialog,da7219.yaml @@ -0,0 +1,237 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/dialog,da7219.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Dialog Semiconductor DA7219 Audio Codec + +maintainers: + - David Rau + +description: + The DA7219 is an ultra low-power audio codec with + in-built advanced accessory detection (AAD) for mobile + computing and accessory applications, which supports + sample rates up to 96 kHz at 24-bit resolution. + +properties: + compatible: + const: dlg,da7219 + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + VDD-supply: + description: + VDD power supply for the device. + + VDDMIC-supply: + description: + VDDMIC power supply for the device. + + VDDIO-supply: + description: + VDDIO power supply for the device. + + interrupt-names: + description: + Should be "wakeup" if interrupt is to be used to wake system, + otherwise "irq" should be used. + enum: + - wakeup + - irq + + wakeup-source: + type: boolean + description: + Flag to indicate this device can wake system (suspend/resume). + + "#clock-cells": + const: 1 + + clock-output-names: + minItems: 2 + maxItems: 2 + description: + Name given for DAI WCLK and BCLK outputs. + + clocks: + maxItems: 1 + description: + phandle and clock specifier for codec MCLK. + + clock-names: + const: mclk + + dlg,micbias-lvl: + enum: [1600, 1800, 2000, 2200, 2400, 2600] + description: + Voltage (mV) for Mic Bias. + $ref: /schemas/types.yaml#/definitions/uint32 + + dlg,mic-amp-in-sel: + enum: ["diff", "se_p", "se_n"] + description: + Mic input source type. + + diff - Differential. + + se_p - MIC_P. + Positive differential analog microphone input. + + se_n - MIC_N. + Negative differential analog microphone input. + $ref: /schemas/types.yaml#/definitions/string + + da7219_aad: + type: object + description: + Configuration of advanced accessory detection. + properties: + dlg,micbias-pulse-lvl: + enum: [2800, 2900] + description: + Mic bias higher voltage pulse level (mV). + $ref: /schemas/types.yaml#/definitions/uint32 + + dlg,micbias-pulse-time: + description: + Mic bias higher voltage pulse duration (ms). + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0 + + dlg,btn-cfg: + enum: [2, 5, 10, 50, 100, 200, 500] + description: + Periodic button press measurements for 4-pole jack (ms). + $ref: /schemas/types.yaml#/definitions/uint32 + + dlg,mic-det-thr: + enum: [200, 500, 750, 1000] + description: + Impedance threshold for mic detection measurement (Ohms). + $ref: /schemas/types.yaml#/definitions/uint32 + + dlg,jack-ins-deb: + enum: [5, 10, 20, 50, 100, 200, 500, 1000] + description: + Debounce time for jack insertion (ms). + $ref: /schemas/types.yaml#/definitions/uint32 + + dlg,jack-ins-det-pty: + enum: ["low", "high"] + description: + Polarity for jack insertion detection. + $ref: /schemas/types.yaml#/definitions/string + + dlg,jack-det-rate: + enum: ["32_64", "64_128", "128_256", "256_512"] + description: + Jack type (3/4 pole) detection latency (ms). + $ref: /schemas/types.yaml#/definitions/string + + dlg,jack-rem-deb: + enum: [1, 5, 10, 20] + description: + Debounce time for jack removal (ms). + $ref: /schemas/types.yaml#/definitions/uint32 + + dlg,a-d-btn-thr: + description: + Impedance threshold between buttons A and D. + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0 + maximum: 255 + + dlg,d-b-btn-thr: + description: + Impedance threshold between buttons D and B. + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0 + maximum: 255 + + dlg,b-c-btn-thr: + description: + Impedance threshold between buttons B and C. + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0 + maximum: 255 + + dlg,c-mic-btn-thr: + description: + Impedance threshold between button C and Mic. + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0 + maximum: 255 + + dlg,btn-avg: + enum: [1, 2, 4, 8] + description: + Number of 8-bit readings for averaged button measurement. + $ref: /schemas/types.yaml#/definitions/uint32 + + dlg,adc-1bit-rpt: + enum: [1, 2, 4, 8] + description: + Repeat count for 1-bit button measurement. + $ref: /schemas/types.yaml#/definitions/uint32 + +required: + - compatible + - reg + - interrupts + - VDD-supply + - VDDMIC-supply + - VDDIO-supply + +additionalProperties: false + +examples: + - | + #include + i2c { + #address-cells = <1>; + #size-cells = <0>; + + codec: da7219@1a { + compatible = "dlg,da7219"; + reg = <0x1a>; + + interrupt-parent = <&gpio6>; + interrupts = <11 IRQ_TYPE_LEVEL_LOW>; + + VDD-supply = <&vdd_reg>; + VDDMIC-supply = <&vddmic_reg>; + VDDIO-supply = <&vddio_reg>; + + #clock-cells = <1>; + clock-output-names = "da7219-dai-wclk", "da7219-dai-bclk"; + + clocks = <&clks 201>; + clock-names = "mclk"; + + dlg,micbias-lvl = <2600>; + dlg,mic-amp-in-sel = "diff"; + + da7219_aad { + dlg,btn-cfg = <50>; + dlg,mic-det-thr = <500>; + dlg,jack-ins-deb = <20>; + dlg,jack-ins-det-pty = "low"; + dlg,jack-det-rate = "32_64"; + dlg,jack-rem-deb = <1>; + + dlg,a-d-btn-thr = <0xa>; + dlg,d-b-btn-thr = <0x16>; + dlg,b-c-btn-thr = <0x21>; + dlg,c-mic-btn-thr = <0x3E>; + + dlg,btn-avg = <4>; + dlg,adc-1bit-rpt = <1>; + }; + }; + }; diff --git a/Documentation/devicetree/bindings/sound/fsl-asoc-card.txt b/Documentation/devicetree/bindings/sound/fsl-asoc-card.txt index 8b4f4015cfe439ca3fbad14b79444572f739c7a1..4e8dbc5abfd1da2ff06e89244b47d6c3a318e64c 100644 --- a/Documentation/devicetree/bindings/sound/fsl-asoc-card.txt +++ b/Documentation/devicetree/bindings/sound/fsl-asoc-card.txt @@ -46,6 +46,8 @@ The compatible list for this generic sound card currently: "fsl,imx-audio-wm8958" + "fsl,imx-audio-nau8822" + Required properties: - compatible : Contains one of entries in the compatible list. diff --git a/Documentation/devicetree/bindings/sound/google,chv3-codec.yaml b/Documentation/devicetree/bindings/sound/google,chv3-codec.yaml new file mode 100644 index 0000000000000000000000000000000000000000..5329dc140b1c3dabbe3cd0da930ad984c82e043c --- /dev/null +++ b/Documentation/devicetree/bindings/sound/google,chv3-codec.yaml @@ -0,0 +1,31 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/google,chv3-codec.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Google Chameleon v3 audio codec + +maintainers: + - Paweł Anikiel + +allOf: + - $ref: dai-common.yaml# + +properties: + compatible: + const: google,chv3-codec + + "#sound-dai-cells": + const: 0 + +required: + - compatible + +additionalProperties: false + +examples: + - | + audio-codec { + compatible = "google,chv3-codec"; + }; diff --git a/Documentation/devicetree/bindings/sound/google,chv3-i2s.yaml b/Documentation/devicetree/bindings/sound/google,chv3-i2s.yaml new file mode 100644 index 0000000000000000000000000000000000000000..3ce910f44d393607c9255a742a5ce7cc34b953f3 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/google,chv3-i2s.yaml @@ -0,0 +1,44 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/google,chv3-i2s.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Google Chameleon v3 I2S device + +maintainers: + - Paweł Anikiel + +description: | + I2S device for the Google Chameleon v3. The device handles both RX + and TX using a producer/consumer ring buffer design. + +properties: + compatible: + const: google,chv3-i2s + + reg: + items: + - description: core registers + - description: irq registers + + interrupts: + maxItems: 1 + +required: + - compatible + - reg + - interrupts + +additionalProperties: false + +examples: + - | + #include + + i2s@c0060300 { + compatible = "google,chv3-i2s"; + reg = <0xc0060300 0x100>, + <0xc0060f00 0x10>; + interrupts = ; + }; diff --git a/Documentation/devicetree/bindings/sound/google,sc7180-trogdor.yaml b/Documentation/devicetree/bindings/sound/google,sc7180-trogdor.yaml index 67ccddd44489b323be952be4da215dce8a9e5e51..666a95ac22c81b49058549329844dc3f5780d6c8 100644 --- a/Documentation/devicetree/bindings/sound/google,sc7180-trogdor.yaml +++ b/Documentation/devicetree/bindings/sound/google,sc7180-trogdor.yaml @@ -74,7 +74,8 @@ patternProperties: properties: sound-dai: - maxItems: 1 + minItems: 1 + maxItems: 4 required: - link-name diff --git a/Documentation/devicetree/bindings/sound/ingenic,aic.yaml b/Documentation/devicetree/bindings/sound/ingenic,aic.yaml index c59a7cd9eaa9b222a1f5c7352d13cc75d2217848..d15c000f14e151e7d71082e426a03effeb8b6783 100644 --- a/Documentation/devicetree/bindings/sound/ingenic,aic.yaml +++ b/Documentation/devicetree/bindings/sound/ingenic,aic.yaml @@ -23,6 +23,7 @@ properties: - ingenic,jz4760-i2s - ingenic,jz4770-i2s - ingenic,jz4780-i2s + - ingenic,x1000-i2s - items: - const: ingenic,jz4725b-i2s - const: ingenic,jz4740-i2s diff --git a/Documentation/devicetree/bindings/sound/loongson,ls-audio-card.yaml b/Documentation/devicetree/bindings/sound/loongson,ls-audio-card.yaml new file mode 100644 index 0000000000000000000000000000000000000000..61e8babed402f0fde361046b9e4f131ecb83ca9e --- /dev/null +++ b/Documentation/devicetree/bindings/sound/loongson,ls-audio-card.yaml @@ -0,0 +1,70 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/loongson,ls-audio-card.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Loongson 7axxx/2kxxx ASoC audio sound card driver + +maintainers: + - Yingkun Meng + +description: + The binding describes the sound card present in loongson + 7axxx/2kxxx platform. The sound card is an ASoC component + which uses Loongson I2S controller to transfer the audio data. + +properties: + compatible: + const: loongson,ls-audio-card + + model: + $ref: /schemas/types.yaml#/definitions/string + description: User specified audio sound card name + + mclk-fs: + $ref: simple-card.yaml#/definitions/mclk-fs + + cpu: + description: Holds subnode which indicates cpu dai. + type: object + additionalProperties: false + properties: + sound-dai: + maxItems: 1 + required: + - sound-dai + + codec: + description: Holds subnode which indicates codec dai. + type: object + additionalProperties: false + properties: + sound-dai: + maxItems: 1 + required: + - sound-dai + +required: + - compatible + - model + - mclk-fs + - cpu + - codec + +additionalProperties: false + +examples: + - | + sound { + compatible = "loongson,ls-audio-card"; + model = "loongson-audio"; + mclk-fs = <512>; + + cpu { + sound-dai = <&i2s>; + }; + codec { + sound-dai = <&es8323>; + }; + }; diff --git a/Documentation/devicetree/bindings/sound/mediatek,mt8188-afe.yaml b/Documentation/devicetree/bindings/sound/mediatek,mt8188-afe.yaml index 82ccb32f08f27fde0063be8e5967eba7348ec006..e6cb711ece773b347562273bbaebafa472e3ec2f 100644 --- a/Documentation/devicetree/bindings/sound/mediatek,mt8188-afe.yaml +++ b/Documentation/devicetree/bindings/sound/mediatek,mt8188-afe.yaml @@ -29,6 +29,10 @@ properties: $ref: /schemas/types.yaml#/definitions/phandle description: The phandle of the mediatek topckgen controller + mediatek,infracfg: + $ref: /schemas/types.yaml#/definitions/phandle + description: The phandle of the mediatek infracfg controller + power-domains: maxItems: 1 @@ -52,6 +56,11 @@ properties: - description: mux for i2si1_mck - description: mux for i2si2_mck - description: audio 26m clock + - description: audio pll1 divide 4 + - description: audio pll2 divide 4 + - description: clock divider for iec + - description: mux for a2sys clock + - description: mux for aud_iec clock-names: items: @@ -63,16 +72,21 @@ properties: - const: apll12_div2 - const: apll12_div3 - const: apll12_div9 - - const: a1sys_hp_sel - - const: aud_intbus_sel - - const: audio_h_sel - - const: audio_local_bus_sel - - const: dptx_m_sel - - const: i2so1_m_sel - - const: i2so2_m_sel - - const: i2si1_m_sel - - const: i2si2_m_sel + - const: top_a1sys_hp + - const: top_aud_intbus + - const: top_audio_h + - const: top_audio_local_bus + - const: top_dptx + - const: top_i2so1 + - const: top_i2so2 + - const: top_i2si1 + - const: top_i2si2 - const: adsp_audio_26m + - const: apll1_d4 + - const: apll2_d4 + - const: apll12_div4 + - const: top_a2sys + - const: top_aud_iec mediatek,etdm-in1-cowork-source: $ref: /schemas/types.yaml#/definitions/uint32 @@ -144,6 +158,7 @@ required: - resets - reset-names - mediatek,topckgen + - mediatek,infracfg - power-domains - clocks - clock-names @@ -162,6 +177,7 @@ examples: resets = <&watchdog 14>; reset-names = "audiosys"; mediatek,topckgen = <&topckgen>; + mediatek,infracfg = <&infracfg_ao>; power-domains = <&spm 13>; //MT8188_POWER_DOMAIN_AUDIO mediatek,etdm-in2-cowork-source = <2>; mediatek,etdm-out2-cowork-source = <0>; @@ -184,7 +200,12 @@ examples: <&topckgen 78>, //CLK_TOP_I2SO2 <&topckgen 79>, //CLK_TOP_I2SI1 <&topckgen 80>, //CLK_TOP_I2SI2 - <&adsp_audio26m 0>; //CLK_AUDIODSP_AUDIO26M + <&adsp_audio26m 0>, //CLK_AUDIODSP_AUDIO26M + <&topckgen 132>, //CLK_TOP_APLL1_D4 + <&topckgen 133>, //CLK_TOP_APLL2_D4 + <&topckgen 183>, //CLK_TOP_APLL12_CK_DIV4 + <&topckgen 84>, //CLK_TOP_A2SYS + <&topckgen 82>; //CLK_TOP_AUD_IEC>; clock-names = "clk26m", "apll1", "apll2", @@ -193,16 +214,21 @@ examples: "apll12_div2", "apll12_div3", "apll12_div9", - "a1sys_hp_sel", - "aud_intbus_sel", - "audio_h_sel", - "audio_local_bus_sel", - "dptx_m_sel", - "i2so1_m_sel", - "i2so2_m_sel", - "i2si1_m_sel", - "i2si2_m_sel", - "adsp_audio_26m"; + "top_a1sys_hp", + "top_aud_intbus", + "top_audio_h", + "top_audio_local_bus", + "top_dptx", + "top_i2so1", + "top_i2so2", + "top_i2si1", + "top_i2si2", + "adsp_audio_26m", + "apll1_d4", + "apll2_d4", + "apll12_div4", + "top_a2sys", + "top_aud_iec"; }; ... diff --git a/Documentation/devicetree/bindings/sound/mediatek,mt8188-mt6359.yaml b/Documentation/devicetree/bindings/sound/mediatek,mt8188-mt6359.yaml index 6640272b3f4f6d5c4d49c96dc314ef746055a699..05e532b5d50a664e1145984accead4ff87485f64 100644 --- a/Documentation/devicetree/bindings/sound/mediatek,mt8188-mt6359.yaml +++ b/Documentation/devicetree/bindings/sound/mediatek,mt8188-mt6359.yaml @@ -11,7 +11,9 @@ maintainers: properties: compatible: - const: mediatek,mt8188-mt6359-evb + enum: + - mediatek,mt8188-mt6359-evb + - mediatek,mt8188-nau8825 model: $ref: /schemas/types.yaml#/definitions/string @@ -42,7 +44,6 @@ patternProperties: we are going to update parameters in this node. items: enum: - - ADDA_BE - DPTX_BE - ETDM1_IN_BE - ETDM2_IN_BE @@ -62,11 +63,28 @@ patternProperties: required: - sound-dai + dai-format: + description: audio format. + items: + enum: + - i2s + - right_j + - left_j + - dsp_a + - dsp_b + + mediatek,clk-provider: + $ref: /schemas/types.yaml#/definitions/string + description: Indicates dai-link clock master. + items: + enum: + - cpu + - codec + additionalProperties: false required: - link-name - - codec additionalProperties: false @@ -87,7 +105,8 @@ examples: "AIN1", "Headset Mic"; dai-link-0 { link-name = "ETDM3_OUT_BE"; - + dai-format = "i2s"; + mediatek,clk-provider = "cpu"; codec { sound-dai = <&hdmi0>; }; diff --git a/Documentation/devicetree/bindings/sound/microchip,sama7g5-pdmc.yaml b/Documentation/devicetree/bindings/sound/microchip,sama7g5-pdmc.yaml index 9b40268537cb2a56f33f36e6e64ba282b71e2082..9aa65c975c4e35b4f9e660f3fd41a30b197c9a87 100644 --- a/Documentation/devicetree/bindings/sound/microchip,sama7g5-pdmc.yaml +++ b/Documentation/devicetree/bindings/sound/microchip,sama7g5-pdmc.yaml @@ -56,13 +56,9 @@ properties: items: items: - description: value for DS line + enum: [0, 1] - description: value for sampling edge - anyOf: - - enum: - - [0, 0] - - [0, 1] - - [1, 0] - - [1, 1] + enum: [0, 1] minItems: 1 maxItems: 4 uniqueItems: true diff --git a/Documentation/devicetree/bindings/sound/nau8315.txt b/Documentation/devicetree/bindings/sound/nau8315.txt deleted file mode 100644 index 1cd94517d45e0178e71dca067464646dc66f45fe..0000000000000000000000000000000000000000 --- a/Documentation/devicetree/bindings/sound/nau8315.txt +++ /dev/null @@ -1,24 +0,0 @@ -Nuvoton NAU8315 Mono Class-D Amplifier - -Required properties: -- compatible : "nuvoton,nau8315" - "nuvoton,nau8318" - -Optional properties: -- enable-gpios : GPIO specifier for the chip's device enable input(EN) pin. - If this option is not specified then driver does not manage - the pin state (e.g. chip is always on). - -Example: - -#include - -nau8315 { - compatible = "nuvoton,nau8315"; - enable-gpios = <&gpio1 5 GPIO_ACTIVE_HIGH>; -}; - -nau8318 { - compatible = "nuvoton,nau8318"; - enable-gpios = <&gpio1 5 GPIO_ACTIVE_HIGH>; -}; diff --git a/Documentation/devicetree/bindings/sound/nau8540.txt b/Documentation/devicetree/bindings/sound/nau8540.txt deleted file mode 100644 index 307a765283208ef441c8be17a6e9efe5d00bc805..0000000000000000000000000000000000000000 --- a/Documentation/devicetree/bindings/sound/nau8540.txt +++ /dev/null @@ -1,16 +0,0 @@ -NAU85L40 audio CODEC - -This device supports I2C only. - -Required properties: - - - compatible : "nuvoton,nau8540" - - - reg : the I2C address of the device. - -Example: - -codec: nau8540@1c { - compatible = "nuvoton,nau8540"; - reg = <0x1c>; -}; diff --git a/Documentation/devicetree/bindings/sound/nau8810.txt b/Documentation/devicetree/bindings/sound/nau8810.txt deleted file mode 100644 index 7deaa452b20026a097d03784617bdb5a3d60c9fa..0000000000000000000000000000000000000000 --- a/Documentation/devicetree/bindings/sound/nau8810.txt +++ /dev/null @@ -1,17 +0,0 @@ -NAU8810/NAU8812/NAU8814 audio CODEC - -This device supports I2C only. - -Required properties: - - - compatible : One of "nuvoton,nau8810" or "nuvoton,nau8812" or - "nuvoton,nau8814" - - - reg : the I2C address of the device. - -Example: - -codec: nau8810@1a { - compatible = "nuvoton,nau8810"; - reg = <0x1a>; -}; diff --git a/Documentation/devicetree/bindings/sound/nau8824.txt b/Documentation/devicetree/bindings/sound/nau8824.txt deleted file mode 100644 index e0058b97e49a48240dee993beca7ae27ea994f8e..0000000000000000000000000000000000000000 --- a/Documentation/devicetree/bindings/sound/nau8824.txt +++ /dev/null @@ -1,88 +0,0 @@ -Nuvoton NAU8824 audio codec - -This device supports I2C only. - -Required properties: - - compatible : Must be "nuvoton,nau8824" - - - reg : the I2C address of the device. This is either 0x1a (CSB=0) or 0x1b (CSB=1). - -Optional properties: - - nuvoton,jkdet-polarity: JKDET pin polarity. 0 - active high, 1 - active low. - - - nuvoton,vref-impedance: VREF Impedance selection - 0 - Open - 1 - 25 kOhm - 2 - 125 kOhm - 3 - 2.5 kOhm - - - nuvoton,micbias-voltage: Micbias voltage level. - 0 - VDDA - 1 - VDDA - 2 - VDDA * 1.1 - 3 - VDDA * 1.2 - 4 - VDDA * 1.3 - 5 - VDDA * 1.4 - 6 - VDDA * 1.53 - 7 - VDDA * 1.53 - - - nuvoton,sar-threshold-num: Number of buttons supported - - nuvoton,sar-threshold: Impedance threshold for each button. Array that contains up to 8 buttons configuration. SAR value is calculated as - SAR = 255 * MICBIAS / SAR_VOLTAGE * R / (2000 + R) - where MICBIAS is configured by 'nuvoton,micbias-voltage', SAR_VOLTAGE is configured by 'nuvoton,sar-voltage', R - button impedance. - Refer datasheet section 10.2 for more information about threshold calculation. - - - nuvoton,sar-hysteresis: Button impedance measurement hysteresis. - - - nuvoton,sar-voltage: Reference voltage for button impedance measurement. - 0 - VDDA - 1 - VDDA - 2 - VDDA * 1.1 - 3 - VDDA * 1.2 - 4 - VDDA * 1.3 - 5 - VDDA * 1.4 - 6 - VDDA * 1.53 - 7 - VDDA * 1.53 - - - nuvoton,sar-compare-time: SAR compare time - 0 - 500 ns - 1 - 1 us - 2 - 2 us - 3 - 4 us - - - nuvoton,sar-sampling-time: SAR sampling time - 0 - 2 us - 1 - 4 us - 2 - 8 us - 3 - 16 us - - - nuvoton,short-key-debounce: Button short key press debounce time. - 0 - 30 ms - 1 - 50 ms - 2 - 100 ms - - - nuvoton,jack-eject-debounce: Jack ejection debounce time. - 0 - 0 ms - 1 - 1 ms - 2 - 10 ms - - -Example: - - headset: nau8824@1a { - compatible = "nuvoton,nau8824"; - reg = <0x1a>; - interrupt-parent = <&gpio>; - interrupts = ; - nuvoton,vref-impedance = <2>; - nuvoton,micbias-voltage = <6>; - // Setup 4 buttons impedance according to Android specification - nuvoton,sar-threshold-num = <4>; - nuvoton,sar-threshold = <0xc 0x1e 0x38 0x60>; - nuvoton,sar-hysteresis = <0>; - nuvoton,sar-voltage = <6>; - nuvoton,sar-compare-time = <1>; - nuvoton,sar-sampling-time = <1>; - nuvoton,short-key-debounce = <0>; - nuvoton,jack-eject-debounce = <1>; - }; diff --git a/Documentation/devicetree/bindings/sound/nau8825.txt b/Documentation/devicetree/bindings/sound/nau8825.txt deleted file mode 100644 index a9c34526f4cb0b078a6a7a4e1ecaa6fd7adc35dc..0000000000000000000000000000000000000000 --- a/Documentation/devicetree/bindings/sound/nau8825.txt +++ /dev/null @@ -1,111 +0,0 @@ -Nuvoton NAU8825 audio codec - -This device supports I2C only. - -Required properties: - - compatible : Must be "nuvoton,nau8825" - - - reg : the I2C address of the device. This is either 0x1a (CSB=0) or 0x1b (CSB=1). - -Optional properties: - - nuvoton,jkdet-enable: Enable jack detection via JKDET pin. - - nuvoton,jkdet-pull-enable: Enable JKDET pin pull. If set - pin pull enabled, - otherwise pin in high impedance state. - - nuvoton,jkdet-pull-up: Pull-up JKDET pin. If set then JKDET pin is pull up, otherwise pull down. - - nuvoton,jkdet-polarity: JKDET pin polarity. 0 - active high, 1 - active low. - - - nuvoton,vref-impedance: VREF Impedance selection - 0 - Open - 1 - 25 kOhm - 2 - 125 kOhm - 3 - 2.5 kOhm - - - nuvoton,micbias-voltage: Micbias voltage level. - 0 - VDDA - 1 - VDDA - 2 - VDDA * 1.1 - 3 - VDDA * 1.2 - 4 - VDDA * 1.3 - 5 - VDDA * 1.4 - 6 - VDDA * 1.53 - 7 - VDDA * 1.53 - - - nuvoton,sar-threshold-num: Number of buttons supported - - nuvoton,sar-threshold: Impedance threshold for each button. Array that contains up to 8 buttons configuration. SAR value is calculated as - SAR = 255 * MICBIAS / SAR_VOLTAGE * R / (2000 + R) - where MICBIAS is configured by 'nuvoton,micbias-voltage', SAR_VOLTAGE is configured by 'nuvoton,sar-voltage', R - button impedance. - Refer datasheet section 10.2 for more information about threshold calculation. - - - nuvoton,sar-hysteresis: Button impedance measurement hysteresis. - - - nuvoton,sar-voltage: Reference voltage for button impedance measurement. - 0 - VDDA - 1 - VDDA - 2 - VDDA * 1.1 - 3 - VDDA * 1.2 - 4 - VDDA * 1.3 - 5 - VDDA * 1.4 - 6 - VDDA * 1.53 - 7 - VDDA * 1.53 - - - nuvoton,sar-compare-time: SAR compare time - 0 - 500 ns - 1 - 1 us - 2 - 2 us - 3 - 4 us - - - nuvoton,sar-sampling-time: SAR sampling time - 0 - 2 us - 1 - 4 us - 2 - 8 us - 3 - 16 us - - - nuvoton,short-key-debounce: Button short key press debounce time. - 0 - 30 ms - 1 - 50 ms - 2 - 100 ms - 3 - 30 ms - - - nuvoton,jack-insert-debounce: number from 0 to 7 that sets debounce time to 2^(n+2) ms - - nuvoton,jack-eject-debounce: number from 0 to 7 that sets debounce time to 2^(n+2) ms - - - nuvoton,crosstalk-enable: make crosstalk function enable if set. - - - nuvoton,adcout-drive-strong: make the drive strength of ADCOUT IO PIN strong if set. - Otherwise, the drive keeps normal strength. - - - nuvoton,adc-delay-ms: Delay (in ms) to make input path stable and avoid pop noise. The - default value is 125 and range between 125 to 500 ms. - - - clocks: list of phandle and clock specifier pairs according to common clock bindings for the - clocks described in clock-names - - clock-names: should include "mclk" for the MCLK master clock - -Example: - - headset: nau8825@1a { - compatible = "nuvoton,nau8825"; - reg = <0x1a>; - interrupt-parent = <&gpio>; - interrupts = ; - nuvoton,jkdet-enable; - nuvoton,jkdet-pull-enable; - nuvoton,jkdet-pull-up; - nuvoton,jkdet-polarity = ; - nuvoton,vref-impedance = <2>; - nuvoton,micbias-voltage = <6>; - // Setup 4 buttons impedance according to Android specification - nuvoton,sar-threshold-num = <4>; - nuvoton,sar-threshold = <0xc 0x1e 0x38 0x60>; - nuvoton,sar-hysteresis = <1>; - nuvoton,sar-voltage = <0>; - nuvoton,sar-compare-time = <0>; - nuvoton,sar-sampling-time = <0>; - nuvoton,short-key-debounce = <2>; - nuvoton,jack-insert-debounce = <7>; - nuvoton,jack-eject-debounce = <7>; - nuvoton,crosstalk-enable; - - clock-names = "mclk"; - clocks = <&tegra_pmc TEGRA_PMC_CLK_OUT_2>; - }; diff --git a/Documentation/devicetree/bindings/sound/nuvoton,nau8315.yaml b/Documentation/devicetree/bindings/sound/nuvoton,nau8315.yaml new file mode 100644 index 0000000000000000000000000000000000000000..24006e9dc501c00048fed39a6705980b08fd5854 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/nuvoton,nau8315.yaml @@ -0,0 +1,44 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/nuvoton,nau8315.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: NAU8315/NAU8318 Mono Class-D Amplifier + +maintainers: + - David Lin + +allOf: + - $ref: dai-common.yaml# + +properties: + compatible: + enum: + - nuvoton,nau8315 + - nuvoton,nau8318 + + '#sound-dai-cells': + const: 0 + + enable-gpios: + maxItems: 1 + description: + GPIO specifier for the chip's device enable input(EN) pin. + If this option is not specified then driver does not manage + the pin state (e.g. chip is always on). + +required: + - compatible + +unevaluatedProperties: false + +examples: + - | + #include + + codec { + compatible = "nuvoton,nau8315"; + #sound-dai-cells = <0>; + enable-gpios = <&gpio1 5 GPIO_ACTIVE_HIGH>; + }; diff --git a/Documentation/devicetree/bindings/sound/nuvoton,nau8540.yaml b/Documentation/devicetree/bindings/sound/nuvoton,nau8540.yaml new file mode 100644 index 0000000000000000000000000000000000000000..7ccfbb8d8b0433ee0be663cd0e3abbb43c0ba3e3 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/nuvoton,nau8540.yaml @@ -0,0 +1,40 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/nuvoton,nau8540.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Nuvoton Technology Corporation NAU85L40 Audio CODEC + +maintainers: + - John Hsu + +allOf: + - $ref: dai-common.yaml# + +properties: + compatible: + const: nuvoton,nau8540 + + reg: + maxItems: 1 + + "#sound-dai-cells": + const: 0 + +required: + - compatible + - reg + +unevaluatedProperties: false + +examples: + - | + i2c { + #address-cells = <1>; + #size-cells = <0>; + codec@1c { + compatible = "nuvoton,nau8540"; + reg = <0x1c>; + }; + }; diff --git a/Documentation/devicetree/bindings/sound/nuvoton,nau8810.yaml b/Documentation/devicetree/bindings/sound/nuvoton,nau8810.yaml new file mode 100644 index 0000000000000000000000000000000000000000..d9696f6c75edd1fae470a00987a7e34fefc070f6 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/nuvoton,nau8810.yaml @@ -0,0 +1,45 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/nuvoton,nau8810.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: NAU8810/NAU8812/NAU8814 audio CODEC + +maintainers: + - David Lin + +allOf: + - $ref: dai-common.yaml# + +properties: + compatible: + enum: + - nuvoton,nau8810 + - nuvoton,nau8812 + - nuvoton,nau8814 + + reg: + maxItems: 1 + + '#sound-dai-cells': + const: 0 + +required: + - compatible + - reg + +unevaluatedProperties: false + +examples: + - | + i2c { + #address-cells = <1>; + #size-cells = <0>; + + codec@1a { + #sound-dai-cells = <0>; + compatible = "nuvoton,nau8810"; + reg = <0x1a>; + }; + }; diff --git a/Documentation/devicetree/bindings/sound/nuvoton,nau8824.yaml b/Documentation/devicetree/bindings/sound/nuvoton,nau8824.yaml new file mode 100644 index 0000000000000000000000000000000000000000..3dbf438c38410e5979d48a4d9137acdb7f7d8a1c --- /dev/null +++ b/Documentation/devicetree/bindings/sound/nuvoton,nau8824.yaml @@ -0,0 +1,182 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/nuvoton,nau8824.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: NAU8824 audio CODEC + +maintainers: + - John Hsu + +allOf: + - $ref: dai-common.yaml# + +properties: + compatible: + enum: + - nuvoton,nau8824 + + reg: + maxItems: 1 + + '#sound-dai-cells': + const: 0 + + interrupts: + maxItems: 1 + + nuvoton,jkdet-polarity: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + JKDET pin polarity. + enum: + - 0 # active high + - 1 # active low + default: 1 + + nuvoton,vref-impedance: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + VREF Impedance selection. + enum: + - 0 # Open + - 1 # 25 kOhm + - 2 # 125 kOhm + - 3 # 2.5 kOhm + default: 2 + + nuvoton,micbias-voltage: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + Micbias voltage level. + enum: + - 0 # VDDA + - 1 # VDDA + - 2 # VDDA * 1.1 + - 3 # VDDA * 1.2 + - 4 # VDDA * 1.3 + - 5 # VDDA * 1.4 + - 6 # VDDA * 1.53 + - 7 # VDDA * 1.53 + default: 6 + + nuvoton,sar-threshold-num: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + Number of buttons supported. + minimum: 1 + maximum: 8 + default: 4 + + nuvoton,sar-threshold: + $ref: /schemas/types.yaml#/definitions/uint32-array + description: + Impedance threshold for each button. Array that contains up to 8 buttons + configuration. SAR value is calculated as + SAR = 255 * MICBIAS / SAR_VOLTAGE * R / (2000 + R) where MICBIAS is + configured by 'nuvoton,micbias-voltage', SAR_VOLTAGE is configured by + 'nuvoton,sar-voltage', R - button impedance. + Refer datasheet section 10.2 for more information about threshold + calculation. + minItems: 1 + maxItems: 8 + items: + minimum: 0 + maximum: 255 + + nuvoton,sar-hysteresis: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + Button impedance measurement hysteresis. + default: 0 + + nuvoton,sar-voltage: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + Reference voltage for button impedance measurement. + enum: + - 0 # VDDA + - 1 # VDDA + - 2 # VDDA * 1.1 + - 3 # VDDA * 1.2 + - 4 # VDDA * 1.3 + - 5 # VDDA * 1.4 + - 6 # VDDA * 1.53 + - 7 # VDDA * 1.53 + default: 6 + + nuvoton,sar-compare-time: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + SAR compare time. + enum: + - 0 # 500ns + - 1 # 1us + - 2 # 2us + - 3 # 4us + default: 1 + + nuvoton,sar-sampling-time: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + SAR sampling time. + enum: + - 0 # 2us + - 1 # 4us + - 2 # 8us + - 3 # 16us + default: 1 + + nuvoton,short-key-debounce: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + Button short key press debounce time. + enum: + - 0 # 30 ms + - 1 # 50 ms + - 2 # 100 ms + default: 0 + + nuvoton,jack-eject-debounce: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + Jack ejection debounce time. + enum: + - 0 # 0 ms + - 1 # 1 ms + - 2 # 10 ms + default: 1 + +required: + - compatible + - reg + +unevaluatedProperties: false + +examples: + - | + #include + #include + i2c { + #address-cells = <1>; + #size-cells = <0>; + codec@1a { + #sound-dai-cells = <0>; + compatible = "nuvoton,nau8824"; + reg = <0x1a>; + interrupt-parent = <&gpio>; + interrupts = <38 IRQ_TYPE_LEVEL_LOW>; + nuvoton,vref-impedance = <2>; + nuvoton,micbias-voltage = <6>; + nuvoton,sar-threshold-num = <4>; + // Setup 4 buttons impedance according to Android specification + nuvoton,sar-threshold = <0xc 0x1e 0x38 0x60>; + nuvoton,sar-hysteresis = <0>; + nuvoton,sar-voltage = <6>; + nuvoton,sar-compare-time = <1>; + nuvoton,sar-sampling-time = <1>; + nuvoton,short-key-debounce = <0>; + nuvoton,jack-eject-debounce = <1>; + }; + }; diff --git a/Documentation/devicetree/bindings/sound/nuvoton,nau8825.yaml b/Documentation/devicetree/bindings/sound/nuvoton,nau8825.yaml new file mode 100644 index 0000000000000000000000000000000000000000..a54f194a0b4923484cba6b6438d1c29923b77f76 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/nuvoton,nau8825.yaml @@ -0,0 +1,239 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/nuvoton,nau8825.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: NAU8825 audio CODEC + +maintainers: + - John Hsu + +allOf: + - $ref: dai-common.yaml# + +properties: + compatible: + enum: + - nuvoton,nau8825 + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + nuvoton,jkdet-enable: + description: + Enable jack detection via JKDET pin. + type: boolean + + nuvoton,jkdet-pull-enable: + description: + Enable JKDET pin pull. + If set - pin pull enabled, otherwise pin in high impedance state. + type: boolean + + nuvoton,jkdet-pull-up: + description: + Pull-up JKDET pin. + If set then JKDET pin is pull up, otherwise pull down. + type: boolean + + nuvoton,jkdet-polarity: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + JKDET pin polarity. + enum: + - 0 # active high + - 1 # active low + default: 1 + + nuvoton,vref-impedance: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + VREF Impedance selection. + enum: + - 0 # Open + - 1 # 25 kOhm + - 2 # 125 kOhm + - 3 # 2.5 kOhm + default: 2 + + nuvoton,micbias-voltage: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + Micbias voltage level. + enum: + - 0 # VDDA + - 1 # VDDA + - 2 # VDDA * 1.1 + - 3 # VDDA * 1.2 + - 4 # VDDA * 1.3 + - 5 # VDDA * 1.4 + - 6 # VDDA * 1.53 + - 7 # VDDA * 1.53 + default: 6 + + nuvoton,sar-threshold-num: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + Number of buttons supported. + minimum: 1 + maximum: 4 + default: 4 + + nuvoton,sar-threshold: + $ref: /schemas/types.yaml#/definitions/uint32-array + description: + Impedance threshold for each button. Array that contains up to 8 buttons + configuration. SAR value is calculated as + SAR = 255 * MICBIAS / SAR_VOLTAGE * R / (2000 + R) where MICBIAS is + configured by 'nuvoton,micbias-voltage', SAR_VOLTAGE is configured by + 'nuvoton,sar-voltage', R - button impedance. + Refer datasheet section 10.2 for more information about threshold + calculation. + minItems: 1 + maxItems: 4 + items: + minimum: 0 + maximum: 255 + + nuvoton,sar-hysteresis: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + Button impedance measurement hysteresis. + default: 0 + + nuvoton,sar-voltage: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + Reference voltage for button impedance measurement. + enum: + - 0 # VDDA + - 1 # VDDA + - 2 # VDDA * 1.1 + - 3 # VDDA * 1.2 + - 4 # VDDA * 1.3 + - 5 # VDDA * 1.4 + - 6 # VDDA * 1.53 + - 7 # VDDA * 1.53 + default: 6 + + nuvoton,sar-compare-time: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + SAR compare time. + enum: + - 0 # 500 ns + - 1 # 1 us + - 2 # 2 us + - 3 # 4 us + default: 1 + + nuvoton,sar-sampling-time: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + SAR sampling time. + enum: + - 0 # 2 us + - 1 # 4 us + - 2 # 8 us + - 3 # 16 us + default: 1 + + nuvoton,short-key-debounce: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + Button short key press debounce time. + enum: + - 0 # 30 ms + - 1 # 50 ms + - 2 # 100 ms + - 3 # 30 ms + default: 3 + + nuvoton,jack-insert-debounce: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + number from 0 to 7 that sets debounce time to 2^(n+2) ms. + maximum: 7 + default: 7 + + nuvoton,jack-eject-debounce: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + number from 0 to 7 that sets debounce time to 2^(n+2) ms + maximum: 7 + default: 0 + + nuvoton,crosstalk-enable: + description: + make crosstalk function enable if set. + type: boolean + + nuvoton,adcout-drive-strong: + description: + make the drive strength of ADCOUT IO PIN strong if set. + Otherwise, the drive keeps normal strength. + type: boolean + + nuvoton,adc-delay-ms: + description: + Delay (in ms) to make input path stable and avoid pop noise. + The default value is 125 and range between 125 to 500 ms. + minimum: 125 + maximum: 500 + default: 125 + + clocks: + maxItems: 1 + + clock-names: + items: + - const: mclk + + '#sound-dai-cells': + const: 0 + +required: + - compatible + - reg + +unevaluatedProperties: false + +examples: + - | + #include + #include + i2c { + #address-cells = <1>; + #size-cells = <0>; + codec@1a { + #sound-dai-cells = <0>; + compatible = "nuvoton,nau8825"; + reg = <0x1a>; + interrupt-parent = <&gpio>; + interrupts = <38 IRQ_TYPE_LEVEL_LOW>; + nuvoton,jkdet-enable; + nuvoton,jkdet-pull-enable; + nuvoton,jkdet-pull-up; + nuvoton,jkdet-polarity = ; + nuvoton,vref-impedance = <2>; + nuvoton,micbias-voltage = <6>; + // Setup 4 buttons impedance according to Android specification + nuvoton,sar-threshold-num = <4>; + nuvoton,sar-threshold = <0xc 0x1e 0x38 0x60>; + nuvoton,sar-hysteresis = <1>; + nuvoton,sar-voltage = <0>; + nuvoton,sar-compare-time = <0>; + nuvoton,sar-sampling-time = <0>; + nuvoton,short-key-debounce = <2>; + nuvoton,jack-insert-debounce = <7>; + nuvoton,jack-eject-debounce = <7>; + nuvoton,crosstalk-enable; + + clock-names = "mclk"; + clocks = <&tegra_pmc 1>; + }; + }; diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-common.yaml b/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-common.yaml index 7c1e9895ce858b2539affa1c1ca8e34a2cb4eda4..2588589ad62d396123c2cb55d1d8c9578f3a62cc 100644 --- a/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-common.yaml +++ b/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-common.yaml @@ -1,8 +1,8 @@ # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) %YAML 1.2 --- -$id: "http://devicetree.org/schemas/sound/nvidia,tegra-audio-common.yaml#" -$schema: "http://devicetree.org/meta-schemas/core.yaml#" +$id: http://devicetree.org/schemas/sound/nvidia,tegra-audio-common.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# title: Common properties for NVIDIA Tegra audio complexes diff --git a/Documentation/devicetree/bindings/sound/qcom,q6apm-dai.yaml b/Documentation/devicetree/bindings/sound/qcom,q6apm-dai.yaml index cdbb4096fa44f561e83e50d58d6744be40b2e954..9e5b30d9c6e62d096b81e07c88925e083d0a7a79 100644 --- a/Documentation/devicetree/bindings/sound/qcom,q6apm-dai.yaml +++ b/Documentation/devicetree/bindings/sound/qcom,q6apm-dai.yaml @@ -1,8 +1,8 @@ # SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) %YAML 1.2 --- -$id: "http://devicetree.org/schemas/sound/qcom,q6apm-dai.yaml#" -$schema: "http://devicetree.org/meta-schemas/core.yaml#" +$id: http://devicetree.org/schemas/sound/qcom,q6apm-dai.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# title: Qualcomm Audio Process Manager Digital Audio Interfaces diff --git a/Documentation/devicetree/bindings/sound/qcom,q6dsp-lpass-clocks.yaml b/Documentation/devicetree/bindings/sound/qcom,q6dsp-lpass-clocks.yaml index 1168410f6fbd7e0ab1a29a1ed026815c0df58f4a..3552c44137ed248472737fe4c50b10e93e591255 100644 --- a/Documentation/devicetree/bindings/sound/qcom,q6dsp-lpass-clocks.yaml +++ b/Documentation/devicetree/bindings/sound/qcom,q6dsp-lpass-clocks.yaml @@ -1,8 +1,8 @@ # SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) %YAML 1.2 --- -$id: "http://devicetree.org/schemas/sound/qcom,q6dsp-lpass-clocks.yaml#" -$schema: "http://devicetree.org/meta-schemas/core.yaml#" +$id: http://devicetree.org/schemas/sound/qcom,q6dsp-lpass-clocks.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# title: Qualcomm DSP LPASS Clock Controller diff --git a/Documentation/devicetree/bindings/sound/qcom,q6dsp-lpass-ports.yaml b/Documentation/devicetree/bindings/sound/qcom,q6dsp-lpass-ports.yaml index 044e77718a1bfe76248118c4af5d613b54d81b01..08c618e7e4281d46c520b26ea24225bddd0d5e8b 100644 --- a/Documentation/devicetree/bindings/sound/qcom,q6dsp-lpass-ports.yaml +++ b/Documentation/devicetree/bindings/sound/qcom,q6dsp-lpass-ports.yaml @@ -1,8 +1,8 @@ # SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) %YAML 1.2 --- -$id: "http://devicetree.org/schemas/sound/qcom,q6dsp-lpass-ports.yaml#" -$schema: "http://devicetree.org/meta-schemas/core.yaml#" +$id: http://devicetree.org/schemas/sound/qcom,q6dsp-lpass-ports.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# title: Qualcomm DSP LPASS(Low Power Audio SubSystem) Audio Ports diff --git a/Documentation/devicetree/bindings/sound/qcom,wsa8840.yaml b/Documentation/devicetree/bindings/sound/qcom,wsa8840.yaml new file mode 100644 index 0000000000000000000000000000000000000000..e6723c9e312a07470056cb38646a83192176a20e --- /dev/null +++ b/Documentation/devicetree/bindings/sound/qcom,wsa8840.yaml @@ -0,0 +1,66 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/qcom,wsa8840.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm WSA8840/WSA8845/WSA8845H smart speaker amplifier + +maintainers: + - Krzysztof Kozlowski + - Srinivas Kandagatla + +description: + WSA884X is a family of Qualcomm Aqstic smart speaker amplifiers using + SoundWire digital audio interface. + +allOf: + - $ref: dai-common.yaml# + +properties: + compatible: + const: sdw20217020400 + + reg: + maxItems: 1 + + powerdown-gpios: + description: Powerdown/Shutdown line to use (pin SD_N) + maxItems: 1 + + '#sound-dai-cells': + const: 0 + + vdd-1p8-supply: true + vdd-io-supply: true + +required: + - compatible + - reg + - powerdown-gpios + - '#sound-dai-cells' + - vdd-1p8-supply + - vdd-io-supply + +unevaluatedProperties: false + +examples: + - | + #include + + soundwire-controller { + #address-cells = <2>; + #size-cells = <0>; + + speaker@0,1 { + compatible = "sdw20217020400"; + reg = <0 1>; + pinctrl-names = "default"; + pinctrl-0 = <&spkr_2_sd_n_active>; + powerdown-gpios = <&lpass_tlmm 18 GPIO_ACTIVE_LOW>; + #sound-dai-cells = <0>; + sound-name-prefix = "SpkrRight"; + vdd-1p8-supply = <&vreg_l15b_1p8>; + vdd-io-supply = <&vreg_l3g_1p2>; + }; + }; diff --git a/Documentation/devicetree/bindings/sound/realtek,rt1016.yaml b/Documentation/devicetree/bindings/sound/realtek,rt1016.yaml new file mode 100644 index 0000000000000000000000000000000000000000..5287e9c9197e0d51da61295e895ae3959396486e --- /dev/null +++ b/Documentation/devicetree/bindings/sound/realtek,rt1016.yaml @@ -0,0 +1,40 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/realtek,rt1016.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Reaktek RT1016 Stereo Class D Audio Amplifier + +maintainers: + - oder_chiou@realtek.com + +allOf: + - $ref: dai-common.yaml# + +properties: + compatible: + const: realtek,rt1016 + + reg: + maxItems: 1 + + "#sound-dai-cells": + const: 0 + +required: + - compatible + - reg + +unevaluatedProperties: false + +examples: + - | + i2c { + #address-cells = <1>; + #size-cells = <0>; + codec@1a { + compatible = "realtek,rt1016"; + reg = <0x1a>; + }; + }; diff --git a/Documentation/devicetree/bindings/sound/rt1016.txt b/Documentation/devicetree/bindings/sound/rt1016.txt deleted file mode 100644 index 2310f8ff259bc0ae6d1824b488168db5d6d8484f..0000000000000000000000000000000000000000 --- a/Documentation/devicetree/bindings/sound/rt1016.txt +++ /dev/null @@ -1,17 +0,0 @@ -RT1016 Stereo Class D Audio Amplifier - -This device supports I2C only. - -Required properties: - -- compatible : "realtek,rt1016". - -- reg : The I2C address of the device. - - -Example: - -rt1016: codec@1a { - compatible = "realtek,rt1016"; - reg = <0x1a>; -}; diff --git a/Documentation/devicetree/bindings/sound/snps,designware-i2s.yaml b/Documentation/devicetree/bindings/sound/snps,designware-i2s.yaml index 56e623d4e168f796a5001978cbebe4ce058c5e5e..a970fd264b2135c27de38825f966417e22284ec5 100644 --- a/Documentation/devicetree/bindings/sound/snps,designware-i2s.yaml +++ b/Documentation/devicetree/bindings/sound/snps,designware-i2s.yaml @@ -36,7 +36,8 @@ properties: const: i2sclk resets: - maxItems: 1 + items: + - description: Optional controller resets dmas: items: diff --git a/Documentation/devicetree/bindings/sound/ssm2518.txt b/Documentation/devicetree/bindings/sound/ssm2518.txt deleted file mode 100644 index 59381a778c7979bb56d7e494906641baf088f402..0000000000000000000000000000000000000000 --- a/Documentation/devicetree/bindings/sound/ssm2518.txt +++ /dev/null @@ -1,20 +0,0 @@ -SSM2518 audio amplifier - -This device supports I2C only. - -Required properties: - - compatible : Must be "adi,ssm2518" - - reg : the I2C address of the device. This will either be 0x34 (ADDR pin low) - or 0x35 (ADDR pin high) - -Optional properties: - - gpios : GPIO connected to the nSD pin. If the property is not present it is - assumed that the nSD pin is hardwired to always on. - -Example: - - ssm2518: ssm2518@34 { - compatible = "adi,ssm2518"; - reg = <0x34>; - gpios = <&gpio 5 0>; - }; diff --git a/Documentation/devicetree/bindings/sound/st,stm32-i2s.yaml b/Documentation/devicetree/bindings/sound/st,stm32-i2s.yaml index a040d4d3141205585e6971d0a7c420a8073307ed..b9111d375b93f52de81452e2a119c833ee2f9e22 100644 --- a/Documentation/devicetree/bindings/sound/st,stm32-i2s.yaml +++ b/Documentation/devicetree/bindings/sound/st,stm32-i2s.yaml @@ -61,6 +61,10 @@ properties: description: Configure the I2S device as MCLK clock provider. const: 0 + port: + $ref: audio-graph-port.yaml# + unevaluatedProperties: false + required: - compatible - "#sound-dai-cells" @@ -89,6 +93,13 @@ examples: dma-names = "rx", "tx"; pinctrl-names = "default"; pinctrl-0 = <&i2s2_pins_a>; + + /* assume audio-graph */ + port { + codec_endpoint: endpoint { + remote-endpoint = <&codec_endpoint>; + }; + }; }; ... diff --git a/Documentation/devicetree/bindings/sound/starfive,jh7110-tdm.yaml b/Documentation/devicetree/bindings/sound/starfive,jh7110-tdm.yaml new file mode 100644 index 0000000000000000000000000000000000000000..abb373fbfa2692ea046400f5c1e83d65215de710 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/starfive,jh7110-tdm.yaml @@ -0,0 +1,98 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/starfive,jh7110-tdm.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: StarFive JH7110 TDM Controller + +description: | + The TDM Controller is a Time Division Multiplexed audio interface + integrated in StarFive JH7110 SoC, allowing up to 8 channels of + audio over a serial interface. The TDM controller can operate both + in master and slave mode. + +maintainers: + - Walker Chen + +allOf: + - $ref: dai-common.yaml# + +properties: + compatible: + enum: + - starfive,jh7110-tdm + + reg: + maxItems: 1 + + clocks: + items: + - description: TDM AHB Clock + - description: TDM APB Clock + - description: TDM Internal Clock + - description: TDM Clock + - description: Inner MCLK + - description: TDM External Clock + + clock-names: + items: + - const: tdm_ahb + - const: tdm_apb + - const: tdm_internal + - const: tdm + - const: mclk_inner + - const: tdm_ext + + resets: + items: + - description: tdm ahb reset line + - description: tdm apb reset line + - description: tdm core reset line + + dmas: + items: + - description: RX DMA Channel + - description: TX DMA Channel + + dma-names: + items: + - const: rx + - const: tx + + "#sound-dai-cells": + const: 0 + +required: + - compatible + - reg + - clocks + - clock-names + - resets + - dmas + - dma-names + - "#sound-dai-cells" + +additionalProperties: false + +examples: + - | + tdm@10090000 { + compatible = "starfive,jh7110-tdm"; + reg = <0x10090000 0x1000>; + clocks = <&syscrg 184>, + <&syscrg 185>, + <&syscrg 186>, + <&syscrg 187>, + <&syscrg 17>, + <&tdm_ext>; + clock-names = "tdm_ahb", "tdm_apb", + "tdm_internal", "tdm", + "mclk_inner", "tdm_ext"; + resets = <&syscrg 105>, + <&syscrg 107>, + <&syscrg 106>; + dmas = <&dma 20>, <&dma 21>; + dma-names = "rx","tx"; + #sound-dai-cells = <0>; + }; diff --git a/Documentation/devicetree/bindings/sound/tas2562.yaml b/Documentation/devicetree/bindings/sound/tas2562.yaml index 31a3024ea7898eba853ef98b300b97c1335a1a24..f01c0dde0cf740e6ff9d500ddedb1e27d320f919 100644 --- a/Documentation/devicetree/bindings/sound/tas2562.yaml +++ b/Documentation/devicetree/bindings/sound/tas2562.yaml @@ -2,8 +2,8 @@ # Copyright (C) 2019 Texas Instruments Incorporated %YAML 1.2 --- -$id: "http://devicetree.org/schemas/sound/tas2562.yaml#" -$schema: "http://devicetree.org/meta-schemas/core.yaml#" +$id: http://devicetree.org/schemas/sound/tas2562.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# title: Texas Instruments TAS2562 Smart PA diff --git a/Documentation/devicetree/bindings/sound/tas2770.yaml b/Documentation/devicetree/bindings/sound/tas2770.yaml index 8908bf1122e965fe8eaab5c2244ac8d5650407eb..be2536e8c4403a84a67a02212dcb118ac489fabf 100644 --- a/Documentation/devicetree/bindings/sound/tas2770.yaml +++ b/Documentation/devicetree/bindings/sound/tas2770.yaml @@ -2,8 +2,8 @@ # Copyright (C) 2019-20 Texas Instruments Incorporated %YAML 1.2 --- -$id: "http://devicetree.org/schemas/sound/tas2770.yaml#" -$schema: "http://devicetree.org/meta-schemas/core.yaml#" +$id: http://devicetree.org/schemas/sound/tas2770.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# title: Texas Instruments TAS2770 Smart PA diff --git a/Documentation/devicetree/bindings/sound/tas27xx.yaml b/Documentation/devicetree/bindings/sound/tas27xx.yaml index a876545ec87d8c6bc766ee7513fb231d52fc848d..f2d878f6f4959c3be4e8295836eeb0ca88e701cd 100644 --- a/Documentation/devicetree/bindings/sound/tas27xx.yaml +++ b/Documentation/devicetree/bindings/sound/tas27xx.yaml @@ -2,8 +2,8 @@ # Copyright (C) 2020-2022 Texas Instruments Incorporated %YAML 1.2 --- -$id: "http://devicetree.org/schemas/sound/tas27xx.yaml#" -$schema: "http://devicetree.org/meta-schemas/core.yaml#" +$id: http://devicetree.org/schemas/sound/tas27xx.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# title: Texas Instruments TAS2764/TAS2780 Smart PA diff --git a/Documentation/devicetree/bindings/sound/ti,tas2781.yaml b/Documentation/devicetree/bindings/sound/ti,tas2781.yaml new file mode 100644 index 0000000000000000000000000000000000000000..8d60e4e236d65cb6083d4bea8b4a47ba73fe8d14 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/ti,tas2781.yaml @@ -0,0 +1,74 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +# Copyright (C) 2022 - 2023 Texas Instruments Incorporated +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/ti,tas2781.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Texas Instruments TAS2781 SmartAMP + +maintainers: + - Shenghao Ding + +description: + The TAS2781 is a mono, digital input Class-D audio amplifier + optimized for efficiently driving high peak power into small + loudspeakers. An integrated on-chip DSP supports Texas Instruments + Smart Amp speaker protection algorithm. The integrated speaker + voltage and current sense provides for real time + monitoring of loudspeaker behavior. + +allOf: + - $ref: dai-common.yaml# + +properties: + compatible: + enum: + - ti,tas2781 + + reg: + description: + I2C address, in multiple tas2781s case, all the i2c address + aggreate as one Audio Device to support multiple audio slots. + maxItems: 8 + minItems: 1 + items: + minimum: 0x38 + maximum: 0x3f + + reset-gpios: + maxItems: 1 + + interrupts: + maxItems: 1 + + '#sound-dai-cells': + const: 0 + +required: + - compatible + - reg + +additionalProperties: false + +examples: + - | + #include + i2c { + /* example with quad tas2781s, such as tablet or pad device */ + #address-cells = <1>; + #size-cells = <0>; + quad_tas2781: tas2781@38 { + compatible = "ti,tas2781"; + reg = <0x38>, /* Audio slot 0 */ + <0x3a>, /* Audio slot 1 */ + <0x39>, /* Audio slot 2 */ + <0x3b>; /* Audio slot 3 */ + + #sound-dai-cells = <0>; + reset-gpios = <&gpio1 10 GPIO_ACTIVE_HIGH>; + interrupt-parent = <&gpio1>; + interrupts = <15>; + }; + }; +... diff --git a/Documentation/devicetree/bindings/sound/ti,tlv320aic32x4.yaml b/Documentation/devicetree/bindings/sound/ti,tlv320aic32x4.yaml new file mode 100644 index 0000000000000000000000000000000000000000..a7cc9aa344684877ea899bfefeeccbca9ad95b29 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/ti,tlv320aic32x4.yaml @@ -0,0 +1,101 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +# Copyright (C) 2019 Texas Instruments Incorporated +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/ti,tlv320aic32x4.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Texas Instruments TLV320AIC32x4 Stereo Audio codec + +maintainers: + - Alexander Stein + +description: | + The TLV320AIC32x4 audio codec can be accessed using I2C or SPI + +properties: + compatible: + enum: + - ti,tas2505 + - ti,tlv320aic32x4 + - ti,tlv320aic32x6 + + reg: + maxItems: 1 + + clocks: + items: + - description: Master clock + + clock-names: + items: + - const: mclk + + av-supply: + description: Analog core power supply + + dv-supply: + description: Digital core power supply + + iov-supply: + description: Digital IO power supply + + ldoin-supply: + description: LDO power supply + + reset-gpios: + maxItems: 1 + + '#sound-dai-cells': + const: 0 + + aic32x4-gpio-func: + description: | + GPIO function configuration for pins MFP1-MFP5. + Types are defined in include/sound/tlv320aic32x4.h + $ref: /schemas/types.yaml#/definitions/uint32-array + minItems: 5 + maxItems: 5 + +required: + - compatible + - reg + - clocks + - clock-names + - iov-supply + +allOf: + - $ref: dai-common.yaml# + - if: + not: + required: + - ldoin-supply + then: + required: + - av-supply + - dv-supply + +additionalProperties: false + +examples: + - | + #include + i2c { + #address-cells = <1>; + #size-cells = <0>; + audio-codec@18 { + compatible = "ti,tlv320aic32x4"; + reg = <0x18>; + iov-supply = <®_3v3>; + ldoin-supply = <®_3v3>; + clocks = <&clks 201>; + clock-names = "mclk"; + aic32x4-gpio-func= < + 0xff /* AIC32X4_MFPX_DEFAULT_VALUE */ + 0xff /* AIC32X4_MFPX_DEFAULT_VALUE */ + 0x04 /* MFP3 AIC32X4_MFP3_GPIO_ENABLED */ + 0xff /* AIC32X4_MFPX_DEFAULT_VALUE */ + 0x08 /* MFP5 AIC32X4_MFP5_GPIO_INPUT */ + >; + }; + }; diff --git a/Documentation/devicetree/bindings/sound/ti,tlv320aic3x.yaml b/Documentation/devicetree/bindings/sound/ti,tlv320aic3x.yaml index e8ca9f3369f8ec4b00c79330fa6492d959032086..206f6d61e362e30725df809bc459a758a992561b 100644 --- a/Documentation/devicetree/bindings/sound/ti,tlv320aic3x.yaml +++ b/Documentation/devicetree/bindings/sound/ti,tlv320aic3x.yaml @@ -61,6 +61,7 @@ properties: GPIO specification for the active low RESET input. gpio-reset: + $ref: /schemas/types.yaml#/definitions/uint32-matrix maxItems: 1 description: Deprecated, please use reset-gpios instead. diff --git a/Documentation/devicetree/bindings/sound/tlv320aic32x4.txt b/Documentation/devicetree/bindings/sound/tlv320aic32x4.txt deleted file mode 100644 index 0b4e21bde5bc1c27fd39835517beb92004c743d0..0000000000000000000000000000000000000000 --- a/Documentation/devicetree/bindings/sound/tlv320aic32x4.txt +++ /dev/null @@ -1,42 +0,0 @@ -Texas Instruments - tlv320aic32x4 Codec module - -The tlv320aic32x4 serial control bus communicates through I2C protocols - -Required properties: - - compatible - "string" - One of: - "ti,tlv320aic32x4" TLV320AIC3204 - "ti,tlv320aic32x6" TLV320AIC3206, TLV320AIC3256 - "ti,tas2505" TAS2505, TAS2521 - - reg: I2C slave address - - *-supply: Required supply regulators are: - "iov" - digital IO power supply - "ldoin" - LDO power supply - "dv" - Digital core power supply - "av" - Analog core power supply - If you supply ldoin, dv and av are optional. Otherwise they are required - See regulator/regulator.txt for more information about the detailed binding - format. - -Optional properties: - - reset-gpios: Reset-GPIO phandle with args as described in gpio/gpio.txt - - clocks/clock-names: Clock named 'mclk' for the master clock of the codec. - See clock/clock-bindings.txt for information about the detailed format. - - aic32x4-gpio-func - - - Types are defined in include/sound/tlv320aic32x4.h - - -Example: - -codec: tlv320aic32x4@18 { - compatible = "ti,tlv320aic32x4"; - reg = <0x18>; - clocks = <&clks 201>; - clock-names = "mclk"; - aic32x4-gpio-func= < - 0xff /* AIC32X4_MFPX_DEFAULT_VALUE */ - 0xff /* AIC32X4_MFPX_DEFAULT_VALUE */ - 0x04 /* MFP3 AIC32X4_MFP3_GPIO_ENABLED */ - 0xff /* AIC32X4_MFPX_DEFAULT_VALUE */ - 0x08 /* MFP5 AIC32X4_MFP5_GPIO_INPUT */ - >; -}; diff --git a/Documentation/devicetree/bindings/sound/wlf,wm8903.yaml b/Documentation/devicetree/bindings/sound/wlf,wm8903.yaml index 7105ed5fd6c7aebdfb31040c844cf48f51dd3e06..4cfa66f6268178df90654fb3abfc7a1916241f21 100644 --- a/Documentation/devicetree/bindings/sound/wlf,wm8903.yaml +++ b/Documentation/devicetree/bindings/sound/wlf,wm8903.yaml @@ -1,8 +1,8 @@ # SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) %YAML 1.2 --- -$id: "http://devicetree.org/schemas/sound/wlf,wm8903.yaml#" -$schema: "http://devicetree.org/meta-schemas/core.yaml#" +$id: http://devicetree.org/schemas/sound/wlf,wm8903.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# title: WM8903 audio codec diff --git a/Documentation/devicetree/bindings/soundwire/qcom,soundwire.yaml b/Documentation/devicetree/bindings/soundwire/qcom,soundwire.yaml index e4dba825ab117b8e346ff4c17d70714555f77bf2..fb44b89a754eca11e3ad372f2b84b2bdf838fca1 100644 --- a/Documentation/devicetree/bindings/soundwire/qcom,soundwire.yaml +++ b/Documentation/devicetree/bindings/soundwire/qcom,soundwire.yaml @@ -21,6 +21,7 @@ properties: - qcom,soundwire-v1.5.1 - qcom,soundwire-v1.6.0 - qcom,soundwire-v1.7.0 + - qcom,soundwire-v2.0.0 reg: maxItems: 1 @@ -80,18 +81,29 @@ properties: or applicable for the respective data port. More info in MIPI Alliance SoundWire 1.0 Specifications. minItems: 3 - maxItems: 8 + maxItems: 16 qcom,ports-sinterval-low: $ref: /schemas/types.yaml#/definitions/uint8-array description: - Sample interval low of each data port. + Sample interval (only lowest byte) of each data port. Out ports followed by In ports. Used for Sample Interval calculation. Value of 0xff indicates that this option is not implemented or applicable for the respective data port. More info in MIPI Alliance SoundWire 1.0 Specifications. minItems: 3 - maxItems: 8 + maxItems: 16 + + qcom,ports-sinterval: + $ref: /schemas/types.yaml#/definitions/uint16-array + description: + Sample interval of each data port. + Out ports followed by In ports. Used for Sample Interval calculation. + Value of 0xffff indicates that this option is not implemented + or applicable for the respective data port. + More info in MIPI Alliance SoundWire 1.0 Specifications. + minItems: 3 + maxItems: 16 qcom,ports-offset1: $ref: /schemas/types.yaml#/definitions/uint8-array @@ -102,7 +114,7 @@ properties: or applicable for the respective data port. More info in MIPI Alliance SoundWire 1.0 Specifications. minItems: 3 - maxItems: 8 + maxItems: 16 qcom,ports-offset2: $ref: /schemas/types.yaml#/definitions/uint8-array @@ -113,7 +125,7 @@ properties: or applicable for the respective data port. More info in MIPI Alliance SoundWire 1.0 Specifications. minItems: 3 - maxItems: 8 + maxItems: 16 qcom,ports-lane-control: $ref: /schemas/types.yaml#/definitions/uint8-array @@ -124,7 +136,7 @@ properties: or applicable for the respective data port. More info in MIPI Alliance SoundWire 1.0 Specifications. minItems: 3 - maxItems: 8 + maxItems: 16 qcom,ports-block-pack-mode: $ref: /schemas/types.yaml#/definitions/uint8-array @@ -137,7 +149,7 @@ properties: or applicable for the respective data port. More info in MIPI Alliance SoundWire 1.0 Specifications. minItems: 3 - maxItems: 8 + maxItems: 16 items: oneOf: - minimum: 0 @@ -154,7 +166,7 @@ properties: or applicable for the respective data port. More info in MIPI Alliance SoundWire 1.0 Specifications. minItems: 3 - maxItems: 8 + maxItems: 16 items: oneOf: - minimum: 0 @@ -171,7 +183,7 @@ properties: or applicable for the respective data port. More info in MIPI Alliance SoundWire 1.0 Specifications. minItems: 3 - maxItems: 8 + maxItems: 16 items: oneOf: - minimum: 0 @@ -187,7 +199,7 @@ properties: or applicable for the respective data port. More info in MIPI Alliance SoundWire 1.0 Specifications. minItems: 3 - maxItems: 8 + maxItems: 16 items: oneOf: - minimum: 0 @@ -219,10 +231,15 @@ required: - '#size-cells' - qcom,dout-ports - qcom,din-ports - - qcom,ports-sinterval-low - qcom,ports-offset1 - qcom,ports-offset2 +oneOf: + - required: + - qcom,ports-sinterval-low + - required: + - qcom,ports-sinterval + additionalProperties: false examples: diff --git a/Documentation/devicetree/bindings/spi/allwinner,sun4i-a10-spi.yaml b/Documentation/devicetree/bindings/spi/allwinner,sun4i-a10-spi.yaml index 2155478bfc4de1d06ec3225050f01d0756c75a09..a6f34bdd1d3c383695d0d527fcd3bcea5e3b4028 100644 --- a/Documentation/devicetree/bindings/spi/allwinner,sun4i-a10-spi.yaml +++ b/Documentation/devicetree/bindings/spi/allwinner,sun4i-a10-spi.yaml @@ -14,9 +14,6 @@ maintainers: - Maxime Ripard properties: - "#address-cells": true - "#size-cells": true - compatible: const: allwinner,sun4i-a10-spi @@ -46,12 +43,9 @@ properties: - const: rx - const: tx - num-cs: true - patternProperties: "^.*@[0-9a-f]+": type: object - additionalProperties: true properties: reg: items: @@ -71,7 +65,7 @@ required: - clocks - clock-names -additionalProperties: false +unevaluatedProperties: false examples: - | diff --git a/Documentation/devicetree/bindings/spi/allwinner,sun6i-a31-spi.yaml b/Documentation/devicetree/bindings/spi/allwinner,sun6i-a31-spi.yaml index de36c6a34a0f6d9561deafc444cef7f6b2458965..28b8ace63044b1724eaefa5646d7caffe145cda1 100644 --- a/Documentation/devicetree/bindings/spi/allwinner,sun6i-a31-spi.yaml +++ b/Documentation/devicetree/bindings/spi/allwinner,sun6i-a31-spi.yaml @@ -14,11 +14,9 @@ maintainers: - Maxime Ripard properties: - "#address-cells": true - "#size-cells": true - compatible: oneOf: + - const: allwinner,sun50i-r329-spi - const: allwinner,sun6i-a31-spi - const: allwinner,sun8i-h3-spi - items: @@ -28,6 +26,15 @@ properties: - allwinner,sun50i-h616-spi - allwinner,suniv-f1c100s-spi - const: allwinner,sun8i-h3-spi + - items: + - enum: + - allwinner,sun20i-d1-spi + - allwinner,sun50i-r329-spi-dbi + - const: allwinner,sun50i-r329-spi + - items: + - const: allwinner,sun20i-d1-spi-dbi + - const: allwinner,sun50i-r329-spi-dbi + - const: allwinner,sun50i-r329-spi reg: maxItems: 1 @@ -58,12 +65,9 @@ properties: - const: rx - const: tx - num-cs: true - patternProperties: "^.*@[0-9a-f]+": type: object - additionalProperties: true properties: reg: items: @@ -83,7 +87,7 @@ required: - clocks - clock-names -additionalProperties: false +unevaluatedProperties: false examples: - | diff --git a/Documentation/devicetree/bindings/spi/atmel,at91rm9200-spi.yaml b/Documentation/devicetree/bindings/spi/atmel,at91rm9200-spi.yaml index 6c57dd6c3a3614d3ed883bff2d1ed2fb20edf483..58367587bfbc26b83ca5fb94728c693d41656ab5 100644 --- a/Documentation/devicetree/bindings/spi/atmel,at91rm9200-spi.yaml +++ b/Documentation/devicetree/bindings/spi/atmel,at91rm9200-spi.yaml @@ -20,6 +20,10 @@ properties: - items: - const: microchip,sam9x60-spi - const: atmel,at91rm9200-spi + - items: + - const: microchip,sam9x7-spi + - const: microchip,sam9x60-spi + - const: atmel,at91rm9200-spi reg: maxItems: 1 diff --git a/Documentation/devicetree/bindings/spi/cdns,qspi-nor.yaml b/Documentation/devicetree/bindings/spi/cdns,qspi-nor.yaml index b310069762dd52513785db2f149ee23daa6fe1a2..4f15f9a0cc34a5904b5b9f69e6c9078ff3711c73 100644 --- a/Documentation/devicetree/bindings/spi/cdns,qspi-nor.yaml +++ b/Documentation/devicetree/bindings/spi/cdns,qspi-nor.yaml @@ -46,12 +46,28 @@ allOf: maxItems: 2 items: enum: [ qspi, qspi-ocp ] + - if: + properties: + compatible: + contains: + const: amd,pensando-elba-qspi + then: + properties: + cdns,fifo-depth: + enum: [ 128, 256, 1024 ] + default: 1024 + else: + properties: + cdns,fifo-depth: + enum: [ 128, 256 ] + default: 128 properties: compatible: oneOf: - items: - enum: + - amd,pensando-elba-qspi - ti,k2g-qspi - ti,am654-ospi - intel,lgm-qspi @@ -76,8 +92,6 @@ properties: description: Size of the data FIFO in words. $ref: /schemas/types.yaml#/definitions/uint32 - enum: [ 128, 256 ] - default: 128 cdns,fifo-width: $ref: /schemas/types.yaml#/definitions/uint32 diff --git a/Documentation/devicetree/bindings/spi/qcom,spi-qcom-qspi.yaml b/Documentation/devicetree/bindings/spi/qcom,spi-qcom-qspi.yaml index ee8f7ea907b0b2a8e068123c1a952fb27731850e..1696ac46a660ec45fa79a437180713e94de67de3 100644 --- a/Documentation/devicetree/bindings/spi/qcom,spi-qcom-qspi.yaml +++ b/Documentation/devicetree/bindings/spi/qcom,spi-qcom-qspi.yaml @@ -29,6 +29,9 @@ properties: reg: maxItems: 1 + iommus: + maxItems: 1 + interrupts: maxItems: 1 diff --git a/Documentation/devicetree/bindings/spi/renesas,rzv2m-csi.yaml b/Documentation/devicetree/bindings/spi/renesas,rzv2m-csi.yaml new file mode 100644 index 0000000000000000000000000000000000000000..e59183e53690b0cdfabc066edb863d026febaa1b --- /dev/null +++ b/Documentation/devicetree/bindings/spi/renesas,rzv2m-csi.yaml @@ -0,0 +1,70 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/spi/renesas,rzv2m-csi.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Renesas RZ/V2M Clocked Serial Interface (CSI) + +maintainers: + - Fabrizio Castro + - Geert Uytterhoeven + +allOf: + - $ref: spi-controller.yaml# + +properties: + compatible: + const: renesas,rzv2m-csi + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + clocks: + items: + - description: The clock used to generate the output clock (CSICLK) + - description: Internal clock to access the registers (PCLK) + + clock-names: + items: + - const: csiclk + - const: pclk + + resets: + maxItems: 1 + + power-domains: + maxItems: 1 + +required: + - compatible + - reg + - interrupts + - clocks + - clock-names + - resets + - power-domains + - '#address-cells' + - '#size-cells' + +unevaluatedProperties: false + +examples: + - | + #include + #include + csi4: spi@a4020200 { + compatible = "renesas,rzv2m-csi"; + reg = <0xa4020200 0x80>; + interrupts = ; + clocks = <&cpg CPG_MOD R9A09G011_CSI4_CLK>, + <&cpg CPG_MOD R9A09G011_CPERI_GRPH_PCLK>; + clock-names = "csiclk", "pclk"; + resets = <&cpg R9A09G011_CSI_GPH_PRESETN>; + power-domains = <&cpg>; + #address-cells = <1>; + #size-cells = <0>; + }; diff --git a/Documentation/devicetree/bindings/spi/samsung,spi.yaml b/Documentation/devicetree/bindings/spi/samsung,spi.yaml index e0a465d70b0a465a7451a6ffe89ce909fe176b68..79da99ca0e53e62991d727ee4cba82e9f88c5716 100644 --- a/Documentation/devicetree/bindings/spi/samsung,spi.yaml +++ b/Documentation/devicetree/bindings/spi/samsung,spi.yaml @@ -35,8 +35,6 @@ properties: minItems: 2 maxItems: 3 - cs-gpios: true - dmas: minItems: 2 maxItems: 2 diff --git a/Documentation/devicetree/bindings/spi/snps,dw-apb-ssi.yaml b/Documentation/devicetree/bindings/spi/snps,dw-apb-ssi.yaml index 12ca108864c6e0d3f1c0790d92129d2181a2baf3..a47cb144b09f2c2245269a18ccc47fe648f89cac 100644 --- a/Documentation/devicetree/bindings/spi/snps,dw-apb-ssi.yaml +++ b/Documentation/devicetree/bindings/spi/snps,dw-apb-ssi.yaml @@ -74,6 +74,8 @@ properties: const: intel,keembay-ssi - description: Intel Thunder Bay SPI Controller const: intel,thunderbay-ssi + - description: Intel Mount Evans Integrated Management Complex SPI Controller + const: intel,mountevans-imc-ssi - description: AMD Pensando Elba SoC SPI Controller const: amd,pensando-elba-spi - description: Baikal-T1 SPI Controller diff --git a/Documentation/devicetree/bindings/spi/socionext,uniphier-spi.yaml b/Documentation/devicetree/bindings/spi/socionext,uniphier-spi.yaml index 597fc4e6b01ca5842fd2afa798b6b0e12c958d48..c96131ebbea1d79aece503671c17e627da3522b0 100644 --- a/Documentation/devicetree/bindings/spi/socionext,uniphier-spi.yaml +++ b/Documentation/devicetree/bindings/spi/socionext,uniphier-spi.yaml @@ -17,9 +17,6 @@ allOf: - $ref: spi-controller.yaml# properties: - "#address-cells": true - "#size-cells": true - compatible: const: socionext,uniphier-scssi diff --git a/Documentation/devicetree/bindings/spi/spi-cadence.yaml b/Documentation/devicetree/bindings/spi/spi-cadence.yaml index b0f83b5c2cdd8a14fbe905955ac8e8bf27087151..b7552739b5545e0f19fdb580325344494a3122bf 100644 --- a/Documentation/devicetree/bindings/spi/spi-cadence.yaml +++ b/Documentation/devicetree/bindings/spi/spi-cadence.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Cadence SPI controller maintainers: - - Michal Simek + - Michal Simek allOf: - $ref: spi-controller.yaml# diff --git a/Documentation/devicetree/bindings/spi/spi-controller.yaml b/Documentation/devicetree/bindings/spi/spi-controller.yaml index 90945f59b7e8b584dbc16d6ad5925308fda668cd..524f6fe8c27b45f2a78f213fa62dd7f9a5a53cd6 100644 --- a/Documentation/devicetree/bindings/spi/spi-controller.yaml +++ b/Documentation/devicetree/bindings/spi/spi-controller.yaml @@ -17,7 +17,7 @@ description: | properties: $nodename: - pattern: "^spi(@.*|-[0-9a-f])*$" + pattern: "^spi(@.*|-([0-9]|[1-9][0-9]+))?$" "#address-cells": enum: [0, 1] diff --git a/Documentation/devicetree/bindings/spi/spi-xilinx.yaml b/Documentation/devicetree/bindings/spi/spi-xilinx.yaml index 6bd83836ededec5e63c98f9e333a98086dd715ab..4beb3af0416de73e82609e3ecc015570226980ba 100644 --- a/Documentation/devicetree/bindings/spi/spi-xilinx.yaml +++ b/Documentation/devicetree/bindings/spi/spi-xilinx.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Xilinx SPI controller maintainers: - - Michal Simek + - Michal Simek allOf: - $ref: spi-controller.yaml# diff --git a/Documentation/devicetree/bindings/spi/spi-zynqmp-qspi.yaml b/Documentation/devicetree/bindings/spi/spi-zynqmp-qspi.yaml index 20f77246d36581ca6590bb4e64ff852ee36a993f..e5199b109dad9f06f273449432943dc10b1f4d13 100644 --- a/Documentation/devicetree/bindings/spi/spi-zynqmp-qspi.yaml +++ b/Documentation/devicetree/bindings/spi/spi-zynqmp-qspi.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Xilinx Zynq UltraScale+ MPSoC GQSPI controller maintainers: - - Michal Simek + - Michal Simek allOf: - $ref: spi-controller.yaml# @@ -32,6 +32,12 @@ properties: clocks: maxItems: 2 + iommus: + maxItems: 1 + + power-domains: + maxItems: 1 + required: - compatible - reg diff --git a/Documentation/devicetree/bindings/spi/xlnx,zynq-qspi.yaml b/Documentation/devicetree/bindings/spi/xlnx,zynq-qspi.yaml index 83e8fb4a548df02223c90f52d19d81989a907e8c..7ea8fb42ce2c0a2d4d6a186292a680a3a9bdb1bf 100644 --- a/Documentation/devicetree/bindings/spi/xlnx,zynq-qspi.yaml +++ b/Documentation/devicetree/bindings/spi/xlnx,zynq-qspi.yaml @@ -14,7 +14,7 @@ allOf: - $ref: spi-controller.yaml# maintainers: - - Michal Simek + - Michal Simek # Everything else is described in the common file properties: diff --git a/Documentation/devicetree/bindings/spmi/mtk,spmi-mtk-pmif.yaml b/Documentation/devicetree/bindings/spmi/mtk,spmi-mtk-pmif.yaml index abcbbe13723fb9dd7aad384045b647300720dcc5..ac99883a3f295ba6e8831a1af3463e261f7c1618 100644 --- a/Documentation/devicetree/bindings/spmi/mtk,spmi-mtk-pmif.yaml +++ b/Documentation/devicetree/bindings/spmi/mtk,spmi-mtk-pmif.yaml @@ -14,13 +14,18 @@ description: |+ for multiple SoCs to control a single SPMI master. allOf: - - $ref: "spmi.yaml" + - $ref: spmi.yaml properties: compatible: - enum: - - mediatek,mt6873-spmi - - mediatek,mt8195-spmi + oneOf: + - enum: + - mediatek,mt6873-spmi + - mediatek,mt8195-spmi + - items: + - enum: + - mediatek,mt8186-spmi + - const: mediatek,mt8195-spmi reg: maxItems: 2 diff --git a/Documentation/devicetree/bindings/sram/qcom,imem.yaml b/Documentation/devicetree/bindings/sram/qcom,imem.yaml index 0548e8e0d30be616f994dbe10ab7363d3bde9970..8025a852bc9c1f0fbf11330662634faf58cc9db2 100644 --- a/Documentation/devicetree/bindings/sram/qcom,imem.yaml +++ b/Documentation/devicetree/bindings/sram/qcom,imem.yaml @@ -18,8 +18,10 @@ properties: items: - enum: - qcom,apq8064-imem + - qcom,msm8226-imem - qcom,msm8974-imem - qcom,qcs404-imem + - qcom,qdu1000-imem - qcom,sc7180-imem - qcom,sc7280-imem - qcom,sdm630-imem diff --git a/Documentation/devicetree/bindings/sram/sram.yaml b/Documentation/devicetree/bindings/sram/sram.yaml index 993430be355b47318105cceb6a274ce05f250d45..0922d1f71ba8a8ebbbc43feee246b29116929316 100644 --- a/Documentation/devicetree/bindings/sram/sram.yaml +++ b/Documentation/devicetree/bindings/sram/sram.yaml @@ -94,6 +94,7 @@ patternProperties: - samsung,exynos4210-sysram - samsung,exynos4210-sysram-ns - socionext,milbeaut-smp-sram + - stericsson,u8500-esram reg: description: diff --git a/Documentation/devicetree/bindings/thermal/armada-thermal.txt b/Documentation/devicetree/bindings/thermal/armada-thermal.txt index b0bee7e420387b92ab30823ecc472ae05ba98fbc..ab8b8fccc7afbbb833da05e0171accda85849c4d 100644 --- a/Documentation/devicetree/bindings/thermal/armada-thermal.txt +++ b/Documentation/devicetree/bindings/thermal/armada-thermal.txt @@ -8,6 +8,7 @@ Required properties: * marvell,armada380-thermal * marvell,armadaxp-thermal * marvell,armada-ap806-thermal + * marvell,armada-ap807-thermal * marvell,armada-cp110-thermal Note: these bindings are deprecated for AP806/CP110 and should instead diff --git a/Documentation/devicetree/bindings/thermal/brcm,bcm2835-thermal.txt b/Documentation/devicetree/bindings/thermal/brcm,bcm2835-thermal.txt deleted file mode 100644 index a3e9ec5dc7ac4c91c8694b42f53f5a16cea96ffd..0000000000000000000000000000000000000000 --- a/Documentation/devicetree/bindings/thermal/brcm,bcm2835-thermal.txt +++ /dev/null @@ -1,41 +0,0 @@ -Binding for Thermal Sensor driver for BCM2835 SoCs. - -Required parameters: -------------------- - -compatible: should be one of: "brcm,bcm2835-thermal", - "brcm,bcm2836-thermal" or "brcm,bcm2837-thermal" -reg: Address range of the thermal registers. -clocks: Phandle of the clock used by the thermal sensor. -#thermal-sensor-cells: should be 0 (see Documentation/devicetree/bindings/thermal/thermal-sensor.yaml) - -Example: - -thermal-zones { - cpu_thermal: cpu-thermal { - polling-delay-passive = <0>; - polling-delay = <1000>; - - thermal-sensors = <&thermal>; - - trips { - cpu-crit { - temperature = <80000>; - hysteresis = <0>; - type = "critical"; - }; - }; - - coefficients = <(-538) 407000>; - - cooling-maps { - }; - }; -}; - -thermal: thermal@7e212000 { - compatible = "brcm,bcm2835-thermal"; - reg = <0x7e212000 0x8>; - clocks = <&clocks BCM2835_CLOCK_TSENS>; - #thermal-sensor-cells = <0>; -}; diff --git a/Documentation/devicetree/bindings/thermal/brcm,bcm2835-thermal.yaml b/Documentation/devicetree/bindings/thermal/brcm,bcm2835-thermal.yaml new file mode 100644 index 0000000000000000000000000000000000000000..2b6026d9fbcf7fcc34df17bfd4a535235e579470 --- /dev/null +++ b/Documentation/devicetree/bindings/thermal/brcm,bcm2835-thermal.yaml @@ -0,0 +1,48 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/thermal/brcm,bcm2835-thermal.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Broadcom BCM2835 thermal sensor + +maintainers: + - Stefan Wahren + +allOf: + - $ref: thermal-sensor.yaml# + +properties: + compatible: + enum: + - brcm,bcm2835-thermal + - brcm,bcm2836-thermal + - brcm,bcm2837-thermal + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + + "#thermal-sensor-cells": + const: 0 + +unevaluatedProperties: false + +required: + - compatible + - reg + - clocks + - '#thermal-sensor-cells' + +examples: + - | + #include + + thermal@7e212000 { + compatible = "brcm,bcm2835-thermal"; + reg = <0x7e212000 0x8>; + clocks = <&clocks BCM2835_CLOCK_TSENS>; + #thermal-sensor-cells = <0>; + }; diff --git a/Documentation/devicetree/bindings/thermal/qcom-tsens.yaml b/Documentation/devicetree/bindings/thermal/qcom-tsens.yaml index d1ec963a6834e746e9232bf834ae0c7788a1e81e..27e9e16e6455abb5235235ca81f38dc4c1e432e6 100644 --- a/Documentation/devicetree/bindings/thermal/qcom-tsens.yaml +++ b/Documentation/devicetree/bindings/thermal/qcom-tsens.yaml @@ -29,6 +29,8 @@ properties: items: - enum: - qcom,mdm9607-tsens + - qcom,msm8226-tsens + - qcom,msm8909-tsens - qcom,msm8916-tsens - qcom,msm8939-tsens - qcom,msm8974-tsens @@ -48,6 +50,7 @@ properties: - qcom,msm8953-tsens - qcom,msm8996-tsens - qcom,msm8998-tsens + - qcom,qcm2290-tsens - qcom,sc7180-tsens - qcom,sc7280-tsens - qcom,sc8180x-tsens @@ -56,6 +59,7 @@ properties: - qcom,sdm845-tsens - qcom,sm6115-tsens - qcom,sm6350-tsens + - qcom,sm6375-tsens - qcom,sm8150-tsens - qcom,sm8250-tsens - qcom,sm8350-tsens @@ -67,6 +71,12 @@ properties: enum: - qcom,ipq8074-tsens + - description: v2 of TSENS with combined interrupt + items: + - enum: + - qcom,ipq9574-tsens + - const: qcom,ipq8074-tsens + reg: items: - description: TM registers @@ -223,12 +233,7 @@ allOf: contains: enum: - qcom,ipq8064-tsens - - qcom,mdm9607-tsens - - qcom,msm8916-tsens - qcom,msm8960-tsens - - qcom,msm8974-tsens - - qcom,msm8976-tsens - - qcom,qcs404-tsens - qcom,tsens-v0_1 - qcom,tsens-v1 then: @@ -244,22 +249,7 @@ allOf: properties: compatible: contains: - enum: - - qcom,msm8953-tsens - - qcom,msm8996-tsens - - qcom,msm8998-tsens - - qcom,sc7180-tsens - - qcom,sc7280-tsens - - qcom,sc8180x-tsens - - qcom,sc8280xp-tsens - - qcom,sdm630-tsens - - qcom,sdm845-tsens - - qcom,sm6350-tsens - - qcom,sm8150-tsens - - qcom,sm8250-tsens - - qcom,sm8350-tsens - - qcom,sm8450-tsens - - qcom,tsens-v2 + const: qcom,tsens-v2 then: properties: interrupts: diff --git a/Documentation/devicetree/bindings/timer/brcm,kona-timer.txt b/Documentation/devicetree/bindings/timer/brcm,kona-timer.txt deleted file mode 100644 index 39adf54b4388b919bc7ed465b93e4200e86000cc..0000000000000000000000000000000000000000 --- a/Documentation/devicetree/bindings/timer/brcm,kona-timer.txt +++ /dev/null @@ -1,25 +0,0 @@ -Broadcom Kona Family timer ------------------------------------------------------ -This timer is used in the following Broadcom SoCs: - BCM11130, BCM11140, BCM11351, BCM28145, BCM28155 - -Required properties: -- compatible : "brcm,kona-timer" -- DEPRECATED: compatible : "bcm,kona-timer" -- reg : Register range for the timer -- interrupts : interrupt for the timer -- clocks: phandle + clock specifier pair of the external clock -- clock-frequency: frequency that the clock operates - -Only one of clocks or clock-frequency should be specified. - -Refer to clocks/clock-bindings.txt for generic clock consumer properties. - -Example: - timer@35006000 { - compatible = "brcm,kona-timer"; - reg = <0x35006000 0x1000>; - interrupts = <0x0 7 0x4>; - clocks = <&hub_timer_clk>; - }; - diff --git a/Documentation/devicetree/bindings/timer/brcm,kona-timer.yaml b/Documentation/devicetree/bindings/timer/brcm,kona-timer.yaml new file mode 100644 index 0000000000000000000000000000000000000000..d6af8383d6fca656f08808fcb8d939ef2c6ef462 --- /dev/null +++ b/Documentation/devicetree/bindings/timer/brcm,kona-timer.yaml @@ -0,0 +1,52 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/timer/brcm,kona-timer.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Broadcom Kona family timer + +maintainers: + - Florian Fainelli + +properties: + compatible: + const: brcm,kona-timer + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + clocks: + maxItems: 1 + + clock-frequency: true + +oneOf: + - required: + - clocks + - required: + - clock-frequency + +required: + - compatible + - reg + - interrupts + +additionalProperties: false + +examples: + - | + #include + #include + #include + + timer@35006000 { + compatible = "brcm,kona-timer"; + reg = <0x35006000 0x1000>; + interrupts = ; + clocks = <&aon_ccu BCM281XX_AON_CCU_HUB_TIMER>; + }; +... diff --git a/Documentation/devicetree/bindings/timer/cdns,ttc.yaml b/Documentation/devicetree/bindings/timer/cdns,ttc.yaml index bc5e6f2262957ebcbdf20aa1fcb9109434a1a37b..dbba780c9b0213ee08bb9ed7568431bce200aeef 100644 --- a/Documentation/devicetree/bindings/timer/cdns,ttc.yaml +++ b/Documentation/devicetree/bindings/timer/cdns,ttc.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Cadence TTC - Triple Timer Counter maintainers: - - Michal Simek + - Michal Simek properties: compatible: diff --git a/Documentation/devicetree/bindings/timer/fsl,imxgpt.yaml b/Documentation/devicetree/bindings/timer/fsl,imxgpt.yaml index 716c6afcca1fa7d21517eced92caeda0eece590e..dbe1267af06a62f6324194352bfc428cd13b9350 100644 --- a/Documentation/devicetree/bindings/timer/fsl,imxgpt.yaml +++ b/Documentation/devicetree/bindings/timer/fsl,imxgpt.yaml @@ -31,9 +31,13 @@ properties: - enum: - fsl,imx6sl-gpt - fsl,imx6sx-gpt + - fsl,imx8mp-gpt - fsl,imxrt1050-gpt - fsl,imxrt1170-gpt - const: fsl,imx6dl-gpt + - items: + - const: fsl,imx6ul-gpt + - const: fsl,imx6sx-gpt reg: maxItems: 1 diff --git a/Documentation/devicetree/bindings/timer/loongson,ls1x-pwmtimer.yaml b/Documentation/devicetree/bindings/timer/loongson,ls1x-pwmtimer.yaml new file mode 100644 index 0000000000000000000000000000000000000000..ad61ae55850be884421fbfb3dbdf7a3dcbf1d5b9 --- /dev/null +++ b/Documentation/devicetree/bindings/timer/loongson,ls1x-pwmtimer.yaml @@ -0,0 +1,48 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/timer/loongson,ls1x-pwmtimer.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Loongson-1 PWM timer + +maintainers: + - Keguang Zhang + +description: + Loongson-1 PWM timer can be used for system clock source + and clock event timers. + +properties: + compatible: + const: loongson,ls1b-pwmtimer + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + + interrupts: + maxItems: 1 + +required: + - compatible + - reg + - clocks + - interrupts + +additionalProperties: false + +examples: + - | + #include + #include + clocksource: timer@1fe5c030 { + compatible = "loongson,ls1b-pwmtimer"; + reg = <0x1fe5c030 0x10>; + + clocks = <&clkc LS1X_CLKID_APB>; + interrupt-parent = <&intc0>; + interrupts = <20 IRQ_TYPE_LEVEL_HIGH>; + }; diff --git a/Documentation/devicetree/bindings/timer/ralink,rt2880-timer.yaml b/Documentation/devicetree/bindings/timer/ralink,rt2880-timer.yaml new file mode 100644 index 0000000000000000000000000000000000000000..daa7832babe32c5c37828fce589f1d97c7a2737f --- /dev/null +++ b/Documentation/devicetree/bindings/timer/ralink,rt2880-timer.yaml @@ -0,0 +1,44 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/timer/ralink,rt2880-timer.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Timer present in Ralink family SoCs + +maintainers: + - Sergio Paracuellos + +properties: + compatible: + const: ralink,rt2880-timer + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + + interrupts: + maxItems: 1 + +required: + - compatible + - reg + - clocks + - interrupts + +additionalProperties: false + +examples: + - | + timer@100 { + compatible = "ralink,rt2880-timer"; + reg = <0x100 0x20>; + + clocks = <&sysc 3>; + + interrupt-parent = <&intc>; + interrupts = <1>; + }; +... diff --git a/Documentation/devicetree/bindings/timer/sifive,clint.yaml b/Documentation/devicetree/bindings/timer/sifive,clint.yaml index 94bef9424df1bc6a7e48a79a48372d5641dab3bc..a0185e15a42fe85a24a17050fc8f71a31681cad2 100644 --- a/Documentation/devicetree/bindings/timer/sifive,clint.yaml +++ b/Documentation/devicetree/bindings/timer/sifive,clint.yaml @@ -29,14 +29,15 @@ properties: oneOf: - items: - enum: - - sifive,fu540-c000-clint - - starfive,jh7100-clint - - starfive,jh7110-clint - - canaan,k210-clint - - const: sifive,clint0 + - canaan,k210-clint # Canaan Kendryte K210 + - sifive,fu540-c000-clint # SiFive FU540 + - starfive,jh7100-clint # StarFive JH7100 + - starfive,jh7110-clint # StarFive JH7110 + - const: sifive,clint0 # SiFive CLINT v0 IP block - items: - enum: - allwinner,sun20i-d1-clint + - thead,th1520-clint - const: thead,c900-clint - items: - const: sifive,clint0 @@ -45,14 +46,9 @@ properties: description: For the QEMU virt machine only description: - Should be ",-clint" and "sifive,clint". - Supported compatible strings are - - "sifive,fu540-c000-clint" for the SiFive CLINT v0 as integrated - onto the SiFive FU540 chip, "canaan,k210-clint" for the SiFive - CLINT v0 as integrated onto the Canaan Kendryte K210 chip, and - "sifive,clint0" for the SiFive CLINT v0 IP block with no chip - integration tweaks. - Please refer to sifive-blocks-ip-versioning.txt for details + Should be ",-clint", followed by "sifive,clint" + when compatible with a SiFive CLINT. Please refer to + sifive-blocks-ip-versioning.txt for details regarding the latter. reg: maxItems: 1 diff --git a/Documentation/devicetree/bindings/timestamp/hardware-timestamps-common.yaml b/Documentation/devicetree/bindings/timestamp/hardware-timestamps-common.yaml index fd6a7b51f571b3a7dac2ca8465268e8000fe4a6a..95f42acd0c54fe58ad410dc06a14c333fc33f27a 100644 --- a/Documentation/devicetree/bindings/timestamp/hardware-timestamps-common.yaml +++ b/Documentation/devicetree/bindings/timestamp/hardware-timestamps-common.yaml @@ -17,7 +17,7 @@ description: properties: $nodename: - pattern: "^timestamp(@.*|-[0-9a-f])?$" + pattern: "^timestamp(@.*|-([0-9]|[1-9][0-9]+))?$" "#timestamp-cells": description: diff --git a/Documentation/devicetree/bindings/trivial-devices.yaml b/Documentation/devicetree/bindings/trivial-devices.yaml index 246863a9bc7e267ecb756c4afd559b64af03711b..ba2bfb547909c7d759e2a0bfcc356fa1b7454abb 100644 --- a/Documentation/devicetree/bindings/trivial-devices.yaml +++ b/Documentation/devicetree/bindings/trivial-devices.yaml @@ -139,6 +139,8 @@ properties: - infineon,ir38164 # Infineon IR38263 Voltage Regulator - infineon,ir38263 + # Infineon IRPS5401 Voltage Regulator (PMIC) + - infineon,irps5401 # Infineon SLB9635 (Soft-) I2C TPM (old protocol, max 100khz) - infineon,slb9635tt # Infineon SLB9645 I2C TPM (new protocol, max 400khz) diff --git a/Documentation/devicetree/bindings/ufs/qcom,ufs.yaml b/Documentation/devicetree/bindings/ufs/qcom,ufs.yaml index c5a06c0483899f42464dca403110e76e5f33ab1f..bdfa86a0cc98c61756b0734080f10612c8ea216b 100644 --- a/Documentation/devicetree/bindings/ufs/qcom,ufs.yaml +++ b/Documentation/devicetree/bindings/ufs/qcom,ufs.yaml @@ -26,6 +26,7 @@ properties: - qcom,msm8994-ufshc - qcom,msm8996-ufshc - qcom,msm8998-ufshc + - qcom,sa8775p-ufshc - qcom,sc8280xp-ufshc - qcom,sdm845-ufshc - qcom,sm6350-ufshc @@ -70,6 +71,10 @@ properties: power-domains: maxItems: 1 + qcom,ice: + $ref: /schemas/types.yaml#/definitions/phandle + description: phandle to the Inline Crypto Engine node + reg: minItems: 1 maxItems: 2 @@ -105,6 +110,7 @@ allOf: contains: enum: - qcom,msm8998-ufshc + - qcom,sa8775p-ufshc - qcom,sc8280xp-ufshc - qcom,sm8250-ufshc - qcom,sm8350-ufshc @@ -187,6 +193,25 @@ allOf: # TODO: define clock bindings for qcom,msm8994-ufshc + - if: + required: + - qcom,ice + then: + properties: + reg: + maxItems: 1 + clocks: + minItems: 8 + maxItems: 8 + else: + properties: + reg: + minItems: 1 + maxItems: 2 + clocks: + minItems: 8 + maxItems: 11 + unevaluatedProperties: false examples: diff --git a/Documentation/devicetree/bindings/ufs/samsung,exynos-ufs.yaml b/Documentation/devicetree/bindings/ufs/samsung,exynos-ufs.yaml index a9988798898de73471bfb0f13482be476adecc1e..88cc1e3a0c887c367c7ed83ff2a0835398a20b93 100644 --- a/Documentation/devicetree/bindings/ufs/samsung,exynos-ufs.yaml +++ b/Documentation/devicetree/bindings/ufs/samsung,exynos-ufs.yaml @@ -54,7 +54,7 @@ properties: const: ufs-phy samsung,sysreg: - $ref: '/schemas/types.yaml#/definitions/phandle-array' + $ref: /schemas/types.yaml#/definitions/phandle-array description: Should be phandle/offset pair. The phandle to the syscon node which indicates the FSYSx sysreg interface and the offset of the control register for UFS io coherency setting. diff --git a/Documentation/devicetree/bindings/usb/ci-hdrc-usb2.yaml b/Documentation/devicetree/bindings/usb/ci-hdrc-usb2.yaml index b26d26c2b023862758f2d284e846c4489df38364..782402800d4ab2aa5dde957c03b558e4444c738d 100644 --- a/Documentation/devicetree/bindings/usb/ci-hdrc-usb2.yaml +++ b/Documentation/devicetree/bindings/usb/ci-hdrc-usb2.yaml @@ -45,7 +45,9 @@ properties: - fsl,vf610-usb - const: fsl,imx27-usb - items: - - const: fsl,imx8dxl-usb + - enum: + - fsl,imx8dxl-usb + - fsl,imx8ulp-usb - const: fsl,imx7ulp-usb - const: fsl,imx6ul-usb - items: diff --git a/Documentation/devicetree/bindings/usb/dwc2.yaml b/Documentation/devicetree/bindings/usb/dwc2.yaml index d3506090f8b142d9b4fbf3212b1c06e607f41285..0a5c98ea711d489cf6b8e81b1c2697e11ee98bc4 100644 --- a/Documentation/devicetree/bindings/usb/dwc2.yaml +++ b/Documentation/devicetree/bindings/usb/dwc2.yaml @@ -53,6 +53,7 @@ properties: - amlogic,meson8b-usb - amlogic,meson-gxbb-usb - amlogic,meson-g12a-usb + - amlogic,meson-a1-usb - intel,socfpga-agilex-hsotg - const: snps,dwc2 - const: amcc,dwc-otg diff --git a/Documentation/devicetree/bindings/usb/dwc3-xilinx.yaml b/Documentation/devicetree/bindings/usb/dwc3-xilinx.yaml index 098b73134a1b9a762482ef05c2f04713bf442d69..bb373eb025a5f92b085d62b21354d94eaa002e65 100644 --- a/Documentation/devicetree/bindings/usb/dwc3-xilinx.yaml +++ b/Documentation/devicetree/bindings/usb/dwc3-xilinx.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Xilinx SuperSpeed DWC3 USB SoC controller maintainers: - - Manish Narani + - Piyush Mehta properties: compatible: diff --git a/Documentation/devicetree/bindings/usb/fsl,imx8qm-cdns3.yaml b/Documentation/devicetree/bindings/usb/fsl,imx8qm-cdns3.yaml new file mode 100644 index 0000000000000000000000000000000000000000..ceb76394af606740b64afd5c6b5799739c9cfffa --- /dev/null +++ b/Documentation/devicetree/bindings/usb/fsl,imx8qm-cdns3.yaml @@ -0,0 +1,103 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +# Copyright (c) 2020 NXP +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/usb/fsl,imx8qm-cdns3.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: NXP iMX8QM Soc USB Controller + +maintainers: + - Frank Li + +properties: + compatible: + const: fsl,imx8qm-usb3 + + reg: + items: + - description: Register set for iMX USB3 Platform Control + + "#address-cells": + enum: [ 1, 2 ] + + "#size-cells": + enum: [ 1, 2 ] + + ranges: true + + clocks: + items: + - description: Standby clock. Used during ultra low power states. + - description: USB bus clock for usb3 controller. + - description: AXI clock for AXI interface. + - description: ipg clock for register access. + - description: Core clock for usb3 controller. + + clock-names: + items: + - const: lpm + - const: bus + - const: aclk + - const: ipg + - const: core + + power-domains: + maxItems: 1 + +# Required child node: + +patternProperties: + "^usb@[0-9a-f]+$": + $ref: cdns,usb3.yaml# + +required: + - compatible + - reg + - "#address-cells" + - "#size-cells" + - ranges + - clocks + - clock-names + - power-domains + +additionalProperties: false + +examples: + - | + #include + #include + #include + + usb@5b110000 { + compatible = "fsl,imx8qm-usb3"; + reg = <0x5b110000 0x10000>; + ranges; + clocks = <&usb3_lpcg IMX_LPCG_CLK_1>, + <&usb3_lpcg IMX_LPCG_CLK_0>, + <&usb3_lpcg IMX_LPCG_CLK_7>, + <&usb3_lpcg IMX_LPCG_CLK_4>, + <&usb3_lpcg IMX_LPCG_CLK_5>; + clock-names = "lpm", "bus", "aclk", "ipg", "core"; + assigned-clocks = <&clk IMX_SC_R_USB_2 IMX_SC_PM_CLK_MST_BUS>; + assigned-clock-rates = <250000000>; + power-domains = <&pd IMX_SC_R_USB_2>; + #address-cells = <1>; + #size-cells = <1>; + + usb@5b120000 { + compatible = "cdns,usb3"; + reg = <0x5b120000 0x10000>, /* memory area for OTG/DRD registers */ + <0x5b130000 0x10000>, /* memory area for HOST registers */ + <0x5b140000 0x10000>; /* memory area for DEVICE registers */ + reg-names = "otg", "xhci", "dev"; + interrupt-parent = <&gic>; + interrupts = , + , + , + ; + interrupt-names = "host", "peripheral", "otg", "wakeup"; + phys = <&usb3_phy>; + phy-names = "cdns3,usb3-phy"; + }; + }; diff --git a/Documentation/devicetree/bindings/usb/generic-ehci.yaml b/Documentation/devicetree/bindings/usb/generic-ehci.yaml index 9445764bd8de7f49ef7197f47db74109cca262e5..b956bb5fada77d2ca6d26c31d1737e3977df3936 100644 --- a/Documentation/devicetree/bindings/usb/generic-ehci.yaml +++ b/Documentation/devicetree/bindings/usb/generic-ehci.yaml @@ -61,6 +61,7 @@ properties: - ibm,476gtr-ehci - nxp,lpc1850-ehci - qca,ar7100-ehci + - rockchip,rk3588-ehci - snps,hsdk-v1.0-ehci - socionext,uniphier-ehci - const: generic-ehci diff --git a/Documentation/devicetree/bindings/usb/generic-ohci.yaml b/Documentation/devicetree/bindings/usb/generic-ohci.yaml index d06d1e7d8876255f85f77418e0fabcb4d533ef77..be268e23ca79b6c4c2c51a9d558cc98cc47adde9 100644 --- a/Documentation/devicetree/bindings/usb/generic-ohci.yaml +++ b/Documentation/devicetree/bindings/usb/generic-ohci.yaml @@ -44,6 +44,7 @@ properties: - hpe,gxp-ohci - ibm,476gtr-ohci - ingenic,jz4740-ohci + - rockchip,rk3588-ohci - snps,hsdk-v1.0-ohci - const: generic-ohci - enum: @@ -69,7 +70,7 @@ properties: clocks: minItems: 1 - maxItems: 3 + maxItems: 4 description: | In case the Renesas R-Car Gen3 SoCs: - if a host only channel: first clock should be host. @@ -147,6 +148,20 @@ allOf: then: properties: transceiver: false + - if: + properties: + compatible: + contains: + const: rockchip,rk3588-ohci + then: + properties: + clocks: + minItems: 4 + else: + properties: + clocks: + minItems: 1 + maxItems: 3 unevaluatedProperties: false diff --git a/Documentation/devicetree/bindings/usb/mediatek,mtu3.yaml b/Documentation/devicetree/bindings/usb/mediatek,mtu3.yaml index 478214ab045e3b15e89e41b02364b72ee236d91a..a59d91243ac836a94c0f990f487fab747ff4708b 100644 --- a/Documentation/devicetree/bindings/usb/mediatek,mtu3.yaml +++ b/Documentation/devicetree/bindings/usb/mediatek,mtu3.yaml @@ -304,7 +304,7 @@ examples: # Dual role switch with type-c - | usb@11201000 { - compatible ="mediatek,mt8183-mtu3", "mediatek,mtu3"; + compatible = "mediatek,mt8183-mtu3", "mediatek,mtu3"; reg = <0x11201000 0x2e00>, <0x11203e00 0x0100>; reg-names = "mac", "ippc"; interrupts = ; diff --git a/Documentation/devicetree/bindings/usb/microchip,usb5744.yaml b/Documentation/devicetree/bindings/usb/microchip,usb5744.yaml new file mode 100644 index 0000000000000000000000000000000000000000..ff3a1707ef570f50871ca6bd630381c6d130fbb7 --- /dev/null +++ b/Documentation/devicetree/bindings/usb/microchip,usb5744.yaml @@ -0,0 +1,107 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/usb/microchip,usb5744.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Microchip USB5744 4-port Hub Controller + +description: + Microchip's USB5744 SmartHubTM IC is a 4 port, SuperSpeed (SS)/Hi-Speed (HS), + low power, low pin count configurable and fully compliant with the USB 3.1 + Gen 1 specification. The USB5744 also supports Full Speed (FS) and Low Speed + (LS) USB signaling, offering complete coverage of all defined USB operating + speeds. The new SuperSpeed hubs operate in parallel with the USB 2.0 + controller, so 5 Gbps SuperSpeed data transfers are not affected by slower + USB 2.0 traffic. + +maintainers: + - Piyush Mehta + - Michal Simek + +properties: + compatible: + enum: + - usb424,2744 + - usb424,5744 + - microchip,usb5744 + + reg: + maxItems: 1 + + reset-gpios: + maxItems: 1 + description: + GPIO controlling the GRST# pin. + + vdd-supply: + description: + VDD power supply to the hub + + peer-hub: + $ref: /schemas/types.yaml#/definitions/phandle + description: + phandle to the peer hub on the controller. + + i2c-bus: + $ref: /schemas/types.yaml#/definitions/phandle + description: + phandle of an usb hub connected via i2c bus. + +required: + - compatible + - reg + +allOf: + - if: + properties: + compatible: + contains: + const: microchip,usb5744 + then: + properties: + reset-gpios: false + vdd-supply: false + peer-hub: false + i2c-bus: false + else: + $ref: /schemas/usb/usb-device.yaml + required: + - peer-hub + +additionalProperties: false + +examples: + - | + #include + i2c: i2c { + #address-cells = <1>; + #size-cells = <0>; + hub: usb-hub@2d { + compatible = "microchip,usb5744"; + reg = <0x2d>; + }; + }; + + usb { + #address-cells = <1>; + #size-cells = <0>; + + /* 2.0 hub on port 1 */ + hub_2_0: hub@1 { + compatible = "usb424,2744"; + reg = <1>; + peer-hub = <&hub_3_0>; + i2c-bus = <&hub>; + reset-gpios = <&gpio 3 GPIO_ACTIVE_LOW>; + }; + + /* 3.0 hub on port 2 */ + hub_3_0: hub@2 { + compatible = "usb424,5744"; + reg = <2>; + peer-hub = <&hub_2_0>; + i2c-bus = <&hub>; + reset-gpios = <&gpio 3 GPIO_ACTIVE_LOW>; + }; + }; diff --git a/Documentation/devicetree/bindings/usb/nvidia,tegra-xudc.yaml b/Documentation/devicetree/bindings/usb/nvidia,tegra-xudc.yaml index e2270ce0c56b2af67f96556193f28564835ea44a..c6e661e8915ca4d3e905331299d981f4d3964314 100644 --- a/Documentation/devicetree/bindings/usb/nvidia,tegra-xudc.yaml +++ b/Documentation/devicetree/bindings/usb/nvidia,tegra-xudc.yaml @@ -91,6 +91,7 @@ properties: phys: minItems: 1 + maxItems: 2 description: Must contain an entry for each entry in phy-names. See ../phy/phy-bindings.txt for details. @@ -99,13 +100,7 @@ properties: minItems: 1 items: - const: usb2-0 - - const: usb2-1 - - const: usb2-2 - - const: usb2-3 - const: usb3-0 - - const: usb3-1 - - const: usb3-2 - - const: usb3-3 avddio-usb-supply: description: PCIe/USB3 analog logic power supply. Must supply 1.05 V. diff --git a/Documentation/devicetree/bindings/usb/onnn,nb7vpq904m.yaml b/Documentation/devicetree/bindings/usb/onnn,nb7vpq904m.yaml new file mode 100644 index 0000000000000000000000000000000000000000..c0201da002f62917aaeb2a90c3f6d4e0c1bcf5ae --- /dev/null +++ b/Documentation/devicetree/bindings/usb/onnn,nb7vpq904m.yaml @@ -0,0 +1,141 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/usb/onnn,nb7vpq904m.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: ON Semiconductor Type-C DisplayPort ALT Mode Linear Redriver + +maintainers: + - Neil Armstrong + +properties: + compatible: + enum: + - onnn,nb7vpq904m + + reg: + maxItems: 1 + + vcc-supply: + description: power supply (1.8V) + + enable-gpios: true + + retimer-switch: + description: Flag the port as possible handle of SuperSpeed signals retiming + type: boolean + + orientation-switch: + description: Flag the port as possible handler of orientation switching + type: boolean + + ports: + $ref: /schemas/graph.yaml#/properties/ports + properties: + port@0: + $ref: /schemas/graph.yaml#/properties/port + description: Super Speed (SS) Output endpoint to the Type-C connector + + port@1: + $ref: /schemas/graph.yaml#/$defs/port-base + description: Super Speed (SS) Input endpoint from the Super-Speed PHY + unevaluatedProperties: false + + properties: + endpoint: + $ref: /schemas/graph.yaml#/$defs/endpoint-base + unevaluatedProperties: false + + properties: + data-lanes: + $ref: /schemas/types.yaml#/definitions/uint32-array + description: | + An array of physical data lane indexes. Position determines how + lanes are connected to the redriver, It is assumed the same order + is kept on the other side of the redriver. + Lane number represents the following + - 0 is RX2 lane + - 1 is TX2 lane + - 2 is TX1 lane + - 3 is RX1 lane + The position determines the physical port of the redriver, in the + order A, B, C & D. + oneOf: + - items: + - const: 0 + - const: 1 + - const: 2 + - const: 3 + description: | + This is the lanes default layout + - Port A to RX2 lane + - Port B to TX2 lane + - Port C to TX1 lane + - Port D to RX1 lane + - items: + - const: 3 + - const: 2 + - const: 1 + - const: 0 + description: | + This is the USBRX2/USBTX2 and USBRX1/USBTX1 swapped lanes layout + - Port A to RX1 lane + - Port B to TX1 lane + - Port C to TX2 lane + - Port D to RX2 lane + + port@2: + $ref: /schemas/graph.yaml#/properties/port + description: + Sideband Use (SBU) AUX lines endpoint to the Type-C connector for the purpose of + handling altmode muxing and orientation switching. + +required: + - compatible + - reg + +additionalProperties: false + +examples: + - | + i2c { + #address-cells = <1>; + #size-cells = <0>; + + typec-mux@32 { + compatible = "onnn,nb7vpq904m"; + reg = <0x32>; + + vcc-supply = <&vreg_l15b_1p8>; + + retimer-switch; + orientation-switch; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + usb_con_ss: endpoint { + remote-endpoint = <&typec_con_ss>; + }; + }; + port@1 { + reg = <1>; + phy_con_ss: endpoint { + remote-endpoint = <&usb_phy_ss>; + data-lanes = <3 2 1 0>; + }; + }; + port@2 { + reg = <2>; + usb_con_sbu: endpoint { + remote-endpoint = <&typec_dp_aux>; + }; + }; + }; + }; + }; +... diff --git a/Documentation/devicetree/bindings/usb/qcom,dwc3.yaml b/Documentation/devicetree/bindings/usb/qcom,dwc3.yaml index d84281926f10bdf8e092c826a4d4b0c7af4364de..ae24dac78d9a35f6d4fc79a4bb0a32473ed92e53 100644 --- a/Documentation/devicetree/bindings/usb/qcom,dwc3.yaml +++ b/Documentation/devicetree/bindings/usb/qcom,dwc3.yaml @@ -17,12 +17,14 @@ properties: - qcom,ipq6018-dwc3 - qcom,ipq8064-dwc3 - qcom,ipq8074-dwc3 + - qcom,ipq9574-dwc3 - qcom,msm8953-dwc3 - qcom,msm8994-dwc3 - qcom,msm8996-dwc3 - qcom,msm8998-dwc3 - qcom,qcm2290-dwc3 - qcom,qcs404-dwc3 + - qcom,sa8775p-dwc3 - qcom,sc7180-dwc3 - qcom,sc7280-dwc3 - qcom,sc8280xp-dwc3 @@ -133,7 +135,6 @@ required: - "#address-cells" - "#size-cells" - ranges - - power-domains - clocks - clock-names - interrupts @@ -177,9 +178,11 @@ allOf: compatible: contains: enum: + - qcom,ipq9574-dwc3 - qcom,msm8953-dwc3 - qcom,msm8996-dwc3 - qcom,msm8998-dwc3 + - qcom,sa8775p-dwc3 - qcom,sc7180-dwc3 - qcom,sc7280-dwc3 - qcom,sdm670-dwc3 @@ -455,6 +458,25 @@ allOf: - const: dm_hs_phy_irq - const: ss_phy_irq + - if: + properties: + compatible: + contains: + enum: + - qcom,sa8775p-dwc3 + then: + properties: + interrupts: + minItems: 3 + maxItems: 4 + interrupt-names: + minItems: 3 + items: + - const: pwr_event + - const: dp_hs_phy_irq + - const: dm_hs_phy_irq + - const: ss_phy_irq + additionalProperties: false examples: diff --git a/Documentation/devicetree/bindings/usb/qcom,pmic-typec.yaml b/Documentation/devicetree/bindings/usb/qcom,pmic-typec.yaml new file mode 100644 index 0000000000000000000000000000000000000000..55df3129a0bc73afe855373655b9daf8d39bf37f --- /dev/null +++ b/Documentation/devicetree/bindings/usb/qcom,pmic-typec.yaml @@ -0,0 +1,190 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/usb/qcom,pmic-typec.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm PMIC based USB Type-C block + +maintainers: + - Bryan O'Donoghue + +description: + Qualcomm PMIC Type-C block + +properties: + compatible: + enum: + - qcom,pm8150b-typec + + connector: + type: object + $ref: /schemas/connector/usb-connector.yaml# + unevaluatedProperties: false + + reg: + description: Type-C port and pdphy SPMI register base offsets + maxItems: 2 + + interrupts: + items: + - description: Type-C CC attach notification, VBUS error, tCCDebounce done + - description: Type-C VCONN powered + - description: Type-C CC state change + - description: Type-C VCONN over-current + - description: Type-C VBUS state change + - description: Type-C Attach/detach notification + - description: Type-C Legacy cable detect + - description: Type-C Try.Src Try.Snk state change + - description: Power Domain Signal TX - HardReset or CableReset signal TX + - description: Power Domain Signal RX - HardReset or CableReset signal RX + - description: Power Domain TX complete + - description: Power Domain RX complete + - description: Power Domain TX fail + - description: Power Domain TX message discard + - description: Power Domain RX message discard + - description: Power Domain Fast Role Swap event + + interrupt-names: + items: + - const: or-rid-detect-change + - const: vpd-detect + - const: cc-state-change + - const: vconn-oc + - const: vbus-change + - const: attach-detach + - const: legacy-cable-detect + - const: try-snk-src-detect + - const: sig-tx + - const: sig-rx + - const: msg-tx + - const: msg-rx + - const: msg-tx-failed + - const: msg-tx-discarded + - const: msg-rx-discarded + - const: fr-swap + + vdd-vbus-supply: + description: VBUS power supply. + + vdd-pdphy-supply: + description: VDD regulator supply to the PDPHY. + + port: + $ref: /schemas/graph.yaml#/properties/port + description: + Contains a port which produces data-role switching messages. + +required: + - compatible + - reg + - interrupts + - interrupt-names + - vdd-vbus-supply + - vdd-pdphy-supply + +additionalProperties: false + +examples: + - | + #include + #include + + pmic { + #address-cells = <1>; + #size-cells = <0>; + + pm8150b_typec: typec@1500 { + compatible = "qcom,pm8150b-typec"; + reg = <0x1500>, + <0x1700>; + + interrupts = <0x2 0x15 0x00 IRQ_TYPE_EDGE_RISING>, + <0x2 0x15 0x01 IRQ_TYPE_EDGE_BOTH>, + <0x2 0x15 0x02 IRQ_TYPE_EDGE_RISING>, + <0x2 0x15 0x03 IRQ_TYPE_EDGE_BOTH>, + <0x2 0x15 0x04 IRQ_TYPE_EDGE_RISING>, + <0x2 0x15 0x05 IRQ_TYPE_EDGE_RISING>, + <0x2 0x15 0x06 IRQ_TYPE_EDGE_BOTH>, + <0x2 0x15 0x07 IRQ_TYPE_EDGE_RISING>, + <0x2 0x17 0x00 IRQ_TYPE_EDGE_RISING>, + <0x2 0x17 0x01 IRQ_TYPE_EDGE_RISING>, + <0x2 0x17 0x02 IRQ_TYPE_EDGE_RISING>, + <0x2 0x17 0x03 IRQ_TYPE_EDGE_RISING>, + <0x2 0x17 0x04 IRQ_TYPE_EDGE_RISING>, + <0x2 0x17 0x05 IRQ_TYPE_EDGE_RISING>, + <0x2 0x17 0x06 IRQ_TYPE_EDGE_RISING>, + <0x2 0x17 0x07 IRQ_TYPE_EDGE_RISING>; + + interrupt-names = "or-rid-detect-change", + "vpd-detect", + "cc-state-change", + "vconn-oc", + "vbus-change", + "attach-detach", + "legacy-cable-detect", + "try-snk-src-detect", + "sig-tx", + "sig-rx", + "msg-tx", + "msg-rx", + "msg-tx-failed", + "msg-tx-discarded", + "msg-rx-discarded", + "fr-swap"; + + vdd-vbus-supply = <&pm8150b_vbus>; + vdd-pdphy-supply = <&vreg_l2a_3p1>; + + connector { + compatible = "usb-c-connector"; + + power-role = "source"; + data-role = "dual"; + self-powered; + + source-pdos = ; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + pmic_typec_mux_out: endpoint { + remote-endpoint = <&usb_phy_typec_mux_in>; + }; + }; + + port@1 { + reg = <1>; + pmic_typec_role_switch_out: endpoint { + remote-endpoint = <&usb_role_switch_in>; + }; + }; + }; + }; + }; + }; + + usb { + dr_mode = "otg"; + usb-role-switch; + port { + usb_role_switch_in: endpoint { + remote-endpoint = <&pmic_typec_role_switch_out>; + }; + }; + }; + + usb-phy { + orientation-switch; + port { + usb_phy_typec_mux_in: endpoint { + remote-endpoint = <&pmic_typec_mux_out>; + }; + }; + }; + +... diff --git a/Documentation/devicetree/bindings/usb/snps,dwc3.yaml b/Documentation/devicetree/bindings/usb/snps,dwc3.yaml index 4f7625955cccccff6964c98cfed9a1dc1f225326..a696f23730d3ecd965cfcd487a320bec5b964684 100644 --- a/Documentation/devicetree/bindings/usb/snps,dwc3.yaml +++ b/Documentation/devicetree/bindings/usb/snps,dwc3.yaml @@ -44,15 +44,15 @@ properties: It's either a single common DWC3 interrupt (dwc_usb3) or individual interrupts for the host, gadget and DRD modes. minItems: 1 - maxItems: 3 + maxItems: 4 interrupt-names: minItems: 1 - maxItems: 3 + maxItems: 4 oneOf: - const: dwc_usb3 - items: - enum: [host, peripheral, otg] + enum: [host, peripheral, otg, wakeup] clocks: description: diff --git a/Documentation/devicetree/bindings/usb/starfive,jh7110-usb.yaml b/Documentation/devicetree/bindings/usb/starfive,jh7110-usb.yaml new file mode 100644 index 0000000000000000000000000000000000000000..24aa9c10d6ab720a27ede33cb28609da8f8ec46b --- /dev/null +++ b/Documentation/devicetree/bindings/usb/starfive,jh7110-usb.yaml @@ -0,0 +1,115 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/usb/starfive,jh7110-usb.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: StarFive JH7110 wrapper module for the Cadence USBSS-DRD controller + +maintainers: + - Minda Chen + +properties: + compatible: + const: starfive,jh7110-usb + + ranges: true + + starfive,stg-syscon: + $ref: /schemas/types.yaml#/definitions/phandle-array + items: + - items: + - description: phandle to System Register Controller stg_syscon node. + - description: dr mode register offset of STG_SYSCONSAIF__SYSCFG register for USB. + description: + The phandle to System Register Controller syscon node and the offset + of STG_SYSCONSAIF__SYSCFG register for USB. + + dr_mode: + enum: [host, otg, peripheral] + + "#address-cells": + enum: [1, 2] + + "#size-cells": + enum: [1, 2] + + clocks: + items: + - description: link power management clock + - description: standby clock + - description: APB clock + - description: AXI clock + - description: UTMI APB clock + + clock-names: + items: + - const: lpm + - const: stb + - const: apb + - const: axi + - const: utmi_apb + + resets: + items: + - description: Power up reset + - description: APB clock reset + - description: AXI clock reset + - description: UTMI APB clock reset + + reset-names: + items: + - const: pwrup + - const: apb + - const: axi + - const: utmi_apb + +patternProperties: + "^usb@[0-9a-f]+$": + $ref: cdns,usb3.yaml# + description: Required child node + +required: + - compatible + - ranges + - starfive,stg-syscon + - '#address-cells' + - '#size-cells' + - dr_mode + - clocks + - resets + +additionalProperties: false + +examples: + - | + usb@10100000 { + compatible = "starfive,jh7110-usb"; + ranges = <0x0 0x10100000 0x100000>; + #address-cells = <1>; + #size-cells = <1>; + starfive,stg-syscon = <&stg_syscon 0x4>; + clocks = <&syscrg 4>, + <&stgcrg 5>, + <&stgcrg 1>, + <&stgcrg 3>, + <&stgcrg 2>; + clock-names = "lpm", "stb", "apb", "axi", "utmi_apb"; + resets = <&stgcrg 10>, + <&stgcrg 8>, + <&stgcrg 7>, + <&stgcrg 9>; + reset-names = "pwrup", "apb", "axi", "utmi_apb"; + dr_mode = "host"; + + usb@0 { + compatible = "cdns,usb3"; + reg = <0x0 0x10000>, + <0x10000 0x10000>, + <0x20000 0x10000>; + reg-names = "otg", "xhci", "dev"; + interrupts = <100>, <108>, <110>; + interrupt-names = "host", "peripheral", "otg"; + maximum-speed = "super-speed"; + }; + }; diff --git a/Documentation/devicetree/bindings/usb/ti,am62-usb.yaml b/Documentation/devicetree/bindings/usb/ti,am62-usb.yaml index d25fc708e32cf8415ffc131e52dfe97906666e36..fec5651f560296828052866e1e8efd621fd33522 100644 --- a/Documentation/devicetree/bindings/usb/ti,am62-usb.yaml +++ b/Documentation/devicetree/bindings/usb/ti,am62-usb.yaml @@ -92,7 +92,7 @@ examples: usb@31100000 { compatible = "snps,dwc3"; - reg =<0x00 0x31100000 0x00 0x50000>; + reg = <0x00 0x31100000 0x00 0x50000>; interrupts = , /* irq.0 */ ; /* irq.0 */ interrupt-names = "host", "peripheral"; diff --git a/Documentation/devicetree/bindings/usb/usb251xb.yaml b/Documentation/devicetree/bindings/usb/usb251xb.yaml index 4d153081681784f2a790be00af89d0f2f444eb23..ac5b99710332a7c263d7583b4749b03405ed52a8 100644 --- a/Documentation/devicetree/bindings/usb/usb251xb.yaml +++ b/Documentation/devicetree/bindings/usb/usb251xb.yaml @@ -231,7 +231,7 @@ properties: power-on sequence to a port until the port has adequate power. swap-dx-lanes: - $ref: /schemas/types.yaml#/definitions/uint8-array + $ref: /schemas/types.yaml#/definitions/uint32-array description: | Specifies the ports which will swap the differential-pair (D+/D-), default is not-swapped. diff --git a/Documentation/devicetree/bindings/usb/xlnx,usb2.yaml b/Documentation/devicetree/bindings/usb/xlnx,usb2.yaml index 04c123c7252a168d400ccceacee9eb05e8a15800..868dffe314bcba9123a4e99b9966de738b0ea8f3 100644 --- a/Documentation/devicetree/bindings/usb/xlnx,usb2.yaml +++ b/Documentation/devicetree/bindings/usb/xlnx,usb2.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Xilinx udc controller maintainers: - - Manish Narani + - Piyush Mehta properties: compatible: diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml index 82d39ab0231b062008b417a7b15607c44c0857f6..af60bf1a66648c32ad0ef20565f1014e7f84664d 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.yaml +++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml @@ -388,6 +388,8 @@ patternProperties: description: EDIMAX Technology Co., Ltd "^edt,.*": description: Emerging Display Technologies + "^ees,.*": + description: Emtop Embedded Solutions "^eeti,.*": description: eGalax_eMPIA Technology Inc "^einfochips,.*": @@ -617,6 +619,8 @@ patternProperties: description: Integrated Micro-Electronics Inc. "^incircuit,.*": description: In-Circuit GmbH + "^indiedroid,.*": + description: Indiedroid "^inet-tek,.*": description: Shenzhen iNet Mobile Internet Technology Co., Ltd "^infineon,.*": @@ -781,6 +785,8 @@ patternProperties: description: Nanjing Loongmasses Ltd. "^lsi,.*": description: LSI Corp. (LSI Logic) + "^lunzn,.*": + description: Shenzhen Lunzn Technology Co., Ltd. "^lwn,.*": description: Liebherr-Werk Nenzing GmbH "^lxa,.*": @@ -1189,6 +1195,8 @@ patternProperties: description: SHIFT GmbH "^shimafuji,.*": description: Shimafuji Electric, Inc. + "^shineworld,.*": + description: ShineWorld Innovations "^shiratech,.*": description: Shiratech Solutions "^si-en,.*": @@ -1267,6 +1275,8 @@ patternProperties: description: SpinalHDL "^sprd,.*": description: Spreadtrum Communications Inc. + "^square,.*": + description: Square "^ssi,.*": description: SSI Computer Corp "^sst,.*": @@ -1339,6 +1349,8 @@ patternProperties: description: Technologic Systems "^techstar,.*": description: Shenzhen Techstar Electronics Co., Ltd. + "^teejet,.*": + description: TeeJet "^teltonika,.*": description: Teltonika Networks "^tempo,.*": diff --git a/Documentation/devicetree/bindings/watchdog/brcm,kona-wdt.txt b/Documentation/devicetree/bindings/watchdog/brcm,kona-wdt.txt deleted file mode 100644 index 2b86a00e351d3725c021fd9754deaa393cf99ba6..0000000000000000000000000000000000000000 --- a/Documentation/devicetree/bindings/watchdog/brcm,kona-wdt.txt +++ /dev/null @@ -1,15 +0,0 @@ -Broadcom Kona Family Watchdog Timer ------------------------------------ - -This watchdog timer is used in the following Broadcom SoCs: - BCM11130, BCM11140, BCM11351, BCM28145, BCM28155 - -Required properties: - - compatible = "brcm,bcm11351-wdt", "brcm,kona-wdt"; - - reg: memory address & range - -Example: - watchdog@35002f40 { - compatible = "brcm,bcm11351-wdt", "brcm,kona-wdt"; - reg = <0x35002f40 0x6c>; - }; diff --git a/Documentation/devicetree/bindings/watchdog/brcm,kona-wdt.yaml b/Documentation/devicetree/bindings/watchdog/brcm,kona-wdt.yaml new file mode 100644 index 0000000000000000000000000000000000000000..3d4403b41cbea0d63e03ac0455baafb46284e791 --- /dev/null +++ b/Documentation/devicetree/bindings/watchdog/brcm,kona-wdt.yaml @@ -0,0 +1,41 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/watchdog/brcm,kona-wdt.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Broadcom Kona Family Watchdog Timer + +description: | + This watchdog timer is used in the following Broadcom SoCs: + BCM11130, BCM11140, BCM11351, BCM28145, BCM28155 + +maintainers: + - Florian Fainelli + - Ray Jui + - Scott Branden + +allOf: + - $ref: watchdog.yaml# + +properties: + compatible: + items: + - const: brcm,bcm11351-wdt + - const: brcm,kona-wdt + + reg: + maxItems: 1 + +required: + - compatible + - reg + +unevaluatedProperties: false + +examples: + - | + watchdog@35002f40 { + compatible = "brcm,bcm11351-wdt", "brcm,kona-wdt"; + reg = <0x35002f40 0x6c>; + }; diff --git a/Documentation/devicetree/bindings/watchdog/cadence-wdt.txt b/Documentation/devicetree/bindings/watchdog/cadence-wdt.txt deleted file mode 100644 index 750a87657448d67e80d6f04d03333edffdff1f03..0000000000000000000000000000000000000000 --- a/Documentation/devicetree/bindings/watchdog/cadence-wdt.txt +++ /dev/null @@ -1,23 +0,0 @@ -Zynq Watchdog Device Tree Bindings -------------------------------------------- - -Required properties: -- compatible : Should be "cdns,wdt-r1p2". -- clocks : This is pclk (APB clock). -- interrupts : This is wd_irq - watchdog timeout interrupt. - -Optional properties -- reset-on-timeout : If this property exists, then a reset is done - when watchdog times out. -- timeout-sec : Watchdog timeout value (in seconds). - -Example: - watchdog@f8005000 { - compatible = "cdns,wdt-r1p2"; - clocks = <&clkc 45>; - interrupt-parent = <&intc>; - interrupts = <0 9 1>; - reg = <0xf8005000 0x1000>; - reset-on-timeout; - timeout-sec = <10>; - }; diff --git a/Documentation/devicetree/bindings/watchdog/cdns,wdt-r1p2.yaml b/Documentation/devicetree/bindings/watchdog/cdns,wdt-r1p2.yaml new file mode 100644 index 0000000000000000000000000000000000000000..3c17c5883bcee072b6a40f19ba04a1d0078d6479 --- /dev/null +++ b/Documentation/devicetree/bindings/watchdog/cdns,wdt-r1p2.yaml @@ -0,0 +1,62 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/watchdog/cdns,wdt-r1p2.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Cadence watchdog timer controller + +maintainers: + - Neeli Srinivas + +description: + The cadence watchdog timer is used to detect and recover from + system malfunctions. This watchdog contains 24 bit counter and + a programmable reset period. The timeout period varies from 1 ms + to 30 seconds while using a 100Mhz clock. + +allOf: + - $ref: watchdog.yaml# + +properties: + compatible: + enum: + - cdns,wdt-r1p2 + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + + interrupts: + maxItems: 1 + + reset-on-timeout: + type: boolean + description: | + If this property exists, then a reset is done when watchdog + times out. + +required: + - compatible + - reg + - clocks + - interrupts + +unevaluatedProperties: false + +examples: + - | + #include + + watchdog@f8005000 { + compatible = "cdns,wdt-r1p2"; + reg = <0xf8005000 0x1000>; + clocks = <&clkc 45>; + interrupt-parent = <&intc>; + interrupts = ; + reset-on-timeout; + timeout-sec = <10>; + }; +... diff --git a/Documentation/devicetree/bindings/watchdog/loongson,ls1x-wdt.yaml b/Documentation/devicetree/bindings/watchdog/loongson,ls1x-wdt.yaml new file mode 100644 index 0000000000000000000000000000000000000000..81690d4b62a643b5c250296a5dae6d574082e8ee --- /dev/null +++ b/Documentation/devicetree/bindings/watchdog/loongson,ls1x-wdt.yaml @@ -0,0 +1,42 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/watchdog/loongson,ls1x-wdt.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Loongson-1 Watchdog Timer + +maintainers: + - Keguang Zhang + +allOf: + - $ref: watchdog.yaml# + +properties: + compatible: + enum: + - loongson,ls1b-wdt + - loongson,ls1c-wdt + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + +required: + - compatible + - reg + - clocks + +unevaluatedProperties: false + +examples: + - | + #include + watchdog: watchdog@1fe5c060 { + compatible = "loongson,ls1b-wdt"; + reg = <0x1fe5c060 0xc>; + + clocks = <&clkc LS1X_CLKID_APB>; + }; diff --git a/Documentation/devicetree/bindings/watchdog/watchdog.yaml b/Documentation/devicetree/bindings/watchdog/watchdog.yaml index 519b48889eb148a131674c85ff79c2cc10fe940b..f0a584af1223ebdf4dd8c31b98270f2bd96972c9 100644 --- a/Documentation/devicetree/bindings/watchdog/watchdog.yaml +++ b/Documentation/devicetree/bindings/watchdog/watchdog.yaml @@ -17,11 +17,11 @@ description: | select: properties: $nodename: - pattern: "^watchdog(@.*|-[0-9a-f])?$" + pattern: "^watchdog(@.*|-([0-9]|[1-9][0-9]+))?$" properties: $nodename: - pattern: "^(timer|watchdog)(@.*|-[0-9a-f])?$" + pattern: "^(timer|watchdog)(@.*|-([0-9]|[1-9][0-9]+))?$" timeout-sec: description: diff --git a/Documentation/devicetree/bindings/watchdog/xlnx,versal-wwdt.yaml b/Documentation/devicetree/bindings/watchdog/xlnx,versal-wwdt.yaml new file mode 100644 index 0000000000000000000000000000000000000000..14b0695997402b3995f7a2ced19fcece24671c3e --- /dev/null +++ b/Documentation/devicetree/bindings/watchdog/xlnx,versal-wwdt.yaml @@ -0,0 +1,50 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/watchdog/xlnx,versal-wwdt.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Xilinx Versal window watchdog timer controller + +maintainers: + - Neeli Srinivas + +description: + Versal watchdog intellectual property uses window watchdog mode. + Window watchdog timer(WWDT) contains closed(first) and open(second) + window with 32 bit width. Write to the watchdog timer within + predefined window periods of time. This means a period that is not + too soon and a period that is not too late. The WWDT has to be + restarted within the open window time. If software tries to restart + WWDT outside of the open window time period, it generates a reset. + +allOf: + - $ref: watchdog.yaml# + +properties: + compatible: + enum: + - xlnx,versal-wwdt + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + +required: + - compatible + - reg + - clocks + +unevaluatedProperties: false + +examples: + - | + watchdog@fd4d0000 { + compatible = "xlnx,versal-wwdt"; + reg = <0xfd4d0000 0x10000>; + clocks = <&clock25>; + timeout-sec = <30>; + }; +... diff --git a/Documentation/devicetree/bindings/watchdog/xlnx,xps-timebase-wdt.yaml b/Documentation/devicetree/bindings/watchdog/xlnx,xps-timebase-wdt.yaml index 8444c56dd6023d47876c38e8853e701e93a78f7d..dc1ff39d05a0cb5933d02a21c758efbf0cba70d1 100644 --- a/Documentation/devicetree/bindings/watchdog/xlnx,xps-timebase-wdt.yaml +++ b/Documentation/devicetree/bindings/watchdog/xlnx,xps-timebase-wdt.yaml @@ -7,8 +7,8 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Xilinx AXI/PLB softcore and window Watchdog Timer maintainers: - - Shubhrajyoti Datta - - Srinivas Neeli + - Shubhrajyoti Datta + - Srinivas Neeli description: The Timebase watchdog timer(WDT) is a free-running 32 bit counter. diff --git a/Documentation/doc-guide/sphinx.rst b/Documentation/doc-guide/sphinx.rst index 23edb427e76f4d8a0cd136cf55a8843145343b21..cd8ad79044910cbb2d647d19e06c5f43e0997d18 100644 --- a/Documentation/doc-guide/sphinx.rst +++ b/Documentation/doc-guide/sphinx.rst @@ -313,9 +313,18 @@ the documentation build system will automatically turn a reference to function name exists. If you see ``c:func:`` use in a kernel document, please feel free to remove it. +Tables +------ + +ReStructuredText provides several options for table syntax. Kernel style for +tables is to prefer *simple table* syntax or *grid table* syntax. See the +`reStructuredText user reference for table syntax`_ for more details. + +.. _reStructuredText user reference for table syntax: + https://docutils.sourceforge.io/docs/user/rst/quickref.html#tables list tables ------------ +~~~~~~~~~~~ The list-table formats can be useful for tables that are not easily laid out in the usual Sphinx ASCII-art formats. These formats are nearly diff --git a/Documentation/driver-api/basics.rst b/Documentation/driver-api/basics.rst index 4b4d8e28d3be47b47105e2cbe27b0134bcc84679..7671b531ba1a851f280972452bde025260224e0b 100644 --- a/Documentation/driver-api/basics.rst +++ b/Documentation/driver-api/basics.rst @@ -84,7 +84,13 @@ Reference counting Atomics ------- -.. kernel-doc:: arch/x86/include/asm/atomic.h +.. kernel-doc:: include/linux/atomic/atomic-instrumented.h + :internal: + +.. kernel-doc:: include/linux/atomic/atomic-arch-fallback.h + :internal: + +.. kernel-doc:: include/linux/atomic/atomic-long.h :internal: Kernel objects manipulation diff --git a/Documentation/driver-api/driver-model/devres.rst b/Documentation/driver-api/driver-model/devres.rst index 4249eb4239e07c80bb30574495ad5bcbd0534569..8be086b3f8297a0549ba128c3ede0ff76cc0da60 100644 --- a/Documentation/driver-api/driver-model/devres.rst +++ b/Documentation/driver-api/driver-model/devres.rst @@ -364,6 +364,7 @@ MEM devm_kmalloc_array() devm_kmemdup() devm_krealloc() + devm_krealloc_array() devm_kstrdup() devm_kstrdup_const() devm_kvasprintf() diff --git a/Documentation/driver-api/edac.rst b/Documentation/driver-api/edac.rst index b8c742aa0a71c6a27aa66c37163065f9ac8887fb..f4f044b95c4f76f85dcf962b778309d7423605cb 100644 --- a/Documentation/driver-api/edac.rst +++ b/Documentation/driver-api/edac.rst @@ -106,6 +106,16 @@ will occupy those chip-select rows. This term is avoided because it is unclear when needing to distinguish between chip-select rows and socket sets. +* High Bandwidth Memory (HBM) + +HBM is a new memory type with low power consumption and ultra-wide +communication lanes. It uses vertically stacked memory chips (DRAM dies) +interconnected by microscopic wires called "through-silicon vias," or +TSVs. + +Several stacks of HBM chips connect to the CPU or GPU through an ultra-fast +interconnect called the "interposer". Therefore, HBM's characteristics +are nearly indistinguishable from on-chip integrated RAM. Memory Controllers ------------------ @@ -176,3 +186,113 @@ nodes:: the L1 and L2 directories would be "edac_device_block's" .. kernel-doc:: drivers/edac/edac_device.h + + +Heterogeneous system support +---------------------------- + +An AMD heterogeneous system is built by connecting the data fabrics of +both CPUs and GPUs via custom xGMI links. Thus, the data fabric on the +GPU nodes can be accessed the same way as the data fabric on CPU nodes. + +The MI200 accelerators are data center GPUs. They have 2 data fabrics, +and each GPU data fabric contains four Unified Memory Controllers (UMC). +Each UMC contains eight channels. Each UMC channel controls one 128-bit +HBM2e (2GB) channel (equivalent to 8 X 2GB ranks). This creates a total +of 4096-bits of DRAM data bus. + +While the UMC is interfacing a 16GB (8high X 2GB DRAM) HBM stack, each UMC +channel is interfacing 2GB of DRAM (represented as rank). + +Memory controllers on AMD GPU nodes can be represented in EDAC thusly: + + GPU DF / GPU Node -> EDAC MC + GPU UMC -> EDAC CSROW + GPU UMC channel -> EDAC CHANNEL + +For example: a heterogeneous system with 1 AMD CPU is connected to +4 MI200 (Aldebaran) GPUs using xGMI. + +Some more heterogeneous hardware details: + +- The CPU UMC (Unified Memory Controller) is mostly the same as the GPU UMC. + They have chip selects (csrows) and channels. However, the layouts are different + for performance, physical layout, or other reasons. +- CPU UMCs use 1 channel, In this case UMC = EDAC channel. This follows the + marketing speak. CPU has X memory channels, etc. +- CPU UMCs use up to 4 chip selects, So UMC chip select = EDAC CSROW. +- GPU UMCs use 1 chip select, So UMC = EDAC CSROW. +- GPU UMCs use 8 channels, So UMC channel = EDAC channel. + +The EDAC subsystem provides a mechanism to handle AMD heterogeneous +systems by calling system specific ops for both CPUs and GPUs. + +AMD GPU nodes are enumerated in sequential order based on the PCI +hierarchy, and the first GPU node is assumed to have a Node ID value +following those of the CPU nodes after latter are fully populated:: + + $ ls /sys/devices/system/edac/mc/ + mc0 - CPU MC node 0 + mc1 | + mc2 |- GPU card[0] => node 0(mc1), node 1(mc2) + mc3 | + mc4 |- GPU card[1] => node 0(mc3), node 1(mc4) + mc5 | + mc6 |- GPU card[2] => node 0(mc5), node 1(mc6) + mc7 | + mc8 |- GPU card[3] => node 0(mc7), node 1(mc8) + +For example, a heterogeneous system with one AMD CPU is connected to +four MI200 (Aldebaran) GPUs using xGMI. This topology can be represented +via the following sysfs entries:: + + /sys/devices/system/edac/mc/.. + + CPU # CPU node + ├── mc 0 + + GPU Nodes are enumerated sequentially after CPU nodes have been populated + GPU card 1 # Each MI200 GPU has 2 nodes/mcs + ├── mc 1 # GPU node 0 == mc1, Each MC node has 4 UMCs/CSROWs + │   ├── csrow 0 # UMC 0 + │   │   ├── channel 0 # Each UMC has 8 channels + │   │   ├── channel 1 # size of each channel is 2 GB, so each UMC has 16 GB + │   │   ├── channel 2 + │   │   ├── channel 3 + │   │   ├── channel 4 + │   │   ├── channel 5 + │   │   ├── channel 6 + │   │   ├── channel 7 + │   ├── csrow 1 # UMC 1 + │   │   ├── channel 0 + │   │   ├── .. + │   │   ├── channel 7 + │   ├── .. .. + │   ├── csrow 3 # UMC 3 + │   │   ├── channel 0 + │   │   ├── .. + │   │   ├── channel 7 + │   ├── rank 0 + │   ├── .. .. + │   ├── rank 31 # total 32 ranks/dimms from 4 UMCs + ├ + ├── mc 2 # GPU node 1 == mc2 + │   ├── .. # each GPU has total 64 GB + + GPU card 2 + ├── mc 3 + │   ├── .. + ├── mc 4 + │   ├── .. + + GPU card 3 + ├── mc 5 + │   ├── .. + ├── mc 6 + │   ├── .. + + GPU card 4 + ├── mc 7 + │   ├── .. + ├── mc 8 + │   ├── .. diff --git a/Documentation/driver-api/gpio/legacy.rst b/Documentation/driver-api/gpio/legacy.rst index 78372853c6d4d67400e2aac44414abb9b9eb1cae..b6505914791c7d2dead8210d0a5c222ec98152ae 100644 --- a/Documentation/driver-api/gpio/legacy.rst +++ b/Documentation/driver-api/gpio/legacy.rst @@ -165,8 +165,7 @@ Most GPIO controllers can be accessed with memory read/write instructions. Those don't need to sleep, and can safely be done from inside hard (nonthreaded) IRQ handlers and similar contexts. -Use the following calls to access such GPIOs, -for which gpio_cansleep() will always return false (see below):: +Use the following calls to access such GPIOs:: /* GPIO INPUT: return zero or nonzero */ int gpio_get_value(unsigned gpio); @@ -200,13 +199,6 @@ Some GPIO controllers must be accessed using message based busses like I2C or SPI. Commands to read or write those GPIO values require waiting to get to the head of a queue to transmit a command and get its response. This requires sleeping, which can't be done from inside IRQ handlers. - -Platforms that support this type of GPIO distinguish them from other GPIOs -by returning nonzero from this call (which requires a valid GPIO number, -which should have been previously allocated with gpio_request):: - - int gpio_cansleep(unsigned gpio); - To access such GPIOs, a different set of accessors is defined:: /* GPIO INPUT: return zero or nonzero, might sleep */ @@ -215,7 +207,6 @@ To access such GPIOs, a different set of accessors is defined:: /* GPIO OUTPUT, might sleep */ void gpio_set_value_cansleep(unsigned gpio, int value); - Accessing such GPIOs requires a context which may sleep, for example a threaded IRQ handler, and those accessors must be used instead of spinlock-safe accessors without the cansleep() name suffix. @@ -319,11 +310,6 @@ where 'flags' is currently defined to specify the following properties: * GPIOF_INIT_LOW - as output, set initial level to LOW * GPIOF_INIT_HIGH - as output, set initial level to HIGH - * GPIOF_OPEN_DRAIN - gpio pin is open drain type. - * GPIOF_OPEN_SOURCE - gpio pin is open source type. - - * GPIOF_EXPORT_DIR_FIXED - export gpio to sysfs, keep direction - * GPIOF_EXPORT_DIR_CHANGEABLE - also export, allow changing direction since GPIOF_INIT_* are only valid when configured as output, so group valid combinations as: @@ -332,20 +318,6 @@ combinations as: * GPIOF_OUT_INIT_LOW - configured as output, initial level LOW * GPIOF_OUT_INIT_HIGH - configured as output, initial level HIGH -When setting the flag as GPIOF_OPEN_DRAIN then it will assume that pins is -open drain type. Such pins will not be driven to 1 in output mode. It is -require to connect pull-up on such pins. By enabling this flag, gpio lib will -make the direction to input when it is asked to set value of 1 in output mode -to make the pin HIGH. The pin is make to LOW by driving value 0 in output mode. - -When setting the flag as GPIOF_OPEN_SOURCE then it will assume that pins is -open source type. Such pins will not be driven to 0 in output mode. It is -require to connect pull-down on such pin. By enabling this flag, gpio lib will -make the direction to input when it is asked to set value of 0 in output mode -to make the pin LOW. The pin is make to HIGH by driving value 1 in output mode. - -In the future, these flags can be extended to support more properties. - Further more, to ease the claim/release of multiple GPIOs, 'struct gpio' is introduced to encapsulate all three fields as:: @@ -556,7 +528,6 @@ code, which always dispatches through the gpio_chip:: #define gpio_get_value __gpio_get_value #define gpio_set_value __gpio_set_value - #define gpio_cansleep __gpio_cansleep Fancier implementations could instead define those as inline functions with logic optimizing access to specific SOC-based GPIOs. For example, if the diff --git a/Documentation/driver-api/index.rst b/Documentation/driver-api/index.rst index ff9aa1afdc6239c49afeeed882236261f90f8f07..1e16a40da3baad60577750d667fe8450e3f845e0 100644 --- a/Documentation/driver-api/index.rst +++ b/Documentation/driver-api/index.rst @@ -113,6 +113,7 @@ available subsections can be seen below. xillybus zorro hte/index + wmi .. only:: subproject and html diff --git a/Documentation/driver-api/media/camera-sensor.rst b/Documentation/driver-api/media/camera-sensor.rst index c7d4891bd24e79fe458fad386e254877c1af8584..93f4f2536c250d543a24bf14095ba3d7c9d818c5 100644 --- a/Documentation/driver-api/media/camera-sensor.rst +++ b/Documentation/driver-api/media/camera-sensor.rst @@ -151,3 +151,25 @@ used to obtain device's power state after the power state transition: The function returns a non-zero value if it succeeded getting the power count or runtime PM was disabled, in either of which cases the driver may proceed to access the device. + +Rotation, orientation and flipping +---------------------------------- + +Some systems have the camera sensor mounted upside down compared to its natural +mounting rotation. In such cases, drivers shall expose the information to +userspace with the :ref:`V4L2_CID_CAMERA_SENSOR_ROTATION +` control. + +Sensor drivers shall also report the sensor's mounting orientation with the +:ref:`V4L2_CID_CAMERA_SENSOR_ORIENTATION `. + +Use ``v4l2_fwnode_device_parse()`` to obtain rotation and orientation +information from system firmware and ``v4l2_ctrl_new_fwnode_properties()`` to +register the appropriate controls. + +Sensor drivers that have any vertical or horizontal flips embedded in the +register programming sequences shall initialize the V4L2_CID_HFLIP and +V4L2_CID_VFLIP controls with the values programmed by the register sequences. +The default values of these controls shall be 0 (disabled). Especially these +controls shall not be inverted, independently of the sensor's mounting +rotation. diff --git a/Documentation/driver-api/ntb.rst b/Documentation/driver-api/ntb.rst index 11577c2105c5583b9c67e5d285baccc909144274..e991d92b8b1d28c49d7bdb3a693876b6d1b4b4b1 100644 --- a/Documentation/driver-api/ntb.rst +++ b/Documentation/driver-api/ntb.rst @@ -207,9 +207,9 @@ The MSI test client serves to test and debug the MSI library which allows for passing MSI interrupts across NTB memory windows. The test client is interacted with through the debugfs filesystem: -* *debugfs*/ntb\_tool/*hw*/ +* *debugfs*/ntb\_msi\_test/*hw*/ A directory in debugfs will be created for each - NTB device probed by the tool. This directory is shortened to *hw* + NTB device probed by the msi test. This directory is shortened to *hw* below. * *hw*/port This file describes the local port number diff --git a/Documentation/driver-api/ptp.rst b/Documentation/driver-api/ptp.rst index 664838ae7776015bc923473fd85c46cf0388fadd..5e033c3b11b32a5c96be24030b44afae2e6b0ab1 100644 --- a/Documentation/driver-api/ptp.rst +++ b/Documentation/driver-api/ptp.rst @@ -73,6 +73,22 @@ Writing clock drivers class driver, since the lock may also be needed by the clock driver's interrupt service routine. +PTP hardware clock requirements for '.adjphase' +----------------------------------------------- + + The 'struct ptp_clock_info' interface has a '.adjphase' function. + This function has a set of requirements from the PHC in order to be + implemented. + + * The PHC implements a servo algorithm internally that is used to + correct the offset passed in the '.adjphase' call. + * When other PTP adjustment functions are called, the PHC servo + algorithm is disabled. + + **NOTE:** '.adjphase' is not a simple time adjustment functionality + that 'jumps' the PHC clock time based on the provided offset. It + should correct the offset provided using an internal algorithm. + Supported hardware ================== @@ -106,3 +122,16 @@ Supported hardware - LPF settings (bandwidth, phase limiting, automatic holdover, physical layer assist (per ITU-T G.8273.2)) - Programmable output PTP clocks, any frequency up to 1GHz (to other PHY/MAC time stampers, refclk to ASSPs/SoCs/FPGAs) - Lock to GNSS input, automatic switching between GNSS and user-space PHC control (optional) + + * NVIDIA Mellanox + + - GPIO + - Certain variants of ConnectX-6 Dx and later products support one + GPIO which can time stamp external triggers and one GPIO to produce + periodic signals. + - Certain variants of ConnectX-5 and older products support one GPIO, + configured to either time stamp external triggers or produce + periodic signals. + - PHC instances + - All ConnectX devices have a free-running counter + - ConnectX-6 Dx and later devices have a UTC format counter diff --git a/Documentation/driver-api/wmi.rst b/Documentation/driver-api/wmi.rst new file mode 100644 index 0000000000000000000000000000000000000000..6ca58c8249e5482550c234784aa09463b708d546 --- /dev/null +++ b/Documentation/driver-api/wmi.rst @@ -0,0 +1,21 @@ +.. SPDX-License-Identifier: GPL-2.0-or-later + +============== +WMI Driver API +============== + +The WMI driver core supports a more modern bus-based interface for interacting +with WMI devices, and an older GUID-based interface. The latter interface is +considered to be deprecated, so new WMI drivers should generally avoid it since +it has some issues with multiple WMI devices and events sharing the same GUIDs +and/or notification IDs. The modern bus-based interface instead maps each +WMI device to a :c:type:`struct wmi_device `, so it supports +WMI devices sharing GUIDs and/or notification IDs. Drivers can then register +a :c:type:`struct wmi_driver `, which will be bound to compatible +WMI devices by the driver core. + +.. kernel-doc:: include/linux/wmi.h + :internal: + +.. kernel-doc:: drivers/platform/x86/wmi.c + :export: diff --git a/Documentation/fault-injection/provoke-crashes.rst b/Documentation/fault-injection/provoke-crashes.rst index 3abe84225613903f373416724b7a0f25e3bcc2f2..1f087e502ca6da92dc30c479057f5a257070e6b5 100644 --- a/Documentation/fault-injection/provoke-crashes.rst +++ b/Documentation/fault-injection/provoke-crashes.rst @@ -29,7 +29,7 @@ recur_count cpoint_name Where in the kernel to trigger the action. It can be one of INT_HARDWARE_ENTRY, INT_HW_IRQ_EN, INT_TASKLET_ENTRY, - FS_DEVRW, MEM_SWAPOUT, TIMERADD, SCSI_QUEUE_RQ, or DIRECT. + FS_SUBMIT_BH, MEM_SWAPOUT, TIMERADD, SCSI_QUEUE_RQ, or DIRECT. cpoint_type Indicates the action to be taken on hitting the crash point. diff --git a/Documentation/features/core/jump-labels/arch-support.txt b/Documentation/features/core/jump-labels/arch-support.txt index 2328eada3a491a4d386f3e99f10fa8fa15219840..94d9dece580f180189a7c3ccf6974892fa46d7d4 100644 --- a/Documentation/features/core/jump-labels/arch-support.txt +++ b/Documentation/features/core/jump-labels/arch-support.txt @@ -13,7 +13,7 @@ | csky: | ok | | hexagon: | TODO | | ia64: | TODO | - | loongarch: | TODO | + | loongarch: | ok | | m68k: | TODO | | microblaze: | TODO | | mips: | ok | diff --git a/Documentation/features/debug/kmemleak/arch-support.txt b/Documentation/features/debug/kmemleak/arch-support.txt index 0cfa5f0e4db152301061f81c244ee3f366d2efcc..4e205ef7036354a429e9e65fa6942ae6094b641b 100644 --- a/Documentation/features/debug/kmemleak/arch-support.txt +++ b/Documentation/features/debug/kmemleak/arch-support.txt @@ -13,7 +13,7 @@ | csky: | ok | | hexagon: | TODO | | ia64: | TODO | - | loongarch: | TODO | + | loongarch: | ok | | m68k: | TODO | | microblaze: | ok | | mips: | ok | diff --git a/Documentation/filesystems/autofs-mount-control.rst b/Documentation/filesystems/autofs-mount-control.rst index bf4b511cdbe85dbb775030ac23761a7b9007e575..b5a379d25c40b3e3ebe17a514e40189216c21d38 100644 --- a/Documentation/filesystems/autofs-mount-control.rst +++ b/Documentation/filesystems/autofs-mount-control.rst @@ -196,7 +196,7 @@ information and return operation results:: struct args_ismountpoint ismountpoint; }; - char path[0]; + char path[]; }; The ioctlfd field is a mount point file descriptor of an autofs mount diff --git a/Documentation/filesystems/autofs.rst b/Documentation/filesystems/autofs.rst index 4f490278d22fca8a27533bb16e5411ea42600f67..3b6e38e646cd8c362960351a84885f56202ccf1a 100644 --- a/Documentation/filesystems/autofs.rst +++ b/Documentation/filesystems/autofs.rst @@ -467,7 +467,7 @@ Each ioctl is passed a pointer to an `autofs_dev_ioctl` structure:: struct args_ismountpoint ismountpoint; }; - char path[0]; + char path[]; }; For the **OPEN_MOUNT** and **IS_MOUNTPOINT** commands, the target diff --git a/Documentation/filesystems/directory-locking.rst b/Documentation/filesystems/directory-locking.rst index 504ba940c36c177071f8c509fdeaf4f1cc368273..dccd61c7c5c3bef2f12506dd3de986e894c8edda 100644 --- a/Documentation/filesystems/directory-locking.rst +++ b/Documentation/filesystems/directory-locking.rst @@ -22,12 +22,11 @@ exclusive. 3) object removal. Locking rules: caller locks parent, finds victim, locks victim and calls the method. Locks are exclusive. -4) rename() that is _not_ cross-directory. Locking rules: caller locks -the parent and finds source and target. In case of exchange (with -RENAME_EXCHANGE in flags argument) lock both. In any case, -if the target already exists, lock it. If the source is a non-directory, -lock it. If we need to lock both, lock them in inode pointer order. -Then call the method. All locks are exclusive. +4) rename() that is _not_ cross-directory. Locking rules: caller locks the +parent and finds source and target. We lock both (provided they exist). If we +need to lock two inodes of different type (dir vs non-dir), we lock directory +first. If we need to lock two inodes of the same type, lock them in inode +pointer order. Then call the method. All locks are exclusive. NB: we might get away with locking the source (and target in exchange case) shared. @@ -44,15 +43,17 @@ All locks are exclusive. rules: * lock the filesystem - * lock parents in "ancestors first" order. + * lock parents in "ancestors first" order. If one is not ancestor of + the other, lock them in inode pointer order. * find source and target. * if old parent is equal to or is a descendent of target fail with -ENOTEMPTY * if new parent is equal to or is a descendent of source fail with -ELOOP - * If it's an exchange, lock both the source and the target. - * If the target exists, lock it. If the source is a non-directory, - lock it. If we need to lock both, do so in inode pointer order. + * Lock both the source and the target provided they exist. If we + need to lock two inodes of different type (dir vs non-dir), we lock + the directory first. If we need to lock two inodes of the same type, + lock them in inode pointer order. * call the method. All ->i_rwsem are taken exclusive. Again, we might get away with locking @@ -66,8 +67,9 @@ If no directory is its own ancestor, the scheme above is deadlock-free. Proof: - First of all, at any moment we have a partial ordering of the - objects - A < B iff A is an ancestor of B. + First of all, at any moment we have a linear ordering of the + objects - A < B iff (A is an ancestor of B) or (B is not an ancestor + of A and ptr(A) < ptr(B)). That ordering can change. However, the following is true: diff --git a/Documentation/filesystems/dlmfs.rst b/Documentation/filesystems/dlmfs.rst index 28dd41a63be24d08a4ef3bf0c0c7231a210db51a..7e2b1fd471d79490debc8da33766624e4e3b7fd3 100644 --- a/Documentation/filesystems/dlmfs.rst +++ b/Documentation/filesystems/dlmfs.rst @@ -12,7 +12,7 @@ dlmfs is built with OCFS2 as it requires most of its infrastructure. :Project web page: http://ocfs2.wiki.kernel.org :Tools web page: https://github.com/markfasheh/ocfs2-tools -:OCFS2 mailing lists: https://oss.oracle.com/projects/ocfs2/mailman/ +:OCFS2 mailing lists: https://subspace.kernel.org/lists.linux.dev.html All code copyright 2005 Oracle except when otherwise noted. diff --git a/Documentation/filesystems/ext4/journal.rst b/Documentation/filesystems/ext4/journal.rst index a6bef5293a6005117fe8c34eeb1b7591a6223e2d..6e8fb2d4b46fed52ef8986d782ed7fc35dc10b8c 100644 --- a/Documentation/filesystems/ext4/journal.rst +++ b/Documentation/filesystems/ext4/journal.rst @@ -260,8 +260,13 @@ which is 1024 bytes long: - s_num_fc_blocks - Number of fast commit blocks in the journal. * - 0x58 + - __be32 + - s_head + - Block number of the head (first unused block) of the journal, only + up-to-date when the journal is empty. + * - 0x5C - __u32 - - s_padding[42] + - s_padding[40] - * - 0xFC - __be32 diff --git a/Documentation/filesystems/f2fs.rst b/Documentation/filesystems/f2fs.rst index c57745375edbc76a3eabcc51edd3458919f547ed..9359978a5af26019ed43ace34c7da3b0055f37ff 100644 --- a/Documentation/filesystems/f2fs.rst +++ b/Documentation/filesystems/f2fs.rst @@ -351,6 +351,22 @@ age_extent_cache Enable an age extent cache based on rb-tree. It records data block update frequency of the extent per inode, in order to provide better temperature hints for data block allocation. +errors=%s Specify f2fs behavior on critical errors. This supports modes: + "panic", "continue" and "remount-ro", respectively, trigger + panic immediately, continue without doing anything, and remount + the partition in read-only mode. By default it uses "continue" + mode. + ====================== =============== =============== ======== + mode continue remount-ro panic + ====================== =============== =============== ======== + access ops normal noraml N/A + syscall errors -EIO -EROFS N/A + mount option rw ro N/A + pending dir write keep keep N/A + pending non-dir write drop keep N/A + pending node write drop keep N/A + pending meta write keep keep N/A + ====================== =============== =============== ======== ======================== ============================================================ Debugfs Entries diff --git a/Documentation/filesystems/fsverity.rst b/Documentation/filesystems/fsverity.rst index ede672dedf110d58e53b8e7124b49da389f740fe..cb845e8e5435304fa887408c0b78f1f1221fc65b 100644 --- a/Documentation/filesystems/fsverity.rst +++ b/Documentation/filesystems/fsverity.rst @@ -38,20 +38,14 @@ fail at runtime. Use cases ========= -By itself, the base fs-verity feature only provides integrity -protection, i.e. detection of accidental (non-malicious) corruption. +By itself, fs-verity only provides integrity protection, i.e. +detection of accidental (non-malicious) corruption. However, because fs-verity makes retrieving the file hash extremely efficient, it's primarily meant to be used as a tool to support authentication (detection of malicious modifications) or auditing (logging file hashes before use). -Trusted userspace code (e.g. operating system code running on a -read-only partition that is itself authenticated by dm-verity) can -authenticate the contents of an fs-verity file by using the -`FS_IOC_MEASURE_VERITY`_ ioctl to retrieve its hash, then verifying a -digital signature of it. - A standard file hash could be used instead of fs-verity. However, this is inefficient if the file is large and only a small portion may be accessed. This is often the case for Android application package @@ -69,24 +63,31 @@ still be used on read-only filesystems. fs-verity is for files that must live on a read-write filesystem because they are independently updated and potentially user-installed, so dm-verity cannot be used. -The base fs-verity feature is a hashing mechanism only; actually -authenticating the files may be done by: - -* Userspace-only - -* Builtin signature verification + userspace policy - - fs-verity optionally supports a simple signature verification - mechanism where users can configure the kernel to require that - all fs-verity files be signed by a key loaded into a keyring; - see `Built-in signature verification`_. - -* Integrity Measurement Architecture (IMA) - - IMA supports including fs-verity file digests and signatures in the - IMA measurement list and verifying fs-verity based file signatures - stored as security.ima xattrs, based on policy. - +fs-verity does not mandate a particular scheme for authenticating its +file hashes. (Similarly, dm-verity does not mandate a particular +scheme for authenticating its block device root hashes.) Options for +authenticating fs-verity file hashes include: + +- Trusted userspace code. Often, the userspace code that accesses + files can be trusted to authenticate them. Consider e.g. an + application that wants to authenticate data files before using them, + or an application loader that is part of the operating system (which + is already authenticated in a different way, such as by being loaded + from a read-only partition that uses dm-verity) and that wants to + authenticate applications before loading them. In these cases, this + trusted userspace code can authenticate a file's contents by + retrieving its fs-verity digest using `FS_IOC_MEASURE_VERITY`_, then + verifying a signature of it using any userspace cryptographic + library that supports digital signatures. + +- Integrity Measurement Architecture (IMA). IMA supports fs-verity + file digests as an alternative to its traditional full file digests. + "IMA appraisal" enforces that files contain a valid, matching + signature in their "security.ima" extended attribute, as controlled + by the IMA policy. For more information, see the IMA documentation. + +- Trusted userspace code in combination with `Built-in signature + verification`_. This approach should be used only with great care. User API ======== @@ -111,8 +112,7 @@ follows:: }; This structure contains the parameters of the Merkle tree to build for -the file, and optionally contains a signature. It must be initialized -as follows: +the file. It must be initialized as follows: - ``version`` must be 1. - ``hash_algorithm`` must be the identifier for the hash algorithm to @@ -129,12 +129,14 @@ as follows: file or device. Currently the maximum salt size is 32 bytes. - ``salt_ptr`` is the pointer to the salt, or NULL if no salt is provided. -- ``sig_size`` is the size of the signature in bytes, or 0 if no - signature is provided. Currently the signature is (somewhat - arbitrarily) limited to 16128 bytes. See `Built-in signature - verification`_ for more information. -- ``sig_ptr`` is the pointer to the signature, or NULL if no - signature is provided. +- ``sig_size`` is the size of the builtin signature in bytes, or 0 if no + builtin signature is provided. Currently the builtin signature is + (somewhat arbitrarily) limited to 16128 bytes. +- ``sig_ptr`` is the pointer to the builtin signature, or NULL if no + builtin signature is provided. A builtin signature is only needed + if the `Built-in signature verification`_ feature is being used. It + is not needed for IMA appraisal, and it is not needed if the file + signature is being handled entirely in userspace. - All reserved fields must be zeroed. FS_IOC_ENABLE_VERITY causes the filesystem to build a Merkle tree for @@ -158,7 +160,7 @@ fatal signal), no changes are made to the file. FS_IOC_ENABLE_VERITY can fail with the following errors: - ``EACCES``: the process does not have write access to the file -- ``EBADMSG``: the signature is malformed +- ``EBADMSG``: the builtin signature is malformed - ``EBUSY``: this ioctl is already running on the file - ``EEXIST``: the file already has verity enabled - ``EFAULT``: the caller provided inaccessible memory @@ -168,10 +170,10 @@ FS_IOC_ENABLE_VERITY can fail with the following errors: reserved bits are set; or the file descriptor refers to neither a regular file nor a directory. - ``EISDIR``: the file descriptor refers to a directory -- ``EKEYREJECTED``: the signature doesn't match the file -- ``EMSGSIZE``: the salt or signature is too long -- ``ENOKEY``: the fs-verity keyring doesn't contain the certificate - needed to verify the signature +- ``EKEYREJECTED``: the builtin signature doesn't match the file +- ``EMSGSIZE``: the salt or builtin signature is too long +- ``ENOKEY``: the ".fs-verity" keyring doesn't contain the certificate + needed to verify the builtin signature - ``ENOPKG``: fs-verity recognizes the hash algorithm, but it's not available in the kernel's crypto API as currently configured (e.g. for SHA-512, missing CONFIG_CRYPTO_SHA512). @@ -180,8 +182,8 @@ FS_IOC_ENABLE_VERITY can fail with the following errors: support; or the filesystem superblock has not had the 'verity' feature enabled on it; or the filesystem does not support fs-verity on this file. (See `Filesystem support`_.) -- ``EPERM``: the file is append-only; or, a signature is required and - one was not provided. +- ``EPERM``: the file is append-only; or, a builtin signature is + required and one was not provided. - ``EROFS``: the filesystem is read-only - ``ETXTBSY``: someone has the file open for writing. This can be the caller's file descriptor, another open file descriptor, or the file @@ -270,9 +272,9 @@ This ioctl takes in a pointer to the following structure:: - ``FS_VERITY_METADATA_TYPE_DESCRIPTOR`` reads the fs-verity descriptor. See `fs-verity descriptor`_. -- ``FS_VERITY_METADATA_TYPE_SIGNATURE`` reads the signature which was - passed to FS_IOC_ENABLE_VERITY, if any. See `Built-in signature - verification`_. +- ``FS_VERITY_METADATA_TYPE_SIGNATURE`` reads the builtin signature + which was passed to FS_IOC_ENABLE_VERITY, if any. See `Built-in + signature verification`_. The semantics are similar to those of ``pread()``. ``offset`` specifies the offset in bytes into the metadata item to read from, and @@ -299,7 +301,7 @@ FS_IOC_READ_VERITY_METADATA can fail with the following errors: overflowed - ``ENODATA``: the file is not a verity file, or FS_VERITY_METADATA_TYPE_SIGNATURE was requested but the file doesn't - have a built-in signature + have a builtin signature - ``ENOTTY``: this type of filesystem does not implement fs-verity, or this ioctl is not yet implemented on it - ``EOPNOTSUPP``: the kernel was not configured with fs-verity @@ -347,8 +349,8 @@ non-verity one, with the following exceptions: with EIO (for read()) or SIGBUS (for mmap() reads). - If the sysctl "fs.verity.require_signatures" is set to 1 and the - file is not signed by a key in the fs-verity keyring, then opening - the file will fail. See `Built-in signature verification`_. + file is not signed by a key in the ".fs-verity" keyring, then + opening the file will fail. See `Built-in signature verification`_. Direct access to the Merkle tree is not supported. Therefore, if a verity file is copied, or is backed up and restored, then it will lose @@ -433,20 +435,25 @@ root hash as well as other fields such as the file size:: Built-in signature verification =============================== -With CONFIG_FS_VERITY_BUILTIN_SIGNATURES=y, fs-verity supports putting -a portion of an authentication policy (see `Use cases`_) in the -kernel. Specifically, it adds support for: +CONFIG_FS_VERITY_BUILTIN_SIGNATURES=y adds supports for in-kernel +verification of fs-verity builtin signatures. + +**IMPORTANT**! Please take great care before using this feature. +It is not the only way to do signatures with fs-verity, and the +alternatives (such as userspace signature verification, and IMA +appraisal) can be much better. It's also easy to fall into a trap +of thinking this feature solves more problems than it actually does. + +Enabling this option adds the following: -1. At fs-verity module initialization time, a keyring ".fs-verity" is - created. The root user can add trusted X.509 certificates to this - keyring using the add_key() system call, then (when done) - optionally use keyctl_restrict_keyring() to prevent additional - certificates from being added. +1. At boot time, the kernel creates a keyring named ".fs-verity". The + root user can add trusted X.509 certificates to this keyring using + the add_key() system call. 2. `FS_IOC_ENABLE_VERITY`_ accepts a pointer to a PKCS#7 formatted detached signature in DER format of the file's fs-verity digest. - On success, this signature is persisted alongside the Merkle tree. - Then, any time the file is opened, the kernel will verify the + On success, the ioctl persists the signature alongside the Merkle + tree. Then, any time the file is opened, the kernel verifies the file's actual digest against this signature, using the certificates in the ".fs-verity" keyring. @@ -454,8 +461,8 @@ kernel. Specifically, it adds support for: When set to 1, the kernel requires that all verity files have a correctly signed digest as described in (2). -fs-verity file digests must be signed in the following format, which -is similar to the structure used by `FS_IOC_MEASURE_VERITY`_:: +The data that the signature as described in (2) must be a signature of +is the fs-verity file digest in the following format:: struct fsverity_formatted_digest { char magic[8]; /* must be "FSVerity" */ @@ -464,13 +471,66 @@ is similar to the structure used by `FS_IOC_MEASURE_VERITY`_:: __u8 digest[]; }; -fs-verity's built-in signature verification support is meant as a -relatively simple mechanism that can be used to provide some level of -authenticity protection for verity files, as an alternative to doing -the signature verification in userspace or using IMA-appraisal. -However, with this mechanism, userspace programs still need to check -that the verity bit is set, and there is no protection against verity -files being swapped around. +That's it. It should be emphasized again that fs-verity builtin +signatures are not the only way to do signatures with fs-verity. See +`Use cases`_ for an overview of ways in which fs-verity can be used. +fs-verity builtin signatures have some major limitations that should +be carefully considered before using them: + +- Builtin signature verification does *not* make the kernel enforce + that any files actually have fs-verity enabled. Thus, it is not a + complete authentication policy. Currently, if it is used, the only + way to complete the authentication policy is for trusted userspace + code to explicitly check whether files have fs-verity enabled with a + signature before they are accessed. (With + fs.verity.require_signatures=1, just checking whether fs-verity is + enabled suffices.) But, in this case the trusted userspace code + could just store the signature alongside the file and verify it + itself using a cryptographic library, instead of using this feature. + +- A file's builtin signature can only be set at the same time that + fs-verity is being enabled on the file. Changing or deleting the + builtin signature later requires re-creating the file. + +- Builtin signature verification uses the same set of public keys for + all fs-verity enabled files on the system. Different keys cannot be + trusted for different files; each key is all or nothing. + +- The sysctl fs.verity.require_signatures applies system-wide. + Setting it to 1 only works when all users of fs-verity on the system + agree that it should be set to 1. This limitation can prevent + fs-verity from being used in cases where it would be helpful. + +- Builtin signature verification can only use signature algorithms + that are supported by the kernel. For example, the kernel does not + yet support Ed25519, even though this is often the signature + algorithm that is recommended for new cryptographic designs. + +- fs-verity builtin signatures are in PKCS#7 format, and the public + keys are in X.509 format. These formats are commonly used, + including by some other kernel features (which is why the fs-verity + builtin signatures use them), and are very feature rich. + Unfortunately, history has shown that code that parses and handles + these formats (which are from the 1990s and are based on ASN.1) + often has vulnerabilities as a result of their complexity. This + complexity is not inherent to the cryptography itself. + + fs-verity users who do not need advanced features of X.509 and + PKCS#7 should strongly consider using simpler formats, such as plain + Ed25519 keys and signatures, and verifying signatures in userspace. + + fs-verity users who choose to use X.509 and PKCS#7 anyway should + still consider that verifying those signatures in userspace is more + flexible (for other reasons mentioned earlier in this document) and + eliminates the need to enable CONFIG_FS_VERITY_BUILTIN_SIGNATURES + and its associated increase in kernel attack surface. In some cases + it can even be necessary, since advanced X.509 and PKCS#7 features + do not always work as intended with the kernel. For example, the + kernel does not check X.509 certificate validity times. + + Note: IMA appraisal, which supports fs-verity, does not use PKCS#7 + for its signatures, so it partially avoids the issues discussed + here. IMA appraisal does use X.509. Filesystem support ================== diff --git a/Documentation/filesystems/locking.rst b/Documentation/filesystems/locking.rst index aa1a233b0fa862a78f8a59cfb6f627525817252b..ed148919e11ad5e49ecd569110f8cabf7541607e 100644 --- a/Documentation/filesystems/locking.rst +++ b/Documentation/filesystems/locking.rst @@ -521,8 +521,6 @@ prototypes:: int (*fsync) (struct file *, loff_t start, loff_t end, int datasync); int (*fasync) (int, struct file *, int); int (*lock) (struct file *, int, struct file_lock *); - 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); diff --git a/Documentation/filesystems/nfs/exporting.rst b/Documentation/filesystems/nfs/exporting.rst index 0e98edd353b5f13920ec0837525e371bf16815ee..3d97b8d8f7354490f152254b3e446b8bfb7bb8f8 100644 --- a/Documentation/filesystems/nfs/exporting.rst +++ b/Documentation/filesystems/nfs/exporting.rst @@ -122,8 +122,8 @@ are exportable by setting the s_export_op field in the struct super_block. This field must point to a "struct export_operations" struct which has the following members: - encode_fh (optional) - Takes a dentry and creates a filehandle fragment which can later be used + encode_fh (optional) + Takes a dentry and creates a filehandle fragment which may later be used to find or create a dentry for the same object. The default implementation creates a filehandle fragment that encodes a 32bit inode and generation number for the inode encoded, and if necessary the diff --git a/Documentation/filesystems/ocfs2.rst b/Documentation/filesystems/ocfs2.rst index 42ca9a3d4c6ea6f0b39f0240df89e2e32623b33d..5827062995cb06a7372bbb4c300164634bac83ed 100644 --- a/Documentation/filesystems/ocfs2.rst +++ b/Documentation/filesystems/ocfs2.rst @@ -14,7 +14,7 @@ get "mount.ocfs2" and "ocfs2_hb_ctl". Project web page: http://ocfs2.wiki.kernel.org Tools git tree: https://github.com/markfasheh/ocfs2-tools -OCFS2 mailing lists: https://oss.oracle.com/projects/ocfs2/mailman/ +OCFS2 mailing lists: https://subspace.kernel.org/lists.linux.dev.html All code copyright 2005 Oracle except when otherwise noted. diff --git a/Documentation/filesystems/overlayfs.rst b/Documentation/filesystems/overlayfs.rst index 4c76fda076454ca8d72157e43fb5a7489cf8b75f..eb7d2c88ddecec72efde088dc589c69d6c032736 100644 --- a/Documentation/filesystems/overlayfs.rst +++ b/Documentation/filesystems/overlayfs.rst @@ -231,12 +231,11 @@ Mount options: Redirects are enabled. - "redirect_dir=follow": Redirects are not created, but followed. -- "redirect_dir=off": - Redirects are not created and only followed if "redirect_always_follow" - feature is enabled in the kernel/module config. - "redirect_dir=nofollow": - Redirects are not created and not followed (equivalent to "redirect_dir=off" - if "redirect_always_follow" feature is not enabled). + Redirects are not created and not followed. +- "redirect_dir=off": + If "redirect_always_follow" is enabled in the kernel/module config, + this "off" traslates to "follow", otherwise it translates to "nofollow". When the NFS export feature is enabled, every copied up directory is indexed by the file handle of the lower inode and a file handle of the @@ -371,6 +370,41 @@ conflict with metacopy=on, and will result in an error. [*] redirect_dir=follow only conflicts with metacopy=on if upperdir=... is given. + +Data-only lower layers +---------------------- + +With "metacopy" feature enabled, an overlayfs regular file may be a composition +of information from up to three different layers: + + 1) metadata from a file in the upper layer + + 2) st_ino and st_dev object identifier from a file in a lower layer + + 3) data from a file in another lower layer (further below) + +The "lower data" file can be on any lower layer, except from the top most +lower layer. + +Below the top most lower layer, any number of lower most layers may be defined +as "data-only" lower layers, using double colon ("::") separators. +A normal lower layer is not allowed to be below a data-only layer, so single +colon separators are not allowed to the right of double colon ("::") separators. + + +For example: + + mount -t overlay overlay -olowerdir=/l1:/l2:/l3::/do1::/do2 /merged + +The paths of files in the "data-only" lower layers are not visible in the +merged overlayfs directories and the metadata and st_ino/st_dev of files +in the "data-only" lower layers are not visible in overlayfs inodes. + +Only the data of the files in the "data-only" lower layers may be visible +when a "metacopy" file in one of the lower layers above it, has a "redirect" +to the absolute path of the "lower data" file in the "data-only" lower layer. + + Sharing and copying layers -------------------------- diff --git a/Documentation/filesystems/vfs.rst b/Documentation/filesystems/vfs.rst index 769be5230210769b454f14cbdf640301dd034121..cb2a97e498726536c7dcc14cafd035bd468882af 100644 --- a/Documentation/filesystems/vfs.rst +++ b/Documentation/filesystems/vfs.rst @@ -1086,7 +1086,6 @@ This describes how the VFS can manipulate an open file. As of kernel int (*fsync) (struct file *, loff_t, loff_t, int datasync); int (*fasync) (int, struct file *, int); int (*lock) (struct file *, int, struct file_lock *); - 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); int (*flock) (struct file *, int, struct file_lock *); diff --git a/Documentation/hwmon/aht10.rst b/Documentation/hwmon/aht10.rst index 4e198c5eb68343901b036007054c2dc6d86a6dbf..213644b4ecba6e5828eb2630eeb2d2190715825c 100644 --- a/Documentation/hwmon/aht10.rst +++ b/Documentation/hwmon/aht10.rst @@ -5,32 +5,42 @@ Kernel driver aht10 Supported chips: - * Aosong AHT10 + * Aosong AHT10/AHT20 Prefix: 'aht10' Addresses scanned: None - Datasheet: + Datasheet(AHT10): Chinese: http://www.aosong.com/userfiles/files/media/AHT10%E4%BA%A7%E5%93%81%E6%89%8B%E5%86%8C%20A3%2020201210.pdf English: https://server4.eca.ir/eshop/AHT10/Aosong_AHT10_en_draft_0c.pdf + Datasheet(AHT20): + + English: http://www.aosong.com/userfiles/files/media/Data%20Sheet%20AHT20.pdf + Author: Johannes Cornelis Draaijer Description ----------- -The AHT10 is a Temperature and Humidity sensor +The AHT10/AHT20 is a Temperature and Humidity sensor The address of this i2c device may only be 0x38 +Special Features +---------------- + +AHT20 has additional CRC8 support which is sent as the last byte of the sensor +values. + Usage Notes ----------- -This driver does not probe for AHT10 devices, as there is no reliable -way to determine if an i2c chip is or isn't an AHT10. The device has +This driver does not probe for AHT10/ATH20 devices, as there is no reliable +way to determine if an i2c chip is or isn't an AHT10/AHT20. The device has to be instantiated explicitly with the address 0x38. See Documentation/i2c/instantiating-devices.rst for details. diff --git a/Documentation/hwmon/aquacomputer_d5next.rst b/Documentation/hwmon/aquacomputer_d5next.rst index 14b37851af0ca77fd5de997b7715b254fd5efc10..94dc2d93d1808dabd7799595f8d09a8bfb4f88b9 100644 --- a/Documentation/hwmon/aquacomputer_d5next.rst +++ b/Documentation/hwmon/aquacomputer_d5next.rst @@ -12,6 +12,7 @@ Supported devices: * Aquacomputer Octo fan controller * Aquacomputer Quadro fan controller * Aquacomputer High Flow Next sensor +* Aquacomputer Leakshield leak prevention system * Aquacomputer Aquastream XT watercooling pump * Aquacomputer Aquastream Ultimate watercooling pump * Aquacomputer Poweradjust 3 fan controller @@ -57,6 +58,11 @@ The High Flow Next exposes +5V voltages, water quality, conductivity and flow re A temperature sensor can be connected to it, in which case it provides its reading and an estimation of the dissipated/absorbed power in the liquid cooling loop. +The Leakshield exposes two temperature sensors and coolant pressure (current, min, max and +target readings). It also exposes the estimated reservoir volume and how much of it is +filled with coolant. Pump RPM and flow can be set to enhance on-device calculations, +but this is not yet implemented here. + The Aquastream XT pump exposes temperature readings for the coolant, external sensor and fan IC. It also exposes pump and fan speeds (in RPM), voltages, as well as pump current. @@ -83,6 +89,9 @@ Sysfs entries temp[1-20]_input Physical/virtual temperature sensors (in millidegrees Celsius) temp[1-8]_offset Temperature sensor correction offset (in millidegrees Celsius) fan[1-8]_input Pump/fan speed (in RPM) / Flow speed (in dL/h) +fan1_min Minimal fan speed (in RPM) +fan1_max Maximal fan speed (in RPM) +fan1_target Target fan speed (in RPM) fan5_pulses Quadro flow sensor pulses power[1-8]_input Pump/fan power (in micro Watts) in[0-7]_input Pump/fan voltage (in milli Volts) diff --git a/Documentation/hwmon/asus_ec_sensors.rst b/Documentation/hwmon/asus_ec_sensors.rst index c92c1d3839e4e9e5cf17a6ac60e4d84693daf70a..7e3cd5b6686faa8673eb0393286d6129010111d1 100644 --- a/Documentation/hwmon/asus_ec_sensors.rst +++ b/Documentation/hwmon/asus_ec_sensors.rst @@ -14,6 +14,7 @@ Supported boards: * ROG CROSSHAIR VIII FORMULA * ROG CROSSHAIR VIII HERO * ROG CROSSHAIR VIII IMPACT + * ROG CROSSHAIR X670E HERO * ROG MAXIMUS XI HERO * ROG MAXIMUS XI HERO (WI-FI) * ROG STRIX B550-E GAMING diff --git a/Documentation/hwmon/corsair-psu.rst b/Documentation/hwmon/corsair-psu.rst index c389bd21f4f2ffb959ea0567b4bbcfdd1b2dc56a..16db34d464dd6b5e2fae59f2d350d9db34500d3e 100644 --- a/Documentation/hwmon/corsair-psu.rst +++ b/Documentation/hwmon/corsair-psu.rst @@ -15,11 +15,11 @@ Supported devices: Corsair HX850i - Corsair HX1000i (revision 1 and 2) + Corsair HX1000i (Series 2022 and 2023) Corsair HX1200i - Corsair HX1500i + Corsair HX1500i (Series 2022 and 2023) Corsair RM550i @@ -69,6 +69,8 @@ power1_input Total power usage power2_input Power usage of the 12v psu rail power3_input Power usage of the 5v psu rail power4_input Power usage of the 3.3v psu rail +pwm1 PWM value, read only +pwm1_enable PWM mode, read only temp1_input Temperature of the psu vrm component temp1_crit Temperature max cirtical value of the psu vrm component temp2_input Temperature of the psu case @@ -78,11 +80,14 @@ temp2_crit Temperature max critical value of psu case Usage Notes ----------- -It is an USB HID device, so it is auto-detected and supports hot-swapping. +It is an USB HID device, so it is auto-detected, supports hot-swapping and +several devices at once. Flickering values in the rail voltage levels can be an indicator for a failing -PSU. The driver also provides some additional useful values via debugfs, which -do not fit into the hwmon class. +PSU. Accordingly to the default automatic fan speed plan the fan starts at about +30% of the wattage rating. If this does not happen, a fan failure is likely. The +driver also provides some additional useful values via debugfs, which do not fit +into the hwmon class. Debugfs entries --------------- diff --git a/Documentation/hwmon/hp-wmi-sensors.rst b/Documentation/hwmon/hp-wmi-sensors.rst new file mode 100644 index 0000000000000000000000000000000000000000..a6bca9aecdde7780b398f08ff4bdf64d65c885da --- /dev/null +++ b/Documentation/hwmon/hp-wmi-sensors.rst @@ -0,0 +1,140 @@ +.. SPDX-License-Identifier: GPL-2.0-or-later + +.. include:: + +=========================== +Linux HP WMI Sensors Driver +=========================== + +:Copyright: |copy| 2023 James Seo + +Description +=========== + +Hewlett-Packard (and some HP Compaq) business-class computers report hardware +monitoring information via Windows Management Instrumentation (WMI). +This driver exposes that information to the Linux hwmon subsystem, allowing +userspace utilities like ``sensors`` to gather numeric sensor readings. + +sysfs interface +=============== + +When the driver is loaded, it discovers the sensors available on the +system and creates the following sysfs attributes as necessary within +``/sys/class/hwmon/hwmon[X]``: + +(``[X]`` is some number that depends on other system components.) + +======================= ======= =================================== +Name Perm Description +======================= ======= =================================== +``curr[X]_input`` RO Current in milliamperes (mA). +``curr[X]_label`` RO Current sensor label. +``fan[X]_input`` RO Fan speed in RPM. +``fan[X]_label`` RO Fan sensor label. +``fan[X]_fault`` RO Fan sensor fault indicator. +``fan[X]_alarm`` RO Fan sensor alarm indicator. +``in[X]_input`` RO Voltage in millivolts (mV). +``in[X]_label`` RO Voltage sensor label. +``temp[X]_input`` RO Temperature in millidegrees Celsius + (m\ |deg|\ C). +``temp[X]_label`` RO Temperature sensor label. +``temp[X]_fault`` RO Temperature sensor fault indicator. +``temp[X]_alarm`` RO Temperature sensor alarm indicator. +``intrusion[X]_alarm`` RW Chassis intrusion alarm indicator. +======================= ======= =================================== + +``fault`` attributes + Reading ``1`` instead of ``0`` as the ``fault`` attribute for a sensor + indicates that it has encountered some issue during operation such that + measurements from it should not be trusted. If a sensor with the fault + condition recovers later, reading this attribute will return ``0`` again. + +``alarm`` attributes + Reading ``1`` instead of ``0`` as the ``alarm`` attribute for a sensor + indicates that one of the following has occurred, depending on its type: + + - ``fan``: The fan has stalled or has been disconnected while running. + - ``temp``: The sensor reading has reached a critical threshold. + The exact threshold is system-dependent. + - ``intrusion``: The system's chassis has been opened. + + After ``1`` is read from an ``alarm`` attribute, the attribute resets itself + and returns ``0`` on subsequent reads. As an exception, an + ``intrusion[X]_alarm`` can only be manually reset by writing ``0`` to it. + +debugfs interface +================= + +.. warning:: The debugfs interface is subject to change without notice + and is only available when the kernel is compiled with + ``CONFIG_DEBUG_FS`` defined. + +The standard hwmon interface in sysfs exposes sensors of several common types +that are connected as of driver initialization. However, there are usually +other sensors in WMI that do not meet these criteria. In addition, a number of +system-dependent "platform events objects" used for ``alarm`` attributes may +be present. A debugfs interface is therefore provided for read-only access to +all available HP WMI sensors and platform events objects. + +``/sys/kernel/debug/hp-wmi-sensors-[X]/sensor`` +contains one numbered entry per sensor with the following attributes: + +=============================== ======================================= +Name Example +=============================== ======================================= +``name`` ``CPU0 Fan`` +``description`` ``Reports CPU0 fan speed`` +``sensor_type`` ``12`` +``other_sensor_type`` (an empty string) +``operational_status`` ``2`` +``possible_states`` ``Normal,Caution,Critical,Not Present`` +``current_state`` ``Normal`` +``base_units`` ``19`` +``unit_modifier`` ``0`` +``current_reading`` ``1008`` +``rate_units`` ``0`` (only exists on some systems) +=============================== ======================================= + +If platform events objects are available, +``/sys/kernel/debug/hp-wmi-sensors-[X]/platform_events`` +contains one numbered entry per object with the following attributes: + +=============================== ==================== +Name Example +=============================== ==================== +``name`` ``CPU0 Fan Stall`` +``description`` ``CPU0 Fan Speed`` +``source_namespace`` ``root\wmi`` +``source_class`` ``HPBIOS_BIOSEvent`` +``category`` ``3`` +``possible_severity`` ``25`` +``possible_status`` ``5`` +=============================== ==================== + +These represent the properties of the underlying ``HPBIOS_BIOSNumericSensor`` +and ``HPBIOS_PlatformEvents`` WMI objects, which vary between systems. +See [#]_ for more details and Managed Object Format (MOF) definitions. + +Known issues and limitations +============================ + +- If the existing hp-wmi driver for non-business-class HP systems is already + loaded, ``alarm`` attributes will be unavailable even on systems that + support them. This is because the same WMI event GUID used by this driver + for ``alarm`` attributes is used on those systems for e.g. laptop hotkeys. +- Dubious sensor hardware and inconsistent BIOS WMI implementations have been + observed to cause inaccurate readings and peculiar behavior, such as alarms + failing to occur or occurring only once per boot. +- Only temperature, fan speed, and intrusion sensor types have been seen in + the wild so far. Support for voltage and current sensors is therefore + provisional. +- Although HP WMI sensors may claim to be of any type, any oddball sensor + types unknown to hwmon will not be supported. + +References +========== + +.. [#] Hewlett-Packard Development Company, L.P., + "HP Client Management Interface Technical White Paper", 2005. [Online]. + Available: https://h20331.www2.hp.com/hpsub/downloads/cmi_whitepaper.pdf diff --git a/Documentation/hwmon/hwmon-kernel-api.rst b/Documentation/hwmon/hwmon-kernel-api.rst index c2d1e0299d8d841fe611ba8e50ff82c1e92fb684..6cacf7daf25c049fcd6ebf369df668f7948c45a7 100644 --- a/Documentation/hwmon/hwmon-kernel-api.rst +++ b/Documentation/hwmon/hwmon-kernel-api.rst @@ -66,7 +66,7 @@ hwmon_device_register_with_info. devm_hwmon_device_unregister does not normally have to be called. It is only needed for error handling, and only needed if the driver probe fails after -the call to hwmon_device_register_with_info and if the automatic (device +the call to devm_hwmon_device_register_with_info and if the automatic (device managed) removal would be too late. All supported hwmon device registration functions only accept valid device diff --git a/Documentation/hwmon/index.rst b/Documentation/hwmon/index.rst index fa1208c62855d59e1a4b1256117155c1aa4cf54e..042e1cf9501bfb36f000159ec6f7eda4e8af5de8 100644 --- a/Documentation/hwmon/index.rst +++ b/Documentation/hwmon/index.rst @@ -9,7 +9,6 @@ Hardware Monitoring hwmon-kernel-api pmbus-core - inspur-ipsps1 submitting-patches sysfs-interface userspace-tools @@ -78,6 +77,7 @@ Hardware Monitoring Kernel Drivers gl518sm gxp-fan-ctrl hih6130 + hp-wmi-sensors ibmaem ibm-cffps ibmpowernv @@ -85,6 +85,7 @@ Hardware Monitoring Kernel Drivers ina2xx ina238 ina3221 + inspur-ipsps1 intel-m10-bmc-hwmon ir35221 ir38064 @@ -140,6 +141,7 @@ Hardware Monitoring Kernel Drivers max31760 max31785 max31790 + max31827 max34440 max6620 max6639 diff --git a/Documentation/hwmon/max31827.rst b/Documentation/hwmon/max31827.rst new file mode 100644 index 0000000000000000000000000000000000000000..b0971d05b8a4758f3f2d611f523090acad633058 --- /dev/null +++ b/Documentation/hwmon/max31827.rst @@ -0,0 +1,90 @@ +.. SPDX-License-Identifier: GPL-2.0 + +Kernel driver max31827 +====================== + +Supported chips: + + * Maxim MAX31827 + + Prefix: 'max31827' + + Addresses scanned: I2C 0x40 - 0x5f + + Datasheet: Publicly available at the Analog Devices website + + * Maxim MAX31828 + + Prefix: 'max31828' + + Addresses scanned: I2C 0x40 - 0x5f + + Datasheet: Publicly available at the Analog Devices website + + * Maxim MAX31829 + + Prefix: 'max31829' + + Addresses scanned: I2C 0x40 - 0x5f + + Datasheet: Publicly available at the Analog Devices website + + +Authors: + - Daniel Matyas + +Description +----------- + +The chips supported by this driver are quite similar. The only difference +between them is found in the default power-on behaviour of the chips. While the +MAX31827's fault queue is set to 1, the other two chip's fault queue is set to +4. Besides this, the MAX31829's alarm active state is high, while the other two +chip's alarms are active on low. It is important to note that the chips can be +configured to operate in the same manner with 1 write operation to the +configuration register. From here on, we will refer to all these chips as +MAX31827. + +MAX31827 implements a temperature sensor with a 6 WLP packaging scheme. This +sensor measures the temperature of the chip itself. + +MAX31827 has low and over temperature alarms with an effective value and a +hysteresis value: -40 and -30 degrees for under temperature alarm and +100 and ++90 degrees for over temperature alarm. + +The alarm can be configured in comparator and interrupt mode. Currently only +comparator mode is implemented. In Comparator mode, the OT/UT status bits have a +value of 1 when the temperature rises above the TH value or falls below TL, +which is also subject to the Fault Queue selection. OT status returns to 0 when +the temperature drops below the TH_HYST value or when shutdown mode is entered. +Similarly, UT status returns to 0 when the temperature rises above TL_HYST value +or when shutdown mode is entered. + +Putting the MAX31827 into shutdown mode also resets the OT/UT status bits. Note +that if the mode is changed while OT/UT status bits are set, an OT/UT status +reset may be required before it begins to behave normally. To prevent this, +it is recommended to perform a read of the configuration/status register to +clear the status bits before changing the operating mode. + +The conversions can be manual with the one-shot functionality and automatic with +a set frequency. When powered on, the chip measures temperatures with 1 conv/s. +Enabling the device when it is already enabled has the side effect of setting +the conversion frequency to 1 conv/s. The conversion time varies depending on +the resolution. The conversion time doubles with every bit of increased +resolution. For 10 bit resolution 35ms are needed, while for 12 bit resolution +(default) 140ms. When chip is in shutdown mode and a read operation is +requested, one-shot is triggered, the device waits for 140 (conversion time) + 1 +(error) ms, and only after that is the temperature value register read. + +The LSB of the temperature values is 0.0625 degrees Celsius, but the values of +the temperatures are displayed in milli-degrees. This means, that some data is +lost. The step between 2 consecutive values is 62 or 63. This effect can be seen +in the writing of alarm values too. For positive numbers the user-input value +will always be rounded down to the nearest possible value, for negative numbers +the user-input will always be rounded up to the nearest possible value. + +Notes +----- + +Currently fault queue, alarm polarity and resolution cannot be modified. +PEC is not implemented either. diff --git a/Documentation/hwmon/oxp-sensors.rst b/Documentation/hwmon/oxp-sensors.rst index 566a8d5bde08d8cbb7fa90f3f08f5908b0913613..3adeb7406243fbaa43a5d3bb1a1d15489122a50f 100644 --- a/Documentation/hwmon/oxp-sensors.rst +++ b/Documentation/hwmon/oxp-sensors.rst @@ -19,18 +19,32 @@ out the EC registers and values to write to since the EC layout and model is different. Aya Neo devices preceding the AIR may not be supportable as the EC model is different and do not appear to have manual control capabilities. +Some models have a toggle for changing the behaviour of the "Turbo/Silent" +button of the device. It will change the key event that it triggers with +a flip of the `tt_toggle` attribute. See below for boards that support this +function. + Supported devices ----------------- Currently the driver supports the following handhelds: - AOK ZOE A1 + - AOK ZOE A1 PRO + - Aya Neo 2 - Aya Neo AIR - Aya Neo AIR Pro + - Aya Neo Geek - OneXPlayer AMD - OneXPlayer mini AMD - OneXPlayer mini AMD PRO +"Turbo/Silent" button behaviour toggle is only supported on: + - AOK ZOE A1 + - AOK ZOE A1 PRO + - OneXPlayer mini AMD (only with updated alpha BIOS) + - OneXPlayer mini AMD PRO + Sysfs entries ------------- @@ -47,3 +61,10 @@ pwm1 Read Write. Read this attribute to see current duty cycle in the range [0-255]. When pwm1_enable is set to "1" (manual) write any value in the range [0-255] to set fan speed. + +tt_toggle + Read Write. Read this attribute to check the status of the turbo/silent + button behaviour function. Write "1" to activate the switch and "0" to + deactivate it. The specific keycodes and behaviour is specific to the device + both with this function on and off. This attribute is attached to the platform + driver and not to the hwmon driver (/sys/devices/platform/oxp-platform/tt_toggle) diff --git a/Documentation/hwmon/sht3x.rst b/Documentation/hwmon/sht3x.rst index 95a850d5b2c1d7b15b98ff2a800d46e93f6816c6..87864ffd1777d07ebe22942993b3b22359fff7f9 100644 --- a/Documentation/hwmon/sht3x.rst +++ b/Documentation/hwmon/sht3x.rst @@ -28,15 +28,8 @@ The device communicates with the I2C protocol. Sensors can have the I2C addresses 0x44 or 0x45, depending on the wiring. See Documentation/i2c/instantiating-devices.rst for methods to instantiate the device. -There are two options configurable by means of sht3x_platform_data: - -1. blocking (pull the I2C clock line down while performing the measurement) or - non-blocking mode. Blocking mode will guarantee the fastest result but - the I2C bus will be busy during that time. By default, non-blocking mode - is used. Make sure clock-stretching works properly on your device if you - want to use blocking mode. -2. high or low accuracy. High accuracy is used by default and using it is - strongly recommended. +Even if sht3x sensor supports clock-strech(blocking mode) and non-strench +(non-blocking mode) in single-shot mode, this driver only supports the latter. The sht3x sensor supports a single shot mode as well as 5 periodic measure modes, which can be controlled with the update_interval sysfs interface. @@ -85,4 +78,11 @@ heater_enable: heater enable, heating element removes excess humidity from update_interval: update interval, 0 for single shot, interval in msec for periodic measurement. If the interval is not supported by the sensor, the next faster interval is chosen +repeatability: write or read repeatability, higher repeatability means + longer measurement duration, lower noise level and + larger energy consumption: + + - 0: low repeatability + - 1: medium repeatability + - 2: high repeatability =================== ============================================================ diff --git a/Documentation/i2c/busses/i2c-i801.rst b/Documentation/i2c/busses/i2c-i801.rst index ab9e850e8fe0e4f79ec9997f0e0ba6777ca4ae61..e76e68ccf7182c55b53c7a0ee8d195ede1163632 100644 --- a/Documentation/i2c/busses/i2c-i801.rst +++ b/Documentation/i2c/busses/i2c-i801.rst @@ -46,7 +46,7 @@ Supported adapters: * Intel Emmitsburg (PCH) * Intel Alder Lake (PCH) * Intel Raptor Lake (PCH) - * Intel Meteor Lake (SOC) + * Intel Meteor Lake (SOC and PCH) Datasheets: Publicly available at the Intel website diff --git a/Documentation/input/devices/xpad.rst b/Documentation/input/devices/xpad.rst index 173c2acda9fd9092fea942e543d48771b75bfae0..a480bc781565e36a21bd3c9e094fdd7ae820ea9d 100644 --- a/Documentation/input/devices/xpad.rst +++ b/Documentation/input/devices/xpad.rst @@ -4,16 +4,16 @@ xpad - Linux USB driver for Xbox compatible controllers This driver exposes all first-party and third-party Xbox compatible controllers. It has a long history and has enjoyed considerable usage -as Window's xinput library caused most PC games to focus on Xbox +as Windows' xinput library caused most PC games to focus on Xbox controller compatibility. Due to backwards compatibility all buttons are reported as digital. -This only effects Original Xbox controllers. All later controller models +This only affects Original Xbox controllers. All later controller models have only digital face buttons. Rumble is supported on some models of Xbox 360 controllers but not of Original Xbox controllers nor on Xbox One controllers. As of writing -the Xbox One's rumble protocol has not been reverse engineered but in +the Xbox One's rumble protocol has not been reverse-engineered but in the future could be supported. @@ -82,7 +82,7 @@ I've tested this with Stepmania, and it works quite well. Unknown Controllers ------------------- -If you have an unknown xbox controller, it should work just fine with +If you have an unknown Xbox controller, it should work just fine with the default settings. HOWEVER if you have an unknown dance pad not listed below, it will not @@ -123,7 +123,7 @@ can be found on the net ([1]_, [2]_, [3]_). Thanks to the trip splitter found on the cable you don't even need to cut the original one. You can buy an extension cable and cut that instead. That way, -you can still use the controller with your X-Box, if you have one ;) +you can still use the controller with your Xbox, if you have one ;) diff --git a/Documentation/input/gamepad.rst b/Documentation/input/gamepad.rst index 71019de4603679ea618dff92b0ee692121145963..eca17a7f5258c2d781f9e06c7127c9ba504ebf02 100644 --- a/Documentation/input/gamepad.rst +++ b/Documentation/input/gamepad.rst @@ -184,7 +184,7 @@ Gamepads report the following events: Many pads also have a third button which is branded or has a special symbol and meaning. Such buttons are mapped as BTN_MODE. Examples are the Nintendo - "HOME" button, the XBox "X"-button or Sony "PS" button. + "HOME" button, the Xbox "X" button or the Sony PlayStation "PS" button. - Rumble: diff --git a/Documentation/kbuild/kbuild.rst b/Documentation/kbuild/kbuild.rst index 2a22ddb1b84829e062386e7ac4e325ffe4861ac3..bd906407e307ca4412581f1bad46ed98c658f1a9 100644 --- a/Documentation/kbuild/kbuild.rst +++ b/Documentation/kbuild/kbuild.rst @@ -150,6 +150,12 @@ the UTS_MACHINE variable, and on some architectures also the kernel config. The value of KBUILD_DEBARCH is assumed (not checked) to be a valid Debian architecture. +KDOCFLAGS +--------- +Specify extra (warning/error) flags for kernel-doc checks during the build, +see scripts/kernel-doc for which flags are supported. Note that this doesn't +(currently) apply to documentation builds. + ARCH ---- Set ARCH to the architecture to be built. diff --git a/Documentation/leds/index.rst b/Documentation/leds/index.rst index ce57254cb871f4ff2d02802e68d248e309bce931..3ade16c18328ad11423b9142c15b109eb5b4534c 100644 --- a/Documentation/leds/index.rst +++ b/Documentation/leds/index.rst @@ -17,6 +17,7 @@ LEDs uleds leds-blinkm + leds-cht-wcove leds-el15203000 leds-lm3556 leds-lp3944 diff --git a/Documentation/leds/leds-cht-wcove.rst b/Documentation/leds/leds-cht-wcove.rst new file mode 100644 index 0000000000000000000000000000000000000000..5ec7cb60c4aaac0f09af02c527fcfa4ae2ece283 --- /dev/null +++ b/Documentation/leds/leds-cht-wcove.rst @@ -0,0 +1,38 @@ +.. SPDX-License-Identifier: GPL-2.0 + +=========================================================== +Kernel driver for Intel Cherry Trail Whiskey Cove PMIC LEDs +=========================================================== + +/sys/class/leds//hw_pattern +-------------------------------- + +Specify a hardware pattern for the Whiskey Cove PMIC LEDs. + +The only supported pattern is hardware breathing mode:: + + "0 2000 1 2000" + + ^ + | + Max-| --- + | / \ + | / \ + | / \ / + | / \ / + Min-|- --- + | + 0------2------4--> time (sec) + +The rise and fall times must be the same value. +Supported values are 2000, 1000, 500 and 250 for +breathing frequencies of 1/4, 1/2, 1 and 2 Hz. + +The set pattern only controls the timing. For max brightness the last +set brightness is used and the max brightness can be changed +while breathing by writing the brightness attribute. + +This is just like how blinking works in the LED subsystem, +for both sw and hw blinking the brightness can also be changed +while blinking. Breathing on this hw really is just a variant +mode of blinking. diff --git a/Documentation/leds/leds-class.rst b/Documentation/leds/leds-class.rst index cd155ead8703d18dc6ed7b7de8bb308ae120ab4b..5db620ed27aa2e6ad9599b9bcf87b337db79cc4c 100644 --- a/Documentation/leds/leds-class.rst +++ b/Documentation/leds/leds-class.rst @@ -169,6 +169,87 @@ Setting the brightness to zero with brightness_set() callback function should completely turn off the LED and cancel the previously programmed hardware blinking function, if any. +Hardware driven LEDs +==================== + +Some LEDs can be programmed to be driven by hardware. This is not +limited to blink but also to turn off or on autonomously. +To support this feature, a LED needs to implement various additional +ops and needs to declare specific support for the supported triggers. + +With hw control we refer to the LED driven by hardware. + +LED driver must define the following value to support hw control: + + - hw_control_trigger: + unique trigger name supported by the LED in hw control + mode. + +LED driver must implement the following API to support hw control: + - hw_control_is_supported: + check if the flags passed by the supported trigger can + be parsed and activate hw control on the LED. + + Return 0 if the passed flags mask is supported and + can be set with hw_control_set(). + + If the passed flags mask is not supported -EOPNOTSUPP + must be returned, the LED trigger will use software + fallback in this case. + + Return a negative error in case of any other error like + device not ready or timeouts. + + - hw_control_set: + activate hw control. LED driver will use the provided + flags passed from the supported trigger, parse them to + a set of mode and setup the LED to be driven by hardware + following the requested modes. + + Set LED_OFF via the brightness_set to deactivate hw control. + + Return 0 on success, a negative error number on failing to + apply flags. + + - hw_control_get: + get active modes from a LED already in hw control, parse + them and set in flags the current active flags for the + supported trigger. + + Return 0 on success, a negative error number on failing + parsing the initial mode. + Error from this function is NOT FATAL as the device may + be in a not supported initial state by the attached LED + trigger. + + - hw_control_get_device: + return the device associated with the LED driver in + hw control. A trigger might use this to match the + returned device from this function with a configured + device for the trigger as the source for blinking + events and correctly enable hw control. + (example a netdev trigger configured to blink for a + particular dev match the returned dev from get_device + to set hw control) + + Returns a pointer to a struct device or NULL if nothing + is currently attached. + +LED driver can activate additional modes by default to workaround the +impossibility of supporting each different mode on the supported trigger. +Examples are hardcoding the blink speed to a set interval, enable special +feature like bypassing blink if some requirements are not met. + +A trigger should first check if the hw control API are supported by the LED +driver and check if the trigger is supported to verify if hw control is possible, +use hw_control_is_supported to check if the flags are supported and only at +the end use hw_control_set to activate hw control. + +A trigger can use hw_control_get to check if a LED is already in hw control +and init their flags. + +When the LED is in hw control, no software blink is possible and doing so +will effectively disable hw control. Known Issues ============ diff --git a/Documentation/leds/well-known-leds.txt b/Documentation/leds/well-known-leds.txt index e9c30dc75884de16a1b7c2e1472c27472b9059a4..67b44704801f236bf66e40d9783b734dd50fd06a 100644 --- a/Documentation/leds/well-known-leds.txt +++ b/Documentation/leds/well-known-leds.txt @@ -58,6 +58,7 @@ LEDs on notebook body, indicating that sound input / output is muted. * System notification +Good: "rgb:status" Legacy: "status-led:{red,green,blue}" (Motorola Droid 4) Legacy: "lp5523:{r,g,b}" (Nokia N900) @@ -65,7 +66,7 @@ Phones usually have multi-color status LED. * Power management -Good: "platform:*:charging" (allwinner sun50i) +Good: "platform:*:charging" (allwinner sun50i, leds-cht-wcove) * Screen diff --git a/Documentation/maintainer/configure-git.rst b/Documentation/maintainer/configure-git.rst index 80ae5030a5902b312ede5bb00b19d7773c1f1b6e..ec0ddfb9cdd3c0f2e8f5beebca669981db360c37 100644 --- a/Documentation/maintainer/configure-git.rst +++ b/Documentation/maintainer/configure-git.rst @@ -56,7 +56,7 @@ by adding the following hook into your git: $ cat >.git/hooks/applypatch-msg <<'EOF' #!/bin/sh . git-sh-setup - perl -pi -e 's|^Message-Id:\s*]+)>?$|Link: https://lore.kernel.org/r/$1|g;' "$1" + perl -pi -e 's|^Message-I[dD]:\s*]+)>?$|Link: https://lore.kernel.org/r/$1|g;' "$1" test -x "$GIT_DIR/hooks/commit-msg" && exec "$GIT_DIR/hooks/commit-msg" ${1+"$@"} : diff --git a/Documentation/misc-devices/index.rst b/Documentation/misc-devices/index.rst index 756be15a49a416d30ec4632a17c0af8e0077dbf0..ecc40fbbcfb8eb63cde4c477d63eeccc6a8c847a 100644 --- a/Documentation/misc-devices/index.rst +++ b/Documentation/misc-devices/index.rst @@ -28,5 +28,6 @@ fit into other categories. oxsemi-tornado pci-endpoint-test spear-pcie-gadget + tps6594-pfsm uacce xilinx_sdfec diff --git a/Documentation/misc-devices/tps6594-pfsm.rst b/Documentation/misc-devices/tps6594-pfsm.rst new file mode 100644 index 0000000000000000000000000000000000000000..4ada37ccdcbae8497f5b30fac82ddd51c4ad690d --- /dev/null +++ b/Documentation/misc-devices/tps6594-pfsm.rst @@ -0,0 +1,87 @@ +.. SPDX-License-Identifier: GPL-2.0 + +===================================== +Texas Instruments TPS6594 PFSM driver +===================================== + +Author: Julien Panis (jpanis@baylibre.com) + +Overview +======== + +Strictly speaking, PFSM (Pre-configurable Finite State Machine) is not +hardware. It is a piece of code. + +The TPS6594 PMIC (Power Management IC) integrates a state machine which +manages operational modes. Depending on the current operational mode, +some voltage domains remain energized while others can be off. + +The PFSM driver can be used to trigger transitions between configured +states. It also provides R/W access to the device registers. + +Supported chips +--------------- + +- tps6594-q1 +- tps6593-q1 +- lp8764-q1 + +Driver location +=============== + +drivers/misc/tps6594-pfsm.c + +Driver type definitions +======================= + +include/uapi/linux/tps6594_pfsm.h + +Driver IOCTLs +============= + +:c:macro::`PMIC_GOTO_STANDBY` +All device resources are powered down. The processor is off, and +no voltage domains are energized. + +:c:macro::`PMIC_GOTO_LP_STANDBY` +The digital and analog functions of the PMIC, which are not +required to be always-on, are turned off (low-power). + +:c:macro::`PMIC_UPDATE_PGM` +Triggers a firmware update. + +:c:macro::`PMIC_SET_ACTIVE_STATE` +One of the operational modes. +The PMICs are fully functional and supply power to all PDN loads. +All voltage domains are energized in both MCU and Main processor +sections. + +:c:macro::`PMIC_SET_MCU_ONLY_STATE` +One of the operational modes. +Only the power resources assigned to the MCU Safety Island are on. + +:c:macro::`PMIC_SET_RETENTION_STATE` +One of the operational modes. +Depending on the triggers set, some DDR/GPIO voltage domains can +remain energized, while all other domains are off to minimize +total system power. + +Driver usage +============ + +See available PFSMs:: + + # ls /dev/pfsm* + +Dump the registers of pages 0 and 1:: + + # hexdump -C /dev/pfsm-0-0x48 + +See PFSM events:: + + # cat /proc/interrupts + +Userspace code example +---------------------- + +samples/pfsm/pfsm-wakeup.c diff --git a/Documentation/mm/damon/design.rst b/Documentation/mm/damon/design.rst index 0cff6fac6b7e8257ddbc7f0ad7b7216baa6d98a7..4bfdf1d30c4aed892da575b89a85be0c3cae52b3 100644 --- a/Documentation/mm/damon/design.rst +++ b/Documentation/mm/damon/design.rst @@ -4,31 +4,55 @@ Design ====== -Configurable Layers -=================== - -DAMON provides data access monitoring functionality while making the accuracy -and the overhead controllable. The fundamental access monitorings require -primitives that dependent on and optimized for the target address space. On -the other hand, the accuracy and overhead tradeoff mechanism, which is the core -of DAMON, is in the pure logic space. DAMON separates the two parts in -different layers and defines its interface to allow various low level -primitives implementations configurable with the core logic. We call the low -level primitives implementations monitoring operations. - -Due to this separated design and the configurable interface, users can extend -DAMON for any address space by configuring the core logics with appropriate -monitoring operations. If appropriate one is not provided, users can implement -the operations on their own. + +Overall Architecture +==================== + +DAMON subsystem is configured with three layers including + +- Operations Set: Implements fundamental operations for DAMON that depends on + the given monitoring target address-space and available set of + software/hardware primitives, +- Core: Implements core logics including monitoring overhead/accurach control + and access-aware system operations on top of the operations set layer, and +- Modules: Implements kernel modules for various purposes that provides + interfaces for the user space, on top of the core layer. + + +Configurable Operations Set +--------------------------- + +For data access monitoring and additional low level work, DAMON needs a set of +implementations for specific operations that are dependent on and optimized for +the given target address space. On the other hand, the accuracy and overhead +tradeoff mechanism, which is the core logic of DAMON, is in the pure logic +space. DAMON separates the two parts in different layers, namely DAMON +Operations Set and DAMON Core Logics Layers, respectively. It further defines +the interface between the layers to allow various operations sets to be +configured with the core logic. + +Due to this design, users can extend DAMON for any address space by configuring +the core logic to use the appropriate operations set. If any appropriate set +is unavailable, users can implement one on their own. For example, physical memory, virtual memory, swap space, those for specific processes, NUMA nodes, files, and backing memory devices would be supportable. -Also, if some architectures or devices support special optimized access check -primitives, those will be easily configurable. +Also, if some architectures or devices supporting special optimized access +check primitives, those will be easily configurable. -Reference Implementations of Address Space Specific Monitoring Operations -========================================================================= +Programmable Modules +-------------------- + +Core layer of DAMON is implemented as a framework, and exposes its application +programming interface to all kernel space components such as subsystems and +modules. For common use cases of DAMON, DAMON subsystem provides kernel +modules that built on top of the core layer using the API, which can be easily +used by the user space end users. + + +Operations Set Layer +==================== The monitoring operations are defined in two parts: @@ -90,8 +114,12 @@ conflict with the reclaim logic using ``PG_idle`` and ``PG_young`` page flags, as Idle page tracking does. -Address Space Independent Core Mechanisms -========================================= +Core Logics +=========== + + +Monitoring +---------- Below four sections describe each of the DAMON core mechanisms and the five monitoring attributes, ``sampling interval``, ``aggregation interval``, @@ -100,7 +128,7 @@ regions``. Access Frequency Monitoring ---------------------------- +~~~~~~~~~~~~~~~~~~~~~~~~~~~ The output of DAMON says what pages are how frequently accessed for a given duration. The resolution of the access frequency is controlled by setting @@ -127,7 +155,7 @@ size of the target workload grows. Region Based Sampling ---------------------- +~~~~~~~~~~~~~~~~~~~~~ To avoid the unbounded increase of the overhead, DAMON groups adjacent pages that assumed to have the same access frequencies into a region. As long as the @@ -144,7 +172,7 @@ assumption is not guaranteed. Adaptive Regions Adjustment ---------------------------- +~~~~~~~~~~~~~~~~~~~~~~~~~~~ Even somehow the initial monitoring target regions are well constructed to fulfill the assumption (pages in same region have similar access frequencies), @@ -162,8 +190,22 @@ In this way, DAMON provides its best-effort quality and minimal overhead while keeping the bounds users set for their trade-off. +Age Tracking +~~~~~~~~~~~~ + +By analyzing the monitoring results, users can also find how long the current +access pattern of a region has maintained. That could be used for good +understanding of the access pattern. For example, page placement algorithm +utilizing both the frequency and the recency could be implemented using that. +To make such access pattern maintained period analysis easier, DAMON maintains +yet another counter called ``age`` in each region. For each ``aggregation +interval``, DAMON checks if the region's size and access frequency +(``nr_accesses``) has significantly changed. If so, the counter is reset to +zero. Otherwise, the counter is increased. + + Dynamic Target Space Updates Handling -------------------------------------- +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The monitoring target address range could dynamically changed. For example, virtual memory could be dynamically mapped and unmapped. Physical memory could @@ -174,3 +216,246 @@ monitoring operations to check dynamic changes including memory mapping changes and applies it to monitoring operations-related data structures such as the abstracted monitoring target memory area only for each of a user-specified time interval (``update interval``). + + +.. _damon_design_damos: + +Operation Schemes +----------------- + +One common purpose of data access monitoring is access-aware system efficiency +optimizations. For example, + + paging out memory regions that are not accessed for more than two minutes + +or + + using THP for memory regions that are larger than 2 MiB and showing a high + access frequency for more than one minute. + +One straightforward approach for such schemes would be profile-guided +optimizations. That is, getting data access monitoring results of the +workloads or the system using DAMON, finding memory regions of special +characteristics by profiling the monitoring results, and making system +operation changes for the regions. The changes could be made by modifying or +providing advice to the software (the application and/or the kernel), or +reconfiguring the hardware. Both offline and online approaches could be +available. + +Among those, providing advice to the kernel at runtime would be flexible and +effective, and therefore widely be used. However, implementing such schemes +could impose unnecessary redundancy and inefficiency. The profiling could be +redundant if the type of interest is common. Exchanging the information +including monitoring results and operation advice between kernel and user +spaces could be inefficient. + +To allow users to reduce such redundancy and inefficiencies by offloading the +works, DAMON provides a feature called Data Access Monitoring-based Operation +Schemes (DAMOS). It lets users specify their desired schemes at a high +level. For such specifications, DAMON starts monitoring, finds regions having +the access pattern of interest, and applies the user-desired operation actions +to the regions as soon as found. + + +.. _damon_design_damos_action: + +Operation Action +~~~~~~~~~~~~~~~~ + +The management action that the users desire to apply to the regions of their +interest. For example, paging out, prioritizing for next reclamation victim +selection, advising ``khugepaged`` to collapse or split, or doing nothing but +collecting statistics of the regions. + +The list of supported actions is defined in DAMOS, but the implementation of +each action is in the DAMON operations set layer because the implementation +normally depends on the monitoring target address space. For example, the code +for paging specific virtual address ranges out would be different from that for +physical address ranges. And the monitoring operations implementation sets are +not mandated to support all actions of the list. Hence, the availability of +specific DAMOS action depends on what operations set is selected to be used +together. + +Applying an action to a region is considered as changing the region's +characteristics. Hence, DAMOS resets the age of regions when an action is +applied to those. + + +.. _damon_design_damos_access_pattern: + +Target Access Pattern +~~~~~~~~~~~~~~~~~~~~~ + +The access pattern of the schemes' interest. The patterns are constructed with +the properties that DAMON's monitoring results provide, specifically the size, +the access frequency, and the age. Users can describe their access pattern of +interest by setting minimum and maximum values of the three properties. If a +region's three properties are in the ranges, DAMOS classifies it as one of the +regions that the scheme is having an interest in. + + +.. _damon_design_damos_quotas: + +Quotas +~~~~~~ + +DAMOS upper-bound overhead control feature. DAMOS could incur high overhead if +the target access pattern is not properly tuned. For example, if a huge memory +region having the access pattern of interest is found, applying the scheme's +action to all pages of the huge region could consume unacceptably large system +resources. Preventing such issues by tuning the access pattern could be +challenging, especially if the access patterns of the workloads are highly +dynamic. + +To mitigate that situation, DAMOS provides an upper-bound overhead control +feature called quotas. It lets users specify an upper limit of time that DAMOS +can use for applying the action, and/or a maximum bytes of memory regions that +the action can be applied within a user-specified time duration. + + +.. _damon_design_damos_quotas_prioritization: + +Prioritization +^^^^^^^^^^^^^^ + +A mechanism for making a good decision under the quotas. When the action +cannot be applied to all regions of interest due to the quotas, DAMOS +prioritizes regions and applies the action to only regions having high enough +priorities so that it will not exceed the quotas. + +The prioritization mechanism should be different for each action. For example, +rarely accessed (colder) memory regions would be prioritized for page-out +scheme action. In contrast, the colder regions would be deprioritized for huge +page collapse scheme action. Hence, the prioritization mechanisms for each +action are implemented in each DAMON operations set, together with the actions. + +Though the implementation is up to the DAMON operations set, it would be common +to calculate the priority using the access pattern properties of the regions. +Some users would want the mechanisms to be personalized for their specific +case. For example, some users would want the mechanism to weigh the recency +(``age``) more than the access frequency (``nr_accesses``). DAMOS allows users +to specify the weight of each access pattern property and passes the +information to the underlying mechanism. Nevertheless, how and even whether +the weight will be respected are up to the underlying prioritization mechanism +implementation. + + +.. _damon_design_damos_watermarks: + +Watermarks +~~~~~~~~~~ + +Conditional DAMOS (de)activation automation. Users might want DAMOS to run +only under certain situations. For example, when a sufficient amount of free +memory is guaranteed, running a scheme for proactive reclamation would only +consume unnecessary system resources. To avoid such consumption, the user would +need to manually monitor some metrics such as free memory ratio, and turn +DAMON/DAMOS on or off. + +DAMOS allows users to offload such works using three watermarks. It allows the +users to configure the metric of their interest, and three watermark values, +namely high, middle, and low. If the value of the metric becomes above the +high watermark or below the low watermark, the scheme is deactivated. If the +metric becomes below the mid watermark but above the low watermark, the scheme +is activated. If all schemes are deactivated by the watermarks, the monitoring +is also deactivated. In this case, the DAMON worker thread only periodically +checks the watermarks and therefore incurs nearly zero overhead. + + +.. _damon_design_damos_filters: + +Filters +~~~~~~~ + +Non-access pattern-based target memory regions filtering. If users run +self-written programs or have good profiling tools, they could know something +more than the kernel, such as future access patterns or some special +requirements for specific types of memory. For example, some users may know +only anonymous pages can impact their program's performance. They can also +have a list of latency-critical processes. + +To let users optimize DAMOS schemes with such special knowledge, DAMOS provides +a feature called DAMOS filters. The feature allows users to set an arbitrary +number of filters for each scheme. Each filter specifies the type of target +memory, and whether it should exclude the memory of the type (filter-out), or +all except the memory of the type (filter-in). + +As of this writing, anonymous page type and memory cgroup type are supported by +the feature. Some filter target types can require additional arguments. For +example, the memory cgroup filter type asks users to specify the file path of +the memory cgroup for the filter. Hence, users can apply specific schemes to +only anonymous pages, non-anonymous pages, pages of specific cgroups, all pages +excluding those of specific cgroups, and any combination of those. + + +Application Programming Interface +--------------------------------- + +The programming interface for kernel space data access-aware applications. +DAMON is a framework, so it does nothing by itself. Instead, it only helps +other kernel components such as subsystems and modules building their data +access-aware applications using DAMON's core features. For this, DAMON exposes +its all features to other kernel components via its application programming +interface, namely ``include/linux/damon.h``. Please refer to the API +:doc:`document ` for details of the interface. + + +Modules +======= + +Because the core of DAMON is a framework for kernel components, it doesn't +provide any direct interface for the user space. Such interfaces should be +implemented by each DAMON API user kernel components, instead. DAMON subsystem +itself implements such DAMON API user modules, which are supposed to be used +for general purpose DAMON control and special purpose data access-aware system +operations, and provides stable application binary interfaces (ABI) for the +user space. The user space can build their efficient data access-aware +applications using the interfaces. + + +General Purpose User Interface Modules +-------------------------------------- + +DAMON modules that provide user space ABIs for general purpose DAMON usage in +runtime. + +DAMON user interface modules, namely 'DAMON sysfs interface' and 'DAMON debugfs +interface' are DAMON API user kernel modules that provide ABIs to the +user-space. Please note that DAMON debugfs interface is currently deprecated. + +Like many other ABIs, the modules create files on sysfs and debugfs, allow +users to specify their requests to and get the answers from DAMON by writing to +and reading from the files. As a response to such I/O, DAMON user interface +modules control DAMON and retrieve the results as user requested via the DAMON +API, and return the results to the user-space. + +The ABIs are designed to be used for user space applications development, +rather than human beings' fingers. Human users are recommended to use such +user space tools. One such Python-written user space tool is available at +Github (https://github.com/awslabs/damo), Pypi +(https://pypistats.org/packages/damo), and Fedora +(https://packages.fedoraproject.org/pkgs/python-damo/damo/). + +Please refer to the ABI :doc:`document ` for +details of the interfaces. + + +Special-Purpose Access-aware Kernel Modules +------------------------------------------- + +DAMON modules that provide user space ABI for specific purpose DAMON usage. + +DAMON sysfs/debugfs user interfaces are for full control of all DAMON features +in runtime. For each special-purpose system-wide data access-aware system +operations such as proactive reclamation or LRU lists balancing, the interfaces +could be simplified by removing unnecessary knobs for the specific purpose, and +extended for boot-time and even compile time control. Default values of DAMON +control parameters for the usage would also need to be optimized for the +purpose. + +To support such cases, yet more DAMON API user kernel modules that provide more +simple and optimized user space interfaces are available. Currently, two +modules for proactive reclamation and LRU lists manipulation are provided. For +more detail, please read the usage documents for those +(:doc:`/admin-guide/mm/damon/reclaim` and +:doc:`/admin-guide/mm/damon/lru_sort`). diff --git a/Documentation/mm/damon/faq.rst b/Documentation/mm/damon/faq.rst index dde7e2414ee60ab45d153b1fa3a9f677244b5b48..3279dc7a8211ff637585dca68d8622cd4b0fba69 100644 --- a/Documentation/mm/damon/faq.rst +++ b/Documentation/mm/damon/faq.rst @@ -4,29 +4,6 @@ Frequently Asked Questions ========================== -Why a new subsystem, instead of extending perf or other user space tools? -========================================================================= - -First, because it needs to be lightweight as much as possible so that it can be -used online, any unnecessary overhead such as kernel - user space context -switching cost should be avoided. Second, DAMON aims to be used by other -programs including the kernel. Therefore, having a dependency on specific -tools like perf is not desirable. These are the two biggest reasons why DAMON -is implemented in the kernel space. - - -Can 'idle pages tracking' or 'perf mem' substitute DAMON? -========================================================= - -Idle page tracking is a low level primitive for access check of the physical -address space. 'perf mem' is similar, though it can use sampling to minimize -the overhead. On the other hand, DAMON is a higher-level framework for the -monitoring of various address spaces. It is focused on memory management -optimization and provides sophisticated accuracy/overhead handling mechanisms. -Therefore, 'idle pages tracking' and 'perf mem' could provide a subset of -DAMON's output, but cannot substitute DAMON. - - Does DAMON support virtual memory only? ======================================= diff --git a/Documentation/mm/damon/maintainer-profile.rst b/Documentation/mm/damon/maintainer-profile.rst index 24a202f03de826ac07e62e8da4f9f8e393f7b56e..a84c14e5905307d50817733bc9e0ab3ef37b904f 100644 --- a/Documentation/mm/damon/maintainer-profile.rst +++ b/Documentation/mm/damon/maintainer-profile.rst @@ -3,7 +3,7 @@ DAMON Maintainer Entry Profile ============================== -The DAMON subsystem covers the files that listed in 'DATA ACCESS MONITOR' +The DAMON subsystem covers the files that are listed in 'DATA ACCESS MONITOR' section of 'MAINTAINERS' file. The mailing lists for the subsystem are damon@lists.linux.dev and @@ -15,7 +15,7 @@ SCM Trees There are multiple Linux trees for DAMON development. Patches under development or testing are queued in damon/next [2]_ by the DAMON maintainer. -Suffieicntly reviewed patches will be queued in mm-unstable [1]_ by the memory +Sufficiently reviewed patches will be queued in mm-unstable [1]_ by the memory management subsystem maintainer. After more sufficient tests, the patches will be queued in mm-stable [3]_ , and finally pull-requested to the mainline by the memory management subsystem maintainer. diff --git a/Documentation/mm/page_migration.rst b/Documentation/mm/page_migration.rst index 313dce18893e918e6bd45400ae477051c48dbdb2..e35af7805be54a6f43f9f7d2047b4ec6dafcb0e8 100644 --- a/Documentation/mm/page_migration.rst +++ b/Documentation/mm/page_migration.rst @@ -73,14 +73,13 @@ In kernel use of migrate_pages() It also prevents the swapper or other scans from encountering the page. -2. We need to have a function of type new_page_t that can be +2. We need to have a function of type new_folio_t that can be passed to migrate_pages(). This function should figure out - how to allocate the correct new page given the old page. + how to allocate the correct new folio given the old folio. 3. The migrate_pages() function is called which attempts to do the migration. It will call the function to allocate - the new page for each page that is considered for - moving. + the new folio for each folio that is considered for moving. How migrate_pages() works ========================= diff --git a/Documentation/mm/page_tables.rst b/Documentation/mm/page_tables.rst index 96939571d7bc1f6aab670434cc170e71f45e47fc..7840c1891751e663c6920f974aceb5babaf0197c 100644 --- a/Documentation/mm/page_tables.rst +++ b/Documentation/mm/page_tables.rst @@ -3,3 +3,152 @@ =========== Page Tables =========== + +Paged virtual memory was invented along with virtual memory as a concept in +1962 on the Ferranti Atlas Computer which was the first computer with paged +virtual memory. The feature migrated to newer computers and became a de facto +feature of all Unix-like systems as time went by. In 1985 the feature was +included in the Intel 80386, which was the CPU Linux 1.0 was developed on. + +Page tables map virtual addresses as seen by the CPU into physical addresses +as seen on the external memory bus. + +Linux defines page tables as a hierarchy which is currently five levels in +height. The architecture code for each supported architecture will then +map this to the restrictions of the hardware. + +The physical address corresponding to the virtual address is often referenced +by the underlying physical page frame. The **page frame number** or **pfn** +is the physical address of the page (as seen on the external memory bus) +divided by `PAGE_SIZE`. + +Physical memory address 0 will be *pfn 0* and the highest pfn will be +the last page of physical memory the external address bus of the CPU can +address. + +With a page granularity of 4KB and a address range of 32 bits, pfn 0 is at +address 0x00000000, pfn 1 is at address 0x00001000, pfn 2 is at 0x00002000 +and so on until we reach pfn 0xfffff at 0xfffff000. With 16KB pages pfs are +at 0x00004000, 0x00008000 ... 0xffffc000 and pfn goes from 0 to 0x3fffff. + +As you can see, with 4KB pages the page base address uses bits 12-31 of the +address, and this is why `PAGE_SHIFT` in this case is defined as 12 and +`PAGE_SIZE` is usually defined in terms of the page shift as `(1 << PAGE_SHIFT)` + +Over time a deeper hierarchy has been developed in response to increasing memory +sizes. When Linux was created, 4KB pages and a single page table called +`swapper_pg_dir` with 1024 entries was used, covering 4MB which coincided with +the fact that Torvald's first computer had 4MB of physical memory. Entries in +this single table were referred to as *PTE*:s - page table entries. + +The software page table hierarchy reflects the fact that page table hardware has +become hierarchical and that in turn is done to save page table memory and +speed up mapping. + +One could of course imagine a single, linear page table with enormous amounts +of entries, breaking down the whole memory into single pages. Such a page table +would be very sparse, because large portions of the virtual memory usually +remains unused. By using hierarchical page tables large holes in the virtual +address space does not waste valuable page table memory, because it will suffice +to mark large areas as unmapped at a higher level in the page table hierarchy. + +Additionally, on modern CPUs, a higher level page table entry can point directly +to a physical memory range, which allows mapping a contiguous range of several +megabytes or even gigabytes in a single high-level page table entry, taking +shortcuts in mapping virtual memory to physical memory: there is no need to +traverse deeper in the hierarchy when you find a large mapped range like this. + +The page table hierarchy has now developed into this:: + + +-----+ + | PGD | + +-----+ + | + | +-----+ + +-->| P4D | + +-----+ + | + | +-----+ + +-->| PUD | + +-----+ + | + | +-----+ + +-->| PMD | + +-----+ + | + | +-----+ + +-->| PTE | + +-----+ + + +Symbols on the different levels of the page table hierarchy have the following +meaning beginning from the bottom: + +- **pte**, `pte_t`, `pteval_t` = **Page Table Entry** - mentioned earlier. + The *pte* is an array of `PTRS_PER_PTE` elements of the `pteval_t` type, each + mapping a single page of virtual memory to a single page of physical memory. + The architecture defines the size and contents of `pteval_t`. + + A typical example is that the `pteval_t` is a 32- or 64-bit value with the + upper bits being a **pfn** (page frame number), and the lower bits being some + architecture-specific bits such as memory protection. + + The **entry** part of the name is a bit confusing because while in Linux 1.0 + this did refer to a single page table entry in the single top level page + table, it was retrofitted to be an array of mapping elements when two-level + page tables were first introduced, so the *pte* is the lowermost page + *table*, not a page table *entry*. + +- **pmd**, `pmd_t`, `pmdval_t` = **Page Middle Directory**, the hierarchy right + above the *pte*, with `PTRS_PER_PMD` references to the *pte*:s. + +- **pud**, `pud_t`, `pudval_t` = **Page Upper Directory** was introduced after + the other levels to handle 4-level page tables. It is potentially unused, + or *folded* as we will discuss later. + +- **p4d**, `p4d_t`, `p4dval_t` = **Page Level 4 Directory** was introduced to + handle 5-level page tables after the *pud* was introduced. Now it was clear + that we needed to replace *pgd*, *pmd*, *pud* etc with a figure indicating the + directory level and that we cannot go on with ad hoc names any more. This + is only used on systems which actually have 5 levels of page tables, otherwise + it is folded. + +- **pgd**, `pgd_t`, `pgdval_t` = **Page Global Directory** - the Linux kernel + main page table handling the PGD for the kernel memory is still found in + `swapper_pg_dir`, but each userspace process in the system also has its own + memory context and thus its own *pgd*, found in `struct mm_struct` which + in turn is referenced to in each `struct task_struct`. So tasks have memory + context in the form of a `struct mm_struct` and this in turn has a + `struct pgt_t *pgd` pointer to the corresponding page global directory. + +To repeat: each level in the page table hierarchy is a *array of pointers*, so +the **pgd** contains `PTRS_PER_PGD` pointers to the next level below, **p4d** +contains `PTRS_PER_P4D` pointers to **pud** items and so on. The number of +pointers on each level is architecture-defined.:: + + PMD + --> +-----+ PTE + | ptr |-------> +-----+ + | ptr |- | ptr |-------> PAGE + | ptr | \ | ptr | + | ptr | \ ... + | ... | \ + | ptr | \ PTE + +-----+ +----> +-----+ + | ptr |-------> PAGE + | ptr | + ... + + +Page Table Folding +================== + +If the architecture does not use all the page table levels, they can be *folded* +which means skipped, and all operations performed on page tables will be +compile-time augmented to just skip a level when accessing the next lower +level. + +Page table handling code that wishes to be architecture-neutral, such as the +virtual memory manager, will need to be written so that it traverses all of the +currently five levels. This style should also be preferred for +architecture-specific code, so as to be robust to future changes. diff --git a/Documentation/mm/split_page_table_lock.rst b/Documentation/mm/split_page_table_lock.rst index 50ee0dfc95be6ef3c298d7ddc1544870546f158e..a834fad9de12096769229d43d61118875781e24b 100644 --- a/Documentation/mm/split_page_table_lock.rst +++ b/Documentation/mm/split_page_table_lock.rst @@ -14,15 +14,20 @@ tables. Access to higher level tables protected by mm->page_table_lock. There are helpers to lock/unlock a table and other accessor functions: - pte_offset_map_lock() - maps pte and takes PTE table lock, returns pointer to the taken - lock; + maps PTE and takes PTE table lock, returns pointer to PTE with + pointer to its PTE table lock, or returns NULL if no PTE table; + - pte_offset_map_nolock() + maps PTE, returns pointer to PTE with pointer to its PTE table + lock (not taken), or returns NULL if no PTE table; + - pte_offset_map() + maps PTE, returns pointer to PTE, or returns NULL if no PTE table; + - pte_unmap() + unmaps PTE table; - pte_unmap_unlock() unlocks and unmaps PTE table; - pte_alloc_map_lock() - allocates PTE table if needed and take the lock, returns pointer - to taken lock or NULL if allocation failed; - - pte_lockptr() - returns pointer to PTE table lock; + allocates PTE table if needed and takes its lock, returns pointer to + PTE with pointer to its lock, or returns NULL if allocation failed; - pmd_lock() takes PMD table lock, returns pointer to taken lock; - pmd_lockptr() diff --git a/Documentation/netlink/genetlink-c.yaml b/Documentation/netlink/genetlink-c.yaml index 8e8c17b0a6c65421d2821071b3545c761be9dae7..57d1c1c4918f2d25da8db5a7ce86e122fbee6c7a 100644 --- a/Documentation/netlink/genetlink-c.yaml +++ b/Documentation/netlink/genetlink-c.yaml @@ -195,6 +195,16 @@ properties: description: Max length for a string or a binary attribute. $ref: '#/$defs/len-or-define' sub-type: *attr-type + display-hint: &display-hint + description: | + Optional format indicator that is intended only for choosing + the right formatting mechanism when displaying values of this + type. + enum: [ hex, mac, fddi, ipv4, ipv6, uuid ] + # Start genetlink-c + name-prefix: + type: string + # End genetlink-c # Make sure name-prefix does not appear in subsets (subsets inherit naming) dependencies: diff --git a/Documentation/netlink/genetlink-legacy.yaml b/Documentation/netlink/genetlink-legacy.yaml index b33541a51d6bb440a5bb642cb4f0b87782d485cc..43b769c98fb277b8c4cf7e0c7fd6eb01bc94c828 100644 --- a/Documentation/netlink/genetlink-legacy.yaml +++ b/Documentation/netlink/genetlink-legacy.yaml @@ -119,9 +119,24 @@ properties: name: type: string type: - enum: [ u8, u16, u32, u64, s8, s16, s32, s64, string ] + description: The netlink attribute type + enum: [ u8, u16, u32, u64, s8, s16, s32, s64, string, binary ] len: $ref: '#/$defs/len-or-define' + byte-order: + enum: [ little-endian, big-endian ] + doc: + description: Documentation for the struct member attribute. + type: string + enum: + description: Name of the enum type used for the attribute. + type: string + display-hint: &display-hint + description: | + Optional format indicator that is intended only for choosing + the right formatting mechanism when displaying values of this + type. + enum: [ hex, mac, fddi, ipv4, ipv6, uuid ] # End genetlink-legacy attribute-sets: @@ -171,6 +186,7 @@ properties: name: type: string type: &attr-type + description: The netlink attribute type enum: [ unused, pad, flag, binary, u8, u16, u32, u64, s32, s64, string, nest, array-nest, nest-type-value ] doc: @@ -218,6 +234,11 @@ properties: description: Max length for a string or a binary attribute. $ref: '#/$defs/len-or-define' sub-type: *attr-type + display-hint: *display-hint + # Start genetlink-c + name-prefix: + type: string + # End genetlink-c # Start genetlink-legacy struct: description: Name of the struct type used for the attribute. diff --git a/Documentation/netlink/genetlink.yaml b/Documentation/netlink/genetlink.yaml index d8b2cdeba058f588d910018c8fe050f877e1342f..1cbb448d2f1c34cb7238bf9cddf1173ee504ee6f 100644 --- a/Documentation/netlink/genetlink.yaml +++ b/Documentation/netlink/genetlink.yaml @@ -168,6 +168,12 @@ properties: description: Max length for a string or a binary attribute. $ref: '#/$defs/len-or-define' sub-type: *attr-type + display-hint: &display-hint + description: | + Optional format indicator that is intended only for choosing + the right formatting mechanism when displaying values of this + type. + enum: [ hex, mac, fddi, ipv4, ipv6, uuid ] # Make sure name-prefix does not appear in subsets (subsets inherit naming) dependencies: diff --git a/Documentation/netlink/specs/devlink.yaml b/Documentation/netlink/specs/devlink.yaml index 90641668232e3525ab5f2b342abebc7ddaa5595c..5d46ca96697923dfb99d41b5fd2bd750448ef07c 100644 --- a/Documentation/netlink/specs/devlink.yaml +++ b/Documentation/netlink/specs/devlink.yaml @@ -9,6 +9,7 @@ doc: Partial family for Devlink. attribute-sets: - name: devlink + name-prefix: devlink-attr- attributes: - name: bus-name @@ -95,10 +96,12 @@ attribute-sets: - name: reload-action-info type: nest + multi-attr: true nested-attributes: dl-reload-act-info - name: reload-action-stats type: nest + multi-attr: true nested-attributes: dl-reload-act-stats - name: dl-dev-stats @@ -196,3 +199,8 @@ operations: attributes: - bus-name - dev-name + - info-driver-name + - info-serial-number + - info-version-fixed + - info-version-running + - info-version-stored diff --git a/Documentation/netlink/specs/ethtool.yaml b/Documentation/netlink/specs/ethtool.yaml index 4846345bade4604d268a5ce5186378f4312d3dac..837b565577ca6a16d69e8e51ba19ef00f5d7c6d7 100644 --- a/Documentation/netlink/specs/ethtool.yaml +++ b/Documentation/netlink/specs/ethtool.yaml @@ -9,8 +9,13 @@ doc: Partial family for Ethtool Netlink. definitions: - name: udp-tunnel-type + enum-name: type: enum entries: [ vxlan, geneve, vxlan-gpe ] + - + name: stringset + type: enum + entries: [] attribute-sets: - @@ -497,7 +502,7 @@ attribute-sets: attributes: - name: pad - type: u32 + type: pad - name: tx-frames type: u64 @@ -577,7 +582,7 @@ attribute-sets: name: phc-index type: u32 - - name: cable-test-ntf-nest-result + name: cable-result attributes: - name: pair @@ -586,7 +591,7 @@ attribute-sets: name: code type: u8 - - name: cable-test-ntf-nest-fault-length + name: cable-fault-length attributes: - name: pair @@ -595,18 +600,25 @@ attribute-sets: name: cm type: u32 - - name: cable-test-ntf-nest + name: cable-nest attributes: - name: result type: nest - nested-attributes: cable-test-ntf-nest-result + nested-attributes: cable-result - name: fault-length type: nest - nested-attributes: cable-test-ntf-nest-fault-length + nested-attributes: cable-fault-length - name: cable-test + attributes: + - + name: header + type: nest + nested-attributes: header + - + name: cable-test-ntf attributes: - name: header @@ -618,7 +630,7 @@ attribute-sets: - name: nest type: nest - nested-attributes: cable-test-ntf-nest + nested-attributes: cable-nest - name: cable-test-tdr-cfg attributes: @@ -632,8 +644,22 @@ attribute-sets: name: step type: u32 - - name: pari + name: pair type: u8 + - + name: cable-test-tdr-ntf + attributes: + - + name: header + type: nest + nested-attributes: header + - + name: status + type: u8 + - + name: nest + type: nest + nested-attributes: cable-nest - name: cable-test-tdr attributes: @@ -646,7 +672,7 @@ attribute-sets: type: nest nested-attributes: cable-test-tdr-cfg - - name: tunnel-info-udp-entry + name: tunnel-udp-entry attributes: - name: port @@ -657,7 +683,7 @@ attribute-sets: type: u32 enum: udp-tunnel-type - - name: tunnel-info-udp-table + name: tunnel-udp-table attributes: - name: size @@ -667,9 +693,17 @@ attribute-sets: type: nest nested-attributes: bitset - - name: udp-ports + name: entry type: nest - nested-attributes: tunnel-info-udp-entry + multi-attr: true + nested-attributes: tunnel-udp-entry + - + name: tunnel-udp + attributes: + - + name: table + type: nest + nested-attributes: tunnel-udp-table - name: tunnel-info attributes: @@ -680,13 +714,13 @@ attribute-sets: - name: udp-ports type: nest - nested-attributes: tunnel-info-udp-table + nested-attributes: tunnel-udp - name: fec-stat attributes: - name: pad - type: u8 + type: pad - name: corrected type: binary @@ -750,7 +784,7 @@ attribute-sets: attributes: - name: pad - type: u32 + type: pad - name: id type: u32 @@ -759,16 +793,29 @@ attribute-sets: type: u32 - name: stat - type: nest - nested-attributes: u64 + type: u64 + type-value: [ id ] - name: hist-rx type: nest - nested-attributes: u64 + nested-attributes: stats-grp-hist - name: hist-tx type: nest - nested-attributes: u64 + nested-attributes: stats-grp-hist + - + name: hist-bkt-low + type: u32 + - + name: hist-bkt-hi + type: u32 + - + name: hist-val + type: u64 + - + name: stats-grp-hist + subset-of: stats-grp + attributes: - name: hist-bkt-low type: u32 @@ -783,7 +830,7 @@ attribute-sets: attributes: - name: pad - type: u32 + type: pad - name: header type: nest @@ -836,12 +883,15 @@ attribute-sets: - name: admin-state type: u32 + name-prefix: ethtool-a-podl-pse- - name: admin-control type: u32 + name-prefix: ethtool-a-podl-pse- - name: pw-d-status type: u32 + name-prefix: ethtool-a-podl-pse- - name: rss attributes: @@ -895,6 +945,7 @@ attribute-sets: operations: enum-model: directional + name-prefix: ethtool-msg- list: - name: strset-get @@ -1348,10 +1399,16 @@ operations: request: attributes: - header - reply: - attributes: - - header - - cable-test-ntf-nest + - + name: cable-test-ntf + doc: Cable test notification. + + attribute-set: cable-test-ntf + + event: + attributes: + - header + - status - name: cable-test-tdr-act doc: Cable test TDR. @@ -1362,10 +1419,17 @@ operations: request: attributes: - header - reply: - attributes: - - header - - cable-test-tdr-cfg + - + name: cable-test-tdr-ntf + doc: Cable test TDR notification. + + attribute-set: cable-test-tdr-ntf + + event: + attributes: + - header + - status + - nest - name: tunnel-info-get doc: Get tsinfo params. diff --git a/Documentation/netlink/specs/ovs_datapath.yaml b/Documentation/netlink/specs/ovs_datapath.yaml index 6d71db8c441638b43327f57216829419818cc0a1..f709c26c3e92d46aafb2163a4462b55ef95eba7c 100644 --- a/Documentation/netlink/specs/ovs_datapath.yaml +++ b/Documentation/netlink/specs/ovs_datapath.yaml @@ -3,6 +3,7 @@ name: ovs_datapath version: 2 protocol: genetlink-legacy +uapi-header: linux/openvswitch.h doc: OVS datapath configuration over generic netlink. @@ -18,6 +19,7 @@ definitions: - name: user-features type: flags + name-prefix: ovs-dp-f- entries: - name: unaligned @@ -33,35 +35,37 @@ definitions: doc: Allow per-cpu dispatch of upcalls - name: datapath-stats + enum-name: ovs-dp-stats type: struct members: - - name: hit + name: n-hit type: u64 - - name: missed + name: n-missed type: u64 - - name: lost + name: n-lost type: u64 - - name: flows + name: n-flows type: u64 - name: megaflow-stats + enum-name: ovs-dp-megaflow-stats type: struct members: - - name: mask-hit + name: n-mask-hit type: u64 - - name: masks + name: n-masks type: u32 - name: padding type: u32 - - name: cache-hits + name: n-cache-hit type: u64 - name: pad1 @@ -70,6 +74,8 @@ definitions: attribute-sets: - name: datapath + name-prefix: ovs-dp-attr- + enum-name: ovs-datapath-attrs attributes: - name: name @@ -101,12 +107,16 @@ attribute-sets: name: per-cpu-pids type: binary sub-type: u32 + - + name: ifindex + type: u32 operations: fixed-header: ovs-header + name-prefix: ovs-dp-cmd- list: - - name: dp-get + name: get doc: Get / dump OVS data path configuration and state value: 3 attribute-set: datapath @@ -125,7 +135,7 @@ operations: - per-cpu-pids dump: *dp-get-op - - name: dp-new + name: new doc: Create new OVS data path value: 1 attribute-set: datapath @@ -137,7 +147,7 @@ operations: - upcall-pid - user-features - - name: dp-del + name: del doc: Delete existing OVS data path value: 2 attribute-set: datapath diff --git a/Documentation/netlink/specs/ovs_flow.yaml b/Documentation/netlink/specs/ovs_flow.yaml new file mode 100644 index 0000000000000000000000000000000000000000..109ca1f57b6c6fb7d9465a7d1886979cfcb2d454 --- /dev/null +++ b/Documentation/netlink/specs/ovs_flow.yaml @@ -0,0 +1,980 @@ +# SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) + +name: ovs_flow +version: 1 +protocol: genetlink-legacy +uapi-header: linux/openvswitch.h + +doc: + OVS flow configuration over generic netlink. + +definitions: + - + name: ovs-header + type: struct + doc: | + Header for OVS Generic Netlink messages. + members: + - + name: dp-ifindex + type: u32 + doc: | + ifindex of local port for datapath (0 to make a request not specific + to a datapath). + - + name: ovs-flow-stats + type: struct + members: + - + name: n-packets + type: u64 + doc: Number of matched packets. + - + name: n-bytes + type: u64 + doc: Number of matched bytes. + - + name: ovs-key-ethernet + type: struct + members: + - + name: eth-src + type: binary + len: 6 + display-hint: mac + - + name: eth-dst + type: binary + len: 6 + display-hint: mac + - + name: ovs-key-mpls + type: struct + members: + - + name: mpls-lse + type: u32 + byte-order: big-endian + - + name: ovs-key-ipv4 + type: struct + members: + - + name: ipv4-src + type: u32 + byte-order: big-endian + display-hint: ipv4 + - + name: ipv4-dst + type: u32 + byte-order: big-endian + display-hint: ipv4 + - + name: ipv4-proto + type: u8 + - + name: ipv4-tos + type: u8 + - + name: ipv4-ttl + type: u8 + - + name: ipv4-frag + type: u8 + enum: ovs-frag-type + - + name: ovs-key-ipv6 + type: struct + members: + - + name: ipv6-src + type: binary + len: 16 + byte-order: big-endian + display-hint: ipv6 + - + name: ipv6-dst + type: binary + len: 16 + byte-order: big-endian + display-hint: ipv6 + - + name: ipv6-label + type: u32 + byte-order: big-endian + - + name: ipv6-proto + type: u8 + - + name: ipv6-tclass + type: u8 + - + name: ipv6-hlimit + type: u8 + - + name: ipv6-frag + type: u8 + - + name: ovs-key-ipv6-exthdrs + type: struct + members: + - + name: hdrs + type: u16 + - + name: ovs-frag-type + name-prefix: ovs-frag-type- + type: enum + entries: + - + name: none + doc: Packet is not a fragment. + - + name: first + doc: Packet is a fragment with offset 0. + - + name: later + doc: Packet is a fragment with nonzero offset. + - + name: any + value: 255 + - + name: ovs-key-tcp + type: struct + members: + - + name: tcp-src + type: u16 + byte-order: big-endian + - + name: tcp-dst + type: u16 + byte-order: big-endian + - + name: ovs-key-udp + type: struct + members: + - + name: udp-src + type: u16 + byte-order: big-endian + - + name: udp-dst + type: u16 + byte-order: big-endian + - + name: ovs-key-sctp + type: struct + members: + - + name: sctp-src + type: u16 + byte-order: big-endian + - + name: sctp-dst + type: u16 + byte-order: big-endian + - + name: ovs-key-icmp + type: struct + members: + - + name: icmp-type + type: u8 + - + name: icmp-code + type: u8 + - + name: ovs-key-arp + type: struct + members: + - + name: arp-sip + type: u32 + byte-order: big-endian + - + name: arp-tip + type: u32 + byte-order: big-endian + - + name: arp-op + type: u16 + byte-order: big-endian + - + name: arp-sha + type: binary + len: 6 + display-hint: mac + - + name: arp-tha + type: binary + len: 6 + display-hint: mac + - + name: ovs-key-nd + type: struct + members: + - + name: nd_target + type: binary + len: 16 + byte-order: big-endian + - + name: nd-sll + type: binary + len: 6 + display-hint: mac + - + name: nd-tll + type: binary + len: 6 + display-hint: mac + - + name: ovs-key-ct-tuple-ipv4 + type: struct + members: + - + name: ipv4-src + type: u32 + byte-order: big-endian + - + name: ipv4-dst + type: u32 + byte-order: big-endian + - + name: src-port + type: u16 + byte-order: big-endian + - + name: dst-port + type: u16 + byte-order: big-endian + - + name: ipv4-proto + type: u8 + - + name: ovs-action-push-vlan + type: struct + members: + - + name: vlan_tpid + type: u16 + byte-order: big-endian + doc: Tag protocol identifier (TPID) to push. + - + name: vlan_tci + type: u16 + byte-order: big-endian + doc: Tag control identifier (TCI) to push. + - + name: ovs-ufid-flags + name-prefix: ovs-ufid-f- + type: flags + entries: + - omit-key + - omit-mask + - omit-actions + - + name: ovs-action-hash + type: struct + members: + - + name: hash-alg + type: u32 + doc: Algorithm used to compute hash prior to recirculation. + - + name: hash-basis + type: u32 + doc: Basis used for computing hash. + - + name: ovs-hash-alg + type: enum + doc: | + Data path hash algorithm for computing Datapath hash. The algorithm type only specifies + the fields in a flow will be used as part of the hash. Each datapath is free to use its + own hash algorithm. The hash value will be opaque to the user space daemon. + entries: + - ovs-hash-alg-l4 + + - + name: ovs-action-push-mpls + type: struct + members: + - + name: mpls-lse + type: u32 + byte-order: big-endian + doc: | + MPLS label stack entry to push + - + name: mpls-ethertype + type: u32 + byte-order: big-endian + doc: | + Ethertype to set in the encapsulating ethernet frame. The only values + ethertype should ever be given are ETH_P_MPLS_UC and ETH_P_MPLS_MC, + indicating MPLS unicast or multicast. Other are rejected. + - + name: ovs-action-add-mpls + type: struct + members: + - + name: mpls-lse + type: u32 + byte-order: big-endian + doc: | + MPLS label stack entry to push + - + name: mpls-ethertype + type: u32 + byte-order: big-endian + doc: | + Ethertype to set in the encapsulating ethernet frame. The only values + ethertype should ever be given are ETH_P_MPLS_UC and ETH_P_MPLS_MC, + indicating MPLS unicast or multicast. Other are rejected. + - + name: tun-flags + type: u16 + doc: | + MPLS tunnel attributes. + - + name: ct-state-flags + type: flags + name-prefix: ovs-cs-f- + entries: + - + name: new + doc: Beginning of a new connection. + - + name: established + doc: Part of an existing connenction + - + name: related + doc: Related to an existing connection. + - + name: reply-dir + doc: Flow is in the reply direction. + - + name: invalid + doc: Could not track the connection. + - + name: tracked + doc: Conntrack has occurred. + - + name: src-nat + doc: Packet's source address/port was mangled by NAT. + - + name: dst-nat + doc: Packet's destination address/port was mangled by NAT. + +attribute-sets: + - + name: flow-attrs + enum-name: ovs-flow-attr + name-prefix: ovs-flow-attr- + attributes: + - + name: key + type: nest + nested-attributes: key-attrs + doc: | + Nested attributes specifying the flow key. Always present in + notifications. Required for all requests (except dumps). + - + name: actions + type: nest + nested-attributes: action-attrs + doc: | + Nested attributes specifying the actions to take for packets that + match the key. Always present in notifications. Required for + OVS_FLOW_CMD_NEW requests, optional for OVS_FLOW_CMD_SET requests. An + OVS_FLOW_CMD_SET without OVS_FLOW_ATTR_ACTIONS will not modify the + actions. To clear the actions, an OVS_FLOW_ATTR_ACTIONS without any + nested attributes must be given. + - + name: stats + type: binary + struct: ovs-flow-stats + doc: | + Statistics for this flow. Present in notifications if the stats would + be nonzero. Ignored in requests. + - + name: tcp-flags + type: u8 + doc: | + An 8-bit value giving the ORed value of all of the TCP flags seen on + packets in this flow. Only present in notifications for TCP flows, and + only if it would be nonzero. Ignored in requests. + - + name: used + type: u64 + doc: | + A 64-bit integer giving the time, in milliseconds on the system + monotonic clock, at which a packet was last processed for this + flow. Only present in notifications if a packet has been processed for + this flow. Ignored in requests. + - + name: clear + type: flag + doc: | + If present in a OVS_FLOW_CMD_SET request, clears the last-used time, + accumulated TCP flags, and statistics for this flow. Otherwise + ignored in requests. Never present in notifications. + - + name: mask + type: nest + nested-attributes: key-attrs + doc: | + Nested attributes specifying the mask bits for wildcarded flow + match. Mask bit value '1' specifies exact match with corresponding + flow key bit, while mask bit value '0' specifies a wildcarded + match. Omitting attribute is treated as wildcarding all corresponding + fields. Optional for all requests. If not present, all flow key bits + are exact match bits. + - + name: probe + type: binary + doc: | + Flow operation is a feature probe, error logging should be suppressed. + - + name: ufid + type: binary + doc: | + A value between 1-16 octets specifying a unique identifier for the + flow. Causes the flow to be indexed by this value rather than the + value of the OVS_FLOW_ATTR_KEY attribute. Optional for all + requests. Present in notifications if the flow was created with this + attribute. + display-hint: uuid + - + name: ufid-flags + type: u32 + enum: ovs-ufid-flags + doc: | + A 32-bit value of ORed flags that provide alternative semantics for + flow installation and retrieval. Optional for all requests. + - + name: pad + type: binary + + - + name: key-attrs + enum-name: ovs-key-attr + name-prefix: ovs-key-attr- + attributes: + - + name: encap + type: nest + nested-attributes: key-attrs + - + name: priority + type: u32 + - + name: in-port + type: u32 + - + name: ethernet + type: binary + struct: ovs-key-ethernet + doc: struct ovs_key_ethernet + - + name: vlan + type: u16 + byte-order: big-endian + - + name: ethertype + type: u16 + byte-order: big-endian + - + name: ipv4 + type: binary + struct: ovs-key-ipv4 + - + name: ipv6 + type: binary + struct: ovs-key-ipv6 + doc: struct ovs_key_ipv6 + - + name: tcp + type: binary + struct: ovs-key-tcp + - + name: udp + type: binary + struct: ovs-key-udp + - + name: icmp + type: binary + struct: ovs-key-icmp + - + name: icmpv6 + type: binary + struct: ovs-key-icmp + - + name: arp + type: binary + struct: ovs-key-arp + doc: struct ovs_key_arp + - + name: nd + type: binary + struct: ovs-key-nd + doc: struct ovs_key_nd + - + name: skb-mark + type: u32 + - + name: tunnel + type: nest + nested-attributes: tunnel-key-attrs + - + name: sctp + type: binary + struct: ovs-key-sctp + - + name: tcp-flags + type: u16 + byte-order: big-endian + - + name: dp-hash + type: u32 + doc: Value 0 indicates the hash is not computed by the datapath. + - + name: recirc-id + type: u32 + - + name: mpls + type: binary + struct: ovs-key-mpls + - + name: ct-state + type: u32 + enum: ct-state-flags + enum-as-flags: true + - + name: ct-zone + type: u16 + doc: connection tracking zone + - + name: ct-mark + type: u32 + doc: connection tracking mark + - + name: ct-labels + type: binary + display-hint: hex + doc: 16-octet connection tracking label + - + name: ct-orig-tuple-ipv4 + type: binary + struct: ovs-key-ct-tuple-ipv4 + - + name: ct-orig-tuple-ipv6 + type: binary + doc: struct ovs_key_ct_tuple_ipv6 + - + name: nsh + type: nest + nested-attributes: ovs-nsh-key-attrs + - + name: packet-type + type: u32 + byte-order: big-endian + doc: Should not be sent to the kernel + - + name: nd-extensions + type: binary + doc: Should not be sent to the kernel + - + name: tunnel-info + type: binary + doc: struct ip_tunnel_info + - + name: ipv6-exthdrs + type: binary + struct: ovs-key-ipv6-exthdrs + doc: struct ovs_key_ipv6_exthdr + - + name: action-attrs + enum-name: ovs-action-attr + name-prefix: ovs-action-attr- + attributes: + - + name: output + type: u32 + doc: ovs port number in datapath + - + name: userspace + type: nest + nested-attributes: userspace-attrs + - + name: set + type: nest + nested-attributes: key-attrs + doc: Replaces the contents of an existing header. The single nested attribute specifies a header to modify and its value. + - + name: push-vlan + type: binary + struct: ovs-action-push-vlan + doc: Push a new outermost 802.1Q or 802.1ad header onto the packet. + - + name: pop-vlan + type: flag + doc: Pop the outermost 802.1Q or 802.1ad header from the packet. + - + name: sample + type: nest + nested-attributes: sample-attrs + doc: | + Probabilistically executes actions, as specified in the nested attributes. + - + name: recirc + type: u32 + doc: recirc id + - + name: hash + type: binary + struct: ovs-action-hash + - + name: push-mpls + type: binary + struct: ovs-action-push-mpls + doc: | + Push a new MPLS label stack entry onto the top of the packets MPLS + label stack. Set the ethertype of the encapsulating frame to either + ETH_P_MPLS_UC or ETH_P_MPLS_MC to indicate the new packet contents. + - + name: pop-mpls + type: u16 + byte-order: big-endian + doc: ethertype + - + name: set-masked + type: nest + nested-attributes: key-attrs + doc: | + Replaces the contents of an existing header. A nested attribute + specifies a header to modify, its value, and a mask. For every bit set + in the mask, the corresponding bit value is copied from the value to + the packet header field, rest of the bits are left unchanged. The + non-masked value bits must be passed in as zeroes. Masking is not + supported for the OVS_KEY_ATTR_TUNNEL attribute. + - + name: ct + type: nest + nested-attributes: ct-attrs + doc: | + Track the connection. Populate the conntrack-related entries + in the flow key. + - + name: trunc + type: u32 + doc: struct ovs_action_trunc is a u32 max length + - + name: push-eth + type: binary + doc: struct ovs_action_push_eth + - + name: pop-eth + type: flag + - + name: ct-clear + type: flag + - + name: push-nsh + type: nest + nested-attributes: ovs-nsh-key-attrs + doc: | + Push NSH header to the packet. + - + name: pop-nsh + type: flag + doc: | + Pop the outermost NSH header off the packet. + - + name: meter + type: u32 + doc: | + Run packet through a meter, which may drop the packet, or modify the + packet (e.g., change the DSCP field) + - + name: clone + type: nest + nested-attributes: action-attrs + doc: | + Make a copy of the packet and execute a list of actions without + affecting the original packet and key. + - + name: check-pkt-len + type: nest + nested-attributes: check-pkt-len-attrs + doc: | + Check the packet length and execute a set of actions if greater than + the specified packet length, else execute another set of actions. + - + name: add-mpls + type: binary + struct: ovs-action-add-mpls + doc: | + Push a new MPLS label stack entry at the start of the packet or at the + start of the l3 header depending on the value of l3 tunnel flag in the + tun_flags field of this OVS_ACTION_ATTR_ADD_MPLS argument. + - + name: dec-ttl + type: nest + nested-attributes: dec-ttl-attrs + - + name: tunnel-key-attrs + enum-name: ovs-tunnel-key-attr + name-prefix: ovs-tunnel-key-attr- + attributes: + - + name: id + type: u64 + byte-order: big-endian + value: 0 + - + name: ipv4-src + type: u32 + byte-order: big-endian + - + name: ipv4-dst + type: u32 + byte-order: big-endian + - + name: tos + type: u8 + - + name: ttl + type: u8 + - + name: dont-fragment + type: flag + - + name: csum + type: flag + - + name: oam + type: flag + - + name: geneve-opts + type: binary + sub-type: u32 + - + name: tp-src + type: u16 + byte-order: big-endian + - + name: tp-dst + type: u16 + byte-order: big-endian + - + name: vxlan-opts + type: nest + nested-attributes: vxlan-ext-attrs + - + name: ipv6-src + type: binary + doc: | + struct in6_addr source IPv6 address + - + name: ipv6-dst + type: binary + doc: | + struct in6_addr destination IPv6 address + - + name: pad + type: binary + - + name: erspan-opts + type: binary + doc: | + struct erspan_metadata + - + name: ipv4-info-bridge + type: flag + - + name: check-pkt-len-attrs + enum-name: ovs-check-pkt-len-attr + name-prefix: ovs-check-pkt-len-attr- + attributes: + - + name: pkt-len + type: u16 + - + name: actions-if-greater + type: nest + nested-attributes: action-attrs + - + name: actions-if-less-equal + type: nest + nested-attributes: action-attrs + - + name: sample-attrs + enum-name: ovs-sample-attr + name-prefix: ovs-sample-attr- + attributes: + - + name: probability + type: u32 + - + name: actions + type: nest + nested-attributes: action-attrs + - + name: userspace-attrs + enum-name: ovs-userspace-attr + name-prefix: ovs-userspace-attr- + attributes: + - + name: pid + type: u32 + - + name: userdata + type: binary + - + name: egress-tun-port + type: u32 + - + name: actions + type: flag + - + name: ovs-nsh-key-attrs + enum-name: ovs-nsh-key-attr + name-prefix: ovs-nsh-key-attr- + attributes: + - + name: base + type: binary + - + name: md1 + type: binary + - + name: md2 + type: binary + - + name: ct-attrs + enum-name: ovs-ct-attr + name-prefix: ovs-ct-attr- + attributes: + - + name: commit + type: flag + - + name: zone + type: u16 + - + name: mark + type: binary + - + name: labels + type: binary + - + name: helper + type: string + - + name: nat + type: nest + nested-attributes: nat-attrs + - + name: force-commit + type: flag + - + name: eventmask + type: u32 + - + name: timeout + type: string + - + name: nat-attrs + enum-name: ovs-nat-attr + name-prefix: ovs-nat-attr- + attributes: + - + name: src + type: flag + - + name: dst + type: flag + - + name: ip-min + type: binary + - + name: ip-max + type: binary + - + name: proto-min + type: u16 + - + name: proto-max + type: u16 + - + name: persistent + type: flag + - + name: proto-hash + type: flag + - + name: proto-random + type: flag + - + name: dec-ttl-attrs + enum-name: ovs-dec-ttl-attr + name-prefix: ovs-dec-ttl-attr- + attributes: + - + name: action + type: nest + nested-attributes: action-attrs + - + name: vxlan-ext-attrs + enum-name: ovs-vxlan-ext- + name-prefix: ovs-vxlan-ext- + attributes: + - + name: gbp + type: u32 + +operations: + name-prefix: ovs-flow-cmd- + fixed-header: ovs-header + list: + - + name: get + doc: Get / dump OVS flow configuration and state + value: 3 + attribute-set: flow-attrs + do: &flow-get-op + request: + attributes: + - dp-ifindex + - key + - ufid + - ufid-flags + reply: + attributes: + - dp-ifindex + - key + - ufid + - mask + - stats + - actions + dump: *flow-get-op + - + name: new + doc: Create OVS flow configuration in a data path + value: 1 + attribute-set: flow-attrs + do: + request: + attributes: + - dp-ifindex + - key + - ufid + - mask + - actions + +mcast-groups: + list: + - + name: ovs_flow diff --git a/Documentation/netlink/specs/ovs_vport.yaml b/Documentation/netlink/specs/ovs_vport.yaml index 8e55622ddf11016018a049caaac222eada0dee4b..17336455bec147bc80d7f056efc3847dba4da6f7 100644 --- a/Documentation/netlink/specs/ovs_vport.yaml +++ b/Documentation/netlink/specs/ovs_vport.yaml @@ -3,6 +3,7 @@ name: ovs_vport version: 2 protocol: genetlink-legacy +uapi-header: linux/openvswitch.h doc: OVS vport configuration over generic netlink. @@ -18,10 +19,13 @@ definitions: - name: vport-type type: enum + enum-name: ovs-vport-type + name-prefix: ovs-vport-type- entries: [ unspec, netdev, internal, gre, vxlan, geneve ] - name: vport-stats type: struct + enum-name: ovs-vport-stats members: - name: rx-packets @@ -51,6 +55,8 @@ definitions: attribute-sets: - name: vport-options + enum-name: ovs-vport-options + name-prefix: ovs-tunnel-attr- attributes: - name: dst-port @@ -60,6 +66,8 @@ attribute-sets: type: u32 - name: upcall-stats + enum-name: ovs-vport-upcall-attr + name-prefix: ovs-vport-upcall-attr- attributes: - name: success @@ -70,6 +78,8 @@ attribute-sets: type: u64 - name: vport + name-prefix: ovs-vport-attr- + enum-name: ovs-vport-attr attributes: - name: port-no @@ -108,9 +118,10 @@ attribute-sets: nested-attributes: upcall-stats operations: + name-prefix: ovs-vport-cmd- list: - - name: vport-get + name: get doc: Get / dump OVS vport configuration and state value: 3 attribute-set: vport diff --git a/Documentation/networking/af_xdp.rst b/Documentation/networking/af_xdp.rst index 247c6c4127e942ae8afcd9ac1983393610a75613..1cc35de336a41ea27000e01e9c5bdf7d39b88d0b 100644 --- a/Documentation/networking/af_xdp.rst +++ b/Documentation/networking/af_xdp.rst @@ -433,6 +433,15 @@ start N bytes into the buffer leaving the first N bytes for the application to use. The final option is the flags field, but it will be dealt with in separate sections for each UMEM flag. +SO_BINDTODEVICE setsockopt +-------------------------- + +This is a generic SOL_SOCKET option that can be used to tie AF_XDP +socket to a particular network interface. It is useful when a socket +is created by a privileged process and passed to a non-privileged one. +Once the option is set, kernel will refuse attempts to bind that socket +to a different interface. Updating the value requires CAP_NET_RAW. + XDP_STATISTICS getsockopt ------------------------- diff --git a/Documentation/networking/device_drivers/cellular/qualcomm/rmnet.rst b/Documentation/networking/device_drivers/cellular/qualcomm/rmnet.rst index 4118384cf8ebeeaa235ee8a95eaabf3bd3e80c59..289c146a82915387e002fa3df2149a04bd58bf01 100644 --- a/Documentation/networking/device_drivers/cellular/qualcomm/rmnet.rst +++ b/Documentation/networking/device_drivers/cellular/qualcomm/rmnet.rst @@ -190,8 +190,7 @@ MAP header|IP Packet|Optional padding|MAP header|Command Packet|Optional pad... 3. Userspace configuration ========================== -rmnet userspace configuration is done through netlink library librmnetctl -and command line utility rmnetcli. Utility is hosted in codeaurora forum git. -The driver uses rtnl_link_ops for communication. +rmnet userspace configuration is done through netlink using iproute2 +https://git.kernel.org/pub/scm/network/iproute2/iproute2.git/ -https://source.codeaurora.org/quic/la/platform/vendor/qcom-opensource/dataservices/tree/rmnetctl +The driver uses rtnl_link_ops for communication. diff --git a/Documentation/networking/device_drivers/ethernet/amazon/ena.rst b/Documentation/networking/device_drivers/ethernet/amazon/ena.rst index 8bcb173e0353febfd483fbcee82fefc37ee32ab1..5eaa3ab6c73e7fb931d3fd8786ec723dd5ffe10a 100644 --- a/Documentation/networking/device_drivers/ethernet/amazon/ena.rst +++ b/Documentation/networking/device_drivers/ethernet/amazon/ena.rst @@ -38,6 +38,7 @@ debug logs. Some of the ENA devices support a working mode called Low-latency Queue (LLQ), which saves several more microseconds. + ENA Source Code Directory Structure =================================== @@ -205,6 +206,8 @@ Adaptive coalescing can be switched on/off through `ethtool(8)`'s More information about Adaptive Interrupt Moderation (DIM) can be found in Documentation/networking/net_dim.rst +.. _`RX copybreak`: + RX copybreak ============ The rx_copybreak is initialized by default to ENA_DEFAULT_RX_COPYBREAK @@ -315,3 +318,34 @@ Rx - The new SKB is updated with the necessary information (protocol, checksum hw verify result, etc), and then passed to the network stack, using the NAPI interface function :code:`napi_gro_receive()`. + +Dynamic RX Buffers (DRB) +------------------------ + +Each RX descriptor in the RX ring is a single memory page (which is either 4KB +or 16KB long depending on system's configurations). +To reduce the memory allocations required when dealing with a high rate of small +packets, the driver tries to reuse the remaining RX descriptor's space if more +than 2KB of this page remain unused. + +A simple example of this mechanism is the following sequence of events: + +:: + + 1. Driver allocates page-sized RX buffer and passes it to hardware + +----------------------+ + |4KB RX Buffer | + +----------------------+ + + 2. A 300Bytes packet is received on this buffer + + 3. The driver increases the ref count on this page and returns it back to + HW as an RX buffer of size 4KB - 300Bytes = 3796 Bytes + +----+--------------------+ + |****|3796 Bytes RX Buffer| + +----+--------------------+ + +This mechanism isn't used when an XDP program is loaded, or when the +RX packet is less than rx_copybreak bytes (in which case the packet is +copied out of the RX buffer into the linear part of a new skb allocated +for it and the RX buffer remains the same size, see `RX copybreak`_). diff --git a/Documentation/networking/device_drivers/ethernet/amd/pds_vdpa.rst b/Documentation/networking/device_drivers/ethernet/amd/pds_vdpa.rst new file mode 100644 index 0000000000000000000000000000000000000000..587927d3de92a41444eb57b62ddda9cf658b9001 --- /dev/null +++ b/Documentation/networking/device_drivers/ethernet/amd/pds_vdpa.rst @@ -0,0 +1,85 @@ +.. SPDX-License-Identifier: GPL-2.0+ +.. note: can be edited and viewed with /usr/bin/formiko-vim + +========================================================== +PCI vDPA driver for the AMD/Pensando(R) DSC adapter family +========================================================== + +AMD/Pensando vDPA VF Device Driver + +Copyright(c) 2023 Advanced Micro Devices, Inc + +Overview +======== + +The ``pds_vdpa`` driver is an auxiliary bus driver that supplies +a vDPA device for use by the virtio network stack. It is used with +the Pensando Virtual Function devices that offer vDPA and virtio queue +services. It depends on the ``pds_core`` driver and hardware for the PF +and VF PCI handling as well as for device configuration services. + +Using the device +================ + +The ``pds_vdpa`` device is enabled via multiple configuration steps and +depends on the ``pds_core`` driver to create and enable SR-IOV Virtual +Function devices. After the VFs are enabled, we enable the vDPA service +in the ``pds_core`` device to create the auxiliary devices used by pds_vdpa. + +Example steps: + +.. code-block:: bash + + #!/bin/bash + + modprobe pds_core + modprobe vdpa + modprobe pds_vdpa + + PF_BDF=`ls /sys/module/pds_core/drivers/pci\:pds_core/*/sriov_numvfs | awk -F / '{print $7}'` + + # Enable vDPA VF auxiliary device(s) in the PF + devlink dev param set pci/$PF_BDF name enable_vnet cmode runtime value true + + # Create a VF for vDPA use + echo 1 > /sys/bus/pci/drivers/pds_core/$PF_BDF/sriov_numvfs + + # Find the vDPA services/devices available + PDS_VDPA_MGMT=`vdpa mgmtdev show | grep vDPA | head -1 | cut -d: -f1` + + # Create a vDPA device for use in virtio network configurations + vdpa dev add name vdpa1 mgmtdev $PDS_VDPA_MGMT mac 00:11:22:33:44:55 + + # Set up an ethernet interface on the vdpa device + modprobe virtio_vdpa + + + +Enabling the driver +=================== + +The driver is enabled via the standard kernel configuration system, +using the make command:: + + make oldconfig/menuconfig/etc. + +The driver is located in the menu structure at: + + -> Device Drivers + -> Network device support (NETDEVICES [=y]) + -> Ethernet driver support + -> Pensando devices + -> Pensando Ethernet PDS_VDPA Support + +Support +======= + +For general Linux networking support, please use the netdev mailing +list, which is monitored by Pensando personnel:: + + netdev@vger.kernel.org + +For more specific support needs, please use the Pensando driver support +email:: + + drivers@pensando.io diff --git a/Documentation/networking/device_drivers/ethernet/index.rst b/Documentation/networking/device_drivers/ethernet/index.rst index 417ca514a4d057162667e2c1a267b0c7bd624c7f..94ecb67c0885023381c80bb8d5bb0502f8d2bf43 100644 --- a/Documentation/networking/device_drivers/ethernet/index.rst +++ b/Documentation/networking/device_drivers/ethernet/index.rst @@ -15,6 +15,7 @@ Contents: amazon/ena altera/altera_tse amd/pds_core + amd/pds_vdpa aquantia/atlantic chelsio/cxgb cirrus/cs89x0 diff --git a/Documentation/networking/device_drivers/ethernet/intel/ice.rst b/Documentation/networking/device_drivers/ethernet/intel/ice.rst index 69695e5511f423554aad6f919fa0115c526f1dd7..e4d065c55ea8d1496cacc7dec5bb8fddd7ac0fb2 100644 --- a/Documentation/networking/device_drivers/ethernet/intel/ice.rst +++ b/Documentation/networking/device_drivers/ethernet/intel/ice.rst @@ -84,24 +84,6 @@ Once the VM shuts down, or otherwise releases the VF, the command will complete. -Important notes for SR-IOV and Link Aggregation ------------------------------------------------ -Link Aggregation is mutually exclusive with SR-IOV. - -- If Link Aggregation is active, SR-IOV VFs cannot be created on the PF. -- If SR-IOV is active, you cannot set up Link Aggregation on the interface. - -Bridging and MACVLAN are also affected by this. If you wish to use bridging or -MACVLAN with SR-IOV, you must set up bridging or MACVLAN before enabling -SR-IOV. If you are using bridging or MACVLAN in conjunction with SR-IOV, and -you want to remove the interface from the bridge or MACVLAN, you must follow -these steps: - -1. Destroy SR-IOV VFs if they exist -2. Remove the interface from the bridge or MACVLAN -3. Recreate SRIOV VFs as needed - - Additional Features and Configurations ====================================== diff --git a/Documentation/networking/device_drivers/ethernet/marvell/octeontx2.rst b/Documentation/networking/device_drivers/ethernet/marvell/octeontx2.rst index 5ba9015336e2ee0e3fa2b66b633a831ea550bdc7..bfd233cfac352de540a1a805dd4ba1a8a9c36a7e 100644 --- a/Documentation/networking/device_drivers/ethernet/marvell/octeontx2.rst +++ b/Documentation/networking/device_drivers/ethernet/marvell/octeontx2.rst @@ -13,6 +13,7 @@ Contents - `Drivers`_ - `Basic packet flow`_ - `Devlink health reporters`_ +- `Quality of service`_ Overview ======== @@ -287,3 +288,47 @@ For example:: NIX_AF_ERR: NIX Error Interrupt Reg : 64 Rx on unmapped PF_FUNC + + +Quality of service +================== + + +Hardware algorithms used in scheduling +-------------------------------------- + +octeontx2 silicon and CN10K transmit interface consists of five transmit levels +starting from SMQ/MDQ, TL4 to TL1. Each packet will traverse MDQ, TL4 to TL1 +levels. Each level contains an array of queues to support scheduling and shaping. +The hardware uses the below algorithms depending on the priority of scheduler queues. +once the usercreates tc classes with different priorities, the driver configures +schedulers allocated to the class with specified priority along with rate-limiting +configuration. + +1. Strict Priority + + - Once packets are submitted to MDQ, hardware picks all active MDQs having different priority + using strict priority. + +2. Round Robin + + - Active MDQs having the same priority level are chosen using round robin. + + +Setup HTB offload +----------------- + +1. Enable HW TC offload on the interface:: + + # ethtool -K hw-tc-offload on + +2. Crate htb root:: + + # tc qdisc add dev clsact + # tc qdisc replace dev root handle 1: htb offload + +3. Create tc classes with different priorities:: + + # tc class add dev parent 1: classid 1:1 htb rate 10Gbit prio 1 + + # tc class add dev parent 1: classid 1:2 htb rate 10Gbit prio 7 diff --git a/Documentation/networking/device_drivers/ethernet/mellanox/mlx5/counters.rst b/Documentation/networking/device_drivers/ethernet/mellanox/mlx5/counters.rst index 6b2d1fe74ecf24634a05afeb884c6335ce08540f..a395df9c275131394d47843dd883cd4cc9593c99 100644 --- a/Documentation/networking/device_drivers/ethernet/mellanox/mlx5/counters.rst +++ b/Documentation/networking/device_drivers/ethernet/mellanox/mlx5/counters.rst @@ -797,6 +797,16 @@ Counters on the NIC port that is connected to a eSwitch. RoCE/UD/RC traffic) [#accel]_. - Acceleration + * - `vport_loopback_packets` + - Unicast, multicast and broadcast packets that were loop-back (received + and transmitted), IB/Eth [#accel]_. + - Acceleration + + * - `vport_loopback_bytes` + - Unicast, multicast and broadcast bytes that were loop-back (received + and transmitted), IB/Eth [#accel]_. + - Acceleration + * - `rx_steer_missed_packets` - Number of packets that was received by the NIC, however was discarded because it did not match any flow in the NIC flow table. diff --git a/Documentation/networking/device_drivers/ethernet/mellanox/mlx5/devlink.rst b/Documentation/networking/device_drivers/ethernet/mellanox/mlx5/devlink.rst index 3354ca3608ee671adc06939d78302420099b3110..a4edf908b707c2a61a007319d31c6e03c182e39a 100644 --- a/Documentation/networking/device_drivers/ethernet/mellanox/mlx5/devlink.rst +++ b/Documentation/networking/device_drivers/ethernet/mellanox/mlx5/devlink.rst @@ -290,6 +290,13 @@ Description of the vnic counters: - nic_receive_steering_discard number of packets that completed RX flow steering but were discarded due to a mismatch in flow table. +- generated_pkt_steering_fail + number of packets generated by the VNIC experiencing unexpected steering + failure (at any point in steering flow). +- handled_pkt_steering_fail + number of packets handled by the VNIC experiencing unexpected steering + failure (at any point in steering flow owned by the VNIC, including the FDB + for the eswitch owner). User commands examples: diff --git a/Documentation/networking/device_drivers/ethernet/mellanox/mlx5/switchdev.rst b/Documentation/networking/device_drivers/ethernet/mellanox/mlx5/switchdev.rst index 01deedb715975581f1052d00601da9e18bc6fa32..6e3f5ee8b0d01452e49d3d4cbbe6ce3dae8b2772 100644 --- a/Documentation/networking/device_drivers/ethernet/mellanox/mlx5/switchdev.rst +++ b/Documentation/networking/device_drivers/ethernet/mellanox/mlx5/switchdev.rst @@ -45,6 +45,28 @@ Following bridge VLAN functions are supported by mlx5: Subfunction =========== +Subfunction which are spawned over the E-switch are created only with devlink +device, and by default all the SF auxiliary devices are disabled. +This will allow user to configure the SF before the SF have been fully probed, +which will save time. + +Usage example: + +- Create SF:: + + $ devlink port add pci/0000:08:00.0 flavour pcisf pfnum 0 sfnum 11 + $ devlink port function set pci/0000:08:00.0/32768 hw_addr 00:00:00:00:00:11 state active + +- Enable ETH auxiliary device:: + + $ devlink dev param set auxiliary/mlx5_core.sf.1 name enable_eth value true cmode driverinit + +- Now, in order to fully probe the SF, use devlink reload:: + + $ devlink dev reload auxiliary/mlx5_core.sf.1 + +mlx5 supports ETH,rdma and vdpa (vnet) auxiliary devices devlink params (see :ref:`Documentation/networking/devlink/devlink-params.rst `). + mlx5 supports subfunction management using devlink port (see :ref:`Documentation/networking/devlink/devlink-port.rst `) interface. A subfunction has its own function capabilities and its own resources. This diff --git a/Documentation/networking/ip-sysctl.rst b/Documentation/networking/ip-sysctl.rst index 80b8f73a0244f4682967e74bb2edec010bf0c27a..4a010a7cde7f8085db5ba6f1b9af53e9e5223cd5 100644 --- a/Documentation/networking/ip-sysctl.rst +++ b/Documentation/networking/ip-sysctl.rst @@ -881,9 +881,10 @@ tcp_fastopen_key - list of comma separated 32-digit hexadecimal INTEGERs tcp_syn_retries - INTEGER Number of times initial SYNs for an active TCP connection attempt will be retransmitted. Should not be higher than 127. Default value - is 6, which corresponds to 63seconds till the last retransmission - with the current initial RTO of 1second. With this the final timeout - for an active TCP connection attempt will happen after 127seconds. + is 6, which corresponds to 67seconds (with tcp_syn_linear_timeouts = 4) + till the last retransmission with the current initial RTO of 1second. + With this the final timeout for an active TCP connection attempt + will happen after 131seconds. tcp_timestamps - INTEGER Enable timestamps as defined in RFC1323. @@ -946,6 +947,16 @@ tcp_pacing_ca_ratio - INTEGER Default: 120 +tcp_syn_linear_timeouts - INTEGER + The number of times for an active TCP connection to retransmit SYNs with + a linear backoff timeout before defaulting to an exponential backoff + timeout. This has no effect on SYNACK at the passive TCP side. + + With an initial RTO of 1 and tcp_syn_linear_timeouts = 4 we would + expect SYN RTOs to be: 1, 1, 1, 1, 1, 2, 4, ... (4 linear timeouts, + and the first exponential backoff using 2^0 * initial_RTO). + Default: 4 + tcp_tso_win_divisor - INTEGER This allows control over what percentage of the congestion window can be consumed by a single TSO frame. @@ -970,6 +981,21 @@ tcp_tw_reuse - INTEGER tcp_window_scaling - BOOLEAN Enable window scaling as defined in RFC1323. +tcp_shrink_window - BOOLEAN + This changes how the TCP receive window is calculated. + + RFC 7323, section 2.4, says there are instances when a retracted + window can be offered, and that TCP implementations MUST ensure + that they handle a shrinking window, as specified in RFC 1122. + + - 0 - Disabled. The window is never shrunk. + - 1 - Enabled. The window is shrunk when necessary to remain within + the memory limit set by autotuning (sk_rcvbuf). + This only occurs if a non-zero receive window + scaling factor is also in effect. + + Default: 0 + tcp_wmem - vector of 3 INTEGERs: min, default, max min: Amount of memory reserved for send buffers for TCP sockets. Each TCP socket has rights to use it due to fact of its birth. diff --git a/Documentation/networking/scaling.rst b/Documentation/networking/scaling.rst index 3d435caa3ef2bbc25414389ba78872260510e63b..92c9fb46d6a21c7c5490973a63301f0fe341a1bf 100644 --- a/Documentation/networking/scaling.rst +++ b/Documentation/networking/scaling.rst @@ -269,8 +269,8 @@ a single application thread handles flows with many different flow hashes. rps_sock_flow_table is a global flow table that contains the *desired* CPU for flows: the CPU that is currently processing the flow in userspace. Each table value is a CPU index that is updated during calls to recvmsg -and sendmsg (specifically, inet_recvmsg(), inet_sendmsg(), inet_sendpage() -and tcp_splice_read()). +and sendmsg (specifically, inet_recvmsg(), inet_sendmsg() and +tcp_splice_read()). When the scheduler moves a thread to a new CPU while it has outstanding receive packets on the old CPU, packets may arrive out of order. To diff --git a/Documentation/powerpc/dexcr.rst b/Documentation/powerpc/dexcr.rst new file mode 100644 index 0000000000000000000000000000000000000000..615a631f51fa1bb71ef79f3ea5a748a512ca2387 --- /dev/null +++ b/Documentation/powerpc/dexcr.rst @@ -0,0 +1,58 @@ +.. SPDX-License-Identifier: GPL-2.0-or-later + +========================================== +DEXCR (Dynamic Execution Control Register) +========================================== + +Overview +======== + +The DEXCR is a privileged special purpose register (SPR) introduced in +PowerPC ISA 3.1B (Power10) that allows per-cpu control over several dynamic +execution behaviours. These behaviours include speculation (e.g., indirect +branch target prediction) and enabling return-oriented programming (ROP) +protection instructions. + +The execution control is exposed in hardware as up to 32 bits ('aspects') in +the DEXCR. Each aspect controls a certain behaviour, and can be set or cleared +to enable/disable the aspect. There are several variants of the DEXCR for +different purposes: + +DEXCR + A privileged SPR that can control aspects for userspace and kernel space +HDEXCR + A hypervisor-privileged SPR that can control aspects for the hypervisor and + enforce aspects for the kernel and userspace. +UDEXCR + An optional ultravisor-privileged SPR that can control aspects for the ultravisor. + +Userspace can examine the current DEXCR state using a dedicated SPR that +provides a non-privileged read-only view of the userspace DEXCR aspects. +There is also an SPR that provides a read-only view of the hypervisor enforced +aspects, which ORed with the userspace DEXCR view gives the effective DEXCR +state for a process. + + +Configuration +============= + +The DEXCR is currently unconfigurable. All threads are run with the +NPHIE aspect enabled. + + +coredump and ptrace +=================== + +The userspace values of the DEXCR and HDEXCR (in this order) are exposed under +``NT_PPC_DEXCR``. These are each 64 bits and readonly, and are intended to +assist with core dumps. The DEXCR may be made writable in future. The top 32 +bits of both registers (corresponding to the non-userspace bits) are masked off. + +If the kernel config ``CONFIG_CHECKPOINT_RESTORE`` is enabled, then +``NT_PPC_HASHKEYR`` is available and exposes the HASHKEYR value of the process +for reading and writing. This is a tradeoff between increased security and +checkpoint/restore support: a process should normally have no need to know its +secret key, but restoring a process requires setting its original key. The key +therefore appears in core dumps, and an attacker may be able to retrieve it from +a coredump and effectively bypass ROP protection on any threads that share this +key (potentially all threads from the same parent that have not run ``exec()``). diff --git a/Documentation/powerpc/index.rst b/Documentation/powerpc/index.rst index 85e80e30160bb64650da63c4b34971ffa2215be6..d33b554ca7ba0df4b3f180b504008cfcf9c1334e 100644 --- a/Documentation/powerpc/index.rst +++ b/Documentation/powerpc/index.rst @@ -15,6 +15,7 @@ powerpc cxl cxlflash dawr-power9 + dexcr dscr eeh-pci-error-recovery elf_hwcaps diff --git a/Documentation/process/2.Process.rst b/Documentation/process/2.Process.rst index 6a919cffcbfd753fad7e74cb3290f1d561a38550..613a01da4717a8d3b69fe09a7ed4d671a5c46a28 100644 --- a/Documentation/process/2.Process.rst +++ b/Documentation/process/2.Process.rst @@ -434,9 +434,10 @@ There are a few hints which can help with linux-kernel survival: questions. Some developers can get impatient with people who clearly have not done their homework. -- Avoid top-posting (the practice of putting your answer above the quoted - text you are responding to). It makes your response harder to read and - makes a poor impression. +- Use interleaved ("inline") replies, which makes your response easier to + read. (i.e. avoid top-posting -- the practice of putting your answer above + the quoted text you are responding to.) For more details, see + :ref:`Documentation/process/submitting-patches.rst `. - Ask on the correct mailing list. Linux-kernel may be the general meeting point, but it is not the best place to find developers from all diff --git a/Documentation/process/6.Followthrough.rst b/Documentation/process/6.Followthrough.rst index a173cd5f93d284f8ca252bdb9b0a7261a470d4ab..66fa400c6d94053c5dd642fbd219dd5f9fac6bd0 100644 --- a/Documentation/process/6.Followthrough.rst +++ b/Documentation/process/6.Followthrough.rst @@ -51,6 +51,13 @@ mind: working toward the creation of the best kernel they can; they are not trying to create discomfort for their employers' competitors. + - Be prepared for seemingly silly requests for coding style changes + and requests to factor out some of your code to shared parts of + the kernel. One job the maintainers do is to keep things looking + the same. Sometimes this means that the clever hack in your driver + to get around a problem actually needs to become a generalized + kernel feature ready for next time. + What all of this comes down to is that, when reviewers send you comments, you need to pay attention to the technical observations that they are making. Do not let their form of expression or your own pride keep that diff --git a/Documentation/process/changes.rst b/Documentation/process/changes.rst index ef540865ad22e3b78352007c5b0f1c05f5a3e2b1..5561dae94f8572a7471a39673bd14ca787cc4ec0 100644 --- a/Documentation/process/changes.rst +++ b/Documentation/process/changes.rst @@ -31,7 +31,7 @@ you probably needn't concern yourself with pcmciautils. ====================== =============== ======================================== GNU C 5.1 gcc --version Clang/LLVM (optional) 11.0.0 clang --version -Rust (optional) 1.62.0 rustc --version +Rust (optional) 1.68.2 rustc --version bindgen (optional) 0.56.0 bindgen --version GNU make 3.82 make --version bash 4.2 bash --version @@ -60,6 +60,8 @@ openssl & libcrypto 1.0.0 openssl version bc 1.06.95 bc --version Sphinx\ [#f1]_ 1.7 sphinx-build --version cpio any cpio --version +GNU tar 1.28 tar --version +gtags (optional) 6.6.5 gtags --version ====================== =============== ======================================== .. [#f1] Sphinx is needed only to build the Kernel documentation @@ -174,6 +176,18 @@ You will need openssl to build kernels 3.7 and higher if module signing is enabled. You will also need openssl development packages to build kernels 4.3 and higher. +Tar +--- + +GNU tar is needed if you want to enable access to the kernel headers via sysfs +(CONFIG_IKHEADERS). + +gtags / GNU GLOBAL (optional) +----------------------------- + +The kernel build requires GNU GLOBAL version 6.6.5 or later to generate +tag files through ``make gtags``. This is due to its use of the gtags +``-C (--directory)`` flag. System utilities **************** diff --git a/Documentation/process/handling-regressions.rst b/Documentation/process/handling-regressions.rst index abb741b1aeee77ef78db02ad92cd8f6bfbd1dbcc..5d3c3de3f4ecbd8953f0b7791e4fabe107a4f57c 100644 --- a/Documentation/process/handling-regressions.rst +++ b/Documentation/process/handling-regressions.rst @@ -129,88 +129,132 @@ tools and scripts used by other kernel developers or Linux distributions; one of these tools is regzbot, which heavily relies on the "Link:" tags to associate reports for regression with changes resolving them. -Prioritize work on fixing regressions -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -You should fix any reported regression as quickly as possible, to provide -affected users with a solution in a timely manner and prevent more users from -running into the issue; nevertheless developers need to take enough time and -care to ensure regression fixes do not cause additional damage. - -In the end though, developers should give their best to prevent users from -running into situations where a regression leaves them only three options: "run -a kernel with a regression that seriously impacts usage", "continue running an -outdated and thus potentially insecure kernel version for more than two weeks -after a regression's culprit was identified", and "downgrade to a still -supported kernel series that lack required features". - -How to realize this depends a lot on the situation. Here are a few rules of -thumb for you, in order or importance: - - * Prioritize work on handling regression reports and fixing regression over all - other Linux kernel work, unless the latter concerns acute security issues or - bugs causing data loss or damage. - - * Always consider reverting the culprit commits and reapplying them later - together with necessary fixes, as this might be the least dangerous and - quickest way to fix a regression. - - * Developers should handle regressions in all supported kernel series, but are - free to delegate the work to the stable team, if the issue probably at no - point in time occurred with mainline. - - * Try to resolve any regressions introduced in the current development before - its end. If you fear a fix might be too risky to apply only days before a new - mainline release, let Linus decide: submit the fix separately to him as soon - as possible with the explanation of the situation. He then can make a call - and postpone the release if necessary, for example if multiple such changes - show up in his inbox. - - * Address regressions in stable, longterm, or proper mainline releases with - more urgency than regressions in mainline pre-releases. That changes after - the release of the fifth pre-release, aka "-rc5": mainline then becomes as - important, to ensure all the improvements and fixes are ideally tested - together for at least one week before Linus releases a new mainline version. - - * Fix regressions within two or three days, if they are critical for some - reason -- for example, if the issue is likely to affect many users of the - kernel series in question on all or certain architectures. Note, this - includes mainline, as issues like compile errors otherwise might prevent many - testers or continuous integration systems from testing the series. - - * Aim to fix regressions within one week after the culprit was identified, if - the issue was introduced in either: - - * a recent stable/longterm release - - * the development cycle of the latest proper mainline release - - In the latter case (say Linux v5.14), try to address regressions even - quicker, if the stable series for the predecessor (v5.13) will be abandoned - soon or already was stamped "End-of-Life" (EOL) -- this usually happens about - three to four weeks after a new mainline release. - - * Try to fix all other regressions within two weeks after the culprit was - found. Two or three additional weeks are acceptable for performance - regressions and other issues which are annoying, but don't prevent anyone - from running Linux (unless it's an issue in the current development cycle, - as those should ideally be addressed before the release). A few weeks in - total are acceptable if a regression can only be fixed with a risky change - and at the same time is affecting only a few users; as much time is - also okay if the regression is already present in the second newest longterm - kernel series. - -Note: The aforementioned time frames for resolving regressions are meant to -include getting the fix tested, reviewed, and merged into mainline, ideally with -the fix being in linux-next at least briefly. This leads to delays you need to -account for. - -Subsystem maintainers are expected to assist in reaching those periods by doing -timely reviews and quick handling of accepted patches. They thus might have to -send git-pull requests earlier or more often than usual; depending on the fix, -it might even be acceptable to skip testing in linux-next. Especially fixes for -regressions in stable and longterm kernels need to be handled quickly, as fixes -need to be merged in mainline before they can be backported to older series. +Expectations and best practices for fixing regressions +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +As a Linux kernel developer, you are expected to give your best to prevent +situations where a regression caused by a recent change of yours leaves users +only these options: + + * Run a kernel with a regression that impacts usage. + + * Switch to an older or newer kernel series. + + * Continue running an outdated and thus potentially insecure kernel for more + than three weeks after the regression's culprit was identified. Ideally it + should be less than two. And it ought to be just a few days, if the issue is + severe or affects many users -- either in general or in prevalent + environments. + +How to realize that in practice depends on various factors. Use the following +rules of thumb as a guide. + +In general: + + * Prioritize work on regressions over all other Linux kernel work, unless the + latter concerns a severe issue (e.g. acute security vulnerability, data loss, + bricked hardware, ...). + + * Expedite fixing mainline regressions that recently made it into a proper + mainline, stable, or longterm release (either directly or via backport). + + * Do not consider regressions from the current cycle as something that can wait + till the end of the cycle, as the issue might discourage or prevent users and + CI systems from testing mainline now or generally. + + * Work with the required care to avoid additional or bigger damage, even if + resolving an issue then might take longer than outlined below. + +On timing once the culprit of a regression is known: + + * Aim to mainline a fix within two or three days, if the issue is severe or + bothering many users -- either in general or in prevalent conditions like a + particular hardware environment, distribution, or stable/longterm series. + + * Aim to mainline a fix by Sunday after the next, if the culprit made it + into a recent mainline, stable, or longterm release (either directly or via + backport); if the culprit became known early during a week and is simple to + resolve, try to mainline the fix within the same week. + + * For other regressions, aim to mainline fixes before the hindmost Sunday + within the next three weeks. One or two Sundays later are acceptable, if the + regression is something people can live with easily for a while -- like a + mild performance regression. + + * It's strongly discouraged to delay mainlining regression fixes till the next + merge window, except when the fix is extraordinarily risky or when the + culprit was mainlined more than a year ago. + +On procedure: + + * Always consider reverting the culprit, as it's often the quickest and least + dangerous way to fix a regression. Don't worry about mainlining a fixed + variant later: that should be straight-forward, as most of the code went + through review once already. + + * Try to resolve any regressions introduced in mainline during the past + twelve months before the current development cycle ends: Linus wants such + regressions to be handled like those from the current cycle, unless fixing + bears unusual risks. + + * Consider CCing Linus on discussions or patch review, if a regression seems + tangly. Do the same in precarious or urgent cases -- especially if the + subsystem maintainer might be unavailable. Also CC the stable team, when you + know such a regression made it into a mainline, stable, or longterm release. + + * For urgent regressions, consider asking Linus to pick up the fix straight + from the mailing list: he is totally fine with that for uncontroversial + fixes. Ideally though such requests should happen in accordance with the + subsystem maintainers or come directly from them. + + * In case you are unsure if a fix is worth the risk applying just days before + a new mainline release, send Linus a mail with the usual lists and people in + CC; in it, summarize the situation while asking him to consider picking up + the fix straight from the list. He then himself can make the call and when + needed even postpone the release. Such requests again should ideally happen + in accordance with the subsystem maintainers or come directly from them. + +Regarding stable and longterm kernels: + + * You are free to leave regressions to the stable team, if they at no point in + time occurred with mainline or were fixed there already. + + * If a regression made it into a proper mainline release during the past + twelve months, ensure to tag the fix with "Cc: stable@vger.kernel.org", as a + "Fixes:" tag alone does not guarantee a backport. Please add the same tag, + in case you know the culprit was backported to stable or longterm kernels. + + * When receiving reports about regressions in recent stable or longterm kernel + series, please evaluate at least briefly if the issue might happen in current + mainline as well -- and if that seems likely, take hold of the report. If in + doubt, ask the reporter to check mainline. + + * Whenever you want to swiftly resolve a regression that recently also made it + into a proper mainline, stable, or longterm release, fix it quickly in + mainline; when appropriate thus involve Linus to fast-track the fix (see + above). That's because the stable team normally does neither revert nor fix + any changes that cause the same problems in mainline. + + * In case of urgent regression fixes you might want to ensure prompt + backporting by dropping the stable team a note once the fix was mainlined; + this is especially advisable during merge windows and shortly thereafter, as + the fix otherwise might land at the end of a huge patch queue. + +On patch flow: + + * Developers, when trying to reach the time periods mentioned above, remember + to account for the time it takes to get fixes tested, reviewed, and merged by + Linus, ideally with them being in linux-next at least briefly. Hence, if a + fix is urgent, make it obvious to ensure others handle it appropriately. + + * Reviewers, you are kindly asked to assist developers in reaching the time + periods mentioned above by reviewing regression fixes in a timely manner. + + * Subsystem maintainers, you likewise are encouraged to expedite the handling + of regression fixes. Thus evaluate if skipping linux-next is an option for + the particular fix. Also consider sending git pull requests more often than + usual when needed. And try to avoid holding onto regression fixes over + weekends -- especially when the fix is marked for backporting. More aspects regarding regressions developers should be aware of diff --git a/Documentation/process/maintainer-handbooks.rst b/Documentation/process/maintainer-handbooks.rst index d783060b4cc6e0c97c715531b1f2cab769b5f757..9992bfd7eaa37cf4eecdba0aaa210839df872212 100644 --- a/Documentation/process/maintainer-handbooks.rst +++ b/Documentation/process/maintainer-handbooks.rst @@ -15,5 +15,7 @@ Contents: :numbered: :maxdepth: 2 - maintainer-tip maintainer-netdev + maintainer-soc + maintainer-tip + maintainer-kvm-x86 diff --git a/Documentation/process/maintainer-kvm-x86.rst b/Documentation/process/maintainer-kvm-x86.rst new file mode 100644 index 0000000000000000000000000000000000000000..9183bd449762619269c51e3d588903c8c9a64073 --- /dev/null +++ b/Documentation/process/maintainer-kvm-x86.rst @@ -0,0 +1,390 @@ +.. SPDX-License-Identifier: GPL-2.0 + +KVM x86 +======= + +Foreword +-------- +KVM strives to be a welcoming community; contributions from newcomers are +valued and encouraged. Please do not be discouraged or intimidated by the +length of this document and the many rules/guidelines it contains. Everyone +makes mistakes, and everyone was a newbie at some point. So long as you make +an honest effort to follow KVM x86's guidelines, are receptive to feedback, +and learn from any mistakes you make, you will be welcomed with open arms, not +torches and pitchforks. + +TL;DR +----- +Testing is mandatory. Be consistent with established styles and patterns. + +Trees +----- +KVM x86 is currently in a transition period from being part of the main KVM +tree, to being "just another KVM arch". As such, KVM x86 is split across the +main KVM tree, ``git.kernel.org/pub/scm/virt/kvm/kvm.git``, and a KVM x86 +specific tree, ``github.com/kvm-x86/linux.git``. + +Generally speaking, fixes for the current cycle are applied directly to the +main KVM tree, while all development for the next cycle is routed through the +KVM x86 tree. In the unlikely event that a fix for the current cycle is routed +through the KVM x86 tree, it will be applied to the ``fixes`` branch before +making its way to the main KVM tree. + +Note, this transition period is expected to last quite some time, i.e. will be +the status quo for the foreseeable future. + +Branches +~~~~~~~~ +The KVM x86 tree is organized into multiple topic branches. The purpose of +using finer-grained topic branches is to make it easier to keep tabs on an area +of development, and to limit the collateral damage of human errors and/or buggy +commits, e.g. dropping the HEAD commit of a topic branch has no impact on other +in-flight commits' SHA1 hashes, and having to reject a pull request due to bugs +delays only that topic branch. + +All topic branches, except for ``next`` and ``fixes``, are rolled into ``next`` +via a Cthulhu merge on an as-needed basis, i.e. when a topic branch is updated. +As a result, force pushes to ``next`` are common. + +Lifecycle +~~~~~~~~~ +Fixes that target the current release, a.k.a. mainline, are typically applied +directly to the main KVM tree, i.e. do not route through the KVM x86 tree. + +Changes that target the next release are routed through the KVM x86 tree. Pull +requests (from KVM x86 to main KVM) are sent for each KVM x86 topic branch, +typically the week before Linus' opening of the merge window, e.g. the week +following rc7 for "normal" releases. If all goes well, the topic branches are +rolled into the main KVM pull request sent during Linus' merge window. + +The KVM x86 tree doesn't have its own official merge window, but there's a soft +close around rc5 for new features, and a soft close around rc6 for fixes (for +the next release; see above for fixes that target the current release). + +Timeline +~~~~~~~~ +Submissions are typically reviewed and applied in FIFO order, with some wiggle +room for the size of a series, patches that are "cache hot", etc. Fixes, +especially for the current release and or stable trees, get to jump the queue. +Patches that will be taken through a non-KVM tree (most often through the tip +tree) and/or have other acks/reviews also jump the queue to some extent. + +Note, the vast majority of review is done between rc1 and rc6, give or take. +The period between rc6 and the next rc1 is used to catch up on other tasks, +i.e. radio silence during this period isn't unusual. + +Pings to get a status update are welcome, but keep in mind the timing of the +current release cycle and have realistic expectations. If you are pinging for +acceptance, i.e. not just for feedback or an update, please do everything you +can, within reason, to ensure that your patches are ready to be merged! Pings +on series that break the build or fail tests lead to unhappy maintainers! + +Development +----------- + +Base Tree/Branch +~~~~~~~~~~~~~~~~ +Fixes that target the current release, a.k.a. mainline, should be based on +``git://git.kernel.org/pub/scm/virt/kvm/kvm.git master``. Note, fixes do not +automatically warrant inclusion in the current release. There is no singular +rule, but typically only fixes for bugs that are urgent, critical, and/or were +introduced in the current release should target the current release. + +Everything else should be based on ``kvm-x86/next``, i.e. there is no need to +select a specific topic branch as the base. If there are conflicts and/or +dependencies across topic branches, it is the maintainer's job to sort them +out. + +The only exception to using ``kvm-x86/next`` as the base is if a patch/series +is a multi-arch series, i.e. has non-trivial modifications to common KVM code +and/or has more than superficial changes to other architectures' code. Multi- +arch patch/series should instead be based on a common, stable point in KVM's +history, e.g. the release candidate upon which ``kvm-x86 next`` is based. If +you're unsure whether a patch/series is truly multi-arch, err on the side of +caution and treat it as multi-arch, i.e. use a common base. + +Coding Style +~~~~~~~~~~~~ +When it comes to style, naming, patterns, etc., consistency is the number one +priority in KVM x86. If all else fails, match what already exists. + +With a few caveats listed below, follow the tip tree maintainers' preferred +:ref:`maintainer-tip-coding-style`, as patches/series often touch both KVM and +non-KVM x86 files, i.e. draw the attention of KVM *and* tip tree maintainers. + +Using reverse fir tree, a.k.a. reverse Christmas tree or reverse XMAS tree, for +variable declarations isn't strictly required, though it is still preferred. + +Except for a handful of special snowflakes, do not use kernel-doc comments for +functions. The vast majority of "public" KVM functions aren't truly public as +they are intended only for KVM-internal consumption (there are plans to +privatize KVM's headers and exports to enforce this). + +Comments +~~~~~~~~ +Write comments using imperative mood and avoid pronouns. Use comments to +provide a high level overview of the code, and/or to explain why the code does +what it does. Do not reiterate what the code literally does; let the code +speak for itself. If the code itself is inscrutable, comments will not help. + +SDM and APM References +~~~~~~~~~~~~~~~~~~~~~~ +Much of KVM's code base is directly tied to architectural behavior defined in +Intel's Software Development Manual (SDM) and AMD's Architecture Programmer’s +Manual (APM). Use of "Intel's SDM" and "AMD's APM", or even just "SDM" or +"APM", without additional context is a-ok. + +Do not reference specific sections, tables, figures, etc. by number, especially +not in comments. Instead, if necessary (see below), copy-paste the relevant +snippet and reference sections/tables/figures by name. The layouts of the SDM +and APM are constantly changing, and so the numbers/labels aren't stable. + +Generally speaking, do not explicitly reference or copy-paste from the SDM or +APM in comments. With few exceptions, KVM *must* honor architectural behavior, +therefore it's implied that KVM behavior is emulating SDM and/or APM behavior. +Note, referencing the SDM/APM in changelogs to justify the change and provide +context is perfectly ok and encouraged. + +Shortlog +~~~~~~~~ +The preferred prefix format is ``KVM: :``, where ```` is one of:: + + - x86 + - x86/mmu + - x86/pmu + - x86/xen + - selftests + - SVM + - nSVM + - VMX + - nVMX + +**DO NOT use x86/kvm!** ``x86/kvm`` is used exclusively for Linux-as-a-KVM-guest +changes, i.e. for arch/x86/kernel/kvm.c. Do not use file names or complete file +paths as the subject/shortlog prefix. + +Note, these don't align with the topics branches (the topic branches care much +more about code conflicts). + +All names are case sensitive! ``KVM: x86:`` is good, ``kvm: vmx:`` is not. + +Capitalize the first word of the condensed patch description, but omit ending +punctionation. E.g.:: + + KVM: x86: Fix a null pointer dereference in function_xyz() + +not:: + + kvm: x86: fix a null pointer dereference in function_xyz. + +If a patch touches multiple topics, traverse up the conceptual tree to find the +first common parent (which is often simply ``x86``). When in doubt, +``git log path/to/file`` should provide a reasonable hint. + +New topics do occasionally pop up, but please start an on-list discussion if +you want to propose introducing a new topic, i.e. don't go rogue. + +See :ref:`the_canonical_patch_format` for more information, with one amendment: +do not treat the 70-75 character limit as an absolute, hard limit. Instead, +use 75 characters as a firm-but-not-hard limit, and use 80 characters as a hard +limit. I.e. let the shortlog run a few characters over the standard limit if +you have good reason to do so. + +Changelog +~~~~~~~~~ +Most importantly, write changelogs using imperative mood and avoid pronouns. + +See :ref:`describe_changes` for more information, with one amendment: lead with +a short blurb on the actual changes, and then follow up with the context and +background. Note! This order directly conflicts with the tip tree's preferred +approach! Please follow the tip tree's preferred style when sending patches +that primarily target arch/x86 code that is _NOT_ KVM code. + +Stating what a patch does before diving into details is preferred by KVM x86 +for several reasons. First and foremost, what code is actually being changed +is arguably the most important information, and so that info should be easy to +find. Changelogs that bury the "what's actually changing" in a one-liner after +3+ paragraphs of background make it very hard to find that information. + +For initial review, one could argue the "what's broken" is more important, but +for skimming logs and git archaeology, the gory details matter less and less. +E.g. when doing a series of "git blame", the details of each change along the +way are useless, the details only matter for the culprit. Providing the "what +changed" makes it easy to quickly determine whether or not a commit might be of +interest. + +Another benefit of stating "what's changing" first is that it's almost always +possible to state "what's changing" in a single sentence. Conversely, all but +the most simple bugs require multiple sentences or paragraphs to fully describe +the problem. If both the "what's changing" and "what's the bug" are super +short then the order doesn't matter. But if one is shorter (almost always the +"what's changing), then covering the shorter one first is advantageous because +it's less of an inconvenience for readers/reviewers that have a strict ordering +preference. E.g. having to skip one sentence to get to the context is less +painful than having to skip three paragraphs to get to "what's changing". + +Fixes +~~~~~ +If a change fixes a KVM/kernel bug, add a Fixes: tag even if the change doesn't +need to be backported to stable kernels, and even if the change fixes a bug in +an older release. + +Conversely, if a fix does need to be backported, explicitly tag the patch with +"Cc: stable@vger.kernel" (though the email itself doesn't need to Cc: stable); +KVM x86 opts out of backporting Fixes: by default. Some auto-selected patches +do get backported, but require explicit maintainer approval (search MANUALSEL). + +Function References +~~~~~~~~~~~~~~~~~~~ +When a function is mentioned in a comment, changelog, or shortlog (or anywhere +for that matter), use the format ``function_name()``. The parentheses provide +context and disambiguate the reference. + +Testing +------- +At a bare minimum, *all* patches in a series must build cleanly for KVM_INTEL=m +KVM_AMD=m, and KVM_WERROR=y. Building every possible combination of Kconfigs +isn't feasible, but the more the merrier. KVM_SMM, KVM_XEN, PROVE_LOCKING, and +X86_64 are particularly interesting knobs to turn. + +Running KVM selftests and KVM-unit-tests is also mandatory (and stating the +obvious, the tests need to pass). The only exception is for changes that have +negligible probability of affecting runtime behavior, e.g. patches that only +modify comments. When possible and relevant, testing on both Intel and AMD is +strongly preferred. Booting an actual VM is encouraged, but not mandatory. + +For changes that touch KVM's shadow paging code, running with TDP (EPT/NPT) +disabled is mandatory. For changes that affect common KVM MMU code, running +with TDP disabled is strongly encouraged. For all other changes, if the code +being modified depends on and/or interacts with a module param, testing with +the relevant settings is mandatory. + +Note, KVM selftests and KVM-unit-tests do have known failures. If you suspect +a failure is not due to your changes, verify that the *exact same* failure +occurs with and without your changes. + +Changes that touch reStructured Text documentation, i.e. .rst files, must build +htmldocs cleanly, i.e. with no new warnings or errors. + +If you can't fully test a change, e.g. due to lack of hardware, clearly state +what level of testing you were able to do, e.g. in the cover letter. + +New Features +~~~~~~~~~~~~ +With one exception, new features *must* come with test coverage. KVM specific +tests aren't strictly required, e.g. if coverage is provided by running a +sufficiently enabled guest VM, or by running a related kernel selftest in a VM, +but dedicated KVM tests are preferred in all cases. Negative testcases in +particular are mandatory for enabling of new hardware features as error and +exception flows are rarely exercised simply by running a VM. + +The only exception to this rule is if KVM is simply advertising support for a +feature via KVM_GET_SUPPORTED_CPUID, i.e. for instructions/features that KVM +can't prevent a guest from using and for which there is no true enabling. + +Note, "new features" does not just mean "new hardware features"! New features +that can't be well validated using existing KVM selftests and/or KVM-unit-tests +must come with tests. + +Posting new feature development without tests to get early feedback is more +than welcome, but such submissions should be tagged RFC, and the cover letter +should clearly state what type of feedback is requested/expected. Do not abuse +the RFC process; RFCs will typically not receive in-depth review. + +Bug Fixes +~~~~~~~~~ +Except for "obvious" found-by-inspection bugs, fixes must be accompanied by a +reproducer for the bug being fixed. In many cases the reproducer is implicit, +e.g. for build errors and test failures, but it should still be clear to +readers what is broken and how to verify the fix. Some leeway is given for +bugs that are found via non-public workloads/tests, but providing regression +tests for such bugs is strongly preferred. + +In general, regression tests are preferred for any bug that is not trivial to +hit. E.g. even if the bug was originally found by a fuzzer such as syzkaller, +a targeted regression test may be warranted if the bug requires hitting a +one-in-a-million type race condition. + +Note, KVM bugs are rarely urgent *and* non-trivial to reproduce. Ask yourself +if a bug is really truly the end of the world before posting a fix without a +reproducer. + +Posting +------- + +Links +~~~~~ +Do not explicitly reference bug reports, prior versions of a patch/series, etc. +via ``In-Reply-To:`` headers. Using ``In-Reply-To:`` becomes an unholy mess +for large series and/or when the version count gets high, and ``In-Reply-To:`` +is useless for anyone that doesn't have the original message, e.g. if someone +wasn't Cc'd on the bug report or if the list of recipients changes between +versions. + +To link to a bug report, previous version, or anything of interest, use lore +links. For referencing previous version(s), generally speaking do not include +a Link: in the changelog as there is no need to record the history in git, i.e. +put the link in the cover letter or in the section git ignores. Do provide a +formal Link: for bug reports and/or discussions that led to the patch. The +context of why a change was made is highly valuable for future readers. + +Git Base +~~~~~~~~ +If you are using git version 2.9.0 or later (Googlers, this is all of you!), +use ``git format-patch`` with the ``--base`` flag to automatically include the +base tree information in the generated patches. + +Note, ``--base=auto`` works as expected if and only if a branch's upstream is +set to the base topic branch, e.g. it will do the wrong thing if your upstream +is set to your personal repository for backup purposes. An alternative "auto" +solution is to derive the names of your development branches based on their +KVM x86 topic, and feed that into ``--base``. E.g. ``x86/pmu/my_branch_name``, +and then write a small wrapper to extract ``pmu`` from the current branch name +to yield ``--base=x/pmu``, where ``x`` is whatever name your repository uses to +track the KVM x86 remote. + +Co-Posting Tests +~~~~~~~~~~~~~~~~ +KVM selftests that are associated with KVM changes, e.g. regression tests for +bug fixes, should be posted along with the KVM changes as a single series. The +standard kernel rules for bisection apply, i.e. KVM changes that result in test +failures should be ordered after the selftests updates, and vice versa, new +tests that fail due to KVM bugs should be ordered after the KVM fixes. + +KVM-unit-tests should *always* be posted separately. Tools, e.g. b4 am, don't +know that KVM-unit-tests is a separate repository and get confused when patches +in a series apply on different trees. To tie KVM-unit-tests patches back to +KVM patches, first post the KVM changes and then provide a lore Link: to the +KVM patch/series in the KVM-unit-tests patch(es). + +Notifications +------------- +When a patch/series is officially accepted, a notification email will be sent +in reply to the original posting (cover letter for multi-patch series). The +notification will include the tree and topic branch, along with the SHA1s of +the commits of applied patches. + +If a subset of patches is applied, this will be clearly stated in the +notification. Unless stated otherwise, it's implied that any patches in the +series that were not accepted need more work and should be submitted in a new +version. + +If for some reason a patch is dropped after officially being accepted, a reply +will be sent to the notification email explaining why the patch was dropped, as +well as the next steps. + +SHA1 Stability +~~~~~~~~~~~~~~ +SHA1s are not 100% guaranteed to be stable until they land in Linus' tree! A +SHA1 is *usually* stable once a notification has been sent, but things happen. +In most cases, an update to the notification email be provided if an applied +patch's SHA1 changes. However, in some scenarios, e.g. if all KVM x86 branches +need to be rebased, individual notifications will not be given. + +Vulnerabilities +--------------- +Bugs that can be exploited by the guest to attack the host (kernel or +userspace), or that can be exploited by a nested VM to *its* host (L2 attacking +L1), are of particular interest to KVM. Please follow the protocol for +:ref:`securitybugs` if you suspect a bug can lead to an escape, data leak, etc. + diff --git a/Documentation/process/maintainer-netdev.rst b/Documentation/process/maintainer-netdev.rst index 83614cec9328b62b2333947a5254b1f57519545f..2ab843cde830cd31b4ba449409d5ffcd08c81fb8 100644 --- a/Documentation/process/maintainer-netdev.rst +++ b/Documentation/process/maintainer-netdev.rst @@ -98,7 +98,7 @@ If you aren't subscribed to netdev and/or are simply unsure if repository link above for any new networking-related commits. You may also check the following website for the current status: - http://vger.kernel.org/~davem/net-next.html + https://patchwork.hopto.org/net-next.html The ``net`` tree continues to collect fixes for the vX.Y content, and is fed back to Linus at regular (~weekly) intervals. Meaning that the @@ -149,8 +149,11 @@ themselves. No email should ever be sent to the list with the main purpose of communicating with the bot, the bot commands should be seen as metadata. The use of the bot is restricted to authors of the patches (the ``From:`` -header on patch submission and command must match!), maintainers themselves -and a handful of senior reviewers. Bot records its activity here: +header on patch submission and command must match!), maintainers of +the modified code according to the MAINTAINERS file (again, ``From:`` +must match the MAINTAINERS entry) and a handful of senior reviewers. + +Bot records its activity here: https://patchwork.hopto.org/pw-bot.html diff --git a/Documentation/process/maintainer-soc.rst b/Documentation/process/maintainer-soc.rst new file mode 100644 index 0000000000000000000000000000000000000000..49f08289d62c157dfbc4f82f328fc66176cd7c62 --- /dev/null +++ b/Documentation/process/maintainer-soc.rst @@ -0,0 +1,177 @@ +.. SPDX-License-Identifier: GPL-2.0 + +============= +SoC Subsystem +============= + +Overview +-------- + +The SoC subsystem is a place of aggregation for SoC-specific code. +The main components of the subsystem are: + +* devicetrees for 32- & 64-bit ARM and RISC-V +* 32-bit ARM board files (arch/arm/mach*) +* 32- & 64-bit ARM defconfigs +* SoC-specific drivers across architectures, in particular for 32- & 64-bit + ARM, RISC-V and Loongarch + +These "SoC-specific drivers" do not include clock, GPIO etc drivers that have +other top-level maintainers. The drivers/soc/ directory is generally meant +for kernel-internal drivers that are used by other drivers to provide SoC- +specific functionality like identifying an SoC revision or interfacing with +power domains. + +The SoC subsystem also serves as an intermediate location for changes to +drivers/bus, drivers/firmware, drivers/reset and drivers/memory. The addition +of new platforms, or the removal of existing ones, often go through the SoC +tree as a dedicated branch covering multiple subsystems. + +The main SoC tree is housed on git.kernel.org: + https://git.kernel.org/pub/scm/linux/kernel/git/soc/soc.git/ + +Clearly this is quite a wide range of topics, which no one person, or even +small group of people are capable of maintaining. Instead, the SoC subsystem +is comprised of many submaintainers, each taking care of individual platforms +and driver subdirectories. +In this regard, "platform" usually refers to a series of SoCs from a given +vendor, for example, Nvidia's series of Tegra SoCs. Many submaintainers operate +on a vendor level, responsible for multiple product lines. For several reasons, +including acquisitions/different business units in a company, things vary +significantly here. The various submaintainers are documented in the +MAINTAINERS file. + +Most of these submaintainers have their own trees where they stage patches, +sending pull requests to the main SoC tree. These trees are usually, but not +always, listed in MAINTAINERS. The main SoC maintainers can be reached via the +alias soc@kernel.org if there is no platform-specific maintainer, or if they +are unresponsive. + +What the SoC tree is not, however, is a location for architecture-specific code +changes. Each architecture has its own maintainers that are responsible for +architectural details, CPU errata and the like. + +Information for (new) Submaintainers +------------------------------------ + +As new platforms spring up, they often bring with them new submaintainers, +many of whom work for the silicon vendor, and may not be familiar with the +process. + +Devicetree ABI Stability +~~~~~~~~~~~~~~~~~~~~~~~~ + +Perhaps one of the most important things to highlight is that dt-bindings +document the ABI between the devicetree and the kernel. +Please read Documentation/devicetree/bindings/ABI.rst. + +If changes are being made to a devicetree that are incompatible with old +kernels, the devicetree patch should not be applied until the driver is, or an +appropriate time later. Most importantly, any incompatible changes should be +clearly pointed out in the patch description and pull request, along with the +expected impact on existing users, such as bootloaders or other operating +systems. + +Driver Branch Dependencies +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +A common problem is synchronizing changes between device drivers and devicetree +files. Even if a change is compatible in both directions, this may require +coordinating how the changes get merged through different maintainer trees. + +Usually the branch that includes a driver change will also include the +corresponding change to the devicetree binding description, to ensure they are +in fact compatible. This means that the devicetree branch can end up causing +warnings in the "make dtbs_check" step. If a devicetree change depends on +missing additions to a header file in include/dt-bindings/, it will fail the +"make dtbs" step and not get merged. + +There are multiple ways to deal with this: + +* Avoid defining custom macros in include/dt-bindings/ for hardware constants + that can be derived from a datasheet -- binding macros in header files should + only be used as a last resort if there is no natural way to define a binding + +* Use literal values in the devicetree file in place of macros even when a + header is required, and change them to the named representation in a + following release + +* Defer the devicetree changes to a release after the binding and driver have + already been merged + +* Change the bindings in a shared immutable branch that is used as the base for + both the driver change and the devicetree changes + +* Add duplicate defines in the devicetree file guarded by an #ifndef section, + removing them in a later release + +Devicetree Naming Convention +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The general naming scheme for devicetree files is as follows. The aspects of a +platform that are set at the SoC level, like CPU cores, are contained in a file +named $soc.dtsi, for example, jh7100.dtsi. Integration details, that will vary +from board to board, are described in $soc-$board.dts. An example of this is +jh7100-beaglev-starlight.dts. Often many boards are variations on a theme, and +frequently there are intermediate files, such as jh7100-common.dtsi, which sit +between the $soc.dtsi and $soc-$board.dts files, containing the descriptions of +common hardware. + +Some platforms also have System on Modules, containing an SoC, which are then +integrated into several different boards. For these platforms, $soc-$som.dtsi +and $soc-$som-$board.dts are typical. + +Directories are usually named after the vendor of the SoC at the time of its +inclusion, leading to some historical directory names in the tree. + +Validating Devicetree Files +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +``make dtbs_check`` can be used to validate that devicetree files are compliant +with the dt-bindings that describe the ABI. Please read the section +"Running checks" of Documentation/devicetree/bindings/writing-schema.rst for +more information on the validation of devicetrees. + +For new platforms, or additions to existing ones, ``make dtbs_check`` should not +add any new warnings. For RISC-V, as it has the advantage of being a newer +architecture, ``make dtbs_check W=1`` is required to not add any new warnings. +If in any doubt about a devicetree change, reach out to the devicetree +maintainers. + +Branches and Pull Requests +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Just as the main SoC tree has several branches, it is expected that +submaintainers will do the same. Driver, defconfig and devicetree changes should +all be split into separate branches and appear in separate pull requests to the +SoC maintainers. Each branch should be usable by itself and avoid +regressions that originate from dependencies on other branches. + +Small sets of patches can also be sent as separate emails to soc@kernel.org, +grouped into the same categories. + +If changes do not fit into the normal patterns, there can be additional +top-level branches, e.g. for a treewide rework, or the addition of new SoC +platforms including dts files and drivers. + +Branches with a lot of changes can benefit from getting split up into separate +topics branches, even if they end up getting merged into the same branch of the +SoC tree. An example here would be one branch for devicetree warning fixes, one +for a rework and one for newly added boards. + +Another common way to split up changes is to send an early pull request with the +majority of the changes at some point between rc1 and rc4, following up with one +or more smaller pull requests towards the end of the cycle that can add late +changes or address problems identified while testing the first set. + +While there is no cut-off time for late pull requests, it helps to only send +small branches as time gets closer to the merge window. + +Pull requests for bugfixes for the current release can be sent at any time, but +again having multiple smaller branches is better than trying to combine too many +patches into one pull request. + +The subject line of a pull request should begin with "[GIT PULL]" and made using +a signed tag, rather than a branch. This tag should contain a short description +summarising the changes in the pull request. For more detail on sending pull +requests, please see Documentation/maintainer/pull-requests.rst. diff --git a/Documentation/process/maintainer-tip.rst b/Documentation/process/maintainer-tip.rst index 178c95fd17dcaded7f5d598987307d01b9eaa165..08dd0f804410b6dde4635c77ed930b70e57c8cac 100644 --- a/Documentation/process/maintainer-tip.rst +++ b/Documentation/process/maintainer-tip.rst @@ -421,6 +421,9 @@ allowing themselves a breath. Please respect that. The release candidate -rc1 is the starting point for new patches to be applied which are targeted for the next merge window. +So called _urgent_ branches will be merged into mainline during the +stabilization phase of each release. + Git ^^^ @@ -452,6 +455,8 @@ and can be added to an existing kernel config by running: Some of these options are x86-specific and can be left out when testing on other architectures. +.. _maintainer-tip-coding-style: + Coding style notes ------------------ diff --git a/Documentation/process/submitting-patches.rst b/Documentation/process/submitting-patches.rst index 486875fd73c0502bf10c04de6b4bd8748523d23f..efac910e26590e8f8677865a87edf2c3b77c8f35 100644 --- a/Documentation/process/submitting-patches.rst +++ b/Documentation/process/submitting-patches.rst @@ -331,6 +331,31 @@ explaining difference against previous submission (see See Documentation/process/email-clients.rst for recommendations on email clients and mailing list etiquette. +.. _interleaved_replies: + +Use trimmed interleaved replies in email discussions +---------------------------------------------------- +Top-posting is strongly discouraged in Linux kernel development +discussions. Interleaved (or "inline") replies make conversations much +easier to follow. For more details see: +https://en.wikipedia.org/wiki/Posting_style#Interleaved_style + +As is frequently quoted on the mailing list:: + + A: http://en.wikipedia.org/wiki/Top_post + Q: Were do I find info about this thing called top-posting? + A: Because it messes up the order in which people normally read text. + Q: Why is top-posting such a bad thing? + A: Top-posting. + Q: What is the most annoying thing in e-mail? + +Similarly, please trim all unneeded quotations that aren't relevant +to your reply. This makes responses easier to find, and saves time and +space. For more details see: http://daringfireball.net/2007/07/on_top :: + + A: No. + Q: Should I include quotations after my reply? + .. _resend_reminders: Don't get discouraged - or impatient diff --git a/Documentation/riscv/acpi.rst b/Documentation/riscv/acpi.rst new file mode 100644 index 0000000000000000000000000000000000000000..9870a282815b2f8840b002c094512c6244e36b65 --- /dev/null +++ b/Documentation/riscv/acpi.rst @@ -0,0 +1,10 @@ +.. SPDX-License-Identifier: GPL-2.0 + +============== +ACPI on RISC-V +============== + +The ISA string parsing rules for ACPI are defined by `Version ASCIIDOC +Conversion, 12/2022 of the RISC-V specifications, as defined by tag +"riscv-isa-release-1239329-2023-05-23" (commit 1239329 +) `_ diff --git a/Documentation/riscv/hwprobe.rst b/Documentation/riscv/hwprobe.rst index 9f0dd62dcb5db66536c1b7272ae73be45888e2b6..933c715065d6f37757818523f1772b6edbd0708c 100644 --- a/Documentation/riscv/hwprobe.rst +++ b/Documentation/riscv/hwprobe.rst @@ -49,7 +49,7 @@ The following keys are defined: privileged ISA, with the following known exceptions (more exceptions may be added, but only if it can be demonstrated that the user ABI is not broken): - * The :fence.i: instruction cannot be directly executed by userspace + * The ``fence.i`` instruction cannot be directly executed by userspace programs (it may still be executed in userspace via a kernel-controlled mechanism such as the vDSO). @@ -64,6 +64,19 @@ The following keys are defined: * :c:macro:`RISCV_HWPROBE_IMA_C`: The C extension is supported, as defined by version 2.2 of the RISC-V ISA manual. + * :c:macro:`RISCV_HWPROBE_IMA_V`: The V extension is supported, as defined by + version 1.0 of the RISC-V Vector extension manual. + + * :c:macro:`RISCV_HWPROBE_EXT_ZBA`: The Zba address generation extension is + supported, as defined in version 1.0 of the Bit-Manipulation ISA + extensions. + + * :c:macro:`RISCV_HWPROBE_EXT_ZBB`: The Zbb extension is supported, as defined + in version 1.0 of the Bit-Manipulation ISA extensions. + + * :c:macro:`RISCV_HWPROBE_EXT_ZBS`: The Zbs extension is supported, as defined + in version 1.0 of the Bit-Manipulation ISA extensions. + * :c:macro:`RISCV_HWPROBE_KEY_CPUPERF_0`: A bitmask that contains performance information about the selected set of processors. diff --git a/Documentation/riscv/index.rst b/Documentation/riscv/index.rst index 175a91db0200e864ad4d81421cb4de9f67ae9a33..81cf6e616476a2355ff6b3b3f5e8bd35d527e717 100644 --- a/Documentation/riscv/index.rst +++ b/Documentation/riscv/index.rst @@ -5,11 +5,13 @@ RISC-V architecture .. toctree:: :maxdepth: 1 + acpi boot-image-header vm-layout hwprobe patch-acceptance uabi + vector features diff --git a/Documentation/riscv/vector.rst b/Documentation/riscv/vector.rst new file mode 100644 index 0000000000000000000000000000000000000000..165b7ed0ac4f1cd45e751154826db1426d992ab5 --- /dev/null +++ b/Documentation/riscv/vector.rst @@ -0,0 +1,140 @@ +.. SPDX-License-Identifier: GPL-2.0 + +========================================= +Vector Extension Support for RISC-V Linux +========================================= + +This document briefly outlines the interface provided to userspace by Linux in +order to support the use of the RISC-V Vector Extension. + +1. prctl() Interface +--------------------- + +Two new prctl() calls are added to allow programs to manage the enablement +status for the use of Vector in userspace. The intended usage guideline for +these interfaces is to give init systems a way to modify the availability of V +for processes running under its domain. Calling thess interfaces is not +recommended in libraries routines because libraries should not override policies +configured from the parant process. Also, users must noted that these interfaces +are not portable to non-Linux, nor non-RISC-V environments, so it is discourage +to use in a portable code. To get the availability of V in an ELF program, +please read :c:macro:`COMPAT_HWCAP_ISA_V` bit of :c:macro:`ELF_HWCAP` in the +auxiliary vector. + +* prctl(PR_RISCV_V_SET_CONTROL, unsigned long arg) + + Sets the Vector enablement status of the calling thread, where the control + argument consists of two 2-bit enablement statuses and a bit for inheritance + mode. Other threads of the calling process are unaffected. + + Enablement status is a tri-state value each occupying 2-bit of space in + the control argument: + + * :c:macro:`PR_RISCV_V_VSTATE_CTRL_DEFAULT`: Use the system-wide default + enablement status on execve(). The system-wide default setting can be + controlled via sysctl interface (see sysctl section below). + + * :c:macro:`PR_RISCV_V_VSTATE_CTRL_ON`: Allow Vector to be run for the + thread. + + * :c:macro:`PR_RISCV_V_VSTATE_CTRL_OFF`: Disallow Vector. Executing Vector + instructions under such condition will trap and casuse the termination of the thread. + + arg: The control argument is a 5-bit value consisting of 3 parts, and + accessed by 3 masks respectively. + + The 3 masks, PR_RISCV_V_VSTATE_CTRL_CUR_MASK, + PR_RISCV_V_VSTATE_CTRL_NEXT_MASK, and PR_RISCV_V_VSTATE_CTRL_INHERIT + represents bit[1:0], bit[3:2], and bit[4]. bit[1:0] accounts for the + enablement status of current thread, and the setting at bit[3:2] takes place + at next execve(). bit[4] defines the inheritance mode of the setting in + bit[3:2]. + + * :c:macro:`PR_RISCV_V_VSTATE_CTRL_CUR_MASK`: bit[1:0]: Account for the + Vector enablement status for the calling thread. The calling thread is + not able to turn off Vector once it has been enabled. The prctl() call + fails with EPERM if the value in this mask is PR_RISCV_V_VSTATE_CTRL_OFF + but the current enablement status is not off. Setting + PR_RISCV_V_VSTATE_CTRL_DEFAULT here takes no effect but to set back + the original enablement status. + + * :c:macro:`PR_RISCV_V_VSTATE_CTRL_NEXT_MASK`: bit[3:2]: Account for the + Vector enablement setting for the calling thread at the next execve() + system call. If PR_RISCV_V_VSTATE_CTRL_DEFAULT is used in this mask, + then the enablement status will be decided by the system-wide + enablement status when execve() happen. + + * :c:macro:`PR_RISCV_V_VSTATE_CTRL_INHERIT`: bit[4]: the inheritance + mode for the setting at PR_RISCV_V_VSTATE_CTRL_NEXT_MASK. If the bit + is set then the following execve() will not clear the setting in both + PR_RISCV_V_VSTATE_CTRL_NEXT_MASK and PR_RISCV_V_VSTATE_CTRL_INHERIT. + This setting persists across changes in the system-wide default value. + + Return value: + * 0 on success; + * EINVAL: Vector not supported, invalid enablement status for current or + next mask; + * EPERM: Turning off Vector in PR_RISCV_V_VSTATE_CTRL_CUR_MASK if Vector + was enabled for the calling thread. + + On success: + * A valid setting for PR_RISCV_V_VSTATE_CTRL_CUR_MASK takes place + immediately. The enablement status specified in + PR_RISCV_V_VSTATE_CTRL_NEXT_MASK happens at the next execve() call, or + all following execve() calls if PR_RISCV_V_VSTATE_CTRL_INHERIT bit is + set. + * Every successful call overwrites a previous setting for the calling + thread. + +* prctl(PR_RISCV_V_GET_CONTROL) + + Gets the same Vector enablement status for the calling thread. Setting for + next execve() call and the inheritance bit are all OR-ed together. + + Note that ELF programs are able to get the availability of V for itself by + reading :c:macro:`COMPAT_HWCAP_ISA_V` bit of :c:macro:`ELF_HWCAP` in the + auxiliary vector. + + Return value: + * a nonnegative value on success; + * EINVAL: Vector not supported. + +2. System runtime configuration (sysctl) +----------------------------------------- + +To mitigate the ABI impact of expansion of the signal stack, a +policy mechanism is provided to the administrators, distro maintainers, and +developers to control the default Vector enablement status for userspace +processes in form of sysctl knob: + +* /proc/sys/abi/riscv_v_default_allow + + Writing the text representation of 0 or 1 to this file sets the default + system enablement status for new starting userspace programs. Valid values + are: + + * 0: Do not allow Vector code to be executed as the default for new processes. + * 1: Allow Vector code to be executed as the default for new processes. + + Reading this file returns the current system default enablement status. + + At every execve() call, a new enablement status of the new process is set to + the system default, unless: + + * PR_RISCV_V_VSTATE_CTRL_INHERIT is set for the calling process, and the + setting in PR_RISCV_V_VSTATE_CTRL_NEXT_MASK is not + PR_RISCV_V_VSTATE_CTRL_DEFAULT. Or, + + * The setting in PR_RISCV_V_VSTATE_CTRL_NEXT_MASK is not + PR_RISCV_V_VSTATE_CTRL_DEFAULT. + + Modifying the system default enablement status does not affect the enablement + status of any existing process of thread that do not make an execve() call. + +3. Vector Register State Across System Calls +--------------------------------------------- + +As indicated by version 1.0 of the V extension [1], vector registers are +clobbered by system calls. + +1: https://github.com/riscv/riscv-v-spec/blob/master/calling-convention.adoc diff --git a/Documentation/rust/quick-start.rst b/Documentation/rust/quick-start.rst index 13b7744b1e2753692c0b9c99ffecd3b663bda575..a8931512ed98986ad188c1601404c0de0d0b4065 100644 --- a/Documentation/rust/quick-start.rst +++ b/Documentation/rust/quick-start.rst @@ -38,9 +38,9 @@ and run:: rustup override set $(scripts/min-tool-version.sh rustc) -Otherwise, fetch a standalone installer or install ``rustup`` from: +Otherwise, fetch a standalone installer from: - https://www.rust-lang.org + https://forge.rust-lang.org/infra/other-installation-methods.html#standalone Rust standard library source diff --git a/Documentation/scheduler/sched-deadline.rst b/Documentation/scheduler/sched-deadline.rst index 9d9be52f221a5a165bb206e6c3e6456c6b6916fd..9fe4846079bbe0e0cb1273e969cf4cd233b41d5b 100644 --- a/Documentation/scheduler/sched-deadline.rst +++ b/Documentation/scheduler/sched-deadline.rst @@ -203,12 +203,15 @@ Deadline Task Scheduling - Total bandwidth (this_bw): this is the sum of all tasks "belonging" to the runqueue, including the tasks in Inactive state. + - Maximum usable bandwidth (max_bw): This is the maximum bandwidth usable by + deadline tasks and is currently set to the RT capacity. + The algorithm reclaims the bandwidth of the tasks in Inactive state. It does so by decrementing the runtime of the executing task Ti at a pace equal to - dq = -max{ Ui / Umax, (1 - Uinact - Uextra) } dt + dq = -(max{ Ui, (Umax - Uinact - Uextra) } / Umax) dt where: diff --git a/Documentation/scsi/arcmsr_spec.rst b/Documentation/scsi/arcmsr_spec.rst index 83dd53bcff78428b59bc755d32effbfe46711ca1..792c731b65708e6a510360630df85104a5101b97 100644 --- a/Documentation/scsi/arcmsr_spec.rst +++ b/Documentation/scsi/arcmsr_spec.rst @@ -1,3 +1,4 @@ +=================== ARECA FIRMWARE SPEC =================== diff --git a/Documentation/scsi/dc395x.rst b/Documentation/scsi/dc395x.rst index d779e782b1cbe1845c214ed518bfbd30b728f798..d92947c175a52f2208fce723e02ff94cb7ed24a5 100644 --- a/Documentation/scsi/dc395x.rst +++ b/Documentation/scsi/dc395x.rst @@ -1,8 +1,8 @@ .. SPDX-License-Identifier: GPL-2.0 -====================================== -README file for the dc395x SCSI driver -====================================== +================== +dc395x SCSI driver +================== Status ------ @@ -11,13 +11,10 @@ be safe to use. Testing with hard disks has not been done to any great degree and caution should be exercised if you want to attempt to use this driver with hard disks. -This is a 2.5 only driver. For a 2.4 driver please see the original -driver (which this driver started from) at -http://www.garloff.de/kurt/linux/dc395/ - -Problems, questions and patches should be submitted to the mailing -list. Details on the list, including archives, are available at -http://lists.twibble.org/mailman/listinfo/dc395x/ +This driver is evolved from `the original 2.4 driver +`_. +Problems, questions and patches should be submitted to the `Linux SCSI +mailing list `_. Parameters ---------- diff --git a/Documentation/scsi/g_NCR5380.rst b/Documentation/scsi/g_NCR5380.rst index a282059fec43c4a0349bc32847c4031cf755576d..b250c24fc760c79ee52b9569ac4de77b511d19ae 100644 --- a/Documentation/scsi/g_NCR5380.rst +++ b/Documentation/scsi/g_NCR5380.rst @@ -1,9 +1,9 @@ .. SPDX-License-Identifier: GPL-2.0 .. include:: -========================================== -README file for the Linux g_NCR5380 driver -========================================== +================ +g_NCR5380 driver +================ Copyright |copy| 1993 Drew Eckhard diff --git a/Documentation/scsi/index.rst b/Documentation/scsi/index.rst index 919f3edfe1bf979ff309b14d24017b18ccfdf741..f15a0f348ae4648eb6daccee0d47ee8cbdc8018a 100644 --- a/Documentation/scsi/index.rst +++ b/Documentation/scsi/index.rst @@ -4,6 +4,38 @@ SCSI Subsystem ============== +.. toctree:: + :maxdepth: 1 + +Introduction +============ + +.. toctree:: + :maxdepth: 1 + + scsi + +SCSI driver APIs +================ + +.. toctree:: + :maxdepth: 1 + + scsi_mid_low_api + scsi_eh + +SCSI driver parameters +====================== + +.. toctree:: + :maxdepth: 1 + + scsi-parameters + link_power_management_policy + +SCSI host adapter drivers +========================= + .. toctree:: :maxdepth: 1 @@ -25,7 +57,6 @@ SCSI Subsystem hpsa hptiop libsas - link_power_management_policy lpfc megaraid ncr53c8xx @@ -33,12 +64,8 @@ SCSI Subsystem ppa qlogicfas scsi-changer - scsi_eh scsi_fc_transport scsi-generic - scsi_mid_low_api - scsi-parameters - scsi sd-parameters smartpqi st diff --git a/Documentation/scsi/megaraid.rst b/Documentation/scsi/megaraid.rst index 22b75a86ba7205e1ff10224334b13143e0985851..10a6b05fc7c496f639d04da6f082472cc62291b9 100644 --- a/Documentation/scsi/megaraid.rst +++ b/Documentation/scsi/megaraid.rst @@ -1,8 +1,8 @@ .. SPDX-License-Identifier: GPL-2.0 -========================== -Notes on Management Module -========================== +================================= +Megaraid Common Management Module +================================= Overview -------- diff --git a/Documentation/scsi/ncr53c8xx.rst b/Documentation/scsi/ncr53c8xx.rst index 1c79e08ec96497342bf4ffe1cc5e5ffd14e5c07e..fd8d26dc5dab96e5f1006d788d7228f04571336f 100644 --- a/Documentation/scsi/ncr53c8xx.rst +++ b/Documentation/scsi/ncr53c8xx.rst @@ -1,8 +1,8 @@ .. SPDX-License-Identifier: GPL-2.0 -================================================= -The Linux NCR53C8XX/SYM53C8XX drivers README file -================================================= +=========================== +NCR53C8XX/SYM53C8XX drivers +=========================== Written by Gerard Roudier diff --git a/Documentation/scsi/scsi-changer.rst b/Documentation/scsi/scsi-changer.rst index ab60e7e61a6c5729d123cef748ab7cc65743248a..5d828c7f492d4305161e07c1a39d769a50987aff 100644 --- a/Documentation/scsi/scsi-changer.rst +++ b/Documentation/scsi/scsi-changer.rst @@ -1,8 +1,8 @@ .. SPDX-License-Identifier: GPL-2.0 -======================================== -README for the SCSI media changer driver -======================================== +========================= +SCSI media changer driver +========================= This is a driver for SCSI Medium Changer devices, which are listed with "Type: Medium Changer" in /proc/scsi/scsi. diff --git a/Documentation/scsi/scsi-generic.rst b/Documentation/scsi/scsi-generic.rst index 258505e557a6361ad95af3afc6fc05c10fc0d865..b82ffe4d8892a442847ceda77798390a0450ac90 100644 --- a/Documentation/scsi/scsi-generic.rst +++ b/Documentation/scsi/scsi-generic.rst @@ -1,15 +1,15 @@ .. SPDX-License-Identifier: GPL-2.0 -======================================= -Notes on Linux SCSI Generic (sg) driver -======================================= +======================== +SCSI Generic (sg) driver +======================== 20020126 Introduction ============ The SCSI Generic driver (sg) is one of the four "high level" SCSI device -drivers along with sd, st and sr (disk, tape and CDROM respectively). Sg +drivers along with sd, st and sr (disk, tape and CD-ROM respectively). Sg is more generalized (but lower level) than its siblings and tends to be used on SCSI devices that don't fit into the already serviced categories. Thus sg is used for scanners, CD writers and reading audio CDs digitally @@ -22,7 +22,7 @@ and examples. Major versions of the sg driver =============================== -There are three major versions of sg found in the linux kernel (lk): +There are three major versions of sg found in the Linux kernel (lk): - sg version 1 (original) from 1992 to early 1999 (lk 2.2.5) . It is based in the sg_header interface structure. - sg version 2 from lk 2.2.6 in the 2.2 series. It is based on @@ -33,34 +33,24 @@ There are three major versions of sg found in the linux kernel (lk): Sg driver documentation ======================= -The most recent documentation of the sg driver is kept at the Linux -Documentation Project's (LDP) site: +The most recent documentation of the sg driver is kept at -- http://www.tldp.org/HOWTO/SCSI-Generic-HOWTO +- https://sg.danny.cz/sg/ This describes the sg version 3 driver found in the lk 2.4 series. -The LDP renders documents in single and multiple page HTML, postscript -and pdf. This document can also be found at: +Documentation (large version) for the version 2 sg driver found in the +lk 2.2 series can be found at -- http://sg.danny.cz/sg/p/sg_v3_ho.html - -Documentation for the version 2 sg driver found in the lk 2.2 series can -be found at http://sg.danny.cz/sg/. A larger version -is at: http://sg.danny.cz/sg/p/scsi-generic_long.txt. +- https://sg.danny.cz/sg/p/scsi-generic_long.txt. The original documentation for the sg driver (prior to lk 2.2.6) can be -found at http://www.torque.net/sg/p/original/SCSI-Programming-HOWTO.txt -and in the LDP archives. +found in the LDP archives at -A changelog with brief notes can be found in the -/usr/src/linux/include/scsi/sg.h file. Note that the glibc maintainers copy -and edit this file (removing its changelog for example) before placing it -in /usr/include/scsi/sg.h . Driver debugging information and other notes -can be found at the top of the /usr/src/linux/drivers/scsi/sg.c file. +- https://tldp.org/HOWTO/archived/SCSI-Programming-HOWTO/index.html A more general description of the Linux SCSI subsystem of which sg is a -part can be found at http://www.tldp.org/HOWTO/SCSI-2.4-HOWTO . +part can be found at https://www.tldp.org/HOWTO/SCSI-2.4-HOWTO . Example code and utilities @@ -73,8 +63,8 @@ There are two packages of sg utilities: and earlier ========= ========================================================== -Both packages will work in the lk 2.4 series however sg3_utils offers more -capabilities. They can be found at: http://sg.danny.cz/sg/sg3_utils.html and +Both packages will work in the lk 2.4 series. However, sg3_utils offers more +capabilities. They can be found at: https://sg.danny.cz/sg/sg3_utils.html and freecode.com Another approach is to look at the applications that use the sg driver. @@ -83,7 +73,7 @@ These include cdrecord, cdparanoia, SANE and cdrdao. Mapping of Linux kernel versions to sg driver versions ====================================================== -Here is a list of linux kernels in the 2.4 series that had new version +Here is a list of Linux kernels in the 2.4 series that had the new version of the sg driver: - lk 2.4.0 : sg version 3.1.17 @@ -92,10 +82,10 @@ of the sg driver: - lk 2.4.17 : sg version 3.1.22 .. [#] There were 3 changes to sg version 3.1.20 by third parties in the - next six linux kernel versions. + next six Linux kernel versions. -For reference here is a list of linux kernels in the 2.2 series that had -new version of the sg driver: +For reference here is a list of Linux kernels in the 2.2 series that had +the new version of the sg driver: - lk 2.2.0 : original sg version [with no version number] - lk 2.2.6 : sg version 2.1.31 @@ -106,9 +96,8 @@ new version of the sg driver: - lk 2.2.17 : sg version 2.1.39 - lk 2.2.20 : sg version 2.1.40 -The lk 2.5 development series has recently commenced and it currently -contains sg version 3.5.23 which is functionally equivalent to sg -version 3.1.22 found in lk 2.4.17. +The lk 2.5 development series currently contains sg version 3.5.23 +which is functionally equivalent to sg version 3.1.22 found in lk 2.4.17. Douglas Gilbert diff --git a/Documentation/scsi/scsi.rst b/Documentation/scsi/scsi.rst index 276918eb4d7442bae0397643807eb19021b80ec4..8556846b9f63d13d562c95bf1abed80ce5d4dce7 100644 --- a/Documentation/scsi/scsi.rst +++ b/Documentation/scsi/scsi.rst @@ -6,30 +6,28 @@ SCSI subsystem documentation The Linux Documentation Project (LDP) maintains a document describing the SCSI subsystem in the Linux kernel (lk) 2.4 series. See: -http://www.tldp.org/HOWTO/SCSI-2.4-HOWTO . The LDP has single +https://www.tldp.org/HOWTO/SCSI-2.4-HOWTO . The LDP has single and multiple page HTML renderings as well as postscript and pdf. -It can also be found at: -http://web.archive.org/web/%2E/http://www.torque.net/scsi/SCSI-2.4-HOWTO Notes on using modules in the SCSI subsystem ============================================ -The scsi support in the linux kernel can be modularized in a number of +The SCSI support in the Linux kernel can be modularized in a number of different ways depending upon the needs of the end user. To understand your options, we should first define a few terms. -The scsi-core (also known as the "mid level") contains the core of scsi -support. Without it you can do nothing with any of the other scsi drivers. -The scsi core support can be a module (scsi_mod.o), or it can be built into -the kernel. If the core is a module, it must be the first scsi module +The scsi-core (also known as the "mid level") contains the core of SCSI +support. Without it you can do nothing with any of the other SCSI drivers. +The SCSI core support can be a module (scsi_mod.o), or it can be built into +the kernel. If the core is a module, it must be the first SCSI module loaded, and if you unload the modules, it will have to be the last one -unloaded. In practice the modprobe and rmmod commands (and "autoclean") +unloaded. In practice the modprobe and rmmod commands will enforce the correct ordering of loading and unloading modules in the SCSI subsystem. The individual upper and lower level drivers can be loaded in any order -once the scsi core is present in the kernel (either compiled in or loaded -as a module). The disk driver (sd_mod.o), cdrom driver (sr_mod.o), -tape driver [1]_ (st.o) and scsi generics driver (sg.o) represent the upper +once the SCSI core is present in the kernel (either compiled in or loaded +as a module). The disk driver (sd_mod.o), CD-ROM driver (sr_mod.o), +tape driver [1]_ (st.o) and SCSI generics driver (sg.o) represent the upper level drivers to support the various assorted devices which can be controlled. You can for example load the tape driver to use the tape drive, and then unload it once you have no further need for the driver (and release @@ -44,4 +42,3 @@ built into the kernel. .. [1] There is a variant of the st driver for controlling OnStream tape devices. Its module name is osst.o . - diff --git a/Documentation/scsi/scsi_fc_transport.rst b/Documentation/scsi/scsi_fc_transport.rst index 176c1862cb9bc96cf9e00463f9fc98afe03d955f..e3ddcfb7f8fd3da573e1df94977f5e4f3c9afb57 100644 --- a/Documentation/scsi/scsi_fc_transport.rst +++ b/Documentation/scsi/scsi_fc_transport.rst @@ -1,8 +1,8 @@ .. SPDX-License-Identifier: GPL-2.0 -================ -SCSI FC Tansport -================ +================= +SCSI FC Transport +================= Date: 11/18/2008 @@ -556,5 +556,5 @@ The following people have contributed to this document: James Smart -james.smart@emulex.com +james.smart@broadcom.com diff --git a/Documentation/scsi/sym53c8xx_2.rst b/Documentation/scsi/sym53c8xx_2.rst index 004f1a750e7d5166200a54f0567cc7335728059c..4eb047921dceda7116b0725edbdfcdcd7a867dc6 100644 --- a/Documentation/scsi/sym53c8xx_2.rst +++ b/Documentation/scsi/sym53c8xx_2.rst @@ -1,8 +1,8 @@ .. SPDX-License-Identifier: GPL-2.0 -========================================= -The Linux SYM-2 driver documentation file -========================================= +============ +SYM-2 driver +============ Written by Gerard Roudier diff --git a/Documentation/sound/cards/audigy-mixer.rst b/Documentation/sound/cards/audigy-mixer.rst index aa176451d5b58cfc8f1b44dadb6bdeabf0ecd4a9..ea66b50a2b035e50528f716de2d47ad18861b2fb 100644 --- a/Documentation/sound/cards/audigy-mixer.rst +++ b/Documentation/sound/cards/audigy-mixer.rst @@ -227,7 +227,7 @@ PCM stream related controls name='EMU10K1 PCM Volume',index 0-31 ------------------------------------ -Channel volume attenuation in range 0-0xffff. The maximum value (no +Channel volume attenuation in range 0-0x1fffd. The middle value (no attenuation) is default. The channel mapping for three values is as follows: @@ -240,30 +240,30 @@ name='EMU10K1 PCM Send Routing',index 0-31 This control specifies the destination - FX-bus accumulators. There are 24 values in this mapping: -* 0 - mono, A destination (FX-bus 0-63), default 0 -* 1 - mono, B destination (FX-bus 0-63), default 1 -* 2 - mono, C destination (FX-bus 0-63), default 2 -* 3 - mono, D destination (FX-bus 0-63), default 3 -* 4 - mono, E destination (FX-bus 0-63), default 0 -* 5 - mono, F destination (FX-bus 0-63), default 0 -* 6 - mono, G destination (FX-bus 0-63), default 0 -* 7 - mono, H destination (FX-bus 0-63), default 0 -* 8 - left, A destination (FX-bus 0-63), default 0 -* 9 - left, B destination (FX-bus 0-63), default 1 +* 0 - mono, A destination (FX-bus 0-63), default 0 +* 1 - mono, B destination (FX-bus 0-63), default 1 +* 2 - mono, C destination (FX-bus 0-63), default 2 +* 3 - mono, D destination (FX-bus 0-63), default 3 +* 4 - mono, E destination (FX-bus 0-63), default 4 +* 5 - mono, F destination (FX-bus 0-63), default 5 +* 6 - mono, G destination (FX-bus 0-63), default 6 +* 7 - mono, H destination (FX-bus 0-63), default 7 +* 8 - left, A destination (FX-bus 0-63), default 0 +* 9 - left, B destination (FX-bus 0-63), default 1 * 10 - left, C destination (FX-bus 0-63), default 2 * 11 - left, D destination (FX-bus 0-63), default 3 -* 12 - left, E destination (FX-bus 0-63), default 0 -* 13 - left, F destination (FX-bus 0-63), default 0 -* 14 - left, G destination (FX-bus 0-63), default 0 -* 15 - left, H destination (FX-bus 0-63), default 0 +* 12 - left, E destination (FX-bus 0-63), default 4 +* 13 - left, F destination (FX-bus 0-63), default 5 +* 14 - left, G destination (FX-bus 0-63), default 6 +* 15 - left, H destination (FX-bus 0-63), default 7 * 16 - right, A destination (FX-bus 0-63), default 0 * 17 - right, B destination (FX-bus 0-63), default 1 * 18 - right, C destination (FX-bus 0-63), default 2 * 19 - right, D destination (FX-bus 0-63), default 3 -* 20 - right, E destination (FX-bus 0-63), default 0 -* 21 - right, F destination (FX-bus 0-63), default 0 -* 22 - right, G destination (FX-bus 0-63), default 0 -* 23 - right, H destination (FX-bus 0-63), default 0 +* 20 - right, E destination (FX-bus 0-63), default 4 +* 21 - right, F destination (FX-bus 0-63), default 5 +* 22 - right, G destination (FX-bus 0-63), default 6 +* 23 - right, H destination (FX-bus 0-63), default 7 Don't forget that it's illegal to assign a channel to the same FX-bus accumulator more than once (it means 0=0 && 1=0 is an invalid combination). diff --git a/Documentation/sound/cards/index.rst b/Documentation/sound/cards/index.rst index c016f8c3b88bf00944684edeb2d06dc5d365d74f..49c1f2f688f852b25cb3be39082e6b97f847846b 100644 --- a/Documentation/sound/cards/index.rst +++ b/Documentation/sound/cards/index.rst @@ -17,3 +17,4 @@ Card-Specific Information hdspm serial-u16550 img-spdif-in + pcmtest diff --git a/Documentation/sound/cards/pcmtest.rst b/Documentation/sound/cards/pcmtest.rst new file mode 100644 index 0000000000000000000000000000000000000000..e163522f32055abb820dafdc41698ed5ae86dcbe --- /dev/null +++ b/Documentation/sound/cards/pcmtest.rst @@ -0,0 +1,120 @@ +.. SPDX-License-Identifier: GPL-2.0 + +The Virtual PCM Test Driver +=========================== + +The Virtual PCM Test Driver emulates a generic PCM device, and can be used for +testing/fuzzing of the userspace ALSA applications, as well as for testing/fuzzing of +the PCM middle layer. Additionally, it can be used for simulating hard to reproduce +problems with PCM devices. + +What can this driver do? +~~~~~~~~~~~~~~~~~~~~~~~~ + +At this moment the driver can do the following things: + * Simulate both capture and playback processes + * Generate random or pattern-based capturing data + * Inject delays into the playback and capturing processes + * Inject errors during the PCM callbacks + +It supports up to 8 substreams and 4 channels. Also it supports both interleaved and +non-interleaved access modes. + +Also, this driver can check the playback stream for containing the predefined pattern, +which is used in the corresponding selftest (alsa/pcmtest-test.sh) to check the PCM middle +layer data transferring functionality. Additionally, this driver redefines the default +RESET ioctl, and the selftest covers this PCM API functionality as well. + +Configuration +------------- + +The driver has several parameters besides the common ALSA module parameters: + + * fill_mode (bool) - Buffer fill mode (see below) + * inject_delay (int) + * inject_hwpars_err (bool) + * inject_prepare_err (bool) + * inject_trigger_err (bool) + + +Capture Data Generation +----------------------- + +The driver has two modes of data generation: the first (0 in the fill_mode parameter) +means random data generation, the second (1 in the fill_mode) - pattern-based +data generation. Let's look at the second mode. + +First of all, you may want to specify the pattern for data generation. You can do it +by writing the pattern to the debugfs file. There are pattern buffer debugfs entries +for each channel, as well as entries which contain the pattern buffer length. + + * /sys/kernel/debug/pcmtest/fill_pattern[0-3] + * /sys/kernel/debug/pcmtest/fill_pattern[0-3]_len + +To set the pattern for the channel 0 you can execute the following command: + +.. code-block:: bash + + echo -n mycoolpattern > /sys/kernel/debug/pcmtest/fill_pattern0 + +Then, after every capture action performed on the 'pcmtest' device the buffer for the +channel 0 will contain 'mycoolpatternmycoolpatternmycoolpatternmy...'. + +The pattern itself can be up to 4096 bytes long. + +Delay injection +--------------- + +The driver has 'inject_delay' parameter, which has very self-descriptive name and +can be used for time delay/speedup simulations. The parameter has integer type, and +it means the delay added between module's internal timer ticks. + +If the 'inject_delay' value is positive, the buffer will be filled slower, if it is +negative - faster. You can try it yourself by starting a recording in any +audiorecording application (like Audacity) and selecting the 'pcmtest' device as a +source. + +This parameter can be also used for generating a huge amount of sound data in a very +short period of time (with the negative 'inject_delay' value). + +Errors injection +---------------- + +This module can be used for injecting errors into the PCM communication process. This +action can help you to figure out how the userspace ALSA program behaves under unusual +circumstances. + +For example, you can make all 'hw_params' PCM callback calls return EBUSY error by +writing '1' to the 'inject_hwpars_err' module parameter: + +.. code-block:: bash + + echo 1 > /sys/module/snd_pcmtest/parameters/inject_hwpars_err + +Errors can be injected into the following PCM callbacks: + + * hw_params (EBUSY) + * prepare (EINVAL) + * trigger (EINVAL) + +Playback test +------------- + +This driver can be also used for the playback functionality testing - every time you +write the playback data to the 'pcmtest' PCM device and close it, the driver checks the +buffer for containing the looped pattern (which is specified in the fill_pattern +debugfs file for each channel). If the playback buffer content represents the looped +pattern, 'pc_test' debugfs entry is set into '1'. Otherwise, the driver sets it to '0'. + +ioctl redefinition test +----------------------- + +The driver redefines the 'reset' ioctl, which is default for all PCM devices. To test +this functionality, we can trigger the reset ioctl and check the 'ioctl_test' debugfs +entry: + +.. code-block:: bash + + cat /sys/kernel/debug/pcmtest/ioctl_test + +If the ioctl is triggered successfully, this file will contain '1', and '0' otherwise. diff --git a/Documentation/sound/cards/sb-live-mixer.rst b/Documentation/sound/cards/sb-live-mixer.rst index 819886634400f22f1cf1336fa1ef578cc5ed2e91..4dd9bfe01bd87b841f938029ff82a9ea321be355 100644 --- a/Documentation/sound/cards/sb-live-mixer.rst +++ b/Documentation/sound/cards/sb-live-mixer.rst @@ -258,7 +258,7 @@ PCM stream related controls ``name='EMU10K1 PCM Volume',index 0-31`` ---------------------------------------- -Channel volume attenuation in range 0-0xffff. The maximum value (no +Channel volume attenuation in range 0-0x1fffd. The middle value (no attenuation) is default. The channel mapping for three values is as follows: diff --git a/Documentation/sound/designs/compress-offload.rst b/Documentation/sound/designs/compress-offload.rst index 935f325dbc773a8b63edaf84f86e05315a1e315d..655624f770921ba0445251e89a9b17be3f9e5764 100644 --- a/Documentation/sound/designs/compress-offload.rst +++ b/Documentation/sound/designs/compress-offload.rst @@ -268,11 +268,12 @@ with setting of meta_data and signalling for next track :: | | | V | +----------+ - | | | - | |NEXT_TRACK| - | | | - | +----------+ - | | + | compr_set_params() | | + | +-----------|NEXT_TRACK| + | | | | + | | +--+-------+ + | | | | + | +--------------+ | | | | | compr_partial_drain() | | diff --git a/Documentation/sound/designs/index.rst b/Documentation/sound/designs/index.rst index 1eb08e7bae5224b9b0d36a612dc35c8c74b5ea4d..b79db9ad87325a70d179197fa22272929ba13a25 100644 --- a/Documentation/sound/designs/index.rst +++ b/Documentation/sound/designs/index.rst @@ -15,3 +15,4 @@ Designs and Implementations oss-emulation seq-oss jack-injection + midi-2.0 diff --git a/Documentation/sound/designs/midi-2.0.rst b/Documentation/sound/designs/midi-2.0.rst new file mode 100644 index 0000000000000000000000000000000000000000..27d0d3dea1b0a53e152879184e5ce81f7185b466 --- /dev/null +++ b/Documentation/sound/designs/midi-2.0.rst @@ -0,0 +1,378 @@ +================= +MIDI 2.0 on Linux +================= + +General +======= + +MIDI 2.0 is an extended protocol for providing higher resolutions and +more fine controls over the legacy MIDI 1.0. The fundamental changes +introduced for supporting MIDI 2.0 are: + +- Support of Universal MIDI Packet (UMP) +- Support of MIDI 2.0 protocol messages +- Transparent conversions between UMP and legacy MIDI 1.0 byte stream +- MIDI-CI for property and profile configurations + +UMP is a new container format to hold all MIDI protocol 1.0 and MIDI +2.0 protocol messages. Unlike the former byte stream, it's 32bit +aligned, and each message can be put in a single packet. UMP can send +the events up to 16 "UMP Groups", where each UMP Group contain up to +16 MIDI channels. + +MIDI 2.0 protocol is an extended protocol to achieve the higher +resolution and more controls over the old MIDI 1.0 protocol. + +MIDI-CI is a high-level protocol that can talk with the MIDI device +for the flexible profiles and configurations. It's represented in the +form of special SysEx. + +For Linux implementations, the kernel supports the UMP transport and +the encoding/decoding of MIDI protocols on UMP, while MIDI-CI is +supported in user-space over the standard SysEx. + +As of this writing, only USB MIDI device supports the UMP and Linux +2.0 natively. The UMP support itself is pretty generic, hence it +could be used by other transport layers, although it could be +implemented differently (e.g. as a ALSA sequencer client), too. + +The access to UMP devices are provided in two ways: the access via +rawmidi device and the access via ALSA sequencer API. + +ALSA sequencer API was extended to allow the payload of UMP packets. +It's allowed to connect freely between MIDI 1.0 and MIDI 2.0 sequencer +clients, and the events are converted transparently. + + +Kernel Configuration +==================== + +The following new configs are added for supporting MIDI 2.0: +`CONFIG_SND_UMP`, `CONFIG_SND_UMP_LEGACY_RAWMIDI`, +`CONFIG_SND_SEQ_UMP`, `CONFIG_SND_SEQ_UMP_CLIENT`, and +`CONFIG_SND_USB_AUDIO_MIDI_V2`. The first visible one is +`CONFIG_SND_USB_AUDIO_MIDI_V2`, and when you choose it (to set `=y`), +the core support for UMP (`CONFIG_SND_UMP`) and the sequencer binding +(`CONFIG_SND_SEQ_UMP_CLIENT`) will be automatically selected. + +Additionally, `CONFIG_SND_UMP_LEGACY_RAWMIDI=y` will enable the +support for the legacy raw MIDI device for UMP Endpoints. + + +Rawmidi Device with USB MIDI 2.0 +================================ + +When a device supports MIDI 2.0, the USB-audio driver probes and uses +the MIDI 2.0 interface (that is found always at the altset 1) as +default instead of the MIDI 1.0 interface (at altset 0). You can +switch back to the binding with the old MIDI 1.0 interface by passing +`midi2_enable=0` option to snd-usb-audio driver module, too. + +The USB audio driver tries to query the UMP Endpoint and UMP Function +Block information that are provided since UMP v1.1, and builds up the +topology based on those information. When the device is older and +doesn't respond to the new UMP inquiries, the driver falls back and +builds the topology based on Group Terminal Block (GTB) information +from the USB descriptor. Some device might be screwed up by the +unexpected UMP command; in such a case, pass `midi2_probe=0` option to +snd-usb-audio driver for skipping the UMP v1.1 inquiries. + +When the MIDI 2.0 device is probed, the kernel creates a rawmidi +device for each UMP Endpoint of the device. Its device name is +`/dev/snd/umpC*D*` and different from the standard rawmidi device name +`/dev/snd/midiC*D*` for MIDI 1.0, in order to avoid confusing the +legacy applications accessing mistakenly to UMP devices. + +You can read and write UMP packet data directly from/to this UMP +rawmidi device. For example, reading via `hexdump` like below will +show the incoming UMP packets of the card 0 device 0 in the hex +format:: + + % hexdump -C /dev/snd/umpC0D0 + 00000000 01 07 b0 20 00 07 b0 20 64 3c 90 20 64 3c 80 20 |... ... d<. d<. | + +Unlike the MIDI 1.0 byte stream, UMP is a 32bit packet, and the size +for reading or writing the device is also aligned to 32bit (which is 4 +bytes). + +The 32-bit words in the UMP packet payload are always in CPU native +endianness. Transport drivers are responsible to convert UMP words +from / to system endianness to required transport endianness / byte +order. + +When `CONFIG_SND_UMP_LEGACY_RAWMIDI` is set, the driver creates +another standard raw MIDI device additionally as `/dev/snd/midiC*D*`. +This contains 16 substreams, and each substream corresponds to a +(0-based) UMP Group. Legacy applications can access to the specified +group via each substream in MIDI 1.0 byte stream format. With the +ALSA rawmidi API, you can open the arbitrary substream, while just +opening `/dev/snd/midiC*D*` will end up with opening the first +substream. + +Each UMP Endpoint can provide the additional information, constructed +from the information inquired via UMP 1.1 Stream messages or USB MIDI +2.0 descriptors. And a UMP Endpoint may contain one or more UMP +Blocks, where UMP Block is an abstraction introduced in the ALSA UMP +implementations to represent the associations among UMP Groups. UMP +Block corresponds to Function Block in UMP 1.1 specification. When +UMP 1.1 Function Block information isn't available, it's filled +partially from Group Terminal Block (GTB) as defined in USB MIDI 2.0 +specifications. + +The information of UMP Endpoints and UMP Blocks are found in the proc +file `/proc/asound/card*/midi*`. For example:: + + % cat /proc/asound/card1/midi0 + ProtoZOA MIDI + + Type: UMP + EP Name: ProtoZOA + EP Product ID: ABCD12345678 + UMP Version: 0x0000 + Protocol Caps: 0x00000100 + Protocol: 0x00000100 + Num Blocks: 3 + + Block 0 (ProtoZOA Main) + Direction: bidirection + Active: Yes + Groups: 1-1 + Is MIDI1: No + + Block 1 (ProtoZOA Ext IN) + Direction: output + Active: Yes + Groups: 2-2 + Is MIDI1: Yes (Low Speed) + .... + +Note that `Groups` field shown in the proc file above indicates the +1-based UMP Group numbers (from-to). + +Those additional UMP Endpoint and UMP Block information can be +obtained via the new ioctls `SNDRV_UMP_IOCTL_ENDPOINT_INFO` and +`SNDRV_UMP_IOCTL_BLOCK_INFO`, respectively. + +The rawmidi name and the UMP Endpoint name are usually identical, and +in the case of USB MIDI, it's taken from `iInterface` of the +corresponding USB MIDI interface descriptor. If it's not provided, +it's copied from `iProduct` of the USB device descriptor as a +fallback. + +The Endpoint Product ID is a string field and supposed to be unique. +It's copied from `iSerialNumber` of the device for USB MIDI. + +The protocol capabilities and the actual protocol bits are defined in +`asound.h`. + + +ALSA Sequencer with USB MIDI 2.0 +================================ + +In addition to the rawmidi interfaces, ALSA sequencer interface +supports the new UMP MIDI 2.0 device, too. Now, each ALSA sequencer +client may set its MIDI version (0, 1 or 2) to declare itself being +either the legacy, UMP MIDI 1.0 or UMP MIDI 2.0 device, respectively. +The first, legacy client is the one that sends/receives the old +sequencer event as was. Meanwhile, UMP MIDI 1.0 and 2.0 clients send +and receive in the extended event record for UMP. The MIDI version is +seen in the new `midi_version` field of `snd_seq_client_info`. + +A UMP packet can be sent/received in a sequencer event embedded by +specifying the new event flag bit `SNDRV_SEQ_EVENT_UMP`. When this +flag is set, the event has 16 byte (128 bit) data payload for holding +the UMP packet. Without the `SNDRV_SEQ_EVENT_UMP` bit flag, the event +is treated as a legacy event as it was (with max 12 byte data +payload). + +With `SNDRV_SEQ_EVENT_UMP` flag set, the type field of a UMP sequencer +event is ignored (but it should be set to 0 as default). + +The type of each client can be seen in `/proc/asound/seq/clients`. +For example:: + + % cat /proc/asound/seq/clients + Client info + cur clients : 3 + .... + Client 14 : "Midi Through" [Kernel Legacy] + Port 0 : "Midi Through Port-0" (RWe-) + Client 20 : "ProtoZOA" [Kernel UMP MIDI1] + UMP Endpoint: ProtoZOA + UMP Block 0: ProtoZOA Main [Active] + Groups: 1-1 + UMP Block 1: ProtoZOA Ext IN [Active] + Groups: 2-2 + UMP Block 2: ProtoZOA Ext OUT [Active] + Groups: 3-3 + Port 0 : "MIDI 2.0" (RWeX) [In/Out] + Port 1 : "ProtoZOA Main" (RWeX) [In/Out] + Port 2 : "ProtoZOA Ext IN" (-We-) [Out] + Port 3 : "ProtoZOA Ext OUT" (R-e-) [In] + +Here you can find two types of kernel clients, "Legacy" for client 14, +and "UMP MIDI1" for client 20, which is a USB MIDI 2.0 device. +A USB MIDI 2.0 client gives always the port 0 as "MIDI 2.0" and the +rest ports from 1 for each UMP Group (e.g. port 1 for Group 1). +In this example, the device has three active groups (Main, Ext IN and +Ext OUT), and those are exposed as sequencer ports from 1 to 3. +The "MIDI 2.0" port is for a UMP Endpoint, and its difference from +other UMP Group ports is that UMP Endpoint port sends the events from +the all ports on the device ("catch-all"), while each UMP Group port +sends only the events from the given UMP Group. +Also, UMP groupless messages (such as the UMP message type 0x0f) are +sent only to the UMP Endpoint port. + +Note that, although each UMP sequencer client usually creates 16 +ports, those ports that don't belong to any UMP Blocks (or belonging +to inactive UMP Blocks) are marked as inactive, and they don't appear +in the proc outputs. In the example above, the sequencer ports from 4 +to 16 are present but not shown there. + +The proc file above shows the UMP Block information, too. The same +entry (but with more detailed information) is found in the rawmidi +proc output. + +When clients are connected between different MIDI versions, the events +are translated automatically depending on the client's version, not +only between the legacy and the UMP MIDI 1.0/2.0 types, but also +between UMP MIDI 1.0 and 2.0 types, too. For example, running +`aseqdump` program on the ProtoZOA Main port in the legacy mode will +give you the output like:: + + % aseqdump -p 20:1 + Waiting for data. Press Ctrl+C to end. + Source Event Ch Data + 20:1 Note on 0, note 60, velocity 100 + 20:1 Note off 0, note 60, velocity 100 + 20:1 Control change 0, controller 11, value 4 + +When you run `aseqdump` in MIDI 2.0 mode, it'll receive the high +precision data like:: + + % aseqdump -u 2 -p 20:1 + Waiting for data. Press Ctrl+C to end. + Source Event Ch Data + 20:1 Note on 0, note 60, velocity 0xc924, attr type = 0, data = 0x0 + 20:1 Note off 0, note 60, velocity 0xc924, attr type = 0, data = 0x0 + 20:1 Control change 0, controller 11, value 0x2000000 + +while the data is automatically converted by ALSA sequencer core. + + +Rawmidi API Extensions +====================== + +* The additional UMP Endpoint information can be obtained via the new + ioctl `SNDRV_UMP_IOCTL_ENDPOINT_INFO`. It contains the associated + card and device numbers, the bit flags, the protocols, the number of + UMP Blocks, the name string of the endpoint, etc. + + The protocols are specified in two field, the protocol capabilities + and the current protocol. Both contain the bit flags specifying the + MIDI protocol version (`SNDRV_UMP_EP_INFO_PROTO_MIDI1` or + `SNDRV_UMP_EP_INFO_PROTO_MIDI2`) in the upper byte and the jitter + reduction timestamp (`SNDRV_UMP_EP_INFO_PROTO_JRTS_TX` and + `SNDRV_UMP_EP_INFO_PROTO_JRTS_RX`) in the lower byte. + + A UMP Endpoint may contain up to 32 UMP Blocks, and the number of + the currently assigned blocks are shown in the Endpoint information. + +* Each UMP Block information can be obtained via another new ioctl + `SNDRV_UMP_IOCTL_BLOCK_INFO`. The block ID number (0-based) has to + be passed for the block to query. The received data contains the + associated the direction of the block, the first associated group ID + (0-based) and the number of groups, the name string of the block, + etc. + + The direction is either `SNDRV_UMP_DIR_INPUT`, + `SNDRV_UMP_DIR_OUTPUT` or `SNDRV_UMP_DIR_BIDIRECTION`. + +* For the device supports UMP v1.1, the UMP MIDI protocol can be + switched via "Stream Configuration Request" message (UMP type 0x0f, + status 0x05). When UMP core receives such a message, it updates the + UMP EP info and the corresponding sequencer clients as well. + + +Control API Extensions +====================== + +* The new ioctl `SNDRV_CTL_IOCTL_UMP_NEXT_DEVICE` is introduced for + querying the next UMP rawmidi device, while the existing ioctl + `SNDRV_CTL_IOCTL_RAWMIDI_NEXT_DEVICE` queries only the legacy + rawmidi devices. + + For setting the subdevice (substream number) to be opened, use the + ioctl `SNDRV_CTL_IOCTL_RAWMIDI_PREFER_SUBDEVICE` like the normal + rawmidi. + +* Two new ioctls `SNDRV_CTL_IOCTL_UMP_ENDPOINT_INFO` and + `SNDRV_CTL_IOCTL_UMP_BLOCK_INFO` provide the UMP Endpoint and UMP + Block information of the specified UMP device via ALSA control API + without opening the actual (UMP) rawmidi device. + The `card` field is ignored upon inquiry, always tied with the card + of the control interface. + + +Sequencer API Extensions +======================== + +* `midi_version` field is added to `snd_seq_client_info` to indicate + the current MIDI version (either 0, 1 or 2) of each client. + When `midi_version` is 1 or 2, the alignment of read from a UMP + sequencer client is also changed from the former 28 bytes to 32 + bytes for the extended payload. The alignment size for the write + isn't changed, but each event size may differ depending on the new + bit flag below. + +* `SNDRV_SEQ_EVENT_UMP` flag bit is added for each sequencer event + flags. When this bit flag is set, the sequencer event is extended + to have a larger payload of 16 bytes instead of the legacy 12 + bytes, and the event contains the UMP packet in the payload. + +* The new sequencer port type bit (`SNDRV_SEQ_PORT_TYPE_MIDI_UMP`) + indicates the port being UMP-capable. + +* The sequencer ports have new capability bits to indicate the + inactive ports (`SNDRV_SEQ_PORT_CAP_INACTIVE`) and the UMP Endpoint + port (`SNDRV_SEQ_PORT_CAP_UMP_ENDPOINT`). + +* The event conversion of ALSA sequencer clients can be suppressed the + new filter bit `SNDRV_SEQ_FILTER_NO_CONVERT` set to the client info. + For example, the kernel pass-through client (`snd-seq-dummy`) sets + this flag internally. + +* The port information gained the new field `direction` to indicate + the direction of the port (either `SNDRV_SEQ_PORT_DIR_INPUT`, + `SNDRV_SEQ_PORT_DIR_OUTPUT` or `SNDRV_SEQ_PORT_DIR_BIDIRECTION`). + +* Another additional field for the port information is `ump_group` + which specifies the associated UMP Group Number (1-based). + When it's non-zero, the UMP group field in the UMP packet updated + upon delivery to the specified group (corrected to be 0-based). + Each sequencer port is supposed to set this field if it's a port to + specific to a certain UMP group. + +* Each client may set the additional event filter for UMP Groups in + `group_filter` bitmap. The filter consists of bitmap from 1-based + Group numbers. For example, when the bit 1 is set, messages from + Group 1 (i.e. the very first group) are filtered and not delivered. + The bit 0 is used for filtering UMP groupless messages. + +* Two new ioctls are added for UMP-capable clients: + `SNDRV_SEQ_IOCTL_GET_CLIENT_UMP_INFO` and + `SNDRV_SEQ_IOCTL_SET_CLIENT_UMP_INFO`. They are used to get and set + either `snd_ump_endpoint_info` or `snd_ump_block_info` data + associated with the sequencer client. The USB MIDI driver provides + those information from the underlying UMP rawmidi, while a + user-space client may provide its own data via `*_SET` ioctl. + For an Endpoint data, pass 0 to the `type` field, while for a Block + data, pass the block number + 1 to the `type` field. + Setting the data for a kernel client shall result in an error. + +* With UMP 1.1, Function Block information may be changed + dynamically. When the update of Function Block is received from the + device, ALSA sequencer core changes the corresponding sequencer port + name and attributes accordingly, and notifies the changes via the + announcement to the ALSA sequencer system port, similarly like the + normal port change notification. diff --git a/Documentation/subsystem-apis.rst b/Documentation/subsystem-apis.rst index b51f38527e148122187c35ea81d1f09efab3a6d2..b67a1b65855bb6a782a58857caee81bc384fa797 100644 --- a/Documentation/subsystem-apis.rst +++ b/Documentation/subsystem-apis.rst @@ -10,6 +10,30 @@ is taken directly from the kernel source, with supplemental material added as needed (or at least as we managed to add it — probably *not* all that is needed). +Human interfaces +---------------- + +.. toctree:: + :maxdepth: 1 + + input/index + hid/index + sound/index + gpu/index + fb/index + +Storage interfaces +------------------ + +.. toctree:: + :maxdepth: 1 + + filesystems/index + block/index + cdrom/index + scsi/index + target/index + **Fixme**: much more organizational work is needed here. .. toctree:: @@ -19,12 +43,8 @@ needed). core-api/index locking/index accounting/index - block/index - cdrom/index cpu-freq/index - fb/index fpga/index - hid/index i2c/index iio/index isdn/index @@ -34,26 +54,21 @@ needed). networking/index pcmcia/index power/index - target/index timers/index spi/index w1/index watchdog/index virt/index - input/index hwmon/index - gpu/index accel/index security/index - sound/index crypto/index - filesystems/index mm/index bpf/index usb/index PCI/index - scsi/index misc-devices/index scheduler/index mhi/index peci/index + wmi/index diff --git a/Documentation/target/scripts.rst b/Documentation/target/scripts.rst index 172d42b522e496e6b1c7c504878ded2315bb8702..aa7b9c62c1b35cd37b330261705260d334422819 100644 --- a/Documentation/target/scripts.rst +++ b/Documentation/target/scripts.rst @@ -1,9 +1,3 @@ -TCM mod builder script ----------------------- - -.. literalinclude:: tcm_mod_builder.py - :language: perl - Target export device script --------------------------- diff --git a/Documentation/target/tcm_mod_builder.py b/Documentation/target/tcm_mod_builder.py deleted file mode 100755 index 54492aa813b9b75cffcdb7453316b93e49500100..0000000000000000000000000000000000000000 --- a/Documentation/target/tcm_mod_builder.py +++ /dev/null @@ -1,656 +0,0 @@ -#!/usr/bin/env python -# The TCM v4 multi-protocol fabric module generation script for drivers/target/$NEW_MOD -# -# Copyright (c) 2010 Rising Tide Systems -# Copyright (c) 2010 Linux-iSCSI.org -# -# Author: nab@kernel.org -# -import os, sys -import subprocess as sub -import string -import re -import optparse - -tcm_dir = "" - -fabric_ops = [] -fabric_mod_dir = "" -fabric_mod_port = "" -fabric_mod_init_port = "" - -def tcm_mod_err(msg): - print msg - sys.exit(1) - -def tcm_mod_create_module_subdir(fabric_mod_dir_var): - - if os.path.isdir(fabric_mod_dir_var) == True: - return 1 - - print "Creating fabric_mod_dir: " + fabric_mod_dir_var - ret = os.mkdir(fabric_mod_dir_var) - if ret: - tcm_mod_err("Unable to mkdir " + fabric_mod_dir_var) - - return - -def tcm_mod_build_FC_include(fabric_mod_dir_var, fabric_mod_name): - global fabric_mod_port - global fabric_mod_init_port - buf = "" - - f = fabric_mod_dir_var + "/" + fabric_mod_name + "_base.h" - print "Writing file: " + f - - p = open(f, 'w'); - if not p: - tcm_mod_err("Unable to open file: " + f) - - buf = "#define " + fabric_mod_name.upper() + "_VERSION \"v0.1\"\n" - buf += "#define " + fabric_mod_name.upper() + "_NAMELEN 32\n" - buf += "\n" - buf += "struct " + fabric_mod_name + "_tpg {\n" - buf += " /* FC lport target portal group tag for TCM */\n" - buf += " u16 lport_tpgt;\n" - buf += " /* Pointer back to " + fabric_mod_name + "_lport */\n" - buf += " struct " + fabric_mod_name + "_lport *lport;\n" - buf += " /* Returned by " + fabric_mod_name + "_make_tpg() */\n" - buf += " struct se_portal_group se_tpg;\n" - buf += "};\n" - buf += "\n" - buf += "struct " + fabric_mod_name + "_lport {\n" - buf += " /* Binary World Wide unique Port Name for FC Target Lport */\n" - buf += " u64 lport_wwpn;\n" - buf += " /* ASCII formatted WWPN for FC Target Lport */\n" - buf += " char lport_name[" + fabric_mod_name.upper() + "_NAMELEN];\n" - buf += " /* Returned by " + fabric_mod_name + "_make_lport() */\n" - buf += " struct se_wwn lport_wwn;\n" - buf += "};\n" - - ret = p.write(buf) - if ret: - tcm_mod_err("Unable to write f: " + f) - - p.close() - - fabric_mod_port = "lport" - fabric_mod_init_port = "nport" - - return - -def tcm_mod_build_SAS_include(fabric_mod_dir_var, fabric_mod_name): - global fabric_mod_port - global fabric_mod_init_port - buf = "" - - f = fabric_mod_dir_var + "/" + fabric_mod_name + "_base.h" - print "Writing file: " + f - - p = open(f, 'w'); - if not p: - tcm_mod_err("Unable to open file: " + f) - - buf = "#define " + fabric_mod_name.upper() + "_VERSION \"v0.1\"\n" - buf += "#define " + fabric_mod_name.upper() + "_NAMELEN 32\n" - buf += "\n" - buf += "struct " + fabric_mod_name + "_tpg {\n" - buf += " /* SAS port target portal group tag for TCM */\n" - buf += " u16 tport_tpgt;\n" - buf += " /* Pointer back to " + fabric_mod_name + "_tport */\n" - buf += " struct " + fabric_mod_name + "_tport *tport;\n" - buf += " /* Returned by " + fabric_mod_name + "_make_tpg() */\n" - buf += " struct se_portal_group se_tpg;\n" - buf += "};\n\n" - buf += "struct " + fabric_mod_name + "_tport {\n" - buf += " /* Binary World Wide unique Port Name for SAS Target port */\n" - buf += " u64 tport_wwpn;\n" - buf += " /* ASCII formatted WWPN for SAS Target port */\n" - buf += " char tport_name[" + fabric_mod_name.upper() + "_NAMELEN];\n" - buf += " /* Returned by " + fabric_mod_name + "_make_tport() */\n" - buf += " struct se_wwn tport_wwn;\n" - buf += "};\n" - - ret = p.write(buf) - if ret: - tcm_mod_err("Unable to write f: " + f) - - p.close() - - fabric_mod_port = "tport" - fabric_mod_init_port = "iport" - - return - -def tcm_mod_build_iSCSI_include(fabric_mod_dir_var, fabric_mod_name): - global fabric_mod_port - global fabric_mod_init_port - buf = "" - - f = fabric_mod_dir_var + "/" + fabric_mod_name + "_base.h" - print "Writing file: " + f - - p = open(f, 'w'); - if not p: - tcm_mod_err("Unable to open file: " + f) - - buf = "#define " + fabric_mod_name.upper() + "_VERSION \"v0.1\"\n" - buf += "#define " + fabric_mod_name.upper() + "_NAMELEN 32\n" - buf += "\n" - buf += "struct " + fabric_mod_name + "_tpg {\n" - buf += " /* iSCSI target portal group tag for TCM */\n" - buf += " u16 tport_tpgt;\n" - buf += " /* Pointer back to " + fabric_mod_name + "_tport */\n" - buf += " struct " + fabric_mod_name + "_tport *tport;\n" - buf += " /* Returned by " + fabric_mod_name + "_make_tpg() */\n" - buf += " struct se_portal_group se_tpg;\n" - buf += "};\n\n" - buf += "struct " + fabric_mod_name + "_tport {\n" - buf += " /* ASCII formatted TargetName for IQN */\n" - buf += " char tport_name[" + fabric_mod_name.upper() + "_NAMELEN];\n" - buf += " /* Returned by " + fabric_mod_name + "_make_tport() */\n" - buf += " struct se_wwn tport_wwn;\n" - buf += "};\n" - - ret = p.write(buf) - if ret: - tcm_mod_err("Unable to write f: " + f) - - p.close() - - fabric_mod_port = "tport" - fabric_mod_init_port = "iport" - - return - -def tcm_mod_build_base_includes(proto_ident, fabric_mod_dir_val, fabric_mod_name): - - if proto_ident == "FC": - tcm_mod_build_FC_include(fabric_mod_dir_val, fabric_mod_name) - elif proto_ident == "SAS": - tcm_mod_build_SAS_include(fabric_mod_dir_val, fabric_mod_name) - elif proto_ident == "iSCSI": - tcm_mod_build_iSCSI_include(fabric_mod_dir_val, fabric_mod_name) - else: - print "Unsupported proto_ident: " + proto_ident - sys.exit(1) - - return - -def tcm_mod_build_configfs(proto_ident, fabric_mod_dir_var, fabric_mod_name): - buf = "" - - f = fabric_mod_dir_var + "/" + fabric_mod_name + "_configfs.c" - print "Writing file: " + f - - p = open(f, 'w'); - if not p: - tcm_mod_err("Unable to open file: " + f) - - buf = "#include \n" - buf += "#include \n" - buf += "#include \n" - buf += "#include \n" - buf += "#include \n" - buf += "#include \n" - buf += "#include \n" - buf += "#include \n" - buf += "#include \n" - buf += "#include \n" - buf += "#include \n" - buf += "#include \n" - buf += "#include \n" - buf += "#include \n\n" - buf += "#include \n" - buf += "#include \n" - buf += "#include \"" + fabric_mod_name + "_base.h\"\n" - buf += "#include \"" + fabric_mod_name + "_fabric.h\"\n\n" - - buf += "static const struct target_core_fabric_ops " + fabric_mod_name + "_ops;\n\n" - - buf += "static struct se_portal_group *" + fabric_mod_name + "_make_tpg(\n" - buf += " struct se_wwn *wwn,\n" - buf += " struct config_group *group,\n" - buf += " const char *name)\n" - buf += "{\n" - buf += " struct " + fabric_mod_name + "_" + fabric_mod_port + "*" + fabric_mod_port + " = container_of(wwn,\n" - buf += " struct " + fabric_mod_name + "_" + fabric_mod_port + ", " + fabric_mod_port + "_wwn);\n\n" - buf += " struct " + fabric_mod_name + "_tpg *tpg;\n" - buf += " unsigned long tpgt;\n" - buf += " int ret;\n\n" - buf += " if (strstr(name, \"tpgt_\") != name)\n" - buf += " return ERR_PTR(-EINVAL);\n" - buf += " if (kstrtoul(name + 5, 10, &tpgt) || tpgt > UINT_MAX)\n" - buf += " return ERR_PTR(-EINVAL);\n\n" - buf += " tpg = kzalloc(sizeof(struct " + fabric_mod_name + "_tpg), GFP_KERNEL);\n" - buf += " if (!tpg) {\n" - buf += " printk(KERN_ERR \"Unable to allocate struct " + fabric_mod_name + "_tpg\");\n" - buf += " return ERR_PTR(-ENOMEM);\n" - buf += " }\n" - buf += " tpg->" + fabric_mod_port + " = " + fabric_mod_port + ";\n" - buf += " tpg->" + fabric_mod_port + "_tpgt = tpgt;\n\n" - - if proto_ident == "FC": - buf += " ret = core_tpg_register(wwn, &tpg->se_tpg, SCSI_PROTOCOL_FCP);\n" - elif proto_ident == "SAS": - buf += " ret = core_tpg_register(wwn, &tpg->se_tpg, SCSI_PROTOCOL_SAS);\n" - elif proto_ident == "iSCSI": - buf += " ret = core_tpg_register(wwn, &tpg->se_tpg, SCSI_PROTOCOL_ISCSI);\n" - - buf += " if (ret < 0) {\n" - buf += " kfree(tpg);\n" - buf += " return NULL;\n" - buf += " }\n" - buf += " return &tpg->se_tpg;\n" - buf += "}\n\n" - buf += "static void " + fabric_mod_name + "_drop_tpg(struct se_portal_group *se_tpg)\n" - buf += "{\n" - buf += " struct " + fabric_mod_name + "_tpg *tpg = container_of(se_tpg,\n" - buf += " struct " + fabric_mod_name + "_tpg, se_tpg);\n\n" - buf += " core_tpg_deregister(se_tpg);\n" - buf += " kfree(tpg);\n" - buf += "}\n\n" - - buf += "static struct se_wwn *" + fabric_mod_name + "_make_" + fabric_mod_port + "(\n" - buf += " struct target_fabric_configfs *tf,\n" - buf += " struct config_group *group,\n" - buf += " const char *name)\n" - buf += "{\n" - buf += " struct " + fabric_mod_name + "_" + fabric_mod_port + " *" + fabric_mod_port + ";\n" - - if proto_ident == "FC" or proto_ident == "SAS": - buf += " u64 wwpn = 0;\n\n" - - buf += " /* if (" + fabric_mod_name + "_parse_wwn(name, &wwpn, 1) < 0)\n" - buf += " return ERR_PTR(-EINVAL); */\n\n" - buf += " " + fabric_mod_port + " = kzalloc(sizeof(struct " + fabric_mod_name + "_" + fabric_mod_port + "), GFP_KERNEL);\n" - buf += " if (!" + fabric_mod_port + ") {\n" - buf += " printk(KERN_ERR \"Unable to allocate struct " + fabric_mod_name + "_" + fabric_mod_port + "\");\n" - buf += " return ERR_PTR(-ENOMEM);\n" - buf += " }\n" - - if proto_ident == "FC" or proto_ident == "SAS": - buf += " " + fabric_mod_port + "->" + fabric_mod_port + "_wwpn = wwpn;\n" - - buf += " /* " + fabric_mod_name + "_format_wwn(&" + fabric_mod_port + "->" + fabric_mod_port + "_name[0], " + fabric_mod_name.upper() + "_NAMELEN, wwpn); */\n\n" - buf += " return &" + fabric_mod_port + "->" + fabric_mod_port + "_wwn;\n" - buf += "}\n\n" - buf += "static void " + fabric_mod_name + "_drop_" + fabric_mod_port + "(struct se_wwn *wwn)\n" - buf += "{\n" - buf += " struct " + fabric_mod_name + "_" + fabric_mod_port + " *" + fabric_mod_port + " = container_of(wwn,\n" - buf += " struct " + fabric_mod_name + "_" + fabric_mod_port + ", " + fabric_mod_port + "_wwn);\n" - buf += " kfree(" + fabric_mod_port + ");\n" - buf += "}\n\n" - - buf += "static const struct target_core_fabric_ops " + fabric_mod_name + "_ops = {\n" - buf += " .module = THIS_MODULE,\n" - buf += " .name = \"" + fabric_mod_name + "\",\n" - buf += " .get_fabric_name = " + fabric_mod_name + "_get_fabric_name,\n" - buf += " .tpg_get_wwn = " + fabric_mod_name + "_get_fabric_wwn,\n" - buf += " .tpg_get_tag = " + fabric_mod_name + "_get_tag,\n" - buf += " .tpg_check_demo_mode = " + fabric_mod_name + "_check_false,\n" - buf += " .tpg_check_demo_mode_cache = " + fabric_mod_name + "_check_true,\n" - buf += " .tpg_check_demo_mode_write_protect = " + fabric_mod_name + "_check_true,\n" - buf += " .tpg_check_prod_mode_write_protect = " + fabric_mod_name + "_check_false,\n" - buf += " .tpg_get_inst_index = " + fabric_mod_name + "_tpg_get_inst_index,\n" - buf += " .release_cmd = " + fabric_mod_name + "_release_cmd,\n" - buf += " .sess_get_index = " + fabric_mod_name + "_sess_get_index,\n" - buf += " .sess_get_initiator_sid = NULL,\n" - buf += " .write_pending = " + fabric_mod_name + "_write_pending,\n" - buf += " .set_default_node_attributes = " + fabric_mod_name + "_set_default_node_attrs,\n" - buf += " .get_cmd_state = " + fabric_mod_name + "_get_cmd_state,\n" - buf += " .queue_data_in = " + fabric_mod_name + "_queue_data_in,\n" - buf += " .queue_status = " + fabric_mod_name + "_queue_status,\n" - buf += " .queue_tm_rsp = " + fabric_mod_name + "_queue_tm_rsp,\n" - buf += " .aborted_task = " + fabric_mod_name + "_aborted_task,\n" - buf += " /*\n" - buf += " * Setup function pointers for generic logic in target_core_fabric_configfs.c\n" - buf += " */\n" - buf += " .fabric_make_wwn = " + fabric_mod_name + "_make_" + fabric_mod_port + ",\n" - buf += " .fabric_drop_wwn = " + fabric_mod_name + "_drop_" + fabric_mod_port + ",\n" - buf += " .fabric_make_tpg = " + fabric_mod_name + "_make_tpg,\n" - buf += " .fabric_drop_tpg = " + fabric_mod_name + "_drop_tpg,\n" - buf += "};\n\n" - - buf += "static int __init " + fabric_mod_name + "_init(void)\n" - buf += "{\n" - buf += " return target_register_template(&" + fabric_mod_name + "_ops);\n" - buf += "};\n\n" - - buf += "static void __exit " + fabric_mod_name + "_exit(void)\n" - buf += "{\n" - buf += " target_unregister_template(&" + fabric_mod_name + "_ops);\n" - buf += "};\n\n" - - buf += "MODULE_DESCRIPTION(\"" + fabric_mod_name.upper() + " series fabric driver\");\n" - buf += "MODULE_LICENSE(\"GPL\");\n" - buf += "module_init(" + fabric_mod_name + "_init);\n" - buf += "module_exit(" + fabric_mod_name + "_exit);\n" - - ret = p.write(buf) - if ret: - tcm_mod_err("Unable to write f: " + f) - - p.close() - - return - -def tcm_mod_scan_fabric_ops(tcm_dir): - - fabric_ops_api = tcm_dir + "include/target/target_core_fabric.h" - - print "Using tcm_mod_scan_fabric_ops: " + fabric_ops_api - process_fo = 0; - - p = open(fabric_ops_api, 'r') - - line = p.readline() - while line: - if process_fo == 0 and re.search('struct target_core_fabric_ops {', line): - line = p.readline() - continue - - if process_fo == 0: - process_fo = 1; - line = p.readline() - # Search for function pointer - if not re.search('\(\*', line): - continue - - fabric_ops.append(line.rstrip()) - continue - - line = p.readline() - # Search for function pointer - if not re.search('\(\*', line): - continue - - fabric_ops.append(line.rstrip()) - - p.close() - return - -def tcm_mod_dump_fabric_ops(proto_ident, fabric_mod_dir_var, fabric_mod_name): - buf = "" - bufi = "" - - f = fabric_mod_dir_var + "/" + fabric_mod_name + "_fabric.c" - print "Writing file: " + f - - p = open(f, 'w') - if not p: - tcm_mod_err("Unable to open file: " + f) - - fi = fabric_mod_dir_var + "/" + fabric_mod_name + "_fabric.h" - print "Writing file: " + fi - - pi = open(fi, 'w') - if not pi: - tcm_mod_err("Unable to open file: " + fi) - - buf = "#include \n" - buf += "#include \n" - buf += "#include \n" - buf += "#include \n" - buf += "#include \n" - buf += "#include \n" - buf += "#include \n" - buf += "#include \n" - buf += "#include \n" - buf += "#include \n" - buf += "#include \n" - buf += "#include \n" - buf += "#include \"" + fabric_mod_name + "_base.h\"\n" - buf += "#include \"" + fabric_mod_name + "_fabric.h\"\n\n" - - buf += "int " + fabric_mod_name + "_check_true(struct se_portal_group *se_tpg)\n" - buf += "{\n" - buf += " return 1;\n" - buf += "}\n\n" - bufi += "int " + fabric_mod_name + "_check_true(struct se_portal_group *);\n" - - buf += "int " + fabric_mod_name + "_check_false(struct se_portal_group *se_tpg)\n" - buf += "{\n" - buf += " return 0;\n" - buf += "}\n\n" - bufi += "int " + fabric_mod_name + "_check_false(struct se_portal_group *);\n" - - total_fabric_ops = len(fabric_ops) - i = 0 - - while i < total_fabric_ops: - fo = fabric_ops[i] - i += 1 -# print "fabric_ops: " + fo - - if re.search('get_fabric_name', fo): - buf += "char *" + fabric_mod_name + "_get_fabric_name(void)\n" - buf += "{\n" - buf += " return \"" + fabric_mod_name + "\";\n" - buf += "}\n\n" - bufi += "char *" + fabric_mod_name + "_get_fabric_name(void);\n" - continue - - if re.search('get_wwn', fo): - buf += "char *" + fabric_mod_name + "_get_fabric_wwn(struct se_portal_group *se_tpg)\n" - buf += "{\n" - buf += " struct " + fabric_mod_name + "_tpg *tpg = container_of(se_tpg,\n" - buf += " struct " + fabric_mod_name + "_tpg, se_tpg);\n" - buf += " struct " + fabric_mod_name + "_" + fabric_mod_port + " *" + fabric_mod_port + " = tpg->" + fabric_mod_port + ";\n\n" - buf += " return &" + fabric_mod_port + "->" + fabric_mod_port + "_name[0];\n" - buf += "}\n\n" - bufi += "char *" + fabric_mod_name + "_get_fabric_wwn(struct se_portal_group *);\n" - - if re.search('get_tag', fo): - buf += "u16 " + fabric_mod_name + "_get_tag(struct se_portal_group *se_tpg)\n" - buf += "{\n" - buf += " struct " + fabric_mod_name + "_tpg *tpg = container_of(se_tpg,\n" - buf += " struct " + fabric_mod_name + "_tpg, se_tpg);\n" - buf += " return tpg->" + fabric_mod_port + "_tpgt;\n" - buf += "}\n\n" - bufi += "u16 " + fabric_mod_name + "_get_tag(struct se_portal_group *);\n" - - if re.search('tpg_get_inst_index\)\(', fo): - buf += "u32 " + fabric_mod_name + "_tpg_get_inst_index(struct se_portal_group *se_tpg)\n" - buf += "{\n" - buf += " return 1;\n" - buf += "}\n\n" - bufi += "u32 " + fabric_mod_name + "_tpg_get_inst_index(struct se_portal_group *);\n" - - if re.search('\*release_cmd\)\(', fo): - buf += "void " + fabric_mod_name + "_release_cmd(struct se_cmd *se_cmd)\n" - buf += "{\n" - buf += " return;\n" - buf += "}\n\n" - bufi += "void " + fabric_mod_name + "_release_cmd(struct se_cmd *);\n" - - if re.search('sess_get_index\)\(', fo): - buf += "u32 " + fabric_mod_name + "_sess_get_index(struct se_session *se_sess)\n" - buf += "{\n" - buf += " return 0;\n" - buf += "}\n\n" - bufi += "u32 " + fabric_mod_name + "_sess_get_index(struct se_session *);\n" - - if re.search('write_pending\)\(', fo): - buf += "int " + fabric_mod_name + "_write_pending(struct se_cmd *se_cmd)\n" - buf += "{\n" - buf += " return 0;\n" - buf += "}\n\n" - bufi += "int " + fabric_mod_name + "_write_pending(struct se_cmd *);\n" - - if re.search('set_default_node_attributes\)\(', fo): - buf += "void " + fabric_mod_name + "_set_default_node_attrs(struct se_node_acl *nacl)\n" - buf += "{\n" - buf += " return;\n" - buf += "}\n\n" - bufi += "void " + fabric_mod_name + "_set_default_node_attrs(struct se_node_acl *);\n" - - if re.search('get_cmd_state\)\(', fo): - buf += "int " + fabric_mod_name + "_get_cmd_state(struct se_cmd *se_cmd)\n" - buf += "{\n" - buf += " return 0;\n" - buf += "}\n\n" - bufi += "int " + fabric_mod_name + "_get_cmd_state(struct se_cmd *);\n" - - if re.search('queue_data_in\)\(', fo): - buf += "int " + fabric_mod_name + "_queue_data_in(struct se_cmd *se_cmd)\n" - buf += "{\n" - buf += " return 0;\n" - buf += "}\n\n" - bufi += "int " + fabric_mod_name + "_queue_data_in(struct se_cmd *);\n" - - if re.search('queue_status\)\(', fo): - buf += "int " + fabric_mod_name + "_queue_status(struct se_cmd *se_cmd)\n" - buf += "{\n" - buf += " return 0;\n" - buf += "}\n\n" - bufi += "int " + fabric_mod_name + "_queue_status(struct se_cmd *);\n" - - if re.search('queue_tm_rsp\)\(', fo): - buf += "void " + fabric_mod_name + "_queue_tm_rsp(struct se_cmd *se_cmd)\n" - buf += "{\n" - buf += " return;\n" - buf += "}\n\n" - bufi += "void " + fabric_mod_name + "_queue_tm_rsp(struct se_cmd *);\n" - - if re.search('aborted_task\)\(', fo): - buf += "void " + fabric_mod_name + "_aborted_task(struct se_cmd *se_cmd)\n" - buf += "{\n" - buf += " return;\n" - buf += "}\n\n" - bufi += "void " + fabric_mod_name + "_aborted_task(struct se_cmd *);\n" - - ret = p.write(buf) - if ret: - tcm_mod_err("Unable to write f: " + f) - - p.close() - - ret = pi.write(bufi) - if ret: - tcm_mod_err("Unable to write fi: " + fi) - - pi.close() - return - -def tcm_mod_build_kbuild(fabric_mod_dir_var, fabric_mod_name): - - buf = "" - f = fabric_mod_dir_var + "/Makefile" - print "Writing file: " + f - - p = open(f, 'w') - if not p: - tcm_mod_err("Unable to open file: " + f) - - buf += fabric_mod_name + "-objs := " + fabric_mod_name + "_fabric.o \\\n" - buf += " " + fabric_mod_name + "_configfs.o\n" - buf += "obj-$(CONFIG_" + fabric_mod_name.upper() + ") += " + fabric_mod_name + ".o\n" - - ret = p.write(buf) - if ret: - tcm_mod_err("Unable to write f: " + f) - - p.close() - return - -def tcm_mod_build_kconfig(fabric_mod_dir_var, fabric_mod_name): - - buf = "" - f = fabric_mod_dir_var + "/Kconfig" - print "Writing file: " + f - - p = open(f, 'w') - if not p: - tcm_mod_err("Unable to open file: " + f) - - buf = "config " + fabric_mod_name.upper() + "\n" - buf += " tristate \"" + fabric_mod_name.upper() + " fabric module\"\n" - buf += " depends on TARGET_CORE && CONFIGFS_FS\n" - buf += " default n\n" - buf += " help\n" - buf += " Say Y here to enable the " + fabric_mod_name.upper() + " fabric module\n" - - ret = p.write(buf) - if ret: - tcm_mod_err("Unable to write f: " + f) - - p.close() - return - -def tcm_mod_add_kbuild(tcm_dir, fabric_mod_name): - buf = "obj-$(CONFIG_" + fabric_mod_name.upper() + ") += " + fabric_mod_name.lower() + "/\n" - kbuild = tcm_dir + "/drivers/target/Makefile" - - f = open(kbuild, 'a') - f.write(buf) - f.close() - return - -def tcm_mod_add_kconfig(tcm_dir, fabric_mod_name): - buf = "source \"drivers/target/" + fabric_mod_name.lower() + "/Kconfig\"\n" - kconfig = tcm_dir + "/drivers/target/Kconfig" - - f = open(kconfig, 'a') - f.write(buf) - f.close() - return - -def main(modname, proto_ident): -# proto_ident = "FC" -# proto_ident = "SAS" -# proto_ident = "iSCSI" - - tcm_dir = os.getcwd(); - tcm_dir += "/../../" - print "tcm_dir: " + tcm_dir - fabric_mod_name = modname - fabric_mod_dir = tcm_dir + "drivers/target/" + fabric_mod_name - print "Set fabric_mod_name: " + fabric_mod_name - print "Set fabric_mod_dir: " + fabric_mod_dir - print "Using proto_ident: " + proto_ident - - if proto_ident != "FC" and proto_ident != "SAS" and proto_ident != "iSCSI": - print "Unsupported proto_ident: " + proto_ident - sys.exit(1) - - ret = tcm_mod_create_module_subdir(fabric_mod_dir) - if ret: - print "tcm_mod_create_module_subdir() failed because module already exists!" - sys.exit(1) - - tcm_mod_build_base_includes(proto_ident, fabric_mod_dir, fabric_mod_name) - tcm_mod_scan_fabric_ops(tcm_dir) - tcm_mod_dump_fabric_ops(proto_ident, fabric_mod_dir, fabric_mod_name) - tcm_mod_build_configfs(proto_ident, fabric_mod_dir, fabric_mod_name) - tcm_mod_build_kbuild(fabric_mod_dir, fabric_mod_name) - tcm_mod_build_kconfig(fabric_mod_dir, fabric_mod_name) - - input = raw_input("Would you like to add " + fabric_mod_name + " to drivers/target/Makefile..? [yes,no]: ") - if input == "yes" or input == "y": - tcm_mod_add_kbuild(tcm_dir, fabric_mod_name) - - input = raw_input("Would you like to add " + fabric_mod_name + " to drivers/target/Kconfig..? [yes,no]: ") - if input == "yes" or input == "y": - tcm_mod_add_kconfig(tcm_dir, fabric_mod_name) - - return - -parser = optparse.OptionParser() -parser.add_option('-m', '--modulename', help='Module name', dest='modname', - action='store', nargs=1, type='string') -parser.add_option('-p', '--protoident', help='Protocol Ident', dest='protoident', - action='store', nargs=1, type='string') - -(opts, args) = parser.parse_args() - -mandatories = ['modname', 'protoident'] -for m in mandatories: - if not opts.__dict__[m]: - print "mandatory option is missing\n" - parser.print_help() - exit(-1) - -if __name__ == "__main__": - - main(str(opts.modname), opts.protoident) diff --git a/Documentation/tools/rtla/common_options.rst b/Documentation/tools/rtla/common_options.rst index af76df6205d4a8f19432cf7836b450e732f1d11a..aeb91ff3bd68cbc8166a3e8781250038a10a5e74 100644 --- a/Documentation/tools/rtla/common_options.rst +++ b/Documentation/tools/rtla/common_options.rst @@ -2,6 +2,10 @@ Set the osnoise tracer to run the sample threads in the cpu-list. +**-H**, **--house-keeping** *cpu-list* + + Run rtla control threads only on the given cpu-list. + **-d**, **--duration** *time[s|m|h|d]* Set the duration of the session. @@ -42,6 +46,10 @@ - *f:prio* - use SCHED_FIFO with *prio*; - *d:runtime[us|ms|s]:period[us|ms|s]* - use SCHED_DEADLINE with *runtime* and *period* in nanoseconds. +**-C**, **--cgroup**\[*=cgroup*] + + Set a *cgroup* to the tracer's threads. If the **-C** option is passed without arguments, the tracer's thread will inherit **rtla**'s *cgroup*. Otherwise, the threads will be placed on the *cgroup* passed to the option. + **-h**, **--help** Print help menu. diff --git a/Documentation/tools/rtla/common_timerlat_aa.rst b/Documentation/tools/rtla/common_timerlat_aa.rst index 795b9fbcbc6de014571b726b70c61e1079378832..077029e6b289eef9f7a9679e9f6b8dcb97a57fcc 100644 --- a/Documentation/tools/rtla/common_timerlat_aa.rst +++ b/Documentation/tools/rtla/common_timerlat_aa.rst @@ -5,10 +5,3 @@ **--no-aa** disable auto-analysis, reducing rtla timerlat cpu usage - -**--aa-only** *us* - - Set stop tracing conditions and run without collecting and displaying statistics. - Print the auto-analysis if the system hits the stop tracing condition. This option - is useful to reduce rtla timerlat CPU, enabling the debug without the overhead of - collecting the statistics. diff --git a/Documentation/tools/rtla/common_timerlat_options.rst b/Documentation/tools/rtla/common_timerlat_options.rst index bacdea6de7a34ed1b1b03c4b66459ee7ac8684c0..88506b397c2dd6d0ce6009881b932016c85f1c48 100644 --- a/Documentation/tools/rtla/common_timerlat_options.rst +++ b/Documentation/tools/rtla/common_timerlat_options.rst @@ -26,3 +26,10 @@ Set the /dev/cpu_dma_latency to *us*, aiming to bound exit from idle latencies. *cyclictest* sets this value to *0* by default, use **--dma-latency** *0* to have similar results. + +**-u**, **--user-threads** + + Set timerlat to run without a workload, and then dispatches user-space workloads + to wait on the timerlat_fd. Once the workload is awakes, it goes to sleep again + adding so the measurement for the kernel-to-user and user-to-kernel to the tracer + output. diff --git a/Documentation/tools/rtla/rtla-timerlat-hist.rst b/Documentation/tools/rtla/rtla-timerlat-hist.rst index 6bf7f0ca45564ad61f02288df4e93ebbe9a4d3b6..057db78d4095a1135a66968fdb6c7a2f18846848 100644 --- a/Documentation/tools/rtla/rtla-timerlat-hist.rst +++ b/Documentation/tools/rtla/rtla-timerlat-hist.rst @@ -29,15 +29,18 @@ OPTIONS .. include:: common_options.rst +.. include:: common_timerlat_aa.rst + EXAMPLE ======= In the example below, **rtla timerlat hist** is set to run for *10* minutes, in the cpus *0-4*, *skipping zero* only lines. Moreover, **rtla timerlat hist** will change the priority of the *timerlat* threads to run under *SCHED_DEADLINE* priority, with a *10us* runtime every *1ms* period. The -*1ms* period is also passed to the *timerlat* tracer:: +*1ms* period is also passed to the *timerlat* tracer. Auto-analysis is disabled +to reduce overhead :: - [root@alien ~]# timerlat hist -d 10m -c 0-4 -P d:100us:1ms -p 1ms + [root@alien ~]# timerlat hist -d 10m -c 0-4 -P d:100us:1ms -p 1ms --no-aa # RTLA timerlat histogram # Time unit is microseconds (us) # Duration: 0 00:10:00 diff --git a/Documentation/tools/rtla/rtla-timerlat-top.rst b/Documentation/tools/rtla/rtla-timerlat-top.rst index 73799c1150adc5af189ce20dcb9dad7ba10d72c3..1b7cf4e3eafe7d194267cb1805a1fde4f41aaff9 100644 --- a/Documentation/tools/rtla/rtla-timerlat-top.rst +++ b/Documentation/tools/rtla/rtla-timerlat-top.rst @@ -32,6 +32,13 @@ OPTIONS .. include:: common_timerlat_aa.rst +**--aa-only** *us* + + Set stop tracing conditions and run without collecting and displaying statistics. + Print the auto-analysis if the system hits the stop tracing condition. This option + is useful to reduce rtla timerlat CPU, enabling the debug without the overhead of + collecting the statistics. + EXAMPLE ======= diff --git a/Documentation/trace/coresight/coresight-dummy.rst b/Documentation/trace/coresight/coresight-dummy.rst new file mode 100644 index 0000000000000000000000000000000000000000..eff7c553ee6ce547f5de31224b6bdeae514a8d26 --- /dev/null +++ b/Documentation/trace/coresight/coresight-dummy.rst @@ -0,0 +1,32 @@ +.. SPDX-License-Identifier: GPL-2.0 + +============================= +Coresight Dummy Trace Module +============================= + + :Author: Hao Zhang + :Date: June 2023 + +Introduction +------------ + +The Coresight dummy trace module is for the specific devices that kernel don't +have permission to access or configure, e.g., CoreSight TPDMs on Qualcomm +platforms. For these devices, a dummy driver is needed to register them as +Coresight devices. The module may also be used to define components that may +not have any programming interfaces, so that paths can be created in the driver. +It provides Coresight API for operations on dummy devices, such as enabling and +disabling them. It also provides the Coresight dummy sink/source paths for +debugging. + +Config details +-------------- + +There are two types of nodes, dummy sink and dummy source. These nodes +are available at ``/sys/bus/coresight/devices``. + +Example output:: + + $ ls -l /sys/bus/coresight/devices | grep dummy + dummy_sink0 -> ../../../devices/platform/soc@0/soc@0:sink/dummy_sink0 + dummy_source0 -> ../../../devices/platform/soc@0/soc@0:source/dummy_source0 diff --git a/Documentation/trace/fprobetrace.rst b/Documentation/trace/fprobetrace.rst new file mode 100644 index 0000000000000000000000000000000000000000..7297f94784594f30cae94a6a92ce03749d7b0592 --- /dev/null +++ b/Documentation/trace/fprobetrace.rst @@ -0,0 +1,188 @@ +.. SPDX-License-Identifier: GPL-2.0 + +========================== +Fprobe-based Event Tracing +========================== + +.. Author: Masami Hiramatsu + +Overview +-------- + +Fprobe event is similar to the kprobe event, but limited to probe on +the function entry and exit only. It is good enough for many use cases +which only traces some specific functions. + +This document also covers tracepoint probe events (tprobe) since this +is also works only on the tracepoint entry. User can trace a part of +tracepoint argument, or the tracepoint without trace-event, which is +not exposed on tracefs. + +As same as other dynamic events, fprobe events and tracepoint probe +events are defined via `dynamic_events` interface file on tracefs. + +Synopsis of fprobe-events +------------------------- +:: + + f[:[GRP1/][EVENT1]] SYM [FETCHARGS] : Probe on function entry + f[MAXACTIVE][:[GRP1/][EVENT1]] SYM%return [FETCHARGS] : Probe on function exit + t[:[GRP2/][EVENT2]] TRACEPOINT [FETCHARGS] : Probe on tracepoint + + GRP1 : Group name for fprobe. If omitted, use "fprobes" for it. + GRP2 : Group name for tprobe. If omitted, use "tracepoints" for it. + EVENT1 : Event name for fprobe. If omitted, the event name is + "SYM__entry" or "SYM__exit". + EVENT2 : Event name for tprobe. If omitted, the event name is + the same as "TRACEPOINT", but if the "TRACEPOINT" starts + with a digit character, "_TRACEPOINT" is used. + MAXACTIVE : Maximum number of instances of the specified function that + can be probed simultaneously, or 0 for the default value + as defined in Documentation/trace/fprobe.rst + + FETCHARGS : Arguments. Each probe can have up to 128 args. + ARG : Fetch "ARG" function argument using BTF (only for function + entry or tracepoint.) (\*1) + @ADDR : Fetch memory at ADDR (ADDR should be in kernel) + @SYM[+|-offs] : Fetch memory at SYM +|- offs (SYM should be a data symbol) + $stackN : Fetch Nth entry of stack (N >= 0) + $stack : Fetch stack address. + $argN : Fetch the Nth function argument. (N >= 1) (\*2) + $retval : Fetch return value.(\*3) + $comm : Fetch current task comm. + +|-[u]OFFS(FETCHARG) : Fetch memory at FETCHARG +|- OFFS address.(\*4)(\*5) + \IMM : Store an immediate value to the argument. + NAME=FETCHARG : Set NAME as the argument name of FETCHARG. + FETCHARG:TYPE : Set TYPE as the type of FETCHARG. Currently, basic types + (u8/u16/u32/u64/s8/s16/s32/s64), hexadecimal types + (x8/x16/x32/x64), "char", "string", "ustring", "symbol", "symstr" + and bitfield are supported. + + (\*1) This is available only when BTF is enabled. + (\*2) only for the probe on function entry (offs == 0). + (\*3) only for return probe. + (\*4) this is useful for fetching a field of data structures. + (\*5) "u" means user-space dereference. + +For the details of TYPE, see :ref:`kprobetrace documentation `. + +BTF arguments +------------- +BTF (BPF Type Format) argument allows user to trace function and tracepoint +parameters by its name instead of ``$argN``. This feature is available if the +kernel is configured with CONFIG_BPF_SYSCALL and CONFIG_DEBUG_INFO_BTF. +If user only specify the BTF argument, the event's argument name is also +automatically set by the given name. :: + + # echo 'f:myprobe vfs_read count pos' >> dynamic_events + # cat dynamic_events + f:fprobes/myprobe vfs_read count=count pos=pos + +It also chooses the fetch type from BTF information. For example, in the above +example, the ``count`` is unsigned long, and the ``pos`` is a pointer. Thus, both +are converted to 64bit unsigned long, but only ``pos`` has "%Lx" print-format as +below :: + + # cat events/fprobes/myprobe/format + name: myprobe + ID: 1313 + format: + field:unsigned short common_type; offset:0; size:2; signed:0; + field:unsigned char common_flags; offset:2; size:1; signed:0; + field:unsigned char common_preempt_count; offset:3; size:1; signed:0; + field:int common_pid; offset:4; size:4; signed:1; + + field:unsigned long __probe_ip; offset:8; size:8; signed:0; + field:u64 count; offset:16; size:8; signed:0; + field:u64 pos; offset:24; size:8; signed:0; + + print fmt: "(%lx) count=%Lu pos=0x%Lx", REC->__probe_ip, REC->count, REC->pos + +If user unsures the name of arguments, ``$arg*`` will be helpful. The ``$arg*`` +is expanded to all function arguments of the function or the tracepoint. :: + + # echo 'f:myprobe vfs_read $arg*' >> dynamic_events + # cat dynamic_events + f:fprobes/myprobe vfs_read file=file buf=buf count=count pos=pos + +BTF also affects the ``$retval``. If user doesn't set any type, the retval type is +automatically picked from the BTF. If the function returns ``void``, ``$retval`` +is rejected. + +Usage examples +-------------- +Here is an example to add fprobe events on ``vfs_read()`` function entry +and exit, with BTF arguments. +:: + + # echo 'f vfs_read $arg*' >> dynamic_events + # echo 'f vfs_read%return $retval' >> dynamic_events + # cat dynamic_events + f:fprobes/vfs_read__entry vfs_read file=file buf=buf count=count pos=pos + f:fprobes/vfs_read__exit vfs_read%return arg1=$retval + # echo 1 > events/fprobes/enable + # head -n 20 trace | tail + # TASK-PID CPU# ||||| TIMESTAMP FUNCTION + # | | | ||||| | | + sh-70 [000] ...1. 335.883195: vfs_read__entry: (vfs_read+0x4/0x340) file=0xffff888005cf9a80 buf=0x7ffef36c6879 count=1 pos=0xffffc900005aff08 + sh-70 [000] ..... 335.883208: vfs_read__exit: (ksys_read+0x75/0x100 <- vfs_read) arg1=1 + sh-70 [000] ...1. 335.883220: vfs_read__entry: (vfs_read+0x4/0x340) file=0xffff888005cf9a80 buf=0x7ffef36c6879 count=1 pos=0xffffc900005aff08 + sh-70 [000] ..... 335.883224: vfs_read__exit: (ksys_read+0x75/0x100 <- vfs_read) arg1=1 + sh-70 [000] ...1. 335.883232: vfs_read__entry: (vfs_read+0x4/0x340) file=0xffff888005cf9a80 buf=0x7ffef36c687a count=1 pos=0xffffc900005aff08 + sh-70 [000] ..... 335.883237: vfs_read__exit: (ksys_read+0x75/0x100 <- vfs_read) arg1=1 + sh-70 [000] ...1. 336.050329: vfs_read__entry: (vfs_read+0x4/0x340) file=0xffff888005cf9a80 buf=0x7ffef36c6879 count=1 pos=0xffffc900005aff08 + sh-70 [000] ..... 336.050343: vfs_read__exit: (ksys_read+0x75/0x100 <- vfs_read) arg1=1 + +You can see all function arguments and return values are recorded as signed int. + +Also, here is an example of tracepoint events on ``sched_switch`` tracepoint. +To compare the result, this also enables the ``sched_switch`` traceevent too. +:: + + # echo 't sched_switch $arg*' >> dynamic_events + # echo 1 > events/sched/sched_switch/enable + # echo 1 > events/tracepoints/sched_switch/enable + # echo > trace + # head -n 20 trace | tail + # TASK-PID CPU# ||||| TIMESTAMP FUNCTION + # | | | ||||| | | + sh-70 [000] d..2. 3912.083993: sched_switch: prev_comm=sh prev_pid=70 prev_prio=120 prev_state=S ==> next_comm=swapper/0 next_pid=0 next_prio=120 + sh-70 [000] d..3. 3912.083995: sched_switch: (__probestub_sched_switch+0x4/0x10) preempt=0 prev=0xffff88800664e100 next=0xffffffff828229c0 prev_state=1 + -0 [000] d..2. 3912.084183: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=rcu_preempt next_pid=16 next_prio=120 + -0 [000] d..3. 3912.084184: sched_switch: (__probestub_sched_switch+0x4/0x10) preempt=0 prev=0xffffffff828229c0 next=0xffff888004208000 prev_state=0 + rcu_preempt-16 [000] d..2. 3912.084196: sched_switch: prev_comm=rcu_preempt prev_pid=16 prev_prio=120 prev_state=I ==> next_comm=swapper/0 next_pid=0 next_prio=120 + rcu_preempt-16 [000] d..3. 3912.084196: sched_switch: (__probestub_sched_switch+0x4/0x10) preempt=0 prev=0xffff888004208000 next=0xffffffff828229c0 prev_state=1026 + -0 [000] d..2. 3912.085191: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=rcu_preempt next_pid=16 next_prio=120 + -0 [000] d..3. 3912.085191: sched_switch: (__probestub_sched_switch+0x4/0x10) preempt=0 prev=0xffffffff828229c0 next=0xffff888004208000 prev_state=0 + +As you can see, the ``sched_switch`` trace-event shows *cooked* parameters, on +the other hand, the ``sched_switch`` tracepoint probe event shows *raw* +parameters. This means you can access any field values in the task +structure pointed by the ``prev`` and ``next`` arguments. + +For example, usually ``task_struct::start_time`` is not traced, but with this +traceprobe event, you can trace it as below. +:: + + # echo 't sched_switch comm=+1896(next):string start_time=+1728(next):u64' > dynamic_events + # head -n 20 trace | tail + # TASK-PID CPU# ||||| TIMESTAMP FUNCTION + # | | | ||||| | | + sh-70 [000] d..3. 5606.686577: sched_switch: (__probestub_sched_switch+0x4/0x10) comm="rcu_preempt" usage=1 start_time=245000000 + rcu_preempt-16 [000] d..3. 5606.686602: sched_switch: (__probestub_sched_switch+0x4/0x10) comm="sh" usage=1 start_time=1596095526 + sh-70 [000] d..3. 5606.686637: sched_switch: (__probestub_sched_switch+0x4/0x10) comm="swapper/0" usage=2 start_time=0 + -0 [000] d..3. 5606.687190: sched_switch: (__probestub_sched_switch+0x4/0x10) comm="rcu_preempt" usage=1 start_time=245000000 + rcu_preempt-16 [000] d..3. 5606.687202: sched_switch: (__probestub_sched_switch+0x4/0x10) comm="swapper/0" usage=2 start_time=0 + -0 [000] d..3. 5606.690317: sched_switch: (__probestub_sched_switch+0x4/0x10) comm="kworker/0:1" usage=1 start_time=137000000 + kworker/0:1-14 [000] d..3. 5606.690339: sched_switch: (__probestub_sched_switch+0x4/0x10) comm="swapper/0" usage=2 start_time=0 + -0 [000] d..3. 5606.692368: sched_switch: (__probestub_sched_switch+0x4/0x10) comm="kworker/0:1" usage=1 start_time=137000000 + +Currently, to find the offset of a specific field in the data structure, +you need to build kernel with debuginfo and run `perf probe` command with +`-D` option. e.g. +:: + + # perf probe -D "__probestub_sched_switch next->comm:string next->start_time" + p:probe/__probestub_sched_switch __probestub_sched_switch+0 comm=+1896(%cx):string start_time=+1728(%cx):u64 + +And replace the ``%cx`` with the ``next``. diff --git a/Documentation/trace/ftrace.rst b/Documentation/trace/ftrace.rst index 027437b745a0c6a0e49d33271ac027e204fbae0a..f606c5bd1c0d00b55907175b6b00d0bf82a14058 100644 --- a/Documentation/trace/ftrace.rst +++ b/Documentation/trace/ftrace.rst @@ -324,6 +324,12 @@ of ftrace. Here is a list of some of the key files: "set_graph_function", or "set_graph_notrace". (See the section "dynamic ftrace" below for more details.) + available_filter_functions_addrs: + + Similar to available_filter_functions, but with address displayed + for each function. The displayed address is the patch-site address + and can differ from /proc/kallsyms address. + dyn_ftrace_total_info: This file is for debugging purposes. The number of functions that @@ -1359,6 +1365,19 @@ Options for function_graph tracer: only a closing curly bracket "}" is displayed for the return of a function. + funcgraph-retval + When set, the return value of each traced function + will be printed after an equal sign "=". By default + this is off. + + funcgraph-retval-hex + When set, the return value will always be printed + in hexadecimal format. If the option is not set and + the return value is an error code, it will be printed + in signed decimal format; otherwise it will also be + printed in hexadecimal format. By default, this option + is off. + sleep-time When running function graph tracer, to include the time a task schedules out in its function. @@ -2704,6 +2723,119 @@ It is default disabled. 0) 1.757 us | } /* kmem_cache_free() */ 0) 2.861 us | } /* putname() */ +The return value of each traced function can be displayed after +an equal sign "=". When encountering system call failures, it +can be verfy helpful to quickly locate the function that first +returns an error code. + + - hide: echo nofuncgraph-retval > trace_options + - show: echo funcgraph-retval > trace_options + + Example with funcgraph-retval:: + + 1) | cgroup_migrate() { + 1) 0.651 us | cgroup_migrate_add_task(); /* = 0xffff93fcfd346c00 */ + 1) | cgroup_migrate_execute() { + 1) | cpu_cgroup_can_attach() { + 1) | cgroup_taskset_first() { + 1) 0.732 us | cgroup_taskset_next(); /* = 0xffff93fc8fb20000 */ + 1) 1.232 us | } /* cgroup_taskset_first = 0xffff93fc8fb20000 */ + 1) 0.380 us | sched_rt_can_attach(); /* = 0x0 */ + 1) 2.335 us | } /* cpu_cgroup_can_attach = -22 */ + 1) 4.369 us | } /* cgroup_migrate_execute = -22 */ + 1) 7.143 us | } /* cgroup_migrate = -22 */ + +The above example shows that the function cpu_cgroup_can_attach +returned the error code -22 firstly, then we can read the code +of this function to get the root cause. + +When the option funcgraph-retval-hex is not set, the return value can +be displayed in a smart way. Specifically, if it is an error code, +it will be printed in signed decimal format, otherwise it will +printed in hexadecimal format. + + - smart: echo nofuncgraph-retval-hex > trace_options + - hexadecimal: echo funcgraph-retval-hex > trace_options + + Example with funcgraph-retval-hex:: + + 1) | cgroup_migrate() { + 1) 0.651 us | cgroup_migrate_add_task(); /* = 0xffff93fcfd346c00 */ + 1) | cgroup_migrate_execute() { + 1) | cpu_cgroup_can_attach() { + 1) | cgroup_taskset_first() { + 1) 0.732 us | cgroup_taskset_next(); /* = 0xffff93fc8fb20000 */ + 1) 1.232 us | } /* cgroup_taskset_first = 0xffff93fc8fb20000 */ + 1) 0.380 us | sched_rt_can_attach(); /* = 0x0 */ + 1) 2.335 us | } /* cpu_cgroup_can_attach = 0xffffffea */ + 1) 4.369 us | } /* cgroup_migrate_execute = 0xffffffea */ + 1) 7.143 us | } /* cgroup_migrate = 0xffffffea */ + +At present, there are some limitations when using the funcgraph-retval +option, and these limitations will be eliminated in the future: + +- Even if the function return type is void, a return value will still + be printed, and you can just ignore it. + +- Even if return values are stored in multiple registers, only the + value contained in the first register will be recorded and printed. + To illustrate, in the x86 architecture, eax and edx are used to store + a 64-bit return value, with the lower 32 bits saved in eax and the + upper 32 bits saved in edx. However, only the value stored in eax + will be recorded and printed. + +- In certain procedure call standards, such as arm64's AAPCS64, when a + type is smaller than a GPR, it is the responsibility of the consumer + to perform the narrowing, and the upper bits may contain UNKNOWN values. + Therefore, it is advisable to check the code for such cases. For instance, + when using a u8 in a 64-bit GPR, bits [63:8] may contain arbitrary values, + especially when larger types are truncated, whether explicitly or implicitly. + Here are some specific cases to illustrate this point: + + **Case One**: + + The function narrow_to_u8 is defined as follows:: + + u8 narrow_to_u8(u64 val) + { + // implicitly truncated + return val; + } + + It may be compiled to:: + + narrow_to_u8: + < ... ftrace instrumentation ... > + RET + + If you pass 0x123456789abcdef to this function and want to narrow it, + it may be recorded as 0x123456789abcdef instead of 0xef. + + **Case Two**: + + The function error_if_not_4g_aligned is defined as follows:: + + int error_if_not_4g_aligned(u64 val) + { + if (val & GENMASK(31, 0)) + return -EINVAL; + + return 0; + } + + It could be compiled to:: + + error_if_not_4g_aligned: + CBNZ w0, .Lnot_aligned + RET // bits [31:0] are zero, bits + // [63:32] are UNKNOWN + .Lnot_aligned: + MOV x0, #-EINVAL + RET + + When passing 0x2_0000_0000 to it, the return value may be recorded as + 0x2_0000_0000 instead of 0. + You can put some comments on specific functions by using trace_printk() For example, if you want to put a comment inside the __might_sleep() function, you just have to include diff --git a/Documentation/trace/hisi-ptt.rst b/Documentation/trace/hisi-ptt.rst index 4f87d8e21065e2da06ec121053abd6f564c6daf3..989255eb56221e7fe56d990f03cc7e2970c9a4c5 100644 --- a/Documentation/trace/hisi-ptt.rst +++ b/Documentation/trace/hisi-ptt.rst @@ -148,14 +148,20 @@ For example, if the desired filter is Endpoint function 0000:01:00.1 the filter value will be 0x00101. If the desired filter is Root Port 0000:00:10.0 then then filter value is calculated as 0x80001. +The driver also presents every supported Root Port and Requester filter through +sysfs. Each filter will be an individual file with name of its related PCIe +device name (domain:bus:device.function). The files of Root Port filters are +under $(PTT PMU dir)/root_port_filters and files of Requester filters +are under $(PTT PMU dir)/requester_filters. + Note that multiple Root Ports can be specified at one time, but only one Endpoint function can be specified in one trace. Specifying both Root Port and function at the same time is not supported. Driver maintains a list of available filters and will check the invalid inputs. -Currently the available filters are detected in driver's probe. If the supported -devices are removed/added after probe, you may need to reload the driver to update -the filters. +The available filters will be dynamically updated, which means you will always +get correct filter information when hotplug events happen, or when you manually +remove/rescan the devices. 2. Type ------- diff --git a/Documentation/trace/index.rst b/Documentation/trace/index.rst index ea25a9220f9262a85416ed97f436ac966ebb8678..5092d6c13af5e3741c8a990f7d1ec42daddbacf3 100644 --- a/Documentation/trace/index.rst +++ b/Documentation/trace/index.rst @@ -13,6 +13,7 @@ Linux Tracing Technologies kprobes kprobetrace uprobetracer + fprobetrace tracepoints events events-kmem diff --git a/Documentation/trace/kprobetrace.rst b/Documentation/trace/kprobetrace.rst index 651f9ab53f3ee9c76a4505a32811b95311a10a14..8a2dfee3814544a76b67c18dd4f033786f4c8132 100644 --- a/Documentation/trace/kprobetrace.rst +++ b/Documentation/trace/kprobetrace.rst @@ -66,6 +66,8 @@ Synopsis of kprobe_events (\*3) this is useful for fetching a field of data structures. (\*4) "u" means user-space dereference. See :ref:`user_mem_access`. +.. _kprobetrace_types: + Types ----- Several types are supported for fetchargs. Kprobe tracer will access memory diff --git a/Documentation/trace/timerlat-tracer.rst b/Documentation/trace/timerlat-tracer.rst index db17df312bc87a1a1c041d6620e97863e5ca1758..53a56823e903d0c82cfec41473f9f6a4bfe36482 100644 --- a/Documentation/trace/timerlat-tracer.rst +++ b/Documentation/trace/timerlat-tracer.rst @@ -180,3 +180,81 @@ dummy_load_1ms_pd_init, which had the following code (on purpose):: return 0; } + +User-space interface +--------------------------- + +Timerlat allows user-space threads to use timerlat infra-structure to +measure scheduling latency. This interface is accessible via a per-CPU +file descriptor inside $tracing_dir/osnoise/per_cpu/cpu$ID/timerlat_fd. + +This interface is accessible under the following conditions: + + - timerlat tracer is enable + - osnoise workload option is set to NO_OSNOISE_WORKLOAD + - The user-space thread is affined to a single processor + - The thread opens the file associated with its single processor + - Only one thread can access the file at a time + +The open() syscall will fail if any of these conditions are not met. +After opening the file descriptor, the user space can read from it. + +The read() system call will run a timerlat code that will arm the +timer in the future and wait for it as the regular kernel thread does. + +When the timer IRQ fires, the timerlat IRQ will execute, report the +IRQ latency and wake up the thread waiting in the read. The thread will be +scheduled and report the thread latency via tracer - as for the kernel +thread. + +The difference from the in-kernel timerlat is that, instead of re-arming +the timer, timerlat will return to the read() system call. At this point, +the user can run any code. + +If the application rereads the file timerlat file descriptor, the tracer +will report the return from user-space latency, which is the total +latency. If this is the end of the work, it can be interpreted as the +response time for the request. + +After reporting the total latency, timerlat will restart the cycle, arm +a timer, and go to sleep for the following activation. + +If at any time one of the conditions is broken, e.g., the thread migrates +while in user space, or the timerlat tracer is disabled, the SIG_KILL +signal will be sent to the user-space thread. + +Here is an basic example of user-space code for timerlat:: + + int main(void) + { + char buffer[1024]; + int timerlat_fd; + int retval; + long cpu = 0; /* place in CPU 0 */ + cpu_set_t set; + + CPU_ZERO(&set); + CPU_SET(cpu, &set); + + if (sched_setaffinity(gettid(), sizeof(set), &set) == -1) + return 1; + + snprintf(buffer, sizeof(buffer), + "/sys/kernel/tracing/osnoise/per_cpu/cpu%ld/timerlat_fd", + cpu); + + timerlat_fd = open(buffer, O_RDONLY); + if (timerlat_fd < 0) { + printf("error opening %s: %s\n", buffer, strerror(errno)); + exit(1); + } + + for (;;) { + retval = read(timerlat_fd, buffer, 1024); + if (retval < 0) + break; + } + + close(timerlat_fd); + exit(0); + } diff --git a/Documentation/trace/user_events.rst b/Documentation/trace/user_events.rst index f79987e16cf43822a9f37d3ecb7fe507062f8460..e7b07313550a3f60e3fe26cad1f2028cd4dc6eb1 100644 --- a/Documentation/trace/user_events.rst +++ b/Documentation/trace/user_events.rst @@ -14,10 +14,6 @@ Programs can view status of the events via /sys/kernel/tracing/user_events_status and can both register and write data out via /sys/kernel/tracing/user_events_data. -Programs can also use /sys/kernel/tracing/dynamic_events to register and -delete user based events via the u: prefix. The format of the command to -dynamic_events is the same as the ioctl with the u: prefix applied. - Typically programs will register a set of events that they wish to expose to tools that can read trace_events (such as ftrace and perf). The registration process tells the kernel which address and bit to reflect if any tool has @@ -144,6 +140,9 @@ its name. Delete will only succeed if there are no references left to the event (in both user and kernel space). User programs should use a separate file to request deletes than the one used for registration due to this. +**NOTE:** By default events will auto-delete when there are no references left +to the event. Flags in the future may change this logic. + Unregistering ------------- If after registering an event it is no longer wanted to be updated then it can diff --git a/Documentation/translations/zh_CN/arm/Booting b/Documentation/translations/zh_CN/arch/arm/Booting similarity index 98% rename from Documentation/translations/zh_CN/arm/Booting rename to Documentation/translations/zh_CN/arch/arm/Booting index 5ecea0767893971a59a5eca3e31a1d1664713a14..f18585156b6771c184da9069b750b3649c06a6d3 100644 --- a/Documentation/translations/zh_CN/arm/Booting +++ b/Documentation/translations/zh_CN/arch/arm/Booting @@ -1,4 +1,4 @@ -Chinese translated version of Documentation/arm/booting.rst +Chinese translated version of Documentation/arch/arm/booting.rst If you have any comment or update to the content, please contact the original document maintainer directly. However, if you have a problem @@ -9,7 +9,7 @@ or if there is a problem with the translation. Maintainer: Russell King Chinese maintainer: Fu Wei --------------------------------------------------------------------- -Documentation/arm/booting.rst 的中文翻译 +Documentation/arch/arm/booting.rst 的中文翻译 如果想评论或更新本文的内容,请直接联系原文档的维护者。如果你使用英文 交流有困难的话,也可以向中文版维护者求助。如果本翻译更新不及时或者翻 diff --git a/Documentation/translations/zh_CN/arm/kernel_user_helpers.txt b/Documentation/translations/zh_CN/arch/arm/kernel_user_helpers.txt similarity index 98% rename from Documentation/translations/zh_CN/arm/kernel_user_helpers.txt rename to Documentation/translations/zh_CN/arch/arm/kernel_user_helpers.txt index 99af4363984dbc74f47ab9993d42da84277db420..018eb7d542331fac6d271e172a6373108acf868c 100644 --- a/Documentation/translations/zh_CN/arm/kernel_user_helpers.txt +++ b/Documentation/translations/zh_CN/arch/arm/kernel_user_helpers.txt @@ -1,4 +1,4 @@ -Chinese translated version of Documentation/arm/kernel_user_helpers.rst +Chinese translated version of Documentation/arch/arm/kernel_user_helpers.rst If you have any comment or update to the content, please contact the original document maintainer directly. However, if you have a problem @@ -10,7 +10,7 @@ Maintainer: Nicolas Pitre Dave Martin Chinese maintainer: Fu Wei --------------------------------------------------------------------- -Documentation/arm/kernel_user_helpers.rst 的中文翻译 +Documentation/arch/arm/kernel_user_helpers.rst 的中文翻译 如果想评论或更新本文的内容,请直接联系原文档的维护者。如果你使用英文 交流有困难的话,也可以向中文版维护者求助。如果本翻译更新不及时或者翻 diff --git a/Documentation/translations/zh_CN/arm64/amu.rst b/Documentation/translations/zh_CN/arch/arm64/amu.rst similarity index 97% rename from Documentation/translations/zh_CN/arm64/amu.rst rename to Documentation/translations/zh_CN/arch/arm64/amu.rst index ab7180f91394f89d14098bf641ff424fd89fc66e..f8e09fd21ef5433c251563d966258857acb1b118 100644 --- a/Documentation/translations/zh_CN/arm64/amu.rst +++ b/Documentation/translations/zh_CN/arch/arm64/amu.rst @@ -1,6 +1,6 @@ -.. include:: ../disclaimer-zh_CN.rst +.. include:: ../../disclaimer-zh_CN.rst -:Original: :ref:`Documentation/arm64/amu.rst ` +:Original: :ref:`Documentation/arch/arm64/amu.rst ` Translator: Bailu Lin diff --git a/Documentation/translations/zh_CN/arm64/booting.txt b/Documentation/translations/zh_CN/arch/arm64/booting.txt similarity index 98% rename from Documentation/translations/zh_CN/arm64/booting.txt rename to Documentation/translations/zh_CN/arch/arm64/booting.txt index 5b0164132c712cd5da47657a074b06f24e3a9be9..630eb32a88549677c723d047737e7204d8ed15fa 100644 --- a/Documentation/translations/zh_CN/arm64/booting.txt +++ b/Documentation/translations/zh_CN/arch/arm64/booting.txt @@ -1,4 +1,4 @@ -Chinese translated version of Documentation/arm64/booting.rst +Chinese translated version of Documentation/arch/arm64/booting.rst If you have any comment or update to the content, please contact the original document maintainer directly. However, if you have a problem @@ -10,7 +10,7 @@ M: Will Deacon zh_CN: Fu Wei C: 55f058e7574c3615dea4615573a19bdb258696c6 --------------------------------------------------------------------- -Documentation/arm64/booting.rst 的中文翻译 +Documentation/arch/arm64/booting.rst 的中文翻译 如果想评论或更新本文的内容,请直接联系原文档的维护者。如果你使用英文 交流有困难的话,也可以向中文版维护者求助。如果本翻译更新不及时或者翻 diff --git a/Documentation/translations/zh_CN/arm64/elf_hwcaps.rst b/Documentation/translations/zh_CN/arch/arm64/elf_hwcaps.rst similarity index 94% rename from Documentation/translations/zh_CN/arm64/elf_hwcaps.rst rename to Documentation/translations/zh_CN/arch/arm64/elf_hwcaps.rst index 9aa4637eac979c6c2c50ec920a7f2fd38ed9d5ce..f60ac1580d3ee97ead2c153037dcd8e7a68a284f 100644 --- a/Documentation/translations/zh_CN/arm64/elf_hwcaps.rst +++ b/Documentation/translations/zh_CN/arch/arm64/elf_hwcaps.rst @@ -1,6 +1,6 @@ -.. include:: ../disclaimer-zh_CN.rst +.. include:: ../../disclaimer-zh_CN.rst -:Original: :ref:`Documentation/arm64/elf_hwcaps.rst ` +:Original: :ref:`Documentation/arch/arm64/elf_hwcaps.rst ` Translator: Bailu Lin @@ -92,7 +92,7 @@ HWCAP_ASIMDHP ID_AA64PFR0_EL1.AdvSIMD == 0b0001 表示有此功能。 HWCAP_CPUID - 根据 Documentation/arm64/cpu-feature-registers.rst 描述,EL0 可以访问 + 根据 Documentation/arch/arm64/cpu-feature-registers.rst 描述,EL0 可以访问 某些 ID 寄存器。 这些 ID 寄存器可能表示功能的可用性。 @@ -152,12 +152,12 @@ HWCAP_SB ID_AA64ISAR1_EL1.SB == 0b0001 表示有此功能。 HWCAP_PACA - 如 Documentation/arm64/pointer-authentication.rst 所描述, + 如 Documentation/arch/arm64/pointer-authentication.rst 所描述, ID_AA64ISAR1_EL1.APA == 0b0001 或 ID_AA64ISAR1_EL1.API == 0b0001 表示有此功能。 HWCAP_PACG - 如 Documentation/arm64/pointer-authentication.rst 所描述, + 如 Documentation/arch/arm64/pointer-authentication.rst 所描述, ID_AA64ISAR1_EL1.GPA == 0b0001 或 ID_AA64ISAR1_EL1.GPI == 0b0001 表示有此功能。 diff --git a/Documentation/translations/zh_CN/arm64/hugetlbpage.rst b/Documentation/translations/zh_CN/arch/arm64/hugetlbpage.rst similarity index 91% rename from Documentation/translations/zh_CN/arm64/hugetlbpage.rst rename to Documentation/translations/zh_CN/arch/arm64/hugetlbpage.rst index 13304d269d0b9f09f35e430453c0820244b54981..8079eadde29ad3b7415d03db0b51018715c9d53c 100644 --- a/Documentation/translations/zh_CN/arm64/hugetlbpage.rst +++ b/Documentation/translations/zh_CN/arch/arm64/hugetlbpage.rst @@ -1,6 +1,6 @@ -.. include:: ../disclaimer-zh_CN.rst +.. include:: ../../disclaimer-zh_CN.rst -:Original: :ref:`Documentation/arm64/hugetlbpage.rst ` +:Original: :ref:`Documentation/arch/arm64/hugetlbpage.rst ` Translator: Bailu Lin diff --git a/Documentation/translations/zh_CN/arm64/index.rst b/Documentation/translations/zh_CN/arch/arm64/index.rst similarity index 63% rename from Documentation/translations/zh_CN/arm64/index.rst rename to Documentation/translations/zh_CN/arch/arm64/index.rst index 57dc5de5ccc5afd3ab182593e4032623dbf854ea..e12b9f6e5d6c3995caf7b2569f09cc12cf0dc367 100644 --- a/Documentation/translations/zh_CN/arm64/index.rst +++ b/Documentation/translations/zh_CN/arch/arm64/index.rst @@ -1,6 +1,6 @@ -.. include:: ../disclaimer-zh_CN.rst +.. include:: ../../disclaimer-zh_CN.rst -:Original: :ref:`Documentation/arm64/index.rst ` +:Original: :ref:`Documentation/arch/arm64/index.rst ` :Translator: Bailu Lin .. _cn_arm64_index: diff --git a/Documentation/translations/zh_CN/arm64/legacy_instructions.txt b/Documentation/translations/zh_CN/arch/arm64/legacy_instructions.txt similarity index 95% rename from Documentation/translations/zh_CN/arm64/legacy_instructions.txt rename to Documentation/translations/zh_CN/arch/arm64/legacy_instructions.txt index e295cf75f606ed3c271ee1952fbb1ae4ceab88b6..e469fccbe35609e280bbb6806ad967eb2f41a544 100644 --- a/Documentation/translations/zh_CN/arm64/legacy_instructions.txt +++ b/Documentation/translations/zh_CN/arch/arm64/legacy_instructions.txt @@ -1,4 +1,4 @@ -Chinese translated version of Documentation/arm64/legacy_instructions.rst +Chinese translated version of Documentation/arch/arm64/legacy_instructions.rst If you have any comment or update to the content, please contact the original document maintainer directly. However, if you have a problem @@ -10,7 +10,7 @@ Maintainer: Punit Agrawal Suzuki K. Poulose Chinese maintainer: Fu Wei --------------------------------------------------------------------- -Documentation/arm64/legacy_instructions.rst 的中文翻译 +Documentation/arch/arm64/legacy_instructions.rst 的中文翻译 如果想评论或更新本文的内容,请直接联系原文档的维护者。如果你使用英文 交流有困难的话,也可以向中文版维护者求助。如果本翻译更新不及时或者翻 diff --git a/Documentation/translations/zh_CN/arm64/memory.txt b/Documentation/translations/zh_CN/arch/arm64/memory.txt similarity index 97% rename from Documentation/translations/zh_CN/arm64/memory.txt rename to Documentation/translations/zh_CN/arch/arm64/memory.txt index be20f8228b91388356f4a3622eac013db8d6487a..c6962e9cb9f8f0c1a0adef4384aae7e9a8d4a00a 100644 --- a/Documentation/translations/zh_CN/arm64/memory.txt +++ b/Documentation/translations/zh_CN/arch/arm64/memory.txt @@ -1,4 +1,4 @@ -Chinese translated version of Documentation/arm64/memory.rst +Chinese translated version of Documentation/arch/arm64/memory.rst If you have any comment or update to the content, please contact the original document maintainer directly. However, if you have a problem @@ -9,7 +9,7 @@ or if there is a problem with the translation. Maintainer: Catalin Marinas Chinese maintainer: Fu Wei --------------------------------------------------------------------- -Documentation/arm64/memory.rst 的中文翻译 +Documentation/arch/arm64/memory.rst 的中文翻译 如果想评论或更新本文的内容,请直接联系原文档的维护者。如果你使用英文 交流有困难的话,也可以向中文版维护者求助。如果本翻译更新不及时或者翻 diff --git a/Documentation/translations/zh_CN/arm64/perf.rst b/Documentation/translations/zh_CN/arch/arm64/perf.rst similarity index 96% rename from Documentation/translations/zh_CN/arm64/perf.rst rename to Documentation/translations/zh_CN/arch/arm64/perf.rst index 9bf21d73f4d1c08fe63d03d1821c4fbbd6f869d4..6be72704e659189a389f13b093ca9a72a9849c63 100644 --- a/Documentation/translations/zh_CN/arm64/perf.rst +++ b/Documentation/translations/zh_CN/arch/arm64/perf.rst @@ -1,8 +1,8 @@ .. SPDX-License-Identifier: GPL-2.0 -.. include:: ../disclaimer-zh_CN.rst +.. include:: ../../disclaimer-zh_CN.rst -:Original: :ref:`Documentation/arm64/perf.rst ` +:Original: :ref:`Documentation/arch/arm64/perf.rst ` Translator: Bailu Lin diff --git a/Documentation/translations/zh_CN/arm64/silicon-errata.txt b/Documentation/translations/zh_CN/arch/arm64/silicon-errata.txt similarity index 97% rename from Documentation/translations/zh_CN/arm64/silicon-errata.txt rename to Documentation/translations/zh_CN/arch/arm64/silicon-errata.txt index 440c59ac7dce83ae9f930563f2536c827791a21a..f4767ffdd61de07f2fa4481ba047576d6858e4e1 100644 --- a/Documentation/translations/zh_CN/arm64/silicon-errata.txt +++ b/Documentation/translations/zh_CN/arch/arm64/silicon-errata.txt @@ -1,4 +1,4 @@ -Chinese translated version of Documentation/arm64/silicon-errata.rst +Chinese translated version of Documentation/arch/arm64/silicon-errata.rst If you have any comment or update to the content, please contact the original document maintainer directly. However, if you have a problem @@ -10,7 +10,7 @@ M: Will Deacon zh_CN: Fu Wei C: 1926e54f115725a9248d0c4c65c22acaf94de4c4 --------------------------------------------------------------------- -Documentation/arm64/silicon-errata.rst 的中文翻译 +Documentation/arch/arm64/silicon-errata.rst 的中文翻译 如果想评论或更新本文的内容,请直接联系原文档的维护者。如果你使用英文 交流有困难的话,也可以向中文版维护者求助。如果本翻译更新不及时或者翻 diff --git a/Documentation/translations/zh_CN/arm64/tagged-pointers.txt b/Documentation/translations/zh_CN/arch/arm64/tagged-pointers.txt similarity index 94% rename from Documentation/translations/zh_CN/arm64/tagged-pointers.txt rename to Documentation/translations/zh_CN/arch/arm64/tagged-pointers.txt index 77ac3548a16d10cf2338dbdcd7b4c51c99486f83..27577c3c5e3f6b3b95182bde37db76a000322574 100644 --- a/Documentation/translations/zh_CN/arm64/tagged-pointers.txt +++ b/Documentation/translations/zh_CN/arch/arm64/tagged-pointers.txt @@ -1,4 +1,4 @@ -Chinese translated version of Documentation/arm64/tagged-pointers.rst +Chinese translated version of Documentation/arch/arm64/tagged-pointers.rst If you have any comment or update to the content, please contact the original document maintainer directly. However, if you have a problem @@ -9,7 +9,7 @@ or if there is a problem with the translation. Maintainer: Will Deacon Chinese maintainer: Fu Wei --------------------------------------------------------------------- -Documentation/arm64/tagged-pointers.rst 的中文翻译 +Documentation/arch/arm64/tagged-pointers.rst 的中文翻译 如果想评论或更新本文的内容,请直接联系原文档的维护者。如果你使用英文 交流有困难的话,也可以向中文版维护者求助。如果本翻译更新不及时或者翻 diff --git a/Documentation/translations/zh_CN/arch/index.rst b/Documentation/translations/zh_CN/arch/index.rst index 908ea131bb1c8eca0bf5ee4cb5a18dd4d8d885fb..6fa0cb6710090f5e6d641b36781454fc13911443 100644 --- a/Documentation/translations/zh_CN/arch/index.rst +++ b/Documentation/translations/zh_CN/arch/index.rst @@ -9,7 +9,7 @@ :maxdepth: 2 ../mips/index - ../arm64/index + arm64/index ../riscv/index openrisc/index parisc/index diff --git a/Documentation/translations/zh_CN/driver-api/gpio/legacy.rst b/Documentation/translations/zh_CN/driver-api/gpio/legacy.rst index 84ce2322fdbac6ffd045dd22c4935073891490a8..aeccff777170903f56a3eab7bbb231aa25f8676c 100644 --- a/Documentation/translations/zh_CN/driver-api/gpio/legacy.rst +++ b/Documentation/translations/zh_CN/driver-api/gpio/legacy.rst @@ -153,8 +153,7 @@ get/set(获取/设置)函数调用没法返回错误,且有可能是配置错误 大多数 GPIO 控制器可以通过内存读/写指令来访问。这些指令不会休眠,可以 安全地在硬(非线程)中断例程和类似的上下文中完成。 -对于那些用 gpio_cansleep()测试总是返回失败的 GPIO(见下文),使用 -以下的函数访问:: +对于那些 GPIO,使用以下的函数访问:: /* GPIO 输入:返回零或非零 */ int gpio_get_value(unsigned gpio); @@ -186,11 +185,6 @@ GPIO值是布尔值,零表示低电平,非零表示高电平。当读取一 GPIO 值的命令需要等待其信息排到队首才发送命令,再获得其反馈。期间需要 休眠,这不能在 IRQ 例程(中断上下文)中执行。 -支持此类 GPIO 的平台通过以下函数返回非零值来区分出这种 GPIO。(此函数需要 -一个之前通过 gpio_request 分配到的有效 GPIO 编号):: - - int gpio_cansleep(unsigned gpio); - 为了访问这种 GPIO,内核定义了一套不同的函数:: /* GPIO 输入:返回零或非零 ,可能会休眠 */ @@ -199,7 +193,6 @@ GPIO 值的命令需要等待其信息排到队首才发送命令,再获得其 /* GPIO 输出,可能会休眠 */ void gpio_set_value_cansleep(unsigned gpio, int value); - 访问这样的 GPIO 需要一个允许休眠的上下文,例如线程 IRQ 处理例程,并用以上的 访问函数替换那些没有 cansleep()后缀的自旋锁安全访问函数。 @@ -294,11 +287,6 @@ gpio_request()前将这类细节配置好,例如使用引脚控制子系统的 * GPIOF_INIT_LOW - 在作为输出时,初始值为低电平 * GPIOF_INIT_HIGH - 在作为输出时,初始值为高电平 - * GPIOF_OPEN_DRAIN - gpio引脚为开漏信号 - * GPIOF_OPEN_SOURCE - gpio引脚为源极开路信号 - - * GPIOF_EXPORT_DIR_FIXED - 将 gpio 导出到 sysfs,并保持方向 - * GPIOF_EXPORT_DIR_CHANGEABLE - 同样是导出, 但允许改变方向 因为 GPIOF_INIT_* 仅有在配置为输出的时候才存在,所以有效的组合为: @@ -306,18 +294,6 @@ gpio_request()前将这类细节配置好,例如使用引脚控制子系统的 * GPIOF_OUT_INIT_LOW - 配置为输出,并初始化为低电平 * GPIOF_OUT_INIT_HIGH - 配置为输出,并初始化为高电平 -当设置 flag 为 GPIOF_OPEN_DRAIN 时,则假设引脚是开漏信号。这样的引脚 -将不会在输出模式下置1。这样的引脚需要连接上拉电阻。通过使能这个标志,gpio库 -将会在被要求输出模式下置1时将引脚变为输入状态来使引脚置高。引脚在输出模式下 -通过置0使其输出低电平。 - -当设置 flag 为 GPIOF_OPEN_SOURCE 时,则假设引脚为源极开路信号。这样的引脚 -将不会在输出模式下置0。这样的引脚需要连接下拉电阻。通过使能这个标志,gpio库 -将会在被要求输出模式下置0时将引脚变为输入状态来使引脚置低。引脚在输出模式下 -通过置1使其输出高电平。 - -将来这些标志可能扩展到支持更多的属性。 - 更进一步,为了更简单地声明/释放多个 GPIO,'struct gpio'被引进来封装所有 这三个领域:: @@ -500,8 +476,8 @@ GPIO 实现者的框架(可选) 为了支持这个框架,一个平台的 Kconfig 文件将会 "select"(选择) ARCH_REQUIRE_GPIOLIB 或 ARCH_WANT_OPTIONAL_GPIOLIB,并让它的 - 包含 ,同时定义三个方法: -gpio_get_value()、gpio_set_value()和 gpio_cansleep()。 + 包含 ,同时定义两个方法: +gpio_get_value()、gpio_set_value()。 它也应提供一个 ARCH_NR_GPIOS 的定义值,这样可以更好地反映该平台 GPIO 的实际数量,节省静态表的空间。(这个定义值应该包含片上系统内建 GPIO 和 @@ -519,7 +495,6 @@ ARCH_WANT_OPTIONAL_GPIOLIB 意味着 gpiolib 核心默认关闭,且用户可以 #define gpio_get_value __gpio_get_value #define gpio_set_value __gpio_set_value - #define gpio_cansleep __gpio_cansleep 这些定义可以用更理想的实现方法替代,那就是使用经过逻辑优化的内联函数来访问 基于特定片上系统的 GPIO。例如,若引用的 GPIO (寄存器位偏移)是常量“12”, diff --git a/Documentation/translations/zh_CN/mm/page_migration.rst b/Documentation/translations/zh_CN/mm/page_migration.rst index 076081dc163546f6a911f07620441804693fa014..f95063826a150d99a461d7cd7fc5d3b5402494df 100644 --- a/Documentation/translations/zh_CN/mm/page_migration.rst +++ b/Documentation/translations/zh_CN/mm/page_migration.rst @@ -55,7 +55,7 @@ mbind()设置一个新的内存策略。一个进程的页面也可以通过sys_ 消失。它还可以防止交换器或其他扫描器遇到该页。 -2. 我们需要有一个new_page_t类型的函数,可以传递给migrate_pages()。这个函数应该计算 +2. 我们需要有一个new_folio_t类型的函数,可以传递给migrate_pages()。这个函数应该计算 出如何在给定的旧页面中分配正确的新页面。 3. migrate_pages()函数被调用,它试图进行迁移。它将调用该函数为每个被考虑迁移的页面分 diff --git a/Documentation/translations/zh_CN/process/2.Process.rst b/Documentation/translations/zh_CN/process/2.Process.rst index 4a6ed021949437d97b8b9c4c60231049b0115973..e68c9de0f7f87edcba7db56464156edad792acfb 100644 --- a/Documentation/translations/zh_CN/process/2.Process.rst +++ b/Documentation/translations/zh_CN/process/2.Process.rst @@ -358,7 +358,7 @@ Andrew Morton 为有抱负的内核开发人员提供了如下建议 机器上始终完美运行”。通常的方法是和其他人一起解决问题(这可能需 要坚持!),但就是如此——这是内核开发的一部分。 -(http://lwn.net/articles/283982/) +(http://lwn.net/Articles/283982/) 在没有明显问题需要解决的情况下,通常建议开发人员查看当前的回归和开放缺陷 列表。从来都不缺少需要解决的问题;通过解决这些问题,开发人员将从该过程获得 diff --git a/Documentation/translations/zh_CN/process/3.Early-stage.rst b/Documentation/translations/zh_CN/process/3.Early-stage.rst index de53dd12e91183d700b4a3c752af05e73134444a..2caba4753b75369260756425b1507aadf4fdd0fe 100644 --- a/Documentation/translations/zh_CN/process/3.Early-stage.rst +++ b/Documentation/translations/zh_CN/process/3.Early-stage.rst @@ -44,7 +44,7 @@ 试图向这些人传达用户需求是浪费时间。他们太“聪明”了,根本听不到少数 人的话。 -(http://lwn.net/articles/131776/) +(http://lwn.net/Articles/131776/) 实际情况却是不同的;与特定模块相比,内核开发人员更关心系统稳定性、长期维护 以及找到问题的正确解决方案。这个故事的寓意是把重点放在问题上——而不是具体的 diff --git a/Documentation/translations/zh_CN/process/4.Coding.rst b/Documentation/translations/zh_CN/process/4.Coding.rst index 94f7f866f10397913a5a62f5faf820a5fd5f1fa8..7cac9424f5d55bd93fa061eff72ea2412b26aa4a 100644 --- a/Documentation/translations/zh_CN/process/4.Coding.rst +++ b/Documentation/translations/zh_CN/process/4.Coding.rst @@ -149,7 +149,7 @@ Linus对这个问题给出了最佳答案: 所以我们不会通过引入新问题来修复错误。这种方式是靠不住的,没人知道 是否真的有进展。是前进两步、后退一步,还是前进一步、后退两步? -(http://lwn.net/articles/243460/) +(http://lwn.net/Articles/243460/) 特别不受欢迎的一种回归类型是用户空间ABI的任何变化。一旦接口被导出到用户空间, 就必须无限期地支持它。这一事实使得用户空间接口的创建特别具有挑战性:因为它们 diff --git a/Documentation/translations/zh_CN/process/7.AdvancedTopics.rst b/Documentation/translations/zh_CN/process/7.AdvancedTopics.rst index 6d0dadae13b12ad1fa3313e5de468b202db480a3..57beca02181ce6b57665ac969e5d5458669443e3 100644 --- a/Documentation/translations/zh_CN/process/7.AdvancedTopics.rst +++ b/Documentation/translations/zh_CN/process/7.AdvancedTopics.rst @@ -98,7 +98,7 @@ Git提供了一些强大的工具,可以让您重写开发历史。一个不 你可以给我发补丁,但当我从你那里拉取一个Git补丁时,我需要知道你清楚 自己在做什么,我需要能够相信事情而 *无需* 手动检查每个单独的更改。 -(http://lwn.net/articles/224135/)。 +(http://lwn.net/Articles/224135/)。 为了避免这种情况,请确保给定分支中的所有补丁都与相关主题紧密相关;“驱动程序 修复”分支不应更改核心内存管理代码。而且,最重要的是,不要使用Git树来绕过 diff --git a/Documentation/translations/zh_TW/arm64/amu.rst b/Documentation/translations/zh_TW/arch/arm64/amu.rst similarity index 97% rename from Documentation/translations/zh_TW/arm64/amu.rst rename to Documentation/translations/zh_TW/arch/arm64/amu.rst index ffdc466e0f62b14411befa85ad631f6b92261af1..f947a6c7369f7c0b4b41695aa77bbb7f50cb6338 100644 --- a/Documentation/translations/zh_TW/arm64/amu.rst +++ b/Documentation/translations/zh_TW/arch/arm64/amu.rst @@ -1,8 +1,8 @@ .. SPDX-License-Identifier: GPL-2.0 -.. include:: ../disclaimer-zh_TW.rst +.. include:: ../../disclaimer-zh_TW.rst -:Original: :ref:`Documentation/arm64/amu.rst ` +:Original: :ref:`Documentation/arch/arm64/amu.rst ` Translator: Bailu Lin Hu Haowen diff --git a/Documentation/translations/zh_TW/arm64/booting.txt b/Documentation/translations/zh_TW/arch/arm64/booting.txt similarity index 98% rename from Documentation/translations/zh_TW/arm64/booting.txt rename to Documentation/translations/zh_TW/arch/arm64/booting.txt index b9439dd540126ef300d302cebfae62954f111398..24817b8b70cd037842a224bd9d45ef5b8546c535 100644 --- a/Documentation/translations/zh_TW/arm64/booting.txt +++ b/Documentation/translations/zh_TW/arch/arm64/booting.txt @@ -1,6 +1,6 @@ SPDX-License-Identifier: GPL-2.0 -Chinese translated version of Documentation/arm64/booting.rst +Chinese translated version of Documentation/arch/arm64/booting.rst If you have any comment or update to the content, please contact the original document maintainer directly. However, if you have a problem @@ -13,7 +13,7 @@ zh_CN: Fu Wei zh_TW: Hu Haowen C: 55f058e7574c3615dea4615573a19bdb258696c6 --------------------------------------------------------------------- -Documentation/arm64/booting.rst 的中文翻譯 +Documentation/arch/arm64/booting.rst 的中文翻譯 如果想評論或更新本文的內容,請直接聯繫原文檔的維護者。如果你使用英文 交流有困難的話,也可以向中文版維護者求助。如果本翻譯更新不及時或者翻 diff --git a/Documentation/translations/zh_TW/arm64/elf_hwcaps.rst b/Documentation/translations/zh_TW/arch/arm64/elf_hwcaps.rst similarity index 94% rename from Documentation/translations/zh_TW/arm64/elf_hwcaps.rst rename to Documentation/translations/zh_TW/arch/arm64/elf_hwcaps.rst index 3eb1c623ce31b0f3a85a1fba6006f0dcdb170c67..fca3c6ff7b939b69f39a95c750e87156604edf88 100644 --- a/Documentation/translations/zh_TW/arm64/elf_hwcaps.rst +++ b/Documentation/translations/zh_TW/arch/arm64/elf_hwcaps.rst @@ -1,8 +1,8 @@ .. SPDX-License-Identifier: GPL-2.0 -.. include:: ../disclaimer-zh_TW.rst +.. include:: ../../disclaimer-zh_TW.rst -:Original: :ref:`Documentation/arm64/elf_hwcaps.rst ` +:Original: :ref:`Documentation/arch/arm64/elf_hwcaps.rst ` Translator: Bailu Lin Hu Haowen @@ -95,7 +95,7 @@ HWCAP_ASIMDHP ID_AA64PFR0_EL1.AdvSIMD == 0b0001 表示有此功能。 HWCAP_CPUID - 根據 Documentation/arm64/cpu-feature-registers.rst 描述,EL0 可以訪問 + 根據 Documentation/arch/arm64/cpu-feature-registers.rst 描述,EL0 可以訪問 某些 ID 寄存器。 這些 ID 寄存器可能表示功能的可用性。 @@ -155,12 +155,12 @@ HWCAP_SB ID_AA64ISAR1_EL1.SB == 0b0001 表示有此功能。 HWCAP_PACA - 如 Documentation/arm64/pointer-authentication.rst 所描述, + 如 Documentation/arch/arm64/pointer-authentication.rst 所描述, ID_AA64ISAR1_EL1.APA == 0b0001 或 ID_AA64ISAR1_EL1.API == 0b0001 表示有此功能。 HWCAP_PACG - 如 Documentation/arm64/pointer-authentication.rst 所描述, + 如 Documentation/arch/arm64/pointer-authentication.rst 所描述, ID_AA64ISAR1_EL1.GPA == 0b0001 或 ID_AA64ISAR1_EL1.GPI == 0b0001 表示有此功能。 diff --git a/Documentation/translations/zh_TW/arm64/hugetlbpage.rst b/Documentation/translations/zh_TW/arch/arm64/hugetlbpage.rst similarity index 91% rename from Documentation/translations/zh_TW/arm64/hugetlbpage.rst rename to Documentation/translations/zh_TW/arch/arm64/hugetlbpage.rst index 846b500dae97cb8d3920d3df52a9b09cceea4f60..10feb329dfb8432689b28435b2c43893959081df 100644 --- a/Documentation/translations/zh_TW/arm64/hugetlbpage.rst +++ b/Documentation/translations/zh_TW/arch/arm64/hugetlbpage.rst @@ -1,8 +1,8 @@ .. SPDX-License-Identifier: GPL-2.0 -.. include:: ../disclaimer-zh_TW.rst +.. include:: ../../disclaimer-zh_TW.rst -:Original: :ref:`Documentation/arm64/hugetlbpage.rst ` +:Original: :ref:`Documentation/arch/arm64/hugetlbpage.rst ` Translator: Bailu Lin Hu Haowen diff --git a/Documentation/translations/zh_TW/arm64/index.rst b/Documentation/translations/zh_TW/arch/arm64/index.rst similarity index 71% rename from Documentation/translations/zh_TW/arm64/index.rst rename to Documentation/translations/zh_TW/arch/arm64/index.rst index 2322783f3881ce4f0019f1da3a5cfa1cf2afdc87..68befee14b99aae4797a3b872b1a19b1ed1c80ab 100644 --- a/Documentation/translations/zh_TW/arm64/index.rst +++ b/Documentation/translations/zh_TW/arch/arm64/index.rst @@ -1,8 +1,8 @@ .. SPDX-License-Identifier: GPL-2.0 -.. include:: ../disclaimer-zh_TW.rst +.. include:: ../../disclaimer-zh_TW.rst -:Original: :ref:`Documentation/arm64/index.rst ` +:Original: :ref:`Documentation/arch/arm64/index.rst ` :Translator: Bailu Lin Hu Haowen diff --git a/Documentation/translations/zh_TW/arm64/legacy_instructions.txt b/Documentation/translations/zh_TW/arch/arm64/legacy_instructions.txt similarity index 96% rename from Documentation/translations/zh_TW/arm64/legacy_instructions.txt rename to Documentation/translations/zh_TW/arch/arm64/legacy_instructions.txt index 6d4454f77b9e2153b90f7942484caf485f49f847..3c915df9836c3153ca9579f2fe8259048c6be4b6 100644 --- a/Documentation/translations/zh_TW/arm64/legacy_instructions.txt +++ b/Documentation/translations/zh_TW/arch/arm64/legacy_instructions.txt @@ -1,6 +1,6 @@ SPDX-License-Identifier: GPL-2.0 -Chinese translated version of Documentation/arm64/legacy_instructions.rst +Chinese translated version of Documentation/arch/arm64/legacy_instructions.rst If you have any comment or update to the content, please contact the original document maintainer directly. However, if you have a problem @@ -13,7 +13,7 @@ Maintainer: Punit Agrawal Chinese maintainer: Fu Wei Traditional Chinese maintainer: Hu Haowen --------------------------------------------------------------------- -Documentation/arm64/legacy_instructions.rst 的中文翻譯 +Documentation/arch/arm64/legacy_instructions.rst 的中文翻譯 如果想評論或更新本文的內容,請直接聯繫原文檔的維護者。如果你使用英文 交流有困難的話,也可以向中文版維護者求助。如果本翻譯更新不及時或者翻 diff --git a/Documentation/translations/zh_TW/arm64/memory.txt b/Documentation/translations/zh_TW/arch/arm64/memory.txt similarity index 97% rename from Documentation/translations/zh_TW/arm64/memory.txt rename to Documentation/translations/zh_TW/arch/arm64/memory.txt index 99c2b78b5674982c79d5fcef76a88621b8949bd2..2437380a26d8a52573bc6cb95c14e7a0fb519c93 100644 --- a/Documentation/translations/zh_TW/arm64/memory.txt +++ b/Documentation/translations/zh_TW/arch/arm64/memory.txt @@ -1,6 +1,6 @@ SPDX-License-Identifier: GPL-2.0 -Chinese translated version of Documentation/arm64/memory.rst +Chinese translated version of Documentation/arch/arm64/memory.rst If you have any comment or update to the content, please contact the original document maintainer directly. However, if you have a problem @@ -12,7 +12,7 @@ Maintainer: Catalin Marinas Chinese maintainer: Fu Wei Traditional Chinese maintainer: Hu Haowen --------------------------------------------------------------------- -Documentation/arm64/memory.rst 的中文翻譯 +Documentation/arch/arm64/memory.rst 的中文翻譯 如果想評論或更新本文的內容,請直接聯繫原文檔的維護者。如果你使用英文 交流有困難的話,也可以向中文版維護者求助。如果本翻譯更新不及時或者翻 diff --git a/Documentation/translations/zh_TW/arm64/perf.rst b/Documentation/translations/zh_TW/arch/arm64/perf.rst similarity index 96% rename from Documentation/translations/zh_TW/arm64/perf.rst rename to Documentation/translations/zh_TW/arch/arm64/perf.rst index f1ffd55dfe50a8c4f528e4c1b33eec8685a97d11..3b39997a52ebb7a0530495b9e3e54a03fe895e59 100644 --- a/Documentation/translations/zh_TW/arm64/perf.rst +++ b/Documentation/translations/zh_TW/arch/arm64/perf.rst @@ -1,8 +1,8 @@ .. SPDX-License-Identifier: GPL-2.0 -.. include:: ../disclaimer-zh_TW.rst +.. include:: ../../disclaimer-zh_TW.rst -:Original: :ref:`Documentation/arm64/perf.rst ` +:Original: :ref:`Documentation/arch/arm64/perf.rst ` Translator: Bailu Lin Hu Haowen diff --git a/Documentation/translations/zh_TW/arm64/silicon-errata.txt b/Documentation/translations/zh_TW/arch/arm64/silicon-errata.txt similarity index 97% rename from Documentation/translations/zh_TW/arm64/silicon-errata.txt rename to Documentation/translations/zh_TW/arch/arm64/silicon-errata.txt index bf2077197504bc7f3dce0b96522899fbdda37217..66c3a350645863061237a10dd66a296c71cd1cdd 100644 --- a/Documentation/translations/zh_TW/arm64/silicon-errata.txt +++ b/Documentation/translations/zh_TW/arch/arm64/silicon-errata.txt @@ -1,6 +1,6 @@ SPDX-License-Identifier: GPL-2.0 -Chinese translated version of Documentation/arm64/silicon-errata.rst +Chinese translated version of Documentation/arch/arm64/silicon-errata.rst If you have any comment or update to the content, please contact the original document maintainer directly. However, if you have a problem @@ -13,7 +13,7 @@ zh_CN: Fu Wei zh_TW: Hu Haowen C: 1926e54f115725a9248d0c4c65c22acaf94de4c4 --------------------------------------------------------------------- -Documentation/arm64/silicon-errata.rst 的中文翻譯 +Documentation/arch/arm64/silicon-errata.rst 的中文翻譯 如果想評論或更新本文的內容,請直接聯繫原文檔的維護者。如果你使用英文 交流有困難的話,也可以向中文版維護者求助。如果本翻譯更新不及時或者翻 diff --git a/Documentation/translations/zh_TW/arm64/tagged-pointers.txt b/Documentation/translations/zh_TW/arch/arm64/tagged-pointers.txt similarity index 95% rename from Documentation/translations/zh_TW/arm64/tagged-pointers.txt rename to Documentation/translations/zh_TW/arch/arm64/tagged-pointers.txt index 87f88628401a3c14dbb44dd2493f51172ddf0202..b7f683f20ed1402285c3dfae507b703a3d4c7554 100644 --- a/Documentation/translations/zh_TW/arm64/tagged-pointers.txt +++ b/Documentation/translations/zh_TW/arch/arm64/tagged-pointers.txt @@ -1,6 +1,6 @@ SPDX-License-Identifier: GPL-2.0 -Chinese translated version of Documentation/arm64/tagged-pointers.rst +Chinese translated version of Documentation/arch/arm64/tagged-pointers.rst If you have any comment or update to the content, please contact the original document maintainer directly. However, if you have a problem @@ -12,7 +12,7 @@ Maintainer: Will Deacon Chinese maintainer: Fu Wei Traditional Chinese maintainer: Hu Haowen --------------------------------------------------------------------- -Documentation/arm64/tagged-pointers.rst 的中文翻譯 +Documentation/arch/arm64/tagged-pointers.rst 的中文翻譯 如果想評論或更新本文的內容,請直接聯繫原文檔的維護者。如果你使用英文 交流有困難的話,也可以向中文版維護者求助。如果本翻譯更新不及時或者翻 diff --git a/Documentation/translations/zh_TW/gpio.txt b/Documentation/translations/zh_TW/gpio.txt index 62e560ffe62833084ce8ae6647181d20b2e824a8..b93788a2628b6af6b0a94d5a489d532c905d9c7f 100644 --- a/Documentation/translations/zh_TW/gpio.txt +++ b/Documentation/translations/zh_TW/gpio.txt @@ -161,8 +161,7 @@ get/set(獲取/設置)函數調用沒法返回錯誤,且有可能是配置錯誤 大多數 GPIO 控制器可以通過內存讀/寫指令來訪問。這些指令不會休眠,可以 安全地在硬(非線程)中斷例程和類似的上下文中完成。 -對於那些用 gpio_cansleep()測試總是返回失敗的 GPIO(見下文),使用 -以下的函數訪問: +對於那些 GPIO,使用以下的函數訪問: /* GPIO 輸入:返回零或非零 */ int gpio_get_value(unsigned gpio); @@ -193,11 +192,6 @@ GPIO值是布爾值,零表示低電平,非零表示高電平。當讀取一 GPIO 值的命令需要等待其信息排到隊首才發送命令,再獲得其反饋。期間需要 休眠,這不能在 IRQ 例程(中斷上下文)中執行。 -支持此類 GPIO 的平台通過以下函數返回非零值來區分出這種 GPIO。(此函數需要 -一個之前通過 gpio_request 分配到的有效 GPIO 編號): - - int gpio_cansleep(unsigned gpio); - 爲了訪問這種 GPIO,內核定義了一套不同的函數: /* GPIO 輸入:返回零或非零 ,可能會休眠 */ @@ -206,7 +200,6 @@ GPIO 值的命令需要等待其信息排到隊首才發送命令,再獲得其 /* GPIO 輸出,可能會休眠 */ void gpio_set_value_cansleep(unsigned gpio, int value); - 訪問這樣的 GPIO 需要一個允許休眠的上下文,例如線程 IRQ 處理例程,並用以上的 訪問函數替換那些沒有 cansleep()後綴的自旋鎖安全訪問函數。 @@ -300,11 +293,6 @@ gpio_request()前將這類細節配置好,例如使用 pinctrl 子系統的映 * GPIOF_INIT_LOW - 在作爲輸出時,初始值爲低電平 * GPIOF_INIT_HIGH - 在作爲輸出時,初始值爲高電平 - * GPIOF_OPEN_DRAIN - gpio引腳爲開漏信號 - * GPIOF_OPEN_SOURCE - gpio引腳爲源極開路信號 - - * GPIOF_EXPORT_DIR_FIXED - 將 gpio 導出到 sysfs,並保持方向 - * GPIOF_EXPORT_DIR_CHANGEABLE - 同樣是導出, 但允許改變方向 因爲 GPIOF_INIT_* 僅有在配置爲輸出的時候才存在,所以有效的組合爲: @@ -312,18 +300,6 @@ gpio_request()前將這類細節配置好,例如使用 pinctrl 子系統的映 * GPIOF_OUT_INIT_LOW - 配置爲輸出,並初始化爲低電平 * GPIOF_OUT_INIT_HIGH - 配置爲輸出,並初始化爲高電平 -當設置 flag 爲 GPIOF_OPEN_DRAIN 時,則假設引腳是開漏信號。這樣的引腳 -將不會在輸出模式下置1。這樣的引腳需要連接上拉電阻。通過使能這個標誌,gpio庫 -將會在被要求輸出模式下置1時將引腳變爲輸入狀態來使引腳置高。引腳在輸出模式下 -通過置0使其輸出低電平。 - -當設置 flag 爲 GPIOF_OPEN_SOURCE 時,則假設引腳爲源極開路信號。這樣的引腳 -將不會在輸出模式下置0。這樣的引腳需要連接下拉電阻。通過使能這個標誌,gpio庫 -將會在被要求輸出模式下置0時將引腳變爲輸入狀態來使引腳置低。引腳在輸出模式下 -通過置1使其輸出高電平。 - -將來這些標誌可能擴展到支持更多的屬性。 - 更進一步,爲了更簡單地聲明/釋放多個 GPIO,'struct gpio'被引進來封裝所有 這三個領域: @@ -466,8 +442,8 @@ GPIO 實現者的框架 (可選) ------- 爲了支持這個框架,一個平台的 Kconfig 文件將會 "select"(選擇) ARCH_REQUIRE_GPIOLIB 或 ARCH_WANT_OPTIONAL_GPIOLIB,並讓它的 - 包含 ,同時定義三個方法: -gpio_get_value()、gpio_set_value()和 gpio_cansleep()。 + 包含 ,同時定義二個方法: +gpio_get_value()、gpio_set_value()。 它也應提供一個 ARCH_NR_GPIOS 的定義值,這樣可以更好地反映該平台 GPIO 的實際數量,節省靜態表的空間。(這個定義值應該包含片上系統內建 GPIO 和 @@ -485,7 +461,6 @@ ARCH_WANT_OPTIONAL_GPIOLIB 意味著 gpiolib 核心默認關閉,且用戶可以 #define gpio_get_value __gpio_get_value #define gpio_set_value __gpio_set_value - #define gpio_cansleep __gpio_cansleep 這些定義可以用更理想的實現方法替代,那就是使用經過邏輯優化的內聯函數來訪問 基於特定片上系統的 GPIO。例如,若引用的 GPIO (寄存器位偏移)是常量「12」, diff --git a/Documentation/translations/zh_TW/index.rst b/Documentation/translations/zh_TW/index.rst index e97d7d5787515117ffc99cc4e8f57b16b586822c..e7c83868e78040a1a68a132715259d8839f4438f 100644 --- a/Documentation/translations/zh_TW/index.rst +++ b/Documentation/translations/zh_TW/index.rst @@ -150,7 +150,7 @@ TODOList: .. toctree:: :maxdepth: 2 - arm64/index + arch/arm64/index TODOList: diff --git a/Documentation/translations/zh_TW/process/2.Process.rst b/Documentation/translations/zh_TW/process/2.Process.rst index b01cdd3a39aea66bc7a7af727936f04e7271b05e..9d465df1f6c3695e36bba750afe5ff67d40698b0 100644 --- a/Documentation/translations/zh_TW/process/2.Process.rst +++ b/Documentation/translations/zh_TW/process/2.Process.rst @@ -361,7 +361,7 @@ Andrew Morton 爲有抱負的內核開發人員提供了如下建議 機器上始終完美運行」。通常的方法是和其他人一起解決問題(這可能需 要堅持!),但就是如此——這是內核開發的一部分。 -(http://lwn.net/articles/283982/) +(http://lwn.net/Articles/283982/) 在沒有明顯問題需要解決的情況下,通常建議開發人員查看當前的回歸和開放缺陷 列表。從來都不缺少需要解決的問題;通過解決這些問題,開發人員將從該過程獲得 diff --git a/Documentation/translations/zh_TW/process/3.Early-stage.rst b/Documentation/translations/zh_TW/process/3.Early-stage.rst index ab2a45fd65a42cc32c95d230d05200333cf35201..076873ca090507ab1dbc5fafbd716114abb57122 100644 --- a/Documentation/translations/zh_TW/process/3.Early-stage.rst +++ b/Documentation/translations/zh_TW/process/3.Early-stage.rst @@ -47,7 +47,7 @@ 試圖向這些人傳達用戶需求是浪費時間。他們太「聰明」了,根本聽不到少數 人的話。 -(http://lwn.net/articles/131776/) +(http://lwn.net/Articles/131776/) 實際情況卻是不同的;與特定模塊相比,內核開發人員更關心系統穩定性、長期維護 以及找到問題的正確解決方案。這個故事的寓意是把重點放在問題上——而不是具體的 diff --git a/Documentation/translations/zh_TW/process/4.Coding.rst b/Documentation/translations/zh_TW/process/4.Coding.rst index ccc3946227a042197fc0fe479f5e54ddefa65a10..7fc0344ed16bb6208ac6f54be70726d4cbd83705 100644 --- a/Documentation/translations/zh_TW/process/4.Coding.rst +++ b/Documentation/translations/zh_TW/process/4.Coding.rst @@ -152,7 +152,7 @@ Linus對這個問題給出了最佳答案: 所以我們不會通過引入新問題來修復錯誤。這種方式是靠不住的,沒人知道 是否真的有進展。是前進兩步、後退一步,還是前進一步、後退兩步? -(http://lwn.net/articles/243460/) +(http://lwn.net/Articles/243460/) 特別不受歡迎的一種回歸類型是用戶空間ABI的任何變化。一旦接口被導出到用戶空間, 就必須無限期地支持它。這一事實使得用戶空間接口的創建特別具有挑戰性:因爲它們 diff --git a/Documentation/translations/zh_TW/process/7.AdvancedTopics.rst b/Documentation/translations/zh_TW/process/7.AdvancedTopics.rst index 3de093d0f1708d74b9b198ffdd29e9826fb4a982..4fbc104a37ca12f1b980e9247beba5c30567da4a 100644 --- a/Documentation/translations/zh_TW/process/7.AdvancedTopics.rst +++ b/Documentation/translations/zh_TW/process/7.AdvancedTopics.rst @@ -101,7 +101,7 @@ Git提供了一些強大的工具,可以讓您重寫開發歷史。一個不 你可以給我發補丁,但當我從你那裡拉取一個Git補丁時,我需要知道你清楚 自己在做什麼,我需要能夠相信事情而 *無需* 手動檢查每個單獨的更改。 -(http://lwn.net/articles/224135/)。 +(http://lwn.net/Articles/224135/)。 爲了避免這種情況,請確保給定分支中的所有補丁都與相關主題緊密相關;「驅動程序 修復」分支不應更改核心內存管理代碼。而且,最重要的是,不要使用Git樹來繞過 diff --git a/Documentation/userspace-api/ioctl/ioctl-number.rst b/Documentation/userspace-api/ioctl/ioctl-number.rst index 4f7b23faebb98c74022604ff24084eb1e8257524..4ea5b837399ad1cb93f837a0f090bc87ed1f3089 100644 --- a/Documentation/userspace-api/ioctl/ioctl-number.rst +++ b/Documentation/userspace-api/ioctl/ioctl-number.rst @@ -180,6 +180,7 @@ Code Seq# Include File Comments 'P' 00-0F drivers/usb/class/usblp.c conflict! 'P' 01-09 drivers/misc/pci_endpoint_test.c conflict! 'P' 00-0F xen/privcmd.h conflict! +'P' 00-05 linux/tps6594_pfsm.h conflict! 'Q' all linux/soundcard.h 'R' 00-1F linux/random.h conflict! 'R' 01 linux/rfkill.h conflict! diff --git a/Documentation/userspace-api/media/frontend.h.rst.exceptions b/Documentation/userspace-api/media/frontend.h.rst.exceptions index 8b73fee11a79744abb4f5789168c15ccd72ce919..dcaf5740de7ec2093b0ce1f526bf69515cfe5f71 100644 --- a/Documentation/userspace-api/media/frontend.h.rst.exceptions +++ b/Documentation/userspace-api/media/frontend.h.rst.exceptions @@ -142,6 +142,10 @@ ignore symbol FEC_26_45 ignore symbol FEC_28_45 ignore symbol FEC_32_45 ignore symbol FEC_77_90 +ignore symbol FEC_11_45 +ignore symbol FEC_4_15 +ignore symbol FEC_14_45 +ignore symbol FEC_7_15 ignore symbol TRANSMISSION_MODE_AUTO ignore symbol TRANSMISSION_MODE_1K diff --git a/Documentation/userspace-api/media/v4l/biblio.rst b/Documentation/userspace-api/media/v4l/biblio.rst index 9cd18c153d195ba71b9458676736af4d4fbafacb..72aef1759b60bb2ff5b276c0fadaba50960f7b2f 100644 --- a/Documentation/userspace-api/media/v4l/biblio.rst +++ b/Documentation/userspace-api/media/v4l/biblio.rst @@ -427,3 +427,12 @@ VP9 :title: VP9 Bitstream & Decoding Process Specification :author: Adrian Grange (Google), Peter de Rivaz (Argon Design), Jonathan Hunt (Argon Design) + +.. _av1: + +AV1 +=== + +:title: AV1 Bitstream & Decoding Process Specification + +:author: Peter de Rivaz, Argon Design Ltd, Jack Haughton, Argon Design Ltd diff --git a/Documentation/userspace-api/media/v4l/ext-ctrls-camera.rst b/Documentation/userspace-api/media/v4l/ext-ctrls-camera.rst index daa4f40869f8f82e52be788c84e8b29a223efc55..cdc515c604683189a0dc13ecf7d4d900f288ad3e 100644 --- a/Documentation/userspace-api/media/v4l/ext-ctrls-camera.rst +++ b/Documentation/userspace-api/media/v4l/ext-ctrls-camera.rst @@ -506,6 +506,8 @@ enum v4l2_scene_mode - value down. A value of zero stops the motion if one is in progress and has no effect otherwise. +.. _v4l2-camera-sensor-orientation: + ``V4L2_CID_CAMERA_ORIENTATION (menu)`` This read-only control describes the camera orientation by reporting its mounting position on the device where the camera is installed. The control @@ -536,6 +538,7 @@ enum v4l2_scene_mode - - The camera is not directly attached to the device and is freely movable. +.. _v4l2-camera-sensor-rotation: ``V4L2_CID_CAMERA_SENSOR_ROTATION (integer)`` This read-only control describes the rotation correction in degrees in the diff --git a/Documentation/userspace-api/media/v4l/ext-ctrls-codec-stateless.rst b/Documentation/userspace-api/media/v4l/ext-ctrls-codec-stateless.rst index 3d8411acd5b8ca9b38b622e8522ce80fe80607ac..81e60f4002c8f12f05f9ecb4e681d62d22e3f91a 100644 --- a/Documentation/userspace-api/media/v4l/ext-ctrls-codec-stateless.rst +++ b/Documentation/userspace-api/media/v4l/ext-ctrls-codec-stateless.rst @@ -1890,11 +1890,11 @@ params syntax' of the :ref:`vp9` specification for more details. * - __u8 - ``tree_probs[7]`` - Specifies the probability values to be used when decoding a Segment-ID. - See '5.15. Segmentation map' section of :ref:`vp9` for more details. + See '5.15 Segmentation map' section of :ref:`vp9` for more details. * - __u8 - ``pred_probs[3]`` - Specifies the probability values to be used when decoding a - Predicted-Segment-ID. See '6.4.14. Get segment id syntax' + Predicted-Segment-ID. See '6.4.14 Get segment id syntax' section of :ref:`vp9` for more details. * - __u8 - ``flags`` @@ -2923,6 +2923,13 @@ This structure contains all loop filter related parameters. See sections - ``poc_lt_curr[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]`` - PocLtCurr as described in section 8.3.2 "Decoding process for reference picture set": provides the index of the long term references in DPB array. + * - __u8 + - ``num_delta_pocs_of_ref_rps_idx`` + - When the short_term_ref_pic_set_sps_flag in the slice header is equal to 0, + it is the same as the derived value NumDeltaPocs[RefRpsIdx]. It can be used to parse + the RPS data in slice headers instead of skipping it with @short_term_ref_pic_set_size. + When the value of short_term_ref_pic_set_sps_flag in the slice header is + equal to 1, num_delta_pocs_of_ref_rps_idx shall be set to 0. * - struct :c:type:`v4l2_hevc_dpb_entry` - ``dpb[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]`` - The decoded picture buffer, for meta-data about reference frames. @@ -2950,3 +2957,1208 @@ This structure contains all loop filter related parameters. See sections * - ``V4L2_HEVC_DECODE_PARAM_FLAG_NO_OUTPUT_OF_PRIOR`` - 0x00000004 - + +.. _v4l2-codec-stateless-av1: + +``V4L2_CID_STATELESS_AV1_SEQUENCE (struct)`` + Represents an AV1 Sequence OBU (Open Bitstream Unit). See section 5.5 + "Sequence header OBU syntax" in :ref:`av1` for more details. + +.. c:type:: v4l2_ctrl_av1_sequence + +.. cssclass:: longtable + +.. tabularcolumns:: |p{5.8cm}|p{4.8cm}|p{6.6cm}| + +.. flat-table:: struct v4l2_ctrl_av1_sequence + :header-rows: 0 + :stub-columns: 0 + :widths: 1 1 2 + + * - __u32 + - ``flags`` + - See :ref:`AV1 Sequence Flags `. + * - __u8 + - ``seq_profile`` + - Specifies the features that can be used in the coded video sequence. + * - __u8 + - ``order_hint_bits`` + - Specifies the number of bits used for the order_hint field at each frame. + * - __u8 + - ``bit_depth`` + - the bit depth to use for the sequence as described in section 5.5.2 + "Color config syntax" in :ref:`av1` for more details. + * - __u8 + - ``reserved`` + - Applications and drivers must set this to zero. + * - __u16 + - ``max_frame_width_minus_1`` + - specifies the maximum frame width minus 1 for the frames represented by + this sequence header. + +.. _av1_sequence_flags: + +``AV1 Sequence Flags`` + +.. cssclass:: longtable + +.. flat-table:: + :header-rows: 0 + :stub-columns: 0 + :widths: 1 1 2 + + * - ``V4L2_AV1_SEQUENCE_FLAG_STILL_PICTURE`` + - 0x00000001 + - If set, specifies that the coded video sequence contains only one coded + frame. If not set, specifies that the coded video sequence contains one + or more coded frames. + * - ``V4L2_AV1_SEQUENCE_FLAG_USE_128X128_SUPERBLOCK`` + - 0x00000002 + - If set, indicates that superblocks contain 128x128 luma samples. + When equal to 0, it indicates that superblocks contain 64x64 luma + samples. The number of contained chroma samples depends on + subsampling_x and subsampling_y. + * - ``V4L2_AV1_SEQUENCE_FLAG_ENABLE_FILTER_INTRA`` + - 0x00000004 + - If set, specifies that the use_filter_intra syntax element may be + present. If not set, specifies that the use_filter_intra syntax element + will not be present. + * - ``V4L2_AV1_SEQUENCE_FLAG_ENABLE_INTRA_EDGE_FILTER`` + - 0x00000008 + - Specifies whether the intra edge filtering process should be enabled. + * - ``V4L2_AV1_SEQUENCE_FLAG_ENABLE_INTERINTRA_COMPOUND`` + - 0x00000010 + - If set, specifies that the mode info for inter blocks may contain the + syntax element interintra. If not set, specifies that the syntax element + interintra will not be present. + * - ``V4L2_AV1_SEQUENCE_FLAG_ENABLE_MASKED_COMPOUND`` + - 0x00000020 + - If set, specifies that the mode info for inter blocks may contain the + syntax element compound_type. If not set, specifies that the syntax + element compound_type will not be present. + * - ``V4L2_AV1_SEQUENCE_FLAG_ENABLE_WARPED_MOTION`` + - 0x00000040 + - If set, indicates that the allow_warped_motion syntax element may be + present. If not set, indicates that the allow_warped_motion syntax + element will not be present. + * - ``V4L2_AV1_SEQUENCE_FLAG_ENABLE_DUAL_FILTER`` + - 0x00000080 + - If set, indicates that the inter prediction filter type may be specified + independently in the horizontal and vertical directions. If the flag is + equal to 0, only one filter type may be specified, which is then used in + both directions. + * - ``V4L2_AV1_SEQUENCE_FLAG_ENABLE_ORDER_HINT`` + - 0x00000100 + - If set, indicates that tools based on the values of order hints may be + used. If not set, indicates that tools based on order hints are + disabled. + * - ``V4L2_AV1_SEQUENCE_FLAG_ENABLE_JNT_COMP`` + - 0x00000200 + - If set, indicates that the distance weights process may be used for + inter prediction. + * - ``V4L2_AV1_SEQUENCE_FLAG_ENABLE_REF_FRAME_MVS`` + - 0x00000400 + - If set, indicates that the use_ref_frame_mvs syntax element may be + present. If not set, indicates that the use_ref_frame_mvs syntax element + will not be present. + * - ``V4L2_AV1_SEQUENCE_FLAG_ENABLE_SUPERRES`` + - 0x00000800 + - If set, specifies that the use_superres syntax element will be present + in the uncompressed header. If not set, specifies that the use_superres + syntax element will not be present (instead use_superres will be set to + 0 in the uncompressed header without being read). + * - ``V4L2_AV1_SEQUENCE_FLAG_ENABLE_CDEF`` + - 0x00001000 + - If set, specifies that cdef filtering may be enabled. If not set, + specifies that cdef filtering is disabled. + * - ``V4L2_AV1_SEQUENCE_FLAG_ENABLE_RESTORATION`` + - 0x00002000 + - If set, specifies that loop restoration filtering may be enabled. If not + set, specifies that loop restoration filtering is disabled. + * - ``V4L2_AV1_SEQUENCE_FLAG_MONO_CHROME`` + - 0x00004000 + - If set, indicates that the video does not contain U and V color planes. + If not set, indicates that the video contains Y, U, and V color planes. + * - ``V4L2_AV1_SEQUENCE_FLAG_COLOR_RANGE`` + - 0x00008000 + - If set, signals full swing representation, i.e. "Full Range + Quantization". If not set, signals studio swing representation, i.e. + "Limited Range Quantization". + * - ``V4L2_AV1_SEQUENCE_FLAG_SUBSAMPLING_X`` + - 0x00010000 + - Specify the chroma subsampling format. + * - ``V4L2_AV1_SEQUENCE_FLAG_SUBSAMPLING_Y`` + - 0x00020000 + - Specify the chroma subsampling format. + * - ``V4L2_AV1_SEQUENCE_FLAG_FILM_GRAIN_PARAMS_PRESENT`` + - 0x00040000 + - Specifies whether film grain parameters are present in the coded video + sequence. + * - ``V4L2_AV1_SEQUENCE_FLAG_SEPARATE_UV_DELTA_Q`` + - 0x00080000 + - If set, indicates that the U and V planes may have separate delta + quantizer values. If not set, indicates that the U and V planes will share + the same delta quantizer value. + +``V4L2_CID_STATELESS_AV1_TILE_GROUP_ENTRY (struct)`` + Represents a single AV1 tile inside an AV1 Tile Group. Note that MiRowStart, + MiRowEnd, MiColStart and MiColEnd can be retrieved from struct + v4l2_av1_tile_info in struct v4l2_ctrl_av1_frame using tile_row and + tile_col. See section 6.10.1 "General tile group OBU semantics" in + :ref:`av1` for more details. + +.. c:type:: v4l2_ctrl_av1_tile_group_entry + +.. cssclass:: longtable + +.. tabularcolumns:: |p{5.8cm}|p{4.8cm}|p{6.6cm}| + +.. flat-table:: struct v4l2_ctrl_av1_tile_group_entry + :header-rows: 0 + :stub-columns: 0 + :widths: 1 1 2 + + * - __u32 + - ``tile_offset`` + - Offset from the OBU data, i.e. where the coded tile data actually starts. + * - __u32 + - ``tile_size`` + - Specifies the size in bytes of the coded tile. Equivalent to "TileSize" + in :ref:`av1`. + * - __u32 + - ``tile_row`` + - Specifies the row of the current tile. Equivalent to "TileRow" in + :ref:`av1`. + * - __u32 + - ``tile_col`` + - Specifies the column of the current tile. Equivalent to "TileColumn" in + :ref:`av1`. + +.. c:type:: v4l2_av1_warp_model + + AV1 Warp Model as described in section 3 "Symbols and abbreviated terms" of + :ref:`av1`. + +.. raw:: latex + + \scriptsize + +.. tabularcolumns:: |p{7.4cm}|p{0.3cm}|p{9.6cm}| + +.. flat-table:: + :header-rows: 0 + :stub-columns: 0 + :widths: 1 1 2 + + * - ``V4L2_AV1_WARP_MODEL_IDENTITY`` + - 0 + - Warp model is just an identity transform. + * - ``V4L2_AV1_WARP_MODEL_TRANSLATION`` + - 1 + - Warp model is a pure translation. + * - ``V4L2_AV1_WARP_MODEL_ROTZOOM`` + - 2 + - Warp model is a rotation + symmetric zoom + translation. + * - ``V4L2_AV1_WARP_MODEL_AFFINE`` + - 3 + - Warp model is a general affine transform. + +.. c:type:: v4l2_av1_reference_frame + +AV1 Reference Frames as described in section 6.10.24 "Ref frames semantics" +of :ref:`av1`. + +.. raw:: latex + + \scriptsize + +.. tabularcolumns:: |p{7.4cm}|p{0.3cm}|p{9.6cm}| + +.. flat-table:: + :header-rows: 0 + :stub-columns: 0 + :widths: 1 1 2 + + * - ``V4L2_AV1_REF_INTRA_FRAME`` + - 0 + - Intra Frame Reference. + * - ``V4L2_AV1_REF_LAST_FRAME`` + - 1 + - Last Frame Reference. + * - ``V4L2_AV1_REF_LAST2_FRAME`` + - 2 + - Last2 Frame Reference. + * - ``V4L2_AV1_REF_LAST3_FRAME`` + - 3 + - Last3 Frame Reference. + * - ``V4L2_AV1_REF_GOLDEN_FRAME`` + - 4 + - Golden Frame Reference. + * - ``V4L2_AV1_REF_BWDREF_FRAME`` + - 5 + - BWD Frame Reference. + * - ``V4L2_AV1_REF_ALTREF2_FRAME`` + - 6 + - ALTREF2 Frame Reference. + * - ``V4L2_AV1_REF_ALTREF_FRAME`` + - 7 + - ALTREF Frame Reference. + +.. c:type:: v4l2_av1_global_motion + +AV1 Global Motion parameters as described in section 6.8.17 +"Global motion params semantics" of :ref:`av1`. + +.. cssclass:: longtable + +.. tabularcolumns:: |p{1.5cm}|p{5.8cm}|p{10.0cm}| + +.. flat-table:: struct v4l2_av1_global_motion + :header-rows: 0 + :stub-columns: 0 + :widths: 1 1 2 + + * - __u8 + - ``flags[V4L2_AV1_TOTAL_REFS_PER_FRAME]`` + - A bitfield containing the flags per reference frame. See + :ref:`AV1 Global Motion Flags ` for more + details. + * - enum :c:type:`v4l2_av1_warp_model` + - ``type[V4L2_AV1_TOTAL_REFS_PER_FRAME]`` + - The type of global motion transform used. + * - __s32 + - ``params[V4L2_AV1_TOTAL_REFS_PER_FRAME][6]`` + - This field has the same meaning as "gm_params" in :ref:`av1`. + * - __u8 + - ``invalid`` + - Bitfield indicating whether the global motion params are invalid for a + given reference frame. See section 7.11.3.6 Setup shear process and the + variable "warpValid". Use V4L2_AV1_GLOBAL_MOTION_IS_INVALID(ref) to + create a suitable mask. + * - __u8 + - ``reserved[3]`` + - Applications and drivers must set this to zero. + +.. _av1_global_motion_flags: + +``AV1 Global Motion Flags`` + +.. cssclass:: longtable + +.. flat-table:: + :header-rows: 0 + :stub-columns: 0 + :widths: 1 1 2 + + * - ``V4L2_AV1_GLOBAL_MOTION_FLAG_IS_GLOBAL`` + - 0x00000001 + - Specifies whether global motion parameters are present for a particular + reference frame. + * - ``V4L2_AV1_GLOBAL_MOTION_FLAG_IS_ROT_ZOOM`` + - 0x00000002 + - Specifies whether a particular reference frame uses rotation and zoom + global motion. + * - ``V4L2_AV1_GLOBAL_MOTION_FLAG_IS_TRANSLATION`` + - 0x00000004 + - Specifies whether a particular reference frame uses translation global + motion + +.. c:type:: v4l2_av1_frame_restoration_type + +AV1 Frame Restoration Type. + +.. raw:: latex + + \scriptsize + +.. tabularcolumns:: |p{7.4cm}|p{0.3cm}|p{9.6cm}| + +.. flat-table:: + :header-rows: 0 + :stub-columns: 0 + :widths: 1 1 2 + + * - ``V4L2_AV1_FRAME_RESTORE_NONE`` + - 0 + - No filtering is applied. + * - ``V4L2_AV1_FRAME_RESTORE_WIENER`` + - 1 + - Wiener filter process is invoked. + * - ``V4L2_AV1_FRAME_RESTORE_SGRPROJ`` + - 2 + - Self guided filter process is invoked. + * - ``V4L2_AV1_FRAME_RESTORE_SWITCHABLE`` + - 3 + - Restoration filter is swichtable. + +.. c:type:: v4l2_av1_loop_restoration + +AV1 Loop Restauration as described in section 6.10.15 "Loop restoration params +semantics" of :ref:`av1`. + +.. cssclass:: longtable + +.. tabularcolumns:: |p{1.5cm}|p{5.8cm}|p{10.0cm}| + +.. flat-table:: struct v4l2_av1_loop_restoration + :header-rows: 0 + :stub-columns: 0 + :widths: 1 1 2 + + * - __u8 + - ``flags`` + - See :ref:`AV1 Loop Restoration Flags `. + * - __u8 + - ``lr_unit_shift`` + - Specifies if the luma restoration size should be halved. + * - __u8 + - ``lr_uv_shift`` + - Specifies if the chroma size should be half the luma size. + * - __u8 + - ``reserved`` + - Applications and drivers must set this to zero. + * - :c:type:`v4l2_av1_frame_restoration_type` + - ``frame_restoration_type[V4L2_AV1_NUM_PLANES_MAX]`` + - Specifies the type of restoration used for each plane. + * - __u8 + - ``loop_restoration_size[V4L2_AV1_MAX_NUM_PLANES]`` + - Specifies the size of loop restoration units in units of samples in the + current plane. + +.. _av1_loop_restoration_flags: + +``AV1 Loop Restoration Flags`` + +.. cssclass:: longtable + +.. flat-table:: + :header-rows: 0 + :stub-columns: 0 + :widths: 1 1 2 + + * - ``V4L2_AV1_LOOP_RESTORATION_FLAG_USES_LR`` + - 0x00000001 + - Retains the same meaning as UsesLr in :ref:`av1`. + * - ``V4L2_AV1_LOOP_RESTORATION_FLAG_USES_CHROMA_LR`` + - 0x00000002 + - Retains the same meaning as UsesChromaLr in :ref:`av1`. + +.. c:type:: v4l2_av1_cdef + +AV1 CDEF params semantics as described in section 6.10.14 "CDEF params +semantics" of :ref:`av1`. + +.. cssclass:: longtable + +.. tabularcolumns:: |p{1.5cm}|p{5.8cm}|p{10.0cm}| + +.. flat-table:: struct v4l2_av1_cdef + :header-rows: 0 + :stub-columns: 0 + :widths: 1 1 2 + + * - __u8 + - ``damping_minus_3`` + - Controls the amount of damping in the deringing filter. + * - __u8 + - ``bits`` + - Specifies the number of bits needed to specify which CDEF filter to + apply. + * - __u8 + - ``y_pri_strength[V4L2_AV1_CDEF_MAX]`` + - Specifies the strength of the primary filter. + * - __u8 + - ``y_sec_strength[V4L2_AV1_CDEF_MAX]`` + - Specifies the strength of the secondary filter. + * - __u8 + - ``uv_pri_strength[V4L2_AV1_CDEF_MAX]`` + - Specifies the strength of the primary filter. + * - __u8 + - ``uv_secondary_strength[V4L2_AV1_CDEF_MAX]`` + - Specifies the strength of the secondary filter. + +.. c:type:: v4l2_av1_segment_feature + +AV1 segment features as described in section 3 "Symbols and abbreviated terms" +of :ref:`av1`. + +.. raw:: latex + + \scriptsize + +.. tabularcolumns:: |p{7.4cm}|p{0.3cm}|p{9.6cm}| + +.. flat-table:: + :header-rows: 0 + :stub-columns: 0 + :widths: 1 1 2 + + * - ``V4L2_AV1_SEG_LVL_ALT_Q`` + - 0 + - Index for quantizer segment feature. + * - ``V4L2_AV1_SEG_LVL_ALT_LF_Y_V`` + - 1 + - Index for vertical luma loop filter segment feature. + * - ``V4L2_AV1_SEG_LVL_REF_FRAME`` + - 5 + - Index for reference frame segment feature. + * - ``V4L2_AV1_SEG_LVL_REF_SKIP`` + - 6 + - Index for skip segment feature. + * - ``V4L2_AV1_SEG_LVL_REF_GLOBALMV`` + - 7 + - Index for global mv feature. + * - ``V4L2_AV1_SEG_LVL_MAX`` + - 8 + - Number of segment features. + +.. c:type:: v4l2_av1_segmentation + +AV1 Segmentation params as defined in section 6.8.13 "Segmentation params +semantics" of :ref:`av1`. + +.. cssclass:: longtable + +.. tabularcolumns:: |p{1.5cm}|p{5.8cm}|p{10.0cm}| + +.. flat-table:: struct v4l2_av1_segmentation + :header-rows: 0 + :stub-columns: 0 + :widths: 1 1 2 + + * - __u8 + - ``flags`` + - See :ref:`AV1 Segmentation Flags ` + * - __u8 + - ``last_active_seg_id`` + - Indicates the highest numbered segment id that has some + enabled feature. This is used when decoding the segment id to only decode + choices corresponding to used segments. + * - __u8 + - ``feature_enabled[V4L2_AV1_MAX_SEGMENTS]`` + - Bitmask defining which features are enabled in each segment. Use + V4L2_AV1_SEGMENT_FEATURE_ENABLED to build a suitable mask. + * - __u16 + - `feature_data[V4L2_AV1_MAX_SEGMENTS][V4L2_AV1_SEG_LVL_MAX]`` + - Data attached to each feature. Data entry is only valid if the feature + is enabled. + +.. _av1_segmentation_flags: + +``AV1 Segmentation Flags`` + +.. cssclass:: longtable + +.. flat-table:: + :header-rows: 0 + :stub-columns: 0 + :widths: 1 1 2 + + * - ``V4L2_AV1_SEGMENTATION_FLAG_ENABLED`` + - 0x00000001 + - If set, indicates that this frame makes use of the segmentation tool. If + not set, indicates that the frame does not use segmentation. + * - ``V4L2_AV1_SEGMENTATION_FLAG_UPDATE_MAP`` + - 0x00000002 + - If set, indicates that the segmentation map are updated during the + decoding of this frame. If not set, indicates that the segmentation map + from the previous frame is used. + * - ``V4L2_AV1_SEGMENTATION_FLAG_TEMPORAL_UPDATE`` + - 0x00000004 + - If set, indicates that the updates to the segmentation map are coded + relative to the existing segmentation map. If not set, indicates that + the new segmentation map is coded without reference to the existing + segmentation map. + * - ``V4L2_AV1_SEGMENTATION_FLAG_UPDATE_DATA`` + - 0x00000008 + - If set, indicates that the updates to the segmentation map are coded + relative to the existing segmentation map. If not set, indicates that + the new segmentation map is coded without reference to the existing + segmentation map. + * - ``V4L2_AV1_SEGMENTATION_FLAG_SEG_ID_PRE_SKIP`` + - 0x00000010 + - If set, indicates that the segment id will be read before the skip + syntax element. If not set, indicates that the skip syntax element will + be read first. + +.. c:type:: v4l2_av1_loop_filter + +AV1 Loop filter params as defined in section 6.8.10 "Loop filter semantics" of +:ref:`av1`. + +.. cssclass:: longtable + +.. tabularcolumns:: |p{1.5cm}|p{5.8cm}|p{10.0cm}| + +.. flat-table:: struct v4l2_av1_global_motion + :header-rows: 0 + :stub-columns: 0 + :widths: 1 1 2 + + * - __u8 + - ``flags`` + - See + :ref:`AV1 Loop Filter flags ` for more details. + * - __u8 + - ``level[4]`` + - An array containing loop filter strength values. Different loop + filter strength values from the array are used depending on the image + plane being filtered, and the edge direction (vertical or horizontal) + being filtered. + * - __u8 + - ``sharpness`` + - indicates the sharpness level. The loop_filter_level and + loop_filter_sharpness together determine when a block edge is filtered, + and by how much the filtering can change the sample values. The loop + filter process is described in section 7.14 of :ref:`av1`. + * - __u8 + - ``ref_deltas[V4L2_AV1_TOTAL_REFS_PER_FRAME]`` + - contains the adjustment needed for the filter level based on the + chosen reference frame. If this syntax element is not present, it + maintains its previous value. + * - __u8 + - ``mode_deltas[2]`` + - contains the adjustment needed for the filter level based on + the chosen mode. If this syntax element is not present, it maintains its + previous value. + * - __u8 + - ``delta_lf_res`` + - specifies the left shift which should be applied to decoded loop filter + delta values. + +.. _av1_loop_filter_flags: + +``AV1 Loop Filter Flags`` + +.. cssclass:: longtable + +.. flat-table:: + :header-rows: 0 + :stub-columns: 0 + :widths: 1 1 2 + + * - ``V4L2_AV1_LOOP_FILTER_FLAG_DELTA_ENABLED`` + - 0x00000001 + - If set, means that the filter level depends on the mode and reference + frame used to predict a block. If not set, means that the filter level + does not depend on the mode and reference frame. + * - ``V4L2_AV1_LOOP_FILTER_FLAG_DELTA_UPDATE`` + - 0x00000002 + - If set, means that additional syntax elements are present that specify + which mode and reference frame deltas are to be updated. If not set, + means that these syntax elements are not present. + * - ``V4L2_AV1_LOOP_FILTER_FLAG_DELTA_LF_PRESENT`` + - 0x00000004 + - Specifies whether loop filter delta values are present + * - ``V4L2_AV1_LOOP_FILTER_FLAG_DELTA_LF_MULTI`` + - 0x00000008 + - A value equal to 1 specifies that separate loop filter + deltas are sent for horizontal luma edges, vertical luma edges, + the U edges, and the V edges. A value of delta_lf_multi equal to 0 + specifies that the same loop filter delta is used for all edges. + +.. c:type:: v4l2_av1_quantization + +AV1 Quantization params as defined in section 6.8.11 "Quantization params +semantics" of :ref:`av1`. + +.. cssclass:: longtable + +.. tabularcolumns:: |p{1.5cm}|p{5.8cm}|p{10.0cm}| + +.. flat-table:: struct v4l2_av1_quantization + :header-rows: 0 + :stub-columns: 0 + :widths: 1 1 2 + + * - __u8 + - ``flags`` + - See + :ref:`AV1 Loop Filter flags ` for more details. + * - __u8 + - ``base_q_idx`` + - Indicates the base frame qindex. This is used for Y AC coefficients and + as the base value for the other quantizers. + * - __u8 + - ``delta_q_y_dc`` + - Indicates the Y DC quantizer relative to base_q_idx. + * - __u8 + - ``delta_q_u_dc`` + - Indicates the U DC quantizer relative to base_q_idx. + * - __u8 + - ``delta_q_u_ac`` + - Indicates the U AC quantizer relative to base_q_idx. + * - __u8 + - ``delta_q_v_dc`` + - Indicates the V DC quantizer relative to base_q_idx. + * - __u8 + - ``delta_q_v_ac`` + - Indicates the V AC quantizer relative to base_q_idx. + * - __u8 + - ``qm_y`` + - Specifies the level in the quantizer matrix that should be used for + luma plane decoding. + * - __u8 + - ``qm_u`` + - Specifies the level in the quantizer matrix that should be used for + chroma U plane decoding. + * - __u8 + - ``qm_v`` + - Specifies the level in the quantizer matrix that should be used for + chroma V plane decoding. + * - __u8 + - ``delta_q_res`` + - Specifies the left shift which should be applied to decoded quantizer + index delta values. + +.. _av1_quantization_flags: + +``AV1 Quantization Flags`` + +.. cssclass:: longtable + +.. flat-table:: + :header-rows: 0 + :stub-columns: 0 + :widths: 1 1 2 + + * - ``V4L2_AV1_QUANTIZATION_FLAG_DIFF_UV_DELTA`` + - 0x00000001 + - If set, indicates that the U and V delta quantizer values are coded + separately. If not set, indicates that the U and V delta quantizer + values share a common value. + * - ``V4L2_AV1_QUANTIZATION_FLAG_USING_QMATRIX`` + - 0x00000002 + - If set, specifies that the quantizer matrix will be used to compute + quantizers. + * - ``V4L2_AV1_QUANTIZATION_FLAG_DELTA_Q_PRESENT`` + - 0x00000004 + - Specifies whether quantizer index delta values are present. + +.. c:type:: v4l2_av1_tile_info + +AV1 Tile info as defined in section 6.8.14 "Tile info semantics" of ref:`av1`. + +.. cssclass:: longtable + +.. tabularcolumns:: |p{1.5cm}|p{5.8cm}|p{10.0cm}| + +.. flat-table:: struct v4l2_av1_tile_info + :header-rows: 0 + :stub-columns: 0 + :widths: 1 1 2 + + * - __u8 + - ``flags`` + - See + :ref:`AV1 Tile Info flags ` for more details. + * - __u8 + - ``context_update_tile_id`` + - Specifies which tile to use for the CDF update. + * - __u8 + - ``tile_cols`` + - Specifies the number of tiles across the frame. + * - __u8 + - ``tile_rows`` + - Specifies the number of tiles down the frame. + * - __u32 + - ``mi_col_starts[V4L2_AV1_MAX_TILE_COLS + 1]`` + - An array specifying the start column (in units of 4x4 luma + samples) for each tile across the image. + * - __u32 + - ``mi_row_starts[V4L2_AV1_MAX_TILE_ROWS + 1]`` + - An array specifying the start row (in units of 4x4 luma + samples) for each tile across the image. + * - __u32 + - ``width_in_sbs_minus_1[V4L2_AV1_MAX_TILE_COLS]`` + - Specifies the width of a tile minus 1 in units of superblocks. + * - __u32 + - ``height_in_sbs_minus_1[V4L2_AV1_MAX_TILE_ROWS]`` + - Specifies the height of a tile minus 1 in units of superblocks. + * - __u8 + - ``tile_size_bytes`` + - Specifies the number of bytes needed to code each tile size. + * - __u8 + - ``reserved[3]`` + - Applications and drivers must set this to zero. + +.. _av1_tile_info_flags: + +``AV1 Tile Info Flags`` + +.. cssclass:: longtable + +.. flat-table:: + :header-rows: 0 + :stub-columns: 0 + :widths: 1 1 2 + + * - ``V4L2_AV1_TILE_INFO_FLAG_UNIFORM_TILE_SPACING`` + - 0x00000001 + - If set, means that the tiles are uniformly spaced across the frame. (In + other words, all tiles are the same size except for the ones at the + right and bottom edge which can be smaller). If not set means that the + tile sizes are coded. + +.. c:type:: v4l2_av1_frame_type + +AV1 Frame Type + +.. raw:: latex + + \scriptsize + +.. tabularcolumns:: |p{7.4cm}|p{0.3cm}|p{9.6cm}| + +.. flat-table:: + :header-rows: 0 + :stub-columns: 0 + :widths: 1 1 2 + + * - ``V4L2_AV1_KEY_FRAME`` + - 0 + - Key frame. + * - ``V4L2_AV1_INTER_FRAME`` + - 1 + - Inter frame. + * - ``V4L2_AV1_INTRA_ONLY_FRAME`` + - 2 + - Intra-only frame. + * - ``V4L2_AV1_SWITCH_FRAME`` + - 3 + - Switch frame. + +.. c:type:: v4l2_av1_interpolation_filter + +AV1 Interpolation Filter + +.. raw:: latex + + \scriptsize + +.. tabularcolumns:: |p{7.4cm}|p{0.3cm}|p{9.6cm}| + +.. flat-table:: + :header-rows: 0 + :stub-columns: 0 + :widths: 1 1 2 + + * - ``V4L2_AV1_INTERPOLATION_FILTER_EIGHTTAP`` + - 0 + - Eight tap filter. + * - ``V4L2_AV1_INTERPOLATION_FILTER_EIGHTTAP_SMOOTH`` + - 1 + - Eight tap smooth filter. + * - ``V4L2_AV1_INTERPOLATION_FILTER_EIGHTTAP_SHARP`` + - 2 + - Eight tap sharp filter. + * - ``V4L2_AV1_INTERPOLATION_FILTER_BILINEAR`` + - 3 + - Bilinear filter. + * - ``V4L2_AV1_INTERPOLATION_FILTER_SWITCHABLE`` + - 4 + - Filter selection is signaled at the block level. + +.. c:type:: v4l2_av1_tx_mode + +AV1 Tx mode as described in section 6.8.21 "TX mode semantics" of :ref:`av1`. + +.. raw:: latex + + \scriptsize + +.. tabularcolumns:: |p{7.4cm}|p{0.3cm}|p{9.6cm}| + +.. flat-table:: + :header-rows: 0 + :stub-columns: 0 + :widths: 1 1 2 + + * - ``V4L2_AV1_TX_MODE_ONLY_4X4`` + - 0 + - The inverse transform will use only 4x4 transforms. + * - ``V4L2_AV1_TX_MODE_LARGEST`` + - 1 + - The inverse transform will use the largest transform size that fits + inside the block. + * - ``V4L2_AV1_TX_MODE_SELECT`` + - 2 + - The choice of transform size is specified explicitly for each block. + +``V4L2_CID_STATELESS_AV1_FRAME (struct)`` + Represents a Frame Header OBU. See 6.8 "Frame Header OBU semantics" of + :ref:`av1` for more details. + +.. c:type:: v4l2_ctrl_av1_frame + +.. cssclass:: longtable + +.. tabularcolumns:: |p{5.8cm}|p{4.8cm}|p{6.6cm}| + +.. flat-table:: struct v4l2_ctrl_av1_frame + :header-rows: 0 + :stub-columns: 0 + :widths: 1 1 2 + + * - struct :c:type:`v4l2_av1_tile_info` + - ``tile_info`` + - Tile info + * - struct :c:type:`v4l2_av1_quantization` + - ``quantization`` + - Quantization parameters. + * - struct :c:type:`v4l2_av1_segmentation` + - ``segmentation`` + - Segmentation parameters. + * - __u8 + - ``superres_denom`` + - The denominator for the upscaling ratio. + * - struct :c:type:`v4l2_av1_loop_filter` + - ``loop_filter`` + - Loop filter params + * - struct :c:type:`v4l2_av1_cdef` + - ``cdef`` + - CDEF params + * - __u8 + - ``skip_mode_frame[2]`` + - Specifies the frames to use for compound prediction when skip_mode is + equal to 1. + * - __u8 + - ``primary_ref_frame`` + - Specifies which reference frame contains the CDF values and other state + that should be loaded at the start of the frame. + * - struct :c:type:`v4l2_av1_loop_restoration` + - ``loop_restoration`` + - Loop restoration parameters. + * - struct :c:type:`v4l2_av1_loop_global_motion` + - ``global_motion`` + - Global motion parameters. + * - __u32 + - ``flags`` + - See + :ref:`AV1 Frame flags ` for more details. + * - enum :c:type:`v4l2_av1_frame_type` + - ``frame_type`` + - Specifies the AV1 frame type + * - __u32 + - ``order_hint`` + - Specifies OrderHintBits least significant bits of the expected output + order for this frame. + * - __u32 + - ``upscaled_width`` + - The upscaled width. + * - enum :c:type:`v4l2_av1_interpolation_filter` + - ``interpolation_filter`` + - Specifies the filter selection used for performing inter prediction. + * - enum :c:type:`v4l2_av1_tx_mode` + - ``tx_mode`` + - Specifies how the transform size is determined. + * - __u32 + - ``frame_width_minus_1`` + - Add 1 to get the frame's width. + * - __u32 + - ``frame_height_minus_1`` + - Add 1 to get the frame's height. + * - __u16 + - ``render_width_minus_1`` + - Add 1 to get the render width of the frame in luma samples. + * - __u16 + - ``render_height_minus_1`` + - Add 1 to get the render height of the frame in luma samples. + * - __u32 + - ``current_frame_id`` + - Specifies the frame id number for the current frame. Frame + id numbers are additional information that do not affect the decoding + process, but provide decoders with a way of detecting missing reference + frames so that appropriate action can be taken. + * - __u8 + - ``buffer_removal_time[V4L2_AV1_MAX_OPERATING_POINTS]`` + - Specifies the frame removal time in units of DecCT clock ticks counted + from the removal time of the last random access point for operating point + opNum. + * - __u8 + - ``reserved[4]`` + - Applications and drivers must set this to zero. + * - __u32 + - ``order_hints[V4L2_AV1_TOTAL_REFS_PER_FRAME]`` + - Specifies the expected output order hint for each reference frame. + This field corresponds to the OrderHints variable from the specification + (section 5.9.2 "Uncompressed header syntax"). As such, this is only + used for non-intra frames and ignored otherwise. order_hints[0] is + always ignored. + * - __u64 + - ``reference_frame_ts[V4L2_AV1_TOTAL_REFS_PER_FRAME]`` + - The V4L2 timestamp for each of the reference frames enumerated in + enum :c:type:`v4l2_av1_reference_frame` starting at + ``V4L2_AV1_REF_LAST_FRAME``. This represents the state of reference + slot as described in the spec and updated by userland through the + "Reference frame update process" in section 7.20 The timestamp refers + to the ``timestamp`` field in struct :c:type:`v4l2_buffer`. Use the + :c:func:`v4l2_timeval_to_ns()` function to convert the struct + :c:type:`timeval` in struct :c:type:`v4l2_buffer` to a __u64. + * - __s8 + - ``ref_frame_idx[V4L2_AV1_REFS_PER_FRAME]`` + - An index into ``reference_frame_ts`` representing the ordered list of + references used by inter-frame. Matches the bitstream syntax + element of the same name. + * - __u8 + - ``refresh_frame_flags`` + - Contains a bitmask that specifies which reference frame slots will be + updated with the current frame after it is decoded. + +.. _av1_frame_flags: + +``AV1 Frame Flags`` + +.. cssclass:: longtable + +.. flat-table:: + :header-rows: 0 + :stub-columns: 0 + :widths: 1 1 2 + + * - ``V4L2_AV1_FRAME_FLAG_SHOW_FRAME`` + - 0x00000001 + - If set, specifies that this frame should be immediately output once + decoded. If not set, specifies that this frame should not be immediately + output; it may be output later if a later uncompressed header uses + show_existing_frame equal to 1. + * - ``V4L2_AV1_FRAME_FLAG_SHOWABLE_FRAME`` + - 0x00000002 + - If set, specifies that the frame may be output using the + show_existing_frame mechanism. If not set, specifies that this frame + will not be output using the show_existing_frame mechanism. + * - ``V4L2_AV1_FRAME_FLAG_ERROR_RESILIENT_MODE`` + - 0x00000004 + - Specifies whether error resilient mode is enabled. + * - ``V4L2_AV1_FRAME_FLAG_DISABLE_CDF_UPDATE`` + - 0x00000008 + - Specifies whether the CDF update in the symbol decoding process should + be disabled. + * - ``V4L2_AV1_FRAME_FLAG_ALLOW_SCREEN_CONTENT_TOOLS`` + - 0x00000010 + - If set, indicates that intra blocks may use palette encoding. If not + set, indicates that palette encoding is never used. + * - ``V4L2_AV1_FRAME_FLAG_FORCE_INTEGER_MV`` + - 0x00000020 + - If set, specifies that motion vectors will always be integers. If not + set, specifies that motion vectors can contain fractional bits. + * - ``V4L2_AV1_FRAME_FLAG_ALLOW_INTRABC`` + - 0x00000040 + - If set, indicates that intra block copy may be used in this frame. If + not set, indicates that intra block copy is not allowed in this frame. + * - ``V4L2_AV1_FRAME_FLAG_USE_SUPERRES`` + - 0x00000080 + - If set, indicates that upscaling is needed. + * - ``V4L2_AV1_FRAME_FLAG_ALLOW_HIGH_PRECISION_MV`` + - 0x00000100 + - If set, specifies that motion vectors are specified to eighth pel + precision. If not set, specifies that motion vectors are specified to + quarter pel precision; + * - ``V4L2_AV1_FRAME_FLAG_IS_MOTION_MODE_SWITCHABLE`` + - 0x00000200 + - If not set, specifies that only the SIMPLE motion mode will be used. + * - ``V4L2_AV1_FRAME_FLAG_USE_REF_FRAME_MVS`` + - 0x00000400 + - If set specifies that motion vector information from a previous frame + can be used when decoding the current frame. If not set, specifies that + this information will not be used. + * - ``V4L2_AV1_FRAME_FLAG_DISABLE_FRAME_END_UPDATE_CDF`` + - 0x00000800 + - If set indicates that the end of frame CDF update is disabled. If not + set, indicates that the end of frame CDF update is enabled + * - ``V4L2_AV1_FRAME_FLAG_ALLOW_WARPED_MOTION`` + - 0x00001000 + - If set, indicates that the syntax element motion_mode may be present, if + not set, indicates that the syntax element motion_mode will not be + present. + * - ``V4L2_AV1_FRAME_FLAG_REFERENCE_SELECT`` + - 0x00002000 + - If set, specifies that the mode info for inter blocks contains the + syntax element comp_mode that indicates whether to use single or + compound reference prediction. If not set, specifies that all inter + blocks will use single prediction. + * - ``V4L2_AV1_FRAME_FLAG_REDUCED_TX_SET`` + - 0x00004000 + - If set, specifies that the frame is restricted to a reduced subset of + the full set of transform types. + * - ``V4L2_AV1_FRAME_FLAG_SKIP_MODE_ALLOWED`` + - 0x00008000 + - This flag retains the same meaning as SkipModeAllowed in :ref:`av1`. + * - ``V4L2_AV1_FRAME_FLAG_SKIP_MODE_PRESENT`` + - 0x00010000 + - If set, specifies that the syntax element skip_mode will be present, if + not set, specifies that skip_mode will not be used for this frame. + * - ``V4L2_AV1_FRAME_FLAG_FRAME_SIZE_OVERRIDE`` + - 0x00020000 + - If set, specifies that the frame size will either be specified as the + size of one of the reference frames, or computed from the + frame_width_minus_1 and frame_height_minus_1 syntax elements. If not + set, specifies that the frame size is equal to the size in the sequence + header. + * - ``V4L2_AV1_FRAME_FLAG_BUFFER_REMOVAL_TIME_PRESENT`` + - 0x00040000 + - If set, specifies that buffer_removal_time is present. If not set, + specifies that buffer_removal_time is not present. + * - ``V4L2_AV1_FRAME_FLAG_FRAME_REFS_SHORT_SIGNALING`` + - 0x00080000 + - If set, indicates that only two reference frames are explicitly + signaled. If not set, indicates that all reference frames are explicitly + signaled. + +``V4L2_CID_STATELESS_AV1_FILM_GRAIN (struct)`` + Represents the optional film grain parameters. See section + 6.8.20 "Film grain params semantics" of :ref:`av1` for more details. + +.. c:type:: v4l2_ctrl_av1_film_grain + +.. cssclass:: longtable + +.. tabularcolumns:: |p{1.5cm}|p{5.8cm}|p{10.0cm}| + +.. flat-table:: struct v4l2_ctrl_av1_film_grain + :header-rows: 0 + :stub-columns: 0 + :widths: 1 1 2 + + * - __u8 + - ``flags`` + - See :ref:`AV1 Film Grain Flags `. + * - __u8 + - ``cr_mult`` + - Represents a multiplier for the cr component used in derivation of the + input index to the cr component scaling function. + * - __u16 + - ``grain_seed`` + - Specifies the starting value for the pseudo-random numbers used during + film grain synthesis. + * - __u8 + - ``film_grain_params_ref_idx`` + - Indicates which reference frame contains the film grain parameters to be + used for this frame. + * - __u8 + - ``num_y_points`` + - Specifies the number of points for the piece-wise linear scaling + function of the luma component. + * - __u8 + - ``point_y_value[V4L2_AV1_MAX_NUM_Y_POINTS]`` + - Represents the x (luma value) coordinate for the i-th point + of the piecewise linear scaling function for luma component. The values + are signaled on the scale of 0..255. In case of 10 bit video, these + values correspond to luma values divided by 4. In case of 12 bit video, + these values correspond to luma values divided by 16. + * - __u8 + - ``point_y_scaling[V4L2_AV1_MAX_NUM_Y_POINTS]`` + - Represents the scaling (output) value for the i-th point + of the piecewise linear scaling function for luma component. + * - __u8 + - ``num_cb_points`` + - Specifies the number of points for the piece-wise linear scaling + function of the cb component. + * - __u8 + - ``point_cb_value[V4L2_AV1_MAX_NUM_CB_POINTS]`` + - Represents the x coordinate for the i-th point of the + piece-wise linear scaling function for cb component. The values are + signaled on the scale of 0..255. + * - __u8 + - ``point_cb_scaling[V4L2_AV1_MAX_NUM_CB_POINTS]`` + - Represents the scaling (output) value for the i-th point of the + piecewise linear scaling function for cb component. + * - __u8 + - ``num_cr_points`` + - Represents the number of points for the piece-wise + linear scaling function of the cr component. + * - __u8 + - ``point_cr_value[V4L2_AV1_MAX_NUM_CR_POINTS]`` + - Represents the x coordinate for the i-th point of the + piece-wise linear scaling function for cr component. The values are + signaled on the scale of 0..255. + * - __u8 + - ``point_cr_scaling[V4L2_AV1_MAX_NUM_CR_POINTS]`` + - Represents the scaling (output) value for the i-th point of the + piecewise linear scaling function for cr component. + * - __u8 + - ``grain_scaling_minus_8`` + - Represents the shift - 8 applied to the values of the chroma component. + The grain_scaling_minus_8 can take values of 0..3 and determines the + range and quantization step of the standard deviation of film grain. + * - __u8 + - ``ar_coeff_lag`` + - Specifies the number of auto-regressive coefficients for luma and + chroma. + * - __u8 + - ``ar_coeffs_y_plus_128[V4L2_AV1_AR_COEFFS_SIZE]`` + - Specifies auto-regressive coefficients used for the Y plane. + * - __u8 + - ``ar_coeffs_cb_plus_128[V4L2_AV1_AR_COEFFS_SIZE]`` + - Specifies auto-regressive coefficients used for the U plane. + * - __u8 + - ``ar_coeffs_cr_plus_128[V4L2_AV1_AR_COEFFS_SIZE]`` + - Specifies auto-regressive coefficients used for the V plane. + * - __u8 + - ``ar_coeff_shift_minus_6`` + - Specifies the range of the auto-regressive coefficients. Values of 0, + 1, 2, and 3 correspond to the ranges for auto-regressive coefficients of + [-2, 2), [-1, 1), [-0.5, 0.5) and [-0.25, 0.25) respectively. + * - __u8 + - ``grain_scale_shift`` + - Specifies how much the Gaussian random numbers should be scaled down + during the grain synthesis process. + * - __u8 + - ``cb_mult`` + - Represents a multiplier for the cb component used in derivation of the + input index to the cb component scaling function. + * - __u8 + - ``cb_luma_mult`` + - Represents a multiplier for the average luma component used in + derivation of the input index to the cb component scaling function.. + * - __u8 + - ``cr_luma_mult`` + - Represents a multiplier for the average luma component used in + derivation of the input index to the cr component scaling function. + * - __u16 + - ``cb_offset`` + - Represents an offset used in derivation of the input index to the + cb component scaling function. + * - __u16 + - ``cr_offset`` + - Represents an offset used in derivation of the input index to the + cr component scaling function. + * - __u8 + - ``reserved[4]`` + - Applications and drivers must set this to zero. + +.. _av1_film_grain_flags: + +``AV1 Film Grain Flags`` + +.. cssclass:: longtable + +.. flat-table:: + :header-rows: 0 + :stub-columns: 0 + :widths: 1 1 2 + + * - ``V4L2_AV1_FILM_GRAIN_FLAG_APPLY_GRAIN`` + - 0x00000001 + - If set, specifies that film grain should be added to this frame. If not + set, specifies that film grain should not be added. + * - ``V4L2_AV1_FILM_GRAIN_FLAG_UPDATE_GRAIN`` + - 0x00000002 + - If set, means that a new set of parameters should be sent. If not set, + specifies that the previous set of parameters should be used. + * - ``V4L2_AV1_FILM_GRAIN_FLAG_CHROMA_SCALING_FROM_LUMA`` + - 0x00000004 + - If set, specifies that the chroma scaling is inferred from the luma + scaling. + * - ``V4L2_AV1_FILM_GRAIN_FLAG_OVERLAP`` + - 0x00000008 + - If set, indicates that the overlap between film grain blocks shall be + applied. If not set, indicates that the overlap between film grain blocks + shall not be applied. + * - ``V4L2_AV1_FILM_GRAIN_FLAG_CLIP_TO_RESTRICTED_RANGE`` + - 0x00000010 + - If set, indicates that clipping to the restricted (studio, i.e. limited) + range shall be applied to the sample values after adding the film grain + (see the semantics for color_range for an explanation of studio swing). + If not set, indicates that clipping to the full range shall be applied + to the sample values after adding the film grain. diff --git a/Documentation/userspace-api/media/v4l/meta-formats.rst b/Documentation/userspace-api/media/v4l/meta-formats.rst index fff25357fe860a182c794fc04c471e89eac96dcc..0bb61fc5bc008cf532cbb385c6c895287c46b91d 100644 --- a/Documentation/userspace-api/media/v4l/meta-formats.rst +++ b/Documentation/userspace-api/media/v4l/meta-formats.rst @@ -12,10 +12,10 @@ These formats are used for the :ref:`metadata` interface only. .. toctree:: :maxdepth: 1 - pixfmt-meta-d4xx - pixfmt-meta-intel-ipu3 - pixfmt-meta-rkisp1 - pixfmt-meta-uvc - pixfmt-meta-vsp1-hgo - pixfmt-meta-vsp1-hgt - pixfmt-meta-vivid + metafmt-d4xx + metafmt-intel-ipu3 + metafmt-rkisp1 + metafmt-uvc + metafmt-vsp1-hgo + metafmt-vsp1-hgt + metafmt-vivid diff --git a/Documentation/userspace-api/media/v4l/pixfmt-meta-d4xx.rst b/Documentation/userspace-api/media/v4l/metafmt-d4xx.rst similarity index 74% rename from Documentation/userspace-api/media/v4l/pixfmt-meta-d4xx.rst rename to Documentation/userspace-api/media/v4l/metafmt-d4xx.rst index 4e437ba97a0ec3b746fbd55dcca760e3d0059eb5..541836074f949278b11cf900f8aa7a0b18fa4d3e 100644 --- a/Documentation/userspace-api/media/v4l/pixfmt-meta-d4xx.rst +++ b/Documentation/userspace-api/media/v4l/metafmt-d4xx.rst @@ -12,7 +12,7 @@ Intel D4xx UVC Cameras Metadata Description =========== -Intel D4xx (D435 and other) cameras include per-frame metadata in their UVC +Intel D4xx (D435, D455 and others) cameras include per-frame metadata in their UVC payload headers, following the Microsoft(R) UVC extension proposal [1_]. That means, that the private D4XX metadata, following the standard UVC header, is organised in blocks. D4XX cameras implement several standard block types, @@ -26,6 +26,8 @@ V4L2_META_FMT_UVC with the only difference, that it also includes proprietary payload header data. D4xx cameras use bulk transfers and only send one payload per frame, therefore their headers cannot be larger than 255 bytes. +This document implements Intel Configuration version 3 [9_]. + Below are proprietary Microsoft style metadata types, used by D4xx cameras, where all fields are in little endian order: @@ -43,10 +45,10 @@ where all fields are in little endian order: * - __u32 ID - 0x80000000 * - __u32 Size - - Size in bytes (currently 56) + - Size in bytes, include ID (all protocol versions: 60) * - __u32 Version - - Version of this structure. The documentation herein corresponds to - version xxx. The version number will be incremented when new fields are + - Version of this structure. The documentation herein covers versions 1, + 2 and 3. The version number will be incremented when new fields are added. * - __u32 Flags - A bitmask of flags: see [2_] below @@ -72,13 +74,17 @@ where all fields are in little endian order: - Bottom border of the AE Region of Interest * - __u32 Preset - Preset selector value, default: 0, unless changed by the user - * - __u32 Laser mode - - 0: off, 1: on + * - __u8 Emitter mode (v3 only) (__u32 Laser mode for v1) [8_] + - 0: off, 1: on, same as __u32 Laser mode for v1 + * - __u8 RFU byte (v3 only) + - Spare byte for future use + * - __u16 LED Power (v3 only) + - Led power value 0-360 (F416 SKU) * - :cspan:`1` *Capture Timing* * - __u32 ID - 0x80000001 * - __u32 Size - - Size in bytes (currently 40) + - Size in bytes, include ID (all protocol versions: 40) * - __u32 Version - Version of this structure. The documentation herein corresponds to version xxx. The version number will be incremented when new fields are @@ -101,7 +107,7 @@ where all fields are in little endian order: * - __u32 ID - 0x80000002 * - __u32 Size - - Size in bytes (currently 40) + - Size in bytes, include ID (v1:36, v3:40) * - __u32 Version - Version of this structure. The documentation herein corresponds to version xxx. The version number will be incremented when new fields are @@ -124,6 +130,14 @@ where all fields are in little endian order: - Requested frame rate per second * - __u16 Trigger - Byte 0: bit 0: depth and RGB are synchronised, bit 1: external trigger + * - __u16 Calibration count (v3 only) + - Calibration counter, see [4_] below + * - __u8 GPIO input data (v3 only) + - GPIO readout, see [4_] below (Supported from FW 5.12.7.0) + * - __u32 Sub-preset info (v3 only) + - Sub-preset choice information, see [4_] below + * - __u8 reserved (v3 only) + - RFU byte. .. _1: @@ -140,6 +154,8 @@ where all fields are in little endian order: 0x00000010 Exposure priority 0x00000020 AE ROI 0x00000040 Preset + 0x00000080 Emitter mode + 0x00000100 LED Power .. _3: @@ -165,6 +181,8 @@ where all fields are in little endian order: 0x00000040 Framerate 0x00000080 Trigger 0x00000100 Cal count + 0x00000200 GPIO Input Data + 0x00000400 Sub-preset Info .. _5: @@ -211,3 +229,24 @@ Left sensor: :: Fish Eye sensor: :: 1 RAW8 + +.. _8: + +[8] The "Laser mode" has been replaced in version 3 by three different fields. +"Laser" has been renamed to "Emitter" as there are multiple technologies for +camera projectors. As we have another field for "Laser Power" we introduced +"LED Power" for extra emitter. + +The "Laser mode" __u32 fiels has been split into: :: + 1 __u8 Emitter mode + 2 __u8 RFU byte + 3 __u16 LED Power + +This is a change between versions 1 and 3. All versions 1, 2 and 3 are backward +compatible with the same data format and they are supported. See [2_] for which +attributes are valid. + +.. _9: + +[9] LibRealSense SDK metadata source: +https://github.com/IntelRealSense/librealsense/blob/master/src/metadata.h diff --git a/Documentation/userspace-api/media/v4l/pixfmt-meta-intel-ipu3.rst b/Documentation/userspace-api/media/v4l/metafmt-intel-ipu3.rst similarity index 100% rename from Documentation/userspace-api/media/v4l/pixfmt-meta-intel-ipu3.rst rename to Documentation/userspace-api/media/v4l/metafmt-intel-ipu3.rst diff --git a/Documentation/userspace-api/media/v4l/pixfmt-meta-rkisp1.rst b/Documentation/userspace-api/media/v4l/metafmt-rkisp1.rst similarity index 100% rename from Documentation/userspace-api/media/v4l/pixfmt-meta-rkisp1.rst rename to Documentation/userspace-api/media/v4l/metafmt-rkisp1.rst diff --git a/Documentation/userspace-api/media/v4l/pixfmt-meta-uvc.rst b/Documentation/userspace-api/media/v4l/metafmt-uvc.rst similarity index 100% rename from Documentation/userspace-api/media/v4l/pixfmt-meta-uvc.rst rename to Documentation/userspace-api/media/v4l/metafmt-uvc.rst diff --git a/Documentation/userspace-api/media/v4l/pixfmt-meta-vivid.rst b/Documentation/userspace-api/media/v4l/metafmt-vivid.rst similarity index 100% rename from Documentation/userspace-api/media/v4l/pixfmt-meta-vivid.rst rename to Documentation/userspace-api/media/v4l/metafmt-vivid.rst diff --git a/Documentation/userspace-api/media/v4l/pixfmt-meta-vsp1-hgo.rst b/Documentation/userspace-api/media/v4l/metafmt-vsp1-hgo.rst similarity index 100% rename from Documentation/userspace-api/media/v4l/pixfmt-meta-vsp1-hgo.rst rename to Documentation/userspace-api/media/v4l/metafmt-vsp1-hgo.rst diff --git a/Documentation/userspace-api/media/v4l/pixfmt-meta-vsp1-hgt.rst b/Documentation/userspace-api/media/v4l/metafmt-vsp1-hgt.rst similarity index 100% rename from Documentation/userspace-api/media/v4l/pixfmt-meta-vsp1-hgt.rst rename to Documentation/userspace-api/media/v4l/metafmt-vsp1-hgt.rst diff --git a/Documentation/userspace-api/media/v4l/pixfmt-compressed.rst b/Documentation/userspace-api/media/v4l/pixfmt-compressed.rst index 06b78e5589d27eda1bf1f9502eb9d7aef4d2486c..806ed73ac474ce0e6df00f902850db9fd0db240e 100644 --- a/Documentation/userspace-api/media/v4l/pixfmt-compressed.rst +++ b/Documentation/userspace-api/media/v4l/pixfmt-compressed.rst @@ -258,6 +258,22 @@ Compressed Formats RV9 players - the format and decoder did not change, only the encoder did. As a result, it uses the same FourCC. + * .. _V4L2-PIX-FMT-AV1-FRAME: + + - ``V4L2_PIX_FMT_AV1_FRAME`` + - 'AV1F' + - AV1 parsed frame, including the frame header, as extracted from the container. + This format is adapted for stateless video decoders that implement a AV1 + pipeline with the :ref:`stateless_decoder`. Metadata associated with the + frame to decode is required to be passed through the + ``V4L2_CID_STATELESS_AV1_SEQUENCE``, ``V4L2_CID_STATELESS_AV1_FRAME``, + and ``V4L2_CID_STATELESS_AV1_TILE_GROUP_ENTRY`` controls. + See the :ref:`associated Codec Control IDs `. + Exactly one output and one capture buffer must be provided for use with + this pixel format. The output buffer must contain the appropriate number + of macroblocks to decode a full corresponding frame to the matching + capture buffer. + .. raw:: latex \normalsize diff --git a/Documentation/userspace-api/media/v4l/pixfmt-yuv-planar.rst b/Documentation/userspace-api/media/v4l/pixfmt-yuv-planar.rst index 72324274f20c945284c138b43f28f5ac28c592a0..1840224faa412660650bbb37aa887c2a5622d3c3 100644 --- a/Documentation/userspace-api/media/v4l/pixfmt-yuv-planar.rst +++ b/Documentation/userspace-api/media/v4l/pixfmt-yuv-planar.rst @@ -137,6 +137,13 @@ All components are stored with the same number of bits per component. - Cb, Cr - No - Linear + * - V4L2_PIX_FMT_NV15_4L4 + - 'VT15' + - 15 + - 4:2:0 + - Cb, Cr + - Yes + - 4x4 tiles * - V4L2_PIX_FMT_NV16 - 'NV16' - 8 @@ -378,6 +385,15 @@ two non-contiguous planes. Example V4L2_PIX_FMT_NV12MT memory layout of tiles +.. _V4L2-PIX-FMT-NV15-4L4: + +Tiled NV15 +---------- + +Semi-planar 10-bit YUV 4:2:0 formats, using 4x4 tiling. +All components are packed without any padding between each other. +As a side-effect, each group of 4 components are stored over 5 bytes +(YYYY or UVUV = 4 * 10 bits = 40 bits = 5 bytes). .. _V4L2-PIX-FMT-NV16: .. _V4L2-PIX-FMT-NV61: diff --git a/Documentation/userspace-api/media/v4l/vidioc-g-ext-ctrls.rst b/Documentation/userspace-api/media/v4l/vidioc-g-ext-ctrls.rst index 5292d5e1a91f6f39d7801d6c92efd79822118a6b..f9f73530a6be016ba8a68953449ee9c89061bcbf 100644 --- a/Documentation/userspace-api/media/v4l/vidioc-g-ext-ctrls.rst +++ b/Documentation/userspace-api/media/v4l/vidioc-g-ext-ctrls.rst @@ -185,12 +185,12 @@ still cause this situation. - ``p_u32`` - A pointer to a matrix control of unsigned 32-bit values. Valid if this control is of type ``V4L2_CTRL_TYPE_U32``. - * - __u32 * + * - __s32 * - ``p_s32`` - A pointer to a matrix control of signed 32-bit values. Valid if this control is of type ``V4L2_CTRL_TYPE_INTEGER`` and ``V4L2_CTRL_FLAG_HAS_PAYLOAD`` is set. - * - __u32 * + * - __s64 * - ``p_s64`` - A pointer to a matrix control of signed 64-bit values. Valid if this control is of type ``V4L2_CTRL_TYPE_INTEGER64`` and @@ -279,6 +279,22 @@ still cause this situation. - ``p_hevc_decode_params`` - A pointer to a struct :c:type:`v4l2_ctrl_hevc_decode_params`. Valid if this control is of type ``V4L2_CTRL_TYPE_HEVC_DECODE_PARAMS``. + * - struct :c:type:`v4l2_ctrl_av1_sequence` * + - ``p_av1_sequence`` + - A pointer to a struct :c:type:`v4l2_ctrl_av1_sequence`. Valid if this control is + of type ``V4L2_CTRL_TYPE_AV1_SEQUENCE``. + * - struct :c:type:`v4l2_ctrl_av1_tile_group_entry` * + - ``p_av1_tile_group_entry`` + - A pointer to a struct :c:type:`v4l2_ctrl_av1_tile_group_entry`. Valid if this control is + of type ``V4L2_CTRL_TYPE_AV1_TILE_GROUP_ENTRY``. + * - struct :c:type:`v4l2_ctrl_av1_frame` * + - ``p_av1_frame`` + - A pointer to a struct :c:type:`v4l2_ctrl_av1_frame`. Valid if this control is + of type ``V4L2_CTRL_TYPE_AV1_FRAME``. + * - struct :c:type:`v4l2_ctrl_av1_film_grain` * + - ``p_av1_film_grain`` + - A pointer to a struct :c:type:`v4l2_ctrl_av1_film_grain`. Valid if this control is + of type ``V4L2_CTRL_TYPE_AV1_FILM_GRAIN``. * - void * - ``ptr`` - A pointer to a compound type which can be an N-dimensional array diff --git a/Documentation/userspace-api/media/v4l/vidioc-queryctrl.rst b/Documentation/userspace-api/media/v4l/vidioc-queryctrl.rst index a20dfa2a933b89c854bfe213b35e83e78d9dccff..4d38acafe8e19309ecf1d4550f6578eddc446cc3 100644 --- a/Documentation/userspace-api/media/v4l/vidioc-queryctrl.rst +++ b/Documentation/userspace-api/media/v4l/vidioc-queryctrl.rst @@ -525,6 +525,30 @@ See also the examples in :ref:`control`. - n/a - A struct :c:type:`v4l2_ctrl_vp9_frame`, containing VP9 frame decode parameters for stateless video decoders. + * - ``V4L2_CTRL_TYPE_AV1_SEQUENCE`` + - n/a + - n/a + - n/a + - A struct :c:type:`v4l2_ctrl_av1_sequence`, containing AV1 Sequence OBU + decoding parameters for stateless video decoders. + * - ``V4L2_CTRL_TYPE_AV1_TILE_GROUP_ENTRY`` + - n/a + - n/a + - n/a + - A struct :c:type:`v4l2_ctrl_av1_tile_group_entry`, containing AV1 Tile Group + OBU decoding parameters for stateless video decoders. + * - ``V4L2_CTRL_TYPE_AV1_FRAME`` + - n/a + - n/a + - n/a + - A struct :c:type:`v4l2_ctrl_av1_frame`, containing AV1 Frame/Frame + Header OBU decoding parameters for stateless video decoders. + * - ``V4L2_CTRL_TYPE_AV1_FILM_GRAIN`` + - n/a + - n/a + - n/a + - A struct :c:type:`v4l2_ctrl_av1_film_grain`, containing AV1 Film Grain + parameters for stateless video decoders. .. raw:: latex diff --git a/Documentation/userspace-api/media/v4l/vidioc-subdev-g-routing.rst b/Documentation/userspace-api/media/v4l/vidioc-subdev-g-routing.rst index 68ca343c3b44a95b046ed6830bce5aa372bec32b..2d6e3bbdd040497e33faf95ee85d2b49dc0a92ad 100644 --- a/Documentation/userspace-api/media/v4l/vidioc-subdev-g-routing.rst +++ b/Documentation/userspace-api/media/v4l/vidioc-subdev-g-routing.rst @@ -122,7 +122,7 @@ for all the route entries and call ``VIDIOC_SUBDEV_G_ROUTING`` again. :widths: 3 1 4 * - V4L2_SUBDEV_ROUTE_FL_ACTIVE - - 0 + - 0x0001 - The route is enabled. Set by applications. Return Value diff --git a/Documentation/userspace-api/media/videodev2.h.rst.exceptions b/Documentation/userspace-api/media/videodev2.h.rst.exceptions index 2a589d34b80ea3f14f18452a57aa93d77331398e..3e58aac4ef0b6e2e0ce1672515ccaff660377e90 100644 --- a/Documentation/userspace-api/media/videodev2.h.rst.exceptions +++ b/Documentation/userspace-api/media/videodev2.h.rst.exceptions @@ -161,6 +161,10 @@ replace symbol V4L2_CTRL_TYPE_HEVC_PPS :c:type:`v4l2_ctrl_type` replace symbol V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS :c:type:`v4l2_ctrl_type` replace symbol V4L2_CTRL_TYPE_HEVC_SCALING_MATRIX :c:type:`v4l2_ctrl_type` replace symbol V4L2_CTRL_TYPE_HEVC_DECODE_PARAMS :c:type:`v4l2_ctrl_type` +replace symbol V4L2_CTRL_TYPE_AV1_SEQUENCE :c:type:`v4l2_ctrl_type` +replace symbol V4L2_CTRL_TYPE_AV1_TILE_GROUP_ENTRY :c:type:`v4l2_ctrl_type` +replace symbol V4L2_CTRL_TYPE_AV1_FRAME :c:type:`v4l2_ctrl_type` +replace symbol V4L2_CTRL_TYPE_AV1_FILM_GRAIN :c:type:`v4l2_ctrl_type` # V4L2 capability defines replace define V4L2_CAP_VIDEO_CAPTURE device-capabilities diff --git a/Documentation/userspace-api/netlink/intro-specs.rst b/Documentation/userspace-api/netlink/intro-specs.rst index a3b847eafff711b6c92e46dbb773696605bb2e06..bada89699455c84d0cceed988389578c96cfded9 100644 --- a/Documentation/userspace-api/netlink/intro-specs.rst +++ b/Documentation/userspace-api/netlink/intro-specs.rst @@ -78,3 +78,82 @@ to see other examples. The code generation itself is performed by ``tools/net/ynl/ynl-gen-c.py`` but it takes a few arguments so calling it directly for each file quickly becomes tedious. + +YNL lib +======= + +``tools/net/ynl/lib/`` contains an implementation of a C library +(based on libmnl) which integrates with code generated by +``tools/net/ynl/ynl-gen-c.py`` to create easy to use netlink wrappers. + +YNL basics +---------- + +The YNL library consists of two parts - the generic code (functions +prefix by ``ynl_``) and per-family auto-generated code (prefixed +with the name of the family). + +To create a YNL socket call ynl_sock_create() passing the family +struct (family structs are exported by the auto-generated code). +ynl_sock_destroy() closes the socket. + +YNL requests +------------ + +Steps for issuing YNL requests are best explained on an example. +All the functions and types in this example come from the auto-generated +code (for the netdev family in this case): + +.. code-block:: c + + // 0. Request and response pointers + struct netdev_dev_get_req *req; + struct netdev_dev_get_rsp *d; + + // 1. Allocate a request + req = netdev_dev_get_req_alloc(); + // 2. Set request parameters (as needed) + netdev_dev_get_req_set_ifindex(req, ifindex); + + // 3. Issues the request + d = netdev_dev_get(ys, req); + // 4. Free the request arguments + netdev_dev_get_req_free(req); + // 5. Error check (the return value from step 3) + if (!d) { + // 6. Print the YNL-generated error + fprintf(stderr, "YNL: %s\n", ys->err.msg); + return -1; + } + + // ... do stuff with the response @d + + // 7. Free response + netdev_dev_get_rsp_free(d); + +YNL dumps +--------- + +Performing dumps follows similar pattern as requests. +Dumps return a list of objects terminated by a special marker, +or NULL on error. Use ``ynl_dump_foreach()`` to iterate over +the result. + +YNL notifications +----------------- + +YNL lib supports using the same socket for notifications and +requests. In case notifications arrive during processing of a request +they are queued internally and can be retrieved at a later time. + +To subscribed to notifications use ``ynl_subscribe()``. +The notifications have to be read out from the socket, +``ynl_socket_get_fd()`` returns the underlying socket fd which can +be plugged into appropriate asynchronous IO API like ``poll``, +or ``select``. + +Notifications can be retrieved using ``ynl_ntf_dequeue()`` and have +to be freed using ``ynl_ntf_free()``. Since we don't know the notification +type upfront the notifications are returned as ``struct ynl_ntf_base_type *`` +and user is expected to cast them to the appropriate full type based +on the ``cmd`` member. diff --git a/Documentation/virt/guest-halt-polling.rst b/Documentation/virt/guest-halt-polling.rst index b4e747942417ad3b94e83fdf5e264ffba71e98ba..922291ddc40c6e858f9e4b6bd06e7bad03fbd875 100644 --- a/Documentation/virt/guest-halt-polling.rst +++ b/Documentation/virt/guest-halt-polling.rst @@ -72,7 +72,7 @@ high once achieves global guest_halt_poll_ns value). Default: Y -The module parameters can be set from the debugfs files in:: +The module parameters can be set from the sysfs files in:: /sys/module/haltpoll/parameters/ diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst index add067793b90b19f2fc7f03cef128b590d604610..c0ddd3035462bd8ad99bb4147381b79399cff807 100644 --- a/Documentation/virt/kvm/api.rst +++ b/Documentation/virt/kvm/api.rst @@ -2613,7 +2613,7 @@ follows:: this vcpu, and determines which register slices are visible through this ioctl interface. -(See Documentation/arm64/sve.rst for an explanation of the "vq" +(See Documentation/arch/arm64/sve.rst for an explanation of the "vq" nomenclature.) KVM_REG_ARM64_SVE_VLS is only accessible after KVM_ARM_VCPU_INIT. @@ -8445,6 +8445,33 @@ structure. When getting the Modified Change Topology Report value, the attr->addr must point to a byte where the value will be stored or retrieved from. +8.40 KVM_CAP_ARM_EAGER_SPLIT_CHUNK_SIZE +--------------------------------------- + +:Capability: KVM_CAP_ARM_EAGER_SPLIT_CHUNK_SIZE +:Architectures: arm64 +:Type: vm +:Parameters: arg[0] is the new split chunk size. +:Returns: 0 on success, -EINVAL if any memslot was already created. + +This capability sets the chunk size used in Eager Page Splitting. + +Eager Page Splitting improves the performance of dirty-logging (used +in live migrations) when guest memory is backed by huge-pages. It +avoids splitting huge-pages (into PAGE_SIZE pages) on fault, by doing +it eagerly when enabling dirty logging (with the +KVM_MEM_LOG_DIRTY_PAGES flag for a memory region), or when using +KVM_CLEAR_DIRTY_LOG. + +The chunk size specifies how many pages to break at a time, using a +single allocation for each chunk. Bigger the chunk size, more pages +need to be allocated ahead of time. + +The chunk size needs to be a valid block size. The list of acceptable +block sizes is exposed in KVM_CAP_ARM_SUPPORTED_BLOCK_SIZES as a +64-bit bitmap (each bit describing a block size). The default value is +0, to disable the eager page splitting. + 9. Known KVM API problems ========================= diff --git a/Documentation/virt/kvm/halt-polling.rst b/Documentation/virt/kvm/halt-polling.rst index 3fae39b1a5ba31f12619a8acc2dfb530279a1b42..4f1a1b23d99cb0e9c9f4866760d34f86f397eef8 100644 --- a/Documentation/virt/kvm/halt-polling.rst +++ b/Documentation/virt/kvm/halt-polling.rst @@ -112,11 +112,11 @@ powerpc kvm-hv case. | | function. | | +-----------------------+---------------------------+-------------------------+ -These module parameters can be set from the debugfs files in: +These module parameters can be set from the sysfs files in: /sys/module/kvm/parameters/ -Note: that these module parameters are system wide values and are not able to +Note: these module parameters are system-wide values and are not able to be tuned on a per vm basis. Any changes to these parameters will be picked up by new and existing vCPUs the @@ -142,12 +142,12 @@ Further Notes global max polling interval (halt_poll_ns) then the host will always poll for the entire block time and thus cpu utilisation will go to 100%. -- Halt polling essentially presents a trade off between power usage and latency and +- Halt polling essentially presents a trade-off between power usage and latency and the module parameters should be used to tune the affinity for this. Idle cpu time is essentially converted to host kernel time with the aim of decreasing latency when entering the guest. - Halt polling will only be conducted by the host when no other tasks are runnable on that cpu, otherwise the polling will cease immediately and schedule will be invoked to - allow that other task to run. Thus this doesn't allow a guest to denial of service the - cpu. + allow that other task to run. Thus this doesn't allow a guest to cause denial of service + of the cpu. diff --git a/Documentation/virt/kvm/locking.rst b/Documentation/virt/kvm/locking.rst index 8c77554e4896340533aa2e37a2dee57b0dd28685..3a034db5e55f89120db01f8c7b4853bdca08cf4d 100644 --- a/Documentation/virt/kvm/locking.rst +++ b/Documentation/virt/kvm/locking.rst @@ -67,7 +67,7 @@ following two cases: 2. Write-Protection: The SPTE is present and the fault is caused by write-protect. That means we just need to change the W bit of the spte. -What we use to avoid all the race is the Host-writable bit and MMU-writable bit +What we use to avoid all the races is the Host-writable bit and MMU-writable bit on the spte: - Host-writable means the gfn is writable in the host kernel page tables and in @@ -130,7 +130,7 @@ to gfn. For indirect sp, we disabled fast page fault for simplicity. A solution for indirect sp could be to pin the gfn, for example via kvm_vcpu_gfn_to_pfn_atomic, before the cmpxchg. After the pinning: -- We have held the refcount of pfn that means the pfn can not be freed and +- We have held the refcount of pfn; that means the pfn can not be freed and be reused for another gfn. - The pfn is writable and therefore it cannot be shared between different gfns by KSM. @@ -186,22 +186,22 @@ writable between reading spte and updating spte. Like below case: The Dirty bit is lost in this case. In order to avoid this kind of issue, we always treat the spte as "volatile" -if it can be updated out of mmu-lock, see spte_has_volatile_bits(), it means, +if it can be updated out of mmu-lock [see spte_has_volatile_bits()]; it means the spte is always atomically updated in this case. 3) flush tlbs due to spte updated -If the spte is updated from writable to readonly, we should flush all TLBs, +If the spte is updated from writable to read-only, we should flush all TLBs, otherwise rmap_write_protect will find a read-only spte, even though the writable spte might be cached on a CPU's TLB. As mentioned before, the spte can be updated to writable out of mmu-lock on -fast page fault path, in order to easily audit the path, we see if TLBs need -be flushed caused by this reason in mmu_spte_update() since this is a common +fast page fault path. In order to easily audit the path, we see if TLBs needing +to be flushed caused this reason in mmu_spte_update() since this is a common function to update spte (present -> present). Since the spte is "volatile" if it can be updated out of mmu-lock, we always -atomically update the spte, the race caused by fast page fault can be avoided, +atomically update the spte and the race caused by fast page fault can be avoided. See the comments in spte_has_volatile_bits() and mmu_spte_update(). Lockless Access Tracking: @@ -283,9 +283,9 @@ time it will be set using the Dirty tracking mechanism described above. :Arch: x86 :Protects: wakeup_vcpus_on_cpu :Comment: This is a per-CPU lock and it is used for VT-d posted-interrupts. - When VT-d posted-interrupts is supported and the VM has assigned + When VT-d posted-interrupts are supported and the VM has assigned devices, we put the blocked vCPU on the list blocked_vcpu_on_cpu - protected by blocked_vcpu_on_cpu_lock, when VT-d hardware issues + protected by blocked_vcpu_on_cpu_lock. When VT-d hardware issues wakeup notification event since external interrupts from the assigned devices happens, we will find the vCPU on the list to wakeup. diff --git a/Documentation/virt/kvm/ppc-pv.rst b/Documentation/virt/kvm/ppc-pv.rst index 5fdb907670be01ecdf1e44fbcaa99dbc2480985e..740d03d2530032abe54a9c6bb8f69715b63c1201 100644 --- a/Documentation/virt/kvm/ppc-pv.rst +++ b/Documentation/virt/kvm/ppc-pv.rst @@ -89,7 +89,7 @@ also define a new hypercall feature to indicate that the host can give you more registers. Only if the host supports the additional features, make use of them. The magic page layout is described by struct kvm_vcpu_arch_shared -in arch/powerpc/include/asm/kvm_para.h. +in arch/powerpc/include/uapi/asm/kvm_para.h. Magic page features =================== @@ -112,7 +112,7 @@ Magic page flags ================ In addition to features that indicate whether a host is capable of a particular -feature we also have a channel for a guest to tell the guest whether it's capable +feature we also have a channel for a guest to tell the host whether it's capable of something. This is what we call "flags". Flags are passed to the host in the low 12 bits of the Effective Address. @@ -139,7 +139,7 @@ Patched instructions ==================== The "ld" and "std" instructions are transformed to "lwz" and "stw" instructions -respectively on 32 bit systems with an added offset of 4 to accommodate for big +respectively on 32-bit systems with an added offset of 4 to accommodate for big endianness. The following is a list of mapping the Linux kernel performs when running as @@ -210,7 +210,7 @@ available on all targets. 2) PAPR hypercalls PAPR hypercalls are needed to run server PowerPC PAPR guests (-M pseries in QEMU). -These are the same hypercalls that pHyp, the POWER hypervisor implements. Some of +These are the same hypercalls that pHyp, the POWER hypervisor, implements. Some of them are handled in the kernel, some are handled in user space. This is only available on book3s_64. diff --git a/Documentation/virt/kvm/vcpu-requests.rst b/Documentation/virt/kvm/vcpu-requests.rst index 87f04c1fa53d1c3c1efef0dff1e2fb88d2f3a258..06718b9bc959777b739da7b9a8901febb71377ad 100644 --- a/Documentation/virt/kvm/vcpu-requests.rst +++ b/Documentation/virt/kvm/vcpu-requests.rst @@ -101,7 +101,7 @@ also be used, e.g. :: However, VCPU request users should refrain from doing so, as it would break the abstraction. The first 8 bits are reserved for architecture -independent requests, all additional bits are available for architecture +independent requests; all additional bits are available for architecture dependent requests. Architecture Independent Requests @@ -151,8 +151,8 @@ KVM_REQUEST_NO_WAKEUP This flag is applied to requests that only need immediate attention from VCPUs running in guest mode. That is, sleeping VCPUs do not need - to be awaken for these requests. Sleeping VCPUs will handle the - requests when they are awaken later for some other reason. + to be awakened for these requests. Sleeping VCPUs will handle the + requests when they are awakened later for some other reason. KVM_REQUEST_WAIT diff --git a/Documentation/virt/kvm/x86/amd-memory-encryption.rst b/Documentation/virt/kvm/x86/amd-memory-encryption.rst index 487b6328b3e703c6321769dbba84194aa992c286..995780088eb23142a169542fad4d298b4cbc2cfe 100644 --- a/Documentation/virt/kvm/x86/amd-memory-encryption.rst +++ b/Documentation/virt/kvm/x86/amd-memory-encryption.rst @@ -57,7 +57,7 @@ information, see the SEV Key Management spec [api-spec]_ The main ioctl to access SEV is KVM_MEMORY_ENCRYPT_OP. If the argument to KVM_MEMORY_ENCRYPT_OP is NULL, the ioctl returns 0 if SEV is enabled -and ``ENOTTY` if it is disabled (on some older versions of Linux, +and ``ENOTTY`` if it is disabled (on some older versions of Linux, the ioctl runs normally even with a NULL argument, and therefore will likely return ``EFAULT``). If non-NULL, the argument to KVM_MEMORY_ENCRYPT_OP must be a struct kvm_sev_cmd:: diff --git a/Documentation/virt/kvm/x86/mmu.rst b/Documentation/virt/kvm/x86/mmu.rst index 8364afa228ecb5df661aa795152c74d0d29527d7..26f62034b6f3edc53de08eaa271c376f329211d4 100644 --- a/Documentation/virt/kvm/x86/mmu.rst +++ b/Documentation/virt/kvm/x86/mmu.rst @@ -205,7 +205,7 @@ Shadow pages contain the following information: role.passthrough: The page is not backed by a guest page table, but its first entry points to one. This is set if NPT uses 5-level page tables (host - CR4.LA57=1) and is shadowing L1's 4-level NPT (L1 CR4.LA57=1). + CR4.LA57=1) and is shadowing L1's 4-level NPT (L1 CR4.LA57=0). gfn: Either the guest page table containing the translations shadowed by this page, or the base page frame for linear translations. See role.direct. diff --git a/Documentation/virt/paravirt_ops.rst b/Documentation/virt/paravirt_ops.rst index 6b789d27cead44d22d1b6a4b299b651ad84b1c4f..62d867e0d4d6368641bbde369e8ce90f1b65ca58 100644 --- a/Documentation/virt/paravirt_ops.rst +++ b/Documentation/virt/paravirt_ops.rst @@ -5,31 +5,31 @@ Paravirt_ops ============ Linux provides support for different hypervisor virtualization technologies. -Historically different binary kernels would be required in order to support -different hypervisors, this restriction was removed with pv_ops. +Historically, different binary kernels would be required in order to support +different hypervisors; this restriction was removed with pv_ops. Linux pv_ops is a virtualization API which enables support for different hypervisors. It allows each hypervisor to override critical operations and allows a single kernel binary to run on all supported execution environments including native machine -- without any hypervisors. pv_ops provides a set of function pointers which represent operations -corresponding to low level critical instructions and high level -functionalities in various areas. pv-ops allows for optimizations at run -time by enabling binary patching of the low-ops critical operations +corresponding to low-level critical instructions and high-level +functionalities in various areas. pv_ops allows for optimizations at run +time by enabling binary patching of the low-level critical operations at boot time. pv_ops operations are classified into three categories: - simple indirect call - These operations correspond to high level functionality where it is + These operations correspond to high-level functionality where it is known that the overhead of indirect call isn't very important. - indirect call which allows optimization with binary patch - Usually these operations correspond to low level critical instructions. They + Usually these operations correspond to low-level critical instructions. They are called frequently and are performance critical. The overhead is very important. - a set of macros for hand written assembly code Hand written assembly codes (.S files) also need paravirtualization - because they include sensitive instructions or some of code paths in + because they include sensitive instructions or some code paths in them are very performance critical. diff --git a/Documentation/wmi/acpi-interface.rst b/Documentation/wmi/acpi-interface.rst new file mode 100644 index 0000000000000000000000000000000000000000..d31af0ed9c0836c86a6c7f19e929f8087df4e581 --- /dev/null +++ b/Documentation/wmi/acpi-interface.rst @@ -0,0 +1,96 @@ +.. SPDX-License-Identifier: GPL-2.0-or-later + +================== +ACPI WMI interface +================== + +The ACPI WMI interface is a proprietary extension of the ACPI specification made +by Microsoft to allow hardware vendors to embed WMI (Windows Management Instrumentation) +objects inside their ACPI firmware. Typical functions implemented over ACPI WMI +are hotkey events on modern notebooks and configuration of BIOS options. + +PNP0C14 ACPI device +------------------- + +Discovery of WMI objects is handled by defining ACPI devices with a PNP ID +of ``PNP0C14``. These devices will contain a set of ACPI buffers and methods +used for mapping and execution of WMI methods and/or queries. If there exist +multiple of such devices, then each device is required to have a +unique ACPI UID. + +_WDG buffer +----------- + +The ``_WDG`` buffer is used to discover WMI objects and is required to be +static. Its internal structure consists of data blocks with a size of 20 bytes, +containing the following data: + +======= =============== ===================================================== +Offset Size (in bytes) Content +======= =============== ===================================================== +0x00 16 128 bit Variant 2 object GUID. +0x10 2 2 character method ID or single byte notification ID. +0x12 1 Object instance count. +0x13 1 Object flags. +======= =============== ===================================================== + +The WMI object flags control whether the method or notification ID is used: + +- 0x1: Data block usage is expensive and must be explicitly enabled/disabled. +- 0x2: Data block contains WMI methods. +- 0x4: Data block contains ASCIZ string. +- 0x8: Data block describes a WMI event, use notification ID instead + of method ID. + +Each WMI object GUID can appear multiple times inside a system. +The method/notification ID is used to construct the ACPI method names used for +interacting with the WMI object. + +WQxx ACPI methods +----------------- + +If a data block does not contain WMI methods, then its content can be retrieved +by this required ACPI method. The last two characters of the ACPI method name +are the method ID of the data block to query. Their single parameter is an +integer describing the instance which should be queried. This parameter can be +omitted if the data block contains only a single instance. + +WSxx ACPI methods +----------------- + +Similar to the ``WQxx`` ACPI methods, except that it is optional and takes an +additional buffer as its second argument. The instance argument also cannot +be omitted. + +WMxx ACPI methods +----------------- + +Used for executing WMI methods associated with a data block. The last two +characters of the ACPI method name are the method ID of the data block +containing the WMI methods. Their first parameter is a integer describing the +instance which methods should be executed. The second parameter is an integer +describing the WMI method ID to execute, and the third parameter is a buffer +containing the WMI method parameters. If the data block is marked as containing +an ASCIZ string, then this buffer should contain an ASCIZ string. The ACPI +method will return the result of the executed WMI method. + +WExx ACPI methods +----------------- + +Used for optionally enabling/disabling WMI events, the last two characters of +the ACPI method are the notification ID of the data block describing the WMI +event as hexadecimal value. Their first parameter is an integer with a value +of 0 if the WMI event should be disabled, other values will enable +the WMI event. + +WCxx ACPI methods +----------------- +Similar to the ``WExx`` ACPI methods, except that it controls data collection +instead of events and thus the last two characters of the ACPI method name are +the method ID of the data block to enable/disable. + +_WED ACPI method +---------------- + +Used to retrieve additional WMI event data, its single parameter is a integer +holding the notification ID of the event. diff --git a/Documentation/wmi/devices/dell-wmi-ddv.rst b/Documentation/wmi/devices/dell-wmi-ddv.rst new file mode 100644 index 0000000000000000000000000000000000000000..bf963d91dd55b0f01bbe2f430e89f46387fb253a --- /dev/null +++ b/Documentation/wmi/devices/dell-wmi-ddv.rst @@ -0,0 +1,297 @@ +.. SPDX-License-Identifier: GPL-2.0-or-later + +============================================ +Dell DDV WMI interface driver (dell-wmi-ddv) +============================================ + +Introduction +============ + +Many Dell notebooks made after ~2020 support a WMI-based interface for +retrieving various system data like battery temperature, ePPID, diagostic data +and fan/thermal sensor data. + +This interface is likely used by the `Dell Data Vault` software on Windows, +so it was called `DDV`. Currently the ``dell-wmi-ddv`` driver supports +version 2 and 3 of the interface, with support for new interface versions +easily added. + +.. warning:: The interface is regarded as internal by Dell, so no vendor + documentation is available. All knowledge was thus obtained by + trial-and-error, please keep that in mind. + +Dell ePPID (electronic Piece Part Identification) +================================================= + +The Dell ePPID is used to uniquely identify components in Dell machines, +including batteries. It has a form similar to `CC-PPPPPP-MMMMM-YMD-SSSS-FFF` +and contains the following information: + +* Country code of origin (CC). +* Part number with the first character being a filling number (PPPPPP). +* Manufacture Identification (MMMMM). +* Manufacturing Year/Month/Date (YMD) in base 36, with Y being the last digit + of the year. +* Manufacture Sequence Number (SSSS). +* Optional Firmware Version/Revision (FFF). + +The `eppidtool `_ python utility can be used +to decode and display this information. + +All information regarding the Dell ePPID was gathered using Dell support +documentation and `this website `_. + +WMI interface description +========================= + +The WMI interface description can be decoded from the embedded binary MOF (bmof) +data using the `bmfdec `_ utility: + +:: + + [WMI, Dynamic, Provider("WmiProv"), Locale("MS\\0x409"), Description("WMI Function"), guid("{8A42EA14-4F2A-FD45-6422-0087F7A7E608}")] + class DDVWmiMethodFunction { + [key, read] string InstanceName; + [read] boolean Active; + + [WmiMethodId(1), Implemented, read, write, Description("Return Battery Design Capacity.")] void BatteryDesignCapacity([in] uint32 arg2, [out] uint32 argr); + [WmiMethodId(2), Implemented, read, write, Description("Return Battery Full Charge Capacity.")] void BatteryFullChargeCapacity([in] uint32 arg2, [out] uint32 argr); + [WmiMethodId(3), Implemented, read, write, Description("Return Battery Manufacture Name.")] void BatteryManufactureName([in] uint32 arg2, [out] string argr); + [WmiMethodId(4), Implemented, read, write, Description("Return Battery Manufacture Date.")] void BatteryManufactureDate([in] uint32 arg2, [out] uint32 argr); + [WmiMethodId(5), Implemented, read, write, Description("Return Battery Serial Number.")] void BatterySerialNumber([in] uint32 arg2, [out] uint32 argr); + [WmiMethodId(6), Implemented, read, write, Description("Return Battery Chemistry Value.")] void BatteryChemistryValue([in] uint32 arg2, [out] string argr); + [WmiMethodId(7), Implemented, read, write, Description("Return Battery Temperature.")] void BatteryTemperature([in] uint32 arg2, [out] uint32 argr); + [WmiMethodId(8), Implemented, read, write, Description("Return Battery Current.")] void BatteryCurrent([in] uint32 arg2, [out] uint32 argr); + [WmiMethodId(9), Implemented, read, write, Description("Return Battery Voltage.")] void BatteryVoltage([in] uint32 arg2, [out] uint32 argr); + [WmiMethodId(10), Implemented, read, write, Description("Return Battery Manufacture Access(MA code).")] void BatteryManufactureAceess([in] uint32 arg2, [out] uint32 argr); + [WmiMethodId(11), Implemented, read, write, Description("Return Battery Relative State-Of-Charge.")] void BatteryRelativeStateOfCharge([in] uint32 arg2, [out] uint32 argr); + [WmiMethodId(12), Implemented, read, write, Description("Return Battery Cycle Count")] void BatteryCycleCount([in] uint32 arg2, [out] uint32 argr); + [WmiMethodId(13), Implemented, read, write, Description("Return Battery ePPID")] void BatteryePPID([in] uint32 arg2, [out] string argr); + [WmiMethodId(14), Implemented, read, write, Description("Return Battery Raw Analytics Start")] void BatteryeRawAnalyticsStart([in] uint32 arg2, [out] uint32 argr); + [WmiMethodId(15), Implemented, read, write, Description("Return Battery Raw Analytics")] void BatteryeRawAnalytics([in] uint32 arg2, [out] uint32 RawSize, [out, WmiSizeIs("RawSize") : ToInstance] uint8 RawData[]); + [WmiMethodId(16), Implemented, read, write, Description("Return Battery Design Voltage.")] void BatteryDesignVoltage([in] uint32 arg2, [out] uint32 argr); + [WmiMethodId(17), Implemented, read, write, Description("Return Battery Raw Analytics A Block")] void BatteryeRawAnalyticsABlock([in] uint32 arg2, [out] uint32 RawSize, [out, WmiSizeIs("RawSize") : ToInstance] uint8 RawData[]); + [WmiMethodId(18), Implemented, read, write, Description("Return Version.")] void ReturnVersion([in] uint32 arg2, [out] uint32 argr); + [WmiMethodId(32), Implemented, read, write, Description("Return Fan Sensor Information")] void FanSensorInformation([in] uint32 arg2, [out] uint32 RawSize, [out, WmiSizeIs("RawSize") : ToInstance] uint8 RawData[]); + [WmiMethodId(34), Implemented, read, write, Description("Return Thermal Sensor Information")] void ThermalSensorInformation([in] uint32 arg2, [out] uint32 RawSize, [out, WmiSizeIs("RawSize") : ToInstance] uint8 RawData[]); + }; + +Each WMI method takes an ACPI buffer containing a 32-bit index as input argument, +with the first 8 bit being used to specify the battery when using battery-related +WMI methods. Other WMI methods may ignore this argument or interpret it +differently. The WMI method output format varies: + +* if the function has only a single output, then an ACPI object + of the corresponding type is returned +* if the function has multiple outputs, when an ACPI package + containing the outputs in the same order is returned + +The format of the output should be thoroughly checked, since many methods can +return malformed data in case of an error. + +The data format of many battery-related methods seems to be based on the +`Smart Battery Data Specification`, so unknown battery-related methods are +likely to follow this standard in some way. + +WMI method GetBatteryDesignCapacity() +------------------------------------- + +Returns the design capacity of the battery in mAh as an u16. + +WMI method BatteryFullCharge() +------------------------------ + +Returns the full charge capacity of the battery in mAh as an u16. + +WMI method BatteryManufactureName() +----------------------------------- + +Returns the manufacture name of the battery as an ASCII string. + +WMI method BatteryManufactureDate() +----------------------------------- + +Returns the manufacture date of the battery as an u16. +The date is encoded in the following manner: + +- bits 0 to 4 contain the manufacture day. +- bits 5 to 8 contain the manufacture month. +- bits 9 to 15 contain the manufacture year biased by 1980. + +.. note:: + The data format needs to be verified on more machines. + +WMI method BatterySerialNumber() +-------------------------------- + +Returns the serial number of the battery as an u16. + +WMI method BatteryChemistryValue() +---------------------------------- + +Returns the chemistry of the battery as an ASCII string. +Known values are: + +- "Li-I" for Li-Ion + +WMI method BatteryTemperature() +------------------------------- + +Returns the temperature of the battery in tenth degree kelvin as an u16. + +WMI method BatteryCurrent() +--------------------------- + +Returns the current flow of the battery in mA as an s16. +Negative values indicate discharging. + +WMI method BatteryVoltage() +--------------------------- + +Returns the voltage flow of the battery in mV as an u16. + +WMI method BatteryManufactureAccess() +------------------------------------- + +Returns a manufacture-defined value as an u16. + +WMI method BatteryRelativeStateOfCharge() +----------------------------------------- + +Returns the capacity of the battery in percent as an u16. + +WMI method BatteryCycleCount() +------------------------------ + +Returns the cycle count of the battery as an u16. + +WMI method BatteryePPID() +------------------------- + +Returns the ePPID of the battery as an ASCII string. + +WMI method BatteryeRawAnalyticsStart() +-------------------------------------- + +Performs an analysis of the battery and returns a status code: + +- ``0x0``: Success +- ``0x1``: Interface not supported +- ``0xfffffffe``: Error/Timeout + +.. note:: + The meaning of this method is still largely unknown. + +WMI method BatteryeRawAnalytics() +--------------------------------- + +Returns a buffer usually containg 12 blocks of analytics data. +Those blocks contain: + +- a block number starting with 0 (u8) +- 31 bytes of unknown data + +.. note:: + The meaning of this method is still largely unknown. + +WMI method BatteryDesignVoltage() +--------------------------------- + +Returns the design voltage of the battery in mV as an u16. + +WMI method BatteryeRawAnalyticsABlock() +--------------------------------------- + +Returns a single block of analytics data, with the second byte +of the index being used for selecting the block number. + +*Supported since WMI interface version 3!* + +.. note:: + The meaning of this method is still largely unknown. + +WMI method ReturnVersion() +-------------------------- + +Returns the WMI interface version as an u32. + +WMI method FanSensorInformation() +--------------------------------- + +Returns a buffer containg fan sensor entries, terminated +with a single ``0xff``. +Those entries contain: + +- fan type (u8) +- fan speed in RPM (little endian u16) + +WMI method ThermalSensorInformation() +------------------------------------- + +Returns a buffer containing thermal sensor entries, terminated +with a single ``0xff``. +Those entries contain: + +- thermal type (u8) +- current temperature (s8) +- min. temperature (s8) +- max. temperature (s8) +- unknown field (u8) + +.. note:: + TODO: Find out what the meaning of the last byte is. + +ACPI battery matching algorithm +=============================== + +The algorithm used to match ACPI batteries to indices is based on information +which was found inside the logging messages of the OEM software. + +Basically for each new ACPI battery, the serial numbers of the batteries behind +indices 1 till 3 are compared with the serial number of the ACPI battery. +Since the serial number of the ACPI battery can either be encoded as a normal +integer or as a hexadecimal value, both cases need to be checked. The first +index with a matching serial number is then selected. + +A serial number of 0 indicates that the corresponding index is not associated +with an actual battery, or that the associated battery is not present. + +Some machines like the Dell Inspiron 3505 only support a single battery and thus +ignore the battery index. Because of this the driver depends on the ACPI battery +hook mechanism to discover batteries. + +.. note:: + The ACPI battery matching algorithm currently used inside the driver is + outdated and does not match the algorithm described above. The reasons for + this are differences in the handling of the ToHexString() ACPI opcode between + Linux and Windows, which distorts the serial number of ACPI batteries on many + machines. Until this issue is resolved, the driver cannot use the above + algorithm. + +Reverse-Engineering the DDV WMI interface +========================================= + +1. Find a supported Dell notebook, usually made after ~2020. +2. Dump the ACPI tables and search for the WMI device (usually called "ADDV"). +3. Decode the corresponding bmof data and look at the ASL code. +4. Try to deduce the meaning of a certain WMI method by comparing the control + flow with other ACPI methods (_BIX or _BIF for battery related methods + for example). +5. Use the built-in UEFI diagostics to view sensor types/values for fan/thermal + related methods (sometimes overwriting static ACPI data fields can be used + to test different sensor type values, since on some machines this data is + not reinitialized upon a warm reset). + +Alternatively: + +1. Load the ``dell-wmi-ddv`` driver, use the ``force`` module param + if necessary. +2. Use the debugfs interface to access the raw fan/thermal sensor buffer data. +3. Compare the data with the built-in UEFI diagnostics. + +In case the DDV WMI interface version available on your Dell notebook is not +supported or you are seeing unknown fan/thermal sensors, please submit a +bugreport on `bugzilla `_ so they can be added +to the ``dell-wmi-ddv`` driver. + +See Documentation/admin-guide/reporting-issues.rst for further information. diff --git a/Documentation/wmi/devices/index.rst b/Documentation/wmi/devices/index.rst new file mode 100644 index 0000000000000000000000000000000000000000..c08735a9d7df36013046499d2326161e2645c6e9 --- /dev/null +++ b/Documentation/wmi/devices/index.rst @@ -0,0 +1,22 @@ +.. SPDX-License-Identifier: GPL-2.0-or-later + +============================= +Driver-specific Documentation +============================= + +This section provides information about various devices supported by +the Linux kernel, their protocols and driver details. + +.. toctree:: + :maxdepth: 1 + :numbered: + :glob: + + * + +.. only:: subproject and html + + Indices + ======= + + * :ref:`genindex` diff --git a/Documentation/wmi/devices/wmi-bmof.rst b/Documentation/wmi/devices/wmi-bmof.rst new file mode 100644 index 0000000000000000000000000000000000000000..ca1ee9a29be3bad31ad7816b25c09932b96b6ab9 --- /dev/null +++ b/Documentation/wmi/devices/wmi-bmof.rst @@ -0,0 +1,25 @@ +.. SPDX-License-Identifier: GPL-2.0-only + +============================== +WMI embedded Binary MOF driver +============================== + +Introduction +============ + +Many machines embed WMI Binary MOF (Managed Object Format) metadata used to +describe the details of their ACPI WMI interfaces. The data can be decoded +with tools like `bmfdec `_ to obtain a +human readable WMI interface description, which is useful for developing +new WMI drivers. + +The Binary MOF data can be retrieved from the ``bmof`` sysfs attribute of the +associated WMI device. Please note that multiple WMI devices containing Binary +MOF data can exist on a given system. + +WMI interface +============= + +The Binary MOF WMI device is identified by the WMI GUID ``05901221-D566-11D1-B2F0-00A0C9062910``. +The Binary MOF can be obtained by doing a WMI data block query. The result is +then returned as an ACPI buffer with a variable size. diff --git a/Documentation/wmi/index.rst b/Documentation/wmi/index.rst new file mode 100644 index 0000000000000000000000000000000000000000..537cff188e14ceda7380559ebe478a6c00c88e68 --- /dev/null +++ b/Documentation/wmi/index.rst @@ -0,0 +1,19 @@ +.. SPDX-License-Identifier: GPL-2.0-or-later + +============= +WMI Subsystem +============= + +.. toctree:: + :maxdepth: 1 + + acpi-interface + devices/index + +.. only:: subproject and html + + + Indices + ======= + + * :ref:`genindex` diff --git a/MAINTAINERS b/MAINTAINERS index 0b8fa84dfcefbfb58440070330635388bd75f8bf..cd882b87a3c607b522c54742f9e1b6bcccdc21e6 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1,81 +1,5 @@ -List of maintainers and how to submit kernel changes -==================================================== - -Please try to follow the guidelines below. This will make things -easier on the maintainers. Not all of these guidelines matter for every -trivial patch so apply some common sense. - -Tips for patch submitters -------------------------- - -1. Always *test* your changes, however small, on at least 4 or - 5 people, preferably many more. - -2. Try to release a few ALPHA test versions to the net. Announce - them onto the kernel channel and await results. This is especially - important for device drivers, because often that's the only way - you will find things like the fact version 3 firmware needs - a magic fix you didn't know about, or some clown changed the - chips on a board and not its name. (Don't laugh! Look at the - SMC etherpower for that.) - -3. Make sure your changes compile correctly in multiple - configurations. In particular check that changes work both as a - module and built into the kernel. - -4. When you are happy with a change make it generally available for - testing and await feedback. - -5. Make a patch available to the relevant maintainer in the list. Use - ``diff -u`` to make the patch easy to merge. Be prepared to get your - changes sent back with seemingly silly requests about formatting - and variable names. These aren't as silly as they seem. One - job the maintainers (and especially Linus) do is to keep things - looking the same. Sometimes this means that the clever hack in - your driver to get around a problem actually needs to become a - generalized kernel feature ready for next time. - - PLEASE check your patch with the automated style checker - (scripts/checkpatch.pl) to catch trivial style violations. - See Documentation/process/coding-style.rst for guidance here. - - PLEASE CC: the maintainers and mailing lists that are generated - by ``scripts/get_maintainer.pl.`` The results returned by the - script will be best if you have git installed and are making - your changes in a branch derived from Linus' latest git tree. - See Documentation/process/submitting-patches.rst for details. - - PLEASE try to include any credit lines you want added with the - patch. It avoids people being missed off by mistake and makes - it easier to know who wants adding and who doesn't. - - PLEASE document known bugs. If it doesn't work for everything - or does something very odd once a month document it. - - PLEASE remember that submissions must be made under the terms - of the Linux Foundation certificate of contribution and should - include a Signed-off-by: line. The current version of this - "Developer's Certificate of Origin" (DCO) is listed in the file - Documentation/process/submitting-patches.rst. - -6. Make sure you have the right to send any changes you make. If you - do changes at work you may find your employer owns the patch - not you. - -7. When sending security related changes or reports to a maintainer - please Cc: security@kernel.org, especially if the maintainer - does not respond. Please keep in mind that the security team is - a small set of people who can be efficient only when working on - verified bugs. Please only Cc: this list when you have identified - that the bug would present a short-term risk to other users if it - were publicly disclosed. For example, reports of address leaks do - not represent an immediate threat and are better handled publicly, - and ideally, should come with a patch proposal. Please do not send - automated reports to this list either. Such bugs will be handled - better and faster in the usual public places. See - Documentation/process/security-bugs.rst for details. - -8. Happy hacking. +List of maintainers +=================== Descriptions of section entries and preferred order --------------------------------------------------- @@ -406,6 +330,13 @@ L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained F: drivers/acpi/arm64 +ACPI FOR RISC-V (ACPI/riscv) +M: Sunil V L +L: linux-acpi@vger.kernel.org +L: linux-riscv@lists.infradead.org +S: Maintained +F: drivers/acpi/riscv/ + ACPI PCC(Platform Communication Channel) MAILBOX DRIVER M: Sudeep Holla L: linux-acpi@vger.kernel.org @@ -449,6 +380,8 @@ F: include/linux/acpi_viot.h ACPI WMI DRIVER L: platform-driver-x86@vger.kernel.org S: Orphan +F: Documentation/driver-api/wmi.rst +F: Documentation/wmi/ F: drivers/platform/x86/wmi.c F: include/uapi/linux/wmi.h @@ -909,13 +842,6 @@ L: netdev@vger.kernel.org S: Maintained F: drivers/net/ethernet/altera/ -ALTERA TSE PCS -M: Maxime Chevallier -L: netdev@vger.kernel.org -S: Supported -F: drivers/net/pcs/pcs-altera-tse.c -F: include/linux/pcs-altera-tse.h - ALTERA UART/JTAG UART SERIAL DRIVERS M: Tobias Klauser L: linux-serial@vger.kernel.org @@ -1634,6 +1560,7 @@ L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained C: irc://irc.libera.chat/armlinux T: git git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc.git +F: Documentation/process/maintainer-soc.rst F: arch/arm/boot/dts/Makefile F: arch/arm64/boot/dts/Makefile @@ -1665,9 +1592,9 @@ F: Documentation/devicetree/bindings/clock/arm,syscon-icst.yaml F: Documentation/devicetree/bindings/i2c/arm,i2c-versatile.yaml F: Documentation/devicetree/bindings/interrupt-controller/arm,versatile-fpga-irq.txt F: Documentation/devicetree/bindings/mtd/mtd-physmap.yaml -F: arch/arm/boot/dts/arm-realview-* -F: arch/arm/boot/dts/integrator* -F: arch/arm/boot/dts/versatile* +F: arch/arm/boot/dts/arm/arm-realview-* +F: arch/arm/boot/dts/arm/integrator* +F: arch/arm/boot/dts/arm/versatile* F: arch/arm/mach-versatile/ F: drivers/bus/arm-integrator-lm.c F: drivers/clk/versatile/ @@ -1838,7 +1765,7 @@ F: Documentation/devicetree/bindings/net/actions,owl-emac.yaml F: Documentation/devicetree/bindings/pinctrl/actions,* F: Documentation/devicetree/bindings/power/actions,owl-sps.txt F: Documentation/devicetree/bindings/timer/actions,owl-timer.txt -F: arch/arm/boot/dts/owl-* +F: arch/arm/boot/dts/actions/ F: arch/arm/mach-actions/ F: arch/arm64/boot/dts/actions/ F: drivers/clk/actions/ @@ -1884,6 +1811,7 @@ L: linux-amlogic@lists.infradead.org S: Maintained F: Documentation/devicetree/bindings/clock/amlogic* F: drivers/clk/meson/ +F: include/dt-bindings/clock/amlogic,a1* F: include/dt-bindings/clock/gxbb* F: include/dt-bindings/clock/meson* @@ -1911,10 +1839,12 @@ L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) L: linux-amlogic@lists.infradead.org S: Maintained W: http://linux-meson.com/ -F: arch/arm/boot/dts/meson* +F: Documentation/devicetree/bindings/phy/amlogic* +F: arch/arm/boot/dts/amlogic/ F: arch/arm/mach-meson/ F: arch/arm64/boot/dts/amlogic/ F: drivers/mmc/host/meson* +F: drivers/phy/amlogic/ F: drivers/pinctrl/meson/ F: drivers/rtc/rtc-meson* F: drivers/soc/amlogic/ @@ -1925,7 +1855,7 @@ M: Tsahee Zidenberg M: Antoine Tenart L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained -F: arch/arm/boot/dts/alpine* +F: arch/arm/boot/dts/amazon/ F: arch/arm/mach-alpine/ F: arch/arm64/boot/dts/amazon/ F: drivers/*/*alpine* @@ -1996,7 +1926,7 @@ M: Lars Persson L: linux-arm-kernel@axis.com S: Maintained F: Documentation/devicetree/bindings/pinctrl/axis,artpec6-pinctrl.txt -F: arch/arm/boot/dts/artpec6* +F: arch/arm/boot/dts/axis/ F: arch/arm/mach-artpec F: drivers/clk/axis F: drivers/crypto/axis @@ -2024,7 +1954,7 @@ S: Supported Q: https://patchwork.ozlabs.org/project/linux-aspeed/list/ T: git git://git.kernel.org/pub/scm/linux/kernel/git/joel/aspeed.git F: Documentation/devicetree/bindings/arm/aspeed/ -F: arch/arm/boot/dts/aspeed-* +F: arch/arm/boot/dts/aspeed/ F: arch/arm/mach-aspeed/ N: aspeed @@ -2043,8 +1973,7 @@ ARM/CALXEDA HIGHBANK ARCHITECTURE M: Andre Przywara L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained -F: arch/arm/boot/dts/ecx-*.dts* -F: arch/arm/boot/dts/highbank.dts +F: arch/arm/boot/dts/calxeda/ F: arch/arm/mach-highbank/ ARM/CAVIUM THUNDER NETWORK DRIVER @@ -2092,12 +2021,13 @@ ARM/CONEXANT DIGICOLOR MACHINE SUPPORT M: Baruch Siach L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained -F: arch/arm/boot/dts/cx92755* +F: arch/arm/boot/dts/cnxt/ N: digicolor ARM/CORESIGHT FRAMEWORK AND DRIVERS M: Suzuki K Poulose R: Mike Leach +R: James Clark R: Leo Yan L: coresight@lists.linaro.org (moderated for non-subscribers) L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) @@ -2131,7 +2061,7 @@ F: Documentation/devicetree/bindings/arm/gemini.yaml F: Documentation/devicetree/bindings/net/cortina,gemini-ethernet.yaml F: Documentation/devicetree/bindings/pinctrl/cortina,gemini-pinctrl.txt F: Documentation/devicetree/bindings/rtc/faraday,ftrtc010.yaml -F: arch/arm/boot/dts/gemini* +F: arch/arm/boot/dts/gemini/ F: arch/arm/mach-gemini/ F: drivers/crypto/gemini/ F: drivers/net/ethernet/cortina/ @@ -2184,7 +2114,8 @@ R: NXP Linux Team L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained T: git git://git.kernel.org/pub/scm/linux/kernel/git/shawnguo/linux.git -F: arch/arm64/boot/dts/freescale/ +F: arch/arm/boot/dts/nxp/imx/ +F: arch/arm/boot/dts/nxp/mxs/ X: arch/arm64/boot/dts/freescale/fsl-* X: arch/arm64/boot/dts/freescale/qoriq-* X: drivers/media/i2c/ @@ -2197,7 +2128,7 @@ M: Li Yang L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained T: git git://git.kernel.org/pub/scm/linux/kernel/git/shawnguo/linux.git -F: arch/arm/boot/dts/ls1021a* +F: arch/arm/boot/dts/nxp/ls/ F: arch/arm64/boot/dts/freescale/fsl-* F: arch/arm64/boot/dts/freescale/qoriq-* @@ -2209,7 +2140,7 @@ R: Stefan Agner L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained T: git git://git.kernel.org/pub/scm/linux/kernel/git/shawnguo/linux.git -F: arch/arm/boot/dts/vf* +F: arch/arm/boot/dts/nxp/vf/ F: arch/arm/mach-imx/*vf610* ARM/GUMSTIX MACHINE SUPPORT @@ -2223,9 +2154,7 @@ L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Supported W: http://www.hisilicon.com T: git https://github.com/hisilicon/linux-hisi.git -F: arch/arm/boot/dts/hi3* -F: arch/arm/boot/dts/hip* -F: arch/arm/boot/dts/hisi* +F: arch/arm/boot/dts/hisilicon/ F: arch/arm/mach-hisi/ F: arch/arm64/boot/dts/hisilicon/ @@ -2247,8 +2176,7 @@ F: Documentation/devicetree/bindings/i2c/hpe,gxp-i2c.yaml F: Documentation/devicetree/bindings/spi/hpe,gxp-spifi.yaml F: Documentation/devicetree/bindings/timer/hpe,gxp-timer.yaml F: Documentation/hwmon/gxp-fan-ctrl.rst -F: arch/arm/boot/dts/hpe-bmc* -F: arch/arm/boot/dts/hpe-gxp* +F: arch/arm/boot/dts/hpe/ F: arch/arm/mach-hpe/ F: drivers/clocksource/timer-gxp.c F: drivers/hwmon/gxp-fan-ctrl.c @@ -2262,7 +2190,7 @@ M: Javier Martinez Canillas L: linux-omap@vger.kernel.org L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained -F: arch/arm/boot/dts/omap3-igep* +F: arch/arm/boot/dts/ti/omap/omap3-igep* ARM/INTEL IXP4XX ARM ARCHITECTURE M: Linus Walleij @@ -2275,7 +2203,7 @@ F: Documentation/devicetree/bindings/gpio/intel,ixp4xx-gpio.txt F: Documentation/devicetree/bindings/interrupt-controller/intel,ixp4xx-interrupt.yaml F: Documentation/devicetree/bindings/memory-controllers/intel,ixp4xx-expansion* F: Documentation/devicetree/bindings/timer/intel,ixp4xx-timer.yaml -F: arch/arm/boot/dts/intel-ixp* +F: arch/arm/boot/dts/intel/ixp/ F: arch/arm/mach-ixp4xx/ F: drivers/bus/intel-ixp4xx-eb.c F: drivers/clocksource/timer-ixp4xx.c @@ -2307,7 +2235,7 @@ M: Vladimir Zapolskiy L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained F: Documentation/devicetree/bindings/i2c/i2c-lpc2k.txt -F: arch/arm/boot/dts/lpc43* +F: arch/arm/boot/dts/nxp/lpc/lpc43* F: drivers/i2c/busses/i2c-lpc2k.c F: drivers/memory/pl172.c F: drivers/mtd/spi-nor/controllers/nxp-spifi.c @@ -2320,7 +2248,7 @@ L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained T: git git://github.com/vzapolskiy/linux-lpc32xx.git F: Documentation/devicetree/bindings/i2c/i2c-pnx.txt -F: arch/arm/boot/dts/lpc32* +F: arch/arm/boot/dts/nxp/lpc/lpc32* F: arch/arm/mach-lpc32xx/ F: drivers/i2c/busses/i2c-pnx.c F: drivers/net/ethernet/nxp/lpc_eth.c @@ -2338,8 +2266,8 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/gclement/mvebu.git F: Documentation/devicetree/bindings/arm/marvell/marvell,dove.txt F: Documentation/devicetree/bindings/arm/marvell/marvell,orion5x.txt F: Documentation/devicetree/bindings/soc/dove/ -F: arch/arm/boot/dts/dove* -F: arch/arm/boot/dts/orion5x* +F: arch/arm/boot/dts/marvell/dove* +F: arch/arm/boot/dts/marvell/orion5x* F: arch/arm/mach-dove/ F: arch/arm/mach-mv78xx0/ F: arch/arm/mach-orion5x/ @@ -2354,12 +2282,13 @@ L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained T: git git://git.kernel.org/pub/scm/linux/kernel/git/gclement/mvebu.git F: Documentation/devicetree/bindings/arm/marvell/ -F: arch/arm/boot/dts/armada* -F: arch/arm/boot/dts/kirkwood* +F: arch/arm/boot/dts/marvell/armada* +F: arch/arm/boot/dts/marvell/kirkwood* F: arch/arm/configs/mvebu_*_defconfig F: arch/arm/mach-mvebu/ F: arch/arm64/boot/dts/marvell/armada* F: arch/arm64/boot/dts/marvell/cn913* +F: drivers/clk/mvebu/ F: drivers/cpufreq/armada-37xx-cpufreq.c F: drivers/cpufreq/armada-8k-cpufreq.c F: drivers/cpufreq/mvebu-cpufreq.c @@ -2389,10 +2318,7 @@ L: linux-mediatek@lists.infradead.org (moderated for non-subscribers) S: Maintained W: https://mtk.wiki.kernel.org/ C: irc://irc.libera.chat/linux-mediatek -F: arch/arm/boot/dts/mt2* -F: arch/arm/boot/dts/mt6* -F: arch/arm/boot/dts/mt7* -F: arch/arm/boot/dts/mt8* +F: arch/arm/boot/dts/mediatek/ F: arch/arm/mach-mediatek/ F: arch/arm64/boot/dts/mediatek/ F: drivers/soc/mediatek/ @@ -2408,6 +2334,15 @@ S: Maintained F: Documentation/devicetree/bindings/phy/mediatek,* F: drivers/phy/mediatek/ +ARM/MICROCHIP (ARM64) SoC support +M: Conor Dooley +M: Nicolas Ferre +M: Claudiu Beznea +L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) +S: Supported +T: git https://git.kernel.org/pub/scm/linux/kernel/git/at91/linux.git +F: arch/arm64/boot/dts/microchip/ + ARM/Microchip (AT91) SoC support M: Nicolas Ferre M: Alexandre Belloni @@ -2416,10 +2351,8 @@ L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Supported W: http://www.linux4sam.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/at91/linux.git -F: arch/arm/boot/dts/at91*.dts -F: arch/arm/boot/dts/at91*.dtsi -F: arch/arm/boot/dts/sama*.dts -F: arch/arm/boot/dts/sama*.dtsi +F: arch/arm/boot/dts/microchip/at91* +F: arch/arm/boot/dts/microchip/sama* F: arch/arm/include/debug/at91.S F: arch/arm/mach-at91/ F: drivers/memory/atmel* @@ -2430,15 +2363,6 @@ X: drivers/net/wireless/atmel/ N: at91 N: atmel -ARM/MICROCHIP (ARM64) SoC support -M: Conor Dooley -M: Nicolas Ferre -M: Claudiu Beznea -L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) -S: Supported -T: git https://git.kernel.org/pub/scm/linux/kernel/git/at91/linux.git -F: arch/arm64/boot/dts/microchip/ - ARM/Microchip Sparx5 SoC support M: Lars Povlsen M: Steen Hegelund @@ -2456,7 +2380,7 @@ M: Taichi Sugaya M: Takao Orito L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained -F: arch/arm/boot/dts/milbeaut* +F: arch/arm/boot/dts/socionext/milbeaut* F: arch/arm/mach-milbeaut/ N: milbeaut @@ -2470,7 +2394,7 @@ T: git git://github.com/linux-chenxing/linux.git F: Documentation/devicetree/bindings/arm/mstar/* F: Documentation/devicetree/bindings/clock/mstar,msc313-mpll.yaml F: Documentation/devicetree/bindings/gpio/mstar,msc313-gpio.yaml -F: arch/arm/boot/dts/mstar-* +F: arch/arm/boot/dts/sigmastar/ F: arch/arm/mach-mstar/ F: drivers/clk/mstar/ F: drivers/clocksource/timer-msc313e.c @@ -2489,7 +2413,7 @@ F: Documentation/devicetree/bindings/arm/ste-* F: Documentation/devicetree/bindings/arm/ux500.yaml F: Documentation/devicetree/bindings/arm/ux500/ F: Documentation/devicetree/bindings/i2c/st,nomadik-i2c.yaml -F: arch/arm/boot/dts/ste-* +F: arch/arm/boot/dts/st/ste-* F: arch/arm/mach-nomadik/ F: arch/arm/mach-ux500/ F: drivers/clk/clk-nomadik.c @@ -2506,6 +2430,18 @@ F: drivers/rtc/rtc-ab8500.c F: drivers/rtc/rtc-pl031.c F: drivers/soc/ux500/ +ARM/NUVOTON MA35 ARCHITECTURE +M: Jacky Huang +M: Shan-Chun Hung +L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) +S: Supported +F: Documentation/devicetree/bindings/*/*/*ma35* +F: Documentation/devicetree/bindings/*/*ma35* +F: arch/arm64/boot/dts/nuvoton/*ma35* +F: drivers/*/*/*ma35* +F: drivers/*/*ma35* +K: ma35d1 + ARM/NUVOTON NPCM ARCHITECTURE M: Avi Fishman M: Tomer Maimon @@ -2517,9 +2453,8 @@ L: openbmc@lists.ozlabs.org (moderated for non-subscribers) S: Supported F: Documentation/devicetree/bindings/*/*/*npcm* F: Documentation/devicetree/bindings/*/*npcm* -F: Documentation/devicetree/bindings/arm/npcm/* F: Documentation/devicetree/bindings/rtc/nuvoton,nct3018y.yaml -F: arch/arm/boot/dts/nuvoton-npcm* +F: arch/arm/boot/dts/nuvoton/nuvoton-npcm* F: arch/arm/mach-npcm/ F: arch/arm64/boot/dts/nuvoton/ F: drivers/*/*/*npcm* @@ -2534,7 +2469,7 @@ L: openbmc@lists.ozlabs.org (moderated for non-subscribers) S: Maintained W: https://github.com/neuschaefer/wpcm450/wiki F: Documentation/devicetree/bindings/*/*wpcm* -F: arch/arm/boot/dts/nuvoton-wpcm450* +F: arch/arm/boot/dts/nuvoton/nuvoton-wpcm450* F: arch/arm/configs/wpcm450_defconfig F: arch/arm/mach-npcm/wpcm450.c F: drivers/*/*/*wpcm* @@ -2575,20 +2510,19 @@ F: arch/arm64/boot/dts/qcom/sdm845-cheza* ARM/QUALCOMM SUPPORT M: Andy Gross M: Bjorn Andersson -R: Konrad Dybcio +M: Konrad Dybcio L: linux-arm-msm@vger.kernel.org S: Maintained T: git git://git.kernel.org/pub/scm/linux/kernel/git/qcom/linux.git F: Documentation/devicetree/bindings/*/qcom* F: Documentation/devicetree/bindings/soc/qcom/ -F: arch/arm/boot/dts/qcom-*.dts -F: arch/arm/boot/dts/qcom-*.dtsi +F: arch/arm/boot/dts/qcom/ F: arch/arm/configs/qcom_defconfig F: arch/arm/mach-qcom/ F: arch/arm64/boot/dts/qcom/ +F: drivers/*/*/pm8???-* F: drivers/*/*/qcom* F: drivers/*/*/qcom/ -F: drivers/*/pm8???-* F: drivers/*/qcom* F: drivers/*/qcom/ F: drivers/bluetooth/btqcomsmd.c @@ -2625,7 +2559,7 @@ F: Documentation/devicetree/bindings/gpio/gpio-rda.yaml F: Documentation/devicetree/bindings/interrupt-controller/rda,8810pl-intc.yaml F: Documentation/devicetree/bindings/serial/rda,8810pl-uart.yaml F: Documentation/devicetree/bindings/timer/rda,8810pl-timer.yaml -F: arch/arm/boot/dts/rda8810pl-* +F: arch/arm/boot/dts/unisoc/ F: drivers/clocksource/timer-rda.c F: drivers/gpio/gpio-rda.c F: drivers/irqchip/irq-rda-intc.c @@ -2637,7 +2571,7 @@ L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) L: linux-realtek-soc@lists.infradead.org (moderated for non-subscribers) S: Maintained F: Documentation/devicetree/bindings/arm/realtek.yaml -F: arch/arm/boot/dts/rtd* +F: arch/arm/boot/dts/realtek/ F: arch/arm/mach-realtek/ F: arch/arm64/boot/dts/realtek/ @@ -2651,13 +2585,7 @@ C: irc://irc.libera.chat/renesas-soc T: git git://git.kernel.org/pub/scm/linux/kernel/git/geert/renesas-devel.git next F: Documentation/devicetree/bindings/hwinfo/renesas,prr.yaml F: Documentation/devicetree/bindings/soc/renesas/ -F: arch/arm/boot/dts/emev2* -F: arch/arm/boot/dts/gr-peach* -F: arch/arm/boot/dts/iwg20d-q7* -F: arch/arm/boot/dts/r7s* -F: arch/arm/boot/dts/r8a* -F: arch/arm/boot/dts/r9a* -F: arch/arm/boot/dts/sh* +F: arch/arm/boot/dts/renesas/ F: arch/arm/configs/shmobile_defconfig F: arch/arm/include/debug/renesas-scif.S F: arch/arm/mach-shmobile/ @@ -2690,8 +2618,7 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/mmind/linux-rockchip.git F: Documentation/devicetree/bindings/i2c/i2c-rk3x.yaml F: Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.yaml F: Documentation/devicetree/bindings/spi/spi-rockchip.yaml -F: arch/arm/boot/dts/rk3* -F: arch/arm/boot/dts/rv11* +F: arch/arm/boot/dts/rockchip/ F: arch/arm/mach-rockchip/ F: drivers/*/*/*rockchip* F: drivers/*/*rockchip* @@ -2710,14 +2637,12 @@ Q: https://patchwork.kernel.org/project/linux-samsung-soc/list/ B: mailto:linux-samsung-soc@vger.kernel.org C: irc://irc.libera.chat/linux-exynos T: git git://git.kernel.org/pub/scm/linux/kernel/git/krzk/linux.git -F: Documentation/arm/samsung/ +F: Documentation/arch/arm/samsung/ F: Documentation/devicetree/bindings/arm/samsung/ F: Documentation/devicetree/bindings/hwinfo/samsung,* F: Documentation/devicetree/bindings/power/pd-samsung.yaml F: Documentation/devicetree/bindings/soc/samsung/ -F: arch/arm/boot/dts/exynos* -F: arch/arm/boot/dts/s3c* -F: arch/arm/boot/dts/s5p* +F: arch/arm/boot/dts/samsung/ F: arch/arm/mach-exynos*/ F: arch/arm/mach-s3c/ F: arch/arm/mach-s5p*/ @@ -2777,7 +2702,7 @@ M: Dinh Nguyen S: Maintained W: http://www.rocketboards.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/dinguyen/linux.git -F: arch/arm/boot/dts/socfpga* +F: arch/arm/boot/dts/intel/socfpga/ F: arch/arm/configs/socfpga_defconfig F: arch/arm/mach-socfpga/ F: arch/arm64/boot/dts/altera/ @@ -2810,7 +2735,7 @@ S: Maintained W: http://www.stlinux.com F: Documentation/devicetree/bindings/i2c/st,sti-i2c.yaml F: Documentation/devicetree/bindings/spi/st,ssc-spi.yaml -F: arch/arm/boot/dts/sti* +F: arch/arm/boot/dts/st/sti* F: arch/arm/mach-sti/ F: drivers/ata/ahci_st.c F: drivers/char/hw_random/st-rng.c @@ -2843,8 +2768,9 @@ L: linux-stm32@st-md-mailman.stormreply.com (moderated for non-subscribers) L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained T: git git://git.kernel.org/pub/scm/linux/kernel/git/atorgue/stm32.git stm32-next -F: arch/arm/boot/dts/stm32* +F: arch/arm/boot/dts/st/stm32* F: arch/arm/mach-stm32/ +F: arch/arm64/boot/dts/st/ F: drivers/clocksource/armv7m_systick.c N: stm32 N: stm @@ -2858,7 +2784,7 @@ F: Documentation/devicetree/bindings/arm/sunplus,sp7021.yaml F: Documentation/devicetree/bindings/clock/sunplus,sp7021-clkc.yaml F: Documentation/devicetree/bindings/interrupt-controller/sunplus,sp7021-intc.yaml F: Documentation/devicetree/bindings/reset/sunplus,reset.yaml -F: arch/arm/boot/dts/sunplus-sp7021*.dts* +F: arch/arm/boot/dts/sunplus/ F: arch/arm/configs/sp7021_*defconfig F: arch/arm/mach-sunplus/ F: drivers/clk/clk-sp7021.c @@ -2872,7 +2798,7 @@ M: Jisheng Zhang M: Sebastian Hesselbarth L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained -F: arch/arm/boot/dts/berlin* +F: arch/arm/boot/dts/synaptics/ F: arch/arm/mach-berlin/ F: arch/arm64/boot/dts/synaptics/ @@ -2914,7 +2840,7 @@ M: Santosh Shilimkar L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained T: git git://git.kernel.org/pub/scm/linux/kernel/git/ti/linux.git -F: arch/arm/boot/dts/keystone-* +F: arch/arm/boot/dts/ti/keystone/ F: arch/arm/mach-keystone/ ARM/TEXAS INSTRUMENT KEYSTONE CLOCK FRAMEWORK @@ -2946,7 +2872,6 @@ F: Documentation/devicetree/bindings/arm/ti/k3.yaml F: Documentation/devicetree/bindings/hwinfo/ti,k3-socinfo.yaml F: arch/arm64/boot/dts/ti/Makefile F: arch/arm64/boot/dts/ti/k3-* -F: include/dt-bindings/pinctrl/k3.h ARM/TOSHIBA VISCONTI ARCHITECTURE M: Nobuhiro Iwamatsu @@ -2979,7 +2904,7 @@ F: Documentation/devicetree/bindings/arm/socionext/uniphier.yaml F: Documentation/devicetree/bindings/gpio/socionext,uniphier-gpio.yaml F: Documentation/devicetree/bindings/pinctrl/socionext,uniphier-pinctrl.yaml F: Documentation/devicetree/bindings/soc/socionext/socionext,uniphier*.yaml -F: arch/arm/boot/dts/uniphier* +F: arch/arm/boot/dts/socionext/uniphier* F: arch/arm/include/asm/hardware/cache-uniphier.h F: arch/arm/mach-uniphier/ F: arch/arm/mm/cache-uniphier.c @@ -3004,7 +2929,7 @@ L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained F: */*/*/vexpress* F: */*/vexpress* -F: arch/arm/boot/dts/vexpress* +F: arch/arm/boot/dts/arm/vexpress* F: arch/arm/mach-versatile/ F: arch/arm64/boot/dts/arm/ F: drivers/clk/versatile/clk-vexpress-osc.c @@ -3062,7 +2987,7 @@ M: Will Deacon L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained T: git git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git -F: Documentation/arm64/ +F: Documentation/arch/arm64/ F: arch/arm64/ F: tools/testing/selftests/arm64/ X: arch/arm64/boot/dts/ @@ -3384,6 +3309,16 @@ F: include/uapi/linux/audit.h F: kernel/audit* F: lib/*audit.c +AUXILIARY BUS DRIVER +M: Greg Kroah-Hartman +R: Dave Ertman +R: Ira Weiny +S: Supported +T: git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core.git +F: Documentation/driver-api/auxiliary_bus.rst +F: drivers/base/auxiliary.c +F: include/linux/auxiliary_bus.h + AUXILIARY DISPLAY DRIVERS M: Miguel Ojeda S: Maintained @@ -3411,10 +3346,10 @@ AXENTIA ARM DEVICES M: Peter Rosin L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained -F: arch/arm/boot/dts/at91-linea.dtsi -F: arch/arm/boot/dts/at91-natte.dtsi -F: arch/arm/boot/dts/at91-nattis-2-natte-2.dts -F: arch/arm/boot/dts/at91-tse850-3.dts +F: arch/arm/boot/dts/microchip/at91-linea.dtsi +F: arch/arm/boot/dts/microchip/at91-natte.dtsi +F: arch/arm/boot/dts/microchip/at91-nattis-2-natte-2.dts +F: arch/arm/boot/dts/microchip/at91-tse850-3.dts AXENTIA ASOC DRIVERS M: Peter Rosin @@ -3564,18 +3499,24 @@ M: Yury Norov R: Andy Shevchenko R: Rasmus Villemoes S: Maintained +F: include/linux/bitfield.h F: include/linux/bitmap.h +F: include/linux/bits.h F: include/linux/cpumask.h F: include/linux/find.h F: include/linux/nodemask.h +F: include/vdso/bits.h F: lib/bitmap.c F: lib/cpumask.c F: lib/cpumask_kunit.c F: lib/find_bit.c F: lib/find_bit_benchmark.c F: lib/test_bitmap.c +F: tools/include/linux/bitfield.h F: tools/include/linux/bitmap.h +F: tools/include/linux/bits.h F: tools/include/linux/find.h +F: tools/include/vdso/bits.h F: tools/lib/bitmap.c F: tools/lib/find_bit.c @@ -3613,6 +3554,7 @@ S: Supported W: http://www.bluez.org/ T: git git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth.git T: git git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next.git +F: Documentation/devicetree/bindings/net/bluetooth/ F: drivers/bluetooth/ BLUETOOTH SUBSYSTEM @@ -3900,7 +3842,7 @@ S: Supported F: drivers/net/ethernet/broadcom/b44.* BROADCOM B53/SF2 ETHERNET SWITCH DRIVER -M: Florian Fainelli +M: Florian Fainelli L: netdev@vger.kernel.org L: openwrt-devel@lists.openwrt.org (subscribers-only) S: Supported @@ -3911,7 +3853,7 @@ F: include/linux/dsa/brcm.h F: include/linux/platform_data/b53.h BROADCOM BCM2711/BCM2835 ARM ARCHITECTURE -M: Florian Fainelli +M: Florian Fainelli R: Broadcom internal kernel review list L: linux-rpi-kernel@lists.infradead.org (moderated for non-subscribers) L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) @@ -3925,7 +3867,7 @@ N: bcm283* N: raspberrypi BROADCOM BCM281XX/BCM11XXX/BCM216XX ARM ARCHITECTURE -M: Florian Fainelli +M: Florian Fainelli M: Ray Jui M: Scott Branden R: Broadcom internal kernel review list @@ -3964,25 +3906,26 @@ F: Documentation/devicetree/bindings/pinctrl/brcm,bcm4908-pinctrl.yaml F: drivers/pinctrl/bcm/pinctrl-bcm4908.c BROADCOM BCM5301X ARM ARCHITECTURE -M: Florian Fainelli +M: Florian Fainelli M: Hauke Mehrtens M: Rafał Miłecki R: Broadcom internal kernel review list L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained -F: arch/arm/boot/dts/bcm470* -F: arch/arm/boot/dts/bcm5301* -F: arch/arm/boot/dts/bcm953012* +F: arch/arm/boot/dts/broadcom/bcm-ns.dtsi +F: arch/arm/boot/dts/broadcom/bcm470* +F: arch/arm/boot/dts/broadcom/bcm5301* +F: arch/arm/boot/dts/broadcom/bcm953012* F: arch/arm/mach-bcm/bcm_5301x.c BROADCOM BCM53573 ARM ARCHITECTURE -M: Florian Fainelli +M: Florian Fainelli M: Rafał Miłecki R: Broadcom internal kernel review list L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained -F: arch/arm/boot/dts/bcm47189* -F: arch/arm/boot/dts/bcm53573* +F: arch/arm/boot/dts/broadcom/bcm47189* +F: arch/arm/boot/dts/broadcom/bcm53573* BROADCOM BCM63XX/BCM33XX UDC DRIVER M: Kevin Cernekee @@ -3991,13 +3934,13 @@ S: Maintained F: drivers/usb/gadget/udc/bcm63xx_udc.* BROADCOM BCM7XXX ARM ARCHITECTURE -M: Florian Fainelli +M: Florian Fainelli R: Broadcom internal kernel review list L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained T: git https://github.com/broadcom/stblinux.git F: Documentation/devicetree/bindings/pci/brcm,stb-pcie.yaml -F: arch/arm/boot/dts/bcm7*.dts* +F: arch/arm/boot/dts/broadcom/bcm7*.dts* F: arch/arm/include/asm/hardware/cache-b15-rac.h F: arch/arm/mach-bcm/*brcmstb* F: arch/arm/mm/cache-b15-rac.c @@ -4011,7 +3954,7 @@ BROADCOM BCMBCA ARM ARCHITECTURE M: William Zhang M: Anand Gore M: Kursad Oney -M: Florian Fainelli +M: Florian Fainelli M: Rafał Miłecki R: Broadcom internal kernel review list L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) @@ -4036,7 +3979,7 @@ N: bcm[9]?6858 N: bcm[9]?6878 BROADCOM BDC DRIVER -M: Justin Chen +M: Justin Chen M: Al Cooper R: Broadcom internal kernel review list L: linux-usb@vger.kernel.org @@ -4052,7 +3995,7 @@ S: Maintained F: drivers/cpufreq/bmips-cpufreq.c BROADCOM BMIPS MIPS ARCHITECTURE -M: Florian Fainelli +M: Florian Fainelli R: Broadcom internal kernel review list L: linux-mips@vger.kernel.org S: Maintained @@ -4120,14 +4063,14 @@ F: drivers/net/wireless/broadcom/brcm80211/ BROADCOM BRCMSTB GPIO DRIVER M: Doug Berger -M: Florian Fainelli +M: Florian Fainelli R: Broadcom internal kernel review list S: Supported F: Documentation/devicetree/bindings/gpio/brcm,brcmstb-gpio.yaml F: drivers/gpio/gpio-brcmstb.c BROADCOM BRCMSTB I2C DRIVER -M: Kamal Dasu +M: Kamal Dasu R: Broadcom internal kernel review list L: linux-i2c@vger.kernel.org S: Supported @@ -4143,7 +4086,7 @@ F: Documentation/devicetree/bindings/serial/brcm,bcm7271-uart.yaml F: drivers/tty/serial/8250/8250_bcm7271.c BROADCOM BRCMSTB USB EHCI DRIVER -M: Justin Chen +M: Justin Chen M: Al Cooper R: Broadcom internal kernel review list L: linux-usb@vger.kernel.org @@ -4160,7 +4103,7 @@ F: Documentation/devicetree/bindings/usb/brcm,usb-pinmap.yaml F: drivers/usb/misc/brcmstb-usb-pinmap.c BROADCOM BRCMSTB USB2 and USB3 PHY DRIVER -M: Justin Chen +M: Justin Chen M: Al Cooper R: Broadcom internal kernel review list L: linux-kernel@vger.kernel.org @@ -4178,8 +4121,15 @@ F: Documentation/devicetree/bindings/spi/brcm,bcm63xx-hsspi.yaml F: drivers/spi/spi-bcm63xx-hsspi.c F: drivers/spi/spi-bcmbca-hsspi.c +BROADCOM BCM6348/BCM6358 SPI controller DRIVER +M: Jonas Gorski +L: linux-spi@vger.kernel.org +S: Odd Fixes +F: Documentation/devicetree/bindings/spi/spi-bcm63xx.txt +F: drivers/spi/spi-bcm63xx.c + BROADCOM ETHERNET PHY DRIVERS -M: Florian Fainelli +M: Florian Fainelli R: Broadcom internal kernel review list L: netdev@vger.kernel.org S: Supported @@ -4190,7 +4140,7 @@ F: include/linux/brcmphy.h BROADCOM GENET ETHERNET DRIVER M: Doug Berger -M: Florian Fainelli +M: Florian Fainelli R: Broadcom internal kernel review list L: netdev@vger.kernel.org S: Supported @@ -4274,7 +4224,7 @@ F: drivers/firmware/broadcom/* BROADCOM PMB (POWER MANAGEMENT BUS) DRIVER M: Rafał Miłecki -M: Florian Fainelli +M: Florian Fainelli R: Broadcom internal kernel review list L: linux-pm@vger.kernel.org S: Maintained @@ -4290,7 +4240,7 @@ F: drivers/bcma/ F: include/linux/bcma/ BROADCOM SPI DRIVER -M: Kamal Dasu +M: Kamal Dasu R: Broadcom internal kernel review list S: Maintained F: Documentation/devicetree/bindings/spi/brcm,spi-bcm-qspi.yaml @@ -4324,7 +4274,7 @@ F: drivers/memory/brcmstb_dpfe.c BROADCOM STB NAND FLASH DRIVER M: Brian Norris -M: Kamal Dasu +M: Kamal Dasu R: Broadcom internal kernel review list L: linux-mtd@lists.infradead.org S: Maintained @@ -4334,7 +4284,7 @@ F: include/linux/platform_data/brcmnand.h BROADCOM STB PCIE DRIVER M: Jim Quinlan M: Nicolas Saenz Julienne -M: Florian Fainelli +M: Florian Fainelli R: Broadcom internal kernel review list L: linux-pci@vger.kernel.org S: Maintained @@ -4342,7 +4292,7 @@ F: Documentation/devicetree/bindings/pci/brcm,stb-pcie.yaml F: drivers/pci/controller/pcie-brcmstb.c BROADCOM SYSTEMPORT ETHERNET DRIVER -M: Florian Fainelli +M: Florian Fainelli R: Broadcom internal kernel review list L: netdev@vger.kernel.org S: Supported @@ -4487,6 +4437,13 @@ S: Supported F: Documentation/filesystems/caching/cachefiles.rst F: fs/cachefiles/ +CACHESTAT: PAGE CACHE STATS FOR A FILE +M: Nhat Pham +M: Johannes Weiner +L: linux-mm@kvack.org +S: Maintained +F: tools/testing/selftests/cachestat/test_cachestat.c + CADENCE MIPI-CSI2 BRIDGES M: Maxime Ripard L: linux-media@vger.kernel.org @@ -4512,6 +4469,12 @@ F: Documentation/devicetree/bindings/usb/cdns,usb3.yaml F: drivers/usb/cdns3/ X: drivers/usb/cdns3/cdnsp* +CADENCE USBHS DRIVER +M: Pawel Laszczak +L: linux-usb@vger.kernel.org +S: Maintained +F: drivers/usb/gadget/udc/cdns2 + CADENCE USBSSP DRD IP DRIVER M: Pawel Laszczak L: linux-usb@vger.kernel.org @@ -5194,6 +5157,13 @@ S: Maintained F: drivers/cxl/ F: include/uapi/linux/cxl_mem.h +COMPUTE EXPRESS LINK PMU (CPMU) +M: Jonathan Cameron +L: linux-cxl@vger.kernel.org +S: Maintained +F: Documentation/admin-guide/perf/cxl.rst +F: drivers/perf/cxl_pmu.c + CONEXANT ACCESSRUNNER USB DRIVER L: accessrunner-general@lists.sourceforge.net S: Orphan @@ -5344,6 +5314,18 @@ F: include/linux/sched/cpufreq.h F: kernel/sched/cpufreq*.c F: tools/testing/selftests/cpufreq/ +CPU HOTPLUG +M: Thomas Gleixner +M: Peter Zijlstra +L: linux-kernel@vger.kernel.org +S: Maintained +T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git smp/core +F: include/linux/cpu.h +F: include/linux/cpuhotplug.h +F: include/linux/smpboot.h +F: kernel/cpu.c +F: kernel/smpboot.* + CPU IDLE TIME MANAGEMENT FRAMEWORK M: "Rafael J. Wysocki" M: Daniel Lezcano @@ -5712,10 +5694,7 @@ DC395x SCSI driver M: Oliver Neukum M: Ali Akcaagac M: Jamie Lenehan -L: dc395x@twibble.org S: Maintained -W: http://twibble.org/dist/dc395x/ -W: http://lists.twibble.org/mailman/listinfo/dc395x/ F: Documentation/scsi/dc395x.rst F: drivers/scsi/dc395x.* @@ -5733,8 +5712,8 @@ M: Thomas Gleixner L: linux-kernel@vger.kernel.org S: Maintained T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git core/debugobjects -F: lib/debugobjects.c F: include/linux/debugobjects.h +F: lib/debugobjects.c DECSTATION PLATFORM SUPPORT M: "Maciej W. Rozycki" @@ -5825,6 +5804,7 @@ M: Armin Wolf S: Maintained F: Documentation/ABI/testing/debugfs-dell-wmi-ddv F: Documentation/ABI/testing/sysfs-platform-dell-wmi-ddv +F: Documentation/wmi/devices/dell-wmi-ddv.rst F: drivers/platform/x86/dell/dell-wmi-ddv.c DELL WMI DESCRIPTOR DRIVER @@ -5889,7 +5869,9 @@ S: Orphan F: drivers/mtd/nand/raw/denali* DESIGNWARE EDMA CORE IP DRIVER -M: Gustavo Pimentel +M: Manivannan Sadhasivam +R: Gustavo Pimentel +R: Serge Semin L: dmaengine@vger.kernel.org S: Maintained F: drivers/dma/dw-edma/ @@ -6006,15 +5988,15 @@ DH ELECTRONICS IMX6 DHCOM/DHCOR BOARD SUPPORT M: Christoph Niedermaier L: kernel@dh-electronics.com S: Maintained -F: arch/arm/boot/dts/imx6*-dhcom-* -F: arch/arm/boot/dts/imx6*-dhcor-* +F: arch/arm/boot/dts/nxp/imx/imx6*-dhcom-* +F: arch/arm/boot/dts/nxp/imx/imx6*-dhcor-* DH ELECTRONICS STM32MP1 DHCOM/DHCOR BOARD SUPPORT M: Marek Vasut L: kernel@dh-electronics.com S: Maintained -F: arch/arm/boot/dts/stm32mp1*-dhcom-* -F: arch/arm/boot/dts/stm32mp1*-dhcor-* +F: arch/arm/boot/dts/st/stm32mp1*-dhcom-* +F: arch/arm/boot/dts/st/stm32mp1*-dhcor-* DIALOG SEMICONDUCTOR DRIVERS M: Support Opensource @@ -6226,6 +6208,12 @@ X: Documentation/power/ X: Documentation/spi/ X: Documentation/userspace-api/media/ +DOCUMENTATION PROCESS +M: Jonathan Corbet +L: workflows@vger.kernel.org +S: Maintained +F: Documentation/process/ + DOCUMENTATION REPORTING ISSUES M: Thorsten Leemhuis L: linux-doc@vger.kernel.org @@ -7100,7 +7088,6 @@ F: Documentation/gpu/xen-front.rst F: drivers/gpu/drm/xen/ DRM DRIVERS FOR XILINX -M: Hyun Kwon M: Laurent Pinchart L: dri-devel@lists.freedesktop.org S: Maintained @@ -7500,6 +7487,14 @@ L: linux-edac@vger.kernel.org S: Maintained F: drivers/edac/mpc85xx_edac.[ch] +EDAC-NPCM +M: Marvin Lin +M: Stanley Chu +L: linux-edac@vger.kernel.org +S: Maintained +F: Documentation/devicetree/bindings/memory-controllers/nuvoton,npcm-memory-controller.yaml +F: drivers/edac/npcm_edac.c + EDAC-PASEMI M: Egor Martovetsky L: linux-edac@vger.kernel.org @@ -7996,6 +7991,12 @@ S: Maintained F: drivers/hwmon/f75375s.c F: include/linux/f75375s.h +FINTEK F81604 USB to 2xCANBUS DEVICE DRIVER +M: Ji-Ze Hong (Peter Hong) +L: linux-can@vger.kernel.org +S: Maintained +F: drivers/net/can/usb/f81604.c + FIREWIRE AUDIO DRIVERS and IEC 61883-1/6 PACKET STREAMING ENGINE M: Clemens Ladisch M: Takashi Sakamoto @@ -8091,6 +8092,7 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux.git for-next/har F: include/linux/fortify-string.h F: lib/fortify_kunit.c F: lib/memcpy_kunit.c +F: lib/strcat_kunit.c F: lib/strscpy_kunit.c F: lib/test_fortify/* F: scripts/test_fortify.sh @@ -8687,8 +8689,14 @@ S: Maintained F: drivers/input/touchscreen/resistive-adc-touch.c GENERIC STRING LIBRARY +M: Kees Cook R: Andy Shevchenko -S: Maintained +L: linux-hardening@vger.kernel.org +S: Supported +T: git git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux.git for-next/hardening +F: include/linux/string.h +F: include/linux/string_choices.h +F: include/linux/string_helpers.h F: lib/string.c F: lib/string_helpers.c F: lib/test-string_helpers.c @@ -9176,6 +9184,12 @@ L: linux-input@vger.kernel.org S: Maintained F: drivers/hid/hid-logitech-* +HID NVIDIA SHIELD DRIVER +M: Rahul Rameshbabu +L: linux-input@vger.kernel.org +S: Maintained +F: drivers/hid/hid-nvidia-shield.c + HID PHOENIX RC FLIGHT CONTROLLER M: Marcus Folkesson L: linux-input@vger.kernel.org @@ -9445,6 +9459,13 @@ F: lib/test_hmm* F: mm/hmm* F: tools/testing/selftests/mm/*hmm* +HONEYWELL MPRLS0025PA PRESSURE SENSOR SERIES IIO DRIVER +M: Andreas Klinger +L: linux-iio@vger.kernel.org +S: Maintained +F: Documentation/devicetree/bindings/iio/pressure/honeywell,mprls0025pa.yaml +F: drivers/iio/pressure/mprls0025pa.c + HOST AP DRIVER M: Jouni Malinen L: linux-wireless@vger.kernel.org @@ -9457,6 +9478,13 @@ L: platform-driver-x86@vger.kernel.org S: Orphan F: drivers/platform/x86/hp/tc1100-wmi.c +HP WMI HARDWARE MONITOR DRIVER +M: James Seo +L: linux-hwmon@vger.kernel.org +S: Maintained +F: Documentation/hwmon/hp-wmi-sensors.rst +F: drivers/hwmon/hp-wmi-sensors.c + HPET: High Precision Event Timers driver M: Clemens Ladisch S: Maintained @@ -9990,8 +10018,9 @@ M: Miquel Raynal L: linux-wpan@vger.kernel.org S: Maintained W: https://linux-wpan.org/ -T: git git://git.kernel.org/pub/scm/linux/kernel/git/sschmidt/wpan.git -T: git git://git.kernel.org/pub/scm/linux/kernel/git/sschmidt/wpan-next.git +Q: https://patchwork.kernel.org/project/linux-wpan/list/ +T: git git://git.kernel.org/pub/scm/linux/kernel/git/wpan/wpan.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/wpan/wpan-next.git F: Documentation/networking/ieee802154.rst F: drivers/net/ieee802154/ F: include/linux/ieee802154.h @@ -10281,6 +10310,13 @@ L: linux-fbdev@vger.kernel.org S: Maintained F: drivers/video/fbdev/i810/ +INTEL 8254 COUNTER DRIVER +M: William Breathitt Gray +L: linux-iio@vger.kernel.org +S: Maintained +F: drivers/counter/i8254.c +F: include/linux/i8254.h + INTEL 8255 GPIO DRIVER M: William Breathitt Gray L: linux-gpio@vger.kernel.org @@ -10363,9 +10399,8 @@ M: Jesse Brandeburg M: Tony Nguyen L: intel-wired-lan@lists.osuosl.org (moderated for non-subscribers) S: Supported -W: http://www.intel.com/support/feedback.htm -W: http://e1000.sourceforge.net/ -Q: http://patchwork.ozlabs.org/project/intel-wired-lan/list/ +W: https://www.intel.com/content/www/us/en/support.html +Q: https://patchwork.ozlabs.org/project/intel-wired-lan/list/ T: git git://git.kernel.org/pub/scm/linux/kernel/git/tnguy/net-queue.git T: git git://git.kernel.org/pub/scm/linux/kernel/git/tnguy/next-queue.git F: Documentation/networking/device_drivers/ethernet/intel/ @@ -10487,7 +10522,7 @@ L: linux-media@vger.kernel.org S: Maintained F: Documentation/admin-guide/media/ipu3.rst F: Documentation/admin-guide/media/ipu3_rcb.svg -F: Documentation/userspace-api/media/v4l/pixfmt-meta-intel-ipu3.rst +F: Documentation/userspace-api/media/v4l/metafmt-intel-ipu3.rst F: drivers/staging/media/ipu3/ INTEL ISHTP ECLITE DRIVER @@ -10831,7 +10866,6 @@ S: Maintained F: drivers/net/ethernet/sgi/ioc3-eth.c IOMAP FILESYSTEM LIBRARY -M: Christoph Hellwig M: Darrick J. Wong L: linux-xfs@vger.kernel.org L: linux-fsdevel@vger.kernel.org @@ -11292,6 +11326,10 @@ W: http://kernelnewbies.org/KernelJanitors KERNEL NFSD, SUNRPC, AND LOCKD SERVERS M: Chuck Lever M: Jeff Layton +R: Neil Brown +R: Olga Kornievskaia +R: Dai Ngo +R: Tom Talpey L: linux-nfs@vger.kernel.org S: Supported W: http://nfs.sourceforge.net/ @@ -11349,6 +11387,8 @@ L: linux-kselftest@vger.kernel.org L: kunit-dev@googlegroups.com S: Maintained W: https://google.github.io/kunit-docs/third_party/kernel/docs/ +T: git git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest.git kunit +T: git git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest.git kunit-fixes F: Documentation/dev-tools/kunit/ F: include/kunit/ F: lib/kunit/ @@ -11397,7 +11437,6 @@ F: tools/testing/selftests/kvm/aarch64/ KERNEL VIRTUAL MACHINE FOR MIPS (KVM/mips) M: Huacai Chen -M: Aleksandar Markovic L: linux-mips@vger.kernel.org L: kvm@vger.kernel.org S: Maintained @@ -11407,7 +11446,13 @@ F: arch/mips/include/uapi/asm/kvm* F: arch/mips/kvm/ KERNEL VIRTUAL MACHINE FOR POWERPC (KVM/powerpc) +M: Michael Ellerman +R: Nicholas Piggin L: linuxppc-dev@lists.ozlabs.org +L: kvm@vger.kernel.org +S: Maintained (Book3S 64-bit HV) +S: Odd fixes (Book3S 64-bit PR) +S: Orphan (Book3E and 32-bit) T: git git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux.git topic/ppc-kvm F: arch/powerpc/include/asm/kvm* F: arch/powerpc/include/uapi/asm/kvm* @@ -11453,6 +11498,7 @@ M: Sean Christopherson M: Paolo Bonzini L: kvm@vger.kernel.org S: Supported +P: Documentation/process/maintainer-kvm-x86.rst T: git git://git.kernel.org/pub/scm/virt/kvm/kvm.git F: arch/x86/include/asm/kvm* F: arch/x86/include/asm/svm.h @@ -11769,7 +11815,7 @@ LEGO MINDSTORMS EV3 R: David Lechner S: Maintained F: Documentation/devicetree/bindings/power/supply/lego,ev3-battery.yaml -F: arch/arm/boot/dts/da850-lego-ev3.dts +F: arch/arm/boot/dts/ti/davinci/da850-lego-ev3.dts F: drivers/power/supply/lego_ev3_battery.c LEGO USB Tower driver @@ -11940,11 +11986,12 @@ F: lib/linear_ranges.c F: lib/test_linear_ranges.c LINUX FOR POWER MACINTOSH -M: Benjamin Herrenschmidt L: linuxppc-dev@lists.ozlabs.org -S: Odd Fixes +S: Orphan F: arch/powerpc/platforms/powermac/ F: drivers/macintosh/ +X: drivers/macintosh/adb-iop.c +X: drivers/macintosh/via-macii.c LINUX FOR POWERPC (32-BIT AND 64-BIT) M: Michael Ellerman @@ -12042,6 +12089,13 @@ F: Documentation/litmus-tests/ F: Documentation/memory-barriers.txt F: tools/memory-model/ +LINUX-NEXT TREE +M: Stephen Rothwell +L: linux-next@vger.kernel.org +S: Supported +B: mailto:linux-next@vger.kernel.org and the appropriate development tree +T: git git://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git/ + LIS3LV02D ACCELEROMETER DRIVER M: Eric Piel S: Maintained @@ -12563,12 +12617,11 @@ MARVELL NAND CONTROLLER DRIVER M: Miquel Raynal L: linux-mtd@lists.infradead.org S: Maintained -F: Documentation/devicetree/bindings/mtd/marvell-nand.txt F: drivers/mtd/nand/raw/marvell_nand.c MARVELL OCTEON ENDPOINT DRIVER M: Veerasenareddy Burru -M: Abhijit Ayarekar +M: Sathesh Edara L: netdev@vger.kernel.org S: Supported F: drivers/net/ethernet/marvell/octeon_ep @@ -12650,6 +12703,15 @@ F: Documentation/userspace-api/media/drivers/max2175.rst F: drivers/media/i2c/max2175* F: include/uapi/linux/max2175.h +MAX31827 TEMPERATURE SWITCH DRIVER +M: Daniel Matyas +L: linux-hwmon@vger.kernel.org +S: Supported +W: http://ez.analog.com/community/linux-device-drivers +F: Documentation/devicetree/bindings/hwmon/adi,max31827.yaml +F: Documentation/hwmon/max31827.rst +F: drivers/hwmon/max31827.c + MAX6650 HARDWARE MONITOR AND FAN CONTROLLER DRIVER L: linux-hwmon@vger.kernel.org S: Orphan @@ -12867,6 +12929,13 @@ F: Documentation/devicetree/bindings/net/ieee802154/mcr20a.txt F: drivers/net/ieee802154/mcr20a.c F: drivers/net/ieee802154/mcr20a.h +MDIO REGMAP DRIVER +M: Maxime Chevallier +L: netdev@vger.kernel.org +S: Maintained +F: drivers/net/mdio/mdio-regmap.c +F: include/linux/mdio/mdio-regmap.h + MEASUREMENT COMPUTING CIO-DAC IIO DRIVER M: William Breathitt Gray L: linux-iio@vger.kernel.org @@ -13166,6 +13235,15 @@ S: Maintained F: drivers/net/pcs/pcs-mtk-lynxi.c F: include/linux/pcs/pcs-mtk-lynxi.h +MEDIATEK ETHERNET PHY DRIVERS +M: Daniel Golle +M: Qingfang Deng +M: SkyLake Huang +L: netdev@vger.kernel.org +S: Maintained +F: drivers/net/phy/mediatek-ge-soc.c +F: drivers/net/phy/mediatek-ge.c + MEDIATEK I2C CONTROLLER DRIVER M: Qii Wang L: linux-i2c@vger.kernel.org @@ -13227,6 +13305,7 @@ R: Shayne Chen R: Sean Wang L: linux-wireless@vger.kernel.org S: Maintained +T: git https://github.com/nbd168/wireless F: Documentation/devicetree/bindings/net/wireless/mediatek,mt76.yaml F: drivers/net/wireless/mediatek/mt76/ @@ -13261,6 +13340,12 @@ S: Maintained F: Documentation/devicetree/bindings/i2c/mediatek,mt7621-i2c.yaml F: drivers/i2c/busses/i2c-mt7621.c +MEDIATEK MTMIPS CLOCK DRIVER +M: Sergio Paracuellos +S: Maintained +F: Documentation/devicetree/bindings/clock/mediatek,mtmips-sysc.yaml +F: drivers/clk/ralink/clk-mtmips.c + MEDIATEK NAND CONTROLLER DRIVER L: linux-mtd@lists.infradead.org S: Orphan @@ -13287,10 +13372,11 @@ F: drivers/memory/mtk-smi.c F: include/soc/mediatek/smi.h MEDIATEK SWITCH DRIVER -M: Sean Wang +M: Arınç ÜNAL +M: Daniel Golle M: Landen Chao M: DENG Qingfang -M: Daniel Golle +M: Sean Wang L: netdev@vger.kernel.org S: Maintained F: drivers/net/dsa/mt7530-mdio.c @@ -13655,6 +13741,7 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/mani/mhi.git F: Documentation/ABI/stable/sysfs-bus-mhi F: Documentation/mhi/ F: drivers/bus/mhi/ +F: drivers/pci/endpoint/functions/pci-epf-mhi.c F: include/linux/mhi.h MICROBLAZE ARCHITECTURE @@ -13737,6 +13824,7 @@ MICROCHIP EIC DRIVER M: Claudiu Beznea L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Supported +F: Documentation/devicetree/bindings/interrupt-controller/microchip,sama7g5-eic.yaml F: drivers/irqchip/irq-mchp-eic.c MICROCHIP I2C DRIVER @@ -13890,6 +13978,7 @@ F: include/dt-bindings/iio/adc/at91-sama5d2_adc.h MICROCHIP SAMA5D2-COMPATIBLE SHUTDOWN CONTROLLER M: Claudiu Beznea S: Supported +F: Documentation/devicetree/bindings/power/reset/atmel,sama5d2-shdwc.yaml F: drivers/power/reset/at91-sama5d2_shdwc.c MICROCHIP SOC DRIVERS @@ -13899,7 +13988,7 @@ T: git https://git.kernel.org/pub/scm/linux/kernel/git/conor/linux.git/ F: drivers/soc/microchip/ MICROCHIP SPI DRIVER -M: Tudor Ambarus +M: Ryan Wanner S: Supported F: drivers/spi/spi-atmel.* @@ -14063,12 +14152,12 @@ MIKROTIK CRS3XX 98DX3236 BOARD SUPPORT M: Luka Kovacic M: Luka Perkov S: Maintained -F: arch/arm/boot/dts/armada-xp-crs305-1g-4s-bit.dts -F: arch/arm/boot/dts/armada-xp-crs305-1g-4s.dts -F: arch/arm/boot/dts/armada-xp-crs326-24g-2s-bit.dts -F: arch/arm/boot/dts/armada-xp-crs326-24g-2s.dts -F: arch/arm/boot/dts/armada-xp-crs328-4c-20s-4s-bit.dts -F: arch/arm/boot/dts/armada-xp-crs328-4c-20s-4s.dts +F: arch/arm/boot/dts/marvell/armada-xp-crs305-1g-4s-bit.dts +F: arch/arm/boot/dts/marvell/armada-xp-crs305-1g-4s.dts +F: arch/arm/boot/dts/marvell/armada-xp-crs326-24g-2s-bit.dts +F: arch/arm/boot/dts/marvell/armada-xp-crs326-24g-2s.dts +F: arch/arm/boot/dts/marvell/armada-xp-crs328-4c-20s-4s-bit.dts +F: arch/arm/boot/dts/marvell/armada-xp-crs328-4c-20s-4s.dts MIPI CCS, SMIA AND SMIA++ IMAGE SENSOR DRIVER M: Sakari Ailus @@ -14171,7 +14260,7 @@ R: Lubomir Rintel L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Odd Fixes T: git git://git.kernel.org/pub/scm/linux/kernel/git/lkundrak/linux-mmp.git -F: arch/arm/boot/dts/mmp* +F: arch/arm/boot/dts/marvell/mmp* F: arch/arm/mach-mmp/ F: include/linux/soc/mmp/ @@ -14599,7 +14688,6 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git F: Documentation/devicetree/bindings/net/ F: drivers/connector/ F: drivers/net/ -X: drivers/net/wireless/ F: include/dt-bindings/net/ F: include/linux/etherdevice.h F: include/linux/fcdevice.h @@ -14610,6 +14698,7 @@ F: include/linux/inetdevice.h F: include/linux/netdevice.h F: include/uapi/linux/if_* F: include/uapi/linux/netdevice.h +X: drivers/net/wireless/ NETWORKING DRIVERS (WIRELESS) M: Kalle Valo @@ -14664,9 +14753,9 @@ F: include/uapi/linux/netdevice.h F: lib/net_utils.c F: lib/random32.c F: net/ -X: net/bluetooth/ F: tools/net/ F: tools/testing/selftests/net/ +X: net/bluetooth/ NETWORKING [IPSEC] M: Steffen Klassert @@ -14711,7 +14800,7 @@ NETWORKING [LABELED] (NetLabel, Labeled IPsec, SECMARK) M: Paul Moore L: netdev@vger.kernel.org L: linux-security-module@vger.kernel.org -S: Maintained +S: Supported W: https://github.com/netlabel F: Documentation/netlabel/ F: include/net/calipso.h @@ -14747,6 +14836,7 @@ NETWORKING [TCP] M: Eric Dumazet L: netdev@vger.kernel.org S: Maintained +F: include/linux/net_mm.h F: include/linux/tcp.h F: include/net/tcp.h F: include/trace/events/tcp.h @@ -14940,7 +15030,7 @@ M: Allen Hubbe L: ntb@lists.linux.dev S: Supported W: https://github.com/jonmason/ntb/wiki -T: git git://github.com/jonmason/ntb.git +T: git https://github.com/jonmason/ntb.git F: drivers/net/ntb_netdev.c F: drivers/ntb/ F: drivers/pci/endpoint/functions/pci-epf-*ntb.c @@ -15303,19 +15393,13 @@ M: Tony Lindgren L: linux-omap@vger.kernel.org L: devicetree@vger.kernel.org S: Maintained -F: arch/arm/boot/dts/*am3* -F: arch/arm/boot/dts/*am4* -F: arch/arm/boot/dts/*am5* -F: arch/arm/boot/dts/*dra7* -F: arch/arm/boot/dts/*omap* -F: arch/arm/boot/dts/logicpd-som-lv* -F: arch/arm/boot/dts/logicpd-torpedo* +F: arch/arm/boot/dts/ti/omap/ OMAP DISPLAY SUBSYSTEM and FRAMEBUFFER SUPPORT (DSS2) L: linux-omap@vger.kernel.org L: linux-fbdev@vger.kernel.org S: Orphan -F: Documentation/arm/omap/dss.rst +F: Documentation/arch/arm/omap/dss.rst F: drivers/video/fbdev/omap2/ OMAP FRAMEBUFFER SUPPORT @@ -15417,7 +15501,7 @@ OMAP/NEWFLOW NANOBONE MACHINE SUPPORT M: Mark Jackson L: linux-omap@vger.kernel.org S: Maintained -F: arch/arm/boot/dts/am335x-nano.dts +F: arch/arm/boot/dts/ti/omap/am335x-nano.dts OMAP1 SUPPORT M: Aaro Koskinen @@ -15444,6 +15528,7 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap.git F: arch/arm/configs/omap2plus_defconfig F: arch/arm/mach-omap2/ F: drivers/bus/ti-sysc.c +F: drivers/gpio/gpio-tps65219.c F: drivers/i2c/busses/i2c-omap.c F: drivers/irqchip/irq-omap-intc.c F: drivers/mfd/*omap*.c @@ -15481,6 +15566,13 @@ L: linux-media@vger.kernel.org S: Maintained F: drivers/media/i2c/og01a1b.c +OMNIVISION OV01A10 SENSOR DRIVER +M: Bingbu Cao +L: linux-media@vger.kernel.org +S: Maintained +T: git git://linuxtv.org/media_tree.git +F: drivers/media/i2c/ov01a10.c + OMNIVISION OV02A10 SENSOR DRIVER M: Dongchun Zhu L: linux-media@vger.kernel.org @@ -15829,7 +15921,7 @@ ORACLE CLUSTER FILESYSTEM 2 (OCFS2) M: Mark Fasheh M: Joel Becker M: Joseph Qi -L: ocfs2-devel@oss.oracle.com (moderated for non-subscribers) +L: ocfs2-devel@lists.linux.dev S: Supported W: http://ocfs2.wiki.kernel.org F: Documentation/filesystems/dlmfs.rst @@ -15864,6 +15956,7 @@ F: include/media/i2c/ov2659.h OVERLAY FILESYSTEM M: Miklos Szeredi +M: Amir Goldstein L: linux-unionfs@vger.kernel.org S: Supported T: git git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/vfs.git @@ -15966,7 +16059,7 @@ F: include/uapi/linux/ppdev.h PARAVIRT_OPS INTERFACE M: Juergen Gross -M: Srivatsa S. Bhat (VMware) +R: Ajay Kaher R: Alexey Makhalov R: VMware PV-Drivers Reviewers L: virtualization@lists.linux-foundation.org @@ -16402,7 +16495,7 @@ F: Documentation/devicetree/bindings/pci/intel,keembay-pcie* F: drivers/pci/controller/dwc/pcie-keembay.c PCIE DRIVER FOR INTEL LGM GW SOC -M: Rahul Tanwar +M: Chuanhua Lei L: linux-pci@vger.kernel.org S: Maintained F: Documentation/devicetree/bindings/pci/intel-gw-pcie.yaml @@ -16482,6 +16575,10 @@ S: Maintained F: crypto/pcrypt.c F: include/crypto/pcrypt.h +PDS DSC VIRTIO DATA PATH ACCELERATOR +R: Shannon Nelson +F: drivers/vdpa/pds/ + PECI HARDWARE MONITORING DRIVERS M: Iwona Winiarska L: linux-hwmon@vger.kernel.org @@ -16709,7 +16806,7 @@ PIN CONTROLLER - QUALCOMM M: Bjorn Andersson L: linux-arm-msm@vger.kernel.org S: Maintained -F: Documentation/devicetree/bindings/pinctrl/qcom,*.txt +F: Documentation/devicetree/bindings/pinctrl/qcom,* F: drivers/pinctrl/qcom/ PIN CONTROLLER - RENESAS @@ -17164,7 +17261,7 @@ L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained T: git git://github.com/hzhuang1/linux.git T: git git://github.com/rjarzmik/linux.git -F: arch/arm/boot/dts/pxa* +F: arch/arm/boot/dts/intel/pxa/ F: arch/arm/mach-pxa/ F: drivers/dma/pxa* F: drivers/pcmcia/pxa2xx* @@ -17202,6 +17299,7 @@ F: sound/soc/codecs/wcd9335.* F: sound/soc/codecs/wcd934x.c F: sound/soc/codecs/wsa881x.c F: sound/soc/codecs/wsa883x.c +F: sound/soc/codecs/wsa884x.c F: sound/soc/qcom/ QCOM EMBEDDED USB DEBUGGER (EUD) @@ -17376,6 +17474,8 @@ QUALCOMM ATHEROS ATH11K WIRELESS DRIVER M: Kalle Valo L: ath11k@lists.infradead.org S: Supported +W: https://wireless.wiki.kernel.org/en/users/Drivers/ath11k +B: https://wireless.wiki.kernel.org/en/users/Drivers/ath11k/bugreport T: git git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git F: Documentation/devicetree/bindings/net/wireless/qcom,ath11k.yaml F: drivers/net/wireless/ath/ath11k/ @@ -17385,6 +17485,7 @@ M: Toke Høiland-Jørgensen L: linux-wireless@vger.kernel.org S: Maintained W: https://wireless.wiki.kernel.org/en/users/Drivers/ath9k +T: git git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git F: Documentation/devicetree/bindings/net/wireless/qca,ath9k.yaml F: drivers/net/wireless/ath/ath9k/ @@ -17462,6 +17563,7 @@ QUALCOMM ETHQOS ETHERNET DRIVER M: Vinod Koul R: Bhupesh Sharma L: netdev@vger.kernel.org +L: linux-arm-msm@vger.kernel.org S: Maintained F: Documentation/devicetree/bindings/net/qcom,ethqos.yaml F: drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c @@ -17571,9 +17673,18 @@ S: Maintained F: Documentation/devicetree/bindings/thermal/qcom-tsens.yaml F: drivers/thermal/qcom/ +QUALCOMM TYPEC PORT MANAGER DRIVER +M: Bryan O'Donoghue +L: linux-arm-msm@vger.kernel.org +L: linux-usb@vger.kernel.org +S: Maintained +F: Documentation/devicetree/bindings/usb/qcom,pmic-*.yaml +F: drivers/usb/typec/tcpm/qcom/ + QUALCOMM VENUS VIDEO ACCELERATOR DRIVER M: Stanimir Varbanov M: Vikash Garodia +R: Bryan O'Donoghue L: linux-media@vger.kernel.org L: linux-arm-msm@vger.kernel.org S: Maintained @@ -17816,7 +17927,7 @@ M: Boqun Feng R: Steven Rostedt R: Mathieu Desnoyers R: Lai Jiangshan -R: Zqiang +R: Zqiang L: rcu@vger.kernel.org S: Supported W: http://www.rdrop.com/users/paulmck/RCU/ @@ -17847,7 +17958,7 @@ F: tools/testing/selftests/rtc/ Real-time Linux Analysis (RTLA) tools M: Daniel Bristot de Oliveira M: Steven Rostedt -L: linux-trace-devel@vger.kernel.org +L: linux-trace-kernel@vger.kernel.org S: Maintained F: Documentation/tools/rtla/ F: tools/tracing/rtla/ @@ -18088,6 +18199,13 @@ S: Maintained F: Documentation/devicetree/bindings/clock/renesas,versaclock7.yaml F: drivers/clk/clk-versaclock7.c +RENESAS X9250 DIGITAL POTENTIOMETERS DRIVER +M: Herve Codina +L: linux-iio@vger.kernel.org +S: Maintained +F: Documentation/devicetree/bindings/iio/potentiometer/renesas,x9250.yaml +F: drivers/iio/potentiometer/x9250.c + RESET CONTROLLER FRAMEWORK M: Philipp Zabel S: Maintained @@ -18183,6 +18301,7 @@ F: drivers/clk/microchip/clk-mpfs*.c F: drivers/i2c/busses/i2c-microchip-corei2c.c F: drivers/mailbox/mailbox-mpfs.c F: drivers/pci/controller/pcie-microchip-host.c +F: drivers/pwm/pwm-microchip-core.c F: drivers/reset/reset-mpfs.c F: drivers/rtc/rtc-mpfs.c F: drivers/soc/microchip/mpfs-sys-controller.c @@ -18199,6 +18318,8 @@ Q: https://patchwork.kernel.org/project/linux-riscv/list/ T: git https://git.kernel.org/pub/scm/linux/kernel/git/conor/linux.git/ F: Documentation/devicetree/bindings/riscv/ F: arch/riscv/boot/dts/ +X: arch/riscv/boot/dts/allwinner/ +X: arch/riscv/boot/dts/renesas/ RISC-V PMU DRIVERS M: Atish Patra @@ -18209,6 +18330,14 @@ F: drivers/perf/riscv_pmu.c F: drivers/perf/riscv_pmu_legacy.c F: drivers/perf/riscv_pmu_sbi.c +RISC-V THEAD SoC SUPPORT +M: Jisheng Zhang +M: Guo Ren +M: Fu Wei +L: linux-riscv@lists.infradead.org +S: Maintained +F: arch/riscv/boot/dts/thead/ + RNBD BLOCK DRIVERS M: Md. Haris Iqbal M: Jack Wang @@ -18245,7 +18374,7 @@ L: linux-rockchip@lists.infradead.org S: Maintained F: Documentation/admin-guide/media/rkisp1.rst F: Documentation/devicetree/bindings/media/rockchip-isp1.yaml -F: Documentation/userspace-api/media/v4l/pixfmt-meta-rkisp1.rst +F: Documentation/userspace-api/media/v4l/metafmt-rkisp1.rst F: drivers/media/platform/rockchip/rkisp1 F: include/uapi/linux/rkisp1-config.h @@ -18290,10 +18419,11 @@ S: Maintained F: Documentation/devicetree/bindings/iio/light/bh1750.yaml F: drivers/iio/light/bh1750.c -ROHM BU27034 AMBIENT LIGHT SENSOR DRIVER +ROHM BU270xx LIGHT SENSOR DRIVERs M: Matti Vaittinen L: linux-iio@vger.kernel.org S: Supported +F: drivers/iio/light/rohm-bu27008.c F: drivers/iio/light/rohm-bu27034.c ROHM MULTIFUNCTION BD9571MWV-M PMIC DEVICE DRIVERS @@ -18417,7 +18547,7 @@ F: drivers/infiniband/ulp/rtrs/ RUNTIME VERIFICATION (RV) M: Daniel Bristot de Oliveira M: Steven Rostedt -L: linux-trace-devel@vger.kernel.org +L: linux-trace-kernel@vger.kernel.org S: Maintained F: Documentation/trace/rv/ F: include/linux/rv.h @@ -18792,7 +18922,7 @@ SANCLOUD BEAGLEBONE ENHANCED DEVICE TREE M: Paul Barker R: Marc Murphy S: Supported -F: arch/arm/boot/dts/am335x-sancloud* +F: arch/arm/boot/dts/ti/omap/am335x-sancloud* SC1200 WDT DRIVER M: Zwane Mwaikambo @@ -18819,6 +18949,16 @@ F: include/linux/wait.h F: include/uapi/linux/sched.h F: kernel/sched/ +SCSI LIBSAS SUBSYSTEM +R: John Garry +R: Jason Yan +L: linux-scsi@vger.kernel.org +S: Supported +F: Documentation/scsi/libsas.rst +F: drivers/scsi/libsas/ +F: include/scsi/libsas.h +F: include/scsi/sas_ata.h + SCSI RDMA PROTOCOL (SRP) INITIATOR M: Bart Van Assche L: linux-rdma@vger.kernel.org @@ -18947,7 +19087,7 @@ K: \bsecure_computing K: \bTIF_SECCOMP\b SECURE DIGITAL HOST CONTROLLER INTERFACE (SDHCI) Broadcom BRCMSTB DRIVER -M: Kamal Dasu +M: Kamal Dasu M: Al Cooper R: Broadcom internal kernel review list L: linux-mmc@vger.kernel.org @@ -19621,15 +19761,15 @@ F: include/uapi/linux/raid/ SOLIDRUN CLEARFOG SUPPORT M: Russell King S: Maintained -F: arch/arm/boot/dts/armada-388-clearfog* -F: arch/arm/boot/dts/armada-38x-solidrun-* +F: arch/arm/boot/dts/marvell/armada-388-clearfog* +F: arch/arm/boot/dts/marvell/armada-38x-solidrun-* SOLIDRUN CUBOX-I/HUMMINGBOARD SUPPORT M: Russell King S: Maintained -F: arch/arm/boot/dts/imx6*-cubox-i* -F: arch/arm/boot/dts/imx6*-hummingboard* -F: arch/arm/boot/dts/imx6*-sr-* +F: arch/arm/boot/dts/nxp/imx/imx6*-cubox-i* +F: arch/arm/boot/dts/nxp/imx/imx6*-hummingboard* +F: arch/arm/boot/dts/nxp/imx/imx6*-sr-* SONIC NETWORK DRIVER M: Thomas Bogendoerfer @@ -19914,7 +20054,7 @@ M: soc@kernel.org L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained W: http://www.st.com/spear -F: arch/arm/boot/dts/spear* +F: arch/arm/boot/dts/st/spear* F: arch/arm/mach-spear/ F: drivers/clk/spear/ F: drivers/pinctrl/spear/ @@ -20127,6 +20267,13 @@ M: Ion Badulescu S: Odd Fixes F: drivers/net/ethernet/adaptec/starfire* +STARFIVE CRYPTO DRIVER +M: Jia Jie Ho +M: William Qiu +S: Supported +F: Documentation/devicetree/bindings/crypto/starfive* +F: drivers/crypto/starfive/ + STARFIVE DEVICETREES M: Emil Renner Berthing S: Maintained @@ -20145,6 +20292,12 @@ S: Supported F: Documentation/devicetree/bindings/mmc/starfive* F: drivers/mmc/host/dw_mmc-starfive.c +STARFIVE JH7110 TDM DRIVER +M: Walker Chen +S: Maintained +F: Documentation/devicetree/bindings/sound/starfive,jh7110-tdm.yaml +F: sound/soc/starfive/jh7110_tdm.c + STARFIVE JH71X0 CLOCK DRIVERS M: Emil Renner Berthing M: Hal Feng @@ -20171,6 +20324,12 @@ F: Documentation/devicetree/bindings/reset/starfive,jh7100-reset.yaml F: drivers/reset/starfive/reset-starfive-jh71* F: include/dt-bindings/reset/starfive?jh71*.h +STARFIVE JH71X0 USB DRIVERS +M: Minda Chen +S: Maintained +F: Documentation/devicetree/bindings/usb/starfive,jh7110-usb.yaml +F: drivers/usb/cdns3/cdns3-starfive.c + STARFIVE JH71XX PMU CONTROLLER DRIVER M: Walker Chen S: Supported @@ -20864,10 +21023,13 @@ TEGRA VIDEO DRIVER M: Thierry Reding M: Jonathan Hunter M: Sowjanya Komatineni +M: Luca Ceresoli L: linux-media@vger.kernel.org L: linux-tegra@vger.kernel.org S: Maintained F: Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-host1x.yaml +F: Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-vi.yaml +F: Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-vip.yaml F: drivers/staging/media/tegra-video/ TEGRA XUSB PADCTL DRIVER @@ -21122,7 +21284,7 @@ L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained T: git git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux.git F: Documentation/devicetree/bindings/i2c/i2c-davinci.txt -F: arch/arm/boot/dts/da850* +F: arch/arm/boot/dts/ti/davinci/ F: arch/arm/mach-davinci/ F: drivers/i2c/busses/i2c-davinci.c @@ -21962,6 +22124,7 @@ F: drivers/usb/ F: include/dt-bindings/usb/ F: include/linux/usb.h F: include/linux/usb/ +F: include/uapi/linux/usb/ USB TYPEC BUS FOR ALTERNATE MODES M: Heikki Krogerus @@ -22136,6 +22299,13 @@ F: Documentation/filesystems/vfat.rst F: fs/fat/ F: tools/testing/selftests/filesystems/fat/ +VFIO CDX DRIVER +M: Nipun Gupta +M: Nikhil Agarwal +L: kvm@vger.kernel.org +S: Maintained +F: drivers/vfio/cdx/* + VFIO DRIVER M: Alex Williamson L: kvm@vger.kernel.org @@ -22217,7 +22387,6 @@ L: linux-fbdev@vger.kernel.org S: Maintained F: drivers/video/fbdev/via/ F: include/linux/via-core.h -F: include/linux/via-gpio.h F: include/linux/via_i2c.h VIA VELOCITY NETWORK DRIVER @@ -22470,6 +22639,14 @@ L: linux-fsdevel@vger.kernel.org S: Maintained F: fs/vboxsf/* +VIRTUAL PCM TEST DRIVER +M: Ivan Orlov +L: alsa-devel@alsa-project.org +S: Maintained +F: Documentation/sound/cards/pcmtest.rst +F: sound/drivers/pcmtest.c +F: tools/testing/selftests/alsa/test-pcmtest-driver.c + VIRTUAL SERIO DEVICE DRIVER M: Stephen Chandler Paul S: Maintained @@ -22540,7 +22717,7 @@ S: Supported F: drivers/misc/vmw_balloon.c VMWARE HYPERVISOR INTERFACE -M: Srivatsa S. Bhat (VMware) +M: Ajay Kaher M: Alexey Makhalov R: VMware PV-Drivers Reviewers L: virtualization@lists.linux-foundation.org @@ -22567,8 +22744,8 @@ F: drivers/scsi/vmw_pvscsi.c F: drivers/scsi/vmw_pvscsi.h VMWARE VIRTUAL PTP CLOCK DRIVER -M: Srivatsa S. Bhat (VMware) M: Deep Shah +R: Ajay Kaher R: Alexey Makhalov R: VMware PV-Drivers Reviewers L: netdev@vger.kernel.org @@ -22791,6 +22968,13 @@ L: linux-wireless@vger.kernel.org S: Odd fixes F: drivers/net/wireless/legacy/wl3501* +WMI BINARY MOF DRIVER +L: platform-drivers-x86@vger.kernel.org +S: Orphan +F: Documentation/ABI/stable/sysfs-platform-wmi-bmof +F: Documentation/wmi/devices/wmi-bmof.rst +F: drivers/platform/x86/wmi-bmof.c + WOLFSON MICROELECTRONICS DRIVERS L: patches@opensource.cirrus.com S: Supported @@ -23170,8 +23354,9 @@ F: Documentation/devicetree/bindings/iio/adc/xlnx,zynqmp-ams.yaml F: drivers/iio/adc/xilinx-ams.c XILINX AXI ETHERNET DRIVER -M: Radhey Shyam Pandey +M: Radhey Shyam Pandey S: Maintained +F: Documentation/devicetree/bindings/net/xlnx,axi-ethernet.yaml F: drivers/net/ethernet/xilinx/xilinx_axienet* XILINX CAN DRIVER @@ -23189,8 +23374,8 @@ F: drivers/soc/xilinx/xlnx_event_manager.c F: include/linux/firmware/xlnx-event-manager.h XILINX GPIO DRIVER -M: Shubhrajyoti Datta -R: Srinivas Neeli +M: Shubhrajyoti Datta +R: Srinivas Neeli R: Michal Simek S: Maintained F: Documentation/devicetree/bindings/gpio/gpio-zynq.yaml @@ -23205,8 +23390,8 @@ F: drivers/pwm/pwm-xilinx.c F: include/clocksource/timer-xilinx.h XILINX SD-FEC IP CORES -M: Derek Kiernan -M: Dragan Cvetic +M: Derek Kiernan +M: Dragan Cvetic S: Maintained F: Documentation/devicetree/bindings/misc/xlnx,sd-fec.txt F: Documentation/misc-devices/xilinx_sdfec.rst @@ -23222,7 +23407,6 @@ S: Maintained F: drivers/tty/serial/uartlite.c XILINX VIDEO IP CORES -M: Hyun Kwon M: Laurent Pinchart L: linux-media@vger.kernel.org S: Supported @@ -23236,8 +23420,10 @@ M: Srinivas Neeli R: Shubhrajyoti Datta R: Michal Simek S: Maintained +F: Documentation/devicetree/bindings/watchdog/xlnx,versal-wwdt.yaml F: Documentation/devicetree/bindings/watchdog/xlnx,xps-timebase-wdt.yaml F: drivers/watchdog/of_xilinx_wdt.c +F: drivers/watchdog/xilinx_wwdt.c XILINX XDMA DRIVER M: Lizhi Hou @@ -23251,7 +23437,6 @@ F: include/linux/dma/amd_xdma.h F: include/linux/platform_data/amd_xdma.h XILINX ZYNQMP DPDMA DRIVER -M: Hyun Kwon M: Laurent Pinchart L: dmaengine@vger.kernel.org S: Supported @@ -23267,7 +23452,6 @@ F: Documentation/devicetree/bindings/memory-controllers/xlnx,zynqmp-ocmc-1.0.yam F: drivers/edac/zynqmp_edac.c XILINX ZYNQMP PSGTR PHY DRIVER -M: Anurag Kumar Vulisha M: Laurent Pinchart L: linux-kernel@vger.kernel.org S: Supported @@ -23276,7 +23460,7 @@ F: Documentation/devicetree/bindings/phy/xlnx,zynqmp-psgtr.yaml F: drivers/phy/xilinx/phy-zynqmp.c XILINX ZYNQMP SHA3 DRIVER -M: Harsha +M: Harsha S: Maintained F: drivers/crypto/xilinx/zynqmp-sha.c diff --git a/Makefile b/Makefile index b68b43c1907225428c34bc7b9022f6d8eb9416ce..658ec2b8aa749bfdde92f6997877c8daa82362be 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,8 @@ # SPDX-License-Identifier: GPL-2.0 VERSION = 6 -PATCHLEVEL = 4 +PATCHLEVEL = 5 SUBLEVEL = 0 -EXTRAVERSION = -rc7 +EXTRAVERSION = -rc2 NAME = Hurr durr I'ma ninja sloth # *DOCUMENTATION* @@ -38,6 +38,10 @@ __all: # descending is started. They are now explicitly listed as the # prepare rule. +this-makefile := $(lastword $(MAKEFILE_LIST)) +export abs_srctree := $(realpath $(dir $(this-makefile))) +export abs_objtree := $(CURDIR) + ifneq ($(sub_make_done),1) # Do not use make's built-in rules and variables @@ -185,20 +189,8 @@ $(if $(abs_objtree),, \ # $(realpath ...) resolves symlinks abs_objtree := $(realpath $(abs_objtree)) -else -abs_objtree := $(CURDIR) endif # ifneq ($(KBUILD_OUTPUT),) -ifeq ($(abs_objtree),$(CURDIR)) -# Suppress "Entering directory ..." unless we are changing the work directory. -MAKEFLAGS += --no-print-directory -else -need-sub-make := 1 -endif - -this-makefile := $(lastword $(MAKEFILE_LIST)) -abs_srctree := $(realpath $(dir $(this-makefile))) - ifneq ($(words $(subst :, ,$(abs_srctree))), 1) $(error source directory cannot contain spaces or colons) endif @@ -211,9 +203,25 @@ need-sub-make := 1 $(this-makefile): ; endif -export abs_srctree abs_objtree export sub_make_done := 1 +endif # sub_make_done + +ifeq ($(abs_objtree),$(CURDIR)) +# Suppress "Entering directory ..." if we are at the final work directory. +no-print-directory := --no-print-directory +else +# Recursion to show "Entering directory ..." +need-sub-make := 1 +endif + +ifeq ($(filter --no-print-directory, $(MAKEFLAGS)),) +# If --no-print-directory is unset, recurse once again to set it. +# You may end up recursing into __sub-make twice. This is needed due to the +# behavior change in GNU Make 4.4.1. +need-sub-make := 1 +endif + ifeq ($(need-sub-make),1) PHONY += $(MAKECMDGOALS) __sub-make @@ -223,18 +231,12 @@ $(filter-out $(this-makefile), $(MAKECMDGOALS)) __all: __sub-make # Invoke a second make in the output directory, passing relevant variables __sub-make: - $(Q)$(MAKE) -C $(abs_objtree) -f $(abs_srctree)/Makefile $(MAKECMDGOALS) + $(Q)$(MAKE) $(no-print-directory) -C $(abs_objtree) \ + -f $(abs_srctree)/Makefile $(MAKECMDGOALS) -endif # need-sub-make -endif # sub_make_done +else # need-sub-make # We process the rest of the Makefile if this is the final invocation of make -ifeq ($(need-sub-make),) - -# Do not print "Entering directory ...", -# but we want to display it when entering to the output directory -# so that IDEs/editors are able to understand relative filenames. -MAKEFLAGS += --no-print-directory ifeq ($(abs_srctree),$(abs_objtree)) # building in the source tree @@ -447,8 +449,7 @@ HOSTRUSTC = rustc HOSTPKG_CONFIG = pkg-config KBUILD_USERHOSTCFLAGS := -Wall -Wmissing-prototypes -Wstrict-prototypes \ - -O2 -fomit-frame-pointer -std=gnu11 \ - -Wdeclaration-after-statement + -O2 -fomit-frame-pointer -std=gnu11 KBUILD_USERCFLAGS := $(KBUILD_USERHOSTCFLAGS) $(USERCFLAGS) KBUILD_USERLDFLAGS := $(USERLDFLAGS) @@ -1012,9 +1013,6 @@ endif # arch Makefile may override CC so keep this after arch Makefile is included NOSTDINC_FLAGS += -nostdinc -# warn about C99 declaration after statement -KBUILD_CFLAGS += -Wdeclaration-after-statement - # Variable Length Arrays (VLAs) should not be used anywhere in the kernel KBUILD_CFLAGS += -Wvla @@ -1026,6 +1024,12 @@ KBUILD_CFLAGS += -Wno-pointer-sign # globally built with -Wcast-function-type. KBUILD_CFLAGS += $(call cc-option, -Wcast-function-type) +# To gain proper coverage for CONFIG_UBSAN_BOUNDS and CONFIG_FORTIFY_SOURCE, +# the kernel uses only C99 flexible arrays for dynamically sized trailing +# arrays. Enforce this for everything that may examine structure sizes and +# perform bounds checking. +KBUILD_CFLAGS += $(call cc-option, -fstrict-flex-arrays=3) + # disable stringop warnings in gcc 8+ KBUILD_CFLAGS += $(call cc-disable-warning, stringop-truncation) @@ -1193,28 +1197,12 @@ endif export KBUILD_VMLINUX_LIBS export KBUILD_LDS := arch/$(SRCARCH)/kernel/vmlinux.lds -# Recurse until adjust_autoksyms.sh is satisfied -PHONY += autoksyms_recursive ifdef CONFIG_TRIM_UNUSED_KSYMS # For the kernel to actually contain only the needed exported symbols, # we have to build modules as well to determine what those symbols are. -# (this can be evaluated only once include/config/auto.conf has been included) KBUILD_MODULES := 1 - -autoksyms_recursive: $(build-dir) modules.order - $(Q)$(CONFIG_SHELL) $(srctree)/scripts/adjust_autoksyms.sh \ - "$(MAKE) -f $(srctree)/Makefile autoksyms_recursive" endif -autoksyms_h := $(if $(CONFIG_TRIM_UNUSED_KSYMS), include/generated/autoksyms.h) - -quiet_cmd_autoksyms_h = GEN $@ - cmd_autoksyms_h = mkdir -p $(dir $@); \ - $(CONFIG_SHELL) $(srctree)/scripts/gen_autoksyms.sh $@ - -$(autoksyms_h): - $(call cmd,autoksyms_h) - # '$(AR) mPi' needs 'T' to workaround the bug of llvm-ar <= 14 quiet_cmd_ar_vmlinux.a = AR $@ cmd_ar_vmlinux.a = \ @@ -1223,7 +1211,7 @@ quiet_cmd_ar_vmlinux.a = AR $@ $(AR) mPiT $$($(AR) t $@ | sed -n 1p) $@ $$($(AR) t $@ | grep -F -f $(srctree)/scripts/head-object-list.txt) targets += vmlinux.a -vmlinux.a: $(KBUILD_VMLINUX_OBJS) scripts/head-object-list.txt autoksyms_recursive FORCE +vmlinux.a: $(KBUILD_VMLINUX_OBJS) scripts/head-object-list.txt FORCE $(call if_changed,ar_vmlinux.a) PHONY += vmlinux_o @@ -1279,7 +1267,7 @@ scripts: scripts_basic scripts_dtc PHONY += prepare archprepare archprepare: outputmakefile archheaders archscripts scripts include/config/kernel.release \ - asm-generic $(version_h) $(autoksyms_h) include/generated/utsrelease.h \ + asm-generic $(version_h) include/generated/utsrelease.h \ include/generated/compile.h include/generated/autoconf.h remove-stale-files prepare0: archprepare @@ -1561,6 +1549,8 @@ modules_sign_only := y endif endif +endif # CONFIG_MODULES + modinst_pre := ifneq ($(filter modules_install,$(MAKECMDGOALS)),) modinst_pre := __modinst_pre @@ -1571,18 +1561,18 @@ PHONY += __modinst_pre __modinst_pre: @rm -rf $(MODLIB)/kernel @rm -f $(MODLIB)/source - @mkdir -p $(MODLIB)/kernel + @mkdir -p $(MODLIB) +ifdef CONFIG_MODULES @ln -s $(abspath $(srctree)) $(MODLIB)/source @if [ ! $(objtree) -ef $(MODLIB)/build ]; then \ rm -f $(MODLIB)/build ; \ ln -s $(CURDIR) $(MODLIB)/build ; \ fi @sed 's:^\(.*\)\.o$$:kernel/\1.ko:' modules.order > $(MODLIB)/modules.order +endif @cp -f modules.builtin $(MODLIB)/ @cp -f $(objtree)/modules.builtin.modinfo $(MODLIB)/ -endif # CONFIG_MODULES - ### # Cleaning is done on three levels. # make clean Delete most generated files @@ -1924,6 +1914,13 @@ help: @echo ' clean - remove generated files in module directory only' @echo '' +__external_modules_error: + @echo >&2 '***' + @echo >&2 '*** The present kernel disabled CONFIG_MODULES.' + @echo >&2 '*** You cannot build or install external modules.' + @echo >&2 '***' + @false + endif # KBUILD_EXTMOD # --------------------------------------------------------------------------- @@ -1960,13 +1957,10 @@ else # CONFIG_MODULES # Modules not configured # --------------------------------------------------------------------------- -modules modules_install: - @echo >&2 '***' - @echo >&2 '*** The present kernel configuration has modules disabled.' - @echo >&2 '*** To use the module feature, please run "make menuconfig" etc.' - @echo >&2 '*** to enable CONFIG_MODULES.' - @echo >&2 '***' - @exit 1 +PHONY += __external_modules_error + +modules modules_install: __external_modules_error + @: KBUILD_MODULES := @@ -2039,7 +2033,7 @@ clean: $(clean-dirs) -o -name '*.dtb.S' -o -name '*.dtbo.S' \ -o -name '*.dt.yaml' \ -o -name '*.dwo' -o -name '*.lst' \ - -o -name '*.su' -o -name '*.mod' -o -name '*.usyms' \ + -o -name '*.su' -o -name '*.mod' \ -o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \ -o -name '*.lex.c' -o -name '*.tab.[ch]' \ -o -name '*.asn1.[ch]' \ diff --git a/arch/Kconfig b/arch/Kconfig index 205fd23e0cadaf6750648416a71aabda63e131f3..aff2746c8af28b6ca56e3335e063936cbf911e33 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -34,6 +34,29 @@ config ARCH_HAS_SUBPAGE_FAULTS config HOTPLUG_SMT bool +# Selected by HOTPLUG_CORE_SYNC_DEAD or HOTPLUG_CORE_SYNC_FULL +config HOTPLUG_CORE_SYNC + bool + +# Basic CPU dead synchronization selected by architecture +config HOTPLUG_CORE_SYNC_DEAD + bool + select HOTPLUG_CORE_SYNC + +# Full CPU synchronization with alive state selected by architecture +config HOTPLUG_CORE_SYNC_FULL + bool + select HOTPLUG_CORE_SYNC_DEAD if HOTPLUG_CPU + select HOTPLUG_CORE_SYNC + +config HOTPLUG_SPLIT_STARTUP + bool + select HOTPLUG_CORE_SYNC_FULL + +config HOTPLUG_PARALLEL + bool + select HOTPLUG_SPLIT_STARTUP + config GENERIC_ENTRY bool @@ -285,6 +308,9 @@ config ARCH_HAS_DMA_SET_UNCACHED config ARCH_HAS_DMA_CLEAR_UNCACHED bool +config ARCH_HAS_CPU_FINALIZE_INIT + bool + # Select if arch init_task must go in the __init_task_data section config ARCH_TASK_STRUCT_ON_STACK bool @@ -400,20 +426,14 @@ config HAVE_HARDLOCKUP_DETECTOR_PERF The arch chooses to use the generic perf-NMI-based hardlockup detector. Must define HAVE_PERF_EVENTS_NMI. -config HAVE_NMI_WATCHDOG - depends on HAVE_NMI - bool - help - The arch provides a low level NMI watchdog. It provides - asm/nmi.h, and defines its own arch_touch_nmi_watchdog(). - config HAVE_HARDLOCKUP_DETECTOR_ARCH bool - select HAVE_NMI_WATCHDOG help - The arch chooses to provide its own hardlockup detector, which is - a superset of the HAVE_NMI_WATCHDOG. It also conforms to config - interfaces and parameters provided by hardlockup detector subsystem. + The arch provides its own hardlockup detector implementation instead + of the generic ones. + + It uses the same command line parameters, and sysctl interface, + as the generic hardlockup detectors. config HAVE_PERF_REGS bool @@ -1188,13 +1208,6 @@ config COMPAT_32BIT_TIME config ARCH_NO_PREEMPT bool -config ARCH_EPHEMERAL_INODES - def_bool n - help - An arch should select this symbol if it doesn't keep track of inode - instances on its own, but instead relies on something else (e.g. the - host kernel for an UML kernel). - config ARCH_SUPPORTS_RT bool diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig index a5c2b1aa46b02edbea92c2fea1d76d0d7e4e887c..d6968d090d49a7b9abe3a8ec1a8f446910ed2447 100644 --- a/arch/alpha/Kconfig +++ b/arch/alpha/Kconfig @@ -30,6 +30,7 @@ config ALPHA select HAS_IOPORT select HAVE_ARCH_AUDITSYSCALL select HAVE_MOD_ARCH_SPECIFIC + select LOCK_MM_AND_FIND_VMA select MODULES_USE_ELF_RELA select ODD_RT_SIGACTION select OLD_SIGSUSPEND diff --git a/arch/alpha/include/asm/atomic.h b/arch/alpha/include/asm/atomic.h index f2861a43a61efc4fd0cb1d971f1a186cec13ca16..cbd9244571af038a9a2f31194e1a91b34cecc282 100644 --- a/arch/alpha/include/asm/atomic.h +++ b/arch/alpha/include/asm/atomic.h @@ -200,25 +200,6 @@ ATOMIC_OPS(xor, xor) #undef ATOMIC_OP_RETURN #undef ATOMIC_OP -#define arch_atomic64_cmpxchg(v, old, new) \ - (arch_cmpxchg(&((v)->counter), old, new)) -#define arch_atomic64_xchg(v, new) \ - (arch_xchg(&((v)->counter), new)) - -#define arch_atomic_cmpxchg(v, old, new) \ - (arch_cmpxchg(&((v)->counter), old, new)) -#define arch_atomic_xchg(v, new) \ - (arch_xchg(&((v)->counter), new)) - -/** - * arch_atomic_fetch_add_unless - add unless the number is a given value - * @v: pointer of type atomic_t - * @a: the amount to add to v... - * @u: ...unless v is equal to u. - * - * Atomically adds @a to @v, so long as it was not @u. - * Returns the old value of @v. - */ static __inline__ int arch_atomic_fetch_add_unless(atomic_t *v, int a, int u) { int c, new, old; @@ -242,15 +223,6 @@ static __inline__ int arch_atomic_fetch_add_unless(atomic_t *v, int a, int u) } #define arch_atomic_fetch_add_unless arch_atomic_fetch_add_unless -/** - * arch_atomic64_fetch_add_unless - add unless the number is a given value - * @v: pointer of type atomic64_t - * @a: the amount to add to v... - * @u: ...unless v is equal to u. - * - * Atomically adds @a to @v, so long as it was not @u. - * Returns the old value of @v. - */ static __inline__ s64 arch_atomic64_fetch_add_unless(atomic64_t *v, s64 a, s64 u) { s64 c, new, old; @@ -274,13 +246,6 @@ static __inline__ s64 arch_atomic64_fetch_add_unless(atomic64_t *v, s64 a, s64 u } #define arch_atomic64_fetch_add_unless arch_atomic64_fetch_add_unless -/* - * arch_atomic64_dec_if_positive - decrement by 1 if old value positive - * @v: pointer of type atomic_t - * - * The function returns the old value of *v minus 1, even if - * the atomic variable, v, was not decremented. - */ static inline s64 arch_atomic64_dec_if_positive(atomic64_t *v) { s64 old, tmp; diff --git a/arch/alpha/include/asm/bugs.h b/arch/alpha/include/asm/bugs.h deleted file mode 100644 index 78030d1c7e7e0210520a57200ecbde11a76c21e5..0000000000000000000000000000000000000000 --- a/arch/alpha/include/asm/bugs.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * include/asm-alpha/bugs.h - * - * Copyright (C) 1994 Linus Torvalds - */ - -/* - * This is included by init/main.c to check for architecture-dependent bugs. - * - * Needs: - * void check_bugs(void); - */ - -/* - * I don't know of any alpha bugs yet.. Nice chip - */ - -static void check_bugs(void) -{ -} diff --git a/arch/alpha/include/uapi/asm/socket.h b/arch/alpha/include/uapi/asm/socket.h index 739891b94136539a3a40fd6ceaab55c56f62cec7..e94f621903feed3a4b6cd5644a93d7c8c512a7cb 100644 --- a/arch/alpha/include/uapi/asm/socket.h +++ b/arch/alpha/include/uapi/asm/socket.h @@ -137,6 +137,9 @@ #define SO_RCVMARK 75 +#define SO_PASSPIDFD 76 +#define SO_PEERPIDFD 77 + #if !defined(__KERNEL__) #if __BITS_PER_LONG == 64 diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c index 2a9a877a0508371fdfd167c256c66ca16104916e..d98701ee36c6a82f4c7385720f26b2dc356d3a2e 100644 --- a/arch/alpha/kernel/osf_sys.c +++ b/arch/alpha/kernel/osf_sys.c @@ -1014,8 +1014,6 @@ SYSCALL_DEFINE2(osf_settimeofday, struct timeval32 __user *, tv, return do_sys_settimeofday64(tv ? &kts : NULL, tz ? &ktz : NULL); } -asmlinkage long sys_ni_posix_timers(void); - SYSCALL_DEFINE2(osf_utimes, const char __user *, filename, struct timeval32 __user *, tvs) { diff --git a/arch/alpha/kernel/setup.c b/arch/alpha/kernel/setup.c index 33bf3a62700270ac732f3b537c0992515041f946..b650ff1cb022eee9865c2890e223067de8e9a309 100644 --- a/arch/alpha/kernel/setup.c +++ b/arch/alpha/kernel/setup.c @@ -658,7 +658,7 @@ setup_arch(char **cmdline_p) #endif /* Default root filesystem to sda2. */ - ROOT_DEV = Root_SDA2; + ROOT_DEV = MKDEV(SCSI_DISK0_MAJOR, 2); #ifdef CONFIG_EISA /* FIXME: only set this when we actually have EISA in this box? */ diff --git a/arch/alpha/kernel/syscalls/syscall.tbl b/arch/alpha/kernel/syscalls/syscall.tbl index 8ebacf37a8cf4ac3050e3e2ae821245d7074cdea..1f13995d00d7b4b7cd773b419406b6f24e413038 100644 --- a/arch/alpha/kernel/syscalls/syscall.tbl +++ b/arch/alpha/kernel/syscalls/syscall.tbl @@ -490,3 +490,4 @@ 558 common process_mrelease sys_process_mrelease 559 common futex_waitv sys_futex_waitv 560 common set_mempolicy_home_node sys_ni_syscall +561 common cachestat sys_cachestat diff --git a/arch/alpha/mm/fault.c b/arch/alpha/mm/fault.c index 7b01ae4f3bc6c7ab53dfb0c219c6fd75e2ffdf36..8c9850437e674451576c27388e0f6fe7b8780758 100644 --- a/arch/alpha/mm/fault.c +++ b/arch/alpha/mm/fault.c @@ -119,20 +119,12 @@ do_page_fault(unsigned long address, unsigned long mmcsr, flags |= FAULT_FLAG_USER; perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address); retry: - mmap_read_lock(mm); - vma = find_vma(mm, address); + vma = lock_mm_and_find_vma(mm, address, regs); if (!vma) - goto bad_area; - if (vma->vm_start <= address) - goto good_area; - if (!(vma->vm_flags & VM_GROWSDOWN)) - goto bad_area; - if (expand_stack(vma, address)) - goto bad_area; + goto bad_area_nosemaphore; /* Ok, we have a good vm_area for this memory access, so we can handle it. */ - good_area: si_code = SEGV_ACCERR; if (cause < 0) { if (!(vma->vm_flags & VM_EXEC)) @@ -192,6 +184,7 @@ do_page_fault(unsigned long address, unsigned long mmcsr, bad_area: mmap_read_unlock(mm); + bad_area_nosemaphore: if (user_mode(regs)) goto do_sigsegv; diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig index ab6d701365bb00c44420d397aa5115555e6bb4d9..96cf8720bb93910d3171c2fbe89d127166bbab23 100644 --- a/arch/arc/Kconfig +++ b/arch/arc/Kconfig @@ -41,6 +41,7 @@ config ARC select HAVE_PERF_EVENTS select HAVE_SYSCALL_TRACEPOINTS select IRQ_DOMAIN + select LOCK_MM_AND_FIND_VMA select MODULES_USE_ELF_RELA select OF select OF_EARLY_FLATTREE diff --git a/arch/arc/configs/axs103_smp_defconfig b/arch/arc/configs/axs103_smp_defconfig index 2f336d99a8cf35218163942edf2217c0ae5455af..07c89281c2e3a9848a34a7b67248259db3fa178d 100644 --- a/arch/arc/configs/axs103_smp_defconfig +++ b/arch/arc/configs/axs103_smp_defconfig @@ -13,7 +13,6 @@ CONFIG_EMBEDDED=y CONFIG_PERF_EVENTS=y # CONFIG_VM_EVENT_COUNTERS is not set # CONFIG_COMPAT_BRK is not set -CONFIG_SLAB=y CONFIG_MODULES=y CONFIG_MODULE_FORCE_LOAD=y CONFIG_MODULE_UNLOAD=y diff --git a/arch/arc/configs/haps_hs_defconfig b/arch/arc/configs/haps_hs_defconfig index 899b2fd5c71d129dea5d8267950271b30208fd3d..8c3ed5d6e6c35100d01b00b1b69703cfccfa4472 100644 --- a/arch/arc/configs/haps_hs_defconfig +++ b/arch/arc/configs/haps_hs_defconfig @@ -14,7 +14,6 @@ CONFIG_BLK_DEV_INITRD=y CONFIG_EXPERT=y CONFIG_PERF_EVENTS=y # CONFIG_COMPAT_BRK is not set -CONFIG_SLAB=y CONFIG_ARC_BUILTIN_DTB_NAME="haps_hs" CONFIG_MODULES=y # CONFIG_BLK_DEV_BSG is not set diff --git a/arch/arc/configs/haps_hs_smp_defconfig b/arch/arc/configs/haps_hs_smp_defconfig index 0d32aac8069f26d2da062c849af17c6be3d3dc14..61107e8bac336d675367aa30b14dddc7b52aae65 100644 --- a/arch/arc/configs/haps_hs_smp_defconfig +++ b/arch/arc/configs/haps_hs_smp_defconfig @@ -15,7 +15,6 @@ CONFIG_EMBEDDED=y CONFIG_PERF_EVENTS=y # CONFIG_VM_EVENT_COUNTERS is not set # CONFIG_COMPAT_BRK is not set -CONFIG_SLAB=y CONFIG_SMP=y CONFIG_ARC_BUILTIN_DTB_NAME="haps_hs_idu" CONFIG_KPROBES=y diff --git a/arch/arc/configs/hsdk_defconfig b/arch/arc/configs/hsdk_defconfig index d18378d2c2a63e37e6575651d7aaec8cdebfc3e0..4ee2a1507b57f9e66c2ac44bd3e7f5ecdff55f64 100644 --- a/arch/arc/configs/hsdk_defconfig +++ b/arch/arc/configs/hsdk_defconfig @@ -13,7 +13,6 @@ CONFIG_EMBEDDED=y CONFIG_PERF_EVENTS=y # CONFIG_VM_EVENT_COUNTERS is not set # CONFIG_COMPAT_BRK is not set -CONFIG_SLAB=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y CONFIG_ARC_SOC_HSDK=y diff --git a/arch/arc/configs/tb10x_defconfig b/arch/arc/configs/tb10x_defconfig index 6f0d2be9d926cee39522744799684be3d25b803c..941bbadd6bf2c33c2d2c31e8fad1fe19523a6947 100644 --- a/arch/arc/configs/tb10x_defconfig +++ b/arch/arc/configs/tb10x_defconfig @@ -19,7 +19,6 @@ CONFIG_KALLSYMS_ALL=y CONFIG_EMBEDDED=y # CONFIG_COMPAT_BRK is not set CONFIG_ISA_ARCOMPACT=y -CONFIG_SLAB=y CONFIG_MODULES=y CONFIG_MODULE_FORCE_LOAD=y CONFIG_MODULE_UNLOAD=y diff --git a/arch/arc/include/asm/atomic-spinlock.h b/arch/arc/include/asm/atomic-spinlock.h index 2c830347bfb4e36059400cb7f37a1489c868dfeb..89d12a60f84c0c69692e6f67bf4fb3e86b17330b 100644 --- a/arch/arc/include/asm/atomic-spinlock.h +++ b/arch/arc/include/asm/atomic-spinlock.h @@ -81,6 +81,11 @@ static inline int arch_atomic_fetch_##op(int i, atomic_t *v) \ ATOMIC_OPS(add, +=, add) ATOMIC_OPS(sub, -=, sub) +#define arch_atomic_fetch_add arch_atomic_fetch_add +#define arch_atomic_fetch_sub arch_atomic_fetch_sub +#define arch_atomic_add_return arch_atomic_add_return +#define arch_atomic_sub_return arch_atomic_sub_return + #undef ATOMIC_OPS #define ATOMIC_OPS(op, c_op, asm_op) \ ATOMIC_OP(op, c_op, asm_op) \ @@ -92,7 +97,11 @@ ATOMIC_OPS(or, |=, or) ATOMIC_OPS(xor, ^=, xor) #define arch_atomic_andnot arch_atomic_andnot + +#define arch_atomic_fetch_and arch_atomic_fetch_and #define arch_atomic_fetch_andnot arch_atomic_fetch_andnot +#define arch_atomic_fetch_or arch_atomic_fetch_or +#define arch_atomic_fetch_xor arch_atomic_fetch_xor #undef ATOMIC_OPS #undef ATOMIC_FETCH_OP diff --git a/arch/arc/include/asm/atomic.h b/arch/arc/include/asm/atomic.h index 52ee51e1ff7c27f795ec3fe17314a30878e7bb28..592d7fffc223c923f4d63ccf27ad01fb9dc56e49 100644 --- a/arch/arc/include/asm/atomic.h +++ b/arch/arc/include/asm/atomic.h @@ -22,30 +22,6 @@ #include #endif -#define arch_atomic_cmpxchg(v, o, n) \ -({ \ - arch_cmpxchg(&((v)->counter), (o), (n)); \ -}) - -#ifdef arch_cmpxchg_relaxed -#define arch_atomic_cmpxchg_relaxed(v, o, n) \ -({ \ - arch_cmpxchg_relaxed(&((v)->counter), (o), (n)); \ -}) -#endif - -#define arch_atomic_xchg(v, n) \ -({ \ - arch_xchg(&((v)->counter), (n)); \ -}) - -#ifdef arch_xchg_relaxed -#define arch_atomic_xchg_relaxed(v, n) \ -({ \ - arch_xchg_relaxed(&((v)->counter), (n)); \ -}) -#endif - /* * 64-bit atomics */ diff --git a/arch/arc/include/asm/atomic64-arcv2.h b/arch/arc/include/asm/atomic64-arcv2.h index c5a8010fdc97ddb0145dc02729aa37f74140a3cd..6b6db981967aea95806a1f8de8922dfc6317a5af 100644 --- a/arch/arc/include/asm/atomic64-arcv2.h +++ b/arch/arc/include/asm/atomic64-arcv2.h @@ -159,6 +159,7 @@ arch_atomic64_cmpxchg(atomic64_t *ptr, s64 expected, s64 new) return prev; } +#define arch_atomic64_cmpxchg arch_atomic64_cmpxchg static inline s64 arch_atomic64_xchg(atomic64_t *ptr, s64 new) { @@ -179,14 +180,7 @@ static inline s64 arch_atomic64_xchg(atomic64_t *ptr, s64 new) return prev; } - -/** - * arch_atomic64_dec_if_positive - decrement by 1 if old value positive - * @v: pointer of type atomic64_t - * - * The function returns the old value of *v minus 1, even if - * the atomic variable, v, was not decremented. - */ +#define arch_atomic64_xchg arch_atomic64_xchg static inline s64 arch_atomic64_dec_if_positive(atomic64_t *v) { @@ -212,15 +206,6 @@ static inline s64 arch_atomic64_dec_if_positive(atomic64_t *v) } #define arch_atomic64_dec_if_positive arch_atomic64_dec_if_positive -/** - * arch_atomic64_fetch_add_unless - add unless the number is a given value - * @v: pointer of type atomic64_t - * @a: the amount to add to v... - * @u: ...unless v is equal to u. - * - * Atomically adds @a to @v, if it was not @u. - * Returns the old value of @v - */ static inline s64 arch_atomic64_fetch_add_unless(atomic64_t *v, s64 a, s64 u) { s64 old, temp; diff --git a/arch/arc/include/asm/linkage.h b/arch/arc/include/asm/linkage.h index c9434ff3aa4ce63fa0ab1177e9f8e60c74e3b33f..8a3fb71e9cfad2a31c92218611b6a7256e67e2f5 100644 --- a/arch/arc/include/asm/linkage.h +++ b/arch/arc/include/asm/linkage.h @@ -8,6 +8,10 @@ #include +#define ASM_NL ` /* use '`' to mark new line in macro */ +#define __ALIGN .align 4 +#define __ALIGN_STR __stringify(__ALIGN) + #ifdef __ASSEMBLY__ .macro ST2 e, o, off @@ -28,10 +32,6 @@ #endif .endm -#define ASM_NL ` /* use '`' to mark new line in macro */ -#define __ALIGN .align 4 -#define __ALIGN_STR __stringify(__ALIGN) - /* annotation for data we want in DCCM - if enabled in .config */ .macro ARCFP_DATA nm #ifdef CONFIG_ARC_HAS_DCCM diff --git a/arch/arc/mm/fault.c b/arch/arc/mm/fault.c index 5ca59a482632a880f0a40d31c44d9b1159581b85..f59e722d147f91972ac8cf42b1f77d1a12cca80b 100644 --- a/arch/arc/mm/fault.c +++ b/arch/arc/mm/fault.c @@ -113,15 +113,9 @@ void do_page_fault(unsigned long address, struct pt_regs *regs) perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address); retry: - mmap_read_lock(mm); - - vma = find_vma(mm, address); + vma = lock_mm_and_find_vma(mm, address, regs); if (!vma) - goto bad_area; - if (unlikely(address < vma->vm_start)) { - if (!(vma->vm_flags & VM_GROWSDOWN) || expand_stack(vma, address)) - goto bad_area; - } + goto bad_area_nosemaphore; /* * vm_area is good, now check permissions for this memory access @@ -161,6 +155,7 @@ void do_page_fault(unsigned long address, struct pt_regs *regs) bad_area: mmap_read_unlock(mm); +bad_area_nosemaphore: /* * Major/minor page fault accounting * (in case of retry we only land here once) diff --git a/arch/arc/mm/init.c b/arch/arc/mm/init.c index 2b89b6c538019cb2008216f4fe5a23ea1f437faa..9f64d729c9f87cc70c9c140439591f323b9bb60f 100644 --- a/arch/arc/mm/init.c +++ b/arch/arc/mm/init.c @@ -87,7 +87,7 @@ void __init setup_arch_memory(void) setup_initial_init_mm(_text, _etext, _edata, _end); /* first page of system - kernel .vector starts here */ - min_low_pfn = virt_to_pfn(CONFIG_LINUX_RAM_BASE); + min_low_pfn = virt_to_pfn((void *)CONFIG_LINUX_RAM_BASE); /* Last usable page of low mem */ max_low_pfn = max_pfn = PFN_DOWN(low_mem_start + low_mem_sz); diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 0fb4b218f6658b72f659bd7952099371886363f0..7a27550ff3c1f81784e79d5202d492a9355a8329 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -5,6 +5,7 @@ config ARM select ARCH_32BIT_OFF_T select ARCH_CORRECT_STACKTRACE_ON_KRETPROBE if HAVE_KRETPROBES && FRAME_POINTER && !ARM_UNWIND select ARCH_HAS_BINFMT_FLAT + select ARCH_HAS_CPU_FINALIZE_INIT if MMU select ARCH_HAS_CURRENT_STACK_POINTER select ARCH_HAS_DEBUG_VIRTUAL if MMU select ARCH_HAS_DMA_WRITE_COMBINE if !ARM_DMA_MEM_BUFFERABLE @@ -124,7 +125,9 @@ config ARM select HAVE_SYSCALL_TRACEPOINTS select HAVE_UID16 select HAVE_VIRT_CPU_ACCOUNTING_GEN + select HOTPLUG_CORE_SYNC_DEAD if HOTPLUG_CPU select IRQ_FORCED_THREADING + select LOCK_MM_AND_FIND_VMA select MODULES_USE_ELF_REL select NEED_DMA_MAP_STATE select OF_EARLY_FLATTREE if OF @@ -1460,6 +1463,9 @@ config USE_OF help Include support for flattened device tree machine descriptions. +config ARCH_WANT_FLAT_DTB_INSTALL + def_bool y + config ATAGS bool "Support for the traditional ATAGS boot data passing" default y @@ -1780,7 +1786,7 @@ config VFP Say Y to include VFP support code in the kernel. This is needed if your hardware includes a VFP unit. - Please see for + Please see for release notes and additional status information. Say N if your target does not have VFP hardware. diff --git a/arch/arm/boot/compressed/atags_to_fdt.c b/arch/arm/boot/compressed/atags_to_fdt.c index 1feb6b0f7a1fda694fb5e21bb9d147cb1c558f01..627752f18661bd0f0a0360065da9b29975886bfc 100644 --- a/arch/arm/boot/compressed/atags_to_fdt.c +++ b/arch/arm/boot/compressed/atags_to_fdt.c @@ -2,6 +2,7 @@ #include #include #include +#include "misc.h" #if defined(CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND) #define do_extend_cmdline 1 diff --git a/arch/arm/boot/compressed/fdt_check_mem_start.c b/arch/arm/boot/compressed/fdt_check_mem_start.c index 9291a2661bdfe57f6a9118baefa9132f6aaa9973..aa856567fd33f9814f2833796ab468f8dd1f3bfc 100644 --- a/arch/arm/boot/compressed/fdt_check_mem_start.c +++ b/arch/arm/boot/compressed/fdt_check_mem_start.c @@ -3,6 +3,7 @@ #include #include #include +#include "misc.h" static const void *get_prop(const void *fdt, const char *node_path, const char *property, int minlen) diff --git a/arch/arm/boot/compressed/misc.c b/arch/arm/boot/compressed/misc.c index abfed1aa2baa81381f3e6d73cbb8aa65fdd384e8..6b4baa6a9a50a1394c8b112e390b1086eaebcc29 100644 --- a/arch/arm/boot/compressed/misc.c +++ b/arch/arm/boot/compressed/misc.c @@ -103,9 +103,6 @@ static void putstr(const char *ptr) /* * gzip declarations */ -extern char input_data[]; -extern char input_data_end[]; - unsigned char *output_data; unsigned long free_mem_ptr; @@ -131,9 +128,6 @@ asmlinkage void __div0(void) error("Attempting division by 0!"); } -extern int do_decompress(u8 *input, int len, u8 *output, void (*error)(char *x)); - - void decompress_kernel(unsigned long output_start, unsigned long free_mem_ptr_p, unsigned long free_mem_ptr_end_p, diff --git a/arch/arm/boot/compressed/misc.h b/arch/arm/boot/compressed/misc.h index c958dccd1d97c1b833b157e85d11aff4f2909acf..6da00a26ac089edd6bc1cf6911e87abd86c1f772 100644 --- a/arch/arm/boot/compressed/misc.h +++ b/arch/arm/boot/compressed/misc.h @@ -6,5 +6,16 @@ void error(char *x) __noreturn; extern unsigned long free_mem_ptr; extern unsigned long free_mem_end_ptr; +void __div0(void); +void +decompress_kernel(unsigned long output_start, unsigned long free_mem_ptr_p, + unsigned long free_mem_ptr_end_p, int arch_id); +void fortify_panic(const char *name); +int atags_to_fdt(void *atag_list, void *fdt, int total_space); +uint32_t fdt_check_mem_start(uint32_t mem_start, const void *fdt); +int do_decompress(u8 *input, int len, u8 *output, void (*error)(char *x)); + +extern char input_data[]; +extern char input_data_end[]; #endif diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 59829fc903152279cc3c670361c88d75cbb4b9a3..efe38eb25301648f231ced32c0e5dc02c68daa90 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -1,1672 +1,41 @@ # SPDX-License-Identifier: GPL-2.0 -dtb-$(CONFIG_ARCH_ALPINE) += \ - alpine-db.dtb -dtb-$(CONFIG_MACH_ARTPEC6) += \ - artpec6-devboard.dtb -dtb-$(CONFIG_MACH_ASM9260) += \ - alphascale-asm9260-devkit.dtb -# Keep at91 dtb files sorted alphabetically for each SoC -dtb-$(CONFIG_SOC_AT91RM9200) += \ - at91rm9200ek.dtb \ - mpa1600.dtb -dtb-$(CONFIG_SOC_AT91SAM9) += \ - animeo_ip.dtb \ - at91-qil_a9260.dtb \ - aks-cdu.dtb \ - ethernut5.dtb \ - evk-pro3.dtb \ - tny_a9260.dtb \ - usb_a9260.dtb \ - at91sam9260ek.dtb \ - at91sam9261ek.dtb \ - at91sam9263ek.dtb \ - at91-sam9_l9260.dtb \ - tny_a9263.dtb \ - usb_a9263.dtb \ - at91-foxg20.dtb \ - at91-kizbox.dtb \ - at91-lmu5000.dtb \ - at91sam9g20ek.dtb \ - at91sam9g20ek_2mmc.dtb \ - tny_a9g20.dtb \ - usb_a9g20.dtb \ - usb_a9g20_lpw.dtb \ - at91sam9m10g45ek.dtb \ - pm9g45.dtb \ - at91sam9n12ek.dtb \ - at91sam9rlek.dtb \ - at91-ariag25.dtb \ - at91-ariettag25.dtb \ - at91-cosino_mega2560.dtb \ - at91-kizboxmini-base.dtb \ - at91-kizboxmini-mb.dtb \ - at91-kizboxmini-rd.dtb \ - at91-q5xr5.dtb \ - at91-smartkiz.dtb \ - at91-wb45n.dtb \ - at91sam9g15ek.dtb \ - at91sam9g25-gardena-smart-gateway.dtb \ - at91sam9g25ek.dtb \ - at91sam9g35ek.dtb \ - at91sam9x25ek.dtb \ - at91sam9x35ek.dtb -dtb-$(CONFIG_SOC_SAM9X60) += \ - at91-sam9x60_curiosity.dtb \ - at91-sam9x60ek.dtb -dtb-$(CONFIG_SOC_SAM_V7) += \ - at91-kizbox2-2.dtb \ - at91-kizbox3-hs.dtb \ - at91-nattis-2-natte-2.dtb \ - at91-sama5d27_som1_ek.dtb \ - at91-sama5d27_wlsom1_ek.dtb \ - at91-sama5d2_icp.dtb \ - at91-sama5d2_ptc_ek.dtb \ - at91-sama5d2_xplained.dtb \ - at91-sama5d3_eds.dtb \ - at91-sama5d3_ksz9477_evb.dtb \ - at91-sama5d3_xplained.dtb \ - at91-dvk_som60.dtb \ - at91-gatwick.dtb \ - at91-tse850-3.dtb \ - at91-wb50n.dtb \ - sama5d31ek.dtb \ - sama5d33ek.dtb \ - sama5d34ek.dtb \ - sama5d35ek.dtb \ - sama5d36ek.dtb \ - sama5d36ek_cmp.dtb \ - at91-sama5d4_ma5d4evk.dtb \ - at91-sama5d4_xplained.dtb \ - at91-sama5d4ek.dtb \ - at91-vinco.dtb -dtb-$(CONFIG_SOC_SAMA7G5) += \ - at91-sama7g5ek.dtb -dtb-$(CONFIG_SOC_SP7021) += \ - sunplus-sp7021-demo-v3.dtb -dtb-$(CONFIG_ARCH_AXXIA) += \ - axm5516-amarillo.dtb -dtb-$(CONFIG_ARCH_BCM2835) += \ - bcm2835-rpi-b.dtb \ - bcm2835-rpi-a.dtb \ - bcm2835-rpi-b-rev2.dtb \ - bcm2835-rpi-b-plus.dtb \ - bcm2835-rpi-a-plus.dtb \ - bcm2835-rpi-cm1-io1.dtb \ - bcm2836-rpi-2-b.dtb \ - bcm2837-rpi-3-a-plus.dtb \ - bcm2837-rpi-3-b.dtb \ - bcm2837-rpi-3-b-plus.dtb \ - bcm2837-rpi-cm3-io3.dtb \ - bcm2837-rpi-zero-2-w.dtb \ - bcm2711-rpi-400.dtb \ - bcm2711-rpi-4-b.dtb \ - bcm2711-rpi-cm4-io.dtb \ - bcm2835-rpi-zero.dtb \ - bcm2835-rpi-zero-w.dtb -dtb-$(CONFIG_ARCH_BCM_5301X) += \ - bcm4708-asus-rt-ac56u.dtb \ - bcm4708-asus-rt-ac68u.dtb \ - bcm4708-buffalo-wzr-1750dhp.dtb \ - bcm4708-buffalo-wzr-1166dhp.dtb \ - bcm4708-buffalo-wzr-1166dhp2.dtb \ - bcm4708-linksys-ea6300-v1.dtb \ - bcm4708-linksys-ea6500-v2.dtb \ - bcm4708-luxul-xap-1510.dtb \ - bcm4708-luxul-xwc-1000.dtb \ - bcm4708-netgear-r6250.dtb \ - bcm4708-netgear-r6300-v2.dtb \ - bcm4708-smartrg-sr400ac.dtb \ - bcm47081-asus-rt-n18u.dtb \ - bcm47081-buffalo-wzr-600dhp2.dtb \ - bcm47081-buffalo-wzr-900dhp.dtb \ - bcm47081-luxul-xap-1410.dtb \ - bcm47081-luxul-xwr-1200.dtb \ - bcm47081-tplink-archer-c5-v2.dtb \ - bcm4709-asus-rt-ac87u.dtb \ - bcm4709-buffalo-wxr-1900dhp.dtb \ - bcm4709-linksys-ea9200.dtb \ - bcm4709-netgear-r7000.dtb \ - bcm4709-netgear-r8000.dtb \ - bcm4709-tplink-archer-c9-v1.dtb \ - bcm47094-asus-rt-ac88u.dtb \ - bcm47094-dlink-dir-885l.dtb \ - bcm47094-dlink-dir-890l.dtb \ - bcm47094-linksys-panamera.dtb \ - bcm47094-luxul-abr-4500.dtb \ - bcm47094-luxul-xap-1610.dtb \ - bcm47094-luxul-xbr-4500.dtb \ - bcm47094-luxul-xwc-2000.dtb \ - bcm47094-luxul-xwr-3100.dtb \ - bcm47094-luxul-xwr-3150-v1.dtb \ - bcm47094-netgear-r8500.dtb \ - bcm47094-phicomm-k3.dtb \ - bcm53015-meraki-mr26.dtb \ - bcm53016-dlink-dwl-8610ap.dtb \ - bcm53016-meraki-mr32.dtb \ - bcm94708.dtb \ - bcm94709.dtb \ - bcm953012er.dtb \ - bcm953012hr.dtb \ - bcm953012k.dtb -dtb-$(CONFIG_ARCH_BCM_53573) += \ - bcm47189-luxul-xap-1440.dtb \ - bcm47189-luxul-xap-810.dtb \ - bcm47189-tenda-ac9.dtb \ - bcm947189acdbmr.dtb -dtb-$(CONFIG_ARCH_BCM_CYGNUS) += \ - bcm911360_entphn.dtb \ - bcm911360k.dtb \ - bcm958300k.dtb \ - bcm958305k.dtb -dtb-$(CONFIG_ARCH_BCM_HR2) += \ - bcm53340-ubnt-unifi-switch8.dtb -dtb-$(CONFIG_ARCH_BCM_MOBILE) += \ - bcm28155-ap.dtb \ - bcm21664-garnet.dtb \ - bcm23550-sparrow.dtb -dtb-$(CONFIG_ARCH_BCM_NSP) += \ - bcm958522er.dtb \ - bcm958525er.dtb \ - bcm958525xmc.dtb \ - bcm958622hr.dtb \ - bcm958623hr.dtb \ - bcm958625-meraki-mx64.dtb \ - bcm958625-meraki-mx64-a0.dtb \ - bcm958625-meraki-mx64w.dtb \ - bcm958625-meraki-mx64w-a0.dtb \ - bcm958625-meraki-mx65.dtb \ - bcm958625-meraki-mx65w.dtb \ - bcm958625hr.dtb \ - bcm988312hr.dtb \ - bcm958625k.dtb -dtb-$(CONFIG_ARCH_BERLIN) += \ - berlin2-sony-nsz-gs7.dtb \ - berlin2cd-google-chromecast.dtb \ - berlin2cd-valve-steamlink.dtb \ - berlin2q-marvell-dmp.dtb -dtb-$(CONFIG_ARCH_BRCMSTB) += \ - bcm7445-bcm97445svmb.dtb -dtb-$(CONFIG_ARCH_BCMBCA) += \ - bcm947622.dtb \ - bcm963138.dtb \ - bcm963138dvt.dtb \ - bcm963148.dtb \ - bcm963178.dtb \ - bcm96756.dtb \ - bcm96846.dtb \ - bcm96855.dtb \ - bcm96878.dtb -dtb-$(CONFIG_ARCH_CLPS711X) += \ - ep7211-edb7211.dtb -dtb-$(CONFIG_ARCH_DAVINCI) += \ - da850-lcdk.dtb \ - da850-enbw-cmc.dtb \ - da850-evm.dtb \ - da850-lego-ev3.dtb -dtb-$(CONFIG_ARCH_DIGICOLOR) += \ - cx92755_equinox.dtb -dtb-$(CONFIG_ARCH_AIROHA) += \ - en7523-evb.dtb -dtb-$(CONFIG_ARCH_EXYNOS3) += \ - exynos3250-artik5-eval.dtb \ - exynos3250-monk.dtb \ - exynos3250-rinato.dtb -dtb-$(CONFIG_ARCH_EXYNOS4) += \ - exynos4210-i9100.dtb \ - exynos4210-origen.dtb \ - exynos4210-smdkv310.dtb \ - exynos4210-trats.dtb \ - exynos4210-universal_c210.dtb \ - exynos4412-i9300.dtb \ - exynos4412-i9305.dtb \ - exynos4412-itop-elite.dtb \ - exynos4412-n710x.dtb \ - exynos4412-odroidu3.dtb \ - exynos4412-odroidx.dtb \ - exynos4412-odroidx2.dtb \ - exynos4412-origen.dtb \ - exynos4412-p4note-n8010.dtb \ - exynos4412-smdk4412.dtb \ - exynos4412-tiny4412.dtb \ - exynos4412-trats2.dtb -dtb-$(CONFIG_ARCH_EXYNOS5) += \ - exynos5250-arndale.dtb \ - exynos5250-smdk5250.dtb \ - exynos5250-snow.dtb \ - exynos5250-snow-rev5.dtb \ - exynos5250-spring.dtb \ - exynos5260-xyref5260.dtb \ - exynos5410-odroidxu.dtb \ - exynos5410-smdk5410.dtb \ - exynos5420-arndale-octa.dtb \ - exynos5420-peach-pit.dtb \ - exynos5420-smdk5420.dtb \ - exynos5420-chagall-wifi.dtb \ - exynos5420-klimt-wifi.dtb \ - exynos5422-odroidhc1.dtb \ - exynos5422-odroidxu3.dtb \ - exynos5422-odroidxu3-lite.dtb \ - exynos5422-odroidxu4.dtb \ - exynos5422-samsung-k3g.dtb \ - exynos5800-peach-pi.dtb -dtb-$(CONFIG_ARCH_GEMINI) += \ - gemini-dlink-dir-685.dtb \ - gemini-dlink-dns-313.dtb \ - gemini-nas4220b.dtb \ - gemini-ns2502.dtb \ - gemini-rut1xx.dtb \ - gemini-sl93512r.dtb \ - gemini-sq201.dtb \ - gemini-ssi1328.dtb \ - gemini-wbd111.dtb \ - gemini-wbd222.dtb -dtb-$(CONFIG_ARCH_HI3xxx) += \ - hi3620-hi4511.dtb -dtb-$(CONFIG_ARCH_HIGHBANK) += \ - highbank.dtb \ - ecx-2000.dtb -dtb-$(CONFIG_ARCH_HIP01) += \ - hip01-ca9x2.dtb -dtb-$(CONFIG_ARCH_HIP04) += \ - hip04-d01.dtb -dtb-$(CONFIG_ARCH_HISI) += \ - hi3519-demb.dtb -dtb-$(CONFIG_ARCH_HIX5HD2) += \ - hisi-x5hd2-dkb.dtb -dtb-$(CONFIG_ARCH_HPE_GXP) += \ - hpe-bmc-dl360gen10.dtb -dtb-$(CONFIG_ARCH_INTEGRATOR) += \ - integratorap.dtb \ - integratorap-im-pd1.dtb \ - integratorcp.dtb -dtb-$(CONFIG_ARCH_IXP4XX) += \ - intel-ixp42x-linksys-nslu2.dtb \ - intel-ixp42x-linksys-wrv54g.dtb \ - intel-ixp42x-freecom-fsg-3.dtb \ - intel-ixp42x-welltech-epbx100.dtb \ - intel-ixp42x-ixdp425.dtb \ - intel-ixp43x-kixrp435.dtb \ - intel-ixp46x-ixdp465.dtb \ - intel-ixp42x-adi-coyote.dtb \ - intel-ixp42x-ixdpg425.dtb \ - intel-ixp42x-goramo-multilink.dtb \ - intel-ixp42x-iomega-nas100d.dtb \ - intel-ixp42x-dlink-dsm-g600.dtb \ - intel-ixp42x-gateworks-gw2348.dtb \ - intel-ixp43x-gateworks-gw2358.dtb \ - intel-ixp42x-netgear-wg302v1.dtb \ - intel-ixp42x-arcom-vulcan.dtb \ - intel-ixp42x-gateway-7001.dtb -dtb-$(CONFIG_ARCH_KEYSTONE) += \ - keystone-k2hk-evm.dtb \ - keystone-k2l-evm.dtb \ - keystone-k2e-evm.dtb \ - keystone-k2g-evm.dtb \ - keystone-k2g-ice.dtb -dtb-$(CONFIG_MACH_KIRKWOOD) += \ - kirkwood-b3.dtb \ - kirkwood-blackarmor-nas220.dtb \ - kirkwood-c200-v1.dtb \ - kirkwood-cloudbox.dtb \ - kirkwood-d2net.dtb \ - kirkwood-db-88f6281.dtb \ - kirkwood-db-88f6282.dtb \ - kirkwood-dir665.dtb \ - kirkwood-dns320.dtb \ - kirkwood-dns325.dtb \ - kirkwood-dockstar.dtb \ - kirkwood-dreamplug.dtb \ - kirkwood-ds109.dtb \ - kirkwood-ds110jv10.dtb \ - kirkwood-ds111.dtb \ - kirkwood-ds112.dtb \ - kirkwood-ds209.dtb \ - kirkwood-ds210.dtb \ - kirkwood-ds212.dtb \ - kirkwood-ds212j.dtb \ - kirkwood-ds409.dtb \ - kirkwood-ds409slim.dtb \ - kirkwood-ds411.dtb \ - kirkwood-ds411j.dtb \ - kirkwood-ds411slim.dtb \ - kirkwood-goflexnet.dtb \ - kirkwood-guruplug-server-plus.dtb \ - kirkwood-ib62x0.dtb \ - kirkwood-iconnect.dtb \ - kirkwood-iomega_ix2_200.dtb \ - kirkwood-is2.dtb \ - kirkwood-km_kirkwood.dtb \ - kirkwood-l-50.dtb \ - kirkwood-laplug.dtb \ - kirkwood-linkstation-lsqvl.dtb \ - kirkwood-linkstation-lsvl.dtb \ - kirkwood-linkstation-lswsxl.dtb \ - kirkwood-linkstation-lswvl.dtb \ - kirkwood-linkstation-lswxl.dtb \ - kirkwood-linksys-viper.dtb \ - kirkwood-lschlv2.dtb \ - kirkwood-lsxhl.dtb \ - kirkwood-mplcec4.dtb \ - kirkwood-mv88f6281gtw-ge.dtb \ - kirkwood-nas2big.dtb \ - kirkwood-net2big.dtb \ - kirkwood-net5big.dtb \ - kirkwood-netgear_readynas_duo_v2.dtb \ - kirkwood-netgear_readynas_nv+_v2.dtb \ - kirkwood-ns2.dtb \ - kirkwood-ns2lite.dtb \ - kirkwood-ns2max.dtb \ - kirkwood-ns2mini.dtb \ - kirkwood-nsa310.dtb \ - kirkwood-nsa310a.dtb \ - kirkwood-nsa310s.dtb \ - kirkwood-nsa320.dtb \ - kirkwood-nsa325.dtb \ - kirkwood-openblocks_a6.dtb \ - kirkwood-openblocks_a7.dtb \ - kirkwood-openrd-base.dtb \ - kirkwood-openrd-client.dtb \ - kirkwood-openrd-ultimate.dtb \ - kirkwood-pogo_e02.dtb \ - kirkwood-pogoplug-series-4.dtb \ - kirkwood-rd88f6192.dtb \ - kirkwood-rd88f6281-z0.dtb \ - kirkwood-rd88f6281-a.dtb \ - kirkwood-rs212.dtb \ - kirkwood-rs409.dtb \ - kirkwood-rs411.dtb \ - kirkwood-sheevaplug.dtb \ - kirkwood-sheevaplug-esata.dtb \ - kirkwood-t5325.dtb \ - kirkwood-topkick.dtb \ - kirkwood-ts219-6281.dtb \ - kirkwood-ts219-6282.dtb \ - kirkwood-ts419-6281.dtb \ - kirkwood-ts419-6282.dtb -dtb-$(CONFIG_ARCH_LPC18XX) += \ - lpc4337-ciaa.dtb \ - lpc4350-hitex-eval.dtb \ - lpc4357-ea4357-devkit.dtb \ - lpc4357-myd-lpc4357.dtb -dtb-$(CONFIG_ARCH_LPC32XX) += \ - lpc3250-ea3250.dtb \ - lpc3250-phy3250.dtb -dtb-$(CONFIG_ARCH_WPCM450) += \ - nuvoton-wpcm450-supermicro-x9sci-ln4f.dtb -dtb-$(CONFIG_ARCH_NPCM7XX) += \ - nuvoton-npcm730-gsj.dtb \ - nuvoton-npcm730-gbs.dtb \ - nuvoton-npcm730-kudo.dtb \ - nuvoton-npcm750-evb.dtb \ - nuvoton-npcm750-runbmc-olympus.dtb -dtb-$(CONFIG_MACH_MESON6) += \ - meson6-atv1200.dtb -dtb-$(CONFIG_MACH_MESON8) += \ - meson8-minix-neo-x8.dtb \ - meson8b-ec100.dtb \ - meson8b-mxq.dtb \ - meson8b-odroidc1.dtb \ - meson8m2-mxiii-plus.dtb -dtb-$(CONFIG_ARCH_MMP) += \ - pxa168-aspenite.dtb \ - pxa910-dkb.dtb \ - mmp2-brownstone.dtb \ - mmp2-olpc-xo-1-75.dtb \ - mmp3-dell-ariel.dtb -dtb-$(CONFIG_ARCH_MPS2) += \ - mps2-an385.dtb \ - mps2-an399.dtb -dtb-$(CONFIG_ARCH_MOXART) += \ - moxart-uc7112lx.dtb -dtb-$(CONFIG_ARCH_SD5203) += \ - sd5203.dtb -dtb-$(CONFIG_SOC_IMX1) += \ - imx1-ads.dtb \ - imx1-apf9328.dtb -dtb-$(CONFIG_SOC_IMX25) += \ - imx25-eukrea-mbimxsd25-baseboard.dtb \ - imx25-eukrea-mbimxsd25-baseboard-cmo-qvga.dtb \ - imx25-eukrea-mbimxsd25-baseboard-dvi-svga.dtb \ - imx25-eukrea-mbimxsd25-baseboard-dvi-vga.dtb \ - imx25-karo-tx25.dtb \ - imx25-pdk.dtb -dtb-$(CONFIG_SOC_IMX27) += \ - imx27-apf27.dtb \ - imx27-apf27dev.dtb \ - imx27-eukrea-mbimxsd27-baseboard.dtb \ - imx27-pdk.dtb \ - imx27-phytec-phycore-rdk.dtb \ - imx27-phytec-phycard-s-rdk.dtb -dtb-$(CONFIG_SOC_IMX31) += \ - imx31-bug.dtb \ - imx31-lite.dtb -dtb-$(CONFIG_SOC_IMX35) += \ - imx35-eukrea-mbimxsd35-baseboard.dtb \ - imx35-pdk.dtb -dtb-$(CONFIG_SOC_IMX50) += \ - imx50-evk.dtb \ - imx50-kobo-aura.dtb -dtb-$(CONFIG_SOC_IMX51) += \ - imx51-apf51.dtb \ - imx51-apf51dev.dtb \ - imx51-babbage.dtb \ - imx51-digi-connectcore-jsk.dtb \ - imx51-eukrea-mbimxsd51-baseboard.dtb \ - imx51-ts4800.dtb \ - imx51-zii-rdu1.dtb \ - imx51-zii-scu2-mezz.dtb \ - imx51-zii-scu3-esb.dtb -dtb-$(CONFIG_SOC_IMX53) += \ - imx53-ard.dtb \ - imx53-cx9020.dtb \ - imx53-kp-ddc.dtb \ - imx53-kp-hsc.dtb \ - imx53-m53evk.dtb \ - imx53-m53menlo.dtb \ - imx53-mba53.dtb \ - imx53-ppd.dtb \ - imx53-qsb.dtb \ - imx53-qsrb.dtb \ - imx53-sk-imx53.dtb \ - imx53-smd.dtb \ - imx53-tx53-x03x.dtb \ - imx53-tx53-x13x.dtb \ - imx53-usbarmory.dtb \ - imx53-voipac-bsb.dtb -dtb-$(CONFIG_SOC_IMX6Q) += \ - imx6dl-alti6p.dtb \ - imx6dl-apf6dev.dtb \ - imx6dl-aristainetos_4.dtb \ - imx6dl-aristainetos_7.dtb \ - imx6dl-aristainetos2_4.dtb \ - imx6dl-aristainetos2_7.dtb \ - imx6dl-colibri-aster.dtb \ - imx6dl-colibri-eval-v3.dtb \ - imx6dl-colibri-iris.dtb \ - imx6dl-colibri-iris-v2.dtb \ - imx6dl-cubox-i.dtb \ - imx6dl-cubox-i-emmc-som-v15.dtb \ - imx6dl-cubox-i-som-v15.dtb \ - imx6dl-dfi-fs700-m60.dtb \ - imx6dl-dhcom-picoitx.dtb \ - imx6dl-eckelmann-ci4x10.dtb \ - imx6dl-emcon-avari.dtb \ - imx6dl-gw51xx.dtb \ - imx6dl-gw52xx.dtb \ - imx6dl-gw53xx.dtb \ - imx6dl-gw54xx.dtb \ - imx6dl-gw551x.dtb \ - imx6dl-gw552x.dtb \ - imx6dl-gw553x.dtb \ - imx6dl-gw560x.dtb \ - imx6dl-gw5903.dtb \ - imx6dl-gw5904.dtb \ - imx6dl-gw5907.dtb \ - imx6dl-gw5910.dtb \ - imx6dl-gw5912.dtb \ - imx6dl-gw5913.dtb \ - imx6dl-hummingboard.dtb \ - imx6dl-hummingboard-emmc-som-v15.dtb \ - imx6dl-hummingboard-som-v15.dtb \ - imx6dl-hummingboard2.dtb \ - imx6dl-hummingboard2-emmc-som-v15.dtb \ - imx6dl-hummingboard2-som-v15.dtb \ - imx6dl-icore.dtb \ - imx6dl-icore-mipi.dtb \ - imx6dl-icore-rqs.dtb \ - imx6dl-lanmcu.dtb \ - imx6dl-mamoj.dtb \ - imx6dl-mba6a.dtb \ - imx6dl-mba6b.dtb \ - imx6dl-nit6xlite.dtb \ - imx6dl-nitrogen6x.dtb \ - imx6dl-phytec-mira-rdk-nand.dtb \ - imx6dl-phytec-pbab01.dtb \ - imx6dl-pico-dwarf.dtb \ - imx6dl-pico-hobbit.dtb \ - imx6dl-pico-nymph.dtb \ - imx6dl-pico-pi.dtb \ - imx6dl-plybas.dtb \ - imx6dl-plym2m.dtb \ - imx6dl-prtmvt.dtb \ - imx6dl-prtrvt.dtb \ - imx6dl-prtvt7.dtb \ - imx6dl-rex-basic.dtb \ - imx6dl-riotboard.dtb \ - imx6dl-sabreauto.dtb \ - imx6dl-sabrelite.dtb \ - imx6dl-sabresd.dtb \ - imx6dl-savageboard.dtb \ - imx6dl-skov-revc-lt2.dtb \ - imx6dl-skov-revc-lt6.dtb \ - imx6dl-solidsense.dtb \ - imx6dl-ts4900.dtb \ - imx6dl-ts7970.dtb \ - imx6dl-tx6dl-comtft.dtb \ - imx6dl-tx6s-8034.dtb \ - imx6dl-tx6s-8034-mb7.dtb \ - imx6dl-tx6s-8035.dtb \ - imx6dl-tx6s-8035-mb7.dtb \ - imx6dl-tx6u-801x.dtb \ - imx6dl-tx6u-80xx-mb7.dtb \ - imx6dl-tx6u-8033.dtb \ - imx6dl-tx6u-8033-mb7.dtb \ - imx6dl-tx6u-811x.dtb \ - imx6dl-tx6u-81xx-mb7.dtb \ - imx6dl-udoo.dtb \ - imx6dl-victgo.dtb \ - imx6dl-vicut1.dtb \ - imx6dl-wandboard.dtb \ - imx6dl-wandboard-revb1.dtb \ - imx6dl-wandboard-revd1.dtb \ - imx6dl-yapp4-draco.dtb \ - imx6dl-yapp4-hydra.dtb \ - imx6dl-yapp4-lynx.dtb \ - imx6dl-yapp4-orion.dtb \ - imx6dl-yapp4-phoenix.dtb \ - imx6dl-yapp4-ursa.dtb \ - imx6q-apalis-eval.dtb \ - imx6q-apalis-ixora.dtb \ - imx6q-apalis-ixora-v1.1.dtb \ - imx6q-apalis-ixora-v1.2.dtb \ - imx6q-apf6dev.dtb \ - imx6q-arm2.dtb \ - imx6q-b450v3.dtb \ - imx6q-b650v3.dtb \ - imx6q-b850v3.dtb \ - imx6q-bosch-acc.dtb \ - imx6q-cm-fx6.dtb \ - imx6q-cubox-i.dtb \ - imx6q-cubox-i-emmc-som-v15.dtb \ - imx6q-cubox-i-som-v15.dtb \ - imx6q-dfi-fs700-m60.dtb \ - imx6q-dhcom-pdk2.dtb \ - imx6q-display5-tianma-tm070-1280x768.dtb \ - imx6q-dmo-edmqmx6.dtb \ - imx6q-dms-ba16.dtb \ - imx6q-ds.dtb \ - imx6q-emcon-avari.dtb \ - imx6q-evi.dtb \ - imx6dl-b105pv2.dtb \ - imx6dl-b105v2.dtb \ - imx6dl-b125v2.dtb \ - imx6dl-b125pv2.dtb \ - imx6dl-b155v2.dtb \ - imx6q-gk802.dtb \ - imx6q-gw51xx.dtb \ - imx6q-gw52xx.dtb \ - imx6q-gw53xx.dtb \ - imx6q-gw5400-a.dtb \ - imx6q-gw54xx.dtb \ - imx6q-gw551x.dtb \ - imx6q-gw552x.dtb \ - imx6q-gw553x.dtb \ - imx6q-gw560x.dtb \ - imx6q-gw5903.dtb \ - imx6q-gw5904.dtb \ - imx6q-gw5907.dtb \ - imx6q-gw5910.dtb \ - imx6q-gw5912.dtb \ - imx6q-gw5913.dtb \ - imx6q-h100.dtb \ - imx6q-hummingboard.dtb \ - imx6q-hummingboard-emmc-som-v15.dtb \ - imx6q-hummingboard-som-v15.dtb \ - imx6q-hummingboard2.dtb \ - imx6q-hummingboard2-emmc-som-v15.dtb \ - imx6q-hummingboard2-som-v15.dtb \ - imx6q-icore.dtb \ - imx6q-icore-mipi.dtb \ - imx6q-icore-ofcap10.dtb \ - imx6q-icore-ofcap12.dtb \ - imx6q-icore-rqs.dtb \ - imx6q-kp-tpc.dtb \ - imx6q-logicpd.dtb \ - imx6q-marsboard.dtb \ - imx6q-mba6a.dtb \ - imx6q-mba6b.dtb \ - imx6q-mccmon6.dtb \ - imx6q-nitrogen6x.dtb \ - imx6q-nitrogen6_max.dtb \ - imx6q-nitrogen6_som2.dtb \ - imx6q-novena.dtb \ - imx6q-phytec-mira-rdk-emmc.dtb \ - imx6q-phytec-mira-rdk-nand.dtb \ - imx6q-phytec-pbab01.dtb \ - imx6q-pico-dwarf.dtb \ - imx6q-pico-hobbit.dtb \ - imx6q-pico-nymph.dtb \ - imx6q-pico-pi.dtb \ - imx6q-pistachio.dtb \ - imx6q-prti6q.dtb \ - imx6q-prtwd2.dtb \ - imx6q-rex-pro.dtb \ - imx6q-sabreauto.dtb \ - imx6q-sabrelite.dtb \ - imx6q-sabresd.dtb \ - imx6q-savageboard.dtb \ - imx6q-sbc6x.dtb \ - imx6q-skov-revc-lt2.dtb \ - imx6q-skov-revc-lt6.dtb \ - imx6q-skov-reve-mi1010ait-1cp1.dtb \ - imx6q-solidsense.dtb \ - imx6q-tbs2910.dtb \ - imx6q-ts4900.dtb \ - imx6q-ts7970.dtb \ - imx6q-tx6q-1010.dtb \ - imx6q-tx6q-1010-comtft.dtb \ - imx6q-tx6q-1020.dtb \ - imx6q-tx6q-1020-comtft.dtb \ - imx6q-tx6q-1036.dtb \ - imx6q-tx6q-1036-mb7.dtb \ - imx6q-tx6q-10x0-mb7.dtb \ - imx6q-tx6q-1110.dtb \ - imx6q-tx6q-11x0-mb7.dtb \ - imx6q-udoo.dtb \ - imx6q-utilite-pro.dtb \ - imx6q-var-dt6customboard.dtb \ - imx6q-vicut1.dtb \ - imx6q-wandboard.dtb \ - imx6q-wandboard-revb1.dtb \ - imx6q-wandboard-revd1.dtb \ - imx6q-yapp4-crux.dtb \ - imx6q-yapp4-pegasus.dtb \ - imx6q-zii-rdu2.dtb \ - imx6qp-mba6b.dtb \ - imx6qp-nitrogen6_max.dtb \ - imx6qp-nitrogen6_som2.dtb \ - imx6qp-phytec-mira-rdk-nand.dtb \ - imx6qp-prtwd3.dtb \ - imx6qp-sabreauto.dtb \ - imx6qp-sabresd.dtb \ - imx6qp-tx6qp-8037.dtb \ - imx6qp-tx6qp-8037-mb7.dtb \ - imx6qp-tx6qp-8137.dtb \ - imx6qp-tx6qp-8137-mb7.dtb \ - imx6qp-vicutp.dtb \ - imx6qp-wandboard-revd1.dtb \ - imx6qp-yapp4-crux-plus.dtb \ - imx6qp-yapp4-pegasus-plus.dtb \ - imx6qp-zii-rdu2.dtb \ - imx6s-dhcom-drc02.dtb -dtb-$(CONFIG_SOC_IMX6SL) += \ - imx6sl-evk.dtb \ - imx6sl-kobo-aura2.dtb \ - imx6sl-tolino-shine2hd.dtb \ - imx6sl-tolino-shine3.dtb \ - imx6sl-tolino-vision.dtb \ - imx6sl-tolino-vision5.dtb \ - imx6sl-warp.dtb -dtb-$(CONFIG_SOC_IMX6SLL) += \ - imx6sll-evk.dtb \ - imx6sll-kobo-clarahd.dtb \ - imx6sll-kobo-librah2o.dtb -dtb-$(CONFIG_SOC_IMX6SX) += \ - imx6sx-nitrogen6sx.dtb \ - imx6sx-sabreauto.dtb \ - imx6sx-sdb-reva.dtb \ - imx6sx-sdb-sai.dtb \ - imx6sx-sdb.dtb \ - imx6sx-sdb-mqs.dtb \ - imx6sx-softing-vining-2000.dtb \ - imx6sx-udoo-neo-basic.dtb \ - imx6sx-udoo-neo-extended.dtb \ - imx6sx-udoo-neo-full.dtb -dtb-$(CONFIG_SOC_IMX6UL) += \ - imx6ul-14x14-evk.dtb \ - imx6ul-ccimx6ulsbcexpress.dtb \ - imx6ul-ccimx6ulsbcpro.dtb \ - imx6ul-geam.dtb \ - imx6ul-isiot-emmc.dtb \ - imx6ul-isiot-nand.dtb \ - imx6ul-kontron-bl.dtb \ - imx6ul-kontron-bl-43.dtb \ - imx6ul-liteboard.dtb \ - imx6ul-tqma6ul1-mba6ulx.dtb \ - imx6ul-tqma6ul2-mba6ulx.dtb \ - imx6ul-tqma6ul2l-mba6ulx.dtb \ - imx6ul-opos6uldev.dtb \ - imx6ul-pico-dwarf.dtb \ - imx6ul-pico-hobbit.dtb \ - imx6ul-pico-pi.dtb \ - imx6ul-phytec-segin-ff-rdk-emmc.dtb \ - imx6ul-phytec-segin-ff-rdk-nand.dtb \ - imx6ul-prti6g.dtb \ - imx6ul-tx6ul-0010.dtb \ - imx6ul-tx6ul-0011.dtb \ - imx6ul-tx6ul-mainboard.dtb \ - imx6ull-14x14-evk.dtb \ - imx6ull-colibri-aster.dtb \ - imx6ull-colibri-emmc-aster.dtb \ - imx6ull-colibri-emmc-eval-v3.dtb \ - imx6ull-colibri-emmc-iris.dtb \ - imx6ull-colibri-emmc-iris-v2.dtb \ - imx6ull-colibri-eval-v3.dtb \ - imx6ull-colibri-iris.dtb \ - imx6ull-colibri-iris-v2.dtb \ - imx6ull-colibri-wifi-aster.dtb \ - imx6ull-colibri-wifi-eval-v3.dtb \ - imx6ull-colibri-wifi-iris.dtb \ - imx6ull-colibri-wifi-iris-v2.dtb \ - imx6ull-dhcom-drc02.dtb \ - imx6ull-dhcom-pdk2.dtb \ - imx6ull-dhcom-picoitx.dtb \ - imx6ull-jozacp.dtb \ - imx6ull-kontron-bl.dtb \ - imx6ull-myir-mys-6ulx-eval.dtb \ - imx6ull-opos6uldev.dtb \ - imx6ull-phytec-segin-ff-rdk-nand.dtb \ - imx6ull-phytec-segin-ff-rdk-emmc.dtb \ - imx6ull-phytec-segin-lc-rdk-nand.dtb \ - imx6ull-phytec-tauri-emmc.dtb \ - imx6ull-phytec-tauri-nand.dtb \ - imx6ull-tarragon-master.dtb \ - imx6ull-tarragon-micro.dtb \ - imx6ull-tarragon-slave.dtb \ - imx6ull-tarragon-slavext.dtb \ - imx6ull-tqma6ull2-mba6ulx.dtb \ - imx6ull-tqma6ull2l-mba6ulx.dtb \ - imx6ulz-14x14-evk.dtb \ - imx6ulz-bsh-smm-m2.dtb -dtb-$(CONFIG_SOC_IMX7D) += \ - imx7d-cl-som-imx7.dtb \ - imx7d-colibri-aster.dtb \ - imx7d-colibri-emmc-aster.dtb \ - imx7d-colibri-emmc-iris.dtb \ - imx7d-colibri-emmc-iris-v2.dtb \ - imx7d-colibri-emmc-eval-v3.dtb \ - imx7d-colibri-eval-v3.dtb \ - imx7d-colibri-iris.dtb \ - imx7d-colibri-iris-v2.dtb \ - imx7d-flex-concentrator.dtb \ - imx7d-flex-concentrator-mfg.dtb \ - imx7d-mba7.dtb \ - imx7d-meerkat96.dtb \ - imx7d-nitrogen7.dtb \ - imx7d-pico-dwarf.dtb \ - imx7d-pico-hobbit.dtb \ - imx7d-pico-nymph.dtb \ - imx7d-pico-pi.dtb \ - imx7d-remarkable2.dtb \ - imx7d-sbc-imx7.dtb \ - imx7d-sdb.dtb \ - imx7d-sdb-reva.dtb \ - imx7d-sdb-sht11.dtb \ - imx7d-smegw01.dtb \ - imx7d-zii-rmu2.dtb \ - imx7d-zii-rpu2.dtb \ - imx7s-colibri-aster.dtb \ - imx7s-colibri-eval-v3.dtb \ - imx7s-colibri-iris.dtb \ - imx7s-colibri-iris-v2.dtb \ - imx7s-mba7.dtb \ - imx7s-warp.dtb -dtb-$(CONFIG_SOC_IMX7ULP) += \ - imx7ulp-com.dtb \ - imx7ulp-evk.dtb -dtb-$(CONFIG_SOC_IMXRT) += \ - imxrt1050-evk.dtb -dtb-$(CONFIG_SOC_LAN966) += \ - lan966x-kontron-kswitch-d10-mmt-6g-2gs.dtb \ - lan966x-kontron-kswitch-d10-mmt-8g.dtb \ - lan966x-pcb8290.dtb \ - lan966x-pcb8291.dtb \ - lan966x-pcb8309.dtb -dtb-$(CONFIG_SOC_LS1021A) += \ - ls1021a-iot.dtb \ - ls1021a-moxa-uc-8410a.dtb \ - ls1021a-qds.dtb \ - ls1021a-tsn.dtb \ - ls1021a-twr.dtb -dtb-$(CONFIG_SOC_VF610) += \ - vf500-colibri-eval-v3.dtb \ - vf610-bk4.dtb \ - vf610-colibri-eval-v3.dtb \ - vf610m4-colibri.dtb \ - vf610-cosmic.dtb \ - vf610m4-cosmic.dtb \ - vf610-twr.dtb \ - vf610-zii-cfu1.dtb \ - vf610-zii-dev-rev-b.dtb \ - vf610-zii-dev-rev-c.dtb \ - vf610-zii-scu4-aib.dtb \ - vf610-zii-spb4.dtb \ - vf610-zii-ssmb-dtu.dtb \ - vf610-zii-ssmb-spu3.dtb -dtb-$(CONFIG_ARCH_MXS) += \ - imx23-evk.dtb \ - imx23-olinuxino.dtb \ - imx23-sansa.dtb \ - imx23-stmp378x_devb.dtb \ - imx23-xfi3.dtb \ - imx28-apf28.dtb \ - imx28-apf28dev.dtb \ - imx28-apx4devkit.dtb \ - imx28-cfa10036.dtb \ - imx28-cfa10037.dtb \ - imx28-cfa10049.dtb \ - imx28-cfa10055.dtb \ - imx28-cfa10056.dtb \ - imx28-cfa10057.dtb \ - imx28-cfa10058.dtb \ - imx28-duckbill-2-485.dtb \ - imx28-duckbill-2.dtb \ - imx28-duckbill-2-enocean.dtb \ - imx28-duckbill-2-spi.dtb \ - imx28-duckbill.dtb \ - imx28-eukrea-mbmx283lc.dtb \ - imx28-eukrea-mbmx287lc.dtb \ - imx28-evk.dtb \ - imx28-m28cu3.dtb \ - imx28-m28evk.dtb \ - imx28-sps1.dtb \ - imx28-ts4600.dtb \ - imx28-tx28.dtb \ - imx28-xea.dtb -dtb-$(CONFIG_ARCH_NOMADIK) += \ - ste-nomadik-s8815.dtb \ - ste-nomadik-nhk15.dtb -dtb-$(CONFIG_ARCH_NSPIRE) += \ - nspire-cx.dtb \ - nspire-tp.dtb \ - nspire-clp.dtb -dtb-$(CONFIG_ARCH_OMAP2) += \ - omap2420-h4.dtb \ - omap2420-n800.dtb \ - omap2420-n810.dtb \ - omap2420-n810-wimax.dtb \ - omap2430-sdp.dtb -dtb-$(CONFIG_ARCH_OMAP3) += \ - am3517-craneboard.dtb \ - am3517-evm.dtb \ - am3517_mt_ventoux.dtb \ - logicpd-torpedo-37xx-devkit.dtb \ - logicpd-som-lv-37xx-devkit.dtb \ - omap3430-sdp.dtb \ - omap3-beagle.dtb \ - omap3-beagle-ab4.dtb \ - omap3-beagle-xm.dtb \ - omap3-beagle-xm-ab.dtb \ - omap3-cm-t3517.dtb \ - omap3-cm-t3530.dtb \ - omap3-cm-t3730.dtb \ - omap3-devkit8000.dtb \ - omap3-devkit8000-lcd43.dtb \ - omap3-devkit8000-lcd70.dtb \ - omap3-echo.dtb \ - omap3-evm.dtb \ - omap3-evm-37xx.dtb \ - omap3-gta04a3.dtb \ - omap3-gta04a4.dtb \ - omap3-gta04a5.dtb \ - omap3-gta04a5one.dtb \ - omap3-ha.dtb \ - omap3-ha-lcd.dtb \ - omap3-igep0020.dtb \ - omap3-igep0020-rev-f.dtb \ - omap3-igep0030.dtb \ - omap3-igep0030-rev-g.dtb \ - omap3-ldp.dtb \ - omap3-lilly-dbb056.dtb \ - omap3-n900.dtb \ - omap3-n9.dtb \ - omap3-n950.dtb \ - omap3-overo-alto35.dtb \ - omap3-overo-chestnut43.dtb \ - omap3-overo-gallop43.dtb \ - omap3-overo-palo35.dtb \ - omap3-overo-palo43.dtb \ - omap3-overo-storm-alto35.dtb \ - omap3-overo-storm-chestnut43.dtb \ - omap3-overo-storm-gallop43.dtb \ - omap3-overo-storm-palo35.dtb \ - omap3-overo-storm-palo43.dtb \ - omap3-overo-storm-summit.dtb \ - omap3-overo-storm-tobi.dtb \ - omap3-overo-storm-tobiduo.dtb \ - omap3-overo-summit.dtb \ - omap3-overo-tobi.dtb \ - omap3-overo-tobiduo.dtb \ - omap3-pandora-600mhz.dtb \ - omap3-pandora-1ghz.dtb \ - omap3-sbc-t3517.dtb \ - omap3-sbc-t3530.dtb \ - omap3-sbc-t3730.dtb \ - omap3-sniper.dtb \ - omap3-thunder.dtb \ - omap3-zoom3.dtb -dtb-$(CONFIG_SOC_TI81XX) += \ - am3874-iceboard.dtb \ - dm8148-evm.dtb \ - dm8148-t410.dtb \ - dm8168-evm.dtb \ - dra62x-j5eco-evm.dtb -dtb-$(CONFIG_SOC_AM33XX) += \ - am335x-baltos-ir2110.dtb \ - am335x-baltos-ir3220.dtb \ - am335x-baltos-ir5221.dtb \ - am335x-base0033.dtb \ - am335x-bone.dtb \ - am335x-boneblack.dtb \ - am335x-boneblack-wireless.dtb \ - am335x-boneblue.dtb \ - am335x-bonegreen.dtb \ - am335x-bonegreen-wireless.dtb \ - am335x-chiliboard.dtb \ - am335x-cm-t335.dtb \ - am335x-evm.dtb \ - am335x-evmsk.dtb \ - am335x-guardian.dtb \ - am335x-icev2.dtb \ - am335x-lxm.dtb \ - am335x-moxa-uc-2101.dtb \ - am335x-moxa-uc-8100-me-t.dtb \ - am335x-myirtech-myd.dtb \ - am335x-nano.dtb \ - am335x-netcan-plus-1xx.dtb \ - am335x-netcom-plus-2xx.dtb \ - am335x-netcom-plus-8xx.dtb \ - am335x-pdu001.dtb \ - am335x-pepper.dtb \ - am335x-phycore-rdk.dtb \ - am335x-pocketbeagle.dtb \ - am335x-regor-rdk.dtb \ - am335x-sancloud-bbe.dtb \ - am335x-sancloud-bbe-lite.dtb \ - am335x-sancloud-bbe-extended-wifi.dtb \ - am335x-shc.dtb \ - am335x-sbc-t335.dtb \ - am335x-sl50.dtb \ - am335x-wega-rdk.dtb \ - am335x-osd3358-sm-red.dtb -dtb-$(CONFIG_ARCH_OMAP4) += \ - omap4-droid-bionic-xt875.dtb \ - omap4-droid4-xt894.dtb \ - omap4-duovero-parlor.dtb \ - omap4-kc1.dtb \ - omap4-panda.dtb \ - omap4-panda-a4.dtb \ - omap4-panda-es.dtb \ - omap4-sdp.dtb \ - omap4-sdp-es23plus.dtb \ - omap4-var-dvk-om44.dtb \ - omap4-var-stk-om44.dtb -dtb-$(CONFIG_SOC_AM43XX) += \ - am43x-epos-evm.dtb \ - am437x-cm-t43.dtb \ - am437x-gp-evm.dtb \ - am437x-idk-evm.dtb \ - am437x-sbc-t43.dtb \ - am437x-sk-evm.dtb -dtb-$(CONFIG_SOC_OMAP5) += \ - omap5-cm-t54.dtb \ - omap5-igep0050.dtb \ - omap5-sbc-t54.dtb \ - omap5-uevm.dtb -am57xx-evm-dtbs := am57xx-beagle-x15.dtb am57xx-evm.dtbo -am57xx-evm-reva3-dtbs := am57xx-beagle-x15-revc.dtb am57xx-evm.dtbo -dtb-$(CONFIG_SOC_DRA7XX) += \ - am57xx-beagle-x15.dtb \ - am57xx-beagle-x15-revb1.dtb \ - am57xx-beagle-x15-revc.dtb \ - am57xx-evm.dtb \ - am57xx-evm-reva3.dtb \ - am5729-beagleboneai.dtb \ - am57xx-cl-som-am57x.dtb \ - am57xx-sbc-am57x.dtb \ - am572x-idk.dtb \ - am572x-idk-touchscreen.dtbo \ - am571x-idk.dtb \ - am571x-idk-touchscreen.dtbo \ - am574x-idk.dtb \ - am57xx-idk-lcd-osd101t2045.dtbo \ - am57xx-idk-lcd-osd101t2587.dtbo \ - dra7-evm.dtb \ - dra72-evm.dtb \ - dra72-evm-revc.dtb \ - dra71-evm.dtb \ - dra76-evm.dtb -dtb-$(CONFIG_ARCH_ORION5X) += \ - orion5x-kuroboxpro.dtb \ - orion5x-lacie-d2-network.dtb \ - orion5x-lacie-ethernet-disk-mini-v2.dtb \ - orion5x-linkstation-lsgl.dtb \ - orion5x-linkstation-lswtgl.dtb \ - orion5x-linkstation-lschl.dtb \ - orion5x-lswsgl.dtb \ - orion5x-maxtor-shared-storage-2.dtb \ - orion5x-netgear-wnr854t.dtb \ - orion5x-rd88f5182-nas.dtb -dtb-$(CONFIG_ARCH_ACTIONS) += \ - owl-s500-cubieboard6.dtb \ - owl-s500-guitar-bb-rev-b.dtb \ - owl-s500-labrador-base-m.dtb \ - owl-s500-roseapplepi.dtb \ - owl-s500-sparky.dtb -dtb-$(CONFIG_ARCH_PXA) += \ - pxa300-raumfeld-connector.dtb \ - pxa300-raumfeld-controller.dtb \ - pxa300-raumfeld-speaker-l.dtb \ - pxa300-raumfeld-speaker-m.dtb \ - pxa300-raumfeld-speaker-one.dtb \ - pxa300-raumfeld-speaker-s.dtb -dtb-$(CONFIG_ARCH_QCOM) += \ - qcom-apq8016-sbc.dtb \ - qcom-apq8026-asus-sparrow.dtb \ - qcom-apq8026-huawei-sturgeon.dtb \ - qcom-apq8026-lg-lenok.dtb \ - qcom-apq8026-samsung-matisse-wifi.dtb \ - qcom-apq8060-dragonboard.dtb \ - qcom-apq8064-cm-qs600.dtb \ - qcom-apq8064-ifc6410.dtb \ - qcom-apq8064-sony-xperia-lagan-yuga.dtb \ - qcom-apq8064-asus-nexus7-flo.dtb \ - qcom-apq8074-dragonboard.dtb \ - qcom-apq8084-ifc6540.dtb \ - qcom-apq8084-mtp.dtb \ - qcom-ipq4018-ap120c-ac.dtb \ - qcom-ipq4018-ap120c-ac-bit.dtb \ - qcom-ipq4018-jalapeno.dtb \ - qcom-ipq4019-ap.dk01.1-c1.dtb \ - qcom-ipq4019-ap.dk04.1-c1.dtb \ - qcom-ipq4019-ap.dk04.1-c3.dtb \ - qcom-ipq4019-ap.dk07.1-c1.dtb \ - qcom-ipq4019-ap.dk07.1-c2.dtb \ - qcom-ipq8064-ap148.dtb \ - qcom-ipq8064-rb3011.dtb \ - qcom-msm8226-samsung-s3ve3g.dtb \ - qcom-msm8660-surf.dtb \ - qcom-msm8916-samsung-e5.dtb \ - qcom-msm8916-samsung-e7.dtb \ - qcom-msm8916-samsung-grandmax.dtb \ - qcom-msm8916-samsung-serranove.dtb \ - qcom-msm8960-cdp.dtb \ - qcom-msm8974-lge-nexus5-hammerhead.dtb \ - qcom-msm8974-sony-xperia-rhine-amami.dtb \ - qcom-msm8974-sony-xperia-rhine-honami.dtb \ - qcom-msm8974pro-fairphone-fp2.dtb \ - qcom-msm8974pro-oneplus-bacon.dtb \ - qcom-msm8974pro-samsung-klte.dtb \ - qcom-msm8974pro-sony-xperia-shinano-castor.dtb \ - qcom-mdm9615-wp8548-mangoh-green.dtb \ - qcom-sdx55-mtp.dtb \ - qcom-sdx55-t55.dtb \ - qcom-sdx55-telit-fn980-tlb.dtb \ - qcom-sdx65-mtp.dtb -dtb-$(CONFIG_ARCH_RDA) += \ - rda8810pl-orangepi-2g-iot.dtb \ - rda8810pl-orangepi-i96.dtb -dtb-$(CONFIG_ARCH_REALTEK) += \ - rtd1195-horseradish.dtb \ - rtd1195-mele-x1000.dtb -dtb-$(CONFIG_ARCH_REALVIEW) += \ - arm-realview-pb1176.dtb \ - arm-realview-pb11mp.dtb \ - arm-realview-eb.dtb \ - arm-realview-eb-bbrevd.dtb \ - arm-realview-eb-11mp.dtb \ - arm-realview-eb-11mp-bbrevd.dtb \ - arm-realview-eb-11mp-ctrevb.dtb \ - arm-realview-eb-11mp-bbrevd-ctrevb.dtb \ - arm-realview-eb-a9mp.dtb \ - arm-realview-eb-a9mp-bbrevd.dtb \ - arm-realview-pba8.dtb \ - arm-realview-pbx-a9.dtb -dtb-$(CONFIG_ARCH_RENESAS) += \ - emev2-kzm9d.dtb \ - r7s72100-genmai.dtb \ - r7s72100-gr-peach.dtb \ - r7s72100-rskrza1.dtb \ - r7s9210-rza2mevb.dtb \ - r8a73a4-ape6evm.dtb \ - r8a7740-armadillo800eva.dtb \ - r8a7742-iwg21d-q7.dtb \ - r8a7742-iwg21d-q7-dbcm-ca.dtb \ - r8a7743-iwg20d-q7.dtb \ - r8a7743-iwg20d-q7-dbcm-ca.dtb \ - r8a7743-sk-rzg1m.dtb \ - r8a7744-iwg20d-q7.dtb \ - r8a7744-iwg20d-q7-dbcm-ca.dtb \ - r8a7745-iwg22d-sodimm.dtb \ - r8a7745-iwg22d-sodimm-dbhd-ca.dtb \ - r8a7745-sk-rzg1e.dtb \ - r8a77470-iwg23s-sbc.dtb \ - r8a7778-bockw.dtb \ - r8a7779-marzen.dtb \ - r8a7790-lager.dtb \ - r8a7790-stout.dtb \ - r8a7791-koelsch.dtb \ - r8a7791-porter.dtb \ - r8a7792-blanche.dtb \ - r8a7792-wheat.dtb \ - r8a7793-gose.dtb \ - r8a7794-alt.dtb \ - r8a7794-silk.dtb \ - r9a06g032-rzn1d400-db.dtb \ - sh73a0-kzm9g.dtb -dtb-$(CONFIG_ARCH_ROCKCHIP) += \ - rv1108-elgin-r1.dtb \ - rv1108-evb.dtb \ - rv1126-edgeble-neu2-io.dtb \ - rk3036-evb.dtb \ - rk3036-kylin.dtb \ - rk3066a-bqcurie2.dtb \ - rk3066a-marsboard.dtb \ - rk3066a-mk808.dtb \ - rk3066a-rayeager.dtb \ - rk3128-evb.dtb \ - rk3188-bqedison2qc.dtb \ - rk3188-px3-evb.dtb \ - rk3188-radxarock.dtb \ - rk3228-evb.dtb \ - rk3229-evb.dtb \ - rk3229-xms6.dtb \ - rk3288-evb-act8846.dtb \ - rk3288-evb-rk808.dtb \ - rk3288-firefly-beta.dtb \ - rk3288-firefly.dtb \ - rk3288-firefly-reload.dtb \ - rk3288-miqi.dtb \ - rk3288-phycore-rdk.dtb \ - rk3288-popmetal.dtb \ - rk3288-r89.dtb \ - rk3288-rock2-square.dtb \ - rk3288-rock-pi-n8.dtb \ - rk3288-tinker.dtb \ - rk3288-tinker-s.dtb \ - rk3288-veyron-brain.dtb \ - rk3288-veyron-fievel.dtb \ - rk3288-veyron-jaq.dtb \ - rk3288-veyron-jerry.dtb \ - rk3288-veyron-mickey.dtb \ - rk3288-veyron-mighty.dtb \ - rk3288-veyron-minnie.dtb \ - rk3288-veyron-pinky.dtb \ - rk3288-veyron-speedy.dtb \ - rk3288-veyron-tiger.dtb \ - rk3288-vyasa.dtb -dtb-$(CONFIG_ARCH_S3C64XX) += \ - s3c6410-mini6410.dtb \ - s3c6410-smdk6410.dtb -dtb-$(CONFIG_ARCH_S5PV210) += \ - s5pv210-aquila.dtb \ - s5pv210-fascinate4g.dtb \ - s5pv210-galaxys.dtb \ - s5pv210-goni.dtb \ - s5pv210-smdkc110.dtb \ - s5pv210-smdkv210.dtb \ - s5pv210-torbreck.dtb -dtb-$(CONFIG_ARCH_INTEL_SOCFPGA) += \ - socfpga_arria5_socdk.dtb \ - socfpga_arria10_chameleonv3.dtb \ - socfpga_arria10_mercury_pe1.dtb \ - socfpga_arria10_socdk_nand.dtb \ - socfpga_arria10_socdk_qspi.dtb \ - socfpga_arria10_socdk_sdmmc.dtb \ - socfpga_cyclone5_chameleon96.dtb \ - socfpga_cyclone5_mcvevk.dtb \ - socfpga_cyclone5_socdk.dtb \ - socfpga_cyclone5_de0_nano_soc.dtb \ - socfpga_cyclone5_sockit.dtb \ - socfpga_cyclone5_socrates.dtb \ - socfpga_cyclone5_sodia.dtb \ - socfpga_cyclone5_vining_fpga.dtb \ - socfpga_vt.dtb -dtb-$(CONFIG_ARCH_SPEAR13XX) += \ - spear1310-evb.dtb \ - spear1340-evb.dtb -dtb-$(CONFIG_ARCH_SPEAR3XX) += \ - spear300-evb.dtb \ - spear310-evb.dtb \ - spear320-evb.dtb \ - spear320-hmi.dtb -dtb-$(CONFIG_ARCH_SPEAR6XX) += \ - spear600-evb.dtb -dtb-$(CONFIG_ARCH_STI) += \ - stih407-b2120.dtb \ - stih410-b2120.dtb \ - stih410-b2260.dtb \ - stih418-b2199.dtb \ - stih418-b2264.dtb -dtb-$(CONFIG_ARCH_STM32) += \ - stm32f429-disco.dtb \ - stm32f469-disco.dtb \ - stm32f746-disco.dtb \ - stm32f769-disco.dtb \ - stm32429i-eval.dtb \ - stm32746g-eval.dtb \ - stm32h743i-eval.dtb \ - stm32h743i-disco.dtb \ - stm32h750i-art-pi.dtb \ - stm32mp135f-dk.dtb \ - stm32mp151a-prtt1a.dtb \ - stm32mp151a-prtt1c.dtb \ - stm32mp151a-prtt1s.dtb \ - stm32mp151a-dhcor-testbench.dtb \ - stm32mp153c-dhcom-drc02.dtb \ - stm32mp153c-dhcor-drc-compact.dtb \ - stm32mp157a-avenger96.dtb \ - stm32mp157a-dhcor-avenger96.dtb \ - stm32mp157a-dk1.dtb \ - stm32mp157a-dk1-scmi.dtb \ - stm32mp157a-iot-box.dtb \ - stm32mp157a-microgea-stm32mp1-microdev2.0.dtb \ - stm32mp157a-microgea-stm32mp1-microdev2.0-of7.dtb \ - stm32mp157a-icore-stm32mp1-ctouch2.dtb \ - stm32mp157a-icore-stm32mp1-ctouch2-of10.dtb \ - stm32mp157a-icore-stm32mp1-edimm2.2.dtb \ - stm32mp157a-stinger96.dtb \ - stm32mp157c-dhcom-pdk2.dtb \ - stm32mp157c-dhcom-picoitx.dtb \ - stm32mp157c-dk2.dtb \ - stm32mp157c-dk2-scmi.dtb \ - stm32mp157c-ed1.dtb \ - stm32mp157c-ed1-scmi.dtb \ - stm32mp157c-emsbc-argon.dtb \ - stm32mp157c-ev1.dtb \ - stm32mp157c-ev1-scmi.dtb \ - stm32mp157c-lxa-mc1.dtb \ - stm32mp157c-odyssey.dtb -dtb-$(CONFIG_MACH_SUN4I) += \ - sun4i-a10-a1000.dtb \ - sun4i-a10-ba10-tvbox.dtb \ - sun4i-a10-chuwi-v7-cw0825.dtb \ - sun4i-a10-cubieboard.dtb \ - sun4i-a10-dserve-dsrv9703c.dtb \ - sun4i-a10-gemei-g9.dtb \ - sun4i-a10-hackberry.dtb \ - sun4i-a10-hyundai-a7hd.dtb \ - sun4i-a10-inet1.dtb \ - sun4i-a10-inet97fv2.dtb \ - sun4i-a10-inet9f-rev03.dtb \ - sun4i-a10-itead-iteaduino-plus.dtb \ - sun4i-a10-jesurun-q5.dtb \ - sun4i-a10-marsboard.dtb \ - sun4i-a10-mini-xplus.dtb \ - sun4i-a10-mk802.dtb \ - sun4i-a10-mk802ii.dtb \ - sun4i-a10-olinuxino-lime.dtb \ - sun4i-a10-pcduino.dtb \ - sun4i-a10-pcduino2.dtb \ - sun4i-a10-pov-protab2-ips9.dtb \ - sun4i-a10-topwise-a721.dtb -dtb-$(CONFIG_MACH_SUN5I) += \ - sun5i-a10s-auxtek-t003.dtb \ - sun5i-a10s-auxtek-t004.dtb \ - sun5i-a10s-mk802.dtb \ - sun5i-a10s-olinuxino-micro.dtb \ - sun5i-a10s-r7-tv-dongle.dtb \ - sun5i-a10s-wobo-i5.dtb \ - sun5i-a13-difrnce-dit4350.dtb \ - sun5i-a13-empire-electronix-d709.dtb \ - sun5i-a13-empire-electronix-m712.dtb \ - sun5i-a13-hsg-h702.dtb \ - sun5i-a13-inet-98v-rev2.dtb \ - sun5i-a13-licheepi-one.dtb \ - sun5i-a13-olinuxino.dtb \ - sun5i-a13-olinuxino-micro.dtb \ - sun5i-a13-pocketbook-touch-lux-3.dtb \ - sun5i-a13-q8-tablet.dtb \ - sun5i-a13-utoo-p66.dtb \ - sun5i-gr8-chip-pro.dtb \ - sun5i-gr8-evb.dtb \ - sun5i-r8-chip.dtb -dtb-$(CONFIG_MACH_SUN6I) += \ - sun6i-a31-app4-evb1.dtb \ - sun6i-a31-colombus.dtb \ - sun6i-a31-hummingbird.dtb \ - sun6i-a31-i7.dtb \ - sun6i-a31-m9.dtb \ - sun6i-a31-mele-a1000g-quad.dtb \ - sun6i-a31s-colorfly-e708-q1.dtb \ - sun6i-a31s-cs908.dtb \ - sun6i-a31s-inet-q972.dtb \ - sun6i-a31s-primo81.dtb \ - sun6i-a31s-sina31s.dtb \ - sun6i-a31s-sinovoip-bpi-m2.dtb \ - sun6i-a31s-yones-toptech-bs1078-v2.dtb -dtb-$(CONFIG_MACH_SUN7I) += \ - sun7i-a20-bananapi.dtb \ - sun7i-a20-bananapi-m1-plus.dtb \ - sun7i-a20-bananapro.dtb \ - sun7i-a20-cubieboard2.dtb \ - sun7i-a20-cubietruck.dtb \ - sun7i-a20-haoyu-marsboard.dtb \ - sun7i-a20-hummingbird.dtb \ - sun7i-a20-itead-ibox.dtb \ - sun7i-a20-i12-tvbox.dtb \ - sun7i-a20-icnova-swac.dtb \ - sun7i-a20-lamobo-r1.dtb \ - sun7i-a20-linutronix-testbox-v2.dtb \ - sun7i-a20-m3.dtb \ - sun7i-a20-mk808c.dtb \ - sun7i-a20-olimex-som-evb.dtb \ - sun7i-a20-olimex-som-evb-emmc.dtb \ - sun7i-a20-olimex-som204-evb.dtb \ - sun7i-a20-olimex-som204-evb-emmc.dtb \ - sun7i-a20-olinuxino-lime.dtb \ - sun7i-a20-olinuxino-lime-emmc.dtb \ - sun7i-a20-olinuxino-lime2.dtb \ - sun7i-a20-olinuxino-lime2-emmc.dtb \ - sun7i-a20-olinuxino-micro.dtb \ - sun7i-a20-olinuxino-micro-emmc.dtb \ - sun7i-a20-orangepi.dtb \ - sun7i-a20-orangepi-mini.dtb \ - sun7i-a20-pcduino3.dtb \ - sun7i-a20-pcduino3-nano.dtb \ - sun7i-a20-wexler-tab7200.dtb \ - sun7i-a20-wits-pro-a20-dkt.dtb -dtb-$(CONFIG_MACH_SUN8I) += \ - sun8i-a23-evb.dtb \ - sun8i-a23-gt90h-v4.dtb \ - sun8i-a23-inet86dz.dtb \ - sun8i-a23-ippo-q8h-v5.dtb \ - sun8i-a23-ippo-q8h-v1.2.dtb \ - sun8i-a23-polaroid-mid2407pxe03.dtb \ - sun8i-a23-polaroid-mid2809pxe04.dtb \ - sun8i-a23-q8-tablet.dtb \ - sun8i-a33-et-q8-v1.6.dtb \ - sun8i-a33-ga10h-v1.1.dtb \ - sun8i-a33-inet-d978-rev2.dtb \ - sun8i-a33-ippo-q8h-v1.2.dtb \ - sun8i-a33-olinuxino.dtb \ - sun8i-a33-q8-tablet.dtb \ - sun8i-a33-sinlinx-sina33.dtb \ - sun8i-a83t-allwinner-h8homlet-v2.dtb \ - sun8i-a83t-bananapi-m3.dtb \ - sun8i-a83t-cubietruck-plus.dtb \ - sun8i-a83t-tbs-a711.dtb \ - sun8i-h2-plus-bananapi-m2-zero.dtb \ - sun8i-h2-plus-libretech-all-h3-cc.dtb \ - sun8i-h2-plus-orangepi-r1.dtb \ - sun8i-h2-plus-orangepi-zero.dtb \ - sun8i-h3-bananapi-m2-plus.dtb \ - sun8i-h3-bananapi-m2-plus-v1.2.dtb \ - sun8i-h3-beelink-x2.dtb \ - sun8i-h3-libretech-all-h3-cc.dtb \ - sun8i-h3-mapleboard-mp130.dtb \ - sun8i-h3-nanopi-duo2.dtb \ - sun8i-h3-nanopi-m1.dtb \ - sun8i-h3-nanopi-m1-plus.dtb \ - sun8i-h3-nanopi-neo.dtb \ - sun8i-h3-nanopi-neo-air.dtb \ - sun8i-h3-nanopi-r1.dtb \ - sun8i-h3-orangepi-2.dtb \ - sun8i-h3-orangepi-lite.dtb \ - sun8i-h3-orangepi-one.dtb \ - sun8i-h3-orangepi-pc.dtb \ - sun8i-h3-orangepi-pc-plus.dtb \ - sun8i-h3-orangepi-plus.dtb \ - sun8i-h3-orangepi-plus2e.dtb \ - sun8i-h3-orangepi-zero-plus2.dtb \ - sun8i-h3-rervision-dvk.dtb \ - sun8i-h3-zeropi.dtb \ - sun8i-h3-emlid-neutis-n5h3-devboard.dtb \ - sun8i-r16-bananapi-m2m.dtb \ - sun8i-r16-nintendo-nes-classic.dtb \ - sun8i-r16-nintendo-super-nes-classic.dtb \ - sun8i-r16-parrot.dtb \ - sun8i-r40-bananapi-m2-ultra.dtb \ - sun8i-r40-oka40i-c.dtb \ - sun8i-s3-elimo-initium.dtb \ - sun8i-s3-lichee-zero-plus.dtb \ - sun8i-s3-pinecube.dtb \ - sun8i-t113s-mangopi-mq-r-t113.dtb \ - sun8i-t3-cqa3t-bv3.dtb \ - sun8i-v3-sl631-imx179.dtb \ - sun8i-v3s-licheepi-zero.dtb \ - sun8i-v3s-licheepi-zero-dock.dtb \ - sun8i-v40-bananapi-m2-berry.dtb -dtb-$(CONFIG_MACH_SUN9I) += \ - sun9i-a80-optimus.dtb \ - sun9i-a80-cubieboard4.dtb -dtb-$(CONFIG_MACH_SUNIV) += \ - suniv-f1c100s-licheepi-nano.dtb \ - suniv-f1c200s-lctech-pi.dtb \ - suniv-f1c200s-popstick-v1.1.dtb -dtb-$(CONFIG_ARCH_TEGRA_2x_SOC) += \ - tegra20-acer-a500-picasso.dtb \ - tegra20-asus-tf101.dtb \ - tegra20-harmony.dtb \ - tegra20-colibri-eval-v3.dtb \ - tegra20-colibri-iris.dtb \ - tegra20-medcom-wide.dtb \ - tegra20-paz00.dtb \ - tegra20-plutux.dtb \ - tegra20-seaboard.dtb \ - tegra20-tec.dtb \ - tegra20-trimslice.dtb \ - tegra20-ventana.dtb -dtb-$(CONFIG_ARCH_TEGRA_3x_SOC) += \ - tegra30-apalis-eval.dtb \ - tegra30-apalis-v1.1-eval.dtb \ - tegra30-asus-nexus7-grouper-PM269.dtb \ - tegra30-asus-nexus7-grouper-E1565.dtb \ - tegra30-asus-nexus7-tilapia-E1565.dtb \ - tegra30-asus-tf201.dtb \ - tegra30-asus-tf300t.dtb \ - tegra30-asus-tf300tg.dtb \ - tegra30-asus-tf700t.dtb \ - tegra30-beaver.dtb \ - tegra30-cardhu-a02.dtb \ - tegra30-cardhu-a04.dtb \ - tegra30-colibri-eval-v3.dtb \ - tegra30-ouya.dtb \ - tegra30-pegatron-chagall.dtb -dtb-$(CONFIG_ARCH_TEGRA_114_SOC) += \ - tegra114-asus-tf701t.dtb \ - tegra114-dalmore.dtb \ - tegra114-roth.dtb \ - tegra114-tn7.dtb -dtb-$(CONFIG_ARCH_TEGRA_124_SOC) += \ - tegra124-apalis-eval.dtb \ - tegra124-apalis-v1.2-eval.dtb \ - tegra124-jetson-tk1.dtb \ - tegra124-nyan-big.dtb \ - tegra124-nyan-big-fhd.dtb \ - tegra124-nyan-blaze.dtb \ - tegra124-venice2.dtb -dtb-$(CONFIG_ARCH_U8500) += \ - ste-snowball.dtb \ - ste-hrefprev60-stuib.dtb \ - ste-hrefprev60-tvk.dtb \ - ste-hrefv60plus-stuib.dtb \ - ste-hrefv60plus-tvk.dtb \ - ste-href520-tvk.dtb \ - ste-ux500-samsung-golden.dtb \ - ste-ux500-samsung-janice.dtb \ - ste-ux500-samsung-gavini.dtb \ - ste-ux500-samsung-codina.dtb \ - ste-ux500-samsung-codina-tmo.dtb \ - ste-ux500-samsung-skomer.dtb \ - ste-ux500-samsung-kyle.dtb -dtb-$(CONFIG_ARCH_UNIPHIER) += \ - uniphier-ld4-ref.dtb \ - uniphier-ld6b-ref.dtb \ - uniphier-pro4-ace.dtb \ - uniphier-pro4-ref.dtb \ - uniphier-pro4-sanji.dtb \ - uniphier-pro5-epcore.dtb \ - uniphier-pro5-proex.dtb \ - uniphier-pxs2-gentil.dtb \ - uniphier-pxs2-vodka.dtb \ - uniphier-sld8-ref.dtb -dtb-$(CONFIG_ARCH_VERSATILE) += \ - versatile-ab.dtb \ - versatile-ab-ib2.dtb \ - versatile-pb.dtb -dtb-$(CONFIG_ARCH_VEXPRESS) += \ - vexpress-v2p-ca5s.dtb \ - vexpress-v2p-ca9.dtb \ - vexpress-v2p-ca15-tc1.dtb \ - vexpress-v2p-ca15_a7.dtb -dtb-$(CONFIG_ARCH_VIRT) += \ - xenvm-4.2.dtb -dtb-$(CONFIG_ARCH_VT8500) += \ - vt8500-bv07.dtb \ - wm8505-ref.dtb \ - wm8650-mid.dtb \ - wm8750-apc8750.dtb \ - wm8850-w70v2.dtb -dtb-$(CONFIG_ARCH_ZYNQ) += \ - zynq-cc108.dtb \ - zynq-ebaz4205.dtb \ - zynq-microzed.dtb \ - zynq-parallella.dtb \ - zynq-zc702.dtb \ - zynq-zc706.dtb \ - zynq-zc770-xm010.dtb \ - zynq-zc770-xm011.dtb \ - zynq-zc770-xm012.dtb \ - zynq-zc770-xm013.dtb \ - zynq-zed.dtb \ - zynq-zturn.dtb \ - zynq-zturn-v5.dtb \ - zynq-zybo.dtb \ - zynq-zybo-z7.dtb -dtb-$(CONFIG_MACH_ARMADA_370) += \ - armada-370-c200-v2.dtb \ - armada-370-db.dtb \ - armada-370-dlink-dns327l.dtb \ - armada-370-mirabox.dtb \ - armada-370-netgear-rn102.dtb \ - armada-370-netgear-rn104.dtb \ - armada-370-rd.dtb \ - armada-370-seagate-nas-2bay.dtb \ - armada-370-seagate-nas-4bay.dtb \ - armada-370-seagate-personal-cloud.dtb \ - armada-370-seagate-personal-cloud-2bay.dtb \ - armada-370-synology-ds213j.dtb -dtb-$(CONFIG_MACH_ARMADA_375) += \ - armada-375-db.dtb -dtb-$(CONFIG_MACH_ARMADA_38X) += \ - armada-381-netgear-gs110emx.dtb \ - armada-382-rd-ac3x-48g4x2xl.dtb \ - armada-385-atl-x530.dtb\ - armada-385-clearfog-gtr-s4.dtb \ - armada-385-clearfog-gtr-l8.dtb \ - armada-385-db-88f6820-amc.dtb \ - armada-385-db-ap.dtb \ - armada-385-linksys-caiman.dtb \ - armada-385-linksys-cobra.dtb \ - armada-385-linksys-rango.dtb \ - armada-385-linksys-shelby.dtb \ - armada-385-synology-ds116.dtb \ - armada-385-turris-omnia.dtb \ - armada-388-clearfog.dtb \ - armada-388-clearfog-base.dtb \ - armada-388-clearfog-pro.dtb \ - armada-388-db.dtb \ - armada-388-gp.dtb \ - armada-388-helios4.dtb \ - armada-388-rd.dtb -dtb-$(CONFIG_MACH_ARMADA_39X) += \ - armada-398-db.dtb -dtb-$(CONFIG_MACH_ARMADA_XP) += \ - armada-xp-axpwifiap.dtb \ - armada-xp-crs305-1g-4s.dtb \ - armada-xp-crs305-1g-4s-bit.dtb \ - armada-xp-crs326-24g-2s.dtb \ - armada-xp-crs326-24g-2s-bit.dtb \ - armada-xp-crs328-4c-20s-4s.dtb \ - armada-xp-crs328-4c-20s-4s-bit.dtb \ - armada-xp-db.dtb \ - armada-xp-db-dxbc2.dtb \ - armada-xp-db-xc3-24g4xg.dtb \ - armada-xp-gp.dtb \ - armada-xp-lenovo-ix4-300d.dtb \ - armada-xp-linksys-mamba.dtb \ - armada-xp-matrix.dtb \ - armada-xp-netgear-rn2120.dtb \ - armada-xp-openblocks-ax3-4.dtb \ - armada-xp-synology-ds414.dtb -dtb-$(CONFIG_MACH_DOVE) += \ - dove-cubox.dtb \ - dove-cubox-es.dtb \ - dove-d2plug.dtb \ - dove-d3plug.dtb \ - dove-dove-db.dtb \ - dove-sbc-a510.dtb -dtb-$(CONFIG_ARCH_MEDIATEK) += \ - mt2701-evb.dtb \ - mt6580-evbp1.dtb \ - mt6589-aquaris5.dtb \ - mt6589-fairphone-fp1.dtb \ - mt6592-evb.dtb \ - mt7623a-rfb-emmc.dtb \ - mt7623a-rfb-nand.dtb \ - mt7623n-rfb-emmc.dtb \ - mt7623n-bananapi-bpi-r2.dtb \ - mt7629-rfb.dtb \ - mt8127-moose.dtb \ - mt8135-evbp1.dtb -dtb-$(CONFIG_ARCH_MILBEAUT) += milbeaut-m10v-evb.dtb -dtb-$(CONFIG_ARCH_MSTARV7) += \ - mstar-infinity-msc313-breadbee_crust.dtb \ - mstar-infinity2m-ssd202d-100ask-dongshanpione.dtb \ - mstar-infinity2m-ssd202d-miyoo-mini.dtb \ - mstar-infinity2m-ssd202d-wirelesstag-ido-sbc2d06-v1b-22w.dtb \ - mstar-infinity2m-ssd202d-ssd201htv2.dtb \ - mstar-infinity2m-ssd202d-unitv2.dtb \ - mstar-infinity3-msc313e-breadbee.dtb \ - mstar-mercury5-ssc8336n-midrived08.dtb -dtb-$(CONFIG_ARCH_ASPEED) += \ - aspeed-ast2500-evb.dtb \ - aspeed-ast2600-evb-a1.dtb \ - aspeed-ast2600-evb.dtb \ - aspeed-bmc-amd-daytonax.dtb \ - aspeed-bmc-amd-ethanolx.dtb \ - aspeed-bmc-ampere-mtjade.dtb \ - aspeed-bmc-ampere-mtmitchell.dtb \ - aspeed-bmc-arm-stardragon4800-rep2.dtb \ - aspeed-bmc-asrock-e3c246d4i.dtb \ - aspeed-bmc-asrock-romed8hm3.dtb \ - aspeed-bmc-bytedance-g220a.dtb \ - aspeed-bmc-delta-ahe50dc.dtb \ - aspeed-bmc-facebook-bletchley.dtb \ - aspeed-bmc-facebook-cloudripper.dtb \ - aspeed-bmc-facebook-cmm.dtb \ - aspeed-bmc-facebook-elbert.dtb \ - aspeed-bmc-facebook-fuji.dtb \ - aspeed-bmc-facebook-galaxy100.dtb \ - aspeed-bmc-facebook-greatlakes.dtb \ - aspeed-bmc-facebook-minipack.dtb \ - aspeed-bmc-facebook-tiogapass.dtb \ - aspeed-bmc-facebook-wedge40.dtb \ - aspeed-bmc-facebook-wedge100.dtb \ - aspeed-bmc-facebook-wedge400.dtb \ - aspeed-bmc-facebook-yamp.dtb \ - aspeed-bmc-facebook-yosemitev2.dtb \ - aspeed-bmc-ibm-bonnell.dtb \ - aspeed-bmc-ibm-everest.dtb \ - aspeed-bmc-ibm-rainier.dtb \ - aspeed-bmc-ibm-rainier-1s4u.dtb \ - aspeed-bmc-ibm-rainier-4u.dtb \ - aspeed-bmc-intel-s2600wf.dtb \ - aspeed-bmc-inspur-fp5280g2.dtb \ - aspeed-bmc-inspur-nf5280m6.dtb \ - aspeed-bmc-lenovo-hr630.dtb \ - aspeed-bmc-lenovo-hr855xg2.dtb \ - aspeed-bmc-microsoft-olympus.dtb \ - aspeed-bmc-opp-lanyang.dtb \ - aspeed-bmc-opp-mowgli.dtb \ - aspeed-bmc-opp-nicole.dtb \ - aspeed-bmc-opp-palmetto.dtb \ - aspeed-bmc-opp-romulus.dtb \ - aspeed-bmc-opp-swift.dtb \ - aspeed-bmc-opp-tacoma.dtb \ - aspeed-bmc-opp-vesnin.dtb \ - aspeed-bmc-opp-witherspoon.dtb \ - aspeed-bmc-opp-zaius.dtb \ - aspeed-bmc-portwell-neptune.dtb \ - aspeed-bmc-qcom-dc-scm-v1.dtb \ - aspeed-bmc-quanta-q71l.dtb \ - aspeed-bmc-quanta-s6q.dtb \ - aspeed-bmc-supermicro-x11spi.dtb \ - aspeed-bmc-inventec-transformers.dtb \ - aspeed-bmc-tyan-s7106.dtb \ - aspeed-bmc-tyan-s8036.dtb \ - aspeed-bmc-ufispace-ncplite.dtb \ - aspeed-bmc-vegman-n110.dtb \ - aspeed-bmc-vegman-rx20.dtb \ - aspeed-bmc-vegman-sx20.dtb +subdir-y += actions +subdir-y += airoha +subdir-y += allwinner +subdir-y += alphascale +subdir-y += amazon +subdir-y += amlogic +subdir-y += arm +subdir-y += aspeed +subdir-y += axis +subdir-y += broadcom +subdir-y += calxeda +subdir-y += cirrus +subdir-y += cnxt +subdir-y += gemini +subdir-y += hisilicon +subdir-y += hpe +subdir-y += intel +subdir-y += marvell +subdir-y += mediatek +subdir-y += microchip +subdir-y += moxa +subdir-y += nspire +subdir-y += nuvoton +subdir-y += nvidia +subdir-y += nxp +subdir-y += qcom +subdir-y += realtek +subdir-y += renesas +subdir-y += rockchip +subdir-y += samsung +subdir-y += sigmastar +subdir-y += socionext +subdir-y += st +subdir-y += sunplus +subdir-y += synaptics +subdir-y += ti +subdir-y += unisoc +subdir-y += vt8500 +subdir-y += xen +subdir-y += xilinx diff --git a/arch/arm/boot/dts/actions/Makefile b/arch/arm/boot/dts/actions/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..f384e4a48e6f65853b9ec33e61196c5933b8f536 --- /dev/null +++ b/arch/arm/boot/dts/actions/Makefile @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: GPL-2.0 +dtb-$(CONFIG_ARCH_ACTIONS) += \ + owl-s500-cubieboard6.dtb \ + owl-s500-guitar-bb-rev-b.dtb \ + owl-s500-labrador-base-m.dtb \ + owl-s500-roseapplepi.dtb \ + owl-s500-sparky.dtb diff --git a/arch/arm/boot/dts/owl-s500-cubieboard6.dts b/arch/arm/boot/dts/actions/owl-s500-cubieboard6.dts similarity index 100% rename from arch/arm/boot/dts/owl-s500-cubieboard6.dts rename to arch/arm/boot/dts/actions/owl-s500-cubieboard6.dts diff --git a/arch/arm/boot/dts/owl-s500-guitar-bb-rev-b.dts b/arch/arm/boot/dts/actions/owl-s500-guitar-bb-rev-b.dts similarity index 100% rename from arch/arm/boot/dts/owl-s500-guitar-bb-rev-b.dts rename to arch/arm/boot/dts/actions/owl-s500-guitar-bb-rev-b.dts diff --git a/arch/arm/boot/dts/owl-s500-guitar.dtsi b/arch/arm/boot/dts/actions/owl-s500-guitar.dtsi similarity index 100% rename from arch/arm/boot/dts/owl-s500-guitar.dtsi rename to arch/arm/boot/dts/actions/owl-s500-guitar.dtsi diff --git a/arch/arm/boot/dts/owl-s500-labrador-base-m.dts b/arch/arm/boot/dts/actions/owl-s500-labrador-base-m.dts similarity index 100% rename from arch/arm/boot/dts/owl-s500-labrador-base-m.dts rename to arch/arm/boot/dts/actions/owl-s500-labrador-base-m.dts diff --git a/arch/arm/boot/dts/owl-s500-labrador-v2.dtsi b/arch/arm/boot/dts/actions/owl-s500-labrador-v2.dtsi similarity index 100% rename from arch/arm/boot/dts/owl-s500-labrador-v2.dtsi rename to arch/arm/boot/dts/actions/owl-s500-labrador-v2.dtsi diff --git a/arch/arm/boot/dts/owl-s500-roseapplepi.dts b/arch/arm/boot/dts/actions/owl-s500-roseapplepi.dts similarity index 100% rename from arch/arm/boot/dts/owl-s500-roseapplepi.dts rename to arch/arm/boot/dts/actions/owl-s500-roseapplepi.dts diff --git a/arch/arm/boot/dts/owl-s500-sparky.dts b/arch/arm/boot/dts/actions/owl-s500-sparky.dts similarity index 100% rename from arch/arm/boot/dts/owl-s500-sparky.dts rename to arch/arm/boot/dts/actions/owl-s500-sparky.dts diff --git a/arch/arm/boot/dts/owl-s500.dtsi b/arch/arm/boot/dts/actions/owl-s500.dtsi similarity index 100% rename from arch/arm/boot/dts/owl-s500.dtsi rename to arch/arm/boot/dts/actions/owl-s500.dtsi diff --git a/arch/arm/boot/dts/airoha/Makefile b/arch/arm/boot/dts/airoha/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..00c31389f622e68d1a8f54ecb5f3c59cbf8aa62e --- /dev/null +++ b/arch/arm/boot/dts/airoha/Makefile @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0 +dtb-$(CONFIG_ARCH_AIROHA) += \ + en7523-evb.dtb diff --git a/arch/arm/boot/dts/en7523-evb.dts b/arch/arm/boot/dts/airoha/en7523-evb.dts similarity index 100% rename from arch/arm/boot/dts/en7523-evb.dts rename to arch/arm/boot/dts/airoha/en7523-evb.dts diff --git a/arch/arm/boot/dts/en7523.dtsi b/arch/arm/boot/dts/airoha/en7523.dtsi similarity index 99% rename from arch/arm/boot/dts/en7523.dtsi rename to arch/arm/boot/dts/airoha/en7523.dtsi index 7f839331a7779f884a8395ba2247eff77ffa0d1a..b523a868c4ad14e796381c4aab15c68044feed84 100644 --- a/arch/arm/boot/dts/en7523.dtsi +++ b/arch/arm/boot/dts/airoha/en7523.dtsi @@ -81,6 +81,8 @@ L2_0: l2-cache0 { compatible = "cache"; + cache-level = <2>; + cache-unified; }; }; diff --git a/arch/arm/boot/dts/allwinner/Makefile b/arch/arm/boot/dts/allwinner/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..589a1ce1120aa6f0652ea03817b11304b2e758ac --- /dev/null +++ b/arch/arm/boot/dts/allwinner/Makefile @@ -0,0 +1,315 @@ +# SPDX-License-Identifier: GPL-2.0 +dtb-$(CONFIG_MACH_SUN4I) += \ + sun4i-a10-a1000.dtb \ + sun4i-a10-ba10-tvbox.dtb \ + sun4i-a10-chuwi-v7-cw0825.dtb \ + sun4i-a10-cubieboard.dtb \ + sun4i-a10-dserve-dsrv9703c.dtb \ + sun4i-a10-gemei-g9.dtb \ + sun4i-a10-hackberry.dtb \ + sun4i-a10-hyundai-a7hd.dtb \ + sun4i-a10-inet1.dtb \ + sun4i-a10-inet97fv2.dtb \ + sun4i-a10-inet9f-rev03.dtb \ + sun4i-a10-itead-iteaduino-plus.dtb \ + sun4i-a10-jesurun-q5.dtb \ + sun4i-a10-marsboard.dtb \ + sun4i-a10-mini-xplus.dtb \ + sun4i-a10-mk802.dtb \ + sun4i-a10-mk802ii.dtb \ + sun4i-a10-olinuxino-lime.dtb \ + sun4i-a10-pcduino.dtb \ + sun4i-a10-pcduino2.dtb \ + sun4i-a10-pov-protab2-ips9.dtb \ + sun4i-a10-topwise-a721.dtb +dtb-$(CONFIG_MACH_SUN4I) += \ + sun4i-a10-a1000.dtb \ + sun4i-a10-ba10-tvbox.dtb \ + sun4i-a10-chuwi-v7-cw0825.dtb \ + sun4i-a10-cubieboard.dtb \ + sun4i-a10-dserve-dsrv9703c.dtb \ + sun4i-a10-gemei-g9.dtb \ + sun4i-a10-hackberry.dtb \ + sun4i-a10-hyundai-a7hd.dtb \ + sun4i-a10-inet1.dtb \ + sun4i-a10-inet97fv2.dtb \ + sun4i-a10-inet9f-rev03.dtb \ + sun4i-a10-itead-iteaduino-plus.dtb \ + sun4i-a10-jesurun-q5.dtb \ + sun4i-a10-marsboard.dtb \ + sun4i-a10-mini-xplus.dtb \ + sun4i-a10-mk802.dtb \ + sun4i-a10-mk802ii.dtb \ + sun4i-a10-olinuxino-lime.dtb \ + sun4i-a10-pcduino.dtb \ + sun4i-a10-pcduino2.dtb \ + sun4i-a10-pov-protab2-ips9.dtb \ + sun4i-a10-topwise-a721.dtb +dtb-$(CONFIG_MACH_SUN5I) += \ + sun5i-a10s-auxtek-t003.dtb \ + sun5i-a10s-auxtek-t004.dtb \ + sun5i-a10s-mk802.dtb \ + sun5i-a10s-olinuxino-micro.dtb \ + sun5i-a10s-r7-tv-dongle.dtb \ + sun5i-a10s-wobo-i5.dtb \ + sun5i-a13-difrnce-dit4350.dtb \ + sun5i-a13-empire-electronix-d709.dtb \ + sun5i-a13-empire-electronix-m712.dtb \ + sun5i-a13-hsg-h702.dtb \ + sun5i-a13-inet-98v-rev2.dtb \ + sun5i-a13-licheepi-one.dtb \ + sun5i-a13-olinuxino.dtb \ + sun5i-a13-olinuxino-micro.dtb \ + sun5i-a13-pocketbook-touch-lux-3.dtb \ + sun5i-a13-q8-tablet.dtb \ + sun5i-a13-utoo-p66.dtb \ + sun5i-gr8-chip-pro.dtb \ + sun5i-gr8-evb.dtb \ + sun5i-r8-chip.dtb +dtb-$(CONFIG_MACH_SUN5I) += \ + sun5i-a10s-auxtek-t003.dtb \ + sun5i-a10s-auxtek-t004.dtb \ + sun5i-a10s-mk802.dtb \ + sun5i-a10s-olinuxino-micro.dtb \ + sun5i-a10s-r7-tv-dongle.dtb \ + sun5i-a10s-wobo-i5.dtb \ + sun5i-a13-difrnce-dit4350.dtb \ + sun5i-a13-empire-electronix-d709.dtb \ + sun5i-a13-empire-electronix-m712.dtb \ + sun5i-a13-hsg-h702.dtb \ + sun5i-a13-inet-98v-rev2.dtb \ + sun5i-a13-licheepi-one.dtb \ + sun5i-a13-olinuxino.dtb \ + sun5i-a13-olinuxino-micro.dtb \ + sun5i-a13-pocketbook-touch-lux-3.dtb \ + sun5i-a13-q8-tablet.dtb \ + sun5i-a13-utoo-p66.dtb \ + sun5i-gr8-chip-pro.dtb \ + sun5i-gr8-evb.dtb \ + sun5i-r8-chip.dtb +dtb-$(CONFIG_MACH_SUN6I) += \ + sun6i-a31-app4-evb1.dtb \ + sun6i-a31-colombus.dtb \ + sun6i-a31-hummingbird.dtb \ + sun6i-a31-i7.dtb \ + sun6i-a31-m9.dtb \ + sun6i-a31-mele-a1000g-quad.dtb \ + sun6i-a31s-colorfly-e708-q1.dtb \ + sun6i-a31s-cs908.dtb \ + sun6i-a31s-inet-q972.dtb \ + sun6i-a31s-primo81.dtb \ + sun6i-a31s-sina31s.dtb \ + sun6i-a31s-sinovoip-bpi-m2.dtb \ + sun6i-a31s-yones-toptech-bs1078-v2.dtb +dtb-$(CONFIG_MACH_SUN6I) += \ + sun6i-a31-app4-evb1.dtb \ + sun6i-a31-colombus.dtb \ + sun6i-a31-hummingbird.dtb \ + sun6i-a31-i7.dtb \ + sun6i-a31-m9.dtb \ + sun6i-a31-mele-a1000g-quad.dtb \ + sun6i-a31s-colorfly-e708-q1.dtb \ + sun6i-a31s-cs908.dtb \ + sun6i-a31s-inet-q972.dtb \ + sun6i-a31s-primo81.dtb \ + sun6i-a31s-sina31s.dtb \ + sun6i-a31s-sinovoip-bpi-m2.dtb \ + sun6i-a31s-yones-toptech-bs1078-v2.dtb +dtb-$(CONFIG_MACH_SUN7I) += \ + sun7i-a20-bananapi.dtb \ + sun7i-a20-bananapi-m1-plus.dtb \ + sun7i-a20-bananapro.dtb \ + sun7i-a20-cubieboard2.dtb \ + sun7i-a20-cubietruck.dtb \ + sun7i-a20-haoyu-marsboard.dtb \ + sun7i-a20-hummingbird.dtb \ + sun7i-a20-itead-ibox.dtb \ + sun7i-a20-i12-tvbox.dtb \ + sun7i-a20-icnova-a20-adb4006.dtb \ + sun7i-a20-icnova-swac.dtb \ + sun7i-a20-lamobo-r1.dtb \ + sun7i-a20-linutronix-testbox-v2.dtb \ + sun7i-a20-m3.dtb \ + sun7i-a20-mk808c.dtb \ + sun7i-a20-olimex-som-evb.dtb \ + sun7i-a20-olimex-som-evb-emmc.dtb \ + sun7i-a20-olimex-som204-evb.dtb \ + sun7i-a20-olimex-som204-evb-emmc.dtb \ + sun7i-a20-olinuxino-lime.dtb \ + sun7i-a20-olinuxino-lime-emmc.dtb \ + sun7i-a20-olinuxino-lime2.dtb \ + sun7i-a20-olinuxino-lime2-emmc.dtb \ + sun7i-a20-olinuxino-micro.dtb \ + sun7i-a20-olinuxino-micro-emmc.dtb \ + sun7i-a20-orangepi.dtb \ + sun7i-a20-orangepi-mini.dtb \ + sun7i-a20-pcduino3.dtb \ + sun7i-a20-pcduino3-nano.dtb \ + sun7i-a20-wexler-tab7200.dtb \ + sun7i-a20-wits-pro-a20-dkt.dtb +dtb-$(CONFIG_MACH_SUN7I) += \ + sun7i-a20-bananapi.dtb \ + sun7i-a20-bananapi-m1-plus.dtb \ + sun7i-a20-bananapro.dtb \ + sun7i-a20-cubieboard2.dtb \ + sun7i-a20-cubietruck.dtb \ + sun7i-a20-haoyu-marsboard.dtb \ + sun7i-a20-hummingbird.dtb \ + sun7i-a20-itead-ibox.dtb \ + sun7i-a20-i12-tvbox.dtb \ + sun7i-a20-icnova-a20-adb4006.dtb \ + sun7i-a20-icnova-swac.dtb \ + sun7i-a20-lamobo-r1.dtb \ + sun7i-a20-linutronix-testbox-v2.dtb \ + sun7i-a20-m3.dtb \ + sun7i-a20-mk808c.dtb \ + sun7i-a20-olimex-som-evb.dtb \ + sun7i-a20-olimex-som-evb-emmc.dtb \ + sun7i-a20-olimex-som204-evb.dtb \ + sun7i-a20-olimex-som204-evb-emmc.dtb \ + sun7i-a20-olinuxino-lime.dtb \ + sun7i-a20-olinuxino-lime-emmc.dtb \ + sun7i-a20-olinuxino-lime2.dtb \ + sun7i-a20-olinuxino-lime2-emmc.dtb \ + sun7i-a20-olinuxino-micro.dtb \ + sun7i-a20-olinuxino-micro-emmc.dtb \ + sun7i-a20-orangepi.dtb \ + sun7i-a20-orangepi-mini.dtb \ + sun7i-a20-pcduino3.dtb \ + sun7i-a20-pcduino3-nano.dtb \ + sun7i-a20-wexler-tab7200.dtb \ + sun7i-a20-wits-pro-a20-dkt.dtb +dtb-$(CONFIG_MACH_SUN8I) += \ + sun8i-a23-evb.dtb \ + sun8i-a23-gt90h-v4.dtb \ + sun8i-a23-inet86dz.dtb \ + sun8i-a23-ippo-q8h-v5.dtb \ + sun8i-a23-ippo-q8h-v1.2.dtb \ + sun8i-a23-polaroid-mid2407pxe03.dtb \ + sun8i-a23-polaroid-mid2809pxe04.dtb \ + sun8i-a23-q8-tablet.dtb \ + sun8i-a33-et-q8-v1.6.dtb \ + sun8i-a33-ga10h-v1.1.dtb \ + sun8i-a33-inet-d978-rev2.dtb \ + sun8i-a33-ippo-q8h-v1.2.dtb \ + sun8i-a33-olinuxino.dtb \ + sun8i-a33-q8-tablet.dtb \ + sun8i-a33-sinlinx-sina33.dtb \ + sun8i-a83t-allwinner-h8homlet-v2.dtb \ + sun8i-a83t-bananapi-m3.dtb \ + sun8i-a83t-cubietruck-plus.dtb \ + sun8i-a83t-tbs-a711.dtb \ + sun8i-h2-plus-bananapi-m2-zero.dtb \ + sun8i-h2-plus-libretech-all-h3-cc.dtb \ + sun8i-h2-plus-orangepi-r1.dtb \ + sun8i-h2-plus-orangepi-zero.dtb \ + sun8i-h3-bananapi-m2-plus.dtb \ + sun8i-h3-bananapi-m2-plus-v1.2.dtb \ + sun8i-h3-beelink-x2.dtb \ + sun8i-h3-libretech-all-h3-cc.dtb \ + sun8i-h3-mapleboard-mp130.dtb \ + sun8i-h3-nanopi-duo2.dtb \ + sun8i-h3-nanopi-m1.dtb \ + sun8i-h3-nanopi-m1-plus.dtb \ + sun8i-h3-nanopi-neo.dtb \ + sun8i-h3-nanopi-neo-air.dtb \ + sun8i-h3-nanopi-r1.dtb \ + sun8i-h3-orangepi-2.dtb \ + sun8i-h3-orangepi-lite.dtb \ + sun8i-h3-orangepi-one.dtb \ + sun8i-h3-orangepi-pc.dtb \ + sun8i-h3-orangepi-pc-plus.dtb \ + sun8i-h3-orangepi-plus.dtb \ + sun8i-h3-orangepi-plus2e.dtb \ + sun8i-h3-orangepi-zero-plus2.dtb \ + sun8i-h3-rervision-dvk.dtb \ + sun8i-h3-zeropi.dtb \ + sun8i-h3-emlid-neutis-n5h3-devboard.dtb \ + sun8i-r16-bananapi-m2m.dtb \ + sun8i-r16-nintendo-nes-classic.dtb \ + sun8i-r16-nintendo-super-nes-classic.dtb \ + sun8i-r16-parrot.dtb \ + sun8i-r40-bananapi-m2-ultra.dtb \ + sun8i-r40-oka40i-c.dtb \ + sun8i-s3-elimo-initium.dtb \ + sun8i-s3-lichee-zero-plus.dtb \ + sun8i-s3-pinecube.dtb \ + sun8i-t113s-mangopi-mq-r-t113.dtb \ + sun8i-t3-cqa3t-bv3.dtb \ + sun8i-v3-sl631-imx179.dtb \ + sun8i-v3s-licheepi-zero.dtb \ + sun8i-v3s-licheepi-zero-dock.dtb \ + sun8i-v40-bananapi-m2-berry.dtb +dtb-$(CONFIG_MACH_SUN8I) += \ + sun8i-a23-evb.dtb \ + sun8i-a23-gt90h-v4.dtb \ + sun8i-a23-inet86dz.dtb \ + sun8i-a23-ippo-q8h-v5.dtb \ + sun8i-a23-ippo-q8h-v1.2.dtb \ + sun8i-a23-polaroid-mid2407pxe03.dtb \ + sun8i-a23-polaroid-mid2809pxe04.dtb \ + sun8i-a23-q8-tablet.dtb \ + sun8i-a33-et-q8-v1.6.dtb \ + sun8i-a33-ga10h-v1.1.dtb \ + sun8i-a33-inet-d978-rev2.dtb \ + sun8i-a33-ippo-q8h-v1.2.dtb \ + sun8i-a33-olinuxino.dtb \ + sun8i-a33-q8-tablet.dtb \ + sun8i-a33-sinlinx-sina33.dtb \ + sun8i-a83t-allwinner-h8homlet-v2.dtb \ + sun8i-a83t-bananapi-m3.dtb \ + sun8i-a83t-cubietruck-plus.dtb \ + sun8i-a83t-tbs-a711.dtb \ + sun8i-h2-plus-bananapi-m2-zero.dtb \ + sun8i-h2-plus-libretech-all-h3-cc.dtb \ + sun8i-h2-plus-orangepi-r1.dtb \ + sun8i-h2-plus-orangepi-zero.dtb \ + sun8i-h3-bananapi-m2-plus.dtb \ + sun8i-h3-bananapi-m2-plus-v1.2.dtb \ + sun8i-h3-beelink-x2.dtb \ + sun8i-h3-libretech-all-h3-cc.dtb \ + sun8i-h3-mapleboard-mp130.dtb \ + sun8i-h3-nanopi-duo2.dtb \ + sun8i-h3-nanopi-m1.dtb\ + \ + sun8i-h3-nanopi-m1-plus.dtb \ + sun8i-h3-nanopi-neo.dtb \ + sun8i-h3-nanopi-neo-air.dtb \ + sun8i-h3-nanopi-r1.dtb \ + sun8i-h3-orangepi-2.dtb \ + sun8i-h3-orangepi-lite.dtb \ + sun8i-h3-orangepi-one.dtb \ + sun8i-h3-orangepi-pc.dtb \ + sun8i-h3-orangepi-pc-plus.dtb \ + sun8i-h3-orangepi-plus.dtb \ + sun8i-h3-orangepi-plus2e.dtb \ + sun8i-h3-orangepi-zero-plus2.dtb \ + sun8i-h3-rervision-dvk.dtb \ + sun8i-h3-zeropi.dtb \ + sun8i-h3-emlid-neutis-n5h3-devboard.dtb \ + sun8i-r16-bananapi-m2m.dtb \ + sun8i-r16-nintendo-nes-classic.dtb \ + sun8i-r16-nintendo-super-nes-classic.dtb \ + sun8i-r16-parrot.dtb \ + sun8i-r40-bananapi-m2-ultra.dtb \ + sun8i-r40-oka40i-c.dtb \ + sun8i-s3-elimo-initium.dtb \ + sun8i-s3-lichee-zero-plus.dtb \ + sun8i-s3-pinecube.dtb \ + sun8i-t113s-mangopi-mq-r-t113.dtb \ + sun8i-t3-cqa3t-bv3.dtb \ + sun8i-v3-sl631-imx179.dtb \ + sun8i-v3s-licheepi-zero.dtb \ + sun8i-v3s-licheepi-zero-dock.dtb \ + sun8i-v40-bananapi-m2-berry.dtb +dtb-$(CONFIG_MACH_SUN9I) += \ + sun9i-a80-optimus.dtb \ + sun9i-a80-cubieboard4.dtb +dtb-$(CONFIG_MACH_SUNIV) += \ + suniv-f1c100s-licheepi-nano.dtb \ + suniv-f1c200s-lctech-pi.dtb \ + suniv-f1c200s-popstick-v1.1.dtb +dtb-$(CONFIG_MACH_SUNIV) += \ + suniv-f1c100s-licheepi-nano.dtb \ + suniv-f1c200s-lctech-pi.dtb \ + suniv-f1c200s-popstick-v1.1.dtb diff --git a/arch/arm/boot/dts/axp152.dtsi b/arch/arm/boot/dts/allwinner/axp152.dtsi similarity index 100% rename from arch/arm/boot/dts/axp152.dtsi rename to arch/arm/boot/dts/allwinner/axp152.dtsi diff --git a/arch/arm/boot/dts/axp209.dtsi b/arch/arm/boot/dts/allwinner/axp209.dtsi similarity index 96% rename from arch/arm/boot/dts/axp209.dtsi rename to arch/arm/boot/dts/allwinner/axp209.dtsi index ca240cd6f6c3583317eb94c05368cbae8c25ffca..469d0f7d5185c602abbec33e0d2b64b77e26959f 100644 --- a/arch/arm/boot/dts/axp209.dtsi +++ b/arch/arm/boot/dts/allwinner/axp209.dtsi @@ -48,6 +48,13 @@ * http://dl.linux-sunxi.org/AXP/AXP209%20Datasheet%20v1.0_cn.pdf */ +/ { + pmic-temp { + compatible = "iio-hwmon"; + io-channels = <&axp_adc 4>; /* Internal temperature */ + }; +}; + &axp209 { compatible = "x-powers,axp209"; interrupt-controller; diff --git a/arch/arm/boot/dts/axp223.dtsi b/arch/arm/boot/dts/allwinner/axp223.dtsi similarity index 100% rename from arch/arm/boot/dts/axp223.dtsi rename to arch/arm/boot/dts/allwinner/axp223.dtsi diff --git a/arch/arm/boot/dts/axp22x.dtsi b/arch/arm/boot/dts/allwinner/axp22x.dtsi similarity index 100% rename from arch/arm/boot/dts/axp22x.dtsi rename to arch/arm/boot/dts/allwinner/axp22x.dtsi diff --git a/arch/arm/boot/dts/axp809.dtsi b/arch/arm/boot/dts/allwinner/axp809.dtsi similarity index 100% rename from arch/arm/boot/dts/axp809.dtsi rename to arch/arm/boot/dts/allwinner/axp809.dtsi diff --git a/arch/arm/boot/dts/axp81x.dtsi b/arch/arm/boot/dts/allwinner/axp81x.dtsi similarity index 100% rename from arch/arm/boot/dts/axp81x.dtsi rename to arch/arm/boot/dts/allwinner/axp81x.dtsi diff --git a/arch/arm/boot/dts/sun4i-a10-a1000.dts b/arch/arm/boot/dts/allwinner/sun4i-a10-a1000.dts similarity index 100% rename from arch/arm/boot/dts/sun4i-a10-a1000.dts rename to arch/arm/boot/dts/allwinner/sun4i-a10-a1000.dts diff --git a/arch/arm/boot/dts/sun4i-a10-ba10-tvbox.dts b/arch/arm/boot/dts/allwinner/sun4i-a10-ba10-tvbox.dts similarity index 100% rename from arch/arm/boot/dts/sun4i-a10-ba10-tvbox.dts rename to arch/arm/boot/dts/allwinner/sun4i-a10-ba10-tvbox.dts diff --git a/arch/arm/boot/dts/sun4i-a10-chuwi-v7-cw0825.dts b/arch/arm/boot/dts/allwinner/sun4i-a10-chuwi-v7-cw0825.dts similarity index 100% rename from arch/arm/boot/dts/sun4i-a10-chuwi-v7-cw0825.dts rename to arch/arm/boot/dts/allwinner/sun4i-a10-chuwi-v7-cw0825.dts diff --git a/arch/arm/boot/dts/sun4i-a10-cubieboard.dts b/arch/arm/boot/dts/allwinner/sun4i-a10-cubieboard.dts similarity index 100% rename from arch/arm/boot/dts/sun4i-a10-cubieboard.dts rename to arch/arm/boot/dts/allwinner/sun4i-a10-cubieboard.dts diff --git a/arch/arm/boot/dts/sun4i-a10-dserve-dsrv9703c.dts b/arch/arm/boot/dts/allwinner/sun4i-a10-dserve-dsrv9703c.dts similarity index 100% rename from arch/arm/boot/dts/sun4i-a10-dserve-dsrv9703c.dts rename to arch/arm/boot/dts/allwinner/sun4i-a10-dserve-dsrv9703c.dts diff --git a/arch/arm/boot/dts/sun4i-a10-gemei-g9.dts b/arch/arm/boot/dts/allwinner/sun4i-a10-gemei-g9.dts similarity index 100% rename from arch/arm/boot/dts/sun4i-a10-gemei-g9.dts rename to arch/arm/boot/dts/allwinner/sun4i-a10-gemei-g9.dts diff --git a/arch/arm/boot/dts/sun4i-a10-hackberry.dts b/arch/arm/boot/dts/allwinner/sun4i-a10-hackberry.dts similarity index 100% rename from arch/arm/boot/dts/sun4i-a10-hackberry.dts rename to arch/arm/boot/dts/allwinner/sun4i-a10-hackberry.dts diff --git a/arch/arm/boot/dts/sun4i-a10-hyundai-a7hd.dts b/arch/arm/boot/dts/allwinner/sun4i-a10-hyundai-a7hd.dts similarity index 100% rename from arch/arm/boot/dts/sun4i-a10-hyundai-a7hd.dts rename to arch/arm/boot/dts/allwinner/sun4i-a10-hyundai-a7hd.dts diff --git a/arch/arm/boot/dts/sun4i-a10-inet1.dts b/arch/arm/boot/dts/allwinner/sun4i-a10-inet1.dts similarity index 100% rename from arch/arm/boot/dts/sun4i-a10-inet1.dts rename to arch/arm/boot/dts/allwinner/sun4i-a10-inet1.dts diff --git a/arch/arm/boot/dts/sun4i-a10-inet97fv2.dts b/arch/arm/boot/dts/allwinner/sun4i-a10-inet97fv2.dts similarity index 100% rename from arch/arm/boot/dts/sun4i-a10-inet97fv2.dts rename to arch/arm/boot/dts/allwinner/sun4i-a10-inet97fv2.dts diff --git a/arch/arm/boot/dts/sun4i-a10-inet9f-rev03.dts b/arch/arm/boot/dts/allwinner/sun4i-a10-inet9f-rev03.dts similarity index 100% rename from arch/arm/boot/dts/sun4i-a10-inet9f-rev03.dts rename to arch/arm/boot/dts/allwinner/sun4i-a10-inet9f-rev03.dts diff --git a/arch/arm/boot/dts/sun4i-a10-itead-iteaduino-plus.dts b/arch/arm/boot/dts/allwinner/sun4i-a10-itead-iteaduino-plus.dts similarity index 100% rename from arch/arm/boot/dts/sun4i-a10-itead-iteaduino-plus.dts rename to arch/arm/boot/dts/allwinner/sun4i-a10-itead-iteaduino-plus.dts diff --git a/arch/arm/boot/dts/sun4i-a10-jesurun-q5.dts b/arch/arm/boot/dts/allwinner/sun4i-a10-jesurun-q5.dts similarity index 100% rename from arch/arm/boot/dts/sun4i-a10-jesurun-q5.dts rename to arch/arm/boot/dts/allwinner/sun4i-a10-jesurun-q5.dts diff --git a/arch/arm/boot/dts/sun4i-a10-marsboard.dts b/arch/arm/boot/dts/allwinner/sun4i-a10-marsboard.dts similarity index 100% rename from arch/arm/boot/dts/sun4i-a10-marsboard.dts rename to arch/arm/boot/dts/allwinner/sun4i-a10-marsboard.dts diff --git a/arch/arm/boot/dts/sun4i-a10-mini-xplus.dts b/arch/arm/boot/dts/allwinner/sun4i-a10-mini-xplus.dts similarity index 100% rename from arch/arm/boot/dts/sun4i-a10-mini-xplus.dts rename to arch/arm/boot/dts/allwinner/sun4i-a10-mini-xplus.dts diff --git a/arch/arm/boot/dts/sun4i-a10-mk802.dts b/arch/arm/boot/dts/allwinner/sun4i-a10-mk802.dts similarity index 100% rename from arch/arm/boot/dts/sun4i-a10-mk802.dts rename to arch/arm/boot/dts/allwinner/sun4i-a10-mk802.dts diff --git a/arch/arm/boot/dts/sun4i-a10-mk802ii.dts b/arch/arm/boot/dts/allwinner/sun4i-a10-mk802ii.dts similarity index 100% rename from arch/arm/boot/dts/sun4i-a10-mk802ii.dts rename to arch/arm/boot/dts/allwinner/sun4i-a10-mk802ii.dts diff --git a/arch/arm/boot/dts/sun4i-a10-olinuxino-lime.dts b/arch/arm/boot/dts/allwinner/sun4i-a10-olinuxino-lime.dts similarity index 100% rename from arch/arm/boot/dts/sun4i-a10-olinuxino-lime.dts rename to arch/arm/boot/dts/allwinner/sun4i-a10-olinuxino-lime.dts diff --git a/arch/arm/boot/dts/sun4i-a10-pcduino.dts b/arch/arm/boot/dts/allwinner/sun4i-a10-pcduino.dts similarity index 100% rename from arch/arm/boot/dts/sun4i-a10-pcduino.dts rename to arch/arm/boot/dts/allwinner/sun4i-a10-pcduino.dts diff --git a/arch/arm/boot/dts/sun4i-a10-pcduino2.dts b/arch/arm/boot/dts/allwinner/sun4i-a10-pcduino2.dts similarity index 100% rename from arch/arm/boot/dts/sun4i-a10-pcduino2.dts rename to arch/arm/boot/dts/allwinner/sun4i-a10-pcduino2.dts diff --git a/arch/arm/boot/dts/sun4i-a10-pov-protab2-ips9.dts b/arch/arm/boot/dts/allwinner/sun4i-a10-pov-protab2-ips9.dts similarity index 100% rename from arch/arm/boot/dts/sun4i-a10-pov-protab2-ips9.dts rename to arch/arm/boot/dts/allwinner/sun4i-a10-pov-protab2-ips9.dts diff --git a/arch/arm/boot/dts/sun4i-a10-topwise-a721.dts b/arch/arm/boot/dts/allwinner/sun4i-a10-topwise-a721.dts similarity index 100% rename from arch/arm/boot/dts/sun4i-a10-topwise-a721.dts rename to arch/arm/boot/dts/allwinner/sun4i-a10-topwise-a721.dts diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/allwinner/sun4i-a10.dtsi similarity index 100% rename from arch/arm/boot/dts/sun4i-a10.dtsi rename to arch/arm/boot/dts/allwinner/sun4i-a10.dtsi diff --git a/arch/arm/boot/dts/sun5i-a10s-auxtek-t003.dts b/arch/arm/boot/dts/allwinner/sun5i-a10s-auxtek-t003.dts similarity index 100% rename from arch/arm/boot/dts/sun5i-a10s-auxtek-t003.dts rename to arch/arm/boot/dts/allwinner/sun5i-a10s-auxtek-t003.dts diff --git a/arch/arm/boot/dts/sun5i-a10s-auxtek-t004.dts b/arch/arm/boot/dts/allwinner/sun5i-a10s-auxtek-t004.dts similarity index 100% rename from arch/arm/boot/dts/sun5i-a10s-auxtek-t004.dts rename to arch/arm/boot/dts/allwinner/sun5i-a10s-auxtek-t004.dts diff --git a/arch/arm/boot/dts/sun5i-a10s-mk802.dts b/arch/arm/boot/dts/allwinner/sun5i-a10s-mk802.dts similarity index 100% rename from arch/arm/boot/dts/sun5i-a10s-mk802.dts rename to arch/arm/boot/dts/allwinner/sun5i-a10s-mk802.dts diff --git a/arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts b/arch/arm/boot/dts/allwinner/sun5i-a10s-olinuxino-micro.dts similarity index 100% rename from arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts rename to arch/arm/boot/dts/allwinner/sun5i-a10s-olinuxino-micro.dts diff --git a/arch/arm/boot/dts/sun5i-a10s-r7-tv-dongle.dts b/arch/arm/boot/dts/allwinner/sun5i-a10s-r7-tv-dongle.dts similarity index 100% rename from arch/arm/boot/dts/sun5i-a10s-r7-tv-dongle.dts rename to arch/arm/boot/dts/allwinner/sun5i-a10s-r7-tv-dongle.dts diff --git a/arch/arm/boot/dts/sun5i-a10s-wobo-i5.dts b/arch/arm/boot/dts/allwinner/sun5i-a10s-wobo-i5.dts similarity index 100% rename from arch/arm/boot/dts/sun5i-a10s-wobo-i5.dts rename to arch/arm/boot/dts/allwinner/sun5i-a10s-wobo-i5.dts diff --git a/arch/arm/boot/dts/sun5i-a10s.dtsi b/arch/arm/boot/dts/allwinner/sun5i-a10s.dtsi similarity index 100% rename from arch/arm/boot/dts/sun5i-a10s.dtsi rename to arch/arm/boot/dts/allwinner/sun5i-a10s.dtsi diff --git a/arch/arm/boot/dts/sun5i-a13-difrnce-dit4350.dts b/arch/arm/boot/dts/allwinner/sun5i-a13-difrnce-dit4350.dts similarity index 100% rename from arch/arm/boot/dts/sun5i-a13-difrnce-dit4350.dts rename to arch/arm/boot/dts/allwinner/sun5i-a13-difrnce-dit4350.dts diff --git a/arch/arm/boot/dts/sun5i-a13-empire-electronix-d709.dts b/arch/arm/boot/dts/allwinner/sun5i-a13-empire-electronix-d709.dts similarity index 100% rename from arch/arm/boot/dts/sun5i-a13-empire-electronix-d709.dts rename to arch/arm/boot/dts/allwinner/sun5i-a13-empire-electronix-d709.dts diff --git a/arch/arm/boot/dts/sun5i-a13-empire-electronix-m712.dts b/arch/arm/boot/dts/allwinner/sun5i-a13-empire-electronix-m712.dts similarity index 100% rename from arch/arm/boot/dts/sun5i-a13-empire-electronix-m712.dts rename to arch/arm/boot/dts/allwinner/sun5i-a13-empire-electronix-m712.dts diff --git a/arch/arm/boot/dts/sun5i-a13-hsg-h702.dts b/arch/arm/boot/dts/allwinner/sun5i-a13-hsg-h702.dts similarity index 100% rename from arch/arm/boot/dts/sun5i-a13-hsg-h702.dts rename to arch/arm/boot/dts/allwinner/sun5i-a13-hsg-h702.dts diff --git a/arch/arm/boot/dts/sun5i-a13-inet-98v-rev2.dts b/arch/arm/boot/dts/allwinner/sun5i-a13-inet-98v-rev2.dts similarity index 100% rename from arch/arm/boot/dts/sun5i-a13-inet-98v-rev2.dts rename to arch/arm/boot/dts/allwinner/sun5i-a13-inet-98v-rev2.dts diff --git a/arch/arm/boot/dts/sun5i-a13-licheepi-one.dts b/arch/arm/boot/dts/allwinner/sun5i-a13-licheepi-one.dts similarity index 100% rename from arch/arm/boot/dts/sun5i-a13-licheepi-one.dts rename to arch/arm/boot/dts/allwinner/sun5i-a13-licheepi-one.dts diff --git a/arch/arm/boot/dts/sun5i-a13-olinuxino-micro.dts b/arch/arm/boot/dts/allwinner/sun5i-a13-olinuxino-micro.dts similarity index 100% rename from arch/arm/boot/dts/sun5i-a13-olinuxino-micro.dts rename to arch/arm/boot/dts/allwinner/sun5i-a13-olinuxino-micro.dts diff --git a/arch/arm/boot/dts/sun5i-a13-olinuxino.dts b/arch/arm/boot/dts/allwinner/sun5i-a13-olinuxino.dts similarity index 100% rename from arch/arm/boot/dts/sun5i-a13-olinuxino.dts rename to arch/arm/boot/dts/allwinner/sun5i-a13-olinuxino.dts diff --git a/arch/arm/boot/dts/sun5i-a13-pocketbook-touch-lux-3.dts b/arch/arm/boot/dts/allwinner/sun5i-a13-pocketbook-touch-lux-3.dts similarity index 100% rename from arch/arm/boot/dts/sun5i-a13-pocketbook-touch-lux-3.dts rename to arch/arm/boot/dts/allwinner/sun5i-a13-pocketbook-touch-lux-3.dts diff --git a/arch/arm/boot/dts/sun5i-a13-q8-tablet.dts b/arch/arm/boot/dts/allwinner/sun5i-a13-q8-tablet.dts similarity index 100% rename from arch/arm/boot/dts/sun5i-a13-q8-tablet.dts rename to arch/arm/boot/dts/allwinner/sun5i-a13-q8-tablet.dts diff --git a/arch/arm/boot/dts/sun5i-a13-utoo-p66.dts b/arch/arm/boot/dts/allwinner/sun5i-a13-utoo-p66.dts similarity index 100% rename from arch/arm/boot/dts/sun5i-a13-utoo-p66.dts rename to arch/arm/boot/dts/allwinner/sun5i-a13-utoo-p66.dts diff --git a/arch/arm/boot/dts/sun5i-a13.dtsi b/arch/arm/boot/dts/allwinner/sun5i-a13.dtsi similarity index 100% rename from arch/arm/boot/dts/sun5i-a13.dtsi rename to arch/arm/boot/dts/allwinner/sun5i-a13.dtsi diff --git a/arch/arm/boot/dts/sun5i-gr8-chip-pro.dts b/arch/arm/boot/dts/allwinner/sun5i-gr8-chip-pro.dts similarity index 100% rename from arch/arm/boot/dts/sun5i-gr8-chip-pro.dts rename to arch/arm/boot/dts/allwinner/sun5i-gr8-chip-pro.dts diff --git a/arch/arm/boot/dts/sun5i-gr8-evb.dts b/arch/arm/boot/dts/allwinner/sun5i-gr8-evb.dts similarity index 100% rename from arch/arm/boot/dts/sun5i-gr8-evb.dts rename to arch/arm/boot/dts/allwinner/sun5i-gr8-evb.dts diff --git a/arch/arm/boot/dts/sun5i-gr8.dtsi b/arch/arm/boot/dts/allwinner/sun5i-gr8.dtsi similarity index 100% rename from arch/arm/boot/dts/sun5i-gr8.dtsi rename to arch/arm/boot/dts/allwinner/sun5i-gr8.dtsi diff --git a/arch/arm/boot/dts/sun5i-r8-chip.dts b/arch/arm/boot/dts/allwinner/sun5i-r8-chip.dts similarity index 97% rename from arch/arm/boot/dts/sun5i-r8-chip.dts rename to arch/arm/boot/dts/allwinner/sun5i-r8-chip.dts index fd37bd1f3920857f51ae9257a625f3c497bbe0c6..4192c23848c316c29ed874ebb85b52ab64c8ce11 100644 --- a/arch/arm/boot/dts/sun5i-r8-chip.dts +++ b/arch/arm/boot/dts/allwinner/sun5i-r8-chip.dts @@ -255,6 +255,12 @@ pinctrl-0 = <&uart3_pg_pins>, <&uart3_cts_rts_pg_pins>; status = "okay"; + + bluetooth { + compatible = "realtek,rtl8723bs-bt"; + device-wake-gpios = <&axp_gpio 3 GPIO_ACTIVE_HIGH>; + host-wake-gpios = <&pio 1 3 GPIO_ACTIVE_HIGH>; /* PB3 */ + }; }; &usb_otg { diff --git a/arch/arm/boot/dts/sun5i-r8.dtsi b/arch/arm/boot/dts/allwinner/sun5i-r8.dtsi similarity index 100% rename from arch/arm/boot/dts/sun5i-r8.dtsi rename to arch/arm/boot/dts/allwinner/sun5i-r8.dtsi diff --git a/arch/arm/boot/dts/sun5i-reference-design-tablet.dtsi b/arch/arm/boot/dts/allwinner/sun5i-reference-design-tablet.dtsi similarity index 100% rename from arch/arm/boot/dts/sun5i-reference-design-tablet.dtsi rename to arch/arm/boot/dts/allwinner/sun5i-reference-design-tablet.dtsi diff --git a/arch/arm/boot/dts/sun5i.dtsi b/arch/arm/boot/dts/allwinner/sun5i.dtsi similarity index 98% rename from arch/arm/boot/dts/sun5i.dtsi rename to arch/arm/boot/dts/allwinner/sun5i.dtsi index 250d6b87ab4d92852e478c4322977a3c433e49b2..d7c7b454a11a3541df97d53a7af3f23f6689ef08 100644 --- a/arch/arm/boot/dts/sun5i.dtsi +++ b/arch/arm/boot/dts/allwinner/sun5i.dtsi @@ -286,7 +286,7 @@ clock-names = "ahb", "tcon-ch0", "tcon-ch1"; - clock-output-names = "tcon-pixel-clock"; + clock-output-names = "tcon-data-clock"; #clock-cells = <0>; status = "disabled"; @@ -517,6 +517,15 @@ bias-pull-up; }; + /omit-if-no-ref/ + mmc2_4bit_pe_pins: mmc2-4bit-pe-pins { + pins = "PE4", "PE5", "PE6", "PE7", + "PE8", "PE9"; + function = "mmc2"; + drive-strength = <30>; + bias-pull-up; + }; + mmc2_8bit_pins: mmc2-8bit-pins { pins = "PC6", "PC7", "PC8", "PC9", "PC10", "PC11", "PC12", "PC13", diff --git a/arch/arm/boot/dts/sun6i-a31-app4-evb1.dts b/arch/arm/boot/dts/allwinner/sun6i-a31-app4-evb1.dts similarity index 100% rename from arch/arm/boot/dts/sun6i-a31-app4-evb1.dts rename to arch/arm/boot/dts/allwinner/sun6i-a31-app4-evb1.dts diff --git a/arch/arm/boot/dts/sun6i-a31-colombus.dts b/arch/arm/boot/dts/allwinner/sun6i-a31-colombus.dts similarity index 100% rename from arch/arm/boot/dts/sun6i-a31-colombus.dts rename to arch/arm/boot/dts/allwinner/sun6i-a31-colombus.dts diff --git a/arch/arm/boot/dts/sun6i-a31-hummingbird.dts b/arch/arm/boot/dts/allwinner/sun6i-a31-hummingbird.dts similarity index 100% rename from arch/arm/boot/dts/sun6i-a31-hummingbird.dts rename to arch/arm/boot/dts/allwinner/sun6i-a31-hummingbird.dts diff --git a/arch/arm/boot/dts/sun6i-a31-i7.dts b/arch/arm/boot/dts/allwinner/sun6i-a31-i7.dts similarity index 100% rename from arch/arm/boot/dts/sun6i-a31-i7.dts rename to arch/arm/boot/dts/allwinner/sun6i-a31-i7.dts diff --git a/arch/arm/boot/dts/sun6i-a31-m9.dts b/arch/arm/boot/dts/allwinner/sun6i-a31-m9.dts similarity index 100% rename from arch/arm/boot/dts/sun6i-a31-m9.dts rename to arch/arm/boot/dts/allwinner/sun6i-a31-m9.dts diff --git a/arch/arm/boot/dts/sun6i-a31-mele-a1000g-quad.dts b/arch/arm/boot/dts/allwinner/sun6i-a31-mele-a1000g-quad.dts similarity index 100% rename from arch/arm/boot/dts/sun6i-a31-mele-a1000g-quad.dts rename to arch/arm/boot/dts/allwinner/sun6i-a31-mele-a1000g-quad.dts diff --git a/arch/arm/boot/dts/sun6i-a31.dtsi b/arch/arm/boot/dts/allwinner/sun6i-a31.dtsi similarity index 100% rename from arch/arm/boot/dts/sun6i-a31.dtsi rename to arch/arm/boot/dts/allwinner/sun6i-a31.dtsi diff --git a/arch/arm/boot/dts/sun6i-a31s-colorfly-e708-q1.dts b/arch/arm/boot/dts/allwinner/sun6i-a31s-colorfly-e708-q1.dts similarity index 100% rename from arch/arm/boot/dts/sun6i-a31s-colorfly-e708-q1.dts rename to arch/arm/boot/dts/allwinner/sun6i-a31s-colorfly-e708-q1.dts diff --git a/arch/arm/boot/dts/sun6i-a31s-cs908.dts b/arch/arm/boot/dts/allwinner/sun6i-a31s-cs908.dts similarity index 100% rename from arch/arm/boot/dts/sun6i-a31s-cs908.dts rename to arch/arm/boot/dts/allwinner/sun6i-a31s-cs908.dts diff --git a/arch/arm/boot/dts/sun6i-a31s-inet-q972.dts b/arch/arm/boot/dts/allwinner/sun6i-a31s-inet-q972.dts similarity index 100% rename from arch/arm/boot/dts/sun6i-a31s-inet-q972.dts rename to arch/arm/boot/dts/allwinner/sun6i-a31s-inet-q972.dts diff --git a/arch/arm/boot/dts/sun6i-a31s-primo81.dts b/arch/arm/boot/dts/allwinner/sun6i-a31s-primo81.dts similarity index 100% rename from arch/arm/boot/dts/sun6i-a31s-primo81.dts rename to arch/arm/boot/dts/allwinner/sun6i-a31s-primo81.dts diff --git a/arch/arm/boot/dts/sun6i-a31s-sina31s-core.dtsi b/arch/arm/boot/dts/allwinner/sun6i-a31s-sina31s-core.dtsi similarity index 100% rename from arch/arm/boot/dts/sun6i-a31s-sina31s-core.dtsi rename to arch/arm/boot/dts/allwinner/sun6i-a31s-sina31s-core.dtsi diff --git a/arch/arm/boot/dts/sun6i-a31s-sina31s.dts b/arch/arm/boot/dts/allwinner/sun6i-a31s-sina31s.dts similarity index 100% rename from arch/arm/boot/dts/sun6i-a31s-sina31s.dts rename to arch/arm/boot/dts/allwinner/sun6i-a31s-sina31s.dts diff --git a/arch/arm/boot/dts/sun6i-a31s-sinovoip-bpi-m2.dts b/arch/arm/boot/dts/allwinner/sun6i-a31s-sinovoip-bpi-m2.dts similarity index 100% rename from arch/arm/boot/dts/sun6i-a31s-sinovoip-bpi-m2.dts rename to arch/arm/boot/dts/allwinner/sun6i-a31s-sinovoip-bpi-m2.dts diff --git a/arch/arm/boot/dts/sun6i-a31s-yones-toptech-bs1078-v2.dts b/arch/arm/boot/dts/allwinner/sun6i-a31s-yones-toptech-bs1078-v2.dts similarity index 100% rename from arch/arm/boot/dts/sun6i-a31s-yones-toptech-bs1078-v2.dts rename to arch/arm/boot/dts/allwinner/sun6i-a31s-yones-toptech-bs1078-v2.dts diff --git a/arch/arm/boot/dts/sun6i-a31s.dtsi b/arch/arm/boot/dts/allwinner/sun6i-a31s.dtsi similarity index 100% rename from arch/arm/boot/dts/sun6i-a31s.dtsi rename to arch/arm/boot/dts/allwinner/sun6i-a31s.dtsi diff --git a/arch/arm/boot/dts/sun6i-reference-design-tablet.dtsi b/arch/arm/boot/dts/allwinner/sun6i-reference-design-tablet.dtsi similarity index 100% rename from arch/arm/boot/dts/sun6i-reference-design-tablet.dtsi rename to arch/arm/boot/dts/allwinner/sun6i-reference-design-tablet.dtsi diff --git a/arch/arm/boot/dts/sun7i-a20-bananapi-m1-plus.dts b/arch/arm/boot/dts/allwinner/sun7i-a20-bananapi-m1-plus.dts similarity index 100% rename from arch/arm/boot/dts/sun7i-a20-bananapi-m1-plus.dts rename to arch/arm/boot/dts/allwinner/sun7i-a20-bananapi-m1-plus.dts diff --git a/arch/arm/boot/dts/sun7i-a20-bananapi.dts b/arch/arm/boot/dts/allwinner/sun7i-a20-bananapi.dts similarity index 100% rename from arch/arm/boot/dts/sun7i-a20-bananapi.dts rename to arch/arm/boot/dts/allwinner/sun7i-a20-bananapi.dts diff --git a/arch/arm/boot/dts/sun7i-a20-bananapro.dts b/arch/arm/boot/dts/allwinner/sun7i-a20-bananapro.dts similarity index 100% rename from arch/arm/boot/dts/sun7i-a20-bananapro.dts rename to arch/arm/boot/dts/allwinner/sun7i-a20-bananapro.dts diff --git a/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts b/arch/arm/boot/dts/allwinner/sun7i-a20-cubieboard2.dts similarity index 100% rename from arch/arm/boot/dts/sun7i-a20-cubieboard2.dts rename to arch/arm/boot/dts/allwinner/sun7i-a20-cubieboard2.dts diff --git a/arch/arm/boot/dts/sun7i-a20-cubietruck.dts b/arch/arm/boot/dts/allwinner/sun7i-a20-cubietruck.dts similarity index 100% rename from arch/arm/boot/dts/sun7i-a20-cubietruck.dts rename to arch/arm/boot/dts/allwinner/sun7i-a20-cubietruck.dts diff --git a/arch/arm/boot/dts/sun7i-a20-haoyu-marsboard.dts b/arch/arm/boot/dts/allwinner/sun7i-a20-haoyu-marsboard.dts similarity index 100% rename from arch/arm/boot/dts/sun7i-a20-haoyu-marsboard.dts rename to arch/arm/boot/dts/allwinner/sun7i-a20-haoyu-marsboard.dts diff --git a/arch/arm/boot/dts/sun7i-a20-hummingbird.dts b/arch/arm/boot/dts/allwinner/sun7i-a20-hummingbird.dts similarity index 100% rename from arch/arm/boot/dts/sun7i-a20-hummingbird.dts rename to arch/arm/boot/dts/allwinner/sun7i-a20-hummingbird.dts diff --git a/arch/arm/boot/dts/sun7i-a20-i12-tvbox.dts b/arch/arm/boot/dts/allwinner/sun7i-a20-i12-tvbox.dts similarity index 100% rename from arch/arm/boot/dts/sun7i-a20-i12-tvbox.dts rename to arch/arm/boot/dts/allwinner/sun7i-a20-i12-tvbox.dts diff --git a/arch/arm/boot/dts/allwinner/sun7i-a20-icnova-a20-adb4006.dts b/arch/arm/boot/dts/allwinner/sun7i-a20-icnova-a20-adb4006.dts new file mode 100644 index 0000000000000000000000000000000000000000..577ead1d02a0f412f0e16d37b4f1198e7d5d613c --- /dev/null +++ b/arch/arm/boot/dts/allwinner/sun7i-a20-icnova-a20-adb4006.dts @@ -0,0 +1,137 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +// Copyright (C) 2023 In-Circuit GmbH + +/dts-v1/; + +#include "sun7i-a20-icnova-a20.dtsi" + +#include +#include + +/ { + model = "In-Circuit ICnova A20 ADB4006"; + compatible = "incircuit,icnova-a20-adb4006", "incircuit,icnova-a20", + "allwinner,sun7i-a20"; + + aliases { + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + hdmi-connector { + compatible = "hdmi-connector"; + type = "a"; + + port { + hdmi_con_in: endpoint { + remote-endpoint = <&hdmi_out_con>; + }; + }; + }; + + leds { + compatible = "gpio-leds"; + + led-0 { + function = LED_FUNCTION_POWER; + color = ; + gpios = <&pio 7 21 GPIO_ACTIVE_HIGH>; /* PH21 */ + default-state = "on"; + }; + + led-1 { + function = LED_FUNCTION_HEARTBEAT; + color = ; + gpios = <&pio 7 20 GPIO_ACTIVE_HIGH>; /* PH20 */ + linux,default-trigger = "heartbeat"; + }; + }; +}; + +&ahci { + target-supply = <®_ahci_5v>; + status = "okay"; +}; + +&codec { + status = "okay"; +}; + +&de { + status = "okay"; +}; + +&ehci0 { + status = "okay"; +}; + +&ehci1 { + status = "okay"; +}; + +&hdmi { + status = "okay"; +}; + +&hdmi_out { + hdmi_out_con: endpoint { + remote-endpoint = <&hdmi_con_in>; + }; +}; + +&mmc0 { + vmmc-supply = <®_vcc3v3>; + bus-width = <4>; + cd-gpios = <&pio 7 1 GPIO_ACTIVE_LOW>; /* PH1 */ + status = "okay"; +}; + +&ohci0 { + status = "okay"; +}; + +&ohci1 { + status = "okay"; +}; + +&otg_sram { + status = "okay"; +}; + +®_ahci_5v { + status = "okay"; +}; + +&ac_power_supply { + status = "okay"; +}; + +®_usb1_vbus { + status = "okay"; +}; + +®_usb2_vbus { + status = "okay"; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pb_pins>; + status = "okay"; +}; + +&usb_otg { + dr_mode = "otg"; + status = "okay"; +}; + +&usbphy { + usb0_id_det-gpios = <&pio 7 4 GPIO_ACTIVE_HIGH>; /* PH4 */ + usb0_vbus_det-gpios = <&pio 7 5 GPIO_ACTIVE_HIGH>; /* PH5 */ + usb1_vbus-supply = <®_usb1_vbus>; + usb2_vbus-supply = <®_usb2_vbus>; + status = "okay"; +}; diff --git a/arch/arm/boot/dts/allwinner/sun7i-a20-icnova-a20.dtsi b/arch/arm/boot/dts/allwinner/sun7i-a20-icnova-a20.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..46616c6bc89912d602dbf5fd16bcd3f723d64060 --- /dev/null +++ b/arch/arm/boot/dts/allwinner/sun7i-a20-icnova-a20.dtsi @@ -0,0 +1,62 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +// Copyright (C) 2023 In-Circuit GmbH + +#include "sun7i-a20.dtsi" +#include "sunxi-common-regulators.dtsi" + +#include + +&cpu0 { + cpu-supply = <®_dcdc2>; +}; + +&gmac { + pinctrl-names = "default"; + pinctrl-0 = <&gmac_mii_pins>; + phy-handle = <&phy1>; + phy-mode = "mii"; + status = "okay"; +}; + +&i2c0 { + status = "okay"; + + axp209: pmic@34 { + reg = <0x34>; + interrupt-parent = <&nmi_intc>; + interrupts = <0 IRQ_TYPE_LEVEL_LOW>; + }; +}; + +&gmac_mdio { + phy1: ethernet-phy@1 { + reg = <1>; + }; +}; + +#include "axp209.dtsi" + +®_dcdc2 { + regulator-always-on; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1400000>; + regulator-name = "vdd-cpu"; +}; + +®_dcdc3 { + regulator-always-on; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1400000>; + regulator-name = "vdd-int-dll"; +}; + +®_ldo1 { + regulator-name = "vdd-rtc"; +}; + +®_ldo2 { + regulator-always-on; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + regulator-name = "avcc"; +}; diff --git a/arch/arm/boot/dts/sun7i-a20-icnova-swac.dts b/arch/arm/boot/dts/allwinner/sun7i-a20-icnova-swac.dts similarity index 100% rename from arch/arm/boot/dts/sun7i-a20-icnova-swac.dts rename to arch/arm/boot/dts/allwinner/sun7i-a20-icnova-swac.dts diff --git a/arch/arm/boot/dts/sun7i-a20-itead-ibox.dts b/arch/arm/boot/dts/allwinner/sun7i-a20-itead-ibox.dts similarity index 100% rename from arch/arm/boot/dts/sun7i-a20-itead-ibox.dts rename to arch/arm/boot/dts/allwinner/sun7i-a20-itead-ibox.dts diff --git a/arch/arm/boot/dts/sun7i-a20-lamobo-r1.dts b/arch/arm/boot/dts/allwinner/sun7i-a20-lamobo-r1.dts similarity index 100% rename from arch/arm/boot/dts/sun7i-a20-lamobo-r1.dts rename to arch/arm/boot/dts/allwinner/sun7i-a20-lamobo-r1.dts diff --git a/arch/arm/boot/dts/sun7i-a20-linutronix-testbox-v2.dts b/arch/arm/boot/dts/allwinner/sun7i-a20-linutronix-testbox-v2.dts similarity index 100% rename from arch/arm/boot/dts/sun7i-a20-linutronix-testbox-v2.dts rename to arch/arm/boot/dts/allwinner/sun7i-a20-linutronix-testbox-v2.dts diff --git a/arch/arm/boot/dts/sun7i-a20-m3.dts b/arch/arm/boot/dts/allwinner/sun7i-a20-m3.dts similarity index 100% rename from arch/arm/boot/dts/sun7i-a20-m3.dts rename to arch/arm/boot/dts/allwinner/sun7i-a20-m3.dts diff --git a/arch/arm/boot/dts/sun7i-a20-mk808c.dts b/arch/arm/boot/dts/allwinner/sun7i-a20-mk808c.dts similarity index 100% rename from arch/arm/boot/dts/sun7i-a20-mk808c.dts rename to arch/arm/boot/dts/allwinner/sun7i-a20-mk808c.dts diff --git a/arch/arm/boot/dts/sun7i-a20-olimex-som-evb-emmc.dts b/arch/arm/boot/dts/allwinner/sun7i-a20-olimex-som-evb-emmc.dts similarity index 100% rename from arch/arm/boot/dts/sun7i-a20-olimex-som-evb-emmc.dts rename to arch/arm/boot/dts/allwinner/sun7i-a20-olimex-som-evb-emmc.dts diff --git a/arch/arm/boot/dts/sun7i-a20-olimex-som-evb.dts b/arch/arm/boot/dts/allwinner/sun7i-a20-olimex-som-evb.dts similarity index 100% rename from arch/arm/boot/dts/sun7i-a20-olimex-som-evb.dts rename to arch/arm/boot/dts/allwinner/sun7i-a20-olimex-som-evb.dts diff --git a/arch/arm/boot/dts/sun7i-a20-olimex-som204-evb-emmc.dts b/arch/arm/boot/dts/allwinner/sun7i-a20-olimex-som204-evb-emmc.dts similarity index 100% rename from arch/arm/boot/dts/sun7i-a20-olimex-som204-evb-emmc.dts rename to arch/arm/boot/dts/allwinner/sun7i-a20-olimex-som204-evb-emmc.dts diff --git a/arch/arm/boot/dts/sun7i-a20-olimex-som204-evb.dts b/arch/arm/boot/dts/allwinner/sun7i-a20-olimex-som204-evb.dts similarity index 100% rename from arch/arm/boot/dts/sun7i-a20-olimex-som204-evb.dts rename to arch/arm/boot/dts/allwinner/sun7i-a20-olimex-som204-evb.dts diff --git a/arch/arm/boot/dts/sun7i-a20-olinuxino-lime-emmc.dts b/arch/arm/boot/dts/allwinner/sun7i-a20-olinuxino-lime-emmc.dts similarity index 100% rename from arch/arm/boot/dts/sun7i-a20-olinuxino-lime-emmc.dts rename to arch/arm/boot/dts/allwinner/sun7i-a20-olinuxino-lime-emmc.dts diff --git a/arch/arm/boot/dts/sun7i-a20-olinuxino-lime.dts b/arch/arm/boot/dts/allwinner/sun7i-a20-olinuxino-lime.dts similarity index 100% rename from arch/arm/boot/dts/sun7i-a20-olinuxino-lime.dts rename to arch/arm/boot/dts/allwinner/sun7i-a20-olinuxino-lime.dts diff --git a/arch/arm/boot/dts/sun7i-a20-olinuxino-lime2-emmc.dts b/arch/arm/boot/dts/allwinner/sun7i-a20-olinuxino-lime2-emmc.dts similarity index 100% rename from arch/arm/boot/dts/sun7i-a20-olinuxino-lime2-emmc.dts rename to arch/arm/boot/dts/allwinner/sun7i-a20-olinuxino-lime2-emmc.dts diff --git a/arch/arm/boot/dts/sun7i-a20-olinuxino-lime2.dts b/arch/arm/boot/dts/allwinner/sun7i-a20-olinuxino-lime2.dts similarity index 100% rename from arch/arm/boot/dts/sun7i-a20-olinuxino-lime2.dts rename to arch/arm/boot/dts/allwinner/sun7i-a20-olinuxino-lime2.dts diff --git a/arch/arm/boot/dts/sun7i-a20-olinuxino-micro-emmc.dts b/arch/arm/boot/dts/allwinner/sun7i-a20-olinuxino-micro-emmc.dts similarity index 100% rename from arch/arm/boot/dts/sun7i-a20-olinuxino-micro-emmc.dts rename to arch/arm/boot/dts/allwinner/sun7i-a20-olinuxino-micro-emmc.dts diff --git a/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts b/arch/arm/boot/dts/allwinner/sun7i-a20-olinuxino-micro.dts similarity index 100% rename from arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts rename to arch/arm/boot/dts/allwinner/sun7i-a20-olinuxino-micro.dts diff --git a/arch/arm/boot/dts/sun7i-a20-orangepi-mini.dts b/arch/arm/boot/dts/allwinner/sun7i-a20-orangepi-mini.dts similarity index 100% rename from arch/arm/boot/dts/sun7i-a20-orangepi-mini.dts rename to arch/arm/boot/dts/allwinner/sun7i-a20-orangepi-mini.dts diff --git a/arch/arm/boot/dts/sun7i-a20-orangepi.dts b/arch/arm/boot/dts/allwinner/sun7i-a20-orangepi.dts similarity index 100% rename from arch/arm/boot/dts/sun7i-a20-orangepi.dts rename to arch/arm/boot/dts/allwinner/sun7i-a20-orangepi.dts diff --git a/arch/arm/boot/dts/sun7i-a20-pcduino3-nano.dts b/arch/arm/boot/dts/allwinner/sun7i-a20-pcduino3-nano.dts similarity index 100% rename from arch/arm/boot/dts/sun7i-a20-pcduino3-nano.dts rename to arch/arm/boot/dts/allwinner/sun7i-a20-pcduino3-nano.dts diff --git a/arch/arm/boot/dts/sun7i-a20-pcduino3.dts b/arch/arm/boot/dts/allwinner/sun7i-a20-pcduino3.dts similarity index 100% rename from arch/arm/boot/dts/sun7i-a20-pcduino3.dts rename to arch/arm/boot/dts/allwinner/sun7i-a20-pcduino3.dts diff --git a/arch/arm/boot/dts/sun7i-a20-wexler-tab7200.dts b/arch/arm/boot/dts/allwinner/sun7i-a20-wexler-tab7200.dts similarity index 100% rename from arch/arm/boot/dts/sun7i-a20-wexler-tab7200.dts rename to arch/arm/boot/dts/allwinner/sun7i-a20-wexler-tab7200.dts diff --git a/arch/arm/boot/dts/sun7i-a20-wits-pro-a20-dkt.dts b/arch/arm/boot/dts/allwinner/sun7i-a20-wits-pro-a20-dkt.dts similarity index 100% rename from arch/arm/boot/dts/sun7i-a20-wits-pro-a20-dkt.dts rename to arch/arm/boot/dts/allwinner/sun7i-a20-wits-pro-a20-dkt.dts diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/allwinner/sun7i-a20.dtsi similarity index 100% rename from arch/arm/boot/dts/sun7i-a20.dtsi rename to arch/arm/boot/dts/allwinner/sun7i-a20.dtsi diff --git a/arch/arm/boot/dts/sun8i-a23-a33.dtsi b/arch/arm/boot/dts/allwinner/sun8i-a23-a33.dtsi similarity index 99% rename from arch/arm/boot/dts/sun8i-a23-a33.dtsi rename to arch/arm/boot/dts/allwinner/sun8i-a23-a33.dtsi index 4aa9d88c9ea3a4bf06841c051cb3377d3a1b70fa..cd4bf60dbb3cb1bdfbf9224e5f94f4933a69c89d 100644 --- a/arch/arm/boot/dts/sun8i-a23-a33.dtsi +++ b/arch/arm/boot/dts/allwinner/sun8i-a23-a33.dtsi @@ -190,7 +190,7 @@ clock-names = "ahb", "tcon-ch0", "lvds-alt"; - clock-output-names = "tcon-pixel-clock"; + clock-output-names = "tcon-data-clock"; #clock-cells = <0>; resets = <&ccu RST_BUS_LCD>, <&ccu RST_BUS_LVDS>; diff --git a/arch/arm/boot/dts/sun8i-a23-evb.dts b/arch/arm/boot/dts/allwinner/sun8i-a23-evb.dts similarity index 100% rename from arch/arm/boot/dts/sun8i-a23-evb.dts rename to arch/arm/boot/dts/allwinner/sun8i-a23-evb.dts diff --git a/arch/arm/boot/dts/sun8i-a23-gt90h-v4.dts b/arch/arm/boot/dts/allwinner/sun8i-a23-gt90h-v4.dts similarity index 100% rename from arch/arm/boot/dts/sun8i-a23-gt90h-v4.dts rename to arch/arm/boot/dts/allwinner/sun8i-a23-gt90h-v4.dts diff --git a/arch/arm/boot/dts/sun8i-a23-inet86dz.dts b/arch/arm/boot/dts/allwinner/sun8i-a23-inet86dz.dts similarity index 100% rename from arch/arm/boot/dts/sun8i-a23-inet86dz.dts rename to arch/arm/boot/dts/allwinner/sun8i-a23-inet86dz.dts diff --git a/arch/arm/boot/dts/sun8i-a23-ippo-q8h-v1.2.dts b/arch/arm/boot/dts/allwinner/sun8i-a23-ippo-q8h-v1.2.dts similarity index 100% rename from arch/arm/boot/dts/sun8i-a23-ippo-q8h-v1.2.dts rename to arch/arm/boot/dts/allwinner/sun8i-a23-ippo-q8h-v1.2.dts diff --git a/arch/arm/boot/dts/sun8i-a23-ippo-q8h-v5.dts b/arch/arm/boot/dts/allwinner/sun8i-a23-ippo-q8h-v5.dts similarity index 100% rename from arch/arm/boot/dts/sun8i-a23-ippo-q8h-v5.dts rename to arch/arm/boot/dts/allwinner/sun8i-a23-ippo-q8h-v5.dts diff --git a/arch/arm/boot/dts/sun8i-a23-polaroid-mid2407pxe03.dts b/arch/arm/boot/dts/allwinner/sun8i-a23-polaroid-mid2407pxe03.dts similarity index 100% rename from arch/arm/boot/dts/sun8i-a23-polaroid-mid2407pxe03.dts rename to arch/arm/boot/dts/allwinner/sun8i-a23-polaroid-mid2407pxe03.dts diff --git a/arch/arm/boot/dts/sun8i-a23-polaroid-mid2809pxe04.dts b/arch/arm/boot/dts/allwinner/sun8i-a23-polaroid-mid2809pxe04.dts similarity index 100% rename from arch/arm/boot/dts/sun8i-a23-polaroid-mid2809pxe04.dts rename to arch/arm/boot/dts/allwinner/sun8i-a23-polaroid-mid2809pxe04.dts diff --git a/arch/arm/boot/dts/sun8i-a23-q8-tablet.dts b/arch/arm/boot/dts/allwinner/sun8i-a23-q8-tablet.dts similarity index 100% rename from arch/arm/boot/dts/sun8i-a23-q8-tablet.dts rename to arch/arm/boot/dts/allwinner/sun8i-a23-q8-tablet.dts diff --git a/arch/arm/boot/dts/sun8i-a23.dtsi b/arch/arm/boot/dts/allwinner/sun8i-a23.dtsi similarity index 100% rename from arch/arm/boot/dts/sun8i-a23.dtsi rename to arch/arm/boot/dts/allwinner/sun8i-a23.dtsi diff --git a/arch/arm/boot/dts/sun8i-a33-et-q8-v1.6.dts b/arch/arm/boot/dts/allwinner/sun8i-a33-et-q8-v1.6.dts similarity index 100% rename from arch/arm/boot/dts/sun8i-a33-et-q8-v1.6.dts rename to arch/arm/boot/dts/allwinner/sun8i-a33-et-q8-v1.6.dts diff --git a/arch/arm/boot/dts/sun8i-a33-ga10h-v1.1.dts b/arch/arm/boot/dts/allwinner/sun8i-a33-ga10h-v1.1.dts similarity index 100% rename from arch/arm/boot/dts/sun8i-a33-ga10h-v1.1.dts rename to arch/arm/boot/dts/allwinner/sun8i-a33-ga10h-v1.1.dts diff --git a/arch/arm/boot/dts/sun8i-a33-inet-d978-rev2.dts b/arch/arm/boot/dts/allwinner/sun8i-a33-inet-d978-rev2.dts similarity index 100% rename from arch/arm/boot/dts/sun8i-a33-inet-d978-rev2.dts rename to arch/arm/boot/dts/allwinner/sun8i-a33-inet-d978-rev2.dts diff --git a/arch/arm/boot/dts/sun8i-a33-ippo-q8h-v1.2.dts b/arch/arm/boot/dts/allwinner/sun8i-a33-ippo-q8h-v1.2.dts similarity index 100% rename from arch/arm/boot/dts/sun8i-a33-ippo-q8h-v1.2.dts rename to arch/arm/boot/dts/allwinner/sun8i-a33-ippo-q8h-v1.2.dts diff --git a/arch/arm/boot/dts/sun8i-a33-olinuxino.dts b/arch/arm/boot/dts/allwinner/sun8i-a33-olinuxino.dts similarity index 100% rename from arch/arm/boot/dts/sun8i-a33-olinuxino.dts rename to arch/arm/boot/dts/allwinner/sun8i-a33-olinuxino.dts diff --git a/arch/arm/boot/dts/sun8i-a33-q8-tablet.dts b/arch/arm/boot/dts/allwinner/sun8i-a33-q8-tablet.dts similarity index 100% rename from arch/arm/boot/dts/sun8i-a33-q8-tablet.dts rename to arch/arm/boot/dts/allwinner/sun8i-a33-q8-tablet.dts diff --git a/arch/arm/boot/dts/sun8i-a33-sinlinx-sina33.dts b/arch/arm/boot/dts/allwinner/sun8i-a33-sinlinx-sina33.dts similarity index 100% rename from arch/arm/boot/dts/sun8i-a33-sinlinx-sina33.dts rename to arch/arm/boot/dts/allwinner/sun8i-a33-sinlinx-sina33.dts diff --git a/arch/arm/boot/dts/sun8i-a33.dtsi b/arch/arm/boot/dts/allwinner/sun8i-a33.dtsi similarity index 100% rename from arch/arm/boot/dts/sun8i-a33.dtsi rename to arch/arm/boot/dts/allwinner/sun8i-a33.dtsi diff --git a/arch/arm/boot/dts/sun8i-a83t-allwinner-h8homlet-v2.dts b/arch/arm/boot/dts/allwinner/sun8i-a83t-allwinner-h8homlet-v2.dts similarity index 100% rename from arch/arm/boot/dts/sun8i-a83t-allwinner-h8homlet-v2.dts rename to arch/arm/boot/dts/allwinner/sun8i-a83t-allwinner-h8homlet-v2.dts diff --git a/arch/arm/boot/dts/sun8i-a83t-bananapi-m3.dts b/arch/arm/boot/dts/allwinner/sun8i-a83t-bananapi-m3.dts similarity index 100% rename from arch/arm/boot/dts/sun8i-a83t-bananapi-m3.dts rename to arch/arm/boot/dts/allwinner/sun8i-a83t-bananapi-m3.dts diff --git a/arch/arm/boot/dts/sun8i-a83t-cubietruck-plus.dts b/arch/arm/boot/dts/allwinner/sun8i-a83t-cubietruck-plus.dts similarity index 100% rename from arch/arm/boot/dts/sun8i-a83t-cubietruck-plus.dts rename to arch/arm/boot/dts/allwinner/sun8i-a83t-cubietruck-plus.dts diff --git a/arch/arm/boot/dts/sun8i-a83t-tbs-a711.dts b/arch/arm/boot/dts/allwinner/sun8i-a83t-tbs-a711.dts similarity index 100% rename from arch/arm/boot/dts/sun8i-a83t-tbs-a711.dts rename to arch/arm/boot/dts/allwinner/sun8i-a83t-tbs-a711.dts diff --git a/arch/arm/boot/dts/sun8i-a83t.dtsi b/arch/arm/boot/dts/allwinner/sun8i-a83t.dtsi similarity index 99% rename from arch/arm/boot/dts/sun8i-a83t.dtsi rename to arch/arm/boot/dts/allwinner/sun8i-a83t.dtsi index 82fdb04122caa9077e79e961677262deb4cae519..94eb3bfc989e2913fb8ce79b6fe1358bcbced75c 100644 --- a/arch/arm/boot/dts/sun8i-a83t.dtsi +++ b/arch/arm/boot/dts/allwinner/sun8i-a83t.dtsi @@ -456,7 +456,7 @@ interrupts = ; clocks = <&ccu CLK_BUS_TCON0>, <&ccu CLK_TCON0>; clock-names = "ahb", "tcon-ch0"; - clock-output-names = "tcon-pixel-clock"; + clock-output-names = "tcon-data-clock"; #clock-cells = <0>; resets = <&ccu RST_BUS_TCON0>, <&ccu RST_BUS_LVDS>; reset-names = "lcd", "lvds"; diff --git a/arch/arm/boot/dts/sun8i-h2-plus-bananapi-m2-zero.dts b/arch/arm/boot/dts/allwinner/sun8i-h2-plus-bananapi-m2-zero.dts similarity index 100% rename from arch/arm/boot/dts/sun8i-h2-plus-bananapi-m2-zero.dts rename to arch/arm/boot/dts/allwinner/sun8i-h2-plus-bananapi-m2-zero.dts diff --git a/arch/arm/boot/dts/sun8i-h2-plus-libretech-all-h3-cc.dts b/arch/arm/boot/dts/allwinner/sun8i-h2-plus-libretech-all-h3-cc.dts similarity index 100% rename from arch/arm/boot/dts/sun8i-h2-plus-libretech-all-h3-cc.dts rename to arch/arm/boot/dts/allwinner/sun8i-h2-plus-libretech-all-h3-cc.dts diff --git a/arch/arm/boot/dts/sun8i-h2-plus-orangepi-r1.dts b/arch/arm/boot/dts/allwinner/sun8i-h2-plus-orangepi-r1.dts similarity index 100% rename from arch/arm/boot/dts/sun8i-h2-plus-orangepi-r1.dts rename to arch/arm/boot/dts/allwinner/sun8i-h2-plus-orangepi-r1.dts diff --git a/arch/arm/boot/dts/sun8i-h2-plus-orangepi-zero.dts b/arch/arm/boot/dts/allwinner/sun8i-h2-plus-orangepi-zero.dts similarity index 100% rename from arch/arm/boot/dts/sun8i-h2-plus-orangepi-zero.dts rename to arch/arm/boot/dts/allwinner/sun8i-h2-plus-orangepi-zero.dts diff --git a/arch/arm/boot/dts/sun8i-h3-bananapi-m2-plus-v1.2.dts b/arch/arm/boot/dts/allwinner/sun8i-h3-bananapi-m2-plus-v1.2.dts similarity index 100% rename from arch/arm/boot/dts/sun8i-h3-bananapi-m2-plus-v1.2.dts rename to arch/arm/boot/dts/allwinner/sun8i-h3-bananapi-m2-plus-v1.2.dts diff --git a/arch/arm/boot/dts/sun8i-h3-bananapi-m2-plus.dts b/arch/arm/boot/dts/allwinner/sun8i-h3-bananapi-m2-plus.dts similarity index 100% rename from arch/arm/boot/dts/sun8i-h3-bananapi-m2-plus.dts rename to arch/arm/boot/dts/allwinner/sun8i-h3-bananapi-m2-plus.dts diff --git a/arch/arm/boot/dts/sun8i-h3-beelink-x2.dts b/arch/arm/boot/dts/allwinner/sun8i-h3-beelink-x2.dts similarity index 100% rename from arch/arm/boot/dts/sun8i-h3-beelink-x2.dts rename to arch/arm/boot/dts/allwinner/sun8i-h3-beelink-x2.dts diff --git a/arch/arm/boot/dts/sun8i-h3-emlid-neutis-n5h3-devboard.dts b/arch/arm/boot/dts/allwinner/sun8i-h3-emlid-neutis-n5h3-devboard.dts similarity index 100% rename from arch/arm/boot/dts/sun8i-h3-emlid-neutis-n5h3-devboard.dts rename to arch/arm/boot/dts/allwinner/sun8i-h3-emlid-neutis-n5h3-devboard.dts diff --git a/arch/arm/boot/dts/sun8i-h3-emlid-neutis-n5h3.dtsi b/arch/arm/boot/dts/allwinner/sun8i-h3-emlid-neutis-n5h3.dtsi similarity index 82% rename from arch/arm/boot/dts/sun8i-h3-emlid-neutis-n5h3.dtsi rename to arch/arm/boot/dts/allwinner/sun8i-h3-emlid-neutis-n5h3.dtsi index eedd5da5dc2f27f46e77fc7567ccbd3003441b08..35e71f46c197e58458b087baa3ae30bff0ce7f17 100644 --- a/arch/arm/boot/dts/sun8i-h3-emlid-neutis-n5h3.dtsi +++ b/arch/arm/boot/dts/allwinner/sun8i-h3-emlid-neutis-n5h3.dtsi @@ -8,4 +8,4 @@ /dts-v1/; #include "sun8i-h3.dtsi" -#include +#include "sunxi-h3-h5-emlid-neutis.dtsi" diff --git a/arch/arm/boot/dts/sun8i-h3-libretech-all-h3-cc.dts b/arch/arm/boot/dts/allwinner/sun8i-h3-libretech-all-h3-cc.dts similarity index 100% rename from arch/arm/boot/dts/sun8i-h3-libretech-all-h3-cc.dts rename to arch/arm/boot/dts/allwinner/sun8i-h3-libretech-all-h3-cc.dts diff --git a/arch/arm/boot/dts/sun8i-h3-mapleboard-mp130.dts b/arch/arm/boot/dts/allwinner/sun8i-h3-mapleboard-mp130.dts similarity index 100% rename from arch/arm/boot/dts/sun8i-h3-mapleboard-mp130.dts rename to arch/arm/boot/dts/allwinner/sun8i-h3-mapleboard-mp130.dts diff --git a/arch/arm/boot/dts/sun8i-h3-nanopi-duo2.dts b/arch/arm/boot/dts/allwinner/sun8i-h3-nanopi-duo2.dts similarity index 100% rename from arch/arm/boot/dts/sun8i-h3-nanopi-duo2.dts rename to arch/arm/boot/dts/allwinner/sun8i-h3-nanopi-duo2.dts diff --git a/arch/arm/boot/dts/sun8i-h3-nanopi-m1-plus.dts b/arch/arm/boot/dts/allwinner/sun8i-h3-nanopi-m1-plus.dts similarity index 100% rename from arch/arm/boot/dts/sun8i-h3-nanopi-m1-plus.dts rename to arch/arm/boot/dts/allwinner/sun8i-h3-nanopi-m1-plus.dts diff --git a/arch/arm/boot/dts/sun8i-h3-nanopi-m1.dts b/arch/arm/boot/dts/allwinner/sun8i-h3-nanopi-m1.dts similarity index 100% rename from arch/arm/boot/dts/sun8i-h3-nanopi-m1.dts rename to arch/arm/boot/dts/allwinner/sun8i-h3-nanopi-m1.dts diff --git a/arch/arm/boot/dts/sun8i-h3-nanopi-neo-air.dts b/arch/arm/boot/dts/allwinner/sun8i-h3-nanopi-neo-air.dts similarity index 100% rename from arch/arm/boot/dts/sun8i-h3-nanopi-neo-air.dts rename to arch/arm/boot/dts/allwinner/sun8i-h3-nanopi-neo-air.dts diff --git a/arch/arm/boot/dts/sun8i-h3-nanopi-neo.dts b/arch/arm/boot/dts/allwinner/sun8i-h3-nanopi-neo.dts similarity index 100% rename from arch/arm/boot/dts/sun8i-h3-nanopi-neo.dts rename to arch/arm/boot/dts/allwinner/sun8i-h3-nanopi-neo.dts diff --git a/arch/arm/boot/dts/sun8i-h3-nanopi-r1.dts b/arch/arm/boot/dts/allwinner/sun8i-h3-nanopi-r1.dts similarity index 100% rename from arch/arm/boot/dts/sun8i-h3-nanopi-r1.dts rename to arch/arm/boot/dts/allwinner/sun8i-h3-nanopi-r1.dts diff --git a/arch/arm/boot/dts/sun8i-h3-nanopi.dtsi b/arch/arm/boot/dts/allwinner/sun8i-h3-nanopi.dtsi similarity index 100% rename from arch/arm/boot/dts/sun8i-h3-nanopi.dtsi rename to arch/arm/boot/dts/allwinner/sun8i-h3-nanopi.dtsi diff --git a/arch/arm/boot/dts/sun8i-h3-orangepi-2.dts b/arch/arm/boot/dts/allwinner/sun8i-h3-orangepi-2.dts similarity index 100% rename from arch/arm/boot/dts/sun8i-h3-orangepi-2.dts rename to arch/arm/boot/dts/allwinner/sun8i-h3-orangepi-2.dts diff --git a/arch/arm/boot/dts/sun8i-h3-orangepi-lite.dts b/arch/arm/boot/dts/allwinner/sun8i-h3-orangepi-lite.dts similarity index 100% rename from arch/arm/boot/dts/sun8i-h3-orangepi-lite.dts rename to arch/arm/boot/dts/allwinner/sun8i-h3-orangepi-lite.dts diff --git a/arch/arm/boot/dts/sun8i-h3-orangepi-one.dts b/arch/arm/boot/dts/allwinner/sun8i-h3-orangepi-one.dts similarity index 100% rename from arch/arm/boot/dts/sun8i-h3-orangepi-one.dts rename to arch/arm/boot/dts/allwinner/sun8i-h3-orangepi-one.dts diff --git a/arch/arm/boot/dts/sun8i-h3-orangepi-pc-plus.dts b/arch/arm/boot/dts/allwinner/sun8i-h3-orangepi-pc-plus.dts similarity index 100% rename from arch/arm/boot/dts/sun8i-h3-orangepi-pc-plus.dts rename to arch/arm/boot/dts/allwinner/sun8i-h3-orangepi-pc-plus.dts diff --git a/arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts b/arch/arm/boot/dts/allwinner/sun8i-h3-orangepi-pc.dts similarity index 100% rename from arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts rename to arch/arm/boot/dts/allwinner/sun8i-h3-orangepi-pc.dts diff --git a/arch/arm/boot/dts/sun8i-h3-orangepi-plus.dts b/arch/arm/boot/dts/allwinner/sun8i-h3-orangepi-plus.dts similarity index 100% rename from arch/arm/boot/dts/sun8i-h3-orangepi-plus.dts rename to arch/arm/boot/dts/allwinner/sun8i-h3-orangepi-plus.dts diff --git a/arch/arm/boot/dts/sun8i-h3-orangepi-plus2e.dts b/arch/arm/boot/dts/allwinner/sun8i-h3-orangepi-plus2e.dts similarity index 100% rename from arch/arm/boot/dts/sun8i-h3-orangepi-plus2e.dts rename to arch/arm/boot/dts/allwinner/sun8i-h3-orangepi-plus2e.dts diff --git a/arch/arm/boot/dts/sun8i-h3-orangepi-zero-plus2.dts b/arch/arm/boot/dts/allwinner/sun8i-h3-orangepi-zero-plus2.dts similarity index 100% rename from arch/arm/boot/dts/sun8i-h3-orangepi-zero-plus2.dts rename to arch/arm/boot/dts/allwinner/sun8i-h3-orangepi-zero-plus2.dts diff --git a/arch/arm/boot/dts/sun8i-h3-rervision-dvk.dts b/arch/arm/boot/dts/allwinner/sun8i-h3-rervision-dvk.dts similarity index 100% rename from arch/arm/boot/dts/sun8i-h3-rervision-dvk.dts rename to arch/arm/boot/dts/allwinner/sun8i-h3-rervision-dvk.dts diff --git a/arch/arm/boot/dts/sun8i-h3-zeropi.dts b/arch/arm/boot/dts/allwinner/sun8i-h3-zeropi.dts similarity index 100% rename from arch/arm/boot/dts/sun8i-h3-zeropi.dts rename to arch/arm/boot/dts/allwinner/sun8i-h3-zeropi.dts diff --git a/arch/arm/boot/dts/sun8i-h3.dtsi b/arch/arm/boot/dts/allwinner/sun8i-h3.dtsi similarity index 100% rename from arch/arm/boot/dts/sun8i-h3.dtsi rename to arch/arm/boot/dts/allwinner/sun8i-h3.dtsi diff --git a/arch/arm/boot/dts/sun8i-q8-common.dtsi b/arch/arm/boot/dts/allwinner/sun8i-q8-common.dtsi similarity index 100% rename from arch/arm/boot/dts/sun8i-q8-common.dtsi rename to arch/arm/boot/dts/allwinner/sun8i-q8-common.dtsi diff --git a/arch/arm/boot/dts/sun8i-r16-bananapi-m2m.dts b/arch/arm/boot/dts/allwinner/sun8i-r16-bananapi-m2m.dts similarity index 100% rename from arch/arm/boot/dts/sun8i-r16-bananapi-m2m.dts rename to arch/arm/boot/dts/allwinner/sun8i-r16-bananapi-m2m.dts diff --git a/arch/arm/boot/dts/sun8i-r16-nintendo-nes-classic.dts b/arch/arm/boot/dts/allwinner/sun8i-r16-nintendo-nes-classic.dts similarity index 100% rename from arch/arm/boot/dts/sun8i-r16-nintendo-nes-classic.dts rename to arch/arm/boot/dts/allwinner/sun8i-r16-nintendo-nes-classic.dts diff --git a/arch/arm/boot/dts/sun8i-r16-nintendo-super-nes-classic.dts b/arch/arm/boot/dts/allwinner/sun8i-r16-nintendo-super-nes-classic.dts similarity index 100% rename from arch/arm/boot/dts/sun8i-r16-nintendo-super-nes-classic.dts rename to arch/arm/boot/dts/allwinner/sun8i-r16-nintendo-super-nes-classic.dts diff --git a/arch/arm/boot/dts/sun8i-r16-parrot.dts b/arch/arm/boot/dts/allwinner/sun8i-r16-parrot.dts similarity index 100% rename from arch/arm/boot/dts/sun8i-r16-parrot.dts rename to arch/arm/boot/dts/allwinner/sun8i-r16-parrot.dts diff --git a/arch/arm/boot/dts/sun8i-r40-bananapi-m2-ultra.dts b/arch/arm/boot/dts/allwinner/sun8i-r40-bananapi-m2-ultra.dts similarity index 100% rename from arch/arm/boot/dts/sun8i-r40-bananapi-m2-ultra.dts rename to arch/arm/boot/dts/allwinner/sun8i-r40-bananapi-m2-ultra.dts diff --git a/arch/arm/boot/dts/sun8i-r40-cpu-opp.dtsi b/arch/arm/boot/dts/allwinner/sun8i-r40-cpu-opp.dtsi similarity index 100% rename from arch/arm/boot/dts/sun8i-r40-cpu-opp.dtsi rename to arch/arm/boot/dts/allwinner/sun8i-r40-cpu-opp.dtsi diff --git a/arch/arm/boot/dts/sun8i-r40-feta40i.dtsi b/arch/arm/boot/dts/allwinner/sun8i-r40-feta40i.dtsi similarity index 100% rename from arch/arm/boot/dts/sun8i-r40-feta40i.dtsi rename to arch/arm/boot/dts/allwinner/sun8i-r40-feta40i.dtsi diff --git a/arch/arm/boot/dts/sun8i-r40-oka40i-c.dts b/arch/arm/boot/dts/allwinner/sun8i-r40-oka40i-c.dts similarity index 100% rename from arch/arm/boot/dts/sun8i-r40-oka40i-c.dts rename to arch/arm/boot/dts/allwinner/sun8i-r40-oka40i-c.dts diff --git a/arch/arm/boot/dts/sun8i-r40.dtsi b/arch/arm/boot/dts/allwinner/sun8i-r40.dtsi similarity index 100% rename from arch/arm/boot/dts/sun8i-r40.dtsi rename to arch/arm/boot/dts/allwinner/sun8i-r40.dtsi diff --git a/arch/arm/boot/dts/sun8i-reference-design-tablet.dtsi b/arch/arm/boot/dts/allwinner/sun8i-reference-design-tablet.dtsi similarity index 100% rename from arch/arm/boot/dts/sun8i-reference-design-tablet.dtsi rename to arch/arm/boot/dts/allwinner/sun8i-reference-design-tablet.dtsi diff --git a/arch/arm/boot/dts/sun8i-s3-elimo-impetus.dtsi b/arch/arm/boot/dts/allwinner/sun8i-s3-elimo-impetus.dtsi similarity index 100% rename from arch/arm/boot/dts/sun8i-s3-elimo-impetus.dtsi rename to arch/arm/boot/dts/allwinner/sun8i-s3-elimo-impetus.dtsi diff --git a/arch/arm/boot/dts/sun8i-s3-elimo-initium.dts b/arch/arm/boot/dts/allwinner/sun8i-s3-elimo-initium.dts similarity index 100% rename from arch/arm/boot/dts/sun8i-s3-elimo-initium.dts rename to arch/arm/boot/dts/allwinner/sun8i-s3-elimo-initium.dts diff --git a/arch/arm/boot/dts/sun8i-s3-lichee-zero-plus.dts b/arch/arm/boot/dts/allwinner/sun8i-s3-lichee-zero-plus.dts similarity index 100% rename from arch/arm/boot/dts/sun8i-s3-lichee-zero-plus.dts rename to arch/arm/boot/dts/allwinner/sun8i-s3-lichee-zero-plus.dts diff --git a/arch/arm/boot/dts/sun8i-s3-pinecube.dts b/arch/arm/boot/dts/allwinner/sun8i-s3-pinecube.dts similarity index 100% rename from arch/arm/boot/dts/sun8i-s3-pinecube.dts rename to arch/arm/boot/dts/allwinner/sun8i-s3-pinecube.dts diff --git a/arch/arm/boot/dts/sun8i-t113s-mangopi-mq-r-t113.dts b/arch/arm/boot/dts/allwinner/sun8i-t113s-mangopi-mq-r-t113.dts similarity index 100% rename from arch/arm/boot/dts/sun8i-t113s-mangopi-mq-r-t113.dts rename to arch/arm/boot/dts/allwinner/sun8i-t113s-mangopi-mq-r-t113.dts diff --git a/arch/arm/boot/dts/sun8i-t113s.dtsi b/arch/arm/boot/dts/allwinner/sun8i-t113s.dtsi similarity index 100% rename from arch/arm/boot/dts/sun8i-t113s.dtsi rename to arch/arm/boot/dts/allwinner/sun8i-t113s.dtsi diff --git a/arch/arm/boot/dts/sun8i-t3-cqa3t-bv3.dts b/arch/arm/boot/dts/allwinner/sun8i-t3-cqa3t-bv3.dts similarity index 100% rename from arch/arm/boot/dts/sun8i-t3-cqa3t-bv3.dts rename to arch/arm/boot/dts/allwinner/sun8i-t3-cqa3t-bv3.dts diff --git a/arch/arm/boot/dts/sun8i-v3-sl631-imx179.dts b/arch/arm/boot/dts/allwinner/sun8i-v3-sl631-imx179.dts similarity index 100% rename from arch/arm/boot/dts/sun8i-v3-sl631-imx179.dts rename to arch/arm/boot/dts/allwinner/sun8i-v3-sl631-imx179.dts diff --git a/arch/arm/boot/dts/sun8i-v3-sl631.dtsi b/arch/arm/boot/dts/allwinner/sun8i-v3-sl631.dtsi similarity index 100% rename from arch/arm/boot/dts/sun8i-v3-sl631.dtsi rename to arch/arm/boot/dts/allwinner/sun8i-v3-sl631.dtsi diff --git a/arch/arm/boot/dts/sun8i-v3.dtsi b/arch/arm/boot/dts/allwinner/sun8i-v3.dtsi similarity index 100% rename from arch/arm/boot/dts/sun8i-v3.dtsi rename to arch/arm/boot/dts/allwinner/sun8i-v3.dtsi diff --git a/arch/arm/boot/dts/sun8i-v3s-licheepi-zero-dock.dts b/arch/arm/boot/dts/allwinner/sun8i-v3s-licheepi-zero-dock.dts similarity index 100% rename from arch/arm/boot/dts/sun8i-v3s-licheepi-zero-dock.dts rename to arch/arm/boot/dts/allwinner/sun8i-v3s-licheepi-zero-dock.dts diff --git a/arch/arm/boot/dts/sun8i-v3s-licheepi-zero.dts b/arch/arm/boot/dts/allwinner/sun8i-v3s-licheepi-zero.dts similarity index 100% rename from arch/arm/boot/dts/sun8i-v3s-licheepi-zero.dts rename to arch/arm/boot/dts/allwinner/sun8i-v3s-licheepi-zero.dts diff --git a/arch/arm/boot/dts/sun8i-v3s.dtsi b/arch/arm/boot/dts/allwinner/sun8i-v3s.dtsi similarity index 99% rename from arch/arm/boot/dts/sun8i-v3s.dtsi rename to arch/arm/boot/dts/allwinner/sun8i-v3s.dtsi index b001251644f75ec5018371dac57a10df1c9c7474..3b9a282c274635361ce2d3563e3c72a6c2be0279 100644 --- a/arch/arm/boot/dts/sun8i-v3s.dtsi +++ b/arch/arm/boot/dts/allwinner/sun8i-v3s.dtsi @@ -191,7 +191,7 @@ <&ccu CLK_TCON0>; clock-names = "ahb", "tcon-ch0"; - clock-output-names = "tcon-pixel-clock"; + clock-output-names = "tcon-data-clock"; #clock-cells = <0>; resets = <&ccu RST_BUS_TCON0>; reset-names = "lcd"; diff --git a/arch/arm/boot/dts/sun8i-v40-bananapi-m2-berry.dts b/arch/arm/boot/dts/allwinner/sun8i-v40-bananapi-m2-berry.dts similarity index 100% rename from arch/arm/boot/dts/sun8i-v40-bananapi-m2-berry.dts rename to arch/arm/boot/dts/allwinner/sun8i-v40-bananapi-m2-berry.dts diff --git a/arch/arm/boot/dts/sun9i-a80-cubieboard4.dts b/arch/arm/boot/dts/allwinner/sun9i-a80-cubieboard4.dts similarity index 100% rename from arch/arm/boot/dts/sun9i-a80-cubieboard4.dts rename to arch/arm/boot/dts/allwinner/sun9i-a80-cubieboard4.dts diff --git a/arch/arm/boot/dts/sun9i-a80-optimus.dts b/arch/arm/boot/dts/allwinner/sun9i-a80-optimus.dts similarity index 100% rename from arch/arm/boot/dts/sun9i-a80-optimus.dts rename to arch/arm/boot/dts/allwinner/sun9i-a80-optimus.dts diff --git a/arch/arm/boot/dts/sun9i-a80.dtsi b/arch/arm/boot/dts/allwinner/sun9i-a80.dtsi similarity index 100% rename from arch/arm/boot/dts/sun9i-a80.dtsi rename to arch/arm/boot/dts/allwinner/sun9i-a80.dtsi diff --git a/arch/arm/boot/dts/suniv-f1c100s-licheepi-nano.dts b/arch/arm/boot/dts/allwinner/suniv-f1c100s-licheepi-nano.dts similarity index 100% rename from arch/arm/boot/dts/suniv-f1c100s-licheepi-nano.dts rename to arch/arm/boot/dts/allwinner/suniv-f1c100s-licheepi-nano.dts diff --git a/arch/arm/boot/dts/suniv-f1c100s.dtsi b/arch/arm/boot/dts/allwinner/suniv-f1c100s.dtsi similarity index 100% rename from arch/arm/boot/dts/suniv-f1c100s.dtsi rename to arch/arm/boot/dts/allwinner/suniv-f1c100s.dtsi diff --git a/arch/arm/boot/dts/suniv-f1c200s-lctech-pi.dts b/arch/arm/boot/dts/allwinner/suniv-f1c200s-lctech-pi.dts similarity index 100% rename from arch/arm/boot/dts/suniv-f1c200s-lctech-pi.dts rename to arch/arm/boot/dts/allwinner/suniv-f1c200s-lctech-pi.dts diff --git a/arch/arm/boot/dts/suniv-f1c200s-popstick-v1.1.dts b/arch/arm/boot/dts/allwinner/suniv-f1c200s-popstick-v1.1.dts similarity index 100% rename from arch/arm/boot/dts/suniv-f1c200s-popstick-v1.1.dts rename to arch/arm/boot/dts/allwinner/suniv-f1c200s-popstick-v1.1.dts diff --git a/arch/arm/boot/dts/sunxi-bananapi-m2-plus-v1.2.dtsi b/arch/arm/boot/dts/allwinner/sunxi-bananapi-m2-plus-v1.2.dtsi similarity index 100% rename from arch/arm/boot/dts/sunxi-bananapi-m2-plus-v1.2.dtsi rename to arch/arm/boot/dts/allwinner/sunxi-bananapi-m2-plus-v1.2.dtsi diff --git a/arch/arm/boot/dts/sunxi-bananapi-m2-plus.dtsi b/arch/arm/boot/dts/allwinner/sunxi-bananapi-m2-plus.dtsi similarity index 100% rename from arch/arm/boot/dts/sunxi-bananapi-m2-plus.dtsi rename to arch/arm/boot/dts/allwinner/sunxi-bananapi-m2-plus.dtsi diff --git a/arch/arm/boot/dts/sunxi-common-regulators.dtsi b/arch/arm/boot/dts/allwinner/sunxi-common-regulators.dtsi similarity index 100% rename from arch/arm/boot/dts/sunxi-common-regulators.dtsi rename to arch/arm/boot/dts/allwinner/sunxi-common-regulators.dtsi diff --git a/arch/arm/boot/dts/sunxi-d1s-t113-mangopi-mq-r.dtsi b/arch/arm/boot/dts/allwinner/sunxi-d1s-t113-mangopi-mq-r.dtsi similarity index 100% rename from arch/arm/boot/dts/sunxi-d1s-t113-mangopi-mq-r.dtsi rename to arch/arm/boot/dts/allwinner/sunxi-d1s-t113-mangopi-mq-r.dtsi diff --git a/arch/arm/boot/dts/sunxi-h3-h5-emlid-neutis.dtsi b/arch/arm/boot/dts/allwinner/sunxi-h3-h5-emlid-neutis.dtsi similarity index 100% rename from arch/arm/boot/dts/sunxi-h3-h5-emlid-neutis.dtsi rename to arch/arm/boot/dts/allwinner/sunxi-h3-h5-emlid-neutis.dtsi diff --git a/arch/arm/boot/dts/sunxi-h3-h5.dtsi b/arch/arm/boot/dts/allwinner/sunxi-h3-h5.dtsi similarity index 100% rename from arch/arm/boot/dts/sunxi-h3-h5.dtsi rename to arch/arm/boot/dts/allwinner/sunxi-h3-h5.dtsi diff --git a/arch/arm/boot/dts/sunxi-itead-core-common.dtsi b/arch/arm/boot/dts/allwinner/sunxi-itead-core-common.dtsi similarity index 100% rename from arch/arm/boot/dts/sunxi-itead-core-common.dtsi rename to arch/arm/boot/dts/allwinner/sunxi-itead-core-common.dtsi diff --git a/arch/arm/boot/dts/sunxi-libretech-all-h3-cc.dtsi b/arch/arm/boot/dts/allwinner/sunxi-libretech-all-h3-cc.dtsi similarity index 100% rename from arch/arm/boot/dts/sunxi-libretech-all-h3-cc.dtsi rename to arch/arm/boot/dts/allwinner/sunxi-libretech-all-h3-cc.dtsi diff --git a/arch/arm/boot/dts/sunxi-libretech-all-h3-it.dtsi b/arch/arm/boot/dts/allwinner/sunxi-libretech-all-h3-it.dtsi similarity index 100% rename from arch/arm/boot/dts/sunxi-libretech-all-h3-it.dtsi rename to arch/arm/boot/dts/allwinner/sunxi-libretech-all-h3-it.dtsi diff --git a/arch/arm/boot/dts/sunxi-reference-design-tablet.dtsi b/arch/arm/boot/dts/allwinner/sunxi-reference-design-tablet.dtsi similarity index 100% rename from arch/arm/boot/dts/sunxi-reference-design-tablet.dtsi rename to arch/arm/boot/dts/allwinner/sunxi-reference-design-tablet.dtsi diff --git a/arch/arm/boot/dts/alphascale/Makefile b/arch/arm/boot/dts/alphascale/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..8d1314fc79d01b5fba69f323f99e4fd88e691d79 --- /dev/null +++ b/arch/arm/boot/dts/alphascale/Makefile @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0 +dtb-$(CONFIG_MACH_ASM9260) += \ + alphascale-asm9260-devkit.dtb +dtb-$(CONFIG_MACH_ASM9260) += \ + alphascale-asm9260-devkit.dtb diff --git a/arch/arm/boot/dts/alphascale-asm9260-devkit.dts b/arch/arm/boot/dts/alphascale/alphascale-asm9260-devkit.dts similarity index 100% rename from arch/arm/boot/dts/alphascale-asm9260-devkit.dts rename to arch/arm/boot/dts/alphascale/alphascale-asm9260-devkit.dts diff --git a/arch/arm/boot/dts/alphascale-asm9260.dtsi b/arch/arm/boot/dts/alphascale/alphascale-asm9260.dtsi similarity index 100% rename from arch/arm/boot/dts/alphascale-asm9260.dtsi rename to arch/arm/boot/dts/alphascale/alphascale-asm9260.dtsi diff --git a/arch/arm/boot/dts/amazon/Makefile b/arch/arm/boot/dts/amazon/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..58af5c4846efc071525af5c93d02080b3be69b36 --- /dev/null +++ b/arch/arm/boot/dts/amazon/Makefile @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0 +dtb-$(CONFIG_ARCH_ALPINE) += \ + alpine-db.dtb +dtb-$(CONFIG_ARCH_ALPINE) += \ + alpine-db.dtb diff --git a/arch/arm/boot/dts/alpine-db.dts b/arch/arm/boot/dts/amazon/alpine-db.dts similarity index 100% rename from arch/arm/boot/dts/alpine-db.dts rename to arch/arm/boot/dts/amazon/alpine-db.dts diff --git a/arch/arm/boot/dts/alpine.dtsi b/arch/arm/boot/dts/amazon/alpine.dtsi similarity index 100% rename from arch/arm/boot/dts/alpine.dtsi rename to arch/arm/boot/dts/amazon/alpine.dtsi diff --git a/arch/arm/boot/dts/amlogic/Makefile b/arch/arm/boot/dts/amlogic/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..a84310780ea3453383b06e40c9047f26093a3b6b --- /dev/null +++ b/arch/arm/boot/dts/amlogic/Makefile @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: GPL-2.0 +dtb-$(CONFIG_MACH_MESON6) += \ + meson6-atv1200.dtb +dtb-$(CONFIG_MACH_MESON8) += \ + meson8-minix-neo-x8.dtb \ + meson8b-ec100.dtb \ + meson8b-mxq.dtb \ + meson8b-odroidc1.dtb \ + meson8m2-mxiii-plus.dtb diff --git a/arch/arm/boot/dts/meson.dtsi b/arch/arm/boot/dts/amlogic/meson.dtsi similarity index 100% rename from arch/arm/boot/dts/meson.dtsi rename to arch/arm/boot/dts/amlogic/meson.dtsi diff --git a/arch/arm/boot/dts/meson6-atv1200.dts b/arch/arm/boot/dts/amlogic/meson6-atv1200.dts similarity index 100% rename from arch/arm/boot/dts/meson6-atv1200.dts rename to arch/arm/boot/dts/amlogic/meson6-atv1200.dts diff --git a/arch/arm/boot/dts/meson6.dtsi b/arch/arm/boot/dts/amlogic/meson6.dtsi similarity index 100% rename from arch/arm/boot/dts/meson6.dtsi rename to arch/arm/boot/dts/amlogic/meson6.dtsi diff --git a/arch/arm/boot/dts/meson8-minix-neo-x8.dts b/arch/arm/boot/dts/amlogic/meson8-minix-neo-x8.dts similarity index 100% rename from arch/arm/boot/dts/meson8-minix-neo-x8.dts rename to arch/arm/boot/dts/amlogic/meson8-minix-neo-x8.dts diff --git a/arch/arm/boot/dts/meson8.dtsi b/arch/arm/boot/dts/amlogic/meson8.dtsi similarity index 99% rename from arch/arm/boot/dts/meson8.dtsi rename to arch/arm/boot/dts/amlogic/meson8.dtsi index 4f22ab451aae2c2c0702db3b41dcc150cdff6930..59932fbfd5d5f03768e20097f4344b715830f4fd 100644 --- a/arch/arm/boot/dts/meson8.dtsi +++ b/arch/arm/boot/dts/amlogic/meson8.dtsi @@ -769,13 +769,13 @@ &uart_B { compatible = "amlogic,meson8-uart"; - clocks = <&xtal>, <&clkc CLKID_UART0>, <&clkc CLKID_CLK81>; + clocks = <&xtal>, <&clkc CLKID_UART1>, <&clkc CLKID_CLK81>; clock-names = "xtal", "pclk", "baud"; }; &uart_C { compatible = "amlogic,meson8-uart"; - clocks = <&xtal>, <&clkc CLKID_UART0>, <&clkc CLKID_CLK81>; + clocks = <&xtal>, <&clkc CLKID_UART2>, <&clkc CLKID_CLK81>; clock-names = "xtal", "pclk", "baud"; }; diff --git a/arch/arm/boot/dts/meson8b-ec100.dts b/arch/arm/boot/dts/amlogic/meson8b-ec100.dts similarity index 100% rename from arch/arm/boot/dts/meson8b-ec100.dts rename to arch/arm/boot/dts/amlogic/meson8b-ec100.dts diff --git a/arch/arm/boot/dts/meson8b-mxq.dts b/arch/arm/boot/dts/amlogic/meson8b-mxq.dts similarity index 100% rename from arch/arm/boot/dts/meson8b-mxq.dts rename to arch/arm/boot/dts/amlogic/meson8b-mxq.dts diff --git a/arch/arm/boot/dts/meson8b-odroidc1.dts b/arch/arm/boot/dts/amlogic/meson8b-odroidc1.dts similarity index 100% rename from arch/arm/boot/dts/meson8b-odroidc1.dts rename to arch/arm/boot/dts/amlogic/meson8b-odroidc1.dts diff --git a/arch/arm/boot/dts/meson8b.dtsi b/arch/arm/boot/dts/amlogic/meson8b.dtsi similarity index 99% rename from arch/arm/boot/dts/meson8b.dtsi rename to arch/arm/boot/dts/amlogic/meson8b.dtsi index 5979209fe91ef3981b093b12dadb02bab33fd215..5198f5177c2c161c28292faaf4d995a7c6d5d112 100644 --- a/arch/arm/boot/dts/meson8b.dtsi +++ b/arch/arm/boot/dts/amlogic/meson8b.dtsi @@ -740,13 +740,13 @@ &uart_B { compatible = "amlogic,meson8b-uart"; - clocks = <&xtal>, <&clkc CLKID_UART0>, <&clkc CLKID_CLK81>; + clocks = <&xtal>, <&clkc CLKID_UART1>, <&clkc CLKID_CLK81>; clock-names = "xtal", "pclk", "baud"; }; &uart_C { compatible = "amlogic,meson8b-uart"; - clocks = <&xtal>, <&clkc CLKID_UART0>, <&clkc CLKID_CLK81>; + clocks = <&xtal>, <&clkc CLKID_UART2>, <&clkc CLKID_CLK81>; clock-names = "xtal", "pclk", "baud"; }; diff --git a/arch/arm/boot/dts/meson8m2-mxiii-plus.dts b/arch/arm/boot/dts/amlogic/meson8m2-mxiii-plus.dts similarity index 100% rename from arch/arm/boot/dts/meson8m2-mxiii-plus.dts rename to arch/arm/boot/dts/amlogic/meson8m2-mxiii-plus.dts diff --git a/arch/arm/boot/dts/meson8m2.dtsi b/arch/arm/boot/dts/amlogic/meson8m2.dtsi similarity index 100% rename from arch/arm/boot/dts/meson8m2.dtsi rename to arch/arm/boot/dts/amlogic/meson8m2.dtsi diff --git a/arch/arm/boot/dts/arm/Makefile b/arch/arm/boot/dts/arm/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..07ebb64e2cd010bf0ba6fe6bf31f26816be1cfa6 --- /dev/null +++ b/arch/arm/boot/dts/arm/Makefile @@ -0,0 +1,30 @@ +# SPDX-License-Identifier: GPL-2.0 +dtb-$(CONFIG_ARCH_INTEGRATOR) += \ + integratorap.dtb \ + integratorap-im-pd1.dtb \ + integratorcp.dtb +dtb-$(CONFIG_ARCH_MPS2) += \ + mps2-an385.dtb \ + mps2-an399.dtb +dtb-$(CONFIG_ARCH_REALVIEW) += \ + arm-realview-pb1176.dtb \ + arm-realview-pb11mp.dtb \ + arm-realview-eb.dtb \ + arm-realview-eb-bbrevd.dtb \ + arm-realview-eb-11mp.dtb \ + arm-realview-eb-11mp-bbrevd.dtb \ + arm-realview-eb-11mp-ctrevb.dtb \ + arm-realview-eb-11mp-bbrevd-ctrevb.dtb \ + arm-realview-eb-a9mp.dtb \ + arm-realview-eb-a9mp-bbrevd.dtb \ + arm-realview-pba8.dtb \ + arm-realview-pbx-a9.dtb +dtb-$(CONFIG_ARCH_VERSATILE) += \ + versatile-ab.dtb \ + versatile-ab-ib2.dtb \ + versatile-pb.dtb +dtb-$(CONFIG_ARCH_VEXPRESS) += \ + vexpress-v2p-ca5s.dtb \ + vexpress-v2p-ca9.dtb \ + vexpress-v2p-ca15-tc1.dtb \ + vexpress-v2p-ca15_a7.dtb diff --git a/arch/arm/boot/dts/arm-realview-eb-11mp-bbrevd-ctrevb.dts b/arch/arm/boot/dts/arm/arm-realview-eb-11mp-bbrevd-ctrevb.dts similarity index 100% rename from arch/arm/boot/dts/arm-realview-eb-11mp-bbrevd-ctrevb.dts rename to arch/arm/boot/dts/arm/arm-realview-eb-11mp-bbrevd-ctrevb.dts diff --git a/arch/arm/boot/dts/arm-realview-eb-11mp-bbrevd.dts b/arch/arm/boot/dts/arm/arm-realview-eb-11mp-bbrevd.dts similarity index 100% rename from arch/arm/boot/dts/arm-realview-eb-11mp-bbrevd.dts rename to arch/arm/boot/dts/arm/arm-realview-eb-11mp-bbrevd.dts diff --git a/arch/arm/boot/dts/arm-realview-eb-11mp-ctrevb.dts b/arch/arm/boot/dts/arm/arm-realview-eb-11mp-ctrevb.dts similarity index 100% rename from arch/arm/boot/dts/arm-realview-eb-11mp-ctrevb.dts rename to arch/arm/boot/dts/arm/arm-realview-eb-11mp-ctrevb.dts diff --git a/arch/arm/boot/dts/arm-realview-eb-11mp.dts b/arch/arm/boot/dts/arm/arm-realview-eb-11mp.dts similarity index 100% rename from arch/arm/boot/dts/arm-realview-eb-11mp.dts rename to arch/arm/boot/dts/arm/arm-realview-eb-11mp.dts diff --git a/arch/arm/boot/dts/arm-realview-eb-a9mp-bbrevd.dts b/arch/arm/boot/dts/arm/arm-realview-eb-a9mp-bbrevd.dts similarity index 100% rename from arch/arm/boot/dts/arm-realview-eb-a9mp-bbrevd.dts rename to arch/arm/boot/dts/arm/arm-realview-eb-a9mp-bbrevd.dts diff --git a/arch/arm/boot/dts/arm-realview-eb-a9mp.dts b/arch/arm/boot/dts/arm/arm-realview-eb-a9mp.dts similarity index 100% rename from arch/arm/boot/dts/arm-realview-eb-a9mp.dts rename to arch/arm/boot/dts/arm/arm-realview-eb-a9mp.dts diff --git a/arch/arm/boot/dts/arm-realview-eb-bbrevd.dts b/arch/arm/boot/dts/arm/arm-realview-eb-bbrevd.dts similarity index 100% rename from arch/arm/boot/dts/arm-realview-eb-bbrevd.dts rename to arch/arm/boot/dts/arm/arm-realview-eb-bbrevd.dts diff --git a/arch/arm/boot/dts/arm-realview-eb-bbrevd.dtsi b/arch/arm/boot/dts/arm/arm-realview-eb-bbrevd.dtsi similarity index 100% rename from arch/arm/boot/dts/arm-realview-eb-bbrevd.dtsi rename to arch/arm/boot/dts/arm/arm-realview-eb-bbrevd.dtsi diff --git a/arch/arm/boot/dts/arm-realview-eb-mp.dtsi b/arch/arm/boot/dts/arm/arm-realview-eb-mp.dtsi similarity index 100% rename from arch/arm/boot/dts/arm-realview-eb-mp.dtsi rename to arch/arm/boot/dts/arm/arm-realview-eb-mp.dtsi diff --git a/arch/arm/boot/dts/arm-realview-eb.dts b/arch/arm/boot/dts/arm/arm-realview-eb.dts similarity index 100% rename from arch/arm/boot/dts/arm-realview-eb.dts rename to arch/arm/boot/dts/arm/arm-realview-eb.dts diff --git a/arch/arm/boot/dts/arm-realview-eb.dtsi b/arch/arm/boot/dts/arm/arm-realview-eb.dtsi similarity index 100% rename from arch/arm/boot/dts/arm-realview-eb.dtsi rename to arch/arm/boot/dts/arm/arm-realview-eb.dtsi diff --git a/arch/arm/boot/dts/arm-realview-pb1176.dts b/arch/arm/boot/dts/arm/arm-realview-pb1176.dts similarity index 100% rename from arch/arm/boot/dts/arm-realview-pb1176.dts rename to arch/arm/boot/dts/arm/arm-realview-pb1176.dts diff --git a/arch/arm/boot/dts/arm-realview-pb11mp.dts b/arch/arm/boot/dts/arm/arm-realview-pb11mp.dts similarity index 100% rename from arch/arm/boot/dts/arm-realview-pb11mp.dts rename to arch/arm/boot/dts/arm/arm-realview-pb11mp.dts diff --git a/arch/arm/boot/dts/arm-realview-pba8.dts b/arch/arm/boot/dts/arm/arm-realview-pba8.dts similarity index 100% rename from arch/arm/boot/dts/arm-realview-pba8.dts rename to arch/arm/boot/dts/arm/arm-realview-pba8.dts diff --git a/arch/arm/boot/dts/arm-realview-pbx-a9.dts b/arch/arm/boot/dts/arm/arm-realview-pbx-a9.dts similarity index 100% rename from arch/arm/boot/dts/arm-realview-pbx-a9.dts rename to arch/arm/boot/dts/arm/arm-realview-pbx-a9.dts diff --git a/arch/arm/boot/dts/arm-realview-pbx.dtsi b/arch/arm/boot/dts/arm/arm-realview-pbx.dtsi similarity index 100% rename from arch/arm/boot/dts/arm-realview-pbx.dtsi rename to arch/arm/boot/dts/arm/arm-realview-pbx.dtsi diff --git a/arch/arm/boot/dts/integrator.dtsi b/arch/arm/boot/dts/arm/integrator.dtsi similarity index 100% rename from arch/arm/boot/dts/integrator.dtsi rename to arch/arm/boot/dts/arm/integrator.dtsi diff --git a/arch/arm/boot/dts/integratorap-im-pd1.dts b/arch/arm/boot/dts/arm/integratorap-im-pd1.dts similarity index 100% rename from arch/arm/boot/dts/integratorap-im-pd1.dts rename to arch/arm/boot/dts/arm/integratorap-im-pd1.dts diff --git a/arch/arm/boot/dts/integratorap.dts b/arch/arm/boot/dts/arm/integratorap.dts similarity index 100% rename from arch/arm/boot/dts/integratorap.dts rename to arch/arm/boot/dts/arm/integratorap.dts diff --git a/arch/arm/boot/dts/integratorcp.dts b/arch/arm/boot/dts/arm/integratorcp.dts similarity index 100% rename from arch/arm/boot/dts/integratorcp.dts rename to arch/arm/boot/dts/arm/integratorcp.dts diff --git a/arch/arm/boot/dts/mps2-an385.dts b/arch/arm/boot/dts/arm/mps2-an385.dts similarity index 100% rename from arch/arm/boot/dts/mps2-an385.dts rename to arch/arm/boot/dts/arm/mps2-an385.dts diff --git a/arch/arm/boot/dts/mps2-an399.dts b/arch/arm/boot/dts/arm/mps2-an399.dts similarity index 100% rename from arch/arm/boot/dts/mps2-an399.dts rename to arch/arm/boot/dts/arm/mps2-an399.dts diff --git a/arch/arm/boot/dts/mps2.dtsi b/arch/arm/boot/dts/arm/mps2.dtsi similarity index 99% rename from arch/arm/boot/dts/mps2.dtsi rename to arch/arm/boot/dts/arm/mps2.dtsi index b99577d411b196fbb81e87a33a82c976450317ba..ce308820765b8e7105f5a4e321eec5df3107411a 100644 --- a/arch/arm/boot/dts/mps2.dtsi +++ b/arch/arm/boot/dts/arm/mps2.dtsi @@ -42,7 +42,7 @@ * OTHER DEALINGS IN THE SOFTWARE. */ -#include "armv7-m.dtsi" +#include "../armv7-m.dtsi" / { #address-cells = <1>; diff --git a/arch/arm/boot/dts/versatile-ab-ib2.dts b/arch/arm/boot/dts/arm/versatile-ab-ib2.dts similarity index 100% rename from arch/arm/boot/dts/versatile-ab-ib2.dts rename to arch/arm/boot/dts/arm/versatile-ab-ib2.dts diff --git a/arch/arm/boot/dts/versatile-ab.dts b/arch/arm/boot/dts/arm/versatile-ab.dts similarity index 100% rename from arch/arm/boot/dts/versatile-ab.dts rename to arch/arm/boot/dts/arm/versatile-ab.dts diff --git a/arch/arm/boot/dts/versatile-pb.dts b/arch/arm/boot/dts/arm/versatile-pb.dts similarity index 100% rename from arch/arm/boot/dts/versatile-pb.dts rename to arch/arm/boot/dts/arm/versatile-pb.dts diff --git a/arch/arm/boot/dts/vexpress-v2m-rs1.dtsi b/arch/arm/boot/dts/arm/vexpress-v2m-rs1.dtsi similarity index 100% rename from arch/arm/boot/dts/vexpress-v2m-rs1.dtsi rename to arch/arm/boot/dts/arm/vexpress-v2m-rs1.dtsi diff --git a/arch/arm/boot/dts/vexpress-v2m.dtsi b/arch/arm/boot/dts/arm/vexpress-v2m.dtsi similarity index 100% rename from arch/arm/boot/dts/vexpress-v2m.dtsi rename to arch/arm/boot/dts/arm/vexpress-v2m.dtsi diff --git a/arch/arm/boot/dts/vexpress-v2p-ca15-tc1.dts b/arch/arm/boot/dts/arm/vexpress-v2p-ca15-tc1.dts similarity index 100% rename from arch/arm/boot/dts/vexpress-v2p-ca15-tc1.dts rename to arch/arm/boot/dts/arm/vexpress-v2p-ca15-tc1.dts diff --git a/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts b/arch/arm/boot/dts/arm/vexpress-v2p-ca15_a7.dts similarity index 100% rename from arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts rename to arch/arm/boot/dts/arm/vexpress-v2p-ca15_a7.dts diff --git a/arch/arm/boot/dts/vexpress-v2p-ca5s.dts b/arch/arm/boot/dts/arm/vexpress-v2p-ca5s.dts similarity index 100% rename from arch/arm/boot/dts/vexpress-v2p-ca5s.dts rename to arch/arm/boot/dts/arm/vexpress-v2p-ca5s.dts diff --git a/arch/arm/boot/dts/vexpress-v2p-ca9.dts b/arch/arm/boot/dts/arm/vexpress-v2p-ca9.dts similarity index 100% rename from arch/arm/boot/dts/vexpress-v2p-ca9.dts rename to arch/arm/boot/dts/arm/vexpress-v2p-ca9.dts diff --git a/arch/arm/boot/dts/aspeed/Makefile b/arch/arm/boot/dts/aspeed/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..c68984322a86c77b7dacbdd3f46d9bd5822320b5 --- /dev/null +++ b/arch/arm/boot/dts/aspeed/Makefile @@ -0,0 +1,62 @@ +# SPDX-License-Identifier: GPL-2.0 +dtb-$(CONFIG_ARCH_ASPEED) += \ + aspeed-ast2500-evb.dtb \ + aspeed-ast2600-evb-a1.dtb \ + aspeed-ast2600-evb.dtb \ + aspeed-bmc-amd-daytonax.dtb \ + aspeed-bmc-amd-ethanolx.dtb \ + aspeed-bmc-ampere-mtjade.dtb \ + aspeed-bmc-ampere-mtmitchell.dtb \ + aspeed-bmc-arm-stardragon4800-rep2.dtb \ + aspeed-bmc-asrock-e3c246d4i.dtb \ + aspeed-bmc-asrock-romed8hm3.dtb \ + aspeed-bmc-bytedance-g220a.dtb \ + aspeed-bmc-delta-ahe50dc.dtb \ + aspeed-bmc-facebook-bletchley.dtb \ + aspeed-bmc-facebook-cloudripper.dtb \ + aspeed-bmc-facebook-cmm.dtb \ + aspeed-bmc-facebook-elbert.dtb \ + aspeed-bmc-facebook-fuji.dtb \ + aspeed-bmc-facebook-galaxy100.dtb \ + aspeed-bmc-facebook-greatlakes.dtb \ + aspeed-bmc-facebook-minipack.dtb \ + aspeed-bmc-facebook-tiogapass.dtb \ + aspeed-bmc-facebook-wedge40.dtb \ + aspeed-bmc-facebook-wedge100.dtb \ + aspeed-bmc-facebook-wedge400.dtb \ + aspeed-bmc-facebook-yamp.dtb \ + aspeed-bmc-facebook-yosemitev2.dtb \ + aspeed-bmc-ibm-bonnell.dtb \ + aspeed-bmc-ibm-everest.dtb \ + aspeed-bmc-ibm-rainier.dtb \ + aspeed-bmc-ibm-rainier-1s4u.dtb \ + aspeed-bmc-ibm-rainier-4u.dtb \ + aspeed-bmc-intel-s2600wf.dtb \ + aspeed-bmc-inspur-fp5280g2.dtb \ + aspeed-bmc-inspur-nf5280m6.dtb \ + aspeed-bmc-inspur-on5263m5.dtb \ + aspeed-bmc-lenovo-hr630.dtb \ + aspeed-bmc-lenovo-hr855xg2.dtb \ + aspeed-bmc-microsoft-olympus.dtb \ + aspeed-bmc-opp-lanyang.dtb \ + aspeed-bmc-opp-mowgli.dtb \ + aspeed-bmc-opp-nicole.dtb \ + aspeed-bmc-opp-palmetto.dtb \ + aspeed-bmc-opp-romulus.dtb \ + aspeed-bmc-opp-swift.dtb \ + aspeed-bmc-opp-tacoma.dtb \ + aspeed-bmc-opp-vesnin.dtb \ + aspeed-bmc-opp-witherspoon.dtb \ + aspeed-bmc-opp-zaius.dtb \ + aspeed-bmc-portwell-neptune.dtb \ + aspeed-bmc-qcom-dc-scm-v1.dtb \ + aspeed-bmc-quanta-q71l.dtb \ + aspeed-bmc-quanta-s6q.dtb \ + aspeed-bmc-supermicro-x11spi.dtb \ + aspeed-bmc-inventec-transformers.dtb \ + aspeed-bmc-tyan-s7106.dtb \ + aspeed-bmc-tyan-s8036.dtb \ + aspeed-bmc-ufispace-ncplite.dtb \ + aspeed-bmc-vegman-n110.dtb \ + aspeed-bmc-vegman-rx20.dtb \ + aspeed-bmc-vegman-sx20.dtb diff --git a/arch/arm/boot/dts/aspeed-ast2500-evb.dts b/arch/arm/boot/dts/aspeed/aspeed-ast2500-evb.dts similarity index 100% rename from arch/arm/boot/dts/aspeed-ast2500-evb.dts rename to arch/arm/boot/dts/aspeed/aspeed-ast2500-evb.dts diff --git a/arch/arm/boot/dts/aspeed-ast2600-evb-a1.dts b/arch/arm/boot/dts/aspeed/aspeed-ast2600-evb-a1.dts similarity index 100% rename from arch/arm/boot/dts/aspeed-ast2600-evb-a1.dts rename to arch/arm/boot/dts/aspeed/aspeed-ast2600-evb-a1.dts diff --git a/arch/arm/boot/dts/aspeed-ast2600-evb.dts b/arch/arm/boot/dts/aspeed/aspeed-ast2600-evb.dts similarity index 100% rename from arch/arm/boot/dts/aspeed-ast2600-evb.dts rename to arch/arm/boot/dts/aspeed/aspeed-ast2600-evb.dts diff --git a/arch/arm/boot/dts/aspeed-bmc-amd-daytonax.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-amd-daytonax.dts similarity index 100% rename from arch/arm/boot/dts/aspeed-bmc-amd-daytonax.dts rename to arch/arm/boot/dts/aspeed/aspeed-bmc-amd-daytonax.dts diff --git a/arch/arm/boot/dts/aspeed-bmc-amd-ethanolx.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-amd-ethanolx.dts similarity index 100% rename from arch/arm/boot/dts/aspeed-bmc-amd-ethanolx.dts rename to arch/arm/boot/dts/aspeed/aspeed-bmc-amd-ethanolx.dts diff --git a/arch/arm/boot/dts/aspeed-bmc-ampere-mtjade.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-ampere-mtjade.dts similarity index 100% rename from arch/arm/boot/dts/aspeed-bmc-ampere-mtjade.dts rename to arch/arm/boot/dts/aspeed/aspeed-bmc-ampere-mtjade.dts diff --git a/arch/arm/boot/dts/aspeed-bmc-ampere-mtmitchell.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-ampere-mtmitchell.dts similarity index 100% rename from arch/arm/boot/dts/aspeed-bmc-ampere-mtmitchell.dts rename to arch/arm/boot/dts/aspeed/aspeed-bmc-ampere-mtmitchell.dts diff --git a/arch/arm/boot/dts/aspeed-bmc-arm-stardragon4800-rep2.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-arm-stardragon4800-rep2.dts similarity index 100% rename from arch/arm/boot/dts/aspeed-bmc-arm-stardragon4800-rep2.dts rename to arch/arm/boot/dts/aspeed/aspeed-bmc-arm-stardragon4800-rep2.dts diff --git a/arch/arm/boot/dts/aspeed-bmc-asrock-e3c246d4i.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-asrock-e3c246d4i.dts similarity index 100% rename from arch/arm/boot/dts/aspeed-bmc-asrock-e3c246d4i.dts rename to arch/arm/boot/dts/aspeed/aspeed-bmc-asrock-e3c246d4i.dts diff --git a/arch/arm/boot/dts/aspeed-bmc-asrock-romed8hm3.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-asrock-romed8hm3.dts similarity index 100% rename from arch/arm/boot/dts/aspeed-bmc-asrock-romed8hm3.dts rename to arch/arm/boot/dts/aspeed/aspeed-bmc-asrock-romed8hm3.dts diff --git a/arch/arm/boot/dts/aspeed-bmc-bytedance-g220a.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-bytedance-g220a.dts similarity index 100% rename from arch/arm/boot/dts/aspeed-bmc-bytedance-g220a.dts rename to arch/arm/boot/dts/aspeed/aspeed-bmc-bytedance-g220a.dts diff --git a/arch/arm/boot/dts/aspeed-bmc-delta-ahe50dc.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-delta-ahe50dc.dts similarity index 100% rename from arch/arm/boot/dts/aspeed-bmc-delta-ahe50dc.dts rename to arch/arm/boot/dts/aspeed/aspeed-bmc-delta-ahe50dc.dts diff --git a/arch/arm/boot/dts/aspeed-bmc-facebook-bletchley.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-bletchley.dts similarity index 100% rename from arch/arm/boot/dts/aspeed-bmc-facebook-bletchley.dts rename to arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-bletchley.dts diff --git a/arch/arm/boot/dts/aspeed-bmc-facebook-cloudripper.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-cloudripper.dts similarity index 100% rename from arch/arm/boot/dts/aspeed-bmc-facebook-cloudripper.dts rename to arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-cloudripper.dts diff --git a/arch/arm/boot/dts/aspeed-bmc-facebook-cmm.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-cmm.dts similarity index 100% rename from arch/arm/boot/dts/aspeed-bmc-facebook-cmm.dts rename to arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-cmm.dts diff --git a/arch/arm/boot/dts/aspeed-bmc-facebook-elbert.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-elbert.dts similarity index 100% rename from arch/arm/boot/dts/aspeed-bmc-facebook-elbert.dts rename to arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-elbert.dts diff --git a/arch/arm/boot/dts/aspeed-bmc-facebook-fuji.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-fuji.dts similarity index 100% rename from arch/arm/boot/dts/aspeed-bmc-facebook-fuji.dts rename to arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-fuji.dts diff --git a/arch/arm/boot/dts/aspeed-bmc-facebook-galaxy100.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-galaxy100.dts similarity index 100% rename from arch/arm/boot/dts/aspeed-bmc-facebook-galaxy100.dts rename to arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-galaxy100.dts diff --git a/arch/arm/boot/dts/aspeed-bmc-facebook-greatlakes.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-greatlakes.dts similarity index 100% rename from arch/arm/boot/dts/aspeed-bmc-facebook-greatlakes.dts rename to arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-greatlakes.dts diff --git a/arch/arm/boot/dts/aspeed-bmc-facebook-minipack.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-minipack.dts similarity index 100% rename from arch/arm/boot/dts/aspeed-bmc-facebook-minipack.dts rename to arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-minipack.dts diff --git a/arch/arm/boot/dts/aspeed-bmc-facebook-tiogapass.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-tiogapass.dts similarity index 100% rename from arch/arm/boot/dts/aspeed-bmc-facebook-tiogapass.dts rename to arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-tiogapass.dts diff --git a/arch/arm/boot/dts/aspeed-bmc-facebook-wedge100.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-wedge100.dts similarity index 100% rename from arch/arm/boot/dts/aspeed-bmc-facebook-wedge100.dts rename to arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-wedge100.dts diff --git a/arch/arm/boot/dts/aspeed-bmc-facebook-wedge40.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-wedge40.dts similarity index 100% rename from arch/arm/boot/dts/aspeed-bmc-facebook-wedge40.dts rename to arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-wedge40.dts diff --git a/arch/arm/boot/dts/aspeed-bmc-facebook-wedge400.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-wedge400.dts similarity index 100% rename from arch/arm/boot/dts/aspeed-bmc-facebook-wedge400.dts rename to arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-wedge400.dts diff --git a/arch/arm/boot/dts/aspeed-bmc-facebook-yamp.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-yamp.dts similarity index 100% rename from arch/arm/boot/dts/aspeed-bmc-facebook-yamp.dts rename to arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-yamp.dts diff --git a/arch/arm/boot/dts/aspeed-bmc-facebook-yosemitev2.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-yosemitev2.dts similarity index 100% rename from arch/arm/boot/dts/aspeed-bmc-facebook-yosemitev2.dts rename to arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-yosemitev2.dts diff --git a/arch/arm/boot/dts/aspeed-bmc-ibm-bonnell.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-ibm-bonnell.dts similarity index 100% rename from arch/arm/boot/dts/aspeed-bmc-ibm-bonnell.dts rename to arch/arm/boot/dts/aspeed/aspeed-bmc-ibm-bonnell.dts diff --git a/arch/arm/boot/dts/aspeed-bmc-ibm-everest.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-ibm-everest.dts similarity index 100% rename from arch/arm/boot/dts/aspeed-bmc-ibm-everest.dts rename to arch/arm/boot/dts/aspeed/aspeed-bmc-ibm-everest.dts diff --git a/arch/arm/boot/dts/aspeed-bmc-ibm-rainier-1s4u.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-ibm-rainier-1s4u.dts similarity index 100% rename from arch/arm/boot/dts/aspeed-bmc-ibm-rainier-1s4u.dts rename to arch/arm/boot/dts/aspeed/aspeed-bmc-ibm-rainier-1s4u.dts diff --git a/arch/arm/boot/dts/aspeed-bmc-ibm-rainier-4u.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-ibm-rainier-4u.dts similarity index 100% rename from arch/arm/boot/dts/aspeed-bmc-ibm-rainier-4u.dts rename to arch/arm/boot/dts/aspeed/aspeed-bmc-ibm-rainier-4u.dts diff --git a/arch/arm/boot/dts/aspeed-bmc-ibm-rainier.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-ibm-rainier.dts similarity index 100% rename from arch/arm/boot/dts/aspeed-bmc-ibm-rainier.dts rename to arch/arm/boot/dts/aspeed/aspeed-bmc-ibm-rainier.dts diff --git a/arch/arm/boot/dts/aspeed-bmc-inspur-fp5280g2.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-inspur-fp5280g2.dts similarity index 100% rename from arch/arm/boot/dts/aspeed-bmc-inspur-fp5280g2.dts rename to arch/arm/boot/dts/aspeed/aspeed-bmc-inspur-fp5280g2.dts diff --git a/arch/arm/boot/dts/aspeed-bmc-inspur-nf5280m6.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-inspur-nf5280m6.dts similarity index 100% rename from arch/arm/boot/dts/aspeed-bmc-inspur-nf5280m6.dts rename to arch/arm/boot/dts/aspeed/aspeed-bmc-inspur-nf5280m6.dts diff --git a/arch/arm/boot/dts/aspeed-bmc-inspur-on5263m5.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-inspur-on5263m5.dts similarity index 100% rename from arch/arm/boot/dts/aspeed-bmc-inspur-on5263m5.dts rename to arch/arm/boot/dts/aspeed/aspeed-bmc-inspur-on5263m5.dts diff --git a/arch/arm/boot/dts/aspeed-bmc-intel-s2600wf.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-intel-s2600wf.dts similarity index 100% rename from arch/arm/boot/dts/aspeed-bmc-intel-s2600wf.dts rename to arch/arm/boot/dts/aspeed/aspeed-bmc-intel-s2600wf.dts diff --git a/arch/arm/boot/dts/aspeed-bmc-inventec-transformers.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-inventec-transformers.dts similarity index 100% rename from arch/arm/boot/dts/aspeed-bmc-inventec-transformers.dts rename to arch/arm/boot/dts/aspeed/aspeed-bmc-inventec-transformers.dts diff --git a/arch/arm/boot/dts/aspeed-bmc-lenovo-hr630.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-lenovo-hr630.dts similarity index 100% rename from arch/arm/boot/dts/aspeed-bmc-lenovo-hr630.dts rename to arch/arm/boot/dts/aspeed/aspeed-bmc-lenovo-hr630.dts diff --git a/arch/arm/boot/dts/aspeed-bmc-lenovo-hr855xg2.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-lenovo-hr855xg2.dts similarity index 100% rename from arch/arm/boot/dts/aspeed-bmc-lenovo-hr855xg2.dts rename to arch/arm/boot/dts/aspeed/aspeed-bmc-lenovo-hr855xg2.dts diff --git a/arch/arm/boot/dts/aspeed-bmc-microsoft-olympus.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-microsoft-olympus.dts similarity index 100% rename from arch/arm/boot/dts/aspeed-bmc-microsoft-olympus.dts rename to arch/arm/boot/dts/aspeed/aspeed-bmc-microsoft-olympus.dts diff --git a/arch/arm/boot/dts/aspeed-bmc-opp-lanyang.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-opp-lanyang.dts similarity index 100% rename from arch/arm/boot/dts/aspeed-bmc-opp-lanyang.dts rename to arch/arm/boot/dts/aspeed/aspeed-bmc-opp-lanyang.dts diff --git a/arch/arm/boot/dts/aspeed-bmc-opp-mowgli.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-opp-mowgli.dts similarity index 100% rename from arch/arm/boot/dts/aspeed-bmc-opp-mowgli.dts rename to arch/arm/boot/dts/aspeed/aspeed-bmc-opp-mowgli.dts diff --git a/arch/arm/boot/dts/aspeed-bmc-opp-nicole.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-opp-nicole.dts similarity index 100% rename from arch/arm/boot/dts/aspeed-bmc-opp-nicole.dts rename to arch/arm/boot/dts/aspeed/aspeed-bmc-opp-nicole.dts diff --git a/arch/arm/boot/dts/aspeed-bmc-opp-palmetto.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-opp-palmetto.dts similarity index 100% rename from arch/arm/boot/dts/aspeed-bmc-opp-palmetto.dts rename to arch/arm/boot/dts/aspeed/aspeed-bmc-opp-palmetto.dts diff --git a/arch/arm/boot/dts/aspeed-bmc-opp-romulus.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-opp-romulus.dts similarity index 100% rename from arch/arm/boot/dts/aspeed-bmc-opp-romulus.dts rename to arch/arm/boot/dts/aspeed/aspeed-bmc-opp-romulus.dts diff --git a/arch/arm/boot/dts/aspeed-bmc-opp-swift.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-opp-swift.dts similarity index 100% rename from arch/arm/boot/dts/aspeed-bmc-opp-swift.dts rename to arch/arm/boot/dts/aspeed/aspeed-bmc-opp-swift.dts diff --git a/arch/arm/boot/dts/aspeed-bmc-opp-tacoma.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-opp-tacoma.dts similarity index 100% rename from arch/arm/boot/dts/aspeed-bmc-opp-tacoma.dts rename to arch/arm/boot/dts/aspeed/aspeed-bmc-opp-tacoma.dts diff --git a/arch/arm/boot/dts/aspeed-bmc-opp-vesnin.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-opp-vesnin.dts similarity index 100% rename from arch/arm/boot/dts/aspeed-bmc-opp-vesnin.dts rename to arch/arm/boot/dts/aspeed/aspeed-bmc-opp-vesnin.dts diff --git a/arch/arm/boot/dts/aspeed-bmc-opp-witherspoon.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-opp-witherspoon.dts similarity index 100% rename from arch/arm/boot/dts/aspeed-bmc-opp-witherspoon.dts rename to arch/arm/boot/dts/aspeed/aspeed-bmc-opp-witherspoon.dts diff --git a/arch/arm/boot/dts/aspeed-bmc-opp-zaius.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-opp-zaius.dts similarity index 100% rename from arch/arm/boot/dts/aspeed-bmc-opp-zaius.dts rename to arch/arm/boot/dts/aspeed/aspeed-bmc-opp-zaius.dts diff --git a/arch/arm/boot/dts/aspeed-bmc-portwell-neptune.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-portwell-neptune.dts similarity index 100% rename from arch/arm/boot/dts/aspeed-bmc-portwell-neptune.dts rename to arch/arm/boot/dts/aspeed/aspeed-bmc-portwell-neptune.dts diff --git a/arch/arm/boot/dts/aspeed-bmc-qcom-dc-scm-v1.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-qcom-dc-scm-v1.dts similarity index 100% rename from arch/arm/boot/dts/aspeed-bmc-qcom-dc-scm-v1.dts rename to arch/arm/boot/dts/aspeed/aspeed-bmc-qcom-dc-scm-v1.dts diff --git a/arch/arm/boot/dts/aspeed-bmc-quanta-q71l.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-quanta-q71l.dts similarity index 100% rename from arch/arm/boot/dts/aspeed-bmc-quanta-q71l.dts rename to arch/arm/boot/dts/aspeed/aspeed-bmc-quanta-q71l.dts diff --git a/arch/arm/boot/dts/aspeed-bmc-quanta-s6q.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-quanta-s6q.dts similarity index 100% rename from arch/arm/boot/dts/aspeed-bmc-quanta-s6q.dts rename to arch/arm/boot/dts/aspeed/aspeed-bmc-quanta-s6q.dts diff --git a/arch/arm/boot/dts/aspeed-bmc-supermicro-x11spi.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-supermicro-x11spi.dts similarity index 100% rename from arch/arm/boot/dts/aspeed-bmc-supermicro-x11spi.dts rename to arch/arm/boot/dts/aspeed/aspeed-bmc-supermicro-x11spi.dts diff --git a/arch/arm/boot/dts/aspeed-bmc-tyan-s7106.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-tyan-s7106.dts similarity index 100% rename from arch/arm/boot/dts/aspeed-bmc-tyan-s7106.dts rename to arch/arm/boot/dts/aspeed/aspeed-bmc-tyan-s7106.dts diff --git a/arch/arm/boot/dts/aspeed-bmc-tyan-s8036.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-tyan-s8036.dts similarity index 100% rename from arch/arm/boot/dts/aspeed-bmc-tyan-s8036.dts rename to arch/arm/boot/dts/aspeed/aspeed-bmc-tyan-s8036.dts diff --git a/arch/arm/boot/dts/aspeed-bmc-ufispace-ncplite.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-ufispace-ncplite.dts similarity index 100% rename from arch/arm/boot/dts/aspeed-bmc-ufispace-ncplite.dts rename to arch/arm/boot/dts/aspeed/aspeed-bmc-ufispace-ncplite.dts diff --git a/arch/arm/boot/dts/aspeed-bmc-vegman-n110.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-vegman-n110.dts similarity index 100% rename from arch/arm/boot/dts/aspeed-bmc-vegman-n110.dts rename to arch/arm/boot/dts/aspeed/aspeed-bmc-vegman-n110.dts diff --git a/arch/arm/boot/dts/aspeed-bmc-vegman-rx20.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-vegman-rx20.dts similarity index 100% rename from arch/arm/boot/dts/aspeed-bmc-vegman-rx20.dts rename to arch/arm/boot/dts/aspeed/aspeed-bmc-vegman-rx20.dts diff --git a/arch/arm/boot/dts/aspeed-bmc-vegman-sx20.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-vegman-sx20.dts similarity index 100% rename from arch/arm/boot/dts/aspeed-bmc-vegman-sx20.dts rename to arch/arm/boot/dts/aspeed/aspeed-bmc-vegman-sx20.dts diff --git a/arch/arm/boot/dts/aspeed-bmc-vegman.dtsi b/arch/arm/boot/dts/aspeed/aspeed-bmc-vegman.dtsi similarity index 100% rename from arch/arm/boot/dts/aspeed-bmc-vegman.dtsi rename to arch/arm/boot/dts/aspeed/aspeed-bmc-vegman.dtsi diff --git a/arch/arm/boot/dts/aspeed-g4.dtsi b/arch/arm/boot/dts/aspeed/aspeed-g4.dtsi similarity index 100% rename from arch/arm/boot/dts/aspeed-g4.dtsi rename to arch/arm/boot/dts/aspeed/aspeed-g4.dtsi diff --git a/arch/arm/boot/dts/aspeed-g5.dtsi b/arch/arm/boot/dts/aspeed/aspeed-g5.dtsi similarity index 100% rename from arch/arm/boot/dts/aspeed-g5.dtsi rename to arch/arm/boot/dts/aspeed/aspeed-g5.dtsi diff --git a/arch/arm/boot/dts/aspeed-g6-pinctrl.dtsi b/arch/arm/boot/dts/aspeed/aspeed-g6-pinctrl.dtsi similarity index 100% rename from arch/arm/boot/dts/aspeed-g6-pinctrl.dtsi rename to arch/arm/boot/dts/aspeed/aspeed-g6-pinctrl.dtsi diff --git a/arch/arm/boot/dts/aspeed-g6.dtsi b/arch/arm/boot/dts/aspeed/aspeed-g6.dtsi similarity index 100% rename from arch/arm/boot/dts/aspeed-g6.dtsi rename to arch/arm/boot/dts/aspeed/aspeed-g6.dtsi diff --git a/arch/arm/boot/dts/ast2400-facebook-netbmc-common.dtsi b/arch/arm/boot/dts/aspeed/ast2400-facebook-netbmc-common.dtsi similarity index 100% rename from arch/arm/boot/dts/ast2400-facebook-netbmc-common.dtsi rename to arch/arm/boot/dts/aspeed/ast2400-facebook-netbmc-common.dtsi diff --git a/arch/arm/boot/dts/ast2500-facebook-netbmc-common.dtsi b/arch/arm/boot/dts/aspeed/ast2500-facebook-netbmc-common.dtsi similarity index 100% rename from arch/arm/boot/dts/ast2500-facebook-netbmc-common.dtsi rename to arch/arm/boot/dts/aspeed/ast2500-facebook-netbmc-common.dtsi diff --git a/arch/arm/boot/dts/ast2600-facebook-netbmc-common.dtsi b/arch/arm/boot/dts/aspeed/ast2600-facebook-netbmc-common.dtsi similarity index 100% rename from arch/arm/boot/dts/ast2600-facebook-netbmc-common.dtsi rename to arch/arm/boot/dts/aspeed/ast2600-facebook-netbmc-common.dtsi diff --git a/arch/arm/boot/dts/facebook-bmc-flash-layout-128.dtsi b/arch/arm/boot/dts/aspeed/facebook-bmc-flash-layout-128.dtsi similarity index 100% rename from arch/arm/boot/dts/facebook-bmc-flash-layout-128.dtsi rename to arch/arm/boot/dts/aspeed/facebook-bmc-flash-layout-128.dtsi diff --git a/arch/arm/boot/dts/facebook-bmc-flash-layout.dtsi b/arch/arm/boot/dts/aspeed/facebook-bmc-flash-layout.dtsi similarity index 100% rename from arch/arm/boot/dts/facebook-bmc-flash-layout.dtsi rename to arch/arm/boot/dts/aspeed/facebook-bmc-flash-layout.dtsi diff --git a/arch/arm/boot/dts/ibm-power9-dual.dtsi b/arch/arm/boot/dts/aspeed/ibm-power9-dual.dtsi similarity index 100% rename from arch/arm/boot/dts/ibm-power9-dual.dtsi rename to arch/arm/boot/dts/aspeed/ibm-power9-dual.dtsi diff --git a/arch/arm/boot/dts/openbmc-flash-layout-128.dtsi b/arch/arm/boot/dts/aspeed/openbmc-flash-layout-128.dtsi similarity index 100% rename from arch/arm/boot/dts/openbmc-flash-layout-128.dtsi rename to arch/arm/boot/dts/aspeed/openbmc-flash-layout-128.dtsi diff --git a/arch/arm/boot/dts/openbmc-flash-layout-64-alt.dtsi b/arch/arm/boot/dts/aspeed/openbmc-flash-layout-64-alt.dtsi similarity index 100% rename from arch/arm/boot/dts/openbmc-flash-layout-64-alt.dtsi rename to arch/arm/boot/dts/aspeed/openbmc-flash-layout-64-alt.dtsi diff --git a/arch/arm/boot/dts/openbmc-flash-layout-64.dtsi b/arch/arm/boot/dts/aspeed/openbmc-flash-layout-64.dtsi similarity index 100% rename from arch/arm/boot/dts/openbmc-flash-layout-64.dtsi rename to arch/arm/boot/dts/aspeed/openbmc-flash-layout-64.dtsi diff --git a/arch/arm/boot/dts/openbmc-flash-layout.dtsi b/arch/arm/boot/dts/aspeed/openbmc-flash-layout.dtsi similarity index 100% rename from arch/arm/boot/dts/openbmc-flash-layout.dtsi rename to arch/arm/boot/dts/aspeed/openbmc-flash-layout.dtsi diff --git a/arch/arm/boot/dts/axis/Makefile b/arch/arm/boot/dts/axis/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..2cab41451281a7711c2eb0628d420807a25c6fe4 --- /dev/null +++ b/arch/arm/boot/dts/axis/Makefile @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0 +dtb-$(CONFIG_MACH_ARTPEC6) += \ + artpec6-devboard.dtb +dtb-$(CONFIG_MACH_ARTPEC6) += \ + artpec6-devboard.dtb diff --git a/arch/arm/boot/dts/artpec6-devboard.dts b/arch/arm/boot/dts/axis/artpec6-devboard.dts similarity index 100% rename from arch/arm/boot/dts/artpec6-devboard.dts rename to arch/arm/boot/dts/axis/artpec6-devboard.dts diff --git a/arch/arm/boot/dts/artpec6.dtsi b/arch/arm/boot/dts/axis/artpec6.dtsi similarity index 100% rename from arch/arm/boot/dts/artpec6.dtsi rename to arch/arm/boot/dts/axis/artpec6.dtsi diff --git a/arch/arm/boot/dts/bcm21664-garnet.dts b/arch/arm/boot/dts/bcm21664-garnet.dts deleted file mode 100644 index cd03fa0c2aae446f94c81471b958243570f98a3c..0000000000000000000000000000000000000000 --- a/arch/arm/boot/dts/bcm21664-garnet.dts +++ /dev/null @@ -1,47 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -// Copyright (C) 2014 Broadcom Corporation - -/dts-v1/; - -#include - -#include "bcm21664.dtsi" - -/ { - model = "BCM21664 Garnet board"; - compatible = "brcm,bcm21664-garnet", "brcm,bcm21664"; - - memory@80000000 { - device_type = "memory"; - reg = <0x80000000 0x40000000>; /* 1 GB */ - }; - - serial@3e000000 { - status = "okay"; - }; - - sdio1: sdio@3f180000 { - max-frequency = <48000000>; - status = "okay"; - }; - - sdio2: sdio@3f190000 { - non-removable; - max-frequency = <48000000>; - status = "okay"; - }; - - sdio4: sdio@3f1b0000 { - max-frequency = <48000000>; - cd-gpios = <&gpio 91 GPIO_ACTIVE_LOW>; - status = "okay"; - }; - - usbotg: usb@3f120000 { - status = "okay"; - }; - - usbphy: usb-phy@3f130000 { - status = "okay"; - }; -}; diff --git a/arch/arm/boot/dts/broadcom/Makefile b/arch/arm/boot/dts/broadcom/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..95b0ef2a4215293c1b15ced54ca6bc7bddcda4d2 --- /dev/null +++ b/arch/arm/boot/dts/broadcom/Makefile @@ -0,0 +1,125 @@ +# SPDX-License-Identifier: GPL-2.0 +# Enables support for device-tree overlays +DTC_FLAGS_bcm2835-rpi-b := -@ +DTC_FLAGS_bcm2835-rpi-a := -@ +DTC_FLAGS_bcm2835-rpi-b-rev2 := -@ +DTC_FLAGS_bcm2835-rpi-b-plus := -@ +DTC_FLAGS_bcm2835-rpi-a-plus := -@ +DTC_FLAGS_bcm2835-rpi-cm1-io1 := -@ +DTC_FLAGS_bcm2836-rpi-2-b := -@ +DTC_FLAGS_bcm2837-rpi-3-a-plus := -@ +DTC_FLAGS_bcm2837-rpi-3-b := -@ +DTC_FLAGS_bcm2837-rpi-3-b-plus := -@ +DTC_FLAGS_bcm2837-rpi-cm3-io3 := -@ +DTC_FLAGS_bcm2837-rpi-zero-2-w := -@ +DTC_FLAGS_bcm2711-rpi-400 := -@ +DTC_FLAGS_bcm2711-rpi-4-b := -@ +DTC_FLAGS_bcm2711-rpi-cm4-io := -@ +DTC_FLAGS_bcm2835-rpi-zero := -@ +DTC_FLAGS_bcm2835-rpi-zero-w := -@ +dtb-$(CONFIG_ARCH_BCM2835) += \ + bcm2835-rpi-b.dtb \ + bcm2835-rpi-a.dtb \ + bcm2835-rpi-b-rev2.dtb \ + bcm2835-rpi-b-plus.dtb \ + bcm2835-rpi-a-plus.dtb \ + bcm2835-rpi-cm1-io1.dtb \ + bcm2836-rpi-2-b.dtb \ + bcm2837-rpi-3-a-plus.dtb \ + bcm2837-rpi-3-b.dtb \ + bcm2837-rpi-3-b-plus.dtb \ + bcm2837-rpi-cm3-io3.dtb \ + bcm2837-rpi-zero-2-w.dtb \ + bcm2711-rpi-400.dtb \ + bcm2711-rpi-4-b.dtb \ + bcm2711-rpi-cm4-io.dtb \ + bcm2835-rpi-zero.dtb \ + bcm2835-rpi-zero-w.dtb +dtb-$(CONFIG_ARCH_BCMBCA) += \ + bcm947622.dtb \ + bcm963138.dtb \ + bcm963138dvt.dtb \ + bcm963148.dtb \ + bcm963178.dtb \ + bcm96756.dtb \ + bcm96846.dtb \ + bcm96855.dtb \ + bcm96878.dtb +dtb-$(CONFIG_ARCH_BCM_5301X) += \ + bcm4708-asus-rt-ac56u.dtb \ + bcm4708-asus-rt-ac68u.dtb \ + bcm4708-buffalo-wzr-1750dhp.dtb \ + bcm4708-buffalo-wzr-1166dhp.dtb \ + bcm4708-buffalo-wzr-1166dhp2.dtb \ + bcm4708-linksys-ea6300-v1.dtb \ + bcm4708-linksys-ea6500-v2.dtb \ + bcm4708-luxul-xap-1510.dtb \ + bcm4708-luxul-xwc-1000.dtb \ + bcm4708-netgear-r6250.dtb \ + bcm4708-netgear-r6300-v2.dtb \ + bcm4708-smartrg-sr400ac.dtb \ + bcm47081-asus-rt-n18u.dtb \ + bcm47081-buffalo-wzr-600dhp2.dtb \ + bcm47081-buffalo-wzr-900dhp.dtb \ + bcm47081-luxul-xap-1410.dtb \ + bcm47081-luxul-xwr-1200.dtb \ + bcm47081-tplink-archer-c5-v2.dtb \ + bcm4709-asus-rt-ac87u.dtb \ + bcm4709-buffalo-wxr-1900dhp.dtb \ + bcm4709-linksys-ea9200.dtb \ + bcm4709-netgear-r7000.dtb \ + bcm4709-netgear-r8000.dtb \ + bcm4709-tplink-archer-c9-v1.dtb \ + bcm47094-asus-rt-ac88u.dtb \ + bcm47094-dlink-dir-885l.dtb \ + bcm47094-dlink-dir-890l.dtb \ + bcm47094-linksys-panamera.dtb \ + bcm47094-luxul-abr-4500.dtb \ + bcm47094-luxul-xap-1610.dtb \ + bcm47094-luxul-xbr-4500.dtb \ + bcm47094-luxul-xwc-2000.dtb \ + bcm47094-luxul-xwr-3100.dtb \ + bcm47094-luxul-xwr-3150-v1.dtb \ + bcm47094-netgear-r8500.dtb \ + bcm47094-phicomm-k3.dtb \ + bcm53015-meraki-mr26.dtb \ + bcm53016-dlink-dwl-8610ap.dtb \ + bcm53016-meraki-mr32.dtb \ + bcm94708.dtb \ + bcm94709.dtb \ + bcm953012er.dtb \ + bcm953012hr.dtb \ + bcm953012k.dtb +dtb-$(CONFIG_ARCH_BCM_53573) += \ + bcm47189-luxul-xap-1440.dtb \ + bcm47189-luxul-xap-810.dtb \ + bcm47189-tenda-ac9.dtb \ + bcm947189acdbmr.dtb +dtb-$(CONFIG_ARCH_BCM_CYGNUS) += \ + bcm911360_entphn.dtb \ + bcm911360k.dtb \ + bcm958300k.dtb \ + bcm958305k.dtb +dtb-$(CONFIG_ARCH_BCM_HR2) += \ + bcm53340-ubnt-unifi-switch8.dtb +dtb-$(CONFIG_ARCH_BCM_MOBILE) += \ + bcm28155-ap.dtb \ + bcm21664-garnet.dtb \ + bcm23550-sparrow.dtb +dtb-$(CONFIG_ARCH_BCM_NSP) += \ + bcm958522er.dtb \ + bcm958525er.dtb \ + bcm958525xmc.dtb \ + bcm958622hr.dtb \ + bcm958623hr.dtb \ + bcm958625-meraki-mx64.dtb \ + bcm958625-meraki-mx64-a0.dtb \ + bcm958625-meraki-mx64w.dtb \ + bcm958625-meraki-mx64w-a0.dtb \ + bcm958625-meraki-mx65.dtb \ + bcm958625-meraki-mx65w.dtb \ + bcm958625hr.dtb \ + bcm988312hr.dtb \ + bcm958625k.dtb +dtb-$(CONFIG_ARCH_BRCMSTB) += \ + bcm7445-bcm97445svmb.dtb diff --git a/arch/arm/boot/dts/bcm-cygnus-clock.dtsi b/arch/arm/boot/dts/broadcom/bcm-cygnus-clock.dtsi similarity index 100% rename from arch/arm/boot/dts/bcm-cygnus-clock.dtsi rename to arch/arm/boot/dts/broadcom/bcm-cygnus-clock.dtsi diff --git a/arch/arm/boot/dts/bcm-cygnus.dtsi b/arch/arm/boot/dts/broadcom/bcm-cygnus.dtsi similarity index 100% rename from arch/arm/boot/dts/bcm-cygnus.dtsi rename to arch/arm/boot/dts/broadcom/bcm-cygnus.dtsi diff --git a/arch/arm/boot/dts/bcm-hr2.dtsi b/arch/arm/boot/dts/broadcom/bcm-hr2.dtsi similarity index 100% rename from arch/arm/boot/dts/bcm-hr2.dtsi rename to arch/arm/boot/dts/broadcom/bcm-hr2.dtsi diff --git a/arch/arm/boot/dts/bcm5301x.dtsi b/arch/arm/boot/dts/broadcom/bcm-ns.dtsi similarity index 71% rename from arch/arm/boot/dts/bcm5301x.dtsi rename to arch/arm/boot/dts/broadcom/bcm-ns.dtsi index 5fc1b847f4aa540f45420be1c24f8bedb305b5dd..dae9c47ace761cdbd1c893ceade44ea07ef75eb4 100644 --- a/arch/arm/boot/dts/bcm5301x.dtsi +++ b/arch/arm/boot/dts/broadcom/bcm-ns.dtsi @@ -1,11 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT /* - * Broadcom BCM470X / BCM5301X ARM platform code. - * Generic DTS part for all BCM53010, BCM53011, BCM53012, BCM53014, BCM53015, - * BCM53016, BCM53017, BCM53018, BCM4707, BCM4708 and BCM4709 SoCs - * * Copyright 2013-2014 Hauke Mehrtens - * - * Licensed under the GNU/GPL. See COPYING for details. */ #include @@ -15,9 +10,9 @@ #include / { + interrupt-parent = <&gic>; #address-cells = <1>; #size-cells = <1>; - interrupt-parent = <&gic>; chipcommon-a-bus@18000000 { compatible = "simple-bus"; @@ -50,13 +45,6 @@ #address-cells = <1>; #size-cells = <1>; - a9pll: arm_clk@0 { - #clock-cells = <0>; - compatible = "brcm,nsp-armpll"; - clocks = <&osc>; - reg = <0x00000 0x1000>; - }; - scu@20000 { compatible = "arm,cortex-a9-scu"; reg = <0x20000 0x100>; @@ -77,14 +65,6 @@ clocks = <&periph_clk>; }; - watchdog@20620 { - compatible = "arm,cortex-a9-twd-wdt"; - reg = <0x20620 0x20>; - interrupts = ; - clocks = <&periph_clk>; - }; - gic: interrupt-controller@21000 { compatible = "arm,cortex-a9-gic"; #interrupt-cells = <3>; @@ -105,49 +85,6 @@ }; }; - pmu { - compatible = "arm,cortex-a9-pmu"; - interrupts = - , - ; - }; - - clocks { - #address-cells = <1>; - #size-cells = <1>; - ranges; - - osc: oscillator { - #clock-cells = <0>; - compatible = "fixed-clock"; - clock-frequency = <25000000>; - }; - - iprocmed: iprocmed { - #clock-cells = <0>; - compatible = "fixed-factor-clock"; - clocks = <&genpll BCM_NSP_GENPLL_IPROCFAST_CLK>; - clock-div = <2>; - clock-mult = <1>; - }; - - iprocslow: iprocslow { - #clock-cells = <0>; - compatible = "fixed-factor-clock"; - clocks = <&genpll BCM_NSP_GENPLL_IPROCFAST_CLK>; - clock-div = <4>; - clock-mult = <1>; - }; - - periph_clk: periph_clk { - #clock-cells = <0>; - compatible = "fixed-factor-clock"; - clocks = <&a9pll>; - clock-div = <2>; - clock-mult = <1>; - }; - }; - axi@18000000 { compatible = "brcm,bus-axi"; reg = <0x18000000 0x1000>; @@ -157,7 +94,7 @@ #interrupt-cells = <1>; interrupt-map-mask = <0x000fffff 0xffff>; - interrupt-map = + interrupt-map = /* ChipCommon */ <0x00000000 0 &gic GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>, @@ -239,14 +176,23 @@ pcie0: pcie@12000 { reg = <0x00012000 0x1000>; + + #address-cells = <3>; + #size-cells = <2>; }; pcie1: pcie@13000 { reg = <0x00013000 0x1000>; + + #address-cells = <3>; + #size-cells = <2>; }; pcie2: pcie@14000 { reg = <0x00014000 0x1000>; + + #address-cells = <3>; + #size-cells = <2>; }; usb2: usb2@21000 { @@ -259,8 +205,6 @@ interrupt-parent = <&gic>; ehci: usb@21000 { - #usb-cells = <0>; - compatible = "generic-ehci"; reg = <0x00021000 0x1000>; interrupts = ; @@ -281,8 +225,6 @@ }; ohci: usb@22000 { - #usb-cells = <0>; - compatible = "generic-ohci"; reg = <0x00022000 0x1000>; interrupts = ; @@ -312,8 +254,6 @@ interrupt-parent = <&gic>; xhci: usb@23000 { - #usb-cells = <0>; - compatible = "generic-xhci"; reg = <0x00023000 0x1000>; interrupts = ; @@ -362,31 +302,61 @@ #address-cells = <1>; }; - mdio-mux@18003000 { - compatible = "mdio-mux-mmioreg", "mdio-mux"; - mdio-parent-bus = <&mdio>; - #address-cells = <1>; - #size-cells = <0>; - reg = <0x18003000 0x4>; - mux-mask = <0x200>; + rng: rng@18004000 { + compatible = "brcm,bcm5301x-rng"; + reg = <0x18004000 0x14>; + }; + + srab: ethernet-switch@18007000 { + compatible = "brcm,bcm53011-srab", "brcm,bcm5301x-srab"; + reg = <0x18007000 0x1000>; + + status = "disabled"; - mdio@0 { - reg = <0x0>; + ports { #address-cells = <1>; #size-cells = <0>; - usb3_phy: usb3-phy@10 { - compatible = "brcm,ns-ax-usb3-phy"; - reg = <0x10>; - usb3-dmp-syscon = <&usb3_dmp>; - #phy-cells = <0>; - status = "disabled"; + port@0 { + reg = <0>; + }; + + port@1 { + reg = <1>; + }; + + port@2 { + reg = <2>; }; - }; - }; - usb3_dmp: syscon@18105000 { - reg = <0x18105000 0x1000>; + port@3 { + reg = <3>; + }; + + port@4 { + reg = <4>; + }; + + port@5 { + reg = <5>; + ethernet = <&gmac0>; + }; + + port@7 { + reg = <7>; + ethernet = <&gmac1>; + }; + + port@8 { + reg = <8>; + ethernet = <&gmac2>; + + fixed-link { + speed = <1000>; + full-duplex; + }; + }; + }; }; uart2: serial@18008000 { @@ -398,16 +368,6 @@ status = "disabled"; }; - i2c0: i2c@18009000 { - compatible = "brcm,iproc-i2c"; - reg = <0x18009000 0x50>; - interrupts = ; - #address-cells = <1>; - #size-cells = <0>; - clock-frequency = <100000>; - status = "disabled"; - }; - dmu-bus@1800c000 { compatible = "simple-bus"; ranges = <0 0x1800c000 0x1000>; @@ -421,26 +381,6 @@ #address-cells = <1>; #size-cells = <1>; - lcpll0: clock-controller@100 { - #clock-cells = <1>; - compatible = "brcm,nsp-lcpll0"; - reg = <0x100 0x14>; - clocks = <&osc>; - clock-output-names = "lcpll0", "pcie_phy", - "sdio", "ddr_phy"; - }; - - genpll: clock-controller@140 { - #clock-cells = <1>; - compatible = "brcm,nsp-genpll"; - reg = <0x140 0x24>; - clocks = <&osc>; - clock-output-names = "genpll", "phy", - "ethernetclk", - "usbclk", "iprocfast", - "sata1", "sata2"; - }; - usb2_phy: phy@164 { compatible = "brcm,ns-usb2-phy"; reg = <0x164 0x4>; @@ -490,24 +430,6 @@ }; }; - srab: ethernet-switch@18007000 { - compatible = "brcm,bcm53011-srab", "brcm,bcm5301x-srab"; - reg = <0x18007000 0x1000>; - - status = "disabled"; - - /* ports are defined in board DTS */ - ports { - #address-cells = <1>; - #size-cells = <0>; - }; - }; - - rng: rng@18004000 { - compatible = "brcm,bcm5301x-rng"; - reg = <0x18004000 0x14>; - }; - nand_controller: nand-controller@18028000 { compatible = "brcm,nand-iproc", "brcm,brcmnand-v6.1", "brcm,brcmnand"; reg = <0x18028000 0x600>, <0x1811a408 0x600>, <0x18028f00 0x20>; @@ -520,45 +442,6 @@ brcm,nand-has-wp; }; - spi@18029200 { - compatible = "brcm,spi-nsp-qspi", "brcm,spi-bcm-qspi"; - reg = <0x18029200 0x184>, - <0x18029000 0x124>, - <0x1811b408 0x004>, - <0x180293a0 0x01c>; - reg-names = "mspi", "bspi", "intr_regs", "intr_status_reg"; - interrupts = , - , - , - , - , - , - ; - interrupt-names = "mspi_done", - "mspi_halted", - "spi_lr_fullness_reached", - "spi_lr_session_aborted", - "spi_lr_impatient", - "spi_lr_session_done", - "spi_lr_overread"; - clocks = <&iprocmed>; - clock-names = "iprocmed"; - num-cs = <2>; - #address-cells = <1>; - #size-cells = <0>; - - spi_nor: flash@0 { - compatible = "jedec,spi-nor"; - reg = <0>; - spi-max-frequency = <20000000>; - status = "disabled"; - - partitions { - compatible = "brcm,bcm947xx-cfe-partitions"; - }; - }; - }; - thermal-zones { cpu_thermal: cpu-thermal { polling-delay-passive = <0>; diff --git a/arch/arm/boot/dts/bcm-nsp-ax.dtsi b/arch/arm/boot/dts/broadcom/bcm-nsp-ax.dtsi similarity index 100% rename from arch/arm/boot/dts/bcm-nsp-ax.dtsi rename to arch/arm/boot/dts/broadcom/bcm-nsp-ax.dtsi diff --git a/arch/arm/boot/dts/bcm-nsp.dtsi b/arch/arm/boot/dts/broadcom/bcm-nsp.dtsi similarity index 100% rename from arch/arm/boot/dts/bcm-nsp.dtsi rename to arch/arm/boot/dts/broadcom/bcm-nsp.dtsi diff --git a/arch/arm/boot/dts/bcm11351.dtsi b/arch/arm/boot/dts/broadcom/bcm11351.dtsi similarity index 96% rename from arch/arm/boot/dts/bcm11351.dtsi rename to arch/arm/boot/dts/broadcom/bcm11351.dtsi index ba75784d66a9726259b4949ddca243de5e9234a4..b271a9bf06a9af51502d3993a10e63b32fa431aa 100644 --- a/arch/arm/boot/dts/bcm11351.dtsi +++ b/arch/arm/boot/dts/broadcom/bcm11351.dtsi @@ -1,11 +1,10 @@ // SPDX-License-Identifier: GPL-2.0-only // Copyright (C) 2012-2013 Broadcom Corporation +#include #include #include -#include "dt-bindings/clock/bcm281xx.h" - / { #address-cells = <1>; #size-cells = <1>; @@ -50,44 +49,44 @@ reg = <0x3404c000 0x400>; /* 1 KiB in SRAM */ }; - serial@3e000000 { + uartb: serial@3e000000 { compatible = "brcm,bcm11351-dw-apb-uart", "snps,dw-apb-uart"; - status = "disabled"; reg = <0x3e000000 0x1000>; clocks = <&slave_ccu BCM281XX_SLAVE_CCU_UARTB>; interrupts = ; reg-shift = <2>; reg-io-width = <4>; + status = "disabled"; }; - serial@3e001000 { + uartb2: serial@3e001000 { compatible = "brcm,bcm11351-dw-apb-uart", "snps,dw-apb-uart"; - status = "disabled"; reg = <0x3e001000 0x1000>; clocks = <&slave_ccu BCM281XX_SLAVE_CCU_UARTB2>; interrupts = ; reg-shift = <2>; reg-io-width = <4>; + status = "disabled"; }; - serial@3e002000 { + uartb3: serial@3e002000 { compatible = "brcm,bcm11351-dw-apb-uart", "snps,dw-apb-uart"; - status = "disabled"; reg = <0x3e002000 0x1000>; clocks = <&slave_ccu BCM281XX_SLAVE_CCU_UARTB3>; interrupts = ; reg-shift = <2>; reg-io-width = <4>; + status = "disabled"; }; - serial@3e003000 { + uartb4: serial@3e003000 { compatible = "brcm,bcm11351-dw-apb-uart", "snps,dw-apb-uart"; - status = "disabled"; reg = <0x3e003000 0x1000>; clocks = <&slave_ccu BCM281XX_SLAVE_CCU_UARTB4>; interrupts = ; reg-shift = <2>; reg-io-width = <4>; + status = "disabled"; }; L2: l2-cache@3ff20000 { @@ -125,7 +124,7 @@ interrupt-controller; }; - sdio1: sdio@3f180000 { + sdio1: mmc@3f180000 { compatible = "brcm,kona-sdhci"; reg = <0x3f180000 0x10000>; interrupts = ; @@ -133,7 +132,7 @@ status = "disabled"; }; - sdio2: sdio@3f190000 { + sdio2: mmc@3f190000 { compatible = "brcm,kona-sdhci"; reg = <0x3f190000 0x10000>; interrupts = ; @@ -141,7 +140,7 @@ status = "disabled"; }; - sdio3: sdio@3f1a0000 { + sdio3: mmc@3f1a0000 { compatible = "brcm,kona-sdhci"; reg = <0x3f1a0000 0x10000>; interrupts = ; @@ -149,7 +148,7 @@ status = "disabled"; }; - sdio4: sdio@3f1b0000 { + sdio4: mmc@3f1b0000 { compatible = "brcm,kona-sdhci"; reg = <0x3f1b0000 0x10000>; interrupts = ; @@ -162,7 +161,7 @@ reg = <0x35004800 0x430>; }; - i2c@3e016000 { + bsc1: i2c@3e016000 { compatible = "brcm,bcm11351-i2c", "brcm,kona-i2c"; reg = <0x3e016000 0x80>; interrupts = ; @@ -172,7 +171,7 @@ status = "disabled"; }; - i2c@3e017000 { + bsc2: i2c@3e017000 { compatible = "brcm,bcm11351-i2c", "brcm,kona-i2c"; reg = <0x3e017000 0x80>; interrupts = ; @@ -182,7 +181,7 @@ status = "disabled"; }; - i2c@3e018000 { + bsc3: i2c@3e018000 { compatible = "brcm,bcm11351-i2c", "brcm,kona-i2c"; reg = <0x3e018000 0x80>; interrupts = ; @@ -192,7 +191,7 @@ status = "disabled"; }; - i2c@3500d000 { + pmu_bsc: i2c@3500d000 { compatible = "brcm,bcm11351-i2c", "brcm,kona-i2c"; reg = <0x3500d000 0x80>; interrupts = ; diff --git a/arch/arm/boot/dts/broadcom/bcm21664-garnet.dts b/arch/arm/boot/dts/broadcom/bcm21664-garnet.dts new file mode 100644 index 0000000000000000000000000000000000000000..8789fae178bf80b8d1ee9c1074f725271935db23 --- /dev/null +++ b/arch/arm/boot/dts/broadcom/bcm21664-garnet.dts @@ -0,0 +1,47 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Copyright (C) 2014 Broadcom Corporation + +/dts-v1/; + +#include + +#include "bcm21664.dtsi" + +/ { + model = "BCM21664 Garnet board"; + compatible = "brcm,bcm21664-garnet", "brcm,bcm21664"; + + memory@80000000 { + device_type = "memory"; + reg = <0x80000000 0x40000000>; /* 1 GB */ + }; +}; + +&sdio1 { + max-frequency = <48000000>; + status = "okay"; +}; + +&sdio2 { + non-removable; + max-frequency = <48000000>; + status = "okay"; +}; + +&sdio4 { + max-frequency = <48000000>; + cd-gpios = <&gpio 91 GPIO_ACTIVE_LOW>; + status = "okay"; +}; + +&uartb { + status = "okay"; +}; + +&usbotg { + status = "okay"; +}; + +&usbphy { + status = "okay"; +}; diff --git a/arch/arm/boot/dts/bcm21664.dtsi b/arch/arm/boot/dts/broadcom/bcm21664.dtsi similarity index 94% rename from arch/arm/boot/dts/bcm21664.dtsi rename to arch/arm/boot/dts/broadcom/bcm21664.dtsi index ed4de031e48eef0f9ad4522cc667ce4f119a7052..2eb7f5b0c1dc5e9cfa7aab56c6014ad99f39c1fb 100644 --- a/arch/arm/boot/dts/bcm21664.dtsi +++ b/arch/arm/boot/dts/broadcom/bcm21664.dtsi @@ -1,11 +1,10 @@ // SPDX-License-Identifier: GPL-2.0-only // Copyright (C) 2014 Broadcom Corporation +#include #include #include -#include "dt-bindings/clock/bcm21664.h" - / { #address-cells = <1>; #size-cells = <1>; @@ -50,34 +49,34 @@ reg = <0x3404e000 0x400>; /* 1 KiB in SRAM */ }; - serial@3e000000 { + uartb: serial@3e000000 { compatible = "brcm,bcm21664-dw-apb-uart", "snps,dw-apb-uart"; - status = "disabled"; reg = <0x3e000000 0x118>; clocks = <&slave_ccu BCM21664_SLAVE_CCU_UARTB>; interrupts = ; reg-shift = <2>; reg-io-width = <4>; + status = "disabled"; }; - serial@3e001000 { + uartb2: serial@3e001000 { compatible = "brcm,bcm21664-dw-apb-uart", "snps,dw-apb-uart"; - status = "disabled"; reg = <0x3e001000 0x118>; clocks = <&slave_ccu BCM21664_SLAVE_CCU_UARTB2>; interrupts = ; reg-shift = <2>; reg-io-width = <4>; + status = "disabled"; }; - serial@3e002000 { + uartb3: serial@3e002000 { compatible = "brcm,bcm21664-dw-apb-uart", "snps,dw-apb-uart"; - status = "disabled"; reg = <0x3e002000 0x118>; clocks = <&slave_ccu BCM21664_SLAVE_CCU_UARTB3>; interrupts = ; reg-shift = <2>; reg-io-width = <4>; + status = "disabled"; }; L2: cache-controller@3ff20000 { @@ -113,7 +112,7 @@ interrupt-controller; }; - sdio1: sdio@3f180000 { + sdio1: mmc@3f180000 { compatible = "brcm,kona-sdhci"; reg = <0x3f180000 0x801c>; interrupts = ; @@ -121,7 +120,7 @@ status = "disabled"; }; - sdio2: sdio@3f190000 { + sdio2: mmc@3f190000 { compatible = "brcm,kona-sdhci"; reg = <0x3f190000 0x801c>; interrupts = ; @@ -129,7 +128,7 @@ status = "disabled"; }; - sdio3: sdio@3f1a0000 { + sdio3: mmc@3f1a0000 { compatible = "brcm,kona-sdhci"; reg = <0x3f1a0000 0x801c>; interrupts = ; @@ -137,7 +136,7 @@ status = "disabled"; }; - sdio4: sdio@3f1b0000 { + sdio4: mmc@3f1b0000 { compatible = "brcm,kona-sdhci"; reg = <0x3f1b0000 0x801c>; interrupts = ; @@ -145,7 +144,7 @@ status = "disabled"; }; - i2c@3e016000 { + bsc1: i2c@3e016000 { compatible = "brcm,bcm21664-i2c", "brcm,kona-i2c"; reg = <0x3e016000 0x70>; interrupts = ; @@ -155,7 +154,7 @@ status = "disabled"; }; - i2c@3e017000 { + bsc2: i2c@3e017000 { compatible = "brcm,bcm21664-i2c", "brcm,kona-i2c"; reg = <0x3e017000 0x70>; interrupts = ; @@ -165,7 +164,7 @@ status = "disabled"; }; - i2c@3e018000 { + bsc3: i2c@3e018000 { compatible = "brcm,bcm21664-i2c", "brcm,kona-i2c"; reg = <0x3e018000 0x70>; interrupts = ; @@ -175,7 +174,7 @@ status = "disabled"; }; - i2c@3e01c000 { + bsc4: i2c@3e01c000 { compatible = "brcm,bcm21664-i2c", "brcm,kona-i2c"; reg = <0x3e01c000 0x70>; interrupts = ; @@ -286,21 +285,21 @@ }; root_ccu: root_ccu@35001000 { - compatible = BCM21664_DT_ROOT_CCU_COMPAT; + compatible = "brcm,bcm21664-root-ccu"; reg = <0x35001000 0x0f00>; #clock-cells = <1>; clock-output-names = "frac_1m"; }; aon_ccu: aon_ccu@35002000 { - compatible = BCM21664_DT_AON_CCU_COMPAT; + compatible = "brcm,bcm21664-aon-ccu"; reg = <0x35002000 0x0f00>; #clock-cells = <1>; clock-output-names = "hub_timer"; }; master_ccu: master_ccu@3f001000 { - compatible = BCM21664_DT_MASTER_CCU_COMPAT; + compatible = "brcm,bcm21664-master-ccu"; reg = <0x3f001000 0x0f00>; #clock-cells = <1>; clock-output-names = "sdio1", @@ -314,7 +313,7 @@ }; slave_ccu: slave_ccu@3e011000 { - compatible = BCM21664_DT_SLAVE_CCU_COMPAT; + compatible = "brcm,bcm21664-slave-ccu"; reg = <0x3e011000 0x0f00>; #clock-cells = <1>; clock-output-names = "uartb", diff --git a/arch/arm/boot/dts/bcm23550-sparrow.dts b/arch/arm/boot/dts/broadcom/bcm23550-sparrow.dts similarity index 100% rename from arch/arm/boot/dts/bcm23550-sparrow.dts rename to arch/arm/boot/dts/broadcom/bcm23550-sparrow.dts diff --git a/arch/arm/boot/dts/bcm23550.dtsi b/arch/arm/boot/dts/broadcom/bcm23550.dtsi similarity index 95% rename from arch/arm/boot/dts/bcm23550.dtsi rename to arch/arm/boot/dts/broadcom/bcm23550.dtsi index a36c9b1d23c8eb6cc7633df18be6b32fa35838b9..445eadb8d871f84ca8613063b1d042e3b96f1851 100644 --- a/arch/arm/boot/dts/bcm23550.dtsi +++ b/arch/arm/boot/dts/broadcom/bcm23550.dtsi @@ -30,12 +30,11 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* BCM23550 and BCM21664 have almost identical clocks */ +#include #include #include -/* BCM23550 and BCM21664 have almost identical clocks */ -#include "dt-bindings/clock/bcm21664.h" - / { #address-cells = <1>; #size-cells = <1>; @@ -130,36 +129,36 @@ uartb: serial@0 { compatible = "snps,dw-apb-uart"; - status = "disabled"; reg = <0x00000000 0x118>; clocks = <&slave_ccu BCM21664_SLAVE_CCU_UARTB>; interrupts = ; reg-shift = <2>; reg-io-width = <4>; + status = "disabled"; }; uartb2: serial@1000 { compatible = "snps,dw-apb-uart"; - status = "disabled"; reg = <0x00001000 0x118>; clocks = <&slave_ccu BCM21664_SLAVE_CCU_UARTB2>; interrupts = ; reg-shift = <2>; reg-io-width = <4>; + status = "disabled"; }; uartb3: serial@2000 { compatible = "snps,dw-apb-uart"; - status = "disabled"; reg = <0x00002000 0x118>; clocks = <&slave_ccu BCM21664_SLAVE_CCU_UARTB3>; interrupts = ; reg-shift = <2>; reg-io-width = <4>; + status = "disabled"; }; bsc1: i2c@16000 { - compatible = "brcm,kona-i2c"; + compatible = "brcm,bcm23550-i2c", "brcm,kona-i2c"; reg = <0x00016000 0x70>; interrupts = ; #address-cells = <1>; @@ -169,7 +168,7 @@ }; bsc2: i2c@17000 { - compatible = "brcm,kona-i2c"; + compatible = "brcm,bcm23550-i2c", "brcm,kona-i2c"; reg = <0x00017000 0x70>; interrupts = ; #address-cells = <1>; @@ -179,7 +178,7 @@ }; bsc3: i2c@18000 { - compatible = "brcm,kona-i2c"; + compatible = "brcm,bcm23550-i2c", "brcm,kona-i2c"; reg = <0x00018000 0x70>; interrupts = ; #address-cells = <1>; @@ -189,7 +188,7 @@ }; bsc4: i2c@1c000 { - compatible = "brcm,kona-i2c"; + compatible = "brcm,bcm23550-i2c", "brcm,kona-i2c"; reg = <0x0001c000 0x70>; interrupts = ; #address-cells = <1>; @@ -224,7 +223,7 @@ status = "disabled"; }; - sdio1: sdio@e80000 { + sdio1: mmc@e80000 { compatible = "brcm,kona-sdhci"; reg = <0x00e80000 0x801c>; interrupts = ; @@ -232,7 +231,7 @@ status = "disabled"; }; - sdio2: sdio@e90000 { + sdio2: mmc@e90000 { compatible = "brcm,kona-sdhci"; reg = <0x00e90000 0x801c>; interrupts = ; @@ -240,7 +239,7 @@ status = "disabled"; }; - sdio3: sdio@ea0000 { + sdio3: mmc@ea0000 { compatible = "brcm,kona-sdhci"; reg = <0x00ea0000 0x801c>; interrupts = ; @@ -248,7 +247,7 @@ status = "disabled"; }; - sdio4: sdio@eb0000 { + sdio4: mmc@eb0000 { compatible = "brcm,kona-sdhci"; reg = <0x00eb0000 0x801c>; interrupts = ; @@ -372,21 +371,21 @@ }; root_ccu: root_ccu@35001000 { - compatible = BCM21664_DT_ROOT_CCU_COMPAT; + compatible = "brcm,bcm21664-root-ccu"; reg = <0x35001000 0x0f00>; #clock-cells = <1>; clock-output-names = "frac_1m"; }; aon_ccu: aon_ccu@35002000 { - compatible = BCM21664_DT_AON_CCU_COMPAT; + compatible = "brcm,bcm21664-aon-ccu"; reg = <0x35002000 0x0f00>; #clock-cells = <1>; clock-output-names = "hub_timer"; }; slave_ccu: slave_ccu@3e011000 { - compatible = BCM21664_DT_SLAVE_CCU_COMPAT; + compatible = "brcm,bcm21664-slave-ccu"; reg = <0x3e011000 0x0f00>; #clock-cells = <1>; clock-output-names = "uartb", @@ -399,7 +398,7 @@ }; master_ccu: master_ccu@3f001000 { - compatible = BCM21664_DT_MASTER_CCU_COMPAT; + compatible = "brcm,bcm21664-master-ccu"; reg = <0x3f001000 0x0f00>; #clock-cells = <1>; clock-output-names = "sdio1", diff --git a/arch/arm/boot/dts/bcm2711-rpi-4-b.dts b/arch/arm/boot/dts/broadcom/bcm2711-rpi-4-b.dts similarity index 100% rename from arch/arm/boot/dts/bcm2711-rpi-4-b.dts rename to arch/arm/boot/dts/broadcom/bcm2711-rpi-4-b.dts diff --git a/arch/arm/boot/dts/bcm2711-rpi-400.dts b/arch/arm/boot/dts/broadcom/bcm2711-rpi-400.dts similarity index 100% rename from arch/arm/boot/dts/bcm2711-rpi-400.dts rename to arch/arm/boot/dts/broadcom/bcm2711-rpi-400.dts diff --git a/arch/arm/boot/dts/bcm2711-rpi-cm4-io.dts b/arch/arm/boot/dts/broadcom/bcm2711-rpi-cm4-io.dts similarity index 100% rename from arch/arm/boot/dts/bcm2711-rpi-cm4-io.dts rename to arch/arm/boot/dts/broadcom/bcm2711-rpi-cm4-io.dts diff --git a/arch/arm/boot/dts/bcm2711-rpi-cm4.dtsi b/arch/arm/boot/dts/broadcom/bcm2711-rpi-cm4.dtsi similarity index 100% rename from arch/arm/boot/dts/bcm2711-rpi-cm4.dtsi rename to arch/arm/boot/dts/broadcom/bcm2711-rpi-cm4.dtsi diff --git a/arch/arm/boot/dts/bcm2711-rpi.dtsi b/arch/arm/boot/dts/broadcom/bcm2711-rpi.dtsi similarity index 100% rename from arch/arm/boot/dts/bcm2711-rpi.dtsi rename to arch/arm/boot/dts/broadcom/bcm2711-rpi.dtsi diff --git a/arch/arm/boot/dts/bcm2711.dtsi b/arch/arm/boot/dts/broadcom/bcm2711.dtsi similarity index 100% rename from arch/arm/boot/dts/bcm2711.dtsi rename to arch/arm/boot/dts/broadcom/bcm2711.dtsi diff --git a/arch/arm/boot/dts/bcm28155-ap.dts b/arch/arm/boot/dts/broadcom/bcm28155-ap.dts similarity index 97% rename from arch/arm/boot/dts/bcm28155-ap.dts rename to arch/arm/boot/dts/broadcom/bcm28155-ap.dts index 60c8ab8a28557063a565a1a4fc8325a298254064..0a8ad1d673d8573ae4e0300f7c1cda62735d7b5f 100644 --- a/arch/arm/boot/dts/bcm28155-ap.dts +++ b/arch/arm/boot/dts/broadcom/bcm28155-ap.dts @@ -21,30 +21,30 @@ }; i2c@3e016000 { - status = "okay"; clock-frequency = <400000>; + status = "okay"; }; i2c@3e017000 { - status = "okay"; clock-frequency = <400000>; + status = "okay"; }; i2c@3e018000 { - status = "okay"; clock-frequency = <400000>; + status = "okay"; }; i2c@3500d000 { - status = "okay"; clock-frequency = <100000>; + status = "okay"; pmu: pmu@8 { reg = <0x08>; }; }; - sdio2: sdio@3f190000 { + sdio2: mmc@3f190000 { non-removable; max-frequency = <48000000>; vmmc-supply = <&camldo1_reg>; @@ -52,7 +52,7 @@ status = "okay"; }; - sdio4: sdio@3f1b0000 { + sdio4: mmc@3f1b0000 { max-frequency = <48000000>; cd-gpios = <&gpio 14 GPIO_ACTIVE_LOW>; vmmc-supply = <&sdldo_reg>; diff --git a/arch/arm/boot/dts/bcm2835-common.dtsi b/arch/arm/boot/dts/broadcom/bcm2835-common.dtsi similarity index 100% rename from arch/arm/boot/dts/bcm2835-common.dtsi rename to arch/arm/boot/dts/broadcom/bcm2835-common.dtsi diff --git a/arch/arm/boot/dts/bcm2835-rpi-a-plus.dts b/arch/arm/boot/dts/broadcom/bcm2835-rpi-a-plus.dts similarity index 100% rename from arch/arm/boot/dts/bcm2835-rpi-a-plus.dts rename to arch/arm/boot/dts/broadcom/bcm2835-rpi-a-plus.dts diff --git a/arch/arm/boot/dts/bcm2835-rpi-a.dts b/arch/arm/boot/dts/broadcom/bcm2835-rpi-a.dts similarity index 100% rename from arch/arm/boot/dts/bcm2835-rpi-a.dts rename to arch/arm/boot/dts/broadcom/bcm2835-rpi-a.dts diff --git a/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts b/arch/arm/boot/dts/broadcom/bcm2835-rpi-b-plus.dts similarity index 100% rename from arch/arm/boot/dts/bcm2835-rpi-b-plus.dts rename to arch/arm/boot/dts/broadcom/bcm2835-rpi-b-plus.dts diff --git a/arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts b/arch/arm/boot/dts/broadcom/bcm2835-rpi-b-rev2.dts similarity index 100% rename from arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts rename to arch/arm/boot/dts/broadcom/bcm2835-rpi-b-rev2.dts diff --git a/arch/arm/boot/dts/bcm2835-rpi-b.dts b/arch/arm/boot/dts/broadcom/bcm2835-rpi-b.dts similarity index 100% rename from arch/arm/boot/dts/bcm2835-rpi-b.dts rename to arch/arm/boot/dts/broadcom/bcm2835-rpi-b.dts diff --git a/arch/arm/boot/dts/bcm2835-rpi-cm1-io1.dts b/arch/arm/boot/dts/broadcom/bcm2835-rpi-cm1-io1.dts similarity index 100% rename from arch/arm/boot/dts/bcm2835-rpi-cm1-io1.dts rename to arch/arm/boot/dts/broadcom/bcm2835-rpi-cm1-io1.dts diff --git a/arch/arm/boot/dts/bcm2835-rpi-cm1.dtsi b/arch/arm/boot/dts/broadcom/bcm2835-rpi-cm1.dtsi similarity index 100% rename from arch/arm/boot/dts/bcm2835-rpi-cm1.dtsi rename to arch/arm/boot/dts/broadcom/bcm2835-rpi-cm1.dtsi diff --git a/arch/arm/boot/dts/bcm2835-rpi-common.dtsi b/arch/arm/boot/dts/broadcom/bcm2835-rpi-common.dtsi similarity index 100% rename from arch/arm/boot/dts/bcm2835-rpi-common.dtsi rename to arch/arm/boot/dts/broadcom/bcm2835-rpi-common.dtsi diff --git a/arch/arm/boot/dts/bcm2835-rpi-zero-w.dts b/arch/arm/boot/dts/broadcom/bcm2835-rpi-zero-w.dts similarity index 100% rename from arch/arm/boot/dts/bcm2835-rpi-zero-w.dts rename to arch/arm/boot/dts/broadcom/bcm2835-rpi-zero-w.dts diff --git a/arch/arm/boot/dts/bcm2835-rpi-zero.dts b/arch/arm/boot/dts/broadcom/bcm2835-rpi-zero.dts similarity index 100% rename from arch/arm/boot/dts/bcm2835-rpi-zero.dts rename to arch/arm/boot/dts/broadcom/bcm2835-rpi-zero.dts diff --git a/arch/arm/boot/dts/bcm2835-rpi.dtsi b/arch/arm/boot/dts/broadcom/bcm2835-rpi.dtsi similarity index 100% rename from arch/arm/boot/dts/bcm2835-rpi.dtsi rename to arch/arm/boot/dts/broadcom/bcm2835-rpi.dtsi diff --git a/arch/arm/boot/dts/bcm2835.dtsi b/arch/arm/boot/dts/broadcom/bcm2835.dtsi similarity index 100% rename from arch/arm/boot/dts/bcm2835.dtsi rename to arch/arm/boot/dts/broadcom/bcm2835.dtsi diff --git a/arch/arm/boot/dts/bcm2836-rpi-2-b.dts b/arch/arm/boot/dts/broadcom/bcm2836-rpi-2-b.dts similarity index 100% rename from arch/arm/boot/dts/bcm2836-rpi-2-b.dts rename to arch/arm/boot/dts/broadcom/bcm2836-rpi-2-b.dts diff --git a/arch/arm/boot/dts/bcm2836-rpi.dtsi b/arch/arm/boot/dts/broadcom/bcm2836-rpi.dtsi similarity index 100% rename from arch/arm/boot/dts/bcm2836-rpi.dtsi rename to arch/arm/boot/dts/broadcom/bcm2836-rpi.dtsi diff --git a/arch/arm/boot/dts/bcm2836.dtsi b/arch/arm/boot/dts/broadcom/bcm2836.dtsi similarity index 100% rename from arch/arm/boot/dts/bcm2836.dtsi rename to arch/arm/boot/dts/broadcom/bcm2836.dtsi diff --git a/arch/arm/boot/dts/bcm2837-rpi-3-a-plus.dts b/arch/arm/boot/dts/broadcom/bcm2837-rpi-3-a-plus.dts similarity index 100% rename from arch/arm/boot/dts/bcm2837-rpi-3-a-plus.dts rename to arch/arm/boot/dts/broadcom/bcm2837-rpi-3-a-plus.dts diff --git a/arch/arm/boot/dts/bcm2837-rpi-3-b-plus.dts b/arch/arm/boot/dts/broadcom/bcm2837-rpi-3-b-plus.dts similarity index 100% rename from arch/arm/boot/dts/bcm2837-rpi-3-b-plus.dts rename to arch/arm/boot/dts/broadcom/bcm2837-rpi-3-b-plus.dts diff --git a/arch/arm/boot/dts/bcm2837-rpi-3-b.dts b/arch/arm/boot/dts/broadcom/bcm2837-rpi-3-b.dts similarity index 100% rename from arch/arm/boot/dts/bcm2837-rpi-3-b.dts rename to arch/arm/boot/dts/broadcom/bcm2837-rpi-3-b.dts diff --git a/arch/arm/boot/dts/bcm2837-rpi-cm3-io3.dts b/arch/arm/boot/dts/broadcom/bcm2837-rpi-cm3-io3.dts similarity index 100% rename from arch/arm/boot/dts/bcm2837-rpi-cm3-io3.dts rename to arch/arm/boot/dts/broadcom/bcm2837-rpi-cm3-io3.dts diff --git a/arch/arm/boot/dts/bcm2837-rpi-cm3.dtsi b/arch/arm/boot/dts/broadcom/bcm2837-rpi-cm3.dtsi similarity index 100% rename from arch/arm/boot/dts/bcm2837-rpi-cm3.dtsi rename to arch/arm/boot/dts/broadcom/bcm2837-rpi-cm3.dtsi diff --git a/arch/arm/boot/dts/bcm2837-rpi-zero-2-w.dts b/arch/arm/boot/dts/broadcom/bcm2837-rpi-zero-2-w.dts similarity index 100% rename from arch/arm/boot/dts/bcm2837-rpi-zero-2-w.dts rename to arch/arm/boot/dts/broadcom/bcm2837-rpi-zero-2-w.dts diff --git a/arch/arm/boot/dts/bcm2837.dtsi b/arch/arm/boot/dts/broadcom/bcm2837.dtsi similarity index 100% rename from arch/arm/boot/dts/bcm2837.dtsi rename to arch/arm/boot/dts/broadcom/bcm2837.dtsi diff --git a/arch/arm/boot/dts/bcm283x-rpi-lan7515.dtsi b/arch/arm/boot/dts/broadcom/bcm283x-rpi-lan7515.dtsi similarity index 100% rename from arch/arm/boot/dts/bcm283x-rpi-lan7515.dtsi rename to arch/arm/boot/dts/broadcom/bcm283x-rpi-lan7515.dtsi diff --git a/arch/arm/boot/dts/bcm283x-rpi-led-deprecated.dtsi b/arch/arm/boot/dts/broadcom/bcm283x-rpi-led-deprecated.dtsi similarity index 100% rename from arch/arm/boot/dts/bcm283x-rpi-led-deprecated.dtsi rename to arch/arm/boot/dts/broadcom/bcm283x-rpi-led-deprecated.dtsi diff --git a/arch/arm/boot/dts/bcm283x-rpi-smsc9512.dtsi b/arch/arm/boot/dts/broadcom/bcm283x-rpi-smsc9512.dtsi similarity index 100% rename from arch/arm/boot/dts/bcm283x-rpi-smsc9512.dtsi rename to arch/arm/boot/dts/broadcom/bcm283x-rpi-smsc9512.dtsi diff --git a/arch/arm/boot/dts/bcm283x-rpi-smsc9514.dtsi b/arch/arm/boot/dts/broadcom/bcm283x-rpi-smsc9514.dtsi similarity index 100% rename from arch/arm/boot/dts/bcm283x-rpi-smsc9514.dtsi rename to arch/arm/boot/dts/broadcom/bcm283x-rpi-smsc9514.dtsi diff --git a/arch/arm/boot/dts/bcm283x-rpi-usb-host.dtsi b/arch/arm/boot/dts/broadcom/bcm283x-rpi-usb-host.dtsi similarity index 100% rename from arch/arm/boot/dts/bcm283x-rpi-usb-host.dtsi rename to arch/arm/boot/dts/broadcom/bcm283x-rpi-usb-host.dtsi diff --git a/arch/arm/boot/dts/bcm283x-rpi-usb-otg.dtsi b/arch/arm/boot/dts/broadcom/bcm283x-rpi-usb-otg.dtsi similarity index 100% rename from arch/arm/boot/dts/bcm283x-rpi-usb-otg.dtsi rename to arch/arm/boot/dts/broadcom/bcm283x-rpi-usb-otg.dtsi diff --git a/arch/arm/boot/dts/bcm283x-rpi-usb-peripheral.dtsi b/arch/arm/boot/dts/broadcom/bcm283x-rpi-usb-peripheral.dtsi similarity index 100% rename from arch/arm/boot/dts/bcm283x-rpi-usb-peripheral.dtsi rename to arch/arm/boot/dts/broadcom/bcm283x-rpi-usb-peripheral.dtsi diff --git a/arch/arm/boot/dts/bcm283x-rpi-wifi-bt.dtsi b/arch/arm/boot/dts/broadcom/bcm283x-rpi-wifi-bt.dtsi similarity index 100% rename from arch/arm/boot/dts/bcm283x-rpi-wifi-bt.dtsi rename to arch/arm/boot/dts/broadcom/bcm283x-rpi-wifi-bt.dtsi diff --git a/arch/arm/boot/dts/bcm283x.dtsi b/arch/arm/boot/dts/broadcom/bcm283x.dtsi similarity index 100% rename from arch/arm/boot/dts/bcm283x.dtsi rename to arch/arm/boot/dts/broadcom/bcm283x.dtsi diff --git a/arch/arm/boot/dts/bcm4708-asus-rt-ac56u.dts b/arch/arm/boot/dts/broadcom/bcm4708-asus-rt-ac56u.dts similarity index 100% rename from arch/arm/boot/dts/bcm4708-asus-rt-ac56u.dts rename to arch/arm/boot/dts/broadcom/bcm4708-asus-rt-ac56u.dts diff --git a/arch/arm/boot/dts/bcm4708-asus-rt-ac68u.dts b/arch/arm/boot/dts/broadcom/bcm4708-asus-rt-ac68u.dts similarity index 100% rename from arch/arm/boot/dts/bcm4708-asus-rt-ac68u.dts rename to arch/arm/boot/dts/broadcom/bcm4708-asus-rt-ac68u.dts diff --git a/arch/arm/boot/dts/bcm4708-buffalo-wzr-1166dhp-common.dtsi b/arch/arm/boot/dts/broadcom/bcm4708-buffalo-wzr-1166dhp-common.dtsi similarity index 95% rename from arch/arm/boot/dts/bcm4708-buffalo-wzr-1166dhp-common.dtsi rename to arch/arm/boot/dts/broadcom/bcm4708-buffalo-wzr-1166dhp-common.dtsi index e583b9cbf07c0f8d1935bbd2c644ba1f92d1b2cd..42bcbf10957c408b48365d2b5a388db39051f542 100644 --- a/arch/arm/boot/dts/bcm4708-buffalo-wzr-1166dhp-common.dtsi +++ b/arch/arm/boot/dts/broadcom/bcm4708-buffalo-wzr-1166dhp-common.dtsi @@ -16,8 +16,8 @@ spi { compatible = "spi-gpio"; num-chipselects = <1>; - gpio-sck = <&chipcommon 7 0>; - gpio-mosi = <&chipcommon 4 0>; + sck-gpios = <&chipcommon 7 0>; + mosi-gpios = <&chipcommon 4 0>; cs-gpios = <&chipcommon 6 0>; #address-cells = <1>; #size-cells = <0>; @@ -159,34 +159,27 @@ ports { port@0 { - reg = <0>; label = "lan1"; }; port@1 { - reg = <1>; label = "lan2"; }; port@2 { - reg = <2>; label = "lan3"; }; port@3 { - reg = <3>; label = "lan4"; }; port@4 { - reg = <4>; label = "wan"; }; port@5 { - reg = <5>; label = "cpu"; - ethernet = <&gmac0>; }; }; }; diff --git a/arch/arm/boot/dts/bcm4708-buffalo-wzr-1166dhp.dts b/arch/arm/boot/dts/broadcom/bcm4708-buffalo-wzr-1166dhp.dts similarity index 100% rename from arch/arm/boot/dts/bcm4708-buffalo-wzr-1166dhp.dts rename to arch/arm/boot/dts/broadcom/bcm4708-buffalo-wzr-1166dhp.dts diff --git a/arch/arm/boot/dts/bcm4708-buffalo-wzr-1166dhp2.dts b/arch/arm/boot/dts/broadcom/bcm4708-buffalo-wzr-1166dhp2.dts similarity index 100% rename from arch/arm/boot/dts/bcm4708-buffalo-wzr-1166dhp2.dts rename to arch/arm/boot/dts/broadcom/bcm4708-buffalo-wzr-1166dhp2.dts diff --git a/arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts b/arch/arm/boot/dts/broadcom/bcm4708-buffalo-wzr-1750dhp.dts similarity index 97% rename from arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts rename to arch/arm/boot/dts/broadcom/bcm4708-buffalo-wzr-1750dhp.dts index 43c698a0a7c390dca51dc65ec21986c25e0c0771..95ef6ca7210b34fe521ed877607ea2277af0129e 100644 --- a/arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts +++ b/arch/arm/boot/dts/broadcom/bcm4708-buffalo-wzr-1750dhp.dts @@ -28,8 +28,8 @@ spi { compatible = "spi-gpio"; num-chipselects = <1>; - gpio-sck = <&chipcommon 7 0>; - gpio-mosi = <&chipcommon 4 0>; + sck-gpios = <&chipcommon 7 0>; + mosi-gpios = <&chipcommon 4 0>; cs-gpios = <&chipcommon 6 0>; #address-cells = <1>; #size-cells = <0>; diff --git a/arch/arm/boot/dts/bcm4708-linksys-ea6300-v1.dts b/arch/arm/boot/dts/broadcom/bcm4708-linksys-ea6300-v1.dts similarity index 100% rename from arch/arm/boot/dts/bcm4708-linksys-ea6300-v1.dts rename to arch/arm/boot/dts/broadcom/bcm4708-linksys-ea6300-v1.dts diff --git a/arch/arm/boot/dts/bcm4708-linksys-ea6500-v2.dts b/arch/arm/boot/dts/broadcom/bcm4708-linksys-ea6500-v2.dts similarity index 100% rename from arch/arm/boot/dts/bcm4708-linksys-ea6500-v2.dts rename to arch/arm/boot/dts/broadcom/bcm4708-linksys-ea6500-v2.dts diff --git a/arch/arm/boot/dts/bcm4708-luxul-xap-1510.dts b/arch/arm/boot/dts/broadcom/bcm4708-luxul-xap-1510.dts similarity index 81% rename from arch/arm/boot/dts/bcm4708-luxul-xap-1510.dts rename to arch/arm/boot/dts/broadcom/bcm4708-luxul-xap-1510.dts index 6de7fe204b0c030eaec623280c12cad1fd613ccb..e04d2e5ea51aa479569baddd2a9d1ec8be2cd738 100644 --- a/arch/arm/boot/dts/bcm4708-luxul-xap-1510.dts +++ b/arch/arm/boot/dts/broadcom/bcm4708-luxul-xap-1510.dts @@ -8,7 +8,7 @@ #include "bcm4708.dtsi" / { - compatible = "luxul,xap-1510v1", "brcm,bcm4708"; + compatible = "luxul,xap-1510-v1", "brcm,bcm4708"; model = "Luxul XAP-1510 V1"; chosen { @@ -20,6 +20,14 @@ reg = <0x00000000 0x08000000>; }; + nvram@1eff0000 { + compatible = "brcm,nvram"; + reg = <0x1eff0000 0x10000>; + + et0macaddr: et0macaddr { + }; + }; + leds { compatible = "gpio-leds"; @@ -53,6 +61,11 @@ }; }; +&gmac0 { + nvmem-cells = <&et0macaddr>; + nvmem-cell-names = "mac-address"; +}; + &spi_nor { status = "okay"; }; @@ -62,19 +75,15 @@ ports { port@0 { - reg = <0>; label = "poe"; }; port@4 { - reg = <4>; label = "lan"; }; port@5 { - reg = <5>; label = "cpu"; - ethernet = <&gmac0>; }; }; }; diff --git a/arch/arm/boot/dts/bcm4708-luxul-xwc-1000.dts b/arch/arm/boot/dts/broadcom/bcm4708-luxul-xwc-1000.dts similarity index 86% rename from arch/arm/boot/dts/bcm4708-luxul-xwc-1000.dts rename to arch/arm/boot/dts/broadcom/bcm4708-luxul-xwc-1000.dts index f5b75ba93512469f6920ded0f6a43623473e805b..a399800139d9ce9c8f90fdfd26321eeee88606e2 100644 --- a/arch/arm/boot/dts/bcm4708-luxul-xwc-1000.dts +++ b/arch/arm/boot/dts/broadcom/bcm4708-luxul-xwc-1000.dts @@ -24,6 +24,14 @@ reg = <0x00000000 0x08000000>; }; + nvram@1eff0000 { + compatible = "brcm,nvram"; + reg = <0x1eff0000 0x10000>; + + et0macaddr: et0macaddr { + }; + }; + nand_controller: nand-controller@18028000 { nand@0 { partitions { @@ -60,6 +68,11 @@ }; }; +&gmac0 { + nvmem-cells = <&et0macaddr>; + nvmem-cell-names = "mac-address"; +}; + &spi_nor { status = "okay"; }; @@ -69,14 +82,11 @@ ports { port@4 { - reg = <4>; label = "lan"; }; port@5 { - reg = <5>; label = "cpu"; - ethernet = <&gmac0>; }; }; }; diff --git a/arch/arm/boot/dts/bcm4708-netgear-r6250.dts b/arch/arm/boot/dts/broadcom/bcm4708-netgear-r6250.dts similarity index 92% rename from arch/arm/boot/dts/bcm4708-netgear-r6250.dts rename to arch/arm/boot/dts/broadcom/bcm4708-netgear-r6250.dts index 89155caf50bef71a9ec14afedffce9170cb50ea9..fad3473810a2e58d471339c69d1cf9c32bc26227 100644 --- a/arch/arm/boot/dts/bcm4708-netgear-r6250.dts +++ b/arch/arm/boot/dts/broadcom/bcm4708-netgear-r6250.dts @@ -13,7 +13,7 @@ #include "bcm5301x-nand-cs0-bch8.dtsi" / { - compatible = "netgear,r6250v1", "brcm,bcm4708"; + compatible = "netgear,r6250-v1", "brcm,bcm4708"; model = "Netgear R6250 V1 (BCM4708)"; chosen { @@ -100,34 +100,27 @@ ports { port@0 { - reg = <0>; label = "lan4"; }; port@1 { - reg = <1>; label = "lan3"; }; port@2 { - reg = <2>; label = "lan2"; }; port@3 { - reg = <3>; label = "lan1"; }; port@4 { - reg = <4>; label = "wan"; }; port@5 { - reg = <5>; label = "cpu"; - ethernet = <&gmac0>; }; }; }; diff --git a/arch/arm/boot/dts/bcm4708-netgear-r6300-v2.dts b/arch/arm/boot/dts/broadcom/bcm4708-netgear-r6300-v2.dts similarity index 96% rename from arch/arm/boot/dts/bcm4708-netgear-r6300-v2.dts rename to arch/arm/boot/dts/broadcom/bcm4708-netgear-r6300-v2.dts index 57d00a0b4765a44bf09fc6fc8541e8186d9886e1..77396730bdd3e4fb4f4b6fe9c6cf2836a7a57031 100644 --- a/arch/arm/boot/dts/bcm4708-netgear-r6300-v2.dts +++ b/arch/arm/boot/dts/broadcom/bcm4708-netgear-r6300-v2.dts @@ -12,7 +12,7 @@ #include "bcm5301x-nand-cs0-bch8.dtsi" / { - compatible = "netgear,r6300v2", "brcm,bcm4708"; + compatible = "netgear,r6300-v2", "brcm,bcm4708"; model = "Netgear R6300 V2 (BCM4708)"; chosen { diff --git a/arch/arm/boot/dts/bcm4708-smartrg-sr400ac.dts b/arch/arm/boot/dts/broadcom/bcm4708-smartrg-sr400ac.dts similarity index 96% rename from arch/arm/boot/dts/bcm4708-smartrg-sr400ac.dts rename to arch/arm/boot/dts/broadcom/bcm4708-smartrg-sr400ac.dts index 26cdeb5cc33773b796a55e408730a99dcdd739bb..5b2b7b8b3b123f5d864f4f2176cd6424eb9f56ad 100644 --- a/arch/arm/boot/dts/bcm4708-smartrg-sr400ac.dts +++ b/arch/arm/boot/dts/broadcom/bcm4708-smartrg-sr400ac.dts @@ -123,34 +123,27 @@ ports { port@0 { - reg = <0>; label = "lan4"; }; port@1 { - reg = <1>; label = "lan3"; }; port@2 { - reg = <2>; label = "lan2"; }; port@3 { - reg = <3>; label = "lan1"; }; port@4 { - reg = <4>; label = "wan"; }; port@5 { - reg = <5>; label = "cpu"; - ethernet = <&gmac0>; }; }; }; diff --git a/arch/arm/boot/dts/bcm4708.dtsi b/arch/arm/boot/dts/broadcom/bcm4708.dtsi similarity index 100% rename from arch/arm/boot/dts/bcm4708.dtsi rename to arch/arm/boot/dts/broadcom/bcm4708.dtsi diff --git a/arch/arm/boot/dts/bcm47081-asus-rt-n18u.dts b/arch/arm/boot/dts/broadcom/bcm47081-asus-rt-n18u.dts similarity index 100% rename from arch/arm/boot/dts/bcm47081-asus-rt-n18u.dts rename to arch/arm/boot/dts/broadcom/bcm47081-asus-rt-n18u.dts diff --git a/arch/arm/boot/dts/bcm47081-buffalo-wzr-600dhp2.dts b/arch/arm/boot/dts/broadcom/bcm47081-buffalo-wzr-600dhp2.dts similarity index 93% rename from arch/arm/boot/dts/bcm47081-buffalo-wzr-600dhp2.dts rename to arch/arm/boot/dts/broadcom/bcm47081-buffalo-wzr-600dhp2.dts index 407319cb5c0dd7e99d436fcc86e64ed034a61e45..d0a26b643b82feb7c6672b89472dc8a88ea412e4 100644 --- a/arch/arm/boot/dts/bcm47081-buffalo-wzr-600dhp2.dts +++ b/arch/arm/boot/dts/broadcom/bcm47081-buffalo-wzr-600dhp2.dts @@ -28,8 +28,8 @@ spi { compatible = "spi-gpio"; num-chipselects = <1>; - gpio-sck = <&chipcommon 7 0>; - gpio-mosi = <&chipcommon 4 0>; + sck-gpios = <&chipcommon 7 0>; + mosi-gpios = <&chipcommon 4 0>; cs-gpios = <&chipcommon 6 0>; #address-cells = <1>; #size-cells = <0>; @@ -123,34 +123,27 @@ ports { port@0 { - reg = <0>; label = "lan1"; }; port@1 { - reg = <1>; label = "lan2"; }; port@2 { - reg = <2>; label = "lan3"; }; port@3 { - reg = <3>; label = "lan4"; }; port@4 { - reg = <4>; label = "wan"; }; port@5 { - reg = <5>; label = "cpu"; - ethernet = <&gmac0>; }; }; }; diff --git a/arch/arm/boot/dts/bcm47081-buffalo-wzr-900dhp.dts b/arch/arm/boot/dts/broadcom/bcm47081-buffalo-wzr-900dhp.dts similarity index 96% rename from arch/arm/boot/dts/bcm47081-buffalo-wzr-900dhp.dts rename to arch/arm/boot/dts/broadcom/bcm47081-buffalo-wzr-900dhp.dts index f8622ecce6a2b36c991809cd07a89f16a4c58604..7655e4ff2d1cca90579ba35fa713c64aad97df0c 100644 --- a/arch/arm/boot/dts/bcm47081-buffalo-wzr-900dhp.dts +++ b/arch/arm/boot/dts/broadcom/bcm47081-buffalo-wzr-900dhp.dts @@ -28,8 +28,8 @@ spi { compatible = "spi-gpio"; num-chipselects = <1>; - gpio-sck = <&chipcommon 7 0>; - gpio-mosi = <&chipcommon 4 0>; + sck-gpios = <&chipcommon 7 0>; + mosi-gpios = <&chipcommon 4 0>; cs-gpios = <&chipcommon 6 0>; #address-cells = <1>; #size-cells = <0>; diff --git a/arch/arm/boot/dts/bcm47081-luxul-xap-1410.dts b/arch/arm/boot/dts/broadcom/bcm47081-luxul-xap-1410.dts similarity index 80% rename from arch/arm/boot/dts/bcm47081-luxul-xap-1410.dts rename to arch/arm/boot/dts/broadcom/bcm47081-luxul-xap-1410.dts index 76c9b30b868d40e7711f388aaab47acedb28f806..9f21d6d6d35b7599cb96325ab4f40d7f6e97c1c9 100644 --- a/arch/arm/boot/dts/bcm47081-luxul-xap-1410.dts +++ b/arch/arm/boot/dts/broadcom/bcm47081-luxul-xap-1410.dts @@ -8,7 +8,7 @@ #include "bcm47081.dtsi" / { - compatible = "luxul,xap-1410v1", "brcm,bcm47081", "brcm,bcm4708"; + compatible = "luxul,xap-1410-v1", "brcm,bcm47081", "brcm,bcm4708"; model = "Luxul XAP-1410 V1"; chosen { @@ -20,6 +20,14 @@ reg = <0x00000000 0x08000000>; }; + nvram@1eff0000 { + compatible = "brcm,nvram"; + reg = <0x1eff0000 0x10000>; + + et0macaddr: et0macaddr { + }; + }; + leds { compatible = "gpio-leds"; @@ -53,6 +61,11 @@ }; }; +&gmac0 { + nvmem-cells = <&et0macaddr>; + nvmem-cell-names = "mac-address"; +}; + &spi_nor { status = "okay"; }; @@ -62,14 +75,11 @@ ports { port@4 { - reg = <4>; label = "poe"; }; port@5 { - reg = <5>; label = "cpu"; - ethernet = <&gmac0>; }; }; }; diff --git a/arch/arm/boot/dts/bcm47081-luxul-xwr-1200.dts b/arch/arm/boot/dts/broadcom/bcm47081-luxul-xwr-1200.dts similarity index 89% rename from arch/arm/boot/dts/bcm47081-luxul-xwr-1200.dts rename to arch/arm/boot/dts/broadcom/bcm47081-luxul-xwr-1200.dts index 6ef0c0788e625c36c4eb34a45f9bdb208d7f50f2..2561072917021cb8efd479710ea1090544c10c47 100644 --- a/arch/arm/boot/dts/bcm47081-luxul-xwr-1200.dts +++ b/arch/arm/boot/dts/broadcom/bcm47081-luxul-xwr-1200.dts @@ -9,7 +9,7 @@ #include "bcm5301x-nand-cs0-bch4.dtsi" / { - compatible = "luxul,xwr-1200v1", "brcm,bcm47081", "brcm,bcm4708"; + compatible = "luxul,xwr-1200-v1", "brcm,bcm47081", "brcm,bcm4708"; model = "Luxul XWR-1200 V1"; chosen { @@ -24,6 +24,10 @@ nvram@1eff0000 { compatible = "brcm,nvram"; reg = <0x1eff0000 0x10000>; + + et0macaddr: et0macaddr { + #nvmem-cell-cells = <1>; + }; }; leds { @@ -106,6 +110,11 @@ vcc-gpio = <&chipcommon 9 GPIO_ACTIVE_HIGH>; }; +&gmac0 { + nvmem-cells = <&et0macaddr 0>; + nvmem-cell-names = "mac-address"; +}; + &spi_nor { status = "okay"; }; @@ -115,34 +124,29 @@ ports { port@0 { - reg = <0>; label = "lan4"; }; port@1 { - reg = <1>; label = "lan3"; }; port@2 { - reg = <2>; label = "lan2"; }; port@3 { - reg = <3>; label = "lan1"; }; port@4 { - reg = <4>; label = "wan"; + nvmem-cells = <&et0macaddr 5>; + nvmem-cell-names = "mac-address"; }; port@5 { - reg = <5>; label = "cpu"; - ethernet = <&gmac0>; }; }; }; diff --git a/arch/arm/boot/dts/bcm47081-tplink-archer-c5-v2.dts b/arch/arm/boot/dts/broadcom/bcm47081-tplink-archer-c5-v2.dts similarity index 100% rename from arch/arm/boot/dts/bcm47081-tplink-archer-c5-v2.dts rename to arch/arm/boot/dts/broadcom/bcm47081-tplink-archer-c5-v2.dts diff --git a/arch/arm/boot/dts/bcm47081.dtsi b/arch/arm/boot/dts/broadcom/bcm47081.dtsi similarity index 100% rename from arch/arm/boot/dts/bcm47081.dtsi rename to arch/arm/boot/dts/broadcom/bcm47081.dtsi diff --git a/arch/arm/boot/dts/bcm4709-asus-rt-ac87u.dts b/arch/arm/boot/dts/broadcom/bcm4709-asus-rt-ac87u.dts similarity index 100% rename from arch/arm/boot/dts/bcm4709-asus-rt-ac87u.dts rename to arch/arm/boot/dts/broadcom/bcm4709-asus-rt-ac87u.dts diff --git a/arch/arm/boot/dts/bcm4709-buffalo-wxr-1900dhp.dts b/arch/arm/boot/dts/broadcom/bcm4709-buffalo-wxr-1900dhp.dts similarity index 100% rename from arch/arm/boot/dts/bcm4709-buffalo-wxr-1900dhp.dts rename to arch/arm/boot/dts/broadcom/bcm4709-buffalo-wxr-1900dhp.dts diff --git a/arch/arm/boot/dts/bcm4709-linksys-ea9200.dts b/arch/arm/boot/dts/broadcom/bcm4709-linksys-ea9200.dts similarity index 100% rename from arch/arm/boot/dts/bcm4709-linksys-ea9200.dts rename to arch/arm/boot/dts/broadcom/bcm4709-linksys-ea9200.dts diff --git a/arch/arm/boot/dts/bcm4709-netgear-r7000.dts b/arch/arm/boot/dts/broadcom/bcm4709-netgear-r7000.dts similarity index 100% rename from arch/arm/boot/dts/bcm4709-netgear-r7000.dts rename to arch/arm/boot/dts/broadcom/bcm4709-netgear-r7000.dts diff --git a/arch/arm/boot/dts/bcm4709-netgear-r8000.dts b/arch/arm/boot/dts/broadcom/bcm4709-netgear-r8000.dts similarity index 89% rename from arch/arm/boot/dts/bcm4709-netgear-r8000.dts rename to arch/arm/boot/dts/broadcom/bcm4709-netgear-r8000.dts index 14303ab521ea49cf446aa31e24dddaa40738b02b..707c561703ed81bc8055795b264b9a7261151ba1 100644 --- a/arch/arm/boot/dts/bcm4709-netgear-r8000.dts +++ b/arch/arm/boot/dts/broadcom/bcm4709-netgear-r8000.dts @@ -137,8 +137,10 @@ #size-cells = <2>; wifi@0,1,0 { + compatible = "brcm,bcm4366-fmac", "brcm,bcm4329-fmac"; reg = <0x0000 0 0 0 0>; ieee80211-freq-limit = <5735000 5835000>; + brcm,ccode-map = "JP-JP-78", "US-Q2-86"; }; }; }; @@ -159,6 +161,19 @@ #address-cells = <3>; #size-cells = <2>; + bridge@1,0 { + reg = <0x800 0 0 0 0>; + + #address-cells = <3>; + #size-cells = <2>; + + wifi@0,0 { + compatible = "brcm,bcm4366-fmac", "brcm,bcm4329-fmac"; + reg = <0x0000 0 0 0 0>; + brcm,ccode-map = "JP-JP-78", "US-Q2-86"; + }; + }; + bridge@1,2,2 { reg = <0x1000 0 0 0 0>; @@ -166,8 +181,10 @@ #size-cells = <2>; wifi@1,4,0 { + compatible = "brcm,bcm4366-fmac", "brcm,bcm4329-fmac"; reg = <0x0000 0 0 0 0>; ieee80211-freq-limit = <5170000 5730000>; + brcm,ccode-map = "JP-JP-78", "US-Q2-86"; }; }; }; @@ -191,39 +208,27 @@ ports { port@0 { - reg = <0>; label = "lan1"; }; port@1 { - reg = <1>; label = "lan2"; }; port@2 { - reg = <2>; label = "lan3"; }; port@3 { - reg = <3>; label = "lan4"; }; port@4 { - reg = <4>; label = "wan"; }; port@8 { - reg = <8>; label = "cpu"; - ethernet = <&gmac2>; - - fixed-link { - speed = <1000>; - full-duplex; - }; }; }; }; diff --git a/arch/arm/boot/dts/bcm4709-tplink-archer-c9-v1.dts b/arch/arm/boot/dts/broadcom/bcm4709-tplink-archer-c9-v1.dts similarity index 100% rename from arch/arm/boot/dts/bcm4709-tplink-archer-c9-v1.dts rename to arch/arm/boot/dts/broadcom/bcm4709-tplink-archer-c9-v1.dts diff --git a/arch/arm/boot/dts/bcm4709.dtsi b/arch/arm/boot/dts/broadcom/bcm4709.dtsi similarity index 100% rename from arch/arm/boot/dts/bcm4709.dtsi rename to arch/arm/boot/dts/broadcom/bcm4709.dtsi diff --git a/arch/arm/boot/dts/bcm47094-asus-rt-ac88u.dts b/arch/arm/boot/dts/broadcom/bcm47094-asus-rt-ac88u.dts similarity index 95% rename from arch/arm/boot/dts/bcm47094-asus-rt-ac88u.dts rename to arch/arm/boot/dts/broadcom/bcm47094-asus-rt-ac88u.dts index a50ff686b557edb39df1f5c2c3da2d3c9a21e128..4d5747aa5dc828df123e42468733c2e3fea6f374 100644 --- a/arch/arm/boot/dts/bcm47094-asus-rt-ac88u.dts +++ b/arch/arm/boot/dts/broadcom/bcm47094-asus-rt-ac88u.dts @@ -181,32 +181,28 @@ ports { port@0 { - reg = <0>; label = "lan4"; }; port@1 { - reg = <1>; label = "lan3"; }; port@2 { - reg = <2>; label = "lan2"; }; port@3 { - reg = <3>; label = "lan1"; }; port@4 { - reg = <4>; label = "wan"; }; sw0_p5: port@5 { - reg = <5>; + /delete-property/ethernet; + label = "extsw"; phy-mode = "rgmii"; @@ -218,8 +214,6 @@ }; port@7 { - reg = <7>; - ethernet = <&gmac1>; label = "cpu"; fixed-link { @@ -229,14 +223,7 @@ }; port@8 { - reg = <8>; - ethernet = <&gmac2>; label = "cpu"; - - fixed-link { - speed = <1000>; - full-duplex; - }; }; }; }; diff --git a/arch/arm/boot/dts/bcm47094-dlink-dir-885l.dts b/arch/arm/boot/dts/broadcom/bcm47094-dlink-dir-885l.dts similarity index 93% rename from arch/arm/boot/dts/bcm47094-dlink-dir-885l.dts rename to arch/arm/boot/dts/broadcom/bcm47094-dlink-dir-885l.dts index 555fbe41dd8fe551490e364ef9a7c0a2c9604a23..51ce510b3e3a0147ccd71bdcf47f350cdea02b15 100644 --- a/arch/arm/boot/dts/bcm47094-dlink-dir-885l.dts +++ b/arch/arm/boot/dts/broadcom/bcm47094-dlink-dir-885l.dts @@ -124,39 +124,27 @@ ports { port@0 { - reg = <0>; label = "lan4"; }; port@1 { - reg = <1>; label = "lan3"; }; port@2 { - reg = <2>; label = "lan2"; }; port@3 { - reg = <3>; label = "lan1"; }; port@4 { - reg = <4>; label = "wan"; }; port@8 { - reg = <8>; label = "cpu"; - ethernet = <&gmac2>; - - fixed-link { - speed = <1000>; - full-duplex; - }; }; }; }; diff --git a/arch/arm/boot/dts/bcm47094-dlink-dir-890l.dts b/arch/arm/boot/dts/broadcom/bcm47094-dlink-dir-890l.dts similarity index 96% rename from arch/arm/boot/dts/bcm47094-dlink-dir-890l.dts rename to arch/arm/boot/dts/broadcom/bcm47094-dlink-dir-890l.dts index d945a20b06e07a1d90f45cc428cf9ab5bdeeb1a8..60744f82c2b71a76a2d93e827347feb4fd001684 100644 --- a/arch/arm/boot/dts/bcm47094-dlink-dir-890l.dts +++ b/arch/arm/boot/dts/broadcom/bcm47094-dlink-dir-890l.dts @@ -172,40 +172,28 @@ ports { port@0 { - reg = <0>; label = "lan1"; }; port@1 { - reg = <1>; label = "lan2"; }; port@2 { - reg = <2>; label = "lan3"; }; port@3 { - reg = <3>; label = "lan4"; }; port@4 { - reg = <4>; label = "wan"; }; port@8 { - reg = <8>; label = "cpu"; - ethernet = <&gmac2>; phy-mode = "rgmii"; - - fixed-link { - speed = <1000>; - full-duplex; - }; }; }; }; diff --git a/arch/arm/boot/dts/bcm47094-linksys-panamera.dts b/arch/arm/boot/dts/broadcom/bcm47094-linksys-panamera.dts similarity index 95% rename from arch/arm/boot/dts/bcm47094-linksys-panamera.dts rename to arch/arm/boot/dts/broadcom/bcm47094-linksys-panamera.dts index d9a16a820e7f902e3d23cb71f07c5f83452dd985..8036c04d81cbf53e3044abc25f0b1add9175b31f 100644 --- a/arch/arm/boot/dts/bcm47094-linksys-panamera.dts +++ b/arch/arm/boot/dts/broadcom/bcm47094-linksys-panamera.dts @@ -207,29 +207,32 @@ dsa,member = <0 0>; ports { + sw0_p0: port@0 { + label = "extsw"; + + fixed-link { + speed = <1000>; + full-duplex; + }; + }; + port@1 { - reg = <1>; label = "lan7"; }; port@2 { - reg = <2>; label = "lan4"; }; port@3 { - reg = <3>; label = "lan8"; }; port@4 { - reg = <4>; label = "wan"; }; port@5 { - reg = <5>; - ethernet = <&gmac0>; label = "cpu"; status = "disabled"; @@ -240,8 +243,6 @@ }; port@7 { - reg = <7>; - ethernet = <&gmac1>; label = "cpu"; status = "disabled"; @@ -252,24 +253,7 @@ }; port@8 { - reg = <8>; - ethernet = <&gmac2>; label = "cpu"; - - fixed-link { - speed = <1000>; - full-duplex; - }; - }; - - sw0_p0: port@0 { - reg = <0>; - label = "extsw"; - - fixed-link { - speed = <1000>; - full-duplex; - }; }; }; }; diff --git a/arch/arm/boot/dts/bcm47094-luxul-abr-4500.dts b/arch/arm/boot/dts/broadcom/bcm47094-luxul-abr-4500.dts similarity index 87% rename from arch/arm/boot/dts/bcm47094-luxul-abr-4500.dts rename to arch/arm/boot/dts/broadcom/bcm47094-luxul-abr-4500.dts index 41a0722fa64a6e411ad09fd8930636c601c654bc..e8991d4e248ce2851a8e4bcecfcccc91c27522d7 100644 --- a/arch/arm/boot/dts/bcm47094-luxul-abr-4500.dts +++ b/arch/arm/boot/dts/broadcom/bcm47094-luxul-abr-4500.dts @@ -25,6 +25,10 @@ nvram@1eff0000 { compatible = "brcm,nvram"; reg = <0x1eff0000 0x10000>; + + et0macaddr: et0macaddr { + #nvmem-cell-cells = <1>; + }; }; leds { @@ -61,6 +65,11 @@ vcc-gpio = <&chipcommon 18 GPIO_ACTIVE_HIGH>; }; +&gmac0 { + nvmem-cells = <&et0macaddr 0>; + nvmem-cell-names = "mac-address"; +}; + &spi_nor { status = "okay"; }; @@ -74,34 +83,29 @@ ports { port@0 { - reg = <0>; label = "wan"; + nvmem-cells = <&et0macaddr 1>; + nvmem-cell-names = "mac-address"; }; port@1 { - reg = <1>; label = "lan4"; }; port@2 { - reg = <2>; label = "lan3"; }; port@3 { - reg = <3>; label = "lan2"; }; port@4 { - reg = <4>; label = "lan1"; }; port@5 { - reg = <5>; label = "cpu"; - ethernet = <&gmac0>; }; }; }; diff --git a/arch/arm/boot/dts/bcm47094-luxul-xap-1610.dts b/arch/arm/boot/dts/broadcom/bcm47094-luxul-xap-1610.dts similarity index 84% rename from arch/arm/boot/dts/bcm47094-luxul-xap-1610.dts rename to arch/arm/boot/dts/broadcom/bcm47094-luxul-xap-1610.dts index c56c7e366848b31f0c004d2f2c72395522beaf30..6875625869d9c8e23a9acd869e51d664a581828e 100644 --- a/arch/arm/boot/dts/bcm47094-luxul-xap-1610.dts +++ b/arch/arm/boot/dts/broadcom/bcm47094-luxul-xap-1610.dts @@ -20,6 +20,14 @@ reg = <0x00000000 0x08000000>; }; + nvram@1eff0000 { + compatible = "brcm,nvram"; + reg = <0x1eff0000 0x10000>; + + et0macaddr: et0macaddr { + }; + }; + leds { compatible = "gpio-leds"; @@ -51,6 +59,11 @@ }; }; +&gmac0 { + nvmem-cells = <&et0macaddr>; + nvmem-cell-names = "mac-address"; +}; + &spi_nor { status = "okay"; }; @@ -60,19 +73,15 @@ ports { port@0 { - reg = <0>; label = "poe"; }; port@1 { - reg = <1>; label = "lan"; }; port@5 { - reg = <5>; label = "cpu"; - ethernet = <&gmac0>; }; }; }; diff --git a/arch/arm/boot/dts/bcm47094-luxul-xbr-4500.dts b/arch/arm/boot/dts/broadcom/bcm47094-luxul-xbr-4500.dts similarity index 87% rename from arch/arm/boot/dts/bcm47094-luxul-xbr-4500.dts rename to arch/arm/boot/dts/broadcom/bcm47094-luxul-xbr-4500.dts index 1b5c91a524ac9b27853d1cc59c8811dff294fb49..7cfa4607ef311fb1b4bb97a548bbb1a177f3faf6 100644 --- a/arch/arm/boot/dts/bcm47094-luxul-xbr-4500.dts +++ b/arch/arm/boot/dts/broadcom/bcm47094-luxul-xbr-4500.dts @@ -25,6 +25,10 @@ nvram@1eff0000 { compatible = "brcm,nvram"; reg = <0x1eff0000 0x10000>; + + et0macaddr: et0macaddr { + #nvmem-cell-cells = <1>; + }; }; leds { @@ -61,6 +65,11 @@ vcc-gpio = <&chipcommon 18 GPIO_ACTIVE_HIGH>; }; +&gmac0 { + nvmem-cells = <&et0macaddr 0>; + nvmem-cell-names = "mac-address"; +}; + &spi_nor { status = "okay"; }; @@ -74,34 +83,29 @@ ports { port@0 { - reg = <0>; label = "wan"; + nvmem-cells = <&et0macaddr 1>; + nvmem-cell-names = "mac-address"; }; port@1 { - reg = <1>; label = "lan4"; }; port@2 { - reg = <2>; label = "lan3"; }; port@3 { - reg = <3>; label = "lan2"; }; port@4 { - reg = <4>; label = "lan1"; }; port@5 { - reg = <5>; label = "cpu"; - ethernet = <&gmac0>; }; }; }; diff --git a/arch/arm/boot/dts/bcm47094-luxul-xwc-2000.dts b/arch/arm/boot/dts/broadcom/bcm47094-luxul-xwc-2000.dts similarity index 83% rename from arch/arm/boot/dts/bcm47094-luxul-xwc-2000.dts rename to arch/arm/boot/dts/broadcom/bcm47094-luxul-xwc-2000.dts index 739063b77b1f6179f484d5ffbc687557542d433d..d55e10095eae79c27412bb311575864d11211dd3 100644 --- a/arch/arm/boot/dts/bcm47094-luxul-xwc-2000.dts +++ b/arch/arm/boot/dts/broadcom/bcm47094-luxul-xwc-2000.dts @@ -22,6 +22,14 @@ <0x88000000 0x18000000>; }; + nvram@1eff0000 { + compatible = "brcm,nvram"; + reg = <0x1eff0000 0x10000>; + + et0macaddr: et0macaddr { + }; + }; + leds { compatible = "gpio-leds"; @@ -47,6 +55,11 @@ status = "okay"; }; +&gmac0 { + nvmem-cells = <&et0macaddr>; + nvmem-cell-names = "mac-address"; +}; + &spi_nor { status = "okay"; }; @@ -56,14 +69,11 @@ ports { port@0 { - reg = <0>; label = "lan"; }; port@5 { - reg = <5>; label = "cpu"; - ethernet = <&gmac0>; }; }; }; diff --git a/arch/arm/boot/dts/bcm47094-luxul-xwr-3100.dts b/arch/arm/boot/dts/broadcom/bcm47094-luxul-xwr-3100.dts similarity index 88% rename from arch/arm/boot/dts/bcm47094-luxul-xwr-3100.dts rename to arch/arm/boot/dts/broadcom/bcm47094-luxul-xwr-3100.dts index 7afc68d5d2c20ce8a8e5ef908265c63a0f5b723e..ccf031c0e276d6b45d1fd1220643845b3a063713 100644 --- a/arch/arm/boot/dts/bcm47094-luxul-xwr-3100.dts +++ b/arch/arm/boot/dts/broadcom/bcm47094-luxul-xwr-3100.dts @@ -9,7 +9,7 @@ #include "bcm5301x-nand-cs0-bch4.dtsi" / { - compatible = "luxul,xwr-3100v1", "brcm,bcm47094", "brcm,bcm4708"; + compatible = "luxul,xwr-3100-v1", "brcm,bcm47094", "brcm,bcm4708"; model = "Luxul XWR-3100 V1"; chosen { @@ -25,6 +25,10 @@ nvram@1eff0000 { compatible = "brcm,nvram"; reg = <0x1eff0000 0x10000>; + + et0macaddr: et0macaddr { + #nvmem-cell-cells = <1>; + }; }; leds { @@ -101,6 +105,11 @@ vcc-gpio = <&chipcommon 18 GPIO_ACTIVE_HIGH>; }; +&gmac0 { + nvmem-cells = <&et0macaddr 0>; + nvmem-cell-names = "mac-address"; +}; + &spi_nor { status = "okay"; }; @@ -114,34 +123,29 @@ ports { port@0 { - reg = <0>; label = "lan4"; }; port@1 { - reg = <1>; label = "lan3"; }; port@2 { - reg = <2>; label = "lan2"; }; port@3 { - reg = <3>; label = "lan1"; }; port@4 { - reg = <4>; label = "wan"; + nvmem-cells = <&et0macaddr 5>; + nvmem-cell-names = "mac-address"; }; port@5 { - reg = <5>; label = "cpu"; - ethernet = <&gmac0>; }; }; }; diff --git a/arch/arm/boot/dts/bcm47094-luxul-xwr-3150-v1.dts b/arch/arm/boot/dts/broadcom/bcm47094-luxul-xwr-3150-v1.dts similarity index 93% rename from arch/arm/boot/dts/bcm47094-luxul-xwr-3150-v1.dts rename to arch/arm/boot/dts/broadcom/bcm47094-luxul-xwr-3150-v1.dts index 60a2c441d5bdacbaa4ea8073c380cd9ae061d79e..789dd2a3d22638f0315c9e7b4f2e10f6a4c16fda 100644 --- a/arch/arm/boot/dts/bcm47094-luxul-xwr-3150-v1.dts +++ b/arch/arm/boot/dts/broadcom/bcm47094-luxul-xwr-3150-v1.dts @@ -27,6 +27,7 @@ reg = <0x1eff0000 0x10000>; et0macaddr: et0macaddr { + #nvmem-cell-cells = <1>; }; }; @@ -76,7 +77,7 @@ }; &gmac0 { - nvmem-cells = <&et0macaddr>; + nvmem-cells = <&et0macaddr 0>; nvmem-cell-names = "mac-address"; }; @@ -97,34 +98,29 @@ ports { port@0 { - reg = <0>; label = "lan4"; }; port@1 { - reg = <1>; label = "lan3"; }; port@2 { - reg = <2>; label = "lan2"; }; port@3 { - reg = <3>; label = "lan1"; }; port@4 { - reg = <4>; label = "wan"; + nvmem-cells = <&et0macaddr 5>; + nvmem-cell-names = "mac-address"; }; port@5 { - reg = <5>; label = "cpu"; - ethernet = <&gmac0>; }; }; }; diff --git a/arch/arm/boot/dts/bcm47094-netgear-r8500.dts b/arch/arm/boot/dts/broadcom/bcm47094-netgear-r8500.dts similarity index 100% rename from arch/arm/boot/dts/bcm47094-netgear-r8500.dts rename to arch/arm/boot/dts/broadcom/bcm47094-netgear-r8500.dts diff --git a/arch/arm/boot/dts/bcm47094-phicomm-k3.dts b/arch/arm/boot/dts/broadcom/bcm47094-phicomm-k3.dts similarity index 100% rename from arch/arm/boot/dts/bcm47094-phicomm-k3.dts rename to arch/arm/boot/dts/broadcom/bcm47094-phicomm-k3.dts diff --git a/arch/arm/boot/dts/bcm47094.dtsi b/arch/arm/boot/dts/broadcom/bcm47094.dtsi similarity index 100% rename from arch/arm/boot/dts/bcm47094.dtsi rename to arch/arm/boot/dts/broadcom/bcm47094.dtsi diff --git a/arch/arm/boot/dts/bcm47189-luxul-xap-1440.dts b/arch/arm/boot/dts/broadcom/bcm47189-luxul-xap-1440.dts similarity index 100% rename from arch/arm/boot/dts/bcm47189-luxul-xap-1440.dts rename to arch/arm/boot/dts/broadcom/bcm47189-luxul-xap-1440.dts diff --git a/arch/arm/boot/dts/bcm47189-luxul-xap-810.dts b/arch/arm/boot/dts/broadcom/bcm47189-luxul-xap-810.dts similarity index 100% rename from arch/arm/boot/dts/bcm47189-luxul-xap-810.dts rename to arch/arm/boot/dts/broadcom/bcm47189-luxul-xap-810.dts diff --git a/arch/arm/boot/dts/bcm47189-tenda-ac9.dts b/arch/arm/boot/dts/broadcom/bcm47189-tenda-ac9.dts similarity index 100% rename from arch/arm/boot/dts/bcm47189-tenda-ac9.dts rename to arch/arm/boot/dts/broadcom/bcm47189-tenda-ac9.dts diff --git a/arch/arm/boot/dts/bcm47622.dtsi b/arch/arm/boot/dts/broadcom/bcm47622.dtsi similarity index 99% rename from arch/arm/boot/dts/bcm47622.dtsi rename to arch/arm/boot/dts/broadcom/bcm47622.dtsi index cd25ed2757b70dafa2db5d3df9298e0792f207f0..7cd38de118c320e86fdc91ea1ebb5f148ee2d69c 100644 --- a/arch/arm/boot/dts/bcm47622.dtsi +++ b/arch/arm/boot/dts/broadcom/bcm47622.dtsi @@ -52,6 +52,7 @@ L2_0: l2-cache0 { compatible = "cache"; cache-level = <2>; + cache-unified; }; }; diff --git a/arch/arm/boot/dts/bcm53015-meraki-mr26.dts b/arch/arm/boot/dts/broadcom/bcm53015-meraki-mr26.dts similarity index 94% rename from arch/arm/boot/dts/bcm53015-meraki-mr26.dts rename to arch/arm/boot/dts/broadcom/bcm53015-meraki-mr26.dts index 14f58033efeb967810feefa93e566eea538fc4d3..03ad614e6b7214665d43dda787fe66a3113fc975 100644 --- a/arch/arm/boot/dts/bcm53015-meraki-mr26.dts +++ b/arch/arm/boot/dts/broadcom/bcm53015-meraki-mr26.dts @@ -39,8 +39,6 @@ keys { compatible = "gpio-keys"; - #address-cells = <1>; - #size-cells = <0>; key-restart { label = "Reset"; @@ -74,8 +72,6 @@ }; &nandcs { - nand-ecc-algo = "hw"; - partitions { compatible = "fixed-partitions"; #address-cells = <0x1>; @@ -117,18 +113,15 @@ ports { port@0 { - reg = <0>; label = "poe"; }; port@5 { - reg = <5>; label = "cpu"; - ethernet = <&gmac0>; fixed-link { speed = <1000>; - duplex-full; + full-duplex; }; }; }; diff --git a/arch/arm/boot/dts/bcm53016-dlink-dwl-8610ap.dts b/arch/arm/boot/dts/broadcom/bcm53016-dlink-dwl-8610ap.dts similarity index 100% rename from arch/arm/boot/dts/bcm53016-dlink-dwl-8610ap.dts rename to arch/arm/boot/dts/broadcom/bcm53016-dlink-dwl-8610ap.dts diff --git a/arch/arm/boot/dts/bcm53016-meraki-mr32.dts b/arch/arm/boot/dts/broadcom/bcm53016-meraki-mr32.dts similarity index 94% rename from arch/arm/boot/dts/bcm53016-meraki-mr32.dts rename to arch/arm/boot/dts/broadcom/bcm53016-meraki-mr32.dts index 46c2c93b01d88ca4a2a16ffe1ed96c9446ad24dd..26c12bfb0bdd4a1a4d88ff980898893748ad9c7a 100644 --- a/arch/arm/boot/dts/bcm53016-meraki-mr32.dts +++ b/arch/arm/boot/dts/broadcom/bcm53016-meraki-mr32.dts @@ -125,8 +125,6 @@ }; &nandcs { - nand-ecc-algo = "hw"; - partitions { /* * The partition autodetection does not work for this device. @@ -140,31 +138,31 @@ #address-cells = <0x1>; #size-cells = <0x1>; - partition0@0 { + partition@0 { label = "u-boot"; reg = <0x0 0x100000>; read-only; }; - partition1@100000 { + partition@100000 { label = "bootkernel1"; reg = <0x100000 0x300000>; read-only; }; - partition2@400000 { + partition@400000 { label = "nvram"; reg = <0x400000 0x100000>; read-only; }; - partition3@500000 { + partition@500000 { label = "bootkernel2"; reg = <0x500000 0x300000>; read-only; }; - partition4@800000 { + partition@800000 { label = "ubi"; reg = <0x800000 0x7780000>; }; @@ -176,18 +174,15 @@ ports { port@0 { - reg = <0>; label = "poe"; }; port@5 { - reg = <5>; label = "cpu"; - ethernet = <&gmac0>; fixed-link { speed = <1000>; - duplex-full; + full-duplex; }; }; }; diff --git a/arch/arm/boot/dts/bcm5301x-nand-cs0-bch1.dtsi b/arch/arm/boot/dts/broadcom/bcm5301x-nand-cs0-bch1.dtsi similarity index 100% rename from arch/arm/boot/dts/bcm5301x-nand-cs0-bch1.dtsi rename to arch/arm/boot/dts/broadcom/bcm5301x-nand-cs0-bch1.dtsi diff --git a/arch/arm/boot/dts/bcm5301x-nand-cs0-bch4.dtsi b/arch/arm/boot/dts/broadcom/bcm5301x-nand-cs0-bch4.dtsi similarity index 100% rename from arch/arm/boot/dts/bcm5301x-nand-cs0-bch4.dtsi rename to arch/arm/boot/dts/broadcom/bcm5301x-nand-cs0-bch4.dtsi diff --git a/arch/arm/boot/dts/bcm5301x-nand-cs0-bch8.dtsi b/arch/arm/boot/dts/broadcom/bcm5301x-nand-cs0-bch8.dtsi similarity index 100% rename from arch/arm/boot/dts/bcm5301x-nand-cs0-bch8.dtsi rename to arch/arm/boot/dts/broadcom/bcm5301x-nand-cs0-bch8.dtsi diff --git a/arch/arm/boot/dts/bcm5301x-nand-cs0.dtsi b/arch/arm/boot/dts/broadcom/bcm5301x-nand-cs0.dtsi similarity index 100% rename from arch/arm/boot/dts/bcm5301x-nand-cs0.dtsi rename to arch/arm/boot/dts/broadcom/bcm5301x-nand-cs0.dtsi diff --git a/arch/arm/boot/dts/broadcom/bcm5301x.dtsi b/arch/arm/boot/dts/broadcom/bcm5301x.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..600a1b54f2ae5c8670d8a97d0cd12b71dfa6d98d --- /dev/null +++ b/arch/arm/boot/dts/broadcom/bcm5301x.dtsi @@ -0,0 +1,170 @@ +/* + * Broadcom BCM470X / BCM5301X ARM platform code. + * Generic DTS part for all BCM53010, BCM53011, BCM53012, BCM53014, BCM53015, + * BCM53016, BCM53017, BCM53018, BCM4707, BCM4708 and BCM4709 SoCs + * + * Licensed under the GNU/GPL. See COPYING for details. + */ + +#include "bcm-ns.dtsi" + +/ { + mpcore-bus@19000000 { + a9pll: arm_clk@0 { + #clock-cells = <0>; + compatible = "brcm,nsp-armpll"; + clocks = <&osc>; + reg = <0x00000 0x1000>; + }; + + watchdog@20620 { + compatible = "arm,cortex-a9-twd-wdt"; + reg = <0x20620 0x20>; + interrupts = ; + clocks = <&periph_clk>; + }; + }; + + pmu { + compatible = "arm,cortex-a9-pmu"; + interrupts = + , + ; + }; + + clocks { + #address-cells = <1>; + #size-cells = <1>; + ranges; + + osc: oscillator { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <25000000>; + }; + + iprocmed: iprocmed { + #clock-cells = <0>; + compatible = "fixed-factor-clock"; + clocks = <&genpll BCM_NSP_GENPLL_IPROCFAST_CLK>; + clock-div = <2>; + clock-mult = <1>; + }; + + iprocslow: iprocslow { + #clock-cells = <0>; + compatible = "fixed-factor-clock"; + clocks = <&genpll BCM_NSP_GENPLL_IPROCFAST_CLK>; + clock-div = <4>; + clock-mult = <1>; + }; + + periph_clk: periph_clk { + #clock-cells = <0>; + compatible = "fixed-factor-clock"; + clocks = <&a9pll>; + clock-div = <2>; + clock-mult = <1>; + }; + }; + + mdio-mux@18003000 { + compatible = "mdio-mux-mmioreg", "mdio-mux"; + mdio-parent-bus = <&mdio>; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x18003000 0x4>; + mux-mask = <0x200>; + + mdio@0 { + reg = <0x0>; + #address-cells = <1>; + #size-cells = <0>; + + usb3_phy: usb3-phy@10 { + compatible = "brcm,ns-ax-usb3-phy"; + reg = <0x10>; + usb3-dmp-syscon = <&usb3_dmp>; + #phy-cells = <0>; + status = "disabled"; + }; + }; + }; + + usb3_dmp: syscon@18105000 { + reg = <0x18105000 0x1000>; + }; + + i2c0: i2c@18009000 { + compatible = "brcm,iproc-i2c"; + reg = <0x18009000 0x50>; + interrupts = ; + #address-cells = <1>; + #size-cells = <0>; + clock-frequency = <100000>; + status = "disabled"; + }; + + dmu-bus@1800c000 { + cru-bus@100 { + lcpll0: clock-controller@100 { + #clock-cells = <1>; + compatible = "brcm,nsp-lcpll0"; + reg = <0x100 0x14>; + clocks = <&osc>; + clock-output-names = "lcpll0", "pcie_phy", + "sdio", "ddr_phy"; + }; + + genpll: clock-controller@140 { + #clock-cells = <1>; + compatible = "brcm,nsp-genpll"; + reg = <0x140 0x24>; + clocks = <&osc>; + clock-output-names = "genpll", "phy", + "ethernetclk", + "usbclk", "iprocfast", + "sata1", "sata2"; + }; + }; + }; + + spi@18029200 { + compatible = "brcm,spi-nsp-qspi", "brcm,spi-bcm-qspi"; + reg = <0x18029200 0x184>, + <0x18029000 0x124>, + <0x1811b408 0x004>, + <0x180293a0 0x01c>; + reg-names = "mspi", "bspi", "intr_regs", "intr_status_reg"; + interrupts = , + , + , + , + , + , + ; + interrupt-names = "mspi_done", + "mspi_halted", + "spi_lr_fullness_reached", + "spi_lr_session_aborted", + "spi_lr_impatient", + "spi_lr_session_done", + "spi_lr_overread"; + clocks = <&iprocmed>; + num-cs = <2>; + #address-cells = <1>; + #size-cells = <0>; + + spi_nor: flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <20000000>; + status = "disabled"; + + partitions { + compatible = "brcm,bcm947xx-cfe-partitions"; + }; + }; + }; +}; diff --git a/arch/arm/boot/dts/bcm53340-ubnt-unifi-switch8.dts b/arch/arm/boot/dts/broadcom/bcm53340-ubnt-unifi-switch8.dts similarity index 100% rename from arch/arm/boot/dts/bcm53340-ubnt-unifi-switch8.dts rename to arch/arm/boot/dts/broadcom/bcm53340-ubnt-unifi-switch8.dts diff --git a/arch/arm/boot/dts/bcm53573.dtsi b/arch/arm/boot/dts/broadcom/bcm53573.dtsi similarity index 100% rename from arch/arm/boot/dts/bcm53573.dtsi rename to arch/arm/boot/dts/broadcom/bcm53573.dtsi diff --git a/arch/arm/boot/dts/bcm59056.dtsi b/arch/arm/boot/dts/broadcom/bcm59056.dtsi similarity index 100% rename from arch/arm/boot/dts/bcm59056.dtsi rename to arch/arm/boot/dts/broadcom/bcm59056.dtsi diff --git a/arch/arm/boot/dts/bcm63138.dtsi b/arch/arm/boot/dts/broadcom/bcm63138.dtsi similarity index 100% rename from arch/arm/boot/dts/bcm63138.dtsi rename to arch/arm/boot/dts/broadcom/bcm63138.dtsi diff --git a/arch/arm/boot/dts/bcm63148.dtsi b/arch/arm/boot/dts/broadcom/bcm63148.dtsi similarity index 99% rename from arch/arm/boot/dts/bcm63148.dtsi rename to arch/arm/boot/dts/broadcom/bcm63148.dtsi index ba7f265db1210038102f456659a07a8654552240..24431de1810ed028651a6b9fb842e2515c01b858 100644 --- a/arch/arm/boot/dts/bcm63148.dtsi +++ b/arch/arm/boot/dts/broadcom/bcm63148.dtsi @@ -36,6 +36,7 @@ L2_0: l2-cache0 { compatible = "cache"; cache-level = <2>; + cache-unified; }; }; diff --git a/arch/arm/boot/dts/bcm63178.dtsi b/arch/arm/boot/dts/broadcom/bcm63178.dtsi similarity index 99% rename from arch/arm/boot/dts/bcm63178.dtsi rename to arch/arm/boot/dts/broadcom/bcm63178.dtsi index d8268a1e889bbdbaeb79d9b82d83514fbd7735e7..3f9aed96babfc75e11bb152aa673c6329f39106d 100644 --- a/arch/arm/boot/dts/bcm63178.dtsi +++ b/arch/arm/boot/dts/broadcom/bcm63178.dtsi @@ -44,6 +44,7 @@ L2_0: l2-cache0 { compatible = "cache"; cache-level = <2>; + cache-unified; }; }; diff --git a/arch/arm/boot/dts/bcm6756.dtsi b/arch/arm/boot/dts/broadcom/bcm6756.dtsi similarity index 99% rename from arch/arm/boot/dts/bcm6756.dtsi rename to arch/arm/boot/dts/broadcom/bcm6756.dtsi index 49ecc1f0c18c5f1d703e8f116412a8869f617111..1d8d957d65dd08292e16b5c54b20316b12545e82 100644 --- a/arch/arm/boot/dts/bcm6756.dtsi +++ b/arch/arm/boot/dts/broadcom/bcm6756.dtsi @@ -52,6 +52,7 @@ L2_0: l2-cache0 { compatible = "cache"; cache-level = <2>; + cache-unified; }; }; diff --git a/arch/arm/boot/dts/bcm6846.dtsi b/arch/arm/boot/dts/broadcom/bcm6846.dtsi similarity index 99% rename from arch/arm/boot/dts/bcm6846.dtsi rename to arch/arm/boot/dts/broadcom/bcm6846.dtsi index fbc7d3a5dc5f1c04aa5c3e1946b4d2bb9cd3fc45..cf92cf8c4693304cf3d0c4dbf36365c5c49ff481 100644 --- a/arch/arm/boot/dts/bcm6846.dtsi +++ b/arch/arm/boot/dts/broadcom/bcm6846.dtsi @@ -36,6 +36,7 @@ L2_0: l2-cache0 { compatible = "cache"; cache-level = <2>; + cache-unified; }; }; diff --git a/arch/arm/boot/dts/bcm6855.dtsi b/arch/arm/boot/dts/broadcom/bcm6855.dtsi similarity index 99% rename from arch/arm/boot/dts/bcm6855.dtsi rename to arch/arm/boot/dts/broadcom/bcm6855.dtsi index 5e0fe26530f18a53195dc42146328f053cc1dfa3..52d6bc89f9f828a725c51692791e135561429ed1 100644 --- a/arch/arm/boot/dts/bcm6855.dtsi +++ b/arch/arm/boot/dts/broadcom/bcm6855.dtsi @@ -44,6 +44,7 @@ L2_0: l2-cache0 { compatible = "cache"; cache-level = <2>; + cache-unified; }; }; diff --git a/arch/arm/boot/dts/bcm6878.dtsi b/arch/arm/boot/dts/broadcom/bcm6878.dtsi similarity index 99% rename from arch/arm/boot/dts/bcm6878.dtsi rename to arch/arm/boot/dts/broadcom/bcm6878.dtsi index 96529d3d4dc26990ecc68997ea3b25be7d0dace5..2c5d706bac7e3def48e2d7f524a18598e3ce721b 100644 --- a/arch/arm/boot/dts/bcm6878.dtsi +++ b/arch/arm/boot/dts/broadcom/bcm6878.dtsi @@ -36,6 +36,7 @@ L2_0: l2-cache0 { compatible = "cache"; cache-level = <2>; + cache-unified; }; }; diff --git a/arch/arm/boot/dts/bcm7445-bcm97445svmb.dts b/arch/arm/boot/dts/broadcom/bcm7445-bcm97445svmb.dts similarity index 100% rename from arch/arm/boot/dts/bcm7445-bcm97445svmb.dts rename to arch/arm/boot/dts/broadcom/bcm7445-bcm97445svmb.dts diff --git a/arch/arm/boot/dts/bcm7445.dtsi b/arch/arm/boot/dts/broadcom/bcm7445.dtsi similarity index 100% rename from arch/arm/boot/dts/bcm7445.dtsi rename to arch/arm/boot/dts/broadcom/bcm7445.dtsi diff --git a/arch/arm/boot/dts/bcm911360_entphn.dts b/arch/arm/boot/dts/broadcom/bcm911360_entphn.dts similarity index 100% rename from arch/arm/boot/dts/bcm911360_entphn.dts rename to arch/arm/boot/dts/broadcom/bcm911360_entphn.dts diff --git a/arch/arm/boot/dts/bcm911360k.dts b/arch/arm/boot/dts/broadcom/bcm911360k.dts similarity index 100% rename from arch/arm/boot/dts/bcm911360k.dts rename to arch/arm/boot/dts/broadcom/bcm911360k.dts diff --git a/arch/arm/boot/dts/bcm94708.dts b/arch/arm/boot/dts/broadcom/bcm94708.dts similarity index 100% rename from arch/arm/boot/dts/bcm94708.dts rename to arch/arm/boot/dts/broadcom/bcm94708.dts diff --git a/arch/arm/boot/dts/bcm94709.dts b/arch/arm/boot/dts/broadcom/bcm94709.dts similarity index 100% rename from arch/arm/boot/dts/bcm94709.dts rename to arch/arm/boot/dts/broadcom/bcm94709.dts diff --git a/arch/arm/boot/dts/bcm947189acdbmr.dts b/arch/arm/boot/dts/broadcom/bcm947189acdbmr.dts similarity index 100% rename from arch/arm/boot/dts/bcm947189acdbmr.dts rename to arch/arm/boot/dts/broadcom/bcm947189acdbmr.dts diff --git a/arch/arm/boot/dts/bcm947622.dts b/arch/arm/boot/dts/broadcom/bcm947622.dts similarity index 100% rename from arch/arm/boot/dts/bcm947622.dts rename to arch/arm/boot/dts/broadcom/bcm947622.dts diff --git a/arch/arm/boot/dts/bcm953012er.dts b/arch/arm/boot/dts/broadcom/bcm953012er.dts similarity index 100% rename from arch/arm/boot/dts/bcm953012er.dts rename to arch/arm/boot/dts/broadcom/bcm953012er.dts diff --git a/arch/arm/boot/dts/bcm953012hr.dts b/arch/arm/boot/dts/broadcom/bcm953012hr.dts similarity index 100% rename from arch/arm/boot/dts/bcm953012hr.dts rename to arch/arm/boot/dts/broadcom/bcm953012hr.dts diff --git a/arch/arm/boot/dts/bcm953012k.dts b/arch/arm/boot/dts/broadcom/bcm953012k.dts similarity index 100% rename from arch/arm/boot/dts/bcm953012k.dts rename to arch/arm/boot/dts/broadcom/bcm953012k.dts diff --git a/arch/arm/boot/dts/bcm958300k.dts b/arch/arm/boot/dts/broadcom/bcm958300k.dts similarity index 100% rename from arch/arm/boot/dts/bcm958300k.dts rename to arch/arm/boot/dts/broadcom/bcm958300k.dts diff --git a/arch/arm/boot/dts/bcm958305k.dts b/arch/arm/boot/dts/broadcom/bcm958305k.dts similarity index 100% rename from arch/arm/boot/dts/bcm958305k.dts rename to arch/arm/boot/dts/broadcom/bcm958305k.dts diff --git a/arch/arm/boot/dts/bcm958522er.dts b/arch/arm/boot/dts/broadcom/bcm958522er.dts similarity index 100% rename from arch/arm/boot/dts/bcm958522er.dts rename to arch/arm/boot/dts/broadcom/bcm958522er.dts diff --git a/arch/arm/boot/dts/bcm958525er.dts b/arch/arm/boot/dts/broadcom/bcm958525er.dts similarity index 100% rename from arch/arm/boot/dts/bcm958525er.dts rename to arch/arm/boot/dts/broadcom/bcm958525er.dts diff --git a/arch/arm/boot/dts/bcm958525xmc.dts b/arch/arm/boot/dts/broadcom/bcm958525xmc.dts similarity index 100% rename from arch/arm/boot/dts/bcm958525xmc.dts rename to arch/arm/boot/dts/broadcom/bcm958525xmc.dts diff --git a/arch/arm/boot/dts/bcm958622hr.dts b/arch/arm/boot/dts/broadcom/bcm958622hr.dts similarity index 100% rename from arch/arm/boot/dts/bcm958622hr.dts rename to arch/arm/boot/dts/broadcom/bcm958622hr.dts diff --git a/arch/arm/boot/dts/bcm958623hr.dts b/arch/arm/boot/dts/broadcom/bcm958623hr.dts similarity index 100% rename from arch/arm/boot/dts/bcm958623hr.dts rename to arch/arm/boot/dts/broadcom/bcm958623hr.dts diff --git a/arch/arm/boot/dts/bcm958625-meraki-alamo.dtsi b/arch/arm/boot/dts/broadcom/bcm958625-meraki-alamo.dtsi similarity index 100% rename from arch/arm/boot/dts/bcm958625-meraki-alamo.dtsi rename to arch/arm/boot/dts/broadcom/bcm958625-meraki-alamo.dtsi diff --git a/arch/arm/boot/dts/bcm958625-meraki-kingpin.dtsi b/arch/arm/boot/dts/broadcom/bcm958625-meraki-kingpin.dtsi similarity index 100% rename from arch/arm/boot/dts/bcm958625-meraki-kingpin.dtsi rename to arch/arm/boot/dts/broadcom/bcm958625-meraki-kingpin.dtsi diff --git a/arch/arm/boot/dts/bcm958625-meraki-mx64-a0.dts b/arch/arm/boot/dts/broadcom/bcm958625-meraki-mx64-a0.dts similarity index 100% rename from arch/arm/boot/dts/bcm958625-meraki-mx64-a0.dts rename to arch/arm/boot/dts/broadcom/bcm958625-meraki-mx64-a0.dts diff --git a/arch/arm/boot/dts/bcm958625-meraki-mx64.dts b/arch/arm/boot/dts/broadcom/bcm958625-meraki-mx64.dts similarity index 100% rename from arch/arm/boot/dts/bcm958625-meraki-mx64.dts rename to arch/arm/boot/dts/broadcom/bcm958625-meraki-mx64.dts diff --git a/arch/arm/boot/dts/bcm958625-meraki-mx64w-a0.dts b/arch/arm/boot/dts/broadcom/bcm958625-meraki-mx64w-a0.dts similarity index 100% rename from arch/arm/boot/dts/bcm958625-meraki-mx64w-a0.dts rename to arch/arm/boot/dts/broadcom/bcm958625-meraki-mx64w-a0.dts diff --git a/arch/arm/boot/dts/bcm958625-meraki-mx64w.dts b/arch/arm/boot/dts/broadcom/bcm958625-meraki-mx64w.dts similarity index 100% rename from arch/arm/boot/dts/bcm958625-meraki-mx64w.dts rename to arch/arm/boot/dts/broadcom/bcm958625-meraki-mx64w.dts diff --git a/arch/arm/boot/dts/bcm958625-meraki-mx65.dts b/arch/arm/boot/dts/broadcom/bcm958625-meraki-mx65.dts similarity index 100% rename from arch/arm/boot/dts/bcm958625-meraki-mx65.dts rename to arch/arm/boot/dts/broadcom/bcm958625-meraki-mx65.dts diff --git a/arch/arm/boot/dts/bcm958625-meraki-mx65w.dts b/arch/arm/boot/dts/broadcom/bcm958625-meraki-mx65w.dts similarity index 100% rename from arch/arm/boot/dts/bcm958625-meraki-mx65w.dts rename to arch/arm/boot/dts/broadcom/bcm958625-meraki-mx65w.dts diff --git a/arch/arm/boot/dts/bcm958625-meraki-mx6x-common.dtsi b/arch/arm/boot/dts/broadcom/bcm958625-meraki-mx6x-common.dtsi similarity index 100% rename from arch/arm/boot/dts/bcm958625-meraki-mx6x-common.dtsi rename to arch/arm/boot/dts/broadcom/bcm958625-meraki-mx6x-common.dtsi diff --git a/arch/arm/boot/dts/bcm958625hr.dts b/arch/arm/boot/dts/broadcom/bcm958625hr.dts similarity index 100% rename from arch/arm/boot/dts/bcm958625hr.dts rename to arch/arm/boot/dts/broadcom/bcm958625hr.dts diff --git a/arch/arm/boot/dts/bcm958625k.dts b/arch/arm/boot/dts/broadcom/bcm958625k.dts similarity index 100% rename from arch/arm/boot/dts/bcm958625k.dts rename to arch/arm/boot/dts/broadcom/bcm958625k.dts diff --git a/arch/arm/boot/dts/bcm963138.dts b/arch/arm/boot/dts/broadcom/bcm963138.dts similarity index 100% rename from arch/arm/boot/dts/bcm963138.dts rename to arch/arm/boot/dts/broadcom/bcm963138.dts diff --git a/arch/arm/boot/dts/bcm963138dvt.dts b/arch/arm/boot/dts/broadcom/bcm963138dvt.dts similarity index 100% rename from arch/arm/boot/dts/bcm963138dvt.dts rename to arch/arm/boot/dts/broadcom/bcm963138dvt.dts diff --git a/arch/arm/boot/dts/bcm963148.dts b/arch/arm/boot/dts/broadcom/bcm963148.dts similarity index 100% rename from arch/arm/boot/dts/bcm963148.dts rename to arch/arm/boot/dts/broadcom/bcm963148.dts diff --git a/arch/arm/boot/dts/bcm963178.dts b/arch/arm/boot/dts/broadcom/bcm963178.dts similarity index 100% rename from arch/arm/boot/dts/bcm963178.dts rename to arch/arm/boot/dts/broadcom/bcm963178.dts diff --git a/arch/arm/boot/dts/bcm96756.dts b/arch/arm/boot/dts/broadcom/bcm96756.dts similarity index 100% rename from arch/arm/boot/dts/bcm96756.dts rename to arch/arm/boot/dts/broadcom/bcm96756.dts diff --git a/arch/arm/boot/dts/bcm96846.dts b/arch/arm/boot/dts/broadcom/bcm96846.dts similarity index 100% rename from arch/arm/boot/dts/bcm96846.dts rename to arch/arm/boot/dts/broadcom/bcm96846.dts diff --git a/arch/arm/boot/dts/bcm96855.dts b/arch/arm/boot/dts/broadcom/bcm96855.dts similarity index 100% rename from arch/arm/boot/dts/bcm96855.dts rename to arch/arm/boot/dts/broadcom/bcm96855.dts diff --git a/arch/arm/boot/dts/bcm96878.dts b/arch/arm/boot/dts/broadcom/bcm96878.dts similarity index 100% rename from arch/arm/boot/dts/bcm96878.dts rename to arch/arm/boot/dts/broadcom/bcm96878.dts diff --git a/arch/arm/boot/dts/bcm988312hr.dts b/arch/arm/boot/dts/broadcom/bcm988312hr.dts similarity index 100% rename from arch/arm/boot/dts/bcm988312hr.dts rename to arch/arm/boot/dts/broadcom/bcm988312hr.dts diff --git a/arch/arm/boot/dts/bcm9hmidc.dtsi b/arch/arm/boot/dts/broadcom/bcm9hmidc.dtsi similarity index 100% rename from arch/arm/boot/dts/bcm9hmidc.dtsi rename to arch/arm/boot/dts/broadcom/bcm9hmidc.dtsi diff --git a/arch/arm/boot/dts/calxeda/Makefile b/arch/arm/boot/dts/calxeda/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..f5126b6d26adc6874424d25c10bcb6d7356948de --- /dev/null +++ b/arch/arm/boot/dts/calxeda/Makefile @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: GPL-2.0 +dtb-$(CONFIG_ARCH_HIGHBANK) += \ + highbank.dtb \ + ecx-2000.dtb +dtb-$(CONFIG_ARCH_HIGHBANK) += \ + highbank.dtb \ + ecx-2000.dtb diff --git a/arch/arm/boot/dts/ecx-2000.dts b/arch/arm/boot/dts/calxeda/ecx-2000.dts similarity index 100% rename from arch/arm/boot/dts/ecx-2000.dts rename to arch/arm/boot/dts/calxeda/ecx-2000.dts diff --git a/arch/arm/boot/dts/ecx-common.dtsi b/arch/arm/boot/dts/calxeda/ecx-common.dtsi similarity index 100% rename from arch/arm/boot/dts/ecx-common.dtsi rename to arch/arm/boot/dts/calxeda/ecx-common.dtsi diff --git a/arch/arm/boot/dts/highbank.dts b/arch/arm/boot/dts/calxeda/highbank.dts similarity index 100% rename from arch/arm/boot/dts/highbank.dts rename to arch/arm/boot/dts/calxeda/highbank.dts diff --git a/arch/arm/boot/dts/cirrus/Makefile b/arch/arm/boot/dts/cirrus/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..e944d3e2129db4c263f68d22f561b573950784be --- /dev/null +++ b/arch/arm/boot/dts/cirrus/Makefile @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0 +dtb-$(CONFIG_ARCH_CLPS711X) += \ + ep7211-edb7211.dtb +dtb-$(CONFIG_ARCH_CLPS711X) += \ + ep7211-edb7211.dtb diff --git a/arch/arm/boot/dts/ep7209.dtsi b/arch/arm/boot/dts/cirrus/ep7209.dtsi similarity index 100% rename from arch/arm/boot/dts/ep7209.dtsi rename to arch/arm/boot/dts/cirrus/ep7209.dtsi diff --git a/arch/arm/boot/dts/ep7211-edb7211.dts b/arch/arm/boot/dts/cirrus/ep7211-edb7211.dts similarity index 100% rename from arch/arm/boot/dts/ep7211-edb7211.dts rename to arch/arm/boot/dts/cirrus/ep7211-edb7211.dts diff --git a/arch/arm/boot/dts/ep7211.dtsi b/arch/arm/boot/dts/cirrus/ep7211.dtsi similarity index 100% rename from arch/arm/boot/dts/ep7211.dtsi rename to arch/arm/boot/dts/cirrus/ep7211.dtsi diff --git a/arch/arm/boot/dts/cnxt/Makefile b/arch/arm/boot/dts/cnxt/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..d49df53f65a165314559a5361a875cca94ca8e9c --- /dev/null +++ b/arch/arm/boot/dts/cnxt/Makefile @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0 +dtb-$(CONFIG_ARCH_DIGICOLOR) += \ + cx92755_equinox.dtb +dtb-$(CONFIG_ARCH_DIGICOLOR) += \ + cx92755_equinox.dtb diff --git a/arch/arm/boot/dts/cx92755.dtsi b/arch/arm/boot/dts/cnxt/cx92755.dtsi similarity index 100% rename from arch/arm/boot/dts/cx92755.dtsi rename to arch/arm/boot/dts/cnxt/cx92755.dtsi diff --git a/arch/arm/boot/dts/cx92755_equinox.dts b/arch/arm/boot/dts/cnxt/cx92755_equinox.dts similarity index 100% rename from arch/arm/boot/dts/cx92755_equinox.dts rename to arch/arm/boot/dts/cnxt/cx92755_equinox.dts diff --git a/arch/arm/boot/dts/gemini/Makefile b/arch/arm/boot/dts/gemini/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..f9f63ce3eb496345ae71bae07ecf216cb8dc22aa --- /dev/null +++ b/arch/arm/boot/dts/gemini/Makefile @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: GPL-2.0 +dtb-$(CONFIG_ARCH_GEMINI) += \ + gemini-dlink-dir-685.dtb \ + gemini-dlink-dns-313.dtb \ + gemini-nas4220b.dtb \ + gemini-ns2502.dtb \ + gemini-rut1xx.dtb \ + gemini-sl93512r.dtb \ + gemini-sq201.dtb \ + gemini-ssi1328.dtb \ + gemini-wbd111.dtb \ + gemini-wbd222.dtb diff --git a/arch/arm/boot/dts/gemini-dlink-dir-685.dts b/arch/arm/boot/dts/gemini/gemini-dlink-dir-685.dts similarity index 100% rename from arch/arm/boot/dts/gemini-dlink-dir-685.dts rename to arch/arm/boot/dts/gemini/gemini-dlink-dir-685.dts diff --git a/arch/arm/boot/dts/gemini-dlink-dns-313.dts b/arch/arm/boot/dts/gemini/gemini-dlink-dns-313.dts similarity index 100% rename from arch/arm/boot/dts/gemini-dlink-dns-313.dts rename to arch/arm/boot/dts/gemini/gemini-dlink-dns-313.dts diff --git a/arch/arm/boot/dts/gemini-nas4220b.dts b/arch/arm/boot/dts/gemini/gemini-nas4220b.dts similarity index 100% rename from arch/arm/boot/dts/gemini-nas4220b.dts rename to arch/arm/boot/dts/gemini/gemini-nas4220b.dts diff --git a/arch/arm/boot/dts/gemini-ns2502.dts b/arch/arm/boot/dts/gemini/gemini-ns2502.dts similarity index 100% rename from arch/arm/boot/dts/gemini-ns2502.dts rename to arch/arm/boot/dts/gemini/gemini-ns2502.dts diff --git a/arch/arm/boot/dts/gemini-rut1xx.dts b/arch/arm/boot/dts/gemini/gemini-rut1xx.dts similarity index 100% rename from arch/arm/boot/dts/gemini-rut1xx.dts rename to arch/arm/boot/dts/gemini/gemini-rut1xx.dts diff --git a/arch/arm/boot/dts/gemini-sl93512r.dts b/arch/arm/boot/dts/gemini/gemini-sl93512r.dts similarity index 100% rename from arch/arm/boot/dts/gemini-sl93512r.dts rename to arch/arm/boot/dts/gemini/gemini-sl93512r.dts diff --git a/arch/arm/boot/dts/gemini-sq201.dts b/arch/arm/boot/dts/gemini/gemini-sq201.dts similarity index 100% rename from arch/arm/boot/dts/gemini-sq201.dts rename to arch/arm/boot/dts/gemini/gemini-sq201.dts diff --git a/arch/arm/boot/dts/gemini-ssi1328.dts b/arch/arm/boot/dts/gemini/gemini-ssi1328.dts similarity index 100% rename from arch/arm/boot/dts/gemini-ssi1328.dts rename to arch/arm/boot/dts/gemini/gemini-ssi1328.dts diff --git a/arch/arm/boot/dts/gemini-wbd111.dts b/arch/arm/boot/dts/gemini/gemini-wbd111.dts similarity index 100% rename from arch/arm/boot/dts/gemini-wbd111.dts rename to arch/arm/boot/dts/gemini/gemini-wbd111.dts diff --git a/arch/arm/boot/dts/gemini-wbd222.dts b/arch/arm/boot/dts/gemini/gemini-wbd222.dts similarity index 100% rename from arch/arm/boot/dts/gemini-wbd222.dts rename to arch/arm/boot/dts/gemini/gemini-wbd222.dts diff --git a/arch/arm/boot/dts/gemini.dtsi b/arch/arm/boot/dts/gemini/gemini.dtsi similarity index 100% rename from arch/arm/boot/dts/gemini.dtsi rename to arch/arm/boot/dts/gemini/gemini.dtsi diff --git a/arch/arm/boot/dts/hisilicon/Makefile b/arch/arm/boot/dts/hisilicon/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..5ce0512c0010e3af6d70056114a66c82d81a9af6 --- /dev/null +++ b/arch/arm/boot/dts/hisilicon/Makefile @@ -0,0 +1,13 @@ +# SPDX-License-Identifier: GPL-2.0 +dtb-$(CONFIG_ARCH_HI3xxx) += \ + hi3620-hi4511.dtb +dtb-$(CONFIG_ARCH_HIP01) += \ + hip01-ca9x2.dtb +dtb-$(CONFIG_ARCH_HIP04) += \ + hip04-d01.dtb +dtb-$(CONFIG_ARCH_HISI) += \ + hi3519-demb.dtb +dtb-$(CONFIG_ARCH_HIX5HD2) += \ + hisi-x5hd2-dkb.dtb +dtb-$(CONFIG_ARCH_SD5203) += \ + sd5203.dtb diff --git a/arch/arm/boot/dts/hi3519-demb.dts b/arch/arm/boot/dts/hisilicon/hi3519-demb.dts similarity index 100% rename from arch/arm/boot/dts/hi3519-demb.dts rename to arch/arm/boot/dts/hisilicon/hi3519-demb.dts diff --git a/arch/arm/boot/dts/hi3519.dtsi b/arch/arm/boot/dts/hisilicon/hi3519.dtsi similarity index 100% rename from arch/arm/boot/dts/hi3519.dtsi rename to arch/arm/boot/dts/hisilicon/hi3519.dtsi diff --git a/arch/arm/boot/dts/hi3620-hi4511.dts b/arch/arm/boot/dts/hisilicon/hi3620-hi4511.dts similarity index 88% rename from arch/arm/boot/dts/hi3620-hi4511.dts rename to arch/arm/boot/dts/hisilicon/hi3620-hi4511.dts index d7f5daecc9dc86940410eb4ab6839fd125c69bde..f1c816a1d7cf7b9f99be2c73b22029ef6b3c4bce 100644 --- a/arch/arm/boot/dts/hi3620-hi4511.dts +++ b/arch/arm/boot/dts/hisilicon/hi3620-hi4511.dts @@ -66,119 +66,119 @@ pinctrl-names = "default"; pinctrl-0 = <&board_pmx_pins>; - board_pmx_pins: board_pmx_pins { + board_pmx_pins: board-pins { pinctrl-single,pins = < 0x008 0x0 /* GPIO -- eFUSE_DOUT */ 0x100 0x0 /* USIM_CLK & USIM_DATA (IOMG63) */ >; }; - uart0_pmx_func: uart0_pmx_func { + uart0_pmx_func: uart0-pins { pinctrl-single,pins = < 0x0f0 0x0 0x0f4 0x0 /* UART0_RX & UART0_TX */ >; }; - uart0_pmx_idle: uart0_pmx_idle { + uart0_pmx_idle: uart0-idle-pins { pinctrl-single,pins = < /*0x0f0 0x1*/ /* UART0_CTS & UART0_RTS */ 0x0f4 0x1 /* UART0_RX & UART0_TX */ >; }; - uart1_pmx_func: uart1_pmx_func { + uart1_pmx_func: uart1-pins { pinctrl-single,pins = < 0x0f8 0x0 /* UART1_CTS & UART1_RTS (IOMG61) */ 0x0fc 0x0 /* UART1_RX & UART1_TX (IOMG62) */ >; }; - uart1_pmx_idle: uart1_pmx_idle { + uart1_pmx_idle: uart1-idle-pins { pinctrl-single,pins = < 0x0f8 0x1 /* GPIO (IOMG61) */ 0x0fc 0x1 /* GPIO (IOMG62) */ >; }; - uart2_pmx_func: uart2_pmx_func { + uart2_pmx_func: uart2-pins { pinctrl-single,pins = < 0x104 0x2 /* UART2_RXD (IOMG96) */ 0x108 0x2 /* UART2_TXD (IOMG64) */ >; }; - uart2_pmx_idle: uart2_pmx_idle { + uart2_pmx_idle: uart2-idle-pins { pinctrl-single,pins = < 0x104 0x1 /* GPIO (IOMG96) */ 0x108 0x1 /* GPIO (IOMG64) */ >; }; - uart3_pmx_func: uart3_pmx_func { + uart3_pmx_func: uart3-pins { pinctrl-single,pins = < 0x160 0x2 /* UART3_CTS & UART3_RTS (IOMG85) */ 0x164 0x2 /* UART3_RXD & UART3_TXD (IOMG86) */ >; }; - uart3_pmx_idle: uart3_pmx_idle { + uart3_pmx_idle: uart3-idle-pins { pinctrl-single,pins = < 0x160 0x1 /* GPIO (IOMG85) */ 0x164 0x1 /* GPIO (IOMG86) */ >; }; - uart4_pmx_func: uart4_pmx_func { + uart4_pmx_func: uart4-pins { pinctrl-single,pins = < 0x168 0x0 /* UART4_CTS & UART4_RTS (IOMG87) */ 0x16c 0x0 /* UART4_RXD (IOMG88) */ 0x170 0x0 /* UART4_TXD (IOMG93) */ >; }; - uart4_pmx_idle: uart4_pmx_idle { + uart4_pmx_idle: uart4-idle-pins { pinctrl-single,pins = < 0x168 0x1 /* GPIO (IOMG87) */ 0x16c 0x1 /* GPIO (IOMG88) */ 0x170 0x1 /* GPIO (IOMG93) */ >; }; - i2c0_pmx_func: i2c0_pmx_func { + i2c0_pmx_func: i2c0-pins { pinctrl-single,pins = < 0x0b4 0x0 /* I2C0_SCL & I2C0_SDA (IOMG45) */ >; }; - i2c0_pmx_idle: i2c0_pmx_idle { + i2c0_pmx_idle: i2c0-idle-pins { pinctrl-single,pins = < 0x0b4 0x1 /* GPIO (IOMG45) */ >; }; - i2c1_pmx_func: i2c1_pmx_func { + i2c1_pmx_func: i2c1-pins { pinctrl-single,pins = < 0x0b8 0x0 /* I2C1_SCL & I2C1_SDA (IOMG46) */ >; }; - i2c1_pmx_idle: i2c1_pmx_idle { + i2c1_pmx_idle: i2c1-idle-pins { pinctrl-single,pins = < 0x0b8 0x1 /* GPIO (IOMG46) */ >; }; - i2c2_pmx_func: i2c2_pmx_func { + i2c2_pmx_func: i2c2-pins { pinctrl-single,pins = < 0x068 0x0 /* I2C2_SCL (IOMG26) */ 0x06c 0x0 /* I2C2_SDA (IOMG27) */ >; }; - i2c2_pmx_idle: i2c2_pmx_idle { + i2c2_pmx_idle: i2c2-idle-pins { pinctrl-single,pins = < 0x068 0x1 /* GPIO (IOMG26) */ 0x06c 0x1 /* GPIO (IOMG27) */ >; }; - i2c3_pmx_func: i2c3_pmx_func { + i2c3_pmx_func: i2c3-pins { pinctrl-single,pins = < 0x050 0x2 /* I2C3_SCL (IOMG20) */ 0x054 0x2 /* I2C3_SDA (IOMG21) */ >; }; - i2c3_pmx_idle: i2c3_pmx_idle { + i2c3_pmx_idle: i2c3-idle-pins { pinctrl-single,pins = < 0x050 0x1 /* GPIO (IOMG20) */ 0x054 0x1 /* GPIO (IOMG21) */ >; }; - spi0_pmx_func: spi0_pmx_func { + spi0_pmx_func: spi0-pins { pinctrl-single,pins = < 0x0d4 0x0 /* SPI0_CLK/SPI0_DI/SPI0_DO (IOMG53) */ 0x0d8 0x0 /* SPI0_CS0 (IOMG54) */ @@ -187,7 +187,7 @@ 0x0e4 0x0 /* SPI0_CS3 (IOMG57) */ >; }; - spi0_pmx_idle: spi0_pmx_idle { + spi0_pmx_idle: spi0-idle-pins { pinctrl-single,pins = < 0x0d4 0x1 /* GPIO (IOMG53) */ 0x0d8 0x1 /* GPIO (IOMG54) */ @@ -196,21 +196,21 @@ 0x0e4 0x1 /* GPIO (IOMG57) */ >; }; - spi1_pmx_func: spi1_pmx_func { + spi1_pmx_func: spi1-pins { pinctrl-single,pins = < 0x184 0x0 /* SPI1_CLK/SPI1_DI (IOMG98) */ 0x0e8 0x0 /* SPI1_DO (IOMG58) */ 0x0ec 0x0 /* SPI1_CS (IOMG95) */ >; }; - spi1_pmx_idle: spi1_pmx_idle { + spi1_pmx_idle: spi1-idle-pins { pinctrl-single,pins = < 0x184 0x1 /* GPIO (IOMG98) */ 0x0e8 0x1 /* GPIO (IOMG58) */ 0x0ec 0x1 /* GPIO (IOMG95) */ >; }; - kpc_pmx_func: kpc_pmx_func { + kpc_pmx_func: kpc-pins { pinctrl-single,pins = < 0x12c 0x0 /* KEY_IN0 (IOMG73) */ 0x130 0x0 /* KEY_IN1 (IOMG74) */ @@ -220,7 +220,7 @@ 0x114 0x0 /* KEY_OUT2 (IOMG67) */ >; }; - kpc_pmx_idle: kpc_pmx_idle { + kpc_pmx_idle: kpc-idle-pins { pinctrl-single,pins = < 0x12c 0x1 /* GPIO (IOMG73) */ 0x130 0x1 /* GPIO (IOMG74) */ @@ -230,13 +230,13 @@ 0x114 0x1 /* GPIO (IOMG67) */ >; }; - gpio_key_func: gpio_key_func { + gpio_key_func: gpio-key-pins { pinctrl-single,pins = < 0x10c 0x1 /* KEY_OUT0/GPIO (IOMG65) */ 0x130 0x1 /* KEY_IN1/GPIO (IOMG74) */ >; }; - emmc_pmx_func: emmc_pmx_func { + emmc_pmx_func: emmc-pins { pinctrl-single,pins = < 0x030 0x2 /* eMMC_CMD/eMMC_CLK (IOMG12) */ 0x018 0x0 /* NAND_CS3_N (IOMG6) */ @@ -245,7 +245,7 @@ 0x02c 0x2 /* eMMC_DATA[0:7] (IOMG10) */ >; }; - emmc_pmx_idle: emmc_pmx_idle { + emmc_pmx_idle: emmc-idle-pins { pinctrl-single,pins = < 0x030 0x0 /* GPIO (IOMG12) */ 0x018 0x1 /* GPIO (IOMG6) */ @@ -254,19 +254,19 @@ 0x02c 0x1 /* GPIO (IOMG10) */ >; }; - sd_pmx_func: sd_pmx_func { + sd_pmx_func: sd-pins { pinctrl-single,pins = < 0x0bc 0x0 /* SD_CLK/SD_CMD/SD_DATA0/SD_DATA1/SD_DATA2 (IOMG47) */ 0x0c0 0x0 /* SD_DATA3 (IOMG48) */ >; }; - sd_pmx_idle: sd_pmx_idle { + sd_pmx_idle: sd-idle-pins { pinctrl-single,pins = < 0x0bc 0x1 /* GPIO (IOMG47) */ 0x0c0 0x1 /* GPIO (IOMG48) */ >; }; - nand_pmx_func: nand_pmx_func { + nand_pmx_func: nand-pins { pinctrl-single,pins = < 0x00c 0x0 /* NAND_ALE/NAND_CLE/.../NAND_DATA[0:7] (IOMG3) */ 0x010 0x0 /* NAND_CS1_N (IOMG4) */ @@ -279,7 +279,7 @@ 0x02c 0x0 /* NAND_DATA[8:15] (IOMG10) */ >; }; - nand_pmx_idle: nand_pmx_idle { + nand_pmx_idle: nand-idle-pins { pinctrl-single,pins = < 0x00c 0x1 /* GPIO (IOMG3) */ 0x010 0x1 /* GPIO (IOMG4) */ @@ -292,17 +292,17 @@ 0x02c 0x1 /* GPIO (IOMG10) */ >; }; - sdio_pmx_func: sdio_pmx_func { + sdio_pmx_func: sdio-pins { pinctrl-single,pins = < 0x0c4 0x0 /* SDIO_CLK/SDIO_CMD/SDIO_DATA[0:3] (IOMG49) */ >; }; - sdio_pmx_idle: sdio_pmx_idle { + sdio_pmx_idle: sdio-idle-pins { pinctrl-single,pins = < 0x0c4 0x1 /* GPIO (IOMG49) */ >; }; - audio_out_pmx_func: audio_out_pmx_func { + audio_out_pmx_func: audio-out-pins { pinctrl-single,pins = < 0x0f0 0x1 /* GPIO (IOMG59), audio spk & earphone */ >; @@ -314,7 +314,7 @@ pinctrl-0 = < &board_pu_pins &board_pd_pins &board_pd_ps_pins &board_np_pins &board_ps_pins &kpc_cfg_func &audio_out_cfg_func>; - board_pu_pins: board_pu_pins { + board_pu_pins: board-pu-pins { pinctrl-single,pins = < 0x014 0 /* GPIO_158 (IOCFG2) */ 0x018 0 /* GPIO_159 (IOCFG3) */ @@ -324,7 +324,7 @@ pinctrl-single,bias-pulldown = <0 2 0 2>; pinctrl-single,bias-pullup = <1 1 0 1>; }; - board_pd_pins: board_pd_pins { + board_pd_pins: board-pd-pins { pinctrl-single,pins = < 0x038 0 /* eFUSE_DOUT (IOCFG11) */ 0x150 0 /* ISP_GPIO8 (IOCFG93) */ @@ -333,7 +333,7 @@ pinctrl-single,bias-pulldown = <2 2 0 2>; pinctrl-single,bias-pullup = <0 1 0 1>; }; - board_pd_ps_pins: board_pd_ps_pins { + board_pd_ps_pins: board-pd-ps-pins { pinctrl-single,pins = < 0x2d8 0 /* CLK_OUT0 (IOCFG190) */ 0x004 0 /* PMU_SPI_DATA (IOCFG192) */ @@ -342,21 +342,21 @@ pinctrl-single,bias-pullup = <0 1 0 1>; pinctrl-single,drive-strength = <0x30 0xf0>; }; - board_np_pins: board_np_pins { + board_np_pins: board-np-pins { pinctrl-single,pins = < 0x24c 0 /* KEYPAD_OUT7 (IOCFG155) */ >; pinctrl-single,bias-pulldown = <0 2 0 2>; pinctrl-single,bias-pullup = <0 1 0 1>; }; - board_ps_pins: board_ps_pins { + board_ps_pins: board-ps-pins { pinctrl-single,pins = < 0x000 0 /* PMU_SPI_CLK (IOCFG191) */ 0x008 0 /* PMU_SPI_CS_N (IOCFG193) */ >; pinctrl-single,drive-strength = <0x30 0xf0>; }; - uart0_cfg_func: uart0_cfg_func { + uart0_cfg_func: uart0-cfg-pins { pinctrl-single,pins = < 0x208 0 /* UART0_RXD (IOCFG138) */ 0x20c 0 /* UART0_TXD (IOCFG139) */ @@ -364,7 +364,7 @@ pinctrl-single,bias-pulldown = <0 2 0 2>; pinctrl-single,bias-pullup = <0 1 0 1>; }; - uart0_cfg_idle: uart0_cfg_idle { + uart0_cfg_idle: uart0-cfg-idle-pins { pinctrl-single,pins = < 0x208 0 /* UART0_RXD (IOCFG138) */ 0x20c 0 /* UART0_TXD (IOCFG139) */ @@ -372,7 +372,7 @@ pinctrl-single,bias-pulldown = <2 2 0 2>; pinctrl-single,bias-pullup = <0 1 0 1>; }; - uart1_cfg_func: uart1_cfg_func { + uart1_cfg_func: uart1-cfg-pins { pinctrl-single,pins = < 0x210 0 /* UART1_CTS (IOCFG140) */ 0x214 0 /* UART1_RTS (IOCFG141) */ @@ -382,7 +382,7 @@ pinctrl-single,bias-pulldown = <0 2 0 2>; pinctrl-single,bias-pullup = <0 1 0 1>; }; - uart1_cfg_idle: uart1_cfg_idle { + uart1_cfg_idle: uart1-cfg-idle-pins { pinctrl-single,pins = < 0x210 0 /* UART1_CTS (IOCFG140) */ 0x214 0 /* UART1_RTS (IOCFG141) */ @@ -392,7 +392,7 @@ pinctrl-single,bias-pulldown = <2 2 0 2>; pinctrl-single,bias-pullup = <0 1 0 1>; }; - uart2_cfg_func: uart2_cfg_func { + uart2_cfg_func: uart2-cfg-pins { pinctrl-single,pins = < 0x220 0 /* UART2_CTS (IOCFG144) */ 0x224 0 /* UART2_RTS (IOCFG145) */ @@ -402,7 +402,7 @@ pinctrl-single,bias-pulldown = <0 2 0 2>; pinctrl-single,bias-pullup = <0 1 0 1>; }; - uart2_cfg_idle: uart2_cfg_idle { + uart2_cfg_idle: uart2-cfg-idle-pins { pinctrl-single,pins = < 0x220 0 /* GPIO (IOCFG144) */ 0x224 0 /* GPIO (IOCFG145) */ @@ -412,7 +412,7 @@ pinctrl-single,bias-pulldown = <2 2 0 2>; pinctrl-single,bias-pullup = <0 1 0 1>; }; - uart3_cfg_func: uart3_cfg_func { + uart3_cfg_func: uart3-cfg-pins { pinctrl-single,pins = < 0x294 0 /* UART3_CTS (IOCFG173) */ 0x298 0 /* UART3_RTS (IOCFG174) */ @@ -422,7 +422,7 @@ pinctrl-single,bias-pulldown = <0 2 0 2>; pinctrl-single,bias-pullup = <0 1 0 1>; }; - uart3_cfg_idle: uart3_cfg_idle { + uart3_cfg_idle: uart3-cfg-idle-pins { pinctrl-single,pins = < 0x294 0 /* UART3_CTS (IOCFG173) */ 0x298 0 /* UART3_RTS (IOCFG174) */ @@ -432,7 +432,7 @@ pinctrl-single,bias-pulldown = <2 2 0 2>; pinctrl-single,bias-pullup = <0 1 0 1>; }; - uart4_cfg_func: uart4_cfg_func { + uart4_cfg_func: uart4-cfg-pins { pinctrl-single,pins = < 0x2a4 0 /* UART4_CTS (IOCFG177) */ 0x2a8 0 /* UART4_RTS (IOCFG178) */ @@ -442,7 +442,7 @@ pinctrl-single,bias-pulldown = <0 2 0 2>; pinctrl-single,bias-pullup = <0 1 0 1>; }; - i2c0_cfg_func: i2c0_cfg_func { + i2c0_cfg_func: i2c0-cfg-pins { pinctrl-single,pins = < 0x17c 0 /* I2C0_SCL (IOCFG103) */ 0x180 0 /* I2C0_SDA (IOCFG104) */ @@ -451,7 +451,7 @@ pinctrl-single,bias-pullup = <0 1 0 1>; pinctrl-single,drive-strength = <0x30 0xf0>; }; - i2c1_cfg_func: i2c1_cfg_func { + i2c1_cfg_func: i2c1-cfg-pins { pinctrl-single,pins = < 0x184 0 /* I2C1_SCL (IOCFG105) */ 0x188 0 /* I2C1_SDA (IOCFG106) */ @@ -460,7 +460,7 @@ pinctrl-single,bias-pullup = <0 1 0 1>; pinctrl-single,drive-strength = <0x30 0xf0>; }; - i2c2_cfg_func: i2c2_cfg_func { + i2c2_cfg_func: i2c2-cfg-pins { pinctrl-single,pins = < 0x118 0 /* I2C2_SCL (IOCFG79) */ 0x11c 0 /* I2C2_SDA (IOCFG80) */ @@ -469,7 +469,7 @@ pinctrl-single,bias-pullup = <0 1 0 1>; pinctrl-single,drive-strength = <0x30 0xf0>; }; - i2c3_cfg_func: i2c3_cfg_func { + i2c3_cfg_func: i2c3-cfg-pins { pinctrl-single,pins = < 0x100 0 /* I2C3_SCL (IOCFG73) */ 0x104 0 /* I2C3_SDA (IOCFG74) */ @@ -478,7 +478,7 @@ pinctrl-single,bias-pullup = <0 1 0 1>; pinctrl-single,drive-strength = <0x30 0xf0>; }; - spi0_cfg_func1: spi0_cfg_func1 { + spi0_cfg_func1: spi0-cfg-func1-pins { pinctrl-single,pins = < 0x1d4 0 /* SPI0_CLK (IOCFG125) */ 0x1d8 0 /* SPI0_DI (IOCFG126) */ @@ -488,7 +488,7 @@ pinctrl-single,bias-pullup = <0 1 0 1>; pinctrl-single,drive-strength = <0x30 0xf0>; }; - spi0_cfg_func2: spi0_cfg_func2 { + spi0_cfg_func2: spi0-cfg-func2-pins { pinctrl-single,pins = < 0x1e0 0 /* SPI0_CS0 (IOCFG128) */ 0x1e4 0 /* SPI0_CS1 (IOCFG129) */ @@ -499,7 +499,7 @@ pinctrl-single,bias-pullup = <1 1 0 1>; pinctrl-single,drive-strength = <0x30 0xf0>; }; - spi1_cfg_func1: spi1_cfg_func1 { + spi1_cfg_func1: spi1-cfg-func1-pins { pinctrl-single,pins = < 0x1f0 0 /* SPI1_CLK (IOCFG132) */ 0x1f4 0 /* SPI1_DI (IOCFG133) */ @@ -509,7 +509,7 @@ pinctrl-single,bias-pullup = <0 1 0 1>; pinctrl-single,drive-strength = <0x30 0xf0>; }; - spi1_cfg_func2: spi1_cfg_func2 { + spi1_cfg_func2: spi1-cfg-func2-pins { pinctrl-single,pins = < 0x1fc 0 /* SPI1_CS (IOCFG135) */ >; @@ -517,7 +517,7 @@ pinctrl-single,bias-pullup = <1 1 0 1>; pinctrl-single,drive-strength = <0x30 0xf0>; }; - kpc_cfg_func: kpc_cfg_func { + kpc_cfg_func: kpc-cfg-pins { pinctrl-single,pins = < 0x250 0 /* KEY_IN0 (IOCFG156) */ 0x254 0 /* KEY_IN1 (IOCFG157) */ @@ -529,7 +529,7 @@ pinctrl-single,bias-pulldown = <2 2 0 2>; pinctrl-single,bias-pullup = <0 1 0 1>; }; - emmc_cfg_func: emmc_cfg_func { + emmc_cfg_func: emmc-cfg-pins { pinctrl-single,pins = < 0x0ac 0 /* eMMC_CMD (IOCFG40) */ 0x0b0 0 /* eMMC_CLK (IOCFG41) */ @@ -549,7 +549,7 @@ pinctrl-single,bias-pullup = <1 1 0 1>; pinctrl-single,drive-strength = <0x30 0xf0>; }; - sd_cfg_func1: sd_cfg_func1 { + sd_cfg_func1: sd-cfg-func1-pins { pinctrl-single,pins = < 0x18c 0 /* SD_CLK (IOCFG107) */ 0x190 0 /* SD_CMD (IOCFG108) */ @@ -558,7 +558,7 @@ pinctrl-single,bias-pullup = <0 1 0 1>; pinctrl-single,drive-strength = <0x30 0xf0>; }; - sd_cfg_func2: sd_cfg_func2 { + sd_cfg_func2: sd-cfg-func2-pins { pinctrl-single,pins = < 0x194 0 /* SD_DATA0 (IOCFG109) */ 0x198 0 /* SD_DATA1 (IOCFG110) */ @@ -569,7 +569,7 @@ pinctrl-single,bias-pullup = <0 1 0 1>; pinctrl-single,drive-strength = <0x70 0xf0>; }; - nand_cfg_func1: nand_cfg_func1 { + nand_cfg_func1: nand-cfg-func1-pins { pinctrl-single,pins = < 0x03c 0 /* NAND_ALE (IOCFG12) */ 0x040 0 /* NAND_CLE (IOCFG13) */ @@ -594,7 +594,7 @@ pinctrl-single,bias-pullup = <0 1 0 1>; pinctrl-single,drive-strength = <0x30 0xf0>; }; - nand_cfg_func2: nand_cfg_func2 { + nand_cfg_func2: nand-cfg-func2-pins { pinctrl-single,pins = < 0x044 0 /* NAND_RE_N (IOCFG14) */ 0x048 0 /* NAND_WE_N (IOCFG15) */ @@ -611,7 +611,7 @@ pinctrl-single,bias-pullup = <1 1 0 1>; pinctrl-single,drive-strength = <0x30 0xf0>; }; - sdio_cfg_func: sdio_cfg_func { + sdio_cfg_func: sdio-cfg-pins { pinctrl-single,pins = < 0x1a4 0 /* SDIO0_CLK (IOCG113) */ 0x1a8 0 /* SDIO0_CMD (IOCG114) */ @@ -624,7 +624,7 @@ pinctrl-single,bias-pullup = <0 1 0 1>; pinctrl-single,drive-strength = <0x30 0xf0>; }; - audio_out_cfg_func: audio_out_cfg_func { + audio_out_cfg_func: audio-out-cfg-pins { pinctrl-single,pins = < 0x200 0 /* GPIO (IOCFG136) */ 0x204 0 /* GPIO (IOCFG137) */ diff --git a/arch/arm/boot/dts/hi3620.dtsi b/arch/arm/boot/dts/hisilicon/hi3620.dtsi similarity index 99% rename from arch/arm/boot/dts/hi3620.dtsi rename to arch/arm/boot/dts/hisilicon/hi3620.dtsi index cf48ec14af434faa3269ba40fe67467585f02833..a254ec0092960fa2c6248cfbb9f6cb915ab1bbeb 100644 --- a/arch/arm/boot/dts/hi3620.dtsi +++ b/arch/arm/boot/dts/hisilicon/hi3620.dtsi @@ -545,10 +545,9 @@ compatible = "pinctrl-single"; reg = <0x803000 0x188>; #address-cells = <1>; - #size-cells = <1>; + #size-cells = <0>; #pinctrl-cells = <1>; #gpio-range-cells = <3>; - ranges; pinctrl-single,register-width = <32>; pinctrl-single,function-mask = <7>; @@ -567,9 +566,8 @@ compatible = "pinconf-single"; reg = <0x803800 0x2dc>; #address-cells = <1>; - #size-cells = <1>; + #size-cells = <0>; #pinctrl-cells = <1>; - ranges; pinctrl-single,register-width = <32>; }; diff --git a/arch/arm/boot/dts/hip01-ca9x2.dts b/arch/arm/boot/dts/hisilicon/hip01-ca9x2.dts similarity index 100% rename from arch/arm/boot/dts/hip01-ca9x2.dts rename to arch/arm/boot/dts/hisilicon/hip01-ca9x2.dts diff --git a/arch/arm/boot/dts/hip01.dtsi b/arch/arm/boot/dts/hisilicon/hip01.dtsi similarity index 100% rename from arch/arm/boot/dts/hip01.dtsi rename to arch/arm/boot/dts/hisilicon/hip01.dtsi diff --git a/arch/arm/boot/dts/hip04-d01.dts b/arch/arm/boot/dts/hisilicon/hip04-d01.dts similarity index 100% rename from arch/arm/boot/dts/hip04-d01.dts rename to arch/arm/boot/dts/hisilicon/hip04-d01.dts diff --git a/arch/arm/boot/dts/hip04.dtsi b/arch/arm/boot/dts/hisilicon/hip04.dtsi similarity index 100% rename from arch/arm/boot/dts/hip04.dtsi rename to arch/arm/boot/dts/hisilicon/hip04.dtsi diff --git a/arch/arm/boot/dts/hisi-x5hd2-dkb.dts b/arch/arm/boot/dts/hisilicon/hisi-x5hd2-dkb.dts similarity index 100% rename from arch/arm/boot/dts/hisi-x5hd2-dkb.dts rename to arch/arm/boot/dts/hisilicon/hisi-x5hd2-dkb.dts diff --git a/arch/arm/boot/dts/hisi-x5hd2.dtsi b/arch/arm/boot/dts/hisilicon/hisi-x5hd2.dtsi similarity index 100% rename from arch/arm/boot/dts/hisi-x5hd2.dtsi rename to arch/arm/boot/dts/hisilicon/hisi-x5hd2.dtsi diff --git a/arch/arm/boot/dts/sd5203.dts b/arch/arm/boot/dts/hisilicon/sd5203.dts similarity index 100% rename from arch/arm/boot/dts/sd5203.dts rename to arch/arm/boot/dts/hisilicon/sd5203.dts diff --git a/arch/arm/boot/dts/hpe/Makefile b/arch/arm/boot/dts/hpe/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..e175b1732cdb563fdf1da7f9ad5d141542535338 --- /dev/null +++ b/arch/arm/boot/dts/hpe/Makefile @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0 +dtb-$(CONFIG_ARCH_HPE_GXP) += \ + hpe-bmc-dl360gen10.dtb diff --git a/arch/arm/boot/dts/hpe-bmc-dl360gen10.dts b/arch/arm/boot/dts/hpe/hpe-bmc-dl360gen10.dts similarity index 100% rename from arch/arm/boot/dts/hpe-bmc-dl360gen10.dts rename to arch/arm/boot/dts/hpe/hpe-bmc-dl360gen10.dts diff --git a/arch/arm/boot/dts/hpe-gxp.dtsi b/arch/arm/boot/dts/hpe/hpe-gxp.dtsi similarity index 100% rename from arch/arm/boot/dts/hpe-gxp.dtsi rename to arch/arm/boot/dts/hpe/hpe-gxp.dtsi diff --git a/arch/arm/boot/dts/intel/Makefile b/arch/arm/boot/dts/intel/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..c5fc845deb61c1c59eeff63ed3ba333254731a51 --- /dev/null +++ b/arch/arm/boot/dts/intel/Makefile @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0 +subdir-y += axm +subdir-y += ixp +subdir-y += pxa +subdir-y += socfpga diff --git a/arch/arm/boot/dts/intel/axm/Makefile b/arch/arm/boot/dts/intel/axm/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..7c7dc679964d17f32c5cad1e8f2918786d7ee8d1 --- /dev/null +++ b/arch/arm/boot/dts/intel/axm/Makefile @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0 +dtb-$(CONFIG_ARCH_AXXIA) += \ + axm5516-amarillo.dtb +dtb-$(CONFIG_ARCH_AXXIA) += \ + axm5516-amarillo.dtb diff --git a/arch/arm/boot/dts/axm5516-amarillo.dts b/arch/arm/boot/dts/intel/axm/axm5516-amarillo.dts similarity index 100% rename from arch/arm/boot/dts/axm5516-amarillo.dts rename to arch/arm/boot/dts/intel/axm/axm5516-amarillo.dts diff --git a/arch/arm/boot/dts/axm5516-cpus.dtsi b/arch/arm/boot/dts/intel/axm/axm5516-cpus.dtsi similarity index 100% rename from arch/arm/boot/dts/axm5516-cpus.dtsi rename to arch/arm/boot/dts/intel/axm/axm5516-cpus.dtsi diff --git a/arch/arm/boot/dts/axm55xx.dtsi b/arch/arm/boot/dts/intel/axm/axm55xx.dtsi similarity index 100% rename from arch/arm/boot/dts/axm55xx.dtsi rename to arch/arm/boot/dts/intel/axm/axm55xx.dtsi diff --git a/arch/arm/boot/dts/intel/ixp/Makefile b/arch/arm/boot/dts/intel/ixp/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..1a25ce3cf84f04ada6f6dc5c0f13177c0a220fc8 --- /dev/null +++ b/arch/arm/boot/dts/intel/ixp/Makefile @@ -0,0 +1,19 @@ +# SPDX-License-Identifier: GPL-2.0 +dtb-$(CONFIG_ARCH_IXP4XX) += \ + intel-ixp42x-linksys-nslu2.dtb \ + intel-ixp42x-linksys-wrv54g.dtb \ + intel-ixp42x-freecom-fsg-3.dtb \ + intel-ixp42x-welltech-epbx100.dtb \ + intel-ixp42x-ixdp425.dtb \ + intel-ixp43x-kixrp435.dtb \ + intel-ixp46x-ixdp465.dtb \ + intel-ixp42x-adi-coyote.dtb \ + intel-ixp42x-ixdpg425.dtb \ + intel-ixp42x-goramo-multilink.dtb \ + intel-ixp42x-iomega-nas100d.dtb \ + intel-ixp42x-dlink-dsm-g600.dtb \ + intel-ixp42x-gateworks-gw2348.dtb \ + intel-ixp43x-gateworks-gw2358.dtb \ + intel-ixp42x-netgear-wg302v1.dtb \ + intel-ixp42x-arcom-vulcan.dtb \ + intel-ixp42x-gateway-7001.dtb diff --git a/arch/arm/boot/dts/intel-ixp42x-adi-coyote.dts b/arch/arm/boot/dts/intel/ixp/intel-ixp42x-adi-coyote.dts similarity index 100% rename from arch/arm/boot/dts/intel-ixp42x-adi-coyote.dts rename to arch/arm/boot/dts/intel/ixp/intel-ixp42x-adi-coyote.dts diff --git a/arch/arm/boot/dts/intel-ixp42x-arcom-vulcan.dts b/arch/arm/boot/dts/intel/ixp/intel-ixp42x-arcom-vulcan.dts similarity index 100% rename from arch/arm/boot/dts/intel-ixp42x-arcom-vulcan.dts rename to arch/arm/boot/dts/intel/ixp/intel-ixp42x-arcom-vulcan.dts diff --git a/arch/arm/boot/dts/intel-ixp42x-dlink-dsm-g600.dts b/arch/arm/boot/dts/intel/ixp/intel-ixp42x-dlink-dsm-g600.dts similarity index 100% rename from arch/arm/boot/dts/intel-ixp42x-dlink-dsm-g600.dts rename to arch/arm/boot/dts/intel/ixp/intel-ixp42x-dlink-dsm-g600.dts diff --git a/arch/arm/boot/dts/intel-ixp42x-freecom-fsg-3.dts b/arch/arm/boot/dts/intel/ixp/intel-ixp42x-freecom-fsg-3.dts similarity index 100% rename from arch/arm/boot/dts/intel-ixp42x-freecom-fsg-3.dts rename to arch/arm/boot/dts/intel/ixp/intel-ixp42x-freecom-fsg-3.dts diff --git a/arch/arm/boot/dts/intel-ixp42x-gateway-7001.dts b/arch/arm/boot/dts/intel/ixp/intel-ixp42x-gateway-7001.dts similarity index 100% rename from arch/arm/boot/dts/intel-ixp42x-gateway-7001.dts rename to arch/arm/boot/dts/intel/ixp/intel-ixp42x-gateway-7001.dts diff --git a/arch/arm/boot/dts/intel-ixp42x-gateworks-gw2348.dts b/arch/arm/boot/dts/intel/ixp/intel-ixp42x-gateworks-gw2348.dts similarity index 100% rename from arch/arm/boot/dts/intel-ixp42x-gateworks-gw2348.dts rename to arch/arm/boot/dts/intel/ixp/intel-ixp42x-gateworks-gw2348.dts diff --git a/arch/arm/boot/dts/intel-ixp42x-goramo-multilink.dts b/arch/arm/boot/dts/intel/ixp/intel-ixp42x-goramo-multilink.dts similarity index 100% rename from arch/arm/boot/dts/intel-ixp42x-goramo-multilink.dts rename to arch/arm/boot/dts/intel/ixp/intel-ixp42x-goramo-multilink.dts diff --git a/arch/arm/boot/dts/intel-ixp42x-iomega-nas100d.dts b/arch/arm/boot/dts/intel/ixp/intel-ixp42x-iomega-nas100d.dts similarity index 100% rename from arch/arm/boot/dts/intel-ixp42x-iomega-nas100d.dts rename to arch/arm/boot/dts/intel/ixp/intel-ixp42x-iomega-nas100d.dts diff --git a/arch/arm/boot/dts/intel-ixp42x-ixdp425.dts b/arch/arm/boot/dts/intel/ixp/intel-ixp42x-ixdp425.dts similarity index 100% rename from arch/arm/boot/dts/intel-ixp42x-ixdp425.dts rename to arch/arm/boot/dts/intel/ixp/intel-ixp42x-ixdp425.dts diff --git a/arch/arm/boot/dts/intel-ixp42x-ixdpg425.dts b/arch/arm/boot/dts/intel/ixp/intel-ixp42x-ixdpg425.dts similarity index 100% rename from arch/arm/boot/dts/intel-ixp42x-ixdpg425.dts rename to arch/arm/boot/dts/intel/ixp/intel-ixp42x-ixdpg425.dts diff --git a/arch/arm/boot/dts/intel-ixp42x-linksys-nslu2.dts b/arch/arm/boot/dts/intel/ixp/intel-ixp42x-linksys-nslu2.dts similarity index 100% rename from arch/arm/boot/dts/intel-ixp42x-linksys-nslu2.dts rename to arch/arm/boot/dts/intel/ixp/intel-ixp42x-linksys-nslu2.dts diff --git a/arch/arm/boot/dts/intel-ixp42x-linksys-wrv54g.dts b/arch/arm/boot/dts/intel/ixp/intel-ixp42x-linksys-wrv54g.dts similarity index 100% rename from arch/arm/boot/dts/intel-ixp42x-linksys-wrv54g.dts rename to arch/arm/boot/dts/intel/ixp/intel-ixp42x-linksys-wrv54g.dts diff --git a/arch/arm/boot/dts/intel-ixp42x-netgear-wg302v1.dts b/arch/arm/boot/dts/intel/ixp/intel-ixp42x-netgear-wg302v1.dts similarity index 100% rename from arch/arm/boot/dts/intel-ixp42x-netgear-wg302v1.dts rename to arch/arm/boot/dts/intel/ixp/intel-ixp42x-netgear-wg302v1.dts diff --git a/arch/arm/boot/dts/intel-ixp42x-welltech-epbx100.dts b/arch/arm/boot/dts/intel/ixp/intel-ixp42x-welltech-epbx100.dts similarity index 100% rename from arch/arm/boot/dts/intel-ixp42x-welltech-epbx100.dts rename to arch/arm/boot/dts/intel/ixp/intel-ixp42x-welltech-epbx100.dts diff --git a/arch/arm/boot/dts/intel-ixp42x.dtsi b/arch/arm/boot/dts/intel/ixp/intel-ixp42x.dtsi similarity index 100% rename from arch/arm/boot/dts/intel-ixp42x.dtsi rename to arch/arm/boot/dts/intel/ixp/intel-ixp42x.dtsi diff --git a/arch/arm/boot/dts/intel-ixp43x-gateworks-gw2358.dts b/arch/arm/boot/dts/intel/ixp/intel-ixp43x-gateworks-gw2358.dts similarity index 100% rename from arch/arm/boot/dts/intel-ixp43x-gateworks-gw2358.dts rename to arch/arm/boot/dts/intel/ixp/intel-ixp43x-gateworks-gw2358.dts diff --git a/arch/arm/boot/dts/intel-ixp43x-kixrp435.dts b/arch/arm/boot/dts/intel/ixp/intel-ixp43x-kixrp435.dts similarity index 100% rename from arch/arm/boot/dts/intel-ixp43x-kixrp435.dts rename to arch/arm/boot/dts/intel/ixp/intel-ixp43x-kixrp435.dts diff --git a/arch/arm/boot/dts/intel-ixp43x.dtsi b/arch/arm/boot/dts/intel/ixp/intel-ixp43x.dtsi similarity index 100% rename from arch/arm/boot/dts/intel-ixp43x.dtsi rename to arch/arm/boot/dts/intel/ixp/intel-ixp43x.dtsi diff --git a/arch/arm/boot/dts/intel-ixp45x-ixp46x.dtsi b/arch/arm/boot/dts/intel/ixp/intel-ixp45x-ixp46x.dtsi similarity index 100% rename from arch/arm/boot/dts/intel-ixp45x-ixp46x.dtsi rename to arch/arm/boot/dts/intel/ixp/intel-ixp45x-ixp46x.dtsi diff --git a/arch/arm/boot/dts/intel-ixp46x-ixdp465.dts b/arch/arm/boot/dts/intel/ixp/intel-ixp46x-ixdp465.dts similarity index 100% rename from arch/arm/boot/dts/intel-ixp46x-ixdp465.dts rename to arch/arm/boot/dts/intel/ixp/intel-ixp46x-ixdp465.dts diff --git a/arch/arm/boot/dts/intel-ixp4xx-reference-design.dtsi b/arch/arm/boot/dts/intel/ixp/intel-ixp4xx-reference-design.dtsi similarity index 100% rename from arch/arm/boot/dts/intel-ixp4xx-reference-design.dtsi rename to arch/arm/boot/dts/intel/ixp/intel-ixp4xx-reference-design.dtsi diff --git a/arch/arm/boot/dts/intel-ixp4xx.dtsi b/arch/arm/boot/dts/intel/ixp/intel-ixp4xx.dtsi similarity index 100% rename from arch/arm/boot/dts/intel-ixp4xx.dtsi rename to arch/arm/boot/dts/intel/ixp/intel-ixp4xx.dtsi diff --git a/arch/arm/boot/dts/intel/pxa/Makefile b/arch/arm/boot/dts/intel/pxa/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..24d5240f08e7e263c621f2d78c5b6b3ceccfbf86 --- /dev/null +++ b/arch/arm/boot/dts/intel/pxa/Makefile @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: GPL-2.0 +dtb-$(CONFIG_ARCH_PXA) += \ + pxa300-raumfeld-connector.dtb \ + pxa300-raumfeld-controller.dtb \ + pxa300-raumfeld-speaker-l.dtb \ + pxa300-raumfeld-speaker-m.dtb \ + pxa300-raumfeld-speaker-one.dtb \ + pxa300-raumfeld-speaker-s.dtb diff --git a/arch/arm/boot/dts/pxa25x.dtsi b/arch/arm/boot/dts/intel/pxa/pxa25x.dtsi similarity index 100% rename from arch/arm/boot/dts/pxa25x.dtsi rename to arch/arm/boot/dts/intel/pxa/pxa25x.dtsi diff --git a/arch/arm/boot/dts/pxa27x.dtsi b/arch/arm/boot/dts/intel/pxa/pxa27x.dtsi similarity index 100% rename from arch/arm/boot/dts/pxa27x.dtsi rename to arch/arm/boot/dts/intel/pxa/pxa27x.dtsi diff --git a/arch/arm/boot/dts/pxa2xx.dtsi b/arch/arm/boot/dts/intel/pxa/pxa2xx.dtsi similarity index 100% rename from arch/arm/boot/dts/pxa2xx.dtsi rename to arch/arm/boot/dts/intel/pxa/pxa2xx.dtsi diff --git a/arch/arm/boot/dts/pxa300-raumfeld-common.dtsi b/arch/arm/boot/dts/intel/pxa/pxa300-raumfeld-common.dtsi similarity index 100% rename from arch/arm/boot/dts/pxa300-raumfeld-common.dtsi rename to arch/arm/boot/dts/intel/pxa/pxa300-raumfeld-common.dtsi diff --git a/arch/arm/boot/dts/pxa300-raumfeld-connector.dts b/arch/arm/boot/dts/intel/pxa/pxa300-raumfeld-connector.dts similarity index 100% rename from arch/arm/boot/dts/pxa300-raumfeld-connector.dts rename to arch/arm/boot/dts/intel/pxa/pxa300-raumfeld-connector.dts diff --git a/arch/arm/boot/dts/pxa300-raumfeld-controller.dts b/arch/arm/boot/dts/intel/pxa/pxa300-raumfeld-controller.dts similarity index 100% rename from arch/arm/boot/dts/pxa300-raumfeld-controller.dts rename to arch/arm/boot/dts/intel/pxa/pxa300-raumfeld-controller.dts diff --git a/arch/arm/boot/dts/pxa300-raumfeld-speaker-l.dts b/arch/arm/boot/dts/intel/pxa/pxa300-raumfeld-speaker-l.dts similarity index 100% rename from arch/arm/boot/dts/pxa300-raumfeld-speaker-l.dts rename to arch/arm/boot/dts/intel/pxa/pxa300-raumfeld-speaker-l.dts diff --git a/arch/arm/boot/dts/pxa300-raumfeld-speaker-m.dts b/arch/arm/boot/dts/intel/pxa/pxa300-raumfeld-speaker-m.dts similarity index 100% rename from arch/arm/boot/dts/pxa300-raumfeld-speaker-m.dts rename to arch/arm/boot/dts/intel/pxa/pxa300-raumfeld-speaker-m.dts diff --git a/arch/arm/boot/dts/pxa300-raumfeld-speaker-one.dts b/arch/arm/boot/dts/intel/pxa/pxa300-raumfeld-speaker-one.dts similarity index 100% rename from arch/arm/boot/dts/pxa300-raumfeld-speaker-one.dts rename to arch/arm/boot/dts/intel/pxa/pxa300-raumfeld-speaker-one.dts diff --git a/arch/arm/boot/dts/pxa300-raumfeld-speaker-s.dts b/arch/arm/boot/dts/intel/pxa/pxa300-raumfeld-speaker-s.dts similarity index 100% rename from arch/arm/boot/dts/pxa300-raumfeld-speaker-s.dts rename to arch/arm/boot/dts/intel/pxa/pxa300-raumfeld-speaker-s.dts diff --git a/arch/arm/boot/dts/pxa300-raumfeld-tuneable-clock.dtsi b/arch/arm/boot/dts/intel/pxa/pxa300-raumfeld-tuneable-clock.dtsi similarity index 100% rename from arch/arm/boot/dts/pxa300-raumfeld-tuneable-clock.dtsi rename to arch/arm/boot/dts/intel/pxa/pxa300-raumfeld-tuneable-clock.dtsi diff --git a/arch/arm/boot/dts/pxa3xx.dtsi b/arch/arm/boot/dts/intel/pxa/pxa3xx.dtsi similarity index 100% rename from arch/arm/boot/dts/pxa3xx.dtsi rename to arch/arm/boot/dts/intel/pxa/pxa3xx.dtsi diff --git a/arch/arm/boot/dts/intel/socfpga/Makefile b/arch/arm/boot/dts/intel/socfpga/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..c467828aeb4b0a78c409c41d8656f291c3ab54f4 --- /dev/null +++ b/arch/arm/boot/dts/intel/socfpga/Makefile @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: GPL-2.0 +dtb-$(CONFIG_ARCH_INTEL_SOCFPGA) += \ + socfpga_arria5_socdk.dtb \ + socfpga_arria10_chameleonv3.dtb \ + socfpga_arria10_mercury_pe1.dtb \ + socfpga_arria10_socdk_nand.dtb \ + socfpga_arria10_socdk_qspi.dtb \ + socfpga_arria10_socdk_sdmmc.dtb \ + socfpga_cyclone5_chameleon96.dtb \ + socfpga_cyclone5_mcvevk.dtb \ + socfpga_cyclone5_socdk.dtb \ + socfpga_cyclone5_de0_nano_soc.dtb \ + socfpga_cyclone5_sockit.dtb \ + socfpga_cyclone5_socrates.dtb \ + socfpga_cyclone5_sodia.dtb \ + socfpga_cyclone5_vining_fpga.dtb \ + socfpga_vt.dtb diff --git a/arch/arm/boot/dts/socfpga.dtsi b/arch/arm/boot/dts/intel/socfpga/socfpga.dtsi similarity index 100% rename from arch/arm/boot/dts/socfpga.dtsi rename to arch/arm/boot/dts/intel/socfpga/socfpga.dtsi diff --git a/arch/arm/boot/dts/socfpga_arria10.dtsi b/arch/arm/boot/dts/intel/socfpga/socfpga_arria10.dtsi similarity index 100% rename from arch/arm/boot/dts/socfpga_arria10.dtsi rename to arch/arm/boot/dts/intel/socfpga/socfpga_arria10.dtsi diff --git a/arch/arm/boot/dts/socfpga_arria10_chameleonv3.dts b/arch/arm/boot/dts/intel/socfpga/socfpga_arria10_chameleonv3.dts similarity index 100% rename from arch/arm/boot/dts/socfpga_arria10_chameleonv3.dts rename to arch/arm/boot/dts/intel/socfpga/socfpga_arria10_chameleonv3.dts diff --git a/arch/arm/boot/dts/socfpga_arria10_mercury_aa1.dtsi b/arch/arm/boot/dts/intel/socfpga/socfpga_arria10_mercury_aa1.dtsi similarity index 100% rename from arch/arm/boot/dts/socfpga_arria10_mercury_aa1.dtsi rename to arch/arm/boot/dts/intel/socfpga/socfpga_arria10_mercury_aa1.dtsi diff --git a/arch/arm/boot/dts/socfpga_arria10_mercury_pe1.dts b/arch/arm/boot/dts/intel/socfpga/socfpga_arria10_mercury_pe1.dts similarity index 100% rename from arch/arm/boot/dts/socfpga_arria10_mercury_pe1.dts rename to arch/arm/boot/dts/intel/socfpga/socfpga_arria10_mercury_pe1.dts diff --git a/arch/arm/boot/dts/socfpga_arria10_socdk.dtsi b/arch/arm/boot/dts/intel/socfpga/socfpga_arria10_socdk.dtsi similarity index 100% rename from arch/arm/boot/dts/socfpga_arria10_socdk.dtsi rename to arch/arm/boot/dts/intel/socfpga/socfpga_arria10_socdk.dtsi diff --git a/arch/arm/boot/dts/socfpga_arria10_socdk_nand.dts b/arch/arm/boot/dts/intel/socfpga/socfpga_arria10_socdk_nand.dts similarity index 100% rename from arch/arm/boot/dts/socfpga_arria10_socdk_nand.dts rename to arch/arm/boot/dts/intel/socfpga/socfpga_arria10_socdk_nand.dts diff --git a/arch/arm/boot/dts/socfpga_arria10_socdk_qspi.dts b/arch/arm/boot/dts/intel/socfpga/socfpga_arria10_socdk_qspi.dts similarity index 100% rename from arch/arm/boot/dts/socfpga_arria10_socdk_qspi.dts rename to arch/arm/boot/dts/intel/socfpga/socfpga_arria10_socdk_qspi.dts diff --git a/arch/arm/boot/dts/socfpga_arria10_socdk_sdmmc.dts b/arch/arm/boot/dts/intel/socfpga/socfpga_arria10_socdk_sdmmc.dts similarity index 100% rename from arch/arm/boot/dts/socfpga_arria10_socdk_sdmmc.dts rename to arch/arm/boot/dts/intel/socfpga/socfpga_arria10_socdk_sdmmc.dts diff --git a/arch/arm/boot/dts/socfpga_arria5.dtsi b/arch/arm/boot/dts/intel/socfpga/socfpga_arria5.dtsi similarity index 100% rename from arch/arm/boot/dts/socfpga_arria5.dtsi rename to arch/arm/boot/dts/intel/socfpga/socfpga_arria5.dtsi diff --git a/arch/arm/boot/dts/socfpga_arria5_socdk.dts b/arch/arm/boot/dts/intel/socfpga/socfpga_arria5_socdk.dts similarity index 100% rename from arch/arm/boot/dts/socfpga_arria5_socdk.dts rename to arch/arm/boot/dts/intel/socfpga/socfpga_arria5_socdk.dts diff --git a/arch/arm/boot/dts/socfpga_cyclone5.dtsi b/arch/arm/boot/dts/intel/socfpga/socfpga_cyclone5.dtsi similarity index 100% rename from arch/arm/boot/dts/socfpga_cyclone5.dtsi rename to arch/arm/boot/dts/intel/socfpga/socfpga_cyclone5.dtsi diff --git a/arch/arm/boot/dts/socfpga_cyclone5_chameleon96.dts b/arch/arm/boot/dts/intel/socfpga/socfpga_cyclone5_chameleon96.dts similarity index 100% rename from arch/arm/boot/dts/socfpga_cyclone5_chameleon96.dts rename to arch/arm/boot/dts/intel/socfpga/socfpga_cyclone5_chameleon96.dts diff --git a/arch/arm/boot/dts/socfpga_cyclone5_de0_nano_soc.dts b/arch/arm/boot/dts/intel/socfpga/socfpga_cyclone5_de0_nano_soc.dts similarity index 100% rename from arch/arm/boot/dts/socfpga_cyclone5_de0_nano_soc.dts rename to arch/arm/boot/dts/intel/socfpga/socfpga_cyclone5_de0_nano_soc.dts diff --git a/arch/arm/boot/dts/socfpga_cyclone5_mcv.dtsi b/arch/arm/boot/dts/intel/socfpga/socfpga_cyclone5_mcv.dtsi similarity index 100% rename from arch/arm/boot/dts/socfpga_cyclone5_mcv.dtsi rename to arch/arm/boot/dts/intel/socfpga/socfpga_cyclone5_mcv.dtsi diff --git a/arch/arm/boot/dts/socfpga_cyclone5_mcvevk.dts b/arch/arm/boot/dts/intel/socfpga/socfpga_cyclone5_mcvevk.dts similarity index 100% rename from arch/arm/boot/dts/socfpga_cyclone5_mcvevk.dts rename to arch/arm/boot/dts/intel/socfpga/socfpga_cyclone5_mcvevk.dts diff --git a/arch/arm/boot/dts/socfpga_cyclone5_socdk.dts b/arch/arm/boot/dts/intel/socfpga/socfpga_cyclone5_socdk.dts similarity index 100% rename from arch/arm/boot/dts/socfpga_cyclone5_socdk.dts rename to arch/arm/boot/dts/intel/socfpga/socfpga_cyclone5_socdk.dts diff --git a/arch/arm/boot/dts/socfpga_cyclone5_sockit.dts b/arch/arm/boot/dts/intel/socfpga/socfpga_cyclone5_sockit.dts similarity index 100% rename from arch/arm/boot/dts/socfpga_cyclone5_sockit.dts rename to arch/arm/boot/dts/intel/socfpga/socfpga_cyclone5_sockit.dts diff --git a/arch/arm/boot/dts/socfpga_cyclone5_socrates.dts b/arch/arm/boot/dts/intel/socfpga/socfpga_cyclone5_socrates.dts similarity index 100% rename from arch/arm/boot/dts/socfpga_cyclone5_socrates.dts rename to arch/arm/boot/dts/intel/socfpga/socfpga_cyclone5_socrates.dts diff --git a/arch/arm/boot/dts/socfpga_cyclone5_sodia.dts b/arch/arm/boot/dts/intel/socfpga/socfpga_cyclone5_sodia.dts similarity index 100% rename from arch/arm/boot/dts/socfpga_cyclone5_sodia.dts rename to arch/arm/boot/dts/intel/socfpga/socfpga_cyclone5_sodia.dts diff --git a/arch/arm/boot/dts/socfpga_cyclone5_vining_fpga.dts b/arch/arm/boot/dts/intel/socfpga/socfpga_cyclone5_vining_fpga.dts similarity index 100% rename from arch/arm/boot/dts/socfpga_cyclone5_vining_fpga.dts rename to arch/arm/boot/dts/intel/socfpga/socfpga_cyclone5_vining_fpga.dts diff --git a/arch/arm/boot/dts/socfpga_vt.dts b/arch/arm/boot/dts/intel/socfpga/socfpga_vt.dts similarity index 100% rename from arch/arm/boot/dts/socfpga_vt.dts rename to arch/arm/boot/dts/intel/socfpga/socfpga_vt.dts diff --git a/arch/arm/boot/dts/marvell/Makefile b/arch/arm/boot/dts/marvell/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..1e0f5ff492f7857ee19343a2c7513592919a30eb --- /dev/null +++ b/arch/arm/boot/dts/marvell/Makefile @@ -0,0 +1,165 @@ +# SPDX-License-Identifier: GPL-2.0 +dtb-$(CONFIG_ARCH_MMP) += \ + pxa168-aspenite.dtb \ + pxa910-dkb.dtb \ + mmp2-brownstone.dtb \ + mmp2-olpc-xo-1-75.dtb \ + mmp3-dell-ariel.dtb +dtb-$(CONFIG_ARCH_ORION5X) += \ + orion5x-kuroboxpro.dtb \ + orion5x-lacie-d2-network.dtb \ + orion5x-lacie-ethernet-disk-mini-v2.dtb \ + orion5x-linkstation-lsgl.dtb \ + orion5x-linkstation-lswtgl.dtb \ + orion5x-linkstation-lschl.dtb \ + orion5x-lswsgl.dtb \ + orion5x-maxtor-shared-storage-2.dtb \ + orion5x-netgear-wnr854t.dtb \ + orion5x-rd88f5182-nas.dtb +dtb-$(CONFIG_MACH_ARMADA_370) += \ + armada-370-c200-v2.dtb \ + armada-370-db.dtb \ + armada-370-dlink-dns327l.dtb \ + armada-370-mirabox.dtb \ + armada-370-netgear-rn102.dtb \ + armada-370-netgear-rn104.dtb \ + armada-370-rd.dtb \ + armada-370-seagate-nas-2bay.dtb \ + armada-370-seagate-nas-4bay.dtb \ + armada-370-seagate-personal-cloud.dtb \ + armada-370-seagate-personal-cloud-2bay.dtb \ + armada-370-synology-ds213j.dtb +dtb-$(CONFIG_MACH_ARMADA_375) += \ + armada-375-db.dtb +dtb-$(CONFIG_MACH_ARMADA_38X) += \ + armada-381-netgear-gs110emx.dtb \ + armada-382-rd-ac3x-48g4x2xl.dtb \ + armada-385-atl-x530.dtb \ + armada-385-clearfog-gtr-s4.dtb \ + armada-385-clearfog-gtr-l8.dtb \ + armada-385-db-88f6820-amc.dtb \ + armada-385-db-ap.dtb \ + armada-385-linksys-caiman.dtb \ + armada-385-linksys-cobra.dtb \ + armada-385-linksys-rango.dtb \ + armada-385-linksys-shelby.dtb \ + armada-385-synology-ds116.dtb \ + armada-385-turris-omnia.dtb \ + armada-388-clearfog.dtb \ + armada-388-clearfog-base.dtb \ + armada-388-clearfog-pro.dtb \ + armada-388-db.dtb \ + armada-388-gp.dtb \ + armada-388-helios4.dtb \ + armada-388-rd.dtb +dtb-$(CONFIG_MACH_ARMADA_39X) += \ + armada-390-db.dtb \ + armada-395-gp.dtb \ + armada-398-db.dtb +dtb-$(CONFIG_MACH_ARMADA_XP) += \ + armada-xp-axpwifiap.dtb \ + armada-xp-crs305-1g-4s.dtb \ + armada-xp-crs305-1g-4s-bit.dtb \ + armada-xp-crs326-24g-2s.dtb \ + armada-xp-crs326-24g-2s-bit.dtb \ + armada-xp-crs328-4c-20s-4s.dtb \ + armada-xp-crs328-4c-20s-4s-bit.dtb \ + armada-xp-db.dtb \ + armada-xp-db-dxbc2.dtb \ + armada-xp-db-xc3-24g4xg.dtb \ + armada-xp-gp.dtb \ + armada-xp-lenovo-ix4-300d.dtb \ + armada-xp-linksys-mamba.dtb \ + armada-xp-matrix.dtb \ + armada-xp-netgear-rn2120.dtb \ + armada-xp-openblocks-ax3-4.dtb \ + armada-xp-synology-ds414.dtb +dtb-$(CONFIG_MACH_DOVE) += \ + dove-cubox.dtb \ + dove-cubox-es.dtb \ + dove-d2plug.dtb \ + dove-d3plug.dtb \ + dove-dove-db.dtb \ + dove-sbc-a510.dtb +dtb-$(CONFIG_MACH_KIRKWOOD) += \ + kirkwood-4i-edge-200.dtb \ + kirkwood-b3.dtb \ + kirkwood-blackarmor-nas220.dtb \ + kirkwood-c200-v1.dtb \ + kirkwood-cloudbox.dtb \ + kirkwood-d2net.dtb \ + kirkwood-db-88f6281.dtb \ + kirkwood-db-88f6282.dtb \ + kirkwood-dir665.dtb \ + kirkwood-dns320.dtb \ + kirkwood-dns325.dtb \ + kirkwood-dockstar.dtb \ + kirkwood-dreamplug.dtb \ + kirkwood-ds109.dtb \ + kirkwood-ds110jv10.dtb \ + kirkwood-ds111.dtb \ + kirkwood-ds112.dtb \ + kirkwood-ds209.dtb \ + kirkwood-ds210.dtb \ + kirkwood-ds212.dtb \ + kirkwood-ds212j.dtb \ + kirkwood-ds409.dtb \ + kirkwood-ds409slim.dtb \ + kirkwood-ds411.dtb \ + kirkwood-ds411j.dtb \ + kirkwood-ds411slim.dtb \ + kirkwood-goflexnet.dtb \ + kirkwood-guruplug-server-plus.dtb \ + kirkwood-ib62x0.dtb \ + kirkwood-iconnect.dtb \ + kirkwood-iomega_ix2_200.dtb \ + kirkwood-is2.dtb \ + kirkwood-km_fixedeth.dtb \ + kirkwood-km_kirkwood.dtb \ + kirkwood-l-50.dtb \ + kirkwood-laplug.dtb \ + kirkwood-linkstation-lsqvl.dtb \ + kirkwood-linkstation-lsvl.dtb \ + kirkwood-linkstation-lswsxl.dtb \ + kirkwood-linkstation-lswvl.dtb \ + kirkwood-linkstation-lswxl.dtb \ + kirkwood-linksys-viper.dtb \ + kirkwood-lschlv2.dtb \ + kirkwood-lsxhl.dtb \ + kirkwood-mplcec4.dtb \ + kirkwood-mv88f6281gtw-ge.dtb \ + kirkwood-nas2big.dtb \ + kirkwood-net2big.dtb \ + kirkwood-net5big.dtb \ + kirkwood-netgear_readynas_duo_v2.dtb \ + kirkwood-netgear_readynas_nv+_v2.dtb \ + kirkwood-ns2.dtb \ + kirkwood-ns2lite.dtb \ + kirkwood-ns2max.dtb \ + kirkwood-ns2mini.dtb \ + kirkwood-nsa310.dtb \ + kirkwood-nsa310a.dtb \ + kirkwood-nsa310s.dtb \ + kirkwood-nsa320.dtb \ + kirkwood-nsa325.dtb \ + kirkwood-openblocks_a6.dtb \ + kirkwood-openblocks_a7.dtb \ + kirkwood-openrd-base.dtb \ + kirkwood-openrd-client.dtb \ + kirkwood-openrd-ultimate.dtb \ + kirkwood-pogo_e02.dtb \ + kirkwood-pogoplug-series-4.dtb \ + kirkwood-rd88f6192.dtb \ + kirkwood-rd88f6281-z0.dtb \ + kirkwood-rd88f6281-a.dtb \ + kirkwood-rs212.dtb \ + kirkwood-rs409.dtb \ + kirkwood-rs411.dtb \ + kirkwood-sheevaplug.dtb \ + kirkwood-sheevaplug-esata.dtb \ + kirkwood-t5325.dtb \ + kirkwood-topkick.dtb \ + kirkwood-ts219-6281.dtb \ + kirkwood-ts219-6282.dtb \ + kirkwood-ts419-6281.dtb \ + kirkwood-ts419-6282.dtb diff --git a/arch/arm/boot/dts/armada-370-c200-v2.dts b/arch/arm/boot/dts/marvell/armada-370-c200-v2.dts similarity index 100% rename from arch/arm/boot/dts/armada-370-c200-v2.dts rename to arch/arm/boot/dts/marvell/armada-370-c200-v2.dts diff --git a/arch/arm/boot/dts/armada-370-db.dts b/arch/arm/boot/dts/marvell/armada-370-db.dts similarity index 100% rename from arch/arm/boot/dts/armada-370-db.dts rename to arch/arm/boot/dts/marvell/armada-370-db.dts diff --git a/arch/arm/boot/dts/armada-370-dlink-dns327l.dts b/arch/arm/boot/dts/marvell/armada-370-dlink-dns327l.dts similarity index 100% rename from arch/arm/boot/dts/armada-370-dlink-dns327l.dts rename to arch/arm/boot/dts/marvell/armada-370-dlink-dns327l.dts diff --git a/arch/arm/boot/dts/armada-370-mirabox.dts b/arch/arm/boot/dts/marvell/armada-370-mirabox.dts similarity index 100% rename from arch/arm/boot/dts/armada-370-mirabox.dts rename to arch/arm/boot/dts/marvell/armada-370-mirabox.dts diff --git a/arch/arm/boot/dts/armada-370-netgear-rn102.dts b/arch/arm/boot/dts/marvell/armada-370-netgear-rn102.dts similarity index 100% rename from arch/arm/boot/dts/armada-370-netgear-rn102.dts rename to arch/arm/boot/dts/marvell/armada-370-netgear-rn102.dts diff --git a/arch/arm/boot/dts/armada-370-netgear-rn104.dts b/arch/arm/boot/dts/marvell/armada-370-netgear-rn104.dts similarity index 100% rename from arch/arm/boot/dts/armada-370-netgear-rn104.dts rename to arch/arm/boot/dts/marvell/armada-370-netgear-rn104.dts diff --git a/arch/arm/boot/dts/armada-370-rd.dts b/arch/arm/boot/dts/marvell/armada-370-rd.dts similarity index 100% rename from arch/arm/boot/dts/armada-370-rd.dts rename to arch/arm/boot/dts/marvell/armada-370-rd.dts diff --git a/arch/arm/boot/dts/armada-370-seagate-nas-2bay.dts b/arch/arm/boot/dts/marvell/armada-370-seagate-nas-2bay.dts similarity index 100% rename from arch/arm/boot/dts/armada-370-seagate-nas-2bay.dts rename to arch/arm/boot/dts/marvell/armada-370-seagate-nas-2bay.dts diff --git a/arch/arm/boot/dts/armada-370-seagate-nas-4bay.dts b/arch/arm/boot/dts/marvell/armada-370-seagate-nas-4bay.dts similarity index 100% rename from arch/arm/boot/dts/armada-370-seagate-nas-4bay.dts rename to arch/arm/boot/dts/marvell/armada-370-seagate-nas-4bay.dts diff --git a/arch/arm/boot/dts/armada-370-seagate-nas-xbay.dtsi b/arch/arm/boot/dts/marvell/armada-370-seagate-nas-xbay.dtsi similarity index 100% rename from arch/arm/boot/dts/armada-370-seagate-nas-xbay.dtsi rename to arch/arm/boot/dts/marvell/armada-370-seagate-nas-xbay.dtsi diff --git a/arch/arm/boot/dts/armada-370-seagate-personal-cloud-2bay.dts b/arch/arm/boot/dts/marvell/armada-370-seagate-personal-cloud-2bay.dts similarity index 100% rename from arch/arm/boot/dts/armada-370-seagate-personal-cloud-2bay.dts rename to arch/arm/boot/dts/marvell/armada-370-seagate-personal-cloud-2bay.dts diff --git a/arch/arm/boot/dts/armada-370-seagate-personal-cloud.dts b/arch/arm/boot/dts/marvell/armada-370-seagate-personal-cloud.dts similarity index 100% rename from arch/arm/boot/dts/armada-370-seagate-personal-cloud.dts rename to arch/arm/boot/dts/marvell/armada-370-seagate-personal-cloud.dts diff --git a/arch/arm/boot/dts/armada-370-seagate-personal-cloud.dtsi b/arch/arm/boot/dts/marvell/armada-370-seagate-personal-cloud.dtsi similarity index 100% rename from arch/arm/boot/dts/armada-370-seagate-personal-cloud.dtsi rename to arch/arm/boot/dts/marvell/armada-370-seagate-personal-cloud.dtsi diff --git a/arch/arm/boot/dts/armada-370-synology-ds213j.dts b/arch/arm/boot/dts/marvell/armada-370-synology-ds213j.dts similarity index 100% rename from arch/arm/boot/dts/armada-370-synology-ds213j.dts rename to arch/arm/boot/dts/marvell/armada-370-synology-ds213j.dts diff --git a/arch/arm/boot/dts/armada-370-xp.dtsi b/arch/arm/boot/dts/marvell/armada-370-xp.dtsi similarity index 100% rename from arch/arm/boot/dts/armada-370-xp.dtsi rename to arch/arm/boot/dts/marvell/armada-370-xp.dtsi diff --git a/arch/arm/boot/dts/armada-370.dtsi b/arch/arm/boot/dts/marvell/armada-370.dtsi similarity index 100% rename from arch/arm/boot/dts/armada-370.dtsi rename to arch/arm/boot/dts/marvell/armada-370.dtsi diff --git a/arch/arm/boot/dts/armada-375-db.dts b/arch/arm/boot/dts/marvell/armada-375-db.dts similarity index 100% rename from arch/arm/boot/dts/armada-375-db.dts rename to arch/arm/boot/dts/marvell/armada-375-db.dts diff --git a/arch/arm/boot/dts/armada-375.dtsi b/arch/arm/boot/dts/marvell/armada-375.dtsi similarity index 100% rename from arch/arm/boot/dts/armada-375.dtsi rename to arch/arm/boot/dts/marvell/armada-375.dtsi diff --git a/arch/arm/boot/dts/armada-380.dtsi b/arch/arm/boot/dts/marvell/armada-380.dtsi similarity index 100% rename from arch/arm/boot/dts/armada-380.dtsi rename to arch/arm/boot/dts/marvell/armada-380.dtsi diff --git a/arch/arm/boot/dts/armada-381-netgear-gs110emx.dts b/arch/arm/boot/dts/marvell/armada-381-netgear-gs110emx.dts similarity index 100% rename from arch/arm/boot/dts/armada-381-netgear-gs110emx.dts rename to arch/arm/boot/dts/marvell/armada-381-netgear-gs110emx.dts diff --git a/arch/arm/boot/dts/armada-382-rd-ac3x-48g4x2xl.dts b/arch/arm/boot/dts/marvell/armada-382-rd-ac3x-48g4x2xl.dts similarity index 100% rename from arch/arm/boot/dts/armada-382-rd-ac3x-48g4x2xl.dts rename to arch/arm/boot/dts/marvell/armada-382-rd-ac3x-48g4x2xl.dts diff --git a/arch/arm/boot/dts/armada-385-atl-x530.dts b/arch/arm/boot/dts/marvell/armada-385-atl-x530.dts similarity index 96% rename from arch/arm/boot/dts/armada-385-atl-x530.dts rename to arch/arm/boot/dts/marvell/armada-385-atl-x530.dts index 241f5d7c80e9a30e2286dff1281262f647239dad..5a9ab8410b7b6ee130c3db005bb1b518d73861fd 100644 --- a/arch/arm/boot/dts/armada-385-atl-x530.dts +++ b/arch/arm/boot/dts/marvell/armada-385-atl-x530.dts @@ -179,19 +179,19 @@ compatible = "fixed-partitions"; #address-cells = <1>; #size-cells = <1>; - partition@u-boot { + partition@0 { reg = <0x00000000 0x00100000>; label = "u-boot"; }; - partition@u-boot-env { + partition@100000 { reg = <0x00100000 0x00040000>; label = "u-boot-env"; }; - partition@unused { + partition@140000 { reg = <0x00140000 0x00e80000>; label = "unused"; }; - partition@idprom { + partition@fc0000 { reg = <0x00fc0000 0x00040000>; label = "idprom"; }; @@ -216,16 +216,16 @@ compatible = "fixed-partitions"; #address-cells = <1>; #size-cells = <1>; - partition@user { + partition@0 { reg = <0x00000000 0x0f000000>; label = "user"; }; - partition@errlog { + partition@f000000 { /* Maximum mtdoops size is 8MB, so set to that. */ reg = <0x0f000000 0x00800000>; label = "errlog"; }; - partition@nand-bbt { + partition@f800000 { reg = <0x0f800000 0x00800000>; label = "nand-bbt"; }; diff --git a/arch/arm/boot/dts/armada-385-clearfog-gtr-l8.dts b/arch/arm/boot/dts/marvell/armada-385-clearfog-gtr-l8.dts similarity index 100% rename from arch/arm/boot/dts/armada-385-clearfog-gtr-l8.dts rename to arch/arm/boot/dts/marvell/armada-385-clearfog-gtr-l8.dts diff --git a/arch/arm/boot/dts/armada-385-clearfog-gtr-s4.dts b/arch/arm/boot/dts/marvell/armada-385-clearfog-gtr-s4.dts similarity index 100% rename from arch/arm/boot/dts/armada-385-clearfog-gtr-s4.dts rename to arch/arm/boot/dts/marvell/armada-385-clearfog-gtr-s4.dts diff --git a/arch/arm/boot/dts/armada-385-clearfog-gtr.dtsi b/arch/arm/boot/dts/marvell/armada-385-clearfog-gtr.dtsi similarity index 100% rename from arch/arm/boot/dts/armada-385-clearfog-gtr.dtsi rename to arch/arm/boot/dts/marvell/armada-385-clearfog-gtr.dtsi diff --git a/arch/arm/boot/dts/armada-385-db-88f6820-amc.dts b/arch/arm/boot/dts/marvell/armada-385-db-88f6820-amc.dts similarity index 100% rename from arch/arm/boot/dts/armada-385-db-88f6820-amc.dts rename to arch/arm/boot/dts/marvell/armada-385-db-88f6820-amc.dts diff --git a/arch/arm/boot/dts/armada-385-db-ap.dts b/arch/arm/boot/dts/marvell/armada-385-db-ap.dts similarity index 100% rename from arch/arm/boot/dts/armada-385-db-ap.dts rename to arch/arm/boot/dts/marvell/armada-385-db-ap.dts diff --git a/arch/arm/boot/dts/armada-385-linksys-caiman.dts b/arch/arm/boot/dts/marvell/armada-385-linksys-caiman.dts similarity index 100% rename from arch/arm/boot/dts/armada-385-linksys-caiman.dts rename to arch/arm/boot/dts/marvell/armada-385-linksys-caiman.dts diff --git a/arch/arm/boot/dts/armada-385-linksys-cobra.dts b/arch/arm/boot/dts/marvell/armada-385-linksys-cobra.dts similarity index 100% rename from arch/arm/boot/dts/armada-385-linksys-cobra.dts rename to arch/arm/boot/dts/marvell/armada-385-linksys-cobra.dts diff --git a/arch/arm/boot/dts/armada-385-linksys-rango.dts b/arch/arm/boot/dts/marvell/armada-385-linksys-rango.dts similarity index 100% rename from arch/arm/boot/dts/armada-385-linksys-rango.dts rename to arch/arm/boot/dts/marvell/armada-385-linksys-rango.dts diff --git a/arch/arm/boot/dts/armada-385-linksys-shelby.dts b/arch/arm/boot/dts/marvell/armada-385-linksys-shelby.dts similarity index 100% rename from arch/arm/boot/dts/armada-385-linksys-shelby.dts rename to arch/arm/boot/dts/marvell/armada-385-linksys-shelby.dts diff --git a/arch/arm/boot/dts/armada-385-linksys.dtsi b/arch/arm/boot/dts/marvell/armada-385-linksys.dtsi similarity index 100% rename from arch/arm/boot/dts/armada-385-linksys.dtsi rename to arch/arm/boot/dts/marvell/armada-385-linksys.dtsi diff --git a/arch/arm/boot/dts/armada-385-synology-ds116.dts b/arch/arm/boot/dts/marvell/armada-385-synology-ds116.dts similarity index 100% rename from arch/arm/boot/dts/armada-385-synology-ds116.dts rename to arch/arm/boot/dts/marvell/armada-385-synology-ds116.dts diff --git a/arch/arm/boot/dts/armada-385-turris-omnia.dts b/arch/arm/boot/dts/marvell/armada-385-turris-omnia.dts similarity index 100% rename from arch/arm/boot/dts/armada-385-turris-omnia.dts rename to arch/arm/boot/dts/marvell/armada-385-turris-omnia.dts diff --git a/arch/arm/boot/dts/armada-385.dtsi b/arch/arm/boot/dts/marvell/armada-385.dtsi similarity index 100% rename from arch/arm/boot/dts/armada-385.dtsi rename to arch/arm/boot/dts/marvell/armada-385.dtsi diff --git a/arch/arm/boot/dts/armada-388-clearfog-base.dts b/arch/arm/boot/dts/marvell/armada-388-clearfog-base.dts similarity index 100% rename from arch/arm/boot/dts/armada-388-clearfog-base.dts rename to arch/arm/boot/dts/marvell/armada-388-clearfog-base.dts diff --git a/arch/arm/boot/dts/armada-388-clearfog-pro.dts b/arch/arm/boot/dts/marvell/armada-388-clearfog-pro.dts similarity index 100% rename from arch/arm/boot/dts/armada-388-clearfog-pro.dts rename to arch/arm/boot/dts/marvell/armada-388-clearfog-pro.dts diff --git a/arch/arm/boot/dts/armada-388-clearfog.dts b/arch/arm/boot/dts/marvell/armada-388-clearfog.dts similarity index 97% rename from arch/arm/boot/dts/armada-388-clearfog.dts rename to arch/arm/boot/dts/marvell/armada-388-clearfog.dts index 95299167dcf580e4a6e251d7b6bfee3885d352b0..32c569df142ffc58afd064c4321865765f95fdc3 100644 --- a/arch/arm/boot/dts/armada-388-clearfog.dts +++ b/arch/arm/boot/dts/marvell/armada-388-clearfog.dts @@ -47,6 +47,8 @@ ð1 { /* ethernet@30000 */ + phy-mode = "1000base-x"; + fixed-link { speed = <1000>; full-duplex; @@ -129,8 +131,9 @@ port@5 { reg = <5>; - label = "cpu"; ethernet = <ð1>; + phy-mode = "1000base-x"; + fixed-link { speed = <1000>; full-duplex; @@ -141,6 +144,8 @@ /* 88E1512 external phy */ reg = <6>; label = "lan6"; + phy-mode = "rgmii-id"; + fixed-link { speed = <1000>; full-duplex; diff --git a/arch/arm/boot/dts/armada-388-clearfog.dtsi b/arch/arm/boot/dts/marvell/armada-388-clearfog.dtsi similarity index 100% rename from arch/arm/boot/dts/armada-388-clearfog.dtsi rename to arch/arm/boot/dts/marvell/armada-388-clearfog.dtsi diff --git a/arch/arm/boot/dts/armada-388-db.dts b/arch/arm/boot/dts/marvell/armada-388-db.dts similarity index 100% rename from arch/arm/boot/dts/armada-388-db.dts rename to arch/arm/boot/dts/marvell/armada-388-db.dts diff --git a/arch/arm/boot/dts/armada-388-gp.dts b/arch/arm/boot/dts/marvell/armada-388-gp.dts similarity index 100% rename from arch/arm/boot/dts/armada-388-gp.dts rename to arch/arm/boot/dts/marvell/armada-388-gp.dts diff --git a/arch/arm/boot/dts/armada-388-helios4.dts b/arch/arm/boot/dts/marvell/armada-388-helios4.dts similarity index 100% rename from arch/arm/boot/dts/armada-388-helios4.dts rename to arch/arm/boot/dts/marvell/armada-388-helios4.dts diff --git a/arch/arm/boot/dts/armada-388-rd.dts b/arch/arm/boot/dts/marvell/armada-388-rd.dts similarity index 100% rename from arch/arm/boot/dts/armada-388-rd.dts rename to arch/arm/boot/dts/marvell/armada-388-rd.dts diff --git a/arch/arm/boot/dts/armada-388.dtsi b/arch/arm/boot/dts/marvell/armada-388.dtsi similarity index 100% rename from arch/arm/boot/dts/armada-388.dtsi rename to arch/arm/boot/dts/marvell/armada-388.dtsi diff --git a/arch/arm/boot/dts/armada-38x-solidrun-microsom.dtsi b/arch/arm/boot/dts/marvell/armada-38x-solidrun-microsom.dtsi similarity index 100% rename from arch/arm/boot/dts/armada-38x-solidrun-microsom.dtsi rename to arch/arm/boot/dts/marvell/armada-38x-solidrun-microsom.dtsi diff --git a/arch/arm/boot/dts/armada-38x.dtsi b/arch/arm/boot/dts/marvell/armada-38x.dtsi similarity index 100% rename from arch/arm/boot/dts/armada-38x.dtsi rename to arch/arm/boot/dts/marvell/armada-38x.dtsi diff --git a/arch/arm/boot/dts/armada-390-db.dts b/arch/arm/boot/dts/marvell/armada-390-db.dts similarity index 99% rename from arch/arm/boot/dts/armada-390-db.dts rename to arch/arm/boot/dts/marvell/armada-390-db.dts index 792d0a0184e8268029da9d0833af5f14279f0289..20f518dbac971c0b5af301a29e9bad94b284c1b6 100644 --- a/arch/arm/boot/dts/armada-390-db.dts +++ b/arch/arm/boot/dts/marvell/armada-390-db.dts @@ -81,7 +81,7 @@ pinctrl-0 = <&spi1_pins>; pinctrl-names = "default"; - flash@1 { + flash@0 { #address-cells = <1>; #size-cells = <1>; compatible = "n25q128a13", diff --git a/arch/arm/boot/dts/armada-390.dtsi b/arch/arm/boot/dts/marvell/armada-390.dtsi similarity index 100% rename from arch/arm/boot/dts/armada-390.dtsi rename to arch/arm/boot/dts/marvell/armada-390.dtsi diff --git a/arch/arm/boot/dts/armada-395-gp.dts b/arch/arm/boot/dts/marvell/armada-395-gp.dts similarity index 100% rename from arch/arm/boot/dts/armada-395-gp.dts rename to arch/arm/boot/dts/marvell/armada-395-gp.dts diff --git a/arch/arm/boot/dts/armada-395.dtsi b/arch/arm/boot/dts/marvell/armada-395.dtsi similarity index 100% rename from arch/arm/boot/dts/armada-395.dtsi rename to arch/arm/boot/dts/marvell/armada-395.dtsi diff --git a/arch/arm/boot/dts/armada-398-db.dts b/arch/arm/boot/dts/marvell/armada-398-db.dts similarity index 100% rename from arch/arm/boot/dts/armada-398-db.dts rename to arch/arm/boot/dts/marvell/armada-398-db.dts diff --git a/arch/arm/boot/dts/armada-398.dtsi b/arch/arm/boot/dts/marvell/armada-398.dtsi similarity index 100% rename from arch/arm/boot/dts/armada-398.dtsi rename to arch/arm/boot/dts/marvell/armada-398.dtsi diff --git a/arch/arm/boot/dts/armada-39x.dtsi b/arch/arm/boot/dts/marvell/armada-39x.dtsi similarity index 100% rename from arch/arm/boot/dts/armada-39x.dtsi rename to arch/arm/boot/dts/marvell/armada-39x.dtsi diff --git a/arch/arm/boot/dts/armada-xp-98dx3236.dtsi b/arch/arm/boot/dts/marvell/armada-xp-98dx3236.dtsi similarity index 100% rename from arch/arm/boot/dts/armada-xp-98dx3236.dtsi rename to arch/arm/boot/dts/marvell/armada-xp-98dx3236.dtsi diff --git a/arch/arm/boot/dts/armada-xp-98dx3336.dtsi b/arch/arm/boot/dts/marvell/armada-xp-98dx3336.dtsi similarity index 100% rename from arch/arm/boot/dts/armada-xp-98dx3336.dtsi rename to arch/arm/boot/dts/marvell/armada-xp-98dx3336.dtsi diff --git a/arch/arm/boot/dts/armada-xp-98dx4251.dtsi b/arch/arm/boot/dts/marvell/armada-xp-98dx4251.dtsi similarity index 100% rename from arch/arm/boot/dts/armada-xp-98dx4251.dtsi rename to arch/arm/boot/dts/marvell/armada-xp-98dx4251.dtsi diff --git a/arch/arm/boot/dts/armada-xp-axpwifiap.dts b/arch/arm/boot/dts/marvell/armada-xp-axpwifiap.dts similarity index 100% rename from arch/arm/boot/dts/armada-xp-axpwifiap.dts rename to arch/arm/boot/dts/marvell/armada-xp-axpwifiap.dts diff --git a/arch/arm/boot/dts/armada-xp-crs305-1g-4s-bit.dts b/arch/arm/boot/dts/marvell/armada-xp-crs305-1g-4s-bit.dts similarity index 100% rename from arch/arm/boot/dts/armada-xp-crs305-1g-4s-bit.dts rename to arch/arm/boot/dts/marvell/armada-xp-crs305-1g-4s-bit.dts diff --git a/arch/arm/boot/dts/armada-xp-crs305-1g-4s.dts b/arch/arm/boot/dts/marvell/armada-xp-crs305-1g-4s.dts similarity index 100% rename from arch/arm/boot/dts/armada-xp-crs305-1g-4s.dts rename to arch/arm/boot/dts/marvell/armada-xp-crs305-1g-4s.dts diff --git a/arch/arm/boot/dts/armada-xp-crs305-1g-4s.dtsi b/arch/arm/boot/dts/marvell/armada-xp-crs305-1g-4s.dtsi similarity index 100% rename from arch/arm/boot/dts/armada-xp-crs305-1g-4s.dtsi rename to arch/arm/boot/dts/marvell/armada-xp-crs305-1g-4s.dtsi diff --git a/arch/arm/boot/dts/armada-xp-crs326-24g-2s-bit.dts b/arch/arm/boot/dts/marvell/armada-xp-crs326-24g-2s-bit.dts similarity index 100% rename from arch/arm/boot/dts/armada-xp-crs326-24g-2s-bit.dts rename to arch/arm/boot/dts/marvell/armada-xp-crs326-24g-2s-bit.dts diff --git a/arch/arm/boot/dts/armada-xp-crs326-24g-2s.dts b/arch/arm/boot/dts/marvell/armada-xp-crs326-24g-2s.dts similarity index 100% rename from arch/arm/boot/dts/armada-xp-crs326-24g-2s.dts rename to arch/arm/boot/dts/marvell/armada-xp-crs326-24g-2s.dts diff --git a/arch/arm/boot/dts/armada-xp-crs326-24g-2s.dtsi b/arch/arm/boot/dts/marvell/armada-xp-crs326-24g-2s.dtsi similarity index 100% rename from arch/arm/boot/dts/armada-xp-crs326-24g-2s.dtsi rename to arch/arm/boot/dts/marvell/armada-xp-crs326-24g-2s.dtsi diff --git a/arch/arm/boot/dts/armada-xp-crs328-4c-20s-4s-bit.dts b/arch/arm/boot/dts/marvell/armada-xp-crs328-4c-20s-4s-bit.dts similarity index 100% rename from arch/arm/boot/dts/armada-xp-crs328-4c-20s-4s-bit.dts rename to arch/arm/boot/dts/marvell/armada-xp-crs328-4c-20s-4s-bit.dts diff --git a/arch/arm/boot/dts/armada-xp-crs328-4c-20s-4s.dts b/arch/arm/boot/dts/marvell/armada-xp-crs328-4c-20s-4s.dts similarity index 100% rename from arch/arm/boot/dts/armada-xp-crs328-4c-20s-4s.dts rename to arch/arm/boot/dts/marvell/armada-xp-crs328-4c-20s-4s.dts diff --git a/arch/arm/boot/dts/armada-xp-crs328-4c-20s-4s.dtsi b/arch/arm/boot/dts/marvell/armada-xp-crs328-4c-20s-4s.dtsi similarity index 100% rename from arch/arm/boot/dts/armada-xp-crs328-4c-20s-4s.dtsi rename to arch/arm/boot/dts/marvell/armada-xp-crs328-4c-20s-4s.dtsi diff --git a/arch/arm/boot/dts/armada-xp-db-dxbc2.dts b/arch/arm/boot/dts/marvell/armada-xp-db-dxbc2.dts similarity index 100% rename from arch/arm/boot/dts/armada-xp-db-dxbc2.dts rename to arch/arm/boot/dts/marvell/armada-xp-db-dxbc2.dts diff --git a/arch/arm/boot/dts/armada-xp-db-xc3-24g4xg.dts b/arch/arm/boot/dts/marvell/armada-xp-db-xc3-24g4xg.dts similarity index 100% rename from arch/arm/boot/dts/armada-xp-db-xc3-24g4xg.dts rename to arch/arm/boot/dts/marvell/armada-xp-db-xc3-24g4xg.dts diff --git a/arch/arm/boot/dts/armada-xp-db.dts b/arch/arm/boot/dts/marvell/armada-xp-db.dts similarity index 100% rename from arch/arm/boot/dts/armada-xp-db.dts rename to arch/arm/boot/dts/marvell/armada-xp-db.dts diff --git a/arch/arm/boot/dts/armada-xp-gp.dts b/arch/arm/boot/dts/marvell/armada-xp-gp.dts similarity index 100% rename from arch/arm/boot/dts/armada-xp-gp.dts rename to arch/arm/boot/dts/marvell/armada-xp-gp.dts diff --git a/arch/arm/boot/dts/armada-xp-lenovo-ix4-300d.dts b/arch/arm/boot/dts/marvell/armada-xp-lenovo-ix4-300d.dts similarity index 98% rename from arch/arm/boot/dts/armada-xp-lenovo-ix4-300d.dts rename to arch/arm/boot/dts/marvell/armada-xp-lenovo-ix4-300d.dts index 0dad95ea26c2a9e187edc22332362b498359eddb..21b95578fe9533b0c481cbf916d29d1426a57787 100644 --- a/arch/arm/boot/dts/armada-xp-lenovo-ix4-300d.dts +++ b/arch/arm/boot/dts/marvell/armada-xp-lenovo-ix4-300d.dts @@ -167,8 +167,8 @@ spi-3 { compatible = "spi-gpio"; status = "okay"; - gpio-sck = <&gpio0 25 GPIO_ACTIVE_LOW>; - gpio-mosi = <&gpio1 15 GPIO_ACTIVE_LOW>; /*gpio 47*/ + sck-gpios = <&gpio0 25 GPIO_ACTIVE_LOW>; + mosi-gpios = <&gpio1 15 GPIO_ACTIVE_LOW>; /*gpio 47*/ cs-gpios = <&gpio0 27 GPIO_ACTIVE_LOW>; num-chipselects = <1>; #address-cells = <1>; diff --git a/arch/arm/boot/dts/armada-xp-linksys-mamba.dts b/arch/arm/boot/dts/marvell/armada-xp-linksys-mamba.dts similarity index 100% rename from arch/arm/boot/dts/armada-xp-linksys-mamba.dts rename to arch/arm/boot/dts/marvell/armada-xp-linksys-mamba.dts diff --git a/arch/arm/boot/dts/armada-xp-matrix.dts b/arch/arm/boot/dts/marvell/armada-xp-matrix.dts similarity index 100% rename from arch/arm/boot/dts/armada-xp-matrix.dts rename to arch/arm/boot/dts/marvell/armada-xp-matrix.dts diff --git a/arch/arm/boot/dts/armada-xp-mv78230.dtsi b/arch/arm/boot/dts/marvell/armada-xp-mv78230.dtsi similarity index 100% rename from arch/arm/boot/dts/armada-xp-mv78230.dtsi rename to arch/arm/boot/dts/marvell/armada-xp-mv78230.dtsi diff --git a/arch/arm/boot/dts/armada-xp-mv78260.dtsi b/arch/arm/boot/dts/marvell/armada-xp-mv78260.dtsi similarity index 100% rename from arch/arm/boot/dts/armada-xp-mv78260.dtsi rename to arch/arm/boot/dts/marvell/armada-xp-mv78260.dtsi diff --git a/arch/arm/boot/dts/armada-xp-mv78460.dtsi b/arch/arm/boot/dts/marvell/armada-xp-mv78460.dtsi similarity index 100% rename from arch/arm/boot/dts/armada-xp-mv78460.dtsi rename to arch/arm/boot/dts/marvell/armada-xp-mv78460.dtsi diff --git a/arch/arm/boot/dts/armada-xp-netgear-rn2120.dts b/arch/arm/boot/dts/marvell/armada-xp-netgear-rn2120.dts similarity index 100% rename from arch/arm/boot/dts/armada-xp-netgear-rn2120.dts rename to arch/arm/boot/dts/marvell/armada-xp-netgear-rn2120.dts diff --git a/arch/arm/boot/dts/armada-xp-openblocks-ax3-4.dts b/arch/arm/boot/dts/marvell/armada-xp-openblocks-ax3-4.dts similarity index 100% rename from arch/arm/boot/dts/armada-xp-openblocks-ax3-4.dts rename to arch/arm/boot/dts/marvell/armada-xp-openblocks-ax3-4.dts diff --git a/arch/arm/boot/dts/armada-xp-synology-ds414.dts b/arch/arm/boot/dts/marvell/armada-xp-synology-ds414.dts similarity index 100% rename from arch/arm/boot/dts/armada-xp-synology-ds414.dts rename to arch/arm/boot/dts/marvell/armada-xp-synology-ds414.dts diff --git a/arch/arm/boot/dts/armada-xp.dtsi b/arch/arm/boot/dts/marvell/armada-xp.dtsi similarity index 100% rename from arch/arm/boot/dts/armada-xp.dtsi rename to arch/arm/boot/dts/marvell/armada-xp.dtsi diff --git a/arch/arm/boot/dts/dove-cm-a510.dtsi b/arch/arm/boot/dts/marvell/dove-cm-a510.dtsi similarity index 100% rename from arch/arm/boot/dts/dove-cm-a510.dtsi rename to arch/arm/boot/dts/marvell/dove-cm-a510.dtsi diff --git a/arch/arm/boot/dts/dove-cubox-es.dts b/arch/arm/boot/dts/marvell/dove-cubox-es.dts similarity index 100% rename from arch/arm/boot/dts/dove-cubox-es.dts rename to arch/arm/boot/dts/marvell/dove-cubox-es.dts diff --git a/arch/arm/boot/dts/dove-cubox.dts b/arch/arm/boot/dts/marvell/dove-cubox.dts similarity index 100% rename from arch/arm/boot/dts/dove-cubox.dts rename to arch/arm/boot/dts/marvell/dove-cubox.dts diff --git a/arch/arm/boot/dts/dove-d2plug.dts b/arch/arm/boot/dts/marvell/dove-d2plug.dts similarity index 100% rename from arch/arm/boot/dts/dove-d2plug.dts rename to arch/arm/boot/dts/marvell/dove-d2plug.dts diff --git a/arch/arm/boot/dts/dove-d3plug.dts b/arch/arm/boot/dts/marvell/dove-d3plug.dts similarity index 100% rename from arch/arm/boot/dts/dove-d3plug.dts rename to arch/arm/boot/dts/marvell/dove-d3plug.dts diff --git a/arch/arm/boot/dts/dove-dove-db.dts b/arch/arm/boot/dts/marvell/dove-dove-db.dts similarity index 100% rename from arch/arm/boot/dts/dove-dove-db.dts rename to arch/arm/boot/dts/marvell/dove-dove-db.dts diff --git a/arch/arm/boot/dts/dove-sbc-a510.dts b/arch/arm/boot/dts/marvell/dove-sbc-a510.dts similarity index 100% rename from arch/arm/boot/dts/dove-sbc-a510.dts rename to arch/arm/boot/dts/marvell/dove-sbc-a510.dts diff --git a/arch/arm/boot/dts/dove.dtsi b/arch/arm/boot/dts/marvell/dove.dtsi similarity index 100% rename from arch/arm/boot/dts/dove.dtsi rename to arch/arm/boot/dts/marvell/dove.dtsi diff --git a/arch/arm/boot/dts/marvell/kirkwood-4i-edge-200.dts b/arch/arm/boot/dts/marvell/kirkwood-4i-edge-200.dts new file mode 100644 index 0000000000000000000000000000000000000000..b1749d3f60b7bb9285b5524a1ff0f27dfaf043ef --- /dev/null +++ b/arch/arm/boot/dts/marvell/kirkwood-4i-edge-200.dts @@ -0,0 +1,205 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Endian 4i Edge 200 Board Description + * Note: Endian UTM Mini is hardware clone of Endian Edge 200 + * Copyright 2021-2022 Pawel Dembicki + */ + +/dts-v1/; + +#include "kirkwood.dtsi" +#include "kirkwood-6281.dtsi" +#include + +/ { + model = "Endian 4i Edge 200"; + compatible = "endian,4i-edge-200", "marvell,kirkwood-88f6281", "marvell,kirkwood"; + + memory { + device_type = "memory"; + reg = <0x00000000 0x20000000>; + }; + + chosen { + bootargs = "console=ttyS0,115200n8"; + stdout-path = &uart0; + }; + + leds { + compatible = "gpio-leds"; + pinctrl-0 = <&pmx_led>; + pinctrl-names = "default"; + + led-1 { + function = LED_FUNCTION_SD; + color = ; + gpios = <&gpio1 2 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "mmc0"; + }; + + led-2 { + function = LED_FUNCTION_STATUS; + color = ; + gpios = <&gpio1 3 GPIO_ACTIVE_HIGH>; + }; + + led-3 { + function = LED_FUNCTION_STATUS; + color = ; + gpios = <&gpio1 17 GPIO_ACTIVE_HIGH>; + }; + }; +}; + +ð0 { + status = "okay"; +}; + +ð0port { + speed = <1000>; + duplex = <1>; +}; + +ð1 { + status = "okay"; +}; + +ð1port { + phy-handle = <ðphyb>; +}; + +&mdio { + status = "okay"; + + ethphyb: ethernet-phy@b { + reg = <0x0b>; + + marvell,reg-init = + /* link-activity, bi-color mode 4 */ + <3 0x10 0xfff0 0xf>; /* Reg 3,16 <- 0xzzzf */ + }; + + switch0: switch@11 { + compatible = "marvell,mv88e6085"; + reg = <0x11>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + label = "port1"; + }; + + port@1 { + reg = <1>; + label = "port2"; + }; + + port@2 { + reg = <2>; + label = "port3"; + }; + + port@3 { + reg = <3>; + label = "port4"; + }; + + port@5 { + reg = <5>; + phy-mode = "rgmii-id"; + ethernet = <ð0port>; + + fixed-link { + speed = <1000>; + full-duplex; + }; + }; + }; + }; +}; + +&nand { + status = "okay"; + pinctrl-0 = <&pmx_nand>; + pinctrl-names = "default"; + + partition@0 { + label = "u-boot"; + reg = <0x00000000 0x000a0000>; + read-only; + }; + + partition@a0000 { + label = "u-boot-env"; + reg = <0x000a0000 0x00060000>; + read-only; + }; + + partition@100000 { + label = "kernel"; + reg = <0x00100000 0x00400000>; + }; + + partition@500000 { + label = "ubi"; + reg = <0x00500000 0x1fb00000>; + }; +}; + +&pciec { + status = "okay"; +}; + +&pcie0 { + status = "okay"; +}; + +&pinctrl { + pinctrl-0 = <&pmx_sysrst>; + pinctrl-names = "default"; + + pmx_sysrst: pmx-sysrst { + marvell,pins = "mpp6"; + marvell,function = "sysrst"; + }; + + pmx_sdio_cd: pmx-sdio-cd { + marvell,pins = "mpp28"; + marvell,function = "gpio"; + }; + + pmx_led: pmx-led { + marvell,pins = "mpp34", "mpp35", "mpp49"; + marvell,function = "gpio"; + }; +}; + +&rtc { + status = "okay"; +}; + +&sata_phy0 { + status = "disabled"; +}; + +&sata_phy1 { + status = "disabled"; +}; + +&sdio { + pinctrl-0 = <&pmx_sdio_cd>; + pinctrl-names = "default"; + status = "okay"; + cd-gpios = <&gpio0 28 9>; +}; + +&uart0 { + status = "okay"; +}; + +&usb0 { + status = "okay"; +}; diff --git a/arch/arm/boot/dts/kirkwood-6192.dtsi b/arch/arm/boot/dts/marvell/kirkwood-6192.dtsi similarity index 100% rename from arch/arm/boot/dts/kirkwood-6192.dtsi rename to arch/arm/boot/dts/marvell/kirkwood-6192.dtsi diff --git a/arch/arm/boot/dts/kirkwood-6281.dtsi b/arch/arm/boot/dts/marvell/kirkwood-6281.dtsi similarity index 100% rename from arch/arm/boot/dts/kirkwood-6281.dtsi rename to arch/arm/boot/dts/marvell/kirkwood-6281.dtsi diff --git a/arch/arm/boot/dts/kirkwood-6282.dtsi b/arch/arm/boot/dts/marvell/kirkwood-6282.dtsi similarity index 100% rename from arch/arm/boot/dts/kirkwood-6282.dtsi rename to arch/arm/boot/dts/marvell/kirkwood-6282.dtsi diff --git a/arch/arm/boot/dts/kirkwood-98dx4122.dtsi b/arch/arm/boot/dts/marvell/kirkwood-98dx4122.dtsi similarity index 100% rename from arch/arm/boot/dts/kirkwood-98dx4122.dtsi rename to arch/arm/boot/dts/marvell/kirkwood-98dx4122.dtsi diff --git a/arch/arm/boot/dts/kirkwood-b3.dts b/arch/arm/boot/dts/marvell/kirkwood-b3.dts similarity index 100% rename from arch/arm/boot/dts/kirkwood-b3.dts rename to arch/arm/boot/dts/marvell/kirkwood-b3.dts diff --git a/arch/arm/boot/dts/kirkwood-blackarmor-nas220.dts b/arch/arm/boot/dts/marvell/kirkwood-blackarmor-nas220.dts similarity index 100% rename from arch/arm/boot/dts/kirkwood-blackarmor-nas220.dts rename to arch/arm/boot/dts/marvell/kirkwood-blackarmor-nas220.dts diff --git a/arch/arm/boot/dts/kirkwood-c200-v1.dts b/arch/arm/boot/dts/marvell/kirkwood-c200-v1.dts similarity index 100% rename from arch/arm/boot/dts/kirkwood-c200-v1.dts rename to arch/arm/boot/dts/marvell/kirkwood-c200-v1.dts diff --git a/arch/arm/boot/dts/kirkwood-cloudbox.dts b/arch/arm/boot/dts/marvell/kirkwood-cloudbox.dts similarity index 100% rename from arch/arm/boot/dts/kirkwood-cloudbox.dts rename to arch/arm/boot/dts/marvell/kirkwood-cloudbox.dts diff --git a/arch/arm/boot/dts/kirkwood-d2net.dts b/arch/arm/boot/dts/marvell/kirkwood-d2net.dts similarity index 100% rename from arch/arm/boot/dts/kirkwood-d2net.dts rename to arch/arm/boot/dts/marvell/kirkwood-d2net.dts diff --git a/arch/arm/boot/dts/kirkwood-db-88f6281.dts b/arch/arm/boot/dts/marvell/kirkwood-db-88f6281.dts similarity index 100% rename from arch/arm/boot/dts/kirkwood-db-88f6281.dts rename to arch/arm/boot/dts/marvell/kirkwood-db-88f6281.dts diff --git a/arch/arm/boot/dts/kirkwood-db-88f6282.dts b/arch/arm/boot/dts/marvell/kirkwood-db-88f6282.dts similarity index 100% rename from arch/arm/boot/dts/kirkwood-db-88f6282.dts rename to arch/arm/boot/dts/marvell/kirkwood-db-88f6282.dts diff --git a/arch/arm/boot/dts/kirkwood-db.dtsi b/arch/arm/boot/dts/marvell/kirkwood-db.dtsi similarity index 100% rename from arch/arm/boot/dts/kirkwood-db.dtsi rename to arch/arm/boot/dts/marvell/kirkwood-db.dtsi diff --git a/arch/arm/boot/dts/kirkwood-dir665.dts b/arch/arm/boot/dts/marvell/kirkwood-dir665.dts similarity index 100% rename from arch/arm/boot/dts/kirkwood-dir665.dts rename to arch/arm/boot/dts/marvell/kirkwood-dir665.dts diff --git a/arch/arm/boot/dts/kirkwood-dns320.dts b/arch/arm/boot/dts/marvell/kirkwood-dns320.dts similarity index 100% rename from arch/arm/boot/dts/kirkwood-dns320.dts rename to arch/arm/boot/dts/marvell/kirkwood-dns320.dts diff --git a/arch/arm/boot/dts/kirkwood-dns325.dts b/arch/arm/boot/dts/marvell/kirkwood-dns325.dts similarity index 100% rename from arch/arm/boot/dts/kirkwood-dns325.dts rename to arch/arm/boot/dts/marvell/kirkwood-dns325.dts diff --git a/arch/arm/boot/dts/kirkwood-dnskw.dtsi b/arch/arm/boot/dts/marvell/kirkwood-dnskw.dtsi similarity index 100% rename from arch/arm/boot/dts/kirkwood-dnskw.dtsi rename to arch/arm/boot/dts/marvell/kirkwood-dnskw.dtsi diff --git a/arch/arm/boot/dts/kirkwood-dockstar.dts b/arch/arm/boot/dts/marvell/kirkwood-dockstar.dts similarity index 100% rename from arch/arm/boot/dts/kirkwood-dockstar.dts rename to arch/arm/boot/dts/marvell/kirkwood-dockstar.dts diff --git a/arch/arm/boot/dts/kirkwood-dreamplug.dts b/arch/arm/boot/dts/marvell/kirkwood-dreamplug.dts similarity index 100% rename from arch/arm/boot/dts/kirkwood-dreamplug.dts rename to arch/arm/boot/dts/marvell/kirkwood-dreamplug.dts diff --git a/arch/arm/boot/dts/kirkwood-ds109.dts b/arch/arm/boot/dts/marvell/kirkwood-ds109.dts similarity index 100% rename from arch/arm/boot/dts/kirkwood-ds109.dts rename to arch/arm/boot/dts/marvell/kirkwood-ds109.dts diff --git a/arch/arm/boot/dts/kirkwood-ds110jv10.dts b/arch/arm/boot/dts/marvell/kirkwood-ds110jv10.dts similarity index 100% rename from arch/arm/boot/dts/kirkwood-ds110jv10.dts rename to arch/arm/boot/dts/marvell/kirkwood-ds110jv10.dts diff --git a/arch/arm/boot/dts/kirkwood-ds111.dts b/arch/arm/boot/dts/marvell/kirkwood-ds111.dts similarity index 100% rename from arch/arm/boot/dts/kirkwood-ds111.dts rename to arch/arm/boot/dts/marvell/kirkwood-ds111.dts diff --git a/arch/arm/boot/dts/kirkwood-ds112.dts b/arch/arm/boot/dts/marvell/kirkwood-ds112.dts similarity index 100% rename from arch/arm/boot/dts/kirkwood-ds112.dts rename to arch/arm/boot/dts/marvell/kirkwood-ds112.dts diff --git a/arch/arm/boot/dts/kirkwood-ds209.dts b/arch/arm/boot/dts/marvell/kirkwood-ds209.dts similarity index 100% rename from arch/arm/boot/dts/kirkwood-ds209.dts rename to arch/arm/boot/dts/marvell/kirkwood-ds209.dts diff --git a/arch/arm/boot/dts/kirkwood-ds210.dts b/arch/arm/boot/dts/marvell/kirkwood-ds210.dts similarity index 100% rename from arch/arm/boot/dts/kirkwood-ds210.dts rename to arch/arm/boot/dts/marvell/kirkwood-ds210.dts diff --git a/arch/arm/boot/dts/kirkwood-ds212.dts b/arch/arm/boot/dts/marvell/kirkwood-ds212.dts similarity index 100% rename from arch/arm/boot/dts/kirkwood-ds212.dts rename to arch/arm/boot/dts/marvell/kirkwood-ds212.dts diff --git a/arch/arm/boot/dts/kirkwood-ds212j.dts b/arch/arm/boot/dts/marvell/kirkwood-ds212j.dts similarity index 100% rename from arch/arm/boot/dts/kirkwood-ds212j.dts rename to arch/arm/boot/dts/marvell/kirkwood-ds212j.dts diff --git a/arch/arm/boot/dts/kirkwood-ds409.dts b/arch/arm/boot/dts/marvell/kirkwood-ds409.dts similarity index 100% rename from arch/arm/boot/dts/kirkwood-ds409.dts rename to arch/arm/boot/dts/marvell/kirkwood-ds409.dts diff --git a/arch/arm/boot/dts/kirkwood-ds409slim.dts b/arch/arm/boot/dts/marvell/kirkwood-ds409slim.dts similarity index 100% rename from arch/arm/boot/dts/kirkwood-ds409slim.dts rename to arch/arm/boot/dts/marvell/kirkwood-ds409slim.dts diff --git a/arch/arm/boot/dts/kirkwood-ds411.dts b/arch/arm/boot/dts/marvell/kirkwood-ds411.dts similarity index 100% rename from arch/arm/boot/dts/kirkwood-ds411.dts rename to arch/arm/boot/dts/marvell/kirkwood-ds411.dts diff --git a/arch/arm/boot/dts/kirkwood-ds411j.dts b/arch/arm/boot/dts/marvell/kirkwood-ds411j.dts similarity index 100% rename from arch/arm/boot/dts/kirkwood-ds411j.dts rename to arch/arm/boot/dts/marvell/kirkwood-ds411j.dts diff --git a/arch/arm/boot/dts/kirkwood-ds411slim.dts b/arch/arm/boot/dts/marvell/kirkwood-ds411slim.dts similarity index 100% rename from arch/arm/boot/dts/kirkwood-ds411slim.dts rename to arch/arm/boot/dts/marvell/kirkwood-ds411slim.dts diff --git a/arch/arm/boot/dts/kirkwood-goflexnet.dts b/arch/arm/boot/dts/marvell/kirkwood-goflexnet.dts similarity index 100% rename from arch/arm/boot/dts/kirkwood-goflexnet.dts rename to arch/arm/boot/dts/marvell/kirkwood-goflexnet.dts diff --git a/arch/arm/boot/dts/kirkwood-guruplug-server-plus.dts b/arch/arm/boot/dts/marvell/kirkwood-guruplug-server-plus.dts similarity index 100% rename from arch/arm/boot/dts/kirkwood-guruplug-server-plus.dts rename to arch/arm/boot/dts/marvell/kirkwood-guruplug-server-plus.dts diff --git a/arch/arm/boot/dts/kirkwood-ib62x0.dts b/arch/arm/boot/dts/marvell/kirkwood-ib62x0.dts similarity index 100% rename from arch/arm/boot/dts/kirkwood-ib62x0.dts rename to arch/arm/boot/dts/marvell/kirkwood-ib62x0.dts diff --git a/arch/arm/boot/dts/kirkwood-iconnect.dts b/arch/arm/boot/dts/marvell/kirkwood-iconnect.dts similarity index 100% rename from arch/arm/boot/dts/kirkwood-iconnect.dts rename to arch/arm/boot/dts/marvell/kirkwood-iconnect.dts diff --git a/arch/arm/boot/dts/kirkwood-iomega_ix2_200.dts b/arch/arm/boot/dts/marvell/kirkwood-iomega_ix2_200.dts similarity index 100% rename from arch/arm/boot/dts/kirkwood-iomega_ix2_200.dts rename to arch/arm/boot/dts/marvell/kirkwood-iomega_ix2_200.dts diff --git a/arch/arm/boot/dts/kirkwood-is2.dts b/arch/arm/boot/dts/marvell/kirkwood-is2.dts similarity index 100% rename from arch/arm/boot/dts/kirkwood-is2.dts rename to arch/arm/boot/dts/marvell/kirkwood-is2.dts diff --git a/arch/arm/boot/dts/kirkwood-km_common.dtsi b/arch/arm/boot/dts/marvell/kirkwood-km_common.dtsi similarity index 100% rename from arch/arm/boot/dts/kirkwood-km_common.dtsi rename to arch/arm/boot/dts/marvell/kirkwood-km_common.dtsi diff --git a/arch/arm/boot/dts/kirkwood-km_fixedeth.dts b/arch/arm/boot/dts/marvell/kirkwood-km_fixedeth.dts similarity index 100% rename from arch/arm/boot/dts/kirkwood-km_fixedeth.dts rename to arch/arm/boot/dts/marvell/kirkwood-km_fixedeth.dts diff --git a/arch/arm/boot/dts/kirkwood-km_kirkwood.dts b/arch/arm/boot/dts/marvell/kirkwood-km_kirkwood.dts similarity index 100% rename from arch/arm/boot/dts/kirkwood-km_kirkwood.dts rename to arch/arm/boot/dts/marvell/kirkwood-km_kirkwood.dts diff --git a/arch/arm/boot/dts/kirkwood-l-50.dts b/arch/arm/boot/dts/marvell/kirkwood-l-50.dts similarity index 100% rename from arch/arm/boot/dts/kirkwood-l-50.dts rename to arch/arm/boot/dts/marvell/kirkwood-l-50.dts diff --git a/arch/arm/boot/dts/kirkwood-laplug.dts b/arch/arm/boot/dts/marvell/kirkwood-laplug.dts similarity index 100% rename from arch/arm/boot/dts/kirkwood-laplug.dts rename to arch/arm/boot/dts/marvell/kirkwood-laplug.dts diff --git a/arch/arm/boot/dts/kirkwood-linkstation-6282.dtsi b/arch/arm/boot/dts/marvell/kirkwood-linkstation-6282.dtsi similarity index 100% rename from arch/arm/boot/dts/kirkwood-linkstation-6282.dtsi rename to arch/arm/boot/dts/marvell/kirkwood-linkstation-6282.dtsi diff --git a/arch/arm/boot/dts/kirkwood-linkstation-duo-6281.dtsi b/arch/arm/boot/dts/marvell/kirkwood-linkstation-duo-6281.dtsi similarity index 100% rename from arch/arm/boot/dts/kirkwood-linkstation-duo-6281.dtsi rename to arch/arm/boot/dts/marvell/kirkwood-linkstation-duo-6281.dtsi diff --git a/arch/arm/boot/dts/kirkwood-linkstation-lsqvl.dts b/arch/arm/boot/dts/marvell/kirkwood-linkstation-lsqvl.dts similarity index 100% rename from arch/arm/boot/dts/kirkwood-linkstation-lsqvl.dts rename to arch/arm/boot/dts/marvell/kirkwood-linkstation-lsqvl.dts diff --git a/arch/arm/boot/dts/kirkwood-linkstation-lsvl.dts b/arch/arm/boot/dts/marvell/kirkwood-linkstation-lsvl.dts similarity index 100% rename from arch/arm/boot/dts/kirkwood-linkstation-lsvl.dts rename to arch/arm/boot/dts/marvell/kirkwood-linkstation-lsvl.dts diff --git a/arch/arm/boot/dts/kirkwood-linkstation-lswsxl.dts b/arch/arm/boot/dts/marvell/kirkwood-linkstation-lswsxl.dts similarity index 100% rename from arch/arm/boot/dts/kirkwood-linkstation-lswsxl.dts rename to arch/arm/boot/dts/marvell/kirkwood-linkstation-lswsxl.dts diff --git a/arch/arm/boot/dts/kirkwood-linkstation-lswvl.dts b/arch/arm/boot/dts/marvell/kirkwood-linkstation-lswvl.dts similarity index 100% rename from arch/arm/boot/dts/kirkwood-linkstation-lswvl.dts rename to arch/arm/boot/dts/marvell/kirkwood-linkstation-lswvl.dts diff --git a/arch/arm/boot/dts/kirkwood-linkstation-lswxl.dts b/arch/arm/boot/dts/marvell/kirkwood-linkstation-lswxl.dts similarity index 100% rename from arch/arm/boot/dts/kirkwood-linkstation-lswxl.dts rename to arch/arm/boot/dts/marvell/kirkwood-linkstation-lswxl.dts diff --git a/arch/arm/boot/dts/kirkwood-linkstation.dtsi b/arch/arm/boot/dts/marvell/kirkwood-linkstation.dtsi similarity index 100% rename from arch/arm/boot/dts/kirkwood-linkstation.dtsi rename to arch/arm/boot/dts/marvell/kirkwood-linkstation.dtsi diff --git a/arch/arm/boot/dts/kirkwood-linksys-viper.dts b/arch/arm/boot/dts/marvell/kirkwood-linksys-viper.dts similarity index 100% rename from arch/arm/boot/dts/kirkwood-linksys-viper.dts rename to arch/arm/boot/dts/marvell/kirkwood-linksys-viper.dts diff --git a/arch/arm/boot/dts/kirkwood-lschlv2.dts b/arch/arm/boot/dts/marvell/kirkwood-lschlv2.dts similarity index 100% rename from arch/arm/boot/dts/kirkwood-lschlv2.dts rename to arch/arm/boot/dts/marvell/kirkwood-lschlv2.dts diff --git a/arch/arm/boot/dts/kirkwood-lsxhl.dts b/arch/arm/boot/dts/marvell/kirkwood-lsxhl.dts similarity index 100% rename from arch/arm/boot/dts/kirkwood-lsxhl.dts rename to arch/arm/boot/dts/marvell/kirkwood-lsxhl.dts diff --git a/arch/arm/boot/dts/kirkwood-lsxl.dtsi b/arch/arm/boot/dts/marvell/kirkwood-lsxl.dtsi similarity index 100% rename from arch/arm/boot/dts/kirkwood-lsxl.dtsi rename to arch/arm/boot/dts/marvell/kirkwood-lsxl.dtsi diff --git a/arch/arm/boot/dts/kirkwood-mplcec4.dts b/arch/arm/boot/dts/marvell/kirkwood-mplcec4.dts similarity index 100% rename from arch/arm/boot/dts/kirkwood-mplcec4.dts rename to arch/arm/boot/dts/marvell/kirkwood-mplcec4.dts diff --git a/arch/arm/boot/dts/kirkwood-mv88f6281gtw-ge.dts b/arch/arm/boot/dts/marvell/kirkwood-mv88f6281gtw-ge.dts similarity index 100% rename from arch/arm/boot/dts/kirkwood-mv88f6281gtw-ge.dts rename to arch/arm/boot/dts/marvell/kirkwood-mv88f6281gtw-ge.dts diff --git a/arch/arm/boot/dts/kirkwood-nas2big.dts b/arch/arm/boot/dts/marvell/kirkwood-nas2big.dts similarity index 100% rename from arch/arm/boot/dts/kirkwood-nas2big.dts rename to arch/arm/boot/dts/marvell/kirkwood-nas2big.dts diff --git a/arch/arm/boot/dts/kirkwood-net2big.dts b/arch/arm/boot/dts/marvell/kirkwood-net2big.dts similarity index 100% rename from arch/arm/boot/dts/kirkwood-net2big.dts rename to arch/arm/boot/dts/marvell/kirkwood-net2big.dts diff --git a/arch/arm/boot/dts/kirkwood-net5big.dts b/arch/arm/boot/dts/marvell/kirkwood-net5big.dts similarity index 100% rename from arch/arm/boot/dts/kirkwood-net5big.dts rename to arch/arm/boot/dts/marvell/kirkwood-net5big.dts diff --git a/arch/arm/boot/dts/kirkwood-netgear_readynas_duo_v2.dts b/arch/arm/boot/dts/marvell/kirkwood-netgear_readynas_duo_v2.dts similarity index 100% rename from arch/arm/boot/dts/kirkwood-netgear_readynas_duo_v2.dts rename to arch/arm/boot/dts/marvell/kirkwood-netgear_readynas_duo_v2.dts diff --git a/arch/arm/boot/dts/kirkwood-netgear_readynas_nv+_v2.dts b/arch/arm/boot/dts/marvell/kirkwood-netgear_readynas_nv+_v2.dts similarity index 100% rename from arch/arm/boot/dts/kirkwood-netgear_readynas_nv+_v2.dts rename to arch/arm/boot/dts/marvell/kirkwood-netgear_readynas_nv+_v2.dts diff --git a/arch/arm/boot/dts/kirkwood-netxbig.dtsi b/arch/arm/boot/dts/marvell/kirkwood-netxbig.dtsi similarity index 100% rename from arch/arm/boot/dts/kirkwood-netxbig.dtsi rename to arch/arm/boot/dts/marvell/kirkwood-netxbig.dtsi diff --git a/arch/arm/boot/dts/kirkwood-ns2-common.dtsi b/arch/arm/boot/dts/marvell/kirkwood-ns2-common.dtsi similarity index 100% rename from arch/arm/boot/dts/kirkwood-ns2-common.dtsi rename to arch/arm/boot/dts/marvell/kirkwood-ns2-common.dtsi diff --git a/arch/arm/boot/dts/kirkwood-ns2.dts b/arch/arm/boot/dts/marvell/kirkwood-ns2.dts similarity index 100% rename from arch/arm/boot/dts/kirkwood-ns2.dts rename to arch/arm/boot/dts/marvell/kirkwood-ns2.dts diff --git a/arch/arm/boot/dts/kirkwood-ns2lite.dts b/arch/arm/boot/dts/marvell/kirkwood-ns2lite.dts similarity index 100% rename from arch/arm/boot/dts/kirkwood-ns2lite.dts rename to arch/arm/boot/dts/marvell/kirkwood-ns2lite.dts diff --git a/arch/arm/boot/dts/kirkwood-ns2max.dts b/arch/arm/boot/dts/marvell/kirkwood-ns2max.dts similarity index 100% rename from arch/arm/boot/dts/kirkwood-ns2max.dts rename to arch/arm/boot/dts/marvell/kirkwood-ns2max.dts diff --git a/arch/arm/boot/dts/kirkwood-ns2mini.dts b/arch/arm/boot/dts/marvell/kirkwood-ns2mini.dts similarity index 100% rename from arch/arm/boot/dts/kirkwood-ns2mini.dts rename to arch/arm/boot/dts/marvell/kirkwood-ns2mini.dts diff --git a/arch/arm/boot/dts/kirkwood-nsa310.dts b/arch/arm/boot/dts/marvell/kirkwood-nsa310.dts similarity index 100% rename from arch/arm/boot/dts/kirkwood-nsa310.dts rename to arch/arm/boot/dts/marvell/kirkwood-nsa310.dts diff --git a/arch/arm/boot/dts/kirkwood-nsa310a.dts b/arch/arm/boot/dts/marvell/kirkwood-nsa310a.dts similarity index 100% rename from arch/arm/boot/dts/kirkwood-nsa310a.dts rename to arch/arm/boot/dts/marvell/kirkwood-nsa310a.dts diff --git a/arch/arm/boot/dts/kirkwood-nsa310s.dts b/arch/arm/boot/dts/marvell/kirkwood-nsa310s.dts similarity index 100% rename from arch/arm/boot/dts/kirkwood-nsa310s.dts rename to arch/arm/boot/dts/marvell/kirkwood-nsa310s.dts diff --git a/arch/arm/boot/dts/kirkwood-nsa320.dts b/arch/arm/boot/dts/marvell/kirkwood-nsa320.dts similarity index 100% rename from arch/arm/boot/dts/kirkwood-nsa320.dts rename to arch/arm/boot/dts/marvell/kirkwood-nsa320.dts diff --git a/arch/arm/boot/dts/kirkwood-nsa325.dts b/arch/arm/boot/dts/marvell/kirkwood-nsa325.dts similarity index 100% rename from arch/arm/boot/dts/kirkwood-nsa325.dts rename to arch/arm/boot/dts/marvell/kirkwood-nsa325.dts diff --git a/arch/arm/boot/dts/kirkwood-nsa3x0-common.dtsi b/arch/arm/boot/dts/marvell/kirkwood-nsa3x0-common.dtsi similarity index 100% rename from arch/arm/boot/dts/kirkwood-nsa3x0-common.dtsi rename to arch/arm/boot/dts/marvell/kirkwood-nsa3x0-common.dtsi diff --git a/arch/arm/boot/dts/kirkwood-openblocks_a6.dts b/arch/arm/boot/dts/marvell/kirkwood-openblocks_a6.dts similarity index 100% rename from arch/arm/boot/dts/kirkwood-openblocks_a6.dts rename to arch/arm/boot/dts/marvell/kirkwood-openblocks_a6.dts diff --git a/arch/arm/boot/dts/kirkwood-openblocks_a7.dts b/arch/arm/boot/dts/marvell/kirkwood-openblocks_a7.dts similarity index 100% rename from arch/arm/boot/dts/kirkwood-openblocks_a7.dts rename to arch/arm/boot/dts/marvell/kirkwood-openblocks_a7.dts diff --git a/arch/arm/boot/dts/kirkwood-openrd-base.dts b/arch/arm/boot/dts/marvell/kirkwood-openrd-base.dts similarity index 100% rename from arch/arm/boot/dts/kirkwood-openrd-base.dts rename to arch/arm/boot/dts/marvell/kirkwood-openrd-base.dts diff --git a/arch/arm/boot/dts/kirkwood-openrd-client.dts b/arch/arm/boot/dts/marvell/kirkwood-openrd-client.dts similarity index 100% rename from arch/arm/boot/dts/kirkwood-openrd-client.dts rename to arch/arm/boot/dts/marvell/kirkwood-openrd-client.dts diff --git a/arch/arm/boot/dts/kirkwood-openrd-ultimate.dts b/arch/arm/boot/dts/marvell/kirkwood-openrd-ultimate.dts similarity index 100% rename from arch/arm/boot/dts/kirkwood-openrd-ultimate.dts rename to arch/arm/boot/dts/marvell/kirkwood-openrd-ultimate.dts diff --git a/arch/arm/boot/dts/kirkwood-openrd.dtsi b/arch/arm/boot/dts/marvell/kirkwood-openrd.dtsi similarity index 100% rename from arch/arm/boot/dts/kirkwood-openrd.dtsi rename to arch/arm/boot/dts/marvell/kirkwood-openrd.dtsi diff --git a/arch/arm/boot/dts/kirkwood-pogo_e02.dts b/arch/arm/boot/dts/marvell/kirkwood-pogo_e02.dts similarity index 100% rename from arch/arm/boot/dts/kirkwood-pogo_e02.dts rename to arch/arm/boot/dts/marvell/kirkwood-pogo_e02.dts diff --git a/arch/arm/boot/dts/kirkwood-pogoplug-series-4.dts b/arch/arm/boot/dts/marvell/kirkwood-pogoplug-series-4.dts similarity index 100% rename from arch/arm/boot/dts/kirkwood-pogoplug-series-4.dts rename to arch/arm/boot/dts/marvell/kirkwood-pogoplug-series-4.dts diff --git a/arch/arm/boot/dts/kirkwood-rd88f6192.dts b/arch/arm/boot/dts/marvell/kirkwood-rd88f6192.dts similarity index 100% rename from arch/arm/boot/dts/kirkwood-rd88f6192.dts rename to arch/arm/boot/dts/marvell/kirkwood-rd88f6192.dts diff --git a/arch/arm/boot/dts/kirkwood-rd88f6281-a.dts b/arch/arm/boot/dts/marvell/kirkwood-rd88f6281-a.dts similarity index 100% rename from arch/arm/boot/dts/kirkwood-rd88f6281-a.dts rename to arch/arm/boot/dts/marvell/kirkwood-rd88f6281-a.dts diff --git a/arch/arm/boot/dts/kirkwood-rd88f6281-z0.dts b/arch/arm/boot/dts/marvell/kirkwood-rd88f6281-z0.dts similarity index 100% rename from arch/arm/boot/dts/kirkwood-rd88f6281-z0.dts rename to arch/arm/boot/dts/marvell/kirkwood-rd88f6281-z0.dts diff --git a/arch/arm/boot/dts/kirkwood-rd88f6281.dtsi b/arch/arm/boot/dts/marvell/kirkwood-rd88f6281.dtsi similarity index 100% rename from arch/arm/boot/dts/kirkwood-rd88f6281.dtsi rename to arch/arm/boot/dts/marvell/kirkwood-rd88f6281.dtsi diff --git a/arch/arm/boot/dts/kirkwood-rs212.dts b/arch/arm/boot/dts/marvell/kirkwood-rs212.dts similarity index 100% rename from arch/arm/boot/dts/kirkwood-rs212.dts rename to arch/arm/boot/dts/marvell/kirkwood-rs212.dts diff --git a/arch/arm/boot/dts/kirkwood-rs409.dts b/arch/arm/boot/dts/marvell/kirkwood-rs409.dts similarity index 100% rename from arch/arm/boot/dts/kirkwood-rs409.dts rename to arch/arm/boot/dts/marvell/kirkwood-rs409.dts diff --git a/arch/arm/boot/dts/kirkwood-rs411.dts b/arch/arm/boot/dts/marvell/kirkwood-rs411.dts similarity index 100% rename from arch/arm/boot/dts/kirkwood-rs411.dts rename to arch/arm/boot/dts/marvell/kirkwood-rs411.dts diff --git a/arch/arm/boot/dts/kirkwood-sheevaplug-common.dtsi b/arch/arm/boot/dts/marvell/kirkwood-sheevaplug-common.dtsi similarity index 100% rename from arch/arm/boot/dts/kirkwood-sheevaplug-common.dtsi rename to arch/arm/boot/dts/marvell/kirkwood-sheevaplug-common.dtsi diff --git a/arch/arm/boot/dts/kirkwood-sheevaplug-esata.dts b/arch/arm/boot/dts/marvell/kirkwood-sheevaplug-esata.dts similarity index 100% rename from arch/arm/boot/dts/kirkwood-sheevaplug-esata.dts rename to arch/arm/boot/dts/marvell/kirkwood-sheevaplug-esata.dts diff --git a/arch/arm/boot/dts/kirkwood-sheevaplug.dts b/arch/arm/boot/dts/marvell/kirkwood-sheevaplug.dts similarity index 100% rename from arch/arm/boot/dts/kirkwood-sheevaplug.dts rename to arch/arm/boot/dts/marvell/kirkwood-sheevaplug.dts diff --git a/arch/arm/boot/dts/kirkwood-synology.dtsi b/arch/arm/boot/dts/marvell/kirkwood-synology.dtsi similarity index 100% rename from arch/arm/boot/dts/kirkwood-synology.dtsi rename to arch/arm/boot/dts/marvell/kirkwood-synology.dtsi diff --git a/arch/arm/boot/dts/kirkwood-t5325.dts b/arch/arm/boot/dts/marvell/kirkwood-t5325.dts similarity index 100% rename from arch/arm/boot/dts/kirkwood-t5325.dts rename to arch/arm/boot/dts/marvell/kirkwood-t5325.dts diff --git a/arch/arm/boot/dts/kirkwood-topkick.dts b/arch/arm/boot/dts/marvell/kirkwood-topkick.dts similarity index 100% rename from arch/arm/boot/dts/kirkwood-topkick.dts rename to arch/arm/boot/dts/marvell/kirkwood-topkick.dts diff --git a/arch/arm/boot/dts/kirkwood-ts219-6281.dts b/arch/arm/boot/dts/marvell/kirkwood-ts219-6281.dts similarity index 100% rename from arch/arm/boot/dts/kirkwood-ts219-6281.dts rename to arch/arm/boot/dts/marvell/kirkwood-ts219-6281.dts diff --git a/arch/arm/boot/dts/kirkwood-ts219-6282.dts b/arch/arm/boot/dts/marvell/kirkwood-ts219-6282.dts similarity index 100% rename from arch/arm/boot/dts/kirkwood-ts219-6282.dts rename to arch/arm/boot/dts/marvell/kirkwood-ts219-6282.dts diff --git a/arch/arm/boot/dts/kirkwood-ts219.dtsi b/arch/arm/boot/dts/marvell/kirkwood-ts219.dtsi similarity index 100% rename from arch/arm/boot/dts/kirkwood-ts219.dtsi rename to arch/arm/boot/dts/marvell/kirkwood-ts219.dtsi diff --git a/arch/arm/boot/dts/kirkwood-ts419-6281.dts b/arch/arm/boot/dts/marvell/kirkwood-ts419-6281.dts similarity index 100% rename from arch/arm/boot/dts/kirkwood-ts419-6281.dts rename to arch/arm/boot/dts/marvell/kirkwood-ts419-6281.dts diff --git a/arch/arm/boot/dts/kirkwood-ts419-6282.dts b/arch/arm/boot/dts/marvell/kirkwood-ts419-6282.dts similarity index 100% rename from arch/arm/boot/dts/kirkwood-ts419-6282.dts rename to arch/arm/boot/dts/marvell/kirkwood-ts419-6282.dts diff --git a/arch/arm/boot/dts/kirkwood-ts419.dtsi b/arch/arm/boot/dts/marvell/kirkwood-ts419.dtsi similarity index 100% rename from arch/arm/boot/dts/kirkwood-ts419.dtsi rename to arch/arm/boot/dts/marvell/kirkwood-ts419.dtsi diff --git a/arch/arm/boot/dts/kirkwood.dtsi b/arch/arm/boot/dts/marvell/kirkwood.dtsi similarity index 100% rename from arch/arm/boot/dts/kirkwood.dtsi rename to arch/arm/boot/dts/marvell/kirkwood.dtsi diff --git a/arch/arm/boot/dts/mmp2-brownstone.dts b/arch/arm/boot/dts/marvell/mmp2-brownstone.dts similarity index 100% rename from arch/arm/boot/dts/mmp2-brownstone.dts rename to arch/arm/boot/dts/marvell/mmp2-brownstone.dts diff --git a/arch/arm/boot/dts/mmp2-olpc-xo-1-75.dts b/arch/arm/boot/dts/marvell/mmp2-olpc-xo-1-75.dts similarity index 100% rename from arch/arm/boot/dts/mmp2-olpc-xo-1-75.dts rename to arch/arm/boot/dts/marvell/mmp2-olpc-xo-1-75.dts diff --git a/arch/arm/boot/dts/mmp2.dtsi b/arch/arm/boot/dts/marvell/mmp2.dtsi similarity index 100% rename from arch/arm/boot/dts/mmp2.dtsi rename to arch/arm/boot/dts/marvell/mmp2.dtsi diff --git a/arch/arm/boot/dts/mmp3-dell-ariel.dts b/arch/arm/boot/dts/marvell/mmp3-dell-ariel.dts similarity index 100% rename from arch/arm/boot/dts/mmp3-dell-ariel.dts rename to arch/arm/boot/dts/marvell/mmp3-dell-ariel.dts diff --git a/arch/arm/boot/dts/mmp3.dtsi b/arch/arm/boot/dts/marvell/mmp3.dtsi similarity index 100% rename from arch/arm/boot/dts/mmp3.dtsi rename to arch/arm/boot/dts/marvell/mmp3.dtsi diff --git a/arch/arm/boot/dts/mvebu-linkstation-fan.dtsi b/arch/arm/boot/dts/marvell/mvebu-linkstation-fan.dtsi similarity index 100% rename from arch/arm/boot/dts/mvebu-linkstation-fan.dtsi rename to arch/arm/boot/dts/marvell/mvebu-linkstation-fan.dtsi diff --git a/arch/arm/boot/dts/mvebu-linkstation-gpio-simple.dtsi b/arch/arm/boot/dts/marvell/mvebu-linkstation-gpio-simple.dtsi similarity index 100% rename from arch/arm/boot/dts/mvebu-linkstation-gpio-simple.dtsi rename to arch/arm/boot/dts/marvell/mvebu-linkstation-gpio-simple.dtsi diff --git a/arch/arm/boot/dts/orion5x-kuroboxpro.dts b/arch/arm/boot/dts/marvell/orion5x-kuroboxpro.dts similarity index 100% rename from arch/arm/boot/dts/orion5x-kuroboxpro.dts rename to arch/arm/boot/dts/marvell/orion5x-kuroboxpro.dts diff --git a/arch/arm/boot/dts/orion5x-lacie-d2-network.dts b/arch/arm/boot/dts/marvell/orion5x-lacie-d2-network.dts similarity index 100% rename from arch/arm/boot/dts/orion5x-lacie-d2-network.dts rename to arch/arm/boot/dts/marvell/orion5x-lacie-d2-network.dts diff --git a/arch/arm/boot/dts/orion5x-lacie-ethernet-disk-mini-v2.dts b/arch/arm/boot/dts/marvell/orion5x-lacie-ethernet-disk-mini-v2.dts similarity index 100% rename from arch/arm/boot/dts/orion5x-lacie-ethernet-disk-mini-v2.dts rename to arch/arm/boot/dts/marvell/orion5x-lacie-ethernet-disk-mini-v2.dts diff --git a/arch/arm/boot/dts/orion5x-linkstation-lschl.dts b/arch/arm/boot/dts/marvell/orion5x-linkstation-lschl.dts similarity index 100% rename from arch/arm/boot/dts/orion5x-linkstation-lschl.dts rename to arch/arm/boot/dts/marvell/orion5x-linkstation-lschl.dts diff --git a/arch/arm/boot/dts/orion5x-linkstation-lsgl.dts b/arch/arm/boot/dts/marvell/orion5x-linkstation-lsgl.dts similarity index 100% rename from arch/arm/boot/dts/orion5x-linkstation-lsgl.dts rename to arch/arm/boot/dts/marvell/orion5x-linkstation-lsgl.dts diff --git a/arch/arm/boot/dts/orion5x-linkstation-lswtgl.dts b/arch/arm/boot/dts/marvell/orion5x-linkstation-lswtgl.dts similarity index 100% rename from arch/arm/boot/dts/orion5x-linkstation-lswtgl.dts rename to arch/arm/boot/dts/marvell/orion5x-linkstation-lswtgl.dts diff --git a/arch/arm/boot/dts/orion5x-linkstation.dtsi b/arch/arm/boot/dts/marvell/orion5x-linkstation.dtsi similarity index 100% rename from arch/arm/boot/dts/orion5x-linkstation.dtsi rename to arch/arm/boot/dts/marvell/orion5x-linkstation.dtsi diff --git a/arch/arm/boot/dts/orion5x-lswsgl.dts b/arch/arm/boot/dts/marvell/orion5x-lswsgl.dts similarity index 100% rename from arch/arm/boot/dts/orion5x-lswsgl.dts rename to arch/arm/boot/dts/marvell/orion5x-lswsgl.dts diff --git a/arch/arm/boot/dts/orion5x-maxtor-shared-storage-2.dts b/arch/arm/boot/dts/marvell/orion5x-maxtor-shared-storage-2.dts similarity index 100% rename from arch/arm/boot/dts/orion5x-maxtor-shared-storage-2.dts rename to arch/arm/boot/dts/marvell/orion5x-maxtor-shared-storage-2.dts diff --git a/arch/arm/boot/dts/orion5x-mv88f5181.dtsi b/arch/arm/boot/dts/marvell/orion5x-mv88f5181.dtsi similarity index 100% rename from arch/arm/boot/dts/orion5x-mv88f5181.dtsi rename to arch/arm/boot/dts/marvell/orion5x-mv88f5181.dtsi diff --git a/arch/arm/boot/dts/orion5x-mv88f5182.dtsi b/arch/arm/boot/dts/marvell/orion5x-mv88f5182.dtsi similarity index 100% rename from arch/arm/boot/dts/orion5x-mv88f5182.dtsi rename to arch/arm/boot/dts/marvell/orion5x-mv88f5182.dtsi diff --git a/arch/arm/boot/dts/orion5x-netgear-wnr854t.dts b/arch/arm/boot/dts/marvell/orion5x-netgear-wnr854t.dts similarity index 100% rename from arch/arm/boot/dts/orion5x-netgear-wnr854t.dts rename to arch/arm/boot/dts/marvell/orion5x-netgear-wnr854t.dts diff --git a/arch/arm/boot/dts/orion5x-rd88f5182-nas.dts b/arch/arm/boot/dts/marvell/orion5x-rd88f5182-nas.dts similarity index 100% rename from arch/arm/boot/dts/orion5x-rd88f5182-nas.dts rename to arch/arm/boot/dts/marvell/orion5x-rd88f5182-nas.dts diff --git a/arch/arm/boot/dts/orion5x.dtsi b/arch/arm/boot/dts/marvell/orion5x.dtsi similarity index 100% rename from arch/arm/boot/dts/orion5x.dtsi rename to arch/arm/boot/dts/marvell/orion5x.dtsi diff --git a/arch/arm/boot/dts/pxa168-aspenite.dts b/arch/arm/boot/dts/marvell/pxa168-aspenite.dts similarity index 100% rename from arch/arm/boot/dts/pxa168-aspenite.dts rename to arch/arm/boot/dts/marvell/pxa168-aspenite.dts diff --git a/arch/arm/boot/dts/pxa168.dtsi b/arch/arm/boot/dts/marvell/pxa168.dtsi similarity index 100% rename from arch/arm/boot/dts/pxa168.dtsi rename to arch/arm/boot/dts/marvell/pxa168.dtsi diff --git a/arch/arm/boot/dts/pxa910-dkb.dts b/arch/arm/boot/dts/marvell/pxa910-dkb.dts similarity index 100% rename from arch/arm/boot/dts/pxa910-dkb.dts rename to arch/arm/boot/dts/marvell/pxa910-dkb.dts diff --git a/arch/arm/boot/dts/pxa910.dtsi b/arch/arm/boot/dts/marvell/pxa910.dtsi similarity index 100% rename from arch/arm/boot/dts/pxa910.dtsi rename to arch/arm/boot/dts/marvell/pxa910.dtsi diff --git a/arch/arm/boot/dts/mediatek/Makefile b/arch/arm/boot/dts/mediatek/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..1957947cb41ce86ed101466bf822d4e2dfdfbb61 --- /dev/null +++ b/arch/arm/boot/dts/mediatek/Makefile @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: GPL-2.0 +dtb-$(CONFIG_ARCH_MEDIATEK) += \ + mt2701-evb.dtb \ + mt6580-evbp1.dtb \ + mt6582-prestigio-pmt5008-3g.dtb \ + mt6589-aquaris5.dtb \ + mt6589-fairphone-fp1.dtb \ + mt6592-evb.dtb \ + mt7623a-rfb-emmc.dtb \ + mt7623a-rfb-nand.dtb \ + mt7623n-rfb-emmc.dtb \ + mt7623n-bananapi-bpi-r2.dtb \ + mt7629-rfb.dtb \ + mt8127-moose.dtb \ + mt8135-evbp1.dtb diff --git a/arch/arm/boot/dts/mt2701-evb.dts b/arch/arm/boot/dts/mediatek/mt2701-evb.dts similarity index 100% rename from arch/arm/boot/dts/mt2701-evb.dts rename to arch/arm/boot/dts/mediatek/mt2701-evb.dts diff --git a/arch/arm/boot/dts/mt2701-pinfunc.h b/arch/arm/boot/dts/mediatek/mt2701-pinfunc.h similarity index 100% rename from arch/arm/boot/dts/mt2701-pinfunc.h rename to arch/arm/boot/dts/mediatek/mt2701-pinfunc.h diff --git a/arch/arm/boot/dts/mt2701.dtsi b/arch/arm/boot/dts/mediatek/mt2701.dtsi similarity index 100% rename from arch/arm/boot/dts/mt2701.dtsi rename to arch/arm/boot/dts/mediatek/mt2701.dtsi diff --git a/arch/arm/boot/dts/mt6323.dtsi b/arch/arm/boot/dts/mediatek/mt6323.dtsi similarity index 100% rename from arch/arm/boot/dts/mt6323.dtsi rename to arch/arm/boot/dts/mediatek/mt6323.dtsi diff --git a/arch/arm/boot/dts/mt6580-evbp1.dts b/arch/arm/boot/dts/mediatek/mt6580-evbp1.dts similarity index 100% rename from arch/arm/boot/dts/mt6580-evbp1.dts rename to arch/arm/boot/dts/mediatek/mt6580-evbp1.dts diff --git a/arch/arm/boot/dts/mt6580.dtsi b/arch/arm/boot/dts/mediatek/mt6580.dtsi similarity index 100% rename from arch/arm/boot/dts/mt6580.dtsi rename to arch/arm/boot/dts/mediatek/mt6580.dtsi diff --git a/arch/arm/boot/dts/mt6582-prestigio-pmt5008-3g.dts b/arch/arm/boot/dts/mediatek/mt6582-prestigio-pmt5008-3g.dts similarity index 100% rename from arch/arm/boot/dts/mt6582-prestigio-pmt5008-3g.dts rename to arch/arm/boot/dts/mediatek/mt6582-prestigio-pmt5008-3g.dts diff --git a/arch/arm/boot/dts/mt6582.dtsi b/arch/arm/boot/dts/mediatek/mt6582.dtsi similarity index 100% rename from arch/arm/boot/dts/mt6582.dtsi rename to arch/arm/boot/dts/mediatek/mt6582.dtsi diff --git a/arch/arm/boot/dts/mt6589-aquaris5.dts b/arch/arm/boot/dts/mediatek/mt6589-aquaris5.dts similarity index 100% rename from arch/arm/boot/dts/mt6589-aquaris5.dts rename to arch/arm/boot/dts/mediatek/mt6589-aquaris5.dts diff --git a/arch/arm/boot/dts/mt6589-fairphone-fp1.dts b/arch/arm/boot/dts/mediatek/mt6589-fairphone-fp1.dts similarity index 100% rename from arch/arm/boot/dts/mt6589-fairphone-fp1.dts rename to arch/arm/boot/dts/mediatek/mt6589-fairphone-fp1.dts diff --git a/arch/arm/boot/dts/mt6589.dtsi b/arch/arm/boot/dts/mediatek/mt6589.dtsi similarity index 100% rename from arch/arm/boot/dts/mt6589.dtsi rename to arch/arm/boot/dts/mediatek/mt6589.dtsi diff --git a/arch/arm/boot/dts/mt6592-evb.dts b/arch/arm/boot/dts/mediatek/mt6592-evb.dts similarity index 100% rename from arch/arm/boot/dts/mt6592-evb.dts rename to arch/arm/boot/dts/mediatek/mt6592-evb.dts diff --git a/arch/arm/boot/dts/mt6592.dtsi b/arch/arm/boot/dts/mediatek/mt6592.dtsi similarity index 100% rename from arch/arm/boot/dts/mt6592.dtsi rename to arch/arm/boot/dts/mediatek/mt6592.dtsi diff --git a/arch/arm/boot/dts/mt7623.dtsi b/arch/arm/boot/dts/mediatek/mt7623.dtsi similarity index 99% rename from arch/arm/boot/dts/mt7623.dtsi rename to arch/arm/boot/dts/mediatek/mt7623.dtsi index 11379c3e6b4ca75af0c6cc5efa555770071fde81..f0b4a09004b31785733a2e6a5288014d40b5a9e6 100644 --- a/arch/arm/boot/dts/mt7623.dtsi +++ b/arch/arm/boot/dts/mediatek/mt7623.dtsi @@ -980,6 +980,18 @@ #address-cells = <1>; #size-cells = <0>; status = "disabled"; + + gmac0: mac@0 { + compatible = "mediatek,eth-mac"; + reg = <0>; + status = "disabled"; + }; + + gmac1: mac@1 { + compatible = "mediatek,eth-mac"; + reg = <1>; + status = "disabled"; + }; }; crypto: crypto@1b240000 { diff --git a/arch/arm/boot/dts/mt7623a-rfb-emmc.dts b/arch/arm/boot/dts/mediatek/mt7623a-rfb-emmc.dts similarity index 79% rename from arch/arm/boot/dts/mt7623a-rfb-emmc.dts rename to arch/arm/boot/dts/mediatek/mt7623a-rfb-emmc.dts index e8b4b6d30d197efa2fbfd619cafd127b48010ff6..5654284bab0186675ffe85453eb7aaaa68a29480 100644 --- a/arch/arm/boot/dts/mt7623a-rfb-emmc.dts +++ b/arch/arm/boot/dts/mediatek/mt7623a-rfb-emmc.dts @@ -112,75 +112,31 @@ status = "okay"; }; -ð { - status = "okay"; +&switch0 { + ports { + port@0 { + status = "okay"; + label = "lan0"; + }; + + port@1 { + status = "okay"; + label = "lan1"; + }; - gmac0: mac@0 { - compatible = "mediatek,eth-mac"; - reg = <0>; - phy-mode = "trgmii"; + port@2 { + status = "okay"; + label = "lan2"; + }; - fixed-link { - speed = <1000>; - full-duplex; - pause; + port@3 { + status = "okay"; + label = "lan3"; }; - }; - mdio-bus { - #address-cells = <1>; - #size-cells = <0>; - - switch@0 { - compatible = "mediatek,mt7530"; - reg = <0>; - mediatek,mcm; - resets = <ðsys MT2701_ETHSYS_MCM_RST>; - reset-names = "mcm"; - core-supply = <&mt6323_vpa_reg>; - io-supply = <&mt6323_vemc3v3_reg>; - - ports { - #address-cells = <1>; - #size-cells = <0>; - - port@0 { - reg = <0>; - label = "lan0"; - }; - - port@1 { - reg = <1>; - label = "lan1"; - }; - - port@2 { - reg = <2>; - label = "lan2"; - }; - - port@3 { - reg = <3>; - label = "lan3"; - }; - - port@4 { - reg = <4>; - label = "wan"; - }; - - port@6 { - reg = <6>; - label = "cpu"; - ethernet = <&gmac0>; - phy-mode = "trgmii"; - - fixed-link { - speed = <1000>; - full-duplex; - }; - }; - }; + port@4 { + status = "okay"; + label = "wan"; }; }; }; diff --git a/arch/arm/boot/dts/mt7623a-rfb-nand.dts b/arch/arm/boot/dts/mediatek/mt7623a-rfb-nand.dts similarity index 81% rename from arch/arm/boot/dts/mt7623a-rfb-nand.dts rename to arch/arm/boot/dts/mediatek/mt7623a-rfb-nand.dts index 61f5da68d4b0ce4db9817f582b1f829159542ea3..afd177b3b5165ccabd3a5bffda9d3c87b8259ae1 100644 --- a/arch/arm/boot/dts/mt7623a-rfb-nand.dts +++ b/arch/arm/boot/dts/mediatek/mt7623a-rfb-nand.dts @@ -116,75 +116,31 @@ status = "okay"; }; -ð { - status = "okay"; +&switch0 { + ports { + port@0 { + status = "okay"; + label = "lan0"; + }; - gmac0: mac@0 { - compatible = "mediatek,eth-mac"; - reg = <0>; - phy-mode = "trgmii"; + port@1 { + status = "okay"; + label = "lan1"; + }; - fixed-link { - speed = <1000>; - full-duplex; - pause; + port@2 { + status = "okay"; + label = "lan2"; }; - }; - mdio-bus { - #address-cells = <1>; - #size-cells = <0>; - - switch@0 { - compatible = "mediatek,mt7530"; - reg = <0>; - mediatek,mcm; - resets = <ðsys MT2701_ETHSYS_MCM_RST>; - reset-names = "mcm"; - core-supply = <&mt6323_vpa_reg>; - io-supply = <&mt6323_vemc3v3_reg>; - - ports { - #address-cells = <1>; - #size-cells = <0>; - - port@0 { - reg = <0>; - label = "lan0"; - }; - - port@1 { - reg = <1>; - label = "lan1"; - }; - - port@2 { - reg = <2>; - label = "lan2"; - }; - - port@3 { - reg = <3>; - label = "lan3"; - }; - - port@4 { - reg = <4>; - label = "wan"; - }; - - port@6 { - reg = <6>; - label = "cpu"; - ethernet = <&gmac0>; - phy-mode = "trgmii"; - - fixed-link { - speed = <1000>; - full-duplex; - }; - }; - }; + port@3 { + status = "okay"; + label = "lan3"; + }; + + port@4 { + status = "okay"; + label = "wan"; }; }; }; diff --git a/arch/arm/boot/dts/mediatek/mt7623a.dtsi b/arch/arm/boot/dts/mediatek/mt7623a.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..bcf909d58a1cca6932a813b589fc397970a85246 --- /dev/null +++ b/arch/arm/boot/dts/mediatek/mt7623a.dtsi @@ -0,0 +1,147 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2017-2018 MediaTek Inc. + * Author: Sean Wang + * + */ + +/dts-v1/; +#include +#include "mt7623.dtsi" + +&afe { + power-domains = <&scpsys MT7623A_POWER_DOMAIN_IFR_MSC>; +}; + +&crypto { + power-domains = <&scpsys MT7623A_POWER_DOMAIN_ETH>; +}; + +&gmac0 { + status = "okay"; + phy-mode = "trgmii"; + + fixed-link { + speed = <1000>; + full-duplex; + pause; + }; +}; + +&gmac1 { + status = "okay"; + phy-mode = "rgmii"; + + fixed-link { + speed = <1000>; + full-duplex; + pause; + }; +}; + +ð { + status = "okay"; + power-domains = <&scpsys MT7623A_POWER_DOMAIN_ETH>; + + mdio: mdio-bus { + #address-cells = <1>; + #size-cells = <0>; + + switch0: switch@1f { + compatible = "mediatek,mt7530"; + reg = <0x1f>; + mediatek,mcm; + resets = <ðsys MT2701_ETHSYS_MCM_RST>; + reset-names = "mcm"; + core-supply = <&mt6323_vpa_reg>; + io-supply = <&mt6323_vemc3v3_reg>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + status = "disabled"; + reg = <0>; + label = "swp0"; + }; + + port@1 { + status = "disabled"; + reg = <1>; + label = "swp1"; + }; + + port@2 { + status = "disabled"; + reg = <2>; + label = "swp2"; + }; + + port@3 { + status = "disabled"; + reg = <3>; + label = "swp3"; + }; + + port@4 { + status = "disabled"; + reg = <4>; + label = "swp4"; + }; + + port@5 { + reg = <5>; + label = "cpu"; + ethernet = <&gmac1>; + phy-mode = "rgmii"; + + fixed-link { + speed = <1000>; + full-duplex; + pause; + }; + }; + + port@6 { + reg = <6>; + label = "cpu"; + ethernet = <&gmac0>; + phy-mode = "trgmii"; + + fixed-link { + speed = <1000>; + full-duplex; + pause; + }; + }; + }; + }; + }; +}; + +&nandc { + power-domains = <&scpsys MT7623A_POWER_DOMAIN_IFR_MSC>; +}; + +&pcie { + power-domains = <&scpsys MT7623A_POWER_DOMAIN_HIF>; +}; + +&scpsys { + compatible = "mediatek,mt7623a-scpsys"; + clocks = <&topckgen CLK_TOP_ETHIF_SEL>; + clock-names = "ethif"; +}; + +&usb0 { + power-domains = <&scpsys MT7623A_POWER_DOMAIN_IFR_MSC>; +}; + +&usb1 { + power-domains = <&scpsys MT7623A_POWER_DOMAIN_HIF>; +}; + +&usb2 { + power-domains = <&scpsys MT7623A_POWER_DOMAIN_HIF>; +}; diff --git a/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts b/arch/arm/boot/dts/mediatek/mt7623n-bananapi-bpi-r2.dts similarity index 93% rename from arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts rename to arch/arm/boot/dts/mediatek/mt7623n-bananapi-bpi-r2.dts index ece61a6a7a897028d45b8bf503f3c1ee59e30c80..a37f3fa223c72de7f6f5305ea593e2ff889e190b 100644 --- a/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts +++ b/arch/arm/boot/dts/mediatek/mt7623n-bananapi-bpi-r2.dts @@ -171,28 +171,38 @@ }; }; -ð { +&gmac0 { status = "okay"; + phy-mode = "trgmii"; - gmac0: mac@0 { - compatible = "mediatek,eth-mac"; - reg = <0>; - phy-mode = "trgmii"; + fixed-link { + speed = <1000>; + full-duplex; + pause; + }; +}; - fixed-link { - speed = <1000>; - full-duplex; - pause; - }; +&gmac1 { + status = "okay"; + phy-mode = "rgmii"; + + fixed-link { + speed = <1000>; + full-duplex; + pause; }; +}; + +ð { + status = "okay"; - mdio: mdio-bus { + mdio-bus { #address-cells = <1>; #size-cells = <0>; - switch@0 { + switch@1f { compatible = "mediatek,mt7530"; - reg = <0>; + reg = <0x1f>; reset-gpios = <&pio 33 0>; core-supply = <&mt6323_vpa_reg>; io-supply = <&mt6323_vemc3v3_reg>; @@ -226,6 +236,19 @@ label = "lan3"; }; + port@5 { + reg = <5>; + label = "cpu"; + ethernet = <&gmac1>; + phy-mode = "rgmii"; + + fixed-link { + speed = <1000>; + full-duplex; + pause; + }; + }; + port@6 { reg = <6>; label = "cpu"; diff --git a/arch/arm/boot/dts/mt7623n-rfb-emmc.dts b/arch/arm/boot/dts/mediatek/mt7623n-rfb-emmc.dts similarity index 95% rename from arch/arm/boot/dts/mt7623n-rfb-emmc.dts rename to arch/arm/boot/dts/mediatek/mt7623n-rfb-emmc.dts index bf67a8e9be59c857b810de408168dc0a59b39f07..34994f3f5a4b2da94ecf1c10d454ab2da943514d 100644 --- a/arch/arm/boot/dts/mt7623n-rfb-emmc.dts +++ b/arch/arm/boot/dts/mediatek/mt7623n-rfb-emmc.dts @@ -156,27 +156,25 @@ }; }; -ð { +&gmac0 { status = "okay"; + phy-mode = "trgmii"; - gmac0: mac@0 { - compatible = "mediatek,eth-mac"; - reg = <0>; - phy-mode = "trgmii"; - - fixed-link { - speed = <1000>; - full-duplex; - pause; - }; + fixed-link { + speed = <1000>; + full-duplex; + pause; }; +}; - mac@1 { - compatible = "mediatek,eth-mac"; - reg = <1>; - phy-mode = "rgmii"; - phy-handle = <&phy5>; - }; +&gmac1 { + status = "okay"; + phy-mode = "rgmii"; + phy-handle = <&phy5>; +}; + +ð { + status = "okay"; mdio-bus { #address-cells = <1>; @@ -187,9 +185,9 @@ phy-mode = "rgmii-rxid"; }; - switch@0 { + switch@1f { compatible = "mediatek,mt7530"; - reg = <0>; + reg = <0x1f>; reset-gpios = <&pio 33 0>; core-supply = <&mt6323_vpa_reg>; io-supply = <&mt6323_vemc3v3_reg>; @@ -232,6 +230,7 @@ fixed-link { speed = <1000>; full-duplex; + pause; }; }; }; diff --git a/arch/arm/boot/dts/mt7623n.dtsi b/arch/arm/boot/dts/mediatek/mt7623n.dtsi similarity index 100% rename from arch/arm/boot/dts/mt7623n.dtsi rename to arch/arm/boot/dts/mediatek/mt7623n.dtsi diff --git a/arch/arm/boot/dts/mt7629-rfb.dts b/arch/arm/boot/dts/mediatek/mt7629-rfb.dts similarity index 100% rename from arch/arm/boot/dts/mt7629-rfb.dts rename to arch/arm/boot/dts/mediatek/mt7629-rfb.dts diff --git a/arch/arm/boot/dts/mt7629.dtsi b/arch/arm/boot/dts/mediatek/mt7629.dtsi similarity index 100% rename from arch/arm/boot/dts/mt7629.dtsi rename to arch/arm/boot/dts/mediatek/mt7629.dtsi diff --git a/arch/arm/boot/dts/mt8127-moose.dts b/arch/arm/boot/dts/mediatek/mt8127-moose.dts similarity index 100% rename from arch/arm/boot/dts/mt8127-moose.dts rename to arch/arm/boot/dts/mediatek/mt8127-moose.dts diff --git a/arch/arm/boot/dts/mt8127.dtsi b/arch/arm/boot/dts/mediatek/mt8127.dtsi similarity index 100% rename from arch/arm/boot/dts/mt8127.dtsi rename to arch/arm/boot/dts/mediatek/mt8127.dtsi diff --git a/arch/arm/boot/dts/mt8135-evbp1.dts b/arch/arm/boot/dts/mediatek/mt8135-evbp1.dts similarity index 100% rename from arch/arm/boot/dts/mt8135-evbp1.dts rename to arch/arm/boot/dts/mediatek/mt8135-evbp1.dts diff --git a/arch/arm/boot/dts/mt8135.dtsi b/arch/arm/boot/dts/mediatek/mt8135.dtsi similarity index 100% rename from arch/arm/boot/dts/mt8135.dtsi rename to arch/arm/boot/dts/mediatek/mt8135.dtsi diff --git a/arch/arm/boot/dts/microchip/Makefile b/arch/arm/boot/dts/microchip/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..0f5193d05a31c25834c7018537aeb19930b10832 --- /dev/null +++ b/arch/arm/boot/dts/microchip/Makefile @@ -0,0 +1,108 @@ +# SPDX-License-Identifier: GPL-2.0 +DTC_FLAGS_at91-sam9x60_curiosity := -@ +DTC_FLAGS_at91-sam9x60ek := -@ +DTC_FLAGS_at91-sama5d27_som1_ek := -@ +DTC_FLAGS_at91-sama5d27_wlsom1_ek := -@ +DTC_FLAGS_at91-sama5d2_icp := -@ +DTC_FLAGS_at91-sama5d2_ptc_ek := -@ +DTC_FLAGS_at91-sama5d2_xplained := -@ +DTC_FLAGS_at91-sama5d3_eds := -@ +DTC_FLAGS_at91-sama5d3_xplained := -@ +DTC_FLAGS_at91-sama5d4_xplained := -@ +DTC_FLAGS_at91-sama7g5ek := -@ +dtb-$(CONFIG_SOC_AT91RM9200) += \ + at91rm9200ek.dtb \ + mpa1600.dtb +dtb-$(CONFIG_SOC_AT91SAM9) += \ + animeo_ip.dtb \ + at91-qil_a9260.dtb \ + aks-cdu.dtb \ + ethernut5.dtb \ + evk-pro3.dtb \ + tny_a9260.dtb \ + usb_a9260.dtb \ + at91sam9260ek.dtb \ + at91sam9261ek.dtb \ + at91sam9263ek.dtb \ + at91-sam9_l9260.dtb \ + tny_a9263.dtb \ + usb_a9263.dtb \ + at91-foxg20.dtb \ + at91-kizbox.dtb \ + at91-lmu5000.dtb \ + at91sam9g20ek.dtb \ + at91sam9g20ek_2mmc.dtb \ + tny_a9g20.dtb \ + usb_a9g20.dtb \ + usb_a9g20_lpw.dtb \ + at91sam9m10g45ek.dtb \ + pm9g45.dtb \ + at91sam9n12ek.dtb \ + at91sam9rlek.dtb \ + at91-ariag25.dtb \ + at91-ariettag25.dtb \ + at91-cosino_mega2560.dtb \ + at91-kizboxmini-base.dtb \ + at91-kizboxmini-mb.dtb \ + at91-kizboxmini-rd.dtb \ + at91-q5xr5.dtb \ + at91-smartkiz.dtb \ + at91-wb45n.dtb \ + at91sam9g15ek.dtb \ + at91sam9g25-gardena-smart-gateway.dtb \ + at91sam9g25ek.dtb \ + at91sam9g35ek.dtb \ + at91sam9x25ek.dtb \ + at91sam9x35ek.dtb +# Enables support for device-tree overlays +DTC_FLAGS_at91-sam9x60_curiosity := -@ +DTC_FLAGS_at91-sam9x60ek := -@ +dtb-$(CONFIG_SOC_SAM9X60) += \ + at91-sam9x60_curiosity.dtb \ + at91-sam9x60ek.dtb +# Enables support for device-tree overlays +DTC_FLAGS_at91-sama5d27_som1_ek := -@ +DTC_FLAGS_at91-sama5d27_wlsom1_ek := -@ +DTC_FLAGS_at91-sama5d2_icp := -@ +DTC_FLAGS_at91-sama5d2_ptc_ek := -@ +DTC_FLAGS_at91-sama5d2_xplained := -@ +DTC_FLAGS_at91-sama5d3_eds := -@ +DTC_FLAGS_at91-sama5d3_xplained := -@ +DTC_FLAGS_at91-sama5d4_xplained := -@ +dtb-$(CONFIG_SOC_SAM_V7) += \ + at91-kizbox2-2.dtb \ + at91-kizbox3-hs.dtb \ + at91-nattis-2-natte-2.dtb \ + at91-sama5d27_som1_ek.dtb \ + at91-sama5d27_wlsom1_ek.dtb \ + at91-sama5d2_icp.dtb \ + at91-sama5d2_ptc_ek.dtb \ + at91-sama5d2_xplained.dtb \ + at91-sama5d3_eds.dtb \ + at91-sama5d3_ksz9477_evb.dtb \ + at91-sama5d3_xplained.dtb \ + at91-dvk_som60.dtb \ + at91-gatwick.dtb \ + at91-tse850-3.dtb \ + at91-wb50n.dtb \ + sama5d31ek.dtb \ + sama5d33ek.dtb \ + sama5d34ek.dtb \ + sama5d35ek.dtb \ + sama5d36ek.dtb \ + sama5d36ek_cmp.dtb \ + at91-sama5d4_ma5d4evk.dtb \ + at91-sama5d4_xplained.dtb \ + at91-sama5d4ek.dtb \ + at91-vinco.dtb +# Enables support for device-tree overlays +DTC_FLAGS_at91-sama7g5ek := -@ +dtb-$(CONFIG_SOC_SAMA7G5) += \ + at91-sama7g5ek.dtb + +dtb-$(CONFIG_SOC_LAN966) += \ + lan966x-kontron-kswitch-d10-mmt-6g-2gs.dtb \ + lan966x-kontron-kswitch-d10-mmt-8g.dtb \ + lan966x-pcb8290.dtb \ + lan966x-pcb8291.dtb \ + lan966x-pcb8309.dtb diff --git a/arch/arm/boot/dts/aks-cdu.dts b/arch/arm/boot/dts/microchip/aks-cdu.dts similarity index 100% rename from arch/arm/boot/dts/aks-cdu.dts rename to arch/arm/boot/dts/microchip/aks-cdu.dts diff --git a/arch/arm/boot/dts/animeo_ip.dts b/arch/arm/boot/dts/microchip/animeo_ip.dts similarity index 100% rename from arch/arm/boot/dts/animeo_ip.dts rename to arch/arm/boot/dts/microchip/animeo_ip.dts diff --git a/arch/arm/boot/dts/at91-ariag25.dts b/arch/arm/boot/dts/microchip/at91-ariag25.dts similarity index 100% rename from arch/arm/boot/dts/at91-ariag25.dts rename to arch/arm/boot/dts/microchip/at91-ariag25.dts diff --git a/arch/arm/boot/dts/at91-ariettag25.dts b/arch/arm/boot/dts/microchip/at91-ariettag25.dts similarity index 100% rename from arch/arm/boot/dts/at91-ariettag25.dts rename to arch/arm/boot/dts/microchip/at91-ariettag25.dts diff --git a/arch/arm/boot/dts/at91-cosino.dtsi b/arch/arm/boot/dts/microchip/at91-cosino.dtsi similarity index 100% rename from arch/arm/boot/dts/at91-cosino.dtsi rename to arch/arm/boot/dts/microchip/at91-cosino.dtsi diff --git a/arch/arm/boot/dts/at91-cosino_mega2560.dts b/arch/arm/boot/dts/microchip/at91-cosino_mega2560.dts similarity index 100% rename from arch/arm/boot/dts/at91-cosino_mega2560.dts rename to arch/arm/boot/dts/microchip/at91-cosino_mega2560.dts diff --git a/arch/arm/boot/dts/at91-dvk_som60.dts b/arch/arm/boot/dts/microchip/at91-dvk_som60.dts similarity index 100% rename from arch/arm/boot/dts/at91-dvk_som60.dts rename to arch/arm/boot/dts/microchip/at91-dvk_som60.dts diff --git a/arch/arm/boot/dts/at91-dvk_su60_somc.dtsi b/arch/arm/boot/dts/microchip/at91-dvk_su60_somc.dtsi similarity index 100% rename from arch/arm/boot/dts/at91-dvk_su60_somc.dtsi rename to arch/arm/boot/dts/microchip/at91-dvk_su60_somc.dtsi diff --git a/arch/arm/boot/dts/at91-dvk_su60_somc_lcm.dtsi b/arch/arm/boot/dts/microchip/at91-dvk_su60_somc_lcm.dtsi similarity index 100% rename from arch/arm/boot/dts/at91-dvk_su60_somc_lcm.dtsi rename to arch/arm/boot/dts/microchip/at91-dvk_su60_somc_lcm.dtsi diff --git a/arch/arm/boot/dts/at91-foxg20.dts b/arch/arm/boot/dts/microchip/at91-foxg20.dts similarity index 100% rename from arch/arm/boot/dts/at91-foxg20.dts rename to arch/arm/boot/dts/microchip/at91-foxg20.dts diff --git a/arch/arm/boot/dts/at91-gatwick.dts b/arch/arm/boot/dts/microchip/at91-gatwick.dts similarity index 100% rename from arch/arm/boot/dts/at91-gatwick.dts rename to arch/arm/boot/dts/microchip/at91-gatwick.dts diff --git a/arch/arm/boot/dts/at91-kizbox.dts b/arch/arm/boot/dts/microchip/at91-kizbox.dts similarity index 100% rename from arch/arm/boot/dts/at91-kizbox.dts rename to arch/arm/boot/dts/microchip/at91-kizbox.dts diff --git a/arch/arm/boot/dts/at91-kizbox2-2.dts b/arch/arm/boot/dts/microchip/at91-kizbox2-2.dts similarity index 100% rename from arch/arm/boot/dts/at91-kizbox2-2.dts rename to arch/arm/boot/dts/microchip/at91-kizbox2-2.dts diff --git a/arch/arm/boot/dts/at91-kizbox2-common.dtsi b/arch/arm/boot/dts/microchip/at91-kizbox2-common.dtsi similarity index 100% rename from arch/arm/boot/dts/at91-kizbox2-common.dtsi rename to arch/arm/boot/dts/microchip/at91-kizbox2-common.dtsi diff --git a/arch/arm/boot/dts/at91-kizbox3-hs.dts b/arch/arm/boot/dts/microchip/at91-kizbox3-hs.dts similarity index 99% rename from arch/arm/boot/dts/at91-kizbox3-hs.dts rename to arch/arm/boot/dts/microchip/at91-kizbox3-hs.dts index 7075df6549e99ad97b15ace959a2fc0bc7e4153c..fec7269088d1091de53bd2fd6e27fc6eadd3e846 100644 --- a/arch/arm/boot/dts/at91-kizbox3-hs.dts +++ b/arch/arm/boot/dts/microchip/at91-kizbox3-hs.dts @@ -225,7 +225,7 @@ pinctrl_pio_io_reset: gpio_io_reset { pinmux = ; bias-disable; - drive-open-drain = <1>; + drive-open-drain; output-low; }; pinctrl_pio_input: gpio_input { diff --git a/arch/arm/boot/dts/at91-kizbox3_common.dtsi b/arch/arm/boot/dts/microchip/at91-kizbox3_common.dtsi similarity index 99% rename from arch/arm/boot/dts/at91-kizbox3_common.dtsi rename to arch/arm/boot/dts/microchip/at91-kizbox3_common.dtsi index abe27adfa4d65ac050b4fa9fd72c7fe3651f18cf..46566462841990483372f5af1c394601a63a123b 100644 --- a/arch/arm/boot/dts/at91-kizbox3_common.dtsi +++ b/arch/arm/boot/dts/microchip/at91-kizbox3_common.dtsi @@ -211,7 +211,7 @@ pinmux = , //DATA ; //CLK bias-disable; - drive-open-drain = <1>; + drive-open-drain; }; pinctrl_pwm0 { diff --git a/arch/arm/boot/dts/at91-kizboxmini-base.dts b/arch/arm/boot/dts/microchip/at91-kizboxmini-base.dts similarity index 100% rename from arch/arm/boot/dts/at91-kizboxmini-base.dts rename to arch/arm/boot/dts/microchip/at91-kizboxmini-base.dts diff --git a/arch/arm/boot/dts/at91-kizboxmini-common.dtsi b/arch/arm/boot/dts/microchip/at91-kizboxmini-common.dtsi similarity index 100% rename from arch/arm/boot/dts/at91-kizboxmini-common.dtsi rename to arch/arm/boot/dts/microchip/at91-kizboxmini-common.dtsi diff --git a/arch/arm/boot/dts/at91-kizboxmini-mb.dts b/arch/arm/boot/dts/microchip/at91-kizboxmini-mb.dts similarity index 100% rename from arch/arm/boot/dts/at91-kizboxmini-mb.dts rename to arch/arm/boot/dts/microchip/at91-kizboxmini-mb.dts diff --git a/arch/arm/boot/dts/at91-kizboxmini-rd.dts b/arch/arm/boot/dts/microchip/at91-kizboxmini-rd.dts similarity index 100% rename from arch/arm/boot/dts/at91-kizboxmini-rd.dts rename to arch/arm/boot/dts/microchip/at91-kizboxmini-rd.dts diff --git a/arch/arm/boot/dts/at91-linea.dtsi b/arch/arm/boot/dts/microchip/at91-linea.dtsi similarity index 100% rename from arch/arm/boot/dts/at91-linea.dtsi rename to arch/arm/boot/dts/microchip/at91-linea.dtsi diff --git a/arch/arm/boot/dts/at91-lmu5000.dts b/arch/arm/boot/dts/microchip/at91-lmu5000.dts similarity index 100% rename from arch/arm/boot/dts/at91-lmu5000.dts rename to arch/arm/boot/dts/microchip/at91-lmu5000.dts diff --git a/arch/arm/boot/dts/at91-natte.dtsi b/arch/arm/boot/dts/microchip/at91-natte.dtsi similarity index 100% rename from arch/arm/boot/dts/at91-natte.dtsi rename to arch/arm/boot/dts/microchip/at91-natte.dtsi diff --git a/arch/arm/boot/dts/at91-nattis-2-natte-2.dts b/arch/arm/boot/dts/microchip/at91-nattis-2-natte-2.dts similarity index 100% rename from arch/arm/boot/dts/at91-nattis-2-natte-2.dts rename to arch/arm/boot/dts/microchip/at91-nattis-2-natte-2.dts diff --git a/arch/arm/boot/dts/at91-q5xr5.dts b/arch/arm/boot/dts/microchip/at91-q5xr5.dts similarity index 100% rename from arch/arm/boot/dts/at91-q5xr5.dts rename to arch/arm/boot/dts/microchip/at91-q5xr5.dts diff --git a/arch/arm/boot/dts/at91-qil_a9260.dts b/arch/arm/boot/dts/microchip/at91-qil_a9260.dts similarity index 99% rename from arch/arm/boot/dts/at91-qil_a9260.dts rename to arch/arm/boot/dts/microchip/at91-qil_a9260.dts index 9d26f999634839770c412e11f4e198f2b559afdf..5ccb3c139592d0db6d5e076547f174be647e614d 100644 --- a/arch/arm/boot/dts/at91-qil_a9260.dts +++ b/arch/arm/boot/dts/microchip/at91-qil_a9260.dts @@ -108,7 +108,7 @@ status = "okay"; }; - shdwc@fffffd10 { + shdwc: poweroff@fffffd10 { atmel,wakeup-counter = <10>; atmel,wakeup-rtt-timer; }; diff --git a/arch/arm/boot/dts/at91-sam9_l9260.dts b/arch/arm/boot/dts/microchip/at91-sam9_l9260.dts similarity index 100% rename from arch/arm/boot/dts/at91-sam9_l9260.dts rename to arch/arm/boot/dts/microchip/at91-sam9_l9260.dts diff --git a/arch/arm/boot/dts/at91-sam9x60_curiosity.dts b/arch/arm/boot/dts/microchip/at91-sam9x60_curiosity.dts similarity index 100% rename from arch/arm/boot/dts/at91-sam9x60_curiosity.dts rename to arch/arm/boot/dts/microchip/at91-sam9x60_curiosity.dts diff --git a/arch/arm/boot/dts/at91-sam9x60ek.dts b/arch/arm/boot/dts/microchip/at91-sam9x60ek.dts similarity index 100% rename from arch/arm/boot/dts/at91-sam9x60ek.dts rename to arch/arm/boot/dts/microchip/at91-sam9x60ek.dts diff --git a/arch/arm/boot/dts/at91-sama5d27_som1.dtsi b/arch/arm/boot/dts/microchip/at91-sama5d27_som1.dtsi similarity index 100% rename from arch/arm/boot/dts/at91-sama5d27_som1.dtsi rename to arch/arm/boot/dts/microchip/at91-sama5d27_som1.dtsi diff --git a/arch/arm/boot/dts/at91-sama5d27_som1_ek.dts b/arch/arm/boot/dts/microchip/at91-sama5d27_som1_ek.dts similarity index 99% rename from arch/arm/boot/dts/at91-sama5d27_som1_ek.dts rename to arch/arm/boot/dts/microchip/at91-sama5d27_som1_ek.dts index 52ddd0571f1c0ac5db75284a6d31cb2b390a1cf6..d0a6dbd377dfa133f330ac5e3f5385f9754bf708 100644 --- a/arch/arm/boot/dts/at91-sama5d27_som1_ek.dts +++ b/arch/arm/boot/dts/microchip/at91-sama5d27_som1_ek.dts @@ -139,7 +139,7 @@ }; }; - shdwc@f8048010 { + poweroff@f8048010 { debounce-delay-us = <976>; atmel,wakeup-rtc-timer; diff --git a/arch/arm/boot/dts/at91-sama5d27_wlsom1.dtsi b/arch/arm/boot/dts/microchip/at91-sama5d27_wlsom1.dtsi similarity index 100% rename from arch/arm/boot/dts/at91-sama5d27_wlsom1.dtsi rename to arch/arm/boot/dts/microchip/at91-sama5d27_wlsom1.dtsi diff --git a/arch/arm/boot/dts/at91-sama5d27_wlsom1_ek.dts b/arch/arm/boot/dts/microchip/at91-sama5d27_wlsom1_ek.dts similarity index 100% rename from arch/arm/boot/dts/at91-sama5d27_wlsom1_ek.dts rename to arch/arm/boot/dts/microchip/at91-sama5d27_wlsom1_ek.dts diff --git a/arch/arm/boot/dts/at91-sama5d2_icp.dts b/arch/arm/boot/dts/microchip/at91-sama5d2_icp.dts similarity index 100% rename from arch/arm/boot/dts/at91-sama5d2_icp.dts rename to arch/arm/boot/dts/microchip/at91-sama5d2_icp.dts diff --git a/arch/arm/boot/dts/at91-sama5d2_ptc_ek.dts b/arch/arm/boot/dts/microchip/at91-sama5d2_ptc_ek.dts similarity index 99% rename from arch/arm/boot/dts/at91-sama5d2_ptc_ek.dts rename to arch/arm/boot/dts/microchip/at91-sama5d2_ptc_ek.dts index bf1c9ca72a9f35a6e313670e6140a9e84dc4f0ae..200b20515ab121beb2988cf3b1e3b0bc06236ec5 100644 --- a/arch/arm/boot/dts/at91-sama5d2_ptc_ek.dts +++ b/arch/arm/boot/dts/microchip/at91-sama5d2_ptc_ek.dts @@ -204,7 +204,7 @@ }; }; - shdwc@f8048010 { + poweroff@f8048010 { debounce-delay-us = <976>; input@0 { diff --git a/arch/arm/boot/dts/at91-sama5d2_xplained.dts b/arch/arm/boot/dts/microchip/at91-sama5d2_xplained.dts similarity index 99% rename from arch/arm/boot/dts/at91-sama5d2_xplained.dts rename to arch/arm/boot/dts/microchip/at91-sama5d2_xplained.dts index 2d53c47d7cc863a87338c22770e5d195465879d3..6680031387e8c33b7f026bcb3550fc7fda07b2c6 100644 --- a/arch/arm/boot/dts/at91-sama5d2_xplained.dts +++ b/arch/arm/boot/dts/microchip/at91-sama5d2_xplained.dts @@ -348,7 +348,7 @@ }; }; - shdwc@f8048010 { + poweroff@f8048010 { debounce-delay-us = <976>; atmel,wakeup-rtc-timer; diff --git a/arch/arm/boot/dts/at91-sama5d3_eds.dts b/arch/arm/boot/dts/microchip/at91-sama5d3_eds.dts similarity index 100% rename from arch/arm/boot/dts/at91-sama5d3_eds.dts rename to arch/arm/boot/dts/microchip/at91-sama5d3_eds.dts diff --git a/arch/arm/boot/dts/at91-sama5d3_ksz9477_evb.dts b/arch/arm/boot/dts/microchip/at91-sama5d3_ksz9477_evb.dts similarity index 100% rename from arch/arm/boot/dts/at91-sama5d3_ksz9477_evb.dts rename to arch/arm/boot/dts/microchip/at91-sama5d3_ksz9477_evb.dts diff --git a/arch/arm/boot/dts/at91-sama5d3_xplained.dts b/arch/arm/boot/dts/microchip/at91-sama5d3_xplained.dts similarity index 100% rename from arch/arm/boot/dts/at91-sama5d3_xplained.dts rename to arch/arm/boot/dts/microchip/at91-sama5d3_xplained.dts diff --git a/arch/arm/boot/dts/at91-sama5d4_ma5d4.dtsi b/arch/arm/boot/dts/microchip/at91-sama5d4_ma5d4.dtsi similarity index 100% rename from arch/arm/boot/dts/at91-sama5d4_ma5d4.dtsi rename to arch/arm/boot/dts/microchip/at91-sama5d4_ma5d4.dtsi diff --git a/arch/arm/boot/dts/at91-sama5d4_ma5d4evk.dts b/arch/arm/boot/dts/microchip/at91-sama5d4_ma5d4evk.dts similarity index 100% rename from arch/arm/boot/dts/at91-sama5d4_ma5d4evk.dts rename to arch/arm/boot/dts/microchip/at91-sama5d4_ma5d4evk.dts diff --git a/arch/arm/boot/dts/at91-sama5d4_xplained.dts b/arch/arm/boot/dts/microchip/at91-sama5d4_xplained.dts similarity index 100% rename from arch/arm/boot/dts/at91-sama5d4_xplained.dts rename to arch/arm/boot/dts/microchip/at91-sama5d4_xplained.dts diff --git a/arch/arm/boot/dts/at91-sama5d4ek.dts b/arch/arm/boot/dts/microchip/at91-sama5d4ek.dts similarity index 100% rename from arch/arm/boot/dts/at91-sama5d4ek.dts rename to arch/arm/boot/dts/microchip/at91-sama5d4ek.dts diff --git a/arch/arm/boot/dts/at91-sama7g5ek.dts b/arch/arm/boot/dts/microchip/at91-sama7g5ek.dts similarity index 100% rename from arch/arm/boot/dts/at91-sama7g5ek.dts rename to arch/arm/boot/dts/microchip/at91-sama7g5ek.dts diff --git a/arch/arm/boot/dts/at91-smartkiz.dts b/arch/arm/boot/dts/microchip/at91-smartkiz.dts similarity index 100% rename from arch/arm/boot/dts/at91-smartkiz.dts rename to arch/arm/boot/dts/microchip/at91-smartkiz.dts diff --git a/arch/arm/boot/dts/at91-som60.dtsi b/arch/arm/boot/dts/microchip/at91-som60.dtsi similarity index 100% rename from arch/arm/boot/dts/at91-som60.dtsi rename to arch/arm/boot/dts/microchip/at91-som60.dtsi diff --git a/arch/arm/boot/dts/at91-tse850-3.dts b/arch/arm/boot/dts/microchip/at91-tse850-3.dts similarity index 78% rename from arch/arm/boot/dts/at91-tse850-3.dts rename to arch/arm/boot/dts/microchip/at91-tse850-3.dts index b99a4fb44a364cd3f691bda2e62d8c026fa4e989..9d58a3931207e7a59fbf38cdde473ac0feffec0a 100644 --- a/arch/arm/boot/dts/at91-tse850-3.dts +++ b/arch/arm/boot/dts/microchip/at91-tse850-3.dts @@ -300,3 +300,63 @@ dmas = <0>, <0>; /* Do not use DMA for dbgu */ }; + +&pioA { + gpio-line-names = + /* 0 */ "SUP-A", "SUP-B", "SUP-C", "SIGLIN", + /* 28 */ "RXD", "TXD", "BRX", "BTX"; +}; + +&pioC { + gpio-line-names = + /* 0 */ "ETX0", "ETX1", "ERX0", "ERX1", + /* 4 */ "ETXEN", "ECRSDV", "ERXER", "EREFCK", + /* 8 */ "EMDC", "EMDIO", "", "", + /* 12 */ "", "", "", "/ILIM", + /* 16 */ "BCK", "LRCK", "DIN", "", + /* 20 */ "", "", "", "", + /* 24 */ "", "", "", "", + /* 28 */ "", "", "", "VBUS"; +}; + +&pioD { + gpio-line-names = + /* 0 */ "I1", "I2", "O1", "EXTVEN", + /* 4 */ "", "456KHZ", "VCTRL", "SYNCSEL", + /* 8 */ "STEREO", "", "", "", + /* 12 */ "", "", "", "", + /* 16 */ "", ">LIN", "LIN>", "", + /* 20 */ "VREFEN", "", "", "", + /* 24 */ "", "", "VINOK", "", + /* 28 */ "POEOK", "USBON", "POELOAD", ""; +}; + +&pioE { + gpio-line-names = + /* 0 */ "", "", "", "", + /* 4 */ "", "", "", "", + /* 8 */ "", "", "", "", + /* 12 */ "", "", "", "", + /* 16 */ "", "", "", "", + /* 20 */ "", "ALE", "CLE", "", + /* 24 */ "", "", "", "", + /* 28 */ "", "", "", "/ETHINT"; +}; diff --git a/arch/arm/boot/dts/at91-vinco.dts b/arch/arm/boot/dts/microchip/at91-vinco.dts similarity index 100% rename from arch/arm/boot/dts/at91-vinco.dts rename to arch/arm/boot/dts/microchip/at91-vinco.dts diff --git a/arch/arm/boot/dts/at91-wb45n.dts b/arch/arm/boot/dts/microchip/at91-wb45n.dts similarity index 100% rename from arch/arm/boot/dts/at91-wb45n.dts rename to arch/arm/boot/dts/microchip/at91-wb45n.dts diff --git a/arch/arm/boot/dts/at91-wb45n.dtsi b/arch/arm/boot/dts/microchip/at91-wb45n.dtsi similarity index 100% rename from arch/arm/boot/dts/at91-wb45n.dtsi rename to arch/arm/boot/dts/microchip/at91-wb45n.dtsi diff --git a/arch/arm/boot/dts/at91-wb50n.dts b/arch/arm/boot/dts/microchip/at91-wb50n.dts similarity index 100% rename from arch/arm/boot/dts/at91-wb50n.dts rename to arch/arm/boot/dts/microchip/at91-wb50n.dts diff --git a/arch/arm/boot/dts/at91-wb50n.dtsi b/arch/arm/boot/dts/microchip/at91-wb50n.dtsi similarity index 100% rename from arch/arm/boot/dts/at91-wb50n.dtsi rename to arch/arm/boot/dts/microchip/at91-wb50n.dtsi diff --git a/arch/arm/boot/dts/at91rm9200.dtsi b/arch/arm/boot/dts/microchip/at91rm9200.dtsi similarity index 99% rename from arch/arm/boot/dts/at91rm9200.dtsi rename to arch/arm/boot/dts/microchip/at91rm9200.dtsi index 6f9004ebf42456f61cd71af5a734e2a8afa54f27..37b500f6f395685fb2d5dc867ef500b410ef3a59 100644 --- a/arch/arm/boot/dts/at91rm9200.dtsi +++ b/arch/arm/boot/dts/microchip/at91rm9200.dtsi @@ -102,7 +102,7 @@ reg = <0xffffff00 0x100>; }; - pmc: pmc@fffffc00 { + pmc: clock-controller@fffffc00 { compatible = "atmel,at91rm9200-pmc", "syscon"; reg = <0xfffffc00 0x100>; interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>; diff --git a/arch/arm/boot/dts/at91rm9200_pqfp.dtsi b/arch/arm/boot/dts/microchip/at91rm9200_pqfp.dtsi similarity index 100% rename from arch/arm/boot/dts/at91rm9200_pqfp.dtsi rename to arch/arm/boot/dts/microchip/at91rm9200_pqfp.dtsi diff --git a/arch/arm/boot/dts/at91rm9200ek.dts b/arch/arm/boot/dts/microchip/at91rm9200ek.dts similarity index 100% rename from arch/arm/boot/dts/at91rm9200ek.dts rename to arch/arm/boot/dts/microchip/at91rm9200ek.dts diff --git a/arch/arm/boot/dts/at91sam9260.dtsi b/arch/arm/boot/dts/microchip/at91sam9260.dtsi similarity index 99% rename from arch/arm/boot/dts/at91sam9260.dtsi rename to arch/arm/boot/dts/microchip/at91sam9260.dtsi index 789fe356dbf60365d427968f9f926bd308ce3170..35a007365b6a5cb1255854278ea1d040dae337ad 100644 --- a/arch/arm/boot/dts/at91sam9260.dtsi +++ b/arch/arm/boot/dts/microchip/at91sam9260.dtsi @@ -115,7 +115,7 @@ reg = <0xffffee00 0x200>; }; - pmc: pmc@fffffc00 { + pmc: clock-controller@fffffc00 { compatible = "atmel,at91sam9260-pmc", "syscon"; reg = <0xfffffc00 0x100>; interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>; @@ -130,7 +130,7 @@ clocks = <&pmc PMC_TYPE_CORE PMC_SLOW>; }; - shdwc@fffffd10 { + shdwc: poweroff@fffffd10 { compatible = "atmel,at91sam9260-shdwc"; reg = <0xfffffd10 0x10>; clocks = <&pmc PMC_TYPE_CORE PMC_SLOW>; diff --git a/arch/arm/boot/dts/at91sam9260ek.dts b/arch/arm/boot/dts/microchip/at91sam9260ek.dts similarity index 99% rename from arch/arm/boot/dts/at91sam9260ek.dts rename to arch/arm/boot/dts/microchip/at91sam9260ek.dts index bb72f050a4fefa04afdbbec20f2e5a798db841f2..720c15472c4a5f1541da1a20e6494316722fb69b 100644 --- a/arch/arm/boot/dts/at91sam9260ek.dts +++ b/arch/arm/boot/dts/microchip/at91sam9260ek.dts @@ -112,7 +112,7 @@ }; }; - shdwc@fffffd10 { + shdwc: poweroff@fffffd10 { atmel,wakeup-counter = <10>; atmel,wakeup-rtt-timer; }; diff --git a/arch/arm/boot/dts/at91sam9261.dtsi b/arch/arm/boot/dts/microchip/at91sam9261.dtsi similarity index 99% rename from arch/arm/boot/dts/at91sam9261.dtsi rename to arch/arm/boot/dts/microchip/at91sam9261.dtsi index ee0bd1aceb3f0cc16d12a926fc3d5a8d7f9b862b..528ffc6f6f962213cdab759a8d3bb1ffad04c9e1 100644 --- a/arch/arm/boot/dts/at91sam9261.dtsi +++ b/arch/arm/boot/dts/microchip/at91sam9261.dtsi @@ -599,7 +599,7 @@ }; }; - pmc: pmc@fffffc00 { + pmc: clock-controller@fffffc00 { compatible = "atmel,at91sam9261-pmc", "syscon"; reg = <0xfffffc00 0x100>; interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>; @@ -614,7 +614,7 @@ clocks = <&slow_xtal>; }; - shdwc@fffffd10 { + poweroff@fffffd10 { compatible = "atmel,at91sam9260-shdwc"; reg = <0xfffffd10 0x10>; clocks = <&slow_xtal>; diff --git a/arch/arm/boot/dts/at91sam9261ek.dts b/arch/arm/boot/dts/microchip/at91sam9261ek.dts similarity index 100% rename from arch/arm/boot/dts/at91sam9261ek.dts rename to arch/arm/boot/dts/microchip/at91sam9261ek.dts diff --git a/arch/arm/boot/dts/at91sam9263.dtsi b/arch/arm/boot/dts/microchip/at91sam9263.dtsi similarity index 99% rename from arch/arm/boot/dts/at91sam9263.dtsi rename to arch/arm/boot/dts/microchip/at91sam9263.dtsi index 3ce9ea9873129a0698811a2ab930c0a34a3ac048..75d8ff2d12c8aa2cdfb5842fdd220a268a4b96be 100644 --- a/arch/arm/boot/dts/at91sam9263.dtsi +++ b/arch/arm/boot/dts/microchip/at91sam9263.dtsi @@ -101,7 +101,7 @@ atmel,external-irqs = <30 31>; }; - pmc: pmc@fffffc00 { + pmc: clock-controller@fffffc00 { compatible = "atmel,at91sam9263-pmc", "syscon"; reg = <0xfffffc00 0x100>; interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>; @@ -158,7 +158,7 @@ clocks = <&slow_xtal>; }; - shdwc@fffffd10 { + poweroff@fffffd10 { compatible = "atmel,at91sam9260-shdwc"; reg = <0xfffffd10 0x10>; clocks = <&slow_xtal>; diff --git a/arch/arm/boot/dts/at91sam9263ek.dts b/arch/arm/boot/dts/microchip/at91sam9263ek.dts similarity index 100% rename from arch/arm/boot/dts/at91sam9263ek.dts rename to arch/arm/boot/dts/microchip/at91sam9263ek.dts diff --git a/arch/arm/boot/dts/at91sam9g15.dtsi b/arch/arm/boot/dts/microchip/at91sam9g15.dtsi similarity index 100% rename from arch/arm/boot/dts/at91sam9g15.dtsi rename to arch/arm/boot/dts/microchip/at91sam9g15.dtsi diff --git a/arch/arm/boot/dts/at91sam9g15ek.dts b/arch/arm/boot/dts/microchip/at91sam9g15ek.dts similarity index 100% rename from arch/arm/boot/dts/at91sam9g15ek.dts rename to arch/arm/boot/dts/microchip/at91sam9g15ek.dts diff --git a/arch/arm/boot/dts/at91sam9g20.dtsi b/arch/arm/boot/dts/microchip/at91sam9g20.dtsi similarity index 96% rename from arch/arm/boot/dts/at91sam9g20.dtsi rename to arch/arm/boot/dts/microchip/at91sam9g20.dtsi index 708e1646b7f46a015944db9b77b780312dda027a..738a43ffd2281dd25e269654c127ed687b4993c1 100644 --- a/arch/arm/boot/dts/at91sam9g20.dtsi +++ b/arch/arm/boot/dts/microchip/at91sam9g20.dtsi @@ -41,7 +41,7 @@ atmel,adc-startup-time = <40>; }; - pmc: pmc@fffffc00 { + pmc: clock-controller@fffffc00 { compatible = "atmel,at91sam9g20-pmc", "atmel,at91sam9260-pmc", "syscon"; }; }; diff --git a/arch/arm/boot/dts/at91sam9g20ek.dts b/arch/arm/boot/dts/microchip/at91sam9g20ek.dts similarity index 100% rename from arch/arm/boot/dts/at91sam9g20ek.dts rename to arch/arm/boot/dts/microchip/at91sam9g20ek.dts diff --git a/arch/arm/boot/dts/at91sam9g20ek_2mmc.dts b/arch/arm/boot/dts/microchip/at91sam9g20ek_2mmc.dts similarity index 100% rename from arch/arm/boot/dts/at91sam9g20ek_2mmc.dts rename to arch/arm/boot/dts/microchip/at91sam9g20ek_2mmc.dts diff --git a/arch/arm/boot/dts/at91sam9g20ek_common.dtsi b/arch/arm/boot/dts/microchip/at91sam9g20ek_common.dtsi similarity index 99% rename from arch/arm/boot/dts/at91sam9g20ek_common.dtsi rename to arch/arm/boot/dts/microchip/at91sam9g20ek_common.dtsi index 024af2db638ebe10537ee358463ae60ed4ae3faf..565b99e79c52097b754a65c70bc8799848c8087e 100644 --- a/arch/arm/boot/dts/at91sam9g20ek_common.dtsi +++ b/arch/arm/boot/dts/microchip/at91sam9g20ek_common.dtsi @@ -126,7 +126,7 @@ }; }; - shdwc@fffffd10 { + shdwc: poweroff@fffffd10 { atmel,wakeup-counter = <10>; atmel,wakeup-rtt-timer; }; diff --git a/arch/arm/boot/dts/at91sam9g25-gardena-smart-gateway.dts b/arch/arm/boot/dts/microchip/at91sam9g25-gardena-smart-gateway.dts similarity index 100% rename from arch/arm/boot/dts/at91sam9g25-gardena-smart-gateway.dts rename to arch/arm/boot/dts/microchip/at91sam9g25-gardena-smart-gateway.dts diff --git a/arch/arm/boot/dts/at91sam9g25.dtsi b/arch/arm/boot/dts/microchip/at91sam9g25.dtsi similarity index 95% rename from arch/arm/boot/dts/at91sam9g25.dtsi rename to arch/arm/boot/dts/microchip/at91sam9g25.dtsi index d2f13afb35eaf8e5a44caef56b8bf498f727deeb..ec3c77221881ca4c50b05816ff70f96de9730b6b 100644 --- a/arch/arm/boot/dts/at91sam9g25.dtsi +++ b/arch/arm/boot/dts/microchip/at91sam9g25.dtsi @@ -26,7 +26,7 @@ >; }; - pmc: pmc@fffffc00 { + pmc: clock-controller@fffffc00 { compatible = "atmel,at91sam9g25-pmc", "atmel,at91sam9x5-pmc", "syscon"; }; }; diff --git a/arch/arm/boot/dts/at91sam9g25ek.dts b/arch/arm/boot/dts/microchip/at91sam9g25ek.dts similarity index 100% rename from arch/arm/boot/dts/at91sam9g25ek.dts rename to arch/arm/boot/dts/microchip/at91sam9g25ek.dts diff --git a/arch/arm/boot/dts/at91sam9g35.dtsi b/arch/arm/boot/dts/microchip/at91sam9g35.dtsi similarity index 95% rename from arch/arm/boot/dts/at91sam9g35.dtsi rename to arch/arm/boot/dts/microchip/at91sam9g35.dtsi index 48c2bc4a7753df4726d5affa318a8a946f08e50b..c9cfb93092ee6d85e0a9d835883f5f4ca4944d6b 100644 --- a/arch/arm/boot/dts/at91sam9g35.dtsi +++ b/arch/arm/boot/dts/microchip/at91sam9g35.dtsi @@ -25,7 +25,7 @@ >; }; - pmc: pmc@fffffc00 { + pmc: clock-controller@fffffc00 { compatible = "atmel,at91sam9g35-pmc", "atmel,at91sam9x5-pmc", "syscon"; }; }; diff --git a/arch/arm/boot/dts/at91sam9g35ek.dts b/arch/arm/boot/dts/microchip/at91sam9g35ek.dts similarity index 100% rename from arch/arm/boot/dts/at91sam9g35ek.dts rename to arch/arm/boot/dts/microchip/at91sam9g35ek.dts diff --git a/arch/arm/boot/dts/at91sam9g45.dtsi b/arch/arm/boot/dts/microchip/at91sam9g45.dtsi similarity index 99% rename from arch/arm/boot/dts/at91sam9g45.dtsi rename to arch/arm/boot/dts/microchip/at91sam9g45.dtsi index 95f5d76234dbbdd6e92a8dae4cd95d1880799683..7cccc606e36cd4970aee05f11297922885bfe88b 100644 --- a/arch/arm/boot/dts/at91sam9g45.dtsi +++ b/arch/arm/boot/dts/microchip/at91sam9g45.dtsi @@ -129,7 +129,7 @@ reg = <0xffffea00 0x200>; }; - pmc: pmc@fffffc00 { + pmc: clock-controller@fffffc00 { compatible = "atmel,at91sam9g45-pmc", "syscon"; reg = <0xfffffc00 0x100>; interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>; @@ -152,7 +152,7 @@ }; - shdwc@fffffd10 { + poweroff@fffffd10 { compatible = "atmel,at91sam9rl-shdwc"; reg = <0xfffffd10 0x10>; clocks = <&clk32k>; @@ -923,7 +923,7 @@ status = "disabled"; }; - clk32k: sckc@fffffd50 { + clk32k: clock-controller@fffffd50 { compatible = "atmel,at91sam9x5-sckc"; reg = <0xfffffd50 0x4>; clocks = <&slow_xtal>; diff --git a/arch/arm/boot/dts/at91sam9m10g45ek.dts b/arch/arm/boot/dts/microchip/at91sam9m10g45ek.dts similarity index 100% rename from arch/arm/boot/dts/at91sam9m10g45ek.dts rename to arch/arm/boot/dts/microchip/at91sam9m10g45ek.dts diff --git a/arch/arm/boot/dts/at91sam9n12.dtsi b/arch/arm/boot/dts/microchip/at91sam9n12.dtsi similarity index 97% rename from arch/arm/boot/dts/at91sam9n12.dtsi rename to arch/arm/boot/dts/microchip/at91sam9n12.dtsi index 83114d26f10d027179ac91d65bbc2290fb1d62fa..8dc04e9031a6c3a59c853e80a580da9c2da64ad6 100644 --- a/arch/arm/boot/dts/at91sam9n12.dtsi +++ b/arch/arm/boot/dts/microchip/at91sam9n12.dtsi @@ -118,7 +118,7 @@ reg = <0xffffea00 0x200>; }; - pmc: pmc@fffffc00 { + pmc: clock-controller@fffffc00 { compatible = "atmel,at91sam9n12-pmc", "syscon"; reg = <0xfffffc00 0x200>; #clock-cells = <2>; @@ -140,34 +140,17 @@ clocks = <&pmc PMC_TYPE_CORE PMC_MCK>; }; - shdwc@fffffe10 { + poweroff@fffffe10 { compatible = "atmel,at91sam9x5-shdwc"; reg = <0xfffffe10 0x10>; clocks = <&clk32k>; }; - sckc@fffffe50 { + clk32k: clock-controller@fffffe50 { compatible = "atmel,at91sam9x5-sckc"; reg = <0xfffffe50 0x4>; - - slow_osc: slow_osc { - compatible = "atmel,at91sam9x5-clk-slow-osc"; - #clock-cells = <0>; - clocks = <&slow_xtal>; - }; - - slow_rc_osc: slow_rc_osc { - compatible = "atmel,at91sam9x5-clk-slow-rc-osc"; - #clock-cells = <0>; - clock-frequency = <32768>; - clock-accuracy = <50000000>; - }; - - clk32k: slck { - compatible = "atmel,at91sam9x5-clk-slow"; - #clock-cells = <0>; - clocks = <&slow_rc_osc>, <&slow_osc>; - }; + clocks = <&slow_xtal>; + #clock-cells = <0>; }; mmc0: mmc@f0008000 { diff --git a/arch/arm/boot/dts/at91sam9n12ek.dts b/arch/arm/boot/dts/microchip/at91sam9n12ek.dts similarity index 100% rename from arch/arm/boot/dts/at91sam9n12ek.dts rename to arch/arm/boot/dts/microchip/at91sam9n12ek.dts diff --git a/arch/arm/boot/dts/at91sam9rl.dtsi b/arch/arm/boot/dts/microchip/at91sam9rl.dtsi similarity index 99% rename from arch/arm/boot/dts/at91sam9rl.dtsi rename to arch/arm/boot/dts/microchip/at91sam9rl.dtsi index 364a2ff0a763d9105da86fabede181ec5078459d..3d089ffbe1626393398f921bd87fd3af01fbfac3 100644 --- a/arch/arm/boot/dts/at91sam9rl.dtsi +++ b/arch/arm/boot/dts/microchip/at91sam9rl.dtsi @@ -763,7 +763,7 @@ }; }; - pmc: pmc@fffffc00 { + pmc: clock-controller@fffffc00 { compatible = "atmel,at91sam9rl-pmc", "syscon"; reg = <0xfffffc00 0x100>; interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>; @@ -778,7 +778,7 @@ clocks = <&clk32k>; }; - shdwc@fffffd10 { + poweroff@fffffd10 { compatible = "atmel,at91sam9260-shdwc"; reg = <0xfffffd10 0x10>; clocks = <&clk32k>; @@ -799,7 +799,7 @@ status = "disabled"; }; - clk32k: sckc@fffffd50 { + clk32k: clock-controller@fffffd50 { compatible = "atmel,at91sam9x5-sckc"; reg = <0xfffffd50 0x4>; clocks = <&slow_xtal>; diff --git a/arch/arm/boot/dts/at91sam9rlek.dts b/arch/arm/boot/dts/microchip/at91sam9rlek.dts similarity index 100% rename from arch/arm/boot/dts/at91sam9rlek.dts rename to arch/arm/boot/dts/microchip/at91sam9rlek.dts diff --git a/arch/arm/boot/dts/at91sam9x25.dtsi b/arch/arm/boot/dts/microchip/at91sam9x25.dtsi similarity index 96% rename from arch/arm/boot/dts/at91sam9x25.dtsi rename to arch/arm/boot/dts/microchip/at91sam9x25.dtsi index 0fe8802e1242bcbf3b534d876056401ba5842f44..7036f5f04571502aa9ab079f1fe3f9f15804d428 100644 --- a/arch/arm/boot/dts/at91sam9x25.dtsi +++ b/arch/arm/boot/dts/microchip/at91sam9x25.dtsi @@ -27,7 +27,7 @@ >; }; - pmc: pmc@fffffc00 { + pmc: clock-controller@fffffc00 { compatible = "atmel,at91sam9x25-pmc", "atmel,at91sam9x5-pmc", "syscon"; }; }; diff --git a/arch/arm/boot/dts/at91sam9x25ek.dts b/arch/arm/boot/dts/microchip/at91sam9x25ek.dts similarity index 100% rename from arch/arm/boot/dts/at91sam9x25ek.dts rename to arch/arm/boot/dts/microchip/at91sam9x25ek.dts diff --git a/arch/arm/boot/dts/at91sam9x35.dtsi b/arch/arm/boot/dts/microchip/at91sam9x35.dtsi similarity index 95% rename from arch/arm/boot/dts/at91sam9x35.dtsi rename to arch/arm/boot/dts/microchip/at91sam9x35.dtsi index 0bfa21f18f870ea62f8832242d6131f0ba663e14..eb03b0497e37197d62e51a406384369dd5705cd1 100644 --- a/arch/arm/boot/dts/at91sam9x35.dtsi +++ b/arch/arm/boot/dts/microchip/at91sam9x35.dtsi @@ -26,7 +26,7 @@ >; }; - pmc: pmc@fffffc00 { + pmc: clock-controller@fffffc00 { compatible = "atmel,at91sam9x35-pmc", "atmel,at91sam9x5-pmc", "syscon"; }; }; diff --git a/arch/arm/boot/dts/at91sam9x35ek.dts b/arch/arm/boot/dts/microchip/at91sam9x35ek.dts similarity index 100% rename from arch/arm/boot/dts/at91sam9x35ek.dts rename to arch/arm/boot/dts/microchip/at91sam9x35ek.dts diff --git a/arch/arm/boot/dts/at91sam9x5.dtsi b/arch/arm/boot/dts/microchip/at91sam9x5.dtsi similarity index 99% rename from arch/arm/boot/dts/at91sam9x5.dtsi rename to arch/arm/boot/dts/microchip/at91sam9x5.dtsi index 0c26c925761b27822142388eb06d979a14ec9da4..a1fed912f2eea2066de0ad556faa2983bfc5fef9 100644 --- a/arch/arm/boot/dts/at91sam9x5.dtsi +++ b/arch/arm/boot/dts/microchip/at91sam9x5.dtsi @@ -126,7 +126,7 @@ reg = <0xffffea00 0x200>; }; - pmc: pmc@fffffc00 { + pmc: clock-controller@fffffc00 { compatible = "atmel,at91sam9x5-pmc", "syscon"; reg = <0xfffffc00 0x200>; interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>; @@ -141,7 +141,7 @@ clocks = <&clk32k>; }; - shutdown_controller: shdwc@fffffe10 { + shutdown_controller: poweroff@fffffe10 { compatible = "atmel,at91sam9x5-shdwc"; reg = <0xfffffe10 0x10>; clocks = <&clk32k>; @@ -154,7 +154,7 @@ clocks = <&pmc PMC_TYPE_CORE PMC_MCK>; }; - clk32k: sckc@fffffe50 { + clk32k: clock-controller@fffffe50 { compatible = "atmel,at91sam9x5-sckc"; reg = <0xfffffe50 0x4>; clocks = <&slow_xtal>; diff --git a/arch/arm/boot/dts/at91sam9x5_can.dtsi b/arch/arm/boot/dts/microchip/at91sam9x5_can.dtsi similarity index 100% rename from arch/arm/boot/dts/at91sam9x5_can.dtsi rename to arch/arm/boot/dts/microchip/at91sam9x5_can.dtsi diff --git a/arch/arm/boot/dts/at91sam9x5_isi.dtsi b/arch/arm/boot/dts/microchip/at91sam9x5_isi.dtsi similarity index 100% rename from arch/arm/boot/dts/at91sam9x5_isi.dtsi rename to arch/arm/boot/dts/microchip/at91sam9x5_isi.dtsi diff --git a/arch/arm/boot/dts/at91sam9x5_lcd.dtsi b/arch/arm/boot/dts/microchip/at91sam9x5_lcd.dtsi similarity index 100% rename from arch/arm/boot/dts/at91sam9x5_lcd.dtsi rename to arch/arm/boot/dts/microchip/at91sam9x5_lcd.dtsi diff --git a/arch/arm/boot/dts/at91sam9x5_macb0.dtsi b/arch/arm/boot/dts/microchip/at91sam9x5_macb0.dtsi similarity index 100% rename from arch/arm/boot/dts/at91sam9x5_macb0.dtsi rename to arch/arm/boot/dts/microchip/at91sam9x5_macb0.dtsi diff --git a/arch/arm/boot/dts/at91sam9x5_macb1.dtsi b/arch/arm/boot/dts/microchip/at91sam9x5_macb1.dtsi similarity index 100% rename from arch/arm/boot/dts/at91sam9x5_macb1.dtsi rename to arch/arm/boot/dts/microchip/at91sam9x5_macb1.dtsi diff --git a/arch/arm/boot/dts/at91sam9x5_usart3.dtsi b/arch/arm/boot/dts/microchip/at91sam9x5_usart3.dtsi similarity index 100% rename from arch/arm/boot/dts/at91sam9x5_usart3.dtsi rename to arch/arm/boot/dts/microchip/at91sam9x5_usart3.dtsi diff --git a/arch/arm/boot/dts/at91sam9x5cm.dtsi b/arch/arm/boot/dts/microchip/at91sam9x5cm.dtsi similarity index 100% rename from arch/arm/boot/dts/at91sam9x5cm.dtsi rename to arch/arm/boot/dts/microchip/at91sam9x5cm.dtsi diff --git a/arch/arm/boot/dts/at91sam9x5dm.dtsi b/arch/arm/boot/dts/microchip/at91sam9x5dm.dtsi similarity index 100% rename from arch/arm/boot/dts/at91sam9x5dm.dtsi rename to arch/arm/boot/dts/microchip/at91sam9x5dm.dtsi diff --git a/arch/arm/boot/dts/at91sam9x5ek.dtsi b/arch/arm/boot/dts/microchip/at91sam9x5ek.dtsi similarity index 100% rename from arch/arm/boot/dts/at91sam9x5ek.dtsi rename to arch/arm/boot/dts/microchip/at91sam9x5ek.dtsi diff --git a/arch/arm/boot/dts/at91sam9xe.dtsi b/arch/arm/boot/dts/microchip/at91sam9xe.dtsi similarity index 100% rename from arch/arm/boot/dts/at91sam9xe.dtsi rename to arch/arm/boot/dts/microchip/at91sam9xe.dtsi diff --git a/arch/arm/boot/dts/ethernut5.dts b/arch/arm/boot/dts/microchip/ethernut5.dts similarity index 100% rename from arch/arm/boot/dts/ethernut5.dts rename to arch/arm/boot/dts/microchip/ethernut5.dts diff --git a/arch/arm/boot/dts/evk-pro3.dts b/arch/arm/boot/dts/microchip/evk-pro3.dts similarity index 100% rename from arch/arm/boot/dts/evk-pro3.dts rename to arch/arm/boot/dts/microchip/evk-pro3.dts diff --git a/arch/arm/boot/dts/ge863-pro3.dtsi b/arch/arm/boot/dts/microchip/ge863-pro3.dtsi similarity index 100% rename from arch/arm/boot/dts/ge863-pro3.dtsi rename to arch/arm/boot/dts/microchip/ge863-pro3.dtsi diff --git a/arch/arm/boot/dts/lan966x-kontron-kswitch-d10-mmt-6g-2gs.dts b/arch/arm/boot/dts/microchip/lan966x-kontron-kswitch-d10-mmt-6g-2gs.dts similarity index 100% rename from arch/arm/boot/dts/lan966x-kontron-kswitch-d10-mmt-6g-2gs.dts rename to arch/arm/boot/dts/microchip/lan966x-kontron-kswitch-d10-mmt-6g-2gs.dts diff --git a/arch/arm/boot/dts/lan966x-kontron-kswitch-d10-mmt-8g.dts b/arch/arm/boot/dts/microchip/lan966x-kontron-kswitch-d10-mmt-8g.dts similarity index 86% rename from arch/arm/boot/dts/lan966x-kontron-kswitch-d10-mmt-8g.dts rename to arch/arm/boot/dts/microchip/lan966x-kontron-kswitch-d10-mmt-8g.dts index 5feef9a59a7905d39429e656b474af869d74ea77..ad5d8b56e6fa96a9f9923dbc6b392dcb02e31dac 100644 --- a/arch/arm/boot/dts/lan966x-kontron-kswitch-d10-mmt-8g.dts +++ b/arch/arm/boot/dts/microchip/lan966x-kontron-kswitch-d10-mmt-8g.dts @@ -15,10 +15,12 @@ &mdio0 { phy2: ethernet-phy@3 { reg = <3>; + interrupts-extended = <&gpio 24 IRQ_TYPE_LEVEL_LOW>; }; phy3: ethernet-phy@4 { reg = <4>; + interrupts-extended = <&gpio 24 IRQ_TYPE_LEVEL_LOW>; }; }; diff --git a/arch/arm/boot/dts/lan966x-kontron-kswitch-d10-mmt.dtsi b/arch/arm/boot/dts/microchip/lan966x-kontron-kswitch-d10-mmt.dtsi similarity index 83% rename from arch/arm/boot/dts/lan966x-kontron-kswitch-d10-mmt.dtsi rename to arch/arm/boot/dts/microchip/lan966x-kontron-kswitch-d10-mmt.dtsi index 0097e72e3fb22ff38e6ae7b8b0c53336650eab18..426893750d51f9f988f9ae7d4cc8c91aaff7a90b 100644 --- a/arch/arm/boot/dts/lan966x-kontron-kswitch-d10-mmt.dtsi +++ b/arch/arm/boot/dts/microchip/lan966x-kontron-kswitch-d10-mmt.dtsi @@ -18,6 +18,8 @@ gpio-restart { compatible = "gpio-restart"; + pinctrl-0 = <&reset_pins>; + pinctrl-names = "default"; gpios = <&gpio 56 GPIO_ACTIVE_LOW>; priority = <200>; }; @@ -39,7 +41,7 @@ status = "okay"; spi3: spi@400 { - pinctrl-0 = <&fc3_b_pins>; + pinctrl-0 = <&fc3_b_pins>, <&spi3_cs_pins>; pinctrl-names = "default"; status = "okay"; cs-gpios = <&gpio 46 GPIO_ACTIVE_LOW>; @@ -47,6 +49,9 @@ }; &gpio { + pinctrl-0 = <&phy_int_pins>; + pinctrl-names = "default"; + fc3_b_pins: fc3-b-pins { /* SCK, MISO, MOSI */ pins = "GPIO_51", "GPIO_52", "GPIO_53"; @@ -59,6 +64,18 @@ function = "miim_c"; }; + phy_int_pins: phy-int-pins { + /* PHY_INT# */ + pins = "GPIO_24"; + function = "gpio"; + }; + + reset_pins: reset-pins { + /* SYS_RST# */ + pins = "GPIO_56"; + function = "gpio"; + }; + sgpio_a_pins: sgpio-a-pins { /* SCK, D0, D1 */ pins = "GPIO_32", "GPIO_33", "GPIO_34"; @@ -71,6 +88,12 @@ function = "sgpio_b"; }; + spi3_cs_pins: spi3-cs-pins { + /* CS# */ + pins = "GPIO_46"; + function = "gpio"; + }; + usart0_pins: usart0-pins { /* RXD, TXD */ pins = "GPIO_25", "GPIO_26"; @@ -93,21 +116,25 @@ phy4: ethernet-phy@5 { reg = <5>; + interrupts-extended = <&gpio 24 IRQ_TYPE_LEVEL_LOW>; coma-mode-gpios = <&gpio 37 GPIO_OPEN_DRAIN>; }; phy5: ethernet-phy@6 { reg = <6>; + interrupts-extended = <&gpio 24 IRQ_TYPE_LEVEL_LOW>; coma-mode-gpios = <&gpio 37 GPIO_OPEN_DRAIN>; }; phy6: ethernet-phy@7 { reg = <7>; + interrupts-extended = <&gpio 24 IRQ_TYPE_LEVEL_LOW>; coma-mode-gpios = <&gpio 37 GPIO_OPEN_DRAIN>; }; phy7: ethernet-phy@8 { reg = <8>; + interrupts-extended = <&gpio 24 IRQ_TYPE_LEVEL_LOW>; coma-mode-gpios = <&gpio 37 GPIO_OPEN_DRAIN>; }; }; diff --git a/arch/arm/boot/dts/lan966x-pcb8290.dts b/arch/arm/boot/dts/microchip/lan966x-pcb8290.dts similarity index 100% rename from arch/arm/boot/dts/lan966x-pcb8290.dts rename to arch/arm/boot/dts/microchip/lan966x-pcb8290.dts diff --git a/arch/arm/boot/dts/lan966x-pcb8291.dts b/arch/arm/boot/dts/microchip/lan966x-pcb8291.dts similarity index 100% rename from arch/arm/boot/dts/lan966x-pcb8291.dts rename to arch/arm/boot/dts/microchip/lan966x-pcb8291.dts diff --git a/arch/arm/boot/dts/lan966x-pcb8309.dts b/arch/arm/boot/dts/microchip/lan966x-pcb8309.dts similarity index 93% rename from arch/arm/boot/dts/lan966x-pcb8309.dts rename to arch/arm/boot/dts/microchip/lan966x-pcb8309.dts index c436cd20d4b4cf86f877d79ca28e39a16987b426..0cb505f79ba1a51254e3076e14888470e2fd3f01 100644 --- a/arch/arm/boot/dts/lan966x-pcb8309.dts +++ b/arch/arm/boot/dts/microchip/lan966x-pcb8309.dts @@ -144,6 +144,18 @@ function = "fc4_b"; }; + pps_out_pins: pps-out-pins { + /* 1pps output */ + pins = "GPIO_38"; + function = "ptpsync_3"; + }; + + ptp_ext_pins: ptp-ext-pins { + /* 1pps input */ + pins = "GPIO_39"; + function = "ptpsync_4"; + }; + sgpio_a_pins: sgpio-a-pins { /* SCK, D0, D1, LD */ pins = "GPIO_32", "GPIO_33", "GPIO_34", "GPIO_35"; @@ -212,5 +224,7 @@ }; &switch { + pinctrl-0 = <&pps_out_pins>, <&ptp_ext_pins>; + pinctrl-names = "default"; status = "okay"; }; diff --git a/arch/arm/boot/dts/lan966x.dtsi b/arch/arm/boot/dts/microchip/lan966x.dtsi similarity index 100% rename from arch/arm/boot/dts/lan966x.dtsi rename to arch/arm/boot/dts/microchip/lan966x.dtsi diff --git a/arch/arm/boot/dts/mpa1600.dts b/arch/arm/boot/dts/microchip/mpa1600.dts similarity index 100% rename from arch/arm/boot/dts/mpa1600.dts rename to arch/arm/boot/dts/microchip/mpa1600.dts diff --git a/arch/arm/boot/dts/pm9g45.dts b/arch/arm/boot/dts/microchip/pm9g45.dts similarity index 100% rename from arch/arm/boot/dts/pm9g45.dts rename to arch/arm/boot/dts/microchip/pm9g45.dts diff --git a/arch/arm/boot/dts/sam9x60.dtsi b/arch/arm/boot/dts/microchip/sam9x60.dtsi similarity index 99% rename from arch/arm/boot/dts/sam9x60.dtsi rename to arch/arm/boot/dts/microchip/sam9x60.dtsi index e67ede940071f227170dba1bc1c35864915ec061..8b53997675e75032fd37583508a984cc060f4098 100644 --- a/arch/arm/boot/dts/sam9x60.dtsi +++ b/arch/arm/boot/dts/microchip/sam9x60.dtsi @@ -1282,7 +1282,7 @@ }; }; - pmc: pmc@fffffc00 { + pmc: clock-controller@fffffc00 { compatible = "microchip,sam9x60-pmc", "syscon"; reg = <0xfffffc00 0x200>; interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>; @@ -1297,7 +1297,7 @@ clocks = <&clk32k 0>; }; - shutdown_controller: shdwc@fffffe10 { + shutdown_controller: poweroff@fffffe10 { compatible = "microchip,sam9x60-shdwc"; reg = <0xfffffe10 0x10>; clocks = <&clk32k 0>; @@ -1322,7 +1322,7 @@ clocks = <&pmc PMC_TYPE_CORE PMC_MCK>; }; - clk32k: sckc@fffffe50 { + clk32k: clock-controller@fffffe50 { compatible = "microchip,sam9x60-sckc"; reg = <0xfffffe50 0x4>; clocks = <&slow_xtal>; diff --git a/arch/arm/boot/dts/sama5d2-pinfunc.h b/arch/arm/boot/dts/microchip/sama5d2-pinfunc.h similarity index 100% rename from arch/arm/boot/dts/sama5d2-pinfunc.h rename to arch/arm/boot/dts/microchip/sama5d2-pinfunc.h diff --git a/arch/arm/boot/dts/sama5d2.dtsi b/arch/arm/boot/dts/microchip/sama5d2.dtsi similarity index 99% rename from arch/arm/boot/dts/sama5d2.dtsi rename to arch/arm/boot/dts/microchip/sama5d2.dtsi index 14c35c12a115fe8900d0b6248b0053ef11ffa219..daeeb24e5f4dba6ec448b9dc63c86055f2ec306c 100644 --- a/arch/arm/boot/dts/sama5d2.dtsi +++ b/arch/arm/boot/dts/microchip/sama5d2.dtsi @@ -284,7 +284,7 @@ clock-names = "dma_clk"; }; - pmc: pmc@f0014000 { + pmc: clock-controller@f0014000 { compatible = "atmel,sama5d2-pmc", "syscon"; reg = <0xf0014000 0x160>; interrupts = <74 IRQ_TYPE_LEVEL_HIGH 7>; @@ -680,7 +680,7 @@ clocks = <&clk32k>; }; - shutdown_controller: shdwc@f8048010 { + shutdown_controller: poweroff@f8048010 { compatible = "atmel,sama5d2-shdwc"; reg = <0xf8048010 0x10>; clocks = <&clk32k>; @@ -704,10 +704,9 @@ status = "disabled"; }; - clk32k: sckc@f8048050 { + clk32k: clock-controller@f8048050 { compatible = "atmel,sama5d4-sckc"; reg = <0xf8048050 0x4>; - clocks = <&slow_xtal>; #clock-cells = <0>; }; diff --git a/arch/arm/boot/dts/sama5d29.dtsi b/arch/arm/boot/dts/microchip/sama5d29.dtsi similarity index 100% rename from arch/arm/boot/dts/sama5d29.dtsi rename to arch/arm/boot/dts/microchip/sama5d29.dtsi diff --git a/arch/arm/boot/dts/sama5d3.dtsi b/arch/arm/boot/dts/microchip/sama5d3.dtsi similarity index 99% rename from arch/arm/boot/dts/sama5d3.dtsi rename to arch/arm/boot/dts/microchip/sama5d3.dtsi index bde8e92d60bb10973b8c53e689e9e9bcea8975cc..d9e66700d1c2033ce84a058f5cd1b3f73e5c7f66 100644 --- a/arch/arm/boot/dts/sama5d3.dtsi +++ b/arch/arm/boot/dts/microchip/sama5d3.dtsi @@ -1001,7 +1001,7 @@ }; }; - pmc: pmc@fffffc00 { + pmc: clock-controller@fffffc00 { compatible = "atmel,sama5d3-pmc", "syscon"; reg = <0xfffffc00 0x120>; interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>; @@ -1016,7 +1016,7 @@ clocks = <&clk32k>; }; - shutdown_controller: shutdown-controller@fffffe10 { + shutdown_controller: poweroff@fffffe10 { compatible = "atmel,at91sam9x5-shdwc"; reg = <0xfffffe10 0x10>; clocks = <&clk32k>; @@ -1040,7 +1040,7 @@ status = "disabled"; }; - clk32k: sckc@fffffe50 { + clk32k: clock-controller@fffffe50 { compatible = "atmel,sama5d3-sckc"; reg = <0xfffffe50 0x4>; clocks = <&slow_xtal>; diff --git a/arch/arm/boot/dts/sama5d31.dtsi b/arch/arm/boot/dts/microchip/sama5d31.dtsi similarity index 100% rename from arch/arm/boot/dts/sama5d31.dtsi rename to arch/arm/boot/dts/microchip/sama5d31.dtsi diff --git a/arch/arm/boot/dts/sama5d31ek.dts b/arch/arm/boot/dts/microchip/sama5d31ek.dts similarity index 100% rename from arch/arm/boot/dts/sama5d31ek.dts rename to arch/arm/boot/dts/microchip/sama5d31ek.dts diff --git a/arch/arm/boot/dts/sama5d33.dtsi b/arch/arm/boot/dts/microchip/sama5d33.dtsi similarity index 100% rename from arch/arm/boot/dts/sama5d33.dtsi rename to arch/arm/boot/dts/microchip/sama5d33.dtsi diff --git a/arch/arm/boot/dts/sama5d33ek.dts b/arch/arm/boot/dts/microchip/sama5d33ek.dts similarity index 100% rename from arch/arm/boot/dts/sama5d33ek.dts rename to arch/arm/boot/dts/microchip/sama5d33ek.dts diff --git a/arch/arm/boot/dts/sama5d34.dtsi b/arch/arm/boot/dts/microchip/sama5d34.dtsi similarity index 100% rename from arch/arm/boot/dts/sama5d34.dtsi rename to arch/arm/boot/dts/microchip/sama5d34.dtsi diff --git a/arch/arm/boot/dts/sama5d34ek.dts b/arch/arm/boot/dts/microchip/sama5d34ek.dts similarity index 100% rename from arch/arm/boot/dts/sama5d34ek.dts rename to arch/arm/boot/dts/microchip/sama5d34ek.dts diff --git a/arch/arm/boot/dts/sama5d35.dtsi b/arch/arm/boot/dts/microchip/sama5d35.dtsi similarity index 100% rename from arch/arm/boot/dts/sama5d35.dtsi rename to arch/arm/boot/dts/microchip/sama5d35.dtsi diff --git a/arch/arm/boot/dts/sama5d35ek.dts b/arch/arm/boot/dts/microchip/sama5d35ek.dts similarity index 100% rename from arch/arm/boot/dts/sama5d35ek.dts rename to arch/arm/boot/dts/microchip/sama5d35ek.dts diff --git a/arch/arm/boot/dts/sama5d36.dtsi b/arch/arm/boot/dts/microchip/sama5d36.dtsi similarity index 100% rename from arch/arm/boot/dts/sama5d36.dtsi rename to arch/arm/boot/dts/microchip/sama5d36.dtsi diff --git a/arch/arm/boot/dts/sama5d36ek.dts b/arch/arm/boot/dts/microchip/sama5d36ek.dts similarity index 100% rename from arch/arm/boot/dts/sama5d36ek.dts rename to arch/arm/boot/dts/microchip/sama5d36ek.dts diff --git a/arch/arm/boot/dts/sama5d36ek_cmp.dts b/arch/arm/boot/dts/microchip/sama5d36ek_cmp.dts similarity index 100% rename from arch/arm/boot/dts/sama5d36ek_cmp.dts rename to arch/arm/boot/dts/microchip/sama5d36ek_cmp.dts diff --git a/arch/arm/boot/dts/sama5d3_can.dtsi b/arch/arm/boot/dts/microchip/sama5d3_can.dtsi similarity index 100% rename from arch/arm/boot/dts/sama5d3_can.dtsi rename to arch/arm/boot/dts/microchip/sama5d3_can.dtsi diff --git a/arch/arm/boot/dts/sama5d3_emac.dtsi b/arch/arm/boot/dts/microchip/sama5d3_emac.dtsi similarity index 98% rename from arch/arm/boot/dts/sama5d3_emac.dtsi rename to arch/arm/boot/dts/microchip/sama5d3_emac.dtsi index 45226108850d281b4106460d781425324b92070c..5d7ce13de8ccfd5a41f161f7ab1e9958490acec0 100644 --- a/arch/arm/boot/dts/sama5d3_emac.dtsi +++ b/arch/arm/boot/dts/microchip/sama5d3_emac.dtsi @@ -30,7 +30,7 @@ }; }; - pmc: pmc@fffffc00 { + pmc: clock-controller@fffffc00 { }; macb1: ethernet@f802c000 { diff --git a/arch/arm/boot/dts/sama5d3_gmac.dtsi b/arch/arm/boot/dts/microchip/sama5d3_gmac.dtsi similarity index 100% rename from arch/arm/boot/dts/sama5d3_gmac.dtsi rename to arch/arm/boot/dts/microchip/sama5d3_gmac.dtsi diff --git a/arch/arm/boot/dts/sama5d3_lcd.dtsi b/arch/arm/boot/dts/microchip/sama5d3_lcd.dtsi similarity index 100% rename from arch/arm/boot/dts/sama5d3_lcd.dtsi rename to arch/arm/boot/dts/microchip/sama5d3_lcd.dtsi diff --git a/arch/arm/boot/dts/sama5d3_mci2.dtsi b/arch/arm/boot/dts/microchip/sama5d3_mci2.dtsi similarity index 100% rename from arch/arm/boot/dts/sama5d3_mci2.dtsi rename to arch/arm/boot/dts/microchip/sama5d3_mci2.dtsi diff --git a/arch/arm/boot/dts/sama5d3_tcb1.dtsi b/arch/arm/boot/dts/microchip/sama5d3_tcb1.dtsi similarity index 100% rename from arch/arm/boot/dts/sama5d3_tcb1.dtsi rename to arch/arm/boot/dts/microchip/sama5d3_tcb1.dtsi diff --git a/arch/arm/boot/dts/sama5d3_uart.dtsi b/arch/arm/boot/dts/microchip/sama5d3_uart.dtsi similarity index 100% rename from arch/arm/boot/dts/sama5d3_uart.dtsi rename to arch/arm/boot/dts/microchip/sama5d3_uart.dtsi diff --git a/arch/arm/boot/dts/sama5d3xcm.dtsi b/arch/arm/boot/dts/microchip/sama5d3xcm.dtsi similarity index 100% rename from arch/arm/boot/dts/sama5d3xcm.dtsi rename to arch/arm/boot/dts/microchip/sama5d3xcm.dtsi diff --git a/arch/arm/boot/dts/sama5d3xcm_cmp.dtsi b/arch/arm/boot/dts/microchip/sama5d3xcm_cmp.dtsi similarity index 100% rename from arch/arm/boot/dts/sama5d3xcm_cmp.dtsi rename to arch/arm/boot/dts/microchip/sama5d3xcm_cmp.dtsi diff --git a/arch/arm/boot/dts/sama5d3xdm.dtsi b/arch/arm/boot/dts/microchip/sama5d3xdm.dtsi similarity index 100% rename from arch/arm/boot/dts/sama5d3xdm.dtsi rename to arch/arm/boot/dts/microchip/sama5d3xdm.dtsi diff --git a/arch/arm/boot/dts/sama5d3xmb.dtsi b/arch/arm/boot/dts/microchip/sama5d3xmb.dtsi similarity index 100% rename from arch/arm/boot/dts/sama5d3xmb.dtsi rename to arch/arm/boot/dts/microchip/sama5d3xmb.dtsi diff --git a/arch/arm/boot/dts/sama5d3xmb_cmp.dtsi b/arch/arm/boot/dts/microchip/sama5d3xmb_cmp.dtsi similarity index 100% rename from arch/arm/boot/dts/sama5d3xmb_cmp.dtsi rename to arch/arm/boot/dts/microchip/sama5d3xmb_cmp.dtsi diff --git a/arch/arm/boot/dts/sama5d3xmb_emac.dtsi b/arch/arm/boot/dts/microchip/sama5d3xmb_emac.dtsi similarity index 100% rename from arch/arm/boot/dts/sama5d3xmb_emac.dtsi rename to arch/arm/boot/dts/microchip/sama5d3xmb_emac.dtsi diff --git a/arch/arm/boot/dts/sama5d3xmb_gmac.dtsi b/arch/arm/boot/dts/microchip/sama5d3xmb_gmac.dtsi similarity index 100% rename from arch/arm/boot/dts/sama5d3xmb_gmac.dtsi rename to arch/arm/boot/dts/microchip/sama5d3xmb_gmac.dtsi diff --git a/arch/arm/boot/dts/sama5d4.dtsi b/arch/arm/boot/dts/microchip/sama5d4.dtsi similarity index 99% rename from arch/arm/boot/dts/sama5d4.dtsi rename to arch/arm/boot/dts/microchip/sama5d4.dtsi index af62157ae214f30b2bde3d88280109926e9c813f..41284e013f531ad5bd0bc1756973141d8b8600d5 100644 --- a/arch/arm/boot/dts/sama5d4.dtsi +++ b/arch/arm/boot/dts/microchip/sama5d4.dtsi @@ -250,7 +250,7 @@ clock-names = "dma_clk"; }; - pmc: pmc@f0018000 { + pmc: clock-controller@f0018000 { compatible = "atmel,sama5d4-pmc", "syscon"; reg = <0xf0018000 0x120>; interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>; @@ -740,7 +740,7 @@ clocks = <&clk32k>; }; - shutdown_controller: shdwc@fc068610 { + shutdown_controller: poweroff@fc068610 { compatible = "atmel,at91sam9x5-shdwc"; reg = <0xfc068610 0x10>; clocks = <&clk32k>; @@ -761,7 +761,7 @@ status = "disabled"; }; - clk32k: sckc@fc068650 { + clk32k: clock-controller@fc068650 { compatible = "atmel,sama5d4-sckc"; reg = <0xfc068650 0x4>; #clock-cells = <0>; diff --git a/arch/arm/boot/dts/sama7g5-pinfunc.h b/arch/arm/boot/dts/microchip/sama7g5-pinfunc.h similarity index 100% rename from arch/arm/boot/dts/sama7g5-pinfunc.h rename to arch/arm/boot/dts/microchip/sama7g5-pinfunc.h diff --git a/arch/arm/boot/dts/sama7g5.dtsi b/arch/arm/boot/dts/microchip/sama7g5.dtsi similarity index 99% rename from arch/arm/boot/dts/sama7g5.dtsi rename to arch/arm/boot/dts/microchip/sama7g5.dtsi index 929ba73702e935acd74a859b745f3afbde5ad7e7..9642a42d84e6026ca936e8c1bb6196b30ab5f295 100644 --- a/arch/arm/boot/dts/sama7g5.dtsi +++ b/arch/arm/boot/dts/microchip/sama7g5.dtsi @@ -241,7 +241,7 @@ clocks = <&pmc PMC_TYPE_PERIPHERAL 11>; }; - pmc: pmc@e0018000 { + pmc: clock-controller@e0018000 { compatible = "microchip,sama7g5-pmc", "syscon"; reg = <0xe0018000 0x200>; interrupts = ; @@ -257,7 +257,7 @@ clocks = <&clk32k 0>; }; - shdwc: shdwc@e001d010 { + shdwc: poweroff@e001d010 { compatible = "microchip,sama7g5-shdwc", "syscon"; reg = <0xe001d010 0x10>; clocks = <&clk32k 0>; diff --git a/arch/arm/boot/dts/tny_a9260.dts b/arch/arm/boot/dts/microchip/tny_a9260.dts similarity index 100% rename from arch/arm/boot/dts/tny_a9260.dts rename to arch/arm/boot/dts/microchip/tny_a9260.dts diff --git a/arch/arm/boot/dts/tny_a9260_common.dtsi b/arch/arm/boot/dts/microchip/tny_a9260_common.dtsi similarity index 100% rename from arch/arm/boot/dts/tny_a9260_common.dtsi rename to arch/arm/boot/dts/microchip/tny_a9260_common.dtsi diff --git a/arch/arm/boot/dts/tny_a9263.dts b/arch/arm/boot/dts/microchip/tny_a9263.dts similarity index 100% rename from arch/arm/boot/dts/tny_a9263.dts rename to arch/arm/boot/dts/microchip/tny_a9263.dts diff --git a/arch/arm/boot/dts/tny_a9g20.dts b/arch/arm/boot/dts/microchip/tny_a9g20.dts similarity index 100% rename from arch/arm/boot/dts/tny_a9g20.dts rename to arch/arm/boot/dts/microchip/tny_a9g20.dts diff --git a/arch/arm/boot/dts/usb_a9260.dts b/arch/arm/boot/dts/microchip/usb_a9260.dts similarity index 95% rename from arch/arm/boot/dts/usb_a9260.dts rename to arch/arm/boot/dts/microchip/usb_a9260.dts index 6cfa83921ac26463d10246833b7eab251edb676f..66f8da89007db4721ba08a618037d0868081a568 100644 --- a/arch/arm/boot/dts/usb_a9260.dts +++ b/arch/arm/boot/dts/microchip/usb_a9260.dts @@ -22,7 +22,7 @@ ahb { apb { - shdwc@fffffd10 { + shdwc: poweroff@fffffd10 { atmel,wakeup-counter = <10>; atmel,wakeup-rtt-timer; }; diff --git a/arch/arm/boot/dts/usb_a9260_common.dtsi b/arch/arm/boot/dts/microchip/usb_a9260_common.dtsi similarity index 100% rename from arch/arm/boot/dts/usb_a9260_common.dtsi rename to arch/arm/boot/dts/microchip/usb_a9260_common.dtsi diff --git a/arch/arm/boot/dts/usb_a9263.dts b/arch/arm/boot/dts/microchip/usb_a9263.dts similarity index 99% rename from arch/arm/boot/dts/usb_a9263.dts rename to arch/arm/boot/dts/microchip/usb_a9263.dts index b6cb9cdf8197336112c8b160d22d97c6fde8b30b..45745915b2e160e8710003411caa2d8fc344157e 100644 --- a/arch/arm/boot/dts/usb_a9263.dts +++ b/arch/arm/boot/dts/microchip/usb_a9263.dts @@ -67,7 +67,7 @@ }; }; - shdwc@fffffd10 { + poweroff@fffffd10 { atmel,wakeup-counter = <10>; atmel,wakeup-rtt-timer; }; diff --git a/arch/arm/boot/dts/usb_a9g20-dab-mmx.dtsi b/arch/arm/boot/dts/microchip/usb_a9g20-dab-mmx.dtsi similarity index 100% rename from arch/arm/boot/dts/usb_a9g20-dab-mmx.dtsi rename to arch/arm/boot/dts/microchip/usb_a9g20-dab-mmx.dtsi diff --git a/arch/arm/boot/dts/usb_a9g20.dts b/arch/arm/boot/dts/microchip/usb_a9g20.dts similarity index 100% rename from arch/arm/boot/dts/usb_a9g20.dts rename to arch/arm/boot/dts/microchip/usb_a9g20.dts diff --git a/arch/arm/boot/dts/usb_a9g20_common.dtsi b/arch/arm/boot/dts/microchip/usb_a9g20_common.dtsi similarity index 100% rename from arch/arm/boot/dts/usb_a9g20_common.dtsi rename to arch/arm/boot/dts/microchip/usb_a9g20_common.dtsi diff --git a/arch/arm/boot/dts/usb_a9g20_lpw.dts b/arch/arm/boot/dts/microchip/usb_a9g20_lpw.dts similarity index 100% rename from arch/arm/boot/dts/usb_a9g20_lpw.dts rename to arch/arm/boot/dts/microchip/usb_a9g20_lpw.dts diff --git a/arch/arm/boot/dts/moxa/Makefile b/arch/arm/boot/dts/moxa/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..d61ce8d4e732ea9043366066df4801031827cb08 --- /dev/null +++ b/arch/arm/boot/dts/moxa/Makefile @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0 +dtb-$(CONFIG_ARCH_MOXART) += \ + moxart-uc7112lx.dtb diff --git a/arch/arm/boot/dts/moxart-uc7112lx.dts b/arch/arm/boot/dts/moxa/moxart-uc7112lx.dts similarity index 100% rename from arch/arm/boot/dts/moxart-uc7112lx.dts rename to arch/arm/boot/dts/moxa/moxart-uc7112lx.dts diff --git a/arch/arm/boot/dts/moxart.dtsi b/arch/arm/boot/dts/moxa/moxart.dtsi similarity index 100% rename from arch/arm/boot/dts/moxart.dtsi rename to arch/arm/boot/dts/moxa/moxart.dtsi diff --git a/arch/arm/boot/dts/mt7623a.dtsi b/arch/arm/boot/dts/mt7623a.dtsi deleted file mode 100644 index d304b62d24b58df37e5bc656d64a0deb3aea35de..0000000000000000000000000000000000000000 --- a/arch/arm/boot/dts/mt7623a.dtsi +++ /dev/null @@ -1,48 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright (c) 2017-2018 MediaTek Inc. - * Author: Sean Wang - * - */ - -/dts-v1/; -#include -#include "mt7623.dtsi" - -&afe { - power-domains = <&scpsys MT7623A_POWER_DOMAIN_IFR_MSC>; -}; - -&crypto { - power-domains = <&scpsys MT7623A_POWER_DOMAIN_ETH>; -}; - -ð { - power-domains = <&scpsys MT7623A_POWER_DOMAIN_ETH>; -}; - -&nandc { - power-domains = <&scpsys MT7623A_POWER_DOMAIN_IFR_MSC>; -}; - -&pcie { - power-domains = <&scpsys MT7623A_POWER_DOMAIN_HIF>; -}; - -&scpsys { - compatible = "mediatek,mt7623a-scpsys"; - clocks = <&topckgen CLK_TOP_ETHIF_SEL>; - clock-names = "ethif"; -}; - -&usb0 { - power-domains = <&scpsys MT7623A_POWER_DOMAIN_IFR_MSC>; -}; - -&usb1 { - power-domains = <&scpsys MT7623A_POWER_DOMAIN_HIF>; -}; - -&usb2 { - power-domains = <&scpsys MT7623A_POWER_DOMAIN_HIF>; -}; diff --git a/arch/arm/boot/dts/nspire/Makefile b/arch/arm/boot/dts/nspire/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..82a2515bdd46086f626a17f137d4ff3de7b43334 --- /dev/null +++ b/arch/arm/boot/dts/nspire/Makefile @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0 +dtb-$(CONFIG_ARCH_NSPIRE) += \ + nspire-cx.dtb \ + nspire-tp.dtb \ + nspire-clp.dtb diff --git a/arch/arm/boot/dts/nspire-classic.dtsi b/arch/arm/boot/dts/nspire/nspire-classic.dtsi similarity index 100% rename from arch/arm/boot/dts/nspire-classic.dtsi rename to arch/arm/boot/dts/nspire/nspire-classic.dtsi diff --git a/arch/arm/boot/dts/nspire-clp.dts b/arch/arm/boot/dts/nspire/nspire-clp.dts similarity index 100% rename from arch/arm/boot/dts/nspire-clp.dts rename to arch/arm/boot/dts/nspire/nspire-clp.dts diff --git a/arch/arm/boot/dts/nspire-cx.dts b/arch/arm/boot/dts/nspire/nspire-cx.dts similarity index 100% rename from arch/arm/boot/dts/nspire-cx.dts rename to arch/arm/boot/dts/nspire/nspire-cx.dts diff --git a/arch/arm/boot/dts/nspire-tp.dts b/arch/arm/boot/dts/nspire/nspire-tp.dts similarity index 100% rename from arch/arm/boot/dts/nspire-tp.dts rename to arch/arm/boot/dts/nspire/nspire-tp.dts diff --git a/arch/arm/boot/dts/nspire.dtsi b/arch/arm/boot/dts/nspire/nspire.dtsi similarity index 100% rename from arch/arm/boot/dts/nspire.dtsi rename to arch/arm/boot/dts/nspire/nspire.dtsi diff --git a/arch/arm/boot/dts/nuvoton/Makefile b/arch/arm/boot/dts/nuvoton/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..89c157dad31232131611ff1bafa082a8e1b5a5fd --- /dev/null +++ b/arch/arm/boot/dts/nuvoton/Makefile @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: GPL-2.0 +dtb-$(CONFIG_ARCH_NPCM7XX) += \ + nuvoton-npcm730-gsj.dtb \ + nuvoton-npcm730-gbs.dtb \ + nuvoton-npcm730-kudo.dtb \ + nuvoton-npcm750-evb.dtb \ + nuvoton-npcm750-runbmc-olympus.dtb +dtb-$(CONFIG_ARCH_WPCM450) += \ + nuvoton-wpcm450-supermicro-x9sci-ln4f.dtb diff --git a/arch/arm/boot/dts/nuvoton-common-npcm7xx.dtsi b/arch/arm/boot/dts/nuvoton/nuvoton-common-npcm7xx.dtsi similarity index 100% rename from arch/arm/boot/dts/nuvoton-common-npcm7xx.dtsi rename to arch/arm/boot/dts/nuvoton/nuvoton-common-npcm7xx.dtsi diff --git a/arch/arm/boot/dts/nuvoton-npcm730-gbs.dts b/arch/arm/boot/dts/nuvoton/nuvoton-npcm730-gbs.dts similarity index 100% rename from arch/arm/boot/dts/nuvoton-npcm730-gbs.dts rename to arch/arm/boot/dts/nuvoton/nuvoton-npcm730-gbs.dts diff --git a/arch/arm/boot/dts/nuvoton-npcm730-gsj-gpio.dtsi b/arch/arm/boot/dts/nuvoton/nuvoton-npcm730-gsj-gpio.dtsi similarity index 100% rename from arch/arm/boot/dts/nuvoton-npcm730-gsj-gpio.dtsi rename to arch/arm/boot/dts/nuvoton/nuvoton-npcm730-gsj-gpio.dtsi diff --git a/arch/arm/boot/dts/nuvoton-npcm730-gsj.dts b/arch/arm/boot/dts/nuvoton/nuvoton-npcm730-gsj.dts similarity index 100% rename from arch/arm/boot/dts/nuvoton-npcm730-gsj.dts rename to arch/arm/boot/dts/nuvoton/nuvoton-npcm730-gsj.dts diff --git a/arch/arm/boot/dts/nuvoton-npcm730-kudo.dts b/arch/arm/boot/dts/nuvoton/nuvoton-npcm730-kudo.dts similarity index 100% rename from arch/arm/boot/dts/nuvoton-npcm730-kudo.dts rename to arch/arm/boot/dts/nuvoton/nuvoton-npcm730-kudo.dts diff --git a/arch/arm/boot/dts/nuvoton-npcm730.dtsi b/arch/arm/boot/dts/nuvoton/nuvoton-npcm730.dtsi similarity index 100% rename from arch/arm/boot/dts/nuvoton-npcm730.dtsi rename to arch/arm/boot/dts/nuvoton/nuvoton-npcm730.dtsi diff --git a/arch/arm/boot/dts/nuvoton-npcm750-evb.dts b/arch/arm/boot/dts/nuvoton/nuvoton-npcm750-evb.dts similarity index 100% rename from arch/arm/boot/dts/nuvoton-npcm750-evb.dts rename to arch/arm/boot/dts/nuvoton/nuvoton-npcm750-evb.dts diff --git a/arch/arm/boot/dts/nuvoton-npcm750-pincfg-evb.dtsi b/arch/arm/boot/dts/nuvoton/nuvoton-npcm750-pincfg-evb.dtsi similarity index 100% rename from arch/arm/boot/dts/nuvoton-npcm750-pincfg-evb.dtsi rename to arch/arm/boot/dts/nuvoton/nuvoton-npcm750-pincfg-evb.dtsi diff --git a/arch/arm/boot/dts/nuvoton-npcm750-runbmc-olympus-pincfg.dtsi b/arch/arm/boot/dts/nuvoton/nuvoton-npcm750-runbmc-olympus-pincfg.dtsi similarity index 100% rename from arch/arm/boot/dts/nuvoton-npcm750-runbmc-olympus-pincfg.dtsi rename to arch/arm/boot/dts/nuvoton/nuvoton-npcm750-runbmc-olympus-pincfg.dtsi diff --git a/arch/arm/boot/dts/nuvoton-npcm750-runbmc-olympus.dts b/arch/arm/boot/dts/nuvoton/nuvoton-npcm750-runbmc-olympus.dts similarity index 100% rename from arch/arm/boot/dts/nuvoton-npcm750-runbmc-olympus.dts rename to arch/arm/boot/dts/nuvoton/nuvoton-npcm750-runbmc-olympus.dts diff --git a/arch/arm/boot/dts/nuvoton-npcm750.dtsi b/arch/arm/boot/dts/nuvoton/nuvoton-npcm750.dtsi similarity index 100% rename from arch/arm/boot/dts/nuvoton-npcm750.dtsi rename to arch/arm/boot/dts/nuvoton/nuvoton-npcm750.dtsi diff --git a/arch/arm/boot/dts/nuvoton-wpcm450-supermicro-x9sci-ln4f.dts b/arch/arm/boot/dts/nuvoton/nuvoton-wpcm450-supermicro-x9sci-ln4f.dts similarity index 100% rename from arch/arm/boot/dts/nuvoton-wpcm450-supermicro-x9sci-ln4f.dts rename to arch/arm/boot/dts/nuvoton/nuvoton-wpcm450-supermicro-x9sci-ln4f.dts diff --git a/arch/arm/boot/dts/nuvoton-wpcm450.dtsi b/arch/arm/boot/dts/nuvoton/nuvoton-wpcm450.dtsi similarity index 100% rename from arch/arm/boot/dts/nuvoton-wpcm450.dtsi rename to arch/arm/boot/dts/nuvoton/nuvoton-wpcm450.dtsi diff --git a/arch/arm/boot/dts/nvidia/Makefile b/arch/arm/boot/dts/nvidia/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..60091bf7e48b008bd06784f91a508aacbaa8ece9 --- /dev/null +++ b/arch/arm/boot/dts/nvidia/Makefile @@ -0,0 +1,43 @@ +# SPDX-License-Identifier: GPL-2.0 +dtb-$(CONFIG_ARCH_TEGRA_114_SOC) += \ + tegra114-asus-tf701t.dtb \ + tegra114-dalmore.dtb \ + tegra114-roth.dtb \ + tegra114-tn7.dtb +dtb-$(CONFIG_ARCH_TEGRA_124_SOC) += \ + tegra124-apalis-eval.dtb \ + tegra124-apalis-v1.2-eval.dtb \ + tegra124-jetson-tk1.dtb \ + tegra124-nyan-big.dtb \ + tegra124-nyan-big-fhd.dtb \ + tegra124-nyan-blaze.dtb \ + tegra124-venice2.dtb +dtb-$(CONFIG_ARCH_TEGRA_2x_SOC) += \ + tegra20-acer-a500-picasso.dtb \ + tegra20-asus-tf101.dtb \ + tegra20-harmony.dtb \ + tegra20-colibri-eval-v3.dtb \ + tegra20-colibri-iris.dtb \ + tegra20-medcom-wide.dtb \ + tegra20-paz00.dtb \ + tegra20-plutux.dtb \ + tegra20-seaboard.dtb \ + tegra20-tec.dtb \ + tegra20-trimslice.dtb \ + tegra20-ventana.dtb +dtb-$(CONFIG_ARCH_TEGRA_3x_SOC) += \ + tegra30-apalis-eval.dtb \ + tegra30-apalis-v1.1-eval.dtb \ + tegra30-asus-nexus7-grouper-PM269.dtb \ + tegra30-asus-nexus7-grouper-E1565.dtb \ + tegra30-asus-nexus7-tilapia-E1565.dtb \ + tegra30-asus-tf201.dtb \ + tegra30-asus-tf300t.dtb \ + tegra30-asus-tf300tg.dtb \ + tegra30-asus-tf700t.dtb \ + tegra30-beaver.dtb \ + tegra30-cardhu-a02.dtb \ + tegra30-cardhu-a04.dtb \ + tegra30-colibri-eval-v3.dtb \ + tegra30-ouya.dtb \ + tegra30-pegatron-chagall.dtb diff --git a/arch/arm/boot/dts/tegra114-asus-tf701t.dts b/arch/arm/boot/dts/nvidia/tegra114-asus-tf701t.dts similarity index 100% rename from arch/arm/boot/dts/tegra114-asus-tf701t.dts rename to arch/arm/boot/dts/nvidia/tegra114-asus-tf701t.dts diff --git a/arch/arm/boot/dts/tegra114-dalmore.dts b/arch/arm/boot/dts/nvidia/tegra114-dalmore.dts similarity index 100% rename from arch/arm/boot/dts/tegra114-dalmore.dts rename to arch/arm/boot/dts/nvidia/tegra114-dalmore.dts diff --git a/arch/arm/boot/dts/tegra114-roth.dts b/arch/arm/boot/dts/nvidia/tegra114-roth.dts similarity index 100% rename from arch/arm/boot/dts/tegra114-roth.dts rename to arch/arm/boot/dts/nvidia/tegra114-roth.dts diff --git a/arch/arm/boot/dts/tegra114-tn7.dts b/arch/arm/boot/dts/nvidia/tegra114-tn7.dts similarity index 100% rename from arch/arm/boot/dts/tegra114-tn7.dts rename to arch/arm/boot/dts/nvidia/tegra114-tn7.dts diff --git a/arch/arm/boot/dts/tegra114.dtsi b/arch/arm/boot/dts/nvidia/tegra114.dtsi similarity index 100% rename from arch/arm/boot/dts/tegra114.dtsi rename to arch/arm/boot/dts/nvidia/tegra114.dtsi diff --git a/arch/arm/boot/dts/tegra124-apalis-emc.dtsi b/arch/arm/boot/dts/nvidia/tegra124-apalis-emc.dtsi similarity index 100% rename from arch/arm/boot/dts/tegra124-apalis-emc.dtsi rename to arch/arm/boot/dts/nvidia/tegra124-apalis-emc.dtsi diff --git a/arch/arm/boot/dts/tegra124-apalis-eval.dts b/arch/arm/boot/dts/nvidia/tegra124-apalis-eval.dts similarity index 100% rename from arch/arm/boot/dts/tegra124-apalis-eval.dts rename to arch/arm/boot/dts/nvidia/tegra124-apalis-eval.dts diff --git a/arch/arm/boot/dts/tegra124-apalis-v1.2-eval.dts b/arch/arm/boot/dts/nvidia/tegra124-apalis-v1.2-eval.dts similarity index 100% rename from arch/arm/boot/dts/tegra124-apalis-v1.2-eval.dts rename to arch/arm/boot/dts/nvidia/tegra124-apalis-v1.2-eval.dts diff --git a/arch/arm/boot/dts/tegra124-apalis-v1.2.dtsi b/arch/arm/boot/dts/nvidia/tegra124-apalis-v1.2.dtsi similarity index 100% rename from arch/arm/boot/dts/tegra124-apalis-v1.2.dtsi rename to arch/arm/boot/dts/nvidia/tegra124-apalis-v1.2.dtsi diff --git a/arch/arm/boot/dts/tegra124-apalis.dtsi b/arch/arm/boot/dts/nvidia/tegra124-apalis.dtsi similarity index 100% rename from arch/arm/boot/dts/tegra124-apalis.dtsi rename to arch/arm/boot/dts/nvidia/tegra124-apalis.dtsi diff --git a/arch/arm/boot/dts/tegra124-jetson-tk1-emc.dtsi b/arch/arm/boot/dts/nvidia/tegra124-jetson-tk1-emc.dtsi similarity index 100% rename from arch/arm/boot/dts/tegra124-jetson-tk1-emc.dtsi rename to arch/arm/boot/dts/nvidia/tegra124-jetson-tk1-emc.dtsi diff --git a/arch/arm/boot/dts/tegra124-jetson-tk1.dts b/arch/arm/boot/dts/nvidia/tegra124-jetson-tk1.dts similarity index 100% rename from arch/arm/boot/dts/tegra124-jetson-tk1.dts rename to arch/arm/boot/dts/nvidia/tegra124-jetson-tk1.dts diff --git a/arch/arm/boot/dts/tegra124-nyan-big-emc.dtsi b/arch/arm/boot/dts/nvidia/tegra124-nyan-big-emc.dtsi similarity index 100% rename from arch/arm/boot/dts/tegra124-nyan-big-emc.dtsi rename to arch/arm/boot/dts/nvidia/tegra124-nyan-big-emc.dtsi diff --git a/arch/arm/boot/dts/tegra124-nyan-big-fhd.dts b/arch/arm/boot/dts/nvidia/tegra124-nyan-big-fhd.dts similarity index 100% rename from arch/arm/boot/dts/tegra124-nyan-big-fhd.dts rename to arch/arm/boot/dts/nvidia/tegra124-nyan-big-fhd.dts diff --git a/arch/arm/boot/dts/tegra124-nyan-big.dts b/arch/arm/boot/dts/nvidia/tegra124-nyan-big.dts similarity index 100% rename from arch/arm/boot/dts/tegra124-nyan-big.dts rename to arch/arm/boot/dts/nvidia/tegra124-nyan-big.dts diff --git a/arch/arm/boot/dts/tegra124-nyan-blaze-emc.dtsi b/arch/arm/boot/dts/nvidia/tegra124-nyan-blaze-emc.dtsi similarity index 100% rename from arch/arm/boot/dts/tegra124-nyan-blaze-emc.dtsi rename to arch/arm/boot/dts/nvidia/tegra124-nyan-blaze-emc.dtsi diff --git a/arch/arm/boot/dts/tegra124-nyan-blaze.dts b/arch/arm/boot/dts/nvidia/tegra124-nyan-blaze.dts similarity index 100% rename from arch/arm/boot/dts/tegra124-nyan-blaze.dts rename to arch/arm/boot/dts/nvidia/tegra124-nyan-blaze.dts diff --git a/arch/arm/boot/dts/tegra124-nyan.dtsi b/arch/arm/boot/dts/nvidia/tegra124-nyan.dtsi similarity index 99% rename from arch/arm/boot/dts/tegra124-nyan.dtsi rename to arch/arm/boot/dts/nvidia/tegra124-nyan.dtsi index 56952333ae2856eb3252025022ccb1746c901e69..0c35ca2e91219d5fd076ae58fb575262455128a0 100644 --- a/arch/arm/boot/dts/tegra124-nyan.dtsi +++ b/arch/arm/boot/dts/nvidia/tegra124-nyan.dtsi @@ -833,4 +833,4 @@ }; }; -#include "cros-ec-keyboard.dtsi" +#include "../cros-ec-keyboard.dtsi" diff --git a/arch/arm/boot/dts/tegra124-peripherals-opp.dtsi b/arch/arm/boot/dts/nvidia/tegra124-peripherals-opp.dtsi similarity index 100% rename from arch/arm/boot/dts/tegra124-peripherals-opp.dtsi rename to arch/arm/boot/dts/nvidia/tegra124-peripherals-opp.dtsi diff --git a/arch/arm/boot/dts/tegra124-venice2.dts b/arch/arm/boot/dts/nvidia/tegra124-venice2.dts similarity index 99% rename from arch/arm/boot/dts/tegra124-venice2.dts rename to arch/arm/boot/dts/nvidia/tegra124-venice2.dts index 7e739879c00c16aae0813d9adee52d9876aa718d..c697301c443c236b28d5a68cc3f01abc2d434a6c 100644 --- a/arch/arm/boot/dts/tegra124-venice2.dts +++ b/arch/arm/boot/dts/nvidia/tegra124-venice2.dts @@ -1253,4 +1253,4 @@ }; }; -#include "cros-ec-keyboard.dtsi" +#include "../cros-ec-keyboard.dtsi" diff --git a/arch/arm/boot/dts/tegra124.dtsi b/arch/arm/boot/dts/nvidia/tegra124.dtsi similarity index 100% rename from arch/arm/boot/dts/tegra124.dtsi rename to arch/arm/boot/dts/nvidia/tegra124.dtsi diff --git a/arch/arm/boot/dts/tegra20-acer-a500-picasso.dts b/arch/arm/boot/dts/nvidia/tegra20-acer-a500-picasso.dts similarity index 100% rename from arch/arm/boot/dts/tegra20-acer-a500-picasso.dts rename to arch/arm/boot/dts/nvidia/tegra20-acer-a500-picasso.dts diff --git a/arch/arm/boot/dts/tegra20-asus-tf101.dts b/arch/arm/boot/dts/nvidia/tegra20-asus-tf101.dts similarity index 100% rename from arch/arm/boot/dts/tegra20-asus-tf101.dts rename to arch/arm/boot/dts/nvidia/tegra20-asus-tf101.dts diff --git a/arch/arm/boot/dts/tegra20-colibri-eval-v3.dts b/arch/arm/boot/dts/nvidia/tegra20-colibri-eval-v3.dts similarity index 100% rename from arch/arm/boot/dts/tegra20-colibri-eval-v3.dts rename to arch/arm/boot/dts/nvidia/tegra20-colibri-eval-v3.dts diff --git a/arch/arm/boot/dts/tegra20-colibri-iris.dts b/arch/arm/boot/dts/nvidia/tegra20-colibri-iris.dts similarity index 100% rename from arch/arm/boot/dts/tegra20-colibri-iris.dts rename to arch/arm/boot/dts/nvidia/tegra20-colibri-iris.dts diff --git a/arch/arm/boot/dts/tegra20-colibri.dtsi b/arch/arm/boot/dts/nvidia/tegra20-colibri.dtsi similarity index 100% rename from arch/arm/boot/dts/tegra20-colibri.dtsi rename to arch/arm/boot/dts/nvidia/tegra20-colibri.dtsi diff --git a/arch/arm/boot/dts/tegra20-cpu-opp-microvolt.dtsi b/arch/arm/boot/dts/nvidia/tegra20-cpu-opp-microvolt.dtsi similarity index 100% rename from arch/arm/boot/dts/tegra20-cpu-opp-microvolt.dtsi rename to arch/arm/boot/dts/nvidia/tegra20-cpu-opp-microvolt.dtsi diff --git a/arch/arm/boot/dts/tegra20-cpu-opp.dtsi b/arch/arm/boot/dts/nvidia/tegra20-cpu-opp.dtsi similarity index 100% rename from arch/arm/boot/dts/tegra20-cpu-opp.dtsi rename to arch/arm/boot/dts/nvidia/tegra20-cpu-opp.dtsi diff --git a/arch/arm/boot/dts/tegra20-harmony.dts b/arch/arm/boot/dts/nvidia/tegra20-harmony.dts similarity index 100% rename from arch/arm/boot/dts/tegra20-harmony.dts rename to arch/arm/boot/dts/nvidia/tegra20-harmony.dts diff --git a/arch/arm/boot/dts/tegra20-medcom-wide.dts b/arch/arm/boot/dts/nvidia/tegra20-medcom-wide.dts similarity index 100% rename from arch/arm/boot/dts/tegra20-medcom-wide.dts rename to arch/arm/boot/dts/nvidia/tegra20-medcom-wide.dts diff --git a/arch/arm/boot/dts/tegra20-paz00.dts b/arch/arm/boot/dts/nvidia/tegra20-paz00.dts similarity index 100% rename from arch/arm/boot/dts/tegra20-paz00.dts rename to arch/arm/boot/dts/nvidia/tegra20-paz00.dts diff --git a/arch/arm/boot/dts/tegra20-peripherals-opp.dtsi b/arch/arm/boot/dts/nvidia/tegra20-peripherals-opp.dtsi similarity index 100% rename from arch/arm/boot/dts/tegra20-peripherals-opp.dtsi rename to arch/arm/boot/dts/nvidia/tegra20-peripherals-opp.dtsi diff --git a/arch/arm/boot/dts/tegra20-plutux.dts b/arch/arm/boot/dts/nvidia/tegra20-plutux.dts similarity index 100% rename from arch/arm/boot/dts/tegra20-plutux.dts rename to arch/arm/boot/dts/nvidia/tegra20-plutux.dts diff --git a/arch/arm/boot/dts/tegra20-seaboard.dts b/arch/arm/boot/dts/nvidia/tegra20-seaboard.dts similarity index 100% rename from arch/arm/boot/dts/tegra20-seaboard.dts rename to arch/arm/boot/dts/nvidia/tegra20-seaboard.dts diff --git a/arch/arm/boot/dts/tegra20-tamonten.dtsi b/arch/arm/boot/dts/nvidia/tegra20-tamonten.dtsi similarity index 100% rename from arch/arm/boot/dts/tegra20-tamonten.dtsi rename to arch/arm/boot/dts/nvidia/tegra20-tamonten.dtsi diff --git a/arch/arm/boot/dts/tegra20-tec.dts b/arch/arm/boot/dts/nvidia/tegra20-tec.dts similarity index 100% rename from arch/arm/boot/dts/tegra20-tec.dts rename to arch/arm/boot/dts/nvidia/tegra20-tec.dts diff --git a/arch/arm/boot/dts/tegra20-trimslice.dts b/arch/arm/boot/dts/nvidia/tegra20-trimslice.dts similarity index 100% rename from arch/arm/boot/dts/tegra20-trimslice.dts rename to arch/arm/boot/dts/nvidia/tegra20-trimslice.dts diff --git a/arch/arm/boot/dts/tegra20-ventana.dts b/arch/arm/boot/dts/nvidia/tegra20-ventana.dts similarity index 100% rename from arch/arm/boot/dts/tegra20-ventana.dts rename to arch/arm/boot/dts/nvidia/tegra20-ventana.dts diff --git a/arch/arm/boot/dts/tegra20.dtsi b/arch/arm/boot/dts/nvidia/tegra20.dtsi similarity index 100% rename from arch/arm/boot/dts/tegra20.dtsi rename to arch/arm/boot/dts/nvidia/tegra20.dtsi diff --git a/arch/arm/boot/dts/tegra30-apalis-eval.dts b/arch/arm/boot/dts/nvidia/tegra30-apalis-eval.dts similarity index 100% rename from arch/arm/boot/dts/tegra30-apalis-eval.dts rename to arch/arm/boot/dts/nvidia/tegra30-apalis-eval.dts diff --git a/arch/arm/boot/dts/tegra30-apalis-v1.1-eval.dts b/arch/arm/boot/dts/nvidia/tegra30-apalis-v1.1-eval.dts similarity index 100% rename from arch/arm/boot/dts/tegra30-apalis-v1.1-eval.dts rename to arch/arm/boot/dts/nvidia/tegra30-apalis-v1.1-eval.dts diff --git a/arch/arm/boot/dts/tegra30-apalis-v1.1.dtsi b/arch/arm/boot/dts/nvidia/tegra30-apalis-v1.1.dtsi similarity index 100% rename from arch/arm/boot/dts/tegra30-apalis-v1.1.dtsi rename to arch/arm/boot/dts/nvidia/tegra30-apalis-v1.1.dtsi diff --git a/arch/arm/boot/dts/tegra30-apalis.dtsi b/arch/arm/boot/dts/nvidia/tegra30-apalis.dtsi similarity index 100% rename from arch/arm/boot/dts/tegra30-apalis.dtsi rename to arch/arm/boot/dts/nvidia/tegra30-apalis.dtsi diff --git a/arch/arm/boot/dts/tegra30-asus-lvds-display.dtsi b/arch/arm/boot/dts/nvidia/tegra30-asus-lvds-display.dtsi similarity index 100% rename from arch/arm/boot/dts/tegra30-asus-lvds-display.dtsi rename to arch/arm/boot/dts/nvidia/tegra30-asus-lvds-display.dtsi diff --git a/arch/arm/boot/dts/tegra30-asus-nexus7-grouper-E1565.dts b/arch/arm/boot/dts/nvidia/tegra30-asus-nexus7-grouper-E1565.dts similarity index 100% rename from arch/arm/boot/dts/tegra30-asus-nexus7-grouper-E1565.dts rename to arch/arm/boot/dts/nvidia/tegra30-asus-nexus7-grouper-E1565.dts diff --git a/arch/arm/boot/dts/tegra30-asus-nexus7-grouper-PM269.dts b/arch/arm/boot/dts/nvidia/tegra30-asus-nexus7-grouper-PM269.dts similarity index 100% rename from arch/arm/boot/dts/tegra30-asus-nexus7-grouper-PM269.dts rename to arch/arm/boot/dts/nvidia/tegra30-asus-nexus7-grouper-PM269.dts diff --git a/arch/arm/boot/dts/tegra30-asus-nexus7-grouper-common.dtsi b/arch/arm/boot/dts/nvidia/tegra30-asus-nexus7-grouper-common.dtsi similarity index 100% rename from arch/arm/boot/dts/tegra30-asus-nexus7-grouper-common.dtsi rename to arch/arm/boot/dts/nvidia/tegra30-asus-nexus7-grouper-common.dtsi diff --git a/arch/arm/boot/dts/tegra30-asus-nexus7-grouper-maxim-pmic.dtsi b/arch/arm/boot/dts/nvidia/tegra30-asus-nexus7-grouper-maxim-pmic.dtsi similarity index 100% rename from arch/arm/boot/dts/tegra30-asus-nexus7-grouper-maxim-pmic.dtsi rename to arch/arm/boot/dts/nvidia/tegra30-asus-nexus7-grouper-maxim-pmic.dtsi diff --git a/arch/arm/boot/dts/tegra30-asus-nexus7-grouper-memory-timings.dtsi b/arch/arm/boot/dts/nvidia/tegra30-asus-nexus7-grouper-memory-timings.dtsi similarity index 100% rename from arch/arm/boot/dts/tegra30-asus-nexus7-grouper-memory-timings.dtsi rename to arch/arm/boot/dts/nvidia/tegra30-asus-nexus7-grouper-memory-timings.dtsi diff --git a/arch/arm/boot/dts/tegra30-asus-nexus7-grouper-ti-pmic.dtsi b/arch/arm/boot/dts/nvidia/tegra30-asus-nexus7-grouper-ti-pmic.dtsi similarity index 100% rename from arch/arm/boot/dts/tegra30-asus-nexus7-grouper-ti-pmic.dtsi rename to arch/arm/boot/dts/nvidia/tegra30-asus-nexus7-grouper-ti-pmic.dtsi diff --git a/arch/arm/boot/dts/tegra30-asus-nexus7-grouper.dtsi b/arch/arm/boot/dts/nvidia/tegra30-asus-nexus7-grouper.dtsi similarity index 100% rename from arch/arm/boot/dts/tegra30-asus-nexus7-grouper.dtsi rename to arch/arm/boot/dts/nvidia/tegra30-asus-nexus7-grouper.dtsi diff --git a/arch/arm/boot/dts/tegra30-asus-nexus7-tilapia-E1565.dts b/arch/arm/boot/dts/nvidia/tegra30-asus-nexus7-tilapia-E1565.dts similarity index 100% rename from arch/arm/boot/dts/tegra30-asus-nexus7-tilapia-E1565.dts rename to arch/arm/boot/dts/nvidia/tegra30-asus-nexus7-tilapia-E1565.dts diff --git a/arch/arm/boot/dts/tegra30-asus-nexus7-tilapia-memory-timings.dtsi b/arch/arm/boot/dts/nvidia/tegra30-asus-nexus7-tilapia-memory-timings.dtsi similarity index 100% rename from arch/arm/boot/dts/tegra30-asus-nexus7-tilapia-memory-timings.dtsi rename to arch/arm/boot/dts/nvidia/tegra30-asus-nexus7-tilapia-memory-timings.dtsi diff --git a/arch/arm/boot/dts/tegra30-asus-nexus7-tilapia.dtsi b/arch/arm/boot/dts/nvidia/tegra30-asus-nexus7-tilapia.dtsi similarity index 100% rename from arch/arm/boot/dts/tegra30-asus-nexus7-tilapia.dtsi rename to arch/arm/boot/dts/nvidia/tegra30-asus-nexus7-tilapia.dtsi diff --git a/arch/arm/boot/dts/tegra30-asus-tf201.dts b/arch/arm/boot/dts/nvidia/tegra30-asus-tf201.dts similarity index 100% rename from arch/arm/boot/dts/tegra30-asus-tf201.dts rename to arch/arm/boot/dts/nvidia/tegra30-asus-tf201.dts diff --git a/arch/arm/boot/dts/tegra30-asus-tf300t.dts b/arch/arm/boot/dts/nvidia/tegra30-asus-tf300t.dts similarity index 100% rename from arch/arm/boot/dts/tegra30-asus-tf300t.dts rename to arch/arm/boot/dts/nvidia/tegra30-asus-tf300t.dts diff --git a/arch/arm/boot/dts/tegra30-asus-tf300tg.dts b/arch/arm/boot/dts/nvidia/tegra30-asus-tf300tg.dts similarity index 100% rename from arch/arm/boot/dts/tegra30-asus-tf300tg.dts rename to arch/arm/boot/dts/nvidia/tegra30-asus-tf300tg.dts diff --git a/arch/arm/boot/dts/tegra30-asus-tf700t.dts b/arch/arm/boot/dts/nvidia/tegra30-asus-tf700t.dts similarity index 100% rename from arch/arm/boot/dts/tegra30-asus-tf700t.dts rename to arch/arm/boot/dts/nvidia/tegra30-asus-tf700t.dts diff --git a/arch/arm/boot/dts/tegra30-asus-transformer-common.dtsi b/arch/arm/boot/dts/nvidia/tegra30-asus-transformer-common.dtsi similarity index 100% rename from arch/arm/boot/dts/tegra30-asus-transformer-common.dtsi rename to arch/arm/boot/dts/nvidia/tegra30-asus-transformer-common.dtsi diff --git a/arch/arm/boot/dts/tegra30-beaver.dts b/arch/arm/boot/dts/nvidia/tegra30-beaver.dts similarity index 100% rename from arch/arm/boot/dts/tegra30-beaver.dts rename to arch/arm/boot/dts/nvidia/tegra30-beaver.dts diff --git a/arch/arm/boot/dts/tegra30-cardhu-a02.dts b/arch/arm/boot/dts/nvidia/tegra30-cardhu-a02.dts similarity index 100% rename from arch/arm/boot/dts/tegra30-cardhu-a02.dts rename to arch/arm/boot/dts/nvidia/tegra30-cardhu-a02.dts diff --git a/arch/arm/boot/dts/tegra30-cardhu-a04.dts b/arch/arm/boot/dts/nvidia/tegra30-cardhu-a04.dts similarity index 100% rename from arch/arm/boot/dts/tegra30-cardhu-a04.dts rename to arch/arm/boot/dts/nvidia/tegra30-cardhu-a04.dts diff --git a/arch/arm/boot/dts/tegra30-cardhu.dtsi b/arch/arm/boot/dts/nvidia/tegra30-cardhu.dtsi similarity index 100% rename from arch/arm/boot/dts/tegra30-cardhu.dtsi rename to arch/arm/boot/dts/nvidia/tegra30-cardhu.dtsi diff --git a/arch/arm/boot/dts/tegra30-colibri-eval-v3.dts b/arch/arm/boot/dts/nvidia/tegra30-colibri-eval-v3.dts similarity index 100% rename from arch/arm/boot/dts/tegra30-colibri-eval-v3.dts rename to arch/arm/boot/dts/nvidia/tegra30-colibri-eval-v3.dts diff --git a/arch/arm/boot/dts/tegra30-colibri.dtsi b/arch/arm/boot/dts/nvidia/tegra30-colibri.dtsi similarity index 100% rename from arch/arm/boot/dts/tegra30-colibri.dtsi rename to arch/arm/boot/dts/nvidia/tegra30-colibri.dtsi diff --git a/arch/arm/boot/dts/tegra30-cpu-opp-microvolt.dtsi b/arch/arm/boot/dts/nvidia/tegra30-cpu-opp-microvolt.dtsi similarity index 100% rename from arch/arm/boot/dts/tegra30-cpu-opp-microvolt.dtsi rename to arch/arm/boot/dts/nvidia/tegra30-cpu-opp-microvolt.dtsi diff --git a/arch/arm/boot/dts/tegra30-cpu-opp.dtsi b/arch/arm/boot/dts/nvidia/tegra30-cpu-opp.dtsi similarity index 100% rename from arch/arm/boot/dts/tegra30-cpu-opp.dtsi rename to arch/arm/boot/dts/nvidia/tegra30-cpu-opp.dtsi diff --git a/arch/arm/boot/dts/tegra30-ouya.dts b/arch/arm/boot/dts/nvidia/tegra30-ouya.dts similarity index 100% rename from arch/arm/boot/dts/tegra30-ouya.dts rename to arch/arm/boot/dts/nvidia/tegra30-ouya.dts diff --git a/arch/arm/boot/dts/tegra30-pegatron-chagall.dts b/arch/arm/boot/dts/nvidia/tegra30-pegatron-chagall.dts similarity index 100% rename from arch/arm/boot/dts/tegra30-pegatron-chagall.dts rename to arch/arm/boot/dts/nvidia/tegra30-pegatron-chagall.dts diff --git a/arch/arm/boot/dts/tegra30-peripherals-opp.dtsi b/arch/arm/boot/dts/nvidia/tegra30-peripherals-opp.dtsi similarity index 100% rename from arch/arm/boot/dts/tegra30-peripherals-opp.dtsi rename to arch/arm/boot/dts/nvidia/tegra30-peripherals-opp.dtsi diff --git a/arch/arm/boot/dts/tegra30.dtsi b/arch/arm/boot/dts/nvidia/tegra30.dtsi similarity index 100% rename from arch/arm/boot/dts/tegra30.dtsi rename to arch/arm/boot/dts/nvidia/tegra30.dtsi diff --git a/arch/arm/boot/dts/nxp/Makefile b/arch/arm/boot/dts/nxp/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..db44e7a0a1983dd0f923b24b5db950fd44d2c105 --- /dev/null +++ b/arch/arm/boot/dts/nxp/Makefile @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0 +subdir-y += imx +subdir-y += lpc +subdir-y += ls +subdir-y += mxs +subdir-y += vf diff --git a/arch/arm/boot/dts/nxp/imx/Makefile b/arch/arm/boot/dts/nxp/imx/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..3629e343d3225b87f75c9c4d2eddc5dbc0bebdd2 --- /dev/null +++ b/arch/arm/boot/dts/nxp/imx/Makefile @@ -0,0 +1,388 @@ +# SPDX-License-Identifier: GPL-2.0 +dtb-$(CONFIG_SOC_IMX1) += \ + imx1-ads.dtb \ + imx1-apf9328.dtb +dtb-$(CONFIG_SOC_IMX25) += \ + imx25-eukrea-mbimxsd25-baseboard.dtb \ + imx25-eukrea-mbimxsd25-baseboard-cmo-qvga.dtb \ + imx25-eukrea-mbimxsd25-baseboard-dvi-svga.dtb \ + imx25-eukrea-mbimxsd25-baseboard-dvi-vga.dtb \ + imx25-karo-tx25.dtb \ + imx25-pdk.dtb +dtb-$(CONFIG_SOC_IMX27) += \ + imx27-apf27.dtb \ + imx27-apf27dev.dtb \ + imx27-eukrea-mbimxsd27-baseboard.dtb \ + imx27-pdk.dtb \ + imx27-phytec-phycore-rdk.dtb \ + imx27-phytec-phycard-s-rdk.dtb +dtb-$(CONFIG_SOC_IMX31) += \ + imx31-bug.dtb \ + imx31-lite.dtb +dtb-$(CONFIG_SOC_IMX35) += \ + imx35-eukrea-mbimxsd35-baseboard.dtb \ + imx35-pdk.dtb +dtb-$(CONFIG_SOC_IMX50) += \ + imx50-evk.dtb \ + imx50-kobo-aura.dtb +dtb-$(CONFIG_SOC_IMX51) += \ + imx51-apf51.dtb \ + imx51-apf51dev.dtb \ + imx51-babbage.dtb \ + imx51-digi-connectcore-jsk.dtb \ + imx51-eukrea-mbimxsd51-baseboard.dtb \ + imx51-ts4800.dtb \ + imx51-zii-rdu1.dtb \ + imx51-zii-scu2-mezz.dtb \ + imx51-zii-scu3-esb.dtb +dtb-$(CONFIG_SOC_IMX53) += \ + imx53-ard.dtb \ + imx53-cx9020.dtb \ + imx53-kp-ddc.dtb \ + imx53-kp-hsc.dtb \ + imx53-m53evk.dtb \ + imx53-m53menlo.dtb \ + imx53-mba53.dtb \ + imx53-ppd.dtb \ + imx53-qsb.dtb \ + imx53-qsrb.dtb \ + imx53-sk-imx53.dtb \ + imx53-smd.dtb \ + imx53-tx53-x03x.dtb \ + imx53-tx53-x13x.dtb \ + imx53-usbarmory.dtb \ + imx53-voipac-bsb.dtb +dtb-$(CONFIG_SOC_IMX6Q) += \ + imx6dl-alti6p.dtb \ + imx6dl-apf6dev.dtb \ + imx6dl-aristainetos_4.dtb \ + imx6dl-aristainetos_7.dtb \ + imx6dl-aristainetos2_4.dtb \ + imx6dl-aristainetos2_7.dtb \ + imx6dl-colibri-aster.dtb \ + imx6dl-colibri-eval-v3.dtb \ + imx6dl-colibri-iris.dtb \ + imx6dl-colibri-iris-v2.dtb \ + imx6dl-cubox-i.dtb \ + imx6dl-cubox-i-emmc-som-v15.dtb \ + imx6dl-cubox-i-som-v15.dtb \ + imx6dl-dfi-fs700-m60.dtb \ + imx6dl-dhcom-picoitx.dtb \ + imx6dl-eckelmann-ci4x10.dtb \ + imx6dl-emcon-avari.dtb \ + imx6dl-gw51xx.dtb \ + imx6dl-gw52xx.dtb \ + imx6dl-gw53xx.dtb \ + imx6dl-gw54xx.dtb \ + imx6dl-gw551x.dtb \ + imx6dl-gw552x.dtb \ + imx6dl-gw553x.dtb \ + imx6dl-gw560x.dtb \ + imx6dl-gw5903.dtb \ + imx6dl-gw5904.dtb \ + imx6dl-gw5907.dtb \ + imx6dl-gw5910.dtb \ + imx6dl-gw5912.dtb \ + imx6dl-gw5913.dtb \ + imx6dl-hummingboard.dtb \ + imx6dl-hummingboard-emmc-som-v15.dtb \ + imx6dl-hummingboard-som-v15.dtb \ + imx6dl-hummingboard2.dtb \ + imx6dl-hummingboard2-emmc-som-v15.dtb \ + imx6dl-hummingboard2-som-v15.dtb \ + imx6dl-icore.dtb \ + imx6dl-icore-mipi.dtb \ + imx6dl-icore-rqs.dtb \ + imx6dl-lanmcu.dtb \ + imx6dl-mamoj.dtb \ + imx6dl-mba6a.dtb \ + imx6dl-mba6b.dtb \ + imx6dl-nit6xlite.dtb \ + imx6dl-nitrogen6x.dtb \ + imx6dl-phytec-mira-rdk-nand.dtb \ + imx6dl-phytec-pbab01.dtb \ + imx6dl-pico-dwarf.dtb \ + imx6dl-pico-hobbit.dtb \ + imx6dl-pico-nymph.dtb \ + imx6dl-pico-pi.dtb \ + imx6dl-plybas.dtb \ + imx6dl-plym2m.dtb \ + imx6dl-prtmvt.dtb \ + imx6dl-prtrvt.dtb \ + imx6dl-prtvt7.dtb \ + imx6dl-rex-basic.dtb \ + imx6dl-riotboard.dtb \ + imx6dl-sabreauto.dtb \ + imx6dl-sabrelite.dtb \ + imx6dl-sabresd.dtb \ + imx6dl-savageboard.dtb \ + imx6dl-skov-revc-lt2.dtb \ + imx6dl-skov-revc-lt6.dtb \ + imx6dl-solidsense.dtb \ + imx6dl-ts4900.dtb \ + imx6dl-ts7970.dtb \ + imx6dl-tx6dl-comtft.dtb \ + imx6dl-tx6s-8034.dtb \ + imx6dl-tx6s-8034-mb7.dtb \ + imx6dl-tx6s-8035.dtb \ + imx6dl-tx6s-8035-mb7.dtb \ + imx6dl-tx6u-801x.dtb \ + imx6dl-tx6u-80xx-mb7.dtb \ + imx6dl-tx6u-8033.dtb \ + imx6dl-tx6u-8033-mb7.dtb \ + imx6dl-tx6u-811x.dtb \ + imx6dl-tx6u-81xx-mb7.dtb \ + imx6dl-udoo.dtb \ + imx6dl-victgo.dtb \ + imx6dl-vicut1.dtb \ + imx6dl-wandboard.dtb \ + imx6dl-wandboard-revb1.dtb \ + imx6dl-wandboard-revd1.dtb \ + imx6dl-yapp4-draco.dtb \ + imx6dl-yapp4-hydra.dtb \ + imx6dl-yapp4-lynx.dtb \ + imx6dl-yapp4-orion.dtb \ + imx6dl-yapp4-phoenix.dtb \ + imx6dl-yapp4-ursa.dtb \ + imx6q-apalis-eval.dtb \ + imx6q-apalis-ixora.dtb \ + imx6q-apalis-ixora-v1.1.dtb \ + imx6q-apalis-ixora-v1.2.dtb \ + imx6q-apf6dev.dtb \ + imx6q-arm2.dtb \ + imx6q-b450v3.dtb \ + imx6q-b650v3.dtb \ + imx6q-b850v3.dtb \ + imx6q-bosch-acc.dtb \ + imx6q-cm-fx6.dtb \ + imx6q-cubox-i.dtb \ + imx6q-cubox-i-emmc-som-v15.dtb \ + imx6q-cubox-i-som-v15.dtb \ + imx6q-dfi-fs700-m60.dtb \ + imx6q-dhcom-pdk2.dtb \ + imx6q-display5-tianma-tm070-1280x768.dtb \ + imx6q-dmo-edmqmx6.dtb \ + imx6q-dms-ba16.dtb \ + imx6q-ds.dtb \ + imx6q-emcon-avari.dtb \ + imx6q-evi.dtb \ + imx6dl-b105pv2.dtb \ + imx6dl-b105v2.dtb \ + imx6dl-b125v2.dtb \ + imx6dl-b125pv2.dtb \ + imx6dl-b155v2.dtb \ + imx6q-gk802.dtb \ + imx6q-gw51xx.dtb \ + imx6q-gw52xx.dtb \ + imx6q-gw53xx.dtb \ + imx6q-gw5400-a.dtb \ + imx6q-gw54xx.dtb \ + imx6q-gw551x.dtb \ + imx6q-gw552x.dtb \ + imx6q-gw553x.dtb \ + imx6q-gw560x.dtb \ + imx6q-gw5903.dtb \ + imx6q-gw5904.dtb \ + imx6q-gw5907.dtb \ + imx6q-gw5910.dtb \ + imx6q-gw5912.dtb \ + imx6q-gw5913.dtb \ + imx6q-h100.dtb \ + imx6q-hummingboard.dtb \ + imx6q-hummingboard-emmc-som-v15.dtb \ + imx6q-hummingboard-som-v15.dtb \ + imx6q-hummingboard2.dtb \ + imx6q-hummingboard2-emmc-som-v15.dtb \ + imx6q-hummingboard2-som-v15.dtb \ + imx6q-icore.dtb \ + imx6q-icore-mipi.dtb \ + imx6q-icore-ofcap10.dtb \ + imx6q-icore-ofcap12.dtb \ + imx6q-icore-rqs.dtb \ + imx6q-kp-tpc.dtb \ + imx6q-logicpd.dtb \ + imx6q-marsboard.dtb \ + imx6q-mba6a.dtb \ + imx6q-mba6b.dtb \ + imx6q-mccmon6.dtb \ + imx6q-nitrogen6x.dtb \ + imx6q-nitrogen6_max.dtb \ + imx6q-nitrogen6_som2.dtb \ + imx6q-novena.dtb \ + imx6q-phytec-mira-rdk-emmc.dtb \ + imx6q-phytec-mira-rdk-nand.dtb \ + imx6q-phytec-pbab01.dtb \ + imx6q-pico-dwarf.dtb \ + imx6q-pico-hobbit.dtb \ + imx6q-pico-nymph.dtb \ + imx6q-pico-pi.dtb \ + imx6q-pistachio.dtb \ + imx6q-prti6q.dtb \ + imx6q-prtwd2.dtb \ + imx6q-rex-pro.dtb \ + imx6q-sabreauto.dtb \ + imx6q-sabrelite.dtb \ + imx6q-sabresd.dtb \ + imx6q-savageboard.dtb \ + imx6q-sbc6x.dtb \ + imx6q-skov-revc-lt2.dtb \ + imx6q-skov-revc-lt6.dtb \ + imx6q-skov-reve-mi1010ait-1cp1.dtb \ + imx6q-solidsense.dtb \ + imx6q-tbs2910.dtb \ + imx6q-ts4900.dtb \ + imx6q-ts7970.dtb \ + imx6q-tx6q-1010.dtb \ + imx6q-tx6q-1010-comtft.dtb \ + imx6q-tx6q-1020.dtb \ + imx6q-tx6q-1020-comtft.dtb \ + imx6q-tx6q-1036.dtb \ + imx6q-tx6q-1036-mb7.dtb \ + imx6q-tx6q-10x0-mb7.dtb \ + imx6q-tx6q-1110.dtb \ + imx6q-tx6q-11x0-mb7.dtb \ + imx6q-udoo.dtb \ + imx6q-utilite-pro.dtb \ + imx6q-var-dt6customboard.dtb \ + imx6q-vicut1.dtb \ + imx6q-wandboard.dtb \ + imx6q-wandboard-revb1.dtb \ + imx6q-wandboard-revd1.dtb \ + imx6q-yapp4-crux.dtb \ + imx6q-yapp4-pegasus.dtb \ + imx6q-zii-rdu2.dtb \ + imx6qp-mba6b.dtb \ + imx6qp-nitrogen6_max.dtb \ + imx6qp-nitrogen6_som2.dtb \ + imx6qp-phytec-mira-rdk-nand.dtb \ + imx6qp-prtwd3.dtb \ + imx6qp-sabreauto.dtb \ + imx6qp-sabresd.dtb \ + imx6qp-tx6qp-8037.dtb \ + imx6qp-tx6qp-8037-mb7.dtb \ + imx6qp-tx6qp-8137.dtb \ + imx6qp-tx6qp-8137-mb7.dtb \ + imx6qp-vicutp.dtb \ + imx6qp-wandboard-revd1.dtb \ + imx6qp-yapp4-crux-plus.dtb \ + imx6qp-yapp4-pegasus-plus.dtb \ + imx6qp-zii-rdu2.dtb \ + imx6s-dhcom-drc02.dtb +dtb-$(CONFIG_SOC_IMX6SL) += \ + imx6sl-evk.dtb \ + imx6sl-kobo-aura2.dtb \ + imx6sl-tolino-shine2hd.dtb \ + imx6sl-tolino-shine3.dtb \ + imx6sl-tolino-vision.dtb \ + imx6sl-tolino-vision5.dtb \ + imx6sl-warp.dtb +dtb-$(CONFIG_SOC_IMX6SLL) += \ + imx6sll-evk.dtb \ + imx6sll-kobo-clarahd.dtb \ + imx6sll-kobo-librah2o.dtb +dtb-$(CONFIG_SOC_IMX6SX) += \ + imx6sx-nitrogen6sx.dtb \ + imx6sx-sabreauto.dtb \ + imx6sx-sdb-reva.dtb \ + imx6sx-sdb-sai.dtb \ + imx6sx-sdb.dtb \ + imx6sx-sdb-mqs.dtb \ + imx6sx-softing-vining-2000.dtb \ + imx6sx-udoo-neo-basic.dtb \ + imx6sx-udoo-neo-extended.dtb \ + imx6sx-udoo-neo-full.dtb +dtb-$(CONFIG_SOC_IMX6UL) += \ + imx6ul-14x14-evk.dtb \ + imx6ul-ccimx6ulsbcexpress.dtb \ + imx6ul-ccimx6ulsbcpro.dtb \ + imx6ul-geam.dtb \ + imx6ul-isiot-emmc.dtb \ + imx6ul-isiot-nand.dtb \ + imx6ul-kontron-bl.dtb \ + imx6ul-kontron-bl-43.dtb \ + imx6ul-liteboard.dtb \ + imx6ul-tqma6ul1-mba6ulx.dtb \ + imx6ul-tqma6ul2-mba6ulx.dtb \ + imx6ul-tqma6ul2l-mba6ulx.dtb \ + imx6ul-opos6uldev.dtb \ + imx6ul-pico-dwarf.dtb \ + imx6ul-pico-hobbit.dtb \ + imx6ul-pico-pi.dtb \ + imx6ul-phytec-segin-ff-rdk-emmc.dtb \ + imx6ul-phytec-segin-ff-rdk-nand.dtb \ + imx6ul-prti6g.dtb \ + imx6ul-tx6ul-0010.dtb \ + imx6ul-tx6ul-0011.dtb \ + imx6ul-tx6ul-mainboard.dtb \ + imx6ull-14x14-evk.dtb \ + imx6ull-colibri-aster.dtb \ + imx6ull-colibri-emmc-aster.dtb \ + imx6ull-colibri-emmc-eval-v3.dtb \ + imx6ull-colibri-emmc-iris.dtb \ + imx6ull-colibri-emmc-iris-v2.dtb \ + imx6ull-colibri-eval-v3.dtb \ + imx6ull-colibri-iris.dtb \ + imx6ull-colibri-iris-v2.dtb \ + imx6ull-colibri-wifi-aster.dtb \ + imx6ull-colibri-wifi-eval-v3.dtb \ + imx6ull-colibri-wifi-iris.dtb \ + imx6ull-colibri-wifi-iris-v2.dtb \ + imx6ull-dhcom-drc02.dtb \ + imx6ull-dhcom-pdk2.dtb \ + imx6ull-dhcom-picoitx.dtb \ + imx6ull-dhcor-maveo-box.dtb \ + imx6ull-jozacp.dtb \ + imx6ull-kontron-bl.dtb \ + imx6ull-myir-mys-6ulx-eval.dtb \ + imx6ull-opos6uldev.dtb \ + imx6ull-phytec-segin-ff-rdk-nand.dtb \ + imx6ull-phytec-segin-ff-rdk-emmc.dtb \ + imx6ull-phytec-segin-lc-rdk-nand.dtb \ + imx6ull-phytec-tauri-emmc.dtb \ + imx6ull-phytec-tauri-nand.dtb \ + imx6ull-tarragon-master.dtb \ + imx6ull-tarragon-micro.dtb \ + imx6ull-tarragon-slave.dtb \ + imx6ull-tarragon-slavext.dtb \ + imx6ull-tqma6ull2-mba6ulx.dtb \ + imx6ull-tqma6ull2l-mba6ulx.dtb \ + imx6ulz-14x14-evk.dtb \ + imx6ulz-bsh-smm-m2.dtb +dtb-$(CONFIG_SOC_IMX7D) += \ + imx7d-cl-som-imx7.dtb \ + imx7d-colibri-aster.dtb \ + imx7d-colibri-emmc-aster.dtb \ + imx7d-colibri-emmc-iris.dtb \ + imx7d-colibri-emmc-iris-v2.dtb \ + imx7d-colibri-emmc-eval-v3.dtb \ + imx7d-colibri-eval-v3.dtb \ + imx7d-colibri-iris.dtb \ + imx7d-colibri-iris-v2.dtb \ + imx7d-flex-concentrator.dtb \ + imx7d-flex-concentrator-mfg.dtb \ + imx7d-mba7.dtb \ + imx7d-meerkat96.dtb \ + imx7d-nitrogen7.dtb \ + imx7d-pico-dwarf.dtb \ + imx7d-pico-hobbit.dtb \ + imx7d-pico-nymph.dtb \ + imx7d-pico-pi.dtb \ + imx7d-remarkable2.dtb \ + imx7d-sbc-imx7.dtb \ + imx7d-sdb.dtb \ + imx7d-sdb-reva.dtb \ + imx7d-sdb-sht11.dtb \ + imx7d-smegw01.dtb \ + imx7d-zii-rmu2.dtb \ + imx7d-zii-rpu2.dtb \ + imx7s-colibri-aster.dtb \ + imx7s-colibri-eval-v3.dtb \ + imx7s-colibri-iris.dtb \ + imx7s-colibri-iris-v2.dtb \ + imx7s-mba7.dtb \ + imx7s-warp.dtb +dtb-$(CONFIG_SOC_IMX7ULP) += \ + imx7ulp-com.dtb \ + imx7ulp-evk.dtb +dtb-$(CONFIG_SOC_IMXRT) += \ + imxrt1050-evk.dtb diff --git a/arch/arm/boot/dts/e60k02.dtsi b/arch/arm/boot/dts/nxp/imx/e60k02.dtsi similarity index 100% rename from arch/arm/boot/dts/e60k02.dtsi rename to arch/arm/boot/dts/nxp/imx/e60k02.dtsi diff --git a/arch/arm/boot/dts/e70k02.dtsi b/arch/arm/boot/dts/nxp/imx/e70k02.dtsi similarity index 100% rename from arch/arm/boot/dts/e70k02.dtsi rename to arch/arm/boot/dts/nxp/imx/e70k02.dtsi diff --git a/arch/arm/boot/dts/imx1-ads.dts b/arch/arm/boot/dts/nxp/imx/imx1-ads.dts similarity index 100% rename from arch/arm/boot/dts/imx1-ads.dts rename to arch/arm/boot/dts/nxp/imx/imx1-ads.dts diff --git a/arch/arm/boot/dts/imx1-apf9328.dts b/arch/arm/boot/dts/nxp/imx/imx1-apf9328.dts similarity index 100% rename from arch/arm/boot/dts/imx1-apf9328.dts rename to arch/arm/boot/dts/nxp/imx/imx1-apf9328.dts diff --git a/arch/arm/boot/dts/imx1-pinfunc.h b/arch/arm/boot/dts/nxp/imx/imx1-pinfunc.h similarity index 100% rename from arch/arm/boot/dts/imx1-pinfunc.h rename to arch/arm/boot/dts/nxp/imx/imx1-pinfunc.h diff --git a/arch/arm/boot/dts/imx1.dtsi b/arch/arm/boot/dts/nxp/imx/imx1.dtsi similarity index 100% rename from arch/arm/boot/dts/imx1.dtsi rename to arch/arm/boot/dts/nxp/imx/imx1.dtsi diff --git a/arch/arm/boot/dts/imx25-eukrea-cpuimx25.dtsi b/arch/arm/boot/dts/nxp/imx/imx25-eukrea-cpuimx25.dtsi similarity index 100% rename from arch/arm/boot/dts/imx25-eukrea-cpuimx25.dtsi rename to arch/arm/boot/dts/nxp/imx/imx25-eukrea-cpuimx25.dtsi diff --git a/arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard-cmo-qvga.dts b/arch/arm/boot/dts/nxp/imx/imx25-eukrea-mbimxsd25-baseboard-cmo-qvga.dts similarity index 100% rename from arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard-cmo-qvga.dts rename to arch/arm/boot/dts/nxp/imx/imx25-eukrea-mbimxsd25-baseboard-cmo-qvga.dts diff --git a/arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard-dvi-svga.dts b/arch/arm/boot/dts/nxp/imx/imx25-eukrea-mbimxsd25-baseboard-dvi-svga.dts similarity index 100% rename from arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard-dvi-svga.dts rename to arch/arm/boot/dts/nxp/imx/imx25-eukrea-mbimxsd25-baseboard-dvi-svga.dts diff --git a/arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard-dvi-vga.dts b/arch/arm/boot/dts/nxp/imx/imx25-eukrea-mbimxsd25-baseboard-dvi-vga.dts similarity index 100% rename from arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard-dvi-vga.dts rename to arch/arm/boot/dts/nxp/imx/imx25-eukrea-mbimxsd25-baseboard-dvi-vga.dts diff --git a/arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard.dts b/arch/arm/boot/dts/nxp/imx/imx25-eukrea-mbimxsd25-baseboard.dts similarity index 100% rename from arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard.dts rename to arch/arm/boot/dts/nxp/imx/imx25-eukrea-mbimxsd25-baseboard.dts diff --git a/arch/arm/boot/dts/imx25-karo-tx25.dts b/arch/arm/boot/dts/nxp/imx/imx25-karo-tx25.dts similarity index 100% rename from arch/arm/boot/dts/imx25-karo-tx25.dts rename to arch/arm/boot/dts/nxp/imx/imx25-karo-tx25.dts diff --git a/arch/arm/boot/dts/imx25-pdk.dts b/arch/arm/boot/dts/nxp/imx/imx25-pdk.dts similarity index 100% rename from arch/arm/boot/dts/imx25-pdk.dts rename to arch/arm/boot/dts/nxp/imx/imx25-pdk.dts diff --git a/arch/arm/boot/dts/imx25-pinfunc.h b/arch/arm/boot/dts/nxp/imx/imx25-pinfunc.h similarity index 100% rename from arch/arm/boot/dts/imx25-pinfunc.h rename to arch/arm/boot/dts/nxp/imx/imx25-pinfunc.h diff --git a/arch/arm/boot/dts/imx25.dtsi b/arch/arm/boot/dts/nxp/imx/imx25.dtsi similarity index 100% rename from arch/arm/boot/dts/imx25.dtsi rename to arch/arm/boot/dts/nxp/imx/imx25.dtsi diff --git a/arch/arm/boot/dts/imx27-apf27.dts b/arch/arm/boot/dts/nxp/imx/imx27-apf27.dts similarity index 100% rename from arch/arm/boot/dts/imx27-apf27.dts rename to arch/arm/boot/dts/nxp/imx/imx27-apf27.dts diff --git a/arch/arm/boot/dts/imx27-apf27dev.dts b/arch/arm/boot/dts/nxp/imx/imx27-apf27dev.dts similarity index 100% rename from arch/arm/boot/dts/imx27-apf27dev.dts rename to arch/arm/boot/dts/nxp/imx/imx27-apf27dev.dts diff --git a/arch/arm/boot/dts/imx27-eukrea-cpuimx27.dtsi b/arch/arm/boot/dts/nxp/imx/imx27-eukrea-cpuimx27.dtsi similarity index 100% rename from arch/arm/boot/dts/imx27-eukrea-cpuimx27.dtsi rename to arch/arm/boot/dts/nxp/imx/imx27-eukrea-cpuimx27.dtsi diff --git a/arch/arm/boot/dts/imx27-eukrea-mbimxsd27-baseboard.dts b/arch/arm/boot/dts/nxp/imx/imx27-eukrea-mbimxsd27-baseboard.dts similarity index 100% rename from arch/arm/boot/dts/imx27-eukrea-mbimxsd27-baseboard.dts rename to arch/arm/boot/dts/nxp/imx/imx27-eukrea-mbimxsd27-baseboard.dts diff --git a/arch/arm/boot/dts/imx27-pdk.dts b/arch/arm/boot/dts/nxp/imx/imx27-pdk.dts similarity index 100% rename from arch/arm/boot/dts/imx27-pdk.dts rename to arch/arm/boot/dts/nxp/imx/imx27-pdk.dts diff --git a/arch/arm/boot/dts/imx27-phytec-phycard-s-rdk.dts b/arch/arm/boot/dts/nxp/imx/imx27-phytec-phycard-s-rdk.dts similarity index 100% rename from arch/arm/boot/dts/imx27-phytec-phycard-s-rdk.dts rename to arch/arm/boot/dts/nxp/imx/imx27-phytec-phycard-s-rdk.dts diff --git a/arch/arm/boot/dts/imx27-phytec-phycard-s-som.dtsi b/arch/arm/boot/dts/nxp/imx/imx27-phytec-phycard-s-som.dtsi similarity index 100% rename from arch/arm/boot/dts/imx27-phytec-phycard-s-som.dtsi rename to arch/arm/boot/dts/nxp/imx/imx27-phytec-phycard-s-som.dtsi diff --git a/arch/arm/boot/dts/imx27-phytec-phycore-rdk.dts b/arch/arm/boot/dts/nxp/imx/imx27-phytec-phycore-rdk.dts similarity index 100% rename from arch/arm/boot/dts/imx27-phytec-phycore-rdk.dts rename to arch/arm/boot/dts/nxp/imx/imx27-phytec-phycore-rdk.dts diff --git a/arch/arm/boot/dts/imx27-phytec-phycore-som.dtsi b/arch/arm/boot/dts/nxp/imx/imx27-phytec-phycore-som.dtsi similarity index 100% rename from arch/arm/boot/dts/imx27-phytec-phycore-som.dtsi rename to arch/arm/boot/dts/nxp/imx/imx27-phytec-phycore-som.dtsi diff --git a/arch/arm/boot/dts/imx27-pinfunc.h b/arch/arm/boot/dts/nxp/imx/imx27-pinfunc.h similarity index 100% rename from arch/arm/boot/dts/imx27-pinfunc.h rename to arch/arm/boot/dts/nxp/imx/imx27-pinfunc.h diff --git a/arch/arm/boot/dts/imx27.dtsi b/arch/arm/boot/dts/nxp/imx/imx27.dtsi similarity index 100% rename from arch/arm/boot/dts/imx27.dtsi rename to arch/arm/boot/dts/nxp/imx/imx27.dtsi diff --git a/arch/arm/boot/dts/imx31-bug.dts b/arch/arm/boot/dts/nxp/imx/imx31-bug.dts similarity index 100% rename from arch/arm/boot/dts/imx31-bug.dts rename to arch/arm/boot/dts/nxp/imx/imx31-bug.dts diff --git a/arch/arm/boot/dts/imx31-lite.dts b/arch/arm/boot/dts/nxp/imx/imx31-lite.dts similarity index 100% rename from arch/arm/boot/dts/imx31-lite.dts rename to arch/arm/boot/dts/nxp/imx/imx31-lite.dts diff --git a/arch/arm/boot/dts/imx31.dtsi b/arch/arm/boot/dts/nxp/imx/imx31.dtsi similarity index 100% rename from arch/arm/boot/dts/imx31.dtsi rename to arch/arm/boot/dts/nxp/imx/imx31.dtsi diff --git a/arch/arm/boot/dts/imx35-eukrea-cpuimx35.dtsi b/arch/arm/boot/dts/nxp/imx/imx35-eukrea-cpuimx35.dtsi similarity index 100% rename from arch/arm/boot/dts/imx35-eukrea-cpuimx35.dtsi rename to arch/arm/boot/dts/nxp/imx/imx35-eukrea-cpuimx35.dtsi diff --git a/arch/arm/boot/dts/imx35-eukrea-mbimxsd35-baseboard.dts b/arch/arm/boot/dts/nxp/imx/imx35-eukrea-mbimxsd35-baseboard.dts similarity index 100% rename from arch/arm/boot/dts/imx35-eukrea-mbimxsd35-baseboard.dts rename to arch/arm/boot/dts/nxp/imx/imx35-eukrea-mbimxsd35-baseboard.dts diff --git a/arch/arm/boot/dts/imx35-pdk.dts b/arch/arm/boot/dts/nxp/imx/imx35-pdk.dts similarity index 100% rename from arch/arm/boot/dts/imx35-pdk.dts rename to arch/arm/boot/dts/nxp/imx/imx35-pdk.dts diff --git a/arch/arm/boot/dts/imx35-pinfunc.h b/arch/arm/boot/dts/nxp/imx/imx35-pinfunc.h similarity index 100% rename from arch/arm/boot/dts/imx35-pinfunc.h rename to arch/arm/boot/dts/nxp/imx/imx35-pinfunc.h diff --git a/arch/arm/boot/dts/imx35.dtsi b/arch/arm/boot/dts/nxp/imx/imx35.dtsi similarity index 99% rename from arch/arm/boot/dts/imx35.dtsi rename to arch/arm/boot/dts/nxp/imx/imx35.dtsi index d650f54c3fc6bd2f886848638a120807c764d5a4..2d20e5541acc8388e3ab41307166f068200c34a3 100644 --- a/arch/arm/boot/dts/imx35.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx35.dtsi @@ -298,7 +298,6 @@ compatible = "fsl,imx35-wdt", "fsl,imx21-wdt"; reg = <0x53fdc000 0x4000>; clocks = <&clks 74>; - clock-names = ""; interrupts = <55>; }; diff --git a/arch/arm/boot/dts/imx50-evk.dts b/arch/arm/boot/dts/nxp/imx/imx50-evk.dts similarity index 100% rename from arch/arm/boot/dts/imx50-evk.dts rename to arch/arm/boot/dts/nxp/imx/imx50-evk.dts diff --git a/arch/arm/boot/dts/imx50-kobo-aura.dts b/arch/arm/boot/dts/nxp/imx/imx50-kobo-aura.dts similarity index 100% rename from arch/arm/boot/dts/imx50-kobo-aura.dts rename to arch/arm/boot/dts/nxp/imx/imx50-kobo-aura.dts diff --git a/arch/arm/boot/dts/imx50-pinfunc.h b/arch/arm/boot/dts/nxp/imx/imx50-pinfunc.h similarity index 100% rename from arch/arm/boot/dts/imx50-pinfunc.h rename to arch/arm/boot/dts/nxp/imx/imx50-pinfunc.h diff --git a/arch/arm/boot/dts/imx50.dtsi b/arch/arm/boot/dts/nxp/imx/imx50.dtsi similarity index 100% rename from arch/arm/boot/dts/imx50.dtsi rename to arch/arm/boot/dts/nxp/imx/imx50.dtsi diff --git a/arch/arm/boot/dts/imx51-apf51.dts b/arch/arm/boot/dts/nxp/imx/imx51-apf51.dts similarity index 100% rename from arch/arm/boot/dts/imx51-apf51.dts rename to arch/arm/boot/dts/nxp/imx/imx51-apf51.dts diff --git a/arch/arm/boot/dts/imx51-apf51dev.dts b/arch/arm/boot/dts/nxp/imx/imx51-apf51dev.dts similarity index 100% rename from arch/arm/boot/dts/imx51-apf51dev.dts rename to arch/arm/boot/dts/nxp/imx/imx51-apf51dev.dts diff --git a/arch/arm/boot/dts/imx51-babbage.dts b/arch/arm/boot/dts/nxp/imx/imx51-babbage.dts similarity index 100% rename from arch/arm/boot/dts/imx51-babbage.dts rename to arch/arm/boot/dts/nxp/imx/imx51-babbage.dts diff --git a/arch/arm/boot/dts/imx51-digi-connectcore-jsk.dts b/arch/arm/boot/dts/nxp/imx/imx51-digi-connectcore-jsk.dts similarity index 100% rename from arch/arm/boot/dts/imx51-digi-connectcore-jsk.dts rename to arch/arm/boot/dts/nxp/imx/imx51-digi-connectcore-jsk.dts diff --git a/arch/arm/boot/dts/imx51-digi-connectcore-som.dtsi b/arch/arm/boot/dts/nxp/imx/imx51-digi-connectcore-som.dtsi similarity index 100% rename from arch/arm/boot/dts/imx51-digi-connectcore-som.dtsi rename to arch/arm/boot/dts/nxp/imx/imx51-digi-connectcore-som.dtsi diff --git a/arch/arm/boot/dts/imx51-eukrea-cpuimx51.dtsi b/arch/arm/boot/dts/nxp/imx/imx51-eukrea-cpuimx51.dtsi similarity index 100% rename from arch/arm/boot/dts/imx51-eukrea-cpuimx51.dtsi rename to arch/arm/boot/dts/nxp/imx/imx51-eukrea-cpuimx51.dtsi diff --git a/arch/arm/boot/dts/imx51-eukrea-mbimxsd51-baseboard.dts b/arch/arm/boot/dts/nxp/imx/imx51-eukrea-mbimxsd51-baseboard.dts similarity index 100% rename from arch/arm/boot/dts/imx51-eukrea-mbimxsd51-baseboard.dts rename to arch/arm/boot/dts/nxp/imx/imx51-eukrea-mbimxsd51-baseboard.dts diff --git a/arch/arm/boot/dts/imx51-pinfunc.h b/arch/arm/boot/dts/nxp/imx/imx51-pinfunc.h similarity index 100% rename from arch/arm/boot/dts/imx51-pinfunc.h rename to arch/arm/boot/dts/nxp/imx/imx51-pinfunc.h diff --git a/arch/arm/boot/dts/imx51-ts4800.dts b/arch/arm/boot/dts/nxp/imx/imx51-ts4800.dts similarity index 100% rename from arch/arm/boot/dts/imx51-ts4800.dts rename to arch/arm/boot/dts/nxp/imx/imx51-ts4800.dts diff --git a/arch/arm/boot/dts/imx51-zii-rdu1.dts b/arch/arm/boot/dts/nxp/imx/imx51-zii-rdu1.dts similarity index 99% rename from arch/arm/boot/dts/imx51-zii-rdu1.dts rename to arch/arm/boot/dts/nxp/imx/imx51-zii-rdu1.dts index e537e06e11d7e6ae198d599a30c41341c4ab9f0c..5d4b29d765853ed27d581bde482596da5e7d84a0 100644 --- a/arch/arm/boot/dts/imx51-zii-rdu1.dts +++ b/arch/arm/boot/dts/nxp/imx/imx51-zii-rdu1.dts @@ -145,9 +145,9 @@ pinctrl-0 = <&pinctrl_gpiospi0>; status = "okay"; - gpio-sck = <&gpio4 15 GPIO_ACTIVE_HIGH>; - gpio-mosi = <&gpio4 12 GPIO_ACTIVE_HIGH>; - gpio-miso = <&gpio4 11 GPIO_ACTIVE_HIGH>; + sck-gpios = <&gpio4 15 GPIO_ACTIVE_HIGH>; + mosi-gpios = <&gpio4 12 GPIO_ACTIVE_HIGH>; + miso-gpios = <&gpio4 11 GPIO_ACTIVE_HIGH>; num-chipselects = <1>; cs-gpios = <&gpio4 14 GPIO_ACTIVE_HIGH>; @@ -181,7 +181,7 @@ port@0 { reg = <0>; - label = "cpu"; + phy-mode = "rev-mii"; ethernet = <&fec>; fixed-link { diff --git a/arch/arm/boot/dts/imx51-zii-scu2-mezz.dts b/arch/arm/boot/dts/nxp/imx/imx51-zii-scu2-mezz.dts similarity index 99% rename from arch/arm/boot/dts/imx51-zii-scu2-mezz.dts rename to arch/arm/boot/dts/nxp/imx/imx51-zii-scu2-mezz.dts index 21dd3f7abd488bd0d52b61e976afc659c878583d..625f9ac671ae9713110fcd2cf62884c8fd79f236 100644 --- a/arch/arm/boot/dts/imx51-zii-scu2-mezz.dts +++ b/arch/arm/boot/dts/nxp/imx/imx51-zii-scu2-mezz.dts @@ -82,7 +82,7 @@ port@4 { reg = <4>; - label = "cpu"; + phy-mode = "rev-mii"; ethernet = <&fec>; fixed-link { diff --git a/arch/arm/boot/dts/imx51-zii-scu3-esb.dts b/arch/arm/boot/dts/nxp/imx/imx51-zii-scu3-esb.dts similarity index 99% rename from arch/arm/boot/dts/imx51-zii-scu3-esb.dts rename to arch/arm/boot/dts/nxp/imx/imx51-zii-scu3-esb.dts index 9f857eb44bf722acef5be1c3e536213f0d8ea206..19a3b142c964919d92ed23657ca749aa95e4d006 100644 --- a/arch/arm/boot/dts/imx51-zii-scu3-esb.dts +++ b/arch/arm/boot/dts/nxp/imx/imx51-zii-scu3-esb.dts @@ -267,7 +267,6 @@ port@6 { reg = <6>; - label = "cpu"; phy-mode = "mii"; ethernet = <&fec>; diff --git a/arch/arm/boot/dts/imx51.dtsi b/arch/arm/boot/dts/nxp/imx/imx51.dtsi similarity index 100% rename from arch/arm/boot/dts/imx51.dtsi rename to arch/arm/boot/dts/nxp/imx/imx51.dtsi diff --git a/arch/arm/boot/dts/imx53-ard.dts b/arch/arm/boot/dts/nxp/imx/imx53-ard.dts similarity index 100% rename from arch/arm/boot/dts/imx53-ard.dts rename to arch/arm/boot/dts/nxp/imx/imx53-ard.dts diff --git a/arch/arm/boot/dts/imx53-cx9020.dts b/arch/arm/boot/dts/nxp/imx/imx53-cx9020.dts similarity index 100% rename from arch/arm/boot/dts/imx53-cx9020.dts rename to arch/arm/boot/dts/nxp/imx/imx53-cx9020.dts diff --git a/arch/arm/boot/dts/imx53-kp-ddc.dts b/arch/arm/boot/dts/nxp/imx/imx53-kp-ddc.dts similarity index 100% rename from arch/arm/boot/dts/imx53-kp-ddc.dts rename to arch/arm/boot/dts/nxp/imx/imx53-kp-ddc.dts diff --git a/arch/arm/boot/dts/imx53-kp-hsc.dts b/arch/arm/boot/dts/nxp/imx/imx53-kp-hsc.dts similarity index 100% rename from arch/arm/boot/dts/imx53-kp-hsc.dts rename to arch/arm/boot/dts/nxp/imx/imx53-kp-hsc.dts diff --git a/arch/arm/boot/dts/imx53-kp.dtsi b/arch/arm/boot/dts/nxp/imx/imx53-kp.dtsi similarity index 100% rename from arch/arm/boot/dts/imx53-kp.dtsi rename to arch/arm/boot/dts/nxp/imx/imx53-kp.dtsi diff --git a/arch/arm/boot/dts/imx53-m53.dtsi b/arch/arm/boot/dts/nxp/imx/imx53-m53.dtsi similarity index 100% rename from arch/arm/boot/dts/imx53-m53.dtsi rename to arch/arm/boot/dts/nxp/imx/imx53-m53.dtsi diff --git a/arch/arm/boot/dts/imx53-m53evk.dts b/arch/arm/boot/dts/nxp/imx/imx53-m53evk.dts similarity index 100% rename from arch/arm/boot/dts/imx53-m53evk.dts rename to arch/arm/boot/dts/nxp/imx/imx53-m53evk.dts diff --git a/arch/arm/boot/dts/imx53-m53menlo.dts b/arch/arm/boot/dts/nxp/imx/imx53-m53menlo.dts similarity index 100% rename from arch/arm/boot/dts/imx53-m53menlo.dts rename to arch/arm/boot/dts/nxp/imx/imx53-m53menlo.dts diff --git a/arch/arm/boot/dts/imx53-mba53.dts b/arch/arm/boot/dts/nxp/imx/imx53-mba53.dts similarity index 100% rename from arch/arm/boot/dts/imx53-mba53.dts rename to arch/arm/boot/dts/nxp/imx/imx53-mba53.dts diff --git a/arch/arm/boot/dts/imx53-pinfunc.h b/arch/arm/boot/dts/nxp/imx/imx53-pinfunc.h similarity index 100% rename from arch/arm/boot/dts/imx53-pinfunc.h rename to arch/arm/boot/dts/nxp/imx/imx53-pinfunc.h diff --git a/arch/arm/boot/dts/imx53-ppd.dts b/arch/arm/boot/dts/nxp/imx/imx53-ppd.dts similarity index 100% rename from arch/arm/boot/dts/imx53-ppd.dts rename to arch/arm/boot/dts/nxp/imx/imx53-ppd.dts diff --git a/arch/arm/boot/dts/imx53-qsb-common.dtsi b/arch/arm/boot/dts/nxp/imx/imx53-qsb-common.dtsi similarity index 100% rename from arch/arm/boot/dts/imx53-qsb-common.dtsi rename to arch/arm/boot/dts/nxp/imx/imx53-qsb-common.dtsi diff --git a/arch/arm/boot/dts/imx53-qsb.dts b/arch/arm/boot/dts/nxp/imx/imx53-qsb.dts similarity index 100% rename from arch/arm/boot/dts/imx53-qsb.dts rename to arch/arm/boot/dts/nxp/imx/imx53-qsb.dts diff --git a/arch/arm/boot/dts/imx53-qsrb.dts b/arch/arm/boot/dts/nxp/imx/imx53-qsrb.dts similarity index 100% rename from arch/arm/boot/dts/imx53-qsrb.dts rename to arch/arm/boot/dts/nxp/imx/imx53-qsrb.dts diff --git a/arch/arm/boot/dts/imx53-sk-imx53.dts b/arch/arm/boot/dts/nxp/imx/imx53-sk-imx53.dts similarity index 100% rename from arch/arm/boot/dts/imx53-sk-imx53.dts rename to arch/arm/boot/dts/nxp/imx/imx53-sk-imx53.dts diff --git a/arch/arm/boot/dts/imx53-smd.dts b/arch/arm/boot/dts/nxp/imx/imx53-smd.dts similarity index 100% rename from arch/arm/boot/dts/imx53-smd.dts rename to arch/arm/boot/dts/nxp/imx/imx53-smd.dts diff --git a/arch/arm/boot/dts/imx53-tqma53.dtsi b/arch/arm/boot/dts/nxp/imx/imx53-tqma53.dtsi similarity index 99% rename from arch/arm/boot/dts/imx53-tqma53.dtsi rename to arch/arm/boot/dts/nxp/imx/imx53-tqma53.dtsi index 7e7f9f3b3906e2ae3164cd30b6735f662288e530..d930739674a19f496eab50ab6f301c39dc892063 100644 --- a/arch/arm/boot/dts/imx53-tqma53.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx53-tqma53.dtsi @@ -274,7 +274,7 @@ reg = <0x48>; }; - eeprom: 24c64@50 { + eeprom: eeprom@50 { compatible = "atmel,24c64"; pagesize = <32>; reg = <0x50>; diff --git a/arch/arm/boot/dts/imx53-tx53-x03x.dts b/arch/arm/boot/dts/nxp/imx/imx53-tx53-x03x.dts similarity index 100% rename from arch/arm/boot/dts/imx53-tx53-x03x.dts rename to arch/arm/boot/dts/nxp/imx/imx53-tx53-x03x.dts diff --git a/arch/arm/boot/dts/imx53-tx53-x13x.dts b/arch/arm/boot/dts/nxp/imx/imx53-tx53-x13x.dts similarity index 100% rename from arch/arm/boot/dts/imx53-tx53-x13x.dts rename to arch/arm/boot/dts/nxp/imx/imx53-tx53-x13x.dts diff --git a/arch/arm/boot/dts/imx53-tx53.dtsi b/arch/arm/boot/dts/nxp/imx/imx53-tx53.dtsi similarity index 100% rename from arch/arm/boot/dts/imx53-tx53.dtsi rename to arch/arm/boot/dts/nxp/imx/imx53-tx53.dtsi diff --git a/arch/arm/boot/dts/imx53-usbarmory.dts b/arch/arm/boot/dts/nxp/imx/imx53-usbarmory.dts similarity index 100% rename from arch/arm/boot/dts/imx53-usbarmory.dts rename to arch/arm/boot/dts/nxp/imx/imx53-usbarmory.dts diff --git a/arch/arm/boot/dts/imx53-voipac-bsb.dts b/arch/arm/boot/dts/nxp/imx/imx53-voipac-bsb.dts similarity index 100% rename from arch/arm/boot/dts/imx53-voipac-bsb.dts rename to arch/arm/boot/dts/nxp/imx/imx53-voipac-bsb.dts diff --git a/arch/arm/boot/dts/imx53-voipac-dmm-668.dtsi b/arch/arm/boot/dts/nxp/imx/imx53-voipac-dmm-668.dtsi similarity index 100% rename from arch/arm/boot/dts/imx53-voipac-dmm-668.dtsi rename to arch/arm/boot/dts/nxp/imx/imx53-voipac-dmm-668.dtsi diff --git a/arch/arm/boot/dts/imx53.dtsi b/arch/arm/boot/dts/nxp/imx/imx53.dtsi similarity index 100% rename from arch/arm/boot/dts/imx53.dtsi rename to arch/arm/boot/dts/nxp/imx/imx53.dtsi diff --git a/arch/arm/boot/dts/imx6-logicpd-baseboard.dtsi b/arch/arm/boot/dts/nxp/imx/imx6-logicpd-baseboard.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6-logicpd-baseboard.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6-logicpd-baseboard.dtsi diff --git a/arch/arm/boot/dts/imx6-logicpd-som.dtsi b/arch/arm/boot/dts/nxp/imx/imx6-logicpd-som.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6-logicpd-som.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6-logicpd-som.dtsi diff --git a/arch/arm/boot/dts/imx6dl-alti6p.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-alti6p.dts similarity index 98% rename from arch/arm/boot/dts/imx6dl-alti6p.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-alti6p.dts index e6a4e27706400b2f8a6ec76e3414053d86873871..4989e8d069a1c593539ce431685ff76f5bdc962e 100644 --- a/arch/arm/boot/dts/imx6dl-alti6p.dts +++ b/arch/arm/boot/dts/nxp/imx/imx6dl-alti6p.dts @@ -361,6 +361,7 @@ pinctrl-0 = <&pinctrl_usbh1>; phy_type = "utmi"; dr_mode = "host"; + over-current-active-low; status = "okay"; }; @@ -370,9 +371,18 @@ pinctrl-0 = <&pinctrl_usbotg>; phy_type = "utmi"; dr_mode = "host"; + over-current-active-low; status = "okay"; }; +&usbphynop1 { + status = "disabled"; +}; + +&usbphynop2 { + status = "disabled"; +}; + &usdhc1 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_usdhc1>; diff --git a/arch/arm/boot/dts/imx6dl-apf6dev.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-apf6dev.dts similarity index 100% rename from arch/arm/boot/dts/imx6dl-apf6dev.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-apf6dev.dts diff --git a/arch/arm/boot/dts/imx6dl-aristainetos2_4.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-aristainetos2_4.dts similarity index 100% rename from arch/arm/boot/dts/imx6dl-aristainetos2_4.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-aristainetos2_4.dts diff --git a/arch/arm/boot/dts/imx6dl-aristainetos2_7.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-aristainetos2_7.dts similarity index 100% rename from arch/arm/boot/dts/imx6dl-aristainetos2_7.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-aristainetos2_7.dts diff --git a/arch/arm/boot/dts/imx6dl-aristainetos_4.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-aristainetos_4.dts similarity index 100% rename from arch/arm/boot/dts/imx6dl-aristainetos_4.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-aristainetos_4.dts diff --git a/arch/arm/boot/dts/imx6dl-aristainetos_7.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-aristainetos_7.dts similarity index 100% rename from arch/arm/boot/dts/imx6dl-aristainetos_7.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-aristainetos_7.dts diff --git a/arch/arm/boot/dts/imx6dl-b105pv2.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-b105pv2.dts similarity index 100% rename from arch/arm/boot/dts/imx6dl-b105pv2.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-b105pv2.dts diff --git a/arch/arm/boot/dts/imx6dl-b105v2.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-b105v2.dts similarity index 100% rename from arch/arm/boot/dts/imx6dl-b105v2.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-b105v2.dts diff --git a/arch/arm/boot/dts/imx6dl-b125pv2.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-b125pv2.dts similarity index 100% rename from arch/arm/boot/dts/imx6dl-b125pv2.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-b125pv2.dts diff --git a/arch/arm/boot/dts/imx6dl-b125v2.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-b125v2.dts similarity index 100% rename from arch/arm/boot/dts/imx6dl-b125v2.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-b125v2.dts diff --git a/arch/arm/boot/dts/imx6dl-b155v2.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-b155v2.dts similarity index 100% rename from arch/arm/boot/dts/imx6dl-b155v2.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-b155v2.dts diff --git a/arch/arm/boot/dts/imx6dl-b1x5pv2.dtsi b/arch/arm/boot/dts/nxp/imx/imx6dl-b1x5pv2.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6dl-b1x5pv2.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6dl-b1x5pv2.dtsi diff --git a/arch/arm/boot/dts/imx6dl-b1x5v2.dtsi b/arch/arm/boot/dts/nxp/imx/imx6dl-b1x5v2.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6dl-b1x5v2.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6dl-b1x5v2.dtsi diff --git a/arch/arm/boot/dts/imx6dl-colibri-aster.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-colibri-aster.dts similarity index 100% rename from arch/arm/boot/dts/imx6dl-colibri-aster.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-colibri-aster.dts diff --git a/arch/arm/boot/dts/imx6dl-colibri-eval-v3.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-colibri-eval-v3.dts similarity index 100% rename from arch/arm/boot/dts/imx6dl-colibri-eval-v3.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-colibri-eval-v3.dts diff --git a/arch/arm/boot/dts/imx6dl-colibri-iris-v2.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-colibri-iris-v2.dts similarity index 100% rename from arch/arm/boot/dts/imx6dl-colibri-iris-v2.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-colibri-iris-v2.dts diff --git a/arch/arm/boot/dts/imx6dl-colibri-iris.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-colibri-iris.dts similarity index 100% rename from arch/arm/boot/dts/imx6dl-colibri-iris.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-colibri-iris.dts diff --git a/arch/arm/boot/dts/imx6dl-cubox-i-emmc-som-v15.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-cubox-i-emmc-som-v15.dts similarity index 100% rename from arch/arm/boot/dts/imx6dl-cubox-i-emmc-som-v15.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-cubox-i-emmc-som-v15.dts diff --git a/arch/arm/boot/dts/imx6dl-cubox-i-som-v15.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-cubox-i-som-v15.dts similarity index 100% rename from arch/arm/boot/dts/imx6dl-cubox-i-som-v15.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-cubox-i-som-v15.dts diff --git a/arch/arm/boot/dts/imx6dl-cubox-i.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-cubox-i.dts similarity index 100% rename from arch/arm/boot/dts/imx6dl-cubox-i.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-cubox-i.dts diff --git a/arch/arm/boot/dts/imx6dl-dfi-fs700-m60.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-dfi-fs700-m60.dts similarity index 100% rename from arch/arm/boot/dts/imx6dl-dfi-fs700-m60.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-dfi-fs700-m60.dts diff --git a/arch/arm/boot/dts/imx6dl-dhcom-picoitx.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-dhcom-picoitx.dts similarity index 100% rename from arch/arm/boot/dts/imx6dl-dhcom-picoitx.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-dhcom-picoitx.dts diff --git a/arch/arm/boot/dts/imx6dl-eckelmann-ci4x10.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-eckelmann-ci4x10.dts similarity index 100% rename from arch/arm/boot/dts/imx6dl-eckelmann-ci4x10.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-eckelmann-ci4x10.dts diff --git a/arch/arm/boot/dts/imx6dl-emcon-avari.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-emcon-avari.dts similarity index 100% rename from arch/arm/boot/dts/imx6dl-emcon-avari.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-emcon-avari.dts diff --git a/arch/arm/boot/dts/imx6dl-gw51xx.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-gw51xx.dts similarity index 100% rename from arch/arm/boot/dts/imx6dl-gw51xx.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-gw51xx.dts diff --git a/arch/arm/boot/dts/imx6dl-gw52xx.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-gw52xx.dts similarity index 100% rename from arch/arm/boot/dts/imx6dl-gw52xx.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-gw52xx.dts diff --git a/arch/arm/boot/dts/imx6dl-gw53xx.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-gw53xx.dts similarity index 100% rename from arch/arm/boot/dts/imx6dl-gw53xx.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-gw53xx.dts diff --git a/arch/arm/boot/dts/imx6dl-gw54xx.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-gw54xx.dts similarity index 100% rename from arch/arm/boot/dts/imx6dl-gw54xx.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-gw54xx.dts diff --git a/arch/arm/boot/dts/imx6dl-gw551x.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-gw551x.dts similarity index 100% rename from arch/arm/boot/dts/imx6dl-gw551x.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-gw551x.dts diff --git a/arch/arm/boot/dts/imx6dl-gw552x.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-gw552x.dts similarity index 100% rename from arch/arm/boot/dts/imx6dl-gw552x.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-gw552x.dts diff --git a/arch/arm/boot/dts/imx6dl-gw553x.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-gw553x.dts similarity index 100% rename from arch/arm/boot/dts/imx6dl-gw553x.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-gw553x.dts diff --git a/arch/arm/boot/dts/imx6dl-gw560x.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-gw560x.dts similarity index 100% rename from arch/arm/boot/dts/imx6dl-gw560x.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-gw560x.dts diff --git a/arch/arm/boot/dts/imx6dl-gw5903.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-gw5903.dts similarity index 100% rename from arch/arm/boot/dts/imx6dl-gw5903.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-gw5903.dts diff --git a/arch/arm/boot/dts/imx6dl-gw5904.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-gw5904.dts similarity index 100% rename from arch/arm/boot/dts/imx6dl-gw5904.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-gw5904.dts diff --git a/arch/arm/boot/dts/imx6dl-gw5907.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-gw5907.dts similarity index 100% rename from arch/arm/boot/dts/imx6dl-gw5907.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-gw5907.dts diff --git a/arch/arm/boot/dts/imx6dl-gw5910.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-gw5910.dts similarity index 100% rename from arch/arm/boot/dts/imx6dl-gw5910.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-gw5910.dts diff --git a/arch/arm/boot/dts/imx6dl-gw5912.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-gw5912.dts similarity index 100% rename from arch/arm/boot/dts/imx6dl-gw5912.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-gw5912.dts diff --git a/arch/arm/boot/dts/imx6dl-gw5913.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-gw5913.dts similarity index 100% rename from arch/arm/boot/dts/imx6dl-gw5913.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-gw5913.dts diff --git a/arch/arm/boot/dts/imx6dl-hummingboard-emmc-som-v15.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-hummingboard-emmc-som-v15.dts similarity index 100% rename from arch/arm/boot/dts/imx6dl-hummingboard-emmc-som-v15.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-hummingboard-emmc-som-v15.dts diff --git a/arch/arm/boot/dts/imx6dl-hummingboard-som-v15.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-hummingboard-som-v15.dts similarity index 100% rename from arch/arm/boot/dts/imx6dl-hummingboard-som-v15.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-hummingboard-som-v15.dts diff --git a/arch/arm/boot/dts/imx6dl-hummingboard.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-hummingboard.dts similarity index 100% rename from arch/arm/boot/dts/imx6dl-hummingboard.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-hummingboard.dts diff --git a/arch/arm/boot/dts/imx6dl-hummingboard2-emmc-som-v15.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-hummingboard2-emmc-som-v15.dts similarity index 100% rename from arch/arm/boot/dts/imx6dl-hummingboard2-emmc-som-v15.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-hummingboard2-emmc-som-v15.dts diff --git a/arch/arm/boot/dts/imx6dl-hummingboard2-som-v15.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-hummingboard2-som-v15.dts similarity index 100% rename from arch/arm/boot/dts/imx6dl-hummingboard2-som-v15.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-hummingboard2-som-v15.dts diff --git a/arch/arm/boot/dts/imx6dl-hummingboard2.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-hummingboard2.dts similarity index 100% rename from arch/arm/boot/dts/imx6dl-hummingboard2.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-hummingboard2.dts diff --git a/arch/arm/boot/dts/imx6dl-icore-mipi.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-icore-mipi.dts similarity index 100% rename from arch/arm/boot/dts/imx6dl-icore-mipi.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-icore-mipi.dts diff --git a/arch/arm/boot/dts/imx6dl-icore-rqs.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-icore-rqs.dts similarity index 100% rename from arch/arm/boot/dts/imx6dl-icore-rqs.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-icore-rqs.dts diff --git a/arch/arm/boot/dts/imx6dl-icore.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-icore.dts similarity index 100% rename from arch/arm/boot/dts/imx6dl-icore.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-icore.dts diff --git a/arch/arm/boot/dts/imx6dl-kontron-samx6i.dtsi b/arch/arm/boot/dts/nxp/imx/imx6dl-kontron-samx6i.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6dl-kontron-samx6i.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6dl-kontron-samx6i.dtsi diff --git a/arch/arm/boot/dts/imx6dl-lanmcu.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-lanmcu.dts similarity index 99% rename from arch/arm/boot/dts/imx6dl-lanmcu.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-lanmcu.dts index fa823988312d63d2c640b96df2e927609c1e89ec..7c62db91173b78659372b3095a2676fec4eaea0f 100644 --- a/arch/arm/boot/dts/imx6dl-lanmcu.dts +++ b/arch/arm/boot/dts/nxp/imx/imx6dl-lanmcu.dts @@ -257,9 +257,18 @@ pinctrl-0 = <&pinctrl_usbotg>; phy_type = "utmi"; dr_mode = "host"; + over-current-active-low; status = "okay"; }; +&usbphynop1 { + status = "disabled"; +}; + +&usbphynop2 { + status = "disabled"; +}; + &usdhc1 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_usdhc1>; diff --git a/arch/arm/boot/dts/imx6dl-mamoj.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-mamoj.dts similarity index 100% rename from arch/arm/boot/dts/imx6dl-mamoj.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-mamoj.dts diff --git a/arch/arm/boot/dts/imx6dl-mba6.dtsi b/arch/arm/boot/dts/nxp/imx/imx6dl-mba6.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6dl-mba6.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6dl-mba6.dtsi diff --git a/arch/arm/boot/dts/imx6dl-mba6a.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-mba6a.dts similarity index 100% rename from arch/arm/boot/dts/imx6dl-mba6a.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-mba6a.dts diff --git a/arch/arm/boot/dts/imx6dl-mba6b.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-mba6b.dts similarity index 100% rename from arch/arm/boot/dts/imx6dl-mba6b.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-mba6b.dts diff --git a/arch/arm/boot/dts/imx6dl-nit6xlite.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-nit6xlite.dts similarity index 100% rename from arch/arm/boot/dts/imx6dl-nit6xlite.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-nit6xlite.dts diff --git a/arch/arm/boot/dts/imx6dl-nitrogen6x.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-nitrogen6x.dts similarity index 100% rename from arch/arm/boot/dts/imx6dl-nitrogen6x.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-nitrogen6x.dts diff --git a/arch/arm/boot/dts/imx6dl-phytec-mira-rdk-nand.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-phytec-mira-rdk-nand.dts similarity index 100% rename from arch/arm/boot/dts/imx6dl-phytec-mira-rdk-nand.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-phytec-mira-rdk-nand.dts diff --git a/arch/arm/boot/dts/imx6dl-phytec-pbab01.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-phytec-pbab01.dts similarity index 100% rename from arch/arm/boot/dts/imx6dl-phytec-pbab01.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-phytec-pbab01.dts diff --git a/arch/arm/boot/dts/imx6dl-phytec-pfla02.dtsi b/arch/arm/boot/dts/nxp/imx/imx6dl-phytec-pfla02.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6dl-phytec-pfla02.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6dl-phytec-pfla02.dtsi diff --git a/arch/arm/boot/dts/imx6dl-pico-dwarf.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-pico-dwarf.dts similarity index 100% rename from arch/arm/boot/dts/imx6dl-pico-dwarf.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-pico-dwarf.dts diff --git a/arch/arm/boot/dts/imx6dl-pico-hobbit.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-pico-hobbit.dts similarity index 100% rename from arch/arm/boot/dts/imx6dl-pico-hobbit.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-pico-hobbit.dts diff --git a/arch/arm/boot/dts/imx6dl-pico-nymph.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-pico-nymph.dts similarity index 100% rename from arch/arm/boot/dts/imx6dl-pico-nymph.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-pico-nymph.dts diff --git a/arch/arm/boot/dts/imx6dl-pico-pi.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-pico-pi.dts similarity index 100% rename from arch/arm/boot/dts/imx6dl-pico-pi.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-pico-pi.dts diff --git a/arch/arm/boot/dts/imx6dl-pinfunc.h b/arch/arm/boot/dts/nxp/imx/imx6dl-pinfunc.h similarity index 100% rename from arch/arm/boot/dts/imx6dl-pinfunc.h rename to arch/arm/boot/dts/nxp/imx/imx6dl-pinfunc.h diff --git a/arch/arm/boot/dts/imx6dl-plybas.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-plybas.dts similarity index 99% rename from arch/arm/boot/dts/imx6dl-plybas.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-plybas.dts index e98046eea7a418a0d94d3b3195ee5e6d45f82b2d..84f34da06267ebd477fbe71b465a44ffe5b4c098 100644 --- a/arch/arm/boot/dts/imx6dl-plybas.dts +++ b/arch/arm/boot/dts/nxp/imx/imx6dl-plybas.dts @@ -235,7 +235,7 @@ pinctrl-0 = <&pinctrl_usbotg>; phy_type = "utmi"; dr_mode = "host"; - disable-over-current; + over-current-active-low; status = "okay"; }; diff --git a/arch/arm/boot/dts/imx6dl-plym2m.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-plym2m.dts similarity index 96% rename from arch/arm/boot/dts/imx6dl-plym2m.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-plym2m.dts index e3c10483f33bdc96c80d2de1255b7a7e749cb260..dfa8110b1d97b14eae30159acc6daf74ae482eb7 100644 --- a/arch/arm/boot/dts/imx6dl-plym2m.dts +++ b/arch/arm/boot/dts/nxp/imx/imx6dl-plym2m.dts @@ -113,18 +113,42 @@ polling-delay = <20000>; polling-delay-passive = <0>; thermal-sensors = <&tsens0>; + + trips { + alert { + temperature = <85000>; /* millicelsius */ + hysteresis = <2000>; /* millicelsius */ + type = "passive"; + }; + }; }; touch-thermal0 { polling-delay = <20000>; polling-delay-passive = <0>; thermal-sensors = <&touch_temp0>; + + trips { + alert { + temperature = <85000>; /* millicelsius */ + hysteresis = <2000>; /* millicelsius */ + type = "passive"; + }; + }; }; touch-thermal1 { polling-delay = <20000>; polling-delay-passive = <0>; thermal-sensors = <&touch_temp1>; + + trips { + alert { + temperature = <85000>; /* millicelsius */ + hysteresis = <2000>; /* millicelsius */ + type = "passive"; + }; + }; }; }; diff --git a/arch/arm/boot/dts/imx6dl-prtmvt.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-prtmvt.dts similarity index 99% rename from arch/arm/boot/dts/imx6dl-prtmvt.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-prtmvt.dts index 5f4fa796ca18fee8a9db0a44e816f6d338846a04..773a84a5739df13c4a82431094256f25f1a0e171 100644 --- a/arch/arm/boot/dts/imx6dl-prtmvt.dts +++ b/arch/arm/boot/dts/nxp/imx/imx6dl-prtmvt.dts @@ -560,6 +560,7 @@ pinctrl-names = "default"; phy_type = "utmi"; dr_mode = "host"; + disable-over-current; status = "okay"; }; @@ -569,10 +570,18 @@ pinctrl-0 = <&pinctrl_usbotg>; phy_type = "utmi"; dr_mode = "host"; - disable-over-current; + over-current-active-low; status = "okay"; }; +&usbphynop1 { + status = "disabled"; +}; + +&usbphynop2 { + status = "disabled"; +}; + &usdhc1 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_usdhc1>; diff --git a/arch/arm/boot/dts/imx6dl-prtrvt.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-prtrvt.dts similarity index 98% rename from arch/arm/boot/dts/imx6dl-prtrvt.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-prtrvt.dts index 56bb1ca56a2df8e72971e1430802cef2bf88e039..36b031236e4756b4a676d5575e3f820a6e172797 100644 --- a/arch/arm/boot/dts/imx6dl-prtrvt.dts +++ b/arch/arm/boot/dts/nxp/imx/imx6dl-prtrvt.dts @@ -124,6 +124,10 @@ status = "disabled"; }; +&usbotg { + disable-over-current; +}; + &vpu { status = "disabled"; }; diff --git a/arch/arm/boot/dts/imx6dl-prtvt7.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-prtvt7.dts similarity index 96% rename from arch/arm/boot/dts/imx6dl-prtvt7.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-prtvt7.dts index a1eb53851794ac5269543fdbcf9a8c0dd23d95a3..568e98cb62aaf50db483edfac731b2d36b99397e 100644 --- a/arch/arm/boot/dts/imx6dl-prtvt7.dts +++ b/arch/arm/boot/dts/nxp/imx/imx6dl-prtvt7.dts @@ -24,7 +24,7 @@ compatible = "pwm-backlight"; pwms = <&pwm1 0 500000 0>; brightness-levels = <0 20 81 248 1000>; - default-brightness-level = <20>; + default-brightness-level = <65>; num-interpolated-steps = <21>; power-supply = <®_bl_12v0>; }; @@ -246,18 +246,42 @@ polling-delay = <20000>; polling-delay-passive = <0>; thermal-sensors = <&tsens0>; + + trips { + alert { + temperature = <105000>; /* millicelsius */ + hysteresis = <2000>; /* millicelsius */ + type = "passive"; + }; + }; }; touch-thermal0 { polling-delay = <20000>; polling-delay-passive = <0>; thermal-sensors = <&touch_temp0>; + + trips { + alert { + temperature = <105000>; /* millicelsius */ + hysteresis = <2000>; /* millicelsius */ + type = "passive"; + }; + }; }; touch-thermal1 { polling-delay = <20000>; polling-delay-passive = <0>; thermal-sensors = <&touch_temp1>; + + trips { + alert { + temperature = <105000>; /* millicelsius */ + hysteresis = <2000>; /* millicelsius */ + type = "passive"; + }; + }; }; }; @@ -267,8 +291,6 @@ <&adc_ts 5>; io-channel-names = "y", "z1", "z2", "x"; touchscreen-min-pressure = <64687>; - touchscreen-inverted-x; - touchscreen-inverted-y; touchscreen-x-plate-ohms = <300>; touchscreen-y-plate-ohms = <800>; }; diff --git a/arch/arm/boot/dts/imx6dl-qmx6.dtsi b/arch/arm/boot/dts/nxp/imx/imx6dl-qmx6.dtsi similarity index 99% rename from arch/arm/boot/dts/imx6dl-qmx6.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6dl-qmx6.dtsi index 150d69858255d32e19203604b893d61bfea78ebd..05fd8ff4da1ee98456689ef08f0e8b2f8225541c 100644 --- a/arch/arm/boot/dts/imx6dl-qmx6.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx6dl-qmx6.dtsi @@ -48,7 +48,7 @@ pinctrl-names = "default"; pinctrl-0 = <&pinctrl_audmux>; - audmux_ssi1 { + mux-ssi1 { fsl,audmux-port = ; fsl,port-config = < (IMX_AUDMUX_V2_PTCR_TFSDIR | @@ -60,7 +60,7 @@ >; }; - audmux_aud6 { + mux-aud6 { fsl,audmux-port = ; fsl,port-config = < IMX_AUDMUX_V2_PTCR_SYN diff --git a/arch/arm/boot/dts/imx6dl-rex-basic.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-rex-basic.dts similarity index 100% rename from arch/arm/boot/dts/imx6dl-rex-basic.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-rex-basic.dts diff --git a/arch/arm/boot/dts/imx6dl-riotboard.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-riotboard.dts similarity index 99% rename from arch/arm/boot/dts/imx6dl-riotboard.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-riotboard.dts index 24c7f535f63bd94c9a54e6fa65fa39df1cbf187d..0366d1037ef4a87cda96dcafc60e0c61845bcf7a 100644 --- a/arch/arm/boot/dts/imx6dl-riotboard.dts +++ b/arch/arm/boot/dts/nxp/imx/imx6dl-riotboard.dts @@ -177,7 +177,7 @@ VDDIO-supply = <®_3p3v>; }; - pmic: pf0100@8 { + pmic: pmic@8 { compatible = "fsl,pfuze100"; reg = <0x08>; interrupt-parent = <&gpio5>; diff --git a/arch/arm/boot/dts/imx6dl-sabreauto.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-sabreauto.dts similarity index 100% rename from arch/arm/boot/dts/imx6dl-sabreauto.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-sabreauto.dts diff --git a/arch/arm/boot/dts/imx6dl-sabrelite.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-sabrelite.dts similarity index 100% rename from arch/arm/boot/dts/imx6dl-sabrelite.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-sabrelite.dts diff --git a/arch/arm/boot/dts/imx6dl-sabresd.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-sabresd.dts similarity index 100% rename from arch/arm/boot/dts/imx6dl-sabresd.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-sabresd.dts diff --git a/arch/arm/boot/dts/imx6dl-savageboard.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-savageboard.dts similarity index 100% rename from arch/arm/boot/dts/imx6dl-savageboard.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-savageboard.dts diff --git a/arch/arm/boot/dts/imx6dl-skov-revc-lt2.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-skov-revc-lt2.dts similarity index 100% rename from arch/arm/boot/dts/imx6dl-skov-revc-lt2.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-skov-revc-lt2.dts diff --git a/arch/arm/boot/dts/imx6dl-skov-revc-lt6.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-skov-revc-lt6.dts similarity index 100% rename from arch/arm/boot/dts/imx6dl-skov-revc-lt6.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-skov-revc-lt6.dts diff --git a/arch/arm/boot/dts/imx6dl-solidsense.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-solidsense.dts similarity index 100% rename from arch/arm/boot/dts/imx6dl-solidsense.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-solidsense.dts diff --git a/arch/arm/boot/dts/imx6dl-tqma6a.dtsi b/arch/arm/boot/dts/nxp/imx/imx6dl-tqma6a.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6dl-tqma6a.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6dl-tqma6a.dtsi diff --git a/arch/arm/boot/dts/imx6dl-tqma6b.dtsi b/arch/arm/boot/dts/nxp/imx/imx6dl-tqma6b.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6dl-tqma6b.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6dl-tqma6b.dtsi diff --git a/arch/arm/boot/dts/imx6dl-ts4900.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-ts4900.dts similarity index 100% rename from arch/arm/boot/dts/imx6dl-ts4900.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-ts4900.dts diff --git a/arch/arm/boot/dts/imx6dl-ts7970.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-ts7970.dts similarity index 100% rename from arch/arm/boot/dts/imx6dl-ts7970.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-ts7970.dts diff --git a/arch/arm/boot/dts/imx6dl-tx6dl-comtft.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-tx6dl-comtft.dts similarity index 100% rename from arch/arm/boot/dts/imx6dl-tx6dl-comtft.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-tx6dl-comtft.dts diff --git a/arch/arm/boot/dts/imx6dl-tx6s-8034-mb7.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-tx6s-8034-mb7.dts similarity index 100% rename from arch/arm/boot/dts/imx6dl-tx6s-8034-mb7.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-tx6s-8034-mb7.dts diff --git a/arch/arm/boot/dts/imx6dl-tx6s-8034.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-tx6s-8034.dts similarity index 100% rename from arch/arm/boot/dts/imx6dl-tx6s-8034.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-tx6s-8034.dts diff --git a/arch/arm/boot/dts/imx6dl-tx6s-8035-mb7.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-tx6s-8035-mb7.dts similarity index 100% rename from arch/arm/boot/dts/imx6dl-tx6s-8035-mb7.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-tx6s-8035-mb7.dts diff --git a/arch/arm/boot/dts/imx6dl-tx6s-8035.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-tx6s-8035.dts similarity index 100% rename from arch/arm/boot/dts/imx6dl-tx6s-8035.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-tx6s-8035.dts diff --git a/arch/arm/boot/dts/imx6dl-tx6u-801x.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-tx6u-801x.dts similarity index 100% rename from arch/arm/boot/dts/imx6dl-tx6u-801x.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-tx6u-801x.dts diff --git a/arch/arm/boot/dts/imx6dl-tx6u-8033-mb7.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-tx6u-8033-mb7.dts similarity index 100% rename from arch/arm/boot/dts/imx6dl-tx6u-8033-mb7.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-tx6u-8033-mb7.dts diff --git a/arch/arm/boot/dts/imx6dl-tx6u-8033.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-tx6u-8033.dts similarity index 100% rename from arch/arm/boot/dts/imx6dl-tx6u-8033.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-tx6u-8033.dts diff --git a/arch/arm/boot/dts/imx6dl-tx6u-80xx-mb7.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-tx6u-80xx-mb7.dts similarity index 100% rename from arch/arm/boot/dts/imx6dl-tx6u-80xx-mb7.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-tx6u-80xx-mb7.dts diff --git a/arch/arm/boot/dts/imx6dl-tx6u-811x.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-tx6u-811x.dts similarity index 100% rename from arch/arm/boot/dts/imx6dl-tx6u-811x.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-tx6u-811x.dts diff --git a/arch/arm/boot/dts/imx6dl-tx6u-81xx-mb7.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-tx6u-81xx-mb7.dts similarity index 100% rename from arch/arm/boot/dts/imx6dl-tx6u-81xx-mb7.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-tx6u-81xx-mb7.dts diff --git a/arch/arm/boot/dts/imx6dl-udoo.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-udoo.dts similarity index 100% rename from arch/arm/boot/dts/imx6dl-udoo.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-udoo.dts diff --git a/arch/arm/boot/dts/imx6dl-victgo.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-victgo.dts similarity index 94% rename from arch/arm/boot/dts/imx6dl-victgo.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-victgo.dts index 23274be08e61ffb3e3b75205e050c637a9578e6d..4875afadb63005d101c4501b70f64761d732b86f 100644 --- a/arch/arm/boot/dts/imx6dl-victgo.dts +++ b/arch/arm/boot/dts/nxp/imx/imx6dl-victgo.dts @@ -74,18 +74,42 @@ polling-delay = <20000>; polling-delay-passive = <0>; thermal-sensors = <&tsens0>; + + trips { + alert { + temperature = <105000>; /* millicelsius */ + hysteresis = <2000>; /* millicelsius */ + type = "passive"; + }; + }; }; touch-thermal0 { polling-delay = <20000>; polling-delay-passive = <0>; thermal-sensors = <&touch_temp0>; + + trips { + alert { + temperature = <105000>; /* millicelsius */ + hysteresis = <2000>; /* millicelsius */ + type = "passive"; + }; + }; }; touch-thermal1 { polling-delay = <20000>; polling-delay-passive = <0>; thermal-sensors = <&touch_temp1>; + + trips { + alert { + temperature = <105000>; /* millicelsius */ + hysteresis = <2000>; /* millicelsius */ + type = "passive"; + }; + }; }; }; diff --git a/arch/arm/boot/dts/imx6dl-vicut1.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-vicut1.dts similarity index 100% rename from arch/arm/boot/dts/imx6dl-vicut1.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-vicut1.dts diff --git a/arch/arm/boot/dts/imx6dl-wandboard-revb1.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-wandboard-revb1.dts similarity index 100% rename from arch/arm/boot/dts/imx6dl-wandboard-revb1.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-wandboard-revb1.dts diff --git a/arch/arm/boot/dts/imx6dl-wandboard-revd1.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-wandboard-revd1.dts similarity index 100% rename from arch/arm/boot/dts/imx6dl-wandboard-revd1.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-wandboard-revd1.dts diff --git a/arch/arm/boot/dts/imx6dl-wandboard.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-wandboard.dts similarity index 100% rename from arch/arm/boot/dts/imx6dl-wandboard.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-wandboard.dts diff --git a/arch/arm/boot/dts/imx6dl-yapp4-common.dtsi b/arch/arm/boot/dts/nxp/imx/imx6dl-yapp4-common.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6dl-yapp4-common.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6dl-yapp4-common.dtsi diff --git a/arch/arm/boot/dts/imx6dl-yapp4-draco.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-yapp4-draco.dts similarity index 100% rename from arch/arm/boot/dts/imx6dl-yapp4-draco.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-yapp4-draco.dts diff --git a/arch/arm/boot/dts/imx6dl-yapp4-hydra.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-yapp4-hydra.dts similarity index 100% rename from arch/arm/boot/dts/imx6dl-yapp4-hydra.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-yapp4-hydra.dts diff --git a/arch/arm/boot/dts/imx6dl-yapp4-lynx.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-yapp4-lynx.dts similarity index 100% rename from arch/arm/boot/dts/imx6dl-yapp4-lynx.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-yapp4-lynx.dts diff --git a/arch/arm/boot/dts/imx6dl-yapp4-orion.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-yapp4-orion.dts similarity index 100% rename from arch/arm/boot/dts/imx6dl-yapp4-orion.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-yapp4-orion.dts diff --git a/arch/arm/boot/dts/imx6dl-yapp4-phoenix.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-yapp4-phoenix.dts similarity index 100% rename from arch/arm/boot/dts/imx6dl-yapp4-phoenix.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-yapp4-phoenix.dts diff --git a/arch/arm/boot/dts/imx6dl-yapp4-ursa.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-yapp4-ursa.dts similarity index 100% rename from arch/arm/boot/dts/imx6dl-yapp4-ursa.dts rename to arch/arm/boot/dts/nxp/imx/imx6dl-yapp4-ursa.dts diff --git a/arch/arm/boot/dts/imx6dl-yapp43-common.dtsi b/arch/arm/boot/dts/nxp/imx/imx6dl-yapp43-common.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6dl-yapp43-common.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6dl-yapp43-common.dtsi diff --git a/arch/arm/boot/dts/imx6dl.dtsi b/arch/arm/boot/dts/nxp/imx/imx6dl.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6dl.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6dl.dtsi diff --git a/arch/arm/boot/dts/imx6q-apalis-eval.dts b/arch/arm/boot/dts/nxp/imx/imx6q-apalis-eval.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-apalis-eval.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-apalis-eval.dts diff --git a/arch/arm/boot/dts/imx6q-apalis-ixora-v1.1.dts b/arch/arm/boot/dts/nxp/imx/imx6q-apalis-ixora-v1.1.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-apalis-ixora-v1.1.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-apalis-ixora-v1.1.dts diff --git a/arch/arm/boot/dts/imx6q-apalis-ixora-v1.2.dts b/arch/arm/boot/dts/nxp/imx/imx6q-apalis-ixora-v1.2.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-apalis-ixora-v1.2.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-apalis-ixora-v1.2.dts diff --git a/arch/arm/boot/dts/imx6q-apalis-ixora.dts b/arch/arm/boot/dts/nxp/imx/imx6q-apalis-ixora.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-apalis-ixora.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-apalis-ixora.dts diff --git a/arch/arm/boot/dts/imx6q-apf6dev.dts b/arch/arm/boot/dts/nxp/imx/imx6q-apf6dev.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-apf6dev.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-apf6dev.dts diff --git a/arch/arm/boot/dts/imx6q-arm2.dts b/arch/arm/boot/dts/nxp/imx/imx6q-arm2.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-arm2.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-arm2.dts diff --git a/arch/arm/boot/dts/imx6q-b450v3.dts b/arch/arm/boot/dts/nxp/imx/imx6q-b450v3.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-b450v3.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-b450v3.dts diff --git a/arch/arm/boot/dts/imx6q-b650v3.dts b/arch/arm/boot/dts/nxp/imx/imx6q-b650v3.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-b650v3.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-b650v3.dts diff --git a/arch/arm/boot/dts/imx6q-b850v3.dts b/arch/arm/boot/dts/nxp/imx/imx6q-b850v3.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-b850v3.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-b850v3.dts diff --git a/arch/arm/boot/dts/imx6q-ba16.dtsi b/arch/arm/boot/dts/nxp/imx/imx6q-ba16.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6q-ba16.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6q-ba16.dtsi diff --git a/arch/arm/boot/dts/imx6q-bosch-acc.dts b/arch/arm/boot/dts/nxp/imx/imx6q-bosch-acc.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-bosch-acc.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-bosch-acc.dts diff --git a/arch/arm/boot/dts/imx6q-bx50v3.dtsi b/arch/arm/boot/dts/nxp/imx/imx6q-bx50v3.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6q-bx50v3.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6q-bx50v3.dtsi diff --git a/arch/arm/boot/dts/imx6q-cm-fx6.dts b/arch/arm/boot/dts/nxp/imx/imx6q-cm-fx6.dts similarity index 99% rename from arch/arm/boot/dts/imx6q-cm-fx6.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-cm-fx6.dts index 1ad41c944b4b9cc4d1449ce623d15bb5ef00fc38..ffb3b8eeae5dba5713de7e5c4e683bc6b1743bf9 100644 --- a/arch/arm/boot/dts/imx6q-cm-fx6.dts +++ b/arch/arm/boot/dts/nxp/imx/imx6q-cm-fx6.dts @@ -141,7 +141,7 @@ pinctrl-0 = <&pinctrl_audmux>; status = "okay"; - ssi2 { + mux-ssi2 { fsl,audmux-port = <1>; fsl,port-config = < (IMX_AUDMUX_V2_PTCR_RCLKDIR | @@ -152,7 +152,7 @@ >; }; - audmux4 { + mux-audmux4 { fsl,audmux-port = <3>; fsl,port-config = < (IMX_AUDMUX_V2_PTCR_TFSDIR | diff --git a/arch/arm/boot/dts/imx6q-cubox-i-emmc-som-v15.dts b/arch/arm/boot/dts/nxp/imx/imx6q-cubox-i-emmc-som-v15.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-cubox-i-emmc-som-v15.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-cubox-i-emmc-som-v15.dts diff --git a/arch/arm/boot/dts/imx6q-cubox-i-som-v15.dts b/arch/arm/boot/dts/nxp/imx/imx6q-cubox-i-som-v15.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-cubox-i-som-v15.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-cubox-i-som-v15.dts diff --git a/arch/arm/boot/dts/imx6q-cubox-i.dts b/arch/arm/boot/dts/nxp/imx/imx6q-cubox-i.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-cubox-i.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-cubox-i.dts diff --git a/arch/arm/boot/dts/imx6q-dfi-fs700-m60.dts b/arch/arm/boot/dts/nxp/imx/imx6q-dfi-fs700-m60.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-dfi-fs700-m60.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-dfi-fs700-m60.dts diff --git a/arch/arm/boot/dts/imx6q-dhcom-pdk2.dts b/arch/arm/boot/dts/nxp/imx/imx6q-dhcom-pdk2.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-dhcom-pdk2.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-dhcom-pdk2.dts diff --git a/arch/arm/boot/dts/imx6q-display5-tianma-tm070-1280x768.dts b/arch/arm/boot/dts/nxp/imx/imx6q-display5-tianma-tm070-1280x768.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-display5-tianma-tm070-1280x768.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-display5-tianma-tm070-1280x768.dts diff --git a/arch/arm/boot/dts/imx6q-display5.dtsi b/arch/arm/boot/dts/nxp/imx/imx6q-display5.dtsi similarity index 99% rename from arch/arm/boot/dts/imx6q-display5.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6q-display5.dtsi index fef5d72545365c7479ad026cde49a6ddff191473..4ab31f2217cdbdd02273f26698ff9a5dff9fa886 100644 --- a/arch/arm/boot/dts/imx6q-display5.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx6q-display5.dtsi @@ -147,7 +147,7 @@ pinctrl-0 = <&pinctrl_audmux>; status = "okay"; - ssi2 { + mux-ssi2 { fsl,audmux-port = <1>; fsl,port-config = < (IMX_AUDMUX_V2_PTCR_SYN | @@ -159,7 +159,7 @@ >; }; - aud6 { + mux-aud6 { fsl,audmux-port = <5>; fsl,port-config = < (IMX_AUDMUX_V2_PTCR_RFSEL(8) | @@ -276,7 +276,7 @@ pinctrl-0 = <&pinctrl_i2c3>; status = "okay"; - at24@50 { + eeprom@50 { compatible = "atmel,24c256"; pagesize = <64>; reg = <0x50>; diff --git a/arch/arm/boot/dts/imx6q-dmo-edmqmx6.dts b/arch/arm/boot/dts/nxp/imx/imx6q-dmo-edmqmx6.dts similarity index 99% rename from arch/arm/boot/dts/imx6q-dmo-edmqmx6.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-dmo-edmqmx6.dts index 9591848cbd37c959b18bed67a74c7a562f9f62fb..3815cb660ff79657bfe862da0e7f1b8c26d27895 100644 --- a/arch/arm/boot/dts/imx6q-dmo-edmqmx6.dts +++ b/arch/arm/boot/dts/nxp/imx/imx6q-dmo-edmqmx6.dts @@ -134,7 +134,7 @@ &pinctrl_pfuze>; status = "okay"; - pmic: pfuze100@8 { + pmic: pmic@8 { compatible = "fsl,pfuze100"; reg = <0x08>; interrupt-parent = <&gpio3>; diff --git a/arch/arm/boot/dts/imx6q-dms-ba16.dts b/arch/arm/boot/dts/nxp/imx/imx6q-dms-ba16.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-dms-ba16.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-dms-ba16.dts diff --git a/arch/arm/boot/dts/imx6q-ds.dts b/arch/arm/boot/dts/nxp/imx/imx6q-ds.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-ds.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-ds.dts diff --git a/arch/arm/boot/dts/imx6q-emcon-avari.dts b/arch/arm/boot/dts/nxp/imx/imx6q-emcon-avari.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-emcon-avari.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-emcon-avari.dts diff --git a/arch/arm/boot/dts/imx6q-evi.dts b/arch/arm/boot/dts/nxp/imx/imx6q-evi.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-evi.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-evi.dts diff --git a/arch/arm/boot/dts/imx6q-gk802.dts b/arch/arm/boot/dts/nxp/imx/imx6q-gk802.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-gk802.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-gk802.dts diff --git a/arch/arm/boot/dts/imx6q-gw51xx.dts b/arch/arm/boot/dts/nxp/imx/imx6q-gw51xx.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-gw51xx.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-gw51xx.dts diff --git a/arch/arm/boot/dts/imx6q-gw52xx.dts b/arch/arm/boot/dts/nxp/imx/imx6q-gw52xx.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-gw52xx.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-gw52xx.dts diff --git a/arch/arm/boot/dts/imx6q-gw53xx.dts b/arch/arm/boot/dts/nxp/imx/imx6q-gw53xx.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-gw53xx.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-gw53xx.dts diff --git a/arch/arm/boot/dts/imx6q-gw5400-a.dts b/arch/arm/boot/dts/nxp/imx/imx6q-gw5400-a.dts similarity index 99% rename from arch/arm/boot/dts/imx6q-gw5400-a.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-gw5400-a.dts index 522a51042965ac9be87e2275b2dca0975525db41..0ba802b891b5b0cf866c47703bdb2a8abc21805a 100644 --- a/arch/arm/boot/dts/imx6q-gw5400-a.dts +++ b/arch/arm/boot/dts/nxp/imx/imx6q-gw5400-a.dts @@ -206,7 +206,7 @@ pinctrl-0 = <&pinctrl_i2c2>; status = "okay"; - pmic: pfuze100@8 { + pmic: pmic@8 { compatible = "fsl,pfuze100"; reg = <0x08>; diff --git a/arch/arm/boot/dts/imx6q-gw54xx.dts b/arch/arm/boot/dts/nxp/imx/imx6q-gw54xx.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-gw54xx.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-gw54xx.dts diff --git a/arch/arm/boot/dts/imx6q-gw551x.dts b/arch/arm/boot/dts/nxp/imx/imx6q-gw551x.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-gw551x.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-gw551x.dts diff --git a/arch/arm/boot/dts/imx6q-gw552x.dts b/arch/arm/boot/dts/nxp/imx/imx6q-gw552x.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-gw552x.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-gw552x.dts diff --git a/arch/arm/boot/dts/imx6q-gw553x.dts b/arch/arm/boot/dts/nxp/imx/imx6q-gw553x.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-gw553x.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-gw553x.dts diff --git a/arch/arm/boot/dts/imx6q-gw560x.dts b/arch/arm/boot/dts/nxp/imx/imx6q-gw560x.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-gw560x.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-gw560x.dts diff --git a/arch/arm/boot/dts/imx6q-gw5903.dts b/arch/arm/boot/dts/nxp/imx/imx6q-gw5903.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-gw5903.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-gw5903.dts diff --git a/arch/arm/boot/dts/imx6q-gw5904.dts b/arch/arm/boot/dts/nxp/imx/imx6q-gw5904.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-gw5904.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-gw5904.dts diff --git a/arch/arm/boot/dts/imx6q-gw5907.dts b/arch/arm/boot/dts/nxp/imx/imx6q-gw5907.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-gw5907.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-gw5907.dts diff --git a/arch/arm/boot/dts/imx6q-gw5910.dts b/arch/arm/boot/dts/nxp/imx/imx6q-gw5910.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-gw5910.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-gw5910.dts diff --git a/arch/arm/boot/dts/imx6q-gw5912.dts b/arch/arm/boot/dts/nxp/imx/imx6q-gw5912.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-gw5912.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-gw5912.dts diff --git a/arch/arm/boot/dts/imx6q-gw5913.dts b/arch/arm/boot/dts/nxp/imx/imx6q-gw5913.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-gw5913.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-gw5913.dts diff --git a/arch/arm/boot/dts/imx6q-h100.dts b/arch/arm/boot/dts/nxp/imx/imx6q-h100.dts similarity index 99% rename from arch/arm/boot/dts/imx6q-h100.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-h100.dts index 6406ade14f57b4b99b40a234976d4ff15fc5baa0..3fe4591e21f5751b16b348c6ce4136a8173f6c33 100644 --- a/arch/arm/boot/dts/imx6q-h100.dts +++ b/arch/arm/boot/dts/nxp/imx/imx6q-h100.dts @@ -166,7 +166,7 @@ pinctrl-0 = <&pinctrl_h100_i2c1>; status = "okay"; - eeprom: 24c02@51 { + eeprom: eeprom@51 { compatible = "microchip,24c02", "atmel,24c02"; reg = <0x51>; }; diff --git a/arch/arm/boot/dts/imx6q-hummingboard-emmc-som-v15.dts b/arch/arm/boot/dts/nxp/imx/imx6q-hummingboard-emmc-som-v15.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-hummingboard-emmc-som-v15.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-hummingboard-emmc-som-v15.dts diff --git a/arch/arm/boot/dts/imx6q-hummingboard-som-v15.dts b/arch/arm/boot/dts/nxp/imx/imx6q-hummingboard-som-v15.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-hummingboard-som-v15.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-hummingboard-som-v15.dts diff --git a/arch/arm/boot/dts/imx6q-hummingboard.dts b/arch/arm/boot/dts/nxp/imx/imx6q-hummingboard.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-hummingboard.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-hummingboard.dts diff --git a/arch/arm/boot/dts/imx6q-hummingboard2-emmc-som-v15.dts b/arch/arm/boot/dts/nxp/imx/imx6q-hummingboard2-emmc-som-v15.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-hummingboard2-emmc-som-v15.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-hummingboard2-emmc-som-v15.dts diff --git a/arch/arm/boot/dts/imx6q-hummingboard2-som-v15.dts b/arch/arm/boot/dts/nxp/imx/imx6q-hummingboard2-som-v15.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-hummingboard2-som-v15.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-hummingboard2-som-v15.dts diff --git a/arch/arm/boot/dts/imx6q-hummingboard2.dts b/arch/arm/boot/dts/nxp/imx/imx6q-hummingboard2.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-hummingboard2.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-hummingboard2.dts diff --git a/arch/arm/boot/dts/imx6q-icore-mipi.dts b/arch/arm/boot/dts/nxp/imx/imx6q-icore-mipi.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-icore-mipi.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-icore-mipi.dts diff --git a/arch/arm/boot/dts/imx6q-icore-ofcap10.dts b/arch/arm/boot/dts/nxp/imx/imx6q-icore-ofcap10.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-icore-ofcap10.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-icore-ofcap10.dts diff --git a/arch/arm/boot/dts/imx6q-icore-ofcap12.dts b/arch/arm/boot/dts/nxp/imx/imx6q-icore-ofcap12.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-icore-ofcap12.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-icore-ofcap12.dts diff --git a/arch/arm/boot/dts/imx6q-icore-rqs.dts b/arch/arm/boot/dts/nxp/imx/imx6q-icore-rqs.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-icore-rqs.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-icore-rqs.dts diff --git a/arch/arm/boot/dts/imx6q-icore.dts b/arch/arm/boot/dts/nxp/imx/imx6q-icore.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-icore.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-icore.dts diff --git a/arch/arm/boot/dts/imx6q-kontron-samx6i.dtsi b/arch/arm/boot/dts/nxp/imx/imx6q-kontron-samx6i.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6q-kontron-samx6i.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6q-kontron-samx6i.dtsi diff --git a/arch/arm/boot/dts/imx6q-kp-tpc.dts b/arch/arm/boot/dts/nxp/imx/imx6q-kp-tpc.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-kp-tpc.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-kp-tpc.dts diff --git a/arch/arm/boot/dts/imx6q-kp.dtsi b/arch/arm/boot/dts/nxp/imx/imx6q-kp.dtsi similarity index 99% rename from arch/arm/boot/dts/imx6q-kp.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6q-kp.dtsi index 5e0ed556004058da72cd6f2931b540e65d09317c..091903f53a56097c40f103600e5ddc2bdabb923c 100644 --- a/arch/arm/boot/dts/imx6q-kp.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx6q-kp.dtsi @@ -135,7 +135,7 @@ pinctrl-0 = <&pinctrl_audmux>; status = "okay"; - ssi1 { + mux-ssi1 { fsl,audmux-port = <0>; fsl,port-config = < (IMX_AUDMUX_V2_PTCR_SYN | @@ -147,7 +147,7 @@ >; }; - aud3 { + mux-aud3 { fsl,audmux-port = <2>; fsl,port-config = < IMX_AUDMUX_V2_PTCR_SYN diff --git a/arch/arm/boot/dts/imx6q-logicpd.dts b/arch/arm/boot/dts/nxp/imx/imx6q-logicpd.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-logicpd.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-logicpd.dts diff --git a/arch/arm/boot/dts/imx6q-marsboard.dts b/arch/arm/boot/dts/nxp/imx/imx6q-marsboard.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-marsboard.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-marsboard.dts diff --git a/arch/arm/boot/dts/imx6q-mba6.dtsi b/arch/arm/boot/dts/nxp/imx/imx6q-mba6.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6q-mba6.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6q-mba6.dtsi diff --git a/arch/arm/boot/dts/imx6q-mba6a.dts b/arch/arm/boot/dts/nxp/imx/imx6q-mba6a.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-mba6a.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-mba6a.dts diff --git a/arch/arm/boot/dts/imx6q-mba6b.dts b/arch/arm/boot/dts/nxp/imx/imx6q-mba6b.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-mba6b.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-mba6b.dts diff --git a/arch/arm/boot/dts/imx6q-mccmon6.dts b/arch/arm/boot/dts/nxp/imx/imx6q-mccmon6.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-mccmon6.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-mccmon6.dts diff --git a/arch/arm/boot/dts/imx6q-nitrogen6_max.dts b/arch/arm/boot/dts/nxp/imx/imx6q-nitrogen6_max.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-nitrogen6_max.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-nitrogen6_max.dts diff --git a/arch/arm/boot/dts/imx6q-nitrogen6_som2.dts b/arch/arm/boot/dts/nxp/imx/imx6q-nitrogen6_som2.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-nitrogen6_som2.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-nitrogen6_som2.dts diff --git a/arch/arm/boot/dts/imx6q-nitrogen6x.dts b/arch/arm/boot/dts/nxp/imx/imx6q-nitrogen6x.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-nitrogen6x.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-nitrogen6x.dts diff --git a/arch/arm/boot/dts/imx6q-novena.dts b/arch/arm/boot/dts/nxp/imx/imx6q-novena.dts similarity index 99% rename from arch/arm/boot/dts/imx6q-novena.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-novena.dts index ee8c0bd3ecfd525739da152e564a5be3235ab46e..a7d5a68110fcf723113ea4144ac8d454bbf5b042 100644 --- a/arch/arm/boot/dts/imx6q-novena.dts +++ b/arch/arm/boot/dts/nxp/imx/imx6q-novena.dts @@ -308,7 +308,7 @@ pinctrl-0 = <&pinctrl_i2c2_novena>; status = "okay"; - pmic: pfuze100@8 { + pmic: pmic@8 { compatible = "fsl,pfuze100"; reg = <0x08>; diff --git a/arch/arm/boot/dts/imx6q-phytec-mira-rdk-emmc.dts b/arch/arm/boot/dts/nxp/imx/imx6q-phytec-mira-rdk-emmc.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-phytec-mira-rdk-emmc.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-phytec-mira-rdk-emmc.dts diff --git a/arch/arm/boot/dts/imx6q-phytec-mira-rdk-nand.dts b/arch/arm/boot/dts/nxp/imx/imx6q-phytec-mira-rdk-nand.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-phytec-mira-rdk-nand.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-phytec-mira-rdk-nand.dts diff --git a/arch/arm/boot/dts/imx6q-phytec-pbab01.dts b/arch/arm/boot/dts/nxp/imx/imx6q-phytec-pbab01.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-phytec-pbab01.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-phytec-pbab01.dts diff --git a/arch/arm/boot/dts/imx6q-phytec-pfla02.dtsi b/arch/arm/boot/dts/nxp/imx/imx6q-phytec-pfla02.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6q-phytec-pfla02.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6q-phytec-pfla02.dtsi diff --git a/arch/arm/boot/dts/imx6q-pico-dwarf.dts b/arch/arm/boot/dts/nxp/imx/imx6q-pico-dwarf.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-pico-dwarf.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-pico-dwarf.dts diff --git a/arch/arm/boot/dts/imx6q-pico-hobbit.dts b/arch/arm/boot/dts/nxp/imx/imx6q-pico-hobbit.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-pico-hobbit.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-pico-hobbit.dts diff --git a/arch/arm/boot/dts/imx6q-pico-nymph.dts b/arch/arm/boot/dts/nxp/imx/imx6q-pico-nymph.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-pico-nymph.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-pico-nymph.dts diff --git a/arch/arm/boot/dts/imx6q-pico-pi.dts b/arch/arm/boot/dts/nxp/imx/imx6q-pico-pi.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-pico-pi.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-pico-pi.dts diff --git a/arch/arm/boot/dts/imx6q-pinfunc.h b/arch/arm/boot/dts/nxp/imx/imx6q-pinfunc.h similarity index 100% rename from arch/arm/boot/dts/imx6q-pinfunc.h rename to arch/arm/boot/dts/nxp/imx/imx6q-pinfunc.h diff --git a/arch/arm/boot/dts/imx6q-pistachio.dts b/arch/arm/boot/dts/nxp/imx/imx6q-pistachio.dts similarity index 99% rename from arch/arm/boot/dts/imx6q-pistachio.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-pistachio.dts index bad8d831e64e6f796b8f1b109e8d20df701982ec..109b46a22b5e85462e8432454b1774a41ac6eed9 100644 --- a/arch/arm/boot/dts/imx6q-pistachio.dts +++ b/arch/arm/boot/dts/nxp/imx/imx6q-pistachio.dts @@ -208,7 +208,7 @@ pinctrl-0 = <&pinctrl_i2c2>; status = "okay"; - pmic: pfuze100@8 { + pmic: pmic@8 { compatible = "fsl,pfuze100"; reg = <0x08>; diff --git a/arch/arm/boot/dts/imx6q-prti6q.dts b/arch/arm/boot/dts/nxp/imx/imx6q-prti6q.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-prti6q.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-prti6q.dts diff --git a/arch/arm/boot/dts/imx6q-prtwd2.dts b/arch/arm/boot/dts/nxp/imx/imx6q-prtwd2.dts similarity index 97% rename from arch/arm/boot/dts/imx6q-prtwd2.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-prtwd2.dts index 54a57a4548e2466cbcd4ee8cddc228c04b1f8360..792b8903d3451c2fc079242cd67cb57a674d3d56 100644 --- a/arch/arm/boot/dts/imx6q-prtwd2.dts +++ b/arch/arm/boot/dts/nxp/imx/imx6q-prtwd2.dts @@ -156,9 +156,6 @@ MX6QDL_PAD_CSI0_DAT4__GPIO5_IO22 0x1b0b0 /* nINTRP */ MX6QDL_PAD_CSI0_DAT5__GPIO5_IO23 0x1b0b0 - - MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x10030 - MX6QDL_PAD_ENET_MDC__ENET_MDC 0x10030 >; }; diff --git a/arch/arm/boot/dts/imx6q-rex-pro.dts b/arch/arm/boot/dts/nxp/imx/imx6q-rex-pro.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-rex-pro.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-rex-pro.dts diff --git a/arch/arm/boot/dts/imx6q-sabreauto.dts b/arch/arm/boot/dts/nxp/imx/imx6q-sabreauto.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-sabreauto.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-sabreauto.dts diff --git a/arch/arm/boot/dts/imx6q-sabrelite.dts b/arch/arm/boot/dts/nxp/imx/imx6q-sabrelite.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-sabrelite.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-sabrelite.dts diff --git a/arch/arm/boot/dts/imx6q-sabresd.dts b/arch/arm/boot/dts/nxp/imx/imx6q-sabresd.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-sabresd.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-sabresd.dts diff --git a/arch/arm/boot/dts/imx6q-savageboard.dts b/arch/arm/boot/dts/nxp/imx/imx6q-savageboard.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-savageboard.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-savageboard.dts diff --git a/arch/arm/boot/dts/imx6q-sbc6x.dts b/arch/arm/boot/dts/nxp/imx/imx6q-sbc6x.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-sbc6x.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-sbc6x.dts diff --git a/arch/arm/boot/dts/imx6q-skov-revc-lt2.dts b/arch/arm/boot/dts/nxp/imx/imx6q-skov-revc-lt2.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-skov-revc-lt2.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-skov-revc-lt2.dts diff --git a/arch/arm/boot/dts/imx6q-skov-revc-lt6.dts b/arch/arm/boot/dts/nxp/imx/imx6q-skov-revc-lt6.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-skov-revc-lt6.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-skov-revc-lt6.dts diff --git a/arch/arm/boot/dts/imx6q-skov-reve-mi1010ait-1cp1.dts b/arch/arm/boot/dts/nxp/imx/imx6q-skov-reve-mi1010ait-1cp1.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-skov-reve-mi1010ait-1cp1.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-skov-reve-mi1010ait-1cp1.dts diff --git a/arch/arm/boot/dts/imx6q-solidsense.dts b/arch/arm/boot/dts/nxp/imx/imx6q-solidsense.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-solidsense.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-solidsense.dts diff --git a/arch/arm/boot/dts/imx6q-tbs2910.dts b/arch/arm/boot/dts/nxp/imx/imx6q-tbs2910.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-tbs2910.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-tbs2910.dts diff --git a/arch/arm/boot/dts/imx6q-tqma6a.dtsi b/arch/arm/boot/dts/nxp/imx/imx6q-tqma6a.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6q-tqma6a.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6q-tqma6a.dtsi diff --git a/arch/arm/boot/dts/imx6q-tqma6b.dtsi b/arch/arm/boot/dts/nxp/imx/imx6q-tqma6b.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6q-tqma6b.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6q-tqma6b.dtsi diff --git a/arch/arm/boot/dts/imx6q-ts4900.dts b/arch/arm/boot/dts/nxp/imx/imx6q-ts4900.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-ts4900.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-ts4900.dts diff --git a/arch/arm/boot/dts/imx6q-ts7970.dts b/arch/arm/boot/dts/nxp/imx/imx6q-ts7970.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-ts7970.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-ts7970.dts diff --git a/arch/arm/boot/dts/imx6q-tx6q-1010-comtft.dts b/arch/arm/boot/dts/nxp/imx/imx6q-tx6q-1010-comtft.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-tx6q-1010-comtft.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-tx6q-1010-comtft.dts diff --git a/arch/arm/boot/dts/imx6q-tx6q-1010.dts b/arch/arm/boot/dts/nxp/imx/imx6q-tx6q-1010.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-tx6q-1010.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-tx6q-1010.dts diff --git a/arch/arm/boot/dts/imx6q-tx6q-1020-comtft.dts b/arch/arm/boot/dts/nxp/imx/imx6q-tx6q-1020-comtft.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-tx6q-1020-comtft.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-tx6q-1020-comtft.dts diff --git a/arch/arm/boot/dts/imx6q-tx6q-1020.dts b/arch/arm/boot/dts/nxp/imx/imx6q-tx6q-1020.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-tx6q-1020.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-tx6q-1020.dts diff --git a/arch/arm/boot/dts/imx6q-tx6q-1036-mb7.dts b/arch/arm/boot/dts/nxp/imx/imx6q-tx6q-1036-mb7.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-tx6q-1036-mb7.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-tx6q-1036-mb7.dts diff --git a/arch/arm/boot/dts/imx6q-tx6q-1036.dts b/arch/arm/boot/dts/nxp/imx/imx6q-tx6q-1036.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-tx6q-1036.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-tx6q-1036.dts diff --git a/arch/arm/boot/dts/imx6q-tx6q-10x0-mb7.dts b/arch/arm/boot/dts/nxp/imx/imx6q-tx6q-10x0-mb7.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-tx6q-10x0-mb7.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-tx6q-10x0-mb7.dts diff --git a/arch/arm/boot/dts/imx6q-tx6q-1110.dts b/arch/arm/boot/dts/nxp/imx/imx6q-tx6q-1110.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-tx6q-1110.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-tx6q-1110.dts diff --git a/arch/arm/boot/dts/imx6q-tx6q-11x0-mb7.dts b/arch/arm/boot/dts/nxp/imx/imx6q-tx6q-11x0-mb7.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-tx6q-11x0-mb7.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-tx6q-11x0-mb7.dts diff --git a/arch/arm/boot/dts/imx6q-udoo.dts b/arch/arm/boot/dts/nxp/imx/imx6q-udoo.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-udoo.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-udoo.dts diff --git a/arch/arm/boot/dts/imx6q-utilite-pro.dts b/arch/arm/boot/dts/nxp/imx/imx6q-utilite-pro.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-utilite-pro.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-utilite-pro.dts diff --git a/arch/arm/boot/dts/imx6q-var-dt6customboard.dts b/arch/arm/boot/dts/nxp/imx/imx6q-var-dt6customboard.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-var-dt6customboard.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-var-dt6customboard.dts diff --git a/arch/arm/boot/dts/imx6q-vicut1.dts b/arch/arm/boot/dts/nxp/imx/imx6q-vicut1.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-vicut1.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-vicut1.dts diff --git a/arch/arm/boot/dts/imx6q-wandboard-revb1.dts b/arch/arm/boot/dts/nxp/imx/imx6q-wandboard-revb1.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-wandboard-revb1.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-wandboard-revb1.dts diff --git a/arch/arm/boot/dts/imx6q-wandboard-revd1.dts b/arch/arm/boot/dts/nxp/imx/imx6q-wandboard-revd1.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-wandboard-revd1.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-wandboard-revd1.dts diff --git a/arch/arm/boot/dts/imx6q-wandboard.dts b/arch/arm/boot/dts/nxp/imx/imx6q-wandboard.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-wandboard.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-wandboard.dts diff --git a/arch/arm/boot/dts/imx6q-yapp4-crux.dts b/arch/arm/boot/dts/nxp/imx/imx6q-yapp4-crux.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-yapp4-crux.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-yapp4-crux.dts diff --git a/arch/arm/boot/dts/imx6q-yapp4-pegasus.dts b/arch/arm/boot/dts/nxp/imx/imx6q-yapp4-pegasus.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-yapp4-pegasus.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-yapp4-pegasus.dts diff --git a/arch/arm/boot/dts/imx6q-zii-rdu2.dts b/arch/arm/boot/dts/nxp/imx/imx6q-zii-rdu2.dts similarity index 100% rename from arch/arm/boot/dts/imx6q-zii-rdu2.dts rename to arch/arm/boot/dts/nxp/imx/imx6q-zii-rdu2.dts diff --git a/arch/arm/boot/dts/imx6q.dtsi b/arch/arm/boot/dts/nxp/imx/imx6q.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6q.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6q.dtsi diff --git a/arch/arm/boot/dts/imx6qdl-apalis.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-apalis.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6qdl-apalis.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6qdl-apalis.dtsi diff --git a/arch/arm/boot/dts/imx6qdl-apf6.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-apf6.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6qdl-apf6.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6qdl-apf6.dtsi diff --git a/arch/arm/boot/dts/imx6qdl-apf6dev.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-apf6dev.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6qdl-apf6dev.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6qdl-apf6dev.dtsi diff --git a/arch/arm/boot/dts/imx6qdl-aristainetos.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-aristainetos.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6qdl-aristainetos.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6qdl-aristainetos.dtsi diff --git a/arch/arm/boot/dts/imx6qdl-aristainetos2.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-aristainetos2.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6qdl-aristainetos2.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6qdl-aristainetos2.dtsi diff --git a/arch/arm/boot/dts/imx6qdl-colibri.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-colibri.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6qdl-colibri.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6qdl-colibri.dtsi diff --git a/arch/arm/boot/dts/imx6qdl-cubox-i.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-cubox-i.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6qdl-cubox-i.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6qdl-cubox-i.dtsi diff --git a/arch/arm/boot/dts/imx6qdl-dfi-fs700-m60.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-dfi-fs700-m60.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6qdl-dfi-fs700-m60.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6qdl-dfi-fs700-m60.dtsi diff --git a/arch/arm/boot/dts/imx6qdl-dhcom-drc02.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-dhcom-drc02.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6qdl-dhcom-drc02.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6qdl-dhcom-drc02.dtsi diff --git a/arch/arm/boot/dts/imx6qdl-dhcom-pdk2.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-dhcom-pdk2.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6qdl-dhcom-pdk2.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6qdl-dhcom-pdk2.dtsi diff --git a/arch/arm/boot/dts/imx6qdl-dhcom-picoitx.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-dhcom-picoitx.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6qdl-dhcom-picoitx.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6qdl-dhcom-picoitx.dtsi diff --git a/arch/arm/boot/dts/imx6qdl-dhcom-som.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-dhcom-som.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6qdl-dhcom-som.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6qdl-dhcom-som.dtsi diff --git a/arch/arm/boot/dts/imx6qdl-ds.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-ds.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6qdl-ds.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6qdl-ds.dtsi diff --git a/arch/arm/boot/dts/imx6qdl-emcon-avari.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-emcon-avari.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6qdl-emcon-avari.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6qdl-emcon-avari.dtsi diff --git a/arch/arm/boot/dts/imx6qdl-emcon.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-emcon.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6qdl-emcon.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6qdl-emcon.dtsi diff --git a/arch/arm/boot/dts/imx6qdl-gw51xx.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-gw51xx.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6qdl-gw51xx.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6qdl-gw51xx.dtsi diff --git a/arch/arm/boot/dts/imx6qdl-gw52xx.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-gw52xx.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6qdl-gw52xx.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6qdl-gw52xx.dtsi diff --git a/arch/arm/boot/dts/imx6qdl-gw53xx.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-gw53xx.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6qdl-gw53xx.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6qdl-gw53xx.dtsi diff --git a/arch/arm/boot/dts/imx6qdl-gw54xx.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-gw54xx.dtsi similarity index 99% rename from arch/arm/boot/dts/imx6qdl-gw54xx.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6qdl-gw54xx.dtsi index 4e20cb97058ebbbb1410f3eed36167a3afc751d9..a642be45ffe2e9b6138a827f6c79748767b1cf80 100644 --- a/arch/arm/boot/dts/imx6qdl-gw54xx.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-gw54xx.dtsi @@ -187,7 +187,7 @@ pinctrl-0 = <&pinctrl_audmux>; /* AUD4<->sgtl5000 */ status = "okay"; - ssi2 { + mux-ssi2 { fsl,audmux-port = <1>; fsl,port-config = < (IMX_AUDMUX_V2_PTCR_TFSDIR | @@ -199,7 +199,7 @@ >; }; - aud5 { + mux-aud5 { fsl,audmux-port = <4>; fsl,port-config = < IMX_AUDMUX_V2_PTCR_SYN @@ -349,8 +349,6 @@ fan-controller@2c { compatible = "gw,gsc-fan"; - #address-cells = <1>; - #size-cells = <0>; reg = <0x2c>; }; }; @@ -400,7 +398,7 @@ pinctrl-0 = <&pinctrl_i2c2>; status = "okay"; - pmic: pfuze100@8 { + pmic: pmic@8 { compatible = "fsl,pfuze100"; reg = <0x08>; diff --git a/arch/arm/boot/dts/imx6qdl-gw551x.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-gw551x.dtsi similarity index 99% rename from arch/arm/boot/dts/imx6qdl-gw551x.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6qdl-gw551x.dtsi index 0fa4b8eeddee75870ccdf653d370ad33f8196dc1..29960d1cf6a03f260e92e7d1a11f34d6c24a3a1e 100644 --- a/arch/arm/boot/dts/imx6qdl-gw551x.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-gw551x.dtsi @@ -171,7 +171,7 @@ pinctrl-0 = <&pinctrl_audmux>; /* AUD5<->tda1997x */ status = "okay"; - ssi1 { + mux-ssi1 { fsl,audmux-port = <0>; fsl,port-config = < (IMX_AUDMUX_V2_PTCR_TFSDIR | @@ -183,7 +183,7 @@ >; }; - aud5 { + mux-aud5 { fsl,audmux-port = <4>; fsl,port-config = < IMX_AUDMUX_V2_PTCR_SYN diff --git a/arch/arm/boot/dts/imx6qdl-gw552x.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-gw552x.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6qdl-gw552x.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6qdl-gw552x.dtsi diff --git a/arch/arm/boot/dts/imx6qdl-gw553x.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-gw553x.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6qdl-gw553x.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6qdl-gw553x.dtsi diff --git a/arch/arm/boot/dts/imx6qdl-gw560x.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-gw560x.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6qdl-gw560x.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6qdl-gw560x.dtsi diff --git a/arch/arm/boot/dts/imx6qdl-gw5903.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-gw5903.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6qdl-gw5903.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6qdl-gw5903.dtsi diff --git a/arch/arm/boot/dts/imx6qdl-gw5904.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-gw5904.dtsi similarity index 99% rename from arch/arm/boot/dts/imx6qdl-gw5904.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6qdl-gw5904.dtsi index 9fc79af2bc9aa18969a2bfe39369e7e83aca7875..9594bc5745ed6f5dc9db215bc805e89594e15d55 100644 --- a/arch/arm/boot/dts/imx6qdl-gw5904.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-gw5904.dtsi @@ -238,8 +238,13 @@ port@5 { reg = <5>; - label = "cpu"; ethernet = <&fec>; + phy-mode = "rgmii-id"; + + fixed-link { + speed = <1000>; + full-duplex; + }; }; }; }; diff --git a/arch/arm/boot/dts/imx6qdl-gw5907.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-gw5907.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6qdl-gw5907.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6qdl-gw5907.dtsi diff --git a/arch/arm/boot/dts/imx6qdl-gw5910.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-gw5910.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6qdl-gw5910.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6qdl-gw5910.dtsi diff --git a/arch/arm/boot/dts/imx6qdl-gw5912.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-gw5912.dtsi similarity index 99% rename from arch/arm/boot/dts/imx6qdl-gw5912.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6qdl-gw5912.dtsi index 40e235e315cc45b9740a47dbb0f1c6b262fa9837..de5983cf7810d19d2239f10420091ed531c3d12a 100644 --- a/arch/arm/boot/dts/imx6qdl-gw5912.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-gw5912.dtsi @@ -243,8 +243,6 @@ fan-controller@a { compatible = "gw,gsc-fan"; - #address-cells = <1>; - #size-cells = <0>; reg = <0x0a>; }; }; diff --git a/arch/arm/boot/dts/imx6qdl-gw5913.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-gw5913.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6qdl-gw5913.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6qdl-gw5913.dtsi diff --git a/arch/arm/boot/dts/imx6qdl-hummingboard.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-hummingboard.dtsi similarity index 99% rename from arch/arm/boot/dts/imx6qdl-hummingboard.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6qdl-hummingboard.dtsi index 2ffb21dd89f2af578524151949a8e526e88ceaeb..bfade71490807a955882d8c35dc5bffbbdee8086 100644 --- a/arch/arm/boot/dts/imx6qdl-hummingboard.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-hummingboard.dtsi @@ -147,7 +147,7 @@ &audmux { status = "okay"; - ssi1 { + mux-ssi1 { fsl,audmux-port = <0>; fsl,port-config = < (IMX_AUDMUX_V2_PTCR_SYN | @@ -159,7 +159,7 @@ >; }; - pins5 { + mux-pins5 { fsl,audmux-port = <4>; fsl,port-config = < IMX_AUDMUX_V2_PTCR_SYN diff --git a/arch/arm/boot/dts/imx6qdl-hummingboard2-emmc.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-hummingboard2-emmc.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6qdl-hummingboard2-emmc.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6qdl-hummingboard2-emmc.dtsi diff --git a/arch/arm/boot/dts/imx6qdl-hummingboard2.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-hummingboard2.dtsi similarity index 99% rename from arch/arm/boot/dts/imx6qdl-hummingboard2.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6qdl-hummingboard2.dtsi index eb1ad28946d3652f664c8154c9a71ae3fcc4cb7b..0883ef99cded09b219ae81cbb0b68eb97e48df8c 100644 --- a/arch/arm/boot/dts/imx6qdl-hummingboard2.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-hummingboard2.dtsi @@ -179,7 +179,7 @@ &audmux { status = "okay"; - ssi1 { + mux-ssi1 { fsl,audmux-port = <0>; fsl,port-config = < (IMX_AUDMUX_V2_PTCR_SYN | @@ -191,7 +191,7 @@ >; }; - pins5 { + mux-pins5 { fsl,audmux-port = <4>; fsl,port-config = < IMX_AUDMUX_V2_PTCR_SYN diff --git a/arch/arm/boot/dts/imx6qdl-icore-1.5.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-icore-1.5.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6qdl-icore-1.5.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6qdl-icore-1.5.dtsi diff --git a/arch/arm/boot/dts/imx6qdl-icore-rqs.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-icore-rqs.dtsi similarity index 99% rename from arch/arm/boot/dts/imx6qdl-icore-rqs.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6qdl-icore-rqs.dtsi index a4217f564a5347a568830e2032dd3fac2ae1c80f..d339957cc09730297bbf3b672985dbd070f5493b 100644 --- a/arch/arm/boot/dts/imx6qdl-icore-rqs.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-icore-rqs.dtsi @@ -118,7 +118,7 @@ pinctrl-0 = <&pinctrl_audmux>; status = "okay"; - audmux_ssi1 { + mux-ssi1 { fsl,audmux-port = ; fsl,port-config = < (IMX_AUDMUX_V2_PTCR_TFSDIR | @@ -130,7 +130,7 @@ >; }; - audmux_aud4 { + mux-aud4 { fsl,audmux-port = ; fsl,port-config = < IMX_AUDMUX_V2_PTCR_SYN @@ -262,7 +262,7 @@ pinctrl-0 = <&pinctrl_usdhc3>; pinctrl-1 = <&pinctrl_usdhc3_100mhz>; pinctrl-2 = <&pinctrl_usdhc3_200mhz>; - vmcc-supply = <®_sd3_vmmc>; + vmmc-supply = <®_sd3_vmmc>; cd-gpios = <&gpio1 1 GPIO_ACTIVE_LOW>; bus-width = <4>; no-1-8-v; @@ -274,7 +274,7 @@ pinctrl-0 = <&pinctrl_usdhc4>; pinctrl-1 = <&pinctrl_usdhc4_100mhz>; pinctrl-2 = <&pinctrl_usdhc4_200mhz>; - vmcc-supply = <®_sd4_vmmc>; + vmmc-supply = <®_sd4_vmmc>; bus-width = <8>; no-1-8-v; non-removable; diff --git a/arch/arm/boot/dts/imx6qdl-icore.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-icore.dtsi similarity index 99% rename from arch/arm/boot/dts/imx6qdl-icore.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6qdl-icore.dtsi index 23c318d9636fcd895e6c6fcdb56934d3a758dbc0..efe11524b885db38ffa295d0e4465611114702bf 100644 --- a/arch/arm/boot/dts/imx6qdl-icore.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-icore.dtsi @@ -109,7 +109,7 @@ status = "okay"; - audmux_ssi1 { + mux-ssi1 { fsl,audmux-port = ; fsl,port-config = < (IMX_AUDMUX_V2_PTCR_TFSDIR | @@ -121,7 +121,7 @@ >; }; - audmux_aud4 { + mux-aud4 { fsl,audmux-port = ; fsl,port-config = < IMX_AUDMUX_V2_PTCR_SYN diff --git a/arch/arm/boot/dts/imx6qdl-kontron-samx6i.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-kontron-samx6i.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6qdl-kontron-samx6i.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6qdl-kontron-samx6i.dtsi diff --git a/arch/arm/boot/dts/imx6qdl-mba6.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-mba6.dtsi similarity index 91% rename from arch/arm/boot/dts/imx6qdl-mba6.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6qdl-mba6.dtsi index 7b7e6c2ad190c838b38c8e9a74ceea01992fdc1b..7d032d1f3b4713a1d67001aa14a725987cb5f642 100644 --- a/arch/arm/boot/dts/imx6qdl-mba6.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-mba6.dtsi @@ -129,7 +129,7 @@ &audmux { status = "okay"; - ssi0 { + mux-ssi0 { fsl,audmux-port = ; fsl,port-config = < (IMX_AUDMUX_V2_PTCR_SYN | @@ -141,7 +141,7 @@ >; }; - aud3 { + mux-aud3 { fsl,audmux-port = ; fsl,port-config = < IMX_AUDMUX_V2_PTCR_SYN @@ -192,6 +192,13 @@ }; }; +&hdmi { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_hdmi>; + ddc-i2c-bus = <&i2c2>; + status = "okay"; +}; + &i2c1 { tlv320aic32x4: audio-codec@18 { compatible = "ti,tlv320aic32x4"; @@ -205,6 +212,17 @@ }; }; +/* DDC */ +&i2c2 { + clock-frequency = <100000>; + pinctrl-names = "default", "gpio"; + pinctrl-0 = <&pinctrl_i2c2>; + pinctrl-1 = <&pinctrl_i2c2_recovery>; + scl-gpios = <&gpio4 12 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + sda-gpios = <&gpio4 13 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + status = "okay"; +}; + &pcie { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_pcie>; @@ -272,6 +290,22 @@ &usbh1 { disable-over-current; status = "okay"; + #address-cells = <1>; + #size-cells = <0>; + + hub@1 { + compatible = "usb424,2517"; + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + ethernet@1 { + compatible = "usb424,9e00"; + reg = <1>; + nvmem-cells = <&mba_mac_address>; + nvmem-cell-names = "mac-address"; + }; + }; }; &usbotg { @@ -396,6 +430,15 @@ >; }; + pinctrl_hdmi: hdmigrp { + /* NOTE: DDC is done via I2C2, so DON'T + * configure DDC pins for HDMI! + */ + fsl,pins = < + MX6QDL_PAD_EIM_A25__HDMI_TX_CEC_LINE 0x1f8b0 + >; + }; + pinctrl_hog: hoggrp { fsl,pins = < MX6QDL_PAD_DI0_PIN4__GPIO4_IO20 0x0001b099 @@ -432,6 +475,20 @@ >; }; + pinctrl_i2c2: i2c2grp { + fsl,pins = < + MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b899 + MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b899 + >; + }; + + pinctrl_i2c2_recovery: i2c2recoverygrp { + fsl,pins = < + MX6QDL_PAD_KEY_COL3__GPIO4_IO12 0x4001b899 + MX6QDL_PAD_KEY_ROW3__GPIO4_IO13 0x4001b899 + >; + }; + pinctrl_pcie: pciegrp { fsl,pins = < /* HYS = 1, DSE = 110, 100k up, SPEED = HIGH (11)*/ diff --git a/arch/arm/boot/dts/imx6qdl-mba6a.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-mba6a.dtsi similarity index 83% rename from arch/arm/boot/dts/imx6qdl-mba6a.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6qdl-mba6a.dtsi index df8fa169e9f6dd94a0ddb48f65ac68dd0f2b9c2e..27fec340c380a225a4fcc0885cb0c69311056fd6 100644 --- a/arch/arm/boot/dts/imx6qdl-mba6a.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-mba6a.dtsi @@ -21,6 +21,12 @@ compatible = "atmel,24c64"; reg = <0x57>; pagesize = <32>; + #address-cells = <1>; + #size-cells = <1>; + + mba_mac_address: mac-address@20 { + reg = <0x20 0x6>; + }; }; rtc0: rtc@68 { diff --git a/arch/arm/boot/dts/imx6qdl-mba6b.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-mba6b.dtsi similarity index 89% rename from arch/arm/boot/dts/imx6qdl-mba6b.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6qdl-mba6b.dtsi index 7d1cd7454c7f5b5033d7d3856dff4ff284fcdfba..0a9f076eeb36ea8fa5c15f3b7dc5639f2c3af85d 100644 --- a/arch/arm/boot/dts/imx6qdl-mba6b.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-mba6b.dtsi @@ -31,6 +31,12 @@ compatible = "atmel,24c64"; reg = <0x57>; pagesize = <32>; + #address-cells = <1>; + #size-cells = <1>; + + mba_mac_address: mac-address@20 { + reg = <0x20 0x6>; + }; }; rtc0: rtc@68 { diff --git a/arch/arm/boot/dts/imx6qdl-nit6xlite.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-nit6xlite.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6qdl-nit6xlite.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6qdl-nit6xlite.dtsi diff --git a/arch/arm/boot/dts/imx6qdl-nitrogen6_max.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-nitrogen6_max.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6qdl-nitrogen6_max.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6qdl-nitrogen6_max.dtsi diff --git a/arch/arm/boot/dts/imx6qdl-nitrogen6_som2.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-nitrogen6_som2.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6qdl-nitrogen6_som2.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6qdl-nitrogen6_som2.dtsi diff --git a/arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-nitrogen6x.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6qdl-nitrogen6x.dtsi diff --git a/arch/arm/boot/dts/imx6qdl-phytec-mira-peb-av-02.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-phytec-mira-peb-av-02.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6qdl-phytec-mira-peb-av-02.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6qdl-phytec-mira-peb-av-02.dtsi diff --git a/arch/arm/boot/dts/imx6qdl-phytec-mira-peb-eval-01.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-phytec-mira-peb-eval-01.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6qdl-phytec-mira-peb-eval-01.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6qdl-phytec-mira-peb-eval-01.dtsi diff --git a/arch/arm/boot/dts/imx6qdl-phytec-mira-peb-wlbt-05.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-phytec-mira-peb-wlbt-05.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6qdl-phytec-mira-peb-wlbt-05.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6qdl-phytec-mira-peb-wlbt-05.dtsi diff --git a/arch/arm/boot/dts/imx6qdl-phytec-mira.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-phytec-mira.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6qdl-phytec-mira.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6qdl-phytec-mira.dtsi diff --git a/arch/arm/boot/dts/imx6qdl-phytec-pbab01.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-phytec-pbab01.dtsi similarity index 99% rename from arch/arm/boot/dts/imx6qdl-phytec-pbab01.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6qdl-phytec-pbab01.dtsi index 51d28e275aa649ba878dc972b281b55ab0d07176..a41e47c06ef40ccee5276ea7e4be17e3a30c127e 100644 --- a/arch/arm/boot/dts/imx6qdl-phytec-pbab01.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-phytec-pbab01.dtsi @@ -75,7 +75,7 @@ &audmux { status = "okay"; - ssi2 { + mux-ssi2 { fsl,audmux-port = <1>; fsl,port-config = < (IMX_AUDMUX_V2_PTCR_SYN | @@ -87,7 +87,7 @@ >; }; - pins5 { + mux-pins5 { fsl,audmux-port = <4>; fsl,port-config = < IMX_AUDMUX_V2_PTCR_SYN diff --git a/arch/arm/boot/dts/imx6qdl-phytec-pfla02.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-phytec-pfla02.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6qdl-phytec-pfla02.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6qdl-phytec-pfla02.dtsi diff --git a/arch/arm/boot/dts/imx6qdl-phytec-phycore-som.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-phytec-phycore-som.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6qdl-phytec-phycore-som.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6qdl-phytec-phycore-som.dtsi diff --git a/arch/arm/boot/dts/imx6qdl-pico-dwarf.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-pico-dwarf.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6qdl-pico-dwarf.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6qdl-pico-dwarf.dtsi diff --git a/arch/arm/boot/dts/imx6qdl-pico-hobbit.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-pico-hobbit.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6qdl-pico-hobbit.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6qdl-pico-hobbit.dtsi diff --git a/arch/arm/boot/dts/imx6qdl-pico-nymph.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-pico-nymph.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6qdl-pico-nymph.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6qdl-pico-nymph.dtsi diff --git a/arch/arm/boot/dts/imx6qdl-pico-pi.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-pico-pi.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6qdl-pico-pi.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6qdl-pico-pi.dtsi diff --git a/arch/arm/boot/dts/imx6qdl-pico.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-pico.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6qdl-pico.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6qdl-pico.dtsi diff --git a/arch/arm/boot/dts/imx6qdl-prti6q.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-prti6q.dtsi similarity index 97% rename from arch/arm/boot/dts/imx6qdl-prti6q.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6qdl-prti6q.dtsi index f0db0d4471f40f014d69613b7822fbd22fe27ae4..36f84f4da6b0ded749241412020a36c5ac258d5d 100644 --- a/arch/arm/boot/dts/imx6qdl-prti6q.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-prti6q.dtsi @@ -69,6 +69,7 @@ vbus-supply = <®_usb_h1_vbus>; phy_type = "utmi"; dr_mode = "host"; + disable-over-current; status = "okay"; }; @@ -78,10 +79,18 @@ pinctrl-0 = <&pinctrl_usbotg>; phy_type = "utmi"; dr_mode = "host"; - disable-over-current; + over-current-active-low; status = "okay"; }; +&usbphynop1 { + status = "disabled"; +}; + +&usbphynop2 { + status = "disabled"; +}; + &usdhc1 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_usdhc1>; diff --git a/arch/arm/boot/dts/imx6qdl-rex.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-rex.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6qdl-rex.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6qdl-rex.dtsi diff --git a/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-sabreauto.dtsi similarity index 99% rename from arch/arm/boot/dts/imx6qdl-sabreauto.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6qdl-sabreauto.dtsi index f79caa36f3d25e3cbac03cac74b3ebf2e20cc399..68e97180d33e38831865b866e861001bca2e4a3d 100644 --- a/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-sabreauto.dtsi @@ -336,7 +336,7 @@ pinctrl-0 = <&pinctrl_i2c2>; status = "okay"; - pmic: pfuze100@8 { + pmic: pmic@8 { compatible = "fsl,pfuze100"; reg = <0x08>; diff --git a/arch/arm/boot/dts/imx6qdl-sabrelite.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-sabrelite.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6qdl-sabrelite.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6qdl-sabrelite.dtsi diff --git a/arch/arm/boot/dts/imx6qdl-sabresd.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-sabresd.dtsi similarity index 99% rename from arch/arm/boot/dts/imx6qdl-sabresd.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6qdl-sabresd.dtsi index 53b080c97f2d990628515dba97f87c6f896f5262..4fe58764b929aee760f60d78a8ad7a6998b57752 100644 --- a/arch/arm/boot/dts/imx6qdl-sabresd.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-sabresd.dtsi @@ -338,7 +338,7 @@ }; }; - pmic: pfuze100@8 { + pmic: pmic@8 { compatible = "fsl,pfuze100"; reg = <0x08>; diff --git a/arch/arm/boot/dts/imx6qdl-savageboard.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-savageboard.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6qdl-savageboard.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6qdl-savageboard.dtsi diff --git a/arch/arm/boot/dts/imx6qdl-skov-cpu-revc.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-skov-cpu-revc.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6qdl-skov-cpu-revc.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6qdl-skov-cpu-revc.dtsi diff --git a/arch/arm/boot/dts/imx6qdl-skov-cpu.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-skov-cpu.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6qdl-skov-cpu.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6qdl-skov-cpu.dtsi diff --git a/arch/arm/boot/dts/imx6qdl-skov-revc-lt2.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-skov-revc-lt2.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6qdl-skov-revc-lt2.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6qdl-skov-revc-lt2.dtsi diff --git a/arch/arm/boot/dts/imx6qdl-solidsense.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-solidsense.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6qdl-solidsense.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6qdl-solidsense.dtsi diff --git a/arch/arm/boot/dts/imx6qdl-sr-som-brcm.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-sr-som-brcm.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6qdl-sr-som-brcm.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6qdl-sr-som-brcm.dtsi diff --git a/arch/arm/boot/dts/imx6qdl-sr-som-emmc.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-sr-som-emmc.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6qdl-sr-som-emmc.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6qdl-sr-som-emmc.dtsi diff --git a/arch/arm/boot/dts/imx6qdl-sr-som-ti.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-sr-som-ti.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6qdl-sr-som-ti.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6qdl-sr-som-ti.dtsi diff --git a/arch/arm/boot/dts/imx6qdl-sr-som.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-sr-som.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6qdl-sr-som.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6qdl-sr-som.dtsi diff --git a/arch/arm/boot/dts/imx6qdl-tqma6.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-tqma6.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6qdl-tqma6.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6qdl-tqma6.dtsi diff --git a/arch/arm/boot/dts/imx6qdl-tqma6a.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-tqma6a.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6qdl-tqma6a.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6qdl-tqma6a.dtsi diff --git a/arch/arm/boot/dts/imx6qdl-tqma6b.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-tqma6b.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6qdl-tqma6b.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6qdl-tqma6b.dtsi diff --git a/arch/arm/boot/dts/imx6qdl-ts4900.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-ts4900.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6qdl-ts4900.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6qdl-ts4900.dtsi diff --git a/arch/arm/boot/dts/imx6qdl-ts7970.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-ts7970.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6qdl-ts7970.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6qdl-ts7970.dtsi diff --git a/arch/arm/boot/dts/imx6qdl-tx6-lcd.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-tx6-lcd.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6qdl-tx6-lcd.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6qdl-tx6-lcd.dtsi diff --git a/arch/arm/boot/dts/imx6qdl-tx6-lvds.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-tx6-lvds.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6qdl-tx6-lvds.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6qdl-tx6-lvds.dtsi diff --git a/arch/arm/boot/dts/imx6qdl-tx6-mb7.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-tx6-mb7.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6qdl-tx6-mb7.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6qdl-tx6-mb7.dtsi diff --git a/arch/arm/boot/dts/imx6qdl-tx6.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-tx6.dtsi similarity index 99% rename from arch/arm/boot/dts/imx6qdl-tx6.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6qdl-tx6.dtsi index a197bac95cbace8b32c5bbbd298fb256302f24c7..e2fe337f7d9ed6eae042516d8db1665764768470 100644 --- a/arch/arm/boot/dts/imx6qdl-tx6.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-tx6.dtsi @@ -216,7 +216,7 @@ &audmux { status = "okay"; - ssi1 { + mux-ssi1 { fsl,audmux-port = <0>; fsl,port-config = < (IMX_AUDMUX_V2_PTCR_SYN | @@ -228,7 +228,7 @@ >; }; - pins5 { + mux-pins5 { fsl,audmux-port = <4>; fsl,port-config = < IMX_AUDMUX_V2_PTCR_SYN diff --git a/arch/arm/boot/dts/imx6qdl-udoo.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-udoo.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6qdl-udoo.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6qdl-udoo.dtsi diff --git a/arch/arm/boot/dts/imx6qdl-var-dart.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-var-dart.dtsi similarity index 99% rename from arch/arm/boot/dts/imx6qdl-var-dart.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6qdl-var-dart.dtsi index c41cac502bacc30ced5a402de990944a8e404a21..200559d7158dc0b7c507471f02895a20d2ce6d1c 100644 --- a/arch/arm/boot/dts/imx6qdl-var-dart.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-var-dart.dtsi @@ -39,7 +39,7 @@ pinctrl-0 = <&pinctrl_audmux>; status = "okay"; - ssi2 { + mux-ssi2 { fsl,audmux-port = <1>; fsl,port-config = < (IMX_AUDMUX_V2_PTCR_SYN | @@ -51,7 +51,7 @@ >; }; - aud3 { + mux-aud3 { fsl,audmux-port = <2>; fsl,port-config = < IMX_AUDMUX_V2_PTCR_SYN diff --git a/arch/arm/boot/dts/imx6qdl-vicut1-12inch.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-vicut1-12inch.dtsi similarity index 99% rename from arch/arm/boot/dts/imx6qdl-vicut1-12inch.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6qdl-vicut1-12inch.dtsi index f505f2704530549983fcade4e74f2c8baff6ba63..73f381e144672badf7d4aedb30f00bc3610835be 100644 --- a/arch/arm/boot/dts/imx6qdl-vicut1-12inch.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-vicut1-12inch.dtsi @@ -10,7 +10,7 @@ pinctrl-0 = <&pinctrl_gpiokeys>; autorepeat; - power { + power-button { label = "Power Button"; gpios = <&gpio2 23 GPIO_ACTIVE_LOW>; linux,code = ; diff --git a/arch/arm/boot/dts/imx6qdl-vicut1.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-vicut1.dtsi similarity index 98% rename from arch/arm/boot/dts/imx6qdl-vicut1.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6qdl-vicut1.dtsi index c4e6cf0527ba40c4cea579a2cebc7601a16ecaad..96e4f4b0b248f47ba45bd40986f45f33e0ce6a8b 100644 --- a/arch/arm/boot/dts/imx6qdl-vicut1.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-vicut1.dtsi @@ -169,6 +169,14 @@ polling-delay = <20000>; polling-delay-passive = <0>; thermal-sensors = <&tsens0>; + + trips { + alert { + temperature = <105000>; /* millicelsius */ + hysteresis = <2000>; /* millicelsius */ + type = "passive"; + }; + }; }; }; }; @@ -393,8 +401,6 @@ }; &ssi1 { - #sound-dai-cells = <0>; - fsl,mode = "ac97-slave"; status = "okay"; }; @@ -426,6 +432,7 @@ pinctrl-names = "default"; phy_type = "utmi"; dr_mode = "host"; + disable-over-current; status = "okay"; }; @@ -439,6 +446,14 @@ status = "okay"; }; +&usbphynop1 { + status = "disabled"; +}; + +&usbphynop2 { + status = "disabled"; +}; + &usdhc1 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_usdhc1>; diff --git a/arch/arm/boot/dts/imx6qdl-wandboard-revb1.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-wandboard-revb1.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6qdl-wandboard-revb1.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6qdl-wandboard-revb1.dtsi diff --git a/arch/arm/boot/dts/imx6qdl-wandboard-revc1.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-wandboard-revc1.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6qdl-wandboard-revc1.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6qdl-wandboard-revc1.dtsi diff --git a/arch/arm/boot/dts/imx6qdl-wandboard-revd1.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-wandboard-revd1.dtsi similarity index 99% rename from arch/arm/boot/dts/imx6qdl-wandboard-revd1.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6qdl-wandboard-revd1.dtsi index bf86b639fdac3c6def06b6bcc72aec82055f5dd3..9b8c9c23ab547596e0c4803ecf29ce9bc64614fb 100644 --- a/arch/arm/boot/dts/imx6qdl-wandboard-revd1.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-wandboard-revd1.dtsi @@ -27,7 +27,7 @@ pinctrl-0 = <&pinctrl_i2c3>; status = "okay"; - pmic: pfuze100@8 { + pmic: pmic@8 { compatible = "fsl,pfuze100"; reg = <0x08>; diff --git a/arch/arm/boot/dts/imx6qdl-wandboard.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-wandboard.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6qdl-wandboard.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6qdl-wandboard.dtsi diff --git a/arch/arm/boot/dts/imx6qdl-zii-rdu2.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-zii-rdu2.dtsi similarity index 99% rename from arch/arm/boot/dts/imx6qdl-zii-rdu2.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6qdl-zii-rdu2.dtsi index 5bb47c79a4da23e96b634da82b7b75d11236e0b1..9ff183e4e069a805adad0d95485713167acd72ba 100644 --- a/arch/arm/boot/dts/imx6qdl-zii-rdu2.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-zii-rdu2.dtsi @@ -757,7 +757,7 @@ port@2 { reg = <2>; - label = "cpu"; + phy-mode = "rev-rmii"; ethernet = <&fec>; fixed-link { @@ -848,7 +848,7 @@ pinctrl-0 = <&pinctrl_audmux>; status = "okay"; - ssi1 { + mux-ssi1 { fsl,audmux-port = <0>; fsl,port-config = < (IMX_AUDMUX_V2_PTCR_SYN | @@ -860,7 +860,7 @@ >; }; - aud3 { + mux-aud3 { fsl,audmux-port = <2>; fsl,port-config = < IMX_AUDMUX_V2_PTCR_SYN @@ -868,7 +868,7 @@ >; }; - ssi2 { + mux-ssi2 { fsl,audmux-port = <1>; fsl,port-config = < (IMX_AUDMUX_V2_PTCR_SYN | @@ -880,7 +880,7 @@ >; }; - aud5 { + mux-aud5 { fsl,audmux-port = <4>; fsl,port-config = < IMX_AUDMUX_V2_PTCR_SYN diff --git a/arch/arm/boot/dts/imx6qdl.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl.dtsi similarity index 99% rename from arch/arm/boot/dts/imx6qdl.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6qdl.dtsi index b72ec745f6d124e1bfd6ae55ef2580c29d9108c6..bda182edc589159f835023e5098f8662c21d1ca3 100644 --- a/arch/arm/boot/dts/imx6qdl.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx6qdl.dtsi @@ -150,7 +150,7 @@ interrupt-parent = <&gpc>; ranges; - dma_apbh: dma-apbh@110000 { + dma_apbh: dma-controller@110000 { compatible = "fsl,imx6q-dma-apbh", "fsl,imx28-dma-apbh"; reg = <0x00110000 0x2000>; interrupts = <0 13 IRQ_TYPE_LEVEL_HIGH>, diff --git a/arch/arm/boot/dts/imx6qp-mba6b.dts b/arch/arm/boot/dts/nxp/imx/imx6qp-mba6b.dts similarity index 100% rename from arch/arm/boot/dts/imx6qp-mba6b.dts rename to arch/arm/boot/dts/nxp/imx/imx6qp-mba6b.dts diff --git a/arch/arm/boot/dts/imx6qp-nitrogen6_max.dts b/arch/arm/boot/dts/nxp/imx/imx6qp-nitrogen6_max.dts similarity index 100% rename from arch/arm/boot/dts/imx6qp-nitrogen6_max.dts rename to arch/arm/boot/dts/nxp/imx/imx6qp-nitrogen6_max.dts diff --git a/arch/arm/boot/dts/imx6qp-nitrogen6_som2.dts b/arch/arm/boot/dts/nxp/imx/imx6qp-nitrogen6_som2.dts similarity index 100% rename from arch/arm/boot/dts/imx6qp-nitrogen6_som2.dts rename to arch/arm/boot/dts/nxp/imx/imx6qp-nitrogen6_som2.dts diff --git a/arch/arm/boot/dts/imx6qp-phytec-mira-rdk-nand.dts b/arch/arm/boot/dts/nxp/imx/imx6qp-phytec-mira-rdk-nand.dts similarity index 100% rename from arch/arm/boot/dts/imx6qp-phytec-mira-rdk-nand.dts rename to arch/arm/boot/dts/nxp/imx/imx6qp-phytec-mira-rdk-nand.dts diff --git a/arch/arm/boot/dts/imx6qp-prtwd3.dts b/arch/arm/boot/dts/nxp/imx/imx6qp-prtwd3.dts similarity index 99% rename from arch/arm/boot/dts/imx6qp-prtwd3.dts rename to arch/arm/boot/dts/nxp/imx/imx6qp-prtwd3.dts index cf6571cc4682e226773b5c996a44cb45b23e57ff..ae00d538a4dfc38bf15bd7a4302b245d8321a87a 100644 --- a/arch/arm/boot/dts/imx6qp-prtwd3.dts +++ b/arch/arm/boot/dts/nxp/imx/imx6qp-prtwd3.dts @@ -350,7 +350,7 @@ pinctrl-0 = <&pinctrl_usbotg>; phy_type = "utmi"; dr_mode = "host"; - disable-over-current; + over-current-active-low; status = "okay"; }; diff --git a/arch/arm/boot/dts/imx6qp-sabreauto.dts b/arch/arm/boot/dts/nxp/imx/imx6qp-sabreauto.dts similarity index 100% rename from arch/arm/boot/dts/imx6qp-sabreauto.dts rename to arch/arm/boot/dts/nxp/imx/imx6qp-sabreauto.dts diff --git a/arch/arm/boot/dts/imx6qp-sabresd.dts b/arch/arm/boot/dts/nxp/imx/imx6qp-sabresd.dts similarity index 100% rename from arch/arm/boot/dts/imx6qp-sabresd.dts rename to arch/arm/boot/dts/nxp/imx/imx6qp-sabresd.dts diff --git a/arch/arm/boot/dts/imx6qp-tqma6b.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qp-tqma6b.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6qp-tqma6b.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6qp-tqma6b.dtsi diff --git a/arch/arm/boot/dts/imx6qp-tx6qp-8037-mb7.dts b/arch/arm/boot/dts/nxp/imx/imx6qp-tx6qp-8037-mb7.dts similarity index 100% rename from arch/arm/boot/dts/imx6qp-tx6qp-8037-mb7.dts rename to arch/arm/boot/dts/nxp/imx/imx6qp-tx6qp-8037-mb7.dts diff --git a/arch/arm/boot/dts/imx6qp-tx6qp-8037.dts b/arch/arm/boot/dts/nxp/imx/imx6qp-tx6qp-8037.dts similarity index 100% rename from arch/arm/boot/dts/imx6qp-tx6qp-8037.dts rename to arch/arm/boot/dts/nxp/imx/imx6qp-tx6qp-8037.dts diff --git a/arch/arm/boot/dts/imx6qp-tx6qp-8137-mb7.dts b/arch/arm/boot/dts/nxp/imx/imx6qp-tx6qp-8137-mb7.dts similarity index 100% rename from arch/arm/boot/dts/imx6qp-tx6qp-8137-mb7.dts rename to arch/arm/boot/dts/nxp/imx/imx6qp-tx6qp-8137-mb7.dts diff --git a/arch/arm/boot/dts/imx6qp-tx6qp-8137.dts b/arch/arm/boot/dts/nxp/imx/imx6qp-tx6qp-8137.dts similarity index 100% rename from arch/arm/boot/dts/imx6qp-tx6qp-8137.dts rename to arch/arm/boot/dts/nxp/imx/imx6qp-tx6qp-8137.dts diff --git a/arch/arm/boot/dts/imx6qp-vicutp.dts b/arch/arm/boot/dts/nxp/imx/imx6qp-vicutp.dts similarity index 100% rename from arch/arm/boot/dts/imx6qp-vicutp.dts rename to arch/arm/boot/dts/nxp/imx/imx6qp-vicutp.dts diff --git a/arch/arm/boot/dts/imx6qp-wandboard-revd1.dts b/arch/arm/boot/dts/nxp/imx/imx6qp-wandboard-revd1.dts similarity index 100% rename from arch/arm/boot/dts/imx6qp-wandboard-revd1.dts rename to arch/arm/boot/dts/nxp/imx/imx6qp-wandboard-revd1.dts diff --git a/arch/arm/boot/dts/imx6qp-yapp4-crux-plus.dts b/arch/arm/boot/dts/nxp/imx/imx6qp-yapp4-crux-plus.dts similarity index 100% rename from arch/arm/boot/dts/imx6qp-yapp4-crux-plus.dts rename to arch/arm/boot/dts/nxp/imx/imx6qp-yapp4-crux-plus.dts diff --git a/arch/arm/boot/dts/imx6qp-yapp4-pegasus-plus.dts b/arch/arm/boot/dts/nxp/imx/imx6qp-yapp4-pegasus-plus.dts similarity index 100% rename from arch/arm/boot/dts/imx6qp-yapp4-pegasus-plus.dts rename to arch/arm/boot/dts/nxp/imx/imx6qp-yapp4-pegasus-plus.dts diff --git a/arch/arm/boot/dts/imx6qp-zii-rdu2.dts b/arch/arm/boot/dts/nxp/imx/imx6qp-zii-rdu2.dts similarity index 100% rename from arch/arm/boot/dts/imx6qp-zii-rdu2.dts rename to arch/arm/boot/dts/nxp/imx/imx6qp-zii-rdu2.dts diff --git a/arch/arm/boot/dts/imx6qp.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qp.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6qp.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6qp.dtsi diff --git a/arch/arm/boot/dts/imx6s-dhcom-drc02.dts b/arch/arm/boot/dts/nxp/imx/imx6s-dhcom-drc02.dts similarity index 100% rename from arch/arm/boot/dts/imx6s-dhcom-drc02.dts rename to arch/arm/boot/dts/nxp/imx/imx6s-dhcom-drc02.dts diff --git a/arch/arm/boot/dts/imx6sl-evk.dts b/arch/arm/boot/dts/nxp/imx/imx6sl-evk.dts similarity index 99% rename from arch/arm/boot/dts/imx6sl-evk.dts rename to arch/arm/boot/dts/nxp/imx/imx6sl-evk.dts index dc5d596c18db4788015c6c5b2d9bc5998e36da3a..239bc6dfc5846475b17ccbf080030959c43eddf2 100644 --- a/arch/arm/boot/dts/imx6sl-evk.dts +++ b/arch/arm/boot/dts/nxp/imx/imx6sl-evk.dts @@ -160,7 +160,7 @@ pinctrl-0 = <&pinctrl_i2c1>; status = "okay"; - pmic: pfuze100@8 { + pmic: pmic@8 { compatible = "fsl,pfuze100"; reg = <0x08>; diff --git a/arch/arm/boot/dts/imx6sl-kobo-aura2.dts b/arch/arm/boot/dts/nxp/imx/imx6sl-kobo-aura2.dts similarity index 100% rename from arch/arm/boot/dts/imx6sl-kobo-aura2.dts rename to arch/arm/boot/dts/nxp/imx/imx6sl-kobo-aura2.dts diff --git a/arch/arm/boot/dts/imx6sl-pinfunc.h b/arch/arm/boot/dts/nxp/imx/imx6sl-pinfunc.h similarity index 100% rename from arch/arm/boot/dts/imx6sl-pinfunc.h rename to arch/arm/boot/dts/nxp/imx/imx6sl-pinfunc.h diff --git a/arch/arm/boot/dts/imx6sl-tolino-shine2hd.dts b/arch/arm/boot/dts/nxp/imx/imx6sl-tolino-shine2hd.dts similarity index 100% rename from arch/arm/boot/dts/imx6sl-tolino-shine2hd.dts rename to arch/arm/boot/dts/nxp/imx/imx6sl-tolino-shine2hd.dts diff --git a/arch/arm/boot/dts/imx6sl-tolino-shine3.dts b/arch/arm/boot/dts/nxp/imx/imx6sl-tolino-shine3.dts similarity index 100% rename from arch/arm/boot/dts/imx6sl-tolino-shine3.dts rename to arch/arm/boot/dts/nxp/imx/imx6sl-tolino-shine3.dts diff --git a/arch/arm/boot/dts/imx6sl-tolino-vision.dts b/arch/arm/boot/dts/nxp/imx/imx6sl-tolino-vision.dts similarity index 100% rename from arch/arm/boot/dts/imx6sl-tolino-vision.dts rename to arch/arm/boot/dts/nxp/imx/imx6sl-tolino-vision.dts diff --git a/arch/arm/boot/dts/imx6sl-tolino-vision5.dts b/arch/arm/boot/dts/nxp/imx/imx6sl-tolino-vision5.dts similarity index 100% rename from arch/arm/boot/dts/imx6sl-tolino-vision5.dts rename to arch/arm/boot/dts/nxp/imx/imx6sl-tolino-vision5.dts diff --git a/arch/arm/boot/dts/imx6sl-warp.dts b/arch/arm/boot/dts/nxp/imx/imx6sl-warp.dts similarity index 100% rename from arch/arm/boot/dts/imx6sl-warp.dts rename to arch/arm/boot/dts/nxp/imx/imx6sl-warp.dts diff --git a/arch/arm/boot/dts/imx6sl.dtsi b/arch/arm/boot/dts/nxp/imx/imx6sl.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6sl.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6sl.dtsi diff --git a/arch/arm/boot/dts/imx6sll-evk.dts b/arch/arm/boot/dts/nxp/imx/imx6sll-evk.dts similarity index 85% rename from arch/arm/boot/dts/imx6sll-evk.dts rename to arch/arm/boot/dts/nxp/imx/imx6sll-evk.dts index 269092ac881c5c4e70e5fbbf8992ec7246ac4f6a..e3e9b0ec4f734af2f660d917f64113a22bceeb9b 100644 --- a/arch/arm/boot/dts/imx6sll-evk.dts +++ b/arch/arm/boot/dts/nxp/imx/imx6sll-evk.dts @@ -109,6 +109,14 @@ enable-active-high; }; + reg_sd2_vmmc: regulator-sd2-vmmc { + compatible = "regulator-fixed"; + regulator-name = "eMMC-VCCQ"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-boot-on; + }; + reg_sd3_vmmc: regulator-sd3-vmmc { compatible = "regulator-fixed"; pinctrl-names = "default"; @@ -343,6 +351,17 @@ status = "okay"; }; +&usdhc2 { + pinctrl-names = "default", "state_100mhz", "state_200mhz"; + pinctrl-0 = <&pinctrl_usdhc2>; + pinctrl-1 = <&pinctrl_usdhc2_100mhz>; + pinctrl-2 = <&pinctrl_usdhc2_200mhz>; + bus-width = <8>; + non-removable; + vqmmc-supply = <®_sd2_vmmc>; + status = "okay"; +}; + &usbotg1 { vbus-supply = <®_usb_otg1_vbus>; pinctrl-names = "default"; @@ -444,7 +463,7 @@ >; }; - pinctrl_usdhc1_100mhz: usdhc1grp_100mhz { + pinctrl_usdhc1_100mhz: usdhc1grp-100mhz { fsl,pins = < MX6SLL_PAD_SD1_CMD__SD1_CMD 0x170b9 MX6SLL_PAD_SD1_CLK__SD1_CLK 0x130b9 @@ -455,7 +474,7 @@ >; }; - pinctrl_usdhc1_200mhz: usdhc1grp_200mhz { + pinctrl_usdhc1_200mhz: usdhc1grp-200mhz { fsl,pins = < MX6SLL_PAD_SD1_CMD__SD1_CMD 0x170f9 MX6SLL_PAD_SD1_CLK__SD1_CLK 0x130f9 @@ -466,6 +485,54 @@ >; }; + pinctrl_usdhc2: usdhc2grp { + fsl,pins = < + MX6SLL_PAD_SD2_CMD__SD2_CMD 0x17059 + MX6SLL_PAD_SD2_CLK__SD2_CLK 0x13059 + MX6SLL_PAD_SD2_DATA0__SD2_DATA0 0x17059 + MX6SLL_PAD_SD2_DATA1__SD2_DATA1 0x17059 + MX6SLL_PAD_SD2_DATA2__SD2_DATA2 0x17059 + MX6SLL_PAD_SD2_DATA3__SD2_DATA3 0x17059 + MX6SLL_PAD_SD2_DATA4__SD2_DATA4 0x17059 + MX6SLL_PAD_SD2_DATA5__SD2_DATA5 0x17059 + MX6SLL_PAD_SD2_DATA6__SD2_DATA6 0x17059 + MX6SLL_PAD_SD2_DATA7__SD2_DATA7 0x17059 + MX6SLL_PAD_GPIO4_IO21__SD2_STROBE 0x13059 + >; + }; + + pinctrl_usdhc2_100mhz: usdhc2grp-100mhz { + fsl,pins = < + MX6SLL_PAD_SD2_CMD__SD2_CMD 0x170b9 + MX6SLL_PAD_SD2_CLK__SD2_CLK 0x130b9 + MX6SLL_PAD_SD2_DATA0__SD2_DATA0 0x170b9 + MX6SLL_PAD_SD2_DATA1__SD2_DATA1 0x170b9 + MX6SLL_PAD_SD2_DATA2__SD2_DATA2 0x170b9 + MX6SLL_PAD_SD2_DATA3__SD2_DATA3 0x170b9 + MX6SLL_PAD_SD2_DATA4__SD2_DATA4 0x170b9 + MX6SLL_PAD_SD2_DATA5__SD2_DATA5 0x170b9 + MX6SLL_PAD_SD2_DATA6__SD2_DATA6 0x170b9 + MX6SLL_PAD_SD2_DATA7__SD2_DATA7 0x170b9 + MX6SLL_PAD_GPIO4_IO21__SD2_STROBE 0x130b9 + >; + }; + + pinctrl_usdhc2_200mhz: usdhc2grp-200mhz { + fsl,pins = < + MX6SLL_PAD_SD2_CMD__SD2_CMD 0x170f9 + MX6SLL_PAD_SD2_CLK__SD2_CLK 0x130f9 + MX6SLL_PAD_SD2_DATA0__SD2_DATA0 0x170f9 + MX6SLL_PAD_SD2_DATA1__SD2_DATA1 0x170f9 + MX6SLL_PAD_SD2_DATA2__SD2_DATA2 0x170f9 + MX6SLL_PAD_SD2_DATA3__SD2_DATA3 0x170f9 + MX6SLL_PAD_SD2_DATA4__SD2_DATA4 0x170f9 + MX6SLL_PAD_SD2_DATA5__SD2_DATA5 0x170f9 + MX6SLL_PAD_SD2_DATA6__SD2_DATA6 0x170f9 + MX6SLL_PAD_SD2_DATA7__SD2_DATA7 0x170f9 + MX6SLL_PAD_GPIO4_IO21__SD2_STROBE 0x130f9 + >; + }; + pinctrl_usbotg1: usbotg1grp { fsl,pins = < MX6SLL_PAD_EPDC_PWR_COM__USB_OTG1_ID 0x17059 @@ -484,7 +551,7 @@ >; }; - pinctrl_usdhc3_100mhz: usdhc3grp_100mhz { + pinctrl_usdhc3_100mhz: usdhc3grp-100mhz { fsl,pins = < MX6SLL_PAD_SD3_CMD__SD3_CMD 0x170a1 MX6SLL_PAD_SD3_CLK__SD3_CLK 0x130a1 @@ -496,7 +563,7 @@ >; }; - pinctrl_usdhc3_200mhz: usdhc3grp_200mhz { + pinctrl_usdhc3_200mhz: usdhc3grp-200mhz { fsl,pins = < MX6SLL_PAD_SD3_CMD__SD3_CMD 0x170e9 MX6SLL_PAD_SD3_CLK__SD3_CLK 0x130f9 diff --git a/arch/arm/boot/dts/imx6sll-kobo-clarahd.dts b/arch/arm/boot/dts/nxp/imx/imx6sll-kobo-clarahd.dts similarity index 100% rename from arch/arm/boot/dts/imx6sll-kobo-clarahd.dts rename to arch/arm/boot/dts/nxp/imx/imx6sll-kobo-clarahd.dts diff --git a/arch/arm/boot/dts/imx6sll-kobo-librah2o.dts b/arch/arm/boot/dts/nxp/imx/imx6sll-kobo-librah2o.dts similarity index 100% rename from arch/arm/boot/dts/imx6sll-kobo-librah2o.dts rename to arch/arm/boot/dts/nxp/imx/imx6sll-kobo-librah2o.dts diff --git a/arch/arm/boot/dts/imx6sll-pinfunc.h b/arch/arm/boot/dts/nxp/imx/imx6sll-pinfunc.h similarity index 100% rename from arch/arm/boot/dts/imx6sll-pinfunc.h rename to arch/arm/boot/dts/nxp/imx/imx6sll-pinfunc.h diff --git a/arch/arm/boot/dts/imx6sll.dtsi b/arch/arm/boot/dts/nxp/imx/imx6sll.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6sll.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6sll.dtsi diff --git a/arch/arm/boot/dts/imx6sx-nitrogen6sx.dts b/arch/arm/boot/dts/nxp/imx/imx6sx-nitrogen6sx.dts similarity index 100% rename from arch/arm/boot/dts/imx6sx-nitrogen6sx.dts rename to arch/arm/boot/dts/nxp/imx/imx6sx-nitrogen6sx.dts diff --git a/arch/arm/boot/dts/imx6sx-pinfunc.h b/arch/arm/boot/dts/nxp/imx/imx6sx-pinfunc.h similarity index 100% rename from arch/arm/boot/dts/imx6sx-pinfunc.h rename to arch/arm/boot/dts/nxp/imx/imx6sx-pinfunc.h diff --git a/arch/arm/boot/dts/imx6sx-sabreauto.dts b/arch/arm/boot/dts/nxp/imx/imx6sx-sabreauto.dts similarity index 100% rename from arch/arm/boot/dts/imx6sx-sabreauto.dts rename to arch/arm/boot/dts/nxp/imx/imx6sx-sabreauto.dts diff --git a/arch/arm/boot/dts/imx6sx-sdb-mqs.dts b/arch/arm/boot/dts/nxp/imx/imx6sx-sdb-mqs.dts similarity index 100% rename from arch/arm/boot/dts/imx6sx-sdb-mqs.dts rename to arch/arm/boot/dts/nxp/imx/imx6sx-sdb-mqs.dts diff --git a/arch/arm/boot/dts/imx6sx-sdb-reva.dts b/arch/arm/boot/dts/nxp/imx/imx6sx-sdb-reva.dts similarity index 99% rename from arch/arm/boot/dts/imx6sx-sdb-reva.dts rename to arch/arm/boot/dts/nxp/imx/imx6sx-sdb-reva.dts index 7dda42553f4bce7db387d112b8dab738525628d9..48f19dede467f7f8a10ce972116af754f1f1b4d1 100644 --- a/arch/arm/boot/dts/imx6sx-sdb-reva.dts +++ b/arch/arm/boot/dts/nxp/imx/imx6sx-sdb-reva.dts @@ -15,7 +15,7 @@ pinctrl-0 = <&pinctrl_i2c1>; status = "okay"; - pmic: pfuze100@8 { + pmic: pmic@8 { compatible = "fsl,pfuze100"; reg = <0x08>; diff --git a/arch/arm/boot/dts/imx6sx-sdb-sai.dts b/arch/arm/boot/dts/nxp/imx/imx6sx-sdb-sai.dts similarity index 100% rename from arch/arm/boot/dts/imx6sx-sdb-sai.dts rename to arch/arm/boot/dts/nxp/imx/imx6sx-sdb-sai.dts diff --git a/arch/arm/boot/dts/imx6sx-sdb.dts b/arch/arm/boot/dts/nxp/imx/imx6sx-sdb.dts similarity index 99% rename from arch/arm/boot/dts/imx6sx-sdb.dts rename to arch/arm/boot/dts/nxp/imx/imx6sx-sdb.dts index 969cfe920d252f61cc71c38cc4f32492b4d61728..e05a1be5553c878b6d109e50b7358bb781c03cd5 100644 --- a/arch/arm/boot/dts/imx6sx-sdb.dts +++ b/arch/arm/boot/dts/nxp/imx/imx6sx-sdb.dts @@ -14,7 +14,7 @@ pinctrl-0 = <&pinctrl_i2c1>; status = "okay"; - pmic: pfuze100@8 { + pmic: pmic@8 { compatible = "fsl,pfuze200"; reg = <0x08>; diff --git a/arch/arm/boot/dts/imx6sx-sdb.dtsi b/arch/arm/boot/dts/nxp/imx/imx6sx-sdb.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6sx-sdb.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6sx-sdb.dtsi diff --git a/arch/arm/boot/dts/imx6sx-softing-vining-2000.dts b/arch/arm/boot/dts/nxp/imx/imx6sx-softing-vining-2000.dts similarity index 99% rename from arch/arm/boot/dts/imx6sx-softing-vining-2000.dts rename to arch/arm/boot/dts/nxp/imx/imx6sx-softing-vining-2000.dts index b9a1401e6c6d2d0e8ffe2b019476ace076294925..bfcd8f7d86dde104035a9f4659c214782c847260 100644 --- a/arch/arm/boot/dts/imx6sx-softing-vining-2000.dts +++ b/arch/arm/boot/dts/nxp/imx/imx6sx-softing-vining-2000.dts @@ -171,7 +171,7 @@ reset-gpios = <&gpio2 10 GPIO_ACTIVE_HIGH>; }; - pmic: pfuze100@8 { + pmic: pmic@8 { compatible = "fsl,pfuze200"; reg = <0x08>; diff --git a/arch/arm/boot/dts/imx6sx-udoo-neo-basic.dts b/arch/arm/boot/dts/nxp/imx/imx6sx-udoo-neo-basic.dts similarity index 100% rename from arch/arm/boot/dts/imx6sx-udoo-neo-basic.dts rename to arch/arm/boot/dts/nxp/imx/imx6sx-udoo-neo-basic.dts diff --git a/arch/arm/boot/dts/imx6sx-udoo-neo-extended.dts b/arch/arm/boot/dts/nxp/imx/imx6sx-udoo-neo-extended.dts similarity index 100% rename from arch/arm/boot/dts/imx6sx-udoo-neo-extended.dts rename to arch/arm/boot/dts/nxp/imx/imx6sx-udoo-neo-extended.dts diff --git a/arch/arm/boot/dts/imx6sx-udoo-neo-full.dts b/arch/arm/boot/dts/nxp/imx/imx6sx-udoo-neo-full.dts similarity index 100% rename from arch/arm/boot/dts/imx6sx-udoo-neo-full.dts rename to arch/arm/boot/dts/nxp/imx/imx6sx-udoo-neo-full.dts diff --git a/arch/arm/boot/dts/imx6sx-udoo-neo.dtsi b/arch/arm/boot/dts/nxp/imx/imx6sx-udoo-neo.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6sx-udoo-neo.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6sx-udoo-neo.dtsi diff --git a/arch/arm/boot/dts/imx6sx.dtsi b/arch/arm/boot/dts/nxp/imx/imx6sx.dtsi similarity index 98% rename from arch/arm/boot/dts/imx6sx.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6sx.dtsi index 93ac2380ca1ec6445f85b0b6bf215d57393971a6..3a430866655222703d374d5a86fbfb1940db115a 100644 --- a/arch/arm/boot/dts/imx6sx.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx6sx.dtsi @@ -209,7 +209,7 @@ power-domains = <&pd_pu>; }; - dma_apbh: dma-apbh@1804000 { + dma_apbh: dma-controller@1804000 { compatible = "fsl,imx6sx-dma-apbh", "fsl,imx28-dma-apbh"; reg = <0x01804000 0x2000>; interrupts = , @@ -841,10 +841,40 @@ reg = <0x020e0000 0x4000>; }; - gpr: iomuxc-gpr@20e4000 { + gpr: syscon@20e4000 { compatible = "fsl,imx6sx-iomuxc-gpr", - "fsl,imx6q-iomuxc-gpr", "syscon"; + "fsl,imx6q-iomuxc-gpr", "syscon", "simple-mfd"; + #address-cells = <1>; + #size-cells = <1>; reg = <0x020e4000 0x4000>; + + lvds_bridge: bridge@18 { + compatible = "fsl,imx6sx-ldb"; + reg = <0x18 0x4>; + clocks = <&clks IMX6SX_CLK_LDB_DI0>; + clock-names = "ldb"; + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + ldb_from_lcdif1: endpoint { + remote-endpoint = <&lcdif1_to_ldb>; + }; + }; + + port@1 { + reg = <1>; + + ldb_lvds_ch0: endpoint { + }; + }; + }; + }; }; sdma: dma-controller@20ec000 { @@ -1278,6 +1308,14 @@ clock-names = "pix", "axi", "disp_axi"; power-domains = <&pd_disp>; status = "disabled"; + + ports { + port { + lcdif1_to_ldb: endpoint { + remote-endpoint = <&ldb_from_lcdif1>; + }; + }; + }; }; lcdif2: lcdif@2224000 { diff --git a/arch/arm/boot/dts/imx6ul-14x14-evk.dts b/arch/arm/boot/dts/nxp/imx/imx6ul-14x14-evk.dts similarity index 100% rename from arch/arm/boot/dts/imx6ul-14x14-evk.dts rename to arch/arm/boot/dts/nxp/imx/imx6ul-14x14-evk.dts diff --git a/arch/arm/boot/dts/imx6ul-14x14-evk.dtsi b/arch/arm/boot/dts/nxp/imx/imx6ul-14x14-evk.dtsi similarity index 99% rename from arch/arm/boot/dts/imx6ul-14x14-evk.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6ul-14x14-evk.dtsi index 7275a13664135db8f7e1896ad0245c1156fc3397..155515fe13fadbc342a20dc939f7e32260ab01bb 100644 --- a/arch/arm/boot/dts/imx6ul-14x14-evk.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx6ul-14x14-evk.dtsi @@ -89,8 +89,8 @@ pinctrl-names = "default"; pinctrl-0 = <&pinctrl_spi4>; status = "okay"; - gpio-sck = <&gpio5 11 0>; - gpio-mosi = <&gpio5 10 0>; + sck-gpios = <&gpio5 11 0>; + mosi-gpios = <&gpio5 10 0>; cs-gpios = <&gpio5 7 GPIO_ACTIVE_LOW>; num-chipselects = <1>; #address-cells = <1>; diff --git a/arch/arm/boot/dts/imx6ul-ccimx6ulsbcexpress.dts b/arch/arm/boot/dts/nxp/imx/imx6ul-ccimx6ulsbcexpress.dts similarity index 100% rename from arch/arm/boot/dts/imx6ul-ccimx6ulsbcexpress.dts rename to arch/arm/boot/dts/nxp/imx/imx6ul-ccimx6ulsbcexpress.dts diff --git a/arch/arm/boot/dts/imx6ul-ccimx6ulsbcpro.dts b/arch/arm/boot/dts/nxp/imx/imx6ul-ccimx6ulsbcpro.dts similarity index 100% rename from arch/arm/boot/dts/imx6ul-ccimx6ulsbcpro.dts rename to arch/arm/boot/dts/nxp/imx/imx6ul-ccimx6ulsbcpro.dts diff --git a/arch/arm/boot/dts/imx6ul-ccimx6ulsom.dtsi b/arch/arm/boot/dts/nxp/imx/imx6ul-ccimx6ulsom.dtsi similarity index 99% rename from arch/arm/boot/dts/imx6ul-ccimx6ulsom.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6ul-ccimx6ulsom.dtsi index b5781c3656d1a7c334cf8c55a56aa94355e2fe96..7d1a391431bd9a16adc4578d9a9587c7378c0a35 100644 --- a/arch/arm/boot/dts/imx6ul-ccimx6ulsom.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx6ul-ccimx6ulsom.dtsi @@ -158,7 +158,7 @@ regulator-max-microvolt = <3300000>; }; - vcoin_chg: vcoin { + vcoin_chg: coin { regulator-min-microvolt = <2500000>; regulator-max-microvolt = <3300000>; }; diff --git a/arch/arm/boot/dts/imx6ul-geam.dts b/arch/arm/boot/dts/nxp/imx/imx6ul-geam.dts similarity index 100% rename from arch/arm/boot/dts/imx6ul-geam.dts rename to arch/arm/boot/dts/nxp/imx/imx6ul-geam.dts diff --git a/arch/arm/boot/dts/imx6ul-imx6ull-opos6ul.dtsi b/arch/arm/boot/dts/nxp/imx/imx6ul-imx6ull-opos6ul.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6ul-imx6ull-opos6ul.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6ul-imx6ull-opos6ul.dtsi diff --git a/arch/arm/boot/dts/imx6ul-imx6ull-opos6uldev.dtsi b/arch/arm/boot/dts/nxp/imx/imx6ul-imx6ull-opos6uldev.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6ul-imx6ull-opos6uldev.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6ul-imx6ull-opos6uldev.dtsi diff --git a/arch/arm/boot/dts/imx6ul-isiot-emmc.dts b/arch/arm/boot/dts/nxp/imx/imx6ul-isiot-emmc.dts similarity index 100% rename from arch/arm/boot/dts/imx6ul-isiot-emmc.dts rename to arch/arm/boot/dts/nxp/imx/imx6ul-isiot-emmc.dts diff --git a/arch/arm/boot/dts/imx6ul-isiot-nand.dts b/arch/arm/boot/dts/nxp/imx/imx6ul-isiot-nand.dts similarity index 100% rename from arch/arm/boot/dts/imx6ul-isiot-nand.dts rename to arch/arm/boot/dts/nxp/imx/imx6ul-isiot-nand.dts diff --git a/arch/arm/boot/dts/imx6ul-isiot.dtsi b/arch/arm/boot/dts/nxp/imx/imx6ul-isiot.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6ul-isiot.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6ul-isiot.dtsi diff --git a/arch/arm/boot/dts/imx6ul-kontron-bl-43.dts b/arch/arm/boot/dts/nxp/imx/imx6ul-kontron-bl-43.dts similarity index 100% rename from arch/arm/boot/dts/imx6ul-kontron-bl-43.dts rename to arch/arm/boot/dts/nxp/imx/imx6ul-kontron-bl-43.dts diff --git a/arch/arm/boot/dts/imx6ul-kontron-bl-common.dtsi b/arch/arm/boot/dts/nxp/imx/imx6ul-kontron-bl-common.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6ul-kontron-bl-common.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6ul-kontron-bl-common.dtsi diff --git a/arch/arm/boot/dts/imx6ul-kontron-bl.dts b/arch/arm/boot/dts/nxp/imx/imx6ul-kontron-bl.dts similarity index 100% rename from arch/arm/boot/dts/imx6ul-kontron-bl.dts rename to arch/arm/boot/dts/nxp/imx/imx6ul-kontron-bl.dts diff --git a/arch/arm/boot/dts/imx6ul-kontron-sl-common.dtsi b/arch/arm/boot/dts/nxp/imx/imx6ul-kontron-sl-common.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6ul-kontron-sl-common.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6ul-kontron-sl-common.dtsi diff --git a/arch/arm/boot/dts/imx6ul-kontron-sl.dtsi b/arch/arm/boot/dts/nxp/imx/imx6ul-kontron-sl.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6ul-kontron-sl.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6ul-kontron-sl.dtsi diff --git a/arch/arm/boot/dts/imx6ul-liteboard.dts b/arch/arm/boot/dts/nxp/imx/imx6ul-liteboard.dts similarity index 100% rename from arch/arm/boot/dts/imx6ul-liteboard.dts rename to arch/arm/boot/dts/nxp/imx/imx6ul-liteboard.dts diff --git a/arch/arm/boot/dts/imx6ul-litesom.dtsi b/arch/arm/boot/dts/nxp/imx/imx6ul-litesom.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6ul-litesom.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6ul-litesom.dtsi diff --git a/arch/arm/boot/dts/imx6ul-opos6ul.dtsi b/arch/arm/boot/dts/nxp/imx/imx6ul-opos6ul.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6ul-opos6ul.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6ul-opos6ul.dtsi diff --git a/arch/arm/boot/dts/imx6ul-opos6uldev.dts b/arch/arm/boot/dts/nxp/imx/imx6ul-opos6uldev.dts similarity index 100% rename from arch/arm/boot/dts/imx6ul-opos6uldev.dts rename to arch/arm/boot/dts/nxp/imx/imx6ul-opos6uldev.dts diff --git a/arch/arm/boot/dts/imx6ul-phytec-phycore-som.dtsi b/arch/arm/boot/dts/nxp/imx/imx6ul-phytec-phycore-som.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6ul-phytec-phycore-som.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6ul-phytec-phycore-som.dtsi diff --git a/arch/arm/boot/dts/imx6ul-phytec-segin-ff-rdk-emmc.dts b/arch/arm/boot/dts/nxp/imx/imx6ul-phytec-segin-ff-rdk-emmc.dts similarity index 100% rename from arch/arm/boot/dts/imx6ul-phytec-segin-ff-rdk-emmc.dts rename to arch/arm/boot/dts/nxp/imx/imx6ul-phytec-segin-ff-rdk-emmc.dts diff --git a/arch/arm/boot/dts/imx6ul-phytec-segin-ff-rdk-nand.dts b/arch/arm/boot/dts/nxp/imx/imx6ul-phytec-segin-ff-rdk-nand.dts similarity index 100% rename from arch/arm/boot/dts/imx6ul-phytec-segin-ff-rdk-nand.dts rename to arch/arm/boot/dts/nxp/imx/imx6ul-phytec-segin-ff-rdk-nand.dts diff --git a/arch/arm/boot/dts/imx6ul-phytec-segin-peb-av-02.dtsi b/arch/arm/boot/dts/nxp/imx/imx6ul-phytec-segin-peb-av-02.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6ul-phytec-segin-peb-av-02.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6ul-phytec-segin-peb-av-02.dtsi diff --git a/arch/arm/boot/dts/imx6ul-phytec-segin-peb-eval-01.dtsi b/arch/arm/boot/dts/nxp/imx/imx6ul-phytec-segin-peb-eval-01.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6ul-phytec-segin-peb-eval-01.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6ul-phytec-segin-peb-eval-01.dtsi diff --git a/arch/arm/boot/dts/imx6ul-phytec-segin-peb-wlbt-05.dtsi b/arch/arm/boot/dts/nxp/imx/imx6ul-phytec-segin-peb-wlbt-05.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6ul-phytec-segin-peb-wlbt-05.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6ul-phytec-segin-peb-wlbt-05.dtsi diff --git a/arch/arm/boot/dts/imx6ul-phytec-segin.dtsi b/arch/arm/boot/dts/nxp/imx/imx6ul-phytec-segin.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6ul-phytec-segin.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6ul-phytec-segin.dtsi diff --git a/arch/arm/boot/dts/imx6ul-pico-dwarf.dts b/arch/arm/boot/dts/nxp/imx/imx6ul-pico-dwarf.dts similarity index 100% rename from arch/arm/boot/dts/imx6ul-pico-dwarf.dts rename to arch/arm/boot/dts/nxp/imx/imx6ul-pico-dwarf.dts diff --git a/arch/arm/boot/dts/imx6ul-pico-hobbit.dts b/arch/arm/boot/dts/nxp/imx/imx6ul-pico-hobbit.dts similarity index 100% rename from arch/arm/boot/dts/imx6ul-pico-hobbit.dts rename to arch/arm/boot/dts/nxp/imx/imx6ul-pico-hobbit.dts diff --git a/arch/arm/boot/dts/imx6ul-pico-pi.dts b/arch/arm/boot/dts/nxp/imx/imx6ul-pico-pi.dts similarity index 100% rename from arch/arm/boot/dts/imx6ul-pico-pi.dts rename to arch/arm/boot/dts/nxp/imx/imx6ul-pico-pi.dts diff --git a/arch/arm/boot/dts/imx6ul-pico.dtsi b/arch/arm/boot/dts/nxp/imx/imx6ul-pico.dtsi similarity index 99% rename from arch/arm/boot/dts/imx6ul-pico.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6ul-pico.dtsi index 357ffb2f5ad6125b625733a8047cd0dc897afa81..4ffe99ed55ca2c000efd480ee54a914cb9c2b14b 100644 --- a/arch/arm/boot/dts/imx6ul-pico.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx6ul-pico.dtsi @@ -131,7 +131,7 @@ pinctrl-0 = <&pinctrl_i2c1>; status = "okay"; - pmic: pfuze3000@8 { + pmic: pmic@8 { compatible = "fsl,pfuze3000"; reg = <0x08>; diff --git a/arch/arm/boot/dts/imx6ul-pinfunc.h b/arch/arm/boot/dts/nxp/imx/imx6ul-pinfunc.h similarity index 100% rename from arch/arm/boot/dts/imx6ul-pinfunc.h rename to arch/arm/boot/dts/nxp/imx/imx6ul-pinfunc.h diff --git a/arch/arm/boot/dts/imx6ul-prti6g.dts b/arch/arm/boot/dts/nxp/imx/imx6ul-prti6g.dts similarity index 99% rename from arch/arm/boot/dts/imx6ul-prti6g.dts rename to arch/arm/boot/dts/nxp/imx/imx6ul-prti6g.dts index b7c96fbe7a919f443aca3a47748ac509785f211e..c3c50f51a5a864a3f00f6d49435e10c898fecd9b 100644 --- a/arch/arm/boot/dts/imx6ul-prti6g.dts +++ b/arch/arm/boot/dts/nxp/imx/imx6ul-prti6g.dts @@ -177,6 +177,7 @@ &usbotg1 { dr_mode = "host"; + over-current-active-low; status = "okay"; }; diff --git a/arch/arm/boot/dts/imx6ul-tqma6ul-common.dtsi b/arch/arm/boot/dts/nxp/imx/imx6ul-tqma6ul-common.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6ul-tqma6ul-common.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6ul-tqma6ul-common.dtsi diff --git a/arch/arm/boot/dts/imx6ul-tqma6ul1-mba6ulx.dts b/arch/arm/boot/dts/nxp/imx/imx6ul-tqma6ul1-mba6ulx.dts similarity index 100% rename from arch/arm/boot/dts/imx6ul-tqma6ul1-mba6ulx.dts rename to arch/arm/boot/dts/nxp/imx/imx6ul-tqma6ul1-mba6ulx.dts diff --git a/arch/arm/boot/dts/imx6ul-tqma6ul1.dtsi b/arch/arm/boot/dts/nxp/imx/imx6ul-tqma6ul1.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6ul-tqma6ul1.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6ul-tqma6ul1.dtsi diff --git a/arch/arm/boot/dts/imx6ul-tqma6ul2-mba6ulx.dts b/arch/arm/boot/dts/nxp/imx/imx6ul-tqma6ul2-mba6ulx.dts similarity index 100% rename from arch/arm/boot/dts/imx6ul-tqma6ul2-mba6ulx.dts rename to arch/arm/boot/dts/nxp/imx/imx6ul-tqma6ul2-mba6ulx.dts diff --git a/arch/arm/boot/dts/imx6ul-tqma6ul2.dtsi b/arch/arm/boot/dts/nxp/imx/imx6ul-tqma6ul2.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6ul-tqma6ul2.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6ul-tqma6ul2.dtsi diff --git a/arch/arm/boot/dts/imx6ul-tqma6ul2l-mba6ulx.dts b/arch/arm/boot/dts/nxp/imx/imx6ul-tqma6ul2l-mba6ulx.dts similarity index 100% rename from arch/arm/boot/dts/imx6ul-tqma6ul2l-mba6ulx.dts rename to arch/arm/boot/dts/nxp/imx/imx6ul-tqma6ul2l-mba6ulx.dts diff --git a/arch/arm/boot/dts/imx6ul-tqma6ul2l.dtsi b/arch/arm/boot/dts/nxp/imx/imx6ul-tqma6ul2l.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6ul-tqma6ul2l.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6ul-tqma6ul2l.dtsi diff --git a/arch/arm/boot/dts/imx6ul-tqma6ulx-common.dtsi b/arch/arm/boot/dts/nxp/imx/imx6ul-tqma6ulx-common.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6ul-tqma6ulx-common.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6ul-tqma6ulx-common.dtsi diff --git a/arch/arm/boot/dts/imx6ul-tqma6ulxl-common.dtsi b/arch/arm/boot/dts/nxp/imx/imx6ul-tqma6ulxl-common.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6ul-tqma6ulxl-common.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6ul-tqma6ulxl-common.dtsi diff --git a/arch/arm/boot/dts/imx6ul-tx6ul-0010.dts b/arch/arm/boot/dts/nxp/imx/imx6ul-tx6ul-0010.dts similarity index 100% rename from arch/arm/boot/dts/imx6ul-tx6ul-0010.dts rename to arch/arm/boot/dts/nxp/imx/imx6ul-tx6ul-0010.dts diff --git a/arch/arm/boot/dts/imx6ul-tx6ul-0011.dts b/arch/arm/boot/dts/nxp/imx/imx6ul-tx6ul-0011.dts similarity index 100% rename from arch/arm/boot/dts/imx6ul-tx6ul-0011.dts rename to arch/arm/boot/dts/nxp/imx/imx6ul-tx6ul-0011.dts diff --git a/arch/arm/boot/dts/imx6ul-tx6ul-mainboard.dts b/arch/arm/boot/dts/nxp/imx/imx6ul-tx6ul-mainboard.dts similarity index 100% rename from arch/arm/boot/dts/imx6ul-tx6ul-mainboard.dts rename to arch/arm/boot/dts/nxp/imx/imx6ul-tx6ul-mainboard.dts diff --git a/arch/arm/boot/dts/imx6ul-tx6ul.dtsi b/arch/arm/boot/dts/nxp/imx/imx6ul-tx6ul.dtsi similarity index 99% rename from arch/arm/boot/dts/imx6ul-tx6ul.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6ul-tx6ul.dtsi index 70cef5e817bd107f38d0b367fb1c99c28265ce32..6bd90473050b002ea6fd20a369788ff1f48ed6e6 100644 --- a/arch/arm/boot/dts/imx6ul-tx6ul.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx6ul-tx6ul.dtsi @@ -218,9 +218,9 @@ compatible = "spi-gpio"; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_spi_gpio>; - gpio-mosi = <&gpio1 30 GPIO_ACTIVE_HIGH>; - gpio-miso = <&gpio1 31 GPIO_ACTIVE_HIGH>; - gpio-sck = <&gpio1 28 GPIO_ACTIVE_HIGH>; + mosi-gpios = <&gpio1 30 GPIO_ACTIVE_HIGH>; + miso-gpios = <&gpio1 31 GPIO_ACTIVE_HIGH>; + sck-gpios = <&gpio1 28 GPIO_ACTIVE_HIGH>; num-chipselects = <2>; cs-gpios = < &gpio1 29 GPIO_ACTIVE_HIGH diff --git a/arch/arm/boot/dts/imx6ul.dtsi b/arch/arm/boot/dts/nxp/imx/imx6ul.dtsi similarity index 99% rename from arch/arm/boot/dts/imx6ul.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6ul.dtsi index 3d9d0f823568507f05a99700abcffa30598885db..0174f3edbd1621513b1566a48290a615cb345fe7 100644 --- a/arch/arm/boot/dts/imx6ul.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx6ul.dtsi @@ -164,7 +164,7 @@ <0x00a06000 0x2000>; }; - dma_apbh: dma-apbh@1804000 { + dma_apbh: dma-controller@1804000 { compatible = "fsl,imx6q-dma-apbh", "fsl,imx28-dma-apbh"; reg = <0x01804000 0x2000>; interrupts = <0 13 IRQ_TYPE_LEVEL_HIGH>, @@ -719,6 +719,18 @@ #interrupt-cells = <3>; interrupts = ; interrupt-parent = <&intc>; + clocks = <&clks IMX6UL_CLK_IPG>; + clock-names = "ipg"; + + pgc { + #address-cells = <1>; + #size-cells = <0>; + + power-domain@0 { + reg = <0>; + #power-domain-cells = <0>; + }; + }; }; iomuxc: pinctrl@20e0000 { diff --git a/arch/arm/boot/dts/imx6ull-14x14-evk.dts b/arch/arm/boot/dts/nxp/imx/imx6ull-14x14-evk.dts similarity index 100% rename from arch/arm/boot/dts/imx6ull-14x14-evk.dts rename to arch/arm/boot/dts/nxp/imx/imx6ull-14x14-evk.dts diff --git a/arch/arm/boot/dts/imx6ull-colibri-aster.dts b/arch/arm/boot/dts/nxp/imx/imx6ull-colibri-aster.dts similarity index 100% rename from arch/arm/boot/dts/imx6ull-colibri-aster.dts rename to arch/arm/boot/dts/nxp/imx/imx6ull-colibri-aster.dts diff --git a/arch/arm/boot/dts/imx6ull-colibri-aster.dtsi b/arch/arm/boot/dts/nxp/imx/imx6ull-colibri-aster.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6ull-colibri-aster.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6ull-colibri-aster.dtsi diff --git a/arch/arm/boot/dts/imx6ull-colibri-emmc-aster.dts b/arch/arm/boot/dts/nxp/imx/imx6ull-colibri-emmc-aster.dts similarity index 100% rename from arch/arm/boot/dts/imx6ull-colibri-emmc-aster.dts rename to arch/arm/boot/dts/nxp/imx/imx6ull-colibri-emmc-aster.dts diff --git a/arch/arm/boot/dts/imx6ull-colibri-emmc-eval-v3.dts b/arch/arm/boot/dts/nxp/imx/imx6ull-colibri-emmc-eval-v3.dts similarity index 100% rename from arch/arm/boot/dts/imx6ull-colibri-emmc-eval-v3.dts rename to arch/arm/boot/dts/nxp/imx/imx6ull-colibri-emmc-eval-v3.dts diff --git a/arch/arm/boot/dts/imx6ull-colibri-emmc-iris-v2.dts b/arch/arm/boot/dts/nxp/imx/imx6ull-colibri-emmc-iris-v2.dts similarity index 100% rename from arch/arm/boot/dts/imx6ull-colibri-emmc-iris-v2.dts rename to arch/arm/boot/dts/nxp/imx/imx6ull-colibri-emmc-iris-v2.dts diff --git a/arch/arm/boot/dts/imx6ull-colibri-emmc-iris.dts b/arch/arm/boot/dts/nxp/imx/imx6ull-colibri-emmc-iris.dts similarity index 100% rename from arch/arm/boot/dts/imx6ull-colibri-emmc-iris.dts rename to arch/arm/boot/dts/nxp/imx/imx6ull-colibri-emmc-iris.dts diff --git a/arch/arm/boot/dts/imx6ull-colibri-emmc-nonwifi.dtsi b/arch/arm/boot/dts/nxp/imx/imx6ull-colibri-emmc-nonwifi.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6ull-colibri-emmc-nonwifi.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6ull-colibri-emmc-nonwifi.dtsi diff --git a/arch/arm/boot/dts/imx6ull-colibri-eval-v3.dts b/arch/arm/boot/dts/nxp/imx/imx6ull-colibri-eval-v3.dts similarity index 100% rename from arch/arm/boot/dts/imx6ull-colibri-eval-v3.dts rename to arch/arm/boot/dts/nxp/imx/imx6ull-colibri-eval-v3.dts diff --git a/arch/arm/boot/dts/imx6ull-colibri-eval-v3.dtsi b/arch/arm/boot/dts/nxp/imx/imx6ull-colibri-eval-v3.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6ull-colibri-eval-v3.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6ull-colibri-eval-v3.dtsi diff --git a/arch/arm/boot/dts/imx6ull-colibri-iris-v2.dts b/arch/arm/boot/dts/nxp/imx/imx6ull-colibri-iris-v2.dts similarity index 100% rename from arch/arm/boot/dts/imx6ull-colibri-iris-v2.dts rename to arch/arm/boot/dts/nxp/imx/imx6ull-colibri-iris-v2.dts diff --git a/arch/arm/boot/dts/imx6ull-colibri-iris-v2.dtsi b/arch/arm/boot/dts/nxp/imx/imx6ull-colibri-iris-v2.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6ull-colibri-iris-v2.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6ull-colibri-iris-v2.dtsi diff --git a/arch/arm/boot/dts/imx6ull-colibri-iris.dts b/arch/arm/boot/dts/nxp/imx/imx6ull-colibri-iris.dts similarity index 100% rename from arch/arm/boot/dts/imx6ull-colibri-iris.dts rename to arch/arm/boot/dts/nxp/imx/imx6ull-colibri-iris.dts diff --git a/arch/arm/boot/dts/imx6ull-colibri-iris.dtsi b/arch/arm/boot/dts/nxp/imx/imx6ull-colibri-iris.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6ull-colibri-iris.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6ull-colibri-iris.dtsi diff --git a/arch/arm/boot/dts/imx6ull-colibri-nonwifi.dtsi b/arch/arm/boot/dts/nxp/imx/imx6ull-colibri-nonwifi.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6ull-colibri-nonwifi.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6ull-colibri-nonwifi.dtsi diff --git a/arch/arm/boot/dts/imx6ull-colibri-wifi-aster.dts b/arch/arm/boot/dts/nxp/imx/imx6ull-colibri-wifi-aster.dts similarity index 100% rename from arch/arm/boot/dts/imx6ull-colibri-wifi-aster.dts rename to arch/arm/boot/dts/nxp/imx/imx6ull-colibri-wifi-aster.dts diff --git a/arch/arm/boot/dts/imx6ull-colibri-wifi-eval-v3.dts b/arch/arm/boot/dts/nxp/imx/imx6ull-colibri-wifi-eval-v3.dts similarity index 100% rename from arch/arm/boot/dts/imx6ull-colibri-wifi-eval-v3.dts rename to arch/arm/boot/dts/nxp/imx/imx6ull-colibri-wifi-eval-v3.dts diff --git a/arch/arm/boot/dts/imx6ull-colibri-wifi-iris-v2.dts b/arch/arm/boot/dts/nxp/imx/imx6ull-colibri-wifi-iris-v2.dts similarity index 100% rename from arch/arm/boot/dts/imx6ull-colibri-wifi-iris-v2.dts rename to arch/arm/boot/dts/nxp/imx/imx6ull-colibri-wifi-iris-v2.dts diff --git a/arch/arm/boot/dts/imx6ull-colibri-wifi-iris.dts b/arch/arm/boot/dts/nxp/imx/imx6ull-colibri-wifi-iris.dts similarity index 100% rename from arch/arm/boot/dts/imx6ull-colibri-wifi-iris.dts rename to arch/arm/boot/dts/nxp/imx/imx6ull-colibri-wifi-iris.dts diff --git a/arch/arm/boot/dts/imx6ull-colibri-wifi.dtsi b/arch/arm/boot/dts/nxp/imx/imx6ull-colibri-wifi.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6ull-colibri-wifi.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6ull-colibri-wifi.dtsi diff --git a/arch/arm/boot/dts/imx6ull-colibri.dtsi b/arch/arm/boot/dts/nxp/imx/imx6ull-colibri.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6ull-colibri.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6ull-colibri.dtsi diff --git a/arch/arm/boot/dts/imx6ull-dhcom-drc02.dts b/arch/arm/boot/dts/nxp/imx/imx6ull-dhcom-drc02.dts similarity index 100% rename from arch/arm/boot/dts/imx6ull-dhcom-drc02.dts rename to arch/arm/boot/dts/nxp/imx/imx6ull-dhcom-drc02.dts diff --git a/arch/arm/boot/dts/imx6ull-dhcom-pdk2.dts b/arch/arm/boot/dts/nxp/imx/imx6ull-dhcom-pdk2.dts similarity index 100% rename from arch/arm/boot/dts/imx6ull-dhcom-pdk2.dts rename to arch/arm/boot/dts/nxp/imx/imx6ull-dhcom-pdk2.dts diff --git a/arch/arm/boot/dts/imx6ull-dhcom-picoitx.dts b/arch/arm/boot/dts/nxp/imx/imx6ull-dhcom-picoitx.dts similarity index 100% rename from arch/arm/boot/dts/imx6ull-dhcom-picoitx.dts rename to arch/arm/boot/dts/nxp/imx/imx6ull-dhcom-picoitx.dts diff --git a/arch/arm/boot/dts/imx6ull-dhcom-som-cfg-sdcard.dtsi b/arch/arm/boot/dts/nxp/imx/imx6ull-dhcom-som-cfg-sdcard.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6ull-dhcom-som-cfg-sdcard.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6ull-dhcom-som-cfg-sdcard.dtsi diff --git a/arch/arm/boot/dts/imx6ull-dhcom-som.dtsi b/arch/arm/boot/dts/nxp/imx/imx6ull-dhcom-som.dtsi similarity index 99% rename from arch/arm/boot/dts/imx6ull-dhcom-som.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6ull-dhcom-som.dtsi index 17837663c0b0d5903f5320390b6b7b5ee961df70..830b5a5064f28b45e7f387fbe2d506540bedafa8 100644 --- a/arch/arm/boot/dts/imx6ull-dhcom-som.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx6ull-dhcom-som.dtsi @@ -7,8 +7,6 @@ / { aliases { - /delete-property/ mmc0; /* Avoid double definitions */ - /delete-property/ mmc1; /delete-property/ spi2; /delete-property/ spi3; i2c0 = &i2c2; diff --git a/arch/arm/boot/dts/nxp/imx/imx6ull-dhcor-maveo-box.dts b/arch/arm/boot/dts/nxp/imx/imx6ull-dhcor-maveo-box.dts new file mode 100644 index 0000000000000000000000000000000000000000..047f7b2d852613c77c597b0c45b55246a559efc0 --- /dev/null +++ b/arch/arm/boot/dts/nxp/imx/imx6ull-dhcor-maveo-box.dts @@ -0,0 +1,359 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT +/* + * Copyright (C) 2023 DH electronics GmbH + * Copyright (C) 2023 Marantec electronics GmbH + * + * DHCOM iMX6ULL variant: + * DHCR-iMX6ULL-C080-R051-SPI-WBT-I-01LG + * DHCOR PCB number: 578-200 or newer + * maveo box PCB number: 525-200 or newer + */ + +/dts-v1/; + +#include "imx6ull-dhcor-som.dtsi" + +/ { + model = "DH electronics i.MX6ULL DHCOR on maveo box"; + compatible = "marantec,imx6ull-dhcor-maveo-box", "dh,imx6ull-dhcor-som", + "fsl,imx6ull"; + + aliases { + mmc2 = &usdhc2; + spi0 = &ecspi4; + spi3 = &ecspi1; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + reg_usb_otg1_vbus: regulator-usb-otg1-vbus { + compatible = "regulator-fixed"; + regulator-max-microvolt = <5000000>; + regulator-min-microvolt = <5000000>; + regulator-name = "usb-otg1-vbus"; + }; + + reg_usb_otg2_vbus: regulator-usb-otg2-vbus { + compatible = "regulator-fixed"; + regulator-max-microvolt = <5000000>; + regulator-min-microvolt = <5000000>; + regulator-name = "usb-otg2-vbus"; + }; + + /* WiFi pin WL_REG_ON is connected to GPIO 5.9 */ + usdhc1_pwrseq: usdhc1-pwrseq { + compatible = "mmc-pwrseq-simple"; + reset-gpios = <&gpio5 9 GPIO_ACTIVE_LOW>; + }; +}; + +/* BT pin BT_REG_ON is connected to GPIO 1.18 */ +&bluetooth { + shutdown-gpios = <&gpio1 18 GPIO_ACTIVE_HIGH>; +}; + +/* X10 connector */ +&ecspi4 { + cs-gpios = <&gpio2 15 GPIO_ACTIVE_LOW>; + pinctrl-0 = <&pinctrl_ecspi4>; + pinctrl-names = "default"; + status = "okay"; + + spidev@0 { + compatible = "dh,dhcom-board"; + reg = <0>; + spi-cpha; + spi-cpol; + spi-max-frequency = <54000000>; + }; +}; + +&gpio1 { + gpio-line-names = + "", "", "", "", + "", "BUTTON-USER", "", "", + "BUTTON-RESET", "", "", "", + "", "", "", "", + "", "", "BT-REG-ON", "", + "", "", "", "", + "", "", "", "", + "", "", "", ""; +}; + +&gpio2 { + gpio-line-names = + "PSOC-GPIO-1", "", "", "X10-12", + "X10-10", "PSOC-GPIO-2", "PSOC-GPIO-3", "", + "X10-11", "X10-9", "", "", + "", "", "", "", + "", "", "", "", + "", "", "", "", + "", "", "", "", + "", "", "", ""; +}; + +&gpio3 { + gpio-line-names = + "DHCOR-HW0", "DHCOR-HW1", "", "", + "", "", "", "", + "", "", "", "", + "", "", "", "", + "", "", "", "", + "", "", "", "", + "", "", "", "", + "", "", "", ""; +}; + +&gpio4 { + gpio-line-names = + "", "", "", "", + "", "", "", "", + "", "", "", "", + "", "", "", "", + "", "MAVEO-BOX-HW0", "LED-G", "MAVEO-BOX-VAR1", + "MAVEO-BOX-VAR0", "MAVEO-BOX-HW1", "MAVEO-BOX-HW2", "LED-B", + "LED-R", "", "", "", + "", "", "", ""; +}; + +&gpio5 { + gpio-line-names = + "PSOC-SWD-IO", "PSOC-SWD-CLK", "PSOC-RESET", "ZIGBEE-PROG", + "ZIGBEE-RESET", "", "PSOC-PWR-FAIL-OUT", "NFC-ENABLE", + "NFC-IRQ", "WL-REG-ON", "DHCOR-BOOT-M0", "DHCOR-BOOT-M1", + "", "", "", "", + "", "", "", "", + "", "", "", "", + "", "", "", "", + "", "", "", ""; +}; + +&i2c2 { + clock-frequency = <100000>; + pinctrl-0 = <&pinctrl_i2c2>; + pinctrl-1 = <&pinctrl_i2c2_gpio>; + pinctrl-names = "default", "gpio"; + scl-gpios = <&gpio1 30 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + sda-gpios = <&gpio1 31 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + status = "okay"; +}; + +/* Console UART */ +&uart1 { + pinctrl-0 = <&pinctrl_uart1>; + pinctrl-names = "default"; + status = "okay"; +}; + +/* BT on LGA */ +&uart2 { + pinctrl-0 = <&pinctrl_uart2 &pinctrl_bt_gpio>; +}; + +/* Zigbee UART */ +&uart3 { + pinctrl-0 = <&pinctrl_uart3 &pinctrl_snvs_zigbee_gpio>; + pinctrl-names = "default"; + status = "okay"; +}; + +&usbotg1 { + adp-disable; + disable-over-current; /* Overcurrent pin isn't connected */ + dr_mode = "otg"; + hnp-disable; + pinctrl-0 = <&pinctrl_usbotg1>; + pinctrl-names = "default"; + srp-disable; + vbus-supply = <®_usb_otg1_vbus>; + status = "okay"; +}; + +&usbotg2 { + disable-over-current; /* Overcurrent pin isn't connected */ + dr_mode = "host"; + pinctrl-0 = <&pinctrl_usbotg2>; + pinctrl-names = "default"; + tpl-support; + vbus-supply = <®_usb_otg2_vbus>; + status = "okay"; +}; + +&usbphy1 { + fsl,tx-d-cal = <106>; +}; + +&usbphy2 { + fsl,tx-d-cal = <106>; +}; + +/* WiFi on LGA */ +&usdhc1 { + mmc-pwrseq = <&usdhc1_pwrseq>; + pinctrl-0 = <&pinctrl_usdhc1_wifi &pinctrl_snvs_wifi_gpio>; +}; + +/* eMMC */ +&usdhc2 { + bus-width = <8>; + no-1-8-v; + non-removable; + pinctrl-0 = <&pinctrl_usdhc2>; + pinctrl-names = "default"; + vmmc-supply = <&vcc_3v3>; + vqmmc-supply = <&vcc_3v3>; + status = "okay"; +}; + +&iomuxc { + pinctrl-0 = <&pinctrl_hog_maveo_box>; + pinctrl-names = "default"; + + pinctrl_hog_maveo_box: hog-maveo-box-grp { + fsl,pins = < + MX6UL_PAD_GPIO1_IO05__GPIO1_IO05 0x120b0 /* BUTTON_USER */ + MX6UL_PAD_GPIO1_IO08__GPIO1_IO08 0x120b0 /* BUTTON_RESET */ + MX6UL_PAD_CSI_PIXCLK__GPIO4_IO18 0x400120b0 /* LED_G */ + MX6UL_PAD_CSI_DATA02__GPIO4_IO23 0x400120b0 /* LED_B */ + MX6UL_PAD_CSI_DATA03__GPIO4_IO24 0x400120b0 /* LED_R */ + MX6UL_PAD_ENET2_RX_DATA1__GPIO2_IO09 0x400120b0 /* X10_9 */ + MX6UL_PAD_ENET1_TX_DATA1__GPIO2_IO04 0x400120b0 /* X10_10 */ + MX6UL_PAD_ENET2_RX_DATA0__GPIO2_IO08 0x400120b0 /* X10_11 */ + MX6UL_PAD_ENET1_TX_DATA0__GPIO2_IO03 0x400120b0 /* X10_12 */ + MX6UL_PAD_ENET1_RX_DATA0__GPIO2_IO00 0x400120b0 /* PSOC_GPIO_1 */ + MX6UL_PAD_ENET1_TX_EN__GPIO2_IO05 0x400120b0 /* PSOC_GPIO_2 */ + MX6UL_PAD_ENET1_TX_CLK__GPIO2_IO06 0x400120b0 /* PSOC_GPIO_3 */ + MX6UL_PAD_CSI_MCLK__GPIO4_IO17 0x120b0 /* MAVEO_BOX_HW0 */ + MX6UL_PAD_CSI_DATA00__GPIO4_IO21 0x120b0 /* MAVEO_BOX_HW1 */ + MX6UL_PAD_CSI_DATA01__GPIO4_IO22 0x120b0 /* MAVEO_BOX_HW2 */ + MX6UL_PAD_CSI_HSYNC__GPIO4_IO20 0x120b0 /* MAVEO_BOX_VAR0 */ + MX6UL_PAD_CSI_VSYNC__GPIO4_IO19 0x120b0 /* MAVEO_BOX_VAR1 */ + MX6UL_PAD_LCD_CLK__GPIO3_IO00 0x120b0 /* DHCOR_HW0 */ + MX6UL_PAD_LCD_ENABLE__GPIO3_IO01 0x120b0 /* DHCOR_HW1 */ + MX6UL_PAD_LCD_DATA00__GPIO3_IO05 0x120b0 + MX6UL_PAD_LCD_DATA01__GPIO3_IO06 0x120b0 + MX6UL_PAD_LCD_DATA02__GPIO3_IO07 0x120b0 + MX6UL_PAD_LCD_DATA03__GPIO3_IO08 0x120b0 + MX6UL_PAD_LCD_DATA04__GPIO3_IO09 0x120b0 + MX6UL_PAD_LCD_DATA05__GPIO3_IO10 0x120b0 + MX6UL_PAD_LCD_DATA06__GPIO3_IO11 0x120b0 + MX6UL_PAD_LCD_DATA07__GPIO3_IO12 0x120b0 + MX6UL_PAD_LCD_DATA08__GPIO3_IO13 0x120b0 + MX6UL_PAD_LCD_DATA09__GPIO3_IO14 0x120b0 + MX6UL_PAD_LCD_DATA10__GPIO3_IO15 0x120b0 + MX6UL_PAD_LCD_DATA11__GPIO3_IO16 0x120b0 + MX6UL_PAD_LCD_DATA12__GPIO3_IO17 0x120b0 + MX6UL_PAD_LCD_DATA13__GPIO3_IO18 0x120b0 + MX6UL_PAD_LCD_DATA14__GPIO3_IO19 0x120b0 + MX6UL_PAD_LCD_DATA15__GPIO3_IO20 0x120b0 + MX6UL_PAD_LCD_DATA16__GPIO3_IO21 0x120b0 + MX6UL_PAD_LCD_DATA17__GPIO3_IO22 0x120b0 + MX6UL_PAD_LCD_DATA18__GPIO3_IO23 0x120b0 + >; + }; + + pinctrl_bt_gpio: bt-gpio-grp { + fsl,pins = < + MX6UL_PAD_UART1_CTS_B__GPIO1_IO18 0x400120b0 /* BT_REG_ON */ + >; + }; + + pinctrl_ecspi4: ecspi4-grp { + fsl,pins = < + MX6UL_PAD_ENET2_TX_CLK__ECSPI4_MISO 0x100b1 + MX6UL_PAD_ENET2_TX_EN__ECSPI4_MOSI 0x100b1 + MX6UL_PAD_ENET2_TX_DATA1__ECSPI4_SCLK 0x100b1 + MX6UL_PAD_ENET2_RX_ER__GPIO2_IO15 0x1b0b0 /* SS0 */ + >; + }; + + pinctrl_i2c2: i2c2-grp { + fsl,pins = < + MX6UL_PAD_UART5_TX_DATA__I2C2_SCL 0x4001b8b0 + MX6UL_PAD_UART5_RX_DATA__I2C2_SDA 0x4001b8b0 + >; + }; + + pinctrl_i2c2_gpio: i2c2-gpio-grp { + fsl,pins = < + MX6UL_PAD_UART5_TX_DATA__GPIO1_IO30 0x4001b8b0 + MX6UL_PAD_UART5_RX_DATA__GPIO1_IO31 0x4001b8b0 + >; + }; + + pinctrl_uart1: uart1-grp { + fsl,pins = < + MX6UL_PAD_UART1_TX_DATA__UART1_DCE_TX 0x1b0b1 + MX6UL_PAD_UART1_RX_DATA__UART1_DCE_RX 0x1b0b1 + >; + }; + + pinctrl_uart3: uart3-grp { + fsl,pins = < + MX6UL_PAD_NAND_READY_B__UART3_DCE_TX 0x1b0b1 + MX6UL_PAD_NAND_CE0_B__UART3_DCE_RX 0x1b0b1 + >; + }; + + pinctrl_usbotg1: usbotg1-grp { + fsl,pins = < + MX6UL_PAD_GPIO1_IO00__ANATOP_OTG1_ID 0x17059 + MX6UL_PAD_GPIO1_IO04__GPIO1_IO04 0x120b0 /* USB_OTG1_PWR */ + >; + }; + + pinctrl_usbotg2: usbotg2-grp { + fsl,pins = < + MX6UL_PAD_GPIO1_IO02__GPIO1_IO02 0x120b0 /* USB_OTG2_PWR */ + >; + }; + + pinctrl_usdhc2: usdhc2-grp { + fsl,pins = < + MX6UL_PAD_NAND_RE_B__USDHC2_CLK 0x10069 + MX6UL_PAD_NAND_WE_B__USDHC2_CMD 0x17059 + MX6UL_PAD_NAND_DATA00__USDHC2_DATA0 0x17059 + MX6UL_PAD_NAND_DATA01__USDHC2_DATA1 0x17059 + MX6UL_PAD_NAND_DATA02__USDHC2_DATA2 0x17059 + MX6UL_PAD_NAND_DATA03__USDHC2_DATA3 0x17059 + MX6UL_PAD_NAND_DATA04__USDHC2_DATA4 0x17059 + MX6UL_PAD_NAND_DATA05__USDHC2_DATA5 0x17059 + MX6UL_PAD_NAND_DATA06__USDHC2_DATA6 0x17059 + MX6UL_PAD_NAND_DATA07__USDHC2_DATA7 0x17059 + MX6UL_PAD_NAND_ALE__USDHC2_RESET_B 0x17059 /* SD2 Reset */ + >; + }; +}; + +&iomuxc_snvs { + pinctrl-0 = <&pinctrl_snvs_hog_maveo_box>; + pinctrl-names = "default"; + + pinctrl_snvs_hog_maveo_box: snvs-hog-maveo-box-grp { + fsl,pins = < + MX6ULL_PAD_SNVS_TAMPER0__GPIO5_IO00 0x400120b0 /* PSOC_SWD_IO */ + MX6ULL_PAD_SNVS_TAMPER1__GPIO5_IO01 0x400120b0 /* PSOC_SWD_CLK */ + MX6ULL_PAD_SNVS_TAMPER2__GPIO5_IO02 0x400120b0 /* PSOC_RESET */ + MX6ULL_PAD_SNVS_TAMPER6__GPIO5_IO06 0x400120b0 /* PSOC_PWR_FAIL_OUT */ + MX6ULL_PAD_SNVS_TAMPER7__GPIO5_IO07 0x400120b0 /* NFC_ENABLE */ + MX6ULL_PAD_SNVS_TAMPER8__GPIO5_IO08 0x400120b0 /* NFC_IRQ */ + MX6ULL_PAD_BOOT_MODE0__GPIO5_IO10 0x120b0 /* DHCOR_BOOT_M0 */ + MX6ULL_PAD_BOOT_MODE1__GPIO5_IO11 0x120b0 /* DHCOR_BOOT_M1 */ + >; + }; + + pinctrl_snvs_wifi_gpio: snvs-wifi-gpio-grp { + fsl,pins = < + MX6ULL_PAD_SNVS_TAMPER9__GPIO5_IO09 0x400120b0 /* WL_REG_ON */ + >; + }; + + pinctrl_snvs_zigbee_gpio: snvs-zigbee-gpio-grp { + fsl,pins = < + MX6ULL_PAD_SNVS_TAMPER3__GPIO5_IO03 0x400120b0 /* ZIGBEE_PROG */ + MX6ULL_PAD_SNVS_TAMPER4__GPIO5_IO04 0x400120b0 /* ZIGBEE_RESET */ + >; + }; +}; diff --git a/arch/arm/boot/dts/imx6ull-dhcor-som.dtsi b/arch/arm/boot/dts/nxp/imx/imx6ull-dhcor-som.dtsi similarity index 98% rename from arch/arm/boot/dts/imx6ull-dhcor-som.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6ull-dhcor-som.dtsi index 32a6022625d979041eb038c70213e696eb81b3ed..45315adfaa86ffad824e3693a1308e689057e5ae 100644 --- a/arch/arm/boot/dts/imx6ull-dhcor-som.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx6ull-dhcor-som.dtsi @@ -12,6 +12,11 @@ #include "imx6ull.dtsi" / { + aliases { + /delete-property/ mmc0; + /delete-property/ mmc1; + }; + memory@80000000 { /* Appropriate memory size will be filled by U-Boot */ reg = <0x80000000 0>; diff --git a/arch/arm/boot/dts/imx6ull-jozacp.dts b/arch/arm/boot/dts/nxp/imx/imx6ull-jozacp.dts similarity index 100% rename from arch/arm/boot/dts/imx6ull-jozacp.dts rename to arch/arm/boot/dts/nxp/imx/imx6ull-jozacp.dts diff --git a/arch/arm/boot/dts/imx6ull-kontron-bl.dts b/arch/arm/boot/dts/nxp/imx/imx6ull-kontron-bl.dts similarity index 100% rename from arch/arm/boot/dts/imx6ull-kontron-bl.dts rename to arch/arm/boot/dts/nxp/imx/imx6ull-kontron-bl.dts diff --git a/arch/arm/boot/dts/imx6ull-kontron-sl.dtsi b/arch/arm/boot/dts/nxp/imx/imx6ull-kontron-sl.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6ull-kontron-sl.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6ull-kontron-sl.dtsi diff --git a/arch/arm/boot/dts/imx6ull-myir-mys-6ulx-eval.dts b/arch/arm/boot/dts/nxp/imx/imx6ull-myir-mys-6ulx-eval.dts similarity index 100% rename from arch/arm/boot/dts/imx6ull-myir-mys-6ulx-eval.dts rename to arch/arm/boot/dts/nxp/imx/imx6ull-myir-mys-6ulx-eval.dts diff --git a/arch/arm/boot/dts/imx6ull-myir-mys-6ulx.dtsi b/arch/arm/boot/dts/nxp/imx/imx6ull-myir-mys-6ulx.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6ull-myir-mys-6ulx.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6ull-myir-mys-6ulx.dtsi diff --git a/arch/arm/boot/dts/imx6ull-opos6ul.dtsi b/arch/arm/boot/dts/nxp/imx/imx6ull-opos6ul.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6ull-opos6ul.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6ull-opos6ul.dtsi diff --git a/arch/arm/boot/dts/imx6ull-opos6uldev.dts b/arch/arm/boot/dts/nxp/imx/imx6ull-opos6uldev.dts similarity index 100% rename from arch/arm/boot/dts/imx6ull-opos6uldev.dts rename to arch/arm/boot/dts/nxp/imx/imx6ull-opos6uldev.dts diff --git a/arch/arm/boot/dts/imx6ull-phytec-phycore-som.dtsi b/arch/arm/boot/dts/nxp/imx/imx6ull-phytec-phycore-som.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6ull-phytec-phycore-som.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6ull-phytec-phycore-som.dtsi diff --git a/arch/arm/boot/dts/imx6ull-phytec-segin-ff-rdk-emmc.dts b/arch/arm/boot/dts/nxp/imx/imx6ull-phytec-segin-ff-rdk-emmc.dts similarity index 100% rename from arch/arm/boot/dts/imx6ull-phytec-segin-ff-rdk-emmc.dts rename to arch/arm/boot/dts/nxp/imx/imx6ull-phytec-segin-ff-rdk-emmc.dts diff --git a/arch/arm/boot/dts/imx6ull-phytec-segin-ff-rdk-nand.dts b/arch/arm/boot/dts/nxp/imx/imx6ull-phytec-segin-ff-rdk-nand.dts similarity index 100% rename from arch/arm/boot/dts/imx6ull-phytec-segin-ff-rdk-nand.dts rename to arch/arm/boot/dts/nxp/imx/imx6ull-phytec-segin-ff-rdk-nand.dts diff --git a/arch/arm/boot/dts/imx6ull-phytec-segin-lc-rdk-nand.dts b/arch/arm/boot/dts/nxp/imx/imx6ull-phytec-segin-lc-rdk-nand.dts similarity index 100% rename from arch/arm/boot/dts/imx6ull-phytec-segin-lc-rdk-nand.dts rename to arch/arm/boot/dts/nxp/imx/imx6ull-phytec-segin-lc-rdk-nand.dts diff --git a/arch/arm/boot/dts/imx6ull-phytec-segin-peb-av-02.dtsi b/arch/arm/boot/dts/nxp/imx/imx6ull-phytec-segin-peb-av-02.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6ull-phytec-segin-peb-av-02.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6ull-phytec-segin-peb-av-02.dtsi diff --git a/arch/arm/boot/dts/imx6ull-phytec-segin-peb-eval-01.dtsi b/arch/arm/boot/dts/nxp/imx/imx6ull-phytec-segin-peb-eval-01.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6ull-phytec-segin-peb-eval-01.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6ull-phytec-segin-peb-eval-01.dtsi diff --git a/arch/arm/boot/dts/imx6ull-phytec-segin-peb-wlbt-05.dtsi b/arch/arm/boot/dts/nxp/imx/imx6ull-phytec-segin-peb-wlbt-05.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6ull-phytec-segin-peb-wlbt-05.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6ull-phytec-segin-peb-wlbt-05.dtsi diff --git a/arch/arm/boot/dts/imx6ull-phytec-segin.dtsi b/arch/arm/boot/dts/nxp/imx/imx6ull-phytec-segin.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6ull-phytec-segin.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6ull-phytec-segin.dtsi diff --git a/arch/arm/boot/dts/imx6ull-phytec-tauri-emmc.dts b/arch/arm/boot/dts/nxp/imx/imx6ull-phytec-tauri-emmc.dts similarity index 100% rename from arch/arm/boot/dts/imx6ull-phytec-tauri-emmc.dts rename to arch/arm/boot/dts/nxp/imx/imx6ull-phytec-tauri-emmc.dts diff --git a/arch/arm/boot/dts/imx6ull-phytec-tauri-nand.dts b/arch/arm/boot/dts/nxp/imx/imx6ull-phytec-tauri-nand.dts similarity index 100% rename from arch/arm/boot/dts/imx6ull-phytec-tauri-nand.dts rename to arch/arm/boot/dts/nxp/imx/imx6ull-phytec-tauri-nand.dts diff --git a/arch/arm/boot/dts/imx6ull-phytec-tauri.dtsi b/arch/arm/boot/dts/nxp/imx/imx6ull-phytec-tauri.dtsi similarity index 99% rename from arch/arm/boot/dts/imx6ull-phytec-tauri.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6ull-phytec-tauri.dtsi index 5464a52a1f94411762da4b20ae9b8accceaae8be..ea627638e40cf63e558647c8f69ad0cdcb1be424 100644 --- a/arch/arm/boot/dts/imx6ull-phytec-tauri.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx6ull-phytec-tauri.dtsi @@ -260,7 +260,6 @@ pinctrl-names = "default"; pinctrl-0 = <&pinctrl_uart4>; rts-gpios = <&gpio3 2 GPIO_ACTIVE_HIGH>; - rs485-rts-active-high; linux,rs485-enabled-at-boot-time; status = "okay"; }; diff --git a/arch/arm/boot/dts/imx6ull-pinfunc-snvs.h b/arch/arm/boot/dts/nxp/imx/imx6ull-pinfunc-snvs.h similarity index 100% rename from arch/arm/boot/dts/imx6ull-pinfunc-snvs.h rename to arch/arm/boot/dts/nxp/imx/imx6ull-pinfunc-snvs.h diff --git a/arch/arm/boot/dts/imx6ull-pinfunc.h b/arch/arm/boot/dts/nxp/imx/imx6ull-pinfunc.h similarity index 100% rename from arch/arm/boot/dts/imx6ull-pinfunc.h rename to arch/arm/boot/dts/nxp/imx/imx6ull-pinfunc.h diff --git a/arch/arm/boot/dts/imx6ull-tarragon-common.dtsi b/arch/arm/boot/dts/nxp/imx/imx6ull-tarragon-common.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6ull-tarragon-common.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6ull-tarragon-common.dtsi diff --git a/arch/arm/boot/dts/imx6ull-tarragon-master.dts b/arch/arm/boot/dts/nxp/imx/imx6ull-tarragon-master.dts similarity index 100% rename from arch/arm/boot/dts/imx6ull-tarragon-master.dts rename to arch/arm/boot/dts/nxp/imx/imx6ull-tarragon-master.dts diff --git a/arch/arm/boot/dts/imx6ull-tarragon-micro.dts b/arch/arm/boot/dts/nxp/imx/imx6ull-tarragon-micro.dts similarity index 100% rename from arch/arm/boot/dts/imx6ull-tarragon-micro.dts rename to arch/arm/boot/dts/nxp/imx/imx6ull-tarragon-micro.dts diff --git a/arch/arm/boot/dts/imx6ull-tarragon-slave.dts b/arch/arm/boot/dts/nxp/imx/imx6ull-tarragon-slave.dts similarity index 100% rename from arch/arm/boot/dts/imx6ull-tarragon-slave.dts rename to arch/arm/boot/dts/nxp/imx/imx6ull-tarragon-slave.dts diff --git a/arch/arm/boot/dts/imx6ull-tarragon-slavext.dts b/arch/arm/boot/dts/nxp/imx/imx6ull-tarragon-slavext.dts similarity index 100% rename from arch/arm/boot/dts/imx6ull-tarragon-slavext.dts rename to arch/arm/boot/dts/nxp/imx/imx6ull-tarragon-slavext.dts diff --git a/arch/arm/boot/dts/imx6ull-tqma6ull2-mba6ulx.dts b/arch/arm/boot/dts/nxp/imx/imx6ull-tqma6ull2-mba6ulx.dts similarity index 100% rename from arch/arm/boot/dts/imx6ull-tqma6ull2-mba6ulx.dts rename to arch/arm/boot/dts/nxp/imx/imx6ull-tqma6ull2-mba6ulx.dts diff --git a/arch/arm/boot/dts/imx6ull-tqma6ull2.dtsi b/arch/arm/boot/dts/nxp/imx/imx6ull-tqma6ull2.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6ull-tqma6ull2.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6ull-tqma6ull2.dtsi diff --git a/arch/arm/boot/dts/imx6ull-tqma6ull2l-mba6ulx.dts b/arch/arm/boot/dts/nxp/imx/imx6ull-tqma6ull2l-mba6ulx.dts similarity index 100% rename from arch/arm/boot/dts/imx6ull-tqma6ull2l-mba6ulx.dts rename to arch/arm/boot/dts/nxp/imx/imx6ull-tqma6ull2l-mba6ulx.dts diff --git a/arch/arm/boot/dts/imx6ull-tqma6ull2l.dtsi b/arch/arm/boot/dts/nxp/imx/imx6ull-tqma6ull2l.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6ull-tqma6ull2l.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6ull-tqma6ull2l.dtsi diff --git a/arch/arm/boot/dts/imx6ull.dtsi b/arch/arm/boot/dts/nxp/imx/imx6ull.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6ull.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6ull.dtsi diff --git a/arch/arm/boot/dts/imx6ulz-14x14-evk.dts b/arch/arm/boot/dts/nxp/imx/imx6ulz-14x14-evk.dts similarity index 100% rename from arch/arm/boot/dts/imx6ulz-14x14-evk.dts rename to arch/arm/boot/dts/nxp/imx/imx6ulz-14x14-evk.dts diff --git a/arch/arm/boot/dts/imx6ulz-bsh-smm-m2.dts b/arch/arm/boot/dts/nxp/imx/imx6ulz-bsh-smm-m2.dts similarity index 100% rename from arch/arm/boot/dts/imx6ulz-bsh-smm-m2.dts rename to arch/arm/boot/dts/nxp/imx/imx6ulz-bsh-smm-m2.dts diff --git a/arch/arm/boot/dts/imx6ulz.dtsi b/arch/arm/boot/dts/nxp/imx/imx6ulz.dtsi similarity index 100% rename from arch/arm/boot/dts/imx6ulz.dtsi rename to arch/arm/boot/dts/nxp/imx/imx6ulz.dtsi diff --git a/arch/arm/boot/dts/imx7-colibri-aster.dtsi b/arch/arm/boot/dts/nxp/imx/imx7-colibri-aster.dtsi similarity index 100% rename from arch/arm/boot/dts/imx7-colibri-aster.dtsi rename to arch/arm/boot/dts/nxp/imx/imx7-colibri-aster.dtsi diff --git a/arch/arm/boot/dts/imx7-colibri-eval-v3.dtsi b/arch/arm/boot/dts/nxp/imx/imx7-colibri-eval-v3.dtsi similarity index 100% rename from arch/arm/boot/dts/imx7-colibri-eval-v3.dtsi rename to arch/arm/boot/dts/nxp/imx/imx7-colibri-eval-v3.dtsi diff --git a/arch/arm/boot/dts/imx7-colibri-iris-v2.dtsi b/arch/arm/boot/dts/nxp/imx/imx7-colibri-iris-v2.dtsi similarity index 100% rename from arch/arm/boot/dts/imx7-colibri-iris-v2.dtsi rename to arch/arm/boot/dts/nxp/imx/imx7-colibri-iris-v2.dtsi diff --git a/arch/arm/boot/dts/imx7-colibri-iris.dtsi b/arch/arm/boot/dts/nxp/imx/imx7-colibri-iris.dtsi similarity index 100% rename from arch/arm/boot/dts/imx7-colibri-iris.dtsi rename to arch/arm/boot/dts/nxp/imx/imx7-colibri-iris.dtsi diff --git a/arch/arm/boot/dts/imx7-colibri.dtsi b/arch/arm/boot/dts/nxp/imx/imx7-colibri.dtsi similarity index 100% rename from arch/arm/boot/dts/imx7-colibri.dtsi rename to arch/arm/boot/dts/nxp/imx/imx7-colibri.dtsi diff --git a/arch/arm/boot/dts/imx7-mba7.dtsi b/arch/arm/boot/dts/nxp/imx/imx7-mba7.dtsi similarity index 100% rename from arch/arm/boot/dts/imx7-mba7.dtsi rename to arch/arm/boot/dts/nxp/imx/imx7-mba7.dtsi diff --git a/arch/arm/boot/dts/imx7-tqma7.dtsi b/arch/arm/boot/dts/nxp/imx/imx7-tqma7.dtsi similarity index 100% rename from arch/arm/boot/dts/imx7-tqma7.dtsi rename to arch/arm/boot/dts/nxp/imx/imx7-tqma7.dtsi diff --git a/arch/arm/boot/dts/imx7d-cl-som-imx7.dts b/arch/arm/boot/dts/nxp/imx/imx7d-cl-som-imx7.dts similarity index 100% rename from arch/arm/boot/dts/imx7d-cl-som-imx7.dts rename to arch/arm/boot/dts/nxp/imx/imx7d-cl-som-imx7.dts diff --git a/arch/arm/boot/dts/imx7d-colibri-aster.dts b/arch/arm/boot/dts/nxp/imx/imx7d-colibri-aster.dts similarity index 100% rename from arch/arm/boot/dts/imx7d-colibri-aster.dts rename to arch/arm/boot/dts/nxp/imx/imx7d-colibri-aster.dts diff --git a/arch/arm/boot/dts/imx7d-colibri-emmc-aster.dts b/arch/arm/boot/dts/nxp/imx/imx7d-colibri-emmc-aster.dts similarity index 100% rename from arch/arm/boot/dts/imx7d-colibri-emmc-aster.dts rename to arch/arm/boot/dts/nxp/imx/imx7d-colibri-emmc-aster.dts diff --git a/arch/arm/boot/dts/imx7d-colibri-emmc-eval-v3.dts b/arch/arm/boot/dts/nxp/imx/imx7d-colibri-emmc-eval-v3.dts similarity index 100% rename from arch/arm/boot/dts/imx7d-colibri-emmc-eval-v3.dts rename to arch/arm/boot/dts/nxp/imx/imx7d-colibri-emmc-eval-v3.dts diff --git a/arch/arm/boot/dts/imx7d-colibri-emmc-iris-v2.dts b/arch/arm/boot/dts/nxp/imx/imx7d-colibri-emmc-iris-v2.dts similarity index 100% rename from arch/arm/boot/dts/imx7d-colibri-emmc-iris-v2.dts rename to arch/arm/boot/dts/nxp/imx/imx7d-colibri-emmc-iris-v2.dts diff --git a/arch/arm/boot/dts/imx7d-colibri-emmc-iris.dts b/arch/arm/boot/dts/nxp/imx/imx7d-colibri-emmc-iris.dts similarity index 100% rename from arch/arm/boot/dts/imx7d-colibri-emmc-iris.dts rename to arch/arm/boot/dts/nxp/imx/imx7d-colibri-emmc-iris.dts diff --git a/arch/arm/boot/dts/imx7d-colibri-emmc.dtsi b/arch/arm/boot/dts/nxp/imx/imx7d-colibri-emmc.dtsi similarity index 100% rename from arch/arm/boot/dts/imx7d-colibri-emmc.dtsi rename to arch/arm/boot/dts/nxp/imx/imx7d-colibri-emmc.dtsi diff --git a/arch/arm/boot/dts/imx7d-colibri-eval-v3.dts b/arch/arm/boot/dts/nxp/imx/imx7d-colibri-eval-v3.dts similarity index 100% rename from arch/arm/boot/dts/imx7d-colibri-eval-v3.dts rename to arch/arm/boot/dts/nxp/imx/imx7d-colibri-eval-v3.dts diff --git a/arch/arm/boot/dts/imx7d-colibri-iris-v2.dts b/arch/arm/boot/dts/nxp/imx/imx7d-colibri-iris-v2.dts similarity index 100% rename from arch/arm/boot/dts/imx7d-colibri-iris-v2.dts rename to arch/arm/boot/dts/nxp/imx/imx7d-colibri-iris-v2.dts diff --git a/arch/arm/boot/dts/imx7d-colibri-iris.dts b/arch/arm/boot/dts/nxp/imx/imx7d-colibri-iris.dts similarity index 100% rename from arch/arm/boot/dts/imx7d-colibri-iris.dts rename to arch/arm/boot/dts/nxp/imx/imx7d-colibri-iris.dts diff --git a/arch/arm/boot/dts/imx7d-colibri.dtsi b/arch/arm/boot/dts/nxp/imx/imx7d-colibri.dtsi similarity index 100% rename from arch/arm/boot/dts/imx7d-colibri.dtsi rename to arch/arm/boot/dts/nxp/imx/imx7d-colibri.dtsi diff --git a/arch/arm/boot/dts/imx7d-flex-concentrator-mfg.dts b/arch/arm/boot/dts/nxp/imx/imx7d-flex-concentrator-mfg.dts similarity index 100% rename from arch/arm/boot/dts/imx7d-flex-concentrator-mfg.dts rename to arch/arm/boot/dts/nxp/imx/imx7d-flex-concentrator-mfg.dts diff --git a/arch/arm/boot/dts/imx7d-flex-concentrator.dts b/arch/arm/boot/dts/nxp/imx/imx7d-flex-concentrator.dts similarity index 99% rename from arch/arm/boot/dts/imx7d-flex-concentrator.dts rename to arch/arm/boot/dts/nxp/imx/imx7d-flex-concentrator.dts index bd6b5285aa8d27b0debd4e73e70251c21159c46d..3a723843d5626f6cc4b9ee2750968c01e46306db 100644 --- a/arch/arm/boot/dts/imx7d-flex-concentrator.dts +++ b/arch/arm/boot/dts/nxp/imx/imx7d-flex-concentrator.dts @@ -107,7 +107,6 @@ &ecspi2 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_ecspi2>; - num-chipselects = <1>; cs-gpios = <&gpio4 23 GPIO_ACTIVE_LOW>; status = "okay"; @@ -122,7 +121,6 @@ &ecspi4 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_ecspi4>; - num-chipselects = <1>; cs-gpios = <&gpio3 3 GPIO_ACTIVE_LOW>; status = "okay"; diff --git a/arch/arm/boot/dts/imx7d-mba7.dts b/arch/arm/boot/dts/nxp/imx/imx7d-mba7.dts similarity index 100% rename from arch/arm/boot/dts/imx7d-mba7.dts rename to arch/arm/boot/dts/nxp/imx/imx7d-mba7.dts diff --git a/arch/arm/boot/dts/imx7d-meerkat96.dts b/arch/arm/boot/dts/nxp/imx/imx7d-meerkat96.dts similarity index 100% rename from arch/arm/boot/dts/imx7d-meerkat96.dts rename to arch/arm/boot/dts/nxp/imx/imx7d-meerkat96.dts diff --git a/arch/arm/boot/dts/imx7d-nitrogen7.dts b/arch/arm/boot/dts/nxp/imx/imx7d-nitrogen7.dts similarity index 99% rename from arch/arm/boot/dts/imx7d-nitrogen7.dts rename to arch/arm/boot/dts/nxp/imx/imx7d-nitrogen7.dts index a31de900139d6d10f0c849756bbf95e83ec5157d..9c6476bda4a020efaf5db0bb0b06eea133c55c82 100644 --- a/arch/arm/boot/dts/imx7d-nitrogen7.dts +++ b/arch/arm/boot/dts/nxp/imx/imx7d-nitrogen7.dts @@ -159,7 +159,7 @@ pinctrl-0 = <&pinctrl_i2c1>; status = "okay"; - pmic: pfuze3000@8 { + pmic: pmic@8 { compatible = "fsl,pfuze3000"; reg = <0x08>; diff --git a/arch/arm/boot/dts/imx7d-pico-dwarf.dts b/arch/arm/boot/dts/nxp/imx/imx7d-pico-dwarf.dts similarity index 100% rename from arch/arm/boot/dts/imx7d-pico-dwarf.dts rename to arch/arm/boot/dts/nxp/imx/imx7d-pico-dwarf.dts diff --git a/arch/arm/boot/dts/imx7d-pico-hobbit.dts b/arch/arm/boot/dts/nxp/imx/imx7d-pico-hobbit.dts similarity index 100% rename from arch/arm/boot/dts/imx7d-pico-hobbit.dts rename to arch/arm/boot/dts/nxp/imx/imx7d-pico-hobbit.dts diff --git a/arch/arm/boot/dts/imx7d-pico-nymph.dts b/arch/arm/boot/dts/nxp/imx/imx7d-pico-nymph.dts similarity index 100% rename from arch/arm/boot/dts/imx7d-pico-nymph.dts rename to arch/arm/boot/dts/nxp/imx/imx7d-pico-nymph.dts diff --git a/arch/arm/boot/dts/imx7d-pico-pi.dts b/arch/arm/boot/dts/nxp/imx/imx7d-pico-pi.dts similarity index 100% rename from arch/arm/boot/dts/imx7d-pico-pi.dts rename to arch/arm/boot/dts/nxp/imx/imx7d-pico-pi.dts diff --git a/arch/arm/boot/dts/imx7d-pico.dtsi b/arch/arm/boot/dts/nxp/imx/imx7d-pico.dtsi similarity index 99% rename from arch/arm/boot/dts/imx7d-pico.dtsi rename to arch/arm/boot/dts/nxp/imx/imx7d-pico.dtsi index e0bff39e8d3e1bc5e464921ab133d4baf32a2462..73d90845e85c211da3e3b4700d135f4465dce5a1 100644 --- a/arch/arm/boot/dts/imx7d-pico.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx7d-pico.dtsi @@ -170,7 +170,7 @@ pinctrl-0 = <&pinctrl_i2c4>; status = "okay"; - pmic: pfuze3000@8 { + pmic: pmic@8 { compatible = "fsl,pfuze3000"; reg = <0x08>; diff --git a/arch/arm/boot/dts/imx7d-pinfunc.h b/arch/arm/boot/dts/nxp/imx/imx7d-pinfunc.h similarity index 100% rename from arch/arm/boot/dts/imx7d-pinfunc.h rename to arch/arm/boot/dts/nxp/imx/imx7d-pinfunc.h diff --git a/arch/arm/boot/dts/imx7d-remarkable2.dts b/arch/arm/boot/dts/nxp/imx/imx7d-remarkable2.dts similarity index 100% rename from arch/arm/boot/dts/imx7d-remarkable2.dts rename to arch/arm/boot/dts/nxp/imx/imx7d-remarkable2.dts diff --git a/arch/arm/boot/dts/imx7d-sbc-imx7.dts b/arch/arm/boot/dts/nxp/imx/imx7d-sbc-imx7.dts similarity index 100% rename from arch/arm/boot/dts/imx7d-sbc-imx7.dts rename to arch/arm/boot/dts/nxp/imx/imx7d-sbc-imx7.dts diff --git a/arch/arm/boot/dts/imx7d-sdb-reva.dts b/arch/arm/boot/dts/nxp/imx/imx7d-sdb-reva.dts similarity index 100% rename from arch/arm/boot/dts/imx7d-sdb-reva.dts rename to arch/arm/boot/dts/nxp/imx/imx7d-sdb-reva.dts diff --git a/arch/arm/boot/dts/imx7d-sdb-sht11.dts b/arch/arm/boot/dts/nxp/imx/imx7d-sdb-sht11.dts similarity index 100% rename from arch/arm/boot/dts/imx7d-sdb-sht11.dts rename to arch/arm/boot/dts/nxp/imx/imx7d-sdb-sht11.dts diff --git a/arch/arm/boot/dts/imx7d-sdb.dts b/arch/arm/boot/dts/nxp/imx/imx7d-sdb.dts similarity index 93% rename from arch/arm/boot/dts/imx7d-sdb.dts rename to arch/arm/boot/dts/nxp/imx/imx7d-sdb.dts index 234e5fc647b22829891b0a38c2490ded483cabde..75f1cd14bea184934c2001ba604391b610bf7293 100644 --- a/arch/arm/boot/dts/imx7d-sdb.dts +++ b/arch/arm/boot/dts/nxp/imx/imx7d-sdb.dts @@ -43,8 +43,8 @@ compatible = "spi-gpio"; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_spi4>; - gpio-sck = <&gpio1 13 GPIO_ACTIVE_HIGH>; - gpio-mosi = <&gpio1 9 GPIO_ACTIVE_HIGH>; + sck-gpios = <&gpio1 13 GPIO_ACTIVE_HIGH>; + mosi-gpios = <&gpio1 9 GPIO_ACTIVE_HIGH>; cs-gpios = <&gpio1 12 GPIO_ACTIVE_LOW>; num-chipselects = <1>; #address-cells = <1>; @@ -60,6 +60,17 @@ }; }; + reg_sd1_vmmc: regulator-sd1-vmmc { + compatible = "regulator-fixed"; + regulator-name = "VDD_SD1"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + gpio = <&gpio5 2 GPIO_ACTIVE_HIGH>; + enable-active-high; + startup-delay-us = <200000>; + off-on-delay-us = <20000>; + }; + reg_usb_otg1_vbus: regulator-usb-otg1-vbus { compatible = "regulator-fixed"; regulator-name = "usb_otg1_vbus"; @@ -264,7 +275,7 @@ pinctrl-0 = <&pinctrl_i2c1>; status = "okay"; - pmic: pfuze3000@8 { + pmic: pmic@8 { compatible = "fsl,pfuze3000"; reg = <0x08>; @@ -473,10 +484,13 @@ }; &usdhc1 { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_usdhc1>; + pinctrl-names = "default", "state_100mhz", "state_200mhz"; + pinctrl-0 = <&pinctrl_usdhc1>, <&pinctrl_usdhc1_gpio>; + pinctrl-1 = <&pinctrl_usdhc1_100mhz>, <&pinctrl_usdhc1_gpio>; + pinctrl-2 = <&pinctrl_usdhc1_200mhz>, <&pinctrl_usdhc1_gpio>; cd-gpios = <&gpio5 0 GPIO_ACTIVE_LOW>; wp-gpios = <&gpio5 1 GPIO_ACTIVE_HIGH>; + vmmc-supply = <®_sd1_vmmc>; wakeup-source; keep-power-in-suspend; status = "okay"; @@ -731,6 +745,15 @@ >; }; + pinctrl_usdhc1_gpio: usdhc1_gpiogrp { + fsl,pins = < + MX7D_PAD_SD1_CD_B__GPIO5_IO0 0x59 /* CD */ + MX7D_PAD_SD1_WP__GPIO5_IO1 0x59 /* WP */ + MX7D_PAD_SD1_RESET_B__GPIO5_IO2 0x59 /* vmmc */ + MX7D_PAD_GPIO1_IO08__SD1_VSELECT 0x59 /* VSELECT */ + >; + }; + pinctrl_usdhc1: usdhc1grp { fsl,pins = < MX7D_PAD_SD1_CMD__SD1_CMD 0x59 @@ -739,9 +762,28 @@ MX7D_PAD_SD1_DATA1__SD1_DATA1 0x59 MX7D_PAD_SD1_DATA2__SD1_DATA2 0x59 MX7D_PAD_SD1_DATA3__SD1_DATA3 0x59 - MX7D_PAD_SD1_CD_B__GPIO5_IO0 0x59 /* CD */ - MX7D_PAD_SD1_WP__GPIO5_IO1 0x59 /* WP */ - MX7D_PAD_SD1_RESET_B__GPIO5_IO2 0x59 /* vmmc */ + >; + }; + + pinctrl_usdhc1_100mhz: usdhc1grp_100mhz { + fsl,pins = < + MX7D_PAD_SD1_CMD__SD1_CMD 0x5a + MX7D_PAD_SD1_CLK__SD1_CLK 0x1a + MX7D_PAD_SD1_DATA0__SD1_DATA0 0x5a + MX7D_PAD_SD1_DATA1__SD1_DATA1 0x5a + MX7D_PAD_SD1_DATA2__SD1_DATA2 0x5a + MX7D_PAD_SD1_DATA3__SD1_DATA3 0x5a + >; + }; + + pinctrl_usdhc1_200mhz: usdhc1grp_200mhz { + fsl,pins = < + MX7D_PAD_SD1_CMD__SD1_CMD 0x5b + MX7D_PAD_SD1_CLK__SD1_CLK 0x1b + MX7D_PAD_SD1_DATA0__SD1_DATA0 0x5b + MX7D_PAD_SD1_DATA1__SD1_DATA1 0x5b + MX7D_PAD_SD1_DATA2__SD1_DATA2 0x5b + MX7D_PAD_SD1_DATA3__SD1_DATA3 0x5b >; }; diff --git a/arch/arm/boot/dts/imx7d-smegw01.dts b/arch/arm/boot/dts/nxp/imx/imx7d-smegw01.dts similarity index 97% rename from arch/arm/boot/dts/imx7d-smegw01.dts rename to arch/arm/boot/dts/nxp/imx/imx7d-smegw01.dts index c0f00f5db11e15004405675494eb5a1ed46262f8..85b97b5f64e72830b2a76d94f5177ac7e4531340 100644 --- a/arch/arm/boot/dts/imx7d-smegw01.dts +++ b/arch/arm/boot/dts/nxp/imx/imx7d-smegw01.dts @@ -13,6 +13,8 @@ compatible = "storopack,imx7d-smegw01", "fsl,imx7d"; aliases { + ethernet0 = &fec1; + ethernet1 = &fec2; mmc0 = &usdhc1; mmc1 = &usdhc3; mmc2 = &usdhc2; @@ -67,7 +69,7 @@ reg_wlan_rfkill: regulator-wlan-rfkill { compatible = "regulator-fixed"; pinctrl-names = "default"; - pinctrl-2 = <&pinctrl_rfkill>; + pinctrl-0 = <&pinctrl_rfkill>; regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; regulator-name = "wlan_rfkill"; @@ -97,8 +99,6 @@ sram@0 { compatible = "microchip,48l640"; reg = <0>; - #address-cells = <1>; - #size-cells = <1>; spi-max-frequency = <16000000>; }; }; @@ -329,7 +329,7 @@ >; }; - pinctrl_rfkill: rfkillrp { + pinctrl_rfkill: rfkillgrp { fsl,pins = < MX7D_PAD_EPDC_DATA11__GPIO2_IO11 0x17059 >; @@ -355,19 +355,19 @@ >; }; - pinctrl_usbotg1_lpsr: usbotg1 { + pinctrl_usbotg1_lpsr: usbotg1grp { fsl,pins = < MX7D_PAD_LPSR_GPIO1_IO04__USB_OTG1_OC 0x04 >; }; - pinctrl_usbotg1_pwr: usbotg1-pwr { + pinctrl_usbotg1_pwr: usbotg1-pwrgrp { fsl,pins = < MX7D_PAD_LPSR_GPIO1_IO05__USB_OTG1_PWR 0x04 >; }; - pinctrl_usbotg1_pwr_gpio: usbotg1-pwr-gpio { + pinctrl_usbotg1_pwr_gpio: usbotg1-pwr-gpiogrp { fsl,pins = < MX7D_PAD_LPSR_GPIO1_IO05__GPIO1_IO5 0x04 >; diff --git a/arch/arm/boot/dts/imx7d-tqma7.dtsi b/arch/arm/boot/dts/nxp/imx/imx7d-tqma7.dtsi similarity index 100% rename from arch/arm/boot/dts/imx7d-tqma7.dtsi rename to arch/arm/boot/dts/nxp/imx/imx7d-tqma7.dtsi diff --git a/arch/arm/boot/dts/imx7d-zii-rmu2.dts b/arch/arm/boot/dts/nxp/imx/imx7d-zii-rmu2.dts similarity index 100% rename from arch/arm/boot/dts/imx7d-zii-rmu2.dts rename to arch/arm/boot/dts/nxp/imx/imx7d-zii-rmu2.dts diff --git a/arch/arm/boot/dts/imx7d-zii-rpu2.dts b/arch/arm/boot/dts/nxp/imx/imx7d-zii-rpu2.dts similarity index 100% rename from arch/arm/boot/dts/imx7d-zii-rpu2.dts rename to arch/arm/boot/dts/nxp/imx/imx7d-zii-rpu2.dts diff --git a/arch/arm/boot/dts/imx7d.dtsi b/arch/arm/boot/dts/nxp/imx/imx7d.dtsi similarity index 100% rename from arch/arm/boot/dts/imx7d.dtsi rename to arch/arm/boot/dts/nxp/imx/imx7d.dtsi diff --git a/arch/arm/boot/dts/imx7s-colibri-aster.dts b/arch/arm/boot/dts/nxp/imx/imx7s-colibri-aster.dts similarity index 100% rename from arch/arm/boot/dts/imx7s-colibri-aster.dts rename to arch/arm/boot/dts/nxp/imx/imx7s-colibri-aster.dts diff --git a/arch/arm/boot/dts/imx7s-colibri-eval-v3.dts b/arch/arm/boot/dts/nxp/imx/imx7s-colibri-eval-v3.dts similarity index 100% rename from arch/arm/boot/dts/imx7s-colibri-eval-v3.dts rename to arch/arm/boot/dts/nxp/imx/imx7s-colibri-eval-v3.dts diff --git a/arch/arm/boot/dts/imx7s-colibri-iris-v2.dts b/arch/arm/boot/dts/nxp/imx/imx7s-colibri-iris-v2.dts similarity index 100% rename from arch/arm/boot/dts/imx7s-colibri-iris-v2.dts rename to arch/arm/boot/dts/nxp/imx/imx7s-colibri-iris-v2.dts diff --git a/arch/arm/boot/dts/imx7s-colibri-iris.dts b/arch/arm/boot/dts/nxp/imx/imx7s-colibri-iris.dts similarity index 100% rename from arch/arm/boot/dts/imx7s-colibri-iris.dts rename to arch/arm/boot/dts/nxp/imx/imx7s-colibri-iris.dts diff --git a/arch/arm/boot/dts/imx7s-colibri.dtsi b/arch/arm/boot/dts/nxp/imx/imx7s-colibri.dtsi similarity index 100% rename from arch/arm/boot/dts/imx7s-colibri.dtsi rename to arch/arm/boot/dts/nxp/imx/imx7s-colibri.dtsi diff --git a/arch/arm/boot/dts/imx7s-mba7.dts b/arch/arm/boot/dts/nxp/imx/imx7s-mba7.dts similarity index 100% rename from arch/arm/boot/dts/imx7s-mba7.dts rename to arch/arm/boot/dts/nxp/imx/imx7s-mba7.dts diff --git a/arch/arm/boot/dts/imx7s-tqma7.dtsi b/arch/arm/boot/dts/nxp/imx/imx7s-tqma7.dtsi similarity index 100% rename from arch/arm/boot/dts/imx7s-tqma7.dtsi rename to arch/arm/boot/dts/nxp/imx/imx7s-tqma7.dtsi diff --git a/arch/arm/boot/dts/imx7s-warp.dts b/arch/arm/boot/dts/nxp/imx/imx7s-warp.dts similarity index 99% rename from arch/arm/boot/dts/imx7s-warp.dts rename to arch/arm/boot/dts/nxp/imx/imx7s-warp.dts index e8734d218b9dea9f08ef8f443bbd99cf2520cd42..ba7231b364bb8c76296e953bbfa450bc49c1293a 100644 --- a/arch/arm/boot/dts/imx7s-warp.dts +++ b/arch/arm/boot/dts/nxp/imx/imx7s-warp.dts @@ -94,7 +94,7 @@ pinctrl-0 = <&pinctrl_i2c1>; status = "okay"; - pmic: pfuze3000@8 { + pmic: pmic@8 { compatible = "fsl,pfuze3000"; reg = <0x08>; diff --git a/arch/arm/boot/dts/imx7s.dtsi b/arch/arm/boot/dts/nxp/imx/imx7s.dtsi similarity index 99% rename from arch/arm/boot/dts/imx7s.dtsi rename to arch/arm/boot/dts/nxp/imx/imx7s.dtsi index efe2525b62fa16225567d73ab6e4222470b6056d..54026c2c93fac8593140e42517b46edb3b1a476f 100644 --- a/arch/arm/boot/dts/imx7s.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx7s.dtsi @@ -1257,7 +1257,7 @@ }; }; - dma_apbh: dma-apbh@33000000 { + dma_apbh: dma-controller@33000000 { compatible = "fsl,imx7d-dma-apbh", "fsl,imx28-dma-apbh"; reg = <0x33000000 0x2000>; interrupts = , diff --git a/arch/arm/boot/dts/imx7ulp-com.dts b/arch/arm/boot/dts/nxp/imx/imx7ulp-com.dts similarity index 100% rename from arch/arm/boot/dts/imx7ulp-com.dts rename to arch/arm/boot/dts/nxp/imx/imx7ulp-com.dts diff --git a/arch/arm/boot/dts/imx7ulp-evk.dts b/arch/arm/boot/dts/nxp/imx/imx7ulp-evk.dts similarity index 100% rename from arch/arm/boot/dts/imx7ulp-evk.dts rename to arch/arm/boot/dts/nxp/imx/imx7ulp-evk.dts diff --git a/arch/arm/boot/dts/imx7ulp-pinfunc.h b/arch/arm/boot/dts/nxp/imx/imx7ulp-pinfunc.h similarity index 100% rename from arch/arm/boot/dts/imx7ulp-pinfunc.h rename to arch/arm/boot/dts/nxp/imx/imx7ulp-pinfunc.h diff --git a/arch/arm/boot/dts/imx7ulp.dtsi b/arch/arm/boot/dts/nxp/imx/imx7ulp.dtsi similarity index 99% rename from arch/arm/boot/dts/imx7ulp.dtsi rename to arch/arm/boot/dts/nxp/imx/imx7ulp.dtsi index f91bf719d4e2fc418e57dcf31f58946a963c7aa7..b01ddda7bd9e25a2eeeefc01fa49e0c9f40bb9e5 100644 --- a/arch/arm/boot/dts/imx7ulp.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx7ulp.dtsi @@ -459,6 +459,8 @@ compatible = "fsl,imx7ulp-ocotp", "syscon"; reg = <0x410a6000 0x4000>; clocks = <&scg1 IMX7ULP_CLK_DUMMY>; + #address-cells = <1>; + #size-cells = <1>; }; }; }; diff --git a/arch/arm/boot/dts/imxrt1050-evk.dts b/arch/arm/boot/dts/nxp/imx/imxrt1050-evk.dts similarity index 100% rename from arch/arm/boot/dts/imxrt1050-evk.dts rename to arch/arm/boot/dts/nxp/imx/imxrt1050-evk.dts diff --git a/arch/arm/boot/dts/imxrt1050-pinfunc.h b/arch/arm/boot/dts/nxp/imx/imxrt1050-pinfunc.h similarity index 100% rename from arch/arm/boot/dts/imxrt1050-pinfunc.h rename to arch/arm/boot/dts/nxp/imx/imxrt1050-pinfunc.h diff --git a/arch/arm/boot/dts/imxrt1050.dtsi b/arch/arm/boot/dts/nxp/imx/imxrt1050.dtsi similarity index 99% rename from arch/arm/boot/dts/imxrt1050.dtsi rename to arch/arm/boot/dts/nxp/imx/imxrt1050.dtsi index 852861558b4773eeec01e2e4d12d64437ac5abee..dd714d235d5f6abd1650562b6e8dd1931863cdea 100644 --- a/arch/arm/boot/dts/imxrt1050.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imxrt1050.dtsi @@ -4,7 +4,7 @@ * Author(s): Giulio Benetti */ -#include "armv7-m.dtsi" +#include "../../armv7-m.dtsi" #include #include #include diff --git a/arch/arm/boot/dts/imxrt1170-pinfunc.h b/arch/arm/boot/dts/nxp/imx/imxrt1170-pinfunc.h similarity index 100% rename from arch/arm/boot/dts/imxrt1170-pinfunc.h rename to arch/arm/boot/dts/nxp/imx/imxrt1170-pinfunc.h diff --git a/arch/arm/boot/dts/mba6ulx.dtsi b/arch/arm/boot/dts/nxp/imx/mba6ulx.dtsi similarity index 98% rename from arch/arm/boot/dts/mba6ulx.dtsi rename to arch/arm/boot/dts/nxp/imx/mba6ulx.dtsi index 5bf831b072d6a32aebff09edff60261abd9a12cd..e3b2d23068f774024644815b6a51f74dd1bf8ec5 100644 --- a/arch/arm/boot/dts/mba6ulx.dtsi +++ b/arch/arm/boot/dts/nxp/imx/mba6ulx.dtsi @@ -57,7 +57,7 @@ label = "POWER"; linux,code = ; gpios = <&gpio1 3 GPIO_ACTIVE_LOW>; - gpio-key,wakeup; + wakeup-source; }; }; @@ -235,6 +235,7 @@ reg = <0x20>; gpio-controller; #gpio-cells = <2>; + vcc-supply = <®_mba6ul_3v3>; }; expander_in0: gpio-expander@21 { @@ -248,6 +249,7 @@ #interrupt-cells = <2>; gpio-controller; #gpio-cells = <2>; + vcc-supply = <®_mba6ul_3v3>; enet1_int-hog { gpio-hog; @@ -267,6 +269,7 @@ reg = <0x22>; gpio-controller; #gpio-cells = <2>; + vcc-supply = <®_mba6ul_3v3>; }; analog_touch: touchscreen@41 { @@ -300,6 +303,7 @@ compatible = "nxp,se97b", "atmel,24c02"; reg = <0x51>; pagesize = <16>; + vcc-supply = <®_mba6ul_3v3>; }; }; diff --git a/arch/arm/boot/dts/nxp/lpc/Makefile b/arch/arm/boot/dts/nxp/lpc/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..56b9a0ebb917923540c8a7961b6722fb766963d5 --- /dev/null +++ b/arch/arm/boot/dts/nxp/lpc/Makefile @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: GPL-2.0 +dtb-$(CONFIG_ARCH_LPC18XX) += \ + lpc4337-ciaa.dtb \ + lpc4350-hitex-eval.dtb \ + lpc4357-ea4357-devkit.dtb \ + lpc4357-myd-lpc4357.dtb +dtb-$(CONFIG_ARCH_LPC32XX) += \ + lpc3250-ea3250.dtb \ + lpc3250-phy3250.dtb diff --git a/arch/arm/boot/dts/lpc18xx.dtsi b/arch/arm/boot/dts/nxp/lpc/lpc18xx.dtsi similarity index 99% rename from arch/arm/boot/dts/lpc18xx.dtsi rename to arch/arm/boot/dts/nxp/lpc/lpc18xx.dtsi index 1bb686a7b3ec94841953275421710391254c8b70..9cf09c183b85e8346ee121034d4d5caef8eb7cc8 100644 --- a/arch/arm/boot/dts/lpc18xx.dtsi +++ b/arch/arm/boot/dts/nxp/lpc/lpc18xx.dtsi @@ -11,7 +11,7 @@ * */ -#include "armv7-m.dtsi" +#include "../../armv7-m.dtsi" #include "dt-bindings/clock/lpc18xx-cgu.h" #include "dt-bindings/clock/lpc18xx-ccu.h" diff --git a/arch/arm/boot/dts/lpc3250-ea3250.dts b/arch/arm/boot/dts/nxp/lpc/lpc3250-ea3250.dts similarity index 100% rename from arch/arm/boot/dts/lpc3250-ea3250.dts rename to arch/arm/boot/dts/nxp/lpc/lpc3250-ea3250.dts diff --git a/arch/arm/boot/dts/lpc3250-phy3250.dts b/arch/arm/boot/dts/nxp/lpc/lpc3250-phy3250.dts similarity index 100% rename from arch/arm/boot/dts/lpc3250-phy3250.dts rename to arch/arm/boot/dts/nxp/lpc/lpc3250-phy3250.dts diff --git a/arch/arm/boot/dts/lpc32xx.dtsi b/arch/arm/boot/dts/nxp/lpc/lpc32xx.dtsi similarity index 100% rename from arch/arm/boot/dts/lpc32xx.dtsi rename to arch/arm/boot/dts/nxp/lpc/lpc32xx.dtsi diff --git a/arch/arm/boot/dts/lpc4337-ciaa.dts b/arch/arm/boot/dts/nxp/lpc/lpc4337-ciaa.dts similarity index 100% rename from arch/arm/boot/dts/lpc4337-ciaa.dts rename to arch/arm/boot/dts/nxp/lpc/lpc4337-ciaa.dts diff --git a/arch/arm/boot/dts/lpc4350-hitex-eval.dts b/arch/arm/boot/dts/nxp/lpc/lpc4350-hitex-eval.dts similarity index 100% rename from arch/arm/boot/dts/lpc4350-hitex-eval.dts rename to arch/arm/boot/dts/nxp/lpc/lpc4350-hitex-eval.dts diff --git a/arch/arm/boot/dts/lpc4350.dtsi b/arch/arm/boot/dts/nxp/lpc/lpc4350.dtsi similarity index 100% rename from arch/arm/boot/dts/lpc4350.dtsi rename to arch/arm/boot/dts/nxp/lpc/lpc4350.dtsi diff --git a/arch/arm/boot/dts/lpc4357-ea4357-devkit.dts b/arch/arm/boot/dts/nxp/lpc/lpc4357-ea4357-devkit.dts similarity index 100% rename from arch/arm/boot/dts/lpc4357-ea4357-devkit.dts rename to arch/arm/boot/dts/nxp/lpc/lpc4357-ea4357-devkit.dts diff --git a/arch/arm/boot/dts/lpc4357-myd-lpc4357.dts b/arch/arm/boot/dts/nxp/lpc/lpc4357-myd-lpc4357.dts similarity index 100% rename from arch/arm/boot/dts/lpc4357-myd-lpc4357.dts rename to arch/arm/boot/dts/nxp/lpc/lpc4357-myd-lpc4357.dts diff --git a/arch/arm/boot/dts/lpc4357.dtsi b/arch/arm/boot/dts/nxp/lpc/lpc4357.dtsi similarity index 100% rename from arch/arm/boot/dts/lpc4357.dtsi rename to arch/arm/boot/dts/nxp/lpc/lpc4357.dtsi diff --git a/arch/arm/boot/dts/nxp/ls/Makefile b/arch/arm/boot/dts/nxp/ls/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..3cb1d516f6fb5a5d1d8ce6f17a401d323d82b71e --- /dev/null +++ b/arch/arm/boot/dts/nxp/ls/Makefile @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: GPL-2.0 +dtb-$(CONFIG_SOC_LS1021A) += \ + ls1021a-iot.dtb \ + ls1021a-moxa-uc-8410a.dtb \ + ls1021a-qds.dtb \ + ls1021a-tsn.dtb \ + ls1021a-twr.dtb diff --git a/arch/arm/boot/dts/ls1021a-iot.dts b/arch/arm/boot/dts/nxp/ls/ls1021a-iot.dts similarity index 100% rename from arch/arm/boot/dts/ls1021a-iot.dts rename to arch/arm/boot/dts/nxp/ls/ls1021a-iot.dts diff --git a/arch/arm/boot/dts/ls1021a-moxa-uc-8410a.dts b/arch/arm/boot/dts/nxp/ls/ls1021a-moxa-uc-8410a.dts similarity index 100% rename from arch/arm/boot/dts/ls1021a-moxa-uc-8410a.dts rename to arch/arm/boot/dts/nxp/ls/ls1021a-moxa-uc-8410a.dts diff --git a/arch/arm/boot/dts/ls1021a-qds.dts b/arch/arm/boot/dts/nxp/ls/ls1021a-qds.dts similarity index 100% rename from arch/arm/boot/dts/ls1021a-qds.dts rename to arch/arm/boot/dts/nxp/ls/ls1021a-qds.dts diff --git a/arch/arm/boot/dts/ls1021a-tsn.dts b/arch/arm/boot/dts/nxp/ls/ls1021a-tsn.dts similarity index 100% rename from arch/arm/boot/dts/ls1021a-tsn.dts rename to arch/arm/boot/dts/nxp/ls/ls1021a-tsn.dts diff --git a/arch/arm/boot/dts/ls1021a-twr.dts b/arch/arm/boot/dts/nxp/ls/ls1021a-twr.dts similarity index 100% rename from arch/arm/boot/dts/ls1021a-twr.dts rename to arch/arm/boot/dts/nxp/ls/ls1021a-twr.dts diff --git a/arch/arm/boot/dts/ls1021a.dtsi b/arch/arm/boot/dts/nxp/ls/ls1021a.dtsi similarity index 100% rename from arch/arm/boot/dts/ls1021a.dtsi rename to arch/arm/boot/dts/nxp/ls/ls1021a.dtsi diff --git a/arch/arm/boot/dts/nxp/mxs/Makefile b/arch/arm/boot/dts/nxp/mxs/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..a430d04f9c6935c7fb47c76c46bf3d2fd741bda4 --- /dev/null +++ b/arch/arm/boot/dts/nxp/mxs/Makefile @@ -0,0 +1,31 @@ +# SPDX-License-Identifier: GPL-2.0 +dtb-$(CONFIG_ARCH_MXS) += \ + imx23-evk.dtb \ + imx23-olinuxino.dtb \ + imx23-sansa.dtb \ + imx23-stmp378x_devb.dtb \ + imx23-xfi3.dtb \ + imx28-apf28.dtb \ + imx28-apf28dev.dtb \ + imx28-apx4devkit.dtb \ + imx28-cfa10036.dtb \ + imx28-cfa10037.dtb \ + imx28-cfa10049.dtb \ + imx28-cfa10055.dtb \ + imx28-cfa10056.dtb \ + imx28-cfa10057.dtb \ + imx28-cfa10058.dtb \ + imx28-duckbill-2-485.dtb \ + imx28-duckbill-2.dtb \ + imx28-duckbill-2-enocean.dtb \ + imx28-duckbill-2-spi.dtb \ + imx28-duckbill.dtb \ + imx28-eukrea-mbmx283lc.dtb \ + imx28-eukrea-mbmx287lc.dtb \ + imx28-evk.dtb \ + imx28-m28cu3.dtb \ + imx28-m28evk.dtb \ + imx28-sps1.dtb \ + imx28-ts4600.dtb \ + imx28-tx28.dtb \ + imx28-xea.dtb diff --git a/arch/arm/boot/dts/imx23-evk.dts b/arch/arm/boot/dts/nxp/mxs/imx23-evk.dts similarity index 100% rename from arch/arm/boot/dts/imx23-evk.dts rename to arch/arm/boot/dts/nxp/mxs/imx23-evk.dts diff --git a/arch/arm/boot/dts/imx23-olinuxino.dts b/arch/arm/boot/dts/nxp/mxs/imx23-olinuxino.dts similarity index 100% rename from arch/arm/boot/dts/imx23-olinuxino.dts rename to arch/arm/boot/dts/nxp/mxs/imx23-olinuxino.dts diff --git a/arch/arm/boot/dts/imx23-pinfunc.h b/arch/arm/boot/dts/nxp/mxs/imx23-pinfunc.h similarity index 100% rename from arch/arm/boot/dts/imx23-pinfunc.h rename to arch/arm/boot/dts/nxp/mxs/imx23-pinfunc.h diff --git a/arch/arm/boot/dts/imx23-sansa.dts b/arch/arm/boot/dts/nxp/mxs/imx23-sansa.dts similarity index 100% rename from arch/arm/boot/dts/imx23-sansa.dts rename to arch/arm/boot/dts/nxp/mxs/imx23-sansa.dts diff --git a/arch/arm/boot/dts/imx23-stmp378x_devb.dts b/arch/arm/boot/dts/nxp/mxs/imx23-stmp378x_devb.dts similarity index 100% rename from arch/arm/boot/dts/imx23-stmp378x_devb.dts rename to arch/arm/boot/dts/nxp/mxs/imx23-stmp378x_devb.dts diff --git a/arch/arm/boot/dts/imx23-xfi3.dts b/arch/arm/boot/dts/nxp/mxs/imx23-xfi3.dts similarity index 100% rename from arch/arm/boot/dts/imx23-xfi3.dts rename to arch/arm/boot/dts/nxp/mxs/imx23-xfi3.dts diff --git a/arch/arm/boot/dts/imx23.dtsi b/arch/arm/boot/dts/nxp/mxs/imx23.dtsi similarity index 99% rename from arch/arm/boot/dts/imx23.dtsi rename to arch/arm/boot/dts/nxp/mxs/imx23.dtsi index d19508c8f9ed63a98648ab1b9c7ea1f1d76660cd..a3668a0827fc8ad66200dfcdb8467aa07e8bf764 100644 --- a/arch/arm/boot/dts/imx23.dtsi +++ b/arch/arm/boot/dts/nxp/mxs/imx23.dtsi @@ -59,7 +59,7 @@ reg = <0x80000000 0x2000>; }; - dma_apbh: dma-apbh@80004000 { + dma_apbh: dma-controller@80004000 { compatible = "fsl,imx23-dma-apbh"; reg = <0x80004000 0x2000>; interrupts = <0 14 20 0 diff --git a/arch/arm/boot/dts/imx28-apf28.dts b/arch/arm/boot/dts/nxp/mxs/imx28-apf28.dts similarity index 100% rename from arch/arm/boot/dts/imx28-apf28.dts rename to arch/arm/boot/dts/nxp/mxs/imx28-apf28.dts diff --git a/arch/arm/boot/dts/imx28-apf28dev.dts b/arch/arm/boot/dts/nxp/mxs/imx28-apf28dev.dts similarity index 100% rename from arch/arm/boot/dts/imx28-apf28dev.dts rename to arch/arm/boot/dts/nxp/mxs/imx28-apf28dev.dts diff --git a/arch/arm/boot/dts/imx28-apx4devkit.dts b/arch/arm/boot/dts/nxp/mxs/imx28-apx4devkit.dts similarity index 100% rename from arch/arm/boot/dts/imx28-apx4devkit.dts rename to arch/arm/boot/dts/nxp/mxs/imx28-apx4devkit.dts diff --git a/arch/arm/boot/dts/imx28-cfa10036.dts b/arch/arm/boot/dts/nxp/mxs/imx28-cfa10036.dts similarity index 100% rename from arch/arm/boot/dts/imx28-cfa10036.dts rename to arch/arm/boot/dts/nxp/mxs/imx28-cfa10036.dts diff --git a/arch/arm/boot/dts/imx28-cfa10037.dts b/arch/arm/boot/dts/nxp/mxs/imx28-cfa10037.dts similarity index 100% rename from arch/arm/boot/dts/imx28-cfa10037.dts rename to arch/arm/boot/dts/nxp/mxs/imx28-cfa10037.dts diff --git a/arch/arm/boot/dts/imx28-cfa10049.dts b/arch/arm/boot/dts/nxp/mxs/imx28-cfa10049.dts similarity index 98% rename from arch/arm/boot/dts/imx28-cfa10049.dts rename to arch/arm/boot/dts/nxp/mxs/imx28-cfa10049.dts index 94d6614c1983d127646f753e128f49bca6544887..c5a7f56d83dbd3cc64d20ed9bf87af583bb2e32f 100644 --- a/arch/arm/boot/dts/imx28-cfa10049.dts +++ b/arch/arm/boot/dts/nxp/mxs/imx28-cfa10049.dts @@ -100,9 +100,9 @@ pinctrl-names = "default"; pinctrl-0 = <&spi2_pins_cfa10049>; status = "okay"; - gpio-sck = <&gpio2 16 0>; - gpio-mosi = <&gpio2 17 0>; - gpio-miso = <&gpio2 18 0>; + sck-gpios = <&gpio2 16 0>; + mosi-gpios = <&gpio2 17 0>; + miso-gpios = <&gpio2 18 0>; cs-gpios = <&gpio3 5 0>; num-chipselects = <1>; #address-cells = <1>; @@ -124,8 +124,8 @@ pinctrl-names = "default"; pinctrl-0 = <&spi3_pins_cfa10049>; status = "okay"; - gpio-sck = <&gpio0 24 0>; - gpio-mosi = <&gpio0 28 0>; + sck-gpios = <&gpio0 24 0>; + mosi-gpios = <&gpio0 28 0>; cs-gpios = <&gpio0 17 0 &gpio0 26 0 &gpio0 27 0>; num-chipselects = <3>; #address-cells = <1>; diff --git a/arch/arm/boot/dts/imx28-cfa10055.dts b/arch/arm/boot/dts/nxp/mxs/imx28-cfa10055.dts similarity index 97% rename from arch/arm/boot/dts/imx28-cfa10055.dts rename to arch/arm/boot/dts/nxp/mxs/imx28-cfa10055.dts index 42ba7da48beb9b83e636fb7be9f1b171c84f1cb1..70e225a99fbe776930be65100318b89a57f99f91 100644 --- a/arch/arm/boot/dts/imx28-cfa10055.dts +++ b/arch/arm/boot/dts/nxp/mxs/imx28-cfa10055.dts @@ -19,9 +19,9 @@ pinctrl-names = "default"; pinctrl-0 = <&spi2_pins_cfa10055>; status = "okay"; - gpio-sck = <&gpio2 16 0>; - gpio-mosi = <&gpio2 17 0>; - gpio-miso = <&gpio2 18 0>; + sck-gpios = <&gpio2 16 0>; + mosi-gpios = <&gpio2 17 0>; + miso-gpios = <&gpio2 18 0>; cs-gpios = <&gpio3 5 0>; num-chipselects = <1>; #address-cells = <1>; diff --git a/arch/arm/boot/dts/imx28-cfa10056.dts b/arch/arm/boot/dts/nxp/mxs/imx28-cfa10056.dts similarity index 96% rename from arch/arm/boot/dts/imx28-cfa10056.dts rename to arch/arm/boot/dts/nxp/mxs/imx28-cfa10056.dts index 0e15bdfd7281c0bdcf8eea7f3b7fd17104be4cf9..bc2d6fcad12f917e0123e64f3b9279a1d37cd99c 100644 --- a/arch/arm/boot/dts/imx28-cfa10056.dts +++ b/arch/arm/boot/dts/nxp/mxs/imx28-cfa10056.dts @@ -18,9 +18,9 @@ pinctrl-names = "default"; pinctrl-0 = <&spi2_pins_cfa10056>; status = "okay"; - gpio-sck = <&gpio2 16 0>; - gpio-mosi = <&gpio2 17 0>; - gpio-miso = <&gpio2 18 0>; + sck-gpios = <&gpio2 16 0>; + mosi-gpios = <&gpio2 17 0>; + miso-gpios = <&gpio2 18 0>; cs-gpios = <&gpio3 5 0>; num-chipselects = <1>; #address-cells = <1>; diff --git a/arch/arm/boot/dts/imx28-cfa10057.dts b/arch/arm/boot/dts/nxp/mxs/imx28-cfa10057.dts similarity index 100% rename from arch/arm/boot/dts/imx28-cfa10057.dts rename to arch/arm/boot/dts/nxp/mxs/imx28-cfa10057.dts diff --git a/arch/arm/boot/dts/imx28-cfa10058.dts b/arch/arm/boot/dts/nxp/mxs/imx28-cfa10058.dts similarity index 100% rename from arch/arm/boot/dts/imx28-cfa10058.dts rename to arch/arm/boot/dts/nxp/mxs/imx28-cfa10058.dts diff --git a/arch/arm/boot/dts/imx28-duckbill-2-485.dts b/arch/arm/boot/dts/nxp/mxs/imx28-duckbill-2-485.dts similarity index 100% rename from arch/arm/boot/dts/imx28-duckbill-2-485.dts rename to arch/arm/boot/dts/nxp/mxs/imx28-duckbill-2-485.dts diff --git a/arch/arm/boot/dts/imx28-duckbill-2-enocean.dts b/arch/arm/boot/dts/nxp/mxs/imx28-duckbill-2-enocean.dts similarity index 100% rename from arch/arm/boot/dts/imx28-duckbill-2-enocean.dts rename to arch/arm/boot/dts/nxp/mxs/imx28-duckbill-2-enocean.dts diff --git a/arch/arm/boot/dts/imx28-duckbill-2-spi.dts b/arch/arm/boot/dts/nxp/mxs/imx28-duckbill-2-spi.dts similarity index 100% rename from arch/arm/boot/dts/imx28-duckbill-2-spi.dts rename to arch/arm/boot/dts/nxp/mxs/imx28-duckbill-2-spi.dts diff --git a/arch/arm/boot/dts/imx28-duckbill-2.dts b/arch/arm/boot/dts/nxp/mxs/imx28-duckbill-2.dts similarity index 100% rename from arch/arm/boot/dts/imx28-duckbill-2.dts rename to arch/arm/boot/dts/nxp/mxs/imx28-duckbill-2.dts diff --git a/arch/arm/boot/dts/imx28-duckbill.dts b/arch/arm/boot/dts/nxp/mxs/imx28-duckbill.dts similarity index 100% rename from arch/arm/boot/dts/imx28-duckbill.dts rename to arch/arm/boot/dts/nxp/mxs/imx28-duckbill.dts diff --git a/arch/arm/boot/dts/imx28-eukrea-mbmx283lc.dts b/arch/arm/boot/dts/nxp/mxs/imx28-eukrea-mbmx283lc.dts similarity index 100% rename from arch/arm/boot/dts/imx28-eukrea-mbmx283lc.dts rename to arch/arm/boot/dts/nxp/mxs/imx28-eukrea-mbmx283lc.dts diff --git a/arch/arm/boot/dts/imx28-eukrea-mbmx287lc.dts b/arch/arm/boot/dts/nxp/mxs/imx28-eukrea-mbmx287lc.dts similarity index 100% rename from arch/arm/boot/dts/imx28-eukrea-mbmx287lc.dts rename to arch/arm/boot/dts/nxp/mxs/imx28-eukrea-mbmx287lc.dts diff --git a/arch/arm/boot/dts/imx28-eukrea-mbmx28lc.dtsi b/arch/arm/boot/dts/nxp/mxs/imx28-eukrea-mbmx28lc.dtsi similarity index 100% rename from arch/arm/boot/dts/imx28-eukrea-mbmx28lc.dtsi rename to arch/arm/boot/dts/nxp/mxs/imx28-eukrea-mbmx28lc.dtsi diff --git a/arch/arm/boot/dts/imx28-evk.dts b/arch/arm/boot/dts/nxp/mxs/imx28-evk.dts similarity index 100% rename from arch/arm/boot/dts/imx28-evk.dts rename to arch/arm/boot/dts/nxp/mxs/imx28-evk.dts diff --git a/arch/arm/boot/dts/imx28-lwe.dtsi b/arch/arm/boot/dts/nxp/mxs/imx28-lwe.dtsi similarity index 100% rename from arch/arm/boot/dts/imx28-lwe.dtsi rename to arch/arm/boot/dts/nxp/mxs/imx28-lwe.dtsi diff --git a/arch/arm/boot/dts/imx28-m28.dtsi b/arch/arm/boot/dts/nxp/mxs/imx28-m28.dtsi similarity index 100% rename from arch/arm/boot/dts/imx28-m28.dtsi rename to arch/arm/boot/dts/nxp/mxs/imx28-m28.dtsi diff --git a/arch/arm/boot/dts/imx28-m28cu3.dts b/arch/arm/boot/dts/nxp/mxs/imx28-m28cu3.dts similarity index 100% rename from arch/arm/boot/dts/imx28-m28cu3.dts rename to arch/arm/boot/dts/nxp/mxs/imx28-m28cu3.dts diff --git a/arch/arm/boot/dts/imx28-m28evk.dts b/arch/arm/boot/dts/nxp/mxs/imx28-m28evk.dts similarity index 100% rename from arch/arm/boot/dts/imx28-m28evk.dts rename to arch/arm/boot/dts/nxp/mxs/imx28-m28evk.dts diff --git a/arch/arm/boot/dts/imx28-pinfunc.h b/arch/arm/boot/dts/nxp/mxs/imx28-pinfunc.h similarity index 100% rename from arch/arm/boot/dts/imx28-pinfunc.h rename to arch/arm/boot/dts/nxp/mxs/imx28-pinfunc.h diff --git a/arch/arm/boot/dts/imx28-sps1.dts b/arch/arm/boot/dts/nxp/mxs/imx28-sps1.dts similarity index 100% rename from arch/arm/boot/dts/imx28-sps1.dts rename to arch/arm/boot/dts/nxp/mxs/imx28-sps1.dts diff --git a/arch/arm/boot/dts/imx28-ts4600.dts b/arch/arm/boot/dts/nxp/mxs/imx28-ts4600.dts similarity index 100% rename from arch/arm/boot/dts/imx28-ts4600.dts rename to arch/arm/boot/dts/nxp/mxs/imx28-ts4600.dts diff --git a/arch/arm/boot/dts/imx28-tx28.dts b/arch/arm/boot/dts/nxp/mxs/imx28-tx28.dts similarity index 99% rename from arch/arm/boot/dts/imx28-tx28.dts rename to arch/arm/boot/dts/nxp/mxs/imx28-tx28.dts index ffe58c7093e1c2489a511e45a70cb905c9003fe9..23ad7cd0a1de02a0233396d1ce4a82244fb02767 100644 --- a/arch/arm/boot/dts/imx28-tx28.dts +++ b/arch/arm/boot/dts/nxp/mxs/imx28-tx28.dts @@ -192,9 +192,9 @@ pinctrl-names = "default"; pinctrl-0 = <&tx28_spi_gpio_pins>; - gpio-sck = <&gpio2 24 GPIO_ACTIVE_HIGH>; - gpio-mosi = <&gpio2 25 GPIO_ACTIVE_HIGH>; - gpio-miso = <&gpio2 26 GPIO_ACTIVE_HIGH>; + sck-gpios = <&gpio2 24 GPIO_ACTIVE_HIGH>; + mosi-gpios = <&gpio2 25 GPIO_ACTIVE_HIGH>; + miso-gpios = <&gpio2 26 GPIO_ACTIVE_HIGH>; num-chipselects = <3>; cs-gpios = < &gpio2 27 GPIO_ACTIVE_LOW diff --git a/arch/arm/boot/dts/imx28-xea.dts b/arch/arm/boot/dts/nxp/mxs/imx28-xea.dts similarity index 100% rename from arch/arm/boot/dts/imx28-xea.dts rename to arch/arm/boot/dts/nxp/mxs/imx28-xea.dts diff --git a/arch/arm/boot/dts/imx28.dtsi b/arch/arm/boot/dts/nxp/mxs/imx28.dtsi similarity index 99% rename from arch/arm/boot/dts/imx28.dtsi rename to arch/arm/boot/dts/nxp/mxs/imx28.dtsi index a8d3c3113e0f60b0414899d038bea32d818ec6a7..29e37b1fae66fd53e533e31974fead464180170e 100644 --- a/arch/arm/boot/dts/imx28.dtsi +++ b/arch/arm/boot/dts/nxp/mxs/imx28.dtsi @@ -78,7 +78,7 @@ status = "disabled"; }; - dma_apbh: dma-apbh@80004000 { + dma_apbh: dma-controller@80004000 { compatible = "fsl,imx28-dma-apbh"; reg = <0x80004000 0x2000>; interrupts = <82 83 84 85 diff --git a/arch/arm/boot/dts/mxs-pinfunc.h b/arch/arm/boot/dts/nxp/mxs/mxs-pinfunc.h similarity index 100% rename from arch/arm/boot/dts/mxs-pinfunc.h rename to arch/arm/boot/dts/nxp/mxs/mxs-pinfunc.h diff --git a/arch/arm/boot/dts/nxp/vf/Makefile b/arch/arm/boot/dts/nxp/vf/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..0a4a7f9dd43e4e75641495d02bfcc868e1f6f67c --- /dev/null +++ b/arch/arm/boot/dts/nxp/vf/Makefile @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: GPL-2.0 +dtb-$(CONFIG_SOC_VF610) += \ + vf500-colibri-eval-v3.dtb \ + vf610-bk4.dtb \ + vf610-colibri-eval-v3.dtb \ + vf610m4-colibri.dtb \ + vf610-cosmic.dtb \ + vf610m4-cosmic.dtb \ + vf610-twr.dtb \ + vf610-zii-cfu1.dtb \ + vf610-zii-dev-rev-b.dtb \ + vf610-zii-dev-rev-c.dtb \ + vf610-zii-scu4-aib.dtb \ + vf610-zii-spb4.dtb \ + vf610-zii-ssmb-dtu.dtb \ + vf610-zii-ssmb-spu3.dtb diff --git a/arch/arm/boot/dts/vf-colibri-eval-v3.dtsi b/arch/arm/boot/dts/nxp/vf/vf-colibri-eval-v3.dtsi similarity index 100% rename from arch/arm/boot/dts/vf-colibri-eval-v3.dtsi rename to arch/arm/boot/dts/nxp/vf/vf-colibri-eval-v3.dtsi diff --git a/arch/arm/boot/dts/vf-colibri.dtsi b/arch/arm/boot/dts/nxp/vf/vf-colibri.dtsi similarity index 100% rename from arch/arm/boot/dts/vf-colibri.dtsi rename to arch/arm/boot/dts/nxp/vf/vf-colibri.dtsi diff --git a/arch/arm/boot/dts/vf500-colibri-eval-v3.dts b/arch/arm/boot/dts/nxp/vf/vf500-colibri-eval-v3.dts similarity index 100% rename from arch/arm/boot/dts/vf500-colibri-eval-v3.dts rename to arch/arm/boot/dts/nxp/vf/vf500-colibri-eval-v3.dts diff --git a/arch/arm/boot/dts/vf500-colibri.dtsi b/arch/arm/boot/dts/nxp/vf/vf500-colibri.dtsi similarity index 100% rename from arch/arm/boot/dts/vf500-colibri.dtsi rename to arch/arm/boot/dts/nxp/vf/vf500-colibri.dtsi diff --git a/arch/arm/boot/dts/vf500.dtsi b/arch/arm/boot/dts/nxp/vf/vf500.dtsi similarity index 100% rename from arch/arm/boot/dts/vf500.dtsi rename to arch/arm/boot/dts/nxp/vf/vf500.dtsi diff --git a/arch/arm/boot/dts/vf610-bk4.dts b/arch/arm/boot/dts/nxp/vf/vf610-bk4.dts similarity index 100% rename from arch/arm/boot/dts/vf610-bk4.dts rename to arch/arm/boot/dts/nxp/vf/vf610-bk4.dts diff --git a/arch/arm/boot/dts/vf610-colibri-eval-v3.dts b/arch/arm/boot/dts/nxp/vf/vf610-colibri-eval-v3.dts similarity index 100% rename from arch/arm/boot/dts/vf610-colibri-eval-v3.dts rename to arch/arm/boot/dts/nxp/vf/vf610-colibri-eval-v3.dts diff --git a/arch/arm/boot/dts/vf610-colibri.dtsi b/arch/arm/boot/dts/nxp/vf/vf610-colibri.dtsi similarity index 100% rename from arch/arm/boot/dts/vf610-colibri.dtsi rename to arch/arm/boot/dts/nxp/vf/vf610-colibri.dtsi diff --git a/arch/arm/boot/dts/vf610-cosmic.dts b/arch/arm/boot/dts/nxp/vf/vf610-cosmic.dts similarity index 100% rename from arch/arm/boot/dts/vf610-cosmic.dts rename to arch/arm/boot/dts/nxp/vf/vf610-cosmic.dts diff --git a/arch/arm/boot/dts/vf610-pinfunc.h b/arch/arm/boot/dts/nxp/vf/vf610-pinfunc.h similarity index 100% rename from arch/arm/boot/dts/vf610-pinfunc.h rename to arch/arm/boot/dts/nxp/vf/vf610-pinfunc.h diff --git a/arch/arm/boot/dts/vf610-twr.dts b/arch/arm/boot/dts/nxp/vf/vf610-twr.dts similarity index 100% rename from arch/arm/boot/dts/vf610-twr.dts rename to arch/arm/boot/dts/nxp/vf/vf610-twr.dts diff --git a/arch/arm/boot/dts/vf610-zii-cfu1.dts b/arch/arm/boot/dts/nxp/vf/vf610-zii-cfu1.dts similarity index 99% rename from arch/arm/boot/dts/vf610-zii-cfu1.dts rename to arch/arm/boot/dts/nxp/vf/vf610-zii-cfu1.dts index 96495d965163569483860930d1f3ac748936878b..1a19aec8957b744e4254931e8527d9829b5a70ac 100644 --- a/arch/arm/boot/dts/vf610-zii-cfu1.dts +++ b/arch/arm/boot/dts/nxp/vf/vf610-zii-cfu1.dts @@ -202,7 +202,7 @@ port@6 { reg = <6>; - label = "cpu"; + phy-mode = "rmii"; ethernet = <&fec1>; fixed-link { diff --git a/arch/arm/boot/dts/vf610-zii-dev-rev-b.dts b/arch/arm/boot/dts/nxp/vf/vf610-zii-dev-rev-b.dts similarity index 98% rename from arch/arm/boot/dts/vf610-zii-dev-rev-b.dts rename to arch/arm/boot/dts/nxp/vf/vf610-zii-dev-rev-b.dts index 6280c5e86a124e2f1547a2a7b74f7f4628db878d..16b4e06c4efad36e5a811d17cdafcb4753559b0a 100644 --- a/arch/arm/boot/dts/vf610-zii-dev-rev-b.dts +++ b/arch/arm/boot/dts/nxp/vf/vf610-zii-dev-rev-b.dts @@ -75,7 +75,7 @@ port@6 { reg = <6>; - label = "cpu"; + phy-mode = "rmii"; ethernet = <&fec1>; fixed-link { @@ -294,9 +294,9 @@ pinctrl-names = "default"; #address-cells = <1>; #size-cells = <0>; - gpio-sck = <&gpio1 12 GPIO_ACTIVE_HIGH>; - gpio-mosi = <&gpio1 11 GPIO_ACTIVE_HIGH>; - gpio-miso = <&gpio1 10 GPIO_ACTIVE_HIGH>; + sck-gpios = <&gpio1 12 GPIO_ACTIVE_HIGH>; + mosi-gpios = <&gpio1 11 GPIO_ACTIVE_HIGH>; + miso-gpios = <&gpio1 10 GPIO_ACTIVE_HIGH>; cs-gpios = <&gpio1 9 GPIO_ACTIVE_LOW &gpio1 8 GPIO_ACTIVE_HIGH>; num-chipselects = <2>; diff --git a/arch/arm/boot/dts/vf610-zii-dev-rev-c.dts b/arch/arm/boot/dts/nxp/vf/vf610-zii-dev-rev-c.dts similarity index 98% rename from arch/arm/boot/dts/vf610-zii-dev-rev-c.dts rename to arch/arm/boot/dts/nxp/vf/vf610-zii-dev-rev-c.dts index c00d39562a10bb9487785b8f77f5fb181fc0cb90..6f9878f124c44b49fce78f8026f733907da8c1c4 100644 --- a/arch/arm/boot/dts/vf610-zii-dev-rev-c.dts +++ b/arch/arm/boot/dts/nxp/vf/vf610-zii-dev-rev-c.dts @@ -44,7 +44,7 @@ port@0 { reg = <0>; - label = "cpu"; + phy-mode = "rmii"; ethernet = <&fec1>; fixed-link { @@ -82,6 +82,11 @@ label = "dsa"; phy-mode = "xaui"; link = <&switch1port10>; + + fixed-link { + speed = <10000>; + full-duplex; + }; }; }; @@ -174,6 +179,11 @@ label = "dsa"; phy-mode = "xaui"; link = <&switch0port10>; + + fixed-link { + speed = <10000>; + full-duplex; + }; }; }; mdio { diff --git a/arch/arm/boot/dts/vf610-zii-dev.dtsi b/arch/arm/boot/dts/nxp/vf/vf610-zii-dev.dtsi similarity index 100% rename from arch/arm/boot/dts/vf610-zii-dev.dtsi rename to arch/arm/boot/dts/nxp/vf/vf610-zii-dev.dtsi diff --git a/arch/arm/boot/dts/vf610-zii-scu4-aib.dts b/arch/arm/boot/dts/nxp/vf/vf610-zii-scu4-aib.dts similarity index 97% rename from arch/arm/boot/dts/vf610-zii-scu4-aib.dts rename to arch/arm/boot/dts/nxp/vf/vf610-zii-scu4-aib.dts index 7b3276cd470fbd54f57610041b64979bb6379e65..df1335492a199841483dc9facd40834fab48003c 100644 --- a/arch/arm/boot/dts/vf610-zii-scu4-aib.dts +++ b/arch/arm/boot/dts/nxp/vf/vf610-zii-scu4-aib.dts @@ -59,7 +59,7 @@ port@0 { reg = <0>; - label = "cpu"; + phy-mode = "rmii"; ethernet = <&fec1>; fixed-link { @@ -115,6 +115,11 @@ link = <&switch1port10 &switch3port10 &switch2port10>; + + fixed-link { + speed = <10000>; + full-duplex; + }; }; }; }; @@ -156,6 +161,11 @@ phy-mode = "xgmii"; link = <&switch3port10 &switch2port10>; + + fixed-link { + speed = <10000>; + full-duplex; + }; }; switch1port10: port@10 { @@ -163,6 +173,11 @@ label = "dsa"; phy-mode = "xgmii"; link = <&switch0port10>; + + fixed-link { + speed = <10000>; + full-duplex; + }; }; }; }; @@ -246,6 +261,11 @@ link = <&switch3port9 &switch1port9 &switch0port10>; + + fixed-link { + speed = <2500>; + full-duplex; + }; }; }; }; @@ -295,6 +315,11 @@ label = "dsa"; phy-mode = "2500base-x"; link = <&switch2port10>; + + fixed-link { + speed = <2500>; + full-duplex; + }; }; switch3port10: port@10 { @@ -303,6 +328,11 @@ phy-mode = "xgmii"; link = <&switch1port9 &switch0port10>; + + fixed-link { + speed = <10000>; + full-duplex; + }; }; }; }; diff --git a/arch/arm/boot/dts/vf610-zii-spb4.dts b/arch/arm/boot/dts/nxp/vf/vf610-zii-spb4.dts similarity index 99% rename from arch/arm/boot/dts/vf610-zii-spb4.dts rename to arch/arm/boot/dts/nxp/vf/vf610-zii-spb4.dts index 180acb0795b9e6fea995053c76c67805ecbff8ef..1461804ecaea3b74bf438663b82663aa8b087104 100644 --- a/arch/arm/boot/dts/vf610-zii-spb4.dts +++ b/arch/arm/boot/dts/nxp/vf/vf610-zii-spb4.dts @@ -140,7 +140,7 @@ port@0 { reg = <0>; - label = "cpu"; + phy-mode = "rmii"; ethernet = <&fec1>; fixed-link { diff --git a/arch/arm/boot/dts/vf610-zii-ssmb-dtu.dts b/arch/arm/boot/dts/nxp/vf/vf610-zii-ssmb-dtu.dts similarity index 99% rename from arch/arm/boot/dts/vf610-zii-ssmb-dtu.dts rename to arch/arm/boot/dts/nxp/vf/vf610-zii-ssmb-dtu.dts index 73fdace4cb42470b33aa9593a3cfb4792cc5ad69..463c2452b9b7f9e6ee02b0a8dcb90b415d64a171 100644 --- a/arch/arm/boot/dts/vf610-zii-ssmb-dtu.dts +++ b/arch/arm/boot/dts/nxp/vf/vf610-zii-ssmb-dtu.dts @@ -129,7 +129,7 @@ port@0 { reg = <0>; - label = "cpu"; + phy-mode = "rmii"; ethernet = <&fec1>; fixed-link { diff --git a/arch/arm/boot/dts/vf610-zii-ssmb-spu3.dts b/arch/arm/boot/dts/nxp/vf/vf610-zii-ssmb-spu3.dts similarity index 99% rename from arch/arm/boot/dts/vf610-zii-ssmb-spu3.dts rename to arch/arm/boot/dts/nxp/vf/vf610-zii-ssmb-spu3.dts index 20beaa8433b6cee26fa7c44c804579a927f29a44..f5ae0d5de31517374a5223518a8de924df1eaa03 100644 --- a/arch/arm/boot/dts/vf610-zii-ssmb-spu3.dts +++ b/arch/arm/boot/dts/nxp/vf/vf610-zii-ssmb-spu3.dts @@ -154,7 +154,7 @@ port@0 { reg = <0>; - label = "cpu"; + phy-mode = "rmii"; ethernet = <&fec1>; fixed-link { diff --git a/arch/arm/boot/dts/vf610.dtsi b/arch/arm/boot/dts/nxp/vf/vf610.dtsi similarity index 100% rename from arch/arm/boot/dts/vf610.dtsi rename to arch/arm/boot/dts/nxp/vf/vf610.dtsi diff --git a/arch/arm/boot/dts/vf610m4-colibri.dts b/arch/arm/boot/dts/nxp/vf/vf610m4-colibri.dts similarity index 100% rename from arch/arm/boot/dts/vf610m4-colibri.dts rename to arch/arm/boot/dts/nxp/vf/vf610m4-colibri.dts diff --git a/arch/arm/boot/dts/vf610m4-cosmic.dts b/arch/arm/boot/dts/nxp/vf/vf610m4-cosmic.dts similarity index 100% rename from arch/arm/boot/dts/vf610m4-cosmic.dts rename to arch/arm/boot/dts/nxp/vf/vf610m4-cosmic.dts diff --git a/arch/arm/boot/dts/vf610m4.dtsi b/arch/arm/boot/dts/nxp/vf/vf610m4.dtsi similarity index 98% rename from arch/arm/boot/dts/vf610m4.dtsi rename to arch/arm/boot/dts/nxp/vf/vf610m4.dtsi index 76bbfd5e32b699fb672520c8dce0c80da6d426bb..2bb331a87721000880cebeb81dd3c00febfbed3c 100644 --- a/arch/arm/boot/dts/vf610m4.dtsi +++ b/arch/arm/boot/dts/nxp/vf/vf610m4.dtsi @@ -42,7 +42,7 @@ * OTHER DEALINGS IN THE SOFTWARE. */ -#include "armv7-m.dtsi" +#include "../../armv7-m.dtsi" #include "vfxxx.dtsi" / { diff --git a/arch/arm/boot/dts/vfxxx.dtsi b/arch/arm/boot/dts/nxp/vf/vfxxx.dtsi similarity index 99% rename from arch/arm/boot/dts/vfxxx.dtsi rename to arch/arm/boot/dts/nxp/vf/vfxxx.dtsi index ff4479994b600c6eb8b23c885bb2575c628c77c3..3f7dc787938eec0d330e5fc383c5487c2caa3183 100644 --- a/arch/arm/boot/dts/vfxxx.dtsi +++ b/arch/arm/boot/dts/nxp/vf/vfxxx.dtsi @@ -294,7 +294,6 @@ reg = <0x4003e000 0x1000>; interrupts = <20 IRQ_TYPE_LEVEL_HIGH>; clocks = <&clks VF610_CLK_WDT>; - clock-names = "wdog"; status = "disabled"; }; diff --git a/arch/arm/boot/dts/qcom/Makefile b/arch/arm/boot/dts/qcom/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..3dfb1c8cefb86e91a04387703d5ddb646bf94c99 --- /dev/null +++ b/arch/arm/boot/dts/qcom/Makefile @@ -0,0 +1,45 @@ +# SPDX-License-Identifier: GPL-2.0 +dtb-$(CONFIG_ARCH_QCOM) += \ + qcom-apq8016-sbc.dtb \ + qcom-apq8026-asus-sparrow.dtb \ + qcom-apq8026-huawei-sturgeon.dtb \ + qcom-apq8026-lg-lenok.dtb \ + qcom-apq8026-samsung-matisse-wifi.dtb \ + qcom-apq8060-dragonboard.dtb \ + qcom-apq8064-cm-qs600.dtb \ + qcom-apq8064-ifc6410.dtb \ + qcom-apq8064-sony-xperia-lagan-yuga.dtb \ + qcom-apq8064-asus-nexus7-flo.dtb \ + qcom-apq8074-dragonboard.dtb \ + qcom-apq8084-ifc6540.dtb \ + qcom-apq8084-mtp.dtb \ + qcom-ipq4018-ap120c-ac.dtb \ + qcom-ipq4018-ap120c-ac-bit.dtb \ + qcom-ipq4018-jalapeno.dtb \ + qcom-ipq4019-ap.dk01.1-c1.dtb \ + qcom-ipq4019-ap.dk04.1-c1.dtb \ + qcom-ipq4019-ap.dk04.1-c3.dtb \ + qcom-ipq4019-ap.dk07.1-c1.dtb \ + qcom-ipq4019-ap.dk07.1-c2.dtb \ + qcom-ipq8064-ap148.dtb \ + qcom-ipq8064-rb3011.dtb \ + qcom-msm8226-samsung-s3ve3g.dtb \ + qcom-msm8660-surf.dtb \ + qcom-msm8916-samsung-e5.dtb \ + qcom-msm8916-samsung-e7.dtb \ + qcom-msm8916-samsung-grandmax.dtb \ + qcom-msm8916-samsung-serranove.dtb \ + qcom-msm8960-cdp.dtb \ + qcom-msm8960-samsung-expressatt.dtb \ + qcom-msm8974-lge-nexus5-hammerhead.dtb \ + qcom-msm8974-sony-xperia-rhine-amami.dtb \ + qcom-msm8974-sony-xperia-rhine-honami.dtb \ + qcom-msm8974pro-fairphone-fp2.dtb \ + qcom-msm8974pro-oneplus-bacon.dtb \ + qcom-msm8974pro-samsung-klte.dtb \ + qcom-msm8974pro-sony-xperia-shinano-castor.dtb \ + qcom-mdm9615-wp8548-mangoh-green.dtb \ + qcom-sdx55-mtp.dtb \ + qcom-sdx55-t55.dtb \ + qcom-sdx55-telit-fn980-tlb.dtb \ + qcom-sdx65-mtp.dtb diff --git a/arch/arm/boot/dts/qcom-apq8016-sbc.dts b/arch/arm/boot/dts/qcom/qcom-apq8016-sbc.dts similarity index 100% rename from arch/arm/boot/dts/qcom-apq8016-sbc.dts rename to arch/arm/boot/dts/qcom/qcom-apq8016-sbc.dts diff --git a/arch/arm/boot/dts/qcom-apq8026-asus-sparrow.dts b/arch/arm/boot/dts/qcom/qcom-apq8026-asus-sparrow.dts similarity index 100% rename from arch/arm/boot/dts/qcom-apq8026-asus-sparrow.dts rename to arch/arm/boot/dts/qcom/qcom-apq8026-asus-sparrow.dts diff --git a/arch/arm/boot/dts/qcom-apq8026-huawei-sturgeon.dts b/arch/arm/boot/dts/qcom/qcom-apq8026-huawei-sturgeon.dts similarity index 92% rename from arch/arm/boot/dts/qcom-apq8026-huawei-sturgeon.dts rename to arch/arm/boot/dts/qcom/qcom-apq8026-huawei-sturgeon.dts index 5593a3a60d6c4dc732db544bee5ea8a5c6a08a25..de19640efe5538349b4fb5740bce4786bec552f0 100644 --- a/arch/arm/boot/dts/qcom-apq8026-huawei-sturgeon.dts +++ b/arch/arm/boot/dts/qcom/qcom-apq8026-huawei-sturgeon.dts @@ -7,6 +7,7 @@ #include "qcom-msm8226.dtsi" #include "qcom-pm8226.dtsi" +#include /delete-node/ &adsp_region; @@ -68,6 +69,26 @@ status = "okay"; }; +&blsp1_i2c2 { + clock-frequency = <384000>; + + status = "okay"; + + vibrator@5a { + compatible = "ti,drv2605"; + reg = <0x5a>; + enable-gpios = <&tlmm 60 GPIO_ACTIVE_HIGH>; + + mode = ; + library-sel = ; + vib-rated-mv = <2765>; + vib-overdrive-mv = <3525>; + + pinctrl-0 = <&vibrator_default_state>; + pinctrl-names = "default"; + }; +}; + &blsp1_i2c5 { clock-frequency = <384000>; @@ -347,6 +368,13 @@ }; }; + vibrator_default_state: vibrator-default-state { + pins = "gpio59", "gpio60"; + function = "gpio"; + drive-strength = <2>; + bias-pull-down; + }; + wlan_hostwake_default_state: wlan-hostwake-default-state { pins = "gpio66"; function = "gpio"; diff --git a/arch/arm/boot/dts/qcom-apq8026-lg-lenok.dts b/arch/arm/boot/dts/qcom/qcom-apq8026-lg-lenok.dts similarity index 100% rename from arch/arm/boot/dts/qcom-apq8026-lg-lenok.dts rename to arch/arm/boot/dts/qcom/qcom-apq8026-lg-lenok.dts diff --git a/arch/arm/boot/dts/qcom-apq8026-samsung-matisse-wifi.dts b/arch/arm/boot/dts/qcom/qcom-apq8026-samsung-matisse-wifi.dts similarity index 99% rename from arch/arm/boot/dts/qcom-apq8026-samsung-matisse-wifi.dts rename to arch/arm/boot/dts/qcom/qcom-apq8026-samsung-matisse-wifi.dts index 91b860e24681f13210dc368ab2f2ca0cf53a619f..884d99297d4cf1eea2465a1297435c18f5618d9b 100644 --- a/arch/arm/boot/dts/qcom-apq8026-samsung-matisse-wifi.dts +++ b/arch/arm/boot/dts/qcom/qcom-apq8026-samsung-matisse-wifi.dts @@ -99,7 +99,6 @@ dev-ctrl = /bits/ 8 <0x80>; init-brt = /bits/ 8 <0x3f>; - pwm-period = <100000>; pwms = <&backlight_pwm 0 100000>; pwm-names = "lp8556"; diff --git a/arch/arm/boot/dts/qcom-apq8060-dragonboard.dts b/arch/arm/boot/dts/qcom/qcom-apq8060-dragonboard.dts similarity index 94% rename from arch/arm/boot/dts/qcom-apq8060-dragonboard.dts rename to arch/arm/boot/dts/qcom/qcom-apq8060-dragonboard.dts index 8e4b61e4d4b1750c8afe8404de9158f32d8dcb5f..db4c791b2e2fb27afdf2b9bf326375e3339f3e60 100644 --- a/arch/arm/boot/dts/qcom-apq8060-dragonboard.dts +++ b/arch/arm/boot/dts/qcom/qcom-apq8060-dragonboard.dts @@ -18,50 +18,46 @@ stdout-path = "serial0:115200n8"; }; - regulators { - compatible = "simple-bus"; - - /* Main power of the board: 3.7V */ - vph: regulator-fixed { - compatible = "regulator-fixed"; - regulator-min-microvolt = <3700000>; - regulator-max-microvolt = <3700000>; - regulator-name = "VPH"; - regulator-type = "voltage"; - regulator-always-on; - regulator-boot-on; - }; - - /* GPIO controlled ethernet power regulator */ - dragon_veth: xc622a331mrg { - compatible = "regulator-fixed"; - regulator-name = "XC6222A331MR-G"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - vin-supply = <&vph>; - gpio = <&pm8058_gpio 40 GPIO_ACTIVE_HIGH>; - enable-active-high; - pinctrl-names = "default"; - pinctrl-0 = <&dragon_veth_gpios>; - regulator-always-on; - }; + /* Main power of the board: 3.7V */ + vph: regulator-fixed { + compatible = "regulator-fixed"; + regulator-min-microvolt = <3700000>; + regulator-max-microvolt = <3700000>; + regulator-name = "VPH"; + regulator-type = "voltage"; + regulator-always-on; + regulator-boot-on; + }; + + /* GPIO controlled ethernet power regulator */ + dragon_veth: xc622a331mrg { + compatible = "regulator-fixed"; + regulator-name = "XC6222A331MR-G"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + vin-supply = <&vph>; + gpio = <&pm8058_gpio 40 GPIO_ACTIVE_HIGH>; + enable-active-high; + pinctrl-names = "default"; + pinctrl-0 = <&dragon_veth_gpios>; + regulator-always-on; + }; - /* VDDvario fixed regulator */ - dragon_vario: nds332p { - compatible = "regulator-fixed"; - regulator-name = "NDS332P"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - vin-supply = <&pm8058_s3>; - }; + /* VDDvario fixed regulator */ + dragon_vario: nds332p { + compatible = "regulator-fixed"; + regulator-name = "NDS332P"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + vin-supply = <&pm8058_s3>; + }; - /* This is a levelshifter for SDCC5 */ - dragon_vio_txb: txb0104rgyr { - compatible = "regulator-fixed"; - regulator-name = "Dragon SDCC levelshifter"; - vin-supply = <&pm8058_l14>; - regulator-always-on; - }; + /* This is a levelshifter for SDCC5 */ + dragon_vio_txb: txb0104rgyr { + compatible = "regulator-fixed"; + regulator-name = "Dragon SDCC levelshifter"; + vin-supply = <&pm8058_l14>; + regulator-always-on; }; /* @@ -451,7 +447,7 @@ * PM8901 supplies "preliminary regulators" whatever * that means */ - pm8901-regulators { + regulators-0 { vdd_l0-supply = <&pm8901_s4>; vdd_l1-supply = <&vph>; vdd_l2-supply = <&vph>; @@ -537,7 +533,7 @@ }; - pm8058-regulators { + regulators-1 { vdd_l0_l1_lvs-supply = <&pm8058_s3>; vdd_l2_l11_l12-supply = <&vph>; vdd_l3_l4_l5-supply = <&vph>; diff --git a/arch/arm/boot/dts/qcom-apq8064-asus-nexus7-flo.dts b/arch/arm/boot/dts/qcom/qcom-apq8064-asus-nexus7-flo.dts similarity index 100% rename from arch/arm/boot/dts/qcom-apq8064-asus-nexus7-flo.dts rename to arch/arm/boot/dts/qcom/qcom-apq8064-asus-nexus7-flo.dts diff --git a/arch/arm/boot/dts/qcom-apq8064-cm-qs600.dts b/arch/arm/boot/dts/qcom/qcom-apq8064-cm-qs600.dts similarity index 100% rename from arch/arm/boot/dts/qcom-apq8064-cm-qs600.dts rename to arch/arm/boot/dts/qcom/qcom-apq8064-cm-qs600.dts diff --git a/arch/arm/boot/dts/qcom-apq8064-ifc6410.dts b/arch/arm/boot/dts/qcom/qcom-apq8064-ifc6410.dts similarity index 100% rename from arch/arm/boot/dts/qcom-apq8064-ifc6410.dts rename to arch/arm/boot/dts/qcom/qcom-apq8064-ifc6410.dts diff --git a/arch/arm/boot/dts/qcom-apq8064-pins.dtsi b/arch/arm/boot/dts/qcom/qcom-apq8064-pins.dtsi similarity index 100% rename from arch/arm/boot/dts/qcom-apq8064-pins.dtsi rename to arch/arm/boot/dts/qcom/qcom-apq8064-pins.dtsi diff --git a/arch/arm/boot/dts/qcom-apq8064-sony-xperia-lagan-yuga.dts b/arch/arm/boot/dts/qcom/qcom-apq8064-sony-xperia-lagan-yuga.dts similarity index 100% rename from arch/arm/boot/dts/qcom-apq8064-sony-xperia-lagan-yuga.dts rename to arch/arm/boot/dts/qcom/qcom-apq8064-sony-xperia-lagan-yuga.dts diff --git a/arch/arm/boot/dts/qcom-apq8064-v2.0.dtsi b/arch/arm/boot/dts/qcom/qcom-apq8064-v2.0.dtsi similarity index 100% rename from arch/arm/boot/dts/qcom-apq8064-v2.0.dtsi rename to arch/arm/boot/dts/qcom/qcom-apq8064-v2.0.dtsi diff --git a/arch/arm/boot/dts/qcom-apq8064.dtsi b/arch/arm/boot/dts/qcom/qcom-apq8064.dtsi similarity index 100% rename from arch/arm/boot/dts/qcom-apq8064.dtsi rename to arch/arm/boot/dts/qcom/qcom-apq8064.dtsi diff --git a/arch/arm/boot/dts/qcom-apq8074-dragonboard.dts b/arch/arm/boot/dts/qcom/qcom-apq8074-dragonboard.dts similarity index 71% rename from arch/arm/boot/dts/qcom-apq8074-dragonboard.dts rename to arch/arm/boot/dts/qcom/qcom-apq8074-dragonboard.dts index 1345df7cbd002ce3c92e97a7e1381b17169c9af3..e0679436000bf077ef2f32f73611b39101616214 100644 --- a/arch/arm/boot/dts/qcom-apq8074-dragonboard.dts +++ b/arch/arm/boot/dts/qcom/qcom-apq8074-dragonboard.dts @@ -1,9 +1,14 @@ // SPDX-License-Identifier: GPL-2.0 #include +#include +#include +#include #include "qcom-msm8974.dtsi" #include "qcom-pm8841.dtsi" #include "qcom-pm8941.dtsi" +/delete-node/ &mpss_region; + / { model = "Qualcomm APQ8074 Dragonboard"; compatible = "qcom,apq8074-dragonboard", "qcom,apq8074"; @@ -17,12 +22,43 @@ chosen { stdout-path = "serial0:115200n8"; }; + + gpio-keys { + compatible = "gpio-keys"; + autorepeat; + + pinctrl-0 = <&msm_keys_default>; + pinctrl-names = "default"; + + button-volup { + label = "Volume Up"; + linux,code = ; + gpios = <&pm8941_gpios 5 GPIO_ACTIVE_LOW>; + }; + + button-general { + label = "General"; + linux,code = ; + gpios = <&pm8941_gpios 23 GPIO_ACTIVE_LOW>; + }; + }; + + reserved-memory { + mpss_region: mpss@ac00000 { + reg = <0x0ac00000 0x2500000>; + no-map; + }; + }; }; &blsp1_uart2 { status = "okay"; }; +&blsp2_dma { + qcom,controlled-remotely; +}; + &blsp2_i2c5 { status = "okay"; clock-frequency = <200000>; @@ -35,6 +71,119 @@ }; }; +&gpu { + status = "okay"; +}; + +&mdss { + status = "okay"; +}; + +&mdss_dsi0 { + vdda-supply = <&pm8941_l2>; + vdd-supply = <&pm8941_l22>; + vddio-supply = <&pm8941_l12>; + + status = "okay"; + + panel: panel@0 { + compatible = "sharp,ls043t1le01-qhd"; + reg = <0>; + + avdd-supply = <&pm8941_l22>; + backlight = <&pm8941_wled>; + reset-gpios = <&pm8941_gpios 19 GPIO_ACTIVE_HIGH>; + + port { + panel_in: endpoint { + remote-endpoint = <&mdss_dsi0_out>; + }; + }; + }; +}; + +&mdss_dsi0_out { + remote-endpoint = <&panel_in>; + data-lanes = <0 1 2 3>; +}; + +&mdss_dsi0_phy { + status = "okay"; + + vddio-supply = <&pm8941_l12>; +}; + +&gpu { + status = "okay"; +}; + +&mdss { + status = "okay"; +}; + +&pm8941_gpios { + msm_keys_default: pm8941-gpio-keys-state { + pins = "gpio5", "gpio23"; + function = "normal"; + input-enable; + drive-push-pull; + bias-pull-up; + qcom,drive-strength = ; + power-source = ; /* 1.8V */ + }; +}; + +&pm8941_lpg { + qcom,power-source = <1>; + status = "okay"; + + led@5 { + reg = <5>; + color = ; + function = LED_FUNCTION_INDICATOR; + }; + + led@6 { + reg = <6>; + color = ; + function = LED_FUNCTION_INDICATOR; + }; + + led@7 { + reg = <7>; + color = ; + function = LED_FUNCTION_INDICATOR; + }; +}; + +&pm8941_wled { + qcom,cs-out; + qcom,switching-freq = <3200>; + qcom,ovp = <32>; + qcom,num-strings = <1>; + + status = "okay"; +}; + +&remoteproc_adsp { + cx-supply = <&pm8841_s2>; + + firmware-name = "qcom/apq8074/adsp.mbn"; + + status = "okay"; +}; + +&remoteproc_mss { + cx-supply = <&pm8841_s2>; + mss-supply = <&pm8841_s3>; + mx-supply = <&pm8841_s1>; + pll-supply = <&pm8941_l12>; + + firmware-name = "qcom/apq8074/mba.mbn", "qcom/apq8074/modem.mbn"; + + status = "okay"; +}; + &rpm_requests { regulators-0 { compatible = "qcom,rpm-pm8841-regulators"; diff --git a/arch/arm/boot/dts/qcom-apq8084-ifc6540.dts b/arch/arm/boot/dts/qcom/qcom-apq8084-ifc6540.dts similarity index 100% rename from arch/arm/boot/dts/qcom-apq8084-ifc6540.dts rename to arch/arm/boot/dts/qcom/qcom-apq8084-ifc6540.dts diff --git a/arch/arm/boot/dts/qcom-apq8084-mtp.dts b/arch/arm/boot/dts/qcom/qcom-apq8084-mtp.dts similarity index 100% rename from arch/arm/boot/dts/qcom-apq8084-mtp.dts rename to arch/arm/boot/dts/qcom/qcom-apq8084-mtp.dts diff --git a/arch/arm/boot/dts/qcom-apq8084.dtsi b/arch/arm/boot/dts/qcom/qcom-apq8084.dtsi similarity index 99% rename from arch/arm/boot/dts/qcom-apq8084.dtsi rename to arch/arm/boot/dts/qcom/qcom-apq8084.dtsi index 83839e1ec4d16cc1534eb176c694e71111ba3213..8f178bc87e1d97519747c0ab90e69b9d27bd199e 100644 --- a/arch/arm/boot/dts/qcom-apq8084.dtsi +++ b/arch/arm/boot/dts/qcom/qcom-apq8084.dtsi @@ -507,7 +507,7 @@ }; }; - tsens: thermal-sensor@fc4a8000 { + tsens: thermal-sensor@fc4a9000 { compatible = "qcom,msm8974-tsens", "qcom,tsens-v0_1"; reg = <0xfc4a9000 0x1000>, /* TM */ <0xfc4a8000 0x1000>; /* SROT */ diff --git a/arch/arm/boot/dts/qcom-ipq4018-ap120c-ac-bit.dts b/arch/arm/boot/dts/qcom/qcom-ipq4018-ap120c-ac-bit.dts similarity index 100% rename from arch/arm/boot/dts/qcom-ipq4018-ap120c-ac-bit.dts rename to arch/arm/boot/dts/qcom/qcom-ipq4018-ap120c-ac-bit.dts diff --git a/arch/arm/boot/dts/qcom-ipq4018-ap120c-ac.dts b/arch/arm/boot/dts/qcom/qcom-ipq4018-ap120c-ac.dts similarity index 100% rename from arch/arm/boot/dts/qcom-ipq4018-ap120c-ac.dts rename to arch/arm/boot/dts/qcom/qcom-ipq4018-ap120c-ac.dts diff --git a/arch/arm/boot/dts/qcom-ipq4018-ap120c-ac.dtsi b/arch/arm/boot/dts/qcom/qcom-ipq4018-ap120c-ac.dtsi similarity index 100% rename from arch/arm/boot/dts/qcom-ipq4018-ap120c-ac.dtsi rename to arch/arm/boot/dts/qcom/qcom-ipq4018-ap120c-ac.dtsi diff --git a/arch/arm/boot/dts/qcom-ipq4018-jalapeno.dts b/arch/arm/boot/dts/qcom/qcom-ipq4018-jalapeno.dts similarity index 100% rename from arch/arm/boot/dts/qcom-ipq4018-jalapeno.dts rename to arch/arm/boot/dts/qcom/qcom-ipq4018-jalapeno.dts diff --git a/arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1-c1.dts b/arch/arm/boot/dts/qcom/qcom-ipq4019-ap.dk01.1-c1.dts similarity index 100% rename from arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1-c1.dts rename to arch/arm/boot/dts/qcom/qcom-ipq4019-ap.dk01.1-c1.dts diff --git a/arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1.dtsi b/arch/arm/boot/dts/qcom/qcom-ipq4019-ap.dk01.1.dtsi similarity index 100% rename from arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1.dtsi rename to arch/arm/boot/dts/qcom/qcom-ipq4019-ap.dk01.1.dtsi diff --git a/arch/arm/boot/dts/qcom-ipq4019-ap.dk04.1-c1.dts b/arch/arm/boot/dts/qcom/qcom-ipq4019-ap.dk04.1-c1.dts similarity index 87% rename from arch/arm/boot/dts/qcom-ipq4019-ap.dk04.1-c1.dts rename to arch/arm/boot/dts/qcom/qcom-ipq4019-ap.dk04.1-c1.dts index 79b0c6318e527db7b4eacf2157d9f372d689857d..0993f840d1fc78001a8a366435b022c1a980484e 100644 --- a/arch/arm/boot/dts/qcom-ipq4019-ap.dk04.1-c1.dts +++ b/arch/arm/boot/dts/qcom/qcom-ipq4019-ap.dk04.1-c1.dts @@ -11,9 +11,9 @@ dma-controller@7984000 { status = "okay"; }; - - qpic-nand@79b0000 { - status = "okay"; - }; }; }; + +&nand { + status = "okay"; +}; diff --git a/arch/arm/boot/dts/qcom-ipq4019-ap.dk04.1-c3.dts b/arch/arm/boot/dts/qcom/qcom-ipq4019-ap.dk04.1-c3.dts similarity index 100% rename from arch/arm/boot/dts/qcom-ipq4019-ap.dk04.1-c3.dts rename to arch/arm/boot/dts/qcom/qcom-ipq4019-ap.dk04.1-c3.dts diff --git a/arch/arm/boot/dts/qcom-ipq4019-ap.dk04.1.dtsi b/arch/arm/boot/dts/qcom/qcom-ipq4019-ap.dk04.1.dtsi similarity index 96% rename from arch/arm/boot/dts/qcom-ipq4019-ap.dk04.1.dtsi rename to arch/arm/boot/dts/qcom/qcom-ipq4019-ap.dk04.1.dtsi index a63b3778636d4d3b173521fbf7d01dacdaa40e71..468ebc40d2ad383c222f6b9d9bffd8bfd8dabc0d 100644 --- a/arch/arm/boot/dts/qcom-ipq4019-ap.dk04.1.dtsi +++ b/arch/arm/boot/dts/qcom/qcom-ipq4019-ap.dk04.1.dtsi @@ -102,10 +102,10 @@ status = "okay"; perst-gpios = <&tlmm 38 GPIO_ACTIVE_LOW>; }; - - qpic-nand@79b0000 { - pinctrl-0 = <&nand_pins>; - pinctrl-names = "default"; - }; }; }; + +&nand { + pinctrl-0 = <&nand_pins>; + pinctrl-names = "default"; +}; diff --git a/arch/arm/boot/dts/qcom-ipq4019-ap.dk07.1-c1.dts b/arch/arm/boot/dts/qcom/qcom-ipq4019-ap.dk07.1-c1.dts similarity index 100% rename from arch/arm/boot/dts/qcom-ipq4019-ap.dk07.1-c1.dts rename to arch/arm/boot/dts/qcom/qcom-ipq4019-ap.dk07.1-c1.dts diff --git a/arch/arm/boot/dts/qcom-ipq4019-ap.dk07.1-c2.dts b/arch/arm/boot/dts/qcom/qcom-ipq4019-ap.dk07.1-c2.dts similarity index 100% rename from arch/arm/boot/dts/qcom-ipq4019-ap.dk07.1-c2.dts rename to arch/arm/boot/dts/qcom/qcom-ipq4019-ap.dk07.1-c2.dts diff --git a/arch/arm/boot/dts/qcom-ipq4019-ap.dk07.1.dtsi b/arch/arm/boot/dts/qcom/qcom-ipq4019-ap.dk07.1.dtsi similarity index 92% rename from arch/arm/boot/dts/qcom-ipq4019-ap.dk07.1.dtsi rename to arch/arm/boot/dts/qcom/qcom-ipq4019-ap.dk07.1.dtsi index 0107f552f5204c0b01024b7127e786c34c8f8c1f..7ef635997efa4595ad9905cc6e562d14a401aa6c 100644 --- a/arch/arm/boot/dts/qcom-ipq4019-ap.dk07.1.dtsi +++ b/arch/arm/boot/dts/qcom/qcom-ipq4019-ap.dk07.1.dtsi @@ -65,11 +65,11 @@ dma-controller@7984000 { status = "okay"; }; - - qpic-nand@79b0000 { - pinctrl-0 = <&nand_pins>; - pinctrl-names = "default"; - status = "okay"; - }; }; }; + +&nand { + pinctrl-0 = <&nand_pins>; + pinctrl-names = "default"; + status = "okay"; +}; diff --git a/arch/arm/boot/dts/qcom-ipq4019.dtsi b/arch/arm/boot/dts/qcom/qcom-ipq4019.dtsi similarity index 100% rename from arch/arm/boot/dts/qcom-ipq4019.dtsi rename to arch/arm/boot/dts/qcom/qcom-ipq4019.dtsi diff --git a/arch/arm/boot/dts/qcom-ipq8062-smb208.dtsi b/arch/arm/boot/dts/qcom/qcom-ipq8062-smb208.dtsi similarity index 100% rename from arch/arm/boot/dts/qcom-ipq8062-smb208.dtsi rename to arch/arm/boot/dts/qcom/qcom-ipq8062-smb208.dtsi diff --git a/arch/arm/boot/dts/qcom-ipq8062.dtsi b/arch/arm/boot/dts/qcom/qcom-ipq8062.dtsi similarity index 100% rename from arch/arm/boot/dts/qcom-ipq8062.dtsi rename to arch/arm/boot/dts/qcom/qcom-ipq8062.dtsi diff --git a/arch/arm/boot/dts/qcom-ipq8064-ap148.dts b/arch/arm/boot/dts/qcom/qcom-ipq8064-ap148.dts similarity index 100% rename from arch/arm/boot/dts/qcom-ipq8064-ap148.dts rename to arch/arm/boot/dts/qcom/qcom-ipq8064-ap148.dts diff --git a/arch/arm/boot/dts/qcom-ipq8064-rb3011.dts b/arch/arm/boot/dts/qcom/qcom-ipq8064-rb3011.dts similarity index 99% rename from arch/arm/boot/dts/qcom-ipq8064-rb3011.dts rename to arch/arm/boot/dts/qcom/qcom-ipq8064-rb3011.dts index 4d509876294be3f29215f80071bcf009952b6021..104eb729c2d6c99317d5927311ae422a23c5f055 100644 --- a/arch/arm/boot/dts/qcom-ipq8064-rb3011.dts +++ b/arch/arm/boot/dts/qcom/qcom-ipq8064-rb3011.dts @@ -323,7 +323,7 @@ pinctrl-0 = <&leds_pins>; pinctrl-names = "default"; - led@7 { + led-0 { label = "rb3011:green:user"; color = ; gpios = <&qcom_pinmux 33 GPIO_ACTIVE_HIGH>; diff --git a/arch/arm/boot/dts/qcom-ipq8064-smb208.dtsi b/arch/arm/boot/dts/qcom/qcom-ipq8064-smb208.dtsi similarity index 100% rename from arch/arm/boot/dts/qcom-ipq8064-smb208.dtsi rename to arch/arm/boot/dts/qcom/qcom-ipq8064-smb208.dtsi diff --git a/arch/arm/boot/dts/qcom-ipq8064-v1.0.dtsi b/arch/arm/boot/dts/qcom/qcom-ipq8064-v1.0.dtsi similarity index 97% rename from arch/arm/boot/dts/qcom-ipq8064-v1.0.dtsi rename to arch/arm/boot/dts/qcom/qcom-ipq8064-v1.0.dtsi index 411c8d63c38e10e6ed027452b82e835edbbebf5c..c5abe7151f14299392fd4d98e02fc72a5f1794da 100644 --- a/arch/arm/boot/dts/qcom-ipq8064-v1.0.dtsi +++ b/arch/arm/boot/dts/qcom/qcom-ipq8064-v1.0.dtsi @@ -92,34 +92,34 @@ pinctrl-0 = <&leds_pins>; pinctrl-names = "default"; - led@7 { + led-0 { label = "led_usb1"; gpios = <&qcom_pinmux 7 GPIO_ACTIVE_HIGH>; linux,default-trigger = "usbdev"; default-state = "off"; }; - led@8 { + led-1 { label = "led_usb3"; gpios = <&qcom_pinmux 8 GPIO_ACTIVE_HIGH>; linux,default-trigger = "usbdev"; default-state = "off"; }; - led@9 { + led-2 { label = "status_led_fail"; function = LED_FUNCTION_STATUS; gpios = <&qcom_pinmux 9 GPIO_ACTIVE_HIGH>; default-state = "off"; }; - led@26 { + led-3 { label = "sata_led"; gpios = <&qcom_pinmux 26 GPIO_ACTIVE_HIGH>; default-state = "off"; }; - led@53 { + led-4 { label = "status_led_pass"; function = LED_FUNCTION_STATUS; gpios = <&qcom_pinmux 53 GPIO_ACTIVE_HIGH>; diff --git a/arch/arm/boot/dts/qcom-ipq8064-v2.0-smb208.dtsi b/arch/arm/boot/dts/qcom/qcom-ipq8064-v2.0-smb208.dtsi similarity index 100% rename from arch/arm/boot/dts/qcom-ipq8064-v2.0-smb208.dtsi rename to arch/arm/boot/dts/qcom/qcom-ipq8064-v2.0-smb208.dtsi diff --git a/arch/arm/boot/dts/qcom-ipq8064-v2.0.dtsi b/arch/arm/boot/dts/qcom/qcom-ipq8064-v2.0.dtsi similarity index 100% rename from arch/arm/boot/dts/qcom-ipq8064-v2.0.dtsi rename to arch/arm/boot/dts/qcom/qcom-ipq8064-v2.0.dtsi diff --git a/arch/arm/boot/dts/qcom-ipq8064.dtsi b/arch/arm/boot/dts/qcom/qcom-ipq8064.dtsi similarity index 99% rename from arch/arm/boot/dts/qcom-ipq8064.dtsi rename to arch/arm/boot/dts/qcom/qcom-ipq8064.dtsi index 7581845737a8b507fcfab4cfb5547bc89c382484..6198f42f6a9c7f36c92148fb3e62af321e5f7b57 100644 --- a/arch/arm/boot/dts/qcom-ipq8064.dtsi +++ b/arch/arm/boot/dts/qcom/qcom-ipq8064.dtsi @@ -521,7 +521,7 @@ #reset-cells = <1>; #power-domain-cells = <1>; - tsens: thermal-sensor@900000 { + tsens: thermal-sensor { compatible = "qcom,ipq8064-tsens"; nvmem-cells = <&tsens_calib>, <&tsens_calib_backup>; @@ -607,12 +607,12 @@ regulator; }; - nss_common: syscon@03000000 { + nss_common: syscon@3000000 { compatible = "syscon"; reg = <0x03000000 0x0000FFFF>; }; - usb3_0: usb3@100f8800 { + usb3_0: usb@100f8800 { compatible = "qcom,ipq8064-dwc3", "qcom,dwc3"; #address-cells = <1>; #size-cells = <1>; @@ -627,7 +627,7 @@ status = "disabled"; - dwc3_0: dwc3@10000000 { + dwc3_0: usb@10000000 { compatible = "snps,dwc3"; reg = <0x10000000 0xcd00>; interrupts = ; @@ -658,7 +658,7 @@ status = "disabled"; }; - usb3_1: usb3@110f8800 { + usb3_1: usb@110f8800 { compatible = "qcom,ipq8064-dwc3", "qcom,dwc3"; #address-cells = <1>; #size-cells = <1>; @@ -673,7 +673,7 @@ status = "disabled"; - dwc3_1: dwc3@11000000 { + dwc3_1: usb@11000000 { compatible = "snps,dwc3"; reg = <0x11000000 0xcd00>; interrupts = ; diff --git a/arch/arm/boot/dts/qcom-ipq8065-smb208.dtsi b/arch/arm/boot/dts/qcom/qcom-ipq8065-smb208.dtsi similarity index 100% rename from arch/arm/boot/dts/qcom-ipq8065-smb208.dtsi rename to arch/arm/boot/dts/qcom/qcom-ipq8065-smb208.dtsi diff --git a/arch/arm/boot/dts/qcom-ipq8065.dtsi b/arch/arm/boot/dts/qcom/qcom-ipq8065.dtsi similarity index 100% rename from arch/arm/boot/dts/qcom-ipq8065.dtsi rename to arch/arm/boot/dts/qcom/qcom-ipq8065.dtsi diff --git a/arch/arm/boot/dts/qcom-mdm9615-wp8548-mangoh-green.dts b/arch/arm/boot/dts/qcom/qcom-mdm9615-wp8548-mangoh-green.dts similarity index 100% rename from arch/arm/boot/dts/qcom-mdm9615-wp8548-mangoh-green.dts rename to arch/arm/boot/dts/qcom/qcom-mdm9615-wp8548-mangoh-green.dts diff --git a/arch/arm/boot/dts/qcom-mdm9615-wp8548.dtsi b/arch/arm/boot/dts/qcom/qcom-mdm9615-wp8548.dtsi similarity index 100% rename from arch/arm/boot/dts/qcom-mdm9615-wp8548.dtsi rename to arch/arm/boot/dts/qcom/qcom-mdm9615-wp8548.dtsi diff --git a/arch/arm/boot/dts/qcom-mdm9615.dtsi b/arch/arm/boot/dts/qcom/qcom-mdm9615.dtsi similarity index 100% rename from arch/arm/boot/dts/qcom-mdm9615.dtsi rename to arch/arm/boot/dts/qcom/qcom-mdm9615.dtsi diff --git a/arch/arm/boot/dts/qcom-msm8226-samsung-s3ve3g.dts b/arch/arm/boot/dts/qcom/qcom-msm8226-samsung-s3ve3g.dts similarity index 100% rename from arch/arm/boot/dts/qcom-msm8226-samsung-s3ve3g.dts rename to arch/arm/boot/dts/qcom/qcom-msm8226-samsung-s3ve3g.dts diff --git a/arch/arm/boot/dts/qcom-msm8226.dtsi b/arch/arm/boot/dts/qcom/qcom-msm8226.dtsi similarity index 78% rename from arch/arm/boot/dts/qcom-msm8226.dtsi rename to arch/arm/boot/dts/qcom/qcom-msm8226.dtsi index 42acb9ddb8ccb15730dc8d7dd1b9c692e9e9a78e..313a726f470475edf61a667d3d8f0a91be4d8f2c 100644 --- a/arch/arm/boot/dts/qcom-msm8226.dtsi +++ b/arch/arm/boot/dts/qcom/qcom-msm8226.dtsi @@ -47,6 +47,12 @@ }; }; + pmu { + compatible = "arm,cortex-a7-pmu"; + interrupts = ; + }; + reserved-memory { #address-cells = <1>; #size-cells = <1>; @@ -176,7 +182,7 @@ interrupt-names = "hc_irq", "pwr_irq"; clocks = <&gcc GCC_SDCC1_AHB_CLK>, <&gcc GCC_SDCC1_APPS_CLK>, - <&xo_board>; + <&rpmcc RPM_SMD_XO_CLK_SRC>; clock-names = "iface", "core", "xo"; pinctrl-names = "default"; pinctrl-0 = <&sdhc1_default_state>; @@ -192,7 +198,7 @@ interrupt-names = "hc_irq", "pwr_irq"; clocks = <&gcc GCC_SDCC2_AHB_CLK>, <&gcc GCC_SDCC2_APPS_CLK>, - <&xo_board>; + <&rpmcc RPM_SMD_XO_CLK_SRC>; clock-names = "iface", "core", "xo"; pinctrl-names = "default"; pinctrl-0 = <&sdhc2_default_state>; @@ -208,7 +214,7 @@ interrupt-names = "hc_irq", "pwr_irq"; clocks = <&gcc GCC_SDCC3_AHB_CLK>, <&gcc GCC_SDCC3_APPS_CLK>, - <&xo_board>; + <&rpmcc RPM_SMD_XO_CLK_SRC>; clock-names = "iface", "core", "xo"; pinctrl-names = "default"; pinctrl-0 = <&sdhc3_default_state>; @@ -362,7 +368,8 @@ compatible = "qcom,usb-hs-phy-msm8226", "qcom,usb-hs-phy"; #phy-cells = <0>; - clocks = <&xo_board>, <&gcc GCC_USB2A_PHY_SLEEP_CLK>; + clocks = <&rpmcc RPM_SMD_XO_CLK_SRC>, + <&gcc GCC_USB2A_PHY_SLEEP_CLK>; clock-names = "ref", "sleep"; resets = <&gcc GCC_USB2A_PHY_BCR>, <&usb 0>; reset-names = "phy", "por"; @@ -391,6 +398,21 @@ #clock-cells = <1>; #reset-cells = <1>; #power-domain-cells = <1>; + + clocks = <&rpmcc RPM_SMD_XO_CLK_SRC>, + <&gcc GCC_MMSS_GPLL0_CLK_SRC>, + <&gcc GPLL0_VOTE>, + <&gcc GPLL1_VOTE>, + <&rpmcc RPM_SMD_GFX3D_CLK_SRC>, + <0>, + <0>; + clock-names = "xo", + "mmss_gpll0_vote", + "gpll0_vote", + "gpll1_vote", + "gfx3d_clk_src", + "dsi0pll", + "dsi0pllbyte"; }; tlmm: pinctrl@fd510000 { @@ -506,11 +528,131 @@ }; }; + tsens: thermal-sensor@fc4a9000 { + compatible = "qcom,msm8226-tsens", "qcom,tsens-v0_1"; + reg = <0xfc4a9000 0x1000>, /* TM */ + <0xfc4a8000 0x1000>; /* SROT */ + nvmem-cells = <&tsens_mode>, + <&tsens_base1>, <&tsens_base2>, + <&tsens_s0_p1>, <&tsens_s0_p2>, + <&tsens_s1_p1>, <&tsens_s1_p2>, + <&tsens_s2_p1>, <&tsens_s2_p2>, + <&tsens_s3_p1>, <&tsens_s3_p2>, + <&tsens_s4_p1>, <&tsens_s4_p2>, + <&tsens_s5_p1>, <&tsens_s5_p2>, + <&tsens_s6_p1>, <&tsens_s6_p2>; + nvmem-cell-names = "mode", + "base1", "base2", + "s0_p1", "s0_p2", + "s1_p1", "s1_p2", + "s2_p1", "s2_p2", + "s3_p1", "s3_p2", + "s4_p1", "s4_p2", + "s5_p1", "s5_p2", + "s6_p1", "s6_p2"; + #qcom,sensors = <6>; + interrupts = ; + interrupt-names = "uplow"; + #thermal-sensor-cells = <1>; + }; + restart@fc4ab000 { compatible = "qcom,pshold"; reg = <0xfc4ab000 0x4>; }; + qfprom: qfprom@fc4bc000 { + compatible = "qcom,msm8226-qfprom", "qcom,qfprom"; + reg = <0xfc4bc000 0x1000>; + #address-cells = <1>; + #size-cells = <1>; + + tsens_base1: base1@1c1 { + reg = <0x1c1 0x2>; + bits = <5 8>; + }; + + tsens_s0_p1: s0-p1@1c2 { + reg = <0x1c2 0x2>; + bits = <5 6>; + }; + + tsens_s1_p1: s1-p1@1c4 { + reg = <0x1c4 0x1>; + bits = <0 6>; + }; + + tsens_s2_p1: s2-p1@1c4 { + reg = <0x1c4 0x2>; + bits = <6 6>; + }; + + tsens_s3_p1: s3-p1@1c5 { + reg = <0x1c5 0x2>; + bits = <4 6>; + }; + + tsens_s4_p1: s4-p1@1c6 { + reg = <0x1c6 0x1>; + bits = <2 6>; + }; + + tsens_s5_p1: s5-p1@1c7 { + reg = <0x1c7 0x1>; + bits = <0 6>; + }; + + tsens_s6_p1: s6-p1@1ca { + reg = <0x1ca 0x2>; + bits = <4 6>; + }; + + tsens_base2: base2@1cc { + reg = <0x1cc 0x1>; + bits = <0 8>; + }; + + tsens_s0_p2: s0-p2@1cd { + reg = <0x1cd 0x1>; + bits = <0 6>; + }; + + tsens_s1_p2: s1-p2@1cd { + reg = <0x1cd 0x2>; + bits = <6 6>; + }; + + tsens_s2_p2: s2-p2@1ce { + reg = <0x1ce 0x2>; + bits = <4 6>; + }; + + tsens_s3_p2: s3-p2@1cf { + reg = <0x1cf 0x1>; + bits = <2 6>; + }; + + tsens_s4_p2: s4-p2@446 { + reg = <0x446 0x2>; + bits = <4 6>; + }; + + tsens_s5_p2: s5-p2@447 { + reg = <0x447 0x1>; + bits = <2 6>; + }; + + tsens_s6_p2: s6-p2@44e { + reg = <0x44e 0x1>; + bits = <1 6>; + }; + + tsens_mode: mode@44f { + reg = <0x44f 0x1>; + bits = <5 3>; + }; + }; + spmi_bus: spmi@fc4cf000 { compatible = "qcom,spmi-pmic-arb"; reg-names = "core", "intr", "cnfg"; @@ -592,6 +734,11 @@ }; }; + sram@fc190000 { + compatible = "qcom,msm8226-rpm-stats"; + reg = <0xfc190000 0x10000>; + }; + rpm_msg_ram: sram@fc428000 { compatible = "qcom,rpm-msg-ram"; reg = <0xfc428000 0x4000>; @@ -617,7 +764,7 @@ power-domains = <&rpmpd MSM8226_VDDCX>; power-domain-names = "cx"; - clocks = <&xo_board>; + clocks = <&rpmcc RPM_SMD_XO_CLK_SRC>; clock-names = "xo"; memory-region = <&adsp_region>; @@ -636,6 +783,64 @@ label = "lpass"; }; }; + + sram@fe805000 { + compatible = "qcom,msm8226-imem", "syscon", "simple-mfd"; + reg = <0xfe805000 0x1000>; + + reboot-mode { + compatible = "syscon-reboot-mode"; + offset = <0x65c>; + + mode-bootloader = <0x77665500>; + mode-normal = <0x77665501>; + mode-recovery = <0x77665502>; + }; + }; + }; + + thermal-zones { + cpu0-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens 5>; + + trips { + cpu_alert0: trip0 { + temperature = <75000>; + hysteresis = <2000>; + type = "passive"; + }; + + cpu_crit0: trip1 { + temperature = <110000>; + hysteresis = <2000>; + type = "critical"; + }; + }; + }; + + cpu1-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens 2>; + + trips { + cpu_alert1: trip0 { + temperature = <75000>; + hysteresis = <2000>; + type = "passive"; + }; + + cpu_crit1: trip1 { + temperature = <110000>; + hysteresis = <2000>; + type = "critical"; + }; + }; + }; }; timer { diff --git a/arch/arm/boot/dts/qcom-msm8660-surf.dts b/arch/arm/boot/dts/qcom/qcom-msm8660-surf.dts similarity index 100% rename from arch/arm/boot/dts/qcom-msm8660-surf.dts rename to arch/arm/boot/dts/qcom/qcom-msm8660-surf.dts diff --git a/arch/arm/boot/dts/qcom-msm8660.dtsi b/arch/arm/boot/dts/qcom/qcom-msm8660.dtsi similarity index 100% rename from arch/arm/boot/dts/qcom-msm8660.dtsi rename to arch/arm/boot/dts/qcom/qcom-msm8660.dtsi diff --git a/arch/arm/boot/dts/qcom-msm8916-samsung-e5.dts b/arch/arm/boot/dts/qcom/qcom-msm8916-samsung-e5.dts similarity index 100% rename from arch/arm/boot/dts/qcom-msm8916-samsung-e5.dts rename to arch/arm/boot/dts/qcom/qcom-msm8916-samsung-e5.dts diff --git a/arch/arm/boot/dts/qcom-msm8916-samsung-e7.dts b/arch/arm/boot/dts/qcom/qcom-msm8916-samsung-e7.dts similarity index 100% rename from arch/arm/boot/dts/qcom-msm8916-samsung-e7.dts rename to arch/arm/boot/dts/qcom/qcom-msm8916-samsung-e7.dts diff --git a/arch/arm/boot/dts/qcom-msm8916-samsung-grandmax.dts b/arch/arm/boot/dts/qcom/qcom-msm8916-samsung-grandmax.dts similarity index 100% rename from arch/arm/boot/dts/qcom-msm8916-samsung-grandmax.dts rename to arch/arm/boot/dts/qcom/qcom-msm8916-samsung-grandmax.dts diff --git a/arch/arm/boot/dts/qcom-msm8916-samsung-serranove.dts b/arch/arm/boot/dts/qcom/qcom-msm8916-samsung-serranove.dts similarity index 100% rename from arch/arm/boot/dts/qcom-msm8916-samsung-serranove.dts rename to arch/arm/boot/dts/qcom/qcom-msm8916-samsung-serranove.dts diff --git a/arch/arm/boot/dts/qcom-msm8916-smp.dtsi b/arch/arm/boot/dts/qcom/qcom-msm8916-smp.dtsi similarity index 100% rename from arch/arm/boot/dts/qcom-msm8916-smp.dtsi rename to arch/arm/boot/dts/qcom/qcom-msm8916-smp.dtsi diff --git a/arch/arm/boot/dts/qcom-msm8960-cdp.dts b/arch/arm/boot/dts/qcom/qcom-msm8960-cdp.dts similarity index 96% rename from arch/arm/boot/dts/qcom-msm8960-cdp.dts rename to arch/arm/boot/dts/qcom/qcom-msm8960-cdp.dts index 8fa2befa629aec1c7bcd303a73ff7c38fc75429b..6c1bc3818883ca34f014e02e1c13e8c08ae717e8 100644 --- a/arch/arm/boot/dts/qcom-msm8960-cdp.dts +++ b/arch/arm/boot/dts/qcom/qcom-msm8960-cdp.dts @@ -15,16 +15,12 @@ stdout-path = "serial0:115200n8"; }; - regulators { - compatible = "simple-bus"; - - ext_l2: gpio-regulator { - compatible = "regulator-fixed"; - regulator-name = "ext_l2"; - gpio = <&msmgpio 91 0>; - startup-delay-us = <10000>; - enable-active-high; - }; + ext_l2: gpio-regulator { + compatible = "regulator-fixed"; + regulator-name = "ext_l2"; + gpio = <&msmgpio 91 0>; + startup-delay-us = <10000>; + enable-active-high; }; }; diff --git a/arch/arm/boot/dts/qcom/qcom-msm8960-samsung-expressatt.dts b/arch/arm/boot/dts/qcom/qcom-msm8960-samsung-expressatt.dts new file mode 100644 index 0000000000000000000000000000000000000000..13e85c2874987110b44ac1947cfdadc6e68d01b8 --- /dev/null +++ b/arch/arm/boot/dts/qcom/qcom-msm8960-samsung-expressatt.dts @@ -0,0 +1,331 @@ +// SPDX-License-Identifier: GPL-2.0 +#include + +#include "qcom-msm8960.dtsi" +#include + +/ { + model = "Samsung Galaxy Express SGH-I437"; + compatible = "samsung,expressatt", "qcom,msm8960"; + chassis-type = "handset"; + + aliases { + serial0 = &gsbi5_serial; + mmc0 = &sdcc1; /* SDCC1 eMMC slot */ + mmc1 = &sdcc3; /* SDCC3 SD card slot */ + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; +}; + +&gsbi5 { + qcom,mode = ; + status = "okay"; +}; + +&gsbi5_serial { + status = "okay"; +}; + +&sdcc1 { + vmmc-supply = <&pm8921_l5>; + status = "okay"; +}; + +&sdcc3 { + vmmc-supply = <&pm8921_l6>; + vqmmc-supply = <&pm8921_l7>; + status = "okay"; +}; + +&gsbi1 { + qcom,mode = ; + pinctrl-0 = <&spi1_default>; + pinctrl-names = "default"; + status = "okay"; +}; + +&gsbi1_spi { + status = "okay"; +}; + +&msmgpio { + spi1_default: spi1-default-state { + mosi-pins { + pins = "gpio6"; + function = "gsbi1"; + drive-strength = <12>; + bias-disable; + }; + + miso-pins { + pins = "gpio7"; + function = "gsbi1"; + drive-strength = <12>; + bias-disable; + }; + + cs-pins { + pins = "gpio8"; + function = "gsbi1"; + drive-strength = <12>; + bias-disable; + output-low; + }; + + clk-pins { + pins = "gpio9"; + function = "gsbi1"; + drive-strength = <12>; + bias-disable; + }; + }; +}; + +&rpm { + regulators { + compatible = "qcom,rpm-pm8921-regulators"; + vin_lvs1_3_6-supply = <&pm8921_s4>; + vin_lvs2-supply = <&pm8921_s4>; + vin_lvs4_5_7-supply = <&pm8921_s4>; + vdd_ncp-supply = <&pm8921_l6>; + vdd_l1_l2_l12_l18-supply = <&pm8921_s4>; + vdd_l21_l23_l29-supply = <&pm8921_s8>; + vdd_l24-supply = <&pm8921_s1>; + vdd_l25-supply = <&pm8921_s1>; + vdd_l27-supply = <&pm8921_s7>; + vdd_l28-supply = <&pm8921_s7>; + + /* Buck SMPS */ + pm8921_s1: s1 { + regulator-always-on; + regulator-min-microvolt = <1225000>; + regulator-max-microvolt = <1225000>; + qcom,switch-mode-frequency = <3200000>; + bias-pull-down; + }; + + pm8921_s2: s2 { + regulator-min-microvolt = <1300000>; + regulator-max-microvolt = <1300000>; + qcom,switch-mode-frequency = <1600000>; + bias-pull-down; + }; + + pm8921_s3: s3 { + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <1150000>; + qcom,switch-mode-frequency = <4800000>; + bias-pull-down; + }; + + pm8921_s4: s4 { + regulator-always-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + qcom,switch-mode-frequency = <1600000>; + bias-pull-down; + qcom,force-mode = ; + }; + + pm8921_s7: s7 { + regulator-min-microvolt = <1150000>; + regulator-max-microvolt = <1150000>; + qcom,switch-mode-frequency = <3200000>; + bias-pull-down; + }; + + pm8921_s8: s8 { + regulator-always-on; + regulator-min-microvolt = <2050000>; + regulator-max-microvolt = <2050000>; + qcom,switch-mode-frequency = <1600000>; + bias-pull-down; + }; + + /* PMOS LDO */ + pm8921_l1: l1 { + regulator-always-on; + regulator-min-microvolt = <1050000>; + regulator-max-microvolt = <1050000>; + bias-pull-down; + }; + + pm8921_l2: l2 { + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + bias-pull-down; + }; + + pm8921_l3: l3 { + regulator-min-microvolt = <3075000>; + regulator-max-microvolt = <3300000>; + bias-pull-down; + }; + + pm8921_l4: l4 { + regulator-always-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + bias-pull-down; + }; + + pm8921_l5: l5 { + regulator-min-microvolt = <2950000>; + regulator-max-microvolt = <2950000>; + bias-pull-down; + }; + + pm8921_l6: l6 { + regulator-min-microvolt = <2950000>; + regulator-max-microvolt = <2950000>; + bias-pull-down; + }; + + pm8921_l7: l7 { + regulator-always-on; + regulator-min-microvolt = <1850000>; + regulator-max-microvolt = <2950000>; + bias-pull-down; + }; + + pm8921_l8: l8 { + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3100000>; + bias-pull-down; + }; + + pm8921_l9: l9 { + regulator-min-microvolt = <2850000>; + regulator-max-microvolt = <2850000>; + bias-pull-down; + }; + + pm8921_l10: l10 { + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + bias-pull-down; + }; + + pm8921_l11: l11 { + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <3300000>; + bias-pull-down; + }; + + pm8921_l12: l12 { + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + bias-pull-down; + }; + + pm8921_l14: l14 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + bias-pull-down; + }; + + pm8921_l15: l15 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <2950000>; + bias-pull-down; + }; + + pm8921_l16: l16 { + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <3000000>; + bias-pull-down; + }; + + pm8921_l17: l17 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + bias-pull-down; + }; + + pm8921_l18: l18 { + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1500000>; + bias-pull-down; + }; + + pm8921_l21: l21 { + regulator-min-microvolt = <1900000>; + regulator-max-microvolt = <1900000>; + bias-pull-down; + }; + + pm8921_l22: l22 { + regulator-min-microvolt = <2750000>; + regulator-max-microvolt = <2750000>; + bias-pull-down; + }; + + pm8921_l23: l23 { + regulator-always-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + bias-pull-down; + }; + + pm8921_l24: l24 { + regulator-min-microvolt = <750000>; + regulator-max-microvolt = <1150000>; + bias-pull-down; + }; + + pm8921_l25: l25 { + regulator-always-on; + regulator-min-microvolt = <1225000>; + regulator-max-microvolt = <1225000>; + bias-pull-down; + }; + + /* Low Voltage Switch */ + pm8921_lvs1: lvs1 { + bias-pull-down; + }; + + pm8921_lvs2: lvs2 { + bias-pull-down; + }; + + pm8921_lvs3: lvs3 { + bias-pull-down; + }; + + pm8921_lvs4: lvs4 { + bias-pull-down; + }; + + pm8921_lvs5: lvs5 { + bias-pull-down; + }; + + pm8921_lvs6: lvs6 { + bias-pull-down; + }; + + pm8921_lvs7: lvs7 { + bias-pull-down; + }; + + pm8921_ncp: ncp { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + qcom,switch-mode-frequency = <1600000>; + }; + }; +}; + +&usb_hs1_phy { + v3p3-supply = <&pm8921_l3>; + v1p8-supply = <&pm8921_l4>; +}; + +&usb1 { + dr_mode = "otg"; + status = "okay"; +}; diff --git a/arch/arm/boot/dts/qcom-msm8960.dtsi b/arch/arm/boot/dts/qcom/qcom-msm8960.dtsi similarity index 90% rename from arch/arm/boot/dts/qcom-msm8960.dtsi rename to arch/arm/boot/dts/qcom/qcom-msm8960.dtsi index 616fef2ea682570c6c49634525a309bdc55a585d..fa2013388d997a4bf98de02766e5c8f7bd0c39bf 100644 --- a/arch/arm/boot/dts/qcom-msm8960.dtsi +++ b/arch/arm/boot/dts/qcom/qcom-msm8960.dtsi @@ -3,6 +3,7 @@ #include #include +#include #include #include #include @@ -72,7 +73,7 @@ clock-output-names = "pxo_board"; }; - sleep_clk { + sleep_clk: sleep_clk { compatible = "fixed-clock"; #clock-cells = <0>; clock-frequency = <32768>; @@ -371,5 +372,36 @@ status = "disabled"; }; }; + + usb1: usb@12500000 { + compatible = "qcom,ci-hdrc"; + reg = <0x12500000 0x200>, + <0x12500200 0x200>; + interrupts = ; + clocks = <&gcc USB_HS1_XCVR_CLK>, <&gcc USB_HS1_H_CLK>; + clock-names = "core", "iface"; + assigned-clocks = <&gcc USB_HS1_XCVR_CLK>; + assigned-clock-rates = <60000000>; + resets = <&gcc USB_HS1_RESET>; + reset-names = "core"; + phy_type = "ulpi"; + ahb-burst-config = <0>; + phys = <&usb_hs1_phy>; + phy-names = "usb-phy"; + #reset-cells = <1>; + status = "disabled"; + + ulpi { + usb_hs1_phy: phy { + compatible = "qcom,usb-hs-phy-msm8960", + "qcom,usb-hs-phy"; + clocks = <&sleep_clk>, <&cxo_board>; + clock-names = "sleep", "ref"; + resets = <&usb1 0>; + reset-names = "por"; + #phy-cells = <0>; + }; + }; + }; }; }; diff --git a/arch/arm/boot/dts/qcom-msm8974-lge-nexus5-hammerhead.dts b/arch/arm/boot/dts/qcom/qcom-msm8974-lge-nexus5-hammerhead.dts similarity index 94% rename from arch/arm/boot/dts/qcom-msm8974-lge-nexus5-hammerhead.dts rename to arch/arm/boot/dts/qcom/qcom-msm8974-lge-nexus5-hammerhead.dts index 861695cecf84e5f57b2ecbaff4895e124b7ad672..60bdfddeae69eb828831d06192d2ca20fd539cf1 100644 --- a/arch/arm/boot/dts/qcom-msm8974-lge-nexus5-hammerhead.dts +++ b/arch/arm/boot/dts/qcom/qcom-msm8974-lge-nexus5-hammerhead.dts @@ -41,6 +41,25 @@ }; }; + clk_pwm: pwm { + compatible = "clk-pwm"; + clocks = <&mmcc CAMSS_GP1_CLK>; + + pinctrl-0 = <&vibrator_pin>; + pinctrl-names = "default"; + + #pwm-cells = <2>; + }; + + vibrator { + compatible = "pwm-vibrator"; + pwms = <&clk_pwm 0 100000>; + pwm-names = "enable"; + + vcc-supply = <&pm8941_l19>; + enable-gpios = <&tlmm 60 GPIO_ACTIVE_HIGH>; + }; + vreg_wlan: wlan-regulator { compatible = "regulator-fixed"; @@ -211,7 +230,11 @@ }; }; -&dsi0 { +&mdss { + status = "okay"; +}; + +&mdss_dsi0 { status = "okay"; vdda-supply = <&pm8941_l2>; @@ -227,27 +250,23 @@ port { panel_in: endpoint { - remote-endpoint = <&dsi0_out>; + remote-endpoint = <&mdss_dsi0_out>; }; }; }; }; -&dsi0_out { +&mdss_dsi0_out { remote-endpoint = <&panel_in>; data-lanes = <0 1 2 3>; }; -&dsi0_phy { +&mdss_dsi0_phy { status = "okay"; vddio-supply = <&pm8941_l12>; }; -&mdss { - status = "okay"; -}; - &pm8941_gpios { gpio_keys_pin_a: gpio-keys-active-state { pins = "gpio2", "gpio3"; @@ -635,6 +654,22 @@ function = "gpio"; }; }; + + vibrator_pin: vibrator-state { + core-pins { + pins = "gpio27"; + function = "gp1_clk"; + drive-strength = <6>; + bias-disable; + }; + + enable-pins { + pins = "gpio60"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + }; }; &usb { diff --git a/arch/arm/boot/dts/qcom-msm8974-sony-xperia-rhine-amami.dts b/arch/arm/boot/dts/qcom/qcom-msm8974-sony-xperia-rhine-amami.dts similarity index 100% rename from arch/arm/boot/dts/qcom-msm8974-sony-xperia-rhine-amami.dts rename to arch/arm/boot/dts/qcom/qcom-msm8974-sony-xperia-rhine-amami.dts diff --git a/arch/arm/boot/dts/qcom-msm8974-sony-xperia-rhine-honami.dts b/arch/arm/boot/dts/qcom/qcom-msm8974-sony-xperia-rhine-honami.dts similarity index 100% rename from arch/arm/boot/dts/qcom-msm8974-sony-xperia-rhine-honami.dts rename to arch/arm/boot/dts/qcom/qcom-msm8974-sony-xperia-rhine-honami.dts diff --git a/arch/arm/boot/dts/qcom-msm8974-sony-xperia-rhine.dtsi b/arch/arm/boot/dts/qcom/qcom-msm8974-sony-xperia-rhine.dtsi similarity index 100% rename from arch/arm/boot/dts/qcom-msm8974-sony-xperia-rhine.dtsi rename to arch/arm/boot/dts/qcom/qcom-msm8974-sony-xperia-rhine.dtsi diff --git a/arch/arm/boot/dts/qcom-msm8974.dtsi b/arch/arm/boot/dts/qcom/qcom-msm8974.dtsi similarity index 98% rename from arch/arm/boot/dts/qcom-msm8974.dtsi rename to arch/arm/boot/dts/qcom/qcom-msm8974.dtsi index 7ed0d925a4e9903a362d62010adba97aef0b7141..aeca504918a0820f9ff4b1242455160d524bbfe9 100644 --- a/arch/arm/boot/dts/qcom-msm8974.dtsi +++ b/arch/arm/boot/dts/qcom/qcom-msm8974.dtsi @@ -301,7 +301,7 @@ qcom,ipc = <&apcs 8 0>; qcom,smd-edge = <15>; - rpm_requests: rpm_requests { + rpm_requests: rpm-requests { compatible = "qcom,rpm-msm8974"; qcom,smd-channels = "rpm_requests"; @@ -676,7 +676,7 @@ #reset-cells = <1>; ulpi { - usb_hs1_phy: phy@a { + usb_hs1_phy: phy-0 { compatible = "qcom,usb-hs-phy-msm8974", "qcom,usb-hs-phy"; #phy-cells = <0>; @@ -687,7 +687,7 @@ status = "disabled"; }; - usb_hs2_phy: phy@b { + usb_hs2_phy: phy-1 { compatible = "qcom,usb-hs-phy-msm8974", "qcom,usb-hs-phy"; #phy-cells = <0>; @@ -707,7 +707,7 @@ clock-names = "core"; }; - pronto: remoteproc@fb21b000 { + pronto: remoteproc@fb204000 { compatible = "qcom,pronto-v2-pil", "qcom,pronto"; reg = <0xfb204000 0x2000>, <0xfb202000 0x1000>, <0xfb21b000 0x3000>; reg-names = "ccu", "dxe", "pmu"; @@ -746,7 +746,7 @@ qcom,mmio = <&pronto>; - bt { + bluetooth { compatible = "qcom,wcnss-bt"; }; @@ -1837,10 +1837,10 @@ <&gcc GPLL0_VOTE>, <&gcc GPLL1_VOTE>, <&rpmcc RPM_SMD_GFX3D_CLK_SRC>, - <&dsi0_phy 1>, - <&dsi0_phy 0>, - <&dsi1_phy 1>, - <&dsi1_phy 0>, + <&mdss_dsi0_phy 1>, + <&mdss_dsi0_phy 0>, + <&mdss_dsi1_phy 1>, + <&mdss_dsi1_phy 0>, <0>, <0>, <0>; @@ -1905,20 +1905,20 @@ port@0 { reg = <0>; mdp5_intf1_out: endpoint { - remote-endpoint = <&dsi0_in>; + remote-endpoint = <&mdss_dsi0_in>; }; }; port@1 { reg = <1>; mdp5_intf2_out: endpoint { - remote-endpoint = <&dsi1_in>; + remote-endpoint = <&mdss_dsi1_in>; }; }; }; }; - dsi0: dsi@fd922800 { + mdss_dsi0: dsi@fd922800 { compatible = "qcom,msm8974-dsi-ctrl", "qcom,mdss-dsi-ctrl"; reg = <0xfd922800 0x1f8>; @@ -1928,7 +1928,7 @@ interrupts = <4>; assigned-clocks = <&mmcc BYTE0_CLK_SRC>, <&mmcc PCLK0_CLK_SRC>; - assigned-clock-parents = <&dsi0_phy 0>, <&dsi0_phy 1>; + assigned-clock-parents = <&mdss_dsi0_phy 0>, <&mdss_dsi0_phy 1>; clocks = <&mmcc MDSS_MDP_CLK>, <&mmcc MDSS_AHB_CLK>, @@ -1945,7 +1945,7 @@ "core", "core_mmss"; - phys = <&dsi0_phy>; + phys = <&mdss_dsi0_phy>; status = "disabled"; @@ -1958,20 +1958,20 @@ port@0 { reg = <0>; - dsi0_in: endpoint { + mdss_dsi0_in: endpoint { remote-endpoint = <&mdp5_intf1_out>; }; }; port@1 { reg = <1>; - dsi0_out: endpoint { + mdss_dsi0_out: endpoint { }; }; }; }; - dsi0_phy: phy@fd922a00 { + mdss_dsi0_phy: phy@fd922a00 { compatible = "qcom,dsi-phy-28nm-hpm"; reg = <0xfd922a00 0xd4>, <0xfd922b00 0x280>, @@ -1989,7 +1989,7 @@ status = "disabled"; }; - dsi1: dsi@fd922e00 { + mdss_dsi1: dsi@fd922e00 { compatible = "qcom,msm8974-dsi-ctrl", "qcom,mdss-dsi-ctrl"; reg = <0xfd922e00 0x1f8>; @@ -1999,7 +1999,7 @@ interrupts = <4>; assigned-clocks = <&mmcc BYTE1_CLK_SRC>, <&mmcc PCLK1_CLK_SRC>; - assigned-clock-parents = <&dsi1_phy 0>, <&dsi1_phy 1>; + assigned-clock-parents = <&mdss_dsi1_phy 0>, <&mdss_dsi1_phy 1>; clocks = <&mmcc MDSS_MDP_CLK>, <&mmcc MDSS_AHB_CLK>, @@ -2016,7 +2016,7 @@ "core", "core_mmss"; - phys = <&dsi1_phy>; + phys = <&mdss_dsi1_phy>; status = "disabled"; @@ -2029,20 +2029,20 @@ port@0 { reg = <0>; - dsi1_in: endpoint { + mdss_dsi1_in: endpoint { remote-endpoint = <&mdp5_intf2_out>; }; }; port@1 { reg = <1>; - dsi1_out: endpoint { + mdss_dsi1_out: endpoint { }; }; }; }; - dsi1_phy: phy@fd923000 { + mdss_dsi1_phy: phy@fd923000 { compatible = "qcom,dsi-phy-28nm-hpm"; reg = <0xfd923000 0xd4>, <0xfd923100 0x280>, diff --git a/arch/arm/boot/dts/qcom-msm8974pro-fairphone-fp2.dts b/arch/arm/boot/dts/qcom/qcom-msm8974pro-fairphone-fp2.dts similarity index 100% rename from arch/arm/boot/dts/qcom-msm8974pro-fairphone-fp2.dts rename to arch/arm/boot/dts/qcom/qcom-msm8974pro-fairphone-fp2.dts diff --git a/arch/arm/boot/dts/qcom-msm8974pro-oneplus-bacon.dts b/arch/arm/boot/dts/qcom/qcom-msm8974pro-oneplus-bacon.dts similarity index 100% rename from arch/arm/boot/dts/qcom-msm8974pro-oneplus-bacon.dts rename to arch/arm/boot/dts/qcom/qcom-msm8974pro-oneplus-bacon.dts diff --git a/arch/arm/boot/dts/qcom-msm8974pro-samsung-klte.dts b/arch/arm/boot/dts/qcom/qcom-msm8974pro-samsung-klte.dts similarity index 99% rename from arch/arm/boot/dts/qcom-msm8974pro-samsung-klte.dts rename to arch/arm/boot/dts/qcom/qcom-msm8974pro-samsung-klte.dts index eb505d6d7f31f656ec575e7bd89071c5306e89ae..3e2c86591ee2f79ef8af323279bac754f302c29e 100644 --- a/arch/arm/boot/dts/qcom-msm8974pro-samsung-klte.dts +++ b/arch/arm/boot/dts/qcom/qcom-msm8974pro-samsung-klte.dts @@ -329,7 +329,15 @@ }; }; -&dsi0 { +&gpu { + status = "okay"; +}; + +&mdss { + status = "okay"; +}; + +&mdss_dsi0 { status = "okay"; vdda-supply = <&pma8084_l2>; @@ -351,31 +359,23 @@ port { panel_in: endpoint { - remote-endpoint = <&dsi0_out>; + remote-endpoint = <&mdss_dsi0_out>; }; }; }; }; -&dsi0_out { +&mdss_dsi0_out { remote-endpoint = <&panel_in>; data-lanes = <0 1 2 3>; }; -&dsi0_phy { +&mdss_dsi0_phy { status = "okay"; vddio-supply = <&pma8084_l12>; }; -&gpu { - status = "okay"; -}; - -&mdss { - status = "okay"; -}; - &pma8084_gpios { gpio_keys_pin_a: gpio-keys-active-state { pins = "gpio2", "gpio3", "gpio5"; diff --git a/arch/arm/boot/dts/qcom-msm8974pro-sony-xperia-shinano-castor.dts b/arch/arm/boot/dts/qcom/qcom-msm8974pro-sony-xperia-shinano-castor.dts similarity index 98% rename from arch/arm/boot/dts/qcom-msm8974pro-sony-xperia-shinano-castor.dts rename to arch/arm/boot/dts/qcom/qcom-msm8974pro-sony-xperia-shinano-castor.dts index 0f650ed3100523854453c66411b8c26606a41531..154639d56f357b338fb6d3fcbcb98254c1ff6433 100644 --- a/arch/arm/boot/dts/qcom-msm8974pro-sony-xperia-shinano-castor.dts +++ b/arch/arm/boot/dts/qcom/qcom-msm8974pro-sony-xperia-shinano-castor.dts @@ -150,47 +150,48 @@ bl-name = "backlight"; dev-ctrl = /bits/ 8 <0x05>; init-brt = /bits/ 8 <0x3f>; - rom_a0h { + + rom-a0h { rom-addr = /bits/ 8 <0xa0>; rom-val = /bits/ 8 <0xff>; }; - rom_a1h { + rom-a1h { rom-addr = /bits/ 8 <0xa1>; rom-val = /bits/ 8 <0x3f>; }; - rom_a2h { + rom-a2h { rom-addr = /bits/ 8 <0xa2>; rom-val = /bits/ 8 <0x20>; }; - rom_a3h { + rom-a3h { rom-addr = /bits/ 8 <0xa3>; rom-val = /bits/ 8 <0x5e>; }; - rom_a4h { + rom-a4h { rom-addr = /bits/ 8 <0xa4>; rom-val = /bits/ 8 <0x02>; }; - rom_a5h { + rom-a5h { rom-addr = /bits/ 8 <0xa5>; rom-val = /bits/ 8 <0x04>; }; - rom_a6h { + rom-a6h { rom-addr = /bits/ 8 <0xa6>; rom-val = /bits/ 8 <0x80>; }; - rom_a7h { + rom-a7h { rom-addr = /bits/ 8 <0xa7>; rom-val = /bits/ 8 <0xf7>; }; - rom_a9h { + rom-a9h { rom-addr = /bits/ 8 <0xa9>; rom-val = /bits/ 8 <0x80>; }; - rom_aah { + rom-aah { rom-addr = /bits/ 8 <0xaa>; rom-val = /bits/ 8 <0x0f>; }; - rom_aeh { + rom-aeh { rom-addr = /bits/ 8 <0xae>; rom-val = /bits/ 8 <0x0f>; }; diff --git a/arch/arm/boot/dts/qcom-msm8974pro.dtsi b/arch/arm/boot/dts/qcom/qcom-msm8974pro.dtsi similarity index 100% rename from arch/arm/boot/dts/qcom-msm8974pro.dtsi rename to arch/arm/boot/dts/qcom/qcom-msm8974pro.dtsi diff --git a/arch/arm/boot/dts/qcom-pm8226.dtsi b/arch/arm/boot/dts/qcom/qcom-pm8226.dtsi similarity index 81% rename from arch/arm/boot/dts/qcom-pm8226.dtsi rename to arch/arm/boot/dts/qcom/qcom-pm8226.dtsi index 46ba84f86c9f180d4cd893822a3be63cb971326b..3b8ad28cecb0d6a53f1b5aba11f3aa3d059a675c 100644 --- a/arch/arm/boot/dts/qcom-pm8226.dtsi +++ b/arch/arm/boot/dts/qcom/qcom-pm8226.dtsi @@ -4,6 +4,36 @@ #include #include +/ { + thermal-zones { + pm8226-thermal { + polling-delay-passive = <100>; + polling-delay = <0>; + thermal-sensors = <&pm8226_temp>; + + trips { + trip0 { + temperature = <105000>; + hysteresis = <2000>; + type = "passive"; + }; + + trip1 { + temperature = <125000>; + hysteresis = <2000>; + type = "hot"; + }; + + crit { + temperature = <145000>; + hysteresis = <2000>; + type = "critical"; + }; + }; + }; + }; +}; + &spmi_bus { pm8226_0: pm8226@0 { compatible = "qcom,pm8226", "qcom,spmi-pmic"; @@ -55,6 +85,15 @@ chg_otg: otg-vbus { }; }; + pm8226_temp: temp-alarm@2400 { + compatible = "qcom,spmi-temp-alarm"; + reg = <0x2400>; + interrupts = <0 0x24 0 IRQ_TYPE_EDGE_RISING>; + io-channels = <&pm8226_vadc VADC_DIE_TEMP>; + io-channel-names = "thermal"; + #thermal-sensor-cells = <0>; + }; + pm8226_vadc: adc@3100 { compatible = "qcom,spmi-vadc"; reg = <0x3100>; diff --git a/arch/arm/boot/dts/qcom-pm8841.dtsi b/arch/arm/boot/dts/qcom/qcom-pm8841.dtsi similarity index 62% rename from arch/arm/boot/dts/qcom-pm8841.dtsi rename to arch/arm/boot/dts/qcom/qcom-pm8841.dtsi index b5cdde034d188f6add87a02b4d5c9feed4e0867c..3bf2ce5c86a6418536f2250ddc58206d7958d5d7 100644 --- a/arch/arm/boot/dts/qcom-pm8841.dtsi +++ b/arch/arm/boot/dts/qcom/qcom-pm8841.dtsi @@ -2,6 +2,37 @@ #include #include + +/ { + thermal-zones { + pm8841-thermal { + polling-delay-passive = <100>; + polling-delay = <0>; + thermal-sensors = <&pm8841_temp>; + + trips { + trip0 { + temperature = <105000>; + hysteresis = <2000>; + type = "passive"; + }; + + trip1 { + temperature = <125000>; + hysteresis = <2000>; + type = "hot"; + }; + + crit { + temperature = <140000>; + hysteresis = <2000>; + type = "critical"; + }; + }; + }; + }; +}; + &spmi_bus { pm8841_0: pm8841@4 { @@ -20,7 +51,7 @@ #interrupt-cells = <2>; }; - temp-alarm@2400 { + pm8841_temp: temp-alarm@2400 { compatible = "qcom,spmi-temp-alarm"; reg = <0x2400>; interrupts = <4 0x24 0 IRQ_TYPE_EDGE_RISING>; diff --git a/arch/arm/boot/dts/qcom-pm8941.dtsi b/arch/arm/boot/dts/qcom/qcom-pm8941.dtsi similarity index 91% rename from arch/arm/boot/dts/qcom-pm8941.dtsi rename to arch/arm/boot/dts/qcom/qcom-pm8941.dtsi index a821f0368a28921dedc25bb05de8c2c1da8a282c..b3e246bacd78c7e89d819bb6c06ed7471332897e 100644 --- a/arch/arm/boot/dts/qcom-pm8941.dtsi +++ b/arch/arm/boot/dts/qcom/qcom-pm8941.dtsi @@ -3,6 +3,37 @@ #include #include + +/ { + thermal-zones { + pm8941-thermal { + polling-delay-passive = <100>; + polling-delay = <0>; + thermal-sensors = <&pm8941_temp>; + + trips { + trip0 { + temperature = <105000>; + hysteresis = <2000>; + type = "passive"; + }; + + trip1 { + temperature = <125000>; + hysteresis = <2000>; + type = "hot"; + }; + + crit { + temperature = <145000>; + hysteresis = <2000>; + type = "critical"; + }; + }; + }; + }; +}; + &spmi_bus { pm8941_0: pm8941@0 { diff --git a/arch/arm/boot/dts/qcom-pma8084.dtsi b/arch/arm/boot/dts/qcom/qcom-pma8084.dtsi similarity index 100% rename from arch/arm/boot/dts/qcom-pma8084.dtsi rename to arch/arm/boot/dts/qcom/qcom-pma8084.dtsi diff --git a/arch/arm/boot/dts/qcom-pmx55.dtsi b/arch/arm/boot/dts/qcom/qcom-pmx55.dtsi similarity index 100% rename from arch/arm/boot/dts/qcom-pmx55.dtsi rename to arch/arm/boot/dts/qcom/qcom-pmx55.dtsi diff --git a/arch/arm/boot/dts/qcom-pmx65.dtsi b/arch/arm/boot/dts/qcom/qcom-pmx65.dtsi similarity index 100% rename from arch/arm/boot/dts/qcom-pmx65.dtsi rename to arch/arm/boot/dts/qcom/qcom-pmx65.dtsi diff --git a/arch/arm/boot/dts/qcom-sdx55-mtp.dts b/arch/arm/boot/dts/qcom/qcom-sdx55-mtp.dts similarity index 100% rename from arch/arm/boot/dts/qcom-sdx55-mtp.dts rename to arch/arm/boot/dts/qcom/qcom-sdx55-mtp.dts diff --git a/arch/arm/boot/dts/qcom-sdx55-t55.dts b/arch/arm/boot/dts/qcom/qcom-sdx55-t55.dts similarity index 100% rename from arch/arm/boot/dts/qcom-sdx55-t55.dts rename to arch/arm/boot/dts/qcom/qcom-sdx55-t55.dts diff --git a/arch/arm/boot/dts/qcom-sdx55-telit-fn980-tlb.dts b/arch/arm/boot/dts/qcom/qcom-sdx55-telit-fn980-tlb.dts similarity index 100% rename from arch/arm/boot/dts/qcom-sdx55-telit-fn980-tlb.dts rename to arch/arm/boot/dts/qcom/qcom-sdx55-telit-fn980-tlb.dts diff --git a/arch/arm/boot/dts/qcom-sdx55.dtsi b/arch/arm/boot/dts/qcom/qcom-sdx55.dtsi similarity index 99% rename from arch/arm/boot/dts/qcom-sdx55.dtsi rename to arch/arm/boot/dts/qcom/qcom-sdx55.dtsi index 342c3d14001eba55702450dbf5f48d01386053f1..df3cd9c4ffb933c4b5cbbdf1e33144629bb37f00 100644 --- a/arch/arm/boot/dts/qcom-sdx55.dtsi +++ b/arch/arm/boot/dts/qcom/qcom-sdx55.dtsi @@ -421,6 +421,10 @@ ; interrupt-names = "global", "doorbell"; + + interconnects = <&system_noc MASTER_PCIE &mc_virt SLAVE_EBI_CH0>; + interconnect-names = "pcie-mem"; + resets = <&gcc GCC_PCIE_BCR>; reset-names = "core"; power-domains = <&gcc PCIE_GDSC>; @@ -515,7 +519,7 @@ #hwlock-cells = <1>; }; - tcsr: syscon@1fcb000 { + tcsr: syscon@1fc0000 { compatible = "qcom,sdx55-tcsr", "syscon"; reg = <0x01fc0000 0x1000>; }; @@ -792,7 +796,7 @@ }; }; - apps_rsc: rsc@17840000 { + apps_rsc: rsc@17830000 { compatible = "qcom,rpmh-rsc"; reg = <0x17830000 0x10000>, <0x17840000 0x10000>; reg-names = "drv-0", "drv-1"; diff --git a/arch/arm/boot/dts/qcom-sdx65-mtp.dts b/arch/arm/boot/dts/qcom/qcom-sdx65-mtp.dts similarity index 89% rename from arch/arm/boot/dts/qcom-sdx65-mtp.dts rename to arch/arm/boot/dts/qcom/qcom-sdx65-mtp.dts index 57bc3b03d3aacfd6e0b6c892c3b1c8e635527f2e..02d8d6e241ae16477f50984853f4d5253b9e4e36 100644 --- a/arch/arm/boot/dts/qcom-sdx65-mtp.dts +++ b/arch/arm/boot/dts/qcom/qcom-sdx65-mtp.dts @@ -250,6 +250,25 @@ status = "okay"; }; +&pcie_ep { + pinctrl-0 = <&pcie_ep_clkreq_default + &pcie_ep_perst_default + &pcie_ep_wake_default>; + pinctrl-names = "default"; + + reset-gpios = <&tlmm 57 GPIO_ACTIVE_LOW>; + wake-gpios = <&tlmm 53 GPIO_ACTIVE_LOW>; + + status = "okay"; +}; + +&pcie_phy { + vdda-phy-supply = <&vreg_l1b_1p2>; + vdda-pll-supply = <&vreg_l4b_0p88>; + + status = "okay"; +}; + &qpic_bam { status = "okay"; }; @@ -274,6 +293,29 @@ status = "okay"; }; +&tlmm { + pcie_ep_clkreq_default: pcie-ep-clkreq-default-state { + pins = "gpio56"; + function = "pcie_clkreq"; + drive-strength = <2>; + bias-disable; + }; + + pcie_ep_perst_default: pcie-ep-perst-default-state { + pins = "gpio57"; + function = "gpio"; + drive-strength = <2>; + bias-pull-down; + }; + + pcie_ep_wake_default: pcie-ep-wake-default-state { + pins = "gpio53"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; +}; + &usb { status = "okay"; }; diff --git a/arch/arm/boot/dts/qcom-sdx65.dtsi b/arch/arm/boot/dts/qcom/qcom-sdx65.dtsi similarity index 89% rename from arch/arm/boot/dts/qcom-sdx65.dtsi rename to arch/arm/boot/dts/qcom/qcom-sdx65.dtsi index 525dd8a1f664952910c6f0ea54a704d9b2d84222..1a3583029a649e1bdb705f969bf60d8f781dac1f 100644 --- a/arch/arm/boot/dts/qcom-sdx65.dtsi +++ b/arch/arm/boot/dts/qcom/qcom-sdx65.dtsi @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -295,12 +296,98 @@ status = "disabled"; }; + pcie_ep: pcie-ep@1c00000 { + compatible = "qcom,sdx65-pcie-ep", "qcom,sdx55-pcie-ep"; + reg = <0x01c00000 0x3000>, + <0x40000000 0xf1d>, + <0x40000f20 0xa8>, + <0x40001000 0x1000>, + <0x40200000 0x100000>, + <0x01c03000 0x3000>; + reg-names = "parf", + "dbi", + "elbi", + "atu", + "addr_space", + "mmio"; + + qcom,perst-regs = <&tcsr 0xb258 0xb270>; + + clocks = <&gcc GCC_PCIE_AUX_CLK>, + <&gcc GCC_PCIE_CFG_AHB_CLK>, + <&gcc GCC_PCIE_MSTR_AXI_CLK>, + <&gcc GCC_PCIE_SLV_AXI_CLK>, + <&gcc GCC_PCIE_SLV_Q2A_AXI_CLK>, + <&gcc GCC_PCIE_SLEEP_CLK>, + <&gcc GCC_PCIE_0_CLKREF_EN>; + clock-names = "aux", + "cfg", + "bus_master", + "bus_slave", + "slave_q2a", + "sleep", + "ref"; + + interrupts = , + ; + interrupt-names = "global", "doorbell"; + + resets = <&gcc GCC_PCIE_BCR>; + reset-names = "core"; + + power-domains = <&gcc PCIE_GDSC>; + + phys = <&pcie_phy>; + phy-names = "pcie-phy"; + + max-link-speed = <3>; + num-lanes = <2>; + + status = "disabled"; + }; + + pcie_phy: phy@1c06000 { + compatible = "qcom,sdx65-qmp-gen4x2-pcie-phy"; + reg = <0x01c06000 0x2000>; + + clocks = <&gcc GCC_PCIE_AUX_PHY_CLK_SRC>, + <&gcc GCC_PCIE_CFG_AHB_CLK>, + <&gcc GCC_PCIE_0_CLKREF_EN>, + <&gcc GCC_PCIE_RCHNG_PHY_CLK>, + <&gcc GCC_PCIE_PIPE_CLK>; + clock-names = "aux", + "cfg_ahb", + "ref", + "rchng", + "pipe"; + + resets = <&gcc GCC_PCIE_PHY_BCR>; + reset-names = "phy"; + + assigned-clocks = <&gcc GCC_PCIE_RCHNG_PHY_CLK>; + assigned-clock-rates = <100000000>; + + power-domains = <&gcc PCIE_GDSC>; + + #clock-cells = <0>; + clock-output-names = "pcie_pipe_clk"; + + #phy-cells = <0>; + + status = "disabled"; + }; + tcsr_mutex: hwlock@1f40000 { compatible = "qcom,tcsr-mutex"; reg = <0x01f40000 0x40000>; #hwlock-cells = <1>; }; + tcsr: syscon@1fcb000 { + compatible = "qcom,sdx65-tcsr", "syscon"; + reg = <0x01fc0000 0x1000>; + }; + ipa: ipa@3f40000 { compatible = "qcom,sdx65-ipa"; diff --git a/arch/arm/boot/dts/realtek/Makefile b/arch/arm/boot/dts/realtek/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..c83671b5560fb058e27ebdc2a2b11cbe84b45969 --- /dev/null +++ b/arch/arm/boot/dts/realtek/Makefile @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 +dtb-$(CONFIG_ARCH_REALTEK) += \ + rtd1195-horseradish.dtb \ + rtd1195-mele-x1000.dtb diff --git a/arch/arm/boot/dts/rtd1195-horseradish.dts b/arch/arm/boot/dts/realtek/rtd1195-horseradish.dts similarity index 100% rename from arch/arm/boot/dts/rtd1195-horseradish.dts rename to arch/arm/boot/dts/realtek/rtd1195-horseradish.dts diff --git a/arch/arm/boot/dts/rtd1195-mele-x1000.dts b/arch/arm/boot/dts/realtek/rtd1195-mele-x1000.dts similarity index 100% rename from arch/arm/boot/dts/rtd1195-mele-x1000.dts rename to arch/arm/boot/dts/realtek/rtd1195-mele-x1000.dts diff --git a/arch/arm/boot/dts/rtd1195.dtsi b/arch/arm/boot/dts/realtek/rtd1195.dtsi similarity index 100% rename from arch/arm/boot/dts/rtd1195.dtsi rename to arch/arm/boot/dts/realtek/rtd1195.dtsi diff --git a/arch/arm/boot/dts/renesas/Makefile b/arch/arm/boot/dts/renesas/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..833a02447ecf7a02bd2efe70fae15213ede9a6de --- /dev/null +++ b/arch/arm/boot/dts/renesas/Makefile @@ -0,0 +1,33 @@ +# SPDX-License-Identifier: GPL-2.0 +dtb-$(CONFIG_ARCH_RENESAS) += \ + emev2-kzm9d.dtb \ + r7s72100-genmai.dtb \ + r7s72100-gr-peach.dtb \ + r7s72100-rskrza1.dtb \ + r7s9210-rza2mevb.dtb \ + r8a73a4-ape6evm.dtb \ + r8a7740-armadillo800eva.dtb \ + r8a7742-iwg21d-q7.dtb \ + r8a7742-iwg21d-q7-dbcm-ca.dtb \ + r8a7743-iwg20d-q7.dtb \ + r8a7743-iwg20d-q7-dbcm-ca.dtb \ + r8a7743-sk-rzg1m.dtb \ + r8a7744-iwg20d-q7.dtb \ + r8a7744-iwg20d-q7-dbcm-ca.dtb \ + r8a7745-iwg22d-sodimm.dtb \ + r8a7745-iwg22d-sodimm-dbhd-ca.dtb \ + r8a7745-sk-rzg1e.dtb \ + r8a77470-iwg23s-sbc.dtb \ + r8a7778-bockw.dtb \ + r8a7779-marzen.dtb \ + r8a7790-lager.dtb \ + r8a7790-stout.dtb \ + r8a7791-koelsch.dtb \ + r8a7791-porter.dtb \ + r8a7792-blanche.dtb \ + r8a7792-wheat.dtb \ + r8a7793-gose.dtb \ + r8a7794-alt.dtb \ + r8a7794-silk.dtb \ + r9a06g032-rzn1d400-db.dtb \ + sh73a0-kzm9g.dtb diff --git a/arch/arm/boot/dts/emev2-kzm9d.dts b/arch/arm/boot/dts/renesas/emev2-kzm9d.dts similarity index 100% rename from arch/arm/boot/dts/emev2-kzm9d.dts rename to arch/arm/boot/dts/renesas/emev2-kzm9d.dts diff --git a/arch/arm/boot/dts/emev2.dtsi b/arch/arm/boot/dts/renesas/emev2.dtsi similarity index 100% rename from arch/arm/boot/dts/emev2.dtsi rename to arch/arm/boot/dts/renesas/emev2.dtsi diff --git a/arch/arm/boot/dts/gr-peach-audiocamerashield.dtsi b/arch/arm/boot/dts/renesas/gr-peach-audiocamerashield.dtsi similarity index 100% rename from arch/arm/boot/dts/gr-peach-audiocamerashield.dtsi rename to arch/arm/boot/dts/renesas/gr-peach-audiocamerashield.dtsi diff --git a/arch/arm/boot/dts/iwg20d-q7-common.dtsi b/arch/arm/boot/dts/renesas/iwg20d-q7-common.dtsi similarity index 99% rename from arch/arm/boot/dts/iwg20d-q7-common.dtsi rename to arch/arm/boot/dts/renesas/iwg20d-q7-common.dtsi index 03caea6fc6ffa4cf3f19c2d23fe0a9144405df62..4351c5a02fa596de7f4bfc09489199a64f4f4b02 100644 --- a/arch/arm/boot/dts/iwg20d-q7-common.dtsi +++ b/arch/arm/boot/dts/renesas/iwg20d-q7-common.dtsi @@ -49,7 +49,7 @@ lcd_backlight: backlight { compatible = "pwm-backlight"; - pwms = <&pwm3 0 5000000 0>; + pwms = <&pwm3 0 5000000>; brightness-levels = <0 4 8 16 32 64 128 255>; default-brightness-level = <7>; enable-gpios = <&gpio5 14 GPIO_ACTIVE_HIGH>; diff --git a/arch/arm/boot/dts/iwg20d-q7-dbcm-ca.dtsi b/arch/arm/boot/dts/renesas/iwg20d-q7-dbcm-ca.dtsi similarity index 100% rename from arch/arm/boot/dts/iwg20d-q7-dbcm-ca.dtsi rename to arch/arm/boot/dts/renesas/iwg20d-q7-dbcm-ca.dtsi diff --git a/arch/arm/boot/dts/r7s72100-genmai.dts b/arch/arm/boot/dts/renesas/r7s72100-genmai.dts similarity index 100% rename from arch/arm/boot/dts/r7s72100-genmai.dts rename to arch/arm/boot/dts/renesas/r7s72100-genmai.dts diff --git a/arch/arm/boot/dts/r7s72100-gr-peach.dts b/arch/arm/boot/dts/renesas/r7s72100-gr-peach.dts similarity index 100% rename from arch/arm/boot/dts/r7s72100-gr-peach.dts rename to arch/arm/boot/dts/renesas/r7s72100-gr-peach.dts diff --git a/arch/arm/boot/dts/r7s72100-rskrza1.dts b/arch/arm/boot/dts/renesas/r7s72100-rskrza1.dts similarity index 100% rename from arch/arm/boot/dts/r7s72100-rskrza1.dts rename to arch/arm/boot/dts/renesas/r7s72100-rskrza1.dts diff --git a/arch/arm/boot/dts/r7s72100.dtsi b/arch/arm/boot/dts/renesas/r7s72100.dtsi similarity index 100% rename from arch/arm/boot/dts/r7s72100.dtsi rename to arch/arm/boot/dts/renesas/r7s72100.dtsi diff --git a/arch/arm/boot/dts/r7s9210-rza2mevb.dts b/arch/arm/boot/dts/renesas/r7s9210-rza2mevb.dts similarity index 100% rename from arch/arm/boot/dts/r7s9210-rza2mevb.dts rename to arch/arm/boot/dts/renesas/r7s9210-rza2mevb.dts diff --git a/arch/arm/boot/dts/r7s9210.dtsi b/arch/arm/boot/dts/renesas/r7s9210.dtsi similarity index 100% rename from arch/arm/boot/dts/r7s9210.dtsi rename to arch/arm/boot/dts/renesas/r7s9210.dtsi diff --git a/arch/arm/boot/dts/r8a73a4-ape6evm.dts b/arch/arm/boot/dts/renesas/r8a73a4-ape6evm.dts similarity index 100% rename from arch/arm/boot/dts/r8a73a4-ape6evm.dts rename to arch/arm/boot/dts/renesas/r8a73a4-ape6evm.dts diff --git a/arch/arm/boot/dts/r8a73a4.dtsi b/arch/arm/boot/dts/renesas/r8a73a4.dtsi similarity index 100% rename from arch/arm/boot/dts/r8a73a4.dtsi rename to arch/arm/boot/dts/renesas/r8a73a4.dtsi diff --git a/arch/arm/boot/dts/r8a7740-armadillo800eva.dts b/arch/arm/boot/dts/renesas/r8a7740-armadillo800eva.dts similarity index 100% rename from arch/arm/boot/dts/r8a7740-armadillo800eva.dts rename to arch/arm/boot/dts/renesas/r8a7740-armadillo800eva.dts diff --git a/arch/arm/boot/dts/r8a7740.dtsi b/arch/arm/boot/dts/renesas/r8a7740.dtsi similarity index 100% rename from arch/arm/boot/dts/r8a7740.dtsi rename to arch/arm/boot/dts/renesas/r8a7740.dtsi diff --git a/arch/arm/boot/dts/r8a7742-iwg21d-q7-dbcm-ca.dts b/arch/arm/boot/dts/renesas/r8a7742-iwg21d-q7-dbcm-ca.dts similarity index 100% rename from arch/arm/boot/dts/r8a7742-iwg21d-q7-dbcm-ca.dts rename to arch/arm/boot/dts/renesas/r8a7742-iwg21d-q7-dbcm-ca.dts diff --git a/arch/arm/boot/dts/r8a7742-iwg21d-q7-dbcm-ov5640-single.dtsi b/arch/arm/boot/dts/renesas/r8a7742-iwg21d-q7-dbcm-ov5640-single.dtsi similarity index 100% rename from arch/arm/boot/dts/r8a7742-iwg21d-q7-dbcm-ov5640-single.dtsi rename to arch/arm/boot/dts/renesas/r8a7742-iwg21d-q7-dbcm-ov5640-single.dtsi diff --git a/arch/arm/boot/dts/r8a7742-iwg21d-q7-dbcm-ov7725-single.dtsi b/arch/arm/boot/dts/renesas/r8a7742-iwg21d-q7-dbcm-ov7725-single.dtsi similarity index 100% rename from arch/arm/boot/dts/r8a7742-iwg21d-q7-dbcm-ov7725-single.dtsi rename to arch/arm/boot/dts/renesas/r8a7742-iwg21d-q7-dbcm-ov7725-single.dtsi diff --git a/arch/arm/boot/dts/r8a7742-iwg21d-q7.dts b/arch/arm/boot/dts/renesas/r8a7742-iwg21d-q7.dts similarity index 100% rename from arch/arm/boot/dts/r8a7742-iwg21d-q7.dts rename to arch/arm/boot/dts/renesas/r8a7742-iwg21d-q7.dts diff --git a/arch/arm/boot/dts/r8a7742-iwg21m.dtsi b/arch/arm/boot/dts/renesas/r8a7742-iwg21m.dtsi similarity index 100% rename from arch/arm/boot/dts/r8a7742-iwg21m.dtsi rename to arch/arm/boot/dts/renesas/r8a7742-iwg21m.dtsi diff --git a/arch/arm/boot/dts/r8a7742.dtsi b/arch/arm/boot/dts/renesas/r8a7742.dtsi similarity index 100% rename from arch/arm/boot/dts/r8a7742.dtsi rename to arch/arm/boot/dts/renesas/r8a7742.dtsi diff --git a/arch/arm/boot/dts/r8a7743-iwg20d-q7-dbcm-ca.dts b/arch/arm/boot/dts/renesas/r8a7743-iwg20d-q7-dbcm-ca.dts similarity index 100% rename from arch/arm/boot/dts/r8a7743-iwg20d-q7-dbcm-ca.dts rename to arch/arm/boot/dts/renesas/r8a7743-iwg20d-q7-dbcm-ca.dts diff --git a/arch/arm/boot/dts/r8a7743-iwg20d-q7.dts b/arch/arm/boot/dts/renesas/r8a7743-iwg20d-q7.dts similarity index 100% rename from arch/arm/boot/dts/r8a7743-iwg20d-q7.dts rename to arch/arm/boot/dts/renesas/r8a7743-iwg20d-q7.dts diff --git a/arch/arm/boot/dts/r8a7743-iwg20m.dtsi b/arch/arm/boot/dts/renesas/r8a7743-iwg20m.dtsi similarity index 100% rename from arch/arm/boot/dts/r8a7743-iwg20m.dtsi rename to arch/arm/boot/dts/renesas/r8a7743-iwg20m.dtsi diff --git a/arch/arm/boot/dts/r8a7743-sk-rzg1m.dts b/arch/arm/boot/dts/renesas/r8a7743-sk-rzg1m.dts similarity index 100% rename from arch/arm/boot/dts/r8a7743-sk-rzg1m.dts rename to arch/arm/boot/dts/renesas/r8a7743-sk-rzg1m.dts diff --git a/arch/arm/boot/dts/r8a7743.dtsi b/arch/arm/boot/dts/renesas/r8a7743.dtsi similarity index 100% rename from arch/arm/boot/dts/r8a7743.dtsi rename to arch/arm/boot/dts/renesas/r8a7743.dtsi diff --git a/arch/arm/boot/dts/r8a7744-iwg20d-q7-dbcm-ca.dts b/arch/arm/boot/dts/renesas/r8a7744-iwg20d-q7-dbcm-ca.dts similarity index 100% rename from arch/arm/boot/dts/r8a7744-iwg20d-q7-dbcm-ca.dts rename to arch/arm/boot/dts/renesas/r8a7744-iwg20d-q7-dbcm-ca.dts diff --git a/arch/arm/boot/dts/r8a7744-iwg20d-q7.dts b/arch/arm/boot/dts/renesas/r8a7744-iwg20d-q7.dts similarity index 100% rename from arch/arm/boot/dts/r8a7744-iwg20d-q7.dts rename to arch/arm/boot/dts/renesas/r8a7744-iwg20d-q7.dts diff --git a/arch/arm/boot/dts/r8a7744-iwg20m.dtsi b/arch/arm/boot/dts/renesas/r8a7744-iwg20m.dtsi similarity index 100% rename from arch/arm/boot/dts/r8a7744-iwg20m.dtsi rename to arch/arm/boot/dts/renesas/r8a7744-iwg20m.dtsi diff --git a/arch/arm/boot/dts/r8a7744.dtsi b/arch/arm/boot/dts/renesas/r8a7744.dtsi similarity index 100% rename from arch/arm/boot/dts/r8a7744.dtsi rename to arch/arm/boot/dts/renesas/r8a7744.dtsi diff --git a/arch/arm/boot/dts/r8a7745-iwg22d-sodimm-dbhd-ca.dts b/arch/arm/boot/dts/renesas/r8a7745-iwg22d-sodimm-dbhd-ca.dts similarity index 100% rename from arch/arm/boot/dts/r8a7745-iwg22d-sodimm-dbhd-ca.dts rename to arch/arm/boot/dts/renesas/r8a7745-iwg22d-sodimm-dbhd-ca.dts diff --git a/arch/arm/boot/dts/r8a7745-iwg22d-sodimm.dts b/arch/arm/boot/dts/renesas/r8a7745-iwg22d-sodimm.dts similarity index 100% rename from arch/arm/boot/dts/r8a7745-iwg22d-sodimm.dts rename to arch/arm/boot/dts/renesas/r8a7745-iwg22d-sodimm.dts diff --git a/arch/arm/boot/dts/r8a7745-iwg22m.dtsi b/arch/arm/boot/dts/renesas/r8a7745-iwg22m.dtsi similarity index 100% rename from arch/arm/boot/dts/r8a7745-iwg22m.dtsi rename to arch/arm/boot/dts/renesas/r8a7745-iwg22m.dtsi diff --git a/arch/arm/boot/dts/r8a7745-sk-rzg1e.dts b/arch/arm/boot/dts/renesas/r8a7745-sk-rzg1e.dts similarity index 100% rename from arch/arm/boot/dts/r8a7745-sk-rzg1e.dts rename to arch/arm/boot/dts/renesas/r8a7745-sk-rzg1e.dts diff --git a/arch/arm/boot/dts/r8a7745.dtsi b/arch/arm/boot/dts/renesas/r8a7745.dtsi similarity index 100% rename from arch/arm/boot/dts/r8a7745.dtsi rename to arch/arm/boot/dts/renesas/r8a7745.dtsi diff --git a/arch/arm/boot/dts/r8a77470-iwg23s-sbc.dts b/arch/arm/boot/dts/renesas/r8a77470-iwg23s-sbc.dts similarity index 100% rename from arch/arm/boot/dts/r8a77470-iwg23s-sbc.dts rename to arch/arm/boot/dts/renesas/r8a77470-iwg23s-sbc.dts diff --git a/arch/arm/boot/dts/r8a77470.dtsi b/arch/arm/boot/dts/renesas/r8a77470.dtsi similarity index 100% rename from arch/arm/boot/dts/r8a77470.dtsi rename to arch/arm/boot/dts/renesas/r8a77470.dtsi diff --git a/arch/arm/boot/dts/r8a7778-bockw.dts b/arch/arm/boot/dts/renesas/r8a7778-bockw.dts similarity index 100% rename from arch/arm/boot/dts/r8a7778-bockw.dts rename to arch/arm/boot/dts/renesas/r8a7778-bockw.dts diff --git a/arch/arm/boot/dts/r8a7778.dtsi b/arch/arm/boot/dts/renesas/r8a7778.dtsi similarity index 100% rename from arch/arm/boot/dts/r8a7778.dtsi rename to arch/arm/boot/dts/renesas/r8a7778.dtsi diff --git a/arch/arm/boot/dts/r8a7779-marzen.dts b/arch/arm/boot/dts/renesas/r8a7779-marzen.dts similarity index 100% rename from arch/arm/boot/dts/r8a7779-marzen.dts rename to arch/arm/boot/dts/renesas/r8a7779-marzen.dts diff --git a/arch/arm/boot/dts/r8a7779.dtsi b/arch/arm/boot/dts/renesas/r8a7779.dtsi similarity index 100% rename from arch/arm/boot/dts/r8a7779.dtsi rename to arch/arm/boot/dts/renesas/r8a7779.dtsi diff --git a/arch/arm/boot/dts/r8a7790-lager.dts b/arch/arm/boot/dts/renesas/r8a7790-lager.dts similarity index 100% rename from arch/arm/boot/dts/r8a7790-lager.dts rename to arch/arm/boot/dts/renesas/r8a7790-lager.dts diff --git a/arch/arm/boot/dts/r8a7790-stout.dts b/arch/arm/boot/dts/renesas/r8a7790-stout.dts similarity index 100% rename from arch/arm/boot/dts/r8a7790-stout.dts rename to arch/arm/boot/dts/renesas/r8a7790-stout.dts diff --git a/arch/arm/boot/dts/r8a7790.dtsi b/arch/arm/boot/dts/renesas/r8a7790.dtsi similarity index 100% rename from arch/arm/boot/dts/r8a7790.dtsi rename to arch/arm/boot/dts/renesas/r8a7790.dtsi diff --git a/arch/arm/boot/dts/r8a7791-koelsch.dts b/arch/arm/boot/dts/renesas/r8a7791-koelsch.dts similarity index 100% rename from arch/arm/boot/dts/r8a7791-koelsch.dts rename to arch/arm/boot/dts/renesas/r8a7791-koelsch.dts diff --git a/arch/arm/boot/dts/r8a7791-porter.dts b/arch/arm/boot/dts/renesas/r8a7791-porter.dts similarity index 100% rename from arch/arm/boot/dts/r8a7791-porter.dts rename to arch/arm/boot/dts/renesas/r8a7791-porter.dts diff --git a/arch/arm/boot/dts/r8a7791.dtsi b/arch/arm/boot/dts/renesas/r8a7791.dtsi similarity index 100% rename from arch/arm/boot/dts/r8a7791.dtsi rename to arch/arm/boot/dts/renesas/r8a7791.dtsi diff --git a/arch/arm/boot/dts/r8a7792-blanche.dts b/arch/arm/boot/dts/renesas/r8a7792-blanche.dts similarity index 100% rename from arch/arm/boot/dts/r8a7792-blanche.dts rename to arch/arm/boot/dts/renesas/r8a7792-blanche.dts diff --git a/arch/arm/boot/dts/r8a7792-wheat.dts b/arch/arm/boot/dts/renesas/r8a7792-wheat.dts similarity index 100% rename from arch/arm/boot/dts/r8a7792-wheat.dts rename to arch/arm/boot/dts/renesas/r8a7792-wheat.dts diff --git a/arch/arm/boot/dts/r8a7792.dtsi b/arch/arm/boot/dts/renesas/r8a7792.dtsi similarity index 100% rename from arch/arm/boot/dts/r8a7792.dtsi rename to arch/arm/boot/dts/renesas/r8a7792.dtsi diff --git a/arch/arm/boot/dts/r8a7793-gose.dts b/arch/arm/boot/dts/renesas/r8a7793-gose.dts similarity index 100% rename from arch/arm/boot/dts/r8a7793-gose.dts rename to arch/arm/boot/dts/renesas/r8a7793-gose.dts diff --git a/arch/arm/boot/dts/r8a7793.dtsi b/arch/arm/boot/dts/renesas/r8a7793.dtsi similarity index 100% rename from arch/arm/boot/dts/r8a7793.dtsi rename to arch/arm/boot/dts/renesas/r8a7793.dtsi diff --git a/arch/arm/boot/dts/r8a7794-alt.dts b/arch/arm/boot/dts/renesas/r8a7794-alt.dts similarity index 100% rename from arch/arm/boot/dts/r8a7794-alt.dts rename to arch/arm/boot/dts/renesas/r8a7794-alt.dts diff --git a/arch/arm/boot/dts/r8a7794-silk.dts b/arch/arm/boot/dts/renesas/r8a7794-silk.dts similarity index 100% rename from arch/arm/boot/dts/r8a7794-silk.dts rename to arch/arm/boot/dts/renesas/r8a7794-silk.dts diff --git a/arch/arm/boot/dts/r8a7794.dtsi b/arch/arm/boot/dts/renesas/r8a7794.dtsi similarity index 100% rename from arch/arm/boot/dts/r8a7794.dtsi rename to arch/arm/boot/dts/renesas/r8a7794.dtsi diff --git a/arch/arm/boot/dts/r8a77xx-aa121td01-panel.dtsi b/arch/arm/boot/dts/renesas/r8a77xx-aa121td01-panel.dtsi similarity index 100% rename from arch/arm/boot/dts/r8a77xx-aa121td01-panel.dtsi rename to arch/arm/boot/dts/renesas/r8a77xx-aa121td01-panel.dtsi diff --git a/arch/arm/boot/dts/r9a06g032-rzn1d400-db.dts b/arch/arm/boot/dts/renesas/r9a06g032-rzn1d400-db.dts similarity index 100% rename from arch/arm/boot/dts/r9a06g032-rzn1d400-db.dts rename to arch/arm/boot/dts/renesas/r9a06g032-rzn1d400-db.dts diff --git a/arch/arm/boot/dts/r9a06g032.dtsi b/arch/arm/boot/dts/renesas/r9a06g032.dtsi similarity index 100% rename from arch/arm/boot/dts/r9a06g032.dtsi rename to arch/arm/boot/dts/renesas/r9a06g032.dtsi diff --git a/arch/arm/boot/dts/sh73a0-kzm9g.dts b/arch/arm/boot/dts/renesas/sh73a0-kzm9g.dts similarity index 100% rename from arch/arm/boot/dts/sh73a0-kzm9g.dts rename to arch/arm/boot/dts/renesas/sh73a0-kzm9g.dts diff --git a/arch/arm/boot/dts/sh73a0.dtsi b/arch/arm/boot/dts/renesas/sh73a0.dtsi similarity index 100% rename from arch/arm/boot/dts/sh73a0.dtsi rename to arch/arm/boot/dts/renesas/sh73a0.dtsi diff --git a/arch/arm/boot/dts/rockchip/Makefile b/arch/arm/boot/dts/rockchip/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..0f46e18fe2754b3743ce2fbe1c8811a033e7a839 --- /dev/null +++ b/arch/arm/boot/dts/rockchip/Makefile @@ -0,0 +1,42 @@ +# SPDX-License-Identifier: GPL-2.0 +dtb-$(CONFIG_ARCH_ROCKCHIP) += \ + rv1108-elgin-r1.dtb \ + rv1108-evb.dtb \ + rv1126-edgeble-neu2-io.dtb \ + rk3036-evb.dtb \ + rk3036-kylin.dtb \ + rk3066a-bqcurie2.dtb \ + rk3066a-marsboard.dtb \ + rk3066a-mk808.dtb \ + rk3066a-rayeager.dtb \ + rk3128-evb.dtb \ + rk3188-bqedison2qc.dtb \ + rk3188-px3-evb.dtb \ + rk3188-radxarock.dtb \ + rk3228-evb.dtb \ + rk3229-evb.dtb \ + rk3229-xms6.dtb \ + rk3288-evb-act8846.dtb \ + rk3288-evb-rk808.dtb \ + rk3288-firefly-beta.dtb \ + rk3288-firefly.dtb \ + rk3288-firefly-reload.dtb \ + rk3288-miqi.dtb \ + rk3288-phycore-rdk.dtb \ + rk3288-popmetal.dtb \ + rk3288-r89.dtb \ + rk3288-rock2-square.dtb \ + rk3288-rock-pi-n8.dtb \ + rk3288-tinker.dtb \ + rk3288-tinker-s.dtb \ + rk3288-veyron-brain.dtb \ + rk3288-veyron-fievel.dtb \ + rk3288-veyron-jaq.dtb \ + rk3288-veyron-jerry.dtb \ + rk3288-veyron-mickey.dtb \ + rk3288-veyron-mighty.dtb \ + rk3288-veyron-minnie.dtb \ + rk3288-veyron-pinky.dtb \ + rk3288-veyron-speedy.dtb \ + rk3288-veyron-tiger.dtb \ + rk3288-vyasa.dtb diff --git a/arch/arm/boot/dts/rk3036-evb.dts b/arch/arm/boot/dts/rockchip/rk3036-evb.dts similarity index 100% rename from arch/arm/boot/dts/rk3036-evb.dts rename to arch/arm/boot/dts/rockchip/rk3036-evb.dts diff --git a/arch/arm/boot/dts/rk3036-kylin.dts b/arch/arm/boot/dts/rockchip/rk3036-kylin.dts similarity index 100% rename from arch/arm/boot/dts/rk3036-kylin.dts rename to arch/arm/boot/dts/rockchip/rk3036-kylin.dts diff --git a/arch/arm/boot/dts/rk3036.dtsi b/arch/arm/boot/dts/rockchip/rk3036.dtsi similarity index 100% rename from arch/arm/boot/dts/rk3036.dtsi rename to arch/arm/boot/dts/rockchip/rk3036.dtsi diff --git a/arch/arm/boot/dts/rk3066a-bqcurie2.dts b/arch/arm/boot/dts/rockchip/rk3066a-bqcurie2.dts similarity index 99% rename from arch/arm/boot/dts/rk3066a-bqcurie2.dts rename to arch/arm/boot/dts/rockchip/rk3066a-bqcurie2.dts index 962b4d1291dba65b634628b47ff92410d819094b..f924d4d64c3d1830c00998135291e711ff1d100b 100644 --- a/arch/arm/boot/dts/rk3066a-bqcurie2.dts +++ b/arch/arm/boot/dts/rockchip/rk3066a-bqcurie2.dts @@ -159,7 +159,7 @@ }; /* must be included after &tps gets defined */ -#include "tps65910.dtsi" +#include "../tps65910.dtsi" &mmc0 { /* sdmmc */ status = "okay"; diff --git a/arch/arm/boot/dts/rk3066a-marsboard.dts b/arch/arm/boot/dts/rockchip/rk3066a-marsboard.dts similarity index 99% rename from arch/arm/boot/dts/rk3066a-marsboard.dts rename to arch/arm/boot/dts/rockchip/rk3066a-marsboard.dts index 8beecd628282412621b89c237cc10af8668c07fd..f6e8d49a02efc07d7b0972e976975bc5c2a1a7cc 100644 --- a/arch/arm/boot/dts/rk3066a-marsboard.dts +++ b/arch/arm/boot/dts/rockchip/rk3066a-marsboard.dts @@ -147,7 +147,7 @@ }; /* must be included after &tps gets defined */ -#include "tps65910.dtsi" +#include "../tps65910.dtsi" &emac { phy = <&phy0>; diff --git a/arch/arm/boot/dts/rk3066a-mk808.dts b/arch/arm/boot/dts/rockchip/rk3066a-mk808.dts similarity index 100% rename from arch/arm/boot/dts/rk3066a-mk808.dts rename to arch/arm/boot/dts/rockchip/rk3066a-mk808.dts diff --git a/arch/arm/boot/dts/rk3066a-rayeager.dts b/arch/arm/boot/dts/rockchip/rk3066a-rayeager.dts similarity index 99% rename from arch/arm/boot/dts/rk3066a-rayeager.dts rename to arch/arm/boot/dts/rockchip/rk3066a-rayeager.dts index 3eee42137b6da8bf70ace489ce5c3dd758bfc8fc..29d8e5bf88f53473fc8674265c473587e1f68597 100644 --- a/arch/arm/boot/dts/rk3066a-rayeager.dts +++ b/arch/arm/boot/dts/rockchip/rk3066a-rayeager.dts @@ -296,7 +296,7 @@ }; }; -#include "tps65910.dtsi" +#include "../tps65910.dtsi" &i2c2 { status = "okay"; diff --git a/arch/arm/boot/dts/rk3066a.dtsi b/arch/arm/boot/dts/rockchip/rk3066a.dtsi similarity index 100% rename from arch/arm/boot/dts/rk3066a.dtsi rename to arch/arm/boot/dts/rockchip/rk3066a.dtsi diff --git a/arch/arm/boot/dts/rk3128-evb.dts b/arch/arm/boot/dts/rockchip/rk3128-evb.dts similarity index 100% rename from arch/arm/boot/dts/rk3128-evb.dts rename to arch/arm/boot/dts/rockchip/rk3128-evb.dts diff --git a/arch/arm/boot/dts/rk3128.dtsi b/arch/arm/boot/dts/rockchip/rk3128.dtsi similarity index 100% rename from arch/arm/boot/dts/rk3128.dtsi rename to arch/arm/boot/dts/rockchip/rk3128.dtsi diff --git a/arch/arm/boot/dts/rk3188-bqedison2qc.dts b/arch/arm/boot/dts/rockchip/rk3188-bqedison2qc.dts similarity index 100% rename from arch/arm/boot/dts/rk3188-bqedison2qc.dts rename to arch/arm/boot/dts/rockchip/rk3188-bqedison2qc.dts diff --git a/arch/arm/boot/dts/rk3188-px3-evb.dts b/arch/arm/boot/dts/rockchip/rk3188-px3-evb.dts similarity index 100% rename from arch/arm/boot/dts/rk3188-px3-evb.dts rename to arch/arm/boot/dts/rockchip/rk3188-px3-evb.dts diff --git a/arch/arm/boot/dts/rk3188-radxarock.dts b/arch/arm/boot/dts/rockchip/rk3188-radxarock.dts similarity index 100% rename from arch/arm/boot/dts/rk3188-radxarock.dts rename to arch/arm/boot/dts/rockchip/rk3188-radxarock.dts diff --git a/arch/arm/boot/dts/rk3188.dtsi b/arch/arm/boot/dts/rockchip/rk3188.dtsi similarity index 100% rename from arch/arm/boot/dts/rk3188.dtsi rename to arch/arm/boot/dts/rockchip/rk3188.dtsi diff --git a/arch/arm/boot/dts/rk3228-evb.dts b/arch/arm/boot/dts/rockchip/rk3228-evb.dts similarity index 100% rename from arch/arm/boot/dts/rk3228-evb.dts rename to arch/arm/boot/dts/rockchip/rk3228-evb.dts diff --git a/arch/arm/boot/dts/rk3229-evb.dts b/arch/arm/boot/dts/rockchip/rk3229-evb.dts similarity index 100% rename from arch/arm/boot/dts/rk3229-evb.dts rename to arch/arm/boot/dts/rockchip/rk3229-evb.dts diff --git a/arch/arm/boot/dts/rk3229-xms6.dts b/arch/arm/boot/dts/rockchip/rk3229-xms6.dts similarity index 100% rename from arch/arm/boot/dts/rk3229-xms6.dts rename to arch/arm/boot/dts/rockchip/rk3229-xms6.dts diff --git a/arch/arm/boot/dts/rk3229.dtsi b/arch/arm/boot/dts/rockchip/rk3229.dtsi similarity index 100% rename from arch/arm/boot/dts/rk3229.dtsi rename to arch/arm/boot/dts/rockchip/rk3229.dtsi diff --git a/arch/arm/boot/dts/rk322x.dtsi b/arch/arm/boot/dts/rockchip/rk322x.dtsi similarity index 100% rename from arch/arm/boot/dts/rk322x.dtsi rename to arch/arm/boot/dts/rockchip/rk322x.dtsi diff --git a/arch/arm/boot/dts/rk3288-evb-act8846.dts b/arch/arm/boot/dts/rockchip/rk3288-evb-act8846.dts similarity index 100% rename from arch/arm/boot/dts/rk3288-evb-act8846.dts rename to arch/arm/boot/dts/rockchip/rk3288-evb-act8846.dts diff --git a/arch/arm/boot/dts/rk3288-evb-rk808.dts b/arch/arm/boot/dts/rockchip/rk3288-evb-rk808.dts similarity index 100% rename from arch/arm/boot/dts/rk3288-evb-rk808.dts rename to arch/arm/boot/dts/rockchip/rk3288-evb-rk808.dts diff --git a/arch/arm/boot/dts/rk3288-evb.dtsi b/arch/arm/boot/dts/rockchip/rk3288-evb.dtsi similarity index 100% rename from arch/arm/boot/dts/rk3288-evb.dtsi rename to arch/arm/boot/dts/rockchip/rk3288-evb.dtsi diff --git a/arch/arm/boot/dts/rk3288-firefly-beta.dts b/arch/arm/boot/dts/rockchip/rk3288-firefly-beta.dts similarity index 100% rename from arch/arm/boot/dts/rk3288-firefly-beta.dts rename to arch/arm/boot/dts/rockchip/rk3288-firefly-beta.dts diff --git a/arch/arm/boot/dts/rk3288-firefly-reload-core.dtsi b/arch/arm/boot/dts/rockchip/rk3288-firefly-reload-core.dtsi similarity index 100% rename from arch/arm/boot/dts/rk3288-firefly-reload-core.dtsi rename to arch/arm/boot/dts/rockchip/rk3288-firefly-reload-core.dtsi diff --git a/arch/arm/boot/dts/rk3288-firefly-reload.dts b/arch/arm/boot/dts/rockchip/rk3288-firefly-reload.dts similarity index 100% rename from arch/arm/boot/dts/rk3288-firefly-reload.dts rename to arch/arm/boot/dts/rockchip/rk3288-firefly-reload.dts diff --git a/arch/arm/boot/dts/rk3288-firefly.dts b/arch/arm/boot/dts/rockchip/rk3288-firefly.dts similarity index 100% rename from arch/arm/boot/dts/rk3288-firefly.dts rename to arch/arm/boot/dts/rockchip/rk3288-firefly.dts diff --git a/arch/arm/boot/dts/rk3288-firefly.dtsi b/arch/arm/boot/dts/rockchip/rk3288-firefly.dtsi similarity index 100% rename from arch/arm/boot/dts/rk3288-firefly.dtsi rename to arch/arm/boot/dts/rockchip/rk3288-firefly.dtsi diff --git a/arch/arm/boot/dts/rk3288-miqi.dts b/arch/arm/boot/dts/rockchip/rk3288-miqi.dts similarity index 100% rename from arch/arm/boot/dts/rk3288-miqi.dts rename to arch/arm/boot/dts/rockchip/rk3288-miqi.dts diff --git a/arch/arm/boot/dts/rk3288-phycore-rdk.dts b/arch/arm/boot/dts/rockchip/rk3288-phycore-rdk.dts similarity index 100% rename from arch/arm/boot/dts/rk3288-phycore-rdk.dts rename to arch/arm/boot/dts/rockchip/rk3288-phycore-rdk.dts diff --git a/arch/arm/boot/dts/rk3288-phycore-som.dtsi b/arch/arm/boot/dts/rockchip/rk3288-phycore-som.dtsi similarity index 100% rename from arch/arm/boot/dts/rk3288-phycore-som.dtsi rename to arch/arm/boot/dts/rockchip/rk3288-phycore-som.dtsi diff --git a/arch/arm/boot/dts/rk3288-popmetal.dts b/arch/arm/boot/dts/rockchip/rk3288-popmetal.dts similarity index 100% rename from arch/arm/boot/dts/rk3288-popmetal.dts rename to arch/arm/boot/dts/rockchip/rk3288-popmetal.dts diff --git a/arch/arm/boot/dts/rk3288-r89.dts b/arch/arm/boot/dts/rockchip/rk3288-r89.dts similarity index 100% rename from arch/arm/boot/dts/rk3288-r89.dts rename to arch/arm/boot/dts/rockchip/rk3288-r89.dts diff --git a/arch/arm/boot/dts/rk3288-rock-pi-n8.dts b/arch/arm/boot/dts/rockchip/rk3288-rock-pi-n8.dts similarity index 86% rename from arch/arm/boot/dts/rk3288-rock-pi-n8.dts rename to arch/arm/boot/dts/rockchip/rk3288-rock-pi-n8.dts index b195930217135a47426e2e75a3da3ec8f3c83665..673466d264befb519370a3fc10d7bb991fbb740d 100644 --- a/arch/arm/boot/dts/rk3288-rock-pi-n8.dts +++ b/arch/arm/boot/dts/rockchip/rk3288-rock-pi-n8.dts @@ -7,7 +7,7 @@ /dts-v1/; #include "rk3288.dtsi" -#include +#include #include "rk3288-vmarc-som.dtsi" / { diff --git a/arch/arm/boot/dts/rk3288-rock2-som.dtsi b/arch/arm/boot/dts/rockchip/rk3288-rock2-som.dtsi similarity index 100% rename from arch/arm/boot/dts/rk3288-rock2-som.dtsi rename to arch/arm/boot/dts/rockchip/rk3288-rock2-som.dtsi diff --git a/arch/arm/boot/dts/rk3288-rock2-square.dts b/arch/arm/boot/dts/rockchip/rk3288-rock2-square.dts similarity index 100% rename from arch/arm/boot/dts/rk3288-rock2-square.dts rename to arch/arm/boot/dts/rockchip/rk3288-rock2-square.dts diff --git a/arch/arm/boot/dts/rk3288-tinker-s.dts b/arch/arm/boot/dts/rockchip/rk3288-tinker-s.dts similarity index 100% rename from arch/arm/boot/dts/rk3288-tinker-s.dts rename to arch/arm/boot/dts/rockchip/rk3288-tinker-s.dts diff --git a/arch/arm/boot/dts/rk3288-tinker.dts b/arch/arm/boot/dts/rockchip/rk3288-tinker.dts similarity index 100% rename from arch/arm/boot/dts/rk3288-tinker.dts rename to arch/arm/boot/dts/rockchip/rk3288-tinker.dts diff --git a/arch/arm/boot/dts/rk3288-tinker.dtsi b/arch/arm/boot/dts/rockchip/rk3288-tinker.dtsi similarity index 100% rename from arch/arm/boot/dts/rk3288-tinker.dtsi rename to arch/arm/boot/dts/rockchip/rk3288-tinker.dtsi diff --git a/arch/arm/boot/dts/rk3288-veyron-analog-audio.dtsi b/arch/arm/boot/dts/rockchip/rk3288-veyron-analog-audio.dtsi similarity index 100% rename from arch/arm/boot/dts/rk3288-veyron-analog-audio.dtsi rename to arch/arm/boot/dts/rockchip/rk3288-veyron-analog-audio.dtsi diff --git a/arch/arm/boot/dts/rk3288-veyron-brain.dts b/arch/arm/boot/dts/rockchip/rk3288-veyron-brain.dts similarity index 100% rename from arch/arm/boot/dts/rk3288-veyron-brain.dts rename to arch/arm/boot/dts/rockchip/rk3288-veyron-brain.dts diff --git a/arch/arm/boot/dts/rk3288-veyron-broadcom-bluetooth.dtsi b/arch/arm/boot/dts/rockchip/rk3288-veyron-broadcom-bluetooth.dtsi similarity index 100% rename from arch/arm/boot/dts/rk3288-veyron-broadcom-bluetooth.dtsi rename to arch/arm/boot/dts/rockchip/rk3288-veyron-broadcom-bluetooth.dtsi diff --git a/arch/arm/boot/dts/rk3288-veyron-chromebook.dtsi b/arch/arm/boot/dts/rockchip/rk3288-veyron-chromebook.dtsi similarity index 99% rename from arch/arm/boot/dts/rk3288-veyron-chromebook.dtsi rename to arch/arm/boot/dts/rockchip/rk3288-veyron-chromebook.dtsi index 700bb548d6b271a434db544ab332ce05065fda2f..092316be67f740bea1d5b2ab2258310e5a2aa2b7 100644 --- a/arch/arm/boot/dts/rk3288-veyron-chromebook.dtsi +++ b/arch/arm/boot/dts/rockchip/rk3288-veyron-chromebook.dtsi @@ -181,4 +181,4 @@ }; }; -#include "cros-ec-keyboard.dtsi" +#include "../cros-ec-keyboard.dtsi" diff --git a/arch/arm/boot/dts/rk3288-veyron-edp.dtsi b/arch/arm/boot/dts/rockchip/rk3288-veyron-edp.dtsi similarity index 100% rename from arch/arm/boot/dts/rk3288-veyron-edp.dtsi rename to arch/arm/boot/dts/rockchip/rk3288-veyron-edp.dtsi diff --git a/arch/arm/boot/dts/rk3288-veyron-fievel.dts b/arch/arm/boot/dts/rockchip/rk3288-veyron-fievel.dts similarity index 100% rename from arch/arm/boot/dts/rk3288-veyron-fievel.dts rename to arch/arm/boot/dts/rockchip/rk3288-veyron-fievel.dts diff --git a/arch/arm/boot/dts/rk3288-veyron-jaq.dts b/arch/arm/boot/dts/rockchip/rk3288-veyron-jaq.dts similarity index 99% rename from arch/arm/boot/dts/rk3288-veyron-jaq.dts rename to arch/arm/boot/dts/rockchip/rk3288-veyron-jaq.dts index 4a148cf1defc49650c4f3baba53e4a93dee7d2b5..0d4c50e05558712d0e56d954bc526a5085945d20 100644 --- a/arch/arm/boot/dts/rk3288-veyron-jaq.dts +++ b/arch/arm/boot/dts/rockchip/rk3288-veyron-jaq.dts @@ -8,7 +8,7 @@ /dts-v1/; #include "rk3288-veyron-chromebook.dtsi" -#include "cros-ec-sbs.dtsi" +#include "../cros-ec-sbs.dtsi" / { model = "Google Jaq"; diff --git a/arch/arm/boot/dts/rk3288-veyron-jerry.dts b/arch/arm/boot/dts/rockchip/rk3288-veyron-jerry.dts similarity index 99% rename from arch/arm/boot/dts/rk3288-veyron-jerry.dts rename to arch/arm/boot/dts/rockchip/rk3288-veyron-jerry.dts index 2c916c50dda5092471c1a2252a98da6183ca8be7..6894763979f035bc827404a04ca0a089a3e92a80 100644 --- a/arch/arm/boot/dts/rk3288-veyron-jerry.dts +++ b/arch/arm/boot/dts/rockchip/rk3288-veyron-jerry.dts @@ -7,7 +7,7 @@ /dts-v1/; #include "rk3288-veyron-chromebook.dtsi" -#include "cros-ec-sbs.dtsi" +#include "../cros-ec-sbs.dtsi" / { model = "Google Jerry"; diff --git a/arch/arm/boot/dts/rk3288-veyron-mickey.dts b/arch/arm/boot/dts/rockchip/rk3288-veyron-mickey.dts similarity index 100% rename from arch/arm/boot/dts/rk3288-veyron-mickey.dts rename to arch/arm/boot/dts/rockchip/rk3288-veyron-mickey.dts diff --git a/arch/arm/boot/dts/rk3288-veyron-mighty.dts b/arch/arm/boot/dts/rockchip/rk3288-veyron-mighty.dts similarity index 100% rename from arch/arm/boot/dts/rk3288-veyron-mighty.dts rename to arch/arm/boot/dts/rockchip/rk3288-veyron-mighty.dts diff --git a/arch/arm/boot/dts/rk3288-veyron-minnie.dts b/arch/arm/boot/dts/rockchip/rk3288-veyron-minnie.dts similarity index 100% rename from arch/arm/boot/dts/rk3288-veyron-minnie.dts rename to arch/arm/boot/dts/rockchip/rk3288-veyron-minnie.dts diff --git a/arch/arm/boot/dts/rk3288-veyron-pinky.dts b/arch/arm/boot/dts/rockchip/rk3288-veyron-pinky.dts similarity index 98% rename from arch/arm/boot/dts/rk3288-veyron-pinky.dts rename to arch/arm/boot/dts/rockchip/rk3288-veyron-pinky.dts index e2a4e6232eb5884c4e4fe2efd6152e0c48b7fd5e..6337238891eb0afd3023ffba5d4b60f9d6185054 100644 --- a/arch/arm/boot/dts/rk3288-veyron-pinky.dts +++ b/arch/arm/boot/dts/rockchip/rk3288-veyron-pinky.dts @@ -7,7 +7,7 @@ /dts-v1/; #include "rk3288-veyron-chromebook.dtsi" -#include "cros-ec-sbs.dtsi" +#include "../cros-ec-sbs.dtsi" / { model = "Google Pinky"; diff --git a/arch/arm/boot/dts/rk3288-veyron-sdmmc.dtsi b/arch/arm/boot/dts/rockchip/rk3288-veyron-sdmmc.dtsi similarity index 100% rename from arch/arm/boot/dts/rk3288-veyron-sdmmc.dtsi rename to arch/arm/boot/dts/rockchip/rk3288-veyron-sdmmc.dtsi diff --git a/arch/arm/boot/dts/rk3288-veyron-speedy.dts b/arch/arm/boot/dts/rockchip/rk3288-veyron-speedy.dts similarity index 99% rename from arch/arm/boot/dts/rk3288-veyron-speedy.dts rename to arch/arm/boot/dts/rockchip/rk3288-veyron-speedy.dts index 4a3ea934d03e5de7bf3071038b5165ad15b9613a..336cd2be52657ba4402b103213ef2231dab38497 100644 --- a/arch/arm/boot/dts/rk3288-veyron-speedy.dts +++ b/arch/arm/boot/dts/rockchip/rk3288-veyron-speedy.dts @@ -8,7 +8,7 @@ /dts-v1/; #include "rk3288-veyron-chromebook.dtsi" #include "rk3288-veyron-broadcom-bluetooth.dtsi" -#include "cros-ec-sbs.dtsi" +#include "../cros-ec-sbs.dtsi" / { model = "Google Speedy"; diff --git a/arch/arm/boot/dts/rk3288-veyron-tiger.dts b/arch/arm/boot/dts/rockchip/rk3288-veyron-tiger.dts similarity index 100% rename from arch/arm/boot/dts/rk3288-veyron-tiger.dts rename to arch/arm/boot/dts/rockchip/rk3288-veyron-tiger.dts diff --git a/arch/arm/boot/dts/rk3288-veyron.dtsi b/arch/arm/boot/dts/rockchip/rk3288-veyron.dtsi similarity index 100% rename from arch/arm/boot/dts/rk3288-veyron.dtsi rename to arch/arm/boot/dts/rockchip/rk3288-veyron.dtsi diff --git a/arch/arm/boot/dts/rk3288-vmarc-som.dtsi b/arch/arm/boot/dts/rockchip/rk3288-vmarc-som.dtsi similarity index 100% rename from arch/arm/boot/dts/rk3288-vmarc-som.dtsi rename to arch/arm/boot/dts/rockchip/rk3288-vmarc-som.dtsi diff --git a/arch/arm/boot/dts/rk3288-vyasa.dts b/arch/arm/boot/dts/rockchip/rk3288-vyasa.dts similarity index 100% rename from arch/arm/boot/dts/rk3288-vyasa.dts rename to arch/arm/boot/dts/rockchip/rk3288-vyasa.dts diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rockchip/rk3288.dtsi similarity index 100% rename from arch/arm/boot/dts/rk3288.dtsi rename to arch/arm/boot/dts/rockchip/rk3288.dtsi diff --git a/arch/arm/boot/dts/rk3xxx.dtsi b/arch/arm/boot/dts/rockchip/rk3xxx.dtsi similarity index 100% rename from arch/arm/boot/dts/rk3xxx.dtsi rename to arch/arm/boot/dts/rockchip/rk3xxx.dtsi diff --git a/arch/arm/boot/dts/rockchip-radxa-dalang-carrier.dtsi b/arch/arm/boot/dts/rockchip/rockchip-radxa-dalang-carrier.dtsi similarity index 100% rename from arch/arm/boot/dts/rockchip-radxa-dalang-carrier.dtsi rename to arch/arm/boot/dts/rockchip/rockchip-radxa-dalang-carrier.dtsi diff --git a/arch/arm/boot/dts/rv1108-elgin-r1.dts b/arch/arm/boot/dts/rockchip/rv1108-elgin-r1.dts similarity index 100% rename from arch/arm/boot/dts/rv1108-elgin-r1.dts rename to arch/arm/boot/dts/rockchip/rv1108-elgin-r1.dts diff --git a/arch/arm/boot/dts/rv1108-evb.dts b/arch/arm/boot/dts/rockchip/rv1108-evb.dts similarity index 100% rename from arch/arm/boot/dts/rv1108-evb.dts rename to arch/arm/boot/dts/rockchip/rv1108-evb.dts diff --git a/arch/arm/boot/dts/rv1108.dtsi b/arch/arm/boot/dts/rockchip/rv1108.dtsi similarity index 100% rename from arch/arm/boot/dts/rv1108.dtsi rename to arch/arm/boot/dts/rockchip/rv1108.dtsi diff --git a/arch/arm/boot/dts/rv1126-edgeble-neu2-io.dts b/arch/arm/boot/dts/rockchip/rv1126-edgeble-neu2-io.dts similarity index 100% rename from arch/arm/boot/dts/rv1126-edgeble-neu2-io.dts rename to arch/arm/boot/dts/rockchip/rv1126-edgeble-neu2-io.dts diff --git a/arch/arm/boot/dts/rv1126-edgeble-neu2.dtsi b/arch/arm/boot/dts/rockchip/rv1126-edgeble-neu2.dtsi similarity index 100% rename from arch/arm/boot/dts/rv1126-edgeble-neu2.dtsi rename to arch/arm/boot/dts/rockchip/rv1126-edgeble-neu2.dtsi diff --git a/arch/arm/boot/dts/rv1126-pinctrl.dtsi b/arch/arm/boot/dts/rockchip/rv1126-pinctrl.dtsi similarity index 100% rename from arch/arm/boot/dts/rv1126-pinctrl.dtsi rename to arch/arm/boot/dts/rockchip/rv1126-pinctrl.dtsi diff --git a/arch/arm/boot/dts/rv1126.dtsi b/arch/arm/boot/dts/rockchip/rv1126.dtsi similarity index 100% rename from arch/arm/boot/dts/rv1126.dtsi rename to arch/arm/boot/dts/rockchip/rv1126.dtsi diff --git a/arch/arm/boot/dts/samsung/Makefile b/arch/arm/boot/dts/samsung/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..c8d067abdd597948445f461a7b38a6b694edb7d2 --- /dev/null +++ b/arch/arm/boot/dts/samsung/Makefile @@ -0,0 +1,54 @@ +# SPDX-License-Identifier: GPL-2.0 +dtb-$(CONFIG_ARCH_EXYNOS3) += \ + exynos3250-artik5-eval.dtb \ + exynos3250-monk.dtb \ + exynos3250-rinato.dtb +dtb-$(CONFIG_ARCH_EXYNOS4) += \ + exynos4210-i9100.dtb \ + exynos4210-origen.dtb \ + exynos4210-smdkv310.dtb \ + exynos4210-trats.dtb \ + exynos4210-universal_c210.dtb \ + exynos4412-i9300.dtb \ + exynos4412-i9305.dtb \ + exynos4412-itop-elite.dtb \ + exynos4412-n710x.dtb \ + exynos4412-odroidu3.dtb \ + exynos4412-odroidx.dtb \ + exynos4412-odroidx2.dtb \ + exynos4412-origen.dtb \ + exynos4412-p4note-n8010.dtb \ + exynos4412-smdk4412.dtb \ + exynos4412-tiny4412.dtb \ + exynos4412-trats2.dtb +dtb-$(CONFIG_ARCH_EXYNOS5) += \ + exynos5250-arndale.dtb \ + exynos5250-smdk5250.dtb \ + exynos5250-snow.dtb \ + exynos5250-snow-rev5.dtb \ + exynos5250-spring.dtb \ + exynos5260-xyref5260.dtb \ + exynos5410-odroidxu.dtb \ + exynos5410-smdk5410.dtb \ + exynos5420-arndale-octa.dtb \ + exynos5420-peach-pit.dtb \ + exynos5420-smdk5420.dtb \ + exynos5420-chagall-wifi.dtb \ + exynos5420-klimt-wifi.dtb \ + exynos5422-odroidhc1.dtb \ + exynos5422-odroidxu3.dtb \ + exynos5422-odroidxu3-lite.dtb \ + exynos5422-odroidxu4.dtb \ + exynos5422-samsung-k3g.dtb \ + exynos5800-peach-pi.dtb +dtb-$(CONFIG_ARCH_S3C64XX) += \ + s3c6410-mini6410.dtb \ + s3c6410-smdk6410.dtb +dtb-$(CONFIG_ARCH_S5PV210) += \ + s5pv210-aquila.dtb \ + s5pv210-fascinate4g.dtb \ + s5pv210-galaxys.dtb \ + s5pv210-goni.dtb \ + s5pv210-smdkc110.dtb \ + s5pv210-smdkv210.dtb \ + s5pv210-torbreck.dtb diff --git a/arch/arm/boot/dts/exynos-mfc-reserved-memory.dtsi b/arch/arm/boot/dts/samsung/exynos-mfc-reserved-memory.dtsi similarity index 100% rename from arch/arm/boot/dts/exynos-mfc-reserved-memory.dtsi rename to arch/arm/boot/dts/samsung/exynos-mfc-reserved-memory.dtsi diff --git a/arch/arm/boot/dts/exynos-pinctrl.h b/arch/arm/boot/dts/samsung/exynos-pinctrl.h similarity index 100% rename from arch/arm/boot/dts/exynos-pinctrl.h rename to arch/arm/boot/dts/samsung/exynos-pinctrl.h diff --git a/arch/arm/boot/dts/exynos-syscon-restart.dtsi b/arch/arm/boot/dts/samsung/exynos-syscon-restart.dtsi similarity index 100% rename from arch/arm/boot/dts/exynos-syscon-restart.dtsi rename to arch/arm/boot/dts/samsung/exynos-syscon-restart.dtsi diff --git a/arch/arm/boot/dts/exynos3250-artik5-eval.dts b/arch/arm/boot/dts/samsung/exynos3250-artik5-eval.dts similarity index 100% rename from arch/arm/boot/dts/exynos3250-artik5-eval.dts rename to arch/arm/boot/dts/samsung/exynos3250-artik5-eval.dts diff --git a/arch/arm/boot/dts/exynos3250-artik5.dtsi b/arch/arm/boot/dts/samsung/exynos3250-artik5.dtsi similarity index 100% rename from arch/arm/boot/dts/exynos3250-artik5.dtsi rename to arch/arm/boot/dts/samsung/exynos3250-artik5.dtsi diff --git a/arch/arm/boot/dts/exynos3250-monk.dts b/arch/arm/boot/dts/samsung/exynos3250-monk.dts similarity index 100% rename from arch/arm/boot/dts/exynos3250-monk.dts rename to arch/arm/boot/dts/samsung/exynos3250-monk.dts diff --git a/arch/arm/boot/dts/exynos3250-pinctrl.dtsi b/arch/arm/boot/dts/samsung/exynos3250-pinctrl.dtsi similarity index 99% rename from arch/arm/boot/dts/exynos3250-pinctrl.dtsi rename to arch/arm/boot/dts/samsung/exynos3250-pinctrl.dtsi index 011ba2eff29ebb8f15830f21c9d7cd3d064105ac..07828551d4b3a345ce0f7e2c473fc1b46e708b87 100644 --- a/arch/arm/boot/dts/exynos3250-pinctrl.dtsi +++ b/arch/arm/boot/dts/samsung/exynos3250-pinctrl.dtsi @@ -5,8 +5,8 @@ * Copyright (c) 2014 Samsung Electronics Co., Ltd. * http://www.samsung.com * - * Samsung's Exynos3250 SoCs pin-mux and pin-config optiosn are listed as device - * tree nodes are listed in this file. + * Samsung's Exynos3250 SoCs pin-mux and pin-config options are listed as device + * tree nodes in this file. */ #include "exynos-pinctrl.h" diff --git a/arch/arm/boot/dts/exynos3250-rinato.dts b/arch/arm/boot/dts/samsung/exynos3250-rinato.dts similarity index 100% rename from arch/arm/boot/dts/exynos3250-rinato.dts rename to arch/arm/boot/dts/samsung/exynos3250-rinato.dts diff --git a/arch/arm/boot/dts/exynos3250.dtsi b/arch/arm/boot/dts/samsung/exynos3250.dtsi similarity index 99% rename from arch/arm/boot/dts/exynos3250.dtsi rename to arch/arm/boot/dts/samsung/exynos3250.dtsi index bd37f1b587f03e3c31a4199d7d4c65828763178e..3f1015edab436a5b399f9b2367f6167efc0c494d 100644 --- a/arch/arm/boot/dts/exynos3250.dtsi +++ b/arch/arm/boot/dts/samsung/exynos3250.dtsi @@ -6,7 +6,7 @@ * http://www.samsung.com * * Samsung's Exynos3250 SoC device nodes are listed in this file. Exynos3250 - * based board files can include this file and provide values for board specfic + * based board files can include this file and provide values for board specific * bindings. * * Note: This file does not include device nodes for all the controllers in diff --git a/arch/arm/boot/dts/exynos4-cpu-thermal.dtsi b/arch/arm/boot/dts/samsung/exynos4-cpu-thermal.dtsi similarity index 100% rename from arch/arm/boot/dts/exynos4-cpu-thermal.dtsi rename to arch/arm/boot/dts/samsung/exynos4-cpu-thermal.dtsi diff --git a/arch/arm/boot/dts/exynos4.dtsi b/arch/arm/boot/dts/samsung/exynos4.dtsi similarity index 99% rename from arch/arm/boot/dts/exynos4.dtsi rename to arch/arm/boot/dts/samsung/exynos4.dtsi index 8dd6976ab0a71ce87c18b35d7c8eb02a7653e06f..f775b9377a38b53fc45e4c69e9408d5c826e1e44 100644 --- a/arch/arm/boot/dts/exynos4.dtsi +++ b/arch/arm/boot/dts/samsung/exynos4.dtsi @@ -9,7 +9,7 @@ * * Samsung's Exynos4 SoC series device nodes are listed in this file. Particular * SoCs from Exynos4 series can include this file and provide values for SoCs - * specfic bindings. + * specific bindings. * * Note: This file does not include device nodes for all the controllers in * Exynos4 SoCs. As device tree coverage for Exynos4 increases, additional @@ -201,8 +201,8 @@ #size-cells = <0>; }; - camera: camera { - compatible = "samsung,fimc", "simple-bus"; + camera: camera@11800000 { + compatible = "samsung,fimc"; status = "disabled"; #address-cells = <1>; #size-cells = <1>; diff --git a/arch/arm/boot/dts/exynos4210-i9100.dts b/arch/arm/boot/dts/samsung/exynos4210-i9100.dts similarity index 100% rename from arch/arm/boot/dts/exynos4210-i9100.dts rename to arch/arm/boot/dts/samsung/exynos4210-i9100.dts diff --git a/arch/arm/boot/dts/exynos4210-origen.dts b/arch/arm/boot/dts/samsung/exynos4210-origen.dts similarity index 100% rename from arch/arm/boot/dts/exynos4210-origen.dts rename to arch/arm/boot/dts/samsung/exynos4210-origen.dts diff --git a/arch/arm/boot/dts/exynos4210-pinctrl.dtsi b/arch/arm/boot/dts/samsung/exynos4210-pinctrl.dtsi similarity index 99% rename from arch/arm/boot/dts/exynos4210-pinctrl.dtsi rename to arch/arm/boot/dts/samsung/exynos4210-pinctrl.dtsi index 76f44ae0de46925b7ac39a4616f468169f942532..70d268f9fcb19028d8eaa6a8eac491139cb35e37 100644 --- a/arch/arm/boot/dts/exynos4210-pinctrl.dtsi +++ b/arch/arm/boot/dts/samsung/exynos4210-pinctrl.dtsi @@ -7,8 +7,8 @@ * Copyright (c) 2011-2012 Linaro Ltd. * www.linaro.org * - * Samsung's Exynos4210 SoC pin-mux and pin-config optiosn are listed as device - * tree nodes are listed in this file. + * Samsung's Exynos4210 SoC pin-mux and pin-config options are listed as device + * tree nodes in this file. */ #include "exynos-pinctrl.h" diff --git a/arch/arm/boot/dts/exynos4210-smdkv310.dts b/arch/arm/boot/dts/samsung/exynos4210-smdkv310.dts similarity index 100% rename from arch/arm/boot/dts/exynos4210-smdkv310.dts rename to arch/arm/boot/dts/samsung/exynos4210-smdkv310.dts diff --git a/arch/arm/boot/dts/exynos4210-trats.dts b/arch/arm/boot/dts/samsung/exynos4210-trats.dts similarity index 99% rename from arch/arm/boot/dts/exynos4210-trats.dts rename to arch/arm/boot/dts/samsung/exynos4210-trats.dts index ff6ee4b2c31b59bc75b4091fcef7719a9ba1f349..bfb04b31e11b83a88d7c4f6574540dab4bcde91c 100644 --- a/arch/arm/boot/dts/exynos4210-trats.dts +++ b/arch/arm/boot/dts/samsung/exynos4210-trats.dts @@ -150,8 +150,6 @@ }; &camera { - pinctrl-names = "default"; - pinctrl-0 = <>; status = "okay"; }; diff --git a/arch/arm/boot/dts/exynos4210-universal_c210.dts b/arch/arm/boot/dts/samsung/exynos4210-universal_c210.dts similarity index 99% rename from arch/arm/boot/dts/exynos4210-universal_c210.dts rename to arch/arm/boot/dts/samsung/exynos4210-universal_c210.dts index 8fe0d5d2be2d9cacb9b280dd69e0214c3326fbf9..c84af3d27c1c51d553eb1438fe3f6141794e10f1 100644 --- a/arch/arm/boot/dts/exynos4210-universal_c210.dts +++ b/arch/arm/boot/dts/samsung/exynos4210-universal_c210.dts @@ -197,9 +197,6 @@ &camera { status = "okay"; - - pinctrl-names = "default"; - pinctrl-0 = <>; }; &cpu0 { diff --git a/arch/arm/boot/dts/exynos4210.dtsi b/arch/arm/boot/dts/samsung/exynos4210.dtsi similarity index 100% rename from arch/arm/boot/dts/exynos4210.dtsi rename to arch/arm/boot/dts/samsung/exynos4210.dtsi diff --git a/arch/arm/boot/dts/samsung/exynos4212.dtsi b/arch/arm/boot/dts/samsung/exynos4212.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..aa984601ee06d656689ee3ba379916c969f0fefb --- /dev/null +++ b/arch/arm/boot/dts/samsung/exynos4212.dtsi @@ -0,0 +1,157 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Samsung's Exynos4212 SoC device tree source + * + * Copyright (c) 2012 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * Samsung's Exynos4212 SoC device nodes are listed in this file. Exynos4212 + * based board files can include this file and provide values for board specific + * bindings. + * + * Note: This file does not include device nodes for all the controllers in + * Exynos4212 SoC. As device tree coverage for Exynos4212 increases, additional + * nodes can be added to this file. + */ + +#include "exynos4x12.dtsi" + +/ { + compatible = "samsung,exynos4212", "samsung,exynos4"; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu-map { + cluster0 { + core0 { + cpu = <&cpu0>; + }; + core1 { + cpu = <&cpu1>; + }; + }; + }; + + cpu0: cpu@a00 { + device_type = "cpu"; + compatible = "arm,cortex-a9"; + reg = <0xa00>; + clocks = <&clock CLK_ARM_CLK>; + clock-names = "cpu"; + operating-points-v2 = <&cpu0_opp_table>; + #cooling-cells = <2>; /* min followed by max */ + }; + + cpu1: cpu@a01 { + device_type = "cpu"; + compatible = "arm,cortex-a9"; + reg = <0xa01>; + clocks = <&clock CLK_ARM_CLK>; + clock-names = "cpu"; + operating-points-v2 = <&cpu0_opp_table>; + #cooling-cells = <2>; /* min followed by max */ + }; + }; + + cpu0_opp_table: opp-table-0 { + compatible = "operating-points-v2"; + opp-shared; + + opp-200000000 { + opp-hz = /bits/ 64 <200000000>; + opp-microvolt = <900000>; + clock-latency-ns = <200000>; + }; + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + opp-microvolt = <900000>; + clock-latency-ns = <200000>; + }; + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + opp-microvolt = <925000>; + clock-latency-ns = <200000>; + }; + opp-500000000 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <950000>; + clock-latency-ns = <200000>; + }; + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + opp-microvolt = <975000>; + clock-latency-ns = <200000>; + }; + opp-700000000 { + opp-hz = /bits/ 64 <700000000>; + opp-microvolt = <987500>; + clock-latency-ns = <200000>; + }; + opp-800000000 { + opp-hz = /bits/ 64 <800000000>; + opp-microvolt = <1000000>; + clock-latency-ns = <200000>; + opp-suspend; + }; + opp-900000000 { + opp-hz = /bits/ 64 <900000000>; + opp-microvolt = <1037500>; + clock-latency-ns = <200000>; + }; + opp-1000000000 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <1087500>; + clock-latency-ns = <200000>; + }; + opp-1100000000 { + opp-hz = /bits/ 64 <1100000000>; + opp-microvolt = <1137500>; + clock-latency-ns = <200000>; + }; + opp-1200000000 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <1187500>; + clock-latency-ns = <200000>; + }; + opp-1300000000 { + opp-hz = /bits/ 64 <1300000000>; + opp-microvolt = <1250000>; + clock-latency-ns = <200000>; + }; + opp-1400000000 { + opp-hz = /bits/ 64 <1400000000>; + opp-microvolt = <1287500>; + clock-latency-ns = <200000>; + }; + cpu0_opp_1500: opp-1500000000 { + opp-hz = /bits/ 64 <1500000000>; + opp-microvolt = <1350000>; + clock-latency-ns = <200000>; + turbo-mode; + }; + }; +}; + +&clock { + compatible = "samsung,exynos4212-clock"; +}; + +&combiner { + samsung,combiner-nr = <18>; +}; + +&gic { + cpu-offset = <0x8000>; +}; + +&pmu { + interrupts = <2 2>, <3 2>; + interrupt-affinity = <&cpu0>, <&cpu1>; + status = "okay"; +}; + +&pmu_system_controller { + compatible = "samsung,exynos4212-pmu", "simple-mfd", "syscon"; +}; diff --git a/arch/arm/boot/dts/exynos4412-galaxy-s3.dtsi b/arch/arm/boot/dts/samsung/exynos4412-galaxy-s3.dtsi similarity index 100% rename from arch/arm/boot/dts/exynos4412-galaxy-s3.dtsi rename to arch/arm/boot/dts/samsung/exynos4412-galaxy-s3.dtsi diff --git a/arch/arm/boot/dts/exynos4412-i9300.dts b/arch/arm/boot/dts/samsung/exynos4412-i9300.dts similarity index 100% rename from arch/arm/boot/dts/exynos4412-i9300.dts rename to arch/arm/boot/dts/samsung/exynos4412-i9300.dts diff --git a/arch/arm/boot/dts/exynos4412-i9305.dts b/arch/arm/boot/dts/samsung/exynos4412-i9305.dts similarity index 100% rename from arch/arm/boot/dts/exynos4412-i9305.dts rename to arch/arm/boot/dts/samsung/exynos4412-i9305.dts diff --git a/arch/arm/boot/dts/exynos4412-itop-elite.dts b/arch/arm/boot/dts/samsung/exynos4412-itop-elite.dts similarity index 100% rename from arch/arm/boot/dts/exynos4412-itop-elite.dts rename to arch/arm/boot/dts/samsung/exynos4412-itop-elite.dts diff --git a/arch/arm/boot/dts/exynos4412-itop-scp-core.dtsi b/arch/arm/boot/dts/samsung/exynos4412-itop-scp-core.dtsi similarity index 100% rename from arch/arm/boot/dts/exynos4412-itop-scp-core.dtsi rename to arch/arm/boot/dts/samsung/exynos4412-itop-scp-core.dtsi diff --git a/arch/arm/boot/dts/exynos4412-midas.dtsi b/arch/arm/boot/dts/samsung/exynos4412-midas.dtsi similarity index 100% rename from arch/arm/boot/dts/exynos4412-midas.dtsi rename to arch/arm/boot/dts/samsung/exynos4412-midas.dtsi diff --git a/arch/arm/boot/dts/exynos4412-n710x.dts b/arch/arm/boot/dts/samsung/exynos4412-n710x.dts similarity index 100% rename from arch/arm/boot/dts/exynos4412-n710x.dts rename to arch/arm/boot/dts/samsung/exynos4412-n710x.dts diff --git a/arch/arm/boot/dts/exynos4412-odroid-common.dtsi b/arch/arm/boot/dts/samsung/exynos4412-odroid-common.dtsi similarity index 99% rename from arch/arm/boot/dts/exynos4412-odroid-common.dtsi rename to arch/arm/boot/dts/samsung/exynos4412-odroid-common.dtsi index 45ef7b7ba7e0f0e8769e9a61631339941fd1bc40..93ddbd4b0a1898303a041ecc453c3d8635c2c8c5 100644 --- a/arch/arm/boot/dts/exynos4412-odroid-common.dtsi +++ b/arch/arm/boot/dts/samsung/exynos4412-odroid-common.dtsi @@ -122,8 +122,6 @@ &camera { status = "okay"; - pinctrl-names = "default"; - pinctrl-0 = <>; }; &clock { diff --git a/arch/arm/boot/dts/exynos4412-odroidu3.dts b/arch/arm/boot/dts/samsung/exynos4412-odroidu3.dts similarity index 100% rename from arch/arm/boot/dts/exynos4412-odroidu3.dts rename to arch/arm/boot/dts/samsung/exynos4412-odroidu3.dts diff --git a/arch/arm/boot/dts/exynos4412-odroidx.dts b/arch/arm/boot/dts/samsung/exynos4412-odroidx.dts similarity index 100% rename from arch/arm/boot/dts/exynos4412-odroidx.dts rename to arch/arm/boot/dts/samsung/exynos4412-odroidx.dts diff --git a/arch/arm/boot/dts/exynos4412-odroidx2.dts b/arch/arm/boot/dts/samsung/exynos4412-odroidx2.dts similarity index 100% rename from arch/arm/boot/dts/exynos4412-odroidx2.dts rename to arch/arm/boot/dts/samsung/exynos4412-odroidx2.dts diff --git a/arch/arm/boot/dts/exynos4412-origen.dts b/arch/arm/boot/dts/samsung/exynos4412-origen.dts similarity index 100% rename from arch/arm/boot/dts/exynos4412-origen.dts rename to arch/arm/boot/dts/samsung/exynos4412-origen.dts diff --git a/arch/arm/boot/dts/exynos4412-p4note-n8010.dts b/arch/arm/boot/dts/samsung/exynos4412-p4note-n8010.dts similarity index 100% rename from arch/arm/boot/dts/exynos4412-p4note-n8010.dts rename to arch/arm/boot/dts/samsung/exynos4412-p4note-n8010.dts diff --git a/arch/arm/boot/dts/exynos4412-p4note.dtsi b/arch/arm/boot/dts/samsung/exynos4412-p4note.dtsi similarity index 100% rename from arch/arm/boot/dts/exynos4412-p4note.dtsi rename to arch/arm/boot/dts/samsung/exynos4412-p4note.dtsi diff --git a/arch/arm/boot/dts/exynos4412-ppmu-common.dtsi b/arch/arm/boot/dts/samsung/exynos4412-ppmu-common.dtsi similarity index 100% rename from arch/arm/boot/dts/exynos4412-ppmu-common.dtsi rename to arch/arm/boot/dts/samsung/exynos4412-ppmu-common.dtsi diff --git a/arch/arm/boot/dts/exynos4412-prime.dtsi b/arch/arm/boot/dts/samsung/exynos4412-prime.dtsi similarity index 100% rename from arch/arm/boot/dts/exynos4412-prime.dtsi rename to arch/arm/boot/dts/samsung/exynos4412-prime.dtsi diff --git a/arch/arm/boot/dts/exynos4412-smdk4412.dts b/arch/arm/boot/dts/samsung/exynos4412-smdk4412.dts similarity index 100% rename from arch/arm/boot/dts/exynos4412-smdk4412.dts rename to arch/arm/boot/dts/samsung/exynos4412-smdk4412.dts diff --git a/arch/arm/boot/dts/exynos4412-tiny4412.dts b/arch/arm/boot/dts/samsung/exynos4412-tiny4412.dts similarity index 100% rename from arch/arm/boot/dts/exynos4412-tiny4412.dts rename to arch/arm/boot/dts/samsung/exynos4412-tiny4412.dts diff --git a/arch/arm/boot/dts/exynos4412-trats2.dts b/arch/arm/boot/dts/samsung/exynos4412-trats2.dts similarity index 100% rename from arch/arm/boot/dts/exynos4412-trats2.dts rename to arch/arm/boot/dts/samsung/exynos4412-trats2.dts diff --git a/arch/arm/boot/dts/samsung/exynos4412.dtsi b/arch/arm/boot/dts/samsung/exynos4412.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..dcbe0ce6180fe8b0709eb087bf0d3afdb7846036 --- /dev/null +++ b/arch/arm/boot/dts/samsung/exynos4412.dtsi @@ -0,0 +1,183 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Samsung's Exynos4412 SoC device tree source + * + * Copyright (c) 2012 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * Samsung's Exynos4412 SoC device nodes are listed in this file. Exynos4412 + * based board files can include this file and provide values for board specific + * bindings. + * + * Note: This file does not include device nodes for all the controllers in + * Exynos4412 SoC. As device tree coverage for Exynos4412 increases, additional + * nodes can be added to this file. + */ + +#include "exynos4x12.dtsi" + +/ { + compatible = "samsung,exynos4412", "samsung,exynos4"; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu-map { + cluster0 { + core0 { + cpu = <&cpu0>; + }; + core1 { + cpu = <&cpu1>; + }; + core2 { + cpu = <&cpu2>; + }; + core3 { + cpu = <&cpu3>; + }; + }; + }; + + cpu0: cpu@a00 { + device_type = "cpu"; + compatible = "arm,cortex-a9"; + reg = <0xa00>; + clocks = <&clock CLK_ARM_CLK>; + clock-names = "cpu"; + operating-points-v2 = <&cpu0_opp_table>; + #cooling-cells = <2>; /* min followed by max */ + }; + + cpu1: cpu@a01 { + device_type = "cpu"; + compatible = "arm,cortex-a9"; + reg = <0xa01>; + clocks = <&clock CLK_ARM_CLK>; + clock-names = "cpu"; + operating-points-v2 = <&cpu0_opp_table>; + #cooling-cells = <2>; /* min followed by max */ + }; + + cpu2: cpu@a02 { + device_type = "cpu"; + compatible = "arm,cortex-a9"; + reg = <0xa02>; + clocks = <&clock CLK_ARM_CLK>; + clock-names = "cpu"; + operating-points-v2 = <&cpu0_opp_table>; + #cooling-cells = <2>; /* min followed by max */ + }; + + cpu3: cpu@a03 { + device_type = "cpu"; + compatible = "arm,cortex-a9"; + reg = <0xa03>; + clocks = <&clock CLK_ARM_CLK>; + clock-names = "cpu"; + operating-points-v2 = <&cpu0_opp_table>; + #cooling-cells = <2>; /* min followed by max */ + }; + }; + + cpu0_opp_table: opp-table-0 { + compatible = "operating-points-v2"; + opp-shared; + + opp-200000000 { + opp-hz = /bits/ 64 <200000000>; + opp-microvolt = <900000>; + clock-latency-ns = <200000>; + }; + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + opp-microvolt = <900000>; + clock-latency-ns = <200000>; + }; + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + opp-microvolt = <925000>; + clock-latency-ns = <200000>; + }; + opp-500000000 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <950000>; + clock-latency-ns = <200000>; + }; + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + opp-microvolt = <975000>; + clock-latency-ns = <200000>; + }; + opp-700000000 { + opp-hz = /bits/ 64 <700000000>; + opp-microvolt = <987500>; + clock-latency-ns = <200000>; + }; + opp-800000000 { + opp-hz = /bits/ 64 <800000000>; + opp-microvolt = <1000000>; + clock-latency-ns = <200000>; + opp-suspend; + }; + opp-900000000 { + opp-hz = /bits/ 64 <900000000>; + opp-microvolt = <1037500>; + clock-latency-ns = <200000>; + }; + opp-1000000000 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <1087500>; + clock-latency-ns = <200000>; + }; + opp-1100000000 { + opp-hz = /bits/ 64 <1100000000>; + opp-microvolt = <1137500>; + clock-latency-ns = <200000>; + }; + opp-1200000000 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <1187500>; + clock-latency-ns = <200000>; + }; + opp-1300000000 { + opp-hz = /bits/ 64 <1300000000>; + opp-microvolt = <1250000>; + clock-latency-ns = <200000>; + }; + opp-1400000000 { + opp-hz = /bits/ 64 <1400000000>; + opp-microvolt = <1287500>; + clock-latency-ns = <200000>; + }; + cpu0_opp_1500: opp-1500000000 { + opp-hz = /bits/ 64 <1500000000>; + opp-microvolt = <1350000>; + clock-latency-ns = <200000>; + turbo-mode; + }; + }; +}; + +&clock { + compatible = "samsung,exynos4412-clock"; +}; + +&combiner { + samsung,combiner-nr = <20>; +}; + +&gic { + cpu-offset = <0x4000>; +}; + +&pmu { + interrupts = <2 2>, <3 2>, <18 2>, <19 2>; + interrupt-affinity = <&cpu0>, <&cpu1>, <&cpu2>, <&cpu3>; + status = "okay"; +}; + +&pmu_system_controller { + compatible = "samsung,exynos4412-pmu", "simple-mfd", "syscon"; +}; diff --git a/arch/arm/boot/dts/exynos4412-pinctrl.dtsi b/arch/arm/boot/dts/samsung/exynos4x12-pinctrl.dtsi similarity index 99% rename from arch/arm/boot/dts/exynos4412-pinctrl.dtsi rename to arch/arm/boot/dts/samsung/exynos4x12-pinctrl.dtsi index 8ab31c3daa4815cf411fb8a9117e08f44d5108b7..04935fbe2f2a4491e980a65d83ea6801ea66d0ac 100644 --- a/arch/arm/boot/dts/exynos4412-pinctrl.dtsi +++ b/arch/arm/boot/dts/samsung/exynos4x12-pinctrl.dtsi @@ -1,12 +1,12 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Samsung's Exynos4412 SoCs pin-mux and pin-config device tree source + * Samsung's Exynos4x12 SoCs pin-mux and pin-config device tree source * * Copyright (c) 2012 Samsung Electronics Co., Ltd. * http://www.samsung.com * - * Samsung's Exynos4412 SoCs pin-mux and pin-config optiosn are listed as device - * tree nodes are listed in this file. + * Samsung's Exynos4x12 SoCs pin-mux and pin-config options are listed as device + * tree nodes in this file. */ #include "exynos-pinctrl.h" diff --git a/arch/arm/boot/dts/exynos4412.dtsi b/arch/arm/boot/dts/samsung/exynos4x12.dtsi similarity index 81% rename from arch/arm/boot/dts/exynos4412.dtsi rename to arch/arm/boot/dts/samsung/exynos4x12.dtsi index 82a36fb5ee8b7ea98bfd10cd32dd16a186613d18..84c1db221c984b4b971faaddbd009c92838832ee 100644 --- a/arch/arm/boot/dts/exynos4412.dtsi +++ b/arch/arm/boot/dts/samsung/exynos4x12.dtsi @@ -5,12 +5,12 @@ * Copyright (c) 2012 Samsung Electronics Co., Ltd. * http://www.samsung.com * - * Samsung's Exynos4412 SoC device nodes are listed in this file. Exynos4412 - * based board files can include this file and provide values for board specfic - * bindings. + * Samsung's Exynos4x12 SoC series device nodes are listed in this file. + * Particular SoCs from Exynos4x12 series can include this file and provide + * values for SoCs specific bindings. * * Note: This file does not include device nodes for all the controllers in - * Exynos4412 SoC. As device tree coverage for Exynos4412 increases, additional + * Exynos4x12 SoCs. As device tree coverage for Exynos4x12 increases, additional * nodes can be added to this file. */ @@ -19,8 +19,6 @@ #include "exynos4-cpu-thermal.dtsi" / { - compatible = "samsung,exynos4412", "samsung,exynos4"; - aliases { pinctrl0 = &pinctrl_0; pinctrl1 = &pinctrl_1; @@ -158,146 +156,6 @@ status = "disabled"; }; - cpus { - #address-cells = <1>; - #size-cells = <0>; - - cpu-map { - cluster0 { - core0 { - cpu = <&cpu0>; - }; - core1 { - cpu = <&cpu1>; - }; - core2 { - cpu = <&cpu2>; - }; - core3 { - cpu = <&cpu3>; - }; - }; - }; - - cpu0: cpu@a00 { - device_type = "cpu"; - compatible = "arm,cortex-a9"; - reg = <0xa00>; - clocks = <&clock CLK_ARM_CLK>; - clock-names = "cpu"; - operating-points-v2 = <&cpu0_opp_table>; - #cooling-cells = <2>; /* min followed by max */ - }; - - cpu1: cpu@a01 { - device_type = "cpu"; - compatible = "arm,cortex-a9"; - reg = <0xa01>; - clocks = <&clock CLK_ARM_CLK>; - clock-names = "cpu"; - operating-points-v2 = <&cpu0_opp_table>; - #cooling-cells = <2>; /* min followed by max */ - }; - - cpu2: cpu@a02 { - device_type = "cpu"; - compatible = "arm,cortex-a9"; - reg = <0xa02>; - clocks = <&clock CLK_ARM_CLK>; - clock-names = "cpu"; - operating-points-v2 = <&cpu0_opp_table>; - #cooling-cells = <2>; /* min followed by max */ - }; - - cpu3: cpu@a03 { - device_type = "cpu"; - compatible = "arm,cortex-a9"; - reg = <0xa03>; - clocks = <&clock CLK_ARM_CLK>; - clock-names = "cpu"; - operating-points-v2 = <&cpu0_opp_table>; - #cooling-cells = <2>; /* min followed by max */ - }; - }; - - cpu0_opp_table: opp-table-0 { - compatible = "operating-points-v2"; - opp-shared; - - opp-200000000 { - opp-hz = /bits/ 64 <200000000>; - opp-microvolt = <900000>; - clock-latency-ns = <200000>; - }; - opp-300000000 { - opp-hz = /bits/ 64 <300000000>; - opp-microvolt = <900000>; - clock-latency-ns = <200000>; - }; - opp-400000000 { - opp-hz = /bits/ 64 <400000000>; - opp-microvolt = <925000>; - clock-latency-ns = <200000>; - }; - opp-500000000 { - opp-hz = /bits/ 64 <500000000>; - opp-microvolt = <950000>; - clock-latency-ns = <200000>; - }; - opp-600000000 { - opp-hz = /bits/ 64 <600000000>; - opp-microvolt = <975000>; - clock-latency-ns = <200000>; - }; - opp-700000000 { - opp-hz = /bits/ 64 <700000000>; - opp-microvolt = <987500>; - clock-latency-ns = <200000>; - }; - opp-800000000 { - opp-hz = /bits/ 64 <800000000>; - opp-microvolt = <1000000>; - clock-latency-ns = <200000>; - opp-suspend; - }; - opp-900000000 { - opp-hz = /bits/ 64 <900000000>; - opp-microvolt = <1037500>; - clock-latency-ns = <200000>; - }; - opp-1000000000 { - opp-hz = /bits/ 64 <1000000000>; - opp-microvolt = <1087500>; - clock-latency-ns = <200000>; - }; - opp-1100000000 { - opp-hz = /bits/ 64 <1100000000>; - opp-microvolt = <1137500>; - clock-latency-ns = <200000>; - }; - opp-1200000000 { - opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <1187500>; - clock-latency-ns = <200000>; - }; - opp-1300000000 { - opp-hz = /bits/ 64 <1300000000>; - opp-microvolt = <1250000>; - clock-latency-ns = <200000>; - }; - opp-1400000000 { - opp-hz = /bits/ 64 <1400000000>; - opp-microvolt = <1287500>; - clock-latency-ns = <200000>; - }; - cpu0_opp_1500: opp-1500000000 { - opp-hz = /bits/ 64 <1500000000>; - opp-microvolt = <1350000>; - clock-latency-ns = <200000>; - turbo-mode; - }; - }; - bus_dmc_opp_table: opp-table-1 { compatible = "operating-points-v2"; @@ -421,7 +279,6 @@ }; clock: clock-controller@10030000 { - compatible = "samsung,exynos4412-clock"; reg = <0x10030000 0x18000>; #clock-cells = <1>; }; @@ -571,7 +428,6 @@ }; &combiner { - samsung,combiner-nr = <20>; interrupts = , , , @@ -719,10 +575,6 @@ samsung,lcd-wb; }; -&gic { - cpu-offset = <0x4000>; -}; - &gpu { interrupts = , , @@ -790,14 +642,7 @@ interconnects = <&bus_display &bus_dmc>; }; -&pmu { - interrupts = <2 2>, <3 2>, <18 2>, <19 2>; - interrupt-affinity = <&cpu0>, <&cpu1>, <&cpu2>, <&cpu3>; - status = "okay"; -}; - &pmu_system_controller { - compatible = "samsung,exynos4412-pmu", "simple-mfd", "syscon"; clock-names = "clkout0", "clkout1", "clkout2", "clkout3", "clkout4", "clkout8", "clkout9"; clocks = <&clock CLK_OUT_DMC>, <&clock CLK_OUT_TOP>, @@ -816,4 +661,4 @@ status = "disabled"; }; -#include "exynos4412-pinctrl.dtsi" +#include "exynos4x12-pinctrl.dtsi" diff --git a/arch/arm/boot/dts/exynos5.dtsi b/arch/arm/boot/dts/samsung/exynos5.dtsi similarity index 99% rename from arch/arm/boot/dts/exynos5.dtsi rename to arch/arm/boot/dts/samsung/exynos5.dtsi index 48e43b6b3213a245310d15d2372a81a6a7501a7b..4a17a19586bb1306a7db0289518a4198a924b429 100644 --- a/arch/arm/boot/dts/exynos5.dtsi +++ b/arch/arm/boot/dts/samsung/exynos5.dtsi @@ -7,7 +7,7 @@ * * Samsung's Exynos5 SoC series device nodes are listed in this file. Particular * SoCs from Exynos5 series can include this file and provide values for SoCs - * specfic bindings. + * specific bindings. */ #include diff --git a/arch/arm/boot/dts/exynos5250-arndale.dts b/arch/arm/boot/dts/samsung/exynos5250-arndale.dts similarity index 100% rename from arch/arm/boot/dts/exynos5250-arndale.dts rename to arch/arm/boot/dts/samsung/exynos5250-arndale.dts diff --git a/arch/arm/boot/dts/exynos5250-pinctrl.dtsi b/arch/arm/boot/dts/samsung/exynos5250-pinctrl.dtsi similarity index 99% rename from arch/arm/boot/dts/exynos5250-pinctrl.dtsi rename to arch/arm/boot/dts/samsung/exynos5250-pinctrl.dtsi index 48732edadff159712bccee4e4c4716aa438e8b1d..d956540a2d88a55da6f971fa4d2b0e8d5f468344 100644 --- a/arch/arm/boot/dts/exynos5250-pinctrl.dtsi +++ b/arch/arm/boot/dts/samsung/exynos5250-pinctrl.dtsi @@ -5,8 +5,8 @@ * Copyright (c) 2012 Samsung Electronics Co., Ltd. * http://www.samsung.com * - * Samsung's Exynos5250 SoC pin-mux and pin-config optiosn are listed as device - * tree nodes are listed in this file. + * Samsung's Exynos5250 SoC pin-mux and pin-config options are listed as device + * tree nodes in this file. */ #include "exynos-pinctrl.h" diff --git a/arch/arm/boot/dts/exynos5250-smdk5250.dts b/arch/arm/boot/dts/samsung/exynos5250-smdk5250.dts similarity index 100% rename from arch/arm/boot/dts/exynos5250-smdk5250.dts rename to arch/arm/boot/dts/samsung/exynos5250-smdk5250.dts diff --git a/arch/arm/boot/dts/exynos5250-snow-common.dtsi b/arch/arm/boot/dts/samsung/exynos5250-snow-common.dtsi similarity index 99% rename from arch/arm/boot/dts/exynos5250-snow-common.dtsi rename to arch/arm/boot/dts/samsung/exynos5250-snow-common.dtsi index 59b2cc35c37b75e819ca0de0c5d30d9d613a615b..c82e2762e07c4d329bd02c989c8b89bd73cd5b54 100644 --- a/arch/arm/boot/dts/exynos5250-snow-common.dtsi +++ b/arch/arm/boot/dts/samsung/exynos5250-snow-common.dtsi @@ -715,4 +715,4 @@ vbus-supply = <&usb3_vbus_reg>; }; -#include "cros-ec-keyboard.dtsi" +#include "../cros-ec-keyboard.dtsi" diff --git a/arch/arm/boot/dts/exynos5250-snow-rev5.dts b/arch/arm/boot/dts/samsung/exynos5250-snow-rev5.dts similarity index 100% rename from arch/arm/boot/dts/exynos5250-snow-rev5.dts rename to arch/arm/boot/dts/samsung/exynos5250-snow-rev5.dts diff --git a/arch/arm/boot/dts/exynos5250-snow.dts b/arch/arm/boot/dts/samsung/exynos5250-snow.dts similarity index 100% rename from arch/arm/boot/dts/exynos5250-snow.dts rename to arch/arm/boot/dts/samsung/exynos5250-snow.dts diff --git a/arch/arm/boot/dts/exynos5250-spring.dts b/arch/arm/boot/dts/samsung/exynos5250-spring.dts similarity index 99% rename from arch/arm/boot/dts/exynos5250-spring.dts rename to arch/arm/boot/dts/samsung/exynos5250-spring.dts index c12bb17631b7c92220de71ab66998a0168c46bd2..d126fccdcaf34c41cac6d7a9499cae9f880b1bc5 100644 --- a/arch/arm/boot/dts/exynos5250-spring.dts +++ b/arch/arm/boot/dts/samsung/exynos5250-spring.dts @@ -564,4 +564,4 @@ vdd33-supply = <&ldo12_reg>; }; -#include "cros-ec-keyboard.dtsi" +#include "../cros-ec-keyboard.dtsi" diff --git a/arch/arm/boot/dts/exynos5250.dtsi b/arch/arm/boot/dts/samsung/exynos5250.dtsi similarity index 99% rename from arch/arm/boot/dts/exynos5250.dtsi rename to arch/arm/boot/dts/samsung/exynos5250.dtsi index 1a4c6c028d038ceef46098ec9f52c451a4444370..99c84bebf25a4b38cfdf7a65e540ee3ea8af055b 100644 --- a/arch/arm/boot/dts/exynos5250.dtsi +++ b/arch/arm/boot/dts/samsung/exynos5250.dtsi @@ -7,7 +7,7 @@ * * Samsung Exynos5250 SoC device nodes are listed in this file. * Exynos5250 based board files can include this file and provide - * values for board specfic bindings. + * values for board specific bindings. * * Note: This file does not include device nodes for all the controllers in * Exynos5250 SoC. As device tree coverage for Exynos5250 increases, diff --git a/arch/arm/boot/dts/exynos5260-pinctrl.dtsi b/arch/arm/boot/dts/samsung/exynos5260-pinctrl.dtsi similarity index 99% rename from arch/arm/boot/dts/exynos5260-pinctrl.dtsi rename to arch/arm/boot/dts/samsung/exynos5260-pinctrl.dtsi index 43e4a541f47984f3fdb8d02754341e8ab8a841b7..d15494b4bda9a3403c0373aa4ce6f8c6cc8678c2 100644 --- a/arch/arm/boot/dts/exynos5260-pinctrl.dtsi +++ b/arch/arm/boot/dts/samsung/exynos5260-pinctrl.dtsi @@ -6,7 +6,7 @@ * http://www.samsung.com * * Samsung's Exynos5260 SoC pin-mux and pin-config options are listed as device - * tree nodes are listed in this file. + * tree nodes in this file. */ #include "exynos-pinctrl.h" diff --git a/arch/arm/boot/dts/exynos5260-xyref5260.dts b/arch/arm/boot/dts/samsung/exynos5260-xyref5260.dts similarity index 100% rename from arch/arm/boot/dts/exynos5260-xyref5260.dts rename to arch/arm/boot/dts/samsung/exynos5260-xyref5260.dts diff --git a/arch/arm/boot/dts/exynos5260.dtsi b/arch/arm/boot/dts/samsung/exynos5260.dtsi similarity index 100% rename from arch/arm/boot/dts/exynos5260.dtsi rename to arch/arm/boot/dts/samsung/exynos5260.dtsi diff --git a/arch/arm/boot/dts/exynos5410-odroidxu.dts b/arch/arm/boot/dts/samsung/exynos5410-odroidxu.dts similarity index 100% rename from arch/arm/boot/dts/exynos5410-odroidxu.dts rename to arch/arm/boot/dts/samsung/exynos5410-odroidxu.dts diff --git a/arch/arm/boot/dts/exynos5410-pinctrl.dtsi b/arch/arm/boot/dts/samsung/exynos5410-pinctrl.dtsi similarity index 100% rename from arch/arm/boot/dts/exynos5410-pinctrl.dtsi rename to arch/arm/boot/dts/samsung/exynos5410-pinctrl.dtsi diff --git a/arch/arm/boot/dts/exynos5410-smdk5410.dts b/arch/arm/boot/dts/samsung/exynos5410-smdk5410.dts similarity index 100% rename from arch/arm/boot/dts/exynos5410-smdk5410.dts rename to arch/arm/boot/dts/samsung/exynos5410-smdk5410.dts diff --git a/arch/arm/boot/dts/exynos5410.dtsi b/arch/arm/boot/dts/samsung/exynos5410.dtsi similarity index 99% rename from arch/arm/boot/dts/exynos5410.dtsi rename to arch/arm/boot/dts/samsung/exynos5410.dtsi index 350b8afa0a3a039a8d95c33df795c7734b5dd21a..546035e78f404d764cb653ce25b73778c53fac0b 100644 --- a/arch/arm/boot/dts/exynos5410.dtsi +++ b/arch/arm/boot/dts/samsung/exynos5410.dtsi @@ -7,7 +7,7 @@ * * Samsung Exynos5410 SoC device nodes are listed in this file. * Exynos5410 based board files can include this file and provide - * values for board specfic bindings. + * values for board specific bindings. */ #include "exynos54xx.dtsi" diff --git a/arch/arm/boot/dts/exynos5420-arndale-octa.dts b/arch/arm/boot/dts/samsung/exynos5420-arndale-octa.dts similarity index 100% rename from arch/arm/boot/dts/exynos5420-arndale-octa.dts rename to arch/arm/boot/dts/samsung/exynos5420-arndale-octa.dts diff --git a/arch/arm/boot/dts/exynos5420-chagall-wifi.dts b/arch/arm/boot/dts/samsung/exynos5420-chagall-wifi.dts similarity index 100% rename from arch/arm/boot/dts/exynos5420-chagall-wifi.dts rename to arch/arm/boot/dts/samsung/exynos5420-chagall-wifi.dts diff --git a/arch/arm/boot/dts/exynos5420-cpus.dtsi b/arch/arm/boot/dts/samsung/exynos5420-cpus.dtsi similarity index 100% rename from arch/arm/boot/dts/exynos5420-cpus.dtsi rename to arch/arm/boot/dts/samsung/exynos5420-cpus.dtsi diff --git a/arch/arm/boot/dts/exynos5420-galaxy-tab-common.dtsi b/arch/arm/boot/dts/samsung/exynos5420-galaxy-tab-common.dtsi similarity index 100% rename from arch/arm/boot/dts/exynos5420-galaxy-tab-common.dtsi rename to arch/arm/boot/dts/samsung/exynos5420-galaxy-tab-common.dtsi diff --git a/arch/arm/boot/dts/exynos5420-klimt-wifi.dts b/arch/arm/boot/dts/samsung/exynos5420-klimt-wifi.dts similarity index 100% rename from arch/arm/boot/dts/exynos5420-klimt-wifi.dts rename to arch/arm/boot/dts/samsung/exynos5420-klimt-wifi.dts diff --git a/arch/arm/boot/dts/exynos5420-peach-pit.dts b/arch/arm/boot/dts/samsung/exynos5420-peach-pit.dts similarity index 99% rename from arch/arm/boot/dts/exynos5420-peach-pit.dts rename to arch/arm/boot/dts/samsung/exynos5420-peach-pit.dts index 7a48f2b32819343996d37a4bf1f4264d52bafaa8..4e757b6e28e1caee77fd0f0cd2efd4402a831703 100644 --- a/arch/arm/boot/dts/exynos5420-peach-pit.dts +++ b/arch/arm/boot/dts/samsung/exynos5420-peach-pit.dts @@ -1122,5 +1122,5 @@ timeout-sec = <32>; }; -#include "cros-ec-keyboard.dtsi" -#include "cros-adc-thermistors.dtsi" +#include "../cros-ec-keyboard.dtsi" +#include "../cros-adc-thermistors.dtsi" diff --git a/arch/arm/boot/dts/exynos5420-pinctrl.dtsi b/arch/arm/boot/dts/samsung/exynos5420-pinctrl.dtsi similarity index 99% rename from arch/arm/boot/dts/exynos5420-pinctrl.dtsi rename to arch/arm/boot/dts/samsung/exynos5420-pinctrl.dtsi index 14cf9c4ca0ed7a654dc963f9acf259c8f78b6207..93b9873fa84fd2d17279592462766c087b6387f7 100644 --- a/arch/arm/boot/dts/exynos5420-pinctrl.dtsi +++ b/arch/arm/boot/dts/samsung/exynos5420-pinctrl.dtsi @@ -6,7 +6,7 @@ * http://www.samsung.com * * Samsung's Exynos5420 SoC pin-mux and pin-config options are listed as device - * tree nodes are listed in this file. + * tree nodes in this file. */ #include "exynos-pinctrl.h" diff --git a/arch/arm/boot/dts/exynos5420-smdk5420.dts b/arch/arm/boot/dts/samsung/exynos5420-smdk5420.dts similarity index 100% rename from arch/arm/boot/dts/exynos5420-smdk5420.dts rename to arch/arm/boot/dts/samsung/exynos5420-smdk5420.dts diff --git a/arch/arm/boot/dts/exynos5420-trip-points.dtsi b/arch/arm/boot/dts/samsung/exynos5420-trip-points.dtsi similarity index 100% rename from arch/arm/boot/dts/exynos5420-trip-points.dtsi rename to arch/arm/boot/dts/samsung/exynos5420-trip-points.dtsi diff --git a/arch/arm/boot/dts/exynos5420.dtsi b/arch/arm/boot/dts/samsung/exynos5420.dtsi similarity index 99% rename from arch/arm/boot/dts/exynos5420.dtsi rename to arch/arm/boot/dts/samsung/exynos5420.dtsi index dd291f1199f28466f9e7f9b660d69b12f8b6cc2c..25ed90374679a8ab6ca5e018bbde8ca689ac483f 100644 --- a/arch/arm/boot/dts/exynos5420.dtsi +++ b/arch/arm/boot/dts/samsung/exynos5420.dtsi @@ -7,7 +7,7 @@ * * Samsung Exynos5420 SoC device nodes are listed in this file. * Exynos5420 based board files can include this file and provide - * values for board specfic bindings. + * values for board specific bindings. */ #include "exynos54xx.dtsi" diff --git a/arch/arm/boot/dts/exynos5422-cpus.dtsi b/arch/arm/boot/dts/samsung/exynos5422-cpus.dtsi similarity index 100% rename from arch/arm/boot/dts/exynos5422-cpus.dtsi rename to arch/arm/boot/dts/samsung/exynos5422-cpus.dtsi diff --git a/arch/arm/boot/dts/exynos5422-odroid-core.dtsi b/arch/arm/boot/dts/samsung/exynos5422-odroid-core.dtsi similarity index 100% rename from arch/arm/boot/dts/exynos5422-odroid-core.dtsi rename to arch/arm/boot/dts/samsung/exynos5422-odroid-core.dtsi diff --git a/arch/arm/boot/dts/exynos5422-odroidhc1.dts b/arch/arm/boot/dts/samsung/exynos5422-odroidhc1.dts similarity index 100% rename from arch/arm/boot/dts/exynos5422-odroidhc1.dts rename to arch/arm/boot/dts/samsung/exynos5422-odroidhc1.dts diff --git a/arch/arm/boot/dts/exynos5422-odroidxu3-audio.dtsi b/arch/arm/boot/dts/samsung/exynos5422-odroidxu3-audio.dtsi similarity index 100% rename from arch/arm/boot/dts/exynos5422-odroidxu3-audio.dtsi rename to arch/arm/boot/dts/samsung/exynos5422-odroidxu3-audio.dtsi diff --git a/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi b/arch/arm/boot/dts/samsung/exynos5422-odroidxu3-common.dtsi similarity index 100% rename from arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi rename to arch/arm/boot/dts/samsung/exynos5422-odroidxu3-common.dtsi diff --git a/arch/arm/boot/dts/exynos5422-odroidxu3-lite.dts b/arch/arm/boot/dts/samsung/exynos5422-odroidxu3-lite.dts similarity index 100% rename from arch/arm/boot/dts/exynos5422-odroidxu3-lite.dts rename to arch/arm/boot/dts/samsung/exynos5422-odroidxu3-lite.dts diff --git a/arch/arm/boot/dts/exynos5422-odroidxu3.dts b/arch/arm/boot/dts/samsung/exynos5422-odroidxu3.dts similarity index 100% rename from arch/arm/boot/dts/exynos5422-odroidxu3.dts rename to arch/arm/boot/dts/samsung/exynos5422-odroidxu3.dts diff --git a/arch/arm/boot/dts/exynos5422-odroidxu4.dts b/arch/arm/boot/dts/samsung/exynos5422-odroidxu4.dts similarity index 100% rename from arch/arm/boot/dts/exynos5422-odroidxu4.dts rename to arch/arm/boot/dts/samsung/exynos5422-odroidxu4.dts diff --git a/arch/arm/boot/dts/exynos5422-samsung-k3g.dts b/arch/arm/boot/dts/samsung/exynos5422-samsung-k3g.dts similarity index 100% rename from arch/arm/boot/dts/exynos5422-samsung-k3g.dts rename to arch/arm/boot/dts/samsung/exynos5422-samsung-k3g.dts diff --git a/arch/arm/boot/dts/exynos54xx-odroidxu-leds.dtsi b/arch/arm/boot/dts/samsung/exynos54xx-odroidxu-leds.dtsi similarity index 100% rename from arch/arm/boot/dts/exynos54xx-odroidxu-leds.dtsi rename to arch/arm/boot/dts/samsung/exynos54xx-odroidxu-leds.dtsi diff --git a/arch/arm/boot/dts/exynos54xx.dtsi b/arch/arm/boot/dts/samsung/exynos54xx.dtsi similarity index 100% rename from arch/arm/boot/dts/exynos54xx.dtsi rename to arch/arm/boot/dts/samsung/exynos54xx.dtsi diff --git a/arch/arm/boot/dts/exynos5800-peach-pi.dts b/arch/arm/boot/dts/samsung/exynos5800-peach-pi.dts similarity index 99% rename from arch/arm/boot/dts/exynos5800-peach-pi.dts rename to arch/arm/boot/dts/samsung/exynos5800-peach-pi.dts index 1f544f12da6c5bd75ed0287e3ca9e65977e61357..f91bc4ae008e43928de3c269b380c59d59cbce26 100644 --- a/arch/arm/boot/dts/exynos5800-peach-pi.dts +++ b/arch/arm/boot/dts/samsung/exynos5800-peach-pi.dts @@ -1104,5 +1104,5 @@ timeout-sec = <32>; }; -#include "cros-ec-keyboard.dtsi" -#include "cros-adc-thermistors.dtsi" +#include "../cros-ec-keyboard.dtsi" +#include "../cros-adc-thermistors.dtsi" diff --git a/arch/arm/boot/dts/exynos5800.dtsi b/arch/arm/boot/dts/samsung/exynos5800.dtsi similarity index 98% rename from arch/arm/boot/dts/exynos5800.dtsi rename to arch/arm/boot/dts/samsung/exynos5800.dtsi index 8328ddb3b02f91ac73bbf756a93c1188afd9a586..72d3a3535a7ae3aea01f57efebb020763b8db2ad 100644 --- a/arch/arm/boot/dts/exynos5800.dtsi +++ b/arch/arm/boot/dts/samsung/exynos5800.dtsi @@ -7,7 +7,7 @@ * * Samsung Exynos5800 SoC device nodes are listed in this file. * Exynos5800 based board files can include this file and provide - * values for board specfic bindings. + * values for board specific bindings. */ #include "exynos5420.dtsi" diff --git a/arch/arm/boot/dts/s3c6400.dtsi b/arch/arm/boot/dts/samsung/s3c6400.dtsi similarity index 98% rename from arch/arm/boot/dts/s3c6400.dtsi rename to arch/arm/boot/dts/samsung/s3c6400.dtsi index 8c28e8a0c8244d43bc928ce1bcd29fbe49299230..7cc785a63866847a2de03126245d67617585afe3 100644 --- a/arch/arm/boot/dts/s3c6400.dtsi +++ b/arch/arm/boot/dts/samsung/s3c6400.dtsi @@ -5,7 +5,7 @@ * Copyright (c) 2013 Tomasz Figa * * Samsung's S3C6400 SoC device nodes are listed in this file. S3C6400 - * based board files can include this file and provide values for board specfic + * based board files can include this file and provide values for board specific * bindings. * * Note: This file does not include device nodes for all the controllers in diff --git a/arch/arm/boot/dts/s3c6410-mini6410.dts b/arch/arm/boot/dts/samsung/s3c6410-mini6410.dts similarity index 100% rename from arch/arm/boot/dts/s3c6410-mini6410.dts rename to arch/arm/boot/dts/samsung/s3c6410-mini6410.dts diff --git a/arch/arm/boot/dts/s3c6410-smdk6410.dts b/arch/arm/boot/dts/samsung/s3c6410-smdk6410.dts similarity index 100% rename from arch/arm/boot/dts/s3c6410-smdk6410.dts rename to arch/arm/boot/dts/samsung/s3c6410-smdk6410.dts diff --git a/arch/arm/boot/dts/s3c6410.dtsi b/arch/arm/boot/dts/samsung/s3c6410.dtsi similarity index 98% rename from arch/arm/boot/dts/s3c6410.dtsi rename to arch/arm/boot/dts/samsung/s3c6410.dtsi index a766d6de696c554595130d8195cf16c3c3b44e7f..13e9cc69b8a80745833552c6fafbcb6a04ed174d 100644 --- a/arch/arm/boot/dts/s3c6410.dtsi +++ b/arch/arm/boot/dts/samsung/s3c6410.dtsi @@ -5,7 +5,7 @@ * Copyright (c) 2013 Tomasz Figa * * Samsung's S3C6410 SoC device nodes are listed in this file. S3C6410 - * based board files can include this file and provide values for board specfic + * based board files can include this file and provide values for board specific * bindings. * * Note: This file does not include device nodes for all the controllers in diff --git a/arch/arm/boot/dts/s3c64xx-pinctrl.dtsi b/arch/arm/boot/dts/samsung/s3c64xx-pinctrl.dtsi similarity index 100% rename from arch/arm/boot/dts/s3c64xx-pinctrl.dtsi rename to arch/arm/boot/dts/samsung/s3c64xx-pinctrl.dtsi diff --git a/arch/arm/boot/dts/s3c64xx-pinctrl.h b/arch/arm/boot/dts/samsung/s3c64xx-pinctrl.h similarity index 100% rename from arch/arm/boot/dts/s3c64xx-pinctrl.h rename to arch/arm/boot/dts/samsung/s3c64xx-pinctrl.h diff --git a/arch/arm/boot/dts/s3c64xx.dtsi b/arch/arm/boot/dts/samsung/s3c64xx.dtsi similarity index 99% rename from arch/arm/boot/dts/s3c64xx.dtsi rename to arch/arm/boot/dts/samsung/s3c64xx.dtsi index c03df635550001353d3844fe44b9a4126c7d63da..0b59135ffe880589bda1d2e6abb646401c10fbc2 100644 --- a/arch/arm/boot/dts/s3c64xx.dtsi +++ b/arch/arm/boot/dts/samsung/s3c64xx.dtsi @@ -6,7 +6,7 @@ * * Samsung's S3C64xx SoC series device nodes are listed in this file. * Particular SoCs from S3C64xx series can include this file and provide - * values for SoCs specfic bindings. + * values for SoCs specific bindings. * * Note: This file does not include device nodes for all the controllers in * S3C64xx SoCs. As device tree coverage for S3C64xx increases, additional diff --git a/arch/arm/boot/dts/s5pv210-aquila.dts b/arch/arm/boot/dts/samsung/s5pv210-aquila.dts similarity index 100% rename from arch/arm/boot/dts/s5pv210-aquila.dts rename to arch/arm/boot/dts/samsung/s5pv210-aquila.dts diff --git a/arch/arm/boot/dts/s5pv210-aries.dtsi b/arch/arm/boot/dts/samsung/s5pv210-aries.dtsi similarity index 100% rename from arch/arm/boot/dts/s5pv210-aries.dtsi rename to arch/arm/boot/dts/samsung/s5pv210-aries.dtsi diff --git a/arch/arm/boot/dts/s5pv210-fascinate4g.dts b/arch/arm/boot/dts/samsung/s5pv210-fascinate4g.dts similarity index 100% rename from arch/arm/boot/dts/s5pv210-fascinate4g.dts rename to arch/arm/boot/dts/samsung/s5pv210-fascinate4g.dts diff --git a/arch/arm/boot/dts/s5pv210-galaxys.dts b/arch/arm/boot/dts/samsung/s5pv210-galaxys.dts similarity index 100% rename from arch/arm/boot/dts/s5pv210-galaxys.dts rename to arch/arm/boot/dts/samsung/s5pv210-galaxys.dts diff --git a/arch/arm/boot/dts/s5pv210-goni.dts b/arch/arm/boot/dts/samsung/s5pv210-goni.dts similarity index 100% rename from arch/arm/boot/dts/s5pv210-goni.dts rename to arch/arm/boot/dts/samsung/s5pv210-goni.dts diff --git a/arch/arm/boot/dts/s5pv210-pinctrl.dtsi b/arch/arm/boot/dts/samsung/s5pv210-pinctrl.dtsi similarity index 98% rename from arch/arm/boot/dts/s5pv210-pinctrl.dtsi rename to arch/arm/boot/dts/samsung/s5pv210-pinctrl.dtsi index 6d6daef9fb7a34965d9e96545065fed897677adc..af740abd9e0f4d55f66dd54656f5e5a02400882a 100644 --- a/arch/arm/boot/dts/s5pv210-pinctrl.dtsi +++ b/arch/arm/boot/dts/samsung/s5pv210-pinctrl.dtsi @@ -1,25 +1,21 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Samsung's S5PV210 SoC device tree source + * Samsung's S5PV210 SoC device tree source - pin control-related + * definitions * * Copyright (c) 2013-2014 Samsung Electronics, Co. Ltd. * * Mateusz Krawczuk * Tomasz Figa * - * Samsung's S5PV210 SoC device nodes are listed in this file. S5PV210 - * based board files can include this file and provide values for board specfic - * bindings. - * - * Note: This file does not include device nodes for all the controllers in - * S5PV210 SoC. As device tree coverage for S5PV210 increases, additional - * nodes can be added to this file. + * Samsung's S5PV210 SoC pin banks, pin-mux and pin-config options are + * listed as device tree nodes in this file. */ #include "s5pv210-pinctrl.h" #define PIN_SLP(_pin, _mode, _pull) \ - _pin { \ + pin- ## _pin { \ samsung,pins = #_pin; \ samsung,pin-con-pdn = ; \ samsung,pin-pud-pdn = ; \ diff --git a/arch/arm/boot/dts/s5pv210-pinctrl.h b/arch/arm/boot/dts/samsung/s5pv210-pinctrl.h similarity index 100% rename from arch/arm/boot/dts/s5pv210-pinctrl.h rename to arch/arm/boot/dts/samsung/s5pv210-pinctrl.h diff --git a/arch/arm/boot/dts/s5pv210-smdkc110.dts b/arch/arm/boot/dts/samsung/s5pv210-smdkc110.dts similarity index 100% rename from arch/arm/boot/dts/s5pv210-smdkc110.dts rename to arch/arm/boot/dts/samsung/s5pv210-smdkc110.dts diff --git a/arch/arm/boot/dts/s5pv210-smdkv210.dts b/arch/arm/boot/dts/samsung/s5pv210-smdkv210.dts similarity index 95% rename from arch/arm/boot/dts/s5pv210-smdkv210.dts rename to arch/arm/boot/dts/samsung/s5pv210-smdkv210.dts index fbae768d65e272cd91e35540c079a477bc66f30f..6e26c67e0a26e6189a0442f0346323d4113a19a1 100644 --- a/arch/arm/boot/dts/s5pv210-smdkv210.dts +++ b/arch/arm/boot/dts/samsung/s5pv210-smdkv210.dts @@ -55,6 +55,14 @@ default-brightness-level = <6>; pinctrl-names = "default"; pinctrl-0 = <&pwm3_out>; + power-supply = <&dc5v_reg>; + }; + + dc5v_reg: regulator-0 { + compatible = "regulator-fixed"; + regulator-name = "DC5V"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; }; }; diff --git a/arch/arm/boot/dts/s5pv210-torbreck.dts b/arch/arm/boot/dts/samsung/s5pv210-torbreck.dts similarity index 100% rename from arch/arm/boot/dts/s5pv210-torbreck.dts rename to arch/arm/boot/dts/samsung/s5pv210-torbreck.dts diff --git a/arch/arm/boot/dts/s5pv210.dtsi b/arch/arm/boot/dts/samsung/s5pv210.dtsi similarity index 98% rename from arch/arm/boot/dts/s5pv210.dtsi rename to arch/arm/boot/dts/samsung/s5pv210.dtsi index 1a9e4a96b2ff7d4dcce03be08c886baa39234361..f7de5b5f2f383794509048c60cb19dcd9bb070b5 100644 --- a/arch/arm/boot/dts/s5pv210.dtsi +++ b/arch/arm/boot/dts/samsung/s5pv210.dtsi @@ -8,7 +8,7 @@ * Tomasz Figa * * Samsung's S5PV210 SoC device nodes are listed in this file. S5PV210 - * based board files can include this file and provide values for board specfic + * based board files can include this file and provide values for board specific * bindings. * * Note: This file does not include device nodes for all the controllers in @@ -401,7 +401,7 @@ status = "disabled"; }; - hsotg: hsotg@ec000000 { + hsotg: usb@ec000000 { compatible = "samsung,s3c6400-hsotg"; reg = <0xec000000 0x20000>; interrupt-parent = <&vic1>; @@ -452,8 +452,8 @@ reg = <0xf1700000 0x10000>; interrupt-parent = <&vic2>; interrupts = <14>; - clocks = <&clocks DOUT_MFC>, <&clocks CLK_MFC>; - clock-names = "sclk_mfc", "mfc"; + clocks = <&clocks CLK_MFC>, <&clocks DOUT_MFC>; + clock-names = "mfc", "sclk_mfc"; }; vic0: interrupt-controller@f2000000 { @@ -547,10 +547,8 @@ status = "disabled"; }; - camera: camera { - compatible = "samsung,fimc", "simple-bus"; - pinctrl-names = "default"; - pinctrl-0 = <>; + camera: camera@fa600000 { + compatible = "samsung,fimc"; clocks = <&clocks SCLK_CAM0>, <&clocks SCLK_CAM1>; clock-names = "sclk_cam0", "sclk_cam1"; #address-cells = <1>; diff --git a/arch/arm/boot/dts/sigmastar/Makefile b/arch/arm/boot/dts/sigmastar/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..b07eaf5d8add917ccfd6d48f78b17a428e0317e8 --- /dev/null +++ b/arch/arm/boot/dts/sigmastar/Makefile @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: GPL-2.0 +dtb-$(CONFIG_ARCH_MSTARV7) += \ + mstar-infinity-msc313-breadbee_crust.dtb \ + mstar-infinity2m-ssd202d-100ask-dongshanpione.dtb \ + mstar-infinity2m-ssd202d-miyoo-mini.dtb \ + mstar-infinity2m-ssd202d-wirelesstag-ido-sbc2d06-v1b-22w.dtb \ + mstar-infinity2m-ssd202d-ssd201htv2.dtb \ + mstar-infinity2m-ssd202d-unitv2.dtb \ + mstar-infinity3-msc313e-breadbee.dtb \ + mstar-mercury5-ssc8336n-midrived08.dtb diff --git a/arch/arm/boot/dts/mstar-infinity-breadbee-common.dtsi b/arch/arm/boot/dts/sigmastar/mstar-infinity-breadbee-common.dtsi similarity index 100% rename from arch/arm/boot/dts/mstar-infinity-breadbee-common.dtsi rename to arch/arm/boot/dts/sigmastar/mstar-infinity-breadbee-common.dtsi diff --git a/arch/arm/boot/dts/mstar-infinity-msc313-breadbee_crust.dts b/arch/arm/boot/dts/sigmastar/mstar-infinity-msc313-breadbee_crust.dts similarity index 100% rename from arch/arm/boot/dts/mstar-infinity-msc313-breadbee_crust.dts rename to arch/arm/boot/dts/sigmastar/mstar-infinity-msc313-breadbee_crust.dts diff --git a/arch/arm/boot/dts/mstar-infinity-msc313.dtsi b/arch/arm/boot/dts/sigmastar/mstar-infinity-msc313.dtsi similarity index 100% rename from arch/arm/boot/dts/mstar-infinity-msc313.dtsi rename to arch/arm/boot/dts/sigmastar/mstar-infinity-msc313.dtsi diff --git a/arch/arm/boot/dts/mstar-infinity.dtsi b/arch/arm/boot/dts/sigmastar/mstar-infinity.dtsi similarity index 100% rename from arch/arm/boot/dts/mstar-infinity.dtsi rename to arch/arm/boot/dts/sigmastar/mstar-infinity.dtsi diff --git a/arch/arm/boot/dts/mstar-infinity2m-ssd201-som2d01.dtsi b/arch/arm/boot/dts/sigmastar/mstar-infinity2m-ssd201-som2d01.dtsi similarity index 100% rename from arch/arm/boot/dts/mstar-infinity2m-ssd201-som2d01.dtsi rename to arch/arm/boot/dts/sigmastar/mstar-infinity2m-ssd201-som2d01.dtsi diff --git a/arch/arm/boot/dts/mstar-infinity2m-ssd202d-100ask-dongshanpione.dts b/arch/arm/boot/dts/sigmastar/mstar-infinity2m-ssd202d-100ask-dongshanpione.dts similarity index 100% rename from arch/arm/boot/dts/mstar-infinity2m-ssd202d-100ask-dongshanpione.dts rename to arch/arm/boot/dts/sigmastar/mstar-infinity2m-ssd202d-100ask-dongshanpione.dts diff --git a/arch/arm/boot/dts/mstar-infinity2m-ssd202d-miyoo-mini.dts b/arch/arm/boot/dts/sigmastar/mstar-infinity2m-ssd202d-miyoo-mini.dts similarity index 100% rename from arch/arm/boot/dts/mstar-infinity2m-ssd202d-miyoo-mini.dts rename to arch/arm/boot/dts/sigmastar/mstar-infinity2m-ssd202d-miyoo-mini.dts diff --git a/arch/arm/boot/dts/mstar-infinity2m-ssd202d-ssd201htv2.dts b/arch/arm/boot/dts/sigmastar/mstar-infinity2m-ssd202d-ssd201htv2.dts similarity index 100% rename from arch/arm/boot/dts/mstar-infinity2m-ssd202d-ssd201htv2.dts rename to arch/arm/boot/dts/sigmastar/mstar-infinity2m-ssd202d-ssd201htv2.dts diff --git a/arch/arm/boot/dts/mstar-infinity2m-ssd202d-unitv2.dts b/arch/arm/boot/dts/sigmastar/mstar-infinity2m-ssd202d-unitv2.dts similarity index 100% rename from arch/arm/boot/dts/mstar-infinity2m-ssd202d-unitv2.dts rename to arch/arm/boot/dts/sigmastar/mstar-infinity2m-ssd202d-unitv2.dts diff --git a/arch/arm/boot/dts/mstar-infinity2m-ssd202d-wirelesstag-ido-sbc2d06-v1b-22w.dts b/arch/arm/boot/dts/sigmastar/mstar-infinity2m-ssd202d-wirelesstag-ido-sbc2d06-v1b-22w.dts similarity index 100% rename from arch/arm/boot/dts/mstar-infinity2m-ssd202d-wirelesstag-ido-sbc2d06-v1b-22w.dts rename to arch/arm/boot/dts/sigmastar/mstar-infinity2m-ssd202d-wirelesstag-ido-sbc2d06-v1b-22w.dts diff --git a/arch/arm/boot/dts/mstar-infinity2m-ssd202d-wirelesstag-ido-som2d01.dtsi b/arch/arm/boot/dts/sigmastar/mstar-infinity2m-ssd202d-wirelesstag-ido-som2d01.dtsi similarity index 100% rename from arch/arm/boot/dts/mstar-infinity2m-ssd202d-wirelesstag-ido-som2d01.dtsi rename to arch/arm/boot/dts/sigmastar/mstar-infinity2m-ssd202d-wirelesstag-ido-som2d01.dtsi diff --git a/arch/arm/boot/dts/mstar-infinity2m-ssd202d.dtsi b/arch/arm/boot/dts/sigmastar/mstar-infinity2m-ssd202d.dtsi similarity index 100% rename from arch/arm/boot/dts/mstar-infinity2m-ssd202d.dtsi rename to arch/arm/boot/dts/sigmastar/mstar-infinity2m-ssd202d.dtsi diff --git a/arch/arm/boot/dts/mstar-infinity2m-ssd20xd.dtsi b/arch/arm/boot/dts/sigmastar/mstar-infinity2m-ssd20xd.dtsi similarity index 100% rename from arch/arm/boot/dts/mstar-infinity2m-ssd20xd.dtsi rename to arch/arm/boot/dts/sigmastar/mstar-infinity2m-ssd20xd.dtsi diff --git a/arch/arm/boot/dts/mstar-infinity2m.dtsi b/arch/arm/boot/dts/sigmastar/mstar-infinity2m.dtsi similarity index 100% rename from arch/arm/boot/dts/mstar-infinity2m.dtsi rename to arch/arm/boot/dts/sigmastar/mstar-infinity2m.dtsi diff --git a/arch/arm/boot/dts/mstar-infinity3-msc313e-breadbee.dts b/arch/arm/boot/dts/sigmastar/mstar-infinity3-msc313e-breadbee.dts similarity index 100% rename from arch/arm/boot/dts/mstar-infinity3-msc313e-breadbee.dts rename to arch/arm/boot/dts/sigmastar/mstar-infinity3-msc313e-breadbee.dts diff --git a/arch/arm/boot/dts/mstar-infinity3-msc313e.dtsi b/arch/arm/boot/dts/sigmastar/mstar-infinity3-msc313e.dtsi similarity index 100% rename from arch/arm/boot/dts/mstar-infinity3-msc313e.dtsi rename to arch/arm/boot/dts/sigmastar/mstar-infinity3-msc313e.dtsi diff --git a/arch/arm/boot/dts/mstar-infinity3.dtsi b/arch/arm/boot/dts/sigmastar/mstar-infinity3.dtsi similarity index 100% rename from arch/arm/boot/dts/mstar-infinity3.dtsi rename to arch/arm/boot/dts/sigmastar/mstar-infinity3.dtsi diff --git a/arch/arm/boot/dts/mstar-mercury5-ssc8336n-midrived08.dts b/arch/arm/boot/dts/sigmastar/mstar-mercury5-ssc8336n-midrived08.dts similarity index 100% rename from arch/arm/boot/dts/mstar-mercury5-ssc8336n-midrived08.dts rename to arch/arm/boot/dts/sigmastar/mstar-mercury5-ssc8336n-midrived08.dts diff --git a/arch/arm/boot/dts/mstar-mercury5-ssc8336n.dtsi b/arch/arm/boot/dts/sigmastar/mstar-mercury5-ssc8336n.dtsi similarity index 100% rename from arch/arm/boot/dts/mstar-mercury5-ssc8336n.dtsi rename to arch/arm/boot/dts/sigmastar/mstar-mercury5-ssc8336n.dtsi diff --git a/arch/arm/boot/dts/mstar-mercury5.dtsi b/arch/arm/boot/dts/sigmastar/mstar-mercury5.dtsi similarity index 100% rename from arch/arm/boot/dts/mstar-mercury5.dtsi rename to arch/arm/boot/dts/sigmastar/mstar-mercury5.dtsi diff --git a/arch/arm/boot/dts/mstar-v7.dtsi b/arch/arm/boot/dts/sigmastar/mstar-v7.dtsi similarity index 100% rename from arch/arm/boot/dts/mstar-v7.dtsi rename to arch/arm/boot/dts/sigmastar/mstar-v7.dtsi diff --git a/arch/arm/boot/dts/socionext/Makefile b/arch/arm/boot/dts/socionext/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..dab4275f6bd6f30ca725e49b26dd0e69ce090255 --- /dev/null +++ b/arch/arm/boot/dts/socionext/Makefile @@ -0,0 +1,13 @@ +# SPDX-License-Identifier: GPL-2.0 +dtb-$(CONFIG_ARCH_MILBEAUT) += milbeaut-m10v-evb.dtb +dtb-$(CONFIG_ARCH_UNIPHIER) += \ + uniphier-ld4-ref.dtb \ + uniphier-ld6b-ref.dtb \ + uniphier-pro4-ace.dtb \ + uniphier-pro4-ref.dtb \ + uniphier-pro4-sanji.dtb \ + uniphier-pro5-epcore.dtb \ + uniphier-pro5-proex.dtb \ + uniphier-pxs2-gentil.dtb \ + uniphier-pxs2-vodka.dtb \ + uniphier-sld8-ref.dtb diff --git a/arch/arm/boot/dts/milbeaut-m10v-evb.dts b/arch/arm/boot/dts/socionext/milbeaut-m10v-evb.dts similarity index 100% rename from arch/arm/boot/dts/milbeaut-m10v-evb.dts rename to arch/arm/boot/dts/socionext/milbeaut-m10v-evb.dts diff --git a/arch/arm/boot/dts/milbeaut-m10v.dtsi b/arch/arm/boot/dts/socionext/milbeaut-m10v.dtsi similarity index 100% rename from arch/arm/boot/dts/milbeaut-m10v.dtsi rename to arch/arm/boot/dts/socionext/milbeaut-m10v.dtsi diff --git a/arch/arm/boot/dts/uniphier-ld4-ref.dts b/arch/arm/boot/dts/socionext/uniphier-ld4-ref.dts similarity index 100% rename from arch/arm/boot/dts/uniphier-ld4-ref.dts rename to arch/arm/boot/dts/socionext/uniphier-ld4-ref.dts diff --git a/arch/arm/boot/dts/uniphier-ld4.dtsi b/arch/arm/boot/dts/socionext/uniphier-ld4.dtsi similarity index 100% rename from arch/arm/boot/dts/uniphier-ld4.dtsi rename to arch/arm/boot/dts/socionext/uniphier-ld4.dtsi diff --git a/arch/arm/boot/dts/uniphier-ld6b-ref.dts b/arch/arm/boot/dts/socionext/uniphier-ld6b-ref.dts similarity index 100% rename from arch/arm/boot/dts/uniphier-ld6b-ref.dts rename to arch/arm/boot/dts/socionext/uniphier-ld6b-ref.dts diff --git a/arch/arm/boot/dts/uniphier-ld6b.dtsi b/arch/arm/boot/dts/socionext/uniphier-ld6b.dtsi similarity index 100% rename from arch/arm/boot/dts/uniphier-ld6b.dtsi rename to arch/arm/boot/dts/socionext/uniphier-ld6b.dtsi diff --git a/arch/arm/boot/dts/uniphier-pinctrl.dtsi b/arch/arm/boot/dts/socionext/uniphier-pinctrl.dtsi similarity index 100% rename from arch/arm/boot/dts/uniphier-pinctrl.dtsi rename to arch/arm/boot/dts/socionext/uniphier-pinctrl.dtsi diff --git a/arch/arm/boot/dts/uniphier-pro4-ace.dts b/arch/arm/boot/dts/socionext/uniphier-pro4-ace.dts similarity index 100% rename from arch/arm/boot/dts/uniphier-pro4-ace.dts rename to arch/arm/boot/dts/socionext/uniphier-pro4-ace.dts diff --git a/arch/arm/boot/dts/uniphier-pro4-ref.dts b/arch/arm/boot/dts/socionext/uniphier-pro4-ref.dts similarity index 100% rename from arch/arm/boot/dts/uniphier-pro4-ref.dts rename to arch/arm/boot/dts/socionext/uniphier-pro4-ref.dts diff --git a/arch/arm/boot/dts/uniphier-pro4-sanji.dts b/arch/arm/boot/dts/socionext/uniphier-pro4-sanji.dts similarity index 100% rename from arch/arm/boot/dts/uniphier-pro4-sanji.dts rename to arch/arm/boot/dts/socionext/uniphier-pro4-sanji.dts diff --git a/arch/arm/boot/dts/uniphier-pro4.dtsi b/arch/arm/boot/dts/socionext/uniphier-pro4.dtsi similarity index 100% rename from arch/arm/boot/dts/uniphier-pro4.dtsi rename to arch/arm/boot/dts/socionext/uniphier-pro4.dtsi diff --git a/arch/arm/boot/dts/uniphier-pro5-epcore.dts b/arch/arm/boot/dts/socionext/uniphier-pro5-epcore.dts similarity index 100% rename from arch/arm/boot/dts/uniphier-pro5-epcore.dts rename to arch/arm/boot/dts/socionext/uniphier-pro5-epcore.dts diff --git a/arch/arm/boot/dts/uniphier-pro5-proex.dts b/arch/arm/boot/dts/socionext/uniphier-pro5-proex.dts similarity index 100% rename from arch/arm/boot/dts/uniphier-pro5-proex.dts rename to arch/arm/boot/dts/socionext/uniphier-pro5-proex.dts diff --git a/arch/arm/boot/dts/uniphier-pro5.dtsi b/arch/arm/boot/dts/socionext/uniphier-pro5.dtsi similarity index 100% rename from arch/arm/boot/dts/uniphier-pro5.dtsi rename to arch/arm/boot/dts/socionext/uniphier-pro5.dtsi diff --git a/arch/arm/boot/dts/uniphier-pxs2-gentil.dts b/arch/arm/boot/dts/socionext/uniphier-pxs2-gentil.dts similarity index 100% rename from arch/arm/boot/dts/uniphier-pxs2-gentil.dts rename to arch/arm/boot/dts/socionext/uniphier-pxs2-gentil.dts diff --git a/arch/arm/boot/dts/uniphier-pxs2-vodka.dts b/arch/arm/boot/dts/socionext/uniphier-pxs2-vodka.dts similarity index 100% rename from arch/arm/boot/dts/uniphier-pxs2-vodka.dts rename to arch/arm/boot/dts/socionext/uniphier-pxs2-vodka.dts diff --git a/arch/arm/boot/dts/uniphier-pxs2.dtsi b/arch/arm/boot/dts/socionext/uniphier-pxs2.dtsi similarity index 100% rename from arch/arm/boot/dts/uniphier-pxs2.dtsi rename to arch/arm/boot/dts/socionext/uniphier-pxs2.dtsi diff --git a/arch/arm/boot/dts/uniphier-ref-daughter.dtsi b/arch/arm/boot/dts/socionext/uniphier-ref-daughter.dtsi similarity index 100% rename from arch/arm/boot/dts/uniphier-ref-daughter.dtsi rename to arch/arm/boot/dts/socionext/uniphier-ref-daughter.dtsi diff --git a/arch/arm/boot/dts/uniphier-sld8-ref.dts b/arch/arm/boot/dts/socionext/uniphier-sld8-ref.dts similarity index 100% rename from arch/arm/boot/dts/uniphier-sld8-ref.dts rename to arch/arm/boot/dts/socionext/uniphier-sld8-ref.dts diff --git a/arch/arm/boot/dts/uniphier-sld8.dtsi b/arch/arm/boot/dts/socionext/uniphier-sld8.dtsi similarity index 100% rename from arch/arm/boot/dts/uniphier-sld8.dtsi rename to arch/arm/boot/dts/socionext/uniphier-sld8.dtsi diff --git a/arch/arm/boot/dts/uniphier-support-card.dtsi b/arch/arm/boot/dts/socionext/uniphier-support-card.dtsi similarity index 100% rename from arch/arm/boot/dts/uniphier-support-card.dtsi rename to arch/arm/boot/dts/socionext/uniphier-support-card.dtsi diff --git a/arch/arm/boot/dts/st/Makefile b/arch/arm/boot/dts/st/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..b3e9d29390e38f55064ac089ac17c5b6c7dfa23b --- /dev/null +++ b/arch/arm/boot/dts/st/Makefile @@ -0,0 +1,74 @@ +# SPDX-License-Identifier: GPL-2.0 +dtb-$(CONFIG_ARCH_NOMADIK) += \ + ste-nomadik-s8815.dtb \ + ste-nomadik-nhk15.dtb +dtb-$(CONFIG_ARCH_SPEAR13XX) += \ + spear1310-evb.dtb \ + spear1340-evb.dtb +dtb-$(CONFIG_ARCH_SPEAR3XX) += \ + spear300-evb.dtb \ + spear310-evb.dtb \ + spear320-evb.dtb \ + spear320-hmi.dtb +dtb-$(CONFIG_ARCH_SPEAR6XX) += \ + spear600-evb.dtb +dtb-$(CONFIG_ARCH_STI) += \ + stih407-b2120.dtb \ + stih410-b2120.dtb \ + stih410-b2260.dtb \ + stih418-b2199.dtb \ + stih418-b2264.dtb +dtb-$(CONFIG_ARCH_STM32) += \ + stm32f429-disco.dtb \ + stm32f469-disco.dtb \ + stm32f746-disco.dtb \ + stm32f769-disco.dtb \ + stm32429i-eval.dtb \ + stm32746g-eval.dtb \ + stm32h743i-eval.dtb \ + stm32h743i-disco.dtb \ + stm32h750i-art-pi.dtb \ + stm32mp135f-dk.dtb \ + stm32mp151a-prtt1a.dtb \ + stm32mp151a-prtt1c.dtb \ + stm32mp151a-prtt1s.dtb \ + stm32mp151a-dhcor-testbench.dtb \ + stm32mp153c-dhcom-drc02.dtb \ + stm32mp153c-dhcor-drc-compact.dtb \ + stm32mp157a-avenger96.dtb \ + stm32mp157a-dhcor-avenger96.dtb \ + stm32mp157a-dk1.dtb \ + stm32mp157a-dk1-scmi.dtb \ + stm32mp157a-iot-box.dtb \ + stm32mp157a-microgea-stm32mp1-microdev2.0.dtb \ + stm32mp157a-microgea-stm32mp1-microdev2.0-of7.dtb \ + stm32mp157a-icore-stm32mp1-ctouch2.dtb \ + stm32mp157a-icore-stm32mp1-ctouch2-of10.dtb \ + stm32mp157a-icore-stm32mp1-edimm2.2.dtb \ + stm32mp157a-stinger96.dtb \ + stm32mp157c-dhcom-pdk2.dtb \ + stm32mp157c-dhcom-picoitx.dtb \ + stm32mp157c-dk2.dtb \ + stm32mp157c-dk2-scmi.dtb \ + stm32mp157c-ed1.dtb \ + stm32mp157c-ed1-scmi.dtb \ + stm32mp157c-emsbc-argon.dtb \ + stm32mp157c-ev1.dtb \ + stm32mp157c-ev1-scmi.dtb \ + stm32mp157c-lxa-mc1.dtb \ + stm32mp157c-odyssey.dtb \ + stm32mp157c-phycore-stm32mp1-3.dtb +dtb-$(CONFIG_ARCH_U8500) += \ + ste-snowball.dtb \ + ste-hrefprev60-stuib.dtb \ + ste-hrefprev60-tvk.dtb \ + ste-hrefv60plus-stuib.dtb \ + ste-hrefv60plus-tvk.dtb \ + ste-href520-tvk.dtb \ + ste-ux500-samsung-golden.dtb \ + ste-ux500-samsung-janice.dtb \ + ste-ux500-samsung-gavini.dtb \ + ste-ux500-samsung-codina.dtb \ + ste-ux500-samsung-codina-tmo.dtb \ + ste-ux500-samsung-skomer.dtb \ + ste-ux500-samsung-kyle.dtb diff --git a/arch/arm/boot/dts/spear1310-evb.dts b/arch/arm/boot/dts/st/spear1310-evb.dts similarity index 100% rename from arch/arm/boot/dts/spear1310-evb.dts rename to arch/arm/boot/dts/st/spear1310-evb.dts diff --git a/arch/arm/boot/dts/spear1310.dtsi b/arch/arm/boot/dts/st/spear1310.dtsi similarity index 99% rename from arch/arm/boot/dts/spear1310.dtsi rename to arch/arm/boot/dts/st/spear1310.dtsi index 2f746a9428a76de35c20939533af380cdc0a438b..ba827d60bf075367862eab0b21471e72a0f1b558 100644 --- a/arch/arm/boot/dts/spear1310.dtsi +++ b/arch/arm/boot/dts/st/spear1310.dtsi @@ -11,7 +11,7 @@ compatible = "st,spear1310"; ahb { - spics: spics@e0700000{ + spics: spics@e0700000 { compatible = "st,spear-spics-gpio"; reg = <0xe0700000 0x1000>; st-spics,peripcfg-reg = <0x3b0>; diff --git a/arch/arm/boot/dts/spear1340-evb.dts b/arch/arm/boot/dts/st/spear1340-evb.dts similarity index 100% rename from arch/arm/boot/dts/spear1340-evb.dts rename to arch/arm/boot/dts/st/spear1340-evb.dts diff --git a/arch/arm/boot/dts/spear1340.dtsi b/arch/arm/boot/dts/st/spear1340.dtsi similarity index 99% rename from arch/arm/boot/dts/spear1340.dtsi rename to arch/arm/boot/dts/st/spear1340.dtsi index 818886e117138dcdfbcfa2c6ad4bf7b66af2bac3..d54e10629a7d76eaa6ec813198364fec63d0619a 100644 --- a/arch/arm/boot/dts/spear1340.dtsi +++ b/arch/arm/boot/dts/st/spear1340.dtsi @@ -12,7 +12,7 @@ ahb { - spics: spics@e0700000{ + spics: spics@e0700000 { compatible = "st,spear-spics-gpio"; reg = <0xe0700000 0x1000>; st-spics,peripcfg-reg = <0x42c>; diff --git a/arch/arm/boot/dts/spear13xx.dtsi b/arch/arm/boot/dts/st/spear13xx.dtsi similarity index 100% rename from arch/arm/boot/dts/spear13xx.dtsi rename to arch/arm/boot/dts/st/spear13xx.dtsi diff --git a/arch/arm/boot/dts/spear300-evb.dts b/arch/arm/boot/dts/st/spear300-evb.dts similarity index 100% rename from arch/arm/boot/dts/spear300-evb.dts rename to arch/arm/boot/dts/st/spear300-evb.dts diff --git a/arch/arm/boot/dts/spear300.dtsi b/arch/arm/boot/dts/st/spear300.dtsi similarity index 100% rename from arch/arm/boot/dts/spear300.dtsi rename to arch/arm/boot/dts/st/spear300.dtsi diff --git a/arch/arm/boot/dts/spear310-evb.dts b/arch/arm/boot/dts/st/spear310-evb.dts similarity index 100% rename from arch/arm/boot/dts/spear310-evb.dts rename to arch/arm/boot/dts/st/spear310-evb.dts diff --git a/arch/arm/boot/dts/spear310.dtsi b/arch/arm/boot/dts/st/spear310.dtsi similarity index 100% rename from arch/arm/boot/dts/spear310.dtsi rename to arch/arm/boot/dts/st/spear310.dtsi diff --git a/arch/arm/boot/dts/spear320-evb.dts b/arch/arm/boot/dts/st/spear320-evb.dts similarity index 100% rename from arch/arm/boot/dts/spear320-evb.dts rename to arch/arm/boot/dts/st/spear320-evb.dts diff --git a/arch/arm/boot/dts/spear320-hmi.dts b/arch/arm/boot/dts/st/spear320-hmi.dts similarity index 100% rename from arch/arm/boot/dts/spear320-hmi.dts rename to arch/arm/boot/dts/st/spear320-hmi.dts diff --git a/arch/arm/boot/dts/spear320.dtsi b/arch/arm/boot/dts/st/spear320.dtsi similarity index 100% rename from arch/arm/boot/dts/spear320.dtsi rename to arch/arm/boot/dts/st/spear320.dtsi diff --git a/arch/arm/boot/dts/spear320s.dtsi b/arch/arm/boot/dts/st/spear320s.dtsi similarity index 100% rename from arch/arm/boot/dts/spear320s.dtsi rename to arch/arm/boot/dts/st/spear320s.dtsi diff --git a/arch/arm/boot/dts/spear3xx.dtsi b/arch/arm/boot/dts/st/spear3xx.dtsi similarity index 100% rename from arch/arm/boot/dts/spear3xx.dtsi rename to arch/arm/boot/dts/st/spear3xx.dtsi diff --git a/arch/arm/boot/dts/spear600-evb.dts b/arch/arm/boot/dts/st/spear600-evb.dts similarity index 100% rename from arch/arm/boot/dts/spear600-evb.dts rename to arch/arm/boot/dts/st/spear600-evb.dts diff --git a/arch/arm/boot/dts/spear600.dtsi b/arch/arm/boot/dts/st/spear600.dtsi similarity index 100% rename from arch/arm/boot/dts/spear600.dtsi rename to arch/arm/boot/dts/st/spear600.dtsi diff --git a/arch/arm/boot/dts/st-pincfg.h b/arch/arm/boot/dts/st/st-pincfg.h similarity index 100% rename from arch/arm/boot/dts/st-pincfg.h rename to arch/arm/boot/dts/st/st-pincfg.h diff --git a/arch/arm/boot/dts/ste-ab8500.dtsi b/arch/arm/boot/dts/st/ste-ab8500.dtsi similarity index 100% rename from arch/arm/boot/dts/ste-ab8500.dtsi rename to arch/arm/boot/dts/st/ste-ab8500.dtsi diff --git a/arch/arm/boot/dts/ste-ab8505.dtsi b/arch/arm/boot/dts/st/ste-ab8505.dtsi similarity index 100% rename from arch/arm/boot/dts/ste-ab8505.dtsi rename to arch/arm/boot/dts/st/ste-ab8505.dtsi diff --git a/arch/arm/boot/dts/ste-db8500.dtsi b/arch/arm/boot/dts/st/ste-db8500.dtsi similarity index 100% rename from arch/arm/boot/dts/ste-db8500.dtsi rename to arch/arm/boot/dts/st/ste-db8500.dtsi diff --git a/arch/arm/boot/dts/ste-db8520.dtsi b/arch/arm/boot/dts/st/ste-db8520.dtsi similarity index 100% rename from arch/arm/boot/dts/ste-db8520.dtsi rename to arch/arm/boot/dts/st/ste-db8520.dtsi diff --git a/arch/arm/boot/dts/ste-db9500.dtsi b/arch/arm/boot/dts/st/ste-db9500.dtsi similarity index 100% rename from arch/arm/boot/dts/ste-db9500.dtsi rename to arch/arm/boot/dts/st/ste-db9500.dtsi diff --git a/arch/arm/boot/dts/ste-dbx5x0-pinctrl.dtsi b/arch/arm/boot/dts/st/ste-dbx5x0-pinctrl.dtsi similarity index 100% rename from arch/arm/boot/dts/ste-dbx5x0-pinctrl.dtsi rename to arch/arm/boot/dts/st/ste-dbx5x0-pinctrl.dtsi diff --git a/arch/arm/boot/dts/ste-dbx5x0.dtsi b/arch/arm/boot/dts/st/ste-dbx5x0.dtsi similarity index 93% rename from arch/arm/boot/dts/ste-dbx5x0.dtsi rename to arch/arm/boot/dts/st/ste-dbx5x0.dtsi index fead7afd551714b1cc14ec3132d5927f0de5ffcb..d5d88771ef976f8069b828c708a9975308822458 100644 --- a/arch/arm/boot/dts/ste-dbx5x0.dtsi +++ b/arch/arm/boot/dts/st/ste-dbx5x0.dtsi @@ -110,6 +110,74 @@ interrupt-parent = <&intc>; ranges; + /* + * 640KB ESRAM (embedded static random access memory), divided + * into 5 banks of 128 KB each. This is a fast memory usually + * used by different accelerators. We group these according to + * their power domains: ESRAM0 (always on) ESRAM 1+2 and + * ESRAM 3+4. + */ + sram@40000000 { + /* The first (always on) ESRAM 0, 128 KB */ + compatible = "mmio-sram"; + reg = <0x40000000 0x20000>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0x40000000 0x20000>; + + sram@0 { + compatible = "stericsson,u8500-esram"; + reg = <0x0 0x10000>; + pool; + }; + lcpa: sram@10000 { + /* + * This eSRAM is used by the DMA40 DMA controller + * for Logical Channel Paramers (LCP), the address + * where these parameters are stored is called "LCPA". + * This is addressed directly by the driver so no + * pool is used. + */ + compatible = "stericsson,u8500-esram"; + label = "DMA40-LCPA"; + reg = <0x10000 0x800>; + }; + sram@10800 { + compatible = "stericsson,u8500-esram"; + reg = <0x10800 0xf800>; + pool; + }; + }; + sram@40020000 { + /* ESRAM 1+2, 256 KB */ + compatible = "mmio-sram"; + reg = <0x40020000 0x40000>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0x40020000 0x40000>; + }; + sram@40060000 { + /* ESRAM 3+4, 256 KB */ + compatible = "mmio-sram"; + reg = <0x40060000 0x40000>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0x40060000 0x40000>; + + lcla: sram@20000 { + /* + * This eSRAM is used by the DMA40 DMA controller + * for Logical Channel Logical Addresses (LCLA), the address + * where these parameters are stored is called "LCLA". + * This is addressed directly by the driver so no + * pool is used. + */ + compatible = "stericsson,u8500-esram"; + label = "DMA40-LCLA"; + reg = <0x20000 0x2000>; + }; + }; + ptm@801ae000 { compatible = "arm,coresight-etm3x", "arm,primecell"; reg = <0x801ae000 0x1000>; @@ -536,9 +604,10 @@ dma: dma-controller@801C0000 { compatible = "stericsson,db8500-dma40", "stericsson,dma40"; - reg = <0x801C0000 0x1000 0x40010000 0x800>; - reg-names = "base", "lcpa"; + reg = <0x801C0000 0x1000>; + reg-names = "base"; interrupts = ; + sram = <&lcpa>, <&lcla>; #dma-cells = <3>; memcpy-channels = <56 57 58 59 60>; @@ -852,7 +921,7 @@ status = "disabled"; }; - serial0: uart@80120000 { + serial0: serial@80120000 { compatible = "arm,pl011", "arm,primecell"; reg = <0x80120000 0x1000>; interrupts = ; @@ -868,7 +937,7 @@ status = "disabled"; }; - serial1: uart@80121000 { + serial1: serial@80121000 { compatible = "arm,pl011", "arm,primecell"; reg = <0x80121000 0x1000>; interrupts = ; @@ -884,7 +953,7 @@ status = "disabled"; }; - serial2: uart@80007000 { + serial2: serial@80007000 { compatible = "arm,pl011", "arm,primecell"; reg = <0x80007000 0x1000>; interrupts = ; diff --git a/arch/arm/boot/dts/ste-href-ab8500.dtsi b/arch/arm/boot/dts/st/ste-href-ab8500.dtsi similarity index 95% rename from arch/arm/boot/dts/ste-href-ab8500.dtsi rename to arch/arm/boot/dts/st/ste-href-ab8500.dtsi index 9fa024900d53436cb95e93966b314401aa5ff6a9..e1de9d389a01bfb0618790f462c0f87781c2444d 100644 --- a/arch/arm/boot/dts/ste-href-ab8500.dtsi +++ b/arch/arm/boot/dts/st/ste-href-ab8500.dtsi @@ -418,6 +418,24 @@ }; }; }; + /* + * Charging is not working on the HREF unless an actual battery is + * mounted, most HREFs have a DC cable in to the "battery power" + * which means this will only be cofusing. So do not enable charging + * of the HREFs. + */ + ab8500_fg { + status = "disabled"; + }; + ab8500_btemp { + status = "disabled"; + }; + ab8500_charger { + status = "disabled"; + }; + ab8500_chargalg { + status = "disabled"; + }; }; }; }; diff --git a/arch/arm/boot/dts/ste-href-family-pinctrl.dtsi b/arch/arm/boot/dts/st/ste-href-family-pinctrl.dtsi similarity index 100% rename from arch/arm/boot/dts/ste-href-family-pinctrl.dtsi rename to arch/arm/boot/dts/st/ste-href-family-pinctrl.dtsi diff --git a/arch/arm/boot/dts/ste-href-stuib.dtsi b/arch/arm/boot/dts/st/ste-href-stuib.dtsi similarity index 98% rename from arch/arm/boot/dts/ste-href-stuib.dtsi rename to arch/arm/boot/dts/st/ste-href-stuib.dtsi index e32d0c36feb8f9ce1341a2efe84d6d43d4d9d978..79c2be36acae7e17fcfe4459feefc06843905711 100644 --- a/arch/arm/boot/dts/ste-href-stuib.dtsi +++ b/arch/arm/boot/dts/st/ste-href-stuib.dtsi @@ -30,12 +30,11 @@ soc { i2c@80004000 { - stmpe1601: stmpe1601@40 { + stmpe1601: port-expander@40 { compatible = "st,stmpe1601"; reg = <0x40>; interrupts = <26 IRQ_TYPE_EDGE_FALLING>; interrupt-parent = <&gpio6>; - interrupt-controller; vcc-supply = <&db8500_vsmps2_reg>; vio-supply = <&db8500_vsmps2_reg>; pinctrl-names = "default"; @@ -44,7 +43,7 @@ wakeup-source; st,autosleep-timeout = <1024>; - stmpe_keypad { + keyboard-controller { compatible = "st,stmpe-keypad"; debounce-interval = <64>; diff --git a/arch/arm/boot/dts/ste-href-tvk1281618-r2.dtsi b/arch/arm/boot/dts/st/ste-href-tvk1281618-r2.dtsi similarity index 100% rename from arch/arm/boot/dts/ste-href-tvk1281618-r2.dtsi rename to arch/arm/boot/dts/st/ste-href-tvk1281618-r2.dtsi diff --git a/arch/arm/boot/dts/ste-href-tvk1281618-r3.dtsi b/arch/arm/boot/dts/st/ste-href-tvk1281618-r3.dtsi similarity index 100% rename from arch/arm/boot/dts/ste-href-tvk1281618-r3.dtsi rename to arch/arm/boot/dts/st/ste-href-tvk1281618-r3.dtsi diff --git a/arch/arm/boot/dts/ste-href.dtsi b/arch/arm/boot/dts/st/ste-href.dtsi similarity index 99% rename from arch/arm/boot/dts/ste-href.dtsi rename to arch/arm/boot/dts/st/ste-href.dtsi index e716121a78cee094a7ee7d3524d47587661ec0f1..13b11dbeba1c1f87fe529fbfeb497af880808f55 100644 --- a/arch/arm/boot/dts/ste-href.dtsi +++ b/arch/arm/boot/dts/st/ste-href.dtsi @@ -45,7 +45,7 @@ }; soc { - uart@80120000 { + serial@80120000 { pinctrl-names = "default", "sleep"; pinctrl-0 = <&u0_a_1_default>; pinctrl-1 = <&u0_a_1_sleep>; @@ -53,13 +53,13 @@ }; /* This UART is unused and thus left disabled */ - uart@80121000 { + serial@80121000 { pinctrl-names = "default", "sleep"; pinctrl-0 = <&u1rxtx_a_1_default>; pinctrl-1 = <&u1rxtx_a_1_sleep>; }; - uart@80007000 { + serial@80007000 { pinctrl-names = "default", "sleep"; pinctrl-0 = <&u2rxtx_c_1_default>; pinctrl-1 = <&u2rxtx_c_1_sleep>; diff --git a/arch/arm/boot/dts/ste-href520-tvk.dts b/arch/arm/boot/dts/st/ste-href520-tvk.dts similarity index 100% rename from arch/arm/boot/dts/ste-href520-tvk.dts rename to arch/arm/boot/dts/st/ste-href520-tvk.dts diff --git a/arch/arm/boot/dts/ste-hrefprev60-stuib.dts b/arch/arm/boot/dts/st/ste-hrefprev60-stuib.dts similarity index 100% rename from arch/arm/boot/dts/ste-hrefprev60-stuib.dts rename to arch/arm/boot/dts/st/ste-hrefprev60-stuib.dts diff --git a/arch/arm/boot/dts/ste-hrefprev60-tvk.dts b/arch/arm/boot/dts/st/ste-hrefprev60-tvk.dts similarity index 100% rename from arch/arm/boot/dts/ste-hrefprev60-tvk.dts rename to arch/arm/boot/dts/st/ste-hrefprev60-tvk.dts diff --git a/arch/arm/boot/dts/ste-hrefprev60.dtsi b/arch/arm/boot/dts/st/ste-hrefprev60.dtsi similarity index 99% rename from arch/arm/boot/dts/ste-hrefprev60.dtsi rename to arch/arm/boot/dts/st/ste-hrefprev60.dtsi index 29b67abfc461af97f7a1e3b365e7035ba830802f..9859ee91a15ece7fbecc6c8f229b0ea9065632eb 100644 --- a/arch/arm/boot/dts/ste-hrefprev60.dtsi +++ b/arch/arm/boot/dts/st/ste-hrefprev60.dtsi @@ -17,7 +17,7 @@ soc { /* Enable UART1 on this board */ - uart@80121000 { + serial@80121000 { status = "okay"; }; diff --git a/arch/arm/boot/dts/ste-hrefv60plus-stuib.dts b/arch/arm/boot/dts/st/ste-hrefv60plus-stuib.dts similarity index 100% rename from arch/arm/boot/dts/ste-hrefv60plus-stuib.dts rename to arch/arm/boot/dts/st/ste-hrefv60plus-stuib.dts diff --git a/arch/arm/boot/dts/ste-hrefv60plus-tvk.dts b/arch/arm/boot/dts/st/ste-hrefv60plus-tvk.dts similarity index 100% rename from arch/arm/boot/dts/ste-hrefv60plus-tvk.dts rename to arch/arm/boot/dts/st/ste-hrefv60plus-tvk.dts diff --git a/arch/arm/boot/dts/ste-hrefv60plus.dtsi b/arch/arm/boot/dts/st/ste-hrefv60plus.dtsi similarity index 100% rename from arch/arm/boot/dts/ste-hrefv60plus.dtsi rename to arch/arm/boot/dts/st/ste-hrefv60plus.dtsi diff --git a/arch/arm/boot/dts/ste-nomadik-nhk15.dts b/arch/arm/boot/dts/st/ste-nomadik-nhk15.dts similarity index 95% rename from arch/arm/boot/dts/ste-nomadik-nhk15.dts rename to arch/arm/boot/dts/st/ste-nomadik-nhk15.dts index 4d741adc16cd9ac07fee4d72f74d9fa9c638087d..cdff33063d6f563e0043235cd9cb6427a6b1f677 100644 --- a/arch/arm/boot/dts/ste-nomadik-nhk15.dts +++ b/arch/arm/boot/dts/st/ste-nomadik-nhk15.dts @@ -99,17 +99,16 @@ pinctrl-names = "default"; reg = <0x1d>; }; - stmpe0: stmpe2401@43 { + stmpe0: port-expander@43 { compatible = "st,stmpe2401"; reg = <0x43>; reset-gpios = <&gpio2 13 GPIO_ACTIVE_LOW>; // GPIO77 interrupts = <12 IRQ_TYPE_EDGE_FALLING>; // GPIO76 interrupt-parent = <&gpio2>; - interrupt-controller; wakeup-source; pinctrl-names = "default"; pinctrl-0 = <&stmpe2401_1_nhk_mode>; - stmpe_gpio43: stmpe_gpio { + stmpe_gpio43: gpio { compatible = "st,stmpe-gpio"; gpio-controller; #gpio-cells = <2>; @@ -118,7 +117,7 @@ /* Some pins in alternate functions */ st,norequest-mask = <0xf0f002>; }; - stmpe_keypad { + keyboard-controller { compatible = "st,stmpe-keypad"; debounce-interval = <64>; st,scan-count = <8>; @@ -140,22 +139,21 @@ 0x03020067 // Up 0x0303006c>; // Down }; - stmpe0_pwm: stmpe_pwm { + stmpe0_pwm: pwm { compatible = "st,stmpe-pwm"; #pwm-cells = <2>; }; }; - stmpe1: stmpe2401@44 { + stmpe1: port-expander@44 { compatible = "st,stmpe2401"; reg = <0x44>; reset-gpios = <&gpio2 15 GPIO_ACTIVE_LOW>; // GPIO79 interrupts = <14 IRQ_TYPE_EDGE_FALLING>; // GPIO78 interrupt-parent = <&gpio2>; - interrupt-controller; wakeup-source; pinctrl-names = "default"; pinctrl-0 = <&stmpe2401_2_nhk_mode>; - stmpe_gpio44: stmpe_gpio { + stmpe_gpio44: gpio { compatible = "st,stmpe-gpio"; gpio-controller; #gpio-cells = <2>; @@ -165,7 +163,7 @@ * This will turn off SATA so that MMC/SD * can thrive */ - mmcsd-gpio { + mmcsd-hog { gpio-hog; gpios = <2 0x0>; output-low; @@ -190,7 +188,7 @@ }; /* Activate RX/TX and CTS/RTS on UART 0 */ - uart0: uart@101fd000 { + uart0: serial@101fd000 { pinctrl-names = "default"; pinctrl-0 = <&uart0_nhk_mode>; status = "okay"; diff --git a/arch/arm/boot/dts/ste-nomadik-pinctrl.dtsi b/arch/arm/boot/dts/st/ste-nomadik-pinctrl.dtsi similarity index 100% rename from arch/arm/boot/dts/ste-nomadik-pinctrl.dtsi rename to arch/arm/boot/dts/st/ste-nomadik-pinctrl.dtsi diff --git a/arch/arm/boot/dts/ste-nomadik-s8815.dts b/arch/arm/boot/dts/st/ste-nomadik-s8815.dts similarity index 99% rename from arch/arm/boot/dts/ste-nomadik-s8815.dts rename to arch/arm/boot/dts/st/ste-nomadik-s8815.dts index f16314ffbf4bd80ce3575b2836e5c59c9fec1885..c905c2643a120c4e9e4fbf474c4e69fe45fed2e9 100644 --- a/arch/arm/boot/dts/ste-nomadik-s8815.dts +++ b/arch/arm/boot/dts/st/ste-nomadik-s8815.dts @@ -133,7 +133,7 @@ amba { /* Activate RXTX on UART 0 */ - uart0: uart@101fd000 { + uart0: serial@101fd000 { pinctrl-names = "default"; pinctrl-0 = <&uart0_s8815_mode>; status = "okay"; diff --git a/arch/arm/boot/dts/ste-nomadik-stn8815.dtsi b/arch/arm/boot/dts/st/ste-nomadik-stn8815.dtsi similarity index 99% rename from arch/arm/boot/dts/ste-nomadik-stn8815.dtsi rename to arch/arm/boot/dts/st/ste-nomadik-stn8815.dtsi index 1815361fe73ce0806880c91e8153f51b8ff84e50..6816eef39d45040859c27383d2a657bd83e2683e 100644 --- a/arch/arm/boot/dts/ste-nomadik-stn8815.dtsi +++ b/arch/arm/boot/dts/st/ste-nomadik-stn8815.dtsi @@ -769,7 +769,7 @@ reg = <0x10140020 0x20>; }; - uart0: uart@101fd000 { + uart0: serial@101fd000 { compatible = "arm,pl011", "arm,primecell"; reg = <0x101fd000 0x1000>; interrupt-parent = <&vica>; @@ -782,7 +782,7 @@ dma-names = "rx", "tx"; }; - uart1: uart@101fb000 { + uart1: serial@101fb000 { compatible = "arm,pl011", "arm,primecell"; reg = <0x101fb000 0x1000>; interrupt-parent = <&vica>; @@ -796,7 +796,7 @@ dma-names = "rx", "tx"; }; - uart2: uart@101f2000 { + uart2: serial@101f2000 { compatible = "arm,pl011", "arm,primecell"; reg = <0x101f2000 0x1000>; interrupt-parent = <&vica>; diff --git a/arch/arm/boot/dts/ste-snowball.dts b/arch/arm/boot/dts/st/ste-snowball.dts similarity index 99% rename from arch/arm/boot/dts/ste-snowball.dts rename to arch/arm/boot/dts/st/ste-snowball.dts index e2f0cdacba7d1417fab287b0b019db80a9357d60..9a3d6546399d77804f182cfaa4b397692e7f6444 100644 --- a/arch/arm/boot/dts/ste-snowball.dts +++ b/arch/arm/boot/dts/st/ste-snowball.dts @@ -308,7 +308,7 @@ status = "okay"; }; - uart@80120000 { + serial@80120000 { pinctrl-names = "default", "sleep"; pinctrl-0 = <&u0_a_1_default>; pinctrl-1 = <&u0_a_1_sleep>; @@ -316,13 +316,13 @@ }; /* This UART is unused and thus left disabled */ - uart@80121000 { + serial@80121000 { pinctrl-names = "default", "sleep"; pinctrl-0 = <&u1rxtx_a_1_default>; pinctrl-1 = <&u1rxtx_a_1_sleep>; }; - uart@80007000 { + serial@80007000 { pinctrl-names = "default", "sleep"; pinctrl-0 = <&u2rxtx_c_1_default>; pinctrl-1 = <&u2rxtx_c_1_sleep>; diff --git a/arch/arm/boot/dts/ste-ux500-samsung-codina-tmo.dts b/arch/arm/boot/dts/st/ste-ux500-samsung-codina-tmo.dts similarity index 99% rename from arch/arm/boot/dts/ste-ux500-samsung-codina-tmo.dts rename to arch/arm/boot/dts/st/ste-ux500-samsung-codina-tmo.dts index e036393d5415c3e00bf7375c41c93d13e4fdfacd..463942ae755ecb728636c264606abb9b04092af8 100644 --- a/arch/arm/boot/dts/ste-ux500-samsung-codina-tmo.dts +++ b/arch/arm/boot/dts/st/ste-ux500-samsung-codina-tmo.dts @@ -369,7 +369,7 @@ }; /* GBF (Bluetooth) UART */ - uart@80120000 { + serial@80120000 { pinctrl-names = "default", "sleep"; pinctrl-0 = <&u0_a_1_default>; pinctrl-1 = <&u0_a_1_sleep>; @@ -393,7 +393,7 @@ }; /* GPS UART */ - uart@80121000 { + serial@80121000 { status = "okay"; pinctrl-names = "default", "sleep"; /* CTS/RTS is not used, CTS is repurposed as GPIO */ @@ -403,7 +403,7 @@ }; /* Debugging console UART connected to AB8505 */ - uart@80007000 { + serial@80007000 { status = "okay"; pinctrl-names = "default", "sleep"; pinctrl-0 = <&u2rxtx_c_1_default>; diff --git a/arch/arm/boot/dts/ste-ux500-samsung-codina.dts b/arch/arm/boot/dts/st/ste-ux500-samsung-codina.dts similarity index 99% rename from arch/arm/boot/dts/ste-ux500-samsung-codina.dts rename to arch/arm/boot/dts/st/ste-ux500-samsung-codina.dts index 1a6d24a7ccb884aef0cc1c036a75701d29a7c2a1..c1ae0e23fe459619e54236ba938a10cfcd217b0a 100644 --- a/arch/arm/boot/dts/ste-ux500-samsung-codina.dts +++ b/arch/arm/boot/dts/st/ste-ux500-samsung-codina.dts @@ -462,7 +462,7 @@ }; /* GBF (Bluetooth) UART */ - uart@80120000 { + serial@80120000 { pinctrl-names = "default", "sleep"; pinctrl-0 = <&u0_a_1_default>; pinctrl-1 = <&u0_a_1_sleep>; @@ -485,7 +485,7 @@ }; /* GPS UART */ - uart@80121000 { + serial@80121000 { status = "okay"; pinctrl-names = "default", "sleep"; pinctrl-0 = <&u1rxtx_a_1_default &u1ctsrts_a_1_default>; @@ -505,7 +505,7 @@ }; /* Debugging console UART connected to TSU6111RSVR (FSA880) */ - uart@80007000 { + serial@80007000 { status = "okay"; pinctrl-names = "default", "sleep"; pinctrl-0 = <&u2rxtx_c_1_default>; diff --git a/arch/arm/boot/dts/ste-ux500-samsung-gavini.dts b/arch/arm/boot/dts/st/ste-ux500-samsung-gavini.dts similarity index 99% rename from arch/arm/boot/dts/ste-ux500-samsung-gavini.dts rename to arch/arm/boot/dts/st/ste-ux500-samsung-gavini.dts index 5b445fa4c8c087cab6ad161deaa3c27eba2515ae..b21e40da3dfdb4161d18dc2d956391ed54fa1b23 100644 --- a/arch/arm/boot/dts/ste-ux500-samsung-gavini.dts +++ b/arch/arm/boot/dts/st/ste-ux500-samsung-gavini.dts @@ -417,7 +417,7 @@ }; /* GBF (Bluetooth) UART */ - uart@80120000 { + serial@80120000 { pinctrl-names = "default", "sleep"; pinctrl-0 = <&u0_a_1_default>; pinctrl-1 = <&u0_a_1_sleep>; @@ -439,7 +439,7 @@ }; /* GPS UART */ - uart@80121000 { + serial@80121000 { status = "okay"; pinctrl-names = "default", "sleep"; /* CTS/RTS is not used, CTS is repurposed as GPIO */ @@ -449,7 +449,7 @@ }; /* Debugging console UART connected to TSU6111RSVR (FSA880) */ - uart@80007000 { + serial@80007000 { status = "okay"; pinctrl-names = "default", "sleep"; pinctrl-0 = <&u2rxtx_c_1_default>; diff --git a/arch/arm/boot/dts/ste-ux500-samsung-golden.dts b/arch/arm/boot/dts/st/ste-ux500-samsung-golden.dts similarity index 99% rename from arch/arm/boot/dts/ste-ux500-samsung-golden.dts rename to arch/arm/boot/dts/st/ste-ux500-samsung-golden.dts index 9604695edf5307fcfa37f5fa7b0e4c6c69366d12..f736888474e7a5af12cd434a48df70a7f8ddd8a9 100644 --- a/arch/arm/boot/dts/ste-ux500-samsung-golden.dts +++ b/arch/arm/boot/dts/st/ste-ux500-samsung-golden.dts @@ -186,7 +186,7 @@ }; /* BT UART */ - uart@80120000 { + serial@80120000 { status = "okay"; pinctrl-names = "default", "sleep"; @@ -209,7 +209,7 @@ }; /* GPF UART */ - uart@80121000 { + serial@80121000 { status = "okay"; pinctrl-names = "default", "sleep"; @@ -218,7 +218,7 @@ }; /* Debugging console UART */ - uart@80007000 { + serial@80007000 { status = "okay"; pinctrl-names = "default", "sleep"; diff --git a/arch/arm/boot/dts/ste-ux500-samsung-janice.dts b/arch/arm/boot/dts/st/ste-ux500-samsung-janice.dts similarity index 99% rename from arch/arm/boot/dts/ste-ux500-samsung-janice.dts rename to arch/arm/boot/dts/st/ste-ux500-samsung-janice.dts index e901cb76b899798b78142d50098bd77343deafbd..6e586e875565a453a9ba4193c95d6ae2b765a711 100644 --- a/arch/arm/boot/dts/ste-ux500-samsung-janice.dts +++ b/arch/arm/boot/dts/st/ste-ux500-samsung-janice.dts @@ -467,7 +467,7 @@ }; /* GBF (Bluetooth) UART */ - uart@80120000 { + serial@80120000 { pinctrl-names = "default", "sleep"; pinctrl-0 = <&u0_a_1_default>; pinctrl-1 = <&u0_a_1_sleep>; @@ -491,7 +491,7 @@ }; /* GPS UART */ - uart@80121000 { + serial@80121000 { status = "okay"; pinctrl-names = "default", "sleep"; /* CTS/RTS is not used, CTS is repurposed as GPIO */ @@ -520,7 +520,7 @@ }; /* Debugging console UART connected to TSU6111RSVR (FSA880) */ - uart@80007000 { + serial@80007000 { status = "okay"; pinctrl-names = "default", "sleep"; pinctrl-0 = <&u2rxtx_c_1_default>; diff --git a/arch/arm/boot/dts/ste-ux500-samsung-kyle.dts b/arch/arm/boot/dts/st/ste-ux500-samsung-kyle.dts similarity index 99% rename from arch/arm/boot/dts/ste-ux500-samsung-kyle.dts rename to arch/arm/boot/dts/st/ste-ux500-samsung-kyle.dts index 45fab5283a9d3988b516f31e1b72ed8600220667..ba4421080b2a55f15562ebbff0f0ccd69b5fd960 100644 --- a/arch/arm/boot/dts/ste-ux500-samsung-kyle.dts +++ b/arch/arm/boot/dts/st/ste-ux500-samsung-kyle.dts @@ -292,7 +292,7 @@ }; /* GBF (Bluetooth) UART */ - uart@80120000 { + serial@80120000 { pinctrl-names = "default", "sleep"; pinctrl-0 = <&u0_a_1_default>; pinctrl-1 = <&u0_a_1_sleep>; @@ -310,7 +310,7 @@ }; /* GPF UART */ - uart@80121000 { + serial@80121000 { status = "okay"; pinctrl-names = "default", "sleep"; pinctrl-0 = <&u1rxtx_a_1_default &u1ctsrts_a_1_default>; @@ -333,7 +333,7 @@ }; /* Debugging console UART connected to AB8505 USB */ - uart@80007000 { + serial@80007000 { status = "okay"; pinctrl-names = "default", "sleep"; pinctrl-0 = <&u2rxtx_c_1_default>; diff --git a/arch/arm/boot/dts/ste-ux500-samsung-skomer.dts b/arch/arm/boot/dts/st/ste-ux500-samsung-skomer.dts similarity index 99% rename from arch/arm/boot/dts/ste-ux500-samsung-skomer.dts rename to arch/arm/boot/dts/st/ste-ux500-samsung-skomer.dts index 93e5f5ed888d1c139981d350d4c5b3b27d51241e..064d6fee88210866baf07a922bcd38b778b43595 100644 --- a/arch/arm/boot/dts/ste-ux500-samsung-skomer.dts +++ b/arch/arm/boot/dts/st/ste-ux500-samsung-skomer.dts @@ -271,7 +271,7 @@ }; /* GBF (Bluetooth) UART */ - uart@80120000 { + serial@80120000 { pinctrl-names = "default", "sleep"; pinctrl-0 = <&u0_a_1_default>; pinctrl-1 = <&u0_a_1_sleep>; @@ -290,7 +290,7 @@ }; /* GPS UART */ - uart@80121000 { + serial@80121000 { status = "okay"; pinctrl-names = "default", "sleep"; pinctrl-0 = <&u1rxtx_a_1_default &u1ctsrts_a_1_default>; @@ -313,7 +313,7 @@ }; /* Debugging console UART connected to AB8505 USB */ - uart@80007000 { + serial@80007000 { status = "okay"; pinctrl-names = "default", "sleep"; pinctrl-0 = <&u2rxtx_c_1_default>; diff --git a/arch/arm/boot/dts/stih407-b2120.dts b/arch/arm/boot/dts/st/stih407-b2120.dts similarity index 100% rename from arch/arm/boot/dts/stih407-b2120.dts rename to arch/arm/boot/dts/st/stih407-b2120.dts diff --git a/arch/arm/boot/dts/stih407-clock.dtsi b/arch/arm/boot/dts/st/stih407-clock.dtsi similarity index 100% rename from arch/arm/boot/dts/stih407-clock.dtsi rename to arch/arm/boot/dts/st/stih407-clock.dtsi diff --git a/arch/arm/boot/dts/stih407-family.dtsi b/arch/arm/boot/dts/st/stih407-family.dtsi similarity index 99% rename from arch/arm/boot/dts/stih407-family.dtsi rename to arch/arm/boot/dts/st/stih407-family.dtsi index 5ebb77947fd913c6abea8f13165a2c8e92b31d5e..3f58383a7b592088e413f44caa3b550afd1a2721 100644 --- a/arch/arm/boot/dts/stih407-family.dtsi +++ b/arch/arm/boot/dts/st/stih407-family.dtsi @@ -645,7 +645,7 @@ st,lpc-mode = ; }; - spifsm: spifsm@9022000{ + spifsm: spifsm@9022000 { compatible = "st,spi-fsm"; reg = <0x9022000 0x1000>; reg-names = "spi-fsm"; diff --git a/arch/arm/boot/dts/stih407-pinctrl.dtsi b/arch/arm/boot/dts/st/stih407-pinctrl.dtsi similarity index 99% rename from arch/arm/boot/dts/stih407-pinctrl.dtsi rename to arch/arm/boot/dts/st/stih407-pinctrl.dtsi index 2cf335714ca21e89bbdf94a5cab60fec956970fa..7815669fe81348015c5354faadb1db13af12d637 100644 --- a/arch/arm/boot/dts/stih407-pinctrl.dtsi +++ b/arch/arm/boot/dts/st/stih407-pinctrl.dtsi @@ -1090,7 +1090,7 @@ }; i2s_out { - pinctrl_i2s_8ch_out: i2s_8ch_out{ + pinctrl_i2s_8ch_out: i2s_8ch_out { st,pins { mclk = <&pio33 5 ALT1 OUT>; lrclk = <&pio33 7 ALT1 OUT>; @@ -1102,7 +1102,7 @@ }; }; - pinctrl_i2s_2ch_out: i2s_2ch_out{ + pinctrl_i2s_2ch_out: i2s_2ch_out { st,pins { mclk = <&pio33 5 ALT1 OUT>; lrclk = <&pio33 7 ALT1 OUT>; @@ -1113,7 +1113,7 @@ }; i2s_in { - pinctrl_i2s_8ch_in: i2s_8ch_in{ + pinctrl_i2s_8ch_in: i2s_8ch_in { st,pins { mclk = <&pio32 5 ALT1 IN>; lrclk = <&pio32 7 ALT1 IN>; @@ -1126,7 +1126,7 @@ }; }; - pinctrl_i2s_2ch_in: i2s_2ch_in{ + pinctrl_i2s_2ch_in: i2s_2ch_in { st,pins { mclk = <&pio32 5 ALT1 IN>; lrclk = <&pio32 7 ALT1 IN>; @@ -1137,7 +1137,7 @@ }; spdif_out { - pinctrl_spdif_out: spdif_out{ + pinctrl_spdif_out: spdif_out { st,pins { spdif_out = <&pio34 7 ALT1 OUT>; }; diff --git a/arch/arm/boot/dts/stih407.dtsi b/arch/arm/boot/dts/st/stih407.dtsi similarity index 100% rename from arch/arm/boot/dts/stih407.dtsi rename to arch/arm/boot/dts/st/stih407.dtsi diff --git a/arch/arm/boot/dts/stih410-b2120.dts b/arch/arm/boot/dts/st/stih410-b2120.dts similarity index 100% rename from arch/arm/boot/dts/stih410-b2120.dts rename to arch/arm/boot/dts/st/stih410-b2120.dts diff --git a/arch/arm/boot/dts/stih410-b2260.dts b/arch/arm/boot/dts/st/stih410-b2260.dts similarity index 100% rename from arch/arm/boot/dts/stih410-b2260.dts rename to arch/arm/boot/dts/st/stih410-b2260.dts diff --git a/arch/arm/boot/dts/stih410-clock.dtsi b/arch/arm/boot/dts/st/stih410-clock.dtsi similarity index 100% rename from arch/arm/boot/dts/stih410-clock.dtsi rename to arch/arm/boot/dts/st/stih410-clock.dtsi diff --git a/arch/arm/boot/dts/stih410-pinctrl.dtsi b/arch/arm/boot/dts/st/stih410-pinctrl.dtsi similarity index 100% rename from arch/arm/boot/dts/stih410-pinctrl.dtsi rename to arch/arm/boot/dts/st/stih410-pinctrl.dtsi diff --git a/arch/arm/boot/dts/stih410.dtsi b/arch/arm/boot/dts/st/stih410.dtsi similarity index 100% rename from arch/arm/boot/dts/stih410.dtsi rename to arch/arm/boot/dts/st/stih410.dtsi diff --git a/arch/arm/boot/dts/stih418-b2199.dts b/arch/arm/boot/dts/st/stih418-b2199.dts similarity index 100% rename from arch/arm/boot/dts/stih418-b2199.dts rename to arch/arm/boot/dts/st/stih418-b2199.dts diff --git a/arch/arm/boot/dts/stih418-b2264.dts b/arch/arm/boot/dts/st/stih418-b2264.dts similarity index 100% rename from arch/arm/boot/dts/stih418-b2264.dts rename to arch/arm/boot/dts/st/stih418-b2264.dts diff --git a/arch/arm/boot/dts/stih418-clock.dtsi b/arch/arm/boot/dts/st/stih418-clock.dtsi similarity index 100% rename from arch/arm/boot/dts/stih418-clock.dtsi rename to arch/arm/boot/dts/st/stih418-clock.dtsi diff --git a/arch/arm/boot/dts/stih418.dtsi b/arch/arm/boot/dts/st/stih418.dtsi similarity index 100% rename from arch/arm/boot/dts/stih418.dtsi rename to arch/arm/boot/dts/st/stih418.dtsi diff --git a/arch/arm/boot/dts/stihxxx-b2120.dtsi b/arch/arm/boot/dts/st/stihxxx-b2120.dtsi similarity index 100% rename from arch/arm/boot/dts/stihxxx-b2120.dtsi rename to arch/arm/boot/dts/st/stihxxx-b2120.dtsi diff --git a/arch/arm/boot/dts/stm32429i-eval.dts b/arch/arm/boot/dts/st/stm32429i-eval.dts similarity index 100% rename from arch/arm/boot/dts/stm32429i-eval.dts rename to arch/arm/boot/dts/st/stm32429i-eval.dts diff --git a/arch/arm/boot/dts/stm32746g-eval.dts b/arch/arm/boot/dts/st/stm32746g-eval.dts similarity index 100% rename from arch/arm/boot/dts/stm32746g-eval.dts rename to arch/arm/boot/dts/st/stm32746g-eval.dts diff --git a/arch/arm/boot/dts/stm32f4-pinctrl.dtsi b/arch/arm/boot/dts/st/stm32f4-pinctrl.dtsi similarity index 100% rename from arch/arm/boot/dts/stm32f4-pinctrl.dtsi rename to arch/arm/boot/dts/st/stm32f4-pinctrl.dtsi diff --git a/arch/arm/boot/dts/stm32f429-disco.dts b/arch/arm/boot/dts/st/stm32f429-disco.dts similarity index 99% rename from arch/arm/boot/dts/stm32f429-disco.dts rename to arch/arm/boot/dts/st/stm32f429-disco.dts index 3b81228d46a20de294b5bd267dc6dde86a3796ab..a3cb4aabdd5add2678eae4ad0770c2e62c62371b 100644 --- a/arch/arm/boot/dts/stm32f429-disco.dts +++ b/arch/arm/boot/dts/st/stm32f429-disco.dts @@ -190,7 +190,7 @@ status = "okay"; }; - display: display@1{ + display: display@1 { /* Connect panel-ilitek-9341 to ltdc */ compatible = "st,sf-tc240t-9370-t", "ilitek,ili9341"; reg = <1>; diff --git a/arch/arm/boot/dts/stm32f429-pinctrl.dtsi b/arch/arm/boot/dts/st/stm32f429-pinctrl.dtsi similarity index 100% rename from arch/arm/boot/dts/stm32f429-pinctrl.dtsi rename to arch/arm/boot/dts/st/stm32f429-pinctrl.dtsi diff --git a/arch/arm/boot/dts/stm32f429.dtsi b/arch/arm/boot/dts/st/stm32f429.dtsi similarity index 99% rename from arch/arm/boot/dts/stm32f429.dtsi rename to arch/arm/boot/dts/st/stm32f429.dtsi index 00bf53f99c294c6c183366798bbd3bca7569456b..8efcda9ef8ae20bfd3ffee07df89d958e28939e9 100644 --- a/arch/arm/boot/dts/stm32f429.dtsi +++ b/arch/arm/boot/dts/st/stm32f429.dtsi @@ -45,7 +45,7 @@ * OTHER DEALINGS IN THE SOFTWARE. */ -#include "armv7-m.dtsi" +#include "../armv7-m.dtsi" #include #include diff --git a/arch/arm/boot/dts/stm32f469-disco.dts b/arch/arm/boot/dts/st/stm32f469-disco.dts similarity index 99% rename from arch/arm/boot/dts/stm32f469-disco.dts rename to arch/arm/boot/dts/st/stm32f469-disco.dts index 5a0daf8e8b118518b018c79881a9fea0a39b6d32..cbbd521bf010847ca06a28972cad4850d502d8c5 100644 --- a/arch/arm/boot/dts/stm32f469-disco.dts +++ b/arch/arm/boot/dts/st/stm32f469-disco.dts @@ -160,7 +160,7 @@ }; }; - panel-dsi@0 { + panel@0 { compatible = "orisetech,otm8009a"; reg = <0>; /* dsi virtual channel (0..3) */ reset-gpios = <&gpioh 7 GPIO_ACTIVE_LOW>; @@ -179,7 +179,7 @@ status = "okay"; port { - ltdc_out_dsi: endpoint@0 { + ltdc_out_dsi: endpoint { remote-endpoint = <&dsi_in>; }; }; diff --git a/arch/arm/boot/dts/stm32f469-pinctrl.dtsi b/arch/arm/boot/dts/st/stm32f469-pinctrl.dtsi similarity index 100% rename from arch/arm/boot/dts/stm32f469-pinctrl.dtsi rename to arch/arm/boot/dts/st/stm32f469-pinctrl.dtsi diff --git a/arch/arm/boot/dts/stm32f469.dtsi b/arch/arm/boot/dts/st/stm32f469.dtsi similarity index 100% rename from arch/arm/boot/dts/stm32f469.dtsi rename to arch/arm/boot/dts/st/stm32f469.dtsi diff --git a/arch/arm/boot/dts/stm32f7-pinctrl.dtsi b/arch/arm/boot/dts/st/stm32f7-pinctrl.dtsi similarity index 100% rename from arch/arm/boot/dts/stm32f7-pinctrl.dtsi rename to arch/arm/boot/dts/st/stm32f7-pinctrl.dtsi diff --git a/arch/arm/boot/dts/stm32f746-disco.dts b/arch/arm/boot/dts/st/stm32f746-disco.dts similarity index 100% rename from arch/arm/boot/dts/stm32f746-disco.dts rename to arch/arm/boot/dts/st/stm32f746-disco.dts diff --git a/arch/arm/boot/dts/stm32f746-pinctrl.dtsi b/arch/arm/boot/dts/st/stm32f746-pinctrl.dtsi similarity index 96% rename from arch/arm/boot/dts/stm32f746-pinctrl.dtsi rename to arch/arm/boot/dts/st/stm32f746-pinctrl.dtsi index fcfd2ac7239bb622b87f92e07105b3ccb21709ca..781197ef42d6b6c3c5d47ac8884d6302a1022179 100644 --- a/arch/arm/boot/dts/stm32f746-pinctrl.dtsi +++ b/arch/arm/boot/dts/st/stm32f746-pinctrl.dtsi @@ -6,6 +6,6 @@ #include "stm32f7-pinctrl.dtsi" -&pinctrl{ +&pinctrl { compatible = "st,stm32f746-pinctrl"; }; diff --git a/arch/arm/boot/dts/stm32f746.dtsi b/arch/arm/boot/dts/st/stm32f746.dtsi similarity index 99% rename from arch/arm/boot/dts/stm32f746.dtsi rename to arch/arm/boot/dts/st/stm32f746.dtsi index dc868e6da40e0fae8e98cfca3f3674efa61210d7..d1802efd067cc096b3f6c14e7babacdc3d257484 100644 --- a/arch/arm/boot/dts/stm32f746.dtsi +++ b/arch/arm/boot/dts/st/stm32f746.dtsi @@ -40,7 +40,7 @@ * OTHER DEALINGS IN THE SOFTWARE. */ -#include "armv7-m.dtsi" +#include "../armv7-m.dtsi" #include #include @@ -515,7 +515,7 @@ crc: crc@40023000 { compatible = "st,stm32f7-crc"; reg = <0x40023000 0x400>; - clocks = <&rcc 0 12>; + clocks = <&rcc 0 STM32F7_AHB1_CLOCK(CRC)>; status = "disabled"; }; diff --git a/arch/arm/boot/dts/stm32f769-disco.dts b/arch/arm/boot/dts/st/stm32f769-disco.dts similarity index 100% rename from arch/arm/boot/dts/stm32f769-disco.dts rename to arch/arm/boot/dts/st/stm32f769-disco.dts diff --git a/arch/arm/boot/dts/stm32f769-pinctrl.dtsi b/arch/arm/boot/dts/st/stm32f769-pinctrl.dtsi similarity index 96% rename from arch/arm/boot/dts/stm32f769-pinctrl.dtsi rename to arch/arm/boot/dts/st/stm32f769-pinctrl.dtsi index 31005dd9929c40cb6d5cf0ff93b141b28ac0dd1d..c26abc04e2cec10be70be55d7e19f36984367b38 100644 --- a/arch/arm/boot/dts/stm32f769-pinctrl.dtsi +++ b/arch/arm/boot/dts/st/stm32f769-pinctrl.dtsi @@ -6,6 +6,6 @@ #include "stm32f7-pinctrl.dtsi" -&pinctrl{ +&pinctrl { compatible = "st,stm32f769-pinctrl"; }; diff --git a/arch/arm/boot/dts/stm32h7-pinctrl.dtsi b/arch/arm/boot/dts/st/stm32h7-pinctrl.dtsi similarity index 99% rename from arch/arm/boot/dts/stm32h7-pinctrl.dtsi rename to arch/arm/boot/dts/st/stm32h7-pinctrl.dtsi index aa1bc3e10a49deaeb688d4705a3b2c67ba3f49fb..7f1d234e102454505ad5f93f4dfc1bec5ebcd7d9 100644 --- a/arch/arm/boot/dts/stm32h7-pinctrl.dtsi +++ b/arch/arm/boot/dts/st/stm32h7-pinctrl.dtsi @@ -94,7 +94,7 @@ drive-push-pull; bias-disable; }; - pins2{ + pins2 { pinmux = ; /* SDMMC1_CMD */ slew-rate = <3>; drive-open-drain; @@ -122,7 +122,7 @@ drive-push-pull; bias-pull-up; }; - pins2{ + pins2 { pinmux = ; /* SDMMC1_CKIN */ bias-pull-up; }; @@ -162,7 +162,7 @@ drive-push-pull; bias-disable; }; - pins2{ + pins2 { pinmux = ; /* SDMMC1_CMD */ slew-rate = <3>; drive-open-drain; diff --git a/arch/arm/boot/dts/stm32h743.dtsi b/arch/arm/boot/dts/st/stm32h743.dtsi similarity index 99% rename from arch/arm/boot/dts/stm32h743.dtsi rename to arch/arm/boot/dts/st/stm32h743.dtsi index f30796f7adf36b0e23b603809b675b723bea7156..b8d4c44c8a82a9058e7cb27ba15246a796556028 100644 --- a/arch/arm/boot/dts/stm32h743.dtsi +++ b/arch/arm/boot/dts/st/stm32h743.dtsi @@ -40,7 +40,7 @@ * OTHER DEALINGS IN THE SOFTWARE. */ -#include "armv7-m.dtsi" +#include "../armv7-m.dtsi" #include #include #include diff --git a/arch/arm/boot/dts/stm32h743i-disco.dts b/arch/arm/boot/dts/st/stm32h743i-disco.dts similarity index 100% rename from arch/arm/boot/dts/stm32h743i-disco.dts rename to arch/arm/boot/dts/st/stm32h743i-disco.dts diff --git a/arch/arm/boot/dts/stm32h743i-eval.dts b/arch/arm/boot/dts/st/stm32h743i-eval.dts similarity index 100% rename from arch/arm/boot/dts/stm32h743i-eval.dts rename to arch/arm/boot/dts/st/stm32h743i-eval.dts diff --git a/arch/arm/boot/dts/stm32h750.dtsi b/arch/arm/boot/dts/st/stm32h750.dtsi similarity index 100% rename from arch/arm/boot/dts/stm32h750.dtsi rename to arch/arm/boot/dts/st/stm32h750.dtsi diff --git a/arch/arm/boot/dts/stm32h750i-art-pi.dts b/arch/arm/boot/dts/st/stm32h750i-art-pi.dts similarity index 99% rename from arch/arm/boot/dts/stm32h750i-art-pi.dts rename to arch/arm/boot/dts/st/stm32h750i-art-pi.dts index f3e70d3b65ac4ac75262b422938d30b965fcb670..44c307f8b09cf7cf4d2dfca24c029ea8327bb0dc 100644 --- a/arch/arm/boot/dts/stm32h750i-art-pi.dts +++ b/arch/arm/boot/dts/st/stm32h750i-art-pi.dts @@ -208,7 +208,7 @@ dmas = <&dmamux1 45 0x400 0x05>, <&dmamux1 46 0x400 0x05>; dma-names = "rx", "tx"; - st,hw-flow-ctrl; + uart-has-rtscts; status = "okay"; bluetooth { diff --git a/arch/arm/boot/dts/stm32mp13-pinctrl.dtsi b/arch/arm/boot/dts/st/stm32mp13-pinctrl.dtsi similarity index 100% rename from arch/arm/boot/dts/stm32mp13-pinctrl.dtsi rename to arch/arm/boot/dts/st/stm32mp13-pinctrl.dtsi diff --git a/arch/arm/boot/dts/stm32mp131.dtsi b/arch/arm/boot/dts/st/stm32mp131.dtsi similarity index 100% rename from arch/arm/boot/dts/stm32mp131.dtsi rename to arch/arm/boot/dts/st/stm32mp131.dtsi diff --git a/arch/arm/boot/dts/stm32mp133.dtsi b/arch/arm/boot/dts/st/stm32mp133.dtsi similarity index 100% rename from arch/arm/boot/dts/stm32mp133.dtsi rename to arch/arm/boot/dts/st/stm32mp133.dtsi diff --git a/arch/arm/boot/dts/stm32mp135.dtsi b/arch/arm/boot/dts/st/stm32mp135.dtsi similarity index 100% rename from arch/arm/boot/dts/stm32mp135.dtsi rename to arch/arm/boot/dts/st/stm32mp135.dtsi diff --git a/arch/arm/boot/dts/stm32mp135f-dk.dts b/arch/arm/boot/dts/st/stm32mp135f-dk.dts similarity index 100% rename from arch/arm/boot/dts/stm32mp135f-dk.dts rename to arch/arm/boot/dts/st/stm32mp135f-dk.dts diff --git a/arch/arm/boot/dts/stm32mp13xc.dtsi b/arch/arm/boot/dts/st/stm32mp13xc.dtsi similarity index 100% rename from arch/arm/boot/dts/stm32mp13xc.dtsi rename to arch/arm/boot/dts/st/stm32mp13xc.dtsi diff --git a/arch/arm/boot/dts/stm32mp13xf.dtsi b/arch/arm/boot/dts/st/stm32mp13xf.dtsi similarity index 100% rename from arch/arm/boot/dts/stm32mp13xf.dtsi rename to arch/arm/boot/dts/st/stm32mp13xf.dtsi diff --git a/arch/arm/boot/dts/stm32mp15-pinctrl.dtsi b/arch/arm/boot/dts/st/stm32mp15-pinctrl.dtsi similarity index 91% rename from arch/arm/boot/dts/stm32mp15-pinctrl.dtsi rename to arch/arm/boot/dts/st/stm32mp15-pinctrl.dtsi index e86d989dd351d3677e3a6f067e2745aeb9ba6bcc..05c9c4f8064c6fa43e4fd75f65b3abcbbfe3e7e6 100644 --- a/arch/arm/boot/dts/stm32mp15-pinctrl.dtsi +++ b/arch/arm/boot/dts/st/stm32mp15-pinctrl.dtsi @@ -341,6 +341,56 @@ }; }; + ethernet0_rgmii_pins_d: rgmii-3 { + pins1 { + pinmux = , /* ETH_RGMII_CLK125 */ + , /* ETH_RGMII_TXD0 */ + , /* ETH_RGMII_TXD1 */ + , /* ETH_RGMII_TXD2 */ + , /* ETH_RGMII_TXD3 */ + , /* ETH_RGMII_TX_CTL */ + ; /* ETH_MDC */ + bias-disable; + drive-push-pull; + slew-rate = <2>; + }; + pins2 { + pinmux = ; /* ETH_MDIO */ + bias-disable; + drive-push-pull; + slew-rate = <0>; + }; + pins3 { + pinmux = , /* ETH_RGMII_RXD0 */ + , /* ETH_RGMII_RXD1 */ + , /* ETH_RGMII_RXD2 */ + , /* ETH_RGMII_RXD3 */ + , /* ETH_RGMII_RX_CLK */ + ; /* ETH_RGMII_RX_CTL */ + bias-disable; + }; + }; + + ethernet0_rgmii_sleep_pins_d: rgmii-sleep-3 { + pins1 { + pinmux = , /* ETH_RGMII_CLK125 */ + , /* ETH_RGMII_GTX_CLK */ + , /* ETH_RGMII_TXD0 */ + , /* ETH_RGMII_TXD1 */ + , /* ETH_RGMII_TXD2 */ + , /* ETH_RGMII_TXD3 */ + , /* ETH_RGMII_TX_CTL */ + , /* ETH_MDIO */ + , /* ETH_MDC */ + , /* ETH_RGMII_RXD0 */ + , /* ETH_RGMII_RXD1 */ + , /* ETH_RGMII_RXD2 */ + , /* ETH_RGMII_RXD3 */ + , /* ETH_RGMII_RX_CLK */ + ; /* ETH_RGMII_RX_CTL */ + }; + }; + ethernet0_rmii_pins_a: rmii-0 { pins1 { pinmux = , /* ETH1_RMII_TXD0 */ @@ -1441,6 +1491,30 @@ }; }; + sai2b_pins_d: sai2b-3 { + pins1 { + pinmux = , /* SAI2_SCK_B */ + , /* SAI2_FS_B */ + ; /* SAI2_MCLK_B */ + slew-rate = <0>; + drive-push-pull; + bias-disable; + }; + pins2 { + pinmux = ; /* SAI2_SD_B */ + bias-disable; + }; + }; + + sai2b_sleep_pins_d: sai2b-sleep-3 { + pins1 { + pinmux = , /* SAI2_SCK_B */ + , /* SAI2_FS_B */ + , /* SAI2_MCLK_B */ + ; /* SAI2_SD_B */ + }; + }; + sai4a_pins_a: sai4a-0 { pins { pinmux = ; /* SAI4_SD_A */ @@ -1522,6 +1596,60 @@ }; }; + sdmmc1_b4_pins_b: sdmmc1-b4-1 { + pins1 { + pinmux = , /* SDMMC1_D0 */ + , /* SDMMC1_D1 */ + , /* SDMMC1_D2 */ + , /* SDMMC1_D3 */ + ; /* SDMMC1_CMD */ + slew-rate = <1>; + drive-push-pull; + bias-disable; + }; + pins2 { + pinmux = ; /* SDMMC1_CK */ + slew-rate = <2>; + drive-push-pull; + bias-disable; + }; + }; + + sdmmc1_b4_od_pins_b: sdmmc1-b4-od-1 { + pins1 { + pinmux = , /* SDMMC1_D0 */ + , /* SDMMC1_D1 */ + , /* SDMMC1_D2 */ + ; /* SDMMC1_D3 */ + slew-rate = <1>; + drive-push-pull; + bias-disable; + }; + pins2 { + pinmux = ; /* SDMMC1_CK */ + slew-rate = <2>; + drive-push-pull; + bias-disable; + }; + pins3 { + pinmux = ; /* SDMMC1_CMD */ + slew-rate = <1>; + drive-open-drain; + bias-disable; + }; + }; + + sdmmc1_b4_sleep_pins_b: sdmmc1-b4-sleep-1 { + pins { + pinmux = , /* SDMMC1_D0 */ + , /* SDMMC1_D1 */ + , /* SDMMC1_D2 */ + , /* SDMMC1_D3 */ + , /* SDMMC1_CK */ + ; /* SDMMC1_CMD */ + }; + }; + sdmmc1_dir_pins_a: sdmmc1-dir-0 { pins1 { pinmux = , /* SDMMC1_D0DIR */ @@ -1531,7 +1659,7 @@ drive-push-pull; bias-pull-up; }; - pins2{ + pins2 { pinmux = ; /* SDMMC1_CKIN */ bias-pull-up; }; @@ -1566,7 +1694,7 @@ drive-push-pull; bias-pull-up; }; - pins2{ + pins2 { pinmux = ; /* SDMMC1_CKIN */ bias-pull-up; }; @@ -1759,6 +1887,27 @@ }; }; + sdmmc2_d47_pins_e: sdmmc2-d47-4 { + pins { + pinmux = , /* SDMMC2_D4 */ + , /* SDMMC2_D5 */ + , /* SDMMC2_D6 */ + ; /* SDMMC2_D7 */ + slew-rate = <1>; + drive-push-pull; + bias-pull-up; + }; + }; + + sdmmc2_d47_sleep_pins_e: sdmmc2-d47-sleep-4 { + pins { + pinmux = , /* SDMMC2_D4 */ + , /* SDMMC2_D5 */ + , /* SDMMC2_D6 */ + ; /* SDMMC2_D7 */ + }; + }; + sdmmc3_b4_pins_a: sdmmc3-b4-0 { pins1 { pinmux = , /* SDMMC3_D0 */ @@ -2124,6 +2273,33 @@ }; }; + usart1_pins_a: usart1-0 { + pins1 { + pinmux = ; /* USART1_RTS */ + bias-disable; + drive-push-pull; + slew-rate = <0>; + }; + pins2 { + pinmux = ; /* USART1_CTS_NSS */ + bias-disable; + }; + }; + + usart1_idle_pins_a: usart1-idle-0 { + pins1 { + pinmux = , /* USART1_RTS */ + ; /* USART1_CTS_NSS */ + }; + }; + + usart1_sleep_pins_a: usart1-sleep-0 { + pins { + pinmux = , /* USART1_RTS */ + ; /* USART1_CTS_NSS */ + }; + }; + usart2_pins_a: usart2-0 { pins1 { pinmux = , /* USART2_TX */ @@ -2226,6 +2402,23 @@ }; }; + usart3_idle_pins_a: usart3-idle-0 { + pins1 { + pinmux = ; /* USART3_TX */ + }; + pins2 { + pinmux = ; /* USART3_RX */ + bias-disable; + }; + }; + + usart3_sleep_pins_a: usart3-sleep-0 { + pins { + pinmux = , /* USART3_TX */ + ; /* USART3_RX */ + }; + }; + usart3_pins_b: usart3-1 { pins1 { pinmux = , /* USART3_TX */ @@ -2463,4 +2656,42 @@ bias-disable; }; }; + + spi1_sleep_pins_a: spi1-sleep-0 { + pins { + pinmux = , /* SPI1_SCK */ + , /* SPI1_MISO */ + ; /* SPI1_MOSI */ + }; + }; + + usart1_pins_b: usart1-1 { + pins1 { + pinmux = ; /* USART1_TX */ + bias-disable; + drive-push-pull; + slew-rate = <0>; + }; + pins2 { + pinmux = ; /* USART1_RX */ + bias-disable; + }; + }; + + usart1_idle_pins_b: usart1-idle-1 { + pins1 { + pinmux = ; /* USART1_TX */ + }; + pins2 { + pinmux = ; /* USART1_RX */ + bias-disable; + }; + }; + + usart1_sleep_pins_b: usart1-sleep-1 { + pins { + pinmux = , /* USART1_TX */ + ; /* USART1_RX */ + }; + }; }; diff --git a/arch/arm/boot/dts/stm32mp15-scmi.dtsi b/arch/arm/boot/dts/st/stm32mp15-scmi.dtsi similarity index 100% rename from arch/arm/boot/dts/stm32mp15-scmi.dtsi rename to arch/arm/boot/dts/st/stm32mp15-scmi.dtsi diff --git a/arch/arm/boot/dts/stm32mp151.dtsi b/arch/arm/boot/dts/st/stm32mp151.dtsi similarity index 99% rename from arch/arm/boot/dts/stm32mp151.dtsi rename to arch/arm/boot/dts/st/stm32mp151.dtsi index 63f4c78fcc1dc9a4cc0d76ec27ff6a8364a07280..61508917521c36e03be08be6fe9422b53ba793e6 100644 --- a/arch/arm/boot/dts/stm32mp151.dtsi +++ b/arch/arm/boot/dts/st/stm32mp151.dtsi @@ -1093,6 +1093,8 @@ adc1: adc@0 { compatible = "st,stm32mp1-adc"; #io-channel-cells = <1>; + #address-cells = <1>; + #size-cells = <0>; reg = <0x0>; interrupt-parent = <&adc>; interrupts = <0>; @@ -1104,12 +1106,24 @@ adc2: adc@100 { compatible = "st,stm32mp1-adc"; #io-channel-cells = <1>; + #address-cells = <1>; + #size-cells = <0>; reg = <0x100>; interrupt-parent = <&adc>; interrupts = <1>; dmas = <&dmamux1 10 0x400 0x01>; dma-names = "rx"; + nvmem-cells = <&vrefint>; + nvmem-cell-names = "vrefint"; status = "disabled"; + channel@13 { + reg = <13>; + label = "vrefint"; + }; + channel@14 { + reg = <14>; + label = "vddcore"; + }; }; }; @@ -1529,11 +1543,6 @@ clock-names = "lcd"; resets = <&rcc LTDC_R>; status = "disabled"; - - port { - #address-cells = <1>; - #size-cells = <0>; - }; }; iwdg2: watchdog@5a002000 { @@ -1620,6 +1629,12 @@ reg = <0x5c005000 0x400>; #address-cells = <1>; #size-cells = <1>; + part_number_otp: part-number-otp@4 { + reg = <0x4 0x1>; + }; + vrefint: vrefin-cal@52 { + reg = <0x52 0x2>; + }; ts_cal1: calib@5c { reg = <0x5c 0x2>; }; @@ -1820,8 +1835,8 @@ <0x30000000 0x40000>, <0x38000000 0x10000>; resets = <&rcc MCU_R>; + reset-names = "mcu_rst"; st,syscfg-holdboot = <&rcc 0x10C 0x1>; - st,syscfg-tz = <&rcc 0x000 0x1>; st,syscfg-pdds = <&pwr_mcu 0x0 0x1>; st,syscfg-rsc-tbl = <&tamp 0x144 0xFFFFFFFF>; st,syscfg-m4-state = <&tamp 0x148 0xFFFFFFFF>; diff --git a/arch/arm/boot/dts/stm32mp151a-dhcor-testbench.dts b/arch/arm/boot/dts/st/stm32mp151a-dhcor-testbench.dts similarity index 100% rename from arch/arm/boot/dts/stm32mp151a-dhcor-testbench.dts rename to arch/arm/boot/dts/st/stm32mp151a-dhcor-testbench.dts diff --git a/arch/arm/boot/dts/stm32mp151a-prtt1a.dts b/arch/arm/boot/dts/st/stm32mp151a-prtt1a.dts similarity index 100% rename from arch/arm/boot/dts/stm32mp151a-prtt1a.dts rename to arch/arm/boot/dts/st/stm32mp151a-prtt1a.dts diff --git a/arch/arm/boot/dts/stm32mp151a-prtt1c.dts b/arch/arm/boot/dts/st/stm32mp151a-prtt1c.dts similarity index 100% rename from arch/arm/boot/dts/stm32mp151a-prtt1c.dts rename to arch/arm/boot/dts/st/stm32mp151a-prtt1c.dts diff --git a/arch/arm/boot/dts/stm32mp151a-prtt1l.dtsi b/arch/arm/boot/dts/st/stm32mp151a-prtt1l.dtsi similarity index 100% rename from arch/arm/boot/dts/stm32mp151a-prtt1l.dtsi rename to arch/arm/boot/dts/st/stm32mp151a-prtt1l.dtsi diff --git a/arch/arm/boot/dts/stm32mp151a-prtt1s.dts b/arch/arm/boot/dts/st/stm32mp151a-prtt1s.dts similarity index 100% rename from arch/arm/boot/dts/stm32mp151a-prtt1s.dts rename to arch/arm/boot/dts/st/stm32mp151a-prtt1s.dts diff --git a/arch/arm/boot/dts/stm32mp153.dtsi b/arch/arm/boot/dts/st/stm32mp153.dtsi similarity index 100% rename from arch/arm/boot/dts/stm32mp153.dtsi rename to arch/arm/boot/dts/st/stm32mp153.dtsi diff --git a/arch/arm/boot/dts/stm32mp153c-dhcom-drc02.dts b/arch/arm/boot/dts/st/stm32mp153c-dhcom-drc02.dts similarity index 100% rename from arch/arm/boot/dts/stm32mp153c-dhcom-drc02.dts rename to arch/arm/boot/dts/st/stm32mp153c-dhcom-drc02.dts diff --git a/arch/arm/boot/dts/stm32mp153c-dhcor-drc-compact.dts b/arch/arm/boot/dts/st/stm32mp153c-dhcor-drc-compact.dts similarity index 100% rename from arch/arm/boot/dts/stm32mp153c-dhcor-drc-compact.dts rename to arch/arm/boot/dts/st/stm32mp153c-dhcor-drc-compact.dts diff --git a/arch/arm/boot/dts/stm32mp157.dtsi b/arch/arm/boot/dts/st/stm32mp157.dtsi similarity index 86% rename from arch/arm/boot/dts/stm32mp157.dtsi rename to arch/arm/boot/dts/st/stm32mp157.dtsi index 54e73ccea4464fcc1cff0a7c759f3519c6ce65b1..5e733cd16ff9e3426a7a5eabecf6b568c7fbe87f 100644 --- a/arch/arm/boot/dts/stm32mp157.dtsi +++ b/arch/arm/boot/dts/st/stm32mp157.dtsi @@ -24,14 +24,7 @@ clock-names = "pclk", "ref", "px_clk"; resets = <&rcc DSI_R>; reset-names = "apb"; - #address-cells = <1>; - #size-cells = <0>; status = "disabled"; - - ports { - #address-cells = <1>; - #size-cells = <0>; - }; }; }; }; diff --git a/arch/arm/boot/dts/stm32mp157a-avenger96.dts b/arch/arm/boot/dts/st/stm32mp157a-avenger96.dts similarity index 100% rename from arch/arm/boot/dts/stm32mp157a-avenger96.dts rename to arch/arm/boot/dts/st/stm32mp157a-avenger96.dts diff --git a/arch/arm/boot/dts/stm32mp157a-dhcor-avenger96.dts b/arch/arm/boot/dts/st/stm32mp157a-dhcor-avenger96.dts similarity index 100% rename from arch/arm/boot/dts/stm32mp157a-dhcor-avenger96.dts rename to arch/arm/boot/dts/st/stm32mp157a-dhcor-avenger96.dts diff --git a/arch/arm/boot/dts/stm32mp157a-dk1-scmi.dts b/arch/arm/boot/dts/st/stm32mp157a-dk1-scmi.dts similarity index 89% rename from arch/arm/boot/dts/stm32mp157a-dk1-scmi.dts rename to arch/arm/boot/dts/st/stm32mp157a-dk1-scmi.dts index e539cc80bef8108cb4d55c3b4130958860c4e072..afcd6285890cc0dad551573a83b81decb8ae459a 100644 --- a/arch/arm/boot/dts/stm32mp157a-dk1-scmi.dts +++ b/arch/arm/boot/dts/st/stm32mp157a-dk1-scmi.dts @@ -55,8 +55,11 @@ resets = <&scmi_reset RST_SCMI_MDMA>; }; -&mlahb { - resets = <&scmi_reset RST_SCMI_MCU>; +&m4_rproc { + /delete-property/ st,syscfg-holdboot; + resets = <&scmi_reset RST_SCMI_MCU>, + <&scmi_reset RST_SCMI_MCU_HOLD_BOOT>; + reset-names = "mcu_rst", "hold_boot"; }; &rcc { diff --git a/arch/arm/boot/dts/stm32mp157a-dk1.dts b/arch/arm/boot/dts/st/stm32mp157a-dk1.dts similarity index 100% rename from arch/arm/boot/dts/stm32mp157a-dk1.dts rename to arch/arm/boot/dts/st/stm32mp157a-dk1.dts diff --git a/arch/arm/boot/dts/stm32mp157a-icore-stm32mp1-ctouch2-of10.dts b/arch/arm/boot/dts/st/stm32mp157a-icore-stm32mp1-ctouch2-of10.dts similarity index 97% rename from arch/arm/boot/dts/stm32mp157a-icore-stm32mp1-ctouch2-of10.dts rename to arch/arm/boot/dts/st/stm32mp157a-icore-stm32mp1-ctouch2-of10.dts index 9a2a4bc7d0793635684f20ec6088069fc5e837f4..4279b26547dfdcfa3569a13eb91cf7533b251675 100644 --- a/arch/arm/boot/dts/stm32mp157a-icore-stm32mp1-ctouch2-of10.dts +++ b/arch/arm/boot/dts/st/stm32mp157a-icore-stm32mp1-ctouch2-of10.dts @@ -49,6 +49,9 @@ phy-dsi-supply = <®18>; ports { + #address-cells = <1>; + #size-cells = <0>; + port@0 { reg = <0>; dsi_in: endpoint { @@ -104,8 +107,7 @@ status = "okay"; port { - ltdc_ep0_out: endpoint@0 { - reg = <0>; + ltdc_ep0_out: endpoint { remote-endpoint = <&dsi_in>; }; }; diff --git a/arch/arm/boot/dts/stm32mp157a-icore-stm32mp1-ctouch2.dts b/arch/arm/boot/dts/st/stm32mp157a-icore-stm32mp1-ctouch2.dts similarity index 100% rename from arch/arm/boot/dts/stm32mp157a-icore-stm32mp1-ctouch2.dts rename to arch/arm/boot/dts/st/stm32mp157a-icore-stm32mp1-ctouch2.dts diff --git a/arch/arm/boot/dts/stm32mp157a-icore-stm32mp1-edimm2.2.dts b/arch/arm/boot/dts/st/stm32mp157a-icore-stm32mp1-edimm2.2.dts similarity index 97% rename from arch/arm/boot/dts/stm32mp157a-icore-stm32mp1-edimm2.2.dts rename to arch/arm/boot/dts/st/stm32mp157a-icore-stm32mp1-edimm2.2.dts index 390ee8c057547445dfe7368f28e683a8bd44e2f0..efba542898207b2fc15e33c82ea181e4c90f2f53 100644 --- a/arch/arm/boot/dts/stm32mp157a-icore-stm32mp1-edimm2.2.dts +++ b/arch/arm/boot/dts/st/stm32mp157a-icore-stm32mp1-edimm2.2.dts @@ -49,6 +49,9 @@ phy-dsi-supply = <®18>; ports { + #address-cells = <1>; + #size-cells = <0>; + port@0 { reg = <0>; dsi_in_ltdc: endpoint { @@ -104,8 +107,7 @@ status = "okay"; port { - ltdc_out_dsi: endpoint@0 { - reg = <0>; + ltdc_out_dsi: endpoint { remote-endpoint = <&dsi_in_ltdc>; }; }; diff --git a/arch/arm/boot/dts/stm32mp157a-icore-stm32mp1.dtsi b/arch/arm/boot/dts/st/stm32mp157a-icore-stm32mp1.dtsi similarity index 99% rename from arch/arm/boot/dts/stm32mp157a-icore-stm32mp1.dtsi rename to arch/arm/boot/dts/st/stm32mp157a-icore-stm32mp1.dtsi index 9de893101b4095b63ebd215241e723361d4c3e58..569a7e940ecc81cfce9abaf2e705d9958b48e55b 100644 --- a/arch/arm/boot/dts/stm32mp157a-icore-stm32mp1.dtsi +++ b/arch/arm/boot/dts/st/stm32mp157a-icore-stm32mp1.dtsi @@ -165,12 +165,12 @@ status = "okay"; }; -&iwdg2{ +&iwdg2 { timeout-sec = <32>; status = "okay"; }; -&m4_rproc{ +&m4_rproc { memory-region = <&retram>, <&mcuram>, <&mcuram2>, <&vdev0vring0>, <&vdev0vring1>, <&vdev0buffer>; mboxes = <&ipcc 0>, <&ipcc 1>, <&ipcc 2>; @@ -184,7 +184,7 @@ status = "okay"; }; -&rtc{ +&rtc { status = "okay"; }; diff --git a/arch/arm/boot/dts/stm32mp157a-iot-box.dts b/arch/arm/boot/dts/st/stm32mp157a-iot-box.dts similarity index 100% rename from arch/arm/boot/dts/stm32mp157a-iot-box.dts rename to arch/arm/boot/dts/st/stm32mp157a-iot-box.dts diff --git a/arch/arm/boot/dts/stm32mp157a-microgea-stm32mp1-microdev2.0-of7.dts b/arch/arm/boot/dts/st/stm32mp157a-microgea-stm32mp1-microdev2.0-of7.dts similarity index 98% rename from arch/arm/boot/dts/stm32mp157a-microgea-stm32mp1-microdev2.0-of7.dts rename to arch/arm/boot/dts/st/stm32mp157a-microgea-stm32mp1-microdev2.0-of7.dts index 0d7560ba2950f868e7de8f934ca8e490de5788ed..5116a77852013ec387151daeb8df91b31a7e57c8 100644 --- a/arch/arm/boot/dts/stm32mp157a-microgea-stm32mp1-microdev2.0-of7.dts +++ b/arch/arm/boot/dts/st/stm32mp157a-microgea-stm32mp1-microdev2.0-of7.dts @@ -81,8 +81,7 @@ status = "okay"; port { - ltdc_ep0_out: endpoint@0 { - reg = <0>; + ltdc_ep0_out: endpoint { remote-endpoint = <&panel_in>; }; }; diff --git a/arch/arm/boot/dts/stm32mp157a-microgea-stm32mp1-microdev2.0.dts b/arch/arm/boot/dts/st/stm32mp157a-microgea-stm32mp1-microdev2.0.dts similarity index 100% rename from arch/arm/boot/dts/stm32mp157a-microgea-stm32mp1-microdev2.0.dts rename to arch/arm/boot/dts/st/stm32mp157a-microgea-stm32mp1-microdev2.0.dts diff --git a/arch/arm/boot/dts/stm32mp157a-microgea-stm32mp1.dtsi b/arch/arm/boot/dts/st/stm32mp157a-microgea-stm32mp1.dtsi similarity index 99% rename from arch/arm/boot/dts/stm32mp157a-microgea-stm32mp1.dtsi rename to arch/arm/boot/dts/st/stm32mp157a-microgea-stm32mp1.dtsi index fb4600a598698837aaac7aa2fb28679c6322d7c0..a75f50cf712345d02dbb0b36dcdd828f723a2aa1 100644 --- a/arch/arm/boot/dts/stm32mp157a-microgea-stm32mp1.dtsi +++ b/arch/arm/boot/dts/st/stm32mp157a-microgea-stm32mp1.dtsi @@ -117,12 +117,12 @@ status = "okay"; }; -&iwdg2{ +&iwdg2 { timeout-sec = <32>; status = "okay"; }; -&m4_rproc{ +&m4_rproc { memory-region = <&retram>, <&mcuram>, <&mcuram2>, <&vdev0vring0>, <&vdev0vring1>, <&vdev0buffer>; mboxes = <&ipcc 0>, <&ipcc 1>, <&ipcc 2>; @@ -136,7 +136,7 @@ status = "okay"; }; -&rtc{ +&rtc { status = "okay"; }; diff --git a/arch/arm/boot/dts/stm32mp157a-stinger96.dts b/arch/arm/boot/dts/st/stm32mp157a-stinger96.dts similarity index 100% rename from arch/arm/boot/dts/stm32mp157a-stinger96.dts rename to arch/arm/boot/dts/st/stm32mp157a-stinger96.dts diff --git a/arch/arm/boot/dts/stm32mp157a-stinger96.dtsi b/arch/arm/boot/dts/st/stm32mp157a-stinger96.dtsi similarity index 99% rename from arch/arm/boot/dts/stm32mp157a-stinger96.dtsi rename to arch/arm/boot/dts/st/stm32mp157a-stinger96.dtsi index 3a36f7fe0a2c3443fb307679aac3419fb993c0f7..5f85598cc7c6bc8edccc24a67ddb5ff281c37145 100644 --- a/arch/arm/boot/dts/stm32mp157a-stinger96.dtsi +++ b/arch/arm/boot/dts/st/stm32mp157a-stinger96.dtsi @@ -287,7 +287,7 @@ pinctrl-names = "default", "sleep"; pinctrl-0 = <&usart2_pins_b>; pinctrl-1 = <&usart2_sleep_pins_b>; - st,hw-flow-ctrl; + uart-has-rtscts; /delete-property/dmas; /delete-property/dma-names; status = "okay"; @@ -297,7 +297,7 @@ &uart4 { pinctrl-names = "default"; pinctrl-0 = <&uart4_pins_c>; - st,hw-flow-ctrl; + uart-has-rtscts; /delete-property/dmas; /delete-property/dma-names; status = "okay"; diff --git a/arch/arm/boot/dts/stm32mp157c-dhcom-pdk2.dts b/arch/arm/boot/dts/st/stm32mp157c-dhcom-pdk2.dts similarity index 100% rename from arch/arm/boot/dts/stm32mp157c-dhcom-pdk2.dts rename to arch/arm/boot/dts/st/stm32mp157c-dhcom-pdk2.dts diff --git a/arch/arm/boot/dts/stm32mp157c-dhcom-picoitx.dts b/arch/arm/boot/dts/st/stm32mp157c-dhcom-picoitx.dts similarity index 100% rename from arch/arm/boot/dts/stm32mp157c-dhcom-picoitx.dts rename to arch/arm/boot/dts/st/stm32mp157c-dhcom-picoitx.dts diff --git a/arch/arm/boot/dts/stm32mp157c-dk2-scmi.dts b/arch/arm/boot/dts/st/stm32mp157c-dk2-scmi.dts similarity index 90% rename from arch/arm/boot/dts/stm32mp157c-dk2-scmi.dts rename to arch/arm/boot/dts/st/stm32mp157c-dk2-scmi.dts index 97e4f94b0a24eeaedc34af98cccfbb76f7877152..39358d9020003153e9c3ba1a523675a6118d81be 100644 --- a/arch/arm/boot/dts/stm32mp157c-dk2-scmi.dts +++ b/arch/arm/boot/dts/st/stm32mp157c-dk2-scmi.dts @@ -61,8 +61,11 @@ resets = <&scmi_reset RST_SCMI_MDMA>; }; -&mlahb { - resets = <&scmi_reset RST_SCMI_MCU>; +&m4_rproc { + /delete-property/ st,syscfg-holdboot; + resets = <&scmi_reset RST_SCMI_MCU>, + <&scmi_reset RST_SCMI_MCU_HOLD_BOOT>; + reset-names = "mcu_rst", "hold_boot"; }; &rcc { diff --git a/arch/arm/boot/dts/stm32mp157c-dk2.dts b/arch/arm/boot/dts/st/stm32mp157c-dk2.dts similarity index 92% rename from arch/arm/boot/dts/stm32mp157c-dk2.dts rename to arch/arm/boot/dts/st/stm32mp157c-dk2.dts index ab13e340f4ef58fa837bf6b4971dee2ca0b8e157..4bef2300ed7ca78dd36435f65702d2dcf91f83e5 100644 --- a/arch/arm/boot/dts/stm32mp157c-dk2.dts +++ b/arch/arm/boot/dts/st/stm32mp157c-dk2.dts @@ -31,10 +31,15 @@ }; &dsi { + #address-cells = <1>; + #size-cells = <0>; status = "okay"; phy-dsi-supply = <®18>; ports { + #address-cells = <1>; + #size-cells = <0>; + port@0 { reg = <0>; dsi_in: endpoint { @@ -82,6 +87,9 @@ status = "okay"; port { + #address-cells = <1>; + #size-cells = <0>; + ltdc_ep1_out: endpoint@1 { reg = <1>; remote-endpoint = <&dsi_in>; diff --git a/arch/arm/boot/dts/stm32mp157c-ed1-scmi.dts b/arch/arm/boot/dts/st/stm32mp157c-ed1-scmi.dts similarity index 90% rename from arch/arm/boot/dts/stm32mp157c-ed1-scmi.dts rename to arch/arm/boot/dts/st/stm32mp157c-ed1-scmi.dts index 9cf0a44d2f47e9e0d0329d896709b07b3d91465e..07ea765a4553a5f6a21ed498b8412bd5cfb3dd18 100644 --- a/arch/arm/boot/dts/stm32mp157c-ed1-scmi.dts +++ b/arch/arm/boot/dts/st/stm32mp157c-ed1-scmi.dts @@ -60,8 +60,11 @@ resets = <&scmi_reset RST_SCMI_MDMA>; }; -&mlahb { - resets = <&scmi_reset RST_SCMI_MCU>; +&m4_rproc { + /delete-property/ st,syscfg-holdboot; + resets = <&scmi_reset RST_SCMI_MCU>, + <&scmi_reset RST_SCMI_MCU_HOLD_BOOT>; + reset-names = "mcu_rst", "hold_boot"; }; &rcc { diff --git a/arch/arm/boot/dts/stm32mp157c-ed1.dts b/arch/arm/boot/dts/st/stm32mp157c-ed1.dts similarity index 97% rename from arch/arm/boot/dts/stm32mp157c-ed1.dts rename to arch/arm/boot/dts/st/stm32mp157c-ed1.dts index 8beb901be5065d95b338fc3e098a99247a006f7e..66ed5f9921ba14d96c5dcc2cc6f4c53cce3f54c9 100644 --- a/arch/arm/boot/dts/stm32mp157c-ed1.dts +++ b/arch/arm/boot/dts/st/stm32mp157c-ed1.dts @@ -103,10 +103,20 @@ vref-supply = <&vdda>; status = "disabled"; adc1: adc@0 { - st,adc-channels = <0 1 6>; - /* 16.5 ck_cycles sampling time */ - st,min-sample-time-nsecs = <400>; status = "okay"; + channel@0 { + reg = <0>; + /* 16.5 ck_cycles sampling time */ + st,min-sample-time-ns = <400>; + }; + channel@1 { + reg = <1>; + st,min-sample-time-ns = <400>; + }; + channel@6 { + reg = <6>; + st,min-sample-time-ns = <400>; + }; }; }; diff --git a/arch/arm/boot/dts/stm32mp157c-emsbc-argon.dts b/arch/arm/boot/dts/st/stm32mp157c-emsbc-argon.dts similarity index 100% rename from arch/arm/boot/dts/stm32mp157c-emsbc-argon.dts rename to arch/arm/boot/dts/st/stm32mp157c-emsbc-argon.dts diff --git a/arch/arm/boot/dts/stm32mp157c-emstamp-argon.dtsi b/arch/arm/boot/dts/st/stm32mp157c-emstamp-argon.dtsi similarity index 99% rename from arch/arm/boot/dts/stm32mp157c-emstamp-argon.dtsi rename to arch/arm/boot/dts/st/stm32mp157c-emstamp-argon.dtsi index b01470a9a3d5320478feeb367daed20595ee1b37..94e38141af6725ddac3bdbdf92befd449f7b4254 100644 --- a/arch/arm/boot/dts/stm32mp157c-emstamp-argon.dtsi +++ b/arch/arm/boot/dts/st/stm32mp157c-emstamp-argon.dtsi @@ -97,9 +97,11 @@ adc1: adc@0 { pinctrl-names = "default"; pinctrl-0 = <&adc1_in6_pins_a>; - st,min-sample-time-nsecs = <5000>; - st,adc-channels = <6>; status = "disabled"; + channel@6 { + reg = <6>; + st,min-sample-time-ns = <5000>; + }; }; adc2: adc@100 { diff --git a/arch/arm/boot/dts/stm32mp157c-ev1-scmi.dts b/arch/arm/boot/dts/st/stm32mp157c-ev1-scmi.dts similarity index 90% rename from arch/arm/boot/dts/stm32mp157c-ev1-scmi.dts rename to arch/arm/boot/dts/st/stm32mp157c-ev1-scmi.dts index 3b9dd6f4ccc96aabb22ddc6ad7a0b9913a394d35..813086ec248959295707f0b26dabc8c77f62c10c 100644 --- a/arch/arm/boot/dts/stm32mp157c-ev1-scmi.dts +++ b/arch/arm/boot/dts/st/stm32mp157c-ev1-scmi.dts @@ -66,8 +66,11 @@ resets = <&scmi_reset RST_SCMI_MDMA>; }; -&mlahb { - resets = <&scmi_reset RST_SCMI_MCU>; +&m4_rproc { + /delete-property/ st,syscfg-holdboot; + resets = <&scmi_reset RST_SCMI_MCU>, + <&scmi_reset RST_SCMI_MCU_HOLD_BOOT>; + reset-names = "mcu_rst", "hold_boot"; }; &rcc { diff --git a/arch/arm/boot/dts/stm32mp157c-ev1.dts b/arch/arm/boot/dts/st/stm32mp157c-ev1.dts similarity index 97% rename from arch/arm/boot/dts/stm32mp157c-ev1.dts rename to arch/arm/boot/dts/st/stm32mp157c-ev1.dts index ba8e9d9a42fafd7a4957bc99c2d868087518fc3d..af3800501875c011965df2de42582c4d5bab117c 100644 --- a/arch/arm/boot/dts/stm32mp157c-ev1.dts +++ b/arch/arm/boot/dts/st/stm32mp157c-ev1.dts @@ -101,9 +101,14 @@ &dsi { phy-dsi-supply = <®18>; + #address-cells = <1>; + #size-cells = <0>; status = "okay"; ports { + #address-cells = <1>; + #size-cells = <0>; + port@0 { reg = <0>; dsi_in: endpoint { @@ -119,7 +124,7 @@ }; }; - panel-dsi@0 { + panel@0 { compatible = "raydium,rm68200"; reg = <0>; reset-gpios = <&gpiof 15 GPIO_ACTIVE_LOW>; @@ -185,7 +190,9 @@ reg = <0x3c>; clocks = <&clk_ext_camera>; clock-names = "xclk"; + AVDD-supply = <&v2v8>; DOVDD-supply = <&v2v8>; + DVDD-supply = <&v2v8>; powerdown-gpios = <&stmfx_pinctrl 18 (GPIO_ACTIVE_HIGH | GPIO_PUSH_PULL)>; reset-gpios = <&stmfx_pinctrl 19 (GPIO_ACTIVE_LOW | GPIO_PUSH_PULL)>; rotation = <180>; @@ -239,8 +246,7 @@ status = "okay"; port { - ltdc_ep0_out: endpoint@0 { - reg = <0>; + ltdc_ep0_out: endpoint { remote-endpoint = <&dsi_in>; }; }; diff --git a/arch/arm/boot/dts/stm32mp157c-lxa-mc1.dts b/arch/arm/boot/dts/st/stm32mp157c-lxa-mc1.dts similarity index 99% rename from arch/arm/boot/dts/stm32mp157c-lxa-mc1.dts rename to arch/arm/boot/dts/st/stm32mp157c-lxa-mc1.dts index 407ed3952f75daf14f8c88e78fe981fca929d563..eada9cf257be9c9946a3a4417f2b0744e0636ca1 100644 --- a/arch/arm/boot/dts/stm32mp157c-lxa-mc1.dts +++ b/arch/arm/boot/dts/st/stm32mp157c-lxa-mc1.dts @@ -161,8 +161,7 @@ status = "okay"; port { - ltdc_ep0_out: endpoint@0 { - reg = <0>; + ltdc_ep0_out: endpoint { remote-endpoint = <&panel_input>; }; }; diff --git a/arch/arm/boot/dts/stm32mp157c-odyssey-som.dtsi b/arch/arm/boot/dts/st/stm32mp157c-odyssey-som.dtsi similarity index 100% rename from arch/arm/boot/dts/stm32mp157c-odyssey-som.dtsi rename to arch/arm/boot/dts/st/stm32mp157c-odyssey-som.dtsi diff --git a/arch/arm/boot/dts/stm32mp157c-odyssey.dts b/arch/arm/boot/dts/st/stm32mp157c-odyssey.dts similarity index 100% rename from arch/arm/boot/dts/stm32mp157c-odyssey.dts rename to arch/arm/boot/dts/st/stm32mp157c-odyssey.dts diff --git a/arch/arm/boot/dts/st/stm32mp157c-phycore-stm32mp1-3.dts b/arch/arm/boot/dts/st/stm32mp157c-phycore-stm32mp1-3.dts new file mode 100644 index 0000000000000000000000000000000000000000..28d7203264cea5cbaa3d1594eabe113eab65607e --- /dev/null +++ b/arch/arm/boot/dts/st/stm32mp157c-phycore-stm32mp1-3.dts @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) Phytec GmbH 2019-2020 - All Rights Reserved + * Author: Dom VOVARD . + */ + +/dts-v1/; + +#include +#include "stm32mp157.dtsi" +#include "stm32mp15xc.dtsi" +#include "stm32mp15xxac-pinctrl.dtsi" +#include "stm32mp157c-phycore-stm32mp15-som.dtsi" + +/ { + model = "PHYTEC phyCORE-STM32MP1-3 Dev Board"; + compatible = "phytec,phycore-stm32mp1-3", + "phytec,phycore-stm32mp157c-som", "st,stm32mp157"; + + aliases { + mmc0 = &sdmmc1; + mmc1 = &sdmmc2; + mmc2 = &sdmmc3; + serial0 = &uart4; + serial1 = &usart3; + serial2 = &usart1; + }; +}; + +&cryp1 { + status = "okay"; +}; + +&dts { + status = "okay"; +}; + +&fmc { + status = "disabled"; +}; + +&gpu { + status = "okay"; +}; + +&i2c4_eeprom { + status = "okay"; +}; + +&i2c4_rtc { + status = "okay"; +}; + +&qspi { + status = "okay"; +}; + +&sdmmc2 { + status = "okay"; +}; diff --git a/arch/arm/boot/dts/st/stm32mp157c-phycore-stm32mp15-som.dtsi b/arch/arm/boot/dts/st/stm32mp157c-phycore-stm32mp15-som.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..4e8b2d2b30c7abcb3a1e5afa1ffcac13348bb177 --- /dev/null +++ b/arch/arm/boot/dts/st/stm32mp157c-phycore-stm32mp15-som.dtsi @@ -0,0 +1,577 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) 2022-2023 Steffen Trumtrar + * Copyright (C) Phytec GmbH 2019-2020 - All Rights Reserved + * Author: Dom VOVARD . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "stm32mp15-pinctrl.dtsi" + +/ { + model = "PHYTEC phyCORE-STM32MP15 SOM"; + compatible = "phytec,phycore-stm32mp157c-som", "st,stm32mp157"; + + aliases { + ethernet0 = ðernet0; + rtc0 = &i2c4_rtc; + rtc1 = &rtc; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + gpio-keys { + compatible = "gpio-keys"; + + key-home { + label = "Home"; + gpios = <&gpioa 13 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + + key-enter { + label = "Enter"; + gpios = <&gpioa 14 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + + retram: retram@38000000 { + compatible = "shared-dma-pool"; + reg = <0x38000000 0x10000>; + no-map; + }; + + mcuram: mcuram@30000000 { + compatible = "shared-dma-pool"; + reg = <0x30000000 0x40000>; + no-map; + }; + + mcuram2: mcuram2@10000000 { + compatible = "shared-dma-pool"; + reg = <0x10000000 0x40000>; + no-map; + }; + + vdev0vring0: vdev0vring0@10040000 { + compatible = "shared-dma-pool"; + reg = <0x10040000 0x1000>; + no-map; + }; + + vdev0vring1: vdev0vring1@10041000 { + compatible = "shared-dma-pool"; + reg = <0x10041000 0x1000>; + no-map; + }; + + vdev0buffer: vdev0buffer@10042000 { + compatible = "shared-dma-pool"; + reg = <0x10042000 0x4000>; + no-map; + }; + }; + + sound { + compatible = "audio-graph-card"; + label = "STM32MP1-PHYCORE"; + routing = + "Playback", "MCLK", /* Set a route between "MCLK" and "playback" widgets */ + "Capture", "MCLK"; + dais = <&sai2b_port>, + <&sai2a_port>; + }; + + regulator_vin: regulator { + compatible = "regulator-fixed"; + regulator-name = "vin"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-always-on; + }; +}; + +ðernet0 { + pinctrl-0 = <ðernet0_rgmii_pins_d>; + pinctrl-1 = <ðernet0_rgmii_sleep_pins_d>; + pinctrl-names = "default", "sleep"; + phy-mode = "rgmii-id"; + max-speed = <1000>; + phy-handle = <&phy0>; + st,eth-clk-sel; + status = "okay"; + + mdio { + #address-cells = <1>; + #size-cells = <0>; + compatible = "snps,dwmac-mdio"; + + phy0: ethernet-phy@1 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <1>; + interrupt-parent = <&gpiog>; + interrupts = <12 IRQ_TYPE_EDGE_FALLING>; + ti,rx-internal-delay = ; + ti,tx-internal-delay = ; + ti,fifo-depth = ; + ti,min-output-impedance; + enet-phy-lane-no-swap; + ti,clk-output-sel = ; + }; + }; +}; + +&i2c1 { + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&i2c1_pins_b>; + pinctrl-1 = <&i2c1_sleep_pins_b>; + i2c-scl-rising-time-ns = <100>; + i2c-scl-falling-time-ns = <7>; + status = "okay"; + + codec@18 { + compatible = "ti,tlv320aic3007"; + reg = <0x18>; + #sound-dai-cells = <0>; + + ai3x-micbias-vg = <2>; + + AVDD-supply = <&v3v3>; + IOVDD-supply = <&v3v3>; + DRVDD-supply = <&v3v3>; + DVDD-supply = <&v1v8_audio>; + + clocks = <&sai2b>; + + port { + #address-cells = <1>; + #size-cells = <0>; + + tlv320_tx_endpoint: endpoint@0 { + reg = <0>; + remote-endpoint = <&sai2b_endpoint>; + frame-master; + bitclock-master; + }; + + tlv320_rx_endpoint: endpoint@1 { + reg = <1>; + remote-endpoint = <&sai2a_endpoint>; + frame-master; + bitclock-master; + }; + }; + }; + + touch@44 { + compatible = "st,stmpe811"; + reg = <0x44>; + interrupts = <3 IRQ_TYPE_EDGE_FALLING>; + interrupt-parent = <&gpioi>; + vio-supply = <&v3v3>; + vcc-supply = <&v3v3>; + + touchscreen { + compatible = "st,stmpe-ts"; + st,sample-time = <4>; + st,mod-12b = <1>; + st,ref-sel = <0>; + st,adc-freq = <1>; + st,ave-ctrl = <1>; + st,touch-det-delay = <2>; + st,settling = <2>; + st,fraction-z = <7>; + st,i-drive = <1>; + }; + }; + + leds@62 { + compatible = "nxp,pca9533"; + reg = <0x62>; + + led-0 { + color = ; + function = LED_FUNCTION_POWER; + type = ; + }; + + led-1 { + color = ; + function = LED_FUNCTION_POWER; + type = ; + }; + + led-2 { + color = ; + function = LED_FUNCTION_HEARTBEAT; + type = ; + linux,default-trigger = "heartbeat"; + }; + }; +}; + +&i2c4 { + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&i2c4_pins_a>; + pinctrl-1 = <&i2c4_sleep_pins_a>; + i2c-scl-rising-time-ns = <185>; + i2c-scl-falling-time-ns = <20>; + status = "okay"; + + pmic@33 { + compatible = "st,stpmic1"; + reg = <0x33>; + interrupts-extended = <&gpioa 0 IRQ_TYPE_EDGE_FALLING>; + interrupt-controller; + #interrupt-cells = <2>; + + regulators { + compatible = "st,stpmic1-regulators"; + buck1-supply = <®ulator_vin>; + buck2-supply = <®ulator_vin>; + buck3-supply = <®ulator_vin>; + buck4-supply = <®ulator_vin>; + ldo1-supply = <&v3v3>; + ldo2-supply = <&v3v3>; + ldo3-supply = <&vdd_ddr>; + ldo4-supply = <®ulator_vin>; + ldo5-supply = <&v3v3>; + ldo6-supply = <&v3v3>; + boost-supply = <®ulator_vin>; + pwr_sw1-supply = <&bst_out>; + pwr_sw2-supply = <&bst_out>; + + vddcore: buck1 { + regulator-name = "vddcore"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1350000>; + regulator-always-on; + regulator-initial-mode = <0>; + }; + + vdd_ddr: buck2 { + regulator-name = "vdd_ddr"; + regulator-min-microvolt = <1350000>; + regulator-max-microvolt = <1350000>; + regulator-always-on; + regulator-initial-mode = <0>; + }; + + vdd: buck3 { + regulator-name = "vdd"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + st,mask-reset; + regulator-initial-mode = <0>; + }; + + v3v3: buck4 { + regulator-name = "v3v3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-initial-mode = <0>; + }; + + v1v8_audio: ldo1 { + regulator-name = "v1v8_audio"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + interrupts = ; + + }; + + vdd_eth_2v5: ldo2 { + regulator-name = "dd_eth_2v5"; + regulator-min-microvolt = <2500000>; + regulator-max-microvolt = <2500000>; + regulator-always-on; + interrupts = ; + + }; + + vtt_ddr: ldo3 { + regulator-name = "vtt_ddr"; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <750000>; + regulator-always-on; + regulator-over-current-protection; + }; + + vdd_usb: ldo4 { + regulator-name = "vdd_usb"; + interrupts = ; + }; + + vdda: ldo5 { + regulator-name = "vdda"; + regulator-min-microvolt = <2900000>; + regulator-max-microvolt = <2900000>; + interrupts = ; + regulator-boot-on; + }; + + vdd_eth_1v0: ldo6 { + regulator-name = "vdd_eth_1v0"; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1000000>; + regulator-always-on; + interrupts = ; + + }; + + vref_ddr: vref_ddr { + regulator-name = "vref_ddr"; + regulator-always-on; + }; + + bst_out: boost { + regulator-name = "bst_out"; + interrupts = ; + }; + + vbus_otg: pwr_sw1 { + regulator-name = "vbus_otg"; + interrupts = ; + regulator-active-discharge = <1>; + }; + + vbus_sw: pwr_sw2 { + regulator-name = "vbus_sw"; + interrupts = ; + regulator-active-discharge = <1>; + }; + }; + + onkey { + compatible = "st,stpmic1-onkey"; + interrupts = , + ; + interrupt-names = "onkey-falling", + "onkey-rising"; + power-off-time-sec = <10>; + }; + + watchdog { + compatible = "st,stpmic1-wdt"; + }; + }; + + i2c4_eeprom: eeprom@50 { + compatible = "microchip,24c32", + "atmel,24c32"; + reg = <0x50>; + }; + + i2c4_rtc: rtc@52 { + compatible = "microcrystal,rv3028"; + reg = <0x52>; + }; +}; + +&ipcc { + status = "okay"; +}; + +&iwdg2 { + timeout-sec = <32>; + status = "okay"; +}; + +&m_can2 { + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&m_can2_pins_a>; + pinctrl-1 = <&m_can2_sleep_pins_a>; + status = "okay"; +}; + +&m4_rproc { + memory-region = <&retram>, <&mcuram>, <&mcuram2>, <&vdev0vring0>, + <&vdev0vring1>, <&vdev0buffer>; + mboxes = <&ipcc 0>, <&ipcc 1>, <&ipcc 2>, <&ipcc 3>; + mbox-names = "vq0", "vq1", "shutdown", "detach"; + interrupt-parent = <&exti>; + interrupts = <68 1>; + status = "okay"; +}; + +&pwr_regulators { + vdd-supply = <&vdd>; + vdd_3v3_usbfs-supply = <&vdd_usb>; +}; + +&qspi { + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&qspi_clk_pins_a &qspi_bk1_pins_a>; + pinctrl-1 = <&qspi_clk_sleep_pins_a &qspi_bk1_sleep_pins_a>; + status = "okay"; + + flash0: flash@0 { + compatible = "winbond,w25q128", "jedec,spi-nor"; + reg = <0>; + spi-rx-bus-width = <4>; + spi-max-frequency = <50000000>; + m25p,fast-read; + #address-cells = <1>; + #size-cells = <1>; + }; +}; + +&rng1 { + status = "okay"; +}; + +&rtc { + status = "okay"; +}; + +&sai2 { + clocks = <&rcc SAI2>, <&rcc PLL3_Q>, <&rcc PLL3_R>; + clock-names = "pclk", "x8k", "x11k"; + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&sai2a_pins_b>, <&sai2b_pins_d>; + pinctrl-1 = <&sai2a_sleep_pins_b>, <&sai2b_sleep_pins_d>; + status = "okay"; +}; + +&sai2a { + dma-names = "rx"; + st,sync = <&sai2b 2>; + clocks = <&rcc SAI2_K>, <&sai2b>; + clock-names = "sai_ck", "MCLK"; + #clock-cells = <0>; + + sai2a_port: port { + sai2a_endpoint: endpoint { + remote-endpoint = <&tlv320_rx_endpoint>; + mclk-fs = <256>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <16>; + }; + }; +}; + +&sai2b { + dma-names = "tx"; + #clock-cells = <0>; + + sai2b_port: port { + sai2b_endpoint: endpoint { + remote-endpoint = <&tlv320_tx_endpoint>; + mclk-fs = <256>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <16>; + }; + }; +}; + +&sdmmc1 { + pinctrl-names = "default", "opendrain", "sleep"; + pinctrl-0 = <&sdmmc1_b4_pins_b>; + pinctrl-1 = <&sdmmc1_b4_od_pins_b>; + pinctrl-2 = <&sdmmc1_b4_sleep_pins_b>; + cd-gpios = <&gpiof 3 GPIO_ACTIVE_LOW>; + disable-wp; + st,neg-edge; + bus-width = <4>; + vmmc-supply = <&v3v3>; + status = "okay"; +}; + +&sdmmc2 { + pinctrl-names = "default", "opendrain", "sleep"; + pinctrl-0 = <&sdmmc2_b4_pins_a &sdmmc2_d47_pins_e>; + pinctrl-1 = <&sdmmc2_b4_od_pins_a &sdmmc2_d47_pins_e>; + pinctrl-2 = <&sdmmc2_b4_sleep_pins_a &sdmmc2_d47_sleep_pins_e>; + non-removable; + no-sd; + no-sdio; + st,neg-edge; + bus-width = <8>; + vmmc-supply = <&v3v3>; + vqmmc-supply = <&v3v3>; + mmc-ddr-3_3v; +}; + +&spi1 { + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&spi1_pins_a>; + pinctrl-1 = <&spi1_sleep_pins_a>; + cs-gpios = <&gpioz 3 0>; + status = "okay"; +}; + +&uart4 { + pinctrl-names = "default", "sleep", "idle"; + pinctrl-0 = <&uart4_pins_a>; + pinctrl-1 = <&uart4_sleep_pins_a>; + pinctrl-2 = <&uart4_idle_pins_a>; + pinctrl-3 = <&uart4_pins_a>; + /delete-property/dmas; + /delete-property/dma-names; + status = "okay"; +}; + +&usart1 { + pinctrl-names = "default", "sleep", "idle"; + pinctrl-0 = <&usart1_pins_b &usart1_pins_a>; + pinctrl-1 = <&usart1_sleep_pins_b &usart1_sleep_pins_a>; + pinctrl-2 = <&usart1_idle_pins_b &usart1_idle_pins_a>; + uart-has-rtscts; + status = "okay"; +}; + +&usart3 { + pinctrl-names = "default", "sleep", "idle"; + pinctrl-0 = <&usart3_pins_a>; + pinctrl-1 = <&usart3_sleep_pins_a>; + pinctrl-2 = <&usart3_idle_pins_a>; + status = "okay"; +}; + +&usbh_ehci { + phys = <&usbphyc_port0>; + phy-names = "usb"; + status = "okay"; +}; + +&usbh_ohci { + phys = <&usbphyc_port0>; + phy-names = "usb"; + status = "okay"; +}; + +&usbotg_hs { + phys = <&usbphyc_port1 0>; + phy-names = "usb2-phy"; + status = "okay"; +}; + +&usbphyc { + status = "okay"; +}; + +&usbphyc_port0 { + phy-supply = <&vdd_usb>; +}; + +&usbphyc_port1 { + phy-supply = <&vdd_usb>; +}; diff --git a/arch/arm/boot/dts/stm32mp15xc.dtsi b/arch/arm/boot/dts/st/stm32mp15xc.dtsi similarity index 100% rename from arch/arm/boot/dts/stm32mp15xc.dtsi rename to arch/arm/boot/dts/st/stm32mp15xc.dtsi diff --git a/arch/arm/boot/dts/stm32mp15xx-dhcom-drc02.dtsi b/arch/arm/boot/dts/st/stm32mp15xx-dhcom-drc02.dtsi similarity index 100% rename from arch/arm/boot/dts/stm32mp15xx-dhcom-drc02.dtsi rename to arch/arm/boot/dts/st/stm32mp15xx-dhcom-drc02.dtsi diff --git a/arch/arm/boot/dts/stm32mp15xx-dhcom-pdk2.dtsi b/arch/arm/boot/dts/st/stm32mp15xx-dhcom-pdk2.dtsi similarity index 96% rename from arch/arm/boot/dts/stm32mp15xx-dhcom-pdk2.dtsi rename to arch/arm/boot/dts/st/stm32mp15xx-dhcom-pdk2.dtsi index 4709677151aac92f56cee5e8caa6cb4de6387fff..46b87a27d8b378fa52ee8ede3a23dd9a4c7424d7 100644 --- a/arch/arm/boot/dts/stm32mp15xx-dhcom-pdk2.dtsi +++ b/arch/arm/boot/dts/st/stm32mp15xx-dhcom-pdk2.dtsi @@ -137,10 +137,13 @@ sound { compatible = "audio-graph-card"; - routing = - "MIC_IN", "Capture", - "Capture", "Mic Bias", - "Playback", "HP_OUT"; + widgets = "Headphone", "Headphone Jack", + "Line", "Line In Jack", + "Microphone", "Microphone Jack"; + routing = "Headphone Jack", "HP_OUT", + "LINE_IN", "Line In Jack", + "MIC_IN", "Microphone Jack", + "Microphone Jack", "Mic Bias"; dais = <&sai2a_port &sai2b_port>; status = "okay"; }; diff --git a/arch/arm/boot/dts/stm32mp15xx-dhcom-picoitx.dtsi b/arch/arm/boot/dts/st/stm32mp15xx-dhcom-picoitx.dtsi similarity index 100% rename from arch/arm/boot/dts/stm32mp15xx-dhcom-picoitx.dtsi rename to arch/arm/boot/dts/st/stm32mp15xx-dhcom-picoitx.dtsi diff --git a/arch/arm/boot/dts/stm32mp15xx-dhcom-som.dtsi b/arch/arm/boot/dts/st/stm32mp15xx-dhcom-som.dtsi similarity index 98% rename from arch/arm/boot/dts/stm32mp15xx-dhcom-som.dtsi rename to arch/arm/boot/dts/st/stm32mp15xx-dhcom-som.dtsi index c06edd2eacb0cd3f35850f0247bda1dedab4f718..e61df23d361a764dd53d08fc86e476df2f9b5d7e 100644 --- a/arch/arm/boot/dts/stm32mp15xx-dhcom-som.dtsi +++ b/arch/arm/boot/dts/st/stm32mp15xx-dhcom-som.dtsi @@ -80,17 +80,19 @@ vdda-supply = <&vdda>; vref-supply = <&vdda>; status = "okay"; +}; - adc1: adc@0 { - st,min-sample-time-nsecs = <5000>; - st,adc-channels = <0>; - status = "okay"; +&adc1 { + channel@0 { + reg = <0>; + st,min-sample-time-ns = <5000>; }; +}; - adc2: adc@100 { - st,adc-channels = <1>; - st,min-sample-time-nsecs = <5000>; - status = "okay"; +&adc2 { + channel@1 { + reg = <1>; + st,min-sample-time-ns = <5000>; }; }; diff --git a/arch/arm/boot/dts/stm32mp15xx-dhcor-avenger96.dtsi b/arch/arm/boot/dts/st/stm32mp15xx-dhcor-avenger96.dtsi similarity index 94% rename from arch/arm/boot/dts/stm32mp15xx-dhcor-avenger96.dtsi rename to arch/arm/boot/dts/st/stm32mp15xx-dhcor-avenger96.dtsi index 50af4a27d6be4d19731ab734717649b41759be04..0069ad75d55e5e14ba530756a314e3c83fc889be 100644 --- a/arch/arm/boot/dts/stm32mp15xx-dhcor-avenger96.dtsi +++ b/arch/arm/boot/dts/st/stm32mp15xx-dhcor-avenger96.dtsi @@ -87,7 +87,7 @@ sound { compatible = "audio-graph-card"; - label = "STM32MP1-AV96-HDMI"; + label = "STM32-AV96-HDMI"; dais = <&sai2a_port>; status = "okay"; }; @@ -111,17 +111,39 @@ vdda-supply = <&vdda>; vref-supply = <&vdda>; status = "okay"; +}; - adc1: adc@0 { - st,adc-channels = <0 1 6>; - st,min-sample-time-nsecs = <5000>; - status = "okay"; +&adc1 { + channel@0 { + reg = <0>; + st,min-sample-time-ns = <5000>; }; - adc2: adc@100 { - st,adc-channels = <0 1 2>; - st,min-sample-time-nsecs = <5000>; - status = "okay"; + channel@1 { + reg = <1>; + st,min-sample-time-ns = <5000>; + }; + + channel@6 { + reg = <6>; + st,min-sample-time-ns = <5000>; + }; +}; + +&adc2 { + channel@0 { + reg = <0>; + st,min-sample-time-ns = <5000>; + }; + + channel@1 { + reg = <1>; + st,min-sample-time-ns = <5000>; + }; + + channel@2 { + reg = <2>; + st,min-sample-time-ns = <5000>; }; }; @@ -321,6 +343,12 @@ }; }; }; + + dh_mac_eeprom: eeprom@53 { + compatible = "atmel,24c02"; + reg = <0x53>; + pagesize = <16>; + }; }; <dc { @@ -330,11 +358,7 @@ status = "okay"; port { - #address-cells = <1>; - #size-cells = <0>; - - ltdc_ep0_out: endpoint@0 { - reg = <0>; + ltdc_ep0_out: endpoint { remote-endpoint = <&adv7513_in>; }; }; @@ -452,7 +476,7 @@ pinctrl-names = "default", "sleep"; pinctrl-0 = <&usart2_pins_a>; pinctrl-1 = <&usart2_sleep_pins_a>; - st,hw-flow-ctrl; + uart-has-rtscts; /delete-property/dmas; /delete-property/dma-names; status = "okay"; diff --git a/arch/arm/boot/dts/stm32mp15xx-dhcor-drc-compact.dtsi b/arch/arm/boot/dts/st/stm32mp15xx-dhcor-drc-compact.dtsi similarity index 92% rename from arch/arm/boot/dts/stm32mp15xx-dhcor-drc-compact.dtsi rename to arch/arm/boot/dts/st/stm32mp15xx-dhcor-drc-compact.dtsi index c32c160f97f204cb6951a5f5893044b12a737edc..92d906bfd5d7d696e73299e0dbc8d0a6cb5f9275 100644 --- a/arch/arm/boot/dts/stm32mp15xx-dhcor-drc-compact.dtsi +++ b/arch/arm/boot/dts/st/stm32mp15xx-dhcor-drc-compact.dtsi @@ -57,15 +57,35 @@ status = "okay"; adc1: adc@0 { - st,adc-channels = <0 1 6>; - st,min-sample-time-nsecs = <5000>; status = "okay"; + channel@0 { + reg = <0>; + st,min-sample-time-ns = <5000>; + }; + channel@1 { + reg = <1>; + st,min-sample-time-ns = <5000>; + }; + channel@6 { + reg = <6>; + st,min-sample-time-ns = <5000>; + }; }; adc2: adc@100 { - st,adc-channels = <0 1 2>; - st,min-sample-time-nsecs = <5000>; status = "okay"; + channel@0 { + reg = <0>; + st,min-sample-time-ns = <5000>; + }; + channel@1 { + reg = <1>; + st,min-sample-time-ns = <5000>; + }; + channel@2 { + reg = <2>; + st,min-sample-time-ns = <5000>; + }; }; }; @@ -192,6 +212,12 @@ reg = <0x50>; pagesize = <16>; }; + + dh_mac_eeprom: eeprom@53 { + compatible = "atmel,24c02"; + reg = <0x53>; + pagesize = <16>; + }; }; &sdmmc1 { /* MicroSD */ diff --git a/arch/arm/boot/dts/stm32mp15xx-dhcor-io1v8.dtsi b/arch/arm/boot/dts/st/stm32mp15xx-dhcor-io1v8.dtsi similarity index 100% rename from arch/arm/boot/dts/stm32mp15xx-dhcor-io1v8.dtsi rename to arch/arm/boot/dts/st/stm32mp15xx-dhcor-io1v8.dtsi diff --git a/arch/arm/boot/dts/stm32mp15xx-dhcor-som.dtsi b/arch/arm/boot/dts/st/stm32mp15xx-dhcor-som.dtsi similarity index 98% rename from arch/arm/boot/dts/stm32mp15xx-dhcor-som.dtsi rename to arch/arm/boot/dts/st/stm32mp15xx-dhcor-som.dtsi index bb40fb46da81d559084f680c11c5c072efa83073..bba19f21e52776efd8a41c086edc9a30ce4cf7f9 100644 --- a/arch/arm/boot/dts/stm32mp15xx-dhcor-som.dtsi +++ b/arch/arm/boot/dts/st/stm32mp15xx-dhcor-som.dtsi @@ -213,12 +213,6 @@ status = "disabled"; }; }; - - eeprom@53 { - compatible = "atmel,24c02"; - reg = <0x53>; - pagesize = <16>; - }; }; &ipcc { diff --git a/arch/arm/boot/dts/stm32mp15xx-dhcor-testbench.dtsi b/arch/arm/boot/dts/st/stm32mp15xx-dhcor-testbench.dtsi similarity index 86% rename from arch/arm/boot/dts/stm32mp15xx-dhcor-testbench.dtsi rename to arch/arm/boot/dts/st/stm32mp15xx-dhcor-testbench.dtsi index 5fdb74b652acaf1003a7156312f7dcafbab87683..ab7f0ba49639688f338930aae81d0e0acd59f86d 100644 --- a/arch/arm/boot/dts/stm32mp15xx-dhcor-testbench.dtsi +++ b/arch/arm/boot/dts/st/stm32mp15xx-dhcor-testbench.dtsi @@ -41,15 +41,35 @@ status = "okay"; adc1: adc@0 { - st,adc-channels = <0 1 6>; - st,min-sample-time-nsecs = <5000>; status = "okay"; + channel@0 { + reg = <0>; + st,min-sample-time-ns = <5000>; + }; + channel@1 { + reg = <1>; + st,min-sample-time-ns = <5000>; + }; + channel@6 { + reg = <6>; + st,min-sample-time-ns = <5000>; + }; }; adc2: adc@100 { - st,adc-channels = <0 1 2>; - st,min-sample-time-nsecs = <5000>; status = "okay"; + channel@0 { + reg = <0>; + st,min-sample-time-ns = <5000>; + }; + channel@1 { + reg = <1>; + st,min-sample-time-ns = <5000>; + }; + channel@2 { + reg = <2>; + st,min-sample-time-ns = <5000>; + }; }; }; @@ -90,6 +110,14 @@ }; }; +&i2c4 { + dh_mac_eeprom: eeprom@53 { + compatible = "atmel,24c02"; + reg = <0x53>; + pagesize = <16>; + }; +}; + &sdmmc1 { pinctrl-names = "default", "opendrain", "sleep"; pinctrl-0 = <&sdmmc1_b4_pins_a &sdmmc1_dir_pins_b>; diff --git a/arch/arm/boot/dts/stm32mp15xx-dkx.dtsi b/arch/arm/boot/dts/st/stm32mp15xx-dkx.dtsi similarity index 96% rename from arch/arm/boot/dts/stm32mp15xx-dkx.dtsi rename to arch/arm/boot/dts/st/stm32mp15xx-dkx.dtsi index cefeeb00fc2286596fc796fa4d8d30e394ee2f8c..511113f2e39928ed337d2d0484c9f66ff611fd59 100644 --- a/arch/arm/boot/dts/stm32mp15xx-dkx.dtsi +++ b/arch/arm/boot/dts/st/stm32mp15xx-dkx.dtsi @@ -93,28 +93,39 @@ &adc { pinctrl-names = "default"; - pinctrl-0 = <&adc12_ain_pins_a>, <&adc12_usb_cc_pins_a>; + pinctrl-0 = <&adc12_usb_cc_pins_a>; vdd-supply = <&vdd>; vdda-supply = <&vdd>; vref-supply = <&vrefbuf>; - status = "disabled"; + status = "okay"; adc1: adc@0 { + status = "okay"; /* * Type-C USB_PWR_CC1 & USB_PWR_CC2 on in18 & in19. * Use at least 5 * RC time, e.g. 5 * (Rp + Rd) * C: * 5 * (56 + 47kOhms) * 5pF => 2.5us. * Use arbitrary margin here (e.g. 5us). */ - st,min-sample-time-nsecs = <5000>; - /* AIN connector, USB Type-C CC1 & CC2 */ - st,adc-channels = <0 1 6 13 18 19>; - status = "okay"; + channel@18 { + reg = <18>; + st,min-sample-time-ns = <5000>; + }; + channel@19 { + reg = <19>; + st,min-sample-time-ns = <5000>; + }; }; adc2: adc@100 { - /* AIN connector, USB Type-C CC1 & CC2 */ - st,adc-channels = <0 1 2 6 18 19>; - st,min-sample-time-nsecs = <5000>; status = "okay"; + /* USB Type-C CC1 & CC2 */ + channel@18 { + reg = <18>; + st,min-sample-time-ns = <5000>; + }; + channel@19 { + reg = <19>; + st,min-sample-time-ns = <5000>; + }; }; }; @@ -379,21 +390,21 @@ regulator-always-on; }; - bst_out: boost { + bst_out: boost { regulator-name = "bst_out"; interrupts = ; - }; + }; vbus_otg: pwr_sw1 { regulator-name = "vbus_otg"; interrupts = ; - }; + }; - vbus_sw: pwr_sw2 { + vbus_sw: pwr_sw2 { regulator-name = "vbus_sw"; interrupts = ; regulator-active-discharge = <1>; - }; + }; }; onkey { @@ -435,7 +446,7 @@ i2s2_port: port { i2s2_endpoint: endpoint { remote-endpoint = <&sii9022_tx_endpoint>; - format = "i2s"; + dai-format = "i2s"; mclk-fs = <256>; }; }; @@ -457,8 +468,7 @@ status = "okay"; port { - ltdc_ep0_out: endpoint@0 { - reg = <0>; + ltdc_ep0_out: endpoint { remote-endpoint = <&sii9022_in>; }; }; diff --git a/arch/arm/boot/dts/stm32mp15xx-osd32.dtsi b/arch/arm/boot/dts/st/stm32mp15xx-osd32.dtsi similarity index 100% rename from arch/arm/boot/dts/stm32mp15xx-osd32.dtsi rename to arch/arm/boot/dts/st/stm32mp15xx-osd32.dtsi diff --git a/arch/arm/boot/dts/stm32mp15xxaa-pinctrl.dtsi b/arch/arm/boot/dts/st/stm32mp15xxaa-pinctrl.dtsi similarity index 100% rename from arch/arm/boot/dts/stm32mp15xxaa-pinctrl.dtsi rename to arch/arm/boot/dts/st/stm32mp15xxaa-pinctrl.dtsi diff --git a/arch/arm/boot/dts/stm32mp15xxab-pinctrl.dtsi b/arch/arm/boot/dts/st/stm32mp15xxab-pinctrl.dtsi similarity index 100% rename from arch/arm/boot/dts/stm32mp15xxab-pinctrl.dtsi rename to arch/arm/boot/dts/st/stm32mp15xxab-pinctrl.dtsi diff --git a/arch/arm/boot/dts/stm32mp15xxac-pinctrl.dtsi b/arch/arm/boot/dts/st/stm32mp15xxac-pinctrl.dtsi similarity index 100% rename from arch/arm/boot/dts/stm32mp15xxac-pinctrl.dtsi rename to arch/arm/boot/dts/st/stm32mp15xxac-pinctrl.dtsi diff --git a/arch/arm/boot/dts/stm32mp15xxad-pinctrl.dtsi b/arch/arm/boot/dts/st/stm32mp15xxad-pinctrl.dtsi similarity index 100% rename from arch/arm/boot/dts/stm32mp15xxad-pinctrl.dtsi rename to arch/arm/boot/dts/st/stm32mp15xxad-pinctrl.dtsi diff --git a/arch/arm/boot/dts/sunplus/Makefile b/arch/arm/boot/dts/sunplus/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..868f2ea0c127a9f0250f4435c3011329ac796717 --- /dev/null +++ b/arch/arm/boot/dts/sunplus/Makefile @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0 +dtb-$(CONFIG_SOC_SP7021) += \ + sunplus-sp7021-demo-v3.dtb +dtb-$(CONFIG_SOC_SP7021) += \ + sunplus-sp7021-demo-v3.dtb diff --git a/arch/arm/boot/dts/sunplus-sp7021-achip.dtsi b/arch/arm/boot/dts/sunplus/sunplus-sp7021-achip.dtsi similarity index 100% rename from arch/arm/boot/dts/sunplus-sp7021-achip.dtsi rename to arch/arm/boot/dts/sunplus/sunplus-sp7021-achip.dtsi diff --git a/arch/arm/boot/dts/sunplus-sp7021-demo-v3.dts b/arch/arm/boot/dts/sunplus/sunplus-sp7021-demo-v3.dts similarity index 100% rename from arch/arm/boot/dts/sunplus-sp7021-demo-v3.dts rename to arch/arm/boot/dts/sunplus/sunplus-sp7021-demo-v3.dts diff --git a/arch/arm/boot/dts/sunplus-sp7021.dtsi b/arch/arm/boot/dts/sunplus/sunplus-sp7021.dtsi similarity index 100% rename from arch/arm/boot/dts/sunplus-sp7021.dtsi rename to arch/arm/boot/dts/sunplus/sunplus-sp7021.dtsi diff --git a/arch/arm/boot/dts/synaptics/Makefile b/arch/arm/boot/dts/synaptics/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..0ecccd156d185e4e32a1946eaae87ae7f68443a5 --- /dev/null +++ b/arch/arm/boot/dts/synaptics/Makefile @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0 +dtb-$(CONFIG_ARCH_BERLIN) += \ + berlin2-sony-nsz-gs7.dtb \ + berlin2cd-google-chromecast.dtb \ + berlin2cd-valve-steamlink.dtb \ + berlin2q-marvell-dmp.dtb diff --git a/arch/arm/boot/dts/berlin2-sony-nsz-gs7.dts b/arch/arm/boot/dts/synaptics/berlin2-sony-nsz-gs7.dts similarity index 100% rename from arch/arm/boot/dts/berlin2-sony-nsz-gs7.dts rename to arch/arm/boot/dts/synaptics/berlin2-sony-nsz-gs7.dts diff --git a/arch/arm/boot/dts/berlin2.dtsi b/arch/arm/boot/dts/synaptics/berlin2.dtsi similarity index 100% rename from arch/arm/boot/dts/berlin2.dtsi rename to arch/arm/boot/dts/synaptics/berlin2.dtsi diff --git a/arch/arm/boot/dts/berlin2cd-google-chromecast.dts b/arch/arm/boot/dts/synaptics/berlin2cd-google-chromecast.dts similarity index 100% rename from arch/arm/boot/dts/berlin2cd-google-chromecast.dts rename to arch/arm/boot/dts/synaptics/berlin2cd-google-chromecast.dts diff --git a/arch/arm/boot/dts/berlin2cd-valve-steamlink.dts b/arch/arm/boot/dts/synaptics/berlin2cd-valve-steamlink.dts similarity index 100% rename from arch/arm/boot/dts/berlin2cd-valve-steamlink.dts rename to arch/arm/boot/dts/synaptics/berlin2cd-valve-steamlink.dts diff --git a/arch/arm/boot/dts/berlin2cd.dtsi b/arch/arm/boot/dts/synaptics/berlin2cd.dtsi similarity index 100% rename from arch/arm/boot/dts/berlin2cd.dtsi rename to arch/arm/boot/dts/synaptics/berlin2cd.dtsi diff --git a/arch/arm/boot/dts/berlin2q-marvell-dmp.dts b/arch/arm/boot/dts/synaptics/berlin2q-marvell-dmp.dts similarity index 100% rename from arch/arm/boot/dts/berlin2q-marvell-dmp.dts rename to arch/arm/boot/dts/synaptics/berlin2q-marvell-dmp.dts diff --git a/arch/arm/boot/dts/berlin2q.dtsi b/arch/arm/boot/dts/synaptics/berlin2q.dtsi similarity index 100% rename from arch/arm/boot/dts/berlin2q.dtsi rename to arch/arm/boot/dts/synaptics/berlin2q.dtsi diff --git a/arch/arm/boot/dts/ti/Makefile b/arch/arm/boot/dts/ti/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..871079a7bc3b9fd5da47d866d25b7d70550bc2bb --- /dev/null +++ b/arch/arm/boot/dts/ti/Makefile @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 +subdir-y += davinci +subdir-y += keystone +subdir-y += omap diff --git a/arch/arm/boot/dts/ti/davinci/Makefile b/arch/arm/boot/dts/ti/davinci/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..c0e388eb3dd1dab15b3d8444c131c369264f66c8 --- /dev/null +++ b/arch/arm/boot/dts/ti/davinci/Makefile @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0 +dtb-$(CONFIG_ARCH_DAVINCI) += \ + da850-lcdk.dtb \ + da850-enbw-cmc.dtb \ + da850-evm.dtb \ + da850-lego-ev3.dtb diff --git a/arch/arm/boot/dts/da850-enbw-cmc.dts b/arch/arm/boot/dts/ti/davinci/da850-enbw-cmc.dts similarity index 100% rename from arch/arm/boot/dts/da850-enbw-cmc.dts rename to arch/arm/boot/dts/ti/davinci/da850-enbw-cmc.dts diff --git a/arch/arm/boot/dts/da850-evm.dts b/arch/arm/boot/dts/ti/davinci/da850-evm.dts similarity index 99% rename from arch/arm/boot/dts/da850-evm.dts rename to arch/arm/boot/dts/ti/davinci/da850-evm.dts index 0ca849885d1fee2aea3b6cefcb50fd34825dd22a..111708d992caf3108ff695a375c2f86628f938b0 100644 --- a/arch/arm/boot/dts/da850-evm.dts +++ b/arch/arm/boot/dts/ti/davinci/da850-evm.dts @@ -333,7 +333,7 @@ status = "okay"; }; -/include/ "tps6507x.dtsi" +/include/ "../../tps6507x.dtsi" &tps { vdcdc1_2-supply = <&vbat>; diff --git a/arch/arm/boot/dts/da850-lcdk.dts b/arch/arm/boot/dts/ti/davinci/da850-lcdk.dts similarity index 100% rename from arch/arm/boot/dts/da850-lcdk.dts rename to arch/arm/boot/dts/ti/davinci/da850-lcdk.dts diff --git a/arch/arm/boot/dts/da850-lego-ev3.dts b/arch/arm/boot/dts/ti/davinci/da850-lego-ev3.dts similarity index 100% rename from arch/arm/boot/dts/da850-lego-ev3.dts rename to arch/arm/boot/dts/ti/davinci/da850-lego-ev3.dts diff --git a/arch/arm/boot/dts/da850.dtsi b/arch/arm/boot/dts/ti/davinci/da850.dtsi similarity index 100% rename from arch/arm/boot/dts/da850.dtsi rename to arch/arm/boot/dts/ti/davinci/da850.dtsi diff --git a/arch/arm/boot/dts/ti/keystone/Makefile b/arch/arm/boot/dts/ti/keystone/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..4b18d08fa57c7913987b2643724ddf612c00909c --- /dev/null +++ b/arch/arm/boot/dts/ti/keystone/Makefile @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: GPL-2.0 +dtb-$(CONFIG_ARCH_KEYSTONE) += \ + keystone-k2hk-evm.dtb \ + keystone-k2l-evm.dtb \ + keystone-k2e-evm.dtb \ + keystone-k2g-evm.dtb \ + keystone-k2g-ice.dtb diff --git a/arch/arm/boot/dts/keystone-clocks.dtsi b/arch/arm/boot/dts/ti/keystone/keystone-clocks.dtsi similarity index 100% rename from arch/arm/boot/dts/keystone-clocks.dtsi rename to arch/arm/boot/dts/ti/keystone/keystone-clocks.dtsi diff --git a/arch/arm/boot/dts/keystone-k2e-clocks.dtsi b/arch/arm/boot/dts/ti/keystone/keystone-k2e-clocks.dtsi similarity index 100% rename from arch/arm/boot/dts/keystone-k2e-clocks.dtsi rename to arch/arm/boot/dts/ti/keystone/keystone-k2e-clocks.dtsi diff --git a/arch/arm/boot/dts/keystone-k2e-evm.dts b/arch/arm/boot/dts/ti/keystone/keystone-k2e-evm.dts similarity index 98% rename from arch/arm/boot/dts/keystone-k2e-evm.dts rename to arch/arm/boot/dts/ti/keystone/keystone-k2e-evm.dts index abd5aef8b87dce154e8214d904c551034df73c6b..6978d6a362f3fa81e74a3dcf707b52f612a9c0fb 100644 --- a/arch/arm/boot/dts/keystone-k2e-evm.dts +++ b/arch/arm/boot/dts/ti/keystone/keystone-k2e-evm.dts @@ -78,7 +78,7 @@ }; &i2c0 { - dtt@50 { + eeprom@50 { compatible = "atmel,24c1024"; reg = <0x50>; }; @@ -130,7 +130,7 @@ partition@180000 { label = "ubifs"; - reg = <0x180000 0x1FE80000>; + reg = <0x180000 0x1fe80000>; }; }; }; diff --git a/arch/arm/boot/dts/keystone-k2e-netcp.dtsi b/arch/arm/boot/dts/ti/keystone/keystone-k2e-netcp.dtsi similarity index 99% rename from arch/arm/boot/dts/keystone-k2e-netcp.dtsi rename to arch/arm/boot/dts/ti/keystone/keystone-k2e-netcp.dtsi index 42cf74db673ccab5fed44cd05888bc3cfd33919b..bff73a0ed10bfb36873b603bb45e8a5cb7408f10 100644 --- a/arch/arm/boot/dts/keystone-k2e-netcp.dtsi +++ b/arch/arm/boot/dts/ti/keystone/keystone-k2e-netcp.dtsi @@ -167,7 +167,7 @@ netcp: netcp@24000000 { <&tsipclka>, <&tsrefclk>, <&tsipclkb>; ti,mux-tbl = <0x0>, <0x1>, <0x2>, - <0x3>, <0x4>, <0x8>, <0xC>; + <0x3>, <0x4>, <0x8>, <0xc>; assigned-clocks = <&cpts_refclk_mux>; assigned-clock-parents = <&chipclk12>; }; diff --git a/arch/arm/boot/dts/keystone-k2e.dtsi b/arch/arm/boot/dts/ti/keystone/keystone-k2e.dtsi similarity index 100% rename from arch/arm/boot/dts/keystone-k2e.dtsi rename to arch/arm/boot/dts/ti/keystone/keystone-k2e.dtsi diff --git a/arch/arm/boot/dts/keystone-k2g-evm.dts b/arch/arm/boot/dts/ti/keystone/keystone-k2g-evm.dts similarity index 95% rename from arch/arm/boot/dts/keystone-k2g-evm.dts rename to arch/arm/boot/dts/ti/keystone/keystone-k2g-evm.dts index 3a87b7943c7064beddd7466671545709931ffc1e..7bfc80f1af26bb0fbd7830714d70740699d766e5 100644 --- a/arch/arm/boot/dts/keystone-k2g-evm.dts +++ b/arch/arm/boot/dts/ti/keystone/keystone-k2g-evm.dts @@ -120,14 +120,14 @@ }; &k2g_pinctrl { - uart0_pins: pinmux_uart0_pins { + uart0_pins: uart0-pins { pinctrl-single,pins = < K2G_CORE_IOPAD(0x11cc) (BUFFER_CLASS_B | PULL_DISABLE | MUX_MODE0) /* uart0_rxd.uart0_rxd */ K2G_CORE_IOPAD(0x11d0) (BUFFER_CLASS_B | PIN_PULLDOWN | MUX_MODE0) /* uart0_txd.uart0_txd */ >; }; - mmc0_pins: pinmux_mmc0_pins { + mmc0_pins: mmc0-pins { pinctrl-single,pins = < K2G_CORE_IOPAD(0x1300) (BUFFER_CLASS_B | PIN_PULLUP | MUX_MODE2) /* mmc0_dat3.mmc0_dat3 */ K2G_CORE_IOPAD(0x1304) (BUFFER_CLASS_B | PIN_PULLUP | MUX_MODE2) /* mmc0_dat2.mmc0_dat2 */ @@ -139,7 +139,7 @@ >; }; - mmc1_pins: pinmux_mmc1_pins { + mmc1_pins: mmc1-pins { pinctrl-single,pins = < K2G_CORE_IOPAD(0x10ec) (BUFFER_CLASS_B | PIN_PULLUP | MUX_MODE0) /* mmc1_dat7.mmc1_dat7 */ K2G_CORE_IOPAD(0x10f0) (BUFFER_CLASS_B | PIN_PULLUP | MUX_MODE0) /* mmc1_dat6.mmc1_dat6 */ @@ -154,27 +154,27 @@ >; }; - i2c0_pins: pinmux_i2c0_pins { + i2c0_pins: i2c0-pins { pinctrl-single,pins = < K2G_CORE_IOPAD(0x137c) (BUFFER_CLASS_B | PIN_PULLUP | MUX_MODE0) /* i2c0_scl.i2c0_scl */ K2G_CORE_IOPAD(0x1380) (BUFFER_CLASS_B | PIN_PULLUP | MUX_MODE0) /* i2c0_sda.i2c0_sda */ >; }; - i2c1_pins: pinmux_i2c1_pins { + i2c1_pins: i2c1-pins { pinctrl-single,pins = < K2G_CORE_IOPAD(0x1384) (BUFFER_CLASS_B | PIN_PULLUP | MUX_MODE0) /* i2c1_scl.i2c1_scl */ K2G_CORE_IOPAD(0x1388) (BUFFER_CLASS_B | PIN_PULLUP | MUX_MODE0) /* i2c1_sda.i2c1_sda */ >; }; - ecap0_pins: ecap0_pins { + ecap0_pins: ecap0-pins { pinctrl-single,pins = < K2G_CORE_IOPAD(0x1374) (BUFFER_CLASS_B | MUX_MODE4) /* pr1_mdio_data.ecap0_in_apwm0_out */ >; }; - spi1_pins: pinmux_spi1_pins { + spi1_pins: spi1-pins { pinctrl-single,pins = < K2G_CORE_IOPAD(0x11a4) (BUFFER_CLASS_B | PULL_DISABLE | MUX_MODE0) /* spi1_scs0.spi1_scs0 */ K2G_CORE_IOPAD(0x11ac) (BUFFER_CLASS_B | PULL_DISABLE | MUX_MODE0) /* spi1_clk.spi1_clk */ @@ -183,7 +183,7 @@ >; }; - qspi_pins: pinmux_qspi_pins { + qspi_pins: qspi-pins { pinctrl-single,pins = < K2G_CORE_IOPAD(0x1204) (BUFFER_CLASS_B | PULL_DISABLE | MUX_MODE0) /* qspi_clk.qspi_clk */ K2G_CORE_IOPAD(0x1208) (BUFFER_CLASS_B | PULL_DISABLE | MUX_MODE0) /* qspi_rclk.qspi_rclk */ @@ -195,52 +195,52 @@ >; }; - uart2_pins: pinmux_uart2_pins { + uart2_pins: uart2-pins { pinctrl-single,pins = < K2G_CORE_IOPAD(0x11ec) (BUFFER_CLASS_B | PULL_DISABLE | MUX_MODE0) /* uart2_rxd.uart2_rxd */ K2G_CORE_IOPAD(0x11f0) (BUFFER_CLASS_B | PIN_PULLDOWN | MUX_MODE0) /* uart2_txd.uart2_txd */ >; }; - dcan0_pins: pinmux_dcan0_pins { + dcan0_pins: dcan0-pins { pinctrl-single,pins = < K2G_CORE_IOPAD(0x11fc) (BUFFER_CLASS_B | PULL_DISABLE | MUX_MODE0) /* dcan0tx.dcan0tx */ K2G_CORE_IOPAD(0x1200) (BUFFER_CLASS_B | PIN_PULLDOWN | MUX_MODE0) /* dcan0rx.dcan0rx */ >; }; - dcan1_pins: pinmux_dcan1_pins { + dcan1_pins: dcan1-pins { pinctrl-single,pins = < K2G_CORE_IOPAD(0x1224) (BUFFER_CLASS_B | PULL_DISABLE | MUX_MODE1) /* qspicsn2.dcan1tx */ K2G_CORE_IOPAD(0x1228) (BUFFER_CLASS_B | PIN_PULLDOWN | MUX_MODE1) /* qspicsn3.dcan1rx */ >; }; - emac_pins: pinmux_emac_pins { + emac_pins: emac-pins { pinctrl-single,pins = < - K2G_CORE_IOPAD(0x113C) (BUFFER_CLASS_D | PULL_DISABLE | MUX_MODE1) /* MII_RXD1.RGMII_RXD1 */ + K2G_CORE_IOPAD(0x113c) (BUFFER_CLASS_D | PULL_DISABLE | MUX_MODE1) /* MII_RXD1.RGMII_RXD1 */ K2G_CORE_IOPAD(0x1138) (BUFFER_CLASS_D | PULL_DISABLE | MUX_MODE1) /* MII_RXD2.RGMII_RXD2 */ K2G_CORE_IOPAD(0x1134) (BUFFER_CLASS_D | PULL_DISABLE | MUX_MODE1) /* MII_RXD3.RGMII_RXD3 */ K2G_CORE_IOPAD(0x1140) (BUFFER_CLASS_D | PULL_DISABLE | MUX_MODE1) /* MII_RXD0.RGMII_RXD0 */ K2G_CORE_IOPAD(0x1178) (BUFFER_CLASS_D | PULL_DISABLE | MUX_MODE1) /* MII_TXD0.RGMII_TXD0 */ K2G_CORE_IOPAD(0x1174) (BUFFER_CLASS_D | PULL_DISABLE | MUX_MODE1) /* MII_TXD1.RGMII_TXD1 */ K2G_CORE_IOPAD(0x1170) (BUFFER_CLASS_D | PULL_DISABLE | MUX_MODE1) /* MII_TXD2.RGMII_TXD2 */ - K2G_CORE_IOPAD(0x116C) (BUFFER_CLASS_D | PULL_DISABLE | MUX_MODE1) /* MII_TXD3.RGMII_TXD3 */ + K2G_CORE_IOPAD(0x116c) (BUFFER_CLASS_D | PULL_DISABLE | MUX_MODE1) /* MII_TXD3.RGMII_TXD3 */ K2G_CORE_IOPAD(0x1154) (BUFFER_CLASS_D | PULL_DISABLE | MUX_MODE1) /* MII_TXCLK.RGMII_TXC */ - K2G_CORE_IOPAD(0x117C) (BUFFER_CLASS_D | PULL_DISABLE | MUX_MODE1) /* MII_TXEN.RGMII_TXCTL */ + K2G_CORE_IOPAD(0x117c) (BUFFER_CLASS_D | PULL_DISABLE | MUX_MODE1) /* MII_TXEN.RGMII_TXCTL */ K2G_CORE_IOPAD(0x1120) (BUFFER_CLASS_D | PULL_DISABLE | MUX_MODE1) /* MII_RXCLK.RGMII_RXC */ K2G_CORE_IOPAD(0x1144) (BUFFER_CLASS_D | PULL_DISABLE | MUX_MODE1) /* MII_RXDV.RGMII_RXCTL */ >; }; - mdio_pins: pinmux_mdio_pins { + mdio_pins: mdio-pins { pinctrl-single,pins = < - K2G_CORE_IOPAD(0x118C) (BUFFER_CLASS_B | PULL_DISABLE | MUX_MODE0) /* MDIO_CLK.MDIO_CLK */ + K2G_CORE_IOPAD(0x118c) (BUFFER_CLASS_B | PULL_DISABLE | MUX_MODE0) /* MDIO_CLK.MDIO_CLK */ K2G_CORE_IOPAD(0x1188) (BUFFER_CLASS_B | PULL_DISABLE | MUX_MODE0) /* MDIO_DATA.MDIO_DATA */ >; }; - vout_pins: pinmux_vout_pins { + vout_pins: vout-pins { pinctrl-single,pins = < K2G_CORE_IOPAD(0x1078) (BUFFER_CLASS_B | PULL_DISABLE | MUX_MODE0) /* dssdata23.dssdata23 */ K2G_CORE_IOPAD(0x107c) (BUFFER_CLASS_B | PULL_DISABLE | MUX_MODE0) /* dssdata22.dssdata22 */ @@ -274,7 +274,7 @@ >; }; - mcasp2_pins: pinmux_mcasp2_pins { + mcasp2_pins: mcasp2-pins { pinctrl-single,pins = < K2G_CORE_IOPAD(0x1234) (BUFFER_CLASS_B | PIN_PULLDOWN | MUX_MODE4) /* pr0_pru_gpo2.mcasp2_axr2 */ K2G_CORE_IOPAD(0x1238) (BUFFER_CLASS_B | PIN_PULLDOWN | MUX_MODE4) /* pr0_pru_gpo3.mcasp2_axr3 */ @@ -424,11 +424,11 @@ }; partition@4 { label = "QSPI.kernel"; - reg = <0x001C0000 0x0800000>; + reg = <0x001c0000 0x0800000>; }; partition@5 { label = "QSPI.file-system"; - reg = <0x009C0000 0x3640000>; + reg = <0x009c0000 0x3640000>; }; }; }; diff --git a/arch/arm/boot/dts/keystone-k2g-ice.dts b/arch/arm/boot/dts/ti/keystone/keystone-k2g-ice.dts similarity index 94% rename from arch/arm/boot/dts/keystone-k2g-ice.dts rename to arch/arm/boot/dts/ti/keystone/keystone-k2g-ice.dts index bd84d7f0f2fe2177bcc2e68ec9f51b2da39f7508..6ceb0d5c6388bf4b3d150d39861fad085efe2c20 100644 --- a/arch/arm/boot/dts/keystone-k2g-ice.dts +++ b/arch/arm/boot/dts/ti/keystone/keystone-k2g-ice.dts @@ -218,14 +218,14 @@ }; &k2g_pinctrl { - uart0_pins: pinmux_uart0_pins { + uart0_pins: uart0-pins { pinctrl-single,pins = < K2G_CORE_IOPAD(0x11cc) (BUFFER_CLASS_B | PULL_DISABLE | MUX_MODE0) /* uart0_rxd.uart0_rxd */ K2G_CORE_IOPAD(0x11d0) (BUFFER_CLASS_B | PIN_PULLDOWN | MUX_MODE0) /* uart0_txd.uart0_txd */ >; }; - qspi_pins: pinmux_qspi_pins { + qspi_pins: qspi-pins { pinctrl-single,pins = < K2G_CORE_IOPAD(0x1204) (BUFFER_CLASS_B | PULL_DISABLE | MUX_MODE0) /* qspi_clk.qspi_clk */ K2G_CORE_IOPAD(0x1208) (BUFFER_CLASS_B | PULL_DISABLE | MUX_MODE0) /* qspi_rclk.qspi_rclk */ @@ -237,35 +237,35 @@ >; }; - mmc1_pins: pinmux_mmc1_pins { + mmc1_pins: mmc1-pins { pinctrl-single,pins = < - K2G_CORE_IOPAD(0x10FC) (BUFFER_CLASS_B | PIN_PULLUP | MUX_MODE0) /* mmc1_dat3.mmc1_dat3 */ + K2G_CORE_IOPAD(0x10fc) (BUFFER_CLASS_B | PIN_PULLUP | MUX_MODE0) /* mmc1_dat3.mmc1_dat3 */ K2G_CORE_IOPAD(0x1100) (BUFFER_CLASS_B | PIN_PULLUP | MUX_MODE0) /* mmc1_dat2.mmc1_dat2 */ K2G_CORE_IOPAD(0x1104) (BUFFER_CLASS_B | PIN_PULLUP | MUX_MODE0) /* mmc1_dat1.mmc1_dat1 */ K2G_CORE_IOPAD(0x1108) (BUFFER_CLASS_B | PIN_PULLUP | MUX_MODE0) /* mmc1_dat0.mmc1_dat0 */ - K2G_CORE_IOPAD(0x110C) (BUFFER_CLASS_B | PIN_PULLUP | MUX_MODE0) /* mmc1_clk.mmc1_clk */ + K2G_CORE_IOPAD(0x110c) (BUFFER_CLASS_B | PIN_PULLUP | MUX_MODE0) /* mmc1_clk.mmc1_clk */ K2G_CORE_IOPAD(0x1110) (BUFFER_CLASS_B | PIN_PULLUP | MUX_MODE0) /* mmc1_cmd.mmc1_cmd */ K2G_CORE_IOPAD(0x1114) (BUFFER_CLASS_B | PIN_PULLUP | MUX_MODE3) /* mmc1_sdcd.gpio0_69 */ K2G_CORE_IOPAD(0x1118) (BUFFER_CLASS_B | PIN_PULLUP | MUX_MODE0) /* mmc1_sdwp.mmc1_sdwp */ - K2G_CORE_IOPAD(0x111C) (BUFFER_CLASS_B | PIN_PULLUP | MUX_MODE0) /* mmc1_pow.mmc1_pow */ + K2G_CORE_IOPAD(0x111c) (BUFFER_CLASS_B | PIN_PULLUP | MUX_MODE0) /* mmc1_pow.mmc1_pow */ >; }; - i2c0_pins: pinmux_i2c0_pins { + i2c0_pins: i2c0-pins { pinctrl-single,pins = < K2G_CORE_IOPAD(0x137c) (BUFFER_CLASS_B | PIN_PULLUP | MUX_MODE0) /* i2c0_scl.i2c0_scl */ K2G_CORE_IOPAD(0x1380) (BUFFER_CLASS_B | PIN_PULLUP | MUX_MODE0) /* i2c0_sda.i2c0_sda */ >; }; - i2c1_pins: pinmux_i2c1_pins { + i2c1_pins: i2c1-pins { pinctrl-single,pins = < K2G_CORE_IOPAD(0x1384) (BUFFER_CLASS_B | PIN_PULLUP | MUX_MODE0) /* i2c1_scl.i2c1_scl */ K2G_CORE_IOPAD(0x1388) (BUFFER_CLASS_B | PIN_PULLUP | MUX_MODE0) /* i2c1_sda.i2c1_sda */ >; }; - user_leds: pinmux_user_leds { + user_leds: user-leds-pins { pinctrl-single,pins = < K2G_CORE_IOPAD(0x102c) (BUFFER_CLASS_B | PIN_PULLUP | MUX_MODE3) /* gpmc_ad11.gpio0_11 */ K2G_CORE_IOPAD(0x1030) (BUFFER_CLASS_B | PIN_PULLUP | MUX_MODE3) /* gpmc_ad12.gpio0_12 */ @@ -283,26 +283,26 @@ >; }; - emac_pins: pinmux_emac_pins { + emac_pins: emac-pins { pinctrl-single,pins = < - K2G_CORE_IOPAD(0x113C) (BUFFER_CLASS_D | PULL_DISABLE | MUX_MODE1) /* MII_RXD1.RGMII_RXD1 */ + K2G_CORE_IOPAD(0x113c) (BUFFER_CLASS_D | PULL_DISABLE | MUX_MODE1) /* MII_RXD1.RGMII_RXD1 */ K2G_CORE_IOPAD(0x1138) (BUFFER_CLASS_D | PULL_DISABLE | MUX_MODE1) /* MII_RXD2.RGMII_RXD2 */ K2G_CORE_IOPAD(0x1134) (BUFFER_CLASS_D | PULL_DISABLE | MUX_MODE1) /* MII_RXD3.RGMII_RXD3 */ K2G_CORE_IOPAD(0x1140) (BUFFER_CLASS_D | PULL_DISABLE | MUX_MODE1) /* MII_RXD0.RGMII_RXD0 */ K2G_CORE_IOPAD(0x1178) (BUFFER_CLASS_D | PULL_DISABLE | MUX_MODE1) /* MII_TXD0.RGMII_TXD0 */ K2G_CORE_IOPAD(0x1174) (BUFFER_CLASS_D | PULL_DISABLE | MUX_MODE1) /* MII_TXD1.RGMII_TXD1 */ K2G_CORE_IOPAD(0x1170) (BUFFER_CLASS_D | PULL_DISABLE | MUX_MODE1) /* MII_TXD2.RGMII_TXD2 */ - K2G_CORE_IOPAD(0x116C) (BUFFER_CLASS_D | PULL_DISABLE | MUX_MODE1) /* MII_TXD3.RGMII_TXD3 */ + K2G_CORE_IOPAD(0x116c) (BUFFER_CLASS_D | PULL_DISABLE | MUX_MODE1) /* MII_TXD3.RGMII_TXD3 */ K2G_CORE_IOPAD(0x1154) (BUFFER_CLASS_D | PULL_DISABLE | MUX_MODE1) /* MII_TXCLK.RGMII_TXC */ - K2G_CORE_IOPAD(0x117C) (BUFFER_CLASS_D | PULL_DISABLE | MUX_MODE1) /* MII_TXEN.RGMII_TXCTL */ + K2G_CORE_IOPAD(0x117c) (BUFFER_CLASS_D | PULL_DISABLE | MUX_MODE1) /* MII_TXEN.RGMII_TXCTL */ K2G_CORE_IOPAD(0x1120) (BUFFER_CLASS_D | PULL_DISABLE | MUX_MODE1) /* MII_RXCLK.RGMII_RXC */ K2G_CORE_IOPAD(0x1144) (BUFFER_CLASS_D | PULL_DISABLE | MUX_MODE1) /* MII_RXDV.RGMII_RXCTL */ >; }; - mdio_pins: pinmux_mdio_pins { + mdio_pins: mdio-pins { pinctrl-single,pins = < - K2G_CORE_IOPAD(0x118C) (BUFFER_CLASS_B | PULL_DISABLE | MUX_MODE0) /* MDIO_CLK.MDIO_CLK */ + K2G_CORE_IOPAD(0x118c) (BUFFER_CLASS_B | PULL_DISABLE | MUX_MODE0) /* MDIO_CLK.MDIO_CLK */ K2G_CORE_IOPAD(0x1188) (BUFFER_CLASS_B | PULL_DISABLE | MUX_MODE0) /* MDIO_DATA.MDIO_DATA */ >; }; diff --git a/arch/arm/boot/dts/keystone-k2g-netcp.dtsi b/arch/arm/boot/dts/ti/keystone/keystone-k2g-netcp.dtsi similarity index 100% rename from arch/arm/boot/dts/keystone-k2g-netcp.dtsi rename to arch/arm/boot/dts/ti/keystone/keystone-k2g-netcp.dtsi diff --git a/arch/arm/boot/dts/keystone-k2g.dtsi b/arch/arm/boot/dts/ti/keystone/keystone-k2g.dtsi similarity index 99% rename from arch/arm/boot/dts/keystone-k2g.dtsi rename to arch/arm/boot/dts/ti/keystone/keystone-k2g.dtsi index 380dd9d637eefb7150869b060e63d6870861413f..102d59694d903707a55da8e30e79dc8863462665 100644 --- a/arch/arm/boot/dts/keystone-k2g.dtsi +++ b/arch/arm/boot/dts/ti/keystone/keystone-k2g.dtsi @@ -177,7 +177,7 @@ dcan0: can@260b200 { compatible = "ti,am4372-d_can", "ti,am3352-d_can"; - reg = <0x0260B200 0x200>; + reg = <0x0260b200 0x200>; interrupts = ; status = "disabled"; power-domains = <&k2g_pds 0x0008>; @@ -186,7 +186,7 @@ dcan1: can@260b400 { compatible = "ti,am4372-d_can", "ti,am3352-d_can"; - reg = <0x0260B400 0x200>; + reg = <0x0260b400 0x200>; interrupts = ; status = "disabled"; power-domains = <&k2g_pds 0x0009>; @@ -593,7 +593,7 @@ spi2: spi@21805c00 { compatible = "ti,keystone-spi"; - reg = <0x21805C00 0x200>; + reg = <0x21805c00 0x200>; num-cs = <4>; ti,davinci-spi-intr-line = <0>; interrupts = ; diff --git a/arch/arm/boot/dts/keystone-k2hk-clocks.dtsi b/arch/arm/boot/dts/ti/keystone/keystone-k2hk-clocks.dtsi similarity index 100% rename from arch/arm/boot/dts/keystone-k2hk-clocks.dtsi rename to arch/arm/boot/dts/ti/keystone/keystone-k2hk-clocks.dtsi diff --git a/arch/arm/boot/dts/keystone-k2hk-evm.dts b/arch/arm/boot/dts/ti/keystone/keystone-k2hk-evm.dts similarity index 99% rename from arch/arm/boot/dts/keystone-k2hk-evm.dts rename to arch/arm/boot/dts/ti/keystone/keystone-k2hk-evm.dts index 1f762af6f50226c04bf4c73fd387b93aea6d8427..206df8a8d9dd7de2de16df712680cceca890fd5a 100644 --- a/arch/arm/boot/dts/keystone-k2hk-evm.dts +++ b/arch/arm/boot/dts/ti/keystone/keystone-k2hk-evm.dts @@ -154,7 +154,7 @@ }; &i2c0 { - dtt@50 { + eeprom@50 { compatible = "atmel,24c1024"; reg = <0x50>; }; diff --git a/arch/arm/boot/dts/keystone-k2hk-netcp.dtsi b/arch/arm/boot/dts/ti/keystone/keystone-k2hk-netcp.dtsi similarity index 100% rename from arch/arm/boot/dts/keystone-k2hk-netcp.dtsi rename to arch/arm/boot/dts/ti/keystone/keystone-k2hk-netcp.dtsi diff --git a/arch/arm/boot/dts/keystone-k2hk.dtsi b/arch/arm/boot/dts/ti/keystone/keystone-k2hk.dtsi similarity index 100% rename from arch/arm/boot/dts/keystone-k2hk.dtsi rename to arch/arm/boot/dts/ti/keystone/keystone-k2hk.dtsi diff --git a/arch/arm/boot/dts/keystone-k2l-clocks.dtsi b/arch/arm/boot/dts/ti/keystone/keystone-k2l-clocks.dtsi similarity index 100% rename from arch/arm/boot/dts/keystone-k2l-clocks.dtsi rename to arch/arm/boot/dts/ti/keystone/keystone-k2l-clocks.dtsi diff --git a/arch/arm/boot/dts/keystone-k2l-evm.dts b/arch/arm/boot/dts/ti/keystone/keystone-k2l-evm.dts similarity index 98% rename from arch/arm/boot/dts/keystone-k2l-evm.dts rename to arch/arm/boot/dts/ti/keystone/keystone-k2l-evm.dts index 3a69f65de81ec3dac723e2fa6c700538a9a4da1b..be619e39a16f3eef9438b08470a04f7e1142795d 100644 --- a/arch/arm/boot/dts/keystone-k2l-evm.dts +++ b/arch/arm/boot/dts/ti/keystone/keystone-k2l-evm.dts @@ -51,7 +51,7 @@ }; &i2c0 { - dtt@50 { + eeprom@50 { compatible = "atmel,24c1024"; reg = <0x50>; }; @@ -103,7 +103,7 @@ partition@180000 { label = "ubifs"; - reg = <0x180000 0x7FE80000>; + reg = <0x180000 0x7fe80000>; }; }; }; diff --git a/arch/arm/boot/dts/keystone-k2l-netcp.dtsi b/arch/arm/boot/dts/ti/keystone/keystone-k2l-netcp.dtsi similarity index 100% rename from arch/arm/boot/dts/keystone-k2l-netcp.dtsi rename to arch/arm/boot/dts/ti/keystone/keystone-k2l-netcp.dtsi diff --git a/arch/arm/boot/dts/keystone-k2l.dtsi b/arch/arm/boot/dts/ti/keystone/keystone-k2l.dtsi similarity index 95% rename from arch/arm/boot/dts/keystone-k2l.dtsi rename to arch/arm/boot/dts/ti/keystone/keystone-k2l.dtsi index 421a02bbc9d30fc0c67f7173daf2c01e0d1523f1..8949578e62e84e791ab20bce43d70b8b07157f8d 100644 --- a/arch/arm/boot/dts/keystone-k2l.dtsi +++ b/arch/arm/boot/dts/ti/keystone/keystone-k2l.dtsi @@ -116,42 +116,42 @@ pinctrl-single,function-mask = <0x1>; status = "disabled"; - uart3_emifa_pins: pinmux_uart3_emifa_pins { + uart3_emifa_pins: uart3-emifa-pins { pinctrl-single,bits = < /* UART3_EMIFA_SEL */ 0x0 0x0 0xc0 >; }; - uart2_emifa_pins: pinmux_uart2_emifa_pins { + uart2_emifa_pins: uart2-emifa-pins { pinctrl-single,bits = < /* UART2_EMIFA_SEL */ 0x0 0x0 0x30 >; }; - uart01_spi2_pins: pinmux_uart01_spi2_pins { + uart01_spi2_pins: uart01-spi2-pins { pinctrl-single,bits = < /* UART01_SPI2_SEL */ 0x0 0x0 0x4 >; }; - dfesync_rp1_pins: pinmux_dfesync_rp1_pins{ + dfesync_rp1_pins: dfesync-rp1-pins{ pinctrl-single,bits = < /* DFESYNC_RP1_SEL */ 0x0 0x0 0x2 >; }; - avsif_pins: pinmux_avsif_pins { + avsif_pins: avsif-pins { pinctrl-single,bits = < /* AVSIF_SEL */ 0x0 0x0 0x1 >; }; - gpio_emu_pins: pinmux_gpio_emu_pins { + gpio_emu_pins: gpio-emu-pins { pinctrl-single,bits = < /* * GPIO_EMU_SEL[31]: 0-GPIO31, 1-EMU33 @@ -170,11 +170,11 @@ * GPIO_EMU_SEL[18]: 0-GPIO18, 1-EMU20 * GPIO_EMU_SEL[17]: 0-GPIO17, 1-EMU19 */ - 0x4 0x0000 0xFFFE0000 + 0x4 0x0000 0xfffe0000 >; }; - gpio_timio_pins: pinmux_gpio_timio_pins { + gpio_timio_pins: gpio-timio-pins { pinctrl-single,bits = < /* * GPIO_TIMIO_SEL[15]: 0-GPIO15, 1-TIMO7 @@ -190,11 +190,11 @@ * GPIO_TIMIO_SEL[5]: 0-GPIO5, 1-TIMI3 * GPIO_TIMIO_SEL[4]: 0-GPIO4, 1-TIMI2 */ - 0x4 0x0 0xFFF0 + 0x4 0x0 0xfff0 >; }; - gpio_spi2cs_pins: pinmux_gpio_spi2cs_pins { + gpio_spi2cs_pins: gpio-spi2cs-pins { pinctrl-single,bits = < /* * GPIO_SPI2CS_SEL[3]: 0-GPIO3, 1-SPI2CS4 @@ -202,11 +202,11 @@ * GPIO_SPI2CS_SEL[1]: 0-GPIO1, 1-SPI2CS2 * GPIO_SPI2CS_SEL[0]: 0-GPIO0, 1-SPI2CS1 */ - 0x4 0x0 0xF + 0x4 0x0 0xf >; }; - gpio_dfeio_pins: pinmux_gpio_dfeio_pins { + gpio_dfeio_pins: gpio-dfeio-pins { pinctrl-single,bits = < /* * GPIO_DFEIO_SEL[31]: 0-DFEIO17, 1-GPIO63 @@ -226,11 +226,11 @@ * GPIO_DFEIO_SEL[17]: 0-DFEIO3, 1-GPIO49 * GPIO_DFEIO_SEL[16]: 0-DFEIO2, 1-GPIO48 */ - 0x8 0x0 0xFFFF0000 + 0x8 0x0 0xffff0000 >; }; - gpio_emifa_pins: pinmux_gpio_emifa_pins { + gpio_emifa_pins: gpio-emifa-pins { pinctrl-single,bits = < /* * GPIO_EMIFA_SEL[15]: 0-EMIFA17, 1-GPIO47 @@ -250,7 +250,7 @@ * GPIO_EMIFA_SEL[1]: 0-EMIFA1, 1-GPIO33 * GPIO_EMIFA_SEL[0]: 0-EMIFA0, 1-GPIO32 */ - 0x8 0x0 0xFFFF + 0x8 0x0 0xffff >; }; }; diff --git a/arch/arm/boot/dts/keystone.dtsi b/arch/arm/boot/dts/ti/keystone/keystone.dtsi similarity index 98% rename from arch/arm/boot/dts/keystone.dtsi rename to arch/arm/boot/dts/ti/keystone/keystone.dtsi index 50789f9e2215f8dba027bd0ccf3dccf88e990934..1fd04bb37a1538763be661ccd251f0fbd87800fe 100644 --- a/arch/arm/boot/dts/keystone.dtsi +++ b/arch/arm/boot/dts/ti/keystone/keystone.dtsi @@ -69,9 +69,9 @@ }; soc0: soc@0 { + compatible = "simple-bus"; #address-cells = <1>; #size-cells = <1>; - compatible = "ti,keystone","simple-bus"; interrupt-parent = <&gic>; ranges = <0x0 0x0 0x0 0xc0000000>; dma-ranges = <0x80000000 0x8 0x00000000 0x80000000>; @@ -282,7 +282,7 @@ ti,davinci-gpio-unbanked = <32>; }; - aemif: aemif@21000A00 { + aemif: aemif@21000a00 { compatible = "ti,keystone-aemif", "ti,davinci-aemif"; #address-cells = <2>; #size-cells = <1>; @@ -290,9 +290,9 @@ clock-names = "aemif"; clock-ranges; - reg = <0x21000A00 0x00000100>; + reg = <0x21000a00 0x00000100>; ranges = <0 0 0x30000000 0x10000000 - 1 0 0x21000A00 0x00000100>; + 1 0 0x21000a00 0x00000100>; }; pcie0: pcie@21800000 { diff --git a/arch/arm/boot/dts/ti/omap/Makefile b/arch/arm/boot/dts/ti/omap/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..d2b590004fedfe8b3b42fe31a3c22684ffc5da06 --- /dev/null +++ b/arch/arm/boot/dts/ti/omap/Makefile @@ -0,0 +1,163 @@ +# SPDX-License-Identifier: GPL-2.0 +dtb-$(CONFIG_ARCH_OMAP2) += \ + omap2420-h4.dtb \ + omap2420-n800.dtb \ + omap2420-n810.dtb \ + omap2420-n810-wimax.dtb \ + omap2430-sdp.dtb +dtb-$(CONFIG_ARCH_OMAP3) += \ + am3517-craneboard.dtb \ + am3517-evm.dtb \ + am3517_mt_ventoux.dtb \ + logicpd-torpedo-35xx-devkit.dtb \ + logicpd-torpedo-37xx-devkit.dtb \ + logicpd-torpedo-37xx-devkit-28.dtb \ + logicpd-som-lv-35xx-devkit.dtb \ + logicpd-som-lv-37xx-devkit.dtb \ + omap3430-sdp.dtb \ + omap3-beagle.dtb \ + omap3-beagle-ab4.dtb \ + omap3-beagle-xm.dtb \ + omap3-beagle-xm-ab.dtb \ + omap3-cm-t3517.dtb \ + omap3-cm-t3530.dtb \ + omap3-cm-t3730.dtb \ + omap3-devkit8000.dtb \ + omap3-devkit8000-lcd43.dtb \ + omap3-devkit8000-lcd70.dtb \ + omap3-echo.dtb \ + omap3-evm.dtb \ + omap3-evm-37xx.dtb \ + omap3-gta04a3.dtb \ + omap3-gta04a4.dtb \ + omap3-gta04a5.dtb \ + omap3-gta04a5one.dtb \ + omap3-ha.dtb \ + omap3-ha-lcd.dtb \ + omap3-igep0020.dtb \ + omap3-igep0020-rev-f.dtb \ + omap3-igep0030.dtb \ + omap3-igep0030-rev-g.dtb \ + omap3-ldp.dtb \ + omap3-lilly-dbb056.dtb \ + omap3-n900.dtb \ + omap3-n9.dtb \ + omap3-n950.dtb \ + omap3-overo-alto35.dtb \ + omap3-overo-chestnut43.dtb \ + omap3-overo-gallop43.dtb \ + omap3-overo-palo35.dtb \ + omap3-overo-palo43.dtb \ + omap3-overo-storm-alto35.dtb \ + omap3-overo-storm-chestnut43.dtb \ + omap3-overo-storm-gallop43.dtb \ + omap3-overo-storm-palo35.dtb \ + omap3-overo-storm-palo43.dtb \ + omap3-overo-storm-summit.dtb \ + omap3-overo-storm-tobi.dtb \ + omap3-overo-storm-tobiduo.dtb \ + omap3-overo-summit.dtb \ + omap3-overo-tobi.dtb \ + omap3-overo-tobiduo.dtb \ + omap3-pandora-600mhz.dtb \ + omap3-pandora-1ghz.dtb \ + omap3-sbc-t3517.dtb \ + omap3-sbc-t3530.dtb \ + omap3-sbc-t3730.dtb \ + omap3-sniper.dtb \ + omap3-thunder.dtb \ + omap3-zoom3.dtb +dtb-$(CONFIG_ARCH_OMAP4) += \ + omap4-droid-bionic-xt875.dtb \ + omap4-droid4-xt894.dtb \ + omap4-duovero-parlor.dtb \ + omap4-epson-embt2ws.dtb \ + omap4-kc1.dtb \ + omap4-panda.dtb \ + omap4-panda-a4.dtb \ + omap4-panda-es.dtb \ + omap4-sdp.dtb \ + omap4-sdp-es23plus.dtb \ + omap4-var-dvk-om44.dtb \ + omap4-var-stk-om44.dtb +dtb-$(CONFIG_SOC_AM33XX) += \ + am335x-baltos-ir2110.dtb \ + am335x-baltos-ir3220.dtb \ + am335x-baltos-ir5221.dtb \ + am335x-base0033.dtb \ + am335x-bone.dtb \ + am335x-boneblack.dtb \ + am335x-boneblack-wireless.dtb \ + am335x-boneblue.dtb \ + am335x-bonegreen.dtb \ + am335x-bonegreen-wireless.dtb \ + am335x-chiliboard.dtb \ + am335x-cm-t335.dtb \ + am335x-evm.dtb \ + am335x-evmsk.dtb \ + am335x-guardian.dtb \ + am335x-icev2.dtb \ + am335x-lxm.dtb \ + am335x-moxa-uc-2101.dtb \ + am335x-moxa-uc-8100-me-t.dtb \ + am335x-myirtech-myd.dtb \ + am335x-nano.dtb \ + am335x-netcan-plus-1xx.dtb \ + am335x-netcom-plus-2xx.dtb \ + am335x-netcom-plus-8xx.dtb \ + am335x-pdu001.dtb \ + am335x-pepper.dtb \ + am335x-phycore-rdk.dtb \ + am335x-pocketbeagle.dtb \ + am335x-regor-rdk.dtb \ + am335x-sancloud-bbe.dtb \ + am335x-sancloud-bbe-lite.dtb \ + am335x-sancloud-bbe-extended-wifi.dtb \ + am335x-shc.dtb \ + am335x-sbc-t335.dtb \ + am335x-sl50.dtb \ + am335x-wega-rdk.dtb \ + am335x-osd3358-sm-red.dtb +dtb-$(CONFIG_SOC_AM43XX) += \ + am43x-epos-evm.dtb \ + am437x-cm-t43.dtb \ + am437x-gp-evm.dtb \ + am437x-idk-evm.dtb \ + am437x-sbc-t43.dtb \ + am437x-sk-evm.dtb + +am57xx-evm-dtbs := am57xx-beagle-x15.dtb am57xx-evm.dtbo +am57xx-evm-reva3-dtbs := am57xx-beagle-x15-revc.dtb am57xx-evm.dtbo + +dtb-$(CONFIG_SOC_DRA7XX) += \ + am57xx-beagle-x15.dtb \ + am57xx-beagle-x15-revb1.dtb \ + am57xx-beagle-x15-revc.dtb \ + am57xx-evm.dtb \ + am57xx-evm-reva3.dtb \ + am5729-beagleboneai.dtb \ + am57xx-cl-som-am57x.dtb \ + am57xx-sbc-am57x.dtb \ + am572x-idk.dtb \ + am572x-idk-touchscreen.dtbo \ + am571x-idk.dtb \ + am571x-idk-touchscreen.dtbo \ + am574x-idk.dtb \ + am57xx-idk-lcd-osd101t2045.dtbo \ + am57xx-idk-lcd-osd101t2587.dtbo \ + dra7-evm.dtb \ + dra72-evm.dtb \ + dra72-evm-revc.dtb \ + dra71-evm.dtb \ + dra76-evm.dtb +dtb-$(CONFIG_SOC_OMAP5) += \ + omap5-cm-t54.dtb \ + omap5-igep0050.dtb \ + omap5-sbc-t54.dtb \ + omap5-uevm.dtb +dtb-$(CONFIG_SOC_TI81XX) += \ + am3874-iceboard.dtb \ + dm8148-evm.dtb \ + dm8148-t410.dtb \ + dm8168-evm.dtb \ + dra62x-j5eco-evm.dtb diff --git a/arch/arm/boot/dts/am335x-baltos-ir2110.dts b/arch/arm/boot/dts/ti/omap/am335x-baltos-ir2110.dts similarity index 98% rename from arch/arm/boot/dts/am335x-baltos-ir2110.dts rename to arch/arm/boot/dts/ti/omap/am335x-baltos-ir2110.dts index 75992eec830f6988da9fba623933d22979330b80..ea5882ed7010499140ed95a65b82574e31640ab7 100644 --- a/arch/arm/boot/dts/am335x-baltos-ir2110.dts +++ b/arch/arm/boot/dts/ti/omap/am335x-baltos-ir2110.dts @@ -18,7 +18,7 @@ }; &am33xx_pinmux { - uart1_pins: pinmux_uart1_pins { + uart1_pins: uart1-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_UART1_RXD, PIN_INPUT, MUX_MODE0) AM33XX_PADCONF(AM335X_PIN_UART1_TXD, PIN_INPUT, MUX_MODE0) @@ -31,7 +31,7 @@ >; }; - mmc1_pins: pinmux_mmc1_pins { + mmc1_pins: mmc1-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_GPMC_AD15, PIN_INPUT, MUX_MODE7) /* MMC1 CD */ >; diff --git a/arch/arm/boot/dts/am335x-baltos-ir3220.dts b/arch/arm/boot/dts/ti/omap/am335x-baltos-ir3220.dts similarity index 97% rename from arch/arm/boot/dts/am335x-baltos-ir3220.dts rename to arch/arm/boot/dts/ti/omap/am335x-baltos-ir3220.dts index 087e084506d258166232b132d9112e0fe5d67c2c..ea4f8dde6424453cfb98dbf04da24b0ea10b66d0 100644 --- a/arch/arm/boot/dts/am335x-baltos-ir3220.dts +++ b/arch/arm/boot/dts/ti/omap/am335x-baltos-ir3220.dts @@ -18,13 +18,13 @@ }; &am33xx_pinmux { - tca6416_pins: pinmux_tca6416_pins { + tca6416_pins: tca6416-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_XDMA_EVENT_INTR1, PIN_INPUT_PULLUP, MUX_MODE7) /* xdma_event_intr1.gpio0[20] tca6416 stuff */ >; }; - uart1_pins: pinmux_uart1_pins { + uart1_pins: uart1-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_UART1_RXD, PIN_INPUT, MUX_MODE0) AM33XX_PADCONF(AM335X_PIN_UART1_TXD, PIN_INPUT, MUX_MODE0) @@ -37,7 +37,7 @@ >; }; - uart2_pins: pinmux_uart2_pins { + uart2_pins: uart2-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_SPI0_SCLK, PIN_INPUT, MUX_MODE1) /* spi0_sclk.uart2_rxd_mux3 */ AM33XX_PADCONF(AM335X_PIN_SPI0_D0, PIN_OUTPUT, MUX_MODE1) /* spi0_d0.uart2_txd_mux3 */ @@ -52,7 +52,7 @@ >; }; - mmc1_pins: pinmux_mmc1_pins { + mmc1_pins: mmc1-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_MII1_RXD3, PIN_INPUT, MUX_MODE7) /* MMC1 CD */ >; diff --git a/arch/arm/boot/dts/am335x-baltos-ir5221.dts b/arch/arm/boot/dts/ti/omap/am335x-baltos-ir5221.dts similarity index 97% rename from arch/arm/boot/dts/am335x-baltos-ir5221.dts rename to arch/arm/boot/dts/ti/omap/am335x-baltos-ir5221.dts index faeb39aab60a727f22ed95e9f847c1ec0fc48d06..ec914f27d11df2c4a5989b88984274bd120ecd5a 100644 --- a/arch/arm/boot/dts/am335x-baltos-ir5221.dts +++ b/arch/arm/boot/dts/ti/omap/am335x-baltos-ir5221.dts @@ -18,21 +18,21 @@ }; &am33xx_pinmux { - tca6416_pins: pinmux_tca6416_pins { + tca6416_pins: tca6416-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_XDMA_EVENT_INTR1, PIN_INPUT_PULLUP, MUX_MODE7) /* xdma_event_intr1.gpio0[20] tca6416 stuff */ >; }; - dcan1_pins: pinmux_dcan1_pins { + dcan1_pins: dcan1-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_UART0_CTSN, PIN_OUTPUT, MUX_MODE2) /* uart0_ctsn.dcan1_tx_mux0 */ AM33XX_PADCONF(AM335X_PIN_UART0_RTSN, PIN_INPUT, MUX_MODE2) /* uart0_rtsn.dcan1_rx_mux0 */ >; }; - uart1_pins: pinmux_uart1_pins { + uart1_pins: uart1-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_UART1_RXD, PIN_INPUT, MUX_MODE0) AM33XX_PADCONF(AM335X_PIN_UART1_TXD, PIN_INPUT, MUX_MODE0) @@ -45,7 +45,7 @@ >; }; - uart2_pins: pinmux_uart2_pins { + uart2_pins: uart2-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_SPI0_SCLK, PIN_INPUT, MUX_MODE1) /* spi0_sclk.uart2_rxd_mux3 */ AM33XX_PADCONF(AM335X_PIN_SPI0_D0, PIN_OUTPUT, MUX_MODE1) /* spi0_d0.uart2_txd_mux3 */ @@ -60,7 +60,7 @@ >; }; - mmc1_pins: pinmux_mmc1_pins { + mmc1_pins: mmc1-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_MII1_RXD3, PIN_INPUT, MUX_MODE7) /* MMC1 CD */ >; diff --git a/arch/arm/boot/dts/am335x-baltos-leds.dtsi b/arch/arm/boot/dts/ti/omap/am335x-baltos-leds.dtsi similarity index 97% rename from arch/arm/boot/dts/am335x-baltos-leds.dtsi rename to arch/arm/boot/dts/ti/omap/am335x-baltos-leds.dtsi index 025014657d12a8ebd959e42af11bfd64eb492113..6a52e42b9e8132dd1b2b137ef7bb0b8b7bd4eb03 100644 --- a/arch/arm/boot/dts/am335x-baltos-leds.dtsi +++ b/arch/arm/boot/dts/ti/omap/am335x-baltos-leds.dtsi @@ -37,7 +37,7 @@ }; &am33xx_pinmux { - user_leds: pinmux_user_leds { + user_leds: user-leds-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_MII1_COL, PIN_OUTPUT_PULLDOWN, MUX_MODE7) /* mii1_col.gpio3_0 PWR LED */ AM33XX_PADCONF(AM335X_PIN_MII1_TXD3, PIN_OUTPUT_PULLDOWN, MUX_MODE7) /* mii1_txd3.gpio0_16 WLAN LED */ diff --git a/arch/arm/boot/dts/am335x-baltos.dtsi b/arch/arm/boot/dts/ti/omap/am335x-baltos.dtsi similarity index 96% rename from arch/arm/boot/dts/am335x-baltos.dtsi rename to arch/arm/boot/dts/ti/omap/am335x-baltos.dtsi index 6161c8929a781ab90b8cc2163bc53c904b4f2d5b..c14d5b70c72f6c3e3b80851be25c5c2b6f2e987f 100644 --- a/arch/arm/boot/dts/am335x-baltos.dtsi +++ b/arch/arm/boot/dts/ti/omap/am335x-baltos.dtsi @@ -48,7 +48,7 @@ }; &am33xx_pinmux { - mmc2_pins: pinmux_mmc2_pins { + mmc2_pins: mmc2-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_GPMC_AD8, PIN_INPUT_PULLUP, MUX_MODE2) /* gpmc_ad8.mmc1_dat0_mux0 */ AM33XX_PADCONF(AM335X_PIN_GPMC_AD9, PIN_INPUT_PULLUP, MUX_MODE2) /* gpmc_ad9.mmc1_dat1_mux0 */ @@ -60,33 +60,33 @@ >; }; - wl12xx_gpio: pinmux_wl12xx_gpio { + wl12xx_gpio: wl12xx-gpio-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_EMU1, PIN_OUTPUT_PULLUP, MUX_MODE7) /* emu1.gpio3[8] */ >; }; - tps65910_pins: pinmux_tps65910_pins { + tps65910_pins: tps65910-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_GPMC_BEN1, PIN_INPUT_PULLUP, MUX_MODE7) /* gpmc_ben1.gpio1[28] */ >; }; - i2c1_pins: pinmux_i2c1_pins { + i2c1_pins: i2c1-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_SPI0_D1, PIN_INPUT, MUX_MODE2) /* spi0_d1.i2c1_sda_mux3 */ AM33XX_PADCONF(AM335X_PIN_SPI0_CS0, PIN_INPUT, MUX_MODE2) /* spi0_cs0.i2c1_scl_mux3 */ >; }; - uart0_pins: pinmux_uart0_pins { + uart0_pins: uart0-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_UART0_RXD, PIN_INPUT_PULLUP, MUX_MODE0) AM33XX_PADCONF(AM335X_PIN_UART0_TXD, PIN_OUTPUT_PULLDOWN, MUX_MODE0) >; }; - cpsw_default: cpsw_default { + cpsw_default: cpsw-default-pins { pinctrl-single,pins = < /* Slave 1 */ AM33XX_PADCONF(AM335X_PIN_MII1_CRS, PIN_INPUT_PULLDOWN, MUX_MODE1) /* mii1_crs.rmii1_crs_dv */ @@ -114,7 +114,7 @@ >; }; - cpsw_sleep: cpsw_sleep { + cpsw_sleep: cpsw-sleep-pins { pinctrl-single,pins = < /* Slave 1 reset value */ AM33XX_PADCONF(AM335X_PIN_MII1_CRS, PIN_INPUT_PULLDOWN, MUX_MODE7) @@ -141,7 +141,7 @@ >; }; - davinci_mdio_default: davinci_mdio_default { + davinci_mdio_default: davinci-mdio-default-pins { pinctrl-single,pins = < /* MDIO */ AM33XX_PADCONF(AM335X_PIN_MDIO, PIN_INPUT_PULLUP | SLEWCTRL_FAST, MUX_MODE0) /* mdio_data.mdio_data */ @@ -149,7 +149,7 @@ >; }; - davinci_mdio_sleep: davinci_mdio_sleep { + davinci_mdio_sleep: davinci-mdio-sleep-pins { pinctrl-single,pins = < /* MDIO reset value */ AM33XX_PADCONF(AM335X_PIN_MDIO, PIN_INPUT_PULLDOWN, MUX_MODE7) @@ -157,7 +157,7 @@ >; }; - nandflash_pins_s0: nandflash_pins_s0 { + nandflash_pins_s0: nandflash-s0-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_GPMC_AD0, PIN_INPUT_PULLUP, MUX_MODE0) /* gpmc_ad0.gpmc_ad0 */ AM33XX_PADCONF(AM335X_PIN_GPMC_AD1, PIN_INPUT_PULLUP, MUX_MODE0) /* gpmc_ad1.gpmc_ad1 */ @@ -258,7 +258,7 @@ }; }; -#include "tps65910.dtsi" +#include "../../tps65910.dtsi" &tps { vcc1-supply = <&vbat>; diff --git a/arch/arm/boot/dts/am335x-base0033.dts b/arch/arm/boot/dts/ti/omap/am335x-base0033.dts similarity index 95% rename from arch/arm/boot/dts/am335x-base0033.dts rename to arch/arm/boot/dts/ti/omap/am335x-base0033.dts index 89c00ce42c261c5866a6c566e7aec1ab51bfb974..eba843e22ea16eb60a62d263e5a65ce796e842cf 100644 --- a/arch/arm/boot/dts/am335x-base0033.dts +++ b/arch/arm/boot/dts/ti/omap/am335x-base0033.dts @@ -41,7 +41,7 @@ }; &am33xx_pinmux { - nxp_hdmi_pins: pinmux_nxp_hdmi_pins { + nxp_hdmi_pins: nxp-hdmi-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_XDMA_EVENT_INTR0, PIN_OUTPUT, MUX_MODE3) /* xdma_event_intr0.clkout1 */ AM33XX_PADCONF(AM335X_PIN_LCD_DATA0, PIN_OUTPUT, MUX_MODE0) @@ -66,13 +66,13 @@ AM33XX_PADCONF(AM335X_PIN_LCD_AC_BIAS_EN, PIN_OUTPUT, MUX_MODE0) >; }; - nxp_hdmi_off_pins: pinmux_nxp_hdmi_off_pins { + nxp_hdmi_off_pins: nxp-hdmi-off-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_XDMA_EVENT_INTR0, PIN_OUTPUT, MUX_MODE3) /* xdma_event_intr0.clkout1 */ >; }; - leds_base_pins: pinmux_leds_base_pins { + leds_base_pins: leds-base-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_GPMC_A5, PIN_OUTPUT_PULLDOWN, MUX_MODE7) /* gpmc_a5.gpio1_21 */ AM33XX_PADCONF(AM335X_PIN_GPMC_CSN3, PIN_OUTPUT_PULLDOWN, MUX_MODE7) /* gpmc_csn3.gpio2_0 */ diff --git a/arch/arm/boot/dts/am335x-bone-common.dtsi b/arch/arm/boot/dts/ti/omap/am335x-bone-common.dtsi similarity index 96% rename from arch/arm/boot/dts/am335x-bone-common.dtsi rename to arch/arm/boot/dts/ti/omap/am335x-bone-common.dtsi index 02e04a12a27031581406c430ae10a362a9206120..b958607c71dcf3096b2f676683cc337dc12a9c9b 100644 --- a/arch/arm/boot/dts/am335x-bone-common.dtsi +++ b/arch/arm/boot/dts/ti/omap/am335x-bone-common.dtsi @@ -66,7 +66,7 @@ pinctrl-names = "default"; pinctrl-0 = <&clkout2_pin>; - user_leds_s0: user_leds_s0 { + user_leds_s0: user-leds-s0-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_GPMC_A5, PIN_OUTPUT_PULLDOWN, MUX_MODE7) /* gpmc_a5.gpio1_21 */ AM33XX_PADCONF(AM335X_PIN_GPMC_A6, PIN_OUTPUT_PULLUP, MUX_MODE7) /* gpmc_a6.gpio1_22 */ @@ -75,34 +75,34 @@ >; }; - i2c0_pins: pinmux_i2c0_pins { + i2c0_pins: i2c0-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_I2C0_SDA, PIN_INPUT_PULLUP, MUX_MODE0) /* i2c0_sda.i2c0_sda */ AM33XX_PADCONF(AM335X_PIN_I2C0_SCL, PIN_INPUT_PULLUP, MUX_MODE0) /* i2c0_scl.i2c0_scl */ >; }; - i2c2_pins: pinmux_i2c2_pins { + i2c2_pins: i2c2-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_UART1_CTSN, PIN_INPUT_PULLUP, MUX_MODE3) /* uart1_ctsn.i2c2_sda */ AM33XX_PADCONF(AM335X_PIN_UART1_RTSN, PIN_INPUT_PULLUP, MUX_MODE3) /* uart1_rtsn.i2c2_scl */ >; }; - uart0_pins: pinmux_uart0_pins { + uart0_pins: uart0-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_UART0_RXD, PIN_INPUT_PULLUP, MUX_MODE0) AM33XX_PADCONF(AM335X_PIN_UART0_TXD, PIN_OUTPUT_PULLDOWN, MUX_MODE0) >; }; - clkout2_pin: pinmux_clkout2_pin { + clkout2_pin: clkout2-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_XDMA_EVENT_INTR1, PIN_OUTPUT_PULLDOWN, MUX_MODE3) /* xdma_event_intr1.clkout2 */ >; }; - cpsw_default: cpsw_default { + cpsw_default: cpsw-default-pins { pinctrl-single,pins = < /* Slave 1 */ AM33XX_PADCONF(AM335X_PIN_MII1_RX_ER, PIN_INPUT_PULLUP, MUX_MODE0) @@ -121,7 +121,7 @@ >; }; - cpsw_sleep: cpsw_sleep { + cpsw_sleep: cpsw-sleep-pins { pinctrl-single,pins = < /* Slave 1 reset value */ AM33XX_PADCONF(AM335X_PIN_MII1_RX_ER, PIN_INPUT_PULLDOWN, MUX_MODE7) @@ -140,7 +140,7 @@ >; }; - davinci_mdio_default: davinci_mdio_default { + davinci_mdio_default: davinci-mdio-default-pins { pinctrl-single,pins = < /* MDIO */ AM33XX_PADCONF(AM335X_PIN_MDIO, PIN_INPUT_PULLUP | SLEWCTRL_FAST, MUX_MODE0) @@ -148,7 +148,7 @@ >; }; - davinci_mdio_sleep: davinci_mdio_sleep { + davinci_mdio_sleep: davinci-mdio-sleep-pins { pinctrl-single,pins = < /* MDIO reset value */ AM33XX_PADCONF(AM335X_PIN_MDIO, PIN_INPUT_PULLDOWN, MUX_MODE7) @@ -156,7 +156,7 @@ >; }; - mmc1_pins: pinmux_mmc1_pins { + mmc1_pins: mmc1-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_SPI0_CS1, PIN_INPUT, MUX_MODE7) /* spio0_cs1.gpio0_6 */ AM33XX_PADCONF(AM335X_PIN_MMC0_DAT0, PIN_INPUT_PULLUP, MUX_MODE0) @@ -168,7 +168,7 @@ >; }; - emmc_pins: pinmux_emmc_pins { + emmc_pins: emmc-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_GPMC_CSN1, PIN_INPUT_PULLUP, MUX_MODE2) /* gpmc_csn1.mmc1_clk */ AM33XX_PADCONF(AM335X_PIN_GPMC_CSN2, PIN_INPUT_PULLUP, MUX_MODE2) /* gpmc_csn2.mmc1_cmd */ @@ -273,7 +273,7 @@ }; -/include/ "tps65217.dtsi" +/include/ "../../tps65217.dtsi" &tps { /* diff --git a/arch/arm/boot/dts/am335x-bone.dts b/arch/arm/boot/dts/ti/omap/am335x-bone.dts similarity index 100% rename from arch/arm/boot/dts/am335x-bone.dts rename to arch/arm/boot/dts/ti/omap/am335x-bone.dts diff --git a/arch/arm/boot/dts/am335x-boneblack-common.dtsi b/arch/arm/boot/dts/ti/omap/am335x-boneblack-common.dtsi similarity index 100% rename from arch/arm/boot/dts/am335x-boneblack-common.dtsi rename to arch/arm/boot/dts/ti/omap/am335x-boneblack-common.dtsi diff --git a/arch/arm/boot/dts/am335x-boneblack-hdmi.dtsi b/arch/arm/boot/dts/ti/omap/am335x-boneblack-hdmi.dtsi similarity index 97% rename from arch/arm/boot/dts/am335x-boneblack-hdmi.dtsi rename to arch/arm/boot/dts/ti/omap/am335x-boneblack-hdmi.dtsi index 486f24deb875c688313fe525c586970da0ff8dc4..109f08fd174d62b891838cb31bebb383aa3981ca 100644 --- a/arch/arm/boot/dts/am335x-boneblack-hdmi.dtsi +++ b/arch/arm/boot/dts/ti/omap/am335x-boneblack-hdmi.dtsi @@ -7,7 +7,7 @@ #include &am33xx_pinmux { - nxp_hdmi_bonelt_pins: nxp_hdmi_bonelt_pins { + nxp_hdmi_bonelt_pins: nxp-hdmi-bonelt-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_XDMA_EVENT_INTR0, PIN_OUTPUT_PULLDOWN, MUX_MODE3) AM33XX_PADCONF(AM335X_PIN_LCD_DATA0, PIN_OUTPUT, MUX_MODE0) @@ -33,13 +33,13 @@ >; }; - nxp_hdmi_bonelt_off_pins: nxp_hdmi_bonelt_off_pins { + nxp_hdmi_bonelt_off_pins: nxp-hdmi-bonelt-off-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_XDMA_EVENT_INTR0, PIN_OUTPUT_PULLDOWN, MUX_MODE3) >; }; - mcasp0_pins: mcasp0_pins { + mcasp0_pins: mcasp0-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_MCASP0_AHCLKX, PIN_INPUT_PULLUP, MUX_MODE0) /* mcasp0_ahcklx.mcasp0_ahclkx */ AM33XX_PADCONF(AM335X_PIN_MCASP0_AHCLKR, PIN_OUTPUT_PULLDOWN, MUX_MODE2) /* mcasp0_ahclkr.mcasp0_axr2*/ diff --git a/arch/arm/boot/dts/am335x-boneblack-wireless.dts b/arch/arm/boot/dts/ti/omap/am335x-boneblack-wireless.dts similarity index 96% rename from arch/arm/boot/dts/am335x-boneblack-wireless.dts rename to arch/arm/boot/dts/ti/omap/am335x-boneblack-wireless.dts index 207d2b63e0eb37e3a87d1793f15f43bf5cb5e249..b4b4b80df08cd3e21f007d5087e4f691aea029b8 100644 --- a/arch/arm/boot/dts/am335x-boneblack-wireless.dts +++ b/arch/arm/boot/dts/ti/omap/am335x-boneblack-wireless.dts @@ -28,13 +28,13 @@ }; &am33xx_pinmux { - bt_pins: pinmux_bt_pins { + bt_pins: bt-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_MII1_TXD0, PIN_OUTPUT_PULLUP, MUX_MODE7) /* gmii1_txd0.gpio0_28 - BT_EN */ >; }; - mmc3_pins: pinmux_mmc3_pins { + mmc3_pins: mmc3-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_MII1_RXD1, PIN_INPUT_PULLUP, MUX_MODE6 ) /* (L15) gmii1_rxd1.mmc2_clk */ AM33XX_PADCONF(AM335X_PIN_MII1_TX_EN, PIN_INPUT_PULLUP, MUX_MODE6 ) /* (J16) gmii1_txen.mmc2_cmd */ @@ -45,7 +45,7 @@ >; }; - uart3_pins: pinmux_uart3_pins { + uart3_pins: uart3-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_MII1_RXD3, PIN_INPUT_PULLUP, MUX_MODE1) /* gmii1_rxd3.uart3_rxd */ AM33XX_PADCONF(AM335X_PIN_MII1_RXD2, PIN_OUTPUT_PULLDOWN, MUX_MODE1) /* gmii1_rxd2.uart3_txd */ @@ -54,7 +54,7 @@ >; }; - wl18xx_pins: pinmux_wl18xx_pins { + wl18xx_pins: wl18xx-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_MII1_TX_CLK, PIN_OUTPUT_PULLDOWN, MUX_MODE7) /* gmii1_txclk.gpio3_9 WL_EN */ AM33XX_PADCONF(AM335X_PIN_RMII1_REF_CLK, PIN_INPUT_PULLDOWN, MUX_MODE7) /* rmii1_refclk.gpio0_29 WL_IRQ */ diff --git a/arch/arm/boot/dts/am335x-boneblack.dts b/arch/arm/boot/dts/ti/omap/am335x-boneblack.dts similarity index 100% rename from arch/arm/boot/dts/am335x-boneblack.dts rename to arch/arm/boot/dts/ti/omap/am335x-boneblack.dts diff --git a/arch/arm/boot/dts/am335x-boneblue.dts b/arch/arm/boot/dts/ti/omap/am335x-boneblue.dts similarity index 96% rename from arch/arm/boot/dts/am335x-boneblue.dts rename to arch/arm/boot/dts/ti/omap/am335x-boneblue.dts index 34579e98636e637c09aa68cf3bd57b58c19f0f04..801399702547d0b0512271d0964626534c1914a1 100644 --- a/arch/arm/boot/dts/am335x-boneblue.dts +++ b/arch/arm/boot/dts/ti/omap/am335x-boneblue.dts @@ -115,7 +115,7 @@ }; &am33xx_pinmux { - user_leds_s0: user_leds_s0 { + user_leds_s0: user-leds-s0-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_GPMC_A5, PIN_OUTPUT, MUX_MODE7) /* (V15) gpmc_a5.gpio1[21] - USR_LED_0 */ AM33XX_PADCONF(AM335X_PIN_GPMC_A6, PIN_OUTPUT, MUX_MODE7) /* (U15) gpmc_a6.gpio1[22] - USR_LED_1 */ @@ -132,7 +132,7 @@ >; }; - i2c2_pins: pinmux_i2c2_pins { + i2c2_pins: i2c2-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_UART1_CTSN, PIN_INPUT_PULLUP, MUX_MODE3) /* (D18) uart1_ctsn.I2C2_SDA */ AM33XX_PADCONF(AM335X_PIN_UART1_RTSN, PIN_INPUT_PULLUP, MUX_MODE3) /* (D17) uart1_rtsn.I2C2_SCL */ @@ -140,7 +140,7 @@ }; /* UT0 */ - uart0_pins: pinmux_uart0_pins { + uart0_pins: uart0-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_UART0_RXD, PIN_INPUT_PULLUP, MUX_MODE0) AM33XX_PADCONF(AM335X_PIN_UART0_TXD, PIN_OUTPUT_PULLDOWN, MUX_MODE0) @@ -148,7 +148,7 @@ }; /* UT1 */ - uart1_pins: pinmux_uart1_pins { + uart1_pins: uart1-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_UART1_RXD, PIN_INPUT_PULLUP, MUX_MODE0) AM33XX_PADCONF(AM335X_PIN_UART1_TXD, PIN_OUTPUT_PULLDOWN, MUX_MODE0) @@ -156,7 +156,7 @@ }; /* GPS */ - uart2_pins: pinmux_uart2_pins { + uart2_pins: uart2-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_SPI0_SCLK, PIN_INPUT_PULLUP, MUX_MODE1) /* (A17) spi0_sclk.uart2_rxd */ AM33XX_PADCONF(AM335X_PIN_SPI0_D0, PIN_OUTPUT_PULLDOWN, MUX_MODE1) /* (B17) spi0_d0.uart2_txd */ @@ -164,27 +164,27 @@ }; /* DSM2 */ - uart4_pins: pinmux_uart4_pins { + uart4_pins: uart4-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_GPMC_WAIT0, PIN_INPUT_PULLUP, MUX_MODE6) /* (T17) gpmc_wait0.uart4_rxd */ >; }; /* UT5 */ - uart5_pins: pinmux_uart5_pins { + uart5_pins: uart5-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_LCD_DATA9, PIN_INPUT_PULLUP, MUX_MODE4) /* (U2) lcd_data9.uart5_rxd */ AM33XX_PADCONF(AM335X_PIN_LCD_DATA8, PIN_OUTPUT_PULLDOWN, MUX_MODE4) /* (U1) lcd_data8.uart5_txd */ >; }; - mmc1_pins: pinmux_mmc1_pins { + mmc1_pins: mmc1-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_SPI0_CS1, PIN_INPUT, MUX_MODE7) /* (C15) spi0_cs1.gpio0[6] */ >; }; - mmc2_pins: pinmux_mmc2_pins { + mmc2_pins: mmc2-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_GPMC_CSN1, PIN_INPUT_PULLUP, MUX_MODE2) /* (U9) gpmc_csn1.mmc1_clk */ AM33XX_PADCONF(AM335X_PIN_GPMC_CSN2, PIN_INPUT_PULLUP, MUX_MODE2) /* (V9) gpmc_csn2.mmc1_cmd */ @@ -199,7 +199,7 @@ >; }; - mmc3_pins: pinmux_mmc3_pins { + mmc3_pins: mmc3-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_MII1_RXD1, PIN_INPUT_PULLUP, MUX_MODE6) /* (L15) gmii1_rxd1.mmc2_clk */ AM33XX_PADCONF(AM335X_PIN_MII1_TX_EN, PIN_INPUT_PULLUP, MUX_MODE6) /* (J16) gmii1_txen.mmc2_cmd */ @@ -210,13 +210,13 @@ >; }; - bt_pins: pinmux_bt_pins { + bt_pins: bt-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_MII1_TXD0, PIN_OUTPUT_PULLUP, MUX_MODE7) /* (K17) gmii1_txd0.gpio0[28] - BT_EN */ >; }; - uart3_pins: pinmux_uart3_pins { + uart3_pins: uart3-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_MII1_RXD3, PIN_INPUT_PULLUP, MUX_MODE1) /* (L17) gmii1_rxd3.uart3_rxd */ AM33XX_PADCONF(AM335X_PIN_MII1_RXD2, PIN_OUTPUT_PULLDOWN, MUX_MODE1) /* (L16) gmii1_rxd2.uart3_txd */ @@ -225,7 +225,7 @@ >; }; - wl18xx_pins: pinmux_wl18xx_pins { + wl18xx_pins: wl18xx-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_MII1_TX_CLK, PIN_OUTPUT_PULLDOWN, MUX_MODE7) /* (K18) gmii1_txclk.gpio3[9] - WL_EN */ AM33XX_PADCONF(AM335X_PIN_MII1_TXD1, PIN_INPUT_PULLDOWN, MUX_MODE7) /* (K16) gmii1_txd1.gpio0[21] - WL_IRQ */ @@ -234,7 +234,7 @@ }; /* DCAN */ - dcan1_pins: pinmux_dcan1_pins { + dcan1_pins: dcan1-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_UART0_RTSN, PIN_INPUT, MUX_MODE2) /* (E17) uart0_rtsn.dcan1_rx */ AM33XX_PADCONF(AM335X_PIN_UART0_CTSN, PIN_OUTPUT, MUX_MODE2) /* (E18) uart0_ctsn.dcan1_tx */ @@ -243,7 +243,7 @@ }; /* E1 */ - eqep0_pins: pinmux_eqep0_pins { + eqep0_pins: eqep0-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_MCASP0_AXR0, PIN_INPUT, MUX_MODE1) /* (B12) mcasp0_aclkr.eQEP0A_in */ AM33XX_PADCONF(AM335X_PIN_MCASP0_FSR, PIN_INPUT, MUX_MODE1) /* (C13) mcasp0_fsr.eQEP0B_in */ @@ -251,7 +251,7 @@ }; /* E2 */ - eqep1_pins: pinmux_eqep1_pins { + eqep1_pins: eqep1-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_LCD_DATA12, PIN_INPUT, MUX_MODE2) /* (V2) lcd_data12.eQEP1A_in */ AM33XX_PADCONF(AM335X_PIN_LCD_DATA13, PIN_INPUT, MUX_MODE2) /* (V3) lcd_data13.eQEP1B_in */ @@ -259,7 +259,7 @@ }; /* E3 */ - eqep2_pins: pinmux_eqep2_pins { + eqep2_pins: eqep2-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_GPMC_AD12, PIN_INPUT, MUX_MODE4) /* (T12) gpmc_ad12.eQEP2A_in */ AM33XX_PADCONF(AM335X_PIN_GPMC_AD13, PIN_INPUT, MUX_MODE4) /* (R12) gpmc_ad13.eQEP2B_in */ @@ -353,7 +353,7 @@ }; }; -/include/ "tps65217.dtsi" +/include/ "../../tps65217.dtsi" &tps { /delete-property/ ti,pmic-shutdown-controller; diff --git a/arch/arm/boot/dts/am335x-bonegreen-common.dtsi b/arch/arm/boot/dts/ti/omap/am335x-bonegreen-common.dtsi similarity index 96% rename from arch/arm/boot/dts/am335x-bonegreen-common.dtsi rename to arch/arm/boot/dts/ti/omap/am335x-bonegreen-common.dtsi index 9f7fb63744d01deacc017361df2334d12d52ae8d..383beeddf595de8091febc18c4675268d7308ee1 100644 --- a/arch/arm/boot/dts/am335x-bonegreen-common.dtsi +++ b/arch/arm/boot/dts/ti/omap/am335x-bonegreen-common.dtsi @@ -22,7 +22,7 @@ }; &am33xx_pinmux { - uart2_pins: uart2_pins { + uart2_pins: uart2-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_SPI0_SCLK, PIN_INPUT, MUX_MODE1) /* spi0_sclk.uart2_rxd */ AM33XX_PADCONF(AM335X_PIN_SPI0_D0, PIN_OUTPUT, MUX_MODE1) /* spi0_d0.uart2_txd */ diff --git a/arch/arm/boot/dts/am335x-bonegreen-wireless.dts b/arch/arm/boot/dts/ti/omap/am335x-bonegreen-wireless.dts similarity index 96% rename from arch/arm/boot/dts/am335x-bonegreen-wireless.dts rename to arch/arm/boot/dts/ti/omap/am335x-bonegreen-wireless.dts index d388cffa1a4d61d79ee90a874b4c6d06ea518f99..a4f5b52626456c4c7c07696728c3156fab8b1fb3 100644 --- a/arch/arm/boot/dts/am335x-bonegreen-wireless.dts +++ b/arch/arm/boot/dts/ti/omap/am335x-bonegreen-wireless.dts @@ -27,13 +27,13 @@ }; &am33xx_pinmux { - bt_pins: pinmux_bt_pins { + bt_pins: bt-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_GPMC_BEN1, PIN_OUTPUT_PULLUP, MUX_MODE7) /* gpmc_ad12.gpio1_28 BT_EN */ >; }; - mmc3_pins: pinmux_mmc3_pins { + mmc3_pins: mmc3-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_GPMC_AD12, PIN_INPUT_PULLUP, MUX_MODE3) /* gpmc_ad12.mmc2_dat0 */ AM33XX_PADCONF(AM335X_PIN_GPMC_AD13, PIN_INPUT_PULLUP, MUX_MODE3) /* gpmc_ad13.mmc2_dat1 */ @@ -44,7 +44,7 @@ >; }; - uart3_pins: pinmux_uart3_pins { + uart3_pins: uart3-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_MII1_RXD3, PIN_INPUT_PULLUP, MUX_MODE1) /* gmii1_rxd3.uart3_rxd */ AM33XX_PADCONF(AM335X_PIN_MII1_RXD2, PIN_OUTPUT_PULLDOWN, MUX_MODE1) /* gmii1_rxd2.uart3_txd */ @@ -53,7 +53,7 @@ >; }; - wl18xx_pins: pinmux_wl18xx_pins { + wl18xx_pins: wl18xx-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_GPMC_AD10, PIN_OUTPUT_PULLDOWN, MUX_MODE7) /* gpmc_ad10.gpio0_26 WL_EN */ AM33XX_PADCONF(AM335X_PIN_GPMC_AD11, PIN_INPUT_PULLDOWN, MUX_MODE7) /* gpmc_ad11.gpio0_27 WL_IRQ */ diff --git a/arch/arm/boot/dts/am335x-bonegreen.dts b/arch/arm/boot/dts/ti/omap/am335x-bonegreen.dts similarity index 100% rename from arch/arm/boot/dts/am335x-bonegreen.dts rename to arch/arm/boot/dts/ti/omap/am335x-bonegreen.dts diff --git a/arch/arm/boot/dts/am335x-chiliboard.dts b/arch/arm/boot/dts/ti/omap/am335x-chiliboard.dts similarity index 94% rename from arch/arm/boot/dts/am335x-chiliboard.dts rename to arch/arm/boot/dts/ti/omap/am335x-chiliboard.dts index a223cdd3e30e88dfe5782e9903e4fef13fcbd30d..648e97fe1dfd5e5b821ced946d6219c497dd1d29 100644 --- a/arch/arm/boot/dts/am335x-chiliboard.dts +++ b/arch/arm/boot/dts/ti/omap/am335x-chiliboard.dts @@ -36,14 +36,14 @@ }; &am33xx_pinmux { - uart0_pins: pinmux_uart0_pins { + uart0_pins: uart0-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_UART0_RXD, PIN_INPUT_PULLUP, MUX_MODE0) AM33XX_PADCONF(AM335X_PIN_UART0_TXD, PIN_OUTPUT_PULLDOWN, MUX_MODE0) >; }; - cpsw_default: cpsw_default { + cpsw_default: cpsw-default-pins { pinctrl-single,pins = < /* Slave 1 */ AM33XX_PADCONF(AM335X_PIN_MII1_CRS, PIN_INPUT_PULLDOWN, MUX_MODE1) @@ -57,7 +57,7 @@ >; }; - cpsw_sleep: cpsw_sleep { + cpsw_sleep: cpsw-sleep-pins { pinctrl-single,pins = < /* Slave 1 reset value */ AM33XX_PADCONF(AM335X_PIN_MII1_CRS, PIN_INPUT_PULLDOWN, MUX_MODE7) @@ -72,7 +72,7 @@ >; }; - davinci_mdio_default: davinci_mdio_default { + davinci_mdio_default: davinci-mdio-default-pins { pinctrl-single,pins = < /* mdio_data.mdio_data */ AM33XX_PADCONF(AM335X_PIN_MDIO, PIN_INPUT_PULLUP | SLEWCTRL_FAST, MUX_MODE0) @@ -81,7 +81,7 @@ >; }; - davinci_mdio_sleep: davinci_mdio_sleep { + davinci_mdio_sleep: davinci-mdio-sleep-pins { pinctrl-single,pins = < /* MDIO reset value */ AM33XX_PADCONF(AM335X_PIN_MDIO, PIN_INPUT_PULLDOWN, MUX_MODE7) @@ -89,13 +89,13 @@ >; }; - usb1_drvvbus: usb1_drvvbus { + usb1_drvvbus: usb1-drvvbus-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_USB1_DRVVBUS, PIN_OUTPUT_PULLDOWN, MUX_MODE0) >; }; - sd_pins: pinmux_sd_card { + sd_pins: sd-card-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_MMC0_DAT3, PIN_INPUT, MUX_MODE0) AM33XX_PADCONF(AM335X_PIN_MMC0_DAT2, PIN_INPUT, MUX_MODE0) @@ -107,7 +107,7 @@ >; }; - led_gpio_pins: led_gpio_pins { + led_gpio_pins: led-gpio-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_EMU0, PIN_OUTPUT, MUX_MODE7) /* emu0.gpio3_7 */ AM33XX_PADCONF(AM335X_PIN_EMU1, PIN_OUTPUT, MUX_MODE7) /* emu1.gpio3_8 */ diff --git a/arch/arm/boot/dts/am335x-chilisom.dtsi b/arch/arm/boot/dts/ti/omap/am335x-chilisom.dtsi similarity index 97% rename from arch/arm/boot/dts/am335x-chilisom.dtsi rename to arch/arm/boot/dts/ti/omap/am335x-chilisom.dtsi index 43b61e43ed1eecb89eaaa4fef4d7d8060b3de9f2..bd43da6356b6680cc05568d722f155d5710f175b 100644 --- a/arch/arm/boot/dts/am335x-chilisom.dtsi +++ b/arch/arm/boot/dts/ti/omap/am335x-chilisom.dtsi @@ -25,14 +25,14 @@ &am33xx_pinmux { pinctrl-names = "default"; - i2c0_pins: pinmux_i2c0_pins { + i2c0_pins: i2c0-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_I2C0_SDA, PIN_INPUT_PULLUP, MUX_MODE0) AM33XX_PADCONF(AM335X_PIN_I2C0_SCL, PIN_INPUT_PULLUP, MUX_MODE0) >; }; - nandflash_pins: nandflash_pins { + nandflash_pins: nandflash-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_GPMC_AD0, PIN_INPUT_PULLDOWN, MUX_MODE0) AM33XX_PADCONF(AM335X_PIN_GPMC_AD1, PIN_INPUT_PULLDOWN, MUX_MODE0) @@ -66,7 +66,7 @@ }; -/include/ "tps65217.dtsi" +/include/ "../../tps65217.dtsi" &tps { regulators { diff --git a/arch/arm/boot/dts/am335x-cm-t335.dts b/arch/arm/boot/dts/ti/omap/am335x-cm-t335.dts similarity index 95% rename from arch/arm/boot/dts/am335x-cm-t335.dts rename to arch/arm/boot/dts/ti/omap/am335x-cm-t335.dts index 993b1342069966a716c014b8a369b75d0588cef9..72990e7ffe10ee0ad399274455d518920520e6af 100644 --- a/arch/arm/boot/dts/am335x-cm-t335.dts +++ b/arch/arm/boot/dts/ti/omap/am335x-cm-t335.dts @@ -88,14 +88,14 @@ pinctrl-names = "default"; pinctrl-0 = <&bluetooth_pins>; - i2c0_pins: pinmux_i2c0_pins { + i2c0_pins: i2c0-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_I2C0_SDA, PIN_INPUT_PULLUP, MUX_MODE0) AM33XX_PADCONF(AM335X_PIN_I2C0_SCL, PIN_INPUT_PULLUP, MUX_MODE0) >; }; - i2c1_pins: pinmux_i2c1_pins { + i2c1_pins: i2c1-pins { pinctrl-single,pins = < /* uart0_ctsn.i2c1_sda */ AM33XX_PADCONF(AM335X_PIN_UART0_CTSN, PIN_INPUT_PULLUP, MUX_MODE2) @@ -104,14 +104,14 @@ >; }; - gpio_led_pins: pinmux_gpio_led_pins { + gpio_led_pins: gpio-led-pins { pinctrl-single,pins = < /* gpmc_csn3.gpio2_0 */ AM33XX_PADCONF(AM335X_PIN_GPMC_CSN3, PIN_OUTPUT, MUX_MODE7) >; }; - nandflash_pins: pinmux_nandflash_pins { + nandflash_pins: nandflash-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_GPMC_AD0, PIN_INPUT_PULLUP, MUX_MODE0) AM33XX_PADCONF(AM335X_PIN_GPMC_AD1, PIN_INPUT_PULLUP, MUX_MODE0) @@ -132,14 +132,14 @@ >; }; - uart0_pins: pinmux_uart0_pins { + uart0_pins: uart0-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_UART0_RXD, PIN_INPUT_PULLUP, MUX_MODE0) AM33XX_PADCONF(AM335X_PIN_UART0_TXD, PIN_OUTPUT_PULLDOWN, MUX_MODE0) >; }; - uart1_pins: pinmux_uart1_pins { + uart1_pins: uart1-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_UART1_CTSN, PIN_INPUT, MUX_MODE0) AM33XX_PADCONF(AM335X_PIN_UART1_RTSN, PIN_OUTPUT_PULLDOWN, MUX_MODE0) @@ -148,7 +148,7 @@ >; }; - dcan0_pins: pinmux_dcan0_pins { + dcan0_pins: dcan0-pins { pinctrl-single,pins = < /* uart1_ctsn.dcan0_tx */ AM33XX_PADCONF(AM335X_PIN_UART1_CTSN, PIN_OUTPUT, MUX_MODE2) @@ -157,7 +157,7 @@ >; }; - dcan1_pins: pinmux_dcan1_pins { + dcan1_pins: dcan1-pins { pinctrl-single,pins = < /* uart1_rxd.dcan1_tx */ AM33XX_PADCONF(AM335X_PIN_UART1_RXD, PIN_OUTPUT, MUX_MODE2) @@ -166,13 +166,13 @@ >; }; - ecap0_pins: pinmux_ecap0_pins { + ecap0_pins: ecap0-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_ECAP0_IN_PWM0_OUT, 0x0, MUX_MODE0) >; }; - cpsw_default: cpsw_default { + cpsw_default: cpsw-default-pins { pinctrl-single,pins = < /* Slave 1 */ /* mii1_tx_en.rgmii1_tctl */ @@ -202,7 +202,7 @@ >; }; - cpsw_sleep: cpsw_sleep { + cpsw_sleep: cpsw-sleep-pins { pinctrl-single,pins = < /* Slave 1 reset value */ AM33XX_PADCONF(AM335X_PIN_MII1_TX_EN, PIN_INPUT_PULLDOWN, MUX_MODE7) @@ -220,14 +220,14 @@ >; }; - davinci_mdio_default: davinci_mdio_default { + davinci_mdio_default: davinci-mdio-default-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_MDIO, PIN_INPUT_PULLUP | SLEWCTRL_FAST, MUX_MODE0) AM33XX_PADCONF(AM335X_PIN_MDC, PIN_OUTPUT_PULLUP, MUX_MODE0) >; }; - davinci_mdio_sleep: davinci_mdio_sleep { + davinci_mdio_sleep: davinci-mdio-sleep-pins { pinctrl-single,pins = < /* MDIO reset value */ AM33XX_PADCONF(AM335X_PIN_MDIO, PIN_INPUT_PULLDOWN, MUX_MODE7) @@ -235,7 +235,7 @@ >; }; - mmc1_pins: pinmux_mmc1_pins { + mmc1_pins: mmc1-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_MMC0_DAT3, PIN_INPUT_PULLUP, MUX_MODE0) AM33XX_PADCONF(AM335X_PIN_MMC0_DAT2, PIN_INPUT_PULLUP, MUX_MODE0) @@ -246,7 +246,7 @@ >; }; - spi0_pins: pinmux_spi0_pins { + spi0_pins: spi0-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_SPI0_SCLK, PIN_INPUT, MUX_MODE0) AM33XX_PADCONF(AM335X_PIN_SPI0_D0, PIN_OUTPUT_PULLUP, MUX_MODE0) @@ -257,7 +257,7 @@ }; /* wl1271 bluetooth */ - bluetooth_pins: pinmux_bluetooth_pins { + bluetooth_pins: bluetooth-pins { pinctrl-single,pins = < /* XDMA_EVENT_INTR0.gpio0_19 - bluetooth enable */ AM33XX_PADCONF(AM335X_PIN_XDMA_EVENT_INTR0, PIN_OUTPUT_PULLUP, MUX_MODE7) @@ -265,7 +265,7 @@ }; /* TLV320AIC23B codec */ - mcasp1_pins: pinmux_mcasp1_pins { + mcasp1_pins: mcasp1-pins { pinctrl-single,pins = < /* MII1_CRS.mcasp1_aclkx */ AM33XX_PADCONF(AM335X_PIN_MII1_CRS, PIN_INPUT_PULLDOWN, MUX_MODE4) @@ -279,7 +279,7 @@ }; /* wl1271 WiFi */ - wifi_pins: pinmux_wifi_pins { + wifi_pins: wifi-pins { pinctrl-single,pins = < /* EMU1.gpio3_8 - WiFi IRQ */ AM33XX_PADCONF(AM335X_PIN_EMU1, PIN_INPUT_PULLUP, MUX_MODE7) diff --git a/arch/arm/boot/dts/am335x-evm.dts b/arch/arm/boot/dts/ti/omap/am335x-evm.dts similarity index 96% rename from arch/arm/boot/dts/am335x-evm.dts rename to arch/arm/boot/dts/ti/omap/am335x-evm.dts index 5beabaa5ff6a1fa8537e0b42d4ca87a51a1f7e13..61bf8bcd4c4ed7c037db51da61ec0c4443b2a01a 100644 --- a/arch/arm/boot/dts/am335x-evm.dts +++ b/arch/arm/boot/dts/ti/omap/am335x-evm.dts @@ -163,7 +163,7 @@ pinctrl-names = "default"; pinctrl-0 = <&matrix_keypad_s0 &volume_keys_s0 &clkout2_pin>; - matrix_keypad_s0: matrix_keypad_s0 { + matrix_keypad_s0: matrix-keypad-s0-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_GPMC_A5, PIN_OUTPUT_PULLDOWN, MUX_MODE7) /* gpmc_a5.gpio1_21 */ AM33XX_PADCONF(AM335X_PIN_GPMC_A6, PIN_OUTPUT_PULLDOWN, MUX_MODE7) /* gpmc_a6.gpio1_22 */ @@ -173,35 +173,35 @@ >; }; - volume_keys_s0: volume_keys_s0 { + volume_keys_s0: volume-keys-s0-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_SPI0_SCLK, PIN_INPUT_PULLDOWN, MUX_MODE7) /* spi0_sclk.gpio0_2 */ AM33XX_PADCONF(AM335X_PIN_SPI0_D0, PIN_INPUT_PULLDOWN, MUX_MODE7) /* spi0_d0.gpio0_3 */ >; }; - i2c0_pins: pinmux_i2c0_pins { + i2c0_pins: i2c0-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_I2C0_SDA, PIN_INPUT_PULLUP, MUX_MODE0) /* i2c0_sda.i2c0_sda */ AM33XX_PADCONF(AM335X_PIN_I2C0_SCL, PIN_INPUT_PULLUP, MUX_MODE0) /* i2c0_scl.i2c0_scl */ >; }; - i2c1_pins: pinmux_i2c1_pins { + i2c1_pins: i2c1-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_SPI0_D1, PIN_INPUT_PULLUP, MUX_MODE2) /* spi0_d1.i2c1_sda */ AM33XX_PADCONF(AM335X_PIN_SPI0_CS0, PIN_INPUT_PULLUP, MUX_MODE2) /* spi0_cs0.i2c1_scl */ >; }; - uart0_pins: pinmux_uart0_pins { + uart0_pins: uart0-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_UART0_RXD, PIN_INPUT_PULLUP, MUX_MODE0) AM33XX_PADCONF(AM335X_PIN_UART0_TXD, PIN_OUTPUT_PULLDOWN, MUX_MODE0) >; }; - uart1_pins: pinmux_uart1_pins { + uart1_pins: uart1-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_UART1_CTSN, PIN_INPUT, MUX_MODE0) AM33XX_PADCONF(AM335X_PIN_UART1_RTSN, PIN_OUTPUT_PULLDOWN, MUX_MODE0) @@ -210,13 +210,13 @@ >; }; - clkout2_pin: pinmux_clkout2_pin { + clkout2_pin: clkout2-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_XDMA_EVENT_INTR1, PIN_OUTPUT_PULLDOWN, MUX_MODE3) /* xdma_event_intr1.clkout2 */ >; }; - nandflash_pins_s0: nandflash_pins_s0 { + nandflash_pins_s0: nandflash-s0-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_GPMC_AD0, PIN_INPUT_PULLUP, MUX_MODE0) AM33XX_PADCONF(AM335X_PIN_GPMC_AD1, PIN_INPUT_PULLUP, MUX_MODE0) @@ -236,13 +236,13 @@ >; }; - ecap0_pins: backlight_pins { + ecap0_pins: backlight-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_ECAP0_IN_PWM0_OUT, 0x0, MUX_MODE0) >; }; - cpsw_default: cpsw_default { + cpsw_default: cpsw-default-pins { pinctrl-single,pins = < /* Slave 1 */ AM33XX_PADCONF(AM335X_PIN_MII1_TX_EN, PIN_OUTPUT_PULLDOWN, MUX_MODE2) /* mii1_txen.rgmii1_tctl */ @@ -260,7 +260,7 @@ >; }; - cpsw_sleep: cpsw_sleep { + cpsw_sleep: cpsw-sleep-pins { pinctrl-single,pins = < /* Slave 1 reset value */ AM33XX_PADCONF(AM335X_PIN_MII1_TX_EN, PIN_INPUT_PULLDOWN, MUX_MODE7) @@ -278,7 +278,7 @@ >; }; - davinci_mdio_default: davinci_mdio_default { + davinci_mdio_default: davinci-mdio-default-pins { pinctrl-single,pins = < /* MDIO */ AM33XX_PADCONF(AM335X_PIN_MDIO, PIN_INPUT_PULLUP | SLEWCTRL_FAST, MUX_MODE0) @@ -286,7 +286,7 @@ >; }; - davinci_mdio_sleep: davinci_mdio_sleep { + davinci_mdio_sleep: davinci-mdio-sleep-pins { pinctrl-single,pins = < /* MDIO reset value */ AM33XX_PADCONF(AM335X_PIN_MDIO, PIN_INPUT_PULLDOWN, MUX_MODE7) @@ -294,7 +294,7 @@ >; }; - mmc1_pins: pinmux_mmc1_pins { + mmc1_pins: mmc1-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_SPI0_CS1, PIN_INPUT, MUX_MODE7) /* spi0_cs1.gpio0_6 */ AM33XX_PADCONF(AM335X_PIN_MMC0_DAT0, PIN_INPUT_PULLUP, MUX_MODE0) @@ -307,7 +307,7 @@ >; }; - mmc3_pins: pinmux_mmc3_pins { + mmc3_pins: mmc3-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_GPMC_A1, PIN_INPUT_PULLUP, MUX_MODE3) /* gpmc_a1.mmc2_dat0, INPUT_PULLUP | MODE3 */ AM33XX_PADCONF(AM335X_PIN_GPMC_A2, PIN_INPUT_PULLUP, MUX_MODE3) /* gpmc_a2.mmc2_dat1, INPUT_PULLUP | MODE3 */ @@ -318,7 +318,7 @@ >; }; - wlan_pins: pinmux_wlan_pins { + wlan_pins: wlan-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_GPMC_A0, PIN_OUTPUT_PULLDOWN, MUX_MODE7) /* gpmc_a0.gpio1_16 */ AM33XX_PADCONF(AM335X_PIN_MCASP0_AHCLKR, PIN_INPUT, MUX_MODE7) /* mcasp0_ahclkr.gpio3_17 */ @@ -326,7 +326,7 @@ >; }; - lcd_pins_s0: lcd_pins_s0 { + lcd_pins_s0: lcd-s0-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_GPMC_AD8, PIN_OUTPUT, MUX_MODE1) /* gpmc_ad8.lcd_data23 */ AM33XX_PADCONF(AM335X_PIN_GPMC_AD9, PIN_OUTPUT, MUX_MODE1) /* gpmc_ad9.lcd_data22 */ @@ -359,7 +359,7 @@ >; }; - mcasp1_pins: mcasp1_pins { + mcasp1_pins: mcasp1-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_MII1_CRS, PIN_INPUT_PULLDOWN, MUX_MODE4) /* mii1_crs.mcasp1_aclkx */ AM33XX_PADCONF(AM335X_PIN_MII1_RX_ER, PIN_INPUT_PULLDOWN, MUX_MODE4) /* mii1_rxerr.mcasp1_fsx */ @@ -368,7 +368,7 @@ >; }; - mcasp1_pins_sleep: mcasp1_pins_sleep { + mcasp1_pins_sleep: mcasp1-sleep-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_MII1_CRS, PIN_INPUT_PULLDOWN, MUX_MODE7) AM33XX_PADCONF(AM335X_PIN_MII1_RX_ER, PIN_INPUT_PULLDOWN, MUX_MODE7) @@ -377,7 +377,7 @@ >; }; - dcan1_pins_default: dcan1_pins_default { + dcan1_pins_default: dcan1-default-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_UART0_CTSN, PIN_OUTPUT, MUX_MODE2) /* uart0_ctsn.d_can1_tx */ AM33XX_PADCONF(AM335X_PIN_UART0_RTSN, PIN_INPUT_PULLDOWN, MUX_MODE2) /* uart0_rtsn.d_can1_rx */ @@ -585,7 +585,7 @@ }; }; -#include "tps65910.dtsi" +#include "../../tps65910.dtsi" &mcasp1 { #sound-dai-cells = <0>; diff --git a/arch/arm/boot/dts/am335x-evmsk.dts b/arch/arm/boot/dts/ti/omap/am335x-evmsk.dts similarity index 97% rename from arch/arm/boot/dts/am335x-evmsk.dts rename to arch/arm/boot/dts/ti/omap/am335x-evmsk.dts index 5b3278c0c46a5179012cac2cd326ff164f6a02c9..57f78846c42d326ba98ed1599b3a2f143e13aa0e 100644 --- a/arch/arm/boot/dts/am335x-evmsk.dts +++ b/arch/arm/boot/dts/ti/omap/am335x-evmsk.dts @@ -202,7 +202,7 @@ pinctrl-names = "default"; pinctrl-0 = <&gpio_keys_s0 &clkout2_pin>; - lcd_pins_default: lcd_pins_default { + lcd_pins_default: lcd-default-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_GPMC_AD8, PIN_OUTPUT, MUX_MODE1) /* gpmc_ad8.lcd_data23 */ AM33XX_PADCONF(AM335X_PIN_GPMC_AD9, PIN_OUTPUT, MUX_MODE1) /* gpmc_ad9.lcd_data22 */ @@ -235,7 +235,7 @@ >; }; - lcd_pins_sleep: lcd_pins_sleep { + lcd_pins_sleep: lcd-sleep-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_GPMC_AD8, PIN_INPUT_PULLDOWN, MUX_MODE7) /* gpmc_ad8.lcd_data23 */ AM33XX_PADCONF(AM335X_PIN_GPMC_AD9, PIN_INPUT_PULLDOWN, MUX_MODE7) /* gpmc_ad9.lcd_data22 */ @@ -269,7 +269,7 @@ }; - user_leds_s0: user_leds_s0 { + user_leds_s0: user-leds-s0-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_GPMC_AD4, PIN_OUTPUT_PULLDOWN, MUX_MODE7) /* gpmc_ad4.gpio1_4 */ AM33XX_PADCONF(AM335X_PIN_GPMC_AD5, PIN_OUTPUT_PULLDOWN, MUX_MODE7) /* gpmc_ad5.gpio1_5 */ @@ -278,7 +278,7 @@ >; }; - gpio_keys_s0: gpio_keys_s0 { + gpio_keys_s0: gpio-keys-s0-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_GPMC_OEN_REN, PIN_INPUT_PULLDOWN, MUX_MODE7) /* gpmc_oen_ren.gpio2_3 */ AM33XX_PADCONF(AM335X_PIN_GPMC_ADVN_ALE, PIN_INPUT_PULLDOWN, MUX_MODE7) /* gpmc_advn_ale.gpio2_2 */ @@ -287,33 +287,33 @@ >; }; - i2c0_pins: pinmux_i2c0_pins { + i2c0_pins: i2c0-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_I2C0_SDA, PIN_INPUT_PULLUP, MUX_MODE0) AM33XX_PADCONF(AM335X_PIN_I2C0_SCL, PIN_INPUT_PULLUP, MUX_MODE0) >; }; - uart0_pins: pinmux_uart0_pins { + uart0_pins: uart0-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_UART0_RXD, PIN_INPUT_PULLUP, MUX_MODE0) AM33XX_PADCONF(AM335X_PIN_UART0_TXD, PIN_OUTPUT_PULLDOWN, MUX_MODE0) >; }; - clkout2_pin: pinmux_clkout2_pin { + clkout2_pin: clkout2-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_XDMA_EVENT_INTR1, PIN_OUTPUT_PULLDOWN, MUX_MODE3) /* xdma_event_intr1.clkout2 */ >; }; - ecap2_pins: backlight_pins { + ecap2_pins: backlight-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_MCASP0_AHCLKR, 0x0, MUX_MODE4) /* mcasp0_ahclkr.ecap2_in_pwm2_out */ >; }; - cpsw_default: cpsw_default { + cpsw_default: cpsw-default-pins { pinctrl-single,pins = < /* Slave 1 */ AM33XX_PADCONF(AM335X_PIN_MII1_TX_EN, PIN_OUTPUT_PULLDOWN, MUX_MODE2) /* mii1_txen.rgmii1_tctl */ @@ -345,7 +345,7 @@ >; }; - cpsw_sleep: cpsw_sleep { + cpsw_sleep: cpsw-sleep-pins { pinctrl-single,pins = < /* Slave 1 reset value */ AM33XX_PADCONF(AM335X_PIN_MII1_TX_EN, PIN_INPUT_PULLDOWN, MUX_MODE7) @@ -377,7 +377,7 @@ >; }; - davinci_mdio_default: davinci_mdio_default { + davinci_mdio_default: davinci-mdio-default-pins { pinctrl-single,pins = < /* MDIO */ AM33XX_PADCONF(AM335X_PIN_MDIO, PIN_INPUT_PULLUP | SLEWCTRL_FAST, MUX_MODE0) @@ -385,7 +385,7 @@ >; }; - davinci_mdio_sleep: davinci_mdio_sleep { + davinci_mdio_sleep: davinci-mdio-sleep-pins { pinctrl-single,pins = < /* MDIO reset value */ AM33XX_PADCONF(AM335X_PIN_MDIO, PIN_INPUT_PULLDOWN, MUX_MODE7) @@ -393,7 +393,7 @@ >; }; - mmc1_pins: pinmux_mmc1_pins { + mmc1_pins: mmc1-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_SPI0_CS1, PIN_INPUT, MUX_MODE7) /* spi0_cs1.gpio0_6 */ AM33XX_PADCONF(AM335X_PIN_MMC0_DAT0, PIN_INPUT_PULLUP, MUX_MODE0) @@ -406,7 +406,7 @@ >; }; - mcasp1_pins: mcasp1_pins { + mcasp1_pins: mcasp1-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_MII1_CRS, PIN_INPUT_PULLDOWN, MUX_MODE4) /* mii1_crs.mcasp1_aclkx */ AM33XX_PADCONF(AM335X_PIN_MII1_RX_ER, PIN_INPUT_PULLDOWN, MUX_MODE4) /* mii1_rxerr.mcasp1_fsx */ @@ -415,7 +415,7 @@ >; }; - mcasp1_pins_sleep: mcasp1_pins_sleep { + mcasp1_pins_sleep: mcasp1-sleep-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_MII1_CRS, PIN_INPUT_PULLDOWN, MUX_MODE7) AM33XX_PADCONF(AM335X_PIN_MII1_RX_ER, PIN_INPUT_PULLDOWN, MUX_MODE7) @@ -424,7 +424,7 @@ >; }; - mmc2_pins: pinmux_mmc2_pins { + mmc2_pins: mmc2-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_GPMC_WPN, PIN_INPUT_PULLUP, MUX_MODE7) /* gpmc_wpn.gpio0_31 */ AM33XX_PADCONF(AM335X_PIN_GPMC_CSN1, PIN_INPUT_PULLUP, MUX_MODE2) /* gpmc_csn1.mmc1_clk */ @@ -436,7 +436,7 @@ >; }; - wl12xx_gpio: pinmux_wl12xx_gpio { + wl12xx_gpio: wl12xx-gpio-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_GPMC_CSN0, PIN_OUTPUT_PULLUP, MUX_MODE7) /* gpmc_csn0.gpio1_29 */ >; @@ -517,7 +517,7 @@ }; }; -#include "tps65910.dtsi" +#include "../../tps65910.dtsi" &tps { vcc1-supply = <&vbat>; diff --git a/arch/arm/boot/dts/am335x-guardian.dts b/arch/arm/boot/dts/ti/omap/am335x-guardian.dts similarity index 96% rename from arch/arm/boot/dts/am335x-guardian.dts rename to arch/arm/boot/dts/ti/omap/am335x-guardian.dts index b357364e93f994a6dc0393ad725628c09423c8d1..205fe0ed7352231ab7dd057ab0d774225885e1a0 100644 --- a/arch/arm/boot/dts/am335x-guardian.dts +++ b/arch/arm/boot/dts/ti/omap/am335x-guardian.dts @@ -292,7 +292,7 @@ status = "okay"; }; -#include "tps65217.dtsi" +#include "../../tps65217.dtsi" &tps { /* @@ -481,14 +481,14 @@ pinctrl-names = "default"; pinctrl-0 = <&clkout2_pin &guardian_interface_pins>; - clkout2_pin: pinmux_clkout2_pin { + clkout2_pin: clkout2-pins { pinctrl-single,pins = < /* xdma_event_intr1.clkout2 */ AM33XX_IOPAD(0x9b4, PIN_OUTPUT_PULLDOWN | MUX_MODE3) >; }; - guardian_interface_pins: pinmux_interface_pins { + guardian_interface_pins: interface-pins { pinctrl-single,pins = < /* ADC_BATSENSE_EN */ /* (A14) MCASP0_AHCLKx.gpio3[21] */ @@ -518,13 +518,13 @@ >; }; - guardian_beeper_pins: pinmux_dmtimer7_pins { + guardian_beeper_pins: dmtimer7-pins { pinctrl-single,pins = < AM33XX_IOPAD(0x968, PIN_OUTPUT | MUX_MODE5) /* (E18) timer7 */ >; }; - guardian_button_pins: pinmux_guardian_button_pins { + guardian_button_pins: guardian-button-pins { pinctrl-single,pins = < AM33XX_IOPAD(0x940, PIN_INPUT | MUX_MODE7) /* (M16) gmii1_rxd0.gpio2[21] */ AM33XX_IOPAD(0x884, PIN_INPUT | MUX_MODE7) /* (V9) gpmc_csn2.gpio1[31] */ @@ -532,28 +532,28 @@ }; - i2c0_pins: pinmux_i2c0_pins { + i2c0_pins: i2c0-pins { pinctrl-single,pins = < AM33XX_IOPAD(0x988, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c0_sda.i2c0_sda */ AM33XX_IOPAD(0x98c, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c0_scl.i2c0_scl */ >; }; - led_bl_pins: gpio_led_bl_pins { + led_bl_pins: gpio-led-bl-pins { pinctrl-single,pins = < /* P9_14, gpmc_a[2].GPIO1[18] (backlight control) */ AM33XX_IOPAD(0x848, PIN_OUTPUT | MUX_MODE7) >; }; - lcd_disen_pins: pinmux_lcd_disen_pins { + lcd_disen_pins: lcd-disen-pins { pinctrl-single,pins = < /* P9_27, mcasp0_fsr.gpio3[19] (lcd_disen) */ AM33XX_IOPAD(0x9a4, PIN_OUTPUT_PULLUP | SLEWCTRL_SLOW | MUX_MODE7) >; }; - lcd_pins_default: pinmux_lcd_pins_default { + lcd_pins_default: lcd-default-pins { pinctrl-single,pins = < /* (U10) gpmc_ad8.lcd_data23 */ AM33XX_IOPAD(0x820, PIN_OUTPUT | SLEWCTRL_SLOW | MUX_MODE1) @@ -614,7 +614,7 @@ >; }; - lcd_pins_sleep: pinmux_lcd_pins_sleep { + lcd_pins_sleep: lcd-sleep-pins { pinctrl-single,pins = < /* lcd_data0.lcd_data0 */ AM33XX_IOPAD(0x8a0, PULL_DISABLE | SLEWCTRL_SLOW | MUX_MODE7) @@ -659,13 +659,13 @@ >; }; - guardian_led_pins: pinmux_guardian_led_pins { + guardian_led_pins: guardian-led-pins { pinctrl-single,pins = < AM33XX_IOPAD(0x868, PIN_OUTPUT | MUX_MODE7) /* (T16) gpmc_a10.gpio1[26] */ >; }; - mmc1_pins: pinmux_mmc1_pins { + mmc1_pins: mmc1-pins { pinctrl-single,pins = < AM33XX_IOPAD(0x8f0, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc0_dat3.mmc0_dat3 */ AM33XX_IOPAD(0x8f4, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc0_dat2.mmc0_dat2 */ @@ -677,7 +677,7 @@ >; }; - spi0_pins: pinmux_spi0_pins { + spi0_pins: spi0-pins { pinctrl-single,pins = < /* SPI0_CLK - spi0_clk.spi */ AM33XX_IOPAD(0x950, PIN_OUTPUT_PULLDOWN | MUX_MODE0) @@ -690,7 +690,7 @@ >; }; - uart0_pins: pinmux_uart0_pins { + uart0_pins: uart0-pins { pinctrl-single,pins = < /* uart0_rxd.uart0_rxd */ AM33XX_IOPAD(0x970, PIN_INPUT_PULLUP | MUX_MODE0) @@ -699,7 +699,7 @@ >; }; - uart2_pins: pinmux_uart2_pins { + uart2_pins: uart2-pins { pinctrl-single,pins = < /* K18 uart2_rxd.mirx_txd */ AM33XX_IOPAD(0x92c, PIN_INPUT_PULLUP | MUX_MODE1) @@ -708,7 +708,7 @@ >; }; - nandflash_pins: pinmux_nandflash_pins { + nandflash_pins: nandflash-pins { pinctrl-single,pins = < /* (U7) gpmc_ad0.gpmc_ad0 */ AM33XX_IOPAD(0x800, PIN_INPUT | MUX_MODE0) diff --git a/arch/arm/boot/dts/am335x-icev2.dts b/arch/arm/boot/dts/ti/omap/am335x-icev2.dts similarity index 96% rename from arch/arm/boot/dts/am335x-icev2.dts rename to arch/arm/boot/dts/ti/omap/am335x-icev2.dts index 5835c0cdda50b74800292b91d9f6077fe37daeaf..3c4228927f56e940af55645b7a5d959287898721 100644 --- a/arch/arm/boot/dts/am335x-icev2.dts +++ b/arch/arm/boot/dts/ti/omap/am335x-icev2.dts @@ -152,7 +152,7 @@ }; &am33xx_pinmux { - user_leds: user_leds { + user_leds: user-leds-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_MII1_TXD3, PIN_OUTPUT, MUX_MODE7) /* (J18) gmii1_txd3.gpio0[16] */ AM33XX_PADCONF(AM335X_PIN_MII1_TXD2, PIN_OUTPUT, MUX_MODE7) /* (K15) gmii1_txd2.gpio0[17] */ @@ -163,7 +163,7 @@ >; }; - mmc0_pins_default: mmc0_pins_default { + mmc0_pins_default: mmc0-default-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_MMC0_DAT3, PIN_INPUT_PULLUP, MUX_MODE0) AM33XX_PADCONF(AM335X_PIN_MMC0_DAT2, PIN_INPUT_PULLUP, MUX_MODE0) @@ -174,14 +174,14 @@ >; }; - i2c0_pins_default: i2c0_pins_default { + i2c0_pins_default: i2c0-default-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_I2C0_SDA, PIN_INPUT, MUX_MODE0) AM33XX_PADCONF(AM335X_PIN_I2C0_SCL, PIN_INPUT, MUX_MODE0) >; }; - spi0_pins_default: spi0_pins_default { + spi0_pins_default: spi0-default-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_SPI0_SCLK, PIN_INPUT_PULLUP, MUX_MODE0) AM33XX_PADCONF(AM335X_PIN_SPI0_D0, PIN_INPUT_PULLUP, MUX_MODE0) @@ -192,14 +192,14 @@ >; }; - uart3_pins_default: uart3_pins_default { + uart3_pins_default: uart3-default-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_MII1_RXD3, PIN_INPUT_PULLUP, MUX_MODE1) /* (L17) gmii1_rxd3.uart3_rxd */ AM33XX_PADCONF(AM335X_PIN_MII1_RXD2, PIN_OUTPUT_PULLUP, MUX_MODE1) /* (L16) gmii1_rxd2.uart3_txd */ >; }; - cpsw_default: cpsw_default { + cpsw_default: cpsw-default-pins { pinctrl-single,pins = < /* Slave 1, RMII mode */ AM33XX_PADCONF(AM335X_PIN_MII1_CRS, PIN_INPUT_PULLUP, MUX_MODE1) /* mii1_crs.rmii1_crs_dv */ @@ -222,7 +222,7 @@ >; }; - cpsw_sleep: cpsw_sleep { + cpsw_sleep: cpsw-sleep-pins { pinctrl-single,pins = < /* Slave 1 reset value */ AM33XX_PADCONF(AM335X_PIN_MII1_CRS, PIN_INPUT_PULLDOWN, MUX_MODE7) @@ -246,7 +246,7 @@ >; }; - davinci_mdio_default: davinci_mdio_default { + davinci_mdio_default: davinci-mdio-default-pins { pinctrl-single,pins = < /* MDIO */ AM33XX_PADCONF(AM335X_PIN_MDIO, PIN_INPUT_PULLUP | SLEWCTRL_FAST, MUX_MODE0) @@ -254,7 +254,7 @@ >; }; - davinci_mdio_sleep: davinci_mdio_sleep { + davinci_mdio_sleep: davinci-mdio-sleep-pins { pinctrl-single,pins = < /* MDIO reset value */ AM33XX_PADCONF(AM335X_PIN_MDIO, PIN_INPUT_PULLDOWN, MUX_MODE7) @@ -360,7 +360,7 @@ }; }; -#include "tps65910.dtsi" +#include "../../tps65910.dtsi" &tps { vcc1-supply = <&vbat>; diff --git a/arch/arm/boot/dts/am335x-igep0033.dtsi b/arch/arm/boot/dts/ti/omap/am335x-igep0033.dtsi similarity index 97% rename from arch/arm/boot/dts/am335x-igep0033.dtsi rename to arch/arm/boot/dts/ti/omap/am335x-igep0033.dtsi index 3fddf80dcf7149b4735ad016b828985251428f8f..e85c33fd42f0217a3e62a14ea33b994a5fa7077a 100644 --- a/arch/arm/boot/dts/am335x-igep0033.dtsi +++ b/arch/arm/boot/dts/ti/omap/am335x-igep0033.dtsi @@ -52,14 +52,14 @@ }; &am33xx_pinmux { - i2c0_pins: pinmux_i2c0_pins { + i2c0_pins: i2c0-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_I2C0_SDA, PIN_INPUT_PULLUP, MUX_MODE0) AM33XX_PADCONF(AM335X_PIN_I2C0_SCL, PIN_INPUT_PULLUP, MUX_MODE0) >; }; - nandflash_pins: pinmux_nandflash_pins { + nandflash_pins: nandflash-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_GPMC_AD0, PIN_INPUT_PULLUP, MUX_MODE0) AM33XX_PADCONF(AM335X_PIN_GPMC_AD1, PIN_INPUT_PULLUP, MUX_MODE0) @@ -79,14 +79,14 @@ >; }; - uart0_pins: pinmux_uart0_pins { + uart0_pins: uart0-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_UART0_RXD, PIN_INPUT_PULLUP, MUX_MODE0) AM33XX_PADCONF(AM335X_PIN_UART0_TXD, PIN_OUTPUT_PULLDOWN, MUX_MODE0) >; }; - leds_pins: pinmux_leds_pins { + leds_pins: leds-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_GPMC_A7, PIN_OUTPUT_PULLDOWN, MUX_MODE7) /* gpmc_a7.gpio1_23 */ >; @@ -221,7 +221,7 @@ dr_mode = "host"; }; -#include "tps65910.dtsi" +#include "../../tps65910.dtsi" &tps { vcc1-supply = <&vbat>; diff --git a/arch/arm/boot/dts/am335x-lxm.dts b/arch/arm/boot/dts/ti/omap/am335x-lxm.dts similarity index 97% rename from arch/arm/boot/dts/am335x-lxm.dts rename to arch/arm/boot/dts/ti/omap/am335x-lxm.dts index 1282dae144ddcc4cac113c40b11f87a73698a20b..be27b5a21b2c60eff996d62fdabfa1371bba6644 100644 --- a/arch/arm/boot/dts/am335x-lxm.dts +++ b/arch/arm/boot/dts/ti/omap/am335x-lxm.dts @@ -41,7 +41,7 @@ }; &am33xx_pinmux { - mmc1_pins: pinmux_mmc1_pins { + mmc1_pins: mmc1-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_MMC0_DAT3, PIN_INPUT_PULLUP, MUX_MODE0) AM33XX_PADCONF(AM335X_PIN_MMC0_DAT2, PIN_INPUT_PULLUP, MUX_MODE0) @@ -52,14 +52,14 @@ >; }; - i2c0_pins: pinmux_i2c0_pins { + i2c0_pins: i2c0-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_I2C0_SDA, PIN_INPUT, MUX_MODE0) AM33XX_PADCONF(AM335X_PIN_I2C0_SCL, PIN_INPUT, MUX_MODE0) >; }; - cpsw_default: cpsw_default { + cpsw_default: cpsw-default-pins { pinctrl-single,pins = < /* Slave 1 */ AM33XX_PADCONF(AM335X_PIN_GPMC_A9, PIN_INPUT_PULLDOWN, MUX_MODE7) /* rmii1_int */ @@ -85,7 +85,7 @@ >; }; - cpsw_sleep: cpsw_sleep { + cpsw_sleep: cpsw-sleep-pins { pinctrl-single,pins = < /* Slave 1 reset value */ AM33XX_PADCONF(AM335X_PIN_GPMC_A9, PIN_INPUT_PULLDOWN, MUX_MODE7) /* rmii1_int */ @@ -111,7 +111,7 @@ >; }; - davinci_mdio_default: davinci_mdio_default { + davinci_mdio_default: davinci-mdio-default-pins { pinctrl-single,pins = < /* MDIO */ AM33XX_PADCONF(AM335X_PIN_MDIO, PIN_INPUT_PULLUP | SLEWCTRL_FAST, MUX_MODE0) @@ -119,7 +119,7 @@ >; }; - davinci_mdio_sleep: davinci_mdio_sleep { + davinci_mdio_sleep: davinci-mdio-sleep-pins { pinctrl-single,pins = < /* MDIO reset value */ AM33XX_PADCONF(AM335X_PIN_MDIO, PIN_INPUT_PULLDOWN, MUX_MODE7) @@ -127,7 +127,7 @@ >; }; - emmc_pins: pinmux_emmc_pins { + emmc_pins: emmc-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_GPMC_CSN1, PIN_INPUT_PULLUP, MUX_MODE2) /* gpmc_csn1.mmc1_clk */ AM33XX_PADCONF(AM335X_PIN_GPMC_CSN2, PIN_INPUT_PULLUP, MUX_MODE2) /* gpmc_csn2.mmc1_cmd */ @@ -142,7 +142,7 @@ >; }; - uart0_pins: pinmux_uart0_pins { + uart0_pins: uart0-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_UART0_RXD, PIN_INPUT_PULLUP, MUX_MODE0) AM33XX_PADCONF(AM335X_PIN_UART0_TXD, PIN_OUTPUT_PULLDOWN, MUX_MODE0) @@ -177,7 +177,7 @@ }; }; -/include/ "tps65910.dtsi" +/include/ "../../tps65910.dtsi" &tps { vcc1-supply = <&vbat>; diff --git a/arch/arm/boot/dts/am335x-moxa-uc-2100-common.dtsi b/arch/arm/boot/dts/ti/omap/am335x-moxa-uc-2100-common.dtsi similarity index 95% rename from arch/arm/boot/dts/am335x-moxa-uc-2100-common.dtsi rename to arch/arm/boot/dts/ti/omap/am335x-moxa-uc-2100-common.dtsi index 49e280b42442f55470ac03f6ebeff69e31fc6d7a..b8730aa52ce6fe521a1b531be42c4ef891c969b5 100644 --- a/arch/arm/boot/dts/am335x-moxa-uc-2100-common.dtsi +++ b/arch/arm/boot/dts/ti/omap/am335x-moxa-uc-2100-common.dtsi @@ -31,27 +31,27 @@ &am33xx_pinmux { pinctrl-names = "default"; - i2c0_pins: pinmux_i2c0_pins { + i2c0_pins: i2c0-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_I2C0_SDA, PIN_INPUT_PULLUP, MUX_MODE0) AM33XX_PADCONF(AM335X_PIN_I2C0_SCL, PIN_INPUT_PULLUP, MUX_MODE0) >; }; - push_button_pins: pinmux_push_button { + push_button_pins: push-button-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_LCD_HSYNC, PIN_INPUT_PULLDOWN, MUX_MODE7) /* lcd_hsync.gpio2_23 */ >; }; - uart0_pins: pinmux_uart0_pins { + uart0_pins: uart0-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_UART0_RXD, PIN_INPUT_PULLUP, MUX_MODE0) AM33XX_PADCONF(AM335X_PIN_UART0_TXD, PIN_OUTPUT_PULLDOWN, MUX_MODE0) >; }; - davinci_mdio_default: davinci_mdio_default { + davinci_mdio_default: davinci-mdio-default-pins { pinctrl-single,pins = < /* MDIO */ AM33XX_PADCONF(AM335X_PIN_MDIO, PIN_INPUT_PULLUP | SLEWCTRL_FAST, MUX_MODE0) @@ -59,7 +59,7 @@ >; }; - mmc1_pins_default: pinmux_mmc1_pins { + mmc1_pins_default: mmc1-pins { pinctrl-single,pins = < /* eMMC */ AM33XX_PADCONF(AM335X_PIN_GPMC_AD0, PIN_INPUT_PULLUP, MUX_MODE1) /* gpmc_ad12.mmc1_dat0 */ @@ -75,7 +75,7 @@ >; }; - spi0_pins: pinmux_spi0 { + spi0_pins: spi0-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_SPI0_SCLK, PIN_INPUT_PULLUP, MUX_MODE0) AM33XX_PADCONF(AM335X_PIN_SPI0_CS0, PIN_INPUT_PULLUP, MUX_MODE0) diff --git a/arch/arm/boot/dts/am335x-moxa-uc-2101.dts b/arch/arm/boot/dts/ti/omap/am335x-moxa-uc-2101.dts similarity index 97% rename from arch/arm/boot/dts/am335x-moxa-uc-2101.dts rename to arch/arm/boot/dts/ti/omap/am335x-moxa-uc-2101.dts index 1cc513ed92ccf30ba34c66462a1de4531be89ce6..e986945ac1b5f60ffb1452f845270b7d8fba631e 100644 --- a/arch/arm/boot/dts/am335x-moxa-uc-2101.dts +++ b/arch/arm/boot/dts/ti/omap/am335x-moxa-uc-2101.dts @@ -28,7 +28,7 @@ &am33xx_pinmux { pinctrl-names = "default"; - cpsw_default: cpsw_default { + cpsw_default: cpsw-default-pins { pinctrl-single,pins = < /* Slave 1 */ AM33XX_PADCONF(AM335X_PIN_MII1_CRS, PIN_INPUT_PULLDOWN, MUX_MODE1) /* mii1_crs.rmii1_crs_dv */ @@ -42,7 +42,7 @@ >; }; - spi1_pins: pinmux_spi1 { + spi1_pins: spi1-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_ECAP0_IN_PWM0_OUT, PIN_INPUT_PULLUP, MUX_MODE4) /* ecap0_in_pwm0_out.spi1_sclk */ AM33XX_PADCONF(AM335X_PIN_UART1_CTSN, PIN_INPUT_PULLUP, MUX_MODE4) /* uart1_ctsn.spi1_cs0 */ diff --git a/arch/arm/boot/dts/am335x-moxa-uc-8100-common.dtsi b/arch/arm/boot/dts/ti/omap/am335x-moxa-uc-8100-common.dtsi similarity index 95% rename from arch/arm/boot/dts/am335x-moxa-uc-8100-common.dtsi rename to arch/arm/boot/dts/ti/omap/am335x-moxa-uc-8100-common.dtsi index 7d00e8b20f18a424b26788df4650b056af121e5a..daaa5eee0f0df7c2806dd834941d6d2c3b7c7416 100644 --- a/arch/arm/boot/dts/am335x-moxa-uc-8100-common.dtsi +++ b/arch/arm/boot/dts/ti/omap/am335x-moxa-uc-8100-common.dtsi @@ -38,7 +38,7 @@ pinctrl-names = "default"; pinctrl-0 = <&minipcie_pins>; - minipcie_pins: pinmux_minipcie { + minipcie_pins: minipcie-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_LCD_PCLK, PIN_INPUT_PULLDOWN, MUX_MODE7) /* lcd_pclk.gpio2_24 */ AM33XX_PADCONF(AM335X_PIN_LCD_AC_BIAS_EN, PIN_INPUT_PULLDOWN, MUX_MODE7) /* lcd_ac_bias_en.gpio2_25 */ @@ -46,13 +46,13 @@ >; }; - push_button_pins: pinmux_push_button { + push_button_pins: push-button-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_MCASP0_AHCLKX, PIN_INPUT_PULLDOWN, MUX_MODE7) /* mcasp0_ahcklx.gpio3_21 */ >; }; - i2c0_pins: pinmux_i2c0_pins { + i2c0_pins: i2c0-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_I2C0_SDA, PIN_INPUT_PULLUP, MUX_MODE0) AM33XX_PADCONF(AM335X_PIN_I2C0_SCL, PIN_INPUT_PULLUP, MUX_MODE0) @@ -60,21 +60,21 @@ }; - i2c1_pins: pinmux_i2c1_pins { + i2c1_pins: i2c1-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_UART0_CTSN, PIN_INPUT_PULLUP, MUX_MODE3) /* uart0_ctsn.i2c1_sda */ AM33XX_PADCONF(AM335X_PIN_UART0_RTSN, PIN_INPUT_PULLUP, MUX_MODE3) /* uart0_rtsn.i2c1_scl */ >; }; - uart0_pins: pinmux_uart0_pins { + uart0_pins: uart0-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_UART0_RXD, PIN_INPUT_PULLUP, MUX_MODE0) AM33XX_PADCONF(AM335X_PIN_UART0_TXD, PIN_OUTPUT_PULLDOWN, MUX_MODE0) >; }; - uart1_pins: pinmux_uart1_pins { + uart1_pins: uart1-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_UART1_CTSN, PIN_INPUT, MUX_MODE0) AM33XX_PADCONF(AM335X_PIN_UART1_RTSN, PIN_OUTPUT_PULLDOWN, MUX_MODE0) @@ -83,7 +83,7 @@ >; }; - uart2_pins: pinmux_uart2_pins { + uart2_pins: uart2-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_LCD_DATA14, PIN_INPUT, MUX_MODE6) /* lcd_data14.uart5_ctsn */ AM33XX_PADCONF(AM335X_PIN_LCD_DATA15, PIN_OUTPUT_PULLDOWN, MUX_MODE6) /* lcd_data15.uart5_rtsn */ @@ -92,7 +92,7 @@ >; }; - cpsw_default: cpsw_default { + cpsw_default: cpsw-default-pins { pinctrl-single,pins = < /* Slave 1 */ AM33XX_PADCONF(AM335X_PIN_MII1_CRS, PIN_INPUT_PULLDOWN, MUX_MODE1) @@ -117,7 +117,7 @@ >; }; - davinci_mdio_default: davinci_mdio_default { + davinci_mdio_default: davinci-mdio-default-pins { pinctrl-single,pins = < /* MDIO */ AM33XX_PADCONF(AM335X_PIN_MDIO, PIN_INPUT_PULLUP | SLEWCTRL_FAST, MUX_MODE0) @@ -125,7 +125,7 @@ >; }; - mmc0_pins_default: pinmux_mmc0_pins { + mmc0_pins_default: mmc0-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_MMC0_DAT3, PIN_INPUT_PULLUP, MUX_MODE0) AM33XX_PADCONF(AM335X_PIN_MMC0_DAT2, PIN_INPUT_PULLUP, MUX_MODE0) @@ -138,7 +138,7 @@ >; }; - mmc2_pins_default: pinmux_mmc2_pins { + mmc2_pins_default: mmc2-pins { pinctrl-single,pins = < /* eMMC */ AM33XX_PADCONF(AM335X_PIN_GPMC_AD12, PIN_INPUT_PULLUP, MUX_MODE3) /* gpmc_ad12.mmc2_dat0 */ @@ -154,7 +154,7 @@ >; }; - spi0_pins: pinmux_spi0 { + spi0_pins: spi0-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_SPI0_SCLK, PIN_INPUT_PULLUP, MUX_MODE0) AM33XX_PADCONF(AM335X_PIN_SPI0_CS0, PIN_INPUT_PULLUP, MUX_MODE0) @@ -233,7 +233,7 @@ }; -#include "tps65910.dtsi" +#include "../../tps65910.dtsi" &tps { vcc1-supply = <&vbat>; vcc2-supply = <&vbat>; diff --git a/arch/arm/boot/dts/am335x-moxa-uc-8100-me-t.dts b/arch/arm/boot/dts/ti/omap/am335x-moxa-uc-8100-me-t.dts similarity index 100% rename from arch/arm/boot/dts/am335x-moxa-uc-8100-me-t.dts rename to arch/arm/boot/dts/ti/omap/am335x-moxa-uc-8100-me-t.dts diff --git a/arch/arm/boot/dts/am335x-myirtech-myc.dtsi b/arch/arm/boot/dts/ti/omap/am335x-myirtech-myc.dtsi similarity index 95% rename from arch/arm/boot/dts/am335x-myirtech-myc.dtsi rename to arch/arm/boot/dts/ti/omap/am335x-myirtech-myc.dtsi index 6eea18b2935574b0d8011a9f8b9481d1d4c5e72f..58459926921773b155f2140fa3478a856b9aedc8 100644 --- a/arch/arm/boot/dts/am335x-myirtech-myc.dtsi +++ b/arch/arm/boot/dts/ti/omap/am335x-myirtech-myc.dtsi @@ -127,6 +127,7 @@ gpmc,bus-turnaround-ns = <0>; gpmc,cycle2cycle-delay-ns = <0>; gpmc,clk-activation-ns = <0>; + gpmc,wait-pin = <0>; gpmc,wr-access-ns = <40>; gpmc,wr-data-mux-bus-ns = <0>; ti,elm-id = <&elm>; @@ -159,21 +160,21 @@ }; &am33xx_pinmux { - mdio_pins_default: pinmux_mdio_pins_default { + mdio_pins_default: mdio-default-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_MDIO, PIN_INPUT_PULLUP | SLEWCTRL_FAST, MUX_MODE0) /* mdio_data */ AM33XX_PADCONF(AM335X_PIN_MDC, PIN_OUTPUT_PULLUP, MUX_MODE0) /* mdio_clk */ >; }; - mdio_pins_sleep: pinmux_mdio_pins_sleep { + mdio_pins_sleep: mdio-sleep-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_MDIO, PIN_INPUT_PULLDOWN, MUX_MODE7) AM33XX_PADCONF(AM335X_PIN_MDC, PIN_INPUT_PULLDOWN, MUX_MODE7) >; }; - eth_slave1_pins_default: pinmux_eth_slave1_pins_default { + eth_slave1_pins_default: eth-slave1-default-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_MII1_TX_EN, PIN_OUTPUT_PULLDOWN, MUX_MODE2) /* rgmii1_tctl */ AM33XX_PADCONF(AM335X_PIN_MII1_RX_DV, PIN_INPUT_PULLDOWN, MUX_MODE2) /* rgmii1_rctl */ @@ -190,7 +191,7 @@ >; }; - eth_slave1_pins_sleep: pinmux_eth_slave1_pins_sleep { + eth_slave1_pins_sleep: eth-slave1-sleep-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_MII1_TX_EN, PIN_INPUT_PULLDOWN, MUX_MODE7) AM33XX_PADCONF(AM335X_PIN_MII1_RX_DV, PIN_INPUT_PULLDOWN, MUX_MODE7) @@ -207,34 +208,34 @@ >; }; - i2c0_pins_default: pinmux_i2c0_pins_default { + i2c0_pins_default: i2c0-default-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_I2C0_SDA, PIN_INPUT | SLEWCTRL_FAST, MUX_MODE0) /* I2C0_SDA */ AM33XX_PADCONF(AM335X_PIN_I2C0_SCL, PIN_INPUT | SLEWCTRL_FAST, MUX_MODE0) /* I2C0_SCL */ >; }; - i2c0_pins_gpio: pinmux_i2c0_pins_gpio { + i2c0_pins_gpio: i2c0-gpio-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_I2C0_SDA, PIN_INPUT, MUX_MODE7) /* gpio3[5] */ AM33XX_PADCONF(AM335X_PIN_I2C0_SCL, PIN_INPUT, MUX_MODE7) /* gpio3[6] */ >; }; - i2c0_pins_sleep: pinmux_i2c0_pins_sleep { + i2c0_pins_sleep: i2c0-sleep-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_I2C0_SDA, PIN_INPUT_PULLDOWN, MUX_MODE7) AM33XX_PADCONF(AM335X_PIN_I2C0_SCL, PIN_INPUT_PULLDOWN, MUX_MODE7) >; }; - led_mod_pins: pinmux_led_mod_pins { + led_mod_pins: led-mod-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_MCASP0_ACLKR, PIN_OUTPUT_PULLDOWN, MUX_MODE7) /* gpio3[18] */ >; }; - nand_pins_default: pinmux_nand_pins_default { + nand_pins_default: nand-default-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_GPMC_AD0, PIN_INPUT_PULLUP, MUX_MODE0) /* gpmc_ad0 */ AM33XX_PADCONF(AM335X_PIN_GPMC_AD1, PIN_INPUT_PULLUP, MUX_MODE0) /* gpmc_ad1 */ @@ -254,7 +255,7 @@ >; }; - nand_pins_sleep: pinmux_nand_pins_sleep { + nand_pins_sleep: nand-sleep-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_GPMC_AD0, PIN_INPUT_PULLDOWN, MUX_MODE7) AM33XX_PADCONF(AM335X_PIN_GPMC_AD1, PIN_INPUT_PULLDOWN, MUX_MODE7) diff --git a/arch/arm/boot/dts/am335x-myirtech-myd.dts b/arch/arm/boot/dts/ti/omap/am335x-myirtech-myd.dts similarity index 93% rename from arch/arm/boot/dts/am335x-myirtech-myd.dts rename to arch/arm/boot/dts/ti/omap/am335x-myirtech-myd.dts index 425ad9b81a68ab182c43fcf842cf9665884f9285..d3bba79b9358c9f18471f68c4e4873bba965daf9 100644 --- a/arch/arm/boot/dts/am335x-myirtech-myd.dts +++ b/arch/arm/boot/dts/ti/omap/am335x-myirtech-myd.dts @@ -304,47 +304,47 @@ }; &am33xx_pinmux { - dcan0_pins_default: pinmux_dcan0_pins_default { + dcan0_pins_default: dcan0-default-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_UART1_CTSN, PIN_OUTPUT, MUX_MODE2) /* dcan0_tx_mux2 */ AM33XX_PADCONF(AM335X_PIN_UART1_RTSN, PIN_INPUT, MUX_MODE2) /* dcan0_rx_mux2 */ >; }; - dcan0_pins_sleep: pinmux_dcan0_pins_sleep { + dcan0_pins_sleep: dcan0-sleep-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_UART1_CTSN, PIN_INPUT_PULLDOWN, MUX_MODE7) AM33XX_PADCONF(AM335X_PIN_UART1_RTSN, PIN_INPUT_PULLDOWN, MUX_MODE7) >; }; - dcan1_pins_default: pinmux_dcan1_pins_default { + dcan1_pins_default: dcan1-default-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_UART0_CTSN, PIN_OUTPUT, MUX_MODE2) /* dcan1_tx_mux0 */ AM33XX_PADCONF(AM335X_PIN_UART0_RTSN, PIN_INPUT, MUX_MODE2) /* dcan1_rx_mux0 */ >; }; - dcan1_pins_sleep: pinmux_dcan1_pins_sleep { + dcan1_pins_sleep: dcan1-sleep-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_UART0_CTSN, PIN_INPUT_PULLDOWN, MUX_MODE7) AM33XX_PADCONF(AM335X_PIN_UART0_RTSN, PIN_INPUT_PULLDOWN, MUX_MODE7) >; }; - ehrpwm0_pins_default: pinmux_ehrpwm0_pins_default { + ehrpwm0_pins_default: ehrpwm0-default-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_SPI0_SCLK, PIN_OUTPUT, MUX_MODE3) /* ehrpwm0A_mux1 */ >; }; - ehrpwm0_pins_sleep: pinmux_ehrpwm0_pins_sleep { + ehrpwm0_pins_sleep: ehrpwm0-sleep-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_SPI0_SCLK, PIN_INPUT_PULLDOWN, MUX_MODE7) >; }; - eth_slave2_pins_default: pinmux_eth_slave2_pins_default { + eth_slave2_pins_default: eth-slave2-default-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_GPMC_A0, PIN_OUTPUT_PULLDOWN, MUX_MODE2) /* rgmii2_tctl */ AM33XX_PADCONF(AM335X_PIN_GPMC_A1, PIN_INPUT_PULLDOWN, MUX_MODE2) /* rgmii2_rctl */ @@ -361,7 +361,7 @@ >; }; - eth_slave2_pins_sleep: pinmux_eth_slave2_pins_sleep { + eth_slave2_pins_sleep: eth-slave2-sleep-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_GPMC_A0, PIN_INPUT_PULLDOWN, MUX_MODE7) AM33XX_PADCONF(AM335X_PIN_GPMC_A1, PIN_INPUT_PULLDOWN, MUX_MODE7) @@ -378,35 +378,35 @@ >; }; - gpio_buttons_pins: pinmux_gpio_buttons_pins { + gpio_buttons_pins: gpio-buttons-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_MII1_COL, PIN_INPUT_PULLDOWN, MUX_MODE7) /* gpio3[0] */ AM33XX_PADCONF(AM335X_PIN_RMII1_REF_CLK, PIN_INPUT, MUX_MODE7) /* gpio0[29] */ >; }; - i2c1_pins_default: pinmux_i2c1_pins_default { + i2c1_pins_default: i2c1-default-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_SPI0_D1, PIN_INPUT | SLEWCTRL_FAST, MUX_MODE2) /* I2C1_SDA_mux3 */ AM33XX_PADCONF(AM335X_PIN_SPI0_CS0, PIN_INPUT | SLEWCTRL_FAST, MUX_MODE2) /* I2C1_SCL_mux3 */ >; }; - i2c1_pins_gpio: pinmux_i2c1_pins_gpio { + i2c1_pins_gpio: i2c1-gpio-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_SPI0_D1, PIN_INPUT, MUX_MODE7) /* gpio0[4] */ AM33XX_PADCONF(AM335X_PIN_SPI0_CS0, PIN_INPUT, MUX_MODE7) /* gpio0[5] */ >; }; - i2c1_pins_sleep: pinmux_i2c1_pins_sleep { + i2c1_pins_sleep: i2c1-sleep-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_SPI0_D1, PIN_INPUT_PULLDOWN, MUX_MODE7) AM33XX_PADCONF(AM335X_PIN_SPI0_CS0, PIN_INPUT_PULLDOWN, MUX_MODE7) >; }; - lcdc_pins_default: pinmux_lcdc_pins_default { + lcdc_pins_default: lcdc-default-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_LCD_DATA0, PIN_OUTPUT, MUX_MODE0) /* lcd_data0 */ AM33XX_PADCONF(AM335X_PIN_LCD_DATA1, PIN_OUTPUT, MUX_MODE0) /* lcd_data1 */ @@ -431,7 +431,7 @@ >; }; - lcdc_pins_sleep: pinmux_lcdc_pins_sleep { + lcdc_pins_sleep: lcdc-sleep-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_LCD_DATA0, PULL_DISABLE, MUX_MODE7) AM33XX_PADCONF(AM335X_PIN_LCD_DATA1, PULL_DISABLE, MUX_MODE7) @@ -456,14 +456,14 @@ >; }; - leds_pins: pinmux_leds_pins { + leds_pins: leds-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_GPMC_AD11, PIN_OUTPUT, MUX_MODE7) /* gpio0[27] */ AM33XX_PADCONF(AM335X_PIN_SPI0_D0, PIN_OUTPUT, MUX_MODE7) /* gpio0[3] */ >; }; - mcasp0_pins_default: pinmux_mcasp0_pins_default { + mcasp0_pins_default: mcasp0-default-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_MCASP0_ACLKX, PIN_INPUT_PULLDOWN, MUX_MODE0) /* mcasp0_aclkx_mux0 */ AM33XX_PADCONF(AM335X_PIN_MCASP0_FSX, PIN_INPUT_PULLDOWN, MUX_MODE0) /* mcasp0_fsx_mux0 */ @@ -472,7 +472,7 @@ >; }; - mcasp0_pins_sleep: pinmux_mcasp0_pins_sleep { + mcasp0_pins_sleep: mcasp0-sleep-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_MCASP0_ACLKX, PIN_INPUT_PULLDOWN, MUX_MODE7) AM33XX_PADCONF(AM335X_PIN_MCASP0_FSX, PIN_INPUT_PULLDOWN, MUX_MODE7) @@ -481,7 +481,7 @@ >; }; - mmc1_pins_default: pinmux_mmc1_pins_default { + mmc1_pins_default: mmc1-default-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_MMC0_DAT3, PIN_INPUT_PULLUP, MUX_MODE0) /* mmc0_dat3 */ AM33XX_PADCONF(AM335X_PIN_MMC0_DAT2, PIN_INPUT_PULLUP, MUX_MODE0) /* mmc0_dat2 */ @@ -493,7 +493,7 @@ >; }; - mmc1_pins_sleep: pinmux_mmc1_pins_sleep { + mmc1_pins_sleep: mmc1-sleep-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_MMC0_DAT3, PIN_INPUT_PULLDOWN, MUX_MODE0) AM33XX_PADCONF(AM335X_PIN_MMC0_DAT2, PIN_INPUT_PULLDOWN, MUX_MODE0) @@ -505,42 +505,42 @@ >; }; - uart0_pins: pinmux_uart0_pins { + uart0_pins: uart0-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_UART0_RXD, PIN_INPUT_PULLUP, MUX_MODE0) /* uart0_rxd */ AM33XX_PADCONF(AM335X_PIN_UART0_TXD, PIN_OUTPUT_PULLDOWN, MUX_MODE0) /* uart0_txd */ >; }; - uart1_pins_default: pinmux_uart1_pins_default { + uart1_pins_default: uart1-default-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_UART1_RXD, PIN_INPUT_PULLUP, MUX_MODE0) /* uart1_rxd */ AM33XX_PADCONF(AM335X_PIN_UART1_TXD, PIN_OUTPUT_PULLDOWN, MUX_MODE0) /* uart1_txd */ >; }; - uart1_pins_sleep: pinmux_uart1_pins_sleep { + uart1_pins_sleep: uart1-sleep-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_UART1_RXD, PIN_INPUT_PULLDOWN, MUX_MODE7) AM33XX_PADCONF(AM335X_PIN_UART1_TXD, PIN_INPUT_PULLDOWN, MUX_MODE7) >; }; - uart2_pins_default: pinmux_uart2_pins_default { + uart2_pins_default: uart2-default-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_MII1_CRS, PIN_INPUT, MUX_MODE6) /* uart2_rxd_mux1 */ AM33XX_PADCONF(AM335X_PIN_MII1_RX_ER, PIN_OUTPUT, MUX_MODE6) /* uart2_txd_mux1 */ >; }; - uart2_pins_sleep: pinmux_uart2_pins_sleep { + uart2_pins_sleep: uart2-sleep-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_MII1_CRS, PIN_INPUT_PULLDOWN, MUX_MODE7) AM33XX_PADCONF(AM335X_PIN_MII1_RX_ER, PIN_INPUT_PULLDOWN, MUX_MODE7) >; }; - usb_pins: pinmux_usb_pins { + usb_pins: usb-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_USB0_DRVVBUS, PIN_OUTPUT_PULLDOWN, MUX_MODE0) /* USB0_DRVVBUS */ AM33XX_PADCONF(AM335X_PIN_USB1_DRVVBUS, PIN_OUTPUT_PULLDOWN, MUX_MODE0) /* USB1_DRVVBUS */ diff --git a/arch/arm/boot/dts/am335x-nano.dts b/arch/arm/boot/dts/ti/omap/am335x-nano.dts similarity index 97% rename from arch/arm/boot/dts/am335x-nano.dts rename to arch/arm/boot/dts/ti/omap/am335x-nano.dts index c447aebd8d8663c831e596d259a4e9a952257e52..a475c0d913060bf153e79ec4084772e55c73b673 100644 --- a/arch/arm/boot/dts/am335x-nano.dts +++ b/arch/arm/boot/dts/ti/omap/am335x-nano.dts @@ -36,13 +36,13 @@ pinctrl-names = "default"; pinctrl-0 = <&misc_pins>; - misc_pins: misc_pins { + misc_pins: misc-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_SPI0_CS0, PIN_OUTPUT, MUX_MODE7) /* spi0_cs0.gpio0_5 */ >; }; - gpmc_pins: gpmc_pins { + gpmc_pins: gpmc-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_GPMC_AD0, PIN_INPUT_PULLUP, MUX_MODE0) AM33XX_PADCONF(AM335X_PIN_GPMC_AD1, PIN_INPUT_PULLUP, MUX_MODE0) @@ -86,21 +86,21 @@ >; }; - i2c0_pins: i2c0_pins { + i2c0_pins: i2c0-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_I2C0_SDA, PIN_INPUT_PULLDOWN, MUX_MODE0) AM33XX_PADCONF(AM335X_PIN_I2C0_SCL, PIN_INPUT_PULLDOWN, MUX_MODE0) >; }; - uart0_pins: uart0_pins { + uart0_pins: uart0-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_UART0_RXD, PIN_INPUT_PULLUP, MUX_MODE0) AM33XX_PADCONF(AM335X_PIN_UART0_TXD, PIN_OUTPUT, MUX_MODE0) >; }; - uart1_pins: uart1_pins { + uart1_pins: uart1-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_UART1_CTSN, PIN_OUTPUT, MUX_MODE7) AM33XX_PADCONF(AM335X_PIN_UART1_RTSN, PIN_OUTPUT, MUX_MODE7) @@ -109,7 +109,7 @@ >; }; - uart2_pins: uart2_pins { + uart2_pins: uart2-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_LCD_DATA8, PIN_INPUT_PULLUP, MUX_MODE7) /* lcd_data8.gpio2[14] */ AM33XX_PADCONF(AM335X_PIN_LCD_DATA9, PIN_OUTPUT, MUX_MODE7) /* lcd_data9.gpio2[15] */ @@ -118,7 +118,7 @@ >; }; - uart3_pins: uart3_pins { + uart3_pins: uart3-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_LCD_DATA10, PIN_INPUT_PULLUP, MUX_MODE7) /* lcd_data10.gpio2[16] */ AM33XX_PADCONF(AM335X_PIN_LCD_DATA11, PIN_OUTPUT, MUX_MODE7) /* lcd_data11.gpio2[17] */ @@ -127,7 +127,7 @@ >; }; - uart4_pins: uart4_pins { + uart4_pins: uart4-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_LCD_DATA12, PIN_INPUT_PULLUP, MUX_MODE7) /* lcd_data12.gpio0[8] */ AM33XX_PADCONF(AM335X_PIN_LCD_DATA13, PIN_OUTPUT, MUX_MODE7) /* lcd_data13.gpio0[9] */ @@ -136,14 +136,14 @@ >; }; - uart5_pins: uart5_pins { + uart5_pins: uart5-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_LCD_DATA14, PIN_INPUT, MUX_MODE4) /* lcd_data14.uart5_rxd */ AM33XX_PADCONF(AM335X_PIN_RMII1_REF_CLK, PIN_OUTPUT, MUX_MODE3) /* rmiii1_refclk.uart5_txd */ >; }; - mmc1_pins: mmc1_pins { + mmc1_pins: mmc1-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_MMC0_DAT3, PIN_INPUT_PULLUP, MUX_MODE0) AM33XX_PADCONF(AM335X_PIN_MMC0_DAT2, PIN_INPUT_PULLUP, MUX_MODE0) @@ -427,7 +427,7 @@ dr_mode = "host"; }; -#include "tps65217.dtsi" +#include "../../tps65217.dtsi" &tps { regulators { diff --git a/arch/arm/boot/dts/am335x-netcan-plus-1xx.dts b/arch/arm/boot/dts/ti/omap/am335x-netcan-plus-1xx.dts similarity index 98% rename from arch/arm/boot/dts/am335x-netcan-plus-1xx.dts rename to arch/arm/boot/dts/ti/omap/am335x-netcan-plus-1xx.dts index 2e049489ac066445e0f9f0d7fbc95a7a983ec47b..f7fad48e36edfa827391782656324e7c9cc6ca3b 100644 --- a/arch/arm/boot/dts/am335x-netcan-plus-1xx.dts +++ b/arch/arm/boot/dts/ti/omap/am335x-netcan-plus-1xx.dts @@ -37,14 +37,14 @@ }; &am33xx_pinmux { - user_leds_s0: user_leds_s0 { + user_leds_s0: user-leds-s0-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_UART1_RXD, PIN_OUTPUT_PULLDOWN, MUX_MODE7) /* CAN Data LED */ AM33XX_PADCONF(AM335X_PIN_UART1_TXD, PIN_OUTPUT_PULLDOWN, MUX_MODE7) /* CAN Error LED */ >; }; - dcan1_pins: pinmux_dcan1_pins { + dcan1_pins: dcan1-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_UART0_CTSN, PIN_OUTPUT, MUX_MODE2) /* CAN TX */ AM33XX_PADCONF(AM335X_PIN_UART0_RTSN, PIN_INPUT, MUX_MODE2) /* CAN RX */ diff --git a/arch/arm/boot/dts/am335x-netcom-plus-2xx.dts b/arch/arm/boot/dts/ti/omap/am335x-netcom-plus-2xx.dts similarity index 98% rename from arch/arm/boot/dts/am335x-netcom-plus-2xx.dts rename to arch/arm/boot/dts/ti/omap/am335x-netcom-plus-2xx.dts index 6ed886c3306be818efcc4eeade51290225b9d873..76751a324ad7562e1ef7bb71c91b57ba5e088b10 100644 --- a/arch/arm/boot/dts/am335x-netcom-plus-2xx.dts +++ b/arch/arm/boot/dts/ti/omap/am335x-netcom-plus-2xx.dts @@ -18,7 +18,7 @@ }; &am33xx_pinmux { - uart1_pins: pinmux_uart1_pins { + uart1_pins: uart1-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_UART1_RXD, PIN_INPUT, MUX_MODE0) /* RX */ AM33XX_PADCONF(AM335X_PIN_UART1_TXD, PIN_INPUT, MUX_MODE0) /* TX */ @@ -31,7 +31,7 @@ >; }; - uart2_pins: pinmux_uart2_pins { + uart2_pins: uart2-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_SPI0_SCLK, PIN_INPUT, MUX_MODE1) /* RX */ AM33XX_PADCONF(AM335X_PIN_SPI0_D0, PIN_OUTPUT, MUX_MODE1) /* TX */ diff --git a/arch/arm/boot/dts/am335x-netcom-plus-8xx.dts b/arch/arm/boot/dts/ti/omap/am335x-netcom-plus-8xx.dts similarity index 97% rename from arch/arm/boot/dts/am335x-netcom-plus-8xx.dts rename to arch/arm/boot/dts/ti/omap/am335x-netcom-plus-8xx.dts index ad3adc7679f983673e18e2304c846d7cb9d1d116..5a9fcec040fae17359a8042f7cf26005af385546 100644 --- a/arch/arm/boot/dts/am335x-netcom-plus-8xx.dts +++ b/arch/arm/boot/dts/ti/omap/am335x-netcom-plus-8xx.dts @@ -20,7 +20,7 @@ pinctrl-names = "default"; pinctrl-0 = <&dip_switches>; - dip_switches: pinmux_dip_switches { + dip_switches: dip-switches-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_GPMC_AD12, PIN_INPUT_PULLDOWN, MUX_MODE7) AM33XX_PADCONF(AM335X_PIN_GPMC_AD13, PIN_INPUT_PULLDOWN, MUX_MODE7) @@ -29,13 +29,13 @@ >; }; - tca6416_pins: pinmux_tca6416_pins { + tca6416_pins: tca6416-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_XDMA_EVENT_INTR1, PIN_INPUT_PULLUP, MUX_MODE7) >; }; - i2c2_pins: pinmux_i2c2_pins { + i2c2_pins: i2c2-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_UART1_CTSN, PIN_INPUT_PULLDOWN, MUX_MODE3) AM33XX_PADCONF(AM335X_PIN_UART1_RTSN, PIN_INPUT_PULLDOWN, MUX_MODE3) diff --git a/arch/arm/boot/dts/am335x-osd3358-sm-red.dts b/arch/arm/boot/dts/ti/omap/am335x-osd3358-sm-red.dts similarity index 97% rename from arch/arm/boot/dts/am335x-osd3358-sm-red.dts rename to arch/arm/boot/dts/ti/omap/am335x-osd3358-sm-red.dts index b2846cd220f0477e03a556928d442e77a3aaa4f9..d28d3972884765047b92d802723a15e175828b0a 100644 --- a/arch/arm/boot/dts/am335x-osd3358-sm-red.dts +++ b/arch/arm/boot/dts/ti/omap/am335x-osd3358-sm-red.dts @@ -239,25 +239,25 @@ >; }; - flash_enable: flash-enable { + flash_enable: flash-enable-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_RMII1_REF_CLK, PIN_OUTPUT_PULLDOWN, MUX_MODE7) /* rmii1_ref_clk.gpio0_29 */ >; }; - imu_interrupt: imu-interrupt { + imu_interrupt: imu-interrupt-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_MII1_RX_ER, PIN_INPUT_PULLDOWN, MUX_MODE7) /* mii1_rx_er.gpio3_2 */ >; }; - ethernet_interrupt: ethernet-interrupt{ + ethernet_interrupt: ethernet-interrupt-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_MII1_COL, PIN_INPUT_PULLDOWN, MUX_MODE7) /* mii1_col.gpio3_0 */ >; }; - user_leds_s0: user-leds-s0 { + user_leds_s0: user-leds-s0-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_GPMC_A5, PIN_OUTPUT_PULLDOWN, MUX_MODE7) /* gpmc_a5.gpio1_21 */ AM33XX_PADCONF(AM335X_PIN_GPMC_A6, PIN_OUTPUT_PULLUP, MUX_MODE7) /* gpmc_a6.gpio1_22 */ @@ -280,13 +280,13 @@ >; }; - clkout2_pin: pinmux-clkout2-pin { + clkout2_pin: pinmux-clkout2-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_XDMA_EVENT_INTR1, PIN_OUTPUT_PULLDOWN, MUX_MODE3) /* xdma_event_intr1.clkout2 */ >; }; - cpsw_default: cpsw-default { + cpsw_default: cpsw-default-pins { pinctrl-single,pins = < /* Slave 1 */ AM33XX_PADCONF(AM335X_PIN_MII1_TX_EN, PIN_OUTPUT_PULLDOWN, MUX_MODE2) /* mii1_txen.rgmii1_tctl */ @@ -304,7 +304,7 @@ >; }; - cpsw_sleep: cpsw-sleep { + cpsw_sleep: cpsw-sleep-pins { pinctrl-single,pins = < /* Slave 1 reset value */ AM33XX_PADCONF(AM335X_PIN_MII1_TX_EN, PIN_INPUT_PULLDOWN, MUX_MODE7) @@ -322,7 +322,7 @@ >; }; - davinci_mdio_default: davinci-mdio-default { + davinci_mdio_default: davinci-mdio-default-pins { pinctrl-single,pins = < /* MDIO */ AM33XX_PADCONF(AM335X_PIN_MDIO, PIN_INPUT_PULLUP | SLEWCTRL_FAST, MUX_MODE0) @@ -330,7 +330,7 @@ >; }; - davinci_mdio_sleep: davinci-mdio-sleep { + davinci_mdio_sleep: davinci-mdio-sleep-pins { pinctrl-single,pins = < /* MDIO reset value */ AM33XX_PADCONF(AM335X_PIN_MDIO, PIN_INPUT_PULLDOWN, MUX_MODE7) diff --git a/arch/arm/boot/dts/am335x-osd335x-common.dtsi b/arch/arm/boot/dts/ti/omap/am335x-osd335x-common.dtsi similarity index 98% rename from arch/arm/boot/dts/am335x-osd335x-common.dtsi rename to arch/arm/boot/dts/ti/omap/am335x-osd335x-common.dtsi index 2888b15999ee68360dd4130c59c18c195c9e4834..9863bf499a39e873f3484c0c5e4ffb236c829004 100644 --- a/arch/arm/boot/dts/am335x-osd335x-common.dtsi +++ b/arch/arm/boot/dts/ti/omap/am335x-osd335x-common.dtsi @@ -54,7 +54,7 @@ }; }; -/include/ "tps65217.dtsi" +/include/ "../../tps65217.dtsi" &tps { interrupts = <7>; /* NMI */ diff --git a/arch/arm/boot/dts/am335x-pcm-953.dtsi b/arch/arm/boot/dts/ti/omap/am335x-pcm-953.dtsi similarity index 95% rename from arch/arm/boot/dts/am335x-pcm-953.dtsi rename to arch/arm/boot/dts/ti/omap/am335x-pcm-953.dtsi index 67c7fcc52ce6d8ecadbdfa4d5e77b6e54b0ed1e1..75efe1cf1dd23d3b782c241216008fc5277bbf0b 100644 --- a/arch/arm/boot/dts/am335x-pcm-953.dtsi +++ b/arch/arm/boot/dts/ti/omap/am335x-pcm-953.dtsi @@ -68,14 +68,14 @@ }; &am33xx_pinmux { - user_buttons_pins: pinmux-user-buttons { + user_buttons_pins: pinmux-user-buttons-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_EMU0, PIN_INPUT_PULLDOWN, MUX_MODE7) /* emu0.gpio3_7 */ AM33XX_PADCONF(AM335X_PIN_EMU1, PIN_INPUT_PULLDOWN, MUX_MODE7) /* emu1.gpio3_8 */ >; }; - user_leds_pins: pinmux-user-leds { + user_leds_pins: pinmux-user-leds-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_GPMC_CSN1, PIN_OUTPUT_PULLDOWN, MUX_MODE7) /* gpmc_csn1.gpio1_30 */ AM33XX_PADCONF(AM335X_PIN_GPMC_CSN2, PIN_OUTPUT_PULLDOWN, MUX_MODE7) /* gpmc_csn2.gpio1_31 */ @@ -85,7 +85,7 @@ /* CAN */ &am33xx_pinmux { - dcan1_pins: pinmux-dcan1 { + dcan1_pins: pinmux-dcan1-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_UART1_RXD, PIN_OUTPUT_PULLUP, MUX_MODE2) /* uart1_rxd.dcan1_tx_mux2 */ AM33XX_PADCONF(AM335X_PIN_UART1_TXD, PIN_INPUT_PULLUP, MUX_MODE2) /* uart1_txd.dcan1_rx_mux2 */ @@ -101,7 +101,7 @@ /* Ethernet */ &am33xx_pinmux { - ethernet1_pins: pinmux_ethernet1 { + ethernet1_pins: ethernet1-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_GPMC_A0, PIN_OUTPUT_PULLDOWN, MUX_MODE2) /* gpmc_a0.rgmii2_tctl */ AM33XX_PADCONF(AM335X_PIN_GPMC_A1, PIN_INPUT_PULLDOWN, MUX_MODE2) /* gpmc_a1.rgmii2_rctl */ @@ -142,7 +142,7 @@ pinctrl-names = "default"; pinctrl-0 = <&cb_gpio_pins>; - cb_gpio_pins: pinmux-cb-gpio { + cb_gpio_pins: pinmux-cb-gpio-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_UART0_CTSN, PIN_OUTPUT_PULLDOWN, MUX_MODE7) /* uart0_ctsn.gpio1_8 */ AM33XX_PADCONF(AM335X_PIN_UART0_RTSN, PIN_OUTPUT_PULLDOWN, MUX_MODE7) /* uart0_rtsn.gpio1_9 */ @@ -176,14 +176,14 @@ /* UARTs */ &am33xx_pinmux { - uart0_pins: pinmux-uart0 { + uart0_pins: pinmux-uart0-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_UART0_RXD, PIN_INPUT_PULLUP, MUX_MODE0) AM33XX_PADCONF(AM335X_PIN_UART0_TXD, PIN_OUTPUT_PULLDOWN, MUX_MODE0) >; }; - uart1_pins: pinmux-uart1 { + uart1_pins: pinmux-uart1-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_UART1_RXD, PIN_INPUT_PULLUP, MUX_MODE0) AM33XX_PADCONF(AM335X_PIN_UART1_TXD, PIN_OUTPUT_PULLDOWN, MUX_MODE0) @@ -192,14 +192,14 @@ >; }; - uart2_pins: pinmux-uart2 { + uart2_pins: pinmux-uart2-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_MII1_TX_CLK, PIN_INPUT_PULLUP, MUX_MODE1) /* mii1_tx_clk.uart2_rxd */ AM33XX_PADCONF(AM335X_PIN_MII1_RX_CLK, PIN_OUTPUT_PULLDOWN, MUX_MODE1) /* mii1_rx_clk.uart2_txd */ >; }; - uart3_pins: pinmux-uart3 { + uart3_pins: pinmux-uart3-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_MII1_RXD3, PIN_INPUT_PULLUP, MUX_MODE1) /* mii1_rxd3.uart3_rxd */ AM33XX_PADCONF(AM335X_PIN_MII1_RXD2, PIN_OUTPUT_PULLDOWN, MUX_MODE1) /* mii1_rxd2.uart3_txd */ diff --git a/arch/arm/boot/dts/am335x-pdu001.dts b/arch/arm/boot/dts/ti/omap/am335x-pdu001.dts similarity index 96% rename from arch/arm/boot/dts/am335x-pdu001.dts rename to arch/arm/boot/dts/ti/omap/am335x-pdu001.dts index ce6cc2b96654f86cc181abcd3647ea8c187428fe..3c9444e98c14b0537a1de5912fa0b04aca491f3a 100644 --- a/arch/arm/boot/dts/am335x-pdu001.dts +++ b/arch/arm/boot/dts/ti/omap/am335x-pdu001.dts @@ -90,28 +90,28 @@ pinctrl-names = "default"; pinctrl-0 = <&clkout2_pin>; - i2c0_pins: pinmux_i2c0_pins { + i2c0_pins: i2c0-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_I2C0_SDA, PIN_INPUT_PULLUP, MUX_MODE0) AM33XX_PADCONF(AM335X_PIN_I2C0_SCL, PIN_INPUT_PULLUP, MUX_MODE0) >; }; - i2c1_pins: pinmux_i2c1_pins { + i2c1_pins: i2c1-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_SPI0_D1, PIN_INPUT_PULLUP, MUX_MODE2) /* spi0_d1.i2c1_sda */ AM33XX_PADCONF(AM335X_PIN_SPI0_CS0, PIN_INPUT_PULLUP, MUX_MODE2) /* spi0_cs0.i2c1_scl */ >; }; - i2c2_pins: pinmux_i2c2_pins { + i2c2_pins: i2c2-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_SPI0_SCLK, PIN_INPUT_PULLUP, MUX_MODE2) /* spi0_clk.i2c2_sda */ AM33XX_PADCONF(AM335X_PIN_SPI0_D0, PIN_INPUT_PULLUP, MUX_MODE2) /* spi0_d0.i2c2_scl */ >; }; - spi1_pins: pinmux_spi1_pins { + spi1_pins: spi1-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_MCASP0_ACLKX, PIN_OUTPUT, MUX_MODE3) /* mcasp0_aclkx.spi1_sclk */ AM33XX_PADCONF(AM335X_PIN_MCASP0_FSX, PIN_OUTPUT, MUX_MODE3) /* mcasp0_fsx.spi1_d0 */ @@ -120,7 +120,7 @@ >; }; - uart0_pins: pinmux_uart0_pins { + uart0_pins: uart0-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_UART0_RTSN, PIN_OUTPUT, MUX_MODE7) AM33XX_PADCONF(AM335X_PIN_UART0_RXD, PIN_INPUT_PULLUP, MUX_MODE0) @@ -128,27 +128,27 @@ >; }; - uart1_pins: pinmux_uart1_pins { + uart1_pins: uart1-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_UART1_RXD, PIN_INPUT_PULLUP, MUX_MODE0) AM33XX_PADCONF(AM335X_PIN_UART1_TXD, PIN_OUTPUT_PULLDOWN, MUX_MODE0) >; }; - uart3_pins: pinmux_uart3_pins { + uart3_pins: uart3-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_SPI0_CS1, PIN_INPUT_PULLUP, MUX_MODE1) /* spi0_cs1.uart3_rxd */ AM33XX_PADCONF(AM335X_PIN_ECAP0_IN_PWM0_OUT, PIN_OUTPUT_PULLDOWN, MUX_MODE1) /* ecap0_in_pwm0_out.uart3_txd */ >; }; - clkout2_pin: pinmux_clkout2_pin { + clkout2_pin: clkout2-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_XDMA_EVENT_INTR1, PIN_OUTPUT_PULLDOWN, MUX_MODE3) /* xdma_event_intr1.clkout2 */ >; }; - cpsw_default: cpsw_default { + cpsw_default: cpsw-default-pins { pinctrl-single,pins = < /* Port 1 (emac0) */ AM33XX_PADCONF(AM335X_PIN_MII1_COL, PIN_INPUT, MUX_MODE0) @@ -186,14 +186,14 @@ >; }; - davinci_mdio_default: davinci_mdio_default { + davinci_mdio_default: davinci-mdio-default-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_MDIO, PIN_INPUT_PULLUP | SLEWCTRL_FAST, MUX_MODE0) AM33XX_PADCONF(AM335X_PIN_MDC, PIN_OUTPUT_PULLUP, MUX_MODE0) >; }; - mmc1_pins: pinmux_mmc1_pins { + mmc1_pins: mmc1-pins { /* eMMC */ pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_MMC0_DAT3, PIN_INPUT_PULLUP, MUX_MODE0) @@ -205,7 +205,7 @@ >; }; - mmc2_pins: pinmux_mmc2_pins { + mmc2_pins: mmc2-pins { /* SD cardcage */ pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_GPMC_AD3, PIN_INPUT_PULLUP, MUX_MODE1) /* gpmc_ad3.mmc1_dat3 */ @@ -219,7 +219,7 @@ >; }; - lcd_pins_s0: lcd_pins_s0 { + lcd_pins_s0: lcd-s0-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_LCD_DATA0, PIN_OUTPUT, MUX_MODE0) AM33XX_PADCONF(AM335X_PIN_LCD_DATA1, PIN_OUTPUT, MUX_MODE0) @@ -244,7 +244,7 @@ >; }; - dcan0_pins: pinmux_dcan0_pins { + dcan0_pins: dcan0-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_UART1_CTSN, PIN_OUTPUT, MUX_MODE2) /* uart1_ctsn.d_can0_tx */ AM33XX_PADCONF(AM335X_PIN_UART1_RTSN, PIN_INPUT_PULLDOWN, MUX_MODE2) /* uart1_rtsn.d_can0_rx */ @@ -400,7 +400,7 @@ status = "okay"; }; -#include "tps65910.dtsi" +#include "../../tps65910.dtsi" &tps { vcc1-supply = <&vbat>; diff --git a/arch/arm/boot/dts/am335x-pepper.dts b/arch/arm/boot/dts/ti/omap/am335x-pepper.dts similarity index 97% rename from arch/arm/boot/dts/am335x-pepper.dts rename to arch/arm/boot/dts/ti/omap/am335x-pepper.dts index a4509e9e1056c72d03f734dfe36216d36b7f1d4b..d5a4a21889d1c1763085a2a4530df7137a9aac63 100644 --- a/arch/arm/boot/dts/am335x-pepper.dts +++ b/arch/arm/boot/dts/ti/omap/am335x-pepper.dts @@ -26,7 +26,7 @@ compatible = "gpio-keys"; }; - leds: user_leds { + leds: user-leds-pins { compatible = "gpio-leds"; }; @@ -88,13 +88,13 @@ }; &am33xx_pinmux { - i2c0_pins: pinmux_i2c0 { + i2c0_pins: i2c0-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_I2C0_SDA, PIN_INPUT_PULLUP, MUX_MODE0) AM33XX_PADCONF(AM335X_PIN_I2C0_SCL, PIN_INPUT_PULLUP, MUX_MODE0) >; }; - i2c1_pins: pinmux_i2c1 { + i2c1_pins: i2c1-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_MII1_CRS, PIN_INPUT_PULLUP, MUX_MODE3) /* mii1_crs,i2c1_sda */ AM33XX_PADCONF(AM335X_PIN_MII1_RX_ER, PIN_INPUT_PULLUP, MUX_MODE3) /* mii1_rxerr,i2c1_scl */ @@ -125,7 +125,7 @@ }; &am33xx_pinmux { - accel_pins: pinmux_accel { + accel_pins: accel-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_GPMC_WEN, PIN_INPUT, MUX_MODE7) /* gpmc_wen.gpio2_4 */ >; @@ -172,7 +172,7 @@ }; &am33xx_pinmux { - audio_pins: pinmux_audio { + audio_pins: audio-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_MCASP0_AHCLKX, PIN_INPUT_PULLDOWN, MUX_MODE0) AM33XX_PADCONF(AM335X_PIN_MCASP0_FSX, PIN_INPUT_PULLDOWN, MUX_MODE0) @@ -223,7 +223,7 @@ }; &am33xx_pinmux { - lcd_pins: pinmux_lcd { + lcd_pins: lcd-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_LCD_DATA0, PIN_OUTPUT, MUX_MODE0) AM33XX_PADCONF(AM335X_PIN_LCD_DATA1, PIN_OUTPUT, MUX_MODE0) @@ -292,7 +292,7 @@ }; &am33xx_pinmux { - ethernet_pins: pinmux_ethernet { + ethernet_pins: ethernet-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_MII1_TX_EN, PIN_OUTPUT_PULLDOWN, MUX_MODE2) /* mii1_txen.rgmii1_tctl */ AM33XX_PADCONF(AM335X_PIN_MII1_RX_DV, PIN_INPUT_PULLUP, MUX_MODE2) /* mii1_rxdv.rgmii1_rctl */ @@ -313,7 +313,7 @@ >; }; - mdio_pins: pinmux_mdio { + mdio_pins: mdio-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_MDIO, PIN_INPUT_PULLUP | SLEWCTRL_FAST, MUX_MODE0) AM33XX_PADCONF(AM335X_PIN_MDC, PIN_OUTPUT_PULLUP, MUX_MODE0) @@ -357,7 +357,7 @@ &am33xx_pinmux { - sd_pins: pinmux_sd_card { + sd_pins: sd-card-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_MMC0_DAT3, PIN_INPUT_PULLUP, MUX_MODE0) AM33XX_PADCONF(AM335X_PIN_MMC0_DAT2, PIN_INPUT_PULLUP, MUX_MODE0) @@ -368,7 +368,7 @@ AM33XX_PADCONF(AM335X_PIN_SPI0_CS1, PIN_INPUT, MUX_MODE7) /* spi0_cs1.gpio0_6 */ >; }; - emmc_pins: pinmux_emmc { + emmc_pins: emmc-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_GPMC_CSN1, PIN_INPUT_PULLUP, MUX_MODE2) /* gpmc_csn1.mmc1_clk */ AM33XX_PADCONF(AM335X_PIN_GPMC_CSN2, PIN_INPUT_PULLUP, MUX_MODE2) /* gpmc_csn2.mmc1_cmd */ @@ -384,7 +384,7 @@ AM33XX_PADCONF(AM335X_PIN_GPMC_WPN, PIN_OUTPUT_PULLUP, MUX_MODE7) /* gpmc_wpn.gpio0_31 */ >; }; - wireless_pins: pinmux_wireless { + wireless_pins: wireless-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_GPMC_A1, PIN_INPUT_PULLUP, MUX_MODE3) /* gpmc_a1.mmc2_dat0 */ AM33XX_PADCONF(AM335X_PIN_GPMC_A2, PIN_INPUT_PULLUP, MUX_MODE3) /* gpmc_a2.mmc2_dat1 */ @@ -423,7 +423,7 @@ vin-supply = <&vbat>; }; -/include/ "tps65217.dtsi" +/include/ "../../tps65217.dtsi" &tps { backlight { @@ -491,7 +491,7 @@ }; &am33xx_pinmux { - spi0_pins: pinmux_spi0 { + spi0_pins: spi0-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_SPI0_SCLK, PIN_INPUT_PULLUP, MUX_MODE0) AM33XX_PADCONF(AM335X_PIN_SPI0_CS0, PIN_INPUT_PULLUP, MUX_MODE0) @@ -532,13 +532,13 @@ }; &am33xx_pinmux { - uart0_pins: pinmux_uart0 { + uart0_pins: uart0-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_UART0_RXD, PIN_INPUT_PULLUP, MUX_MODE0) AM33XX_PADCONF(AM335X_PIN_UART0_TXD, PIN_OUTPUT_PULLDOWN, MUX_MODE0) >; }; - uart1_pins: pinmux_uart1 { + uart1_pins: uart1-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_UART1_CTSN, PIN_INPUT_PULLUP, MUX_MODE0) AM33XX_PADCONF(AM335X_PIN_UART1_RTSN, PIN_OUTPUT_PULLDOWN, MUX_MODE0) @@ -563,7 +563,7 @@ }; &am33xx_pinmux { - usb_pins: pinmux_usb { + usb_pins: usb-pins { pinctrl-single,pins = < /* USB0 Over-Current (active low) */ AM33XX_PADCONF(AM335X_PIN_GPMC_A9, PIN_INPUT, MUX_MODE7) /* gpmc_a9.gpio1_25 */ @@ -620,14 +620,14 @@ }; &am33xx_pinmux { - user_leds_pins: pinmux_user_leds { + user_leds_pins: user-leds-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_GPMC_A4, PIN_OUTPUT, MUX_MODE7) /* gpmc_a4.gpio1_20 */ AM33XX_PADCONF(AM335X_PIN_GPMC_A5, PIN_OUTPUT, MUX_MODE7) /* gpmc_a5.gpio1_21 */ >; }; - user_buttons_pins: pinmux_user_buttons { + user_buttons_pins: user-buttons-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_GPMC_A6, PIN_INPUT_PULLUP, MUX_MODE7) /* gpmc_a6.gpio1_22 */ AM33XX_PADCONF(AM335X_PIN_GPMC_A7, PIN_INPUT_PULLUP, MUX_MODE7) /* gpmc_a7.gpio1_21 */ diff --git a/arch/arm/boot/dts/am335x-phycore-rdk.dts b/arch/arm/boot/dts/ti/omap/am335x-phycore-rdk.dts similarity index 100% rename from arch/arm/boot/dts/am335x-phycore-rdk.dts rename to arch/arm/boot/dts/ti/omap/am335x-phycore-rdk.dts diff --git a/arch/arm/boot/dts/am335x-phycore-som.dtsi b/arch/arm/boot/dts/ti/omap/am335x-phycore-som.dtsi similarity index 97% rename from arch/arm/boot/dts/am335x-phycore-som.dtsi rename to arch/arm/boot/dts/ti/omap/am335x-phycore-som.dtsi index 034dc518167948d7d127b41cee50d1c7ad8c4211..84c15a44df6a826a6b3d1b58001cbb1e1f61cb57 100644 --- a/arch/arm/boot/dts/am335x-phycore-som.dtsi +++ b/arch/arm/boot/dts/ti/omap/am335x-phycore-som.dtsi @@ -76,7 +76,7 @@ /* Ethernet */ &am33xx_pinmux { - ethernet0_pins: pinmux_ethernet0 { + ethernet0_pins: ethernet0-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_MII1_CRS, PIN_INPUT_PULLDOWN, MUX_MODE1) AM33XX_PADCONF(AM335X_PIN_MII1_RX_ER, PIN_INPUT_PULLDOWN, MUX_MODE1) @@ -89,7 +89,7 @@ >; }; - mdio_pins: pinmux_mdio { + mdio_pins: mdio-pins { pinctrl-single,pins = < /* MDIO */ AM33XX_PADCONF(AM335X_PIN_MDIO, PIN_INPUT_PULLUP | SLEWCTRL_FAST, MUX_MODE0) @@ -125,7 +125,7 @@ /* I2C Busses */ &am33xx_pinmux { - i2c0_pins: pinmux-i2c0 { + i2c0_pins: pinmux-i2c0-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_I2C0_SDA, PIN_INPUT, MUX_MODE0) AM33XX_PADCONF(AM335X_PIN_I2C0_SCL, PIN_INPUT, MUX_MODE0) @@ -165,7 +165,7 @@ /* NAND memory */ &am33xx_pinmux { - nandflash_pins: pinmux-nandflash { + nandflash_pins: pinmux-nandflash-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_GPMC_AD0, PIN_INPUT_PULLUP, MUX_MODE0) AM33XX_PADCONF(AM335X_PIN_GPMC_AD1, PIN_INPUT_PULLUP, MUX_MODE0) @@ -233,7 +233,7 @@ }; /* Power */ -#include "tps65910.dtsi" +#include "../../tps65910.dtsi" &tps { vcc1-supply = <&vcc5v>; @@ -316,7 +316,7 @@ /* SPI Busses */ &am33xx_pinmux { - spi0_pins: pinmux-spi0 { + spi0_pins: pinmux-spi0-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_SPI0_SCLK, PIN_INPUT_PULLDOWN, MUX_MODE0) AM33XX_PADCONF(AM335X_PIN_SPI0_D0, PIN_INPUT_PULLDOWN, MUX_MODE0) diff --git a/arch/arm/boot/dts/am335x-pocketbeagle.dts b/arch/arm/boot/dts/ti/omap/am335x-pocketbeagle.dts similarity index 96% rename from arch/arm/boot/dts/am335x-pocketbeagle.dts rename to arch/arm/boot/dts/ti/omap/am335x-pocketbeagle.dts index 0ba4883cd4eff9dda74b460457287eb4f70b9616..5dfe4d4bab934bd3f210a523e9ae29b4a3e36746 100644 --- a/arch/arm/boot/dts/am335x-pocketbeagle.dts +++ b/arch/arm/boot/dts/ti/omap/am335x-pocketbeagle.dts @@ -214,7 +214,7 @@ &P2_17_gpio >; /* P2_03 (ZCZ ball T10) gpio0_23 0x824 PIN 9 */ - P2_03_gpio: pinmux_P2_03_gpio { + P2_03_gpio: P2-03-gpio-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_GPMC_AD9, PIN_INPUT_PULLUP, MUX_MODE7) >; @@ -223,7 +223,7 @@ }; /* P1_34 (ZCZ ball T11) gpio0_26 0x828 PIN 10 */ - P1_34_gpio: pinmux_P1_34_gpio { + P1_34_gpio: P1-34-gpio-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_GPMC_AD10, PIN_INPUT_PULLUP, MUX_MODE7) >; @@ -232,7 +232,7 @@ }; /* P2_19 (ZCZ ball U12) gpio0_27 0x82c PIN 11 */ - P2_19_gpio: pinmux_P2_19_gpio { + P2_19_gpio: P2-19-gpio-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_GPMC_AD11, PIN_INPUT_PULLUP, MUX_MODE7) >; @@ -241,7 +241,7 @@ }; /* P2_24 (ZCZ ball T12) gpio1_12 0x830 PIN 12 */ - P2_24_gpio: pinmux_P2_24_gpio { + P2_24_gpio: P2-24-gpio-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_GPMC_AD12, PIN_INPUT_PULLUP, MUX_MODE7) >; @@ -250,7 +250,7 @@ }; /* P2_33 (ZCZ ball R12) gpio1_13 0x834 PIN 13 */ - P2_33_gpio: pinmux_P2_33_gpio { + P2_33_gpio: P2-33-gpio-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_GPMC_AD13, PIN_INPUT_PULLUP, MUX_MODE7) >; @@ -259,7 +259,7 @@ }; /* P2_22 (ZCZ ball V13) gpio1_14 0x838 PIN 14 */ - P2_22_gpio: pinmux_P2_22_gpio { + P2_22_gpio: P2-22-gpio-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_GPMC_AD14, PIN_INPUT_PULLUP, MUX_MODE7) >; @@ -268,7 +268,7 @@ }; /* P2_18 (ZCZ ball U13) gpio1_15 0x83c PIN 15 */ - P2_18_gpio: pinmux_P2_18_gpio { + P2_18_gpio: P2-18-gpio-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_GPMC_AD15, PIN_INPUT_PULLUP, MUX_MODE7) >; @@ -277,7 +277,7 @@ }; /* P2_10 (ZCZ ball R14) gpio1_20 0x850 PIN 20 */ - P2_10_gpio: pinmux_P2_10_gpio { + P2_10_gpio: P2-10-gpio-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_GPMC_A4, PIN_INPUT_PULLUP, MUX_MODE7) >; @@ -286,7 +286,7 @@ }; /* P2_06 (ZCZ ball U16) gpio1_25 0x864 PIN 25 */ - P2_06_gpio: pinmux_P2_06_gpio { + P2_06_gpio: P2-06-gpio-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_GPMC_A9, PIN_INPUT_PULLUP, MUX_MODE7) >; @@ -295,7 +295,7 @@ }; /* P2_04 (ZCZ ball T16) gpio1_26 0x868 PIN 26 */ - P2_04_gpio: pinmux_P2_04_gpio { + P2_04_gpio: P2-04-gpio-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_GPMC_A10, PIN_INPUT_PULLUP, MUX_MODE7) >; @@ -304,7 +304,7 @@ }; /* P2_02 (ZCZ ball V17) gpio1_27 0x86c PIN 27 */ - P2_02_gpio: pinmux_P2_02_gpio { + P2_02_gpio: P2-02-gpio-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_GPMC_A11, PIN_INPUT_PULLUP, MUX_MODE7) >; @@ -313,7 +313,7 @@ }; /* P2_08 (ZCZ ball U18) gpio1_28 0x878 PIN 30 */ - P2_08_gpio: pinmux_P2_08_gpio { + P2_08_gpio: P2-08-gpio-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_GPMC_BEN1, PIN_INPUT_PULLDOWN, MUX_MODE7) >; @@ -322,7 +322,7 @@ }; /* P2_17 (ZCZ ball V12) gpio2_1 0x88c PIN 35 */ - P2_17_gpio: pinmux_P2_17_gpio { + P2_17_gpio: P2-17-gpio-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_GPMC_CLK, PIN_INPUT_PULLUP, MUX_MODE7) >; diff --git a/arch/arm/boot/dts/am335x-regor-rdk.dts b/arch/arm/boot/dts/ti/omap/am335x-regor-rdk.dts similarity index 100% rename from arch/arm/boot/dts/am335x-regor-rdk.dts rename to arch/arm/boot/dts/ti/omap/am335x-regor-rdk.dts diff --git a/arch/arm/boot/dts/am335x-regor.dtsi b/arch/arm/boot/dts/ti/omap/am335x-regor.dtsi similarity index 95% rename from arch/arm/boot/dts/am335x-regor.dtsi rename to arch/arm/boot/dts/ti/omap/am335x-regor.dtsi index 3894f14a914cff14de5d7d83a7e0971dda3259ed..625db3bcd3656dc60545d7865a6c40b7ffae9f87 100644 --- a/arch/arm/boot/dts/am335x-regor.dtsi +++ b/arch/arm/boot/dts/ti/omap/am335x-regor.dtsi @@ -39,7 +39,7 @@ /* User Leds */ &am33xx_pinmux { - user_leds_pins: pinmux-user-leds { + user_leds_pins: pinmux-user-leds-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_LCD_VSYNC, PIN_OUTPUT_PULLDOWN, MUX_MODE7) /* lcd_hsync.gpio2_22 */ AM33XX_PADCONF(AM335X_PIN_MCASP0_FSX, PIN_OUTPUT_PULLDOWN, MUX_MODE7) /* mcasp0_fsx.gpio3_15 */ @@ -49,7 +49,7 @@ /* CAN Busses */ &am33xx_pinmux { - dcan1_pins: pinmux-dcan1 { + dcan1_pins: pinmux-dcan1-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_UART0_CTSN, PIN_OUTPUT_PULLUP, MUX_MODE2) /* uart0_ctsn.d_can1_tx */ AM33XX_PADCONF(AM335X_PIN_UART0_RTSN, PIN_INPUT_PULLUP, MUX_MODE2) /* uart0_rtsn.d_can1_rx */ @@ -65,7 +65,7 @@ /* Ethernet */ &am33xx_pinmux { - ethernet1_pins: pinmux-ethernet1 { + ethernet1_pins: pinmux-ethernet1-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_GPMC_A0, PIN_OUTPUT, MUX_MODE1) /* gpmc_a0.mii2_txen */ AM33XX_PADCONF(AM335X_PIN_GPMC_A1, PIN_INPUT_PULLDOWN, MUX_MODE1) /* gpmc_a1.mii2_rxdv */ @@ -108,7 +108,7 @@ pinctrl-names = "default"; pinctrl-0 = <&user_gpios_pins>; - user_gpios_pins: pinmux-user-gpios { + user_gpios_pins: pinmux-user-gpios-pins { pinctrl-single,pins = < /* DIGIN 1-4 */ AM33XX_PADCONF(AM335X_PIN_GPMC_AD11, PIN_INPUT, MUX_MODE7) /* gpmc_ad11.gpio0_27 */ @@ -126,7 +126,7 @@ /* MMC */ &am33xx_pinmux { - mmc1_pins: pinmux-mmc1 { + mmc1_pins: pinmux-mmc1-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_MMC0_DAT3, PIN_INPUT_PULLUP, MUX_MODE0) AM33XX_PADCONF(AM335X_PIN_MMC0_DAT2, PIN_INPUT_PULLUP, MUX_MODE0) @@ -155,14 +155,14 @@ /* UARTs */ &am33xx_pinmux { - uart0_pins: pinmux-uart0 { + uart0_pins: pinmux-uart0-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_UART0_RXD, PIN_INPUT_PULLUP, MUX_MODE0) AM33XX_PADCONF(AM335X_PIN_UART0_TXD, PIN_OUTPUT_PULLDOWN, MUX_MODE0) >; }; - uart2_pins: pinmux-uart2 { + uart2_pins: pinmux-uart2-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_MII1_TX_CLK, PIN_INPUT_PULLUP, MUX_MODE1) /* mii1_tx_clk.uart2_rxd */ AM33XX_PADCONF(AM335X_PIN_MII1_RX_CLK, PIN_OUTPUT_PULLDOWN, MUX_MODE1) /* mii1_rx_clk.uart2_txd */ diff --git a/arch/arm/boot/dts/am335x-sancloud-bbe-common.dtsi b/arch/arm/boot/dts/ti/omap/am335x-sancloud-bbe-common.dtsi similarity index 96% rename from arch/arm/boot/dts/am335x-sancloud-bbe-common.dtsi rename to arch/arm/boot/dts/ti/omap/am335x-sancloud-bbe-common.dtsi index f9b7e774ac48d21e854aec8db9d8d46e555e1b2e..a138eb35687449545f898ace0948c694a44b998b 100644 --- a/arch/arm/boot/dts/am335x-sancloud-bbe-common.dtsi +++ b/arch/arm/boot/dts/ti/omap/am335x-sancloud-bbe-common.dtsi @@ -4,7 +4,7 @@ */ &am33xx_pinmux { - cpsw_default: cpsw_default { + cpsw_default: cpsw-default-pins { pinctrl-single,pins = < /* Slave 1 */ AM33XX_PADCONF(AM335X_PIN_MII1_TX_EN, PIN_OUTPUT_PULLDOWN, MUX_MODE2) /* mii1_txen.rgmii1_tctl */ @@ -22,7 +22,7 @@ >; }; - cpsw_sleep: cpsw_sleep { + cpsw_sleep: cpsw-sleep-pins { pinctrl-single,pins = < /* Slave 1 reset value */ AM33XX_PADCONF(AM335X_PIN_MII1_TX_EN, PIN_INPUT_PULLDOWN, MUX_MODE7) @@ -40,7 +40,7 @@ >; }; - usb_hub_ctrl: usb_hub_ctrl { + usb_hub_ctrl: usb-hub-ctrl-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_RMII1_REF_CLK, PIN_OUTPUT_PULLUP, MUX_MODE7) /* rmii1_refclk.gpio0_29 */ >; diff --git a/arch/arm/boot/dts/am335x-sancloud-bbe-extended-wifi.dts b/arch/arm/boot/dts/ti/omap/am335x-sancloud-bbe-extended-wifi.dts similarity index 96% rename from arch/arm/boot/dts/am335x-sancloud-bbe-extended-wifi.dts rename to arch/arm/boot/dts/ti/omap/am335x-sancloud-bbe-extended-wifi.dts index a2676d10c24af1830ba6daabf22579db4f85f28c..5522759def2669b2800283fc8c3d8ae3c6de0939 100644 --- a/arch/arm/boot/dts/am335x-sancloud-bbe-extended-wifi.dts +++ b/arch/arm/boot/dts/ti/omap/am335x-sancloud-bbe-extended-wifi.dts @@ -28,7 +28,7 @@ }; &am33xx_pinmux { - mmc3_pins: pinmux_mmc3_pins { + mmc3_pins: mmc3-pins { pinctrl-single,pins = < /* gpmc_a9.gpio1_25: RADIO_EN */ AM33XX_PADCONF(AM335X_PIN_GPMC_A9, PIN_OUTPUT_PULLUP, MUX_MODE7) @@ -53,14 +53,14 @@ >; }; - bluetooth_pins: pinmux_bluetooth_pins { + bluetooth_pins: bluetooth-pins { pinctrl-single,pins = < /* event_intr0.gpio0_19 */ AM33XX_PADCONF(AM335X_PIN_XDMA_EVENT_INTR0, PIN_INPUT_PULLUP, MUX_MODE7) >; }; - uart1_pins: pinmux_uart1_pins { + uart1_pins: uart1-pins { pinctrl-single,pins = < /* uart1_rxd */ AM33XX_PADCONF(AM335X_PIN_UART1_RXD, PIN_INPUT, MUX_MODE0) diff --git a/arch/arm/boot/dts/am335x-sancloud-bbe-lite.dts b/arch/arm/boot/dts/ti/omap/am335x-sancloud-bbe-lite.dts similarity index 96% rename from arch/arm/boot/dts/am335x-sancloud-bbe-lite.dts rename to arch/arm/boot/dts/ti/omap/am335x-sancloud-bbe-lite.dts index d6ef19311a914272cb9d7fe0e9e55c1d9c306294..b1b400226d837f0fa48395c8b68e9e0b84c98d45 100644 --- a/arch/arm/boot/dts/am335x-sancloud-bbe-lite.dts +++ b/arch/arm/boot/dts/ti/omap/am335x-sancloud-bbe-lite.dts @@ -19,7 +19,7 @@ }; &am33xx_pinmux { - bb_spi0_pins: pinmux_bb_spi0_pins { + bb_spi0_pins: bb-spi0-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_SPI0_SCLK, PIN_INPUT, MUX_MODE0) AM33XX_PADCONF(AM335X_PIN_SPI0_D0, PIN_INPUT, MUX_MODE0) diff --git a/arch/arm/boot/dts/am335x-sancloud-bbe.dts b/arch/arm/boot/dts/ti/omap/am335x-sancloud-bbe.dts similarity index 94% rename from arch/arm/boot/dts/am335x-sancloud-bbe.dts rename to arch/arm/boot/dts/ti/omap/am335x-sancloud-bbe.dts index efbe93135dbe45e716fb7abf46a8fe9583d89e14..32669346cefe8215e5ceeb5d12d0180c0b5cc811 100644 --- a/arch/arm/boot/dts/am335x-sancloud-bbe.dts +++ b/arch/arm/boot/dts/ti/omap/am335x-sancloud-bbe.dts @@ -17,13 +17,13 @@ }; &am33xx_pinmux { - mpu6050_pins: pinmux_mpu6050_pins { + mpu6050_pins: mpu6050-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_UART0_CTSN, PIN_INPUT, MUX_MODE7) /* uart0_ctsn.gpio1_8 */ >; }; - lps3331ap_pins: pinmux_lps3331ap_pins { + lps3331ap_pins: lps3331ap-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_GPMC_A10, PIN_INPUT, MUX_MODE7) /* gpmc_a10.gpio1_26 */ >; diff --git a/arch/arm/boot/dts/am335x-sbc-t335.dts b/arch/arm/boot/dts/ti/omap/am335x-sbc-t335.dts similarity index 98% rename from arch/arm/boot/dts/am335x-sbc-t335.dts rename to arch/arm/boot/dts/ti/omap/am335x-sbc-t335.dts index 81e4453687ba111f7094706cc89c949fea02cb6e..596774c847448f121751717a2df6c9a34df93ea6 100644 --- a/arch/arm/boot/dts/am335x-sbc-t335.dts +++ b/arch/arm/boot/dts/ti/omap/am335x-sbc-t335.dts @@ -64,7 +64,7 @@ &am33xx_pinmux { /* Display */ - lcd_pins_default: lcd_pins_default { + lcd_pins_default: lcd-default-pins { pinctrl-single,pins = < /* gpmc_ad8.lcd_data23 */ AM33XX_PADCONF(AM335X_PIN_GPMC_AD8, PIN_OUTPUT, MUX_MODE1) @@ -105,7 +105,7 @@ >; }; - lcd_pins_sleep: lcd_pins_sleep { + lcd_pins_sleep: lcd-sleep-pins { pinctrl-single,pins = < /* gpmc_ad8.lcd_data23 */ AM33XX_PADCONF(AM335X_PIN_GPMC_AD8, PIN_INPUT_PULLDOWN, MUX_MODE7) diff --git a/arch/arm/boot/dts/am335x-shc.dts b/arch/arm/boot/dts/ti/omap/am335x-shc.dts similarity index 96% rename from arch/arm/boot/dts/am335x-shc.dts rename to arch/arm/boot/dts/ti/omap/am335x-shc.dts index c497200f9cb0b436590feb975c68a1d1af113056..9297cb1efcd4b6991a4b67cdc861a2045dd7082e 100644 --- a/arch/arm/boot/dts/am335x-shc.dts +++ b/arch/arm/boot/dts/ti/omap/am335x-shc.dts @@ -366,14 +366,14 @@ pinctrl-names = "default"; pinctrl-0 = <&clkout2_pin>; - clkout2_pin: pinmux_clkout2_pin { + clkout2_pin: clkout2-pins { pinctrl-single,pins = < /* xdma_event_intr1.clkout2 */ AM33XX_PADCONF(AM335X_PIN_XDMA_EVENT_INTR1, PIN_INPUT, MUX_MODE6) >; }; - cpsw_default: cpsw_default { + cpsw_default: cpsw-default-pins { pinctrl-single,pins = < /* Slave 1 */ AM33XX_PADCONF(AM335X_PIN_MII1_RX_ER, PIN_INPUT_PULLDOWN, MUX_MODE0) @@ -392,7 +392,7 @@ >; }; - cpsw_sleep: cpsw_sleep { + cpsw_sleep: cpsw-sleep-pins { pinctrl-single,pins = < /* Slave 1 reset value */ AM33XX_PADCONF(AM335X_PIN_MII1_RX_ER, PIN_INPUT_PULLDOWN, MUX_MODE7) @@ -411,14 +411,14 @@ >; }; - davinci_mdio_default: davinci_mdio_default { + davinci_mdio_default: davinci-mdio-default-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_MDIO, PIN_INPUT_PULLUP | SLEWCTRL_FAST, MUX_MODE0) AM33XX_PADCONF(AM335X_PIN_MDC, PIN_OUTPUT_PULLUP, MUX_MODE0) >; }; - davinci_mdio_sleep: davinci_mdio_sleep { + davinci_mdio_sleep: davinci-mdio-sleep-pins { pinctrl-single,pins = < /* MDIO reset value */ AM33XX_PADCONF(AM335X_PIN_MDIO, PIN_INPUT_PULLDOWN, MUX_MODE7) @@ -426,13 +426,13 @@ >; }; - ehrpwm1_pins: pinmux_ehrpwm1 { + ehrpwm1_pins: ehrpwm1-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_GPMC_A3, PIN_OUTPUT, MUX_MODE6) /* gpmc_a3.gpio1_19 */ >; }; - emmc_pins: pinmux_emmc_pins { + emmc_pins: emmc-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_GPMC_CSN1, PIN_INPUT, MUX_MODE2) AM33XX_PADCONF(AM335X_PIN_GPMC_CSN2, PIN_INPUT_PULLUP, MUX_MODE2) @@ -447,20 +447,20 @@ >; }; - i2c0_pins: pinmux_i2c0_pins { + i2c0_pins: i2c0-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_I2C0_SDA, PIN_INPUT, MUX_MODE0) AM33XX_PADCONF(AM335X_PIN_I2C0_SCL, PIN_INPUT, MUX_MODE0) >; }; - mmc1_pins: pinmux_mmc1_pins { + mmc1_pins: mmc1-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_SPI0_CS1, PIN_INPUT, MUX_MODE5) >; }; - mmc3_pins: pinmux_mmc3_pins { + mmc3_pins: mmc3-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_GPMC_AD12, PIN_INPUT, MUX_MODE3) AM33XX_PADCONF(AM335X_PIN_GPMC_AD13, PIN_INPUT, MUX_MODE3) @@ -471,7 +471,7 @@ >; }; - uart0_pins: pinmux_uart0_pins { + uart0_pins: uart0-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_UART0_CTSN, PIN_INPUT_PULLDOWN, MUX_MODE0) AM33XX_PADCONF(AM335X_PIN_UART0_RTSN, PIN_OUTPUT, MUX_MODE0) @@ -480,7 +480,7 @@ >; }; - uart1_pins: pinmux_uart1 { + uart1_pins: uart1-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_UART1_CTSN, PIN_INPUT_PULLDOWN, MUX_MODE0) AM33XX_PADCONF(AM335X_PIN_UART1_RTSN, PIN_OUTPUT, MUX_MODE0) @@ -489,21 +489,21 @@ >; }; - uart2_pins: pinmux_uart2_pins { + uart2_pins: uart2-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_SPI0_SCLK, PIN_INPUT, MUX_MODE1) AM33XX_PADCONF(AM335X_PIN_SPI0_D0, PIN_OUTPUT, MUX_MODE1) >; }; - uart4_pins: pinmux_uart4_pins { + uart4_pins: uart4-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_GPMC_WAIT0, PIN_INPUT_PULLUP, MUX_MODE6) AM33XX_PADCONF(AM335X_PIN_GPMC_WPN, PIN_OUTPUT_PULLUP, MUX_MODE6) >; }; - user_leds_s0: user_leds_s0 { + user_leds_s0: user-leds-s0-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_GPMC_AD8, PIN_OUTPUT, MUX_MODE7) AM33XX_PADCONF(AM335X_PIN_GPMC_AD9, PIN_OUTPUT, MUX_MODE7) diff --git a/arch/arm/boot/dts/am335x-sl50.dts b/arch/arm/boot/dts/ti/omap/am335x-sl50.dts similarity index 95% rename from arch/arm/boot/dts/am335x-sl50.dts rename to arch/arm/boot/dts/ti/omap/am335x-sl50.dts index 73b5d1a024bd1d522a6591294b008a7f8a3b6b86..1115c812f6c8be454644fb46bbca1b98c716cf97 100644 --- a/arch/arm/boot/dts/am335x-sl50.dts +++ b/arch/arm/boot/dts/ti/omap/am335x-sl50.dts @@ -213,7 +213,7 @@ pinctrl-names = "default"; pinctrl-0 = <&lwb_pins>; - audio_pins: pinmux_audio_pins { + audio_pins: audio-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_MCASP0_AHCLKX, PIN_INPUT_PULLDOWN, MUX_MODE0) AM33XX_PADCONF(AM335X_PIN_MCASP0_FSX, PIN_INPUT_PULLDOWN, MUX_MODE0) @@ -223,31 +223,31 @@ >; }; - audio_pa_pins: pinmux_audio_pa_pins { + audio_pa_pins: audio-pa-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_MCASP0_ACLKR, PIN_INPUT_PULLDOWN, MUX_MODE7) /* SoundPA_en - mcasp0_aclkr.gpio3_18 */ >; }; - audio_mclk_pins: pinmux_audio_mclk_pins { + audio_mclk_pins: audio-mclk-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_GPMC_A11, PIN_INPUT_PULLDOWN, MUX_MODE7) /* gpmc_a11.gpio1_27 */ >; }; - backlight0_pins: pinmux_backlight0_pins { + backlight0_pins: backlight0-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_GPMC_WEN, PIN_OUTPUT, MUX_MODE7) /* gpmc_wen.gpio2_4 */ >; }; - backlight1_pins: pinmux_backlight1_pins { + backlight1_pins: backlight1-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_GPMC_AD10, PIN_OUTPUT, MUX_MODE7) /* gpmc_ad10.gpio0_26 */ >; }; - lcd_pins: pinmux_lcd_pins { + lcd_pins: lcd-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_LCD_DATA0, PIN_OUTPUT, MUX_MODE0) AM33XX_PADCONF(AM335X_PIN_LCD_DATA1, PIN_OUTPUT, MUX_MODE0) @@ -272,7 +272,7 @@ >; }; - led_pins: pinmux_led_pins { + led_pins: led-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_GPMC_A5, PIN_OUTPUT, MUX_MODE7) /* gpmc_a5.gpio1_21 */ AM33XX_PADCONF(AM335X_PIN_GPMC_A6, PIN_OUTPUT, MUX_MODE7) /* gpmc_a6.gpio1_22 */ @@ -281,42 +281,42 @@ >; }; - uart0_pins: pinmux_uart0_pins { + uart0_pins: uart0-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_UART0_RXD, PIN_INPUT_PULLUP, MUX_MODE0) AM33XX_PADCONF(AM335X_PIN_UART0_TXD, PIN_OUTPUT_PULLDOWN, MUX_MODE0) >; }; - uart1_pins: pinmux_uart1_pins { + uart1_pins: uart1-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_UART1_RXD, PIN_INPUT_PULLUP, MUX_MODE0) AM33XX_PADCONF(AM335X_PIN_UART1_TXD, PIN_OUTPUT_PULLDOWN, MUX_MODE0) >; }; - uart4_pins: pinmux_uart4_pins { + uart4_pins: uart4-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_GPMC_WAIT0, PIN_INPUT_PULLUP, MUX_MODE6) /* gpmc_wait0.uart4_rxd */ AM33XX_PADCONF(AM335X_PIN_GPMC_WPN, PIN_OUTPUT_PULLDOWN, MUX_MODE6) /* gpmc_wpn.uart4_txd */ >; }; - i2c0_pins: pinmux_i2c0_pins { + i2c0_pins: i2c0-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_I2C0_SDA, PIN_INPUT_PULLUP, MUX_MODE0) AM33XX_PADCONF(AM335X_PIN_I2C0_SCL, PIN_INPUT_PULLUP, MUX_MODE0) >; }; - i2c2_pins: pinmux_i2c2_pins { + i2c2_pins: i2c2-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_UART1_CTSN, PIN_INPUT_PULLUP, MUX_MODE3) /* uart1_ctsn.i2c2_sda */ AM33XX_PADCONF(AM335X_PIN_UART1_RTSN, PIN_INPUT_PULLUP, MUX_MODE3) /* uart1_rtsn.i2c2_scl */ >; }; - cpsw_default: cpsw_default { + cpsw_default: cpsw-default-pins { pinctrl-single,pins = < /* Slave 1 */ AM33XX_PADCONF(AM335X_PIN_MII1_RX_ER, PIN_INPUT_PULLUP, MUX_MODE0) @@ -335,7 +335,7 @@ >; }; - cpsw_sleep: cpsw_sleep { + cpsw_sleep: cpsw-sleep-pins { pinctrl-single,pins = < /* Slave 1 reset value */ AM33XX_PADCONF(AM335X_PIN_MII1_RX_ER, PIN_INPUT_PULLDOWN, MUX_MODE7) @@ -354,7 +354,7 @@ >; }; - davinci_mdio_default: davinci_mdio_default { + davinci_mdio_default: davinci-mdio-default-pins { pinctrl-single,pins = < /* MDIO */ AM33XX_PADCONF(AM335X_PIN_MDIO, PIN_INPUT_PULLUP | SLEWCTRL_FAST, MUX_MODE0) @@ -364,7 +364,7 @@ >; }; - davinci_mdio_sleep: davinci_mdio_sleep { + davinci_mdio_sleep: davinci-mdio-sleep-pins { pinctrl-single,pins = < /* MDIO reset value */ AM33XX_PADCONF(AM335X_PIN_MDIO, PIN_INPUT_PULLDOWN, MUX_MODE7) @@ -372,19 +372,19 @@ >; }; - mmc1_pins: pinmux_mmc1_pins { + mmc1_pins: mmc1-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_UART0_RTSN, PIN_INPUT, MUX_MODE7) /* uart0_rtsn.gpio1_9 */ >; }; - emmc_pwrseq_pins: pinmux_emmc_pwrseq_pins { + emmc_pwrseq_pins: emmc-pwrseq-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_GPMC_A4, PIN_OUTPUT_PULLUP, MUX_MODE7) /* gpmc_a4.gpio1_20 */ >; }; - emmc_pins: pinmux_emmc_pins { + emmc_pins: emmc-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_GPMC_CSN1, PIN_INPUT_PULLUP, MUX_MODE2) /* gpmc_csn1.mmc1_clk */ AM33XX_PADCONF(AM335X_PIN_GPMC_CSN2, PIN_INPUT_PULLUP, MUX_MODE2) /* gpmc_csn2.mmc1_cmd */ @@ -399,20 +399,20 @@ >; }; - ehrpwm1_pins: pinmux_ehrpwm1a_pins { + ehrpwm1_pins: ehrpwm1a-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_GPMC_A2, PIN_OUTPUT, MUX_MODE6) /* gpmc_a2.ehrpwm1a */ AM33XX_PADCONF(AM335X_PIN_GPMC_A3, PIN_OUTPUT, MUX_MODE6) /* gpmc_a3.ehrpwm1b */ >; }; - rtc0_irq_pins: pinmux_rtc0_irq_pins { + rtc0_irq_pins: rtc0-irq-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_GPMC_AD9, PIN_INPUT_PULLUP, MUX_MODE7) /* gpmc_ad9.gpio0_23 */ >; }; - spi0_pins: pinmux_spi0_pins { + spi0_pins: spi0-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_SPI0_D0, PIN_INPUT_PULLUP, MUX_MODE0) /* SPI0_MOSI */ AM33XX_PADCONF(AM335X_PIN_SPI0_D1, PIN_INPUT_PULLUP, MUX_MODE0) /* SPI0_MISO */ @@ -422,7 +422,7 @@ >; }; - lwb_pins: pinmux_lwb_pins { + lwb_pins: lwb-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_GPMC_AD12, PIN_INPUT_PULLUP, MUX_MODE7) /* nKbdInt - gpmc_ad12.gpio1_12 */ AM33XX_PADCONF(AM335X_PIN_GPMC_AD13, PIN_INPUT_PULLUP, MUX_MODE7) /* nKbdReset - gpmc_ad13.gpio1_13 */ @@ -597,7 +597,7 @@ }; }; -#include "tps65217.dtsi" +#include "../../tps65217.dtsi" &tps { ti,pmic-shutdown-controller; diff --git a/arch/arm/boot/dts/am335x-wega-rdk.dts b/arch/arm/boot/dts/ti/omap/am335x-wega-rdk.dts similarity index 100% rename from arch/arm/boot/dts/am335x-wega-rdk.dts rename to arch/arm/boot/dts/ti/omap/am335x-wega-rdk.dts diff --git a/arch/arm/boot/dts/am335x-wega.dtsi b/arch/arm/boot/dts/ti/omap/am335x-wega.dtsi similarity index 96% rename from arch/arm/boot/dts/am335x-wega.dtsi rename to arch/arm/boot/dts/ti/omap/am335x-wega.dtsi index 6a103f17585b4c7d04cc0a05d87116ec65cd5215..cb27ff464dbeb4090c049e3566f03d61b094d022 100644 --- a/arch/arm/boot/dts/am335x-wega.dtsi +++ b/arch/arm/boot/dts/ti/omap/am335x-wega.dtsi @@ -49,7 +49,7 @@ /* Audio */ &am33xx_pinmux { - mcasp0_pins: pinmux-mcasp0 { + mcasp0_pins: pinmux-mcasp0-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_MCASP0_AHCLKX, PIN_OUTPUT_PULLDOWN, MUX_MODE0) AM33XX_PADCONF(AM335X_PIN_MCASP0_ACLKX, PIN_INPUT_PULLDOWN, MUX_MODE0) @@ -90,7 +90,7 @@ /* CAN Busses */ &am33xx_pinmux { - dcan1_pins: pinmux-dcan1 { + dcan1_pins: pinmux-dcan1-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_UART0_CTSN, PIN_OUTPUT_PULLUP, MUX_MODE2) /* uart0_ctsn.d_can1_tx */ AM33XX_PADCONF(AM335X_PIN_UART0_RTSN, PIN_INPUT_PULLUP, MUX_MODE2) /* uart0_rtsn.d_can1_rx */ @@ -106,7 +106,7 @@ /* Ethernet */ &am33xx_pinmux { - ethernet1_pins: pinmux-ethernet1 { + ethernet1_pins: pinmux-ethernet1-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_GPMC_A0, PIN_OUTPUT, MUX_MODE1) /* gpmc_a0.mii2_txen */ AM33XX_PADCONF(AM335X_PIN_GPMC_A1, PIN_INPUT_PULLDOWN, MUX_MODE1) /* gpmc_a1.mii2_rxdv */ @@ -146,7 +146,7 @@ /* MMC */ &am33xx_pinmux { - mmc1_pins: pinmux-mmc1 { + mmc1_pins: pinmux-mmc1-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_MMC0_DAT3, PIN_INPUT_PULLUP, MUX_MODE0) AM33XX_PADCONF(AM335X_PIN_MMC0_DAT2, PIN_INPUT_PULLUP, MUX_MODE0) @@ -176,14 +176,14 @@ /* UARTs */ &am33xx_pinmux { - uart0_pins: pinmux-uart0 { + uart0_pins: pinmux-uart0-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_UART0_RXD, PIN_INPUT_PULLUP, MUX_MODE0) AM33XX_PADCONF(AM335X_PIN_UART0_TXD, PIN_OUTPUT_PULLDOWN, MUX_MODE0) >; }; - uart1_pins: pinmux-uart1 { + uart1_pins: pinmux-uart1-pins { pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_UART1_RXD, PIN_INPUT_PULLUP, MUX_MODE0) AM33XX_PADCONF(AM335X_PIN_UART1_TXD, PIN_OUTPUT_PULLDOWN, MUX_MODE0) diff --git a/arch/arm/boot/dts/am33xx-clocks.dtsi b/arch/arm/boot/dts/ti/omap/am33xx-clocks.dtsi similarity index 100% rename from arch/arm/boot/dts/am33xx-clocks.dtsi rename to arch/arm/boot/dts/ti/omap/am33xx-clocks.dtsi diff --git a/arch/arm/boot/dts/am33xx-l4.dtsi b/arch/arm/boot/dts/ti/omap/am33xx-l4.dtsi similarity index 100% rename from arch/arm/boot/dts/am33xx-l4.dtsi rename to arch/arm/boot/dts/ti/omap/am33xx-l4.dtsi diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/ti/omap/am33xx.dtsi similarity index 100% rename from arch/arm/boot/dts/am33xx.dtsi rename to arch/arm/boot/dts/ti/omap/am33xx.dtsi diff --git a/arch/arm/boot/dts/am3517-craneboard.dts b/arch/arm/boot/dts/ti/omap/am3517-craneboard.dts similarity index 98% rename from arch/arm/boot/dts/am3517-craneboard.dts rename to arch/arm/boot/dts/ti/omap/am3517-craneboard.dts index 3642cfc801941d6da2117a2a6ed116b8f4f80db1..d035c888731fc7df9163cc91824b4765d528bfde 100644 --- a/arch/arm/boot/dts/am3517-craneboard.dts +++ b/arch/arm/boot/dts/ti/omap/am3517-craneboard.dts @@ -69,10 +69,10 @@ status = "disabled"; }; -#include "tps65910.dtsi" +#include "../../tps65910.dtsi" &omap3_pmx_core { - tps_pins: pinmux_tps_pins { + tps_pins: tps-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x21e0, PIN_INPUT_PULLUP | MUX_MODE0) /* sys_nirq.sys_nirq */ >; diff --git a/arch/arm/boot/dts/am3517-evm-ui.dtsi b/arch/arm/boot/dts/ti/omap/am3517-evm-ui.dtsi similarity index 98% rename from arch/arm/boot/dts/am3517-evm-ui.dtsi rename to arch/arm/boot/dts/ti/omap/am3517-evm-ui.dtsi index 75ad42179aeebeb9e1b43f39cf6f0719ba2235b7..16b8968d5be8a44a87b9a660c419ccba822e1819 100644 --- a/arch/arm/boot/dts/am3517-evm-ui.dtsi +++ b/arch/arm/boot/dts/ti/omap/am3517-evm-ui.dtsi @@ -197,7 +197,7 @@ }; &omap3_pmx_core { - mcbsp1_pins: pinmux_mcbsp1_pins { + mcbsp1_pins: mcbsp1-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x2190, PIN_OUTPUT | MUX_MODE0) /* mcbsp1_dx.mcbsp1_dx */ OMAP3_CORE1_IOPAD(0x2192, PIN_INPUT | MUX_MODE0) /* mcbsp1_dx.mcbsp1_dr */ @@ -206,7 +206,7 @@ >; }; - mcbsp2_pins: pinmux_mcbsp2_pins { + mcbsp2_pins: mcbsp2-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x213c, PIN_INPUT | MUX_MODE0) /* mcbsp2_fsx.mcbsp2_fsx */ OMAP3_CORE1_IOPAD(0x213e, PIN_INPUT | MUX_MODE0) /* mcbsp2_clkx.mcbsp2_clkx */ diff --git a/arch/arm/boot/dts/am3517-evm.dts b/arch/arm/boot/dts/ti/omap/am3517-evm.dts similarity index 96% rename from arch/arm/boot/dts/am3517-evm.dts rename to arch/arm/boot/dts/ti/omap/am3517-evm.dts index 11618aa501fc516ae65b6cbd9e39d4dd33b7febb..af9df15274bed1f495ca26b9b20ac5f18a1cb727 100644 --- a/arch/arm/boot/dts/am3517-evm.dts +++ b/arch/arm/boot/dts/ti/omap/am3517-evm.dts @@ -242,7 +242,7 @@ &omap3_pmx_core { - ethernet_pins: pinmux_ethernet_pins { + ethernet_pins: ethernet-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x21fe, PIN_INPUT | MUX_MODE0) /* rmii_mdio_data */ OMAP3_CORE1_IOPAD(0x2200, MUX_MODE0) /* rmii_mdio_clk */ @@ -257,28 +257,28 @@ >; }; - i2c2_pins: pinmux_i2c2_pins { + i2c2_pins: i2c2-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x21be, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c2_scl */ OMAP3_CORE1_IOPAD(0x21c0, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c2_sda */ >; }; - i2c3_pins: pinmux_i2c3_pins { + i2c3_pins: i2c3-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x21c2, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c3_scl */ OMAP3_CORE1_IOPAD(0x21c4, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c3_sda */ >; }; - leds_pins: pinmux_leds_pins { + leds_pins: leds-pins { pinctrl-single,pins = < OMAP3_WKUP_IOPAD(0x2a24, PIN_OUTPUT_PULLUP | MUX_MODE4) /* jtag_emu0.gpio_11 */ OMAP3_WKUP_IOPAD(0x2a26, PIN_OUTPUT_PULLUP | MUX_MODE4) /* jtag_emu1.gpio_31 */ >; }; - mmc1_pins: pinmux_mmc1_pins { + mmc1_pins: mmc1-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x2144, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc1_clk.sdmmc1_clk */ OMAP3_CORE1_IOPAD(0x2146, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc1_cmd.sdmmc1_cmd */ @@ -291,19 +291,19 @@ >; }; - pwm_pins: pinmux_pwm_pins { + pwm_pins: pwm-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x21dc, PIN_OUTPUT | MUX_MODE1) /* mcspi2_cs0.gpt11_pwm */ >; }; - backlight_pins: pinmux_backlight_pins { + backlight_pins: backlight-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x21de, PIN_OUTPUT | MUX_MODE4) /* mcspi2_cs1.gpio_182 */ >; }; - dss_dpi_pins: pinmux_dss_dpi_pins { + dss_dpi_pins: dss-dpi-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x21d2, PIN_OUTPUT | MUX_MODE4) /* mcspi1_cs2.gpio_176 */ OMAP3_CORE1_IOPAD(0x20d4, PIN_OUTPUT | MUX_MODE0) /* dss_pclk.dss_pclk */ @@ -329,7 +329,7 @@ >; }; - hsusb1_rst_pins: pinmux_hsusb1_rst_pins { + hsusb1_rst_pins: hsusb1-rst-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x20ba, PIN_OUTPUT | MUX_MODE4) /* gpmc_ncs6.gpio_57 */ >; @@ -338,7 +338,7 @@ &omap3_pmx_core2 { - hsusb1_pins: pinmux_hsusb1_pins { + hsusb1_pins: hsusb1-pins { pinctrl-single,pins = < OMAP3430_CORE2_IOPAD(0x25d8, PIN_OUTPUT | MUX_MODE3) /* etk_clk.hsusb1_stp */ OMAP3430_CORE2_IOPAD(0x25da, PIN_OUTPUT | MUX_MODE3) /* etk_ctl.hsusb1_clk */ diff --git a/arch/arm/boot/dts/am3517-som.dtsi b/arch/arm/boot/dts/ti/omap/am3517-som.dtsi similarity index 96% rename from arch/arm/boot/dts/am3517-som.dtsi rename to arch/arm/boot/dts/ti/omap/am3517-som.dtsi index f7b680f6c48adba4d8e6210d4be3b460e7426998..bd0a6c95afa16dda1752a24e59612c2a1961bb16 100644 --- a/arch/arm/boot/dts/am3517-som.dtsi +++ b/arch/arm/boot/dts/ti/omap/am3517-som.dtsi @@ -181,20 +181,20 @@ &omap3_pmx_core { - i2c1_pins: pinmux_i2c1_pins { + i2c1_pins: i2c1-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x21ba, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c1_scl */ OMAP3_CORE1_IOPAD(0x21bc, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c1_sda */ >; }; - wl12xx_buffer_pins: pinmux_wl12xx_buffer_pins { + wl12xx_buffer_pins: wl12xx-buffer-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x2156, PIN_OUTPUT | MUX_MODE4) /* mmc1_dat7.gpio_129 */ >; }; - mmc2_pins: pinmux_mmc2_pins { + mmc2_pins: mmc2-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x2158, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc2_clk.mmc2_clk */ OMAP3_CORE1_IOPAD(0x215a, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc2_cmd.mmc2_cmd */ @@ -210,19 +210,19 @@ >; }; - rtc_pins: pinmux_rtc_pins { + rtc_pins: rtc-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x20b6, PIN_INPUT_PULLUP | MUX_MODE4) /* gpmc_ncs4.gpio_55 */ >; }; - tsc2004_pins: pinmux_tsc2004_pins { + tsc2004_pins: tsc2004-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x20d2, PIN_INPUT | MUX_MODE4) /* gpmc_wait3.gpio_65 */ >; }; - uart2_pins: pinmux_uart2_pins { + uart2_pins: uart2-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x2174, PIN_INPUT_PULLUP | MUX_MODE0) /* uart2_cts */ OMAP3_CORE1_IOPAD(0x2176, PIN_OUTPUT_PULLUP | MUX_MODE0) /* uart2_rts */ @@ -235,7 +235,7 @@ &omap3_pmx_wkup { - wl12xx_wkup_pins: pinmux_wl12xx_wkup_pins { + wl12xx_wkup_pins: wl12xx-wkup-pins { pinctrl-single,pins = < OMAP3_WKUP_IOPAD(0x2a0c, PIN_OUTPUT | MUX_MODE4) /* sys_boot1.gpio_3 */ >; diff --git a/arch/arm/boot/dts/am3517.dtsi b/arch/arm/boot/dts/ti/omap/am3517.dtsi similarity index 100% rename from arch/arm/boot/dts/am3517.dtsi rename to arch/arm/boot/dts/ti/omap/am3517.dtsi diff --git a/arch/arm/boot/dts/am3517_mt_ventoux.dts b/arch/arm/boot/dts/ti/omap/am3517_mt_ventoux.dts similarity index 100% rename from arch/arm/boot/dts/am3517_mt_ventoux.dts rename to arch/arm/boot/dts/ti/omap/am3517_mt_ventoux.dts diff --git a/arch/arm/boot/dts/am35xx-clocks.dtsi b/arch/arm/boot/dts/ti/omap/am35xx-clocks.dtsi similarity index 100% rename from arch/arm/boot/dts/am35xx-clocks.dtsi rename to arch/arm/boot/dts/ti/omap/am35xx-clocks.dtsi diff --git a/arch/arm/boot/dts/am3703.dtsi b/arch/arm/boot/dts/ti/omap/am3703.dtsi similarity index 100% rename from arch/arm/boot/dts/am3703.dtsi rename to arch/arm/boot/dts/ti/omap/am3703.dtsi diff --git a/arch/arm/boot/dts/am3715.dtsi b/arch/arm/boot/dts/ti/omap/am3715.dtsi similarity index 100% rename from arch/arm/boot/dts/am3715.dtsi rename to arch/arm/boot/dts/ti/omap/am3715.dtsi diff --git a/arch/arm/boot/dts/am3874-iceboard.dts b/arch/arm/boot/dts/ti/omap/am3874-iceboard.dts similarity index 98% rename from arch/arm/boot/dts/am3874-iceboard.dts rename to arch/arm/boot/dts/ti/omap/am3874-iceboard.dts index 791478e81c5ad5b30239a1dc6905dbee10744c9d..ac082e83a9a2045cdee565c5687ae2e2843f5b37 100644 --- a/arch/arm/boot/dts/am3874-iceboard.dts +++ b/arch/arm/boot/dts/ti/omap/am3874-iceboard.dts @@ -285,7 +285,7 @@ }; &pincntl { - mmc2_pins: pinmux_mmc2_pins { + mmc2_pins: mmc2-pins { pinctrl-single,pins = < DM814X_IOPAD(0x0800, PIN_INPUT | 0x1) /* SD1_CLK */ DM814X_IOPAD(0x0804, PIN_INPUT_PULLUP | 0x1) /* SD1_CMD */ @@ -299,19 +299,19 @@ >; }; - usb0_pins: pinmux_usb0_pins { + usb0_pins: usb0-pins { pinctrl-single,pins = < DM814X_IOPAD(0x0c34, PIN_OUTPUT | 0x1) /* USB0_DRVVBUS */ >; }; - usb1_pins: pinmux_usb1_pins { + usb1_pins: usb1-pins { pinctrl-single,pins = < DM814X_IOPAD(0x0834, PIN_OUTPUT | 0x80) /* USB1_DRVVBUS */ >; }; - gpio1_pins: pinmux_gpio1_pins { + gpio1_pins: gpio1-pins { pinctrl-single,pins = < DM814X_IOPAD(0x081c, PIN_OUTPUT | 0x80) /* PROGRAM_B */ DM814X_IOPAD(0x0820, PIN_INPUT | 0x80) /* INIT_B */ @@ -336,7 +336,7 @@ >; }; - gpio2_pins: pinmux_gpio2_pins { + gpio2_pins: gpio2-pins { pinctrl-single,pins = < DM814X_IOPAD(0x090c, PIN_INPUT_PULLUP | 0x80) /* PHY A IRQ */ DM814X_IOPAD(0x0910, PIN_INPUT_PULLUP | 0x80) /* PHY A RESET */ @@ -349,7 +349,7 @@ >; }; - gpio4_pins: pinmux_gpio4_pins { + gpio4_pins: gpio4-pins { pinctrl-single,pins = < /* The PLL doesn't react well to the SPI controller reset, so * we force the CS lines to pull up as GPIOs until we're ready. @@ -364,14 +364,14 @@ >; }; - spi2_pins: pinmux_spi2_pins { + spi2_pins: spi2-pins { pinctrl-single,pins = < DM814X_IOPAD(0x0950, PIN_INPUT_PULLUP | 0x80) /* PLL SPI CS1 as GPIO */ DM814X_IOPAD(0x0818, PIN_INPUT_PULLUP | 0x80) /* PLL SPI CS2 as GPIO */ >; }; - spi4_pins: pinmux_spi4_pins { + spi4_pins: spi4-pins { pinctrl-single,pins = < DM814X_IOPAD(0x0a7c, 0x20) DM814X_IOPAD(0x0b74, 0x20) diff --git a/arch/arm/boot/dts/am4372.dtsi b/arch/arm/boot/dts/ti/omap/am4372.dtsi similarity index 100% rename from arch/arm/boot/dts/am4372.dtsi rename to arch/arm/boot/dts/ti/omap/am4372.dtsi diff --git a/arch/arm/boot/dts/am437x-cm-t43.dts b/arch/arm/boot/dts/ti/omap/am437x-cm-t43.dts similarity index 97% rename from arch/arm/boot/dts/am437x-cm-t43.dts rename to arch/arm/boot/dts/ti/omap/am437x-cm-t43.dts index 0861e868b75ab278432f3d476160862e6bf0d90d..9ec75d03eaff1f24e36369e19897c926295025dc 100644 --- a/arch/arm/boot/dts/am437x-cm-t43.dts +++ b/arch/arm/boot/dts/ti/omap/am437x-cm-t43.dts @@ -38,20 +38,20 @@ pinctrl-names = "default"; pinctrl-0 = <&cm_t43_led_pins>; - cm_t43_led_pins: cm_t43_led_pins { + cm_t43_led_pins: cm-t43-led-pins { pinctrl-single,pins = < AM4372_IOPAD(0xa78, MUX_MODE7) >; }; - i2c0_pins: i2c0_pins { + i2c0_pins: i2c0-pins { pinctrl-single,pins = < AM4372_IOPAD(0x988, PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0) /* i2c0_sda.i2c0_sda */ AM4372_IOPAD(0x98c, PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0) /* i2c0_scl.i2c0_scl */ >; }; - emmc_pins: emmc_pins { + emmc_pins: emmc-pins { pinctrl-single,pins = < AM4372_IOPAD(0x820, PIN_INPUT_PULLUP | MUX_MODE2) /* gpmc_ad8.mmc1_dat0 */ AM4372_IOPAD(0x824, PIN_INPUT_PULLUP | MUX_MODE2) /* gpmc_ad9.mmc1_dat1 */ @@ -66,7 +66,7 @@ >; }; - spi0_pins: pinmux_spi0_pins { + spi0_pins: spi0-pins { pinctrl-single,pins = < AM4372_IOPAD(0x950, PIN_INPUT | MUX_MODE0) /* spi0_sclk.spi0_sclk */ AM4372_IOPAD(0x954, PIN_INPUT | MUX_MODE0) /* spi0_d0.spi0_d0 */ @@ -75,7 +75,7 @@ >; }; - nand_flash_x8: nand_flash_x8 { + nand_flash_x8: nand-flash-x8-pins { pinctrl-single,pins = < AM4372_IOPAD(0x800, PIN_INPUT | PULL_DISABLE | MUX_MODE0) AM4372_IOPAD(0x804, PIN_INPUT | PULL_DISABLE | MUX_MODE0) @@ -95,7 +95,7 @@ >; }; - cpsw_default: cpsw_default { + cpsw_default: cpsw-default-pins { pinctrl-single,pins = < /* Slave 1 */ AM4372_IOPAD(0x914, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txen.rgmii1_txen */ @@ -128,7 +128,7 @@ >; }; - davinci_mdio_default: davinci_mdio_default { + davinci_mdio_default: davinci-mdio-default-pins { pinctrl-single,pins = < /* MDIO */ AM4372_IOPAD(0x948, PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0) /* mdio_data.mdio_data */ diff --git a/arch/arm/boot/dts/am437x-gp-evm.dts b/arch/arm/boot/dts/ti/omap/am437x-gp-evm.dts similarity index 95% rename from arch/arm/boot/dts/am437x-gp-evm.dts rename to arch/arm/boot/dts/ti/omap/am437x-gp-evm.dts index 46d5361fe876440073b8e0d31dad4dc1e8bd4017..f7aad0323d1913b3e56252a946594e69a1059789 100644 --- a/arch/arm/boot/dts/am437x-gp-evm.dts +++ b/arch/arm/boot/dts/ti/omap/am437x-gp-evm.dts @@ -153,45 +153,45 @@ pinctrl-0 = <&wlan_pins_default &ddr3_vtt_toggle_default &unused_pins &debugss_pins>; pinctrl-1 = <&wlan_pins_sleep>; - ddr3_vtt_toggle_default: ddr_vtt_toggle_default { + ddr3_vtt_toggle_default: ddr-vtt-toggle-default-pins { pinctrl-single,pins = < 0x25C (DS0_PULL_UP_DOWN_EN | PIN_OUTPUT_PULLUP | DS0_FORCE_OFF_MODE | MUX_MODE7) /* spi0_cs0.gpio5_7 */ >; }; - i2c0_pins: i2c0_pins { + i2c0_pins: i2c0-pins { pinctrl-single,pins = < AM4372_IOPAD(0x988, PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0) /* i2c0_sda.i2c0_sda */ AM4372_IOPAD(0x98c, PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0) /* i2c0_scl.i2c0_scl */ >; }; - i2c1_pins: i2c1_pins { + i2c1_pins: i2c1-pins { pinctrl-single,pins = < AM4372_IOPAD(0x95c, PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE2) /* spi0_cs0.i2c1_scl */ AM4372_IOPAD(0x958, PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE2) /* spi0_d1.i2c1_sda */ >; }; - mmc1_pins: pinmux_mmc1_pins { + mmc1_pins: mmc1-pins { pinctrl-single,pins = < AM4372_IOPAD(0x960, PIN_INPUT | MUX_MODE7) /* spi0_cs1.gpio0_6 */ >; }; - ecap0_pins: backlight_pins { + ecap0_pins: backlight-pins { pinctrl-single,pins = < AM4372_IOPAD(0x964, MUX_MODE0) /* eCAP0_in_PWM0_out.eCAP0_in_PWM0_out MODE0 */ >; }; - pixcir_ts_pins: pixcir_ts_pins { + pixcir_ts_pins: pixcir-ts-pins { pinctrl-single,pins = < AM4372_IOPAD(0xa64, PIN_INPUT_PULLUP | MUX_MODE7) /* spi2_d0.gpio3_22 */ >; }; - cpsw_default: cpsw_default { + cpsw_default: cpsw-default-pins { pinctrl-single,pins = < /* Slave 1 */ AM4372_IOPAD(0x914, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txen.rgmii1_txen */ @@ -209,7 +209,7 @@ >; }; - cpsw_sleep: cpsw_sleep { + cpsw_sleep: cpsw-sleep-pins { pinctrl-single,pins = < /* Slave 1 reset value */ AM4372_IOPAD(0x914, PIN_INPUT_PULLDOWN | MUX_MODE7) @@ -227,7 +227,7 @@ >; }; - davinci_mdio_default: davinci_mdio_default { + davinci_mdio_default: davinci-mdio-default-pins { pinctrl-single,pins = < /* MDIO */ AM4372_IOPAD(0x948, PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0) /* mdio_data.mdio_data */ @@ -235,7 +235,7 @@ >; }; - davinci_mdio_sleep: davinci_mdio_sleep { + davinci_mdio_sleep: davinci-mdio-sleep-pins { pinctrl-single,pins = < /* MDIO reset value */ AM4372_IOPAD(0x948, PIN_INPUT_PULLDOWN | MUX_MODE7) @@ -243,7 +243,7 @@ >; }; - nand_flash_x8: nand_flash_x8 { + nand_flash_x8: nand-flash-x8-pins { pinctrl-single,pins = < AM4372_IOPAD(0x800, PIN_INPUT | MUX_MODE0) /* gpmc_ad0.gpmc_ad0 */ AM4372_IOPAD(0x804, PIN_INPUT | MUX_MODE0) /* gpmc_ad1.gpmc_ad1 */ @@ -263,7 +263,7 @@ >; }; - dss_pins: dss_pins { + dss_pins: dss-pins { pinctrl-single,pins = < AM4372_IOPAD(0x820, PIN_OUTPUT_PULLUP | MUX_MODE1) /*gpmc ad 8 -> DSS DATA 23 */ AM4372_IOPAD(0x824, PIN_OUTPUT_PULLUP | MUX_MODE1) @@ -297,42 +297,42 @@ >; }; - display_mux_pins: display_mux_pins { + display_mux_pins: display-mux-pins { pinctrl-single,pins = < /* GPIO 5_8 to select LCD / HDMI */ AM4372_IOPAD(0xa38, PIN_OUTPUT_PULLUP | MUX_MODE7) >; }; - dcan0_default: dcan0_default_pins { + dcan0_default: dcan0-default-pins { pinctrl-single,pins = < AM4372_IOPAD(0x978, PIN_OUTPUT | MUX_MODE2) /* uart1_ctsn.d_can0_tx */ AM4372_IOPAD(0x97c, PIN_INPUT_PULLUP | MUX_MODE2) /* uart1_rtsn.d_can0_rx */ >; }; - dcan0_sleep: dcan0_sleep_pins { + dcan0_sleep: dcan0-sleep-pins { pinctrl-single,pins = < AM4372_IOPAD(0x978, PIN_INPUT_PULLUP | MUX_MODE7) /* uart1_ctsn.gpio0_12 */ AM4372_IOPAD(0x97c, PIN_INPUT_PULLUP | MUX_MODE7) /* uart1_rtsn.gpio0_13 */ >; }; - dcan1_default: dcan1_default_pins { + dcan1_default: dcan1-default-pins { pinctrl-single,pins = < AM4372_IOPAD(0x980, PIN_OUTPUT | MUX_MODE2) /* uart1_rxd.d_can1_tx */ AM4372_IOPAD(0x984, PIN_INPUT_PULLUP | MUX_MODE2) /* uart1_txd.d_can1_rx */ >; }; - dcan1_sleep: dcan1_sleep_pins { + dcan1_sleep: dcan1-sleep-pins { pinctrl-single,pins = < AM4372_IOPAD(0x980, PIN_INPUT_PULLUP | MUX_MODE7) /* uart1_rxd.gpio0_14 */ AM4372_IOPAD(0x984, PIN_INPUT_PULLUP | MUX_MODE7) /* uart1_txd.gpio0_15 */ >; }; - vpfe0_pins_default: vpfe0_pins_default { + vpfe0_pins_default: vpfe0-default-pins { pinctrl-single,pins = < AM4372_IOPAD(0x9b0, PIN_INPUT_PULLUP | MUX_MODE0) /* cam0_hd mode 0*/ AM4372_IOPAD(0x9b4, PIN_INPUT_PULLUP | MUX_MODE0) /* cam0_vd mode 0*/ @@ -350,7 +350,7 @@ >; }; - vpfe0_pins_sleep: vpfe0_pins_sleep { + vpfe0_pins_sleep: vpfe0-sleep-pins { pinctrl-single,pins = < AM4372_IOPAD(0x9b0, DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) /* cam0_hd mode 0*/ AM4372_IOPAD(0x9b4, DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) /* cam0_vd mode 0*/ @@ -368,7 +368,7 @@ >; }; - vpfe1_pins_default: vpfe1_pins_default { + vpfe1_pins_default: vpfe1-default-pins { pinctrl-single,pins = < AM4372_IOPAD(0x9cc, PIN_INPUT_PULLUP | MUX_MODE0) /* cam1_data9 mode 0*/ AM4372_IOPAD(0x9d0, PIN_INPUT_PULLUP | MUX_MODE0) /* cam1_data8 mode 0*/ @@ -386,7 +386,7 @@ >; }; - vpfe1_pins_sleep: vpfe1_pins_sleep { + vpfe1_pins_sleep: vpfe1-sleep-pins { pinctrl-single,pins = < AM4372_IOPAD(0x9cc, DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) /* cam1_data9 mode 0*/ AM4372_IOPAD(0x9d0, DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) /* cam1_data8 mode 0*/ @@ -404,7 +404,7 @@ >; }; - mmc3_pins_default: pinmux_mmc3_pins_default { + mmc3_pins_default: mmc3-default-pins { pinctrl-single,pins = < AM4372_IOPAD(0x88c, PIN_INPUT_PULLUP | MUX_MODE3) /* gpmc_clk.mmc2_clk */ AM4372_IOPAD(0x888, PIN_INPUT_PULLUP | MUX_MODE3) /* gpmc_csn3.mmc2_cmd */ @@ -415,7 +415,7 @@ >; }; - mmc3_pins_sleep: pinmux_mmc3_pins_sleep { + mmc3_pins_sleep: mmc3-sleep-pins { pinctrl-single,pins = < AM4372_IOPAD(0x88c, PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_clk.mmc2_clk */ AM4372_IOPAD(0x888, PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_csn3.mmc2_cmd */ @@ -426,7 +426,7 @@ >; }; - wlan_pins_default: pinmux_wlan_pins_default { + wlan_pins_default: wlan-default-pins { pinctrl-single,pins = < AM4372_IOPAD(0x850, PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_a4.gpio1_20 WL_EN */ AM4372_IOPAD(0x85c, PIN_INPUT | WAKEUP_ENABLE | MUX_MODE7) /* gpmc_a7.gpio1_23 WL_IRQ*/ @@ -434,7 +434,7 @@ >; }; - wlan_pins_sleep: pinmux_wlan_pins_sleep { + wlan_pins_sleep: wlan-sleep-pins { pinctrl-single,pins = < AM4372_IOPAD(0x850, PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_a4.gpio1_20 WL_EN */ AM4372_IOPAD(0x85c, PIN_INPUT | WAKEUP_ENABLE | MUX_MODE7) /* gpmc_a7.gpio1_23 WL_IRQ*/ @@ -442,7 +442,7 @@ >; }; - uart3_pins: uart3_pins { + uart3_pins: uart3-pins { pinctrl-single,pins = < AM4372_IOPAD(0xa28, PIN_INPUT | MUX_MODE0) /* uart3_rxd.uart3_rxd */ AM4372_IOPAD(0xa2c, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* uart3_txd.uart3_txd */ @@ -451,7 +451,7 @@ >; }; - mcasp1_pins: mcasp1_pins { + mcasp1_pins: mcasp1-pins { pinctrl-single,pins = < AM4372_IOPAD(0x908, PIN_OUTPUT_PULLDOWN | MUX_MODE4) /* mii1_col.mcasp1_axr2 */ AM4372_IOPAD(0x90c, PIN_INPUT_PULLDOWN | MUX_MODE4) /* mii1_crs.mcasp1_aclkx */ @@ -460,7 +460,7 @@ >; }; - mcasp1_sleep_pins: mcasp1_sleep_pins { + mcasp1_sleep_pins: mcasp1-sleep-pins { pinctrl-single,pins = < AM4372_IOPAD(0x908, PIN_INPUT_PULLDOWN | MUX_MODE7) AM4372_IOPAD(0x90c, PIN_INPUT_PULLDOWN | MUX_MODE7) @@ -469,13 +469,13 @@ >; }; - gpio0_pins: gpio0_pins { + gpio0_pins: gpio0-pins { pinctrl-single,pins = < AM4372_IOPAD(0xa6c, PIN_OUTPUT | MUX_MODE9) /* spi2_cs0.gpio0_23 SEL_eMMCorNANDn */ >; }; - emmc_pins_default: emmc_pins_default { + emmc_pins_default: emmc-default-pins { pinctrl-single,pins = < AM4372_IOPAD(0x800, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad0.mmc1_dat0 */ AM4372_IOPAD(0x804, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad1.mmc1_dat1 */ @@ -490,7 +490,7 @@ >; }; - emmc_pins_sleep: emmc_pins_sleep { + emmc_pins_sleep: emmc-sleep-pins { pinctrl-single,pins = < AM4372_IOPAD(0x800, PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_ad0.gpio1_0 */ AM4372_IOPAD(0x804, PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_ad1.gpio1_1 */ @@ -505,19 +505,19 @@ >; }; - beeper_pins_default: beeper_pins_default { + beeper_pins_default: beeper-default-pins { pinctrl-single,pins = < AM4372_IOPAD(0x9e0, PIN_OUTPUT_PULLUP | MUX_MODE7) /* cam1_field.gpio4_12 */ >; }; - beeper_pins_sleep: beeper_pins_sleep { + beeper_pins_sleep: beeper-sleep-pins { pinctrl-single,pins = < AM4372_IOPAD(0x9e0, PIN_INPUT_PULLDOWN | MUX_MODE7) /* cam1_field.gpio4_12 */ >; }; - unused_pins: unused_pins { + unused_pins: unused-pins { pinctrl-single,pins = < AM4372_IOPAD(0x854, PIN_INPUT_PULLDOWN | MUX_MODE7) AM4372_IOPAD(0x858, PIN_INPUT_PULLDOWN | MUX_MODE7) @@ -566,7 +566,7 @@ >; }; - debugss_pins: pinmux_debugss_pins { + debugss_pins: debugss-pins { pinctrl-single,pins = < AM4372_IOPAD(0xa90, PIN_INPUT_PULLDOWN) AM4372_IOPAD(0xa94, PIN_INPUT_PULLDOWN) @@ -578,7 +578,7 @@ >; }; - uart0_pins_default: uart0_pins_default { + uart0_pins_default: uart0-default-pins { pinctrl-single,pins = < AM4372_IOPAD(0x968, DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE0) /* uart0_ctsn.uart0_ctsn */ AM4372_IOPAD(0x96C, DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE0) /* uart0_rtsn.uart0_rtsn */ @@ -587,7 +587,7 @@ >; }; - uart0_pins_sleep: uart0_pins_sleep { + uart0_pins_sleep: uart0-sleep-pins { pinctrl-single,pins = < AM4372_IOPAD(0x968, DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) /* uart0_ctsn.uart0_ctsn */ AM4372_IOPAD(0x96C, DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) /* uart0_rtsn.uart0_rtsn */ @@ -596,7 +596,7 @@ >; }; - matrix_keypad_default: matrix_keypad_default { + matrix_keypad_default: matrix-keypad-default-pins { pinctrl-single,pins = < AM4372_IOPAD(0x9a4, PIN_OUTPUT | MUX_MODE7) AM4372_IOPAD(0x9a8, PIN_OUTPUT | MUX_MODE7) @@ -605,7 +605,7 @@ >; }; - matrix_keypad_sleep: matrix_keypad_sleep { + matrix_keypad_sleep: matrix-keypad-sleep-pins { pinctrl-single,pins = < AM4372_IOPAD(0x9a4, PULL_UP | MUX_MODE7) AM4372_IOPAD(0x9a8, PULL_UP | MUX_MODE7) diff --git a/arch/arm/boot/dts/am437x-idk-evm.dts b/arch/arm/boot/dts/ti/omap/am437x-idk-evm.dts similarity index 95% rename from arch/arm/boot/dts/am437x-idk-evm.dts rename to arch/arm/boot/dts/ti/omap/am437x-idk-evm.dts index e46cf2a9d075c4b3a14c5f0b49b7624327611744..863552393c07a9884a8124c59805c062de46c2ae 100644 --- a/arch/arm/boot/dts/am437x-idk-evm.dts +++ b/arch/arm/boot/dts/ti/omap/am437x-idk-evm.dts @@ -171,41 +171,41 @@ }; &am43xx_pinmux { - gpio_keys_pins_default: gpio_keys_pins_default { + gpio_keys_pins_default: gpio-keys-default-pins { pinctrl-single,pins = < AM4372_IOPAD(0x9b8, PIN_INPUT | MUX_MODE7) /* cam0_field.gpio4_2 */ >; }; - i2c0_pins_default: i2c0_pins_default { + i2c0_pins_default: i2c0-default-pins { pinctrl-single,pins = < AM4372_IOPAD(0x988, PIN_INPUT | SLEWCTRL_FAST | MUX_MODE0) /* i2c0_sda.i2c0_sda */ AM4372_IOPAD(0x98c, PIN_INPUT | SLEWCTRL_FAST | MUX_MODE0) /* i2c0_scl.i2c0_scl */ >; }; - i2c0_pins_sleep: i2c0_pins_sleep { + i2c0_pins_sleep: i2c0-sleep-pins { pinctrl-single,pins = < AM4372_IOPAD(0x988, PIN_INPUT_PULLDOWN | MUX_MODE7) AM4372_IOPAD(0x98c, PIN_INPUT_PULLDOWN | MUX_MODE7) >; }; - i2c2_pins_default: i2c2_pins_default { + i2c2_pins_default: i2c2-default-pins { pinctrl-single,pins = < AM4372_IOPAD(0x9e8, PIN_INPUT | SLEWCTRL_FAST | MUX_MODE3) /* cam1_data1.i2c2_scl */ AM4372_IOPAD(0x9ec, PIN_INPUT | SLEWCTRL_FAST | MUX_MODE3) /* cam1_data0.i2c2_sda */ >; }; - i2c2_pins_sleep: i2c2_pins_sleep { + i2c2_pins_sleep: i2c2-sleep-pins { pinctrl-single,pins = < AM4372_IOPAD(0x9e8, PIN_INPUT_PULLDOWN | MUX_MODE7) AM4372_IOPAD(0x9ec, PIN_INPUT_PULLDOWN | MUX_MODE7) >; }; - mmc1_pins_default: pinmux_mmc1_pins_default { + mmc1_pins_default: mmc1-default-pins { pinctrl-single,pins = < AM4372_IOPAD(0x900, PIN_INPUT | MUX_MODE0) /* mmc0_clk.mmc0_clk */ AM4372_IOPAD(0x904, PIN_INPUT | MUX_MODE0) /* mmc0_cmd.mmc0_cmd */ @@ -217,7 +217,7 @@ >; }; - mmc1_pins_sleep: pinmux_mmc1_pins_sleep { + mmc1_pins_sleep: mmc1-sleep-pins { pinctrl-single,pins = < AM4372_IOPAD(0x900, PIN_INPUT_PULLDOWN | MUX_MODE7) AM4372_IOPAD(0x904, PIN_INPUT_PULLDOWN | MUX_MODE7) @@ -229,7 +229,7 @@ >; }; - spi1_pins_default: spi1_pins_default { + spi1_pins_default: spi1-default-pins { pinctrl-single,pins = < AM4372_IOPAD(0x908, PIN_INPUT | MUX_MODE2) /* mii1_col.spi1_sclk */ AM4372_IOPAD(0x910, PIN_INPUT | MUX_MODE2) /* mii1_rx_er.spi1_d1 */ @@ -238,7 +238,7 @@ >; }; - spi1_pins_sleep: spi1_pins_sleep { + spi1_pins_sleep: spi1-sleep-pins { pinctrl-single,pins = < AM4372_IOPAD(0x908, PIN_INPUT_PULLDOWN | MUX_MODE7) AM4372_IOPAD(0x910, PIN_INPUT_PULLDOWN | MUX_MODE7) @@ -247,13 +247,13 @@ >; }; - ecap0_pins_default: backlight_pins_default { + ecap0_pins_default: backlight-default-pins { pinctrl-single,pins = < AM4372_IOPAD(0x964, PIN_OUTPUT | MUX_MODE0) /* ecap0_in_pwm0_out.ecap0_in_pwm0_out */ >; }; - cpsw_default: cpsw_default { + cpsw_default: cpsw-default-pins { pinctrl-single,pins = < AM4372_IOPAD(0x92c, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txclk.rgmii1_tclk */ AM4372_IOPAD(0x914, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txen.rgmii1_tctl */ @@ -270,7 +270,7 @@ >; }; - cpsw_sleep: cpsw_sleep { + cpsw_sleep: cpsw-sleep-pins { pinctrl-single,pins = < AM4372_IOPAD(0x92c, PIN_INPUT_PULLDOWN | MUX_MODE7) AM4372_IOPAD(0x914, PIN_INPUT_PULLDOWN | MUX_MODE7) @@ -287,7 +287,7 @@ >; }; - davinci_mdio_default: davinci_mdio_default { + davinci_mdio_default: davinci-mdio-default-pins { pinctrl-single,pins = < /* MDIO */ AM4372_IOPAD(0x948, PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0) /* mdio_data.mdio_data */ @@ -295,7 +295,7 @@ >; }; - davinci_mdio_sleep: davinci_mdio_sleep { + davinci_mdio_sleep: davinci-mdio-sleep-pins { pinctrl-single,pins = < /* MDIO reset value */ AM4372_IOPAD(0x948, PIN_INPUT_PULLDOWN | MUX_MODE7) @@ -303,7 +303,7 @@ >; }; - qspi_pins_default: qspi_pins_default { + qspi_pins_default: qspi-default-pins { pinctrl-single,pins = < AM4372_IOPAD(0x87c, PIN_OUTPUT_PULLUP | MUX_MODE3) /* gpmc_csn0.qspi_csn */ AM4372_IOPAD(0x888, PIN_OUTPUT | MUX_MODE2) /* gpmc_csn3.qspi_clk */ @@ -314,7 +314,7 @@ >; }; - qspi_pins_sleep: qspi_pins_sleep{ + qspi_pins_sleep: qspi-sleep-pins { pinctrl-single,pins = < AM4372_IOPAD(0x87c, PIN_INPUT_PULLDOWN | MUX_MODE7) AM4372_IOPAD(0x888, PIN_INPUT_PULLDOWN | MUX_MODE7) diff --git a/arch/arm/boot/dts/am437x-l4.dtsi b/arch/arm/boot/dts/ti/omap/am437x-l4.dtsi similarity index 100% rename from arch/arm/boot/dts/am437x-l4.dtsi rename to arch/arm/boot/dts/ti/omap/am437x-l4.dtsi diff --git a/arch/arm/boot/dts/am437x-sbc-t43.dts b/arch/arm/boot/dts/ti/omap/am437x-sbc-t43.dts similarity index 95% rename from arch/arm/boot/dts/am437x-sbc-t43.dts rename to arch/arm/boot/dts/ti/omap/am437x-sbc-t43.dts index 8ea3780f939ded427b492e27ed25c1372681965e..34a5407bee151f9322f6962e8386ded10911404f 100644 --- a/arch/arm/boot/dts/am437x-sbc-t43.dts +++ b/arch/arm/boot/dts/ti/omap/am437x-sbc-t43.dts @@ -16,7 +16,7 @@ }; &am43xx_pinmux { - mmc1_pins: pinmux_mmc1_pins { + mmc1_pins: mmc1-pins { pinctrl-single,pins = < AM4372_IOPAD(0x900, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc0_clk.mmc0_clk */ AM4372_IOPAD(0x904, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc0_cmd.mmc0_cmd */ @@ -29,7 +29,7 @@ >; }; - dss_pinctrl_default: dss_pinctrl_default { + dss_pinctrl_default: dss-pinctrl-default-pins { pinctrl-single,pins = < AM4372_IOPAD(0x9b0, PIN_OUTPUT_PULLUP | MUX_MODE2) /* cam0 hd -> DSS DATA 23 */ AM4372_IOPAD(0x9b4, PIN_OUTPUT_PULLUP | MUX_MODE2) @@ -64,7 +64,7 @@ >; }; - uart0_pins_default: uart0_pins_default { + uart0_pins_default: uart0-default-pins { pinctrl-single,pins = < AM4372_IOPAD(0x968, DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE0) AM4372_IOPAD(0x96C, DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE0) @@ -73,27 +73,27 @@ >; }; - i2c1_pins: i2c1_pins { + i2c1_pins: i2c1-pins { pinctrl-single,pins = < AM4372_IOPAD(0xa6c, PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE1) /* spi2_cs0.i2c1_sda */ AM4372_IOPAD(0xa60, PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE1) /* spi2_sclk.i2c1_scl */ >; }; - i2c2_pins: i2c2_pins { + i2c2_pins: i2c2-pins { pinctrl-single,pins = < AM4372_IOPAD(0x978, PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE3) /* uart1_ctsn.i2c2_sda */ AM4372_IOPAD(0x97c, PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE3) /* uart1_rtsn.i2c2_scl */ >; }; - usb2_phy1_default: usb2_phy1_default { + usb2_phy1_default: usb2-phy1-default-pins { pinctrl-single,pins = < AM4372_IOPAD(0xac0, DS0_PULL_UP_DOWN_EN | PIN_INPUT_PULLDOWN | MUX_MODE0) >; }; - usb2_phy2_default: usb2_phy2_default { + usb2_phy2_default: usb2-phy2-default-pins { pinctrl-single,pins = < AM4372_IOPAD(0xac4, DS0_PULL_UP_DOWN_EN | PIN_INPUT_PULLDOWN | MUX_MODE0) >; diff --git a/arch/arm/boot/dts/am437x-sk-evm.dts b/arch/arm/boot/dts/ti/omap/am437x-sk-evm.dts similarity index 96% rename from arch/arm/boot/dts/am437x-sk-evm.dts rename to arch/arm/boot/dts/ti/omap/am437x-sk-evm.dts index 511a02e13e2c9d1ca67744ee8e7ff16bfa429c95..9c97006ffd5b01b879ad88b04bed11596506c744 100644 --- a/arch/arm/boot/dts/am437x-sk-evm.dts +++ b/arch/arm/boot/dts/ti/omap/am437x-sk-evm.dts @@ -159,7 +159,7 @@ }; &am43xx_pinmux { - matrix_keypad_pins: matrix_keypad_pins { + matrix_keypad_pins: matrix-keypad-pins { pinctrl-single,pins = < AM4372_IOPAD(0xa4c, PIN_OUTPUT | MUX_MODE7) /* gpio5_13.gpio5_13 */ AM4372_IOPAD(0xa50, PIN_OUTPUT | MUX_MODE7) /* spi4_sclk.gpio5_4 */ @@ -168,7 +168,7 @@ >; }; - leds_pins: leds_pins { + leds_pins: leds-pins { pinctrl-single,pins = < AM4372_IOPAD(0xa28, PIN_OUTPUT | MUX_MODE7) /* uart3_rxd.gpio5_2 */ AM4372_IOPAD(0xa2c, PIN_OUTPUT | MUX_MODE7) /* uart3_txd.gpio5_3 */ @@ -177,21 +177,21 @@ >; }; - i2c0_pins: i2c0_pins { + i2c0_pins: i2c0-pins { pinctrl-single,pins = < AM4372_IOPAD(0x988, PIN_INPUT | SLEWCTRL_FAST | MUX_MODE0) /* i2c0_sda.i2c0_sda */ AM4372_IOPAD(0x98c, PIN_INPUT | SLEWCTRL_FAST | MUX_MODE0) /* i2c0_scl.i2c0_scl */ >; }; - i2c1_pins: i2c1_pins { + i2c1_pins: i2c1-pins { pinctrl-single,pins = < AM4372_IOPAD(0x95c, PIN_INPUT | SLEWCTRL_FAST | MUX_MODE2) /* spi0_cs0.i2c1_scl */ AM4372_IOPAD(0x958, PIN_INPUT | SLEWCTRL_FAST | MUX_MODE2) /* spi0_d1.i2c1_sda */ >; }; - mmc1_pins: pinmux_mmc1_pins { + mmc1_pins: mmc1-pins { pinctrl-single,pins = < AM4372_IOPAD(0x8f0, PIN_INPUT | MUX_MODE0) /* mmc0_dat3.mmc0_dat3 */ AM4372_IOPAD(0x8f4, PIN_INPUT | MUX_MODE0) /* mmc0_dat2.mmc0_dat2 */ @@ -203,20 +203,20 @@ >; }; - ecap0_pins: backlight_pins { + ecap0_pins: backlight-pins { pinctrl-single,pins = < AM4372_IOPAD(0x964, PIN_OUTPUT | MUX_MODE0) /* eCAP0_in_PWM0_out.eCAP0_in_PWM0_out */ >; }; - edt_ft5306_ts_pins: edt_ft5306_ts_pins { + edt_ft5306_ts_pins: edt-ft5306-ts-pins { pinctrl-single,pins = < AM4372_IOPAD(0x874, PIN_INPUT | MUX_MODE7) /* gpmc_wpn.gpio0_31 */ AM4372_IOPAD(0x878, PIN_OUTPUT | MUX_MODE7) /* gpmc_be1n.gpio1_28 */ >; }; - vpfe0_pins_default: vpfe0_pins_default { + vpfe0_pins_default: vpfe0-default-pins { pinctrl-single,pins = < AM4372_IOPAD(0x9b0, PIN_INPUT_PULLUP | MUX_MODE0) /* cam0_hd mode 0*/ AM4372_IOPAD(0x9b4, PIN_INPUT_PULLUP | MUX_MODE0) /* cam0_vd mode 0*/ @@ -236,7 +236,7 @@ >; }; - vpfe0_pins_sleep: vpfe0_pins_sleep { + vpfe0_pins_sleep: vpfe0-sleep-pins { pinctrl-single,pins = < AM4372_IOPAD(0x9b0, DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) AM4372_IOPAD(0x9b4, DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) @@ -256,13 +256,13 @@ >; }; - clkout1_pin: pinmux_clkout1_pin { + clkout1_pin: clkout1-pins { pinctrl-single,pins = < 0x270 (PIN_OUTPUT_PULLDOWN | MUX_MODE3) /* XDMA_EVENT_INTR0/CLKOUT1 */ >; }; - cpsw_default: cpsw_default { + cpsw_default: cpsw-default-pins { pinctrl-single,pins = < /* Slave 1 */ AM4372_IOPAD(0x92c, PIN_OUTPUT | MUX_MODE2) /* mii1_txclk.rmii1_tclk */ @@ -294,7 +294,7 @@ >; }; - cpsw_sleep: cpsw_sleep { + cpsw_sleep: cpsw-sleep-pins { pinctrl-single,pins = < /* Slave 1 reset value */ AM4372_IOPAD(0x92c, PIN_INPUT_PULLDOWN | MUX_MODE7) @@ -326,7 +326,7 @@ >; }; - davinci_mdio_default: davinci_mdio_default { + davinci_mdio_default: davinci-mdio-default-pins { pinctrl-single,pins = < /* MDIO */ AM4372_IOPAD(0x948, PIN_INPUT | SLEWCTRL_FAST | MUX_MODE0) /* mdio_data.mdio_data */ @@ -334,7 +334,7 @@ >; }; - davinci_mdio_sleep: davinci_mdio_sleep { + davinci_mdio_sleep: davinci-mdio-sleep-pins { pinctrl-single,pins = < /* MDIO reset value */ AM4372_IOPAD(0x948, PIN_INPUT_PULLDOWN | MUX_MODE7) @@ -342,7 +342,7 @@ >; }; - dss_pins: dss_pins { + dss_pins: dss-pins { pinctrl-single,pins = < AM4372_IOPAD(0x820, PIN_OUTPUT | MUX_MODE1) /* gpmc ad 8 -> DSS DATA 23 */ AM4372_IOPAD(0x824, PIN_OUTPUT | MUX_MODE1) @@ -376,7 +376,7 @@ >; }; - qspi_pins: qspi_pins { + qspi_pins: qspi-pins { pinctrl-single,pins = < AM4372_IOPAD(0x87c, PIN_OUTPUT | MUX_MODE3) /* gpmc_csn0.qspi_csn */ AM4372_IOPAD(0x888, PIN_OUTPUT | MUX_MODE2) /* gpmc_csn3.qspi_clk */ @@ -387,7 +387,7 @@ >; }; - mcasp1_pins: mcasp1_pins { + mcasp1_pins: mcasp1-pins { pinctrl-single,pins = < AM4372_IOPAD(0x90c, PIN_INPUT_PULLDOWN | MUX_MODE4) /* mii1_crs.mcasp1_aclkx */ AM4372_IOPAD(0x910, PIN_INPUT_PULLDOWN | MUX_MODE4) /* mii1_rxerr.mcasp1_fsx */ @@ -396,7 +396,7 @@ >; }; - mcasp1_pins_sleep: mcasp1_pins_sleep { + mcasp1_pins_sleep: mcasp1-sleep-pins { pinctrl-single,pins = < AM4372_IOPAD(0x90c, PIN_INPUT_PULLDOWN | MUX_MODE7) AM4372_IOPAD(0x910, PIN_INPUT_PULLDOWN | MUX_MODE7) @@ -405,25 +405,25 @@ >; }; - lcd_pins: lcd_pins { + lcd_pins: lcd-pins { pinctrl-single,pins = < AM4372_IOPAD(0x81c, PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpcm_ad7.gpio1_7 */ >; }; - usb1_pins: usb1_pins { + usb1_pins: usb1-pins { pinctrl-single,pins = < AM4372_IOPAD(0xac0, PIN_OUTPUT | MUX_MODE0) /* usb0_drvvbus.usb0_drvvbus */ >; }; - usb2_pins: usb2_pins { + usb2_pins: usb2-pins { pinctrl-single,pins = < AM4372_IOPAD(0xac4, PIN_OUTPUT | MUX_MODE0) /* usb0_drvvbus.usb0_drvvbus */ >; }; - mmc3_pins_default: pinmux_mmc3_pins_default { + mmc3_pins_default: mmc3-default-pins { pinctrl-single,pins = < AM4372_IOPAD(0x9f0, PIN_INPUT_PULLUP | MUX_MODE3) /* (AD21) cam1_data2.mmc2_clk */ AM4372_IOPAD(0x9f4, PIN_INPUT_PULLUP | MUX_MODE3) /* (AE22) cam1_data3.mmc2_cmd */ @@ -434,7 +434,7 @@ >; }; - mmc3_pins_sleep: pinmux_mmc3_pins_sleep { + mmc3_pins_sleep: mmc3-sleep-pins { pinctrl-single,pins = < AM4372_IOPAD(0x9f0, PIN_INPUT_PULLDOWN | MUX_MODE7) /* (AD21) cam1_data2.mmc2_clk */ AM4372_IOPAD(0x9f4, PIN_INPUT_PULLDOWN | MUX_MODE7) /* (AE22) cam1_data3.mmc2_cmd */ @@ -445,21 +445,21 @@ >; }; - wlan_pins_default: pinmux_wlan_pins_default { + wlan_pins_default: wlan-default-pins { pinctrl-single,pins = < AM4372_IOPAD(0x9d0, PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* cam1_data8.gpio4_8 WL_EN */ AM4372_IOPAD(0x9e4, PIN_INPUT | WAKEUP_ENABLE | MUX_MODE7) /* cam1_wen.gpio4_13 WL_IRQ */ >; }; - wlan_pins_sleep: pinmux_wlan_pins_sleep { + wlan_pins_sleep: wlan-sleep-pins { pinctrl-single,pins = < AM4372_IOPAD(0x9d0, PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* cam1_data8.gpio4_8 WL_EN */ AM4372_IOPAD(0x9e4, PIN_INPUT | WAKEUP_ENABLE | MUX_MODE7) /* cam1_wen.gpio4_13 WL_IRQ */ >; }; - uart1_bt_pins_default: pinmux_uart1_bt_pins_default { + uart1_bt_pins_default: uart1-bt-default-pins { pinctrl-single,pins = < AM4372_IOPAD(0x980, PIN_INPUT | MUX_MODE0) /* uart1_rxd.uart1_rxd */ AM4372_IOPAD(0x984, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* uart1_txd.uart1_txd */ @@ -469,7 +469,7 @@ >; }; - uart1_bt_pins_sleep: pinmux_uart1_bt_pins_sleep { + uart1_bt_pins_sleep: uart1-bt-sleep-pins { pinctrl-single,pins = < AM4372_IOPAD(0x980, PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* uart1_rxd.uart1_rxd */ AM4372_IOPAD(0x984, PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* uart1_txd.uart1_txd */ diff --git a/arch/arm/boot/dts/am43x-epos-evm.dts b/arch/arm/boot/dts/ti/omap/am43x-epos-evm.dts similarity index 95% rename from arch/arm/boot/dts/am43x-epos-evm.dts rename to arch/arm/boot/dts/ti/omap/am43x-epos-evm.dts index 9fc915a2582e24d7caf436b9c7ab9d94d9b8c804..9193a4cfba78a91f98e8cea3486a0e31cf480a75 100644 --- a/arch/arm/boot/dts/am43x-epos-evm.dts +++ b/arch/arm/boot/dts/ti/omap/am43x-epos-evm.dts @@ -141,7 +141,7 @@ pinctrl-names = "default"; pinctrl-0 = <&unused_pins>; - unused_pins: unused_pins { + unused_pins: unused-pins { pinctrl-single,pins = < AM4372_IOPAD(0x848, DS0_PIN_OUTPUT_PULLUP | PIN_OUTPUT_PULLUP | MUX_MODE7) AM4372_IOPAD(0x850, DS0_PIN_INPUT | PIN_INPUT_PULLDOWN | MUX_MODE7) @@ -175,7 +175,7 @@ >; }; - cpsw_default: cpsw_default { + cpsw_default: cpsw-default-pins { pinctrl-single,pins = < /* Slave 1 */ AM4372_IOPAD(0x90c, PIN_INPUT_PULLDOWN | MUX_MODE1) /* mii1_crs.rmii1_crs */ @@ -190,7 +190,7 @@ >; }; - cpsw_sleep: cpsw_sleep { + cpsw_sleep: cpsw-sleep-pins { pinctrl-single,pins = < /* Slave 1 reset value */ AM4372_IOPAD(0x90c, PIN_INPUT_PULLDOWN | MUX_MODE7) @@ -205,7 +205,7 @@ >; }; - davinci_mdio_default: davinci_mdio_default { + davinci_mdio_default: davinci-mdio-default-pins { pinctrl-single,pins = < /* MDIO */ AM4372_IOPAD(0x948, PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0) /* mdio_data.mdio_data */ @@ -213,7 +213,7 @@ >; }; - davinci_mdio_sleep: davinci_mdio_sleep { + davinci_mdio_sleep: davinci-mdio-sleep-pins { pinctrl-single,pins = < /* MDIO reset value */ AM4372_IOPAD(0x948, PIN_INPUT_PULLDOWN | MUX_MODE7) @@ -221,14 +221,14 @@ >; }; - i2c0_pins: pinmux_i2c0_pins { + i2c0_pins: i2c0-pins { pinctrl-single,pins = < AM4372_IOPAD(0x988, PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0) /* i2c0_sda.i2c0_sda */ AM4372_IOPAD(0x98c, PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0) /* i2c0_scl.i2c0_scl */ >; }; - nand_flash_x8_default: nand_flash_x8_default { + nand_flash_x8_default: nand-flash-x8-default-pins { pinctrl-single,pins = < AM4372_IOPAD(0x840, PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_a0.SELQSPIorNAND/GPIO */ AM4372_IOPAD(0x800, PIN_INPUT_PULLDOWN | MUX_MODE0) /* gpmc_ad0.gpmc_ad0 */ @@ -249,7 +249,7 @@ >; }; - nand_flash_x8_sleep: nand_flash_x8_sleep { + nand_flash_x8_sleep: nand-flash-x8-sleep-pins { pinctrl-single,pins = < AM4372_IOPAD(0x840, DS0_PIN_OUTPUT_PULLDOWN | MUX_MODE7) AM4372_IOPAD(0x800, DS0_PIN_OUTPUT_PULLDOWN | MUX_MODE7) @@ -270,26 +270,26 @@ >; }; - ecap0_pins_default: backlight_pins_default { + ecap0_pins_default: backlight-default-pins { pinctrl-single,pins = < AM4372_IOPAD(0x964, MUX_MODE0) /* eCAP0_in_PWM0_out.eCAP0_in_PWM0_out MODE0 */ >; }; - ecap0_pins_sleep: backlight_pins_sleep { + ecap0_pins_sleep: backlight-sleep-pins { pinctrl-single,pins = < AM4372_IOPAD(0x964, DS0_PIN_OUTPUT_PULLUP | MUX_MODE7) >; }; - i2c2_pins: pinmux_i2c2_pins { + i2c2_pins: i2c2-pins { pinctrl-single,pins = < AM4372_IOPAD(0x9c0, PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE8) /* i2c2_sda.i2c2_sda */ AM4372_IOPAD(0x9c4, PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE8) /* i2c2_scl.i2c2_scl */ >; }; - spi0_pins_default: pinmux_spi0_pins_default { + spi0_pins_default: spi0-default-pins { pinctrl-single,pins = < AM4372_IOPAD(0x950, PIN_INPUT | MUX_MODE0) /* spi0_clk.spi0_clk */ AM4372_IOPAD(0x954, PIN_OUTPUT | MUX_MODE0) /* spi0_d0.spi0_d0 */ @@ -298,7 +298,7 @@ >; }; - spi0_pins_sleep: pinmux_spi0_pins_sleep { + spi0_pins_sleep: spi0-sleep-pins { pinctrl-single,pins = < AM4372_IOPAD(0x950, DS0_PIN_OUTPUT_PULLUP | PIN_OUTPUT_PULLUP | MUX_MODE7) AM4372_IOPAD(0x954, DS0_PIN_OUTPUT_PULLUP | PIN_OUTPUT_PULLUP | MUX_MODE7) @@ -307,7 +307,7 @@ >; }; - spi1_pins_default: pinmux_spi1_pins_default { + spi1_pins_default: spi1-default-pins { pinctrl-single,pins = < AM4372_IOPAD(0x990, PIN_INPUT | MUX_MODE3) /* mcasp0_aclkx.spi1_clk */ AM4372_IOPAD(0x994, PIN_OUTPUT | MUX_MODE3) /* mcasp0_fsx.spi1_d0 */ @@ -316,7 +316,7 @@ >; }; - spi1_pins_sleep: pinmux_spi1_pins_sleep { + spi1_pins_sleep: spi1-sleep-pins { pinctrl-single,pins = < AM4372_IOPAD(0x990, DS0_PIN_OUTPUT_PULLDOWN | PIN_OUTPUT_PULLDOWN | MUX_MODE7) AM4372_IOPAD(0x994, DS0_PIN_OUTPUT_PULLDOWN | PIN_OUTPUT_PULLDOWN | MUX_MODE7) @@ -325,19 +325,19 @@ >; }; - mmc1_pins_default: pinmux_mmc1_pins_default { + mmc1_pins_default: mmc1-default-pins { pinctrl-single,pins = < AM4372_IOPAD(0x960, PIN_INPUT | MUX_MODE7) /* spi0_cs1.gpio0_6 */ >; }; - mmc1_pins_sleep: pinmux_mmc1_pins_sleep { + mmc1_pins_sleep: mmc1-sleep-pins { pinctrl-single,pins = < AM4372_IOPAD(0x960, DS0_PIN_OUTPUT_PULLUP | PIN_INPUT | MUX_MODE7) >; }; - matrix_keypad_default: matrix_keypad_default { + matrix_keypad_default: matrix-keypad-default-pins { pinctrl-single,pins = < AM4372_IOPAD(0x92c, PIN_OUTPUT | MUX_MODE7) /* mii1_tx_clk.gpio3_9 */ AM4372_IOPAD(0x930, PIN_OUTPUT | MUX_MODE7) /* mii1_rx_clk.gpio3_10 */ @@ -350,7 +350,7 @@ >; }; - matrix_keypad_sleep: matrix_keypad_sleep { + matrix_keypad_sleep: matrix-keypad-sleep-pins { pinctrl-single,pins = < AM4372_IOPAD(0x92c, PIN_INPUT_PULLUP | MUX_MODE7) AM4372_IOPAD(0x930, PIN_INPUT_PULLUP | MUX_MODE7) @@ -363,7 +363,7 @@ >; }; - qspi1_pins_default: qspi1_pins_default { + qspi1_pins_default: qspi1-default-pins { pinctrl-single,pins = < AM4372_IOPAD(0x87c, PIN_INPUT_PULLUP | MUX_MODE3) AM4372_IOPAD(0x888, PIN_INPUT_PULLUP | MUX_MODE2) @@ -374,7 +374,7 @@ >; }; - qspi1_pins_sleep: qspi1_pins_sleep { + qspi1_pins_sleep: qspi1-sleep-pins { pinctrl-single,pins = < AM4372_IOPAD(0x87c, DS0_PIN_OUTPUT_PULLUP | MUX_MODE7) AM4372_IOPAD(0x888, DS0_PIN_OUTPUT_PULLUP | MUX_MODE7) @@ -385,25 +385,25 @@ >; }; - pixcir_ts_pins_default: pixcir_ts_pins_default { + pixcir_ts_pins_default: pixcir-ts-default-pins { pinctrl-single,pins = < AM4372_IOPAD(0x844, PIN_INPUT_PULLUP | MUX_MODE7) /* gpmc_a1.gpio1_17 */ >; }; - pixcir_ts_pins_sleep: pixcir_ts_pins_sleep { + pixcir_ts_pins_sleep: pixcir-ts-sleep-pins { pinctrl-single,pins = < AM4372_IOPAD(0x844, DS0_PIN_OUTPUT_PULLUP | PIN_OUTPUT_PULLUP | MUX_MODE7) /* gpmc_a1.gpio1_17 */ >; }; - hdq_pins: pinmux_hdq_pins { + hdq_pins: hdq-pins { pinctrl-single,pins = < AM4372_IOPAD(0xa34, PIN_INPUT_PULLUP | MUX_MODE1) /* cam1_wen.hdq_gpio */ >; }; - dss_pins: dss_pins { + dss_pins: dss-pins { pinctrl-single,pins = < AM4372_IOPAD(0x820, PIN_OUTPUT_PULLUP | MUX_MODE1) /*gpmc ad 8 -> DSS DATA 23 */ AM4372_IOPAD(0x824, PIN_OUTPUT_PULLUP | MUX_MODE1) @@ -436,14 +436,14 @@ >; }; - display_mux_pins: display_mux_pins { + display_mux_pins: display-mux-pins { pinctrl-single,pins = < /* GPMC CLK -> GPIO 2_1 to select LCD / HDMI */ AM4372_IOPAD(0x88C, PIN_OUTPUT_PULLUP | MUX_MODE7) >; }; - vpfe1_pins_default: vpfe1_pins_default { + vpfe1_pins_default: vpfe1-default-pins { pinctrl-single,pins = < AM4372_IOPAD(0x9cc, PIN_INPUT_PULLUP | MUX_MODE0) /* cam1_data9 mode 0 */ AM4372_IOPAD(0x9d0, PIN_INPUT_PULLUP | MUX_MODE0) /* cam1_data8 mode 0 */ @@ -461,7 +461,7 @@ >; }; - vpfe1_pins_sleep: vpfe1_pins_sleep { + vpfe1_pins_sleep: vpfe1-sleep-pins { pinctrl-single,pins = < AM4372_IOPAD(0x9cc, DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) AM4372_IOPAD(0x9d0, DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) @@ -479,7 +479,7 @@ >; }; - uart0_pins_default: uart0_pins_default { + uart0_pins_default: uart0-default-pins { pinctrl-single,pins = < AM4372_IOPAD(0x968, DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE0) /* uart0_ctsn.uart0_ctsn */ AM4372_IOPAD(0x96C, DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE0) /* uart0_rtsn.uart0_rtsn */ @@ -488,7 +488,7 @@ >; }; - uart0_pins_sleep: uart0_pins_sleep { + uart0_pins_sleep: uart0-sleep-pins { pinctrl-single,pins = < AM4372_IOPAD(0x968, DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) AM4372_IOPAD(0x96C, DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) @@ -497,31 +497,31 @@ >; }; - usb2_phy1_default: usb2_phy1_default { + usb2_phy1_default: usb2-phy1-default-pins { pinctrl-single,pins = < AM4372_IOPAD(0xac0, PIN_INPUT_PULLDOWN | MUX_MODE0) >; }; - usb2_phy1_sleep: usb2_phy1_sleep { + usb2_phy1_sleep: usb2-phy1-sleep-pins { pinctrl-single,pins = < AM4372_IOPAD(0xac0, DS0_PULL_UP_DOWN_EN | PIN_INPUT_PULLDOWN | MUX_MODE7) >; }; - usb2_phy2_default: usb2_phy2_default { + usb2_phy2_default: usb2-phy2-default-pins { pinctrl-single,pins = < AM4372_IOPAD(0xac4, PIN_INPUT_PULLDOWN | MUX_MODE0) >; }; - usb2_phy2_sleep: usb2_phy2_sleep { + usb2_phy2_sleep: usb2-phy2-sleep-pins { pinctrl-single,pins = < AM4372_IOPAD(0xac4, DS0_PULL_UP_DOWN_EN | PIN_INPUT_PULLDOWN | MUX_MODE7) >; }; - mcasp1_pins: mcasp1_pins { + mcasp1_pins: mcasp1-pins { pinctrl-single,pins = < AM4372_IOPAD(0x9a0, PIN_INPUT_PULLDOWN | MUX_MODE3) /* MCASP0_ACLKR/MCASP1_ACLKX */ AM4372_IOPAD(0x9a4, PIN_INPUT_PULLDOWN | MUX_MODE3) /* MCASP0_FSR/MCASP1_FSX */ @@ -530,7 +530,7 @@ >; }; - mcasp1_sleep_pins: mcasp1_sleep_pins { + mcasp1_sleep_pins: mcasp1-sleep-pins { pinctrl-single,pins = < AM4372_IOPAD(0x9a0, PIN_INPUT_PULLDOWN | MUX_MODE7) AM4372_IOPAD(0x9a4, PIN_INPUT_PULLDOWN | MUX_MODE7) diff --git a/arch/arm/boot/dts/am43xx-clocks.dtsi b/arch/arm/boot/dts/ti/omap/am43xx-clocks.dtsi similarity index 100% rename from arch/arm/boot/dts/am43xx-clocks.dtsi rename to arch/arm/boot/dts/ti/omap/am43xx-clocks.dtsi diff --git a/arch/arm/boot/dts/am57-pruss.dtsi b/arch/arm/boot/dts/ti/omap/am57-pruss.dtsi similarity index 100% rename from arch/arm/boot/dts/am57-pruss.dtsi rename to arch/arm/boot/dts/ti/omap/am57-pruss.dtsi diff --git a/arch/arm/boot/dts/am5718.dtsi b/arch/arm/boot/dts/ti/omap/am5718.dtsi similarity index 100% rename from arch/arm/boot/dts/am5718.dtsi rename to arch/arm/boot/dts/ti/omap/am5718.dtsi diff --git a/arch/arm/boot/dts/am571x-idk-touchscreen.dtso b/arch/arm/boot/dts/ti/omap/am571x-idk-touchscreen.dtso similarity index 100% rename from arch/arm/boot/dts/am571x-idk-touchscreen.dtso rename to arch/arm/boot/dts/ti/omap/am571x-idk-touchscreen.dtso diff --git a/arch/arm/boot/dts/am571x-idk.dts b/arch/arm/boot/dts/ti/omap/am571x-idk.dts similarity index 100% rename from arch/arm/boot/dts/am571x-idk.dts rename to arch/arm/boot/dts/ti/omap/am571x-idk.dts diff --git a/arch/arm/boot/dts/am5728.dtsi b/arch/arm/boot/dts/ti/omap/am5728.dtsi similarity index 100% rename from arch/arm/boot/dts/am5728.dtsi rename to arch/arm/boot/dts/ti/omap/am5728.dtsi diff --git a/arch/arm/boot/dts/am5729-beagleboneai.dts b/arch/arm/boot/dts/ti/omap/am5729-beagleboneai.dts similarity index 100% rename from arch/arm/boot/dts/am5729-beagleboneai.dts rename to arch/arm/boot/dts/ti/omap/am5729-beagleboneai.dts diff --git a/arch/arm/boot/dts/am572x-idk-common.dtsi b/arch/arm/boot/dts/ti/omap/am572x-idk-common.dtsi similarity index 100% rename from arch/arm/boot/dts/am572x-idk-common.dtsi rename to arch/arm/boot/dts/ti/omap/am572x-idk-common.dtsi diff --git a/arch/arm/boot/dts/am572x-idk-touchscreen.dtso b/arch/arm/boot/dts/ti/omap/am572x-idk-touchscreen.dtso similarity index 100% rename from arch/arm/boot/dts/am572x-idk-touchscreen.dtso rename to arch/arm/boot/dts/ti/omap/am572x-idk-touchscreen.dtso diff --git a/arch/arm/boot/dts/am572x-idk.dts b/arch/arm/boot/dts/ti/omap/am572x-idk.dts similarity index 100% rename from arch/arm/boot/dts/am572x-idk.dts rename to arch/arm/boot/dts/ti/omap/am572x-idk.dts diff --git a/arch/arm/boot/dts/am5748.dtsi b/arch/arm/boot/dts/ti/omap/am5748.dtsi similarity index 100% rename from arch/arm/boot/dts/am5748.dtsi rename to arch/arm/boot/dts/ti/omap/am5748.dtsi diff --git a/arch/arm/boot/dts/am574x-idk.dts b/arch/arm/boot/dts/ti/omap/am574x-idk.dts similarity index 100% rename from arch/arm/boot/dts/am574x-idk.dts rename to arch/arm/boot/dts/ti/omap/am574x-idk.dts diff --git a/arch/arm/boot/dts/am57xx-beagle-x15-common.dtsi b/arch/arm/boot/dts/ti/omap/am57xx-beagle-x15-common.dtsi similarity index 100% rename from arch/arm/boot/dts/am57xx-beagle-x15-common.dtsi rename to arch/arm/boot/dts/ti/omap/am57xx-beagle-x15-common.dtsi diff --git a/arch/arm/boot/dts/am57xx-beagle-x15-revb1.dts b/arch/arm/boot/dts/ti/omap/am57xx-beagle-x15-revb1.dts similarity index 100% rename from arch/arm/boot/dts/am57xx-beagle-x15-revb1.dts rename to arch/arm/boot/dts/ti/omap/am57xx-beagle-x15-revb1.dts diff --git a/arch/arm/boot/dts/am57xx-beagle-x15-revc.dts b/arch/arm/boot/dts/ti/omap/am57xx-beagle-x15-revc.dts similarity index 100% rename from arch/arm/boot/dts/am57xx-beagle-x15-revc.dts rename to arch/arm/boot/dts/ti/omap/am57xx-beagle-x15-revc.dts diff --git a/arch/arm/boot/dts/am57xx-beagle-x15.dts b/arch/arm/boot/dts/ti/omap/am57xx-beagle-x15.dts similarity index 100% rename from arch/arm/boot/dts/am57xx-beagle-x15.dts rename to arch/arm/boot/dts/ti/omap/am57xx-beagle-x15.dts diff --git a/arch/arm/boot/dts/am57xx-cl-som-am57x.dts b/arch/arm/boot/dts/ti/omap/am57xx-cl-som-am57x.dts similarity index 96% rename from arch/arm/boot/dts/am57xx-cl-som-am57x.dts rename to arch/arm/boot/dts/ti/omap/am57xx-cl-som-am57x.dts index 625b9b311b49d2791f949ed06285838a6c36fca9..4fd831ff206fa1ace68c2ea748b181280fdbdf62 100644 --- a/arch/arm/boot/dts/am57xx-cl-som-am57x.dts +++ b/arch/arm/boot/dts/ti/omap/am57xx-cl-som-am57x.dts @@ -77,40 +77,40 @@ }; &dra7_pmx_core { - leds_pins_default: leds_pins_default { + leds_pins_default: leds-default-pins { pinctrl-single,pins = < DRA7XX_CORE_IOPAD(0x347c, PIN_OUTPUT | MUX_MODE14) /* gpmc_a15.gpio2_5 */ >; }; - i2c1_pins_default: i2c1_pins_default { + i2c1_pins_default: i2c1-default-pins { pinctrl-single,pins = < DRA7XX_CORE_IOPAD(0x3800, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c1_sda.sda */ DRA7XX_CORE_IOPAD(0x3804, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c1_scl.scl */ >; }; - i2c3_pins_default: i2c3_pins_default { + i2c3_pins_default: i2c3-default-pins { pinctrl-single,pins = < DRA7XX_CORE_IOPAD(0x36a4, PIN_INPUT| MUX_MODE10) /* mcasp1_aclkx.i2c3_sda */ DRA7XX_CORE_IOPAD(0x36a8, PIN_INPUT| MUX_MODE10) /* mcasp1_fsx.i2c3_scl */ >; }; - i2c4_pins_default: i2c4_pins_default { + i2c4_pins_default: i2c4-default-pins { pinctrl-single,pins = < DRA7XX_CORE_IOPAD(0x36ac, PIN_INPUT| MUX_MODE10) /* mcasp1_acl.i2c4_sda */ DRA7XX_CORE_IOPAD(0x36b0, PIN_INPUT| MUX_MODE10) /* mcasp1_fsr.i2c4_scl */ >; }; - tps659038_pins_default: tps659038_pins_default { + tps659038_pins_default: tps659038-default-pins { pinctrl-single,pins = < DRA7XX_CORE_IOPAD(0x3818, PIN_INPUT_PULLUP | MUX_MODE14) /* wakeup0.gpio1_0 */ >; }; - mmc2_pins_default: mmc2_pins_default { + mmc2_pins_default: mmc2-default-pins { pinctrl-single,pins = < DRA7XX_CORE_IOPAD(0x349c, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a23.mmc2_clk */ DRA7XX_CORE_IOPAD(0x34b0, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_cs1.mmc2_cmd */ @@ -125,7 +125,7 @@ >; }; - qspi1_pins: pinmux_qspi1_pins { + qspi1_pins: qspi1-pins { pinctrl-single,pins = < DRA7XX_CORE_IOPAD(0x3474, PIN_INPUT | MUX_MODE1) /* gpmc_a13.qspi1_rtclk */ DRA7XX_CORE_IOPAD(0x3480, PIN_INPUT | MUX_MODE1) /* gpmc_a16.qspi1_d0 */ @@ -136,7 +136,7 @@ >; }; - cpsw_pins_default: cpsw_pins_default { + cpsw_pins_default: cpsw-default-pins { pinctrl-single,pins = < /* Slave at addr 0x0 */ DRA7XX_CORE_IOPAD(0x3650, PIN_OUTPUT | MUX_MODE0) /* rgmii0_tclk */ @@ -168,7 +168,7 @@ >; }; - cpsw_pins_sleep: cpsw_pins_sleep { + cpsw_pins_sleep: cpsw-sleep-pins { pinctrl-single,pins = < /* Slave 1 */ DRA7XX_CORE_IOPAD(0x3650, PIN_INPUT | MUX_MODE15) @@ -200,7 +200,7 @@ >; }; - davinci_mdio_pins_default: davinci_mdio_pins_default { + davinci_mdio_pins_default: davinci-mdio-default-pins { pinctrl-single,pins = < /* MDIO */ DRA7XX_CORE_IOPAD(0x3590, PIN_OUTPUT_PULLUP | MUX_MODE3)/* vin2a_d10.mdio_mclk */ @@ -208,20 +208,20 @@ >; }; - davinci_mdio_pins_sleep: davinci_mdio_pins_sleep { + davinci_mdio_pins_sleep: davinci-mdio-sleep-pins { pinctrl-single,pins = < DRA7XX_CORE_IOPAD(0x3590, PIN_INPUT | MUX_MODE15) DRA7XX_CORE_IOPAD(0x3594, PIN_INPUT | MUX_MODE15) >; }; - ads7846_pins: pinmux_ads7846_pins { + ads7846_pins: ads7846-pins { pinctrl-single,pins = < DRA7XX_CORE_IOPAD(0x3464, PIN_INPUT_PULLDOWN | MUX_MODE14) /* gpmc_a9.gpio1_31 */ >; }; - mcasp3_pins_default: mcasp3_pins_default { + mcasp3_pins_default: mcasp3-default-pins { pinctrl-single,pins = < DRA7XX_CORE_IOPAD(0x3724, PIN_INPUT_PULLDOWN | MUX_MODE0) /* mcasp3_aclkx.mcasp3_aclkx */ DRA7XX_CORE_IOPAD(0x3728, PIN_INPUT_PULLDOWN | MUX_MODE0) /* mcasp3_fsx.mcasp3_fsx */ @@ -230,7 +230,7 @@ >; }; - mcasp3_pins_sleep: mcasp3_pins_sleep { + mcasp3_pins_sleep: mcasp3-sleep-pins { pinctrl-single,pins = < DRA7XX_CORE_IOPAD(0x3724, PIN_INPUT | MUX_MODE15) DRA7XX_CORE_IOPAD(0x3728, PIN_INPUT | MUX_MODE15) diff --git a/arch/arm/boot/dts/am57xx-commercial-grade.dtsi b/arch/arm/boot/dts/ti/omap/am57xx-commercial-grade.dtsi similarity index 100% rename from arch/arm/boot/dts/am57xx-commercial-grade.dtsi rename to arch/arm/boot/dts/ti/omap/am57xx-commercial-grade.dtsi diff --git a/arch/arm/boot/dts/am57xx-evm.dtso b/arch/arm/boot/dts/ti/omap/am57xx-evm.dtso similarity index 100% rename from arch/arm/boot/dts/am57xx-evm.dtso rename to arch/arm/boot/dts/ti/omap/am57xx-evm.dtso diff --git a/arch/arm/boot/dts/am57xx-idk-common.dtsi b/arch/arm/boot/dts/ti/omap/am57xx-idk-common.dtsi similarity index 99% rename from arch/arm/boot/dts/am57xx-idk-common.dtsi rename to arch/arm/boot/dts/ti/omap/am57xx-idk-common.dtsi index 7f092a8811e884f3e5b5e77133228d670f12a663..43e3623f079c874d5a7420947209a5b6ce0e4313 100644 --- a/arch/arm/boot/dts/am57xx-idk-common.dtsi +++ b/arch/arm/boot/dts/ti/omap/am57xx-idk-common.dtsi @@ -158,14 +158,14 @@ }; &dra7_pmx_core { - dcan1_pins_default: dcan1_pins_default { + dcan1_pins_default: dcan1-default-pins { pinctrl-single,pins = < DRA7XX_CORE_IOPAD(0x37d0, PIN_OUTPUT_PULLUP | MUX_MODE0) /* dcan1_tx */ DRA7XX_CORE_IOPAD(0x37d4, PIN_INPUT_PULLUP | MUX_MODE0) /* dcan1_rx */ >; }; - dcan1_pins_sleep: dcan1_pins_sleep { + dcan1_pins_sleep: dcan1-sleep-pins { pinctrl-single,pins = < DRA7XX_CORE_IOPAD(0x37d0, MUX_MODE15 | PULL_UP) /* dcan1_tx.off */ DRA7XX_CORE_IOPAD(0x37d4, MUX_MODE15 | PULL_UP) /* dcan1_rx.off */ diff --git a/arch/arm/boot/dts/am57xx-idk-lcd-osd101t2045.dtso b/arch/arm/boot/dts/ti/omap/am57xx-idk-lcd-osd101t2045.dtso similarity index 100% rename from arch/arm/boot/dts/am57xx-idk-lcd-osd101t2045.dtso rename to arch/arm/boot/dts/ti/omap/am57xx-idk-lcd-osd101t2045.dtso diff --git a/arch/arm/boot/dts/am57xx-idk-lcd-osd101t2587.dtso b/arch/arm/boot/dts/ti/omap/am57xx-idk-lcd-osd101t2587.dtso similarity index 100% rename from arch/arm/boot/dts/am57xx-idk-lcd-osd101t2587.dtso rename to arch/arm/boot/dts/ti/omap/am57xx-idk-lcd-osd101t2587.dtso diff --git a/arch/arm/boot/dts/am57xx-industrial-grade.dtsi b/arch/arm/boot/dts/ti/omap/am57xx-industrial-grade.dtsi similarity index 100% rename from arch/arm/boot/dts/am57xx-industrial-grade.dtsi rename to arch/arm/boot/dts/ti/omap/am57xx-industrial-grade.dtsi diff --git a/arch/arm/boot/dts/am57xx-sbc-am57x.dts b/arch/arm/boot/dts/ti/omap/am57xx-sbc-am57x.dts similarity index 93% rename from arch/arm/boot/dts/am57xx-sbc-am57x.dts rename to arch/arm/boot/dts/ti/omap/am57xx-sbc-am57x.dts index beef63e8a005791d3a5979c3e56c8d28b26690ce..363115afb0a45d4c424c8264f05d1742e1696293 100644 --- a/arch/arm/boot/dts/am57xx-sbc-am57x.dts +++ b/arch/arm/boot/dts/ti/omap/am57xx-sbc-am57x.dts @@ -20,14 +20,14 @@ }; &dra7_pmx_core { - uart3_pins_default: uart3_pins_default { + uart3_pins_default: uart3-default-pins { pinctrl-single,pins = < DRA7XX_CORE_IOPAD(0x3648, PIN_INPUT_SLEW | MUX_MODE0) /* uart3_rxd */ DRA7XX_CORE_IOPAD(0x364c, PIN_INPUT_SLEW | MUX_MODE0) /* uart3_txd */ >; }; - mmc1_pins_default: mmc1_pins_default { + mmc1_pins_default: mmc1-default-pins { pinctrl-single,pins = < DRA7XX_CORE_IOPAD(0x3754, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_clk.clk */ DRA7XX_CORE_IOPAD(0x3758, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_cmd.cmd */ @@ -40,33 +40,33 @@ >; }; - usb1_pins: pinmux_usb1_pins { + usb1_pins: usb1-pins { pinctrl-single,pins = < DRA7XX_CORE_IOPAD(0x3680, PIN_INPUT_SLEW | MUX_MODE0) /* usb1_drvvbus */ >; }; - i2c5_pins_default: i2c5_pins_default { + i2c5_pins_default: i2c5-default-pins { pinctrl-single,pins = < DRA7XX_CORE_IOPAD(0x36b4, PIN_INPUT| MUX_MODE10) /* mcasp1_axr0.i2c5_sda */ DRA7XX_CORE_IOPAD(0x36b8, PIN_INPUT| MUX_MODE10) /* mcasp1_axr1.i2c5_scl */ >; }; - lcd_pins_default: lcd_pins_default { + lcd_pins_default: lcd-default-pins { pinctrl-single,pins = < DRA7XX_CORE_IOPAD(0x3564, PIN_OUTPUT | MUX_MODE14) /* vin2a_vsync0.gpio4_0 */ >; }; - hdmi_pins: pinmux_hdmi_pins { + hdmi_pins: hdmi-pins { pinctrl-single,pins = < DRA7XX_CORE_IOPAD(0x3808, PIN_INPUT | MUX_MODE1) /* i2c2_sda.hdmi1_ddc_scl */ DRA7XX_CORE_IOPAD(0x380c, PIN_INPUT | MUX_MODE1) /* i2c2_scl.hdmi1_ddc_sda */ >; }; - hdmi_conn_pins: pinmux_hdmi_conn_pins { + hdmi_conn_pins: hdmi-conn-pins { pinctrl-single,pins = < DRA7XX_CORE_IOPAD(0x37b8, PIN_INPUT | MUX_MODE14) /* spi1_cs2.gpio7_12 */ >; diff --git a/arch/arm/boot/dts/compulab-sb-som.dtsi b/arch/arm/boot/dts/ti/omap/compulab-sb-som.dtsi similarity index 100% rename from arch/arm/boot/dts/compulab-sb-som.dtsi rename to arch/arm/boot/dts/ti/omap/compulab-sb-som.dtsi diff --git a/arch/arm/boot/dts/dm3725.dtsi b/arch/arm/boot/dts/ti/omap/dm3725.dtsi similarity index 100% rename from arch/arm/boot/dts/dm3725.dtsi rename to arch/arm/boot/dts/ti/omap/dm3725.dtsi diff --git a/arch/arm/boot/dts/dm8148-evm.dts b/arch/arm/boot/dts/ti/omap/dm8148-evm.dts similarity index 97% rename from arch/arm/boot/dts/dm8148-evm.dts rename to arch/arm/boot/dts/ti/omap/dm8148-evm.dts index fe3f9a970b1883737ac2404c1ff903820ce4c624..ae8d9fa09d16b999088c2cf1579afa5f9e20cdf7 100644 --- a/arch/arm/boot/dts/dm8148-evm.dts +++ b/arch/arm/boot/dts/ti/omap/dm8148-evm.dts @@ -116,7 +116,7 @@ }; &pincntl { - sd1_pins: pinmux_sd1_pins { + sd1_pins: sd1-pins { pinctrl-single,pins = < DM814X_IOPAD(0x0800, PIN_INPUT | 0x1) /* SD1_CLK */ DM814X_IOPAD(0x0804, PIN_INPUT_PULLUP | 0x1) /* SD1_CMD */ @@ -129,13 +129,13 @@ >; }; - usb0_pins: pinmux_usb0_pins { + usb0_pins: usb0-pins { pinctrl-single,pins = < DM814X_IOPAD(0x0c34, PIN_OUTPUT | 0x1) /* USB0_DRVVBUS */ >; }; - usb1_pins: pinmux_usb1_pins { + usb1_pins: usb1-pins { pinctrl-single,pins = < DM814X_IOPAD(0x0834, PIN_OUTPUT | 0x80) /* USB1_DRVVBUS */ >; diff --git a/arch/arm/boot/dts/dm8148-t410.dts b/arch/arm/boot/dts/ti/omap/dm8148-t410.dts similarity index 96% rename from arch/arm/boot/dts/dm8148-t410.dts rename to arch/arm/boot/dts/ti/omap/dm8148-t410.dts index 79ccdd4470f4cb61cd2f9aca0cb7faca172276a6..f3e2ecf6d72332420920cda0df8052d17bd3dda0 100644 --- a/arch/arm/boot/dts/dm8148-t410.dts +++ b/arch/arm/boot/dts/ti/omap/dm8148-t410.dts @@ -71,7 +71,7 @@ }; &pincntl { - sd2_pins: pinmux_sd2_pins { + sd2_pins: sd2-pins { pinctrl-single,pins = < DM814X_IOPAD(0x09c0, PIN_INPUT_PULLUP | 0x1) /* SD2_DAT[7] */ DM814X_IOPAD(0x09c4, PIN_INPUT_PULLUP | 0x1) /* SD2_DAT[6] */ @@ -87,13 +87,13 @@ >; }; - usb0_pins: pinmux_usb0_pins { + usb0_pins: usb0-pins { pinctrl-single,pins = < DM814X_IOPAD(0x0c34, PIN_OUTPUT | 0x1) /* USB0_DRVVBUS */ >; }; - usb1_pins: pinmux_usb1_pins { + usb1_pins: usb1-pins { pinctrl-single,pins = < DM814X_IOPAD(0x0834, PIN_OUTPUT | 0x80) /* USB1_DRVVBUS */ >; diff --git a/arch/arm/boot/dts/dm814x-clocks.dtsi b/arch/arm/boot/dts/ti/omap/dm814x-clocks.dtsi similarity index 100% rename from arch/arm/boot/dts/dm814x-clocks.dtsi rename to arch/arm/boot/dts/ti/omap/dm814x-clocks.dtsi diff --git a/arch/arm/boot/dts/dm814x.dtsi b/arch/arm/boot/dts/ti/omap/dm814x.dtsi similarity index 100% rename from arch/arm/boot/dts/dm814x.dtsi rename to arch/arm/boot/dts/ti/omap/dm814x.dtsi diff --git a/arch/arm/boot/dts/dm8168-evm.dts b/arch/arm/boot/dts/ti/omap/dm8168-evm.dts similarity index 97% rename from arch/arm/boot/dts/dm8168-evm.dts rename to arch/arm/boot/dts/ti/omap/dm8168-evm.dts index 244a957f9ba3a44963c10b12d639a4aac08e7dfd..1d80288f6ba5fad1ca6bbf710ae7d1ac16bf29d8 100644 --- a/arch/arm/boot/dts/dm8168-evm.dts +++ b/arch/arm/boot/dts/ti/omap/dm8168-evm.dts @@ -30,7 +30,7 @@ }; &dm816x_pinmux { - mcspi1_pins: pinmux_mcspi1_pins { + mcspi1_pins: mcspi1-pins { pinctrl-single,pins = < DM816X_IOPAD(0x0a94, MUX_MODE0) /* SPI_SCLK */ DM816X_IOPAD(0x0a98, MUX_MODE0) /* SPI_SCS0 */ @@ -39,7 +39,7 @@ >; }; - mmc_pins: pinmux_mmc_pins { + mmc_pins: mmc-pins { pinctrl-single,pins = < DM816X_IOPAD(0x0a70, MUX_MODE0) /* SD_POW */ DM816X_IOPAD(0x0a74, MUX_MODE0) /* SD_CLK */ @@ -53,19 +53,19 @@ >; }; - usb0_pins: pinmux_usb0_pins { + usb0_pins: usb0-pins { pinctrl-single,pins = < DM816X_IOPAD(0x0d04, MUX_MODE0) /* USB0_DRVVBUS */ >; }; - usb1_pins: pinmux_usb1_pins { + usb1_pins: usb1-pins { pinctrl-single,pins = < DM816X_IOPAD(0x0d08, MUX_MODE0) /* USB1_DRVVBUS */ >; }; - nandflash_pins: nandflash_pins { + nandflash_pins: nandflash-pins { pinctrl-single,pins = < DM816X_IOPAD(0x0b38, PULL_UP | MUX_MODE0) /* PINCTRL207 GPMC_CS0*/ DM816X_IOPAD(0x0b60, PULL_ENA | MUX_MODE0) /* PINCTRL217 GPMC_ADV_ALE */ diff --git a/arch/arm/boot/dts/dm816x-clocks.dtsi b/arch/arm/boot/dts/ti/omap/dm816x-clocks.dtsi similarity index 100% rename from arch/arm/boot/dts/dm816x-clocks.dtsi rename to arch/arm/boot/dts/ti/omap/dm816x-clocks.dtsi diff --git a/arch/arm/boot/dts/dm816x.dtsi b/arch/arm/boot/dts/ti/omap/dm816x.dtsi similarity index 100% rename from arch/arm/boot/dts/dm816x.dtsi rename to arch/arm/boot/dts/ti/omap/dm816x.dtsi diff --git a/arch/arm/boot/dts/dra62x-clocks.dtsi b/arch/arm/boot/dts/ti/omap/dra62x-clocks.dtsi similarity index 100% rename from arch/arm/boot/dts/dra62x-clocks.dtsi rename to arch/arm/boot/dts/ti/omap/dra62x-clocks.dtsi diff --git a/arch/arm/boot/dts/dra62x-j5eco-evm.dts b/arch/arm/boot/dts/ti/omap/dra62x-j5eco-evm.dts similarity index 98% rename from arch/arm/boot/dts/dra62x-j5eco-evm.dts rename to arch/arm/boot/dts/ti/omap/dra62x-j5eco-evm.dts index 577114c4c20a374f49ba3a8ae2fb18db53d7264d..2f6ac267fc150330c44371c1cf0ea7ab1bc13923 100644 --- a/arch/arm/boot/dts/dra62x-j5eco-evm.dts +++ b/arch/arm/boot/dts/ti/omap/dra62x-j5eco-evm.dts @@ -108,7 +108,7 @@ }; &pincntl { - sd1_pins: pinmux_sd1_pins { + sd1_pins: sd1-pins { pinctrl-single,pins = < DM814X_IOPAD(0x0800, PIN_INPUT | 0x1) /* SD1_CLK */ DM814X_IOPAD(0x0804, PIN_INPUT_PULLUP | 0x1) /* SD1_CMD */ @@ -121,7 +121,7 @@ >; }; - usb0_pins: pinmux_usb0_pins { + usb0_pins: usb0-pins { pinctrl-single,pins = < DM814X_IOPAD(0x0c34, PIN_OUTPUT | 0x1) /* USB0_DRVVBUS */ >; diff --git a/arch/arm/boot/dts/dra62x.dtsi b/arch/arm/boot/dts/ti/omap/dra62x.dtsi similarity index 100% rename from arch/arm/boot/dts/dra62x.dtsi rename to arch/arm/boot/dts/ti/omap/dra62x.dtsi diff --git a/arch/arm/boot/dts/dra7-dspeve-thermal.dtsi b/arch/arm/boot/dts/ti/omap/dra7-dspeve-thermal.dtsi similarity index 100% rename from arch/arm/boot/dts/dra7-dspeve-thermal.dtsi rename to arch/arm/boot/dts/ti/omap/dra7-dspeve-thermal.dtsi diff --git a/arch/arm/boot/dts/dra7-evm-common.dtsi b/arch/arm/boot/dts/ti/omap/dra7-evm-common.dtsi similarity index 100% rename from arch/arm/boot/dts/dra7-evm-common.dtsi rename to arch/arm/boot/dts/ti/omap/dra7-evm-common.dtsi diff --git a/arch/arm/boot/dts/dra7-evm.dts b/arch/arm/boot/dts/ti/omap/dra7-evm.dts similarity index 99% rename from arch/arm/boot/dts/dra7-evm.dts rename to arch/arm/boot/dts/ti/omap/dra7-evm.dts index 8cbcf55a5a339ac21f8be9c5bc1461174bac2137..46efbaa67a8e2b052f6377c1ce7798b3428abc23 100644 --- a/arch/arm/boot/dts/dra7-evm.dts +++ b/arch/arm/boot/dts/ti/omap/dra7-evm.dts @@ -152,14 +152,14 @@ }; &dra7_pmx_core { - dcan1_pins_default: dcan1_pins_default { + dcan1_pins_default: dcan1-default-pins { pinctrl-single,pins = < DRA7XX_CORE_IOPAD(0x37d0, PIN_OUTPUT_PULLUP | MUX_MODE0) /* dcan1_tx */ DRA7XX_CORE_IOPAD(0x3818, PULL_UP | MUX_MODE1) /* wakeup0.dcan1_rx */ >; }; - dcan1_pins_sleep: dcan1_pins_sleep { + dcan1_pins_sleep: dcan1-sleep-pins { pinctrl-single,pins = < DRA7XX_CORE_IOPAD(0x37d0, MUX_MODE15 | PULL_UP) /* dcan1_tx.off */ DRA7XX_CORE_IOPAD(0x3818, MUX_MODE15 | PULL_UP) /* wakeup0.off */ diff --git a/arch/arm/boot/dts/dra7-ipu-dsp-common.dtsi b/arch/arm/boot/dts/ti/omap/dra7-ipu-dsp-common.dtsi similarity index 100% rename from arch/arm/boot/dts/dra7-ipu-dsp-common.dtsi rename to arch/arm/boot/dts/ti/omap/dra7-ipu-dsp-common.dtsi diff --git a/arch/arm/boot/dts/dra7-iva-thermal.dtsi b/arch/arm/boot/dts/ti/omap/dra7-iva-thermal.dtsi similarity index 100% rename from arch/arm/boot/dts/dra7-iva-thermal.dtsi rename to arch/arm/boot/dts/ti/omap/dra7-iva-thermal.dtsi diff --git a/arch/arm/boot/dts/dra7-l4.dtsi b/arch/arm/boot/dts/ti/omap/dra7-l4.dtsi similarity index 100% rename from arch/arm/boot/dts/dra7-l4.dtsi rename to arch/arm/boot/dts/ti/omap/dra7-l4.dtsi diff --git a/arch/arm/boot/dts/dra7-mmc-iodelay.dtsi b/arch/arm/boot/dts/ti/omap/dra7-mmc-iodelay.dtsi similarity index 92% rename from arch/arm/boot/dts/dra7-mmc-iodelay.dtsi rename to arch/arm/boot/dts/ti/omap/dra7-mmc-iodelay.dtsi index aa094726652693ecf814806d58362a5d510c1e31..cb1a682c26cda89fdf091bb95e9754a338639682 100644 --- a/arch/arm/boot/dts/dra7-mmc-iodelay.dtsi +++ b/arch/arm/boot/dts/ti/omap/dra7-mmc-iodelay.dtsi @@ -6,7 +6,7 @@ */ &dra7_pmx_core { - mmc1_pins_default_no_clk_pu: mmc1_pins_default_no_clk_pu { + mmc1_pins_default_no_clk_pu: mmc1-default-no-clk-pu-pins { pinctrl-single,pins = < DRA7XX_CORE_IOPAD(0x3754, PIN_INPUT_PULLDOWN | MUX_MODE0) /* mmc1_clk.clk */ DRA7XX_CORE_IOPAD(0x3758, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_cmd.cmd */ diff --git a/arch/arm/boot/dts/dra7.dtsi b/arch/arm/boot/dts/ti/omap/dra7.dtsi similarity index 100% rename from arch/arm/boot/dts/dra7.dtsi rename to arch/arm/boot/dts/ti/omap/dra7.dtsi diff --git a/arch/arm/boot/dts/dra71-evm.dts b/arch/arm/boot/dts/ti/omap/dra71-evm.dts similarity index 100% rename from arch/arm/boot/dts/dra71-evm.dts rename to arch/arm/boot/dts/ti/omap/dra71-evm.dts diff --git a/arch/arm/boot/dts/dra71x.dtsi b/arch/arm/boot/dts/ti/omap/dra71x.dtsi similarity index 100% rename from arch/arm/boot/dts/dra71x.dtsi rename to arch/arm/boot/dts/ti/omap/dra71x.dtsi diff --git a/arch/arm/boot/dts/dra72-evm-common.dtsi b/arch/arm/boot/dts/ti/omap/dra72-evm-common.dtsi similarity index 99% rename from arch/arm/boot/dts/dra72-evm-common.dtsi rename to arch/arm/boot/dts/ti/omap/dra72-evm-common.dtsi index c79ba671ec2b91dbe9eb4303d40dac26039e1871..31ab0c60ca75e02e924f3dd9ec630ad6249fee8e 100644 --- a/arch/arm/boot/dts/dra72-evm-common.dtsi +++ b/arch/arm/boot/dts/ti/omap/dra72-evm-common.dtsi @@ -197,14 +197,14 @@ }; &dra7_pmx_core { - dcan1_pins_default: dcan1_pins_default { + dcan1_pins_default: dcan1-default-pins { pinctrl-single,pins = < DRA7XX_CORE_IOPAD(0x37d0, PIN_OUTPUT_PULLUP | MUX_MODE0) /* dcan1_tx */ DRA7XX_CORE_IOPAD(0x3818, PULL_UP | MUX_MODE1) /* wakeup0.dcan1_rx */ >; }; - dcan1_pins_sleep: dcan1_pins_sleep { + dcan1_pins_sleep: dcan1-sleep-pins { pinctrl-single,pins = < DRA7XX_CORE_IOPAD(0x37d0, MUX_MODE15 | PULL_UP) /* dcan1_tx.off */ DRA7XX_CORE_IOPAD(0x3818, MUX_MODE15 | PULL_UP) /* wakeup0.off */ diff --git a/arch/arm/boot/dts/dra72-evm-revc.dts b/arch/arm/boot/dts/ti/omap/dra72-evm-revc.dts similarity index 100% rename from arch/arm/boot/dts/dra72-evm-revc.dts rename to arch/arm/boot/dts/ti/omap/dra72-evm-revc.dts diff --git a/arch/arm/boot/dts/dra72-evm-tps65917.dtsi b/arch/arm/boot/dts/ti/omap/dra72-evm-tps65917.dtsi similarity index 100% rename from arch/arm/boot/dts/dra72-evm-tps65917.dtsi rename to arch/arm/boot/dts/ti/omap/dra72-evm-tps65917.dtsi diff --git a/arch/arm/boot/dts/dra72-evm.dts b/arch/arm/boot/dts/ti/omap/dra72-evm.dts similarity index 100% rename from arch/arm/boot/dts/dra72-evm.dts rename to arch/arm/boot/dts/ti/omap/dra72-evm.dts diff --git a/arch/arm/boot/dts/dra72x-mmc-iodelay.dtsi b/arch/arm/boot/dts/ti/omap/dra72x-mmc-iodelay.dtsi similarity index 97% rename from arch/arm/boot/dts/dra72x-mmc-iodelay.dtsi rename to arch/arm/boot/dts/ti/omap/dra72x-mmc-iodelay.dtsi index 34eea3c048bdfd9acc251416d2258b9020c3dd32..d006f1dfdeb57105490e4c29481725df06e5a6ad 100644 --- a/arch/arm/boot/dts/dra72x-mmc-iodelay.dtsi +++ b/arch/arm/boot/dts/ti/omap/dra72x-mmc-iodelay.dtsi @@ -32,7 +32,7 @@ */ &dra7_pmx_core { - mmc1_pins_default: mmc1_pins_default { + mmc1_pins_default: mmc1-default-pins { pinctrl-single,pins = < DRA7XX_CORE_IOPAD(0x3754, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_clk.clk */ DRA7XX_CORE_IOPAD(0x3758, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_cmd.cmd */ @@ -43,7 +43,7 @@ >; }; - mmc1_pins_sdr12: mmc1_pins_sdr12 { + mmc1_pins_sdr12: mmc1-sdr12-pins { pinctrl-single,pins = < DRA7XX_CORE_IOPAD(0x3754, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_clk.clk */ DRA7XX_CORE_IOPAD(0x3758, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_cmd.cmd */ @@ -54,7 +54,7 @@ >; }; - mmc1_pins_hs: mmc1_pins_hs { + mmc1_pins_hs: mmc1-hs-pins { pinctrl-single,pins = < DRA7XX_CORE_IOPAD(0x3754, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_clk.clk */ DRA7XX_CORE_IOPAD(0x3758, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_cmd.cmd */ @@ -65,7 +65,7 @@ >; }; - mmc1_pins_sdr25: mmc1_pins_sdr25 { + mmc1_pins_sdr25: mmc1-sdr25-pins { pinctrl-single,pins = < DRA7XX_CORE_IOPAD(0x3754, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_clk.clk */ DRA7XX_CORE_IOPAD(0x3758, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_cmd.cmd */ @@ -76,7 +76,7 @@ >; }; - mmc1_pins_sdr50: mmc1_pins_sdr50 { + mmc1_pins_sdr50: mmc1-sdr50-pins { pinctrl-single,pins = < DRA7XX_CORE_IOPAD(0x3754, PIN_INPUT_PULLUP | MUX_VIRTUAL_MODE15 | MUX_MODE0) /* mmc1_clk.clk */ DRA7XX_CORE_IOPAD(0x3758, PIN_INPUT_PULLUP | MUX_VIRTUAL_MODE15 | MUX_MODE0) /* mmc1_cmd.cmd */ @@ -87,7 +87,7 @@ >; }; - mmc1_pins_ddr50_rev10: mmc1_pins_ddr50_rev10 { + mmc1_pins_ddr50_rev10: mmc1-ddr50-rev10-pins { pinctrl-single,pins = < DRA7XX_CORE_IOPAD(0x3754, PIN_INPUT_PULLUP | MUX_VIRTUAL_MODE14 | MUX_MODE0) /* mmc1_clk.mmc1_clk */ DRA7XX_CORE_IOPAD(0x3758, PIN_INPUT_PULLUP | MUX_VIRTUAL_MODE14 | MUX_MODE0) /* mmc1_cmd.mmc1_cmd */ @@ -98,7 +98,7 @@ >; }; - mmc1_pins_ddr50_rev20: mmc1_pins_ddr50_rev20 { + mmc1_pins_ddr50_rev20: mmc1-ddr50-rev20-pins { pinctrl-single,pins = < DRA7XX_CORE_IOPAD(0x3754, PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE0) /* mmc1_clk.clk */ DRA7XX_CORE_IOPAD(0x3758, PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE0) /* mmc1_cmd.cmd */ @@ -109,7 +109,7 @@ >; }; - mmc1_pins_sdr104: mmc1_pins_sdr104 { + mmc1_pins_sdr104: mmc1-sdr104-pins { pinctrl-single,pins = < DRA7XX_CORE_IOPAD(0x3754, PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE0) /* mmc1_clk.clk */ DRA7XX_CORE_IOPAD(0x3758, PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE0) /* mmc1_cmd.cmd */ @@ -120,7 +120,7 @@ >; }; - mmc2_pins_default: mmc2_pins_default { + mmc2_pins_default: mmc2-default-pins { pinctrl-single,pins = < DRA7XX_CORE_IOPAD(0x349c, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a23.mmc2_clk */ DRA7XX_CORE_IOPAD(0x34b0, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_cs1.mmc2_cmd */ @@ -135,7 +135,7 @@ >; }; - mmc2_pins_hs: mmc2_pins_hs { + mmc2_pins_hs: mmc2-hs-pins { pinctrl-single,pins = < DRA7XX_CORE_IOPAD(0x349c, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a23.mmc2_clk */ DRA7XX_CORE_IOPAD(0x34b0, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_cs1.mmc2_cmd */ @@ -150,7 +150,7 @@ >; }; - mmc2_pins_ddr_rev10: mmc2_pins_ddr_rev10 { + mmc2_pins_ddr_rev10: mmc2-ddr-rev10-pins { pinctrl-single,pins = < DRA7XX_CORE_IOPAD(0x348c, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a19.mmc2_dat4 */ DRA7XX_CORE_IOPAD(0x3490, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a20.mmc2_dat5 */ @@ -165,7 +165,7 @@ >; }; - mmc2_pins_ddr_rev20: mmc2_pins_ddr_rev20 { + mmc2_pins_ddr_rev20: mmc2-ddr-rev20-pins { pinctrl-single,pins = < DRA7XX_CORE_IOPAD(0x349c, PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE1) /* gpmc_a23.mmc2_clk */ DRA7XX_CORE_IOPAD(0x34b0, PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE1) /* gpmc_cs1.mmc2_cmd */ @@ -180,7 +180,7 @@ >; }; - mmc2_pins_hs200: mmc2_pins_hs200 { + mmc2_pins_hs200: mmc2-hs200-pins { pinctrl-single,pins = < DRA7XX_CORE_IOPAD(0x349c, PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE1) /* gpmc_a23.mmc2_clk */ DRA7XX_CORE_IOPAD(0x34b0, PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE1) /* gpmc_cs1.mmc2_cmd */ @@ -195,7 +195,7 @@ >; }; - mmc4_pins_default: mmc4_pins_default { + mmc4_pins_default: mmc4-default-pins { pinctrl-single,pins = < DRA7XX_CORE_IOPAD(0x37e8, PIN_INPUT_PULLUP | MUX_MODE3) /* uart1_ctsn.mmc4_clk */ DRA7XX_CORE_IOPAD(0x37ec, PIN_INPUT_PULLUP | MUX_MODE3) /* uart1_rtsn.mmc4_cmd */ diff --git a/arch/arm/boot/dts/dra72x.dtsi b/arch/arm/boot/dts/ti/omap/dra72x.dtsi similarity index 100% rename from arch/arm/boot/dts/dra72x.dtsi rename to arch/arm/boot/dts/ti/omap/dra72x.dtsi diff --git a/arch/arm/boot/dts/dra74-ipu-dsp-common.dtsi b/arch/arm/boot/dts/ti/omap/dra74-ipu-dsp-common.dtsi similarity index 100% rename from arch/arm/boot/dts/dra74-ipu-dsp-common.dtsi rename to arch/arm/boot/dts/ti/omap/dra74-ipu-dsp-common.dtsi diff --git a/arch/arm/boot/dts/dra74x-mmc-iodelay.dtsi b/arch/arm/boot/dts/ti/omap/dra74x-mmc-iodelay.dtsi similarity index 97% rename from arch/arm/boot/dts/dra74x-mmc-iodelay.dtsi rename to arch/arm/boot/dts/ti/omap/dra74x-mmc-iodelay.dtsi index b9d040135c5faa6fa6277c6bce5de2eaea95e741..e2fdb0702f5c9b0c1a0c98e29168b8f36c425c72 100644 --- a/arch/arm/boot/dts/dra74x-mmc-iodelay.dtsi +++ b/arch/arm/boot/dts/ti/omap/dra74x-mmc-iodelay.dtsi @@ -30,7 +30,7 @@ */ &dra7_pmx_core { - mmc1_pins_default: mmc1_pins_default { + mmc1_pins_default: mmc1-default-pins { pinctrl-single,pins = < DRA7XX_CORE_IOPAD(0x3754, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_clk.clk */ DRA7XX_CORE_IOPAD(0x3758, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_cmd.cmd */ @@ -41,7 +41,7 @@ >; }; - mmc1_pins_sdr12: mmc1_pins_sdr12 { + mmc1_pins_sdr12: mmc1-sdr12-pins { pinctrl-single,pins = < DRA7XX_CORE_IOPAD(0x3754, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_clk.clk */ DRA7XX_CORE_IOPAD(0x3758, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_cmd.cmd */ @@ -52,7 +52,7 @@ >; }; - mmc1_pins_hs: mmc1_pins_hs { + mmc1_pins_hs: mmc1-hs-pins { pinctrl-single,pins = < DRA7XX_CORE_IOPAD(0x3754, PIN_INPUT_PULLUP | MUX_VIRTUAL_MODE11 | MUX_MODE0) /* mmc1_clk.clk */ DRA7XX_CORE_IOPAD(0x3758, PIN_INPUT_PULLUP | MUX_VIRTUAL_MODE11 | MUX_MODE0) /* mmc1_cmd.cmd */ @@ -63,7 +63,7 @@ >; }; - mmc1_pins_sdr25: mmc1_pins_sdr25 { + mmc1_pins_sdr25: mmc1-sdr25-pins { pinctrl-single,pins = < DRA7XX_CORE_IOPAD(0x3754, PIN_INPUT_PULLUP | MUX_VIRTUAL_MODE11 | MUX_MODE0) /* mmc1_clk.clk */ DRA7XX_CORE_IOPAD(0x3758, PIN_INPUT_PULLUP | MUX_VIRTUAL_MODE11 | MUX_MODE0) /* mmc1_cmd.cmd */ @@ -74,7 +74,7 @@ >; }; - mmc1_pins_sdr50: mmc1_pins_sdr50 { + mmc1_pins_sdr50: mmc1-sdr50-pins { pinctrl-single,pins = < DRA7XX_CORE_IOPAD(0x3754, PIN_INPUT_PULLUP | MUX_VIRTUAL_MODE10 | MUX_MODE0) /* mmc1_clk.clk */ DRA7XX_CORE_IOPAD(0x3758, PIN_INPUT_PULLUP | MUX_VIRTUAL_MODE10 | MUX_MODE0) /* mmc1_cmd.cmd */ @@ -85,7 +85,7 @@ >; }; - mmc1_pins_ddr50: mmc1_pins_ddr50 { + mmc1_pins_ddr50: mmc1-ddr50-pins { pinctrl-single,pins = < DRA7XX_CORE_IOPAD(0x3754, PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE0) /* mmc1_clk.clk */ DRA7XX_CORE_IOPAD(0x3758, PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE0) /* mmc1_cmd.cmd */ @@ -96,7 +96,7 @@ >; }; - mmc1_pins_sdr104: mmc1_pins_sdr104 { + mmc1_pins_sdr104: mmc1-sdr104-pins { pinctrl-single,pins = < DRA7XX_CORE_IOPAD(0x3754, PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE0) /* mmc1_clk.clk */ DRA7XX_CORE_IOPAD(0x3758, PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE0) /* mmc1_cmd.cmd */ @@ -107,7 +107,7 @@ >; }; - mmc2_pins_default: mmc2_pins_default { + mmc2_pins_default: mmc2-default-pins { pinctrl-single,pins = < DRA7XX_CORE_IOPAD(0x349c, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a23.mmc2_clk */ DRA7XX_CORE_IOPAD(0x34b0, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_cs1.mmc2_cmd */ @@ -122,7 +122,7 @@ >; }; - mmc2_pins_hs: mmc2_pins_hs { + mmc2_pins_hs: mmc2-hs-pins { pinctrl-single,pins = < DRA7XX_CORE_IOPAD(0x349c, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a23.mmc2_clk */ DRA7XX_CORE_IOPAD(0x34b0, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_cs1.mmc2_cmd */ @@ -137,7 +137,7 @@ >; }; - mmc2_pins_ddr_3_3v_rev11: mmc2_pins_ddr_3_3v_rev11 { + mmc2_pins_ddr_3_3v_rev11: mmc2-ddr-3-3v-rev11-pins { pinctrl-single,pins = < DRA7XX_CORE_IOPAD(0x349c, PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE1) /* gpmc_a23.mmc2_clk */ DRA7XX_CORE_IOPAD(0x34b0, PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE1) /* gpmc_cs1.mmc2_cmd */ @@ -152,7 +152,7 @@ >; }; - mmc2_pins_ddr_1_8v_rev11: mmc2_pins_ddr_1_8v_rev11 { + mmc2_pins_ddr_1_8v_rev11: mmc2-ddr-1-8v-rev11-pins { pinctrl-single,pins = < DRA7XX_CORE_IOPAD(0x349c, PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE1) /* gpmc_a23.mmc2_clk */ DRA7XX_CORE_IOPAD(0x34b0, PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE1) /* gpmc_cs1.mmc2_cmd */ @@ -167,7 +167,7 @@ >; }; - mmc2_pins_ddr_rev20: mmc2_pins_ddr_rev20 { + mmc2_pins_ddr_rev20: mmc2-ddr-rev20-pins { pinctrl-single,pins = < DRA7XX_CORE_IOPAD(0x349c, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a23.mmc2_clk */ DRA7XX_CORE_IOPAD(0x34b0, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_cs1.mmc2_cmd */ @@ -182,7 +182,7 @@ >; }; - mmc2_pins_hs200: mmc2_pins_hs200 { + mmc2_pins_hs200: mmc2-hs200-pins { pinctrl-single,pins = < DRA7XX_CORE_IOPAD(0x349c, PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE1) /* gpmc_a23.mmc2_clk */ DRA7XX_CORE_IOPAD(0x34b0, PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE1) /* gpmc_cs1.mmc2_cmd */ @@ -197,7 +197,7 @@ >; }; - mmc4_pins_default: mmc4_pins_default { + mmc4_pins_default: mmc4-default-pins { pinctrl-single,pins = < DRA7XX_CORE_IOPAD(0x37e8, PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE3) /* uart1_ctsn.mmc4_clk */ DRA7XX_CORE_IOPAD(0x37ec, PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE3) /* uart1_rtsn.mmc4_cmd */ @@ -208,7 +208,7 @@ >; }; - mmc4_pins_hs: mmc4_pins_hs { + mmc4_pins_hs: mmc4-hs-pins { pinctrl-single,pins = < DRA7XX_CORE_IOPAD(0x37e8, PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE3) /* uart1_ctsn.mmc4_clk */ DRA7XX_CORE_IOPAD(0x37ec, PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE3) /* uart1_rtsn.mmc4_cmd */ @@ -219,7 +219,7 @@ >; }; - mmc3_pins_default: mmc3_pins_default { + mmc3_pins_default: mmc3-default-pins { pinctrl-single,pins = < DRA7XX_CORE_IOPAD(0x377c, (PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE0)) /* mmc3_clk.mmc3_clk */ DRA7XX_CORE_IOPAD(0x3780, (PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE0)) /* mmc3_cmd.mmc3_cmd */ @@ -230,7 +230,7 @@ >; }; - mmc3_pins_hs: mmc3_pins_hs { + mmc3_pins_hs: mmc3-hs-pins { pinctrl-single,pins = < DRA7XX_CORE_IOPAD(0x377c, (PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE0)) /* mmc3_clk.mmc3_clk */ DRA7XX_CORE_IOPAD(0x3780, (PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE0)) /* mmc3_cmd.mmc3_cmd */ @@ -241,7 +241,7 @@ >; }; - mmc3_pins_sdr12: mmc3_pins_sdr12 { + mmc3_pins_sdr12: mmc3-sdr12-pins { pinctrl-single,pins = < DRA7XX_CORE_IOPAD(0x377c, (PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE0)) /* mmc3_clk.mmc3_clk */ DRA7XX_CORE_IOPAD(0x3780, (PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE0)) /* mmc3_cmd.mmc3_cmd */ @@ -252,7 +252,7 @@ >; }; - mmc3_pins_sdr25: mmc3_pins_sdr25 { + mmc3_pins_sdr25: mmc3-sdr25-pins { pinctrl-single,pins = < DRA7XX_CORE_IOPAD(0x377c, (PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE0)) /* mmc3_clk.mmc3_clk */ DRA7XX_CORE_IOPAD(0x3780, (PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE0)) /* mmc3_cmd.mmc3_cmd */ @@ -263,7 +263,7 @@ >; }; - mmc3_pins_sdr50: mmc3_pins_sdr50 { + mmc3_pins_sdr50: mmc3-sdr50-pins { pinctrl-single,pins = < DRA7XX_CORE_IOPAD(0x377c, (PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE0)) /* mmc3_clk.mmc3_clk */ DRA7XX_CORE_IOPAD(0x3780, (PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE0)) /* mmc3_cmd.mmc3_cmd */ @@ -274,7 +274,7 @@ >; }; - mmc4_pins_sdr12: mmc4_pins_sdr12 { + mmc4_pins_sdr12: mmc4-sdr12-pins { pinctrl-single,pins = < DRA7XX_CORE_IOPAD(0x37e8, PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE3) /* uart1_ctsn.mmc4_clk */ DRA7XX_CORE_IOPAD(0x37ec, PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE3) /* uart1_rtsn.mmc4_cmd */ @@ -285,7 +285,7 @@ >; }; - mmc4_pins_sdr25: mmc4_pins_sdr25 { + mmc4_pins_sdr25: mmc4-sdr25-pins { pinctrl-single,pins = < DRA7XX_CORE_IOPAD(0x37e8, PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE3) /* uart1_ctsn.mmc4_clk */ DRA7XX_CORE_IOPAD(0x37ec, PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE3) /* uart1_rtsn.mmc4_cmd */ diff --git a/arch/arm/boot/dts/dra74x-p.dtsi b/arch/arm/boot/dts/ti/omap/dra74x-p.dtsi similarity index 100% rename from arch/arm/boot/dts/dra74x-p.dtsi rename to arch/arm/boot/dts/ti/omap/dra74x-p.dtsi diff --git a/arch/arm/boot/dts/dra74x.dtsi b/arch/arm/boot/dts/ti/omap/dra74x.dtsi similarity index 100% rename from arch/arm/boot/dts/dra74x.dtsi rename to arch/arm/boot/dts/ti/omap/dra74x.dtsi diff --git a/arch/arm/boot/dts/dra76-evm.dts b/arch/arm/boot/dts/ti/omap/dra76-evm.dts similarity index 100% rename from arch/arm/boot/dts/dra76-evm.dts rename to arch/arm/boot/dts/ti/omap/dra76-evm.dts diff --git a/arch/arm/boot/dts/dra76x-mmc-iodelay.dtsi b/arch/arm/boot/dts/ti/omap/dra76x-mmc-iodelay.dtsi similarity index 98% rename from arch/arm/boot/dts/dra76x-mmc-iodelay.dtsi rename to arch/arm/boot/dts/ti/omap/dra76x-mmc-iodelay.dtsi index fdca48186916097692406f8518e2af96765a5ce6..4690554dfa6e224b97c1ef8a8072675c9dfe0b43 100644 --- a/arch/arm/boot/dts/dra76x-mmc-iodelay.dtsi +++ b/arch/arm/boot/dts/ti/omap/dra76x-mmc-iodelay.dtsi @@ -27,7 +27,7 @@ */ &dra7_pmx_core { - mmc1_pins_default: mmc1_pins_default { + mmc1_pins_default: mmc1-default-pins { pinctrl-single,pins = < DRA7XX_CORE_IOPAD(0x3754, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_clk.clk */ DRA7XX_CORE_IOPAD(0x3758, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_cmd.cmd */ @@ -38,7 +38,7 @@ >; }; - mmc1_pins_hs: mmc1_pins_hs { + mmc1_pins_hs: mmc1-hs-pins { pinctrl-single,pins = < DRA7XX_CORE_IOPAD(0x3754, PIN_INPUT_PULLUP | MUX_VIRTUAL_MODE11 | MUX_MODE0) /* mmc1_clk.clk */ DRA7XX_CORE_IOPAD(0x3758, PIN_INPUT_PULLUP | MUX_VIRTUAL_MODE11 | MUX_MODE0) /* mmc1_cmd.cmd */ @@ -49,7 +49,7 @@ >; }; - mmc1_pins_sdr50: mmc1_pins_sdr50 { + mmc1_pins_sdr50: mmc1-sdr50-pins { pinctrl-single,pins = < DRA7XX_CORE_IOPAD(0x3754, PIN_INPUT_PULLUP | MUX_VIRTUAL_MODE10 | MUX_MODE0) /* mmc1_clk.clk */ DRA7XX_CORE_IOPAD(0x3758, PIN_INPUT_PULLUP | MUX_VIRTUAL_MODE10 | MUX_MODE0) /* mmc1_cmd.cmd */ @@ -60,7 +60,7 @@ >; }; - mmc1_pins_ddr50: mmc1_pins_ddr50 { + mmc1_pins_ddr50: mmc1-ddr50-pins { pinctrl-single,pins = < DRA7XX_CORE_IOPAD(0x3754, PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE0) /* mmc1_clk.clk */ DRA7XX_CORE_IOPAD(0x3758, PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE0) /* mmc1_cmd.cmd */ @@ -71,7 +71,7 @@ >; }; - mmc2_pins_default: mmc2_pins_default { + mmc2_pins_default: mmc2-default-pins { pinctrl-single,pins = < DRA7XX_CORE_IOPAD(0x349c, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a23.mmc2_clk */ DRA7XX_CORE_IOPAD(0x34b0, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_cs1.mmc2_cmd */ @@ -86,7 +86,7 @@ >; }; - mmc2_pins_hs200: mmc2_pins_hs200 { + mmc2_pins_hs200: mmc2-hs200-pins { pinctrl-single,pins = < DRA7XX_CORE_IOPAD(0x349c, PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE1) /* gpmc_a23.mmc2_clk */ DRA7XX_CORE_IOPAD(0x34b0, PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE1) /* gpmc_cs1.mmc2_cmd */ @@ -101,7 +101,7 @@ >; }; - mmc3_pins_default: mmc3_pins_default { + mmc3_pins_default: mmc3-default-pins { pinctrl-single,pins = < DRA7XX_CORE_IOPAD(0x377c, (PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE0)) /* mmc3_clk.mmc3_clk */ DRA7XX_CORE_IOPAD(0x3780, (PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE0)) /* mmc3_cmd.mmc3_cmd */ @@ -112,7 +112,7 @@ >; }; - mmc4_pins_hs: mmc4_pins_hs { + mmc4_pins_hs: mmc4-hs-pins { pinctrl-single,pins = < DRA7XX_CORE_IOPAD(0x37e8, PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE3) /* uart1_ctsn.mmc4_clk */ DRA7XX_CORE_IOPAD(0x37ec, PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE3) /* uart1_rtsn.mmc4_cmd */ diff --git a/arch/arm/boot/dts/dra76x.dtsi b/arch/arm/boot/dts/ti/omap/dra76x.dtsi similarity index 100% rename from arch/arm/boot/dts/dra76x.dtsi rename to arch/arm/boot/dts/ti/omap/dra76x.dtsi diff --git a/arch/arm/boot/dts/dra7xx-clocks.dtsi b/arch/arm/boot/dts/ti/omap/dra7xx-clocks.dtsi similarity index 100% rename from arch/arm/boot/dts/dra7xx-clocks.dtsi rename to arch/arm/boot/dts/ti/omap/dra7xx-clocks.dtsi diff --git a/arch/arm/boot/dts/elpida_ecb240abacn.dtsi b/arch/arm/boot/dts/ti/omap/elpida_ecb240abacn.dtsi similarity index 100% rename from arch/arm/boot/dts/elpida_ecb240abacn.dtsi rename to arch/arm/boot/dts/ti/omap/elpida_ecb240abacn.dtsi diff --git a/arch/arm/boot/dts/logicpd-som-lv-35xx-devkit.dts b/arch/arm/boot/dts/ti/omap/logicpd-som-lv-35xx-devkit.dts similarity index 96% rename from arch/arm/boot/dts/logicpd-som-lv-35xx-devkit.dts rename to arch/arm/boot/dts/ti/omap/logicpd-som-lv-35xx-devkit.dts index 3240c67e0c3920c802425b3a947a5bc109d81973..c1705f6f3d108afecbb4afd45978f356ad5848c2 100644 --- a/arch/arm/boot/dts/logicpd-som-lv-35xx-devkit.dts +++ b/arch/arm/boot/dts/ti/omap/logicpd-som-lv-35xx-devkit.dts @@ -15,7 +15,7 @@ &omap3_pmx_core2 { pinctrl-names = "default"; pinctrl-0 = <&hsusb2_2_pins>; - hsusb2_2_pins: pinmux_hsusb2_2_pins { + hsusb2_2_pins: hsusb2-2-pins { pinctrl-single,pins = < OMAP3430_CORE2_IOPAD(0x25f0, PIN_OUTPUT | MUX_MODE3) /* etk_d10.hsusb2_clk */ OMAP3430_CORE2_IOPAD(0x25f2, PIN_OUTPUT | MUX_MODE3) /* etk_d11.hsusb2_stp */ diff --git a/arch/arm/boot/dts/logicpd-som-lv-37xx-devkit.dts b/arch/arm/boot/dts/ti/omap/logicpd-som-lv-37xx-devkit.dts similarity index 96% rename from arch/arm/boot/dts/logicpd-som-lv-37xx-devkit.dts rename to arch/arm/boot/dts/ti/omap/logicpd-som-lv-37xx-devkit.dts index c757f0d7781c1b093717cb538c701d009131a6c2..9dbbcc7ced7ce5cff222560a91c402db5dde2416 100644 --- a/arch/arm/boot/dts/logicpd-som-lv-37xx-devkit.dts +++ b/arch/arm/boot/dts/ti/omap/logicpd-som-lv-37xx-devkit.dts @@ -15,7 +15,7 @@ &omap3_pmx_core2 { pinctrl-names = "default"; pinctrl-0 = <&hsusb2_2_pins>; - hsusb2_2_pins: pinmux_hsusb2_2_pins { + hsusb2_2_pins: hsusb2-2-pins { pinctrl-single,pins = < OMAP3630_CORE2_IOPAD(0x25f0, PIN_OUTPUT | MUX_MODE3) /* etk_d10.hsusb2_clk */ OMAP3630_CORE2_IOPAD(0x25f2, PIN_OUTPUT | MUX_MODE3) /* etk_d11.hsusb2_stp */ diff --git a/arch/arm/boot/dts/logicpd-som-lv-baseboard.dtsi b/arch/arm/boot/dts/ti/omap/logicpd-som-lv-baseboard.dtsi similarity index 95% rename from arch/arm/boot/dts/logicpd-som-lv-baseboard.dtsi rename to arch/arm/boot/dts/ti/omap/logicpd-som-lv-baseboard.dtsi index 7d0468a237818ceca1ef0ab9c842907815d937da..690f2ad50c653f8838764f7d6ebea796187412d0 100644 --- a/arch/arm/boot/dts/logicpd-som-lv-baseboard.dtsi +++ b/arch/arm/boot/dts/ti/omap/logicpd-som-lv-baseboard.dtsi @@ -141,25 +141,25 @@ }; &omap3_pmx_core { - gpio_key_pins: pinmux_gpio_key_pins { + gpio_key_pins: gpio-key-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x212e, PIN_INPUT_PULLUP | MUX_MODE4) /* cam_xclkb.gpio_111 / uP_GPIO_3*/ >; }; - led_pins: pinmux_led_pins { + led_pins: led-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x215e, PIN_OUTPUT_PULLUP | MUX_MODE4) /* sdmmc2_dat1.gpio_133 / uP_GPIO_0 */ >; }; - lan9221_pins: pinmux_lan9221_pins { + lan9221_pins: lan9221-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x2184, PIN_INPUT_PULLUP | MUX_MODE4) /* mcbsp4_clkx.gpio_152 */ >; }; - mmc1_pins: pinmux_mmc1_pins { + mmc1_pins: mmc1-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x2144, PIN_OUTPUT | MUX_MODE0) /* sdmmc1_clk.sdmmc1_clk */ OMAP3_CORE1_IOPAD(0x2146, PIN_INPUT | MUX_MODE0) /* sdmmc1_cmd.sdmmc1_cmd */ @@ -172,13 +172,13 @@ >; }; - lcd_enable_pin: pinmux_lcd_enable_pin { + lcd_enable_pin: lcd-enable-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x218a, PIN_OUTPUT | PIN_OFF_OUTPUT_LOW | MUX_MODE4) /* mcbsp4_fs.gpio_155 */ >; }; - dss_dpi_pins1: pinmux_dss_dpi_pins1 { + dss_dpi_pins1: dss-dpi1-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x20d4, PIN_OUTPUT_PULLDOWN | PIN_OFF_OUTPUT_LOW | MUX_MODE0) /* dss_pclk.dss_pclk */ OMAP3_CORE1_IOPAD(0x20d6, PIN_OUTPUT_PULLDOWN | PIN_OFF_OUTPUT_LOW | MUX_MODE0) /* dss_hsync.dss_hsync */ @@ -206,13 +206,13 @@ }; &omap3_pmx_wkup { - led_pins_wkup: pinmux_led_pins_wkup { + led_pins_wkup: led-wkup-pins { pinctrl-single,pins = < OMAP3_WKUP_IOPAD(0x2a24, PIN_OUTPUT_PULLUP | MUX_MODE4) /* jtag_emu0.gpio_11 / uP_GPIO_1 */ >; }; - backlight_pins: pinmux_backlight_pins { + backlight_pins: backlight-pins { pinctrl-single,pins = < OMAP3_WKUP_IOPAD(0x2a16, PIN_OUTPUT | PIN_OFF_OUTPUT_LOW | MUX_MODE4) /* sys_boot6.gpio_8 */ >; diff --git a/arch/arm/boot/dts/logicpd-som-lv.dtsi b/arch/arm/boot/dts/ti/omap/logicpd-som-lv.dtsi similarity index 95% rename from arch/arm/boot/dts/logicpd-som-lv.dtsi rename to arch/arm/boot/dts/ti/omap/logicpd-som-lv.dtsi index 9ba0ea4eb48a8e43efa44ff1233657187fc579fa..c0e6b73fa472db9648911e06a7bcc80ecc650f9b 100644 --- a/arch/arm/boot/dts/logicpd-som-lv.dtsi +++ b/arch/arm/boot/dts/ti/omap/logicpd-som-lv.dtsi @@ -157,7 +157,7 @@ &omap3_pmx_core { - mmc3_pins: pinmux_mm3_pins { + mmc3_pins: mm3-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x2164, PIN_INPUT_PULLUP | MUX_MODE3) /* sdmmc2_dat4.sdmmc3_dat0 */ OMAP3_CORE1_IOPAD(0x2166, PIN_INPUT_PULLUP | MUX_MODE3) /* sdmmc2_dat5.sdmmc3_dat1 */ @@ -167,7 +167,7 @@ OMAP3_CORE1_IOPAD(0x21d2, PIN_INPUT_PULLUP | MUX_MODE3) /* mcspi1_cs2.sdmmc_clk */ >; }; - mcbsp2_pins: pinmux_mcbsp2_pins { + mcbsp2_pins: mcbsp2-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x213c, PIN_INPUT | MUX_MODE0) /* mcbsp2_fsx */ OMAP3_CORE1_IOPAD(0x213e, PIN_INPUT | MUX_MODE0) /* mcbsp2_clkx */ @@ -175,7 +175,7 @@ OMAP3_CORE1_IOPAD(0x2142, PIN_OUTPUT | MUX_MODE0) /* mcbsp2_dx */ >; }; - uart2_pins: pinmux_uart2_pins { + uart2_pins: uart2-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x2174, PIN_INPUT | MUX_MODE0) /* uart2_cts.uart2_cts */ OMAP3_CORE1_IOPAD(0x2176, PIN_OUTPUT | MUX_MODE0) /* uart2_rts .uart2_rts*/ @@ -184,7 +184,7 @@ OMAP3_CORE1_IOPAD(0x2198, PIN_OUTPUT | MUX_MODE4) /* GPIO_162,BT_EN */ >; }; - mcspi1_pins: pinmux_mcspi1_pins { + mcspi1_pins: mcspi1-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x21c8, PIN_INPUT | MUX_MODE0) /* mcspi1_clk.mcspi1_clk */ OMAP3_CORE1_IOPAD(0x21ca, PIN_OUTPUT | MUX_MODE0) /* mcspi1_simo.mcspi1_simo */ @@ -193,7 +193,7 @@ >; }; - hsusb2_pins: pinmux_hsusb2_pins { + hsusb2_pins: hsusb2-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x21d4, PIN_INPUT_PULLDOWN | MUX_MODE3) /* mcspi1_cs3.hsusb2_data2 */ OMAP3_CORE1_IOPAD(0x21d6, PIN_INPUT_PULLDOWN | MUX_MODE3) /* mcspi2_clk.hsusb2_data7 */ @@ -204,7 +204,7 @@ >; }; - hsusb_otg_pins: pinmux_hsusb_otg_pins { + hsusb_otg_pins: hsusb-otg-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x21a2, PIN_INPUT | MUX_MODE0) /* hsusb0_clk.hsusb0_clk */ OMAP3_CORE1_IOPAD(0x21a4, PIN_OUTPUT | MUX_MODE0) /* hsusb0_stp.hsusb0_stp */ @@ -221,7 +221,7 @@ >; }; - i2c1_pins: pinmux_i2c1_pins { + i2c1_pins: i2c1-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x21ba, PIN_INPUT | MUX_MODE0) /* i2c1_scl.i2c1_scl */ OMAP3_CORE1_IOPAD(0x21bc, PIN_INPUT | MUX_MODE0) /* i2c1_sda.i2c1_sda */ @@ -229,21 +229,21 @@ >; }; - i2c2_pins: pinmux_i2c2_pins { + i2c2_pins: i2c2-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x21be, PIN_INPUT | MUX_MODE0) /* i2c2_scl */ OMAP3_CORE1_IOPAD(0x21c0, PIN_INPUT | MUX_MODE0) /* i2c2_sda */ >; }; - i2c3_pins: pinmux_i2c3_pins { + i2c3_pins: i2c3-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x21c2, PIN_INPUT | MUX_MODE0) /* i2c3_scl */ OMAP3_CORE1_IOPAD(0x21c4, PIN_INPUT | MUX_MODE0) /* i2c3_sda */ >; }; - tsc2004_pins: pinmux_tsc2004_pins { + tsc2004_pins: tsc2004-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x2186, PIN_INPUT | MUX_MODE4) /* mcbsp4_dr.gpio_153 */ >; @@ -252,12 +252,12 @@ &omap3_pmx_wkup { - hsusb2_reset_pin: pinmux_hsusb1_reset_pin { + hsusb2_reset_pin: hsusb1-reset-pins { pinctrl-single,pins = < OMAP3_WKUP_IOPAD(0x2a0e, PIN_OUTPUT | MUX_MODE4) /* sys_boot2.gpio_4 */ >; }; - wl127x_gpio: pinmux_wl127x_gpio_pin { + wl127x_gpio: wl127x-gpio-pins { pinctrl-single,pins = < OMAP3_WKUP_IOPAD(0x2a0a, PIN_INPUT | MUX_MODE4) /* sys_boot0.gpio_2 */ OMAP3_WKUP_IOPAD(0x2a0c, PIN_OUTPUT | MUX_MODE4) /* sys_boot1.gpio_3 */ diff --git a/arch/arm/boot/dts/logicpd-torpedo-35xx-devkit.dts b/arch/arm/boot/dts/ti/omap/logicpd-torpedo-35xx-devkit.dts similarity index 92% rename from arch/arm/boot/dts/logicpd-torpedo-35xx-devkit.dts rename to arch/arm/boot/dts/ti/omap/logicpd-torpedo-35xx-devkit.dts index cb08aa62d96715fa9d24f3def3b268d7d037bf5f..eaa583fdc3d6b48b817c96f7d66b450801e79d5c 100644 --- a/arch/arm/boot/dts/logicpd-torpedo-35xx-devkit.dts +++ b/arch/arm/boot/dts/ti/omap/logicpd-torpedo-35xx-devkit.dts @@ -13,7 +13,7 @@ }; &omap3_pmx_core { - isp1763_pins: pinmux_isp1763_pins { + isp1763_pins: isp1763-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x2154, PIN_INPUT_PULLUP | MUX_MODE4) /* sdmmc1_dat6.gpio_128 */ >; diff --git a/arch/arm/boot/dts/logicpd-torpedo-37xx-devkit-28.dts b/arch/arm/boot/dts/ti/omap/logicpd-torpedo-37xx-devkit-28.dts similarity index 100% rename from arch/arm/boot/dts/logicpd-torpedo-37xx-devkit-28.dts rename to arch/arm/boot/dts/ti/omap/logicpd-torpedo-37xx-devkit-28.dts diff --git a/arch/arm/boot/dts/logicpd-torpedo-37xx-devkit.dts b/arch/arm/boot/dts/ti/omap/logicpd-torpedo-37xx-devkit.dts similarity index 96% rename from arch/arm/boot/dts/logicpd-torpedo-37xx-devkit.dts rename to arch/arm/boot/dts/ti/omap/logicpd-torpedo-37xx-devkit.dts index 07ea822fe40528fd521ce856b56c4aaa43db058a..533ce7ce387a54891b8e0ee25e8ba79fa554d0f2 100644 --- a/arch/arm/boot/dts/logicpd-torpedo-37xx-devkit.dts +++ b/arch/arm/boot/dts/ti/omap/logicpd-torpedo-37xx-devkit.dts @@ -65,7 +65,7 @@ }; &omap3_pmx_core { - mmc3_pins: pinmux_mm3_pins { + mmc3_pins: mm3-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x2164, PIN_INPUT_PULLUP | MUX_MODE3) /* sdmmc2_dat4.sdmmc3_dat0 */ OMAP3_CORE1_IOPAD(0x2166, PIN_INPUT_PULLUP | MUX_MODE3) /* sdmmc2_dat5.sdmmc3_dat1 */ @@ -78,7 +78,7 @@ }; &omap3_pmx_core2 { - mmc3_core2_pins: pinmux_mmc3_core2_pins { + mmc3_core2_pins: mmc3-core2-pins { pinctrl-single,pins = < OMAP3630_CORE2_IOPAD(0x25d8, PIN_INPUT_PULLUP | MUX_MODE2) /* etk_clk.sdmmc3_clk */ OMAP3630_CORE2_IOPAD(0x25da, PIN_INPUT_PULLUP | MUX_MODE2) /* etk_ctl.sdmmc3_cmd */ @@ -88,7 +88,7 @@ /* The gpio muxing between omap3530 and dm3730 is different for GPIO_128 */ &omap3_pmx_wkup { - isp1763_pins: pinmux_isp1763_pins { + isp1763_pins: isp1763-pins { pinctrl-single,pins = < OMAP3_WKUP_IOPAD(0x2a58, PIN_INPUT_PULLUP | MUX_MODE4) /* reserved.gpio_128 */ >; diff --git a/arch/arm/boot/dts/logicpd-torpedo-baseboard.dtsi b/arch/arm/boot/dts/ti/omap/logicpd-torpedo-baseboard.dtsi similarity index 96% rename from arch/arm/boot/dts/logicpd-torpedo-baseboard.dtsi rename to arch/arm/boot/dts/ti/omap/logicpd-torpedo-baseboard.dtsi index e0cbac500e1729ef096e6757312033998e4dd064..e0caed53981040a4d16dc196d666d628ed04140f 100644 --- a/arch/arm/boot/dts/logicpd-torpedo-baseboard.dtsi +++ b/arch/arm/boot/dts/ti/omap/logicpd-torpedo-baseboard.dtsi @@ -209,33 +209,33 @@ }; &omap3_pmx_core { - gpio_key_pins: pinmux_gpio_key_pins { + gpio_key_pins: gpio-key-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x21d6, PIN_INPUT_PULLUP | MUX_MODE4) /* mcspi2_clk.gpio_178 */ OMAP3_CORE1_IOPAD(0x21dc, PIN_INPUT_PULLUP | MUX_MODE4) /* mcspi2_cs0.gpio_181 */ >; }; - hdq_pins: hdq_pins { + hdq_pins: hdq-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x21c6, PIN_INPUT_PULLUP | MUX_MODE0) /* hdq_sio */ >; }; - pwm_pins: pinmux_pwm_pins { + pwm_pins: pwm-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x20B8, PIN_OUTPUT | PIN_OFF_OUTPUT_LOW | MUX_MODE3) /* gpmc_ncs5.gpt_10_pwm_evt */ >; }; - led_pins: pinmux_led_pins { + led_pins: led-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x21d8, PIN_OUTPUT | MUX_MODE4) /* gpio_179 */ OMAP3_CORE1_IOPAD(0x21da, PIN_OUTPUT | MUX_MODE4) /* gpio_180 */ >; }; - mmc1_pins: pinmux_mmc1_pins { + mmc1_pins: mmc1-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x2144, PIN_OUTPUT | MUX_MODE0) /* sdmmc1_clk.sdmmc1_clk */ OMAP3_CORE1_IOPAD(0x2146, PIN_INPUT | MUX_MODE0) /* sdmmc1_cmd.sdmmc1_cmd */ @@ -246,19 +246,19 @@ >; }; - tsc2004_pins: pinmux_tsc2004_pins { + tsc2004_pins: tsc2004-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x2186, PIN_INPUT | MUX_MODE4) /* mcbsp4_dr.gpio_153 */ >; }; - backlight_pins: pinmux_backlight_pins { + backlight_pins: backlight-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x2188, PIN_OUTPUT | PIN_OFF_OUTPUT_LOW | MUX_MODE4) /* mcbsp4_dx.gpio_154 */ >; }; - isp_pins: pinmux_isp_pins { + isp_pins: isp-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x210c, PIN_INPUT | MUX_MODE0) /* cam_hs.cam_hs */ OMAP3_CORE1_IOPAD(0x210e, PIN_INPUT | MUX_MODE0) /* cam_vs.cam_vs */ @@ -276,13 +276,13 @@ >; }; - panel_pwr_pins: pinmux_panel_pwr_pins { + panel_pwr_pins: panel-pwr-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x218a, PIN_OUTPUT | PIN_OFF_OUTPUT_LOW | MUX_MODE4) /* mcbsp4_fs.gpio_155 */ >; }; - dss_dpi_pins1: pinmux_dss_dpi_pins1 { + dss_dpi_pins1: dss-dpi1-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x20d4, PIN_OUTPUT_PULLDOWN | PIN_OFF_OUTPUT_LOW | MUX_MODE0) /* dss_pclk.dss_pclk */ OMAP3_CORE1_IOPAD(0x20d6, PIN_OUTPUT_PULLDOWN | PIN_OFF_OUTPUT_LOW | MUX_MODE0) /* dss_hsync.dss_hsync */ @@ -313,20 +313,20 @@ }; &omap3_pmx_wkup { - gpio_key_pins_wkup: pinmux_gpio_key_pins_wkup { + gpio_key_pins_wkup: gpio-key-wkup-pins { pinctrl-single,pins = < OMAP3_WKUP_IOPAD(0x2a0a, PIN_INPUT_PULLUP | MUX_MODE4) /* sys_boot0.gpio_2 */ OMAP3_WKUP_IOPAD(0x2a14, PIN_INPUT_PULLUP | MUX_MODE4) /* sys_boot5.gpio_7 */ >; }; - lan9221_pins: pinmux_lan9221_pins { + lan9221_pins: lan9221-pins { pinctrl-single,pins = < OMAP3_WKUP_IOPAD(0x2a5a, PIN_INPUT | MUX_MODE4) /* reserved.gpio_129 */ >; }; - mmc1_cd: pinmux_mmc1_cd { + mmc1_cd: mmc1-cd-pins { pinctrl-single,pins = < OMAP3_WKUP_IOPAD(0x2a54, PIN_INPUT_PULLUP | MUX_MODE4) /* reserved.gpio_127 */ >; diff --git a/arch/arm/boot/dts/logicpd-torpedo-som.dtsi b/arch/arm/boot/dts/ti/omap/logicpd-torpedo-som.dtsi similarity index 95% rename from arch/arm/boot/dts/logicpd-torpedo-som.dtsi rename to arch/arm/boot/dts/ti/omap/logicpd-torpedo-som.dtsi index 72b5af475d09c2a715dec335591db701cf6df85f..227699890890a6fb3ac4e637cd6b0f8199727061 100644 --- a/arch/arm/boot/dts/logicpd-torpedo-som.dtsi +++ b/arch/arm/boot/dts/ti/omap/logicpd-torpedo-som.dtsi @@ -111,7 +111,7 @@ }; &omap3_pmx_core { - mcbsp2_pins: pinmux_mcbsp2_pins { + mcbsp2_pins: mcbsp2-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x213c, PIN_INPUT | MUX_MODE0) /* mcbsp2_fsx */ OMAP3_CORE1_IOPAD(0x213e, PIN_INPUT | MUX_MODE0) /* mcbsp2_clkx */ @@ -119,7 +119,7 @@ OMAP3_CORE1_IOPAD(0x2142, PIN_OUTPUT | MUX_MODE0) /* mcbsp2_dx */ >; }; - uart2_pins: pinmux_uart2_pins { + uart2_pins: uart2-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x2174, PIN_INPUT | MUX_MODE0) /* uart2_cts.uart2_cts */ OMAP3_CORE1_IOPAD(0x2176, PIN_OUTPUT | MUX_MODE0) /* uart2_rts .uart2_rts*/ @@ -128,7 +128,7 @@ OMAP3_CORE1_IOPAD(0x2198, PIN_OUTPUT | MUX_MODE4) /* GPIO_162,BT_EN */ >; }; - mcspi1_pins: pinmux_mcspi1_pins { + mcspi1_pins: mcspi1-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x21c8, PIN_INPUT | MUX_MODE0) /* mcspi1_clk.mcspi1_clk */ OMAP3_CORE1_IOPAD(0x21ca, PIN_OUTPUT | MUX_MODE0) /* mcspi1_simo.mcspi1_simo */ @@ -136,7 +136,7 @@ OMAP3_CORE1_IOPAD(0x21ce, PIN_OUTPUT | MUX_MODE0) /* mcspi1_cs0.mcspi1_cs0 */ >; }; - hsusb_otg_pins: pinmux_hsusb_otg_pins { + hsusb_otg_pins: hsusb-otg-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x21a2, PIN_INPUT | MUX_MODE0) /* hsusb0_clk.hsusb0_clk */ OMAP3_CORE1_IOPAD(0x21a4, PIN_OUTPUT | MUX_MODE0) /* hsusb0_stp.hsusb0_stp */ @@ -153,19 +153,19 @@ OMAP3_CORE1_IOPAD(0x21b8, PIN_INPUT | MUX_MODE0) /* hsusb0_data7.hsusb0_data7 */ >; }; - i2c1_pins: pinmux_i2c1_pins { + i2c1_pins: i2c1-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x21ba, PIN_INPUT | MUX_MODE0) /* i2c1_scl.i2c1_scl */ OMAP3_CORE1_IOPAD(0x21bc, PIN_INPUT | MUX_MODE0) /* i2c1_sda.i2c1_sda */ >; }; - i2c2_pins: pinmux_i2c2_pins { + i2c2_pins: i2c2-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x21be, PIN_INPUT | MUX_MODE0) /* i2c2_scl */ OMAP3_CORE1_IOPAD(0x21c0, PIN_INPUT | MUX_MODE0) /* i2c2_sda */ >; }; - i2c3_pins: pinmux_i2c3_pins { + i2c3_pins: i2c3-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x21c2, PIN_INPUT | MUX_MODE0) /* i2c3_scl */ OMAP3_CORE1_IOPAD(0x21c4, PIN_INPUT | MUX_MODE0) /* i2c3_sda */ diff --git a/arch/arm/boot/dts/motorola-cpcap-mapphone.dtsi b/arch/arm/boot/dts/ti/omap/motorola-cpcap-mapphone.dtsi similarity index 100% rename from arch/arm/boot/dts/motorola-cpcap-mapphone.dtsi rename to arch/arm/boot/dts/ti/omap/motorola-cpcap-mapphone.dtsi diff --git a/arch/arm/boot/dts/motorola-mapphone-common.dtsi b/arch/arm/boot/dts/ti/omap/motorola-mapphone-common.dtsi similarity index 95% rename from arch/arm/boot/dts/motorola-mapphone-common.dtsi rename to arch/arm/boot/dts/ti/omap/motorola-mapphone-common.dtsi index f7cc8fc678fa5a76ee46c2164dafe47ca8979f23..091ba310053ebc6fb99424c136b7794efc4721b4 100644 --- a/arch/arm/boot/dts/motorola-mapphone-common.dtsi +++ b/arch/arm/boot/dts/ti/omap/motorola-mapphone-common.dtsi @@ -352,13 +352,13 @@ &omap4_pmx_core { /* hdmi_hpd.gpio_63 */ - hdmi_hpd_gpio: pinmux_hdmi_hpd_pins { + hdmi_hpd_gpio: hdmi-hpd-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x098, PIN_INPUT | MUX_MODE3) >; }; - hdq_pins: pinmux_hdq_pins { + hdq_pins: hdq-pins { pinctrl-single,pins = < /* 0x4a100120 hdq_sio.hdq_sio aa27 */ OMAP4_IOPAD(0x120, PIN_INPUT | MUX_MODE0) @@ -366,7 +366,7 @@ }; /* hdmi_cec.hdmi_cec, hdmi_scl.hdmi_scl, hdmi_sda.hdmi_sda */ - dss_hdmi_pins: pinmux_dss_hdmi_pins { + dss_hdmi_pins: dss-hdmi-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x09a, PIN_INPUT | MUX_MODE0) OMAP4_IOPAD(0x09c, PIN_INPUT | MUX_MODE0) @@ -380,7 +380,7 @@ * devices. Off mode value should be tested if we have off mode working * later on. */ - mmc3_pins: pinmux_mmc3_pins { + mmc3_pins: mmc3-pins { pinctrl-single,pins = < /* 0x4a10008e gpmc_wait2.gpio_100 d23 */ OMAP4_IOPAD(0x08e, PIN_INPUT | MUX_MODE3) @@ -406,40 +406,40 @@ }; /* gpmc_ncs0.gpio_50 */ - poweroff_gpio: pinmux_poweroff_pins { + poweroff_gpio: poweroff-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x074, PIN_OUTPUT_PULLUP | MUX_MODE3) >; }; /* kpd_row0.gpio_178 */ - tmp105_irq: pinmux_tmp105_irq { + tmp105_irq: tmp105-irq-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x18e, PIN_INPUT_PULLUP | MUX_MODE3) >; }; - usb_gpio_mux_sel1: pinmux_usb_gpio_mux_sel1_pins { + usb_gpio_mux_sel1: usb-gpio-mux-sel1-pins { /* gpio_60 */ pinctrl-single,pins = < OMAP4_IOPAD(0x088, PIN_OUTPUT | MUX_MODE3) >; }; - touchscreen_pins: pinmux_touchscreen_pins { + touchscreen_pins: touchscreen-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x180, PIN_OUTPUT | MUX_MODE3) OMAP4_IOPAD(0x1a0, PIN_INPUT_PULLUP | MUX_MODE3) >; }; - als_proximity_pins: pinmux_als_proximity_pins { + als_proximity_pins: als-proximity-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x18c, PIN_INPUT_PULLUP | MUX_MODE3) >; }; - usb_mdm6600_pins: pinmux_usb_mdm6600_pins { + usb_mdm6600_pins: usb-mdm6600-pins { pinctrl-single,pins = < /* enable 0x4a1000d8 usbb1_ulpitll_dat7.gpio_95 ag16 */ OMAP4_IOPAD(0x0d8, PIN_INPUT | MUX_MODE3) @@ -476,7 +476,7 @@ >; }; - usb_ulpi_pins: pinmux_usb_ulpi_pins { + usb_ulpi_pins: usb-ulpi-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x196, MUX_MODE7) OMAP4_IOPAD(0x198, MUX_MODE7) @@ -496,7 +496,7 @@ }; /* usb0_otg_dp and usb0_otg_dm */ - usb_utmi_pins: pinmux_usb_utmi_pins { + usb_utmi_pins: usb-utmi-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x196, PIN_INPUT | MUX_MODE0) OMAP4_IOPAD(0x198, PIN_INPUT | MUX_MODE0) @@ -521,7 +521,7 @@ * when not used. If needed, we can add rts pin remux later based * on power measurements. */ - uart1_pins: pinmux_uart1_pins { + uart1_pins: uart1-pins { pinctrl-single,pins = < /* 0x4a10013c mcspi1_cs2.uart1_cts ag23 */ OMAP4_IOPAD(0x13c, PIN_INPUT_PULLUP | MUX_MODE1) @@ -538,7 +538,7 @@ }; /* uart3_tx_irtx and uart3_rx_irrx */ - uart3_pins: pinmux_uart3_pins { + uart3_pins: uart3-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x196, MUX_MODE7) OMAP4_IOPAD(0x198, MUX_MODE7) @@ -557,7 +557,7 @@ >; }; - uart4_pins: pinmux_uart4_pins { + uart4_pins: uart4-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x15c, PIN_INPUT | MUX_MODE0) /* uart4_rx */ OMAP4_IOPAD(0x15e, PIN_OUTPUT | MUX_MODE0) /* uart4_tx */ @@ -566,7 +566,7 @@ >; }; - mcbsp2_pins: pinmux_mcbsp2_pins { + mcbsp2_pins: mcbsp2-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x0f6, PIN_INPUT | MUX_MODE0) /* abe_mcbsp2_clkx */ OMAP4_IOPAD(0x0f8, PIN_INPUT | MUX_MODE0) /* abe_mcbsp2_dr */ @@ -575,7 +575,7 @@ >; }; - mcbsp3_pins: pinmux_mcbsp3_pins { + mcbsp3_pins: mcbsp3-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x106, PIN_INPUT | MUX_MODE1) /* abe_mcbsp3_dr */ OMAP4_IOPAD(0x108, PIN_OUTPUT | MUX_MODE1) /* abe_mcbsp3_dx */ @@ -584,13 +584,13 @@ >; }; - vibrator_direction_pin: pinmux_vibrator_direction_pin { + vibrator_direction_pin: vibrator-direction-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x1ce, PIN_OUTPUT | MUX_MODE1) /* dmtimer8_pwm_evt (gpio_27) */ >; }; - vibrator_enable_pin: pinmux_vibrator_enable_pin { + vibrator_enable_pin: vibrator-enable-pins { pinctrl-single,pins = < OMAP4_IOPAD(0X1d0, PIN_OUTPUT | MUX_MODE1) /* dmtimer9_pwm_evt (gpio_28) */ >; @@ -598,7 +598,7 @@ }; &omap4_pmx_wkup { - usb_gpio_mux_sel2: pinmux_usb_gpio_mux_sel2_pins { + usb_gpio_mux_sel2: usb-gpio-mux-sel2-pins { /* gpio_wk0 */ pinctrl-single,pins = < OMAP4_IOPAD(0x040, PIN_OUTPUT_PULLDOWN | MUX_MODE3) diff --git a/arch/arm/boot/dts/omap-gpmc-smsc911x.dtsi b/arch/arm/boot/dts/ti/omap/omap-gpmc-smsc911x.dtsi similarity index 100% rename from arch/arm/boot/dts/omap-gpmc-smsc911x.dtsi rename to arch/arm/boot/dts/ti/omap/omap-gpmc-smsc911x.dtsi diff --git a/arch/arm/boot/dts/omap-gpmc-smsc9221.dtsi b/arch/arm/boot/dts/ti/omap/omap-gpmc-smsc9221.dtsi similarity index 100% rename from arch/arm/boot/dts/omap-gpmc-smsc9221.dtsi rename to arch/arm/boot/dts/ti/omap/omap-gpmc-smsc9221.dtsi diff --git a/arch/arm/boot/dts/omap-zoom-common.dtsi b/arch/arm/boot/dts/ti/omap/omap-zoom-common.dtsi similarity index 100% rename from arch/arm/boot/dts/omap-zoom-common.dtsi rename to arch/arm/boot/dts/ti/omap/omap-zoom-common.dtsi diff --git a/arch/arm/boot/dts/omap2.dtsi b/arch/arm/boot/dts/ti/omap/omap2.dtsi similarity index 100% rename from arch/arm/boot/dts/omap2.dtsi rename to arch/arm/boot/dts/ti/omap/omap2.dtsi diff --git a/arch/arm/boot/dts/omap2420-clocks.dtsi b/arch/arm/boot/dts/ti/omap/omap2420-clocks.dtsi similarity index 100% rename from arch/arm/boot/dts/omap2420-clocks.dtsi rename to arch/arm/boot/dts/ti/omap/omap2420-clocks.dtsi diff --git a/arch/arm/boot/dts/omap2420-h4.dts b/arch/arm/boot/dts/ti/omap/omap2420-h4.dts similarity index 100% rename from arch/arm/boot/dts/omap2420-h4.dts rename to arch/arm/boot/dts/ti/omap/omap2420-h4.dts diff --git a/arch/arm/boot/dts/omap2420-n800.dts b/arch/arm/boot/dts/ti/omap/omap2420-n800.dts similarity index 100% rename from arch/arm/boot/dts/omap2420-n800.dts rename to arch/arm/boot/dts/ti/omap/omap2420-n800.dts diff --git a/arch/arm/boot/dts/omap2420-n810-wimax.dts b/arch/arm/boot/dts/ti/omap/omap2420-n810-wimax.dts similarity index 100% rename from arch/arm/boot/dts/omap2420-n810-wimax.dts rename to arch/arm/boot/dts/ti/omap/omap2420-n810-wimax.dts diff --git a/arch/arm/boot/dts/omap2420-n810.dts b/arch/arm/boot/dts/ti/omap/omap2420-n810.dts similarity index 97% rename from arch/arm/boot/dts/omap2420-n810.dts rename to arch/arm/boot/dts/ti/omap/omap2420-n810.dts index 09c1dbc0bb6904c82b0a94d95c97ff0a1f16446f..3bf8175d85a821315ab38192dd3285649789bb8a 100644 --- a/arch/arm/boot/dts/omap2420-n810.dts +++ b/arch/arm/boot/dts/ti/omap/omap2420-n810.dts @@ -23,7 +23,7 @@ }; &omap2420_pmx { - mcbsp2_pins: mcbsp2_pins { + mcbsp2_pins: mcbsp2-pins { pinctrl-single,pins = < OMAP2420_CORE_IOPAD(0x0124, PIN_INPUT | MUX_MODE1) /* eac_ac_sclk.mcbsp2_clkx */ OMAP2420_CORE_IOPAD(0x0125, PIN_INPUT | MUX_MODE1) /* eac_ac_fs.mcbsp2_fsx */ @@ -32,7 +32,7 @@ >; }; - aic33_pins: aic33_pins { + aic33_pins: aic33-pins { pinctrl-single,pins = < OMAP2420_CORE_IOPAD(0x0129, PIN_OUTPUT | MUX_MODE3) /* eac_ac_rst.gpio118 */ OMAP2420_CORE_IOPAD(0x00e8, PIN_OUTPUT | MUX_MODE2) /* vlynq_tx1.sys_clkout2 */ diff --git a/arch/arm/boot/dts/omap2420-n8x0-common.dtsi b/arch/arm/boot/dts/ti/omap/omap2420-n8x0-common.dtsi similarity index 100% rename from arch/arm/boot/dts/omap2420-n8x0-common.dtsi rename to arch/arm/boot/dts/ti/omap/omap2420-n8x0-common.dtsi diff --git a/arch/arm/boot/dts/omap2420.dtsi b/arch/arm/boot/dts/ti/omap/omap2420.dtsi similarity index 100% rename from arch/arm/boot/dts/omap2420.dtsi rename to arch/arm/boot/dts/ti/omap/omap2420.dtsi diff --git a/arch/arm/boot/dts/omap2430-clocks.dtsi b/arch/arm/boot/dts/ti/omap/omap2430-clocks.dtsi similarity index 100% rename from arch/arm/boot/dts/omap2430-clocks.dtsi rename to arch/arm/boot/dts/ti/omap/omap2430-clocks.dtsi diff --git a/arch/arm/boot/dts/omap2430-sdp.dts b/arch/arm/boot/dts/ti/omap/omap2430-sdp.dts similarity index 100% rename from arch/arm/boot/dts/omap2430-sdp.dts rename to arch/arm/boot/dts/ti/omap/omap2430-sdp.dts diff --git a/arch/arm/boot/dts/omap2430.dtsi b/arch/arm/boot/dts/ti/omap/omap2430.dtsi similarity index 100% rename from arch/arm/boot/dts/omap2430.dtsi rename to arch/arm/boot/dts/ti/omap/omap2430.dtsi diff --git a/arch/arm/boot/dts/omap24xx-clocks.dtsi b/arch/arm/boot/dts/ti/omap/omap24xx-clocks.dtsi similarity index 100% rename from arch/arm/boot/dts/omap24xx-clocks.dtsi rename to arch/arm/boot/dts/ti/omap/omap24xx-clocks.dtsi diff --git a/arch/arm/boot/dts/omap3-beagle-ab4.dts b/arch/arm/boot/dts/ti/omap/omap3-beagle-ab4.dts similarity index 100% rename from arch/arm/boot/dts/omap3-beagle-ab4.dts rename to arch/arm/boot/dts/ti/omap/omap3-beagle-ab4.dts diff --git a/arch/arm/boot/dts/omap3-beagle-xm-ab.dts b/arch/arm/boot/dts/ti/omap/omap3-beagle-xm-ab.dts similarity index 100% rename from arch/arm/boot/dts/omap3-beagle-xm-ab.dts rename to arch/arm/boot/dts/ti/omap/omap3-beagle-xm-ab.dts diff --git a/arch/arm/boot/dts/omap3-beagle-xm.dts b/arch/arm/boot/dts/ti/omap/omap3-beagle-xm.dts similarity index 97% rename from arch/arm/boot/dts/omap3-beagle-xm.dts rename to arch/arm/boot/dts/ti/omap/omap3-beagle-xm.dts index 1a085bc0131779e6b55d2b33e594d21ce1e53826..08ee0f8ea68fda443b980074f956715398664b4c 100644 --- a/arch/arm/boot/dts/omap3-beagle-xm.dts +++ b/arch/arm/boot/dts/ti/omap/omap3-beagle-xm.dts @@ -90,7 +90,7 @@ }; /* HS USB Host PHY on PORT 2 */ - hsusb2_phy: hsusb2_phy { + hsusb2_phy: hsusb2-phy-pins { compatible = "usb-nop-xceiv"; reset-gpios = <&gpio5 19 GPIO_ACTIVE_LOW>; /* gpio_147 */ vcc-supply = <&hsusb2_power>; @@ -183,13 +183,13 @@ }; &omap3_pmx_wkup { - gpio1_pins: pinmux_gpio1_pins { + gpio1_pins: gpio1-pins { pinctrl-single,pins = < OMAP3_WKUP_IOPAD(0x2a0e, PIN_INPUT | PIN_OFF_WAKEUPENABLE | MUX_MODE4) /* sys_boot2.gpio_4 */ >; }; - dss_dpi_pins2: pinmux_dss_dpi_pins1 { + dss_dpi_pins2: dss-dpi1-pins { pinctrl-single,pins = < OMAP3_WKUP_IOPAD(0x2a0a, PIN_OUTPUT | MUX_MODE3) /* sys_boot0.dss_data18 */ OMAP3_WKUP_IOPAD(0x2a0c, PIN_OUTPUT | MUX_MODE3) /* sys_boot1.dss_data19 */ @@ -207,14 +207,14 @@ &hsusb2_pins >; - uart3_pins: pinmux_uart3_pins { + uart3_pins: uart3-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x219e, PIN_INPUT | MUX_MODE0) /* uart3_rx_irrx.uart3_rx_irrx */ OMAP3_CORE1_IOPAD(0x21a0, PIN_OUTPUT | MUX_MODE0) /* uart3_tx_irtx.uart3_tx_irtx OUTPUT | MODE0 */ >; }; - hsusb2_pins: pinmux_hsusb2_pins { + hsusb2_pins: hsusb2-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x21d4, PIN_INPUT_PULLDOWN | MUX_MODE3) /* mcspi1_cs3.hsusb2_data2 */ OMAP3_CORE1_IOPAD(0x21d6, PIN_INPUT_PULLDOWN | MUX_MODE3) /* mcspi2_clk.hsusb2_data7 */ @@ -225,7 +225,7 @@ >; }; - dss_dpi_pins1: pinmux_dss_dpi_pins2 { + dss_dpi_pins1: dss-dpi2-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x20d4, PIN_OUTPUT | MUX_MODE0) /* dss_pclk.dss_pclk */ OMAP3_CORE1_IOPAD(0x20d6, PIN_OUTPUT | MUX_MODE0) /* dss_hsync.dss_hsync */ @@ -261,7 +261,7 @@ &hsusb2_2_pins >; - hsusb2_2_pins: pinmux_hsusb2_2_pins { + hsusb2_2_pins: hsusb2-2-pins { pinctrl-single,pins = < OMAP3630_CORE2_IOPAD(0x25f0, PIN_OUTPUT | MUX_MODE3) /* etk_d10.hsusb2_clk */ OMAP3630_CORE2_IOPAD(0x25f2, PIN_OUTPUT | MUX_MODE3) /* etk_d11.hsusb2_stp */ diff --git a/arch/arm/boot/dts/omap3-beagle.dts b/arch/arm/boot/dts/ti/omap/omap3-beagle.dts similarity index 97% rename from arch/arm/boot/dts/omap3-beagle.dts rename to arch/arm/boot/dts/ti/omap/omap3-beagle.dts index 47ff1ffddfc529e2f89c56c3f6c1c2fca01a2240..4d9a8eab6abf8030f2801a3c1cef8f7eda085dd6 100644 --- a/arch/arm/boot/dts/omap3-beagle.dts +++ b/arch/arm/boot/dts/ti/omap/omap3-beagle.dts @@ -57,7 +57,7 @@ }; /* HS USB Host PHY on PORT 2 */ - hsusb2_phy: hsusb2_phy { + hsusb2_phy: hsusb2-phy-pins { compatible = "usb-nop-xceiv"; reset-gpios = <&gpio5 19 GPIO_ACTIVE_LOW>; /* gpio_147 */ vcc-supply = <&hsusb2_power>; @@ -170,7 +170,7 @@ }; &omap3_pmx_wkup { - gpio1_pins: pinmux_gpio1_pins { + gpio1_pins: gpio1-pins { pinctrl-single,pins = < OMAP3_WKUP_IOPAD(0x2a14, PIN_INPUT | PIN_OFF_WAKEUPENABLE | MUX_MODE4) /* sys_boot5.gpio_7 */ >; @@ -183,7 +183,7 @@ &hsusb2_pins >; - hsusb2_pins: pinmux_hsusb2_pins { + hsusb2_pins: hsusb2-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x21d4, PIN_INPUT_PULLDOWN | MUX_MODE3) /* mcspi1_cs3.hsusb2_data2 */ OMAP3_CORE1_IOPAD(0x21d6, PIN_INPUT_PULLDOWN | MUX_MODE3) /* mcspi2_clk.hsusb2_data7 */ @@ -194,20 +194,20 @@ >; }; - uart3_pins: pinmux_uart3_pins { + uart3_pins: uart3-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x219e, PIN_INPUT | PIN_OFF_WAKEUPENABLE | MUX_MODE0) /* uart3_rx_irrx.uart3_rx_irrx */ OMAP3_CORE1_IOPAD(0x21a0, PIN_OUTPUT | MUX_MODE0) /* uart3_tx_irtx.uart3_tx_irtx */ >; }; - tfp410_pins: pinmux_tfp410_pins { + tfp410_pins: tfp410-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x21c6, PIN_OUTPUT | MUX_MODE4) /* hdq_sio.gpio_170 */ >; }; - dss_dpi_pins: pinmux_dss_dpi_pins { + dss_dpi_pins: dss-dpi-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x20d4, PIN_OUTPUT | MUX_MODE0) /* dss_pclk.dss_pclk */ OMAP3_CORE1_IOPAD(0x20d6, PIN_OUTPUT | MUX_MODE0) /* dss_hsync.dss_hsync */ @@ -247,7 +247,7 @@ &hsusb2_2_pins >; - hsusb2_2_pins: pinmux_hsusb2_2_pins { + hsusb2_2_pins: hsusb2-2-pins { pinctrl-single,pins = < OMAP3430_CORE2_IOPAD(0x25f0, PIN_OUTPUT | MUX_MODE3) /* etk_d10.hsusb2_clk */ OMAP3430_CORE2_IOPAD(0x25f2, PIN_OUTPUT | MUX_MODE3) /* etk_d11.hsusb2_stp */ diff --git a/arch/arm/boot/dts/omap3-cm-t3517.dts b/arch/arm/boot/dts/ti/omap/omap3-cm-t3517.dts similarity index 92% rename from arch/arm/boot/dts/omap3-cm-t3517.dts rename to arch/arm/boot/dts/ti/omap/omap3-cm-t3517.dts index f25c0a84a190ca36bb2d021440b74ddac6ec15e5..f776e0527049c0537ff4d9b883e759c96a5cde7d 100644 --- a/arch/arm/boot/dts/omap3-cm-t3517.dts +++ b/arch/arm/boot/dts/ti/omap/omap3-cm-t3517.dts @@ -43,7 +43,7 @@ &omap3_pmx_wkup { - wl12xx_wkup_pins: pinmux_wl12xx_wkup_pins { + wl12xx_wkup_pins: wl12xx-wkup-pins { pinctrl-single,pins = < OMAP3_WKUP_IOPAD(0x2a0e, PIN_OUTPUT | MUX_MODE4) /* sys_boot2.gpio_4 */ OMAP3_WKUP_IOPAD(0x2a12, PIN_OUTPUT | MUX_MODE4) /* sys_boot4.gpio_6 */ @@ -53,25 +53,25 @@ &omap3_pmx_core { - phy1_reset_pins: pinmux_hsusb1_phy_reset_pins { + phy1_reset_pins: hsusb1-phy-reset-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x2178, PIN_OUTPUT | MUX_MODE4) /* uart2_tx.gpio_146 */ >; }; - phy2_reset_pins: pinmux_hsusb2_phy_reset_pins { + phy2_reset_pins: hsusb2-phy-reset-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x217a, PIN_OUTPUT | MUX_MODE4) /* uart2_rx.gpio_147 */ >; }; - otg_drv_vbus: pinmux_otg_drv_vbus { + otg_drv_vbus: otg-drv-vbus-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x2210, PIN_INPUT_PULLDOWN | MUX_MODE0) /* rmii_50MHz_clk.usb0_drvvbus */ >; }; - mmc2_pins: pinmux_mmc2_pins { + mmc2_pins: mmc2-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x2158, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc2_clk.sdmmc2_clk */ OMAP3_CORE1_IOPAD(0x215a, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc2_cmd.sdmmc2_cmd */ @@ -82,14 +82,14 @@ >; }; - wl12xx_core_pins: pinmux_wl12xx_core_pins { + wl12xx_core_pins: wl12xx-core-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x20b8, PIN_OUTPUT | MUX_MODE4) /* gpmc_ncs5.gpio_56 */ OMAP3_CORE1_IOPAD(0x2176, PIN_INPUT_PULLUP | MUX_MODE4) /* uart2_rts.gpio_145 */ >; }; - usb_hub_pins: pinmux_usb_hub_pins { + usb_hub_pins: usb-hub-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x2184, PIN_OUTPUT | MUX_MODE4) /* mcbsp4_clkx.gpio_152 - USB HUB RST */ >; diff --git a/arch/arm/boot/dts/omap3-cm-t3530.dts b/arch/arm/boot/dts/ti/omap/omap3-cm-t3530.dts similarity index 98% rename from arch/arm/boot/dts/omap3-cm-t3530.dts rename to arch/arm/boot/dts/ti/omap/omap3-cm-t3530.dts index bc545ee23e711a9f328f88168e3db6dd147e0aa4..0c6f14963e5ea06eb656833f328f40fa1b04ce3d 100644 --- a/arch/arm/boot/dts/omap3-cm-t3530.dts +++ b/arch/arm/boot/dts/ti/omap/omap3-cm-t3530.dts @@ -23,7 +23,7 @@ }; &omap3_pmx_core { - mmc2_pins: pinmux_mmc2_pins { + mmc2_pins: mmc2-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x2158, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc2_clk.sdmmc2_clk */ OMAP3_CORE1_IOPAD(0x215a, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc2_cmd.sdmmc2_cmd */ diff --git a/arch/arm/boot/dts/omap3-cm-t3730.dts b/arch/arm/boot/dts/ti/omap/omap3-cm-t3730.dts similarity index 95% rename from arch/arm/boot/dts/omap3-cm-t3730.dts rename to arch/arm/boot/dts/ti/omap/omap3-cm-t3730.dts index e1b1a047f77a08fb2946dbff0dac296143a1ccc3..f1a8f0fd7a8315fcb45dfe10e9f3174dc441629f 100644 --- a/arch/arm/boot/dts/omap3-cm-t3730.dts +++ b/arch/arm/boot/dts/ti/omap/omap3-cm-t3730.dts @@ -33,7 +33,7 @@ }; &omap3_pmx_wkup { - dss_dpi_pins_cm_t3730: pinmux_dss_dpi_pins_cm_t3730 { + dss_dpi_pins_cm_t3730: dss-dpi-cm-t3730-pins { pinctrl-single,pins = < OMAP3_WKUP_IOPAD(0x2a08, PIN_OUTPUT | MUX_MODE3) /* sys_boot0.dss_data18 */ OMAP3_WKUP_IOPAD(0x2a0c, PIN_OUTPUT | MUX_MODE3) /* sys_boot1.dss_data19 */ @@ -47,7 +47,7 @@ &omap3_pmx_core { - mmc2_pins: pinmux_mmc2_pins { + mmc2_pins: mmc2-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x2158, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc2_clk.sdmmc2_clk */ OMAP3_CORE1_IOPAD(0x215a, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc2_cmd.sdmmc2_cmd */ @@ -58,7 +58,7 @@ >; }; - wl12xx_gpio: pinmux_wl12xx_gpio { + wl12xx_gpio: wl12xx-gpio-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x20e2, PIN_OUTPUT | MUX_MODE4) /* dss_data3.gpio_73 */ OMAP3_CORE1_IOPAD(0x2164, PIN_INPUT | MUX_MODE4) /* sdmmc2_dat4.gpio_136 */ diff --git a/arch/arm/boot/dts/omap3-cm-t3x.dtsi b/arch/arm/boot/dts/ti/omap/omap3-cm-t3x.dtsi similarity index 95% rename from arch/arm/boot/dts/omap3-cm-t3x.dtsi rename to arch/arm/boot/dts/ti/omap/omap3-cm-t3x.dtsi index 51baedf1603bd43248ad4ed15b36dfdb5b6d6274..950a29f9b4a0b724012be0972b34ba3ff2e6ccea 100644 --- a/arch/arm/boot/dts/omap3-cm-t3x.dtsi +++ b/arch/arm/boot/dts/ti/omap/omap3-cm-t3x.dtsi @@ -47,7 +47,7 @@ }; /* HS USB Host PHY on PORT 2 */ - hsusb2_phy: hsusb2_phy { + hsusb2_phy: hsusb2-phy-pins { compatible = "usb-nop-xceiv"; vcc-supply = <&hsusb2_power>; #phy-cells = <0>; @@ -74,14 +74,14 @@ &omap3_pmx_core { - uart3_pins: pinmux_uart3_pins { + uart3_pins: uart3-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x219e, PIN_INPUT | MUX_MODE0) /* uart3_rx_irrx.uart3_rx_irrx */ OMAP3_CORE1_IOPAD(0x21a0, PIN_OUTPUT | MUX_MODE0) /* uart3_tx_irtx.uart3_tx_irtx */ >; }; - mmc1_pins: pinmux_mmc1_pins { + mmc1_pins: mmc1-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x2144, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc1_clk.sdmmc1_clk */ OMAP3_CORE1_IOPAD(0x2146, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc1_cmd.sdmmc1_cmd */ @@ -92,13 +92,13 @@ >; }; - green_led_pins: pinmux_green_led_pins { + green_led_pins: green-led-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x21e2, PIN_OUTPUT | MUX_MODE4) /* sys_clkout2.gpio_186 */ >; }; - dss_dpi_pins_common: pinmux_dss_dpi_pins_common { + dss_dpi_pins_common: dss-dpi-common-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x20d4, PIN_OUTPUT | MUX_MODE0) /* dss_pclk.dss_pclk */ OMAP3_CORE1_IOPAD(0x20d6, PIN_OUTPUT | MUX_MODE0) /* dss_hsync.dss_hsync */ @@ -126,7 +126,7 @@ >; }; - dss_dpi_pins_cm_t35x: pinmux_dss_dpi_pins_cm_t35x { + dss_dpi_pins_cm_t35x: dss-dpi-cm-t35x-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x20dc, PIN_OUTPUT | MUX_MODE0) /* dss_data0.dss_data0 */ OMAP3_CORE1_IOPAD(0x20de, PIN_OUTPUT | MUX_MODE0) /* dss_data1.dss_data1 */ @@ -137,13 +137,13 @@ >; }; - ads7846_pins: pinmux_ads7846_pins { + ads7846_pins: ads7846-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x20ba, PIN_INPUT_PULLUP | MUX_MODE4) /* gpmc_ncs6.gpio_57 */ >; }; - mcspi1_pins: pinmux_mcspi1_pins { + mcspi1_pins: mcspi1-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x21c8, PIN_INPUT | MUX_MODE0) /* mcspi1_clk */ OMAP3_CORE1_IOPAD(0x21ca, PIN_INPUT | MUX_MODE0) /* mcspi1_simo */ @@ -152,14 +152,14 @@ >; }; - i2c1_pins: pinmux_i2c1_pins { + i2c1_pins: i2c1-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x21ba, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c1_scl */ OMAP3_CORE1_IOPAD(0x21bc, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c1_sda */ >; }; - mcbsp2_pins: pinmux_mcbsp2_pins { + mcbsp2_pins: mcbsp2-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x213c, PIN_INPUT | MUX_MODE0) /* mcbsp2_fsx */ OMAP3_CORE1_IOPAD(0x213e, PIN_INPUT | MUX_MODE0) /* mcbsp2_clkx */ diff --git a/arch/arm/boot/dts/omap3-cm-t3x30.dtsi b/arch/arm/boot/dts/ti/omap/omap3-cm-t3x30.dtsi similarity index 97% rename from arch/arm/boot/dts/omap3-cm-t3x30.dtsi rename to arch/arm/boot/dts/ti/omap/omap3-cm-t3x30.dtsi index 5e8943539fcc27129d66e450f4872e2235f63914..0e942513560d619d702efe003e90c1a58a05eea0 100644 --- a/arch/arm/boot/dts/omap3-cm-t3x30.dtsi +++ b/arch/arm/boot/dts/ti/omap/omap3-cm-t3x30.dtsi @@ -22,14 +22,14 @@ &omap3_pmx_core { - smsc1_pins: pinmux_smsc1_pins { + smsc1_pins: smsc1-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x20b8, PIN_OUTPUT | MUX_MODE0) /* gpmc_ncs5.gpmc_ncs5 */ OMAP3_CORE1_IOPAD(0x219a, PIN_INPUT_PULLUP | MUX_MODE4) /* uart3_cts_rctx.gpio_163 */ >; }; - hsusb0_pins: pinmux_hsusb0_pins { + hsusb0_pins: hsusb0-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x21a2, PIN_OUTPUT | MUX_MODE0) /* hsusb0_clk.hsusb0_clk */ OMAP3_CORE1_IOPAD(0x21a4, PIN_OUTPUT | MUX_MODE0) /* hsusb0_stp.hsusb0_stp */ diff --git a/arch/arm/boot/dts/omap3-cpu-thermal.dtsi b/arch/arm/boot/dts/ti/omap/omap3-cpu-thermal.dtsi similarity index 100% rename from arch/arm/boot/dts/omap3-cpu-thermal.dtsi rename to arch/arm/boot/dts/ti/omap/omap3-cpu-thermal.dtsi diff --git a/arch/arm/boot/dts/omap3-devkit8000-common.dtsi b/arch/arm/boot/dts/ti/omap/omap3-devkit8000-common.dtsi similarity index 99% rename from arch/arm/boot/dts/omap3-devkit8000-common.dtsi rename to arch/arm/boot/dts/ti/omap/omap3-devkit8000-common.dtsi index 38aa1febc33f35272e27f904ac1901c126829591..3b9838f1bb6b30783e635116b148d33e9c39406f 100644 --- a/arch/arm/boot/dts/omap3-devkit8000-common.dtsi +++ b/arch/arm/boot/dts/ti/omap/omap3-devkit8000-common.dtsi @@ -312,7 +312,7 @@ }; &omap3_pmx_core { - dss_dpi_pins: pinmux_dss_dpi_pins { + dss_dpi_pins: dss-dpi-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x20d4, PIN_OUTPUT | MUX_MODE0) /* dss_pclk.dss_pclk */ OMAP3_CORE1_IOPAD(0x20d6, PIN_OUTPUT | MUX_MODE0) /* dss_hsync.dss_hsync */ diff --git a/arch/arm/boot/dts/omap3-devkit8000-lcd-common.dtsi b/arch/arm/boot/dts/ti/omap/omap3-devkit8000-lcd-common.dtsi similarity index 100% rename from arch/arm/boot/dts/omap3-devkit8000-lcd-common.dtsi rename to arch/arm/boot/dts/ti/omap/omap3-devkit8000-lcd-common.dtsi diff --git a/arch/arm/boot/dts/omap3-devkit8000-lcd43.dts b/arch/arm/boot/dts/ti/omap/omap3-devkit8000-lcd43.dts similarity index 100% rename from arch/arm/boot/dts/omap3-devkit8000-lcd43.dts rename to arch/arm/boot/dts/ti/omap/omap3-devkit8000-lcd43.dts diff --git a/arch/arm/boot/dts/omap3-devkit8000-lcd70.dts b/arch/arm/boot/dts/ti/omap/omap3-devkit8000-lcd70.dts similarity index 100% rename from arch/arm/boot/dts/omap3-devkit8000-lcd70.dts rename to arch/arm/boot/dts/ti/omap/omap3-devkit8000-lcd70.dts diff --git a/arch/arm/boot/dts/omap3-devkit8000.dts b/arch/arm/boot/dts/ti/omap/omap3-devkit8000.dts similarity index 100% rename from arch/arm/boot/dts/omap3-devkit8000.dts rename to arch/arm/boot/dts/ti/omap/omap3-devkit8000.dts diff --git a/arch/arm/boot/dts/omap3-echo.dts b/arch/arm/boot/dts/ti/omap/omap3-echo.dts similarity index 98% rename from arch/arm/boot/dts/omap3-echo.dts rename to arch/arm/boot/dts/ti/omap/omap3-echo.dts index 06d2377d28adb54eef71232a5ea6086b88556b20..96011c976f5b8fce977922082bef6eab6827397c 100644 --- a/arch/arm/boot/dts/omap3-echo.dts +++ b/arch/arm/boot/dts/ti/omap/omap3-echo.dts @@ -521,16 +521,16 @@ }; -#include "tps65910.dtsi" +#include "../../tps65910.dtsi" &omap3_pmx_core { - tps_pins: pinmux_tps_pins { + tps_pins: tps-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x21e0, PIN_INPUT_PULLUP | PIN_OFF_INPUT_PULLUP | PIN_OFF_OUTPUT_LOW | PIN_OFF_WAKEUPENABLE | MUX_MODE0) /* sys_nirq.sys_nirq */ >; }; - button_pins: pinmux_button_pins { + button_pins: button-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x20dc, PIN_INPUT | MUX_MODE4) /* dss_data0.gpio_70 */ OMAP3_CORE1_IOPAD(0x20e0, PIN_INPUT | MUX_MODE4) /* dss_data2.gpio_72 */ @@ -540,7 +540,7 @@ >; }; - mmc1_pins: pinmux_mmc1_pins { + mmc1_pins: mmc1-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x2144, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc1_clk.sdmmc1_clk */ OMAP3_CORE1_IOPAD(0x2146, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc1_cmd.sdmmc1_cmd */ @@ -551,7 +551,7 @@ >; }; - mmc2_pins: pinmux_mmc2_pins { + mmc2_pins: mmc2-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x2158, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc2_clk.sdmmc2_clk */ OMAP3_CORE1_IOPAD(0x215a, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc2_cmd.sdmmc2_cmd */ @@ -566,7 +566,7 @@ >; }; - mcbsp2_pins: pinmux_mcbsp2_pins { + mcbsp2_pins: mcbsp2-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x213c, PIN_INPUT | MUX_MODE0) /* mcbsp2_fsx.mcbsp2_fsx */ OMAP3_CORE1_IOPAD(0x213e, PIN_INPUT | MUX_MODE0) /* mcbsp2_clkx.mcbsp2_clkx */ @@ -577,7 +577,7 @@ }; &omap3_pmx_core2 { - mmc3_pins: pinmux_mmc3_pins { + mmc3_pins: mmc3-pins { pinctrl-single,pins = < OMAP3630_CORE2_IOPAD(0x25d8, PIN_INPUT_PULLUP | MUX_MODE2) /* etk_clk.sdmmc3_clk */ OMAP3630_CORE2_IOPAD(0x25da, PIN_INPUT_PULLUP | MUX_MODE2) /* etk_ctl.sdmmc3_cmd */ diff --git a/arch/arm/boot/dts/omap3-evm-37xx.dts b/arch/arm/boot/dts/ti/omap/omap3-evm-37xx.dts similarity index 96% rename from arch/arm/boot/dts/omap3-evm-37xx.dts rename to arch/arm/boot/dts/ti/omap/omap3-evm-37xx.dts index abd403c228c7a856720272d476f8aa2c195ec5ba..e0346bf842fcd142b87e245fe7d1c051b51077f0 100644 --- a/arch/arm/boot/dts/omap3-evm-37xx.dts +++ b/arch/arm/boot/dts/ti/omap/omap3-evm-37xx.dts @@ -17,7 +17,7 @@ pinctrl-names = "default"; pinctrl-0 = <&hsusb2_2_pins>; - ehci_phy_pins: pinmux_ehci_phy_pins { + ehci_phy_pins: ehci-phy-pins { pinctrl-single,pins = < /* EHCI PHY reset GPIO etk_d7.gpio_21 */ @@ -29,7 +29,7 @@ }; /* Used by OHCI and EHCI. OHCI won't work without external phy */ - hsusb2_2_pins: pinmux_hsusb2_2_pins { + hsusb2_2_pins: hsusb2-2-pins { pinctrl-single,pins = < /* etk_d10.hsusb2_clk */ diff --git a/arch/arm/boot/dts/omap3-evm-common.dtsi b/arch/arm/boot/dts/ti/omap/omap3-evm-common.dtsi similarity index 99% rename from arch/arm/boot/dts/omap3-evm-common.dtsi rename to arch/arm/boot/dts/ti/omap/omap3-evm-common.dtsi index 17c89df6ce6b14b897b2f3859db3d6637275853e..1b6023c4cdf31c93d54d8df8d0807d33fca9a2ba 100644 --- a/arch/arm/boot/dts/omap3-evm-common.dtsi +++ b/arch/arm/boot/dts/ti/omap/omap3-evm-common.dtsi @@ -25,7 +25,7 @@ }; /* HS USB Host PHY on PORT 2 */ - hsusb2_phy: hsusb2_phy { + hsusb2_phy: hsusb2-phy-pins { compatible = "usb-nop-xceiv"; reset-gpios = <&gpio1 21 GPIO_ACTIVE_LOW>; /* gpio_21 */ vcc-supply = <&hsusb2_power>; diff --git a/arch/arm/boot/dts/omap3-evm-processor-common.dtsi b/arch/arm/boot/dts/ti/omap/omap3-evm-processor-common.dtsi similarity index 95% rename from arch/arm/boot/dts/omap3-evm-processor-common.dtsi rename to arch/arm/boot/dts/ti/omap/omap3-evm-processor-common.dtsi index e6ba30a2116638563ef5faad8d1b6c998185dc1f..e27837093e43d82fbe7ce183efb42efa262c69ed 100644 --- a/arch/arm/boot/dts/omap3-evm-processor-common.dtsi +++ b/arch/arm/boot/dts/ti/omap/omap3-evm-processor-common.dtsi @@ -33,7 +33,7 @@ pinctrl-names = "default"; pinctrl-0 = <&on_board_gpio_61 &hsusb2_pins>; - dss_dpi_pins1: pinmux_dss_dpi_pins2 { + dss_dpi_pins1: dss-dpi2-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x20d4, PIN_OUTPUT | MUX_MODE0) /* dss_pclk.dss_pclk */ OMAP3_CORE1_IOPAD(0x20d6, PIN_OUTPUT | MUX_MODE0) /* dss_hsync.dss_hsync */ @@ -62,7 +62,7 @@ >; }; - mmc1_pins: pinmux_mmc1_pins { + mmc1_pins: mmc1-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x2144, PIN_OUTPUT_PULLUP | MUX_MODE0) /* sdmmc1_clk.sdmmc1_clk */ OMAP3_CORE1_IOPAD(0x2146, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc1_cmd.sdmmc1_cmd */ @@ -78,7 +78,7 @@ }; /* NOTE: Clocked externally, needs INPUT also for sdmmc2_clk.sdmmc2_clk */ - mmc2_pins: pinmux_mmc2_pins { + mmc2_pins: mmc2-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x2158, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc2_clk.sdmmc2_clk */ OMAP3_CORE1_IOPAD(0x215a, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc2_cmd.sdmmc2_cmd */ @@ -93,7 +93,7 @@ >; }; - uart3_pins: pinmux_uart3_pins { + uart3_pins: uart3-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x219e, WAKEUP_EN | PIN_INPUT | MUX_MODE0) /* uart3_rx_irrx.uart3_rx_irrx */ OMAP3_CORE1_IOPAD(0x21a0, PIN_OUTPUT | MUX_MODE0) /* uart3_tx_irtx.uart3_tx_irtx */ @@ -101,14 +101,14 @@ }; /* Devices are routed with gpmc_nbe1.gpio_61 to on-board devices */ - on_board_gpio_61: pinmux_ehci_port_select_pins { + on_board_gpio_61: ehci-port-select-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x20c8, PIN_OUTPUT | MUX_MODE4) >; }; /* Used by OHCI and EHCI. OHCI won't work without external phy */ - hsusb2_pins: pinmux_hsusb2_pins { + hsusb2_pins: hsusb2-pins { pinctrl-single,pins = < /* mcspi1_cs3.hsusb2_data2 */ @@ -135,14 +135,14 @@ * Note that gpio_150 pulled high with internal pull to prevent wlcore * reset on return from off mode in idle. */ - wl12xx_gpio: pinmux_wl12xx_gpio { + wl12xx_gpio: wl12xx-gpio-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x2180, PIN_INPUT_PULLUP | MUX_MODE7) /* uart1_cts.gpio_150 */ OMAP3_CORE1_IOPAD(0x217e, PIN_INPUT | MUX_MODE4) /* uart1_rts.gpio_149 */ >; }; - smsc911x_pins: pinmux_smsc911x_pins { + smsc911x_pins: smsc911x-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x21d2, PIN_INPUT | MUX_MODE4) /* mcspi1_cs2.gpio_176 */ >; @@ -150,7 +150,7 @@ }; &omap3_pmx_wkup { - dss_dpi_pins2: pinmux_dss_dpi_pins1 { + dss_dpi_pins2: dss-dpi1-pins { pinctrl-single,pins = < OMAP3_WKUP_IOPAD(0x2a0a, PIN_OUTPUT | MUX_MODE3) /* sys_boot0.dss_data18 */ OMAP3_WKUP_IOPAD(0x2a0c, PIN_OUTPUT | MUX_MODE3) /* sys_boot1.dss_data19 */ diff --git a/arch/arm/boot/dts/omap3-evm.dts b/arch/arm/boot/dts/ti/omap/omap3-evm.dts similarity index 96% rename from arch/arm/boot/dts/omap3-evm.dts rename to arch/arm/boot/dts/ti/omap/omap3-evm.dts index f95eea63b355f215bcdee7742628f9d172cb89b0..a2a1613c45c3ef111b0b53e6f2e456b63ac6a220 100644 --- a/arch/arm/boot/dts/omap3-evm.dts +++ b/arch/arm/boot/dts/ti/omap/omap3-evm.dts @@ -17,7 +17,7 @@ pinctrl-names = "default"; pinctrl-0 = <&hsusb2_2_pins>; - ehci_phy_pins: pinmux_ehci_phy_pins { + ehci_phy_pins: ehci-phy-pins { pinctrl-single,pins = < /* EHCI PHY reset GPIO etk_d7.gpio_21 */ @@ -29,7 +29,7 @@ }; /* Used by OHCI and EHCI. OHCI won't work without external phy */ - hsusb2_2_pins: pinmux_hsusb2_2_pins { + hsusb2_2_pins: hsusb2-2-pins { pinctrl-single,pins = < /* etk_d10.hsusb2_clk */ diff --git a/arch/arm/boot/dts/omap3-gta04.dtsi b/arch/arm/boot/dts/ti/omap/omap3-gta04.dtsi similarity index 95% rename from arch/arm/boot/dts/omap3-gta04.dtsi rename to arch/arm/boot/dts/ti/omap/omap3-gta04.dtsi index 4183fde460596b73017a10574ba9879f5fd10f61..b6b27e93857f56874b71a437ee0fc4e19660a995 100644 --- a/arch/arm/boot/dts/omap3-gta04.dtsi +++ b/arch/arm/boot/dts/ti/omap/omap3-gta04.dtsi @@ -153,7 +153,7 @@ ti,clock-source = <0x01>; }; - hsusb2_phy: hsusb2_phy { + hsusb2_phy: hsusb2-phy-pins { compatible = "usb-nop-xceiv"; reset-gpios = <&gpio6 14 GPIO_ACTIVE_LOW>; #phy-cells = <0>; @@ -200,7 +200,7 @@ }; /* devconf0 setup for mcbsp1 clock pins */ - pinmux_mcbsp1@48002274 { + pinmux@48002274 { compatible = "pinctrl-single"; reg = <0x48002274 4>; /* CONTROL_DEVCONF0 */ #address-cells = <1>; @@ -211,14 +211,14 @@ #pinctrl-cells = <2>; pinctrl-names = "default"; pinctrl-0 = <&mcbsp1_devconf0_pins>; - mcbsp1_devconf0_pins: pinmux_mcbsp1_devconf0_pins { + mcbsp1_devconf0_pins: mcbsp1-devconf0-pins { /* offset bits mask */ pinctrl-single,bits = <0x00 0x08 0x1c>; /* set MCBSP1_CLKR */ }; }; /* devconf1 setup for tvout pins */ - pinmux_tv_out@480022d8 { + pinmux@480022d8 { compatible = "pinctrl-single"; reg = <0x480022d8 4>; /* CONTROL_DEVCONF1 */ #address-cells = <1>; @@ -229,7 +229,7 @@ #pinctrl-cells = <2>; pinctrl-names = "default"; pinctrl-0 = <&tv_acbias_devconf1_pins>; - tv_acbias_devconf1_pins: pinmux_tv_acbias_devconf1_pins { + tv_acbias_devconf1_pins: tv-acbias-devconf1-pins { /* offset bits mask */ pinctrl-single,bits = <0x00 0x40800 0x40800>; /* set TVOUTBYPASS and TVOUTACEN */ }; @@ -237,7 +237,7 @@ }; &omap3_pmx_wkup { - gpio1_pins: pinmux_gpio1_pins { + gpio1_pins: gpio1-pins { pinctrl-single,pins = < OMAP3_WKUP_IOPAD(0x2a14, PIN_INPUT | PIN_OFF_WAKEUPENABLE | MUX_MODE4) /* sys_boot5.gpio_7 */ OMAP3_WKUP_IOPAD(0x2a1a, PIN_INPUT | PIN_OFF_WAKEUPENABLE | MUX_MODE4) /* sys_clkout.gpio_10 */ @@ -251,7 +251,7 @@ &hsusb2_pins >; - hsusb2_pins: pinmux_hsusb2_pins { + hsusb2_pins: hsusb2-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x21d4, PIN_INPUT_PULLDOWN | MUX_MODE3) /* mcspi1_cs3.hsusb2_data2 */ OMAP3_CORE1_IOPAD(0x21d6, PIN_INPUT_PULLDOWN | MUX_MODE3) /* mcspi2_clk.hsusb2_data7 */ @@ -262,28 +262,28 @@ >; }; - uart1_pins: pinmux_uart1_pins { + uart1_pins: uart1-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x2182, PIN_INPUT | MUX_MODE0) /* uart1_rx.uart1_rx */ OMAP3_CORE1_IOPAD(0x217c, PIN_OUTPUT | MUX_MODE0) /* uart1_tx.uart1_tx */ >; }; - uart2_pins: pinmux_uart2_pins { + uart2_pins: uart2-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x217a, PIN_INPUT | MUX_MODE0) /* uart2_rx.uart2_rx */ OMAP3_CORE1_IOPAD(0x2178, PIN_OUTPUT | MUX_MODE0) /* uart2_tx.uart2_tx */ >; }; - uart3_pins: pinmux_uart3_pins { + uart3_pins: uart3-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x219e, PIN_INPUT | MUX_MODE0) /* uart3_rx.uart3_rx */ OMAP3_CORE1_IOPAD(0x21a0, PIN_OUTPUT | MUX_MODE0) /* uart3_tx.uart3_tx */ >; }; - mmc1_pins: pinmux_mmc1_pins { + mmc1_pins: mmc1-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x2144, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc1_clk.sdmmc1_clk */ OMAP3_CORE1_IOPAD(0x2146, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc1_cmd.sdmmc1_cmd */ @@ -294,13 +294,13 @@ >; }; - backlight_pins: backlight_pins_pinmux { + backlight_pins: backlight-pinmux-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x20ba, MUX_MODE3) /* gpt11/gpio57 */ >; }; - dss_dpi_pins: pinmux_dss_dpi_pins { + dss_dpi_pins: dss-dpi-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x20d4, PIN_OUTPUT | MUX_MODE0) /* dss_pclk.dss_pclk */ OMAP3_CORE1_IOPAD(0x20d6, PIN_OUTPUT | MUX_MODE0) /* dss_hsync.dss_hsync */ @@ -333,50 +333,50 @@ >; }; - gps_pins: pinmux_gps_pins { + gps_pins: gps-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x2176, PIN_OUTPUT_PULLDOWN | MUX_MODE4) /* gpio145 */ >; }; - hdq_pins: hdq_pins { + hdq_pins: hdq-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x21c6, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c3_sda.hdq */ >; }; - bmp085_pins: pinmux_bmp085_pins { + bmp085_pins: bmp085-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x2136, PIN_INPUT_PULLUP | MUX_MODE4) /* gpio113 */ >; }; - bma180_pins: pinmux_bma180_pins { + bma180_pins: bma180-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x213a, PIN_INPUT_PULLUP | MUX_MODE4) /* gpio115 */ >; }; - itg3200_pins: pinmux_itg3200_pins { + itg3200_pins: itg3200-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x20b8, PIN_INPUT_PULLUP | MUX_MODE4) /* gpio56 */ >; }; - hmc5843_pins: pinmux_hmc5843_pins { + hmc5843_pins: hmc5843-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x2134, PIN_INPUT_PULLUP | MUX_MODE4) /* gpio112 */ >; }; - penirq_pins: pinmux_penirq_pins { + penirq_pins: penirq-pins { pinctrl-single,pins = < /* here we could enable to wakeup the cpu from suspend by a pen touch */ OMAP3_CORE1_IOPAD(0x2194, PIN_INPUT_PULLUP | MUX_MODE4) /* gpio160 */ >; }; - camera_pins: pinmux_camera_pins { + camera_pins: camera-pins { pinctrl-single,pins = < /* set up parallel camera interface */ OMAP3_CORE1_IOPAD(0x210c, PIN_INPUT_PULLDOWN | MUX_MODE0) /* cam_hs */ @@ -402,7 +402,7 @@ >; }; - mcbsp1_pins: pinmux_mcbsp1_pins { + mcbsp1_pins: mcbsp1-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x218c, PIN_INPUT | MUX_MODE4) /* mcbsp1_clkr.mcbsp1_clkr - gpio_156 FM interrupt */ OMAP3_CORE1_IOPAD(0x218e, PIN_OUTPUT | MUX_MODE0) /* mcbsp1_clkr.mcbsp1_fsr */ @@ -415,7 +415,7 @@ >; }; - mcbsp2_pins: pinmux_mcbsp2_pins { + mcbsp2_pins: mcbsp2-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x213c, PIN_INPUT | MUX_MODE0) /* mcbsp2_fsx.mcbsp2_fsx */ OMAP3_CORE1_IOPAD(0x213e, PIN_INPUT | MUX_MODE0) /* mcbsp2_fsx.mcbsp2_clkx */ @@ -424,7 +424,7 @@ >; }; - mcbsp3_pins: pinmux_mcbsp3_pins { + mcbsp3_pins: mcbsp3-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x216c, PIN_OUTPUT | MUX_MODE0) /* mcbsp3_dx.mcbsp3_dx */ OMAP3_CORE1_IOPAD(0x216e, PIN_INPUT | MUX_MODE0) /* mcbsp3_dx.mcbsp3_dr */ @@ -433,7 +433,7 @@ >; }; - mcbsp4_pins: pinmux_mcbsp4_pins { + mcbsp4_pins: mcbsp4-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x2184, PIN_INPUT_PULLDOWN | MUX_MODE0) /* mcbsp4_clkx.mcbsp4_clkx */ OMAP3_CORE1_IOPAD(0x2186, PIN_INPUT_PULLDOWN | MUX_MODE0) /* mcbsp4_clkx.mcbsp4_dr */ @@ -448,7 +448,7 @@ &hsusb2_2_pins >; - hsusb2_2_pins: pinmux_hsusb2_2_pins { + hsusb2_2_pins: hsusb2-2-pins { pinctrl-single,pins = < OMAP3630_CORE2_IOPAD(0x25f0, PIN_OUTPUT | MUX_MODE3) /* etk_d10.hsusb2_clk */ OMAP3630_CORE2_IOPAD(0x25f2, PIN_OUTPUT | MUX_MODE3) /* etk_d11.hsusb2_stp */ @@ -459,7 +459,7 @@ >; }; - spi_gpio_pins: spi_gpio_pinmux { + spi_gpio_pins: spi-gpio-pinmux-pins { pinctrl-single,pins = < OMAP3630_CORE2_IOPAD(0x25d8, PIN_OUTPUT | MUX_MODE4) /* clk */ OMAP3630_CORE2_IOPAD(0x25e6, PIN_OUTPUT | MUX_MODE4) /* cs */ diff --git a/arch/arm/boot/dts/omap3-gta04a3.dts b/arch/arm/boot/dts/ti/omap/omap3-gta04a3.dts similarity index 100% rename from arch/arm/boot/dts/omap3-gta04a3.dts rename to arch/arm/boot/dts/ti/omap/omap3-gta04a3.dts diff --git a/arch/arm/boot/dts/omap3-gta04a4.dts b/arch/arm/boot/dts/ti/omap/omap3-gta04a4.dts similarity index 100% rename from arch/arm/boot/dts/omap3-gta04a4.dts rename to arch/arm/boot/dts/ti/omap/omap3-gta04a4.dts diff --git a/arch/arm/boot/dts/omap3-gta04a5.dts b/arch/arm/boot/dts/ti/omap/omap3-gta04a5.dts similarity index 95% rename from arch/arm/boot/dts/omap3-gta04a5.dts rename to arch/arm/boot/dts/ti/omap/omap3-gta04a5.dts index 425081201fd42daf04d8a0a638d0878ee5be750e..8bd6b4b1f30b89c998647ac83fe2d6f0233ca02f 100644 --- a/arch/arm/boot/dts/omap3-gta04a5.dts +++ b/arch/arm/boot/dts/ti/omap/omap3-gta04a5.dts @@ -45,31 +45,31 @@ }; &omap3_pmx_core { - bt_pins: pinmux_bt_pins { + bt_pins: bt-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x2166, PIN_OUTPUT | MUX_MODE4) /* mmc2_dat5 = mmc3_dat1 = gpio137 */ >; }; - wlan_pins: pinmux_wlan_pins { + wlan_pins: wlan-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x2168, PIN_OUTPUT | MUX_MODE4) /* mmc2_dat6 = mmc3_dat2 = gpio138 */ >; }; - wlan_irq_pin: pinmux_wlan_irq_pin { + wlan_irq_pin: wlan-irq-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x216a, PIN_INPUT_PULLUP | MUX_MODE4) /* mmc2_dat7 = mmc3_dat3 = gpio139 */ >; }; - irda_pins: pinmux_irda { + irda_pins: irda-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x21d0, PIN_OUTPUT_PULLUP | MUX_MODE4) /* mcspi1_cs1 = gpio175 */ >; }; - pps_pins: pinmux_pps_pins { + pps_pins: pps-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x2138, PIN_INPUT | MUX_MODE4) /* gpin114 */ >; diff --git a/arch/arm/boot/dts/omap3-gta04a5one.dts b/arch/arm/boot/dts/ti/omap/omap3-gta04a5one.dts similarity index 99% rename from arch/arm/boot/dts/omap3-gta04a5one.dts rename to arch/arm/boot/dts/ti/omap/omap3-gta04a5one.dts index 9db9fe67cd63b6ed57a6e0ba6c63a7657f3d04f7..1e5703d1b02eec330ca963282d2c0bc380c599f4 100644 --- a/arch/arm/boot/dts/omap3-gta04a5one.dts +++ b/arch/arm/boot/dts/ti/omap/omap3-gta04a5one.dts @@ -5,10 +5,12 @@ #include "omap3-gta04a5.dts" -&omap3_pmx_core { +/ { model = "Goldelico GTA04A5/Letux 2804 with OneNAND"; +}; - gpmc_pins: pinmux_gpmc_pins { +&omap3_pmx_core { + gpmc_pins: gpmc-pins { pinctrl-single,pins = < /* address lines */ diff --git a/arch/arm/boot/dts/omap3-ha-common.dtsi b/arch/arm/boot/dts/ti/omap/omap3-ha-common.dtsi similarity index 86% rename from arch/arm/boot/dts/omap3-ha-common.dtsi rename to arch/arm/boot/dts/ti/omap/omap3-ha-common.dtsi index a010585d0302ad32532498471e98ce21cb8996fc..3a258a692757f4ffe308dde708b8e9a9dc5c8993 100644 --- a/arch/arm/boot/dts/omap3-ha-common.dtsi +++ b/arch/arm/boot/dts/ti/omap/omap3-ha-common.dtsi @@ -17,43 +17,43 @@ }; &omap3_pmx_core { - sound2_pins: pinmux_sound2_pins { + sound2_pins: sound2-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x209e, PIN_OUTPUT | MUX_MODE4) /* gpmc_d8 gpio_44 */ >; }; - led_blue_pins: pinmux_led_blue_pins { + led_blue_pins: led-blue-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x2110, PIN_OUTPUT | MUX_MODE4) /* cam_xclka gpio_96, LED blue */ >; }; - led_green_pins: pinmux_led_green_pins { + led_green_pins: led-green-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x2126, PIN_OUTPUT | MUX_MODE4) /* cam_d8 gpio_107, LED green */ >; }; - led_red_pins: pinmux_led_red_pins { + led_red_pins: led-red-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x212e, PIN_OUTPUT_PULLUP | MUX_MODE4) /* cam_xclkb gpio_111, LED red */ >; }; - poweroff_pins: pinmux_poweroff_pins { + poweroff_pins: poweroff-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x21be, PIN_OUTPUT_PULLUP | MUX_MODE4) /* i2c2_scl gpio_168 */ >; }; - powerdown_input_pins: pinmux_powerdown_input_pins { + powerdown_input_pins: powerdown-input-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x21c0, PIN_INPUT_PULLUP | MUX_MODE4) /* i2c2_sda gpio_183 */ >; }; - fpga_boot0_pins: fpga_boot0_pins { + fpga_boot0_pins: fpga-boot0-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x211a, PIN_INPUT | MUX_MODE4) /* cam_d2 gpio_101 */ OMAP3_CORE1_IOPAD(0x211c, PIN_OUTPUT | MUX_MODE4) /* cam_d3 gpio_102 */ @@ -62,7 +62,7 @@ >; }; - fpga_boot1_pins: fpga_boot1_pins { + fpga_boot1_pins: fpga-boot1-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x20a2, PIN_INPUT | MUX_MODE4) /* gpmc_d10 gpio_46 */ OMAP3_CORE1_IOPAD(0x20a4, PIN_OUTPUT | MUX_MODE4) /* gpmc_d11 gpio_47 */ diff --git a/arch/arm/boot/dts/omap3-ha-lcd.dts b/arch/arm/boot/dts/ti/omap/omap3-ha-lcd.dts similarity index 95% rename from arch/arm/boot/dts/omap3-ha-lcd.dts rename to arch/arm/boot/dts/ti/omap/omap3-ha-lcd.dts index 643283f0c3dbb2a0266f80a3927243c8ee05d249..94f6b7931e33369fac02dd92518db185de8b27a2 100644 --- a/arch/arm/boot/dts/omap3-ha-lcd.dts +++ b/arch/arm/boot/dts/ti/omap/omap3-ha-lcd.dts @@ -24,19 +24,19 @@ &touchscreen_wake_pins >; - touchscreen_irq_pins: pinmux_touchscreen_irq_pins { + touchscreen_irq_pins: touchscreen-irq-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x2164, PIN_INPUT_PULLUP | MUX_MODE4) /* gpio_136, Touchscreen IRQ */ >; }; - touchscreen_wake_pins: pinmux_touchscreen_wake_pins { + touchscreen_wake_pins: touchscreen-wake-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x212c, PIN_OUTPUT_PULLUP | MUX_MODE4) /* gpio_110, Touchscreen Wake */ >; }; - dss_dpi_pins: pinmux_dss_dpi_pins { + dss_dpi_pins: dss-dpi-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x20d4, PIN_OUTPUT | MUX_MODE0) /* dss_pclk.dss_pclk */ OMAP3_CORE1_IOPAD(0x20d6, PIN_OUTPUT | MUX_MODE0) /* dss_hsync.dss_hsync */ @@ -69,13 +69,13 @@ >; }; - lte430_pins: pinmux_lte430_pins { + lte430_pins: lte430-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x2168, PIN_OUTPUT | MUX_MODE4) /* sdmmc2_dat6.gpio_138 */ >; }; - backlight_pins: pinmux_backlight_pins { + backlight_pins: backlight-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x216a, PIN_OUTPUT | MUX_MODE4) /* sdmmc2_dat7.gpio_139 */ >; diff --git a/arch/arm/boot/dts/omap3-ha.dts b/arch/arm/boot/dts/ti/omap/omap3-ha.dts similarity index 100% rename from arch/arm/boot/dts/omap3-ha.dts rename to arch/arm/boot/dts/ti/omap/omap3-ha.dts diff --git a/arch/arm/boot/dts/omap3-igep.dtsi b/arch/arm/boot/dts/ti/omap/omap3-igep.dtsi similarity index 95% rename from arch/arm/boot/dts/omap3-igep.dtsi rename to arch/arm/boot/dts/ti/omap/omap3-igep.dtsi index 2192026104638315a537143b8c41814b99c48ade..e068ecf86b8f8ae0643843f4f32c0083313a2f7b 100644 --- a/arch/arm/boot/dts/omap3-igep.dtsi +++ b/arch/arm/boot/dts/ti/omap/omap3-igep.dtsi @@ -34,28 +34,28 @@ }; &omap3_pmx_core { - gpmc_pins: pinmux_gpmc_pins { + gpmc_pins: gpmc-pins { pinctrl-single,pins = < /* OneNAND seems to require PIN_INPUT on clock. */ OMAP3_CORE1_IOPAD(0x20be, PIN_INPUT | MUX_MODE0) /* gpmc_clk.gpmc_clk */ >; }; - uart1_pins: pinmux_uart1_pins { + uart1_pins: uart1-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x2182, PIN_INPUT | MUX_MODE0) /* uart1_rx.uart1_rx */ OMAP3_CORE1_IOPAD(0x217c, PIN_OUTPUT | MUX_MODE0) /* uart1_tx.uart1_tx */ >; }; - uart3_pins: pinmux_uart3_pins { + uart3_pins: uart3-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x219e, PIN_INPUT | MUX_MODE0) /* uart3_rx.uart3_rx */ OMAP3_CORE1_IOPAD(0x21a0, PIN_OUTPUT | MUX_MODE0) /* uart3_tx.uart3_tx */ >; }; - mcbsp2_pins: pinmux_mcbsp2_pins { + mcbsp2_pins: mcbsp2-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x213c, PIN_INPUT | MUX_MODE0) /* mcbsp2_fsx.mcbsp2_fsx */ OMAP3_CORE1_IOPAD(0x213e, PIN_INPUT | MUX_MODE0) /* mcbsp2_clkx.mcbsp2_clkx */ @@ -64,7 +64,7 @@ >; }; - mmc1_pins: pinmux_mmc1_pins { + mmc1_pins: mmc1-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x2144, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc1_clk.sdmmc1_clk */ OMAP3_CORE1_IOPAD(0x2146, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc1_cmd.sdmmc1_cmd */ @@ -75,7 +75,7 @@ >; }; - mmc2_pins: pinmux_mmc2_pins { + mmc2_pins: mmc2-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x2158, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc2_clk.sdmmc2_clk */ OMAP3_CORE1_IOPAD(0x215a, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc2_cmd.sdmmc2_cmd */ @@ -86,14 +86,14 @@ >; }; - i2c1_pins: pinmux_i2c1_pins { + i2c1_pins: i2c1-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x21ba, PIN_INPUT | MUX_MODE0) /* i2c1_scl.i2c1_scl */ OMAP3_CORE1_IOPAD(0x21bc, PIN_INPUT | MUX_MODE0) /* i2c1_sda.i2c1_sda */ >; }; - i2c3_pins: pinmux_i2c3_pins { + i2c3_pins: i2c3-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x21c2, PIN_INPUT | MUX_MODE0) /* i2c3_scl.i2c3_scl */ OMAP3_CORE1_IOPAD(0x21c4, PIN_INPUT | MUX_MODE0) /* i2c3_sda.i2c3_sda */ diff --git a/arch/arm/boot/dts/omap3-igep0020-common.dtsi b/arch/arm/boot/dts/ti/omap/omap3-igep0020-common.dtsi similarity index 96% rename from arch/arm/boot/dts/omap3-igep0020-common.dtsi rename to arch/arm/boot/dts/ti/omap/omap3-igep0020-common.dtsi index 73d8f471b9ec9f034693cbaeb249d8308feb19e0..13f434625407ac1954cf124cf653ee63b91243f4 100644 --- a/arch/arm/boot/dts/omap3-igep0020-common.dtsi +++ b/arch/arm/boot/dts/ti/omap/omap3-igep0020-common.dtsi @@ -107,13 +107,13 @@ &dss_dpi_pins >; - tfp410_pins: pinmux_tfp410_pins { + tfp410_pins: tfp410-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x21c6, PIN_OUTPUT | MUX_MODE4) /* hdq_sio.gpio_170 */ >; }; - dss_dpi_pins: pinmux_dss_dpi_pins { + dss_dpi_pins: dss-dpi-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x20d4, PIN_OUTPUT | MUX_MODE0) /* dss_pclk.dss_pclk */ OMAP3_CORE1_IOPAD(0x20d6, PIN_OUTPUT | MUX_MODE0) /* dss_hsync.dss_hsync */ @@ -146,7 +146,7 @@ >; }; - uart2_pins: pinmux_uart2_pins { + uart2_pins: uart2-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x2174, PIN_INPUT | MUX_MODE0) /* uart2_cts.uart2_cts */ OMAP3_CORE1_IOPAD(0x2176, PIN_OUTPUT | MUX_MODE0) /* uart2_rts .uart2_rts*/ @@ -155,7 +155,7 @@ >; }; - smsc9221_pins: pinmux_smsc9221_pins { + smsc9221_pins: smsc9221-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x21d2, PIN_INPUT | MUX_MODE4) /* mcspi1_cs2.gpio_176 */ >; @@ -168,7 +168,7 @@ &hsusbb1_pins >; - hsusbb1_pins: pinmux_hsusbb1_pins { + hsusbb1_pins: hsusbb1-pins { pinctrl-single,pins = < OMAP3630_CORE2_IOPAD(0x25da, PIN_OUTPUT | MUX_MODE3) /* etk_ctl.hsusb1_clk */ OMAP3630_CORE2_IOPAD(0x25d8, PIN_OUTPUT | MUX_MODE3) /* etk_clk.hsusb1_stp */ @@ -185,7 +185,7 @@ >; }; - leds_pins: pinmux_leds_pins { + leds_pins: leds-pins { pinctrl-single,pins = < OMAP3630_CORE2_IOPAD(0x25f4, PIN_OUTPUT | MUX_MODE4) /* etk_d12.gpio_26 */ OMAP3630_CORE2_IOPAD(0x25f6, PIN_OUTPUT | MUX_MODE4) /* etk_d13.gpio_27 */ @@ -193,7 +193,7 @@ >; }; - mmc1_wp_pins: pinmux_mmc1_cd_pins { + mmc1_wp_pins: mmc1-cd-pins { pinctrl-single,pins = < OMAP3630_CORE2_IOPAD(0x25fa, PIN_INPUT | MUX_MODE4) /* etk_d15.gpio_29 */ >; diff --git a/arch/arm/boot/dts/omap3-igep0020-rev-f.dts b/arch/arm/boot/dts/ti/omap/omap3-igep0020-rev-f.dts similarity index 97% rename from arch/arm/boot/dts/omap3-igep0020-rev-f.dts rename to arch/arm/boot/dts/ti/omap/omap3-igep0020-rev-f.dts index eadb5b857f48b96061dea3536220b5fd1320d34e..316e8e6b39cde90d6e0eba2241d92d9b7e294c32 100644 --- a/arch/arm/boot/dts/omap3-igep0020-rev-f.dts +++ b/arch/arm/boot/dts/ti/omap/omap3-igep0020-rev-f.dts @@ -24,7 +24,7 @@ }; &omap3_pmx_core { - lbep5clwmc_pins: pinmux_lbep5clwmc_pins { + lbep5clwmc_pins: lbep5clwmc-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x21d4, PIN_INPUT | MUX_MODE4) /* mcspi1_cs3.gpio_177 - W_IRQ */ OMAP3_CORE1_IOPAD(0x2166, PIN_OUTPUT | MUX_MODE4) /* sdmmc2_dat5.gpio_137 - BT_EN */ diff --git a/arch/arm/boot/dts/omap3-igep0020.dts b/arch/arm/boot/dts/ti/omap/omap3-igep0020.dts similarity index 96% rename from arch/arm/boot/dts/omap3-igep0020.dts rename to arch/arm/boot/dts/ti/omap/omap3-igep0020.dts index 3f0197ceae09e6ba057873506a0808d51af66e73..232cf91878223a10379a946b047dedc6f1c92fbd 100644 --- a/arch/arm/boot/dts/omap3-igep0020.dts +++ b/arch/arm/boot/dts/ti/omap/omap3-igep0020.dts @@ -27,7 +27,7 @@ }; &omap3_pmx_core { - lbee1usjyc_pins: pinmux_lbee1usjyc_pins { + lbee1usjyc_pins: lbee1usjyc-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x2166, PIN_OUTPUT | MUX_MODE4) /* sdmmc2_dat5.gpio_137 - RESET_N_W */ OMAP3_CORE1_IOPAD(0x2168, PIN_OUTPUT | MUX_MODE4) /* sdmmc2_dat6.gpio_138 - WIFI_PDN */ diff --git a/arch/arm/boot/dts/omap3-igep0030-common.dtsi b/arch/arm/boot/dts/ti/omap/omap3-igep0030-common.dtsi similarity index 93% rename from arch/arm/boot/dts/omap3-igep0030-common.dtsi rename to arch/arm/boot/dts/ti/omap/omap3-igep0030-common.dtsi index 742e3e14706331b6e25b5a9f66ff3739199f115c..d434f75aadaca738969832b31b5a35a894718abd 100644 --- a/arch/arm/boot/dts/omap3-igep0030-common.dtsi +++ b/arch/arm/boot/dts/ti/omap/omap3-igep0030-common.dtsi @@ -31,7 +31,7 @@ }; }; - hsusb2_phy: hsusb2_phy { + hsusb2_phy: hsusb2-phy-pins { compatible = "usb-nop-xceiv"; reset-gpios = <&gpio2 22 GPIO_ACTIVE_LOW>; /* gpio_54 */ #phy-cells = <0>; @@ -42,7 +42,7 @@ pinctrl-names = "default"; pinctrl-0 = <&hsusb2_pins>; - hsusb2_pins: pinmux_hsusb2_pins { + hsusb2_pins: hsusb2-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x21d4, PIN_INPUT_PULLDOWN | MUX_MODE3) /* mcspi1_cs3.hsusb2_data2 */ OMAP3_CORE1_IOPAD(0x21d6, PIN_INPUT_PULLDOWN | MUX_MODE3) /* mcspi2_clk.hsusb2_data7 */ @@ -53,7 +53,7 @@ >; }; - uart2_pins: pinmux_uart2_pins { + uart2_pins: uart2-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x216c, PIN_INPUT | MUX_MODE1) /* mcbsp3_dx.uart2_cts */ OMAP3_CORE1_IOPAD(0x216e, PIN_OUTPUT | MUX_MODE1) /* mcbsp3_dr.uart2_rts */ @@ -67,7 +67,7 @@ pinctrl-names = "default"; pinctrl-0 = <&hsusb2_core2_pins>; - hsusb2_core2_pins: pinmux_hsusb2_core2_pins { + hsusb2_core2_pins: hsusb2-core2-pins { pinctrl-single,pins = < OMAP3630_CORE2_IOPAD(0x25f0, PIN_OUTPUT | MUX_MODE3) /* etk_d10.hsusb2_clk */ OMAP3630_CORE2_IOPAD(0x25f2, PIN_OUTPUT | MUX_MODE3) /* etk_d11.hsusb2_stp */ @@ -78,7 +78,7 @@ >; }; - leds_core2_pins: pinmux_leds_core2_pins { + leds_core2_pins: leds-core2-pins { pinctrl-single,pins = < OMAP3630_CORE2_IOPAD(0x25e0, PIN_OUTPUT | MUX_MODE4) /* etk_d2.gpio_16 */ >; diff --git a/arch/arm/boot/dts/omap3-igep0030-rev-g.dts b/arch/arm/boot/dts/ti/omap/omap3-igep0030-rev-g.dts similarity index 96% rename from arch/arm/boot/dts/omap3-igep0030-rev-g.dts rename to arch/arm/boot/dts/ti/omap/omap3-igep0030-rev-g.dts index bc95a8df2e6a1ee2a2c60a86cd1d950d910c6861..fddd7c86fec4bad367d8b650b01a8ca65f98a9f4 100644 --- a/arch/arm/boot/dts/omap3-igep0030-rev-g.dts +++ b/arch/arm/boot/dts/ti/omap/omap3-igep0030-rev-g.dts @@ -24,7 +24,7 @@ }; &omap3_pmx_core { - lbep5clwmc_pins: pinmux_lbep5clwmc_pins { + lbep5clwmc_pins: lbep5clwmc-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x2164, PIN_INPUT | MUX_MODE4) /* sdmmc2_dat4.gpio_136 - W_IRQ */ OMAP3_CORE1_IOPAD(0x2166, PIN_OUTPUT | MUX_MODE4) /* sdmmc2_dat5.gpio_137 - BT_EN */ @@ -32,7 +32,7 @@ >; }; - leds_pins: pinmux_leds_pins { + leds_pins: leds-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x21be, PIN_OUTPUT | MUX_MODE4) /* i2c2_scl.gpio_168 */ >; diff --git a/arch/arm/boot/dts/omap3-igep0030.dts b/arch/arm/boot/dts/ti/omap/omap3-igep0030.dts similarity index 97% rename from arch/arm/boot/dts/omap3-igep0030.dts rename to arch/arm/boot/dts/ti/omap/omap3-igep0030.dts index d36ceecb7328cb9c17ab6a853584d6e0bd5cd829..e3f99dbef2a10c944fec49c01eeb7cfce1674275 100644 --- a/arch/arm/boot/dts/omap3-igep0030.dts +++ b/arch/arm/boot/dts/ti/omap/omap3-igep0030.dts @@ -27,7 +27,7 @@ }; &omap3_pmx_core { - lbee1usjyc_pins: pinmux_lbee1usjyc_pins { + lbee1usjyc_pins: lbee1usjyc-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x2166, PIN_OUTPUT | MUX_MODE4) /* sdmmc2_dat5.gpio_137 - RESET_N_W */ OMAP3_CORE1_IOPAD(0x2168, PIN_OUTPUT | MUX_MODE4) /* sdmmc2_dat6.gpio_138 - WIFI_PDN */ diff --git a/arch/arm/boot/dts/omap3-ldp.dts b/arch/arm/boot/dts/ti/omap/omap3-ldp.dts similarity index 98% rename from arch/arm/boot/dts/omap3-ldp.dts rename to arch/arm/boot/dts/ti/omap/omap3-ldp.dts index 85f33bbb566f9f22f8d3725d259d55cba7f4dc64..bb6fab9fa47dfd6a190d94e4cfdb048728e29028 100644 --- a/arch/arm/boot/dts/omap3-ldp.dts +++ b/arch/arm/boot/dts/ti/omap/omap3-ldp.dts @@ -223,7 +223,7 @@ }; &omap3_pmx_core { - gpio_key_pins: pinmux_gpio_key_pins { + gpio_key_pins: gpio-key-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x211a, PIN_INPUT | MUX_MODE4) /* cam_d2.gpio_101 */ OMAP3_CORE1_IOPAD(0x211c, PIN_INPUT | MUX_MODE4) /* cam_d3.gpio_102 */ @@ -237,7 +237,7 @@ >; }; - musb_pins: pinmux_musb_pins { + musb_pins: musb-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x21a2, PIN_INPUT | MUX_MODE0) /* hsusb0_clk.hsusb0_clk */ OMAP3_CORE1_IOPAD(0x21aa, PIN_INPUT | MUX_MODE0) /* hsusb0_data0.hsusb0_data0 */ @@ -254,7 +254,7 @@ >; }; - mmc1_pins: pinmux_mmc1_pins { + mmc1_pins: mmc1-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x2144, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_clk.mmc1_clk */ OMAP3_CORE1_IOPAD(0x2146, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_cmd.mmc1_cmd */ diff --git a/arch/arm/boot/dts/omap3-lilly-a83x.dtsi b/arch/arm/boot/dts/ti/omap/omap3-lilly-a83x.dtsi similarity index 95% rename from arch/arm/boot/dts/omap3-lilly-a83x.dtsi rename to arch/arm/boot/dts/ti/omap/omap3-lilly-a83x.dtsi index d310b5c7bac362e8e2ae24e512d3667841fc9752..565a6c0e7b37d51b7ce8e7ed100f827c4629a0a0 100644 --- a/arch/arm/boot/dts/omap3-lilly-a83x.dtsi +++ b/arch/arm/boot/dts/ti/omap/omap3-lilly-a83x.dtsi @@ -54,19 +54,19 @@ &omap3_pmx_wkup { pinctrl-names = "default"; - lan9221_pins: pinmux_lan9221_pins { + lan9221_pins: lan9221-pins { pinctrl-single,pins = < OMAP3_WKUP_IOPAD(0x2a5a, PIN_INPUT | MUX_MODE4) /* reserved.gpio_129 */ >; }; - tsc2048_pins: pinmux_tsc2048_pins { + tsc2048_pins: tsc2048-pins { pinctrl-single,pins = < OMAP3_WKUP_IOPAD(0x2a16, PIN_INPUT_PULLUP | MUX_MODE4) /* sys_boot6.gpio_8 */ >; }; - mmc1cd_pins: pinmux_mmc1cd_pins { + mmc1cd_pins: mmc1cd-pins { pinctrl-single,pins = < OMAP3_WKUP_IOPAD(0x2a56, PIN_INPUT | MUX_MODE4) /* reserved.gpio_126 */ >; @@ -76,7 +76,7 @@ &omap3_pmx_core { pinctrl-names = "default"; - uart1_pins: pinmux_uart1_pins { + uart1_pins: uart1-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x217c, PIN_OUTPUT | MUX_MODE0) /* uart1_tx.uart1_tx */ OMAP3_CORE1_IOPAD(0x217e, PIN_OUTPUT | MUX_MODE0) /* uart1_rts.uart1_rts */ @@ -85,42 +85,42 @@ >; }; - uart2_pins: pinmux_uart2_pins { + uart2_pins: uart2-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x2170, PIN_OUTPUT | MUX_MODE1) /* mcbsp3_clkx.uart2_tx */ OMAP3_CORE1_IOPAD(0x2172, PIN_INPUT | MUX_MODE1) /* mcbsp3_fsx.uart2_rx */ >; }; - uart3_pins: pinmux_uart3_pins { + uart3_pins: uart3-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x219e, PIN_INPUT | MUX_MODE0) /* uart3_rx_irrx.uart3_rx_irrx */ OMAP3_CORE1_IOPAD(0x21a0, PIN_OUTPUT | MUX_MODE0) /* uart3_tx_irtx.uart3_tx_irtx */ >; }; - i2c1_pins: pinmux_i2c1_pins { + i2c1_pins: i2c1-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x21ba ,PIN_INPUT_PULLUP | MUX_MODE0) /* i2c1_scl.i2c1_scl */ OMAP3_CORE1_IOPAD(0x21bc ,PIN_INPUT_PULLUP | MUX_MODE0) /* i2c1_sda.i2c1_sda */ >; }; - i2c2_pins: pinmux_i2c2_pins { + i2c2_pins: i2c2-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x21be, PIN_INPUT | MUX_MODE0) /* i2c2_scl.i2c2_scl */ OMAP3_CORE1_IOPAD(0x21c0, PIN_INPUT | MUX_MODE0) /* i2c2_sda.i2c2_sda */ >; }; - i2c3_pins: pinmux_i2c3_pins { + i2c3_pins: i2c3-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x21c2, PIN_INPUT | MUX_MODE0) /* i2c3_scl.i2c3_scl */ OMAP3_CORE1_IOPAD(0x21c4, PIN_INPUT | MUX_MODE0) /* i2c3_sda.i2c3_sda */ >; }; - hsusb1_pins: pinmux_hsusb1_pins { + hsusb1_pins: hsusb1-pins { pinctrl-single,pins = < /* GPIO 182 controls USB-Hub reset. But USB-Phy its @@ -132,7 +132,7 @@ >; }; - hsusb_otg_pins: pinmux_hsusb_otg_pins { + hsusb_otg_pins: hsusb-otg-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x21a2, PIN_INPUT | MUX_MODE0) /* hsusb0_clk.hsusb0_clk */ OMAP3_CORE1_IOPAD(0x21a4, PIN_OUTPUT | MUX_MODE0) /* hsusb0_stp.hsusb0_stp */ @@ -149,7 +149,7 @@ >; }; - mmc1_pins: pinmux_mmc1_pins { + mmc1_pins: mmc1-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x2144, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc1_clk.sdmmc1_clk */ OMAP3_CORE1_IOPAD(0x2146, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc1_cmd.sdmmc1_cmd */ @@ -160,7 +160,7 @@ >; }; - spi2_pins: pinmux_spi2_pins { + spi2_pins: spi2-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x21d6, PIN_INPUT_PULLDOWN | MUX_MODE0) /* mcspi2_clk.mcspi2_clk */ OMAP3_CORE1_IOPAD(0x21d8, PIN_INPUT_PULLDOWN | MUX_MODE0) /* mcspi2_simo.mcspi2_simo */ @@ -173,7 +173,7 @@ &omap3_pmx_core2 { pinctrl-names = "default"; - hsusb1_2_pins: pinmux_hsusb1_2_pins { + hsusb1_2_pins: hsusb1-2-pins { pinctrl-single,pins = < OMAP3630_CORE2_IOPAD(0x25d8, PIN_OUTPUT | MUX_MODE3) /* etk_clk.hsusb1_stp */ OMAP3630_CORE2_IOPAD(0x25da, PIN_INPUT | MUX_MODE3) /* etk_ctl.hsusb1_clk */ @@ -190,7 +190,7 @@ >; }; - gpio1_pins: pinmux_gpio1_pins { + gpio1_pins: gpio1-pins { pinctrl-single,pins = < OMAP3630_CORE2_IOPAD(0x25fa, PIN_OUTPUT_PULLDOWN | MUX_MODE4) /* etk_d15.gpio_29 */ >; diff --git a/arch/arm/boot/dts/omap3-lilly-dbb056.dts b/arch/arm/boot/dts/ti/omap/omap3-lilly-dbb056.dts similarity index 96% rename from arch/arm/boot/dts/omap3-lilly-dbb056.dts rename to arch/arm/boot/dts/ti/omap/omap3-lilly-dbb056.dts index f6bbea2be54c59407ace337d4eeb2c0792b172d4..0891c6682a67e29de8712c3a57cf3c7c9fa1be9b 100644 --- a/arch/arm/boot/dts/omap3-lilly-dbb056.dts +++ b/arch/arm/boot/dts/ti/omap/omap3-lilly-dbb056.dts @@ -24,25 +24,25 @@ pinctrl-names = "default"; pinctrl-0 = <&lcd_pins>; - lan9117_pins: pinmux_lan9117_pins { + lan9117_pins: lan9117-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x2114, PIN_INPUT | MUX_MODE4) /* cam_fld.gpio_98 */ >; }; - gpio4_pins: pinmux_gpio4_pins { + gpio4_pins: gpio4-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x212e, PIN_INPUT | MUX_MODE4) /* cam_xclkb.gpio_111 -> sja1000 IRQ */ >; }; - gpio5_pins: pinmux_gpio5_pins { + gpio5_pins: gpio5-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x218c, PIN_OUTPUT | PIN_OFF_OUTPUT_HIGH | MUX_MODE4) /* mcbsp1_clk.gpio_156 -> enable DSS */ >; }; - lcd_pins: pinmux_lcd_pins { + lcd_pins: lcd-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x20d4, PIN_OUTPUT | MUX_MODE0) /* dss_pclk.dss_pclk */ OMAP3_CORE1_IOPAD(0x20d6, PIN_OUTPUT | MUX_MODE0) /* dss_hsync.dss_hsync */ @@ -69,7 +69,7 @@ >; }; - mmc2_pins: pinmux_mmc2_pins { + mmc2_pins: mmc2-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x2158, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc2_clk.sdmmc2_clk */ OMAP3_CORE1_IOPAD(0x215a, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc2_cmd.sdmmc2_cmd */ @@ -86,7 +86,7 @@ >; }; - spi1_pins: pinmux_spi1_pins { + spi1_pins: spi1-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x21c8, PIN_INPUT | MUX_MODE0) /* mcspi1_clk.mcspi1_clk */ OMAP3_CORE1_IOPAD(0x21ca, PIN_INPUT | MUX_MODE0) /* mcspi1_simo.mcspi1_simo */ diff --git a/arch/arm/boot/dts/omap3-n9.dts b/arch/arm/boot/dts/ti/omap/omap3-n9.dts similarity index 100% rename from arch/arm/boot/dts/omap3-n9.dts rename to arch/arm/boot/dts/ti/omap/omap3-n9.dts diff --git a/arch/arm/boot/dts/omap3-n900.dts b/arch/arm/boot/dts/ti/omap/omap3-n900.dts similarity index 98% rename from arch/arm/boot/dts/omap3-n900.dts rename to arch/arm/boot/dts/ti/omap/omap3-n900.dts index f9f9eca0c56ccfaaeba12b106050aa92a511f3cf..d334853412517378b460577067da2241cde0d319 100644 --- a/arch/arm/boot/dts/omap3-n900.dts +++ b/arch/arm/boot/dts/ti/omap/omap3-n900.dts @@ -209,7 +209,7 @@ &omap3_pmx_core { pinctrl-names = "default"; - uart2_pins: pinmux_uart2_pins { + uart2_pins: uart2-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x2174, PIN_INPUT_PULLUP | MUX_MODE0) /* uart2_cts */ OMAP3_CORE1_IOPAD(0x2176, PIN_OUTPUT | MUX_MODE0) /* uart2_rts */ @@ -218,14 +218,14 @@ >; }; - uart3_pins: pinmux_uart3_pins { + uart3_pins: uart3-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x219e, PIN_INPUT | MUX_MODE0) /* uart3_rx */ OMAP3_CORE1_IOPAD(0x21a0, PIN_OUTPUT | MUX_MODE0) /* uart3_tx */ >; }; - ethernet_pins: pinmux_ethernet_pins { + ethernet_pins: ethernet-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x20b4, PIN_INPUT_PULLDOWN | MUX_MODE4) /* gpmc_ncs3.gpio_54 */ OMAP3_CORE1_IOPAD(0x20fc, PIN_OUTPUT | MUX_MODE4) /* dss_data16.gpio_86 */ @@ -233,7 +233,7 @@ >; }; - gpmc_pins: pinmux_gpmc_pins { + gpmc_pins: gpmc-pins { pinctrl-single,pins = < /* address lines */ @@ -260,34 +260,34 @@ >; }; - i2c1_pins: pinmux_i2c1_pins { + i2c1_pins: i2c1-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x21ba, PIN_INPUT | MUX_MODE0) /* i2c1_scl */ OMAP3_CORE1_IOPAD(0x21bc, PIN_INPUT | MUX_MODE0) /* i2c1_sda */ >; }; - i2c2_pins: pinmux_i2c2_pins { + i2c2_pins: i2c2-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x21be, PIN_INPUT | MUX_MODE0) /* i2c2_scl */ OMAP3_CORE1_IOPAD(0x21c0, PIN_INPUT | MUX_MODE0) /* i2c2_sda */ >; }; - i2c3_pins: pinmux_i2c3_pins { + i2c3_pins: i2c3-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x21c2, PIN_INPUT | MUX_MODE0) /* i2c3_scl */ OMAP3_CORE1_IOPAD(0x21c4, PIN_INPUT | MUX_MODE0) /* i2c3_sda */ >; }; - debug_leds: pinmux_debug_led_pins { + debug_leds: debug-led-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x2198, PIN_OUTPUT | MUX_MODE4) /* mcbsp1_clkx.gpio_162 */ >; }; - mcspi4_pins: pinmux_mcspi4_pins { + mcspi4_pins: mcspi4-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x218c, PIN_INPUT_PULLDOWN | MUX_MODE1) /* mcspi4_clk */ OMAP3_CORE1_IOPAD(0x2192, PIN_INPUT_PULLDOWN | MUX_MODE1) /* mcspi4_somi */ @@ -296,7 +296,7 @@ >; }; - mmc1_pins: pinmux_mmc1_pins { + mmc1_pins: mmc1-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x2144, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc1_clk */ OMAP3_CORE1_IOPAD(0x2146, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc1_cmd */ @@ -307,7 +307,7 @@ >; }; - mmc2_pins: pinmux_mmc2_pins { + mmc2_pins: mmc2-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x2158, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc2_clk */ OMAP3_CORE1_IOPAD(0x215a, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc2_cmd */ @@ -322,13 +322,13 @@ >; }; - acx565akm_pins: pinmux_acx565akm_pins { + acx565akm_pins: acx565akm-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x2104, PIN_OUTPUT | MUX_MODE4) /* RX51_LCD_RESET_GPIO */ >; }; - dss_sdi_pins: pinmux_dss_sdi_pins { + dss_sdi_pins: dss-sdi-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x20f0, PIN_OUTPUT | MUX_MODE1) /* dss_data10.sdi_dat1n */ OMAP3_CORE1_IOPAD(0x20f2, PIN_OUTPUT | MUX_MODE1) /* dss_data11.sdi_dat1p */ @@ -340,14 +340,14 @@ >; }; - wl1251_pins: pinmux_wl1251 { + wl1251_pins: wl1251-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x20fe, PIN_OUTPUT | MUX_MODE4) /* gpio 87 => wl1251 enable */ OMAP3_CORE1_IOPAD(0x208a, PIN_INPUT | MUX_MODE4) /* gpio 42 => wl1251 irq */ >; }; - ssi_pins: pinmux_ssi { + ssi_pins: ssi-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x2180, PIN_INPUT_PULLUP | MUX_MODE1) /* ssi1_rdy_tx */ OMAP3_CORE1_IOPAD(0x217e, PIN_OUTPUT | MUX_MODE1) /* ssi1_flag_tx */ @@ -360,7 +360,7 @@ >; }; - modem_pins: pinmux_modem { + modem_pins: modem-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x20dc, PIN_OUTPUT | MUX_MODE4) /* gpio 70 => cmt_apeslpx */ OMAP3_CORE1_IOPAD(0x20e0, PIN_INPUT | MUX_MODE4) /* gpio 72 => ape_rst_rq */ @@ -371,7 +371,7 @@ >; }; - camera_pins: pinmux_camera { + camera_pins: camera-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x210c, PIN_OUTPUT | MUX_MODE7) /* cam_hs */ OMAP3_CORE1_IOPAD(0x210e, PIN_OUTPUT | MUX_MODE7) /* cam_vs */ diff --git a/arch/arm/boot/dts/omap3-n950-n9.dtsi b/arch/arm/boot/dts/ti/omap/omap3-n950-n9.dtsi similarity index 97% rename from arch/arm/boot/dts/omap3-n950-n9.dtsi rename to arch/arm/boot/dts/ti/omap/omap3-n950-n9.dtsi index f68da828b0505b58c967cb4a68ea21d46792acbe..aa4fcdbedd8fbad0d6c29363f4d9c3e71cf1f958 100644 --- a/arch/arm/boot/dts/omap3-n950-n9.dtsi +++ b/arch/arm/boot/dts/ti/omap/omap3-n950-n9.dtsi @@ -57,20 +57,20 @@ }; &omap3_pmx_core { - accelerator_pins: pinmux_accelerator_pins { + accelerator_pins: accelerator-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x21da, PIN_INPUT | MUX_MODE4) /* mcspi2_somi.gpio_180 -> LIS302 INT1 */ OMAP3_CORE1_IOPAD(0x21dc, PIN_INPUT | MUX_MODE4) /* mcspi2_cs0.gpio_181 -> LIS302 INT2 */ >; }; - debug_leds: pinmux_debug_led_pins { + debug_leds: debug-led-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x2108, PIN_OUTPUT | MUX_MODE4) /* dss_data22.gpio_92 */ >; }; - mmc2_pins: pinmux_mmc2_pins { + mmc2_pins: mmc2-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x2158, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc2_clk */ OMAP3_CORE1_IOPAD(0x215a, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc2_cmd */ @@ -81,14 +81,14 @@ >; }; - wlan_pins: pinmux_wlan_pins { + wlan_pins: wlan-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x207c, PIN_OUTPUT | MUX_MODE4) /* gpio 35 - wlan enable */ OMAP3_CORE1_IOPAD(0x208a, PIN_INPUT | MUX_MODE4) /* gpio 42 - wlan irq */ >; }; - ssi_pins: pinmux_ssi_pins { + ssi_pins: ssi-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x217c, PIN_OUTPUT | MUX_MODE1) /* ssi1_dat_tx */ OMAP3_CORE1_IOPAD(0x217e, PIN_OUTPUT | MUX_MODE1) /* ssi1_flag_tx */ @@ -101,7 +101,7 @@ >; }; - ssi_pins_idle: pinmux_ssi_pins_idle { + ssi_pins_idle: ssi-idle-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x217c, PIN_OUTPUT | MUX_MODE7) /* ssi1_dat_tx */ OMAP3_CORE1_IOPAD(0x217e, PIN_OUTPUT | MUX_MODE7) /* ssi1_flag_tx */ @@ -114,7 +114,7 @@ >; }; - modem_pins1: pinmux_modem_core1_pins { + modem_pins1: modem-core1-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x207a, PIN_INPUT | MUX_MODE4) /* gpio_34 (ape_rst_rq) */ OMAP3_CORE1_IOPAD(0x2100, PIN_OUTPUT | MUX_MODE4) /* gpio_88 (cmt_rst_rq) */ @@ -122,7 +122,7 @@ >; }; - uart2_pins: pinmux_uart2_pins { + uart2_pins: uart2-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x2174, PIN_INPUT_PULLUP | MUX_MODE0) /* uart2_cts */ OMAP3_CORE1_IOPAD(0x2176, PIN_OUTPUT | MUX_MODE0) /* uart2_rts */ @@ -133,7 +133,7 @@ }; &omap3_pmx_core2 { - modem_pins2: pinmux_modem_core2_pins { + modem_pins2: modem-core2-pins { pinctrl-single,pins = < OMAP3630_CORE2_IOPAD(0x25ec, PIN_OUTPUT | MUX_MODE4) /* gpio_23 (cmt_en) */ >; diff --git a/arch/arm/boot/dts/omap3-n950.dts b/arch/arm/boot/dts/ti/omap/omap3-n950.dts similarity index 97% rename from arch/arm/boot/dts/omap3-n950.dts rename to arch/arm/boot/dts/ti/omap/omap3-n950.dts index cbaf79c4e8422a19eccdc58c37aae522fe2fc322..b99f97880204dae796777adda76631a7b7cc61bc 100644 --- a/arch/arm/boot/dts/omap3-n950.dts +++ b/arch/arm/boot/dts/ti/omap/omap3-n950.dts @@ -30,7 +30,7 @@ }; &omap3_pmx_core { - keypad_slide_pins: pinmux_debug_led_pins { + keypad_slide_pins: debug-led-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x212a, PIN_INPUT | MUX_MODE4) /* cam_d10.gpio_109 */ >; @@ -38,7 +38,7 @@ }; &omap3_pmx_core { - spi4_pins: pinmux_spi4_pins { + spi4_pins: spi4-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x218c, PIN_INPUT_PULLDOWN | MUX_MODE1) /* mcspi4_clk */ OMAP3_CORE1_IOPAD(0x2190, PIN_OUTPUT | MUX_MODE1) /* mcspi4_simo */ @@ -49,7 +49,7 @@ }; &omap3_pmx_core { - dsi_pins: pinmux_dsi_pins { + dsi_pins: dsi-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x20dc, PIN_OUTPUT | MUX_MODE1) /* dsi_dx0 - data0+ */ OMAP3_CORE1_IOPAD(0x20de, PIN_OUTPUT | MUX_MODE1) /* dsi_dy0 - data0- */ @@ -60,7 +60,7 @@ >; }; - display_pins: pinmux_display_pins { + display_pins: display-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x20ca, PIN_INPUT | MUX_MODE4) /* gpio 62 - display te */ OMAP3_CORE1_IOPAD(0x20fe, PIN_OUTPUT | MUX_MODE4) /* gpio 87 - display reset */ diff --git a/arch/arm/boot/dts/omap3-overo-alto35-common.dtsi b/arch/arm/boot/dts/ti/omap/omap3-overo-alto35-common.dtsi similarity index 96% rename from arch/arm/boot/dts/omap3-overo-alto35-common.dtsi rename to arch/arm/boot/dts/ti/omap/omap3-overo-alto35-common.dtsi index a6dbbba799b2ebdbe8713e90fda1a01d51bbc78f..7f1671bf3dfacb27e4c65cf6b4ed7cd3f6fe1841 100644 --- a/arch/arm/boot/dts/omap3-overo-alto35-common.dtsi +++ b/arch/arm/boot/dts/ti/omap/omap3-overo-alto35-common.dtsi @@ -51,7 +51,7 @@ }; &omap3_pmx_core { - led_pins: pinmux_led_pins { + led_pins: led-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x217c, PIN_OUTPUT | MUX_MODE4) /* uart1_tx.gpio_148 */ OMAP3_CORE1_IOPAD(0x2180, PIN_OUTPUT | MUX_MODE4) /* uart1_cts.gpio_150 */ @@ -62,7 +62,7 @@ }; &omap3_pmx_wkup { - button_pins: pinmux_button_pins { + button_pins: button-pins { pinctrl-single,pins = < OMAP3_WKUP_IOPAD(0x2a18, PIN_INPUT | MUX_MODE4) /* sys_clkout1.gpio_10 */ >; diff --git a/arch/arm/boot/dts/omap3-overo-alto35.dts b/arch/arm/boot/dts/ti/omap/omap3-overo-alto35.dts similarity index 100% rename from arch/arm/boot/dts/omap3-overo-alto35.dts rename to arch/arm/boot/dts/ti/omap/omap3-overo-alto35.dts diff --git a/arch/arm/boot/dts/omap3-overo-base.dtsi b/arch/arm/boot/dts/ti/omap/omap3-overo-base.dtsi similarity index 96% rename from arch/arm/boot/dts/omap3-overo-base.dtsi rename to arch/arm/boot/dts/ti/omap/omap3-overo-base.dtsi index adc714c398257b7075e4a65d48ea7efb465cf6c9..cc57626ea6076daffc4a59d09de500ddb091a032 100644 --- a/arch/arm/boot/dts/omap3-overo-base.dtsi +++ b/arch/arm/boot/dts/ti/omap/omap3-overo-base.dtsi @@ -44,7 +44,7 @@ }; /* HS USB Host PHY on PORT 2 */ - hsusb2_phy: hsusb2_phy { + hsusb2_phy: hsusb2-phy-pins { compatible = "usb-nop-xceiv"; reset-gpios = <&gpio6 23 GPIO_ACTIVE_LOW>; /* gpio_183 */ vcc-supply = <&hsusb2_power>; @@ -80,7 +80,7 @@ &hsusb2_pins >; - uart2_pins: pinmux_uart2_pins { + uart2_pins: uart2-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x216c, PIN_INPUT | MUX_MODE1) /* mcbsp3_dx.uart2_cts */ OMAP3_CORE1_IOPAD(0x216e, PIN_OUTPUT | MUX_MODE1) /* mcbsp3_dr.uart2_rts */ @@ -89,14 +89,14 @@ >; }; - i2c1_pins: pinmux_i2c1_pins { + i2c1_pins: i2c1-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x21ba, PIN_INPUT | MUX_MODE0) /* i2c1_scl.i2c1_scl */ OMAP3_CORE1_IOPAD(0x21bc, PIN_INPUT | MUX_MODE0) /* i2c1_sda.i2c1_sda */ >; }; - mmc1_pins: pinmux_mmc1_pins { + mmc1_pins: mmc1-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x2144, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc1_clk.sdmmc1_clk */ OMAP3_CORE1_IOPAD(0x2146, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc1_cmd.sdmmc1_cmd */ @@ -107,7 +107,7 @@ >; }; - mmc2_pins: pinmux_mmc2_pins { + mmc2_pins: mmc2-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x2158, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc2_clk.sdmmc2_clk */ OMAP3_CORE1_IOPAD(0x215a, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc2_cmd.sdmmc2_cmd */ @@ -119,14 +119,14 @@ }; /* WiFi/BT combo */ - w3cbw003c_pins: pinmux_w3cbw003c_pins { + w3cbw003c_pins: w3cbw003c-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x20b4, PIN_OUTPUT | MUX_MODE4) /* gpmc_ncs3.gpio_54 */ OMAP3_CORE1_IOPAD(0x219c, PIN_OUTPUT | MUX_MODE4) /* uart3_rts_sd.gpio_164 */ >; }; - hsusb2_pins: pinmux_hsusb2_pins { + hsusb2_pins: hsusb2-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x21d4, PIN_INPUT_PULLDOWN | MUX_MODE3) /* mcspi1_cs3.hsusb2_data2 */ OMAP3_CORE1_IOPAD(0x21d6, PIN_INPUT_PULLDOWN | MUX_MODE3) /* mcspi2_clk.hsusb2_data7 */ diff --git a/arch/arm/boot/dts/omap3-overo-chestnut43-common.dtsi b/arch/arm/boot/dts/ti/omap/omap3-overo-chestnut43-common.dtsi similarity index 100% rename from arch/arm/boot/dts/omap3-overo-chestnut43-common.dtsi rename to arch/arm/boot/dts/ti/omap/omap3-overo-chestnut43-common.dtsi diff --git a/arch/arm/boot/dts/omap3-overo-chestnut43.dts b/arch/arm/boot/dts/ti/omap/omap3-overo-chestnut43.dts similarity index 92% rename from arch/arm/boot/dts/omap3-overo-chestnut43.dts rename to arch/arm/boot/dts/ti/omap/omap3-overo-chestnut43.dts index d147d704b89f1a8730757029122e20ecb253c9e0..bb53c76fff6ca59db6e83c5ae5f69e78d4ac4ad0 100644 --- a/arch/arm/boot/dts/omap3-overo-chestnut43.dts +++ b/arch/arm/boot/dts/ti/omap/omap3-overo-chestnut43.dts @@ -18,14 +18,14 @@ }; &omap3_pmx_core2 { - led_pins: pinmux_led_pins { + led_pins: led-pins { pinctrl-single,pins = < OMAP3430_CORE2_IOPAD(0x25ea, PIN_OUTPUT | MUX_MODE4) /* etk_d7.gpio_21 */ OMAP3430_CORE2_IOPAD(0x25ec, PIN_OUTPUT | MUX_MODE4) /* etk_d8.gpio_22 */ >; }; - button_pins: pinmux_button_pins { + button_pins: button-pins { pinctrl-single,pins = < OMAP3430_CORE2_IOPAD(0x25ee, PIN_INPUT | MUX_MODE4) /* etk_d9.gpio_23 */ OMAP3430_CORE2_IOPAD(0x25dc, PIN_INPUT | MUX_MODE4) /* etk_d0.gpio_14 */ diff --git a/arch/arm/boot/dts/omap3-overo-common-dvi.dtsi b/arch/arm/boot/dts/ti/omap/omap3-overo-common-dvi.dtsi similarity index 98% rename from arch/arm/boot/dts/omap3-overo-common-dvi.dtsi rename to arch/arm/boot/dts/ti/omap/omap3-overo-common-dvi.dtsi index 339a51fa41198063c359c6188a5f2412e15b05f7..b1a800f2e940da6481ec9eb10facf2e44cb52c72 100644 --- a/arch/arm/boot/dts/omap3-overo-common-dvi.dtsi +++ b/arch/arm/boot/dts/ti/omap/omap3-overo-common-dvi.dtsi @@ -8,7 +8,7 @@ */ &omap3_pmx_core { - dss_dpi_pins: pinmux_dss_dpi_pins { + dss_dpi_pins: dss-dpi-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x20d4, PIN_OUTPUT | MUX_MODE0) /* dss_pclk.dss_pclk */ OMAP3_CORE1_IOPAD(0x20d6, PIN_OUTPUT | MUX_MODE0) /* dss_hsync.dss_hsync */ diff --git a/arch/arm/boot/dts/omap3-overo-common-lcd35.dtsi b/arch/arm/boot/dts/ti/omap/omap3-overo-common-lcd35.dtsi similarity index 96% rename from arch/arm/boot/dts/omap3-overo-common-lcd35.dtsi rename to arch/arm/boot/dts/ti/omap/omap3-overo-common-lcd35.dtsi index c3570acc35fadaabafeb7ea1433b6322535b322f..0da561a23f36b967b8e553de502de6012c6124c6 100644 --- a/arch/arm/boot/dts/omap3-overo-common-lcd35.dtsi +++ b/arch/arm/boot/dts/ti/omap/omap3-overo-common-lcd35.dtsi @@ -8,7 +8,7 @@ */ &omap3_pmx_core { - dss_dpi_pins: pinmux_dss_dpi_pins { + dss_dpi_pins: dss-dpi-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x20d4, PIN_OUTPUT | MUX_MODE0) /* dss_pclk.dss_pclk */ OMAP3_CORE1_IOPAD(0x20d6, PIN_OUTPUT | MUX_MODE0) /* dss_hsync.dss_hsync */ @@ -41,19 +41,19 @@ >; }; - lb035_pins: pinmux_lb035_pins { + lb035_pins: lb035-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x2174, PIN_OUTPUT | MUX_MODE4) /* uart2_cts.gpio_144 */ >; }; - backlight_pins: pinmux_backlight_pins { + backlight_pins: backlight-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x2176, PIN_OUTPUT | MUX_MODE4) /* uart2_rts.gpio_145 */ >; }; - mcspi1_pins: pinmux_mcspi1_pins { + mcspi1_pins: mcspi1-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x21c8, PIN_INPUT | MUX_MODE0) /* mcspi1_clk.mcspi1_clk */ OMAP3_CORE1_IOPAD(0x21ca, PIN_INPUT | MUX_MODE0) /* mcspi1_simo.mcspi1_simo */ @@ -63,7 +63,7 @@ >; }; - ads7846_pins: pinmux_ads7846_pins { + ads7846_pins: ads7846-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x2138, PIN_INPUT_PULLDOWN | MUX_MODE4) /* csi2_dx1.gpio_114 */ >; diff --git a/arch/arm/boot/dts/omap3-overo-common-lcd43.dtsi b/arch/arm/boot/dts/ti/omap/omap3-overo-common-lcd43.dtsi similarity index 96% rename from arch/arm/boot/dts/omap3-overo-common-lcd43.dtsi rename to arch/arm/boot/dts/ti/omap/omap3-overo-common-lcd43.dtsi index d95a0e130058cbe7c6ef3c1c3771970f77d48bea..981f02f088f85a79b3e9d38e718de8fcdd09cb1e 100644 --- a/arch/arm/boot/dts/omap3-overo-common-lcd43.dtsi +++ b/arch/arm/boot/dts/ti/omap/omap3-overo-common-lcd43.dtsi @@ -8,7 +8,7 @@ */ &omap3_pmx_core { - dss_dpi_pins: pinmux_dss_dpi_pins { + dss_dpi_pins: dss-dpi-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x20d4, PIN_OUTPUT | MUX_MODE0) /* dss_pclk.dss_pclk */ OMAP3_CORE1_IOPAD(0x20d6, PIN_OUTPUT | MUX_MODE0) /* dss_hsync.dss_hsync */ @@ -41,19 +41,19 @@ >; }; - lte430_pins: pinmux_lte430_pins { + lte430_pins: lte430-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x2174, PIN_OUTPUT | MUX_MODE4) /* uart2_cts.gpio_144 */ >; }; - backlight_pins: pinmux_backlight_pins { + backlight_pins: backlight-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x2176, PIN_OUTPUT | MUX_MODE4) /* uart2_rts.gpio_145 */ >; }; - mcspi1_pins: pinmux_mcspi1_pins { + mcspi1_pins: mcspi1-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x21c8, PIN_INPUT | MUX_MODE0) /* mcspi1_clk.mcspi1_clk */ OMAP3_CORE1_IOPAD(0x21ca, PIN_INPUT | MUX_MODE0) /* mcspi1_simo.mcspi1_simo */ @@ -62,7 +62,7 @@ >; }; - ads7846_pins: pinmux_ads7846_pins { + ads7846_pins: ads7846-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x2138, PIN_INPUT_PULLDOWN | MUX_MODE4) /* csi2_dx1.gpio_114 */ >; diff --git a/arch/arm/boot/dts/omap3-overo-common-peripherals.dtsi b/arch/arm/boot/dts/ti/omap/omap3-overo-common-peripherals.dtsi similarity index 96% rename from arch/arm/boot/dts/omap3-overo-common-peripherals.dtsi rename to arch/arm/boot/dts/ti/omap/omap3-overo-common-peripherals.dtsi index 8a4a02472c9a37456b1296999c55a265fd89938d..00369f699e2078d8e044e77230d8316219c00f3a 100644 --- a/arch/arm/boot/dts/omap3-overo-common-peripherals.dtsi +++ b/arch/arm/boot/dts/ti/omap/omap3-overo-common-peripherals.dtsi @@ -24,14 +24,14 @@ }; &omap3_pmx_core { - i2c3_pins: pinmux_i2c3_pins { + i2c3_pins: i2c3-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x21c2, PIN_INPUT | MUX_MODE0) /* i2c3_scl.i2c3_scl */ OMAP3_CORE1_IOPAD(0x21c4, PIN_INPUT | MUX_MODE0) /* i2c3_sda.i2c3_sda */ >; }; - uart3_pins: pinmux_uart3_pins { + uart3_pins: uart3-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x219e, PIN_INPUT | MUX_MODE0) /* uart3_rx_irrx.uart3_rx_irrx */ OMAP3_CORE1_IOPAD(0x21a0, PIN_OUTPUT | MUX_MODE0) /* uart3_tx_irtx.uart3_tx_irtx */ diff --git a/arch/arm/boot/dts/omap3-overo-gallop43-common.dtsi b/arch/arm/boot/dts/ti/omap/omap3-overo-gallop43-common.dtsi similarity index 100% rename from arch/arm/boot/dts/omap3-overo-gallop43-common.dtsi rename to arch/arm/boot/dts/ti/omap/omap3-overo-gallop43-common.dtsi diff --git a/arch/arm/boot/dts/omap3-overo-gallop43.dts b/arch/arm/boot/dts/ti/omap/omap3-overo-gallop43.dts similarity index 92% rename from arch/arm/boot/dts/omap3-overo-gallop43.dts rename to arch/arm/boot/dts/ti/omap/omap3-overo-gallop43.dts index 24b40bdf7ea1df96d72a2f4898695a72994b79e6..d882a58028c14a4f201b2c703d594fdab6942d38 100644 --- a/arch/arm/boot/dts/omap3-overo-gallop43.dts +++ b/arch/arm/boot/dts/ti/omap/omap3-overo-gallop43.dts @@ -18,14 +18,14 @@ }; &omap3_pmx_core2 { - led_pins: pinmux_led_pins { + led_pins: led-pins { pinctrl-single,pins = < OMAP3430_CORE2_IOPAD(0x25ea, PIN_OUTPUT | MUX_MODE4) /* etk_d7.gpio_21 */ OMAP3430_CORE2_IOPAD(0x25ec, PIN_OUTPUT | MUX_MODE4) /* etk_d8.gpio_22 */ >; }; - button_pins: pinmux_button_pins { + button_pins: button-pins { pinctrl-single,pins = < OMAP3430_CORE2_IOPAD(0x25ee, PIN_INPUT | MUX_MODE4) /* etk_d9.gpio_23 */ OMAP3430_CORE2_IOPAD(0x25dc, PIN_INPUT | MUX_MODE4) /* etk_d0.gpio_14 */ diff --git a/arch/arm/boot/dts/omap3-overo-palo35-common.dtsi b/arch/arm/boot/dts/ti/omap/omap3-overo-palo35-common.dtsi similarity index 100% rename from arch/arm/boot/dts/omap3-overo-palo35-common.dtsi rename to arch/arm/boot/dts/ti/omap/omap3-overo-palo35-common.dtsi diff --git a/arch/arm/boot/dts/omap3-overo-palo35.dts b/arch/arm/boot/dts/ti/omap/omap3-overo-palo35.dts similarity index 92% rename from arch/arm/boot/dts/omap3-overo-palo35.dts rename to arch/arm/boot/dts/ti/omap/omap3-overo-palo35.dts index 55e08d56b18b327d75bd8d56f821007cd30be75f..39c8e9ce57760e050965cb659a85a0913be249ab 100644 --- a/arch/arm/boot/dts/omap3-overo-palo35.dts +++ b/arch/arm/boot/dts/ti/omap/omap3-overo-palo35.dts @@ -18,14 +18,14 @@ }; &omap3_pmx_core2 { - led_pins: pinmux_led_pins { + led_pins: led-pins { pinctrl-single,pins = < OMAP3430_CORE2_IOPAD(0x25ea, PIN_OUTPUT | MUX_MODE4) /* etk_d7.gpio_21 */ OMAP3430_CORE2_IOPAD(0x25ec, PIN_OUTPUT | MUX_MODE4) /* etk_d8.gpio_22 */ >; }; - button_pins: pinmux_button_pins { + button_pins: button-pins { pinctrl-single,pins = < OMAP3430_CORE2_IOPAD(0x25ee, PIN_INPUT | MUX_MODE4) /* etk_d9.gpio_23 */ OMAP3430_CORE2_IOPAD(0x25dc, PIN_INPUT | MUX_MODE4) /* etk_d0.gpio_14 */ diff --git a/arch/arm/boot/dts/omap3-overo-palo43-common.dtsi b/arch/arm/boot/dts/ti/omap/omap3-overo-palo43-common.dtsi similarity index 100% rename from arch/arm/boot/dts/omap3-overo-palo43-common.dtsi rename to arch/arm/boot/dts/ti/omap/omap3-overo-palo43-common.dtsi diff --git a/arch/arm/boot/dts/omap3-overo-palo43.dts b/arch/arm/boot/dts/ti/omap/omap3-overo-palo43.dts similarity index 92% rename from arch/arm/boot/dts/omap3-overo-palo43.dts rename to arch/arm/boot/dts/ti/omap/omap3-overo-palo43.dts index 092c8325a133da800adde120e4498d1a7fa56dcc..2c0f755ec8cc57435a33041b5c79ce3f9024bf49 100644 --- a/arch/arm/boot/dts/omap3-overo-palo43.dts +++ b/arch/arm/boot/dts/ti/omap/omap3-overo-palo43.dts @@ -18,14 +18,14 @@ }; &omap3_pmx_core2 { - led_pins: pinmux_led_pins { + led_pins: led-pins { pinctrl-single,pins = < OMAP3430_CORE2_IOPAD(0x25ea, PIN_OUTPUT | MUX_MODE4) /* etk_d7.gpio_21 */ OMAP3430_CORE2_IOPAD(0x25ec, PIN_OUTPUT | MUX_MODE4) /* etk_d8.gpio_22 */ >; }; - button_pins: pinmux_button_pins { + button_pins: button-pins { pinctrl-single,pins = < OMAP3430_CORE2_IOPAD(0x25ee, PIN_INPUT | MUX_MODE4) /* etk_d9.gpio_23 */ OMAP3430_CORE2_IOPAD(0x25dc, PIN_INPUT | MUX_MODE4) /* etk_d0.gpio_14 */ diff --git a/arch/arm/boot/dts/omap3-overo-storm-alto35.dts b/arch/arm/boot/dts/ti/omap/omap3-overo-storm-alto35.dts similarity index 100% rename from arch/arm/boot/dts/omap3-overo-storm-alto35.dts rename to arch/arm/boot/dts/ti/omap/omap3-overo-storm-alto35.dts diff --git a/arch/arm/boot/dts/omap3-overo-storm-chestnut43.dts b/arch/arm/boot/dts/ti/omap/omap3-overo-storm-chestnut43.dts similarity index 92% rename from arch/arm/boot/dts/omap3-overo-storm-chestnut43.dts rename to arch/arm/boot/dts/ti/omap/omap3-overo-storm-chestnut43.dts index 3af8d10d722478d17f6764647d3311cf6190d05a..25e82efe4f3b6c7da718644177e6c8dc7ab13f03 100644 --- a/arch/arm/boot/dts/omap3-overo-storm-chestnut43.dts +++ b/arch/arm/boot/dts/ti/omap/omap3-overo-storm-chestnut43.dts @@ -18,14 +18,14 @@ }; &omap3_pmx_core2 { - led_pins: pinmux_led_pins { + led_pins: led-pins { pinctrl-single,pins = < OMAP3630_CORE2_IOPAD(0x25ea, PIN_OUTPUT | MUX_MODE4) /* etk_d7.gpio_21 */ OMAP3630_CORE2_IOPAD(0x25ec, PIN_OUTPUT | MUX_MODE4) /* etk_d8.gpio_22 */ >; }; - button_pins: pinmux_button_pins { + button_pins: button-pins { pinctrl-single,pins = < OMAP3630_CORE2_IOPAD(0x25ee, PIN_INPUT | MUX_MODE4) /* etk_d9.gpio_23 */ OMAP3630_CORE2_IOPAD(0x25dc, PIN_INPUT | MUX_MODE4) /* etk_d0.gpio_14 */ diff --git a/arch/arm/boot/dts/omap3-overo-storm-gallop43.dts b/arch/arm/boot/dts/ti/omap/omap3-overo-storm-gallop43.dts similarity index 92% rename from arch/arm/boot/dts/omap3-overo-storm-gallop43.dts rename to arch/arm/boot/dts/ti/omap/omap3-overo-storm-gallop43.dts index 813e3c9fe3b64b93f348d3196da14d150f25ee77..0c93ea3f977438bd6b1a1c2ff0aa199c832eecff 100644 --- a/arch/arm/boot/dts/omap3-overo-storm-gallop43.dts +++ b/arch/arm/boot/dts/ti/omap/omap3-overo-storm-gallop43.dts @@ -18,14 +18,14 @@ }; &omap3_pmx_core2 { - led_pins: pinmux_led_pins { + led_pins: led-pins { pinctrl-single,pins = < OMAP3630_CORE2_IOPAD(0x25ea, PIN_OUTPUT | MUX_MODE4) /* etk_d7.gpio_21 */ OMAP3630_CORE2_IOPAD(0x25ec, PIN_OUTPUT | MUX_MODE4) /* etk_d8.gpio_22 */ >; }; - button_pins: pinmux_button_pins { + button_pins: button-pins { pinctrl-single,pins = < OMAP3630_CORE2_IOPAD(0x25ee, PIN_INPUT | MUX_MODE4) /* etk_d9.gpio_23 */ OMAP3630_CORE2_IOPAD(0x25dc, PIN_INPUT | MUX_MODE4) /* etk_d0.gpio_14 */ diff --git a/arch/arm/boot/dts/omap3-overo-storm-palo35.dts b/arch/arm/boot/dts/ti/omap/omap3-overo-storm-palo35.dts similarity index 92% rename from arch/arm/boot/dts/omap3-overo-storm-palo35.dts rename to arch/arm/boot/dts/ti/omap/omap3-overo-storm-palo35.dts index 8405bd9262de6d58b9dd37764f1eeefe0f3c1425..9468ef9f9742e9506e87a00b3dbbdbb6a714a23f 100644 --- a/arch/arm/boot/dts/omap3-overo-storm-palo35.dts +++ b/arch/arm/boot/dts/ti/omap/omap3-overo-storm-palo35.dts @@ -18,14 +18,14 @@ }; &omap3_pmx_core2 { - led_pins: pinmux_led_pins { + led_pins: led-pins { pinctrl-single,pins = < OMAP3630_CORE2_IOPAD(0x25ea, PIN_OUTPUT | MUX_MODE4) /* etk_d7.gpio_21 */ OMAP3630_CORE2_IOPAD(0x25ec, PIN_OUTPUT | MUX_MODE4) /* etk_d8.gpio_22 */ >; }; - button_pins: pinmux_button_pins { + button_pins: button-pins { pinctrl-single,pins = < OMAP3630_CORE2_IOPAD(0x25ee, PIN_INPUT | MUX_MODE4) /* etk_d9.gpio_23 */ OMAP3630_CORE2_IOPAD(0x25dc, PIN_INPUT | MUX_MODE4) /* etk_d0.gpio_14 */ diff --git a/arch/arm/boot/dts/omap3-overo-storm-palo43.dts b/arch/arm/boot/dts/ti/omap/omap3-overo-storm-palo43.dts similarity index 92% rename from arch/arm/boot/dts/omap3-overo-storm-palo43.dts rename to arch/arm/boot/dts/ti/omap/omap3-overo-storm-palo43.dts index b9558d736e7956cf8309b2f3f96bd69749a441c2..9feead584479266da58eafee01fc35897a3d8e54 100644 --- a/arch/arm/boot/dts/omap3-overo-storm-palo43.dts +++ b/arch/arm/boot/dts/ti/omap/omap3-overo-storm-palo43.dts @@ -18,14 +18,14 @@ }; &omap3_pmx_core2 { - led_pins: pinmux_led_pins { + led_pins: led-pins { pinctrl-single,pins = < OMAP3630_CORE2_IOPAD(0x25ea, PIN_OUTPUT | MUX_MODE4) /* etk_d7.gpio_21 */ OMAP3630_CORE2_IOPAD(0x25ec, PIN_OUTPUT | MUX_MODE4) /* etk_d8.gpio_22 */ >; }; - button_pins: pinmux_button_pins { + button_pins: button-pins { pinctrl-single,pins = < OMAP3630_CORE2_IOPAD(0x25ee, PIN_INPUT | MUX_MODE4) /* etk_d9.gpio_23 */ OMAP3630_CORE2_IOPAD(0x25dc, PIN_INPUT | MUX_MODE4) /* etk_d0.gpio_14 */ diff --git a/arch/arm/boot/dts/omap3-overo-storm-summit.dts b/arch/arm/boot/dts/ti/omap/omap3-overo-storm-summit.dts similarity index 95% rename from arch/arm/boot/dts/omap3-overo-storm-summit.dts rename to arch/arm/boot/dts/ti/omap/omap3-overo-storm-summit.dts index fcfc449f2abea22de010afddfe0e1a08c160109c..92f56b9d009d1924b5bd86df38aa31fdb15aab98 100644 --- a/arch/arm/boot/dts/omap3-overo-storm-summit.dts +++ b/arch/arm/boot/dts/ti/omap/omap3-overo-storm-summit.dts @@ -18,7 +18,7 @@ }; &omap3_pmx_core2 { - led_pins: pinmux_led_pins { + led_pins: led-pins { pinctrl-single,pins = < OMAP3630_CORE2_IOPAD(0x25ea, PIN_OUTPUT | MUX_MODE4) /* etk_d7.gpio_21 */ >; diff --git a/arch/arm/boot/dts/omap3-overo-storm-tobi.dts b/arch/arm/boot/dts/ti/omap/omap3-overo-storm-tobi.dts similarity index 100% rename from arch/arm/boot/dts/omap3-overo-storm-tobi.dts rename to arch/arm/boot/dts/ti/omap/omap3-overo-storm-tobi.dts diff --git a/arch/arm/boot/dts/omap3-overo-storm-tobiduo.dts b/arch/arm/boot/dts/ti/omap/omap3-overo-storm-tobiduo.dts similarity index 100% rename from arch/arm/boot/dts/omap3-overo-storm-tobiduo.dts rename to arch/arm/boot/dts/ti/omap/omap3-overo-storm-tobiduo.dts diff --git a/arch/arm/boot/dts/omap3-overo-storm.dtsi b/arch/arm/boot/dts/ti/omap/omap3-overo-storm.dtsi similarity index 91% rename from arch/arm/boot/dts/omap3-overo-storm.dtsi rename to arch/arm/boot/dts/ti/omap/omap3-overo-storm.dtsi index 2af15d5f61f92a9c2d4bbaacef2dd191e25ed851..da583b47ed8db0935c92ac9bf683ccbcb546bb23 100644 --- a/arch/arm/boot/dts/omap3-overo-storm.dtsi +++ b/arch/arm/boot/dts/ti/omap/omap3-overo-storm.dtsi @@ -12,7 +12,7 @@ &hsusb2_2_pins >; - hsusb2_2_pins: pinmux_hsusb2_2_pins { + hsusb2_2_pins: hsusb2-2-pins { pinctrl-single,pins = < OMAP3630_CORE2_IOPAD(0x25f0, PIN_OUTPUT | MUX_MODE3) /* etk_d10.hsusb2_clk */ OMAP3630_CORE2_IOPAD(0x25f2, PIN_OUTPUT | MUX_MODE3) /* etk_d11.hsusb2_stp */ @@ -23,7 +23,7 @@ >; }; - w3cbw003c_2_pins: pinmux_w3cbw003c_2_pins { + w3cbw003c_2_pins: w3cbw003c-2-pins { pinctrl-single,pins = < OMAP3630_CORE2_IOPAD(0x25e0, PIN_OUTPUT | MUX_MODE4) /* etk_d2.gpio_16 */ >; diff --git a/arch/arm/boot/dts/omap3-overo-summit-common.dtsi b/arch/arm/boot/dts/ti/omap/omap3-overo-summit-common.dtsi similarity index 100% rename from arch/arm/boot/dts/omap3-overo-summit-common.dtsi rename to arch/arm/boot/dts/ti/omap/omap3-overo-summit-common.dtsi diff --git a/arch/arm/boot/dts/omap3-overo-summit.dts b/arch/arm/boot/dts/ti/omap/omap3-overo-summit.dts similarity index 94% rename from arch/arm/boot/dts/omap3-overo-summit.dts rename to arch/arm/boot/dts/ti/omap/omap3-overo-summit.dts index a6c9799fe49159e1729e3ad4bbfcb0f0807a77a7..da5ca80430aebdd9ee249b111e3bd21b0e9a880a 100644 --- a/arch/arm/boot/dts/omap3-overo-summit.dts +++ b/arch/arm/boot/dts/ti/omap/omap3-overo-summit.dts @@ -18,7 +18,7 @@ }; &omap3_pmx_core2 { - led_pins: pinmux_led_pins { + led_pins: led-pins { pinctrl-single,pins = < OMAP3430_CORE2_IOPAD(0x25ea, PIN_OUTPUT | MUX_MODE4) /* etk_d7.gpio_21 */ >; diff --git a/arch/arm/boot/dts/omap3-overo-tobi-common.dtsi b/arch/arm/boot/dts/ti/omap/omap3-overo-tobi-common.dtsi similarity index 100% rename from arch/arm/boot/dts/omap3-overo-tobi-common.dtsi rename to arch/arm/boot/dts/ti/omap/omap3-overo-tobi-common.dtsi diff --git a/arch/arm/boot/dts/omap3-overo-tobi.dts b/arch/arm/boot/dts/ti/omap/omap3-overo-tobi.dts similarity index 100% rename from arch/arm/boot/dts/omap3-overo-tobi.dts rename to arch/arm/boot/dts/ti/omap/omap3-overo-tobi.dts diff --git a/arch/arm/boot/dts/omap3-overo-tobiduo-common.dtsi b/arch/arm/boot/dts/ti/omap/omap3-overo-tobiduo-common.dtsi similarity index 100% rename from arch/arm/boot/dts/omap3-overo-tobiduo-common.dtsi rename to arch/arm/boot/dts/ti/omap/omap3-overo-tobiduo-common.dtsi diff --git a/arch/arm/boot/dts/omap3-overo-tobiduo.dts b/arch/arm/boot/dts/ti/omap/omap3-overo-tobiduo.dts similarity index 100% rename from arch/arm/boot/dts/omap3-overo-tobiduo.dts rename to arch/arm/boot/dts/ti/omap/omap3-overo-tobiduo.dts diff --git a/arch/arm/boot/dts/omap3-overo.dtsi b/arch/arm/boot/dts/ti/omap/omap3-overo.dtsi similarity index 91% rename from arch/arm/boot/dts/omap3-overo.dtsi rename to arch/arm/boot/dts/ti/omap/omap3-overo.dtsi index cc9263e99254f6e8089597818b5addc61dbbb935..7dc044e87226cf0d65d22789281b22b94797df53 100644 --- a/arch/arm/boot/dts/omap3-overo.dtsi +++ b/arch/arm/boot/dts/ti/omap/omap3-overo.dtsi @@ -12,7 +12,7 @@ &hsusb2_2_pins >; - hsusb2_2_pins: pinmux_hsusb2_2_pins { + hsusb2_2_pins: hsusb2-2-pins { pinctrl-single,pins = < OMAP3430_CORE2_IOPAD(0x25f0, PIN_OUTPUT | MUX_MODE3) /* etk_d10.hsusb2_clk */ OMAP3430_CORE2_IOPAD(0x25f2, PIN_OUTPUT | MUX_MODE3) /* etk_d11.hsusb2_stp */ @@ -23,7 +23,7 @@ >; }; - w3cbw003c_2_pins: pinmux_w3cbw003c_2_pins { + w3cbw003c_2_pins: w3cbw003c-2-pins { pinctrl-single,pins = < OMAP3430_CORE2_IOPAD(0x25e0, PIN_OUTPUT | MUX_MODE4) /* etk_d2.gpio_16 */ >; diff --git a/arch/arm/boot/dts/omap3-pandora-1ghz.dts b/arch/arm/boot/dts/ti/omap/omap3-pandora-1ghz.dts similarity index 95% rename from arch/arm/boot/dts/omap3-pandora-1ghz.dts rename to arch/arm/boot/dts/ti/omap/omap3-pandora-1ghz.dts index c0252f8a798aaf28bc52d4ca97f175c034930845..8d8c9085e6ffe03a46b43641efa60d0fca342872 100644 --- a/arch/arm/boot/dts/omap3-pandora-1ghz.dts +++ b/arch/arm/boot/dts/ti/omap/omap3-pandora-1ghz.dts @@ -27,7 +27,7 @@ &control_pins >; - hsusb2_2_pins: pinmux_hsusb2_2_pins { + hsusb2_2_pins: hsusb2-2-pins { pinctrl-single,pins = < OMAP3630_CORE2_IOPAD(0x25f0, PIN_OUTPUT | MUX_MODE3) /* etk_d10.hsusb2_clk */ OMAP3630_CORE2_IOPAD(0x25f2, PIN_OUTPUT | MUX_MODE3) /* etk_d11.hsusb2_stp */ @@ -38,7 +38,7 @@ >; }; - mmc3_pins: pinmux_mmc3_pins { + mmc3_pins: mmc3-pins { pinctrl-single,pins = < OMAP3630_CORE2_IOPAD(0x25d8, PIN_INPUT_PULLUP | MUX_MODE2) /* etk_clk.sdmmc3_clk */ OMAP3630_CORE2_IOPAD(0x25da, PIN_INPUT_PULLUP | MUX_MODE2) /* etk_ctl.sdmmc3_cmd */ @@ -49,7 +49,7 @@ >; }; - control_pins: pinmux_control_pins { + control_pins: control-pins { pinctrl-single,pins = < OMAP3630_CORE2_IOPAD(0x25dc, PIN_INPUT_PULLDOWN | MUX_MODE4) /* etk_d0.gpio_14 = HP_SHUTDOWN */ OMAP3630_CORE2_IOPAD(0x25de, PIN_OUTPUT | MUX_MODE4) /* etk_d1.gpio_15 = BT_SHUTDOWN */ diff --git a/arch/arm/boot/dts/omap3-pandora-600mhz.dts b/arch/arm/boot/dts/ti/omap/omap3-pandora-600mhz.dts similarity index 95% rename from arch/arm/boot/dts/omap3-pandora-600mhz.dts rename to arch/arm/boot/dts/ti/omap/omap3-pandora-600mhz.dts index 6bd9041942f2a026cc2d46129861eeeb1724cb1d..2d5eac3ffc6cd4dfac0c44d9aa54a1e56ab27db3 100644 --- a/arch/arm/boot/dts/omap3-pandora-600mhz.dts +++ b/arch/arm/boot/dts/ti/omap/omap3-pandora-600mhz.dts @@ -27,7 +27,7 @@ &control_pins >; - hsusb2_2_pins: pinmux_hsusb2_2_pins { + hsusb2_2_pins: hsusb2-2-pins { pinctrl-single,pins = < OMAP3430_CORE2_IOPAD(0x25f0, PIN_OUTPUT | MUX_MODE3) /* etk_d10.hsusb2_clk */ OMAP3430_CORE2_IOPAD(0x25f2, PIN_OUTPUT | MUX_MODE3) /* etk_d11.hsusb2_stp */ @@ -38,7 +38,7 @@ >; }; - mmc3_pins: pinmux_mmc3_pins { + mmc3_pins: mmc3-pins { pinctrl-single,pins = < OMAP3430_CORE2_IOPAD(0x25d8, PIN_INPUT_PULLUP | MUX_MODE2) /* etk_clk.sdmmc3_clk */ OMAP3430_CORE2_IOPAD(0x25da, PIN_INPUT_PULLUP | MUX_MODE2) /* etk_ctl.sdmmc3_cmd */ @@ -49,7 +49,7 @@ >; }; - control_pins: pinmux_control_pins { + control_pins: control-pins { pinctrl-single,pins = < OMAP3430_CORE2_IOPAD(0x25dc, PIN_INPUT_PULLDOWN | MUX_MODE4) /* etk_d0.gpio_14 = HP_SHUTDOWN */ OMAP3430_CORE2_IOPAD(0x25de, PIN_OUTPUT | MUX_MODE4) /* etk_d1.gpio_15 = BT_SHUTDOWN */ diff --git a/arch/arm/boot/dts/omap3-pandora-common.dtsi b/arch/arm/boot/dts/ti/omap/omap3-pandora-common.dtsi similarity index 98% rename from arch/arm/boot/dts/omap3-pandora-common.dtsi rename to arch/arm/boot/dts/ti/omap/omap3-pandora-common.dtsi index 4c3b6bab179cc1be81e22f5735c1a245efb32385..06c5b23589991395dcf83ab4e81ade4a7e005515 100644 --- a/arch/arm/boot/dts/omap3-pandora-common.dtsi +++ b/arch/arm/boot/dts/ti/omap/omap3-pandora-common.dtsi @@ -205,7 +205,7 @@ }; /* HS USB Host PHY on PORT 2 */ - hsusb2_phy: hsusb2_phy { + hsusb2_phy: hsusb2-phy-pins { compatible = "usb-nop-xceiv"; reset-gpios = <&gpio1 16 GPIO_ACTIVE_LOW>; /* GPIO_16 */ vcc-supply = <&vaux2>; @@ -251,7 +251,7 @@ &omap3_pmx_core { - mmc1_pins: pinmux_mmc1_pins { + mmc1_pins: mmc1-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x2144, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc1_clk.sdmmc1_clk */ OMAP3_CORE1_IOPAD(0x2146, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc1_cmd.sdmmc1_cmd */ @@ -262,7 +262,7 @@ >; }; - mmc2_pins: pinmux_mmc2_pins { + mmc2_pins: mmc2-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x2158, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc2_clk.sdmmc2_clk */ OMAP3_CORE1_IOPAD(0x215a, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc2_cmd.sdmmc2_cmd */ @@ -277,7 +277,7 @@ >; }; - dss_dpi_pins: pinmux_dss_dpi_pins { + dss_dpi_pins: dss-dpi-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x20d4, PIN_OUTPUT | MUX_MODE0) /* dss_pclk.dss_pclk */ OMAP3_CORE1_IOPAD(0x20d6, PIN_OUTPUT | MUX_MODE0) /* dss_hsync.dss_hsync */ @@ -311,14 +311,14 @@ >; }; - uart3_pins: pinmux_uart3_pins { + uart3_pins: uart3-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x219e, PIN_INPUT | PIN_OFF_WAKEUPENABLE | MUX_MODE0) /* uart3_rx_irrx.uart3_rx_irrx */ OMAP3_CORE1_IOPAD(0x21a0, PIN_OUTPUT | MUX_MODE0) /* uart3_tx_irtx.uart3_tx_irtx */ >; }; - led_pins: pinmux_leds_pins { + led_pins: leds-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x2154, PIN_OUTPUT | MUX_MODE4) /* GPIO_128 */ OMAP3_CORE1_IOPAD(0x2156, PIN_OUTPUT | MUX_MODE4) /* GPIO_129 */ @@ -327,7 +327,7 @@ >; }; - button_pins: pinmux_button_pins { + button_pins: button-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x2110, PIN_INPUT | MUX_MODE4) /* GPIO_96 */ OMAP3_CORE1_IOPAD(0x2112, PIN_INPUT | MUX_MODE4) /* GPIO_97 */ @@ -349,7 +349,7 @@ >; }; - penirq_pins: pinmux_penirq_pins { + penirq_pins: penirq-pins { pinctrl-single,pins = < /* here we could enable to wakeup the cpu from suspend by a pen touch */ OMAP3_CORE1_IOPAD(0x210c, PIN_INPUT | MUX_MODE4) /* GPIO_94 */ diff --git a/arch/arm/boot/dts/omap3-panel-sharp-ls037v7dw01.dtsi b/arch/arm/boot/dts/ti/omap/omap3-panel-sharp-ls037v7dw01.dtsi similarity index 100% rename from arch/arm/boot/dts/omap3-panel-sharp-ls037v7dw01.dtsi rename to arch/arm/boot/dts/ti/omap/omap3-panel-sharp-ls037v7dw01.dtsi diff --git a/arch/arm/boot/dts/omap3-sb-t35.dtsi b/arch/arm/boot/dts/ti/omap/omap3-sb-t35.dtsi similarity index 95% rename from arch/arm/boot/dts/omap3-sb-t35.dtsi rename to arch/arm/boot/dts/ti/omap/omap3-sb-t35.dtsi index 5ec0893415e03def61b265b63d9f0e2e61b26f69..6730c749d5eaf7cb778188f2ea89afd0c03646fa 100644 --- a/arch/arm/boot/dts/omap3-sb-t35.dtsi +++ b/arch/arm/boot/dts/ti/omap/omap3-sb-t35.dtsi @@ -56,27 +56,27 @@ }; &omap3_pmx_core { - smsc2_pins: pinmux_smsc2_pins { + smsc2_pins: smsc2-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x20b6, PIN_OUTPUT | MUX_MODE0) /* gpmc_ncs4.gpmc_ncs4 */ OMAP3_CORE1_IOPAD(0x20d2, PIN_INPUT_PULLUP | MUX_MODE4) /* gpmc_wait3.gpio_65 */ >; }; - tfp410_pins: pinmux_tfp410_pins { + tfp410_pins: tfp410-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x20b4, PIN_OUTPUT | MUX_MODE4) /* gpmc_ncs3.gpio_54 */ >; }; - i2c3_pins: pinmux_i2c3_pins { + i2c3_pins: i2c3-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x21c2, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c3_scl */ OMAP3_CORE1_IOPAD(0x21c4, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c3_sda */ >; }; - sb_t35_audio_amp: pinmux_sb_t35_audio_amp { + sb_t35_audio_amp: sb-t35-audio-amp-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x20c8, PIN_OUTPUT | MUX_MODE4) /* gpmc_nbe1.gpio_61 */ >; diff --git a/arch/arm/boot/dts/omap3-sbc-t3517.dts b/arch/arm/boot/dts/ti/omap/omap3-sbc-t3517.dts similarity index 94% rename from arch/arm/boot/dts/omap3-sbc-t3517.dts rename to arch/arm/boot/dts/ti/omap/omap3-sbc-t3517.dts index a69d328604219e4dd434454d82c785da49daedcd..07bec48dc4416ff067f62d6f5b1145ac4d964505 100644 --- a/arch/arm/boot/dts/omap3-sbc-t3517.dts +++ b/arch/arm/boot/dts/ti/omap/omap3-sbc-t3517.dts @@ -36,14 +36,14 @@ &usb_hub_pins >; - mmc1_aux_pins: pinmux_mmc1_aux_pins { + mmc1_aux_pins: mmc1-aux-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x20c0, PIN_INPUT_PULLUP | MUX_MODE4) /* gpmc_clk.gpio_59 */ OMAP3_CORE1_IOPAD(0x2174, PIN_INPUT_PULLUP | MUX_MODE4) /* uart2_cts.gpio_144 */ >; }; - sb_t35_usb_hub_pins: pinmux_sb_t35_usb_hub_pins { + sb_t35_usb_hub_pins: sb-t35-usb-hub-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x21ec, PIN_OUTPUT | MUX_MODE4) /* ccdc_wen.gpio_98 - SB-T35 USB HUB RST */ >; diff --git a/arch/arm/boot/dts/omap3-sbc-t3530.dts b/arch/arm/boot/dts/ti/omap/omap3-sbc-t3530.dts similarity index 94% rename from arch/arm/boot/dts/omap3-sbc-t3530.dts rename to arch/arm/boot/dts/ti/omap/omap3-sbc-t3530.dts index 24bf3fd86641f3c26e64724d90f9c994b9623605..1beefc3194224f55714d4615ee7e7b2e907ddb45 100644 --- a/arch/arm/boot/dts/omap3-sbc-t3530.dts +++ b/arch/arm/boot/dts/ti/omap/omap3-sbc-t3530.dts @@ -20,7 +20,7 @@ pinctrl-names = "default"; pinctrl-0 = <&sb_t35_usb_hub_pins>; - sb_t35_usb_hub_pins: pinmux_sb_t35_usb_hub_pins { + sb_t35_usb_hub_pins: sb-t35-usb-hub-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x2130, PIN_OUTPUT | MUX_MODE4) /* ccdc_wen.gpio_167 - SB-T35 USB HUB RST */ >; diff --git a/arch/arm/boot/dts/omap3-sbc-t3730.dts b/arch/arm/boot/dts/ti/omap/omap3-sbc-t3730.dts similarity index 94% rename from arch/arm/boot/dts/omap3-sbc-t3730.dts rename to arch/arm/boot/dts/ti/omap/omap3-sbc-t3730.dts index 4c36bde62491d7797fe340315e8dc588bd2983f5..aefc1187ebc9e1c8a2c72df122fcc913fddcf1e0 100644 --- a/arch/arm/boot/dts/omap3-sbc-t3730.dts +++ b/arch/arm/boot/dts/ti/omap/omap3-sbc-t3730.dts @@ -20,7 +20,7 @@ pinctrl-names = "default"; pinctrl-0 = <&sb_t35_usb_hub_pins>; - sb_t35_usb_hub_pins: pinmux_sb_t35_usb_hub_pins { + sb_t35_usb_hub_pins: sb-t35-usb-hub-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x2130, PIN_OUTPUT | MUX_MODE4) /* ccdc_wen.gpio_167 - SB-T35 USB HUB RST */ >; diff --git a/arch/arm/boot/dts/omap3-sniper.dts b/arch/arm/boot/dts/ti/omap/omap3-sniper.dts similarity index 94% rename from arch/arm/boot/dts/omap3-sniper.dts rename to arch/arm/boot/dts/ti/omap/omap3-sniper.dts index 0591af4941847d4f69ed657ba24df2e3c04fe550..79e00405748217f0906b30c53cac78ad04e5d583 100644 --- a/arch/arm/boot/dts/omap3-sniper.dts +++ b/arch/arm/boot/dts/ti/omap/omap3-sniper.dts @@ -26,48 +26,48 @@ &omap3_pmx_core { pinctrl-names = "default"; - uart3_pins: pinmux_uart3_pins { + uart3_pins: uart3-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x219e, PIN_INPUT | MUX_MODE0) /* uart3_rx_irrx */ OMAP3_CORE1_IOPAD(0x21a0, PIN_OUTPUT | MUX_MODE0) /* uart3_tx_irtx */ >; }; - dp3t_sel_pins: pinmux_dp3t_sel_pins { + dp3t_sel_pins: dp3t-sel-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x2196, PIN_OUTPUT | MUX_MODE4) /* gpio_161 */ OMAP3_CORE1_IOPAD(0x2198, PIN_OUTPUT | MUX_MODE4) /* gpio_162 */ >; }; - i2c1_pins: pinmux_i2c1_pins { + i2c1_pins: i2c1-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x21ba, PIN_INPUT | MUX_MODE0) /* i2c1_scl */ OMAP3_CORE1_IOPAD(0x21bc, PIN_INPUT | MUX_MODE0) /* i2c1_sda */ >; }; - i2c2_pins: pinmux_i2c2_pins { + i2c2_pins: i2c2-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x21be, PIN_INPUT | MUX_MODE0) /* i2c2_scl */ OMAP3_CORE1_IOPAD(0x21c0, PIN_INPUT | MUX_MODE0) /* i2c2_sda */ >; }; - i2c3_pins: pinmux_i2c3_pins { + i2c3_pins: i2c3-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x21c2, PIN_INPUT | MUX_MODE0) /* i2c3_scl */ OMAP3_CORE1_IOPAD(0x21c4, PIN_INPUT | MUX_MODE0) /* i2c3_sda */ >; }; - lp8720_en_pin: pinmux_lp8720_en_pin { + lp8720_en_pin: lp8720-en-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x2080, PIN_OUTPUT | MUX_MODE4) /* gpio_37 */ >; }; - mmc1_pins: pinmux_mmc1_pins { + mmc1_pins: mmc1-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x2144, PIN_INPUT | MUX_MODE0) /* sdmmc1_clk */ OMAP3_CORE1_IOPAD(0x2146, PIN_INPUT | MUX_MODE0) /* sdmmc1_cmd */ @@ -78,7 +78,7 @@ >; }; - mmc2_pins: pinmux_mmc2_pins { + mmc2_pins: mmc2-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x2158, PIN_INPUT | MUX_MODE0) /* sdmmc2_clk */ OMAP3_CORE1_IOPAD(0x215a, PIN_INPUT | MUX_MODE0) /* sdmmc2_cmd */ @@ -93,7 +93,7 @@ >; }; - usb_otg_hs_pins: pinmux_usb_otg_hs_pins { + usb_otg_hs_pins: usb-otg-hs-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x21a2, PIN_INPUT | MUX_MODE0) /* hsusb0_clk */ OMAP3_CORE1_IOPAD(0x21a4, PIN_OUTPUT | MUX_MODE0) /* hsusb0_stp */ @@ -114,7 +114,7 @@ &omap3_pmx_wkup { pinctrl-names = "default"; - mmc1_cd_pin: pinmux_mmc1_cd_pin { + mmc1_cd_pin: mmc1-cd-pins { pinctrl-single,pins = < OMAP3_WKUP_IOPAD(0x2a1a, PIN_INPUT | MUX_MODE4) /* gpio_10 */ >; diff --git a/arch/arm/boot/dts/omap3-tao3530.dtsi b/arch/arm/boot/dts/ti/omap/omap3-tao3530.dtsi similarity index 96% rename from arch/arm/boot/dts/omap3-tao3530.dtsi rename to arch/arm/boot/dts/ti/omap/omap3-tao3530.dtsi index 7f440d11f7e759906fb1abd2555a8a19861e02d4..92a5846048bd7f174baa709b089054998c883312 100644 --- a/arch/arm/boot/dts/omap3-tao3530.dtsi +++ b/arch/arm/boot/dts/ti/omap/omap3-tao3530.dtsi @@ -43,7 +43,7 @@ }; /* HS USB Host PHY on PORT 2 */ - hsusb2_phy: hsusb2_phy { + hsusb2_phy: hsusb2-phy-pins { compatible = "usb-nop-xceiv"; reset-gpios = <&gpio6 2 GPIO_ACTIVE_LOW>; /* gpio_162 */ vcc-supply = <&hsusb2_power>; @@ -70,7 +70,7 @@ }; &omap3_pmx_core { - hsusbb2_pins: pinmux_hsusbb2_pins { + hsusbb2_pins: hsusbb2-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x25f0, PIN_OUTPUT | MUX_MODE3) /* etk_d10.hsusb2_clk */ OMAP3_CORE1_IOPAD(0x25f2, PIN_OUTPUT | MUX_MODE3) /* etk_d11.hsusb2_stp */ @@ -87,7 +87,7 @@ >; }; - mmc1_pins: pinmux_mmc1_pins { + mmc1_pins: mmc1-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x2144, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc1_clk.sdmmc1_clk */ OMAP3_CORE1_IOPAD(0x2146, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc1_cmd.sdmmc1_cmd */ @@ -102,7 +102,7 @@ >; }; - mmc2_pins: pinmux_mmc2_pins { + mmc2_pins: mmc2-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x2158, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc2_clk.sdmmc2_clk */ OMAP3_CORE1_IOPAD(0x215a, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc2_cmd.sdmmc2_cmd */ @@ -114,27 +114,27 @@ }; /* wlan GPIO output for WLAN_EN */ - wlan_gpio: pinmux_wlan_gpio { + wlan_gpio: wlan-gpio-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x218e, PIN_OUTPUT | MUX_MODE4) /* mcbsp1_fsr gpio_157 */ >; }; - uart3_pins: pinmux_uart3_pins { + uart3_pins: uart3-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x219e, PIN_INPUT | PIN_OFF_WAKEUPENABLE | MUX_MODE0) /* uart3_rx_irrx.uart3_rx_irrx */ OMAP3_CORE1_IOPAD(0x21a0, PIN_OUTPUT | MUX_MODE0) /* uart3_tx_irtx.uart3_tx_irtx */ >; }; - i2c3_pins: pinmux_i2c3_pins { + i2c3_pins: i2c3-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x21c2, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c3_scl.i2c3_scl */ OMAP3_CORE1_IOPAD(0x21c4, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c3_sda.i2c3_sda */ >; }; - mcspi1_pins: pinmux_mcspi1_pins { + mcspi1_pins: mcspi1-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x21c8, PIN_INPUT | MUX_MODE0) /* mcspi1_clk.mcspi1_clk */ OMAP3_CORE1_IOPAD(0x21ca, PIN_OUTPUT | MUX_MODE0) /* mcspi1_simo.mcspi1_simo */ @@ -143,7 +143,7 @@ >; }; - mcspi3_pins: pinmux_mcspi3_pins { + mcspi3_pins: mcspi3-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x25dc, PIN_OUTPUT | MUX_MODE1) /* etk_d0.mcspi3_simo gpio14 INPUT | MODE1 */ OMAP3_CORE1_IOPAD(0x25de, PIN_INPUT_PULLUP | MUX_MODE1) /* etk_d1.mcspi3_somi gpio15 INPUT | MODE1 */ @@ -152,7 +152,7 @@ >; }; - mcbsp3_pins: pinmux_mcbsp3_pins { + mcbsp3_pins: mcbsp3-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x216c, PIN_OUTPUT | MUX_MODE0) /* mcbsp3_dx.uart2_cts */ OMAP3_CORE1_IOPAD(0x216e, PIN_INPUT | MUX_MODE0) /* mcbsp3_dr.uart2_rts */ diff --git a/arch/arm/boot/dts/omap3-thunder.dts b/arch/arm/boot/dts/ti/omap/omap3-thunder.dts similarity index 97% rename from arch/arm/boot/dts/omap3-thunder.dts rename to arch/arm/boot/dts/ti/omap/omap3-thunder.dts index d82cab8e213a661a2a52462cc8d9fbf2f3487e7e..c87956c59b083b08db3bebf36c99152f548d940d 100644 --- a/arch/arm/boot/dts/omap3-thunder.dts +++ b/arch/arm/boot/dts/ti/omap/omap3-thunder.dts @@ -12,7 +12,7 @@ }; &omap3_pmx_core { - dss_dpi_pins: pinmux_dss_dpi_pins { + dss_dpi_pins: dss-dpi-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x20d4, PIN_OUTPUT | MUX_MODE0) /* dss_pclk.dss_pclk */ OMAP3_CORE1_IOPAD(0x20d6, PIN_OUTPUT | MUX_MODE0) /* dss_hsync.dss_hsync */ @@ -45,13 +45,13 @@ >; }; - lte430_pins: pinmux_lte430_pins { + lte430_pins: lte430-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x2168, PIN_OUTPUT | MUX_MODE4) /* sdmmc2_dat6.gpio_138 */ >; }; - backlight_pins: pinmux_backlight_pins { + backlight_pins: backlight-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x216a, PIN_OUTPUT | MUX_MODE4) /* sdmmc2_dat7.gpio_139 */ >; diff --git a/arch/arm/boot/dts/omap3-zoom3.dts b/arch/arm/boot/dts/ti/omap/omap3-zoom3.dts similarity index 95% rename from arch/arm/boot/dts/omap3-zoom3.dts rename to arch/arm/boot/dts/ti/omap/omap3-zoom3.dts index ab52e8d68f76058ed8d0753d7ed0a07895a5bc87..9f1e125fd77b64eaa4c41adef8eac999c68a8f0d 100644 --- a/arch/arm/boot/dts/omap3-zoom3.dts +++ b/arch/arm/boot/dts/ti/omap/omap3-zoom3.dts @@ -49,7 +49,7 @@ &omap3_pmx_core { /* REVISIT: twl gpio0 is mmc0_cd */ - mmc1_pins: pinmux_mmc1_pins { + mmc1_pins: mmc1-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x2144, PIN_OUTPUT_PULLUP | MUX_MODE0) /* sdmmc1_clk.sdmmc1_clk */ OMAP3_CORE1_IOPAD(0x2146, PIN_OUTPUT_PULLUP | MUX_MODE0) /* sdmmc1_cmd.sdmmc1_cmd */ @@ -60,7 +60,7 @@ >; }; - mmc2_pins: pinmux_mmc2_pins { + mmc2_pins: mmc2-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x2158, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc2_clk.sdmmc2_clk */ OMAP3_CORE1_IOPAD(0x215a, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc2_cmd.sdmmc2_cmd */ @@ -75,14 +75,14 @@ >; }; - mmc3_pins: pinmux_mmc3_pins { + mmc3_pins: mmc3-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x2198, PIN_INPUT | MUX_MODE4) /* mcbsp1_clkx.gpio_162 WLAN IRQ */ OMAP3_CORE1_IOPAD(0x21d0, PIN_INPUT_PULLUP | MUX_MODE3) /* mcspi1_cs1.sdmmc3_cmd */ >; }; - uart1_pins: pinmux_uart1_pins { + uart1_pins: uart1-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x2180, PIN_INPUT | MUX_MODE0) /* uart1_cts.uart1_cts */ OMAP3_CORE1_IOPAD(0x217e, PIN_OUTPUT | MUX_MODE0) /* uart1_rts.uart1_rts */ @@ -91,7 +91,7 @@ >; }; - uart2_pins: pinmux_uart2_pins { + uart2_pins: uart2-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x2174, PIN_INPUT_PULLUP | MUX_MODE0) /* uart2_cts.uart2_cts */ OMAP3_CORE1_IOPAD(0x2176, PIN_OUTPUT | MUX_MODE0) /* uart2_rts.uart2_rts */ @@ -100,7 +100,7 @@ >; }; - uart3_pins: pinmux_uart3_pins { + uart3_pins: uart3-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x219a, PIN_INPUT_PULLDOWN | MUX_MODE0) /* uart3_cts_rctx.uart3_cts_rctx */ OMAP3_CORE1_IOPAD(0x219c, PIN_OUTPUT | MUX_MODE0) /* uart3_rts_sd.uart3_rts_sd */ @@ -110,7 +110,7 @@ }; /* wl12xx GPIO output for WLAN_EN */ - wl12xx_gpio: pinmux_wl12xx_gpio { + wl12xx_gpio: wl12xx-gpio-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x211a, PIN_OUTPUT| MUX_MODE4) /* cam_d2.gpio_101 */ >; @@ -118,7 +118,7 @@ }; &omap3_pmx_core2 { - mmc3_2_pins: pinmux_mmc3_2_pins { + mmc3_2_pins: mmc3-2-pins { pinctrl-single,pins = < OMAP3630_CORE2_IOPAD(0x25d8, PIN_INPUT_PULLUP | MUX_MODE2) /* etk_clk.sdmmc3_clk */ OMAP3630_CORE2_IOPAD(0x25e4, PIN_INPUT_PULLUP | MUX_MODE2) /* etk_d4.sdmmc3_dat0 */ @@ -130,7 +130,7 @@ }; &omap3_pmx_wkup { - wlan_host_wkup: pinmux_wlan_host_wkup_pins { + wlan_host_wkup: wlan-host-wkup-pins { pinctrl-single,pins = < OMAP3_WKUP_IOPAD(0x2a1a, PIN_INPUT_PULLUP | MUX_MODE4) /* sys_clkout1.gpio_10 WLAN_HOST_WKUP */ >; diff --git a/arch/arm/boot/dts/omap3.dtsi b/arch/arm/boot/dts/ti/omap/omap3.dtsi similarity index 100% rename from arch/arm/boot/dts/omap3.dtsi rename to arch/arm/boot/dts/ti/omap/omap3.dtsi diff --git a/arch/arm/boot/dts/omap3430-sdp.dts b/arch/arm/boot/dts/ti/omap/omap3430-sdp.dts similarity index 100% rename from arch/arm/boot/dts/omap3430-sdp.dts rename to arch/arm/boot/dts/ti/omap/omap3430-sdp.dts diff --git a/arch/arm/boot/dts/omap3430es1-clocks.dtsi b/arch/arm/boot/dts/ti/omap/omap3430es1-clocks.dtsi similarity index 100% rename from arch/arm/boot/dts/omap3430es1-clocks.dtsi rename to arch/arm/boot/dts/ti/omap/omap3430es1-clocks.dtsi diff --git a/arch/arm/boot/dts/omap34xx-omap36xx-clocks.dtsi b/arch/arm/boot/dts/ti/omap/omap34xx-omap36xx-clocks.dtsi similarity index 100% rename from arch/arm/boot/dts/omap34xx-omap36xx-clocks.dtsi rename to arch/arm/boot/dts/ti/omap/omap34xx-omap36xx-clocks.dtsi diff --git a/arch/arm/boot/dts/omap34xx.dtsi b/arch/arm/boot/dts/ti/omap/omap34xx.dtsi similarity index 100% rename from arch/arm/boot/dts/omap34xx.dtsi rename to arch/arm/boot/dts/ti/omap/omap34xx.dtsi diff --git a/arch/arm/boot/dts/omap36xx-am35xx-omap3430es2plus-clocks.dtsi b/arch/arm/boot/dts/ti/omap/omap36xx-am35xx-omap3430es2plus-clocks.dtsi similarity index 100% rename from arch/arm/boot/dts/omap36xx-am35xx-omap3430es2plus-clocks.dtsi rename to arch/arm/boot/dts/ti/omap/omap36xx-am35xx-omap3430es2plus-clocks.dtsi diff --git a/arch/arm/boot/dts/omap36xx-clocks.dtsi b/arch/arm/boot/dts/ti/omap/omap36xx-clocks.dtsi similarity index 100% rename from arch/arm/boot/dts/omap36xx-clocks.dtsi rename to arch/arm/boot/dts/ti/omap/omap36xx-clocks.dtsi diff --git a/arch/arm/boot/dts/omap36xx-omap3430es2plus-clocks.dtsi b/arch/arm/boot/dts/ti/omap/omap36xx-omap3430es2plus-clocks.dtsi similarity index 100% rename from arch/arm/boot/dts/omap36xx-omap3430es2plus-clocks.dtsi rename to arch/arm/boot/dts/ti/omap/omap36xx-omap3430es2plus-clocks.dtsi diff --git a/arch/arm/boot/dts/omap36xx.dtsi b/arch/arm/boot/dts/ti/omap/omap36xx.dtsi similarity index 100% rename from arch/arm/boot/dts/omap36xx.dtsi rename to arch/arm/boot/dts/ti/omap/omap36xx.dtsi diff --git a/arch/arm/boot/dts/omap3xxx-clocks.dtsi b/arch/arm/boot/dts/ti/omap/omap3xxx-clocks.dtsi similarity index 100% rename from arch/arm/boot/dts/omap3xxx-clocks.dtsi rename to arch/arm/boot/dts/ti/omap/omap3xxx-clocks.dtsi diff --git a/arch/arm/boot/dts/omap4-cpu-thermal.dtsi b/arch/arm/boot/dts/ti/omap/omap4-cpu-thermal.dtsi similarity index 100% rename from arch/arm/boot/dts/omap4-cpu-thermal.dtsi rename to arch/arm/boot/dts/ti/omap/omap4-cpu-thermal.dtsi diff --git a/arch/arm/boot/dts/omap4-droid-bionic-xt875.dts b/arch/arm/boot/dts/ti/omap/omap4-droid-bionic-xt875.dts similarity index 100% rename from arch/arm/boot/dts/omap4-droid-bionic-xt875.dts rename to arch/arm/boot/dts/ti/omap/omap4-droid-bionic-xt875.dts diff --git a/arch/arm/boot/dts/omap4-droid4-xt894.dts b/arch/arm/boot/dts/ti/omap/omap4-droid4-xt894.dts similarity index 100% rename from arch/arm/boot/dts/omap4-droid4-xt894.dts rename to arch/arm/boot/dts/ti/omap/omap4-droid4-xt894.dts diff --git a/arch/arm/boot/dts/omap4-duovero-parlor.dts b/arch/arm/boot/dts/ti/omap/omap4-duovero-parlor.dts similarity index 95% rename from arch/arm/boot/dts/omap4-duovero-parlor.dts rename to arch/arm/boot/dts/ti/omap/omap4-duovero-parlor.dts index b294c22177cbf9b692060b0e47fb52cdbd8c735b..6d1beb453234efdd474cd991555a9e386a5f2460 100644 --- a/arch/arm/boot/dts/omap4-duovero-parlor.dts +++ b/arch/arm/boot/dts/ti/omap/omap4-duovero-parlor.dts @@ -62,33 +62,33 @@ &smsc_pins >; - led_pins: pinmux_led_pins { + led_pins: led-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x116, PIN_OUTPUT | MUX_MODE3) /* abe_dmic_din3.gpio_122 */ >; }; - button_pins: pinmux_button_pins { + button_pins: button-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x114, PIN_INPUT_PULLUP | MUX_MODE3) /* abe_dmic_din2.gpio_121 */ >; }; - i2c2_pins: pinmux_i2c2_pins { + i2c2_pins: i2c2-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x126, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c2_scl */ OMAP4_IOPAD(0x128, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c2_sda */ >; }; - i2c3_pins: pinmux_i2c3_pins { + i2c3_pins: i2c3-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x12a, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c3_scl */ OMAP4_IOPAD(0x12c, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c3_sda */ >; }; - smsc_pins: pinmux_smsc_pins { + smsc_pins: smsc-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x068, PIN_INPUT | MUX_MODE3) /* gpmc_a20.gpio_44: IRQ */ OMAP4_IOPAD(0x06a, PIN_INPUT_PULLUP | MUX_MODE3) /* gpmc_a21.gpio_45: nReset */ @@ -96,7 +96,7 @@ >; }; - dss_hdmi_pins: pinmux_dss_hdmi_pins { + dss_hdmi_pins: dss-hdmi-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x098, PIN_INPUT | MUX_MODE3) /* hdmi_hpd.gpio_63 */ OMAP4_IOPAD(0x09a, PIN_INPUT | MUX_MODE0) /* hdmi_cec.hdmi_cec */ diff --git a/arch/arm/boot/dts/omap4-duovero.dtsi b/arch/arm/boot/dts/ti/omap/omap4-duovero.dtsi similarity index 95% rename from arch/arm/boot/dts/omap4-duovero.dtsi rename to arch/arm/boot/dts/ti/omap/omap4-duovero.dtsi index 805dfd40030dc934cb3e1d32031a8eec50feec0c..b8af455b411a953eebe13035df1b6f27b75b58e1 100644 --- a/arch/arm/boot/dts/omap4-duovero.dtsi +++ b/arch/arm/boot/dts/ti/omap/omap4-duovero.dtsi @@ -73,14 +73,14 @@ &hsusbb1_pins >; - twl6040_pins: pinmux_twl6040_pins { + twl6040_pins: twl6040-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x166, PIN_OUTPUT | MUX_MODE3) /* usbb2_ulpitll_nxt.gpio_160 */ OMAP4_IOPAD(0x1a0, PIN_INPUT | MUX_MODE0) /* sys_nirq2.sys_nirq2 */ >; }; - mcbsp1_pins: pinmux_mcbsp1_pins { + mcbsp1_pins: mcbsp1-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x0fe, PIN_INPUT | MUX_MODE0) /* abe_mcbsp1_clkx.abe_mcbsp1_clkx */ OMAP4_IOPAD(0x100, PIN_INPUT_PULLDOWN | MUX_MODE0) /* abe_mcbsp1_dr.abe_mcbsp1_dr */ @@ -89,7 +89,7 @@ >; }; - hsusbb1_pins: pinmux_hsusbb1_pins { + hsusbb1_pins: hsusbb1-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x0c2, PIN_INPUT_PULLDOWN | MUX_MODE4) /* usbb1_ulpitll_clk.usbb1_ulpiphy_clk */ OMAP4_IOPAD(0x0c4, PIN_OUTPUT | MUX_MODE4) /* usbb1_ulpitll_stp.usbb1_ulpiphy_stp */ @@ -106,34 +106,34 @@ >; }; - hsusb1phy_pins: pinmux_hsusb1phy_pins { + hsusb1phy_pins: hsusb1phy-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x08c, PIN_OUTPUT | MUX_MODE3) /* gpmc_wait1.gpio_62 */ >; }; - w2cbw0015_pins: pinmux_w2cbw0015_pins { + w2cbw0015_pins: w2cbw0015-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x066, PIN_OUTPUT | MUX_MODE3) /* gpmc_a19.gpio_43 */ OMAP4_IOPAD(0x07a, PIN_INPUT | MUX_MODE3) /* gpmc_ncs3.gpio_53 */ >; }; - i2c1_pins: pinmux_i2c1_pins { + i2c1_pins: i2c1-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x122, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c1_scl */ OMAP4_IOPAD(0x124, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c1_sda */ >; }; - i2c4_pins: pinmux_i2c4_pins { + i2c4_pins: i2c4-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x12e, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c4_scl */ OMAP4_IOPAD(0x130, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c4_sda */ >; }; - mmc1_pins: pinmux_mmc1_pins { + mmc1_pins: mmc1-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x0e2, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc1_clk */ OMAP4_IOPAD(0x0e4, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmcc1_cmd */ @@ -144,7 +144,7 @@ >; }; - mmc5_pins: pinmux_mmc5_pins { + mmc5_pins: mmc5-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x148, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc5_clk */ OMAP4_IOPAD(0x14a, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmcc5_cmd */ diff --git a/arch/arm/boot/dts/ti/omap/omap4-epson-embt2ws.dts b/arch/arm/boot/dts/ti/omap/omap4-epson-embt2ws.dts new file mode 100644 index 0000000000000000000000000000000000000000..e119e2cccc4e16348a1957296168029ceaaae77d --- /dev/null +++ b/arch/arm/boot/dts/ti/omap/omap4-epson-embt2ws.dts @@ -0,0 +1,450 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2023 Andreas Kemnade + */ +/dts-v1/; + +#include +#include "omap4460.dtsi" + +/ { + model = "Epson Moverio BT-200"; + compatible = "epson,embt2ws", "ti,omap4460", "ti,omap4"; + + memory@80000000 { + device_type = "memory"; + reg = <0x80000000 0x40000000>; /* 1024M */ + }; + + backlight-left { + compatible = "pwm-backlight"; + pwms = <&twl_pwm 1 7812500>; + power-supply = <&unknown_supply>; + }; + + backlight-right { + compatible = "pwm-backlight"; + pwms = <&twl_pwm 0 7812500>; + power-supply = <&unknown_supply>; + }; + + chosen { + stdout-path = &uart3; + }; + + gpio-keys { + compatible = "gpio-keys"; + pinctrl-names = "default"; + pinctrl-0 = <&gpio_keys_pins>; + + key-lock { + label = "Lock"; + gpios = <&gpio2 3 GPIO_ACTIVE_LOW>; + linux,code = ; /* SW_TOUCHPAD_LOCK */ + linux,input-type = ; + }; + }; + + unknown_supply: unknown-supply { + compatible = "regulator-fixed"; + regulator-name = "unknown"; + }; + + /* regulator for wl12xx on sdio2 */ + wl12xx_vmmc: wl12xx-vmmc { + pinctrl-names = "default"; + pinctrl-0 = <&wl12xx_gpio>; + compatible = "regulator-fixed"; + regulator-name = "vwl1271"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + gpio = <&gpio1 24 GPIO_ACTIVE_HIGH>; + startup-delay-us = <70000>; + enable-active-high; + }; +}; + +&i2c1 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c1_pins>; + + clock-frequency = <400000>; + + twl: pmic@48 { + compatible = "ti,twl6032"; + reg = <0x48>; + /* IRQ# = 7 */ + interrupts = ; /* IRQ_SYS_1N cascaded to gic */ + interrupt-controller; + #interrupt-cells = <1>; + + rtc { + compatible = "ti,twl4030-rtc"; + interrupts = <11>; + }; + + ldo2: regulator-ldo2 { + compatible = "ti,twl6032-ldo2"; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <3000000>; + }; + + ldo4: regulator-ldo4 { + compatible = "ti,twl6032-ldo4"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <2800000>; + }; + + ldo3: regulator-ldo3 { + compatible = "ti,twl6032-ldo3"; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <3000000>; + }; + + ldo5: regulator-ldo5 { + compatible = "ti,twl6032-ldo5"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <3000000>; + ti,retain-on-reset; + }; + + ldo1: regulator-ldo1 { + compatible = "ti,twl6032-ldo1"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <2500000>; + }; + + ldo7: regulator-ldo7 { + compatible = "ti,twl6032-ldo7"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <2900000>; + }; + + ldoln: regulator-ldoln { + compatible = "ti,twl6032-ldoln"; + regulator-always-on; + }; + + ldo6: regulator-ldo6 { + compatible = "ti,twl6032-ldo6"; + regulator-always-on; + }; + + ldousb: regulator-ldousb { + compatible = "ti,twl6032-ldousb"; + regulator-always-on; + }; + + vio: regulator-vio { + compatible = "ti,twl6032-vio"; + regulator-always-on; + }; + + twl_usb_comparator: usb-comparator { + compatible = "ti,twl6030-usb"; + interrupts = <4>, <10>; + }; + + twl_pwm: pwm { + /* provides two PWMs (id 0, 1 for PWM1 and PWM2) */ + compatible = "ti,twl6030-pwm"; + #pwm-cells = <2>; + }; + + twl_pwmled: pwmled { + /* provides one PWM (id 0 for Charging indicator LED) */ + compatible = "ti,twl6030-pwmled"; + #pwm-cells = <2>; + }; + + gpadc { + compatible = "ti,twl6032-gpadc"; + interrupts = <3>; + #io-channel-cells = <1>; + }; + + }; +}; + +#include "twl6030_omap4.dtsi" + +&twl_usb_comparator { + usb-supply = <&ldousb>; +}; + + +&i2c2 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c2_pins>; + + clock-frequency = <200000>; + + /* at head/glasses */ + mpu9150h: imu@68 { + compatible = "invensense,mpu9150"; + reg = <0x68>; + + pinctrl-names = "default"; + pinctrl-0 = <&mpu9150h_pins>; + interrupt-parent = <&gpio2>; + interrupt = <19 IRQ_TYPE_LEVEL_HIGH>; + + i2c-gate { + #address-cells = <1>; + #size-cells = <0>; + magnetometer@c { + compatible = "asahi-kasei,ak8975"; + reg = <0x0c>; + }; + }; + }; +}; + +&i2c3 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c3_pins>; + + clock-frequency = <100000>; + + /* TODO: BD2606MVV at 0x66 */ +}; + +&i2c4 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c4_pins>; + + clock-frequency = <360000>; + + /* TODO: KXTI9 at 0xf */ + + tlv320aic3x: codec@18 { + compatible = "ti,tlv320aic3x"; + reg = <0x18>; + pinctrl-names = "default"; + pinctrl-0 = <&tlv320aic3x_pins>; + #sound-dai-cells = <0>; + + reset-gpios = <&gpio2 23 GPIO_ACTIVE_LOW>; + }; + + /* TODO: mpu9150 at control unit, seems to require quirks */ +}; + +&keypad { + pinctrl-names = "default"; + pinctrl-0 = <&keypad_pins>; + keypad,num-rows = <2>; + keypad,num-columns = <3>; + linux,keymap = ; + linux,input-no-autorepeat; +}; + +&mcbsp2 { + #sound-dai-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&mcbsp2_pins>; + status = "okay"; +}; + + +&mmc1 { + /* sdcard */ + vmmc-supply = <&ldo5>; + broken-cd; + bus-width = <4>; +}; + +&mmc2 { + /* emmc */ + vmmc-supply = <&ldo2>; + bus-width = <8>; +}; + +&mmc3 { + pinctrl-names = "default"; + pinctrl-0 = <&wl12xx_pins>; + vmmc-supply = <&wl12xx_vmmc>; + interrupts-extended = <&wakeupgen GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH + &omap4_pmx_core 0x12e>; + non-removable; + bus-width = <4>; + cap-power-off-card; + + #address-cells = <1>; + #size-cells = <0>; + wlcore: wlcore@2 { + compatible = "ti,wl1283"; + reg = <2>; + interrupts-extended = <&gpio1 23 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "irq"; + ref-clock-frequency = <26000000>; + tcxo-clock-frequency = <26000000>; + }; +}; + +&mmc4 { + status = "disabled"; +}; + +&mmc5 { + status = "disabled"; +}; + +&omap4_pmx_core { + bt_pins: pinmux-bt-pins { + pinctrl-single,pins = < + OMAP4_IOPAD(0x1ca, PIN_OUTPUT | MUX_MODE3) /* gpio25 */ + >; + }; + + gpio_keys_pins: pinmux-gpio-key-pins { + pinctrl-single,pins = < + OMAP4_IOPAD(0x56, PIN_INPUT_PULLUP | MUX_MODE3) /* gpio35 */ + >; + }; + + i2c1_pins: pinmux-i2c1-pins { + pinctrl-single,pins = < + OMAP4_IOPAD(0x122, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c1_scl */ + OMAP4_IOPAD(0x124, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c1_sda */ + >; + }; + + i2c2_pins: pinmux-i2c2-pins { + pinctrl-single,pins = < + OMAP4_IOPAD(0x126, PIN_INPUT | MUX_MODE0) /* i2c2_scl */ + OMAP4_IOPAD(0x128, PIN_INPUT | MUX_MODE0) /* i2c2_sda */ + >; + }; + + i2c3_pins: pinmux-i2c3-pins { + pinctrl-single,pins = < + OMAP4_IOPAD(0x12a, PIN_INPUT | MUX_MODE0) /* i2c3_scl */ + OMAP4_IOPAD(0x12c, PIN_INPUT | MUX_MODE0) /* i2c3_sda */ + >; + }; + + i2c4_pins: pinmux-i2c4-pins { + pinctrl-single,pins = < + OMAP4_IOPAD(0x12e, PIN_INPUT | MUX_MODE0) /* i2c4_scl */ + OMAP4_IOPAD(0x130, PIN_INPUT | MUX_MODE0) /* i2c4_sda */ + >; + }; + + keypad_pins: pinmux-keypad-pins { + pinctrl-single,pins = < + /* kpd_row0 */ + OMAP4_IOPAD(0x0050, PIN_INPUT_PULLUP | MUX_MODE1) + /* kpd_row1 */ + OMAP4_IOPAD(0x0052, PIN_INPUT_PULLUP | MUX_MODE1) + /* kpd_row2 */ + OMAP4_IOPAD(0x0054, PIN_INPUT_PULLUP | MUX_MODE1) + /* kpd_col0 */ + OMAP4_IOPAD(0x0058, PIN_OUTPUT | MUX_MODE1) + /* kpd_col1 */ + OMAP4_IOPAD(0x005a, PIN_OUTPUT | MUX_MODE1) + /* kpd_col2 */ + OMAP4_IOPAD(0x005c, PIN_OUTPUT | MUX_MODE1) + >; + }; + + mcbsp2_pins: pinmux-mcbsp2-pins { + pinctrl-single,pins = < + OMAP4_IOPAD(0x0f6, PIN_INPUT | MUX_MODE0) /* abe_mcbsp2_clkx */ + OMAP4_IOPAD(0x0f8, PIN_INPUT | MUX_MODE0) /* abe_mcbsp2_dr */ + OMAP4_IOPAD(0x0fa, PIN_OUTPUT | MUX_MODE0) /* abe_mcbsp2_dx */ + OMAP4_IOPAD(0x0fc, PIN_INPUT | MUX_MODE0) /* abe_mcbsp2_fsx */ + >; + }; + + mpu9150h_pins: pinmux-mpu9150h-pins { + pinctrl-single,pins = < + OMAP4_IOPAD(0x76, PIN_INPUT_PULLUP | MUX_MODE3) + >; + }; + + tlv320aic3x_pins: pinmux-tlv320aic3x-pins { + pinctrl-single,pins = < + OMAP4_IOPAD(0x7e, PIN_OUTPUT | MUX_MODE3) + >; + }; + + uart2_pins: pinmux-uart2-pins { + pinctrl-single,pins = < + OMAP4_IOPAD(0x118, PIN_INPUT_PULLUP | MUX_MODE0) /* uart2_cts.uart2_cts */ + OMAP4_IOPAD(0x11a, PIN_OUTPUT | MUX_MODE0) /* uart2_rts.uart2_rts */ + OMAP4_IOPAD(0x11c, PIN_INPUT_PULLUP | MUX_MODE0) /* uart2_rx.uart2_rx */ + OMAP4_IOPAD(0x11e, PIN_OUTPUT | MUX_MODE0) /* uart2_tx.uart2_tx */ + >; + }; + + uart3_pins: pinmux-uart3-pins { + pinctrl-single,pins = < + OMAP4_IOPAD(0x144, PIN_INPUT | MUX_MODE0) /* uart3_rx_irrx */ + OMAP4_IOPAD(0x146, PIN_OUTPUT | MUX_MODE0) /* uart3_tx_irtx */ + >; + }; + + usb_otg_hs_pins: pinmux-usb-otg-hs-pins { + pinctrl-single,pins = < + OMAP4_IOPAD(0x194, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* usba0_otg_ce */ + OMAP4_IOPAD(0x196, PIN_INPUT | MUX_MODE0) /* usba0_otg_dp */ + OMAP4_IOPAD(0x198, PIN_INPUT | MUX_MODE0) /* usba0_otg_dm */ + >; + }; + + wl12xx_pins: pinmux-wl12xx-pins { + pinctrl-single,pins = < + OMAP4_IOPAD(0x1c6, PIN_INPUT | MUX_MODE3) /* gpio_23 / IRQ */ + OMAP4_IOPAD(0x16c, PIN_INPUT_PULLUP | MUX_MODE2) /* sdmmc3_dat2 */ + OMAP4_IOPAD(0x16e, PIN_INPUT_PULLUP | MUX_MODE2) /* sdmmc3_dat1 */ + OMAP4_IOPAD(0x170, PIN_INPUT_PULLUP | MUX_MODE2) /* sdmmc3_dat0 */ + OMAP4_IOPAD(0x172, PIN_INPUT_PULLUP | MUX_MODE2) /* sdmmc3_dat3 */ + OMAP4_IOPAD(0x174, PIN_INPUT_PULLUP | MUX_MODE2) /* sdmmc3_cmd */ + OMAP4_IOPAD(0x176, PIN_INPUT_PULLUP | MUX_MODE2) /* sdmmc3_clk */ + >; + }; + + wl12xx_gpio: pinmux-wl12xx-gpio { + pinctrl-single,pins = < + OMAP4_IOPAD(0x1c8, PIN_OUTPUT | MUX_MODE3) /* gpio_24 / WLAN_EN */ + >; + }; +}; + +&uart2 { + pinctrl-names = "default"; + pinctrl-0 = <&uart2_pins &bt_pins>; + interrupts-extended = <&wakeupgen GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH + &omap4_pmx_core OMAP4_UART2_RX>; + + /* + * BT + GPS in WL1283 in WG7500 requiring CLK32KAUDIO of pmic + * which does not have a driver + */ +}; + +&uart3 { + pinctrl-names = "default"; + pinctrl-0 = <&uart3_pins>; + interrupts-extended = <&wakeupgen GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH + &omap4_pmx_core OMAP4_UART3_RX>; +}; + +&usb_otg_hs { + pinctrl-names = "default"; + pinctrl-0 = <&usb_otg_hs_pins>; + + interface-type = <1>; + mode = <3>; + power = <50>; +}; + +&usbhshost { + status = "disabled"; +}; diff --git a/arch/arm/boot/dts/omap4-kc1.dts b/arch/arm/boot/dts/ti/omap/omap4-kc1.dts similarity index 94% rename from arch/arm/boot/dts/omap4-kc1.dts rename to arch/arm/boot/dts/ti/omap/omap4-kc1.dts index e59d17b25a1d9f9302a4e358b23826316ab9dbc1..c6b79ba8bbc91a250e3a4e93e741298d7e7d3f4d 100644 --- a/arch/arm/boot/dts/omap4-kc1.dts +++ b/arch/arm/boot/dts/ti/omap/omap4-kc1.dts @@ -35,42 +35,42 @@ &omap4_pmx_core { pinctrl-names = "default"; - uart3_pins: pinmux_uart3_pins { + uart3_pins: uart3-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x144, PIN_INPUT | MUX_MODE0) /* uart3_rx_irrx */ OMAP4_IOPAD(0x146, PIN_OUTPUT | MUX_MODE0) /* uart3_tx_irtx */ >; }; - i2c1_pins: pinmux_i2c1_pins { + i2c1_pins: i2c1-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x122, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c1_scl */ OMAP4_IOPAD(0x124, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c1_sda */ >; }; - i2c2_pins: pinmux_i2c2_pins { + i2c2_pins: i2c2-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x126, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c2_scl */ OMAP4_IOPAD(0x128, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c2_sda */ >; }; - i2c3_pins: pinmux_i2c3_pins { + i2c3_pins: i2c3-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x12a, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c3_scl */ OMAP4_IOPAD(0x12c, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c3_sda */ >; }; - i2c4_pins: pinmux_i2c4_pins { + i2c4_pins: i2c4-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x12e, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c4_scl */ OMAP4_IOPAD(0x130, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c4_sda */ >; }; - mmc2_pins: pinmux_mmc2_pins { + mmc2_pins: mmc2-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x040, PIN_INPUT_PULLUP | MUX_MODE1) /* sdmmc2_dat0 */ OMAP4_IOPAD(0x042, PIN_INPUT_PULLUP | MUX_MODE1) /* sdmmc2_dat1 */ @@ -85,7 +85,7 @@ >; }; - usb_otg_hs_pins: pinmux_usb_otg_hs_pins { + usb_otg_hs_pins: usb-otg-hs-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x194, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* usba0_otg_ce */ OMAP4_IOPAD(0x196, PIN_INPUT | MUX_MODE0) /* usba0_otg_dp */ diff --git a/arch/arm/boot/dts/omap4-l4-abe.dtsi b/arch/arm/boot/dts/ti/omap/omap4-l4-abe.dtsi similarity index 100% rename from arch/arm/boot/dts/omap4-l4-abe.dtsi rename to arch/arm/boot/dts/ti/omap/omap4-l4-abe.dtsi diff --git a/arch/arm/boot/dts/omap4-l4.dtsi b/arch/arm/boot/dts/ti/omap/omap4-l4.dtsi similarity index 100% rename from arch/arm/boot/dts/omap4-l4.dtsi rename to arch/arm/boot/dts/ti/omap/omap4-l4.dtsi diff --git a/arch/arm/boot/dts/omap4-mcpdm.dtsi b/arch/arm/boot/dts/ti/omap/omap4-mcpdm.dtsi similarity index 97% rename from arch/arm/boot/dts/omap4-mcpdm.dtsi rename to arch/arm/boot/dts/ti/omap/omap4-mcpdm.dtsi index 915a9b31a33b42e37230e7335d613526fe10833b..03ade47431fbe67b6692fe162f39173d5596c0c3 100644 --- a/arch/arm/boot/dts/omap4-mcpdm.dtsi +++ b/arch/arm/boot/dts/ti/omap/omap4-mcpdm.dtsi @@ -7,7 +7,7 @@ */ &omap4_pmx_core { - mcpdm_pins: pinmux_mcpdm_pins { + mcpdm_pins: mcpdm-pins { pinctrl-single,pins = < /* 0x4a100106 abe_pdm_ul_data.abe_pdm_ul_data ag25 */ OMAP4_IOPAD(0x106, PIN_INPUT_PULLDOWN | MUX_MODE0) diff --git a/arch/arm/boot/dts/omap4-panda-a4.dts b/arch/arm/boot/dts/ti/omap/omap4-panda-a4.dts similarity index 100% rename from arch/arm/boot/dts/omap4-panda-a4.dts rename to arch/arm/boot/dts/ti/omap/omap4-panda-a4.dts diff --git a/arch/arm/boot/dts/omap4-panda-common.dtsi b/arch/arm/boot/dts/ti/omap/omap4-panda-common.dtsi similarity index 96% rename from arch/arm/boot/dts/omap4-panda-common.dtsi rename to arch/arm/boot/dts/ti/omap/omap4-panda-common.dtsi index 0269424350aae2f106bdf775e6f2213261a39053..f528511c2537b68221faaaba30bab6131109b97c 100644 --- a/arch/arm/boot/dts/omap4-panda-common.dtsi +++ b/arch/arm/boot/dts/ti/omap/omap4-panda-common.dtsi @@ -237,14 +237,14 @@ &hsusbb1_pins >; - twl6040_pins: pinmux_twl6040_pins { + twl6040_pins: twl6040-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x120, PIN_OUTPUT | MUX_MODE3) /* hdq_sio.gpio_127 */ OMAP4_IOPAD(0x1a0, PIN_INPUT | MUX_MODE0) /* sys_nirq2.sys_nirq2 */ >; }; - mcbsp1_pins: pinmux_mcbsp1_pins { + mcbsp1_pins: mcbsp1-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x0fe, PIN_INPUT | MUX_MODE0) /* abe_mcbsp1_clkx.abe_mcbsp1_clkx */ OMAP4_IOPAD(0x100, PIN_INPUT_PULLDOWN | MUX_MODE0) /* abe_mcbsp1_dr.abe_mcbsp1_dr */ @@ -253,7 +253,7 @@ >; }; - dss_dpi_pins: pinmux_dss_dpi_pins { + dss_dpi_pins: dss-dpi-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x162, PIN_OUTPUT | MUX_MODE5) /* dispc2_data23 */ OMAP4_IOPAD(0x164, PIN_OUTPUT | MUX_MODE5) /* dispc2_data22 */ @@ -288,13 +288,13 @@ >; }; - tfp410_pins: pinmux_tfp410_pins { + tfp410_pins: tfp410-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x184, PIN_OUTPUT | MUX_MODE3) /* gpio_0 */ >; }; - dss_hdmi_pins: pinmux_dss_hdmi_pins { + dss_hdmi_pins: dss-hdmi-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x09a, PIN_INPUT | MUX_MODE0) /* hdmi_cec.hdmi_cec */ OMAP4_IOPAD(0x09c, PIN_INPUT_PULLUP | MUX_MODE0) /* hdmi_scl.hdmi_scl */ @@ -302,7 +302,7 @@ >; }; - tpd12s015_pins: pinmux_tpd12s015_pins { + tpd12s015_pins: tpd12s015-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x062, PIN_OUTPUT | MUX_MODE3) /* gpmc_a17.gpio_41 */ OMAP4_IOPAD(0x088, PIN_OUTPUT | MUX_MODE3) /* gpmc_nbe1.gpio_60 */ @@ -310,7 +310,7 @@ >; }; - hsusbb1_pins: pinmux_hsusbb1_pins { + hsusbb1_pins: hsusbb1-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x0c2, PIN_INPUT_PULLDOWN | MUX_MODE4) /* usbb1_ulpitll_clk.usbb1_ulpiphy_clk */ OMAP4_IOPAD(0x0c4, PIN_OUTPUT | MUX_MODE4) /* usbb1_ulpitll_stp.usbb1_ulpiphy_stp */ @@ -327,28 +327,28 @@ >; }; - i2c1_pins: pinmux_i2c1_pins { + i2c1_pins: i2c1-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x122, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c1_scl */ OMAP4_IOPAD(0x124, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c1_sda */ >; }; - i2c2_pins: pinmux_i2c2_pins { + i2c2_pins: i2c2-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x126, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c2_scl */ OMAP4_IOPAD(0x128, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c2_sda */ >; }; - i2c3_pins: pinmux_i2c3_pins { + i2c3_pins: i2c3-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x12a, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c3_scl */ OMAP4_IOPAD(0x12c, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c3_sda */ >; }; - i2c4_pins: pinmux_i2c4_pins { + i2c4_pins: i2c4-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x12e, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c4_scl */ OMAP4_IOPAD(0x130, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c4_sda */ @@ -359,7 +359,7 @@ * wl12xx GPIO outputs for WLAN_EN, BT_EN, FM_EN, BT_WAKEUP * REVISIT: Are the pull-ups needed for GPIO 48 and 49? */ - wl12xx_gpio: pinmux_wl12xx_gpio { + wl12xx_gpio: wl12xx-gpio-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x066, PIN_OUTPUT | MUX_MODE3) /* gpmc_a19.gpio_43 */ OMAP4_IOPAD(0x06c, PIN_OUTPUT | MUX_MODE3) /* gpmc_a22.gpio_46 */ @@ -369,7 +369,7 @@ }; /* wl12xx GPIO inputs and SDIO pins */ - wl12xx_pins: pinmux_wl12xx_pins { + wl12xx_pins: wl12xx-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x078, PIN_INPUT | MUX_MODE3) /* gpmc_ncs2.gpio_52 */ OMAP4_IOPAD(0x07a, PIN_INPUT | MUX_MODE3) /* gpmc_ncs3.gpio_53 */ @@ -382,7 +382,7 @@ >; }; - button_pins: pinmux_button_pins { + button_pins: button-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x114, PIN_INPUT_PULLUP | MUX_MODE3) /* gpio_121 */ >; @@ -390,7 +390,7 @@ }; &omap4_pmx_wkup { - led_wkgpio_pins: pinmux_leds_wkpins { + led_wkgpio_pins: leds-wkpins-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x05a, PIN_OUTPUT | MUX_MODE3) /* gpio_wk7 */ OMAP4_IOPAD(0x05c, PIN_OUTPUT | MUX_MODE3) /* gpio_wk8 */ diff --git a/arch/arm/boot/dts/omap4-panda-es.dts b/arch/arm/boot/dts/ti/omap/omap4-panda-es.dts similarity index 95% rename from arch/arm/boot/dts/omap4-panda-es.dts rename to arch/arm/boot/dts/ti/omap/omap4-panda-es.dts index 7631029e4d7a8906459f32dfe88160701896a546..fe7b156d10ed03a43781f98871517f3c332fcb7c 100644 --- a/arch/arm/boot/dts/omap4-panda-es.dts +++ b/arch/arm/boot/dts/ti/omap/omap4-panda-es.dts @@ -38,26 +38,26 @@ }; &omap4_pmx_core { - led_gpio_pins: gpio_led_pmx { + led_gpio_pins: gpio-led-pmx-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x0f6, PIN_OUTPUT | MUX_MODE3) /* gpio_110 */ >; }; - button_pins: pinmux_button_pins { + button_pins: button-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x0fc, PIN_INPUT_PULLUP | MUX_MODE3) /* gpio_113 */ >; }; - bt_pins: pinmux_bt_pins { + bt_pins: bt-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x06c, PIN_OUTPUT | MUX_MODE3) /* gpmc_a22.gpio_46 - BTEN */ OMAP4_IOPAD(0x072, PIN_OUTPUT_PULLUP | MUX_MODE3) /* gpmc_a25.gpio_49 - BTWAKEUP */ >; }; - uart2_pins: pinmux_uart2_pins { + uart2_pins: uart2-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x118, PIN_INPUT_PULLUP | MUX_MODE0) /* uart2_cts.uart2_cts - HCI */ OMAP4_IOPAD(0x11a, PIN_OUTPUT | MUX_MODE0) /* uart2_rts.uart2_rts */ diff --git a/arch/arm/boot/dts/omap4-panda.dts b/arch/arm/boot/dts/ti/omap/omap4-panda.dts similarity index 100% rename from arch/arm/boot/dts/omap4-panda.dts rename to arch/arm/boot/dts/ti/omap/omap4-panda.dts diff --git a/arch/arm/boot/dts/omap4-sdp-es23plus.dts b/arch/arm/boot/dts/ti/omap/omap4-sdp-es23plus.dts similarity index 100% rename from arch/arm/boot/dts/omap4-sdp-es23plus.dts rename to arch/arm/boot/dts/ti/omap/omap4-sdp-es23plus.dts diff --git a/arch/arm/boot/dts/omap4-sdp.dts b/arch/arm/boot/dts/ti/omap/omap4-sdp.dts similarity index 96% rename from arch/arm/boot/dts/omap4-sdp.dts rename to arch/arm/boot/dts/ti/omap/omap4-sdp.dts index 9e976140f34a625663b26a7da7496dcbdeab7d1e..b2cb93edbc3a69a11bbf3ee6ecf74f5cfa2f3e08 100644 --- a/arch/arm/boot/dts/omap4-sdp.dts +++ b/arch/arm/boot/dts/ti/omap/omap4-sdp.dts @@ -214,7 +214,7 @@ &tpd12s015_pins >; - uart2_pins: pinmux_uart2_pins { + uart2_pins: uart2-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x118, PIN_INPUT_PULLUP | MUX_MODE0) /* uart2_cts.uart2_cts */ OMAP4_IOPAD(0x11a, PIN_OUTPUT | MUX_MODE0) /* uart2_rts.uart2_rts */ @@ -223,7 +223,7 @@ >; }; - uart3_pins: pinmux_uart3_pins { + uart3_pins: uart3-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x140, PIN_INPUT_PULLUP | MUX_MODE0) /* uart3_cts_rctx.uart3_cts_rctx */ OMAP4_IOPAD(0x142, PIN_OUTPUT | MUX_MODE0) /* uart3_rts_sd.uart3_rts_sd */ @@ -232,21 +232,21 @@ >; }; - uart4_pins: pinmux_uart4_pins { + uart4_pins: uart4-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x15c, PIN_INPUT | MUX_MODE0) /* uart4_rx.uart4_rx */ OMAP4_IOPAD(0x15e, PIN_OUTPUT | MUX_MODE0) /* uart4_tx.uart4_tx */ >; }; - twl6040_pins: pinmux_twl6040_pins { + twl6040_pins: twl6040-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x120, PIN_OUTPUT | MUX_MODE3) /* hdq_sio.gpio_127 */ OMAP4_IOPAD(0x1a0, PIN_INPUT | MUX_MODE0) /* sys_nirq2.sys_nirq2 */ >; }; - dmic_pins: pinmux_dmic_pins { + dmic_pins: dmic-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x110, PIN_OUTPUT | MUX_MODE0) /* abe_dmic_clk1.abe_dmic_clk1 */ OMAP4_IOPAD(0x112, PIN_INPUT | MUX_MODE0) /* abe_dmic_din1.abe_dmic_din1 */ @@ -255,7 +255,7 @@ >; }; - mcbsp1_pins: pinmux_mcbsp1_pins { + mcbsp1_pins: mcbsp1-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x0fe, PIN_INPUT | MUX_MODE0) /* abe_mcbsp1_clkx.abe_mcbsp1_clkx */ OMAP4_IOPAD(0x100, PIN_INPUT_PULLDOWN | MUX_MODE0) /* abe_mcbsp1_dr.abe_mcbsp1_dr */ @@ -264,7 +264,7 @@ >; }; - mcbsp2_pins: pinmux_mcbsp2_pins { + mcbsp2_pins: mcbsp2-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x0f6, PIN_INPUT | MUX_MODE0) /* abe_mcbsp2_clkx.abe_mcbsp2_clkx */ OMAP4_IOPAD(0x0f8, PIN_INPUT_PULLDOWN | MUX_MODE0) /* abe_mcbsp2_dr.abe_mcbsp2_dr */ @@ -273,7 +273,7 @@ >; }; - mcspi1_pins: pinmux_mcspi1_pins { + mcspi1_pins: mcspi1-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x132, PIN_INPUT | MUX_MODE0) /* mcspi1_clk.mcspi1_clk */ OMAP4_IOPAD(0x134, PIN_INPUT | MUX_MODE0) /* mcspi1_somi.mcspi1_somi */ @@ -282,7 +282,7 @@ >; }; - dss_hdmi_pins: pinmux_dss_hdmi_pins { + dss_hdmi_pins: dss-hdmi-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x09a, PIN_INPUT | MUX_MODE0) /* hdmi_cec.hdmi_cec */ OMAP4_IOPAD(0x09c, PIN_INPUT_PULLUP | MUX_MODE0) /* hdmi_scl.hdmi_scl */ @@ -290,7 +290,7 @@ >; }; - tpd12s015_pins: pinmux_tpd12s015_pins { + tpd12s015_pins: tpd12s015-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x062, PIN_OUTPUT | MUX_MODE3) /* gpmc_a17.gpio_41 */ OMAP4_IOPAD(0x088, PIN_OUTPUT | MUX_MODE3) /* gpmc_nbe1.gpio_60 */ @@ -298,28 +298,28 @@ >; }; - i2c1_pins: pinmux_i2c1_pins { + i2c1_pins: i2c1-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x122, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c1_scl */ OMAP4_IOPAD(0x124, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c1_sda */ >; }; - i2c2_pins: pinmux_i2c2_pins { + i2c2_pins: i2c2-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x126, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c2_scl */ OMAP4_IOPAD(0x128, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c2_sda */ >; }; - i2c3_pins: pinmux_i2c3_pins { + i2c3_pins: i2c3-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x12a, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c3_scl */ OMAP4_IOPAD(0x12c, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c3_sda */ >; }; - i2c4_pins: pinmux_i2c4_pins { + i2c4_pins: i2c4-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x12e, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c4_scl */ OMAP4_IOPAD(0x130, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c4_sda */ @@ -327,14 +327,14 @@ }; /* wl12xx GPIO output for WLAN_EN */ - wl12xx_gpio: pinmux_wl12xx_gpio { + wl12xx_gpio: wl12xx-gpio-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x07c, PIN_OUTPUT | MUX_MODE3) /* gpmc_nwp.gpio_54 */ >; }; /* wl12xx GPIO inputs and SDIO pins */ - wl12xx_pins: pinmux_wl12xx_pins { + wl12xx_pins: wl12xx-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x07a, PIN_INPUT | MUX_MODE3) /* gpmc_ncs3.gpio_53 */ OMAP4_IOPAD(0x148, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc5_clk.sdmmc5_clk */ @@ -347,13 +347,13 @@ }; /* gpio_48 for ENET_ENABLE */ - enet_enable_gpio: pinmux_enet_enable_gpio { + enet_enable_gpio: enet-enable-gpio-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x070, PIN_OUTPUT_PULLDOWN | MUX_MODE3) /* gpmc_a24.gpio_48 */ >; }; - ks8851_pins: pinmux_ks8851_pins { + ks8851_pins: ks8851-pins { pinctrl-single,pins = < /* ENET_INT */ OMAP4_IOPAD(0x054, PIN_INPUT_PULLUP | MUX_MODE3) /* gpmc_ad10.gpio_34 */ diff --git a/arch/arm/boot/dts/omap4-var-dvk-om44.dts b/arch/arm/boot/dts/ti/omap/omap4-var-dvk-om44.dts similarity index 100% rename from arch/arm/boot/dts/omap4-var-dvk-om44.dts rename to arch/arm/boot/dts/ti/omap/omap4-var-dvk-om44.dts diff --git a/arch/arm/boot/dts/omap4-var-om44customboard.dtsi b/arch/arm/boot/dts/ti/omap/omap4-var-om44customboard.dtsi similarity index 93% rename from arch/arm/boot/dts/omap4-var-om44customboard.dtsi rename to arch/arm/boot/dts/ti/omap/omap4-var-om44customboard.dtsi index 458cb53dd3d18b85a5d3d77e3eb26bba7db73829..cadc7e02592bfd96838db11bbcfc5533959b3923 100644 --- a/arch/arm/boot/dts/omap4-var-om44customboard.dtsi +++ b/arch/arm/boot/dts/ti/omap/omap4-var-om44customboard.dtsi @@ -60,7 +60,7 @@ }; &omap4_pmx_core { - uart1_pins: pinmux_uart1_pins { + uart1_pins: uart1-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x13c, PIN_INPUT_PULLUP | MUX_MODE1) /* mcspi1_cs2.uart1_cts */ OMAP4_IOPAD(0x13e, PIN_OUTPUT | MUX_MODE1) /* mcspi1_cs3.uart1_rts */ @@ -69,7 +69,7 @@ >; }; - mcspi1_pins: pinmux_mcspi1_pins { + mcspi1_pins: mcspi1-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x132, PIN_INPUT | MUX_MODE0) /* mcspi1_clk.mcspi1_clk */ OMAP4_IOPAD(0x134, PIN_INPUT | MUX_MODE0) /* mcspi1_somi.mcspi1_somi */ @@ -78,13 +78,13 @@ >; }; - mcasp_pins: pinmux_mcsasp_pins { + mcasp_pins: mcsasp-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x0f8, PIN_OUTPUT | MUX_MODE2) /* mcbsp2_dr.abe_mcasp_axr */ >; }; - dss_dpi_pins: pinmux_dss_dpi_pins { + dss_dpi_pins: dss-dpi-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x162, PIN_OUTPUT | MUX_MODE5) /* dispc2_data23 */ OMAP4_IOPAD(0x164, PIN_OUTPUT | MUX_MODE5) /* dispc2_data22 */ @@ -117,7 +117,7 @@ >; }; - dss_hdmi_pins: pinmux_dss_hdmi_pins { + dss_hdmi_pins: dss-hdmi-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x09a, PIN_INPUT | MUX_MODE0) /* hdmi_cec.hdmi_cec */ OMAP4_IOPAD(0x09c, PIN_INPUT_PULLUP | MUX_MODE0) /* hdmi_scl.hdmi_scl */ @@ -125,14 +125,14 @@ >; }; - i2c4_pins: pinmux_i2c4_pins { + i2c4_pins: i2c4-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x12e, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c4_scl */ OMAP4_IOPAD(0x130, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c4_sda */ >; }; - mmc5_pins: pinmux_mmc5_pins { + mmc5_pins: mmc5-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x0f6, PIN_INPUT | MUX_MODE3) /* abe_mcbsp2_clkx.gpio_110 */ OMAP4_IOPAD(0x148, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc5_clk.sdmmc5_clk */ @@ -144,32 +144,32 @@ >; }; - gpio_led_pins: pinmux_gpio_led_pins { + gpio_led_pins: gpio-led-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x17e, PIN_OUTPUT | MUX_MODE3) /* kpd_col4.gpio_172 */ OMAP4_IOPAD(0x180, PIN_OUTPUT | MUX_MODE3) /* kpd_col5.gpio_173 */ >; }; - gpio_key_pins: pinmux_gpio_key_pins { + gpio_key_pins: gpio-key-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x1a2, PIN_INPUT | MUX_MODE3) /* sys_boot0.gpio_184 */ >; }; - ks8851_irq_pins: pinmux_ks8851_irq_pins { + ks8851_irq_pins: ks8851-irq-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x17c, PIN_INPUT_PULLUP | MUX_MODE3) /* kpd_col3.gpio_171 */ >; }; - hdmi_hpd_pins: pinmux_hdmi_hpd_pins { + hdmi_hpd_pins: hdmi-hpd-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x098, PIN_INPUT_PULLDOWN | MUX_MODE3) /* hdmi_hpd.gpio_63 */ >; }; - backlight_pins: pinmux_backlight_pins { + backlight_pins: backlight-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x116, PIN_OUTPUT | MUX_MODE3) /* abe_dmic_din3.gpio_122 */ >; diff --git a/arch/arm/boot/dts/omap4-var-som-om44-wlan.dtsi b/arch/arm/boot/dts/ti/omap/omap4-var-som-om44-wlan.dtsi similarity index 95% rename from arch/arm/boot/dts/omap4-var-som-om44-wlan.dtsi rename to arch/arm/boot/dts/ti/omap/omap4-var-som-om44-wlan.dtsi index d0032213101e652dd4b7ce54615178ce5bf44e98..de779d2d7c3e96b4b64824751e9f0e8ab2646b5a 100644 --- a/arch/arm/boot/dts/omap4-var-som-om44-wlan.dtsi +++ b/arch/arm/boot/dts/ti/omap/omap4-var-som-om44-wlan.dtsi @@ -19,7 +19,7 @@ }; &omap4_pmx_core { - uart2_pins: pinmux_uart2_pins { + uart2_pins: uart2-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x118, PIN_INPUT_PULLUP | MUX_MODE0) /* uart2_cts.uart2_cts */ OMAP4_IOPAD(0x11a, PIN_OUTPUT | MUX_MODE0) /* uart2_rts.uart2_rts */ @@ -28,7 +28,7 @@ >; }; - wl12xx_ctrl_pins: pinmux_wl12xx_ctrl_pins { + wl12xx_ctrl_pins: wl12xx-ctrl-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x062, PIN_INPUT_PULLUP | MUX_MODE3) /* gpmc_a17.gpio_41 (WLAN_IRQ) */ OMAP4_IOPAD(0x064, PIN_OUTPUT | MUX_MODE3) /* gpmc_a18.gpio_42 (BT_EN) */ @@ -36,7 +36,7 @@ >; }; - mmc4_pins: pinmux_mmc4_pins { + mmc4_pins: mmc4-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x154, PIN_INPUT_PULLUP | MUX_MODE1) /* mcspi4_clk.sdmmc4_clk */ OMAP4_IOPAD(0x156, PIN_INPUT_PULLUP | MUX_MODE1) /* mcspi4_simo.sdmmc4_cmd */ diff --git a/arch/arm/boot/dts/omap4-var-som-om44.dtsi b/arch/arm/boot/dts/ti/omap/omap4-var-som-om44.dtsi similarity index 94% rename from arch/arm/boot/dts/omap4-var-som-om44.dtsi rename to arch/arm/boot/dts/ti/omap/omap4-var-som-om44.dtsi index 334cbbaa5b8b0a22ddb3a2f9e62f6765a3b272f4..37d56b3010cff0f6ea6208289da0aba7328067d5 100644 --- a/arch/arm/boot/dts/omap4-var-som-om44.dtsi +++ b/arch/arm/boot/dts/ti/omap/omap4-var-som-om44.dtsi @@ -65,21 +65,21 @@ &hsusbb1_pins >; - twl6040_pins: pinmux_twl6040_pins { + twl6040_pins: twl6040-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x19c, PIN_OUTPUT | MUX_MODE3) /* fref_clk2_out.gpio_182 */ OMAP4_IOPAD(0x1a0, PIN_INPUT | MUX_MODE0) /* sys_nirq2.sys_nirq2 */ >; }; - tsc2004_pins: pinmux_tsc2004_pins { + tsc2004_pins: tsc2004-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x090, PIN_INPUT | MUX_MODE3) /* gpmc_ncs4.gpio_101 (irq) */ OMAP4_IOPAD(0x092, PIN_OUTPUT | MUX_MODE3) /* gpmc_ncs5.gpio_102 (rst) */ >; }; - uart3_pins: pinmux_uart3_pins { + uart3_pins: uart3-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x140, PIN_INPUT_PULLUP | MUX_MODE0) /* uart3_cts_rctx.uart3_cts_rctx */ OMAP4_IOPAD(0x142, PIN_OUTPUT | MUX_MODE0) /* uart3_rts_sd.uart3_rts_sd */ @@ -88,7 +88,7 @@ >; }; - hsusbb1_pins: pinmux_hsusbb1_pins { + hsusbb1_pins: hsusbb1-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x0c2, PIN_INPUT_PULLDOWN | MUX_MODE4) /* usbb1_ulpitll_clk.usbb1_ulpiphy_clk */ OMAP4_IOPAD(0x0c4, PIN_OUTPUT | MUX_MODE4) /* usbb1_ulpitll_stp.usbb1_ulpiphy_stp */ @@ -105,27 +105,27 @@ >; }; - hsusbb1_phy_rst_pins: pinmux_hsusbb1_phy_rst_pins { + hsusbb1_phy_rst_pins: hsusbb1-phy-rst-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x18c, PIN_OUTPUT | MUX_MODE3) /* kpd_row2.gpio_177 */ >; }; - i2c1_pins: pinmux_i2c1_pins { + i2c1_pins: i2c1-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x122, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c1_scl */ OMAP4_IOPAD(0x124, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c1_sda */ >; }; - i2c3_pins: pinmux_i2c3_pins { + i2c3_pins: i2c3-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x12a, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c3_scl */ OMAP4_IOPAD(0x12c, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c3_sda */ >; }; - mmc1_pins: pinmux_mmc1_pins { + mmc1_pins: mmc1-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x0e2, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc1_clk.sdmmc1_clk */ OMAP4_IOPAD(0x0e4, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc1_cmd.sdmmc1_cmd */ @@ -144,19 +144,19 @@ &lan7500_rst_pins >; - hsusbb1_phy_clk_pins: pinmux_hsusbb1_phy_clk_pins { + hsusbb1_phy_clk_pins: hsusbb1-phy-clk-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x058, PIN_OUTPUT | MUX_MODE0) /* fref_clk3_out */ >; }; - hsusbb1_hub_rst_pins: pinmux_hsusbb1_hub_rst_pins { + hsusbb1_hub_rst_pins: hsusbb1-hub-rst-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x042, PIN_OUTPUT | MUX_MODE3) /* gpio_wk1 */ >; }; - lan7500_rst_pins: pinmux_lan7500_rst_pins { + lan7500_rst_pins: lan7500-rst-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x040, PIN_OUTPUT | MUX_MODE3) /* gpio_wk0 */ >; diff --git a/arch/arm/boot/dts/omap4-var-stk-om44.dts b/arch/arm/boot/dts/ti/omap/omap4-var-stk-om44.dts similarity index 100% rename from arch/arm/boot/dts/omap4-var-stk-om44.dts rename to arch/arm/boot/dts/ti/omap/omap4-var-stk-om44.dts diff --git a/arch/arm/boot/dts/omap4.dtsi b/arch/arm/boot/dts/ti/omap/omap4.dtsi similarity index 100% rename from arch/arm/boot/dts/omap4.dtsi rename to arch/arm/boot/dts/ti/omap/omap4.dtsi diff --git a/arch/arm/boot/dts/omap443x-clocks.dtsi b/arch/arm/boot/dts/ti/omap/omap443x-clocks.dtsi similarity index 100% rename from arch/arm/boot/dts/omap443x-clocks.dtsi rename to arch/arm/boot/dts/ti/omap/omap443x-clocks.dtsi diff --git a/arch/arm/boot/dts/omap443x.dtsi b/arch/arm/boot/dts/ti/omap/omap443x.dtsi similarity index 100% rename from arch/arm/boot/dts/omap443x.dtsi rename to arch/arm/boot/dts/ti/omap/omap443x.dtsi diff --git a/arch/arm/boot/dts/omap4460.dtsi b/arch/arm/boot/dts/ti/omap/omap4460.dtsi similarity index 100% rename from arch/arm/boot/dts/omap4460.dtsi rename to arch/arm/boot/dts/ti/omap/omap4460.dtsi diff --git a/arch/arm/boot/dts/omap446x-clocks.dtsi b/arch/arm/boot/dts/ti/omap/omap446x-clocks.dtsi similarity index 100% rename from arch/arm/boot/dts/omap446x-clocks.dtsi rename to arch/arm/boot/dts/ti/omap/omap446x-clocks.dtsi diff --git a/arch/arm/boot/dts/omap44xx-clocks.dtsi b/arch/arm/boot/dts/ti/omap/omap44xx-clocks.dtsi similarity index 100% rename from arch/arm/boot/dts/omap44xx-clocks.dtsi rename to arch/arm/boot/dts/ti/omap/omap44xx-clocks.dtsi diff --git a/arch/arm/boot/dts/omap5-board-common.dtsi b/arch/arm/boot/dts/ti/omap/omap5-board-common.dtsi similarity index 95% rename from arch/arm/boot/dts/omap5-board-common.dtsi rename to arch/arm/boot/dts/ti/omap/omap5-board-common.dtsi index 373984c130e01d98f10916b2d481bbefc833146b..6f46f1ecf1e577958efe9aa0b951e7313ee948a1 100644 --- a/arch/arm/boot/dts/omap5-board-common.dtsi +++ b/arch/arm/boot/dts/ti/omap/omap5-board-common.dtsi @@ -56,7 +56,7 @@ }; /* HS USB Host PHY on PORT 2 */ - hsusb2_phy: hsusb2_phy { + hsusb2_phy: hsusb2-phy-pins { compatible = "usb-nop-xceiv"; reset-gpios = <&gpio3 16 GPIO_ACTIVE_LOW>; /* gpio3_80 HUB_NRESET */ clocks = <&auxclk1_ck>; @@ -156,13 +156,13 @@ &led_gpio_pins >; - twl6040_pins: pinmux_twl6040_pins { + twl6040_pins: twl6040-pins { pinctrl-single,pins = < OMAP5_IOPAD(0x1be, PIN_OUTPUT | MUX_MODE6) /* mcspi1_somi.gpio5_141 */ >; }; - mcpdm_pins: pinmux_mcpdm_pins { + mcpdm_pins: mcpdm-pins { pinctrl-single,pins = < OMAP5_IOPAD(0x182, PIN_INPUT_PULLDOWN | MUX_MODE0) /* abe_clks.abe_clks */ OMAP5_IOPAD(0x19c, PIN_INPUT_PULLDOWN | MUX_MODE0) /* abemcpdm_ul_data.abemcpdm_ul_data */ @@ -172,7 +172,7 @@ >; }; - mcbsp1_pins: pinmux_mcbsp1_pins { + mcbsp1_pins: mcbsp1-pins { pinctrl-single,pins = < OMAP5_IOPAD(0x18c, PIN_INPUT | MUX_MODE1) /* abedmic_clk2.abemcbsp1_fsx */ OMAP5_IOPAD(0x18e, PIN_OUTPUT_PULLDOWN | MUX_MODE1) /* abedmic_clk3.abemcbsp1_dx */ @@ -181,7 +181,7 @@ >; }; - mcbsp2_pins: pinmux_mcbsp2_pins { + mcbsp2_pins: mcbsp2-pins { pinctrl-single,pins = < OMAP5_IOPAD(0x194, PIN_INPUT_PULLDOWN | MUX_MODE0) /* abemcbsp2_dr.abemcbsp2_dr */ OMAP5_IOPAD(0x196, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* abemcbsp2_dx.abemcbsp2_dx */ @@ -190,14 +190,14 @@ >; }; - i2c1_pins: pinmux_i2c1_pins { + i2c1_pins: i2c1-pins { pinctrl-single,pins = < OMAP5_IOPAD(0x1f2, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c1_scl */ OMAP5_IOPAD(0x1f4, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c1_sda */ >; }; - mcspi2_pins: pinmux_mcspi2_pins { + mcspi2_pins: mcspi2-pins { pinctrl-single,pins = < OMAP5_IOPAD(0x0fc, PIN_INPUT | MUX_MODE0) /* mcspi2_clk */ OMAP5_IOPAD(0x0fe, PIN_INPUT | MUX_MODE0) /* mcspi2_simo */ @@ -206,7 +206,7 @@ >; }; - mcspi3_pins: pinmux_mcspi3_pins { + mcspi3_pins: mcspi3-pins { pinctrl-single,pins = < OMAP5_IOPAD(0x0b8, PIN_INPUT | MUX_MODE1) /* mcspi3_somi */ OMAP5_IOPAD(0x0ba, PIN_INPUT | MUX_MODE1) /* mcspi3_cs0 */ @@ -215,7 +215,7 @@ >; }; - mmc3_pins: pinmux_mmc3_pins { + mmc3_pins: mmc3-pins { pinctrl-single,pins = < OMAP5_IOPAD(0x01a4, PIN_INPUT_PULLUP | MUX_MODE0) /* wlsdio_clk */ OMAP5_IOPAD(0x01a6, PIN_INPUT_PULLUP | MUX_MODE0) /* wlsdio_cmd */ @@ -226,20 +226,20 @@ >; }; - wlan_pins: pinmux_wlan_pins { + wlan_pins: wlan-pins { pinctrl-single,pins = < OMAP5_IOPAD(0x1bc, PIN_OUTPUT | MUX_MODE6) /* mcspi1_clk.gpio5_140 */ >; }; /* TI trees use GPIO mode; msecure mode does not work reliably? */ - palmas_msecure_pins: palmas_msecure_pins { + palmas_msecure_pins: palmas-msecure-pins { pinctrl-single,pins = < OMAP5_IOPAD(0x180, PIN_OUTPUT | MUX_MODE6) /* gpio8_234 */ >; }; - usbhost_pins: pinmux_usbhost_pins { + usbhost_pins: usbhost-pins { pinctrl-single,pins = < OMAP5_IOPAD(0x0c4, PIN_INPUT | MUX_MODE0) /* usbb2_hsic_strobe */ OMAP5_IOPAD(0x0c6, PIN_INPUT | MUX_MODE0) /* usbb2_hsic_data */ @@ -252,13 +252,13 @@ >; }; - led_gpio_pins: pinmux_led_gpio_pins { + led_gpio_pins: led-gpio-pins { pinctrl-single,pins = < OMAP5_IOPAD(0x1d6, PIN_OUTPUT | MUX_MODE6) /* uart3_cts_rctx.gpio5_153 */ >; }; - uart1_pins: pinmux_uart1_pins { + uart1_pins: uart1-pins { pinctrl-single,pins = < OMAP5_IOPAD(0x0a0, PIN_OUTPUT | MUX_MODE0) /* uart1_tx.uart1_cts */ OMAP5_IOPAD(0x0a2, PIN_INPUT_PULLUP | MUX_MODE0) /* uart1_tx.uart1_cts */ @@ -267,14 +267,14 @@ >; }; - uart3_pins: pinmux_uart3_pins { + uart3_pins: uart3-pins { pinctrl-single,pins = < OMAP5_IOPAD(0x1da, PIN_OUTPUT | MUX_MODE0) /* uart3_rts_irsd.uart3_tx_irtx */ OMAP5_IOPAD(0x1dc, PIN_INPUT_PULLUP | MUX_MODE0) /* uart3_rx_irrx.uart3_usbb3_hsic */ >; }; - uart5_pins: pinmux_uart5_pins { + uart5_pins: uart5-pins { pinctrl-single,pins = < OMAP5_IOPAD(0x1b0, PIN_INPUT_PULLUP | MUX_MODE0) /* uart5_rx.uart5_rx */ OMAP5_IOPAD(0x1b2, PIN_OUTPUT | MUX_MODE0) /* uart5_tx.uart5_tx */ @@ -283,7 +283,7 @@ >; }; - dss_hdmi_pins: pinmux_dss_hdmi_pins { + dss_hdmi_pins: dss-hdmi-pins { pinctrl-single,pins = < OMAP5_IOPAD(0x13c, PIN_INPUT | MUX_MODE0) /* hdmi_cec.hdmi_cec */ OMAP5_IOPAD(0x140, PIN_INPUT | MUX_MODE0) /* hdmi_ddc_scl.hdmi_ddc_scl */ @@ -291,7 +291,7 @@ >; }; - tpd12s015_pins: pinmux_tpd12s015_pins { + tpd12s015_pins: tpd12s015-pins { pinctrl-single,pins = < OMAP5_IOPAD(0x13e, PIN_INPUT_PULLDOWN | MUX_MODE6) /* hdmi_hpd.gpio7_193 */ >; @@ -304,20 +304,20 @@ &usbhost_wkup_pins >; - palmas_sys_nirq_pins: pinmux_palmas_sys_nirq_pins { + palmas_sys_nirq_pins: palmas-sys-nirq-pins { pinctrl-single,pins = < /* sys_nirq1 is pulled down as the SoC is inverting it for GIC */ OMAP5_IOPAD(0x068, PIN_INPUT_PULLUP | MUX_MODE0) >; }; - usbhost_wkup_pins: pinmux_usbhost_wkup_pins { + usbhost_wkup_pins: usbhost-wkup-pins { pinctrl-single,pins = < OMAP5_IOPAD(0x05a, PIN_OUTPUT | MUX_MODE0) /* fref_clk1_out, USB hub clk */ >; }; - wlcore_irq_pin: pinmux_wlcore_irq_pin { + wlcore_irq_pin: wlcore-irq-pin-pins { pinctrl-single,pins = < OMAP5_IOPAD(0x40, PIN_INPUT | MUX_MODE6) /* llia_wakereqin.gpio1_wk14 */ >; diff --git a/arch/arm/boot/dts/omap5-cm-t54.dts b/arch/arm/boot/dts/ti/omap/omap5-cm-t54.dts similarity index 96% rename from arch/arm/boot/dts/omap5-cm-t54.dts rename to arch/arm/boot/dts/ti/omap/omap5-cm-t54.dts index af288d63a26a464b456e5f353a0464d61715022e..6767382996ab3343038618f0da6523ac16ce2823 100644 --- a/arch/arm/boot/dts/omap5-cm-t54.dts +++ b/arch/arm/boot/dts/ti/omap/omap5-cm-t54.dts @@ -60,7 +60,7 @@ }; /* HS USB Host PHY on PORT 2 */ - hsusb2_phy: hsusb2_phy { + hsusb2_phy: hsusb2-phy-pins { compatible = "usb-nop-xceiv"; reset-gpios = <&gpio3 12 GPIO_ACTIVE_LOW>; /* gpio3_76 HUB_RESET */ #phy-cells = <0>; @@ -176,13 +176,13 @@ &omap5_pmx_wkup { - ads7846_pins: pinmux_ads7846_pins { + ads7846_pins: ads7846-pins { pinctrl-single,pins = < OMAP5_IOPAD(0x0042, PIN_INPUT_PULLDOWN | MUX_MODE6) /* llib_wakereqin.gpio1_wk15 */ >; }; - palmas_sys_nirq_pins: pinmux_palmas_sys_nirq_pins { + palmas_sys_nirq_pins: palmas-sys-nirq-pins { pinctrl-single,pins = < /* sys_nirq1 is pulled down as the SoC is inverting it for GIC */ OMAP5_IOPAD(0x068, PIN_INPUT_PULLUP | MUX_MODE0) @@ -197,27 +197,27 @@ &usbhost_pins >; - led_gpio_pins: pinmux_led_gpio_pins { + led_gpio_pins: led-gpio-pins { pinctrl-single,pins = < OMAP5_IOPAD(0x00b0, PIN_OUTPUT | MUX_MODE6) /* hsi2_caflag.gpio3_80 */ >; }; - i2c1_pins: pinmux_i2c1_pins { + i2c1_pins: i2c1-pins { pinctrl-single,pins = < OMAP5_IOPAD(0x01f2, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c1_pmic_scl */ OMAP5_IOPAD(0x01f4, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c1_pmic_sda */ >; }; - i2c2_pins: pinmux_i2c2_pins { + i2c2_pins: i2c2-pins { pinctrl-single,pins = < OMAP5_IOPAD(0x01b8, PIN_INPUT | MUX_MODE0) /* i2c2_scl */ OMAP5_IOPAD(0x01ba, PIN_INPUT | MUX_MODE0) /* i2c2_sda */ >; }; - mmc1_pins: pinmux_mmc1_pins { + mmc1_pins: mmc1-pins { pinctrl-single,pins = < OMAP5_IOPAD(0x01e2, PIN_INPUT_PULLUP | MUX_MODE0) /* sdcard_clk */ OMAP5_IOPAD(0x01e4, PIN_INPUT_PULLUP | MUX_MODE0) /* sdcard_cmd */ @@ -228,7 +228,7 @@ >; }; - mmc2_pins: pinmux_mmc2_pins { + mmc2_pins: mmc2-pins { pinctrl-single,pins = < OMAP5_IOPAD(0x0040, PIN_INPUT_PULLUP | MUX_MODE0) /* emmc_clk */ OMAP5_IOPAD(0x0042, PIN_INPUT_PULLUP | MUX_MODE0) /* emmc_cmd */ @@ -243,7 +243,7 @@ >; }; - mmc3_pins: pinmux_mmc3_pins { + mmc3_pins: mmc3-pins { pinctrl-single,pins = < OMAP5_IOPAD(0x01a4, PIN_INPUT_PULLUP | MUX_MODE0) /* wlsdio_clk */ OMAP5_IOPAD(0x01a6, PIN_INPUT_PULLUP | MUX_MODE0) /* wlsdio_cmd */ @@ -254,14 +254,14 @@ >; }; - wlan_gpios_pins: pinmux_wlan_gpios_pins { + wlan_gpios_pins: wlan-gpios-pins { pinctrl-single,pins = < OMAP5_IOPAD(0x019c, PIN_OUTPUT_PULLDOWN | MUX_MODE6) /* abemcpdm_ul_data.gpio4_109 */ OMAP5_IOPAD(0x019e, PIN_OUTPUT_PULLDOWN | MUX_MODE6) /* abemcpdm_dl_data.gpio4_110 */ >; }; - usbhost_pins: pinmux_usbhost_pins { + usbhost_pins: usbhost-pins { pinctrl-single,pins = < OMAP5_IOPAD(0x00c4, PIN_INPUT | MUX_MODE0) /* usbb2_hsic_strobe */ OMAP5_IOPAD(0x00c6, PIN_INPUT | MUX_MODE0) /* usbb2_hsic_data */ @@ -274,7 +274,7 @@ >; }; - dss_hdmi_pins: pinmux_dss_hdmi_pins { + dss_hdmi_pins: dss-hdmi-pins { pinctrl-single,pins = < OMAP5_IOPAD(0x013c, PIN_INPUT | MUX_MODE0) /* hdmi_cec */ OMAP5_IOPAD(0x0140, PIN_INPUT | MUX_MODE0) /* hdmi_ddc_scl */ @@ -282,19 +282,19 @@ >; }; - lcd_pins: pinmux_lcd_pins { + lcd_pins: lcd-pins { pinctrl-single,pins = < OMAP5_IOPAD(0x0172, PIN_OUTPUT_PULLDOWN | MUX_MODE6) /* timer11_pwm_evt.gpio8_227 */ >; }; - hdmi_conn_pins: pinmux_hdmi_conn_pins { + hdmi_conn_pins: hdmi-conn-pins { pinctrl-single,pins = < OMAP5_IOPAD(0x013e, PIN_INPUT | MUX_MODE6) /* hdmi_hpd.gpio7_193 */ >; }; - dss_dpi_pins: pinmux_dss_dpi_pins { + dss_dpi_pins: dss-dpi-pins { pinctrl-single,pins = < OMAP5_IOPAD(0x0104, PIN_OUTPUT | MUX_MODE3) /* rfbi_data15.dispc_data15 */ OMAP5_IOPAD(0x0106, PIN_OUTPUT | MUX_MODE3) /* rfbi_data14.dispc_data14 */ @@ -327,7 +327,7 @@ >; }; - mcspi2_pins: pinmux_mcspi1_pins { + mcspi2_pins: mcspi1-pins { pinctrl-single,pins = < OMAP5_IOPAD(0x00fc, PIN_INPUT | MUX_MODE0) /* mcspi2_clk */ OMAP5_IOPAD(0x00fe, PIN_INPUT | MUX_MODE0) /* mcspi2_simo */ diff --git a/arch/arm/boot/dts/omap5-core-thermal.dtsi b/arch/arm/boot/dts/ti/omap/omap5-core-thermal.dtsi similarity index 100% rename from arch/arm/boot/dts/omap5-core-thermal.dtsi rename to arch/arm/boot/dts/ti/omap/omap5-core-thermal.dtsi diff --git a/arch/arm/boot/dts/omap5-gpu-thermal.dtsi b/arch/arm/boot/dts/ti/omap/omap5-gpu-thermal.dtsi similarity index 100% rename from arch/arm/boot/dts/omap5-gpu-thermal.dtsi rename to arch/arm/boot/dts/ti/omap/omap5-gpu-thermal.dtsi diff --git a/arch/arm/boot/dts/omap5-igep0050.dts b/arch/arm/boot/dts/ti/omap/omap5-igep0050.dts similarity index 97% rename from arch/arm/boot/dts/omap5-igep0050.dts rename to arch/arm/boot/dts/ti/omap/omap5-igep0050.dts index 3851120857d790d7266ecc44695bf0d6c7d71463..d4ca2e3a14dd882f08dbd5c75e836f8b626a339c 100644 --- a/arch/arm/boot/dts/omap5-igep0050.dts +++ b/arch/arm/boot/dts/ti/omap/omap5-igep0050.dts @@ -85,14 +85,14 @@ }; &omap5_pmx_core { - i2c4_pins: pinmux_i2c4_pins { + i2c4_pins: i2c4-pins { pinctrl-single,pins = < OMAP5_IOPAD(0x0f8, PIN_INPUT | MUX_MODE0) /* i2c4_scl */ OMAP5_IOPAD(0x0fa, PIN_INPUT | MUX_MODE0) /* i2c4_sda */ >; }; - power_button_pin: pinctrl_power_button_pin { + power_button_pin: power-button-pins { pinctrl-single,pins = < OMAP5_IOPAD(0x086, PIN_INPUT | MUX_MODE6) /* gpio4_118 */ >; diff --git a/arch/arm/boot/dts/omap5-l4-abe.dtsi b/arch/arm/boot/dts/ti/omap/omap5-l4-abe.dtsi similarity index 100% rename from arch/arm/boot/dts/omap5-l4-abe.dtsi rename to arch/arm/boot/dts/ti/omap/omap5-l4-abe.dtsi diff --git a/arch/arm/boot/dts/omap5-l4.dtsi b/arch/arm/boot/dts/ti/omap/omap5-l4.dtsi similarity index 100% rename from arch/arm/boot/dts/omap5-l4.dtsi rename to arch/arm/boot/dts/ti/omap/omap5-l4.dtsi diff --git a/arch/arm/boot/dts/omap5-sbc-t54.dts b/arch/arm/boot/dts/ti/omap/omap5-sbc-t54.dts similarity index 93% rename from arch/arm/boot/dts/omap5-sbc-t54.dts rename to arch/arm/boot/dts/ti/omap/omap5-sbc-t54.dts index 657df46251c2ecd3a4053389ad33645a38ff6ae5..02716fb796bda154810a0b6767585109f60b9cb4 100644 --- a/arch/arm/boot/dts/omap5-sbc-t54.dts +++ b/arch/arm/boot/dts/ti/omap/omap5-sbc-t54.dts @@ -11,14 +11,14 @@ }; &omap5_pmx_core { - i2c4_pins: pinmux_i2c4_pins { + i2c4_pins: i2c4-pins { pinctrl-single,pins = < OMAP5_IOPAD(0x00f8, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c4_scl */ OMAP5_IOPAD(0x00fa, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c4_sda */ >; }; - mmc1_aux_pins: pinmux_mmc1_aux_pins { + mmc1_aux_pins: mmc1-aux-pins { pinctrl-single,pins = < OMAP5_IOPAD(0x0174, PIN_INPUT_PULLUP | MUX_MODE6) /* timer5_pwm_evt.gpio8_228 */ OMAP5_IOPAD(0x0176, PIN_INPUT_PULLUP | MUX_MODE6) /* timer6_pwm_evt.gpio8_229 */ diff --git a/arch/arm/boot/dts/omap5-uevm.dts b/arch/arm/boot/dts/ti/omap/omap5-uevm.dts similarity index 97% rename from arch/arm/boot/dts/omap5-uevm.dts rename to arch/arm/boot/dts/ti/omap/omap5-uevm.dts index 453da9f18a997489c6c5e95a55b8e725eeadd9ec..933de05d3ca19cdc5e6f1d62ac0f1ffa49e7966c 100644 --- a/arch/arm/boot/dts/omap5-uevm.dts +++ b/arch/arm/boot/dts/ti/omap/omap5-uevm.dts @@ -162,20 +162,20 @@ }; &omap5_pmx_core { - evm_keys_pins: pinmux_evm_keys_gpio_pins { + evm_keys_pins: evm-keys-gpio-pins { pinctrl-single,pins = < OMAP5_IOPAD(0x0b6, PIN_INPUT | MUX_MODE6) /* gpio3_83 */ >; }; - i2c5_pins: pinmux_i2c5_pins { + i2c5_pins: i2c5-pins { pinctrl-single,pins = < OMAP5_IOPAD(0x1c6, PIN_INPUT | MUX_MODE0) /* i2c5_scl */ OMAP5_IOPAD(0x1c8, PIN_INPUT | MUX_MODE0) /* i2c5_sda */ >; }; - mmc1_pins: pinmux_mmc1_pins { + mmc1_pins: mmc1-pins { pinctrl-single,pins = < OMAP5_IOPAD(0x1d4, PIN_INPUT_PULLUP | MUX_MODE6) /* gpio5_152 */ >; diff --git a/arch/arm/boot/dts/omap5.dtsi b/arch/arm/boot/dts/ti/omap/omap5.dtsi similarity index 100% rename from arch/arm/boot/dts/omap5.dtsi rename to arch/arm/boot/dts/ti/omap/omap5.dtsi diff --git a/arch/arm/boot/dts/omap54xx-clocks.dtsi b/arch/arm/boot/dts/ti/omap/omap54xx-clocks.dtsi similarity index 100% rename from arch/arm/boot/dts/omap54xx-clocks.dtsi rename to arch/arm/boot/dts/ti/omap/omap54xx-clocks.dtsi diff --git a/arch/arm/boot/dts/twl4030.dtsi b/arch/arm/boot/dts/ti/omap/twl4030.dtsi similarity index 100% rename from arch/arm/boot/dts/twl4030.dtsi rename to arch/arm/boot/dts/ti/omap/twl4030.dtsi diff --git a/arch/arm/boot/dts/twl4030_omap3.dtsi b/arch/arm/boot/dts/ti/omap/twl4030_omap3.dtsi similarity index 93% rename from arch/arm/boot/dts/twl4030_omap3.dtsi rename to arch/arm/boot/dts/ti/omap/twl4030_omap3.dtsi index 683419d5c0e5c0213d1890daaa8f681b08fc424d..89433f251df039f8df4dd2cc140a043d4ba7ef21 100644 --- a/arch/arm/boot/dts/twl4030_omap3.dtsi +++ b/arch/arm/boot/dts/ti/omap/twl4030_omap3.dtsi @@ -14,7 +14,7 @@ * to the SYS_NIRQ line on OMAP. Therefore, configure the * defaults for the SYS_NIRQ pin here. */ - twl4030_pins: pinmux_twl4030_pins { + twl4030_pins: twl4030-pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x21e0, PIN_INPUT_PULLUP | PIN_OFF_WAKEUPENABLE | MUX_MODE0) /* sys_nirq.sys_nirq */ >; @@ -28,7 +28,7 @@ * sys_nvmode2 signaling. */ &omap3_pmx_wkup { - twl4030_vpins: pinmux_twl4030_vpins { + twl4030_vpins: twl4030-vpins-pins { pinctrl-single,pins = < OMAP3_WKUP_IOPAD(0x2a00, PIN_INPUT | MUX_MODE0) /* i2c4_scl.i2c4_scl */ OMAP3_WKUP_IOPAD(0x2a02, PIN_INPUT | MUX_MODE0) /* i2c4_sda.i2c4_sda */ diff --git a/arch/arm/boot/dts/twl6030.dtsi b/arch/arm/boot/dts/ti/omap/twl6030.dtsi similarity index 100% rename from arch/arm/boot/dts/twl6030.dtsi rename to arch/arm/boot/dts/ti/omap/twl6030.dtsi diff --git a/arch/arm/boot/dts/twl6030_omap4.dtsi b/arch/arm/boot/dts/ti/omap/twl6030_omap4.dtsi similarity index 90% rename from arch/arm/boot/dts/twl6030_omap4.dtsi rename to arch/arm/boot/dts/ti/omap/twl6030_omap4.dtsi index 5730e46b00677aff88dc7065d708e110e42c72d2..64e38c7c8be70bca3f9f51621008271c29e88b66 100644 --- a/arch/arm/boot/dts/twl6030_omap4.dtsi +++ b/arch/arm/boot/dts/ti/omap/twl6030_omap4.dtsi @@ -19,7 +19,7 @@ }; &omap4_pmx_wkup { - twl6030_wkup_pins: pinmux_twl6030_wkup_pins { + twl6030_wkup_pins: twl6030-wkup-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x054, PIN_OUTPUT | MUX_MODE2) /* fref_clk0_out.sys_drm_msecure */ >; @@ -27,7 +27,7 @@ }; &omap4_pmx_core { - twl6030_pins: pinmux_twl6030_pins { + twl6030_pins: twl6030-pins { pinctrl-single,pins = < OMAP4_IOPAD(0x19e, WAKEUP_EN | PIN_INPUT_PULLUP | MUX_MODE0) /* sys_nirq1.sys_nirq1 */ >; diff --git a/arch/arm/boot/dts/unisoc/Makefile b/arch/arm/boot/dts/unisoc/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..dba5cd874ee74f6f38be39120876c10a0b8fa3ba --- /dev/null +++ b/arch/arm/boot/dts/unisoc/Makefile @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 +dtb-$(CONFIG_ARCH_RDA) += \ + rda8810pl-orangepi-2g-iot.dtb \ + rda8810pl-orangepi-i96.dtb diff --git a/arch/arm/boot/dts/rda8810pl-orangepi-2g-iot.dts b/arch/arm/boot/dts/unisoc/rda8810pl-orangepi-2g-iot.dts similarity index 100% rename from arch/arm/boot/dts/rda8810pl-orangepi-2g-iot.dts rename to arch/arm/boot/dts/unisoc/rda8810pl-orangepi-2g-iot.dts diff --git a/arch/arm/boot/dts/rda8810pl-orangepi-i96.dts b/arch/arm/boot/dts/unisoc/rda8810pl-orangepi-i96.dts similarity index 100% rename from arch/arm/boot/dts/rda8810pl-orangepi-i96.dts rename to arch/arm/boot/dts/unisoc/rda8810pl-orangepi-i96.dts diff --git a/arch/arm/boot/dts/rda8810pl.dtsi b/arch/arm/boot/dts/unisoc/rda8810pl.dtsi similarity index 100% rename from arch/arm/boot/dts/rda8810pl.dtsi rename to arch/arm/boot/dts/unisoc/rda8810pl.dtsi diff --git a/arch/arm/boot/dts/vt8500/Makefile b/arch/arm/boot/dts/vt8500/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..255f4403af91c1d6a22416ab694b8eab44bf98a2 --- /dev/null +++ b/arch/arm/boot/dts/vt8500/Makefile @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: GPL-2.0 +dtb-$(CONFIG_ARCH_VT8500) += \ + vt8500-bv07.dtb \ + wm8505-ref.dtb \ + wm8650-mid.dtb \ + wm8750-apc8750.dtb \ + wm8850-w70v2.dtb diff --git a/arch/arm/boot/dts/vt8500-bv07.dts b/arch/arm/boot/dts/vt8500/vt8500-bv07.dts similarity index 100% rename from arch/arm/boot/dts/vt8500-bv07.dts rename to arch/arm/boot/dts/vt8500/vt8500-bv07.dts diff --git a/arch/arm/boot/dts/vt8500.dtsi b/arch/arm/boot/dts/vt8500/vt8500.dtsi similarity index 100% rename from arch/arm/boot/dts/vt8500.dtsi rename to arch/arm/boot/dts/vt8500/vt8500.dtsi diff --git a/arch/arm/boot/dts/wm8505-ref.dts b/arch/arm/boot/dts/vt8500/wm8505-ref.dts similarity index 100% rename from arch/arm/boot/dts/wm8505-ref.dts rename to arch/arm/boot/dts/vt8500/wm8505-ref.dts diff --git a/arch/arm/boot/dts/wm8505.dtsi b/arch/arm/boot/dts/vt8500/wm8505.dtsi similarity index 100% rename from arch/arm/boot/dts/wm8505.dtsi rename to arch/arm/boot/dts/vt8500/wm8505.dtsi diff --git a/arch/arm/boot/dts/wm8650-mid.dts b/arch/arm/boot/dts/vt8500/wm8650-mid.dts similarity index 100% rename from arch/arm/boot/dts/wm8650-mid.dts rename to arch/arm/boot/dts/vt8500/wm8650-mid.dts diff --git a/arch/arm/boot/dts/wm8650.dtsi b/arch/arm/boot/dts/vt8500/wm8650.dtsi similarity index 100% rename from arch/arm/boot/dts/wm8650.dtsi rename to arch/arm/boot/dts/vt8500/wm8650.dtsi diff --git a/arch/arm/boot/dts/wm8750-apc8750.dts b/arch/arm/boot/dts/vt8500/wm8750-apc8750.dts similarity index 100% rename from arch/arm/boot/dts/wm8750-apc8750.dts rename to arch/arm/boot/dts/vt8500/wm8750-apc8750.dts diff --git a/arch/arm/boot/dts/wm8750.dtsi b/arch/arm/boot/dts/vt8500/wm8750.dtsi similarity index 100% rename from arch/arm/boot/dts/wm8750.dtsi rename to arch/arm/boot/dts/vt8500/wm8750.dtsi diff --git a/arch/arm/boot/dts/wm8850-w70v2.dts b/arch/arm/boot/dts/vt8500/wm8850-w70v2.dts similarity index 100% rename from arch/arm/boot/dts/wm8850-w70v2.dts rename to arch/arm/boot/dts/vt8500/wm8850-w70v2.dts diff --git a/arch/arm/boot/dts/wm8850.dtsi b/arch/arm/boot/dts/vt8500/wm8850.dtsi similarity index 100% rename from arch/arm/boot/dts/wm8850.dtsi rename to arch/arm/boot/dts/vt8500/wm8850.dtsi diff --git a/arch/arm/boot/dts/xen/Makefile b/arch/arm/boot/dts/xen/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..26c50f1389529f1075a3154c325c4c309769718b --- /dev/null +++ b/arch/arm/boot/dts/xen/Makefile @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0 +dtb-$(CONFIG_ARCH_VIRT) += \ + xenvm-4.2.dtb diff --git a/arch/arm/boot/dts/xenvm-4.2.dts b/arch/arm/boot/dts/xen/xenvm-4.2.dts similarity index 100% rename from arch/arm/boot/dts/xenvm-4.2.dts rename to arch/arm/boot/dts/xen/xenvm-4.2.dts diff --git a/arch/arm/boot/dts/xilinx/Makefile b/arch/arm/boot/dts/xilinx/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..9233e539b192bcc69391d6fc9cee22981cae02b7 --- /dev/null +++ b/arch/arm/boot/dts/xilinx/Makefile @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: GPL-2.0 +dtb-$(CONFIG_ARCH_ZYNQ) += \ + zynq-cc108.dtb \ + zynq-ebaz4205.dtb \ + zynq-microzed.dtb \ + zynq-parallella.dtb \ + zynq-zc702.dtb \ + zynq-zc706.dtb \ + zynq-zc770-xm010.dtb \ + zynq-zc770-xm011.dtb \ + zynq-zc770-xm012.dtb \ + zynq-zc770-xm013.dtb \ + zynq-zed.dtb \ + zynq-zturn.dtb \ + zynq-zturn-v5.dtb \ + zynq-zybo.dtb \ + zynq-zybo-z7.dtb diff --git a/arch/arm/boot/dts/zynq-7000.dtsi b/arch/arm/boot/dts/xilinx/zynq-7000.dtsi similarity index 99% rename from arch/arm/boot/dts/zynq-7000.dtsi rename to arch/arm/boot/dts/xilinx/zynq-7000.dtsi index cd9931f6bcbdc4b71327a435970533fc752095c9..a7db3f3009f2a3ea12530a4168c040c3b99b5889 100644 --- a/arch/arm/boot/dts/zynq-7000.dtsi +++ b/arch/arm/boot/dts/xilinx/zynq-7000.dtsi @@ -149,6 +149,7 @@ clocks = <&clkc 38>; interrupt-parent = <&intc>; interrupts = <0 25 4>; + clock-frequency = <400000>; reg = <0xe0004000 0x1000>; #address-cells = <1>; #size-cells = <0>; @@ -160,6 +161,7 @@ clocks = <&clkc 39>; interrupt-parent = <&intc>; interrupts = <0 48 4>; + clock-frequency = <400000>; reg = <0xe0005000 0x1000>; #address-cells = <1>; #size-cells = <0>; diff --git a/arch/arm/boot/dts/zynq-cc108.dts b/arch/arm/boot/dts/xilinx/zynq-cc108.dts similarity index 100% rename from arch/arm/boot/dts/zynq-cc108.dts rename to arch/arm/boot/dts/xilinx/zynq-cc108.dts diff --git a/arch/arm/boot/dts/zynq-ebaz4205.dts b/arch/arm/boot/dts/xilinx/zynq-ebaz4205.dts similarity index 100% rename from arch/arm/boot/dts/zynq-ebaz4205.dts rename to arch/arm/boot/dts/xilinx/zynq-ebaz4205.dts diff --git a/arch/arm/boot/dts/zynq-microzed.dts b/arch/arm/boot/dts/xilinx/zynq-microzed.dts similarity index 100% rename from arch/arm/boot/dts/zynq-microzed.dts rename to arch/arm/boot/dts/xilinx/zynq-microzed.dts diff --git a/arch/arm/boot/dts/zynq-parallella.dts b/arch/arm/boot/dts/xilinx/zynq-parallella.dts similarity index 100% rename from arch/arm/boot/dts/zynq-parallella.dts rename to arch/arm/boot/dts/xilinx/zynq-parallella.dts diff --git a/arch/arm/boot/dts/zynq-zc702.dts b/arch/arm/boot/dts/xilinx/zynq-zc702.dts similarity index 93% rename from arch/arm/boot/dts/zynq-zc702.dts rename to arch/arm/boot/dts/xilinx/zynq-zc702.dts index d23201ba8cd7d1282d4b7525558512e87f65751f..6efdbca9d3efb924900b450fa0d95a6ad521fb3a 100644 --- a/arch/arm/boot/dts/zynq-zc702.dts +++ b/arch/arm/boot/dts/xilinx/zynq-zc702.dts @@ -5,6 +5,7 @@ */ /dts-v1/; #include "zynq-7000.dtsi" +#include / { model = "Xilinx ZC702 board"; @@ -106,8 +107,11 @@ &i2c0 { status = "okay"; clock-frequency = <400000>; - pinctrl-names = "default"; + pinctrl-names = "default", "gpio"; pinctrl-0 = <&pinctrl_i2c0_default>; + pinctrl-1 = <&pinctrl_i2c0_gpio>; + scl-gpios = <&gpio0 50 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + sda-gpios = <&gpio0 51 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; i2c-mux@74 { compatible = "nxp,pca9548"; @@ -298,6 +302,19 @@ }; }; + pinctrl_i2c0_gpio: i2c0-gpio { + mux { + groups = "gpio0_50_grp", "gpio0_51_grp"; + function = "gpio0"; + }; + + conf { + groups = "gpio0_50_grp", "gpio0_51_grp"; + slew-rate = <0>; + io-standard = <1>; + }; + }; + pinctrl_sdhci0_default: sdhci0-default { mux { groups = "sdio0_2_grp"; diff --git a/arch/arm/boot/dts/zynq-zc706.dts b/arch/arm/boot/dts/xilinx/zynq-zc706.dts similarity index 100% rename from arch/arm/boot/dts/zynq-zc706.dts rename to arch/arm/boot/dts/xilinx/zynq-zc706.dts diff --git a/arch/arm/boot/dts/zynq-zc770-xm010.dts b/arch/arm/boot/dts/xilinx/zynq-zc770-xm010.dts similarity index 100% rename from arch/arm/boot/dts/zynq-zc770-xm010.dts rename to arch/arm/boot/dts/xilinx/zynq-zc770-xm010.dts diff --git a/arch/arm/boot/dts/zynq-zc770-xm011.dts b/arch/arm/boot/dts/xilinx/zynq-zc770-xm011.dts similarity index 100% rename from arch/arm/boot/dts/zynq-zc770-xm011.dts rename to arch/arm/boot/dts/xilinx/zynq-zc770-xm011.dts diff --git a/arch/arm/boot/dts/zynq-zc770-xm012.dts b/arch/arm/boot/dts/xilinx/zynq-zc770-xm012.dts similarity index 100% rename from arch/arm/boot/dts/zynq-zc770-xm012.dts rename to arch/arm/boot/dts/xilinx/zynq-zc770-xm012.dts diff --git a/arch/arm/boot/dts/zynq-zc770-xm013.dts b/arch/arm/boot/dts/xilinx/zynq-zc770-xm013.dts similarity index 100% rename from arch/arm/boot/dts/zynq-zc770-xm013.dts rename to arch/arm/boot/dts/xilinx/zynq-zc770-xm013.dts diff --git a/arch/arm/boot/dts/zynq-zed.dts b/arch/arm/boot/dts/xilinx/zynq-zed.dts similarity index 100% rename from arch/arm/boot/dts/zynq-zed.dts rename to arch/arm/boot/dts/xilinx/zynq-zed.dts diff --git a/arch/arm/boot/dts/zynq-zturn-common.dtsi b/arch/arm/boot/dts/xilinx/zynq-zturn-common.dtsi similarity index 100% rename from arch/arm/boot/dts/zynq-zturn-common.dtsi rename to arch/arm/boot/dts/xilinx/zynq-zturn-common.dtsi diff --git a/arch/arm/boot/dts/zynq-zturn-v5.dts b/arch/arm/boot/dts/xilinx/zynq-zturn-v5.dts similarity index 100% rename from arch/arm/boot/dts/zynq-zturn-v5.dts rename to arch/arm/boot/dts/xilinx/zynq-zturn-v5.dts diff --git a/arch/arm/boot/dts/zynq-zturn.dts b/arch/arm/boot/dts/xilinx/zynq-zturn.dts similarity index 100% rename from arch/arm/boot/dts/zynq-zturn.dts rename to arch/arm/boot/dts/xilinx/zynq-zturn.dts diff --git a/arch/arm/boot/dts/zynq-zybo-z7.dts b/arch/arm/boot/dts/xilinx/zynq-zybo-z7.dts similarity index 100% rename from arch/arm/boot/dts/zynq-zybo-z7.dts rename to arch/arm/boot/dts/xilinx/zynq-zybo-z7.dts diff --git a/arch/arm/boot/dts/zynq-zybo.dts b/arch/arm/boot/dts/xilinx/zynq-zybo.dts similarity index 100% rename from arch/arm/boot/dts/zynq-zybo.dts rename to arch/arm/boot/dts/xilinx/zynq-zybo.dts diff --git a/arch/arm/common/mcpm_entry.c b/arch/arm/common/mcpm_entry.c index 8a9aeeb504ddedea662fd2da8ef6c4aec715bdd2..e013ff1168d3f1103bbc4512ecf50448149fb339 100644 --- a/arch/arm/common/mcpm_entry.c +++ b/arch/arm/common/mcpm_entry.c @@ -21,7 +21,7 @@ /* * The public API for this code is documented in arch/arm/include/asm/mcpm.h. * For a comprehensive description of the main algorithm used here, please - * see Documentation/arm/cluster-pm-race-avoidance.rst. + * see Documentation/arch/arm/cluster-pm-race-avoidance.rst. */ struct sync_struct mcpm_sync; diff --git a/arch/arm/common/mcpm_head.S b/arch/arm/common/mcpm_head.S index 299495c43dfd189659a629004ab7377943f6b5b3..f590e803ca1125f76a164e14e4fbf8297d49367b 100644 --- a/arch/arm/common/mcpm_head.S +++ b/arch/arm/common/mcpm_head.S @@ -5,7 +5,7 @@ * Created by: Nicolas Pitre, March 2012 * Copyright: (C) 2012-2013 Linaro Limited * - * Refer to Documentation/arm/cluster-pm-race-avoidance.rst + * Refer to Documentation/arch/arm/cluster-pm-race-avoidance.rst * for details of the synchronisation algorithms used here. */ diff --git a/arch/arm/common/sa1111.c b/arch/arm/common/sa1111.c index aad6ba236f0fa0cfe9dbaa8892c85df317addcc9..77c83ba81715a04bc21eb10fe3c7abd8dbb5c09a 100644 --- a/arch/arm/common/sa1111.c +++ b/arch/arm/common/sa1111.c @@ -695,7 +695,7 @@ static u32 sa1111_dma_mask[] = { /* * Configure the SA1111 shared memory controller. */ -void +static void sa1111_configure_smc(struct sa1111 *sachip, int sdram, unsigned int drac, unsigned int cas_latency) { diff --git a/arch/arm/common/sharpsl_param.c b/arch/arm/common/sharpsl_param.c index 6237ede2f0c70010c6bc5fd9c3688365a602a787..1ca26c063f800b0511e9ca25431c45e3c15dfb15 100644 --- a/arch/arm/common/sharpsl_param.c +++ b/arch/arm/common/sharpsl_param.c @@ -11,7 +11,7 @@ #include #include #include -#include +#include /* * Certain hardware parameters determined at the time of device manufacture, diff --git a/arch/arm/common/vlock.S b/arch/arm/common/vlock.S index 1fa09c4697edc604f9300f4c26db4725c0d200c9..c5eaed5a76f067dd81e936ef6388102a5f7494b5 100644 --- a/arch/arm/common/vlock.S +++ b/arch/arm/common/vlock.S @@ -6,7 +6,7 @@ * Copyright: (C) 2012-2013 Linaro Limited * * This algorithm is described in more detail in - * Documentation/arm/vlocks.rst. + * Documentation/arch/arm/vlocks.rst. */ #include diff --git a/arch/arm/configs/am200epdkit_defconfig b/arch/arm/configs/am200epdkit_defconfig index 3f633eaf97700e6adf59868e2a543dae0b661f4a..a25834e4c9015553afc0764959e29c383b59ed17 100644 --- a/arch/arm/configs/am200epdkit_defconfig +++ b/arch/arm/configs/am200epdkit_defconfig @@ -15,7 +15,6 @@ CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y CONFIG_PARTITION_ADVANCED=y # CONFIG_SWAP is not set -CONFIG_SLAB=y # CONFIG_VM_EVENT_COUNTERS is not set CONFIG_NET=y CONFIG_PACKET=m diff --git a/arch/arm/configs/at91_dt_defconfig b/arch/arm/configs/at91_dt_defconfig index 82bcf4dc7f5431da594e4daf755885aa293ae351..8cc602853cc5bd17a0260b7a0bac74a339dcccdd 100644 --- a/arch/arm/configs/at91_dt_defconfig +++ b/arch/arm/configs/at91_dt_defconfig @@ -27,7 +27,6 @@ CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set # CONFIG_SWAP is not set -CONFIG_SLAB=y CONFIG_NET=y CONFIG_PACKET=y CONFIG_UNIX=y diff --git a/arch/arm/configs/dove_defconfig b/arch/arm/configs/dove_defconfig index c8d559f38f48f8856b700f7fd4f2ebb416d3b169..46859e6fee5ba8134e0959d7767fc53cbc62a702 100644 --- a/arch/arm/configs/dove_defconfig +++ b/arch/arm/configs/dove_defconfig @@ -17,7 +17,6 @@ CONFIG_VFP=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y CONFIG_PARTITION_ADVANCED=y -CONFIG_SLAB=y CONFIG_NET=y CONFIG_PACKET=y CONFIG_UNIX=y diff --git a/arch/arm/configs/ep93xx_defconfig b/arch/arm/configs/ep93xx_defconfig index 3154125321c5cddef1530dfa9e857135d4354114..44e89a980d29d187a2d6e2781b8adf016a96a604 100644 --- a/arch/arm/configs/ep93xx_defconfig +++ b/arch/arm/configs/ep93xx_defconfig @@ -24,7 +24,6 @@ CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y CONFIG_MODULE_FORCE_UNLOAD=y CONFIG_PARTITION_ADVANCED=y -CONFIG_SLAB=y CONFIG_NET=y CONFIG_PACKET=y CONFIG_UNIX=y diff --git a/arch/arm/configs/imx_v4_v5_defconfig b/arch/arm/configs/imx_v4_v5_defconfig index c9a602aee7155014c008b254a4e79343c5a8fd1b..ec45e622522545436af34214f5d32f82f4a448f5 100644 --- a/arch/arm/configs/imx_v4_v5_defconfig +++ b/arch/arm/configs/imx_v4_v5_defconfig @@ -26,7 +26,6 @@ CONFIG_KPROBES=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y # CONFIG_SWAP is not set -CONFIG_SLAB=y # CONFIG_COMPAT_BRK is not set CONFIG_NET=y CONFIG_PACKET=y diff --git a/arch/arm/configs/imx_v6_v7_defconfig b/arch/arm/configs/imx_v6_v7_defconfig index 4de293da4789a7196bdfb2085b15b3e23a2e460d..05706696a5fb56c7fef6042975bf6bd53fe00a62 100644 --- a/arch/arm/configs/imx_v6_v7_defconfig +++ b/arch/arm/configs/imx_v6_v7_defconfig @@ -1,4 +1,3 @@ -CONFIG_KERNEL_LZO=y CONFIG_SYSVIPC=y CONFIG_NO_HZ_IDLE=y CONFIG_HIGH_RES_TIMERS=y @@ -80,8 +79,6 @@ CONFIG_PCI_IMX6_HOST=y CONFIG_DEVTMPFS=y CONFIG_DEVTMPFS_MOUNT=y # CONFIG_STANDALONE is not set -CONFIG_FW_LOADER_USER_HELPER=y -CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y CONFIG_IMX_WEIM=y CONFIG_CONNECTOR=y CONFIG_MTD=y diff --git a/arch/arm/configs/lpc32xx_defconfig b/arch/arm/configs/lpc32xx_defconfig index fabb66a53350cee0019af037cd0545f43a043a79..d7df0486850f689808fc615e00c788e48844b645 100644 --- a/arch/arm/configs/lpc32xx_defconfig +++ b/arch/arm/configs/lpc32xx_defconfig @@ -23,7 +23,6 @@ CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y CONFIG_PARTITION_ADVANCED=y # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set -CONFIG_SLAB=y CONFIG_NET=y CONFIG_PACKET=y CONFIG_UNIX=y diff --git a/arch/arm/configs/mmp2_defconfig b/arch/arm/configs/mmp2_defconfig index 7984640e994ee3637ca4c44427195f6075740947..3d1d6f3b592a4565867916e3158321518711cda4 100644 --- a/arch/arm/configs/mmp2_defconfig +++ b/arch/arm/configs/mmp2_defconfig @@ -12,7 +12,6 @@ CONFIG_VFP=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y CONFIG_MODULE_FORCE_UNLOAD=y -CONFIG_SLAB=y CONFIG_NET=y CONFIG_PACKET=y CONFIG_UNIX=y diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig index 871fffe92187bf34cc3ec06f3bba07f77e39a787..f0800f806b5f6237fe0d05945e3b4236d37eea3c 100644 --- a/arch/arm/configs/multi_v7_defconfig +++ b/arch/arm/configs/multi_v7_defconfig @@ -596,7 +596,7 @@ CONFIG_MFD_CPCAP=y CONFIG_MFD_PM8XXX=y CONFIG_MFD_QCOM_RPM=y CONFIG_MFD_SPMI_PMIC=y -CONFIG_MFD_RK808=y +CONFIG_MFD_RK8XX_I2C=y CONFIG_MFD_RN5T618=y CONFIG_MFD_SEC_CORE=y CONFIG_MFD_STMPE=y diff --git a/arch/arm/configs/mvebu_v7_defconfig b/arch/arm/configs/mvebu_v7_defconfig index 68a18264f31b054a5ca2ab90aa1c82af998e0218..2d2a4dc8f37937023524b9203ae004a583afa4ed 100644 --- a/arch/arm/configs/mvebu_v7_defconfig +++ b/arch/arm/configs/mvebu_v7_defconfig @@ -23,7 +23,6 @@ CONFIG_VFP=y CONFIG_NEON=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y -CONFIG_SLAB=y # CONFIG_COMPACTION is not set CONFIG_NET=y CONFIG_PACKET=y diff --git a/arch/arm/configs/nhk8815_defconfig b/arch/arm/configs/nhk8815_defconfig index 4171dafddc0a646e35f969d63828a6e5de4462f0..ea28ed8991b4ee9ff6e6f322a970790525bc782d 100644 --- a/arch/arm/configs/nhk8815_defconfig +++ b/arch/arm/configs/nhk8815_defconfig @@ -16,7 +16,6 @@ CONFIG_AEABI=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y # CONFIG_SWAP is not set -CONFIG_SLAB=y CONFIG_CMA=y CONFIG_NET=y CONFIG_PACKET=y diff --git a/arch/arm/configs/omap2plus_defconfig b/arch/arm/configs/omap2plus_defconfig index c4216c5521000f6f92d09290f8477561393cd2e0..9bd36dd39bd0058dbfc4267652418109608ccba2 100644 --- a/arch/arm/configs/omap2plus_defconfig +++ b/arch/arm/configs/omap2plus_defconfig @@ -62,7 +62,6 @@ CONFIG_MODVERSIONS=y CONFIG_MODULE_SRCVERSION_ALL=y CONFIG_PARTITION_ADVANCED=y CONFIG_BINFMT_MISC=y -CONFIG_SLAB=y CONFIG_CMA=y CONFIG_ZSMALLOC=m CONFIG_NET=y diff --git a/arch/arm/configs/pxa168_defconfig b/arch/arm/configs/pxa168_defconfig index 8422ddc9bab236299a9f0425abcfbefde4851c90..ec3a43f9c85ea82aa4d8a256a375c3ffc6661b85 100644 --- a/arch/arm/configs/pxa168_defconfig +++ b/arch/arm/configs/pxa168_defconfig @@ -12,7 +12,6 @@ CONFIG_FPE_NWFPE=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y CONFIG_MODULE_FORCE_UNLOAD=y -CONFIG_SLAB=y CONFIG_NET=y CONFIG_PACKET=y CONFIG_UNIX=y diff --git a/arch/arm/configs/pxa3xx_defconfig b/arch/arm/configs/pxa3xx_defconfig index d1e83b52e03a54bdafa84c8aff699e315370f791..7f95fa273a7d7fc4cf829fe49fc7a50b42830aab 100644 --- a/arch/arm/configs/pxa3xx_defconfig +++ b/arch/arm/configs/pxa3xx_defconfig @@ -12,7 +12,6 @@ CONFIG_AEABI=y CONFIG_CMDLINE="root=/dev/nfs rootfstype=nfs nfsroot=192.168.1.100:/nfsroot/ ip=192.168.1.101:192.168.1.100::255.255.255.0::eth0:on console=ttyS0,115200 mem=64M debug" CONFIG_FPE_NWFPE=y CONFIG_MODULES=y -CONFIG_SLAB=y CONFIG_NET=y CONFIG_PACKET=y CONFIG_UNIX=y diff --git a/arch/arm/configs/pxa910_defconfig b/arch/arm/configs/pxa910_defconfig index 48e41ca582afe458728242c6a062ad86c657f4e7..958d958377dca5fed01d225e0b2f48891d477cac 100644 --- a/arch/arm/configs/pxa910_defconfig +++ b/arch/arm/configs/pxa910_defconfig @@ -13,7 +13,6 @@ CONFIG_MODULE_FORCE_UNLOAD=y # CONFIG_BLK_DEV_BSG is not set CONFIG_AEABI=y CONFIG_FPE_NWFPE=y -CONFIG_SLAB=y CONFIG_NET=y CONFIG_PACKET=y CONFIG_UNIX=y diff --git a/arch/arm/configs/realview_defconfig b/arch/arm/configs/realview_defconfig index 92f803c2805c3673ca0dd87ea4c8289a5cd832ba..a221a99f6472054036f9b9899c521ca35ba0e5b9 100644 --- a/arch/arm/configs/realview_defconfig +++ b/arch/arm/configs/realview_defconfig @@ -20,7 +20,6 @@ CONFIG_VFP=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y # CONFIG_SWAP is not set -CONFIG_SLAB=y CONFIG_CMA=y CONFIG_NET=y CONFIG_PACKET=y diff --git a/arch/arm/configs/rpc_defconfig b/arch/arm/configs/rpc_defconfig index 210974364d619852ca410b866f451c219159457d..65a3fded55be002f681b0a68a868191f8fa2835f 100644 --- a/arch/arm/configs/rpc_defconfig +++ b/arch/arm/configs/rpc_defconfig @@ -11,7 +11,6 @@ CONFIG_CPU_SA110=y CONFIG_FPE_NWFPE=y CONFIG_PARTITION_ADVANCED=y CONFIG_BSD_DISKLABEL=y -CONFIG_SLAB=y CONFIG_NET=y CONFIG_PACKET=y CONFIG_UNIX=y diff --git a/arch/arm/configs/sama5_defconfig b/arch/arm/configs/sama5_defconfig index c6aff6fb084d7a2d6eee9dc1bee6acbf12b587e5..56ee511210de9dd4240874bbfb0688ba870d860b 100644 --- a/arch/arm/configs/sama5_defconfig +++ b/arch/arm/configs/sama5_defconfig @@ -26,7 +26,6 @@ CONFIG_MODULE_UNLOAD=y CONFIG_MODULE_FORCE_UNLOAD=y # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set # CONFIG_SWAP is not set -CONFIG_SLAB=y CONFIG_NET=y CONFIG_PACKET=y CONFIG_UNIX=y diff --git a/arch/arm/configs/sama7_defconfig b/arch/arm/configs/sama7_defconfig index 9541120414034ebba5a4b59b6146d0968671bfdd..a89767c89d179e59bda13f1daf49690ad5e42551 100644 --- a/arch/arm/configs/sama7_defconfig +++ b/arch/arm/configs/sama7_defconfig @@ -41,7 +41,6 @@ CONFIG_PARTITION_ADVANCED=y # CONFIG_EFI_PARTITION is not set # CONFIG_COREDUMP is not set # CONFIG_SWAP is not set -CONFIG_SLAB=y # CONFIG_COMPACTION is not set CONFIG_CMA=y # CONFIG_VM_EVENT_COUNTERS is not set diff --git a/arch/arm/configs/shmobile_defconfig b/arch/arm/configs/shmobile_defconfig index 0b21c0a4758286efe9f65bbd54ed51f7e8b40ab9..22205ef0f3768420b868c1a924b35b62db35d736 100644 --- a/arch/arm/configs/shmobile_defconfig +++ b/arch/arm/configs/shmobile_defconfig @@ -24,7 +24,6 @@ CONFIG_CPUFREQ_DT=y CONFIG_VFP=y CONFIG_NEON=y # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set -CONFIG_SLAB=y CONFIG_CMA=y CONFIG_NET=y CONFIG_PACKET=y @@ -36,8 +35,8 @@ CONFIG_NET_DSA=y CONFIG_CAN=y CONFIG_PCI=y CONFIG_PCI_MSI=y -CONFIG_PCI_RCAR_GEN2=y CONFIG_PCIE_RCAR_HOST=y +CONFIG_PCI_RCAR_GEN2=y CONFIG_DEVTMPFS=y CONFIG_DEVTMPFS_MOUNT=y CONFIG_MTD=y @@ -76,7 +75,6 @@ CONFIG_SERIAL_8250=y # CONFIG_SERIAL_8250_16550A_VARIANTS is not set CONFIG_SERIAL_8250_CONSOLE=y # CONFIG_SERIAL_8250_PCI is not set -# CONFIG_SERIAL_8250_PCI1XXXX is not set CONFIG_SERIAL_8250_DW=y CONFIG_SERIAL_8250_EM=y # CONFIG_SERIAL_8250_PERICOM is not set diff --git a/arch/arm/configs/sp7021_defconfig b/arch/arm/configs/sp7021_defconfig index c6448ac860b692a1b97ef47d9683a03768c05160..ec723401b4405141a40c8aab666dd80ed5bc5a36 100644 --- a/arch/arm/configs/sp7021_defconfig +++ b/arch/arm/configs/sp7021_defconfig @@ -24,7 +24,6 @@ CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y CONFIG_MODVERSIONS=y # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set -CONFIG_SLAB=y CONFIG_UEVENT_HELPER=y CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" CONFIG_DEVTMPFS=y diff --git a/arch/arm/configs/tegra_defconfig b/arch/arm/configs/tegra_defconfig index f32047e24b633eef6dfd26e32a544142ccce42da..3c6af935e9328a2ddcfead451f9de556f28ac161 100644 --- a/arch/arm/configs/tegra_defconfig +++ b/arch/arm/configs/tegra_defconfig @@ -32,7 +32,6 @@ CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y CONFIG_MODULE_FORCE_UNLOAD=y CONFIG_PARTITION_ADVANCED=y -CONFIG_SLAB=y CONFIG_CMA=y CONFIG_NET=y CONFIG_PACKET=y diff --git a/arch/arm/configs/versatile_defconfig b/arch/arm/configs/versatile_defconfig index 67e3f9138306600b1bab0cb2be34a5671eb6ff23..849118cbbb441d4e40700cd47a9d19cbc0af0ce3 100644 --- a/arch/arm/configs/versatile_defconfig +++ b/arch/arm/configs/versatile_defconfig @@ -14,7 +14,6 @@ CONFIG_VFP=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y CONFIG_PARTITION_ADVANCED=y -CONFIG_SLAB=y CONFIG_CMA=y CONFIG_NET=y CONFIG_PACKET=y diff --git a/arch/arm/crypto/sha1_neon_glue.c b/arch/arm/crypto/sha1_neon_glue.c index cfe36ae0f3f596fd7e34be2b2d61a61589933849..9c70b87e69f7083118a0644e65d9568d9e3d5141 100644 --- a/arch/arm/crypto/sha1_neon_glue.c +++ b/arch/arm/crypto/sha1_neon_glue.c @@ -26,8 +26,8 @@ #include "sha1.h" -asmlinkage void sha1_transform_neon(void *state_h, const char *data, - unsigned int rounds); +asmlinkage void sha1_transform_neon(struct sha1_state *state_h, + const u8 *data, int rounds); static int sha1_neon_update(struct shash_desc *desc, const u8 *data, unsigned int len) @@ -39,8 +39,7 @@ static int sha1_neon_update(struct shash_desc *desc, const u8 *data, return sha1_update_arm(desc, data, len); kernel_neon_begin(); - sha1_base_do_update(desc, data, len, - (sha1_block_fn *)sha1_transform_neon); + sha1_base_do_update(desc, data, len, sha1_transform_neon); kernel_neon_end(); return 0; @@ -54,9 +53,8 @@ static int sha1_neon_finup(struct shash_desc *desc, const u8 *data, kernel_neon_begin(); if (len) - sha1_base_do_update(desc, data, len, - (sha1_block_fn *)sha1_transform_neon); - sha1_base_do_finalize(desc, (sha1_block_fn *)sha1_transform_neon); + sha1_base_do_update(desc, data, len, sha1_transform_neon); + sha1_base_do_finalize(desc, sha1_transform_neon); kernel_neon_end(); return sha1_base_finish(desc, out); diff --git a/arch/arm/crypto/sha256_neon_glue.c b/arch/arm/crypto/sha256_neon_glue.c index 701706262ef34e831ff25ad8bf84b739ff35f6a1..ccdcfff71910d864d261d6ab6bb723821abd3017 100644 --- a/arch/arm/crypto/sha256_neon_glue.c +++ b/arch/arm/crypto/sha256_neon_glue.c @@ -21,8 +21,8 @@ #include "sha256_glue.h" -asmlinkage void sha256_block_data_order_neon(u32 *digest, const void *data, - unsigned int num_blks); +asmlinkage void sha256_block_data_order_neon(struct sha256_state *digest, + const u8 *data, int num_blks); static int crypto_sha256_neon_update(struct shash_desc *desc, const u8 *data, unsigned int len) @@ -34,8 +34,7 @@ static int crypto_sha256_neon_update(struct shash_desc *desc, const u8 *data, return crypto_sha256_arm_update(desc, data, len); kernel_neon_begin(); - sha256_base_do_update(desc, data, len, - (sha256_block_fn *)sha256_block_data_order_neon); + sha256_base_do_update(desc, data, len, sha256_block_data_order_neon); kernel_neon_end(); return 0; @@ -50,9 +49,8 @@ static int crypto_sha256_neon_finup(struct shash_desc *desc, const u8 *data, kernel_neon_begin(); if (len) sha256_base_do_update(desc, data, len, - (sha256_block_fn *)sha256_block_data_order_neon); - sha256_base_do_finalize(desc, - (sha256_block_fn *)sha256_block_data_order_neon); + sha256_block_data_order_neon); + sha256_base_do_finalize(desc, sha256_block_data_order_neon); kernel_neon_end(); return sha256_base_finish(desc, out); diff --git a/arch/arm/crypto/sha512-neon-glue.c b/arch/arm/crypto/sha512-neon-glue.c index c879ad32db51f27e27bc57d4550b269445b205fe..c6e58fe475acf94f32b96698f0e7ca0567304491 100644 --- a/arch/arm/crypto/sha512-neon-glue.c +++ b/arch/arm/crypto/sha512-neon-glue.c @@ -20,8 +20,8 @@ MODULE_ALIAS_CRYPTO("sha384-neon"); MODULE_ALIAS_CRYPTO("sha512-neon"); -asmlinkage void sha512_block_data_order_neon(u64 *state, u8 const *src, - int blocks); +asmlinkage void sha512_block_data_order_neon(struct sha512_state *state, + const u8 *src, int blocks); static int sha512_neon_update(struct shash_desc *desc, const u8 *data, unsigned int len) @@ -33,8 +33,7 @@ static int sha512_neon_update(struct shash_desc *desc, const u8 *data, return sha512_arm_update(desc, data, len); kernel_neon_begin(); - sha512_base_do_update(desc, data, len, - (sha512_block_fn *)sha512_block_data_order_neon); + sha512_base_do_update(desc, data, len, sha512_block_data_order_neon); kernel_neon_end(); return 0; @@ -49,9 +48,8 @@ static int sha512_neon_finup(struct shash_desc *desc, const u8 *data, kernel_neon_begin(); if (len) sha512_base_do_update(desc, data, len, - (sha512_block_fn *)sha512_block_data_order_neon); - sha512_base_do_finalize(desc, - (sha512_block_fn *)sha512_block_data_order_neon); + sha512_block_data_order_neon); + sha512_base_do_finalize(desc, sha512_block_data_order_neon); kernel_neon_end(); return sha512_base_finish(desc, out); diff --git a/arch/arm/include/asm/arm_pmuv3.h b/arch/arm/include/asm/arm_pmuv3.h index f4db3e75d75f024ef41943729e4558d6eb3bf604..f3cd04ff022df106f17ce676ede60d647cb3cf20 100644 --- a/arch/arm/include/asm/arm_pmuv3.h +++ b/arch/arm/include/asm/arm_pmuv3.h @@ -222,6 +222,11 @@ static inline bool kvm_pmu_counter_deferred(struct perf_event_attr *attr) return false; } +static inline bool kvm_set_pmuserenr(u64 val) +{ + return false; +} + /* PMU Version in DFR Register */ #define ARMV8_PMU_DFR_VER_NI 0 #define ARMV8_PMU_DFR_VER_V3P4 0x5 diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h index 505a306e0271a9c44b7f78db3f653372e4133523..aebe2c8f6a686cc591f4dc8c19582e7701251051 100644 --- a/arch/arm/include/asm/assembler.h +++ b/arch/arm/include/asm/assembler.h @@ -394,6 +394,23 @@ ALT_UP_B(.L0_\@) #endif .endm +/* + * Raw SMP data memory barrier + */ + .macro __smp_dmb mode +#if __LINUX_ARM_ARCH__ >= 7 + .ifeqs "\mode","arm" + dmb ish + .else + W(dmb) ish + .endif +#elif __LINUX_ARM_ARCH__ == 6 + mcr p15, 0, r0, c7, c10, 5 @ dmb +#else + .error "Incompatible SMP platform" +#endif + .endm + #if defined(CONFIG_CPU_V7M) /* * setmode is used to assert to be in svc mode during boot. For v7-M diff --git a/arch/arm/include/asm/atomic.h b/arch/arm/include/asm/atomic.h index db8512d9a918de2fd00cd1313a4f3a3761c16144..f0e3b01afa746d0206fbbb3d5d6102e8c6a337c8 100644 --- a/arch/arm/include/asm/atomic.h +++ b/arch/arm/include/asm/atomic.h @@ -197,6 +197,16 @@ static inline int arch_atomic_fetch_##op(int i, atomic_t *v) \ return val; \ } +#define arch_atomic_add_return arch_atomic_add_return +#define arch_atomic_sub_return arch_atomic_sub_return +#define arch_atomic_fetch_add arch_atomic_fetch_add +#define arch_atomic_fetch_sub arch_atomic_fetch_sub + +#define arch_atomic_fetch_and arch_atomic_fetch_and +#define arch_atomic_fetch_andnot arch_atomic_fetch_andnot +#define arch_atomic_fetch_or arch_atomic_fetch_or +#define arch_atomic_fetch_xor arch_atomic_fetch_xor + static inline int arch_atomic_cmpxchg(atomic_t *v, int old, int new) { int ret; @@ -210,8 +220,7 @@ static inline int arch_atomic_cmpxchg(atomic_t *v, int old, int new) return ret; } - -#define arch_atomic_fetch_andnot arch_atomic_fetch_andnot +#define arch_atomic_cmpxchg arch_atomic_cmpxchg #endif /* __LINUX_ARM_ARCH__ */ @@ -240,8 +249,6 @@ ATOMIC_OPS(xor, ^=, eor) #undef ATOMIC_OP_RETURN #undef ATOMIC_OP -#define arch_atomic_xchg(v, new) (arch_xchg(&((v)->counter), new)) - #ifndef CONFIG_GENERIC_ATOMIC64 typedef struct { s64 counter; diff --git a/arch/arm/include/asm/bugs.h b/arch/arm/include/asm/bugs.h index 97a312ba08401f9a9b88d6037ca33d2d404aa39b..fe385551edeca4af00f8673e803dcc3f1f2d38e7 100644 --- a/arch/arm/include/asm/bugs.h +++ b/arch/arm/include/asm/bugs.h @@ -1,7 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * arch/arm/include/asm/bugs.h - * * Copyright (C) 1995-2003 Russell King */ #ifndef __ASM_BUGS_H @@ -10,10 +8,8 @@ extern void check_writebuffer_bugs(void); #ifdef CONFIG_MMU -extern void check_bugs(void); extern void check_other_bugs(void); #else -#define check_bugs() do { } while (0) #define check_other_bugs() do { } while (0) #endif diff --git a/arch/arm/include/asm/delay.h b/arch/arm/include/asm/delay.h index 4f80b72372b4160594366199b53f5261fc6d3f14..1d069e558d8debcbb261f490e78edc1726e5f3d4 100644 --- a/arch/arm/include/asm/delay.h +++ b/arch/arm/include/asm/delay.h @@ -7,7 +7,7 @@ #ifndef __ASM_ARM_DELAY_H #define __ASM_ARM_DELAY_H -#include +#include #include /* HZ */ /* diff --git a/arch/arm/include/asm/ftrace.h b/arch/arm/include/asm/ftrace.h index 7e9251ca29fe7696c6f11497a3ced2d805220730..5be3ddc96a503a580bfdce4b2300999aebeb8e72 100644 --- a/arch/arm/include/asm/ftrace.h +++ b/arch/arm/include/asm/ftrace.h @@ -75,6 +75,10 @@ static inline bool arch_syscall_match_sym_name(const char *sym, return !strcasecmp(sym, name); } +void prepare_ftrace_return(unsigned long *parent, unsigned long self, + unsigned long frame_pointer, + unsigned long stack_pointer); + #endif /* ifndef __ASSEMBLY__ */ #endif /* _ASM_ARM_FTRACE */ diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h index 7fcdc785366c54ce0720c9e7271dbb15edb529da..56b08ed6cc3bcb30f472a09d13f4952f960dc013 100644 --- a/arch/arm/include/asm/io.h +++ b/arch/arm/include/asm/io.h @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include /* diff --git a/arch/arm/include/asm/irq.h b/arch/arm/include/asm/irq.h index a7c2337b0c7d66ff7f7709ec684150b10243d3ab..18605f1b3580715a7e90cffdab75e454eb972b29 100644 --- a/arch/arm/include/asm/irq.h +++ b/arch/arm/include/asm/irq.h @@ -27,7 +27,6 @@ struct irqaction; struct pt_regs; void handle_IRQ(unsigned int, struct pt_regs *); -void init_IRQ(void); #ifdef CONFIG_SMP #include diff --git a/arch/arm/include/asm/mach/arch.h b/arch/arm/include/asm/mach/arch.h index 9349e7a82c9c4e249725178a1c67b18a453a8f00..2b18a258204d734cf060bd10dd2633caa6f96c78 100644 --- a/arch/arm/include/asm/mach/arch.h +++ b/arch/arm/include/asm/mach/arch.h @@ -56,7 +56,6 @@ struct machine_desc { void (*init_time)(void); void (*init_machine)(void); void (*init_late)(void); - void (*handle_irq)(struct pt_regs *); void (*restart)(enum reboot_mode, const char *); }; diff --git a/arch/arm/include/asm/memory.h b/arch/arm/include/asm/memory.h index 62e9df024445724ab6a5e0cc83aba4628fd3fbea..ef2aa79ece5ad53472d64961a4c5b28eb4a9f84a 100644 --- a/arch/arm/include/asm/memory.h +++ b/arch/arm/include/asm/memory.h @@ -5,11 +5,16 @@ * Copyright (C) 2000-2002 Russell King * modification for nommu, Hyok S. Choi, 2004 * - * Note: this file should not be included by non-asm/.h files + * Note: this file should not be included explicitly, include + * to get access to these definitions. */ #ifndef __ASM_ARM_MEMORY_H #define __ASM_ARM_MEMORY_H +#ifndef _ASMARM_PAGE_H +#error "Do not include directly" +#endif + #include #include #include @@ -288,10 +293,12 @@ static inline unsigned long __phys_to_virt(phys_addr_t x) #endif -#define virt_to_pfn(kaddr) \ - ((((unsigned long)(kaddr) - PAGE_OFFSET) >> PAGE_SHIFT) + \ - PHYS_PFN_OFFSET) - +static inline unsigned long virt_to_pfn(const void *p) +{ + unsigned long kaddr = (unsigned long)p; + return (((kaddr - PAGE_OFFSET) >> PAGE_SHIFT) + + PHYS_PFN_OFFSET); +} #define __pa_symbol_nodebug(x) __virt_to_phys_nodebug((x)) #ifdef CONFIG_DEBUG_VIRTUAL diff --git a/arch/arm/include/asm/page.h b/arch/arm/include/asm/page.h index 74bb5947b387ab1491b37296676f58ee4d3b2404..119aa85d1feb4d24726f3e3619c0f46c98b07f80 100644 --- a/arch/arm/include/asm/page.h +++ b/arch/arm/include/asm/page.h @@ -113,6 +113,28 @@ struct cpu_user_fns { unsigned long vaddr, struct vm_area_struct *vma); }; +void fa_copy_user_highpage(struct page *to, struct page *from, + unsigned long vaddr, struct vm_area_struct *vma); +void fa_clear_user_highpage(struct page *page, unsigned long vaddr); +void feroceon_copy_user_highpage(struct page *to, struct page *from, + unsigned long vaddr, struct vm_area_struct *vma); +void feroceon_clear_user_highpage(struct page *page, unsigned long vaddr); +void v4_mc_copy_user_highpage(struct page *to, struct page *from, + unsigned long vaddr, struct vm_area_struct *vma); +void v4_mc_clear_user_highpage(struct page *page, unsigned long vaddr); +void v4wb_copy_user_highpage(struct page *to, struct page *from, + unsigned long vaddr, struct vm_area_struct *vma); +void v4wb_clear_user_highpage(struct page *page, unsigned long vaddr); +void v4wt_copy_user_highpage(struct page *to, struct page *from, + unsigned long vaddr, struct vm_area_struct *vma); +void v4wt_clear_user_highpage(struct page *page, unsigned long vaddr); +void xsc3_mc_copy_user_highpage(struct page *to, struct page *from, + unsigned long vaddr, struct vm_area_struct *vma); +void xsc3_mc_clear_user_highpage(struct page *page, unsigned long vaddr); +void xscale_mc_copy_user_highpage(struct page *to, struct page *from, + unsigned long vaddr, struct vm_area_struct *vma); +void xscale_mc_clear_user_highpage(struct page *page, unsigned long vaddr); + #ifdef MULTI_USER extern struct cpu_user_fns cpu_user; @@ -161,10 +183,10 @@ extern int pfn_valid(unsigned long); #define pfn_valid pfn_valid #endif -#include - #endif /* !__ASSEMBLY__ */ +#include + #define VM_DATA_DEFAULT_FLAGS VM_DATA_FLAGS_TSK_EXEC #include diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h index a58ccbb406adf23722e5ae430009745f0338c49a..34662a9d4cabf78270734a91337c9b02de8ea09d 100644 --- a/arch/arm/include/asm/pgtable.h +++ b/arch/arm/include/asm/pgtable.h @@ -27,7 +27,7 @@ extern struct page *empty_zero_page; #else #include -#include +#include #include diff --git a/arch/arm/include/asm/proc-fns.h b/arch/arm/include/asm/proc-fns.h index c82f7a29ec4a6ebab3f1203028bea92765b09e21..280396483f5dd845fc25b3a772062ab37000faef 100644 --- a/arch/arm/include/asm/proc-fns.h +++ b/arch/arm/include/asm/proc-fns.h @@ -147,8 +147,6 @@ static inline void init_proc_vtable(const struct processor *p) extern void cpu_resume(void); -#include - #ifdef CONFIG_MMU #define cpu_switch_mm(pgd,mm) cpu_do_switch_mm(virt_to_phys(pgd),mm) diff --git a/arch/arm/include/asm/ptrace.h b/arch/arm/include/asm/ptrace.h index 483b8ddfcb82cdb89d3c26ed6da8259f426b1cd5..7f44e88d1f25bcc57891701af2339f57054b3f14 100644 --- a/arch/arm/include/asm/ptrace.h +++ b/arch/arm/include/asm/ptrace.h @@ -193,5 +193,8 @@ static inline unsigned long it_advance(unsigned long cpsr) return cpsr; } +int syscall_trace_enter(struct pt_regs *regs); +void syscall_trace_exit(struct pt_regs *regs); + #endif /* __ASSEMBLY__ */ #endif diff --git a/arch/arm/include/asm/setup.h b/arch/arm/include/asm/setup.h index ba0872a8dcdabda567c68ef9c28e2d689c8959b7..546af8b1e3f6532dcacd694732a3827fbdf8edfd 100644 --- a/arch/arm/include/asm/setup.h +++ b/arch/arm/include/asm/setup.h @@ -5,7 +5,7 @@ * Copyright (C) 1997-1999 Russell King * * Structure passed to kernel to tell it about the - * hardware it's running on. See Documentation/arm/setup.rst + * hardware it's running on. See Documentation/arch/arm/setup.rst * for more info. */ #ifndef __ASMARM_SETUP_H @@ -28,4 +28,11 @@ extern void save_atags(const struct tag *tags); static inline void save_atags(const struct tag *tags) { } #endif +struct machine_desc; +void init_default_cache_policy(unsigned long); +void paging_init(const struct machine_desc *desc); +void early_mm_init(const struct machine_desc *); +void adjust_lowmem_bounds(void); +void setup_dma_zone(const struct machine_desc *desc); + #endif diff --git a/arch/arm/include/asm/signal.h b/arch/arm/include/asm/signal.h index 430be7774402ef10b0b34c7f8a28c13bcfddc85c..8b84092d151800cb4076672d1c31f0a83777d0d8 100644 --- a/arch/arm/include/asm/signal.h +++ b/arch/arm/include/asm/signal.h @@ -22,4 +22,9 @@ typedef struct { #define __ARCH_HAS_SA_RESTORER #include + +void do_rseq_syscall(struct pt_regs *regs); +int do_work_pending(struct pt_regs *regs, unsigned int thread_flags, + int syscall); + #endif diff --git a/arch/arm/include/asm/smp.h b/arch/arm/include/asm/smp.h index 7c1c90d9f582759c8f4d152a144996ab7379743b..8c05a7f374d8b3d69d51e0d8dc11ceaea5611069 100644 --- a/arch/arm/include/asm/smp.h +++ b/arch/arm/include/asm/smp.h @@ -64,7 +64,7 @@ extern void secondary_startup_arm(void); extern int __cpu_disable(void); -extern void __cpu_die(unsigned int cpu); +static inline void __cpu_die(unsigned int cpu) { } extern void arch_send_call_function_single_ipi(int cpu); extern void arch_send_call_function_ipi_mask(const struct cpumask *mask); diff --git a/arch/arm/include/asm/sparsemem.h b/arch/arm/include/asm/sparsemem.h index d362233856a5baaa4a3f2b063bd529141917802b..421e3415338ac26c7a4cf81acc34299c4f772951 100644 --- a/arch/arm/include/asm/sparsemem.h +++ b/arch/arm/include/asm/sparsemem.h @@ -2,7 +2,7 @@ #ifndef ASMARM_SPARSEMEM_H #define ASMARM_SPARSEMEM_H -#include +#include /* * Two definitions are required for sparsemem: diff --git a/arch/arm/include/asm/spectre.h b/arch/arm/include/asm/spectre.h index 85f9e538fb325730613f78419f52826a68b8d76c..d9c28b3b6b62ec68c5d73db224ea849a525fab3c 100644 --- a/arch/arm/include/asm/spectre.h +++ b/arch/arm/include/asm/spectre.h @@ -35,4 +35,8 @@ static inline void spectre_v2_update_state(unsigned int state, int spectre_bhb_update_vectors(unsigned int method); +void cpu_v7_ca8_ibe(void); +void cpu_v7_ca15_ibe(void); +void cpu_v7_bugs_init(void); + #endif diff --git a/arch/arm/include/asm/suspend.h b/arch/arm/include/asm/suspend.h index 506314265c6f1a24e50641dbbea1d41367d322d5..be81b9ca2ea1a9d0a1815ae2a855e946455c8113 100644 --- a/arch/arm/include/asm/suspend.h +++ b/arch/arm/include/asm/suspend.h @@ -13,5 +13,6 @@ extern void cpu_resume(void); extern void cpu_resume_no_hyp(void); extern void cpu_resume_arm(void); extern int cpu_suspend(unsigned long, int (*)(unsigned long)); +extern void __cpu_suspend_save(u32 *ptr, u32 ptrsz, u32 sp, u32 *save_ptr); #endif diff --git a/arch/arm/include/asm/sync_bitops.h b/arch/arm/include/asm/sync_bitops.h index 6f5d627c44a3cbbefaeee6fca2b7f409f645b3fb..f46b3c570f92e296690b01dd0f259ff15dac4afc 100644 --- a/arch/arm/include/asm/sync_bitops.h +++ b/arch/arm/include/asm/sync_bitops.h @@ -14,14 +14,35 @@ * ops which are SMP safe even on a UP kernel. */ +/* + * Unordered + */ + #define sync_set_bit(nr, p) _set_bit(nr, p) #define sync_clear_bit(nr, p) _clear_bit(nr, p) #define sync_change_bit(nr, p) _change_bit(nr, p) -#define sync_test_and_set_bit(nr, p) _test_and_set_bit(nr, p) -#define sync_test_and_clear_bit(nr, p) _test_and_clear_bit(nr, p) -#define sync_test_and_change_bit(nr, p) _test_and_change_bit(nr, p) #define sync_test_bit(nr, addr) test_bit(nr, addr) -#define arch_sync_cmpxchg arch_cmpxchg +/* + * Fully ordered + */ + +int _sync_test_and_set_bit(int nr, volatile unsigned long * p); +#define sync_test_and_set_bit(nr, p) _sync_test_and_set_bit(nr, p) + +int _sync_test_and_clear_bit(int nr, volatile unsigned long * p); +#define sync_test_and_clear_bit(nr, p) _sync_test_and_clear_bit(nr, p) + +int _sync_test_and_change_bit(int nr, volatile unsigned long * p); +#define sync_test_and_change_bit(nr, p) _sync_test_and_change_bit(nr, p) + +#define arch_sync_cmpxchg(ptr, old, new) \ +({ \ + __typeof__(*(ptr)) __ret; \ + __smp_mb__before_atomic(); \ + __ret = arch_cmpxchg_relaxed((ptr), (old), (new)); \ + __smp_mb__after_atomic(); \ + __ret; \ +}) #endif diff --git a/arch/arm/include/asm/syscalls.h b/arch/arm/include/asm/syscalls.h new file mode 100644 index 0000000000000000000000000000000000000000..5912e7cffa6a27c8d5970cf57fe40c205bad8d9d --- /dev/null +++ b/arch/arm/include/asm/syscalls.h @@ -0,0 +1,51 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +#ifndef __ASM_SYSCALLS_H +#define __ASM_SYSCALLS_H + +#include +#include + +struct pt_regs; +asmlinkage int sys_sigreturn(struct pt_regs *regs); +asmlinkage int sys_rt_sigreturn(struct pt_regs *regs); +asmlinkage long sys_arm_fadvise64_64(int fd, int advice, + loff_t offset, loff_t len); + +struct oldabi_stat64; +asmlinkage long sys_oabi_stat64(const char __user * filename, + struct oldabi_stat64 __user * statbuf); +asmlinkage long sys_oabi_lstat64(const char __user * filename, + struct oldabi_stat64 __user * statbuf); +asmlinkage long sys_oabi_fstat64(unsigned long fd, + struct oldabi_stat64 __user * statbuf); +asmlinkage long sys_oabi_fstatat64(int dfd, + const char __user *filename, + struct oldabi_stat64 __user *statbuf, + int flag); +asmlinkage long sys_oabi_fcntl64(unsigned int fd, unsigned int cmd, + unsigned long arg); +struct oabi_epoll_event; +asmlinkage long sys_oabi_epoll_ctl(int epfd, int op, int fd, + struct oabi_epoll_event __user *event); +struct oabi_sembuf; +struct old_timespec32; +asmlinkage long sys_oabi_semtimedop(int semid, + struct oabi_sembuf __user *tsops, + unsigned nsops, + const struct old_timespec32 __user *timeout); +asmlinkage long sys_oabi_semop(int semid, struct oabi_sembuf __user *tsops, + unsigned nsops); +asmlinkage int sys_oabi_ipc(uint call, int first, int second, int third, + void __user *ptr, long fifth); +struct sockaddr; +asmlinkage long sys_oabi_bind(int fd, struct sockaddr __user *addr, int addrlen); +asmlinkage long sys_oabi_connect(int fd, struct sockaddr __user *addr, int addrlen); +asmlinkage long sys_oabi_sendto(int fd, void __user *buff, + size_t len, unsigned flags, + struct sockaddr __user *addr, + int addrlen); +struct user_msghdr; +asmlinkage long sys_oabi_sendmsg(int fd, struct user_msghdr __user *msg, unsigned flags); +asmlinkage long sys_oabi_socketcall(int call, unsigned long __user *args); + +#endif diff --git a/arch/arm/include/asm/tcm.h b/arch/arm/include/asm/tcm.h index d8bd8a4b0eded44a142734ce8276d5db2f0c41d6..e1f7dca86a22d43bc0ccc9d823409984aba696bc 100644 --- a/arch/arm/include/asm/tcm.h +++ b/arch/arm/include/asm/tcm.h @@ -9,9 +9,7 @@ #ifndef __ASMARM_TCM_H #define __ASMARM_TCM_H -#ifndef CONFIG_HAVE_TCM -#error "You should not be including tcm.h unless you have a TCM!" -#endif +#ifdef CONFIG_HAVE_TCM #include @@ -29,4 +27,11 @@ void tcm_free(void *addr, size_t len); bool tcm_dtcm_present(void); bool tcm_itcm_present(void); +void __init tcm_init(void); +#else +/* No TCM support, just blank inlines to be optimized out */ +static inline void tcm_init(void) +{ +} +#endif #endif diff --git a/arch/arm/include/asm/traps.h b/arch/arm/include/asm/traps.h index 987fefb0a4dbc452fda484512cedf6818838d965..0aaefe3e17008e1d468d0bad750bf9bebdcaef7b 100644 --- a/arch/arm/include/asm/traps.h +++ b/arch/arm/include/asm/traps.h @@ -35,4 +35,13 @@ extern void ptrace_break(struct pt_regs *regs); extern void *vectors_page; +asmlinkage void dump_backtrace_stm(u32 *stack, u32 instruction, const char *loglvl); +asmlinkage void do_undefinstr(struct pt_regs *regs); +asmlinkage void handle_fiq_as_nmi(struct pt_regs *regs); +asmlinkage void bad_mode(struct pt_regs *regs, int reason); +asmlinkage int arm_syscall(int no, struct pt_regs *regs); +asmlinkage void baddataabort(int code, unsigned long instr, struct pt_regs *regs); +asmlinkage void __div0(void); +asmlinkage void handle_bad_stack(struct pt_regs *regs); + #endif diff --git a/arch/arm/include/asm/uaccess-asm.h b/arch/arm/include/asm/uaccess-asm.h index 6451a433912c61fc380e985771d8a12d9e288e51..65da32e1f1c15d87ca51db4df4679275dd89c87d 100644 --- a/arch/arm/include/asm/uaccess-asm.h +++ b/arch/arm/include/asm/uaccess-asm.h @@ -5,7 +5,7 @@ #include #include -#include +#include #include .macro csdb diff --git a/arch/arm/include/asm/uaccess.h b/arch/arm/include/asm/uaccess.h index 2fcbec9c306cfb6b379a52e02568c40cf7b0a2a4..bb5c8182311774469a4d6d64a6b2910239f34b31 100644 --- a/arch/arm/include/asm/uaccess.h +++ b/arch/arm/include/asm/uaccess.h @@ -9,7 +9,7 @@ * User space memory access functions */ #include -#include +#include #include #include #include diff --git a/arch/arm/include/asm/unwind.h b/arch/arm/include/asm/unwind.h index b51f85417f58e185edd1ae6b2dd01caaac03b82c..d60b09a5acfc346178e3227809573d9739c9cc6b 100644 --- a/arch/arm/include/asm/unwind.h +++ b/arch/arm/include/asm/unwind.h @@ -40,6 +40,10 @@ extern void unwind_table_del(struct unwind_table *tab); extern void unwind_backtrace(struct pt_regs *regs, struct task_struct *tsk, const char *loglvl); +void __aeabi_unwind_cpp_pr0(void); +void __aeabi_unwind_cpp_pr1(void); +void __aeabi_unwind_cpp_pr2(void); + #endif /* !__ASSEMBLY__ */ #ifdef CONFIG_ARM_UNWIND diff --git a/arch/arm/include/asm/vdso.h b/arch/arm/include/asm/vdso.h index 5b85889f82eeb422400c039e8b5e8a2a6d4553b3..422c3afa806a91660459075604b61c5de1050176 100644 --- a/arch/arm/include/asm/vdso.h +++ b/arch/arm/include/asm/vdso.h @@ -24,6 +24,11 @@ static inline void arm_install_vdso(struct mm_struct *mm, unsigned long addr) #endif /* CONFIG_VDSO */ +int __vdso_clock_gettime(clockid_t clock, struct old_timespec32 *ts); +int __vdso_clock_gettime64(clockid_t clock, struct __kernel_timespec *ts); +int __vdso_gettimeofday(struct __kernel_old_timeval *tv, struct timezone *tz); +int __vdso_clock_getres(clockid_t clock_id, struct old_timespec32 *res); + #endif /* __ASSEMBLY__ */ #endif /* __KERNEL__ */ diff --git a/arch/arm/include/asm/vfp.h b/arch/arm/include/asm/vfp.h index 157ea34261586d136ab574cf4f4bed8e3148dfb1..5b57b8768baccdbc558a8f415abbb86d8c65a9d6 100644 --- a/arch/arm/include/asm/vfp.h +++ b/arch/arm/include/asm/vfp.h @@ -102,6 +102,7 @@ #ifndef __ASSEMBLY__ void vfp_disable(void); +void VFP_bounce(u32 trigger, u32 fpexc, struct pt_regs *regs); #endif #endif /* __ASM_VFP_H */ diff --git a/arch/arm/include/uapi/asm/setup.h b/arch/arm/include/uapi/asm/setup.h index 25ceda63b284d2f1c5e6bcf7e757fd66db060a71..8e50e034fec73ad23da29514d185a2ec150fda92 100644 --- a/arch/arm/include/uapi/asm/setup.h +++ b/arch/arm/include/uapi/asm/setup.h @@ -9,7 +9,7 @@ * published by the Free Software Foundation. * * Structure passed to kernel to tell it about the - * hardware it's running on. See Documentation/arm/setup.rst + * hardware it's running on. See Documentation/arch/arm/setup.rst * for more info. */ #ifndef _UAPI__ASMARM_SETUP_H diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c index 38121c59cbc26cdd51afc30e3593b909e3890c18..6a80d4be743b4f9d95d3b29e9c36f5ef65c863b3 100644 --- a/arch/arm/kernel/asm-offsets.c +++ b/arch/arm/kernel/asm-offsets.c @@ -17,7 +17,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/arch/arm/kernel/atags_parse.c b/arch/arm/kernel/atags_parse.c index 373b61f9a4f01c17fba7a5d4398034129a43f3d1..33f6eb5213a5a8c9aabbd2a5c3f20188e2144e32 100644 --- a/arch/arm/kernel/atags_parse.c +++ b/arch/arm/kernel/atags_parse.c @@ -127,7 +127,7 @@ static int __init parse_tag_cmdline(const struct tag *tag) #elif defined(CONFIG_CMDLINE_FORCE) pr_warn("Ignoring tag cmdline (using the default kernel command line)\n"); #else - strlcpy(default_command_line, tag->u.cmdline.cmdline, + strscpy(default_command_line, tag->u.cmdline.cmdline, COMMAND_LINE_SIZE); #endif return 0; @@ -224,7 +224,7 @@ setup_machine_tags(void *atags_vaddr, unsigned int machine_nr) } /* parse_early_param needs a boot_command_line */ - strlcpy(boot_command_line, from, COMMAND_LINE_SIZE); + strscpy(boot_command_line, from, COMMAND_LINE_SIZE); return mdesc; } diff --git a/arch/arm/kernel/bugs.c b/arch/arm/kernel/bugs.c index 14c8dbbb7d2dfd7a0143d941224152a326982d7f..087bce6ec8e9b20a2efc05284b8d205849c0521a 100644 --- a/arch/arm/kernel/bugs.c +++ b/arch/arm/kernel/bugs.c @@ -1,5 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 #include +#include #include #include @@ -11,7 +12,7 @@ void check_other_bugs(void) #endif } -void __init check_bugs(void) +void __init arch_cpu_finalize_init(void) { check_writebuffer_bugs(); check_other_bugs(); diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index c39303e5c23470e6a37a91185193b8964794a628..76e8125d05d26030fa02fcb36e3ca3014bea1a26 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S @@ -15,7 +15,7 @@ #include #include -#include +#include #include #include #include @@ -875,7 +875,7 @@ ENDPROC(__bad_stack) * existing ones. This mechanism should be used only for things that are * really small and justified, and not be abused freely. * - * See Documentation/arm/kernel_user_helpers.rst for formal definitions. + * See Documentation/arch/arm/kernel_user_helpers.rst for formal definitions. */ THUMB( .arm ) diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S index 03d4c5578c5c98481539afb942565f7af0c0859f..bcc4c9ec3aa4ecdfb8027f55d87e1346db74705e 100644 --- a/arch/arm/kernel/entry-common.S +++ b/arch/arm/kernel/entry-common.S @@ -9,7 +9,7 @@ #include #include #include -#include +#include #ifdef CONFIG_AEABI #include #endif diff --git a/arch/arm/kernel/entry-v7m.S b/arch/arm/kernel/entry-v7m.S index de8a60363c8597769d0d3b5d8bbe28208c724bdd..52bacf07ba16da2534ae40e83d1fa4ace6b0ec6f 100644 --- a/arch/arm/kernel/entry-v7m.S +++ b/arch/arm/kernel/entry-v7m.S @@ -6,7 +6,7 @@ * * Low-level vector interface routines for the ARMv7-M architecture */ -#include +#include #include #include #include diff --git a/arch/arm/kernel/fiq.c b/arch/arm/kernel/fiq.c index 98ca3e3fa8471f9cd490bf5fe31c7720f89b641f..d2c8e53135397e3fdebd1cd3ed6a0a58bb198c1d 100644 --- a/arch/arm/kernel/fiq.c +++ b/arch/arm/kernel/fiq.c @@ -45,6 +45,7 @@ #include #include #include +#include #include #include diff --git a/arch/arm/kernel/head-inflate-data.c b/arch/arm/kernel/head-inflate-data.c index 89a52104d32ac7ac5c32020687964f41a0d94a6b..225c0699a12c34a0c540e1485a3efa371e471467 100644 --- a/arch/arm/kernel/head-inflate-data.c +++ b/arch/arm/kernel/head-inflate-data.c @@ -8,16 +8,13 @@ #include #include +#include "head.h" /* for struct inflate_state */ #include "../../../lib/zlib_inflate/inftrees.h" #include "../../../lib/zlib_inflate/inflate.h" #include "../../../lib/zlib_inflate/infutil.h" -extern char __data_loc[]; -extern char _edata_loc[]; -extern char _sdata[]; - /* * This code is called very early during the boot process to decompress * the .data segment stored compressed in ROM. Therefore none of the global diff --git a/arch/arm/kernel/head-nommu.S b/arch/arm/kernel/head-nommu.S index 950bef83339f5e5bcde33333b2f081a546f98297..b9d6818f1ee164e1c872ab2984fd6d26efa9175a 100644 --- a/arch/arm/kernel/head-nommu.S +++ b/arch/arm/kernel/head-nommu.S @@ -14,12 +14,11 @@ #include #include #include -#include +#include #include #include #include #include -#include /* * Kernel startup entry point. diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S index 656991055bc17bc422e4084e990847b27d6cd324..1ec35f065617e4c0dabfe7ff0b915ac6985e638a 100644 --- a/arch/arm/kernel/head.S +++ b/arch/arm/kernel/head.S @@ -17,7 +17,7 @@ #include #include #include -#include +#include #include #if defined(CONFIG_DEBUG_LL) && !defined(CONFIG_DEBUG_SEMIHOSTING) diff --git a/arch/arm/kernel/head.h b/arch/arm/kernel/head.h new file mode 100644 index 0000000000000000000000000000000000000000..0eb5accf71412d3c564056ae9551ac2a259c3cbf --- /dev/null +++ b/arch/arm/kernel/head.h @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0-only + +extern char __data_loc[]; +extern char _edata_loc[]; +extern char _sdata[]; + +int __init __inflate_kernel_data(void); diff --git a/arch/arm/kernel/hibernate.c b/arch/arm/kernel/hibernate.c index 2373020af96588ba0f54c5fca3f5d302a0cacb3f..38a90a3d12b2cfcc1b96b8999950f9a8f0f244fb 100644 --- a/arch/arm/kernel/hibernate.c +++ b/arch/arm/kernel/hibernate.c @@ -19,7 +19,7 @@ #include #include #include -#include +#include #include #include "reboot.h" diff --git a/arch/arm/kernel/module.c b/arch/arm/kernel/module.c index d59c36dc0494bddf90d10950ab97d76a770a2730..e74d84f58b77c31b644918d646f5baf67a746b7b 100644 --- a/arch/arm/kernel/module.c +++ b/arch/arm/kernel/module.c @@ -169,8 +169,7 @@ apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex, offset = __mem_to_opcode_arm(*(u32 *)loc); offset = (offset & 0x00ffffff) << 2; - if (offset & 0x02000000) - offset -= 0x04000000; + offset = sign_extend32(offset, 25); offset += sym->st_value - loc; @@ -236,7 +235,7 @@ apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex, case R_ARM_MOVT_PREL: offset = tmp = __mem_to_opcode_arm(*(u32 *)loc); offset = ((offset & 0xf0000) >> 4) | (offset & 0xfff); - offset = (offset ^ 0x8000) - 0x8000; + offset = sign_extend32(offset, 15); offset += sym->st_value; if (ELF32_R_TYPE(rel->r_info) == R_ARM_MOVT_PREL || @@ -344,8 +343,7 @@ apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex, ((~(j2 ^ sign) & 1) << 22) | ((upper & 0x03ff) << 12) | ((lower & 0x07ff) << 1); - if (offset & 0x01000000) - offset -= 0x02000000; + offset = sign_extend32(offset, 24); offset += sym->st_value - loc; /* @@ -401,7 +399,7 @@ apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex, offset = ((upper & 0x000f) << 12) | ((upper & 0x0400) << 1) | ((lower & 0x7000) >> 4) | (lower & 0x00ff); - offset = (offset ^ 0x8000) - 0x8000; + offset = sign_extend32(offset, 15); offset += sym->st_value; if (ELF32_R_TYPE(rel->r_info) == R_ARM_THM_MOVT_PREL || diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index 75cd4699e7b3eed073e6c29311cdb1dca94f0947..c66b560562b301b0705163dfd201ee1e2cfbaa4c 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -76,13 +76,6 @@ static int __init fpe_setup(char *line) __setup("fpe=", fpe_setup); #endif -extern void init_default_cache_policy(unsigned long); -extern void paging_init(const struct machine_desc *desc); -extern void early_mm_init(const struct machine_desc *); -extern void adjust_lowmem_bounds(void); -extern enum reboot_mode reboot_mode; -extern void setup_dma_zone(const struct machine_desc *desc); - unsigned int processor_id; EXPORT_SYMBOL(processor_id); unsigned int __machine_arch_type __read_mostly; @@ -1142,7 +1135,7 @@ void __init setup_arch(char **cmdline_p) setup_initial_init_mm(_text, _etext, _edata, _end); /* populate cmd_line too for later use, preserving boot_command_line */ - strlcpy(cmd_line, boot_command_line, COMMAND_LINE_SIZE); + strscpy(cmd_line, boot_command_line, COMMAND_LINE_SIZE); *cmdline_p = cmd_line; early_fixmap_init(); @@ -1198,10 +1191,6 @@ void __init setup_arch(char **cmdline_p) reserve_crashkernel(); -#ifdef CONFIG_GENERIC_IRQ_MULTI_HANDLER - handle_arch_irq = mdesc->handle_irq; -#endif - #ifdef CONFIG_VT #if defined(CONFIG_VGA_CONSOLE) conswitchp = &vga_con; diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c index e07f359254c3cca23352984055a98a5e21230220..8d0afa11bed5448dd0aefca20ec8cfbaed80783f 100644 --- a/arch/arm/kernel/signal.c +++ b/arch/arm/kernel/signal.c @@ -18,6 +18,7 @@ #include #include #include +#include #include "signal.h" diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index 87f8d0e5e314a87acbae464484c5d565f2874018..6756203e45f3d0b7780d2144ab21a0a80e048883 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -288,15 +288,11 @@ int __cpu_disable(void) } /* - * called on the thread which is asking for a CPU to be shutdown - - * waits until shutdown has completed, or it is timed out. + * called on the thread which is asking for a CPU to be shutdown after the + * shutdown completed. */ -void __cpu_die(unsigned int cpu) +void arch_cpuhp_cleanup_dead_cpu(unsigned int cpu) { - if (!cpu_wait_death(cpu, 5)) { - pr_err("CPU%u: cpu didn't die\n", cpu); - return; - } pr_debug("CPU%u: shutdown\n", cpu); clear_tasks_mm_cpumask(cpu); @@ -336,11 +332,11 @@ void __noreturn arch_cpu_idle_dead(void) flush_cache_louis(); /* - * Tell __cpu_die() that this CPU is now safe to dispose of. Once - * this returns, power and/or clocks can be removed at any point - * from this CPU and its cache by platform_cpu_kill(). + * Tell cpuhp_bp_sync_dead() that this CPU is now safe to dispose + * of. Once this returns, power and/or clocks can be removed at + * any point from this CPU and its cache by platform_cpu_kill(). */ - (void)cpu_report_death(); + cpuhp_ap_report_dead(); /* * Ensure that the cache lines associated with that completion are diff --git a/arch/arm/kernel/suspend.c b/arch/arm/kernel/suspend.c index 43f0a3ebf3909d6c85daa059cdd7e1acbb2a50bc..c3ec3861dd0792a5ad18ac3875ffcfedefa2b8ec 100644 --- a/arch/arm/kernel/suspend.c +++ b/arch/arm/kernel/suspend.c @@ -8,7 +8,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/arch/arm/kernel/sys_arm.c b/arch/arm/kernel/sys_arm.c index a5f183cfecb175eb3ed95dbd7c6c33097d3d6286..0141e9bb02e8cdb8dcfe16e19808a483dfd6645a 100644 --- a/arch/arm/kernel/sys_arm.c +++ b/arch/arm/kernel/sys_arm.c @@ -24,6 +24,7 @@ #include #include #include +#include /* * Since loff_t is a 64 bit type we avoid a lot of ABI hassle diff --git a/arch/arm/kernel/sys_oabi-compat.c b/arch/arm/kernel/sys_oabi-compat.c index 006163195d67e486b9c7a3debc0d8626e53d6dfb..d00f4040a9f593142504974369e5f5678ee2ed5f 100644 --- a/arch/arm/kernel/sys_oabi-compat.c +++ b/arch/arm/kernel/sys_oabi-compat.c @@ -10,6 +10,8 @@ * Copyright: MontaVista Software, Inc. */ +#include + /* * The legacy ABI and the new ARM EABI have different rules making some * syscalls incompatible especially with structure arguments. diff --git a/arch/arm/kernel/tcm.c b/arch/arm/kernel/tcm.c index d3a85f01b328648b9ed39156841ab2b5da52bebb..f59927bcfbce31d8c5604821e0e4b187792bb046 100644 --- a/arch/arm/kernel/tcm.c +++ b/arch/arm/kernel/tcm.c @@ -15,7 +15,7 @@ #include /* memcpy */ #include #include -#include +#include #include #include #include diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index 40c7c807d67f4ed6039eccd8637943bcc6005704..3bad79db5d6e8095214d39d89853ff85d46d5eed 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c @@ -756,6 +756,7 @@ void __readwrite_bug(const char *fn) } EXPORT_SYMBOL(__readwrite_bug); +#ifdef CONFIG_MMU void __pte_error(const char *file, int line, pte_t pte) { pr_err("%s:%d: bad pte %08llx.\n", file, line, (long long)pte_val(pte)); @@ -770,6 +771,7 @@ void __pgd_error(const char *file, int line, pgd_t pgd) { pr_err("%s:%d: bad pgd %08llx.\n", file, line, (long long)pgd_val(pgd)); } +#endif asmlinkage void __div0(void) { diff --git a/arch/arm/kernel/vdso.c b/arch/arm/kernel/vdso.c index 3408269d19c7dc1181cf1512531a2788a1b3c41b..f297d66a8a7624daca23ad2ff052c504fb859b34 100644 --- a/arch/arm/kernel/vdso.c +++ b/arch/arm/kernel/vdso.c @@ -135,7 +135,7 @@ static Elf32_Sym * __init find_symbol(struct elfinfo *lib, const char *symname) if (lib->dynsym[i].st_name == 0) continue; - strlcpy(name, lib->dynstr + lib->dynsym[i].st_name, + strscpy(name, lib->dynstr + lib->dynsym[i].st_name, MAX_SYMNAME); c = strchr(name, '@'); if (c) diff --git a/arch/arm/kernel/vmlinux-xip.lds.S b/arch/arm/kernel/vmlinux-xip.lds.S index 76678732c60da42e02718cc2a21b878a472a0265..c16d196b5aad3e159c160295fd21c75c3cb7055b 100644 --- a/arch/arm/kernel/vmlinux-xip.lds.S +++ b/arch/arm/kernel/vmlinux-xip.lds.S @@ -12,9 +12,8 @@ #include #include #include -#include -#include #include +#include OUTPUT_ARCH(arm) ENTRY(stext) diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S index aa12b65a7fd6a8cc60463e9beec35698397daeee..bd9127c4b451015bb67b64cc273ff10ebb68a398 100644 --- a/arch/arm/kernel/vmlinux.lds.S +++ b/arch/arm/kernel/vmlinux.lds.S @@ -12,9 +12,8 @@ #include #include #include -#include -#include #include +#include OUTPUT_ARCH(arm) ENTRY(stext) diff --git a/arch/arm/lib/bitops.h b/arch/arm/lib/bitops.h index 95bd359912889a5d31ceaefeaefb7597deaf5c14..f069d1b2318e643111f828e719f454e42f9ca241 100644 --- a/arch/arm/lib/bitops.h +++ b/arch/arm/lib/bitops.h @@ -28,7 +28,7 @@ UNWIND( .fnend ) ENDPROC(\name ) .endm - .macro testop, name, instr, store + .macro __testop, name, instr, store, barrier ENTRY( \name ) UNWIND( .fnstart ) ands ip, r1, #3 @@ -38,7 +38,7 @@ UNWIND( .fnstart ) mov r0, r0, lsr #5 add r1, r1, r0, lsl #2 @ Get word offset mov r3, r2, lsl r3 @ create mask - smp_dmb + \barrier #if __LINUX_ARM_ARCH__ >= 7 && defined(CONFIG_SMP) .arch_extension mp ALT_SMP(W(pldw) [r1]) @@ -50,13 +50,21 @@ UNWIND( .fnstart ) strex ip, r2, [r1] cmp ip, #0 bne 1b - smp_dmb + \barrier cmp r0, #0 movne r0, #1 2: bx lr UNWIND( .fnend ) ENDPROC(\name ) .endm + + .macro testop, name, instr, store + __testop \name, \instr, \store, smp_dmb + .endm + + .macro sync_testop, name, instr, store + __testop \name, \instr, \store, __smp_dmb + .endm #else .macro bitop, name, instr ENTRY( \name ) diff --git a/arch/arm/lib/testchangebit.S b/arch/arm/lib/testchangebit.S index 4ebecc67e6e044ab6fc38fb254314a2cd0332c83..f13fe9bc2399ad81bee58d0bfd933c007326ed04 100644 --- a/arch/arm/lib/testchangebit.S +++ b/arch/arm/lib/testchangebit.S @@ -10,3 +10,7 @@ .text testop _test_and_change_bit, eor, str + +#if __LINUX_ARM_ARCH__ >= 6 +sync_testop _sync_test_and_change_bit, eor, str +#endif diff --git a/arch/arm/lib/testclearbit.S b/arch/arm/lib/testclearbit.S index 009afa0f5b4a73fcafac5b2736aa90258fe1f77d..4d2c5ca620ebf6230dff24656a6e281afe8c2483 100644 --- a/arch/arm/lib/testclearbit.S +++ b/arch/arm/lib/testclearbit.S @@ -10,3 +10,7 @@ .text testop _test_and_clear_bit, bicne, strne + +#if __LINUX_ARM_ARCH__ >= 6 +sync_testop _sync_test_and_clear_bit, bicne, strne +#endif diff --git a/arch/arm/lib/testsetbit.S b/arch/arm/lib/testsetbit.S index f3192e55acc87fede3a34a50d7ca6d446b049b89..649dbab65d8d0e3735a8c395a3bd85edeb0ac81c 100644 --- a/arch/arm/lib/testsetbit.S +++ b/arch/arm/lib/testsetbit.S @@ -10,3 +10,7 @@ .text testop _test_and_set_bit, orreq, streq + +#if __LINUX_ARM_ARCH__ >= 6 +sync_testop _sync_test_and_set_bit, orreq, streq +#endif diff --git a/arch/arm/lib/uaccess_with_memcpy.c b/arch/arm/lib/uaccess_with_memcpy.c index e4c2677cc1e9e45cac842f71d88267cb3cce32ac..2f6163f05e9357398a5d718be0a31e0ea132e0d2 100644 --- a/arch/arm/lib/uaccess_with_memcpy.c +++ b/arch/arm/lib/uaccess_with_memcpy.c @@ -74,6 +74,9 @@ pin_page_for_write(const void __user *_addr, pte_t **ptep, spinlock_t **ptlp) return 0; pte = pte_offset_map_lock(current->mm, pmd, addr, &ptl); + if (unlikely(!pte)) + return 0; + if (unlikely(!pte_present(*pte) || !pte_young(*pte) || !pte_write(*pte) || !pte_dirty(*pte))) { pte_unmap_unlock(pte, ptl); diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig index 3dd9e718661b5fd0307a0fb914f6502712f83153..a8c022b4c0535a20aa818a39d36e0e4f7584ab5c 100644 --- a/arch/arm/mach-at91/Kconfig +++ b/arch/arm/mach-at91/Kconfig @@ -97,7 +97,6 @@ config SOC_AT91SAM9 depends on ARCH_MULTI_V5 select ATMEL_AIC_IRQ select ATMEL_PM if PM - select ATMEL_SDRAMC select CPU_ARM926T select HAVE_AT91_SMD select HAVE_AT91_USB_CLK @@ -131,7 +130,6 @@ config SOC_SAM9X60 depends on ARCH_MULTI_V5 select ATMEL_AIC5_IRQ select ATMEL_PM if PM - select ATMEL_SDRAMC select CPU_ARM926T select HAVE_AT91_USB_CLK select HAVE_AT91_GENERATED_CLK @@ -213,7 +211,6 @@ config SOC_SAMA5 bool select ATMEL_AIC5_IRQ select ATMEL_PM if PM - select ATMEL_SDRAMC select MEMORY select SOC_SAM_V7 select SRAM if PM @@ -234,7 +231,6 @@ config SOC_SAMA7 bool select ARM_GIC select ATMEL_PM if PM - select ATMEL_SDRAMC select MEMORY select SOC_SAM_V7 select SRAM if PM diff --git a/arch/arm/mach-berlin/platsmp.c b/arch/arm/mach-berlin/platsmp.c index 593fc4a69d8442527b222ded1ffedcd760dda670..ed94758d30ff9ae5628cbce7bdc7b58edd1d7512 100644 --- a/arch/arm/mach-berlin/platsmp.c +++ b/arch/arm/mach-berlin/platsmp.c @@ -12,7 +12,7 @@ #include #include -#include +#include #include #include diff --git a/arch/arm/mach-davinci/common.c b/arch/arm/mach-davinci/common.c index c1ce6b2a8d48f1a169ca9af319900c6dd67fb313..7bc7018688de1328226710088fa7ccc67f473bd3 100644 --- a/arch/arm/mach-davinci/common.c +++ b/arch/arm/mach-davinci/common.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include diff --git a/arch/arm/mach-davinci/common.h b/arch/arm/mach-davinci/common.h index b4fd0e9acf6c60378b451bc07c9c48bee37dcd69..8aa6d4fc3f6f41d0c61c27e3a1a5e7f17d129c90 100644 --- a/arch/arm/mach-davinci/common.h +++ b/arch/arm/mach-davinci/common.h @@ -55,12 +55,6 @@ extern void davinci_common_init(const struct davinci_soc_info *soc_info); extern void davinci_init_ide(void); void davinci_init_late(void); -#ifdef CONFIG_CPU_FREQ -int davinci_cpufreq_init(void); -#else -static inline int davinci_cpufreq_init(void) { return 0; } -#endif - #ifdef CONFIG_SUSPEND int davinci_pm_init(void); #else diff --git a/arch/arm/mach-ep93xx/timer-ep93xx.c b/arch/arm/mach-ep93xx/timer-ep93xx.c index dd4b164d18317de367c3dcb3f86decae3711aef0..a9efa7bc2fa127bec73ecffb602a84feb37863c6 100644 --- a/arch/arm/mach-ep93xx/timer-ep93xx.c +++ b/arch/arm/mach-ep93xx/timer-ep93xx.c @@ -9,6 +9,7 @@ #include #include #include "soc.h" +#include "platform.h" /************************************************************************* * Timer handling for EP93xx @@ -60,7 +61,7 @@ static u64 notrace ep93xx_read_sched_clock(void) return ret; } -u64 ep93xx_clocksource_read(struct clocksource *c) +static u64 ep93xx_clocksource_read(struct clocksource *c) { u64 ret; diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig index 4d3b40e4049ab09462969b45173b427206b78fbe..b3d5df5225fe6ff80e78857041006744517833ce 100644 --- a/arch/arm/mach-exynos/Kconfig +++ b/arch/arm/mach-exynos/Kconfig @@ -78,6 +78,11 @@ config CPU_EXYNOS4210 default y depends on ARCH_EXYNOS4 +config SOC_EXYNOS4212 + bool "Samsung Exynos4212" + default y + depends on ARCH_EXYNOS4 + config SOC_EXYNOS4412 bool "Samsung Exynos4412" default y diff --git a/arch/arm/mach-exynos/common.h b/arch/arm/mach-exynos/common.h index 29eb075b24a4ee0350b9d20be2c4cb12bcb03ea3..f4c0d33a29e2b6c994411a367bb66271eeff0c52 100644 --- a/arch/arm/mach-exynos/common.h +++ b/arch/arm/mach-exynos/common.h @@ -15,6 +15,7 @@ #define EXYNOS3_SOC_MASK 0xFFFFF000 #define EXYNOS4210_CPU_ID 0x43210000 +#define EXYNOS4212_CPU_ID 0x43220000 #define EXYNOS4412_CPU_ID 0xE4412200 #define EXYNOS4_CPU_MASK 0xFFFE0000 @@ -34,6 +35,7 @@ static inline int is_samsung_##name(void) \ IS_SAMSUNG_CPU(exynos3250, EXYNOS3250_SOC_ID, EXYNOS3_SOC_MASK) IS_SAMSUNG_CPU(exynos4210, EXYNOS4210_CPU_ID, EXYNOS4_CPU_MASK) +IS_SAMSUNG_CPU(exynos4212, EXYNOS4212_CPU_ID, EXYNOS4_CPU_MASK) IS_SAMSUNG_CPU(exynos4412, EXYNOS4412_CPU_ID, EXYNOS4_CPU_MASK) IS_SAMSUNG_CPU(exynos5250, EXYNOS5250_SOC_ID, EXYNOS5_SOC_MASK) IS_SAMSUNG_CPU(exynos5410, EXYNOS5410_SOC_ID, EXYNOS5_SOC_MASK) @@ -52,6 +54,12 @@ IS_SAMSUNG_CPU(exynos5800, EXYNOS5800_SOC_ID, EXYNOS5_SOC_MASK) # define soc_is_exynos4210() 0 #endif +#if defined(CONFIG_SOC_EXYNOS4212) +# define soc_is_exynos4212() is_samsung_exynos4212() +#else +# define soc_is_exynos4212() 0 +#endif + #if defined(CONFIG_SOC_EXYNOS4412) # define soc_is_exynos4412() is_samsung_exynos4412() #else @@ -106,7 +114,7 @@ void exynos_firmware_init(void); #define C2_STATE (1 << 3) /* * Magic values for bootloader indicating chosen low power mode. - * See also Documentation/arm/samsung/bootloader-interface.rst + * See also Documentation/arch/arm/samsung/bootloader-interface.rst */ #define EXYNOS_SLEEP_MAGIC 0x00000bad #define EXYNOS_AFTR_MAGIC 0xfcba0d10 diff --git a/arch/arm/mach-exynos/exynos.c b/arch/arm/mach-exynos/exynos.c index 966a0995e0475636cfbd1f706251a3ee2f30cbd2..2e8099479ffab9bb59e3a2a896b72c680b247e8f 100644 --- a/arch/arm/mach-exynos/exynos.c +++ b/arch/arm/mach-exynos/exynos.c @@ -180,6 +180,7 @@ static void __init exynos_dt_machine_init(void) exynos_cpuidle.dev.platform_data = &cpuidle_coupled_exynos_data; #endif if (of_machine_is_compatible("samsung,exynos4210") || + of_machine_is_compatible("samsung,exynos4212") || (of_machine_is_compatible("samsung,exynos4412") && (of_machine_is_compatible("samsung,trats2") || of_machine_is_compatible("samsung,midas") || @@ -194,6 +195,7 @@ static char const *const exynos_dt_compat[] __initconst = { "samsung,exynos3250", "samsung,exynos4", "samsung,exynos4210", + "samsung,exynos4212", "samsung,exynos4412", "samsung,exynos5", "samsung,exynos5250", diff --git a/arch/arm/mach-exynos/firmware.c b/arch/arm/mach-exynos/firmware.c index 2da5b60b59e29a82d291ccb8c2a517f8c8055fab..a5e22678e27becd53765150c3d7d8d9198045dd0 100644 --- a/arch/arm/mach-exynos/firmware.c +++ b/arch/arm/mach-exynos/firmware.c @@ -63,12 +63,18 @@ static int exynos_cpu_boot(int cpu) * * On Exynos5 devices the call is ignored by trustzone firmware. */ - if (!soc_is_exynos4210() && !soc_is_exynos4412()) + if (!soc_is_exynos4210() && !soc_is_exynos4212() && + !soc_is_exynos4412()) return 0; /* * The second parameter of SMC_CMD_CPU1BOOT command means CPU id. + * But, Exynos4212 has only one secondary CPU so second parameter + * isn't used for informing secure firmware about CPU id. */ + if (soc_is_exynos4212()) + cpu = 0; + exynos_smc(SMC_CMD_CPU1BOOT, cpu, 0, 0); return 0; } diff --git a/arch/arm/mach-exynos/pm.c b/arch/arm/mach-exynos/pm.c index 30f4e55bf39e640c8ab2f4549623faf1c9436b67..0019d21bff90c36345c1c4d7d0b29132d907ea7f 100644 --- a/arch/arm/mach-exynos/pm.c +++ b/arch/arm/mach-exynos/pm.c @@ -161,7 +161,7 @@ void exynos_enter_aftr(void) exynos_pm_central_suspend(); - if (soc_is_exynos4412()) { + if (soc_is_exynos4212() || soc_is_exynos4412()) { /* Setting SEQ_OPTION register */ pmu_raw_writel(S5P_USE_STANDBY_WFI0 | S5P_USE_STANDBY_WFE0, S5P_CENTRAL_SEQ_OPTION); diff --git a/arch/arm/mach-exynos/suspend.c b/arch/arm/mach-exynos/suspend.c index 6d5d7696aaf71c3684196eb8505db8b6bc0c8e61..cac4e82f6c824f45d80a7c00db1ef8db2c3f49ec 100644 --- a/arch/arm/mach-exynos/suspend.c +++ b/arch/arm/mach-exynos/suspend.c @@ -231,6 +231,7 @@ static int __init exynos_pmu_irq_init(struct device_node *node, EXYNOS_PMU_IRQ(exynos3250_pmu_irq, "samsung,exynos3250-pmu"); EXYNOS_PMU_IRQ(exynos4210_pmu_irq, "samsung,exynos4210-pmu"); +EXYNOS_PMU_IRQ(exynos4212_pmu_irq, "samsung,exynos4212-pmu"); EXYNOS_PMU_IRQ(exynos4412_pmu_irq, "samsung,exynos4412-pmu"); EXYNOS_PMU_IRQ(exynos5250_pmu_irq, "samsung,exynos5250-pmu"); EXYNOS_PMU_IRQ(exynos5420_pmu_irq, "samsung,exynos5420-pmu"); @@ -640,6 +641,9 @@ static const struct of_device_id exynos_pmu_of_device_ids[] __initconst = { }, { .compatible = "samsung,exynos4210-pmu", .data = &exynos4_pm_data, + }, { + .compatible = "samsung,exynos4212-pmu", + .data = &exynos4_pm_data, }, { .compatible = "samsung,exynos4412-pmu", .data = &exynos4_pm_data, diff --git a/arch/arm/mach-highbank/pm.c b/arch/arm/mach-highbank/pm.c index 561941baeda961c6e6f96bdb6e2c81e8ed69ec3b..3fdbdb83113b5ed45fc1e48cd058c37a9e312a32 100644 --- a/arch/arm/mach-highbank/pm.c +++ b/arch/arm/mach-highbank/pm.c @@ -12,6 +12,8 @@ #include +#include "core.h" + #define HIGHBANK_SUSPEND_PARAM \ ((0 << PSCI_0_2_POWER_STATE_ID_SHIFT) | \ (1 << PSCI_0_2_POWER_STATE_AFFL_SHIFT) | \ diff --git a/arch/arm/mach-imx/pm-imx25.c b/arch/arm/mach-imx/pm-imx25.c index f253e50194651e5dd3865162dc88b716951f76b8..0c574e8607fd9ee7e00b12f350e954db38be936b 100644 --- a/arch/arm/mach-imx/pm-imx25.c +++ b/arch/arm/mach-imx/pm-imx25.c @@ -6,6 +6,7 @@ #include #include #include +#include "common.h" static int imx25_suspend_enter(suspend_state_t state) { diff --git a/arch/arm/mach-keystone/keystone.c b/arch/arm/mach-keystone/keystone.c index aa352c2de3138974d9f359ba7c9fd15fb3c90366..68039aad3014e26972ed07ebc43ebb7e6709f3b7 100644 --- a/arch/arm/mach-keystone/keystone.c +++ b/arch/arm/mach-keystone/keystone.c @@ -18,7 +18,7 @@ #include #include #include -#include +#include #include "memory.h" diff --git a/arch/arm/mach-lpc32xx/serial.c b/arch/arm/mach-lpc32xx/serial.c index 3e765c4bf986091eb881fd588e549165d3edf7f3..3b1203db81b2cd19ce2c7daee08625dc871a3b96 100644 --- a/arch/arm/mach-lpc32xx/serial.c +++ b/arch/arm/mach-lpc32xx/serial.c @@ -15,6 +15,7 @@ #include #include #include +#include #include "lpc32xx.h" #include "common.h" diff --git a/arch/arm/mach-mxs/mach-mxs.c b/arch/arm/mach-mxs/mach-mxs.c index 51e47053c81667d7d89dce10f518e02c241f2146..3faf9a1e3e36aa6b70f7858fc61bb4727cea034f 100644 --- a/arch/arm/mach-mxs/mach-mxs.c +++ b/arch/arm/mach-mxs/mach-mxs.c @@ -11,7 +11,6 @@ #include #include #include -#include #include #include #include @@ -472,7 +471,6 @@ static const char *const mxs_dt_compat[] __initconst = { }; DT_MACHINE_START(MXS, "Freescale MXS (Device Tree)") - .handle_irq = icoll_handle_irq, .init_machine = mxs_machine_init, .init_late = mxs_pm_init, .dt_compat = mxs_dt_compat, diff --git a/arch/arm/mach-omap1/board-ams-delta.c b/arch/arm/mach-omap1/board-ams-delta.c index 9108c871d129a82401de41ce7344f06499a18389..9808cd27e2cf9359108ee6df0c1d63052ce52dd9 100644 --- a/arch/arm/mach-omap1/board-ams-delta.c +++ b/arch/arm/mach-omap1/board-ams-delta.c @@ -11,7 +11,6 @@ #include #include #include -#include #include #include #include @@ -877,7 +876,6 @@ MACHINE_START(AMS_DELTA, "Amstrad E3 (Delta)") .map_io = ams_delta_map_io, .init_early = omap1_init_early, .init_irq = omap1_init_irq, - .handle_irq = omap1_handle_irq, .init_machine = ams_delta_init, .init_late = ams_delta_init_late, .init_time = omap1_timer_init, diff --git a/arch/arm/mach-omap1/board-nokia770.c b/arch/arm/mach-omap1/board-nokia770.c index a501a473ffd6824a4628a5637aababa92439dd26..3312ef93355da7eb63ec9ee956fcae497b59cae5 100644 --- a/arch/arm/mach-omap1/board-nokia770.c +++ b/arch/arm/mach-omap1/board-nokia770.c @@ -6,17 +6,18 @@ */ #include #include -#include +#include #include +#include #include #include #include #include +#include #include #include #include -#include #include #include @@ -35,6 +36,25 @@ #include "clock.h" #include "mmc.h" +static const struct software_node nokia770_mpuio_gpiochip_node = { + .name = "mpuio", +}; + +static const struct software_node nokia770_gpiochip1_node = { + .name = "gpio-0-15", +}; + +static const struct software_node nokia770_gpiochip2_node = { + .name = "gpio-16-31", +}; + +static const struct software_node *nokia770_gpiochip_nodes[] = { + &nokia770_mpuio_gpiochip_node, + &nokia770_gpiochip1_node, + &nokia770_gpiochip2_node, + NULL +}; + #define ADS7846_PENDOWN_GPIO 15 static const unsigned int nokia770_keymap[] = { @@ -85,40 +105,47 @@ static struct platform_device *nokia770_devices[] __initdata = { &nokia770_kp_device, }; -static void mipid_shutdown(struct mipid_platform_data *pdata) -{ - if (pdata->nreset_gpio != -1) { - printk(KERN_INFO "shutdown LCD\n"); - gpio_set_value(pdata->nreset_gpio, 0); - msleep(120); - } -} - -static struct mipid_platform_data nokia770_mipid_platform_data = { - .shutdown = mipid_shutdown, -}; +static struct mipid_platform_data nokia770_mipid_platform_data = { }; static const struct omap_lcd_config nokia770_lcd_config __initconst = { .ctrl_name = "hwa742", }; +static const struct property_entry nokia770_mipid_props[] = { + PROPERTY_ENTRY_GPIO("reset-gpios", &nokia770_gpiochip1_node, + 13, GPIO_ACTIVE_LOW), + { } +}; + +static const struct software_node nokia770_mipid_swnode = { + .name = "lcd_mipid", + .properties = nokia770_mipid_props, +}; + static void __init mipid_dev_init(void) { - nokia770_mipid_platform_data.nreset_gpio = 13; nokia770_mipid_platform_data.data_lines = 16; omapfb_set_lcd_config(&nokia770_lcd_config); } -static struct ads7846_platform_data nokia770_ads7846_platform_data __initdata = { - .x_max = 0x0fff, - .y_max = 0x0fff, - .x_plate_ohms = 180, - .pressure_max = 255, - .debounce_max = 10, - .debounce_tol = 3, - .debounce_rep = 1, - .gpio_pendown = ADS7846_PENDOWN_GPIO, +static const struct property_entry nokia770_ads7846_props[] = { + PROPERTY_ENTRY_STRING("compatible", "ti,ads7846"), + PROPERTY_ENTRY_U32("touchscreen-size-x", 4096), + PROPERTY_ENTRY_U32("touchscreen-size-y", 4096), + PROPERTY_ENTRY_U32("touchscreen-max-pressure", 256), + PROPERTY_ENTRY_U32("touchscreen-average-samples", 10), + PROPERTY_ENTRY_U16("ti,x-plate-ohms", 180), + PROPERTY_ENTRY_U16("ti,debounce-tol", 3), + PROPERTY_ENTRY_U16("ti,debounce-rep", 1), + PROPERTY_ENTRY_GPIO("pendown-gpios", &nokia770_gpiochip1_node, + ADS7846_PENDOWN_GPIO, GPIO_ACTIVE_LOW), + { } +}; + +static const struct software_node nokia770_ads7846_swnode = { + .name = "ads7846", + .properties = nokia770_ads7846_props, }; static struct spi_board_info nokia770_spi_board_info[] __initdata = { @@ -128,13 +155,14 @@ static struct spi_board_info nokia770_spi_board_info[] __initdata = { .chip_select = 3, .max_speed_hz = 12000000, .platform_data = &nokia770_mipid_platform_data, + .swnode = &nokia770_mipid_swnode, }, [1] = { .modalias = "ads7846", .bus_num = 2, .chip_select = 0, .max_speed_hz = 2500000, - .platform_data = &nokia770_ads7846_platform_data, + .swnode = &nokia770_ads7846_swnode, }, }; @@ -156,27 +184,23 @@ static struct omap_usb_config nokia770_usb_config __initdata = { #if IS_ENABLED(CONFIG_MMC_OMAP) -#define NOKIA770_GPIO_MMC_POWER 41 -#define NOKIA770_GPIO_MMC_SWITCH 23 - -static int nokia770_mmc_set_power(struct device *dev, int slot, int power_on, - int vdd) -{ - gpio_set_value(NOKIA770_GPIO_MMC_POWER, power_on); - return 0; -} - -static int nokia770_mmc_get_cover_state(struct device *dev, int slot) -{ - return gpio_get_value(NOKIA770_GPIO_MMC_SWITCH); -} +static struct gpiod_lookup_table nokia770_mmc_gpio_table = { + .dev_id = "mmci-omap.1", + .table = { + /* Slot index 0, VSD power, GPIO 41 */ + GPIO_LOOKUP_IDX("gpio-32-47", 9, + "vsd", 0, GPIO_ACTIVE_HIGH), + /* Slot index 0, switch, GPIO 23 */ + GPIO_LOOKUP_IDX("gpio-16-31", 7, + "cover", 0, GPIO_ACTIVE_HIGH), + { } + }, +}; static struct omap_mmc_platform_data nokia770_mmc2_data = { .nr_slots = 1, .max_freq = 12000000, .slots[0] = { - .set_power = nokia770_mmc_set_power, - .get_cover_state = nokia770_mmc_get_cover_state, .ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34, .name = "mmcblk", }, @@ -186,20 +210,7 @@ static struct omap_mmc_platform_data *nokia770_mmc_data[OMAP16XX_NR_MMC]; static void __init nokia770_mmc_init(void) { - int ret; - - ret = gpio_request(NOKIA770_GPIO_MMC_POWER, "MMC power"); - if (ret < 0) - return; - gpio_direction_output(NOKIA770_GPIO_MMC_POWER, 0); - - ret = gpio_request(NOKIA770_GPIO_MMC_SWITCH, "MMC cover"); - if (ret < 0) { - gpio_free(NOKIA770_GPIO_MMC_POWER); - return; - } - gpio_direction_input(NOKIA770_GPIO_MMC_SWITCH); - + gpiod_add_lookup_table(&nokia770_mmc_gpio_table); /* Only the second MMC controller is used */ nokia770_mmc_data[1] = &nokia770_mmc2_data; omap1_init_mmc(nokia770_mmc_data, OMAP16XX_NR_MMC); @@ -212,14 +223,16 @@ static inline void nokia770_mmc_init(void) #endif #if IS_ENABLED(CONFIG_I2C_CBUS_GPIO) -static struct gpiod_lookup_table nokia770_cbus_gpio_table = { - .dev_id = "i2c-cbus-gpio.2", - .table = { - GPIO_LOOKUP_IDX("mpuio", 9, NULL, 0, 0), /* clk */ - GPIO_LOOKUP_IDX("mpuio", 10, NULL, 1, 0), /* dat */ - GPIO_LOOKUP_IDX("mpuio", 11, NULL, 2, 0), /* sel */ - { }, - }, + +static const struct software_node_ref_args nokia770_cbus_gpio_refs[] = { + SOFTWARE_NODE_REFERENCE(&nokia770_mpuio_gpiochip_node, 9, 0), + SOFTWARE_NODE_REFERENCE(&nokia770_mpuio_gpiochip_node, 10, 0), + SOFTWARE_NODE_REFERENCE(&nokia770_mpuio_gpiochip_node, 11, 0), +}; + +static const struct property_entry nokia770_cbus_props[] = { + PROPERTY_ENTRY_REF_ARRAY("gpios", nokia770_cbus_gpio_refs), + { } }; static struct platform_device nokia770_cbus_device = { @@ -238,22 +251,29 @@ static struct i2c_board_info nokia770_i2c_board_info_2[] __initdata = { static void __init nokia770_cbus_init(void) { - const int retu_irq_gpio = 62; - const int tahvo_irq_gpio = 40; - - if (gpio_request_one(retu_irq_gpio, GPIOF_IN, "Retu IRQ")) - return; - if (gpio_request_one(tahvo_irq_gpio, GPIOF_IN, "Tahvo IRQ")) { - gpio_free(retu_irq_gpio); - return; + struct gpio_desc *d; + int irq; + + d = gpiod_get(NULL, "retu_irq", GPIOD_IN); + if (IS_ERR(d)) { + pr_err("Unable to get CBUS Retu IRQ GPIO descriptor\n"); + } else { + irq = gpiod_to_irq(d); + irq_set_irq_type(irq, IRQ_TYPE_EDGE_RISING); + nokia770_i2c_board_info_2[0].irq = irq; + } + d = gpiod_get(NULL, "tahvo_irq", GPIOD_IN); + if (IS_ERR(d)) { + pr_err("Unable to get CBUS Tahvo IRQ GPIO descriptor\n"); + } else { + irq = gpiod_to_irq(d); + irq_set_irq_type(irq, IRQ_TYPE_EDGE_RISING); + nokia770_i2c_board_info_2[1].irq = irq; } - irq_set_irq_type(gpio_to_irq(retu_irq_gpio), IRQ_TYPE_EDGE_RISING); - irq_set_irq_type(gpio_to_irq(tahvo_irq_gpio), IRQ_TYPE_EDGE_RISING); - nokia770_i2c_board_info_2[0].irq = gpio_to_irq(retu_irq_gpio); - nokia770_i2c_board_info_2[1].irq = gpio_to_irq(tahvo_irq_gpio); i2c_register_board_info(2, nokia770_i2c_board_info_2, ARRAY_SIZE(nokia770_i2c_board_info_2)); - gpiod_add_lookup_table(&nokia770_cbus_gpio_table); + device_create_managed_software_node(&nokia770_cbus_device.dev, + nokia770_cbus_props, NULL); platform_device_register(&nokia770_cbus_device); } #else /* CONFIG_I2C_CBUS_GPIO */ @@ -262,8 +282,33 @@ static void __init nokia770_cbus_init(void) } #endif /* CONFIG_I2C_CBUS_GPIO */ +static struct gpiod_lookup_table nokia770_irq_gpio_table = { + .dev_id = NULL, + .table = { + /* GPIO used by SPI device 1 */ + GPIO_LOOKUP("gpio-0-15", 15, "ads7846_irq", + GPIO_ACTIVE_HIGH), + /* GPIO used for retu IRQ */ + GPIO_LOOKUP("gpio-48-63", 15, "retu_irq", + GPIO_ACTIVE_HIGH), + /* GPIO used for tahvo IRQ */ + GPIO_LOOKUP("gpio-32-47", 8, "tahvo_irq", + GPIO_ACTIVE_HIGH), + /* GPIOs used by serial wakeup IRQs */ + GPIO_LOOKUP_IDX("gpio-32-47", 5, "wakeup", 0, + GPIO_ACTIVE_HIGH), + GPIO_LOOKUP_IDX("gpio-16-31", 2, "wakeup", 1, + GPIO_ACTIVE_HIGH), + GPIO_LOOKUP_IDX("gpio-48-63", 1, "wakeup", 2, + GPIO_ACTIVE_HIGH), + { } + }, +}; + static void __init omap_nokia770_init(void) { + struct gpio_desc *d; + /* On Nokia 770, the SleepX signal is masked with an * MPUIO line by default. It has to be unmasked for it * to become functional */ @@ -273,8 +318,16 @@ static void __init omap_nokia770_init(void) /* Unmask SleepX signal */ omap_writew((omap_readw(0xfffb5004) & ~2), 0xfffb5004); + software_node_register_node_group(nokia770_gpiochip_nodes); platform_add_devices(nokia770_devices, ARRAY_SIZE(nokia770_devices)); - nokia770_spi_board_info[1].irq = gpio_to_irq(15); + + gpiod_add_lookup_table(&nokia770_irq_gpio_table); + d = gpiod_get(NULL, "ads7846_irq", GPIOD_IN); + if (IS_ERR(d)) + pr_err("Unable to get ADS7846 IRQ GPIO descriptor\n"); + else + nokia770_spi_board_info[1].irq = gpiod_to_irq(d); + spi_register_board_info(nokia770_spi_board_info, ARRAY_SIZE(nokia770_spi_board_info)); omap_serial_init(); @@ -291,7 +344,6 @@ MACHINE_START(NOKIA770, "Nokia 770") .map_io = omap1_map_io, .init_early = omap1_init_early, .init_irq = omap1_init_irq, - .handle_irq = omap1_handle_irq, .init_machine = omap_nokia770_init, .init_late = omap1_init_late, .init_time = omap1_timer_init, diff --git a/arch/arm/mach-omap1/board-osk.c b/arch/arm/mach-omap1/board-osk.c index df758c1f92373bbfc0e0e6aa2b0c109da6d500ab..7d5e6f9039d5b185328573d5ac1fffcd7c2f284f 100644 --- a/arch/arm/mach-omap1/board-osk.c +++ b/arch/arm/mach-omap1/board-osk.c @@ -25,7 +25,8 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include +#include +#include #include #include #include @@ -64,13 +65,12 @@ /* TPS65010 has four GPIOs. nPG and LED2 can be treated like GPIOs with * alternate pin configurations for hardware-controlled blinking. */ -#define OSK_TPS_GPIO_BASE (OMAP_MAX_GPIO_LINES + 16 /* MPUIO */) -# define OSK_TPS_GPIO_USB_PWR_EN (OSK_TPS_GPIO_BASE + 0) -# define OSK_TPS_GPIO_LED_D3 (OSK_TPS_GPIO_BASE + 1) -# define OSK_TPS_GPIO_LAN_RESET (OSK_TPS_GPIO_BASE + 2) -# define OSK_TPS_GPIO_DSP_PWR_EN (OSK_TPS_GPIO_BASE + 3) -# define OSK_TPS_GPIO_LED_D9 (OSK_TPS_GPIO_BASE + 4) -# define OSK_TPS_GPIO_LED_D2 (OSK_TPS_GPIO_BASE + 5) +#define OSK_TPS_GPIO_USB_PWR_EN 0 +#define OSK_TPS_GPIO_LED_D3 1 +#define OSK_TPS_GPIO_LAN_RESET 2 +#define OSK_TPS_GPIO_DSP_PWR_EN 3 +#define OSK_TPS_GPIO_LED_D9 4 +#define OSK_TPS_GPIO_LED_D2 5 static struct mtd_partition osk_partitions[] = { /* bootloader (U-Boot, etc) in first sector */ @@ -174,11 +174,20 @@ static const struct gpio_led tps_leds[] = { /* NOTE: D9 and D2 have hardware blink support. * Also, D9 requires non-battery power. */ - { .gpio = OSK_TPS_GPIO_LED_D9, .name = "d9", - .default_trigger = "disk-activity", }, - { .gpio = OSK_TPS_GPIO_LED_D2, .name = "d2", }, - { .gpio = OSK_TPS_GPIO_LED_D3, .name = "d3", .active_low = 1, - .default_trigger = "heartbeat", }, + { .name = "d9", .default_trigger = "disk-activity", }, + { .name = "d2", }, + { .name = "d3", .default_trigger = "heartbeat", }, +}; + +static struct gpiod_lookup_table tps_leds_gpio_table = { + .dev_id = "leds-gpio", + .table = { + /* Use local offsets on TPS65010 */ + GPIO_LOOKUP_IDX("tps65010", OSK_TPS_GPIO_LED_D9, NULL, 0, GPIO_ACTIVE_HIGH), + GPIO_LOOKUP_IDX("tps65010", OSK_TPS_GPIO_LED_D2, NULL, 1, GPIO_ACTIVE_HIGH), + GPIO_LOOKUP_IDX("tps65010", OSK_TPS_GPIO_LED_D3, NULL, 2, GPIO_ACTIVE_LOW), + { } + }, }; static struct gpio_led_platform_data tps_leds_data = { @@ -192,29 +201,34 @@ static struct platform_device osk5912_tps_leds = { .dev.platform_data = &tps_leds_data, }; -static int osk_tps_setup(struct i2c_client *client, void *context) +/* The board just hold these GPIOs hogged from setup to teardown */ +static struct gpio_desc *eth_reset; +static struct gpio_desc *vdd_dsp; + +static int osk_tps_setup(struct i2c_client *client, struct gpio_chip *gc) { + struct gpio_desc *d; if (!IS_BUILTIN(CONFIG_TPS65010)) return -ENOSYS; /* Set GPIO 1 HIGH to disable VBUS power supply; * OHCI driver powers it up/down as needed. */ - gpio_request(OSK_TPS_GPIO_USB_PWR_EN, "n_vbus_en"); - gpio_direction_output(OSK_TPS_GPIO_USB_PWR_EN, 1); + d = gpiochip_request_own_desc(gc, OSK_TPS_GPIO_USB_PWR_EN, "n_vbus_en", + GPIO_ACTIVE_HIGH, GPIOD_OUT_HIGH); /* Free the GPIO again as the driver will request it */ - gpio_free(OSK_TPS_GPIO_USB_PWR_EN); + gpiochip_free_own_desc(d); /* Set GPIO 2 high so LED D3 is off by default */ tps65010_set_gpio_out_value(GPIO2, HIGH); /* Set GPIO 3 low to take ethernet out of reset */ - gpio_request(OSK_TPS_GPIO_LAN_RESET, "smc_reset"); - gpio_direction_output(OSK_TPS_GPIO_LAN_RESET, 0); + eth_reset = gpiochip_request_own_desc(gc, OSK_TPS_GPIO_LAN_RESET, "smc_reset", + GPIO_ACTIVE_HIGH, GPIOD_OUT_LOW); /* GPIO4 is VDD_DSP */ - gpio_request(OSK_TPS_GPIO_DSP_PWR_EN, "dsp_power"); - gpio_direction_output(OSK_TPS_GPIO_DSP_PWR_EN, 1); + vdd_dsp = gpiochip_request_own_desc(gc, OSK_TPS_GPIO_DSP_PWR_EN, "dsp_power", + GPIO_ACTIVE_HIGH, GPIOD_OUT_HIGH); /* REVISIT if DSP support isn't configured, power it off ... */ /* Let LED1 (D9) blink; leds-gpio may override it */ @@ -232,15 +246,22 @@ static int osk_tps_setup(struct i2c_client *client, void *context) /* register these three LEDs */ osk5912_tps_leds.dev.parent = &client->dev; + gpiod_add_lookup_table(&tps_leds_gpio_table); platform_device_register(&osk5912_tps_leds); return 0; } +static void osk_tps_teardown(struct i2c_client *client, struct gpio_chip *gc) +{ + gpiochip_free_own_desc(eth_reset); + gpiochip_free_own_desc(vdd_dsp); +} + static struct tps65010_board tps_board = { - .base = OSK_TPS_GPIO_BASE, .outmask = 0x0f, .setup = osk_tps_setup, + .teardown = osk_tps_teardown, }; static struct i2c_board_info __initdata osk_i2c_board_info[] = { @@ -263,11 +284,6 @@ static void __init osk_init_smc91x(void) { u32 l; - if ((gpio_request(0, "smc_irq")) < 0) { - printk("Error requesting gpio 0 for smc91x irq\n"); - return; - } - /* Check EMIFS wait states to fix errors with SMC_GET_PKT_HDR */ l = omap_readl(EMIFS_CCS(1)); l |= 0x3; @@ -279,10 +295,6 @@ static void __init osk_init_cf(int seg) struct resource *res = &osk5912_cf_resources[1]; omap_cfg_reg(M7_1610_GPIO62); - if ((gpio_request(62, "cf_irq")) < 0) { - printk("Error requesting gpio 62 for CF irq\n"); - return; - } switch (seg) { /* NOTE: CS0 could be configured too ... */ @@ -308,18 +320,17 @@ static void __init osk_init_cf(int seg) seg, omap_readl(EMIFS_CCS(seg)), omap_readl(EMIFS_ACS(seg))); omap_writel(0x0004a1b3, EMIFS_CCS(seg)); /* synch mode 4 etc */ omap_writel(0x00000000, EMIFS_ACS(seg)); /* OE hold/setup */ - - /* the CF I/O IRQ is really active-low */ - irq_set_irq_type(gpio_to_irq(62), IRQ_TYPE_EDGE_FALLING); } static struct gpiod_lookup_table osk_usb_gpio_table = { .dev_id = "ohci", .table = { /* Power GPIO on the I2C-attached TPS65010 */ - GPIO_LOOKUP("tps65010", 0, "power", GPIO_ACTIVE_HIGH), + GPIO_LOOKUP("tps65010", OSK_TPS_GPIO_USB_PWR_EN, "power", + GPIO_ACTIVE_HIGH), GPIO_LOOKUP(OMAP_GPIO_LABEL, 9, "overcurrent", GPIO_ACTIVE_HIGH), + { } }, }; @@ -341,8 +352,32 @@ static struct omap_usb_config osk_usb_config __initdata = { #define EMIFS_CS3_VAL (0x88013141) +static struct gpiod_lookup_table osk_irq_gpio_table = { + .dev_id = NULL, + .table = { + /* GPIO used for SMC91x IRQ */ + GPIO_LOOKUP(OMAP_GPIO_LABEL, 0, "smc_irq", + GPIO_ACTIVE_HIGH), + /* GPIO used for CF IRQ */ + GPIO_LOOKUP("gpio-48-63", 14, "cf_irq", + GPIO_ACTIVE_HIGH), + /* GPIO used by the TPS65010 chip */ + GPIO_LOOKUP("mpuio", 1, "tps65010", + GPIO_ACTIVE_HIGH), + /* GPIOs used for serial wakeup IRQs */ + GPIO_LOOKUP_IDX("gpio-32-47", 5, "wakeup", 0, + GPIO_ACTIVE_HIGH), + GPIO_LOOKUP_IDX("gpio-16-31", 2, "wakeup", 1, + GPIO_ACTIVE_HIGH), + GPIO_LOOKUP_IDX("gpio-48-63", 1, "wakeup", 2, + GPIO_ACTIVE_HIGH), + { } + }, +}; + static void __init osk_init(void) { + struct gpio_desc *d; u32 l; osk_init_smc91x(); @@ -359,10 +394,31 @@ static void __init osk_init(void) osk_flash_resource.end = osk_flash_resource.start = omap_cs3_phys(); osk_flash_resource.end += SZ_32M - 1; - osk5912_smc91x_resources[1].start = gpio_to_irq(0); - osk5912_smc91x_resources[1].end = gpio_to_irq(0); - osk5912_cf_resources[0].start = gpio_to_irq(62); - osk5912_cf_resources[0].end = gpio_to_irq(62); + + /* + * Add the GPIOs to be used as IRQs and immediately look them up + * to be passed as an IRQ resource. This is ugly but should work + * until the day we convert to device tree. + */ + gpiod_add_lookup_table(&osk_irq_gpio_table); + + d = gpiod_get(NULL, "smc_irq", GPIOD_IN); + if (IS_ERR(d)) { + pr_err("Unable to get SMC IRQ GPIO descriptor\n"); + } else { + irq_set_irq_type(gpiod_to_irq(d), IRQ_TYPE_EDGE_RISING); + osk5912_smc91x_resources[1] = DEFINE_RES_IRQ(gpiod_to_irq(d)); + } + + d = gpiod_get(NULL, "cf_irq", GPIOD_IN); + if (IS_ERR(d)) { + pr_err("Unable to get CF IRQ GPIO descriptor\n"); + } else { + /* the CF I/O IRQ is really active-low */ + irq_set_irq_type(gpiod_to_irq(d), IRQ_TYPE_EDGE_FALLING); + osk5912_cf_resources[0] = DEFINE_RES_IRQ(gpiod_to_irq(d)); + } + platform_add_devices(osk5912_devices, ARRAY_SIZE(osk5912_devices)); l = omap_readl(USB_TRANSCEIVER_CTRL); @@ -372,13 +428,15 @@ static void __init osk_init(void) gpiod_add_lookup_table(&osk_usb_gpio_table); omap1_usb_init(&osk_usb_config); + omap_serial_init(); + /* irq for tps65010 chip */ /* bootloader effectively does: omap_cfg_reg(U19_1610_MPUIO1); */ - if (gpio_request(OMAP_MPUIO(1), "tps65010") == 0) - gpio_direction_input(OMAP_MPUIO(1)); - - omap_serial_init(); - osk_i2c_board_info[0].irq = gpio_to_irq(OMAP_MPUIO(1)); + d = gpiod_get(NULL, "tps65010", GPIOD_IN); + if (IS_ERR(d)) + pr_err("Unable to get TPS65010 IRQ GPIO descriptor\n"); + else + osk_i2c_board_info[0].irq = gpiod_to_irq(d); omap_register_i2c_bus(1, 400, osk_i2c_board_info, ARRAY_SIZE(osk_i2c_board_info)); } @@ -389,7 +447,6 @@ MACHINE_START(OMAP_OSK, "TI-OSK") .map_io = omap1_map_io, .init_early = omap1_init_early, .init_irq = omap1_init_irq, - .handle_irq = omap1_handle_irq, .init_machine = osk_init, .init_late = omap1_init_late, .init_time = omap1_timer_init, diff --git a/arch/arm/mach-omap1/board-palmte.c b/arch/arm/mach-omap1/board-palmte.c index f79c497f04d5723ff7fe384fd987438ef16f927d..7e061d671fde421b6d87de67ed8f6421720079b0 100644 --- a/arch/arm/mach-omap1/board-palmte.c +++ b/arch/arm/mach-omap1/board-palmte.c @@ -13,7 +13,8 @@ * * Copyright (c) 2006 Andrzej Zaborowski */ -#include +#include +#include #include #include #include @@ -187,23 +188,6 @@ static struct spi_board_info palmte_spi_info[] __initdata = { }, }; -static void __init palmte_misc_gpio_setup(void) -{ - /* Set TSC2102 PINTDAV pin as input (used by TSC2102 driver) */ - if (gpio_request(PALMTE_PINTDAV_GPIO, "TSC2102 PINTDAV") < 0) { - printk(KERN_ERR "Could not reserve PINTDAV GPIO!\n"); - return; - } - gpio_direction_input(PALMTE_PINTDAV_GPIO); - - /* Set USB-or-DC-IN pin as input (unused) */ - if (gpio_request(PALMTE_USB_OR_DC_GPIO, "USB/DC-IN") < 0) { - printk(KERN_ERR "Could not reserve cable signal GPIO!\n"); - return; - } - gpio_direction_input(PALMTE_USB_OR_DC_GPIO); -} - #if IS_ENABLED(CONFIG_MMC_OMAP) static struct omap_mmc_platform_data _palmte_mmc_config = { @@ -231,8 +215,23 @@ static void palmte_mmc_init(void) #endif /* CONFIG_MMC_OMAP */ +static struct gpiod_lookup_table palmte_irq_gpio_table = { + .dev_id = NULL, + .table = { + /* GPIO used for TSC2102 PINTDAV IRQ */ + GPIO_LOOKUP("gpio-0-15", PALMTE_PINTDAV_GPIO, "tsc2102_irq", + GPIO_ACTIVE_HIGH), + /* GPIO used for USB or DC input detection */ + GPIO_LOOKUP("gpio-0-15", PALMTE_USB_OR_DC_GPIO, "usb_dc_irq", + GPIO_ACTIVE_HIGH), + { } + }, +}; + static void __init omap_palmte_init(void) { + struct gpio_desc *d; + /* mux pins for uarts */ omap_cfg_reg(UART1_TX); omap_cfg_reg(UART1_RTS); @@ -243,9 +242,21 @@ static void __init omap_palmte_init(void) platform_add_devices(palmte_devices, ARRAY_SIZE(palmte_devices)); - palmte_spi_info[0].irq = gpio_to_irq(PALMTE_PINTDAV_GPIO); + gpiod_add_lookup_table(&palmte_irq_gpio_table); + d = gpiod_get(NULL, "tsc2102_irq", GPIOD_IN); + if (IS_ERR(d)) + pr_err("Unable to get TSC2102 IRQ GPIO descriptor\n"); + else + palmte_spi_info[0].irq = gpiod_to_irq(d); spi_register_board_info(palmte_spi_info, ARRAY_SIZE(palmte_spi_info)); - palmte_misc_gpio_setup(); + + /* We are getting this just to set it up as input */ + d = gpiod_get(NULL, "usb_dc_irq", GPIOD_IN); + if (IS_ERR(d)) + pr_err("Unable to get USB/DC IRQ GPIO descriptor\n"); + else + gpiod_put(d); + omap_serial_init(); omap1_usb_init(&palmte_usb_config); omap_register_i2c_bus(1, 100, NULL, 0); @@ -259,7 +270,6 @@ MACHINE_START(OMAP_PALMTE, "OMAP310 based Palm Tungsten E") .map_io = omap1_map_io, .init_early = omap1_init_early, .init_irq = omap1_init_irq, - .handle_irq = omap1_handle_irq, .init_machine = omap_palmte_init, .init_late = omap1_init_late, .init_time = omap1_timer_init, diff --git a/arch/arm/mach-omap1/board-sx1-mmc.c b/arch/arm/mach-omap1/board-sx1-mmc.c index f1c160924dfe4988d0cde87ca4359151ef656b48..f183a8448a7b055bd7f3d5b4513ee2cb0a930486 100644 --- a/arch/arm/mach-omap1/board-sx1-mmc.c +++ b/arch/arm/mach-omap1/board-sx1-mmc.c @@ -9,7 +9,6 @@ * Copyright (C) 2007 Instituto Nokia de Tecnologia - INdT */ -#include #include #include "hardware.h" diff --git a/arch/arm/mach-omap1/board-sx1.c b/arch/arm/mach-omap1/board-sx1.c index 0c0cdd5e77c795b93d2a0ba6a8f592eefb4fb1cc..b869c7ba1a1b762b9474313530755208764b6a91 100644 --- a/arch/arm/mach-omap1/board-sx1.c +++ b/arch/arm/mach-omap1/board-sx1.c @@ -11,7 +11,8 @@ * Maintainters : Vladimir Ananiev (aka Vovan888), Sergge * oslik.ru */ -#include +#include +#include #include #include #include @@ -304,8 +305,23 @@ static struct platform_device *sx1_devices[] __initdata = { /*-----------------------------------------*/ +static struct gpiod_lookup_table sx1_gpio_table = { + .dev_id = NULL, + .table = { + GPIO_LOOKUP("gpio-0-15", 1, "irda_off", + GPIO_ACTIVE_HIGH), + GPIO_LOOKUP("gpio-0-15", 11, "switch", + GPIO_ACTIVE_HIGH), + GPIO_LOOKUP("gpio-0-15", 15, "usb_on", + GPIO_ACTIVE_HIGH), + { } + }, +}; + static void __init omap_sx1_init(void) { + struct gpio_desc *d; + /* mux pins for uarts */ omap_cfg_reg(UART1_TX); omap_cfg_reg(UART1_RTS); @@ -320,15 +336,25 @@ static void __init omap_sx1_init(void) omap_register_i2c_bus(1, 100, NULL, 0); omap1_usb_init(&sx1_usb_config); sx1_mmc_init(); + gpiod_add_lookup_table(&sx1_gpio_table); /* turn on USB power */ /* sx1_setusbpower(1); can't do it here because i2c is not ready */ - gpio_request(1, "A_IRDA_OFF"); - gpio_request(11, "A_SWITCH"); - gpio_request(15, "A_USB_ON"); - gpio_direction_output(1, 1); /*A_IRDA_OFF = 1 */ - gpio_direction_output(11, 0); /*A_SWITCH = 0 */ - gpio_direction_output(15, 0); /*A_USB_ON = 0 */ + d = gpiod_get(NULL, "irda_off", GPIOD_OUT_HIGH); + if (IS_ERR(d)) + pr_err("Unable to get IRDA OFF GPIO descriptor\n"); + else + gpiod_put(d); + d = gpiod_get(NULL, "switch", GPIOD_OUT_LOW); + if (IS_ERR(d)) + pr_err("Unable to get SWITCH GPIO descriptor\n"); + else + gpiod_put(d); + d = gpiod_get(NULL, "usb_on", GPIOD_OUT_LOW); + if (IS_ERR(d)) + pr_err("Unable to get USB ON GPIO descriptor\n"); + else + gpiod_put(d); omapfb_set_lcd_config(&sx1_lcd_config); } @@ -338,7 +364,6 @@ MACHINE_START(SX1, "OMAP310 based Siemens SX1") .map_io = omap1_map_io, .init_early = omap1_init_early, .init_irq = omap1_init_irq, - .handle_irq = omap1_handle_irq, .init_machine = omap_sx1_init, .init_late = omap1_init_late, .init_time = omap1_timer_init, diff --git a/arch/arm/mach-omap1/devices.c b/arch/arm/mach-omap1/devices.c index 5304699c7a97eeab2629392958d9f73da6bbf6aa..8b2c5f911e973823cf29d2556c44f149a7821e93 100644 --- a/arch/arm/mach-omap1/devices.c +++ b/arch/arm/mach-omap1/devices.c @@ -6,7 +6,6 @@ */ #include -#include #include #include #include diff --git a/arch/arm/mach-omap1/gpio15xx.c b/arch/arm/mach-omap1/gpio15xx.c index 61fa26efd865340312e12b6fc914c85fbcb6df17..6724af4925f24b573b6b657d04580ec42db0cd43 100644 --- a/arch/arm/mach-omap1/gpio15xx.c +++ b/arch/arm/mach-omap1/gpio15xx.c @@ -8,7 +8,6 @@ * Charulatha V */ -#include #include #include #include diff --git a/arch/arm/mach-omap1/gpio16xx.c b/arch/arm/mach-omap1/gpio16xx.c index cf052714b3f8a65215d281df2e327ca4f4badbe9..55acec22fef4e73f20935473602ef6cb2f4f379c 100644 --- a/arch/arm/mach-omap1/gpio16xx.c +++ b/arch/arm/mach-omap1/gpio16xx.c @@ -8,7 +8,6 @@ * Charulatha V */ -#include #include #include diff --git a/arch/arm/mach-omap1/irq.c b/arch/arm/mach-omap1/irq.c index bfc7ab010ae28d147d9bc6fec79c8749462bda1f..9b587ecebb1cca4d472b5729a303f09bd2c68e1d 100644 --- a/arch/arm/mach-omap1/irq.c +++ b/arch/arm/mach-omap1/irq.c @@ -35,8 +35,8 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include #include +#include #include #include #include @@ -254,4 +254,6 @@ void __init omap1_init_irq(void) ct = irq_data_get_chip_type(d); ct->chip.irq_unmask(d); } + + set_handle_irq(omap1_handle_irq); } diff --git a/arch/arm/mach-omap1/pm.c b/arch/arm/mach-omap1/pm.c index 9761d8404949b58effb0202c16f07ab2c9f7e8d4..6a5815aa05e6aadc42ea4d33fae37ffe16eb9259 100644 --- a/arch/arm/mach-omap1/pm.c +++ b/arch/arm/mach-omap1/pm.c @@ -632,7 +632,7 @@ static int __init omap_pm_init(void) error = sysfs_create_file(power_kobj, &sleep_while_idle_attr.attr); if (error) - printk(KERN_ERR "sysfs_create_file failed: %d\n", error); + pr_err("sysfs_create_file failed: %d\n", error); if (cpu_is_omap16xx()) { /* configure LOW_PWR pin */ diff --git a/arch/arm/mach-omap1/serial.c b/arch/arm/mach-omap1/serial.c index c7f5906457748a208aa136264eec63d77db9c7a2..ffa4a9bece1e9eb0fe213cc02fec067950c47838 100644 --- a/arch/arm/mach-omap1/serial.c +++ b/arch/arm/mach-omap1/serial.c @@ -4,7 +4,8 @@ * * OMAP1 serial support. */ -#include +#include +#include #include #include #include @@ -19,6 +20,7 @@ #include +#include "common.h" #include "serial.h" #include "mux.h" #include "pm.h" @@ -196,39 +198,38 @@ void omap_serial_wake_trigger(int enable) } } -static void __init omap_serial_set_port_wakeup(int gpio_nr) +static void __init omap_serial_set_port_wakeup(int idx) { + struct gpio_desc *d; int ret; - ret = gpio_request(gpio_nr, "UART wake"); - if (ret < 0) { - printk(KERN_ERR "Could not request UART wake GPIO: %i\n", - gpio_nr); + d = gpiod_get_index(NULL, "wakeup", idx, GPIOD_IN); + if (IS_ERR(d)) { + pr_err("Unable to get UART wakeup GPIO descriptor\n"); return; } - gpio_direction_input(gpio_nr); - ret = request_irq(gpio_to_irq(gpio_nr), &omap_serial_wake_interrupt, + ret = request_irq(gpiod_to_irq(d), &omap_serial_wake_interrupt, IRQF_TRIGGER_RISING, "serial wakeup", NULL); if (ret) { - gpio_free(gpio_nr); - printk(KERN_ERR "No interrupt for UART wake GPIO: %i\n", - gpio_nr); + gpiod_put(d); + pr_err("No interrupt for UART%d wake GPIO\n", idx + 1); return; } - enable_irq_wake(gpio_to_irq(gpio_nr)); + enable_irq_wake(gpiod_to_irq(d)); } + int __init omap_serial_wakeup_init(void) { if (!cpu_is_omap16xx()) return 0; if (uart1_ck != NULL) - omap_serial_set_port_wakeup(37); + omap_serial_set_port_wakeup(0); if (uart2_ck != NULL) - omap_serial_set_port_wakeup(18); + omap_serial_set_port_wakeup(1); if (uart3_ck != NULL) - omap_serial_set_port_wakeup(49); + omap_serial_set_port_wakeup(2); return 0; } diff --git a/arch/arm/mach-omap1/sram-init.c b/arch/arm/mach-omap1/sram-init.c index 26427d6be896f24a3aca18898d1fe5c644cd0966..736a72a2b184cb9382367e3f94e4515a4c93771a 100644 --- a/arch/arm/mach-omap1/sram-init.c +++ b/arch/arm/mach-omap1/sram-init.c @@ -23,7 +23,7 @@ #define OMAP1_SRAM_PA 0x20000000 #define SRAM_BOOTLOADER_SZ 0x80 -#define ROUND_DOWN(value,boundary) ((value) & (~((boundary)-1))) +#define ROUND_DOWN(value, boundary) ((value) & (~((boundary) - 1))) static void __iomem *omap_sram_base; static unsigned long omap_sram_start; diff --git a/arch/arm/mach-omap2/board-generic.c b/arch/arm/mach-omap2/board-generic.c index 1610c567a6a3a10302d17898ee6cacf7ba0bfb1a..10d2f078e4a8e87c710889c37dd8b965cd406b38 100644 --- a/arch/arm/mach-omap2/board-generic.c +++ b/arch/arm/mach-omap2/board-generic.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include diff --git a/arch/arm/mach-omap2/board-n8x0.c b/arch/arm/mach-omap2/board-n8x0.c index 3353b0a923d9661796659c7faeff034434907fbf..8e3b5068d4ab07cab11d73bf114b3c3a54f3dae9 100644 --- a/arch/arm/mach-omap2/board-n8x0.c +++ b/arch/arm/mach-omap2/board-n8x0.c @@ -10,7 +10,8 @@ #include #include -#include +#include +#include #include #include #include @@ -28,13 +29,12 @@ #include "common.h" #include "mmc.h" +#include "usb-tusb6010.h" #include "soc.h" #include "common-board-devices.h" #define TUSB6010_ASYNC_CS 1 #define TUSB6010_SYNC_CS 4 -#define TUSB6010_GPIO_INT 58 -#define TUSB6010_GPIO_ENABLE 0 #define TUSB6010_DMACHAN 0x3f #define NOKIA_N810_WIMAX (1 << 2) @@ -61,37 +61,6 @@ static void board_check_revision(void) } #if IS_ENABLED(CONFIG_USB_MUSB_TUSB6010) -/* - * Enable or disable power to TUSB6010. When enabling, turn on 3.3 V and - * 1.5 V voltage regulators of PM companion chip. Companion chip will then - * provide then PGOOD signal to TUSB6010 which will release it from reset. - */ -static int tusb_set_power(int state) -{ - int i, retval = 0; - - if (state) { - gpio_set_value(TUSB6010_GPIO_ENABLE, 1); - msleep(1); - - /* Wait until TUSB6010 pulls INT pin down */ - i = 100; - while (i && gpio_get_value(TUSB6010_GPIO_INT)) { - msleep(1); - i--; - } - - if (!i) { - printk(KERN_ERR "tusb: powerup failed\n"); - retval = -ENODEV; - } - } else { - gpio_set_value(TUSB6010_GPIO_ENABLE, 0); - msleep(10); - } - - return retval; -} static struct musb_hdrc_config musb_config = { .multipoint = 1, @@ -102,39 +71,36 @@ static struct musb_hdrc_config musb_config = { static struct musb_hdrc_platform_data tusb_data = { .mode = MUSB_OTG, - .set_power = tusb_set_power, .min_power = 25, /* x2 = 50 mA drawn from VBUS as peripheral */ .power = 100, /* Max 100 mA VBUS for host mode */ .config = &musb_config, }; +static struct gpiod_lookup_table tusb_gpio_table = { + .dev_id = "musb-tusb", + .table = { + GPIO_LOOKUP("gpio-0-15", 0, "enable", + GPIO_ACTIVE_HIGH), + GPIO_LOOKUP("gpio-48-63", 10, "int", + GPIO_ACTIVE_HIGH), + { } + }, +}; + static void __init n8x0_usb_init(void) { int ret = 0; - static const char announce[] __initconst = KERN_INFO "TUSB 6010\n"; - - /* PM companion chip power control pin */ - ret = gpio_request_one(TUSB6010_GPIO_ENABLE, GPIOF_OUT_INIT_LOW, - "TUSB6010 enable"); - if (ret != 0) { - printk(KERN_ERR "Could not get TUSB power GPIO%i\n", - TUSB6010_GPIO_ENABLE); - return; - } - tusb_set_power(0); + gpiod_add_lookup_table(&tusb_gpio_table); ret = tusb6010_setup_interface(&tusb_data, TUSB6010_REFCLK_19, 2, - TUSB6010_ASYNC_CS, TUSB6010_SYNC_CS, - TUSB6010_GPIO_INT, TUSB6010_DMACHAN); + TUSB6010_ASYNC_CS, TUSB6010_SYNC_CS, + TUSB6010_DMACHAN); if (ret != 0) - goto err; + return; - printk(announce); + pr_info("TUSB 6010\n"); return; - -err: - gpio_free(TUSB6010_GPIO_ENABLE); } #else @@ -170,22 +136,32 @@ static struct spi_board_info n800_spi_board_info[] __initdata = { * GPIO23 and GPIO9 slot 2 EMMC on N810 * */ -#define N8X0_SLOT_SWITCH_GPIO 96 -#define N810_EMMC_VSD_GPIO 23 -#define N810_EMMC_VIO_GPIO 9 - static int slot1_cover_open; static int slot2_cover_open; static struct device *mmc_device; -static int n8x0_mmc_switch_slot(struct device *dev, int slot) -{ -#ifdef CONFIG_MMC_DEBUG - dev_dbg(dev, "Choose slot %d\n", slot + 1); -#endif - gpio_set_value(N8X0_SLOT_SWITCH_GPIO, slot); - return 0; -} +static struct gpiod_lookup_table nokia8xx_mmc_gpio_table = { + .dev_id = "mmci-omap.0", + .table = { + /* Slot switch, GPIO 96 */ + GPIO_LOOKUP("gpio-80-111", 16, + "switch", GPIO_ACTIVE_HIGH), + { } + }, +}; + +static struct gpiod_lookup_table nokia810_mmc_gpio_table = { + .dev_id = "mmci-omap.0", + .table = { + /* Slot index 1, VSD power, GPIO 23 */ + GPIO_LOOKUP_IDX("gpio-16-31", 7, + "vsd", 1, GPIO_ACTIVE_HIGH), + /* Slot index 1, VIO power, GPIO 9 */ + GPIO_LOOKUP_IDX("gpio-0-15", 9, + "vio", 1, GPIO_ACTIVE_HIGH), + { } + }, +}; static int n8x0_mmc_set_power_menelaus(struct device *dev, int slot, int power_on, int vdd) @@ -256,31 +232,13 @@ static int n8x0_mmc_set_power_menelaus(struct device *dev, int slot, return 0; } -static void n810_set_power_emmc(struct device *dev, - int power_on) -{ - dev_dbg(dev, "Set EMMC power %s\n", power_on ? "on" : "off"); - - if (power_on) { - gpio_set_value(N810_EMMC_VSD_GPIO, 1); - msleep(1); - gpio_set_value(N810_EMMC_VIO_GPIO, 1); - msleep(1); - } else { - gpio_set_value(N810_EMMC_VIO_GPIO, 0); - msleep(50); - gpio_set_value(N810_EMMC_VSD_GPIO, 0); - msleep(50); - } -} - static int n8x0_mmc_set_power(struct device *dev, int slot, int power_on, int vdd) { if (board_is_n800() || slot == 0) return n8x0_mmc_set_power_menelaus(dev, slot, power_on, vdd); - n810_set_power_emmc(dev, power_on); + /* The n810 power will be handled by GPIO code in the driver */ return 0; } @@ -418,13 +376,6 @@ static void n8x0_mmc_shutdown(struct device *dev) static void n8x0_mmc_cleanup(struct device *dev) { menelaus_unregister_mmc_callback(); - - gpio_free(N8X0_SLOT_SWITCH_GPIO); - - if (board_is_n810()) { - gpio_free(N810_EMMC_VSD_GPIO); - gpio_free(N810_EMMC_VIO_GPIO); - } } /* @@ -433,7 +384,6 @@ static void n8x0_mmc_cleanup(struct device *dev) */ static struct omap_mmc_platform_data mmc1_data = { .nr_slots = 0, - .switch_slot = n8x0_mmc_switch_slot, .init = n8x0_mmc_late_init, .cleanup = n8x0_mmc_cleanup, .shutdown = n8x0_mmc_shutdown, @@ -463,14 +413,9 @@ static struct omap_mmc_platform_data mmc1_data = { static struct omap_mmc_platform_data *mmc_data[OMAP24XX_NR_MMC]; -static struct gpio n810_emmc_gpios[] __initdata = { - { N810_EMMC_VSD_GPIO, GPIOF_OUT_INIT_LOW, "MMC slot 2 Vddf" }, - { N810_EMMC_VIO_GPIO, GPIOF_OUT_INIT_LOW, "MMC slot 2 Vdd" }, -}; - static void __init n8x0_mmc_init(void) { - int err; + gpiod_add_lookup_table(&nokia8xx_mmc_gpio_table); if (board_is_n810()) { mmc1_data.slots[0].name = "external"; @@ -483,20 +428,7 @@ static void __init n8x0_mmc_init(void) */ mmc1_data.slots[1].name = "internal"; mmc1_data.slots[1].ban_openended = 1; - } - - err = gpio_request_one(N8X0_SLOT_SWITCH_GPIO, GPIOF_OUT_INIT_LOW, - "MMC slot switch"); - if (err) - return; - - if (board_is_n810()) { - err = gpio_request_array(n810_emmc_gpios, - ARRAY_SIZE(n810_emmc_gpios)); - if (err) { - gpio_free(N8X0_SLOT_SWITCH_GPIO); - return; - } + gpiod_add_lookup_table(&nokia810_mmc_gpio_table); } mmc1_data.nr_slots = 2; diff --git a/arch/arm/mach-omap2/omap-wakeupgen.c b/arch/arm/mach-omap2/omap-wakeupgen.c index 8d21e3a3c05fc0bd9a688e25138b1d9fbcba22e6..6f0d6120c174e0b55f24b7d27e2681bc0aafce93 100644 --- a/arch/arm/mach-omap2/omap-wakeupgen.c +++ b/arch/arm/mach-omap2/omap-wakeupgen.c @@ -374,6 +374,7 @@ static void irq_restore_context(void) static void irq_save_secure_context(void) { u32 ret; + ret = omap_secure_dispatcher(OMAP4_HAL_SAVEGIC_INDEX, FLAG_START_CRITICAL, 0, 0, 0, 0, 0); diff --git a/arch/arm/mach-omap2/omap_device.c b/arch/arm/mach-omap2/omap_device.c index 4afa2f08e66811f1ac5994b0f6adbe15c60233ce..fca7869c8075a3c841a56ad745d9dab7877f1866 100644 --- a/arch/arm/mach-omap2/omap_device.c +++ b/arch/arm/mach-omap2/omap_device.c @@ -244,7 +244,6 @@ static int _omap_device_notifier_call(struct notifier_block *nb, case BUS_NOTIFY_ADD_DEVICE: if (pdev->dev.of_node) omap_device_build_from_dt(pdev); - omap_auxdata_legacy_init(dev); fallthrough; default: od = to_omap_device(pdev); diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c index cb33f0382a90d7d0a50443c440708dcbd2311d5c..5cbdf58ad59f70e5e58c34ef72bf9df16cff86b9 100644 --- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c @@ -1851,7 +1851,7 @@ static struct omap_hwmod_ocp_if omap3xxx_l4_core__dss_rfbi = { .fw = { .omap2 = { .l4_fw_region = OMAP3_L4_CORE_FW_DSS_RFBI_REGION, - .l4_prot_group = OMAP3_L4_CORE_FW_DSS_PROT_GROUP , + .l4_prot_group = OMAP3_L4_CORE_FW_DSS_PROT_GROUP, .flags = OMAP_FIREWALL_L4, }, }, @@ -2172,7 +2172,7 @@ static struct omap_hwmod am35xx_emac_hwmod = { /* * According to Mark Greer, the MPU will not return from WFI * when the EMAC signals an interrupt. - * http://www.spinics.net/lists/arm-kernel/msg174734.html + * https://lore.kernel.org/all/1336770778-23044-3-git-send-email-mgreer@animalcreek.com/ */ .flags = (HWMOD_NO_IDLEST | HWMOD_BLOCK_WFI), }; @@ -2346,13 +2346,12 @@ static struct omap_hwmod_ocp_if *omap36xx_sham_hwmod_ocp_ifs[] __initdata = { NULL }; - /* * Apparently the SHA/MD5 and AES accelerator IP blocks are * only present on some AM35xx chips, and no one knows which - * ones. See - * http://www.spinics.net/lists/arm-kernel/msg215466.html So - * if you need these IP blocks on an AM35xx, try uncommenting + * ones. + * See https://lore.kernel.org/all/20130108203853.GB1876@animalcreek.com/ + * So if you need these IP blocks on an AM35xx, try uncommenting * the following lines. */ static struct omap_hwmod_ocp_if *am35xx_sham_hwmod_ocp_ifs[] __initdata = { diff --git a/arch/arm/mach-omap2/omap_phy_internal.c b/arch/arm/mach-omap2/omap_phy_internal.c index 21c6e7929d37a8bb544252d2bd5d9d158c7945f1..a1d001170a683bae10b808eecfdffb6ad12e0b6d 100644 --- a/arch/arm/mach-omap2/omap_phy_internal.c +++ b/arch/arm/mach-omap2/omap_phy_internal.c @@ -1,11 +1,11 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* - * This file configures the internal USB PHY in OMAP4430. Used - * with TWL6030 transceiver and MUSB on OMAP4430. - * - * Copyright (C) 2010 Texas Instruments Incorporated - https://www.ti.com - * Author: Hema HK - */ + * This file configures the internal USB PHY in OMAP4430. Used + * with TWL6030 transceiver and MUSB on OMAP4430. + * + * Copyright (C) 2010 Texas Instruments Incorporated - https://www.ti.com + * Author: Hema HK + */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt diff --git a/arch/arm/mach-omap2/pdata-quirks.c b/arch/arm/mach-omap2/pdata-quirks.c index 04208cc52784ea2f18fc180b6498d7cc79fd4475..c1c0121f478d66b43d262217f573e490891230d5 100644 --- a/arch/arm/mach-omap2/pdata-quirks.c +++ b/arch/arm/mach-omap2/pdata-quirks.c @@ -6,8 +6,8 @@ */ #include #include +#include #include -#include #include #include #include @@ -41,7 +41,6 @@ struct pdata_init { }; static struct of_dev_auxdata omap_auxdata_lookup[]; -static struct twl4030_gpio_platform_data twl_gpio_auxdata; #ifdef CONFIG_MACH_NOKIA_N8X0 static void __init omap2420_n8x0_legacy_init(void) @@ -98,52 +97,43 @@ static struct iommu_platform_data omap3_iommu_isp_pdata = { }; #endif -static int omap3_sbc_t3730_twl_callback(struct device *dev, - unsigned gpio, - unsigned ngpio) +static void __init omap3_sbc_t3x_usb_hub_init(char *hub_name, int idx) { - int res; + struct gpio_desc *d; - res = gpio_request_one(gpio + 2, GPIOF_OUT_INIT_HIGH, - "wlan pwr"); - if (res) - return res; - - gpiod_export(gpio_to_desc(gpio), 0); - - return 0; -} - -static void __init omap3_sbc_t3x_usb_hub_init(int gpio, char *hub_name) -{ - int err = gpio_request_one(gpio, GPIOF_OUT_INIT_LOW, hub_name); - - if (err) { - pr_err("SBC-T3x: %s reset gpio request failed: %d\n", - hub_name, err); + /* This asserts the RESET line (reverse polarity) */ + d = gpiod_get_index(NULL, "reset", idx, GPIOD_OUT_HIGH); + if (IS_ERR(d)) { + pr_err("Unable to get T3x USB reset GPIO descriptor\n"); return; } - - gpiod_export(gpio_to_desc(gpio), 0); - + gpiod_set_consumer_name(d, hub_name); + gpiod_export(d, 0); udelay(10); - gpio_set_value(gpio, 1); + /* De-assert RESET */ + gpiod_set_value(d, 0); msleep(1); } -static void __init omap3_sbc_t3730_twl_init(void) -{ - twl_gpio_auxdata.setup = omap3_sbc_t3730_twl_callback; -} +static struct gpiod_lookup_table omap3_sbc_t3x_usb_gpio_table = { + .dev_id = NULL, + .table = { + GPIO_LOOKUP_IDX("gpio-160-175", 7, "reset", 0, + GPIO_ACTIVE_LOW), + { } + }, +}; static void __init omap3_sbc_t3730_legacy_init(void) { - omap3_sbc_t3x_usb_hub_init(167, "sb-t35 usb hub"); + gpiod_add_lookup_table(&omap3_sbc_t3x_usb_gpio_table); + omap3_sbc_t3x_usb_hub_init("sb-t35 usb hub", 0); } static void __init omap3_sbc_t3530_legacy_init(void) { - omap3_sbc_t3x_usb_hub_init(167, "sb-t35 usb hub"); + gpiod_add_lookup_table(&omap3_sbc_t3x_usb_gpio_table); + omap3_sbc_t3x_usb_hub_init("sb-t35 usb hub", 0); } static void __init omap3_evm_legacy_init(void) @@ -187,31 +177,59 @@ static void __init am35xx_emac_reset(void) omap_ctrl_readl(AM35XX_CONTROL_IP_SW_RESET); /* OCP barrier */ } -static struct gpio cm_t3517_wlan_gpios[] __initdata = { - { 56, GPIOF_OUT_INIT_HIGH, "wlan pwr" }, - { 4, GPIOF_OUT_INIT_HIGH, "xcvr noe" }, +static struct gpiod_lookup_table cm_t3517_wlan_gpio_table = { + .dev_id = NULL, + .table = { + GPIO_LOOKUP("gpio-48-53", 8, "power", + GPIO_ACTIVE_HIGH), + GPIO_LOOKUP("gpio-0-15", 4, "noe", + GPIO_ACTIVE_HIGH), + { } + }, }; static void __init omap3_sbc_t3517_wifi_init(void) { - int err = gpio_request_array(cm_t3517_wlan_gpios, - ARRAY_SIZE(cm_t3517_wlan_gpios)); - if (err) { - pr_err("SBC-T3517: wl12xx gpios request failed: %d\n", err); - return; - } + struct gpio_desc *d; + + gpiod_add_lookup_table(&cm_t3517_wlan_gpio_table); - gpiod_export(gpio_to_desc(cm_t3517_wlan_gpios[0].gpio), 0); - gpiod_export(gpio_to_desc(cm_t3517_wlan_gpios[1].gpio), 0); + /* This asserts the RESET line (reverse polarity) */ + d = gpiod_get(NULL, "power", GPIOD_OUT_HIGH); + if (IS_ERR(d)) { + pr_err("Unable to get CM T3517 WLAN power GPIO descriptor\n"); + } else { + gpiod_set_consumer_name(d, "wlan pwr"); + gpiod_export(d, 0); + } + d = gpiod_get(NULL, "noe", GPIOD_OUT_HIGH); + if (IS_ERR(d)) { + pr_err("Unable to get CM T3517 WLAN XCVR NOE GPIO descriptor\n"); + } else { + gpiod_set_consumer_name(d, "xcvr noe"); + gpiod_export(d, 0); + } msleep(100); - gpio_set_value(cm_t3517_wlan_gpios[1].gpio, 0); -} + gpiod_set_value(d, 0); +} + +static struct gpiod_lookup_table omap3_sbc_t3517_usb_gpio_table = { + .dev_id = NULL, + .table = { + GPIO_LOOKUP_IDX("gpio-144-159", 8, "reset", 0, + GPIO_ACTIVE_LOW), + GPIO_LOOKUP_IDX("gpio-96-111", 2, "reset", 1, + GPIO_ACTIVE_LOW), + { } + }, +}; static void __init omap3_sbc_t3517_legacy_init(void) { - omap3_sbc_t3x_usb_hub_init(152, "cm-t3517 usb hub"); - omap3_sbc_t3x_usb_hub_init(98, "sb-t35 usb hub"); + gpiod_add_lookup_table(&omap3_sbc_t3517_usb_gpio_table); + omap3_sbc_t3x_usb_hub_init("cm-t3517 usb hub", 0); + omap3_sbc_t3x_usb_hub_init("sb-t35 usb hub", 1); am35xx_emac_reset(); hsmmc2_internal_input_clk(); omap3_sbc_t3517_wifi_init(); @@ -393,21 +411,6 @@ static struct ti_prm_platform_data ti_prm_pdata = { .clkdm_lookup = clkdm_lookup, }; -/* - * GPIOs for TWL are initialized by the I2C bus and need custom - * handing until DSS has device tree bindings. - */ -void omap_auxdata_legacy_init(struct device *dev) -{ - if (dev->platform_data) - return; - - if (strcmp("twl4030-gpio", dev_name(dev))) - return; - - dev->platform_data = &twl_gpio_auxdata; -} - #if defined(CONFIG_ARCH_OMAP3) && IS_ENABLED(CONFIG_SND_SOC_OMAP_MCBSP) static struct omap_mcbsp_platform_data mcbsp_pdata; static void __init omap3_mcbsp_init(void) @@ -427,9 +430,6 @@ static struct pdata_init auxdata_quirks[] __initdata = { { "nokia,n800", omap2420_n8x0_legacy_init, }, { "nokia,n810", omap2420_n8x0_legacy_init, }, { "nokia,n810-wimax", omap2420_n8x0_legacy_init, }, -#endif -#ifdef CONFIG_ARCH_OMAP3 - { "compulab,omap3-sbc-t3730", omap3_sbc_t3730_twl_init, }, #endif { /* sentinel */ }, }; diff --git a/arch/arm/mach-omap2/sdrc2xxx.c b/arch/arm/mach-omap2/sdrc2xxx.c index 529d46cfdea269727845a5295ed7eca1ddb17af5..5a275b4fd4046b621c6c46a1ba5387d1674ac309 100644 --- a/arch/arm/mach-omap2/sdrc2xxx.c +++ b/arch/arm/mach-omap2/sdrc2xxx.c @@ -1,7 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * linux/arch/arm/mach-omap2/sdrc2xxx.c - * * SDRAM timing related functions for OMAP2xxx * * Copyright (C) 2005, 2008 Texas Instruments Inc. diff --git a/arch/arm/mach-omap2/sleep33xx.S b/arch/arm/mach-omap2/sleep33xx.S index ac3d0b363c511330775de8498ad0dd13be181dee..3bfd8b5e03ed6b2ab065642c8f3df05ffbfe9c40 100644 --- a/arch/arm/mach-omap2/sleep33xx.S +++ b/arch/arm/mach-omap2/sleep33xx.S @@ -10,7 +10,7 @@ #include #include #include -#include +#include #include "iomap.h" #include "cm33xx.h" diff --git a/arch/arm/mach-omap2/sleep43xx.S b/arch/arm/mach-omap2/sleep43xx.S index 832c913279455855b3ef9441f0c8b70880bee99e..ec0972a48f08d4a6ffe81840eb068bb35dce8d4e 100644 --- a/arch/arm/mach-omap2/sleep43xx.S +++ b/arch/arm/mach-omap2/sleep43xx.S @@ -11,7 +11,7 @@ #include #include #include -#include +#include #include "cm33xx.h" #include "common.h" diff --git a/arch/arm/mach-omap2/sleep44xx.S b/arch/arm/mach-omap2/sleep44xx.S index f60f6a9aed7351532fbe0116a0fa7025e20dc367..f09c9197808b1640c928e34a1edd6a977404f945 100644 --- a/arch/arm/mach-omap2/sleep44xx.S +++ b/arch/arm/mach-omap2/sleep44xx.S @@ -9,7 +9,7 @@ #include #include #include -#include +#include #include #include "omap-secure.h" diff --git a/arch/arm/mach-omap2/sram.c b/arch/arm/mach-omap2/sram.c index 815d390109d21bef4a9af992138c63ff64a1daba..898b011ae8d9037419a09de4db166bc16d6785ab 100644 --- a/arch/arm/mach-omap2/sram.c +++ b/arch/arm/mach-omap2/sram.c @@ -45,7 +45,7 @@ #define GP_DEVICE 0x300 -#define ROUND_DOWN(value,boundary) ((value) & (~((boundary)-1))) +#define ROUND_DOWN(value, boundary) ((value) & (~((boundary) - 1))) static unsigned long omap_sram_start; static unsigned long omap_sram_size; @@ -118,7 +118,7 @@ static void omap_sram_reset(void) */ static int is_sram_locked(void) { - if (OMAP2_DEVICE_TYPE_GP == omap_type()) { + if (omap_type() == OMAP2_DEVICE_TYPE_GP) { /* RAMFW: R/W access to all initiators for all qualifier sets */ if (cpu_is_omap242x()) { writel_relaxed(0xFF, OMAP24XX_VA_REQINFOPERM0); /* all q-vects */ diff --git a/arch/arm/mach-omap2/ti81xx-restart.c b/arch/arm/mach-omap2/ti81xx-restart.c index d6dc518b1dde9b3e640eabda4e703f5bf1abd3b1..5b5fb37caa504f52dac965abb51cd01b0fb7b849 100644 --- a/arch/arm/mach-omap2/ti81xx-restart.c +++ b/arch/arm/mach-omap2/ti81xx-restart.c @@ -26,5 +26,6 @@ void ti81xx_restart(enum reboot_mode mode, const char *cmd) { omap2_prm_set_mod_reg_bits(TI81XX_GLOBAL_RST_COLD, 0, TI81XX_PRM_DEVICE_RSTCTRL); - while (1); + while (1) + ; } diff --git a/arch/arm/mach-omap2/usb-tusb6010.c b/arch/arm/mach-omap2/usb-tusb6010.c index 18fa52f828dc71ce30b8e5c581127944bfd4f7d0..b46c254c2bc41a9ab59d9391b0474982fcd857c5 100644 --- a/arch/arm/mach-omap2/usb-tusb6010.c +++ b/arch/arm/mach-omap2/usb-tusb6010.c @@ -11,12 +11,12 @@ #include #include #include -#include #include #include #include +#include "usb-tusb6010.h" #include "gpmc.h" static u8 async_cs, sync_cs; @@ -132,10 +132,6 @@ static struct resource tusb_resources[] = { { /* Synchronous access */ .flags = IORESOURCE_MEM, }, - { /* IRQ */ - .name = "mc", - .flags = IORESOURCE_IRQ, - }, }; static u64 tusb_dmamask = ~(u32)0; @@ -154,9 +150,9 @@ static struct platform_device tusb_device = { /* this may be called only from board-*.c setup code */ int __init tusb6010_setup_interface(struct musb_hdrc_platform_data *data, - unsigned ps_refclk, unsigned waitpin, - unsigned async, unsigned sync, - unsigned irq, unsigned dmachan) + unsigned int ps_refclk, unsigned int waitpin, + unsigned int async, unsigned int sync, + unsigned int dmachan) { int status; static char error[] __initdata = @@ -192,14 +188,6 @@ int __init tusb6010_setup_interface(struct musb_hdrc_platform_data *data, if (status < 0) return status; - /* IRQ */ - status = gpio_request_one(irq, GPIOF_IN, "TUSB6010 irq"); - if (status < 0) { - printk(error, 3, status); - return status; - } - tusb_resources[2].start = gpio_to_irq(irq); - /* set up memory timings ... can speed them up later */ if (!ps_refclk) { printk(error, 4, status); diff --git a/arch/arm/mach-omap2/usb-tusb6010.h b/arch/arm/mach-omap2/usb-tusb6010.h new file mode 100644 index 0000000000000000000000000000000000000000..d210ff6238c268c9f0d50716047e980542f49eb4 --- /dev/null +++ b/arch/arm/mach-omap2/usb-tusb6010.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef __USB_TUSB6010_H +#define __USB_TUSB6010_H + +extern int __init tusb6010_setup_interface( + struct musb_hdrc_platform_data *data, + unsigned int ps_refclk, unsigned int waitpin, + unsigned int async_cs, unsigned int sync_cs, + unsigned int dmachan); + +#endif /* __USB_TUSB6010_H */ diff --git a/arch/arm/mach-orion5x/board-dt.c b/arch/arm/mach-orion5x/board-dt.c index e3736ffc8347789c8c8ed78ea0d29df62f598c5b..be47492c6640d482fc64de48937a1e98cfd208da 100644 --- a/arch/arm/mach-orion5x/board-dt.c +++ b/arch/arm/mach-orion5x/board-dt.c @@ -60,6 +60,9 @@ static void __init orion5x_dt_init(void) if (of_machine_is_compatible("maxtor,shared-storage-2")) mss2_init(); + if (of_machine_is_compatible("lacie,d2-network")) + d2net_init(); + of_platform_default_populate(NULL, orion5x_auxdata_lookup, NULL); } diff --git a/arch/arm/mach-orion5x/common.h b/arch/arm/mach-orion5x/common.h index f2e0577bf50f4ec25edd138e81448b136e5e6d81..8df70e23aa82a26956575a50c9ff6ea71ade3b99 100644 --- a/arch/arm/mach-orion5x/common.h +++ b/arch/arm/mach-orion5x/common.h @@ -73,6 +73,12 @@ extern void mss2_init(void); static inline void mss2_init(void) {} #endif +#ifdef CONFIG_MACH_D2NET_DT +void d2net_init(void); +#else +static inline void d2net_init(void) {} +#endif + /***************************************************************************** * Helpers to access Orion registers ****************************************************************************/ diff --git a/arch/arm/mach-pxa/generic.h b/arch/arm/mach-pxa/generic.h index 7bb1499de4c5d8d88acba4babd4699e92917fddb..c9c2c46ecead02b4e36b095fe81a2c7473cdedd7 100644 --- a/arch/arm/mach-pxa/generic.h +++ b/arch/arm/mach-pxa/generic.h @@ -27,7 +27,6 @@ extern void __init pxa25x_map_io(void); extern void __init pxa26x_init_irq(void); #define pxa27x_handle_irq ichp_handle_irq -extern unsigned pxa27x_get_clk_frequency_khz(int); extern void __init pxa27x_init_irq(void); extern void __init pxa27x_map_io(void); @@ -52,18 +51,4 @@ extern void pxa2xx_clear_reset_status(unsigned int); static inline void pxa2xx_clear_reset_status(unsigned int mask) {} #endif -/* - * Once fully converted to the clock framework, all these functions should be - * removed, and replaced with a clk_get(NULL, "core"). - */ -#ifdef CONFIG_PXA25x -extern unsigned pxa25x_get_clk_frequency_khz(int); -#else -#define pxa25x_get_clk_frequency_khz(x) (0) -#endif - -#ifdef CONFIG_PXA27x -#else -#define pxa27x_get_clk_frequency_khz(x) (0) -#endif diff --git a/arch/arm/mach-pxa/gumstix.c b/arch/arm/mach-pxa/gumstix.c index 72b08a9bf0fd2a70962c4e943d3acfed851567a5..c9f0f62187bd3e69458128c5000b04880aae56d3 100644 --- a/arch/arm/mach-pxa/gumstix.c +++ b/arch/arm/mach-pxa/gumstix.c @@ -26,7 +26,7 @@ #include #include -#include +#include #include #include #include @@ -233,7 +233,6 @@ MACHINE_START(GUMSTIX, "Gumstix") .map_io = pxa25x_map_io, .nr_irqs = PXA_NR_IRQS, .init_irq = pxa25x_init_irq, - .handle_irq = pxa25x_handle_irq, .init_time = pxa_timer_init, .init_machine = gumstix_init, .restart = pxa_restart, diff --git a/arch/arm/mach-pxa/mfp-pxa2xx.c b/arch/arm/mach-pxa/mfp-pxa2xx.c index b556452dfcf93b4f0c8a1a591d0de1c6628cc641..f5a3d890f682e75fb8a37438c77d1f396f64389e 100644 --- a/arch/arm/mach-pxa/mfp-pxa2xx.c +++ b/arch/arm/mach-pxa/mfp-pxa2xx.c @@ -20,6 +20,7 @@ #include "pxa2xx-regs.h" #include "mfp-pxa2xx.h" +#include "mfp-pxa27x.h" #include "generic.h" diff --git a/arch/arm/mach-pxa/pxa25x.c b/arch/arm/mach-pxa/pxa25x.c index 1b83be181bab3f9eb3a2548c9fb3e583d6f3e635..02712d24be829c29b6d05086ce380fd0f940dd72 100644 --- a/arch/arm/mach-pxa/pxa25x.c +++ b/arch/arm/mach-pxa/pxa25x.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -143,6 +144,7 @@ static int pxa25x_set_wake(struct irq_data *d, unsigned int on) void __init pxa25x_init_irq(void) { pxa_init_irq(32, pxa25x_set_wake); + set_handle_irq(pxa25x_handle_irq); } static int __init __init diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c index 4135ba2877c4f2fd556d4c28271bce2f139052d3..d71491e2e1d6eec4c7c7a6c3c788fa43ceb77803 100644 --- a/arch/arm/mach-pxa/pxa27x.c +++ b/arch/arm/mach-pxa/pxa27x.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -31,7 +32,9 @@ #include "irqs.h" #include "pxa27x.h" #include "reset.h" +#include #include +#include #include "pm.h" #include "addr-map.h" #include "smemc.h" @@ -228,6 +231,7 @@ static int pxa27x_set_wake(struct irq_data *d, unsigned int on) void __init pxa27x_init_irq(void) { pxa_init_irq(34, pxa27x_set_wake); + set_handle_irq(pxa27x_handle_irq); } static int __init diff --git a/arch/arm/mach-pxa/reset.c b/arch/arm/mach-pxa/reset.c index f0be90573ad3248cbfe7fc1e0acd6fd361cc8ea8..27293549f8ad7e592f6cc1e0665d4ad657275469 100644 --- a/arch/arm/mach-pxa/reset.c +++ b/arch/arm/mach-pxa/reset.c @@ -10,6 +10,7 @@ #include "regs-ost.h" #include "reset.h" #include "smemc.h" +#include "generic.h" static void do_hw_reset(void); diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c index 4325bdc2b9ff8b4168b50e361de436caa954a676..d01ea54b0b782063e6016093c6e2eb384feb2684 100644 --- a/arch/arm/mach-pxa/spitz.c +++ b/arch/arm/mach-pxa/spitz.c @@ -506,10 +506,18 @@ static struct ads7846_platform_data spitz_ads7846_info = { .x_plate_ohms = 419, .y_plate_ohms = 486, .pressure_max = 1024, - .gpio_pendown = SPITZ_GPIO_TP_INT, .wait_for_sync = spitz_ads7846_wait_for_hsync, }; +static struct gpiod_lookup_table spitz_ads7846_gpio_table = { + .dev_id = "spi2.0", + .table = { + GPIO_LOOKUP("gpio-pxa", SPITZ_GPIO_TP_INT, + "pendown", GPIO_ACTIVE_LOW), + { } + }, +}; + static void spitz_bl_kick_battery(void) { void (*kick_batt)(void); @@ -594,6 +602,7 @@ static void __init spitz_spi_init(void) else gpiod_add_lookup_table(&spitz_lcdcon_gpio_table); + gpiod_add_lookup_table(&spitz_ads7846_gpio_table); gpiod_add_lookup_table(&spitz_spi_gpio_table); pxa2xx_set_spi_info(2, &spitz_spi_info); spi_register_board_info(ARRAY_AND_SIZE(spitz_spi_devices)); @@ -1043,7 +1052,6 @@ MACHINE_START(SPITZ, "SHARP Spitz") .map_io = pxa27x_map_io, .nr_irqs = PXA_NR_IRQS, .init_irq = pxa27x_init_irq, - .handle_irq = pxa27x_handle_irq, .init_machine = spitz_init, .init_time = pxa_timer_init, .restart = spitz_restart, @@ -1056,7 +1064,6 @@ MACHINE_START(BORZOI, "SHARP Borzoi") .map_io = pxa27x_map_io, .nr_irqs = PXA_NR_IRQS, .init_irq = pxa27x_init_irq, - .handle_irq = pxa27x_handle_irq, .init_machine = spitz_init, .init_time = pxa_timer_init, .restart = spitz_restart, @@ -1069,7 +1076,6 @@ MACHINE_START(AKITA, "SHARP Akita") .map_io = pxa27x_map_io, .nr_irqs = PXA_NR_IRQS, .init_irq = pxa27x_init_irq, - .handle_irq = pxa27x_handle_irq, .init_machine = spitz_init, .init_time = pxa_timer_init, .restart = spitz_restart, diff --git a/arch/arm/mach-pxa/spitz_pm.c b/arch/arm/mach-pxa/spitz_pm.c index 6689b67f9ce5ad400a66f1f6f3cfca9acb408ac9..1c021cef965fb5b5a99485f00be1d9edb28d45e5 100644 --- a/arch/arm/mach-pxa/spitz_pm.c +++ b/arch/arm/mach-pxa/spitz_pm.c @@ -166,7 +166,7 @@ static bool spitz_charger_wakeup(void) gpio_get_value(SPITZ_GPIO_SYNC); } -unsigned long spitzpm_read_devdata(int type) +static unsigned long spitzpm_read_devdata(int type) { switch (type) { case SHARPSL_STATUS_ACIN: diff --git a/arch/arm/mach-rockchip/sleep.S b/arch/arm/mach-rockchip/sleep.S index 3eca3922c944576c9c6aae93cea3a94b24055702..38b6c5186c3c63c2e48370d714771edabdd50d1b 100644 --- a/arch/arm/mach-rockchip/sleep.S +++ b/arch/arm/mach-rockchip/sleep.S @@ -6,7 +6,7 @@ #include #include -#include +#include .data /* diff --git a/arch/arm/mach-s3c/Kconfig.s3c64xx b/arch/arm/mach-s3c/Kconfig.s3c64xx index 01a7a8eec6e80e0c082c026aafda625cbd7b0ba8..8f40af063ad6fdaf7e4e622712ce30cb13f7f851 100644 --- a/arch/arm/mach-s3c/Kconfig.s3c64xx +++ b/arch/arm/mach-s3c/Kconfig.s3c64xx @@ -69,11 +69,6 @@ config S3C64XX_SETUP_I2C1 help Common setup code for i2c bus 1. -config S3C64XX_SETUP_IDE - bool - help - Common setup code for S3C64XX IDE. - config S3C64XX_SETUP_FB_24BPP bool help @@ -110,7 +105,6 @@ config MACH_WLF_CRAGG_6410 select S3C64XX_DEV_SPI0 select S3C64XX_SETUP_FB_24BPP select S3C64XX_SETUP_I2C1 - select S3C64XX_SETUP_IDE select S3C64XX_SETUP_KEYPAD select S3C64XX_SETUP_SDHCI select S3C64XX_SETUP_SPI diff --git a/arch/arm/mach-s3c/mach-crag6410-module.c b/arch/arm/mach-s3c/mach-crag6410-module.c index 4edde13b89b58d041e68e9dc6c73bfdf6dd3813b..8fce1e815ee83ab71385b5a65c31f742b503ec5e 100644 --- a/arch/arm/mach-s3c/mach-crag6410-module.c +++ b/arch/arm/mach-s3c/mach-crag6410-module.c @@ -418,7 +418,7 @@ static struct i2c_driver wlf_gf_module_driver = { .driver = { .name = "wlf-gf-module" }, - .probe_new = wlf_gf_module_probe, + .probe = wlf_gf_module_probe, .id_table = wlf_gf_module_id, }; diff --git a/arch/arm/mach-sa1100/assabet.c b/arch/arm/mach-sa1100/assabet.c index d000c678b4392f29218bcb963cf2cae92181ff24..2b833aa0212b294eecd7a8177d58c7cb50fe6c61 100644 --- a/arch/arm/mach-sa1100/assabet.c +++ b/arch/arm/mach-sa1100/assabet.c @@ -710,7 +710,7 @@ static void __init assabet_map_io(void) sa1100_register_uart(2, 3); } -void __init assabet_init_irq(void) +static void __init assabet_init_irq(void) { u32 def_val; diff --git a/arch/arm/mach-sa1100/pm.c b/arch/arm/mach-sa1100/pm.c index 9a7079f565bd394c4ae1436e8a2b14cd52acba34..9495fc109baa29deb1d6ec5607531e7efe469b96 100644 --- a/arch/arm/mach-sa1100/pm.c +++ b/arch/arm/mach-sa1100/pm.c @@ -29,10 +29,12 @@ #include #include -#include +#include #include #include +#include "generic.h" + extern int sa1100_finish_suspend(unsigned long); #define SAVE(x) sleep_save[SLEEP_SAVE_##x] = x diff --git a/arch/arm/mach-shmobile/headsmp-scu.S b/arch/arm/mach-shmobile/headsmp-scu.S index d0234296ae622b5f1745d9be7002d4705c3e4913..e892ee794d649559cc39d4634f871bd464148773 100644 --- a/arch/arm/mach-shmobile/headsmp-scu.S +++ b/arch/arm/mach-shmobile/headsmp-scu.S @@ -7,7 +7,7 @@ #include #include -#include +#include /* * Boot code for secondary CPUs. diff --git a/arch/arm/mach-shmobile/headsmp.S b/arch/arm/mach-shmobile/headsmp.S index 9466ae61f56abd17726098143c4019789da1b201..a956b489b6ea12caeb667b9531c512b334319352 100644 --- a/arch/arm/mach-shmobile/headsmp.S +++ b/arch/arm/mach-shmobile/headsmp.S @@ -11,7 +11,7 @@ #include #include #include -#include +#include #define SCTLR_MMU 0x01 #define BOOTROM_ADDRESS 0xE6340000 diff --git a/arch/arm/mach-socfpga/headsmp.S b/arch/arm/mach-socfpga/headsmp.S index 54f1844eac031bd165484daec502040fee2a992a..f7e91a772428c8416f37646542754b93a367afcc 100644 --- a/arch/arm/mach-socfpga/headsmp.S +++ b/arch/arm/mach-socfpga/headsmp.S @@ -6,7 +6,7 @@ */ #include #include -#include +#include #include .arch armv7-a diff --git a/arch/arm/mach-spear/pl080.c b/arch/arm/mach-spear/pl080.c index d6b8627d25447abb77e4849385350c5fe6971029..47243a8153d02b387a34071b30221b1d10bf46cf 100644 --- a/arch/arm/mach-spear/pl080.c +++ b/arch/arm/mach-spear/pl080.c @@ -16,6 +16,7 @@ #include #include "spear.h" #include "misc_regs.h" +#include "pl080.h" static spinlock_t lock = __SPIN_LOCK_UNLOCKED(x); diff --git a/arch/arm/mach-spear/spear.h b/arch/arm/mach-spear/spear.h index 432efd407c7633640d7ef24a21fc494be7e843fb..f23eaf1e522f491dc75560f11aa9aca5382a8210 100644 --- a/arch/arm/mach-spear/spear.h +++ b/arch/arm/mach-spear/spear.h @@ -10,7 +10,7 @@ #ifndef __MACH_SPEAR_H #define __MACH_SPEAR_H -#include +#include #if defined(CONFIG_ARCH_SPEAR3XX) || defined (CONFIG_ARCH_SPEAR6XX) diff --git a/arch/arm/mach-sti/Kconfig b/arch/arm/mach-sti/Kconfig index b2d45cf10a3c3f87284d5545fab59f59d0ab0fe6..b3842c971d31b80edaf88ab907f4377bea0a2af5 100644 --- a/arch/arm/mach-sti/Kconfig +++ b/arch/arm/mach-sti/Kconfig @@ -21,7 +21,7 @@ menuconfig ARCH_STI help Include support for STMicroelectronics' STiH415/416, STiH407/10 and STiH418 family SoCs using the Device Tree for discovery. More - information can be found in Documentation/arm/sti/ and + information can be found in Documentation/arch/arm/sti/ and Documentation/devicetree. if ARCH_STI diff --git a/arch/arm/mach-versatile/versatile.c b/arch/arm/mach-versatile/versatile.c index 02ba68abe53309e616ed0073ac0f9c801e52711b..7ef03d0c224d579926309529fc483bcb0d8a49c7 100644 --- a/arch/arm/mach-versatile/versatile.c +++ b/arch/arm/mach-versatile/versatile.c @@ -53,7 +53,7 @@ static void __iomem *versatile_sys_base; -unsigned int mmc_status(struct device *dev) +static unsigned int mmc_status(struct device *dev) { struct amba_device *adev = container_of(dev, struct amba_device, dev); u32 mask; diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig index be183ed1232d6cc84db32a5da4f4bee22769cacc..c164cde50243444c4ab926d5b49a0ab3cbf65ca3 100644 --- a/arch/arm/mm/Kconfig +++ b/arch/arm/mm/Kconfig @@ -712,7 +712,7 @@ config ARM_VIRT_EXT assistance. A compliant bootloader is required in order to make maximum - use of this feature. Refer to Documentation/arm/booting.rst for + use of this feature. Refer to Documentation/arch/arm/booting.rst for details. config SWP_EMULATE @@ -904,7 +904,7 @@ config KUSER_HELPERS the CPU type fitted to the system. This permits binaries to be run on ARMv4 through to ARMv7 without modification. - See Documentation/arm/kernel_user_helpers.rst for details. + See Documentation/arch/arm/kernel_user_helpers.rst for details. However, the fixed address nature of these helpers can be used by ROP (return orientated programming) authors when creating diff --git a/arch/arm/mm/cache-fa.S b/arch/arm/mm/cache-fa.S index 3a464d1649b4b25b8e718be84d1d42d7093646e7..71c64e92deada9c392431c70661aaa2dbd37897f 100644 --- a/arch/arm/mm/cache-fa.S +++ b/arch/arm/mm/cache-fa.S @@ -13,7 +13,6 @@ #include #include #include -#include #include #include "proc-macros.S" diff --git a/arch/arm/mm/cache-v4wb.S b/arch/arm/mm/cache-v4wb.S index 905ac2fa2b1ea27b918f1d3c06960425403ac8fb..ad382cee0fdbd016b7c8a6bfb8dd81fb21cc3dc2 100644 --- a/arch/arm/mm/cache-v4wb.S +++ b/arch/arm/mm/cache-v4wb.S @@ -7,7 +7,6 @@ #include #include #include -#include #include #include "proc-macros.S" diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c index b4a33358d2e9c8c09c55cfe05c46673aa5cc23e7..033a1bce2b175e4c74a33e9f31c3d221d87b2405 100644 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c @@ -25,7 +25,7 @@ #include #include -#include +#include #include #include #include @@ -258,12 +258,14 @@ static struct dma_contig_early_reserve dma_mmu_remap[MAX_CMA_AREAS] __initdata; static int dma_mmu_remap_num __initdata; +#ifdef CONFIG_DMA_CMA void __init dma_contiguous_early_fixup(phys_addr_t base, unsigned long size) { dma_mmu_remap[dma_mmu_remap_num].base = base; dma_mmu_remap[dma_mmu_remap_num].size = size; dma_mmu_remap_num++; } +#endif void __init dma_contiguous_remap(void) { diff --git a/arch/arm/mm/dump.c b/arch/arm/mm/dump.c index 059eb4cdc9c28b8f0d5f07a8b8c8b60700fbc8a1..a9381095ab3662cc6f2e7fdcbedb387c12efeed2 100644 --- a/arch/arm/mm/dump.c +++ b/arch/arm/mm/dump.c @@ -15,7 +15,7 @@ #include #include -#include +#include #include static struct addr_marker address_markers[] = { diff --git a/arch/arm/mm/fault-armv.c b/arch/arm/mm/fault-armv.c index 0e49154454a6f9078870ca38c5bdddd68ab66d18..ca5302b0b7eef94e90e39cbd85b1ef7a83276110 100644 --- a/arch/arm/mm/fault-armv.c +++ b/arch/arm/mm/fault-armv.c @@ -117,8 +117,11 @@ static int adjust_pte(struct vm_area_struct *vma, unsigned long address, * must use the nested version. This also means we need to * open-code the spin-locking. */ - ptl = pte_lockptr(vma->vm_mm, pmd); pte = pte_offset_map(pmd, address); + if (!pte) + return 0; + + ptl = pte_lockptr(vma->vm_mm, pmd); do_pte_lock(ptl); ret = do_adjust_pte(vma, address, pfn, pte); diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c index 2418f1efabd8710d91a9f86b0fbdca59d9818339..fef62e4a9edde6ce1343c8a81e4e65b883e11e83 100644 --- a/arch/arm/mm/fault.c +++ b/arch/arm/mm/fault.c @@ -85,6 +85,9 @@ void show_pte(const char *lvl, struct mm_struct *mm, unsigned long addr) break; pte = pte_offset_map(pmd, addr); + if (!pte) + break; + pr_cont(", *pte=%08llx", (long long)pte_val(*pte)); #ifndef CONFIG_ARM_LPAE pr_cont(", *ppte=%08llx", @@ -232,37 +235,11 @@ static inline bool is_permission_fault(unsigned int fsr) return false; } -static vm_fault_t __kprobes -__do_page_fault(struct mm_struct *mm, unsigned long addr, unsigned int flags, - unsigned long vma_flags, struct pt_regs *regs) -{ - struct vm_area_struct *vma = find_vma(mm, addr); - if (unlikely(!vma)) - return VM_FAULT_BADMAP; - - if (unlikely(vma->vm_start > addr)) { - if (!(vma->vm_flags & VM_GROWSDOWN)) - return VM_FAULT_BADMAP; - if (addr < FIRST_USER_ADDRESS) - return VM_FAULT_BADMAP; - if (expand_stack(vma, addr)) - return VM_FAULT_BADMAP; - } - - /* - * ok, we have a good vm_area for this memory access, check the - * permissions on the VMA allow for the fault which occurred. - */ - if (!(vma->vm_flags & vma_flags)) - return VM_FAULT_BADACCESS; - - return handle_mm_fault(vma, addr & PAGE_MASK, flags, regs); -} - static int __kprobes do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs) { struct mm_struct *mm = current->mm; + struct vm_area_struct *vma; int sig, code; vm_fault_t fault; unsigned int flags = FAULT_FLAG_DEFAULT; @@ -301,31 +278,21 @@ do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs) perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, addr); - /* - * As per x86, we may deadlock here. However, since the kernel only - * validly references user space from well defined areas of the code, - * we can bug out early if this is from code which shouldn't. - */ - if (!mmap_read_trylock(mm)) { - if (!user_mode(regs) && !search_exception_tables(regs->ARM_pc)) - goto no_context; retry: - mmap_read_lock(mm); - } else { - /* - * The above down_read_trylock() might have succeeded in - * which case, we'll have missed the might_sleep() from - * down_read() - */ - might_sleep(); -#ifdef CONFIG_DEBUG_VM - if (!user_mode(regs) && - !search_exception_tables(regs->ARM_pc)) - goto no_context; -#endif + vma = lock_mm_and_find_vma(mm, addr, regs); + if (unlikely(!vma)) { + fault = VM_FAULT_BADMAP; + goto bad_area; } - fault = __do_page_fault(mm, addr, flags, vm_flags, regs); + /* + * ok, we have a good vm_area for this memory access, check the + * permissions on the VMA allow for the fault which occurred. + */ + if (!(vma->vm_flags & vm_flags)) + fault = VM_FAULT_BADACCESS; + else + fault = handle_mm_fault(vma, addr & PAGE_MASK, flags, regs); /* If we need to retry but a fatal signal is pending, handle the * signal first. We do not need to release the mmap_lock because @@ -356,6 +323,7 @@ do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs) if (likely(!(fault & (VM_FAULT_ERROR | VM_FAULT_BADMAP | VM_FAULT_BADACCESS)))) return 0; +bad_area: /* * If we are in kernel mode at this point, we * have no context to handle this fault with. diff --git a/arch/arm/mm/fault.h b/arch/arm/mm/fault.h index 54927ba1fa6ede55ce78ee2da53ab1ef8149eed6..e8f8c190254442a015a6cbc179602589cfddb0ea 100644 --- a/arch/arm/mm/fault.h +++ b/arch/arm/mm/fault.h @@ -37,5 +37,9 @@ static inline int fsr_fs(unsigned int fsr) void do_bad_area(unsigned long addr, unsigned int fsr, struct pt_regs *regs); void early_abt_enable(void); +asmlinkage void do_DataAbort(unsigned long addr, unsigned int fsr, + struct pt_regs *regs); +asmlinkage void do_PrefetchAbort(unsigned long addr, unsigned int ifsr, + struct pt_regs *regs); #endif /* __ARCH_ARM_FAULT_H */ diff --git a/arch/arm/mm/flush.c b/arch/arm/mm/flush.c index 7ff9feea13a6a795c10ece78c46fe70e66efa0c3..2508be91b7a006d7529a50b244dbc010192b199c 100644 --- a/arch/arm/mm/flush.c +++ b/arch/arm/mm/flush.c @@ -354,6 +354,7 @@ EXPORT_SYMBOL(flush_dcache_page); * memcpy() to/from page * if written to page, flush_dcache_page() */ +void __flush_anon_page(struct vm_area_struct *vma, struct page *page, unsigned long vmaddr); void __flush_anon_page(struct vm_area_struct *vma, struct page *page, unsigned long vmaddr) { unsigned long pfn; diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index ce64bdb55a16bc8d5266af40e9c155b8c2ef3569..a42e4cd11db2949875814e23cb21e8a3203ace60 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c @@ -26,7 +26,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/arch/arm/mm/kasan_init.c b/arch/arm/mm/kasan_init.c index 46d9f4a622cbc4c3822a7812cc106462f3e0fa4f..24d71b5db62de43bac5639a325b26fbba16f3f33 100644 --- a/arch/arm/mm/kasan_init.c +++ b/arch/arm/mm/kasan_init.c @@ -17,7 +17,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index 463fc2a8448f0a28725f3f26bf098fa8c504de0b..13fc4bb5f7924b347cdb3246652d8c4be32cf232 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c @@ -21,12 +21,13 @@ #include #include #include +#include #include #include #include #include #include -#include +#include #include #include @@ -37,7 +38,6 @@ #include "fault.h" #include "mm.h" -#include "tcm.h" extern unsigned long __atags_pointer; diff --git a/arch/arm/mm/nommu.c b/arch/arm/mm/nommu.c index 53f2d8774fdb9aaaeb04fe818da08ccfc0bc4803..43cfd06bbebad236b9450bfcb0677221e5d71eb2 100644 --- a/arch/arm/mm/nommu.c +++ b/arch/arm/mm/nommu.c @@ -21,6 +21,7 @@ #include #include #include +#include #include "mm.h" diff --git a/arch/arm/mm/physaddr.c b/arch/arm/mm/physaddr.c index cf75819e4c137618cfe1c5c18ef91e7ede6b98bb..3f263c840ebc462e13c34d33be0161e7a473173d 100644 --- a/arch/arm/mm/physaddr.c +++ b/arch/arm/mm/physaddr.c @@ -6,7 +6,7 @@ #include #include -#include +#include #include #include diff --git a/arch/arm/mm/pmsa-v8.c b/arch/arm/mm/pmsa-v8.c index 8359748a19a11a6a206c59facacc0378704c6cc4..28cdc5468406c447872da251f57f78a224643e34 100644 --- a/arch/arm/mm/pmsa-v8.c +++ b/arch/arm/mm/pmsa-v8.c @@ -11,7 +11,7 @@ #include #include -#include +#include #include #include "mm.h" diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S index 6b4ef9539b68384d618029a6f517f494cf03b635..193c7aeb670391ff27b764d9667baa1ffa1e4992 100644 --- a/arch/arm/mm/proc-v7.S +++ b/arch/arm/mm/proc-v7.S @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include "proc-macros.S" diff --git a/arch/arm/mm/proc-v7m.S b/arch/arm/mm/proc-v7m.S index 335144d50134840887d7dcebdd301bd109a5c3af..d65a12f851a978f573b4fcf09310332553d0def3 100644 --- a/arch/arm/mm/proc-v7m.S +++ b/arch/arm/mm/proc-v7m.S @@ -9,7 +9,7 @@ */ #include #include -#include +#include #include #include "proc-macros.S" diff --git a/arch/arm/mm/pv-fixup-asm.S b/arch/arm/mm/pv-fixup-asm.S index f8e11f7c78807d3dbdfc1d5738a76b995ee53a52..1d9f52c71ad0dfcab86c94a427f072e6f6c3ea9c 100644 --- a/arch/arm/mm/pv-fixup-asm.S +++ b/arch/arm/mm/pv-fixup-asm.S @@ -9,7 +9,7 @@ #include #include #include -#include +#include .section ".idmap.text", "ax" diff --git a/arch/arm/mm/tcm.h b/arch/arm/mm/tcm.h deleted file mode 100644 index 6b80a760d8750ab8940d2fd966e3f7b00e896e10..0000000000000000000000000000000000000000 --- a/arch/arm/mm/tcm.h +++ /dev/null @@ -1,17 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright (C) 2008-2009 ST-Ericsson AB - * TCM memory handling for ARM systems - * - * Author: Linus Walleij - * Author: Rickard Andersson - */ - -#ifdef CONFIG_HAVE_TCM -void __init tcm_init(void); -#else -/* No TCM support, just blank inlines to be optimized out */ -static inline void tcm_init(void) -{ -} -#endif diff --git a/arch/arm/probes/kprobes/checkers-common.c b/arch/arm/probes/kprobes/checkers-common.c index 4d720990cf2a3a8bb5d6723cb51d8ab29f51bc4f..eba7ac4725c02ee8e5d2cc40ab4e599afdc5dea0 100644 --- a/arch/arm/probes/kprobes/checkers-common.c +++ b/arch/arm/probes/kprobes/checkers-common.c @@ -40,7 +40,7 @@ enum probes_insn checker_stack_use_imm_0xx(probes_opcode_t insn, * Different from other insn uses imm8, the real addressing offset of * STRD in T32 encoding should be imm8 * 4. See ARMARM description. */ -enum probes_insn checker_stack_use_t32strd(probes_opcode_t insn, +static enum probes_insn checker_stack_use_t32strd(probes_opcode_t insn, struct arch_probes_insn *asi, const struct decode_header *h) { diff --git a/arch/arm/probes/kprobes/core.c b/arch/arm/probes/kprobes/core.c index 9090c3a74dcceaff4bfc5a0d4ba9ae0952d755e5..d8238da095df7d2890e0d8e14162fdc3315f905a 100644 --- a/arch/arm/probes/kprobes/core.c +++ b/arch/arm/probes/kprobes/core.c @@ -233,7 +233,7 @@ singlestep(struct kprobe *p, struct pt_regs *regs, struct kprobe_ctlblk *kcb) * kprobe, and that level is reserved for user kprobe handlers, so we can't * risk encountering a new kprobe in an interrupt handler. */ -void __kprobes kprobe_handler(struct pt_regs *regs) +static void __kprobes kprobe_handler(struct pt_regs *regs) { struct kprobe *p, *cur; struct kprobe_ctlblk *kcb; diff --git a/arch/arm/probes/kprobes/opt-arm.c b/arch/arm/probes/kprobes/opt-arm.c index dbef34ed933f2a5159597683516d3d27906f7314..7f65048380ca513c60675abf8a3916542c58fa2c 100644 --- a/arch/arm/probes/kprobes/opt-arm.c +++ b/arch/arm/probes/kprobes/opt-arm.c @@ -145,8 +145,6 @@ __arch_remove_optimized_kprobe(struct optimized_kprobe *op, int dirty) } } -extern void kprobe_handler(struct pt_regs *regs); - static void optimized_callback(struct optimized_kprobe *op, struct pt_regs *regs) { diff --git a/arch/arm/probes/kprobes/test-core.c b/arch/arm/probes/kprobes/test-core.c index c562832b86272d9dcc2f2d9d642f5dec93bb09cb..171c7076b89f45c9c0d37d084f03a881980e0112 100644 --- a/arch/arm/probes/kprobes/test-core.c +++ b/arch/arm/probes/kprobes/test-core.c @@ -720,7 +720,7 @@ static const char coverage_register_lookup[16] = { [REG_TYPE_NOSPPCX] = COVERAGE_ANY_REG | COVERAGE_SP, }; -unsigned coverage_start_registers(const struct decode_header *h) +static unsigned coverage_start_registers(const struct decode_header *h) { unsigned regs = 0; int i; diff --git a/arch/arm/probes/kprobes/test-core.h b/arch/arm/probes/kprobes/test-core.h index 56ad3c0aaeeac6dc78462f114f70b4f698dfd87d..c7297037c16235ba55709b7fcea1d91065465d64 100644 --- a/arch/arm/probes/kprobes/test-core.h +++ b/arch/arm/probes/kprobes/test-core.h @@ -454,3 +454,7 @@ void kprobe_thumb32_test_cases(void); #else void kprobe_arm_test_cases(void); #endif + +void __kprobes_test_case_start(void); +void __kprobes_test_case_end_16(void); +void __kprobes_test_case_end_32(void); diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types index 9e74c7ff6b0444a75578148f6fa99080f143dfeb..97e2bfa01f4b674191630c004aaddee22e7523cb 100644 --- a/arch/arm/tools/mach-types +++ b/arch/arm/tools/mach-types @@ -7,7 +7,7 @@ # http://www.arm.linux.org.uk/developer/machines/download.php # # Please do not send patches to this file; it is automatically generated! -# To add an entry into this database, please see Documentation/arm/arm.rst, +# To add an entry into this database, please see Documentation/arch/arm/arm.rst, # or visit: # # http://www.arm.linux.org.uk/developer/machines/?action=new diff --git a/arch/arm/tools/syscall.tbl b/arch/arm/tools/syscall.tbl index ac964612d8b0781f21891cd09a95955de0215288..8ebed8a138747c0a4ace00253eadcc03f302e06b 100644 --- a/arch/arm/tools/syscall.tbl +++ b/arch/arm/tools/syscall.tbl @@ -464,3 +464,4 @@ 448 common process_mrelease sys_process_mrelease 449 common futex_waitv sys_futex_waitv 450 common set_mempolicy_home_node sys_set_mempolicy_home_node +451 common cachestat sys_cachestat diff --git a/arch/arm/vdso/vgettimeofday.c b/arch/arm/vdso/vgettimeofday.c index 1976c6f325a40117105419251976971e90eda268..a003beacac761c51ea8055f40f11734ff0acd5dd 100644 --- a/arch/arm/vdso/vgettimeofday.c +++ b/arch/arm/vdso/vgettimeofday.c @@ -6,6 +6,8 @@ */ #include #include +#include +#include int __vdso_clock_gettime(clockid_t clock, struct old_timespec32 *ts) diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c index 349dcb944a937a72907d60eb0020c963b040afdd..1ba5078c10258b2b0ae1b334796bf5c78a431445 100644 --- a/arch/arm/vfp/vfpmodule.c +++ b/arch/arm/vfp/vfpmodule.c @@ -25,6 +25,7 @@ #include #include #include +#include #include "vfpinstr.h" #include "vfp.h" diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 343e1e1cae10a3d51098b2ad7b9f1d457fcca2a5..a2511b30d0f676b5c70f4b98a78ea024ce79de19 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -120,6 +120,7 @@ config ARM64 select CRC32 select DCACHE_WORD_ACCESS select DYNAMIC_FTRACE if FUNCTION_TRACER + select DMA_BOUNCE_UNALIGNED_KMALLOC select DMA_DIRECT_REMAP select EDAC_SUPPORT select FRAME_POINTER @@ -196,19 +197,26 @@ config ARM64 !CC_OPTIMIZE_FOR_SIZE) select FTRACE_MCOUNT_USE_PATCHABLE_FUNCTION_ENTRY \ if DYNAMIC_FTRACE_WITH_ARGS + select HAVE_SAMPLE_FTRACE_DIRECT + select HAVE_SAMPLE_FTRACE_DIRECT_MULTI select HAVE_EFFICIENT_UNALIGNED_ACCESS select HAVE_FAST_GUP select HAVE_FTRACE_MCOUNT_RECORD select HAVE_FUNCTION_TRACER select HAVE_FUNCTION_ERROR_INJECTION + select HAVE_FUNCTION_GRAPH_RETVAL if HAVE_FUNCTION_GRAPH_TRACER select HAVE_FUNCTION_GRAPH_TRACER select HAVE_GCC_PLUGINS + select HAVE_HARDLOCKUP_DETECTOR_PERF if PERF_EVENTS && \ + HW_PERF_EVENTS && HAVE_PERF_EVENTS_NMI select HAVE_HW_BREAKPOINT if PERF_EVENTS select HAVE_IOREMAP_PROT select HAVE_IRQ_TIME_ACCOUNTING select HAVE_KVM + select HAVE_MOD_ARCH_SPECIFIC select HAVE_NMI select HAVE_PERF_EVENTS + select HAVE_PERF_EVENTS_NMI if ARM64_PSEUDO_NMI select HAVE_PERF_REGS select HAVE_PERF_USER_STACK_DUMP select HAVE_PREEMPT_DYNAMIC_KEY @@ -222,9 +230,11 @@ config ARM64 select HAVE_KPROBES select HAVE_KRETPROBES select HAVE_GENERIC_VDSO + select HOTPLUG_CORE_SYNC_DEAD if HOTPLUG_CPU select IRQ_DOMAIN select IRQ_FORCED_THREADING select KASAN_VMALLOC if KASAN + select LOCK_MM_AND_FIND_VMA select MODULES_USE_ELF_RELA select NEED_DMA_MAP_STATE select NEED_SG_DMA_LENGTH @@ -406,6 +416,25 @@ menu "Kernel Features" menu "ARM errata workarounds via the alternatives framework" +config AMPERE_ERRATUM_AC03_CPU_38 + bool "AmpereOne: AC03_CPU_38: Certain bits in the Virtualization Translation Control Register and Translation Control Registers do not follow RES0 semantics" + default y + help + This option adds an alternative code sequence to work around Ampere + erratum AC03_CPU_38 on AmpereOne. + + The affected design reports FEAT_HAFDBS as not implemented in + ID_AA64MMFR1_EL1.HAFDBS, but (V)TCR_ELx.{HA,HD} are not RES0 + as required by the architecture. The unadvertised HAFDBS + implementation suffers from an additional erratum where hardware + A/D updates can occur after a PTE has been marked invalid. + + The workaround forces KVM to explicitly set VTCR_EL2.HA to 0, + which avoids enabling unadvertised hardware Access Flag management + at stage-2. + + If unsure, say Y. + config ARM64_WORKAROUND_CLEAN_CACHE bool @@ -577,7 +606,6 @@ config ARM64_ERRATUM_845719 config ARM64_ERRATUM_843419 bool "Cortex-A53: 843419: A load or store might access an incorrect address" default y - select ARM64_MODULE_PLTS if MODULES help This option links the kernel with '--fix-cortex-a53-843419' and enables PLT support to replace certain ADRP instructions, which can @@ -1585,7 +1613,7 @@ config ARM64_TAGGED_ADDR_ABI When this option is enabled, user applications can opt in to a relaxed ABI via prctl() allowing tagged addresses to be passed to system calls as pointer arguments. For details, see - Documentation/arm64/tagged-address-abi.rst. + Documentation/arch/arm64/tagged-address-abi.rst. menuconfig COMPAT bool "Kernel support for 32-bit EL0" @@ -1619,7 +1647,7 @@ config KUSER_HELPERS the system. This permits binaries to be run on ARMv4 through to ARMv8 without modification. - See Documentation/arm/kernel_user_helpers.rst for details. + See Documentation/arch/arm/kernel_user_helpers.rst for details. However, the fixed address nature of these helpers can be used by ROP (return orientated programming) authors when creating @@ -2047,7 +2075,7 @@ config ARM64_MTE explicitly opt in. The mechanism for the userspace is described in: - Documentation/arm64/memory-tagging-extension.rst. + Documentation/arch/arm64/memory-tagging-extension.rst. endmenu # "ARMv8.5 architectural features" @@ -2107,26 +2135,6 @@ config ARM64_SME register state capable of holding two dimensional matrix tiles to enable various matrix operations. -config ARM64_MODULE_PLTS - bool "Use PLTs to allow module memory to spill over into vmalloc area" - depends on MODULES - select HAVE_MOD_ARCH_SPECIFIC - help - Allocate PLTs when loading modules so that jumps and calls whose - targets are too far away for their relative offsets to be encoded - in the instructions themselves can be bounced via veneers in the - module's PLT. This allows modules to be allocated in the generic - vmalloc area after the dedicated module memory area has been - exhausted. - - When running with address space randomization (KASLR), the module - region itself may be too far away for ordinary relative jumps and - calls, and so in that case, module PLTs are required and cannot be - disabled. - - Specific errata workaround(s) might also force module PLTs to be - enabled (ARM64_ERRATUM_843419). - config ARM64_PSEUDO_NMI bool "Support for NMI-like interrupts" select ARM_GIC_V3 @@ -2167,7 +2175,6 @@ config RELOCATABLE config RANDOMIZE_BASE bool "Randomize the address of the kernel image" - select ARM64_MODULE_PLTS if MODULES select RELOCATABLE help Randomizes the virtual address at which the kernel image is @@ -2198,9 +2205,8 @@ config RANDOMIZE_MODULE_REGION_FULL When this option is not set, the module region will be randomized over a limited range that contains the [_stext, _etext] interval of the core kernel, so branch relocations are almost always in range unless - ARM64_MODULE_PLTS is enabled and the region is exhausted. In this - particular case of region exhaustion, modules might be able to fall - back to a larger 2GB area. + the region is exhausted. In this particular case of region + exhaustion, modules might be able to fall back to a larger 2GB area. config CC_HAVE_STACKPROTECTOR_SYSREG def_bool $(cc-option,-mstack-protector-guard=sysreg -mstack-protector-guard-reg=sp_el0 -mstack-protector-guard-offset=0) diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms index 89a0b13b058d6281412545565e5f65235506b1aa..6069120199bbcaf26800641174b423ee84cc30fd 100644 --- a/arch/arm64/Kconfig.platforms +++ b/arch/arm64/Kconfig.platforms @@ -225,6 +225,14 @@ config ARCH_S32 endif +config ARCH_MA35 + bool "Nuvoton MA35 Architecture" + select GPIOLIB + select PINCTRL + select RESET_CONTROLLER + help + This enables support for the ARMv8 based Nuvoton MA35 series SoCs. + config ARCH_NPCM bool "Nuvoton NPCM Architecture" select PINCTRL @@ -277,6 +285,20 @@ config ARCH_INTEL_SOCFPGA Stratix 10 (ex. Altera), Stratix10 Software Virtual Platform, Agilex and eASIC N5X. +config ARCH_STM32 + bool "STMicroelectronics STM32 SoC Family" + select GPIOLIB + select PINCTRL + select PINCTRL_STM32MP257 + select ARM_SMC_MBOX + select ARM_SCMI_PROTOCOL + select COMMON_CLK_SCMI + help + This enables support for ARMv8 based STMicroelectronics + STM32 family, including: + - STM32MP25: + - STM32MP251, STM32MP253, STM32MP255 and STM32MP257. + config ARCH_SYNQUACER bool "Socionext SynQuacer SoC Family" select IRQ_FASTEOI_HIERARCHY_HANDLERS diff --git a/arch/arm64/boot/dts/Makefile b/arch/arm64/boot/dts/Makefile index 7b107fa7414bf212827dc9a15c0e010f66453548..30dd6347a929ecc628cd30a69967944f171142ab 100644 --- a/arch/arm64/boot/dts/Makefile +++ b/arch/arm64/boot/dts/Makefile @@ -27,6 +27,7 @@ subdir-y += renesas subdir-y += rockchip subdir-y += socionext subdir-y += sprd +subdir-y += st subdir-y += synaptics subdir-y += tesla subdir-y += ti diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi index 62f45f71ec654aae960c470288d1eb46e3946ad5..57ac18738c995ba7cdb686b0adc1eb9549690110 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi +++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi @@ -93,6 +93,7 @@ L2: l2-cache { compatible = "cache"; cache-level = <2>; + cache-unified; }; }; @@ -407,7 +408,7 @@ interrupts = ; clocks = <&ccu CLK_BUS_TCON0>, <&ccu CLK_TCON0>; clock-names = "ahb", "tcon-ch0"; - clock-output-names = "tcon-pixel-clock"; + clock-output-names = "tcon-data-clock"; #clock-cells = <0>; resets = <&ccu RST_BUS_TCON0>, <&ccu RST_BUS_LVDS>; reset-names = "lcd", "lvds"; diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h5-bananapi-m2-plus-v1.2.dts b/arch/arm64/boot/dts/allwinner/sun50i-h5-bananapi-m2-plus-v1.2.dts index 8857a3791593fb787a6d207bbc579c5f4cfdb67b..6406a29c85f2a064da8ed8059d946fa88cf7861e 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-h5-bananapi-m2-plus-v1.2.dts +++ b/arch/arm64/boot/dts/allwinner/sun50i-h5-bananapi-m2-plus-v1.2.dts @@ -4,7 +4,7 @@ /dts-v1/; #include "sun50i-h5.dtsi" #include "sun50i-h5-cpu-opp.dtsi" -#include +#include / { model = "Banana Pi BPI-M2-Plus v1.2 H5"; diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h5-bananapi-m2-plus.dts b/arch/arm64/boot/dts/allwinner/sun50i-h5-bananapi-m2-plus.dts index 77661006dfba148d02e266554d31200b8d35ccd2..cfb943e9ae85aa5b78287636e6601136a3a6c122 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-h5-bananapi-m2-plus.dts +++ b/arch/arm64/boot/dts/allwinner/sun50i-h5-bananapi-m2-plus.dts @@ -3,7 +3,7 @@ /dts-v1/; #include "sun50i-h5.dtsi" -#include +#include / { model = "Banana Pi BPI-M2-Plus H5"; diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h5-emlid-neutis-n5.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h5-emlid-neutis-n5.dtsi index fc570011495f39c3e52a42eccda0dce936938694..2f4b46746f47c638ddb2d1de11e61a6af92b8d61 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-h5-emlid-neutis-n5.dtsi +++ b/arch/arm64/boot/dts/allwinner/sun50i-h5-emlid-neutis-n5.dtsi @@ -8,4 +8,4 @@ /dts-v1/; #include "sun50i-h5.dtsi" -#include +#include diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h5-libretech-all-h3-cc.dts b/arch/arm64/boot/dts/allwinner/sun50i-h5-libretech-all-h3-cc.dts index d811df332824b53882a76678d29203d9e6403da7..b79018c65cae1f1e35fcefd63899068a3d1231ba 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-h5-libretech-all-h3-cc.dts +++ b/arch/arm64/boot/dts/allwinner/sun50i-h5-libretech-all-h3-cc.dts @@ -5,7 +5,7 @@ /dts-v1/; #include "sun50i-h5.dtsi" #include "sun50i-h5-cpu-opp.dtsi" -#include +#include / { model = "Libre Computer Board ALL-H3-CC H5"; diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h5-libretech-all-h3-it.dts b/arch/arm64/boot/dts/allwinner/sun50i-h5-libretech-all-h3-it.dts index e59d68b525fc936579fbd76e78e3e27312c07fef..dc657de2a1a408f2dd689e64126db18f5b6dad51 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-h5-libretech-all-h3-it.dts +++ b/arch/arm64/boot/dts/allwinner/sun50i-h5-libretech-all-h3-it.dts @@ -3,7 +3,7 @@ /dts-v1/; #include "sun50i-h5.dtsi" -#include +#include / { model = "Libre Computer Board ALL-H3-IT H5"; diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi index a56fae761a1f3468329c9a0dd2261b9cba4dae92..d3caf27b6a55c59827048fa1d8004afc9770625f 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi +++ b/arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi @@ -1,7 +1,7 @@ // SPDX-License-Identifier: (GPL-2.0+ OR MIT) // Copyright (C) 2016 ARM Ltd. -#include +#include #include diff --git a/arch/arm64/boot/dts/amazon/alpine-v3.dtsi b/arch/arm64/boot/dts/amazon/alpine-v3.dtsi index 73a352ea8fd5c2402e5ccbdee739f744e129d94c..39481d7fd7d4da806fe1ab1e4b2320cc732f37d5 100644 --- a/arch/arm64/boot/dts/amazon/alpine-v3.dtsi +++ b/arch/arm64/boot/dts/amazon/alpine-v3.dtsi @@ -250,6 +250,7 @@ cache-line-size = <64>; cache-sets = <2048>; cache-level = <2>; + cache-unified; }; cluster1_l2: cache@100 { @@ -258,6 +259,7 @@ cache-line-size = <64>; cache-sets = <2048>; cache-level = <2>; + cache-unified; }; cluster2_l2: cache@200 { @@ -266,6 +268,7 @@ cache-line-size = <64>; cache-sets = <2048>; cache-level = <2>; + cache-unified; }; cluster3_l2: cache@300 { @@ -274,6 +277,7 @@ cache-line-size = <64>; cache-sets = <2048>; cache-level = <2>; + cache-unified; }; }; diff --git a/arch/arm64/boot/dts/amlogic/Makefile b/arch/arm64/boot/dts/amlogic/Makefile index cd1c5b04890a306ad78a33e929e3ce5178e661e2..6f61798a109f4822c9dbf4c810c16dd9152a4c1f 100644 --- a/arch/arm64/boot/dts/amlogic/Makefile +++ b/arch/arm64/boot/dts/amlogic/Makefile @@ -1,4 +1,5 @@ # SPDX-License-Identifier: GPL-2.0 +dtb-$(CONFIG_ARCH_MESON) += amlogic-c3-c302x-aw409.dtb dtb-$(CONFIG_ARCH_MESON) += meson-a1-ad401.dtb dtb-$(CONFIG_ARCH_MESON) += meson-axg-jethome-jethub-j100.dtb dtb-$(CONFIG_ARCH_MESON) += meson-axg-jethome-jethub-j110-rev-2.dtb diff --git a/arch/arm64/boot/dts/amlogic/amlogic-c3-c302x-aw409.dts b/arch/arm64/boot/dts/amlogic/amlogic-c3-c302x-aw409.dts new file mode 100644 index 0000000000000000000000000000000000000000..edce8850b33860baa1e9b0be062c1a9480bc5bf6 --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/amlogic-c3-c302x-aw409.dts @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2021 Amlogic, Inc. All rights reserved. + */ + +/dts-v1/; + +#include "amlogic-c3.dtsi" + +/ { + model = "Amlogic C302 aw409 Development Board"; + compatible = "amlogic,aw409", "amlogic,c3"; + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + aliases { + serial0 = &uart_b; + }; + + memory@0 { + device_type = "memory"; + reg = <0x0 0x0 0x0 0x10000000>; + }; +}; + +&uart_b { + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/amlogic/amlogic-c3.dtsi b/arch/arm64/boot/dts/amlogic/amlogic-c3.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..60ad4f3eef9d77d65de09e600601520ea76830de --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/amlogic-c3.dtsi @@ -0,0 +1,87 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2021 Amlogic, Inc. All rights reserved. + */ + +#include +#include +#include + +/ { + cpus { + #address-cells = <2>; + #size-cells = <0>; + + cpu0: cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a35"; + reg = <0x0 0x0>; + enable-method = "psci"; + }; + + cpu1: cpu@1 { + device_type = "cpu"; + compatible = "arm,cortex-a35"; + reg = <0x0 0x1>; + enable-method = "psci"; + }; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts = , + , + , + ; + }; + + psci { + compatible = "arm,psci-1.0"; + method = "smc"; + }; + + xtal: xtal-clk { + compatible = "fixed-clock"; + clock-frequency = <24000000>; + clock-output-names = "xtal"; + #clock-cells = <0>; + }; + + soc { + compatible = "simple-bus"; + #address-cells = <2>; + #size-cells = <2>; + ranges; + + gic: interrupt-controller@fff01000 { + compatible = "arm,gic-400"; + #interrupt-cells = <3>; + #address-cells = <0>; + interrupt-controller; + reg = <0x0 0xfff01000 0 0x1000>, + <0x0 0xfff02000 0 0x2000>, + <0x0 0xfff04000 0 0x2000>, + <0x0 0xfff06000 0 0x2000>; + interrupts = ; + }; + + apb4: bus@fe000000 { + compatible = "simple-bus"; + reg = <0x0 0xfe000000 0x0 0x480000>; + #address-cells = <2>; + #size-cells = <2>; + ranges = <0x0 0x0 0x0 0xfe000000 0x0 0x480000>; + + uart_b: serial@7a000 { + compatible = "amlogic,meson-s4-uart", + "amlogic,meson-ao-uart"; + reg = <0x0 0x7a000 0x0 0x18>; + interrupts = ; + status = "disabled"; + clocks = <&xtal>, <&xtal>, <&xtal>; + clock-names = "xtal", "pclk", "baud"; + }; + + }; + }; +}; diff --git a/arch/arm64/boot/dts/amlogic/meson-a1.dtsi b/arch/arm64/boot/dts/amlogic/meson-a1.dtsi index eed96f262844158c9bb3a7e3206b815d74580ff4..c8f344596285ec8d188d0596ac2b0ec72d5445e3 100644 --- a/arch/arm64/boot/dts/amlogic/meson-a1.dtsi +++ b/arch/arm64/boot/dts/amlogic/meson-a1.dtsi @@ -37,6 +37,7 @@ l2: l2-cache0 { compatible = "cache"; cache-level = <2>; + cache-unified; }; }; diff --git a/arch/arm64/boot/dts/amlogic/meson-axg.dtsi b/arch/arm64/boot/dts/amlogic/meson-axg.dtsi index b984950591e2f6cc09c891321cb20d1d2a5ab0a9..768d0ed78dbe637af76f5c420ba8f7a0fb495491 100644 --- a/arch/arm64/boot/dts/amlogic/meson-axg.dtsi +++ b/arch/arm64/boot/dts/amlogic/meson-axg.dtsi @@ -106,6 +106,7 @@ l2: l2-cache0 { compatible = "cache"; cache-level = <2>; + cache-unified; }; }; diff --git a/arch/arm64/boot/dts/amlogic/meson-g12a.dtsi b/arch/arm64/boot/dts/amlogic/meson-g12a.dtsi index f58fd2a6fe61cb8be93b64f922a2f6b1754fc73b..543e70669df54afab046c09e9c154e8956eda5f0 100644 --- a/arch/arm64/boot/dts/amlogic/meson-g12a.dtsi +++ b/arch/arm64/boot/dts/amlogic/meson-g12a.dtsi @@ -51,6 +51,7 @@ l2: l2-cache0 { compatible = "cache"; cache-level = <2>; + cache-unified; }; }; diff --git a/arch/arm64/boot/dts/amlogic/meson-g12b.dtsi b/arch/arm64/boot/dts/amlogic/meson-g12b.dtsi index 431572b384db92152b98d3bbbc878cdb02d89231..86e6ceb31d5e2683644d078f0605091b5847ba7f 100644 --- a/arch/arm64/boot/dts/amlogic/meson-g12b.dtsi +++ b/arch/arm64/boot/dts/amlogic/meson-g12b.dtsi @@ -106,6 +106,7 @@ l2: l2-cache0 { compatible = "cache"; cache-level = <2>; + cache-unified; }; }; }; diff --git a/arch/arm64/boot/dts/amlogic/meson-gx.dtsi b/arch/arm64/boot/dts/amlogic/meson-gx.dtsi index 11f89bfecb56a8bf9c17a736bd4ed6cd24932847..2673f0dbafe76456d03617014d61ce0105746376 100644 --- a/arch/arm64/boot/dts/amlogic/meson-gx.dtsi +++ b/arch/arm64/boot/dts/amlogic/meson-gx.dtsi @@ -133,6 +133,7 @@ l2: l2-cache0 { compatible = "cache"; cache-level = <2>; + cache-unified; }; }; diff --git a/arch/arm64/boot/dts/amlogic/meson-sm1.dtsi b/arch/arm64/boot/dts/amlogic/meson-sm1.dtsi index 617d322af0df8d9fea0c8a0611165b616fa9598c..643f94d9d08e107a7c1ea6f689a910f06804e342 100644 --- a/arch/arm64/boot/dts/amlogic/meson-sm1.dtsi +++ b/arch/arm64/boot/dts/amlogic/meson-sm1.dtsi @@ -89,6 +89,7 @@ l2: l2-cache0 { compatible = "cache"; cache-level = <2>; + cache-unified; }; }; diff --git a/arch/arm64/boot/dts/apm/apm-shadowcat.dtsi b/arch/arm64/boot/dts/apm/apm-shadowcat.dtsi index 70a10bcafcffc7f8bbe51a63c53cec289ea3e403..377660d705d1ae3eb75ee7aa2337f059789bc167 100644 --- a/arch/arm64/boot/dts/apm/apm-shadowcat.dtsi +++ b/arch/arm64/boot/dts/apm/apm-shadowcat.dtsi @@ -97,15 +97,23 @@ }; xgene_L2_0: l2-cache-0 { compatible = "cache"; + cache-level = <2>; + cache-unified; }; xgene_L2_1: l2-cache-1 { compatible = "cache"; + cache-level = <2>; + cache-unified; }; xgene_L2_2: l2-cache-2 { compatible = "cache"; + cache-level = <2>; + cache-unified; }; xgene_L2_3: l2-cache-3 { compatible = "cache"; + cache-level = <2>; + cache-unified; }; }; diff --git a/arch/arm64/boot/dts/apm/apm-storm.dtsi b/arch/arm64/boot/dts/apm/apm-storm.dtsi index d73e809fe41a8616d731ce6a275a98b678d4e596..efa79209f4b2c0ddee7017d57e11674ab25530a6 100644 --- a/arch/arm64/boot/dts/apm/apm-storm.dtsi +++ b/arch/arm64/boot/dts/apm/apm-storm.dtsi @@ -81,15 +81,23 @@ }; xgene_L2_0: l2-cache-0 { compatible = "cache"; + cache-level = <2>; + cache-unified; }; xgene_L2_1: l2-cache-1 { compatible = "cache"; + cache-level = <2>; + cache-unified; }; xgene_L2_2: l2-cache-2 { compatible = "cache"; + cache-level = <2>; + cache-unified; }; xgene_L2_3: l2-cache-3 { compatible = "cache"; + cache-level = <2>; + cache-unified; }; }; diff --git a/arch/arm64/boot/dts/arm/vexpress-v2f-1xv7-ca53x2.dts b/arch/arm64/boot/dts/arm/vexpress-v2f-1xv7-ca53x2.dts index 7bdeb965f0a964f3dd77d9c6d39717b4b9b00201..8db4243a494728fed2833d60edfb94e282c66ed0 100644 --- a/arch/arm64/boot/dts/arm/vexpress-v2f-1xv7-ca53x2.dts +++ b/arch/arm64/boot/dts/arm/vexpress-v2f-1xv7-ca53x2.dts @@ -13,7 +13,7 @@ /dts-v1/; #include -#include "vexpress-v2m-rs1.dtsi" +#include "arm/arm/vexpress-v2m-rs1.dtsi" / { model = "V2F-1XV7 Cortex-A53x2 SMM"; diff --git a/arch/arm64/boot/dts/broadcom/Makefile b/arch/arm64/boot/dts/broadcom/Makefile index 05d8c5ecf3b0f546e25b8b397bac0481442ad2c0..8b4591ddd27ccc9beac5e3aa5b634a962e10a0d4 100644 --- a/arch/arm64/boot/dts/broadcom/Makefile +++ b/arch/arm64/boot/dts/broadcom/Makefile @@ -1,4 +1,8 @@ # SPDX-License-Identifier: GPL-2.0 + +# Enables support for device-tree overlays +DTC_FLAGS := -@ + dtb-$(CONFIG_ARCH_BCM2835) += bcm2711-rpi-400.dtb \ bcm2711-rpi-4-b.dtb \ bcm2711-rpi-cm4-io.dtb \ diff --git a/arch/arm64/boot/dts/broadcom/bcm2711-rpi-4-b.dts b/arch/arm64/boot/dts/broadcom/bcm2711-rpi-4-b.dts index d24c53682e44903f4ed9c5c62df456cb69c67b73..c7280bdefa8d6c685438c13e8e3d17cfc9be0a19 100644 --- a/arch/arm64/boot/dts/broadcom/bcm2711-rpi-4-b.dts +++ b/arch/arm64/boot/dts/broadcom/bcm2711-rpi-4-b.dts @@ -1,2 +1,2 @@ // SPDX-License-Identifier: GPL-2.0 -#include "arm/bcm2711-rpi-4-b.dts" +#include "arm/broadcom/bcm2711-rpi-4-b.dts" diff --git a/arch/arm64/boot/dts/broadcom/bcm2711-rpi-400.dts b/arch/arm64/boot/dts/broadcom/bcm2711-rpi-400.dts index b9000f58beb55992c7c8fb4124bab898cf0e0361..d9d2852b794f006cad689413e14ee2f2cfafc562 100644 --- a/arch/arm64/boot/dts/broadcom/bcm2711-rpi-400.dts +++ b/arch/arm64/boot/dts/broadcom/bcm2711-rpi-400.dts @@ -1,2 +1,2 @@ // SPDX-License-Identifier: GPL-2.0 -#include "arm/bcm2711-rpi-400.dts" +#include "arm/broadcom/bcm2711-rpi-400.dts" diff --git a/arch/arm64/boot/dts/broadcom/bcm2711-rpi-cm4-io.dts b/arch/arm64/boot/dts/broadcom/bcm2711-rpi-cm4-io.dts index e36d395e3951006a37c589a0aa7b3a1ca402d5fa..8810322aa66aeeb7409012738e6b3e5c395f92d1 100644 --- a/arch/arm64/boot/dts/broadcom/bcm2711-rpi-cm4-io.dts +++ b/arch/arm64/boot/dts/broadcom/bcm2711-rpi-cm4-io.dts @@ -1,2 +1,2 @@ // SPDX-License-Identifier: GPL-2.0 -#include "arm/bcm2711-rpi-cm4-io.dts" +#include "arm/broadcom/bcm2711-rpi-cm4-io.dts" diff --git a/arch/arm64/boot/dts/broadcom/bcm2837-rpi-3-a-plus.dts b/arch/arm64/boot/dts/broadcom/bcm2837-rpi-3-a-plus.dts index f0ec56a1c4d72bf993253ae30a5565752ccf63cc..17d778a7e0c9ef41f7b934634b714eda6e9d36bd 100644 --- a/arch/arm64/boot/dts/broadcom/bcm2837-rpi-3-a-plus.dts +++ b/arch/arm64/boot/dts/broadcom/bcm2837-rpi-3-a-plus.dts @@ -1,2 +1,2 @@ // SPDX-License-Identifier: GPL-2.0 -#include "arm/bcm2837-rpi-3-a-plus.dts" +#include "arm/broadcom/bcm2837-rpi-3-a-plus.dts" diff --git a/arch/arm64/boot/dts/broadcom/bcm2837-rpi-3-b-plus.dts b/arch/arm64/boot/dts/broadcom/bcm2837-rpi-3-b-plus.dts index 46ad2023cccf1c89e80d5c8a6387d9beaec52458..0cf6240b6bf0c3b02915bc1cc8760f511b31d2bd 100644 --- a/arch/arm64/boot/dts/broadcom/bcm2837-rpi-3-b-plus.dts +++ b/arch/arm64/boot/dts/broadcom/bcm2837-rpi-3-b-plus.dts @@ -1,2 +1,2 @@ // SPDX-License-Identifier: GPL-2.0 -#include "arm/bcm2837-rpi-3-b-plus.dts" +#include "arm/broadcom/bcm2837-rpi-3-b-plus.dts" diff --git a/arch/arm64/boot/dts/broadcom/bcm2837-rpi-3-b.dts b/arch/arm64/boot/dts/broadcom/bcm2837-rpi-3-b.dts index 89b78d6c19bf19321e2941deff4783058b26ace5..f429468fd86e88d9a7ef3f01bb222f7c432a9063 100644 --- a/arch/arm64/boot/dts/broadcom/bcm2837-rpi-3-b.dts +++ b/arch/arm64/boot/dts/broadcom/bcm2837-rpi-3-b.dts @@ -1,2 +1,2 @@ // SPDX-License-Identifier: GPL-2.0 -#include "arm/bcm2837-rpi-3-b.dts" +#include "arm/broadcom/bcm2837-rpi-3-b.dts" diff --git a/arch/arm64/boot/dts/broadcom/bcm2837-rpi-cm3-io3.dts b/arch/arm64/boot/dts/broadcom/bcm2837-rpi-cm3-io3.dts index b1c4ab212c64919f0784189b6686feeceb1c9dfb..3fa21bd16b4992ef6a95c3a8be560c705df8e903 100644 --- a/arch/arm64/boot/dts/broadcom/bcm2837-rpi-cm3-io3.dts +++ b/arch/arm64/boot/dts/broadcom/bcm2837-rpi-cm3-io3.dts @@ -1,2 +1,2 @@ // SPDX-License-Identifier: GPL-2.0 -#include "arm/bcm2837-rpi-cm3-io3.dts" +#include "arm/broadcom/bcm2837-rpi-cm3-io3.dts" diff --git a/arch/arm64/boot/dts/broadcom/bcm2837-rpi-zero-2-w.dts b/arch/arm64/boot/dts/broadcom/bcm2837-rpi-zero-2-w.dts index 307ae693e4a0ba3f85402ac177a16bb0feef075b..363381a0cfb5e53102d4f51a725e8c125d7150d3 100644 --- a/arch/arm64/boot/dts/broadcom/bcm2837-rpi-zero-2-w.dts +++ b/arch/arm64/boot/dts/broadcom/bcm2837-rpi-zero-2-w.dts @@ -1,2 +1,2 @@ // SPDX-License-Identifier: GPL-2.0 -#include "arm/bcm2837-rpi-zero-2-w.dts" +#include "arm/broadcom/bcm2837-rpi-zero-2-w.dts" diff --git a/arch/arm64/boot/dts/broadcom/bcmbca/bcm4908.dtsi b/arch/arm64/boot/dts/broadcom/bcmbca/bcm4908.dtsi index 457805efb385ebbbd6d640c4756f60a431205a55..f549bda8c48c761f6bd2d81c8f4aa8bc5df050be 100644 --- a/arch/arm64/boot/dts/broadcom/bcmbca/bcm4908.dtsi +++ b/arch/arm64/boot/dts/broadcom/bcmbca/bcm4908.dtsi @@ -64,6 +64,7 @@ l2: l2-cache0 { compatible = "cache"; cache-level = <2>; + cache-unified; }; }; diff --git a/arch/arm64/boot/dts/broadcom/bcmbca/bcm4912.dtsi b/arch/arm64/boot/dts/broadcom/bcmbca/bcm4912.dtsi index 46aa8c0b797197dddcbe7e7be03bb66da6c837d3..d658c81f7285ece1eb405bc8781a493fcd0713f3 100644 --- a/arch/arm64/boot/dts/broadcom/bcmbca/bcm4912.dtsi +++ b/arch/arm64/boot/dts/broadcom/bcmbca/bcm4912.dtsi @@ -52,6 +52,7 @@ L2_0: l2-cache0 { compatible = "cache"; cache-level = <2>; + cache-unified; }; }; diff --git a/arch/arm64/boot/dts/broadcom/bcmbca/bcm63146.dtsi b/arch/arm64/boot/dts/broadcom/bcmbca/bcm63146.dtsi index 7020f2e995e2134a5da3e82f974d32e51c6a65a7..4f474d47022e261bafd0e876d1fa3ea3452ece36 100644 --- a/arch/arm64/boot/dts/broadcom/bcmbca/bcm63146.dtsi +++ b/arch/arm64/boot/dts/broadcom/bcmbca/bcm63146.dtsi @@ -36,6 +36,7 @@ L2_0: l2-cache0 { compatible = "cache"; cache-level = <2>; + cache-unified; }; }; diff --git a/arch/arm64/boot/dts/broadcom/bcmbca/bcm63158.dtsi b/arch/arm64/boot/dts/broadcom/bcmbca/bcm63158.dtsi index 6a0242cbea5719c8ca4061eb1d76537beda7ea80..909f254dc47d1112549b0e3cf9576f18b3566fce 100644 --- a/arch/arm64/boot/dts/broadcom/bcmbca/bcm63158.dtsi +++ b/arch/arm64/boot/dts/broadcom/bcmbca/bcm63158.dtsi @@ -52,6 +52,7 @@ L2_0: l2-cache0 { compatible = "cache"; cache-level = <2>; + cache-unified; }; }; diff --git a/arch/arm64/boot/dts/broadcom/bcmbca/bcm6813.dtsi b/arch/arm64/boot/dts/broadcom/bcmbca/bcm6813.dtsi index 1a12905266ef9183e6581899d7339db4f78d584a..685ae32951c9c7313e509e046fe8df6df3ffc10d 100644 --- a/arch/arm64/boot/dts/broadcom/bcmbca/bcm6813.dtsi +++ b/arch/arm64/boot/dts/broadcom/bcmbca/bcm6813.dtsi @@ -52,6 +52,7 @@ L2_0: l2-cache0 { compatible = "cache"; cache-level = <2>; + cache-unified; }; }; diff --git a/arch/arm64/boot/dts/broadcom/bcmbca/bcm6856.dtsi b/arch/arm64/boot/dts/broadcom/bcmbca/bcm6856.dtsi index f41ebc30666f2bb26d8cd6cd1f243fdeb2fc6091..820553ce541b4fd12f2fbcbf7bd1cbb73c42b512 100644 --- a/arch/arm64/boot/dts/broadcom/bcmbca/bcm6856.dtsi +++ b/arch/arm64/boot/dts/broadcom/bcmbca/bcm6856.dtsi @@ -36,6 +36,7 @@ L2_0: l2-cache0 { compatible = "cache"; cache-level = <2>; + cache-unified; }; }; diff --git a/arch/arm64/boot/dts/broadcom/bcmbca/bcm6858.dtsi b/arch/arm64/boot/dts/broadcom/bcmbca/bcm6858.dtsi index fa2688f41f0694788c44851158a40c781d8ac64b..0eb93c298297221787ff0ee1bfc1d7f121baee63 100644 --- a/arch/arm64/boot/dts/broadcom/bcmbca/bcm6858.dtsi +++ b/arch/arm64/boot/dts/broadcom/bcmbca/bcm6858.dtsi @@ -51,6 +51,7 @@ L2_0: l2-cache0 { compatible = "cache"; cache-level = <2>; + cache-unified; }; }; diff --git a/arch/arm64/boot/dts/broadcom/northstar2/ns2.dtsi b/arch/arm64/boot/dts/broadcom/northstar2/ns2.dtsi index e1b80e569cdfcc6b8e8924714a9bf35f35fdd49a..9dcd25ec2c04183fb90f160452142c2f5a790136 100644 --- a/arch/arm64/boot/dts/broadcom/northstar2/ns2.dtsi +++ b/arch/arm64/boot/dts/broadcom/northstar2/ns2.dtsi @@ -80,6 +80,7 @@ CLUSTER0_L2: l2-cache@0 { compatible = "cache"; cache-level = <2>; + cache-unified; }; }; diff --git a/arch/arm64/boot/dts/broadcom/stingray/stingray-pinctrl.dtsi b/arch/arm64/boot/dts/broadcom/stingray/stingray-pinctrl.dtsi index 56789ccf94545f39cde28c34f9dba8af495322a7..46a82752192156c9e7448e077bb79446ba08a7d9 100644 --- a/arch/arm64/boot/dts/broadcom/stingray/stingray-pinctrl.dtsi +++ b/arch/arm64/boot/dts/broadcom/stingray/stingray-pinctrl.dtsi @@ -44,7 +44,7 @@ compatible = "pinctrl-single"; reg = <0x0014029c 0x26c>; #address-cells = <1>; - #size-cells = <1>; + #size-cells = <0>; pinctrl-single,register-width = <32>; pinctrl-single,function-mask = <0xf>; pinctrl-single,gpio-range = < @@ -56,14 +56,14 @@ }; /* pinctrl functions */ - tsio_pins: pinmux_gpio_14 { + tsio_pins: gpio-14-pins { pinctrl-single,pins = < 0x038 MODE_NITRO /* tsio_0 */ 0x03c MODE_NITRO /* tsio_1 */ >; }; - nor_pins: pinmux_pnor_adv_n { + nor_pins: pnor-adv-n-pins { pinctrl-single,pins = < 0x0ac MODE_PNOR /* nand_ce1_n */ 0x0b0 MODE_PNOR /* nand_ce0_n */ @@ -119,7 +119,7 @@ >; }; - nand_pins: pinmux_nand_ce1_n { + nand_pins: nand-ce1-n-pins { pinctrl-single,pins = < 0x0ac MODE_NAND /* nand_ce1_n */ 0x0b0 MODE_NAND /* nand_ce0_n */ @@ -148,59 +148,59 @@ >; }; - pwm0_pins: pinmux_pwm_0 { + pwm0_pins: pwm-0-pins { pinctrl-single,pins = < 0x10c MODE_NITRO >; }; - pwm1_pins: pinmux_pwm_1 { + pwm1_pins: pwm-1-pins { pinctrl-single,pins = < 0x110 MODE_NITRO >; }; - pwm2_pins: pinmux_pwm_2 { + pwm2_pins: pwm-2-pins { pinctrl-single,pins = < 0x114 MODE_NITRO >; }; - pwm3_pins: pinmux_pwm_3 { + pwm3_pins: pwm-3-pins { pinctrl-single,pins = < 0x118 MODE_NITRO >; }; - dbu_rxd_pins: pinmux_uart1_sin_nitro { + dbu_rxd_pins: uart1-sin-nitro-pins { pinctrl-single,pins = < 0x11c MODE_NITRO /* dbu_rxd */ 0x120 MODE_NITRO /* dbu_txd */ >; }; - uart1_pins: pinmux_uart1_sin_nand { + uart1_pins: uart1-sin-nand-pins { pinctrl-single,pins = < 0x11c MODE_NAND /* uart1_sin */ 0x120 MODE_NAND /* uart1_out */ >; }; - uart2_pins: pinmux_uart2_sin { + uart2_pins: uart2-sin-pins { pinctrl-single,pins = < 0x124 MODE_NITRO /* uart2_sin */ 0x128 MODE_NITRO /* uart2_out */ >; }; - uart3_pins: pinmux_uart3_sin { + uart3_pins: uart3-sin-pins { pinctrl-single,pins = < 0x12c MODE_NITRO /* uart3_sin */ 0x130 MODE_NITRO /* uart3_out */ >; }; - i2s_pins: pinmux_i2s_bitclk { + i2s_pins: i2s-bitclk-pins { pinctrl-single,pins = < 0x134 MODE_NITRO /* i2s_bitclk */ 0x138 MODE_NITRO /* i2s_sdout */ @@ -211,7 +211,7 @@ >; }; - qspi_pins: pinumx_qspi_hold_n { + qspi_pins: qspi-hold-n-pins { pinctrl-single,pins = < 0x14c MODE_NAND /* qspi_hold_n */ 0x150 MODE_NAND /* qspi_wp_n */ @@ -222,28 +222,28 @@ >; }; - mdio_pins: pinumx_ext_mdio { + mdio_pins: ext-mdio-pins { pinctrl-single,pins = < 0x164 MODE_NITRO /* ext_mdio */ 0x168 MODE_NITRO /* ext_mdc */ >; }; - i2c0_pins: pinmux_i2c0_sda { + i2c0_pins: i2c0-sda-pins { pinctrl-single,pins = < 0x16c MODE_NITRO /* i2c0_sda */ 0x170 MODE_NITRO /* i2c0_scl */ >; }; - i2c1_pins: pinmux_i2c1_sda { + i2c1_pins: i2c1-sda-pins { pinctrl-single,pins = < 0x174 MODE_NITRO /* i2c1_sda */ 0x178 MODE_NITRO /* i2c1_scl */ >; }; - sdio0_pins: pinmux_sdio0_cd_l { + sdio0_pins: sdio0-cd-l-pins { pinctrl-single,pins = < 0x17c MODE_NITRO /* sdio0_cd_l */ 0x180 MODE_NITRO /* sdio0_clk_sdcard */ @@ -262,7 +262,7 @@ >; }; - sdio1_pins: pinmux_sdio1_cd_l { + sdio1_pins: sdio1-cd-l-pins { pinctrl-single,pins = < 0x1b4 MODE_NITRO /* sdio1_cd_l */ 0x1b8 MODE_NITRO /* sdio1_clk_sdcard */ @@ -281,7 +281,7 @@ >; }; - spi0_pins: pinmux_spi0_sck_nand { + spi0_pins: spi0-sck-nand-pins { pinctrl-single,pins = < 0x1ec MODE_NITRO /* spi0_sck */ 0x1f0 MODE_NITRO /* spi0_rxd */ @@ -290,7 +290,7 @@ >; }; - spi1_pins: pinmux_spi1_sck_nand { + spi1_pins: spi1-sck-nand-pins { pinctrl-single,pins = < 0x1fc MODE_NITRO /* spi1_sck */ 0x200 MODE_NITRO /* spi1_rxd */ @@ -299,14 +299,14 @@ >; }; - nuart_pins: pinmux_uart0_sin_nitro { + nuart_pins: uart0-sin-nitro-pins { pinctrl-single,pins = < 0x20c MODE_NITRO /* nuart_rxd */ 0x210 MODE_NITRO /* nuart_txd */ >; }; - uart0_pins: pinumux_uart0_sin_nand { + uart0_pins: uart0-sin-nand-pins { pinctrl-single,pins = < 0x20c MODE_NAND /* uart0_sin */ 0x210 MODE_NAND /* uart0_out */ @@ -319,7 +319,7 @@ >; }; - drdu2_pins: pinmux_drdu2_overcurrent { + drdu2_pins: drdu2-overcurrent-pins { pinctrl-single,pins = < 0x22c MODE_NITRO /* drdu2_overcurrent */ 0x230 MODE_NITRO /* drdu2_vbus_ppc */ @@ -328,7 +328,7 @@ >; }; - drdu3_pins: pinmux_drdu3_overcurrent { + drdu3_pins: drdu3-overcurrent-pins { pinctrl-single,pins = < 0x23c MODE_NITRO /* drdu3_overcurrent */ 0x240 MODE_NITRO /* drdu3_vbus_ppc */ @@ -337,7 +337,7 @@ >; }; - usb3h_pins: pinmux_usb3h_overcurrent { + usb3h_pins: usb3h-overcurrent-pins { pinctrl-single,pins = < 0x24c MODE_NITRO /* usb3h_overcurrent */ 0x250 MODE_NITRO /* usb3h_vbus_ppc */ diff --git a/arch/arm64/boot/dts/broadcom/stingray/stingray.dtsi b/arch/arm64/boot/dts/broadcom/stingray/stingray.dtsi index 388424b3e1d39c2ddb48e52928ae9f2473d4f6a6..7aece79bf882b4e1e28f3f0ca444f713f6a05a33 100644 --- a/arch/arm64/boot/dts/broadcom/stingray/stingray.dtsi +++ b/arch/arm64/boot/dts/broadcom/stingray/stingray.dtsi @@ -109,21 +109,25 @@ CLUSTER0_L2: l2-cache@0 { compatible = "cache"; cache-level = <2>; + cache-unified; }; CLUSTER1_L2: l2-cache@100 { compatible = "cache"; cache-level = <2>; + cache-unified; }; CLUSTER2_L2: l2-cache@200 { compatible = "cache"; cache-level = <2>; + cache-unified; }; CLUSTER3_L2: l2-cache@300 { compatible = "cache"; cache-level = <2>; + cache-unified; }; }; diff --git a/arch/arm64/boot/dts/exynos/exynos7.dtsi b/arch/arm64/boot/dts/exynos/exynos7.dtsi index b1fa68835b09cfafc6e182e40387e90172bfd34e..5ea8bda2bfa6b94b4b6f31ed04578d4dfbce28b1 100644 --- a/arch/arm64/boot/dts/exynos/exynos7.dtsi +++ b/arch/arm64/boot/dts/exynos/exynos7.dtsi @@ -734,4 +734,4 @@ }; #include "exynos7-pinctrl.dtsi" -#include "arm/exynos-syscon-restart.dtsi" +#include "arm/samsung/exynos-syscon-restart.dtsi" diff --git a/arch/arm64/boot/dts/exynos/exynos7885.dtsi b/arch/arm64/boot/dts/exynos/exynos7885.dtsi index 23c2e0bb0a2c5ad4c1ab2c364af107d271b77d1e..d69fc2392bd0e37842109865f226925d7ac4d602 100644 --- a/arch/arm64/boot/dts/exynos/exynos7885.dtsi +++ b/arch/arm64/boot/dts/exynos/exynos7885.dtsi @@ -452,4 +452,4 @@ }; #include "exynos7885-pinctrl.dtsi" -#include "arm/exynos-syscon-restart.dtsi" +#include "arm/samsung/exynos-syscon-restart.dtsi" diff --git a/arch/arm64/boot/dts/exynos/exynos850.dtsi b/arch/arm64/boot/dts/exynos/exynos850.dtsi index d67e981203132b5a57f80d72ac2cd714fcffe097..aa077008b3bef188cb27ab01024b02b9bb823260 100644 --- a/arch/arm64/boot/dts/exynos/exynos850.dtsi +++ b/arch/arm64/boot/dts/exynos/exynos850.dtsi @@ -200,7 +200,6 @@ pmu_system_controller: system-controller@11860000 { compatible = "samsung,exynos850-pmu", "syscon"; reg = <0x11860000 0x10000>; - clocks = <&cmu_apm CLK_GOUT_PMU_ALIVE_PCLK>; reboot: syscon-reboot { compatible = "syscon-reboot"; diff --git a/arch/arm64/boot/dts/freescale/Makefile b/arch/arm64/boot/dts/freescale/Makefile index ef7d17aef58f0adeacb8d4f8cfc1a7382950ed44..a750be13ace894f82aeeda19931181defa883a54 100644 --- a/arch/arm64/boot/dts/freescale/Makefile +++ b/arch/arm64/boot/dts/freescale/Makefile @@ -54,7 +54,9 @@ dtb-$(CONFIG_ARCH_MXC) += imx8mm-beacon-kit.dtb dtb-$(CONFIG_ARCH_MXC) += imx8mm-data-modul-edm-sbc.dtb dtb-$(CONFIG_ARCH_MXC) += imx8mm-ddr4-evk.dtb dtb-$(CONFIG_ARCH_MXC) += imx8mm-emcon-avari.dtb +dtb-$(CONFIG_ARCH_MXC) += imx8mm-emtop-baseboard.dtb dtb-$(CONFIG_ARCH_MXC) += imx8mm-evk.dtb +dtb-$(CONFIG_ARCH_MXC) += imx8mm-evkb.dtb dtb-$(CONFIG_ARCH_MXC) += imx8mm-icore-mx8mm-ctouch2.dtb dtb-$(CONFIG_ARCH_MXC) += imx8mm-icore-mx8mm-edimm2.2.dtb dtb-$(CONFIG_ARCH_MXC) += imx8mm-innocomm-wb15-evk.dtb @@ -99,6 +101,7 @@ dtb-$(CONFIG_ARCH_MXC) += imx8mp-msc-sm2s-ep1.dtb dtb-$(CONFIG_ARCH_MXC) += imx8mp-phyboard-pollux-rdk.dtb dtb-$(CONFIG_ARCH_MXC) += imx8mp-tqma8mpql-mba8mpxl.dtb dtb-$(CONFIG_ARCH_MXC) += imx8mp-venice-gw74xx.dtb +dtb-$(CONFIG_ARCH_MXC) += imx8mp-venice-gw7905-2x.dtb dtb-$(CONFIG_ARCH_MXC) += imx8mp-verdin-nonwifi-dahlia.dtb dtb-$(CONFIG_ARCH_MXC) += imx8mp-verdin-nonwifi-dev.dtb dtb-$(CONFIG_ARCH_MXC) += imx8mp-verdin-nonwifi-yavia.dtb diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi index 678bb0358751eb741adbd2dcb2a96af57e6c63c7..9cbb31191cf92fd345e6908922fa68cf8a8eeed9 100644 --- a/arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi +++ b/arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi @@ -47,6 +47,7 @@ l2: l2-cache { compatible = "cache"; cache-level = <2>; + cache-unified; }; }; diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi index b9fd24cdc919beff2e75b0fe0e8d194465a563fb..f8acbefc805b2039ca47038b4d3b8239e505a5f8 100644 --- a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi +++ b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi @@ -85,6 +85,7 @@ l2: l2-cache { compatible = "cache"; cache-level = <2>; + cache-unified; }; }; diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi index a01e3cfec77fb9794d7fd8a61557cac963ad3881..50f68ca5a9af710eba8044f1f164142791cab0ec 100644 --- a/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi +++ b/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi @@ -80,6 +80,7 @@ l2: l2-cache { compatible = "cache"; cache-level = <2>; + cache-unified; }; }; diff --git a/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi index 1e5d76c4d83db04e127d7528b2fddb05de53849a..1aa38ed09aa4fa89c29f651d175e75c78593e079 100644 --- a/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi +++ b/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi @@ -96,21 +96,25 @@ cluster0_l2: l2-cache0 { compatible = "cache"; cache-level = <2>; + cache-unified; }; cluster1_l2: l2-cache1 { compatible = "cache"; cache-level = <2>; + cache-unified; }; cluster2_l2: l2-cache2 { compatible = "cache"; cache-level = <2>; + cache-unified; }; cluster3_l2: l2-cache3 { compatible = "cache"; cache-level = <2>; + cache-unified; }; CPU_PW20: cpu-pw20 { diff --git a/arch/arm64/boot/dts/freescale/fsl-ls2088a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls2088a.dtsi index c12c86915ec87df70563100c4ad2011a800cf1fb..8581ea55d2540f087e5944beafde9a16f1637db4 100644 --- a/arch/arm64/boot/dts/freescale/fsl-ls2088a.dtsi +++ b/arch/arm64/boot/dts/freescale/fsl-ls2088a.dtsi @@ -96,21 +96,25 @@ cluster0_l2: l2-cache0 { compatible = "cache"; cache-level = <2>; + cache-unified; }; cluster1_l2: l2-cache1 { compatible = "cache"; cache-level = <2>; + cache-unified; }; cluster2_l2: l2-cache2 { compatible = "cache"; cache-level = <2>; + cache-unified; }; cluster3_l2: l2-cache3 { compatible = "cache"; cache-level = <2>; + cache-unified; }; CPU_PW20: cpu-pw20 { diff --git a/arch/arm64/boot/dts/freescale/imx8dxl.dtsi b/arch/arm64/boot/dts/freescale/imx8dxl.dtsi index 70fadd79851a41374a683586117aba18c57a2f4d..792b7224ca5b5ce755929843323171711659ea8e 100644 --- a/arch/arm64/boot/dts/freescale/imx8dxl.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8dxl.dtsi @@ -60,6 +60,7 @@ A35_L2: l2-cache0 { compatible = "cache"; cache-level = <2>; + cache-unified; }; }; diff --git a/arch/arm64/boot/dts/freescale/imx8mm-emtop-baseboard.dts b/arch/arm64/boot/dts/freescale/imx8mm-emtop-baseboard.dts new file mode 100644 index 0000000000000000000000000000000000000000..1c4e4d175989e670f33a7c88eaff8df367a4cc85 --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx8mm-emtop-baseboard.dts @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright 2023 Emtop Embedded Solutions + */ + +/dts-v1/; + +#include "imx8mm-emtop-som.dtsi" + +/ { + model = "Emtop Embedded Solutions i.MX8M Mini Baseboard V1"; + compatible = "ees,imx8mm-emtop-baseboard", "ees,imx8mm-emtop-som", + "fsl,imx8mm"; + +}; diff --git a/arch/arm64/boot/dts/freescale/imx8mm-emtop-som.dtsi b/arch/arm64/boot/dts/freescale/imx8mm-emtop-som.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..67d22d3768aa8ae7343cffeebcfdde89ed25cc2d --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx8mm-emtop-som.dtsi @@ -0,0 +1,261 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright 2023 Emtop Embedded Solutions + */ + +/dts-v1/; + +#include +#include +#include + +#include "imx8mm.dtsi" + +/ { + model = "Emtop Embedded Solutions i.MX8M Mini SOM-IMX8MMLPD4 SoM"; + compatible = "ees,imx8mm-emtop-som", "fsl,imx8mm"; + + chosen { + stdout-path = &uart2; + }; + + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_gpio_led>; + + led-0 { + function = LED_FUNCTION_POWER; + gpios = <&gpio3 16 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "heartbeat"; + }; + }; +}; + +&A53_0 { + cpu-supply = <&buck2>; +}; + +&A53_1 { + cpu-supply = <&buck2>; +}; + +&A53_2 { + cpu-supply = <&buck2>; +}; + +&A53_3 { + cpu-supply = <&buck2>; +}; + +&i2c1 { + clock-frequency = <400000>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c1>; + status = "okay"; + + pmic@25 { + compatible = "nxp,pca9450c"; + reg = <0x25>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_pmic>; + interrupt-parent = <&gpio1>; + interrupts = <3 IRQ_TYPE_EDGE_RISING>; + + regulators { + buck1: BUCK1 { + regulator-name = "BUCK1"; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <1000000>; + regulator-boot-on; + regulator-always-on; + regulator-ramp-delay = <3125>; + }; + + buck2: BUCK2 { + regulator-name = "BUCK2"; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <900000>; + regulator-boot-on; + regulator-always-on; + regulator-ramp-delay = <3125>; + }; + + buck3: BUCK3 { + regulator-name = "BUCK3"; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <1000000>; + regulator-boot-on; + regulator-always-on; + }; + + buck4: BUCK4 { + regulator-name = "BUCK4"; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3600000>; + regulator-boot-on; + regulator-always-on; + }; + + buck5: BUCK5 { + regulator-name = "BUCK5"; + regulator-min-microvolt = <1650000>; + regulator-max-microvolt = <1950000>; + regulator-boot-on; + regulator-always-on; + }; + + buck6: BUCK6 { + regulator-name = "BUCK6"; + regulator-min-microvolt = <1100000>; + regulator-max-microvolt = <1200000>; + regulator-boot-on; + regulator-always-on; + }; + + ldo1: LDO1 { + regulator-name = "LDO1"; + regulator-min-microvolt = <1650000>; + regulator-max-microvolt = <1950000>; + regulator-boot-on; + regulator-always-on; + }; + + ldo2: LDO2 { + regulator-name = "LDO2"; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <945000>; + regulator-boot-on; + regulator-always-on; + }; + + ldo3: LDO3 { + regulator-name = "LDO3"; + regulator-min-microvolt = <1710000>; + regulator-max-microvolt = <1890000>; + regulator-boot-on; + regulator-always-on; + }; + + ldo4: LDO4 { + regulator-name = "LDO4"; + regulator-min-microvolt = <810000>; + regulator-max-microvolt = <945000>; + regulator-boot-on; + regulator-always-on; + }; + + ldo5: LDO5 { + regulator-name = "LDO5"; + regulator-min-microvolt = <1650000>; + regulator-max-microvolt = <3600000>; + }; + }; + }; +}; + +&uart2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart2>; + status = "okay"; +}; + +&usdhc3 { + pinctrl-names = "default", "state_100mhz", "state_200mhz"; + pinctrl-0 = <&pinctrl_usdhc3>; + pinctrl-1 = <&pinctrl_usdhc3_100mhz>; + pinctrl-2 = <&pinctrl_usdhc3_200mhz>; + bus-width = <8>; + non-removable; + status = "okay"; +}; + +&wdog1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_wdog>; + fsl,ext-reset-output; + status = "okay"; +}; + +&iomuxc { + pinctrl_gpio_led: emtop-gpio-led-grp { + fsl,pins = < + MX8MM_IOMUXC_NAND_READY_B_GPIO3_IO16 0x19 + MX8MM_IOMUXC_SAI3_RXC_GPIO4_IO29 0x19 + >; + }; + + pinctrl_i2c1: emtop-i2c1-grp { + fsl,pins = < + MX8MM_IOMUXC_I2C1_SCL_I2C1_SCL 0x400001c3 + MX8MM_IOMUXC_I2C1_SDA_I2C1_SDA 0x400001c3 + >; + }; + + pinctrl_pmic: emtop-pmic-grp { + fsl,pins = < + MX8MM_IOMUXC_GPIO1_IO03_GPIO1_IO3 0x41 + >; + }; + + pinctrl_uart2: emtop-uart2-grp { + fsl,pins = < + MX8MM_IOMUXC_UART2_RXD_UART2_DCE_RX 0x140 + MX8MM_IOMUXC_UART2_TXD_UART2_DCE_TX 0x140 + >; + }; + + pinctrl_usdhc3: emtop-usdhc3-grp { + fsl,pins = < + MX8MM_IOMUXC_NAND_WE_B_USDHC3_CLK 0x190 + MX8MM_IOMUXC_NAND_WP_B_USDHC3_CMD 0x1d0 + MX8MM_IOMUXC_NAND_DATA04_USDHC3_DATA0 0x1d0 + MX8MM_IOMUXC_NAND_DATA05_USDHC3_DATA1 0x1d0 + MX8MM_IOMUXC_NAND_DATA06_USDHC3_DATA2 0x1d0 + MX8MM_IOMUXC_NAND_DATA07_USDHC3_DATA3 0x1d0 + MX8MM_IOMUXC_NAND_RE_B_USDHC3_DATA4 0x1d0 + MX8MM_IOMUXC_NAND_CE2_B_USDHC3_DATA5 0x1d0 + MX8MM_IOMUXC_NAND_CE3_B_USDHC3_DATA6 0x1d0 + MX8MM_IOMUXC_NAND_CLE_USDHC3_DATA7 0x1d0 + MX8MM_IOMUXC_NAND_CE1_B_USDHC3_STROBE 0x190 + >; + }; + + pinctrl_usdhc3_100mhz: emtop-usdhc3-100mhz-grp { + fsl,pins = < + MX8MM_IOMUXC_NAND_WE_B_USDHC3_CLK 0x194 + MX8MM_IOMUXC_NAND_WP_B_USDHC3_CMD 0x1d4 + MX8MM_IOMUXC_NAND_DATA04_USDHC3_DATA0 0x1d4 + MX8MM_IOMUXC_NAND_DATA05_USDHC3_DATA1 0x1d4 + MX8MM_IOMUXC_NAND_DATA06_USDHC3_DATA2 0x1d4 + MX8MM_IOMUXC_NAND_DATA07_USDHC3_DATA3 0x1d4 + MX8MM_IOMUXC_NAND_RE_B_USDHC3_DATA4 0x1d4 + MX8MM_IOMUXC_NAND_CE2_B_USDHC3_DATA5 0x1d4 + MX8MM_IOMUXC_NAND_CE3_B_USDHC3_DATA6 0x1d4 + MX8MM_IOMUXC_NAND_CLE_USDHC3_DATA7 0x1d4 + MX8MM_IOMUXC_NAND_CE1_B_USDHC3_STROBE 0x194 + >; + }; + + pinctrl_usdhc3_200mhz: emtop-usdhc3-200mhz-grp { + fsl,pins = < + MX8MM_IOMUXC_NAND_WE_B_USDHC3_CLK 0x196 + MX8MM_IOMUXC_NAND_WP_B_USDHC3_CMD 0x1d6 + MX8MM_IOMUXC_NAND_DATA04_USDHC3_DATA0 0x1d6 + MX8MM_IOMUXC_NAND_DATA05_USDHC3_DATA1 0x1d6 + MX8MM_IOMUXC_NAND_DATA06_USDHC3_DATA2 0x1d6 + MX8MM_IOMUXC_NAND_DATA07_USDHC3_DATA3 0x1d6 + MX8MM_IOMUXC_NAND_RE_B_USDHC3_DATA4 0x1d6 + MX8MM_IOMUXC_NAND_CE2_B_USDHC3_DATA5 0x1d6 + MX8MM_IOMUXC_NAND_CE3_B_USDHC3_DATA6 0x1d6 + MX8MM_IOMUXC_NAND_CLE_USDHC3_DATA7 0x1d6 + MX8MM_IOMUXC_NAND_CE1_B_USDHC3_STROBE 0x196 + >; + }; + + pinctrl_wdog: emtop-wdog-grp { + fsl,pins = < + MX8MM_IOMUXC_GPIO1_IO02_WDOG1_WDOG_B 0xc6 + >; + }; +}; diff --git a/arch/arm64/boot/dts/freescale/imx8mm-evk.dtsi b/arch/arm64/boot/dts/freescale/imx8mm-evk.dtsi index 3f9dfd4d38848fc314cb7081b97c6968f3429dcf..df8e808ac47398bace042153e94f15bb194f9269 100644 --- a/arch/arm64/boot/dts/freescale/imx8mm-evk.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mm-evk.dtsi @@ -19,6 +19,18 @@ reg = <0x0 0x40000000 0 0x80000000>; }; + hdmi-connector { + compatible = "hdmi-connector"; + label = "hdmi"; + type = "a"; + + port { + hdmi_connector_in: endpoint { + remote-endpoint = <&adv7533_out>; + }; + }; + }; + leds { compatible = "gpio-leds"; pinctrl-names = "default"; @@ -303,6 +315,41 @@ pinctrl-0 = <&pinctrl_i2c2>; status = "okay"; + hdmi@3d { + compatible = "adi,adv7535"; + reg = <0x3d>, <0x3c>, <0x3e>, <0x3f>; + reg-names = "main", "cec", "edid", "packet"; + adi,dsi-lanes = <4>; + + adi,input-depth = <8>; + adi,input-colorspace = "rgb"; + adi,input-clock = "1x"; + adi,input-style = <1>; + adi,input-justification = "evenly"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + adv7533_in: endpoint { + remote-endpoint = <&dsi_out>; + }; + }; + + port@1 { + reg = <1>; + + adv7533_out: endpoint { + remote-endpoint = <&hdmi_connector_in>; + }; + }; + + }; + }; + ptn5110: tcpc@50 { compatible = "nxp,ptn5110"; pinctrl-names = "default"; @@ -348,6 +395,26 @@ }; }; +&lcdif { + status = "okay"; +}; + +&mipi_dsi { + samsung,esc-clock-frequency = <10000000>; + status = "okay"; + + ports { + port@1 { + reg = <1>; + + dsi_out: endpoint { + remote-endpoint = <&adv7533_in>; + data-lanes = <1 2 3 4>; + }; + }; + }; +}; + &pcie_phy { fsl,refclk-pad-mode = ; fsl,tx-deemph-gen1 = <0x2d>; diff --git a/arch/arm64/boot/dts/freescale/imx8mm-evkb.dts b/arch/arm64/boot/dts/freescale/imx8mm-evkb.dts new file mode 100644 index 0000000000000000000000000000000000000000..164df627a213a915a75174099e909a7a0377d1dc --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx8mm-evkb.dts @@ -0,0 +1,128 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright 2019-2020 NXP + */ + +/dts-v1/; + +#include "imx8mm-evk.dtsi" + +/ { + model = "FSL i.MX8MM EVKB"; + compatible = "fsl,imx8mm-evkb", "fsl,imx8mm"; +}; + +&i2c1 { + /delete-node/ pmic@4b; + + pmic@25 { + compatible = "nxp,pca9450a"; + reg = <0x25>; + pinctrl-0 = <&pinctrl_pmic>; + pinctrl-names = "default"; + interrupt-parent = <&gpio1>; + interrupts = <3 IRQ_TYPE_LEVEL_LOW>; + + regulators { + /* VDD_SOC with PCIe */ + buck1_reg: BUCK1 { + regulator-name = "BUCK1"; + regulator-min-microvolt = <850000>; + regulator-max-microvolt = <850000>; + regulator-boot-on; + regulator-always-on; + regulator-ramp-delay = <3125>; + }; + + /* VDD_ARM */ + buck2_reg: BUCK2 { + regulator-name = "BUCK2"; + regulator-min-microvolt = <850000>; + regulator-max-microvolt = <1000000>; + regulator-boot-on; + regulator-always-on; + regulator-ramp-delay = <3125>; + nxp,dvs-standby-voltage = <850000>; + }; + + /* VDD_GPU, VDD_VPU, VDD_DRAM */ + buck3_reg: BUCK3 { + regulator-name = "BUCK3"; + regulator-min-microvolt = <850000>; + regulator-max-microvolt = <1000000>; + regulator-boot-on; + regulator-always-on; + }; + + /* NVCC_3V3 */ + buck4_reg: BUCK4 { + regulator-name = "BUCK4"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + regulator-always-on; + }; + + /* VDD_1V8, NVCC_1V8, NVCC_ENET */ + buck5_reg: BUCK5 { + regulator-name = "BUCK5"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-boot-on; + regulator-always-on; + }; + + /* NVCC_DRAM for LPDDR4 */ + buck6_reg: BUCK6 { + regulator-name = "BUCK6"; + regulator-min-microvolt = <1100000>; + regulator-max-microvolt = <1100000>; + regulator-boot-on; + regulator-always-on; + }; + + /* NVCC_SNVS_1P8 */ + ldo1_reg: LDO1 { + regulator-name = "LDO1"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-boot-on; + regulator-always-on; + }; + + /* VDD_SNVS_0P8 */ + ldo2_reg: LDO2 { + regulator-name = "LDO2"; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <800000>; + regulator-boot-on; + regulator-always-on; + }; + + /* VDD_*_1V8 */ + ldo3_reg: LDO3 { + regulator-name = "LDO3"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-boot-on; + regulator-always-on; + }; + + /* VDD_PHY_0V9 */ + ldo4_reg: LDO4 { + regulator-name = "LDO4"; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <900000>; + regulator-boot-on; + regulator-always-on; + }; + + /* NVCC_SD2 */ + ldo5_reg: LDO5 { + regulator-name = "LDO5"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + }; + }; + }; +}; diff --git a/arch/arm64/boot/dts/freescale/imx8mm-phg.dts b/arch/arm64/boot/dts/freescale/imx8mm-phg.dts index e9447738b104f5ad64d7a01a4b600d823aeec6f4..606a4f4d5f1509f5fc472cb54c4b3e14a636f10b 100644 --- a/arch/arm64/boot/dts/freescale/imx8mm-phg.dts +++ b/arch/arm64/boot/dts/freescale/imx8mm-phg.dts @@ -80,6 +80,35 @@ startup-delay-us = <100>; off-on-delay-us = <12000>; }; + + panel { + compatible = "panel-lvds"; + width-mm = <170>; + height-mm = <28>; + data-mapping = "jeida-18"; + + panel-timing { + clock-frequency = <49500000>; + hactive = <800>; + hback-porch = <48>; + hfront-porch = <312>; + hsync-len = <40>; + vactive = <600>; + vback-porch = <19>; + vfront-porch = <61>; + vsync-len = <20>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <1>; + pixelclk-active = <1>; + }; + + port { + panel_out_bridge: endpoint { + remote-endpoint = <&bridge_out_panel>; + }; + }; + }; }; &ecspi1 { @@ -113,8 +142,60 @@ pinctrl-names = "default"; pinctrl-0 = <&pinctrl_i2c2>; status = "okay"; + + bridge@2c { + compatible = "ti,sn65dsi83"; + reg = <0x2c>; + enable-gpios = <&gpio2 3 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_dsi_bridge>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + bridge_in_dsi: endpoint { + remote-endpoint = <&dsi_out_bridge>; + data-lanes = <1 2 3 4>; + }; + }; + + port@2 { + reg = <2>; + + bridge_out_panel: endpoint { + remote-endpoint = <&panel_out_bridge>; + }; + }; + }; + }; }; +&lcdif { + status = "okay"; +}; + +&mipi_dsi { + samsung,esc-clock-frequency = <10000000>; + status = "okay"; + + ports { + port@1 { + reg = <1>; + + dsi_out_bridge: endpoint { + data-lanes = <1 2>; + lane-polarities = <1 0 0 0 0>; + remote-endpoint = <&bridge_in_dsi>; + }; + }; + }; +}; + + &uart2 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_uart2>; @@ -166,6 +247,12 @@ >; }; + pinctrl_dsi_bridge: dsibridgeggrp { + fsl,pins = < + MX8MM_IOMUXC_SD1_DATA1_GPIO2_IO3 0x19 + >; + }; + pinctrl_ecspi1: ecspi1grp { fsl,pins = < MX8MM_IOMUXC_ECSPI1_MISO_ECSPI1_MISO 0x82 diff --git a/arch/arm64/boot/dts/freescale/imx8mm-tqma8mqml.dtsi b/arch/arm64/boot/dts/freescale/imx8mm-tqma8mqml.dtsi index 12260290c109e40259d245873fb77a447a066d65..b4466a26d838a414fa6fba88ca1203434ba9f5d1 100644 --- a/arch/arm64/boot/dts/freescale/imx8mm-tqma8mqml.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mm-tqma8mqml.dtsi @@ -219,12 +219,14 @@ read-only; reg = <0x53>; pagesize = <16>; + vcc-supply = <®_vcc3v3>; }; eeprom0: eeprom@57 { compatible = "atmel,24c64"; reg = <0x57>; pagesize = <32>; + vcc-supply = <®_vcc3v3>; }; }; diff --git a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw700x.dtsi b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw700x.dtsi index 9e7d388721575593330bff0051b6973122577532..de7f67a4ff2a7fd99ff37711daa92db10e2a3952 100644 --- a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw700x.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw700x.dtsi @@ -149,7 +149,7 @@ }; channel@8 { - gw,mode = <1>; + gw,mode = <3>; reg = <0x08>; label = "vdd_bat"; }; @@ -234,8 +234,6 @@ }; fan-controller@0 { - #address-cells = <1>; - #size-cells = <0>; compatible = "gw,gsc-fan"; reg = <0x0a>; }; diff --git a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7901.dts b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7901.dts index df3b2c93d2d583e3435193ac33db3be0c6343b87..0ec2ce3dd7218f4ad4d5febb7a26383419964d4a 100644 --- a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7901.dts +++ b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7901.dts @@ -354,7 +354,7 @@ }; channel@8 { - gw,mode = <1>; + gw,mode = <3>; reg = <0x08>; label = "vdd_bat"; }; diff --git a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7902.dts b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7902.dts index c33ec6826d324d123ecc1e4d5b71bf32059dceef..03cd29063312f22fac55b6aa0d5d9899e3bacead 100644 --- a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7902.dts +++ b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7902.dts @@ -327,7 +327,7 @@ }; channel@8 { - gw,mode = <1>; + gw,mode = <3>; reg = <0x08>; label = "vdd_bat"; }; diff --git a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7903.dts b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7903.dts index 363020a08c9b8b6764e051ea004b27167a397944..6f26914602c8841c6dc182d1f57986bcc29b844e 100644 --- a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7903.dts +++ b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7903.dts @@ -293,7 +293,7 @@ }; channel@8 { - gw,mode = <1>; + gw,mode = <3>; reg = <0x08>; label = "vdd_bat"; }; diff --git a/arch/arm64/boot/dts/freescale/imx8mn-beacon-baseboard.dtsi b/arch/arm64/boot/dts/freescale/imx8mn-beacon-baseboard.dtsi index 5a1f7c30afe57a09f16c658fc50ef228c3b86bd6..16761975f56e3ec0d701aa7f2ed26e733bf153cb 100644 --- a/arch/arm64/boot/dts/freescale/imx8mn-beacon-baseboard.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mn-beacon-baseboard.dtsi @@ -43,6 +43,17 @@ enable-active-high; }; + reg_camera: regulator-camera { + compatible = "regulator-fixed"; + regulator-name = "mipi_pwr"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + gpio = <&pca6416_1 0 GPIO_ACTIVE_HIGH>; + enable-active-high; + startup-delay-us = <100000>; + regulator-always-on; + }; + reg_usdhc2_vmmc: regulator-usdhc2 { compatible = "regulator-fixed"; regulator-name = "vsd_3v3"; @@ -63,18 +74,30 @@ enable-active-high; }; - sound { - compatible = "fsl,imx-audio-wm8962"; - model = "wm8962-audio"; - audio-cpu = <&sai3>; - audio-codec = <&wm8962>; - audio-routing = - "Headphone Jack", "HPOUTL", - "Headphone Jack", "HPOUTR", - "Ext Spk", "SPKOUTL", - "Ext Spk", "SPKOUTR", - "AMIC", "MICBIAS", - "IN3R", "AMIC"; + sound-wm8962 { + compatible = "simple-audio-card"; + simple-audio-card,name = "wm8962"; + simple-audio-card,format = "i2s"; + simple-audio-card,widgets = "Headphone", "Headphones", + "Microphone", "Headset Mic", + "Speaker", "Speaker"; + simple-audio-card,routing = "Headphones", "HPOUTL", + "Headphones", "HPOUTR", + "Speaker", "SPKOUTL", + "Speaker", "SPKOUTR", + "Headset Mic", "MICBIAS", + "IN3R", "Headset Mic"; + + simple-audio-card,cpu { + sound-dai = <&sai3>; + }; + + simple-audio-card,codec { + sound-dai = <&wm8962>; + clocks = <&clk IMX8MN_CLK_SAI3_ROOT>; + frame-master; + bitclock-master; + }; }; }; @@ -96,6 +119,36 @@ }; }; +&i2c2 { + clock-frequency = <384000>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c2>; + status = "okay"; + + camera@10 { + compatible = "ovti,ov5640"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_ov5640>; + reg = <0x10>; + clocks = <&clk IMX8MN_CLK_CLKO1>; + clock-names = "xclk"; + assigned-clocks = <&clk IMX8MN_CLK_CLKO1>; + assigned-clock-parents = <&clk IMX8MN_CLK_24M>; + assigned-clock-rates = <24000000>; + AVDD-supply = <®_camera>; /* 2.8v */ + powerdown-gpios = <&gpio1 7 GPIO_ACTIVE_HIGH>; + reset-gpios = <&gpio1 6 GPIO_ACTIVE_LOW>; + + port { + /* MIPI CSI-2 bus endpoint */ + ov5640_to_mipi_csi2: endpoint { + remote-endpoint = <&mipi_csi_in>; + clock-lanes = <0>; + data-lanes = <1 2>; + }; + }; + }; +}; &i2c4 { clock-frequency = <400000>; pinctrl-names = "default"; @@ -142,14 +195,32 @@ 0x0000 /* 4:FN_DMICCDAT */ 0x0000 /* 5:Default */ >; + #sound-dai-cells = <0>; }; }; +&isi { + status = "okay"; +}; + &easrc { fsl,asrc-rate = <48000>; status = "okay"; }; +&mipi_csi { + status = "okay"; + + ports { + port@0 { + mipi_csi_in: endpoint { + remote-endpoint = <&ov5640_to_mipi_csi2>; + data-lanes = <1 2>; + }; + }; + }; +}; + &sai3 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_sai3>; @@ -226,6 +297,14 @@ >; }; + pinctrl_ov5640: ov5640grp { + fsl,pins = < + MX8MN_IOMUXC_GPIO1_IO07_GPIO1_IO7 0x19 + MX8MN_IOMUXC_GPIO1_IO06_GPIO1_IO6 0x19 + MX8MN_IOMUXC_GPIO1_IO14_CCMSRCGPCMIX_CLKO1 0x59 + >; + }; + pinctrl_pcal6414: pcal6414-gpiogrp { fsl,pins = < MX8MN_IOMUXC_SAI2_MCLK_GPIO4_IO27 0x19 diff --git a/arch/arm64/boot/dts/freescale/imx8mn-var-som-symphony.dts b/arch/arm64/boot/dts/freescale/imx8mn-var-som-symphony.dts index 3ed7021a487cf11e4b5533b4b9bf512815adcb7c..406a711486da53a18fc8dd9ccbcdd672a4c48ebf 100644 --- a/arch/arm64/boot/dts/freescale/imx8mn-var-som-symphony.dts +++ b/arch/arm64/boot/dts/freescale/imx8mn-var-som-symphony.dts @@ -152,46 +152,6 @@ extcon = <&extcon_usbotg1>, <&extcon_usbotg1>; }; -&pinctrl_fec1 { - fsl,pins = < - MX8MN_IOMUXC_ENET_MDC_ENET1_MDC 0x3 - MX8MN_IOMUXC_ENET_MDIO_ENET1_MDIO 0x3 - MX8MN_IOMUXC_ENET_TD3_ENET1_RGMII_TD3 0x1f - MX8MN_IOMUXC_ENET_TD2_ENET1_RGMII_TD2 0x1f - MX8MN_IOMUXC_ENET_TD1_ENET1_RGMII_TD1 0x1f - MX8MN_IOMUXC_ENET_TD0_ENET1_RGMII_TD0 0x1f - MX8MN_IOMUXC_ENET_RD3_ENET1_RGMII_RD3 0x91 - MX8MN_IOMUXC_ENET_RD2_ENET1_RGMII_RD2 0x91 - MX8MN_IOMUXC_ENET_RD1_ENET1_RGMII_RD1 0x91 - MX8MN_IOMUXC_ENET_RD0_ENET1_RGMII_RD0 0x91 - MX8MN_IOMUXC_ENET_TXC_ENET1_RGMII_TXC 0x1f - MX8MN_IOMUXC_ENET_RXC_ENET1_RGMII_RXC 0x91 - MX8MN_IOMUXC_ENET_RX_CTL_ENET1_RGMII_RX_CTL 0x91 - MX8MN_IOMUXC_ENET_TX_CTL_ENET1_RGMII_TX_CTL 0x1f - /* Remove the MX8MM_IOMUXC_GPIO1_IO09_GPIO1_IO9 as not used */ - >; -}; - -&pinctrl_fec1_sleep { - fsl,pins = < - MX8MN_IOMUXC_ENET_MDC_GPIO1_IO16 0x120 - MX8MN_IOMUXC_ENET_MDIO_GPIO1_IO17 0x120 - MX8MN_IOMUXC_ENET_TD3_GPIO1_IO18 0x120 - MX8MN_IOMUXC_ENET_TD2_GPIO1_IO19 0x120 - MX8MN_IOMUXC_ENET_TD1_GPIO1_IO20 0x120 - MX8MN_IOMUXC_ENET_TD0_GPIO1_IO21 0x120 - MX8MN_IOMUXC_ENET_RD3_GPIO1_IO29 0x120 - MX8MN_IOMUXC_ENET_RD2_GPIO1_IO28 0x120 - MX8MN_IOMUXC_ENET_RD1_GPIO1_IO27 0x120 - MX8MN_IOMUXC_ENET_RD0_GPIO1_IO26 0x120 - MX8MN_IOMUXC_ENET_TXC_GPIO1_IO23 0x120 - MX8MN_IOMUXC_ENET_RXC_GPIO1_IO25 0x120 - MX8MN_IOMUXC_ENET_RX_CTL_GPIO1_IO24 0x120 - MX8MN_IOMUXC_ENET_TX_CTL_GPIO1_IO22 0x120 - /* Remove the MX8MM_IOMUXC_GPIO1_IO09_GPIO1_IO9 as not used */ - >; -}; - &iomuxc { pinctrl_captouch: captouchgrp { fsl,pins = < diff --git a/arch/arm64/boot/dts/freescale/imx8mn-var-som.dtsi b/arch/arm64/boot/dts/freescale/imx8mn-var-som.dtsi index cbd9d124c80d09adcdc630a8cf4710e89201aa50..d3a67109d55b267a16425f1c1efb30ac785fc2d1 100644 --- a/arch/arm64/boot/dts/freescale/imx8mn-var-som.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mn-var-som.dtsi @@ -27,6 +27,7 @@ regulator-name = "eth_phy_pwr"; regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; + regulator-enable-ramp-delay = <20000>; gpio = <&gpio2 9 GPIO_ACTIVE_HIGH>; enable-active-high; }; @@ -228,6 +229,12 @@ }; }; }; + + eeprom_som: eeprom@52 { + compatible = "atmel,24c04"; + reg = <0x52>; + pagesize = <16>; + }; }; &i2c3 { diff --git a/arch/arm64/boot/dts/freescale/imx8mn-venice-gw7902.dts b/arch/arm64/boot/dts/freescale/imx8mn-venice-gw7902.dts index 7c12518dbc96371ce1eeefb6238455322f8da247..2ddba4213001b202239085e31aaec529e3c5b5fd 100644 --- a/arch/arm64/boot/dts/freescale/imx8mn-venice-gw7902.dts +++ b/arch/arm64/boot/dts/freescale/imx8mn-venice-gw7902.dts @@ -325,7 +325,7 @@ }; channel@8 { - gw,mode = <1>; + gw,mode = <3>; reg = <0x08>; label = "vdd_bat"; }; diff --git a/arch/arm64/boot/dts/freescale/imx8mn.dtsi b/arch/arm64/boot/dts/freescale/imx8mn.dtsi index 8be8f090e8b8e9e7c89a998463b23b067e40ff30..9869fe7652fcaf75e083d5e5b771de520a44d8e7 100644 --- a/arch/arm64/boot/dts/freescale/imx8mn.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mn.dtsi @@ -1104,6 +1104,30 @@ }; }; + isi: isi@32e20000 { + compatible = "fsl,imx8mn-isi"; + reg = <0x32e20000 0x8000>; + interrupts = ; + clocks = <&clk IMX8MN_CLK_DISP_AXI_ROOT>, + <&clk IMX8MN_CLK_DISP_APB_ROOT>; + clock-names = "axi", "apb"; + fsl,blk-ctrl = <&disp_blk_ctrl>; + power-domains = <&disp_blk_ctrl IMX8MN_DISPBLK_PD_ISI>; + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + isi_in: endpoint { + remote-endpoint = <&mipi_csi_out>; + }; + }; + }; + }; + disp_blk_ctrl: blk-ctrl@32e28000 { compatible = "fsl,imx8mn-disp-blk-ctrl", "syscon"; reg = <0x32e28000 0x100>; @@ -1147,6 +1171,42 @@ #power-domain-cells = <1>; }; + mipi_csi: mipi-csi@32e30000 { + compatible = "fsl,imx8mm-mipi-csi2"; + reg = <0x32e30000 0x1000>; + interrupts = ; + assigned-clocks = <&clk IMX8MN_CLK_CAMERA_PIXEL>, + <&clk IMX8MN_CLK_CSI1_PHY_REF>; + assigned-clock-parents = <&clk IMX8MN_SYS_PLL2_1000M>, + <&clk IMX8MN_SYS_PLL2_1000M>; + assigned-clock-rates = <333000000>; + clock-frequency = <333000000>; + clocks = <&clk IMX8MN_CLK_DISP_APB_ROOT>, + <&clk IMX8MN_CLK_CAMERA_PIXEL>, + <&clk IMX8MN_CLK_CSI1_PHY_REF>, + <&clk IMX8MN_CLK_DISP_AXI_ROOT>; + clock-names = "pclk", "wrap", "phy", "axi"; + power-domains = <&disp_blk_ctrl IMX8MN_DISPBLK_PD_MIPI_CSI>; + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + }; + + port@1 { + reg = <1>; + + mipi_csi_out: endpoint { + remote-endpoint = <&isi_in>; + }; + }; + }; + }; + usbotg1: usb@32e40000 { compatible = "fsl,imx8mn-usb", "fsl,imx7d-usb", "fsl,imx27-usb"; reg = <0x32e40000 0x200>; diff --git a/arch/arm64/boot/dts/freescale/imx8mp-beacon-kit.dts b/arch/arm64/boot/dts/freescale/imx8mp-beacon-kit.dts index cdae45a48c2cb96278fa9de42aa274fbec6d0498..06e91297fb163b8a8488f3f2c0bf419bcf90ba5d 100644 --- a/arch/arm64/boot/dts/freescale/imx8mp-beacon-kit.dts +++ b/arch/arm64/boot/dts/freescale/imx8mp-beacon-kit.dts @@ -118,6 +118,15 @@ clock-frequency = <100000000>; }; + reg_audio: regulator-wm8962 { + compatible = "regulator-fixed"; + regulator-name = "3v3_aud"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + gpio = <&pca6416_1 11 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + reg_usdhc2_vmmc: regulator-usdhc2 { compatible = "regulator-fixed"; regulator-name = "VSD_3V3"; @@ -137,6 +146,32 @@ gpio = <&pca6416_1 0 GPIO_ACTIVE_HIGH>; enable-active-high; }; + + sound-wm8962 { + compatible = "simple-audio-card"; + simple-audio-card,name = "wm8962"; + simple-audio-card,format = "i2s"; + simple-audio-card,widgets = "Headphone", "Headphones", + "Microphone", "Headset Mic", + "Speaker", "Speaker"; + simple-audio-card,routing = "Headphones", "HPOUTL", + "Headphones", "HPOUTR", + "Speaker", "SPKOUTL", + "Speaker", "SPKOUTR", + "Headset Mic", "MICBIAS", + "IN3R", "Headset Mic"; + + simple-audio-card,cpu { + sound-dai = <&sai3>; + }; + + simple-audio-card,codec { + sound-dai = <&wm8962>; + clocks = <&clk IMX8MP_CLK_IPP_DO_CLKO1>; + frame-master; + bitclock-master; + }; + }; }; &ecspi2 { @@ -239,6 +274,34 @@ clock-frequency = <384000>; status = "okay"; + wm8962: audio-codec@1a { + compatible = "wlf,wm8962"; + reg = <0x1a>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_wm8962>; + clocks = <&clk IMX8MP_CLK_IPP_DO_CLKO1>; + assigned-clocks = <&clk IMX8MP_CLK_IPP_DO_CLKO1>; + assigned-clock-parents = <&clk IMX8MP_AUDIO_PLL2_OUT>; + assigned-clock-rates = <22576000>; + DCVDD-supply = <®_audio>; + DBVDD-supply = <®_audio>; + AVDD-supply = <®_audio>; + CPVDD-supply = <®_audio>; + MICVDD-supply = <®_audio>; + PLLVDD-supply = <®_audio>; + SPKVDD1-supply = <®_audio>; + SPKVDD2-supply = <®_audio>; + gpio-cfg = < + 0x0000 /* 0:Default */ + 0x0000 /* 1:Default */ + 0x0000 /* 2:FN_DMICCLK */ + 0x0000 /* 3:Default */ + 0x0000 /* 4:FN_DMICCDAT */ + 0x0000 /* 5:Default */ + >; + #sound-dai-cells = <0>; + }; + pca6416: gpio@20 { compatible = "nxp,pcal6416"; reg = <0x20>; @@ -315,6 +378,16 @@ status = "okay"; }; +&sai3 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_sai3>; + assigned-clocks = <&clk IMX8MP_CLK_SAI3>; + assigned-clock-parents = <&clk IMX8MP_AUDIO_PLL2_OUT>; + assigned-clock-rates = <12288000>; + fsl,sai-mclk-direction-output; + status = "okay"; +}; + &snvs_pwrkey { status = "okay"; }; @@ -477,6 +550,16 @@ >; }; + pinctrl_sai3: sai3grp { + fsl,pins = < + MX8MP_IOMUXC_SAI3_TXFS__AUDIOMIX_SAI3_TX_SYNC 0xd6 + MX8MP_IOMUXC_SAI3_TXC__AUDIOMIX_SAI3_TX_BCLK 0xd6 + MX8MP_IOMUXC_SAI3_RXD__AUDIOMIX_SAI3_RX_DATA00 0xd6 + MX8MP_IOMUXC_SAI3_TXD__AUDIOMIX_SAI3_TX_DATA00 0xd6 + MX8MP_IOMUXC_SAI3_MCLK__AUDIOMIX_SAI3_MCLK 0xd6 + >; + }; + pinctrl_tpm: tpmgrp { fsl,pins = < MX8MP_IOMUXC_SAI1_RXFS__GPIO4_IO00 0x19 /* Reset */ @@ -547,4 +630,10 @@ MX8MP_IOMUXC_SD2_CD_B__GPIO2_IO12 0x1c4 >; }; + + pinctrl_wm8962: wm8962grp { + fsl,pins = < + MX8MP_IOMUXC_GPIO1_IO14__CCM_CLKO1 0x59 + >; + }; }; diff --git a/arch/arm64/boot/dts/freescale/imx8mp-dhcom-pdk2.dts b/arch/arm64/boot/dts/freescale/imx8mp-dhcom-pdk2.dts index 92df6c1277c3633a472f01add5f7f582678ced22..e9fb5f7f39b50435c8ba754f283ad1326c80111a 100644 --- a/arch/arm64/boot/dts/freescale/imx8mp-dhcom-pdk2.dts +++ b/arch/arm64/boot/dts/freescale/imx8mp-dhcom-pdk2.dts @@ -23,6 +23,12 @@ stdout-path = &uart1; }; + clk_ext_audio_codec: clock-codec { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <24000000>; + }; + gpio-keys { compatible = "gpio-keys"; @@ -102,6 +108,43 @@ pinctrl-names = "default"; }; }; + + reg_3p3vdd: regulator-3p3vdd { /* 3.3VDD */ + compatible = "regulator-fixed"; + regulator-always-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-name = "3P3VDD"; + }; + + sound { + compatible = "simple-audio-card"; + simple-audio-card,name = "SGTL5000-Card"; + simple-audio-card,format = "i2s"; + simple-audio-card,bitclock-master = <&codec_dai>; + simple-audio-card,frame-master = <&codec_dai>; + simple-audio-card,widgets = "Headphone", "Headphone Jack"; + simple-audio-card,routing = "Headphone Jack", "HP_OUT"; + + cpu_dai: simple-audio-card,cpu { + sound-dai = <&sai3>; + }; + + codec_dai: simple-audio-card,codec { + sound-dai = <&sgtl5000>; + }; + }; +}; + +&i2c5 { + sgtl5000: codec@a { + compatible = "fsl,sgtl5000"; + reg = <0x0a>; + #sound-dai-cells = <0>; + clocks = <&clk_ext_audio_codec>; + VDDA-supply = <®_3p3vdd>; + VDDIO-supply = <®_vdd_3p3v_awo>; + }; }; &fec { /* Second ethernet */ @@ -155,6 +198,17 @@ status = "okay"; }; +&sai3 { + #sound-dai-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_sai3>; + assigned-clocks = <&clk IMX8MP_CLK_SAI3>; + assigned-clock-parents = <&clk IMX8MP_AUDIO_PLL1_OUT>; + assigned-clock-rates = <12288000>; + fsl,sai-mclk-direction-output; + status = "okay"; +}; + &usb3_1 { fsl,over-current-active-low; }; diff --git a/arch/arm64/boot/dts/freescale/imx8mp-dhcom-pdk3.dts b/arch/arm64/boot/dts/freescale/imx8mp-dhcom-pdk3.dts index b5e76b992a103351f3ff9f1e43b8c19059c94bcb..31d85d5871c91afac7247474d44a2fbf8843496c 100644 --- a/arch/arm64/boot/dts/freescale/imx8mp-dhcom-pdk3.dts +++ b/arch/arm64/boot/dts/freescale/imx8mp-dhcom-pdk3.dts @@ -23,10 +23,16 @@ stdout-path = &uart1; }; - clk_pcie: clock-pcie { + clk_ext_audio_codec: clock-codec { compatible = "fixed-clock"; #clock-cells = <0>; - clock-frequency = <100000000>; + clock-frequency = <24000000>; + }; + + clk_xtal25: clock-xtal25 { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <25000000>; }; connector { @@ -140,12 +146,30 @@ }; }; - reg_avdd: regulator-avdd { /* AUDIO_VDD */ + reg_3p3vdd: regulator-3p3vdd { /* 3.3VDD */ compatible = "regulator-fixed"; regulator-always-on; regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; - regulator-name = "AUDIO_VDD"; + regulator-name = "3P3VDD"; + }; + + sound { + compatible = "simple-audio-card"; + simple-audio-card,name = "SGTL5000-Card"; + simple-audio-card,format = "i2s"; + simple-audio-card,bitclock-master = <&codec_dai>; + simple-audio-card,frame-master = <&codec_dai>; + simple-audio-card,widgets = "Headphone", "Headphone Jack"; + simple-audio-card,routing = "Headphone Jack", "HP_OUT"; + + cpu_dai: simple-audio-card,cpu { + sound-dai = <&sai3>; + }; + + codec_dai: simple-audio-card,codec { + sound-dai = <&sgtl5000>; + }; }; }; @@ -161,6 +185,15 @@ #size-cells = <0>; reg = <0>; + sgtl5000: codec@a { + compatible = "fsl,sgtl5000"; + reg = <0x0a>; + #sound-dai-cells = <0>; + clocks = <&clk_ext_audio_codec>; + VDDA-supply = <®_3p3vdd>; + VDDIO-supply = <®_vdd_3p3v_awo>; + }; + typec@3d { compatible = "nxp,ptn5150"; reg = <0x3d>; @@ -203,6 +236,13 @@ pagesize = <16>; reg = <0x54>; }; + + pcieclk: clock@6b { + compatible = "skyworks,si52144"; + reg = <0x6b>; + clocks = <&clk_xtal25>; + #clock-cells = <1>; + }; }; i2cmuxed1: i2c@1 { /* HDMI DDC I2C */ @@ -244,7 +284,7 @@ }; &pcie_phy { - clocks = <&clk_pcie>; + clocks = <&pcieclk 1>; clock-names = "ref"; fsl,refclk-pad-mode = ; status = "okay"; @@ -256,6 +296,16 @@ status = "okay"; }; +&sai3 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_sai3>; + assigned-clocks = <&clk IMX8MP_CLK_SAI3>; + assigned-clock-parents = <&clk IMX8MP_AUDIO_PLL1_OUT>; + assigned-clock-rates = <12288000>; + fsl,sai-mclk-direction-output; + status = "okay"; +}; + &usb_dwc3_0 { usb-role-switch; diff --git a/arch/arm64/boot/dts/freescale/imx8mp-dhcom-som.dtsi b/arch/arm64/boot/dts/freescale/imx8mp-dhcom-som.dtsi index 7e804f65078432268d40b89240d059757aa09f78..cb1953d14aa907c51fb6a40234d4005d8e7a880f 100644 --- a/arch/arm64/boot/dts/freescale/imx8mp-dhcom-som.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mp-dhcom-som.dtsi @@ -49,6 +49,14 @@ startup-delay-us = <100>; vin-supply = <&buck4>; }; + + reg_vdd_3p3v_awo: regulator-vdd-3p3v-awo { /* VDD_3V3_AWO */ + compatible = "regulator-fixed"; + regulator-always-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-name = "VDD_3P3V_AWO"; + }; }; &A53_0 { @@ -232,6 +240,36 @@ sda-gpios = <&gpio5 19 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; status = "okay"; + tc_bridge: bridge@f { + compatible = "toshiba,tc9595", "toshiba,tc358767"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_tc9595>; + reg = <0xf>; + clock-names = "ref"; + clocks = <&clk IMX8MP_CLK_CLKOUT2>; + assigned-clocks = <&clk IMX8MP_CLK_CLKOUT2_SEL>, + <&clk IMX8MP_CLK_CLKOUT2>, + <&clk IMX8MP_AUDIO_PLL2_OUT>; + assigned-clock-parents = <&clk IMX8MP_AUDIO_PLL2_OUT>; + assigned-clock-rates = <13000000>, <13000000>, <156000000>; + reset-gpios = <&gpio3 21 GPIO_ACTIVE_HIGH>; + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + tc_bridge_in: endpoint { + data-lanes = <1 2 3 4>; + remote-endpoint = <&dsi_out>; + }; + }; + }; + }; + pmic: pmic@25 { compatible = "nxp,pca9450c"; reg = <0x25>; @@ -398,6 +436,22 @@ status = "okay"; }; +&mipi_dsi { + samsung,burst-clock-frequency = <160000000>; + samsung,esc-clock-frequency = <10000000>; + + ports { + port@1 { + reg = <1>; + + dsi_out: endpoint { + data-lanes = <1 2 3 4>; + remote-endpoint = <&tc_bridge_in>; + }; + }; + }; +}; + &pwm1 { pinctrl-0 = <&pinctrl_pwm1>; pinctrl-names = "default"; @@ -863,6 +917,24 @@ >; }; + pinctrl_tc9595: dhcom-tc9595-grp { + fsl,pins = < + /* RESET_DSIBRIDGE */ + MX8MP_IOMUXC_SAI1_RXC__GPIO4_IO01 0x40000146 + /* DSI-CONV_INT Interrupt */ + MX8MP_IOMUXC_SAI5_RXD0__GPIO3_IO21 0x141 + >; + }; + + pinctrl_sai3: dhcom-sai3-grp { + fsl,pins = < + MX8MP_IOMUXC_SAI3_TXFS__AUDIOMIX_SAI3_TX_SYNC 0xd6 + MX8MP_IOMUXC_SAI3_TXC__AUDIOMIX_SAI3_TX_BCLK 0xd6 + MX8MP_IOMUXC_SAI3_RXD__AUDIOMIX_SAI3_RX_DATA00 0xd6 + MX8MP_IOMUXC_SAI3_TXD__AUDIOMIX_SAI3_TX_DATA00 0xd6 + >; + }; + pinctrl_touch: dhcom-touch-grp { fsl,pins = < /* #TOUCH_INT */ diff --git a/arch/arm64/boot/dts/freescale/imx8mp-evk.dts b/arch/arm64/boot/dts/freescale/imx8mp-evk.dts index 7816853162b3fa3388d1b93b2a2ad3b41d146243..fa37ce89f8d3d76da32017bd5b6d55a0ab279b57 100644 --- a/arch/arm64/boot/dts/freescale/imx8mp-evk.dts +++ b/arch/arm64/boot/dts/freescale/imx8mp-evk.dts @@ -40,6 +40,17 @@ clock-frequency = <100000000>; }; + reg_audio_pwr: regulator-audio-pwr { + compatible = "regulator-fixed"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_audio_pwr_reg>; + regulator-name = "audio-pwr"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + gpio = <&gpio4 29 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + reg_can1_stby: regulator-can1-stby { compatible = "regulator-fixed"; regulator-name = "can1-stby"; @@ -83,6 +94,37 @@ gpio = <&gpio2 19 GPIO_ACTIVE_HIGH>; enable-active-high; }; + + sound { + compatible = "simple-audio-card"; + simple-audio-card,name = "wm8960-audio"; + simple-audio-card,format = "i2s"; + simple-audio-card,frame-master = <&cpudai>; + simple-audio-card,bitclock-master = <&cpudai>; + simple-audio-card,widgets = + "Headphone", "Headphone Jack", + "Speaker", "External Speaker", + "Microphone", "Mic Jack"; + simple-audio-card,routing = + "Headphone Jack", "HP_L", + "Headphone Jack", "HP_R", + "External Speaker", "SPK_LP", + "External Speaker", "SPK_LN", + "External Speaker", "SPK_RP", + "External Speaker", "SPK_RN", + "LINPUT1", "Mic Jack", + "LINPUT3", "Mic Jack", + "Mic Jack", "MICB"; + + cpudai: simple-audio-card,cpu { + sound-dai = <&sai3>; + }; + + simple-audio-card,codec { + sound-dai = <&wm8960>; + }; + + }; }; &flexspi { @@ -344,6 +386,18 @@ pinctrl-0 = <&pinctrl_i2c3>; status = "okay"; + wm8960: codec@1a { + compatible = "wlf,wm8960"; + reg = <0x1a>; + #sound-dai-cells = <0>; + clocks = <&audio_blk_ctrl IMX8MP_CLK_AUDIOMIX_SAI3_MCLK1>; + clock-names = "mclk"; + wlf,shared-lrclk; + wlf,hp-cfg = <3 2 3>; + wlf,gpio-cfg = <1 3>; + SPKVDD1-supply = <®_audio_pwr>; + }; + pca6416: gpio@20 { compatible = "ti,tca6416"; reg = <0x20>; @@ -422,6 +476,16 @@ status = "okay"; }; +&sai3 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_sai3>; + assigned-clocks = <&clk IMX8MP_CLK_SAI3>; + assigned-clock-parents = <&clk IMX8MP_AUDIO_PLL1_OUT>; + assigned-clock-rates = <12288000>; + fsl,sai-mclk-direction-output; + status = "okay"; +}; + &snvs_pwrkey { status = "okay"; }; @@ -499,6 +563,12 @@ }; &iomuxc { + pinctrl_audio_pwr_reg: audiopwrreggrp { + fsl,pins = < + MX8MP_IOMUXC_SAI3_RXC__GPIO4_IO29 0xd6 + >; + }; + pinctrl_eqos: eqosgrp { fsl,pins = < MX8MP_IOMUXC_ENET_MDC__ENET_QOS_MDC 0x2 @@ -668,6 +738,16 @@ >; }; + pinctrl_sai3: sai3grp { + fsl,pins = < + MX8MP_IOMUXC_SAI3_TXFS__AUDIOMIX_SAI3_TX_SYNC 0xd6 + MX8MP_IOMUXC_SAI3_TXC__AUDIOMIX_SAI3_TX_BCLK 0xd6 + MX8MP_IOMUXC_SAI3_RXD__AUDIOMIX_SAI3_RX_DATA00 0xd6 + MX8MP_IOMUXC_SAI3_TXD__AUDIOMIX_SAI3_TX_DATA00 0xd6 + MX8MP_IOMUXC_SAI3_MCLK__AUDIOMIX_SAI3_MCLK 0xd6 + >; + }; + pinctrl_uart2: uart2grp { fsl,pins = < MX8MP_IOMUXC_UART2_RXD__UART2_DCE_RX 0x140 diff --git a/arch/arm64/boot/dts/freescale/imx8mp-msc-sm2s-ep1.dts b/arch/arm64/boot/dts/freescale/imx8mp-msc-sm2s-ep1.dts index 470ff8e31e3274bfd461149e30031fe06db36ec8..64d522c71a44869429e49c29600e67bb931f1b09 100644 --- a/arch/arm64/boot/dts/freescale/imx8mp-msc-sm2s-ep1.dts +++ b/arch/arm64/boot/dts/freescale/imx8mp-msc-sm2s-ep1.dts @@ -14,6 +14,67 @@ compatible = "avnet,sm2s-imx8mp-14N0600E-ep1", "avnet,sm2s-imx8mp-14N0600E", "avnet,sm2s-imx8mp", "fsl,imx8mp"; + + reg_vcc_3v3_audio: 3v3-audio-regulator { + compatible = "regulator-fixed"; + regulator-name = "VCC_3V3_AUD"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + reg_vcc_1v8_audio: 1v8-audio-regulator { + compatible = "regulator-fixed"; + regulator-name = "VCC_1V8_AUD"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + sound { + compatible = "simple-audio-card"; + simple-audio-card,name = "sgtl5000-audio"; + simple-audio-card,format = "i2s"; + simple-audio-card,frame-master = <&codec_dai>; + simple-audio-card,bitclock-master = <&codec_dai>; + + simple-audio-card,cpu { + sound-dai = <&sai2>; + }; + + codec_dai: simple-audio-card,codec { + sound-dai = <&sgtl5000>; + }; + }; +}; + +&i2c1 { + sgtl5000: audio-codec@a { + compatible = "fsl,sgtl5000"; + reg = <0x0a>; + + assigned-clocks = <&clk IMX8MP_CLK_CLKOUT1_SEL>; + assigned-clock-parents = <&clk IMX8MP_CLK_24M>; + assigned-clock-rates = <24000000>; + clocks = <&clk IMX8MP_CLK_CLKOUT1>; + clock-names = "mclk"; + #sound-dai-cells = <0>; + + VDDA-supply = <®_vcc_3v3_audio>; + VDDD-supply = <®_vcc_1v8_audio>; + VDDIO-supply = <®_vcc_1v8_audio>; + }; +}; + +/* I2S-0 = sai2 */ +&sai2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_sai2>; + + assigned-clocks = <&clk IMX8MP_CLK_SAI2>; + assigned-clock-parents = <&clk IMX8MP_AUDIO_PLL1_OUT>; + assigned-clock-rates = <12288000>; + + fsl,sai-mclk-direction-output; + status = "okay"; }; &flexcan1 { @@ -32,6 +93,15 @@ pinctrl-names = "default"; pinctrl-0 = <&pinctrl_smarc_gpio>; + pinctrl_sai2: sai2grp { + fsl,pins = < + MX8MP_IOMUXC_SAI2_TXFS__AUDIOMIX_SAI2_TX_SYNC 0xd6 + MX8MP_IOMUXC_SAI2_TXC__AUDIOMIX_SAI2_TX_BCLK 0xd6 + MX8MP_IOMUXC_SAI2_RXD0__AUDIOMIX_SAI2_RX_DATA00 0xd6 + MX8MP_IOMUXC_SAI2_TXD0__AUDIOMIX_SAI2_TX_DATA00 0xd6 + >; + }; + pinctrl_smarc_gpio: smarcgpiosgrp { fsl,pins = , /* GPIO0 */ diff --git a/arch/arm64/boot/dts/freescale/imx8mp-tqma8mpql-mba8mpxl.dts b/arch/arm64/boot/dts/freescale/imx8mp-tqma8mpql-mba8mpxl.dts index d8fb29e7e1484bbd5d32d92407de1e7d54fe5ed8..4240e20d38ac32eb5fa27d169ddadbe625d4f15f 100644 --- a/arch/arm64/boot/dts/freescale/imx8mp-tqma8mpql-mba8mpxl.dts +++ b/arch/arm64/boot/dts/freescale/imx8mp-tqma8mpql-mba8mpxl.dts @@ -202,6 +202,13 @@ }; }; + sound { + compatible = "fsl,imx-audio-tlv320aic32x4"; + model = "tq-tlv320aic32x"; + audio-cpu = <&sai3>; + audio-codec = <&tlv320aic3x04>; + }; + thermal-zones { soc-thermal { trips { @@ -449,6 +456,18 @@ sda-gpios = <&gpio5 17 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; status = "okay"; + tlv320aic3x04: audio-codec@18 { + compatible = "ti,tlv320aic32x4"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_tlv320aic3x04>; + reg = <0x18>; + clock-names = "mclk"; + clocks = <&audio_blk_ctrl IMX8MP_CLK_AUDIOMIX_SAI3_MCLK1>; + reset-gpios = <&gpio4 29 GPIO_ACTIVE_LOW>; + iov-supply = <®_vcc_3v3>; + ldoin-supply = <®_vcc_3v3>; + }; + se97_1c: temperature-sensor@1c { compatible = "nxp,se97b", "jedec,jc-42.4-temp"; reg = <0x1c>; @@ -528,6 +547,16 @@ status = "okay"; }; +&sai3 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_sai3>; + assigned-clocks = <&clk IMX8MP_CLK_SAI3>; + assigned-clock-parents = <&clk IMX8MP_AUDIO_PLL1_OUT>; + assigned-clock-rates = <12288000>; + fsl,sai-mclk-direction-output; + status = "okay"; +}; + &snvs_pwrkey { status = "okay"; }; @@ -843,6 +872,23 @@ fsl,pins = ; }; + pinctrl_sai3: sai3grp { + fsl,pins = < + MX8MP_IOMUXC_SAI3_TXFS__AUDIOMIX_SAI3_TX_SYNC 0x94 + MX8MP_IOMUXC_SAI3_TXC__AUDIOMIX_SAI3_TX_BCLK 0x94 + MX8MP_IOMUXC_SAI3_RXD__AUDIOMIX_SAI3_RX_DATA00 0x94 + MX8MP_IOMUXC_SAI3_TXD__AUDIOMIX_SAI3_TX_DATA00 0x94 + MX8MP_IOMUXC_SAI3_MCLK__AUDIOMIX_SAI3_MCLK 0x94 + >; + }; + + pinctrl_tlv320aic3x04: tlv320aic3x04grp { + fsl,pins = < + /* CODEC RST# */ + MX8MP_IOMUXC_SAI3_RXC__GPIO4_IO29 0x180 + >; + }; + /* X61 */ pinctrl_uart1: uart1grp { fsl,pins = , diff --git a/arch/arm64/boot/dts/freescale/imx8mp-venice-gw702x.dtsi b/arch/arm64/boot/dts/freescale/imx8mp-venice-gw702x.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..560c68e4da6dc836944506bf173d6403381132e7 --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx8mp-venice-gw702x.dtsi @@ -0,0 +1,587 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright 2023 Gateworks Corporation + */ + +#include +#include +#include + +/ { + aliases { + ethernet0 = &eqos; + }; + + memory@40000000 { + device_type = "memory"; + reg = <0x0 0x40000000 0 0x80000000>; + }; + + gpio-keys { + compatible = "gpio-keys"; + + key-user-pb { + label = "user_pb"; + gpios = <&gpio 2 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + + key-user-pb1x { + label = "user_pb1x"; + linux,code = ; + interrupt-parent = <&gsc>; + interrupts = <0>; + }; + + key-erased { + label = "key_erased"; + linux,code = ; + interrupt-parent = <&gsc>; + interrupts = <1>; + }; + + key-eeprom-wp { + label = "eeprom_wp"; + linux,code = ; + interrupt-parent = <&gsc>; + interrupts = <2>; + }; + + key-tamper { + label = "tamper"; + linux,code = ; + interrupt-parent = <&gsc>; + interrupts = <5>; + }; + + switch-hold { + label = "switch_hold"; + linux,code = ; + interrupt-parent = <&gsc>; + interrupts = <7>; + }; + }; +}; + +&A53_0 { + cpu-supply = <&buck3_reg>; +}; + +&A53_1 { + cpu-supply = <&buck3_reg>; +}; + +&A53_2 { + cpu-supply = <&buck3_reg>; +}; + +&A53_3 { + cpu-supply = <&buck3_reg>; +}; + +&eqos { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_eqos>; + phy-mode = "rgmii-id"; + phy-handle = <ðphy0>; + status = "okay"; + + mdio { + compatible = "snps,dwmac-mdio"; + #address-cells = <1>; + #size-cells = <0>; + + ethphy0: ethernet-phy@0 { + compatible = "ethernet-phy-ieee802.3-c22"; + pinctrl-0 = <&pinctrl_ethphy0>; + pinctrl-names = "default"; + reg = <0x0>; + interrupt-parent = <&gpio3>; + interrupts = <16 IRQ_TYPE_EDGE_FALLING>; + ti,rx-internal-delay = ; + ti,tx-internal-delay = ; + tx-fifo-depth = ; + rx-fifo-depth = ; + }; + }; +}; + +&i2c1 { + clock-frequency = <100000>; + pinctrl-names = "default", "gpio"; + pinctrl-0 = <&pinctrl_i2c1>; + pinctrl-1 = <&pinctrl_i2c1_gpio>; + scl-gpios = <&gpio5 14 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + sda-gpios = <&gpio5 15 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + status = "okay"; + + gsc: gsc@20 { + compatible = "gw,gsc"; + reg = <0x20>; + pinctrl-0 = <&pinctrl_gsc>; + interrupt-parent = <&gpio2>; + interrupts = <6 IRQ_TYPE_EDGE_FALLING>; + interrupt-controller; + #interrupt-cells = <1>; + #address-cells = <1>; + #size-cells = <0>; + + adc { + compatible = "gw,gsc-adc"; + #address-cells = <1>; + #size-cells = <0>; + + channel@6 { + gw,mode = <0>; + reg = <0x06>; + label = "temp"; + }; + + channel@8 { + gw,mode = <3>; + reg = <0x08>; + label = "vdd_bat"; + }; + + channel@16 { + gw,mode = <4>; + reg = <0x16>; + label = "fan_tach"; + }; + + channel@82 { + gw,mode = <2>; + reg = <0x82>; + label = "vdd_vin"; + gw,voltage-divider-ohms = <22100 1000>; + }; + + channel@84 { + gw,mode = <2>; + reg = <0x84>; + label = "vdd_adc1"; + gw,voltage-divider-ohms = <10000 10000>; + }; + + channel@86 { + gw,mode = <2>; + reg = <0x86>; + label = "vdd_adc2"; + gw,voltage-divider-ohms = <10000 10000>; + }; + + channel@88 { + gw,mode = <2>; + reg = <0x88>; + label = "vdd_1p0"; + }; + + channel@8c { + gw,mode = <2>; + reg = <0x8c>; + label = "vdd_1p8"; + }; + + channel@8e { + gw,mode = <2>; + reg = <0x8e>; + label = "vdd_2p5"; + }; + + channel@90 { + gw,mode = <2>; + reg = <0x90>; + label = "vdd_3p3"; + gw,voltage-divider-ohms = <10000 10000>; + }; + + channel@92 { + gw,mode = <2>; + reg = <0x92>; + label = "vdd_dram"; + }; + + channel@98 { + gw,mode = <2>; + reg = <0x98>; + label = "vdd_soc"; + }; + + channel@9a { + gw,mode = <2>; + reg = <0x9a>; + label = "vdd_arm"; + }; + + channel@a2 { + gw,mode = <2>; + reg = <0xa2>; + label = "vdd_gsc"; + gw,voltage-divider-ohms = <10000 10000>; + }; + }; + + fan-controller@0 { + compatible = "gw,gsc-fan"; + reg = <0x0a>; + }; + }; + + gpio: gpio@23 { + compatible = "nxp,pca9555"; + reg = <0x23>; + gpio-controller; + #gpio-cells = <2>; + interrupt-parent = <&gsc>; + interrupts = <4>; + }; + + eeprom@50 { + compatible = "atmel,24c02"; + reg = <0x50>; + pagesize = <16>; + }; + + eeprom@51 { + compatible = "atmel,24c02"; + reg = <0x51>; + pagesize = <16>; + }; + + eeprom@52 { + compatible = "atmel,24c02"; + reg = <0x52>; + pagesize = <16>; + }; + + eeprom@53 { + compatible = "atmel,24c02"; + reg = <0x53>; + pagesize = <16>; + }; + + rtc@68 { + compatible = "dallas,ds1672"; + reg = <0x68>; + }; + + pmic@69 { + compatible = "mps,mp5416"; + reg = <0x69>; + + regulators { + /* vdd_soc */ + buck1 { + regulator-name = "buck1"; + regulator-min-microvolt = <850000>; + regulator-max-microvolt = <1000000>; + regulator-always-on; + regulator-boot-on; + }; + + /* vdd_dram */ + buck2 { + regulator-name = "buck2"; + regulator-min-microvolt = <1100000>; + regulator-max-microvolt = <1100000>; + regulator-always-on; + regulator-boot-on; + }; + + /* vdd_arm */ + buck3_reg: buck3 { + regulator-name = "buck3"; + regulator-min-microvolt = <850000>; + regulator-max-microvolt = <1000000>; + regulator-always-on; + regulator-boot-on; + }; + + /* vdd_1p8 */ + buck4 { + regulator-name = "buck4"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + regulator-boot-on; + }; + + /* OUT2: nvcc_snvs_1p8 */ + ldo1 { + regulator-name = "ldo1"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + regulator-boot-on; + }; + + /* OUT3: vdd_1p0 */ + ldo2 { + regulator-name = "ldo2"; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1000000>; + regulator-always-on; + regulator-boot-on; + }; + + /* OUT4: vdd_2p5 */ + ldo3 { + regulator-name = "ldo3"; + regulator-min-microvolt = <2500000>; + regulator-max-microvolt = <2500000>; + regulator-always-on; + regulator-boot-on; + }; + + /* OUT5: vdd_3p3 */ + ldo4 { + regulator-name = "ldo4"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-boot-on; + }; + }; + }; +}; + +/* off-board header */ +&i2c2 { + clock-frequency = <400000>; + pinctrl-names = "default", "gpio"; + pinctrl-0 = <&pinctrl_i2c2>; + pinctrl-1 = <&pinctrl_i2c2_gpio>; + scl-gpios = <&gpio5 16 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + sda-gpios = <&gpio5 17 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + status = "okay"; + + eeprom@52 { + compatible = "atmel,24c32"; + reg = <0x52>; + pagesize = <32>; + }; +}; + +/* off-board header */ +&i2c3 { + clock-frequency = <400000>; + pinctrl-names = "default", "gpio"; + pinctrl-0 = <&pinctrl_i2c3>; + pinctrl-1 = <&pinctrl_i2c3_gpio>; + scl-gpios = <&gpio5 18 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + sda-gpios = <&gpio5 19 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + status = "okay"; +}; + +/* off-board header */ +&uart1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart1>; + status = "okay"; +}; + +/* console */ +&uart2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart2>; + status = "okay"; +}; + +/* off-board header */ +&uart3 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart3>; + status = "okay"; +}; + +/* off-board */ +&usdhc1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usdhc1>; + bus-width = <4>; + non-removable; + status = "okay"; + bus-width = <4>; + non-removable; + status = "okay"; +}; + +/* eMMC */ +&usdhc3 { + pinctrl-names = "default", "state_100mhz", "state_200mhz"; + pinctrl-0 = <&pinctrl_usdhc3>; + pinctrl-1 = <&pinctrl_usdhc3_100mhz>; + pinctrl-2 = <&pinctrl_usdhc3_200mhz>; + bus-width = <8>; + non-removable; + status = "okay"; +}; + +&wdog1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_wdog>; + fsl,ext-reset-output; + status = "okay"; +}; + +&iomuxc { + pinctrl_eqos: eqosgrp { + fsl,pins = < + MX8MP_IOMUXC_ENET_MDC__ENET_QOS_MDC 0x2 + MX8MP_IOMUXC_ENET_MDIO__ENET_QOS_MDIO 0x2 + MX8MP_IOMUXC_ENET_RD0__ENET_QOS_RGMII_RD0 0x90 + MX8MP_IOMUXC_ENET_RD1__ENET_QOS_RGMII_RD1 0x90 + MX8MP_IOMUXC_ENET_RD2__ENET_QOS_RGMII_RD2 0x90 + MX8MP_IOMUXC_ENET_RD3__ENET_QOS_RGMII_RD3 0x90 + MX8MP_IOMUXC_ENET_RXC__CCM_ENET_QOS_CLOCK_GENERATE_RX_CLK 0x90 + MX8MP_IOMUXC_ENET_RX_CTL__ENET_QOS_RGMII_RX_CTL 0x90 + MX8MP_IOMUXC_ENET_TD0__ENET_QOS_RGMII_TD0 0x16 + MX8MP_IOMUXC_ENET_TD1__ENET_QOS_RGMII_TD1 0x16 + MX8MP_IOMUXC_ENET_TD2__ENET_QOS_RGMII_TD2 0x16 + MX8MP_IOMUXC_ENET_TD3__ENET_QOS_RGMII_TD3 0x16 + MX8MP_IOMUXC_ENET_TX_CTL__ENET_QOS_RGMII_TX_CTL 0x16 + MX8MP_IOMUXC_ENET_TXC__CCM_ENET_QOS_CLOCK_GENERATE_TX_CLK 0x16 + >; + }; + + pinctrl_ethphy0: ethphy0grp { + fsl,pins = < + MX8MP_IOMUXC_NAND_DQS__GPIO3_IO14 0x140 /* RST# */ + MX8MP_IOMUXC_NAND_READY_B__GPIO3_IO16 0x150 /* IRQ# */ + >; + }; + + pinctrl_gsc: gscgrp { + fsl,pins = < + MX8MP_IOMUXC_SD1_DATA4__GPIO2_IO06 0x150 /* IRQ# */ + >; + }; + + pinctrl_i2c1: i2c1grp { + fsl,pins = < + MX8MP_IOMUXC_I2C1_SCL__I2C1_SCL 0x400001c2 + MX8MP_IOMUXC_I2C1_SDA__I2C1_SDA 0x400001c2 + >; + }; + + pinctrl_i2c1_gpio: i2c1gpiogrp { + fsl,pins = < + MX8MP_IOMUXC_I2C1_SCL__GPIO5_IO14 0x400001c2 + MX8MP_IOMUXC_I2C1_SDA__GPIO5_IO15 0x400001c2 + >; + }; + + pinctrl_i2c2: i2c2grp { + fsl,pins = < + MX8MP_IOMUXC_I2C2_SCL__I2C2_SCL 0x400001c2 + MX8MP_IOMUXC_I2C2_SDA__I2C2_SDA 0x400001c2 + >; + }; + + pinctrl_i2c2_gpio: i2c2gpiogrp { + fsl,pins = < + MX8MP_IOMUXC_I2C2_SCL__GPIO5_IO16 0x400001c2 + MX8MP_IOMUXC_I2C2_SDA__GPIO5_IO17 0x400001c2 + >; + }; + + pinctrl_i2c3: i2c3grp { + fsl,pins = < + MX8MP_IOMUXC_I2C3_SCL__I2C3_SCL 0x400001c2 + MX8MP_IOMUXC_I2C3_SDA__I2C3_SDA 0x400001c2 + >; + }; + + pinctrl_i2c3_gpio: i2c3gpiogrp { + fsl,pins = < + MX8MP_IOMUXC_I2C3_SCL__GPIO5_IO18 0x400001c2 + MX8MP_IOMUXC_I2C3_SDA__GPIO5_IO19 0x400001c2 + >; + }; + + pinctrl_uart1: uart1grp { + fsl,pins = < + MX8MP_IOMUXC_UART1_RXD__UART1_DCE_RX 0x140 + MX8MP_IOMUXC_UART1_TXD__UART1_DCE_TX 0x140 + >; + }; + + pinctrl_uart2: uart2grp { + fsl,pins = < + MX8MP_IOMUXC_UART2_RXD__UART2_DCE_RX 0x140 + MX8MP_IOMUXC_UART2_TXD__UART2_DCE_TX 0x140 + >; + }; + + pinctrl_uart3: uart3grp { + fsl,pins = < + MX8MP_IOMUXC_UART3_RXD__UART3_DCE_RX 0x140 + MX8MP_IOMUXC_UART3_TXD__UART3_DCE_TX 0x140 + >; + }; + + pinctrl_usdhc1: usdhc1grp { + fsl,pins = < + MX8MP_IOMUXC_SD1_CLK__USDHC1_CLK 0x190 + MX8MP_IOMUXC_SD1_CMD__USDHC1_CMD 0x1d0 + MX8MP_IOMUXC_SD1_DATA0__USDHC1_DATA0 0x1d0 + MX8MP_IOMUXC_SD1_DATA1__USDHC1_DATA1 0x1d0 + MX8MP_IOMUXC_SD1_DATA2__USDHC1_DATA2 0x1d0 + MX8MP_IOMUXC_SD1_DATA3__USDHC1_DATA3 0x1d0 + >; + }; + + pinctrl_usdhc3: usdhc3grp { + fsl,pins = < + MX8MP_IOMUXC_NAND_WE_B__USDHC3_CLK 0x190 + MX8MP_IOMUXC_NAND_WP_B__USDHC3_CMD 0x1d0 + MX8MP_IOMUXC_NAND_DATA04__USDHC3_DATA0 0x1d0 + MX8MP_IOMUXC_NAND_DATA05__USDHC3_DATA1 0x1d0 + MX8MP_IOMUXC_NAND_DATA06__USDHC3_DATA2 0x1d0 + MX8MP_IOMUXC_NAND_DATA07__USDHC3_DATA3 0x1d0 + MX8MP_IOMUXC_NAND_RE_B__USDHC3_DATA4 0x1d0 + MX8MP_IOMUXC_NAND_CE2_B__USDHC3_DATA5 0x1d0 + MX8MP_IOMUXC_NAND_CE3_B__USDHC3_DATA6 0x1d0 + MX8MP_IOMUXC_NAND_CLE__USDHC3_DATA7 0x1d0 + MX8MP_IOMUXC_NAND_CE1_B__USDHC3_STROBE 0x190 + >; + }; + + pinctrl_usdhc3_100mhz: usdhc3-100mhzgrp { + fsl,pins = < + MX8MP_IOMUXC_NAND_WE_B__USDHC3_CLK 0x194 + MX8MP_IOMUXC_NAND_WP_B__USDHC3_CMD 0x1d4 + MX8MP_IOMUXC_NAND_DATA04__USDHC3_DATA0 0x1d4 + MX8MP_IOMUXC_NAND_DATA05__USDHC3_DATA1 0x1d4 + MX8MP_IOMUXC_NAND_DATA06__USDHC3_DATA2 0x1d4 + MX8MP_IOMUXC_NAND_DATA07__USDHC3_DATA3 0x1d4 + MX8MP_IOMUXC_NAND_RE_B__USDHC3_DATA4 0x1d4 + MX8MP_IOMUXC_NAND_CE2_B__USDHC3_DATA5 0x1d4 + MX8MP_IOMUXC_NAND_CE3_B__USDHC3_DATA6 0x1d4 + MX8MP_IOMUXC_NAND_CLE__USDHC3_DATA7 0x1d4 + MX8MP_IOMUXC_NAND_CE1_B__USDHC3_STROBE 0x194 + >; + }; + + pinctrl_usdhc3_200mhz: usdhc3-200mhzgrp { + fsl,pins = < + MX8MP_IOMUXC_NAND_WE_B__USDHC3_CLK 0x196 + MX8MP_IOMUXC_NAND_WP_B__USDHC3_CMD 0x1d6 + MX8MP_IOMUXC_NAND_DATA04__USDHC3_DATA0 0x1d6 + MX8MP_IOMUXC_NAND_DATA05__USDHC3_DATA1 0x1d6 + MX8MP_IOMUXC_NAND_DATA06__USDHC3_DATA2 0x1d6 + MX8MP_IOMUXC_NAND_DATA07__USDHC3_DATA3 0x1d6 + MX8MP_IOMUXC_NAND_RE_B__USDHC3_DATA4 0x1d6 + MX8MP_IOMUXC_NAND_CE2_B__USDHC3_DATA5 0x1d6 + MX8MP_IOMUXC_NAND_CE3_B__USDHC3_DATA6 0x1d6 + MX8MP_IOMUXC_NAND_CLE__USDHC3_DATA7 0x1d6 + MX8MP_IOMUXC_NAND_CE1_B__USDHC3_STROBE 0x196 + >; + }; + + pinctrl_wdog: wdoggrp { + fsl,pins = < + MX8MP_IOMUXC_GPIO1_IO02__WDOG1_WDOG_B 0x166 + >; + }; +}; diff --git a/arch/arm64/boot/dts/freescale/imx8mp-venice-gw74xx.dts b/arch/arm64/boot/dts/freescale/imx8mp-venice-gw74xx.dts index eb51d648359bed38b1b4a2e87c953be82f4864ba..92514b71b5f4a99b00cf1f4b2ed0666184553d8a 100644 --- a/arch/arm64/boot/dts/freescale/imx8mp-venice-gw74xx.dts +++ b/arch/arm64/boot/dts/freescale/imx8mp-venice-gw74xx.dts @@ -281,7 +281,7 @@ }; channel@8 { - gw,mode = <1>; + gw,mode = <3>; reg = <0x08>; label = "vdd_bat"; }; diff --git a/arch/arm64/boot/dts/freescale/imx8mp-venice-gw7905-2x.dts b/arch/arm64/boot/dts/freescale/imx8mp-venice-gw7905-2x.dts new file mode 100644 index 0000000000000000000000000000000000000000..4a1bbbbe19e66a6b9274a7a2ef735e00e833875d --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx8mp-venice-gw7905-2x.dts @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright 2023 Gateworks Corporation + */ + +/dts-v1/; + +#include "imx8mp.dtsi" +#include "imx8mp-venice-gw702x.dtsi" +#include "imx8mp-venice-gw7905.dtsi" + +/ { + model = "Gateworks Venice GW7905-2x i.MX8MP Development Kit"; + compatible = "gateworks,imx8mp-gw7905-2x", "fsl,imx8mp"; + + chosen { + stdout-path = &uart2; + }; +}; + +/* Disable SOM interfaces not used on baseboard */ +&eqos { + status = "disabled"; +}; + +&usdhc1 { + status = "disabled"; +}; diff --git a/arch/arm64/boot/dts/freescale/imx8mp-venice-gw7905.dtsi b/arch/arm64/boot/dts/freescale/imx8mp-venice-gw7905.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..0d40cb0f05f6771d5173ebd5498440645645c569 --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx8mp-venice-gw7905.dtsi @@ -0,0 +1,309 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright 2023 Gateworks Corporation + */ + +#include +#include +#include + +/ { + led-controller { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_gpio_leds>; + + led-0 { + function = LED_FUNCTION_STATUS; + color = ; + gpios = <&gpio4 22 GPIO_ACTIVE_HIGH>; + default-state = "on"; + linux,default-trigger = "heartbeat"; + }; + + led-1 { + function = LED_FUNCTION_STATUS; + color = ; + gpios = <&gpio4 27 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + }; + + pcie0_refclk: pcie0-refclk { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <100000000>; + }; + + pps { + compatible = "pps-gpio"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_pps>; + gpios = <&gpio4 21 GPIO_ACTIVE_HIGH>; + status = "okay"; + }; + + reg_usb2_vbus: regulator-usb2-vbus { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_reg_usb2_en>; + compatible = "regulator-fixed"; + regulator-name = "usb2_vbus"; + gpio = <&gpio4 12 GPIO_ACTIVE_HIGH>; + enable-active-high; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + }; + + reg_usdhc2_vmmc: regulator-usdhc2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_reg_usdhc2_vmmc>; + compatible = "regulator-fixed"; + regulator-name = "SD2_3P3V"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + gpio = <&gpio2 19 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; +}; + +/* off-board header */ +&ecspi2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_spi2>; + cs-gpios = <&gpio5 13 GPIO_ACTIVE_LOW>; + status = "okay"; +}; + +&gpio4 { + gpio-line-names = + "", "", "", "", + "", "", "", "", + "", "", "", "", + "", "gpioa", "", "", + "", "", "", "", + "", "", "", "", + "", "", "", "", + "", "", "", ""; +}; + +&gpio4 { + gpio-line-names = + "", "gpiod", "", "", + "gpiob", "gpioc", "", "", + "", "", "", "", + "", "", "", "", + "", "", "", "", + "", "", "", "", + "", "", "pci_usb_sel", "", + "pci_wdis#", "", "", ""; +}; + +&i2c2 { + clock-frequency = <400000>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c2>; + status = "okay"; + + eeprom@52 { + compatible = "atmel,24c32"; + reg = <0x52>; + pagesize = <32>; + }; +}; + +/* off-board header */ +&i2c3 { + clock-frequency = <400000>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c3>; + status = "okay"; +}; + +&pcie_phy { + fsl,refclk-pad-mode = ; + fsl,clkreq-unsupported; + clocks = <&pcie0_refclk>; + clock-names = "ref"; + status = "okay"; +}; + +&pcie { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_pcie0>; + reset-gpio = <&gpio4 29 GPIO_ACTIVE_LOW>; + status = "okay"; +}; + +/* GPS */ +&uart1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart1>; + status = "okay"; +}; + +/* USB1 - Type C front panel SINK port J14 */ +&usb3_0 { + status = "okay"; +}; + +&usb3_phy0 { + status = "okay"; +}; + +&usb_dwc3_0 { + dr_mode = "peripheral"; + status = "okay"; +}; + +/* USB2 4-port USB3.0 HUB: + * P1 - USBC connector (host only) + * P2 - USB2 test connector + * P3 - miniPCIe full card + * P4 - miniPCIe half card + */ +&usb3_phy1 { + vbus-supply = <®_usb2_vbus>; + status = "okay"; +}; + +&usb3_1 { + fsl,permanently-attached; + fsl,disable-port-power-control; + status = "okay"; +}; + +&usb_dwc3_1 { + dr_mode = "host"; + status = "okay"; +}; + +/* microSD */ +&usdhc2 { + pinctrl-names = "default", "state_100mhz", "state_200mhz"; + pinctrl-0 = <&pinctrl_usdhc2>, <&pinctrl_usdhc2_gpio>; + pinctrl-1 = <&pinctrl_usdhc2_100mhz>, <&pinctrl_usdhc2_gpio>; + pinctrl-2 = <&pinctrl_usdhc2_200mhz>, <&pinctrl_usdhc2_gpio>; + cd-gpios = <&gpio2 12 GPIO_ACTIVE_LOW>; + vmmc-supply = <®_usdhc2_vmmc>; + bus-width = <4>; + status = "okay"; +}; + +&iomuxc { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_hog>; + + pinctrl_hog: hoggrp { + fsl,pins = < + MX8MP_IOMUXC_GPIO1_IO13__GPIO1_IO13 0x40000040 /* GPIOA */ + MX8MP_IOMUXC_SAI1_RXC__GPIO4_IO01 0x40000040 /* GPIOD */ + MX8MP_IOMUXC_SAI1_RXD2__GPIO4_IO04 0x40000040 /* GPIOB */ + MX8MP_IOMUXC_SAI1_RXD3__GPIO4_IO05 0x40000040 /* GPIOC */ + MX8MP_IOMUXC_SAI2_TXD0__GPIO4_IO26 0x40000106 /* PCI_USBSEL */ + MX8MP_IOMUXC_SAI3_RXFS__GPIO4_IO28 0x40000106 /* PCI_WDIS# */ + >; + }; + + pinctrl_gpio_leds: gpioledgrp { + fsl,pins = < + MX8MP_IOMUXC_SAI2_RXC__GPIO4_IO22 0x6 /* LEDG */ + MX8MP_IOMUXC_SAI2_MCLK__GPIO4_IO27 0x6 /* LEDR */ + >; + }; + + pinctrl_i2c2: i2c2grp { + fsl,pins = < + MX8MP_IOMUXC_I2C2_SCL__I2C2_SCL 0x400001c2 + MX8MP_IOMUXC_I2C2_SDA__I2C2_SDA 0x400001c2 + >; + }; + + pinctrl_i2c3: i2c3grp { + fsl,pins = < + MX8MP_IOMUXC_I2C3_SCL__I2C3_SCL 0x400001c2 + MX8MP_IOMUXC_I2C3_SDA__I2C3_SDA 0x400001c2 + >; + }; + + pinctrl_pcie0: pciegrp { + fsl,pins = < + MX8MP_IOMUXC_SAI3_RXC__GPIO4_IO29 0x106 + >; + }; + + pinctrl_pps: ppsgrp { + fsl,pins = < + MX8MP_IOMUXC_SAI2_RXFS__GPIO4_IO21 0x106 + >; + }; + + pinctrl_reg_usb2_en: regusb2grp { + fsl,pins = < + MX8MP_IOMUXC_SAI1_TXD0__GPIO4_IO12 0x6 /* USBHUB_RST# (ext p/u) */ + >; + }; + + pinctrl_reg_usdhc2_vmmc: regusdhc2vmmcgrp { + fsl,pins = < + MX8MP_IOMUXC_SD2_RESET_B__GPIO2_IO19 0x40 + >; + }; + + pinctrl_spi2: spi2grp { + fsl,pins = < + MX8MP_IOMUXC_ECSPI2_SCLK__ECSPI2_SCLK 0x140 + MX8MP_IOMUXC_ECSPI2_MOSI__ECSPI2_MOSI 0x140 + MX8MP_IOMUXC_ECSPI2_MISO__ECSPI2_MISO 0x140 + MX8MP_IOMUXC_ECSPI2_SS0__GPIO5_IO13 0x140 + >; + }; + + pinctrl_uart1: uart1grp { + fsl,pins = < + MX8MP_IOMUXC_UART1_RXD__UART1_DCE_RX 0x140 + MX8MP_IOMUXC_UART1_TXD__UART1_DCE_TX 0x140 + >; + }; + + pinctrl_usdhc2: usdhc2grp { + fsl,pins = < + MX8MP_IOMUXC_SD2_CLK__USDHC2_CLK 0x190 + MX8MP_IOMUXC_SD2_CMD__USDHC2_CMD 0x1d0 + MX8MP_IOMUXC_SD2_DATA0__USDHC2_DATA0 0x1d0 + MX8MP_IOMUXC_SD2_DATA1__USDHC2_DATA1 0x1d0 + MX8MP_IOMUXC_SD2_DATA2__USDHC2_DATA2 0x1d0 + MX8MP_IOMUXC_SD2_DATA3__USDHC2_DATA3 0x1d0 + MX8MP_IOMUXC_GPIO1_IO04__USDHC2_VSELECT 0xc0 + >; + }; + + pinctrl_usdhc2_100mhz: usdhc2-100mhzgrp { + fsl,pins = < + MX8MP_IOMUXC_SD2_CLK__USDHC2_CLK 0x194 + MX8MP_IOMUXC_SD2_CMD__USDHC2_CMD 0x1d4 + MX8MP_IOMUXC_SD2_DATA0__USDHC2_DATA0 0x1d4 + MX8MP_IOMUXC_SD2_DATA1__USDHC2_DATA1 0x1d4 + MX8MP_IOMUXC_SD2_DATA2__USDHC2_DATA2 0x1d4 + MX8MP_IOMUXC_SD2_DATA3__USDHC2_DATA3 0x1d4 + MX8MP_IOMUXC_GPIO1_IO04__USDHC2_VSELECT 0xc0 + >; + }; + + pinctrl_usdhc2_200mhz: usdhc2-200mhzgrp { + fsl,pins = < + MX8MP_IOMUXC_SD2_CLK__USDHC2_CLK 0x196 + MX8MP_IOMUXC_SD2_CMD__USDHC2_CMD 0x1d6 + MX8MP_IOMUXC_SD2_DATA0__USDHC2_DATA0 0x1d6 + MX8MP_IOMUXC_SD2_DATA1__USDHC2_DATA1 0x1d6 + MX8MP_IOMUXC_SD2_DATA2__USDHC2_DATA2 0x1d6 + MX8MP_IOMUXC_SD2_DATA3__USDHC2_DATA3 0x1d6 + MX8MP_IOMUXC_GPIO1_IO04__USDHC2_VSELECT 0xc0 + >; + }; + + pinctrl_usdhc2_gpio: usdhc2gpiogrp { + fsl,pins = < + MX8MP_IOMUXC_SD2_CD_B__GPIO2_IO12 0x1c4 + >; + }; +}; diff --git a/arch/arm64/boot/dts/freescale/imx8mp.dtsi b/arch/arm64/boot/dts/freescale/imx8mp.dtsi index 428c60462e3d6be7c09f62ea51f48be069af802f..cc406bb338feb6af0919893df57c3bd609f70fec 100644 --- a/arch/arm64/boot/dts/freescale/imx8mp.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mp.dtsi @@ -304,6 +304,210 @@ nvmem-cells = <&imx8mp_uid>; nvmem-cell-names = "soc_unique_id"; + etm0: etm@28440000 { + compatible = "arm,coresight-etm4x", "arm,primecell"; + reg = <0x28440000 0x10000>; + arm,primecell-periphid = <0xbb95d>; + cpu = <&A53_0>; + clocks = <&clk IMX8MP_CLK_MAIN_AXI>; + clock-names = "apb_pclk"; + + out-ports { + port { + etm0_out_port: endpoint { + remote-endpoint = <&ca_funnel_in_port0>; + }; + }; + }; + }; + + etm1: etm@28540000 { + compatible = "arm,coresight-etm4x", "arm,primecell"; + reg = <0x28540000 0x10000>; + arm,primecell-periphid = <0xbb95d>; + cpu = <&A53_1>; + clocks = <&clk IMX8MP_CLK_MAIN_AXI>; + clock-names = "apb_pclk"; + + out-ports { + port { + etm1_out_port: endpoint { + remote-endpoint = <&ca_funnel_in_port1>; + }; + }; + }; + }; + + etm2: etm@28640000 { + compatible = "arm,coresight-etm4x", "arm,primecell"; + reg = <0x28640000 0x10000>; + arm,primecell-periphid = <0xbb95d>; + cpu = <&A53_2>; + clocks = <&clk IMX8MP_CLK_MAIN_AXI>; + clock-names = "apb_pclk"; + + out-ports { + port { + etm2_out_port: endpoint { + remote-endpoint = <&ca_funnel_in_port2>; + }; + }; + }; + }; + + etm3: etm@28740000 { + compatible = "arm,coresight-etm4x", "arm,primecell"; + reg = <0x28740000 0x10000>; + arm,primecell-periphid = <0xbb95d>; + cpu = <&A53_3>; + clocks = <&clk IMX8MP_CLK_MAIN_AXI>; + clock-names = "apb_pclk"; + + out-ports { + port { + etm3_out_port: endpoint { + remote-endpoint = <&ca_funnel_in_port3>; + }; + }; + }; + }; + + funnel { + /* + * non-configurable funnel don't show up on the AMBA + * bus. As such no need to add "arm,primecell". + */ + compatible = "arm,coresight-static-funnel"; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + ca_funnel_in_port0: endpoint { + remote-endpoint = <&etm0_out_port>; + }; + }; + + port@1 { + reg = <1>; + + ca_funnel_in_port1: endpoint { + remote-endpoint = <&etm1_out_port>; + }; + }; + + port@2 { + reg = <2>; + + ca_funnel_in_port2: endpoint { + remote-endpoint = <&etm2_out_port>; + }; + }; + + port@3 { + reg = <3>; + + ca_funnel_in_port3: endpoint { + remote-endpoint = <&etm3_out_port>; + }; + }; + }; + + out-ports { + port { + ca_funnel_out_port0: endpoint { + remote-endpoint = <&hugo_funnel_in_port0>; + }; + }; + }; + }; + + funnel@28c03000 { + compatible = "arm,coresight-dynamic-funnel", "arm,primecell"; + reg = <0x28c03000 0x1000>; + clocks = <&clk IMX8MP_CLK_MAIN_AXI>; + clock-names = "apb_pclk"; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + hugo_funnel_in_port0: endpoint { + remote-endpoint = <&ca_funnel_out_port0>; + }; + }; + + port@1 { + reg = <1>; + + hugo_funnel_in_port1: endpoint { + /* M7 input */ + }; + }; + + port@2 { + reg = <2>; + + hugo_funnel_in_port2: endpoint { + /* DSP input */ + }; + }; + /* the other input ports are not connect to anything */ + }; + + out-ports { + port { + hugo_funnel_out_port0: endpoint { + remote-endpoint = <&etf_in_port>; + }; + }; + }; + }; + + etf@28c04000 { + compatible = "arm,coresight-tmc", "arm,primecell"; + reg = <0x28c04000 0x1000>; + clocks = <&clk IMX8MP_CLK_MAIN_AXI>; + clock-names = "apb_pclk"; + + in-ports { + port { + etf_in_port: endpoint { + remote-endpoint = <&hugo_funnel_out_port0>; + }; + }; + }; + + out-ports { + port { + etf_out_port: endpoint { + remote-endpoint = <&etr_in_port>; + }; + }; + }; + }; + + etr@28c06000 { + compatible = "arm,coresight-tmc", "arm,primecell"; + reg = <0x28c06000 0x1000>; + clocks = <&clk IMX8MP_CLK_MAIN_AXI>; + clock-names = "apb_pclk"; + + in-ports { + port { + etr_in_port: endpoint { + remote-endpoint = <&etf_out_port>; + }; + }; + }; + }; + aips1: bus@30000000 { compatible = "fsl,aips-bus", "simple-bus"; reg = <0x30000000 0x400000>; @@ -534,26 +738,16 @@ <&clk IMX8MP_CLK_A53_CORE>, <&clk IMX8MP_CLK_NOC>, <&clk IMX8MP_CLK_NOC_IO>, - <&clk IMX8MP_CLK_GIC>, - <&clk IMX8MP_CLK_AUDIO_AHB>, - <&clk IMX8MP_CLK_AUDIO_AXI_SRC>, - <&clk IMX8MP_AUDIO_PLL1>, - <&clk IMX8MP_AUDIO_PLL2>; + <&clk IMX8MP_CLK_GIC>; assigned-clock-parents = <&clk IMX8MP_SYS_PLL1_800M>, <&clk IMX8MP_ARM_PLL_OUT>, <&clk IMX8MP_SYS_PLL2_1000M>, <&clk IMX8MP_SYS_PLL1_800M>, - <&clk IMX8MP_SYS_PLL2_500M>, - <&clk IMX8MP_SYS_PLL1_800M>, - <&clk IMX8MP_SYS_PLL1_800M>; + <&clk IMX8MP_SYS_PLL2_500M>; assigned-clock-rates = <0>, <0>, <1000000000>, <800000000>, - <500000000>, - <400000000>, - <800000000>, - <393216000>, - <361267200>; + <500000000>; }; src: reset-controller@30390000 { @@ -595,6 +789,13 @@ reg = ; }; + pgc_audio: power-domain@5 { + #power-domain-cells = <0>; + reg = ; + clocks = <&clk IMX8MP_CLK_AUDIO_ROOT>, + <&clk IMX8MP_CLK_AUDIO_AXI>; + }; + pgc_gpu2d: power-domain@6 { #power-domain-cells = <0>; reg = ; @@ -1147,6 +1348,157 @@ }; }; + aips5: bus@30c00000 { + compatible = "fsl,aips-bus", "simple-bus"; + reg = <0x30c00000 0x400000>; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + spba-bus@30c00000 { + compatible = "fsl,spba-bus", "simple-bus"; + reg = <0x30c00000 0x100000>; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + sai1: sai@30c10000 { + compatible = "fsl,imx8mp-sai", "fsl,imx8mq-sai"; + reg = <0x30c10000 0x10000>; + #sound-dai-cells = <0>; + clocks = <&audio_blk_ctrl IMX8MP_CLK_AUDIOMIX_SAI1_IPG>, + <&clk IMX8MP_CLK_DUMMY>, + <&audio_blk_ctrl IMX8MP_CLK_AUDIOMIX_SAI1_MCLK1>, + <&audio_blk_ctrl IMX8MP_CLK_AUDIOMIX_SAI1_MCLK2>, + <&audio_blk_ctrl IMX8MP_CLK_AUDIOMIX_SAI1_MCLK3>; + clock-names = "bus", "mclk0", "mclk1", "mclk2", "mclk3"; + dmas = <&sdma2 0 2 0>, <&sdma2 1 2 0>; + dma-names = "rx", "tx"; + interrupts = ; + status = "disabled"; + }; + + sai2: sai@30c20000 { + compatible = "fsl,imx8mp-sai", "fsl,imx8mq-sai"; + reg = <0x30c20000 0x10000>; + #sound-dai-cells = <0>; + clocks = <&audio_blk_ctrl IMX8MP_CLK_AUDIOMIX_SAI2_IPG>, + <&clk IMX8MP_CLK_DUMMY>, + <&audio_blk_ctrl IMX8MP_CLK_AUDIOMIX_SAI2_MCLK1>, + <&audio_blk_ctrl IMX8MP_CLK_AUDIOMIX_SAI2_MCLK2>, + <&audio_blk_ctrl IMX8MP_CLK_AUDIOMIX_SAI2_MCLK3>; + clock-names = "bus", "mclk0", "mclk1", "mclk2", "mclk3"; + dmas = <&sdma2 2 2 0>, <&sdma2 3 2 0>; + dma-names = "rx", "tx"; + interrupts = ; + status = "disabled"; + }; + + sai3: sai@30c30000 { + compatible = "fsl,imx8mp-sai", "fsl,imx8mq-sai"; + reg = <0x30c30000 0x10000>; + #sound-dai-cells = <0>; + clocks = <&audio_blk_ctrl IMX8MP_CLK_AUDIOMIX_SAI3_IPG>, + <&clk IMX8MP_CLK_DUMMY>, + <&audio_blk_ctrl IMX8MP_CLK_AUDIOMIX_SAI3_MCLK1>, + <&audio_blk_ctrl IMX8MP_CLK_AUDIOMIX_SAI3_MCLK2>, + <&audio_blk_ctrl IMX8MP_CLK_AUDIOMIX_SAI3_MCLK3>; + clock-names = "bus", "mclk0", "mclk1", "mclk2", "mclk3"; + dmas = <&sdma2 4 2 0>, <&sdma2 5 2 0>; + dma-names = "rx", "tx"; + interrupts = ; + status = "disabled"; + }; + + sai5: sai@30c50000 { + compatible = "fsl,imx8mp-sai", "fsl,imx8mq-sai"; + reg = <0x30c50000 0x10000>; + #sound-dai-cells = <0>; + clocks = <&audio_blk_ctrl IMX8MP_CLK_AUDIOMIX_SAI5_IPG>, + <&clk IMX8MP_CLK_DUMMY>, + <&audio_blk_ctrl IMX8MP_CLK_AUDIOMIX_SAI5_MCLK1>, + <&audio_blk_ctrl IMX8MP_CLK_AUDIOMIX_SAI5_MCLK2>, + <&audio_blk_ctrl IMX8MP_CLK_AUDIOMIX_SAI5_MCLK3>; + clock-names = "bus", "mclk0", "mclk1", "mclk2", "mclk3"; + dmas = <&sdma2 8 2 0>, <&sdma2 9 2 0>; + dma-names = "rx", "tx"; + interrupts = ; + status = "disabled"; + }; + + sai6: sai@30c60000 { + compatible = "fsl,imx8mp-sai", "fsl,imx8mq-sai"; + reg = <0x30c60000 0x10000>; + #sound-dai-cells = <0>; + clocks = <&audio_blk_ctrl IMX8MP_CLK_AUDIOMIX_SAI6_IPG>, + <&clk IMX8MP_CLK_DUMMY>, + <&audio_blk_ctrl IMX8MP_CLK_AUDIOMIX_SAI6_MCLK1>, + <&audio_blk_ctrl IMX8MP_CLK_AUDIOMIX_SAI6_MCLK2>, + <&audio_blk_ctrl IMX8MP_CLK_AUDIOMIX_SAI6_MCLK3>; + clock-names = "bus", "mclk0", "mclk1", "mclk2", "mclk3"; + dmas = <&sdma2 10 2 0>, <&sdma2 11 2 0>; + dma-names = "rx", "tx"; + interrupts = ; + status = "disabled"; + }; + + sai7: sai@30c80000 { + compatible = "fsl,imx8mp-sai", "fsl,imx8mq-sai"; + reg = <0x30c80000 0x10000>; + #sound-dai-cells = <0>; + clocks = <&audio_blk_ctrl IMX8MP_CLK_AUDIOMIX_SAI7_IPG>, + <&clk IMX8MP_CLK_DUMMY>, + <&audio_blk_ctrl IMX8MP_CLK_AUDIOMIX_SAI7_MCLK1>, + <&audio_blk_ctrl IMX8MP_CLK_AUDIOMIX_SAI7_MCLK2>, + <&audio_blk_ctrl IMX8MP_CLK_AUDIOMIX_SAI7_MCLK3>; + clock-names = "bus", "mclk0", "mclk1", "mclk2", "mclk3"; + dmas = <&sdma2 12 2 0>, <&sdma2 13 2 0>; + dma-names = "rx", "tx"; + interrupts = ; + status = "disabled"; + }; + }; + + sdma3: dma-controller@30e00000 { + compatible = "fsl,imx8mp-sdma", "fsl,imx8mq-sdma"; + reg = <0x30e00000 0x10000>; + #dma-cells = <3>; + clocks = <&audio_blk_ctrl IMX8MP_CLK_AUDIOMIX_SDMA3_ROOT>, + <&clk IMX8MP_CLK_AUDIO_ROOT>; + clock-names = "ipg", "ahb"; + interrupts = ; + fsl,sdma-ram-script-name = "imx/sdma/sdma-imx7d.bin"; + }; + + sdma2: dma-controller@30e10000 { + compatible = "fsl,imx8mp-sdma", "fsl,imx8mq-sdma"; + reg = <0x30e10000 0x10000>; + #dma-cells = <3>; + clocks = <&audio_blk_ctrl IMX8MP_CLK_AUDIOMIX_SDMA2_ROOT>, + <&clk IMX8MP_CLK_AUDIO_ROOT>; + clock-names = "ipg", "ahb"; + interrupts = ; + fsl,sdma-ram-script-name = "imx/sdma/sdma-imx7d.bin"; + }; + + audio_blk_ctrl: clock-controller@30e20000 { + compatible = "fsl,imx8mp-audio-blk-ctrl"; + reg = <0x30e20000 0x10000>; + #clock-cells = <1>; + clocks = <&clk IMX8MP_CLK_AUDIO_ROOT>, + <&clk IMX8MP_CLK_SAI1>, + <&clk IMX8MP_CLK_SAI2>, + <&clk IMX8MP_CLK_SAI3>, + <&clk IMX8MP_CLK_SAI5>, + <&clk IMX8MP_CLK_SAI6>, + <&clk IMX8MP_CLK_SAI7>; + clock-names = "ahb", + "sai1", "sai2", "sai3", + "sai5", "sai6", "sai7"; + power-domains = <&pgc_audio>; + }; + }; + noc: interconnect@32700000 { compatible = "fsl,imx8mp-noc", "fsl,imx8m-noc"; reg = <0x32700000 0x100000>; @@ -1174,6 +1526,118 @@ #size-cells = <1>; ranges; + isi_0: isi@32e00000 { + compatible = "fsl,imx8mp-isi"; + reg = <0x32e00000 0x4000>; + interrupts = , + ; + clocks = <&clk IMX8MP_CLK_MEDIA_AXI_ROOT>, + <&clk IMX8MP_CLK_MEDIA_APB_ROOT>; + clock-names = "axi", "apb"; + fsl,blk-ctrl = <&media_blk_ctrl>; + power-domains = <&media_blk_ctrl IMX8MP_MEDIABLK_PD_ISI>; + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + isi_in_0: endpoint { + remote-endpoint = <&mipi_csi_0_out>; + }; + }; + + port@1 { + reg = <1>; + + isi_in_1: endpoint { + remote-endpoint = <&mipi_csi_1_out>; + }; + }; + }; + }; + + dewarp: dwe@32e30000 { + compatible = "nxp,imx8mp-dw100"; + reg = <0x32e30000 0x10000>; + interrupts = ; + clocks = <&clk IMX8MP_CLK_MEDIA_AXI_ROOT>, + <&clk IMX8MP_CLK_MEDIA_APB_ROOT>; + clock-names = "axi", "ahb"; + power-domains = <&media_blk_ctrl IMX8MP_MEDIABLK_PD_DWE>; + }; + + mipi_csi_0: csi@32e40000 { + compatible = "fsl,imx8mp-mipi-csi2", "fsl,imx8mm-mipi-csi2"; + reg = <0x32e40000 0x10000>; + interrupts = ; + clock-frequency = <500000000>; + clocks = <&clk IMX8MP_CLK_MEDIA_APB_ROOT>, + <&clk IMX8MP_CLK_MEDIA_CAM1_PIX_ROOT>, + <&clk IMX8MP_CLK_MEDIA_MIPI_PHY1_REF_ROOT>, + <&clk IMX8MP_CLK_MEDIA_AXI_ROOT>; + clock-names = "pclk", "wrap", "phy", "axi"; + assigned-clocks = <&clk IMX8MP_CLK_MEDIA_CAM1_PIX>; + assigned-clock-parents = <&clk IMX8MP_SYS_PLL2_1000M>; + assigned-clock-rates = <500000000>; + power-domains = <&media_blk_ctrl IMX8MP_MEDIABLK_PD_MIPI_CSI2_1>; + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + }; + + port@1 { + reg = <1>; + + mipi_csi_0_out: endpoint { + remote-endpoint = <&isi_in_0>; + }; + }; + }; + }; + + mipi_csi_1: csi@32e50000 { + compatible = "fsl,imx8mp-mipi-csi2", "fsl,imx8mm-mipi-csi2"; + reg = <0x32e50000 0x10000>; + interrupts = ; + clock-frequency = <266000000>; + clocks = <&clk IMX8MP_CLK_MEDIA_APB_ROOT>, + <&clk IMX8MP_CLK_MEDIA_CAM2_PIX_ROOT>, + <&clk IMX8MP_CLK_MEDIA_MIPI_PHY1_REF_ROOT>, + <&clk IMX8MP_CLK_MEDIA_AXI_ROOT>; + clock-names = "pclk", "wrap", "phy", "axi"; + assigned-clocks = <&clk IMX8MP_CLK_MEDIA_CAM2_PIX>; + assigned-clock-parents = <&clk IMX8MP_SYS_PLL2_1000M>; + assigned-clock-rates = <266000000>; + power-domains = <&media_blk_ctrl IMX8MP_MEDIABLK_PD_MIPI_CSI2_2>; + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + }; + + port@1 { + reg = <1>; + + mipi_csi_1_out: endpoint { + remote-endpoint = <&isi_in_1>; + }; + }; + }; + }; + mipi_dsi: dsi@32e60000 { compatible = "fsl,imx8mp-mipi-dsim"; reg = <0x32e60000 0x400>; diff --git a/arch/arm64/boot/dts/freescale/imx8mq-mnt-reform2.dts b/arch/arm64/boot/dts/freescale/imx8mq-mnt-reform2.dts index 200268660518d8ede95e0cf9ba07e67aa3e8aa7a..3ae3824be0271f8c5804faf63eaf51aafde9875f 100644 --- a/arch/arm64/boot/dts/freescale/imx8mq-mnt-reform2.dts +++ b/arch/arm64/boot/dts/freescale/imx8mq-mnt-reform2.dts @@ -26,7 +26,7 @@ }; panel { - compatible = "innolux,n125hce-gn1", "simple-panel"; + compatible = "innolux,n125hce-gn1"; power-supply = <®_main_3v3>; backlight = <&backlight>; no-hpd; diff --git a/arch/arm64/boot/dts/freescale/imx8mq-tqma8mq-mba8mx.dts b/arch/arm64/boot/dts/freescale/imx8mq-tqma8mq-mba8mx.dts index c5244b608524dd6c3001350b1de240ebf5852ab0..afb3ceb0675179933cb946e81aff61cf424d77d0 100644 --- a/arch/arm64/boot/dts/freescale/imx8mq-tqma8mq-mba8mx.dts +++ b/arch/arm64/boot/dts/freescale/imx8mq-tqma8mq-mba8mx.dts @@ -108,8 +108,6 @@ <&pcie0_refclk>, <&clk IMX8MQ_CLK_PCIE1_PHY>, <&clk IMX8MQ_CLK_PCIE1_AUX>; - epdev_on-supply = <®_vcc_3v3>; - hard-wired = <1>; status = "okay"; }; @@ -122,8 +120,6 @@ <&pcie1_refclk>, <&clk IMX8MQ_CLK_PCIE2_PHY>, <&clk IMX8MQ_CLK_PCIE2_AUX>; - epdev_on-supply = <®_vcc_3v3>; - hard-wired = <1>; status = "okay"; }; diff --git a/arch/arm64/boot/dts/freescale/imx8mq-zii-ultra.dtsi b/arch/arm64/boot/dts/freescale/imx8mq-zii-ultra.dtsi index 3a52679ecd68e543ee161b5c35cfd75c282b10e5..cb777b47baf9b7642f976995ae5bafd9c0562f7f 100644 --- a/arch/arm64/boot/dts/freescale/imx8mq-zii-ultra.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mq-zii-ultra.dtsi @@ -177,7 +177,7 @@ port@2 { reg = <2>; - label = "cpu"; + phy-mode = "rev-rmii"; ethernet = <&fec1>; fixed-link { diff --git a/arch/arm64/boot/dts/freescale/imx8mq.dtsi b/arch/arm64/boot/dts/freescale/imx8mq.dtsi index 0492556a10dbc4151c1c02e03c93c385d7c28df1..1a2d2c04db32949ed810fb43426f721497cb157f 100644 --- a/arch/arm64/boot/dts/freescale/imx8mq.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mq.dtsi @@ -547,11 +547,13 @@ }; lcdif: lcd-controller@30320000 { - compatible = "fsl,imx8mq-lcdif", "fsl,imx28-lcdif"; + compatible = "fsl,imx8mq-lcdif", "fsl,imx6sx-lcdif"; reg = <0x30320000 0x10000>; interrupts = ; - clocks = <&clk IMX8MQ_CLK_LCDIF_PIXEL>; - clock-names = "pix"; + clocks = <&clk IMX8MQ_CLK_LCDIF_PIXEL>, + <&clk IMX8MQ_CLK_DISP_APB_ROOT>, + <&clk IMX8MQ_CLK_DISP_AXI_ROOT>; + clock-names = "pix", "axi", "disp_axi"; assigned-clocks = <&clk IMX8MQ_VIDEO_PLL1_REF_SEL>, <&clk IMX8MQ_VIDEO_PLL1_BYPASS>, <&clk IMX8MQ_CLK_LCDIF_PIXEL>, @@ -1054,9 +1056,11 @@ }; }; - mipi_dsi: mipi-dsi@30a00000 { + mipi_dsi: dsi@30a00000 { compatible = "fsl,imx8mq-nwl-dsi"; reg = <0x30a00000 0x300>; + #address-cells = <1>; + #size-cells = <0>; clocks = <&clk IMX8MQ_CLK_DSI_CORE>, <&clk IMX8MQ_CLK_DSI_AHB>, <&clk IMX8MQ_CLK_DSI_IPG_DIV>, @@ -1577,6 +1581,7 @@ #address-cells = <3>; #size-cells = <2>; device_type = "pci"; + bus-range = <0x00 0xff>; ranges = <0x81000000 0 0x00000000 0x27f80000 0 0x00010000>, /* downstream I/O 64KB */ <0x82000000 0 0x20000000 0x20000000 0 0x07f00000>; /* non-prefetchable memory */ num-lanes = <1>; diff --git a/arch/arm64/boot/dts/freescale/imx8ulp.dtsi b/arch/arm64/boot/dts/freescale/imx8ulp.dtsi index 32193a43ff49da7e76ed6ac329070a74613d966b..57627bdaa851bdb451324dcaeb55df41eabd10cf 100644 --- a/arch/arm64/boot/dts/freescale/imx8ulp.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8ulp.dtsi @@ -52,6 +52,7 @@ A35_L2: l2-cache0 { compatible = "cache"; cache-level = <2>; + cache-unified; }; }; diff --git a/arch/arm64/boot/dts/freescale/imx93-11x11-evk.dts b/arch/arm64/boot/dts/freescale/imx93-11x11-evk.dts index fefb93487291483808a1ed581dc1c1e3f5613c66..c50f46f06f62cd710c5ede27facf46ca9d4e9cd8 100644 --- a/arch/arm64/boot/dts/freescale/imx93-11x11-evk.dts +++ b/arch/arm64/boot/dts/freescale/imx93-11x11-evk.dts @@ -116,6 +116,10 @@ no-mmc; }; +&wdog3 { + status = "okay"; +}; + &iomuxc { pinctrl_eqos: eqosgrp { fsl,pins = < diff --git a/arch/arm64/boot/dts/freescale/imx93.dtsi b/arch/arm64/boot/dts/freescale/imx93.dtsi index e8d49660ac85b00add7f0181b9b8b777bd48fb7f..8643612ace8c7b444451bafb03bf52bfda5acfba 100644 --- a/arch/arm64/boot/dts/freescale/imx93.dtsi +++ b/arch/arm64/boot/dts/freescale/imx93.dtsi @@ -46,12 +46,27 @@ #address-cells = <1>; #size-cells = <0>; + idle-states { + entry-method = "psci"; + + cpu_pd_wait: cpu-pd-wait { + compatible = "arm,idle-state"; + arm,psci-suspend-param = <0x0010033>; + local-timer-stop; + entry-latency-us = <10000>; + exit-latency-us = <7000>; + min-residency-us = <27000>; + wakeup-latency-us = <15000>; + }; + }; + A55_0: cpu@0 { device_type = "cpu"; compatible = "arm,cortex-a55"; reg = <0x0>; enable-method = "psci"; #cooling-cells = <2>; + cpu-idle-states = <&cpu_pd_wait>; }; A55_1: cpu@100 { @@ -60,6 +75,7 @@ reg = <0x100>; enable-method = "psci"; #cooling-cells = <2>; + cpu-idle-states = <&cpu_pd_wait>; }; }; @@ -153,6 +169,24 @@ nxp,no-divider; }; + wdog1: watchdog@442d0000 { + compatible = "fsl,imx93-wdt"; + reg = <0x442d0000 0x10000>; + interrupts = ; + clocks = <&clk IMX93_CLK_WDOG1_GATE>; + timeout-sec = <40>; + status = "disabled"; + }; + + wdog2: watchdog@442e0000 { + compatible = "fsl,imx93-wdt"; + reg = <0x442e0000 0x10000>; + interrupts = ; + clocks = <&clk IMX93_CLK_WDOG2_GATE>; + timeout-sec = <40>; + status = "disabled"; + }; + tpm1: pwm@44310000 { compatible = "fsl,imx7ulp-pwm"; reg = <0x44310000 0x1000>; @@ -287,14 +321,6 @@ #size-cells = <1>; ranges; - mediamix: power-domain@44462400 { - compatible = "fsl,imx93-src-slice"; - reg = <0x44462400 0x400>, <0x44465800 0x400>; - #power-domain-cells = <0>; - clocks = <&clk IMX93_CLK_MEDIA_AXI>, - <&clk IMX93_CLK_MEDIA_APB>; - }; - mlmix: power-domain@44461800 { compatible = "fsl,imx93-src-slice"; reg = <0x44461800 0x400>, <0x44464800 0x400>; @@ -302,6 +328,14 @@ clocks = <&clk IMX93_CLK_ML_APB>, <&clk IMX93_CLK_ML>; }; + + mediamix: power-domain@44462400 { + compatible = "fsl,imx93-src-slice"; + reg = <0x44462400 0x400>, <0x44465800 0x400>; + #power-domain-cells = <0>; + clocks = <&clk IMX93_CLK_MEDIA_AXI>, + <&clk IMX93_CLK_MEDIA_APB>; + }; }; anatop: anatop@44480000 { @@ -344,6 +378,33 @@ status = "disabled"; }; + wdog3: watchdog@42490000 { + compatible = "fsl,imx93-wdt"; + reg = <0x42490000 0x10000>; + interrupts = ; + clocks = <&clk IMX93_CLK_WDOG3_GATE>; + timeout-sec = <40>; + status = "disabled"; + }; + + wdog4: watchdog@424a0000 { + compatible = "fsl,imx93-wdt"; + reg = <0x424a0000 0x10000>; + interrupts = ; + clocks = <&clk IMX93_CLK_WDOG4_GATE>; + timeout-sec = <40>; + status = "disabled"; + }; + + wdog5: watchdog@424b0000 { + compatible = "fsl,imx93-wdt"; + reg = <0x424b0000 0x10000>; + interrupts = ; + clocks = <&clk IMX93_CLK_WDOG5_GATE>; + timeout-sec = <40>; + status = "disabled"; + }; + tpm3: pwm@424e0000 { compatible = "fsl,imx7ulp-pwm"; reg = <0x424e0000 0x1000>; @@ -640,28 +701,6 @@ status = "disabled"; }; - eqos: ethernet@428a0000 { - compatible = "nxp,imx93-dwmac-eqos", "snps,dwmac-5.10a"; - reg = <0x428a0000 0x10000>; - interrupts = , - ; - interrupt-names = "macirq", "eth_wake_irq"; - clocks = <&clk IMX93_CLK_ENET_QOS_GATE>, - <&clk IMX93_CLK_ENET_QOS_GATE>, - <&clk IMX93_CLK_ENET_TIMER2>, - <&clk IMX93_CLK_ENET>, - <&clk IMX93_CLK_ENET_QOS_GATE>; - clock-names = "stmmaceth", "pclk", "ptp_ref", "tx", "mem"; - assigned-clocks = <&clk IMX93_CLK_ENET_TIMER2>, - <&clk IMX93_CLK_ENET>; - assigned-clock-parents = <&clk IMX93_CLK_SYS_PLL_PFD1_DIV2>, - <&clk IMX93_CLK_SYS_PLL_PFD0_DIV2>; - assigned-clock-rates = <100000000>, <250000000>; - intf_mode = <&wakeupmix_gpr 0x28>; - snps,clk-csr = <0>; - status = "disabled"; - }; - fec: ethernet@42890000 { compatible = "fsl,imx93-fec", "fsl,imx8mq-fec", "fsl,imx6sx-fec"; reg = <0x42890000 0x10000>; @@ -685,6 +724,29 @@ assigned-clock-rates = <100000000>, <250000000>, <50000000>; fsl,num-tx-queues = <3>; fsl,num-rx-queues = <3>; + fsl,stop-mode = <&wakeupmix_gpr 0x0c 1>; + status = "disabled"; + }; + + eqos: ethernet@428a0000 { + compatible = "nxp,imx93-dwmac-eqos", "snps,dwmac-5.10a"; + reg = <0x428a0000 0x10000>; + interrupts = , + ; + interrupt-names = "macirq", "eth_wake_irq"; + clocks = <&clk IMX93_CLK_ENET_QOS_GATE>, + <&clk IMX93_CLK_ENET_QOS_GATE>, + <&clk IMX93_CLK_ENET_TIMER2>, + <&clk IMX93_CLK_ENET>, + <&clk IMX93_CLK_ENET_QOS_GATE>; + clock-names = "stmmaceth", "pclk", "ptp_ref", "tx", "mem"; + assigned-clocks = <&clk IMX93_CLK_ENET_TIMER2>, + <&clk IMX93_CLK_ENET>; + assigned-clock-parents = <&clk IMX93_CLK_SYS_PLL_PFD1_DIV2>, + <&clk IMX93_CLK_SYS_PLL_PFD0_DIV2>; + assigned-clock-rates = <100000000>, <250000000>; + intf_mode = <&wakeupmix_gpr 0x28>; + snps,clk-csr = <0>; status = "disabled"; }; @@ -760,6 +822,13 @@ gpio-ranges = <&iomuxc 0 92 16>; }; + ocotp: efuse@47510000 { + compatible = "fsl,imx93-ocotp", "syscon"; + reg = <0x47510000 0x10000>; + #address-cells = <1>; + #size-cells = <1>; + }; + s4muap: mailbox@47520000 { compatible = "fsl,imx93-mu-s4"; reg = <0x47520000 0x10000>; @@ -788,5 +857,11 @@ #power-domain-cells = <1>; status = "disabled"; }; + + ddr-pmu@4e300dc0 { + compatible = "fsl,imx93-ddr-pmu"; + reg = <0x4e300dc0 0x200>; + interrupts = ; + }; }; }; diff --git a/arch/arm64/boot/dts/freescale/s32g2.dtsi b/arch/arm64/boot/dts/freescale/s32g2.dtsi index d8c82da88ca070f5e389b7f74ffc06a000870d86..5ac1cc9ff50ed140a8e0c13456c05bd8310fef0e 100644 --- a/arch/arm64/boot/dts/freescale/s32g2.dtsi +++ b/arch/arm64/boot/dts/freescale/s32g2.dtsi @@ -53,11 +53,13 @@ cluster0_l2: l2-cache0 { compatible = "cache"; cache-level = <2>; + cache-unified; }; cluster1_l2: l2-cache1 { compatible = "cache"; cache-level = <2>; + cache-unified; }; }; diff --git a/arch/arm64/boot/dts/freescale/s32v234.dtsi b/arch/arm64/boot/dts/freescale/s32v234.dtsi index 3e306218d5331a841209d924b6ee926315e7955d..42409ec567925f68317ca239f083784159d2f1c1 100644 --- a/arch/arm64/boot/dts/freescale/s32v234.dtsi +++ b/arch/arm64/boot/dts/freescale/s32v234.dtsi @@ -62,11 +62,13 @@ cluster0_l2_cache: l2-cache0 { compatible = "cache"; cache-level = <2>; + cache-unified; }; cluster1_l2_cache: l2-cache1 { compatible = "cache"; cache-level = <2>; + cache-unified; }; }; diff --git a/arch/arm64/boot/dts/hisilicon/hi3660.dtsi b/arch/arm64/boot/dts/hisilicon/hi3660.dtsi index a57f35eb5ef6054599b7773a9f709f2bdae09871..7e137a884ae555457800439498affbebcd855a78 100644 --- a/arch/arm64/boot/dts/hisilicon/hi3660.dtsi +++ b/arch/arm64/boot/dts/hisilicon/hi3660.dtsi @@ -204,11 +204,13 @@ A53_L2: l2-cache0 { compatible = "cache"; cache-level = <2>; + cache-unified; }; A73_L2: l2-cache1 { compatible = "cache"; cache-level = <2>; + cache-unified; }; }; diff --git a/arch/arm64/boot/dts/hisilicon/hi6220.dtsi b/arch/arm64/boot/dts/hisilicon/hi6220.dtsi index f6d3202b0d1adb10c0d8822347ea8081565b7f61..b7e2cbf466b3b9c5e5a15330bd5e3a397650a915 100644 --- a/arch/arm64/boot/dts/hisilicon/hi6220.dtsi +++ b/arch/arm64/boot/dts/hisilicon/hi6220.dtsi @@ -187,11 +187,13 @@ CLUSTER0_L2: l2-cache0 { compatible = "cache"; cache-level = <2>; + cache-unified; }; CLUSTER1_L2: l2-cache1 { compatible = "cache"; cache-level = <2>; + cache-unified; }; }; @@ -407,7 +409,7 @@ compatible = "pinctrl-single"; reg = <0x0 0xf7010000 0x0 0x27c>; #address-cells = <1>; - #size-cells = <1>; + #size-cells = <0>; #pinctrl-cells = <1>; #gpio-range-cells = <3>; pinctrl-single,register-width = <32>; @@ -446,7 +448,7 @@ compatible = "pinconf-single"; reg = <0x0 0xf7010800 0x0 0x28c>; #address-cells = <1>; - #size-cells = <1>; + #size-cells = <0>; #pinctrl-cells = <1>; pinctrl-single,register-width = <32>; }; @@ -455,7 +457,7 @@ compatible = "pinconf-single"; reg = <0x0 0xf8001800 0x0 0x78>; #address-cells = <1>; - #size-cells = <1>; + #size-cells = <0>; #pinctrl-cells = <1>; pinctrl-single,register-width = <32>; }; diff --git a/arch/arm64/boot/dts/hisilicon/hikey-pinctrl.dtsi b/arch/arm64/boot/dts/hisilicon/hikey-pinctrl.dtsi index e7d22619a4c0b43e34d6e3d2493f9d3a640fd772..3e27624c31def6fd3c5eba65109e3ba11d40d878 100644 --- a/arch/arm64/boot/dts/hisilicon/hikey-pinctrl.dtsi +++ b/arch/arm64/boot/dts/hisilicon/hikey-pinctrl.dtsi @@ -17,13 +17,13 @@ &bl_pwm_pmx_func >; - boot_sel_pmx_func: boot_sel_pmx_func { + boot_sel_pmx_func: boot-sel-pins { pinctrl-single,pins = < 0x0 MUX_M0 /* BOOT_SEL (IOMG000) */ >; }; - emmc_pmx_func: emmc_pmx_func { + emmc_pmx_func: emmc-pins { pinctrl-single,pins = < 0x100 MUX_M0 /* EMMC_CLK (IOMG064) */ 0x104 MUX_M0 /* EMMC_CMD (IOMG065) */ @@ -38,7 +38,7 @@ >; }; - sd_pmx_func: sd_pmx_func { + sd_pmx_func: sd-pins { pinctrl-single,pins = < 0xc MUX_M0 /* SD_CLK (IOMG003) */ 0x10 MUX_M0 /* SD_CMD (IOMG004) */ @@ -48,7 +48,7 @@ 0x20 MUX_M0 /* SD_DATA3 (IOMG008) */ >; }; - sd_pmx_idle: sd_pmx_idle { + sd_pmx_idle: sd-idle-pins { pinctrl-single,pins = < 0xc MUX_M1 /* SD_CLK (IOMG003) */ 0x10 MUX_M1 /* SD_CMD (IOMG004) */ @@ -59,7 +59,7 @@ >; }; - sdio_pmx_func: sdio_pmx_func { + sdio_pmx_func: sdio-pins { pinctrl-single,pins = < 0x128 MUX_M0 /* SDIO_CLK (IOMG074) */ 0x12c MUX_M0 /* SDIO_CMD (IOMG075) */ @@ -69,7 +69,7 @@ 0x13c MUX_M0 /* SDIO_DATA3 (IOMG079) */ >; }; - sdio_pmx_idle: sdio_pmx_idle { + sdio_pmx_idle: sdio-idle-pins { pinctrl-single,pins = < 0x128 MUX_M1 /* SDIO_CLK (IOMG074) */ 0x12c MUX_M1 /* SDIO_CMD (IOMG075) */ @@ -80,7 +80,7 @@ >; }; - isp_pmx_func: isp_pmx_func { + isp_pmx_func: isp-pins { pinctrl-single,pins = < 0x24 MUX_M0 /* ISP_PWDN0 (IOMG009) */ 0x28 MUX_M0 /* ISP_PWDN1 (IOMG010) */ @@ -101,19 +101,19 @@ >; }; - hkadc_ssi_pmx_func: hkadc_ssi_pmx_func { + hkadc_ssi_pmx_func: hkadc-ssi-pins { pinctrl-single,pins = < 0x68 MUX_M0 /* HKADC_SSI (IOMG026) */ >; }; - codec_clk_pmx_func: codec_clk_pmx_func { + codec_clk_pmx_func: codec-clk-pins { pinctrl-single,pins = < 0x6c MUX_M0 /* CODEC_CLK (IOMG027) */ >; }; - codec_pmx_func: codec_pmx_func { + codec_pmx_func: codec-pins { pinctrl-single,pins = < 0x70 MUX_M1 /* DMIC_CLK (IOMG028) */ 0x74 MUX_M0 /* CODEC_SYNC (IOMG029) */ @@ -122,7 +122,7 @@ >; }; - fm_pmx_func: fm_pmx_func { + fm_pmx_func: fm-pins { pinctrl-single,pins = < 0x80 MUX_M1 /* FM_XCLK (IOMG032) */ 0x84 MUX_M1 /* FM_XFS (IOMG033) */ @@ -131,7 +131,7 @@ >; }; - bt_pmx_func: bt_pmx_func { + bt_pmx_func: bt-pins { pinctrl-single,pins = < 0x90 MUX_M0 /* BT_XCLK (IOMG036) */ 0x94 MUX_M0 /* BT_XFS (IOMG037) */ @@ -140,26 +140,26 @@ >; }; - pwm_in_pmx_func: pwm_in_pmx_func { + pwm_in_pmx_func: pwm-in-pins { pinctrl-single,pins = < 0xb8 MUX_M1 /* PWM_IN (IOMG046) */ >; }; - bl_pwm_pmx_func: bl_pwm_pmx_func { + bl_pwm_pmx_func: bl-pwm-pins { pinctrl-single,pins = < 0xbc MUX_M1 /* BL_PWM (IOMG047) */ >; }; - uart0_pmx_func: uart0_pmx_func { + uart0_pmx_func: uart0-pins { pinctrl-single,pins = < 0xc0 MUX_M0 /* UART0_RXD (IOMG048) */ 0xc4 MUX_M0 /* UART0_TXD (IOMG049) */ >; }; - uart1_pmx_func: uart1_pmx_func { + uart1_pmx_func: uart1-pins { pinctrl-single,pins = < 0xc8 MUX_M0 /* UART1_CTS_N (IOMG050) */ 0xcc MUX_M0 /* UART1_RTS_N (IOMG051) */ @@ -168,7 +168,7 @@ >; }; - uart2_pmx_func: uart2_pmx_func { + uart2_pmx_func: uart2-pins { pinctrl-single,pins = < 0xd8 MUX_M0 /* UART2_CTS_N (IOMG054) */ 0xdc MUX_M0 /* UART2_RTS_N (IOMG055) */ @@ -177,7 +177,7 @@ >; }; - uart3_pmx_func: uart3_pmx_func { + uart3_pmx_func: uart3-pins { pinctrl-single,pins = < 0x180 MUX_M1 /* UART3_CTS_N (IOMG096) */ 0x184 MUX_M1 /* UART3_RTS_N (IOMG097) */ @@ -186,7 +186,7 @@ >; }; - uart4_pmx_func: uart4_pmx_func { + uart4_pmx_func: uart4-pins { pinctrl-single,pins = < 0x1d0 MUX_M1 /* UART4_CTS_N (IOMG116) */ 0x1d4 MUX_M1 /* UART4_RTS_N (IOMG117) */ @@ -195,35 +195,35 @@ >; }; - uart5_pmx_func: uart5_pmx_func { + uart5_pmx_func: uart5-pins { pinctrl-single,pins = < 0x1c8 MUX_M1 /* UART5_RXD (IOMG114) */ 0x1cc MUX_M1 /* UART5_TXD (IOMG115) */ >; }; - i2c0_pmx_func: i2c0_pmx_func { + i2c0_pmx_func: i2c0-pins { pinctrl-single,pins = < 0xe8 MUX_M0 /* I2C0_SCL (IOMG058) */ 0xec MUX_M0 /* I2C0_SDA (IOMG059) */ >; }; - i2c1_pmx_func: i2c1_pmx_func { + i2c1_pmx_func: i2c1-pins { pinctrl-single,pins = < 0xf0 MUX_M0 /* I2C1_SCL (IOMG060) */ 0xf4 MUX_M0 /* I2C1_SDA (IOMG061) */ >; }; - i2c2_pmx_func: i2c2_pmx_func { + i2c2_pmx_func: i2c2-pins { pinctrl-single,pins = < 0xf8 MUX_M0 /* I2C2_SCL (IOMG062) */ 0xfc MUX_M0 /* I2C2_SDA (IOMG063) */ >; }; - spi0_pmx_func: spi0_pmx_func { + spi0_pmx_func: spi0-pins { pinctrl-single,pins = < 0x1a0 MUX_M1 /* SPI0_DI (IOMG104) */ 0x1a4 MUX_M1 /* SPI0_DO (IOMG105) */ @@ -244,7 +244,7 @@ &bl_pwm_cfg_func >; - boot_sel_cfg_func: boot_sel_cfg_func { + boot_sel_cfg_func: boot-sel-cfg-pins { pinctrl-single,pins = < 0x0 0x0 /* BOOT_SEL (IOCFG000) */ >; @@ -253,7 +253,7 @@ pinctrl-single,drive-strength = ; }; - hkadc_ssi_cfg_func: hkadc_ssi_cfg_func { + hkadc_ssi_cfg_func: hkadc-ssi-cfg-pins { pinctrl-single,pins = < 0x6c 0x0 /* HKADC_SSI (IOCFG027) */ >; @@ -262,7 +262,7 @@ pinctrl-single,drive-strength = ; }; - emmc_clk_cfg_func: emmc_clk_cfg_func { + emmc_clk_cfg_func: emmc-clk-cfg-pins { pinctrl-single,pins = < 0x104 0x0 /* EMMC_CLK (IOCFG065) */ >; @@ -271,7 +271,7 @@ pinctrl-single,drive-strength = ; }; - emmc_cfg_func: emmc_cfg_func { + emmc_cfg_func: emmc-cfg-pins { pinctrl-single,pins = < 0x108 0x0 /* EMMC_CMD (IOCFG066) */ 0x10c 0x0 /* EMMC_DATA0 (IOCFG067) */ @@ -288,7 +288,7 @@ pinctrl-single,drive-strength = ; }; - emmc_rst_cfg_func: emmc_rst_cfg_func { + emmc_rst_cfg_func: emmc-rst-cfg-pins { pinctrl-single,pins = < 0x12c 0x0 /* EMMC_RST_N (IOCFG075) */ >; @@ -297,7 +297,7 @@ pinctrl-single,drive-strength = ; }; - sd_clk_cfg_func: sd_clk_cfg_func { + sd_clk_cfg_func: sd-clk-cfg-pins { pinctrl-single,pins = < 0xc 0x0 /* SD_CLK (IOCFG003) */ >; @@ -305,7 +305,7 @@ pinctrl-single,bias-pullup = ; pinctrl-single,drive-strength = ; }; - sd_clk_cfg_idle: sd_clk_cfg_idle { + sd_clk_cfg_idle: sd-clk-cfg-idle-pins { pinctrl-single,pins = < 0xc 0x0 /* SD_CLK (IOCFG003) */ >; @@ -314,7 +314,7 @@ pinctrl-single,drive-strength = ; }; - sd_cfg_func: sd_cfg_func { + sd_cfg_func: sd-cfg-pins { pinctrl-single,pins = < 0x10 0x0 /* SD_CMD (IOCFG004) */ 0x14 0x0 /* SD_DATA0 (IOCFG005) */ @@ -326,7 +326,7 @@ pinctrl-single,bias-pullup = ; pinctrl-single,drive-strength = ; }; - sd_cfg_idle: sd_cfg_idle { + sd_cfg_idle: sd-cfg-idle-pins { pinctrl-single,pins = < 0x10 0x0 /* SD_CMD (IOCFG004) */ 0x14 0x0 /* SD_DATA0 (IOCFG005) */ @@ -339,7 +339,7 @@ pinctrl-single,drive-strength = ; }; - sdio_clk_cfg_func: sdio_clk_cfg_func { + sdio_clk_cfg_func: sdio-clk-cfg-pins { pinctrl-single,pins = < 0x134 0x0 /* SDIO_CLK (IOCFG077) */ >; @@ -347,7 +347,7 @@ pinctrl-single,bias-pullup = ; pinctrl-single,drive-strength = ; }; - sdio_clk_cfg_idle: sdio_clk_cfg_idle { + sdio_clk_cfg_idle: sdio-clk-cfg-idle-pins { pinctrl-single,pins = < 0x134 0x0 /* SDIO_CLK (IOCFG077) */ >; @@ -356,7 +356,7 @@ pinctrl-single,drive-strength = ; }; - sdio_cfg_func: sdio_cfg_func { + sdio_cfg_func: sdio-cfg-pins { pinctrl-single,pins = < 0x138 0x0 /* SDIO_CMD (IOCFG078) */ 0x13c 0x0 /* SDIO_DATA0 (IOCFG079) */ @@ -368,7 +368,7 @@ pinctrl-single,bias-pullup = ; pinctrl-single,drive-strength = ; }; - sdio_cfg_idle: sdio_cfg_idle { + sdio_cfg_idle: sdio-cfg-idle-pins { pinctrl-single,pins = < 0x138 0x0 /* SDIO_CMD (IOCFG078) */ 0x13c 0x0 /* SDIO_DATA0 (IOCFG079) */ @@ -381,7 +381,7 @@ pinctrl-single,drive-strength = ; }; - isp_cfg_func1: isp_cfg_func1 { + isp_cfg_func1: isp-cfg-func1-pins { pinctrl-single,pins = < 0x28 0x0 /* ISP_PWDN0 (IOCFG010) */ 0x2c 0x0 /* ISP_PWDN1 (IOCFG011) */ @@ -403,7 +403,7 @@ pinctrl-single,bias-pullup = ; pinctrl-single,drive-strength = ; }; - isp_cfg_idle1: isp_cfg_idle1 { + isp_cfg_idle1: isp-cfg-idle1-pins { pinctrl-single,pins = < 0x34 0x0 /* ISP_SHUTTER0 (IOCFG013) */ 0x38 0x0 /* ISP_SHUTTER1 (IOCFG014) */ @@ -413,7 +413,7 @@ pinctrl-single,drive-strength = ; }; - isp_cfg_func2: isp_cfg_func2 { + isp_cfg_func2: isp-cfg-func2-pins { pinctrl-single,pins = < 0x54 0x0 /* ISP_STROBE1 (IOCFG021) */ >; @@ -422,7 +422,7 @@ pinctrl-single,drive-strength = ; }; - codec_clk_cfg_func: codec_clk_cfg_func { + codec_clk_cfg_func: codec-clk-cfg-pins { pinctrl-single,pins = < 0x70 0x0 /* CODEC_CLK (IOCFG028) */ >; @@ -430,7 +430,7 @@ pinctrl-single,bias-pullup = ; pinctrl-single,drive-strength = ; }; - codec_clk_cfg_idle: codec_clk_cfg_idle { + codec_clk_cfg_idle: codec-clk-cfg-idle-pins { pinctrl-single,pins = < 0x70 0x0 /* CODEC_CLK (IOCFG028) */ >; @@ -439,7 +439,7 @@ pinctrl-single,drive-strength = ; }; - codec_cfg_func1: codec_cfg_func1 { + codec_cfg_func1: codec-cfg-func1-pins { pinctrl-single,pins = < 0x74 0x0 /* DMIC_CLK (IOCFG029) */ >; @@ -448,7 +448,7 @@ pinctrl-single,drive-strength = ; }; - codec_cfg_func2: codec_cfg_func2 { + codec_cfg_func2: codec-cfg-func2-pins { pinctrl-single,pins = < 0x78 0x0 /* CODEC_SYNC (IOCFG030) */ 0x7c 0x0 /* CODEC_DI (IOCFG031) */ @@ -458,7 +458,7 @@ pinctrl-single,bias-pullup = ; pinctrl-single,drive-strength = ; }; - codec_cfg_idle2: codec_cfg_idle2 { + codec_cfg_idle2: codec-cfg-idle2-pins { pinctrl-single,pins = < 0x78 0x0 /* CODEC_SYNC (IOCFG030) */ 0x7c 0x0 /* CODEC_DI (IOCFG031) */ @@ -469,7 +469,7 @@ pinctrl-single,drive-strength = ; }; - fm_cfg_func: fm_cfg_func { + fm_cfg_func: fm-cfg-pins { pinctrl-single,pins = < 0x84 0x0 /* FM_XCLK (IOCFG033) */ 0x88 0x0 /* FM_XFS (IOCFG034) */ @@ -481,7 +481,7 @@ pinctrl-single,drive-strength = ; }; - bt_cfg_func: bt_cfg_func { + bt_cfg_func: bt-cfg-pins { pinctrl-single,pins = < 0x94 0x0 /* BT_XCLK (IOCFG037) */ 0x98 0x0 /* BT_XFS (IOCFG038) */ @@ -492,7 +492,7 @@ pinctrl-single,bias-pullup = ; pinctrl-single,drive-strength = ; }; - bt_cfg_idle: bt_cfg_idle { + bt_cfg_idle: bt-cfg-idle-pins { pinctrl-single,pins = < 0x94 0x0 /* BT_XCLK (IOCFG037) */ 0x98 0x0 /* BT_XFS (IOCFG038) */ @@ -504,7 +504,7 @@ pinctrl-single,drive-strength = ; }; - pwm_in_cfg_func: pwm_in_cfg_func { + pwm_in_cfg_func: pwm-in-cfg-pins { pinctrl-single,pins = < 0xbc 0x0 /* PWM_IN (IOCFG047) */ >; @@ -513,7 +513,7 @@ pinctrl-single,drive-strength = ; }; - bl_pwm_cfg_func: bl_pwm_cfg_func { + bl_pwm_cfg_func: bl-pwm-cfg-pins { pinctrl-single,pins = < 0xc0 0x0 /* BL_PWM (IOCFG048) */ >; @@ -522,7 +522,7 @@ pinctrl-single,drive-strength = ; }; - uart0_cfg_func1: uart0_cfg_func1 { + uart0_cfg_func1: uart0-cfg-func1-pins { pinctrl-single,pins = < 0xc4 0x0 /* UART0_RXD (IOCFG049) */ >; @@ -531,7 +531,7 @@ pinctrl-single,drive-strength = ; }; - uart0_cfg_func2: uart0_cfg_func2 { + uart0_cfg_func2: uart0-cfg-func2-pins { pinctrl-single,pins = < 0xc8 0x0 /* UART0_TXD (IOCFG050) */ >; @@ -540,7 +540,7 @@ pinctrl-single,drive-strength = ; }; - uart1_cfg_func1: uart1_cfg_func1 { + uart1_cfg_func1: uart1-cfg-func1-pins { pinctrl-single,pins = < 0xcc 0x0 /* UART1_CTS_N (IOCFG051) */ 0xd4 0x0 /* UART1_RXD (IOCFG053) */ @@ -550,7 +550,7 @@ pinctrl-single,drive-strength = ; }; - uart1_cfg_func2: uart1_cfg_func2 { + uart1_cfg_func2: uart1-cfg-func2-pins { pinctrl-single,pins = < 0xd0 0x0 /* UART1_RTS_N (IOCFG052) */ 0xd8 0x0 /* UART1_TXD (IOCFG054) */ @@ -560,7 +560,7 @@ pinctrl-single,drive-strength = ; }; - uart2_cfg_func: uart2_cfg_func { + uart2_cfg_func: uart2-cfg-pins { pinctrl-single,pins = < 0xdc 0x0 /* UART2_CTS_N (IOCFG055) */ 0xe0 0x0 /* UART2_RTS_N (IOCFG056) */ @@ -572,7 +572,7 @@ pinctrl-single,drive-strength = ; }; - uart3_cfg_func: uart3_cfg_func { + uart3_cfg_func: uart3-cfg-pins { pinctrl-single,pins = < 0x190 0x0 /* UART3_CTS_N (IOCFG100) */ 0x194 0x0 /* UART3_RTS_N (IOCFG101) */ @@ -584,7 +584,7 @@ pinctrl-single,drive-strength = ; }; - uart4_cfg_func: uart4_cfg_func { + uart4_cfg_func: uart4-cfg-pins { pinctrl-single,pins = < 0x1e0 0x0 /* UART4_CTS_N (IOCFG120) */ 0x1e4 0x0 /* UART4_RTS_N (IOCFG121) */ @@ -596,7 +596,7 @@ pinctrl-single,drive-strength = ; }; - uart5_cfg_func: uart5_cfg_func { + uart5_cfg_func: uart5-cfg-pins { pinctrl-single,pins = < 0x1d8 0x0 /* UART4_RXD (IOCFG118) */ 0x1dc 0x0 /* UART4_TXD (IOCFG119) */ @@ -606,7 +606,7 @@ pinctrl-single,drive-strength = ; }; - i2c0_cfg_func: i2c0_cfg_func { + i2c0_cfg_func: i2c0-cfg-pins { pinctrl-single,pins = < 0xec 0x0 /* I2C0_SCL (IOCFG059) */ 0xf0 0x0 /* I2C0_SDA (IOCFG060) */ @@ -616,7 +616,7 @@ pinctrl-single,drive-strength = ; }; - i2c1_cfg_func: i2c1_cfg_func { + i2c1_cfg_func: i2c1-cfg-pins { pinctrl-single,pins = < 0xf4 0x0 /* I2C1_SCL (IOCFG061) */ 0xf8 0x0 /* I2C1_SDA (IOCFG062) */ @@ -626,7 +626,7 @@ pinctrl-single,drive-strength = ; }; - i2c2_cfg_func: i2c2_cfg_func { + i2c2_cfg_func: i2c2-cfg-pins { pinctrl-single,pins = < 0xfc 0x0 /* I2C2_SCL (IOCFG063) */ 0x100 0x0 /* I2C2_SDA (IOCFG064) */ @@ -636,7 +636,7 @@ pinctrl-single,drive-strength = ; }; - spi0_cfg_func: spi0_cfg_func { + spi0_cfg_func: spi0-cfg-pins { pinctrl-single,pins = < 0x1b0 0x0 /* SPI0_DI (IOCFG108) */ 0x1b4 0x0 /* SPI0_DO (IOCFG109) */ @@ -656,7 +656,7 @@ &rstout_n_cfg_func >; - rstout_n_cfg_func: rstout_n_cfg_func { + rstout_n_cfg_func: rstout-n-cfg-pins { pinctrl-single,pins = < 0x0 0x0 /* RSTOUT_N (IOCFG000) */ >; @@ -665,7 +665,7 @@ pinctrl-single,drive-strength = ; }; - pmu_peri_en_cfg_func: pmu_peri_en_cfg_func { + pmu_peri_en_cfg_func: pmu-peri-en-cfg-pins { pinctrl-single,pins = < 0x4 0x0 /* PMU_PERI_EN (IOCFG001) */ >; @@ -674,7 +674,7 @@ pinctrl-single,drive-strength = ; }; - sysclk0_en_cfg_func: sysclk0_en_cfg_func { + sysclk0_en_cfg_func: sysclk0-en-cfg-pins { pinctrl-single,pins = < 0x8 0x0 /* SYSCLK0_EN (IOCFG002) */ >; @@ -683,7 +683,7 @@ pinctrl-single,drive-strength = ; }; - jtag_tdo_cfg_func: jtag_tdo_cfg_func { + jtag_tdo_cfg_func: jtag-tdo-cfg-pins { pinctrl-single,pins = < 0xc 0x0 /* JTAG_TDO (IOCFG003) */ >; @@ -692,7 +692,7 @@ pinctrl-single,drive-strength = ; }; - rf_reset_cfg_func: rf_reset_cfg_func { + rf_reset_cfg_func: rf-reset-cfg-pins { pinctrl-single,pins = < 0x70 0x0 /* RF_RESET0 (IOCFG028) */ 0x74 0x0 /* RF_RESET1 (IOCFG029) */ diff --git a/arch/arm64/boot/dts/hisilicon/hikey960-pinctrl.dtsi b/arch/arm64/boot/dts/hisilicon/hikey960-pinctrl.dtsi index 920a3111c66ddcf10f48f0dc8b25cc64f9bffd75..b801a48041f9c0a22f3b31cbb0f78b4174bd3d49 100644 --- a/arch/arm64/boot/dts/hisilicon/hikey960-pinctrl.dtsi +++ b/arch/arm64/boot/dts/hisilicon/hikey960-pinctrl.dtsi @@ -25,7 +25,7 @@ &range 0 7 0 &range 8 116 0>; - pmu_pmx_func: pmu_pmx_func { + pmu_pmx_func: pmu-pins { pinctrl-single,pins = < 0x008 MUX_M1 /* PMU1_SSI */ 0x00c MUX_M1 /* PMU2_SSI */ @@ -34,19 +34,19 @@ >; }; - csi0_pwd_n_pmx_func: csi0_pwd_n_pmx_func { + csi0_pwd_n_pmx_func: csi0-pwd-n-pins { pinctrl-single,pins = < 0x044 MUX_M0 /* CSI0_PWD_N */ >; }; - csi1_pwd_n_pmx_func: csi1_pwd_n_pmx_func { + csi1_pwd_n_pmx_func: csi1-pwd-n-pins { pinctrl-single,pins = < 0x04c MUX_M0 /* CSI1_PWD_N */ >; }; - isp0_pmx_func: isp0_pmx_func { + isp0_pmx_func: isp0-pins { pinctrl-single,pins = < 0x058 MUX_M1 /* ISP_CLK0 */ 0x064 MUX_M1 /* ISP_SCL0 */ @@ -54,7 +54,7 @@ >; }; - isp1_pmx_func: isp1_pmx_func { + isp1_pmx_func: isp1-pins { pinctrl-single,pins = < 0x05c MUX_M1 /* ISP_CLK1 */ 0x06c MUX_M1 /* ISP_SCL1 */ @@ -62,47 +62,47 @@ >; }; - pwr_key_pmx_func: pwr_key_pmx_func { + pwr_key_pmx_func: pwr-key-pins { pinctrl-single,pins = < 0x080 MUX_M0 /* GPIO_034 */ >; }; - i2c3_pmx_func: i2c3_pmx_func { + i2c3_pmx_func: i2c3-pins { pinctrl-single,pins = < 0x02c MUX_M1 /* I2C3_SCL */ 0x030 MUX_M1 /* I2C3_SDA */ >; }; - i2c4_pmx_func: i2c4_pmx_func { + i2c4_pmx_func: i2c4-pins { pinctrl-single,pins = < 0x090 MUX_M1 /* I2C4_SCL */ 0x094 MUX_M1 /* I2C4_SDA */ >; }; - pcie_perstn_pmx_func: pcie_perstn_pmx_func { + pcie_perstn_pmx_func: pcie-perstn-pins { pinctrl-single,pins = < 0x15c MUX_M1 /* PCIE_PERST_N */ >; }; - usbhub5734_pmx_func: usbhub5734_pmx_func { + usbhub5734_pmx_func: usbhub5734-pins { pinctrl-single,pins = < 0x11c MUX_M0 /* GPIO_073 */ 0x120 MUX_M0 /* GPIO_074 */ >; }; - uart0_pmx_func: uart0_pmx_func { + uart0_pmx_func: uart0-pins { pinctrl-single,pins = < 0x0cc MUX_M2 /* UART0_RXD */ 0x0d0 MUX_M2 /* UART0_TXD */ >; }; - uart1_pmx_func: uart1_pmx_func { + uart1_pmx_func: uart1-pins { pinctrl-single,pins = < 0x0b0 MUX_M2 /* UART1_CTS_N */ 0x0b4 MUX_M2 /* UART1_RTS_N */ @@ -111,7 +111,7 @@ >; }; - uart2_pmx_func: uart2_pmx_func { + uart2_pmx_func: uart2-pins { pinctrl-single,pins = < 0x0bc MUX_M2 /* UART2_CTS_N */ 0x0c0 MUX_M2 /* UART2_RTS_N */ @@ -120,7 +120,7 @@ >; }; - uart3_pmx_func: uart3_pmx_func { + uart3_pmx_func: uart3-pins { pinctrl-single,pins = < 0x0dc MUX_M1 /* UART3_CTS_N */ 0x0e0 MUX_M1 /* UART3_RTS_N */ @@ -129,7 +129,7 @@ >; }; - uart4_pmx_func: uart4_pmx_func { + uart4_pmx_func: uart4-pins { pinctrl-single,pins = < 0x0ec MUX_M1 /* UART4_CTS_N */ 0x0f0 MUX_M1 /* UART4_RTS_N */ @@ -138,7 +138,7 @@ >; }; - uart5_pmx_func: uart5_pmx_func { + uart5_pmx_func: uart5-pins { pinctrl-single,pins = < 0x0c4 MUX_M3 /* UART5_CTS_N */ 0x0c8 MUX_M3 /* UART5_RTS_N */ @@ -147,7 +147,7 @@ >; }; - uart6_pmx_func: uart6_pmx_func { + uart6_pmx_func: uart6-pins { pinctrl-single,pins = < 0x0cc MUX_M1 /* UART6_CTS_N */ 0x0d0 MUX_M1 /* UART6_RTS_N */ @@ -156,13 +156,13 @@ >; }; - cam0_rst_pmx_func: cam0_rst_pmx_func { + cam0_rst_pmx_func: cam0-rst-pins { pinctrl-single,pins = < 0x0c8 MUX_M0 /* CAM0_RST */ >; }; - cam1_rst_pmx_func: cam1_rst_pmx_func { + cam1_rst_pmx_func: cam1-rst-pins { pinctrl-single,pins = < 0x124 MUX_M0 /* CAM1_RST */ >; @@ -180,7 +180,7 @@ /* pin base, nr pins & gpio function */ pinctrl-single,gpio-range = <&range 0 6 0>; - sd_pmx_func: sd_pmx_func { + sd_pmx_func: sd-pins { pinctrl-single,pins = < 0x000 MUX_M1 /* SD_CLK */ 0x004 MUX_M1 /* SD_CMD */ @@ -203,14 +203,14 @@ /* pin base, nr pins & gpio function */ pinctrl-single,gpio-range = <&range 0 12 0>; - ufs_pmx_func: ufs_pmx_func { + ufs_pmx_func: ufs-pins { pinctrl-single,pins = < 0x000 MUX_M1 /* UFS_REF_CLK */ 0x004 MUX_M1 /* UFS_RST_N */ >; }; - spi3_pmx_func: spi3_pmx_func { + spi3_pmx_func: spi3-pins { pinctrl-single,pins = < 0x008 MUX_M1 /* SPI3_CLK */ 0x00c MUX_M1 /* SPI3_DI */ @@ -231,7 +231,7 @@ /* pin base, nr pins & gpio function */ pinctrl-single,gpio-range = <&range 0 6 0>; - sdio_pmx_func: sdio_pmx_func { + sdio_pmx_func: sdio-pins { pinctrl-single,pins = < 0x000 MUX_M1 /* SDIO_CLK */ 0x004 MUX_M1 /* SDIO_CMD */ @@ -254,7 +254,7 @@ /* pin base in node, nr pins & gpio function */ pinctrl-single,gpio-range = <&range 0 42 0>; - i2s2_pmx_func: i2s2_pmx_func { + i2s2_pmx_func: i2s2-pins { pinctrl-single,pins = < 0x044 MUX_M1 /* I2S2_DI */ 0x048 MUX_M1 /* I2S2_DO */ @@ -263,42 +263,42 @@ >; }; - slimbus_pmx_func: slimbus_pmx_func { + slimbus_pmx_func: slimbus-pins { pinctrl-single,pins = < 0x02c MUX_M1 /* SLIMBUS_CLK */ 0x030 MUX_M1 /* SLIMBUS_DATA */ >; }; - i2c0_pmx_func: i2c0_pmx_func { + i2c0_pmx_func: i2c0-pins { pinctrl-single,pins = < 0x014 MUX_M1 /* I2C0_SCL */ 0x018 MUX_M1 /* I2C0_SDA */ >; }; - i2c1_pmx_func: i2c1_pmx_func { + i2c1_pmx_func: i2c1-pins { pinctrl-single,pins = < 0x01c MUX_M1 /* I2C1_SCL */ 0x020 MUX_M1 /* I2C1_SDA */ >; }; - i2c7_pmx_func: i2c7_pmx_func { + i2c7_pmx_func: i2c7-pins { pinctrl-single,pins = < 0x024 MUX_M3 /* I2C7_SCL */ 0x028 MUX_M3 /* I2C7_SDA */ >; }; - pcie_pmx_func: pcie_pmx_func { + pcie_pmx_func: pcie-pins { pinctrl-single,pins = < 0x084 MUX_M1 /* PCIE_CLKREQ_N */ 0x088 MUX_M1 /* PCIE_WAKE_N */ >; }; - spi2_pmx_func: spi2_pmx_func { + spi2_pmx_func: spi2-pins { pinctrl-single,pins = < 0x08c MUX_M1 /* SPI2_CLK */ 0x090 MUX_M1 /* SPI2_DI */ @@ -307,7 +307,7 @@ >; }; - i2s0_pmx_func: i2s0_pmx_func { + i2s0_pmx_func: i2s0-pins { pinctrl-single,pins = < 0x034 MUX_M1 /* I2S0_DI */ 0x038 MUX_M1 /* I2S0_DO */ @@ -323,7 +323,7 @@ #pinctrl-cells = <1>; pinctrl-single,register-width = <0x20>; - pmu_cfg_func: pmu_cfg_func { + pmu_cfg_func: pmu-cfg-pins { pinctrl-single,pins = < 0x010 0x0 /* PMU1_SSI */ 0x014 0x0 /* PMU2_SSI */ @@ -347,7 +347,7 @@ >; }; - i2c3_cfg_func: i2c3_cfg_func { + i2c3_cfg_func: i2c3-cfg-pins { pinctrl-single,pins = < 0x038 0x0 /* I2C3_SCL */ 0x03c 0x0 /* I2C3_SDA */ @@ -369,7 +369,7 @@ >; }; - csi0_pwd_n_cfg_func: csi0_pwd_n_cfg_func { + csi0_pwd_n_cfg_func: csi0-pwd-n-cfg-pins { pinctrl-single,pins = < 0x050 0x0 /* CSI0_PWD_N */ >; @@ -390,7 +390,7 @@ >; }; - csi1_pwd_n_cfg_func: csi1_pwd_n_cfg_func { + csi1_pwd_n_cfg_func: csi1-pwd-n-cfg-pins { pinctrl-single,pins = < 0x058 0x0 /* CSI1_PWD_N */ >; @@ -411,7 +411,7 @@ >; }; - isp0_cfg_func: isp0_cfg_func { + isp0_cfg_func: isp0-cfg-pins { pinctrl-single,pins = < 0x064 0x0 /* ISP_CLK0 */ 0x070 0x0 /* ISP_SCL0 */ @@ -433,7 +433,7 @@ DRIVE7_04MA DRIVE6_MASK>; }; - isp1_cfg_func: isp1_cfg_func { + isp1_cfg_func: isp1-cfg-pins { pinctrl-single,pins = < 0x068 0x0 /* ISP_CLK1 */ 0x078 0x0 /* ISP_SCL1 */ @@ -456,7 +456,7 @@ >; }; - pwr_key_cfg_func: pwr_key_cfg_func { + pwr_key_cfg_func: pwr-key-cfg-pins { pinctrl-single,pins = < 0x08c 0x0 /* GPIO_034 */ >; @@ -477,7 +477,7 @@ >; }; - uart1_cfg_func: uart1_cfg_func { + uart1_cfg_func: uart1-cfg-pins { pinctrl-single,pins = < 0x0b4 0x0 /* UART1_RXD */ 0x0b8 0x0 /* UART1_TXD */ @@ -501,7 +501,7 @@ >; }; - uart2_cfg_func: uart2_cfg_func { + uart2_cfg_func: uart2-cfg-pins { pinctrl-single,pins = < 0x0c8 0x0 /* UART2_CTS_N */ 0x0cc 0x0 /* UART2_RTS_N */ @@ -525,7 +525,7 @@ >; }; - uart5_cfg_func: uart5_cfg_func { + uart5_cfg_func: uart5-cfg-pins { pinctrl-single,pins = < 0x0c8 0x0 /* UART5_RXD */ 0x0cc 0x0 /* UART5_TXD */ @@ -549,7 +549,7 @@ >; }; - cam0_rst_cfg_func: cam0_rst_cfg_func { + cam0_rst_cfg_func: cam0-rst-cfg-pins { pinctrl-single,pins = < 0x0d4 0x0 /* CAM0_RST */ >; @@ -570,7 +570,7 @@ >; }; - uart0_cfg_func: uart0_cfg_func { + uart0_cfg_func: uart0-cfg-pins { pinctrl-single,pins = < 0x0d8 0x0 /* UART0_RXD */ 0x0dc 0x0 /* UART0_TXD */ @@ -592,7 +592,7 @@ >; }; - uart6_cfg_func: uart6_cfg_func { + uart6_cfg_func: uart6-cfg-pins { pinctrl-single,pins = < 0x0d8 0x0 /* UART6_CTS_N */ 0x0dc 0x0 /* UART6_RTS_N */ @@ -616,7 +616,7 @@ >; }; - uart3_cfg_func: uart3_cfg_func { + uart3_cfg_func: uart3-cfg-pins { pinctrl-single,pins = < 0x0e8 0x0 /* UART3_CTS_N */ 0x0ec 0x0 /* UART3_RTS_N */ @@ -640,7 +640,7 @@ >; }; - uart4_cfg_func: uart4_cfg_func { + uart4_cfg_func: uart4-cfg-pins { pinctrl-single,pins = < 0x0f8 0x0 /* UART4_CTS_N */ 0x0fc 0x0 /* UART4_RTS_N */ @@ -664,7 +664,7 @@ >; }; - cam1_rst_cfg_func: cam1_rst_cfg_func { + cam1_rst_cfg_func: cam1-rst-cfg-pins { pinctrl-single,pins = < 0x130 0x0 /* CAM1_RST */ >; @@ -692,7 +692,7 @@ #pinctrl-cells = <1>; pinctrl-single,register-width = <0x20>; - ufs_cfg_func: ufs_cfg_func { + ufs_cfg_func: ufs-cfg-pins { pinctrl-single,pins = < 0x000 0x0 /* UFS_REF_CLK */ 0x004 0x0 /* UFS_RST_N */ @@ -714,7 +714,7 @@ >; }; - spi3_cfg_func: spi3_cfg_func { + spi3_cfg_func: spi3-cfg-pins { pinctrl-single,pins = < 0x008 0x0 /* SPI3_CLK */ 0x00c 0x0 /* SPI3_DI */ @@ -745,7 +745,7 @@ #pinctrl-cells = <1>; pinctrl-single,register-width = <0x20>; - sdio_clk_cfg_func: sdio_clk_cfg_func { + sdio_clk_cfg_func: sdio-clk-cfg-pins { pinctrl-single,pins = < 0x000 0x0 /* SDIO_CLK */ >; @@ -766,7 +766,7 @@ >; }; - sdio_cfg_func: sdio_cfg_func { + sdio_cfg_func: sdio-cfg-pins { pinctrl-single,pins = < 0x004 0x0 /* SDIO_CMD */ 0x008 0x0 /* SDIO_DATA0 */ @@ -798,7 +798,7 @@ #pinctrl-cells = <1>; pinctrl-single,register-width = <0x20>; - sd_clk_cfg_func: sd_clk_cfg_func { + sd_clk_cfg_func: sd-clk-cfg-pins { pinctrl-single,pins = < 0x000 0x0 /* SD_CLK */ >; @@ -820,7 +820,7 @@ >; }; - sd_cfg_func: sd_cfg_func { + sd_cfg_func: sd-cfg-pins { pinctrl-single,pins = < 0x004 0x0 /* SD_CMD */ 0x008 0x0 /* SD_DATA0 */ @@ -853,7 +853,7 @@ #pinctrl-cells = <1>; pinctrl-single,register-width = <0x20>; - i2c0_cfg_func: i2c0_cfg_func { + i2c0_cfg_func: i2c0-cfg-pins { pinctrl-single,pins = < 0x01c 0x0 /* I2C0_SCL */ 0x020 0x0 /* I2C0_SDA */ @@ -875,7 +875,7 @@ >; }; - i2c1_cfg_func: i2c1_cfg_func { + i2c1_cfg_func: i2c1-cfg-pins { pinctrl-single,pins = < 0x024 0x0 /* I2C1_SCL */ 0x028 0x0 /* I2C1_SDA */ @@ -897,7 +897,7 @@ >; }; - i2c7_cfg_func: i2c7_cfg_func { + i2c7_cfg_func: i2c7-cfg-pins { pinctrl-single,pins = < 0x02c 0x0 /* I2C7_SCL */ 0x030 0x0 /* I2C7_SDA */ @@ -919,7 +919,7 @@ >; }; - slimbus_cfg_func: slimbus_cfg_func { + slimbus_cfg_func: slimbus-cfg-pins { pinctrl-single,pins = < 0x034 0x0 /* SLIMBUS_CLK */ 0x038 0x0 /* SLIMBUS_DATA */ @@ -941,7 +941,7 @@ >; }; - i2s0_cfg_func: i2s0_cfg_func { + i2s0_cfg_func: i2s0-cfg-pins { pinctrl-single,pins = < 0x040 0x0 /* I2S0_DI */ 0x044 0x0 /* I2S0_DO */ @@ -965,7 +965,7 @@ >; }; - i2s2_cfg_func: i2s2_cfg_func { + i2s2_cfg_func: i2s2-cfg-pins { pinctrl-single,pins = < 0x050 0x0 /* I2S2_DI */ 0x054 0x0 /* I2S2_DO */ @@ -989,7 +989,7 @@ >; }; - pcie_cfg_func: pcie_cfg_func { + pcie_cfg_func: pcie-cfg-pins { pinctrl-single,pins = < 0x094 0x0 /* PCIE_CLKREQ_N */ 0x098 0x0 /* PCIE_WAKE_N */ @@ -1011,7 +1011,7 @@ >; }; - spi2_cfg_func: spi2_cfg_func { + spi2_cfg_func: spi2-cfg-pins { pinctrl-single,pins = < 0x09c 0x0 /* SPI2_CLK */ 0x0a0 0x0 /* SPI2_DI */ @@ -1035,7 +1035,7 @@ >; }; - usb_cfg_func: usb_cfg_func { + usb_cfg_func: usb-cfg-pins { pinctrl-single,pins = < 0x0ac 0x0 /* GPIO_219 */ >; diff --git a/arch/arm64/boot/dts/hisilicon/hikey970-pinctrl.dtsi b/arch/arm64/boot/dts/hisilicon/hikey970-pinctrl.dtsi index 77bd8c3a83145e613dfb14bd11baccb30f29cfc8..8f7bf80e6ece73929040aac5950e623566bda497 100644 --- a/arch/arm64/boot/dts/hisilicon/hikey970-pinctrl.dtsi +++ b/arch/arm64/boot/dts/hisilicon/hikey970-pinctrl.dtsi @@ -21,14 +21,14 @@ /* pin base, nr pins & gpio function */ pinctrl-single,gpio-range = <&range 0 82 0>; - uart0_pmx_func: uart0_pmx_func { + uart0_pmx_func: uart0-pins { pinctrl-single,pins = < 0x054 MUX_M2 /* UART0_RXD */ 0x058 MUX_M2 /* UART0_TXD */ >; }; - uart2_pmx_func: uart2_pmx_func { + uart2_pmx_func: uart2-pins { pinctrl-single,pins = < 0x700 MUX_M2 /* UART2_CTS_N */ 0x704 MUX_M2 /* UART2_RTS_N */ @@ -37,7 +37,7 @@ >; }; - uart3_pmx_func: uart3_pmx_func { + uart3_pmx_func: uart3-pins { pinctrl-single,pins = < 0x064 MUX_M1 /* UART3_CTS_N */ 0x068 MUX_M1 /* UART3_RTS_N */ @@ -46,7 +46,7 @@ >; }; - uart4_pmx_func: uart4_pmx_func { + uart4_pmx_func: uart4-pins { pinctrl-single,pins = < 0x074 MUX_M1 /* UART4_CTS_N */ 0x078 MUX_M1 /* UART4_RTS_N */ @@ -55,52 +55,52 @@ >; }; - uart6_pmx_func: uart6_pmx_func { + uart6_pmx_func: uart6-pins { pinctrl-single,pins = < 0x05c MUX_M1 /* UART6_RXD */ 0x060 MUX_M1 /* UART6_TXD */ >; }; - i2c3_pmx_func: i2c3_pmx_func { + i2c3_pmx_func: i2c3-pins { pinctrl-single,pins = < 0x010 MUX_M1 /* I2C3_SCL */ 0x014 MUX_M1 /* I2C3_SDA */ >; }; - i2c4_pmx_func: i2c4_pmx_func { + i2c4_pmx_func: i2c4-pins { pinctrl-single,pins = < 0x03c MUX_M1 /* I2C4_SCL */ 0x040 MUX_M1 /* I2C4_SDA */ >; }; - cam0_rst_pmx_func: cam0_rst_pmx_func { + cam0_rst_pmx_func: cam0-rst-pins { pinctrl-single,pins = < 0x714 MUX_M0 /* CAM0_RST */ >; }; - cam1_rst_pmx_func: cam1_rst_pmx_func { + cam1_rst_pmx_func: cam1-rst-pins { pinctrl-single,pins = < 0x048 MUX_M0 /* CAM1_RST */ >; }; - cam0_pwd_n_pmx_func: cam0_pwd_n_pmx_func { + cam0_pwd_n_pmx_func: cam0-pwd-n-pins { pinctrl-single,pins = < 0x098 MUX_M0 /* CAM0_PWD_N */ >; }; - cam1_pwd_n_pmx_func: cam1_pwd_n_pmx_func { + cam1_pwd_n_pmx_func: cam1-pwd-n-pins { pinctrl-single,pins = < 0x044 MUX_M0 /* CAM1_PWD_N */ >; }; - isp0_pmx_func: isp0_pmx_func { + isp0_pmx_func: isp0-pins { pinctrl-single,pins = < 0x018 MUX_M1 /* ISP_CLK0 */ 0x024 MUX_M1 /* ISP_SCL0 */ @@ -108,7 +108,7 @@ >; }; - isp1_pmx_func: isp1_pmx_func { + isp1_pmx_func: isp1-pins { pinctrl-single,pins = < 0x01c MUX_M1 /* ISP_CLK1 */ 0x02c MUX_M1 /* ISP_SCL1 */ @@ -127,19 +127,19 @@ /* pin base, nr pins & gpio function */ pinctrl-single,gpio-range = <&range 0 46 0>; - pwr_key_pmx_func: pwr_key_pmx_func { + pwr_key_pmx_func: pwr-key-pins { pinctrl-single,pins = < 0x064 MUX_M0 /* GPIO_203 */ >; }; - pd_pmx_func: pd_pmx_func{ + pd_pmx_func: pd-pins { pinctrl-single,pins = < 0x080 MUX_M0 /* GPIO_221 */ >; }; - i2s2_pmx_func: i2s2_pmx_func { + i2s2_pmx_func: i2s2-pins { pinctrl-single,pins = < 0x050 MUX_M1 /* I2S2_DI */ 0x054 MUX_M1 /* I2S2_DO */ @@ -148,7 +148,7 @@ >; }; - spi0_pmx_func: spi0_pmx_func { + spi0_pmx_func: spi0-pins { pinctrl-single,pins = < 0x094 MUX_M1 /* SPI0_CLK */ 0x098 MUX_M1 /* SPI0_DI */ @@ -157,7 +157,7 @@ >; }; - spi2_pmx_func: spi2_pmx_func { + spi2_pmx_func: spi2-pins { pinctrl-single,pins = < 0x710 MUX_M1 /* SPI2_CLK */ 0x714 MUX_M1 /* SPI2_DI */ @@ -166,7 +166,7 @@ >; }; - spi3_pmx_func: spi3_pmx_func { + spi3_pmx_func: spi3-pins { pinctrl-single,pins = < 0x72c MUX_M1 /* SPI3_CLK */ 0x730 MUX_M1 /* SPI3_DI */ @@ -175,37 +175,37 @@ >; }; - i2c0_pmx_func: i2c0_pmx_func { + i2c0_pmx_func: i2c0-pins { pinctrl-single,pins = < 0x020 MUX_M1 /* I2C0_SCL */ 0x024 MUX_M1 /* I2C0_SDA */ >; }; - i2c1_pmx_func: i2c1_pmx_func { + i2c1_pmx_func: i2c1-pins { pinctrl-single,pins = < 0x028 MUX_M1 /* I2C1_SCL */ 0x02c MUX_M1 /* I2C1_SDA */ >; }; - i2c2_pmx_func: i2c2_pmx_func { + i2c2_pmx_func: i2c2-pins { pinctrl-single,pins = < 0x030 MUX_M1 /* I2C2_SCL */ 0x034 MUX_M1 /* I2C2_SDA */ >; }; - pcie_clkreq_pmx_func: pcie_clkreq_pmx_func { + pcie_clkreq_pmx_func: pcie-clkreq-pins { pinctrl-single,pins = < 0x084 MUX_M1 /* PCIE0_CLKREQ_N */ >; }; - gpio185_pmx_func: gpio185_pmx_func { + gpio185_pmx_func: gpio185-pins { pinctrl-single,pins = <0x01C 0x1>; }; - gpio185_pmx_idle: gpio185_pmx_idle { + gpio185_pmx_idle: gpio185-idle-pins { pinctrl-single,pins = <0x01C 0x0>; }; }; @@ -216,7 +216,7 @@ #pinctrl-cells = <1>; pinctrl-single,register-width = <0x20>; - uart0_cfg_func: uart0_cfg_func { + uart0_cfg_func: uart0-cfg-pins { pinctrl-single,pins = < 0x058 0x0 /* UART0_RXD */ 0x05c 0x0 /* UART0_TXD */ @@ -238,7 +238,7 @@ >; }; - uart2_cfg_func: uart2_cfg_func { + uart2_cfg_func: uart2-cfg-pins { pinctrl-single,pins = < 0x700 0x0 /* UART2_CTS_N */ 0x704 0x0 /* UART2_RTS_N */ @@ -262,7 +262,7 @@ >; }; - uart3_cfg_func: uart3_cfg_func { + uart3_cfg_func: uart3-cfg-pins { pinctrl-single,pins = < 0x068 0x0 /* UART3_CTS_N */ 0x06c 0x0 /* UART3_RTS_N */ @@ -286,7 +286,7 @@ >; }; - uart4_cfg_func: uart4_cfg_func { + uart4_cfg_func: uart4-cfg-pins { pinctrl-single,pins = < 0x078 0x0 /* UART4_CTS_N */ 0x07c 0x0 /* UART4_RTS_N */ @@ -310,7 +310,7 @@ >; }; - uart6_cfg_func: uart6_cfg_func { + uart6_cfg_func: uart6-cfg-pins { pinctrl-single,pins = < 0x060 0x0 /* UART6_RXD */ 0x064 0x0 /* UART6_TXD */ @@ -332,7 +332,7 @@ >; }; - i2c3_cfg_func: i2c3_cfg_func { + i2c3_cfg_func: i2c3-cfg-pins { pinctrl-single,pins = < 0x014 0x0 /* I2C3_SCL */ 0x018 0x0 /* I2C3_SDA */ @@ -354,7 +354,7 @@ >; }; - i2c4_cfg_func: i2c4_cfg_func { + i2c4_cfg_func: i2c4-cfg-pins { pinctrl-single,pins = < 0x040 0x0 /* I2C4_SCL */ 0x044 0x0 /* I2C4_SDA */ @@ -376,7 +376,7 @@ >; }; - cam0_rst_cfg_func: cam0_rst_cfg_func { + cam0_rst_cfg_func: cam0-rst-cfg-pins { pinctrl-single,pins = < 0x714 0x0 /* CAM0_RST */ >; @@ -397,7 +397,7 @@ >; }; - cam1_rst_cfg_func: cam1_rst_cfg_func { + cam1_rst_cfg_func: cam1-rst-cfg-pins { pinctrl-single,pins = < 0x04C 0x0 /* CAM1_RST */ >; @@ -418,7 +418,7 @@ >; }; - cam0_pwd_n_cfg_func: cam0_pwd_n_cfg_func { + cam0_pwd_n_cfg_func: cam0-pwd-n-cfg-pins { pinctrl-single,pins = < 0x09C 0x0 /* CAM0_PWD_N */ >; @@ -439,7 +439,7 @@ >; }; - cam1_pwd_n_cfg_func: cam1_pwd_n_cfg_func { + cam1_pwd_n_cfg_func: cam1-pwd-n-cfg-pins { pinctrl-single,pins = < 0x048 0x0 /* CAM1_PWD_N */ >; @@ -460,7 +460,7 @@ >; }; - isp0_cfg_func: isp0_cfg_func { + isp0_cfg_func: isp0-cfg-pins { pinctrl-single,pins = < 0x01C 0x0 /* ISP_CLK0 */ 0x028 0x0 /* ISP_SCL0 */ @@ -483,7 +483,7 @@ >; }; - isp1_cfg_func: isp1_cfg_func { + isp1_cfg_func: isp1-cfg-pins { pinctrl-single,pins = < 0x020 0x0 /* ISP_CLK1 */ 0x030 0x0 /* ISP_SCL1 */ @@ -517,7 +517,7 @@ /* pin base, nr pins & gpio function */ pinctrl-single,gpio-range = <&range 0 10 0>; - sdio_pmx_func: sdio_pmx_func { + sdio_pmx_func: sdio-pins { pinctrl-single,pins = < 0x000 MUX_M1 /* SDIO_CLK */ 0x004 MUX_M1 /* SDIO_CMD */ @@ -535,7 +535,7 @@ #pinctrl-cells = <1>; pinctrl-single,register-width = <0x20>; - sdio_clk_cfg_func: sdio_clk_cfg_func { + sdio_clk_cfg_func: sdio-clk-cfg-pins { pinctrl-single,pins = < 0x000 0x0 /* SDIO_CLK */ >; @@ -556,7 +556,7 @@ >; }; - sdio_cfg_func: sdio_cfg_func { + sdio_cfg_func: sdio-cfg-pins { pinctrl-single,pins = < 0x004 0x0 /* SDIO_CMD */ 0x008 0x0 /* SDIO_DATA0 */ @@ -592,7 +592,7 @@ /* pin base, nr pins & gpio function */ pinctrl-single,gpio-range = <&range 0 12 0>; - sd_pmx_func: sd_pmx_func { + sd_pmx_func: sd-pins { pinctrl-single,pins = < 0x000 MUX_M1 /* SD_CLK */ 0x004 MUX_M1 /* SD_CMD */ @@ -610,7 +610,7 @@ #pinctrl-cells = <1>; pinctrl-single,register-width = <0x20>; - sd_clk_cfg_func: sd_clk_cfg_func { + sd_clk_cfg_func: sd-clk-cfg-pins { pinctrl-single,pins = < 0x000 0x0 /* SD_CLK */ >; @@ -632,7 +632,7 @@ >; }; - sd_cfg_func: sd_cfg_func { + sd_cfg_func: sd-cfg-pins { pinctrl-single,pins = < 0x004 0x0 /* SD_CMD */ 0x008 0x0 /* SD_DATA0 */ @@ -665,7 +665,7 @@ #pinctrl-cells = <1>; pinctrl-single,register-width = <0x20>; - pwr_key_cfg_func: pwr_key_cfg_func { + pwr_key_cfg_func: pwr-key-cfg-pins { pinctrl-single,pins = < 0x090 0x0 /* GPIO_203 */ >; @@ -686,7 +686,7 @@ >; }; - usb_cfg_func: usb_cfg_func { + usb_cfg_func: usb-cfg-pins { pinctrl-single,pins = < 0x0AC 0x0 /* GPIO_221 */ >; @@ -707,7 +707,7 @@ >; }; - spi0_cfg_func: spi0_cfg_func { + spi0_cfg_func: spi0-cfg-pins { pinctrl-single,pins = < 0x0c8 0x0 /* SPI0_DI */ 0x0cc 0x0 /* SPI0_DO */ @@ -730,7 +730,7 @@ >; }; - spi2_cfg_func: spi2_cfg_func { + spi2_cfg_func: spi2-cfg-pins { pinctrl-single,pins = < 0x714 0x0 /* SPI2_DI */ 0x718 0x0 /* SPI2_DO */ @@ -753,7 +753,7 @@ >; }; - spi3_cfg_func: spi3_cfg_func { + spi3_cfg_func: spi3-cfg-pins { pinctrl-single,pins = < 0x730 0x0 /* SPI3_DI */ 0x734 0x0 /* SPI3_DO */ @@ -776,7 +776,7 @@ >; }; - spi0_clk_cfg_func: spi0_clk_cfg_func { + spi0_clk_cfg_func: spi0-clk-cfg-pins { pinctrl-single,pins = < 0x0c4 0x0 /* SPI0_CLK */ >; @@ -797,7 +797,7 @@ >; }; - spi2_clk_cfg_func: spi2_clk_cfg_func { + spi2_clk_cfg_func: spi2-clk-cfg-pins { pinctrl-single,pins = < 0x710 0x0 /* SPI2_CLK */ >; @@ -818,7 +818,7 @@ >; }; - spi3_clk_cfg_func: spi3_clk_cfg_func { + spi3_clk_cfg_func: spi3-clk-cfg-pins { pinctrl-single,pins = < 0x72c 0x0 /* SPI3_CLK */ >; @@ -839,7 +839,7 @@ >; }; - i2c0_cfg_func: i2c0_cfg_func { + i2c0_cfg_func: i2c0-cfg-pins { pinctrl-single,pins = < 0x04c 0x0 /* I2C0_SCL */ 0x050 0x0 /* I2C0_SDA */ @@ -861,7 +861,7 @@ >; }; - i2c1_cfg_func: i2c1_cfg_func { + i2c1_cfg_func: i2c1-cfg-pins { pinctrl-single,pins = < 0x054 0x0 /* I2C1_SCL */ 0x058 0x0 /* I2C1_SDA */ @@ -883,7 +883,7 @@ >; }; - i2c2_cfg_func: i2c2_cfg_func { + i2c2_cfg_func: i2c2-cfg-pins { pinctrl-single,pins = < 0x05c 0x0 /* I2C2_SCL */ 0x060 0x0 /* I2C2_SDA */ @@ -905,7 +905,7 @@ >; }; - pcie_clkreq_cfg_func: pcie_clkreq_cfg_func { + pcie_clkreq_cfg_func: pcie-clkreq-cfg-pins { pinctrl-single,pins = < 0x0b0 0x0 >; @@ -925,7 +925,7 @@ DRIVE7_06MA DRIVE6_MASK >; }; - i2s2_cfg_func: i2s2_cfg_func { + i2s2_cfg_func: i2s2-cfg-pins { pinctrl-single,pins = < 0x07c 0x0 /* I2S2_DI */ 0x080 0x0 /* I2S2_DO */ @@ -949,7 +949,7 @@ >; }; - gpio185_cfg_func: gpio185_cfg_func { + gpio185_cfg_func: gpio185-cfg-pins { pinctrl-single,pins = <0x048 0>; pinctrl-single,bias-pulldown = <0 2 0 2>; pinctrl-single,bias-pullup = <0 1 0 1>; @@ -957,7 +957,7 @@ pinctrl-single,slew-rate = <0x0 0x80>; }; - gpio185_cfg_idle: gpio185_cfg_idle { + gpio185_cfg_idle: gpio185-cfg-idle-pins { pinctrl-single,pins = <0x048 0>; pinctrl-single,bias-pulldown = <2 2 0 2>; pinctrl-single,bias-pullup = <0 1 0 1>; diff --git a/arch/arm64/boot/dts/hisilicon/hip05.dtsi b/arch/arm64/boot/dts/hisilicon/hip05.dtsi index 5b2b1bfd0d2a12fea89e8d725822a53f29844d6a..65ddc0698f8285d203a8620b769d4704811fd6e0 100644 --- a/arch/arm64/boot/dts/hisilicon/hip05.dtsi +++ b/arch/arm64/boot/dts/hisilicon/hip05.dtsi @@ -212,21 +212,25 @@ cluster0_l2: l2-cache0 { compatible = "cache"; cache-level = <2>; + cache-unified; }; cluster1_l2: l2-cache1 { compatible = "cache"; cache-level = <2>; + cache-unified; }; cluster2_l2: l2-cache2 { compatible = "cache"; cache-level = <2>; + cache-unified; }; cluster3_l2: l2-cache3 { compatible = "cache"; cache-level = <2>; + cache-unified; }; }; diff --git a/arch/arm64/boot/dts/hisilicon/hip06.dtsi b/arch/arm64/boot/dts/hisilicon/hip06.dtsi index 291c2ee3828823eb1c6278556919ce8f12dd8c85..c588848bfdebb2428bd5a4620da7e81e9c92ba21 100644 --- a/arch/arm64/boot/dts/hisilicon/hip06.dtsi +++ b/arch/arm64/boot/dts/hisilicon/hip06.dtsi @@ -212,21 +212,25 @@ cluster0_l2: l2-cache0 { compatible = "cache"; cache-level = <2>; + cache-unified; }; cluster1_l2: l2-cache1 { compatible = "cache"; cache-level = <2>; + cache-unified; }; cluster2_l2: l2-cache2 { compatible = "cache"; cache-level = <2>; + cache-unified; }; cluster3_l2: l2-cache3 { compatible = "cache"; cache-level = <2>; + cache-unified; }; }; diff --git a/arch/arm64/boot/dts/hisilicon/hip07.dtsi b/arch/arm64/boot/dts/hisilicon/hip07.dtsi index 8a9436ca253114b7ebf13fb7d21bb0aca914423c..595abe339c5df767f0671273e3ac78c5e560fcde 100644 --- a/arch/arm64/boot/dts/hisilicon/hip07.dtsi +++ b/arch/arm64/boot/dts/hisilicon/hip07.dtsi @@ -843,81 +843,97 @@ cluster0_l2: l2-cache0 { compatible = "cache"; cache-level = <2>; + cache-unified; }; cluster1_l2: l2-cache1 { compatible = "cache"; cache-level = <2>; + cache-unified; }; cluster2_l2: l2-cache2 { compatible = "cache"; cache-level = <2>; + cache-unified; }; cluster3_l2: l2-cache3 { compatible = "cache"; cache-level = <2>; + cache-unified; }; cluster4_l2: l2-cache4 { compatible = "cache"; cache-level = <2>; + cache-unified; }; cluster5_l2: l2-cache5 { compatible = "cache"; cache-level = <2>; + cache-unified; }; cluster6_l2: l2-cache6 { compatible = "cache"; cache-level = <2>; + cache-unified; }; cluster7_l2: l2-cache7 { compatible = "cache"; cache-level = <2>; + cache-unified; }; cluster8_l2: l2-cache8 { compatible = "cache"; cache-level = <2>; + cache-unified; }; cluster9_l2: l2-cache9 { compatible = "cache"; cache-level = <2>; + cache-unified; }; cluster10_l2: l2-cache10 { compatible = "cache"; cache-level = <2>; + cache-unified; }; cluster11_l2: l2-cache11 { compatible = "cache"; cache-level = <2>; + cache-unified; }; cluster12_l2: l2-cache12 { compatible = "cache"; cache-level = <2>; + cache-unified; }; cluster13_l2: l2-cache13 { compatible = "cache"; cache-level = <2>; + cache-unified; }; cluster14_l2: l2-cache14 { compatible = "cache"; cache-level = <2>; + cache-unified; }; cluster15_l2: l2-cache15 { compatible = "cache"; cache-level = <2>; + cache-unified; }; }; diff --git a/arch/arm64/boot/dts/marvell/ac5-98dx25xx.dtsi b/arch/arm64/boot/dts/marvell/ac5-98dx25xx.dtsi index 8bce6406913875d38b7d2759561ac8c7db786726..c9ce1010c4156deafc0fde0abe54bb8b67010f5e 100644 --- a/arch/arm64/boot/dts/marvell/ac5-98dx25xx.dtsi +++ b/arch/arm64/boot/dts/marvell/ac5-98dx25xx.dtsi @@ -50,6 +50,7 @@ l2: l2-cache { compatible = "cache"; cache-level = <2>; + cache-unified; }; }; diff --git a/arch/arm64/boot/dts/marvell/armada-3720-espressobin-ultra.dts b/arch/arm64/boot/dts/marvell/armada-3720-espressobin-ultra.dts index d29d2da95f4c3e78ed4f37273b9ee946ffc7c988..f9abef8dcc94891979d60b7b69029e3a9ede24d9 100644 --- a/arch/arm64/boot/dts/marvell/armada-3720-espressobin-ultra.dts +++ b/arch/arm64/boot/dts/marvell/armada-3720-espressobin-ultra.dts @@ -24,6 +24,8 @@ ethernet5 = &switch0port4; }; + /delete-node/ regulator; + reg_usb3_vbus: usb3-vbus { compatible = "regulator-fixed"; regulator-name = "usb3-vbus"; @@ -66,6 +68,7 @@ }; &sdhci1 { + /delete-property/ vqmmc-supply; status = "disabled"; }; diff --git a/arch/arm64/boot/dts/marvell/armada-8040-mcbin.dtsi b/arch/arm64/boot/dts/marvell/armada-8040-mcbin.dtsi index ca1aeb69a8929931db866ec7b60b71b22fdfccc9..c864df9ec84d1b6faf8f17b8354aece241c9b9ce 100644 --- a/arch/arm64/boot/dts/marvell/armada-8040-mcbin.dtsi +++ b/arch/arm64/boot/dts/marvell/armada-8040-mcbin.dtsi @@ -135,7 +135,7 @@ pinctrl-0 = <&cp0_i2c1_pins>; status = "okay"; - i2c-switch@70 { + i2c-mux@70 { compatible = "nxp,pca9548"; #address-cells = <1>; #size-cells = <0>; diff --git a/arch/arm64/boot/dts/marvell/armada-8040-puzzle-m801.dts b/arch/arm64/boot/dts/marvell/armada-8040-puzzle-m801.dts index eb04735039362373bb9072f3184081d62c324d08..42a60f3dd5d142fcd1556939b897ae5446db9505 100644 --- a/arch/arm64/boot/dts/marvell/armada-8040-puzzle-m801.dts +++ b/arch/arm64/boot/dts/marvell/armada-8040-puzzle-m801.dts @@ -285,7 +285,7 @@ pinctrl-0 = <&cp0_i2c1_pins>; status = "okay"; - i2c-switch@70 { + i2c-mux@70 { compatible = "nxp,pca9544"; #address-cells = <1>; #size-cells = <0>; diff --git a/arch/arm64/boot/dts/marvell/armada-ap806-dual.dtsi b/arch/arm64/boot/dts/marvell/armada-ap806-dual.dtsi index 990f70303fe6fd18b426a0f4795a06849fbc5b4d..3ed6fba1f4383d6353c710d5bdd2355a56201571 100644 --- a/arch/arm64/boot/dts/marvell/armada-ap806-dual.dtsi +++ b/arch/arm64/boot/dts/marvell/armada-ap806-dual.dtsi @@ -52,6 +52,7 @@ cache-line-size = <64>; cache-sets = <512>; cache-level = <2>; + cache-unified; }; }; diff --git a/arch/arm64/boot/dts/marvell/armada-ap806-quad.dtsi b/arch/arm64/boot/dts/marvell/armada-ap806-quad.dtsi index a7b8e001cc9c1fdf7f1b3d9e4c3021c79f5650db..cf6a96ddcf40fccdce6626cf8db8499feb0b968b 100644 --- a/arch/arm64/boot/dts/marvell/armada-ap806-quad.dtsi +++ b/arch/arm64/boot/dts/marvell/armada-ap806-quad.dtsi @@ -82,6 +82,7 @@ cache-line-size = <64>; cache-sets = <512>; cache-level = <2>; + cache-unified; }; l2_1: l2-cache1 { @@ -90,6 +91,7 @@ cache-line-size = <64>; cache-sets = <512>; cache-level = <2>; + cache-unified; }; }; }; diff --git a/arch/arm64/boot/dts/marvell/armada-ap807-quad.dtsi b/arch/arm64/boot/dts/marvell/armada-ap807-quad.dtsi index 7740098fd108b82ceb62912dae39f8234c5504b2..8848238f9565dc82fe543e233f21c0dc3bfa75c0 100644 --- a/arch/arm64/boot/dts/marvell/armada-ap807-quad.dtsi +++ b/arch/arm64/boot/dts/marvell/armada-ap807-quad.dtsi @@ -82,6 +82,7 @@ cache-line-size = <64>; cache-sets = <512>; cache-level = <2>; + cache-unified; }; l2_1: l2-cache1 { @@ -90,6 +91,7 @@ cache-line-size = <64>; cache-sets = <512>; cache-level = <2>; + cache-unified; }; }; }; diff --git a/arch/arm64/boot/dts/marvell/armada-cp11x.dtsi b/arch/arm64/boot/dts/marvell/armada-cp11x.dtsi index 0cc9ee9871e70c55a7a1d90b8b8e8e371d13c3c5..4ec1aae0a3a9c397b3985b8f45176764f6592e4d 100644 --- a/arch/arm64/boot/dts/marvell/armada-cp11x.dtsi +++ b/arch/arm64/boot/dts/marvell/armada-cp11x.dtsi @@ -468,7 +468,7 @@ status = "disabled"; }; - CP11X_LABEL(nand_controller): nand@720000 { + CP11X_LABEL(nand_controller): nand-controller@720000 { /* * Due to the limitation of the pins available * this controller is only usable on the CPM diff --git a/arch/arm64/boot/dts/mediatek/mt2712-evb.dts b/arch/arm64/boot/dts/mediatek/mt2712-evb.dts index d31a194124c91a0b140da54a596be20ae3bed609..fffdb7bbf889e48a675e1e7efe10b2d7023d01ed 100644 --- a/arch/arm64/boot/dts/mediatek/mt2712-evb.dts +++ b/arch/arm64/boot/dts/mediatek/mt2712-evb.dts @@ -11,6 +11,7 @@ / { model = "MediaTek MT2712 evaluation board"; + chassis-type = "embedded"; compatible = "mediatek,mt2712-evb", "mediatek,mt2712"; aliases { diff --git a/arch/arm64/boot/dts/mediatek/mt6331.dtsi b/arch/arm64/boot/dts/mediatek/mt6331.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..d89858c73ab1b087eab89f0376c01c281c1d66c1 --- /dev/null +++ b/arch/arm64/boot/dts/mediatek/mt6331.dtsi @@ -0,0 +1,284 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/* + * Copyright (c) 2023 Collabora Ltd. + * Author: AngeloGioacchino Del Regno + */ +#include + +&pwrap { + pmic: mt6331 { + compatible = "mediatek,mt6331"; + interrupt-controller; + #interrupt-cells = <2>; + + mt6331regulator: mt6331regulator { + compatible = "mediatek,mt6331-regulator"; + + mt6331_vdvfs11_reg: buck-vdvfs11 { + regulator-name = "vdvfs11"; + regulator-min-microvolt = <700000>; + regulator-max-microvolt = <1493750>; + regulator-ramp-delay = <12500>; + regulator-enable-ramp-delay = <0>; + regulator-allowed-modes = <0 1>; + regulator-always-on; + }; + + mt6331_vdvfs12_reg: buck-vdvfs12 { + regulator-name = "vdvfs12"; + regulator-min-microvolt = <700000>; + regulator-max-microvolt = <1493750>; + regulator-ramp-delay = <12500>; + regulator-enable-ramp-delay = <0>; + regulator-allowed-modes = <0 1>; + regulator-always-on; + }; + + mt6331_vdvfs13_reg: buck-vdvfs13 { + regulator-name = "vdvfs13"; + regulator-min-microvolt = <700000>; + regulator-max-microvolt = <1493750>; + regulator-ramp-delay = <12500>; + regulator-enable-ramp-delay = <0>; + regulator-allowed-modes = <0 1>; + regulator-always-on; + }; + + mt6331_vdvfs14_reg: buck-vdvfs14 { + regulator-name = "vdvfs14"; + regulator-min-microvolt = <700000>; + regulator-max-microvolt = <1493750>; + regulator-ramp-delay = <12500>; + regulator-enable-ramp-delay = <0>; + regulator-allowed-modes = <0 1>; + regulator-always-on; + }; + + mt6331_vcore2_reg: buck-vcore2 { + regulator-name = "vcore2"; + regulator-min-microvolt = <700000>; + regulator-max-microvolt = <1493750>; + regulator-ramp-delay = <12500>; + regulator-enable-ramp-delay = <0>; + regulator-allowed-modes = <0 1>; + regulator-always-on; + }; + + mt6331_vio18_reg: buck-vio18 { + regulator-name = "vio18"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-ramp-delay = <12500>; + regulator-enable-ramp-delay = <0>; + regulator-allowed-modes = <0 1>; + regulator-always-on; + }; + + mt6331_vtcxo1_reg: ldo-vtcxo1 { + regulator-name = "vtcxo1"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + regulator-ramp-delay = <0>; + regulator-always-on; + regulator-boot-on; + }; + + mt6331_vtcxo2_reg: ldo-vtcxo2 { + regulator-name = "vtcxo2"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + regulator-ramp-delay = <0>; + regulator-always-on; + regulator-boot-on; + }; + + mt6331_avdd32_aud_reg: ldo-avdd32aud { + regulator-name = "avdd32_aud"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <3200000>; + regulator-ramp-delay = <0>; + regulator-always-on; + regulator-boot-on; + }; + + mt6331_vauxa32_reg: ldo-vauxa32 { + regulator-name = "vauxa32"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <3200000>; + regulator-ramp-delay = <0>; + }; + + mt6331_vcama_reg: ldo-vcama { + regulator-name = "vcama"; + regulator-min-microvolt = <1500000>; + regulator-max-microvolt = <2800000>; + regulator-ramp-delay = <0>; + }; + + mt6331_vio28_reg: ldo-vio28 { + regulator-name = "vio28"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + regulator-ramp-delay = <0>; + regulator-always-on; + regulator-boot-on; + }; + + mt6331_vcamaf_reg: ldo-vcamaf { + regulator-name = "vcam_af"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <3300000>; + regulator-ramp-delay = <0>; + }; + + mt6331_vmc_reg: ldo-vmc { + regulator-name = "vmc"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-ramp-delay = <0>; + }; + + mt6331_vmch_reg: ldo-vmch { + regulator-name = "vmch"; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3300000>; + regulator-ramp-delay = <0>; + }; + + mt6331_vemc33_reg: ldo-vemc33 { + regulator-name = "vemc33"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-ramp-delay = <0>; + regulator-always-on; + }; + + mt6331_vgp1_reg: ldo-vgp1 { + regulator-name = "vgp1"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <3300000>; + regulator-ramp-delay = <0>; + regulator-always-on; + }; + + mt6331_vsim1_reg: ldo-vsim1 { + regulator-name = "vsim1"; + regulator-min-microvolt = <1700000>; + regulator-max-microvolt = <3100000>; + regulator-ramp-delay = <0>; + regulator-always-on; + }; + + mt6331_vsim2_reg: ldo-vsim2 { + regulator-name = "vsim2"; + regulator-min-microvolt = <1700000>; + regulator-max-microvolt = <3100000>; + regulator-ramp-delay = <0>; + }; + + mt6331_vmipi_reg: ldo-vmipi { + regulator-name = "vmipi"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <3300000>; + regulator-ramp-delay = <0>; + regulator-always-on; + }; + + mt6331_vibr_reg: ldo-vibr { + regulator-name = "vibr"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <3300000>; + regulator-ramp-delay = <0>; + }; + + mt6331_vgp4_reg: ldo-vgp4 { + regulator-name = "vgp4"; + regulator-min-microvolt = <1600000>; + regulator-max-microvolt = <2200000>; + regulator-ramp-delay = <0>; + regulator-always-on; + }; + + mt6331_vcamd_reg: ldo-vcamd { + regulator-name = "vcamd"; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <1500000>; + regulator-ramp-delay = <0>; + regulator-always-on; + }; + + mt6331_vusb10_reg: ldo-vusb10 { + regulator-name = "vusb"; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1300000>; + regulator-ramp-delay = <0>; + regulator-always-on; + regulator-boot-on; + }; + + mt6331_vcamio_reg: ldo-vcamio { + regulator-name = "vcam_io"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1800000>; + regulator-ramp-delay = <0>; + }; + + mt6331_vsram_reg: ldo-vsram { + regulator-name = "vsram"; + regulator-min-microvolt = <1012500>; + regulator-max-microvolt = <1012500>; + regulator-ramp-delay = <0>; + regulator-always-on; + regulator-boot-on; + }; + + mt6331_vgp2_reg: ldo-vgp2 { + regulator-name = "vgp2"; + regulator-min-microvolt = <1100000>; + regulator-max-microvolt = <1500000>; + regulator-ramp-delay = <0>; + regulator-always-on; + regulator-boot-on; + }; + + mt6331_vgp3_reg: ldo-vgp3 { + regulator-name = "vgp3"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1800000>; + regulator-ramp-delay = <0>; + regulator-always-on; + }; + + mt6331_vrtc_reg: ldo-vrtc { + regulator-name = "vrtc"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + regulator-ramp-delay = <0>; + regulator-always-on; + }; + + mt6331_vdig18_reg: ldo-vdig18 { + regulator-name = "dvdd18_dig"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-ramp-delay = <0>; + regulator-always-on; + }; + }; + + mt6331rtc: mt6331rtc { + compatible = "mediatek,mt6331-rtc"; + }; + + mt6331keys: mt6331keys { + compatible = "mediatek,mt6331-keys"; + power { + linux,keycodes = ; + wakeup-source; + }; + home { + linux,keycodes = ; + }; + }; + }; +}; diff --git a/arch/arm64/boot/dts/mediatek/mt6755-evb.dts b/arch/arm64/boot/dts/mediatek/mt6755-evb.dts index e079b7932ba3475033487e22017b3afef5298a5c..00b14f85c6a16f0adf6dd3cfc228ea7f58b94c99 100644 --- a/arch/arm64/boot/dts/mediatek/mt6755-evb.dts +++ b/arch/arm64/boot/dts/mediatek/mt6755-evb.dts @@ -9,6 +9,7 @@ / { model = "MediaTek MT6755 EVB"; + chassis-type = "embedded"; compatible = "mediatek,mt6755-evb", "mediatek,mt6755"; aliases { diff --git a/arch/arm64/boot/dts/mediatek/mt6779-evb.dts b/arch/arm64/boot/dts/mediatek/mt6779-evb.dts index 164f5cbb3821df2b10f50d596e5a097c22693257..56b1bf06e26b562890559ca3c746b670316997ad 100644 --- a/arch/arm64/boot/dts/mediatek/mt6779-evb.dts +++ b/arch/arm64/boot/dts/mediatek/mt6779-evb.dts @@ -10,6 +10,7 @@ / { model = "MediaTek MT6779 EVB"; + chassis-type = "embedded"; compatible = "mediatek,mt6779-evb", "mediatek,mt6779"; aliases { diff --git a/arch/arm64/boot/dts/mediatek/mt6795-evb.dts b/arch/arm64/boot/dts/mediatek/mt6795-evb.dts index 1ed2f81edeff0232c270d2869d25118ef570bbe0..e0d4d7a63139473f5af62a41970e8a3de3432894 100644 --- a/arch/arm64/boot/dts/mediatek/mt6795-evb.dts +++ b/arch/arm64/boot/dts/mediatek/mt6795-evb.dts @@ -9,6 +9,7 @@ / { model = "MediaTek MT6795 Evaluation Board"; + chassis-type = "embedded"; compatible = "mediatek,mt6795-evb", "mediatek,mt6795"; aliases { diff --git a/arch/arm64/boot/dts/mediatek/mt6795-sony-xperia-m5.dts b/arch/arm64/boot/dts/mediatek/mt6795-sony-xperia-m5.dts index 507b5b567a3671e0a4327f7bbfcf30ffd093e89d..b5746e6d0b15a5d6d59be2217225f3ad4fd03237 100644 --- a/arch/arm64/boot/dts/mediatek/mt6795-sony-xperia-m5.dts +++ b/arch/arm64/boot/dts/mediatek/mt6795-sony-xperia-m5.dts @@ -7,6 +7,7 @@ /dts-v1/; #include #include "mt6795.dtsi" +#include "mt6331.dtsi" / { model = "Sony Xperia M5"; @@ -16,6 +17,7 @@ aliases { mmc0 = &mmc0; mmc1 = &mmc1; + mmc2 = &mmc2; serial0 = &uart0; serial1 = &uart1; }; @@ -132,7 +134,97 @@ }; }; +&mmc0 { + /* eMMC controller */ + mediatek,latch-ck = <0x14>; /* hs400 */ + mediatek,hs200-cmd-int-delay = <1>; + mediatek,hs400-cmd-int-delay = <1>; + mediatek,hs400-ds-dly3 = <0x1a>; + non-removable; + pinctrl-names = "default", "state_uhs"; + pinctrl-0 = <&mmc0_pins_default>; + pinctrl-1 = <&mmc0_pins_uhs>; + vmmc-supply = <&mt6331_vemc33_reg>; + vqmmc-supply = <&mt6331_vio18_reg>; + status = "okay"; +}; + +&mmc1 { + /* MicroSD card slot */ + vmmc-supply = <&mt6331_vmc_reg>; + vqmmc-supply = <&mt6331_vmch_reg>; + status = "okay"; +}; + +&mmc2 { + /* SDIO WiFi on MMC2 */ + vmmc-supply = <&mt6331_vmc_reg>; + vqmmc-supply = <&mt6331_vmch_reg>; + status = "okay"; +}; + &pio { + mmc0_pins_default: emmc-sdr-pins { + pins-cmd-dat { + pinmux = , + , + , + , + , + , + , + , + ; + input-enable; + bias-pull-up = ; + }; + + pins-clk { + pinmux = ; + bias-pull-down = ; + }; + + pins-rst { + pinmux = ; + bias-pull-up = ; + }; + }; + + mmc0_pins_uhs: emmc-uhs-pins { + pins-cmd-dat { + pinmux = , + , + , + , + , + , + , + , + ; + input-enable; + drive-strength = ; + bias-pull-up = ; + }; + + pins-clk { + pinmux = ; + drive-strength = ; + bias-pull-down = ; + }; + + pins-rst { + pinmux = ; + drive-strength = ; + bias-pull-up = ; + }; + + pins-ds { + pinmux = ; + drive-strength = ; + bias-pull-down = ; + }; + }; + nfc_pins: nfc-pins { pins-irq { pinmux = ; @@ -239,6 +331,15 @@ }; }; +&pmic { + /* + * Smartphones, including the Xperia M5, are equipped with a companion + * MT6332 PMIC: when this is present, the main MT6331 PMIC will fire + * an interrupt on the companion, so we use the MT6332 IRQ GPIO. + */ + interrupts = ; +}; + &uart0 { status = "okay"; diff --git a/arch/arm64/boot/dts/mediatek/mt6795.dtsi b/arch/arm64/boot/dts/mediatek/mt6795.dtsi index 17019fbea0af7773f07b1b8a47f20e0e21662b6f..597bce2fed7293c3343d8035bb1cfdff8842a5f0 100644 --- a/arch/arm64/boot/dts/mediatek/mt6795.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt6795.dtsi @@ -7,6 +7,8 @@ #include #include #include +#include +#include #include #include #include @@ -372,6 +374,17 @@ clocks = <&system_clk>, <&clk32k>; }; + pwrap: pwrap@1000d000 { + compatible = "mediatek,mt6795-pwrap"; + reg = <0 0x1000d000 0 0x1000>; + reg-names = "pwrap"; + interrupts = ; + resets = <&infracfg MT6795_INFRA_RST0_PMIC_WRAP_RST>; + reset-names = "pwrap"; + clocks = <&topckgen CLK_TOP_PMICSPI_SEL>, <&clk26m>; + clock-names = "spi", "wrap"; + }; + sysirq: intpol-controller@10200620 { compatible = "mediatek,mt6795-sysirq", "mediatek,mt6577-sysirq"; @@ -389,6 +402,17 @@ clock-names = "clk13m"; }; + iommu: iommu@10205000 { + compatible = "mediatek,mt6795-m4u"; + reg = <0 0x10205000 0 0x1000>; + clocks = <&infracfg CLK_INFRA_M4U>; + clock-names = "bclk"; + interrupts = ; + mediatek,larbs = <&larb0 &larb1 &larb2 &larb3>; + power-domains = <&spm MT6795_POWER_DOMAIN_MM>; + #iommu-cells = <1>; + }; + apmixedsys: syscon@10209000 { compatible = "mediatek,mt6795-apmixedsys", "syscon"; reg = <0 0x10209000 0 0x1000>; @@ -401,6 +425,15 @@ status = "disabled"; }; + gce: mailbox@10212000 { + compatible = "mediatek,mt6795-gce", "mediatek,mt8173-gce"; + reg = <0 0x10212000 0 0x1000>; + interrupts = ; + clocks = <&infracfg CLK_INFRA_GCE>; + clock-names = "gce"; + #mbox-cells = <2>; + }; + gic: interrupt-controller@10221000 { compatible = "arm,gic-400"; #interrupt-cells = <3>; @@ -644,16 +677,77 @@ status = "disabled"; }; + mmsys: syscon@14000000 { + compatible = "mediatek,mt6795-mmsys", "syscon"; + reg = <0 0x14000000 0 0x1000>; + power-domains = <&spm MT6795_POWER_DOMAIN_MM>; + assigned-clocks = <&topckgen CLK_TOP_MM_SEL>; + assigned-clock-rates = <400000000>; + #clock-cells = <1>; + #reset-cells = <1>; + mboxes = <&gce 0 CMDQ_THR_PRIO_HIGHEST>, + <&gce 1 CMDQ_THR_PRIO_HIGHEST>; + mediatek,gce-client-reg = <&gce SUBSYS_1400XXXX 0 0x1000>; + }; + + larb0: larb@14021000 { + compatible = "mediatek,mt6795-smi-larb"; + reg = <0 0x14021000 0 0x1000>; + clocks = <&mmsys CLK_MM_SMI_COMMON>, <&mmsys CLK_MM_SMI_LARB0>; + clock-names = "apb", "smi"; + mediatek,smi = <&smi_common>; + mediatek,larb-id = <0>; + power-domains = <&spm MT6795_POWER_DOMAIN_MM>; + }; + + smi_common: smi@14022000 { + compatible = "mediatek,mt6795-smi-common"; + reg = <0 0x14022000 0 0x1000>; + power-domains = <&spm MT6795_POWER_DOMAIN_MM>; + clocks = <&infracfg CLK_INFRA_SMI>, <&mmsys CLK_MM_SMI_COMMON>; + clock-names = "apb", "smi"; + }; + + larb2: larb@15001000 { + compatible = "mediatek,mt6795-smi-larb"; + reg = <0 0x15001000 0 0x1000>; + clocks = <&mmsys CLK_MM_SMI_COMMON>, <&infracfg CLK_INFRA_SMI>; + clock-names = "apb", "smi"; + mediatek,smi = <&smi_common>; + mediatek,larb-id = <2>; + power-domains = <&spm MT6795_POWER_DOMAIN_ISP>; + }; + vdecsys: clock-controller@16000000 { compatible = "mediatek,mt6795-vdecsys"; reg = <0 0x16000000 0 0x1000>; #clock-cells = <1>; }; + larb1: larb@16010000 { + compatible = "mediatek,mt6795-smi-larb"; + reg = <0 0x16010000 0 0x1000>; + mediatek,smi = <&smi_common>; + mediatek,larb-id = <1>; + clocks = <&vdecsys CLK_VDEC_CKEN>, <&vdecsys CLK_VDEC_LARB_CKEN>; + clock-names = "apb", "smi"; + power-domains = <&spm MT6795_POWER_DOMAIN_VDEC>; + }; + vencsys: clock-controller@18000000 { compatible = "mediatek,mt6795-vencsys"; reg = <0 0x18000000 0 0x1000>; #clock-cells = <1>; }; + + larb3: larb@18001000 { + compatible = "mediatek,mt6795-smi-larb"; + reg = <0 0x18001000 0 0x1000>; + clocks = <&vencsys CLK_VENC_VENC>, <&vencsys CLK_VENC_LARB>; + clock-names = "apb", "smi"; + mediatek,smi = <&smi_common>; + mediatek,larb-id = <3>; + power-domains = <&spm MT6795_POWER_DOMAIN_VENC>; + }; }; }; diff --git a/arch/arm64/boot/dts/mediatek/mt6797-evb.dts b/arch/arm64/boot/dts/mediatek/mt6797-evb.dts index 2327e752d164829a6a300c8a44cb68024d6502e3..c927932afa0d6b0de9290d529a30c8f9b8d70c2f 100644 --- a/arch/arm64/boot/dts/mediatek/mt6797-evb.dts +++ b/arch/arm64/boot/dts/mediatek/mt6797-evb.dts @@ -9,6 +9,7 @@ / { model = "MediaTek MT6797 Evaluation Board"; + chassis-type = "embedded"; compatible = "mediatek,mt6797-evb", "mediatek,mt6797"; aliases { diff --git a/arch/arm64/boot/dts/mediatek/mt6797-x20-dev.dts b/arch/arm64/boot/dts/mediatek/mt6797-x20-dev.dts index eff9e8dbd0769df195be078d4b07392a4e5ec696..9534cf3a09d01f65d30edf70d89643063154c0e7 100644 --- a/arch/arm64/boot/dts/mediatek/mt6797-x20-dev.dts +++ b/arch/arm64/boot/dts/mediatek/mt6797-x20-dev.dts @@ -12,6 +12,7 @@ / { model = "Mediatek X20 Development Board"; + chassis-type = "embedded"; compatible = "archermind,mt6797-x20-dev", "mediatek,mt6797"; aliases { diff --git a/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts index af3fe61e409382a4d8186d893f00c4e65d8d96f3..e4605d23fdc8ee760bf327b4efeffb35c6843969 100644 --- a/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts +++ b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts @@ -15,6 +15,7 @@ / { model = "Bananapi BPI-R64"; + chassis-type = "embedded"; compatible = "bananapi,bpi-r64", "mediatek,mt7622"; aliases { @@ -150,6 +151,10 @@ switch@0 { compatible = "mediatek,mt7531"; reg = <0>; + interrupt-controller; + #interrupt-cells = <1>; + interrupt-parent = <&pio>; + interrupts = <53 IRQ_TYPE_LEVEL_HIGH>; reset-gpios = <&pio 54 0>; ports { @@ -248,14 +253,42 @@ status = "disabled"; }; -&nor_flash { - pinctrl-names = "default"; - pinctrl-0 = <&spi_nor_pins>; - status = "disabled"; +&bch { + status = "okay"; +}; +&snfi { + pinctrl-names = "default"; + pinctrl-0 = <&serial_nand_pins>; + status = "okay"; flash@0 { - compatible = "jedec,spi-nor"; + compatible = "spi-nand"; reg = <0>; + spi-tx-bus-width = <4>; + spi-rx-bus-width = <4>; + nand-ecc-engine = <&snfi>; + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "bl2"; + reg = <0x0 0x80000>; + read-only; + }; + + partition@80000 { + label = "fip"; + reg = <0x80000 0x200000>; + read-only; + }; + + ubi: partition@280000 { + label = "ubi"; + reg = <0x280000 0x7d80000>; + }; + }; }; }; diff --git a/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts b/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts index b74e774c6eba975ee56d5ef91ffb0f6622259600..dad8e683aac5bcdadb55d997c8d3bab51b68c154 100644 --- a/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts +++ b/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts @@ -15,6 +15,7 @@ / { model = "MediaTek MT7622 RFB1 board"; + chassis-type = "embedded"; compatible = "mediatek,mt7622-rfb1", "mediatek,mt7622"; aliases { diff --git a/arch/arm64/boot/dts/mediatek/mt7622.dtsi b/arch/arm64/boot/dts/mediatek/mt7622.dtsi index 006cd639059faf260194e54594b1624f8e245376..36ef2dbe8add484ea9d3ba0fbb294376d77a9215 100644 --- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi @@ -101,6 +101,7 @@ L2: l2-cache { compatible = "cache"; cache-level = <2>; + cache-unified; }; }; diff --git a/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-nand.dtso b/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-nand.dtso index 15ee8c568f3c3f681fca32d547bcf16c94f239c5..543c13385d6e3f82f013b2e6261e4d51c8b39f06 100644 --- a/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-nand.dtso +++ b/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-nand.dtso @@ -29,13 +29,13 @@ partition@0 { label = "bl2"; - reg = <0x0 0x80000>; + reg = <0x0 0x100000>; read-only; }; - partition@80000 { + partition@100000 { label = "reserved"; - reg = <0x80000 0x300000>; + reg = <0x100000 0x280000>; }; partition@380000 { diff --git a/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-nor.dtso b/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-nor.dtso index 84aa229e80f3745be2983529c9c7c00d48ec9697..e48881be4ed60c98bc89214cfe7b1dfdbf1ddf35 100644 --- a/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-nor.dtso +++ b/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-nor.dtso @@ -27,15 +27,10 @@ partition@0 { label = "bl2"; - reg = <0x0 0x20000>; + reg = <0x0 0x40000>; read-only; }; - partition@20000 { - label = "reserved"; - reg = <0x20000 0x20000>; - }; - partition@40000 { label = "u-boot-env"; reg = <0x40000 0x40000>; diff --git a/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts b/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts index 33bd6febc16053efa990e3214deb38bf92764e75..af4a4309bda4b93191601f6e38fc6044211278a9 100644 --- a/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts +++ b/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts @@ -16,6 +16,7 @@ / { model = "Bananapi BPI-R3"; + chassis-type = "embedded"; compatible = "bananapi,bpi-r3", "mediatek,mt7986a"; aliases { @@ -37,6 +38,15 @@ regulator-always-on; }; + fan: pwm-fan { + compatible = "pwm-fan"; + #cooling-cells = <2>; + /* cooling level (0, 1, 2) - pwm inverted */ + cooling-levels = <255 96 0>; + pwms = <&pwm 0 10000 0>; + status = "okay"; + }; + gpio-keys { compatible = "gpio-keys"; @@ -132,6 +142,28 @@ }; }; +&cpu_thermal { + cooling-maps { + cpu-active-high { + /* active: set fan to cooling level 2 */ + cooling-device = <&fan 2 2>; + trip = <&cpu_trip_active_high>; + }; + + cpu-active-low { + /* active: set fan to cooling level 1 */ + cooling-device = <&fan 1 1>; + trip = <&cpu_trip_active_low>; + }; + + cpu-passive { + /* passive: set fan to cooling level 0 */ + cooling-device = <&fan 0 0>; + trip = <&cpu_trip_passive>; + }; + }; +}; + &crypto { status = "okay"; }; @@ -274,6 +306,13 @@ }; }; + pwm_pins: pwm-pins { + mux { + function = "pwm"; + groups = "pwm0", "pwm1_0"; + }; + }; + spi_flash_pins: spi-flash-pins { mux { function = "spi"; @@ -344,6 +383,12 @@ }; }; +&pwm { + pinctrl-names = "default"; + pinctrl-0 = <&pwm_pins>; + status = "okay"; +}; + &spi0 { pinctrl-names = "default"; pinctrl-0 = <&spi_flash_pins>; @@ -446,5 +491,9 @@ pinctrl-names = "default", "dbdc"; pinctrl-0 = <&wf_2g_5g_pins>, <&wf_led_pins>; pinctrl-1 = <&wf_dbdc_pins>, <&wf_led_pins>; + + led { + led-active-low; + }; }; diff --git a/arch/arm64/boot/dts/mediatek/mt7986a-rfb.dts b/arch/arm64/boot/dts/mediatek/mt7986a-rfb.dts index 4f18b4a9a8c82ffa0196cf7d26df3a3566d82ccc..3ef371ca254e816c9c4be836e0c04b4bca20f584 100644 --- a/arch/arm64/boot/dts/mediatek/mt7986a-rfb.dts +++ b/arch/arm64/boot/dts/mediatek/mt7986a-rfb.dts @@ -11,6 +11,7 @@ / { model = "MediaTek MT7986a RFB"; + chassis-type = "embedded"; compatible = "mediatek,mt7986a-rfb", "mediatek,mt7986a"; aliases { diff --git a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi index 51944690e790177d6f1e15923df4a00887ef7a3f..68539ea788dfcce5e52cb996693de7766607e05e 100644 --- a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi @@ -240,6 +240,20 @@ status = "disabled"; }; + pwm: pwm@10048000 { + compatible = "mediatek,mt7986-pwm"; + reg = <0 0x10048000 0 0x1000>; + #clock-cells = <1>; + #pwm-cells = <2>; + interrupts = ; + clocks = <&topckgen CLK_TOP_PWM_SEL>, + <&infracfg CLK_INFRA_PWM_STA>, + <&infracfg CLK_INFRA_PWM1_CK>, + <&infracfg CLK_INFRA_PWM2_CK>; + clock-names = "top", "main", "pwm1", "pwm2"; + status = "disabled"; + }; + uart0: serial@11002000 { compatible = "mediatek,mt7986-uart", "mediatek,mt6577-uart"; @@ -323,6 +337,15 @@ status = "disabled"; }; + auxadc: adc@1100d000 { + compatible = "mediatek,mt7986-auxadc"; + reg = <0 0x1100d000 0 0x1000>; + clocks = <&infracfg CLK_INFRA_ADC_26M_CK>; + clock-names = "main"; + #io-channel-cells = <1>; + status = "disabled"; + }; + ssusb: usb@11200000 { compatible = "mediatek,mt7986-xhci", "mediatek,mtk-xhci"; @@ -361,6 +384,21 @@ status = "disabled"; }; + thermal: thermal@1100c800 { + #thermal-sensor-cells = <1>; + compatible = "mediatek,mt7986-thermal"; + reg = <0 0x1100c800 0 0x800>; + interrupts = ; + clocks = <&infracfg CLK_INFRA_THERM_CK>, + <&infracfg CLK_INFRA_ADC_26M_CK>, + <&infracfg CLK_INFRA_ADC_FRC_CK>; + clock-names = "therm", "auxadc", "adc_32k"; + mediatek,auxadc = <&auxadc>; + mediatek,apmixedsys = <&apmixedsys>; + nvmem-cells = <&thermal_calibration>; + nvmem-cell-names = "calibration-data"; + }; + pcie: pcie@11280000 { compatible = "mediatek,mt7986-pcie", "mediatek,mt8192-pcie"; @@ -412,6 +450,17 @@ }; }; + efuse: efuse@11d00000 { + compatible = "mediatek,mt7986-efuse", "mediatek,efuse"; + reg = <0 0x11d00000 0 0x1000>; + #address-cells = <1>; + #size-cells = <1>; + + thermal_calibration: calib@274 { + reg = <0x274 0xc>; + }; + }; + usb_phy: t-phy@11e10000 { compatible = "mediatek,mt7986-tphy", "mediatek,generic-tphy-v2"; @@ -554,4 +603,31 @@ }; }; + thermal-zones { + cpu_thermal: cpu-thermal { + polling-delay-passive = <1000>; + polling-delay = <1000>; + thermal-sensors = <&thermal 0>; + + trips { + cpu_trip_active_high: active-high { + temperature = <115000>; + hysteresis = <2000>; + type = "active"; + }; + + cpu_trip_active_low: active-low { + temperature = <85000>; + hysteresis = <2000>; + type = "active"; + }; + + cpu_trip_passive: passive { + temperature = <40000>; + hysteresis = <2000>; + type = "passive"; + }; + }; + }; + }; }; diff --git a/arch/arm64/boot/dts/mediatek/mt7986b-rfb.dts b/arch/arm64/boot/dts/mediatek/mt7986b-rfb.dts index 188ce82ae56ce7bf8cedd704e12985059c92ec25..dde190442e3866ce5cfee5be7846028e96be966c 100644 --- a/arch/arm64/boot/dts/mediatek/mt7986b-rfb.dts +++ b/arch/arm64/boot/dts/mediatek/mt7986b-rfb.dts @@ -9,6 +9,7 @@ / { model = "MediaTek MT7986b RFB"; + chassis-type = "embedded"; compatible = "mediatek,mt7986b-rfb", "mediatek,mt7986b"; aliases { diff --git a/arch/arm64/boot/dts/mediatek/mt8167-pumpkin.dts b/arch/arm64/boot/dts/mediatek/mt8167-pumpkin.dts index 774a2f3fb4b29f29b77fad6b1c7483a986ffcc9d..ebf1a358f42aaf97cd94c3cb6978028a772f2553 100644 --- a/arch/arm64/boot/dts/mediatek/mt8167-pumpkin.dts +++ b/arch/arm64/boot/dts/mediatek/mt8167-pumpkin.dts @@ -11,6 +11,7 @@ / { model = "Pumpkin MT8167"; + chassis-type = "embedded"; compatible = "mediatek,mt8167-pumpkin", "mediatek,mt8167"; memory@40000000 { diff --git a/arch/arm64/boot/dts/mediatek/mt8173-elm-hana-rev7.dts b/arch/arm64/boot/dts/mediatek/mt8173-elm-hana-rev7.dts index 28433b94f7c71a01b537cb72a0148df0f0789348..256f245ac01d879254b3a1e3e51fc1e010abf483 100644 --- a/arch/arm64/boot/dts/mediatek/mt8173-elm-hana-rev7.dts +++ b/arch/arm64/boot/dts/mediatek/mt8173-elm-hana-rev7.dts @@ -8,6 +8,7 @@ / { model = "Google Hanawl"; + chassis-type = "laptop"; compatible = "google,hana-rev7", "mediatek,mt8173"; }; diff --git a/arch/arm64/boot/dts/mediatek/mt8173-elm-hana.dts b/arch/arm64/boot/dts/mediatek/mt8173-elm-hana.dts index c234296755e1a247c265e871c6cf21e9a67636b5..fcf0cb76a87c340b3a2061430f91e8ac4d9baa31 100644 --- a/arch/arm64/boot/dts/mediatek/mt8173-elm-hana.dts +++ b/arch/arm64/boot/dts/mediatek/mt8173-elm-hana.dts @@ -8,6 +8,7 @@ / { model = "Google Hana"; + chassis-type = "laptop"; compatible = "google,hana-rev6", "google,hana-rev5", "google,hana-rev4", "google,hana-rev3", "google,hana", "mediatek,mt8173"; diff --git a/arch/arm64/boot/dts/mediatek/mt8173-elm.dts b/arch/arm64/boot/dts/mediatek/mt8173-elm.dts index e9e4ac0b74b2a9394b0a68d2b2a9e6c439bedadd..2390d04204e83323aa0104a243bedb2824d26f97 100644 --- a/arch/arm64/boot/dts/mediatek/mt8173-elm.dts +++ b/arch/arm64/boot/dts/mediatek/mt8173-elm.dts @@ -8,6 +8,7 @@ / { model = "Google Elm"; + chassis-type = "laptop"; compatible = "google,elm-rev8", "google,elm-rev7", "google,elm-rev6", "google,elm-rev5", "google,elm-rev4", "google,elm-rev3", "google,elm", "mediatek,mt8173"; diff --git a/arch/arm64/boot/dts/mediatek/mt8173-elm.dtsi b/arch/arm64/boot/dts/mediatek/mt8173-elm.dtsi index d77f6af19065e7a664b1495b33cc1b9946c78984..111495622cacdc6c05b590ee273e331a97af3ed6 100644 --- a/arch/arm64/boot/dts/mediatek/mt8173-elm.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt8173-elm.dtsi @@ -96,6 +96,8 @@ regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; enable-active-high; + regulator-boot-on; + off-on-delay-us = <500000>; gpio = <&pio 41 GPIO_ACTIVE_HIGH>; pinctrl-names = "default"; pinctrl-0 = <&panel_fixed_pins>; @@ -285,7 +287,7 @@ aux-bus { panel: panel { - compatible = "lg,lp120up1"; + compatible = "edp-panel"; power-supply = <&panel_fixed_3v3>; backlight = <&backlight>; diff --git a/arch/arm64/boot/dts/mediatek/mt8173-evb.dts b/arch/arm64/boot/dts/mediatek/mt8173-evb.dts index 755df569423452d8a1be4291d29fedf695e8ffda..5122963d8743ab3fd5049032369976099e1a26d6 100644 --- a/arch/arm64/boot/dts/mediatek/mt8173-evb.dts +++ b/arch/arm64/boot/dts/mediatek/mt8173-evb.dts @@ -10,6 +10,7 @@ / { model = "MediaTek MT8173 evaluation board"; + chassis-type = "embedded"; compatible = "mediatek,mt8173-evb", "mediatek,mt8173"; aliases { diff --git a/arch/arm64/boot/dts/mediatek/mt8183-evb.dts b/arch/arm64/boot/dts/mediatek/mt8183-evb.dts index 3e3f4b1b00f02179573a1f5ff46721d4438c763d..d8bd5180768327bc76b9a1f77716ee8ee64d38c8 100644 --- a/arch/arm64/boot/dts/mediatek/mt8183-evb.dts +++ b/arch/arm64/boot/dts/mediatek/mt8183-evb.dts @@ -11,6 +11,7 @@ / { model = "MediaTek MT8183 evaluation board"; + chassis-type = "embedded"; compatible = "mediatek,mt8183-evb", "mediatek,mt8183"; aliases { diff --git a/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-burnet.dts b/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-burnet.dts index 1a2ec0787d3caa5ae29e3d3f510681f28fd427c7..19c1e2bee494c98c0db87308494713a26e304cd2 100644 --- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-burnet.dts +++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-burnet.dts @@ -9,6 +9,7 @@ / { model = "Google burnet board"; + chassis-type = "convertible"; compatible = "google,burnet", "mediatek,mt8183"; }; diff --git a/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-damu.dts b/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-damu.dts index 0eca3ff8672a755cf60359a9f1be88832c59844f..552bfc72699945bd86f84a8688edb3bd80be4869 100644 --- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-damu.dts +++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-damu.dts @@ -9,6 +9,7 @@ / { model = "Google damu board"; + chassis-type = "convertible"; compatible = "google,damu", "mediatek,mt8183"; }; diff --git a/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-juniper-sku16.dts b/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-juniper-sku16.dts index bc2c57f0a827b1fdbc09320964e689206e335774..8ac6bf5b17f97719e532eec9b22c964e0b663d63 100644 --- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-juniper-sku16.dts +++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-juniper-sku16.dts @@ -9,6 +9,7 @@ / { model = "Google juniper sku16 board"; + chassis-type = "convertible"; compatible = "google,juniper-sku16", "google,juniper", "mediatek,mt8183"; }; diff --git a/arch/arm64/boot/dts/mediatek/mt8183-kukui-kakadu-sku22.dts b/arch/arm64/boot/dts/mediatek/mt8183-kukui-kakadu-sku22.dts index 3a724e6f915cd5c765a013fe72df84250ef6bcb4..fcce8ea1232e64e91bdc9835d18756df9f9d031e 100644 --- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-kakadu-sku22.dts +++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-kakadu-sku22.dts @@ -9,6 +9,7 @@ / { model = "MediaTek kakadu board sku22"; + chassis-type = "tablet"; compatible = "google,kakadu-rev3-sku22", "google,kakadu-rev2-sku22", "google,kakadu", "mediatek,mt8183"; }; diff --git a/arch/arm64/boot/dts/mediatek/mt8183-kukui-kakadu.dts b/arch/arm64/boot/dts/mediatek/mt8183-kukui-kakadu.dts index 89a139a0ee44426922c1d3e5bbe9c8375a22a1e7..ebfabba72507583c1bb410f334056b0367632fea 100644 --- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-kakadu.dts +++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-kakadu.dts @@ -9,6 +9,7 @@ / { model = "MediaTek kakadu board"; + chassis-type = "tablet"; compatible = "google,kakadu-rev3", "google,kakadu-rev2", "google,kakadu", "mediatek,mt8183"; }; diff --git a/arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama-sku16.dts b/arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama-sku16.dts index e3dd75bdaea4310c86e29a92c52dfb0e2f7781bf..7213cdcca612a6fdc7933d7aca5dbd5f9ca45b6b 100644 --- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama-sku16.dts +++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama-sku16.dts @@ -12,6 +12,7 @@ / { model = "MediaTek kodama sku16 board"; + chassis-type = "tablet"; compatible = "google,kodama-sku16", "google,kodama", "mediatek,mt8183"; }; diff --git a/arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama-sku272.dts b/arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama-sku272.dts index d81935ae07bc9b8bb6fbc63a3f486e3ac3f6c177..bbf0cd1aa66d1121b1415bd5605b95b9e2810e0e 100644 --- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama-sku272.dts +++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama-sku272.dts @@ -12,6 +12,7 @@ / { model = "MediaTek kodama sku272 board"; + chassis-type = "tablet"; compatible = "google,kodama-sku272", "google,kodama", "mediatek,mt8183"; }; diff --git a/arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama-sku288.dts b/arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama-sku288.dts index f4082fbe0517a593fcd022cf52a30dc389c5a610..a429ffeac3bdf98dab72932cbe300cb2659be308 100644 --- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama-sku288.dts +++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama-sku288.dts @@ -12,6 +12,7 @@ / { model = "MediaTek kodama sku288 board"; + chassis-type = "tablet"; compatible = "google,kodama-sku288", "google,kodama", "mediatek,mt8183"; }; diff --git a/arch/arm64/boot/dts/mediatek/mt8183-kukui-krane-sku0.dts b/arch/arm64/boot/dts/mediatek/mt8183-kukui-krane-sku0.dts index fb5ee91b6fe0e197b3884574d96cc07f3c7cc784..4ac75806fa9484e6e0e524b210bbb3a3d8eda6e5 100644 --- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-krane-sku0.dts +++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-krane-sku0.dts @@ -14,6 +14,7 @@ / { model = "MediaTek krane sku0 board"; + chassis-type = "tablet"; compatible = "google,krane-sku0", "google,krane", "mediatek,mt8183"; }; diff --git a/arch/arm64/boot/dts/mediatek/mt8183-kukui-krane-sku176.dts b/arch/arm64/boot/dts/mediatek/mt8183-kukui-krane-sku176.dts index 721d16f9c3b4fcc4f106b2ef24837c7209dc8877..095279e55d50c8a6e4a5641959137f71e9aa8992 100644 --- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-krane-sku176.dts +++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-krane-sku176.dts @@ -14,6 +14,7 @@ / { model = "MediaTek krane sku176 board"; + chassis-type = "tablet"; compatible = "google,krane-sku176", "google,krane", "mediatek,mt8183"; }; diff --git a/arch/arm64/boot/dts/mediatek/mt8183-kukui.dtsi b/arch/arm64/boot/dts/mediatek/mt8183-kukui.dtsi index 63952c1251dfd7bb48d1ae9f274dbbec64afb818..6ce16a265e05303a53c2524df04218f61f9a64b5 100644 --- a/arch/arm64/boot/dts/mediatek/mt8183-kukui.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui.dtsi @@ -292,6 +292,10 @@ }; }; +&gic { + mediatek,broken-save-restore-fw; +}; + &gpu { mali-supply = <&mt6358_vgpu_reg>; }; @@ -822,6 +826,8 @@ &scp { status = "okay"; + + firmware-name = "mediatek/mt8183/scp.img"; pinctrl-names = "default"; pinctrl-0 = <&scp_pins>; diff --git a/arch/arm64/boot/dts/mediatek/mt8186-evb.dts b/arch/arm64/boot/dts/mediatek/mt8186-evb.dts index ed74a3617c13521eacb103a3bd250839cbb5539e..2667a7424200e2ede7d7aaf8b76e6829ae01e758 100644 --- a/arch/arm64/boot/dts/mediatek/mt8186-evb.dts +++ b/arch/arm64/boot/dts/mediatek/mt8186-evb.dts @@ -7,6 +7,7 @@ / { model = "MediaTek MT8186 evaluation board"; + chassis-type = "embedded"; compatible = "mediatek,mt8186-evb", "mediatek,mt8186"; aliases { diff --git a/arch/arm64/boot/dts/mediatek/mt8186.dtsi b/arch/arm64/boot/dts/mediatek/mt8186.dtsi index 5e83d4e9efa4103ed6e9ccb12571ac4b674c02c3..f04ae70c470aa3f409579187c12ac9eac77b4cd9 100644 --- a/arch/arm64/boot/dts/mediatek/mt8186.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt8186.dtsi @@ -5,6 +5,7 @@ */ /dts-v1/; #include +#include #include #include #include @@ -19,6 +20,308 @@ #address-cells = <2>; #size-cells = <2>; + aliases { + ovl0 = &ovl0; + ovl_2l0 = &ovl_2l0; + rdma0 = &rdma0; + rdma1 = &rdma1; + }; + + cci: cci { + compatible = "mediatek,mt8186-cci"; + clocks = <&mcusys CLK_MCU_ARMPLL_BUS_SEL>, + <&apmixedsys CLK_APMIXED_MAINPLL>; + clock-names = "cci", "intermediate"; + operating-points-v2 = <&cci_opp>; + }; + + cci_opp: opp-table-cci { + compatible = "operating-points-v2"; + opp-shared; + + cci_opp_0: opp-500000000 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <600000>; + }; + + cci_opp_1: opp-560000000 { + opp-hz = /bits/ 64 <560000000>; + opp-microvolt = <675000>; + }; + + cci_opp_2: opp-612000000 { + opp-hz = /bits/ 64 <612000000>; + opp-microvolt = <693750>; + }; + + cci_opp_3: opp-682000000 { + opp-hz = /bits/ 64 <682000000>; + opp-microvolt = <718750>; + }; + + cci_opp_4: opp-752000000 { + opp-hz = /bits/ 64 <752000000>; + opp-microvolt = <743750>; + }; + + cci_opp_5: opp-822000000 { + opp-hz = /bits/ 64 <822000000>; + opp-microvolt = <768750>; + }; + + cci_opp_6: opp-875000000 { + opp-hz = /bits/ 64 <875000000>; + opp-microvolt = <781250>; + }; + + cci_opp_7: opp-927000000 { + opp-hz = /bits/ 64 <927000000>; + opp-microvolt = <800000>; + }; + + cci_opp_8: opp-980000000 { + opp-hz = /bits/ 64 <980000000>; + opp-microvolt = <818750>; + }; + + cci_opp_9: opp-1050000000 { + opp-hz = /bits/ 64 <1050000000>; + opp-microvolt = <843750>; + }; + + cci_opp_10: opp-1120000000 { + opp-hz = /bits/ 64 <1120000000>; + opp-microvolt = <862500>; + }; + + cci_opp_11: opp-1155000000 { + opp-hz = /bits/ 64 <1155000000>; + opp-microvolt = <887500>; + }; + + cci_opp_12: opp-1190000000 { + opp-hz = /bits/ 64 <1190000000>; + opp-microvolt = <906250>; + }; + + cci_opp_13: opp-1260000000 { + opp-hz = /bits/ 64 <1260000000>; + opp-microvolt = <950000>; + }; + + cci_opp_14: opp-1330000000 { + opp-hz = /bits/ 64 <1330000000>; + opp-microvolt = <993750>; + }; + + cci_opp_15: opp-1400000000 { + opp-hz = /bits/ 64 <1400000000>; + opp-microvolt = <1031250>; + }; + }; + + cluster0_opp: opp-table-cluster0 { + compatible = "operating-points-v2"; + opp-shared; + + opp-500000000 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <600000>; + required-opps = <&cci_opp_0>; + }; + + opp-774000000 { + opp-hz = /bits/ 64 <774000000>; + opp-microvolt = <675000>; + required-opps = <&cci_opp_1>; + }; + + opp-875000000 { + opp-hz = /bits/ 64 <875000000>; + opp-microvolt = <700000>; + required-opps = <&cci_opp_2>; + }; + + opp-975000000 { + opp-hz = /bits/ 64 <975000000>; + opp-microvolt = <725000>; + required-opps = <&cci_opp_3>; + }; + + opp-1075000000 { + opp-hz = /bits/ 64 <1075000000>; + opp-microvolt = <750000>; + required-opps = <&cci_opp_4>; + }; + + opp-1175000000 { + opp-hz = /bits/ 64 <1175000000>; + opp-microvolt = <775000>; + required-opps = <&cci_opp_5>; + }; + + opp-1275000000 { + opp-hz = /bits/ 64 <1275000000>; + opp-microvolt = <800000>; + required-opps = <&cci_opp_6>; + }; + + opp-1375000000 { + opp-hz = /bits/ 64 <1375000000>; + opp-microvolt = <825000>; + required-opps = <&cci_opp_7>; + }; + + opp-1500000000 { + opp-hz = /bits/ 64 <1500000000>; + opp-microvolt = <856250>; + required-opps = <&cci_opp_8>; + }; + + opp-1618000000 { + opp-hz = /bits/ 64 <1618000000>; + opp-microvolt = <875000>; + required-opps = <&cci_opp_9>; + }; + + opp-1666000000 { + opp-hz = /bits/ 64 <1666000000>; + opp-microvolt = <900000>; + required-opps = <&cci_opp_10>; + }; + + opp-1733000000 { + opp-hz = /bits/ 64 <1733000000>; + opp-microvolt = <925000>; + required-opps = <&cci_opp_11>; + }; + + opp-1800000000 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <950000>; + required-opps = <&cci_opp_12>; + }; + + opp-1866000000 { + opp-hz = /bits/ 64 <1866000000>; + opp-microvolt = <981250>; + required-opps = <&cci_opp_13>; + }; + + opp-1933000000 { + opp-hz = /bits/ 64 <1933000000>; + opp-microvolt = <1006250>; + required-opps = <&cci_opp_14>; + }; + + opp-2000000000 { + opp-hz = /bits/ 64 <2000000000>; + opp-microvolt = <1031250>; + required-opps = <&cci_opp_15>; + }; + }; + + cluster1_opp: opp-table-cluster1 { + compatible = "operating-points-v2"; + opp-shared; + + opp-774000000 { + opp-hz = /bits/ 64 <774000000>; + opp-microvolt = <675000>; + required-opps = <&cci_opp_0>; + }; + + opp-835000000 { + opp-hz = /bits/ 64 <835000000>; + opp-microvolt = <693750>; + required-opps = <&cci_opp_1>; + }; + + opp-919000000 { + opp-hz = /bits/ 64 <919000000>; + opp-microvolt = <718750>; + required-opps = <&cci_opp_2>; + }; + + opp-1002000000 { + opp-hz = /bits/ 64 <1002000000>; + opp-microvolt = <743750>; + required-opps = <&cci_opp_3>; + }; + + opp-1085000000 { + opp-hz = /bits/ 64 <1085000000>; + opp-microvolt = <775000>; + required-opps = <&cci_opp_4>; + }; + + opp-1169000000 { + opp-hz = /bits/ 64 <1169000000>; + opp-microvolt = <800000>; + required-opps = <&cci_opp_5>; + }; + + opp-1308000000 { + opp-hz = /bits/ 64 <1308000000>; + opp-microvolt = <843750>; + required-opps = <&cci_opp_6>; + }; + + opp-1419000000 { + opp-hz = /bits/ 64 <1419000000>; + opp-microvolt = <875000>; + required-opps = <&cci_opp_7>; + }; + + opp-1530000000 { + opp-hz = /bits/ 64 <1530000000>; + opp-microvolt = <912500>; + required-opps = <&cci_opp_8>; + }; + + opp-1670000000 { + opp-hz = /bits/ 64 <1670000000>; + opp-microvolt = <956250>; + required-opps = <&cci_opp_9>; + }; + + opp-1733000000 { + opp-hz = /bits/ 64 <1733000000>; + opp-microvolt = <981250>; + required-opps = <&cci_opp_10>; + }; + + opp-1796000000 { + opp-hz = /bits/ 64 <1796000000>; + opp-microvolt = <1012500>; + required-opps = <&cci_opp_11>; + }; + + opp-1860000000 { + opp-hz = /bits/ 64 <1860000000>; + opp-microvolt = <1037500>; + required-opps = <&cci_opp_12>; + }; + + opp-1923000000 { + opp-hz = /bits/ 64 <1923000000>; + opp-microvolt = <1062500>; + required-opps = <&cci_opp_13>; + }; + + cluster1_opp_14: opp-1986000000 { + opp-hz = /bits/ 64 <1986000000>; + opp-microvolt = <1093750>; + required-opps = <&cci_opp_14>; + }; + + cluster1_opp_15: opp-2050000000 { + opp-hz = /bits/ 64 <2050000000>; + opp-microvolt = <1118750>; + required-opps = <&cci_opp_15>; + }; + }; + cpus { #address-cells = <1>; #size-cells = <0>; @@ -65,6 +368,11 @@ reg = <0x000>; enable-method = "psci"; clock-frequency = <2000000000>; + clocks = <&mcusys CLK_MCU_ARMPLL_LL_SEL>, + <&apmixedsys CLK_APMIXED_MAINPLL>; + clock-names = "cpu", "intermediate"; + operating-points-v2 = <&cluster0_opp>; + dynamic-power-coefficient = <84>; capacity-dmips-mhz = <382>; cpu-idle-states = <&cpu_ret_l &cpu_off_l>; i-cache-size = <32768>; @@ -75,6 +383,7 @@ d-cache-sets = <128>; next-level-cache = <&l2_0>; #cooling-cells = <2>; + mediatek,cci = <&cci>; }; cpu1: cpu@100 { @@ -83,6 +392,11 @@ reg = <0x100>; enable-method = "psci"; clock-frequency = <2000000000>; + clocks = <&mcusys CLK_MCU_ARMPLL_LL_SEL>, + <&apmixedsys CLK_APMIXED_MAINPLL>; + clock-names = "cpu", "intermediate"; + operating-points-v2 = <&cluster0_opp>; + dynamic-power-coefficient = <84>; capacity-dmips-mhz = <382>; cpu-idle-states = <&cpu_ret_l &cpu_off_l>; i-cache-size = <32768>; @@ -93,6 +407,7 @@ d-cache-sets = <128>; next-level-cache = <&l2_0>; #cooling-cells = <2>; + mediatek,cci = <&cci>; }; cpu2: cpu@200 { @@ -101,6 +416,11 @@ reg = <0x200>; enable-method = "psci"; clock-frequency = <2000000000>; + clocks = <&mcusys CLK_MCU_ARMPLL_LL_SEL>, + <&apmixedsys CLK_APMIXED_MAINPLL>; + clock-names = "cpu", "intermediate"; + operating-points-v2 = <&cluster0_opp>; + dynamic-power-coefficient = <84>; capacity-dmips-mhz = <382>; cpu-idle-states = <&cpu_ret_l &cpu_off_l>; i-cache-size = <32768>; @@ -111,6 +431,7 @@ d-cache-sets = <128>; next-level-cache = <&l2_0>; #cooling-cells = <2>; + mediatek,cci = <&cci>; }; cpu3: cpu@300 { @@ -119,6 +440,11 @@ reg = <0x300>; enable-method = "psci"; clock-frequency = <2000000000>; + clocks = <&mcusys CLK_MCU_ARMPLL_LL_SEL>, + <&apmixedsys CLK_APMIXED_MAINPLL>; + clock-names = "cpu", "intermediate"; + operating-points-v2 = <&cluster0_opp>; + dynamic-power-coefficient = <84>; capacity-dmips-mhz = <382>; cpu-idle-states = <&cpu_ret_l &cpu_off_l>; i-cache-size = <32768>; @@ -129,6 +455,7 @@ d-cache-sets = <128>; next-level-cache = <&l2_0>; #cooling-cells = <2>; + mediatek,cci = <&cci>; }; cpu4: cpu@400 { @@ -137,6 +464,11 @@ reg = <0x400>; enable-method = "psci"; clock-frequency = <2000000000>; + clocks = <&mcusys CLK_MCU_ARMPLL_LL_SEL>, + <&apmixedsys CLK_APMIXED_MAINPLL>; + clock-names = "cpu", "intermediate"; + operating-points-v2 = <&cluster0_opp>; + dynamic-power-coefficient = <84>; capacity-dmips-mhz = <382>; cpu-idle-states = <&cpu_ret_l &cpu_off_l>; i-cache-size = <32768>; @@ -147,6 +479,7 @@ d-cache-sets = <128>; next-level-cache = <&l2_0>; #cooling-cells = <2>; + mediatek,cci = <&cci>; }; cpu5: cpu@500 { @@ -155,6 +488,11 @@ reg = <0x500>; enable-method = "psci"; clock-frequency = <2000000000>; + clocks = <&mcusys CLK_MCU_ARMPLL_LL_SEL>, + <&apmixedsys CLK_APMIXED_MAINPLL>; + clock-names = "cpu", "intermediate"; + operating-points-v2 = <&cluster0_opp>; + dynamic-power-coefficient = <84>; capacity-dmips-mhz = <382>; cpu-idle-states = <&cpu_ret_l &cpu_off_l>; i-cache-size = <32768>; @@ -165,6 +503,7 @@ d-cache-sets = <128>; next-level-cache = <&l2_0>; #cooling-cells = <2>; + mediatek,cci = <&cci>; }; cpu6: cpu@600 { @@ -173,6 +512,11 @@ reg = <0x600>; enable-method = "psci"; clock-frequency = <2050000000>; + clocks = <&mcusys CLK_MCU_ARMPLL_BL_SEL>, + <&apmixedsys CLK_APMIXED_MAINPLL>; + clock-names = "cpu", "intermediate"; + operating-points-v2 = <&cluster1_opp>; + dynamic-power-coefficient = <335>; capacity-dmips-mhz = <1024>; cpu-idle-states = <&cpu_ret_b &cpu_off_b>; i-cache-size = <65536>; @@ -183,6 +527,7 @@ d-cache-sets = <256>; next-level-cache = <&l2_1>; #cooling-cells = <2>; + mediatek,cci = <&cci>; }; cpu7: cpu@700 { @@ -191,6 +536,11 @@ reg = <0x700>; enable-method = "psci"; clock-frequency = <2050000000>; + clocks = <&mcusys CLK_MCU_ARMPLL_BL_SEL>, + <&apmixedsys CLK_APMIXED_MAINPLL>; + clock-names = "cpu", "intermediate"; + operating-points-v2 = <&cluster1_opp>; + dynamic-power-coefficient = <335>; capacity-dmips-mhz = <1024>; cpu-idle-states = <&cpu_ret_b &cpu_off_b>; i-cache-size = <65536>; @@ -201,6 +551,7 @@ d-cache-sets = <256>; next-level-cache = <&l2_1>; #cooling-cells = <2>; + mediatek,cci = <&cci>; }; idle-states { @@ -250,6 +601,7 @@ cache-line-size = <64>; cache-sets = <512>; next-level-cache = <&l3_0>; + cache-unified; }; l2_1: l2-cache1 { @@ -259,6 +611,7 @@ cache-line-size = <64>; cache-sets = <512>; next-level-cache = <&l3_0>; + cache-unified; }; l3_0: l3-cache { @@ -294,6 +647,142 @@ clock-output-names = "clk32k"; }; + gpu_opp_table: opp-table-gpu { + compatible = "operating-points-v2"; + + opp-299000000 { + opp-hz = /bits/ 64 <299000000>; + opp-microvolt = <612500>; + opp-supported-hw = <0xff>; + }; + + opp-332000000 { + opp-hz = /bits/ 64 <332000000>; + opp-microvolt = <625000>; + opp-supported-hw = <0xff>; + }; + + opp-366000000 { + opp-hz = /bits/ 64 <366000000>; + opp-microvolt = <637500>; + opp-supported-hw = <0xff>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + opp-microvolt = <643750>; + opp-supported-hw = <0xff>; + }; + + opp-434000000 { + opp-hz = /bits/ 64 <434000000>; + opp-microvolt = <656250>; + opp-supported-hw = <0xff>; + }; + + opp-484000000 { + opp-hz = /bits/ 64 <484000000>; + opp-microvolt = <668750>; + opp-supported-hw = <0xff>; + }; + + opp-535000000 { + opp-hz = /bits/ 64 <535000000>; + opp-microvolt = <687500>; + opp-supported-hw = <0xff>; + }; + + opp-586000000 { + opp-hz = /bits/ 64 <586000000>; + opp-microvolt = <700000>; + opp-supported-hw = <0xff>; + }; + + opp-637000000 { + opp-hz = /bits/ 64 <637000000>; + opp-microvolt = <712500>; + opp-supported-hw = <0xff>; + }; + + opp-690000000 { + opp-hz = /bits/ 64 <690000000>; + opp-microvolt = <737500>; + opp-supported-hw = <0xff>; + }; + + opp-743000000 { + opp-hz = /bits/ 64 <743000000>; + opp-microvolt = <756250>; + opp-supported-hw = <0xff>; + }; + + opp-796000000 { + opp-hz = /bits/ 64 <796000000>; + opp-microvolt = <781250>; + opp-supported-hw = <0xff>; + }; + + opp-850000000 { + opp-hz = /bits/ 64 <850000000>; + opp-microvolt = <800000>; + opp-supported-hw = <0xff>; + }; + + opp-900000000-3 { + opp-hz = /bits/ 64 <900000000>; + opp-microvolt = <850000>; + opp-supported-hw = <0x8>; + }; + + opp-900000000-4 { + opp-hz = /bits/ 64 <900000000>; + opp-microvolt = <837500>; + opp-supported-hw = <0x10>; + }; + + opp-900000000-5 { + opp-hz = /bits/ 64 <900000000>; + opp-microvolt = <825000>; + opp-supported-hw = <0x30>; + }; + + opp-950000000-3 { + opp-hz = /bits/ 64 <950000000>; + opp-microvolt = <900000>; + opp-supported-hw = <0x8>; + }; + + opp-950000000-4 { + opp-hz = /bits/ 64 <950000000>; + opp-microvolt = <875000>; + opp-supported-hw = <0x10>; + }; + + opp-950000000-5 { + opp-hz = /bits/ 64 <950000000>; + opp-microvolt = <850000>; + opp-supported-hw = <0x30>; + }; + + opp-1000000000-3 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <950000>; + opp-supported-hw = <0x8>; + }; + + opp-1000000000-4 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <912500>; + opp-supported-hw = <0x10>; + }; + + opp-1000000000-5 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <875000>; + opp-supported-hw = <0x30>; + }; + }; + pmu-a55 { compatible = "arm,cortex-a55-pmu"; interrupt-parent = <&gic>; @@ -412,7 +901,7 @@ #size-cells = <0>; #power-domain-cells = <1>; - power-domain@MT8186_POWER_DOMAIN_MFG1 { + mfg1: power-domain@MT8186_POWER_DOMAIN_MFG1 { reg = ; mediatek,infracfg = <&infracfg_ao>; #address-cells = <1>; @@ -603,6 +1092,21 @@ clock-names = "spi", "wrap"; }; + spmi: spmi@10015000 { + compatible = "mediatek,mt8186-spmi", "mediatek,mt8195-spmi"; + reg = <0 0x10015000 0 0x000e00>, <0 0x1001B000 0 0x000100>; + reg-names = "pmif", "spmimst"; + clocks = <&infracfg_ao CLK_INFRA_AO_PMIC_AP>, + <&infracfg_ao CLK_INFRA_AO_PMIC_TMR>, + <&topckgen CLK_TOP_SPMI_MST>; + clock-names = "pmif_sys_ck", "pmif_tmr_ck", "spmimst_clk_mux"; + assigned-clocks = <&topckgen CLK_TOP_SPMI_MST>; + assigned-clock-parents = <&topckgen CLK_TOP_ULPOSC1_D10>; + interrupts = , + ; + status = "disabled"; + }; + systimer: timer@10017000 { compatible = "mediatek,mt8186-timer", "mediatek,mt6765-timer"; @@ -611,6 +1115,15 @@ clocks = <&clk13m>; }; + gce: mailbox@1022c000 { + compatible = "mediatek,mt8186-gce"; + reg = <0 0X1022c000 0 0x4000>; + clocks = <&infracfg_ao CLK_INFRA_AO_GCE>; + clock-names = "gce"; + interrupts = ; + #mbox-cells = <2>; + }; + scp: scp@10500000 { compatible = "mediatek,mt8186-scp"; reg = <0 0x10500000 0 0x40000>, @@ -619,6 +1132,22 @@ interrupts = ; }; + adsp: adsp@10680000 { + compatible = "mediatek,mt8186-dsp"; + reg = <0 0x10680000 0 0x2000>, <0 0x10800000 0 0x100000>, + <0 0x1068b000 0 0x100>, <0 0x1068f000 0 0x1000>; + reg-names = "cfg", "sram", "sec", "bus"; + clocks = <&topckgen CLK_TOP_AUDIODSP>, <&topckgen CLK_TOP_ADSP_BUS>; + clock-names = "audiodsp", "adsp_bus"; + assigned-clocks = <&topckgen CLK_TOP_AUDIODSP>, + <&topckgen CLK_TOP_ADSP_BUS>; + assigned-clock-parents = <&clk26m>, <&topckgen CLK_TOP_MAINPLL_D2_D2>; + mbox-names = "rx", "tx"; + mboxes = <&adsp_mailbox0>, <&adsp_mailbox1>; + power-domains = <&spm MT8186_POWER_DOMAIN_ADSP_TOP>; + status = "disabled"; + }; + adsp_mailbox0: mailbox@10686000 { compatible = "mediatek,mt8186-adsp-mbox"; #mbox-cells = <0>; @@ -982,6 +1511,40 @@ status = "disabled"; }; + ssusb0: usb@11201000 { + compatible = "mediatek,mt8186-mtu3", "mediatek,mtu3"; + reg = <0 0x11201000 0 0x2dff>, <0 0x11203e00 0 0x0100>; + reg-names = "mac", "ippc"; + clocks = <&topckgen CLK_TOP_USB_TOP>, + <&infracfg_ao CLK_INFRA_AO_SSUSB_TOP_REF>, + <&infracfg_ao CLK_INFRA_AO_SSUSB_TOP_HCLK>, + <&infracfg_ao CLK_INFRA_AO_ICUSB>; + clock-names = "sys_ck", "ref_ck", "mcu_ck", "dma_ck"; + interrupts = ; + phys = <&u2port0 PHY_TYPE_USB2>; + power-domains = <&spm MT8186_POWER_DOMAIN_SSUSB>; + #address-cells = <2>; + #size-cells = <2>; + ranges; + status = "disabled"; + + usb_host0: usb@11200000 { + compatible = "mediatek,mt8186-xhci", "mediatek,mtk-xhci"; + reg = <0 0x11200000 0 0x1000>; + reg-names = "mac"; + clocks = <&topckgen CLK_TOP_USB_TOP>, + <&infracfg_ao CLK_INFRA_AO_SSUSB_TOP_REF>, + <&infracfg_ao CLK_INFRA_AO_SSUSB_TOP_HCLK>, + <&infracfg_ao CLK_INFRA_AO_ICUSB>, + <&infracfg_ao CLK_INFRA_AO_SSUSB_TOP_XHCI>; + clock-names = "sys_ck", "ref_ck", "mcu_ck", "dma_ck", "xhci_ck"; + interrupts = ; + mediatek,syscon-wakeup = <&pericfg 0x420 2>; + wakeup-source; + status = "disabled"; + }; + }; + mmc0: mmc@11230000 { compatible = "mediatek,mt8186-mmc", "mediatek,mt8183-mmc"; @@ -1013,6 +1576,40 @@ status = "disabled"; }; + ssusb1: usb@11281000 { + compatible = "mediatek,mt8186-mtu3", "mediatek,mtu3"; + reg = <0 0x11281000 0 0x2dff>, <0 0x11283e00 0 0x0100>; + reg-names = "mac", "ippc"; + clocks = <&infracfg_ao CLK_INFRA_AO_SSUSB_TOP_P1_SYS>, + <&infracfg_ao CLK_INFRA_AO_SSUSB_TOP_P1_REF>, + <&infracfg_ao CLK_INFRA_AO_SSUSB_TOP_P1_HCLK>, + <&clk26m>; + clock-names = "sys_ck", "ref_ck", "mcu_ck", "dma_ck"; + interrupts = ; + phys = <&u2port1 PHY_TYPE_USB2>, <&u3port1 PHY_TYPE_USB3>; + power-domains = <&spm MT8186_POWER_DOMAIN_SSUSB_P1>; + #address-cells = <2>; + #size-cells = <2>; + ranges; + status = "disabled"; + + usb_host1: usb@11280000 { + compatible = "mediatek,mt8186-xhci", "mediatek,mtk-xhci"; + reg = <0 0x11280000 0 0x1000>; + reg-names = "mac"; + clocks = <&infracfg_ao CLK_INFRA_AO_SSUSB_TOP_P1_SYS>, + <&infracfg_ao CLK_INFRA_AO_SSUSB_TOP_P1_REF>, + <&infracfg_ao CLK_INFRA_AO_SSUSB_TOP_P1_HCLK>, + <&clk26m>, + <&infracfg_ao CLK_INFRA_AO_SSUSB_TOP_P1_XHCI>; + clock-names = "sys_ck", "ref_ck", "mcu_ck", "dma_ck","xhci_ck"; + interrupts = ; + mediatek,syscon-wakeup = <&pericfg 0x424 2>; + wakeup-source; + status = "disabled"; + }; + }; + u3phy0: t-phy@11c80000 { compatible = "mediatek,mt8186-tphy", "mediatek,generic-tphy-v2"; @@ -1058,6 +1655,11 @@ reg = <0 0x11cb0000 0 0x1000>; #address-cells = <1>; #size-cells = <1>; + + gpu_speedbin: gpu-speed-bin@59c { + reg = <0x59c 0x4>; + bits = <0 3>; + }; }; mipi_tx0: dsi-phy@11cc0000 { @@ -1090,6 +1692,10 @@ <&spm MT8186_POWER_DOMAIN_MFG3>; power-domain-names = "core0", "core1"; #cooling-cells = <2>; + nvmem-cells = <&gpu_speedbin>; + nvmem-cell-names = "speed-bin"; + operating-points-v2 = <&gpu_opp_table>; + dynamic-power-coefficient = <4687>; status = "disabled"; }; @@ -1098,6 +1704,20 @@ reg = <0 0x14000000 0 0x1000>; #clock-cells = <1>; #reset-cells = <1>; + mboxes = <&gce 0 CMDQ_THR_PRIO_HIGHEST>, + <&gce 1 CMDQ_THR_PRIO_HIGHEST>; + mediatek,gce-client-reg = <&gce SUBSYS_1400XXXX 0 0x1000>; + }; + + mutex: mutex@14001000 { + compatible = "mediatek,mt8186-disp-mutex"; + reg = <0 0x14001000 0 0x1000>; + clocks = <&mmsys CLK_MM_DISP_MUTEX0>; + interrupts = ; + mediatek,gce-client-reg = <&gce SUBSYS_1401XXXX 0x1000 0x1000>; + mediatek,gce-events = , + ; + power-domains = <&spm MT8186_POWER_DOMAIN_DIS>; }; smi_common: smi@14002000 { @@ -1131,6 +1751,45 @@ power-domains = <&spm MT8186_POWER_DOMAIN_DIS>; }; + ovl0: ovl@14005000 { + compatible = "mediatek,mt8186-disp-ovl", "mediatek,mt8192-disp-ovl"; + reg = <0 0x14005000 0 0x1000>; + clocks = <&mmsys CLK_MM_DISP_OVL0>; + interrupts = ; + iommus = <&iommu_mm IOMMU_PORT_L0_OVL_RDMA0>; + mediatek,gce-client-reg = <&gce SUBSYS_1400XXXX 0x5000 0x1000>; + power-domains = <&spm MT8186_POWER_DOMAIN_DIS>; + }; + + ovl_2l0: ovl@14006000 { + compatible = "mediatek,mt8186-disp-ovl-2l", "mediatek,mt8192-disp-ovl-2l"; + reg = <0 0x14006000 0 0x1000>; + clocks = <&mmsys CLK_MM_DISP_OVL0_2L>; + interrupts = ; + iommus = <&iommu_mm IOMMU_PORT_L1_OVL_2L_RDMA0>; + mediatek,gce-client-reg = <&gce SUBSYS_1400XXXX 0x6000 0x1000>; + power-domains = <&spm MT8186_POWER_DOMAIN_DIS>; + }; + + rdma0: rdma@14007000 { + compatible = "mediatek,mt8186-disp-rdma", "mediatek,mt8183-disp-rdma"; + reg = <0 0x14007000 0 0x1000>; + clocks = <&mmsys CLK_MM_DISP_RDMA0>; + interrupts = ; + iommus = <&iommu_mm IOMMU_PORT_L1_DISP_RDMA0>; + mediatek,gce-client-reg = <&gce SUBSYS_1400XXXX 0x7000 0x1000>; + power-domains = <&spm MT8186_POWER_DOMAIN_DIS>; + }; + + color: color@14009000 { + compatible = "mediatek,mt8186-disp-color", "mediatek,mt8173-disp-color"; + reg = <0 0x14009000 0 0x1000>; + clocks = <&mmsys CLK_MM_DISP_COLOR0>; + interrupts = ; + mediatek,gce-client-reg = <&gce SUBSYS_1400XXXX 0x8000 0x1000>; + power-domains = <&spm MT8186_POWER_DOMAIN_DIS>; + }; + dpi: dpi@1400a000 { compatible = "mediatek,mt8186-dpi"; reg = <0 0x1400a000 0 0x1000>; @@ -1148,6 +1807,52 @@ }; }; + ccorr: ccorr@1400b000 { + compatible = "mediatek,mt8186-disp-ccorr", "mediatek,mt8192-disp-ccorr"; + reg = <0 0x1400b000 0 0x1000>; + clocks = <&mmsys CLK_MM_DISP_CCORR0>; + interrupts = ; + mediatek,gce-client-reg = <&gce SUBSYS_1400XXXX 0xb000 0x1000>; + power-domains = <&spm MT8186_POWER_DOMAIN_DIS>; + }; + + aal: aal@1400c000 { + compatible = "mediatek,mt8186-disp-aal", "mediatek,mt8183-disp-aal"; + reg = <0 0x1400c000 0 0x1000>; + clocks = <&mmsys CLK_MM_DISP_AAL0>; + interrupts = ; + mediatek,gce-client-reg = <&gce SUBSYS_1400XXXX 0xc000 0x1000>; + power-domains = <&spm MT8186_POWER_DOMAIN_DIS>; + }; + + gamma: gamma@1400d000 { + compatible = "mediatek,mt8186-disp-gamma", "mediatek,mt8183-disp-gamma"; + reg = <0 0x1400d000 0 0x1000>; + clocks = <&mmsys CLK_MM_DISP_GAMMA0>; + interrupts = ; + mediatek,gce-client-reg = <&gce SUBSYS_1400XXXX 0xd000 0x1000>; + power-domains = <&spm MT8186_POWER_DOMAIN_DIS>; + }; + + postmask: postmask@1400e000 { + compatible = "mediatek,mt8186-disp-postmask", + "mediatek,mt8192-disp-postmask"; + reg = <0 0x1400e000 0 0x1000>; + clocks = <&mmsys CLK_MM_DISP_POSTMASK0>; + interrupts = ; + mediatek,gce-client-reg = <&gce SUBSYS_1400XXXX 0xe000 0x1000>; + power-domains = <&spm MT8186_POWER_DOMAIN_DIS>; + }; + + dither: dither@1400f000 { + compatible = "mediatek,mt8186-disp-dither", "mediatek,mt8183-disp-dither"; + reg = <0 0x1400f000 0 0x1000>; + clocks = <&mmsys CLK_MM_DISP_DITHER0>; + interrupts = ; + mediatek,gce-client-reg = <&gce SUBSYS_1400XXXX 0xf000 0x1000>; + power-domains = <&spm MT8186_POWER_DOMAIN_DIS>; + }; + dsi0: dsi@14013000 { compatible = "mediatek,mt8186-dsi"; reg = <0 0x14013000 0 0x1000>; @@ -1181,6 +1886,16 @@ #iommu-cells = <1>; }; + rdma1: rdma@1401f000 { + compatible = "mediatek,mt8186-disp-rdma", "mediatek,mt8183-disp-rdma"; + reg = <0 0x1401f000 0 0x1000>; + clocks = <&mmsys CLK_MM_DISP_RDMA1>; + interrupts = ; + iommus = <&iommu_mm IOMMU_PORT_L1_DISP_RDMA1>; + mediatek,gce-client-reg = <&gce SUBSYS_1401XXXX 0xf000 0x1000>; + power-domains = <&spm MT8186_POWER_DOMAIN_DIS>; + }; + wpesys: clock-controller@14020000 { compatible = "mediatek,mt8186-wpesys"; reg = <0 0x14020000 0 0x1000>; diff --git a/arch/arm64/boot/dts/mediatek/mt8192-asurada-hayato-r1.dts b/arch/arm64/boot/dts/mediatek/mt8192-asurada-hayato-r1.dts index 43a823990a927ad6aa3a3ba6a7ffbe4a9af4ed8a..6e23428a3ed23809e808d06d6bc7efec78a50c15 100644 --- a/arch/arm64/boot/dts/mediatek/mt8192-asurada-hayato-r1.dts +++ b/arch/arm64/boot/dts/mediatek/mt8192-asurada-hayato-r1.dts @@ -40,9 +40,90 @@ >; }; +&pio { + bt_pins: bt-pins { + pins-bt-kill { + pinmux = ; + output-low; + }; + + pins-bt-wake { + pinmux = ; + bias-pull-up; + }; + + pins-ap-wake-bt { + pinmux = ; + output-low; + }; + }; + + uart1_pins: uart1-pins { + pins-rx { + pinmux = ; + input-enable; + bias-pull-up; + }; + + pins-tx { + pinmux = ; + }; + + pins-cts { + pinmux = ; + input-enable; + }; + + pins-rts { + pinmux = ; + }; + }; + + uart1_pins_sleep: uart1-sleep-pins { + pins-rx { + pinmux = ; + input-enable; + bias-pull-up; + }; + + pins-tx { + pinmux = ; + }; + + pins-cts { + pinmux = ; + input-enable; + }; + + pins-rts { + pinmux = ; + }; + }; +}; + &touchscreen { compatible = "hid-over-i2c"; post-power-on-delay-ms = <10>; hid-descr-addr = <0x0001>; vdd-supply = <&pp3300_u>; }; + +&uart1 { + status = "okay"; + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&uart1_pins>; + pinctrl-1 = <&uart1_pins_sleep>; + /delete-property/ interrupts; + interrupts-extended = <&gic GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH 0>, + <&pio 94 IRQ_TYPE_EDGE_FALLING>; + + bluetooth { + compatible = "realtek,rtl8822cs-bt"; + pinctrl-names = "default"; + pinctrl-0 = <&bt_pins>; + + enable-gpios = <&pio 144 GPIO_ACTIVE_HIGH>; + device-wake-gpios = <&pio 168 GPIO_ACTIVE_HIGH>; + host-wake-gpios = <&pio 22 GPIO_ACTIVE_LOW>; + }; +}; diff --git a/arch/arm64/boot/dts/mediatek/mt8192-asurada.dtsi b/arch/arm64/boot/dts/mediatek/mt8192-asurada.dtsi index 5a440504d4f9b7470d778ef22807cfe231267705..0e8b341170907d894db292d531f70f8e1eb2c7f0 100644 --- a/arch/arm64/boot/dts/mediatek/mt8192-asurada.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt8192-asurada.dtsi @@ -275,6 +275,10 @@ remote-endpoint = <&anx7625_in>; }; +&gic { + mediatek,broken-save-restore-fw; +}; + &gpu { mali-supply = <&mt6315_7_vbuck1>; status = "okay"; diff --git a/arch/arm64/boot/dts/mediatek/mt8192.dtsi b/arch/arm64/boot/dts/mediatek/mt8192.dtsi index 5c30caf74026565e85bdef3882dadb67330ae9c4..69f4cded5dbbf2112c082378b9018b5e7dbec1d2 100644 --- a/arch/arm64/boot/dts/mediatek/mt8192.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt8192.dtsi @@ -70,7 +70,8 @@ d-cache-line-size = <64>; d-cache-sets = <128>; next-level-cache = <&l2_0>; - capacity-dmips-mhz = <530>; + performance-domains = <&performance 0>; + capacity-dmips-mhz = <427>; }; cpu1: cpu@100 { @@ -87,7 +88,8 @@ d-cache-line-size = <64>; d-cache-sets = <128>; next-level-cache = <&l2_0>; - capacity-dmips-mhz = <530>; + performance-domains = <&performance 0>; + capacity-dmips-mhz = <427>; }; cpu2: cpu@200 { @@ -104,7 +106,8 @@ d-cache-line-size = <64>; d-cache-sets = <128>; next-level-cache = <&l2_0>; - capacity-dmips-mhz = <530>; + performance-domains = <&performance 0>; + capacity-dmips-mhz = <427>; }; cpu3: cpu@300 { @@ -121,7 +124,8 @@ d-cache-line-size = <64>; d-cache-sets = <128>; next-level-cache = <&l2_0>; - capacity-dmips-mhz = <530>; + performance-domains = <&performance 0>; + capacity-dmips-mhz = <427>; }; cpu4: cpu@400 { @@ -138,6 +142,7 @@ d-cache-line-size = <64>; d-cache-sets = <256>; next-level-cache = <&l2_1>; + performance-domains = <&performance 1>; capacity-dmips-mhz = <1024>; }; @@ -155,6 +160,7 @@ d-cache-line-size = <64>; d-cache-sets = <256>; next-level-cache = <&l2_1>; + performance-domains = <&performance 1>; capacity-dmips-mhz = <1024>; }; @@ -172,6 +178,7 @@ d-cache-line-size = <64>; d-cache-sets = <256>; next-level-cache = <&l2_1>; + performance-domains = <&performance 1>; capacity-dmips-mhz = <1024>; }; @@ -189,6 +196,7 @@ d-cache-line-size = <64>; d-cache-sets = <256>; next-level-cache = <&l2_1>; + performance-domains = <&performance 1>; capacity-dmips-mhz = <1024>; }; @@ -228,6 +236,7 @@ cache-line-size = <64>; cache-sets = <512>; next-level-cache = <&l3_0>; + cache-unified; }; l2_1: l2-cache1 { @@ -237,6 +246,7 @@ cache-line-size = <64>; cache-sets = <512>; next-level-cache = <&l3_0>; + cache-unified; }; l3_0: l3-cache { @@ -401,8 +411,15 @@ #address-cells = <2>; #size-cells = <2>; compatible = "simple-bus"; + dma-ranges = <0x0 0x0 0x0 0x0 0x4 0x0>; ranges; + performance: performance-controller@11bc10 { + compatible = "mediatek,cpufreq-hw"; + reg = <0 0x0011bc10 0 0x120>, <0 0x0011bd30 0 0x120>; + #performance-domain-cells = <1>; + }; + gic: interrupt-controller@c000000 { compatible = "arm,gic-v3"; #interrupt-cells = <4>; @@ -1625,6 +1642,65 @@ power-domains = <&spm MT8192_POWER_DOMAIN_ISP2>; }; + vcodec_dec: video-codec@16000000 { + compatible = "mediatek,mt8192-vcodec-dec"; + reg = <0 0x16000000 0 0x1000>; + mediatek,scp = <&scp>; + iommus = <&iommu0 M4U_PORT_L4_VDEC_MC_EXT>; + #address-cells = <2>; + #size-cells = <2>; + ranges = <0 0 0 0x16000000 0 0x26000>; + + video-codec@10000 { + compatible = "mediatek,mtk-vcodec-lat"; + reg = <0x0 0x10000 0 0x800>; + interrupts = ; + iommus = <&iommu0 M4U_PORT_L5_VDEC_LAT0_VLD_EXT>, + <&iommu0 M4U_PORT_L5_VDEC_LAT0_VLD2_EXT>, + <&iommu0 M4U_PORT_L5_VDEC_LAT0_AVC_MV_EXT>, + <&iommu0 M4U_PORT_L5_VDEC_LAT0_PRED_RD_EXT>, + <&iommu0 M4U_PORT_L5_VDEC_LAT0_TILE_EXT>, + <&iommu0 M4U_PORT_L5_VDEC_LAT0_WDMA_EXT>, + <&iommu0 M4U_PORT_L5_VDEC_LAT0_RG_CTRL_DMA_EXT>, + <&iommu0 M4U_PORT_L5_VDEC_UFO_ENC_EXT>; + clocks = <&topckgen CLK_TOP_VDEC_SEL>, + <&vdecsys_soc CLK_VDEC_SOC_VDEC>, + <&vdecsys_soc CLK_VDEC_SOC_LAT>, + <&vdecsys_soc CLK_VDEC_SOC_LARB1>, + <&topckgen CLK_TOP_MAINPLL_D4>; + clock-names = "sel", "soc-vdec", "soc-lat", "vdec", "top"; + assigned-clocks = <&topckgen CLK_TOP_VDEC_SEL>; + assigned-clock-parents = <&topckgen CLK_TOP_MAINPLL_D4>; + power-domains = <&spm MT8192_POWER_DOMAIN_VDEC>; + }; + + video-codec@25000 { + compatible = "mediatek,mtk-vcodec-core"; + reg = <0 0x25000 0 0x1000>; + interrupts = ; + iommus = <&iommu0 M4U_PORT_L4_VDEC_MC_EXT>, + <&iommu0 M4U_PORT_L4_VDEC_UFO_EXT>, + <&iommu0 M4U_PORT_L4_VDEC_PP_EXT>, + <&iommu0 M4U_PORT_L4_VDEC_PRED_RD_EXT>, + <&iommu0 M4U_PORT_L4_VDEC_PRED_WR_EXT>, + <&iommu0 M4U_PORT_L4_VDEC_PPWRAP_EXT>, + <&iommu0 M4U_PORT_L4_VDEC_TILE_EXT>, + <&iommu0 M4U_PORT_L4_VDEC_VLD_EXT>, + <&iommu0 M4U_PORT_L4_VDEC_VLD2_EXT>, + <&iommu0 M4U_PORT_L4_VDEC_AVC_MV_EXT>, + <&iommu0 M4U_PORT_L4_VDEC_RG_CTRL_DMA_EXT>; + clocks = <&topckgen CLK_TOP_VDEC_SEL>, + <&vdecsys CLK_VDEC_VDEC>, + <&vdecsys CLK_VDEC_LAT>, + <&vdecsys CLK_VDEC_LARB1>, + <&topckgen CLK_TOP_MAINPLL_D4>; + clock-names = "sel", "soc-vdec", "soc-lat", "vdec", "top"; + assigned-clocks = <&topckgen CLK_TOP_VDEC_SEL>; + assigned-clock-parents = <&topckgen CLK_TOP_MAINPLL_D4>; + power-domains = <&spm MT8192_POWER_DOMAIN_VDEC2>; + }; + }; + larb5: larb@1600d000 { compatible = "mediatek,mt8192-smi-larb"; reg = <0 0x1600d000 0 0x1000>; diff --git a/arch/arm64/boot/dts/mediatek/mt8195-cherry.dtsi b/arch/arm64/boot/dts/mediatek/mt8195-cherry.dtsi index 8ac80a136c3710b4350e47b9fab96ea6811c54e2..37a3e9de90ff705a2cf8a0e1e25f0c185bcd059e 100644 --- a/arch/arm64/boot/dts/mediatek/mt8195-cherry.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt8195-cherry.dtsi @@ -255,6 +255,10 @@ }; }; +&gic { + mediatek,broken-save-restore-fw; +}; + &gpu { status = "okay"; mali-supply = <&mt6315_7_vbuck1>; @@ -464,6 +468,13 @@ }; }; +&pcie1 { + status = "okay"; + + pinctrl-names = "default"; + pinctrl-0 = <&pcie1_pins_default>; +}; + &pio { mediatek,rsel-resistance-in-si-unit; pinctrl-names = "default"; @@ -852,6 +863,24 @@ }; }; + pcie0_pins_default: pcie0-default-pins { + pins-bus { + pinmux = , + , + ; + bias-pull-up; + }; + }; + + pcie1_pins_default: pcie1-default-pins { + pins-bus { + pinmux = , + , + ; + bias-pull-up; + }; + }; + pio_default: pio-default-pins { pins-wifi-enable { pinmux = ; diff --git a/arch/arm64/boot/dts/mediatek/mt8195.dtsi b/arch/arm64/boot/dts/mediatek/mt8195.dtsi index a44aae4ab95378dd31b5ec8c8acc79f411294ac9..4dbbf8fdab75857d7a9f889c3222900331c81174 100644 --- a/arch/arm64/boot/dts/mediatek/mt8195.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt8195.dtsi @@ -24,6 +24,8 @@ #size-cells = <2>; aliases { + dp-intf0 = &dp_intf0; + dp-intf1 = &dp_intf1; gce0 = &gce0; gce1 = &gce1; ethdr0 = ðdr0; @@ -283,6 +285,7 @@ cache-line-size = <64>; cache-sets = <512>; next-level-cache = <&l3_0>; + cache-unified; }; l2_1: l2-cache1 { @@ -292,6 +295,7 @@ cache-line-size = <64>; cache-sets = <512>; next-level-cache = <&l3_0>; + cache-unified; }; l3_0: l3-cache { @@ -2366,6 +2370,76 @@ power-domains = <&spm MT8195_POWER_DOMAIN_CAM>; }; + video-codec@18000000 { + compatible = "mediatek,mt8195-vcodec-dec"; + mediatek,scp = <&scp>; + iommus = <&iommu_vdo M4U_PORT_L21_VDEC_MC_EXT>; + #address-cells = <2>; + #size-cells = <2>; + reg = <0 0x18000000 0 0x1000>, + <0 0x18004000 0 0x1000>; + ranges = <0 0 0 0x18000000 0 0x26000>; + + video-codec@2000 { + compatible = "mediatek,mtk-vcodec-lat-soc"; + reg = <0 0x2000 0 0x800>; + iommus = <&iommu_vpp M4U_PORT_L23_VDEC_UFO_ENC_EXT>, + <&iommu_vpp M4U_PORT_L23_VDEC_RDMA_EXT>; + clocks = <&topckgen CLK_TOP_VDEC>, + <&vdecsys_soc CLK_VDEC_SOC_VDEC>, + <&vdecsys_soc CLK_VDEC_SOC_LAT>, + <&topckgen CLK_TOP_UNIVPLL_D4>; + clock-names = "sel", "vdec", "lat", "top"; + assigned-clocks = <&topckgen CLK_TOP_VDEC>; + assigned-clock-parents = <&topckgen CLK_TOP_UNIVPLL_D4>; + power-domains = <&spm MT8195_POWER_DOMAIN_VDEC0>; + }; + + video-codec@10000 { + compatible = "mediatek,mtk-vcodec-lat"; + reg = <0 0x10000 0 0x800>; + interrupts = ; + iommus = <&iommu_vdo M4U_PORT_L24_VDEC_LAT0_VLD_EXT>, + <&iommu_vdo M4U_PORT_L24_VDEC_LAT0_VLD2_EXT>, + <&iommu_vdo M4U_PORT_L24_VDEC_LAT0_AVC_MC_EXT>, + <&iommu_vdo M4U_PORT_L24_VDEC_LAT0_PRED_RD_EXT>, + <&iommu_vdo M4U_PORT_L24_VDEC_LAT0_TILE_EXT>, + <&iommu_vdo M4U_PORT_L24_VDEC_LAT0_WDMA_EXT>; + clocks = <&topckgen CLK_TOP_VDEC>, + <&vdecsys_soc CLK_VDEC_SOC_VDEC>, + <&vdecsys_soc CLK_VDEC_SOC_LAT>, + <&topckgen CLK_TOP_UNIVPLL_D4>; + clock-names = "sel", "vdec", "lat", "top"; + assigned-clocks = <&topckgen CLK_TOP_VDEC>; + assigned-clock-parents = <&topckgen CLK_TOP_UNIVPLL_D4>; + power-domains = <&spm MT8195_POWER_DOMAIN_VDEC0>; + }; + + video-codec@25000 { + compatible = "mediatek,mtk-vcodec-core"; + reg = <0 0x25000 0 0x1000>; /* VDEC_CORE_MISC */ + interrupts = ; + iommus = <&iommu_vdo M4U_PORT_L21_VDEC_MC_EXT>, + <&iommu_vdo M4U_PORT_L21_VDEC_UFO_EXT>, + <&iommu_vdo M4U_PORT_L21_VDEC_PP_EXT>, + <&iommu_vdo M4U_PORT_L21_VDEC_PRED_RD_EXT>, + <&iommu_vdo M4U_PORT_L21_VDEC_PRED_WR_EXT>, + <&iommu_vdo M4U_PORT_L21_VDEC_PPWRAP_EXT>, + <&iommu_vdo M4U_PORT_L21_VDEC_TILE_EXT>, + <&iommu_vdo M4U_PORT_L21_VDEC_VLD_EXT>, + <&iommu_vdo M4U_PORT_L21_VDEC_VLD2_EXT>, + <&iommu_vdo M4U_PORT_L21_VDEC_AVC_MV_EXT>; + clocks = <&topckgen CLK_TOP_VDEC>, + <&vdecsys CLK_VDEC_VDEC>, + <&vdecsys CLK_VDEC_LAT>, + <&topckgen CLK_TOP_UNIVPLL_D4>; + clock-names = "sel", "vdec", "lat", "top"; + assigned-clocks = <&topckgen CLK_TOP_VDEC>; + assigned-clock-parents = <&topckgen CLK_TOP_UNIVPLL_D4>; + power-domains = <&spm MT8195_POWER_DOMAIN_VDEC1>; + }; + }; + larb24: larb@1800d000 { compatible = "mediatek,mt8195-smi-larb"; reg = <0 0x1800d000 0 0x1000>; @@ -3262,5 +3336,185 @@ }; }; }; + + vpu0-thermal { + polling-delay = <1000>; + polling-delay-passive = <250>; + thermal-sensors = <&lvts_ap MT8195_AP_VPU0>; + + trips { + vpu0_alert: trip-alert { + temperature = <85000>; + hysteresis = <2000>; + type = "passive"; + }; + + vpu0_crit: trip-crit { + temperature = <100000>; + hysteresis = <2000>; + type = "critical"; + }; + }; + }; + + vpu1-thermal { + polling-delay = <1000>; + polling-delay-passive = <250>; + thermal-sensors = <&lvts_ap MT8195_AP_VPU1>; + + trips { + vpu1_alert: trip-alert { + temperature = <85000>; + hysteresis = <2000>; + type = "passive"; + }; + + vpu1_crit: trip-crit { + temperature = <100000>; + hysteresis = <2000>; + type = "critical"; + }; + }; + }; + + gpu0-thermal { + polling-delay = <1000>; + polling-delay-passive = <250>; + thermal-sensors = <&lvts_ap MT8195_AP_GPU0>; + + trips { + gpu0_alert: trip-alert { + temperature = <85000>; + hysteresis = <2000>; + type = "passive"; + }; + + gpu0_crit: trip-crit { + temperature = <100000>; + hysteresis = <2000>; + type = "critical"; + }; + }; + }; + + gpu1-thermal { + polling-delay = <1000>; + polling-delay-passive = <250>; + thermal-sensors = <&lvts_ap MT8195_AP_GPU1>; + + trips { + gpu1_alert: trip-alert { + temperature = <85000>; + hysteresis = <2000>; + type = "passive"; + }; + + gpu1_crit: trip-crit { + temperature = <100000>; + hysteresis = <2000>; + type = "critical"; + }; + }; + }; + + vdec-thermal { + polling-delay = <1000>; + polling-delay-passive = <250>; + thermal-sensors = <&lvts_ap MT8195_AP_VDEC>; + + trips { + vdec_alert: trip-alert { + temperature = <85000>; + hysteresis = <2000>; + type = "passive"; + }; + + vdec_crit: trip-crit { + temperature = <100000>; + hysteresis = <2000>; + type = "critical"; + }; + }; + }; + + img-thermal { + polling-delay = <1000>; + polling-delay-passive = <250>; + thermal-sensors = <&lvts_ap MT8195_AP_IMG>; + + trips { + img_alert: trip-alert { + temperature = <85000>; + hysteresis = <2000>; + type = "passive"; + }; + + img_crit: trip-crit { + temperature = <100000>; + hysteresis = <2000>; + type = "critical"; + }; + }; + }; + + infra-thermal { + polling-delay = <1000>; + polling-delay-passive = <250>; + thermal-sensors = <&lvts_ap MT8195_AP_INFRA>; + + trips { + infra_alert: trip-alert { + temperature = <85000>; + hysteresis = <2000>; + type = "passive"; + }; + + infra_crit: trip-crit { + temperature = <100000>; + hysteresis = <2000>; + type = "critical"; + }; + }; + }; + + cam0-thermal { + polling-delay = <1000>; + polling-delay-passive = <250>; + thermal-sensors = <&lvts_ap MT8195_AP_CAM0>; + + trips { + cam0_alert: trip-alert { + temperature = <85000>; + hysteresis = <2000>; + type = "passive"; + }; + + cam0_crit: trip-crit { + temperature = <100000>; + hysteresis = <2000>; + type = "critical"; + }; + }; + }; + + cam1-thermal { + polling-delay = <1000>; + polling-delay-passive = <250>; + thermal-sensors = <&lvts_ap MT8195_AP_CAM1>; + + trips { + cam1_alert: trip-alert { + temperature = <85000>; + hysteresis = <2000>; + type = "passive"; + }; + + cam1_crit: trip-crit { + temperature = <100000>; + hysteresis = <2000>; + type = "critical"; + }; + }; + }; }; }; diff --git a/arch/arm64/boot/dts/mediatek/mt8365-evk.dts b/arch/arm64/boot/dts/mediatek/mt8365-evk.dts index ceb48eb1a6e6942888b9d7efb5682c673adb6b2d..50cbaefa1a9936c6ff6c3bb7ccb94e7326d4f7a1 100644 --- a/arch/arm64/boot/dts/mediatek/mt8365-evk.dts +++ b/arch/arm64/boot/dts/mediatek/mt8365-evk.dts @@ -12,6 +12,7 @@ #include #include #include "mt8365.dtsi" +#include "mt6357.dtsi" / { model = "MediaTek MT8365 Open Platform EVK"; @@ -87,6 +88,49 @@ }; }; +&cpu0 { + proc-supply = <&mt6357_vproc_reg>; + sram-supply = <&mt6357_vsram_proc_reg>; +}; + +&cpu1 { + proc-supply = <&mt6357_vproc_reg>; + sram-supply = <&mt6357_vsram_proc_reg>; +}; + +&cpu2 { + proc-supply = <&mt6357_vproc_reg>; + sram-supply = <&mt6357_vsram_proc_reg>; +}; + +&cpu3 { + proc-supply = <&mt6357_vproc_reg>; + sram-supply = <&mt6357_vsram_proc_reg>; +}; + +ðernet { + pinctrl-0 = <ðernet_pins>; + pinctrl-names = "default"; + phy-handle = <ð_phy>; + phy-mode = "rmii"; + /* + * Ethernet and HDMI (DSI0) are sharing pins. + * Only one can be enabled at a time and require the physical switch + * SW2101 to be set on LAN position + * mt6357_vibr_reg and mt6357_vsim2_reg are needed to supply ethernet + */ + status = "disabled"; + + mdio { + #address-cells = <1>; + #size-cells = <0>; + + eth_phy: ethernet-phy@0 { + reg = <0>; + }; + }; +}; + &i2c0 { clock-frequency = <100000>; pinctrl-0 = <&i2c0_pins>; @@ -94,7 +138,74 @@ status = "okay"; }; +&mmc0 { + assigned-clock-parents = <&topckgen CLK_TOP_MSDCPLL>; + assigned-clocks = <&topckgen CLK_TOP_MSDC50_0_SEL>; + bus-width = <8>; + cap-mmc-highspeed; + cap-mmc-hw-reset; + hs400-ds-delay = <0x12012>; + max-frequency = <200000000>; + mmc-hs200-1_8v; + mmc-hs400-1_8v; + no-sd; + no-sdio; + non-removable; + pinctrl-0 = <&mmc0_default_pins>; + pinctrl-1 = <&mmc0_uhs_pins>; + pinctrl-names = "default", "state_uhs"; + vmmc-supply = <&mt6357_vemc_reg>; + vqmmc-supply = <&mt6357_vio18_reg>; + status = "okay"; +}; + +&mmc1 { + bus-width = <4>; + cap-sd-highspeed; + cd-gpios = <&pio 76 GPIO_ACTIVE_LOW>; + max-frequency = <200000000>; + pinctrl-0 = <&mmc1_default_pins>; + pinctrl-1 = <&mmc1_uhs_pins>; + pinctrl-names = "default", "state_uhs"; + sd-uhs-sdr104; + sd-uhs-sdr50; + vmmc-supply = <&mt6357_vmch_reg>; + vqmmc-supply = <&mt6357_vmc_reg>; + status = "okay"; +}; + +&mt6357_pmic { + interrupts-extended = <&pio 145 IRQ_TYPE_LEVEL_HIGH>; + interrupt-controller; + #interrupt-cells = <2>; +}; + &pio { + ethernet_pins: ethernet-pins { + phy_reset_pins { + pinmux = ; + }; + + rmii_pins { + pinmux = , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + ; + }; + }; + gpio_keys: gpio-keys-pins { pins { pinmux = ; @@ -111,6 +222,108 @@ }; }; + mmc0_default_pins: mmc0-default-pins { + clk-pins { + pinmux = ; + bias-pull-down; + }; + + cmd-dat-pins { + pinmux = , + , + , + , + , + , + , + , + ; + input-enable; + bias-pull-up; + }; + + rst-pins { + pinmux = ; + bias-pull-up; + }; + }; + + mmc0_uhs_pins: mmc0-uhs-pins { + clk-pins { + pinmux = ; + drive-strength = ; + bias-pull-down = ; + }; + + cmd-dat-pins { + pinmux = , + , + , + , + , + , + , + , + ; + input-enable; + drive-strength = ; + bias-pull-up = ; + }; + + ds-pins { + pinmux = ; + drive-strength = ; + bias-pull-down = ; + }; + + rst-pins { + pinmux = ; + drive-strength = ; + bias-pull-up; + }; + }; + + mmc1_default_pins: mmc1-default-pins { + cd-pins { + pinmux = ; + bias-pull-up; + }; + + clk-pins { + pinmux = ; + bias-pull-down = ; + }; + + cmd-dat-pins { + pinmux = , + , + , + , + ; + input-enable; + bias-pull-up = ; + }; + }; + + mmc1_uhs_pins: mmc1-uhs-pins { + clk-pins { + pinmux = ; + drive-strength = ; + bias-pull-down = ; + }; + + cmd-dat-pins { + pinmux = , + , + , + , + ; + input-enable; + drive-strength = ; + bias-pull-up = ; + }; + }; + uart0_pins: uart0-pins { pins { pinmux = , @@ -164,6 +377,28 @@ status = "okay"; }; +&ssusb { + dr_mode = "otg"; + maximum-speed = "high-speed"; + pinctrl-0 = <&usb_pins>; + pinctrl-names = "default"; + usb-role-switch; + vusb33-supply = <&mt6357_vusb33_reg>; + status = "okay"; + + connector { + compatible = "gpio-usb-b-connector", "usb-b-connector"; + id-gpios = <&pio 17 GPIO_ACTIVE_HIGH>; + type = "micro"; + vbus-supply = <&usb_otg_vbus>; + }; +}; + +&usb_host { + vusb33-supply = <&mt6357_vusb33_reg>; + status = "okay"; +}; + &uart0 { pinctrl-0 = <&uart0_pins>; pinctrl-names = "default"; diff --git a/arch/arm64/boot/dts/mediatek/mt8365.dtsi b/arch/arm64/boot/dts/mediatek/mt8365.dtsi index 1f6b48359115d4c2a74f495e77b62d8998256c2c..413496c9206954588da59718e121a948b0b2ed8a 100644 --- a/arch/arm64/boot/dts/mediatek/mt8365.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt8365.dtsi @@ -20,6 +20,91 @@ #address-cells = <1>; #size-cells = <0>; + cluster0_opp: opp-table-0 { + compatible = "operating-points-v2"; + opp-shared; + + opp-850000000 { + opp-hz = /bits/ 64 <850000000>; + opp-microvolt = <650000>; + }; + + opp-918000000 { + opp-hz = /bits/ 64 <918000000>; + opp-microvolt = <668750>; + }; + + opp-987000000 { + opp-hz = /bits/ 64 <987000000>; + opp-microvolt = <687500>; + }; + + opp-1056000000 { + opp-hz = /bits/ 64 <1056000000>; + opp-microvolt = <706250>; + }; + + opp-1125000000 { + opp-hz = /bits/ 64 <1125000000>; + opp-microvolt = <725000>; + }; + + opp-1216000000 { + opp-hz = /bits/ 64 <1216000000>; + opp-microvolt = <750000>; + }; + + opp-1308000000 { + opp-hz = /bits/ 64 <1308000000>; + opp-microvolt = <775000>; + }; + + opp-1400000000 { + opp-hz = /bits/ 64 <1400000000>; + opp-microvolt = <800000>; + }; + + opp-1466000000 { + opp-hz = /bits/ 64 <1466000000>; + opp-microvolt = <825000>; + }; + + opp-1533000000 { + opp-hz = /bits/ 64 <1533000000>; + opp-microvolt = <850000>; + }; + + opp-1633000000 { + opp-hz = /bits/ 64 <1633000000>; + opp-microvolt = <887500>; + }; + + opp-1700000000 { + opp-hz = /bits/ 64 <1700000000>; + opp-microvolt = <912500>; + }; + + opp-1767000000 { + opp-hz = /bits/ 64 <1767000000>; + opp-microvolt = <937500>; + }; + + opp-1834000000 { + opp-hz = /bits/ 64 <1834000000>; + opp-microvolt = <962500>; + }; + + opp-1917000000 { + opp-hz = /bits/ 64 <1917000000>; + opp-microvolt = <993750>; + }; + + opp-2001000000 { + opp-hz = /bits/ 64 <2001000000>; + opp-microvolt = <1025000>; + }; + }; + cpu-map { cluster0 { core0 { @@ -43,6 +128,7 @@ reg = <0x0>; #cooling-cells = <2>; enable-method = "psci"; + cpu-idle-states = <&CPU_MCDI &CLUSTER_MCDI &CLUSTER_DPIDLE>; i-cache-size = <0x8000>; i-cache-line-size = <64>; i-cache-sets = <256>; @@ -50,6 +136,10 @@ d-cache-line-size = <64>; d-cache-sets = <256>; next-level-cache = <&l2>; + clocks = <&mcucfg CLK_MCU_BUS_SEL>, + <&apmixedsys CLK_APMIXED_MAINPLL>; + clock-names = "cpu", "intermediate"; + operating-points-v2 = <&cluster0_opp>; }; cpu1: cpu@1 { @@ -58,6 +148,7 @@ reg = <0x1>; #cooling-cells = <2>; enable-method = "psci"; + cpu-idle-states = <&CPU_MCDI &CLUSTER_MCDI &CLUSTER_DPIDLE>; i-cache-size = <0x8000>; i-cache-line-size = <64>; i-cache-sets = <256>; @@ -65,6 +156,10 @@ d-cache-line-size = <64>; d-cache-sets = <256>; next-level-cache = <&l2>; + clocks = <&mcucfg CLK_MCU_BUS_SEL>, + <&apmixedsys CLK_APMIXED_MAINPLL>; + clock-names = "cpu", "intermediate", "armpll"; + operating-points-v2 = <&cluster0_opp>; }; cpu2: cpu@2 { @@ -73,6 +168,7 @@ reg = <0x2>; #cooling-cells = <2>; enable-method = "psci"; + cpu-idle-states = <&CPU_MCDI &CLUSTER_MCDI &CLUSTER_DPIDLE>; i-cache-size = <0x8000>; i-cache-line-size = <64>; i-cache-sets = <256>; @@ -80,6 +176,10 @@ d-cache-line-size = <64>; d-cache-sets = <256>; next-level-cache = <&l2>; + clocks = <&mcucfg CLK_MCU_BUS_SEL>, + <&apmixedsys CLK_APMIXED_MAINPLL>; + clock-names = "cpu", "intermediate", "armpll"; + operating-points-v2 = <&cluster0_opp>; }; cpu3: cpu@3 { @@ -88,6 +188,7 @@ reg = <0x3>; #cooling-cells = <2>; enable-method = "psci"; + cpu-idle-states = <&CPU_MCDI &CLUSTER_MCDI &CLUSTER_DPIDLE>; i-cache-size = <0x8000>; i-cache-line-size = <64>; i-cache-sets = <256>; @@ -95,6 +196,41 @@ d-cache-line-size = <64>; d-cache-sets = <256>; next-level-cache = <&l2>; + clocks = <&mcucfg CLK_MCU_BUS_SEL>, + <&apmixedsys CLK_APMIXED_MAINPLL>; + clock-names = "cpu", "intermediate", "armpll"; + operating-points-v2 = <&cluster0_opp>; + }; + + idle-states { + entry-method = "psci"; + + CPU_MCDI: cpu-mcdi { + compatible = "arm,idle-state"; + local-timer-stop; + arm,psci-suspend-param = <0x00010001>; + entry-latency-us = <300>; + exit-latency-us = <200>; + min-residency-us = <1000>; + }; + + CLUSTER_MCDI: cluster-mcdi { + compatible = "arm,idle-state"; + local-timer-stop; + arm,psci-suspend-param = <0x01010001>; + entry-latency-us = <350>; + exit-latency-us = <250>; + min-residency-us = <1200>; + }; + + CLUSTER_DPIDLE: cluster-dpidle { + compatible = "arm,idle-state"; + local-timer-stop; + arm,psci-suspend-param = <0x01010004>; + entry-latency-us = <300>; + exit-latency-us = <800>; + min-residency-us = <3300>; + }; }; l2: l2-cache { @@ -162,6 +298,12 @@ reg = <0 0x10005000 0 0x1000>; }; + watchdog: watchdog@10007000 { + compatible = "mediatek,mt8365-wdt", "mediatek,mt6589-wdt"; + reg = <0 0x10007000 0 0x100>; + #reset-cells = <1>; + }; + pio: pinctrl@1000b000 { compatible = "mediatek,mt8365-pinctrl"; reg = <0 0x1000b000 0 0x1000>; diff --git a/arch/arm64/boot/dts/microchip/sparx5.dtsi b/arch/arm64/boot/dts/microchip/sparx5.dtsi index 0367a00a269b3a2be52a872fdf3f36606e47b427..4996499cc738f69e2f29c19609fd5582c74d2f8e 100644 --- a/arch/arm64/boot/dts/microchip/sparx5.dtsi +++ b/arch/arm64/boot/dts/microchip/sparx5.dtsi @@ -24,7 +24,7 @@ }; cpus { - #address-cells = <2>; + #address-cells = <1>; #size-cells = <0>; cpu-map { cluster0 { @@ -39,19 +39,21 @@ cpu0: cpu@0 { compatible = "arm,cortex-a53"; device_type = "cpu"; - reg = <0x0 0x0>; + reg = <0x0>; enable-method = "psci"; next-level-cache = <&L2_0>; }; cpu1: cpu@1 { compatible = "arm,cortex-a53"; device_type = "cpu"; - reg = <0x0 0x1>; + reg = <0x1>; enable-method = "psci"; next-level-cache = <&L2_0>; }; L2_0: l2-cache0 { compatible = "cache"; + cache-level = <2>; + cache-unified; }; }; @@ -61,7 +63,7 @@ interrupt-affinity = <&cpu0>, <&cpu1>; }; - psci { + psci: psci { compatible = "arm,psci-0.2"; method = "smc"; }; diff --git a/arch/arm64/boot/dts/microchip/sparx5_pcb134_board.dtsi b/arch/arm64/boot/dts/microchip/sparx5_pcb134_board.dtsi index ed94a80bf05ff799e0419beb0bc43c282f7b9bd4..f3e226de5e5e913025146efcdef60a4c5c2093ef 100644 --- a/arch/arm64/boot/dts/microchip/sparx5_pcb134_board.dtsi +++ b/arch/arm64/boot/dts/microchip/sparx5_pcb134_board.dtsi @@ -325,69 +325,69 @@ }; &gpio { - i2cmux_pins_i: i2cmux-pins-i { + i2cmux_pins_i: i2cmux-pins { pins = "GPIO_16", "GPIO_17", "GPIO_18", "GPIO_19", "GPIO_20", "GPIO_22", "GPIO_36", "GPIO_35", "GPIO_50", "GPIO_51", "GPIO_56", "GPIO_57"; function = "twi_scl_m"; output-low; }; - i2cmux_0: i2cmux-0 { + i2cmux_0: i2cmux-0-pins { pins = "GPIO_16"; function = "twi_scl_m"; output-high; }; - i2cmux_1: i2cmux-1 { + i2cmux_1: i2cmux-1-pins { pins = "GPIO_17"; function = "twi_scl_m"; output-high; }; - i2cmux_2: i2cmux-2 { + i2cmux_2: i2cmux-2-pins { pins = "GPIO_18"; function = "twi_scl_m"; output-high; }; - i2cmux_3: i2cmux-3 { + i2cmux_3: i2cmux-3-pins { pins = "GPIO_19"; function = "twi_scl_m"; output-high; }; - i2cmux_4: i2cmux-4 { + i2cmux_4: i2cmux-4-pins { pins = "GPIO_20"; function = "twi_scl_m"; output-high; }; - i2cmux_5: i2cmux-5 { + i2cmux_5: i2cmux-5-pins { pins = "GPIO_22"; function = "twi_scl_m"; output-high; }; - i2cmux_6: i2cmux-6 { + i2cmux_6: i2cmux-6-pins { pins = "GPIO_36"; function = "twi_scl_m"; output-high; }; - i2cmux_7: i2cmux-7 { + i2cmux_7: i2cmux-7-pins { pins = "GPIO_35"; function = "twi_scl_m"; output-high; }; - i2cmux_8: i2cmux-8 { + i2cmux_8: i2cmux-8-pins { pins = "GPIO_50"; function = "twi_scl_m"; output-high; }; - i2cmux_9: i2cmux-9 { + i2cmux_9: i2cmux-9-pins { pins = "GPIO_51"; function = "twi_scl_m"; output-high; }; - i2cmux_10: i2cmux-10 { + i2cmux_10: i2cmux-10-pins { pins = "GPIO_56"; function = "twi_scl_m"; output-high; }; - i2cmux_11: i2cmux-11 { + i2cmux_11: i2cmux-11-pins { pins = "GPIO_57"; function = "twi_scl_m"; output-high; diff --git a/arch/arm64/boot/dts/microchip/sparx5_pcb135_board.dtsi b/arch/arm64/boot/dts/microchip/sparx5_pcb135_board.dtsi index 0760cf2e48bc5812054c99d322e677db4124c356..82ce007d99592cac131cee3cfb2f5014ff56d3b4 100644 --- a/arch/arm64/boot/dts/microchip/sparx5_pcb135_board.dtsi +++ b/arch/arm64/boot/dts/microchip/sparx5_pcb135_board.dtsi @@ -59,28 +59,28 @@ }; &gpio { - i2cmux_pins_i: i2cmux-pins-i { + i2cmux_pins_i: i2cmux-pins { pins = "GPIO_35", "GPIO_36", "GPIO_50", "GPIO_51"; function = "twi_scl_m"; output-low; }; - i2cmux_s29: i2cmux-0 { + i2cmux_s29: i2cmux-0-pins { pins = "GPIO_35"; function = "twi_scl_m"; output-high; }; - i2cmux_s30: i2cmux-1 { + i2cmux_s30: i2cmux-1-pins { pins = "GPIO_36"; function = "twi_scl_m"; output-high; }; - i2cmux_s31: i2cmux-2 { + i2cmux_s31: i2cmux-2-pins { pins = "GPIO_50"; function = "twi_scl_m"; output-high; }; - i2cmux_s32: i2cmux-3 { + i2cmux_s32: i2cmux-3-pins { pins = "GPIO_51"; function = "twi_scl_m"; output-high; diff --git a/arch/arm64/boot/dts/microchip/sparx5_pcb_common.dtsi b/arch/arm64/boot/dts/microchip/sparx5_pcb_common.dtsi index 9d1a082de3e29f19d34e11fbdcca241ad3b9e960..32bb76b3202a0c66f93868498099add6f843028d 100644 --- a/arch/arm64/boot/dts/microchip/sparx5_pcb_common.dtsi +++ b/arch/arm64/boot/dts/microchip/sparx5_pcb_common.dtsi @@ -6,6 +6,18 @@ /dts-v1/; #include "sparx5.dtsi" +&psci { + status = "disabled"; +}; + +&cpu0 { + enable-method = "spin-table"; +}; + +&cpu1 { + enable-method = "spin-table"; +}; + &uart0 { status = "okay"; }; diff --git a/arch/arm64/boot/dts/nuvoton/Makefile b/arch/arm64/boot/dts/nuvoton/Makefile index a99dab90472aebb44f29134efc1cc948d0cd1d55..3bc9787801a557c76f63b69647416eacaa45e3e0 100644 --- a/arch/arm64/boot/dts/nuvoton/Makefile +++ b/arch/arm64/boot/dts/nuvoton/Makefile @@ -1,2 +1,4 @@ # SPDX-License-Identifier: GPL-2.0 +dtb-$(CONFIG_ARCH_MA35) += ma35d1-iot-512m.dtb +dtb-$(CONFIG_ARCH_MA35) += ma35d1-som-256m.dtb dtb-$(CONFIG_ARCH_NPCM) += nuvoton-npcm845-evb.dtb diff --git a/arch/arm64/boot/dts/nuvoton/ma35d1-iot-512m.dts b/arch/arm64/boot/dts/nuvoton/ma35d1-iot-512m.dts new file mode 100644 index 0000000000000000000000000000000000000000..b89e2be6abaeb045c5a75e52a79d141b30fa6781 --- /dev/null +++ b/arch/arm64/boot/dts/nuvoton/ma35d1-iot-512m.dts @@ -0,0 +1,56 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2023 Nuvoton Technology Corp. + * Author: Shan-Chun Hung + * Jacky huang + */ + +/dts-v1/; +#include "ma35d1.dtsi" + +/ { + model = "Nuvoton MA35D1-IoT"; + compatible = "nuvoton,ma35d1-iot", "nuvoton,ma35d1"; + + aliases { + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + mem: memory@80000000 { + device_type = "memory"; + reg = <0x00000000 0x80000000 0 0x20000000>; /* 512M DRAM */ + }; + + clk_hxt: clock-hxt { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <24000000>; + clock-output-names = "clk_hxt"; + }; +}; + +&uart0 { + status = "okay"; +}; + +&clk { + assigned-clocks = <&clk CAPLL>, + <&clk DDRPLL>, + <&clk APLL>, + <&clk EPLL>, + <&clk VPLL>; + assigned-clock-rates = <800000000>, + <266000000>, + <180000000>, + <500000000>, + <102000000>; + nuvoton,pll-mode = "integer", + "fractional", + "integer", + "integer", + "integer"; +}; diff --git a/arch/arm64/boot/dts/nuvoton/ma35d1-som-256m.dts b/arch/arm64/boot/dts/nuvoton/ma35d1-som-256m.dts new file mode 100644 index 0000000000000000000000000000000000000000..a1ebddecb7f8166bf83ed4a39e1542c8d5232b80 --- /dev/null +++ b/arch/arm64/boot/dts/nuvoton/ma35d1-som-256m.dts @@ -0,0 +1,56 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2023 Nuvoton Technology Corp. + * Author: Shan-Chun Hung + * Jacky huang + */ + +/dts-v1/; +#include "ma35d1.dtsi" + +/ { + model = "Nuvoton MA35D1-SOM"; + compatible = "nuvoton,ma35d1-som", "nuvoton,ma35d1"; + + aliases { + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + mem: memory@80000000 { + device_type = "memory"; + reg = <0x00000000 0x80000000 0 0x10000000>; /* 256M DRAM */ + }; + + clk_hxt: clock-hxt { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <24000000>; + clock-output-names = "clk_hxt"; + }; +}; + +&uart0 { + status = "okay"; +}; + +&clk { + assigned-clocks = <&clk CAPLL>, + <&clk DDRPLL>, + <&clk APLL>, + <&clk EPLL>, + <&clk VPLL>; + assigned-clock-rates = <800000000>, + <266000000>, + <180000000>, + <500000000>, + <102000000>; + nuvoton,pll-mode = "integer", + "fractional", + "integer", + "integer", + "integer"; +}; diff --git a/arch/arm64/boot/dts/nuvoton/ma35d1.dtsi b/arch/arm64/boot/dts/nuvoton/ma35d1.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..781cdae566a012e53af085960d8ade9f9b0bc99f --- /dev/null +++ b/arch/arm64/boot/dts/nuvoton/ma35d1.dtsi @@ -0,0 +1,234 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2023 Nuvoton Technology Corp. + * Author: Shan-Chun Hung + * Jacky huang + */ + +#include +#include +#include +#include +#include + +/ { + compatible = "nuvoton,ma35d1"; + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + cpus { + #address-cells = <2>; + #size-cells = <0>; + + cpu0: cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a35"; + reg = <0x0 0x0>; + enable-method = "psci"; + next-level-cache = <&L2_0>; + }; + + cpu1: cpu@1 { + device_type = "cpu"; + compatible = "arm,cortex-a35"; + reg = <0x0 0x1>; + enable-method = "psci"; + next-level-cache = <&L2_0>; + }; + + L2_0: l2-cache { + compatible = "cache"; + cache-level = <2>; + cache-unified; + cache-size = <0x80000>; + }; + }; + + psci { + compatible = "arm,psci-0.2"; + method = "smc"; + }; + + gic: interrupt-controller@50801000 { + compatible = "arm,gic-400"; + reg = <0x0 0x50801000 0 0x1000>, /* GICD */ + <0x0 0x50802000 0 0x2000>, /* GICC */ + <0x0 0x50804000 0 0x2000>, /* GICH */ + <0x0 0x50806000 0 0x2000>; /* GICV */ + #interrupt-cells = <3>; + interrupt-parent = <&gic>; + interrupt-controller; + interrupts = ; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts = , /* Physical Secure */ + , /* Physical Non-Secure */ + , /* Virtual */ + ; /* Hypervisor */ + interrupt-parent = <&gic>; + }; + + soc { + compatible = "simple-bus"; + #address-cells = <2>; + #size-cells = <2>; + ranges; + + sys: system-management@40460000 { + compatible = "nuvoton,ma35d1-reset"; + reg = <0x0 0x40460000 0x0 0x200>; + #reset-cells = <1>; + }; + + clk: clock-controller@40460200 { + compatible = "nuvoton,ma35d1-clk"; + reg = <0x00000000 0x40460200 0x0 0x100>; + #clock-cells = <1>; + clocks = <&clk_hxt>; + }; + + uart0: serial@40700000 { + compatible = "nuvoton,ma35d1-uart"; + reg = <0x0 0x40700000 0x0 0x100>; + interrupts = ; + clocks = <&clk UART0_GATE>; + status = "disabled"; + }; + + uart1: serial@40710000 { + compatible = "nuvoton,ma35d1-uart"; + reg = <0x0 0x40710000 0x0 0x100>; + interrupts = ; + clocks = <&clk UART1_GATE>; + status = "disabled"; + }; + + uart2: serial@40720000 { + compatible = "nuvoton,ma35d1-uart"; + reg = <0x0 0x40720000 0x0 0x100>; + interrupts = ; + clocks = <&clk UART2_GATE>; + status = "disabled"; + }; + + uart3: serial@40730000 { + compatible = "nuvoton,ma35d1-uart"; + reg = <0x0 0x40730000 0x0 0x100>; + interrupts = ; + clocks = <&clk UART3_GATE>; + status = "disabled"; + }; + + uart4: serial@40740000 { + compatible = "nuvoton,ma35d1-uart"; + reg = <0x0 0x40740000 0x0 0x100>; + interrupts = ; + clocks = <&clk UART4_GATE>; + status = "disabled"; + }; + + uart5: serial@40750000 { + compatible = "nuvoton,ma35d1-uart"; + reg = <0x0 0x40750000 0x0 0x100>; + interrupts = ; + clocks = <&clk UART5_GATE>; + status = "disabled"; + }; + + uart6: serial@40760000 { + compatible = "nuvoton,ma35d1-uart"; + reg = <0x0 0x40760000 0x0 0x100>; + interrupts = ; + clocks = <&clk UART6_GATE>; + status = "disabled"; + }; + + uart7: serial@40770000 { + compatible = "nuvoton,ma35d1-uart"; + reg = <0x0 0x40770000 0x0 0x100>; + interrupts = ; + clocks = <&clk UART7_GATE>; + status = "disabled"; + }; + + uart8: serial@40780000 { + compatible = "nuvoton,ma35d1-uart"; + reg = <0x0 0x40780000 0x0 0x100>; + interrupts = ; + clocks = <&clk UART8_GATE>; + status = "disabled"; + }; + + uart9: serial@40790000 { + compatible = "nuvoton,ma35d1-uart"; + reg = <0x0 0x40790000 0x0 0x100>; + interrupts = ; + clocks = <&clk UART9_GATE>; + status = "disabled"; + }; + + uart10: serial@407a0000 { + compatible = "nuvoton,ma35d1-uart"; + reg = <0x0 0x407a0000 0x0 0x100>; + interrupts = ; + clocks = <&clk UART10_GATE>; + status = "disabled"; + }; + + uart11: serial@407b0000 { + compatible = "nuvoton,ma35d1-uart"; + reg = <0x0 0x407b0000 0x0 0x100>; + interrupts = ; + clocks = <&clk UART11_GATE>; + status = "disabled"; + }; + + uart12: serial@407c0000 { + compatible = "nuvoton,ma35d1-uart"; + reg = <0x0 0x407c0000 0x0 0x100>; + interrupts = ; + clocks = <&clk UART12_GATE>; + status = "disabled"; + }; + + uart13: serial@407d0000 { + compatible = "nuvoton,ma35d1-uart"; + reg = <0x0 0x407d0000 0x0 0x100>; + interrupts = ; + clocks = <&clk UART13_GATE>; + status = "disabled"; + }; + + uart14: serial@407e0000 { + compatible = "nuvoton,ma35d1-uart"; + reg = <0x0 0x407e0000 0x0 0x100>; + interrupts = ; + clocks = <&clk UART14_GATE>; + status = "disabled"; + }; + + uart15: serial@407f0000 { + compatible = "nuvoton,ma35d1-uart"; + reg = <0x0 0x407f0000 0x0 0x100>; + interrupts = ; + clocks = <&clk UART15_GATE>; + status = "disabled"; + }; + + uart16: serial@40880000 { + compatible = "nuvoton,ma35d1-uart"; + reg = <0x0 0x40880000 0x0 0x100>; + interrupts = ; + clocks = <&clk UART16_GATE>; + status = "disabled"; + }; + }; +}; diff --git a/arch/arm64/boot/dts/nvidia/Makefile b/arch/arm64/boot/dts/nvidia/Makefile index 1406d5d40b8f109bab58debd588cd991550c0bd4..c38c809fe577106fd887398fc1af903b2094ca3b 100644 --- a/arch/arm64/boot/dts/nvidia/Makefile +++ b/arch/arm64/boot/dts/nvidia/Makefile @@ -9,7 +9,9 @@ DTC_FLAGS_tegra194-p2972-0000 := -@ DTC_FLAGS_tegra194-p3509-0000+p3668-0000 := -@ DTC_FLAGS_tegra194-p3509-0000+p3668-0001 := -@ DTC_FLAGS_tegra234-p3737-0000+p3701-0000 := -@ +DTC_FLAGS_tegra234-p3740-0002+p3701-0008 := -@ DTC_FLAGS_tegra234-p3768-0000+p3767-0000 := -@ +DTC_FLAGS_tegra234-p3768-0000+p3767-0005 := -@ dtb-$(CONFIG_ARCH_TEGRA_132_SOC) += tegra132-norrin.dtb dtb-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210-p2371-0000.dtb @@ -25,4 +27,6 @@ dtb-$(CONFIG_ARCH_TEGRA_194_SOC) += tegra194-p3509-0000+p3668-0000.dtb dtb-$(CONFIG_ARCH_TEGRA_194_SOC) += tegra194-p3509-0000+p3668-0001.dtb dtb-$(CONFIG_ARCH_TEGRA_234_SOC) += tegra234-sim-vdk.dtb dtb-$(CONFIG_ARCH_TEGRA_234_SOC) += tegra234-p3737-0000+p3701-0000.dtb +dtb-$(CONFIG_ARCH_TEGRA_234_SOC) += tegra234-p3740-0002+p3701-0008.dtb dtb-$(CONFIG_ARCH_TEGRA_234_SOC) += tegra234-p3768-0000+p3767-0000.dtb +dtb-$(CONFIG_ARCH_TEGRA_234_SOC) += tegra234-p3768-0000+p3767-0005.dtb diff --git a/arch/arm64/boot/dts/nvidia/tegra210-smaug.dts b/arch/arm64/boot/dts/nvidia/tegra210-smaug.dts index d7d7c63e62e254ba75a64c375a26bdb39b450b79..5a1ce432c1fbb9e0a726cf54bcebf993b67fae59 100644 --- a/arch/arm64/boot/dts/nvidia/tegra210-smaug.dts +++ b/arch/arm64/boot/dts/nvidia/tegra210-smaug.dts @@ -36,6 +36,11 @@ }; }; + gpu@57000000 { + vdd-supply = <&max77621_gpu>; + status = "okay"; + }; + pinmux: pinmux@700008d4 { pinctrl-names = "boot"; pinctrl-0 = <&state_boot>; @@ -1370,11 +1375,27 @@ maxim,dvs-default-state = <1>; maxim,enable-active-discharge; maxim,enable-bias-control; - maxim,enable-etr; maxim,enable-gpio = <&pmic 5 0>; maxim,externally-enable; }; + max77621_gpu: regulator@1c { + compatible = "maxim,max77621"; + reg = <0x1c>; + interrupt-parent = <&gpio>; + interrupts = ; + regulator-min-microvolt = <840000>; + regulator-max-microvolt = <1150000>; + regulator-name = "PPVAR_GPU"; + regulator-ramp-delay = <12500>; + maxim,dvs-default-state = <1>; + maxim,enable-active-discharge; + maxim,enable-bias-control; + maxim,disable-etr; + maxim,enable-gpio = <&pmic 6 GPIO_ACTIVE_HIGH>; + maxim,externally-enable; + }; + pmic: pmic@3c { compatible = "maxim,max77620"; reg = <0x3c>; diff --git a/arch/arm64/boot/dts/nvidia/tegra210.dtsi b/arch/arm64/boot/dts/nvidia/tegra210.dtsi index 0e463b3cbe01006fe5ae2e5a03aeb46e0793d112..617583ff273664eace4f055c58dff6d53e3ba3af 100644 --- a/arch/arm64/boot/dts/nvidia/tegra210.dtsi +++ b/arch/arm64/boot/dts/nvidia/tegra210.dtsi @@ -2000,6 +2000,7 @@ L2: l2-cache { compatible = "cache"; cache-level = <2>; + cache-unified; }; }; diff --git a/arch/arm64/boot/dts/nvidia/tegra234-p3701-0000.dtsi b/arch/arm64/boot/dts/nvidia/tegra234-p3701-0000.dtsi index 2378da324273cc013dee9ded4bb4645534557784..319b3a9cff2440beda2815cde3896594ee90e50a 100644 --- a/arch/arm64/boot/dts/nvidia/tegra234-p3701-0000.dtsi +++ b/arch/arm64/boot/dts/nvidia/tegra234-p3701-0000.dtsi @@ -126,7 +126,7 @@ regulator-name = "VDD_3V3_PCIE"; regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; - gpio = <&gpio TEGRA234_MAIN_GPIO(Z, 2) GPIO_ACTIVE_HIGH>; + gpio = <&gpio TEGRA234_MAIN_GPIO(H, 4) GPIO_ACTIVE_HIGH>; regulator-boot-on; enable-active-high; }; @@ -139,4 +139,26 @@ gpio = <&gpio TEGRA234_MAIN_GPIO(A, 1) GPIO_ACTIVE_LOW>; regulator-boot-on; }; + + thermal-zones { + tj-thermal { + polling-delay = <1000>; + polling-delay-passive = <1000>; + status = "okay"; + + trips { + tj_trip_active0: active-0 { + temperature = <75000>; + hysteresis = <4000>; + type = "active"; + }; + + tj_trip_active1: active-1 { + temperature = <95000>; + hysteresis = <4000>; + type = "active"; + }; + }; + }; + }; }; diff --git a/arch/arm64/boot/dts/nvidia/tegra234-p3701-0008.dtsi b/arch/arm64/boot/dts/nvidia/tegra234-p3701-0008.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..e468352b8b7f09b39dcbe475b2df115babae6274 --- /dev/null +++ b/arch/arm64/boot/dts/nvidia/tegra234-p3701-0008.dtsi @@ -0,0 +1,111 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include "tegra234.dtsi" + +/ { + compatible = "nvidia,p3701-0008", "nvidia,tegra234"; + + bus@0 { + i2c@3160000 { + status = "okay"; + + eeprom@50 { + compatible = "atmel,24c02"; + reg = <0x50>; + label = "module"; + vcc-supply = <&vdd_1v8_hs>; + address-width = <8>; + pagesize = <8>; + size = <256>; + read-only; + }; + }; + + spi@3270000 { + status = "okay"; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <102000000>; + spi-tx-bus-width = <4>; + spi-rx-bus-width = <4>; + }; + }; + + mmc@3460000 { + status = "okay"; + bus-width = <8>; + non-removable; + }; + + i2c@c240000 { + status = "okay"; + }; + + rtc@c2a0000 { + status = "okay"; + }; + + pmc@c360000 { + nvidia,invert-interrupt; + }; + }; + + bpmp { + i2c { + status = "okay"; + + thermal-sensor@4c { + status = "okay"; + reg = <0x4c>; + vcc-supply = <&vdd_1v8_ao>; + }; + }; + + thermal { + status = "okay"; + }; + }; + + vdd_1v8_ao: regulator-vdd-1v8-ao { + compatible = "regulator-fixed"; + regulator-name = "VDD_1V8_AO"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + }; + + vdd_1v8_hs: regulator-vdd-1v8-hs { + compatible = "regulator-fixed"; + regulator-name = "VDD_1V8_HS"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + }; + + vdd_1v8_ls: regulator-vdd-1v8-ls { + compatible = "regulator-fixed"; + regulator-name = "VDD_1V8_LS"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + }; + + vdd_3v3_ao: regulator-vdd-3v3-ao { + compatible = "regulator-fixed"; + regulator-name = "vdd-AO-3v3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + + vdd_5v0_sys: regulator-vdd-5v0-sys { + compatible = "regulator-fixed"; + regulator-name = "VIN_SYS_5V0"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-always-on; + regulator-boot-on; + }; +}; diff --git a/arch/arm64/boot/dts/nvidia/tegra234-p3737-0000+p3701-0000.dts b/arch/arm64/boot/dts/nvidia/tegra234-p3737-0000+p3701-0000.dts index caa9e952a149c981c6e38104482c7b7fe10d97da..cd13cf2381dded8d6408d3fabd1a08fc87072160 100644 --- a/arch/arm64/boot/dts/nvidia/tegra234-p3737-0000+p3701-0000.dts +++ b/arch/arm64/boot/dts/nvidia/tegra234-p3737-0000+p3701-0000.dts @@ -2096,7 +2096,8 @@ ports { usb2-0 { - mode = "host"; + mode = "otg"; + usb-role-switch; status = "okay"; port { hs_typec_p1: endpoint { @@ -2152,6 +2153,14 @@ }; }; + usb@3550000 { + status = "okay"; + + phys = <&{/bus@0/padctl@3520000/pads/usb2/lanes/usb2-0}>, + <&{/bus@0/padctl@3520000/pads/usb3/lanes/usb3-1}>; + phy-names = "usb2-0", "usb3-0"; + }; + usb@3610000 { status = "okay"; @@ -2238,6 +2247,7 @@ i2c@c240000 { status = "okay"; + typec@8 { compatible = "cypress,cypd4226"; reg = <0x08>; @@ -2245,22 +2255,27 @@ interrupts = ; firmware-name = "nvidia,jetson-agx-xavier"; status = "okay"; + #address-cells = <1>; #size-cells = <0>; + ccg_typec_con0: connector@0 { compatible = "usb-c-connector"; reg = <0>; label = "USB-C"; data-role = "host"; + ports { #address-cells = <1>; #size-cells = <0>; + port@0 { reg = <0>; hs_ucsi_ccg_p0: endpoint { remote-endpoint = <&hs_typec_p0>; }; }; + port@1 { reg = <1>; ss_ucsi_ccg_p0: endpoint { @@ -2269,20 +2284,24 @@ }; }; }; + ccg_typec_con1: connector@1 { compatible = "usb-c-connector"; reg = <1>; label = "USB-C"; data-role = "dual"; + ports { #address-cells = <1>; #size-cells = <0>; + port@0 { reg = <0>; hs_ucsi_ccg_p1: endpoint { remote-endpoint = <&hs_typec_p1>; }; }; + port@1 { reg = <1>; ss_ucsi_ccg_p1: endpoint { @@ -2324,11 +2343,7 @@ }; pwm-fan { - compatible = "pwm-fan"; - pwms = <&pwm3 0 45334>; - - cooling-levels = <0 95 178 255>; - #cooling-cells = <2>; + cooling-levels = <66 215 255>; }; serial { @@ -2336,9 +2351,8 @@ }; sound { - status = "okay"; - compatible = "nvidia,tegra186-audio-graph-card"; + status = "okay"; dais = /* ADMAIF (FE) Ports */ <&admaif0_port>, <&admaif1_port>, <&admaif2_port>, <&admaif3_port>, @@ -2415,4 +2429,20 @@ "CVB-RT DMIC1", "CVB-RT MIC", "CVB-RT DMIC2", "CVB-RT MIC"; }; + + thermal-zones { + tj-thermal { + cooling-maps { + map-active-0 { + cooling-device = <&fan 0 1>; + trip = <&tj_trip_active0>; + }; + + map-active-1 { + cooling-device = <&fan 1 2>; + trip = <&tj_trip_active1>; + }; + }; + }; + }; }; diff --git a/arch/arm64/boot/dts/nvidia/tegra234-p3737-0000.dtsi b/arch/arm64/boot/dts/nvidia/tegra234-p3737-0000.dtsi index 022a5408d8693e34a41588a4af5f717524614809..d94147f22ebf747b78443114c85f1be21bbe8d40 100644 --- a/arch/arm64/boot/dts/nvidia/tegra234-p3737-0000.dtsi +++ b/arch/arm64/boot/dts/nvidia/tegra234-p3737-0000.dtsi @@ -33,6 +33,12 @@ }; }; + fan: pwm-fan { + compatible = "pwm-fan"; + pwms = <&pwm3 0 45334>; + #cooling-cells = <2>; + }; + vdd_1v8_sys: regulator-vdd-1v8-sys { compatible = "regulator-fixed"; regulator-name = "VDD_1V8_SYS"; diff --git a/arch/arm64/boot/dts/nvidia/tegra234-p3740-0002+p3701-0008.dts b/arch/arm64/boot/dts/nvidia/tegra234-p3740-0002+p3701-0008.dts new file mode 100644 index 0000000000000000000000000000000000000000..43d797e5544f5e478b0ecddda930bd02d31bebfa --- /dev/null +++ b/arch/arm64/boot/dts/nvidia/tegra234-p3740-0002+p3701-0008.dts @@ -0,0 +1,154 @@ +// SPDX-License-Identifier: GPL-2.0 +/dts-v1/; + +#include +#include +#include "tegra234-p3701-0008.dtsi" +#include "tegra234-p3740-0002.dtsi" + +/ { + model = "NVIDIA IGX Orin Development Kit"; + compatible = "nvidia,p3740-0002+p3701-0008", "nvidia,p3701-0008", "nvidia,tegra234"; + + aliases { + serial0 = &tcu; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + bus@0 { + host1x@13e00000 { + nvdec@15480000 { + status = "okay"; + }; + }; + + pcie@140e0000 { + status = "okay"; + vddio-pex-ctl-supply = <&vdd_1v8_ls>; + phys = <&p2u_gbe_4>, <&p2u_gbe_5>; + phy-names = "p2u-0", "p2u-1"; + }; + + pcie@14100000 { + status = "okay"; + vddio-pex-ctl-supply = <&vdd_1v8_ao>; + phys = <&p2u_hsio_3>; + phy-names = "p2u-0"; + }; + + pcie@14160000 { + status = "okay"; + vddio-pex-ctl-supply = <&vdd_1v8_ao>; + phys = <&p2u_hsio_7>, <&p2u_hsio_6>, <&p2u_hsio_5>, + <&p2u_hsio_4>; + phy-names = "p2u-0", "p2u-1", "p2u-2", "p2u-3"; + }; + + pcie@141a0000 { + status = "okay"; + vddio-pex-ctl-supply = <&vdd_1v8_ls>; + phys = <&p2u_nvhs_0>, <&p2u_nvhs_1>, <&p2u_nvhs_2>, + <&p2u_nvhs_3>, <&p2u_nvhs_4>, <&p2u_nvhs_5>, + <&p2u_nvhs_6>, <&p2u_nvhs_7>; + phy-names = "p2u-0", "p2u-1", "p2u-2", "p2u-3", "p2u-4", + "p2u-5", "p2u-6", "p2u-7"; + }; + + pcie@141e0000 { + status = "okay"; + vddio-pex-ctl-supply = <&vdd_1v8_ls>; + phys = <&p2u_gbe_0>, <&p2u_gbe_1>; + phy-names = "p2u-0", "p2u-1"; + }; + + aconnect@2900000 { + status = "okay"; + }; + + serial@3100000 { + compatible = "nvidia,tegra194-hsuart"; + status = "okay"; + }; + + i2c@3160000 { + status = "okay"; + }; + + i2c@3180000 { + status = "okay"; + }; + + i2c@3190000 { + status = "okay"; + }; + + i2c@31b0000 { + status = "okay"; + }; + + i2c@31c0000 { + status = "okay"; + + }; + + i2c@31e0000 { + status = "okay"; + }; + + spi@3270000 { + status = "okay"; + }; + + hda@3510000 { + nvidia,model = "NVIDIA IGX HDA"; + status = "okay"; + }; + + fuse@3810000 { + status = "okay"; + }; + + i2c@c240000 { + status = "okay"; + }; + + i2c@c250000 { + status = "okay"; + }; + }; + + gpio-keys { + compatible = "gpio-keys"; + status = "okay"; + + key-force-recovery { + label = "Force Recovery"; + gpios = <&gpio TEGRA234_MAIN_GPIO(G, 0) GPIO_ACTIVE_LOW>; + linux,input-type = ; + linux,code = ; + }; + + key-power { + label = "Power"; + gpios = <&gpio_aon TEGRA234_AON_GPIO(EE, 4) GPIO_ACTIVE_LOW>; + linux,input-type = ; + linux,code = ; + wakeup-event-action = ; + wakeup-source; + }; + + key-suspend { + label = "Suspend"; + gpios = <&gpio TEGRA234_MAIN_GPIO(G, 2) GPIO_ACTIVE_LOW>; + linux,input-type = ; + linux,code = ; + }; + }; + + serial { + status = "okay"; + }; +}; diff --git a/arch/arm64/boot/dts/nvidia/tegra234-p3740-0002.dtsi b/arch/arm64/boot/dts/nvidia/tegra234-p3740-0002.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..c95063b1932186e87cb02aebc0c1e4d2aba59b78 --- /dev/null +++ b/arch/arm64/boot/dts/nvidia/tegra234-p3740-0002.dtsi @@ -0,0 +1,137 @@ +// SPDX-License-Identifier: GPL-2.0 + +/ { + compatible = "nvidia,p3740-0002"; + + bus@0 { + i2c@31c0000 { + /* carrier board ID EEPROM */ + eeprom@55 { + compatible = "atmel,24c02"; + reg = <0x55>; + + label = "system"; + vcc-supply = <&vdd_1v8_ls>; + address-width = <8>; + pagesize = <8>; + size = <256>; + read-only; + }; + }; + + padctl@3520000 { + vclamp-usb-supply = <&vdd_1v8_ao>; + avdd-usb-supply = <&vdd_3v3_ao>; + status = "okay"; + + pads { + usb2 { + lanes { + usb2-0 { + nvidia,function = "xusb"; + status = "okay"; + }; + + usb2-1 { + nvidia,function = "xusb"; + status = "okay"; + }; + + usb2-2 { + nvidia,function = "xusb"; + status = "okay"; + }; + + usb2-3 { + nvidia,function = "xusb"; + status = "okay"; + }; + }; + }; + + usb3 { + lanes { + usb3-0 { + nvidia,function = "xusb"; + status = "okay"; + }; + + usb3-1 { + nvidia,function = "xusb"; + status = "okay"; + }; + + usb3-2 { + nvidia,function = "xusb"; + status = "okay"; + }; + }; + }; + }; + + ports { + usb2-0 { + mode = "otg"; + usb-role-switch; + status = "okay"; + vbus-supply = <&vdd_5v0_sys>; + }; + + usb2-1 { + mode = "host"; + status = "okay"; + vbus-supply = <&vdd_5v0_sys>; + }; + + usb2-2 { + mode = "host"; + status = "okay"; + vbus-supply = <&vdd_5v0_sys>; + }; + + usb2-3 { + mode = "host"; + status = "okay"; + vbus-supply = <&vdd_5v0_sys>; + }; + + usb3-0 { + nvidia,usb2-companion = <2>; + status = "okay"; + }; + + usb3-1 { + nvidia,usb2-companion = <0>; + status = "okay"; + }; + + usb3-2 { + nvidia,usb2-companion = <1>; + status = "okay"; + }; + }; + }; + + usb@3550000 { + status = "okay"; + + phys = <&{/bus@0/padctl@3520000/pads/usb2/lanes/usb2-0}>, + <&{/bus@0/padctl@3520000/pads/usb3/lanes/usb3-1}>; + phy-names = "usb2-0", "usb3-0"; + }; + + usb@3610000 { + status = "okay"; + + phys = <&{/bus@0/padctl@3520000/pads/usb2/lanes/usb2-0}>, + <&{/bus@0/padctl@3520000/pads/usb2/lanes/usb2-1}>, + <&{/bus@0/padctl@3520000/pads/usb2/lanes/usb2-2}>, + <&{/bus@0/padctl@3520000/pads/usb2/lanes/usb2-3}>, + <&{/bus@0/padctl@3520000/pads/usb3/lanes/usb3-0}>, + <&{/bus@0/padctl@3520000/pads/usb3/lanes/usb3-1}>, + <&{/bus@0/padctl@3520000/pads/usb3/lanes/usb3-2}>; + phy-names = "usb2-0", "usb2-1", "usb2-2", "usb2-3", + "usb3-0", "usb3-1", "usb3-2"; + }; + }; +}; diff --git a/arch/arm64/boot/dts/nvidia/tegra234-p3767-0005.dtsi b/arch/arm64/boot/dts/nvidia/tegra234-p3767-0005.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..232fa95ef4ae563317dcd3deeedc60949ffd9b17 --- /dev/null +++ b/arch/arm64/boot/dts/nvidia/tegra234-p3767-0005.dtsi @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include "tegra234-p3767.dtsi" + +/ { + compatible = "nvidia,p3767-0005", "nvidia,tegra234"; + model = "NVIDIA Jetson Orin Nano"; + + bus@0 { + hda@3510000 { + nvidia,model = "NVIDIA Jetson Orin Nano HDA"; + }; + }; +}; diff --git a/arch/arm64/boot/dts/nvidia/tegra234-p3767.dtsi b/arch/arm64/boot/dts/nvidia/tegra234-p3767.dtsi index bd60478fa75e7c9a644c4c5556a8ac48ed436480..a8aa6e7d8fbc51718aa85f071d705aa5a1ffd01c 100644 --- a/arch/arm64/boot/dts/nvidia/tegra234-p3767.dtsi +++ b/arch/arm64/boot/dts/nvidia/tegra234-p3767.dtsi @@ -99,74 +99,24 @@ }; thermal-zones { - /* - * This monitoring is far from optimal, but it's good enough - * at this stage. - */ - cpu-thermal { + tj-thermal { polling-delay = <1000>; polling-delay-passive = <1000>; status = "okay"; trips { - critical { - temperature = <104500>; - hysteresis = <0>; - type = "critical"; - }; - - hot { - temperature = <99000>; - hysteresis = <1000>; - type = "hot"; - }; - - board_trip_passive: passive { - temperature = <95000>; - hysteresis = <2000>; - type = "passive"; - }; - - board_trip_active2: active-2 { - temperature = <80000>; + tj_trip_active0: active-0 { + temperature = <74000>; hysteresis = <4000>; type = "active"; }; - board_trip_active1: active-1 { - temperature = <65000>; - hysteresis = <4000>; - type = "active"; - }; - - board_trip_active0: active-0 { - temperature = <50000>; + tj_trip_active1: active-1 { + temperature = <95000>; hysteresis = <4000>; type = "active"; }; }; - - cooling-maps { - passive { - cooling-device = <&fan 3 3>; - trip = <&board_trip_passive>; - }; - - active2 { - cooling-device = <&fan 2 3>; - trip = <&board_trip_active2>; - }; - - active1 { - cooling-device = <&fan 1 2>; - trip = <&board_trip_active1>; - }; - - active0 { - cooling-device = <&fan 0 1>; - trip = <&board_trip_active0>; - }; - }; }; }; }; diff --git a/arch/arm64/boot/dts/nvidia/tegra234-p3768-0000+p3767-0000.dts b/arch/arm64/boot/dts/nvidia/tegra234-p3768-0000+p3767-0000.dts index 7dfbc38eb3c456ad991f3b20120501ea08417e39..65e4b51b79c1b1dbe81bfce9ea2aba0dcdcc2daf 100644 --- a/arch/arm64/boot/dts/nvidia/tegra234-p3768-0000+p3767-0000.dts +++ b/arch/arm64/boot/dts/nvidia/tegra234-p3768-0000+p3767-0000.dts @@ -112,11 +112,8 @@ }; }; - fan: pwm-fan { - compatible = "pwm-fan"; - pwms = <&pwm3 0 45334>; - cooling-levels = <0 95 178 255>; - #cooling-cells = <2>; + pwm-fan { + cooling-levels = <0 187 255>; }; vdd_3v3_pcie: regulator-vdd-3v3-pcie { @@ -131,4 +128,20 @@ serial { status = "okay"; }; + + thermal-zones { + tj-thermal { + cooling-maps { + map-active-0 { + cooling-device = <&fan 0 1>; + trip = <&tj_trip_active0>; + }; + + map-active-1 { + cooling-device = <&fan 1 2>; + trip = <&tj_trip_active1>; + }; + }; + }; + }; }; diff --git a/arch/arm64/boot/dts/nvidia/tegra234-p3768-0000+p3767-0005.dts b/arch/arm64/boot/dts/nvidia/tegra234-p3768-0000+p3767-0005.dts new file mode 100644 index 0000000000000000000000000000000000000000..9b86aa6f7dbe197d5c531e0a0f0152fe1e63bc67 --- /dev/null +++ b/arch/arm64/boot/dts/nvidia/tegra234-p3768-0000+p3767-0005.dts @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: GPL-2.0 +/dts-v1/; + +#include +#include + +#include "tegra234-p3767-0005.dtsi" +#include "tegra234-p3768-0000.dtsi" + +/ { + compatible = "nvidia,p3768-0000+p3767-0005", "nvidia,p3767-0005", "nvidia,tegra234"; + model = "NVIDIA Jetson Orin Nano Developer Kit"; + + pwm-fan { + cooling-levels = <0 187 255>; + }; + + thermal-zones { + tj-thermal { + cooling-maps { + map-active-0 { + cooling-device = <&fan 0 1>; + trip = <&tj_trip_active0>; + }; + + map-active-1 { + cooling-device = <&fan 1 2>; + trip = <&tj_trip_active1>; + }; + }; + }; + }; +}; diff --git a/arch/arm64/boot/dts/nvidia/tegra234-p3768-0000.dtsi b/arch/arm64/boot/dts/nvidia/tegra234-p3768-0000.dtsi index aee21428e1a52ddd8c44c9fffae16c2eb0b12f89..c7291ba27cfa776a8dbf2d0248aa0eb56f00c018 100644 --- a/arch/arm64/boot/dts/nvidia/tegra234-p3768-0000.dtsi +++ b/arch/arm64/boot/dts/nvidia/tegra234-p3768-0000.dtsi @@ -119,7 +119,7 @@ phys = <&{/bus@0/padctl@3520000/pads/usb2/lanes/usb2-0}>, <&{/bus@0/padctl@3520000/pads/usb3/lanes/usb3-1}>; - phy-names = "usb2-0", "usb3-1"; + phy-names = "usb2-0", "usb3-0"; }; usb@3610000 { @@ -209,7 +209,6 @@ fan: pwm-fan { compatible = "pwm-fan"; pwms = <&pwm3 0 45334>; - cooling-levels = <0 95 178 255>; #cooling-cells = <2>; }; diff --git a/arch/arm64/boot/dts/nvidia/tegra234.dtsi b/arch/arm64/boot/dts/nvidia/tegra234.dtsi index 18b4c2b2c42c80bf38cd840cba81345b09d3f80a..f4974e81dd4b070c1d665e153b6dff733429027f 100644 --- a/arch/arm64/boot/dts/nvidia/tegra234.dtsi +++ b/arch/arm64/boot/dts/nvidia/tegra234.dtsi @@ -8,6 +8,7 @@ #include #include #include +#include / { compatible = "nvidia,tegra234"; @@ -108,6 +109,12 @@ interrupt-controller; #gpio-cells = <2>; gpio-controller; + gpio-ranges = <&pinmux 0 0 164>; + }; + + pinmux: pinmux@2430000 { + compatible = "nvidia,tegra234-pinmux"; + reg = <0x0 0x2430000 0x0 0x19100>; }; gpcdma: dma-controller@2600000 { @@ -1749,6 +1756,12 @@ interrupt-controller; #gpio-cells = <2>; gpio-controller; + gpio-ranges = <&pinmux_aon 0 0 32>; + }; + + pinmux_aon: pinmux@c300000 { + compatible = "nvidia,tegra234-pinmux-aon"; + reg = <0x0 0xc300000 0x0 0x4000>; }; pwm4: pwm@c340000 { @@ -3015,6 +3028,11 @@ #address-cells = <1>; #size-cells = <0>; }; + + bpmp_thermal: thermal { + compatible = "nvidia,tegra186-bpmp-thermal"; + #thermal-sensor-cells = <1>; + }; }; cpus { @@ -3028,6 +3046,9 @@ enable-method = "psci"; + operating-points-v2 = <&cl0_opp_tbl>; + interconnects = <&mc TEGRA_ICC_MC_CPU_CLUSTER0 &emc>; + i-cache-size = <65536>; i-cache-line-size = <64>; i-cache-sets = <256>; @@ -3044,6 +3065,9 @@ enable-method = "psci"; + operating-points-v2 = <&cl0_opp_tbl>; + interconnects = <&mc TEGRA_ICC_MC_CPU_CLUSTER0 &emc>; + i-cache-size = <65536>; i-cache-line-size = <64>; i-cache-sets = <256>; @@ -3060,6 +3084,9 @@ enable-method = "psci"; + operating-points-v2 = <&cl0_opp_tbl>; + interconnects = <&mc TEGRA_ICC_MC_CPU_CLUSTER0 &emc>; + i-cache-size = <65536>; i-cache-line-size = <64>; i-cache-sets = <256>; @@ -3076,6 +3103,9 @@ enable-method = "psci"; + operating-points-v2 = <&cl0_opp_tbl>; + interconnects = <&mc TEGRA_ICC_MC_CPU_CLUSTER0 &emc>; + i-cache-size = <65536>; i-cache-line-size = <64>; i-cache-sets = <256>; @@ -3092,6 +3122,9 @@ enable-method = "psci"; + operating-points-v2 = <&cl1_opp_tbl>; + interconnects = <&mc TEGRA_ICC_MC_CPU_CLUSTER1 &emc>; + i-cache-size = <65536>; i-cache-line-size = <64>; i-cache-sets = <256>; @@ -3108,6 +3141,9 @@ enable-method = "psci"; + operating-points-v2 = <&cl1_opp_tbl>; + interconnects = <&mc TEGRA_ICC_MC_CPU_CLUSTER1 &emc>; + i-cache-size = <65536>; i-cache-line-size = <64>; i-cache-sets = <256>; @@ -3124,6 +3160,9 @@ enable-method = "psci"; + operating-points-v2 = <&cl1_opp_tbl>; + interconnects = <&mc TEGRA_ICC_MC_CPU_CLUSTER1 &emc>; + i-cache-size = <65536>; i-cache-line-size = <64>; i-cache-sets = <256>; @@ -3140,6 +3179,9 @@ enable-method = "psci"; + operating-points-v2 = <&cl1_opp_tbl>; + interconnects = <&mc TEGRA_ICC_MC_CPU_CLUSTER1 &emc>; + i-cache-size = <65536>; i-cache-line-size = <64>; i-cache-sets = <256>; @@ -3156,6 +3198,9 @@ enable-method = "psci"; + operating-points-v2 = <&cl2_opp_tbl>; + interconnects = <&mc TEGRA_ICC_MC_CPU_CLUSTER2 &emc>; + i-cache-size = <65536>; i-cache-line-size = <64>; i-cache-sets = <256>; @@ -3172,6 +3217,9 @@ enable-method = "psci"; + operating-points-v2 = <&cl2_opp_tbl>; + interconnects = <&mc TEGRA_ICC_MC_CPU_CLUSTER2 &emc>; + i-cache-size = <65536>; i-cache-line-size = <64>; i-cache-sets = <256>; @@ -3188,6 +3236,9 @@ enable-method = "psci"; + operating-points-v2 = <&cl2_opp_tbl>; + interconnects = <&mc TEGRA_ICC_MC_CPU_CLUSTER2 &emc>; + i-cache-size = <65536>; i-cache-line-size = <64>; i-cache-sets = <256>; @@ -3204,6 +3255,9 @@ enable-method = "psci"; + operating-points-v2 = <&cl2_opp_tbl>; + interconnects = <&mc TEGRA_ICC_MC_CPU_CLUSTER2 &emc>; + i-cache-size = <65536>; i-cache-line-size = <64>; i-cache-sets = <256>; @@ -3469,6 +3523,53 @@ <&bpmp TEGRA234_CLK_PLLA_OUT0>; }; + thermal-zones { + cpu-thermal { + thermal-sensors = <&{/bpmp/thermal} TEGRA234_BPMP_THERMAL_ZONE_CPU>; + status = "disabled"; + }; + + gpu-thermal { + thermal-sensors = <&{/bpmp/thermal} TEGRA234_BPMP_THERMAL_ZONE_GPU>; + status = "disabled"; + }; + + cv0-thermal { + thermal-sensors = <&{/bpmp/thermal} TEGRA234_BPMP_THERMAL_ZONE_CV0>; + status = "disabled"; + }; + + cv1-thermal { + thermal-sensors = <&{/bpmp/thermal} TEGRA234_BPMP_THERMAL_ZONE_CV1>; + status = "disabled"; + }; + + cv2-thermal { + thermal-sensors = <&{/bpmp/thermal} TEGRA234_BPMP_THERMAL_ZONE_CV2>; + status = "disabled"; + }; + + soc0-thermal { + thermal-sensors = <&{/bpmp/thermal} TEGRA234_BPMP_THERMAL_ZONE_SOC0>; + status = "disabled"; + }; + + soc1-thermal { + thermal-sensors = <&{/bpmp/thermal} TEGRA234_BPMP_THERMAL_ZONE_SOC1>; + status = "disabled"; + }; + + soc2-thermal { + thermal-sensors = <&{/bpmp/thermal} TEGRA234_BPMP_THERMAL_ZONE_SOC2>; + status = "disabled"; + }; + + tj-thermal { + thermal-sensors = <&{/bpmp/thermal} TEGRA234_BPMP_THERMAL_ZONE_TJ_MAX>; + status = "disabled"; + }; + }; + timer { compatible = "arm,armv8-timer"; interrupts = , @@ -3478,4 +3579,244 @@ interrupt-parent = <&gic>; always-on; }; + + cl0_opp_tbl: opp-table-cluster0 { + compatible = "operating-points-v2"; + opp-shared; + + cl0_ch1_opp1: opp-115200000 { + opp-hz = /bits/ 64 <115200000>; + opp-peak-kBps = <816000>; + }; + + cl0_ch1_opp2: opp-268800000 { + opp-hz = /bits/ 64 <268800000>; + opp-peak-kBps = <816000>; + }; + + cl0_ch1_opp3: opp-422400000 { + opp-hz = /bits/ 64 <422400000>; + opp-peak-kBps = <816000>; + }; + + cl0_ch1_opp4: opp-576000000 { + opp-hz = /bits/ 64 <576000000>; + opp-peak-kBps = <816000>; + }; + + cl0_ch1_opp5: opp-729600000 { + opp-hz = /bits/ 64 <729600000>; + opp-peak-kBps = <816000>; + }; + + cl0_ch1_opp6: opp-883200000 { + opp-hz = /bits/ 64 <883200000>; + opp-peak-kBps = <816000>; + }; + + cl0_ch1_opp7: opp-1036800000 { + opp-hz = /bits/ 64 <1036800000>; + opp-peak-kBps = <816000>; + }; + + cl0_ch1_opp8: opp-1190400000 { + opp-hz = /bits/ 64 <1190400000>; + opp-peak-kBps = <816000>; + }; + + cl0_ch1_opp9: opp-1344000000 { + opp-hz = /bits/ 64 <1344000000>; + opp-peak-kBps = <1632000>; + }; + + cl0_ch1_opp10: opp-1497600000 { + opp-hz = /bits/ 64 <1497600000>; + opp-peak-kBps = <1632000>; + }; + + cl0_ch1_opp11: opp-1651200000 { + opp-hz = /bits/ 64 <1651200000>; + opp-peak-kBps = <2660000>; + }; + + cl0_ch1_opp12: opp-1804800000 { + opp-hz = /bits/ 64 <1804800000>; + opp-peak-kBps = <2660000>; + }; + + cl0_ch1_opp13: opp-1958400000 { + opp-hz = /bits/ 64 <1958400000>; + opp-peak-kBps = <3200000>; + }; + + cl0_ch1_opp14: opp-2112000000 { + opp-hz = /bits/ 64 <2112000000>; + opp-peak-kBps = <6400000>; + }; + + cl0_ch1_opp15: opp-2201600000 { + opp-hz = /bits/ 64 <2201600000>; + opp-peak-kBps = <6400000>; + }; + }; + + cl1_opp_tbl: opp-table-cluster1 { + compatible = "operating-points-v2"; + opp-shared; + + cl1_ch1_opp1: opp-115200000 { + opp-hz = /bits/ 64 <115200000>; + opp-peak-kBps = <816000>; + }; + + cl1_ch1_opp2: opp-268800000 { + opp-hz = /bits/ 64 <268800000>; + opp-peak-kBps = <816000>; + }; + + cl1_ch1_opp3: opp-422400000 { + opp-hz = /bits/ 64 <422400000>; + opp-peak-kBps = <816000>; + }; + + cl1_ch1_opp4: opp-576000000 { + opp-hz = /bits/ 64 <576000000>; + opp-peak-kBps = <816000>; + }; + + cl1_ch1_opp5: opp-729600000 { + opp-hz = /bits/ 64 <729600000>; + opp-peak-kBps = <816000>; + }; + + cl1_ch1_opp6: opp-883200000 { + opp-hz = /bits/ 64 <883200000>; + opp-peak-kBps = <816000>; + }; + + cl1_ch1_opp7: opp-1036800000 { + opp-hz = /bits/ 64 <1036800000>; + opp-peak-kBps = <816000>; + }; + + cl1_ch1_opp8: opp-1190400000 { + opp-hz = /bits/ 64 <1190400000>; + opp-peak-kBps = <816000>; + }; + + cl1_ch1_opp9: opp-1344000000 { + opp-hz = /bits/ 64 <1344000000>; + opp-peak-kBps = <1632000>; + }; + + cl1_ch1_opp10: opp-1497600000 { + opp-hz = /bits/ 64 <1497600000>; + opp-peak-kBps = <1632000>; + }; + + cl1_ch1_opp11: opp-1651200000 { + opp-hz = /bits/ 64 <1651200000>; + opp-peak-kBps = <2660000>; + }; + + cl1_ch1_opp12: opp-1804800000 { + opp-hz = /bits/ 64 <1804800000>; + opp-peak-kBps = <2660000>; + }; + + cl1_ch1_opp13: opp-1958400000 { + opp-hz = /bits/ 64 <1958400000>; + opp-peak-kBps = <3200000>; + }; + + cl1_ch1_opp14: opp-2112000000 { + opp-hz = /bits/ 64 <2112000000>; + opp-peak-kBps = <6400000>; + }; + + cl1_ch1_opp15: opp-2201600000 { + opp-hz = /bits/ 64 <2201600000>; + opp-peak-kBps = <6400000>; + }; + }; + + cl2_opp_tbl: opp-table-cluster2 { + compatible = "operating-points-v2"; + opp-shared; + + cl2_ch1_opp1: opp-115200000 { + opp-hz = /bits/ 64 <115200000>; + opp-peak-kBps = <816000>; + }; + + cl2_ch1_opp2: opp-268800000 { + opp-hz = /bits/ 64 <268800000>; + opp-peak-kBps = <816000>; + }; + + cl2_ch1_opp3: opp-422400000 { + opp-hz = /bits/ 64 <422400000>; + opp-peak-kBps = <816000>; + }; + + cl2_ch1_opp4: opp-576000000 { + opp-hz = /bits/ 64 <576000000>; + opp-peak-kBps = <816000>; + }; + + cl2_ch1_opp5: opp-729600000 { + opp-hz = /bits/ 64 <729600000>; + opp-peak-kBps = <816000>; + }; + + cl2_ch1_opp6: opp-883200000 { + opp-hz = /bits/ 64 <883200000>; + opp-peak-kBps = <816000>; + }; + + cl2_ch1_opp7: opp-1036800000 { + opp-hz = /bits/ 64 <1036800000>; + opp-peak-kBps = <816000>; + }; + + cl2_ch1_opp8: opp-1190400000 { + opp-hz = /bits/ 64 <1190400000>; + opp-peak-kBps = <816000>; + }; + + cl2_ch1_opp9: opp-1344000000 { + opp-hz = /bits/ 64 <1344000000>; + opp-peak-kBps = <1632000>; + }; + + cl2_ch1_opp10: opp-1497600000 { + opp-hz = /bits/ 64 <1497600000>; + opp-peak-kBps = <1632000>; + }; + + cl2_ch1_opp11: opp-1651200000 { + opp-hz = /bits/ 64 <1651200000>; + opp-peak-kBps = <2660000>; + }; + + cl2_ch1_opp12: opp-1804800000 { + opp-hz = /bits/ 64 <1804800000>; + opp-peak-kBps = <2660000>; + }; + + cl2_ch1_opp13: opp-1958400000 { + opp-hz = /bits/ 64 <1958400000>; + opp-peak-kBps = <3200000>; + }; + + cl2_ch1_opp14: opp-2112000000 { + opp-hz = /bits/ 64 <2112000000>; + opp-peak-kBps = <6400000>; + }; + + cl2_ch1_opp15: opp-2201600000 { + opp-hz = /bits/ 64 <2201600000>; + opp-peak-kBps = <6400000>; + }; + }; }; diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index d42c59572ace0f7aa528e10d022c6dfd8acda1c8..337abc4ceb17758c6390a88b887b8ba70c2cedff 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -1,15 +1,22 @@ # SPDX-License-Identifier: GPL-2.0 dtb-$(CONFIG_ARCH_QCOM) += apq8016-sbc.dtb +dtb-$(CONFIG_ARCH_QCOM) += apq8039-t2.dtb dtb-$(CONFIG_ARCH_QCOM) += apq8094-sony-xperia-kitakami-karin_windy.dtb dtb-$(CONFIG_ARCH_QCOM) += apq8096-db820c.dtb dtb-$(CONFIG_ARCH_QCOM) += apq8096-ifc6640.dtb -dtb-$(CONFIG_ARCH_QCOM) += ipq5332-mi01.2.dtb +dtb-$(CONFIG_ARCH_QCOM) += ipq5332-rdp441.dtb +dtb-$(CONFIG_ARCH_QCOM) += ipq5332-rdp442.dtb dtb-$(CONFIG_ARCH_QCOM) += ipq5332-rdp468.dtb +dtb-$(CONFIG_ARCH_QCOM) += ipq5332-rdp474.dtb dtb-$(CONFIG_ARCH_QCOM) += ipq6018-cp01-c1.dtb dtb-$(CONFIG_ARCH_QCOM) += ipq8074-hk01.dtb dtb-$(CONFIG_ARCH_QCOM) += ipq8074-hk10-c1.dtb dtb-$(CONFIG_ARCH_QCOM) += ipq8074-hk10-c2.dtb -dtb-$(CONFIG_ARCH_QCOM) += ipq9574-al02-c7.dtb +dtb-$(CONFIG_ARCH_QCOM) += ipq9574-rdp418.dtb +dtb-$(CONFIG_ARCH_QCOM) += ipq9574-rdp433.dtb +dtb-$(CONFIG_ARCH_QCOM) += ipq9574-rdp449.dtb +dtb-$(CONFIG_ARCH_QCOM) += ipq9574-rdp453.dtb +dtb-$(CONFIG_ARCH_QCOM) += ipq9574-rdp454.dtb dtb-$(CONFIG_ARCH_QCOM) += msm8916-acer-a1-724.dtb dtb-$(CONFIG_ARCH_QCOM) += msm8916-alcatel-idol347.dtb dtb-$(CONFIG_ARCH_QCOM) += msm8916-asus-z00l.dtb @@ -32,6 +39,7 @@ dtb-$(CONFIG_ARCH_QCOM) += msm8916-thwc-uf896.dtb dtb-$(CONFIG_ARCH_QCOM) += msm8916-thwc-ufi001c.dtb dtb-$(CONFIG_ARCH_QCOM) += msm8916-wingtech-wt88047.dtb dtb-$(CONFIG_ARCH_QCOM) += msm8916-yiming-uz801v3.dtb +dtb-$(CONFIG_ARCH_QCOM) += msm8939-sony-xperia-kanuti-tulip.dtb dtb-$(CONFIG_ARCH_QCOM) += msm8953-motorola-potter.dtb dtb-$(CONFIG_ARCH_QCOM) += msm8953-xiaomi-daisy.dtb dtb-$(CONFIG_ARCH_QCOM) += msm8953-xiaomi-mido.dtb @@ -82,6 +90,7 @@ dtb-$(CONFIG_ARCH_QCOM) += sa8155p-adp.dtb dtb-$(CONFIG_ARCH_QCOM) += sa8295p-adp.dtb dtb-$(CONFIG_ARCH_QCOM) += sa8540p-ride.dtb dtb-$(CONFIG_ARCH_QCOM) += sa8775p-ride.dtb +dtb-$(CONFIG_ARCH_QCOM) += sc7180-acer-aspire1.dtb dtb-$(CONFIG_ARCH_QCOM) += sc7180-idp.dtb dtb-$(CONFIG_ARCH_QCOM) += sc7180-trogdor-coachz-r1.dtb dtb-$(CONFIG_ARCH_QCOM) += sc7180-trogdor-coachz-r1-lte.dtb @@ -140,6 +149,8 @@ dtb-$(CONFIG_ARCH_QCOM) += sc7280-herobrine-zombie-nvme-lte.dtb dtb-$(CONFIG_ARCH_QCOM) += sc7280-idp.dtb dtb-$(CONFIG_ARCH_QCOM) += sc7280-idp2.dtb dtb-$(CONFIG_ARCH_QCOM) += sc7280-crd-r3.dtb +dtb-$(CONFIG_ARCH_QCOM) += sc8180x-lenovo-flex-5g.dtb +dtb-$(CONFIG_ARCH_QCOM) += sc8180x-primus.dtb dtb-$(CONFIG_ARCH_QCOM) += sc8280xp-crd.dtb dtb-$(CONFIG_ARCH_QCOM) += sc8280xp-lenovo-thinkpad-x13s.dtb dtb-$(CONFIG_ARCH_QCOM) += sda660-inforce-ifc6560.dtb @@ -173,7 +184,9 @@ dtb-$(CONFIG_ARCH_QCOM) += sdm845-xiaomi-polaris.dtb dtb-$(CONFIG_ARCH_QCOM) += sdm845-shift-axolotl.dtb dtb-$(CONFIG_ARCH_QCOM) += sdm850-lenovo-yoga-c630.dtb dtb-$(CONFIG_ARCH_QCOM) += sdm850-samsung-w737.dtb +dtb-$(CONFIG_ARCH_QCOM) += sdx75-idp.dtb dtb-$(CONFIG_ARCH_QCOM) += sm4250-oneplus-billie2.dtb +dtb-$(CONFIG_ARCH_QCOM) += sm6115-fxtec-pro1x.dtb dtb-$(CONFIG_ARCH_QCOM) += sm6115p-lenovo-j606f.dtb dtb-$(CONFIG_ARCH_QCOM) += sm6125-sony-xperia-seine-pdx201.dtb dtb-$(CONFIG_ARCH_QCOM) += sm6125-xiaomi-laurel-sprout.dtb diff --git a/arch/arm64/boot/dts/qcom/apq8016-sbc.dts b/arch/arm64/boot/dts/qcom/apq8016-sbc.dts index 59860a2223b83950cca71e23e58d10cf2d23a904..f3d65a6061949f3c091a7f70961222b309205fba 100644 --- a/arch/arm64/boot/dts/qcom/apq8016-sbc.dts +++ b/arch/arm64/boot/dts/qcom/apq8016-sbc.dts @@ -18,8 +18,10 @@ compatible = "qcom,apq8016-sbc", "qcom,apq8016"; aliases { - serial0 = &blsp1_uart2; - serial1 = &blsp1_uart1; + mmc0 = &sdhc_1; /* eMMC */ + mmc1 = &sdhc_2; /* SD card */ + serial0 = &blsp_uart2; + serial1 = &blsp_uart1; usid0 = &pm8916_0; i2c0 = &blsp_i2c2; i2c1 = &blsp_i2c6; @@ -75,7 +77,7 @@ usb_id: usb-id { compatible = "linux,extcon-usb-gpio"; - id-gpio = <&msmgpio 121 GPIO_ACTIVE_HIGH>; + id-gpio = <&tlmm 121 GPIO_ACTIVE_HIGH>; pinctrl-names = "default"; pinctrl-0 = <&usb_id_default>; }; @@ -101,13 +103,13 @@ button { label = "Volume Up"; linux,code = ; - gpios = <&msmgpio 107 GPIO_ACTIVE_LOW>; + gpios = <&tlmm 107 GPIO_ACTIVE_LOW>; }; }; leds { pinctrl-names = "default"; - pinctrl-0 = <&msmgpio_leds>, + pinctrl-0 = <&tlmm_leds>, <&pm8916_gpios_leds>, <&pm8916_mpps_leds>; @@ -117,7 +119,7 @@ label = "apq8016-sbc:green:user1"; function = LED_FUNCTION_HEARTBEAT; color = ; - gpios = <&msmgpio 21 GPIO_ACTIVE_HIGH>; + gpios = <&tlmm 21 GPIO_ACTIVE_HIGH>; linux,default-trigger = "heartbeat"; default-state = "off"; }; @@ -126,7 +128,7 @@ label = "apq8016-sbc:green:user2"; function = LED_FUNCTION_DISK_ACTIVITY; color = ; - gpios = <&msmgpio 120 GPIO_ACTIVE_HIGH>; + gpios = <&tlmm 120 GPIO_ACTIVE_HIGH>; linux,default-trigger = "mmc0"; default-state = "off"; }; @@ -186,14 +188,14 @@ compatible = "adi,adv7533"; reg = <0x39>; - interrupt-parent = <&msmgpio>; + interrupt-parent = <&tlmm>; interrupts = <31 IRQ_TYPE_EDGE_FALLING>; adi,dsi-lanes = <4>; clocks = <&rpmcc RPM_SMD_BB_CLK2>; clock-names = "cec"; - pd-gpios = <&msmgpio 32 GPIO_ACTIVE_HIGH>; + pd-gpios = <&tlmm 32 GPIO_ACTIVE_HIGH>; avdd-supply = <&pm8916_l6>; v1p2-supply = <&pm8916_l6>; @@ -211,7 +213,7 @@ port@0 { reg = <0>; adv7533_in: endpoint { - remote-endpoint = <&dsi0_out>; + remote-endpoint = <&mdss_dsi0_out>; }; }; @@ -243,12 +245,12 @@ label = "LS-SPI0"; }; -&blsp1_uart1 { +&blsp_uart1 { status = "okay"; label = "LS-UART0"; }; -&blsp1_uart2 { +&blsp_uart2 { status = "okay"; label = "LS-UART1"; }; @@ -276,8 +278,8 @@ compatible = "ovti,ov5640"; reg = <0x3b>; - enable-gpios = <&msmgpio 34 GPIO_ACTIVE_HIGH>; - reset-gpios = <&msmgpio 35 GPIO_ACTIVE_LOW>; + enable-gpios = <&tlmm 34 GPIO_ACTIVE_HIGH>; + reset-gpios = <&tlmm 35 GPIO_ACTIVE_LOW>; pinctrl-names = "default"; pinctrl-0 = <&camera_rear_default>; @@ -301,12 +303,11 @@ }; }; -&dsi0_out { - data-lanes = <0 1 2 3>; - remote-endpoint = <&adv7533_in>; +&lpass { + status = "okay"; }; -&lpass { +&lpass_codec { status = "okay"; }; @@ -314,40 +315,78 @@ status = "okay"; }; +&mdss_dsi0_out { + data-lanes = <0 1 2 3>; + remote-endpoint = <&adv7533_in>; +}; + &mpss { status = "okay"; firmware-name = "qcom/apq8016/mba.mbn", "qcom/apq8016/modem.mbn"; }; +&pm8916_codec { + status = "okay"; + clocks = <&gcc GCC_CODEC_DIGCODEC_CLK>; + clock-names = "mclk"; + qcom,mbhc-vthreshold-low = <75 150 237 450 500>; + qcom,mbhc-vthreshold-high = <75 150 237 450 500>; +}; + &pm8916_resin { status = "okay"; linux,code = ; }; +&pm8916_rpm_regulators { + /* + * The 96Boards specification expects a 1.8V power rail on the low-speed + * expansion connector that is able to provide at least 0.18W / 100 mA. + * L15/L16 are connected in parallel to provide 55 mA each. A minimum load + * must be specified to ensure the regulators are not put in LPM where they + * would only provide 5 mA. + */ + pm8916_l15: l15 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-system-load = <50000>; + regulator-allow-set-load; + regulator-always-on; + }; + pm8916_l16: l16 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-system-load = <50000>; + regulator-allow-set-load; + regulator-always-on; + }; + + pm8916_l17: l17 { + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; +}; + &sdhc_1 { status = "okay"; - - pinctrl-names = "default", "sleep"; - pinctrl-0 = <&sdc1_clk_on &sdc1_cmd_on &sdc1_data_on>; - pinctrl-1 = <&sdc1_clk_off &sdc1_cmd_off &sdc1_data_off>; }; &sdhc_2 { status = "okay"; pinctrl-names = "default", "sleep"; - pinctrl-0 = <&sdc2_clk_on &sdc2_cmd_on &sdc2_data_on &sdc2_cd_on>; - pinctrl-1 = <&sdc2_clk_off &sdc2_cmd_off &sdc2_data_off &sdc2_cd_off>; + pinctrl-0 = <&sdc2_default &sdc2_cd_default>; + pinctrl-1 = <&sdc2_sleep &sdc2_cd_default>; - cd-gpios = <&msmgpio 38 GPIO_ACTIVE_LOW>; + cd-gpios = <&tlmm 38 GPIO_ACTIVE_LOW>; }; &sound { status = "okay"; - pinctrl-0 = <&cdc_pdm_lines_act &ext_sec_tlmm_lines_act &ext_mclk_tlmm_lines_act>; - pinctrl-1 = <&cdc_pdm_lines_sus &ext_sec_tlmm_lines_sus &ext_mclk_tlmm_lines_sus>; + pinctrl-0 = <&cdc_pdm_default &sec_mi2s_default>; + pinctrl-1 = <&cdc_pdm_sleep &sec_mi2s_sleep>; pinctrl-names = "default", "sleep"; model = "DB410c"; audio-routing = @@ -370,7 +409,7 @@ sound-dai = <&lpass MI2S_PRIMARY>; }; codec { - sound-dai = <&lpass_codec 0>, <&wcd_codec 0>; + sound-dai = <&lpass_codec 0>, <&pm8916_codec 0>; }; }; @@ -380,7 +419,7 @@ sound-dai = <&lpass MI2S_TERTIARY>; }; codec { - sound-dai = <&lpass_codec 1>, <&wcd_codec 1>; + sound-dai = <&lpass_codec 1>, <&pm8916_codec 1>; }; }; }; @@ -398,13 +437,6 @@ extcon = <&usb_id>; }; -&wcd_codec { - clocks = <&gcc GCC_CODEC_DIGCODEC_CLK>; - clock-names = "mclk"; - qcom,mbhc-vthreshold-low = <75 150 237 450 500>; - qcom,mbhc-vthreshold-high = <75 150 237 450 500>; -}; - &wcnss { status = "okay"; firmware-name = "qcom/apq8016/wcnss.mbn"; @@ -441,130 +473,19 @@ &stm { status = "okay"; }; &tpiu { status = "okay"; }; -&smd_rpm_regulators { - vdd_l1_l2_l3-supply = <&pm8916_s3>; - vdd_l4_l5_l6-supply = <&pm8916_s4>; - vdd_l7-supply = <&pm8916_s4>; - - s3 { - regulator-min-microvolt = <375000>; - regulator-max-microvolt = <1562000>; - }; - - s4 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - - regulator-always-on; - regulator-boot-on; - }; - - l1 { - regulator-min-microvolt = <375000>; - regulator-max-microvolt = <1525000>; - }; - - l2 { - regulator-min-microvolt = <1200000>; - regulator-max-microvolt = <1200000>; - }; - - l4 { - regulator-min-microvolt = <1750000>; - regulator-max-microvolt = <3337000>; - }; - - l5 { - regulator-min-microvolt = <1750000>; - regulator-max-microvolt = <3337000>; - }; - - l6 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - }; - - l7 { - regulator-min-microvolt = <1750000>; - regulator-max-microvolt = <3337000>; - }; - - l8 { - regulator-min-microvolt = <1750000>; - regulator-max-microvolt = <3337000>; - }; - - l9 { - regulator-min-microvolt = <1750000>; - regulator-max-microvolt = <3337000>; - }; - - l10 { - regulator-min-microvolt = <1750000>; - regulator-max-microvolt = <3337000>; - }; - - l11 { - regulator-min-microvolt = <1750000>; - regulator-max-microvolt = <3337000>; - regulator-allow-set-load; - regulator-system-load = <200000>; - }; - - l12 { - regulator-min-microvolt = <1750000>; - regulator-max-microvolt = <3337000>; - }; - - l13 { - regulator-min-microvolt = <1750000>; - regulator-max-microvolt = <3337000>; - }; - - l14 { - regulator-min-microvolt = <1750000>; - regulator-max-microvolt = <3337000>; - }; - - /** - * 1.8v required on LS expansion - * for mezzanine boards - */ - l15 { - regulator-min-microvolt = <1750000>; - regulator-max-microvolt = <3337000>; - regulator-always-on; - }; - - l16 { - regulator-min-microvolt = <1750000>; - regulator-max-microvolt = <3337000>; - }; - - l17 { - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - }; - - l18 { - regulator-min-microvolt = <1750000>; - regulator-max-microvolt = <3337000>; - }; -}; - /* * 2mA drive strength is not enough when connecting multiple * I2C devices with different pull up resistors. */ -&i2c2_default { +&blsp_i2c2_default { drive-strength = <16>; }; -&i2c4_default { +&blsp_i2c4_default { drive-strength = <16>; }; -&i2c6_default { +&blsp_i2c6_default { drive-strength = <16>; }; @@ -592,7 +513,7 @@ * ones actually used for GPIO. */ -&msmgpio { +&tlmm { gpio-line-names = "[UART0_TX]", /* GPIO_0, LSEC pin 5 */ "[UART0_RX]", /* GPIO_1, LSEC pin 7 */ @@ -717,7 +638,14 @@ "USR_LED_2_CTRL", /* GPIO 120 */ "SB_HS_ID"; - msmgpio_leds: msmgpio-leds-state { + sdc2_cd_default: sdc2-cd-default-state { + pins = "gpio38"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + + tlmm_leds: tlmm-leds-state { pins = "gpio21", "gpio120"; function = "gpio"; diff --git a/arch/arm64/boot/dts/qcom/apq8039-t2.dts b/arch/arm64/boot/dts/qcom/apq8039-t2.dts new file mode 100644 index 0000000000000000000000000000000000000000..40644c242fb7df309dd81d94e3dbde2d895750bc --- /dev/null +++ b/arch/arm64/boot/dts/qcom/apq8039-t2.dts @@ -0,0 +1,395 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2015, The Linux Foundation. All rights reserved. + * Copyright (c) 2020-2023, Linaro Ltd. + * + */ + +/dts-v1/; + +#include "msm8939.dtsi" +#include "msm8939-pm8916.dtsi" +#include +#include +#include +#include + +/ { + model = "Square, Inc. T2 Devkit"; + compatible = "square,apq8039-t2", "qcom,msm8939"; + + qcom,board-id = <0x53 0x54>; + qcom,msm-id = ; + + aliases { + mmc0 = &sdhc_1; + mmc1 = &sdhc_2; + serial0 = &blsp_uart1; + serial1 = &blsp_uart2; + }; + + bl: backlight { + compatible = "gpio-backlight"; + pinctrl-0 = <&pinctrl_backlight>; + pinctrl-names = "default"; + gpios = <&tlmm 98 GPIO_ACTIVE_HIGH>; + }; + + chosen { + stdout-path = "serial1:115200n8"; + }; + + vreg_lcd_avdd_reg: lcd-avdd-regulator { + compatible = "regulator-fixed"; + regulator-name = "lcd_avdd"; + regulator-min-microvolt = <5600000>; + regulator-max-microvolt = <5600000>; + pinctrl-0 = <&pinctrl_lcd_avdd_reg>; + pinctrl-names = "default"; + gpio = <&tlmm 86 GPIO_ACTIVE_HIGH>; + startup-delay-us = <300>; + enable-active-high; + }; + + vreg_lcd_avee_reg: lcd-avee-regulator { + compatible = "regulator-fixed"; + regulator-name = "lcd_avee"; + regulator-min-microvolt = <5600000>; + regulator-max-microvolt = <5600000>; + pinctrl-0 = <&pinctrl_lcd_avee_reg>; + pinctrl-names = "default"; + gpio = <&tlmm 87 GPIO_ACTIVE_HIGH>; + startup-delay-us = <300>; + enable-active-high; + }; + + vreg_lcd_iovcc_reg: lcd-iovcc-regulator { + compatible = "regulator-fixed"; + regulator-name = "lcd_iovcc"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + pinctrl-0 = <&pinctrl_lcd_iovcc_reg>; + pinctrl-names = "default"; + gpio = <&tlmm 9 GPIO_ACTIVE_HIGH>; + startup-delay-us = <300>; + enable-active-high; + }; +}; + +&blsp_i2c1 { + status = "okay"; +}; + +&blsp_i2c2 { + status = "okay"; +}; + +&blsp_i2c3 { + status = "okay"; + + typec_pd: usb-pd@38 { + compatible = "ti,tps6598x"; + reg = <0x38>; + + interrupt-parent = <&tlmm>; + interrupts = <107 IRQ_TYPE_LEVEL_LOW>; + interrupt-names = "irq"; + + pinctrl-names = "default"; + pinctrl-0 = <&typec_irq>; + + typec_con: connector { + compatible = "usb-c-connector"; + label = "USB-C"; + + port { + typec_ep: endpoint { + remote-endpoint = <&otg_ep>; + }; + }; + }; + }; +}; + +&blsp_i2c5 { + status = "okay"; +}; + +&blsp_uart1 { + status = "okay"; +}; + +&blsp_uart1_default { + pins = "gpio0", "gpio1"; +}; + +&blsp_uart1_sleep { + pins = "gpio0", "gpio1"; +}; + +&blsp_uart2 { + status = "okay"; +}; + +&lpass { + status = "okay"; +}; + +&lpass_codec { + status = "okay"; +}; + +&mdss { + status = "okay"; +}; + +&pm8916_codec { + qcom,hphl-jack-type-normally-open; + qcom,mbhc-vthreshold-low = <75 150 237 450 500>; + qcom,mbhc-vthreshold-high = <75 150 237 450 500>; + status = "okay"; +}; + +&pm8916_gpios { + gpio-line-names = + "PM_GPIO1", /* WIFI_GPIO1_PRE */ + "PM_GPIO2", /* WIFI_GPIO2_PRE */ + "PM_GPIO3", + "PM_GPIO4"; +}; + +&sdhc_1 { + status = "okay"; +}; + +&sound { + model = "apq8039-square-sndcard"; + audio-routing = "AMIC2", "MIC BIAS Internal2"; + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&cdc_pdm_default>; + pinctrl-1 = <&cdc_pdm_sleep>; + + internal-codec-playback-dai-link { + link-name = "WCD"; + cpu { + sound-dai = <&lpass MI2S_PRIMARY>; + }; + codec { + sound-dai = <&lpass_codec 0>, <&pm8916_codec 0>; + }; + }; + + internal-codec-capture-dai-link { + link-name = "WCD-Capture"; + cpu { + sound-dai = <&lpass MI2S_TERTIARY>; + }; + codec { + sound-dai = <&lpass_codec 1>, <&pm8916_codec 1>; + }; + }; +}; + +/* + * Line names are taken from the schematic of T2, Ver X03. + * July 14, 2018. Page 4 in particular. + */ +&tlmm { + gpio-line-names = + "APQ_UART1_TX", /* GPIO_0 */ + "APQ_UART1_RX", + "APQ_I2C1_SDA", + "APQ_I2C1_SCL", + "APQ_UART2_TX_1V8", + "APQ_UART2_RX_1V8", + "APQ_I2C2_SDA", + "APQ_I2C2_SCL", + "NC", + "APQ_LCD_IOVCC_EN", + "APQ_I2C3_SDA", /* GPIO_10 */ + "APQ_I2C3_SCL", + "TOUCH_RST_1V8_L", + "NC", + "APQ_I2C4_SDA", + "APQ_I2C4_SCL", + "APQ_ID5", + "USB_DISCONNECT", + "APQ_I2C5_SDA", + "APQ_I2C5_SCL", + "APQ_USBC_SPI_MOSI", /* GPIO_20 */ + "APQ_USBC_SPI_MISO", + "APQ_USBC_SPI_SS_L", + "APQ_USBC_SPI_CLK", + "APQ_LCD_TE0", + "APQ_LCD_RST_L", + "NC", + "NC", + "ACCELEROMETER_INT1", + "APQ_CAM_I2C0_SDA", + "APQ_CAM_I2C0_SCL", /* GPIO_30 */ + "ACCELEROMETER_INT2", + "NC", + "NC", + "NC", + "APQ_K21_RST_1V8_L", + "NC", + "APQ_EDL_1V8", + "TP145", + "BT_SSBI", + "NC", /* GPIO_40 */ + "NC", + "NC", + "NC", + "NC", + "NC", + "NC", + "BT_CTRL", + "BT_DAT", + "PWR_GPIO_IN", + "PWR_GPIO_OUT", /* GPIO_50 */ + "CARD_DET_MLB_L", + "HALL_SENSOR", + "TP63", + "TP64", + "TP65", + "NC", + "NC", + "NC", + "NC", + "NC", /* GPIO_60 */ + "NC", + "APQ_K21_GPIO0_1V8", + "CDC_PDM_CLK", + "CDC_PDM_SYNC", + "CDC_PDM_TX", + "CDC_PDM_RX0", + "CDC_PDM_RX1", + "CDC_PDM_RX2", + "APQ_K21_GPIO1_1V8", + "NC", /* GPIO_70 */ + "APQ_HUB_SEL_1V8", + "APQ_K21_GPIO2_1V8", + "APQ_K21_GPIO3_1V8", + "APQ_ID0", + "APQ_ID1", + "APQ_ID2", + "APQ_ID3", + "APQ_ID4", + "APQ_HUB_SUSP_IND", + "BOOT_CONFIG_0", /* GPIO_80 */ + "BOOT_CONFIG_1", + "BOOT_CONFIG_2", + "BOOT_CONFIG_3", + "NC", + "NC", + "APQ_LCD_AVDD_EN", + "APQ_LCD_AVEE_EN", + "TP70", + "NC", + "APQ_DEBUG0", /* GPIO_90 */ + "APQ_DEBUG1", + "APQ_DEBUG2", + "APQ_DEBUG3", + "TP165", + "NC", + "APQ_LNA_PWR_EN", + "NC", + "APQ_LCD_BL_EN", + "NC", + "APQ_LCD_ID0", /* GPIO_100 */ + "APQ_LCD_ID1", + "USBC_GPIO5_1V8", + "NC", + "NC", + "NC", + "APQ_HUB_RST_1V8_L", + "USBC_I2C_IRQ_1V8_L", + "SPE_PWR_EN", + "NC", + "APQ_USB_ID", /* GPIO_110 */ + "APQ_EXT_BUCK_VSEL", + "APQ_USB_ID_OUT", + "NC", + "PRNT_RST_L", + "APQ_CRQ_I2C_RDY_1V8", + "TYPEC_RST_1V8_H", + "CHG_BACKPWR_EN", + "CHG_PROCHOT_L", + "NC", + "USBC_GPIO7_1V8", /* GPIO_120 */ + "NC"; + + pinctrl_backlight: backlight-state { + pins = "gpio98"; + function = "gpio"; + }; + + pinctrl_lcd_avdd_reg: lcd-avdd-reg-state { + pins = "gpio86"; + function = "gpio"; + }; + + pinctrl_lcd_avee_reg: lcd-avee-reg-state { + pins = "gpio87"; + function = "gpio"; + }; + + pinctrl_lcd_iovcc_reg: lcd-iovcc-reg-state { + pins = "gpio9"; + function = "gpio"; + }; + + pinctrl_lcd_rst: lcd-rst-state { + pins = "gpio25"; + function = "gpio"; + }; + + pinctrl_otg_default: otg-default-state { + function = "gpio"; + pins = "gpio17"; + output-high; + }; + + pinctrl_otg_device: otg-device-state { + function = "gpio"; + pins = "gpio17"; + output-low; + }; + + pinctrl_otg_host: otg-host-state { + function = "gpio"; + pins = "gpio17"; + output-low; + }; + + typec_irq: typec-irq-state { + function = "gpio"; + pins = "gpio107"; + bias-pull-up; + input-enable; + }; +}; + +&usb { + pinctrl-names = "default", "host", "device"; + pinctrl-0 = <&pinctrl_otg_default>; + pinctrl-1 = <&pinctrl_otg_host>; + pinctrl-2 = <&pinctrl_otg_device>; + pin-switch-delay-us = <100000>; + usb-role-switch; + status = "okay"; + + port { + otg_ep: endpoint { + remote-endpoint = <&typec_ep>; + }; + }; +}; + +&wcnss { + status = "okay"; +}; + +&wcnss_iris { + compatible = "qcom,wcn3680"; +}; diff --git a/arch/arm64/boot/dts/qcom/apq8096-db820c.dts b/arch/arm64/boot/dts/qcom/apq8096-db820c.dts index b599909c446392665f8a39a61b53828f40d42783..537547b97459bdcd8785ba46a3129831cbb78334 100644 --- a/arch/arm64/boot/dts/qcom/apq8096-db820c.dts +++ b/arch/arm64/boot/dts/qcom/apq8096-db820c.dts @@ -208,25 +208,6 @@ status = "okay"; }; -&hdmi { - status = "okay"; - - pinctrl-names = "default", "sleep"; - pinctrl-0 = <&hdmi_hpd_active &hdmi_ddc_active>; - pinctrl-1 = <&hdmi_hpd_suspend &hdmi_ddc_suspend>; - - core-vdda-supply = <&vreg_l12a_1p8>; - core-vcc-supply = <&vreg_s4a_1p8>; -}; - -&hdmi_phy { - status = "okay"; - - vddio-supply = <&vreg_l12a_1p8>; - vcca-supply = <&vreg_l28a_0p925>; - #phy-cells = <0>; -}; - &hsusb_phy1 { status = "okay"; @@ -251,6 +232,25 @@ status = "okay"; }; +&mdss_hdmi { + status = "okay"; + + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&mdss_hdmi_hpd_active &mdss_hdmi_ddc_active>; + pinctrl-1 = <&mdss_hdmi_hpd_suspend &mdss_hdmi_ddc_suspend>; + + core-vdda-supply = <&vreg_l12a_1p8>; + core-vcc-supply = <&vreg_s4a_1p8>; +}; + +&mdss_hdmi_phy { + status = "okay"; + + vddio-supply = <&vreg_l12a_1p8>; + vcca-supply = <&vreg_l28a_0p925>; + #phy-cells = <0>; +}; + &mmcc { vdd-gfx-supply = <&vdd_gfx>; }; @@ -433,28 +433,28 @@ drive-strength = <2>; }; - hdmi_hpd_active: hdmi-hpd-active-state { + mdss_hdmi_hpd_active: mdss_hdmi-hpd-active-state { pins = "gpio34"; function = "hdmi_hot"; bias-pull-down; drive-strength = <16>; }; - hdmi_hpd_suspend: hdmi-hpd-suspend-state { + mdss_hdmi_hpd_suspend: mdss_hdmi-hpd-suspend-state { pins = "gpio34"; function = "hdmi_hot"; bias-pull-down; drive-strength = <2>; }; - hdmi_ddc_active: hdmi-ddc-active-state { + mdss_hdmi_ddc_active: mdss_hdmi-ddc-active-state { pins = "gpio32", "gpio33"; function = "hdmi_ddc"; drive-strength = <2>; bias-pull-up; }; - hdmi_ddc_suspend: hdmi-ddc-suspend-state { + mdss_hdmi_ddc_suspend: mdss_hdmi-ddc-suspend-state { pins = "gpio32", "gpio33"; function = "hdmi_ddc"; drive-strength = <2>; @@ -1043,7 +1043,7 @@ }; }; - hdmi-dai-link { + mdss_hdmi-dai-link { link-name = "HDMI"; cpu { sound-dai = <&q6afedai HDMI_RX>; @@ -1054,7 +1054,7 @@ }; codec { - sound-dai = <&hdmi 0>; + sound-dai = <&mdss_hdmi 0>; }; }; diff --git a/arch/arm64/boot/dts/qcom/apq8096-ifc6640.dts b/arch/arm64/boot/dts/qcom/apq8096-ifc6640.dts index 71e0a500599c88a8045651433b1e5c48e84e8528..ac6471d1db1f73cc5d5ae83e6f640e8d04ef54d9 100644 --- a/arch/arm64/boot/dts/qcom/apq8096-ifc6640.dts +++ b/arch/arm64/boot/dts/qcom/apq8096-ifc6640.dts @@ -26,7 +26,7 @@ v1p05: v1p05-regulator { compatible = "regulator-fixed"; - reglator-name = "v1p05"; + regulator-name = "v1p05"; regulator-always-on; regulator-boot-on; @@ -38,7 +38,7 @@ v12_poe: v12-poe-regulator { compatible = "regulator-fixed"; - reglator-name = "v12_poe"; + regulator-name = "v12_poe"; regulator-always-on; regulator-boot-on; @@ -92,15 +92,15 @@ status = "okay"; }; -&hdmi { +&mdss { status = "okay"; }; -&hdmi_phy { +&mdss_hdmi { status = "okay"; }; -&mdss { +&mdss_hdmi_phy { status = "okay"; }; diff --git a/arch/arm64/boot/dts/qcom/ipq5332-mi01.2.dts b/arch/arm64/boot/dts/qcom/ipq5332-rdp441.dts similarity index 100% rename from arch/arm64/boot/dts/qcom/ipq5332-mi01.2.dts rename to arch/arm64/boot/dts/qcom/ipq5332-rdp441.dts diff --git a/arch/arm64/boot/dts/qcom/ipq5332-rdp442.dts b/arch/arm64/boot/dts/qcom/ipq5332-rdp442.dts new file mode 100644 index 0000000000000000000000000000000000000000..bcf3b31c20e35e4be36bf956fe00ca51875a91f0 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/ipq5332-rdp442.dts @@ -0,0 +1,117 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * IPQ5332 RDP442 board device tree source + * + * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +/dts-v1/; + +#include "ipq5332.dtsi" + +/ { + model = "Qualcomm Technologies, Inc. IPQ5332 MI01.3"; + compatible = "qcom,ipq5332-ap-mi01.3", "qcom,ipq5332"; + + aliases { + serial0 = &blsp1_uart0; + }; + + chosen { + stdout-path = "serial0"; + }; +}; + +&blsp1_uart0 { + pinctrl-0 = <&serial_0_pins>; + pinctrl-names = "default"; + status = "okay"; +}; + +&blsp1_i2c1 { + clock-frequency = <400000>; + pinctrl-0 = <&i2c_1_pins>; + pinctrl-names = "default"; + status = "okay"; +}; + +&blsp1_spi0 { + pinctrl-0 = <&spi_0_data_clk_pins &spi_0_cs_pins>; + pinctrl-names = "default"; + status = "okay"; + + flash@0 { + compatible = "micron,n25q128a11", "jedec,spi-nor"; + reg = <0>; + #address-cells = <1>; + #size-cells = <1>; + spi-max-frequency = <50000000>; + }; +}; + +&sdhc { + bus-width = <4>; + max-frequency = <192000000>; + mmc-ddr-1_8v; + mmc-hs200-1_8v; + non-removable; + pinctrl-0 = <&sdc_default_state>; + pinctrl-names = "default"; + status = "okay"; +}; + +&sleep_clk { + clock-frequency = <32000>; +}; + +&xo_board { + clock-frequency = <24000000>; +}; + +/* PINCTRL */ + +&tlmm { + i2c_1_pins: i2c-1-state { + pins = "gpio29", "gpio30"; + function = "blsp1_i2c0"; + drive-strength = <8>; + bias-pull-up; + }; + + sdc_default_state: sdc-default-state { + clk-pins { + pins = "gpio13"; + function = "sdc_clk"; + drive-strength = <8>; + bias-disable; + }; + + cmd-pins { + pins = "gpio12"; + function = "sdc_cmd"; + drive-strength = <8>; + bias-pull-up; + }; + + data-pins { + pins = "gpio8", "gpio9", "gpio10", "gpio11"; + function = "sdc_data"; + drive-strength = <8>; + bias-pull-up; + }; + }; + + spi_0_data_clk_pins: spi-0-data-clk-state { + pins = "gpio14", "gpio15", "gpio16"; + function = "blsp0_spi"; + drive-strength = <2>; + bias-pull-down; + }; + + spi_0_cs_pins: spi-0-cs-state { + pins = "gpio17"; + function = "blsp0_spi"; + drive-strength = <2>; + bias-pull-up; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/ipq5332-rdp474.dts b/arch/arm64/boot/dts/qcom/ipq5332-rdp474.dts new file mode 100644 index 0000000000000000000000000000000000000000..53c68d8c5e5d295af34b0d19edd3bcbc42f79960 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/ipq5332-rdp474.dts @@ -0,0 +1,112 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * IPQ5332 RDP474 board device tree source + * + * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +/dts-v1/; + +#include +#include +#include "ipq5332.dtsi" + +/ { + model = "Qualcomm Technologies, Inc. IPQ5332 MI01.9"; + compatible = "qcom,ipq5332-ap-mi01.9", "qcom,ipq5332"; + + aliases { + serial0 = &blsp1_uart0; + }; + + chosen { + stdout-path = "serial0"; + }; + + gpio-keys { + compatible = "gpio-keys"; + pinctrl-0 = <&gpio_keys_default_state>; + pinctrl-names = "default"; + + button-wps { + label = "wps"; + linux,code = ; + gpios = <&tlmm 35 GPIO_ACTIVE_LOW>; + linux,input-type = <1>; + debounce-interval = <60>; + }; + }; +}; + +&blsp1_uart0 { + pinctrl-0 = <&serial_0_pins>; + pinctrl-names = "default"; + status = "okay"; +}; + +&blsp1_i2c1 { + clock-frequency = <400000>; + pinctrl-0 = <&i2c_1_pins>; + pinctrl-names = "default"; + status = "okay"; +}; + +&sdhc { + bus-width = <4>; + max-frequency = <192000000>; + mmc-ddr-1_8v; + mmc-hs200-1_8v; + non-removable; + pinctrl-0 = <&sdc_default_state>; + pinctrl-names = "default"; + status = "okay"; +}; + +&sleep_clk { + clock-frequency = <32000>; +}; + +&xo_board { + clock-frequency = <24000000>; +}; + +/* PINCTRL */ + +&tlmm { + gpio_keys_default_state: gpio-keys-default-state { + pins = "gpio35"; + function = "gpio"; + drive-strength = <8>; + bias-pull-up; + }; + + i2c_1_pins: i2c-1-state { + pins = "gpio29", "gpio30"; + function = "blsp1_i2c0"; + drive-strength = <8>; + bias-pull-up; + }; + + sdc_default_state: sdc-default-state { + clk-pins { + pins = "gpio13"; + function = "sdc_clk"; + drive-strength = <8>; + bias-disable; + }; + + cmd-pins { + pins = "gpio12"; + function = "sdc_cmd"; + drive-strength = <8>; + bias-pull-up; + }; + + data-pins { + pins = "gpio8", "gpio9", "gpio10", "gpio11"; + function = "sdc_data"; + drive-strength = <8>; + bias-pull-up; + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/ipq5332.dtsi b/arch/arm64/boot/dts/qcom/ipq5332.dtsi index af4d97143bcf53e45f8d67b836d15cbf8e8f8d10..8bfc2db44624af8d5780814b2bde23bfc518ce4d 100644 --- a/arch/arm64/boot/dts/qcom/ipq5332.dtsi +++ b/arch/arm64/boot/dts/qcom/ipq5332.dtsi @@ -115,6 +115,16 @@ #size-cells = <2>; ranges; + bootloader@4a100000 { + reg = <0x0 0x4a100000 0x0 0x400000>; + no-map; + }; + + sbl@4a500000 { + reg = <0x0 0x4a500000 0x0 0x100000>; + no-map; + }; + tz_mem: tz@4a600000 { reg = <0x0 0x4a600000 0x0 0x200000>; no-map; @@ -122,7 +132,7 @@ smem@4a800000 { compatible = "qcom,smem"; - reg = <0x0 0x4a800000 0x0 0x00100000>; + reg = <0x0 0x4a800000 0x0 0x100000>; no-map; hwlocks = <&tcsr_mutex 0>; @@ -135,6 +145,13 @@ #size-cells = <1>; ranges = <0 0 0 0xffffffff>; + qfprom: efuse@a4000 { + compatible = "qcom,ipq5332-qfprom", "qcom,qfprom"; + reg = <0x000a4000 0x721>; + #address-cells = <1>; + #size-cells = <1>; + }; + rng: rng@e3000 { compatible = "qcom,prng-ee"; reg = <0x000e3000 0x1000>; @@ -219,6 +236,18 @@ status = "disabled"; }; + blsp1_uart1: serial@78b0000 { + compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm"; + reg = <0x078b0000 0x200>; + interrupts = ; + clocks = <&gcc GCC_BLSP1_UART2_APPS_CLK>, + <&gcc GCC_BLSP1_AHB_CLK>; + clock-names = "core", "iface"; + dmas = <&blsp_dma 2>, <&blsp_dma 3>; + dma-names = "tx", "rx"; + status = "disabled"; + }; + blsp1_spi0: spi@78b5000 { compatible = "qcom,spi-qup-v2.2.1"; reg = <0x078b5000 0x600>; diff --git a/arch/arm64/boot/dts/qcom/ipq6018.dtsi b/arch/arm64/boot/dts/qcom/ipq6018.dtsi index f531797f26195f027205594083690eb7afb8c104..7355f266742aa1d5b0d168f02c3215e9deb4e48c 100644 --- a/arch/arm64/boot/dts/qcom/ipq6018.dtsi +++ b/arch/arm64/boot/dts/qcom/ipq6018.dtsi @@ -91,6 +91,7 @@ firmware { scm { compatible = "qcom,scm-ipq6018", "qcom,scm"; + qcom,dload-mode = <&tcsr 0x6100>; }; }; @@ -155,18 +156,28 @@ no-map; }; + bootloader@4a100000 { + reg = <0x0 0x4a100000 0x0 0x400000>; + no-map; + }; + + sbl@4a500000 { + reg = <0x0 0x4a500000 0x0 0x100000>; + no-map; + }; + tz: memory@4a600000 { - reg = <0x0 0x4a600000 0x0 0x00400000>; + reg = <0x0 0x4a600000 0x0 0x400000>; no-map; }; smem_region: memory@4aa00000 { - reg = <0x0 0x4aa00000 0x0 0x00100000>; + reg = <0x0 0x4aa00000 0x0 0x100000>; no-map; }; q6_region: memory@4ab00000 { - reg = <0x0 0x4ab00000 0x0 0x05500000>; + reg = <0x0 0x4ab00000 0x0 0x5500000>; no-map; }; }; @@ -199,7 +210,7 @@ hwlocks = <&tcsr_mutex 0>; }; - soc: soc { + soc: soc@0 { #address-cells = <2>; #size-cells = <2>; ranges = <0 0 0 0 0x0 0xffffffff>; @@ -302,7 +313,14 @@ status = "disabled"; }; - prng: qrng@e1000 { + qfprom: efuse@a4000 { + compatible = "qcom,ipq6018-qfprom", "qcom,qfprom"; + reg = <0x0 0x000a4000 0x0 0x2000>; + #address-cells = <1>; + #size-cells = <1>; + }; + + prng: qrng@e3000 { compatible = "qcom,prng-ee"; reg = <0x0 0x000e3000 0x0 0x1000>; clocks = <&gcc GCC_PRNG_AHB_CLK>; @@ -441,7 +459,6 @@ #size-cells = <0>; reg = <0x0 0x078b5000 0x0 0x600>; interrupts = ; - spi-max-frequency = <50000000>; clocks = <&gcc GCC_BLSP1_QUP1_SPI_APPS_CLK>, <&gcc GCC_BLSP1_AHB_CLK>; clock-names = "core", "iface"; @@ -456,7 +473,6 @@ #size-cells = <0>; reg = <0x0 0x078b6000 0x0 0x600>; interrupts = ; - spi-max-frequency = <50000000>; clocks = <&gcc GCC_BLSP1_QUP2_SPI_APPS_CLK>, <&gcc GCC_BLSP1_AHB_CLK>; clock-names = "core", "iface"; @@ -572,7 +588,7 @@ #address-cells = <2>; #size-cells = <2>; interrupt-controller; - #interrupt-cells = <0x3>; + #interrupt-cells = <3>; reg = <0x0 0x0b000000 0x0 0x1000>, /*GICD*/ <0x0 0x0b002000 0x0 0x1000>, /*GICC*/ <0x0 0x0b001000 0x0 0x1000>, /*GICH*/ diff --git a/arch/arm64/boot/dts/qcom/ipq8074.dtsi b/arch/arm64/boot/dts/qcom/ipq8074.dtsi index 5b2c1986c8f4f3c8696edd240edd63d69bd00169..68839acbd613f8fc0284780a6edd7b13b582a3e4 100644 --- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi +++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi @@ -29,8 +29,8 @@ }; cpus { - #address-cells = <0x1>; - #size-cells = <0x0>; + #address-cells = <1>; + #size-cells = <0>; CPU0: cpu@0 { device_type = "cpu"; @@ -86,29 +86,40 @@ #size-cells = <2>; ranges; + bootloader@4a600000 { + reg = <0x0 0x4a600000 0x0 0x400000>; + no-map; + }; + + sbl@4aa00000 { + reg = <0x0 0x4aa00000 0x0 0x100000>; + no-map; + }; + smem@4ab00000 { compatible = "qcom,smem"; - reg = <0x0 0x4ab00000 0x0 0x00100000>; + reg = <0x0 0x4ab00000 0x0 0x100000>; no-map; hwlocks = <&tcsr_mutex 0>; }; memory@4ac00000 { + reg = <0x0 0x4ac00000 0x0 0x400000>; no-map; - reg = <0x0 0x4ac00000 0x0 0x00400000>; }; }; firmware { scm { compatible = "qcom,scm-ipq8074", "qcom,scm"; + qcom,dload-mode = <&tcsr 0x6100>; }; }; - soc: soc { - #address-cells = <0x1>; - #size-cells = <0x1>; + soc: soc@0 { + #address-cells = <1>; + #size-cells = <1>; ranges = <0 0 0 0xffffffff>; compatible = "simple-bus"; @@ -322,9 +333,9 @@ interrupts = ; gpio-controller; gpio-ranges = <&tlmm 0 0 70>; - #gpio-cells = <0x2>; + #gpio-cells = <2>; interrupt-controller; - #interrupt-cells = <0x2>; + #interrupt-cells = <2>; serial_4_pins: serial4-state { pins = "gpio23", "gpio24"; @@ -382,6 +393,11 @@ #hwlock-cells = <1>; }; + tcsr: syscon@1937000 { + compatible = "qcom,tcsr-ipq8074", "syscon"; + reg = <0x01937000 0x21000>; + }; + spmi_bus: spmi@200f000 { compatible = "qcom,spmi-pmic-arb"; reg = <0x0200f000 0x001000>, @@ -476,7 +492,6 @@ #size-cells = <0>; reg = <0x078b5000 0x600>; interrupts = ; - spi-max-frequency = <50000000>; clocks = <&gcc GCC_BLSP1_QUP1_SPI_APPS_CLK>, <&gcc GCC_BLSP1_AHB_CLK>; clock-names = "core", "iface"; @@ -534,6 +549,20 @@ status = "disabled"; }; + blsp1_spi5: spi@78b9000 { + compatible = "qcom,spi-qup-v2.2.1"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x78b9000 0x600>; + interrupts = ; + clocks = <&gcc GCC_BLSP1_QUP5_SPI_APPS_CLK>, + <&gcc GCC_BLSP1_AHB_CLK>; + clock-names = "core", "iface"; + dmas = <&blsp_dma 20>, <&blsp_dma 21>; + dma-names = "tx", "rx"; + status = "disabled"; + }; + blsp1_i2c6: i2c@78ba000 { compatible = "qcom,i2c-qup-v2.2.1"; #address-cells = <1>; @@ -667,7 +696,7 @@ #address-cells = <1>; #size-cells = <1>; interrupt-controller; - #interrupt-cells = <0x3>; + #interrupt-cells = <3>; reg = <0x0b000000 0x1000>, <0x0b002000 0x1000>; ranges = <0 0xb00a000 0xffd>; @@ -904,6 +933,14 @@ polling-delay = <1000>; thermal-sensors = <&tsens 4>; + + trips { + nss-top-crit { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; }; nss0-thermal { @@ -911,6 +948,14 @@ polling-delay = <1000>; thermal-sensors = <&tsens 5>; + + trips { + nss-0-crit { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; }; nss1-thermal { @@ -918,6 +963,14 @@ polling-delay = <1000>; thermal-sensors = <&tsens 6>; + + trips { + nss-1-crit { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; }; wcss-phya0-thermal { @@ -925,6 +978,14 @@ polling-delay = <1000>; thermal-sensors = <&tsens 7>; + + trips { + wcss-phya0-crit { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; }; wcss-phya1-thermal { @@ -932,6 +993,14 @@ polling-delay = <1000>; thermal-sensors = <&tsens 8>; + + trips { + wcss-phya1-crit { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; }; cpu0_thermal: cpu0-thermal { @@ -939,6 +1008,14 @@ polling-delay = <1000>; thermal-sensors = <&tsens 9>; + + trips { + cpu0-crit { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; }; cpu1_thermal: cpu1-thermal { @@ -946,6 +1023,14 @@ polling-delay = <1000>; thermal-sensors = <&tsens 10>; + + trips { + cpu1-crit { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; }; cpu2_thermal: cpu2-thermal { @@ -953,6 +1038,14 @@ polling-delay = <1000>; thermal-sensors = <&tsens 11>; + + trips { + cpu2-crit { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; }; cpu3_thermal: cpu3-thermal { @@ -960,6 +1053,14 @@ polling-delay = <1000>; thermal-sensors = <&tsens 12>; + + trips { + cpu3-crit { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; }; cluster_thermal: cluster-thermal { @@ -967,6 +1068,14 @@ polling-delay = <1000>; thermal-sensors = <&tsens 13>; + + trips { + cluster-crit { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; }; wcss-phyb0-thermal { @@ -974,6 +1083,14 @@ polling-delay = <1000>; thermal-sensors = <&tsens 14>; + + trips { + wcss-phyb0-crit { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; }; wcss-phyb1-thermal { @@ -981,6 +1098,14 @@ polling-delay = <1000>; thermal-sensors = <&tsens 15>; + + trips { + wcss-phyb1-crit { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; }; }; }; diff --git a/arch/arm64/boot/dts/qcom/ipq9574-rdp418.dts b/arch/arm64/boot/dts/qcom/ipq9574-rdp418.dts new file mode 100644 index 0000000000000000000000000000000000000000..2b093e02637ba5537d741fe6c0f15deb8fc82ae1 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/ipq9574-rdp418.dts @@ -0,0 +1,124 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * IPQ9574 RDP418 board device tree source + * + * Copyright (c) 2020-2021 The Linux Foundation. All rights reserved. + * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +/dts-v1/; + +#include "ipq9574.dtsi" + +/ { + model = "Qualcomm Technologies, Inc. IPQ9574/AP-AL02-C2"; + compatible = "qcom,ipq9574-ap-al02-c2", "qcom,ipq9574"; + + aliases { + serial0 = &blsp1_uart2; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; +}; + +&blsp1_spi0 { + pinctrl-0 = <&spi_0_pins>; + pinctrl-names = "default"; + status = "okay"; + + flash@0 { + compatible = "micron,n25q128a11", "jedec,spi-nor"; + reg = <0>; + #address-cells = <1>; + #size-cells = <1>; + spi-max-frequency = <50000000>; + }; +}; + +&blsp1_uart2 { + pinctrl-0 = <&uart2_pins>; + pinctrl-names = "default"; + status = "okay"; +}; + +&rpm_requests { + regulators { + compatible = "qcom,rpm-mp5496-regulators"; + + ipq9574_s1: s1 { + /* + * During kernel bootup, the SoC runs at 800MHz with 875mV set by the bootloaders. + * During regulator registration, kernel not knowing the initial voltage, + * considers it as zero and brings up the regulators with minimum supported voltage. + * Update the regulator-min-microvolt with SVS voltage of 725mV so that + * the regulators are brought up with 725mV which is sufficient for all the + * corner parts to operate at 800MHz + */ + regulator-min-microvolt = <725000>; + regulator-max-microvolt = <1075000>; + }; + }; +}; + +&sdhc_1 { + pinctrl-0 = <&sdc_default_state>; + pinctrl-names = "default"; + mmc-ddr-1_8v; + mmc-hs200-1_8v; + mmc-hs400-1_8v; + mmc-hs400-enhanced-strobe; + max-frequency = <384000000>; + bus-width = <8>; + status = "okay"; +}; + +&sleep_clk { + clock-frequency = <32000>; +}; + +&tlmm { + sdc_default_state: sdc-default-state { + clk-pins { + pins = "gpio5"; + function = "sdc_clk"; + drive-strength = <8>; + bias-disable; + }; + + cmd-pins { + pins = "gpio4"; + function = "sdc_cmd"; + drive-strength = <8>; + bias-pull-up; + }; + + data-pins { + pins = "gpio0", "gpio1", "gpio2", + "gpio3", "gpio6", "gpio7", + "gpio8", "gpio9"; + function = "sdc_data"; + drive-strength = <8>; + bias-pull-up; + }; + + rclk-pins { + pins = "gpio10"; + function = "sdc_rclk"; + drive-strength = <8>; + bias-pull-down; + }; + }; + + spi_0_pins: spi-0-state { + pins = "gpio11", "gpio12", "gpio13", "gpio14"; + function = "blsp0_spi"; + drive-strength = <8>; + bias-disable; + }; +}; + +&xo_board_clk { + clock-frequency = <24000000>; +}; diff --git a/arch/arm64/boot/dts/qcom/ipq9574-al02-c7.dts b/arch/arm64/boot/dts/qcom/ipq9574-rdp433.dts similarity index 67% rename from arch/arm64/boot/dts/qcom/ipq9574-al02-c7.dts rename to arch/arm64/boot/dts/qcom/ipq9574-rdp433.dts index 2c8430197ec0f3b3b80c6ec36308dc10c23af291..2b3ed8d351f701699dc5b1a605b29418fe26696c 100644 --- a/arch/arm64/boot/dts/qcom/ipq9574-al02-c7.dts +++ b/arch/arm64/boot/dts/qcom/ipq9574-rdp433.dts @@ -1,6 +1,6 @@ // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) /* - * IPQ9574 AL02-C7 board device tree source + * IPQ9574 RDP433 board device tree source * * Copyright (c) 2020-2021 The Linux Foundation. All rights reserved. * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved. @@ -29,6 +29,25 @@ status = "okay"; }; +&rpm_requests { + regulators { + compatible = "qcom,rpm-mp5496-regulators"; + + ipq9574_s1: s1 { + /* + * During kernel bootup, the SoC runs at 800MHz with 875mV set by the bootloaders. + * During regulator registration, kernel not knowing the initial voltage, + * considers it as zero and brings up the regulators with minimum supported voltage. + * Update the regulator-min-microvolt with SVS voltage of 725mV so that + * the regulators are brought up with 725mV which is sufficient for all the + * corner parts to operate at 800MHz + */ + regulator-min-microvolt = <725000>; + regulator-max-microvolt = <1075000>; + }; + }; +}; + &sdhc_1 { pinctrl-0 = <&sdc_default_state>; pinctrl-names = "default"; diff --git a/arch/arm64/boot/dts/qcom/ipq9574-rdp449.dts b/arch/arm64/boot/dts/qcom/ipq9574-rdp449.dts new file mode 100644 index 0000000000000000000000000000000000000000..c8fa54e1a62cc0c0815a191d1e1996c45ffcb6d8 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/ipq9574-rdp449.dts @@ -0,0 +1,80 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * IPQ9574 RDP449 board device tree source + * + * Copyright (c) 2020-2021 The Linux Foundation. All rights reserved. + * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +/dts-v1/; + +#include "ipq9574.dtsi" + +/ { + model = "Qualcomm Technologies, Inc. IPQ9574/AP-AL02-C6"; + compatible = "qcom,ipq9574-ap-al02-c6", "qcom,ipq9574"; + + aliases { + serial0 = &blsp1_uart2; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; +}; + +&blsp1_spi0 { + pinctrl-0 = <&spi_0_pins>; + pinctrl-names = "default"; + status = "okay"; + + flash@0 { + compatible = "micron,n25q128a11", "jedec,spi-nor"; + reg = <0>; + #address-cells = <1>; + #size-cells = <1>; + spi-max-frequency = <50000000>; + }; +}; + +&blsp1_uart2 { + pinctrl-0 = <&uart2_pins>; + pinctrl-names = "default"; + status = "okay"; +}; + +&rpm_requests { + regulators { + compatible = "qcom,rpm-mp5496-regulators"; + + ipq9574_s1: s1 { + /* + * During kernel bootup, the SoC runs at 800MHz with 875mV set by the bootloaders. + * During regulator registration, kernel not knowing the initial voltage, + * considers it as zero and brings up the regulators with minimum supported voltage. + * Update the regulator-min-microvolt with SVS voltage of 725mV so that + * the regulators are brought up with 725mV which is sufficient for all the + * corner parts to operate at 800MHz + */ + regulator-min-microvolt = <725000>; + regulator-max-microvolt = <1075000>; + }; + }; +}; + +&sleep_clk { + clock-frequency = <32000>; +}; + +&tlmm { + spi_0_pins: spi-0-state { + pins = "gpio11", "gpio12", "gpio13", "gpio14"; + function = "blsp0_spi"; + drive-strength = <8>; + bias-disable; + }; +}; + +&xo_board_clk { + clock-frequency = <24000000>; +}; diff --git a/arch/arm64/boot/dts/qcom/ipq9574-rdp453.dts b/arch/arm64/boot/dts/qcom/ipq9574-rdp453.dts new file mode 100644 index 0000000000000000000000000000000000000000..f01de6628c3b115c43d19265ad66929864f70120 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/ipq9574-rdp453.dts @@ -0,0 +1,80 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * IPQ9574 RDP453 board device tree source + * + * Copyright (c) 2020-2021 The Linux Foundation. All rights reserved. + * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +/dts-v1/; + +#include "ipq9574.dtsi" + +/ { + model = "Qualcomm Technologies, Inc. IPQ9574/AP-AL02-C8"; + compatible = "qcom,ipq9574-ap-al02-c8", "qcom,ipq9574"; + + aliases { + serial0 = &blsp1_uart2; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; +}; + +&blsp1_spi0 { + pinctrl-0 = <&spi_0_pins>; + pinctrl-names = "default"; + status = "okay"; + + flash@0 { + compatible = "micron,n25q128a11", "jedec,spi-nor"; + reg = <0>; + #address-cells = <1>; + #size-cells = <1>; + spi-max-frequency = <50000000>; + }; +}; + +&blsp1_uart2 { + pinctrl-0 = <&uart2_pins>; + pinctrl-names = "default"; + status = "okay"; +}; + +&rpm_requests { + regulators { + compatible = "qcom,rpm-mp5496-regulators"; + + ipq9574_s1: s1 { + /* + * During kernel bootup, the SoC runs at 800MHz with 875mV set by the bootloaders. + * During regulator registration, kernel not knowing the initial voltage, + * considers it as zero and brings up the regulators with minimum supported voltage. + * Update the regulator-min-microvolt with SVS voltage of 725mV so that + * the regulators are brought up with 725mV which is sufficient for all the + * corner parts to operate at 800MHz + */ + regulator-min-microvolt = <725000>; + regulator-max-microvolt = <1075000>; + }; + }; +}; + +&sleep_clk { + clock-frequency = <32000>; +}; + +&tlmm { + spi_0_pins: spi-0-state { + pins = "gpio11", "gpio12", "gpio13", "gpio14"; + function = "blsp0_spi"; + drive-strength = <8>; + bias-disable; + }; +}; + +&xo_board_clk { + clock-frequency = <24000000>; +}; diff --git a/arch/arm64/boot/dts/qcom/ipq9574-rdp454.dts b/arch/arm64/boot/dts/qcom/ipq9574-rdp454.dts new file mode 100644 index 0000000000000000000000000000000000000000..6efae3426cb84055b8449030561946e58af3df75 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/ipq9574-rdp454.dts @@ -0,0 +1,80 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * IPQ9574 RDP454 board device tree source + * + * Copyright (c) 2020-2021 The Linux Foundation. All rights reserved. + * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +/dts-v1/; + +#include "ipq9574.dtsi" + +/ { + model = "Qualcomm Technologies, Inc. IPQ9574/AP-AL02-C9"; + compatible = "qcom,ipq9574-ap-al02-c9", "qcom,ipq9574"; + + aliases { + serial0 = &blsp1_uart2; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; +}; + +&blsp1_spi0 { + pinctrl-0 = <&spi_0_pins>; + pinctrl-names = "default"; + status = "okay"; + + flash@0 { + compatible = "micron,n25q128a11", "jedec,spi-nor"; + reg = <0>; + #address-cells = <1>; + #size-cells = <1>; + spi-max-frequency = <50000000>; + }; +}; + +&blsp1_uart2 { + pinctrl-0 = <&uart2_pins>; + pinctrl-names = "default"; + status = "okay"; +}; + +&rpm_requests { + regulators { + compatible = "qcom,rpm-mp5496-regulators"; + + ipq9574_s1: s1 { + /* + * During kernel bootup, the SoC runs at 800MHz with 875mV set by the bootloaders. + * During regulator registration, kernel not knowing the initial voltage, + * considers it as zero and brings up the regulators with minimum supported voltage. + * Update the regulator-min-microvolt with SVS voltage of 725mV so that + * the regulators are brought up with 725mV which is sufficient for all the + * corner parts to operate at 800MHz + */ + regulator-min-microvolt = <725000>; + regulator-max-microvolt = <1075000>; + }; + }; +}; + +&sleep_clk { + clock-frequency = <32000>; +}; + +&tlmm { + spi_0_pins: spi-0-state { + pins = "gpio11", "gpio12", "gpio13", "gpio14"; + function = "blsp0_spi"; + drive-strength = <8>; + bias-disable; + }; +}; + +&xo_board_clk { + clock-frequency = <24000000>; +}; diff --git a/arch/arm64/boot/dts/qcom/ipq9574.dtsi b/arch/arm64/boot/dts/qcom/ipq9574.dtsi index 0ed19fbf7d87d1c7abdb8db7258b39d25660020b..f120c7c523517b6c6a6c7d5e23336fb04cb55fae 100644 --- a/arch/arm64/boot/dts/qcom/ipq9574.dtsi +++ b/arch/arm64/boot/dts/qcom/ipq9574.dtsi @@ -6,8 +6,9 @@ * Copyright (c) 2023, Qualcomm Innovation Center, Inc. All rights reserved. */ -#include +#include #include +#include #include / { @@ -16,12 +17,6 @@ #size-cells = <2>; clocks { - bias_pll_ubi_nc_clk: bias-pll-ubi-nc-clk { - compatible = "fixed-clock"; - clock-frequency = <353000000>; - #clock-cells = <0>; - }; - sleep_clk: sleep-clk { compatible = "fixed-clock"; #clock-cells = <0>; @@ -43,6 +38,10 @@ reg = <0x0>; enable-method = "psci"; next-level-cache = <&L2_0>; + clocks = <&apcs_glb APCS_ALIAS0_CORE_CLK>; + clock-names = "cpu"; + operating-points-v2 = <&cpu_opp_table>; + cpu-supply = <&ipq9574_s1>; }; CPU1: cpu@1 { @@ -51,6 +50,10 @@ reg = <0x1>; enable-method = "psci"; next-level-cache = <&L2_0>; + clocks = <&apcs_glb APCS_ALIAS0_CORE_CLK>; + clock-names = "cpu"; + operating-points-v2 = <&cpu_opp_table>; + cpu-supply = <&ipq9574_s1>; }; CPU2: cpu@2 { @@ -59,6 +62,10 @@ reg = <0x2>; enable-method = "psci"; next-level-cache = <&L2_0>; + clocks = <&apcs_glb APCS_ALIAS0_CORE_CLK>; + clock-names = "cpu"; + operating-points-v2 = <&cpu_opp_table>; + cpu-supply = <&ipq9574_s1>; }; CPU3: cpu@3 { @@ -67,6 +74,10 @@ reg = <0x3>; enable-method = "psci"; next-level-cache = <&L2_0>; + clocks = <&apcs_glb APCS_ALIAS0_CORE_CLK>; + clock-names = "cpu"; + operating-points-v2 = <&cpu_opp_table>; + cpu-supply = <&ipq9574_s1>; }; L2_0: l2-cache { @@ -76,12 +87,60 @@ }; }; + firmware { + scm { + compatible = "qcom,scm-ipq9574", "qcom,scm"; + qcom,dload-mode = <&tcsr 0x6100>; + }; + }; + memory@40000000 { device_type = "memory"; /* We expect the bootloader to fill in the size */ reg = <0x0 0x40000000 0x0 0x0>; }; + cpu_opp_table: opp-table-cpu { + compatible = "operating-points-v2"; + opp-shared; + + opp-936000000 { + opp-hz = /bits/ 64 <936000000>; + opp-microvolt = <725000>; + clock-latency-ns = <200000>; + }; + + opp-1104000000 { + opp-hz = /bits/ 64 <1104000000>; + opp-microvolt = <787500>; + clock-latency-ns = <200000>; + }; + + opp-1416000000 { + opp-hz = /bits/ 64 <1416000000>; + opp-microvolt = <862500>; + clock-latency-ns = <200000>; + }; + + opp-1488000000 { + opp-hz = /bits/ 64 <1488000000>; + opp-microvolt = <925000>; + clock-latency-ns = <200000>; + }; + + opp-1800000000 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <987500>; + clock-latency-ns = <200000>; + }; + + opp-2208000000 { + opp-hz = /bits/ 64 <2208000000>; + opp-microvolt = <1062500>; + clock-latency-ns = <200000>; + }; + }; + pmu { compatible = "arm,cortex-a73-pmu"; interrupts = ; @@ -97,10 +156,39 @@ #size-cells = <2>; ranges; + bootloader@4a100000 { + reg = <0x0 0x4a100000 0x0 0x400000>; + no-map; + }; + + sbl@4a500000 { + reg = <0x0 0x4a500000 0x0 0x100000>; + no-map; + }; + tz_region: tz@4a600000 { reg = <0x0 0x4a600000 0x0 0x400000>; no-map; }; + + smem@4aa00000 { + compatible = "qcom,smem"; + reg = <0x0 0x4aa00000 0x0 0x100000>; + hwlocks = <&tcsr_mutex 0>; + no-map; + }; + }; + + rpm-glink { + compatible = "qcom,glink-rpm"; + interrupts = ; + qcom,rpm-msg-ram = <&rpm_msg_ram>; + mboxes = <&apcs_glb 0>; + + rpm_requests: rpm-requests { + compatible = "qcom,rpm-ipq9574"; + qcom,glink-channels = "rpm_requests"; + }; }; soc: soc@0 { @@ -109,6 +197,55 @@ #size-cells = <1>; ranges = <0 0 0 0xffffffff>; + rpm_msg_ram: sram@60000 { + compatible = "qcom,rpm-msg-ram"; + reg = <0x00060000 0x6000>; + }; + + rng: rng@e3000 { + compatible = "qcom,prng-ee"; + reg = <0x000e3000 0x1000>; + clocks = <&gcc GCC_PRNG_AHB_CLK>; + clock-names = "core"; + }; + + qfprom: efuse@a4000 { + compatible = "qcom,ipq9574-qfprom", "qcom,qfprom"; + reg = <0x000a4000 0x5a1>; + #address-cells = <1>; + #size-cells = <1>; + }; + + cryptobam: dma-controller@704000 { + compatible = "qcom,bam-v1.7.4", "qcom,bam-v1.7.0"; + reg = <0x00704000 0x20000>; + interrupts = ; + #dma-cells = <1>; + qcom,ee = <1>; + qcom,controlled-remotely; + }; + + crypto: crypto@73a000 { + compatible = "qcom,ipq9574-qce", "qcom,ipq4019-qce", "qcom,qce"; + reg = <0x0073a000 0x6000>; + clocks = <&gcc GCC_CRYPTO_AHB_CLK>, + <&gcc GCC_CRYPTO_AXI_CLK>, + <&gcc GCC_CRYPTO_CLK>; + clock-names = "iface", "bus", "core"; + dmas = <&cryptobam 2>, <&cryptobam 3>; + dma-names = "rx", "tx"; + }; + + tsens: thermal-sensor@4a9000 { + compatible = "qcom,ipq9574-tsens", "qcom,ipq8074-tsens"; + reg = <0x004a9000 0x1000>, + <0x004a8000 0x1000>; + interrupts = ; + interrupt-names = "combined"; + #qcom,sensors = <16>; + #thermal-sensor-cells = <1>; + }; + tlmm: pinctrl@1000000 { compatible = "qcom,ipq9574-tlmm"; reg = <0x01000000 0x300000>; @@ -132,7 +269,7 @@ reg = <0x01800000 0x80000>; clocks = <&xo_board_clk>, <&sleep_clk>, - <&bias_pll_ubi_nc_clk>, + <0>, <0>, <0>, <0>, @@ -143,6 +280,17 @@ #power-domain-cells = <1>; }; + tcsr_mutex: hwlock@1905000 { + compatible = "qcom,tcsr-mutex"; + reg = <0x01905000 0x20000>; + #hwlock-cells = <1>; + }; + + tcsr: syscon@1937000 { + compatible = "qcom,tcsr-ipq9574", "syscon"; + reg = <0x01937000 0x21000>; + }; + sdhc_1: mmc@7804000 { compatible = "qcom,ipq9574-sdhci", "qcom,sdhci-msm-v5"; reg = <0x07804000 0x1000>, <0x07805000 0x1000>; @@ -160,6 +308,36 @@ status = "disabled"; }; + blsp_dma: dma-controller@7884000 { + compatible = "qcom,bam-v1.7.0"; + reg = <0x07884000 0x2b000>; + interrupts = ; + clocks = <&gcc GCC_BLSP1_AHB_CLK>; + clock-names = "bam_clk"; + #dma-cells = <1>; + qcom,ee = <0>; + }; + + blsp1_uart0: serial@78af000 { + compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm"; + reg = <0x078af000 0x200>; + interrupts = ; + clocks = <&gcc GCC_BLSP1_UART1_APPS_CLK>, + <&gcc GCC_BLSP1_AHB_CLK>; + clock-names = "core", "iface"; + status = "disabled"; + }; + + blsp1_uart1: serial@78b0000 { + compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm"; + reg = <0x078b0000 0x200>; + interrupts = ; + clocks = <&gcc GCC_BLSP1_UART2_APPS_CLK>, + <&gcc GCC_BLSP1_AHB_CLK>; + clock-names = "core", "iface"; + status = "disabled"; + }; + blsp1_uart2: serial@78b1000 { compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm"; reg = <0x078b1000 0x200>; @@ -170,17 +348,174 @@ status = "disabled"; }; + blsp1_uart3: serial@78b2000 { + compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm"; + reg = <0x078b2000 0x200>; + interrupts = ; + clocks = <&gcc GCC_BLSP1_UART4_APPS_CLK>, + <&gcc GCC_BLSP1_AHB_CLK>; + clock-names = "core", "iface"; + status = "disabled"; + }; + + blsp1_uart4: serial@78b3000 { + compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm"; + reg = <0x078b3000 0x200>; + interrupts = ; + clocks = <&gcc GCC_BLSP1_UART5_APPS_CLK>, + <&gcc GCC_BLSP1_AHB_CLK>; + clock-names = "core", "iface"; + status = "disabled"; + }; + + blsp1_uart5: serial@78b4000 { + compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm"; + reg = <0x078b4000 0x200>; + interrupts = ; + clocks = <&gcc GCC_BLSP1_UART6_APPS_CLK>, + <&gcc GCC_BLSP1_AHB_CLK>; + clock-names = "core", "iface"; + status = "disabled"; + }; + + blsp1_spi0: spi@78b5000 { + compatible = "qcom,spi-qup-v2.2.1"; + reg = <0x078b5000 0x600>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = ; + clocks = <&gcc GCC_BLSP1_QUP1_SPI_APPS_CLK>, + <&gcc GCC_BLSP1_AHB_CLK>; + clock-names = "core", "iface"; + dmas = <&blsp_dma 12>, <&blsp_dma 13>; + dma-names = "tx", "rx"; + status = "disabled"; + }; + + blsp1_i2c1: i2c@78b6000 { + compatible = "qcom,i2c-qup-v2.2.1"; + reg = <0x078b6000 0x600>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = ; + clocks = <&gcc GCC_BLSP1_QUP2_I2C_APPS_CLK>, + <&gcc GCC_BLSP1_AHB_CLK>; + clock-names = "core", "iface"; + dmas = <&blsp_dma 14>, <&blsp_dma 15>; + dma-names = "tx", "rx"; + status = "disabled"; + }; + + blsp1_spi1: spi@78b6000 { + compatible = "qcom,spi-qup-v2.2.1"; + reg = <0x078b6000 0x600>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = ; + clocks = <&gcc GCC_BLSP1_QUP2_SPI_APPS_CLK>, + <&gcc GCC_BLSP1_AHB_CLK>; + clock-names = "core", "iface"; + dmas = <&blsp_dma 14>, <&blsp_dma 15>; + dma-names = "tx", "rx"; + status = "disabled"; + }; + + blsp1_i2c2: i2c@78b7000 { + compatible = "qcom,i2c-qup-v2.2.1"; + reg = <0x078b7000 0x600>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = ; + clocks = <&gcc GCC_BLSP1_QUP3_I2C_APPS_CLK>, + <&gcc GCC_BLSP1_AHB_CLK>; + clock-names = "core", "iface"; + dmas = <&blsp_dma 16>, <&blsp_dma 17>; + dma-names = "tx", "rx"; + status = "disabled"; + }; + + blsp1_spi2: spi@78b7000 { + compatible = "qcom,spi-qup-v2.2.1"; + reg = <0x078b7000 0x600>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = ; + clocks = <&gcc GCC_BLSP1_QUP3_SPI_APPS_CLK>, + <&gcc GCC_BLSP1_AHB_CLK>; + clock-names = "core", "iface"; + dmas = <&blsp_dma 16>, <&blsp_dma 17>; + dma-names = "tx", "rx"; + status = "disabled"; + }; + + blsp1_i2c3: i2c@78b8000 { + compatible = "qcom,i2c-qup-v2.2.1"; + reg = <0x078b8000 0x600>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = ; + clocks = <&gcc GCC_BLSP1_QUP4_I2C_APPS_CLK>, + <&gcc GCC_BLSP1_AHB_CLK>; + clock-names = "core", "iface"; + dmas = <&blsp_dma 18>, <&blsp_dma 19>; + dma-names = "tx", "rx"; + status = "disabled"; + }; + + blsp1_spi3: spi@78b8000 { + compatible = "qcom,spi-qup-v2.2.1"; + reg = <0x078b8000 0x600>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = ; + spi-max-frequency = <50000000>; + clocks = <&gcc GCC_BLSP1_QUP4_SPI_APPS_CLK>, + <&gcc GCC_BLSP1_AHB_CLK>; + clock-names = "core", "iface"; + dmas = <&blsp_dma 18>, <&blsp_dma 19>; + dma-names = "tx", "rx"; + status = "disabled"; + }; + + blsp1_i2c4: i2c@78b9000 { + compatible = "qcom,i2c-qup-v2.2.1"; + reg = <0x078b9000 0x600>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = ; + clocks = <&gcc GCC_BLSP1_QUP5_I2C_APPS_CLK>, + <&gcc GCC_BLSP1_AHB_CLK>; + clock-names = "core", "iface"; + dmas = <&blsp_dma 20>, <&blsp_dma 21>; + dma-names = "tx", "rx"; + status = "disabled"; + }; + + blsp1_spi4: spi@78b9000 { + compatible = "qcom,spi-qup-v2.2.1"; + reg = <0x078b9000 0x600>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = ; + clocks = <&gcc GCC_BLSP1_QUP5_SPI_APPS_CLK>, + <&gcc GCC_BLSP1_AHB_CLK>; + clock-names = "core", "iface"; + dmas = <&blsp_dma 20>, <&blsp_dma 21>; + dma-names = "tx", "rx"; + status = "disabled"; + }; + intc: interrupt-controller@b000000 { compatible = "qcom,msm-qgic2"; reg = <0x0b000000 0x1000>, /* GICD */ - <0x0b002000 0x1000>, /* GICC */ + <0x0b002000 0x2000>, /* GICC */ <0x0b001000 0x1000>, /* GICH */ - <0x0b004000 0x1000>; /* GICV */ + <0x0b004000 0x2000>; /* GICV */ #address-cells = <1>; #size-cells = <1>; interrupt-controller; #interrupt-cells = <3>; - interrupts = ; + interrupts = ; ranges = <0 0x0b00c000 0x3000>; v2m0: v2m@0 { @@ -202,6 +537,32 @@ }; }; + watchdog: watchdog@b017000 { + compatible = "qcom,apss-wdt-ipq9574", "qcom,kpss-wdt"; + reg = <0x0b017000 0x1000>; + interrupts = ; + clocks = <&sleep_clk>; + timeout-sec = <30>; + }; + + apcs_glb: mailbox@b111000 { + compatible = "qcom,ipq9574-apcs-apps-global", + "qcom,ipq6018-apcs-apps-global"; + reg = <0x0b111000 0x1000>; + #clock-cells = <1>; + clocks = <&a73pll>, <&xo_board_clk>; + clock-names = "pll", "xo"; + #mbox-cells = <1>; + }; + + a73pll: clock@b116000 { + compatible = "qcom,ipq9574-a73pll"; + reg = <0x0b116000 0x40>; + #clock-cells = <0>; + clocks = <&xo_board_clk>; + clock-names = "xo"; + }; + timer@b120000 { compatible = "arm,armv7-timer-mem"; reg = <0x0b120000 0x1000>; @@ -261,6 +622,214 @@ }; }; + thermal-zones { + nss-top-thermal { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-sensors = <&tsens 3>; + + trips { + nss-top-critical { + temperature = <125000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + }; + + ubi-0-thermal { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-sensors = <&tsens 4>; + + trips { + ubi_0-critical { + temperature = <125000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + }; + + ubi-1-thermal { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-sensors = <&tsens 5>; + + trips { + ubi_1-critical { + temperature = <125000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + }; + + ubi-2-thermal { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-sensors = <&tsens 6>; + + trips { + ubi_2-critical { + temperature = <125000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + }; + + ubi-3-thermal { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-sensors = <&tsens 7>; + + trips { + ubi_3-critical { + temperature = <125000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + }; + + cpuss0-thermal { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-sensors = <&tsens 8>; + + trips { + cpu-critical { + temperature = <125000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + }; + + cpuss1-thermal { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-sensors = <&tsens 9>; + + trips { + cpu-critical { + temperature = <125000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + }; + + cpu0-thermal { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-sensors = <&tsens 10>; + + trips { + cpu-critical { + temperature = <120000>; + hysteresis = <10000>; + type = "critical"; + }; + + cpu-passive { + temperature = <110000>; + hysteresis = <1000>; + type = "passive"; + }; + }; + }; + + cpu1-thermal { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-sensors = <&tsens 11>; + + trips { + cpu-critical { + temperature = <120000>; + hysteresis = <10000>; + type = "critical"; + }; + + cpu-passive { + temperature = <110000>; + hysteresis = <1000>; + type = "passive"; + }; + }; + }; + + cpu2-thermal { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-sensors = <&tsens 12>; + + trips { + cpu-critical { + temperature = <120000>; + hysteresis = <10000>; + type = "critical"; + }; + + cpu-passive { + temperature = <110000>; + hysteresis = <1000>; + type = "passive"; + }; + }; + }; + + cpu3-thermal { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-sensors = <&tsens 13>; + + trips { + cpu-critical { + temperature = <120000>; + hysteresis = <10000>; + type = "critical"; + }; + + cpu-passive { + temperature = <110000>; + hysteresis = <1000>; + type = "passive"; + }; + }; + }; + + wcss-phyb-thermal { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-sensors = <&tsens 14>; + + trips { + wcss_phyb-critical { + temperature = <125000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + }; + + top-glue-thermal { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-sensors = <&tsens 15>; + + trips { + top_glue-critical { + temperature = <125000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + }; + }; + timer { compatible = "arm,armv8-timer"; interrupts = , diff --git a/arch/arm64/boot/dts/qcom/msm8916-acer-a1-724.dts b/arch/arm64/boot/dts/qcom/msm8916-acer-a1-724.dts index 13cd9ad167df745287680195a0519a11db81b856..5ad49fe999dba5f103a467e08afe6871504895d2 100644 --- a/arch/arm64/boot/dts/qcom/msm8916-acer-a1-724.dts +++ b/arch/arm64/boot/dts/qcom/msm8916-acer-a1-724.dts @@ -22,7 +22,9 @@ chassis-type = "tablet"; aliases { - serial0 = &blsp1_uart2; + mmc0 = &sdhc_1; /* eMMC */ + mmc1 = &sdhc_2; /* SD card */ + serial0 = &blsp_uart2; }; chosen { @@ -39,14 +41,14 @@ button-volume-up { label = "Volume Up"; - gpios = <&msmgpio 107 GPIO_ACTIVE_LOW>; + gpios = <&tlmm 107 GPIO_ACTIVE_LOW>; linux,code = ; }; }; usb_id: usb-id { compatible = "linux,extcon-usb-gpio"; - id-gpio = <&msmgpio 110 GPIO_ACTIVE_HIGH>; + id-gpio = <&tlmm 110 GPIO_ACTIVE_HIGH>; pinctrl-names = "default"; pinctrl-0 = <&usb_id_default>; }; @@ -58,7 +60,7 @@ accelerometer@10 { compatible = "bosch,bmc150_accel"; reg = <0x10>; - interrupt-parent = <&msmgpio>; + interrupt-parent = <&tlmm>; interrupts = <115 IRQ_TYPE_EDGE_RISING>; vdd-supply = <&pm8916_l17>; @@ -89,10 +91,10 @@ compatible = "edt,edt-ft5406"; reg = <0x38>; - interrupt-parent = <&msmgpio>; + interrupt-parent = <&tlmm>; interrupts = <13 IRQ_TYPE_LEVEL_LOW>; - reset-gpios = <&msmgpio 12 GPIO_ACTIVE_LOW>; + reset-gpios = <&tlmm 12 GPIO_ACTIVE_LOW>; vcc-supply = <&pm8916_l16>; iovcc-supply = <&pm8916_l6>; @@ -105,7 +107,7 @@ }; }; -&blsp1_uart2 { +&blsp_uart2 { status = "okay"; }; @@ -114,24 +116,32 @@ status = "okay"; }; +&pm8916_rpm_regulators { + pm8916_l16: l16 { + regulator-min-microvolt = <2900000>; + regulator-max-microvolt = <2900000>; + }; + + pm8916_l17: l17 { + regulator-min-microvolt = <2850000>; + regulator-max-microvolt = <2850000>; + }; +}; + &pm8916_vib { status = "okay"; }; &sdhc_1 { - pinctrl-names = "default", "sleep"; - pinctrl-0 = <&sdc1_clk_on &sdc1_cmd_on &sdc1_data_on>; - pinctrl-1 = <&sdc1_clk_off &sdc1_cmd_off &sdc1_data_off>; - status = "okay"; }; &sdhc_2 { pinctrl-names = "default", "sleep"; - pinctrl-0 = <&sdc2_clk_on &sdc2_cmd_on &sdc2_data_on>; - pinctrl-1 = <&sdc2_clk_off &sdc2_cmd_off &sdc2_data_off>; + pinctrl-0 = <&sdc2_default &sdc2_cd_default>; + pinctrl-1 = <&sdc2_sleep &sdc2_cd_default>; - cd-gpios = <&msmgpio 38 GPIO_ACTIVE_HIGH>; + cd-gpios = <&tlmm 38 GPIO_ACTIVE_HIGH>; status = "okay"; }; @@ -153,110 +163,7 @@ compatible = "qcom,wcn3620"; }; -&smd_rpm_regulators { - vdd_l1_l2_l3-supply = <&pm8916_s3>; - vdd_l4_l5_l6-supply = <&pm8916_s4>; - vdd_l7-supply = <&pm8916_s4>; - - s3 { - regulator-min-microvolt = <1200000>; - regulator-max-microvolt = <1300000>; - }; - - s4 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <2100000>; - }; - - l1 { - regulator-min-microvolt = <1225000>; - regulator-max-microvolt = <1225000>; - }; - - l2 { - regulator-min-microvolt = <1200000>; - regulator-max-microvolt = <1200000>; - }; - - l4 { - regulator-min-microvolt = <2050000>; - regulator-max-microvolt = <2050000>; - }; - - l5 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - }; - - l6 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - }; - - l7 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - }; - - l8 { - regulator-min-microvolt = <2850000>; - regulator-max-microvolt = <2900000>; - }; - - l9 { - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - }; - - l10 { - regulator-min-microvolt = <2700000>; - regulator-max-microvolt = <2800000>; - }; - - l11 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <2950000>; - regulator-system-load = <200000>; - regulator-allow-set-load; - }; - - l12 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <2950000>; - }; - - l13 { - regulator-min-microvolt = <3075000>; - regulator-max-microvolt = <3075000>; - }; - - l14 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <3300000>; - }; - - l15 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <3300000>; - }; - - l16 { - regulator-min-microvolt = <2900000>; - regulator-max-microvolt = <2900000>; - }; - - l17 { - regulator-min-microvolt = <2850000>; - regulator-max-microvolt = <2850000>; - }; - - l18 { - regulator-min-microvolt = <2700000>; - regulator-max-microvolt = <2700000>; - }; -}; - -&msmgpio { +&tlmm { accel_int_default: accel-int-default-state { pins = "gpio115"; function = "gpio"; @@ -273,6 +180,13 @@ bias-pull-up; }; + sdc2_cd_default: sdc2-cd-default-state { + pins = "gpio38"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + touchscreen_default: touchscreen-default-state { reset-pins { pins = "gpio12"; diff --git a/arch/arm64/boot/dts/qcom/msm8916-alcatel-idol347.dts b/arch/arm64/boot/dts/qcom/msm8916-alcatel-idol347.dts index fecb69944cfa38ca3dfa5586dfd4f031d04afc67..1c43f3d6a0b4b63160690ce2711a7baf32ebeaff 100644 --- a/arch/arm64/boot/dts/qcom/msm8916-alcatel-idol347.dts +++ b/arch/arm64/boot/dts/qcom/msm8916-alcatel-idol347.dts @@ -13,7 +13,9 @@ chassis-type = "handset"; aliases { - serial0 = &blsp1_uart2; + mmc0 = &sdhc_1; /* eMMC */ + mmc1 = &sdhc_2; /* SD card */ + serial0 = &blsp_uart2; }; chosen { @@ -30,7 +32,7 @@ button-volume-up { label = "Volume Up"; - gpios = <&msmgpio 107 GPIO_ACTIVE_LOW>; + gpios = <&tlmm 107 GPIO_ACTIVE_LOW>; linux,code = ; }; }; @@ -42,7 +44,7 @@ pinctrl-0 = <&gpio_leds_default>; led-0 { - gpios = <&msmgpio 32 GPIO_ACTIVE_HIGH>; + gpios = <&tlmm 32 GPIO_ACTIVE_HIGH>; linux,default-trigger = "torch"; function = LED_FUNCTION_TORCH; }; @@ -50,13 +52,13 @@ usb_id: usb-id { compatible = "linux,extcon-usb-gpio"; - id-gpio = <&msmgpio 69 GPIO_ACTIVE_HIGH>; + id-gpio = <&tlmm 69 GPIO_ACTIVE_HIGH>; pinctrl-names = "default"; pinctrl-0 = <&usb_id_default>; }; }; -&blsp1_uart2 { +&blsp_uart2 { status = "okay"; }; @@ -66,9 +68,9 @@ touchscreen@26 { compatible = "mstar,msg2638"; reg = <0x26>; - interrupt-parent = <&msmgpio>; + interrupt-parent = <&tlmm>; interrupts = <13 IRQ_TYPE_EDGE_FALLING>; - reset-gpios = <&msmgpio 100 GPIO_ACTIVE_LOW>; + reset-gpios = <&tlmm 100 GPIO_ACTIVE_LOW>; pinctrl-names = "default"; pinctrl-0 = <&ts_int_reset_default>; vdd-supply = <&pm8916_l17>; @@ -86,7 +88,7 @@ reg = <0x0c>; vdd-supply = <&pm8916_l17>; vid-supply = <&pm8916_l6>; - reset-gpios = <&msmgpio 8 GPIO_ACTIVE_LOW>; + reset-gpios = <&tlmm 8 GPIO_ACTIVE_LOW>; pinctrl-names = "default"; pinctrl-0 = <&mag_reset_default>; mount-matrix = "0", "1", "0", @@ -99,7 +101,7 @@ reg = <0x0f>; vdd-supply = <&pm8916_l17>; vddio-supply = <&pm8916_l6>; - interrupt-parent = <&msmgpio>; + interrupt-parent = <&tlmm>; interrupts = <31 IRQ_TYPE_EDGE_RISING>; pinctrl-names = "default"; pinctrl-0 = <&accel_int_default>; @@ -111,7 +113,7 @@ proximity@48 { compatible = "sensortek,stk3310"; reg = <0x48>; - interrupt-parent = <&msmgpio>; + interrupt-parent = <&tlmm>; interrupts = <12 IRQ_TYPE_EDGE_FALLING>; pinctrl-names = "default"; pinctrl-0 = <&proximity_int_default>; @@ -122,7 +124,7 @@ reg = <0x68>; vdd-supply = <&pm8916_l17>; vddio-supply = <&pm8916_l6>; - interrupt-parent = <&msmgpio>; + interrupt-parent = <&tlmm>; interrupts = <97 IRQ_TYPE_EDGE_RISING>, <98 IRQ_TYPE_EDGE_RISING>; pinctrl-names = "default"; @@ -136,7 +138,7 @@ led-controller@68 { compatible = "si-en,sn3190"; reg = <0x68>; - shutdown-gpios = <&msmgpio 89 GPIO_ACTIVE_HIGH>; + shutdown-gpios = <&tlmm 89 GPIO_ACTIVE_HIGH>; pinctrl-names = "default"; pinctrl-0 = <&led_enable_default &led_shutdown_default>; #address-cells = <1>; @@ -156,26 +158,29 @@ linux,code = ; }; +&pm8916_rpm_regulators { + pm8916_l17: l17 { + regulator-min-microvolt = <2850000>; + regulator-max-microvolt = <2850000>; + }; +}; + &pm8916_vib { status = "okay"; }; &sdhc_1 { status = "okay"; - - pinctrl-names = "default", "sleep"; - pinctrl-0 = <&sdc1_clk_on &sdc1_cmd_on &sdc1_data_on>; - pinctrl-1 = <&sdc1_clk_off &sdc1_cmd_off &sdc1_data_off>; }; &sdhc_2 { status = "okay"; pinctrl-names = "default", "sleep"; - pinctrl-0 = <&sdc2_clk_on &sdc2_cmd_on &sdc2_data_on &sdc2_cd_on>; - pinctrl-1 = <&sdc2_clk_off &sdc2_cmd_off &sdc2_data_off &sdc2_cd_off>; + pinctrl-0 = <&sdc2_default &sdc2_cd_default>; + pinctrl-1 = <&sdc2_sleep &sdc2_cd_default>; - cd-gpios = <&msmgpio 38 GPIO_ACTIVE_LOW>; + cd-gpios = <&tlmm 38 GPIO_ACTIVE_LOW>; }; &usb { @@ -195,110 +200,7 @@ compatible = "qcom,wcn3620"; }; -&smd_rpm_regulators { - vdd_l1_l2_l3-supply = <&pm8916_s3>; - vdd_l4_l5_l6-supply = <&pm8916_s4>; - vdd_l7-supply = <&pm8916_s4>; - - s3 { - regulator-min-microvolt = <1200000>; - regulator-max-microvolt = <1300000>; - }; - - s4 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <2100000>; - }; - - l1 { - regulator-min-microvolt = <1225000>; - regulator-max-microvolt = <1225000>; - }; - - l2 { - regulator-min-microvolt = <1200000>; - regulator-max-microvolt = <1200000>; - }; - - l4 { - regulator-min-microvolt = <2050000>; - regulator-max-microvolt = <2050000>; - }; - - l5 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - }; - - l6 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - }; - - l7 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - }; - - l8 { - regulator-min-microvolt = <2850000>; - regulator-max-microvolt = <2900000>; - }; - - l9 { - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - }; - - l10 { - regulator-min-microvolt = <2700000>; - regulator-max-microvolt = <2800000>; - }; - - l11 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <2950000>; - regulator-allow-set-load; - regulator-system-load = <200000>; - }; - - l12 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <2950000>; - }; - - l13 { - regulator-min-microvolt = <3075000>; - regulator-max-microvolt = <3075000>; - }; - - l14 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <3300000>; - }; - - l15 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <3300000>; - }; - - l16 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <3300000>; - }; - - l17 { - regulator-min-microvolt = <2850000>; - regulator-max-microvolt = <2850000>; - }; - - l18 { - regulator-min-microvolt = <2700000>; - regulator-max-microvolt = <2700000>; - }; -}; - -&msmgpio { +&tlmm { accel_int_default: accel-int-default-state { pins = "gpio31"; function = "gpio"; @@ -370,6 +272,13 @@ bias-pull-up; }; + sdc2_cd_default: sdc2-cd-default-state { + pins = "gpio38"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + ts_int_reset_default: ts-int-reset-default-state { pins = "gpio13", "gpio100"; function = "gpio"; diff --git a/arch/arm64/boot/dts/qcom/msm8916-asus-z00l.dts b/arch/arm64/boot/dts/qcom/msm8916-asus-z00l.dts index 91284a1d0966f1f84453abbd8b7ff898101a2005..92f695481769216eae316d4fa4ba3d4457020fed 100644 --- a/arch/arm64/boot/dts/qcom/msm8916-asus-z00l.dts +++ b/arch/arm64/boot/dts/qcom/msm8916-asus-z00l.dts @@ -13,7 +13,9 @@ chassis-type = "handset"; aliases { - serial0 = &blsp1_uart2; + mmc0 = &sdhc_1; /* eMMC */ + mmc1 = &sdhc_2; /* SD card */ + serial0 = &blsp_uart2; }; chosen { @@ -30,14 +32,14 @@ button-volume-up { label = "Volume Up"; - gpios = <&msmgpio 107 GPIO_ACTIVE_LOW>; + gpios = <&tlmm 107 GPIO_ACTIVE_LOW>; linux,code = ; debounce-interval = <15>; }; button-volume-down { label = "Volume Down"; - gpios = <&msmgpio 117 GPIO_ACTIVE_LOW>; + gpios = <&tlmm 117 GPIO_ACTIVE_LOW>; linux,code = ; debounce-interval = <15>; }; @@ -49,7 +51,7 @@ regulator-min-microvolt = <2950000>; regulator-max-microvolt = <2950000>; - gpio = <&msmgpio 87 GPIO_ACTIVE_HIGH>; + gpio = <&tlmm 87 GPIO_ACTIVE_HIGH>; enable-active-high; startup-delay-us = <200>; @@ -60,7 +62,7 @@ usb_id: usb-id { compatible = "linux,extcon-usb-gpio"; - id-gpios = <&msmgpio 110 GPIO_ACTIVE_HIGH>; + id-gpios = <&tlmm 110 GPIO_ACTIVE_HIGH>; pinctrl-names = "default"; pinctrl-0 = <&usb_id_default>; }; @@ -76,7 +78,7 @@ vdd-supply = <&pm8916_l8>; vid-supply = <&pm8916_l6>; - reset-gpios = <&msmgpio 112 GPIO_ACTIVE_LOW>; + reset-gpios = <&tlmm 112 GPIO_ACTIVE_LOW>; pinctrl-names = "default"; pinctrl-0 = <&mag_reset_default>; @@ -86,7 +88,7 @@ compatible = "invensense,mpu6515"; reg = <0x68>; - interrupt-parent = <&msmgpio>; + interrupt-parent = <&tlmm>; interrupts = <36 IRQ_TYPE_EDGE_RISING>; vdd-supply = <&pm8916_l17>; @@ -108,10 +110,10 @@ compatible = "edt,edt-ft5306"; reg = <0x38>; - interrupt-parent = <&msmgpio>; + interrupt-parent = <&tlmm>; interrupts = <13 IRQ_TYPE_EDGE_FALLING>; - reset-gpios = <&msmgpio 12 GPIO_ACTIVE_LOW>; + reset-gpios = <&tlmm 12 GPIO_ACTIVE_LOW>; vcc-supply = <&pm8916_l11>; iovcc-supply = <&pm8916_l6>; @@ -124,16 +126,19 @@ }; }; -&blsp1_uart2 { +&blsp_uart2 { status = "okay"; }; +&pm8916_rpm_regulators { + pm8916_l17: l17 { + regulator-min-microvolt = <2850000>; + regulator-max-microvolt = <2850000>; + }; +}; + &sdhc_1 { status = "okay"; - - pinctrl-names = "default", "sleep"; - pinctrl-0 = <&sdc1_clk_on &sdc1_cmd_on &sdc1_data_on>; - pinctrl-1 = <&sdc1_clk_off &sdc1_cmd_off &sdc1_data_off>; }; &sdhc_2 { @@ -141,9 +146,9 @@ vmmc-supply = <®_sd_vmmc>; pinctrl-names = "default", "sleep"; - pinctrl-0 = <&sdc2_clk_on &sdc2_cmd_on &sdc2_data_on &sdc2_cd_on>; - pinctrl-1 = <&sdc2_clk_off &sdc2_cmd_off &sdc2_data_off &sdc2_cd_off>; - cd-gpios = <&msmgpio 38 GPIO_ACTIVE_LOW>; + pinctrl-0 = <&sdc2_default &sdc2_cd_default>; + pinctrl-1 = <&sdc2_sleep &sdc2_cd_default>; + cd-gpios = <&tlmm 38 GPIO_ACTIVE_LOW>; }; &usb { @@ -163,110 +168,7 @@ compatible = "qcom,wcn3620"; }; -&smd_rpm_regulators { - vdd_l1_l2_l3-supply = <&pm8916_s3>; - vdd_l4_l5_l6-supply = <&pm8916_s4>; - vdd_l7-supply = <&pm8916_s4>; - - s3 { - regulator-min-microvolt = <1200000>; - regulator-max-microvolt = <1300000>; - }; - - s4 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <2100000>; - }; - - l1 { - regulator-min-microvolt = <1225000>; - regulator-max-microvolt = <1225000>; - }; - - l2 { - regulator-min-microvolt = <1200000>; - regulator-max-microvolt = <1200000>; - }; - - l4 { - regulator-min-microvolt = <2050000>; - regulator-max-microvolt = <2050000>; - }; - - l5 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - }; - - l6 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - }; - - l7 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - }; - - l8 { - regulator-min-microvolt = <2850000>; - regulator-max-microvolt = <2900000>; - }; - - l9 { - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - }; - - l10 { - regulator-min-microvolt = <2700000>; - regulator-max-microvolt = <2800000>; - }; - - l11 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <2950000>; - regulator-allow-set-load; - regulator-system-load = <200000>; - }; - - l12 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <2950000>; - }; - - l13 { - regulator-min-microvolt = <3075000>; - regulator-max-microvolt = <3075000>; - }; - - l14 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <3300000>; - }; - - l15 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <3300000>; - }; - - l16 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <3300000>; - }; - - l17 { - regulator-min-microvolt = <2850000>; - regulator-max-microvolt = <2850000>; - }; - - l18 { - regulator-min-microvolt = <2700000>; - regulator-max-microvolt = <2700000>; - }; -}; - -&msmgpio { +&tlmm { gpio_keys_default: gpio-keys-default-state { pins = "gpio107", "gpio117"; function = "gpio"; @@ -299,6 +201,13 @@ bias-disable; }; + sdc2_cd_default: sdc2-cd-default-state { + pins = "gpio38"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + touchscreen_default: touchscreen-default-state { touch-pins { pins = "gpio13"; diff --git a/arch/arm64/boot/dts/qcom/msm8916-gplus-fl8005a.dts b/arch/arm64/boot/dts/qcom/msm8916-gplus-fl8005a.dts index 525ec76efeeb78db7b8f336c1301064dc5f27d81..f4dbc515c47adba3cb52a092915831d87ffdacea 100644 --- a/arch/arm64/boot/dts/qcom/msm8916-gplus-fl8005a.dts +++ b/arch/arm64/boot/dts/qcom/msm8916-gplus-fl8005a.dts @@ -14,7 +14,9 @@ chassis-type = "tablet"; aliases { - serial0 = &blsp1_uart2; + mmc0 = &sdhc_1; /* eMMC */ + mmc1 = &sdhc_2; /* SD card */ + serial0 = &blsp_uart2; }; chosen { @@ -24,8 +26,8 @@ flash-led-controller { /* Actually qcom,leds-gpio-flash */ compatible = "sgmicro,sgm3140"; - enable-gpios = <&msmgpio 31 GPIO_ACTIVE_HIGH>; - flash-gpios = <&msmgpio 32 GPIO_ACTIVE_HIGH>; + enable-gpios = <&tlmm 31 GPIO_ACTIVE_HIGH>; + flash-gpios = <&tlmm 32 GPIO_ACTIVE_HIGH>; pinctrl-0 = <&camera_flash_default>; pinctrl-names = "default"; @@ -45,7 +47,7 @@ button-volume-up { label = "Volume Up"; - gpios = <&msmgpio 107 GPIO_ACTIVE_LOW>; + gpios = <&tlmm 107 GPIO_ACTIVE_LOW>; linux,code = ; }; }; @@ -59,21 +61,21 @@ led-red { function = LED_FUNCTION_CHARGING; color = ; - gpios = <&msmgpio 117 GPIO_ACTIVE_HIGH>; + gpios = <&tlmm 117 GPIO_ACTIVE_HIGH>; retain-state-suspended; }; led-green { function = LED_FUNCTION_CHARGING; color = ; - gpios = <&msmgpio 118 GPIO_ACTIVE_HIGH>; + gpios = <&tlmm 118 GPIO_ACTIVE_HIGH>; retain-state-suspended; }; }; usb_id: usb-id { compatible = "linux,extcon-usb-gpio"; - id-gpio = <&msmgpio 110 GPIO_ACTIVE_HIGH>; + id-gpio = <&tlmm 110 GPIO_ACTIVE_HIGH>; pinctrl-0 = <&usb_id_default>; pinctrl-names = "default"; }; @@ -87,10 +89,10 @@ compatible = "edt,edt-ft5406"; reg = <0x38>; - interrupt-parent = <&msmgpio>; + interrupt-parent = <&tlmm>; interrupts = <13 IRQ_TYPE_EDGE_FALLING>; - reset-gpios = <&msmgpio 12 GPIO_ACTIVE_LOW>; + reset-gpios = <&tlmm 12 GPIO_ACTIVE_LOW>; vcc-supply = <&pm8916_l17>; iovcc-supply = <&pm8916_l6>; @@ -105,7 +107,7 @@ }; }; -&blsp1_uart2 { +&blsp_uart2 { status = "okay"; }; @@ -114,24 +116,27 @@ status = "okay"; }; +&pm8916_rpm_regulators { + pm8916_l17: l17 { + regulator-min-microvolt = <2850000>; + regulator-max-microvolt = <2850000>; + }; +}; + &pm8916_vib { status = "okay"; }; &sdhc_1 { - pinctrl-0 = <&sdc1_clk_on &sdc1_cmd_on &sdc1_data_on>; - pinctrl-1 = <&sdc1_clk_off &sdc1_cmd_off &sdc1_data_off>; - pinctrl-names = "default", "sleep"; - status = "okay"; }; &sdhc_2 { - pinctrl-0 = <&sdc2_clk_on &sdc2_cmd_on &sdc2_data_on>; - pinctrl-1 = <&sdc2_clk_off &sdc2_cmd_off &sdc2_data_off>; + pinctrl-0 = <&sdc2_default &sdc2_cd_default>; + pinctrl-1 = <&sdc2_sleep &sdc2_cd_default>; pinctrl-names = "default", "sleep"; - cd-gpios = <&msmgpio 38 GPIO_ACTIVE_LOW>; + cd-gpios = <&tlmm 38 GPIO_ACTIVE_LOW>; status = "okay"; }; @@ -153,110 +158,7 @@ compatible = "qcom,wcn3620"; }; -&smd_rpm_regulators { - vdd_l1_l2_l3-supply = <&pm8916_s3>; - vdd_l4_l5_l6-supply = <&pm8916_s4>; - vdd_l7-supply = <&pm8916_s4>; - - s3 { - regulator-min-microvolt = <1200000>; - regulator-max-microvolt = <1300000>; - }; - - s4 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <2100000>; - }; - - l1 { - regulator-min-microvolt = <1225000>; - regulator-max-microvolt = <1225000>; - }; - - l2 { - regulator-min-microvolt = <1200000>; - regulator-max-microvolt = <1200000>; - }; - - l4 { - regulator-min-microvolt = <2050000>; - regulator-max-microvolt = <2050000>; - }; - - l5 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - }; - - l6 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - }; - - l7 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - }; - - l8 { - regulator-min-microvolt = <2850000>; - regulator-max-microvolt = <2900000>; - }; - - l9 { - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - }; - - l10 { - regulator-min-microvolt = <2700000>; - regulator-max-microvolt = <2800000>; - }; - - l11 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <2950000>; - regulator-system-load = <200000>; - regulator-allow-set-load; - }; - - l12 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <2950000>; - }; - - l13 { - regulator-min-microvolt = <3075000>; - regulator-max-microvolt = <3075000>; - }; - - l14 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <3300000>; - }; - - l15 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <3300000>; - }; - - l16 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <3300000>; - }; - - l17 { - regulator-min-microvolt = <2850000>; - regulator-max-microvolt = <2850000>; - }; - - l18 { - regulator-min-microvolt = <2700000>; - regulator-max-microvolt = <2700000>; - }; -}; - -&msmgpio { +&tlmm { camera_flash_default: camera-flash-default-state { pins = "gpio31", "gpio32"; function = "gpio"; @@ -278,6 +180,13 @@ bias-disable; }; + sdc2_cd_default: sdc2-cd-default-state { + pins = "gpio38"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + touchscreen_default: touchscreen-default-state { reset-pins { pins = "gpio12"; diff --git a/arch/arm64/boot/dts/qcom/msm8916-huawei-g7.dts b/arch/arm64/boot/dts/qcom/msm8916-huawei-g7.dts index 5b1bac8f51220e28cf2702359ba2de9b35fb41da..4239c8fda11b4834364ddb37a83ae054ab79dc9b 100644 --- a/arch/arm64/boot/dts/qcom/msm8916-huawei-g7.dts +++ b/arch/arm64/boot/dts/qcom/msm8916-huawei-g7.dts @@ -26,7 +26,9 @@ chassis-type = "handset"; aliases { - serial0 = &blsp1_uart2; + mmc0 = &sdhc_1; /* eMMC */ + mmc1 = &sdhc_2; /* SD card */ + serial0 = &blsp_uart2; }; chosen { @@ -43,7 +45,7 @@ button-volume-up { label = "Volume Up"; - gpios = <&msmgpio 107 GPIO_ACTIVE_LOW>; + gpios = <&tlmm 107 GPIO_ACTIVE_LOW>; linux,code = ; }; }; @@ -55,21 +57,21 @@ pinctrl-0 = <&gpio_leds_default>; led-0 { - gpios = <&msmgpio 8 GPIO_ACTIVE_HIGH>; + gpios = <&tlmm 8 GPIO_ACTIVE_HIGH>; color = ; default-state = "off"; function = LED_FUNCTION_INDICATOR; }; led-1 { - gpios = <&msmgpio 9 GPIO_ACTIVE_HIGH>; + gpios = <&tlmm 9 GPIO_ACTIVE_HIGH>; color = ; default-state = "off"; function = LED_FUNCTION_INDICATOR; }; led-2 { - gpios = <&msmgpio 10 GPIO_ACTIVE_HIGH>; + gpios = <&tlmm 10 GPIO_ACTIVE_HIGH>; color = ; default-state = "off"; function = LED_FUNCTION_INDICATOR; @@ -78,7 +80,7 @@ usb_id: usb-id { compatible = "linux,extcon-usb-gpio"; - id-gpio = <&msmgpio 117 GPIO_ACTIVE_HIGH>; + id-gpio = <&tlmm 117 GPIO_ACTIVE_HIGH>; pinctrl-names = "default"; pinctrl-0 = <&usb_id_default>; }; @@ -94,7 +96,7 @@ vdd-supply = <&pm8916_l17>; vid-supply = <&pm8916_l6>; - reset-gpios = <&msmgpio 36 GPIO_ACTIVE_LOW>; + reset-gpios = <&tlmm 36 GPIO_ACTIVE_LOW>; pinctrl-names = "default"; pinctrl-0 = <&mag_reset_default>; @@ -104,7 +106,7 @@ compatible = "kionix,kx023-1025"; reg = <0x1e>; - interrupt-parent = <&msmgpio>; + interrupt-parent = <&tlmm>; interrupts = <115 IRQ_TYPE_EDGE_RISING>; vdd-supply = <&pm8916_l17>; @@ -122,7 +124,7 @@ compatible = "avago,apds9930"; reg = <0x39>; - interrupt-parent = <&msmgpio>; + interrupt-parent = <&tlmm>; interrupts = <113 IRQ_TYPE_EDGE_FALLING>; vdd-supply = <&pm8916_l17>; @@ -146,7 +148,7 @@ regulator-name = "outp"; regulator-min-microvolt = <5400000>; regulator-max-microvolt = <5400000>; - enable-gpios = <&msmgpio 97 GPIO_ACTIVE_HIGH>; + enable-gpios = <&tlmm 97 GPIO_ACTIVE_HIGH>; regulator-active-discharge = <1>; }; @@ -154,7 +156,7 @@ regulator-name = "outn"; regulator-min-microvolt = <5400000>; regulator-max-microvolt = <5400000>; - enable-gpios = <&msmgpio 32 GPIO_ACTIVE_HIGH>; + enable-gpios = <&tlmm 32 GPIO_ACTIVE_HIGH>; regulator-active-discharge = <1>; }; }; @@ -169,7 +171,7 @@ #address-cells = <1>; #size-cells = <0>; - interrupt-parent = <&msmgpio>; + interrupt-parent = <&tlmm>; interrupts = <13 IRQ_TYPE_EDGE_FALLING>; vdd-supply = <&pm8916_l17>; @@ -199,18 +201,18 @@ compatible = "nxp,pn547", "nxp,nxp-nci-i2c"; reg = <0x28>; - interrupt-parent = <&msmgpio>; + interrupt-parent = <&tlmm>; interrupts = <21 IRQ_TYPE_EDGE_RISING>; - enable-gpios = <&msmgpio 20 GPIO_ACTIVE_HIGH>; - firmware-gpios = <&msmgpio 2 GPIO_ACTIVE_HIGH>; + enable-gpios = <&tlmm 20 GPIO_ACTIVE_HIGH>; + firmware-gpios = <&tlmm 2 GPIO_ACTIVE_HIGH>; pinctrl-names = "default"; pinctrl-0 = <&nfc_default>; }; }; -&blsp1_uart2 { +&blsp_uart2 { status = "okay"; }; @@ -218,32 +220,57 @@ status = "okay"; }; +&lpass_codec { + status = "okay"; +}; + +&pm8916_codec { + status = "okay"; + qcom,micbias-lvl = <2800>; + qcom,mbhc-vthreshold-low = <75 150 237 450 500>; + qcom,mbhc-vthreshold-high = <75 150 237 450 500>; + qcom,hphl-jack-type-normally-open; +}; + +&pm8916_l8 { + regulator-min-microvolt = <2950000>; + regulator-max-microvolt = <2950000>; +}; + &pm8916_resin { status = "okay"; linux,code = ; }; +&pm8916_rpm_regulators { + pm8916_l16: l16 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + pm8916_l17: l17 { + regulator-min-microvolt = <2850000>; + regulator-max-microvolt = <2850000>; + }; +}; + &pm8916_vib { status = "okay"; }; &sdhc_1 { status = "okay"; - - pinctrl-names = "default", "sleep"; - pinctrl-0 = <&sdc1_clk_on &sdc1_cmd_on &sdc1_data_on>; - pinctrl-1 = <&sdc1_clk_off &sdc1_cmd_off &sdc1_data_off>; }; &sdhc_2 { status = "okay"; pinctrl-names = "default", "sleep"; - pinctrl-0 = <&sdc2_clk_on &sdc2_cmd_on &sdc2_data_on &sdhc2_cd_default>; - pinctrl-1 = <&sdc2_clk_off &sdc2_cmd_off &sdc2_data_off &sdhc2_cd_default>; + pinctrl-0 = <&sdc2_default &sdc2_cd_default>; + pinctrl-1 = <&sdc2_sleep &sdc2_cd_default>; /* - * The Huawei device tree sets cd-gpios = <&msmgpio 38 GPIO_ACTIVE_HIGH>. + * The Huawei device tree sets cd-gpios = <&tlmm 38 GPIO_ACTIVE_HIGH>. * However, gpio38 does not change its state when inserting/removing the * SD card, it's just low all the time. The Huawei kernel seems to use * polling for SD card detection instead. @@ -255,7 +282,7 @@ * Maybe Huawei decided to replace the second SIM card slot with the * SD card slot and forgot to re-route to gpio38. */ - cd-gpios = <&msmgpio 56 GPIO_ACTIVE_LOW>; + cd-gpios = <&tlmm 56 GPIO_ACTIVE_LOW>; }; &sound { @@ -268,8 +295,8 @@ "AMIC3", "MIC BIAS External1"; pinctrl-names = "default", "sleep"; - pinctrl-0 = <&cdc_pdm_lines_act>; - pinctrl-1 = <&cdc_pdm_lines_sus>; + pinctrl-0 = <&cdc_pdm_default>; + pinctrl-1 = <&cdc_pdm_sleep>; primary-dai-link { link-name = "WCD"; @@ -277,7 +304,7 @@ sound-dai = <&lpass MI2S_PRIMARY>; }; codec { - sound-dai = <&lpass_codec 0>, <&wcd_codec 0>; + sound-dai = <&lpass_codec 0>, <&pm8916_codec 0>; }; }; @@ -287,7 +314,7 @@ sound-dai = <&lpass MI2S_TERTIARY>; }; codec { - sound-dai = <&lpass_codec 1>, <&wcd_codec 1>; + sound-dai = <&lpass_codec 1>, <&pm8916_codec 1>; }; }; }; @@ -301,13 +328,6 @@ extcon = <&usb_id>; }; -&wcd_codec { - qcom,micbias-lvl = <2800>; - qcom,mbhc-vthreshold-low = <75 150 237 450 500>; - qcom,mbhc-vthreshold-high = <75 150 237 450 500>; - qcom,hphl-jack-type-normally-open; -}; - &wcnss { status = "okay"; }; @@ -316,110 +336,7 @@ compatible = "qcom,wcn3620"; }; -&smd_rpm_regulators { - vdd_l1_l2_l3-supply = <&pm8916_s3>; - vdd_l4_l5_l6-supply = <&pm8916_s4>; - vdd_l7-supply = <&pm8916_s4>; - - s3 { - regulator-min-microvolt = <1200000>; - regulator-max-microvolt = <1300000>; - }; - - s4 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <2100000>; - }; - - l1 { - regulator-min-microvolt = <1225000>; - regulator-max-microvolt = <1225000>; - }; - - l2 { - regulator-min-microvolt = <1200000>; - regulator-max-microvolt = <1200000>; - }; - - l4 { - regulator-min-microvolt = <2050000>; - regulator-max-microvolt = <2050000>; - }; - - l5 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - }; - - l6 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - }; - - l7 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - }; - - l8 { - regulator-min-microvolt = <2950000>; - regulator-max-microvolt = <2950000>; - }; - - l9 { - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - }; - - l10 { - regulator-min-microvolt = <2700000>; - regulator-max-microvolt = <2800000>; - }; - - l11 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <2950000>; - regulator-allow-set-load; - regulator-system-load = <200000>; - }; - - l12 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <2950000>; - }; - - l13 { - regulator-min-microvolt = <3075000>; - regulator-max-microvolt = <3075000>; - }; - - l14 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <3300000>; - }; - - l15 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <3300000>; - }; - - l16 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - }; - - l17 { - regulator-min-microvolt = <2850000>; - regulator-max-microvolt = <2850000>; - }; - - l18 { - regulator-min-microvolt = <2700000>; - regulator-max-microvolt = <2700000>; - }; -}; - -&msmgpio { +&tlmm { accel_irq_default: accel-irq-default-state { pins = "gpio115"; function = "gpio"; @@ -476,7 +393,7 @@ bias-disable; }; - sdhc2_cd_default: sdhc2-cd-default-state { + sdc2_cd_default: sdc2-cd-default-state { pins = "gpio56"; function = "gpio"; diff --git a/arch/arm64/boot/dts/qcom/msm8916-longcheer-l8150.dts b/arch/arm64/boot/dts/qcom/msm8916-longcheer-l8150.dts index f1dd625e1822782e7ca874f80891c12f1e361a4d..97262b8519b36c90a4be37ad50021822dc4e0c49 100644 --- a/arch/arm64/boot/dts/qcom/msm8916-longcheer-l8150.dts +++ b/arch/arm64/boot/dts/qcom/msm8916-longcheer-l8150.dts @@ -14,7 +14,9 @@ chassis-type = "handset"; aliases { - serial0 = &blsp1_uart2; + mmc0 = &sdhc_1; /* eMMC */ + mmc1 = &sdhc_2; /* SD card */ + serial0 = &blsp_uart2; }; chosen { @@ -41,7 +43,7 @@ button-volume-up { label = "Volume Up"; - gpios = <&msmgpio 107 GPIO_ACTIVE_LOW>; + gpios = <&tlmm 107 GPIO_ACTIVE_LOW>; linux,code = ; }; }; @@ -53,7 +55,7 @@ regulator-min-microvolt = <2800000>; regulator-max-microvolt = <2800000>; - gpio = <&msmgpio 17 GPIO_ACTIVE_HIGH>; + gpio = <&tlmm 17 GPIO_ACTIVE_HIGH>; enable-active-high; pinctrl-names = "default"; @@ -62,8 +64,8 @@ flash-led-controller { compatible = "sgmicro,sgm3140"; - flash-gpios = <&msmgpio 31 GPIO_ACTIVE_HIGH>; - enable-gpios = <&msmgpio 32 GPIO_ACTIVE_HIGH>; + flash-gpios = <&tlmm 31 GPIO_ACTIVE_HIGH>; + enable-gpios = <&tlmm 32 GPIO_ACTIVE_HIGH>; pinctrl-names = "default"; pinctrl-0 = <&camera_flash_default>; @@ -122,7 +124,7 @@ * to the BMC156. However, there are two pads next to the chip * that can be shorted to make it work if needed. * - * interrupt-parent = <&msmgpio>; + * interrupt-parent = <&tlmm>; * interrupts = <116 IRQ_TYPE_EDGE_RISING>; */ @@ -141,7 +143,7 @@ compatible = "bosch,bmc156_magn"; reg = <0x12>; - interrupt-parent = <&msmgpio>; + interrupt-parent = <&tlmm>; interrupts = <113 IRQ_TYPE_EDGE_RISING>; pinctrl-names = "default"; @@ -156,7 +158,7 @@ reg = <0x23>; proximity-near-level = <75>; - interrupt-parent = <&msmgpio>; + interrupt-parent = <&tlmm>; interrupts = <115 IRQ_TYPE_EDGE_FALLING>; pinctrl-names = "default"; @@ -170,7 +172,7 @@ compatible = "bosch,bmg160"; reg = <0x68>; - interrupt-parent = <&msmgpio>; + interrupt-parent = <&tlmm>; interrupts = <23 IRQ_TYPE_EDGE_RISING>, <22 IRQ_TYPE_EDGE_RISING>; @@ -191,7 +193,7 @@ #address-cells = <1>; #size-cells = <0>; - interrupt-parent = <&msmgpio>; + interrupt-parent = <&tlmm>; interrupts = <13 IRQ_TYPE_EDGE_FALLING>; vdd-supply = <®_ctp>; @@ -214,7 +216,7 @@ }; }; -&blsp1_uart2 { +&blsp_uart2 { status = "okay"; }; @@ -223,6 +225,13 @@ linux,code = ; }; +&pm8916_rpm_regulators { + pm8916_l17: l17 { + regulator-min-microvolt = <2850000>; + regulator-max-microvolt = <2850000>; + }; +}; + &pm8916_usbin { status = "okay"; }; @@ -233,19 +242,10 @@ &sdhc_1 { status = "okay"; - - pinctrl-names = "default", "sleep"; - pinctrl-0 = <&sdc1_clk_on &sdc1_cmd_on &sdc1_data_on>; - pinctrl-1 = <&sdc1_clk_off &sdc1_cmd_off &sdc1_data_off>; }; &sdhc_2 { status = "okay"; - - pinctrl-names = "default", "sleep"; - pinctrl-0 = <&sdc2_clk_on &sdc2_cmd_on &sdc2_data_on>; - pinctrl-1 = <&sdc2_clk_off &sdc2_cmd_off &sdc2_data_off>; - non-removable; }; @@ -267,110 +267,7 @@ compatible = "qcom,wcn3620"; }; -&smd_rpm_regulators { - vdd_l1_l2_l3-supply = <&pm8916_s3>; - vdd_l4_l5_l6-supply = <&pm8916_s4>; - vdd_l7-supply = <&pm8916_s4>; - - s3 { - regulator-min-microvolt = <1200000>; - regulator-max-microvolt = <1300000>; - }; - - s4 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <2100000>; - }; - - l1 { - regulator-min-microvolt = <1225000>; - regulator-max-microvolt = <1225000>; - }; - - l2 { - regulator-min-microvolt = <1200000>; - regulator-max-microvolt = <1200000>; - }; - - l4 { - regulator-min-microvolt = <2050000>; - regulator-max-microvolt = <2050000>; - }; - - l5 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - }; - - l6 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - }; - - l7 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - }; - - l8 { - regulator-min-microvolt = <2850000>; - regulator-max-microvolt = <2900000>; - }; - - l9 { - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - }; - - l10 { - regulator-min-microvolt = <2700000>; - regulator-max-microvolt = <2800000>; - }; - - l11 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <2950000>; - regulator-allow-set-load; - regulator-system-load = <200000>; - }; - - l12 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <2950000>; - }; - - l13 { - regulator-min-microvolt = <3075000>; - regulator-max-microvolt = <3075000>; - }; - - l14 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <3300000>; - }; - - l15 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <3300000>; - }; - - l16 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <3300000>; - }; - - l17 { - regulator-min-microvolt = <2850000>; - regulator-max-microvolt = <2850000>; - }; - - l18 { - regulator-min-microvolt = <2700000>; - regulator-max-microvolt = <2700000>; - }; -}; - -&msmgpio { +&tlmm { accel_int_default: accel-int-default-state { pins = "gpio116"; function = "gpio"; diff --git a/arch/arm64/boot/dts/qcom/msm8916-longcheer-l8910.dts b/arch/arm64/boot/dts/qcom/msm8916-longcheer-l8910.dts index b79e80913af9fb86b75e0263fea7104acc19f60b..9757182fba3e64b970d5e35592dd3ab20c6a4e1a 100644 --- a/arch/arm64/boot/dts/qcom/msm8916-longcheer-l8910.dts +++ b/arch/arm64/boot/dts/qcom/msm8916-longcheer-l8910.dts @@ -13,13 +13,30 @@ chassis-type = "handset"; aliases { - serial0 = &blsp1_uart2; + mmc0 = &sdhc_1; /* eMMC */ + mmc1 = &sdhc_2; /* SD card */ + serial0 = &blsp_uart2; }; chosen { stdout-path = "serial0"; }; + flash-led-controller { + compatible = "ocs,ocp8110"; + enable-gpios = <&tlmm 49 GPIO_ACTIVE_HIGH>; + flash-gpios = <&tlmm 119 GPIO_ACTIVE_HIGH>; + + pinctrl-0 = <&camera_front_flash_default>; + pinctrl-names = "default"; + + flash_led: led { + function = LED_FUNCTION_FLASH; + color = ; + flash-max-timeout-us = <250000>; + }; + }; + gpio-keys { compatible = "gpio-keys"; @@ -30,7 +47,7 @@ button-volume-up { label = "Volume Up"; - gpios = <&msmgpio 107 GPIO_ACTIVE_LOW>; + gpios = <&tlmm 107 GPIO_ACTIVE_LOW>; linux,code = ; }; }; @@ -39,7 +56,7 @@ compatible = "gpio-leds"; led-0 { - gpios = <&msmgpio 17 GPIO_ACTIVE_HIGH>; + gpios = <&tlmm 17 GPIO_ACTIVE_HIGH>; color = ; default-state = "off"; function = LED_FUNCTION_KBD_BACKLIGHT; @@ -51,7 +68,7 @@ usb_id: usb-id { compatible = "linux,extcon-usb-gpio"; - id-gpio = <&msmgpio 110 GPIO_ACTIVE_HIGH>; + id-gpio = <&tlmm 110 GPIO_ACTIVE_HIGH>; pinctrl-names = "default"; pinctrl-0 = <&usb_id_default>; }; @@ -67,7 +84,7 @@ vdd-supply = <&pm8916_l17>; vid-supply = <&pm8916_l6>; - reset-gpios = <&msmgpio 111 GPIO_ACTIVE_LOW>; + reset-gpios = <&tlmm 111 GPIO_ACTIVE_LOW>; pinctrl-names = "default"; pinctrl-0 = <&mag_reset_default>; @@ -86,7 +103,7 @@ }; }; -&blsp1_uart2 { +&blsp_uart2 { status = "okay"; }; @@ -95,26 +112,29 @@ linux,code = ; }; +&pm8916_rpm_regulators { + pm8916_l17: l17 { + regulator-min-microvolt = <2850000>; + regulator-max-microvolt = <2850000>; + }; +}; + &pm8916_vib { status = "okay"; }; &sdhc_1 { status = "okay"; - - pinctrl-names = "default", "sleep"; - pinctrl-0 = <&sdc1_clk_on &sdc1_cmd_on &sdc1_data_on>; - pinctrl-1 = <&sdc1_clk_off &sdc1_cmd_off &sdc1_data_off>; }; &sdhc_2 { status = "okay"; pinctrl-names = "default", "sleep"; - pinctrl-0 = <&sdc2_clk_on &sdc2_cmd_on &sdc2_data_on &sdc2_cd_on>; - pinctrl-1 = <&sdc2_clk_off &sdc2_cmd_off &sdc2_data_off &sdc2_cd_off>; + pinctrl-0 = <&sdc2_default &sdc2_cd_default>; + pinctrl-1 = <&sdc2_sleep &sdc2_cd_default>; - cd-gpios = <&msmgpio 38 GPIO_ACTIVE_LOW>; + cd-gpios = <&tlmm 38 GPIO_ACTIVE_LOW>; }; &usb { @@ -134,110 +154,7 @@ compatible = "qcom,wcn3620"; }; -&smd_rpm_regulators { - vdd_l1_l2_l3-supply = <&pm8916_s3>; - vdd_l4_l5_l6-supply = <&pm8916_s4>; - vdd_l7-supply = <&pm8916_s4>; - - s3 { - regulator-min-microvolt = <1200000>; - regulator-max-microvolt = <1300000>; - }; - - s4 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <2100000>; - }; - - l1 { - regulator-min-microvolt = <1225000>; - regulator-max-microvolt = <1225000>; - }; - - l2 { - regulator-min-microvolt = <1200000>; - regulator-max-microvolt = <1200000>; - }; - - l4 { - regulator-min-microvolt = <2050000>; - regulator-max-microvolt = <2050000>; - }; - - l5 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - }; - - l6 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - }; - - l7 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - }; - - l8 { - regulator-min-microvolt = <2850000>; - regulator-max-microvolt = <2900000>; - }; - - l9 { - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - }; - - l10 { - regulator-min-microvolt = <2700000>; - regulator-max-microvolt = <2800000>; - }; - - l11 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <2950000>; - regulator-allow-set-load; - regulator-system-load = <200000>; - }; - - l12 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <2950000>; - }; - - l13 { - regulator-min-microvolt = <3075000>; - regulator-max-microvolt = <3075000>; - }; - - l14 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <3300000>; - }; - - l15 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <3300000>; - }; - - l16 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <3300000>; - }; - - l17 { - regulator-min-microvolt = <2850000>; - regulator-max-microvolt = <2850000>; - }; - - l18 { - regulator-min-microvolt = <2700000>; - regulator-max-microvolt = <2700000>; - }; -}; - -&msmgpio { +&tlmm { button_backlight_default: button-backlight-default-state { pins = "gpio17"; function = "gpio"; @@ -246,6 +163,13 @@ bias-disable; }; + camera_front_flash_default: camera-front-flash-default-state { + pins = "gpio49", "gpio119"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + gpio_keys_default: gpio-keys-default-state { pins = "gpio107"; function = "gpio"; @@ -262,6 +186,13 @@ bias-disable; }; + sdc2_cd_default: sdc2-cd-default-state { + pins = "gpio38"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + usb_id_default: usb-id-default-state { pins = "gpio110"; function = "gpio"; diff --git a/arch/arm64/boot/dts/qcom/msm8916-mtp.dts b/arch/arm64/boot/dts/qcom/msm8916-mtp.dts index 7c0ceb3cff45eb176129804a62002eda513f123c..438eb1faee1d8bf62e9d94b469f37cab722d206b 100644 --- a/arch/arm64/boot/dts/qcom/msm8916-mtp.dts +++ b/arch/arm64/boot/dts/qcom/msm8916-mtp.dts @@ -12,7 +12,7 @@ compatible = "qcom,msm8916-mtp", "qcom,msm8916-mtp/1", "qcom,msm8916"; aliases { - serial0 = &blsp1_uart2; + serial0 = &blsp_uart2; usid0 = &pm8916_0; }; @@ -21,6 +21,6 @@ }; }; -&blsp1_uart2 { +&blsp_uart2 { status = "okay"; }; diff --git a/arch/arm64/boot/dts/qcom/msm8916-pins.dtsi b/arch/arm64/boot/dts/qcom/msm8916-pins.dtsi deleted file mode 100644 index 33dfcf318a81bebb3e619c7c6696d64f08d25066..0000000000000000000000000000000000000000 --- a/arch/arm64/boot/dts/qcom/msm8916-pins.dtsi +++ /dev/null @@ -1,582 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. - */ - -&msmgpio { - - blsp1_uart1_default: blsp1-uart1-default-state { - /* TX, RX, CTS_N, RTS_N */ - pins = "gpio0", "gpio1", "gpio2", "gpio3"; - function = "blsp_uart1"; - - drive-strength = <16>; - bias-disable; - }; - - blsp1_uart1_sleep: blsp1-uart1-sleep-state { - pins = "gpio0", "gpio1", "gpio2", "gpio3"; - function = "gpio"; - - drive-strength = <2>; - bias-pull-down; - }; - - blsp1_uart2_default: blsp1-uart2-default-state { - pins = "gpio4", "gpio5"; - function = "blsp_uart2"; - - drive-strength = <16>; - bias-disable; - }; - - blsp1_uart2_sleep: blsp1-uart2-sleep-state { - pins = "gpio4", "gpio5"; - function = "gpio"; - - drive-strength = <2>; - bias-pull-down; - }; - - spi1_default: spi1-default-state { - spi-pins { - pins = "gpio0", "gpio1", "gpio3"; - function = "blsp_spi1"; - - drive-strength = <12>; - bias-disable; - }; - cs-pins { - pins = "gpio2"; - function = "gpio"; - - drive-strength = <16>; - bias-disable; - output-high; - }; - }; - - spi1_sleep: spi1-sleep-state { - pins = "gpio0", "gpio1", "gpio2", "gpio3"; - function = "gpio"; - - drive-strength = <2>; - bias-pull-down; - }; - - spi2_default: spi2-default-state { - spi-pins { - pins = "gpio4", "gpio5", "gpio7"; - function = "blsp_spi2"; - - drive-strength = <12>; - bias-disable; - }; - cs-pins { - pins = "gpio6"; - function = "gpio"; - - drive-strength = <16>; - bias-disable; - output-high; - }; - }; - - spi2_sleep: spi2-sleep-state { - pins = "gpio4", "gpio5", "gpio6", "gpio7"; - function = "gpio"; - - drive-strength = <2>; - bias-pull-down; - }; - - spi3_default: spi3-default-state { - spi-pins { - pins = "gpio8", "gpio9", "gpio11"; - function = "blsp_spi3"; - - drive-strength = <12>; - bias-disable; - }; - cs-pins { - pins = "gpio10"; - function = "gpio"; - - drive-strength = <16>; - bias-disable; - output-high; - }; - }; - - spi3_sleep: spi3-sleep-state { - pins = "gpio8", "gpio9", "gpio10", "gpio11"; - function = "gpio"; - - drive-strength = <2>; - bias-pull-down; - }; - - spi4_default: spi4-default-state { - spi-pins { - pins = "gpio12", "gpio13", "gpio15"; - function = "blsp_spi4"; - - drive-strength = <12>; - bias-disable; - }; - cs-pins { - pins = "gpio14"; - function = "gpio"; - - drive-strength = <16>; - bias-disable; - output-high; - }; - }; - - spi4_sleep: spi4-sleep-state { - pins = "gpio12", "gpio13", "gpio14", "gpio15"; - function = "gpio"; - - drive-strength = <2>; - bias-pull-down; - }; - - spi5_default: spi5-default-state { - spi-pins { - pins = "gpio16", "gpio17", "gpio19"; - function = "blsp_spi5"; - - drive-strength = <12>; - bias-disable; - }; - cs-pins { - pins = "gpio18"; - function = "gpio"; - - drive-strength = <16>; - bias-disable; - output-high; - }; - }; - - spi5_sleep: spi5-sleep-state { - pins = "gpio16", "gpio17", "gpio18", "gpio19"; - function = "gpio"; - - drive-strength = <2>; - bias-pull-down; - }; - - spi6_default: spi6-default-state { - spi-pins { - pins = "gpio20", "gpio21", "gpio23"; - function = "blsp_spi6"; - - drive-strength = <12>; - bias-disable; - }; - cs-pins { - pins = "gpio22"; - function = "gpio"; - - drive-strength = <16>; - bias-disable; - output-high; - }; - }; - - spi6_sleep: spi6-sleep-state { - pins = "gpio20", "gpio21", "gpio22", "gpio23"; - function = "gpio"; - - drive-strength = <2>; - bias-pull-down; - }; - - i2c1_default: i2c1-default-state { - pins = "gpio2", "gpio3"; - function = "blsp_i2c1"; - - drive-strength = <2>; - bias-disable; - }; - - i2c1_sleep: i2c1-sleep-state { - pins = "gpio2", "gpio3"; - function = "gpio"; - - drive-strength = <2>; - bias-disable; - }; - - i2c2_default: i2c2-default-state { - pins = "gpio6", "gpio7"; - function = "blsp_i2c2"; - - drive-strength = <2>; - bias-disable; - }; - - i2c2_sleep: i2c2-sleep-state { - pins = "gpio6", "gpio7"; - function = "gpio"; - - drive-strength = <2>; - bias-disable; - }; - - i2c3_default: i2c3-default-state { - pins = "gpio10", "gpio11"; - function = "blsp_i2c3"; - - drive-strength = <2>; - bias-disable; - }; - - i2c3_sleep: i2c3-sleep-state { - pins = "gpio10", "gpio11"; - function = "gpio"; - - drive-strength = <2>; - bias-disable; - }; - - i2c4_default: i2c4-default-state { - pins = "gpio14", "gpio15"; - function = "blsp_i2c4"; - - drive-strength = <2>; - bias-disable; - }; - - i2c4_sleep: i2c4-sleep-state { - pins = "gpio14", "gpio15"; - function = "gpio"; - - drive-strength = <2>; - bias-disable; - }; - - i2c5_default: i2c5-default-state { - pins = "gpio18", "gpio19"; - function = "blsp_i2c5"; - - drive-strength = <2>; - bias-disable; - }; - - i2c5_sleep: i2c5-sleep-state { - pins = "gpio18", "gpio19"; - function = "gpio"; - - drive-strength = <2>; - bias-disable; - }; - - i2c6_default: i2c6-default-state { - pins = "gpio22", "gpio23"; - function = "blsp_i2c6"; - - drive-strength = <2>; - bias-disable; - }; - - i2c6_sleep: i2c6-sleep-state { - pins = "gpio22", "gpio23"; - function = "gpio"; - - drive-strength = <2>; - bias-disable; - }; - - pmx-sdc1-clk-state { - sdc1_clk_on: clk-on-pins { - pins = "sdc1_clk"; - - bias-disable; - drive-strength = <16>; - }; - sdc1_clk_off: clk-off-pins { - pins = "sdc1_clk"; - - bias-disable; - drive-strength = <2>; - }; - }; - - pmx-sdc1-cmd-state { - sdc1_cmd_on: cmd-on-pins { - pins = "sdc1_cmd"; - - bias-pull-up; - drive-strength = <10>; - }; - sdc1_cmd_off: cmd-off-pins { - pins = "sdc1_cmd"; - - bias-pull-up; - drive-strength = <2>; - }; - }; - - pmx-sdc1-data-state { - sdc1_data_on: data-on-pins { - pins = "sdc1_data"; - - bias-pull-up; - drive-strength = <10>; - }; - sdc1_data_off: data-off-pins { - pins = "sdc1_data"; - - bias-pull-up; - drive-strength = <2>; - }; - }; - - pmx-sdc2-clk-state { - sdc2_clk_on: clk-on-pins { - pins = "sdc2_clk"; - - bias-disable; - drive-strength = <16>; - }; - sdc2_clk_off: clk-off-pins { - pins = "sdc2_clk"; - - bias-disable; - drive-strength = <2>; - }; - }; - - pmx-sdc2-cmd-state { - sdc2_cmd_on: cmd-on-pins { - pins = "sdc2_cmd"; - - bias-pull-up; - drive-strength = <10>; - }; - sdc2_cmd_off: cmd-off-pins { - pins = "sdc2_cmd"; - - bias-pull-up; - drive-strength = <2>; - }; - }; - - pmx-sdc2-data-state { - sdc2_data_on: data-on-pins { - pins = "sdc2_data"; - - bias-pull-up; - drive-strength = <10>; - }; - sdc2_data_off: data-off-pins { - pins = "sdc2_data"; - - bias-pull-up; - drive-strength = <2>; - }; - }; - - pmx-sdc2-cd-pin-state { - sdc2_cd_on: cd-on-pins { - pins = "gpio38"; - function = "gpio"; - - drive-strength = <2>; - bias-pull-up; - }; - sdc2_cd_off: cd-off-pins { - pins = "gpio38"; - function = "gpio"; - - drive-strength = <2>; - bias-disable; - }; - }; - - cdc-pdm-lines-state { - cdc_pdm_lines_act: pdm-lines-on-pins { - pins = "gpio63", "gpio64", "gpio65", "gpio66", - "gpio67", "gpio68"; - function = "cdc_pdm0"; - - drive-strength = <8>; - bias-disable; - }; - cdc_pdm_lines_sus: pdm-lines-off-pins { - pins = "gpio63", "gpio64", "gpio65", "gpio66", - "gpio67", "gpio68"; - function = "cdc_pdm0"; - - drive-strength = <2>; - bias-pull-down; - }; - }; - - ext-pri-tlmm-lines-state { - ext_pri_tlmm_lines_act: ext-pa-on-pins { - pins = "gpio113", "gpio114", "gpio115", "gpio116"; - function = "pri_mi2s"; - - drive-strength = <8>; - bias-disable; - }; - ext_pri_tlmm_lines_sus: ext-pa-off-pins { - pins = "gpio113", "gpio114", "gpio115", "gpio116"; - function = "pri_mi2s"; - - drive-strength = <2>; - bias-disable; - }; - }; - - ext-pri-ws-line-state { - ext_pri_ws_act: ext-pa-on-pins { - pins = "gpio110"; - function = "pri_mi2s_ws"; - - drive-strength = <8>; - bias-disable; - }; - ext_pri_ws_sus: ext-pa-off-pins { - pins = "gpio110"; - function = "pri_mi2s_ws"; - - drive-strength = <2>; - bias-disable; - }; - }; - - ext-mclk-tlmm-lines-state { - ext_mclk_tlmm_lines_act: mclk-lines-on-pins { - pins = "gpio116"; - function = "pri_mi2s"; - - drive-strength = <8>; - bias-disable; - }; - ext_mclk_tlmm_lines_sus: mclk-lines-off-pins { - pins = "gpio116"; - function = "pri_mi2s"; - - drive-strength = <2>; - bias-disable; - }; - }; - - /* secondary Mi2S */ - ext-sec-tlmm-lines-state { - ext_sec_tlmm_lines_act: tlmm-lines-on-pins { - pins = "gpio112", "gpio117", "gpio118", "gpio119"; - function = "sec_mi2s"; - - drive-strength = <8>; - bias-disable; - }; - ext_sec_tlmm_lines_sus: tlmm-lines-off-pins { - pins = "gpio112", "gpio117", "gpio118", "gpio119"; - function = "sec_mi2s"; - - drive-strength = <2>; - bias-disable; - }; - }; - - cdc_dmic_lines_act: cdc-dmic-lines-on-state { - clk-pins { - pins = "gpio0"; - function = "dmic0_clk"; - - drive-strength = <8>; - }; - data-pins { - pins = "gpio1"; - function = "dmic0_data"; - - drive-strength = <8>; - }; - }; - cdc_dmic_lines_sus: cdc-dmic-lines-off-state { - clk-pins { - pins = "gpio0"; - function = "dmic0_clk"; - - drive-strength = <2>; - bias-disable; - }; - data-pins { - pins = "gpio1"; - function = "dmic0_data"; - - drive-strength = <2>; - bias-disable; - }; - }; - - wcnss_pin_a: wcnss-active-state { - pins = "gpio40", "gpio41", "gpio42", "gpio43", "gpio44"; - function = "wcss_wlan"; - - drive-strength = <6>; - bias-pull-up; - }; - - cci0_default: cci0-default-state { - pins = "gpio29", "gpio30"; - function = "cci_i2c"; - - drive-strength = <16>; - bias-disable; - }; - - camera_front_default: camera-front-default-state { - pwdn-pins { - pins = "gpio33"; - function = "gpio"; - - drive-strength = <16>; - bias-disable; - }; - rst-pins { - pins = "gpio28"; - function = "gpio"; - - drive-strength = <16>; - bias-disable; - }; - mclk1-pins { - pins = "gpio27"; - function = "cam_mclk1"; - - drive-strength = <16>; - bias-disable; - }; - }; - - camera_rear_default: camera-rear-default-state { - pwdn-pins { - pins = "gpio34"; - function = "gpio"; - - drive-strength = <16>; - bias-disable; - }; - rst-pins { - pins = "gpio35"; - function = "gpio"; - - drive-strength = <16>; - bias-disable; - }; - mclk0-pins { - pins = "gpio26"; - function = "cam_mclk0"; - - drive-strength = <16>; - bias-disable; - }; - }; -}; diff --git a/arch/arm64/boot/dts/qcom/msm8916-pm8916.dtsi b/arch/arm64/boot/dts/qcom/msm8916-pm8916.dtsi index 6eb5e0a39510026b2321a1420a6cc45e9286a943..b1a7eafbee31f7a5ef957597237e56644ffd45cf 100644 --- a/arch/arm64/boot/dts/qcom/msm8916-pm8916.dtsi +++ b/arch/arm64/boot/dts/qcom/msm8916-pm8916.dtsi @@ -1,4 +1,12 @@ // SPDX-License-Identifier: GPL-2.0-only +/* + * msm8916-pm8916.dtsi describes common properties (e.g. regulator connections) + * that apply to most devices that make use of the MSM8916 SoC and PM8916 PMIC. + * Many regulators have a fixed purpose in the original reference design and + * were rarely re-used for different purposes. Devices that deviate from the + * typical reference design should not make use of this include and instead add + * the necessary properties in the board-specific device tree. + */ #include "msm8916.dtsi" #include "pm8916.dtsi" @@ -7,12 +15,12 @@ vdda-supply = <&pm8916_l2>; }; -&dsi0 { +&mdss_dsi0 { vdda-supply = <&pm8916_l2>; vddio-supply = <&pm8916_l6>; }; -&dsi_phy0 { +&mdss_dsi0_phy { vddio-supply = <&pm8916_l6>; }; @@ -20,6 +28,12 @@ pll-supply = <&pm8916_l7>; }; +&pm8916_codec { + vdd-cdc-io-supply = <&pm8916_l5>; + vdd-cdc-tx-rx-cx-supply = <&pm8916_l5>; + vdd-micbias-supply = <&pm8916_l13>; +}; + &sdhc_1 { vmmc-supply = <&pm8916_l8>; vqmmc-supply = <&pm8916_l5>; @@ -47,30 +61,97 @@ }; &rpm_requests { - smd_rpm_regulators: regulators { + pm8916_rpm_regulators: regulators { compatible = "qcom,rpm-pm8916-regulators"; + vdd_l1_l2_l3-supply = <&pm8916_s3>; + vdd_l4_l5_l6-supply = <&pm8916_s4>; + vdd_l7-supply = <&pm8916_s4>; /* pm8916_s1 is managed by rpmpd (MSM8916_VDDCX) */ - pm8916_s3: s3 {}; - pm8916_s4: s4 {}; - pm8916_l1: l1 {}; - pm8916_l2: l2 {}; + pm8916_s3: s3 { + regulator-min-microvolt = <1250000>; + regulator-max-microvolt = <1350000>; + regulator-always-on; /* Needed for L2 */ + }; + + pm8916_s4: s4 { + regulator-min-microvolt = <1850000>; + regulator-max-microvolt = <2150000>; + regulator-always-on; /* Needed for L5/L7 */ + }; + + /* + * Some of the regulators are unused or managed by another + * processor (e.g. the modem). We should still define nodes for + * them to ensure the vote from the application processor can be + * dropped in case the regulators are already on during boot. + * + * The labels for these nodes are omitted on purpose because + * boards should configure a proper voltage before using them. + */ + l1 {}; + + pm8916_l2: l2 { + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-always-on; /* Needed for LPDDR RAM */ + }; + /* pm8916_l3 is managed by rpmpd (MSM8916_VDDMX) */ - pm8916_l4: l4 {}; - pm8916_l5: l5 {}; - pm8916_l6: l6 {}; - pm8916_l7: l7 {}; - pm8916_l8: l8 {}; - pm8916_l9: l9 {}; - pm8916_l10: l10 {}; - pm8916_l11: l11 {}; - pm8916_l12: l12 {}; - pm8916_l13: l13 {}; - pm8916_l14: l14 {}; - pm8916_l15: l15 {}; - pm8916_l16: l16 {}; - pm8916_l17: l17 {}; - pm8916_l18: l18 {}; + + l4 {}; + + pm8916_l5: l5 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; /* Needed for most digital I/O */ + }; + + pm8916_l6: l6 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + pm8916_l7: l7 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; /* Needed for CPU PLL */ + }; + + pm8916_l8: l8 { + regulator-min-microvolt = <2900000>; + regulator-max-microvolt = <2900000>; + }; + + pm8916_l9: l9 { + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + l10 {}; + + pm8916_l11: l11 { + regulator-min-microvolt = <2950000>; + regulator-max-microvolt = <2950000>; + regulator-allow-set-load; + regulator-system-load = <200000>; + }; + + pm8916_l12: l12 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <2950000>; + }; + + pm8916_l13: l13 { + regulator-min-microvolt = <3075000>; + regulator-max-microvolt = <3075000>; + }; + + l14 {}; + l15 {}; + l16 {}; + l17 {}; + l18 {}; }; }; diff --git a/arch/arm64/boot/dts/qcom/msm8916-samsung-a2015-common.dtsi b/arch/arm64/boot/dts/qcom/msm8916-samsung-a2015-common.dtsi index 16d67749960e0471a236d030526bdcb9e4f62da0..019bf73178fa603db76f58c3a7e63c4f55f1f762 100644 --- a/arch/arm64/boot/dts/qcom/msm8916-samsung-a2015-common.dtsi +++ b/arch/arm64/boot/dts/qcom/msm8916-samsung-a2015-common.dtsi @@ -8,7 +8,9 @@ / { aliases { - serial0 = &blsp1_uart2; + mmc0 = &sdhc_1; /* eMMC */ + mmc1 = &sdhc_2; /* SD card */ + serial0 = &blsp_uart2; }; chosen { @@ -44,13 +46,13 @@ button-volume-up { label = "Volume Up"; - gpios = <&msmgpio 107 GPIO_ACTIVE_LOW>; + gpios = <&tlmm 107 GPIO_ACTIVE_LOW>; linux,code = ; }; button-home { label = "Home"; - gpios = <&msmgpio 109 GPIO_ACTIVE_LOW>; + gpios = <&tlmm 109 GPIO_ACTIVE_LOW>; linux,code = ; }; }; @@ -65,7 +67,7 @@ event-hall-sensor { label = "Hall Effect Sensor"; - gpios = <&msmgpio 52 GPIO_ACTIVE_LOW>; + gpios = <&tlmm 52 GPIO_ACTIVE_LOW>; linux,input-type = ; linux,code = ; linux,can-disable; @@ -83,7 +85,7 @@ regulator-min-microvolt = <3000000>; regulator-max-microvolt = <3000000>; - gpio = <&msmgpio 76 GPIO_ACTIVE_HIGH>; + gpio = <&tlmm 76 GPIO_ACTIVE_HIGH>; enable-active-high; pinctrl-names = "default"; @@ -96,7 +98,7 @@ regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; - gpio = <&msmgpio 73 GPIO_ACTIVE_HIGH>; + gpio = <&tlmm 73 GPIO_ACTIVE_HIGH>; enable-active-high; pinctrl-names = "default"; @@ -105,8 +107,8 @@ i2c-muic { compatible = "i2c-gpio"; - sda-gpios = <&msmgpio 105 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>; - scl-gpios = <&msmgpio 106 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>; + sda-gpios = <&tlmm 105 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>; + scl-gpios = <&tlmm 106 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>; pinctrl-names = "default"; pinctrl-0 = <&muic_i2c_default>; @@ -118,7 +120,7 @@ compatible = "siliconmitus,sm5502-muic"; reg = <0x25>; - interrupt-parent = <&msmgpio>; + interrupt-parent = <&tlmm>; interrupts = <12 IRQ_TYPE_EDGE_FALLING>; pinctrl-names = "default"; @@ -128,8 +130,8 @@ i2c-tkey { compatible = "i2c-gpio"; - sda-gpios = <&msmgpio 16 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>; - scl-gpios = <&msmgpio 17 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>; + sda-gpios = <&tlmm 16 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>; + scl-gpios = <&tlmm 17 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>; pinctrl-names = "default"; pinctrl-0 = <&tkey_i2c_default>; @@ -142,7 +144,7 @@ compatible = "coreriver,tc360-touchkey"; reg = <0x20>; - interrupt-parent = <&msmgpio>; + interrupt-parent = <&tlmm>; interrupts = <98 IRQ_TYPE_EDGE_FALLING>; /* vcc/vdd-supply are board-specific */ @@ -157,8 +159,8 @@ i2c-nfc { compatible = "i2c-gpio"; - sda-gpios = <&msmgpio 0 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>; - scl-gpios = <&msmgpio 1 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>; + sda-gpios = <&tlmm 0 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>; + scl-gpios = <&tlmm 1 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>; pinctrl-names = "default"; pinctrl-0 = <&nfc_i2c_default>; @@ -170,11 +172,11 @@ compatible = "samsung,s3fwrn5-i2c"; reg = <0x27>; - interrupt-parent = <&msmgpio>; + interrupt-parent = <&tlmm>; interrupts = <21 IRQ_TYPE_EDGE_RISING>; - en-gpios = <&msmgpio 20 GPIO_ACTIVE_LOW>; - wake-gpios = <&msmgpio 49 GPIO_ACTIVE_HIGH>; + en-gpios = <&tlmm 20 GPIO_ACTIVE_LOW>; + wake-gpios = <&tlmm 49 GPIO_ACTIVE_HIGH>; clocks = <&rpmcc RPM_SMD_BB_CLK2_PIN>; @@ -200,7 +202,7 @@ accelerometer: accelerometer@10 { compatible = "bosch,bmc150_accel"; reg = <0x10>; - interrupt-parent = <&msmgpio>; + interrupt-parent = <&tlmm>; interrupts = <115 IRQ_TYPE_EDGE_RISING>; vdd-supply = <&pm8916_l17>; @@ -225,7 +227,7 @@ battery@35 { compatible = "richtek,rt5033-battery"; reg = <0x35>; - interrupt-parent = <&msmgpio>; + interrupt-parent = <&tlmm>; interrupts = <121 IRQ_TYPE_EDGE_BOTH>; pinctrl-names = "default"; @@ -233,41 +235,44 @@ }; }; -&blsp1_uart2 { +&blsp_uart2 { status = "okay"; }; -&dsi0 { +&mdss { + status = "okay"; +}; + +&mdss_dsi0 { pinctrl-names = "default", "sleep"; pinctrl-0 = <&mdss_default>; pinctrl-1 = <&mdss_sleep>; }; -&mdss { - status = "okay"; -}; - &pm8916_resin { status = "okay"; linux,code = ; }; +&pm8916_rpm_regulators { + pm8916_l17: l17 { + regulator-min-microvolt = <2850000>; + regulator-max-microvolt = <2850000>; + }; +}; + &sdhc_1 { status = "okay"; - - pinctrl-names = "default", "sleep"; - pinctrl-0 = <&sdc1_clk_on &sdc1_cmd_on &sdc1_data_on>; - pinctrl-1 = <&sdc1_clk_off &sdc1_cmd_off &sdc1_data_off>; }; &sdhc_2 { status = "okay"; pinctrl-names = "default", "sleep"; - pinctrl-0 = <&sdc2_clk_on &sdc2_cmd_on &sdc2_data_on &sdc2_cd_on>; - pinctrl-1 = <&sdc2_clk_off &sdc2_cmd_off &sdc2_data_off &sdc2_cd_off>; + pinctrl-0 = <&sdc2_default &sdc2_cd_default>; + pinctrl-1 = <&sdc2_sleep &sdc2_cd_default>; - cd-gpios = <&msmgpio 38 GPIO_ACTIVE_LOW>; + cd-gpios = <&tlmm 38 GPIO_ACTIVE_LOW>; }; &usb { @@ -279,110 +284,7 @@ extcon = <&muic>; }; -&smd_rpm_regulators { - vdd_l1_l2_l3-supply = <&pm8916_s3>; - vdd_l4_l5_l6-supply = <&pm8916_s4>; - vdd_l7-supply = <&pm8916_s4>; - - s3 { - regulator-min-microvolt = <1200000>; - regulator-max-microvolt = <1300000>; - }; - - s4 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <2100000>; - }; - - l1 { - regulator-min-microvolt = <1225000>; - regulator-max-microvolt = <1225000>; - }; - - l2 { - regulator-min-microvolt = <1200000>; - regulator-max-microvolt = <1200000>; - }; - - l4 { - regulator-min-microvolt = <2050000>; - regulator-max-microvolt = <2050000>; - }; - - l5 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - }; - - l6 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - }; - - l7 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - }; - - l8 { - regulator-min-microvolt = <2850000>; - regulator-max-microvolt = <2900000>; - }; - - l9 { - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - }; - - l10 { - regulator-min-microvolt = <2700000>; - regulator-max-microvolt = <2800000>; - }; - - l11 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <2950000>; - regulator-allow-set-load; - regulator-system-load = <200000>; - }; - - l12 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <2950000>; - }; - - l13 { - regulator-min-microvolt = <3075000>; - regulator-max-microvolt = <3075000>; - }; - - l14 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <3300000>; - }; - - l15 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <3300000>; - }; - - l16 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <3300000>; - }; - - l17 { - regulator-min-microvolt = <2850000>; - regulator-max-microvolt = <2850000>; - }; - - l18 { - regulator-min-microvolt = <2700000>; - regulator-max-microvolt = <2700000>; - }; -}; - -&msmgpio { +&tlmm { accel_int_default: accel-int-default-state { pins = "gpio115"; function = "gpio"; @@ -485,6 +387,13 @@ bias-disable; }; + sdc2_cd_default: sdc2-cd-default-state { + pins = "gpio38"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + tkey_default: tkey-default-state { pins = "gpio98"; function = "gpio"; diff --git a/arch/arm64/boot/dts/qcom/msm8916-samsung-a3u-eur.dts b/arch/arm64/boot/dts/qcom/msm8916-samsung-a3u-eur.dts index a1ca4d88342013003ab5f054a02c5acb33cf5472..e5a569698c4f222209802767968471067d70034b 100644 --- a/arch/arm64/boot/dts/qcom/msm8916-samsung-a3u-eur.dts +++ b/arch/arm64/boot/dts/qcom/msm8916-samsung-a3u-eur.dts @@ -15,7 +15,7 @@ regulator-min-microvolt = <1800000>; regulator-max-microvolt = <1800000>; - gpio = <&msmgpio 9 GPIO_ACTIVE_HIGH>; + gpio = <&tlmm 9 GPIO_ACTIVE_HIGH>; enable-active-high; pinctrl-names = "default"; @@ -28,7 +28,7 @@ regulator-min-microvolt = <2800000>; regulator-max-microvolt = <2800000>; - gpio = <&msmgpio 86 GPIO_ACTIVE_HIGH>; + gpio = <&tlmm 86 GPIO_ACTIVE_HIGH>; enable-active-high; pinctrl-names = "default"; @@ -41,7 +41,7 @@ regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; - gpio = <&msmgpio 60 GPIO_ACTIVE_HIGH>; + gpio = <&tlmm 60 GPIO_ACTIVE_HIGH>; enable-active-high; pinctrl-names = "default"; @@ -67,7 +67,7 @@ compatible = "zinitix,bt541"; reg = <0x20>; - interrupt-parent = <&msmgpio>; + interrupt-parent = <&tlmm>; interrupts = <13 IRQ_TYPE_EDGE_FALLING>; touchscreen-size-x = <540>; @@ -85,7 +85,7 @@ status = "okay"; }; -&dsi0 { +&mdss_dsi0 { panel@0 { reg = <0>; @@ -93,17 +93,17 @@ vdd3-supply = <®_panel_vdd3>; vci-supply = <&pm8916_l17>; - reset-gpios = <&msmgpio 25 GPIO_ACTIVE_HIGH>; + reset-gpios = <&tlmm 25 GPIO_ACTIVE_HIGH>; port { panel_in: endpoint { - remote-endpoint = <&dsi0_out>; + remote-endpoint = <&mdss_dsi0_out>; }; }; }; }; -&dsi0_out { +&mdss_dsi0_out { data-lanes = <0 1>; remote-endpoint = <&panel_in>; }; @@ -120,7 +120,7 @@ compatible = "qcom,wcn3620"; }; -&msmgpio { +&tlmm { panel_vdd3_default: panel-vdd3-default-state { pins = "gpio9"; function = "gpio"; diff --git a/arch/arm64/boot/dts/qcom/msm8916-samsung-a5u-eur.dts b/arch/arm64/boot/dts/qcom/msm8916-samsung-a5u-eur.dts index 4e10b8a5e9f9c0d60124a2eacfa9e039051f3851..388482a1e3d9fa7d8c5f1c61b160774efcc3334f 100644 --- a/arch/arm64/boot/dts/qcom/msm8916-samsung-a5u-eur.dts +++ b/arch/arm64/boot/dts/qcom/msm8916-samsung-a5u-eur.dts @@ -15,7 +15,7 @@ regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; - gpio = <&msmgpio 97 GPIO_ACTIVE_HIGH>; + gpio = <&tlmm 97 GPIO_ACTIVE_HIGH>; enable-active-high; pinctrl-names = "default"; @@ -36,7 +36,7 @@ compatible = "melfas,mms345l"; reg = <0x48>; - interrupt-parent = <&msmgpio>; + interrupt-parent = <&tlmm>; interrupts = <13 IRQ_TYPE_EDGE_FALLING>; touchscreen-size-x = <720>; @@ -71,7 +71,7 @@ compatible = "qcom,wcn3660b"; }; -&msmgpio { +&tlmm { tkey_en_default: tkey-en-default-state { pins = "gpio97"; function = "gpio"; diff --git a/arch/arm64/boot/dts/qcom/msm8916-samsung-e2015-common.dtsi b/arch/arm64/boot/dts/qcom/msm8916-samsung-e2015-common.dtsi index f6c4a011fdfd2506a3ce0ae7b73207d5a68fcf78..0cdd6af7817f4b7571d32847b70805ea3bcd135c 100644 --- a/arch/arm64/boot/dts/qcom/msm8916-samsung-e2015-common.dtsi +++ b/arch/arm64/boot/dts/qcom/msm8916-samsung-e2015-common.dtsi @@ -18,7 +18,7 @@ compatible = "siliconmitus,sm5504-muic"; reg = <0x14>; - interrupt-parent = <&msmgpio>; + interrupt-parent = <&tlmm>; interrupts = <12 IRQ_TYPE_EDGE_FALLING>; pinctrl-names = "default"; @@ -32,7 +32,7 @@ regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; - gpio = <&msmgpio 97 GPIO_ACTIVE_HIGH>; + gpio = <&tlmm 97 GPIO_ACTIVE_HIGH>; enable-active-high; pinctrl-names = "default"; @@ -66,7 +66,7 @@ compatible = "qcom,wcn3620"; }; -&msmgpio { +&tlmm { tkey_en_default: tkey-en-default-state { pins = "gpio97"; function = "gpio"; diff --git a/arch/arm64/boot/dts/qcom/msm8916-samsung-grandmax.dts b/arch/arm64/boot/dts/qcom/msm8916-samsung-grandmax.dts index 4cbd68b8944815f2b36a3b1bc3eacdf8bac9f11f..3f145dde4059f86992a40002496a7bc7ec59bb4b 100644 --- a/arch/arm64/boot/dts/qcom/msm8916-samsung-grandmax.dts +++ b/arch/arm64/boot/dts/qcom/msm8916-samsung-grandmax.dts @@ -33,7 +33,7 @@ function = LED_FUNCTION_KBD_BACKLIGHT; color = ; - gpios = <&msmgpio 60 GPIO_ACTIVE_HIGH>; + gpios = <&tlmm 60 GPIO_ACTIVE_HIGH>; pinctrl-names = "default"; pinctrl-0 = <&gpio_leds_default>; @@ -42,14 +42,14 @@ }; ®_motor_vdd { - gpio = <&msmgpio 72 GPIO_ACTIVE_HIGH>; + gpio = <&tlmm 72 GPIO_ACTIVE_HIGH>; }; ®_touch_key { status = "disabled"; }; -&msmgpio { +&tlmm { gpio_leds_default: gpio-led-default-state { pins = "gpio60"; function = "gpio"; diff --git a/arch/arm64/boot/dts/qcom/msm8916-samsung-gt5-common.dtsi b/arch/arm64/boot/dts/qcom/msm8916-samsung-gt5-common.dtsi index 74ffd04db8d84c5f22b465182e66be1324736247..7943bb619116309137082c1b40b6520ec53ddc4f 100644 --- a/arch/arm64/boot/dts/qcom/msm8916-samsung-gt5-common.dtsi +++ b/arch/arm64/boot/dts/qcom/msm8916-samsung-gt5-common.dtsi @@ -9,7 +9,9 @@ / { aliases { - serial0 = &blsp1_uart2; + mmc0 = &sdhc_1; /* eMMC */ + mmc1 = &sdhc_2; /* SD card */ + serial0 = &blsp_uart2; }; chosen { @@ -34,13 +36,13 @@ volume-up-button { label = "Volume Up"; - gpios = <&msmgpio 107 GPIO_ACTIVE_LOW>; + gpios = <&tlmm 107 GPIO_ACTIVE_LOW>; linux,code = ; }; home-button { label = "Home"; - gpios = <&msmgpio 109 GPIO_ACTIVE_LOW>; + gpios = <&tlmm 109 GPIO_ACTIVE_LOW>; linux,code = ; }; }; @@ -55,7 +57,7 @@ hall-sensor-switch { label = "Hall Effect Sensor"; - gpios = <&msmgpio 52 GPIO_ACTIVE_LOW>; + gpios = <&tlmm 52 GPIO_ACTIVE_LOW>; linux,input-type = ; linux,code = ; linux,can-disable; @@ -74,7 +76,7 @@ maxim,over-heat-temp = <600>; maxim,over-volt = <4400>; - interrupt-parent = <&msmgpio>; + interrupt-parent = <&tlmm>; interrupts = <121 IRQ_TYPE_EDGE_FALLING>; pinctrl-0 = <&fuelgauge_int_default>; @@ -97,7 +99,7 @@ vdd-supply = <&pm8916_l17>; vddio-supply = <&pm8916_l5>; - interrupt-parent = <&msmgpio>; + interrupt-parent = <&tlmm>; interrupts = <115 IRQ_TYPE_LEVEL_HIGH>; interrupt-names = "INT1"; @@ -111,7 +113,7 @@ }; }; -&blsp1_uart2 { +&blsp_uart2 { status = "okay"; }; @@ -120,25 +122,28 @@ status = "okay"; }; +&pm8916_rpm_regulators { + pm8916_l17: l17 { + regulator-min-microvolt = <2850000>; + regulator-max-microvolt = <2850000>; + }; +}; + /* FIXME: Replace with MAX77849 MUIC when driver is available */ &pm8916_usbin { status = "okay"; }; &sdhc_1 { - pinctrl-0 = <&sdc1_clk_on &sdc1_cmd_on &sdc1_data_on>; - pinctrl-1 = <&sdc1_clk_off &sdc1_cmd_off &sdc1_data_off>; - pinctrl-names = "default", "sleep"; - status = "okay"; }; &sdhc_2 { - pinctrl-0 = <&sdc2_clk_on &sdc2_cmd_on &sdc2_data_on &sdc2_cd_on>; - pinctrl-1 = <&sdc2_clk_off &sdc2_cmd_off &sdc2_data_off &sdc2_cd_off>; + pinctrl-0 = <&sdc2_default &sdc2_cd_default>; + pinctrl-1 = <&sdc2_sleep &sdc2_cd_default>; pinctrl-names = "default", "sleep"; - cd-gpios = <&msmgpio 38 GPIO_ACTIVE_LOW>; + cd-gpios = <&tlmm 38 GPIO_ACTIVE_LOW>; status = "okay"; }; @@ -162,110 +167,7 @@ compatible = "qcom,wcn3660b"; }; -&smd_rpm_regulators { - vdd_l1_l2_l3-supply = <&pm8916_s3>; - vdd_l4_l5_l6-supply = <&pm8916_s4>; - vdd_l7-supply = <&pm8916_s4>; - - s3 { - regulator-min-microvolt = <1200000>; - regulator-max-microvolt = <1300000>; - }; - - s4 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <2100000>; - }; - - l1 { - regulator-min-microvolt = <1225000>; - regulator-max-microvolt = <1225000>; - }; - - l2 { - regulator-min-microvolt = <1200000>; - regulator-max-microvolt = <1200000>; - }; - - l4 { - regulator-min-microvolt = <2050000>; - regulator-max-microvolt = <2050000>; - }; - - l5 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - }; - - l6 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - }; - - l7 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - }; - - l8 { - regulator-min-microvolt = <2850000>; - regulator-max-microvolt = <2900000>; - }; - - l9 { - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - }; - - l10 { - regulator-min-microvolt = <2700000>; - regulator-max-microvolt = <2800000>; - }; - - l11 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <2950000>; - regulator-system-load = <200000>; - regulator-allow-set-load; - }; - - l12 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <2950000>; - }; - - l13 { - regulator-min-microvolt = <3075000>; - regulator-max-microvolt = <3075000>; - }; - - l14 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <3300000>; - }; - - l15 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <3300000>; - }; - - l16 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <3300000>; - }; - - l17 { - regulator-min-microvolt = <2850000>; - regulator-max-microvolt = <2850000>; - }; - - l18 { - regulator-min-microvolt = <2700000>; - regulator-max-microvolt = <2700000>; - }; -}; - -&msmgpio { +&tlmm { accel_int_default: accel-int-default-state { pins = "gpio115"; function = "gpio"; @@ -293,4 +195,11 @@ drive-strength = <2>; bias-disable; }; + + sdc2_cd_default: sdc2-cd-default-state { + pins = "gpio38"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; }; diff --git a/arch/arm64/boot/dts/qcom/msm8916-samsung-gt510.dts b/arch/arm64/boot/dts/qcom/msm8916-samsung-gt510.dts index 607a5dc8a5341ab5bbb9e9ff9ef6382d555040ee..48111c6a2c78fb5d2e2e535247dbb949a736c316 100644 --- a/arch/arm64/boot/dts/qcom/msm8916-samsung-gt510.dts +++ b/arch/arm64/boot/dts/qcom/msm8916-samsung-gt510.dts @@ -25,7 +25,7 @@ regulator-min-microvolt = <3000000>; regulator-max-microvolt = <3000000>; - gpio = <&msmgpio 76 GPIO_ACTIVE_HIGH>; + gpio = <&tlmm 76 GPIO_ACTIVE_HIGH>; enable-active-high; pinctrl-0 = <&motor_en_default>; @@ -38,7 +38,7 @@ regulator-min-microvolt = <1800000>; regulator-max-microvolt = <1800000>; - gpio = <&msmgpio 73 GPIO_ACTIVE_HIGH>; + gpio = <&tlmm 73 GPIO_ACTIVE_HIGH>; enable-active-high; pinctrl-0 = <&tsp_en_default>; @@ -51,7 +51,7 @@ regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; - gpio = <&msmgpio 73 GPIO_ACTIVE_HIGH>; + gpio = <&tlmm 73 GPIO_ACTIVE_HIGH>; enable-active-high; }; @@ -71,20 +71,20 @@ touchscreen@4a { compatible = "atmel,maxtouch"; reg = <0x4a>; - interrupt-parent = <&msmgpio>; + interrupt-parent = <&tlmm>; interrupts = <13 IRQ_TYPE_LEVEL_LOW>; vdd-supply = <®_tsp_1p8v>; vdda-supply = <®_tsp_3p3v>; - reset-gpios = <&msmgpio 114 GPIO_ACTIVE_LOW>; + reset-gpios = <&tlmm 114 GPIO_ACTIVE_LOW>; pinctrl-0 = <&tsp_int_rst_default>; pinctrl-names = "default"; }; }; -&msmgpio { +&tlmm { motor_en_default: motor-en-default-state { pins = "gpio76"; function = "gpio"; diff --git a/arch/arm64/boot/dts/qcom/msm8916-samsung-gt58.dts b/arch/arm64/boot/dts/qcom/msm8916-samsung-gt58.dts index 5d6f8383306bb9c3497bc7987eff4a3cc409ccff..98ceaad7fcea903f2ff5b54dc51e9df50703aef9 100644 --- a/arch/arm64/boot/dts/qcom/msm8916-samsung-gt58.dts +++ b/arch/arm64/boot/dts/qcom/msm8916-samsung-gt58.dts @@ -15,7 +15,7 @@ regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; - gpio = <&msmgpio 73 GPIO_ACTIVE_HIGH>; + gpio = <&tlmm 73 GPIO_ACTIVE_HIGH>; enable-active-high; pinctrl-0 = <®_tsp_en_default>; @@ -24,7 +24,7 @@ vibrator { compatible = "gpio-vibrator"; - enable-gpios = <&msmgpio 76 GPIO_ACTIVE_HIGH>; + enable-gpios = <&tlmm 76 GPIO_ACTIVE_HIGH>; pinctrl-0 = <&vibrator_en_default>; pinctrl-names = "default"; @@ -37,7 +37,7 @@ touchscreen@20 { compatible = "zinitix,bt532"; reg = <0x20>; - interrupt-parent = <&msmgpio>; + interrupt-parent = <&tlmm>; interrupts = <13 IRQ_TYPE_EDGE_FALLING>; touchscreen-size-x = <768>; @@ -51,7 +51,7 @@ }; }; -&msmgpio { +&tlmm { reg_tsp_en_default: reg-tsp-en-default-state { pins = "gpio73"; function = "gpio"; diff --git a/arch/arm64/boot/dts/qcom/msm8916-samsung-j5-common.dtsi b/arch/arm64/boot/dts/qcom/msm8916-samsung-j5-common.dtsi index adeee0830e7680df17f1ec5bb66390c456b6ebe6..f4fd5d72b28bcec028c115a1cb7651efc1c4b4d8 100644 --- a/arch/arm64/boot/dts/qcom/msm8916-samsung-j5-common.dtsi +++ b/arch/arm64/boot/dts/qcom/msm8916-samsung-j5-common.dtsi @@ -7,7 +7,9 @@ / { aliases { - serial0 = &blsp1_uart2; + mmc0 = &sdhc_1; /* eMMC */ + mmc1 = &sdhc_2; /* SD card */ + serial0 = &blsp_uart2; }; chosen { @@ -32,7 +34,7 @@ event-hall-sensor { label = "Hall Effect Sensor"; - gpios = <&msmgpio 52 GPIO_ACTIVE_LOW>; + gpios = <&tlmm 52 GPIO_ACTIVE_LOW>; linux,input-type = ; linux,code = ; linux,can-disable; @@ -49,21 +51,21 @@ button-volume-up { label = "Volume Up"; - gpios = <&msmgpio 107 GPIO_ACTIVE_LOW>; + gpios = <&tlmm 107 GPIO_ACTIVE_LOW>; linux,code = ; }; button-home { label = "Home Key"; - gpios = <&msmgpio 109 GPIO_ACTIVE_LOW>; + gpios = <&tlmm 109 GPIO_ACTIVE_LOW>; linux,code = ; }; }; i2c_muic: i2c-muic { compatible = "i2c-gpio"; - sda-gpios = <&msmgpio 105 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>; - scl-gpios = <&msmgpio 106 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>; + sda-gpios = <&tlmm 105 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>; + scl-gpios = <&tlmm 106 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>; pinctrl-names = "default"; pinctrl-0 = <&muic_i2c_default>; @@ -75,7 +77,7 @@ compatible = "siliconmitus,sm5703-muic"; reg = <0x25>; - interrupt-parent = <&msmgpio>; + interrupt-parent = <&tlmm>; interrupts = <12 IRQ_TYPE_EDGE_FALLING>; pinctrl-names = "default"; @@ -84,7 +86,7 @@ }; }; -&blsp1_uart2 { +&blsp_uart2 { status = "okay"; }; @@ -95,20 +97,16 @@ &sdhc_1 { status = "okay"; - - pinctrl-names = "default", "sleep"; - pinctrl-0 = <&sdc1_clk_on &sdc1_cmd_on &sdc1_data_on>; - pinctrl-1 = <&sdc1_clk_off &sdc1_cmd_off &sdc1_data_off>; }; &sdhc_2 { status = "okay"; pinctrl-names = "default", "sleep"; - pinctrl-0 = <&sdc2_clk_on &sdc2_cmd_on &sdc2_data_on &sdc2_cd_on>; - pinctrl-1 = <&sdc2_clk_off &sdc2_cmd_off &sdc2_data_off &sdc2_cd_off>; + pinctrl-0 = <&sdc2_default &sdc2_cd_default>; + pinctrl-1 = <&sdc2_sleep &sdc2_cd_default>; - cd-gpios = <&msmgpio 38 GPIO_ACTIVE_LOW>; + cd-gpios = <&tlmm 38 GPIO_ACTIVE_LOW>; }; &usb { @@ -128,110 +126,7 @@ compatible = "qcom,wcn3620"; }; -&smd_rpm_regulators { - vdd_l1_l2_l3-supply = <&pm8916_s3>; - vdd_l4_l5_l6-supply = <&pm8916_s4>; - vdd_l7-supply = <&pm8916_s4>; - - s3 { - regulator-min-microvolt = <1200000>; - regulator-max-microvolt = <1300000>; - }; - - s4 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <2100000>; - }; - - l1 { - regulator-min-microvolt = <1225000>; - regulator-max-microvolt = <1225000>; - }; - - l2 { - regulator-min-microvolt = <1200000>; - regulator-max-microvolt = <1200000>; - }; - - l4 { - regulator-min-microvolt = <2050000>; - regulator-max-microvolt = <2050000>; - }; - - l5 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - }; - - l6 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - }; - - l7 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - }; - - l8 { - regulator-min-microvolt = <2850000>; - regulator-max-microvolt = <2900000>; - }; - - l9 { - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - }; - - l10 { - regulator-min-microvolt = <2700000>; - regulator-max-microvolt = <2800000>; - }; - - l11 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <2950000>; - regulator-allow-set-load; - regulator-system-load = <200000>; - }; - - l12 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <2950000>; - }; - - l13 { - regulator-min-microvolt = <3075000>; - regulator-max-microvolt = <3075000>; - }; - - l14 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <3300000>; - }; - - l15 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <3300000>; - }; - - l16 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <3300000>; - }; - - l17 { - regulator-min-microvolt = <3000000>; - regulator-max-microvolt = <3000000>; - }; - - l18 { - regulator-min-microvolt = <2700000>; - regulator-max-microvolt = <2700000>; - }; -}; - -&msmgpio { +&tlmm { gpio_hall_sensor_default: gpio-hall-sensor-default-state { pins = "gpio52"; function = "gpio"; @@ -263,4 +158,11 @@ drive-strength = <2>; bias-disable; }; + + sdc2_cd_default: sdc2-cd-default-state { + pins = "gpio38"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; }; diff --git a/arch/arm64/boot/dts/qcom/msm8916-samsung-serranove.dts b/arch/arm64/boot/dts/qcom/msm8916-samsung-serranove.dts index 1a41a4db874daeac500314e5579c239c34a03232..15dc246e84e2bdeffcf11b9b5da0813990633676 100644 --- a/arch/arm64/boot/dts/qcom/msm8916-samsung-serranove.dts +++ b/arch/arm64/boot/dts/qcom/msm8916-samsung-serranove.dts @@ -28,7 +28,9 @@ chassis-type = "handset"; aliases { - serial0 = &blsp1_uart2; + mmc0 = &sdhc_1; /* eMMC */ + mmc1 = &sdhc_2; /* SD card */ + serial0 = &blsp_uart2; }; chosen { @@ -53,13 +55,13 @@ button-volume-up { label = "Volume Up"; - gpios = <&msmgpio 107 GPIO_ACTIVE_LOW>; + gpios = <&tlmm 107 GPIO_ACTIVE_LOW>; linux,code = ; }; button-home { label = "Home"; - gpios = <&msmgpio 109 GPIO_ACTIVE_LOW>; + gpios = <&tlmm 109 GPIO_ACTIVE_LOW>; linux,code = ; }; }; @@ -74,7 +76,7 @@ event-hall-sensor { label = "Hall Effect Sensor"; - gpios = <&msmgpio 52 GPIO_ACTIVE_LOW>; + gpios = <&tlmm 52 GPIO_ACTIVE_LOW>; linux,input-type = ; linux,code = ; linux,can-disable; @@ -87,7 +89,7 @@ regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; - gpio = <&msmgpio 73 GPIO_ACTIVE_HIGH>; + gpio = <&tlmm 73 GPIO_ACTIVE_HIGH>; enable-active-high; pinctrl-names = "default"; @@ -100,7 +102,7 @@ regulator-min-microvolt = <2800000>; regulator-max-microvolt = <2800000>; - gpio = <&msmgpio 86 GPIO_ACTIVE_HIGH>; + gpio = <&tlmm 86 GPIO_ACTIVE_HIGH>; enable-active-high; pinctrl-names = "default"; @@ -113,7 +115,7 @@ regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; - gpio = <&msmgpio 60 GPIO_ACTIVE_HIGH>; + gpio = <&tlmm 60 GPIO_ACTIVE_HIGH>; enable-active-high; pinctrl-names = "default"; @@ -122,8 +124,8 @@ i2c-muic { compatible = "i2c-gpio"; - sda-gpios = <&msmgpio 105 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>; - scl-gpios = <&msmgpio 106 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>; + sda-gpios = <&tlmm 105 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>; + scl-gpios = <&tlmm 106 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>; pinctrl-names = "default"; pinctrl-0 = <&muic_i2c_default>; @@ -135,7 +137,7 @@ compatible = "siliconmitus,sm5504-muic"; reg = <0x14>; - interrupt-parent = <&msmgpio>; + interrupt-parent = <&tlmm>; interrupts = <12 IRQ_TYPE_EDGE_FALLING>; pinctrl-names = "default"; @@ -145,8 +147,8 @@ i2c-tkey { compatible = "i2c-gpio"; - sda-gpios = <&msmgpio 16 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>; - scl-gpios = <&msmgpio 17 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>; + sda-gpios = <&tlmm 16 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>; + scl-gpios = <&tlmm 17 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>; pinctrl-names = "default"; pinctrl-0 = <&tkey_i2c_default>; @@ -158,7 +160,7 @@ compatible = "coreriver,tc360-touchkey"; reg = <0x20>; - interrupt-parent = <&msmgpio>; + interrupt-parent = <&tlmm>; interrupts = <98 IRQ_TYPE_EDGE_FALLING>; vcc-supply = <®_touch_key>; @@ -174,8 +176,8 @@ i2c-nfc { compatible = "i2c-gpio"; - sda-gpios = <&msmgpio 0 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>; - scl-gpios = <&msmgpio 1 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>; + sda-gpios = <&tlmm 0 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>; + scl-gpios = <&tlmm 1 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>; pinctrl-names = "default"; pinctrl-0 = <&nfc_i2c_default>; @@ -187,11 +189,11 @@ compatible = "nxp,pn547", "nxp,nxp-nci-i2c"; reg = <0x2b>; - interrupt-parent = <&msmgpio>; + interrupt-parent = <&tlmm>; interrupts = <21 IRQ_TYPE_EDGE_RISING>; - enable-gpios = <&msmgpio 20 GPIO_ACTIVE_HIGH>; - firmware-gpios = <&msmgpio 49 GPIO_ACTIVE_HIGH>; + enable-gpios = <&tlmm 20 GPIO_ACTIVE_HIGH>; + firmware-gpios = <&tlmm 49 GPIO_ACTIVE_HIGH>; pinctrl-names = "default"; pinctrl-0 = <&nfc_default>; @@ -206,7 +208,7 @@ compatible = "st,lsm6ds3"; reg = <0x6b>; - interrupt-parent = <&msmgpio>; + interrupt-parent = <&tlmm>; interrupts = <115 IRQ_TYPE_EDGE_RISING>; pinctrl-names = "default"; @@ -230,7 +232,7 @@ compatible = "richtek,rt5033-battery"; reg = <0x35>; - interrupt-parent = <&msmgpio>; + interrupt-parent = <&tlmm>; interrupts = <121 IRQ_TYPE_EDGE_FALLING>; pinctrl-names = "default"; @@ -245,7 +247,7 @@ compatible = "zinitix,bt541"; reg = <0x20>; - interrupt-parent = <&msmgpio>; + interrupt-parent = <&tlmm>; interrupts = <13 IRQ_TYPE_EDGE_FALLING>; touchscreen-size-x = <540>; @@ -259,7 +261,7 @@ }; }; -&blsp1_uart2 { +&blsp_uart2 { status = "okay"; }; @@ -274,19 +276,10 @@ &sdhc_1 { status = "okay"; - - pinctrl-names = "default", "sleep"; - pinctrl-0 = <&sdc1_clk_on &sdc1_cmd_on &sdc1_data_on>; - pinctrl-1 = <&sdc1_clk_off &sdc1_cmd_off &sdc1_data_off>; }; &sdhc_2 { status = "okay"; - - pinctrl-names = "default", "sleep"; - pinctrl-0 = <&sdc2_clk_on &sdc2_cmd_on &sdc2_data_on>; - pinctrl-1 = <&sdc2_clk_off &sdc2_cmd_off &sdc2_data_off>; - non-removable; /* @@ -320,110 +313,7 @@ compatible = "qcom,wcn3660b"; }; -&smd_rpm_regulators { - vdd_l1_l2_l3-supply = <&pm8916_s3>; - vdd_l4_l5_l6-supply = <&pm8916_s4>; - vdd_l7-supply = <&pm8916_s4>; - - s3 { - regulator-min-microvolt = <1200000>; - regulator-max-microvolt = <1300000>; - }; - - s4 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <2100000>; - }; - - l1 { - regulator-min-microvolt = <1225000>; - regulator-max-microvolt = <1225000>; - }; - - l2 { - regulator-min-microvolt = <1200000>; - regulator-max-microvolt = <1200000>; - }; - - l4 { - regulator-min-microvolt = <2050000>; - regulator-max-microvolt = <2050000>; - }; - - l5 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - }; - - l6 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - }; - - l7 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - }; - - l8 { - regulator-min-microvolt = <2850000>; - regulator-max-microvolt = <2900000>; - }; - - l9 { - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - }; - - l10 { - regulator-min-microvolt = <2700000>; - regulator-max-microvolt = <2800000>; - }; - - l11 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <2950000>; - regulator-allow-set-load; - regulator-system-load = <200000>; - }; - - l12 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <2950000>; - }; - - l13 { - regulator-min-microvolt = <3075000>; - regulator-max-microvolt = <3075000>; - }; - - l14 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <3300000>; - }; - - l15 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <3300000>; - }; - - l16 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <3300000>; - }; - - l17 { - regulator-min-microvolt = <2850000>; - regulator-max-microvolt = <2850000>; - }; - - l18 { - regulator-min-microvolt = <2700000>; - regulator-max-microvolt = <2700000>; - }; -}; - -&msmgpio { +&tlmm { fg_alert_default: fg-alert-default-state { pins = "gpio121"; function = "gpio"; diff --git a/arch/arm64/boot/dts/qcom/msm8916-thwc-uf896.dts b/arch/arm64/boot/dts/qcom/msm8916-thwc-uf896.dts index 82e260375174d1b86608db45876ff363ff1acd52..6fe1850ba20e9ebde315642f1c620e9a4deb7146 100644 --- a/arch/arm64/boot/dts/qcom/msm8916-thwc-uf896.dts +++ b/arch/arm64/boot/dts/qcom/msm8916-thwc-uf896.dts @@ -10,19 +10,19 @@ }; &button_restart { - gpios = <&msmgpio 35 GPIO_ACTIVE_LOW>; + gpios = <&tlmm 35 GPIO_ACTIVE_LOW>; }; &led_r { - gpios = <&msmgpio 82 GPIO_ACTIVE_HIGH>; + gpios = <&tlmm 82 GPIO_ACTIVE_HIGH>; }; &led_g { - gpios = <&msmgpio 83 GPIO_ACTIVE_HIGH>; + gpios = <&tlmm 83 GPIO_ACTIVE_HIGH>; }; &led_b { - gpios = <&msmgpio 81 GPIO_ACTIVE_HIGH>; + gpios = <&tlmm 81 GPIO_ACTIVE_HIGH>; }; &button_default { diff --git a/arch/arm64/boot/dts/qcom/msm8916-thwc-ufi001c.dts b/arch/arm64/boot/dts/qcom/msm8916-thwc-ufi001c.dts index 978f0abcdf8ff712d41b1ab67b5d15f6aa47eacd..16d4a91022be6f9897c73abd1b56f0d860b1692d 100644 --- a/arch/arm64/boot/dts/qcom/msm8916-thwc-ufi001c.dts +++ b/arch/arm64/boot/dts/qcom/msm8916-thwc-ufi001c.dts @@ -10,19 +10,19 @@ }; &button_restart { - gpios = <&msmgpio 37 GPIO_ACTIVE_HIGH>; + gpios = <&tlmm 37 GPIO_ACTIVE_HIGH>; }; &led_r { - gpios = <&msmgpio 22 GPIO_ACTIVE_HIGH>; + gpios = <&tlmm 22 GPIO_ACTIVE_HIGH>; }; &led_g { - gpios = <&msmgpio 21 GPIO_ACTIVE_HIGH>; + gpios = <&tlmm 21 GPIO_ACTIVE_HIGH>; }; &led_b { - gpios = <&msmgpio 20 GPIO_ACTIVE_HIGH>; + gpios = <&tlmm 20 GPIO_ACTIVE_HIGH>; }; &mpss { @@ -40,7 +40,7 @@ }; /* This selects the external SIM card slot by default */ -&msmgpio { +&tlmm { sim_ctrl_default: sim-ctrl-default-state { esim-sel-pins { pins = "gpio0", "gpio3"; diff --git a/arch/arm64/boot/dts/qcom/msm8916-ufi.dtsi b/arch/arm64/boot/dts/qcom/msm8916-ufi.dtsi index 50bae6f214f1fbabd7a405252579b7a6001955e7..004a129a2ee2b1f1e7d04f46715b5799e5d8aae6 100644 --- a/arch/arm64/boot/dts/qcom/msm8916-ufi.dtsi +++ b/arch/arm64/boot/dts/qcom/msm8916-ufi.dtsi @@ -9,7 +9,8 @@ chassis-type = "embedded"; aliases { - serial0 = &blsp1_uart2; + mmc0 = &sdhc_1; /* eMMC */ + serial0 = &blsp_uart2; }; chosen { @@ -82,11 +83,11 @@ status = "okay"; }; -&blsp1_uart2 { +&blsp_uart2 { status = "okay"; }; -/* Remove &dsi_phy0 from clocks to make sure that gcc probes with display disabled */ +/* Remove &mdss_dsi0_phy from clocks to make sure that gcc probes with display disabled */ &gcc { clocks = <&xo_board>, <&sleep_clk>, <0>, <0>, <0>, <0>, <0>; }; @@ -100,16 +101,12 @@ }; &sdhc_1 { - pinctrl-0 = <&sdc1_clk_on &sdc1_cmd_on &sdc1_data_on>; - pinctrl-1 = <&sdc1_clk_off &sdc1_cmd_off &sdc1_data_off>; - pinctrl-names = "default", "sleep"; - status = "okay"; }; &usb { extcon = <&pm8916_usbin>; - dr_mode = "peripheral"; + usb-role-switch; status = "okay"; }; @@ -126,110 +123,7 @@ compatible = "qcom,wcn3620"; }; -&smd_rpm_regulators { - vdd_l1_l2_l3-supply = <&pm8916_s3>; - vdd_l4_l5_l6-supply = <&pm8916_s4>; - vdd_l7-supply = <&pm8916_s4>; - - s3 { - regulator-min-microvolt = <1200000>; - regulator-max-microvolt = <1300000>; - }; - - s4 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <2100000>; - }; - - l1 { - regulator-min-microvolt = <1225000>; - regulator-max-microvolt = <1225000>; - }; - - l2 { - regulator-min-microvolt = <1200000>; - regulator-max-microvolt = <1200000>; - }; - - l4 { - regulator-min-microvolt = <2050000>; - regulator-max-microvolt = <2050000>; - }; - - l5 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - }; - - l6 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - }; - - l7 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - }; - - l8 { - regulator-min-microvolt = <2850000>; - regulator-max-microvolt = <2900000>; - }; - - l9 { - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - }; - - l10 { - regulator-min-microvolt = <2700000>; - regulator-max-microvolt = <2800000>; - }; - - l11 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <2950000>; - regulator-system-load = <200000>; - regulator-allow-set-load; - }; - - l12 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <2950000>; - }; - - l13 { - regulator-min-microvolt = <3075000>; - regulator-max-microvolt = <3075000>; - }; - - l14 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <3300000>; - }; - - l15 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <3300000>; - }; - - l16 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <3300000>; - }; - - l17 { - regulator-min-microvolt = <2850000>; - regulator-max-microvolt = <2850000>; - }; - - l18 { - regulator-min-microvolt = <2700000>; - regulator-max-microvolt = <2700000>; - }; -}; - -&msmgpio { +&tlmm { /* pins are board-specific */ button_default: button-default-state { function = "gpio"; diff --git a/arch/arm64/boot/dts/qcom/msm8916-wingtech-wt88047.dts b/arch/arm64/boot/dts/qcom/msm8916-wingtech-wt88047.dts index ac56c7595f78a5b40ec1bd9622d72669f0bbf9b6..c94d36b3865179de1f1b8da343893f520376840a 100644 --- a/arch/arm64/boot/dts/qcom/msm8916-wingtech-wt88047.dts +++ b/arch/arm64/boot/dts/qcom/msm8916-wingtech-wt88047.dts @@ -16,7 +16,9 @@ chassis-type = "handset"; aliases { - serial0 = &blsp1_uart2; + mmc0 = &sdhc_1; /* eMMC */ + mmc1 = &sdhc_2; /* SD card */ + serial0 = &blsp_uart2; }; chosen { @@ -25,8 +27,8 @@ flash-led-controller { compatible = "ocs,ocp8110"; - enable-gpios = <&msmgpio 31 GPIO_ACTIVE_HIGH>; - flash-gpios = <&msmgpio 32 GPIO_ACTIVE_HIGH>; + enable-gpios = <&tlmm 31 GPIO_ACTIVE_HIGH>; + flash-gpios = <&tlmm 32 GPIO_ACTIVE_HIGH>; pinctrl-names = "default"; pinctrl-0 = <&camera_flash_default>; @@ -47,14 +49,14 @@ button-volume-up { label = "Volume Up"; - gpios = <&msmgpio 107 GPIO_ACTIVE_LOW>; + gpios = <&tlmm 107 GPIO_ACTIVE_LOW>; linux,code = ; }; }; usb_id: usb-id { compatible = "linux,extcon-usb-gpio"; - id-gpio = <&msmgpio 110 GPIO_ACTIVE_HIGH>; + id-gpio = <&tlmm 110 GPIO_ACTIVE_HIGH>; pinctrl-names = "default"; pinctrl-0 = <&usb_id_default>; }; @@ -67,7 +69,7 @@ compatible = "invensense,mpu6880"; reg = <0x68>; - interrupt-parent = <&msmgpio>; + interrupt-parent = <&tlmm>; interrupts = <115 IRQ_TYPE_EDGE_RISING>; vdd-supply = <&pm8916_l17>; @@ -90,10 +92,10 @@ compatible = "edt,edt-ft5506"; reg = <0x38>; - interrupt-parent = <&msmgpio>; + interrupt-parent = <&tlmm>; interrupts = <13 IRQ_TYPE_EDGE_FALLING>; - reset-gpios = <&msmgpio 12 GPIO_ACTIVE_LOW>; + reset-gpios = <&tlmm 12 GPIO_ACTIVE_LOW>; vcc-supply = <&pm8916_l17>; iovcc-supply = <&pm8916_l6>; @@ -140,7 +142,7 @@ }; }; -&blsp1_uart2 { +&blsp_uart2 { status = "okay"; }; @@ -149,25 +151,32 @@ linux,code = ; }; +&pm8916_rpm_regulators { + pm8916_l16: l16 { + /* + * L16 is only used for AW2013 which is fine with 2.5-3.3V. + * Use the recommended typical voltage of 2.8V as minimum. + */ + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <3300000>; + }; + + pm8916_l17: l17 { + regulator-min-microvolt = <2850000>; + regulator-max-microvolt = <2850000>; + }; +}; + &pm8916_vib { status = "okay"; }; &sdhc_1 { status = "okay"; - - pinctrl-names = "default", "sleep"; - pinctrl-0 = <&sdc1_clk_on &sdc1_cmd_on &sdc1_data_on>; - pinctrl-1 = <&sdc1_clk_off &sdc1_cmd_off &sdc1_data_off>; }; &sdhc_2 { status = "okay"; - - pinctrl-names = "default", "sleep"; - pinctrl-0 = <&sdc2_clk_on &sdc2_cmd_on &sdc2_data_on>; - pinctrl-1 = <&sdc2_clk_off &sdc2_cmd_off &sdc2_data_off>; - non-removable; }; @@ -188,110 +197,7 @@ compatible = "qcom,wcn3620"; }; -&smd_rpm_regulators { - vdd_l1_l2_l3-supply = <&pm8916_s3>; - vdd_l4_l5_l6-supply = <&pm8916_s4>; - vdd_l7-supply = <&pm8916_s4>; - - s3 { - regulator-min-microvolt = <1200000>; - regulator-max-microvolt = <1300000>; - }; - - s4 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <2100000>; - }; - - l1 { - regulator-min-microvolt = <1225000>; - regulator-max-microvolt = <1225000>; - }; - - l2 { - regulator-min-microvolt = <1200000>; - regulator-max-microvolt = <1200000>; - }; - - l4 { - regulator-min-microvolt = <2050000>; - regulator-max-microvolt = <2050000>; - }; - - l5 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - }; - - l6 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - }; - - l7 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - }; - - l8 { - regulator-min-microvolt = <2850000>; - regulator-max-microvolt = <2900000>; - }; - - l9 { - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - }; - - l10 { - regulator-min-microvolt = <2700000>; - regulator-max-microvolt = <2800000>; - }; - - l11 { - regulator-min-microvolt = <2950000>; - regulator-max-microvolt = <2950000>; - regulator-allow-set-load; - regulator-system-load = <200000>; - }; - - l12 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <2950000>; - }; - - l13 { - regulator-min-microvolt = <3075000>; - regulator-max-microvolt = <3075000>; - }; - - l14 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <3300000>; - }; - - l15 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <3300000>; - }; - - l16 { - regulator-min-microvolt = <2800000>; - regulator-max-microvolt = <3300000>; - }; - - l17 { - regulator-min-microvolt = <2850000>; - regulator-max-microvolt = <2850000>; - }; - - l18 { - regulator-min-microvolt = <2700000>; - regulator-max-microvolt = <2700000>; - }; -}; - -&msmgpio { +&tlmm { camera_flash_default: camera-flash-default-state { pins = "gpio31", "gpio32"; function = "gpio"; diff --git a/arch/arm64/boot/dts/qcom/msm8916-yiming-uz801v3.dts b/arch/arm64/boot/dts/qcom/msm8916-yiming-uz801v3.dts index 74ce6563be183f685678abb925ad71eb3c37602b..5e6ba8c58bb577274dfb3b0253bfef7ee6c3f211 100644 --- a/arch/arm64/boot/dts/qcom/msm8916-yiming-uz801v3.dts +++ b/arch/arm64/boot/dts/qcom/msm8916-yiming-uz801v3.dts @@ -10,19 +10,19 @@ }; &button_restart { - gpios = <&msmgpio 23 GPIO_ACTIVE_LOW>; + gpios = <&tlmm 23 GPIO_ACTIVE_LOW>; }; &led_r { - gpios = <&msmgpio 7 GPIO_ACTIVE_HIGH>; + gpios = <&tlmm 7 GPIO_ACTIVE_HIGH>; }; &led_g { - gpios = <&msmgpio 8 GPIO_ACTIVE_HIGH>; + gpios = <&tlmm 8 GPIO_ACTIVE_HIGH>; }; &led_b { - gpios = <&msmgpio 6 GPIO_ACTIVE_HIGH>; + gpios = <&tlmm 6 GPIO_ACTIVE_HIGH>; }; &button_default { diff --git a/arch/arm64/boot/dts/qcom/msm8916.dtsi b/arch/arm64/boot/dts/qcom/msm8916.dtsi index 834e0b66b7f2e68a477a9443894e80e9a1002dad..7582c7d748fe9a6c191e2ba9c72a552279134012 100644 --- a/arch/arm64/boot/dts/qcom/msm8916.dtsi +++ b/arch/arm64/boot/dts/qcom/msm8916.dtsi @@ -18,11 +18,6 @@ #address-cells = <2>; #size-cells = <2>; - aliases { - mmc0 = &sdhc_1; /* SDC1 eMMC slot */ - mmc1 = &sdhc_2; /* SDC2 SD card slot */ - }; - chosen { }; memory@80000000 { @@ -993,15 +988,494 @@ }; }; - msmgpio: pinctrl@1000000 { + tlmm: pinctrl@1000000 { compatible = "qcom,msm8916-pinctrl"; reg = <0x01000000 0x300000>; interrupts = ; gpio-controller; - gpio-ranges = <&msmgpio 0 0 122>; + gpio-ranges = <&tlmm 0 0 122>; #gpio-cells = <2>; interrupt-controller; #interrupt-cells = <2>; + + blsp_i2c1_default: blsp-i2c1-default-state { + pins = "gpio2", "gpio3"; + function = "blsp_i2c1"; + drive-strength = <2>; + bias-disable; + }; + + blsp_i2c1_sleep: blsp-i2c1-sleep-state { + pins = "gpio2", "gpio3"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + + blsp_i2c2_default: blsp-i2c2-default-state { + pins = "gpio6", "gpio7"; + function = "blsp_i2c2"; + drive-strength = <2>; + bias-disable; + }; + + blsp_i2c2_sleep: blsp-i2c2-sleep-state { + pins = "gpio6", "gpio7"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + + blsp_i2c3_default: blsp-i2c3-default-state { + pins = "gpio10", "gpio11"; + function = "blsp_i2c3"; + drive-strength = <2>; + bias-disable; + }; + + blsp_i2c3_sleep: blsp-i2c3-sleep-state { + pins = "gpio10", "gpio11"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + + blsp_i2c4_default: blsp-i2c4-default-state { + pins = "gpio14", "gpio15"; + function = "blsp_i2c4"; + drive-strength = <2>; + bias-disable; + }; + + blsp_i2c4_sleep: blsp-i2c4-sleep-state { + pins = "gpio14", "gpio15"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + + blsp_i2c5_default: blsp-i2c5-default-state { + pins = "gpio18", "gpio19"; + function = "blsp_i2c5"; + drive-strength = <2>; + bias-disable; + }; + + blsp_i2c5_sleep: blsp-i2c5-sleep-state { + pins = "gpio18", "gpio19"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + + blsp_i2c6_default: blsp-i2c6-default-state { + pins = "gpio22", "gpio23"; + function = "blsp_i2c6"; + drive-strength = <2>; + bias-disable; + }; + + blsp_i2c6_sleep: blsp-i2c6-sleep-state { + pins = "gpio22", "gpio23"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + + blsp_spi1_default: blsp-spi1-default-state { + spi-pins { + pins = "gpio0", "gpio1", "gpio3"; + function = "blsp_spi1"; + drive-strength = <12>; + bias-disable; + }; + cs-pins { + pins = "gpio2"; + function = "gpio"; + drive-strength = <16>; + bias-disable; + output-high; + }; + }; + + blsp_spi1_sleep: blsp-spi1-sleep-state { + pins = "gpio0", "gpio1", "gpio2", "gpio3"; + function = "gpio"; + drive-strength = <2>; + bias-pull-down; + }; + + blsp_spi2_default: blsp-spi2-default-state { + spi-pins { + pins = "gpio4", "gpio5", "gpio7"; + function = "blsp_spi2"; + drive-strength = <12>; + bias-disable; + }; + cs-pins { + pins = "gpio6"; + function = "gpio"; + drive-strength = <16>; + bias-disable; + output-high; + }; + }; + + blsp_spi2_sleep: blsp-spi2-sleep-state { + pins = "gpio4", "gpio5", "gpio6", "gpio7"; + function = "gpio"; + drive-strength = <2>; + bias-pull-down; + }; + + blsp_spi3_default: blsp-spi3-default-state { + spi-pins { + pins = "gpio8", "gpio9", "gpio11"; + function = "blsp_spi3"; + drive-strength = <12>; + bias-disable; + }; + cs-pins { + pins = "gpio10"; + function = "gpio"; + drive-strength = <16>; + bias-disable; + output-high; + }; + }; + + blsp_spi3_sleep: blsp-spi3-sleep-state { + pins = "gpio8", "gpio9", "gpio10", "gpio11"; + function = "gpio"; + drive-strength = <2>; + bias-pull-down; + }; + + blsp_spi4_default: blsp-spi4-default-state { + spi-pins { + pins = "gpio12", "gpio13", "gpio15"; + function = "blsp_spi4"; + drive-strength = <12>; + bias-disable; + }; + cs-pins { + pins = "gpio14"; + function = "gpio"; + drive-strength = <16>; + bias-disable; + output-high; + }; + }; + + blsp_spi4_sleep: blsp-spi4-sleep-state { + pins = "gpio12", "gpio13", "gpio14", "gpio15"; + function = "gpio"; + drive-strength = <2>; + bias-pull-down; + }; + + blsp_spi5_default: blsp-spi5-default-state { + spi-pins { + pins = "gpio16", "gpio17", "gpio19"; + function = "blsp_spi5"; + drive-strength = <12>; + bias-disable; + }; + cs-pins { + pins = "gpio18"; + function = "gpio"; + drive-strength = <16>; + bias-disable; + output-high; + }; + }; + + blsp_spi5_sleep: blsp-spi5-sleep-state { + pins = "gpio16", "gpio17", "gpio18", "gpio19"; + function = "gpio"; + drive-strength = <2>; + bias-pull-down; + }; + + blsp_spi6_default: blsp-spi6-default-state { + spi-pins { + pins = "gpio20", "gpio21", "gpio23"; + function = "blsp_spi6"; + drive-strength = <12>; + bias-disable; + }; + cs-pins { + pins = "gpio22"; + function = "gpio"; + drive-strength = <16>; + bias-disable; + output-high; + }; + }; + + blsp_spi6_sleep: blsp-spi6-sleep-state { + pins = "gpio20", "gpio21", "gpio22", "gpio23"; + function = "gpio"; + drive-strength = <2>; + bias-pull-down; + }; + + blsp_uart1_default: blsp-uart1-default-state { + /* TX, RX, CTS_N, RTS_N */ + pins = "gpio0", "gpio1", "gpio2", "gpio3"; + function = "blsp_uart1"; + drive-strength = <16>; + bias-disable; + }; + + blsp_uart1_sleep: blsp-uart1-sleep-state { + pins = "gpio0", "gpio1", "gpio2", "gpio3"; + function = "gpio"; + drive-strength = <2>; + bias-pull-down; + }; + + blsp_uart2_default: blsp-uart2-default-state { + pins = "gpio4", "gpio5"; + function = "blsp_uart2"; + drive-strength = <16>; + bias-disable; + }; + + blsp_uart2_sleep: blsp-uart2-sleep-state { + pins = "gpio4", "gpio5"; + function = "gpio"; + drive-strength = <2>; + bias-pull-down; + }; + + camera_front_default: camera-front-default-state { + pwdn-pins { + pins = "gpio33"; + function = "gpio"; + drive-strength = <16>; + bias-disable; + }; + rst-pins { + pins = "gpio28"; + function = "gpio"; + drive-strength = <16>; + bias-disable; + }; + mclk1-pins { + pins = "gpio27"; + function = "cam_mclk1"; + drive-strength = <16>; + bias-disable; + }; + }; + + camera_rear_default: camera-rear-default-state { + pwdn-pins { + pins = "gpio34"; + function = "gpio"; + drive-strength = <16>; + bias-disable; + }; + rst-pins { + pins = "gpio35"; + function = "gpio"; + drive-strength = <16>; + bias-disable; + }; + mclk0-pins { + pins = "gpio26"; + function = "cam_mclk0"; + drive-strength = <16>; + bias-disable; + }; + }; + + cci0_default: cci0-default-state { + pins = "gpio29", "gpio30"; + function = "cci_i2c"; + drive-strength = <16>; + bias-disable; + }; + + cdc_dmic_default: cdc-dmic-default-state { + clk-pins { + pins = "gpio0"; + function = "dmic0_clk"; + drive-strength = <8>; + }; + data-pins { + pins = "gpio1"; + function = "dmic0_data"; + drive-strength = <8>; + }; + }; + + cdc_dmic_sleep: cdc-dmic-sleep-state { + clk-pins { + pins = "gpio0"; + function = "dmic0_clk"; + drive-strength = <2>; + bias-disable; + }; + data-pins { + pins = "gpio1"; + function = "dmic0_data"; + drive-strength = <2>; + bias-disable; + }; + }; + + cdc_pdm_default: cdc-pdm-default-state { + pins = "gpio63", "gpio64", "gpio65", "gpio66", + "gpio67", "gpio68"; + function = "cdc_pdm0"; + drive-strength = <8>; + bias-disable; + }; + + cdc_pdm_sleep: cdc-pdm-sleep-state { + pins = "gpio63", "gpio64", "gpio65", "gpio66", + "gpio67", "gpio68"; + function = "cdc_pdm0"; + drive-strength = <2>; + bias-pull-down; + }; + + pri_mi2s_default: mi2s-pri-default-state { + pins = "gpio113", "gpio114", "gpio115", "gpio116"; + function = "pri_mi2s"; + drive-strength = <8>; + bias-disable; + }; + + pri_mi2s_sleep: mi2s-pri-sleep-state { + pins = "gpio113", "gpio114", "gpio115", "gpio116"; + function = "pri_mi2s"; + drive-strength = <2>; + bias-disable; + }; + + pri_mi2s_mclk_default: mi2s-pri-mclk-default-state { + pins = "gpio116"; + function = "pri_mi2s"; + drive-strength = <8>; + bias-disable; + }; + + pri_mi2s_mclk_sleep: mi2s-pri-mclk-sleep-state { + pins = "gpio116"; + function = "pri_mi2s"; + drive-strength = <2>; + bias-disable; + }; + + pri_mi2s_ws_default: mi2s-pri-ws-default-state { + pins = "gpio110"; + function = "pri_mi2s_ws"; + drive-strength = <8>; + bias-disable; + }; + + pri_mi2s_ws_sleep: mi2s-pri-ws-sleep-state { + pins = "gpio110"; + function = "pri_mi2s_ws"; + drive-strength = <2>; + bias-disable; + }; + + sec_mi2s_default: mi2s-sec-default-state { + pins = "gpio112", "gpio117", "gpio118", "gpio119"; + function = "sec_mi2s"; + drive-strength = <8>; + bias-disable; + }; + + sec_mi2s_sleep: mi2s-sec-sleep-state { + pins = "gpio112", "gpio117", "gpio118", "gpio119"; + function = "sec_mi2s"; + drive-strength = <2>; + bias-disable; + }; + + sdc1_default: sdc1-default-state { + clk-pins { + pins = "sdc1_clk"; + bias-disable; + drive-strength = <16>; + }; + cmd-pins { + pins = "sdc1_cmd"; + bias-pull-up; + drive-strength = <10>; + }; + data-pins { + pins = "sdc1_data"; + bias-pull-up; + drive-strength = <10>; + }; + }; + + sdc1_sleep: sdc1-sleep-state { + clk-pins { + pins = "sdc1_clk"; + bias-disable; + drive-strength = <2>; + }; + cmd-pins { + pins = "sdc1_cmd"; + bias-pull-up; + drive-strength = <2>; + }; + data-pins { + pins = "sdc1_data"; + bias-pull-up; + drive-strength = <2>; + }; + }; + + sdc2_default: sdc2-default-state { + clk-pins { + pins = "sdc2_clk"; + bias-disable; + drive-strength = <16>; + }; + cmd-pins { + pins = "sdc2_cmd"; + bias-pull-up; + drive-strength = <10>; + }; + data-pins { + pins = "sdc2_data"; + bias-pull-up; + drive-strength = <10>; + }; + }; + + sdc2_sleep: sdc2-sleep-state { + clk-pins { + pins = "sdc2_clk"; + bias-disable; + drive-strength = <2>; + }; + cmd-pins { + pins = "sdc2_cmd"; + bias-pull-up; + drive-strength = <2>; + }; + data-pins { + pins = "sdc2_data"; + bias-pull-up; + drive-strength = <2>; + }; + }; + + wcss_wlan_default: wcss-wlan-default-state { + pins = "gpio40", "gpio41", "gpio42", "gpio43", "gpio44"; + function = "wcss_wlan"; + drive-strength = <6>; + bias-pull-up; + }; }; gcc: clock-controller@1800000 { @@ -1012,8 +1486,8 @@ reg = <0x01800000 0x80000>; clocks = <&xo_board>, <&sleep_clk>, - <&dsi_phy0 1>, - <&dsi_phy0 0>, + <&mdss_dsi0_phy 1>, + <&mdss_dsi0_phy 0>, <0>, <0>, <0>; @@ -1062,7 +1536,7 @@ #size-cells = <1>; ranges; - mdp: display-controller@1a01000 { + mdss_mdp: display-controller@1a01000 { compatible = "qcom,msm8916-mdp5", "qcom,mdp5"; reg = <0x01a01000 0x89000>; reg-names = "mdp_phys"; @@ -1087,14 +1561,14 @@ port@0 { reg = <0>; - mdp5_intf1_out: endpoint { - remote-endpoint = <&dsi0_in>; + mdss_mdp_intf1_out: endpoint { + remote-endpoint = <&mdss_dsi0_in>; }; }; }; }; - dsi0: dsi@1a98000 { + mdss_dsi0: dsi@1a98000 { compatible = "qcom,msm8916-dsi-ctrl", "qcom,mdss-dsi-ctrl"; reg = <0x01a98000 0x25c>; @@ -1105,8 +1579,8 @@ assigned-clocks = <&gcc BYTE0_CLK_SRC>, <&gcc PCLK0_CLK_SRC>; - assigned-clock-parents = <&dsi_phy0 0>, - <&dsi_phy0 1>; + assigned-clock-parents = <&mdss_dsi0_phy 0>, + <&mdss_dsi0_phy 1>; clocks = <&gcc GCC_MDSS_MDP_CLK>, <&gcc GCC_MDSS_AHB_CLK>, @@ -1120,7 +1594,7 @@ "byte", "pixel", "core"; - phys = <&dsi_phy0>; + phys = <&mdss_dsi0_phy>; #address-cells = <1>; #size-cells = <0>; @@ -1131,20 +1605,20 @@ port@0 { reg = <0>; - dsi0_in: endpoint { - remote-endpoint = <&mdp5_intf1_out>; + mdss_dsi0_in: endpoint { + remote-endpoint = <&mdss_mdp_intf1_out>; }; }; port@1 { reg = <1>; - dsi0_out: endpoint { + mdss_dsi0_out: endpoint { }; }; }; }; - dsi_phy0: phy@1a98300 { + mdss_dsi0_phy: phy@1a98300 { compatible = "qcom,dsi-phy-28nm-lp"; reg = <0x01a98300 0xd4>, <0x01a98500 0x280>, @@ -1162,7 +1636,7 @@ }; }; - camss: camss@1b00000 { + camss: camss@1b0ac00 { compatible = "qcom,msm8916-camss"; reg = <0x01b0ac00 0x200>, <0x01b00030 0x4>, @@ -1520,20 +1994,20 @@ * Primary/Secondary MI2S both use the PRI_I2S_CLK. */ clocks = <&gcc GCC_ULTAUDIO_AHBFABRIC_IXFABRIC_CLK>, - <&gcc GCC_ULTAUDIO_PCNOC_MPORT_CLK>, - <&gcc GCC_ULTAUDIO_PCNOC_SWAY_CLK>, <&gcc GCC_ULTAUDIO_LPAIF_PRI_I2S_CLK>, <&gcc GCC_ULTAUDIO_LPAIF_PRI_I2S_CLK>, <&gcc GCC_ULTAUDIO_LPAIF_SEC_I2S_CLK>, - <&gcc GCC_ULTAUDIO_LPAIF_AUX_I2S_CLK>; + <&gcc GCC_ULTAUDIO_LPAIF_AUX_I2S_CLK>, + <&gcc GCC_ULTAUDIO_PCNOC_MPORT_CLK>, + <&gcc GCC_ULTAUDIO_PCNOC_SWAY_CLK>; clock-names = "ahbix-clk", - "pcnoc-mport-clk", - "pcnoc-sway-clk", "mi2s-bit-clk0", "mi2s-bit-clk1", "mi2s-bit-clk2", - "mi2s-bit-clk3"; + "mi2s-bit-clk3", + "pcnoc-mport-clk", + "pcnoc-sway-clk"; #sound-dai-cells = <1>; interrupts = ; @@ -1552,9 +2026,10 @@ <&gcc GCC_CODEC_DIGCODEC_CLK>; clock-names = "ahbix-clk", "mclk"; #sound-dai-cells = <1>; + status = "disabled"; }; - sdhc_1: mmc@7824000 { + sdhc_1: mmc@7824900 { compatible = "qcom,msm8916-sdhci", "qcom,sdhci-msm-v4"; reg = <0x07824900 0x11c>, <0x07824000 0x800>; reg-names = "hc", "core"; @@ -1566,13 +2041,16 @@ <&gcc GCC_SDCC1_APPS_CLK>, <&xo_board>; clock-names = "iface", "core", "xo"; + pinctrl-0 = <&sdc1_default>; + pinctrl-1 = <&sdc1_sleep>; + pinctrl-names = "default", "sleep"; mmc-ddr-1_8v; bus-width = <8>; non-removable; status = "disabled"; }; - sdhc_2: mmc@7864000 { + sdhc_2: mmc@7864900 { compatible = "qcom,msm8916-sdhci", "qcom,sdhci-msm-v4"; reg = <0x07864900 0x11c>, <0x07864000 0x800>; reg-names = "hc", "core"; @@ -1584,6 +2062,9 @@ <&gcc GCC_SDCC2_APPS_CLK>, <&xo_board>; clock-names = "iface", "core", "xo"; + pinctrl-0 = <&sdc2_default>; + pinctrl-1 = <&sdc2_sleep>; + pinctrl-names = "default", "sleep"; bus-width = <4>; status = "disabled"; }; @@ -1598,7 +2079,7 @@ qcom,ee = <0>; }; - blsp1_uart1: serial@78af000 { + blsp_uart1: serial@78af000 { compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm"; reg = <0x078af000 0x200>; interrupts = ; @@ -1607,12 +2088,12 @@ dmas = <&blsp_dma 0>, <&blsp_dma 1>; dma-names = "tx", "rx"; pinctrl-names = "default", "sleep"; - pinctrl-0 = <&blsp1_uart1_default>; - pinctrl-1 = <&blsp1_uart1_sleep>; + pinctrl-0 = <&blsp_uart1_default>; + pinctrl-1 = <&blsp_uart1_sleep>; status = "disabled"; }; - blsp1_uart2: serial@78b0000 { + blsp_uart2: serial@78b0000 { compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm"; reg = <0x078b0000 0x200>; interrupts = ; @@ -1621,8 +2102,8 @@ dmas = <&blsp_dma 2>, <&blsp_dma 3>; dma-names = "tx", "rx"; pinctrl-names = "default", "sleep"; - pinctrl-0 = <&blsp1_uart2_default>; - pinctrl-1 = <&blsp1_uart2_sleep>; + pinctrl-0 = <&blsp_uart2_default>; + pinctrl-1 = <&blsp_uart2_sleep>; status = "disabled"; }; @@ -1636,8 +2117,8 @@ dmas = <&blsp_dma 4>, <&blsp_dma 5>; dma-names = "tx", "rx"; pinctrl-names = "default", "sleep"; - pinctrl-0 = <&i2c1_default>; - pinctrl-1 = <&i2c1_sleep>; + pinctrl-0 = <&blsp_i2c1_default>; + pinctrl-1 = <&blsp_i2c1_sleep>; #address-cells = <1>; #size-cells = <0>; status = "disabled"; @@ -1653,8 +2134,8 @@ dmas = <&blsp_dma 4>, <&blsp_dma 5>; dma-names = "tx", "rx"; pinctrl-names = "default", "sleep"; - pinctrl-0 = <&spi1_default>; - pinctrl-1 = <&spi1_sleep>; + pinctrl-0 = <&blsp_spi1_default>; + pinctrl-1 = <&blsp_spi1_sleep>; #address-cells = <1>; #size-cells = <0>; status = "disabled"; @@ -1670,8 +2151,8 @@ dmas = <&blsp_dma 6>, <&blsp_dma 7>; dma-names = "tx", "rx"; pinctrl-names = "default", "sleep"; - pinctrl-0 = <&i2c2_default>; - pinctrl-1 = <&i2c2_sleep>; + pinctrl-0 = <&blsp_i2c2_default>; + pinctrl-1 = <&blsp_i2c2_sleep>; #address-cells = <1>; #size-cells = <0>; status = "disabled"; @@ -1687,8 +2168,8 @@ dmas = <&blsp_dma 6>, <&blsp_dma 7>; dma-names = "tx", "rx"; pinctrl-names = "default", "sleep"; - pinctrl-0 = <&spi2_default>; - pinctrl-1 = <&spi2_sleep>; + pinctrl-0 = <&blsp_spi2_default>; + pinctrl-1 = <&blsp_spi2_sleep>; #address-cells = <1>; #size-cells = <0>; status = "disabled"; @@ -1704,8 +2185,8 @@ dmas = <&blsp_dma 8>, <&blsp_dma 9>; dma-names = "tx", "rx"; pinctrl-names = "default", "sleep"; - pinctrl-0 = <&i2c3_default>; - pinctrl-1 = <&i2c3_sleep>; + pinctrl-0 = <&blsp_i2c3_default>; + pinctrl-1 = <&blsp_i2c3_sleep>; #address-cells = <1>; #size-cells = <0>; status = "disabled"; @@ -1721,8 +2202,8 @@ dmas = <&blsp_dma 8>, <&blsp_dma 9>; dma-names = "tx", "rx"; pinctrl-names = "default", "sleep"; - pinctrl-0 = <&spi3_default>; - pinctrl-1 = <&spi3_sleep>; + pinctrl-0 = <&blsp_spi3_default>; + pinctrl-1 = <&blsp_spi3_sleep>; #address-cells = <1>; #size-cells = <0>; status = "disabled"; @@ -1738,8 +2219,8 @@ dmas = <&blsp_dma 10>, <&blsp_dma 11>; dma-names = "tx", "rx"; pinctrl-names = "default", "sleep"; - pinctrl-0 = <&i2c4_default>; - pinctrl-1 = <&i2c4_sleep>; + pinctrl-0 = <&blsp_i2c4_default>; + pinctrl-1 = <&blsp_i2c4_sleep>; #address-cells = <1>; #size-cells = <0>; status = "disabled"; @@ -1755,8 +2236,8 @@ dmas = <&blsp_dma 10>, <&blsp_dma 11>; dma-names = "tx", "rx"; pinctrl-names = "default", "sleep"; - pinctrl-0 = <&spi4_default>; - pinctrl-1 = <&spi4_sleep>; + pinctrl-0 = <&blsp_spi4_default>; + pinctrl-1 = <&blsp_spi4_sleep>; #address-cells = <1>; #size-cells = <0>; status = "disabled"; @@ -1772,8 +2253,8 @@ dmas = <&blsp_dma 12>, <&blsp_dma 13>; dma-names = "tx", "rx"; pinctrl-names = "default", "sleep"; - pinctrl-0 = <&i2c5_default>; - pinctrl-1 = <&i2c5_sleep>; + pinctrl-0 = <&blsp_i2c5_default>; + pinctrl-1 = <&blsp_i2c5_sleep>; #address-cells = <1>; #size-cells = <0>; status = "disabled"; @@ -1789,8 +2270,8 @@ dmas = <&blsp_dma 12>, <&blsp_dma 13>; dma-names = "tx", "rx"; pinctrl-names = "default", "sleep"; - pinctrl-0 = <&spi5_default>; - pinctrl-1 = <&spi5_sleep>; + pinctrl-0 = <&blsp_spi5_default>; + pinctrl-1 = <&blsp_spi5_sleep>; #address-cells = <1>; #size-cells = <0>; status = "disabled"; @@ -1806,8 +2287,8 @@ dmas = <&blsp_dma 14>, <&blsp_dma 15>; dma-names = "tx", "rx"; pinctrl-names = "default", "sleep"; - pinctrl-0 = <&i2c6_default>; - pinctrl-1 = <&i2c6_sleep>; + pinctrl-0 = <&blsp_i2c6_default>; + pinctrl-1 = <&blsp_i2c6_sleep>; #address-cells = <1>; #size-cells = <0>; status = "disabled"; @@ -1823,8 +2304,8 @@ dmas = <&blsp_dma 14>, <&blsp_dma 15>; dma-names = "tx", "rx"; pinctrl-names = "default", "sleep"; - pinctrl-0 = <&spi6_default>; - pinctrl-1 = <&spi6_sleep>; + pinctrl-0 = <&blsp_spi6_default>; + pinctrl-1 = <&blsp_spi6_sleep>; #address-cells = <1>; #size-cells = <0>; status = "disabled"; @@ -1871,7 +2352,7 @@ }; }; - wcnss: remoteproc@a21b000 { + wcnss: remoteproc@a204000 { compatible = "qcom,pronto-v2-pil", "qcom,pronto"; reg = <0x0a204000 0x2000>, <0x0a202000 0x1000>, <0x0a21b000 0x3000>; reg-names = "ccu", "dxe", "pmu"; @@ -1893,7 +2374,7 @@ qcom,smem-state-names = "stop"; pinctrl-names = "default"; - pinctrl-0 = <&wcnss_pin_a>; + pinctrl-0 = <&wcss_wlan_default>; status = "disabled"; @@ -2190,5 +2671,3 @@ ; }; }; - -#include "msm8916-pins.dtsi" diff --git a/arch/arm64/boot/dts/qcom/msm8939-pm8916.dtsi b/arch/arm64/boot/dts/qcom/msm8939-pm8916.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..adb96cd8d643e5fde1ac95c0fc3c9c3c3efb07e8 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/msm8939-pm8916.dtsi @@ -0,0 +1,161 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * msm8939-pm8916.dtsi describes common properties (e.g. regulator connections) + * that apply to most devices that make use of the MSM8939 SoC and PM8916 PMIC. + * Many regulators have a fixed purpose in the original reference design and + * were rarely re-used for different purposes. Devices that deviate from the + * typical reference design should not make use of this include and instead add + * the necessary properties in the board-specific device tree. + */ + +#include "msm8939.dtsi" +#include "pm8916.dtsi" + +&mdss_dsi0 { + vdda-supply = <&pm8916_l2>; + vddio-supply = <&pm8916_l6>; +}; + +&mdss_dsi0_phy { + vddio-supply = <&pm8916_l6>; +}; + +&mdss_dsi1 { + vdda-supply = <&pm8916_l2>; + vddio-supply = <&pm8916_l6>; +}; + +&mdss_dsi1_phy { + vddio-supply = <&pm8916_l6>; +}; + +&mpss { + pll-supply = <&pm8916_l7>; +}; + +&pm8916_codec { + vdd-cdc-io-supply = <&pm8916_l5>; + vdd-cdc-tx-rx-cx-supply = <&pm8916_l5>; + vdd-micbias-supply = <&pm8916_l13>; +}; + +&rpm_requests { + pm8916_rpm_regulators: regulators { + compatible = "qcom,rpm-pm8916-regulators"; + vdd_l1_l2_l3-supply = <&pm8916_s3>; + vdd_l4_l5_l6-supply = <&pm8916_s4>; + vdd_l7-supply = <&pm8916_s4>; + + /* pm8916_s1 is managed by rpmpd (MSM8939_VDDMDCX) */ + /* pm8916_s2 is managed by rpmpd (MSM8939_VDDCX) */ + pm8916_s3: s3 { + regulator-min-microvolt = <1250000>; + regulator-max-microvolt = <1350000>; + regulator-always-on; /* Needed for L2 */ + }; + pm8916_s4: s4 { + regulator-min-microvolt = <1850000>; + regulator-max-microvolt = <2150000>; + regulator-always-on; /* Needed for L5/L7 */ + }; + + /* + * Some of the regulators are unused or managed by another + * processor (e.g. the modem). We should still define nodes for + * them to ensure the vote from the application processor can be + * dropped in case the regulators are already on during boot. + * + * The labels for these nodes are omitted on purpose because + * boards should configure a proper voltage before using them. + */ + l1 {}; + + pm8916_l2: l2 { + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-always-on; /* Needed for LPDDR RAM */ + }; + + /* pm8916_l3 is managed by rpmpd (MSM8939_VDDMX) */ + + l4 {}; + + pm8916_l5: l5 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; /* Needed for most digital I/O */ + }; + + pm8916_l6: l6 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + pm8916_l7: l7 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; /* Needed for CPU PLL */ + }; + + pm8916_l8: l8 { + regulator-min-microvolt = <2900000>; + regulator-max-microvolt = <2900000>; + }; + + pm8916_l9: l9 { + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + l10 {}; + + pm8916_l11: l11 { + regulator-min-microvolt = <2950000>; + regulator-max-microvolt = <2950000>; + regulator-allow-set-load; + regulator-system-load = <200000>; + }; + + pm8916_l12: l12 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <2950000>; + }; + + pm8916_l13: l13 { + regulator-min-microvolt = <3075000>; + regulator-max-microvolt = <3075000>; + }; + + l14 {}; + l15 {}; + l16 {}; + l17 {}; + l18 {}; + }; +}; + +&sdhc_1 { + vmmc-supply = <&pm8916_l8>; + vqmmc-supply = <&pm8916_l5>; +}; + +&sdhc_2 { + vmmc-supply = <&pm8916_l11>; + vqmmc-supply = <&pm8916_l12>; +}; + +&usb_hs_phy { + v1p8-supply = <&pm8916_l7>; + v3p3-supply = <&pm8916_l13>; +}; + +&wcnss { + vddpx-supply = <&pm8916_l7>; +}; + +&wcnss_iris { + vddxo-supply = <&pm8916_l7>; + vddrfa-supply = <&pm8916_s3>; + vddpa-supply = <&pm8916_l9>; + vdddig-supply = <&pm8916_l5>; +}; diff --git a/arch/arm64/boot/dts/qcom/msm8939-sony-xperia-kanuti-tulip.dts b/arch/arm64/boot/dts/qcom/msm8939-sony-xperia-kanuti-tulip.dts new file mode 100644 index 0000000000000000000000000000000000000000..8613cf93dac58bbb4c4937a57bbc3552f125f4c1 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/msm8939-sony-xperia-kanuti-tulip.dts @@ -0,0 +1,88 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2015, The Linux Foundation. All rights reserved. + * Copyright (c) 2022-2023, Bryan O'Donoghue. + * + */ + +/dts-v1/; + +#include "msm8939.dtsi" +#include "msm8939-pm8916.dtsi" +#include +#include +#include + +/ { + model = "Sony Xperia M4 Aqua"; + compatible = "sony,kanuti-tulip", "qcom,msm8939"; + + qcom,board-id = ; + qcom,msm-id = , ; + + aliases { + mmc0 = &sdhc_1; /* SDC1 eMMC slot */ + mmc1 = &sdhc_2; /* SDC2 SD card slot */ + serial0 = &blsp_uart2; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + usb_id: usb-id { + compatible = "linux,extcon-usb-gpio"; + id-gpio = <&tlmm 110 GPIO_ACTIVE_HIGH>; + pinctrl-0 = <&usb_id_default>; + pinctrl-names = "default"; + }; +}; + +&mdss { + status = "okay"; +}; + +&tlmm { + sdc2_cd_default: sdc2-cd-default-state { + pins = "gpio38"; + function = "gpio"; + drive-strength = <2>; + bias-pull-up; + }; + + usb_id_default: usb-id-default-state { + pins = "gpio110"; + function = "gpio"; + bias-pull-up; + drive-strength = <8>; + }; +}; + +&sdhc_1 { + status = "okay"; +}; + +&sdhc_2 { + pinctrl-0 = <&sdc2_default &sdc2_cd_default>; + pinctrl-1 = <&sdc2_sleep &sdc2_cd_default>; + pinctrl-names = "default", "sleep"; + cd-gpios = <&tlmm 38 GPIO_ACTIVE_HIGH>; + status = "okay"; +}; + +&usb { + extcon = <&usb_id>, <&usb_id>; + status = "okay"; +}; + +&usb_hs_phy { + extcon = <&usb_id>; +}; + +&wcnss { + status = "okay"; +}; + +&wcnss_iris { + compatible = "qcom,wcn3660"; +}; diff --git a/arch/arm64/boot/dts/qcom/msm8939.dtsi b/arch/arm64/boot/dts/qcom/msm8939.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..895cafc11480b6f0ba0ca33b299c2b7af5ee16ee --- /dev/null +++ b/arch/arm64/boot/dts/qcom/msm8939.dtsi @@ -0,0 +1,2436 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. + * Copyright (c) 2020-2023, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include + +/ { + interrupt-parent = <&intc>; + + /* + * Stock LK wants address-cells/size-cells = 2 + * A number of our drivers want address/size cells = 1 + * hence the disparity between top-level and /soc below. + */ + #address-cells = <2>; + #size-cells = <2>; + + clocks { + xo_board: xo-board { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <19200000>; + }; + + sleep_clk: sleep-clk { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <32768>; + }; + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + CPU0: cpu@100 { + compatible = "arm,cortex-a53"; + device_type = "cpu"; + enable-method = "spin-table"; + reg = <0x100>; + next-level-cache = <&L2_1>; + qcom,acc = <&acc0>; + qcom,saw = <&saw0>; + cpu-idle-states = <&CPU_SLEEP_0>; + clocks = <&apcs1_mbox>; + #cooling-cells = <2>; + L2_1: l2-cache { + compatible = "cache"; + cache-level = <2>; + }; + }; + + CPU1: cpu@101 { + compatible = "arm,cortex-a53"; + device_type = "cpu"; + enable-method = "spin-table"; + reg = <0x101>; + next-level-cache = <&L2_1>; + qcom,acc = <&acc1>; + qcom,saw = <&saw1>; + cpu-idle-states = <&CPU_SLEEP_0>; + clocks = <&apcs1_mbox>; + #cooling-cells = <2>; + }; + + CPU2: cpu@102 { + compatible = "arm,cortex-a53"; + device_type = "cpu"; + enable-method = "spin-table"; + reg = <0x102>; + next-level-cache = <&L2_1>; + qcom,acc = <&acc2>; + qcom,saw = <&saw2>; + cpu-idle-states = <&CPU_SLEEP_0>; + clocks = <&apcs1_mbox>; + #cooling-cells = <2>; + }; + + CPU3: cpu@103 { + compatible = "arm,cortex-a53"; + device_type = "cpu"; + enable-method = "spin-table"; + reg = <0x103>; + next-level-cache = <&L2_1>; + qcom,acc = <&acc3>; + qcom,saw = <&saw3>; + cpu-idle-states = <&CPU_SLEEP_0>; + clocks = <&apcs1_mbox>; + #cooling-cells = <2>; + }; + + CPU4: cpu@0 { + compatible = "arm,cortex-a53"; + device_type = "cpu"; + enable-method = "spin-table"; + reg = <0x0>; + qcom,acc = <&acc4>; + qcom,saw = <&saw4>; + cpu-idle-states = <&CPU_SLEEP_0>; + clocks = <&apcs0_mbox>; + #cooling-cells = <2>; + next-level-cache = <&L2_0>; + L2_0: l2-cache { + compatible = "cache"; + cache-level = <2>; + }; + }; + + CPU5: cpu@1 { + compatible = "arm,cortex-a53"; + device_type = "cpu"; + enable-method = "spin-table"; + reg = <0x1>; + next-level-cache = <&L2_0>; + qcom,acc = <&acc5>; + qcom,saw = <&saw5>; + cpu-idle-states = <&CPU_SLEEP_0>; + clocks = <&apcs0_mbox>; + #cooling-cells = <2>; + }; + + CPU6: cpu@2 { + compatible = "arm,cortex-a53"; + device_type = "cpu"; + enable-method = "spin-table"; + reg = <0x2>; + next-level-cache = <&L2_0>; + qcom,acc = <&acc6>; + qcom,saw = <&saw6>; + cpu-idle-states = <&CPU_SLEEP_0>; + clocks = <&apcs0_mbox>; + #cooling-cells = <2>; + }; + + CPU7: cpu@3 { + compatible = "arm,cortex-a53"; + device_type = "cpu"; + enable-method = "spin-table"; + reg = <0x3>; + next-level-cache = <&L2_0>; + qcom,acc = <&acc7>; + qcom,saw = <&saw7>; + cpu-idle-states = <&CPU_SLEEP_0>; + clocks = <&apcs0_mbox>; + #cooling-cells = <2>; + }; + + idle-states { + CPU_SLEEP_0: cpu-sleep-0 { + compatible ="qcom,idle-state-spc", "arm,idle-state"; + entry-latency-us = <130>; + exit-latency-us = <150>; + min-residency-us = <2000>; + local-timer-stop; + }; + }; + }; + + /* + * MSM8939 has a big.LITTLE heterogeneous computing architecture, + * consisting of two clusters of four ARM Cortex-A53s each. The + * LITTLE cluster runs at 1.0-1.2GHz, and the big cluster runs + * at 1.5-1.7GHz. + * + * The enable method used here is spin-table which presupposes use + * of a 2nd stage boot shim such as lk2nd to have installed a + * spin-table, the downstream non-psci/non-spin-table method that + * default msm8916/msm8936/msm8939 will not be supported upstream. + */ + cpu-map { + /* LITTLE (efficiency) cluster */ + cluster0 { + core0 { + cpu = <&CPU4>; + }; + + core1 { + cpu = <&CPU5>; + }; + + core2 { + cpu = <&CPU6>; + }; + + core3 { + cpu = <&CPU7>; + }; + }; + + /* big (performance) cluster */ + /* Boot CPU is cluster 1 core 0 */ + cluster1 { + core0 { + cpu = <&CPU0>; + }; + + core1 { + cpu = <&CPU1>; + }; + + core2 { + cpu = <&CPU2>; + }; + + core3 { + cpu = <&CPU3>; + }; + }; + }; + + firmware { + scm: scm { + compatible = "qcom,scm-msm8916", "qcom,scm"; + clocks = <&gcc GCC_CRYPTO_CLK>, + <&gcc GCC_CRYPTO_AXI_CLK>, + <&gcc GCC_CRYPTO_AHB_CLK>; + clock-names = "core", "bus", "iface"; + #reset-cells = <1>; + + qcom,dload-mode = <&tcsr 0x6100>; + }; + }; + + memory@80000000 { + device_type = "memory"; + /* We expect the bootloader to fill in the reg */ + reg = <0x0 0x80000000 0x0 0x0>; + }; + + pmu { + compatible = "arm,cortex-a53-pmu"; + interrupts = ; + }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + + tz-apps@86000000 { + reg = <0x0 0x86000000 0x0 0x300000>; + no-map; + }; + + smem@86300000 { + compatible = "qcom,smem"; + reg = <0x0 0x86300000 0x0 0x100000>; + no-map; + + hwlocks = <&tcsr_mutex 3>; + qcom,rpm-msg-ram = <&rpm_msg_ram>; + }; + + hypervisor@86400000 { + reg = <0x0 0x86400000 0x0 0x100000>; + no-map; + }; + + tz@86500000 { + reg = <0x0 0x86500000 0x0 0x180000>; + no-map; + }; + + reserved@86680000 { + reg = <0x0 0x86680000 0x0 0x80000>; + no-map; + }; + + rmtfs@86700000 { + compatible = "qcom,rmtfs-mem"; + reg = <0x0 0x86700000 0x0 0xe0000>; + no-map; + + qcom,client-id = <1>; + }; + + rfsa@867e0000 { + reg = <0x0 0x867e0000 0x0 0x20000>; + no-map; + }; + + mpss_mem: mpss@86800000 { + reg = <0x0 0x86800000 0x0 0x5500000>; + no-map; + }; + + wcnss_mem: wcnss@8bd00000 { + reg = <0x0 0x8bd00000 0x0 0x600000>; + no-map; + }; + + venus_mem: venus@8c300000 { + reg = <0x0 0x8c300000 0x0 0x800000>; + no-map; + }; + + mba_mem: mba@8cb00000 { + reg = <0x0 0x8cb00000 0x0 0x100000>; + no-map; + }; + }; + + smd { + compatible = "qcom,smd"; + + rpm { + interrupts = ; + qcom,ipc = <&apcs1_mbox 8 0>; + qcom,smd-edge = <15>; + + rpm_requests: rpm-requests { + compatible = "qcom,rpm-msm8936"; + qcom,smd-channels = "rpm_requests"; + + rpmcc: clock-controller { + compatible = "qcom,rpmcc-msm8936", "qcom,rpmcc"; + #clock-cells = <1>; + clock-names = "xo"; + clocks = <&xo_board>; + }; + + rpmpd: power-controller { + compatible = "qcom,msm8939-rpmpd"; + #power-domain-cells = <1>; + operating-points-v2 = <&rpmpd_opp_table>; + + rpmpd_opp_table: opp-table { + compatible = "operating-points-v2"; + + rpmpd_opp_ret: opp1 { + opp-level = <1>; + }; + + rpmpd_opp_svs_krait: opp2 { + opp-level = <2>; + }; + + rpmpd_opp_svs_soc: opp3 { + opp-level = <3>; + }; + + rpmpd_opp_nom: opp4 { + opp-level = <4>; + }; + + rpmpd_opp_turbo: opp5 { + opp-level = <5>; + }; + + rpmpd_opp_super_turbo: opp6 { + opp-level = <6>; + }; + }; + }; + }; + }; + }; + + smp2p-hexagon { + compatible = "qcom,smp2p"; + qcom,smem = <435>, <428>; + + interrupts = ; + + mboxes = <&apcs1_mbox 14>; + + qcom,local-pid = <0>; + qcom,remote-pid = <1>; + + hexagon_smp2p_out: master-kernel { + qcom,entry-name = "master-kernel"; + + #qcom,smem-state-cells = <1>; + }; + + hexagon_smp2p_in: slave-kernel { + qcom,entry-name = "slave-kernel"; + + interrupt-controller; + #interrupt-cells = <2>; + #address-cells = <0>; + #size-cells = <0>; + }; + }; + + smp2p-wcnss { + compatible = "qcom,smp2p"; + qcom,smem = <451>, <431>; + + interrupts = ; + + mboxes = <&apcs1_mbox 18>; + + qcom,local-pid = <0>; + qcom,remote-pid = <4>; + + wcnss_smp2p_in: slave-kernel { + qcom,entry-name = "slave-kernel"; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + wcnss_smp2p_out: master-kernel { + qcom,entry-name = "master-kernel"; + + #qcom,smem-state-cells = <1>; + }; + }; + + smsm { + compatible = "qcom,smsm"; + + #address-cells = <1>; + #size-cells = <0>; + + qcom,ipc-1 = <&apcs1_mbox 8 13>; + qcom,ipc-3 = <&apcs1_mbox 8 19>; + + apps_smsm: apps@0 { + reg = <0>; + + #qcom,smem-state-cells = <1>; + }; + + hexagon_smsm: hexagon@1 { + reg = <1>; + interrupts = ; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + wcnss_smsm: wcnss@6 { + reg = <6>; + interrupts = ; + + interrupt-controller; + #interrupt-cells = <2>; + }; + }; + + soc: soc@0 { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0 0 0xffffffff>; + + rng@22000 { + compatible = "qcom,prng"; + reg = <0x00022000 0x200>; + clocks = <&gcc GCC_PRNG_AHB_CLK>; + clock-names = "core"; + }; + + qfprom: qfprom@5c000 { + compatible = "qcom,msm8916-qfprom", "qcom,qfprom"; + reg = <0x0005c000 0x1000>; + #address-cells = <1>; + #size-cells = <1>; + + tsens_base1: base1@a0 { + reg = <0xa0 0x1>; + bits = <0 8>; + }; + + tsens_s6_p1: s6-p1@a1 { + reg = <0xa1 0x1>; + bits = <0 6>; + }; + + tsens_s6_p2: s6-p2@a1 { + reg = <0xa1 0x2>; + bits = <6 6>; + }; + + tsens_s7_p1: s7-p1@a2 { + reg = <0xa2 0x2>; + bits = <4 6>; + }; + + tsens_s7_p2: s7-p2@a3 { + reg = <0xa3 0x1>; + bits = <2 6>; + }; + + tsens_s8_p1: s8-p1@a4 { + reg = <0xa4 0x1>; + bits = <0 6>; + }; + + tsens_s8_p2: s8-p2@a4 { + reg = <0xa4 0x2>; + bits = <6 6>; + }; + + tsens_s9_p1: s9-p1@a5 { + reg = <0xa5 0x2>; + bits = <4 6>; + }; + + tsens_s9_p2: s9-p2@a6 { + reg = <0xa6 0x1>; + bits = <2 6>; + }; + + tsens_base2: base2@a7 { + reg = <0xa7 0x1>; + bits = <0 8>; + }; + + tsens_mode: mode@d0 { + reg = <0xd0 0x1>; + bits = <0 3>; + }; + + tsens_s0_p1: s0-p1@d0 { + reg = <0xd0 0x2>; + bits = <3 6>; + }; + + tsens_s0_p2: s0-p1@d1 { + reg = <0xd1 0x1>; + bits = <1 6>; + }; + + tsens_s1_p1: s1-p1@d1 { + reg = <0xd1 0x2>; + bits = <7 6>; + }; + + tsens_s1_p2: s1-p2@d2 { + reg = <0xd2 0x2>; + bits = <5 6>; + }; + + tsens_s2_p1: s2-p1@d3 { + reg = <0xd3 0x2>; + bits = <3 6>; + }; + + tsens_s2_p2: s2-p2@d4 { + reg = <0xd4 0x1>; + bits = <1 6>; + }; + + tsens_s3_p1: s3-p1@d4 { + reg = <0xd4 0x2>; + bits = <7 6>; + }; + + tsens_s3_p2: s3-p2@d5 { + reg = <0xd5 0x2>; + bits = <5 6>; + }; + + tsens_s5_p1: s5-p1@d6 { + reg = <0xd6 0x2>; + bits = <3 6>; + }; + + tsens_s5_p2: s5-p2@d7 { + reg = <0xd7 0x1>; + bits = <1 6>; + }; + }; + + rpm_msg_ram: sram@60000 { + compatible = "qcom,rpm-msg-ram"; + reg = <0x00060000 0x8000>; + }; + + bimc: interconnect@400000 { + compatible = "qcom,msm8939-bimc"; + reg = <0x00400000 0x62000>; + clock-names = "bus", "bus_a"; + clocks = <&rpmcc RPM_SMD_BIMC_CLK>, + <&rpmcc RPM_SMD_BIMC_A_CLK>; + #interconnect-cells = <1>; + }; + + tsens: thermal-sensor@4a9000 { + compatible = "qcom,msm8939-tsens", "qcom,tsens-v0_1"; + reg = <0x004a9000 0x1000>, /* TM */ + <0x004a8000 0x1000>; /* SROT */ + nvmem-cells = <&tsens_mode>, + <&tsens_base1>, <&tsens_base2>, + <&tsens_s0_p1>, <&tsens_s0_p2>, + <&tsens_s1_p1>, <&tsens_s1_p2>, + <&tsens_s2_p1>, <&tsens_s2_p2>, + <&tsens_s3_p1>, <&tsens_s3_p2>, + <&tsens_s5_p1>, <&tsens_s5_p2>, + <&tsens_s6_p1>, <&tsens_s6_p2>, + <&tsens_s7_p1>, <&tsens_s7_p2>, + <&tsens_s8_p1>, <&tsens_s8_p2>, + <&tsens_s9_p1>, <&tsens_s9_p2>; + nvmem-cell-names = "mode", + "base1", "base2", + "s0_p1", "s0_p2", + "s1_p1", "s1_p2", + "s2_p1", "s2_p2", + "s3_p1", "s3_p2", + "s5_p1", "s5_p2", + "s6_p1", "s6_p2", + "s7_p1", "s7_p2", + "s8_p1", "s8_p2", + "s9_p1", "s9_p2"; + #qcom,sensors = <9>; + interrupts = ; + interrupt-names = "uplow"; + #thermal-sensor-cells = <1>; + }; + + restart@4ab000 { + compatible = "qcom,pshold"; + reg = <0x004ab000 0x4>; + }; + + pcnoc: interconnect@500000 { + compatible = "qcom,msm8939-pcnoc"; + reg = <0x00500000 0x11000>; + clock-names = "bus", "bus_a"; + clocks = <&rpmcc RPM_SMD_PCNOC_CLK>, + <&rpmcc RPM_SMD_PCNOC_A_CLK>; + #interconnect-cells = <1>; + }; + + snoc: interconnect@580000 { + compatible = "qcom,msm8939-snoc"; + reg = <0x00580000 0x14080>; + clock-names = "bus", "bus_a"; + clocks = <&rpmcc RPM_SMD_SNOC_CLK>, + <&rpmcc RPM_SMD_SNOC_A_CLK>; + #interconnect-cells = <1>; + + snoc_mm: interconnect-snoc { + compatible = "qcom,msm8939-snoc-mm"; + clock-names = "bus", "bus_a"; + clocks = <&rpmcc RPM_SMD_SYSMMNOC_CLK>, + <&rpmcc RPM_SMD_SYSMMNOC_A_CLK>; + #interconnect-cells = <1>; + }; + }; + + tlmm: pinctrl@1000000 { + compatible = "qcom,msm8916-pinctrl"; + reg = <0x01000000 0x300000>; + interrupts = ; + gpio-controller; + gpio-ranges = <&tlmm 0 0 122>; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + + blsp_i2c1_default: blsp-i2c1-default-state { + pins = "gpio2", "gpio3"; + function = "blsp_i2c1"; + drive-strength = <2>; + bias-disable; + }; + + blsp_i2c1_sleep: blsp-i2c1-sleep-state { + pins = "gpio2", "gpio3"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + + blsp_i2c2_default: blsp-i2c2-default-state { + pins = "gpio6", "gpio7"; + function = "blsp_i2c2"; + drive-strength = <2>; + bias-disable; + }; + + blsp_i2c2_sleep: blsp-i2c2-sleep-state { + pins = "gpio6", "gpio7"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + + blsp_i2c3_default: blsp-i2c3-default-state { + pins = "gpio10", "gpio11"; + function = "blsp_i2c3"; + drive-strength = <2>; + bias-disable; + }; + + blsp_i2c3_sleep: blsp-i2c3-sleep-state { + pins = "gpio10", "gpio11"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + + blsp_i2c4_default: blsp-i2c4-default-state { + pins = "gpio14", "gpio15"; + function = "blsp_i2c4"; + drive-strength = <2>; + bias-disable; + }; + + blsp_i2c4_sleep: blsp-i2c4-sleep-state { + pins = "gpio14", "gpio15"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + + blsp_i2c5_default: blsp-i2c5-default-state { + pins = "gpio18", "gpio19"; + function = "blsp_i2c5"; + drive-strength = <2>; + bias-disable; + }; + + blsp_i2c5_sleep: blsp-i2c5-sleep-state { + pins = "gpio18", "gpio19"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + + blsp_i2c6_default: blsp-i2c6-default-state { + pins = "gpio22", "gpio23"; + function = "blsp_i2c6"; + drive-strength = <2>; + bias-disable; + }; + + blsp_i2c6_sleep: blsp-i2c6-sleep-state { + pins = "gpio22", "gpio23"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + + blsp_spi1_default: blsp-spi1-default-state { + spi-pins { + pins = "gpio0", "gpio1", "gpio3"; + function = "blsp_spi1"; + drive-strength = <12>; + bias-disable; + }; + + cs-pins { + pins = "gpio2"; + function = "gpio"; + drive-strength = <16>; + bias-disable; + output-high; + }; + }; + + blsp_spi1_sleep: blsp-spi1-sleep-state { + pins = "gpio0", "gpio1", "gpio2", "gpio3"; + function = "gpio"; + drive-strength = <2>; + bias-pull-down; + }; + + blsp_spi2_default: blsp-spi2-default-state { + spi-pins { + pins = "gpio4", "gpio5", "gpio7"; + function = "blsp_spi2"; + drive-strength = <12>; + bias-disable; + }; + + cs-pins { + pins = "gpio6"; + function = "gpio"; + drive-strength = <16>; + bias-disable; + output-high; + }; + }; + + blsp_spi2_sleep: blsp-spi2-sleep-state { + pins = "gpio4", "gpio5", "gpio6", "gpio7"; + function = "gpio"; + drive-strength = <2>; + bias-pull-down; + }; + + blsp_spi3_default: blsp-spi3-default-state { + spi-pins { + pins = "gpio8", "gpio9", "gpio11"; + function = "blsp_spi3"; + drive-strength = <12>; + bias-disable; + }; + + cs-pins { + pins = "gpio10"; + function = "gpio"; + drive-strength = <16>; + bias-disable; + output-high; + }; + }; + + blsp_spi3_sleep: blsp-spi3-sleep-state { + pins = "gpio8", "gpio9", "gpio10", "gpio11"; + function = "gpio"; + drive-strength = <2>; + bias-pull-down; + }; + + blsp_spi4_default: blsp-spi4-default-state { + spi-pins { + pins = "gpio12", "gpio13", "gpio15"; + function = "blsp_spi4"; + drive-strength = <12>; + bias-disable; + }; + + cs-pins { + pins = "gpio14"; + function = "gpio"; + drive-strength = <16>; + bias-disable; + output-high; + }; + }; + + blsp_spi4_sleep: blsp-spi4-sleep-state { + pins = "gpio12", "gpio13", "gpio14", "gpio15"; + function = "gpio"; + drive-strength = <2>; + bias-pull-down; + }; + + blsp_spi5_default: blsp-spi5-default-state { + spi-pins { + pins = "gpio16", "gpio17", "gpio19"; + function = "blsp_spi5"; + drive-strength = <12>; + bias-disable; + }; + + cs-pins { + pins = "gpio18"; + function = "gpio"; + drive-strength = <16>; + bias-disable; + output-high; + }; + }; + + blsp_spi5_sleep: blsp-spi5-sleep-state { + pins = "gpio16", "gpio17", "gpio18", "gpio19"; + function = "gpio"; + drive-strength = <2>; + bias-pull-down; + }; + + blsp_spi6_default: blsp-spi6-default-state { + spi-pins { + pins = "gpio20", "gpio21", "gpio23"; + function = "blsp_spi6"; + drive-strength = <12>; + bias-disable; + }; + + cs-pins { + pins = "gpio22"; + function = "gpio"; + drive-strength = <16>; + bias-disable; + output-high; + }; + }; + + blsp_spi6_sleep: blsp-spi6-sleep-state { + pins = "gpio20", "gpio21", "gpio22", "gpio23"; + function = "gpio"; + drive-strength = <2>; + bias-pull-down; + }; + + blsp_uart1_default: blsp-uart1-default-state { + pins = "gpio0", "gpio1", "gpio2", "gpio3"; + function = "blsp_uart1"; + drive-strength = <16>; + bias-disable; + }; + + blsp_uart1_sleep: blsp-uart1-sleep-state { + pins = "gpio0", "gpio1", "gpio2", "gpio3"; + function = "gpio"; + drive-strength = <2>; + bias-pull-down; + }; + + blsp_uart2_default: blsp-uart2-default-state { + pins = "gpio4", "gpio5"; + function = "blsp_uart2"; + drive-strength = <16>; + bias-disable; + }; + + blsp_uart2_sleep: blsp-uart2-sleep-state { + pins = "gpio4", "gpio5"; + function = "gpio"; + drive-strength = <2>; + bias-pull-down; + }; + + camera_front_default: camera-front-default-state { + pwdn-pins { + pins = "gpio33"; + function = "gpio"; + drive-strength = <16>; + bias-disable; + }; + + rst-pins { + pins = "gpio28"; + function = "gpio"; + drive-strength = <16>; + bias-disable; + }; + + mclk1-pins { + pins = "gpio27"; + function = "cam_mclk1"; + drive-strength = <16>; + bias-disable; + }; + }; + + camera_rear_default: camera-rear-default-state { + pwdn-pins { + pins = "gpio34"; + function = "gpio"; + drive-strength = <16>; + bias-disable; + }; + + rst-pins { + pins = "gpio35"; + function = "gpio"; + drive-strength = <16>; + bias-disable; + }; + + mclk0-pins { + pins = "gpio26"; + function = "cam_mclk0"; + drive-strength = <16>; + bias-disable; + }; + }; + + cci0_default: cci0-default-state { + pins = "gpio29", "gpio30"; + function = "cci_i2c"; + drive-strength = <16>; + bias-disable; + }; + + cdc_dmic_default: cdc-dmic-default-state { + clk-pins { + pins = "gpio0"; + function = "dmic0_clk"; + drive-strength = <8>; + }; + + data-pins { + pins = "gpio1"; + function = "dmic0_data"; + drive-strength = <8>; + }; + }; + + cdc_dmic_sleep: cdc-dmic-sleep-state { + clk-pins { + pins = "gpio0"; + function = "dmic0_clk"; + drive-strength = <2>; + bias-disable; + }; + + data-pins { + pins = "gpio1"; + function = "dmic0_data"; + drive-strength = <2>; + bias-disable; + }; + }; + + cdc_pdm_default: cdc-pdm-default-state { + pins = "gpio63", "gpio64", "gpio65", "gpio66", + "gpio67", "gpio68"; + function = "cdc_pdm0"; + drive-strength = <8>; + bias-disable; + }; + + cdc_pdm_sleep: cdc-pdm-sleep-state { + pins = "gpio63", "gpio64", "gpio65", "gpio66", + "gpio67", "gpio68"; + function = "cdc_pdm0"; + drive-strength = <2>; + bias-pull-down; + }; + + pri_mi2s_default: mi2s-pri-default-state { + pins = "gpio113", "gpio114", "gpio115", "gpio116"; + function = "pri_mi2s"; + drive-strength = <8>; + bias-disable; + }; + + pri_mi2s_sleep: mi2s-pri-sleep-state { + pins = "gpio113", "gpio114", "gpio115", "gpio116"; + function = "pri_mi2s"; + drive-strength = <2>; + bias-disable; + }; + + pri_mi2s_mclk_default: mi2s-pri-mclk-default-state { + pins = "gpio116"; + function = "pri_mi2s"; + drive-strength = <8>; + bias-disable; + }; + + pri_mi2s_mclk_sleep: mi2s-pri-mclk-sleep-state { + pins = "gpio116"; + function = "pri_mi2s"; + drive-strength = <2>; + bias-disable; + }; + + pri_mi2s_ws_default: mi2s-pri-ws-default-state { + pins = "gpio110"; + function = "pri_mi2s_ws"; + drive-strength = <8>; + bias-disable; + }; + + pri_mi2s_ws_sleep: mi2s-pri-ws-sleep-state { + pins = "gpio110"; + function = "pri_mi2s_ws"; + drive-strength = <2>; + bias-disable; + }; + + sec_mi2s_default: mi2s-sec-default-state { + pins = "gpio112", "gpio117", "gpio118", "gpio119"; + function = "sec_mi2s"; + drive-strength = <8>; + bias-disable; + }; + + sec_mi2s_sleep: mi2s-sec-sleep-state { + pins = "gpio112", "gpio117", "gpio118", "gpio119"; + function = "sec_mi2s"; + drive-strength = <2>; + bias-disable; + }; + + sdc1_default: sdc1-default-state { + clk-pins { + pins = "sdc1_clk"; + bias-disable; + drive-strength = <16>; + }; + + cmd-pins { + pins = "sdc1_cmd"; + bias-pull-up; + drive-strength = <10>; + }; + + data-pins { + pins = "sdc1_data"; + bias-pull-up; + drive-strength = <10>; + }; + }; + + sdc1_sleep: sdc1-sleep-state { + clk-pins { + pins = "sdc1_clk"; + bias-disable; + drive-strength = <2>; + }; + + cmd-pins { + pins = "sdc1_cmd"; + bias-pull-up; + drive-strength = <2>; + }; + + data-pins { + pins = "sdc1_data"; + bias-pull-up; + drive-strength = <2>; + }; + }; + + sdc2_default: sdc2-default-state { + clk-pins { + pins = "sdc2_clk"; + bias-disable; + drive-strength = <16>; + }; + + cmd-pins { + pins = "sdc2_cmd"; + bias-pull-up; + drive-strength = <10>; + }; + + data-pins { + pins = "sdc2_data"; + bias-pull-up; + drive-strength = <10>; + }; + }; + + sdc2_sleep: sdc2-sleep-state { + clk-pins { + pins = "sdc2_clk"; + bias-disable; + drive-strength = <2>; + }; + + cmd-pins { + pins = "sdc2_cmd"; + bias-pull-up; + drive-strength = <2>; + }; + + data-pins { + pins = "sdc2_data"; + bias-pull-up; + drive-strength = <2>; + }; + }; + + wcss_wlan_default: wcss-wlan-default-state { + pins = "gpio40", "gpio41", "gpio42", "gpio43", "gpio44"; + function = "wcss_wlan"; + drive-strength = <6>; + bias-pull-up; + }; + }; + + gcc: clock-controller@1800000 { + compatible = "qcom,gcc-msm8939"; + reg = <0x01800000 0x80000>; + clocks = <&rpmcc RPM_SMD_XO_CLK_SRC>, + <&sleep_clk>, + <&mdss_dsi0_phy 1>, + <&mdss_dsi0_phy 0>, + <0>, + <0>, + <0>; + clock-names = "xo", + "sleep_clk", + "dsi0pll", + "dsi0pllbyte", + "ext_mclk", + "ext_pri_i2s", + "ext_sec_i2s"; + #clock-cells = <1>; + #reset-cells = <1>; + #power-domain-cells = <1>; + }; + + tcsr_mutex: hwlock@1905000 { + compatible = "qcom,tcsr-mutex"; + reg = <0x01905000 0x20000>; + #hwlock-cells = <1>; + }; + + tcsr: syscon@1937000 { + compatible = "qcom,tcsr-msm8916", "syscon"; + reg = <0x01937000 0x30000>; + }; + + mdss: display-subsystem@1a00000 { + compatible = "qcom,mdss"; + reg = <0x01a00000 0x1000>, + <0x01ac8000 0x3000>; + reg-names = "mdss_phys", "vbif_phys"; + + interrupts = ; + interrupt-controller; + + clocks = <&gcc GCC_MDSS_AHB_CLK>, + <&gcc GCC_MDSS_AXI_CLK>, + <&gcc GCC_MDSS_VSYNC_CLK>; + clock-names = "iface", + "bus", + "vsync"; + + power-domains = <&gcc MDSS_GDSC>; + + #address-cells = <1>; + #size-cells = <1>; + #interrupt-cells = <1>; + ranges; + + status = "disabled"; + + mdss_mdp: display-controller@1a01000 { + compatible = "qcom,mdp5"; + reg = <0x01a01000 0x89000>; + reg-names = "mdp_phys"; + + interrupt-parent = <&mdss>; + interrupts = <0>; + + clocks = <&gcc GCC_MDSS_AHB_CLK>, + <&gcc GCC_MDSS_AXI_CLK>, + <&gcc GCC_MDSS_MDP_CLK>, + <&gcc GCC_MDSS_VSYNC_CLK>; + clock-names = "iface", + "bus", + "core", + "vsync"; + + iommus = <&apps_iommu 4>; + + interconnects = <&snoc_mm MASTER_MDP_PORT0 &bimc SLAVE_EBI_CH0>, + <&snoc_mm MASTER_MDP_PORT1 &bimc SLAVE_EBI_CH0>; + interconnect-names = "mdp0-mem", "mdp1-mem"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + mdss_mdp_intf1_out: endpoint { + remote-endpoint = <&mdss_dsi0_in>; + }; + }; + + port@1 { + reg = <1>; + mdss_mdp_intf2_out: endpoint { + remote-endpoint = <&mdss_dsi1_in>; + }; + }; + }; + }; + + mdss_dsi0: dsi@1a98000 { + compatible = "qcom,msm8916-dsi-ctrl", + "qcom,mdss-dsi-ctrl"; + reg = <0x01a98000 0x25c>; + reg-names = "dsi_ctrl"; + + interrupt-parent = <&mdss>; + interrupts = <4>; + + clocks = <&gcc GCC_MDSS_MDP_CLK>, + <&gcc GCC_MDSS_AHB_CLK>, + <&gcc GCC_MDSS_AXI_CLK>, + <&gcc GCC_MDSS_BYTE0_CLK>, + <&gcc GCC_MDSS_PCLK0_CLK>, + <&gcc GCC_MDSS_ESC0_CLK>; + clock-names = "mdp_core", + "iface", + "bus", + "byte", + "pixel", + "core"; + assigned-clocks = <&gcc BYTE0_CLK_SRC>, + <&gcc PCLK0_CLK_SRC>; + assigned-clock-parents = <&mdss_dsi0_phy 0>, + <&mdss_dsi0_phy 1>; + + phys = <&mdss_dsi0_phy>; + status = "disabled"; + + #address-cells = <1>; + #size-cells = <0>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + mdss_dsi0_in: endpoint { + remote-endpoint = <&mdss_mdp_intf1_out>; + }; + }; + + port@1 { + reg = <1>; + mdss_dsi0_out: endpoint { + }; + }; + }; + }; + + mdss_dsi0_phy: phy@1a98300 { + compatible = "qcom,dsi-phy-28nm-lp"; + reg = <0x01a98300 0xd4>, + <0x01a98500 0x280>, + <0x01a98780 0x30>; + reg-names = "dsi_pll", + "dsi_phy", + "dsi_phy_regulator"; + + clocks = <&gcc GCC_MDSS_AHB_CLK>, + <&rpmcc RPM_SMD_XO_CLK_SRC>; + clock-names = "iface", "ref"; + + #clock-cells = <1>; + #phy-cells = <0>; + status = "disabled"; + }; + + mdss_dsi1: dsi@1aa0000 { + compatible = "qcom,msm8916-dsi-ctrl", + "qcom,mdss-dsi-ctrl"; + reg = <0x01aa0000 0x25c>; + reg-names = "dsi_ctrl"; + + interrupt-parent = <&mdss>; + interrupts = <5>; + + clocks = <&gcc GCC_MDSS_MDP_CLK>, + <&gcc GCC_MDSS_AHB_CLK>, + <&gcc GCC_MDSS_AXI_CLK>, + <&gcc GCC_MDSS_BYTE1_CLK>, + <&gcc GCC_MDSS_PCLK1_CLK>, + <&gcc GCC_MDSS_ESC1_CLK>; + clock-names = "mdp_core", + "iface", + "bus", + "byte", + "pixel", + "core"; + assigned-clocks = <&gcc BYTE1_CLK_SRC>, + <&gcc PCLK1_CLK_SRC>; + assigned-clock-parents = <&mdss_dsi0_phy 0>, + <&mdss_dsi0_phy 1>; + phys = <&mdss_dsi1_phy>; + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + mdss_dsi1_in: endpoint { + remote-endpoint = <&mdss_mdp_intf2_out>; + }; + }; + + port@1 { + reg = <1>; + mdss_dsi1_out: endpoint { + }; + }; + }; + }; + + mdss_dsi1_phy: phy@1aa0300 { + compatible = "qcom,dsi-phy-28nm-lp"; + reg = <0x01aa0300 0xd4>, + <0x01aa0500 0x280>, + <0x01aa0780 0x30>; + reg-names = "dsi_pll", + "dsi_phy", + "dsi_phy_regulator"; + + clocks = <&gcc GCC_MDSS_AHB_CLK>, + <&rpmcc RPM_SMD_XO_CLK_SRC>; + clock-names = "iface", "ref"; + + #clock-cells = <1>; + #phy-cells = <0>; + status = "disabled"; + }; + }; + + gpu@1c00000 { + compatible = "qcom,adreno-405.0", "qcom,adreno"; + reg = <0x01c00000 0x10000>; + reg-names = "kgsl_3d0_reg_memory"; + interrupts = ; + interrupt-names = "kgsl_3d0_irq"; + clock-names = "core", + "iface", + "mem", + "mem_iface", + "alt_mem_iface", + "gfx3d", + "rbbmtimer"; + clocks = <&gcc GCC_OXILI_GFX3D_CLK>, + <&gcc GCC_OXILI_AHB_CLK>, + <&gcc GCC_OXILI_GMEM_CLK>, + <&gcc GCC_BIMC_GFX_CLK>, + <&gcc GCC_BIMC_GPU_CLK>, + <&gcc GFX3D_CLK_SRC>, + <&gcc GCC_OXILI_TIMER_CLK>; + power-domains = <&gcc OXILI_GDSC>; + operating-points-v2 = <&opp_table>; + iommus = <&gpu_iommu 1>, <&gpu_iommu 2>; + + opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-550000000 { + opp-hz = /bits/ 64 <550000000>; + }; + + opp-465000000 { + opp-hz = /bits/ 64 <465000000>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + }; + + opp-220000000 { + opp-hz = /bits/ 64 <220000000>; + }; + + opp-19200000 { + opp-hz = /bits/ 64 <19200000>; + }; + }; + }; + + apps_iommu: iommu@1ef0000 { + compatible = "qcom,msm8916-iommu", "qcom,msm-iommu-v1"; + reg = <0x01ef0000 0x3000>; + ranges = <0 0x01e20000 0x40000>; + clocks = <&gcc GCC_SMMU_CFG_CLK>, + <&gcc GCC_APSS_TCU_CLK>; + clock-names = "iface", "bus"; + #address-cells = <1>; + #size-cells = <1>; + #iommu-cells = <1>; + qcom,iommu-secure-id = <17>; + + /* mdp_0: */ + iommu-ctx@4000 { + compatible = "qcom,msm-iommu-v1-ns"; + reg = <0x4000 0x1000>; + interrupts = ; + }; + + /* venus_ns: */ + iommu-ctx@5000 { + compatible = "qcom,msm-iommu-v1-sec"; + reg = <0x5000 0x1000>; + interrupts = ; + }; + }; + + gpu_iommu: iommu@1f08000 { + compatible = "qcom,msm8916-iommu", "qcom,msm-iommu-v1"; + ranges = <0 0x1f08000 0x10000>; + clocks = <&gcc GCC_SMMU_CFG_CLK>, + <&gcc GCC_GFX_TCU_CLK>, + <&gcc GCC_GFX_TBU_CLK>; + clock-names = "iface", "bus", "tbu"; + #address-cells = <1>; + #size-cells = <1>; + #iommu-cells = <1>; + qcom,iommu-secure-id = <18>; + + /* gfx3d_user: */ + iommu-ctx@1000 { + compatible = "qcom,msm-iommu-v1-ns"; + reg = <0x1000 0x1000>; + interrupts = ; + }; + + /* gfx3d_priv: */ + iommu-ctx@2000 { + compatible = "qcom,msm-iommu-v1-ns"; + reg = <0x2000 0x1000>; + interrupts = ; + }; + }; + + spmi_bus: spmi@200f000 { + compatible = "qcom,spmi-pmic-arb"; + reg = <0x0200f000 0x001000>, + <0x02400000 0x400000>, + <0x02c00000 0x400000>, + <0x03800000 0x200000>, + <0x0200a000 0x002100>; + reg-names = "core", "chnls", "obsrvr", "intr", "cnfg"; + interrupt-names = "periph_irq"; + interrupts = ; + qcom,ee = <0>; + qcom,channel = <0>; + #address-cells = <2>; + #size-cells = <0>; + interrupt-controller; + #interrupt-cells = <4>; + }; + + mpss: remoteproc@4080000 { + compatible = "qcom,msm8916-mss-pil"; + reg = <0x04080000 0x100>, <0x04020000 0x040>; + reg-names = "qdsp6", "rmb"; + interrupts-extended = <&intc GIC_SPI 24 IRQ_TYPE_EDGE_RISING>, + <&hexagon_smp2p_in 0 IRQ_TYPE_EDGE_RISING>, + <&hexagon_smp2p_in 1 IRQ_TYPE_EDGE_RISING>, + <&hexagon_smp2p_in 2 IRQ_TYPE_EDGE_RISING>, + <&hexagon_smp2p_in 3 IRQ_TYPE_EDGE_RISING>; + interrupt-names = "wdog", + "fatal", + "ready", + "handover", + "stop-ack"; + clocks = <&gcc GCC_MSS_CFG_AHB_CLK>, + <&gcc GCC_MSS_Q6_BIMC_AXI_CLK>, + <&gcc GCC_BOOT_ROM_AHB_CLK>, + <&rpmcc RPM_SMD_XO_CLK_SRC>; + clock-names = "iface", + "bus", + "mem", + "xo"; + power-domains = <&rpmpd MSM8939_VDDMDCX>, + <&rpmpd MSM8939_VDDMX>; + power-domain-names = "cx", "mx"; + qcom,smem-states = <&hexagon_smp2p_out 0>; + qcom,smem-state-names = "stop"; + resets = <&scm 0>; + reset-names = "mss_restart"; + qcom,halt-regs = <&tcsr 0x18000 0x19000 0x1a000>; + status = "disabled"; + + mba { + memory-region = <&mba_mem>; + }; + + mpss { + memory-region = <&mpss_mem>; + }; + + smd-edge { + interrupts = ; + + qcom,smd-edge = <0>; + mboxes = <&apcs1_mbox 12>; + qcom,remote-pid = <1>; + + label = "hexagon"; + }; + }; + + sound: sound@7702000 { + compatible = "qcom,apq8016-sbc-sndcard"; + reg = <0x07702000 0x4>, + <0x07702004 0x4>; + reg-names = "mic-iomux", "spkr-iomux"; + status = "disabled"; + }; + + lpass: audio-controller@7708000 { + compatible = "qcom,apq8016-lpass-cpu"; + reg = <0x07708000 0x10000>; + reg-names = "lpass-lpaif"; + interrupts = ; + interrupt-names = "lpass-irq-lpaif"; + clocks = <&gcc GCC_ULTAUDIO_AHBFABRIC_IXFABRIC_CLK>, + <&gcc GCC_ULTAUDIO_LPAIF_PRI_I2S_CLK>, + <&gcc GCC_ULTAUDIO_LPAIF_PRI_I2S_CLK>, + <&gcc GCC_ULTAUDIO_LPAIF_SEC_I2S_CLK>, + <&gcc GCC_ULTAUDIO_LPAIF_AUX_I2S_CLK>, + <&gcc GCC_ULTAUDIO_PCNOC_MPORT_CLK>, + <&gcc GCC_ULTAUDIO_PCNOC_SWAY_CLK>; + clock-names = "ahbix-clk", + "mi2s-bit-clk0", + "mi2s-bit-clk1", + "mi2s-bit-clk2", + "mi2s-bit-clk3", + "pcnoc-mport-clk", + "pcnoc-sway-clk"; + #sound-dai-cells = <1>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + lpass_codec: audio-codec@771c000 { + compatible = "qcom,msm8916-wcd-digital-codec"; + reg = <0x0771c000 0x400>; + clocks = <&gcc GCC_ULTAUDIO_AHBFABRIC_IXFABRIC_CLK>, + <&gcc GCC_CODEC_DIGCODEC_CLK>; + clock-names = "ahbix-clk", "mclk"; + #sound-dai-cells = <1>; + status = "disabled"; + }; + + sdhc_1: mmc@7824900 { + compatible = "qcom,msm8916-sdhci", "qcom,sdhci-msm-v4"; + reg = <0x07824900 0x11c>, <0x07824000 0x800>; + reg-names = "hc", "core"; + + interrupts = , + ; + interrupt-names = "hc_irq", "pwr_irq"; + clocks = <&gcc GCC_SDCC1_AHB_CLK>, + <&gcc GCC_SDCC1_APPS_CLK>, + <&rpmcc RPM_SMD_XO_CLK_SRC>; + clock-names = "iface", "core", "xo"; + resets = <&gcc GCC_SDCC1_BCR>; + pinctrl-0 = <&sdc1_default>; + pinctrl-1 = <&sdc1_sleep>; + pinctrl-names = "default", "sleep"; + mmc-ddr-1_8v; + bus-width = <8>; + non-removable; + status = "disabled"; + }; + + sdhc_2: mmc@7864900 { + compatible = "qcom,msm8916-sdhci", "qcom,sdhci-msm-v4"; + reg = <0x07864900 0x11c>, <0x07864000 0x800>; + reg-names = "hc", "core"; + + interrupts = , + ; + interrupt-names = "hc_irq", "pwr_irq"; + clocks = <&gcc GCC_SDCC2_AHB_CLK>, + <&gcc GCC_SDCC2_APPS_CLK>, + <&rpmcc RPM_SMD_XO_CLK_SRC>; + clock-names = "iface", "core", "xo"; + resets = <&gcc GCC_SDCC2_BCR>; + pinctrl-0 = <&sdc2_default>; + pinctrl-1 = <&sdc2_sleep>; + pinctrl-names = "default", "sleep"; + bus-width = <4>; + status = "disabled"; + }; + + blsp_dma: dma-controller@7884000 { + compatible = "qcom,bam-v1.7.0"; + reg = <0x07884000 0x23000>; + interrupts = ; + clocks = <&gcc GCC_BLSP1_AHB_CLK>; + clock-names = "bam_clk"; + #dma-cells = <1>; + qcom,ee = <0>; + }; + + blsp_uart1: serial@78af000 { + compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm"; + reg = <0x078af000 0x200>; + interrupts = ; + clocks = <&gcc GCC_BLSP1_UART1_APPS_CLK>, <&gcc GCC_BLSP1_AHB_CLK>; + clock-names = "core", "iface"; + dmas = <&blsp_dma 0>, <&blsp_dma 1>; + dma-names = "tx", "rx"; + pinctrl-0 = <&blsp_uart1_default>; + pinctrl-1 = <&blsp_uart1_sleep>; + pinctrl-names = "default", "sleep"; + status = "disabled"; + }; + + blsp_uart2: serial@78b0000 { + compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm"; + reg = <0x078b0000 0x200>; + interrupts = ; + clocks = <&gcc GCC_BLSP1_UART2_APPS_CLK>, <&gcc GCC_BLSP1_AHB_CLK>; + clock-names = "core", "iface"; + dmas = <&blsp_dma 2>, <&blsp_dma 3>; + dma-names = "tx", "rx"; + pinctrl-0 = <&blsp_uart2_default>; + pinctrl-1 = <&blsp_uart2_sleep>; + pinctrl-names = "default", "sleep"; + status = "disabled"; + }; + + blsp_i2c1: i2c@78b5000 { + compatible = "qcom,i2c-qup-v2.2.1"; + reg = <0x078b5000 0x500>; + interrupts = ; + clocks = <&gcc GCC_BLSP1_QUP1_I2C_APPS_CLK>, + <&gcc GCC_BLSP1_AHB_CLK>; + clock-names = "core", "iface"; + dmas = <&blsp_dma 4>, <&blsp_dma 5>; + dma-names = "tx", "rx"; + pinctrl-0 = <&blsp_i2c1_default>; + pinctrl-1 = <&blsp_i2c1_sleep>; + pinctrl-names = "default", "sleep"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + blsp_spi1: spi@78b5000 { + compatible = "qcom,spi-qup-v2.2.1"; + reg = <0x078b5000 0x500>; + interrupts = ; + clocks = <&gcc GCC_BLSP1_QUP1_SPI_APPS_CLK>, + <&gcc GCC_BLSP1_AHB_CLK>; + clock-names = "core", "iface"; + dmas = <&blsp_dma 4>, <&blsp_dma 5>; + dma-names = "tx", "rx"; + pinctrl-0 = <&blsp_spi1_default>; + pinctrl-1 = <&blsp_spi1_sleep>; + pinctrl-names = "default", "sleep"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + blsp_i2c2: i2c@78b6000 { + compatible = "qcom,i2c-qup-v2.2.1"; + reg = <0x078b6000 0x500>; + interrupts = ; + clocks = <&gcc GCC_BLSP1_QUP2_I2C_APPS_CLK>, + <&gcc GCC_BLSP1_AHB_CLK>; + clock-names = "core", "iface"; + dmas = <&blsp_dma 6>, <&blsp_dma 7>; + dma-names = "tx", "rx"; + pinctrl-0 = <&blsp_i2c2_default>; + pinctrl-1 = <&blsp_i2c2_sleep>; + pinctrl-names = "default", "sleep"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + blsp_spi2: spi@78b6000 { + compatible = "qcom,spi-qup-v2.2.1"; + reg = <0x078b6000 0x500>; + interrupts = ; + clocks = <&gcc GCC_BLSP1_QUP2_SPI_APPS_CLK>, + <&gcc GCC_BLSP1_AHB_CLK>; + clock-names = "core", "iface"; + dmas = <&blsp_dma 6>, <&blsp_dma 7>; + dma-names = "tx", "rx"; + pinctrl-0 = <&blsp_spi2_default>; + pinctrl-1 = <&blsp_spi2_sleep>; + pinctrl-names = "default", "sleep"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + blsp_i2c3: i2c@78b7000 { + compatible = "qcom,i2c-qup-v2.2.1"; + reg = <0x078b7000 0x500>; + interrupts = ; + clocks = <&gcc GCC_BLSP1_QUP3_I2C_APPS_CLK>, + <&gcc GCC_BLSP1_AHB_CLK>; + clock-names = "core", "iface"; + dmas = <&blsp_dma 8>, <&blsp_dma 9>; + dma-names = "tx", "rx"; + pinctrl-0 = <&blsp_i2c3_default>; + pinctrl-1 = <&blsp_i2c3_sleep>; + pinctrl-names = "default", "sleep"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + blsp_spi3: spi@78b7000 { + compatible = "qcom,spi-qup-v2.2.1"; + reg = <0x078b7000 0x500>; + interrupts = ; + clocks = <&gcc GCC_BLSP1_QUP3_SPI_APPS_CLK>, + <&gcc GCC_BLSP1_AHB_CLK>; + clock-names = "core", "iface"; + dmas = <&blsp_dma 8>, <&blsp_dma 9>; + dma-names = "tx", "rx"; + pinctrl-0 = <&blsp_spi3_default>; + pinctrl-1 = <&blsp_spi3_sleep>; + pinctrl-names = "default", "sleep"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + blsp_i2c4: i2c@78b8000 { + compatible = "qcom,i2c-qup-v2.2.1"; + reg = <0x078b8000 0x500>; + interrupts = ; + clocks = <&gcc GCC_BLSP1_QUP4_I2C_APPS_CLK>, + <&gcc GCC_BLSP1_AHB_CLK>; + clock-names = "core", "iface"; + dmas = <&blsp_dma 10>, <&blsp_dma 11>; + dma-names = "tx", "rx"; + pinctrl-0 = <&blsp_i2c4_default>; + pinctrl-1 = <&blsp_i2c4_sleep>; + pinctrl-names = "default", "sleep"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + blsp_spi4: spi@78b8000 { + compatible = "qcom,spi-qup-v2.2.1"; + reg = <0x078b8000 0x500>; + interrupts = ; + clocks = <&gcc GCC_BLSP1_QUP4_SPI_APPS_CLK>, + <&gcc GCC_BLSP1_AHB_CLK>; + clock-names = "core", "iface"; + dmas = <&blsp_dma 10>, <&blsp_dma 11>; + dma-names = "tx", "rx"; + pinctrl-0 = <&blsp_spi4_default>; + pinctrl-1 = <&blsp_spi4_sleep>; + pinctrl-names = "default", "sleep"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + blsp_i2c5: i2c@78b9000 { + compatible = "qcom,i2c-qup-v2.2.1"; + reg = <0x078b9000 0x500>; + interrupts = ; + clocks = <&gcc GCC_BLSP1_QUP5_I2C_APPS_CLK>, + <&gcc GCC_BLSP1_AHB_CLK>; + clock-names = "core", "iface"; + dmas = <&blsp_dma 12>, <&blsp_dma 13>; + dma-names = "tx", "rx"; + pinctrl-0 = <&blsp_i2c5_default>; + pinctrl-1 = <&blsp_i2c5_sleep>; + pinctrl-names = "default", "sleep"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + blsp_spi5: spi@78b9000 { + compatible = "qcom,spi-qup-v2.2.1"; + reg = <0x078b9000 0x500>; + interrupts = ; + clocks = <&gcc GCC_BLSP1_QUP5_SPI_APPS_CLK>, + <&gcc GCC_BLSP1_AHB_CLK>; + clock-names = "core", "iface"; + dmas = <&blsp_dma 12>, <&blsp_dma 13>; + dma-names = "tx", "rx"; + pinctrl-0 = <&blsp_spi5_default>; + pinctrl-1 = <&blsp_spi5_sleep>; + pinctrl-names = "default", "sleep"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + blsp_i2c6: i2c@78ba000 { + compatible = "qcom,i2c-qup-v2.2.1"; + reg = <0x078ba000 0x500>; + interrupts = ; + clocks = <&gcc GCC_BLSP1_QUP6_I2C_APPS_CLK>, + <&gcc GCC_BLSP1_AHB_CLK>; + clock-names = "core", "iface"; + dmas = <&blsp_dma 14>, <&blsp_dma 15>; + dma-names = "tx", "rx"; + pinctrl-0 = <&blsp_i2c6_default>; + pinctrl-1 = <&blsp_i2c6_sleep>; + pinctrl-names = "default", "sleep"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + blsp_spi6: spi@78ba000 { + compatible = "qcom,spi-qup-v2.2.1"; + reg = <0x078ba000 0x500>; + interrupts = ; + clocks = <&gcc GCC_BLSP1_QUP6_SPI_APPS_CLK>, + <&gcc GCC_BLSP1_AHB_CLK>; + clock-names = "core", "iface"; + dmas = <&blsp_dma 14>, <&blsp_dma 15>; + dma-names = "tx", "rx"; + pinctrl-0 = <&blsp_spi6_default>; + pinctrl-1 = <&blsp_spi6_sleep>; + pinctrl-names = "default", "sleep"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + usb: usb@78d9000 { + compatible = "qcom,ci-hdrc"; + reg = <0x078d9000 0x200>, + <0x078d9200 0x200>; + interrupts = , + ; + clocks = <&gcc GCC_USB_HS_AHB_CLK>, + <&gcc GCC_USB_HS_SYSTEM_CLK>; + clock-names = "iface", "core"; + assigned-clocks = <&gcc GCC_USB_HS_SYSTEM_CLK>; + assigned-clock-rates = <80000000>; + resets = <&gcc GCC_USB_HS_BCR>; + reset-names = "core"; + #reset-cells = <1>; + phy_type = "ulpi"; + dr_mode = "otg"; + adp-disable; + hnp-disable; + srp-disable; + ahb-burst-config = <0>; + phy-names = "usb-phy"; + phys = <&usb_hs_phy>; + status = "disabled"; + + ulpi { + usb_hs_phy: phy { + compatible = "qcom,usb-hs-phy-msm8916", + "qcom,usb-hs-phy"; + clocks = <&rpmcc RPM_SMD_XO_CLK_SRC>, + <&gcc GCC_USB2A_PHY_SLEEP_CLK>; + clock-names = "ref", "sleep"; + resets = <&gcc GCC_USB2A_PHY_BCR>, <&usb 0>; + reset-names = "phy", "por"; + #phy-cells = <0>; + qcom,init-seq = /bits/ 8 <0x0 0x44>, + <0x1 0x6b>, + <0x2 0x24>, + <0x3 0x13>; + }; + }; + }; + + wcnss: remoteproc@a204000 { + compatible = "qcom,pronto-v2-pil", "qcom,pronto"; + interrupts-extended = <&intc GIC_SPI 149 IRQ_TYPE_EDGE_RISING>, + <&wcnss_smp2p_in 0 IRQ_TYPE_EDGE_RISING>, + <&wcnss_smp2p_in 1 IRQ_TYPE_EDGE_RISING>, + <&wcnss_smp2p_in 2 IRQ_TYPE_EDGE_RISING>, + <&wcnss_smp2p_in 3 IRQ_TYPE_EDGE_RISING>; + interrupt-names = "wdog", + "fatal", + "ready", + "handover", + "stop-ack"; + reg = <0x0a204000 0x2000>, + <0x0a202000 0x1000>, + <0x0a21b000 0x3000>; + reg-names = "ccu", "dxe", "pmu"; + + memory-region = <&wcnss_mem>; + + power-domains = <&rpmpd MSM8939_VDDCX>, + <&rpmpd MSM8939_VDDMX>; + power-domain-names = "cx", "mx"; + + qcom,smem-states = <&wcnss_smp2p_out 0>; + qcom,smem-state-names = "stop"; + + pinctrl-names = "default"; + pinctrl-0 = <&wcss_wlan_default>; + + status = "disabled"; + + wcnss_iris: iris { + /* Separate chip, compatible is board-specific */ + clocks = <&rpmcc RPM_SMD_RF_CLK2>; + clock-names = "xo"; + }; + + smd-edge { + interrupts = ; + qcom,ipc = <&apcs1_mbox 8 17>; + qcom,smd-edge = <6>; + qcom,remote-pid = <4>; + + label = "pronto"; + + wcnss { + compatible = "qcom,wcnss"; + qcom,smd-channels = "WCNSS_CTRL"; + + qcom,mmio = <&wcnss>; + + wcnss_bt: bluetooth { + compatible = "qcom,wcnss-bt"; + }; + + wcnss_wifi: wifi { + compatible = "qcom,wcnss-wlan"; + + interrupts = , + ; + interrupt-names = "tx", "rx"; + + qcom,smem-states = <&apps_smsm 10>, + <&apps_smsm 9>; + qcom,smem-state-names = "tx-enable", + "tx-rings-empty"; + }; + }; + }; + }; + + intc: interrupt-controller@b000000 { + compatible = "qcom,msm-qgic2"; + reg = <0x0b000000 0x1000>, <0x0b002000 0x2000>, + <0x0b001000 0x1000>, <0x0b004000 0x2000>; + interrupt-controller; + #interrupt-cells = <3>; + interrupts = ; + }; + + apcs1_mbox: mailbox@b011000 { + compatible = "qcom,msm8939-apcs-kpss-global", "syscon"; + reg = <0x0b011000 0x1000>; + clocks = <&a53pll_c1>, <&gcc GPLL0_VOTE>, <&rpmcc RPM_SMD_XO_CLK_SRC>; + clock-names = "pll", "aux", "ref"; + #clock-cells = <0>; + assigned-clocks = <&apcs2>; + assigned-clock-rates = <297600000>; + #mbox-cells = <1>; + }; + + a53pll_c1: clock@b016000 { + compatible = "qcom,msm8939-a53pll"; + reg = <0x0b016000 0x40>; + #clock-cells = <0>; + }; + + acc0: clock-controller@b088000 { + compatible = "qcom,kpss-acc-v2"; + reg = <0x0b088000 0x1000>; + }; + + saw0: power-manager@b089000 { + compatible = "qcom,msm8939-saw2-v3.0-cpu", "qcom,saw2"; + reg = <0x0b089000 0x1000>; + }; + + acc1: clock-controller@b098000 { + compatible = "qcom,kpss-acc-v2"; + reg = <0x0b098000 0x1000>; + }; + + saw1: power-manager@b099000 { + compatible = "qcom,msm8939-saw2-v3.0-cpu", "qcom,saw2"; + reg = <0x0b099000 0x1000>; + }; + + acc2: clock-controller@b0a8000 { + compatible = "qcom,kpss-acc-v2"; + reg = <0x0b0a8000 0x1000>; + }; + + saw2: power-manager@b0a9000 { + compatible = "qcom,msm8939-saw2-v3.0-cpu", "qcom,saw2"; + reg = <0x0b0a9000 0x1000>; + }; + + acc3: clock-controller@b0b8000 { + compatible = "qcom,kpss-acc-v2"; + reg = <0x0b0b8000 0x1000>; + }; + + saw3: power-manager@b0b9000 { + compatible = "qcom,msm8939-saw2-v3.0-cpu", "qcom,saw2"; + reg = <0x0b0b9000 0x1000>; + }; + + apcs0_mbox: mailbox@b111000 { + compatible = "qcom,msm8939-apcs-kpss-global", "syscon"; + reg = <0x0b111000 0x1000>; + clocks = <&a53pll_c0>, <&gcc GPLL0_VOTE>, <&rpmcc RPM_SMD_XO_CLK_SRC>; + clock-names = "pll", "aux", "ref"; + #clock-cells = <0>; + #mbox-cells = <1>; + }; + + a53pll_c0: clock@b116000 { + compatible = "qcom,msm8939-a53pll"; + reg = <0x0b116000 0x40>; + #clock-cells = <0>; + }; + + timer@b120000 { + compatible = "arm,armv7-timer-mem"; + reg = <0x0b120000 0x1000>; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + frame@b121000 { + reg = <0x0b121000 0x1000>, + <0x0b122000 0x1000>; + interrupts = , + ; + frame-number = <0>; + }; + + frame@b123000 { + reg = <0x0b123000 0x1000>; + interrupts = ; + frame-number = <1>; + status = "disabled"; + }; + + frame@b124000 { + reg = <0x0b124000 0x1000>; + interrupts = ; + frame-number = <2>; + status = "disabled"; + }; + + frame@b125000 { + reg = <0x0b125000 0x1000>; + interrupts = ; + frame-number = <3>; + status = "disabled"; + }; + + frame@b126000 { + reg = <0x0b126000 0x1000>; + interrupts = ; + frame-number = <4>; + status = "disabled"; + }; + + frame@b127000 { + reg = <0x0b127000 0x1000>; + interrupts = ; + frame-number = <5>; + status = "disabled"; + }; + + frame@b128000 { + reg = <0x0b128000 0x1000>; + interrupts = ; + frame-number = <6>; + status = "disabled"; + }; + }; + + acc4: clock-controller@b188000 { + compatible = "qcom,kpss-acc-v2"; + reg = <0x0b188000 0x1000>; + }; + + saw4: power-manager@b189000 { + compatible = "qcom,msm8939-saw2-v3.0-cpu", "qcom,saw2"; + reg = <0x0b189000 0x1000>; + }; + + acc5: clock-controller@b198000 { + compatible = "qcom,kpss-acc-v2"; + reg = <0x0b198000 0x1000>; + }; + + saw5: power-manager@b199000 { + compatible = "qcom,msm8939-saw2-v3.0-cpu", "qcom,saw2"; + reg = <0x0b199000 0x1000>; + }; + + acc6: clock-controller@b1a8000 { + compatible = "qcom,kpss-acc-v2"; + reg = <0x0b1a8000 0x1000>; + }; + + saw6: power-manager@b1a9000 { + compatible = "qcom,msm8939-saw2-v3.0-cpu", "qcom,saw2"; + reg = <0x0b1a9000 0x1000>; + }; + + acc7: clock-controller@b1b8000 { + compatible = "qcom,kpss-acc-v2"; + reg = <0x0b1b8000 0x1000>; + }; + + saw7: power-manager@b1b9000 { + compatible = "qcom,msm8939-saw2-v3.0-cpu", "qcom,saw2"; + reg = <0x0b1b9000 0x1000>; + }; + + a53pll_cci: clock@b1d0000 { + compatible = "qcom,msm8939-a53pll"; + reg = <0x0b1d0000 0x40>; + #clock-cells = <0>; + }; + + apcs2: mailbox@b1d1000 { + compatible = "qcom,msm8939-apcs-kpss-global", "syscon"; + reg = <0x0b1d1000 0x1000>; + clocks = <&a53pll_cci>, <&gcc GPLL0_VOTE>, <&rpmcc RPM_SMD_XO_CLK_SRC>; + clock-names = "pll", "aux", "ref"; + #clock-cells = <0>; + #mbox-cells = <1>; + }; + }; + + thermal_zones: thermal-zones { + cpu0-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens 5>; + + trips { + cpu0_alert: trip0 { + temperature = <75000>; + hysteresis = <2000>; + type = "passive"; + }; + + cpu0_crit: trip1 { + temperature = <115000>; + hysteresis = <0>; + type = "critical"; + }; + }; + + cooling-maps { + map0 { + trip = <&cpu0_alert>; + cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; + }; + + cpu1-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens 6>; + + trips { + cpu1_alert: trip0 { + temperature = <75000>; + hysteresis = <2000>; + type = "passive"; + }; + + cpu1_crit: trip1 { + temperature = <110000>; + hysteresis = <2000>; + type = "critical"; + }; + }; + + cooling-maps { + map0 { + trip = <&cpu1_alert>; + cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; + }; + + cpu2-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens 7>; + + trips { + cpu2_alert: trip0 { + temperature = <75000>; + hysteresis = <2000>; + type = "passive"; + }; + + cpu2_crit: trip1 { + temperature = <110000>; + hysteresis = <2000>; + type = "critical"; + }; + }; + + cooling-maps { + map0 { + trip = <&cpu2_alert>; + cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; + }; + + cpu3-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens 8>; + + trips { + cpu3_alert: trip0 { + temperature = <75000>; + hysteresis = <2000>; + type = "passive"; + }; + + cpu3_crit: trip1 { + temperature = <110000>; + hysteresis = <2000>; + type = "critical"; + }; + }; + + cooling-maps { + map0 { + trip = <&cpu3_alert>; + cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; + }; + + cpu4567-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens 9>; + + trips { + cpu4567_alert: trip0 { + temperature = <75000>; + hysteresis = <2000>; + type = "passive"; + }; + + cpu4567_crit: trip1 { + temperature = <110000>; + hysteresis = <2000>; + type = "critical"; + }; + }; + + cooling-maps { + map0 { + trip = <&cpu4567_alert>; + cooling-device = <&CPU4 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&CPU5 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&CPU6 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&CPU7 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; + }; + + gpu-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens 3>; + + trips { + gpu_alert0: trip-point0 { + temperature = <75000>; + hysteresis = <2000>; + type = "passive"; + }; + + gpu_crit: gpu_crit { + temperature = <95000>; + hysteresis = <2000>; + type = "critical"; + }; + }; + }; + + modem1-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens 0>; + + trips { + modem1_alert0: trip-point0 { + temperature = <85000>; + hysteresis = <2000>; + type = "hot"; + }; + }; + }; + + modem2-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens 2>; + + trips { + modem2_alert0: trip-point0 { + temperature = <85000>; + hysteresis = <2000>; + type = "hot"; + }; + }; + }; + + camera-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens 1>; + + trips { + cam_alert0: trip-point0 { + temperature = <75000>; + hysteresis = <2000>; + type = "hot"; + }; + }; + }; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts = , + , + , + ; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/msm8953.dtsi b/arch/arm64/boot/dts/qcom/msm8953.dtsi index d44cfa0471e9a6f0e37c2244d0ff349aba44ddb3..b711cf9a6dc0313a810826a3f2a6139b50eafe9d 100644 --- a/arch/arm64/boot/dts/qcom/msm8953.dtsi +++ b/arch/arm64/boot/dts/qcom/msm8953.dtsi @@ -766,10 +766,10 @@ #power-domain-cells = <1>; clocks = <&rpmcc RPM_SMD_XO_CLK_SRC>, <&sleep_clk>, - <&dsi0_phy 1>, - <&dsi0_phy 0>, - <&dsi1_phy 1>, - <&dsi1_phy 0>; + <&mdss_dsi0_phy 1>, + <&mdss_dsi0_phy 0>, + <&mdss_dsi1_phy 1>, + <&mdss_dsi1_phy 0>; clock-names = "xo", "sleep", "dsi0pll", @@ -851,20 +851,20 @@ port@0 { reg = <0>; mdp5_intf1_out: endpoint { - remote-endpoint = <&dsi0_in>; + remote-endpoint = <&mdss_dsi0_in>; }; }; port@1 { reg = <1>; mdp5_intf2_out: endpoint { - remote-endpoint = <&dsi1_in>; + remote-endpoint = <&mdss_dsi1_in>; }; }; }; }; - dsi0: dsi@1a94000 { + mdss_dsi0: dsi@1a94000 { compatible = "qcom,msm8953-dsi-ctrl", "qcom,mdss-dsi-ctrl"; reg = <0x01a94000 0x400>; reg-names = "dsi_ctrl"; @@ -874,8 +874,8 @@ assigned-clocks = <&gcc BYTE0_CLK_SRC>, <&gcc PCLK0_CLK_SRC>; - assigned-clock-parents = <&dsi0_phy 0>, - <&dsi0_phy 1>; + assigned-clock-parents = <&mdss_dsi0_phy 0>, + <&mdss_dsi0_phy 1>; clocks = <&gcc GCC_MDSS_MDP_CLK>, <&gcc GCC_MDSS_AHB_CLK>, @@ -890,7 +890,7 @@ "pixel", "core"; - phys = <&dsi0_phy>; + phys = <&mdss_dsi0_phy>; #address-cells = <1>; #size-cells = <0>; @@ -903,20 +903,20 @@ port@0 { reg = <0>; - dsi0_in: endpoint { + mdss_dsi0_in: endpoint { remote-endpoint = <&mdp5_intf1_out>; }; }; port@1 { reg = <1>; - dsi0_out: endpoint { + mdss_dsi0_out: endpoint { }; }; }; }; - dsi0_phy: phy@1a94400 { + mdss_dsi0_phy: phy@1a94400 { compatible = "qcom,dsi-phy-14nm-8953"; reg = <0x01a94400 0x100>, <0x01a94500 0x300>, @@ -934,7 +934,7 @@ status = "disabled"; }; - dsi1: dsi@1a96000 { + mdss_dsi1: dsi@1a96000 { compatible = "qcom,msm8953-dsi-ctrl", "qcom,mdss-dsi-ctrl"; reg = <0x01a96000 0x400>; reg-names = "dsi_ctrl"; @@ -944,8 +944,8 @@ assigned-clocks = <&gcc BYTE1_CLK_SRC>, <&gcc PCLK1_CLK_SRC>; - assigned-clock-parents = <&dsi1_phy 0>, - <&dsi1_phy 1>; + assigned-clock-parents = <&mdss_dsi1_phy 0>, + <&mdss_dsi1_phy 1>; clocks = <&gcc GCC_MDSS_MDP_CLK>, <&gcc GCC_MDSS_AHB_CLK>, @@ -960,7 +960,7 @@ "pixel", "core"; - phys = <&dsi1_phy>; + phys = <&mdss_dsi1_phy>; status = "disabled"; @@ -970,20 +970,20 @@ port@0 { reg = <0>; - dsi1_in: endpoint { + mdss_dsi1_in: endpoint { remote-endpoint = <&mdp5_intf2_out>; }; }; port@1 { reg = <1>; - dsi1_out: endpoint { + mdss_dsi1_out: endpoint { }; }; }; }; - dsi1_phy: phy@1a96400 { + mdss_dsi1_phy: phy@1a96400 { compatible = "qcom,dsi-phy-14nm-8953"; reg = <0x01a96400 0x100>, <0x01a96500 0x300>, @@ -1002,7 +1002,7 @@ }; }; - apps_iommu: iommu@1e00000 { + apps_iommu: iommu@1e20000 { compatible = "qcom,msm8953-iommu", "qcom,msm-iommu-v1"; ranges = <0 0x01e20000 0x20000>; @@ -1276,6 +1276,19 @@ }; }; + blsp1_dma: dma-controller@7884000 { + compatible = "qcom,bam-v1.7.0"; + reg = <0x07884000 0x1f000>; + interrupts = ; + clocks = <&gcc GCC_BLSP1_AHB_CLK>; + clock-names = "bam_clk"; + num-channels = <12>; + #dma-cells = <1>; + qcom,ee = <0>; + qcom,num-ees = <4>; + qcom,controlled-remotely; + }; + uart_0: serial@78af000 { compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm"; reg = <0x078af000 0x200>; @@ -1294,6 +1307,8 @@ clock-names = "core", "iface"; clocks = <&gcc GCC_BLSP1_QUP1_I2C_APPS_CLK>, <&gcc GCC_BLSP1_AHB_CLK>; + dmas = <&blsp1_dma 4>, <&blsp1_dma 5>; + dma-names = "tx", "rx"; pinctrl-names = "default", "sleep"; pinctrl-0 = <&i2c_1_default>; @@ -1312,6 +1327,8 @@ clock-names = "core", "iface"; clocks = <&gcc GCC_BLSP1_QUP2_I2C_APPS_CLK>, <&gcc GCC_BLSP1_AHB_CLK>; + dmas = <&blsp1_dma 6>, <&blsp1_dma 7>; + dma-names = "tx", "rx"; pinctrl-names = "default", "sleep"; pinctrl-0 = <&i2c_2_default>; @@ -1330,6 +1347,9 @@ clock-names = "core", "iface"; clocks = <&gcc GCC_BLSP1_QUP3_I2C_APPS_CLK>, <&gcc GCC_BLSP1_AHB_CLK>; + dmas = <&blsp1_dma 8>, <&blsp1_dma 9>; + dma-names = "tx", "rx"; + pinctrl-names = "default", "sleep"; pinctrl-0 = <&i2c_3_default>; pinctrl-1 = <&i2c_3_sleep>; @@ -1347,6 +1367,9 @@ clock-names = "core", "iface"; clocks = <&gcc GCC_BLSP1_QUP4_I2C_APPS_CLK>, <&gcc GCC_BLSP1_AHB_CLK>; + dmas = <&blsp2_dma 10>, <&blsp2_dma 11>; + dma-names = "tx", "rx"; + pinctrl-names = "default", "sleep"; pinctrl-0 = <&i2c_4_default>; pinctrl-1 = <&i2c_4_sleep>; @@ -1357,6 +1380,19 @@ status = "disabled"; }; + blsp2_dma: dma-controller@7ac4000 { + compatible = "qcom,bam-v1.7.0"; + reg = <0x07ac4000 0x1f000>; + interrupts = ; + clocks = <&gcc GCC_BLSP2_AHB_CLK>; + clock-names = "bam_clk"; + num-channels = <12>; + #dma-cells = <1>; + qcom,ee = <0>; + qcom,num-ees = <4>; + qcom,controlled-remotely; + }; + i2c_5: i2c@7af5000 { compatible = "qcom,i2c-qup-v2.2.1"; reg = <0x07af5000 0x600>; @@ -1364,6 +1400,9 @@ clock-names = "core", "iface"; clocks = <&gcc GCC_BLSP2_QUP1_I2C_APPS_CLK>, <&gcc GCC_BLSP2_AHB_CLK>; + dmas = <&blsp2_dma 4>, <&blsp2_dma 5>; + dma-names = "tx", "rx"; + pinctrl-names = "default", "sleep"; pinctrl-0 = <&i2c_5_default>; pinctrl-1 = <&i2c_5_sleep>; @@ -1381,6 +1420,9 @@ clock-names = "core", "iface"; clocks = <&gcc GCC_BLSP2_QUP2_I2C_APPS_CLK>, <&gcc GCC_BLSP2_AHB_CLK>; + dmas = <&blsp2_dma 6>, <&blsp2_dma 7>; + dma-names = "tx", "rx"; + pinctrl-names = "default", "sleep"; pinctrl-0 = <&i2c_6_default>; pinctrl-1 = <&i2c_6_sleep>; @@ -1398,6 +1440,9 @@ clock-names = "core", "iface"; clocks = <&gcc GCC_BLSP2_QUP3_I2C_APPS_CLK>, <&gcc GCC_BLSP2_AHB_CLK>; + dmas = <&blsp2_dma 8>, <&blsp2_dma 9>; + dma-names = "tx", "rx"; + pinctrl-names = "default", "sleep"; pinctrl-0 = <&i2c_7_default>; pinctrl-1 = <&i2c_7_sleep>; @@ -1415,6 +1460,9 @@ clock-names = "core", "iface"; clocks = <&gcc GCC_BLSP2_QUP4_I2C_APPS_CLK>, <&gcc GCC_BLSP2_AHB_CLK>; + dmas = <&blsp2_dma 10>, <&blsp2_dma 11>; + dma-names = "tx", "rx"; + pinctrl-names = "default", "sleep"; pinctrl-0 = <&i2c_8_default>; pinctrl-1 = <&i2c_8_sleep>; @@ -1425,7 +1473,7 @@ status = "disabled"; }; - wcnss: remoteproc@a21b000 { + wcnss: remoteproc@a204000 { compatible = "qcom,pronto-v3-pil", "qcom,pronto"; reg = <0x0a204000 0x2000>, <0x0a202000 0x1000>, <0x0a21b000 0x3000>; reg-names = "ccu", "dxe", "pmu"; @@ -1507,8 +1555,8 @@ timer@b120000 { compatible = "arm,armv7-timer-mem"; reg = <0x0b120000 0x1000>; - #address-cells = <0x01>; - #size-cells = <0x01>; + #address-cells = <1>; + #size-cells = <1>; ranges; frame@b121000 { diff --git a/arch/arm64/boot/dts/qcom/msm8976.dtsi b/arch/arm64/boot/dts/qcom/msm8976.dtsi index f47fb8ea71e20049d5ca78996c14e7a31626065a..753b9a2105eddbdddf1d336651f68276bb9362b2 100644 --- a/arch/arm64/boot/dts/qcom/msm8976.dtsi +++ b/arch/arm64/boot/dts/qcom/msm8976.dtsi @@ -822,7 +822,7 @@ #interrupt-cells = <4>; }; - sdhc_1: mmc@7824000 { + sdhc_1: mmc@7824900 { compatible = "qcom,msm8976-sdhci", "qcom,sdhci-msm-v4"; reg = <0x07824900 0x500>, <0x07824000 0x800>; reg-names = "hc", "core"; @@ -838,7 +838,7 @@ status = "disabled"; }; - sdhc_2: mmc@7864000 { + sdhc_2: mmc@7864900 { compatible = "qcom,msm8976-sdhci", "qcom,sdhci-msm-v4"; reg = <0x07864900 0x11c>, <0x07864000 0x800>; reg-names = "hc", "core"; @@ -957,7 +957,7 @@ #reset-cells = <1>; }; - sdhc_3: mmc@7a24000 { + sdhc_3: mmc@7a24900 { compatible = "qcom,msm8976-sdhci", "qcom,sdhci-msm-v4"; reg = <0x07a24900 0x11c>, <0x07a24000 0x800>; reg-names = "hc", "core"; diff --git a/arch/arm64/boot/dts/qcom/msm8994.dtsi b/arch/arm64/boot/dts/qcom/msm8994.dtsi index bdc3f2ba1755e48b3e1b81cbd9ee0e790cfe2314..5a7923d7c62ab15b71d901b8d35366bf51585feb 100644 --- a/arch/arm64/boot/dts/qcom/msm8994.dtsi +++ b/arch/arm64/boot/dts/qcom/msm8994.dtsi @@ -342,8 +342,7 @@ }; }; - soc: soc { - + soc: soc@0 { #address-cells = <1>; #size-cells = <1>; ranges = <0 0 0 0xffffffff>; @@ -747,7 +746,7 @@ reg = <0xfc4ab000 0x4>; }; - spmi_bus: spmi@fc4c0000 { + spmi_bus: spmi@fc4cf000 { compatible = "qcom,spmi-pmic-arb"; reg = <0xfc4cf000 0x1000>, <0xfc4cb000 0x1000>, diff --git a/arch/arm64/boot/dts/qcom/msm8996-mtp.dts b/arch/arm64/boot/dts/qcom/msm8996-mtp.dts index 596ad4c896f5577d379955e3d88c8522ddbf4928..495d45a16e63a95a8492a7b5b1c9d7205791e7d8 100644 --- a/arch/arm64/boot/dts/qcom/msm8996-mtp.dts +++ b/arch/arm64/boot/dts/qcom/msm8996-mtp.dts @@ -24,10 +24,10 @@ status = "okay"; }; -&hdmi { +&mdss_hdmi { status = "okay"; }; -&hdmi_phy { +&mdss_hdmi_phy { status = "okay"; }; diff --git a/arch/arm64/boot/dts/qcom/msm8996-oneplus-common.dtsi b/arch/arm64/boot/dts/qcom/msm8996-oneplus-common.dtsi index 2adadc1e5b7ca503480c8e78fd52354ea020f772..ec5457508fe63b08448f40990468ef5bd3a81d8d 100644 --- a/arch/arm64/boot/dts/qcom/msm8996-oneplus-common.dtsi +++ b/arch/arm64/boot/dts/qcom/msm8996-oneplus-common.dtsi @@ -164,21 +164,6 @@ vdda-supply = <&vreg_l2a_1p25>; }; -&dsi0 { - vdda-supply = <&vreg_l2a_1p25>; - vcca-supply = <&vreg_l22a_3p0>; - status = "okay"; -}; - -&dsi0_out { - data-lanes = <0 1 2 3>; -}; - -&dsi0_phy { - vcca-supply = <&vreg_l28a_0p925>; - status = "okay"; -}; - &hsusb_phy1 { vdd-supply = <&vreg_l28a_0p925>; vdda-pll-supply = <&vreg_l12a_1p8>; @@ -201,6 +186,21 @@ status = "okay"; }; +&mdss_dsi0 { + vdda-supply = <&vreg_l2a_1p25>; + vcca-supply = <&vreg_l22a_3p0>; + status = "okay"; +}; + +&mdss_dsi0_out { + data-lanes = <0 1 2 3>; +}; + +&mdss_dsi0_phy { + vcca-supply = <&vreg_l28a_0p925>; + status = "okay"; +}; + &mmcc { vdd-gfx-supply = <&vdd_gfx>; }; diff --git a/arch/arm64/boot/dts/qcom/msm8996-sony-xperia-tone.dtsi b/arch/arm64/boot/dts/qcom/msm8996-sony-xperia-tone.dtsi index 7f4d493a55ff499477ab0bb58f00f201c7b6cbf2..b4b770a9277dc511e18850b2c7cf63d7faf8f70c 100644 --- a/arch/arm64/boot/dts/qcom/msm8996-sony-xperia-tone.dtsi +++ b/arch/arm64/boot/dts/qcom/msm8996-sony-xperia-tone.dtsi @@ -11,6 +11,7 @@ #include "pmi8996.dtsi" #include #include +#include #include #include @@ -605,6 +606,34 @@ }; }; +&pmi8994_lpg { + qcom,power-source = <1>; + status = "okay"; + + multi-led { + color = ; + function = LED_FUNCTION_STATUS; + + #address-cells = <1>; + #size-cells = <0>; + + led@1 { + reg = <1>; + color = ; + }; + + led@2 { + reg = <2>; + color = ; + }; + + led@3 { + reg = <3>; + color = ; + }; + }; +}; + &pmi8994_spmi_regulators { vdd_gfx: pmi8994_s2: s2 { diff --git a/arch/arm64/boot/dts/qcom/msm8996-xiaomi-common.dtsi b/arch/arm64/boot/dts/qcom/msm8996-xiaomi-common.dtsi index 1ce5df0a340543c858f6dfd42c0d352b4d2dd1f8..47f55c7311e925174a84853e4371a33093bb42c1 100644 --- a/arch/arm64/boot/dts/qcom/msm8996-xiaomi-common.dtsi +++ b/arch/arm64/boot/dts/qcom/msm8996-xiaomi-common.dtsi @@ -235,7 +235,15 @@ }; }; -&dsi0 { +&gpu { + status = "okay"; +}; + +&mdss { + status = "okay"; +}; + +&mdss_dsi0 { status = "okay"; vdd-supply = <&vreg_l2a_1p25>; @@ -246,26 +254,18 @@ pinctrl-1 = <&mdss_dsi_sleep &mdss_te_sleep>; }; -&dsi0_out { +&mdss_dsi0_out { status = "okay"; data-lanes = <0 1 2 3>; }; -&dsi0_phy { +&mdss_dsi0_phy { status = "okay"; vcca-supply = <&vreg_l28a_0p925>; }; -&gpu { - status = "okay"; -}; - -&mdss { - status = "okay"; -}; - &mmcc { vdd-gfx-supply = <&vdd_gfx>; }; diff --git a/arch/arm64/boot/dts/qcom/msm8996-xiaomi-gemini.dts b/arch/arm64/boot/dts/qcom/msm8996-xiaomi-gemini.dts index 100123d51494434b027bc12574192950144a2d1f..bdedcf9dff0325fd8c1853d5a75a39d4351f7df3 100644 --- a/arch/arm64/boot/dts/qcom/msm8996-xiaomi-gemini.dts +++ b/arch/arm64/boot/dts/qcom/msm8996-xiaomi-gemini.dts @@ -93,7 +93,13 @@ }; -&dsi0 { +&gpu { + zap-shader { + firmware-name = "qcom/msm8996/gemini/a530_zap.mbn"; + }; +}; + +&mdss_dsi0 { status = "okay"; vdd-supply = <&vreg_l2a_1p25>; @@ -112,22 +118,16 @@ port { panel_in: endpoint { - remote-endpoint = <&dsi0_out>; + remote-endpoint = <&mdss_dsi0_out>; }; }; }; }; -&dsi0_out { +&mdss_dsi0_out { remote-endpoint = <&panel_in>; }; -&gpu { - zap-shader { - firmware-name = "qcom/msm8996/gemini/a530_zap.mbn"; - }; -}; - &pmi8994_wled { status = "okay"; }; diff --git a/arch/arm64/boot/dts/qcom/msm8996.dtsi b/arch/arm64/boot/dts/qcom/msm8996.dtsi index 30257c07e1279f71a2536aafb34573a245c32ed3..0cb2d4f08c3a13a4be10b69e271e0986ecdc3d08 100644 --- a/arch/arm64/boot/dts/qcom/msm8996.dtsi +++ b/arch/arm64/boot/dts/qcom/msm8996.dtsi @@ -606,7 +606,7 @@ }; }; - soc: soc { + soc: soc@0 { #address-cells = <1>; #size-cells = <1>; ranges = <0 0 0 0xffffffff>; @@ -889,16 +889,16 @@ #power-domain-cells = <1>; reg = <0x008c0000 0x40000>; clocks = <&xo_board>, - <&gcc GCC_MMSS_NOC_CFG_AHB_CLK>, <&gcc GPLL0>, - <&dsi0_phy 1>, - <&dsi0_phy 0>, - <&dsi1_phy 1>, - <&dsi1_phy 0>, - <&hdmi_phy>; + <&gcc GCC_MMSS_NOC_CFG_AHB_CLK>, + <&mdss_dsi0_phy 1>, + <&mdss_dsi0_phy 0>, + <&mdss_dsi1_phy 1>, + <&mdss_dsi1_phy 0>, + <&mdss_hdmi_phy>; clock-names = "xo", - "gcc_mmss_noc_cfg_ahb_clk", "gpll0", + "gcc_mmss_noc_cfg_ahb_clk", "dsi0pll", "dsi0pllbyte", "dsi1pll", @@ -980,27 +980,27 @@ port@0 { reg = <0>; mdp5_intf3_out: endpoint { - remote-endpoint = <&hdmi_in>; + remote-endpoint = <&mdss_hdmi_in>; }; }; port@1 { reg = <1>; mdp5_intf1_out: endpoint { - remote-endpoint = <&dsi0_in>; + remote-endpoint = <&mdss_dsi0_in>; }; }; port@2 { reg = <2>; mdp5_intf2_out: endpoint { - remote-endpoint = <&dsi1_in>; + remote-endpoint = <&mdss_dsi1_in>; }; }; }; }; - dsi0: dsi@994000 { + mdss_dsi0: dsi@994000 { compatible = "qcom,msm8996-dsi-ctrl", "qcom,mdss-dsi-ctrl"; reg = <0x00994000 0x400>; @@ -1024,9 +1024,9 @@ "pixel", "core"; assigned-clocks = <&mmcc BYTE0_CLK_SRC>, <&mmcc PCLK0_CLK_SRC>; - assigned-clock-parents = <&dsi0_phy 0>, <&dsi0_phy 1>; + assigned-clock-parents = <&mdss_dsi0_phy 0>, <&mdss_dsi0_phy 1>; - phys = <&dsi0_phy>; + phys = <&mdss_dsi0_phy>; status = "disabled"; #address-cells = <1>; @@ -1038,20 +1038,20 @@ port@0 { reg = <0>; - dsi0_in: endpoint { + mdss_dsi0_in: endpoint { remote-endpoint = <&mdp5_intf1_out>; }; }; port@1 { reg = <1>; - dsi0_out: endpoint { + mdss_dsi0_out: endpoint { }; }; }; }; - dsi0_phy: phy@994400 { + mdss_dsi0_phy: phy@994400 { compatible = "qcom,dsi-phy-14nm"; reg = <0x00994400 0x100>, <0x00994500 0x300>, @@ -1068,7 +1068,7 @@ status = "disabled"; }; - dsi1: dsi@996000 { + mdss_dsi1: dsi@996000 { compatible = "qcom,msm8996-dsi-ctrl", "qcom,mdss-dsi-ctrl"; reg = <0x00996000 0x400>; @@ -1092,9 +1092,9 @@ "pixel", "core"; assigned-clocks = <&mmcc BYTE1_CLK_SRC>, <&mmcc PCLK1_CLK_SRC>; - assigned-clock-parents = <&dsi1_phy 0>, <&dsi1_phy 1>; + assigned-clock-parents = <&mdss_dsi1_phy 0>, <&mdss_dsi1_phy 1>; - phys = <&dsi1_phy>; + phys = <&mdss_dsi1_phy>; status = "disabled"; #address-cells = <1>; @@ -1106,20 +1106,20 @@ port@0 { reg = <0>; - dsi1_in: endpoint { + mdss_dsi1_in: endpoint { remote-endpoint = <&mdp5_intf2_out>; }; }; port@1 { reg = <1>; - dsi1_out: endpoint { + mdss_dsi1_out: endpoint { }; }; }; }; - dsi1_phy: phy@996400 { + mdss_dsi1_phy: phy@996400 { compatible = "qcom,dsi-phy-14nm"; reg = <0x00996400 0x100>, <0x00996500 0x300>, @@ -1136,8 +1136,8 @@ status = "disabled"; }; - hdmi: hdmi-tx@9a0000 { - compatible = "qcom,hdmi-tx-8996"; + mdss_hdmi: mdss_hdmi-tx@9a0000 { + compatible = "qcom,mdss_hdmi-tx-8996"; reg = <0x009a0000 0x50c>, <0x00070000 0x6158>, <0x009e0000 0xfff>; @@ -1160,7 +1160,7 @@ "alt_iface", "extp"; - phys = <&hdmi_phy>; + phys = <&mdss_hdmi_phy>; #sound-dai-cells = <1>; status = "disabled"; @@ -1171,16 +1171,16 @@ port@0 { reg = <0>; - hdmi_in: endpoint { + mdss_hdmi_in: endpoint { remote-endpoint = <&mdp5_intf3_out>; }; }; }; }; - hdmi_phy: phy@9a0600 { + mdss_hdmi_phy: phy@9a0600 { #phy-cells = <0>; - compatible = "qcom,hdmi-phy-8996"; + compatible = "qcom,mdss_hdmi-phy-8996"; reg = <0x009a0600 0x1c4>, <0x009a0a00 0x124>, <0x009a0c00 0x124>, @@ -1832,7 +1832,7 @@ compatible = "simple-pm-bus"; #address-cells = <1>; #size-cells = <1>; - ranges; + ranges = <0x0 0x0 0xffffffff>; pcie0: pcie@600000 { compatible = "qcom,pcie-msm8996"; @@ -2069,7 +2069,7 @@ }; }; - camss: camss@a00000 { + camss: camss@a34000 { compatible = "qcom,msm8996-camss"; reg = <0x00a34000 0x1000>, <0x00a00030 0x4>, diff --git a/arch/arm64/boot/dts/qcom/msm8996pro-xiaomi-natrium.dts b/arch/arm64/boot/dts/qcom/msm8996pro-xiaomi-natrium.dts index d18d0b0eda95e33ad4dcd7e1399ac816b7ef63e8..7957c8823f0d5c44e8d4b3446691c16e4a0f9b2e 100644 --- a/arch/arm64/boot/dts/qcom/msm8996pro-xiaomi-natrium.dts +++ b/arch/arm64/boot/dts/qcom/msm8996pro-xiaomi-natrium.dts @@ -39,7 +39,13 @@ }; }; -&dsi0 { +&gpu { + zap-shader { + firmware-name = "qcom/msm8996/natrium/a530_zap.mbn"; + }; +}; + +&mdss_dsi0 { status = "okay"; vdda-supply = <&vreg_l2a_1p25>; @@ -57,22 +63,16 @@ port { panel_in: endpoint { - remote-endpoint = <&dsi0_out>; + remote-endpoint = <&mdss_dsi0_out>; }; }; }; }; -&dsi0_out { +&mdss_dsi0_out { remote-endpoint = <&panel_in>; }; -&gpu { - zap-shader { - firmware-name = "qcom/msm8996/natrium/a530_zap.mbn"; - }; -}; - &mss_pil { firmware-name = "qcom/msm8996/natrium/mba.mbn", "qcom/msm8996/natrium/modem.mbn"; diff --git a/arch/arm64/boot/dts/qcom/msm8996pro.dtsi b/arch/arm64/boot/dts/qcom/msm8996pro.dtsi index a679a9c0cf99d0a991e4f5a575132eee2eb76cac..b74cff06f300d920fe4a057c5ac12aaf3d10c37b 100644 --- a/arch/arm64/boot/dts/qcom/msm8996pro.dtsi +++ b/arch/arm64/boot/dts/qcom/msm8996pro.dtsi @@ -24,101 +24,121 @@ opp-hz = /bits/ 64 <307200000>; opp-supported-hw = <0x70>; clock-latency-ns = <200000>; + opp-peak-kBps = <192000>; }; opp-384000000 { opp-hz = /bits/ 64 <384000000>; opp-supported-hw = <0x70>; clock-latency-ns = <200000>; + opp-peak-kBps = <192000>; }; opp-460800000 { opp-hz = /bits/ 64 <460800000>; opp-supported-hw = <0x70>; clock-latency-ns = <200000>; + opp-peak-kBps = <192000>; }; opp-537600000 { opp-hz = /bits/ 64 <537600000>; opp-supported-hw = <0x70>; clock-latency-ns = <200000>; + opp-peak-kBps = <192000>; }; opp-614400000 { opp-hz = /bits/ 64 <614400000>; opp-supported-hw = <0x70>; clock-latency-ns = <200000>; + opp-peak-kBps = <192000>; }; opp-691200000 { opp-hz = /bits/ 64 <691200000>; opp-supported-hw = <0x70>; clock-latency-ns = <200000>; + opp-peak-kBps = <307200>; }; opp-768000000 { opp-hz = /bits/ 64 <768000000>; opp-supported-hw = <0x70>; clock-latency-ns = <200000>; + opp-peak-kBps = <307200>; }; opp-844800000 { opp-hz = /bits/ 64 <844800000>; opp-supported-hw = <0x70>; clock-latency-ns = <200000>; + opp-peak-kBps = <384000>; }; opp-902400000 { opp-hz = /bits/ 64 <902400000>; opp-supported-hw = <0x70>; clock-latency-ns = <200000>; + opp-peak-kBps = <441600>; }; opp-979200000 { opp-hz = /bits/ 64 <979200000>; opp-supported-hw = <0x70>; clock-latency-ns = <200000>; + opp-peak-kBps = <537600>; }; opp-1056000000 { opp-hz = /bits/ 64 <1056000000>; opp-supported-hw = <0x70>; clock-latency-ns = <200000>; + opp-peak-kBps = <614400>; }; opp-1132800000 { opp-hz = /bits/ 64 <1132800000>; opp-supported-hw = <0x70>; clock-latency-ns = <200000>; + opp-peak-kBps = <691200>; }; opp-1209600000 { opp-hz = /bits/ 64 <1209600000>; opp-supported-hw = <0x70>; clock-latency-ns = <200000>; + opp-peak-kBps = <768000>; }; opp-1286400000 { opp-hz = /bits/ 64 <1286400000>; opp-supported-hw = <0x70>; clock-latency-ns = <200000>; + opp-peak-kBps = <844800>; }; opp-1363200000 { opp-hz = /bits/ 64 <1363200000>; opp-supported-hw = <0x70>; clock-latency-ns = <200000>; + opp-peak-kBps = <902400>; }; opp-1440000000 { opp-hz = /bits/ 64 <1440000000>; opp-supported-hw = <0x70>; clock-latency-ns = <200000>; + opp-peak-kBps = <979200>; }; opp-1516800000 { opp-hz = /bits/ 64 <1516800000>; opp-supported-hw = <0x70>; clock-latency-ns = <200000>; + opp-peak-kBps = <1132800>; }; opp-1593600000 { opp-hz = /bits/ 64 <1593600000>; opp-supported-hw = <0x70>; clock-latency-ns = <200000>; + opp-peak-kBps = <1190400>; }; opp-1996800000 { opp-hz = /bits/ 64 <1996800000>; opp-supported-hw = <0x20>; clock-latency-ns = <200000>; + opp-peak-kBps = <1516800>; }; opp-2188800000 { opp-hz = /bits/ 64 <2188800000>; opp-supported-hw = <0x10>; clock-latency-ns = <200000>; + opp-peak-kBps = <1593600>; }; }; @@ -131,136 +151,163 @@ opp-hz = /bits/ 64 <307200000>; opp-supported-hw = <0x70>; clock-latency-ns = <200000>; + opp-peak-kBps = <192000>; }; opp-384000000 { opp-hz = /bits/ 64 <384000000>; opp-supported-hw = <0x70>; clock-latency-ns = <200000>; + opp-peak-kBps = <192000>; }; opp-460800000 { opp-hz = /bits/ 64 <460800000>; opp-supported-hw = <0x70>; clock-latency-ns = <200000>; + opp-peak-kBps = <192000>; }; opp-537600000 { opp-hz = /bits/ 64 <537600000>; opp-supported-hw = <0x70>; clock-latency-ns = <200000>; + opp-peak-kBps = <192000>; }; opp-614400000 { opp-hz = /bits/ 64 <614400000>; opp-supported-hw = <0x70>; clock-latency-ns = <200000>; + opp-peak-kBps = <192000>; }; opp-691200000 { opp-hz = /bits/ 64 <691200000>; opp-supported-hw = <0x70>; clock-latency-ns = <200000>; + opp-peak-kBps = <307200>; }; opp-748800000 { opp-hz = /bits/ 64 <748800000>; opp-supported-hw = <0x70>; clock-latency-ns = <200000>; + opp-peak-kBps = <307200>; }; opp-825600000 { opp-hz = /bits/ 64 <825600000>; opp-supported-hw = <0x70>; clock-latency-ns = <200000>; + opp-peak-kBps = <384000>; }; opp-902400000 { opp-hz = /bits/ 64 <902400000>; opp-supported-hw = <0x70>; clock-latency-ns = <200000>; + opp-peak-kBps = <441600>; }; opp-979200000 { opp-hz = /bits/ 64 <979200000>; opp-supported-hw = <0x70>; clock-latency-ns = <200000>; + opp-peak-kBps = <441600>; }; opp-1056000000 { opp-hz = /bits/ 64 <1056000000>; opp-supported-hw = <0x70>; clock-latency-ns = <200000>; + opp-peak-kBps = <537600>; }; opp-1132800000 { opp-hz = /bits/ 64 <1132800000>; opp-supported-hw = <0x70>; clock-latency-ns = <200000>; + opp-peak-kBps = <614400>; }; opp-1209600000 { opp-hz = /bits/ 64 <1209600000>; opp-supported-hw = <0x70>; clock-latency-ns = <200000>; + opp-peak-kBps = <691200>; }; opp-1286400000 { opp-hz = /bits/ 64 <1286400000>; opp-supported-hw = <0x70>; clock-latency-ns = <200000>; + opp-peak-kBps = <768000>; }; opp-1363200000 { opp-hz = /bits/ 64 <1363200000>; opp-supported-hw = <0x70>; clock-latency-ns = <200000>; + opp-peak-kBps = <844800>; }; opp-1440000000 { opp-hz = /bits/ 64 <1440000000>; opp-supported-hw = <0x70>; clock-latency-ns = <200000>; + opp-peak-kBps = <902400>; }; opp-1516800000 { opp-hz = /bits/ 64 <1516800000>; opp-supported-hw = <0x70>; clock-latency-ns = <200000>; + opp-peak-kBps = <979200>; }; opp-1593600000 { opp-hz = /bits/ 64 <1593600000>; opp-supported-hw = <0x70>; clock-latency-ns = <200000>; + opp-peak-kBps = <1056000>; }; opp-1670400000 { opp-hz = /bits/ 64 <1670400000>; opp-supported-hw = <0x70>; clock-latency-ns = <200000>; + opp-peak-kBps = <1132800>; }; opp-1747200000 { opp-hz = /bits/ 64 <1747200000>; opp-supported-hw = <0x70>; clock-latency-ns = <200000>; + opp-peak-kBps = <1190400>; }; opp-1824000000 { opp-hz = /bits/ 64 <1824000000>; opp-supported-hw = <0x70>; clock-latency-ns = <200000>; + opp-peak-kBps = <1286400>; }; opp-1900800000 { opp-hz = /bits/ 64 <1900800000>; opp-supported-hw = <0x70>; clock-latency-ns = <200000>; + opp-peak-kBps = <1363200>; }; opp-1977600000 { opp-hz = /bits/ 64 <1977600000>; opp-supported-hw = <0x30>; clock-latency-ns = <200000>; + opp-peak-kBps = <1440000>; }; opp-2054400000 { opp-hz = /bits/ 64 <2054400000>; opp-supported-hw = <0x30>; clock-latency-ns = <200000>; + opp-peak-kBps = <1516800>; }; opp-2150400000 { opp-hz = /bits/ 64 <2150400000>; opp-supported-hw = <0x30>; clock-latency-ns = <200000>; + opp-peak-kBps = <1593600>; }; opp-2246400000 { opp-hz = /bits/ 64 <2246400000>; opp-supported-hw = <0x10>; clock-latency-ns = <200000>; + opp-peak-kBps = <1593600>; }; opp-2342400000 { opp-hz = /bits/ 64 <2342400000>; opp-supported-hw = <0x10>; clock-latency-ns = <200000>; + opp-peak-kBps = <1593600>; }; }; }; @@ -289,3 +336,7 @@ }; /* The rest is inherited from msm8996 */ }; + +&cbf { + compatible = "qcom,msm8996pro-cbf"; +}; diff --git a/arch/arm64/boot/dts/qcom/msm8998-oneplus-common.dtsi b/arch/arm64/boot/dts/qcom/msm8998-oneplus-common.dtsi index 062d56c42385e2a92144279216c1db678938bb13..68e634f8212cb7eaf2282f21d991171d2b47b3d9 100644 --- a/arch/arm64/boot/dts/qcom/msm8998-oneplus-common.dtsi +++ b/arch/arm64/boot/dts/qcom/msm8998-oneplus-common.dtsi @@ -279,10 +279,6 @@ }; }; -&pmi8998_rradc { - status = "okay"; -}; - &qusb2phy { status = "okay"; diff --git a/arch/arm64/boot/dts/qcom/msm8998.dtsi b/arch/arm64/boot/dts/qcom/msm8998.dtsi index 3ec941fed14fedcd6c8c36a829e01d562394d6d6..f0e943ff004640908237ee4b0cba30bca7d22d11 100644 --- a/arch/arm64/boot/dts/qcom/msm8998.dtsi +++ b/arch/arm64/boot/dts/qcom/msm8998.dtsi @@ -802,7 +802,7 @@ ; }; - soc: soc { + soc: soc@0 { #address-cells = <1>; #size-cells = <1>; ranges = <0 0 0 0xffffffff>; @@ -1230,6 +1230,57 @@ drive-strength = <2>; bias-pull-up; }; + + blsp1_spi_b_default: blsp1-spi-b-default-state { + pins = "gpio23", "gpio28"; + function = "blsp1_spi_b"; + drive-strength = <6>; + bias-disable; + }; + + blsp1_spi1_default: blsp1-spi1-default-state { + pins = "gpio0", "gpio1", "gpio2", "gpio3"; + function = "blsp_spi1"; + drive-strength = <6>; + bias-disable; + }; + + blsp1_spi2_default: blsp1-spi2-default-state { + pins = "gpio31", "gpio34", "gpio32", "gpio33"; + function = "blsp_spi2"; + drive-strength = <6>; + bias-disable; + }; + + blsp1_spi3_default: blsp1-spi3-default-state { + pins = "gpio45", "gpio46", "gpio47", "gpio48"; + function = "blsp_spi2"; + drive-strength = <6>; + bias-disable; + }; + + blsp1_spi4_default: blsp1-spi4-default-state { + pins = "gpio8", "gpio9", "gpio10", "gpio11"; + function = "blsp_spi4"; + drive-strength = <6>; + bias-disable; + }; + + blsp1_spi5_default: blsp1-spi5-default-state { + pins = "gpio85", "gpio86", "gpio87", "gpio88"; + function = "blsp_spi5"; + drive-strength = <6>; + bias-disable; + }; + + blsp1_spi6_default: blsp1-spi6-default-state { + pins = "gpio41", "gpio42", "gpio43", "gpio44"; + function = "blsp_spi6"; + drive-strength = <6>; + bias-disable; + }; + + /* 6 interfaces per QUP, BLSP2 indexes are numbered (n)+6 */ blsp2_i2c1_default: blsp2-i2c1-default-state { pins = "gpio55", "gpio56"; @@ -1314,6 +1365,48 @@ drive-strength = <2>; bias-pull-up; }; + + blsp2_spi1_default: blsp2-spi1-default-state { + pins = "gpio53", "gpio54", "gpio55", "gpio56"; + function = "blsp_spi7"; + drive-strength = <6>; + bias-disable; + }; + + blsp2_spi2_default: blsp2-spi2-default-state { + pins = "gpio4", "gpio5", "gpio6", "gpio7"; + function = "blsp_spi8"; + drive-strength = <6>; + bias-disable; + }; + + blsp2_spi3_default: blsp2-spi3-default-state { + pins = "gpio49", "gpio50", "gpio51", "gpio52"; + function = "blsp_spi9"; + drive-strength = <6>; + bias-disable; + }; + + blsp2_spi4_default: blsp2-spi4-default-state { + pins = "gpio65", "gpio66", "gpio67", "gpio68"; + function = "blsp_spi10"; + drive-strength = <6>; + bias-disable; + }; + + blsp2_spi5_default: blsp2-spi5-default-state { + pins = "gpio58", "gpio59", "gpio60", "gpio61"; + function = "blsp_spi11"; + drive-strength = <6>; + bias-disable; + }; + + blsp2_spi6_default: blsp2-spi6-default-state { + pins = "gpio81", "gpio82", "gpio83", "gpio84"; + function = "blsp_spi12"; + drive-strength = <6>; + bias-disable; + }; }; remoteproc_mss: remoteproc@4080000 { @@ -2251,6 +2344,114 @@ #size-cells = <0>; }; + blsp1_spi1: spi@c175000 { + compatible = "qcom,spi-qup-v2.2.1"; + reg = <0x0c175000 0x600>; + interrupts = ; + + clocks = <&gcc GCC_BLSP1_QUP1_SPI_APPS_CLK>, + <&gcc GCC_BLSP1_AHB_CLK>; + clock-names = "core", "iface"; + dmas = <&blsp1_dma 6>, <&blsp1_dma 7>; + dma-names = "tx", "rx"; + pinctrl-names = "default"; + pinctrl-0 = <&blsp1_spi1_default>; + + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; + }; + + blsp1_spi2: spi@c176000 { + compatible = "qcom,spi-qup-v2.2.1"; + reg = <0x0c176000 0x600>; + interrupts = ; + + clocks = <&gcc GCC_BLSP1_QUP2_SPI_APPS_CLK>, + <&gcc GCC_BLSP1_AHB_CLK>; + clock-names = "core", "iface"; + dmas = <&blsp1_dma 8>, <&blsp1_dma 9>; + dma-names = "tx", "rx"; + pinctrl-names = "default"; + pinctrl-0 = <&blsp1_spi2_default>; + + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; + }; + + blsp1_spi3: spi@c177000 { + compatible = "qcom,spi-qup-v2.2.1"; + reg = <0x0c177000 0x600>; + interrupts = ; + + clocks = <&gcc GCC_BLSP1_QUP3_SPI_APPS_CLK>, + <&gcc GCC_BLSP1_AHB_CLK>; + clock-names = "core", "iface"; + dmas = <&blsp1_dma 10>, <&blsp1_dma 11>; + dma-names = "tx", "rx"; + pinctrl-names = "default"; + pinctrl-0 = <&blsp1_spi3_default>; + + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; + }; + + blsp1_spi4: spi@c178000 { + compatible = "qcom,spi-qup-v2.2.1"; + reg = <0x0c178000 0x600>; + interrupts = ; + + clocks = <&gcc GCC_BLSP1_QUP4_SPI_APPS_CLK>, + <&gcc GCC_BLSP1_AHB_CLK>; + clock-names = "core", "iface"; + dmas = <&blsp1_dma 12>, <&blsp1_dma 13>; + dma-names = "tx", "rx"; + pinctrl-names = "default"; + pinctrl-0 = <&blsp1_spi4_default>; + + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; + }; + + blsp1_spi5: spi@c179000 { + compatible = "qcom,spi-qup-v2.2.1"; + reg = <0x0c179000 0x600>; + interrupts = ; + + clocks = <&gcc GCC_BLSP1_QUP5_SPI_APPS_CLK>, + <&gcc GCC_BLSP1_AHB_CLK>; + clock-names = "core", "iface"; + dmas = <&blsp1_dma 14>, <&blsp1_dma 15>; + dma-names = "tx", "rx"; + pinctrl-names = "default"; + pinctrl-0 = <&blsp1_spi5_default>; + + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; + }; + + blsp1_spi6: spi@c17a000 { + compatible = "qcom,spi-qup-v2.2.1"; + reg = <0x0c17a000 0x600>; + interrupts = ; + + clocks = <&gcc GCC_BLSP1_QUP6_SPI_APPS_CLK>, + <&gcc GCC_BLSP1_AHB_CLK>; + clock-names = "core", "iface"; + dmas = <&blsp1_dma 16>, <&blsp1_dma 17>; + dma-names = "tx", "rx"; + pinctrl-names = "default"; + pinctrl-0 = <&blsp1_spi6_default>; + + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; + }; + blsp2_dma: dma-controller@c184000 { compatible = "qcom,bam-v1.7.0"; reg = <0x0c184000 0x25000>; @@ -2394,6 +2595,114 @@ #size-cells = <0>; }; + blsp2_spi1: spi@c1b5000 { + compatible = "qcom,spi-qup-v2.2.1"; + reg = <0x0c1b5000 0x600>; + interrupts = ; + + clocks = <&gcc GCC_BLSP2_QUP1_SPI_APPS_CLK>, + <&gcc GCC_BLSP2_AHB_CLK>; + clock-names = "core", "iface"; + dmas = <&blsp2_dma 6>, <&blsp2_dma 7>; + dma-names = "tx", "rx"; + pinctrl-names = "default"; + pinctrl-0 = <&blsp2_spi1_default>; + + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; + }; + + blsp2_spi2: spi@c1b6000 { + compatible = "qcom,spi-qup-v2.2.1"; + reg = <0x0c1b6000 0x600>; + interrupts = ; + + clocks = <&gcc GCC_BLSP2_QUP2_SPI_APPS_CLK>, + <&gcc GCC_BLSP2_AHB_CLK>; + clock-names = "core", "iface"; + dmas = <&blsp2_dma 8>, <&blsp2_dma 9>; + dma-names = "tx", "rx"; + pinctrl-names = "default"; + pinctrl-0 = <&blsp2_spi2_default>; + + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; + }; + + blsp2_spi3: spi@c1b7000 { + compatible = "qcom,spi-qup-v2.2.1"; + reg = <0x0c1b7000 0x600>; + interrupts = ; + + clocks = <&gcc GCC_BLSP2_QUP3_SPI_APPS_CLK>, + <&gcc GCC_BLSP2_AHB_CLK>; + clock-names = "core", "iface"; + dmas = <&blsp2_dma 10>, <&blsp2_dma 11>; + dma-names = "tx", "rx"; + pinctrl-names = "default"; + pinctrl-0 = <&blsp2_spi3_default>; + + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; + }; + + blsp2_spi4: spi@c1b8000 { + compatible = "qcom,spi-qup-v2.2.1"; + reg = <0x0c1b8000 0x600>; + interrupts = ; + + clocks = <&gcc GCC_BLSP2_QUP4_SPI_APPS_CLK>, + <&gcc GCC_BLSP2_AHB_CLK>; + clock-names = "core", "iface"; + dmas = <&blsp2_dma 12>, <&blsp2_dma 13>; + dma-names = "tx", "rx"; + pinctrl-names = "default"; + pinctrl-0 = <&blsp2_spi4_default>; + + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; + }; + + blsp2_spi5: spi@c1b9000 { + compatible = "qcom,spi-qup-v2.2.1"; + reg = <0x0c1b9000 0x600>; + interrupts = ; + + clocks = <&gcc GCC_BLSP2_QUP5_SPI_APPS_CLK>, + <&gcc GCC_BLSP2_AHB_CLK>; + clock-names = "core", "iface"; + dmas = <&blsp2_dma 14>, <&blsp2_dma 15>; + dma-names = "tx", "rx"; + pinctrl-names = "default"; + pinctrl-0 = <&blsp2_spi5_default>; + + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; + }; + + blsp2_spi6: spi@c1ba000 { + compatible = "qcom,spi-qup-v2.2.1"; + reg = <0x0c1ba000 0x600>; + interrupts = ; + + clocks = <&gcc GCC_BLSP2_QUP6_SPI_APPS_CLK>, + <&gcc GCC_BLSP2_AHB_CLK>; + clock-names = "core", "iface"; + dmas = <&blsp2_dma 16>, <&blsp2_dma 17>; + dma-names = "tx", "rx"; + pinctrl-names = "default"; + pinctrl-0 = <&blsp2_spi6_default>; + + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; + }; + mmcc: clock-controller@c8c0000 { compatible = "qcom,mmcc-msm8998"; #clock-cells = <1>; diff --git a/arch/arm64/boot/dts/qcom/pm7250b.dtsi b/arch/arm64/boot/dts/qcom/pm7250b.dtsi index d709d955a2f5a4e73da404bd2243c33d7407c2c2..daa6f1d30efa01b4616b45da0092875bc8fac0a0 100644 --- a/arch/arm64/boot/dts/qcom/pm7250b.dtsi +++ b/arch/arm64/boot/dts/qcom/pm7250b.dtsi @@ -3,6 +3,7 @@ * Copyright (C) 2022 Luca Weiss */ +#include #include #include diff --git a/arch/arm64/boot/dts/qcom/pm8550.dtsi b/arch/arm64/boot/dts/qcom/pm8550.dtsi index 46396ec1a330afd371f0ba84b0b77d9669ed58a4..db3d5c17a77dfbe363e3b0ccfff0c4b92863f109 100644 --- a/arch/arm64/boot/dts/qcom/pm8550.dtsi +++ b/arch/arm64/boot/dts/qcom/pm8550.dtsi @@ -55,5 +55,21 @@ interrupt-controller; #interrupt-cells = <2>; }; + + pm8550_flash: led-controller@ee00 { + compatible = "qcom,pm8550-flash-led", "qcom,spmi-flash-led"; + reg = <0xee00>; + status = "disabled"; + }; + + pm8550_pwm: pwm { + compatible = "qcom,pm8550-pwm", "qcom,pm8350c-pwm"; + + #address-cells = <1>; + #size-cells = <0>; + #pwm-cells = <2>; + + status = "disabled"; + }; }; }; diff --git a/arch/arm64/boot/dts/qcom/pm8916.dtsi b/arch/arm64/boot/dts/qcom/pm8916.dtsi index f4fb1a92ab55a51a65638e7696ab245e91c8b240..1ea8920ff3694108672bdeea260ba587ed3e7303 100644 --- a/arch/arm64/boot/dts/qcom/pm8916.dtsi +++ b/arch/arm64/boot/dts/qcom/pm8916.dtsi @@ -139,7 +139,7 @@ status = "disabled"; }; - wcd_codec: audio-codec@f000 { + pm8916_codec: audio-codec@f000 { compatible = "qcom,pm8916-wcd-analog-codec"; reg = <0xf000>; reg-names = "pmic-codec-core"; @@ -174,10 +174,8 @@ "cdc_ear_cnp_int", "cdc_hphr_cnp_int", "cdc_hphl_cnp_int"; - vdd-cdc-io-supply = <&pm8916_l5>; - vdd-cdc-tx-rx-cx-supply = <&pm8916_l5>; - vdd-micbias-supply = <&pm8916_l13>; #sound-dai-cells = <1>; + status = "disabled"; }; }; }; diff --git a/arch/arm64/boot/dts/qcom/pm8953.dtsi b/arch/arm64/boot/dts/qcom/pm8953.dtsi index a1d36f9ebbd259e41a80e3af516d9a044419afe0..2268daf27fa7afc028d9a244f6c03a31375aecd8 100644 --- a/arch/arm64/boot/dts/qcom/pm8953.dtsi +++ b/arch/arm64/boot/dts/qcom/pm8953.dtsi @@ -79,6 +79,16 @@ reg-names = "rtc", "alarm"; interrupts = <0x0 0x61 0x1 IRQ_TYPE_EDGE_RISING>; }; + + pm8953_gpios: gpio@c000 { + compatible = "qcom,pm8953-gpio", "qcom,spmi-gpio"; + reg = <0xc000>; + gpio-controller; + gpio-ranges = <&pm8953_gpios 0 0 8>; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + }; }; pmic@1 { diff --git a/arch/arm64/boot/dts/qcom/pm8998.dtsi b/arch/arm64/boot/dts/qcom/pm8998.dtsi index 340033ac31860e52fb5c9edc65b7e0fb08a5d601..695d79116cde257b94ddc9083072863fca7cef76 100644 --- a/arch/arm64/boot/dts/qcom/pm8998.dtsi +++ b/arch/arm64/boot/dts/qcom/pm8998.dtsi @@ -55,7 +55,7 @@ pm8998_resin: resin { compatible = "qcom,pm8941-resin"; - interrupts = ; + interrupts = <0x0 0x8 1 IRQ_TYPE_EDGE_BOTH>; debounce = <15625>; bias-pull-up; status = "disabled"; diff --git a/arch/arm64/boot/dts/qcom/pmi632.dtsi b/arch/arm64/boot/dts/qcom/pmi632.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..4eb79e0ce40a5e9715d15d5dfadecac7dbe0fbab --- /dev/null +++ b/arch/arm64/boot/dts/qcom/pmi632.dtsi @@ -0,0 +1,165 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (C) 2023 Luca Weiss + */ + +#include +#include +#include + +/ { + thermal-zones { + pmi632-thermal { + polling-delay-passive = <100>; + polling-delay = <0>; + + thermal-sensors = <&pmi632_temp>; + + trips { + trip0 { + temperature = <95000>; + hysteresis = <0>; + type = "passive"; + }; + + trip1 { + temperature = <115000>; + hysteresis = <0>; + type = "hot"; + }; + + trip2 { + temperature = <125000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + }; +}; + +&spmi_bus { + pmic@2 { + compatible = "qcom,pmi632", "qcom,spmi-pmic"; + reg = <0x2 SPMI_USID>; + #address-cells = <1>; + #size-cells = <0>; + + pmi632_temp: temp-alarm@2400 { + compatible = "qcom,spmi-temp-alarm"; + reg = <0x2400>; + interrupts = <0x2 0x24 0x0 IRQ_TYPE_EDGE_BOTH>; + #thermal-sensor-cells = <0>; + }; + + pmi632_adc: adc@3100 { + compatible = "qcom,spmi-adc5"; + reg = <0x3100>; + #address-cells = <1>; + #size-cells = <0>; + #io-channel-cells = <1>; + interrupts = <0x2 0x31 0x0 IRQ_TYPE_EDGE_RISING>; + + channel@0 { + reg = ; + qcom,pre-scaling = <1 1>; + label = "ref_gnd"; + }; + + channel@1 { + reg = ; + qcom,pre-scaling = <1 1>; + label = "vref_1p25"; + }; + + channel@6 { + reg = ; + qcom,pre-scaling = <1 1>; + label = "die_temp"; + }; + + channel@7 { + reg = ; + qcom,pre-scaling = <1 1>; + label = "usb_in_i_uv"; + }; + + channel@8 { + reg = ; + qcom,pre-scaling = <1 16>; + label = "usb_in_v_div_16"; + }; + + channel@9 { + reg = ; + qcom,pre-scaling = <1 1>; + label = "chg_temp"; + }; + + channel@4b { + reg = ; + qcom,hw-settle-time = <200>; + qcom,pre-scaling = <1 1>; + qcom,ratiometric; + label = "bat_id"; + }; + + channel@83 { + reg = ; + qcom,pre-scaling = <1 3>; + label = "vph_pwr"; + }; + + channel@84 { + reg = ; + qcom,pre-scaling = <1 3>; + label = "vbat_sns"; + }; + }; + + pmi632_adc_tm: adc-tm@3500 { + compatible = "qcom,spmi-adc-tm5"; + reg = <0x3500>; + interrupts = <0x2 0x35 0x0 IRQ_TYPE_EDGE_RISING>; + #thermal-sensor-cells = <1>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + pmi632_sdam_7: nvram@b600 { + compatible = "qcom,spmi-sdam"; + reg = <0xb600>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0xb600 0x100>; + }; + + pmi632_gpios: gpio@c000 { + compatible = "qcom,pmi632-gpio", "qcom,spmi-gpio"; + reg = <0xc000>; + gpio-controller; + gpio-ranges = <&pmi632_gpios 0 0 8>; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + }; + }; + + pmic@3 { + compatible = "qcom,pmi632", "qcom,spmi-pmic"; + reg = <0x3 SPMI_USID>; + #address-cells = <1>; + #size-cells = <0>; + + pmi632_lpg: pwm { + compatible = "qcom,pmi632-lpg"; + + #address-cells = <1>; + #size-cells = <0>; + #pwm-cells = <2>; + + status = "disabled"; + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/pmi8998.dtsi b/arch/arm64/boot/dts/qcom/pmi8998.dtsi index ffe587f281d8cdc81703d545b98b661e09b87853..cd3f0790fd4202b7c7fbf2c309811819ec8a6a8e 100644 --- a/arch/arm64/boot/dts/qcom/pmi8998.dtsi +++ b/arch/arm64/boot/dts/qcom/pmi8998.dtsi @@ -9,6 +9,26 @@ #address-cells = <1>; #size-cells = <0>; + pmi8998_charger: charger@1000 { + compatible = "qcom,pmi8998-charger"; + reg = <0x1000>; + + interrupts = <0x2 0x13 0x4 IRQ_TYPE_EDGE_BOTH>, + <0x2 0x12 0x2 IRQ_TYPE_EDGE_BOTH>, + <0x2 0x16 0x1 IRQ_TYPE_EDGE_RISING>, + <0x2 0x13 0x6 IRQ_TYPE_EDGE_RISING>; + interrupt-names = "usb-plugin", + "bat-ov", + "wdog-bark", + "usbin-icl-change"; + + io-channels = <&pmi8998_rradc 3>, + <&pmi8998_rradc 4>; + io-channel-names = "usbin_i", "usbin_v"; + + status = "disabled"; + }; + pmi8998_gpios: gpio@c000 { compatible = "qcom,pmi8998-gpio", "qcom,spmi-gpio"; reg = <0xc000>; @@ -23,8 +43,6 @@ compatible = "qcom,pmi8998-rradc"; reg = <0x4500>; #io-channel-cells = <1>; - - status = "disabled"; }; }; @@ -60,6 +78,12 @@ status = "disabled"; }; + pmi8998_flash: led-controller@d300 { + compatible = "qcom,pmi8998-flash-led", "qcom,spmi-flash-led"; + reg = <0xd300>; + status = "disabled"; + }; + pmi8998_wled: leds@d800 { compatible = "qcom,pmi8998-wled"; reg = <0xd800>, <0xd900>; diff --git a/arch/arm64/boot/dts/qcom/pmk8350.dtsi b/arch/arm64/boot/dts/qcom/pmk8350.dtsi index f26fb7d32faf2e7e29ed1787c60d974e62dbd957..bc6297e7253e2bb8602402a5aab1f1aeb6120135 100644 --- a/arch/arm64/boot/dts/qcom/pmk8350.dtsi +++ b/arch/arm64/boot/dts/qcom/pmk8350.dtsi @@ -13,6 +13,16 @@ #define PMK8350_SID 0 #endif +/ { + reboot-mode { + compatible = "nvmem-reboot-mode"; + nvmem-cells = <&reboot_reason>; + nvmem-cell-names = "reboot-mode"; + mode-recovery = <0x01>; + mode-bootloader = <0x02>; + }; +}; + &spmi_bus { pmk8350: pmic@PMK8350_SID { compatible = "qcom,pmk8350", "qcom,spmi-pmic"; @@ -66,6 +76,19 @@ status = "disabled"; }; + pmk8350_sdam_2: nvram@7100 { + compatible = "qcom,spmi-sdam"; + reg = <0x7100>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0x7100 0x100>; + + reboot_reason: reboot-reason@48 { + reg = <0x48 0x1>; + bits = <1 7>; + }; + }; + pmk8350_gpios: gpio@b000 { compatible = "qcom,pmk8350-gpio", "qcom,spmi-gpio"; reg = <0xb000>; diff --git a/arch/arm64/boot/dts/qcom/pmk8550.dtsi b/arch/arm64/boot/dts/qcom/pmk8550.dtsi index 201efeda7d2d972deb8819625a77763e20eaefd5..c7ac9b2eaacfe6e8363448d9d2ffb4ac8f5f4dd2 100644 --- a/arch/arm64/boot/dts/qcom/pmk8550.dtsi +++ b/arch/arm64/boot/dts/qcom/pmk8550.dtsi @@ -8,6 +8,16 @@ #include #include +/ { + reboot-mode { + compatible = "nvmem-reboot-mode"; + nvmem-cells = <&reboot_reason>; + nvmem-cell-names = "reboot-mode"; + mode-recovery = <0x01>; + mode-bootloader = <0x02>; + }; +}; + &spmi_bus { pmk8550: pmic@0 { compatible = "qcom,pm8550", "qcom,spmi-pmic"; @@ -39,7 +49,19 @@ reg = <0x6100>, <0x6200>; reg-names = "rtc", "alarm"; interrupts = <0x0 0x62 0x1 IRQ_TYPE_EDGE_RISING>; - status = "disabled"; + }; + + pmk8550_sdam_2: nvram@7100 { + compatible = "qcom,spmi-sdam"; + reg = <0x7100>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0x7100 0x100>; + + reboot_reason: reboot-reason@48 { + reg = <0x48 0x1>; + bits = <1 7>; + }; }; pmk8550_gpios: gpio@8800 { diff --git a/arch/arm64/boot/dts/qcom/qcm2290.dtsi b/arch/arm64/boot/dts/qcom/qcm2290.dtsi index b29bc4e4b837c6f083aa48c4e13dbbd2df8d4947..0ed11e80e5e29f716809c85f1cc86aaa17240a2f 100644 --- a/arch/arm64/boot/dts/qcom/qcm2290.dtsi +++ b/arch/arm64/boot/dts/qcom/qcm2290.dtsi @@ -48,6 +48,8 @@ enable-method = "psci"; next-level-cache = <&L2_0>; qcom,freq-domain = <&cpufreq_hw 0>; + power-domains = <&CPU_PD0>; + power-domain-names = "psci"; L2_0: l2-cache { compatible = "cache"; cache-level = <2>; @@ -65,6 +67,8 @@ enable-method = "psci"; next-level-cache = <&L2_0>; qcom,freq-domain = <&cpufreq_hw 0>; + power-domains = <&CPU_PD1>; + power-domain-names = "psci"; }; CPU2: cpu@2 { @@ -77,6 +81,8 @@ enable-method = "psci"; next-level-cache = <&L2_0>; qcom,freq-domain = <&cpufreq_hw 0>; + power-domains = <&CPU_PD2>; + power-domain-names = "psci"; }; CPU3: cpu@3 { @@ -89,6 +95,8 @@ enable-method = "psci"; next-level-cache = <&L2_0>; qcom,freq-domain = <&cpufreq_hw 0>; + power-domains = <&CPU_PD3>; + power-domain-names = "psci"; }; cpu-map { @@ -110,6 +118,30 @@ }; }; }; + + domain-idle-states { + CLUSTER_SLEEP: cluster-sleep-0 { + compatible = "domain-idle-state"; + arm,psci-suspend-param = <0x41000043>; + entry-latency-us = <800>; + exit-latency-us = <2118>; + min-residency-us = <7376>; + }; + }; + + idle-states { + entry-method = "psci"; + + CPU_SLEEP: cpu-sleep-0 { + compatible = "arm,idle-state"; + idle-state-name = "power-collapse"; + arm,psci-suspend-param = <0x40000003>; + entry-latency-us = <290>; + exit-latency-us = <376>; + min-residency-us = <1182>; + local-timer-stop; + }; + }; }; firmware { @@ -135,6 +167,35 @@ psci { compatible = "arm,psci-1.0"; method = "smc"; + + CPU_PD0: power-domain-cpu0 { + #power-domain-cells = <0>; + power-domains = <&CLUSTER_PD>; + domain-idle-states = <&CPU_SLEEP>; + }; + + CPU_PD1: power-domain-cpu1 { + #power-domain-cells = <0>; + power-domains = <&CLUSTER_PD>; + domain-idle-states = <&CPU_SLEEP>; + }; + + CPU_PD2: power-domain-cpu2 { + #power-domain-cells = <0>; + power-domains = <&CLUSTER_PD>; + domain-idle-states = <&CPU_SLEEP>; + }; + + CPU_PD3: power-domain-cpu3 { + #power-domain-cells = <0>; + power-domains = <&CLUSTER_PD>; + domain-idle-states = <&CPU_SLEEP>; + }; + + CLUSTER_PD: power-domain-cpu-cluster { + #power-domain-cells = <0>; + domain-idle-states = <&CLUSTER_SLEEP>; + }; }; reserved_memory: reserved-memory { diff --git a/arch/arm64/boot/dts/qcom/qcs404-evb-4000.dts b/arch/arm64/boot/dts/qcom/qcs404-evb-4000.dts index 59702ba24f3517fbb231bc05682aba20657396cb..358827c2fbd31b2018c1de1d1a926da020471a05 100644 --- a/arch/arm64/boot/dts/qcom/qcs404-evb-4000.dts +++ b/arch/arm64/boot/dts/qcom/qcs404-evb-4000.dts @@ -27,8 +27,8 @@ phy-handle = <&phy1>; phy-mode = "rgmii"; mdio { - #address-cells = <0x1>; - #size-cells = <0x0>; + #address-cells = <1>; + #size-cells = <0>; compatible = "snps,dwmac-mdio"; phy1: phy@4 { compatible = "ethernet-phy-ieee802.3-c22"; diff --git a/arch/arm64/boot/dts/qcom/qdu1000-idp.dts b/arch/arm64/boot/dts/qcom/qdu1000-idp.dts index 9e9fd4b8023e67e838518492ccdb8e9a6e394258..1d22f87fd238d6a3499e769bec34ee56f94596c5 100644 --- a/arch/arm64/boot/dts/qcom/qdu1000-idp.dts +++ b/arch/arm64/boot/dts/qcom/qdu1000-idp.dts @@ -448,6 +448,29 @@ status = "okay"; }; +&sdhc { + pinctrl-0 = <&sdc_on_state>; + pinctrl-1 = <&sdc_off_state>; + pinctrl-names = "default", "sleep"; + + cap-mmc-hw-reset; + mmc-ddr-1_8v; + mmc-hs200-1_8v; + mmc-hs400-1_8v; + mmc-hs400-enhanced-strobe; + + non-removable; + no-sd; + no-sdio; + + supports-cqe; + + vmmc-supply = <&vreg_l10a_2p95>; + vqmmc-supply = <&vreg_l7a_1p8>; + + status = "okay"; +}; + &uart7 { status = "okay"; }; diff --git a/arch/arm64/boot/dts/qcom/qdu1000.dtsi b/arch/arm64/boot/dts/qcom/qdu1000.dtsi index fb553f0bb17aae36b16b0c08dd5241409cffcab3..1c0e5d271e91bb1c55445423a84b082ece168070 100644 --- a/arch/arm64/boot/dts/qcom/qdu1000.dtsi +++ b/arch/arm64/boot/dts/qcom/qdu1000.dtsi @@ -852,6 +852,53 @@ #hwlock-cells = <1>; }; + sdhc: mmc@8804000 { + compatible = "qcom,qdu1000-sdhci", "qcom,sdhci-msm-v5"; + reg = <0x0 0x08804000 0x0 0x1000>, + <0x0 0x08805000 0x0 0x1000>; + reg-names = "hc", "cqhci"; + + interrupts = , + ; + interrupt-names = "hc_irq", "pwr_irq"; + + clocks = <&gcc GCC_SDCC5_AHB_CLK>, + <&gcc GCC_SDCC5_APPS_CLK>, + <&rpmhcc RPMH_CXO_CLK>; + clock-names = "iface", + "core", + "xo"; + + resets = <&gcc GCC_SDCC5_BCR>; + + interconnects = <&system_noc MASTER_SDCC_1 0 &mc_virt SLAVE_EBI1 0>, + <&gem_noc MASTER_APPSS_PROC 0 &system_noc SLAVE_SDCC_2 0>; + interconnect-names = "sdhc-ddr", "cpu-sdhc"; + power-domains = <&rpmhpd QDU1000_CX>; + operating-points-v2 = <&sdhc1_opp_table>; + + iommus = <&apps_smmu 0x80 0x0>; + dma-coherent; + + bus-width = <8>; + + qcom,dll-config = <0x0007642c>; + qcom,ddr-config = <0x80040868>; + + status = "disabled"; + + sdhc1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-384000000 { + opp-hz = /bits/ 64 <384000000>; + required-opps = <&rpmhpd_opp_nom>; + opp-peak-kBps = <6528000 1652800>; + opp-avg-kBps = <400000 0>; + }; + }; + }; + pdc: interrupt-controller@b220000 { compatible = "qcom,qdu1000-pdc", "qcom,pdc"; reg = <0x0 0xb220000 0x0 0x30000>, <0x0 0x174000f0 0x0 0x64>; @@ -1110,10 +1157,73 @@ pins = "gpio31"; function = "gpio"; }; + + sdc_on_state: sdc-on-state { + clk-pins { + pins = "sdc1_clk"; + drive-strength = <16>; + bias-disable; + }; + + cmd-pins { + pins = "sdc1_cmd"; + drive-strength = <10>; + bias-pull-up; + }; + + data-pins { + pins = "sdc1_data"; + drive-strength = <10>; + bias-pull-up; + }; + + rclk-pins { + pins = "sdc1_rclk"; + bias-pull-down; + }; + }; + + sdc_off_state: sdc-off-state { + clk-pins { + pins = "sdc1_clk"; + drive-strength = <2>; + bias-disable; + }; + + cmd-pins { + pins = "sdc1_cmd"; + drive-strength = <2>; + bias-pull-up; + }; + + data-pins { + pins = "sdc1_data"; + drive-strength = <2>; + bias-pull-up; + }; + + rclk-pins { + pins = "sdc1_rclk"; + bias-pull-down; + }; + }; + }; + + sram@14680000 { + compatible = "qcom,qdu1000-imem", "syscon", "simple-mfd"; + reg = <0 0x14680000 0 0x1000>; + ranges = <0 0 0x14680000 0x1000>; + #address-cells = <1>; + #size-cells = <1>; + + pil-reloc@94c { + compatible = "qcom,pil-reloc-info"; + reg = <0x94c 0xc8>; + }; }; apps_smmu: iommu@15000000 { - compatible = "qcom,qdu1000-smmu-500", "arm,mmu-500"; + compatible = "qcom,qdu1000-smmu-500", "qcom,smmu-500", "arm,mmu-500"; reg = <0x0 0x15000000 0x0 0x100000>; #iommu-cells = <2>; #global-interrupts = <2>; @@ -1252,6 +1362,7 @@ qcom,tcs-config = , , , ; label = "apps_rsc"; + power-domains = <&CLUSTER_PD>; apps_bcm_voter: bcm-voter { compatible = "qcom,bcm-voter"; diff --git a/arch/arm64/boot/dts/qcom/qrb4210-rb2.dts b/arch/arm64/boot/dts/qcom/qrb4210-rb2.dts index dc80f0bca7676d6fb3ac5744ca854d68b7498d0b..e23a0406eaccd58d0e82dc243ce0f63d48751e22 100644 --- a/arch/arm64/boot/dts/qcom/qrb4210-rb2.dts +++ b/arch/arm64/boot/dts/qcom/qrb4210-rb2.dts @@ -5,7 +5,9 @@ /dts-v1/; +#include #include "sm4250.dtsi" +#include "pm6125.dtsi" / { model = "Qualcomm Technologies, Inc. QRB4210 RB2"; @@ -19,21 +21,257 @@ stdout-path = "serial0:115200n8"; }; - vph_pwr: vph-pwr-regulator { + clocks { + clk40M: can-clk { + compatible = "fixed-clock"; + clock-frequency = <40000000>; + #clock-cells = <0>; + }; + }; + + gpio-keys { + compatible = "gpio-keys"; + label = "gpio-keys"; + + pinctrl-0 = <&kypd_vol_up_n>; + pinctrl-names = "default"; + + key-volume-up { + label = "Volume Up"; + linux,code = ; + gpios = <&pm6125_gpios 5 GPIO_ACTIVE_LOW>; + debounce-interval = <15>; + linux,can-disable; + wakeup-source; + }; + }; + + hdmi-connector { + compatible = "hdmi-connector"; + type = "a"; + + port { + hdmi_con: endpoint { + remote-endpoint = <<9611_out>; + }; + }; + }; + + leds { + compatible = "gpio-leds"; + + led-bt { + label = "blue:bt"; + function = LED_FUNCTION_BLUETOOTH; + color = ; + gpios = <&tlmm 45 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "bluetooth-power"; + default-state = "off"; + }; + + led-user0 { + label = "green:user0"; + function = LED_FUNCTION_INDICATOR; + color = ; + gpios = <&tlmm 52 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "none"; + default-state = "off"; + panic-indicator; + }; + + led-wlan { + label = "yellow:wlan"; + function = LED_FUNCTION_WLAN; + color = ; + gpios = <&tlmm 47 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "phy0tx"; + default-state = "off"; + }; + }; + + vreg_hdmi_out_1p2: regulator-hdmi-out-1p2 { + compatible = "regulator-fixed"; + regulator-name = "VREG_HDMI_OUT_1P2"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + vin-supply = <&vdc_1v2>; + regulator-always-on; + regulator-boot-on; + }; + + lt9611_3v3: regulator-lt9611-3v3 { + compatible = "regulator-fixed"; + regulator-name = "LT9611_3V3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + vin-supply = <&vdc_3v3>; + regulator-always-on; + regulator-boot-on; + }; + + /* Main barrel jack input */ + vdc_12v: regulator-vdc-12v { + compatible = "regulator-fixed"; + regulator-name = "DC_12V"; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + regulator-always-on; + regulator-boot-on; + }; + + /* 1.2V supply stepped down from the barrel jack input */ + vdc_1v2: regulator-vdc-1v2 { + compatible = "regulator-fixed"; + regulator-name = "VDC_1V2"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + vin-supply = <&vdc_12v>; + regulator-always-on; + regulator-boot-on; + }; + + /* 3.3V supply stepped down from the barrel jack input */ + vdc_3v3: regulator-vdc-3v3 { + compatible = "regulator-fixed"; + regulator-name = "VDC_3V3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + vin-supply = <&vdc_12v>; + regulator-always-on; + regulator-boot-on; + }; + + /* 5V supply stepped down from the barrel jack input */ + vdc_5v: regulator-vdc-5v { + compatible = "regulator-fixed"; + regulator-name = "VDC_5V"; + + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-always-on; + regulator-boot-on; + }; + + /* "Battery" voltage for the SoM, stepped down from the barrel jack input */ + vdc_vbat_som: regulator-vdc-vbat { + compatible = "regulator-fixed"; + regulator-name = "VBAT_SOM"; + regulator-min-microvolt = <4200000>; + regulator-max-microvolt = <4200000>; + regulator-always-on; + regulator-boot-on; + }; + + /* PMI632 charger out, supplied by VBAT */ + vph_pwr: regulator-vph-pwr { compatible = "regulator-fixed"; regulator-name = "vph_pwr"; regulator-min-microvolt = <3700000>; regulator-max-microvolt = <3700000>; + vin-supply = <&vdc_vbat_som>; regulator-always-on; regulator-boot-on; }; }; +&gpi_dma0 { + status = "okay"; +}; + +&i2c2 { + clock-frequency = <400000>; + status = "okay"; + + lt9611_codec: hdmi-bridge@2b { + compatible = "lontium,lt9611uxc"; + reg = <0x2b>; + interrupts-extended = <&tlmm 46 IRQ_TYPE_EDGE_FALLING>; + reset-gpios = <&tlmm 41 GPIO_ACTIVE_HIGH>; + + vdd-supply = <&vreg_hdmi_out_1p2>; + vcc-supply = <<9611_3v3>; + + pinctrl-0 = <<9611_irq_pin <9611_rst_pin>; + pinctrl-names = "default"; + #sound-dai-cells = <1>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + lt9611_a: endpoint { + remote-endpoint = <&mdss_dsi0_out>; + }; + }; + + port@2 { + reg = <2>; + + lt9611_out: endpoint { + remote-endpoint = <&hdmi_con>; + }; + }; + }; + }; +}; + +&mdss { + status = "okay"; +}; + +&mdss_dsi0 { + vdda-supply = <&vreg_l18a_1p232>; + status = "okay"; +}; + +&mdss_dsi0_out { + remote-endpoint = <<9611_a>; + data-lanes = <0 1 2 3>; +}; + +&mdss_dsi0_phy { + status = "okay"; +}; + +&pm6125_gpios { + kypd_vol_up_n: kypd-vol-up-n-state { + pins = "gpio5"; + function = "normal"; + power-source = <0>; + bias-pull-up; + input-enable; + }; +}; + +&pon_pwrkey { + status = "okay"; +}; + +&pon_resin { + linux,code = ; + status = "okay"; +}; + &qupv3_id_0 { status = "okay"; }; +&remoteproc_adsp { + firmware-name = "qcom/qrb4210/adsp.mbn"; + + status = "okay"; +}; + +&remoteproc_cdsp { + firmware-name = "qcom/qrb4210/cdsp.mbn"; + + status = "okay"; +}; + &rpm_requests { regulators { compatible = "qcom,rpm-pm6125-regulators"; @@ -86,6 +324,7 @@ vreg_l5a_2p96: l5 { regulator-min-microvolt = <1648000>; regulator-max-microvolt = <3056000>; + regulator-allow-set-load; }; vreg_l6a_0p6: l6 { @@ -116,6 +355,7 @@ vreg_l11a_1p8: l11 { regulator-min-microvolt = <1704000>; regulator-max-microvolt = <1952000>; + regulator-allow-set-load; }; vreg_l12a_1p8: l12 { @@ -190,6 +430,10 @@ }; &sdhc_1 { + pinctrl-0 = <&sdc1_state_on>; + pinctrl-1 = <&sdc1_state_off>; + pinctrl-names = "default", "sleep"; + vmmc-supply = <&vreg_l24a_2p96>; vqmmc-supply = <&vreg_l11a_1p8>; no-sdio; @@ -199,7 +443,12 @@ }; &sdhc_2 { - cd-gpios = <&tlmm 88 GPIO_ACTIVE_HIGH>; /* card detect gpio */ + cd-gpios = <&tlmm 88 GPIO_ACTIVE_LOW>; /* card detect gpio */ + + pinctrl-0 = <&sdc2_state_on &sdc2_card_det_n>; + pinctrl-1 = <&sdc2_state_off &sdc2_card_det_n>; + pinctrl-names = "default", "sleep"; + vmmc-supply = <&vreg_l22a_2p96>; vqmmc-supply = <&vreg_l5a_2p96>; no-sdio; @@ -207,21 +456,78 @@ status = "okay"; }; +&spi5 { + status = "okay"; + + can@0 { + compatible = "microchip,mcp2518fd"; + reg = <0>; + interrupts-extended = <&tlmm 39 IRQ_TYPE_LEVEL_LOW>; + clocks = <&clk40M>; + spi-max-frequency = <10000000>; + vdd-supply = <&vdc_5v>; + xceiver-supply = <&vdc_5v>; + }; +}; + &sleep_clk { clock-frequency = <32000>; }; &tlmm { - gpio-reserved-ranges = <37 5>, <43 2>, <47 1>, - <49 1>, <52 1>, <54 1>, + gpio-reserved-ranges = <43 2>, <49 1>, <54 1>, <56 3>, <61 2>, <64 1>, <68 1>, <72 8>, <96 1>; + + lt9611_rst_pin: lt9611-rst-state { + pins = "gpio41"; + function = "gpio"; + input-disable; + output-high; + }; + + lt9611_irq_pin: lt9611-irq-state { + pins = "gpio46"; + function = "gpio"; + bias-disable; + }; + + sdc2_card_det_n: sd-card-det-n-state { + pins = "gpio88"; + function = "gpio"; + drive-strength = <2>; + bias-pull-up; + }; }; &uart4 { status = "okay"; }; +&usb { + status = "okay"; +}; + +&usb_dwc3 { + maximum-speed = "super-speed"; + dr_mode = "peripheral"; +}; + +&usb_hsphy { + vdd-supply = <&vreg_l4a_0p9>; + vdda-pll-supply = <&vreg_l12a_1p8>; + vdda-phy-dpdm-supply = <&vreg_l15a_3p128>; + + status = "okay"; +}; + +&usb_qmpphy { + vdda-phy-supply = <&vreg_l4a_0p9>; + vdda-pll-supply = <&vreg_l12a_1p8>; + + status = "okay"; +}; + &xo_board { clock-frequency = <19200000>; }; diff --git a/arch/arm64/boot/dts/qcom/qrb5165-rb5.dts b/arch/arm64/boot/dts/qcom/qrb5165-rb5.dts index dd924331b0eea6b1557fcfb02f0accc60756a328..9022ad726741cb112a92076d6652930f9b64082f 100644 --- a/arch/arm64/boot/dts/qcom/qrb5165-rb5.dts +++ b/arch/arm64/boot/dts/qcom/qrb5165-rb5.dts @@ -535,30 +535,6 @@ firmware-name = "qcom/sm8250/cdsp.mbn"; }; -&dsi0 { - status = "okay"; - vdda-supply = <&vreg_l9a_1p2>; - -#if 0 - qcom,dual-dsi-mode; - qcom,master-dsi; -#endif - - ports { - port@1 { - endpoint { - remote-endpoint = <<9611_a>; - data-lanes = <0 1 2 3>; - }; - }; - }; -}; - -&dsi0_phy { - status = "okay"; - vdds-supply = <&vreg_l5a_0p88>; -}; - &gmu { status = "okay"; }; @@ -604,7 +580,7 @@ reg = <0>; lt9611_a: endpoint { - remote-endpoint = <&dsi0_out>; + remote-endpoint = <&mdss_dsi0_out>; }; }; @@ -613,7 +589,7 @@ reg = <1>; lt9611_b: endpoint { - remote-endpoint = <&dsi1_out>; + remote-endpoint = <&mdss_dsi1_out>; }; }; #endif @@ -639,8 +615,28 @@ status = "okay"; }; -&mdss_mdp { +&mdss_dsi0 { + status = "okay"; + vdda-supply = <&vreg_l9a_1p2>; + +#if 0 + qcom,dual-dsi-mode; + qcom,master-dsi; +#endif + + ports { + port@1 { + endpoint { + remote-endpoint = <<9611_a>; + data-lanes = <0 1 2 3>; + }; + }; + }; +}; + +&mdss_dsi0_phy { status = "okay"; + vdds-supply = <&vreg_l5a_0p88>; }; &pm8150_adc { diff --git a/arch/arm64/boot/dts/qcom/sa8155p-adp.dts b/arch/arm64/boot/dts/qcom/sa8155p-adp.dts index 15e1ae1c1a9774302bf44490e99cbb515cb61208..5e4287f8c8cd19c84181b9533b9476eb0f7927ca 100644 --- a/arch/arm64/boot/dts/qcom/sa8155p-adp.dts +++ b/arch/arm64/boot/dts/qcom/sa8155p-adp.dts @@ -47,29 +47,6 @@ vin-supply = <&vreg_3p3>; }; - - mtl_rx_setup: rx-queues-config { - snps,rx-queues-to-use = <1>; - snps,rx-sched-sp; - - queue0 { - snps,dcb-algorithm; - snps,map-to-dma-channel = <0x0>; - snps,route-up; - snps,priority = <0x1>; - }; - }; - - mtl_tx_setup: tx-queues-config { - snps,tx-queues-to-use = <1>; - snps,tx-sched-wrr; - - queue0 { - snps,weight = <0x10>; - snps,dcb-algorithm; - snps,priority = <0x0>; - }; - }; }; &apps_rsc { @@ -352,19 +329,40 @@ max-speed = <1000>; mdio { - #address-cells = <0x1>; - #size-cells = <0x0>; - compatible = "snps,dwmac-mdio"; + #address-cells = <1>; + #size-cells = <0>; /* Micrel KSZ9031RNZ PHY */ rgmii_phy: phy@7 { + compatible = "ethernet-phy-ieee802.3-c22"; reg = <0x7>; - interrupt-parent = <&tlmm>; - interrupts-extended = <&tlmm 124 IRQ_TYPE_EDGE_FALLING>; /* phy intr */ + interrupts-extended = <&tlmm 124 IRQ_TYPE_EDGE_FALLING>; device_type = "ethernet-phy"; - compatible = "ethernet-phy-ieee802.3-c22"; + }; + }; + + mtl_rx_setup: rx-queues-config { + snps,rx-queues-to-use = <1>; + snps,rx-sched-sp; + + queue0 { + snps,dcb-algorithm; + snps,map-to-dma-channel = <0x0>; + snps,route-up; + snps,priority = <0x1>; + }; + }; + + mtl_tx_setup: tx-queues-config { + snps,tx-queues-to-use = <1>; + snps,tx-sched-wrr; + + queue0 { + snps,weight = <0x10>; + snps,dcb-algorithm; + snps,priority = <0x0>; }; }; }; diff --git a/arch/arm64/boot/dts/qcom/sa8540p-ride.dts b/arch/arm64/boot/dts/qcom/sa8540p-ride.dts index 24fa449d48a6640a0753366c95b947f02c51b431..5a26974dcf8f95c97dfad53cd0da627331f5e4f3 100644 --- a/arch/arm64/boot/dts/qcom/sa8540p-ride.dts +++ b/arch/arm64/boot/dts/qcom/sa8540p-ride.dts @@ -151,6 +151,185 @@ }; }; +ðernet0 { + snps,mtl-rx-config = <ðernet0_mtl_rx_setup>; + snps,mtl-tx-config = <ðernet0_mtl_tx_setup>; + + max-speed = <1000>; + phy-handle = <&rgmii_phy>; + phy-mode = "rgmii-txid"; + + pinctrl-names = "default"; + pinctrl-0 = <ðernet0_default>; + + status = "okay"; + + mdio { + compatible = "snps,dwmac-mdio"; + #address-cells = <1>; + #size-cells = <0>; + + /* Marvell 88EA1512 */ + rgmii_phy: phy@8 { + compatible = "ethernet-phy-id0141.0dd4"; + reg = <0x8>; + + interrupts-extended = <&tlmm 127 IRQ_TYPE_EDGE_FALLING>; + + reset-gpios = <&pmm8540c_gpios 1 GPIO_ACTIVE_LOW>; + reset-assert-us = <11000>; + reset-deassert-us = <70000>; + + device_type = "ethernet-phy"; + + /* Set to RGMII_SGMII mode and soft reset. Turn off auto-negotiation + * from userspace to talk to the switch on the SGMII side of things + */ + marvell,reg-init = + /* Set MODE[2:0] to RGMII_SGMII */ + <0x12 0x14 0xfff8 0x4>, + /* Soft reset required after changing MODE[2:0] */ + <0x12 0x14 0x7fff 0x8000>; + }; + }; + + ethernet0_mtl_rx_setup: rx-queues-config { + snps,rx-queues-to-use = <1>; + snps,rx-sched-sp; + + queue0 { + snps,dcb-algorithm; + snps,map-to-dma-channel = <0x0>; + snps,route-up; + snps,priority = <0x1>; + }; + + queue1 { + snps,dcb-algorithm; + snps,map-to-dma-channel = <0x1>; + snps,route-ptp; + }; + + queue2 { + snps,avb-algorithm; + snps,map-to-dma-channel = <0x2>; + snps,route-avcp; + }; + + queue3 { + snps,avb-algorithm; + snps,map-to-dma-channel = <0x3>; + snps,priority = <0xc>; + }; + }; + + ethernet0_mtl_tx_setup: tx-queues-config { + snps,tx-queues-to-use = <1>; + snps,tx-sched-sp; + + queue0 { + snps,dcb-algorithm; + }; + + queue1 { + snps,dcb-algorithm; + }; + + queue2 { + snps,avb-algorithm; + snps,send_slope = <0x1000>; + snps,idle_slope = <0x1000>; + snps,high_credit = <0x3e800>; + snps,low_credit = <0xffc18000>; + }; + + queue3 { + snps,avb-algorithm; + snps,send_slope = <0x1000>; + snps,idle_slope = <0x1000>; + snps,high_credit = <0x3e800>; + snps,low_credit = <0xffc18000>; + }; + }; +}; + +ðernet1 { + snps,mtl-rx-config = <ðernet1_mtl_rx_setup>; + snps,mtl-tx-config = <ðernet1_mtl_tx_setup>; + + max-speed = <1000>; + phy-mode = "rgmii-txid"; + + pinctrl-names = "default"; + pinctrl-0 = <ðernet1_default>; + + status = "okay"; + + fixed-link { + speed = <1000>; + full-duplex; + }; + + ethernet1_mtl_rx_setup: rx-queues-config { + snps,rx-queues-to-use = <1>; + snps,rx-sched-sp; + + queue0 { + snps,dcb-algorithm; + snps,map-to-dma-channel = <0x0>; + snps,route-up; + snps,priority = <0x1>; + }; + + queue1 { + snps,dcb-algorithm; + snps,map-to-dma-channel = <0x1>; + snps,route-ptp; + }; + + queue2 { + snps,avb-algorithm; + snps,map-to-dma-channel = <0x2>; + snps,route-avcp; + }; + + queue3 { + snps,avb-algorithm; + snps,map-to-dma-channel = <0x3>; + snps,priority = <0xc>; + }; + }; + + ethernet1_mtl_tx_setup: tx-queues-config { + snps,tx-queues-to-use = <1>; + snps,tx-sched-sp; + + queue0 { + snps,dcb-algorithm; + }; + + queue1 { + snps,dcb-algorithm; + }; + + queue2 { + snps,avb-algorithm; + snps,send_slope = <0x1000>; + snps,idle_slope = <0x1000>; + snps,high_credit = <0x3e800>; + snps,low_credit = <0xffc18000>; + }; + + queue3 { + snps,avb-algorithm; + snps,send_slope = <0x1000>; + snps,idle_slope = <0x1000>; + snps,high_credit = <0x3e800>; + snps,low_credit = <0xffc18000>; + }; + }; +}; + &i2c0 { pinctrl-names = "default"; pinctrl-0 = <&i2c0_default>; @@ -316,6 +495,66 @@ /* PINCTRL */ &tlmm { + ethernet0_default: ethernet0-default-state { + mdc-pins { + pins = "gpio175"; + function = "rgmii_0"; + drive-strength = <16>; + bias-pull-up; + }; + + mdio-pins { + pins = "gpio176"; + function = "rgmii_0"; + drive-strength = <16>; + bias-pull-up; + }; + + rgmii-tx-pins { + pins = "gpio183", "gpio184", "gpio185", "gpio186", "gpio187", "gpio188"; + function = "rgmii_0"; + drive-strength = <16>; + bias-pull-up; + }; + + rgmii-rx-pins { + pins = "gpio177", "gpio178", "gpio179", "gpio180", "gpio181", "gpio182"; + function = "rgmii_0"; + drive-strength = <16>; + bias-disable; + }; + }; + + ethernet1_default: ethernet1-default-state { + mdc-pins { + pins = "gpio97"; + function = "rgmii_1"; + drive-strength = <16>; + bias-pull-up; + }; + + mdio-pins { + pins = "gpio98"; + function = "rgmii_1"; + drive-strength = <16>; + bias-pull-up; + }; + + rgmii-tx-pins { + pins = "gpio105", "gpio106", "gpio107", "gpio108", "gpio109", "gpio110"; + function = "rgmii_1"; + drive-strength = <16>; + bias-pull-up; + }; + + rgmii-rx-pins { + pins = "gpio99", "gpio100", "gpio101", "gpio102", "gpio103", "gpio104"; + function = "rgmii_1"; + drive-strength = <16>; + bias-disable; + }; + }; + i2c0_default: i2c0-default-state { /* To USB7002T-I/KDXVA0 USB hub (SIP1 only) */ pins = "gpio135", "gpio136"; diff --git a/arch/arm64/boot/dts/qcom/sa8540p.dtsi b/arch/arm64/boot/dts/qcom/sa8540p.dtsi index 4a990fda8fc32d3b903202e71221380ac6ce6791..bacbdec5628147c38590b207841b28c17cdca138 100644 --- a/arch/arm64/boot/dts/qcom/sa8540p.dtsi +++ b/arch/arm64/boot/dts/qcom/sa8540p.dtsi @@ -167,6 +167,14 @@ }; }; +&gpucc { + status = "disabled"; +}; + +&gpu_smmu { + status = "disabled"; +}; + &pcie2a { compatible = "qcom,pcie-sa8540p"; diff --git a/arch/arm64/boot/dts/qcom/sa8775p-pmics.dtsi b/arch/arm64/boot/dts/qcom/sa8775p-pmics.dtsi index 7602cca47baec48038766ee4985e30c073d28c69..3c3b6287cd274854252ea7e109d631dceddb5081 100644 --- a/arch/arm64/boot/dts/qcom/sa8775p-pmics.dtsi +++ b/arch/arm64/boot/dts/qcom/sa8775p-pmics.dtsi @@ -88,6 +88,14 @@ }; }; }; + + reboot-mode { + compatible = "nvmem-reboot-mode"; + nvmem-cells = <&reboot_reason>; + nvmem-cell-names = "reboot-mode"; + mode-recovery = <0x01>; + mode-bootloader = <0x02>; + }; }; &spmi_bus { @@ -108,8 +116,6 @@ compatible = "qcom,pmk8350-pon"; reg = <0x1200>, <0x800>; reg-names = "hlos", "pbs"; - mode-recovery = <0x1>; - mode-bootloader = <0x2>; pmm8654au_0_pon_pwrkey: pwrkey { compatible = "qcom,pmk8350-pwrkey"; @@ -135,6 +141,19 @@ interrupt-controller; #interrupt-cells = <2>; }; + + pmm8654au_0_sdam_0: nvram@7100 { + compatible = "qcom,spmi-sdam"; + reg = <0x7100>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0x7100 0x100>; + + reboot_reason: reboot-reason@48 { + reg = <0x48 0x1>; + bits = <1 7>; + }; + }; }; pmm8654au_1: pmic@2 { diff --git a/arch/arm64/boot/dts/qcom/sa8775p-ride.dts b/arch/arm64/boot/dts/qcom/sa8775p-ride.dts index f238a02a54480ed40a401e1a7846f306d7fbb9da..ab767cfa51ff5e4bca344ea04d4e5cf7bd447867 100644 --- a/arch/arm64/boot/dts/qcom/sa8775p-ride.dts +++ b/arch/arm64/boot/dts/qcom/sa8775p-ride.dts @@ -5,6 +5,7 @@ /dts-v1/; +#include #include #include "sa8775p.dtsi" @@ -18,8 +19,10 @@ serial0 = &uart10; serial1 = &uart12; serial2 = &uart17; + i2c11 = &i2c11; i2c18 = &i2c18; spi16 = &spi16; + ufshc1 = &ufs_mem_hc; }; chosen { @@ -258,6 +261,13 @@ }; }; +&i2c11 { + clock-frequency = <400000>; + pinctrl-0 = <&qup_i2c11_default>; + pinctrl-names = "default"; + status = "okay"; +}; + &i2c18 { clock-frequency = <400000>; pinctrl-0 = <&qup_i2c18_default>; @@ -291,6 +301,13 @@ "BT_EN", "USB2_PWR_EN", "USB2_FAULT"; + + usb2_en_state: usb2-en-state { + pins = "gpio9"; + function = "normal"; + output-high; + power-source = <0>; + }; }; &pmm8654au_2_gpios { @@ -306,6 +323,20 @@ "USB1_PWR_ENABLE", "USB1_FAULT", "VMON_SPX8"; + + usb0_en_state: usb0-en-state { + pins = "gpio3"; + function = "normal"; + output-high; + power-source = <0>; + }; + + usb1_en_state: usb1-en-state { + pins = "gpio10"; + function = "normal"; + output-high; + power-source = <0>; + }; }; &pmm8654au_3_gpios { @@ -347,6 +378,13 @@ bias-disable; }; + qup_i2c11_default: qup-i2c11-state { + pins = "gpio48", "gpio49"; + function = "qup1_se4"; + drive-strength = <2>; + bias-pull-up; + }; + qup_i2c18_default: qup-i2c18-state { pins = "gpio95", "gpio96"; function = "qup2_se4"; @@ -426,6 +464,94 @@ status = "okay"; }; +&ufs_mem_hc { + reset-gpios = <&tlmm 149 GPIO_ACTIVE_LOW>; + vcc-supply = <&vreg_l8a>; + vcc-max-microamp = <1100000>; + vccq-supply = <&vreg_l4c>; + vccq-max-microamp = <1200000>; + + status = "okay"; +}; + +&ufs_mem_phy { + vdda-phy-supply = <&vreg_l4a>; + vdda-pll-supply = <&vreg_l1c>; + + status = "okay"; +}; + +&usb_0 { + pinctrl-names = "default"; + pinctrl-0 = <&usb0_en_state>; + + status = "okay"; +}; + +&usb_0_dwc3 { + dr_mode = "peripheral"; +}; + +&usb_0_hsphy { + vdda-pll-supply = <&vreg_l7a>; + vdda18-supply = <&vreg_l6c>; + vdda33-supply = <&vreg_l9a>; + + status = "okay"; +}; + +&usb_0_qmpphy { + vdda-phy-supply = <&vreg_l1c>; + vdda-pll-supply = <&vreg_l7a>; + + status = "okay"; +}; + +&usb_1 { + pinctrl-names = "default"; + pinctrl-0 = <&usb1_en_state>; + + status = "okay"; +}; + +&usb_1_dwc3 { + dr_mode = "host"; +}; + +&usb_1_hsphy { + vdda-pll-supply = <&vreg_l7a>; + vdda18-supply = <&vreg_l6c>; + vdda33-supply = <&vreg_l9a>; + + status = "okay"; +}; + +&usb_1_qmpphy { + vdda-phy-supply = <&vreg_l1c>; + vdda-pll-supply = <&vreg_l7a>; + + status = "okay"; +}; + +&usb_2 { + pinctrl-names = "default"; + pinctrl-0 = <&usb2_en_state>; + + status = "okay"; +}; + +&usb_2_dwc3 { + dr_mode = "host"; +}; + +&usb_2_hsphy { + vdda-pll-supply = <&vreg_l7a>; + vdda18-supply = <&vreg_l6c>; + vdda33-supply = <&vreg_l9a>; + + status = "okay"; +}; + &xo_board_clk { clock-frequency = <38400000>; }; diff --git a/arch/arm64/boot/dts/qcom/sa8775p.dtsi b/arch/arm64/boot/dts/qcom/sa8775p.dtsi index c3310caf9f68c6451692efc1fba96f9bfc4b08e7..b130136acffe90cce3ff1cfb978f333bf3703867 100644 --- a/arch/arm64/boot/dts/qcom/sa8775p.dtsi +++ b/arch/arm64/boot/dts/qcom/sa8775p.dtsi @@ -7,7 +7,9 @@ #include #include #include +#include #include +#include #include #include @@ -308,6 +310,11 @@ }; }; + pmu { + compatible = "arm,armv8-pmuv3"; + interrupts = ; + }; + psci { compatible = "arm,psci-1.0"; method = "smc"; @@ -469,8 +476,8 @@ <0>, <0>, <0>, - <0>, - <0>, + <&usb_0_qmpphy>, + <&usb_1_qmpphy>, <0>, <0>, <0>, @@ -491,126 +498,1345 @@ #mbox-cells = <2>; }; - qupv3_id_2: geniqup@8c0000 { - compatible = "qcom,geni-se-qup"; - reg = <0x0 0x008c0000 0x0 0x6000>; - ranges; - clocks = <&gcc GCC_QUPV3_WRAP_2_M_AHB_CLK>, - <&gcc GCC_QUPV3_WRAP_2_S_AHB_CLK>; - clock-names = "m-ahb", "s-ahb"; - iommus = <&apps_smmu 0x5a3 0x0>; - #address-cells = <2>; - #size-cells = <2>; - status = "disabled"; + qupv3_id_2: geniqup@8c0000 { + compatible = "qcom,geni-se-qup"; + reg = <0x0 0x008c0000 0x0 0x6000>; + ranges; + clocks = <&gcc GCC_QUPV3_WRAP_2_M_AHB_CLK>, + <&gcc GCC_QUPV3_WRAP_2_S_AHB_CLK>; + clock-names = "m-ahb", "s-ahb"; + iommus = <&apps_smmu 0x5a3 0x0>; + #address-cells = <2>; + #size-cells = <2>; + status = "disabled"; + + i2c14: i2c@880000 { + compatible = "qcom,geni-i2c"; + reg = <0x0 0x880000 0x0 0x4000>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = ; + clocks = <&gcc GCC_QUPV3_WRAP2_S0_CLK>; + clock-names = "se"; + interconnects = <&clk_virt MASTER_QUP_CORE_2 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_2 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ALWAYS + &config_noc SLAVE_QUP_2 QCOM_ICC_TAG_ALWAYS>, + <&aggre2_noc MASTER_QUP_2 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "qup-core", + "qup-config", + "qup-memory"; + power-domains = <&rpmhpd SA8775P_CX>; + status = "disabled"; + }; + + spi14: spi@880000 { + compatible = "qcom,geni-spi"; + reg = <0x0 0x880000 0x0 0x4000>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = ; + clocks = <&gcc GCC_QUPV3_WRAP2_S0_CLK>; + clock-names = "se"; + interconnects = <&clk_virt MASTER_QUP_CORE_2 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_2 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ALWAYS + &config_noc SLAVE_QUP_2 QCOM_ICC_TAG_ALWAYS>, + <&aggre2_noc MASTER_QUP_2 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "qup-core", + "qup-config", + "qup-memory"; + power-domains = <&rpmhpd SA8775P_CX>; + status = "disabled"; + }; + + i2c15: i2c@884000 { + compatible = "qcom,geni-i2c"; + reg = <0x0 0x884000 0x0 0x4000>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = ; + clocks = <&gcc GCC_QUPV3_WRAP2_S1_CLK>; + clock-names = "se"; + interconnects = <&clk_virt MASTER_QUP_CORE_2 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_2 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ALWAYS + &config_noc SLAVE_QUP_2 QCOM_ICC_TAG_ALWAYS>, + <&aggre2_noc MASTER_QUP_2 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "qup-core", + "qup-config", + "qup-memory"; + power-domains = <&rpmhpd SA8775P_CX>; + status = "disabled"; + }; + + spi15: spi@884000 { + compatible = "qcom,geni-spi"; + reg = <0x0 0x884000 0x0 0x4000>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = ; + clocks = <&gcc GCC_QUPV3_WRAP2_S1_CLK>; + clock-names = "se"; + interconnects = <&clk_virt MASTER_QUP_CORE_2 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_2 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ALWAYS + &config_noc SLAVE_QUP_2 QCOM_ICC_TAG_ALWAYS>, + <&aggre2_noc MASTER_QUP_2 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "qup-core", + "qup-config", + "qup-memory"; + power-domains = <&rpmhpd SA8775P_CX>; + status = "disabled"; + }; + + i2c16: i2c@888000 { + compatible = "qcom,geni-i2c"; + reg = <0x0 0x888000 0x0 0x4000>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = ; + clocks = <&gcc GCC_QUPV3_WRAP2_S2_CLK>; + clock-names = "se"; + interconnects = <&clk_virt MASTER_QUP_CORE_2 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_2 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ALWAYS + &config_noc SLAVE_QUP_2 QCOM_ICC_TAG_ALWAYS>, + <&aggre2_noc MASTER_QUP_2 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "qup-core", + "qup-config", + "qup-memory"; + power-domains = <&rpmhpd SA8775P_CX>; + status = "disabled"; + }; + + spi16: spi@888000 { + compatible = "qcom,geni-spi"; + reg = <0x0 0x00888000 0x0 0x4000>; + interrupts = ; + clocks = <&gcc GCC_QUPV3_WRAP2_S2_CLK>; + clock-names = "se"; + interconnects = <&clk_virt MASTER_QUP_CORE_2 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_2 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ALWAYS + &config_noc SLAVE_QUP_2 QCOM_ICC_TAG_ALWAYS>, + <&aggre2_noc MASTER_QUP_2 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "qup-core", + "qup-config", + "qup-memory"; + power-domains = <&rpmhpd SA8775P_CX>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + i2c17: i2c@88c000 { + compatible = "qcom,geni-i2c"; + reg = <0x0 0x88c000 0x0 0x4000>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = ; + clocks = <&gcc GCC_QUPV3_WRAP2_S3_CLK>; + clock-names = "se"; + interconnects = <&clk_virt MASTER_QUP_CORE_2 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_2 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ALWAYS + &config_noc SLAVE_QUP_2 QCOM_ICC_TAG_ALWAYS>, + <&aggre2_noc MASTER_QUP_2 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "qup-core", + "qup-config", + "qup-memory"; + power-domains = <&rpmhpd SA8775P_CX>; + status = "disabled"; + }; + + spi17: spi@88c000 { + compatible = "qcom,geni-spi"; + reg = <0x0 0x88c000 0x0 0x4000>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = ; + clocks = <&gcc GCC_QUPV3_WRAP2_S3_CLK>; + clock-names = "se"; + interconnects = <&clk_virt MASTER_QUP_CORE_2 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_2 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ALWAYS + &config_noc SLAVE_QUP_2 QCOM_ICC_TAG_ALWAYS>, + <&aggre2_noc MASTER_QUP_2 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "qup-core", + "qup-config", + "qup-memory"; + power-domains = <&rpmhpd SA8775P_CX>; + status = "disabled"; + }; + + uart17: serial@88c000 { + compatible = "qcom,geni-uart"; + reg = <0x0 0x0088c000 0x0 0x4000>; + interrupts = ; + clocks = <&gcc GCC_QUPV3_WRAP2_S3_CLK>; + clock-names = "se"; + interconnects = <&clk_virt MASTER_QUP_CORE_2 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_2 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ALWAYS + &config_noc SLAVE_QUP_2 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "qup-core", "qup-config"; + power-domains = <&rpmhpd SA8775P_CX>; + status = "disabled"; + }; + + i2c18: i2c@890000 { + compatible = "qcom,geni-i2c"; + reg = <0x0 0x00890000 0x0 0x4000>; + interrupts = ; + clocks = <&gcc GCC_QUPV3_WRAP2_S4_CLK>; + clock-names = "se"; + interconnects = <&clk_virt MASTER_QUP_CORE_2 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_2 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ALWAYS + &config_noc SLAVE_QUP_2 QCOM_ICC_TAG_ALWAYS>, + <&aggre2_noc MASTER_QUP_2 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "qup-core", + "qup-config", + "qup-memory"; + power-domains = <&rpmhpd SA8775P_CX>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + spi18: spi@890000 { + compatible = "qcom,geni-spi"; + reg = <0x0 0x890000 0x0 0x4000>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = ; + clocks = <&gcc GCC_QUPV3_WRAP2_S4_CLK>; + clock-names = "se"; + interconnects = <&clk_virt MASTER_QUP_CORE_2 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_2 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ALWAYS + &config_noc SLAVE_QUP_2 QCOM_ICC_TAG_ALWAYS>, + <&aggre2_noc MASTER_QUP_2 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "qup-core", + "qup-config", + "qup-memory"; + power-domains = <&rpmhpd SA8775P_CX>; + status = "disabled"; + }; + + i2c19: i2c@894000 { + compatible = "qcom,geni-i2c"; + reg = <0x0 0x894000 0x0 0x4000>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = ; + clocks = <&gcc GCC_QUPV3_WRAP2_S5_CLK>; + clock-names = "se"; + interconnects = <&clk_virt MASTER_QUP_CORE_2 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_2 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ALWAYS + &config_noc SLAVE_QUP_2 QCOM_ICC_TAG_ALWAYS>, + <&aggre2_noc MASTER_QUP_2 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "qup-core", + "qup-config", + "qup-memory"; + power-domains = <&rpmhpd SA8775P_CX>; + status = "disabled"; + }; + + spi19: spi@894000 { + compatible = "qcom,geni-spi"; + reg = <0x0 0x894000 0x0 0x4000>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = ; + clocks = <&gcc GCC_QUPV3_WRAP2_S5_CLK>; + clock-names = "se"; + interconnects = <&clk_virt MASTER_QUP_CORE_2 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_2 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ALWAYS + &config_noc SLAVE_QUP_2 QCOM_ICC_TAG_ALWAYS>, + <&aggre2_noc MASTER_QUP_2 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "qup-core", + "qup-config", + "qup-memory"; + power-domains = <&rpmhpd SA8775P_CX>; + status = "disabled"; + }; + + i2c20: i2c@898000 { + compatible = "qcom,geni-i2c"; + reg = <0x0 0x898000 0x0 0x4000>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = ; + clocks = <&gcc GCC_QUPV3_WRAP2_S6_CLK>; + clock-names = "se"; + interconnects = <&clk_virt MASTER_QUP_CORE_2 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_2 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ALWAYS + &config_noc SLAVE_QUP_2 QCOM_ICC_TAG_ALWAYS>, + <&aggre2_noc MASTER_QUP_2 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "qup-core", + "qup-config", + "qup-memory"; + power-domains = <&rpmhpd SA8775P_CX>; + status = "disabled"; + }; + + spi20: spi@898000 { + compatible = "qcom,geni-spi"; + reg = <0x0 0x898000 0x0 0x4000>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = ; + clocks = <&gcc GCC_QUPV3_WRAP2_S6_CLK>; + clock-names = "se"; + interconnects = <&clk_virt MASTER_QUP_CORE_2 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_2 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ALWAYS + &config_noc SLAVE_QUP_2 QCOM_ICC_TAG_ALWAYS>, + <&aggre2_noc MASTER_QUP_2 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "qup-core", + "qup-config", + "qup-memory"; + power-domains = <&rpmhpd SA8775P_CX>; + status = "disabled"; + }; + }; + + qupv3_id_0: geniqup@9c0000 { + compatible = "qcom,geni-se-qup"; + reg = <0x0 0x9c0000 0x0 0x6000>; + #address-cells = <2>; + #size-cells = <2>; + ranges; + clock-names = "m-ahb", "s-ahb"; + clocks = <&gcc GCC_QUPV3_WRAP_0_M_AHB_CLK>, + <&gcc GCC_QUPV3_WRAP_0_S_AHB_CLK>; + iommus = <&apps_smmu 0x403 0x0>; + status = "disabled"; + + i2c0: i2c@980000 { + compatible = "qcom,geni-i2c"; + reg = <0x0 0x980000 0x0 0x4000>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = ; + clocks = <&gcc GCC_QUPV3_WRAP0_S0_CLK>; + clock-names = "se"; + interconnects = <&clk_virt MASTER_QUP_CORE_0 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_0 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ALWAYS + &config_noc SLAVE_QUP_0 QCOM_ICC_TAG_ALWAYS>, + <&aggre2_noc MASTER_QUP_0 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "qup-core", + "qup-config", + "qup-memory"; + power-domains = <&rpmhpd SA8775P_CX>; + status = "disabled"; + }; + + spi0: spi@980000 { + compatible = "qcom,geni-spi"; + reg = <0x0 0x980000 0x0 0x4000>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = ; + clocks = <&gcc GCC_QUPV3_WRAP0_S0_CLK>; + clock-names = "se"; + interconnects = <&clk_virt MASTER_QUP_CORE_0 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_0 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ALWAYS + &config_noc SLAVE_QUP_0 QCOM_ICC_TAG_ALWAYS>, + <&aggre2_noc MASTER_QUP_0 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "qup-core", + "qup-config", + "qup-memory"; + power-domains = <&rpmhpd SA8775P_CX>; + status = "disabled"; + }; + + i2c1: i2c@984000 { + compatible = "qcom,geni-i2c"; + reg = <0x0 0x984000 0x0 0x4000>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = ; + clocks = <&gcc GCC_QUPV3_WRAP0_S1_CLK>; + clock-names = "se"; + interconnects = <&clk_virt MASTER_QUP_CORE_0 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_0 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ALWAYS + &config_noc SLAVE_QUP_0 QCOM_ICC_TAG_ALWAYS>, + <&aggre2_noc MASTER_QUP_0 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "qup-core", + "qup-config", + "qup-memory"; + power-domains = <&rpmhpd SA8775P_CX>; + status = "disabled"; + }; + + spi1: spi@984000 { + compatible = "qcom,geni-spi"; + reg = <0x0 0x984000 0x0 0x4000>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = ; + clocks = <&gcc GCC_QUPV3_WRAP0_S1_CLK>; + clock-names = "se"; + interconnects = <&clk_virt MASTER_QUP_CORE_0 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_0 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ALWAYS + &config_noc SLAVE_QUP_0 QCOM_ICC_TAG_ALWAYS>, + <&aggre2_noc MASTER_QUP_0 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "qup-core", + "qup-config", + "qup-memory"; + power-domains = <&rpmhpd SA8775P_CX>; + status = "disabled"; + }; + + i2c2: i2c@988000 { + compatible = "qcom,geni-i2c"; + reg = <0x0 0x988000 0x0 0x4000>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = ; + clocks = <&gcc GCC_QUPV3_WRAP0_S2_CLK>; + clock-names = "se"; + interconnects = <&clk_virt MASTER_QUP_CORE_0 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_0 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ALWAYS + &config_noc SLAVE_QUP_0 QCOM_ICC_TAG_ALWAYS>, + <&aggre2_noc MASTER_QUP_0 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "qup-core", + "qup-config", + "qup-memory"; + power-domains = <&rpmhpd SA8775P_CX>; + status = "disabled"; + }; + + spi2: spi@988000 { + compatible = "qcom,geni-spi"; + reg = <0x0 0x988000 0x0 0x4000>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = ; + clocks = <&gcc GCC_QUPV3_WRAP0_S2_CLK>; + clock-names = "se"; + interconnects = <&clk_virt MASTER_QUP_CORE_0 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_0 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ALWAYS + &config_noc SLAVE_QUP_0 QCOM_ICC_TAG_ALWAYS>, + <&aggre2_noc MASTER_QUP_0 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "qup-core", + "qup-config", + "qup-memory"; + power-domains = <&rpmhpd SA8775P_CX>; + status = "disabled"; + }; + + i2c3: i2c@98c000 { + compatible = "qcom,geni-i2c"; + reg = <0x0 0x98c000 0x0 0x4000>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = ; + clocks = <&gcc GCC_QUPV3_WRAP0_S3_CLK>; + clock-names = "se"; + interconnects = <&clk_virt MASTER_QUP_CORE_0 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_0 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ALWAYS + &config_noc SLAVE_QUP_0 QCOM_ICC_TAG_ALWAYS>, + <&aggre2_noc MASTER_QUP_0 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "qup-core", + "qup-config", + "qup-memory"; + power-domains = <&rpmhpd SA8775P_CX>; + status = "disabled"; + }; + + spi3: spi@98c000 { + compatible = "qcom,geni-spi"; + reg = <0x0 0x98c000 0x0 0x4000>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = ; + clocks = <&gcc GCC_QUPV3_WRAP0_S3_CLK>; + clock-names = "se"; + interconnects = <&clk_virt MASTER_QUP_CORE_0 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_0 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ALWAYS + &config_noc SLAVE_QUP_0 QCOM_ICC_TAG_ALWAYS>, + <&aggre2_noc MASTER_QUP_0 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "qup-core", + "qup-config", + "qup-memory"; + power-domains = <&rpmhpd SA8775P_CX>; + status = "disabled"; + }; + + i2c4: i2c@990000 { + compatible = "qcom,geni-i2c"; + reg = <0x0 0x990000 0x0 0x4000>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = ; + clocks = <&gcc GCC_QUPV3_WRAP0_S4_CLK>; + clock-names = "se"; + interconnects = <&clk_virt MASTER_QUP_CORE_0 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_0 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ALWAYS + &config_noc SLAVE_QUP_0 QCOM_ICC_TAG_ALWAYS>, + <&aggre2_noc MASTER_QUP_0 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "qup-core", + "qup-config", + "qup-memory"; + power-domains = <&rpmhpd SA8775P_CX>; + status = "disabled"; + }; + + spi4: spi@990000 { + compatible = "qcom,geni-spi"; + reg = <0x0 0x990000 0x0 0x4000>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = ; + clocks = <&gcc GCC_QUPV3_WRAP0_S4_CLK>; + clock-names = "se"; + interconnects = <&clk_virt MASTER_QUP_CORE_0 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_0 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ALWAYS + &config_noc SLAVE_QUP_0 QCOM_ICC_TAG_ALWAYS>, + <&aggre2_noc MASTER_QUP_0 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "qup-core", + "qup-config", + "qup-memory"; + power-domains = <&rpmhpd SA8775P_CX>; + status = "disabled"; + }; + + i2c5: i2c@994000 { + compatible = "qcom,geni-i2c"; + reg = <0x0 0x994000 0x0 0x4000>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = ; + clocks = <&gcc GCC_QUPV3_WRAP0_S5_CLK>; + clock-names = "se"; + interconnects = <&clk_virt MASTER_QUP_CORE_0 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_0 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ALWAYS + &config_noc SLAVE_QUP_0 QCOM_ICC_TAG_ALWAYS>, + <&aggre2_noc MASTER_QUP_0 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "qup-core", + "qup-config", + "qup-memory"; + power-domains = <&rpmhpd SA8775P_CX>; + status = "disabled"; + }; + + spi5: spi@994000 { + compatible = "qcom,geni-spi"; + reg = <0x0 0x994000 0x0 0x4000>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = ; + clocks = <&gcc GCC_QUPV3_WRAP0_S5_CLK>; + clock-names = "se"; + interconnects = <&clk_virt MASTER_QUP_CORE_0 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_0 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ALWAYS + &config_noc SLAVE_QUP_0 QCOM_ICC_TAG_ALWAYS>, + <&aggre2_noc MASTER_QUP_0 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "qup-core", + "qup-config", + "qup-memory"; + power-domains = <&rpmhpd SA8775P_CX>; + status = "disabled"; + }; + + uart5: serial@994000 { + compatible = "qcom,geni-uart"; + reg = <0x0 0x994000 0x0 0x4000>; + interrupts = ; + clocks = <&gcc GCC_QUPV3_WRAP0_S5_CLK>; + clock-names = "se"; + interconnects = <&clk_virt MASTER_QUP_CORE_0 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_0 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ALWAYS + &config_noc SLAVE_QUP_0 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "qup-core", "qup-config"; + power-domains = <&rpmhpd SA8775P_CX>; + status = "disabled"; + }; + }; + + qupv3_id_1: geniqup@ac0000 { + compatible = "qcom,geni-se-qup"; + reg = <0x0 0x00ac0000 0x0 0x6000>; + #address-cells = <2>; + #size-cells = <2>; + ranges; + clock-names = "m-ahb", "s-ahb"; + clocks = <&gcc GCC_QUPV3_WRAP_1_M_AHB_CLK>, + <&gcc GCC_QUPV3_WRAP_1_S_AHB_CLK>; + iommus = <&apps_smmu 0x443 0x0>; + status = "disabled"; + + i2c7: i2c@a80000 { + compatible = "qcom,geni-i2c"; + reg = <0x0 0xa80000 0x0 0x4000>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = ; + clocks = <&gcc GCC_QUPV3_WRAP1_S0_CLK>; + clock-names = "se"; + interconnects = <&clk_virt MASTER_QUP_CORE_1 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_1 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ALWAYS + &config_noc SLAVE_QUP_1 QCOM_ICC_TAG_ALWAYS>, + <&aggre2_noc MASTER_QUP_1 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "qup-core", + "qup-config", + "qup-memory"; + power-domains = <&rpmhpd SA8775P_CX>; + status = "disabled"; + }; + + spi7: spi@a80000 { + compatible = "qcom,geni-spi"; + reg = <0x0 0xa80000 0x0 0x4000>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = ; + clocks = <&gcc GCC_QUPV3_WRAP1_S0_CLK>; + clock-names = "se"; + interconnects = <&clk_virt MASTER_QUP_CORE_1 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_1 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ALWAYS + &config_noc SLAVE_QUP_1 QCOM_ICC_TAG_ALWAYS>, + <&aggre2_noc MASTER_QUP_1 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "qup-core", + "qup-config", + "qup-memory"; + power-domains = <&rpmhpd SA8775P_CX>; + status = "disabled"; + }; + + i2c8: i2c@a84000 { + compatible = "qcom,geni-i2c"; + reg = <0x0 0xa84000 0x0 0x4000>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = ; + clocks = <&gcc GCC_QUPV3_WRAP1_S1_CLK>; + clock-names = "se"; + interconnects = <&clk_virt MASTER_QUP_CORE_1 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_1 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ALWAYS + &config_noc SLAVE_QUP_1 QCOM_ICC_TAG_ALWAYS>, + <&aggre2_noc MASTER_QUP_1 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "qup-core", + "qup-config", + "qup-memory"; + power-domains = <&rpmhpd SA8775P_CX>; + status = "disabled"; + }; + + spi8: spi@a84000 { + compatible = "qcom,geni-spi"; + reg = <0x0 0xa84000 0x0 0x4000>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = ; + clocks = <&gcc GCC_QUPV3_WRAP1_S1_CLK>; + clock-names = "se"; + interconnects = <&clk_virt MASTER_QUP_CORE_1 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_1 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ALWAYS + &config_noc SLAVE_QUP_1 QCOM_ICC_TAG_ALWAYS>, + <&aggre2_noc MASTER_QUP_1 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "qup-core", + "qup-config", + "qup-memory"; + power-domains = <&rpmhpd SA8775P_CX>; + status = "disabled"; + }; + + i2c9: i2c@a88000 { + compatible = "qcom,geni-i2c"; + reg = <0x0 0xa88000 0x0 0x4000>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = ; + clocks = <&gcc GCC_QUPV3_WRAP1_S2_CLK>; + clock-names = "se"; + interconnects = <&clk_virt MASTER_QUP_CORE_1 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_1 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ALWAYS + &config_noc SLAVE_QUP_1 QCOM_ICC_TAG_ALWAYS>, + <&aggre2_noc MASTER_QUP_1 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "qup-core", + "qup-config", + "qup-memory"; + power-domains = <&rpmhpd SA8775P_CX>; + status = "disabled"; + }; + + spi9: spi@a88000 { + compatible = "qcom,geni-spi"; + reg = <0x0 0xa88000 0x0 0x4000>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = ; + clocks = <&gcc GCC_QUPV3_WRAP1_S2_CLK>; + clock-names = "se"; + interconnects = <&clk_virt MASTER_QUP_CORE_1 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_1 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ALWAYS + &config_noc SLAVE_QUP_1 QCOM_ICC_TAG_ALWAYS>, + <&aggre2_noc MASTER_QUP_1 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "qup-core", + "qup-config", + "qup-memory"; + power-domains = <&rpmhpd SA8775P_CX>; + status = "disabled"; + }; + + uart9: serial@a88000 { + compatible = "qcom,geni-uart"; + reg = <0x0 0xa88000 0x0 0x4000>; + interrupts = ; + clocks = <&gcc GCC_QUPV3_WRAP1_S2_CLK>; + clock-names = "se"; + interconnects = <&clk_virt MASTER_QUP_CORE_1 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_1 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ALWAYS + &config_noc SLAVE_QUP_1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "qup-core", "qup-config"; + power-domains = <&rpmhpd SA8775P_CX>; + status = "disabled"; + }; + + i2c10: i2c@a8c000 { + compatible = "qcom,geni-i2c"; + reg = <0x0 0xa8c000 0x0 0x4000>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = ; + clocks = <&gcc GCC_QUPV3_WRAP1_S3_CLK>; + clock-names = "se"; + interconnects = <&clk_virt MASTER_QUP_CORE_1 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_1 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ALWAYS + &config_noc SLAVE_QUP_1 QCOM_ICC_TAG_ALWAYS>, + <&aggre2_noc MASTER_QUP_1 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "qup-core", + "qup-config", + "qup-memory"; + power-domains = <&rpmhpd SA8775P_CX>; + status = "disabled"; + }; + + spi10: spi@a8c000 { + compatible = "qcom,geni-spi"; + reg = <0x0 0xa8c000 0x0 0x4000>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = ; + clocks = <&gcc GCC_QUPV3_WRAP1_S3_CLK>; + clock-names = "se"; + interconnects = <&clk_virt MASTER_QUP_CORE_1 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_1 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ALWAYS + &config_noc SLAVE_QUP_1 QCOM_ICC_TAG_ALWAYS>, + <&aggre2_noc MASTER_QUP_1 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "qup-core", + "qup-config", + "qup-memory"; + power-domains = <&rpmhpd SA8775P_CX>; + status = "disabled"; + }; + + uart10: serial@a8c000 { + compatible = "qcom,geni-uart"; + reg = <0x0 0x00a8c000 0x0 0x4000>; + interrupts = ; + clock-names = "se"; + clocks = <&gcc GCC_QUPV3_WRAP1_S3_CLK>; + interconnect-names = "qup-core", "qup-config"; + interconnects = <&clk_virt MASTER_QUP_CORE_1 0 + &clk_virt SLAVE_QUP_CORE_1 0>, + <&gem_noc MASTER_APPSS_PROC 0 + &config_noc SLAVE_QUP_1 0>; + power-domains = <&rpmhpd SA8775P_CX>; + operating-points-v2 = <&qup_opp_table_100mhz>; + status = "disabled"; + }; + + i2c11: i2c@a90000 { + compatible = "qcom,geni-i2c"; + reg = <0x0 0xa90000 0x0 0x4000>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = ; + clocks = <&gcc GCC_QUPV3_WRAP1_S4_CLK>; + clock-names = "se"; + interconnects = <&clk_virt MASTER_QUP_CORE_1 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_1 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ALWAYS + &config_noc SLAVE_QUP_1 QCOM_ICC_TAG_ALWAYS>, + <&aggre2_noc MASTER_QUP_1 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "qup-core", + "qup-config", + "qup-memory"; + power-domains = <&rpmhpd SA8775P_CX>; + status = "disabled"; + }; - spi16: spi@888000 { + spi11: spi@a90000 { compatible = "qcom,geni-spi"; - reg = <0x0 0x00888000 0x0 0x4000>; - interrupts = ; - clocks = <&gcc GCC_QUPV3_WRAP2_S2_CLK>; + reg = <0x0 0xa90000 0x0 0x4000>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = ; + clocks = <&gcc GCC_QUPV3_WRAP1_S4_CLK>; clock-names = "se"; - interconnects = <&clk_virt MASTER_QUP_CORE_2 QCOM_ICC_TAG_ALWAYS - &clk_virt SLAVE_QUP_CORE_2 QCOM_ICC_TAG_ALWAYS>, + interconnects = <&clk_virt MASTER_QUP_CORE_1 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_1 QCOM_ICC_TAG_ALWAYS>, <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ALWAYS - &config_noc SLAVE_QUP_2 QCOM_ICC_TAG_ALWAYS>, - <&aggre2_noc MASTER_QUP_2 QCOM_ICC_TAG_ALWAYS + &config_noc SLAVE_QUP_1 QCOM_ICC_TAG_ALWAYS>, + <&aggre2_noc MASTER_QUP_1 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "qup-core", + "qup-config", + "qup-memory"; + power-domains = <&rpmhpd SA8775P_CX>; + status = "disabled"; + }; + + i2c12: i2c@a94000 { + compatible = "qcom,geni-i2c"; + reg = <0x0 0xa94000 0x0 0x4000>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = ; + clocks = <&gcc GCC_QUPV3_WRAP1_S5_CLK>; + clock-names = "se"; + interconnects = <&clk_virt MASTER_QUP_CORE_1 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_1 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ALWAYS + &config_noc SLAVE_QUP_1 QCOM_ICC_TAG_ALWAYS>, + <&aggre2_noc MASTER_QUP_1 QCOM_ICC_TAG_ALWAYS &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; interconnect-names = "qup-core", "qup-config", "qup-memory"; power-domains = <&rpmhpd SA8775P_CX>; + status = "disabled"; + }; + + spi12: spi@a94000 { + compatible = "qcom,geni-spi"; + reg = <0x0 0xa94000 0x0 0x4000>; #address-cells = <1>; #size-cells = <0>; + interrupts = ; + clocks = <&gcc GCC_QUPV3_WRAP1_S5_CLK>; + clock-names = "se"; + interconnects = <&clk_virt MASTER_QUP_CORE_1 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_1 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ALWAYS + &config_noc SLAVE_QUP_1 QCOM_ICC_TAG_ALWAYS>, + <&aggre2_noc MASTER_QUP_1 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "qup-core", + "qup-config", + "qup-memory"; + power-domains = <&rpmhpd SA8775P_CX>; status = "disabled"; }; - uart17: serial@88c000 { + uart12: serial@a94000 { compatible = "qcom,geni-uart"; - reg = <0x0 0x0088c000 0x0 0x4000>; - interrupts = ; - clocks = <&gcc GCC_QUPV3_WRAP2_S3_CLK>; + reg = <0x0 0x00a94000 0x0 0x4000>; + interrupts = ; + clocks = <&gcc GCC_QUPV3_WRAP1_S5_CLK>; clock-names = "se"; - interconnects = <&clk_virt MASTER_QUP_CORE_2 QCOM_ICC_TAG_ALWAYS - &clk_virt SLAVE_QUP_CORE_2 QCOM_ICC_TAG_ALWAYS>, + interconnects = <&clk_virt MASTER_QUP_CORE_1 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_1 QCOM_ICC_TAG_ALWAYS>, <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ALWAYS - &config_noc SLAVE_QUP_2 QCOM_ICC_TAG_ALWAYS>; + &config_noc SLAVE_QUP_1 QCOM_ICC_TAG_ALWAYS>; interconnect-names = "qup-core", "qup-config"; power-domains = <&rpmhpd SA8775P_CX>; status = "disabled"; }; - i2c18: i2c@890000 { + i2c13: i2c@a98000 { compatible = "qcom,geni-i2c"; - reg = <0x0 0x00890000 0x0 0x4000>; - interrupts = ; - clocks = <&gcc GCC_QUPV3_WRAP2_S4_CLK>; + reg = <0x0 0xa98000 0x0 0x4000>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = ; + clocks = <&gcc GCC_QUPV3_WRAP1_S6_CLK>; clock-names = "se"; - interconnects = <&clk_virt MASTER_QUP_CORE_2 QCOM_ICC_TAG_ALWAYS - &clk_virt SLAVE_QUP_CORE_2 QCOM_ICC_TAG_ALWAYS>, + interconnects = <&clk_virt MASTER_QUP_CORE_1 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_1 QCOM_ICC_TAG_ALWAYS>, <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ALWAYS - &config_noc SLAVE_QUP_2 QCOM_ICC_TAG_ALWAYS>, - <&aggre2_noc MASTER_QUP_2 QCOM_ICC_TAG_ALWAYS + &config_noc SLAVE_QUP_1 QCOM_ICC_TAG_ALWAYS>, + <&aggre2_noc MASTER_QUP_1 QCOM_ICC_TAG_ALWAYS &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; interconnect-names = "qup-core", "qup-config", "qup-memory"; power-domains = <&rpmhpd SA8775P_CX>; - #address-cells = <1>; - #size-cells = <0>; status = "disabled"; }; }; - qupv3_id_1: geniqup@ac0000 { + qupv3_id_3: geniqup@bc0000 { compatible = "qcom,geni-se-qup"; - reg = <0x0 0x00ac0000 0x0 0x6000>; + reg = <0x0 0xbc0000 0x0 0x6000>; #address-cells = <2>; #size-cells = <2>; ranges; clock-names = "m-ahb", "s-ahb"; - clocks = <&gcc GCC_QUPV3_WRAP_1_M_AHB_CLK>, - <&gcc GCC_QUPV3_WRAP_1_S_AHB_CLK>; - iommus = <&apps_smmu 0x443 0x0>; + clocks = <&gcc GCC_QUPV3_WRAP_3_M_AHB_CLK>, + <&gcc GCC_QUPV3_WRAP_3_S_AHB_CLK>; + iommus = <&apps_smmu 0x43 0x0>; status = "disabled"; - uart10: serial@a8c000 { - compatible = "qcom,geni-uart"; - reg = <0x0 0x00a8c000 0x0 0x4000>; - interrupts = ; + i2c21: i2c@b80000 { + compatible = "qcom,geni-i2c"; + reg = <0x0 0xb80000 0x0 0x4000>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = ; + clocks = <&gcc GCC_QUPV3_WRAP3_S0_CLK>; clock-names = "se"; - clocks = <&gcc GCC_QUPV3_WRAP1_S3_CLK>; - interconnect-names = "qup-core", "qup-config"; - interconnects = <&clk_virt MASTER_QUP_CORE_1 0 - &clk_virt SLAVE_QUP_CORE_1 0>, - <&gem_noc MASTER_APPSS_PROC 0 - &config_noc SLAVE_QUP_1 0>; + interconnects = <&clk_virt MASTER_QUP_CORE_3 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_3 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ALWAYS + &config_noc SLAVE_QUP_3 QCOM_ICC_TAG_ALWAYS>, + <&aggre1_noc MASTER_QUP_3 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "qup-core", + "qup-config", + "qup-memory"; power-domains = <&rpmhpd SA8775P_CX>; - operating-points-v2 = <&qup_opp_table_100mhz>; status = "disabled"; }; - uart12: serial@a94000 { - compatible = "qcom,geni-uart"; - reg = <0x0 0x00a94000 0x0 0x4000>; - interrupts = ; - clocks = <&gcc GCC_QUPV3_WRAP1_S5_CLK>; + spi21: spi@b80000 { + compatible = "qcom,geni-spi"; + reg = <0x0 0xb80000 0x0 0x4000>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = ; + clocks = <&gcc GCC_QUPV3_WRAP3_S0_CLK>; clock-names = "se"; - interconnects = <&clk_virt MASTER_QUP_CORE_1 QCOM_ICC_TAG_ALWAYS - &clk_virt SLAVE_QUP_CORE_1 QCOM_ICC_TAG_ALWAYS>, - <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ALWAYS - &config_noc SLAVE_QUP_1 QCOM_ICC_TAG_ALWAYS>; - interconnect-names = "qup-core", "qup-config"; + interconnects = <&clk_virt MASTER_QUP_CORE_3 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_3 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ALWAYS + &config_noc SLAVE_QUP_3 QCOM_ICC_TAG_ALWAYS>, + <&aggre1_noc MASTER_QUP_3 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "qup-core", + "qup-config", + "qup-memory"; power-domains = <&rpmhpd SA8775P_CX>; status = "disabled"; }; }; + ufs_mem_hc: ufs@1d84000 { + compatible = "qcom,sa8775p-ufshc", "qcom,ufshc", "jedec,ufs-2.0"; + reg = <0x0 0x01d84000 0x0 0x3000>; + interrupts = ; + phys = <&ufs_mem_phy>; + phy-names = "ufsphy"; + lanes-per-direction = <2>; + #reset-cells = <1>; + resets = <&gcc GCC_UFS_PHY_BCR>; + reset-names = "rst"; + power-domains = <&gcc UFS_PHY_GDSC>; + required-opps = <&rpmhpd_opp_nom>; + iommus = <&apps_smmu 0x100 0x0>; + dma-coherent; + clocks = <&gcc GCC_UFS_PHY_AXI_CLK>, + <&gcc GCC_AGGRE_UFS_PHY_AXI_CLK>, + <&gcc GCC_UFS_PHY_AHB_CLK>, + <&gcc GCC_UFS_PHY_UNIPRO_CORE_CLK>, + <&rpmhcc RPMH_CXO_CLK>, + <&gcc GCC_UFS_PHY_TX_SYMBOL_0_CLK>, + <&gcc GCC_UFS_PHY_RX_SYMBOL_0_CLK>, + <&gcc GCC_UFS_PHY_RX_SYMBOL_1_CLK>; + clock-names = "core_clk", + "bus_aggr_clk", + "iface_clk", + "core_clk_unipro", + "ref_clk", + "tx_lane0_sync_clk", + "rx_lane0_sync_clk", + "rx_lane1_sync_clk"; + freq-table-hz = <75000000 300000000>, + <0 0>, + <0 0>, + <75000000 300000000>, + <0 0>, + <0 0>, + <0 0>, + <0 0>; + status = "disabled"; + }; + + ufs_mem_phy: phy@1d87000 { + compatible = "qcom,sa8775p-qmp-ufs-phy"; + reg = <0x0 0x01d87000 0x0 0xe10>; + /* + * Yes, GCC_EDP_REF_CLKREF_EN is correct in qref. It + * enables the CXO clock to eDP *and* UFS PHY. + */ + clocks = <&rpmhcc RPMH_CXO_CLK>, + <&gcc GCC_UFS_PHY_PHY_AUX_CLK>, + <&gcc GCC_EDP_REF_CLKREF_EN>; + clock-names = "ref", "ref_aux", "qref"; + power-domains = <&gcc UFS_PHY_GDSC>; + resets = <&ufs_mem_hc 0>; + reset-names = "ufsphy"; + #phy-cells = <0>; + status = "disabled"; + }; + + usb_0_hsphy: phy@88e4000 { + compatible = "qcom,sa8775p-usb-hs-phy", + "qcom,usb-snps-hs-5nm-phy"; + reg = <0 0x088e4000 0 0x120>; + clocks = <&rpmhcc RPMH_CXO_CLK>; + clock-names = "ref"; + resets = <&gcc GCC_USB2_PHY_PRIM_BCR>; + + #phy-cells = <0>; + + status = "disabled"; + }; + + usb_0_qmpphy: phy@88e8000 { + compatible = "qcom,sa8775p-qmp-usb3-uni-phy"; + reg = <0 0x088e8000 0 0x2000>; + + clocks = <&gcc GCC_USB3_PRIM_PHY_AUX_CLK>, + <&gcc GCC_USB_CLKREF_EN>, + <&gcc GCC_USB3_PRIM_PHY_COM_AUX_CLK>, + <&gcc GCC_USB3_PRIM_PHY_PIPE_CLK>; + clock-names = "aux", "ref", "com_aux", "pipe"; + + resets = <&gcc GCC_USB3_PHY_PRIM_BCR>, + <&gcc GCC_USB3PHY_PHY_PRIM_BCR>; + reset-names = "phy", "phy_phy"; + + power-domains = <&gcc USB30_PRIM_GDSC>; + + #clock-cells = <0>; + clock-output-names = "usb3_prim_phy_pipe_clk_src"; + + #phy-cells = <0>; + + status = "disabled"; + }; + + usb_0: usb@a6f8800 { + compatible = "qcom,sa8775p-dwc3", "qcom,dwc3"; + reg = <0 0x0a6f8800 0 0x400>; + #address-cells = <2>; + #size-cells = <2>; + ranges; + + clocks = <&gcc GCC_CFG_NOC_USB3_PRIM_AXI_CLK>, + <&gcc GCC_USB30_PRIM_MASTER_CLK>, + <&gcc GCC_AGGRE_USB3_PRIM_AXI_CLK>, + <&gcc GCC_USB30_PRIM_SLEEP_CLK>, + <&gcc GCC_USB30_PRIM_MOCK_UTMI_CLK>; + clock-names = "cfg_noc", "core", "iface", "sleep", "mock_utmi"; + + assigned-clocks = <&gcc GCC_USB30_PRIM_MOCK_UTMI_CLK>, + <&gcc GCC_USB30_PRIM_MASTER_CLK>; + assigned-clock-rates = <19200000>, <200000000>; + + interrupts-extended = <&intc GIC_SPI 287 IRQ_TYPE_LEVEL_HIGH>, + <&pdc 14 IRQ_TYPE_EDGE_RISING>, + <&pdc 15 IRQ_TYPE_EDGE_RISING>, + <&pdc 12 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "pwr_event", + "dp_hs_phy_irq", + "dm_hs_phy_irq", + "ss_phy_irq"; + + power-domains = <&gcc USB30_PRIM_GDSC>; + required-opps = <&rpmhpd_opp_nom>; + + resets = <&gcc GCC_USB30_PRIM_BCR>; + + interconnects = <&aggre1_noc MASTER_USB3_0 0 &mc_virt SLAVE_EBI1 0>, + <&gem_noc MASTER_APPSS_PROC 0 &config_noc SLAVE_USB3_0 0>; + interconnect-names = "usb-ddr", "apps-usb"; + + wakeup-source; + + status = "disabled"; + + usb_0_dwc3: usb@a600000 { + compatible = "snps,dwc3"; + reg = <0 0x0a600000 0 0xe000>; + interrupts = ; + iommus = <&apps_smmu 0x080 0x0>; + phys = <&usb_0_hsphy>, <&usb_0_qmpphy>; + phy-names = "usb2-phy", "usb3-phy"; + }; + }; + + usb_1_hsphy: phy@88e6000 { + compatible = "qcom,sa8775p-usb-hs-phy", + "qcom,usb-snps-hs-5nm-phy"; + reg = <0 0x088e6000 0 0x120>; + clocks = <&gcc GCC_USB_CLKREF_EN>; + clock-names = "ref"; + resets = <&gcc GCC_USB2_PHY_SEC_BCR>; + + #phy-cells = <0>; + + status = "disabled"; + }; + + usb_1_qmpphy: phy@88ea000 { + compatible = "qcom,sa8775p-qmp-usb3-uni-phy"; + reg = <0 0x088ea000 0 0x2000>; + + clocks = <&gcc GCC_USB3_SEC_PHY_AUX_CLK>, + <&gcc GCC_USB_CLKREF_EN>, + <&gcc GCC_USB3_SEC_PHY_COM_AUX_CLK>, + <&gcc GCC_USB3_SEC_PHY_PIPE_CLK>; + clock-names = "aux", "ref", "com_aux", "pipe"; + + resets = <&gcc GCC_USB3_PHY_SEC_BCR>, + <&gcc GCC_USB3PHY_PHY_SEC_BCR>; + reset-names = "phy", "phy_phy"; + + power-domains = <&gcc USB30_SEC_GDSC>; + + #clock-cells = <0>; + clock-output-names = "usb3_sec_phy_pipe_clk_src"; + + #phy-cells = <0>; + + status = "disabled"; + }; + + usb_1: usb@a8f8800 { + compatible = "qcom,sa8775p-dwc3", "qcom,dwc3"; + reg = <0 0x0a8f8800 0 0x400>; + #address-cells = <2>; + #size-cells = <2>; + ranges; + + clocks = <&gcc GCC_CFG_NOC_USB3_SEC_AXI_CLK>, + <&gcc GCC_USB30_SEC_MASTER_CLK>, + <&gcc GCC_AGGRE_USB3_SEC_AXI_CLK>, + <&gcc GCC_USB30_SEC_SLEEP_CLK>, + <&gcc GCC_USB30_SEC_MOCK_UTMI_CLK>; + clock-names = "cfg_noc", "core", "iface", "sleep", "mock_utmi"; + + assigned-clocks = <&gcc GCC_USB30_SEC_MOCK_UTMI_CLK>, + <&gcc GCC_USB30_SEC_MASTER_CLK>; + assigned-clock-rates = <19200000>, <200000000>; + + interrupts-extended = <&intc GIC_SPI 352 IRQ_TYPE_LEVEL_HIGH>, + <&pdc 8 IRQ_TYPE_EDGE_RISING>, + <&pdc 7 IRQ_TYPE_EDGE_RISING>, + <&pdc 13 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "pwr_event", + "dp_hs_phy_irq", + "dm_hs_phy_irq", + "ss_phy_irq"; + + power-domains = <&gcc USB30_SEC_GDSC>; + required-opps = <&rpmhpd_opp_nom>; + + resets = <&gcc GCC_USB30_SEC_BCR>; + + interconnects = <&aggre1_noc MASTER_USB3_1 0 &mc_virt SLAVE_EBI1 0>, + <&gem_noc MASTER_APPSS_PROC 0 &config_noc SLAVE_USB3_1 0>; + interconnect-names = "usb-ddr", "apps-usb"; + + wakeup-source; + + status = "disabled"; + + usb_1_dwc3: usb@a800000 { + compatible = "snps,dwc3"; + reg = <0 0x0a800000 0 0xe000>; + interrupts = ; + iommus = <&apps_smmu 0x0a0 0x0>; + phys = <&usb_1_hsphy>, <&usb_1_qmpphy>; + phy-names = "usb2-phy", "usb3-phy"; + }; + }; + + usb_2_hsphy: phy@88e7000 { + compatible = "qcom,sa8775p-usb-hs-phy", + "qcom,usb-snps-hs-5nm-phy"; + reg = <0 0x088e7000 0 0x120>; + clocks = <&gcc GCC_USB_CLKREF_EN>; + clock-names = "ref"; + resets = <&gcc GCC_USB3_PHY_TERT_BCR>; + + #phy-cells = <0>; + + status = "disabled"; + }; + + usb_2: usb@a4f8800 { + compatible = "qcom,sa8775p-dwc3", "qcom,dwc3"; + reg = <0 0x0a4f8800 0 0x400>; + #address-cells = <2>; + #size-cells = <2>; + ranges; + + clocks = <&gcc GCC_CFG_NOC_USB2_PRIM_AXI_CLK>, + <&gcc GCC_USB20_MASTER_CLK>, + <&gcc GCC_AGGRE_USB2_PRIM_AXI_CLK>, + <&gcc GCC_USB20_SLEEP_CLK>, + <&gcc GCC_USB20_MOCK_UTMI_CLK>; + clock-names = "cfg_noc", "core", "iface", "sleep", "mock_utmi"; + + assigned-clocks = <&gcc GCC_USB20_MOCK_UTMI_CLK>, + <&gcc GCC_USB20_MASTER_CLK>; + assigned-clock-rates = <19200000>, <200000000>; + + interrupts-extended = <&intc GIC_SPI 444 IRQ_TYPE_LEVEL_HIGH>, + <&pdc 10 IRQ_TYPE_EDGE_RISING>, + <&pdc 9 IRQ_TYPE_EDGE_RISING>; + interrupt-names = "pwr_event", + "dp_hs_phy_irq", + "dm_hs_phy_irq"; + + power-domains = <&gcc USB20_PRIM_GDSC>; + required-opps = <&rpmhpd_opp_nom>; + + resets = <&gcc GCC_USB20_PRIM_BCR>; + + interconnects = <&aggre1_noc MASTER_USB2 0 &mc_virt SLAVE_EBI1 0>, + <&gem_noc MASTER_APPSS_PROC 0 &config_noc SLAVE_USB2 0>; + interconnect-names = "usb-ddr", "apps-usb"; + + wakeup-source; + + status = "disabled"; + + usb_2_dwc3: usb@a400000 { + compatible = "snps,dwc3"; + reg = <0 0x0a400000 0 0xe000>; + interrupts = ; + iommus = <&apps_smmu 0x020 0x0>; + phys = <&usb_2_hsphy>; + phy-names = "usb2-phy"; + }; + }; + tcsr_mutex: hwlock@1f40000 { compatible = "qcom,tcsr-mutex"; reg = <0x0 0x01f40000 0x0 0x20000>; #hwlock-cells = <1>; }; + gpucc: clock-controller@3d90000 { + compatible = "qcom,sa8775p-gpucc"; + reg = <0x0 0x03d90000 0x0 0xa000>; + clocks = <&rpmhcc RPMH_CXO_CLK>, + <&gcc GCC_GPU_GPLL0_CLK_SRC>, + <&gcc GCC_GPU_GPLL0_DIV_CLK_SRC>; + clock-names = "bi_tcxo", + "gcc_gpu_gpll0_clk_src", + "gcc_gpu_gpll0_div_clk_src"; + #clock-cells = <1>; + #reset-cells = <1>; + #power-domain-cells = <1>; + }; + + adreno_smmu: iommu@3da0000 { + compatible = "qcom,sa8775p-smmu-500", "qcom,adreno-smmu", + "qcom,smmu-500", "arm,mmu-500"; + reg = <0x0 0x03da0000 0x0 0x20000>; + #iommu-cells = <2>; + #global-interrupts = <2>; + dma-coherent; + power-domains = <&gpucc GPU_CC_CX_GDSC>; + clocks = <&gcc GCC_GPU_MEMNOC_GFX_CLK>, + <&gcc GCC_GPU_SNOC_DVM_GFX_CLK>, + <&gpucc GPU_CC_AHB_CLK>, + <&gpucc GPU_CC_HLOS1_VOTE_GPU_SMMU_CLK>, + <&gpucc GPU_CC_CX_GMU_CLK>, + <&gpucc GPU_CC_HUB_CX_INT_CLK>, + <&gpucc GPU_CC_HUB_AON_CLK>; + clock-names = "gcc_gpu_memnoc_gfx_clk", + "gcc_gpu_snoc_dvm_gfx_clk", + "gpu_cc_ahb_clk", + "gpu_cc_hlos1_vote_gpu_smmu_clk", + "gpu_cc_cx_gmu_clk", + "gpu_cc_hub_cx_int_clk", + "gpu_cc_hub_aon_clk"; + interrupts = , + , + , + , + , + , + , + , + , + , + , + ; + }; + pdc: interrupt-controller@b220000 { compatible = "qcom,sa8775p-pdc", "qcom,pdc"; reg = <0x0 0x0b220000 0x0 0x30000>, @@ -658,6 +1884,16 @@ interrupt-controller; }; + aoss_qmp: power-management@c300000 { + compatible = "qcom,sa8775p-aoss-qmp", "qcom,aoss-qmp"; + reg = <0x0 0x0c300000 0x0 0x400>; + interrupts-extended = <&ipcc IPCC_CLIENT_AOP + IPCC_MPROC_SIGNAL_GLINK_QMP + IRQ_TYPE_EDGE_RISING>; + mboxes = <&ipcc IPCC_CLIENT_AOP IPCC_MPROC_SIGNAL_GLINK_QMP>; + #clock-cells = <0>; + }; + spmi_bus: spmi@c440000 { compatible = "qcom,spmi-pmic-arb"; reg = <0x0 0x0c440000 0x0 0x1100>, @@ -829,6 +2065,80 @@ ; }; + pcie_smmu: iommu@15200000 { + compatible = "qcom,sa8775p-smmu-500", "qcom,smmu-500", "arm,mmu-500"; + reg = <0x0 0x15200000 0x0 0x80000>; + #iommu-cells = <2>; + #global-interrupts = <2>; + + interrupts = , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + ; + }; + intc: interrupt-controller@17a00000 { compatible = "arm,gic-v3"; reg = <0x0 0x17a00000 0x0 0x10000>, /* GICD */ @@ -840,6 +2150,13 @@ redistributor-stride = <0x0 0x20000>; }; + watchdog@17c10000 { + compatible = "qcom,apss-wdt-sa8775p", "qcom,kpss-wdt"; + reg = <0x0 0x17c10000 0x0 0x1000>; + clocks = <&sleep_clk>; + interrupts = ; + }; + memtimer: timer@17c20000 { compatible = "arm,armv7-timer-mem"; reg = <0x0 0x17c20000 0x0 0x1000>; diff --git a/arch/arm64/boot/dts/qcom/sc7180-acer-aspire1.dts b/arch/arm64/boot/dts/qcom/sc7180-acer-aspire1.dts new file mode 100644 index 0000000000000000000000000000000000000000..b637b4270f889b8815941551aa50143d6caea6b6 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/sc7180-acer-aspire1.dts @@ -0,0 +1,845 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/dts-v1/; + +#include +#include + +#include "sc7180.dtsi" + +#include "pm6150.dtsi" +#include "pm6150l.dtsi" + +/delete-node/ &tz_mem; +/delete-node/ &ipa_fw_mem; + +/ { + model = "Acer Aspire 1"; + compatible = "acer,aspire1", "qcom,sc7180"; + chassis-type = "laptop"; + + aliases { + bluetooth0 = &bluetooth; + hsuart0 = &uart3; + serial0 = &uart8; + wifi0 = &wifi; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + reserved-memory { + zap_mem: zap-shader@80840000 { + reg = <0x0 0x80840000 0 0x2000>; + no-map; + }; + + venus_mem: venus@85b00000 { + reg = <0x0 0x85b00000 0 0x500000>; + no-map; + }; + + mpss_mem: mpss@86000000 { + reg = <0x0 0x86000000 0x0 0x2000000>; + no-map; + }; + + adsp_mem: adsp@8e400000 { + reg = <0x0 0x8e400000 0x0 0x2800000>; + no-map; + }; + + wlan_mem: wlan@93900000 { + reg = <0x0 0x93900000 0x0 0x200000>; + no-map; + }; + }; + + max98357a: audio-codec { + compatible = "maxim,max98357a"; + sdmode-gpios = <&tlmm 23 GPIO_ACTIVE_HIGH>; + + pinctrl-0 = <&_sd_mode_default>; + pinctrl-names = "default"; + + #sound-dai-cells = <0>; + }; + + backlight: backlight { + compatible = "pwm-backlight"; + pwms = <&sn65dsi86_bridge 1000000>; + enable-gpios = <&tlmm 10 GPIO_ACTIVE_HIGH>; + + pinctrl-0 = <&soc_bkoff_default>; + pinctrl-names = "default"; + }; + + reg_brij_1p2: bridge-1p2-regulator { + compatible = "regulator-fixed"; + regulator-name = "brij_1p2"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + + gpio = <&tlmm 19 GPIO_ACTIVE_HIGH>; + enable-active-high; + + pinctrl-0 = <®_edp_1p2_en_default>; + pinctrl-names = "default"; + }; + + reg_brij_1p8: bridge-regulator { + compatible = "regulator-fixed"; + regulator-name = "brij_1p8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + + vin-supply = <&vreg_l8c_1p8>; + + gpio = <&tlmm 20 GPIO_ACTIVE_HIGH>; + enable-active-high; + + pinctrl-0 = <®_edp_1p8_en_default>; + pinctrl-names = "default"; + }; + + reg_codec_3p3: codec-regulator { + compatible = "regulator-fixed"; + regulator-name = "codec_3p3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + + gpio = <&tlmm 83 GPIO_ACTIVE_HIGH>; + enable-active-high; + + pinctrl-0 = <®_audio_en_default>; + pinctrl-names = "default"; + }; + + reg_lcm_3p3: panel-regulator { + compatible = "regulator-fixed"; + regulator-name = "lcm_3p3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + + gpio = <&tlmm 26 GPIO_ACTIVE_HIGH>; + enable-active-high; + + pinctrl-0 = <®_lcm_en_default>; + pinctrl-names = "default"; + }; + + reg_tp_3p3: touchpad-regulator { + compatible = "regulator-fixed"; + regulator-name = "tp_3p3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + + gpio = <&tlmm 25 GPIO_ACTIVE_HIGH>; + enable-active-high; + + pinctrl-0 = <®_tp_en_default>; + pinctrl-names = "default"; + }; +}; + +&i2c2 { + clock-frequency = <400000>; + status = "okay"; + + /* embedded-controller@76 */ +}; + +&i2c4 { + clock-frequency = <400000>; + status = "okay"; + + /* + * NOTE: DSDT defines two possible touchpads, other one is + * + * reg = <0x15>; + * hid-descr-addr = <0x1>; + */ + + touchpad@2c { + compatible = "hid-over-i2c"; + reg = <0x2c>; + hid-descr-addr = <0x20>; + + vdd-supply = <®_tp_3p3>; + + interrupts-extended = <&tlmm 94 IRQ_TYPE_LEVEL_LOW>; + + pinctrl-0 = <&hid_touchpad_default>; + pinctrl-names = "default"; + + wakeup-source; + }; + + keyboard@3a { + compatible = "hid-over-i2c"; + reg = <0x3a>; + hid-descr-addr = <0x1>; + + interrupts-extended = <&tlmm 33 IRQ_TYPE_LEVEL_LOW>; + + pinctrl-0 = <&hid_keyboard_default>; + pinctrl-names = "default"; + + wakeup-source; + }; +}; + +&i2c9 { + clock-frequency = <400000>; + status = "okay"; + + alc5682: codec@1a { + compatible = "realtek,rt5682i"; + reg = <0x1a>; + + #sound-dai-cells = <1>; + + interrupt-parent = <&tlmm>; + interrupts = <28 IRQ_TYPE_EDGE_BOTH>; + + pinctrl-0 = <&codec_irq_default>; + pinctrl-names = "default"; + + AVDD-supply = <&vreg_l15a_1p8>; + MICVDD-supply = <®_codec_3p3>; + VBAT-supply = <®_codec_3p3>; + + realtek,dmic1-data-pin = <1>; + realtek,dmic1-clk-pin = <1>; + realtek,jd-src = <1>; + }; +}; + +&i2c10 { + clock-frequency = <400000>; + status = "okay"; + + sn65dsi86_bridge: bridge@2c { + compatible = "ti,sn65dsi86"; + reg = <0x2c>; + gpio-controller; + #gpio-cells = <2>; + #pwm-cells = <1>; + + interrupt-parent = <&tlmm>; + interrupts = <11 IRQ_TYPE_LEVEL_HIGH>; + + enable-gpios = <&tlmm 51 GPIO_ACTIVE_HIGH>; + suspend-gpios = <&tlmm 22 GPIO_ACTIVE_LOW>; + + pinctrl-0 = <&bridge_en_default>, + <&edp_bridge_irq_default>, + <&bridge_suspend_default>; + pinctrl-names = "default"; + + vpll-supply = <®_brij_1p8>; + vccio-supply = <®_brij_1p8>; + vcca-supply = <®_brij_1p2>; + vcc-supply = <®_brij_1p2>; + + clocks = <&rpmhcc RPMH_LN_BB_CLK3>; + clock-names = "refclk"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + sn65dsi86_in: endpoint { + remote-endpoint = <&mdss_dsi0_out>; + }; + }; + + port@1 { + reg = <1>; + + sn65dsi86_out: endpoint { + data-lanes = <0 1>; + remote-endpoint = <&panel_in_edp>; + }; + }; + }; + + aux-bus { + panel: panel { + compatible = "edp-panel"; + power-supply = <®_lcm_3p3>; + backlight = <&backlight>; + hpd-absent-delay-ms = <200>; + + port { + panel_in_edp: endpoint { + remote-endpoint = <&sn65dsi86_out>; + }; + }; + }; + }; + }; +}; + +&gpu { + status = "okay"; + + zap-shader { + memory-region = <&zap_mem>; + firmware-name = "qcom/sc7180/acer/aspire1/qcdxkmsuc7180.mbn"; + }; +}; + +&mdss { + status = "okay"; +}; + +&mdss_dsi0 { + vdda-supply = <&vreg_l3c_1p2>; + status = "okay"; +}; + +&mdss_dsi0_out { + remote-endpoint = <&sn65dsi86_in>; + data-lanes = <0 1 2 3>; +}; + +&mdss_dsi0_phy { + vdds-supply = <&vreg_l4a_0p8>; + status = "okay"; +}; + +&pm6150_adc { + thermistor@4e { + reg = ; + qcom,ratiometric; + qcom,hw-settle-time = <200>; + }; + + charger-thermistor@4f { + reg = ; + qcom,ratiometric; + qcom,hw-settle-time = <200>; + }; +}; + +&pm6150_adc_tm { + status = "okay"; + + charger-thermistor@0 { + reg = <0>; + io-channels = <&pm6150_adc ADC5_AMUX_THM3_100K_PU>; + qcom,ratiometric; + qcom,hw-settle-time-us = <200>; + }; + + thermistor@1 { + reg = <1>; + io-channels = <&pm6150_adc ADC5_AMUX_THM2_100K_PU>; + qcom,ratiometric; + qcom,hw-settle-time-us = <200>; + }; +}; + +&pm6150_pon { + status = "disabled"; +}; + +&qupv3_id_0 { + status = "okay"; +}; + +&qupv3_id_1 { + status = "okay"; +}; + +&remoteproc_mpss { + firmware-name = "qcom/sc7180/acer/aspire1/qcmpss7180_nm.mbn"; + status = "okay"; +}; + +&sdhc_1 { + pinctrl-0 = <&sdc1_default>; + pinctrl-1 = <&sdc1_sleep>; + pinctrl-names = "default", "sleep"; + vmmc-supply = <&vreg_l19a_2p9>; + vqmmc-supply = <&vreg_l12a_1p8>; + + status = "okay"; +}; + +&uart3 { + /delete-property/interrupts; + interrupts-extended = <&intc GIC_SPI 604 IRQ_TYPE_LEVEL_HIGH>, + <&tlmm 41 IRQ_TYPE_EDGE_FALLING>; + + pinctrl-1 = <&qup_uart3_sleep>; + pinctrl-names = "default", "sleep"; + + status = "okay"; + + bluetooth: bluetooth { + compatible = "qcom,wcn3991-bt"; + vddio-supply = <&vreg_l10a_1p8>; + vddxo-supply = <&vreg_l1c_1p8>; + vddrf-supply = <&vreg_l2c_1p3>; + vddch0-supply = <&vreg_l10c_3p3>; + max-speed = <3200000>; + }; +}; + +&uart8 { + status = "okay"; +}; + +&usb_1 { + status = "okay"; +}; + +&usb_1_dwc3 { + dr_mode = "host"; + #address-cells = <1>; + #size-cells = <0>; + + usb_hub_2_x: hub@1 { + compatible = "usbbda,5411"; + reg = <1>; + peer-hub = <&usb_hub_3_x>; + }; + + usb_hub_3_x: hub@2 { + compatible = "usbbda,411"; + reg = <2>; + peer-hub = <&usb_hub_2_x>; + }; +}; + +&usb_1_hsphy { + vdd-supply = <&vreg_l4a_0p8>; + vdda-pll-supply = <&vreg_l11a_1p8>; + vdda-phy-dpdm-supply = <&vreg_l17a_3p0>; + qcom,imp-res-offset-value = <8>; + qcom,preemphasis-level = ; + qcom,preemphasis-width = ; + qcom,bias-ctrl-value = <0x22>; + qcom,charge-ctrl-value = <3>; + qcom,hsdisc-trim-value = <0>; + + status = "okay"; +}; + +&usb_1_qmpphy { + vdda-phy-supply = <&vreg_l3c_1p2>; + vdda-pll-supply = <&vreg_l4a_0p8>; + + status = "okay"; +}; + +&venus { + firmware-name = "qcom/sc7180/acer/aspire1/qcvss7180.mbn"; +}; + +&wifi { + vdd-0.8-cx-mx-supply = <&vreg_l9a_0p6>; + vdd-1.8-xo-supply = <&vreg_l1c_1p8>; + vdd-1.3-rfa-supply = <&vreg_l2c_1p3>; + vdd-3.3-ch0-supply = <&vreg_l10c_3p3>; + vdd-3.3-ch1-supply = <&vreg_l11c_3p3>; + + status = "okay"; +}; + +&apps_rsc { + regulators-0 { + compatible = "qcom,pm6150-rpmh-regulators"; + qcom,pmic-id = "a"; + + vreg_s1a_1p1: smps1 { + regulator-min-microvolt = <1128000>; + regulator-max-microvolt = <1128000>; + }; + + vreg_l4a_0p8: ldo4 { + regulator-min-microvolt = <824000>; + regulator-max-microvolt = <928000>; + regulator-initial-mode = ; + }; + + vreg_l9a_0p6: ldo9 { + regulator-min-microvolt = <488000>; + regulator-max-microvolt = <800000>; + regulator-initial-mode = ; + }; + + vreg_l10a_1p8: ldo10 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-initial-mode = ; + regulator-always-on; + regulator-boot-on; + }; + + vreg_l11a_1p8: ldo11 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-initial-mode = ; + }; + + vreg_l12a_1p8: ldo12 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-initial-mode = ; + }; + + vreg_l13a_1p8: ldo13 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-initial-mode = ; + }; + + vreg_l14a_1p8: ldo14 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-initial-mode = ; + }; + + vreg_l15a_1p8: ldo15 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-initial-mode = ; + }; + + vreg_l16a_2p7: ldo16 { + regulator-min-microvolt = <2496000>; + regulator-max-microvolt = <3304000>; + regulator-initial-mode = ; + }; + + vreg_l17a_3p0: ldo17 { + regulator-min-microvolt = <2920000>; + regulator-max-microvolt = <3232000>; + regulator-initial-mode = ; + }; + + vreg_l18a_2p8: ldo18 { + regulator-min-microvolt = <2496000>; + regulator-max-microvolt = <3304000>; + regulator-initial-mode = ; + }; + + vreg_l19a_2p9: ldo19 { + regulator-min-microvolt = <2960000>; + regulator-max-microvolt = <2960000>; + regulator-initial-mode = ; + }; + }; + + regulators-1 { + compatible = "qcom,pm6150l-rpmh-regulators"; + qcom,pmic-id = "c"; + + vreg_s8c_1p3: smps8 { + regulator-min-microvolt = <1120000>; + regulator-max-microvolt = <1408000>; + }; + + vreg_l1c_1p8: ldo1 { + regulator-min-microvolt = <1616000>; + regulator-max-microvolt = <1984000>; + regulator-initial-mode = ; + }; + + vreg_l2c_1p3: ldo2 { + regulator-min-microvolt = <1168000>; + regulator-max-microvolt = <1304000>; + regulator-initial-mode = ; + }; + + vreg_l3c_1p2: ldo3 { + regulator-min-microvolt = <1144000>; + regulator-max-microvolt = <1304000>; + regulator-initial-mode = ; + }; + + vreg_l4c_1p8: ldo4 { + regulator-min-microvolt = <1648000>; + regulator-max-microvolt = <3304000>; + regulator-initial-mode = ; + }; + + vreg_l5c_1p8: ldo5 { + regulator-min-microvolt = <1648000>; + regulator-max-microvolt = <3304000>; + regulator-initial-mode = ; + }; + + vreg_l6c_2p9: ldo6 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <2950000>; + regulator-initial-mode = ; + }; + + vreg_l7c_3p0: ldo7 { + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3312000>; + regulator-initial-mode = ; + }; + + vreg_l8c_1p8: ldo8 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-initial-mode = ; + }; + + vreg_l9c_2p9: ldo9 { + regulator-min-microvolt = <2952000>; + regulator-max-microvolt = <2952000>; + regulator-initial-mode = ; + }; + + vreg_l10c_3p3: ldo10 { + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3400000>; + regulator-initial-mode = ; + }; + + vreg_l11c_3p3: ldo11 { + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3400000>; + regulator-initial-mode = ; + }; + + vreg_bob: bob { + regulator-min-microvolt = <3008000>; + regulator-max-microvolt = <3960000>; + regulator-initial-mode = ; + }; + }; +}; + +&qup_i2c2_default { + drive-strength = <2>; + + /* Has external pullup */ + bias-disable; +}; + +&qup_i2c4_default { + drive-strength = <2>; + + /* Has external pullup */ + bias-disable; +}; + +&qup_i2c9_default { + drive-strength = <2>; + + /* Has external pullup */ + bias-disable; +}; + +&qup_i2c10_default { + drive-strength = <2>; + + /* Has external pullup */ + bias-disable; +}; + +&tlmm { + /* + * The TZ seem to protect those because some boards can have + * fingerprint sensor connected to this range. Not connected + * on this board + */ + gpio-reserved-ranges = <58 5>; + + amp_sd_mode_default: amp-sd-mode-deault-state { + pins = "gpio23"; + function = "gpio"; + drive-strength = <16>; + bias-disable; + }; + + bridge_en_default: bridge-en-default-state { + pins = "gpio51"; + function = "gpio"; + drive-strength = <16>; + bias-disable; + }; + + bridge_suspend_default: bridge-suspend-default-state { + pins = "gpio22"; + function = "gpio"; + drive-strength = <16>; + bias-pull-up; + }; + + codec_irq_default: codec-irq-deault-state { + pins = "gpio28"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + + edp_bridge_irq_default: edp-bridge-irq-default-state { + pins = "gpio11"; + function = "gpio"; + drive-strength = <2>; + bias-pull-down; + }; + + hid_keyboard_default: hid-keyboard-default-state { + pins = "gpio33"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + + hid_touchpad_default: hid-touchpad-default-state { + pins = "gpio94"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + + qup_uart3_sleep: qup-uart3-sleep-state { + cts-pins { + /* + * Configure a pull-down on CTS to match the pull of + * the Bluetooth module. + */ + pins = "gpio38"; + function = "gpio"; + bias-pull-down; + }; + + rts-pins { + /* + * Configure pull-down on RTS. As RTS is active low + * signal, pull it low to indicate the BT SoC that it + * can wakeup the system anytime from suspend state by + * pulling RX low (by sending wakeup bytes). + */ + pins = "gpio39"; + function = "gpio"; + bias-pull-down; + }; + + tx-pins { + /* + * Configure pull-up on TX when it isn't actively driven + * to prevent BT SoC from receiving garbage during sleep. + */ + pins = "gpio40"; + function = "gpio"; + bias-pull-up; + }; + + rx-pins { + /* + * Configure a pull-up on RX. This is needed to avoid + * garbage data when the TX pin of the Bluetooth module + * is floating which may cause spurious wakeups. + */ + pins = "gpio41"; + function = "gpio"; + bias-pull-up; + }; + }; + + reg_edp_1p2_en_default: reg-edp-1p2-en-deault-state { + pins = "gpio19"; + function = "gpio"; + drive-strength = <16>; + bias-disable; + }; + + reg_edp_1p8_en_default: reg-edp-1p8-en-deault-state { + pins = "gpio20"; + function = "gpio"; + drive-strength = <16>; + bias-disable; + }; + + reg_lcm_en_default: reg-lcm-en-deault-state { + pins = "gpio26"; + function = "gpio"; + drive-strength = <16>; + bias-disable; + }; + + reg_audio_en_default: reg-audio-en-deault-state { + pins = "gpio83"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + + reg_tp_en_default: reg-tp-en-deault-state { + pins = "gpio25"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + + soc_bkoff_default: soc-bkoff-deault-state { + pins = "gpio10"; + function = "gpio"; + drive-strength = <16>; + bias-disable; + }; + + sdc1_default: sdc1-default-state { + clk-pins { + pins = "sdc1_clk"; + drive-strength = <16>; + bias-disable; + }; + + cmd-pins { + pins = "sdc1_cmd"; + drive-strength = <16>; + bias-pull-up; + }; + + data-pins { + pins = "sdc1_data"; + drive-strength = <16>; + bias-pull-up; + }; + + rclk-pins { + pins = "sdc1_rclk"; + bias-pull-down; + }; + }; + + sdc1_sleep: sdc1-sleep-state { + clk-pins { + pins = "sdc1_clk"; + drive-strength = <2>; + bias-disable; + }; + + cmd-pins { + pins = "sdc1_cmd"; + drive-strength = <2>; + bias-pull-up; + }; + + data-pins { + pins = "sdc1_data"; + drive-strength = <2>; + bias-pull-up; + }; + + rclk-pins { + pins = "sdc1_rclk"; + bias-pull-down; + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/sc7180-idp.dts b/arch/arm64/boot/dts/qcom/sc7180-idp.dts index 9f052270e0908c8e48b8c724edded66fb663f323..a1c50be4ad9554d71c1ab7f717782fe2beb0e247 100644 --- a/arch/arm64/boot/dts/qcom/sc7180-idp.dts +++ b/arch/arm64/boot/dts/qcom/sc7180-idp.dts @@ -295,7 +295,11 @@ }; }; -&dsi0 { +&mdss { + status = "okay"; +}; + +&mdss_dsi0 { status = "okay"; vdda-supply = <&vreg_l3c_1p2>; @@ -314,7 +318,7 @@ port { panel0_in: endpoint { - remote-endpoint = <&dsi0_out>; + remote-endpoint = <&mdss_dsi0_out>; }; }; }; @@ -329,19 +333,11 @@ }; }; -&dsi_phy { +&mdss_dsi0_phy { status = "okay"; vdds-supply = <&vreg_l4a_0p8>; }; -&mdp { - status = "okay"; -}; - -&mdss { - status = "okay"; -}; - &qfprom { vcc-supply = <&vreg_l11a_1p8>; }; @@ -393,6 +389,11 @@ qcom,spare-regs = <&tcsr_regs_2 0xb3e4>; }; +&scm { + /* TF-A firmware maps memory cached so mark dma-coherent to match. */ + dma-coherent; +}; + &sdhc_1 { status = "okay"; diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor-parade-ps8640.dtsi b/arch/arm64/boot/dts/qcom/sc7180-trogdor-parade-ps8640.dtsi index 5aa7949b532806b33c22af9c0d7b530464111398..bede23369fedec7daae7bb163a7f688ef9d9169a 100644 --- a/arch/arm64/boot/dts/qcom/sc7180-trogdor-parade-ps8640.dtsi +++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor-parade-ps8640.dtsi @@ -46,10 +46,6 @@ /* ADDITIONS TO NODES DEFINED IN PARENT DEVICE TREE FILES */ -&dsi0_out { - remote-endpoint = <&ps8640_in>; -}; - edp_brij_i2c: &i2c2 { status = "okay"; clock-frequency = <400000>; @@ -74,7 +70,7 @@ edp_brij_i2c: &i2c2 { port@0 { reg = <0>; ps8640_in: endpoint { - remote-endpoint = <&dsi0_out>; + remote-endpoint = <&mdss_dsi0_out>; }; }; @@ -102,6 +98,10 @@ edp_brij_i2c: &i2c2 { }; }; +&mdss_dsi0_out { + remote-endpoint = <&ps8640_in>; +}; + &tlmm { edp_brij_ps8640_rst: edp-brij-ps8640-rst-state { pins = "gpio11"; diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor-quackingstick-r0.dts b/arch/arm64/boot/dts/qcom/sc7180-trogdor-quackingstick-r0.dts index 5c81e44ed4a5aa6d06c9aadce58e973373a65e2a..0a7f2286b541897dcc8eb221222318eb5e0d0829 100644 --- a/arch/arm64/boot/dts/qcom/sc7180-trogdor-quackingstick-r0.dts +++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor-quackingstick-r0.dts @@ -15,7 +15,7 @@ compatible = "google,quackingstick-sku1537", "qcom,sc7180"; }; -&dsi_phy { +&mdss_dsi0_phy { qcom,phy-rescode-offset-top = /bits/ 8 <(-13) (-13) (-13) (-13) (-13)>; qcom,phy-rescode-offset-bot = /bits/ 8 <(-13) (-13) (-13) (-13) (-13)>; qcom,phy-drive-ldo-level = <375>; diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor-quackingstick.dtsi b/arch/arm64/boot/dts/qcom/sc7180-trogdor-quackingstick.dtsi index 8e7b42f843d459dd6fb67d667319cc12a33df1c1..62ab6427dd65d6523d2a33d34798f0e67da7cda7 100644 --- a/arch/arm64/boot/dts/qcom/sc7180-trogdor-quackingstick.dtsi +++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor-quackingstick.dtsi @@ -52,7 +52,31 @@ }; }; -&dsi0 { +&gpio_keys { + status = "okay"; +}; + +&i2c4 { + status = "okay"; + clock-frequency = <400000>; + + ap_ts: touchscreen@10 { + compatible = "hid-over-i2c"; + reg = <0x10>; + pinctrl-names = "default"; + pinctrl-0 = <&ts_int_l>, <&ts_reset_l>; + + interrupt-parent = <&tlmm>; + interrupts = <9 IRQ_TYPE_LEVEL_LOW>; + + post-power-on-delay-ms = <20>; + hid-descr-addr = <0x0001>; + + vdd-supply = <&pp3300_ts>; + }; +}; + +&mdss_dsi0 { panel: panel@0 { /* Compatible will be filled in per-board */ reg = <0>; @@ -67,7 +91,7 @@ port { panel_in: endpoint { - remote-endpoint = <&dsi0_out>; + remote-endpoint = <&mdss_dsi0_out>; }; }; }; @@ -82,30 +106,6 @@ }; }; -&gpio_keys { - status = "okay"; -}; - -&i2c4 { - status = "okay"; - clock-frequency = <400000>; - - ap_ts: touchscreen@10 { - compatible = "hid-over-i2c"; - reg = <0x10>; - pinctrl-names = "default"; - pinctrl-0 = <&ts_int_l>, <&ts_reset_l>; - - interrupt-parent = <&tlmm>; - interrupts = <9 IRQ_TYPE_LEVEL_LOW>; - - post-power-on-delay-ms = <20>; - hid-descr-addr = <0x0001>; - - vdd-supply = <&pp3300_ts>; - }; -}; - &sdhc_2 { status = "okay"; }; diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor-ti-sn65dsi86.dtsi b/arch/arm64/boot/dts/qcom/sc7180-trogdor-ti-sn65dsi86.dtsi index e52b8776755dbba0151d9b68af03a670597470c5..b0c3be4c3bb48422378b2f0217a8bf9682358b5d 100644 --- a/arch/arm64/boot/dts/qcom/sc7180-trogdor-ti-sn65dsi86.dtsi +++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor-ti-sn65dsi86.dtsi @@ -27,10 +27,6 @@ /* ADDITIONS TO NODES DEFINED IN PARENT DEVICE TREE FILES */ -&dsi0_out { - remote-endpoint = <&sn65dsi86_in>; -}; - edp_brij_i2c: &i2c2 { status = "okay"; clock-frequency = <400000>; @@ -65,7 +61,7 @@ edp_brij_i2c: &i2c2 { port@0 { reg = <0>; sn65dsi86_in: endpoint { - remote-endpoint = <&dsi0_out>; + remote-endpoint = <&mdss_dsi0_out>; }; }; @@ -95,6 +91,10 @@ edp_brij_i2c: &i2c2 { }; }; +&mdss_dsi0_out { + remote-endpoint = <&sn65dsi86_in>; +}; + &tlmm { edp_brij_irq: edp-brij-irq-state { pins = "gpio11"; diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor-wormdingler-rev1-boe.dts b/arch/arm64/boot/dts/qcom/sc7180-trogdor-wormdingler-rev1-boe.dts index c5b0658bd63230fd8398367c69053d69d71e5a42..6eeead70d3eb3d489768259ea3af4ffdd411570c 100644 --- a/arch/arm64/boot/dts/qcom/sc7180-trogdor-wormdingler-rev1-boe.dts +++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor-wormdingler-rev1-boe.dts @@ -17,7 +17,7 @@ compatible = "google,wormdingler-sku1024", "qcom,sc7180"; }; -&dsi_phy { +&mdss_dsi0_phy { qcom,phy-rescode-offset-top = /bits/ 8 <31 31 31 31 (-32)>; qcom,phy-rescode-offset-bot = /bits/ 8 <31 31 31 31 (-32)>; qcom,phy-drive-ldo-level = <450>; diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor-wormdingler.dtsi b/arch/arm64/boot/dts/qcom/sc7180-trogdor-wormdingler.dtsi index 262d6691abd95973512b7686a0b600277fdf9697..2efa8a4bcda603f3806c9a5597f446cba91993e0 100644 --- a/arch/arm64/boot/dts/qcom/sc7180-trogdor-wormdingler.dtsi +++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor-wormdingler.dtsi @@ -110,7 +110,28 @@ }; }; -&dsi0 { +&i2c4 { + status = "okay"; + clock-frequency = <400000>; + + ap_ts: touchscreen@1 { + compatible = "hid-over-i2c"; + reg = <0x01>; + pinctrl-names = "default"; + pinctrl-0 = <&ts_int_l>; + + interrupt-parent = <&tlmm>; + interrupts = <9 IRQ_TYPE_EDGE_FALLING>; + + post-power-on-delay-ms = <70>; + hid-descr-addr = <0x0001>; + + vdd-supply = <&pp3300_ts>; + vddl-supply = <&pp1800_ts>; + }; +}; + +&mdss_dsi0 { panel: panel@0 { reg = <0>; @@ -126,7 +147,7 @@ port { panel_in: endpoint { - remote-endpoint = <&dsi0_out>; + remote-endpoint = <&mdss_dsi0_out>; }; }; }; @@ -141,27 +162,6 @@ }; }; -&i2c4 { - status = "okay"; - clock-frequency = <400000>; - - ap_ts: touchscreen@1 { - compatible = "hid-over-i2c"; - reg = <0x01>; - pinctrl-names = "default"; - pinctrl-0 = <&ts_int_l>; - - interrupt-parent = <&tlmm>; - interrupts = <9 IRQ_TYPE_EDGE_FALLING>; - - post-power-on-delay-ms = <70>; - hid-descr-addr = <0x0001>; - - vdd-supply = <&pp3300_ts>; - vddl-supply = <&pp1800_ts>; - }; -}; - &pm6150_adc { skin-temp-thermistor@4d { reg = ; diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor.dtsi b/arch/arm64/boot/dts/qcom/sc7180-trogdor.dtsi index ca6920de7ea879bbcdf302b51c76909aab7e092b..681637cf6c4aff415352652e97f4692791b22d77 100644 --- a/arch/arm64/boot/dts/qcom/sc7180-trogdor.dtsi +++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor.dtsi @@ -705,20 +705,6 @@ ap_h1_spi: &spi0 { status = "disabled"; }; -&dsi0 { - status = "okay"; - vdda-supply = <&vdda_mipi_dsi0_1p2>; -}; - -&dsi0_out { - data-lanes = <0 1 2 3>; -}; - -&dsi_phy { - status = "okay"; - vdds-supply = <&vdda_mipi_dsi0_pll>; -}; - ap_sar_sensor_i2c: &i2c5 { clock-frequency = <400000>; @@ -788,6 +774,10 @@ hp_i2c: &i2c9 { }; }; +&lpasscc { + status = "okay"; +}; + &lpass_cpu { status = "okay"; @@ -813,7 +803,7 @@ hp_i2c: &i2c9 { }; }; -&mdp { +&lpass_hm { status = "okay"; }; @@ -832,6 +822,20 @@ hp_i2c: &i2c9 { link-frequencies = /bits/ 64 <1620000000 2700000000 5400000000>; }; +&mdss_dsi0 { + status = "okay"; + vdda-supply = <&vdda_mipi_dsi0_1p2>; +}; + +&mdss_dsi0_out { + data-lanes = <0 1 2 3>; +}; + +&mdss_dsi0_phy { + status = "okay"; + vdds-supply = <&vdda_mipi_dsi0_pll>; +}; + &pm6150_adc { charger-thermistor@4f { reg = ; @@ -892,6 +896,11 @@ hp_i2c: &i2c9 { qcom,spare-regs = <&tcsr_regs_2 0xb3e4>; }; +&scm { + /* TF-A firmware maps memory cached so mark dma-coherent to match. */ + dma-coherent; +}; + &sdhc_1 { status = "okay"; diff --git a/arch/arm64/boot/dts/qcom/sc7180.dtsi b/arch/arm64/boot/dts/qcom/sc7180.dtsi index f479cab8ab45c44a3f3a45617908884df4a4ea6f..e25dc2bb52a7e9ddea5cfc21a3b7f12aa8cca880 100644 --- a/arch/arm64/boot/dts/qcom/sc7180.dtsi +++ b/arch/arm64/boot/dts/qcom/sc7180.dtsi @@ -369,7 +369,7 @@ }; firmware { - scm { + scm: scm { compatible = "qcom,scm-sc7180", "qcom,scm"; }; }; @@ -2700,6 +2700,7 @@ qspi: spi@88dc000 { compatible = "qcom,sc7180-qspi", "qcom,qspi-v1"; reg = <0 0x088dc000 0 0x600>; + iommus = <&apps_smmu 0x20 0x0>; #address-cells = <1>; #size-cells = <0>; interrupts = ; @@ -2997,8 +2998,6 @@ interrupt-parent = <&mdss>; interrupts = <0>; - status = "disabled"; - ports { #address-cells = <1>; #size-cells = <0>; @@ -3006,7 +3005,7 @@ port@0 { reg = <0>; dpu_intf1_out: endpoint { - remote-endpoint = <&dsi0_in>; + remote-endpoint = <&mdss_dsi0_in>; }; }; @@ -3043,7 +3042,7 @@ }; }; - dsi0: dsi@ae94000 { + mdss_dsi0: dsi@ae94000 { compatible = "qcom,sc7180-dsi-ctrl", "qcom,mdss-dsi-ctrl"; reg = <0 0x0ae94000 0 0x400>; @@ -3066,12 +3065,12 @@ "bus"; assigned-clocks = <&dispcc DISP_CC_MDSS_BYTE0_CLK_SRC>, <&dispcc DISP_CC_MDSS_PCLK0_CLK_SRC>; - assigned-clock-parents = <&dsi_phy 0>, <&dsi_phy 1>; + assigned-clock-parents = <&mdss_dsi0_phy 0>, <&mdss_dsi0_phy 1>; operating-points-v2 = <&dsi_opp_table>; power-domains = <&rpmhpd SC7180_CX>; - phys = <&dsi_phy>; + phys = <&mdss_dsi0_phy>; #address-cells = <1>; #size-cells = <0>; @@ -3084,14 +3083,14 @@ port@0 { reg = <0>; - dsi0_in: endpoint { + mdss_dsi0_in: endpoint { remote-endpoint = <&dpu_intf1_out>; }; }; port@1 { reg = <1>; - dsi0_out: endpoint { + mdss_dsi0_out: endpoint { }; }; }; @@ -3116,13 +3115,13 @@ }; }; - dsi_phy: phy@ae94400 { + mdss_dsi0_phy: phy@ae94400 { compatible = "qcom,dsi-phy-10nm"; reg = <0 0x0ae94400 0 0x200>, <0 0x0ae94600 0 0x280>, <0 0x0ae94a00 0 0x1e0>; - reg-names = "dsi_phy", - "dsi_phy_lane", + reg-names = "dsi0_phy", + "dsi0_phy_lane", "dsi_pll"; #clock-cells = <1>; @@ -3213,8 +3212,8 @@ reg = <0 0x0af00000 0 0x200000>; clocks = <&rpmhcc RPMH_CXO_CLK>, <&gcc GCC_DISP_GPLL0_CLK_SRC>, - <&dsi_phy 0>, - <&dsi_phy 1>, + <&mdss_dsi0_phy 0>, + <&mdss_dsi0_phy 1>, <&dp_phy 0>, <&dp_phy 1>; clock-names = "bi_tcxo", @@ -3636,6 +3635,8 @@ power-domains = <&lpass_hm LPASS_CORE_HM_GDSCR>; #clock-cells = <1>; #power-domain-cells = <1>; + + status = "reserved"; /* Controlled by ADSP */ }; lpass_cpu: lpass@62d87000 { @@ -3684,6 +3685,8 @@ #clock-cells = <1>; #power-domain-cells = <1>; + + status = "reserved"; /* Controlled by ADSP */ }; }; diff --git a/arch/arm64/boot/dts/qcom/sc7280-chrome-common.dtsi b/arch/arm64/boot/dts/qcom/sc7280-chrome-common.dtsi index f562e4d2b6552c4922ffdafeb669285063e60b21..2e1cd219fc182204d4f1c8845701ca757750a0d0 100644 --- a/arch/arm64/boot/dts/qcom/sc7280-chrome-common.dtsi +++ b/arch/arm64/boot/dts/qcom/sc7280-chrome-common.dtsi @@ -79,6 +79,11 @@ firmware-name = "ath11k/WCN6750/hw1.0/wpss.mdt"; }; +&scm { + /* TF-A firmware maps memory cached so mark dma-coherent to match. */ + dma-coherent; +}; + &wifi { status = "okay"; diff --git a/arch/arm64/boot/dts/qcom/sc7280-herobrine.dtsi b/arch/arm64/boot/dts/qcom/sc7280-herobrine.dtsi index 5b1c175c47f103806ab7511937db670cdddcc753..9ea6636125ad9026dd5e8be174989a32fbb3796d 100644 --- a/arch/arm64/boot/dts/qcom/sc7280-herobrine.dtsi +++ b/arch/arm64/boot/dts/qcom/sc7280-herobrine.dtsi @@ -467,10 +467,6 @@ ap_i2c_tpm: &i2c14 { link-frequencies = /bits/ 64 <1620000000 2700000000 5400000000>; }; -&mdss_mdp { - status = "okay"; -}; - /* NVMe drive, enabled on a per-board basis */ &pcie1 { pinctrl-names = "default"; diff --git a/arch/arm64/boot/dts/qcom/sc7280.dtsi b/arch/arm64/boot/dts/qcom/sc7280.dtsi index 2fd1d3c0eb345b1302e6ca89f62af4b875360747..a0e8db8270e7a4567c1786d0bd0099b90d753676 100644 --- a/arch/arm64/boot/dts/qcom/sc7280.dtsi +++ b/arch/arm64/boot/dts/qcom/sc7280.dtsi @@ -649,6 +649,18 @@ }; }; + eud_typec: connector { + compatible = "usb-c-connector"; + + ports { + port@0 { + con_eud: endpoint { + remote-endpoint = <&eud_con>; + }; + }; + }; + }; + memory@80000000 { device_type = "memory"; /* We expect the bootloader to fill in the size */ @@ -656,7 +668,7 @@ }; firmware { - scm { + scm: scm { compatible = "qcom,scm-sc7280", "qcom,scm"; }; }; @@ -3430,6 +3442,7 @@ phy-names = "usb2-phy"; maximum-speed = "high-speed"; usb-role-switch; + port { usb2_role_switch: endpoint { remote-endpoint = <&eud_ep>; @@ -3441,6 +3454,7 @@ qspi: spi@88dc000 { compatible = "qcom,sc7280-qspi", "qcom,qspi-v1"; reg = <0 0x088dc000 0 0x1000>; + iommus = <&apps_smmu 0x20 0x0>; #address-cells = <1>; #size-cells = <0>; interrupts = ; @@ -3605,10 +3619,11 @@ }; eud: eud@88e0000 { - compatible = "qcom,sc7280-eud","qcom,eud"; - reg = <0 0x088e0000 0 0x2000>, - <0 0x088e2000 0 0x1000>; + compatible = "qcom,sc7280-eud", "qcom,eud"; + reg = <0 0x88e0000 0 0x2000>, + <0 0x88e2000 0 0x1000>; interrupts-extended = <&pdc 11 IRQ_TYPE_LEVEL_HIGH>; + ports { #address-cells = <1>; #size-cells = <0>; @@ -3619,6 +3634,7 @@ remote-endpoint = <&usb2_role_switch>; }; }; + port@1 { reg = <1>; eud_con: endpoint { @@ -3628,21 +3644,6 @@ }; }; - eud_typec: connector { - compatible = "usb-c-connector"; - ports { - #address-cells = <1>; - #size-cells = <0>; - - port@0 { - reg = <0>; - con_eud: endpoint { - remote-endpoint = <&eud_con>; - }; - }; - }; - }; - nsp_noc: interconnect@a0c0000 { reg = <0 0x0a0c0000 0 0x10000>; compatible = "qcom,sc7280-nsp-noc"; @@ -3880,8 +3881,6 @@ interrupt-parent = <&mdss>; interrupts = <0>; - status = "disabled"; - ports { #address-cells = <1>; #size-cells = <0>; @@ -3889,7 +3888,7 @@ port@0 { reg = <0>; dpu_intf1_out: endpoint { - remote-endpoint = <&dsi0_in>; + remote-endpoint = <&mdss_dsi0_in>; }; }; @@ -3974,14 +3973,14 @@ port@0 { reg = <0>; - dsi0_in: endpoint { + mdss_dsi0_in: endpoint { remote-endpoint = <&dpu_intf1_out>; }; }; port@1 { reg = <1>; - dsi0_out: endpoint { + mdss_dsi0_out: endpoint { }; }; }; diff --git a/arch/arm64/boot/dts/qcom/sc8180x-lenovo-flex-5g.dts b/arch/arm64/boot/dts/qcom/sc8180x-lenovo-flex-5g.dts new file mode 100644 index 0000000000000000000000000000000000000000..fe3b366e1435d2deb89c91cca00be55615c725dd --- /dev/null +++ b/arch/arm64/boot/dts/qcom/sc8180x-lenovo-flex-5g.dts @@ -0,0 +1,583 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2020-2023, Linaro Limited + */ + +/dts-v1/; + +#include +#include +#include +#include +#include "sc8180x.dtsi" +#include "sc8180x-pmics.dtsi" + +/ { + model = "Lenovo Flex 5G"; + compatible = "lenovo,flex-5g", "qcom,sc8180x"; + + aliases { + serial0 = &uart13; + }; + + backlight: backlight { + compatible = "pwm-backlight"; + pwms = <&pmc8180c_lpg 4 1000000>; + enable-gpios = <&pmc8180c_gpios 8 GPIO_ACTIVE_HIGH>; + + pinctrl-0 = <&bl_pwm_default>; + pinctrl-names = "default"; + }; + + gpio-keys { + compatible = "gpio-keys"; + + pinctrl-0 = <&hall_int_active_state>; + pinctrl-names = "default"; + + lid { + gpios = <&tlmm 121 GPIO_ACTIVE_LOW>; + linux,input-type = ; + linux,code = ; + wakeup-source; + wakeup-event-action = ; + }; + }; + + reserved-memory { + rmtfs_mem: rmtfs-region@85500000 { + compatible = "qcom,rmtfs-mem"; + reg = <0x0 0x85500000 0x0 0x200000>; + no-map; + + qcom,client-id = <1>; + qcom,vmid = <15>; + }; + + wlan_mem: wlan-region@8bc00000 { + reg = <0x0 0x8bc00000 0x0 0x180000>; + no-map; + }; + + mpss_mem: mpss-region@8d800000 { + reg = <0x0 0x8d800000 0x0 0x3000000>; + no-map; + }; + + adsp_mem: adsp-region@90800000 { + reg = <0x0 0x90800000 0x0 0x1c00000>; + no-map; + }; + + gpu_mem: gpu-region@98715000 { + reg = <0x0 0x98715000 0x0 0x2000>; + no-map; + }; + + cdsp_mem: cdsp-region@98900000 { + reg = <0x0 0x98900000 0x0 0x1400000>; + no-map; + }; + }; + + vph_pwr: vph-pwr-regulator { + compatible = "regulator-fixed"; + regulator-name = "vph_pwr"; + regulator-min-microvolt = <3700000>; + regulator-max-microvolt = <3700000>; + }; + + vreg_s4a_1p8: pm8150-s4-regulator { + compatible = "regulator-fixed"; + regulator-name = "vreg_s4a_1p8"; + + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + + regulator-always-on; + regulator-boot-on; + + vin-supply = <&vph_pwr>; + }; +}; + +&apps_rsc { + regulators-0 { + compatible = "qcom,pmc8180-rpmh-regulators"; + qcom,pmic-id = "a"; + + vdd-s5-supply = <&vph_pwr>; + vdd-l7-l12-l14-l15-supply = <&vreg_s5a_2p0>; + + vreg_s5a_2p0: smps5 { + regulator-min-microvolt = <2040000>; + regulator-max-microvolt = <2100000>; + }; + + vreg_l7a_1p8: ldo7 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-initial-mode = ; + }; + + vreg_l9a_1p3: ldo9 { + regulator-min-microvolt = <1296000>; + regulator-max-microvolt = <1304000>; + regulator-initial-mode = ; + }; + + vreg_l12a_1p8: ldo12 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-initial-mode = ; + }; + }; + + regulators-1 { + compatible = "qcom,pmc8180c-rpmh-regulators"; + qcom,pmic-id = "c"; + + vdd-s6-supply = <&vph_pwr>; + vdd-l2-l3-supply = <&vreg_s6c_1p35>; + vdd-bob-supply = <&vph_pwr>; + + vreg_s6c_1p35: smps6 { + regulator-min-microvolt = <1350000>; + regulator-max-microvolt = <1372000>; + regulator-initial-mode = ; + }; + + vreg_l3c_1p2: ldo3 { + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-initial-mode = ; + }; + + vreg_l10c_3p3: ldo10 { + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3312000>; + regulator-initial-mode = ; + }; + + vreg_l11c_3p3: ldo11 { + regulator-min-microvolt = <3296000>; + regulator-max-microvolt = <3304000>; + regulator-initial-mode = ; + }; + + vreg_bob: bob { + regulator-min-microvolt = <3296000>; + regulator-max-microvolt = <3350000>; + regulator-initial-mode = ; + }; + }; + + regulators-2 { + compatible = "qcom,pmc8180-rpmh-regulators"; + qcom,pmic-id = "e"; + + vdd-s4-supply = <&vph_pwr>; + vdd-s5-supply = <&vph_pwr>; + vdd-l2-l10-supply = <&vreg_bob>; + vdd-l3-l4-l5-l18-supply = <&vreg_s4e_0p98>; + vdd-l7-l12-l14-l15-supply = <&vreg_s5e_2p05>; + vdd-l13-l16-l17-supply = <&vreg_bob>; + + vreg_s4e_0p98: smps4 { + regulator-min-microvolt = <992000>; + regulator-max-microvolt = <992000>; + regulator-initial-mode = ; + }; + + vreg_s5e_2p05: smps5 { + regulator-min-microvolt = <2040000>; + regulator-max-microvolt = <2040000>; + regulator-initial-mode = ; + }; + + vreg_l1e_0p75: ldo1 { + regulator-min-microvolt = <752000>; + regulator-max-microvolt = <752000>; + regulator-initial-mode = ; + }; + + vreg_l5e_0p88: ldo5 { + regulator-min-microvolt = <880000>; + regulator-max-microvolt = <880000>; + regulator-initial-mode = ; + }; + + vreg_l7e_1p8: ldo7 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-initial-mode = ; + }; + + vreg_l10e_2p9: ldo10 { + regulator-min-microvolt = <2904000>; + regulator-max-microvolt = <2904000>; + regulator-initial-mode = ; + }; + + vreg_l16e_3p0: ldo16 { + regulator-min-microvolt = <3072000>; + regulator-max-microvolt = <3072000>; + regulator-initial-mode = ; + }; + }; +}; + +&gpu { + status = "okay"; + + zap-shader { + memory-region = <&gpu_mem>; + firmware-name = "qcom/sc8180x/qcdxkmsuc8180.mbn"; + }; +}; + +&i2c1 { + clock-frequency = <100000>; + + pinctrl-0 = <&i2c1_active>, <&i2c1_hid_active>; + pinctrl-names = "default"; + + status = "okay"; + + hid@10 { + compatible = "hid-over-i2c"; + reg = <0x10>; + hid-descr-addr = <0x1>; + + interrupts-extended = <&tlmm 122 IRQ_TYPE_LEVEL_LOW>; + }; +}; + +&i2c7 { + clock-frequency = <100000>; + + pinctrl-0 = <&i2c7_active>, <&i2c7_hid_active>; + pinctrl-names = "default"; + + status = "okay"; + + hid@5 { + compatible = "hid-over-i2c"; + reg = <0x5>; + hid-descr-addr = <0x20>; + + interrupts-extended = <&tlmm 37 IRQ_TYPE_LEVEL_LOW>; + }; + + hid@2c { + compatible = "hid-over-i2c"; + reg = <0x2c>; + hid-descr-addr = <0x20>; + + interrupts-extended = <&tlmm 24 IRQ_TYPE_LEVEL_LOW>; + }; +}; + +&mdss { + status = "okay"; +}; + +&mdss_edp { + data-lanes = <0 1 2 3>; + + pinctrl-0 = <&edp_hpd_active>; + pinctrl-names = "default"; + + status = "okay"; + + aux-bus { + panel { + compatible = "edp-panel"; + no-hpd; + + backlight = <&backlight>; + + ports { + port { + auo_b140han06_in: endpoint { + remote-endpoint = <&mdss_edp_out>; + }; + }; + }; + }; + }; + + ports { + port@1 { + reg = <1>; + mdss_edp_out: endpoint { + remote-endpoint = <&auo_b140han06_in>; + }; + }; + }; +}; + +&pcie3 { + perst-gpio = <&tlmm 178 GPIO_ACTIVE_LOW>; + wake-gpio = <&tlmm 180 GPIO_ACTIVE_HIGH>; + pinctrl-0 = <&pcie3_default_state>; + pinctrl-names = "default"; + + status = "okay"; +}; + +&pcie3_phy { + vdda-phy-supply = <&vreg_l5e_0p88>; + vdda-pll-supply = <&vreg_l3c_1p2>; + + status = "okay"; +}; + +&pmc8180c_lpg { + status = "okay"; +}; + +&qupv3_id_0 { + status = "okay"; +}; + +&qupv3_id_1 { + status = "okay"; +}; + +&qupv3_id_2 { + status = "okay"; +}; + +&remoteproc_adsp { + memory-region = <&adsp_mem>; + firmware-name = "qcom/sc8180x/LENOVO/82AK/qcadsp8180.mbn"; + + status = "okay"; +}; + +&remoteproc_cdsp { + memory-region = <&cdsp_mem>; + firmware-name = "qcom/sc8180x/LENOVO/82AK/qccdsp8180.mbn"; + + status = "okay"; +}; + +&remoteproc_mpss { + memory-region = <&mpss_mem>; + firmware-name = "qcom/sc8180x/LENOVO/82AK/qcmpss8180_nm.mbn"; + + status = "okay"; +}; + +&uart13 { + pinctrl-0 = <&uart13_state>; + pinctrl-names = "default"; + + status = "okay"; + + bluetooth { + compatible = "qcom,wcn3998-bt"; + + vddio-supply = <&vreg_s4a_1p8>; + vddxo-supply = <&vreg_l7a_1p8>; + vddrf-supply = <&vreg_l9a_1p3>; + vddch0-supply = <&vreg_l11c_3p3>; + max-speed = <3200000>; + }; +}; + +&ufs_mem_hc { + reset-gpios = <&tlmm 190 GPIO_ACTIVE_LOW>; + + vcc-supply = <&vreg_l10e_2p9>; + vcc-max-microamp = <155000>; + + vccq2-supply = <&vreg_l7e_1p8>; + vccq2-max-microamp = <425000>; + + status = "okay"; +}; + +&ufs_mem_phy { + vdda-phy-supply = <&vreg_l5e_0p88>; + vdda-pll-supply = <&vreg_l3c_1p2>; + + status = "okay"; +}; + +&usb_prim_hsphy { + vdda-pll-supply = <&vreg_l5e_0p88>; + vdda18-supply = <&vreg_l12a_1p8>; + vdda33-supply = <&vreg_l16e_3p0>; + + status = "okay"; +}; + +&usb_prim_qmpphy { + vdda-phy-supply = <&vreg_l3c_1p2>; + vdda-pll-supply = <&vreg_l5e_0p88>; + + status = "okay"; +}; + +&usb_prim { + status = "okay"; +}; + +&usb_prim_dwc3 { + dr_mode = "host"; +}; + +&usb_sec_hsphy { + vdda-pll-supply = <&vreg_l5e_0p88>; + vdda18-supply = <&vreg_l12a_1p8>; + vdda33-supply = <&vreg_l16e_3p0>; + + status = "okay"; +}; + +&usb_sec_qmpphy { + vdda-phy-supply = <&vreg_l3c_1p2>; + vdda-pll-supply = <&vreg_l5e_0p88>; + + status = "okay"; +}; + +&usb_sec { + status = "okay"; +}; + +&usb_sec_dwc3 { + dr_mode = "host"; +}; + +&wifi { + memory-region = <&wlan_mem>; + + vdd-0.8-cx-mx-supply = <&vreg_l1e_0p75>; + vdd-1.8-xo-supply = <&vreg_l7a_1p8>; + vdd-1.3-rfa-supply = <&vreg_l9a_1p3>; + vdd-3.3-ch0-supply = <&vreg_l11c_3p3>; + vdd-3.3-ch1-supply = <&vreg_l10c_3p3>; + + status = "okay"; +}; + +&xo_board_clk { + clock-frequency = <38400000>; +}; + +/* PINCTRL */ + +&pmc8180c_gpios { + bl_pwm_default: bl-pwm-default-state { + en-pins { + pins = "gpio8"; + function = "normal"; + }; + + pwm-pins { + pins = "gpio10"; + function = "func1"; + }; + }; +}; + +&tlmm { + gpio-reserved-ranges = <0 4>, <47 4>, <126 4>; + + edp_hpd_active: epd-hpd-active-state { + pins = "gpio10"; + function = "edp_hot"; + }; + + hall_int_active_state: hall-int-active-state { + pins = "gpio121"; + function = "gpio"; + + input-enable; + bias-disable; + }; + + i2c1_active: i2c1-active-state { + pins = "gpio114", "gpio115"; + function = "qup1"; + + bias-pull-up = <1>; + drive-strength = <2>; + }; + + i2c1_hid_active: i2c1-hid-active-state { + pins = "gpio122"; + function = "gpio"; + + input-enable; + bias-pull-up; + drive-strength = <2>; + }; + + i2c7_active: i2c7-active-state { + pins = "gpio98", "gpio99"; + function = "qup7"; + + bias-pull-up; + drive-strength = <2>; + }; + + i2c7_hid_active: i2c7-hid-active-state { + pins = "gpio37", "gpio24"; + function = "gpio"; + + input-enable; + bias-pull-up; + drive-strength = <2>; + }; + + pcie3_default_state: pcie3-default-state { + clkreq-pins { + pins = "gpio179"; + function = "pci_e3"; + bias-pull-up; + }; + + reset-n-pins { + pins = "gpio178"; + function = "gpio"; + + drive-strength = <2>; + output-low; + bias-pull-down; + }; + + wake-n-pins { + pins = "gpio180"; + function = "gpio"; + + drive-strength = <2>; + bias-pull-up; + }; + }; + + uart13_state: uart13-state { + cts-pins { + pins = "gpio43"; + function = "qup13"; + bias-pull-down; + }; + + rts-tx-pins { + pins = "gpio44", "gpio45"; + function = "qup13"; + drive-strength = <2>; + bias-disable; + }; + + rx-pins { + pins = "gpio46"; + function = "qup13"; + bias-pull-up; + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/sc8180x-pmics.dtsi b/arch/arm64/boot/dts/qcom/sc8180x-pmics.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..8247af01c84a5ad3dab6803b5af30a52ed569d27 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/sc8180x-pmics.dtsi @@ -0,0 +1,326 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2021-2023, Linaro Limited + */ + +#include +#include +#include +#include + +/ { + thermal-zones { + pmc8180-thermal { + polling-delay-passive = <100>; + polling-delay = <0>; + + thermal-sensors = <&pmc8180_temp>; + + trips { + trip0 { + temperature = <95000>; + hysteresis = <0>; + type = "passive"; + }; + + trip1 { + temperature = <115000>; + hysteresis = <0>; + type = "hot"; + }; + + trip2 { + temperature = <145000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + pmc8180c-thermal { + polling-delay-passive = <100>; + polling-delay = <0>; + + thermal-sensors = <&pmc8180c_temp>; + + trips { + trip0 { + temperature = <95000>; + hysteresis = <0>; + type = "passive"; + }; + + trip1 { + temperature = <115000>; + hysteresis = <0>; + type = "hot"; + }; + + trip2 { + temperature = <145000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + }; +}; + +&spmi_bus { + pmc8180_0: pmic@0 { + compatible = "qcom,pm8150", "qcom,spmi-pmic"; + reg = <0x0 SPMI_USID>; + #address-cells = <1>; + #size-cells = <0>; + + pon: power-on@800 { + compatible = "qcom,pm8916-pon"; + reg = <0x0800>; + pwrkey { + compatible = "qcom,pm8941-pwrkey"; + interrupts = <0x0 0x8 0x0 IRQ_TYPE_EDGE_BOTH>; + debounce = <15625>; + bias-pull-up; + linux,code = ; + + status = "disabled"; + }; + }; + + pmc8180_temp: temp-alarm@2400 { + compatible = "qcom,spmi-temp-alarm"; + reg = <0x2400>; + interrupts = <0x0 0x24 0x0 IRQ_TYPE_EDGE_BOTH>; + io-channels = <&pmc8180_adc ADC5_DIE_TEMP>; + io-channel-names = "thermal"; + #thermal-sensor-cells = <0>; + }; + + pmc8180_adc: adc@3100 { + compatible = "qcom,spmi-adc5"; + reg = <0x3100>; + #address-cells = <1>; + #size-cells = <0>; + #io-channel-cells = <1>; + interrupts = <0x0 0x31 0x0 IRQ_TYPE_EDGE_RISING>; + + ref-gnd@0 { + reg = ; + qcom,pre-scaling = <1 1>; + label = "ref_gnd"; + }; + + vref-1p25@1 { + reg = ; + qcom,pre-scaling = <1 1>; + label = "vref_1p25"; + }; + + die-temp@6 { + reg = ; + qcom,pre-scaling = <1 1>; + label = "die_temp"; + }; + }; + + pmc8180_adc_tm: adc-tm@3500 { + compatible = "qcom,spmi-adc-tm5"; + reg = <0x3500>; + interrupts = <0x0 0x35 0x0 IRQ_TYPE_EDGE_RISING>; + #thermal-sensor-cells = <1>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + rtc@6000 { + compatible = "qcom,pm8941-rtc"; + reg = <0x6000>; + reg-names = "rtc", "alarm"; + interrupts = <0x0 0x61 0x1 IRQ_TYPE_NONE>; + }; + + pmc8180_gpios: gpio@c000 { + compatible = "qcom,pmc8180-gpio"; + reg = <0xc000>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + }; + }; + + pmic@1 { + compatible = "qcom,pmc8180", "qcom,spmi-pmic"; + reg = <0x1 SPMI_USID>; + #address-cells = <1>; + #size-cells = <0>; + }; + + pmic@2 { + compatible = "qcom,smb2351", "qcom,spmi-pmic"; + reg = <0x2 SPMI_USID>; + #address-cells = <1>; + #size-cells = <0>; + + adc@3100 { + compatible = "qcom,spmi-adc-rev2"; + reg = <0x3100>; + #address-cells = <1>; + #size-cells = <0>; + #io-channel-cells = <1>; + interrupts = <0x2 0x31 0x0 IRQ_TYPE_EDGE_RISING>; + + ref-gnd@0 { + reg = ; + qcom,pre-scaling = <1 1>; + label = "ref_gnd"; + }; + + vref-1p25@1 { + reg = ; + qcom,pre-scaling = <1 1>; + label = "vref_1p25"; + }; + + vcoin@85 { + reg = <0x85>; + qcom,pre-scaling = <1 1>; + label = "vcoin2"; + }; + }; + }; + + pmic@6 { + compatible = "qcom,pm8150c", "qcom,spmi-pmic"; + reg = <0x6 SPMI_USID>; + #address-cells = <1>; + #size-cells = <0>; + }; + + pmic@8 { + compatible = "qcom,pm8150", "qcom,spmi-pmic"; + reg = <0x8 SPMI_USID>; + #address-cells = <1>; + #size-cells = <0>; + }; + + pmic@a { + compatible = "qcom,smb2351", "qcom,spmi-pmic"; + reg = <0xa SPMI_USID>; + #address-cells = <1>; + #size-cells = <0>; + + adc@3100 { + compatible = "qcom,spmi-adc-rev2"; + reg = <0x3100>; + #address-cells = <1>; + #size-cells = <0>; + #io-channel-cells = <1>; + interrupts = <0xa 0x31 0x0 IRQ_TYPE_EDGE_RISING>; + + ref-gnd@0 { + reg = ; + qcom,pre-scaling = <1 1>; + label = "ref_gnd"; + }; + + vref-1p25@1 { + reg = ; + qcom,pre-scaling = <1 1>; + label = "vref_1p25"; + }; + + vcoin@85 { + reg = <0x85>; + qcom,pre-scaling = <1 1>; + label = "vcoin"; + }; + }; + }; + + pmic@4 { + compatible = "qcom,pm8150c", "qcom,spmi-pmic"; + reg = <0x4 SPMI_USID>; + #address-cells = <1>; + #size-cells = <0>; + + power-on@800 { + compatible = "qcom,pm8916-pon"; + reg = <0x0800>; + + status = "disabled"; + }; + + pmc8180c_temp: temp-alarm@2400 { + compatible = "qcom,spmi-temp-alarm"; + reg = <0x2400>; + interrupts = <0x4 0x24 0x0 IRQ_TYPE_EDGE_BOTH>; + io-channels = <&pmc8180c_adc ADC5_DIE_TEMP>; + io-channel-names = "thermal"; + #thermal-sensor-cells = <0>; + }; + + pmc8180c_adc: adc@3100 { + compatible = "qcom,spmi-adc5"; + reg = <0x3100>; + #address-cells = <1>; + #size-cells = <0>; + #io-channel-cells = <1>; + interrupts = <0x4 0x31 0x0 IRQ_TYPE_EDGE_RISING>; + + ref-gnd@0 { + reg = ; + qcom,pre-scaling = <1 1>; + label = "ref_gnd"; + }; + + vref-1p25@1 { + reg = ; + qcom,pre-scaling = <1 1>; + label = "vref_1p25"; + }; + + die-temp@6 { + reg = ; + qcom,pre-scaling = <1 1>; + label = "die_temp"; + }; + }; + + pmc8180c_adc_tm: adc-tm@3500 { + compatible = "qcom,spmi-adc-tm5"; + reg = <0x3500>; + interrupts = <0x4 0x35 0x0 IRQ_TYPE_EDGE_RISING>; + #thermal-sensor-cells = <1>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + pmc8180c_gpios: gpio@c000 { + compatible = "qcom,pmc8180c-gpio"; + reg = <0xc000>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + }; + }; + + pmic@5 { + compatible = "qcom,pmc8180c", "qcom,spmi-pmic"; + reg = <0x5 SPMI_USID>; + + pmc8180c_lpg: lpg { + compatible = "qcom,pmc8180c-lpg"; + + #address-cells = <1>; + #size-cells = <0>; + #pwm-cells = <2>; + + status = "disabled"; + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/sc8180x-primus.dts b/arch/arm64/boot/dts/qcom/sc8180x-primus.dts new file mode 100644 index 0000000000000000000000000000000000000000..fc038474cb71b6d5b99026b4357fd5ee2a2b94b3 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/sc8180x-primus.dts @@ -0,0 +1,702 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2020-2023, Linaro Limited + */ + +/dts-v1/; + +#include +#include +#include +#include +#include "sc8180x.dtsi" +#include "sc8180x-pmics.dtsi" + +/ { + model = "Qualcomm SC8180x Primus"; + compatible = "qcom,sc8180x-primus", "qcom,sc8180x"; + + aliases { + serial0 = &uart12; + serial1 = &uart13; + }; + + backlight: backlight { + compatible = "pwm-backlight"; + pwms = <&pmc8180c_lpg 4 1000000>; + enable-gpios = <&pmc8180c_gpios 8 GPIO_ACTIVE_HIGH>; + + pinctrl-names = "default"; + pinctrl-0 = <&bl_pwm_default>; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + gpio-keys { + compatible = "gpio-keys"; + + pinctrl-names = "default"; + pinctrl-0 = <&hall_int_active_state>; + + lid-switch { + gpios = <&tlmm 121 GPIO_ACTIVE_HIGH>; + linux,input-type = ; + linux,code = ; + wakeup-source; + wakeup-event-action = ; + }; + }; + + reserved-memory { + rmtfs_mem: rmtfs-region@85500000 { + compatible = "qcom,rmtfs-mem"; + reg = <0x0 0x85500000 0x0 0x200000>; + no-map; + + qcom,client-id = <1>; + qcom,vmid = <15>; + }; + + wlan_mem: wlan-region@8bc00000 { + reg = <0x0 0x8bc00000 0x0 0x180000>; + no-map; + }; + + adsp_mem: adsp-region@96e00000 { + reg = <0x0 0x96e00000 0x0 0x1c00000>; + no-map; + }; + + mpss_mem: mpss-region@8d800000 { + reg = <0x0 0x8d800000 0x0 0x9600000>; + no-map; + }; + + gpu_mem: gpu-region@98a00000 { + reg = <0x0 0x98a00000 0x0 0x2000>; + no-map; + }; + + reserved-region@9a500000 { + reg = <0x0 0x9a500000 0x0 0x600000>; + no-map; + }; + }; + + vreg_nvme_0p9: nvme-0p9-regulator { + compatible = "regulator-fixed"; + regulator-name = "vreg_nvme_0p9"; + + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <900000>; + + regulator-always-on; + }; + + vreg_nvme_3p3: nvme-3p3-regulator { + compatible = "regulator-fixed"; + regulator-name = "vreg_nvme_3p3"; + + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + + gpio = <&pmc8180c_gpios 11 0>; + enable-active-high; + + regulator-always-on; + }; + + vdd_kb_tp_3v3: vdd-kb-tp-3v3-regulator { + compatible = "regulator-fixed"; + regulator-name = "vdd_kb_tp_3v3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + + gpio = <&tlmm 4 GPIO_ACTIVE_HIGH>; + enable-active-high; + + regulator-always-on; + + pinctrl-names = "default"; + pinctrl-0 = <&kb_tp_3v3_en_active_state>; + }; + + vph_pwr: vph-pwr-regulator { + compatible = "regulator-fixed"; + regulator-name = "vph_pwr"; + regulator-min-microvolt = <3700000>; + regulator-max-microvolt = <3700000>; + }; + + vreg_s4a_1p8: pm8150-s4 { + compatible = "regulator-fixed"; + regulator-name = "vreg_s4a_1p8"; + + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + + regulator-always-on; + regulator-boot-on; + + vin-supply = <&vph_pwr>; + }; +}; + +&apps_rsc { + regulators-0 { + compatible = "qcom,pmc8180-rpmh-regulators"; + qcom,pmic-id = "a"; + + vdd-s5-supply = <&vph_pwr>; + vdd-l7-l12-l14-l15-supply = <&vreg_s5a_2p0>; + + vreg_s5a_2p0: smps5 { + regulator-min-microvolt = <2040000>; + regulator-max-microvolt = <2100000>; + }; + + vreg_l7a_1p8: ldo7 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-initial-mode = ; + }; + + vreg_l9a_1p3: ldo9 { + regulator-min-microvolt = <1296000>; + regulator-max-microvolt = <1304000>; + regulator-initial-mode = ; + }; + + vreg_l12a_1p8: ldo12 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-initial-mode = ; + }; + }; + + regulators-1 { + compatible = "qcom,pmc8180c-rpmh-regulators"; + qcom,pmic-id = "c"; + + vdd-s6-supply = <&vph_pwr>; + vdd-s8-supply = <&vph_pwr>; + vdd-l2-l3-supply = <&vreg_s6c_1p35>; + vdd-bob-supply = <&vph_pwr>; + + vreg_s6c_1p35: smps6 { + regulator-min-microvolt = <1350000>; + regulator-max-microvolt = <1372000>; + regulator-initial-mode = ; + }; + + vreg_s8c_1p8: smps8 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-initial-mode = ; + regulator-always-on; + }; + + vreg_l3c_1p2: ldo3 { + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-initial-mode = ; + }; + + vreg_l4c_3p3: ldo4 { + regulator-min-microvolt = <3008000>; + regulator-max-microvolt = <3008000>; + regulator-initial-mode = ; + }; + + vreg_l10c_3p3: ldo10 { + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3312000>; + regulator-initial-mode = ; + }; + + vreg_l11c_3p3: ldo11 { + regulator-min-microvolt = <3296000>; + regulator-max-microvolt = <3304000>; + regulator-initial-mode = ; + }; + + vreg_bob: bob { + regulator-min-microvolt = <3296000>; + regulator-max-microvolt = <3350000>; + regulator-initial-mode = ; + }; + }; + + regulators-2 { + compatible = "qcom,pmc8180-rpmh-regulators"; + qcom,pmic-id = "e"; + + vdd-s4-supply = <&vph_pwr>; + vdd-s5-supply = <&vph_pwr>; + vdd-l2-l10-supply = <&vreg_bob>; + vdd-l3-l4-l5-l18-supply = <&vreg_s4e_0p98>; + vdd-l7-l12-l14-l15-supply = <&vreg_s5e_2p05>; + vdd-l13-l16-l17-supply = <&vreg_bob>; + + vreg_s4e_0p98: smps4 { + regulator-min-microvolt = <992000>; + regulator-max-microvolt = <992000>; + regulator-initial-mode = ; + }; + + vreg_s5e_2p05: smps5 { + regulator-min-microvolt = <2040000>; + regulator-max-microvolt = <2040000>; + regulator-initial-mode = ; + }; + + vreg_l1e_0p75: ldo1 { + regulator-min-microvolt = <752000>; + regulator-max-microvolt = <752000>; + regulator-initial-mode = ; + }; + + vreg_l5e_0p88: ldo5 { + regulator-min-microvolt = <880000>; + regulator-max-microvolt = <880000>; + regulator-initial-mode = ; + }; + + vreg_l7e_1p8: ldo7 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-initial-mode = ; + }; + + vreg_l10e_2p9: ldo10 { + regulator-min-microvolt = <2904000>; + regulator-max-microvolt = <2904000>; + regulator-initial-mode = ; + }; + + vreg_l12e: ldo12 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-initial-mode = ; + }; + + vreg_l16e_3p0: ldo16 { + regulator-min-microvolt = <3072000>; + regulator-max-microvolt = <3072000>; + regulator-initial-mode = ; + }; + }; +}; + +&gpu { + status = "okay"; + + zap-shader { + memory-region = <&gpu_mem>; + firmware-name = "qcom/sc8180x/qcdxkmsuc8180.mbn"; + }; +}; + +&i2c1 { + clock-frequency = <100000>; + + pinctrl-names = "default"; + pinctrl-0 = <&ts_i2c_active_state>; + + status = "okay"; + + touchscreen@10 { + compatible = "hid-over-i2c"; + reg = <0x10>; + hid-descr-addr = <0x1>; + + vdd-supply = <&vreg_l4c_3p3>; + vddl-supply = <&vreg_l12e>; + + post-power-on-delay-ms = <20>; + + interrupts-extended = <&tlmm 122 IRQ_TYPE_LEVEL_LOW>; + + pinctrl-names = "default"; + pinctrl-0 = <&ts_active_state>; + }; +}; + +&i2c7 { + clock-frequency = <100000>; + + pinctrl-names = "default"; + pinctrl-0 = <&aux_i2c_active_state>; + + status = "okay"; + + touchpad@15 { + compatible = "hid-over-i2c"; + reg = <0x15>; + hid-descr-addr = <0x1>; + + interrupts-extended = <&tlmm 24 IRQ_TYPE_LEVEL_LOW>; + + pinctrl-names = "default"; + pinctrl-0 = <&tp_int_active_state>; + + vdd-supply = <&vdd_kb_tp_3v3>; + }; + + keyboard@3a { + compatible = "hid-over-i2c"; + reg = <0x3a>; + hid-descr-addr = <0x1>; + interrupts-extended = <&tlmm 37 IRQ_TYPE_LEVEL_LOW>; + + pinctrl-names = "default"; + pinctrl-0 = <&kb_int_active_state>; + + vdd-supply = <&vdd_kb_tp_3v3>; + }; +}; + +&mdss { + status = "okay"; +}; + +&mdss_edp { + data-lanes = <0 1 2 3>; + + pinctrl-names = "default"; + pinctrl-0 = <&edp_hpd_active>; + + status = "okay"; + + aux-bus { + panel { + compatible = "edp-panel"; + + backlight = <&backlight>; + + ports { + port { + auo_b133han05_in: endpoint { + remote-endpoint = <&mdss_edp_out>; + }; + }; + }; + }; + }; + + ports { + port@1 { + reg = <1>; + mdss_edp_out: endpoint { + remote-endpoint = <&auo_b133han05_in>; + }; + }; + }; +}; + +&pcie1 { + perst-gpio = <&tlmm 175 GPIO_ACTIVE_LOW>; + wake-gpio = <&tlmm 177 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&pcie2_default_state>; + + status = "okay"; +}; + +&pcie1_phy { + vdda-phy-supply = <&vreg_l5e_0p88>; + vdda-pll-supply = <&vreg_l3c_1p2>; + + status = "okay"; +}; + +&pmc8180c_lpg { + status = "okay"; +}; + +&qupv3_id_0 { + status = "okay"; +}; + +&qupv3_id_1 { + status = "okay"; +}; + +&qupv3_id_2 { + status = "okay"; +}; + +&remoteproc_adsp { + memory-region = <&adsp_mem>; + firmware-name = "qcom/sc8180x/qcadsp8180.mbn"; + + status = "okay"; +}; + +&remoteproc_mpss { + memory-region = <&mpss_mem>; + firmware-name = "qcom/sc8180x/qcmpss8180.mbn"; + + status = "okay"; +}; + +&uart12 { + compatible = "qcom,geni-debug-uart"; + status = "okay"; +}; + +&uart13 { + pinctrl-names = "default"; + pinctrl-0 = <&uart13_state>; + + status = "okay"; + + bluetooth { + compatible = "qcom,wcn3998-bt"; + + vddio-supply = <&vreg_s4a_1p8>; + vddxo-supply = <&vreg_l7a_1p8>; + vddrf-supply = <&vreg_l9a_1p3>; + vddch0-supply = <&vreg_l11c_3p3>; + max-speed = <3200000>; + }; +}; + +&ufs_mem_hc { + reset-gpios = <&tlmm 190 GPIO_ACTIVE_LOW>; + + vcc-supply = <&vreg_l10e_2p9>; + vcc-max-microamp = <155000>; + + vccq2-supply = <&vreg_l7e_1p8>; + vccq2-max-microamp = <425000>; + + status = "okay"; +}; + +&ufs_mem_phy { + vdda-phy-supply = <&vreg_l5e_0p88>; + vdda-pll-supply = <&vreg_l3c_1p2>; + + status = "okay"; +}; + +&usb_prim_hsphy { + vdda-pll-supply = <&vreg_l5e_0p88>; + vdda18-supply = <&vreg_l12a_1p8>; + vdda33-supply = <&vreg_l16e_3p0>; + + status = "okay"; +}; + +&usb_prim_qmpphy { + vdda-phy-supply = <&vreg_l3c_1p2>; + vdda-pll-supply = <&vreg_l5e_0p88>; + + status = "okay"; +}; + +&usb_prim { + status = "okay"; +}; + +&usb_prim_dwc3 { + dr_mode = "host"; +}; + +&usb_sec_hsphy { + vdda-pll-supply = <&vreg_l5e_0p88>; + vdda18-supply = <&vreg_l12a_1p8>; + vdda33-supply = <&vreg_l16e_3p0>; + + status = "okay"; +}; + +&usb_sec_qmpphy { + vdda-phy-supply = <&vreg_l3c_1p2>; + vdda-pll-supply = <&vreg_l5e_0p88>; + + status = "okay"; +}; + +&usb_sec { + status = "okay"; +}; + +&usb_sec_dwc3 { + dr_mode = "host"; +}; + +&wifi { + memory-region = <&wlan_mem>; + + vdd-0.8-cx-mx-supply = <&vreg_l1e_0p75>; + vdd-1.8-xo-supply = <&vreg_l7a_1p8>; + vdd-1.3-rfa-supply = <&vreg_l9a_1p3>; + vdd-3.3-ch0-supply = <&vreg_l11c_3p3>; + vdd-3.3-ch1-supply = <&vreg_l10c_3p3>; + + status = "okay"; +}; + +&xo_board_clk { + clock-frequency = <38400000>; +}; + +/* PINCTRL */ + +&pmc8180c_gpios { + bl_pwm_default: bl-pwm-default-state { + en-pins { + pins = "gpio8"; + function = "normal"; + }; + + pwm-pins { + pins = "gpio10"; + function = "func1"; + }; + }; +}; + +&tlmm { + gpio-reserved-ranges = <0 4>, <47 4>, <126 4>; + + aux_i2c_active_state: aux-i2c-active-state { + pins = "gpio98", "gpio99"; + function = "qup7"; + + bias-disable; + drive-strength = <16>; + }; + + edp_hpd_active: epd-hpd-active-state { + pins = "gpio10"; + function = "edp_hot"; + }; + + hall_int_active_state: hall-int-active-state { + pins = "gpio121"; + function = "gpio"; + + input-enable; + bias-disable; + }; + + kb_int_active_state: kb-int-active-state { + int-n-pins { + pins = "gpio37"; + function = "gpio"; + + bias-pull-up; + intput-enable; + }; + + kp-disable-pins { + pins = "gpio135"; + function = "gpio"; + + output-high; + }; + }; + + kb_tp_3v3_en_active_state: kb-tp-3v3-en-active-state { + pins = "gpio4"; + function = "gpio"; + + bias-disable; + }; + + pcie2_default_state: pcie2-default-state { + clkreq-pins { + pins = "gpio176"; + function = "pci_e2"; + bias-pull-up; + }; + + reset-n-pins { + pins = "gpio175"; + function = "gpio"; + + drive-strength = <2>; + output-low; + bias-pull-down; + }; + + wake-n-pins { + pins = "gpio177"; + function = "gpio"; + + drive-strength = <2>; + bias-pull-up; + }; + }; + + tp_int_active_state: tp-int-active-state { + tp-int-pins { + pins = "gpio24"; + function = "gpio"; + + bias-disable; + input-enable; + }; + + tp-close-n-pins { + pins = "gpio116"; + function = "gpio"; + + bias-disable; + input-enable; + }; + }; + + ts_active_state: ts-active-state { + int-n-pins { + pins = "gpio122"; + function = "gpio"; + + input-enable; + bias-disable; + }; + + reset-n-pins { + pins = "gpio54"; + function = "gpio"; + + output-high; + }; + }; + + ts_i2c_active_state: ts-i2c-active-state { + pins = "gpio114", "gpio115"; + function = "qup1"; + + /* External pull up */ + bias-disable; + drive-strength = <2>; + }; + + uart13_state: uart13-state { + cts-pins { + pins = "gpio43"; + function = "qup13"; + bias-pull-down; + }; + + rts-tx-pins { + pins = "gpio44", "gpio45"; + function = "qup13"; + drive-strength = <2>; + bias-disable; + }; + + rx-pins { + pins = "gpio46"; + function = "qup13"; + bias-pull-up; + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/sc8180x.dtsi b/arch/arm64/boot/dts/qcom/sc8180x.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..d3ae185356365d74833e3b2ac60219490d54c83c --- /dev/null +++ b/arch/arm64/boot/dts/qcom/sc8180x.dtsi @@ -0,0 +1,4032 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2020-2023, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/ { + interrupt-parent = <&intc>; + + #address-cells = <2>; + #size-cells = <2>; + + clocks { + xo_board_clk: xo-board { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <38400000>; + }; + + sleep_clk: sleep-clk { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <32764>; + clock-output-names = "sleep_clk"; + }; + }; + + cpus { + #address-cells = <2>; + #size-cells = <0>; + + CPU0: cpu@0 { + device_type = "cpu"; + compatible = "qcom,kryo485"; + reg = <0x0 0x0>; + enable-method = "psci"; + capacity-dmips-mhz = <602>; + next-level-cache = <&L2_0>; + qcom,freq-domain = <&cpufreq_hw 0>; + operating-points-v2 = <&cpu0_opp_table>; + interconnects = <&gem_noc MASTER_AMPSS_M0 3 &mc_virt SLAVE_EBI_CH0 3>, + <&osm_l3 MASTER_OSM_L3_APPS &osm_l3 SLAVE_OSM_L3>; + power-domains = <&CPU_PD0>; + power-domain-names = "psci"; + #cooling-cells = <2>; + clocks = <&cpufreq_hw 0>; + + L2_0: l2-cache { + compatible = "cache"; + cache-level = <2>; + cache-unified; + next-level-cache = <&L3_0>; + L3_0: l3-cache { + compatible = "cache"; + cache-level = <3>; + }; + }; + }; + + CPU1: cpu@100 { + device_type = "cpu"; + compatible = "qcom,kryo485"; + reg = <0x0 0x100>; + enable-method = "psci"; + capacity-dmips-mhz = <602>; + next-level-cache = <&L2_100>; + qcom,freq-domain = <&cpufreq_hw 0>; + operating-points-v2 = <&cpu0_opp_table>; + interconnects = <&gem_noc MASTER_AMPSS_M0 3 &mc_virt SLAVE_EBI_CH0 3>, + <&osm_l3 MASTER_OSM_L3_APPS &osm_l3 SLAVE_OSM_L3>; + power-domains = <&CPU_PD1>; + power-domain-names = "psci"; + #cooling-cells = <2>; + clocks = <&cpufreq_hw 0>; + + L2_100: l2-cache { + compatible = "cache"; + cache-level = <2>; + cache-unified; + next-level-cache = <&L3_0>; + }; + + }; + + CPU2: cpu@200 { + device_type = "cpu"; + compatible = "qcom,kryo485"; + reg = <0x0 0x200>; + enable-method = "psci"; + capacity-dmips-mhz = <602>; + next-level-cache = <&L2_200>; + qcom,freq-domain = <&cpufreq_hw 0>; + operating-points-v2 = <&cpu0_opp_table>; + interconnects = <&gem_noc MASTER_AMPSS_M0 3 &mc_virt SLAVE_EBI_CH0 3>, + <&osm_l3 MASTER_OSM_L3_APPS &osm_l3 SLAVE_OSM_L3>; + power-domains = <&CPU_PD2>; + power-domain-names = "psci"; + #cooling-cells = <2>; + clocks = <&cpufreq_hw 0>; + + L2_200: l2-cache { + compatible = "cache"; + cache-level = <2>; + cache-unified; + next-level-cache = <&L3_0>; + }; + }; + + CPU3: cpu@300 { + device_type = "cpu"; + compatible = "qcom,kryo485"; + reg = <0x0 0x300>; + enable-method = "psci"; + capacity-dmips-mhz = <602>; + next-level-cache = <&L2_300>; + qcom,freq-domain = <&cpufreq_hw 0>; + operating-points-v2 = <&cpu0_opp_table>; + interconnects = <&gem_noc MASTER_AMPSS_M0 3 &mc_virt SLAVE_EBI_CH0 3>, + <&osm_l3 MASTER_OSM_L3_APPS &osm_l3 SLAVE_OSM_L3>; + power-domains = <&CPU_PD3>; + power-domain-names = "psci"; + #cooling-cells = <2>; + clocks = <&cpufreq_hw 0>; + + L2_300: l2-cache { + compatible = "cache"; + cache-unified; + cache-level = <2>; + next-level-cache = <&L3_0>; + }; + }; + + CPU4: cpu@400 { + device_type = "cpu"; + compatible = "qcom,kryo485"; + reg = <0x0 0x400>; + enable-method = "psci"; + capacity-dmips-mhz = <1024>; + next-level-cache = <&L2_400>; + qcom,freq-domain = <&cpufreq_hw 1>; + operating-points-v2 = <&cpu4_opp_table>; + interconnects = <&gem_noc MASTER_AMPSS_M0 3 &mc_virt SLAVE_EBI_CH0 3>, + <&osm_l3 MASTER_OSM_L3_APPS &osm_l3 SLAVE_OSM_L3>; + power-domains = <&CPU_PD4>; + power-domain-names = "psci"; + #cooling-cells = <2>; + clocks = <&cpufreq_hw 1>; + + L2_400: l2-cache { + compatible = "cache"; + cache-unified; + cache-level = <2>; + next-level-cache = <&L3_0>; + }; + }; + + CPU5: cpu@500 { + device_type = "cpu"; + compatible = "qcom,kryo485"; + reg = <0x0 0x500>; + enable-method = "psci"; + capacity-dmips-mhz = <1024>; + next-level-cache = <&L2_500>; + qcom,freq-domain = <&cpufreq_hw 1>; + operating-points-v2 = <&cpu4_opp_table>; + interconnects = <&gem_noc MASTER_AMPSS_M0 3 &mc_virt SLAVE_EBI_CH0 3>, + <&osm_l3 MASTER_OSM_L3_APPS &osm_l3 SLAVE_OSM_L3>; + power-domains = <&CPU_PD5>; + power-domain-names = "psci"; + #cooling-cells = <2>; + clocks = <&cpufreq_hw 1>; + + L2_500: l2-cache { + compatible = "cache"; + cache-unified; + cache-level = <2>; + next-level-cache = <&L3_0>; + }; + }; + + CPU6: cpu@600 { + device_type = "cpu"; + compatible = "qcom,kryo485"; + reg = <0x0 0x600>; + enable-method = "psci"; + capacity-dmips-mhz = <1024>; + next-level-cache = <&L2_600>; + qcom,freq-domain = <&cpufreq_hw 1>; + operating-points-v2 = <&cpu4_opp_table>; + interconnects = <&gem_noc MASTER_AMPSS_M0 3 &mc_virt SLAVE_EBI_CH0 3>, + <&osm_l3 MASTER_OSM_L3_APPS &osm_l3 SLAVE_OSM_L3>; + power-domains = <&CPU_PD6>; + power-domain-names = "psci"; + #cooling-cells = <2>; + clocks = <&cpufreq_hw 1>; + + L2_600: l2-cache { + compatible = "cache"; + cache-unified; + cache-level = <2>; + next-level-cache = <&L3_0>; + }; + }; + + CPU7: cpu@700 { + device_type = "cpu"; + compatible = "qcom,kryo485"; + reg = <0x0 0x700>; + enable-method = "psci"; + capacity-dmips-mhz = <1024>; + next-level-cache = <&L2_700>; + qcom,freq-domain = <&cpufreq_hw 1>; + operating-points-v2 = <&cpu4_opp_table>; + interconnects = <&gem_noc MASTER_AMPSS_M0 3 &mc_virt SLAVE_EBI_CH0 3>, + <&osm_l3 MASTER_OSM_L3_APPS &osm_l3 SLAVE_OSM_L3>; + power-domains = <&CPU_PD7>; + power-domain-names = "psci"; + #cooling-cells = <2>; + clocks = <&cpufreq_hw 1>; + + L2_700: l2-cache { + compatible = "cache"; + cache-unified; + cache-level = <2>; + next-level-cache = <&L3_0>; + }; + }; + + cpu-map { + cluster0 { + core0 { + cpu = <&CPU0>; + }; + + core1 { + cpu = <&CPU1>; + }; + + core2 { + cpu = <&CPU2>; + }; + + core3 { + cpu = <&CPU3>; + }; + + core4 { + cpu = <&CPU4>; + }; + + core5 { + cpu = <&CPU5>; + }; + + core6 { + cpu = <&CPU6>; + }; + + core7 { + cpu = <&CPU7>; + }; + }; + }; + + idle-states { + entry-method = "psci"; + + LITTLE_CPU_SLEEP_0: cpu-sleep-0-0 { + compatible = "arm,idle-state"; + arm,psci-suspend-param = <0x40000004>; + entry-latency-us = <355>; + exit-latency-us = <909>; + min-residency-us = <3934>; + local-timer-stop; + }; + + BIG_CPU_SLEEP_0: cpu-sleep-1-0 { + compatible = "arm,idle-state"; + arm,psci-suspend-param = <0x40000004>; + entry-latency-us = <241>; + exit-latency-us = <1461>; + min-residency-us = <4488>; + local-timer-stop; + }; + }; + + domain-idle-states { + CLUSTER_SLEEP_0: cluster-sleep-0 { + compatible = "domain-idle-state"; + arm,psci-suspend-param = <0x4100c244>; + entry-latency-us = <3263>; + exit-latency-us = <6562>; + min-residency-us = <9987>; + }; + }; + }; + + cpu0_opp_table: opp-table-cpu0 { + compatible = "operating-points-v2"; + opp-shared; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + opp-peak-kBps = <800000 9600000>; + }; + + opp-422400000 { + opp-hz = /bits/ 64 <422400000>; + opp-peak-kBps = <800000 9600000>; + }; + + opp-537600000 { + opp-hz = /bits/ 64 <537600000>; + opp-peak-kBps = <800000 12902400>; + }; + + opp-652800000 { + opp-hz = /bits/ 64 <652800000>; + opp-peak-kBps = <800000 12902400>; + }; + + opp-768000000 { + opp-hz = /bits/ 64 <768000000>; + opp-peak-kBps = <800000 15974400>; + }; + + opp-883200000 { + opp-hz = /bits/ 64 <883200000>; + opp-peak-kBps = <1804000 19660800>; + }; + + opp-998400000 { + opp-hz = /bits/ 64 <998400000>; + opp-peak-kBps = <1804000 19660800>; + }; + + opp-1113600000 { + opp-hz = /bits/ 64 <1113600000>; + opp-peak-kBps = <1804000 22732800>; + }; + + opp-1228800000 { + opp-hz = /bits/ 64 <1228800000>; + opp-peak-kBps = <1804000 22732800>; + }; + + opp-1363200000 { + opp-hz = /bits/ 64 <1363200000>; + opp-peak-kBps = <2188000 25804800>; + }; + + opp-1478400000 { + opp-hz = /bits/ 64 <1478400000>; + opp-peak-kBps = <2188000 31948800>; + }; + + opp-1574400000 { + opp-hz = /bits/ 64 <1574400000>; + opp-peak-kBps = <3072000 31948800>; + }; + + opp-1670400000 { + opp-hz = /bits/ 64 <1670400000>; + opp-peak-kBps = <3072000 31948800>; + }; + + opp-1766400000 { + opp-hz = /bits/ 64 <1766400000>; + opp-peak-kBps = <3072000 31948800>; + }; + }; + + cpu4_opp_table: opp-table-cpu4 { + compatible = "operating-points-v2"; + opp-shared; + + opp-825600000 { + opp-hz = /bits/ 64 <825600000>; + opp-peak-kBps = <1804000 15974400>; + }; + + opp-940800000 { + opp-hz = /bits/ 64 <940800000>; + opp-peak-kBps = <2188000 19660800>; + }; + + opp-1056000000 { + opp-hz = /bits/ 64 <1056000000>; + opp-peak-kBps = <2188000 22732800>; + }; + + opp-1171200000 { + opp-hz = /bits/ 64 <1171200000>; + opp-peak-kBps = <3072000 25804800>; + }; + + opp-1286400000 { + opp-hz = /bits/ 64 <1286400000>; + opp-peak-kBps = <3072000 31948800>; + }; + + opp-1420800000 { + opp-hz = /bits/ 64 <1420800000>; + opp-peak-kBps = <4068000 31948800>; + }; + + opp-1536000000 { + opp-hz = /bits/ 64 <1536000000>; + opp-peak-kBps = <4068000 31948800>; + }; + + opp-1651200000 { + opp-hz = /bits/ 64 <1651200000>; + opp-peak-kBps = <4068000 40550400>; + }; + + opp-1766400000 { + opp-hz = /bits/ 64 <1766400000>; + opp-peak-kBps = <4068000 40550400>; + }; + + opp-1881600000 { + opp-hz = /bits/ 64 <1881600000>; + opp-peak-kBps = <4068000 43008000>; + }; + + opp-1996800000 { + opp-hz = /bits/ 64 <1996800000>; + opp-peak-kBps = <6220000 43008000>; + }; + + opp-2131200000 { + opp-hz = /bits/ 64 <2131200000>; + opp-peak-kBps = <6220000 49152000>; + }; + + opp-2246400000 { + opp-hz = /bits/ 64 <2246400000>; + opp-peak-kBps = <7216000 49152000>; + }; + + opp-2361600000 { + opp-hz = /bits/ 64 <2361600000>; + opp-peak-kBps = <8368000 49152000>; + }; + + opp-2457600000 { + opp-hz = /bits/ 64 <2457600000>; + opp-peak-kBps = <8368000 51609600>; + }; + + opp-2553600000 { + opp-hz = /bits/ 64 <2553600000>; + opp-peak-kBps = <8368000 51609600>; + }; + + opp-2649600000 { + opp-hz = /bits/ 64 <2649600000>; + opp-peak-kBps = <8368000 51609600>; + }; + + opp-2745600000 { + opp-hz = /bits/ 64 <2745600000>; + opp-peak-kBps = <8368000 51609600>; + }; + + opp-2841600000 { + opp-hz = /bits/ 64 <2841600000>; + opp-peak-kBps = <8368000 51609600>; + }; + + opp-2918400000 { + opp-hz = /bits/ 64 <2918400000>; + opp-peak-kBps = <8368000 51609600>; + }; + + opp-2995200000 { + opp-hz = /bits/ 64 <2995200000>; + opp-peak-kBps = <8368000 51609600>; + }; + }; + + firmware { + scm: scm { + compatible = "qcom,scm-sc8180x", "qcom,scm"; + }; + }; + + camnoc_virt: interconnect-camnoc-virt { + compatible = "qcom,sc8180x-camnoc-virt"; + #interconnect-cells = <2>; + qcom,bcm-voters = <&apps_bcm_voter>; + }; + + mc_virt: interconnect-mc-virt { + compatible = "qcom,sc8180x-mc-virt"; + #interconnect-cells = <2>; + qcom,bcm-voters = <&apps_bcm_voter>; + }; + + qup_virt: interconnect-qup-virt { + compatible = "qcom,sc8180x-qup-virt"; + #interconnect-cells = <2>; + qcom,bcm-voters = <&apps_bcm_voter>; + }; + + memory@80000000 { + device_type = "memory"; + /* We expect the bootloader to fill in the size */ + reg = <0x0 0x80000000 0x0 0x0>; + }; + + pmu { + compatible = "arm,armv8-pmuv3"; + interrupts = ; + }; + + psci { + compatible = "arm,psci-1.0"; + method = "smc"; + + CPU_PD0: power-domain-cpu0 { + #power-domain-cells = <0>; + power-domains = <&CLUSTER_PD>; + domain-idle-states = <&LITTLE_CPU_SLEEP_0>; + }; + + CPU_PD1: power-domain-cpu1 { + #power-domain-cells = <0>; + power-domains = <&CLUSTER_PD>; + domain-idle-states = <&LITTLE_CPU_SLEEP_0>; + }; + + CPU_PD2: power-domain-cpu2 { + #power-domain-cells = <0>; + power-domains = <&CLUSTER_PD>; + domain-idle-states = <&LITTLE_CPU_SLEEP_0>; + }; + + CPU_PD3: power-domain-cpu3 { + #power-domain-cells = <0>; + power-domains = <&CLUSTER_PD>; + domain-idle-states = <&LITTLE_CPU_SLEEP_0>; + }; + + CPU_PD4: power-domain-cpu4 { + #power-domain-cells = <0>; + power-domains = <&CLUSTER_PD>; + domain-idle-states = <&BIG_CPU_SLEEP_0>; + }; + + CPU_PD5: power-domain-cpu5 { + #power-domain-cells = <0>; + power-domains = <&CLUSTER_PD>; + domain-idle-states = <&BIG_CPU_SLEEP_0>; + }; + + CPU_PD6: power-domain-cpu6 { + #power-domain-cells = <0>; + power-domains = <&CLUSTER_PD>; + domain-idle-states = <&BIG_CPU_SLEEP_0>; + }; + + CPU_PD7: power-domain-cpu7 { + #power-domain-cells = <0>; + power-domains = <&CLUSTER_PD>; + domain-idle-states = <&BIG_CPU_SLEEP_0>; + }; + + CLUSTER_PD: power-domain-cpu-cluster0 { + #power-domain-cells = <0>; + domain-idle-states = <&CLUSTER_SLEEP_0>; + }; + }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + + hyp_mem: hyp@85700000 { + reg = <0x0 0x85700000 0x0 0x600000>; + no-map; + }; + + xbl_mem: xbl@85d00000 { + reg = <0x0 0x85d00000 0x0 0x140000>; + no-map; + }; + + aop_mem: aop@85f00000 { + reg = <0x0 0x85f00000 0x0 0x20000>; + no-map; + }; + + aop_cmd_db: cmd-db@85f20000 { + compatible = "qcom,cmd-db"; + reg = <0x0 0x85f20000 0x0 0x20000>; + no-map; + }; + + reserved@85f40000 { + reg = <0x0 0x85f40000 0x0 0x10000>; + no-map; + }; + + smem_mem: smem@86000000 { + compatible = "qcom,smem"; + reg = <0x0 0x86000000 0x0 0x200000>; + no-map; + hwlocks = <&tcsr_mutex 3>; + }; + + reserved@86200000 { + reg = <0x0 0x86200000 0x0 0x3900000>; + no-map; + }; + + reserved@89b00000 { + reg = <0x0 0x89b00000 0x0 0x1c00000>; + no-map; + }; + + reserved@9d400000 { + reg = <0x0 0x9d400000 0x0 0x1000000>; + no-map; + }; + + reserved@9e400000 { + reg = <0x0 0x9e400000 0x0 0x1400000>; + no-map; + }; + + reserved@9f800000 { + reg = <0x0 0x9f800000 0x0 0x800000>; + no-map; + }; + }; + + smp2p-cdsp { + compatible = "qcom,smp2p"; + qcom,smem = <94>, <432>; + + interrupts = ; + + mboxes = <&apss_shared 6>; + + qcom,local-pid = <0>; + qcom,remote-pid = <5>; + + cdsp_smp2p_out: master-kernel { + qcom,entry-name = "master-kernel"; + #qcom,smem-state-cells = <1>; + }; + + cdsp_smp2p_in: slave-kernel { + qcom,entry-name = "slave-kernel"; + + interrupt-controller; + #interrupt-cells = <2>; + }; + }; + + smp2p-lpass { + compatible = "qcom,smp2p"; + qcom,smem = <443>, <429>; + + interrupts = ; + + mboxes = <&apss_shared 10>; + + qcom,local-pid = <0>; + qcom,remote-pid = <2>; + + adsp_smp2p_out: master-kernel { + qcom,entry-name = "master-kernel"; + #qcom,smem-state-cells = <1>; + }; + + adsp_smp2p_in: slave-kernel { + qcom,entry-name = "slave-kernel"; + + interrupt-controller; + #interrupt-cells = <2>; + }; + }; + + smp2p-mpss { + compatible = "qcom,smp2p"; + qcom,smem = <435>, <428>; + + interrupts = ; + + mboxes = <&apss_shared 14>; + + qcom,local-pid = <0>; + qcom,remote-pid = <1>; + + modem_smp2p_out: master-kernel { + qcom,entry-name = "master-kernel"; + #qcom,smem-state-cells = <1>; + }; + + modem_smp2p_in: slave-kernel { + qcom,entry-name = "slave-kernel"; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + modem_smp2p_ipa_out: ipa-ap-to-modem { + qcom,entry-name = "ipa"; + #qcom,smem-state-cells = <1>; + }; + + modem_smp2p_ipa_in: ipa-modem-to-ap { + qcom,entry-name = "ipa"; + interrupt-controller; + #interrupt-cells = <2>; + }; + + modem_smp2p_wlan_in: wlan-wpss-to-ap { + qcom,entry-name = "wlan"; + interrupt-controller; + #interrupt-cells = <2>; + }; + }; + + smp2p-slpi { + compatible = "qcom,smp2p"; + qcom,smem = <481>, <430>; + + interrupts = ; + + mboxes = <&apss_shared 26>; + + qcom,local-pid = <0>; + qcom,remote-pid = <3>; + + slpi_smp2p_out: master-kernel { + qcom,entry-name = "master-kernel"; + #qcom,smem-state-cells = <1>; + }; + + slpi_smp2p_in: slave-kernel { + qcom,entry-name = "slave-kernel"; + + interrupt-controller; + #interrupt-cells = <2>; + }; + }; + + soc: soc@0 { + compatible = "simple-bus"; + #address-cells = <2>; + #size-cells = <2>; + ranges = <0 0 0 0 0x10 0>; + dma-ranges = <0 0 0 0 0x10 0>; + + gcc: clock-controller@100000 { + compatible = "qcom,gcc-sc8180x"; + reg = <0x0 0x00100000 0x0 0x1f0000>; + #clock-cells = <1>; + #reset-cells = <1>; + #power-domain-cells = <1>; + clocks = <&rpmhcc RPMH_CXO_CLK>, + <&rpmhcc RPMH_CXO_CLK_A>, + <&sleep_clk>; + clock-names = "bi_tcxo", + "bi_tcxo_ao", + "sleep_clk"; + }; + + qupv3_id_0: geniqup@8c0000 { + compatible = "qcom,geni-se-qup"; + reg = <0 0x008c0000 0 0x6000>; + clocks = <&gcc GCC_QUPV3_WRAP_0_M_AHB_CLK>, + <&gcc GCC_QUPV3_WRAP_0_S_AHB_CLK>; + clock-names = "m-ahb", "s-ahb"; + #address-cells = <2>; + #size-cells = <2>; + ranges; + iommus = <&apps_smmu 0x4c3 0>; + status = "disabled"; + + i2c0: i2c@880000 { + compatible = "qcom,geni-i2c"; + reg = <0 0x00880000 0 0x4000>; + clocks = <&gcc GCC_QUPV3_WRAP0_S0_CLK>; + clock-names = "se"; + interrupts = ; + interconnects = <&qup_virt MASTER_QUP_CORE_0 0 &qup_virt SLAVE_QUP_CORE_0 0>, + <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_0 0>, + <&aggre2_noc MASTER_QUP_0 0 &mc_virt SLAVE_EBI_CH0 0>; + interconnect-names = "qup-core", "qup-config", "qup-memory"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + spi0: spi@880000 { + compatible = "qcom,geni-spi"; + reg = <0 0x00880000 0 0x4000>; + clocks = <&gcc GCC_QUPV3_WRAP0_S0_CLK>; + clock-names = "se"; + interrupts = ; + interconnects = <&qup_virt MASTER_QUP_CORE_0 0 &qup_virt SLAVE_QUP_CORE_0 0>, + <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_0 0>; + interconnect-names = "qup-core", "qup-config"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + uart0: serial@880000 { + compatible = "qcom,geni-uart"; + reg = <0 0x00880000 0 0x4000>; + clocks = <&gcc GCC_QUPV3_WRAP0_S0_CLK>; + clock-names = "se"; + interrupts = ; + interconnects = <&qup_virt MASTER_QUP_CORE_0 0 &qup_virt SLAVE_QUP_CORE_0 0>, + <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_0 0>; + interconnect-names = "qup-core", "qup-config"; + status = "disabled"; + }; + + i2c1: i2c@884000 { + compatible = "qcom,geni-i2c"; + reg = <0 0x00884000 0 0x4000>; + clocks = <&gcc GCC_QUPV3_WRAP0_S1_CLK>; + clock-names = "se"; + interrupts = ; + interconnects = <&qup_virt MASTER_QUP_CORE_0 0 &qup_virt SLAVE_QUP_CORE_0 0>, + <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_0 0>, + <&aggre2_noc MASTER_QUP_0 0 &mc_virt SLAVE_EBI_CH0 0>; + interconnect-names = "qup-core", "qup-config", "qup-memory"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + spi1: spi@884000 { + compatible = "qcom,geni-spi"; + reg = <0 0x00884000 0 0x4000>; + clocks = <&gcc GCC_QUPV3_WRAP0_S1_CLK>; + clock-names = "se"; + interrupts = ; + interconnects = <&qup_virt MASTER_QUP_CORE_0 0 &qup_virt SLAVE_QUP_CORE_0 0>, + <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_0 0>; + interconnect-names = "qup-core", "qup-config"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + uart1: serial@884000 { + compatible = "qcom,geni-uart"; + reg = <0 0x00884000 0 0x4000>; + clocks = <&gcc GCC_QUPV3_WRAP0_S1_CLK>; + clock-names = "se"; + interrupts = ; + interconnects = <&qup_virt MASTER_QUP_CORE_0 0 &qup_virt SLAVE_QUP_CORE_0 0>, + <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_0 0>; + interconnect-names = "qup-core", "qup-config"; + status = "disabled"; + }; + + i2c2: i2c@888000 { + compatible = "qcom,geni-i2c"; + reg = <0 0x00888000 0 0x4000>; + clocks = <&gcc GCC_QUPV3_WRAP0_S2_CLK>; + clock-names = "se"; + interrupts = ; + interconnects = <&qup_virt MASTER_QUP_CORE_0 0 &qup_virt SLAVE_QUP_CORE_0 0>, + <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_0 0>, + <&aggre2_noc MASTER_QUP_0 0 &mc_virt SLAVE_EBI_CH0 0>; + interconnect-names = "qup-core", "qup-config", "qup-memory"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + spi2: spi@888000 { + compatible = "qcom,geni-spi"; + reg = <0 0x00888000 0 0x4000>; + clocks = <&gcc GCC_QUPV3_WRAP0_S2_CLK>; + clock-names = "se"; + interrupts = ; + interconnects = <&qup_virt MASTER_QUP_CORE_0 0 &qup_virt SLAVE_QUP_CORE_0 0>, + <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_0 0>; + interconnect-names = "qup-core", "qup-config"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + uart2: serial@888000 { + compatible = "qcom,geni-uart"; + reg = <0 0x00888000 0 0x4000>; + clocks = <&gcc GCC_QUPV3_WRAP0_S2_CLK>; + clock-names = "se"; + interrupts = ; + interconnects = <&qup_virt MASTER_QUP_CORE_0 0 &qup_virt SLAVE_QUP_CORE_0 0>, + <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_0 0>; + interconnect-names = "qup-core", "qup-config"; + status = "disabled"; + }; + + i2c3: i2c@88c000 { + compatible = "qcom,geni-i2c"; + reg = <0 0x0088c000 0 0x4000>; + clocks = <&gcc GCC_QUPV3_WRAP0_S3_CLK>; + clock-names = "se"; + interrupts = ; + interconnects = <&qup_virt MASTER_QUP_CORE_0 0 &qup_virt SLAVE_QUP_CORE_0 0>, + <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_0 0>, + <&aggre2_noc MASTER_QUP_0 0 &mc_virt SLAVE_EBI_CH0 0>; + interconnect-names = "qup-core", "qup-config", "qup-memory"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + spi3: spi@88c000 { + compatible = "qcom,geni-spi"; + reg = <0 0x0088c000 0 0x4000>; + clocks = <&gcc GCC_QUPV3_WRAP0_S3_CLK>; + clock-names = "se"; + interrupts = ; + interconnects = <&qup_virt MASTER_QUP_CORE_0 0 &qup_virt SLAVE_QUP_CORE_0 0>, + <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_0 0>; + interconnect-names = "qup-core", "qup-config"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + uart3: serial@88c000 { + compatible = "qcom,geni-uart"; + reg = <0 0x0088c000 0 0x4000>; + clocks = <&gcc GCC_QUPV3_WRAP0_S3_CLK>; + clock-names = "se"; + interrupts = ; + interconnects = <&qup_virt MASTER_QUP_CORE_0 0 &qup_virt SLAVE_QUP_CORE_0 0>, + <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_0 0>; + interconnect-names = "qup-core", "qup-config"; + status = "disabled"; + }; + + i2c4: i2c@890000 { + compatible = "qcom,geni-i2c"; + reg = <0 0x00890000 0 0x4000>; + clocks = <&gcc GCC_QUPV3_WRAP0_S4_CLK>; + clock-names = "se"; + interrupts = ; + interconnects = <&qup_virt MASTER_QUP_CORE_0 0 &qup_virt SLAVE_QUP_CORE_0 0>, + <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_0 0>, + <&aggre2_noc MASTER_QUP_0 0 &mc_virt SLAVE_EBI_CH0 0>; + interconnect-names = "qup-core", "qup-config", "qup-memory"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + spi4: spi@890000 { + compatible = "qcom,geni-spi"; + reg = <0 0x00890000 0 0x4000>; + clocks = <&gcc GCC_QUPV3_WRAP0_S4_CLK>; + clock-names = "se"; + interrupts = ; + interconnects = <&qup_virt MASTER_QUP_CORE_0 0 &qup_virt SLAVE_QUP_CORE_0 0>, + <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_0 0>; + interconnect-names = "qup-core", "qup-config"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + uart4: serial@890000 { + compatible = "qcom,geni-uart"; + reg = <0 0x00890000 0 0x4000>; + clocks = <&gcc GCC_QUPV3_WRAP0_S4_CLK>; + clock-names = "se"; + interrupts = ; + interconnects = <&qup_virt MASTER_QUP_CORE_0 0 &qup_virt SLAVE_QUP_CORE_0 0>, + <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_0 0>; + interconnect-names = "qup-core", "qup-config"; + status = "disabled"; + }; + + i2c5: i2c@894000 { + compatible = "qcom,geni-i2c"; + reg = <0 0x00894000 0 0x4000>; + clocks = <&gcc GCC_QUPV3_WRAP0_S5_CLK>; + clock-names = "se"; + interrupts = ; + interconnects = <&qup_virt MASTER_QUP_CORE_0 0 &qup_virt SLAVE_QUP_CORE_0 0>, + <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_0 0>, + <&aggre2_noc MASTER_QUP_0 0 &mc_virt SLAVE_EBI_CH0 0>; + interconnect-names = "qup-core", "qup-config", "qup-memory"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + spi5: spi@894000 { + compatible = "qcom,geni-spi"; + reg = <0 0x00894000 0 0x4000>; + clocks = <&gcc GCC_QUPV3_WRAP0_S5_CLK>; + clock-names = "se"; + interrupts = ; + interconnects = <&qup_virt MASTER_QUP_CORE_0 0 &qup_virt SLAVE_QUP_CORE_0 0>, + <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_0 0>; + interconnect-names = "qup-core", "qup-config"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + uart5: serial@894000 { + compatible = "qcom,geni-uart"; + reg = <0 0x00894000 0 0x4000>; + clocks = <&gcc GCC_QUPV3_WRAP0_S5_CLK>; + clock-names = "se"; + interrupts = ; + interconnects = <&qup_virt MASTER_QUP_CORE_0 0 &qup_virt SLAVE_QUP_CORE_0 0>, + <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_0 0>; + interconnect-names = "qup-core", "qup-config"; + status = "disabled"; + }; + + i2c6: i2c@898000 { + compatible = "qcom,geni-i2c"; + reg = <0 0x00898000 0 0x4000>; + clocks = <&gcc GCC_QUPV3_WRAP0_S6_CLK>; + clock-names = "se"; + interrupts = ; + interconnects = <&qup_virt MASTER_QUP_CORE_0 0 &qup_virt SLAVE_QUP_CORE_0 0>, + <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_0 0>, + <&aggre2_noc MASTER_QUP_0 0 &mc_virt SLAVE_EBI_CH0 0>; + interconnect-names = "qup-core", "qup-config", "qup-memory"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + spi6: spi@898000 { + compatible = "qcom,geni-spi"; + reg = <0 0x00898000 0 0x4000>; + clocks = <&gcc GCC_QUPV3_WRAP0_S6_CLK>; + clock-names = "se"; + interrupts = ; + interconnects = <&qup_virt MASTER_QUP_CORE_0 0 &qup_virt SLAVE_QUP_CORE_0 0>, + <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_0 0>; + interconnect-names = "qup-core", "qup-config"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + uart6: serial@898000 { + compatible = "qcom,geni-uart"; + reg = <0 0x00898000 0 0x4000>; + clocks = <&gcc GCC_QUPV3_WRAP0_S6_CLK>; + clock-names = "se"; + interrupts = ; + interconnects = <&qup_virt MASTER_QUP_CORE_0 0 &qup_virt SLAVE_QUP_CORE_0 0>, + <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_0 0>; + interconnect-names = "qup-core", "qup-config"; + status = "disabled"; + }; + + i2c7: i2c@89c000 { + compatible = "qcom,geni-i2c"; + reg = <0 0x0089c000 0 0x4000>; + clocks = <&gcc GCC_QUPV3_WRAP0_S7_CLK>; + clock-names = "se"; + interrupts = ; + interconnects = <&qup_virt MASTER_QUP_CORE_0 0 &qup_virt SLAVE_QUP_CORE_0 0>, + <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_0 0>, + <&aggre2_noc MASTER_QUP_0 0 &mc_virt SLAVE_EBI_CH0 0>; + interconnect-names = "qup-core", "qup-config", "qup-memory"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + spi7: spi@89c000 { + compatible = "qcom,geni-spi"; + reg = <0 0x0089c000 0 0x4000>; + clocks = <&gcc GCC_QUPV3_WRAP0_S7_CLK>; + clock-names = "se"; + interrupts = ; + interconnects = <&qup_virt MASTER_QUP_CORE_0 0 &qup_virt SLAVE_QUP_CORE_0 0>, + <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_0 0>; + interconnect-names = "qup-core", "qup-config"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + uart7: serial@89c000 { + compatible = "qcom,geni-uart"; + reg = <0 0x0089c000 0 0x4000>; + clocks = <&gcc GCC_QUPV3_WRAP0_S7_CLK>; + clock-names = "se"; + interrupts = ; + interconnects = <&qup_virt MASTER_QUP_CORE_0 0 &qup_virt SLAVE_QUP_CORE_0 0>, + <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_0 0>; + interconnect-names = "qup-core", "qup-config"; + status = "disabled"; + }; + }; + + qupv3_id_1: geniqup@ac0000 { + compatible = "qcom,geni-se-qup"; + reg = <0x0 0x00ac0000 0x0 0x6000>; + clocks = <&gcc GCC_QUPV3_WRAP_1_M_AHB_CLK>, + <&gcc GCC_QUPV3_WRAP_1_S_AHB_CLK>; + clock-names = "m-ahb", "s-ahb"; + #address-cells = <2>; + #size-cells = <2>; + ranges; + iommus = <&apps_smmu 0x603 0>; + status = "disabled"; + + i2c8: i2c@a80000 { + compatible = "qcom,geni-i2c"; + reg = <0 0x00a80000 0 0x4000>; + clocks = <&gcc GCC_QUPV3_WRAP1_S0_CLK>; + clock-names = "se"; + interrupts = ; + interconnects = <&qup_virt MASTER_QUP_CORE_1 0 &qup_virt SLAVE_QUP_CORE_1 0>, + <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_1 0>, + <&aggre2_noc MASTER_QUP_1 0 &mc_virt SLAVE_EBI_CH0 0>; + interconnect-names = "qup-core", "qup-config", "qup-memory"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + spi8: spi@a80000 { + compatible = "qcom,geni-spi"; + reg = <0 0x00a80000 0 0x4000>; + clocks = <&gcc GCC_QUPV3_WRAP1_S0_CLK>; + clock-names = "se"; + interrupts = ; + interconnects = <&qup_virt MASTER_QUP_CORE_1 0 &qup_virt SLAVE_QUP_CORE_1 0>, + <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_1 0>; + interconnect-names = "qup-core", "qup-config"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + uart8: serial@a80000 { + compatible = "qcom,geni-uart"; + reg = <0 0x00a80000 0 0x4000>; + clocks = <&gcc GCC_QUPV3_WRAP1_S0_CLK>; + clock-names = "se"; + interrupts = ; + interconnects = <&qup_virt MASTER_QUP_CORE_1 0 &qup_virt SLAVE_QUP_CORE_1 0>, + <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_1 0>; + interconnect-names = "qup-core", "qup-config"; + status = "disabled"; + }; + + i2c9: i2c@a84000 { + compatible = "qcom,geni-i2c"; + reg = <0 0x00a84000 0 0x4000>; + clocks = <&gcc GCC_QUPV3_WRAP1_S1_CLK>; + clock-names = "se"; + interrupts = ; + interconnects = <&qup_virt MASTER_QUP_CORE_1 0 &qup_virt SLAVE_QUP_CORE_1 0>, + <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_1 0>, + <&aggre2_noc MASTER_QUP_1 0 &mc_virt SLAVE_EBI_CH0 0>; + interconnect-names = "qup-core", "qup-config", "qup-memory"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + spi9: spi@a84000 { + compatible = "qcom,geni-spi"; + reg = <0 0x00a84000 0 0x4000>; + clocks = <&gcc GCC_QUPV3_WRAP1_S1_CLK>; + clock-names = "se"; + interrupts = ; + interconnects = <&qup_virt MASTER_QUP_CORE_1 0 &qup_virt SLAVE_QUP_CORE_1 0>, + <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_1 0>; + interconnect-names = "qup-core", "qup-config"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + uart9: serial@a84000 { + compatible = "qcom,geni-debug-uart"; + reg = <0 0x00a84000 0 0x4000>; + clocks = <&gcc GCC_QUPV3_WRAP1_S1_CLK>; + clock-names = "se"; + interrupts = ; + interconnects = <&qup_virt MASTER_QUP_CORE_1 0 &qup_virt SLAVE_QUP_CORE_1 0>, + <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_1 0>; + interconnect-names = "qup-core", "qup-config"; + status = "disabled"; + }; + + i2c10: i2c@a88000 { + compatible = "qcom,geni-i2c"; + reg = <0 0x00a88000 0 0x4000>; + clocks = <&gcc GCC_QUPV3_WRAP1_S2_CLK>; + clock-names = "se"; + interrupts = ; + interconnects = <&qup_virt MASTER_QUP_CORE_1 0 &qup_virt SLAVE_QUP_CORE_1 0>, + <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_1 0>, + <&aggre2_noc MASTER_QUP_1 0 &mc_virt SLAVE_EBI_CH0 0>; + interconnect-names = "qup-core", "qup-config", "qup-memory"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + spi10: spi@a88000 { + compatible = "qcom,geni-spi"; + reg = <0 0x00a88000 0 0x4000>; + clocks = <&gcc GCC_QUPV3_WRAP1_S2_CLK>; + clock-names = "se"; + interrupts = ; + interconnects = <&qup_virt MASTER_QUP_CORE_1 0 &qup_virt SLAVE_QUP_CORE_1 0>, + <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_1 0>; + interconnect-names = "qup-core", "qup-config"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + uart10: serial@a88000 { + compatible = "qcom,geni-uart"; + reg = <0 0x00a88000 0 0x4000>; + clocks = <&gcc GCC_QUPV3_WRAP1_S2_CLK>; + clock-names = "se"; + interrupts = ; + interconnects = <&qup_virt MASTER_QUP_CORE_1 0 &qup_virt SLAVE_QUP_CORE_1 0>, + <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_1 0>; + interconnect-names = "qup-core", "qup-config"; + status = "disabled"; + }; + + i2c11: i2c@a8c000 { + compatible = "qcom,geni-i2c"; + reg = <0 0x00a8c000 0 0x4000>; + clocks = <&gcc GCC_QUPV3_WRAP1_S3_CLK>; + clock-names = "se"; + interrupts = ; + interconnects = <&qup_virt MASTER_QUP_CORE_1 0 &qup_virt SLAVE_QUP_CORE_1 0>, + <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_1 0>, + <&aggre2_noc MASTER_QUP_1 0 &mc_virt SLAVE_EBI_CH0 0>; + interconnect-names = "qup-core", "qup-config", "qup-memory"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + spi11: spi@a8c000 { + compatible = "qcom,geni-spi"; + reg = <0 0x00a8c000 0 0x4000>; + clocks = <&gcc GCC_QUPV3_WRAP1_S3_CLK>; + clock-names = "se"; + interrupts = ; + interconnects = <&qup_virt MASTER_QUP_CORE_1 0 &qup_virt SLAVE_QUP_CORE_1 0>, + <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_1 0>; + interconnect-names = "qup-core", "qup-config"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + uart11: serial@a8c000 { + compatible = "qcom,geni-uart"; + reg = <0 0x00a8c000 0 0x4000>; + clocks = <&gcc GCC_QUPV3_WRAP1_S3_CLK>; + clock-names = "se"; + interrupts = ; + interconnects = <&qup_virt MASTER_QUP_CORE_1 0 &qup_virt SLAVE_QUP_CORE_1 0>, + <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_1 0>; + interconnect-names = "qup-core", "qup-config"; + status = "disabled"; + }; + + i2c12: i2c@a90000 { + compatible = "qcom,geni-i2c"; + reg = <0 0x00a90000 0 0x4000>; + clocks = <&gcc GCC_QUPV3_WRAP1_S4_CLK>; + clock-names = "se"; + interrupts = ; + interconnects = <&qup_virt MASTER_QUP_CORE_1 0 &qup_virt SLAVE_QUP_CORE_1 0>, + <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_1 0>, + <&aggre2_noc MASTER_QUP_1 0 &mc_virt SLAVE_EBI_CH0 0>; + interconnect-names = "qup-core", "qup-config", "qup-memory"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + spi12: spi@a90000 { + compatible = "qcom,geni-spi"; + reg = <0 0x00a90000 0 0x4000>; + clocks = <&gcc GCC_QUPV3_WRAP1_S4_CLK>; + clock-names = "se"; + interrupts = ; + interconnects = <&qup_virt MASTER_QUP_CORE_1 0 &qup_virt SLAVE_QUP_CORE_1 0>, + <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_1 0>; + interconnect-names = "qup-core", "qup-config"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + uart12: serial@a90000 { + compatible = "qcom,geni-uart"; + reg = <0 0x00a90000 0 0x4000>; + clocks = <&gcc GCC_QUPV3_WRAP1_S4_CLK>; + clock-names = "se"; + interrupts = ; + interconnects = <&qup_virt MASTER_QUP_CORE_1 0 &qup_virt SLAVE_QUP_CORE_1 0>, + <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_1 0>; + interconnect-names = "qup-core", "qup-config"; + status = "disabled"; + }; + + i2c16: i2c@a94000 { + compatible = "qcom,geni-i2c"; + reg = <0 0x00a94000 0 0x4000>; + clocks = <&gcc GCC_QUPV3_WRAP1_S5_CLK>; + clock-names = "se"; + interrupts = ; + interconnects = <&qup_virt MASTER_QUP_CORE_1 0 &qup_virt SLAVE_QUP_CORE_1 0>, + <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_1 0>, + <&aggre2_noc MASTER_QUP_1 0 &mc_virt SLAVE_EBI_CH0 0>; + interconnect-names = "qup-core", "qup-config", "qup-memory"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + spi16: spi@a94000 { + compatible = "qcom,geni-spi"; + reg = <0 0x00a94000 0 0x4000>; + clocks = <&gcc GCC_QUPV3_WRAP1_S5_CLK>; + clock-names = "se"; + interrupts = ; + interconnects = <&qup_virt MASTER_QUP_CORE_1 0 &qup_virt SLAVE_QUP_CORE_1 0>, + <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_1 0>; + interconnect-names = "qup-core", "qup-config"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + uart16: serial@a94000 { + compatible = "qcom,geni-uart"; + reg = <0 0x00a94000 0 0x4000>; + clocks = <&gcc GCC_QUPV3_WRAP1_S5_CLK>; + clock-names = "se"; + interrupts = ; + interconnects = <&qup_virt MASTER_QUP_CORE_1 0 &qup_virt SLAVE_QUP_CORE_1 0>, + <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_1 0>; + interconnect-names = "qup-core", "qup-config"; + status = "disabled"; + }; + }; + + qupv3_id_2: geniqup@cc0000 { + compatible = "qcom,geni-se-qup"; + reg = <0x0 0x00cc0000 0x0 0x6000>; + clocks = <&gcc GCC_QUPV3_WRAP_2_M_AHB_CLK>, + <&gcc GCC_QUPV3_WRAP_2_S_AHB_CLK>; + clock-names = "m-ahb", "s-ahb"; + #address-cells = <2>; + #size-cells = <2>; + ranges; + iommus = <&apps_smmu 0x7a3 0>; + status = "disabled"; + + i2c17: i2c@c80000 { + compatible = "qcom,geni-i2c"; + reg = <0 0x00c80000 0 0x4000>; + clocks = <&gcc GCC_QUPV3_WRAP2_S0_CLK>; + clock-names = "se"; + interrupts = ; + interconnects = <&qup_virt MASTER_QUP_CORE_2 0 &qup_virt SLAVE_QUP_CORE_2 0>, + <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_2 0>, + <&aggre2_noc MASTER_QUP_2 0 &mc_virt SLAVE_EBI_CH0 0>; + interconnect-names = "qup-core", "qup-config", "qup-memory"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + spi17: spi@c80000 { + compatible = "qcom,geni-spi"; + reg = <0 0x00c80000 0 0x4000>; + clocks = <&gcc GCC_QUPV3_WRAP2_S0_CLK>; + clock-names = "se"; + interrupts = ; + interconnects = <&qup_virt MASTER_QUP_CORE_2 0 &qup_virt SLAVE_QUP_CORE_2 0>, + <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_2 0>; + interconnect-names = "qup-core", "qup-config"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + uart17: serial@c80000 { + compatible = "qcom,geni-uart"; + reg = <0 0x00c80000 0 0x4000>; + clocks = <&gcc GCC_QUPV3_WRAP2_S0_CLK>; + clock-names = "se"; + interrupts = ; + interconnects = <&qup_virt MASTER_QUP_CORE_2 0 &qup_virt SLAVE_QUP_CORE_2 0>, + <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_2 0>; + interconnect-names = "qup-core", "qup-config"; + status = "disabled"; + }; + + i2c18: i2c@c84000 { + compatible = "qcom,geni-i2c"; + reg = <0 0x00c84000 0 0x4000>; + clocks = <&gcc GCC_QUPV3_WRAP2_S1_CLK>; + clock-names = "se"; + interrupts = ; + interconnects = <&qup_virt MASTER_QUP_CORE_2 0 &qup_virt SLAVE_QUP_CORE_2 0>, + <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_2 0>, + <&aggre2_noc MASTER_QUP_2 0 &mc_virt SLAVE_EBI_CH0 0>; + interconnect-names = "qup-core", "qup-config", "qup-memory"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + spi18: spi@c84000 { + compatible = "qcom,geni-spi"; + reg = <0 0x00c84000 0 0x4000>; + clocks = <&gcc GCC_QUPV3_WRAP2_S1_CLK>; + clock-names = "se"; + interrupts = ; + interconnects = <&qup_virt MASTER_QUP_CORE_2 0 &qup_virt SLAVE_QUP_CORE_2 0>, + <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_2 0>; + interconnect-names = "qup-core", "qup-config"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + uart18: serial@c84000 { + compatible = "qcom,geni-uart"; + reg = <0 0x00c84000 0 0x4000>; + clocks = <&gcc GCC_QUPV3_WRAP2_S1_CLK>; + clock-names = "se"; + interrupts = ; + interconnects = <&qup_virt MASTER_QUP_CORE_2 0 &qup_virt SLAVE_QUP_CORE_2 0>, + <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_2 0>; + interconnect-names = "qup-core", "qup-config"; + status = "disabled"; + }; + + i2c19: i2c@c88000 { + compatible = "qcom,geni-i2c"; + reg = <0 0x00c88000 0 0x4000>; + clocks = <&gcc GCC_QUPV3_WRAP2_S2_CLK>; + clock-names = "se"; + interrupts = ; + interconnects = <&qup_virt MASTER_QUP_CORE_2 0 &qup_virt SLAVE_QUP_CORE_2 0>, + <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_2 0>, + <&aggre2_noc MASTER_QUP_2 0 &mc_virt SLAVE_EBI_CH0 0>; + interconnect-names = "qup-core", "qup-config", "qup-memory"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + spi19: spi@c88000 { + compatible = "qcom,geni-spi"; + reg = <0 0x00c88000 0 0x4000>; + clocks = <&gcc GCC_QUPV3_WRAP2_S2_CLK>; + clock-names = "se"; + interrupts = ; + interconnects = <&qup_virt MASTER_QUP_CORE_2 0 &qup_virt SLAVE_QUP_CORE_2 0>, + <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_2 0>; + interconnect-names = "qup-core", "qup-config"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + uart19: serial@c88000 { + compatible = "qcom,geni-uart"; + reg = <0 0x00c88000 0 0x4000>; + clocks = <&gcc GCC_QUPV3_WRAP2_S2_CLK>; + clock-names = "se"; + interrupts = ; + interconnects = <&qup_virt MASTER_QUP_CORE_2 0 &qup_virt SLAVE_QUP_CORE_2 0>, + <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_2 0>; + interconnect-names = "qup-core", "qup-config"; + status = "disabled"; + }; + + i2c13: i2c@c8c000 { + compatible = "qcom,geni-i2c"; + reg = <0 0x00c8c000 0 0x4000>; + clocks = <&gcc GCC_QUPV3_WRAP2_S3_CLK>; + clock-names = "se"; + interrupts = ; + interconnects = <&qup_virt MASTER_QUP_CORE_2 0 &qup_virt SLAVE_QUP_CORE_2 0>, + <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_2 0>, + <&aggre2_noc MASTER_QUP_2 0 &mc_virt SLAVE_EBI_CH0 0>; + interconnect-names = "qup-core", "qup-config", "qup-memory"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + spi13: spi@c8c000 { + compatible = "qcom,geni-spi"; + reg = <0 0x00c8c000 0 0x4000>; + clocks = <&gcc GCC_QUPV3_WRAP2_S3_CLK>; + clock-names = "se"; + interrupts = ; + interconnects = <&qup_virt MASTER_QUP_CORE_2 0 &qup_virt SLAVE_QUP_CORE_2 0>, + <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_2 0>; + interconnect-names = "qup-core", "qup-config"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + uart13: serial@c8c000 { + compatible = "qcom,geni-uart"; + reg = <0 0x00c8c000 0 0x4000>; + clocks = <&gcc GCC_QUPV3_WRAP2_S3_CLK>; + clock-names = "se"; + interrupts = ; + interconnects = <&qup_virt MASTER_QUP_CORE_2 0 &qup_virt SLAVE_QUP_CORE_2 0>, + <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_2 0>; + interconnect-names = "qup-core", "qup-config"; + status = "disabled"; + }; + + i2c14: i2c@c90000 { + compatible = "qcom,geni-i2c"; + reg = <0 0x00c90000 0 0x4000>; + clocks = <&gcc GCC_QUPV3_WRAP2_S4_CLK>; + clock-names = "se"; + interrupts = ; + interconnects = <&qup_virt MASTER_QUP_CORE_2 0 &qup_virt SLAVE_QUP_CORE_2 0>, + <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_2 0>, + <&aggre2_noc MASTER_QUP_2 0 &mc_virt SLAVE_EBI_CH0 0>; + interconnect-names = "qup-core", "qup-config", "qup-memory"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + spi14: spi@c90000 { + compatible = "qcom,geni-spi"; + reg = <0 0x00c90000 0 0x4000>; + clocks = <&gcc GCC_QUPV3_WRAP2_S4_CLK>; + clock-names = "se"; + interrupts = ; + interconnects = <&qup_virt MASTER_QUP_CORE_2 0 &qup_virt SLAVE_QUP_CORE_2 0>, + <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_2 0>; + interconnect-names = "qup-core", "qup-config"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + uart14: serial@c90000 { + compatible = "qcom,geni-uart"; + reg = <0 0x00c90000 0 0x4000>; + clocks = <&gcc GCC_QUPV3_WRAP2_S4_CLK>; + clock-names = "se"; + interrupts = ; + interconnects = <&qup_virt MASTER_QUP_CORE_2 0 &qup_virt SLAVE_QUP_CORE_2 0>, + <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_2 0>; + interconnect-names = "qup-core", "qup-config"; + status = "disabled"; + }; + + i2c15: i2c@c94000 { + compatible = "qcom,geni-i2c"; + reg = <0 0x00c94000 0 0x4000>; + clocks = <&gcc GCC_QUPV3_WRAP2_S5_CLK>; + clock-names = "se"; + interrupts = ; + interconnects = <&qup_virt MASTER_QUP_CORE_2 0 &qup_virt SLAVE_QUP_CORE_2 0>, + <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_2 0>, + <&aggre2_noc MASTER_QUP_2 0 &mc_virt SLAVE_EBI_CH0 0>; + interconnect-names = "qup-core", "qup-config", "qup-memory"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + spi15: spi@c94000 { + compatible = "qcom,geni-spi"; + reg = <0 0x00c94000 0 0x4000>; + clocks = <&gcc GCC_QUPV3_WRAP2_S5_CLK>; + clock-names = "se"; + interrupts = ; + interconnects = <&qup_virt MASTER_QUP_CORE_2 0 &qup_virt SLAVE_QUP_CORE_2 0>, + <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_2 0>; + interconnect-names = "qup-core", "qup-config"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + uart15: serial@c94000 { + compatible = "qcom,geni-uart"; + reg = <0 0x00c94000 0 0x4000>; + clocks = <&gcc GCC_QUPV3_WRAP2_S5_CLK>; + clock-names = "se"; + interrupts = ; + interconnects = <&qup_virt MASTER_QUP_CORE_2 0 &qup_virt SLAVE_QUP_CORE_2 0>, + <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_2 0>; + interconnect-names = "qup-core", "qup-config"; + status = "disabled"; + }; + }; + + config_noc: interconnect@1500000 { + compatible = "qcom,sc8180x-config-noc"; + reg = <0 0x01500000 0 0x7400>; + #interconnect-cells = <2>; + qcom,bcm-voters = <&apps_bcm_voter>; + }; + + system_noc: interconnect@1620000 { + compatible = "qcom,sc8180x-system-noc"; + reg = <0 0x01620000 0 0x19400>; + #interconnect-cells = <2>; + qcom,bcm-voters = <&apps_bcm_voter>; + }; + + aggre1_noc: interconnect@16e0000 { + compatible = "qcom,sc8180x-aggre1-noc"; + reg = <0 0x016e0000 0 0xd080>; + #interconnect-cells = <2>; + qcom,bcm-voters = <&apps_bcm_voter>; + }; + + aggre2_noc: interconnect@1700000 { + compatible = "qcom,sc8180x-aggre2-noc"; + reg = <0 0x01700000 0 0x20000>; + #interconnect-cells = <2>; + qcom,bcm-voters = <&apps_bcm_voter>; + }; + + compute_noc: interconnect@1720000 { + compatible = "qcom,sc8180x-compute-noc"; + reg = <0 0x01720000 0 0x7000>; + #interconnect-cells = <2>; + qcom,bcm-voters = <&apps_bcm_voter>; + }; + + mmss_noc: interconnect@1740000 { + compatible = "qcom,sc8180x-mmss-noc"; + reg = <0 0x01740000 0 0x1c100>; + #interconnect-cells = <2>; + qcom,bcm-voters = <&apps_bcm_voter>; + }; + + pcie0: pci@1c00000 { + compatible = "qcom,pcie-sc8180x"; + reg = <0 0x01c00000 0 0x3000>, + <0 0x60000000 0 0xf1d>, + <0 0x60000f20 0 0xa8>, + <0 0x60001000 0 0x1000>, + <0 0x60100000 0 0x100000>; + reg-names = "parf", + "dbi", + "elbi", + "atu", + "config"; + device_type = "pci"; + linux,pci-domain = <0>; + bus-range = <0x00 0xff>; + num-lanes = <2>; + + #address-cells = <3>; + #size-cells = <2>; + + ranges = <0x01000000 0x0 0x60200000 0x0 0x60200000 0x0 0x100000>, + <0x02000000 0x0 0x60300000 0x0 0x60300000 0x0 0x3d00000>; + + interrupts = ; + interrupt-names = "msi"; + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 0 0x7>; + interrupt-map = <0 0 0 1 &intc 0 149 IRQ_TYPE_LEVEL_HIGH>, /* int_a */ + <0 0 0 2 &intc 0 150 IRQ_TYPE_LEVEL_HIGH>, /* int_b */ + <0 0 0 3 &intc 0 151 IRQ_TYPE_LEVEL_HIGH>, /* int_c */ + <0 0 0 4 &intc 0 152 IRQ_TYPE_LEVEL_HIGH>; /* int_d */ + + clocks = <&gcc GCC_PCIE_0_PIPE_CLK>, + <&gcc GCC_PCIE_0_AUX_CLK>, + <&gcc GCC_PCIE_0_CFG_AHB_CLK>, + <&gcc GCC_PCIE_0_MSTR_AXI_CLK>, + <&gcc GCC_PCIE_0_SLV_AXI_CLK>, + <&gcc GCC_PCIE_0_SLV_Q2A_AXI_CLK>, + <&gcc GCC_PCIE_0_CLKREF_CLK>, + <&gcc GCC_AGGRE_NOC_PCIE_TBU_CLK>; + clock-names = "pipe", + "aux", + "cfg", + "bus_master", + "bus_slave", + "slave_q2a", + "ref", + "tbu"; + + assigned-clocks = <&gcc GCC_PCIE_0_AUX_CLK>; + assigned-clock-rates = <19200000>; + + iommus = <&apps_smmu 0x1d80 0x7f>; + iommu-map = <0x0 &apps_smmu 0x1d80 0x1>, + <0x100 &apps_smmu 0x1d81 0x1>; + + resets = <&gcc GCC_PCIE_0_BCR>; + reset-names = "pci"; + + power-domains = <&gcc PCIE_0_GDSC>; + + interconnects = <&aggre2_noc MASTER_PCIE 0 &mc_virt SLAVE_EBI_CH0 0>, + <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_PCIE_0 0>; + interconnect-names = "pcie-mem", "cpu-pcie"; + + phys = <&pcie0_lane>; + phy-names = "pciephy"; + + status = "disabled"; + }; + + pcie0_phy: phy-wrapper@1c06000 { + compatible = "qcom,sc8180x-qmp-pcie-phy"; + reg = <0 0x1c06000 0 0x1c0>; + #address-cells = <2>; + #size-cells = <2>; + ranges; + clocks = <&gcc GCC_PCIE_PHY_AUX_CLK>, + <&gcc GCC_PCIE_0_CFG_AHB_CLK>, + <&gcc GCC_PCIE_0_CLKREF_CLK>, + <&gcc GCC_PCIE1_PHY_REFGEN_CLK>; + clock-names = "aux", "cfg_ahb", "ref", "refgen"; + + resets = <&gcc GCC_PCIE_0_PHY_BCR>; + reset-names = "phy"; + + assigned-clocks = <&gcc GCC_PCIE0_PHY_REFGEN_CLK>; + assigned-clock-rates = <100000000>; + + status = "disabled"; + + pcie0_lane: phy@1c06200 { + reg = <0 0x1c06200 0 0x170>, /* tx0 */ + <0 0x1c06400 0 0x200>, /* rx0 */ + <0 0x1c06a00 0 0x1f0>, /* pcs */ + <0 0x1c06600 0 0x170>, /* tx1 */ + <0 0x1c06800 0 0x200>, /* rx1 */ + <0 0x1c06e00 0 0xf4>; /* pcs_com */ + clocks = <&gcc GCC_PCIE_0_PIPE_CLK>; + clock-names = "pipe0"; + + #clock-cells = <0>; + clock-output-names = "pcie_0_pipe_clk"; + #phy-cells = <0>; + }; + }; + + pcie3: pci@1c08000 { + compatible = "qcom,pcie-sc8180x"; + reg = <0 0x01c08000 0 0x3000>, + <0 0x40000000 0 0xf1d>, + <0 0x40000f20 0 0xa8>, + <0 0x40001000 0 0x1000>, + <0 0x40100000 0 0x100000>; + reg-names = "parf", + "dbi", + "elbi", + "atu", + "config"; + device_type = "pci"; + linux,pci-domain = <3>; + bus-range = <0x00 0xff>; + num-lanes = <2>; + + #address-cells = <3>; + #size-cells = <2>; + + ranges = <0x01000000 0x0 0x40200000 0x0 0x40200000 0x0 0x100000>, + <0x02000000 0x0 0x40300000 0x0 0x40300000 0x0 0x1fd00000>; + + interrupts = ; + interrupt-names = "msi"; + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 0 0x7>; + interrupt-map = <0 0 0 1 &intc 0 434 IRQ_TYPE_LEVEL_HIGH>, /* int_a */ + <0 0 0 2 &intc 0 435 IRQ_TYPE_LEVEL_HIGH>, /* int_b */ + <0 0 0 3 &intc 0 438 IRQ_TYPE_LEVEL_HIGH>, /* int_c */ + <0 0 0 4 &intc 0 439 IRQ_TYPE_LEVEL_HIGH>; /* int_d */ + + clocks = <&gcc GCC_PCIE_3_PIPE_CLK>, + <&gcc GCC_PCIE_3_AUX_CLK>, + <&gcc GCC_PCIE_3_CFG_AHB_CLK>, + <&gcc GCC_PCIE_3_MSTR_AXI_CLK>, + <&gcc GCC_PCIE_3_SLV_AXI_CLK>, + <&gcc GCC_PCIE_3_SLV_Q2A_AXI_CLK>, + <&gcc GCC_PCIE_3_CLKREF_CLK>, + <&gcc GCC_AGGRE_NOC_PCIE_TBU_CLK>; + clock-names = "pipe", + "aux", + "cfg", + "bus_master", + "bus_slave", + "slave_q2a", + "ref", + "tbu"; + + assigned-clocks = <&gcc GCC_PCIE_3_AUX_CLK>; + assigned-clock-rates = <19200000>; + + iommus = <&apps_smmu 0x1e00 0x7f>; + iommu-map = <0x0 &apps_smmu 0x1e00 0x1>, + <0x100 &apps_smmu 0x1e01 0x1>; + + resets = <&gcc GCC_PCIE_3_BCR>; + reset-names = "pci"; + + power-domains = <&gcc PCIE_3_GDSC>; + + interconnects = <&aggre2_noc MASTER_PCIE_3 0 &mc_virt SLAVE_EBI_CH0 0>, + <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_PCIE_0 0>; + interconnect-names = "pcie-mem", "cpu-pcie"; + + phys = <&pcie3_lane>; + phy-names = "pciephy"; + + status = "disabled"; + }; + + pcie3_phy: phy-wrapper@1c0c000 { + compatible = "qcom,sc8180x-qmp-pcie-phy"; + reg = <0 0x1c0c000 0 0x1c0>; + #address-cells = <2>; + #size-cells = <2>; + ranges; + clocks = <&gcc GCC_PCIE_PHY_AUX_CLK>, + <&gcc GCC_PCIE_3_CFG_AHB_CLK>, + <&gcc GCC_PCIE_3_CLKREF_CLK>, + <&gcc GCC_PCIE2_PHY_REFGEN_CLK>; + clock-names = "aux", "cfg_ahb", "ref", "refgen"; + + resets = <&gcc GCC_PCIE_3_PHY_BCR>; + reset-names = "phy"; + + assigned-clocks = <&gcc GCC_PCIE3_PHY_REFGEN_CLK>; + assigned-clock-rates = <100000000>; + + status = "disabled"; + + pcie3_lane: phy@1c0c200 { + reg = <0 0x1c0c200 0 0x170>, /* tx0 */ + <0 0x1c0c400 0 0x200>, /* rx0 */ + <0 0x1c0ca00 0 0x1f0>, /* pcs */ + <0 0x1c0c600 0 0x170>, /* tx1 */ + <0 0x1c0c800 0 0x200>, /* rx1 */ + <0 0x1c0ce00 0 0xf4>; /* pcs_com */ + clocks = <&gcc GCC_PCIE_3_PIPE_CLK>; + clock-names = "pipe0"; + + #clock-cells = <0>; + clock-output-names = "pcie_3_pipe_clk"; + #phy-cells = <0>; + }; + }; + + pcie1: pci@1c10000 { + compatible = "qcom,pcie-sc8180x"; + reg = <0 0x01c10000 0 0x3000>, + <0 0x68000000 0 0xf1d>, + <0 0x68000f20 0 0xa8>, + <0 0x68001000 0 0x1000>, + <0 0x68100000 0 0x100000>; + reg-names = "parf", + "dbi", + "elbi", + "atu", + "config"; + device_type = "pci"; + linux,pci-domain = <1>; + bus-range = <0x00 0xff>; + num-lanes = <2>; + + #address-cells = <3>; + #size-cells = <2>; + + ranges = <0x01000000 0x0 0x68200000 0x0 0x68200000 0x0 0x100000>, + <0x02000000 0x0 0x68300000 0x0 0x68300000 0x0 0x3d00000>; + + interrupts = ; + interrupt-names = "msi"; + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 0 0x7>; + interrupt-map = <0 0 0 1 &intc 0 747 IRQ_TYPE_LEVEL_HIGH>, /* int_a */ + <0 0 0 2 &intc 0 746 IRQ_TYPE_LEVEL_HIGH>, /* int_b */ + <0 0 0 3 &intc 0 745 IRQ_TYPE_LEVEL_HIGH>, /* int_c */ + <0 0 0 4 &intc 0 744 IRQ_TYPE_LEVEL_HIGH>; /* int_d */ + + clocks = <&gcc GCC_PCIE_1_PIPE_CLK>, + <&gcc GCC_PCIE_1_AUX_CLK>, + <&gcc GCC_PCIE_1_CFG_AHB_CLK>, + <&gcc GCC_PCIE_1_MSTR_AXI_CLK>, + <&gcc GCC_PCIE_1_SLV_AXI_CLK>, + <&gcc GCC_PCIE_1_SLV_Q2A_AXI_CLK>, + <&gcc GCC_PCIE_1_CLKREF_CLK>, + <&gcc GCC_AGGRE_NOC_PCIE_TBU_CLK>; + clock-names = "pipe", + "aux", + "cfg", + "bus_master", + "bus_slave", + "slave_q2a", + "ref", + "tbu"; + + assigned-clocks = <&gcc GCC_PCIE_1_AUX_CLK>; + assigned-clock-rates = <19200000>; + + iommus = <&apps_smmu 0x1c80 0x7f>; + iommu-map = <0x0 &apps_smmu 0x1c80 0x1>, + <0x100 &apps_smmu 0x1c81 0x1>; + + resets = <&gcc GCC_PCIE_1_BCR>; + reset-names = "pci"; + + power-domains = <&gcc PCIE_1_GDSC>; + + interconnects = <&aggre2_noc MASTER_PCIE_1 0 &mc_virt SLAVE_EBI_CH0 0>, + <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_PCIE_0 0>; + interconnect-names = "pcie-mem", "cpu-pcie"; + + phys = <&pcie1_lane>; + phy-names = "pciephy"; + + status = "disabled"; + }; + + pcie1_phy: phy-wrapper@1c16000 { + compatible = "qcom,sc8180x-qmp-pcie-phy"; + reg = <0 0x1c16000 0 0x1c0>; + #address-cells = <2>; + #size-cells = <2>; + ranges; + clocks = <&gcc GCC_PCIE_PHY_AUX_CLK>, + <&gcc GCC_PCIE_1_CFG_AHB_CLK>, + <&gcc GCC_PCIE_1_CLKREF_CLK>, + <&gcc GCC_PCIE1_PHY_REFGEN_CLK>; + clock-names = "aux", "cfg_ahb", "ref", "refgen"; + + resets = <&gcc GCC_PCIE_1_PHY_BCR>; + reset-names = "phy"; + + assigned-clocks = <&gcc GCC_PCIE1_PHY_REFGEN_CLK>; + assigned-clock-rates = <100000000>; + + status = "disabled"; + + pcie1_lane: phy@1c0e200 { + reg = <0 0x1c16200 0 0x170>, /* tx0 */ + <0 0x1c16400 0 0x200>, /* rx0 */ + <0 0x1c16a00 0 0x1f0>, /* pcs */ + <0 0x1c16600 0 0x170>, /* tx1 */ + <0 0x1c16800 0 0x200>, /* rx1 */ + <0 0x1c16e00 0 0xf4>; /* pcs_com */ + clocks = <&gcc GCC_PCIE_1_PIPE_CLK>; + clock-names = "pipe0"; + #clock-cells = <0>; + clock-output-names = "pcie_1_pipe_clk"; + + #phy-cells = <0>; + }; + }; + + pcie2: pci@1c18000 { + compatible = "qcom,pcie-sc8180x"; + reg = <0 0x01c18000 0 0x3000>, + <0 0x70000000 0 0xf1d>, + <0 0x70000f20 0 0xa8>, + <0 0x70001000 0 0x1000>, + <0 0x70100000 0 0x100000>; + reg-names = "parf", + "dbi", + "elbi", + "atu", + "config"; + device_type = "pci"; + linux,pci-domain = <2>; + bus-range = <0x00 0xff>; + num-lanes = <4>; + + #address-cells = <3>; + #size-cells = <2>; + + ranges = <0x01000000 0x0 0x70200000 0x0 0x70200000 0x0 0x100000>, + <0x02000000 0x0 0x70300000 0x0 0x70300000 0x0 0x3d00000>; + + interrupts = ; + interrupt-names = "msi"; + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 0 0x7>; + interrupt-map = <0 0 0 1 &intc 0 663 IRQ_TYPE_LEVEL_HIGH>, /* int_a */ + <0 0 0 2 &intc 0 662 IRQ_TYPE_LEVEL_HIGH>, /* int_b */ + <0 0 0 3 &intc 0 661 IRQ_TYPE_LEVEL_HIGH>, /* int_c */ + <0 0 0 4 &intc 0 660 IRQ_TYPE_LEVEL_HIGH>; /* int_d */ + + clocks = <&gcc GCC_PCIE_2_PIPE_CLK>, + <&gcc GCC_PCIE_2_AUX_CLK>, + <&gcc GCC_PCIE_2_CFG_AHB_CLK>, + <&gcc GCC_PCIE_2_MSTR_AXI_CLK>, + <&gcc GCC_PCIE_2_SLV_AXI_CLK>, + <&gcc GCC_PCIE_2_SLV_Q2A_AXI_CLK>, + <&gcc GCC_PCIE_2_CLKREF_CLK>, + <&gcc GCC_AGGRE_NOC_PCIE_TBU_CLK>; + clock-names = "pipe", + "aux", + "cfg", + "bus_master", + "bus_slave", + "slave_q2a", + "ref", + "tbu"; + + assigned-clocks = <&gcc GCC_PCIE_2_AUX_CLK>; + assigned-clock-rates = <19200000>; + + iommus = <&apps_smmu 0x1d00 0x7f>; + iommu-map = <0x0 &apps_smmu 0x1d00 0x1>, + <0x100 &apps_smmu 0x1d01 0x1>; + + resets = <&gcc GCC_PCIE_2_BCR>; + reset-names = "pci"; + + power-domains = <&gcc PCIE_2_GDSC>; + + interconnects = <&aggre2_noc MASTER_PCIE_2 0 &mc_virt SLAVE_EBI_CH0 0>, + <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_PCIE_0 0>; + interconnect-names = "pcie-mem", "cpu-pcie"; + + phys = <&pcie2_lane>; + phy-names = "pciephy"; + + status = "disabled"; + }; + + pcie2_phy: phy-wrapper@1c1c000 { + compatible = "qcom,sc8180x-qmp-pcie-phy"; + reg = <0 0x1c1c000 0 0x1c0>; + #address-cells = <2>; + #size-cells = <2>; + ranges; + clocks = <&gcc GCC_PCIE_PHY_AUX_CLK>, + <&gcc GCC_PCIE_2_CFG_AHB_CLK>, + <&gcc GCC_PCIE_2_CLKREF_CLK>, + <&gcc GCC_PCIE2_PHY_REFGEN_CLK>; + clock-names = "aux", "cfg_ahb", "ref", "refgen"; + + resets = <&gcc GCC_PCIE_2_PHY_BCR>; + reset-names = "phy"; + + assigned-clocks = <&gcc GCC_PCIE2_PHY_REFGEN_CLK>; + assigned-clock-rates = <100000000>; + + status = "disabled"; + + pcie2_lane: phy@1c0e200 { + reg = <0 0x1c1c200 0 0x170>, /* tx0 */ + <0 0x1c1c400 0 0x200>, /* rx0 */ + <0 0x1c1ca00 0 0x1f0>, /* pcs */ + <0 0x1c1c600 0 0x170>, /* tx1 */ + <0 0x1c1c800 0 0x200>, /* rx1 */ + <0 0x1c1ce00 0 0xf4>; /* pcs_com */ + clocks = <&gcc GCC_PCIE_2_PIPE_CLK>; + clock-names = "pipe0"; + + #clock-cells = <0>; + clock-output-names = "pcie_2_pipe_clk"; + + #phy-cells = <0>; + }; + }; + + ufs_mem_hc: ufshc@1d84000 { + compatible = "qcom,sc8180x-ufshc", "qcom,ufshc", + "jedec,ufs-2.0"; + reg = <0 0x01d84000 0 0x2500>; + interrupts = ; + phys = <&ufs_mem_phy_lanes>; + phy-names = "ufsphy"; + lanes-per-direction = <2>; + #reset-cells = <1>; + resets = <&gcc GCC_UFS_PHY_BCR>; + reset-names = "rst"; + + iommus = <&apps_smmu 0x300 0>; + + clocks = <&gcc GCC_UFS_PHY_AXI_CLK>, + <&gcc GCC_AGGRE_UFS_PHY_AXI_CLK>, + <&gcc GCC_UFS_PHY_AHB_CLK>, + <&gcc GCC_UFS_PHY_UNIPRO_CORE_CLK>, + <&rpmhcc RPMH_CXO_CLK>, + <&gcc GCC_UFS_PHY_TX_SYMBOL_0_CLK>, + <&gcc GCC_UFS_PHY_RX_SYMBOL_0_CLK>, + <&gcc GCC_UFS_PHY_RX_SYMBOL_1_CLK>; + clock-names = "core_clk", + "bus_aggr_clk", + "iface_clk", + "core_clk_unipro", + "ref_clk", + "tx_lane0_sync_clk", + "rx_lane0_sync_clk", + "rx_lane1_sync_clk"; + freq-table-hz = <37500000 300000000>, + <0 0>, + <0 0>, + <37500000 300000000>, + <0 0>, + <0 0>, + <0 0>, + <0 0>; + + status = "disabled"; + }; + + ufs_mem_phy: phy-wrapper@1d87000 { + compatible = "qcom,sc8180x-qmp-ufs-phy"; + reg = <0 0x01d87000 0 0x1c0>; + #address-cells = <2>; + #size-cells = <2>; + ranges; + clocks = <&rpmhcc RPMH_CXO_CLK>, + <&gcc GCC_UFS_PHY_PHY_AUX_CLK>; + clock-names = "ref", + "ref_aux"; + + resets = <&ufs_mem_hc 0>; + reset-names = "ufsphy"; + status = "disabled"; + + ufs_mem_phy_lanes: phy@1d87400 { + reg = <0 0x01d87400 0 0x108>, + <0 0x01d87600 0 0x1e0>, + <0 0x01d87c00 0 0x1dc>, + <0 0x01d87800 0 0x108>, + <0 0x01d87a00 0 0x1e0>; + #phy-cells = <0>; + }; + }; + + ipa_virt: interconnect@1e00000 { + compatible = "qcom,sc8180x-ipa-virt"; + reg = <0 0x01e00000 0 0x1000>; + #interconnect-cells = <2>; + qcom,bcm-voters = <&apps_bcm_voter>; + }; + + tcsr_mutex: hwlock@1f40000 { + compatible = "qcom,tcsr-mutex"; + reg = <0x0 0x01f40000 0x0 0x40000>; + #hwlock-cells = <1>; + }; + + gpu: gpu@2c00000 { + compatible = "qcom,adreno-680.1", "qcom,adreno"; + #stream-id-cells = <16>; + + reg = <0 0x02c00000 0 0x40000>; + reg-names = "kgsl_3d0_reg_memory"; + + interrupts = ; + + iommus = <&adreno_smmu 0 0xc01>; + + operating-points-v2 = <&gpu_opp_table>; + + interconnects = <&gem_noc MASTER_GRAPHICS_3D 0 &mc_virt SLAVE_EBI_CH0 0>; + interconnect-names = "gfx-mem"; + + qcom,gmu = <&gmu>; + status = "disabled"; + + gpu_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-514000000 { + opp-hz = /bits/ 64 <514000000>; + opp-level = ; + }; + + opp-500000000 { + opp-hz = /bits/ 64 <500000000>; + opp-level = ; + }; + + opp-461000000 { + opp-hz = /bits/ 64 <461000000>; + opp-level = ; + }; + + opp-405000000 { + opp-hz = /bits/ 64 <405000000>; + opp-level = ; + }; + + opp-315000000 { + opp-hz = /bits/ 64 <315000000>; + opp-level = ; + }; + + opp-256000000 { + opp-hz = /bits/ 64 <256000000>; + opp-level = ; + }; + + opp-177000000 { + opp-hz = /bits/ 64 <177000000>; + opp-level = ; + }; + }; + }; + + gmu: gmu@2c6a000 { + compatible="qcom,adreno-gmu-680.1", "qcom,adreno-gmu"; + + reg = <0 0x02c6a000 0 0x30000>, + <0 0x0b290000 0 0x10000>, + <0 0x0b490000 0 0x10000>; + reg-names = "gmu", + "gmu_pdc", + "gmu_pdc_seq"; + + interrupts = , + ; + interrupt-names = "hfi", "gmu"; + + clocks = <&gpucc GPU_CC_AHB_CLK>, + <&gpucc GPU_CC_CX_GMU_CLK>, + <&gpucc GPU_CC_CXO_CLK>, + <&gcc GCC_DDRSS_GPU_AXI_CLK>, + <&gcc GCC_GPU_MEMNOC_GFX_CLK>; + clock-names = "ahb", "gmu", "cxo", "axi", "memnoc"; + + power-domains = <&gpucc GPU_CX_GDSC>, + <&gpucc GPU_GX_GDSC>; + power-domain-names = "cx", "gx"; + + iommus = <&adreno_smmu 5 0xc00>; + + operating-points-v2 = <&gmu_opp_table>; + + gmu_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-200000000 { + opp-hz = /bits/ 64 <200000000>; + opp-level = ; + }; + + opp-500000000 { + opp-hz = /bits/ 64 <500000000>; + opp-level = ; + }; + }; + }; + + gpucc: clock-controller@2c90000 { + compatible = "qcom,sc8180x-gpucc"; + reg = <0 0x02c90000 0 0x9000>; + clocks = <&rpmhcc RPMH_CXO_CLK>, + <&gcc GCC_GPU_GPLL0_CLK_SRC>, + <&gcc GCC_GPU_GPLL0_DIV_CLK_SRC>; + clock-names = "bi_tcxo", + "gcc_gpu_gpll0_clk_src", + "gcc_gpu_gpll0_div_clk_src"; + #clock-cells = <1>; + #reset-cells = <1>; + #power-domain-cells = <1>; + }; + + adreno_smmu: iommu@2ca0000 { + compatible = "qcom,sc8180x-smmu-500", "qcom,adreno-smmu", + "qcom,smmu-500", "arm,mmu-500"; + reg = <0 0x02ca0000 0 0x10000>; + #iommu-cells = <2>; + #global-interrupts = <1>; + interrupts = , + , + , + , + , + , + , + , + ; + clocks = <&gpucc GPU_CC_AHB_CLK>, + <&gcc GCC_GPU_MEMNOC_GFX_CLK>, + <&gcc GCC_GPU_SNOC_DVM_GFX_CLK>; + clock-names = "ahb", "bus", "iface"; + + power-domains = <&gpucc GPU_CX_GDSC>; + }; + + tlmm: pinctrl@3100000 { + compatible = "qcom,sc8180x-tlmm"; + reg = <0 0x03100000 0 0x300000>, + <0 0x03500000 0 0x700000>, + <0 0x03d00000 0 0x300000>; + reg-names = "west", "east", "south"; + interrupts = ; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + gpio-ranges = <&tlmm 0 0 191>; + wakeup-parent = <&pdc>; + }; + + remoteproc_mpss: remoteproc@4080000 { + compatible = "qcom,sc8180x-mpss-pas"; + reg = <0x0 0x04080000 0x0 0x4040>; + + interrupts-extended = <&intc GIC_SPI 266 IRQ_TYPE_EDGE_RISING>, + <&modem_smp2p_in 0 IRQ_TYPE_EDGE_RISING>, + <&modem_smp2p_in 1 IRQ_TYPE_EDGE_RISING>, + <&modem_smp2p_in 2 IRQ_TYPE_EDGE_RISING>, + <&modem_smp2p_in 3 IRQ_TYPE_EDGE_RISING>, + <&modem_smp2p_in 7 IRQ_TYPE_EDGE_RISING>; + interrupt-names = "wdog", "fatal", "ready", "handover", + "stop-ack", "shutdown-ack"; + + clocks = <&rpmhcc RPMH_CXO_CLK>; + clock-names = "xo"; + + power-domains = <&rpmhpd SC8180X_CX>, + <&rpmhpd SC8180X_MSS>; + power-domain-names = "cx", "mss"; + + qcom,qmp = <&aoss_qmp>; + + qcom,smem-states = <&modem_smp2p_out 0>; + qcom,smem-state-names = "stop"; + + glink-edge { + interrupts = ; + label = "modem"; + qcom,remote-pid = <1>; + mboxes = <&apss_shared 12>; + }; + }; + + remoteproc_cdsp: remoteproc@8300000 { + compatible = "qcom,sc8180x-cdsp-pas"; + reg = <0x0 0x08300000 0x0 0x4040>; + + interrupts-extended = <&intc GIC_SPI 578 IRQ_TYPE_EDGE_RISING>, + <&cdsp_smp2p_in 0 IRQ_TYPE_EDGE_RISING>, + <&cdsp_smp2p_in 1 IRQ_TYPE_EDGE_RISING>, + <&cdsp_smp2p_in 2 IRQ_TYPE_EDGE_RISING>, + <&cdsp_smp2p_in 3 IRQ_TYPE_EDGE_RISING>; + interrupt-names = "wdog", "fatal", "ready", + "handover", "stop-ack"; + + clocks = <&rpmhcc RPMH_CXO_CLK>; + clock-names = "xo"; + + power-domains = <&rpmhpd SC8180X_CX>; + power-domain-names = "cx"; + + qcom,qmp = <&aoss_qmp>; + + qcom,smem-states = <&cdsp_smp2p_out 0>; + qcom,smem-state-names = "stop"; + + status = "disabled"; + + glink-edge { + interrupts = ; + label = "cdsp"; + qcom,remote-pid = <5>; + mboxes = <&apss_shared 4>; + }; + }; + + usb_prim_hsphy: phy@88e2000 { + compatible = "qcom,sc8180x-usb-hs-phy", + "qcom,usb-snps-hs-7nm-phy"; + reg = <0 0x088e2000 0 0x400>; + clocks = <&rpmhcc RPMH_CXO_CLK>; + clock-names = "ref"; + resets = <&gcc GCC_QUSB2PHY_PRIM_BCR>; + + #phy-cells = <0>; + + status = "disabled"; + }; + + usb_sec_hsphy: phy@88e3000 { + compatible = "qcom,sc8180x-usb-hs-phy", + "qcom,usb-snps-hs-7nm-phy"; + reg = <0 0x088e3000 0 0x400>; + clocks = <&rpmhcc RPMH_CXO_CLK>; + clock-names = "ref"; + resets = <&gcc GCC_QUSB2PHY_SEC_BCR>; + + #phy-cells = <0>; + + status = "disabled"; + }; + + usb_prim_qmpphy: phy@88e9000 { + compatible = "qcom,sc8180x-qmp-usb3-dp-phy"; + reg = <0 0x088e9000 0 0x18c>, + <0 0x088e8000 0 0x38>, + <0 0x088ea000 0 0x40>; + reg-names = "reg-base", "dp_com"; + clocks = <&gcc GCC_USB3_PRIM_PHY_AUX_CLK>, + <&rpmhcc RPMH_CXO_CLK>, + <&gcc GCC_USB3_PRIM_CLKREF_CLK>, + <&gcc GCC_USB3_PRIM_PHY_COM_AUX_CLK>; + clock-names = "aux", + "ref_clk_src", + "ref", + "com_aux"; + resets = <&gcc GCC_USB3_DP_PHY_PRIM_SP0_BCR>, + <&gcc GCC_USB3_PHY_PRIM_SP0_BCR>; + reset-names = "phy", "common"; + + #clock-cells = <1>; + #address-cells = <2>; + #size-cells = <2>; + ranges; + + status = "disabled"; + + usb_prim_ssphy: usb3-phy@88e9200 { + reg = <0 0x088e9200 0 0x200>, + <0 0x088e9400 0 0x200>, + <0 0x088e9c00 0 0x218>, + <0 0x088e9600 0 0x200>, + <0 0x088e9800 0 0x200>, + <0 0x088e9a00 0 0x100>; + #phy-cells = <0>; + clocks = <&gcc GCC_USB3_PRIM_PHY_PIPE_CLK>; + clock-names = "pipe0"; + clock-output-names = "usb3_prim_phy_pipe_clk_src"; + }; + + usb_prim_dpphy: dp-phy@88ea200 { + reg = <0 0x088ea200 0 0x200>, + <0 0x088ea400 0 0x200>, + <0 0x088eaa00 0 0x200>, + <0 0x088ea600 0 0x200>, + <0 0x088ea800 0 0x200>; + #clock-cells = <1>; + #phy-cells = <0>; + }; + }; + + usb_sec_qmpphy: phy@88ee000 { + compatible = "qcom,sc8180x-qmp-usb3-dp-phy"; + reg = <0 0x088ee000 0 0x18c>, + <0 0x088ed000 0 0x10>, + <0 0x088ef000 0 0x40>; + reg-names = "reg-base", "dp_com"; + clocks = <&gcc GCC_USB3_SEC_PHY_AUX_CLK>, + <&rpmhcc RPMH_CXO_CLK>, + <&gcc GCC_USB3_SEC_CLKREF_CLK>, + <&gcc GCC_USB3_SEC_PHY_COM_AUX_CLK>; + clock-names = "aux", + "ref_clk_src", + "ref", + "com_aux"; + resets = <&gcc GCC_USB3_DP_PHY_SEC_BCR>, + <&gcc GCC_USB3_PHY_SEC_BCR>; + reset-names = "phy", "common"; + + #clock-cells = <1>; + #address-cells = <2>; + #size-cells = <2>; + ranges; + + status = "disabled"; + + usb_sec_ssphy: usb3-phy@88e9200 { + reg = <0 0x088ee200 0 0x200>, + <0 0x088ee400 0 0x200>, + <0 0x088eec00 0 0x218>, + <0 0x088ee600 0 0x200>, + <0 0x088ee800 0 0x200>, + <0 0x088eea00 0 0x100>; + #phy-cells = <0>; + clocks = <&gcc GCC_USB3_SEC_PHY_PIPE_CLK>; + clock-names = "pipe0"; + clock-output-names = "usb3_sec_phy_pipe_clk_src"; + }; + + usb_sec_dpphy: dp-phy@88ef200 { + reg = <0 0x088ef200 0 0x200>, + <0 0x088ef400 0 0x200>, + <0 0x088efa00 0 0x200>, + <0 0x088ef600 0 0x200>, + <0 0x088ef800 0 0x200>; + #clock-cells = <1>; + #phy-cells = <0>; + clock-output-names = "qmp_dptx1_phy_pll_link_clk", + "qmp_dptx1_phy_pll_vco_div_clk"; + }; + }; + + system-cache-controller@9200000 { + compatible = "qcom,sc8180x-llcc"; + reg = <0 0x09200000 0 0x50000>, <0 0x09600000 0 0x50000>; + reg-names = "llcc_base", "llcc_broadcast_base"; + interrupts = ; + }; + + gem_noc: interconnect@9680000 { + compatible = "qcom,sc8180x-gem-noc"; + reg = <0 0x09680000 0 0x58200>; + #interconnect-cells = <2>; + qcom,bcm-voters = <&apps_bcm_voter>; + }; + + usb_prim: usb@a6f8800 { + compatible = "qcom,sc8180x-dwc3", "qcom,dwc3"; + reg = <0 0x0a6f8800 0 0x400>; + interrupts = , + , + , + ; + interrupt-names = "hs_phy_irq", + "ss_phy_irq", + "dm_hs_phy_irq", + "dp_hs_phy_irq"; + + clocks = <&gcc GCC_CFG_NOC_USB3_PRIM_AXI_CLK>, + <&gcc GCC_USB30_PRIM_MASTER_CLK>, + <&gcc GCC_AGGRE_USB3_PRIM_AXI_CLK>, + <&gcc GCC_USB30_PRIM_MOCK_UTMI_CLK>, + <&gcc GCC_USB30_PRIM_SLEEP_CLK>, + <&gcc GCC_USB3_SEC_CLKREF_CLK>; + clock-names = "cfg_noc", + "core", + "iface", + "mock_utmi", + "sleep", + "xo"; + resets = <&gcc GCC_USB30_PRIM_BCR>; + power-domains = <&gcc USB30_PRIM_GDSC>; + + interconnects = <&aggre1_noc MASTER_USB3 0 &mc_virt SLAVE_EBI_CH0 0>, + <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_USB3 0>; + interconnect-names = "usb-ddr", "apps-usb"; + + assigned-clocks = <&gcc GCC_USB30_PRIM_MOCK_UTMI_CLK>, + <&gcc GCC_USB30_PRIM_MASTER_CLK>; + assigned-clock-rates = <19200000>, <200000000>; + + #address-cells = <2>; + #size-cells = <2>; + ranges; + dma-ranges; + + status = "disabled"; + + usb_prim_dwc3: usb@a600000 { + compatible = "snps,dwc3"; + reg = <0 0x0a600000 0 0xcd00>; + interrupts = ; + iommus = <&apps_smmu 0x140 0>; + snps,dis_u2_susphy_quirk; + snps,dis_enblslpm_quirk; + phys = <&usb_prim_hsphy>, <&usb_prim_ssphy>; + phy-names = "usb2-phy", "usb3-phy"; + }; + }; + + usb_sec: usb@a8f8800 { + compatible = "qcom,sc8180x-dwc3", "qcom,dwc3"; + reg = <0 0x0a8f8800 0 0x400>; + + clocks = <&gcc GCC_CFG_NOC_USB3_SEC_AXI_CLK>, + <&gcc GCC_USB30_SEC_MASTER_CLK>, + <&gcc GCC_AGGRE_USB3_SEC_AXI_CLK>, + <&gcc GCC_USB30_SEC_MOCK_UTMI_CLK>, + <&gcc GCC_USB30_SEC_SLEEP_CLK>, + <&gcc GCC_USB3_SEC_CLKREF_CLK>; + clock-names = "cfg_noc", + "core", + "iface", + "mock_utmi", + "sleep", + "xo"; + resets = <&gcc GCC_USB30_SEC_BCR>; + power-domains = <&gcc USB30_SEC_GDSC>; + interrupts = , + , + , + ; + interrupt-names = "hs_phy_irq", "ss_phy_irq", + "dm_hs_phy_irq", "dp_hs_phy_irq"; + + assigned-clocks = <&gcc GCC_USB30_SEC_MOCK_UTMI_CLK>, + <&gcc GCC_USB30_SEC_MASTER_CLK>; + assigned-clock-rates = <19200000>, <200000000>; + + interconnects = <&aggre1_noc MASTER_USB3_1 0 &mc_virt SLAVE_EBI_CH0 0>, + <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_USB3_1 0>; + interconnect-names = "usb-ddr", "apps-usb"; + + #address-cells = <2>; + #size-cells = <2>; + ranges; + dma-ranges; + + status = "disabled"; + + usb_sec_dwc3: usb@a800000 { + compatible = "snps,dwc3"; + reg = <0 0x0a800000 0 0xcd00>; + interrupts = ; + iommus = <&apps_smmu 0x160 0>; + snps,dis_u2_susphy_quirk; + snps,dis_enblslpm_quirk; + phys = <&usb_sec_hsphy>, <&usb_sec_ssphy>; + phy-names = "usb2-phy", "usb3-phy"; + }; + }; + + mdss: mdss@ae00000 { + compatible = "qcom,sc8180x-mdss"; + reg = <0 0x0ae00000 0 0x1000>; + reg-names = "mdss"; + + power-domains = <&dispcc MDSS_GDSC>; + + clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>, + <&gcc GCC_DISP_HF_AXI_CLK>, + <&gcc GCC_DISP_SF_AXI_CLK>, + <&dispcc DISP_CC_MDSS_MDP_CLK>; + clock-names = "iface", + "bus", + "nrt_bus", + "core"; + + resets = <&dispcc DISP_CC_MDSS_CORE_BCR>; + + interrupts = ; + interrupt-controller; + #interrupt-cells = <1>; + + interconnects = <&mmss_noc MASTER_MDP_PORT0 0 &mc_virt SLAVE_EBI_CH0 0>, + <&mmss_noc MASTER_MDP_PORT1 0 &mc_virt SLAVE_EBI_CH0 0>; + interconnect-names = "mdp0-mem", "mdp1-mem"; + + iommus = <&apps_smmu 0x800 0x420>; + + #address-cells = <2>; + #size-cells = <2>; + ranges; + + status = "disabled"; + + mdss_mdp: mdp@ae01000 { + compatible = "qcom,sc8180x-dpu"; + reg = <0 0x0ae01000 0 0x8f000>, + <0 0x0aeb0000 0 0x2008>; + reg-names = "mdp", "vbif"; + + clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>, + <&gcc GCC_DISP_HF_AXI_CLK>, + <&dispcc DISP_CC_MDSS_MDP_CLK>, + <&dispcc DISP_CC_MDSS_VSYNC_CLK>; + clock-names = "iface", + "bus", + "core", + "vsync"; + + assigned-clocks = <&dispcc DISP_CC_MDSS_MDP_CLK>, + <&dispcc DISP_CC_MDSS_VSYNC_CLK>; + assigned-clock-rates = <460000000>, + <19200000>; + + operating-points-v2 = <&mdp_opp_table>; + power-domains = <&rpmhpd SC8180X_MMCX>; + + interrupt-parent = <&mdss>; + interrupts = <0 IRQ_TYPE_LEVEL_HIGH>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + dpu_intf0_out: endpoint { + remote-endpoint = <&dp0_in>; + }; + }; + + port@1 { + reg = <1>; + dpu_intf1_out: endpoint { + remote-endpoint = <&mdss_dsi0_in>; + }; + }; + + port@2 { + reg = <2>; + dpu_intf2_out: endpoint { + remote-endpoint = <&mdss_dsi1_in>; + }; + }; + + port@4 { + reg = <4>; + dpu_intf4_out: endpoint { + remote-endpoint = <&dp1_in>; + }; + }; + + port@5 { + reg = <5>; + dpu_intf5_out: endpoint { + remote-endpoint = <&edp_in>; + }; + }; + }; + + mdp_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-200000000 { + opp-hz = /bits/ 64 <200000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-345000000 { + opp-hz = /bits/ 64 <345000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-460000000 { + opp-hz = /bits/ 64 <460000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + mdss_dsi0: dsi@ae94000 { + compatible = "qcom,mdss-dsi-ctrl"; + reg = <0 0x0ae94000 0 0x400>; + reg-names = "dsi_ctrl"; + + interrupt-parent = <&mdss>; + interrupts = <4 IRQ_TYPE_LEVEL_HIGH>; + + clocks = <&dispcc DISP_CC_MDSS_BYTE0_CLK>, + <&dispcc DISP_CC_MDSS_BYTE0_INTF_CLK>, + <&dispcc DISP_CC_MDSS_PCLK0_CLK>, + <&dispcc DISP_CC_MDSS_ESC0_CLK>, + <&dispcc DISP_CC_MDSS_AHB_CLK>, + <&gcc GCC_DISP_HF_AXI_CLK>; + clock-names = "byte", + "byte_intf", + "pixel", + "core", + "iface", + "bus"; + + operating-points-v2 = <&dsi_opp_table>; + power-domains = <&rpmhpd SC8180X_MMCX>; + + phys = <&mdss_dsi0_phy>; + phy-names = "dsi"; + + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + mdss_dsi0_in: endpoint { + remote-endpoint = <&dpu_intf1_out>; + }; + }; + + port@1 { + reg = <1>; + mdss_dsi0_out: endpoint { + }; + }; + }; + + dsi_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-187500000 { + opp-hz = /bits/ 64 <187500000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-358000000 { + opp-hz = /bits/ 64 <358000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + }; + }; + + mdss_dsi0_phy: dsi-phy@ae94400 { + compatible = "qcom,dsi-phy-7nm"; + reg = <0 0x0ae94400 0 0x200>, + <0 0x0ae94600 0 0x280>, + <0 0x0ae94900 0 0x260>; + reg-names = "dsi_phy", + "dsi_phy_lane", + "dsi_pll"; + + #clock-cells = <1>; + #phy-cells = <0>; + + clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>, + <&rpmhcc RPMH_CXO_CLK>; + clock-names = "iface", "ref"; + + status = "disabled"; + }; + + mdss_dsi1: dsi@ae96000 { + compatible = "qcom,mdss-dsi-ctrl"; + reg = <0 0x0ae96000 0 0x400>; + reg-names = "dsi_ctrl"; + + interrupt-parent = <&mdss>; + interrupts = <5 IRQ_TYPE_LEVEL_HIGH>; + + clocks = <&dispcc DISP_CC_MDSS_BYTE1_CLK>, + <&dispcc DISP_CC_MDSS_BYTE1_INTF_CLK>, + <&dispcc DISP_CC_MDSS_PCLK1_CLK>, + <&dispcc DISP_CC_MDSS_ESC1_CLK>, + <&dispcc DISP_CC_MDSS_AHB_CLK>, + <&gcc GCC_DISP_HF_AXI_CLK>; + clock-names = "byte", + "byte_intf", + "pixel", + "core", + "iface", + "bus"; + + operating-points-v2 = <&dsi_opp_table>; + power-domains = <&rpmhpd SC8180X_MMCX>; + + phys = <&mdss_dsi1_phy>; + phy-names = "dsi"; + + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + mdss_dsi1_in: endpoint { + remote-endpoint = <&dpu_intf2_out>; + }; + }; + + port@1 { + reg = <1>; + mdss_dsi1_out: endpoint { + }; + }; + }; + }; + + mdss_dsi1_phy: dsi-phy@ae96400 { + compatible = "qcom,dsi-phy-7nm"; + reg = <0 0x0ae96400 0 0x200>, + <0 0x0ae96600 0 0x280>, + <0 0x0ae96900 0 0x260>; + reg-names = "dsi_phy", + "dsi_phy_lane", + "dsi_pll"; + + #clock-cells = <1>; + #phy-cells = <0>; + + clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>, + <&rpmhcc RPMH_CXO_CLK>; + clock-names = "iface", "ref"; + + status = "disabled"; + }; + + mdss_dp0: displayport-controller@ae90000 { + compatible = "qcom,sc8180x-dp"; + reg = <0 0xae90000 0 0x200>, + <0 0xae90200 0 0x200>, + <0 0xae90400 0 0x600>, + <0 0xae90a00 0 0x400>; + interrupt-parent = <&mdss>; + interrupts = <12>; + clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>, + <&dispcc DISP_CC_MDSS_DP_AUX_CLK>, + <&dispcc DISP_CC_MDSS_DP_LINK_CLK>, + <&dispcc DISP_CC_MDSS_DP_LINK_INTF_CLK>, + <&dispcc DISP_CC_MDSS_DP_PIXEL_CLK>; + clock-names = "core_iface", + "core_aux", + "ctrl_link", + "ctrl_link_iface", + "stream_pixel"; + + assigned-clocks = <&dispcc DISP_CC_MDSS_DP_LINK_CLK_SRC>, + <&dispcc DISP_CC_MDSS_DP_PIXEL_CLK_SRC>; + assigned-clock-parents = <&usb_prim_dpphy 0>, <&usb_prim_dpphy 1>; + + phys = <&usb_prim_dpphy>; + phy-names = "dp"; + + #sound-dai-cells = <0>; + + operating-points-v2 = <&dp0_opp_table>; + power-domains = <&rpmhpd SC8180X_MMCX>; + + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + dp0_in: endpoint { + remote-endpoint = <&dpu_intf0_out>; + }; + }; + + port@1 { + reg = <1>; + }; + }; + + dp0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-160000000 { + opp-hz = /bits/ 64 <160000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-270000000 { + opp-hz = /bits/ 64 <270000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-540000000 { + opp-hz = /bits/ 64 <540000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-810000000 { + opp-hz = /bits/ 64 <810000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + mdss_dp1: displayport-controller@ae98000 { + compatible = "qcom,sc8180x-dp"; + reg = <0 0xae98000 0 0x200>, + <0 0xae98200 0 0x200>, + <0 0xae98400 0 0x600>, + <0 0xae98a00 0 0x400>; + interrupt-parent = <&mdss>; + interrupts = <13>; + clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>, + <&dispcc DISP_CC_MDSS_DP_AUX1_CLK>, + <&dispcc DISP_CC_MDSS_DP_LINK1_CLK>, + <&dispcc DISP_CC_MDSS_DP_LINK1_INTF_CLK>, + <&dispcc DISP_CC_MDSS_DP_PIXEL2_CLK>; + clock-names = "core_iface", + "core_aux", + "ctrl_link", + "ctrl_link_iface", + "stream_pixel"; + + assigned-clocks = <&dispcc DISP_CC_MDSS_DP_LINK1_CLK_SRC>, + <&dispcc DISP_CC_MDSS_DP_PIXEL2_CLK_SRC>; + assigned-clock-parents = <&usb_sec_dpphy 0>, <&usb_sec_dpphy 1>; + + phys = <&usb_sec_dpphy>; + phy-names = "dp"; + + #sound-dai-cells = <0>; + + operating-points-v2 = <&dp0_opp_table>; + power-domains = <&rpmhpd SC8180X_MMCX>; + + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + dp1_in: endpoint { + remote-endpoint = <&dpu_intf4_out>; + }; + }; + + port@1 { + reg = <1>; + }; + }; + + dp1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-160000000 { + opp-hz = /bits/ 64 <160000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-270000000 { + opp-hz = /bits/ 64 <270000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-540000000 { + opp-hz = /bits/ 64 <540000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-810000000 { + opp-hz = /bits/ 64 <810000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + mdss_edp: displayport-controller@ae9a000 { + compatible = "qcom,sc8180x-edp"; + reg = <0 0xae9a000 0 0x200>, + <0 0xae9a200 0 0x200>, + <0 0xae9a400 0 0x600>, + <0 0xae9aa00 0 0x400>; + interrupt-parent = <&mdss>; + interrupts = <14>; + clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>, + <&dispcc DISP_CC_MDSS_EDP_AUX_CLK>, + <&dispcc DISP_CC_MDSS_EDP_LINK_CLK>, + <&dispcc DISP_CC_MDSS_EDP_LINK_INTF_CLK>, + <&dispcc DISP_CC_MDSS_EDP_PIXEL_CLK>; + clock-names = "core_iface", + "core_aux", + "ctrl_link", + "ctrl_link_iface", + "stream_pixel"; + + assigned-clocks = <&dispcc DISP_CC_MDSS_EDP_LINK_CLK_SRC>, + <&dispcc DISP_CC_MDSS_EDP_PIXEL_CLK_SRC>; + assigned-clock-parents = <&edp_phy 0>, <&edp_phy 1>; + + phys = <&edp_phy>; + phy-names = "dp"; + + #sound-dai-cells = <0>; + + operating-points-v2 = <&edp_opp_table>; + power-domains = <&rpmhpd SC8180X_MMCX>; + + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + edp_in: endpoint { + remote-endpoint = <&dpu_intf5_out>; + }; + }; + }; + + edp_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-160000000 { + opp-hz = /bits/ 64 <160000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-270000000 { + opp-hz = /bits/ 64 <270000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-540000000 { + opp-hz = /bits/ 64 <540000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-810000000 { + opp-hz = /bits/ 64 <810000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + }; + + edp_phy: phy@aec2a00 { + compatible = "qcom,sc8180x-edp-phy"; + reg = <0 0x0aec2a00 0 0x1c0>, + <0 0x0aec2200 0 0xa0>, + <0 0x0aec2600 0 0xa0>, + <0 0x0aec2000 0 0x19c>; + + clocks = <&dispcc DISP_CC_MDSS_EDP_AUX_CLK>, + <&dispcc DISP_CC_MDSS_AHB_CLK>; + clock-names = "aux", "cfg_ahb"; + + power-domains = <&dispcc MDSS_GDSC>; + + #clock-cells = <1>; + #phy-cells = <0>; + }; + + dispcc: clock-controller@af00000 { + compatible = "qcom,sc8180x-dispcc"; + reg = <0 0x0af00000 0 0x20000>; + clocks = <&rpmhcc RPMH_CXO_CLK>, + <&sleep_clk>, + <&usb_prim_dpphy 0>, + <&usb_prim_dpphy 1>, + <&usb_sec_dpphy 0>, + <&usb_sec_dpphy 1>, + <&edp_phy 0>, + <&edp_phy 1>; + clock-names = "bi_tcxo", + "sleep_clk", + "dp_phy_pll_link_clk", + "dp_phy_pll_vco_div_clk", + "dptx1_phy_pll_link_clk", + "dptx1_phy_pll_vco_div_clk", + "edp_phy_pll_link_clk", + "edp_phy_pll_vco_div_clk"; + power-domains = <&rpmhpd SC8180X_MMCX>; + #clock-cells = <1>; + #reset-cells = <1>; + #power-domain-cells = <1>; + }; + + pdc: interrupt-controller@b220000 { + compatible = "qcom,sc8180x-pdc", "qcom,pdc"; + reg = <0 0x0b220000 0 0x30000>; + qcom,pdc-ranges = <0 480 94>, <94 609 31>; + #interrupt-cells = <2>; + interrupt-parent = <&intc>; + interrupt-controller; + }; + + tsens0: thermal-sensor@c263000 { + compatible = "qcom,sc8180x-tsens", "qcom,tsens-v2"; + reg = <0 0x0c263000 0 0x1ff>, /* TM */ + <0 0x0c222000 0 0x1ff>; /* SROT */ + #qcom,sensors = <16>; + interrupts = , + ; + interrupt-names = "uplow", "critical"; + #thermal-sensor-cells = <1>; + }; + + tsens1: thermal-sensor@c265000 { + compatible = "qcom,sc8180x-tsens", "qcom,tsens-v2"; + reg = <0 0x0c265000 0 0x1ff>, /* TM */ + <0 0x0c223000 0 0x1ff>; /* SROT */ + #qcom,sensors = <9>; + interrupts = , + ; + interrupt-names = "uplow", "critical"; + #thermal-sensor-cells = <1>; + }; + + aoss_qmp: power-controller@c300000 { + compatible = "qcom,sc8180x-aoss-qmp", "qcom,aoss-qmp"; + reg = <0x0 0x0c300000 0x0 0x100000>; + interrupts = ; + mboxes = <&apss_shared 0>; + + #clock-cells = <0>; + #power-domain-cells = <1>; + }; + + spmi_bus: spmi@c440000 { + compatible = "qcom,spmi-pmic-arb"; + reg = <0x0 0x0c440000 0x0 0x0001100>, + <0x0 0x0c600000 0x0 0x2000000>, + <0x0 0x0e600000 0x0 0x0100000>, + <0x0 0x0e700000 0x0 0x00a0000>, + <0x0 0x0c40a000 0x0 0x0026000>; + reg-names = "core", "chnls", "obsrvr", "intr", "cnfg"; + interrupt-names = "periph_irq"; + interrupts = ; + qcom,ee = <0>; + qcom,channel = <0>; + #address-cells = <2>; + #size-cells = <0>; + interrupt-controller; + #interrupt-cells = <4>; + cell-index = <0>; + }; + + apps_smmu: iommu@15000000 { + compatible = "qcom,sc8180x-smmu-500", "arm,mmu-500"; + reg = <0 0x15000000 0 0x100000>; + #iommu-cells = <2>; + #global-interrupts = <1>; + interrupts = , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + ; + + }; + + remoteproc_adsp: remoteproc@17300000 { + compatible = "qcom,sc8180x-adsp-pas"; + reg = <0x0 0x17300000 0x0 0x4040>; + + interrupts-extended = <&intc GIC_SPI 162 IRQ_TYPE_EDGE_RISING>, + <&adsp_smp2p_in 0 IRQ_TYPE_EDGE_RISING>, + <&adsp_smp2p_in 1 IRQ_TYPE_EDGE_RISING>, + <&adsp_smp2p_in 2 IRQ_TYPE_EDGE_RISING>, + <&adsp_smp2p_in 3 IRQ_TYPE_EDGE_RISING>; + interrupt-names = "wdog", "fatal", "ready", + "handover", "stop-ack"; + + clocks = <&rpmhcc RPMH_CXO_CLK>; + clock-names = "xo"; + + power-domains = <&rpmhpd SC8180X_CX>; + power-domain-names = "cx"; + + qcom,qmp = <&aoss_qmp>; + + qcom,smem-states = <&adsp_smp2p_out 0>; + qcom,smem-state-names = "stop"; + + status = "disabled"; + + remoteproc_adsp_glink: glink-edge { + interrupts = ; + label = "lpass"; + qcom,remote-pid = <2>; + mboxes = <&apss_shared 8>; + }; + }; + + intc: interrupt-controller@17a00000 { + compatible = "arm,gic-v3"; + interrupt-controller; + #interrupt-cells = <3>; + reg = <0x0 0x17a00000 0x0 0x10000>, /* GICD */ + <0x0 0x17a60000 0x0 0x100000>; /* GICR * 8 */ + interrupts = ; + }; + + apss_shared: mailbox@17c00000 { + compatible = "qcom,sc8180x-apss-shared"; + reg = <0x0 0x17c00000 0x0 0x1000>; + #mbox-cells = <1>; + }; + + timer@17c20000 { + compatible = "arm,armv7-timer-mem"; + reg = <0x0 0x17c20000 0x0 0x1000>; + + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0 0 0x20000000>; + + frame@17c21000{ + reg = <0x17c21000 0x1000>, + <0x17c22000 0x1000>; + frame-number = <0>; + interrupts = , + ; + }; + + frame@17c23000 { + reg = <0x17c23000 0x1000>; + frame-number = <1>; + interrupts = ; + status = "disabled"; + }; + + frame@17c25000 { + reg = <0x17c25000 0x1000>; + frame-number = <2>; + interrupts = ; + status = "disabled"; + }; + + frame@17c27000 { + reg = <0x17c26000 0x1000>; + frame-number = <3>; + interrupts = ; + status = "disabled"; + }; + + frame@17c29000 { + reg = <0x17c29000 0x1000>; + frame-number = <4>; + interrupts = ; + status = "disabled"; + }; + + frame@17c2b000 { + reg = <0x17c2b000 0x1000>; + frame-number = <5>; + interrupts = ; + status = "disabled"; + }; + + frame@17c2d000 { + reg = <0x17c2d000 0x1000>; + frame-number = <6>; + interrupts = ; + status = "disabled"; + }; + }; + + apps_rsc: rsc@18200000 { + compatible = "qcom,rpmh-rsc"; + reg = <0x0 0x18200000 0x0 0x10000>, + <0x0 0x18210000 0x0 0x10000>, + <0x0 0x18220000 0x0 0x10000>; + reg-names = "drv-0", "drv-1", "drv-2"; + interrupts = , + , + ; + qcom,tcs-offset = <0xd00>; + qcom,drv-id = <2>; + qcom,tcs-config = , + , + , + ; + label = "apps_rsc"; + power-domains = <&CLUSTER_PD>; + + apps_bcm_voter: bcm-voter { + compatible = "qcom,bcm-voter"; + }; + + rpmhcc: clock-controller { + compatible = "qcom,sc8180x-rpmh-clk"; + #clock-cells = <1>; + clock-names = "xo"; + clocks = <&xo_board_clk>; + }; + + rpmhpd: power-controller { + compatible = "qcom,sc8180x-rpmhpd"; + #power-domain-cells = <1>; + operating-points-v2 = <&rpmhpd_opp_table>; + + rpmhpd_opp_table: opp-table { + compatible = "operating-points-v2"; + + rpmhpd_opp_ret: opp1 { + opp-level = ; + }; + + rpmhpd_opp_min_svs: opp2 { + opp-level = ; + }; + + rpmhpd_opp_low_svs: opp3 { + opp-level = ; + }; + + rpmhpd_opp_svs: opp4 { + opp-level = ; + }; + + rpmhpd_opp_svs_l1: opp5 { + opp-level = ; + }; + + rpmhpd_opp_nom: opp6 { + opp-level = ; + }; + + rpmhpd_opp_nom_l1: opp7 { + opp-level = ; + }; + + rpmhpd_opp_nom_l2: opp8 { + opp-level = ; + }; + + rpmhpd_opp_turbo: opp9 { + opp-level = ; + }; + + rpmhpd_opp_turbo_l1: opp10 { + opp-level = ; + }; + }; + }; + }; + + osm_l3: interconnect@18321000 { + compatible = "qcom,sc8180x-osm-l3"; + reg = <0 0x18321000 0 0x1400>; + + clocks = <&rpmhcc RPMH_CXO_CLK>, <&gcc GPLL0>; + clock-names = "xo", "alternate"; + + #interconnect-cells = <1>; + }; + + lmh@18350800 { + compatible = "qcom,sc8180x-lmh"; + reg = <0 0x18350800 0 0x400>; + interrupts = ; + cpus = <&CPU4>; + qcom,lmh-temp-arm-millicelsius = <65000>; + qcom,lmh-temp-low-millicelsius = <94500>; + qcom,lmh-temp-high-millicelsius = <95000>; + interrupt-controller; + #interrupt-cells = <1>; + }; + + lmh@18358800 { + compatible = "qcom,sc8180x-lmh"; + reg = <0 0x18358800 0 0x400>; + interrupts = ; + cpus = <&CPU0>; + qcom,lmh-temp-arm-millicelsius = <65000>; + qcom,lmh-temp-low-millicelsius = <94500>; + qcom,lmh-temp-high-millicelsius = <95000>; + interrupt-controller; + #interrupt-cells = <1>; + }; + + cpufreq_hw: cpufreq@18323000 { + compatible = "qcom,cpufreq-hw"; + reg = <0 0x18323000 0 0x1400>, <0 0x18325800 0 0x1400>; + reg-names = "freq-domain0", "freq-domain1"; + + clocks = <&rpmhcc RPMH_CXO_CLK>, <&gcc GPLL0>; + clock-names = "xo", "alternate"; + + #freq-domain-cells = <1>; + #clock-cells = <1>; + }; + + wifi: wifi@18800000 { + compatible = "qcom,wcn3990-wifi"; + reg = <0 0x18800000 0 0x800000>; + reg-names = "membase"; + clock-names = "cxo_ref_clk_pin"; + clocks = <&rpmhcc RPMH_RF_CLK2>; + interrupts = , + , + , + , + , + , + , + , + , + , + , + ; + iommus = <&apps_smmu 0x0640 0x1>; + qcom,msa-fixed-perm; + status = "disabled"; + }; + }; + + thermal-zones { + cpu0-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens0 1>; + + trips { + cpu-crit { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + }; + + cpu1-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens0 2>; + + trips { + cpu-crit { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + }; + + cpu2-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens0 3>; + + trips { + cpu-crit { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + }; + + cpu3-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens0 4>; + + trips { + cpu-crit { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + }; + + cpu4-top-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens0 7>; + + trips { + cpu-crit { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + }; + + cpu5-top-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens0 8>; + + trips { + cpu-crit { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + }; + + cpu6-top-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens0 9>; + + trips { + cpu-crit { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + }; + + cpu7-top-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens0 10>; + + trips { + cpu-crit { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + }; + + cpu4-bottom-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens0 11>; + + trips { + cpu-crit { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + }; + + cpu5-bottom-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens0 12>; + + trips { + cpu-crit { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + }; + + cpu6-bottom-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens0 13>; + + trips { + cpu-crit { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + }; + + cpu7-bottom-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens0 14>; + + trips { + cpu-crit { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + }; + + aoss0-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens0 0>; + + trips { + trip-point0 { + temperature = <90000>; + hysteresis = <2000>; + type = "hot"; + }; + }; + }; + + cluster0-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens0 5>; + + trips { + cluster-crit { + temperature = <110000>; + hysteresis = <2000>; + type = "critical"; + }; + }; + }; + + cluster1-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens0 6>; + + trips { + cluster-crit { + temperature = <110000>; + hysteresis = <2000>; + type = "critical"; + }; + }; + }; + + gpu-thermal-top { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens0 15>; + + trips { + trip-point0 { + temperature = <90000>; + hysteresis = <2000>; + type = "hot"; + }; + }; + }; + + aoss1-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens1 0>; + + trips { + trip-point0 { + temperature = <90000>; + hysteresis = <2000>; + type = "hot"; + }; + }; + }; + + wlan-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens1 1>; + + trips { + trip-point0 { + temperature = <90000>; + hysteresis = <2000>; + type = "hot"; + }; + }; + }; + + video-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens1 2>; + + trips { + trip-point0 { + temperature = <90000>; + hysteresis = <2000>; + type = "hot"; + }; + }; + }; + + mem-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens1 3>; + + trips { + trip-point0 { + temperature = <90000>; + hysteresis = <2000>; + type = "hot"; + }; + }; + }; + + q6-hvx-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens1 4>; + + trips { + trip-point0 { + temperature = <90000>; + hysteresis = <2000>; + type = "hot"; + }; + }; + }; + + camera-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens1 5>; + + trips { + trip-point0 { + temperature = <90000>; + hysteresis = <2000>; + type = "hot"; + }; + }; + }; + + compute-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens1 6>; + + trips { + trip-point0 { + temperature = <90000>; + hysteresis = <2000>; + type = "hot"; + }; + }; + }; + + mdm-dsp-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens1 7>; + + trips { + trip-point0 { + temperature = <90000>; + hysteresis = <2000>; + type = "hot"; + }; + }; + }; + + npu-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens1 8>; + + trips { + trip-point0 { + temperature = <90000>; + hysteresis = <2000>; + type = "hot"; + }; + }; + }; + + gpu-thermal-bottom { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens1 11>; + + trips { + trip-point0 { + temperature = <90000>; + hysteresis = <2000>; + type = "hot"; + }; + }; + }; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts = , + , + , + ; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/sc8280xp-crd.dts b/arch/arm64/boot/dts/qcom/sc8280xp-crd.dts index 5b25d54b959115e3e18f19c90886e4d41bdafc5c..b566e403d1db211e7c79870fd46c07e4674974e9 100644 --- a/arch/arm64/boot/dts/qcom/sc8280xp-crd.dts +++ b/arch/arm64/boot/dts/qcom/sc8280xp-crd.dts @@ -64,7 +64,7 @@ reg = <1>; pmic_glink_con0_ss: endpoint { - remote-endpoint = <&mdss0_dp0_out>; + remote-endpoint = <&usb_0_qmpphy_out>; }; }; @@ -99,7 +99,7 @@ reg = <1>; pmic_glink_con1_ss: endpoint { - remote-endpoint = <&mdss0_dp1_out>; + remote-endpoint = <&usb_1_qmpphy_out>; }; }; @@ -210,6 +210,11 @@ }; reserved-memory { + gpu_mem: gpu-mem@8bf00000 { + reg = <0 0x8bf00000 0 0x2000>; + no-map; + }; + linux,cma { compatible = "shared-dma-pool"; size = <0x0 0x8000000>; @@ -308,6 +313,13 @@ regulator-initial-mode = ; }; + vreg_l6c: ldo6 { + regulator-name = "vreg_l6c"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <2960000>; + regulator-initial-mode = ; + }; + vreg_l7c: ldo7 { regulator-name = "vreg_l7c"; regulator-min-microvolt = <2504000>; @@ -318,6 +330,13 @@ RPMH_REGULATOR_MODE_HPM>; }; + vreg_l9c: ldo9 { + regulator-name = "vreg_l9c"; + regulator-min-microvolt = <2960000>; + regulator-max-microvolt = <2960000>; + regulator-initial-mode = ; + }; + vreg_l13c: ldo13 { regulator-name = "vreg_l13c"; regulator-min-microvolt = <3072000>; @@ -376,6 +395,15 @@ status = "okay"; }; +&gpu { + status = "okay"; + + zap-shader { + memory-region = <&gpu_mem>; + firmware-name = "qcom/sc8280xp/qcdxkmsuc8280.mbn"; + }; +}; + &mdss0 { status = "okay"; }; @@ -386,7 +414,7 @@ &mdss0_dp0_out { data-lanes = <0 1>; - remote-endpoint = <&pmic_glink_con0_ss>; + remote-endpoint = <&usb_0_qmpphy_dp_in>; }; &mdss0_dp1 { @@ -395,7 +423,7 @@ &mdss0_dp1_out { data-lanes = <0 1>; - remote-endpoint = <&pmic_glink_con1_ss>; + remote-endpoint = <&usb_1_qmpphy_dp_in>; }; &mdss0_dp3 { @@ -600,6 +628,19 @@ status = "okay"; }; +&sdc2 { + pinctrl-0 = <&sdc2_default_state>; + pinctrl-1 = <&sdc2_sleep_state>; + pinctrl-names = "default", "sleep"; + + vmmc-supply = <&vreg_l9c>; + vqmmc-supply = <&vreg_l6c>; + + cd-gpios = <&tlmm 131 GPIO_ACTIVE_LOW>; + + status = "okay"; +}; + &uart17 { compatible = "qcom,geni-debug-uart"; @@ -644,9 +685,19 @@ vdda-phy-supply = <&vreg_l9d>; vdda-pll-supply = <&vreg_l4d>; + orientation-switch; + status = "okay"; }; +&usb_0_qmpphy_dp_in { + remote-endpoint = <&mdss0_dp0_out>; +}; + +&usb_0_qmpphy_out { + remote-endpoint = <&pmic_glink_con0_ss>; +}; + &usb_0_role_switch { remote-endpoint = <&pmic_glink_con0_hs>; }; @@ -671,9 +722,19 @@ vdda-phy-supply = <&vreg_l4b>; vdda-pll-supply = <&vreg_l3b>; + orientation-switch; + status = "okay"; }; +&usb_1_qmpphy_dp_in { + remote-endpoint = <&mdss0_dp1_out>; +}; + +&usb_1_qmpphy_out { + remote-endpoint = <&pmic_glink_con1_ss>; +}; + &usb_1_role_switch { remote-endpoint = <&pmic_glink_con1_hs>; }; @@ -842,6 +903,60 @@ }; }; + sdc2_default_state: sdc2-default-state { + clk-pins { + pins = "sdc2_clk"; + drive-strength = <16>; + bias-disable; + }; + + cmd-pins { + pins = "sdc2_cmd"; + drive-strength = <16>; + bias-pull-up; + }; + + data-pins { + pins = "sdc2_data"; + drive-strength = <16>; + bias-pull-up; + }; + + card-detect-pins { + pins = "gpio131"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + }; + + sdc2_sleep_state: sdc2-sleep-state { + clk-pins { + pins = "sdc2_clk"; + drive-strength = <2>; + bias-disable; + }; + + cmd-pins { + pins = "sdc2_cmd"; + drive-strength = <2>; + bias-pull-up; + }; + + data-pins { + pins = "sdc2_data"; + drive-strength = <2>; + bias-pull-up; + }; + + card-detect-pins { + pins = "gpio131"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + }; + tpad_default: tpad-default-state { int-n-pins { pins = "gpio182"; diff --git a/arch/arm64/boot/dts/qcom/sc8280xp-lenovo-thinkpad-x13s.dts b/arch/arm64/boot/dts/qcom/sc8280xp-lenovo-thinkpad-x13s.dts index bdcba719fc38523266dd86648aa5b5cf6c632971..7cc3028440b64c2c836aeea25dc65163f88ccd29 100644 --- a/arch/arm64/boot/dts/qcom/sc8280xp-lenovo-thinkpad-x13s.dts +++ b/arch/arm64/boot/dts/qcom/sc8280xp-lenovo-thinkpad-x13s.dts @@ -106,7 +106,7 @@ reg = <1>; pmic_glink_con0_ss: endpoint { - remote-endpoint = <&mdss0_dp0_out>; + remote-endpoint = <&usb_0_qmpphy_out>; }; }; @@ -141,7 +141,7 @@ reg = <1>; pmic_glink_con1_ss: endpoint { - remote-endpoint = <&mdss0_dp1_out>; + remote-endpoint = <&usb_1_qmpphy_out>; }; }; @@ -264,6 +264,11 @@ }; reserved-memory { + gpu_mem: gpu-mem@8bf00000 { + reg = <0 0x8bf00000 0 0x2000>; + no-map; + }; + linux,cma { compatible = "shared-dma-pool"; size = <0x0 0x8000000>; @@ -518,6 +523,15 @@ status = "okay"; }; +&gpu { + status = "okay"; + + zap-shader { + memory-region = <&gpu_mem>; + firmware-name = "qcom/sc8280xp/LENOVO/21BX/qcdxkmsuc8280.mbn"; + }; +}; + &mdss0 { status = "okay"; }; @@ -528,7 +542,7 @@ &mdss0_dp0_out { data-lanes = <0 1>; - remote-endpoint = <&pmic_glink_con0_ss>; + remote-endpoint = <&usb_0_qmpphy_dp_in>; }; &mdss0_dp1 { @@ -537,7 +551,7 @@ &mdss0_dp1_out { data-lanes = <0 1>; - remote-endpoint = <&pmic_glink_con1_ss>; + remote-endpoint = <&usb_1_qmpphy_dp_in>; }; &mdss0_dp3 { @@ -1114,9 +1128,19 @@ vdda-phy-supply = <&vreg_l9d>; vdda-pll-supply = <&vreg_l4d>; + orientation-switch; + status = "okay"; }; +&usb_0_qmpphy_dp_in { + remote-endpoint = <&mdss0_dp0_out>; +}; + +&usb_0_qmpphy_out { + remote-endpoint = <&pmic_glink_con0_ss>; +}; + &usb_0_role_switch { remote-endpoint = <&pmic_glink_con0_hs>; }; @@ -1141,9 +1165,19 @@ vdda-phy-supply = <&vreg_l4b>; vdda-pll-supply = <&vreg_l3b>; + orientation-switch; + status = "okay"; }; +&usb_1_qmpphy_dp_in { + remote-endpoint = <&mdss0_dp1_out>; +}; + +&usb_1_qmpphy_out { + remote-endpoint = <&pmic_glink_con1_ss>; +}; + &usb_1_role_switch { remote-endpoint = <&pmic_glink_con1_hs>; }; diff --git a/arch/arm64/boot/dts/qcom/sc8280xp.dtsi b/arch/arm64/boot/dts/qcom/sc8280xp.dtsi index cc4aef21e6172e6b7399da43b09cd1896daa62e6..ac0596dfdbc473b308dcf37ed80e2fadbd63f2ed 100644 --- a/arch/arm64/boot/dts/qcom/sc8280xp.dtsi +++ b/arch/arm64/boot/dts/qcom/sc8280xp.dtsi @@ -6,7 +6,9 @@ #include #include +#include #include +#include #include #include #include @@ -777,6 +779,36 @@ ranges = <0 0 0 0 0x10 0>; dma-ranges = <0 0 0 0 0x10 0>; + ethernet0: ethernet@20000 { + compatible = "qcom,sc8280xp-ethqos"; + reg = <0x0 0x00020000 0x0 0x10000>, + <0x0 0x00036000 0x0 0x100>; + reg-names = "stmmaceth", "rgmii"; + + clocks = <&gcc GCC_EMAC0_AXI_CLK>, + <&gcc GCC_EMAC0_SLV_AHB_CLK>, + <&gcc GCC_EMAC0_PTP_CLK>, + <&gcc GCC_EMAC0_RGMII_CLK>; + clock-names = "stmmaceth", + "pclk", + "ptp_ref", + "rgmii"; + + interrupts = , + ; + interrupt-names = "macirq", "eth_lpi"; + + iommus = <&apps_smmu 0x4c0 0xf>; + power-domains = <&gcc EMAC_0_GDSC>; + + snps,tso; + snps,pbl = <32>; + rx-fifo-depth = <4096>; + tx-fifo-depth = <4096>; + + status = "disabled"; + }; + gcc: clock-controller@100000 { compatible = "qcom,gcc-sc8280xp"; reg = <0x0 0x00100000 0x0 0x1f0000>; @@ -2310,6 +2342,180 @@ reg = <0x0 0x01fc0000 0x0 0x30000>; }; + gpu: gpu@3d00000 { + compatible = "qcom,adreno-690.0", "qcom,adreno"; + + reg = <0 0x03d00000 0 0x40000>, + <0 0x03d9e000 0 0x1000>, + <0 0x03d61000 0 0x800>; + reg-names = "kgsl_3d0_reg_memory", + "cx_mem", + "cx_dbgc"; + interrupts = ; + iommus = <&gpu_smmu 0 0xc00>, <&gpu_smmu 1 0xc00>; + operating-points-v2 = <&gpu_opp_table>; + + qcom,gmu = <&gmu>; + interconnects = <&gem_noc MASTER_GFX3D 0 &mc_virt SLAVE_EBI1 0>; + interconnect-names = "gfx-mem"; + #cooling-cells = <2>; + + status = "disabled"; + + gpu_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-270000000 { + opp-hz = /bits/ 64 <270000000>; + opp-level = ; + opp-peak-kBps = <451000>; + }; + + opp-410000000 { + opp-hz = /bits/ 64 <410000000>; + opp-level = ; + opp-peak-kBps = <1555000>; + }; + + opp-500000000 { + opp-hz = /bits/ 64 <500000000>; + opp-level = ; + opp-peak-kBps = <1555000>; + }; + + opp-547000000 { + opp-hz = /bits/ 64 <547000000>; + opp-level = ; + opp-peak-kBps = <1555000>; + }; + + opp-606000000 { + opp-hz = /bits/ 64 <606000000>; + opp-level = ; + opp-peak-kBps = <2736000>; + }; + + opp-640000000 { + opp-hz = /bits/ 64 <640000000>; + opp-level = ; + opp-peak-kBps = <2736000>; + }; + + opp-655000000 { + opp-hz = /bits/ 64 <655000000>; + opp-level = ; + opp-peak-kBps = <2736000>; + }; + + opp-690000000 { + opp-hz = /bits/ 64 <690000000>; + opp-level = ; + opp-peak-kBps = <2736000>; + }; + }; + }; + + gmu: gmu@3d6a000 { + compatible = "qcom,adreno-gmu-690.0", "qcom,adreno-gmu"; + reg = <0 0x03d6a000 0 0x34000>, + <0 0x03de0000 0 0x10000>, + <0 0x0b290000 0 0x10000>; + reg-names = "gmu", "rscc", "gmu_pdc"; + interrupts = , + ; + interrupt-names = "hfi", "gmu"; + clocks = <&gpucc GPU_CC_CX_GMU_CLK>, + <&gpucc GPU_CC_CXO_CLK>, + <&gcc GCC_DDRSS_GPU_AXI_CLK>, + <&gcc GCC_GPU_MEMNOC_GFX_CLK>, + <&gpucc GPU_CC_AHB_CLK>, + <&gpucc GPU_CC_HUB_CX_INT_CLK>, + <&gpucc GPU_CC_HLOS1_VOTE_GPU_SMMU_CLK>; + clock-names = "gmu", + "cxo", + "axi", + "memnoc", + "ahb", + "hub", + "smmu_vote"; + power-domains = <&gpucc GPU_CC_CX_GDSC>, + <&gpucc GPU_CC_GX_GDSC>; + power-domain-names = "cx", + "gx"; + iommus = <&gpu_smmu 5 0xc00>; + operating-points-v2 = <&gmu_opp_table>; + + gmu_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-200000000 { + opp-hz = /bits/ 64 <200000000>; + opp-level = ; + }; + + opp-500000000 { + opp-hz = /bits/ 64 <500000000>; + opp-level = ; + }; + }; + }; + + gpucc: clock-controller@3d90000 { + compatible = "qcom,sc8280xp-gpucc"; + reg = <0 0x03d90000 0 0x9000>; + clocks = <&rpmhcc RPMH_CXO_CLK>, + <&gcc GCC_GPU_GPLL0_CLK_SRC>, + <&gcc GCC_GPU_GPLL0_DIV_CLK_SRC>; + clock-names = "bi_tcxo", + "gcc_gpu_gpll0_clk_src", + "gcc_gpu_gpll0_div_clk_src"; + + power-domains = <&rpmhpd SC8280XP_GFX>; + #clock-cells = <1>; + #reset-cells = <1>; + #power-domain-cells = <1>; + }; + + gpu_smmu: iommu@3da0000 { + compatible = "qcom,sc8280xp-smmu-500", "qcom,adreno-smmu", + "qcom,smmu-500", "arm,mmu-500"; + reg = <0 0x03da0000 0 0x20000>; + #iommu-cells = <2>; + #global-interrupts = <2>; + interrupts = , + , + , + , + , + , + , + , + , + , + , + , + , + ; + + clocks = <&gcc GCC_GPU_MEMNOC_GFX_CLK>, + <&gcc GCC_GPU_SNOC_DVM_GFX_CLK>, + <&gpucc GPU_CC_AHB_CLK>, + <&gpucc GPU_CC_HLOS1_VOTE_GPU_SMMU_CLK>, + <&gpucc GPU_CC_CX_GMU_CLK>, + <&gpucc GPU_CC_HUB_CX_INT_CLK>, + <&gpucc GPU_CC_HUB_AON_CLK>; + clock-names = "gcc_gpu_memnoc_gfx_clk", + "gcc_gpu_snoc_dvm_gfx_clk", + "gpu_cc_ahb_clk", + "gpu_cc_hlos1_vote_gpu_smmu_clk", + "gpu_cc_cx_gmu_clk", + "gpu_cc_hub_cx_int_clk", + "gpu_cc_hub_aon_clk"; + + power-domains = <&gpucc GPU_CC_CX_GDSC>; + dma-coherent; + }; + usb_0_hsphy: phy@88e5000 { compatible = "qcom,sc8280xp-usb-hs-phy", "qcom,usb-snps-hs-5nm-phy"; @@ -2530,6 +2736,8 @@ interrupts = ; clocks = <&rxmacro>; clock-names = "iface"; + resets = <&lpass_audiocc LPASS_AUDIO_SWR_RX_CGCR>; + reset-names = "swr_audio_cgcr"; label = "RX"; qcom,din-ports = <0>; @@ -2604,6 +2812,8 @@ interrupts = ; clocks = <&wsamacro>; clock-names = "iface"; + resets = <&lpass_audiocc LPASS_AUDIO_SWR_WSA_CGCR>; + reset-names = "swr_audio_cgcr"; label = "WSA"; qcom,din-ports = <2>; @@ -2626,6 +2836,13 @@ status = "disabled"; }; + lpass_audiocc: clock-controller@32a9000 { + compatible = "qcom,sc8280xp-lpassaudiocc"; + reg = <0 0x032a9000 0 0x1000>; + #clock-cells = <1>; + #reset-cells = <1>; + }; + swr2: soundwire-controller@3330000 { compatible = "qcom,soundwire-v1.6.0"; reg = <0 0x03330000 0 0x2000>; @@ -2635,6 +2852,8 @@ clocks = <&txmacro>; clock-names = "iface"; + resets = <&lpasscc LPASS_AUDIO_SWR_TX_CGCR>; + reset-names = "swr_audio_cgcr"; label = "TX"; #sound-dai-cells = <1>; #address-cells = <2>; @@ -2828,6 +3047,56 @@ }; }; + lpasscc: clock-controller@33e0000 { + compatible = "qcom,sc8280xp-lpasscc"; + reg = <0 0x033e0000 0 0x12000>; + #clock-cells = <1>; + #reset-cells = <1>; + }; + + sdc2: mmc@8804000 { + compatible = "qcom,sc8280xp-sdhci", "qcom,sdhci-msm-v5"; + reg = <0 0x08804000 0 0x1000>; + + interrupts = , + ; + interrupt-names = "hc_irq", "pwr_irq"; + + clocks = <&gcc GCC_SDCC2_AHB_CLK>, + <&gcc GCC_SDCC2_APPS_CLK>, + <&rpmhcc RPMH_CXO_CLK>; + clock-names = "iface", "core", "xo"; + resets = <&gcc GCC_SDCC2_BCR>; + interconnects = <&aggre2_noc MASTER_SDCC_2 0 &mc_virt SLAVE_EBI1 0>, + <&gem_noc MASTER_APPSS_PROC 0 &config_noc SLAVE_SDCC_2 0>; + interconnect-names = "sdhc-ddr","cpu-sdhc"; + iommus = <&apps_smmu 0x4e0 0x0>; + power-domains = <&rpmhpd SC8280XP_CX>; + operating-points-v2 = <&sdc2_opp_table>; + bus-width = <4>; + dma-coherent; + + status = "disabled"; + + sdc2_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-100000000 { + opp-hz = /bits/ 64 <100000000>; + required-opps = <&rpmhpd_opp_low_svs>; + opp-peak-kBps = <1800000 400000>; + opp-avg-kBps = <100000 0>; + }; + + opp-202000000 { + opp-hz = /bits/ 64 <202000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + opp-peak-kBps = <5400000 1600000>; + opp-avg-kBps = <200000 0>; + }; + }; + }; + usb_0_qmpphy: phy@88eb000 { compatible = "qcom,sc8280xp-qmp-usb43dp-phy"; reg = <0 0x088eb000 0 0x4000>; @@ -2848,6 +3117,23 @@ #phy-cells = <1>; status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + usb_0_qmpphy_out: endpoint {}; + }; + + port@2 { + reg = <2>; + + usb_0_qmpphy_dp_in: endpoint {}; + }; + }; }; usb_1_hsphy: phy@8902000 { @@ -2884,6 +3170,23 @@ #phy-cells = <1>; status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + usb_1_qmpphy_out: endpoint {}; + }; + + port@2 { + reg = <2>; + + usb_1_qmpphy_dp_in: endpoint {}; + }; + }; }; mdss1_dp0_phy: phy@8909a00 { @@ -3908,7 +4211,7 @@ #size-cells = <2>; ranges; - gic-its@17a40000 { + msi-controller@17a40000 { compatible = "arm,gic-v3-its"; reg = <0 0x17a40000 0 0x20000>; msi-controller; @@ -4720,6 +5023,36 @@ status = "disabled"; }; + + ethernet1: ethernet@23000000 { + compatible = "qcom,sc8280xp-ethqos"; + reg = <0x0 0x23000000 0x0 0x10000>, + <0x0 0x23016000 0x0 0x100>; + reg-names = "stmmaceth", "rgmii"; + + clocks = <&gcc GCC_EMAC1_AXI_CLK>, + <&gcc GCC_EMAC1_SLV_AHB_CLK>, + <&gcc GCC_EMAC1_PTP_CLK>, + <&gcc GCC_EMAC1_RGMII_CLK>; + clock-names = "stmmaceth", + "pclk", + "ptp_ref", + "rgmii"; + + interrupts = , + ; + interrupt-names = "macirq", "eth_lpi"; + + iommus = <&apps_smmu 0x40 0xf>; + power-domains = <&gcc EMAC_1_GDSC>; + + snps,tso; + snps,pbl = <32>; + rx-fifo-depth = <4096>; + tx-fifo-depth = <4096>; + + status = "disabled"; + }; }; sound: sound { diff --git a/arch/arm64/boot/dts/qcom/sda660-inforce-ifc6560.dts b/arch/arm64/boot/dts/qcom/sda660-inforce-ifc6560.dts index 7459525d99828b5badfc2d0ca4afba3e99c4bf45..0b23d5bb3f26c0a50d4ee8099aac22ec69d0cb7d 100644 --- a/arch/arm64/boot/dts/qcom/sda660-inforce-ifc6560.dts +++ b/arch/arm64/boot/dts/qcom/sda660-inforce-ifc6560.dts @@ -134,7 +134,7 @@ reg = <0>; adv7533_in: endpoint { - remote-endpoint = <&dsi0_out>; + remote-endpoint = <&mdss_dsi0_out>; }; }; @@ -183,25 +183,25 @@ }; }; -&dsi0 { +&mdss { + status = "okay"; +}; + +&mdss_dsi0 { status = "okay"; vdda-supply = <&vreg_l1a_1p225>; }; -&dsi0_out { +&mdss_dsi0_out { remote-endpoint = <&adv7533_in>; data-lanes = <0 1 2 3>; }; -&dsi0_phy { +&mdss_dsi0_phy { status = "okay"; vcca-supply = <&vreg_l1b_0p925>; }; -&mdss { - status = "okay"; -}; - &mmss_smmu { status = "okay"; }; diff --git a/arch/arm64/boot/dts/qcom/sdm630-sony-xperia-nile.dtsi b/arch/arm64/boot/dts/qcom/sdm630-sony-xperia-nile.dtsi index 2ca713a3902a9f2c8c9d19f4c33ab1022a963997..3033723fc6ff3d68fa37f0a4a003acf267314a9f 100644 --- a/arch/arm64/boot/dts/qcom/sdm630-sony-xperia-nile.dtsi +++ b/arch/arm64/boot/dts/qcom/sdm630-sony-xperia-nile.dtsi @@ -138,11 +138,6 @@ no-map; }; - reserved@85800000 { - reg = <0x00 0x85800000 0x00 0x3700000>; - no-map; - }; - cont_splash_mem: splash@9d400000 { reg = <0 0x9d400000 0 (1920 * 1080 * 4)>; no-map; @@ -256,6 +251,10 @@ linux,code = ; }; +&qhee_code { + reg = <0x00 0x85800000 0x00 0x3700000>; +}; + &qusb2phy0 { status = "okay"; diff --git a/arch/arm64/boot/dts/qcom/sdm630.dtsi b/arch/arm64/boot/dts/qcom/sdm630.dtsi index eaead2f7beb4ea93a3e2c498c4455fc13fd0558c..bba0f366ef03bf72084b2d6779c2d91fd05a1572 100644 --- a/arch/arm64/boot/dts/qcom/sdm630.dtsi +++ b/arch/arm64/boot/dts/qcom/sdm630.dtsi @@ -550,7 +550,7 @@ }; }; - soc { + soc@0 { #address-cells = <1>; #size-cells = <1>; ranges = <0 0 0 0xffffffff>; @@ -1463,8 +1463,8 @@ <&sleep_clk>, <&gcc GCC_MMSS_GPLL0_CLK>, <&gcc GCC_MMSS_GPLL0_DIV_CLK>, - <&dsi0_phy 1>, - <&dsi0_phy 0>, + <&mdss_dsi0_phy 1>, + <&mdss_dsi0_phy 0>, <0>, <0>, <0>, @@ -1536,7 +1536,7 @@ port@0 { reg = <0>; mdp5_intf1_out: endpoint { - remote-endpoint = <&dsi0_in>; + remote-endpoint = <&mdss_dsi0_in>; }; }; }; @@ -1572,7 +1572,7 @@ }; }; - dsi0: dsi@c994000 { + mdss_dsi0: dsi@c994000 { compatible = "qcom,sdm660-dsi-ctrl", "qcom,mdss-dsi-ctrl"; reg = <0x0c994000 0x400>; @@ -1586,8 +1586,8 @@ assigned-clocks = <&mmcc BYTE0_CLK_SRC>, <&mmcc PCLK0_CLK_SRC>; - assigned-clock-parents = <&dsi0_phy 0>, - <&dsi0_phy 1>; + assigned-clock-parents = <&mdss_dsi0_phy 0>, + <&mdss_dsi0_phy 1>; clocks = <&mmcc MDSS_MDP_CLK>, <&mmcc MDSS_BYTE0_CLK>, @@ -1608,7 +1608,7 @@ "pixel", "core"; - phys = <&dsi0_phy>; + phys = <&mdss_dsi0_phy>; status = "disabled"; @@ -1618,20 +1618,20 @@ port@0 { reg = <0>; - dsi0_in: endpoint { + mdss_dsi0_in: endpoint { remote-endpoint = <&mdp5_intf1_out>; }; }; port@1 { reg = <1>; - dsi0_out: endpoint { + mdss_dsi0_out: endpoint { }; }; }; }; - dsi0_phy: phy@c994400 { + mdss_dsi0_phy: phy@c994400 { compatible = "qcom,dsi-phy-14nm-660"; reg = <0x0c994400 0x100>, <0x0c994500 0x300>, @@ -1894,7 +1894,7 @@ }; }; - camss: camss@ca00000 { + camss: camss@ca00020 { compatible = "qcom,sdm660-camss"; reg = <0x0ca00020 0x10>, <0x0ca30000 0x100>, diff --git a/arch/arm64/boot/dts/qcom/sdm632-fairphone-fp3.dts b/arch/arm64/boot/dts/qcom/sdm632-fairphone-fp3.dts index 70e683b7e4fce3acf4acf949193116f5ac33b4b3..301eca9a4f313c7dbf24ce942adabbe6c0607ec3 100644 --- a/arch/arm64/boot/dts/qcom/sdm632-fairphone-fp3.dts +++ b/arch/arm64/boot/dts/qcom/sdm632-fairphone-fp3.dts @@ -4,8 +4,10 @@ */ /dts-v1/; +#include #include "sdm632.dtsi" #include "pm8953.dtsi" +#include "pmi632.dtsi" / { model = "Fairphone 3"; @@ -83,6 +85,33 @@ linux,code = ; }; +&pmi632_lpg { + status = "okay"; + + multi-led { + color = ; + function = LED_FUNCTION_STATUS; + + #address-cells = <1>; + #size-cells = <0>; + + led@1 { + reg = <1>; + color = ; + }; + + led@2 { + reg = <2>; + color = ; + }; + + led@3 { + reg = <3>; + color = ; + }; + }; +}; + &sdhc_1 { status = "okay"; vmmc-supply = <&pm8953_l8>; diff --git a/arch/arm64/boot/dts/qcom/sdm660.dtsi b/arch/arm64/boot/dts/qcom/sdm660.dtsi index f0f27fc12c18ec621ee05569a059b98fcd886e31..f89b27c99f40cf0c2edb71aa2e54c413971d0989 100644 --- a/arch/arm64/boot/dts/qcom/sdm660.dtsi +++ b/arch/arm64/boot/dts/qcom/sdm660.dtsi @@ -148,14 +148,14 @@ port@1 { reg = <1>; mdp5_intf2_out: endpoint { - remote-endpoint = <&dsi1_in>; + remote-endpoint = <&mdss_dsi1_in>; }; }; }; }; &mdss { - dsi1: dsi@c996000 { + mdss_dsi1: dsi@c996000 { compatible = "qcom,sdm660-dsi-ctrl", "qcom,mdss-dsi-ctrl"; reg = <0x0c996000 0x400>; @@ -170,8 +170,8 @@ assigned-clocks = <&mmcc BYTE1_CLK_SRC>, <&mmcc PCLK1_CLK_SRC>; - assigned-clock-parents = <&dsi1_phy 0>, - <&dsi1_phy 1>; + assigned-clock-parents = <&mdss_dsi1_phy 0>, + <&mdss_dsi1_phy 1>; clocks = <&mmcc MDSS_MDP_CLK>, <&mmcc MDSS_BYTE1_CLK>, @@ -192,7 +192,7 @@ "pixel", "core"; - phys = <&dsi1_phy>; + phys = <&mdss_dsi1_phy>; status = "disabled"; @@ -202,20 +202,20 @@ port@0 { reg = <0>; - dsi1_in: endpoint { + mdss_dsi1_in: endpoint { remote-endpoint = <&mdp5_intf2_out>; }; }; port@1 { reg = <1>; - dsi1_out: endpoint { + mdss_dsi1_out: endpoint { }; }; }; }; - dsi1_phy: phy@c996400 { + mdss_dsi1_phy: phy@c996400 { compatible = "qcom,dsi-phy-14nm-660"; reg = <0x0c996400 0x100>, <0x0c996500 0x300>, @@ -239,10 +239,10 @@ <&sleep_clk>, <&gcc GCC_MMSS_GPLL0_CLK>, <&gcc GCC_MMSS_GPLL0_DIV_CLK>, - <&dsi0_phy 1>, - <&dsi0_phy 0>, - <&dsi1_phy 1>, - <&dsi1_phy 0>, + <&mdss_dsi0_phy 1>, + <&mdss_dsi0_phy 0>, + <&mdss_dsi1_phy 1>, + <&mdss_dsi1_phy 0>, <0>, <0>; }; diff --git a/arch/arm64/boot/dts/qcom/sdm670.dtsi b/arch/arm64/boot/dts/qcom/sdm670.dtsi index b61e13db89bd58fcfb012d0c0d8e5f1e8ff7fb8a..a1c207c0266dab6242a3d8c56b15677288115682 100644 --- a/arch/arm64/boot/dts/qcom/sdm670.dtsi +++ b/arch/arm64/boot/dts/qcom/sdm670.dtsi @@ -1282,6 +1282,7 @@ , , ; + power-domains = <&CLUSTER_PD>; apps_bcm_voter: bcm-voter { compatible = "qcom,bcm-voter"; diff --git a/arch/arm64/boot/dts/qcom/sdm845-cheza.dtsi b/arch/arm64/boot/dts/qcom/sdm845-cheza.dtsi index d05c511718df8b055c1d8bedd441df65e70f1c01..1ce413263b7f99a7f67e9ab0b94f95d0cf5b3490 100644 --- a/arch/arm64/boot/dts/qcom/sdm845-cheza.dtsi +++ b/arch/arm64/boot/dts/qcom/sdm845-cheza.dtsi @@ -636,25 +636,6 @@ }; }; -&dsi0 { - status = "okay"; - vdda-supply = <&vdda_mipi_dsi0_1p2>; - - ports { - port@1 { - endpoint { - remote-endpoint = <&sn65dsi86_in>; - data-lanes = <0 1 2 3>; - }; - }; - }; -}; - -&dsi0_phy { - status = "okay"; - vdds-supply = <&vdda_mipi_dsi0_pll>; -}; - edp_brij_i2c: &i2c3 { status = "okay"; clock-frequency = <400000>; @@ -687,7 +668,7 @@ edp_brij_i2c: &i2c3 { port@0 { reg = <0>; sn65dsi86_in: endpoint { - remote-endpoint = <&dsi0_out>; + remote-endpoint = <&mdss_dsi0_out>; }; }; @@ -767,6 +748,25 @@ ap_ts_i2c: &i2c14 { status = "okay"; }; +&mdss_dsi0 { + status = "okay"; + vdda-supply = <&vdda_mipi_dsi0_1p2>; + + ports { + port@1 { + endpoint { + remote-endpoint = <&sn65dsi86_in>; + data-lanes = <0 1 2 3>; + }; + }; + }; +}; + +&mdss_dsi0_phy { + status = "okay"; + vdds-supply = <&vdda_mipi_dsi0_pll>; +}; + /* * Cheza fw does not properly program the GPU aperture to allow the * GPU to update the SMMU pagetables for context switches. Work diff --git a/arch/arm64/boot/dts/qcom/sdm845-db845c.dts b/arch/arm64/boot/dts/qcom/sdm845-db845c.dts index e14fe9bbb386a0132e8c5bf8a68cb92ba709238d..d6b464cb61d6f88a3a61981d7e4d5489e3fef426 100644 --- a/arch/arm64/boot/dts/qcom/sdm845-db845c.dts +++ b/arch/arm64/boot/dts/qcom/sdm845-db845c.dts @@ -415,25 +415,6 @@ firmware-name = "qcom/sdm845/cdsp.mbn"; }; -&dsi0 { - status = "okay"; - vdda-supply = <&vreg_l26a_1p2>; - - ports { - port@1 { - endpoint { - remote-endpoint = <<9611_a>; - data-lanes = <0 1 2 3>; - }; - }; - }; -}; - -&dsi0_phy { - status = "okay"; - vdds-supply = <&vreg_l1a_0p875>; -}; - &gcc { protected-clocks = , , @@ -489,7 +470,15 @@ reg = <0>; lt9611_a: endpoint { - remote-endpoint = <&dsi0_out>; + remote-endpoint = <&mdss_dsi0_out>; + }; + }; + + port@1 { + reg = <1>; + + lt9611_b: endpoint { + remote-endpoint = <&mdss_dsi1_out>; }; }; @@ -520,6 +509,53 @@ status = "okay"; }; +&mdss_dsi0 { + status = "okay"; + vdda-supply = <&vreg_l26a_1p2>; + + qcom,dual-dsi-mode; + qcom,master-dsi; + + ports { + port@1 { + endpoint { + remote-endpoint = <<9611_a>; + data-lanes = <0 1 2 3>; + }; + }; + }; +}; + +&mdss_dsi0_phy { + status = "okay"; + vdds-supply = <&vreg_l1a_0p875>; +}; + +&mdss_dsi1 { + vdda-supply = <&vreg_l26a_1p2>; + + qcom,dual-dsi-mode; + + /* DSI1 is slave, so use DSI0 clocks */ + assigned-clock-parents = <&mdss_dsi0_phy 0>, <&mdss_dsi0_phy 1>; + + status = "okay"; + + ports { + port@1 { + endpoint { + remote-endpoint = <<9611_b>; + data-lanes = <0 1 2 3>; + }; + }; + }; +}; + +&mdss_dsi1_phy { + vdds-supply = <&vreg_l1a_0p875>; + status = "okay"; +}; + &mss_pil { status = "okay"; firmware-name = "qcom/sdm845/mba.mbn", "qcom/sdm845/modem.mbn"; @@ -649,10 +685,6 @@ }; }; -&pmi8998_rradc { - status = "okay"; -}; - /* QUAT I2S Uses 4 I2S SD Lines for audio on LT9611 HDMI Bridge */ &q6afedai { dai@22 { diff --git a/arch/arm64/boot/dts/qcom/sdm845-mtp.dts b/arch/arm64/boot/dts/qcom/sdm845-mtp.dts index d1440b790fa6d88dc9a4a5f17294e32cbc6fb037..b2d4336e764bfd3c66144c8482ea9a1caa963404 100644 --- a/arch/arm64/boot/dts/qcom/sdm845-mtp.dts +++ b/arch/arm64/boot/dts/qcom/sdm845-mtp.dts @@ -417,7 +417,43 @@ firmware-name = "qcom/sdm845/cdsp.mdt"; }; -&dsi0 { +&gcc { + protected-clocks = , + , + , + , + ; +}; + +&gmu { + status = "okay"; +}; + +&gpu { + status = "okay"; + + zap-shader { + memory-region = <&gpu_mem>; + firmware-name = "qcom/sdm845/a630_zap.mbn"; + }; +}; + +&i2c10 { + status = "okay"; + clock-frequency = <400000>; +}; + +&ipa { + qcom,gsi-loader = "self"; + memory-region = <&ipa_fw_mem>; + status = "okay"; +}; + +&mdss { + status = "okay"; +}; + +&mdss_dsi0 { status = "okay"; vdda-supply = <&vdda_mipi_dsi0_1p2>; @@ -448,33 +484,33 @@ port@0 { reg = <0>; truly_in_0: endpoint { - remote-endpoint = <&dsi0_out>; + remote-endpoint = <&mdss_dsi0_out>; }; }; port@1 { reg = <1>; truly_in_1: endpoint { - remote-endpoint = <&dsi1_out>; + remote-endpoint = <&mdss_dsi1_out>; }; }; }; }; }; -&dsi0_phy { +&mdss_dsi0_phy { status = "okay"; vdds-supply = <&vdda_mipi_dsi0_pll>; }; -&dsi1 { +&mdss_dsi1 { status = "okay"; vdda-supply = <&vdda_mipi_dsi1_1p2>; qcom,dual-dsi-mode; /* DSI1 is slave, so use DSI0 clocks */ - assigned-clock-parents = <&dsi0_phy 0>, <&dsi0_phy 1>; + assigned-clock-parents = <&mdss_dsi0_phy 0>, <&mdss_dsi0_phy 1>; ports { port@1 { @@ -486,47 +522,11 @@ }; }; -&dsi1_phy { +&mdss_dsi1_phy { status = "okay"; vdds-supply = <&vdda_mipi_dsi1_pll>; }; -&gcc { - protected-clocks = , - , - , - , - ; -}; - -&gmu { - status = "okay"; -}; - -&gpu { - status = "okay"; - - zap-shader { - memory-region = <&gpu_mem>; - firmware-name = "qcom/sdm845/a630_zap.mbn"; - }; -}; - -&i2c10 { - status = "okay"; - clock-frequency = <400000>; -}; - -&ipa { - qcom,gsi-loader = "self"; - memory-region = <&ipa_fw_mem>; - status = "okay"; -}; - -&mdss { - status = "okay"; -}; - &mss_pil { status = "okay"; firmware-name = "qcom/sdm845/mba.mbn", "qcom/sdm845/modem.mbn"; diff --git a/arch/arm64/boot/dts/qcom/sdm845-oneplus-common.dtsi b/arch/arm64/boot/dts/qcom/sdm845-oneplus-common.dtsi index 5c384345c05d2ae1fdf338249c047f42b0666262..122c7128dea9da3aa2d609191d2ac3b012d0c55e 100644 --- a/arch/arm64/boot/dts/qcom/sdm845-oneplus-common.dtsi +++ b/arch/arm64/boot/dts/qcom/sdm845-oneplus-common.dtsi @@ -336,44 +336,6 @@ firmware-name = "qcom/sdm845/oneplus6/cdsp.mbn"; }; -&dsi0 { - status = "okay"; - vdda-supply = <&vdda_mipi_dsi0_1p2>; - - /* - * Both devices use different panels but all other properties - * are common. Compatible line is declared in device dts. - */ - display_panel: panel@0 { - status = "disabled"; - - reg = <0>; - - vddio-supply = <&vreg_l14a_1p88>; - - reset-gpios = <&tlmm 6 GPIO_ACTIVE_LOW>; - - pinctrl-names = "default"; - pinctrl-0 = <&panel_reset_pins &panel_te_pin &panel_esd_pin>; - - port { - panel_in: endpoint { - remote-endpoint = <&dsi0_out>; - }; - }; - }; -}; - -&dsi0_out { - remote-endpoint = <&panel_in>; - data-lanes = <0 1 2 3>; -}; - -&dsi0_phy { - status = "okay"; - vdds-supply = <&vdda_mipi_dsi0_pll>; -}; - &gcc { protected-clocks = , , @@ -452,6 +414,44 @@ status = "okay"; }; +&mdss_dsi0 { + status = "okay"; + vdda-supply = <&vdda_mipi_dsi0_1p2>; + + /* + * Both devices use different panels but all other properties + * are common. Compatible line is declared in device dts. + */ + display_panel: panel@0 { + status = "disabled"; + + reg = <0>; + + vddio-supply = <&vreg_l14a_1p88>; + + reset-gpios = <&tlmm 6 GPIO_ACTIVE_LOW>; + + pinctrl-names = "default"; + pinctrl-0 = <&panel_reset_pins &panel_te_pin &panel_esd_pin>; + + port { + panel_in: endpoint { + remote-endpoint = <&mdss_dsi0_out>; + }; + }; + }; +}; + +&mdss_dsi0_out { + remote-endpoint = <&panel_in>; + data-lanes = <0 1 2 3>; +}; + +&mdss_dsi0_phy { + status = "okay"; + vdds-supply = <&vdda_mipi_dsi0_pll>; +}; + /* Modem/wifi */ &mss_pil { status = "okay"; @@ -480,7 +480,7 @@ }; }; -&pmi8998_rradc { +&pmi8998_charger { status = "okay"; }; diff --git a/arch/arm64/boot/dts/qcom/sdm845-oneplus-enchilada.dts b/arch/arm64/boot/dts/qcom/sdm845-oneplus-enchilada.dts index 6cdda971bb4bfefcf1cbaf21225baf10b69ac058..623a826b18a3ec5a98f91a939e494206006b133f 100644 --- a/arch/arm64/boot/dts/qcom/sdm845-oneplus-enchilada.dts +++ b/arch/arm64/boot/dts/qcom/sdm845-oneplus-enchilada.dts @@ -51,6 +51,10 @@ }; }; +&pmi8998_charger { + monitored-battery = <&battery>; +}; + &sound { model = "OnePlus 6"; audio-routing = "RX_BIAS", "MCLK", diff --git a/arch/arm64/boot/dts/qcom/sdm845-oneplus-fajita.dts b/arch/arm64/boot/dts/qcom/sdm845-oneplus-fajita.dts index d82c0d4407f061a5ed1311aa158aa3f3b4df4f22..9471ada0d6ad8bd44cc58a6efa07f7eb27921af9 100644 --- a/arch/arm64/boot/dts/qcom/sdm845-oneplus-fajita.dts +++ b/arch/arm64/boot/dts/qcom/sdm845-oneplus-fajita.dts @@ -47,6 +47,10 @@ "AMIC5", "MIC BIAS3"; }; +&pmi8998_charger { + monitored-battery = <&battery>; +}; + /* * The TFA9894 codec is currently unsupported. * We need to delete the node to allow the soundcard diff --git a/arch/arm64/boot/dts/qcom/sdm845-shift-axolotl.dts b/arch/arm64/boot/dts/qcom/sdm845-shift-axolotl.dts index 0ad891348e0c39edeb5a3bea6a5713044ac464b8..dce0141f371904d1074365c069665f2002fc533e 100644 --- a/arch/arm64/boot/dts/qcom/sdm845-shift-axolotl.dts +++ b/arch/arm64/boot/dts/qcom/sdm845-shift-axolotl.dts @@ -411,44 +411,6 @@ firmware-name = "qcom/sdm845/axolotl/cdsp.mbn"; }; -&dsi0 { - status = "okay"; - vdda-supply = <&vdda_mipi_dsi0_1p2>; - - panel@0 { - compatible = "visionox,rm69299-shift"; - status = "okay"; - reg = <0>; - vdda-supply = <&vreg_l14a_1p88>; - vdd3p3-supply = <&vreg_l28a_3p0>; - - #address-cells = <1>; - #size-cells = <0>; - - reset-gpios = <&tlmm 6 GPIO_ACTIVE_HIGH>; - - pinctrl-names = "default", "sleep"; - pinctrl-0 = <&sde_dsi_active &sde_te_active>; - pinctrl-1 = <&sde_dsi_suspend &sde_te_suspend>; - - port { - panel_in_0: endpoint { - remote-endpoint = <&dsi0_out>; - }; - }; - }; -}; - -&dsi0_out { - remote-endpoint = <&panel_in_0>; - data-lanes = <0 1 2 3>; -}; - -&dsi0_phy { - status = "okay"; - vdds-supply = <&vdda_mipi_dsi0_pll>; -}; - &gcc { protected-clocks = , , @@ -494,6 +456,10 @@ }; }; +&i2c10 { + /* SMB1355@0x0C */ +}; + &ipa { qcom,gsi-loader = "self"; memory-region = <&ipa_fw_mem>; @@ -505,6 +471,44 @@ status = "okay"; }; +&mdss_dsi0 { + status = "okay"; + vdda-supply = <&vdda_mipi_dsi0_1p2>; + + panel@0 { + compatible = "visionox,rm69299-shift"; + status = "okay"; + reg = <0>; + vdda-supply = <&vreg_l14a_1p88>; + vdd3p3-supply = <&vreg_l28a_3p0>; + + #address-cells = <1>; + #size-cells = <0>; + + reset-gpios = <&tlmm 6 GPIO_ACTIVE_HIGH>; + + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&sde_dsi_active &sde_te_active>; + pinctrl-1 = <&sde_dsi_suspend &sde_te_suspend>; + + port { + panel_in_0: endpoint { + remote-endpoint = <&mdss_dsi0_out>; + }; + }; + }; +}; + +&mdss_dsi0_out { + remote-endpoint = <&panel_in_0>; + data-lanes = <0 1 2 3>; +}; + +&mdss_dsi0_phy { + status = "okay"; + vdds-supply = <&vdda_mipi_dsi0_pll>; +}; + &mss_pil { status = "okay"; firmware-name = "qcom/sdm845/axolotl/mba.mbn", "qcom/sdm845/axolotl/modem.mbn"; @@ -522,6 +526,12 @@ }; }; +&pmi8998_charger { + monitored-battery = <&battery>; + + status = "okay"; +}; + &pm8998_resin { linux,code = ; status = "okay"; @@ -554,6 +564,28 @@ }; }; +&pmi8998_flash { + status = "okay"; + + led-0 { + function = LED_FUNCTION_FLASH; + color = ; + led-sources = <1>; + led-max-microamp = <100000>; + flash-max-microamp = <1100000>; + flash-max-timeout-us = <1280000>; + }; + + led-1 { + function = LED_FUNCTION_FLASH; + color = ; + led-sources = <2>; + led-max-microamp = <100000>; + flash-max-microamp = <1100000>; + flash-max-timeout-us = <1280000>; + }; +}; + &qup_uart9_rx { drive-strength = <2>; bias-pull-up; diff --git a/arch/arm64/boot/dts/qcom/sdm845-sony-xperia-tama.dtsi b/arch/arm64/boot/dts/qcom/sdm845-sony-xperia-tama.dtsi index 420ffede3e8047ec364749984e1711f70487e67e..3bc187a066aebf3ddcb0a0ab236840cb0187d987 100644 --- a/arch/arm64/boot/dts/qcom/sdm845-sony-xperia-tama.dtsi +++ b/arch/arm64/boot/dts/qcom/sdm845-sony-xperia-tama.dtsi @@ -368,43 +368,6 @@ status = "okay"; }; -&dsi0 { - vdda-supply = <&vreg_l26a_1p2>; - status = "okay"; - - panel: panel@0 { - /* The compatible is assigned in device DTs. */ - reg = <0>; - - backlight = <&pmi8998_wled>; - vddio-supply = <&vreg_l14a_1p8>; - vsp-supply = <&lab>; - vsn-supply = <&ibb>; - panel-reset-gpios = <&tlmm 6 GPIO_ACTIVE_HIGH>; - touch-reset-gpios = <&tlmm 99 GPIO_ACTIVE_HIGH>; - - pinctrl-0 = <&sde_dsi_active &sde_te_active_sleep>; - pinctrl-1 = <&sde_dsi_sleep &sde_te_active_sleep>; - pinctrl-names = "default", "sleep"; - - port { - panel_in: endpoint { - remote-endpoint = <&dsi0_out>; - }; - }; - }; -}; - -&dsi0_out { - remote-endpoint = <&panel_in>; - data-lanes = <0 1 2 3>; -}; - -&dsi0_phy { - vdds-supply = <&vreg_l1a_0p9>; - status = "okay"; -}; - &gcc { protected-clocks = , , @@ -515,6 +478,43 @@ status = "okay"; }; +&mdss_dsi0 { + vdda-supply = <&vreg_l26a_1p2>; + status = "okay"; + + panel: panel@0 { + /* The compatible is assigned in device DTs. */ + reg = <0>; + + backlight = <&pmi8998_wled>; + vddio-supply = <&vreg_l14a_1p8>; + vsp-supply = <&lab>; + vsn-supply = <&ibb>; + panel-reset-gpios = <&tlmm 6 GPIO_ACTIVE_HIGH>; + touch-reset-gpios = <&tlmm 99 GPIO_ACTIVE_HIGH>; + + pinctrl-0 = <&sde_dsi_active &sde_te_active_sleep>; + pinctrl-1 = <&sde_dsi_sleep &sde_te_active_sleep>; + pinctrl-names = "default", "sleep"; + + port { + panel_in: endpoint { + remote-endpoint = <&mdss_dsi0_out>; + }; + }; + }; +}; + +&mdss_dsi0_out { + remote-endpoint = <&panel_in>; + data-lanes = <0 1 2 3>; +}; + +&mdss_dsi0_phy { + vdds-supply = <&vreg_l1a_0p9>; + status = "okay"; +}; + &pm8998_gpios { focus_n: focus-n-state { pins = "gpio2"; diff --git a/arch/arm64/boot/dts/qcom/sdm845-xiaomi-beryllium-common.dtsi b/arch/arm64/boot/dts/qcom/sdm845-xiaomi-beryllium-common.dtsi index 5ed975cc6ecbadcb322962820e71a81e34c9d72e..9d6faeb6562441381d3302cc763251fd5401cc11 100644 --- a/arch/arm64/boot/dts/qcom/sdm845-xiaomi-beryllium-common.dtsi +++ b/arch/arm64/boot/dts/qcom/sdm845-xiaomi-beryllium-common.dtsi @@ -115,6 +115,14 @@ }; }; + battery: battery { + compatible = "simple-battery"; + + charge-full-design-microamp-hours = <4000000>; + voltage-min-design-microvolt = <3400000>; + voltage-max-design-microvolt = <4400000>; + }; + vreg_s4a_1p8: vreg-s4a-1p8 { compatible = "regulator-fixed"; regulator-name = "vreg_s4a_1p8"; @@ -223,39 +231,6 @@ firmware-name = "qcom/sdm845/beryllium/cdsp.mbn"; }; -&dsi0 { - status = "okay"; - vdda-supply = <&vreg_l26a_1p2>; - - display_panel: panel@0 { - reg = <0>; - vddio-supply = <&vreg_l14a_1p8>; - vddpos-supply = <&lab>; - vddneg-supply = <&ibb>; - - backlight = <&pmi8998_wled>; - reset-gpios = <&tlmm 6 GPIO_ACTIVE_LOW>; - - status = "disabled"; - - port { - panel_in_0: endpoint { - remote-endpoint = <&dsi0_out>; - }; - }; - }; -}; - -&dsi0_out { - remote-endpoint = <&panel_in_0>; - data-lanes = <0 1 2 3>; -}; - -&dsi0_phy { - status = "okay"; - vdds-supply = <&vreg_l1a_0p875>; -}; - &gcc { protected-clocks = , , @@ -298,6 +273,39 @@ status = "okay"; }; +&mdss_dsi0 { + status = "okay"; + vdda-supply = <&vreg_l26a_1p2>; + + display_panel: panel@0 { + reg = <0>; + vddio-supply = <&vreg_l14a_1p8>; + vddpos-supply = <&lab>; + vddneg-supply = <&ibb>; + + backlight = <&pmi8998_wled>; + reset-gpios = <&tlmm 6 GPIO_ACTIVE_LOW>; + + status = "disabled"; + + port { + panel_in_0: endpoint { + remote-endpoint = <&mdss_dsi0_out>; + }; + }; + }; +}; + +&mdss_dsi0_out { + remote-endpoint = <&panel_in_0>; + data-lanes = <0 1 2 3>; +}; + +&mdss_dsi0_phy { + status = "okay"; + vdds-supply = <&vreg_l1a_0p875>; +}; + &mss_pil { status = "okay"; firmware-name = "qcom/sdm845/beryllium/mba.mbn", "qcom/sdm845/beryllium/modem.mbn"; @@ -341,12 +349,14 @@ qcom,cabc; }; -&pm8998_resin { - linux,code = ; +&pmi8998_charger { + monitored-battery = <&battery>; + status = "okay"; }; -&pmi8998_rradc { +&pm8998_resin { + linux,code = ; status = "okay"; }; diff --git a/arch/arm64/boot/dts/qcom/sdm845-xiaomi-polaris.dts b/arch/arm64/boot/dts/qcom/sdm845-xiaomi-polaris.dts index 8ae0ffccaab22ea18b664ed170103b55317a78ad..6db12abaa88d17b0988ec63be162054e5623a50c 100644 --- a/arch/arm64/boot/dts/qcom/sdm845-xiaomi-polaris.dts +++ b/arch/arm64/boot/dts/qcom/sdm845-xiaomi-polaris.dts @@ -373,44 +373,6 @@ status = "okay"; }; -&dsi0 { - vdda-supply = <&vdda_mipi_dsi0_1p2>; - status = "okay"; - - display_panel: panel@0 { - compatible = "jdi,fhd-nt35596s"; - #address-cells = <1>; - #size-cells = <0>; - reg = <0>; - - reset-gpios = <&tlmm 6 GPIO_ACTIVE_LOW>; - vddio-supply = <&vreg_l14a_1p8>; - backlight = <&pmi8998_wled>; - vddpos-supply = <&lab>; - vddneg-supply = <&ibb>; - - pinctrl-names = "default", "sleep"; - pinctrl-0 = <&sde_dsi_active>; - pinctrl-1 = <&sde_dsi_suspend>; - - port { - panel_in: endpoint { - remote-endpoint = <&dsi0_out>; - }; - }; - }; -}; - -&dsi0_out { - remote-endpoint = <&panel_in>; - data-lanes = <0 1 2 3>; -}; - -&dsi0_phy { - vdds-supply = <&vdda_mipi_dsi0_pll>; - status = "okay"; -}; - &gcc { protected-clocks = , , @@ -483,6 +445,7 @@ }; rmi4-f12@12 { + reg = <0x12>; syna,rezero-wait-ms = <0xc8>; syna,clip-x-high = <0x438>; syna,clip-y-high = <0x870>; @@ -504,6 +467,44 @@ status = "okay"; }; +&mdss_dsi0 { + vdda-supply = <&vdda_mipi_dsi0_1p2>; + status = "okay"; + + display_panel: panel@0 { + compatible = "jdi,fhd-nt35596s"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0>; + + reset-gpios = <&tlmm 6 GPIO_ACTIVE_LOW>; + vddio-supply = <&vreg_l14a_1p8>; + backlight = <&pmi8998_wled>; + vddpos-supply = <&lab>; + vddneg-supply = <&ibb>; + + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&sde_dsi_active>; + pinctrl-1 = <&sde_dsi_suspend>; + + port { + panel_in: endpoint { + remote-endpoint = <&mdss_dsi0_out>; + }; + }; + }; +}; + +&mdss_dsi0_out { + remote-endpoint = <&panel_in>; + data-lanes = <0 1 2 3>; +}; + +&mdss_dsi0_phy { + vdds-supply = <&vdda_mipi_dsi0_pll>; + status = "okay"; +}; + &mss_pil { firmware-name = "qcom/sdm845/polaris/mba.mbn", "qcom/sdm845/polaris/modem.mbn"; status = "okay"; diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi index cdeb05e95674e9d490b37b26e008f98599b8476e..02a6ea0b8b2c9bd0a45c0b612243acf03ccaae2a 100644 --- a/arch/arm64/boot/dts/qcom/sdm845.dtsi +++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi @@ -3899,6 +3899,7 @@ qspi: spi@88df000 { compatible = "qcom,sdm845-qspi", "qcom,qspi-v1"; reg = <0 0x088df000 0 0x600>; + iommus = <&apps_smmu 0x160 0x0>; #address-cells = <1>; #size-cells = <0>; interrupts = ; @@ -4238,7 +4239,7 @@ #reset-cells = <1>; }; - camss: camss@a00000 { + camss: camss@acb3000 { compatible = "qcom,sdm845-camss"; reg = <0 0x0acb3000 0 0x1000>, @@ -4509,14 +4510,14 @@ port@1 { reg = <1>; dpu_intf1_out: endpoint { - remote-endpoint = <&dsi0_in>; + remote-endpoint = <&mdss_dsi0_in>; }; }; port@2 { reg = <2>; dpu_intf2_out: endpoint { - remote-endpoint = <&dsi1_in>; + remote-endpoint = <&mdss_dsi1_in>; }; }; }; @@ -4616,7 +4617,7 @@ }; }; - dsi0: dsi@ae94000 { + mdss_dsi0: dsi@ae94000 { compatible = "qcom,sdm845-dsi-ctrl", "qcom,mdss-dsi-ctrl"; reg = <0 0x0ae94000 0 0x400>; @@ -4638,12 +4639,12 @@ "iface", "bus"; assigned-clocks = <&dispcc DISP_CC_MDSS_BYTE0_CLK_SRC>, <&dispcc DISP_CC_MDSS_PCLK0_CLK_SRC>; - assigned-clock-parents = <&dsi0_phy 0>, <&dsi0_phy 1>; + assigned-clock-parents = <&mdss_dsi0_phy 0>, <&mdss_dsi0_phy 1>; operating-points-v2 = <&dsi_opp_table>; power-domains = <&rpmhpd SDM845_CX>; - phys = <&dsi0_phy>; + phys = <&mdss_dsi0_phy>; status = "disabled"; @@ -4656,20 +4657,20 @@ port@0 { reg = <0>; - dsi0_in: endpoint { + mdss_dsi0_in: endpoint { remote-endpoint = <&dpu_intf1_out>; }; }; port@1 { reg = <1>; - dsi0_out: endpoint { + mdss_dsi0_out: endpoint { }; }; }; }; - dsi0_phy: phy@ae94400 { + mdss_dsi0_phy: phy@ae94400 { compatible = "qcom,dsi-phy-10nm"; reg = <0 0x0ae94400 0 0x200>, <0 0x0ae94600 0 0x280>, @@ -4688,7 +4689,7 @@ status = "disabled"; }; - dsi1: dsi@ae96000 { + mdss_dsi1: dsi@ae96000 { compatible = "qcom,sdm845-dsi-ctrl", "qcom,mdss-dsi-ctrl"; reg = <0 0x0ae96000 0 0x400>; @@ -4710,12 +4711,12 @@ "iface", "bus"; assigned-clocks = <&dispcc DISP_CC_MDSS_BYTE1_CLK_SRC>, <&dispcc DISP_CC_MDSS_PCLK1_CLK_SRC>; - assigned-clock-parents = <&dsi1_phy 0>, <&dsi1_phy 1>; + assigned-clock-parents = <&mdss_dsi1_phy 0>, <&mdss_dsi1_phy 1>; operating-points-v2 = <&dsi_opp_table>; power-domains = <&rpmhpd SDM845_CX>; - phys = <&dsi1_phy>; + phys = <&mdss_dsi1_phy>; status = "disabled"; @@ -4728,20 +4729,20 @@ port@0 { reg = <0>; - dsi1_in: endpoint { + mdss_dsi1_in: endpoint { remote-endpoint = <&dpu_intf2_out>; }; }; port@1 { reg = <1>; - dsi1_out: endpoint { + mdss_dsi1_out: endpoint { }; }; }; }; - dsi1_phy: phy@ae96400 { + mdss_dsi1_phy: phy@ae96400 { compatible = "qcom,dsi-phy-10nm"; reg = <0 0x0ae96400 0 0x200>, <0 0x0ae96600 0 0x280>, @@ -4903,10 +4904,10 @@ clocks = <&rpmhcc RPMH_CXO_CLK>, <&gcc GCC_DISP_GPLL0_CLK_SRC>, <&gcc GCC_DISP_GPLL0_DIV_CLK_SRC>, - <&dsi0_phy 0>, - <&dsi0_phy 1>, - <&dsi1_phy 0>, - <&dsi1_phy 1>, + <&mdss_dsi0_phy 0>, + <&mdss_dsi0_phy 1>, + <&mdss_dsi1_phy 0>, + <&mdss_dsi1_phy 1>, <&dp_phy 0>, <&dp_phy 1>; clock-names = "bi_tcxo", @@ -5137,6 +5138,7 @@ , , ; + power-domains = <&CLUSTER_PD>; apps_bcm_voter: bcm-voter { compatible = "qcom,bcm-voter"; @@ -5221,7 +5223,7 @@ }; slimbam: dma-controller@17184000 { - compatible = "qcom,bam-v1.7.0"; + compatible = "qcom,bam-v1.7.4", "qcom,bam-v1.7.0"; qcom,controlled-remotely; reg = <0 0x17184000 0 0x2a000>; num-channels = <31>; diff --git a/arch/arm64/boot/dts/qcom/sdm850-lenovo-yoga-c630.dts b/arch/arm64/boot/dts/qcom/sdm850-lenovo-yoga-c630.dts index 1326c171fe7282f2d4be63acab63cdaf28466115..cfbc4fc1eba9237eb5217b69bbabfc471d181f45 100644 --- a/arch/arm64/boot/dts/qcom/sdm850-lenovo-yoga-c630.dts +++ b/arch/arm64/boot/dts/qcom/sdm850-lenovo-yoga-c630.dts @@ -311,25 +311,6 @@ status = "okay"; }; -&dsi0 { - status = "okay"; - vdda-supply = <&vreg_l26a_1p2>; - - ports { - port@1 { - endpoint { - remote-endpoint = <&sn65dsi86_in_a>; - data-lanes = <0 1 2 3>; - }; - }; - }; -}; - -&dsi0_phy { - status = "okay"; - vdds-supply = <&vreg_l1a_0p875>; -}; - &gcc { protected-clocks = , , @@ -422,7 +403,7 @@ port@0 { reg = <0>; sn65dsi86_in_a: endpoint { - remote-endpoint = <&dsi0_out>; + remote-endpoint = <&mdss_dsi0_out>; }; }; @@ -475,6 +456,25 @@ status = "okay"; }; +&mdss_dsi0 { + status = "okay"; + vdda-supply = <&vreg_l26a_1p2>; + + ports { + port@1 { + endpoint { + remote-endpoint = <&sn65dsi86_in_a>; + data-lanes = <0 1 2 3>; + }; + }; + }; +}; + +&mdss_dsi0_phy { + status = "okay"; + vdds-supply = <&vreg_l1a_0p875>; +}; + &mss_pil { status = "okay"; firmware-name = "qcom/sdm850/LENOVO/81JL/qcdsp1v2850.mbn", "qcom/sdm850/LENOVO/81JL/qcdsp2850.mbn"; diff --git a/arch/arm64/boot/dts/qcom/sdx75-idp.dts b/arch/arm64/boot/dts/qcom/sdx75-idp.dts new file mode 100644 index 0000000000000000000000000000000000000000..cbe5cdf5a2282b3903c5a64f833874c006623a41 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/sdx75-idp.dts @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +/dts-v1/; + +#include "sdx75.dtsi" + +/ { + model = "Qualcomm Technologies, Inc. SDX75 IDP"; + compatible = "qcom,sdx75-idp", "qcom,sdx75"; + + aliases { + serial0 = &uart1; + }; +}; + +&chosen { + stdout-path = "serial0:115200n8"; +}; + +&qupv3_id_0 { + status = "okay"; +}; + +&tlmm { + gpio-reserved-ranges = <110 6>; +}; + +&uart1 { + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/qcom/sdx75.dtsi b/arch/arm64/boot/dts/qcom/sdx75.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..21d5d55da5ebf761f94fd2cb1c3dde36ceeffb7a --- /dev/null +++ b/arch/arm64/boot/dts/qcom/sdx75.dtsi @@ -0,0 +1,670 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * SDX75 SoC device tree source + * + * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved. + * + */ + +#include +#include +#include +#include + +/ { + #address-cells = <2>; + #size-cells = <2>; + interrupt-parent = <&intc>; + + chosen: chosen { }; + + clocks { + xo_board: xo-board { + compatible = "fixed-clock"; + clock-frequency = <76800000>; + #clock-cells = <0>; + }; + + sleep_clk: sleep-clk { + compatible = "fixed-clock"; + clock-frequency = <32000>; + #clock-cells = <0>; + }; + }; + + cpus { + #address-cells = <2>; + #size-cells = <0>; + + CPU0: cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a55"; + reg = <0x0 0x0>; + clocks = <&cpufreq_hw 0>; + enable-method = "psci"; + power-domains = <&CPU_PD0>; + power-domain-names = "psci"; + qcom,freq-domain = <&cpufreq_hw 0>; + capacity-dmips-mhz = <1024>; + dynamic-power-coefficient = <100>; + next-level-cache = <&L2_0>; + + L2_0: l2-cache { + compatible = "cache"; + cache-level = <2>; + cache-unified; + next-level-cache = <&L3_0>; + L3_0: l3-cache { + compatible = "cache"; + cache-level = <3>; + cache-unified; + }; + }; + }; + + CPU1: cpu@100 { + device_type = "cpu"; + compatible = "arm,cortex-a55"; + reg = <0x0 0x100>; + clocks = <&cpufreq_hw 0>; + enable-method = "psci"; + power-domains = <&CPU_PD1>; + power-domain-names = "psci"; + qcom,freq-domain = <&cpufreq_hw 0>; + capacity-dmips-mhz = <1024>; + dynamic-power-coefficient = <100>; + next-level-cache = <&L2_100>; + + L2_100: l2-cache { + compatible = "cache"; + cache-level = <2>; + cache-unified; + next-level-cache = <&L3_0>; + }; + }; + + CPU2: cpu@200 { + device_type = "cpu"; + compatible = "arm,cortex-a55"; + reg = <0x0 0x200>; + clocks = <&cpufreq_hw 0>; + enable-method = "psci"; + power-domains = <&CPU_PD2>; + power-domain-names = "psci"; + qcom,freq-domain = <&cpufreq_hw 0>; + capacity-dmips-mhz = <1024>; + dynamic-power-coefficient = <100>; + next-level-cache = <&L2_200>; + + L2_200: l2-cache { + compatible = "cache"; + cache-level = <2>; + cache-unified; + next-level-cache = <&L3_0>; + }; + }; + + CPU3: cpu@300 { + device_type = "cpu"; + compatible = "arm,cortex-a55"; + reg = <0x0 0x300>; + clocks = <&cpufreq_hw 0>; + enable-method = "psci"; + power-domains = <&CPU_PD3>; + power-domain-names = "psci"; + qcom,freq-domain = <&cpufreq_hw 0>; + capacity-dmips-mhz = <1024>; + dynamic-power-coefficient = <100>; + next-level-cache = <&L2_300>; + + L2_300: l2-cache { + compatible = "cache"; + cache-level = <2>; + cache-unified; + next-level-cache = <&L3_0>; + }; + }; + + cpu-map { + cluster0 { + core0 { + cpu = <&CPU0>; + }; + + core1 { + cpu = <&CPU1>; + }; + + core2 { + cpu = <&CPU2>; + }; + + core3 { + cpu = <&CPU3>; + }; + }; + }; + + idle-states { + entry-method = "psci"; + + CPU_OFF: cpu-sleep-0 { + compatible = "arm,idle-state"; + entry-latency-us = <235>; + exit-latency-us = <428>; + min-residency-us = <1774>; + arm,psci-suspend-param = <0x40000003>; + local-timer-stop; + }; + + CPU_RAIL_OFF: cpu-rail-sleep-1 { + compatible = "arm,idle-state"; + entry-latency-us = <800>; + exit-latency-us = <750>; + min-residency-us = <4090>; + arm,psci-suspend-param = <0x40000004>; + local-timer-stop; + }; + + }; + + domain-idle-states { + CLUSTER_SLEEP_0: cluster-sleep-0 { + compatible = "domain-idle-state"; + arm,psci-suspend-param = <0x41000044>; + entry-latency-us = <1050>; + exit-latency-us = <2500>; + min-residency-us = <5309>; + }; + + CLUSTER_SLEEP_1: cluster-sleep-1 { + compatible = "domain-idle-state"; + arm,psci-suspend-param = <0x41001344>; + entry-latency-us = <2761>; + exit-latency-us = <3964>; + min-residency-us = <8467>; + }; + + CLUSTER_SLEEP_2: cluster-sleep-2 { + compatible = "domain-idle-state"; + arm,psci-suspend-param = <0x4100b344>; + entry-latency-us = <2793>; + exit-latency-us = <4023>; + min-residency-us = <9826>; + }; + }; + }; + + firmware { + scm: scm { + compatible = "qcom,scm-sdx75", "qcom,scm"; + }; + }; + + memory@80000000 { + device_type = "memory"; + reg = <0x0 0x80000000 0x0 0x0>; + }; + + pmu { + compatible = "arm,armv8-pmuv3"; + interrupts = ; + }; + + psci { + compatible = "arm,psci-1.0"; + method = "smc"; + + CPU_PD0: power-domain-cpu0 { + #power-domain-cells = <0>; + power-domains = <&CLUSTER_PD>; + domain-idle-states = <&CPU_OFF &CPU_RAIL_OFF>; + }; + + CPU_PD1: power-domain-cpu1 { + #power-domain-cells = <0>; + power-domains = <&CLUSTER_PD>; + domain-idle-states = <&CPU_OFF &CPU_RAIL_OFF>; + }; + + CPU_PD2: power-domain-cpu2 { + #power-domain-cells = <0>; + power-domains = <&CLUSTER_PD>; + domain-idle-states = <&CPU_OFF &CPU_RAIL_OFF>; + }; + + CPU_PD3: power-domain-cpu3 { + #power-domain-cells = <0>; + power-domains = <&CLUSTER_PD>; + domain-idle-states = <&CPU_OFF &CPU_RAIL_OFF>; + }; + + CLUSTER_PD: power-domain-cpu-cluster0 { + #power-domain-cells = <0>; + domain-idle-states = <&CLUSTER_SLEEP_0 &CLUSTER_SLEEP_1 &CLUSTER_SLEEP_2>; + }; + }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + + gunyah_hyp_mem: gunyah-hyp@80000000 { + reg = <0x0 0x80000000 0x0 0x800000>; + no-map; + }; + + hyp_elf_package_mem: hyp-elf-package@80800000 { + reg = <0x0 0x80800000 0x0 0x200000>; + no-map; + }; + + access_control_db_mem: access-control-db@81380000 { + reg = <0x0 0x81380000 0x0 0x80000>; + no-map; + }; + + qteetz_mem: qteetz@814e0000 { + reg = <0x0 0x814e0000 0x0 0x2a0000>; + no-map; + }; + + trusted_apps_mem: trusted-apps@81780000 { + reg = <0x0 0x81780000 0x0 0xa00000>; + no-map; + }; + + xbl_ramdump_mem: xbl-ramdump@87a00000 { + reg = <0x0 0x87a00000 0x0 0x1c0000>; + no-map; + }; + + cpucp_fw_mem: cpucp-fw@87c00000 { + reg = <0x0 0x87c00000 0x0 0x100000>; + no-map; + }; + + xbl_dtlog_mem: xbl-dtlog@87d00000 { + reg = <0x0 0x87d00000 0x0 0x40000>; + no-map; + }; + + xbl_sc_mem: xbl-sc@87d40000 { + reg = <0x0 0x87d40000 0x0 0x40000>; + no-map; + }; + + modem_efs_shared_mem: modem-efs-shared@87d80000 { + reg = <0x0 0x87d80000 0x0 0x10000>; + no-map; + }; + + aop_image_mem: aop-image@87e00000 { + reg = <0x0 0x87e00000 0x0 0x20000>; + no-map; + }; + + smem_mem: smem@87e20000 { + reg = <0x0 0x87e20000 0x0 0xc0000>; + no-map; + }; + + aop_cmd_db_mem: aop-cmd-db@87ee0000 { + compatible = "qcom,cmd-db"; + reg = <0x0 0x87ee0000 0x0 0x20000>; + no-map; + }; + + aop_config_mem: aop-config@87f00000 { + reg = <0x0 0x87f00000 0x0 0x20000>; + no-map; + }; + + ipa_fw_mem: ipa-fw@87f20000 { + reg = <0x0 0x87f20000 0x0 0x10000>; + no-map; + }; + + secdata_mem: secdata@87f30000 { + reg = <0x0 0x87f30000 0x0 0x1000>; + no-map; + }; + + tme_crashdump_mem: tme-crashdump@87f31000 { + reg = <0x0 0x87f31000 0x0 0x40000>; + no-map; + }; + + tme_log_mem: tme-log@87f71000 { + reg = <0x0 0x87f71000 0x0 0x4000>; + no-map; + }; + + uefi_log_mem: uefi-log@87f75000 { + reg = <0x0 0x87f75000 0x0 0x10000>; + no-map; + }; + + qdss_mem: qdss@88800000 { + reg = <0x0 0x88800000 0x0 0x300000>; + no-map; + }; + + audio_heap_mem: audio-heap@88b00000 { + compatible = "shared-dma-pool"; + reg = <0x0 0x88b00000 0x0 0x400000>; + no-map; + }; + + mpss_dsmharq_mem: mpss-dsmharq@88f00000 { + reg = <0x0 0x88f00000 0x0 0x5080000>; + no-map; + }; + + q6_mpss_dtb_mem: q6-mpss-dtb@8df80000 { + reg = <0x0 0x8df80000 0x0 0x80000>; + no-map; + }; + + mpssadsp_mem: mpssadsp@8e000000 { + reg = <0x0 0x8e000000 0x0 0xf400000>; + no-map; + }; + + gunyah_trace_buffer_mem: gunyah-trace-buffer@bdb00000 { + reg = <0x0 0xbdb00000 0x0 0x2000000>; + no-map; + }; + + smmu_debug_buf_mem: smmu-debug-buf@bfb00000 { + reg = <0x0 0xbfb00000 0x0 0x100000>; + no-map; + }; + + hyp_smmu_s2_pt_mem: hyp-smmu-s2-pt@bfc00000 { + reg = <0x0 0xbfc00000 0x0 0x400000>; + no-map; + }; + }; + + smem: qcom,smem { + compatible = "qcom,smem"; + memory-region = <&smem_mem>; + hwlocks = <&tcsr_mutex 3>; + }; + + soc: soc { + compatible = "simple-bus"; + #address-cells = <2>; + #size-cells = <2>; + ranges = <0 0 0 0 0x10 0>; + dma-ranges = <0 0 0 0 0x10 0>; + + gcc: clock-controller@80000 { + compatible = "qcom,sdx75-gcc"; + reg = <0x0 0x0080000 0x0 0x1f7400>; + clocks = <&rpmhcc RPMH_CXO_CLK>, + <&sleep_clk>, + <0>, + <0>, + <0>, + <0>, + <0>, + <0>, + <0>, + <0>, + <0>, + <0>, + <0>, + <0>, + <0>; + #clock-cells = <1>; + #reset-cells = <1>; + #power-domain-cells = <1>; + }; + + qupv3_id_0: geniqup@9c0000 { + compatible = "qcom,geni-se-qup"; + reg = <0x0 0x009c0000 0x0 0x2000>; + clocks = <&gcc GCC_QUPV3_WRAP_0_M_AHB_CLK>, + <&gcc GCC_QUPV3_WRAP_0_S_AHB_CLK>; + clock-names = "m-ahb", + "s-ahb"; + iommus = <&apps_smmu 0xe3 0x0>; + #address-cells = <2>; + #size-cells = <2>; + ranges; + status = "disabled"; + + uart1: serial@984000 { + compatible = "qcom,geni-debug-uart"; + reg = <0x0 0x00984000 0x0 0x4000>; + clocks = <&gcc GCC_QUPV3_WRAP0_S1_CLK>; + clock-names = "se"; + interrupts = ; + pinctrl-0 = <&qupv3_se1_2uart_active>; + pinctrl-1 = <&qupv3_se1_2uart_sleep>; + pinctrl-names = "default", + "sleep"; + status = "disabled"; + }; + }; + + tcsr_mutex: hwlock@1f40000 { + compatible = "qcom,tcsr-mutex"; + reg = <0x0 0x01f40000 0x0 0x40000>; + #hwlock-cells = <1>; + }; + + pdc: interrupt-controller@b220000 { + compatible = "qcom,sdx75-pdc", "qcom,pdc"; + reg = <0x0 0xb220000 0x0 0x30000>, + <0x0 0x174000f0 0x0 0x64>; + qcom,pdc-ranges = <0 147 52>, + <52 266 32>, + <84 500 59>; + #interrupt-cells = <2>; + interrupt-parent = <&intc>; + interrupt-controller; + }; + + tlmm: pinctrl@f000000 { + compatible = "qcom,sdx75-tlmm"; + reg = <0x0 0x0f000000 0x0 0x400000>; + interrupts = ; + gpio-controller; + #gpio-cells = <2>; + gpio-ranges = <&tlmm 0 0 133>; + interrupt-controller; + #interrupt-cells = <2>; + wakeup-parent = <&pdc>; + + qupv3_se1_2uart_active: qupv3-se1-2uart-active-state { + tx-pins { + pins = "gpio12"; + function = "qup_se1_l2_mira"; + drive-strength= <2>; + bias-disable; + }; + + rx-pins { + pins = "gpio13"; + function = "qup_se1_l3_mira"; + drive-strength= <2>; + bias-disable; + }; + }; + + qupv3_se1_2uart_sleep: qupv3-se1-2uart-sleep-state { + pins = "gpio12", "gpio13"; + function = "gpio"; + drive-strength = <2>; + bias-pull-down; + }; + }; + + apps_smmu: iommu@15000000 { + compatible = "qcom,sdx75-smmu-500", "qcom,smmu-500", "arm,mmu-500"; + reg = <0x0 0x15000000 0x0 0x40000>; + #iommu-cells = <2>; + #global-interrupts = <2>; + dma-coherent; + interrupts = , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + ; + }; + + intc: interrupt-controller@17200000 { + compatible = "arm,gic-v3"; + #interrupt-cells = <3>; + interrupt-controller; + #redistributor-regions = <1>; + redistributor-stride = <0x0 0x20000>; + reg = <0x0 0x17200000 0x0 0x10000>, + <0x0 0x17260000 0x0 0x80000>; + interrupts = ; + }; + + timer@17420000 { + compatible = "arm,armv7-timer-mem"; + reg = <0x0 0x17420000 0x0 0x1000>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0 0 0x20000000>; + + frame@17421000 { + reg = <0x17421000 0x1000>, + <0x17422000 0x1000>; + frame-number = <0>; + interrupts = , + ; + }; + + frame@17423000 { + reg = <0x17423000 0x1000>; + frame-number = <1>; + interrupts = ; + status = "disabled"; + }; + + frame@17425000 { + reg = <0x17425000 0x1000>; + frame-number = <2>; + interrupts = ; + status = "disabled"; + }; + + frame@17427000 { + reg = <0x17427000 0x1000>; + frame-number = <3>; + interrupts = ; + status = "disabled"; + }; + + frame@17429000 { + reg = <0x17429000 0x1000>; + frame-number = <4>; + interrupts = ; + status = "disabled"; + }; + + frame@1742b000 { + reg = <0x1742b000 0x1000>; + frame-number = <5>; + interrupts = ; + status = "disabled"; + }; + + frame@1742d000 { + reg = <0x1742d000 0x1000>; + frame-number = <6>; + interrupts = ; + status = "disabled"; + }; + }; + + apps_rsc: rsc@17a00000 { + label = "apps_rsc"; + compatible = "qcom,rpmh-rsc"; + reg = <0x0 0x17a00000 0x0 0x10000>, + <0x0 0x17a10000 0x0 0x10000>, + <0x0 0x17a20000 0x0 0x10000>; + reg-names = "drv-0", "drv-1", "drv-2"; + interrupts = , + , + ; + + power-domains = <&CLUSTER_PD>; + qcom,tcs-offset = <0xd00>; + qcom,drv-id = <2>; + qcom,tcs-config = , + , + , + ; + + apps_bcm_voter: bcm-voter { + compatible = "qcom,bcm-voter"; + }; + + rpmhcc: clock-controller { + compatible = "qcom,sdx75-rpmh-clk"; + clocks = <&xo_board>; + clock-names = "xo"; + #clock-cells = <1>; + }; + }; + + cpufreq_hw: cpufreq@17d91000 { + compatible = "qcom,sdx75-cpufreq-epss", "qcom,cpufreq-epss"; + reg = <0x0 0x17d91000 0x0 0x1000>; + reg-names = "freq-domain0"; + clocks = <&rpmhcc RPMH_CXO_CLK>, + <&gcc GPLL0>; + clock-names = "xo", + "alternate"; + interrupts = ; + interrupt-names = "dcvsh-irq-0"; + #freq-domain-cells = <1>; + #clock-cells = <1>; + }; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts = , + , + , + ; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/sm4250-oneplus-billie2.dts b/arch/arm64/boot/dts/qcom/sm4250-oneplus-billie2.dts index a1f0622db5a0a3783575172ba10906c152374e36..75951fd439dfb02ff4a4116b87cfd608eca3541d 100644 --- a/arch/arm64/boot/dts/qcom/sm4250-oneplus-billie2.dts +++ b/arch/arm64/boot/dts/qcom/sm4250-oneplus-billie2.dts @@ -242,6 +242,9 @@ &usb_dwc3 { maximum-speed = "high-speed"; dr_mode = "peripheral"; + + phys = <&usb_hsphy>; + phy-names = "usb2-phy"; }; &usb_hsphy { diff --git a/arch/arm64/boot/dts/qcom/sm6115-fxtec-pro1x.dts b/arch/arm64/boot/dts/qcom/sm6115-fxtec-pro1x.dts new file mode 100644 index 0000000000000000000000000000000000000000..3ce9875e932c7dd32d0633d044e3c0961e45ac07 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/sm6115-fxtec-pro1x.dts @@ -0,0 +1,250 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (c) 2023, Dang Huynh + */ + +/dts-v1/; + +#include "sm6115.dtsi" +#include "pm6125.dtsi" +#include + +/ { + model = "F(x)tec Pro1X (QX1050)"; + compatible = "fxtec,pro1x", "qcom,sm6115"; + chassis-type = "handset"; + + qcom,msm-id = ; + + chosen { + #address-cells = <2>; + #size-cells = <2>; + ranges; + + framebuffer0: framebuffer@5c000000 { + compatible = "simple-framebuffer"; + reg = <0x0 0x5c000000 0x0 (1080 * 2160 * 4)>; + width = <1080>; + height = <2160>; + stride = <(1080 * 4)>; + format = "a8r8g8b8"; + clocks = <&gcc GCC_DISP_HF_AXI_CLK>; + }; + }; + + gpio-keys { + compatible = "gpio-keys"; + + pinctrl-0 = <&vol_up_n>; + pinctrl-names = "default"; + + key-volume-up { + label = "Volume Up"; + linux,code = ; + gpios = <&pm6125_gpios 5 GPIO_ACTIVE_LOW>; + debounce-interval = <15>; + linux,can-disable; + gpio-key,wakeup; + }; + }; +}; + +&dispcc { + /* HACK: disable until a panel driver is ready to retain simplefb */ + status = "disabled"; +}; + +&pm6125_gpios { + vol_up_n: vol-up-n-state { + pins = "gpio5"; + function = "normal"; + power-source = <0>; + bias-pull-up; + input-enable; + }; +}; + +&pon_pwrkey { + status = "okay"; +}; + +&pon_resin { + linux,code = ; + status = "okay"; +}; + +&rpm_requests { + regulators-0 { + compatible = "qcom,rpm-pm6125-regulators"; + + pm6125_s6a: s6 { + regulator-min-microvolt = <304000>; + regulator-max-microvolt = <1456000>; + }; + + pm6125_s7a: s7 { + regulator-min-microvolt = <1280000>; + regulator-max-microvolt = <2040000>; + }; + + pm6125_s8a: s8 { + regulator-min-microvolt = <1064000>; + regulator-max-microvolt = <1304000>; + }; + + pm6125_l1a: l1 { + regulator-min-microvolt = <952000>; + regulator-max-microvolt = <1152000>; + }; + + pm6125_l4a: l4 { + regulator-min-microvolt = <488000>; + regulator-max-microvolt = <1000000>; + }; + + pm6125_l5a: l5 { + regulator-min-microvolt = <1648000>; + regulator-max-microvolt = <3056000>; + }; + + pm6125_l6a: l6 { + regulator-min-microvolt = <576000>; + regulator-max-microvolt = <656000>; + }; + + pm6125_l7a: l7 { + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1304000>; + }; + + pm6125_l8a: l8 { + regulator-min-microvolt = <400000>; + regulator-max-microvolt = <728000>; + }; + + pm6125_l9a: l9 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <2000000>; + }; + + pm6125_l10a: l10 { + regulator-min-microvolt = <1704000>; + regulator-max-microvolt = <1904000>; + }; + + pm6125_l11a: l11 { + regulator-min-microvolt = <1704000>; + regulator-max-microvolt = <1952000>; + regulator-allow-set-load; + }; + + pm6125_l12a: l12 { + regulator-min-microvolt = <1624000>; + regulator-max-microvolt = <1984000>; + }; + + pm6125_l13a: l13 { + regulator-min-microvolt = <1504000>; + regulator-max-microvolt = <1952000>; + }; + + pm6125_l14a: l14 { + regulator-min-microvolt = <1704000>; + regulator-max-microvolt = <1904000>; + }; + + pm6125_l15a: l15 { + regulator-min-microvolt = <2920000>; + regulator-max-microvolt = <3232000>; + }; + + pm6125_l16a: l16 { + regulator-min-microvolt = <1704000>; + regulator-max-microvolt = <1904000>; + }; + + pm6125_l17a: l17 { + regulator-min-microvolt = <1152000>; + regulator-max-microvolt = <1384000>; + }; + + pm6125_l18a: l18 { + regulator-min-microvolt = <1104000>; + regulator-max-microvolt = <1312000>; + }; + + pm6125_l19a: l19 { + regulator-min-microvolt = <1624000>; + regulator-max-microvolt = <3304000>; + }; + + pm6125_l20a: l20 { + regulator-min-microvolt = <1624000>; + regulator-max-microvolt = <3304000>; + }; + + pm6125_l21a: l21 { + regulator-min-microvolt = <2400000>; + regulator-max-microvolt = <3600000>; + }; + + pm6125_l22a: l22 { + regulator-min-microvolt = <2952000>; + regulator-max-microvolt = <3304000>; + }; + + pm6125_l23a: l23 { + regulator-min-microvolt = <3200000>; + regulator-max-microvolt = <3400000>; + }; + + pm6125_l24a: l24 { + regulator-min-microvolt = <2704000>; + regulator-max-microvolt = <3600000>; + regulator-allow-set-load; + }; + }; +}; + +&sleep_clk { + clock-frequency = <32764>; +}; + +&tlmm { + gpio-reserved-ranges = <0 4>, <14 4>; +}; + +&ufs_mem_hc { + vcc-supply = <&pm6125_l24a>; + vcc-max-microamp = <600000>; + vccq2-supply = <&pm6125_l11a>; + vccq2-max-microamp = <600000>; + status = "okay"; +}; + +&ufs_mem_phy { + vdda-phy-supply = <&pm6125_l4a>; + vdda-pll-supply = <&pm6125_l12a>; + vddp-ref-clk-supply = <&pm6125_l18a>; + status = "okay"; +}; + +&usb { + status = "okay"; +}; + +&usb_dwc3 { + maximum-speed = "high-speed"; + dr_mode = "peripheral"; +}; + +&usb_hsphy { + vdd-supply = <&pm6125_l4a>; + vdda-pll-supply = <&pm6125_l12a>; + vdda-phy-dpdm-supply = <&pm6125_l15a>; + status = "okay"; +}; + +&xo_board { + clock-frequency = <19200000>; +}; diff --git a/arch/arm64/boot/dts/qcom/sm6115.dtsi b/arch/arm64/boot/dts/qcom/sm6115.dtsi index 43f31c1b9d5a74952bd0b324553506c601b76e3e..55118577bf923c19d650f5e6eefb751672161c1c 100644 --- a/arch/arm64/boot/dts/qcom/sm6115.dtsi +++ b/arch/arm64/boot/dts/qcom/sm6115.dtsi @@ -47,6 +47,8 @@ enable-method = "psci"; next-level-cache = <&L2_0>; qcom,freq-domain = <&cpufreq_hw 0>; + power-domains = <&CPU_PD0>; + power-domain-names = "psci"; L2_0: l2-cache { compatible = "cache"; cache-level = <2>; @@ -64,6 +66,8 @@ enable-method = "psci"; next-level-cache = <&L2_0>; qcom,freq-domain = <&cpufreq_hw 0>; + power-domains = <&CPU_PD1>; + power-domain-names = "psci"; }; CPU2: cpu@2 { @@ -76,6 +80,8 @@ enable-method = "psci"; next-level-cache = <&L2_0>; qcom,freq-domain = <&cpufreq_hw 0>; + power-domains = <&CPU_PD2>; + power-domain-names = "psci"; }; CPU3: cpu@3 { @@ -88,6 +94,8 @@ enable-method = "psci"; next-level-cache = <&L2_0>; qcom,freq-domain = <&cpufreq_hw 0>; + power-domains = <&CPU_PD3>; + power-domain-names = "psci"; }; CPU4: cpu@100 { @@ -100,6 +108,8 @@ dynamic-power-coefficient = <282>; next-level-cache = <&L2_1>; qcom,freq-domain = <&cpufreq_hw 1>; + power-domains = <&CPU_PD4>; + power-domain-names = "psci"; L2_1: l2-cache { compatible = "cache"; cache-level = <2>; @@ -117,6 +127,8 @@ enable-method = "psci"; next-level-cache = <&L2_1>; qcom,freq-domain = <&cpufreq_hw 1>; + power-domains = <&CPU_PD5>; + power-domain-names = "psci"; }; CPU6: cpu@102 { @@ -129,6 +141,8 @@ enable-method = "psci"; next-level-cache = <&L2_1>; qcom,freq-domain = <&cpufreq_hw 1>; + power-domains = <&CPU_PD6>; + power-domain-names = "psci"; }; CPU7: cpu@103 { @@ -141,6 +155,8 @@ enable-method = "psci"; next-level-cache = <&L2_1>; qcom,freq-domain = <&cpufreq_hw 1>; + power-domains = <&CPU_PD7>; + power-domain-names = "psci"; }; cpu-map { @@ -180,6 +196,68 @@ }; }; }; + + idle-states { + entry-method = "psci"; + + LITTLE_CPU_SLEEP_0: cpu-sleep-0-0 { + compatible = "arm,idle-state"; + idle-state-name = "silver-rail-power-collapse"; + arm,psci-suspend-param = <0x40000003>; + entry-latency-us = <290>; + exit-latency-us = <376>; + min-residency-us = <1182>; + local-timer-stop; + }; + + BIG_CPU_SLEEP_0: cpu-sleep-1-0 { + compatible = "arm,idle-state"; + idle-state-name = "gold-rail-power-collapse"; + arm,psci-suspend-param = <0x40000003>; + entry-latency-us = <297>; + exit-latency-us = <324>; + min-residency-us = <1110>; + local-timer-stop; + }; + }; + + domain-idle-states { + CLUSTER_0_SLEEP_0: cluster-sleep-0-0 { + /* GDHS */ + compatible = "domain-idle-state"; + arm,psci-suspend-param = <0x40000022>; + entry-latency-us = <360>; + exit-latency-us = <421>; + min-residency-us = <782>; + }; + + CLUSTER_0_SLEEP_1: cluster-sleep-0-1 { + /* Power Collapse */ + compatible = "domain-idle-state"; + arm,psci-suspend-param = <0x41000044>; + entry-latency-us = <800>; + exit-latency-us = <2118>; + min-residency-us = <7376>; + }; + + CLUSTER_1_SLEEP_0: cluster-sleep-1-0 { + /* GDHS */ + compatible = "domain-idle-state"; + arm,psci-suspend-param = <0x40000042>; + entry-latency-us = <314>; + exit-latency-us = <345>; + min-residency-us = <660>; + }; + + CLUSTER_1_SLEEP_1: cluster-sleep-1-1 { + /* Power Collapse */ + compatible = "domain-idle-state"; + arm,psci-suspend-param = <0x41000044>; + entry-latency-us = <640>; + exit-latency-us = <1654>; + min-residency-us = <8094>; + }; + }; }; firmware { @@ -203,6 +281,64 @@ psci { compatible = "arm,psci-1.0"; method = "smc"; + + CPU_PD0: power-domain-cpu0 { + #power-domain-cells = <0>; + power-domains = <&CLUSTER_0_PD>; + domain-idle-states = <&LITTLE_CPU_SLEEP_0>; + }; + + CPU_PD1: power-domain-cpu1 { + #power-domain-cells = <0>; + power-domains = <&CLUSTER_0_PD>; + domain-idle-states = <&LITTLE_CPU_SLEEP_0>; + }; + + CPU_PD2: power-domain-cpu2 { + #power-domain-cells = <0>; + power-domains = <&CLUSTER_0_PD>; + domain-idle-states = <&LITTLE_CPU_SLEEP_0>; + }; + + CPU_PD3: power-domain-cpu3 { + #power-domain-cells = <0>; + power-domains = <&CLUSTER_0_PD>; + domain-idle-states = <&LITTLE_CPU_SLEEP_0>; + }; + + CPU_PD4: power-domain-cpu4 { + #power-domain-cells = <0>; + power-domains = <&CLUSTER_1_PD>; + domain-idle-states = <&BIG_CPU_SLEEP_0>; + }; + + CPU_PD5: power-domain-cpu5 { + #power-domain-cells = <0>; + power-domains = <&CLUSTER_1_PD>; + domain-idle-states = <&BIG_CPU_SLEEP_0>; + }; + + CPU_PD6: power-domain-cpu6 { + #power-domain-cells = <0>; + power-domains = <&CLUSTER_1_PD>; + domain-idle-states = <&BIG_CPU_SLEEP_0>; + }; + + CPU_PD7: power-domain-cpu7 { + #power-domain-cells = <0>; + power-domains = <&CLUSTER_1_PD>; + domain-idle-states = <&BIG_CPU_SLEEP_0>; + }; + + CLUSTER_0_PD: power-domain-cpu-cluster0 { + #power-domain-cells = <0>; + domain-idle-states = <&CLUSTER_0_SLEEP_0>, <&CLUSTER_0_SLEEP_1>; + }; + + CLUSTER_1_PD: power-domain-cpu-cluster1 { + #power-domain-cells = <0>; + domain-idle-states = <&CLUSTER_1_SLEEP_0>, <&CLUSTER_1_SLEEP_1>; + }; }; reserved_memory: reserved-memory { @@ -663,6 +799,62 @@ status = "disabled"; }; + cryptobam: dma-controller@1b04000 { + compatible = "qcom,bam-v1.7.4", "qcom,bam-v1.7.0"; + reg = <0x0 0x01b04000 0x0 0x24000>; + interrupts = ; + clocks = <&rpmcc RPM_SMD_CE1_CLK>; + clock-names = "bam_clk"; + #dma-cells = <1>; + qcom,ee = <0>; + qcom,controlled-remotely; + iommus = <&apps_smmu 0x92 0>, + <&apps_smmu 0x94 0x11>, + <&apps_smmu 0x96 0x11>, + <&apps_smmu 0x98 0x1>, + <&apps_smmu 0x9F 0>; + }; + + crypto: crypto@1b3a000 { + compatible = "qcom,sm6115-qce", "qcom,ipq4019-qce", "qcom,qce"; + reg = <0x0 0x01b3a000 0x0 0x6000>; + clocks = <&rpmcc RPM_SMD_CE1_CLK>; + clock-names = "core"; + + dmas = <&cryptobam 6>, <&cryptobam 7>; + dma-names = "rx", "tx"; + iommus = <&apps_smmu 0x92 0>, + <&apps_smmu 0x94 0x11>, + <&apps_smmu 0x96 0x11>, + <&apps_smmu 0x98 0x1>, + <&apps_smmu 0x9F 0>; + }; + + usb_qmpphy: phy@1615000 { + compatible = "qcom,sm6115-qmp-usb3-phy"; + reg = <0x0 0x01615000 0x0 0x1000>; + + clocks = <&gcc GCC_AHB2PHY_USB_CLK>, + <&gcc GCC_USB3_PRIM_CLKREF_CLK>, + <&gcc GCC_USB3_PRIM_PHY_COM_AUX_CLK>, + <&gcc GCC_USB3_PRIM_PHY_PIPE_CLK>; + clock-names = "cfg_ahb", + "ref", + "com_aux", + "pipe"; + + resets = <&gcc GCC_USB3_PHY_PRIM_SP0_BCR>, + <&gcc GCC_USB3PHY_PHY_PRIM_SP0_BCR>; + reset-names = "phy", "phy_phy"; + + #clock-cells = <0>; + clock-output-names = "usb3_phy_pipe_clk_src"; + + #phy-cells = <0>; + + status = "disabled"; + }; + qfprom@1b40000 { compatible = "qcom,sm6115-qfprom", "qcom,qfprom"; reg = <0x0 0x01b40000 0x0 0x7000>; @@ -700,7 +892,7 @@ #interrupt-cells = <4>; }; - tsens0: thermal-sensor@4410000 { + tsens0: thermal-sensor@4411000 { compatible = "qcom,sm6115-tsens", "qcom,tsens-v2"; reg = <0x0 0x04411000 0x0 0x1ff>, /* TM */ <0x0 0x04410000 0x0 0x8>; /* SROT */ @@ -1113,8 +1305,8 @@ compatible = "snps,dwc3"; reg = <0x0 0x04e00000 0x0 0xcd00>; interrupts = ; - phys = <&usb_hsphy>; - phy-names = "usb2-phy"; + phys = <&usb_hsphy>, <&usb_qmpphy>; + phy-names = "usb2-phy", "usb3-phy"; iommus = <&apps_smmu 0x120 0x0>; snps,dis_u2_susphy_quirk; snps,dis_enblslpm_quirk; diff --git a/arch/arm64/boot/dts/qcom/sm6115p-lenovo-j606f.dts b/arch/arm64/boot/dts/qcom/sm6115p-lenovo-j606f.dts index ea3340d31110c9cff3f48af49a68989073767592..81fdcaf489266af642b6d158ea946a884acd19c3 100644 --- a/arch/arm64/boot/dts/qcom/sm6115p-lenovo-j606f.dts +++ b/arch/arm64/boot/dts/qcom/sm6115p-lenovo-j606f.dts @@ -306,6 +306,9 @@ &usb_dwc3 { maximum-speed = "high-speed"; dr_mode = "peripheral"; + + phys = <&usb_hsphy>; + phy-names = "usb2-phy"; }; &usb_hsphy { diff --git a/arch/arm64/boot/dts/qcom/sm6125-xiaomi-laurel-sprout.dts b/arch/arm64/boot/dts/qcom/sm6125-xiaomi-laurel-sprout.dts index b1038eb8cebc29548ae127871d6967fe6c5fc985..a7f4aeae9c1a515f3c9cec826c4f4703fbc9cb29 100644 --- a/arch/arm64/boot/dts/qcom/sm6125-xiaomi-laurel-sprout.dts +++ b/arch/arm64/boot/dts/qcom/sm6125-xiaomi-laurel-sprout.dts @@ -138,7 +138,7 @@ pinctrl-names = "default"; pinctrl-0 = <&camera_flash_therm &emmc_ufs_therm>; - adc-chan@4d { + channel@4d { reg = ; qcom,ratiometric; qcom,hw-settle-time = <200>; @@ -146,7 +146,7 @@ label = "rf_pa0_therm"; }; - adc-chan@4e { + channel@4e { reg = ; qcom,ratiometric; qcom,hw-settle-time = <200>; @@ -154,7 +154,7 @@ label = "quiet_therm"; }; - adc-chan@52 { + channel@52 { reg = ; qcom,ratiometric; qcom,hw-settle-time = <200>; @@ -162,7 +162,7 @@ label = "camera_flash_therm"; }; - adc-chan@54 { + channel@54 { reg = ; qcom,ratiometric; qcom,hw-settle-time = <200>; diff --git a/arch/arm64/boot/dts/qcom/sm6125.dtsi b/arch/arm64/boot/dts/qcom/sm6125.dtsi index 2aa093d16858a68e5c4aa1f1a663f850d2182930..a596baa6ce3ebaa417ee968fee72323756e0929c 100644 --- a/arch/arm64/boot/dts/qcom/sm6125.dtsi +++ b/arch/arm64/boot/dts/qcom/sm6125.dtsi @@ -366,7 +366,7 @@ hwlocks = <&tcsr_mutex 3>; }; - soc { + soc@0 { #address-cells = <1>; #size-cells = <1>; ranges = <0x00 0x00 0x00 0xffffffff>; diff --git a/arch/arm64/boot/dts/qcom/sm6350.dtsi b/arch/arm64/boot/dts/qcom/sm6350.dtsi index ad34301f6cddf9fd62f1297e28d377b6bc398f1c..30e77010aed575476aab7c8afdcfe1d82f6c2f85 100644 --- a/arch/arm64/boot/dts/qcom/sm6350.dtsi +++ b/arch/arm64/boot/dts/qcom/sm6350.dtsi @@ -56,6 +56,8 @@ interconnects = <&gem_noc MASTER_AMPSS_M0 QCOM_ICC_TAG_ACTIVE_ONLY &clk_virt SLAVE_EBI_CH0 QCOM_ICC_TAG_ACTIVE_ONLY>, <&osm_l3 MASTER_OSM_L3_APPS &osm_l3 SLAVE_OSM_L3>; + power-domains = <&CPU_PD0>; + power-domain-names = "psci"; #cooling-cells = <2>; L2_0: l2-cache { compatible = "cache"; @@ -84,6 +86,8 @@ interconnects = <&gem_noc MASTER_AMPSS_M0 QCOM_ICC_TAG_ACTIVE_ONLY &clk_virt SLAVE_EBI_CH0 QCOM_ICC_TAG_ACTIVE_ONLY>, <&osm_l3 MASTER_OSM_L3_APPS &osm_l3 SLAVE_OSM_L3>; + power-domains = <&CPU_PD1>; + power-domain-names = "psci"; #cooling-cells = <2>; L2_100: l2-cache { compatible = "cache"; @@ -107,6 +111,8 @@ interconnects = <&gem_noc MASTER_AMPSS_M0 QCOM_ICC_TAG_ACTIVE_ONLY &clk_virt SLAVE_EBI_CH0 QCOM_ICC_TAG_ACTIVE_ONLY>, <&osm_l3 MASTER_OSM_L3_APPS &osm_l3 SLAVE_OSM_L3>; + power-domains = <&CPU_PD2>; + power-domain-names = "psci"; #cooling-cells = <2>; L2_200: l2-cache { compatible = "cache"; @@ -130,6 +136,8 @@ interconnects = <&gem_noc MASTER_AMPSS_M0 QCOM_ICC_TAG_ACTIVE_ONLY &clk_virt SLAVE_EBI_CH0 QCOM_ICC_TAG_ACTIVE_ONLY>, <&osm_l3 MASTER_OSM_L3_APPS &osm_l3 SLAVE_OSM_L3>; + power-domains = <&CPU_PD3>; + power-domain-names = "psci"; #cooling-cells = <2>; L2_300: l2-cache { compatible = "cache"; @@ -153,6 +161,8 @@ interconnects = <&gem_noc MASTER_AMPSS_M0 QCOM_ICC_TAG_ACTIVE_ONLY &clk_virt SLAVE_EBI_CH0 QCOM_ICC_TAG_ACTIVE_ONLY>, <&osm_l3 MASTER_OSM_L3_APPS &osm_l3 SLAVE_OSM_L3>; + power-domains = <&CPU_PD4>; + power-domain-names = "psci"; #cooling-cells = <2>; L2_400: l2-cache { compatible = "cache"; @@ -176,6 +186,8 @@ interconnects = <&gem_noc MASTER_AMPSS_M0 QCOM_ICC_TAG_ACTIVE_ONLY &clk_virt SLAVE_EBI_CH0 QCOM_ICC_TAG_ACTIVE_ONLY>, <&osm_l3 MASTER_OSM_L3_APPS &osm_l3 SLAVE_OSM_L3>; + power-domains = <&CPU_PD5>; + power-domain-names = "psci"; #cooling-cells = <2>; L2_500: l2-cache { compatible = "cache"; @@ -199,6 +211,8 @@ interconnects = <&gem_noc MASTER_AMPSS_M0 QCOM_ICC_TAG_ACTIVE_ONLY &clk_virt SLAVE_EBI_CH0 QCOM_ICC_TAG_ACTIVE_ONLY>, <&osm_l3 MASTER_OSM_L3_APPS &osm_l3 SLAVE_OSM_L3>; + power-domains = <&CPU_PD6>; + power-domain-names = "psci"; #cooling-cells = <2>; L2_600: l2-cache { compatible = "cache"; @@ -222,6 +236,8 @@ interconnects = <&gem_noc MASTER_AMPSS_M0 QCOM_ICC_TAG_ACTIVE_ONLY &clk_virt SLAVE_EBI_CH0 QCOM_ICC_TAG_ACTIVE_ONLY>, <&osm_l3 MASTER_OSM_L3_APPS &osm_l3 SLAVE_OSM_L3>; + power-domains = <&CPU_PD7>; + power-domain-names = "psci"; #cooling-cells = <2>; L2_700: l2-cache { compatible = "cache"; @@ -266,6 +282,76 @@ }; }; }; + + domain-idle-states { + CLUSTER_SLEEP_PC: cluster-sleep-0 { + compatible = "domain-idle-state"; + arm,psci-suspend-param = <0x41000044>; + entry-latency-us = <2752>; + exit-latency-us = <3048>; + min-residency-us = <6118>; + }; + + CLUSTER_SLEEP_CX_RET: cluster-sleep-1 { + compatible = "domain-idle-state"; + arm,psci-suspend-param = <0x41001244>; + entry-latency-us = <3638>; + exit-latency-us = <4562>; + min-residency-us = <8467>; + }; + + CLUSTER_AOSS_SLEEP: cluster-sleep-2 { + compatible = "domain-idle-state"; + arm,psci-suspend-param = <0x4100b244>; + entry-latency-us = <3263>; + exit-latency-us = <6562>; + min-residency-us = <9987>; + }; + }; + + cpu_idle_states: idle-states { + entry-method = "psci"; + + LITTLE_CPU_SLEEP_0: cpu-sleep-0-0 { + compatible = "arm,idle-state"; + idle-state-name = "little-power-collapse"; + arm,psci-suspend-param = <0x40000003>; + entry-latency-us = <549>; + exit-latency-us = <901>; + min-residency-us = <1774>; + local-timer-stop; + }; + + LITTLE_CPU_SLEEP_1: cpu-sleep-0-1 { + compatible = "arm,idle-state"; + idle-state-name = "little-rail-power-collapse"; + arm,psci-suspend-param = <0x40000004>; + entry-latency-us = <702>; + exit-latency-us = <915>; + min-residency-us = <4001>; + local-timer-stop; + }; + + BIG_CPU_SLEEP_0: cpu-sleep-1-0 { + compatible = "arm,idle-state"; + idle-state-name = "big-power-collapse"; + arm,psci-suspend-param = <0x40000003>; + entry-latency-us = <523>; + exit-latency-us = <1244>; + min-residency-us = <2207>; + local-timer-stop; + }; + + BIG_CPU_SLEEP_1: cpu-sleep-1-1 { + compatible = "arm,idle-state"; + idle-state-name = "big-rail-power-collapse"; + arm,psci-suspend-param = <0x40000004>; + entry-latency-us = <526>; + exit-latency-us = <1854>; + min-residency-us = <5555>; + local-timer-stop; + }; + }; }; firmware { @@ -387,6 +473,25 @@ }; }; + qup_opp_table: opp-table-qup { + compatible = "operating-points-v2"; + + opp-75000000 { + opp-hz = /bits/ 64 <75000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-100000000 { + opp-hz = /bits/ 64 <100000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-128000000 { + opp-hz = /bits/ 64 <128000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + pmu { compatible = "arm,armv8-pmuv3"; interrupts = ; @@ -395,6 +500,61 @@ psci { compatible = "arm,psci-1.0"; method = "smc"; + + CPU_PD0: power-domain-cpu0 { + #power-domain-cells = <0>; + power-domains = <&CLUSTER_PD>; + domain-idle-states = <&LITTLE_CPU_SLEEP_0 &LITTLE_CPU_SLEEP_1>; + }; + + CPU_PD1: power-domain-cpu1 { + #power-domain-cells = <0>; + power-domains = <&CLUSTER_PD>; + domain-idle-states = <&LITTLE_CPU_SLEEP_0 &LITTLE_CPU_SLEEP_1>; + }; + + CPU_PD2: power-domain-cpu2 { + #power-domain-cells = <0>; + power-domains = <&CLUSTER_PD>; + domain-idle-states = <&LITTLE_CPU_SLEEP_0 &LITTLE_CPU_SLEEP_1>; + }; + + CPU_PD3: power-domain-cpu3 { + #power-domain-cells = <0>; + power-domains = <&CLUSTER_PD>; + domain-idle-states = <&LITTLE_CPU_SLEEP_0 &LITTLE_CPU_SLEEP_1>; + }; + + CPU_PD4: power-domain-cpu4 { + #power-domain-cells = <0>; + power-domains = <&CLUSTER_PD>; + domain-idle-states = <&LITTLE_CPU_SLEEP_0 &LITTLE_CPU_SLEEP_1>; + }; + + CPU_PD5: power-domain-cpu5 { + #power-domain-cells = <0>; + power-domains = <&CLUSTER_PD>; + domain-idle-states = <&LITTLE_CPU_SLEEP_0 &LITTLE_CPU_SLEEP_1>; + }; + + CPU_PD6: power-domain-cpu6 { + #power-domain-cells = <0>; + power-domains = <&CLUSTER_PD>; + domain-idle-states = <&BIG_CPU_SLEEP_0 &BIG_CPU_SLEEP_1>; + }; + + CPU_PD7: power-domain-cpu7 { + #power-domain-cells = <0>; + power-domains = <&CLUSTER_PD>; + domain-idle-states = <&BIG_CPU_SLEEP_0 &BIG_CPU_SLEEP_1>; + }; + + CLUSTER_PD: power-domain-cpu-cluster0 { + #power-domain-cells = <0>; + domain-idle-states = <&CLUSTER_SLEEP_PC + &CLUSTER_SLEEP_CX_RET + &CLUSTER_AOSS_SLEEP>; + }; }; reserved_memory: reserved-memory { @@ -750,6 +910,22 @@ status = "disabled"; }; + uart1: serial@884000 { + compatible = "qcom,geni-uart"; + reg = <0 0x00884000 0 0x4000>; + clock-names = "se"; + clocks = <&gcc GCC_QUPV3_WRAP0_S1_CLK>; + pinctrl-names = "default"; + pinctrl-0 = <&qup_uart1_cts>, <&qup_uart1_rts>, <&qup_uart1_tx>, <&qup_uart1_rx>; + interrupts = ; + power-domains = <&rpmhpd SM6350_CX>; + operating-points-v2 = <&qup_opp_table>; + interconnects = <&clk_virt MASTER_QUP_CORE_0 0 &clk_virt SLAVE_QUP_CORE_0 0>, + <&aggre1_noc MASTER_QUP_0 0 &clk_virt SLAVE_EBI_CH0 0>; + interconnect-names = "qup-core", "qup-config"; + status = "disabled"; + }; + i2c2: i2c@888000 { compatible = "qcom,geni-i2c"; reg = <0 0x00888000 0 0x4000>; @@ -1735,6 +1911,34 @@ drive-strength = <2>; bias-pull-up; }; + + qup_uart1_cts: qup-uart1-cts-default-state { + pins = "gpio61"; + function = "qup01"; + drive-strength = <2>; + bias-disable; + }; + + qup_uart1_rts: qup-uart1-rts-default-state { + pins = "gpio62"; + function = "qup01"; + drive-strength = <2>; + bias-pull-down; + }; + + qup_uart1_rx: qup-uart1-rx-default-state { + pins = "gpio64"; + function = "qup01"; + drive-strength = <2>; + bias-disable; + }; + + qup_uart1_tx: qup-uart1-tx-default-state { + pins = "gpio63"; + function = "qup01"; + drive-strength = <2>; + bias-pull-up; + }; }; apps_smmu: iommu@15000000 { @@ -1900,28 +2104,6 @@ }; }; - wifi: wifi@18800000 { - compatible = "qcom,wcn3990-wifi"; - reg = <0 0x18800000 0 0x800000>; - reg-names = "membase"; - memory-region = <&wlan_fw_mem>; - interrupts = , - , - , - , - , - , - , - , - , - , - , - ; - iommus = <&apps_smmu 0x20 0x1>; - qcom,msa-fixed-perm; - status = "disabled"; - }; - apps_rsc: rsc@18200000 { compatible = "qcom,rpmh-rsc"; label = "apps_rsc"; @@ -1936,6 +2118,7 @@ qcom,drv-id = <2>; qcom,tcs-config = , , , ; + power-domains = <&CLUSTER_PD>; rpmhcc: clock-controller { compatible = "qcom,sm6350-rpmh-clk"; @@ -2019,6 +2202,28 @@ #freq-domain-cells = <1>; #clock-cells = <1>; }; + + wifi: wifi@18800000 { + compatible = "qcom,wcn3990-wifi"; + reg = <0 0x18800000 0 0x800000>; + reg-names = "membase"; + memory-region = <&wlan_fw_mem>; + interrupts = , + , + , + , + , + , + , + , + , + , + , + ; + iommus = <&apps_smmu 0x20 0x1>; + qcom,msa-fixed-perm; + status = "disabled"; + }; }; timer { diff --git a/arch/arm64/boot/dts/qcom/sm6375.dtsi b/arch/arm64/boot/dts/qcom/sm6375.dtsi index f8d9c34d3b2f4f55e11cf3ba4beaa4ad0e0ac5b7..3dba34210a6d0921cc99c988a4807c364569502a 100644 --- a/arch/arm64/boot/dts/qcom/sm6375.dtsi +++ b/arch/arm64/boot/dts/qcom/sm6375.dtsi @@ -5,6 +5,7 @@ #include #include +#include #include #include #include @@ -1276,6 +1277,42 @@ }; }; + adreno_smmu: iommu@5940000 { + compatible = "qcom,sm6375-smmu-v2", "qcom,smmu-v2"; + reg = <0 0x05940000 0 0x10000>; + #iommu-cells = <1>; + #global-interrupts = <2>; + interrupts = , + , + , + , + , + , + , + , + , + ; + + clocks = <&gcc GCC_GPU_MEMNOC_GFX_CLK>; + clock-names = "bus"; + + power-domains = <&gpucc GPU_CX_GDSC>; + }; + + gpucc: clock-controller@5990000 { + compatible = "qcom,sm6375-gpucc"; + reg = <0 0x05990000 0 0x9000>; + clocks = <&rpmcc RPM_SMD_XO_CLK_SRC>, + <&gcc GCC_GPU_GPLL0_CLK_SRC>, + <&gcc GCC_GPU_GPLL0_DIV_CLK_SRC>, + <&gcc GCC_GPU_SNOC_DVM_GFX_CLK>; + power-domains = <&rpmpd SM6375_VDDGX>; + required-opps = <&rpmpd_opp_low_svs>; + #clock-cells = <1>; + #reset-cells = <1>; + #power-domain-cells = <1>; + }; + remoteproc_mss: remoteproc@6000000 { compatible = "qcom,sm6375-mpss-pas"; reg = <0 0x06000000 0 0x4040>; diff --git a/arch/arm64/boot/dts/qcom/sm7225-fairphone-fp4.dts b/arch/arm64/boot/dts/qcom/sm7225-fairphone-fp4.dts index 7ae6aba5d2ec7a473c83473cd03eab0c8c65d258..e3dc499515238639b1af2573c7cb5f7698455bd6 100644 --- a/arch/arm64/boot/dts/qcom/sm7225-fairphone-fp4.dts +++ b/arch/arm64/boot/dts/qcom/sm7225-fairphone-fp4.dts @@ -31,6 +31,7 @@ aliases { serial0 = &uart9; + serial1 = &uart1; }; chosen { @@ -524,6 +525,39 @@ }; }; +&qup_uart1_cts { + /* + * Configure a bias-bus-hold on CTS to lower power + * usage when Bluetooth is turned off. Bus hold will + * maintain a low power state regardless of whether + * the Bluetooth module drives the pin in either + * direction or leaves the pin fully unpowered. + */ + bias-bus-hold; +}; + +&qup_uart1_rts { + /* We'll drive RTS, so no pull */ + drive-strength = <2>; + bias-disable; +}; + +&qup_uart1_rx { + /* + * Configure a pull-up on RX. This is needed to avoid + * garbage data when the TX pin of the Bluetooth module is + * in tri-state (module powered off or not driving the + * signal yet). + */ + bias-pull-up; +}; + +&qup_uart1_tx { + /* We'll drive TX, so no pull */ + drive-strength = <2>; + bias-disable; +}; + &qupv3_id_0 { status = "okay"; }; @@ -561,6 +595,75 @@ &tlmm { gpio-reserved-ranges = <13 4>, <56 2>; + + qup_uart1_sleep_cts: qup-uart1-sleep-cts-state { + pins = "gpio61"; + function = "gpio"; + /* + * Configure a bias-bus-hold on CTS to lower power + * usage when Bluetooth is turned off. Bus hold will + * maintain a low power state regardless of whether + * the Bluetooth module drives the pin in either + * direction or leaves the pin fully unpowered. + */ + bias-bus-hold; + }; + + qup_uart1_sleep_rts: qup-uart1-sleep-rts-state { + pins = "gpio62"; + function = "gpio"; + /* + * Configure pull-down on RTS. As RTS is active low + * signal, pull it low to indicate the BT SoC that it + * can wakeup the system anytime from suspend state by + * pulling RX low (by sending wakeup bytes). + */ + bias-pull-down; + }; + + qup_uart1_sleep_rx: qup-uart1-sleep-rx-state { + pins = "gpio64"; + function = "gpio"; + /* + * Configure a pull-up on RX. This is needed to avoid + * garbage data when the TX pin of the Bluetooth module + * is floating which may cause spurious wakeups. + */ + bias-pull-up; + }; + + qup_uart1_sleep_tx: qup-uart1-sleep-tx-state { + pins = "gpio63"; + function = "gpio"; + /* + * Configure pull-up on TX when it isn't actively driven + * to prevent BT SoC from receiving garbage during sleep. + */ + bias-pull-up; + }; +}; + +&uart1 { + /delete-property/ interrupts; + interrupts-extended = <&intc GIC_SPI 602 IRQ_TYPE_LEVEL_HIGH>, + <&tlmm 64 IRQ_TYPE_EDGE_FALLING>; + + pinctrl-names = "default", "sleep"; + pinctrl-1 = <&qup_uart1_sleep_cts>, <&qup_uart1_sleep_rts>, <&qup_uart1_sleep_tx>, <&qup_uart1_sleep_rx>; + + status = "okay"; + + bluetooth { + compatible = "qcom,wcn3988-bt"; + + vddio-supply = <&vreg_l11a>; + vddxo-supply = <&vreg_l7a>; + vddrf-supply = <&vreg_l2e>; + vddch0-supply = <&vreg_l10e>; + swctrl-gpios = <&tlmm 69 GPIO_ACTIVE_HIGH>; + + max-speed = <3200000>; + }; }; &uart9 { diff --git a/arch/arm64/boot/dts/qcom/sm8150-sony-xperia-kumano.dtsi b/arch/arm64/boot/dts/qcom/sm8150-sony-xperia-kumano.dtsi index 47e2430991ca0e6b64d56f31da777a2aa78a0c6b..baafea53770bff2dfceaaf4640ce71b054d8a469 100644 --- a/arch/arm64/boot/dts/qcom/sm8150-sony-xperia-kumano.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8150-sony-xperia-kumano.dtsi @@ -6,6 +6,7 @@ /dts-v1/; #include +#include #include #include "sm8150.dtsi" #include "pm8150.dtsi" @@ -81,6 +82,66 @@ }; }; + cam0_vdig_vreg: cam0-vdig-regulator { + compatible = "regulator-fixed"; + regulator-name = "camera0_vdig_vreg"; + gpio = <&tlmm 22 GPIO_ACTIVE_HIGH>; + enable-active-high; + + pinctrl-0 = <&main_cam_pwr_en>; + pinctrl-names = "default"; + }; + + cam1_vdig_vreg: cam1-vdig-regulator { + compatible = "regulator-fixed"; + regulator-name = "camera1_vdig_vreg"; + gpio = <&tlmm 79 GPIO_ACTIVE_HIGH>; + enable-active-high; + + pinctrl-0 = <&sub_cam_pwr_en>; + pinctrl-names = "default"; + }; + + cam2_vdig_vreg: cam2-vdig-regulator { + compatible = "regulator-fixed"; + regulator-name = "camera2_vdig_vreg"; + gpio = <&tlmm 25 GPIO_ACTIVE_HIGH>; + enable-active-high; + + pinctrl-0 = <&chat_cam_pwr_en>; + pinctrl-names = "default"; + }; + + cam3_vdig_vreg: cam3-vdig-regulator { + compatible = "regulator-fixed"; + regulator-name = "camera3_vdig_vreg"; + gpio = <&pm8150_gpios 7 GPIO_ACTIVE_HIGH>; + enable-active-high; + + pinctrl-0 = <&supwc_pwr_en>; + pinctrl-names = "default"; + }; + + cam_vmdr_vreg: cam-vmdr-regulator { + compatible = "regulator-fixed"; + regulator-name = "camera_vmdr_vreg"; + gpio = <&pm8150l_gpios 3 GPIO_ACTIVE_HIGH>; + enable-active-high; + + pinctrl-0 = <&main_cam_pwr_vmdr_en>; + pinctrl-names = "default"; + }; + + rgbcir_vreg: rgbcir-regulator { + compatible = "regulator-fixed"; + regulator-name = "rgbcir_vreg"; + gpio = <&tlmm 29 GPIO_ACTIVE_HIGH>; + enable-active-high; + + pinctrl-0 = <&rgbc_ir_pwr_en>; + pinctrl-names = "default"; + }; + vph_pwr: vph-pwr-regulator { compatible = "regulator-fixed"; regulator-name = "vph_pwr"; @@ -456,6 +517,17 @@ }; &pm8150_gpios { + gpio-line-names = "VOL_DOWN_N", /* GPIO_1 */ + "", + "NC", + "NC", + "", + "NC", + "SUPWC_PWR_EN", + "", + "NC", + "NC"; /* GPIO_10 */ + vol_down_n: vol-down-n-state { pins = "gpio1"; function = "normal"; @@ -463,9 +535,31 @@ bias-pull-up; input-enable; }; + + supwc_pwr_en: supwc-pwr-en-state { + pins = "gpio7"; + function = "normal"; + qcom,drive-strength = <1>; + power-source = <1>; + drive-push-pull; + output-low; + }; }; &pm8150b_gpios { + gpio-line-names = "SNAPSHOT_N", /* GPIO_1 */ + "FOCUS_N", + "NC", + "NC", + "RF_LCD_ID_EN", + "NC", + "TS_VDDH_EN", + "LCD_ID", + "", + "NC", /* GPIO_10 */ + "NC", + "RF_ID"; + snapshot_n: snapshot-n-state { pins = "gpio1"; function = "normal"; @@ -483,6 +577,30 @@ }; }; +&pm8150l_gpios { + gpio-line-names = "TS_VDDIO_EN", /* GPIO_1 */ + "NC", + "MAIN_CAM_PWR_VMDR_EN", + "NC", + "", + "NC", + "NC", + "FP_LDO_EN", + "NC", + "NC", /* GPIO_10 */ + "NC", + "NC"; + + main_cam_pwr_vmdr_en: main-cam-pwr-vmdr-en-state { + pins = "gpio3"; + function = "normal"; + qcom,drive-strength = ; + power-source = <0>; + drive-push-pull; + output-low; + }; +}; + &pon_pwrkey { status = "okay"; }; @@ -500,8 +618,225 @@ status = "okay"; }; +&sdhc_2 { + vmmc-supply = <&vreg_l9c_2p9>; + vqmmc-supply = <&vreg_l6c_2p9>; + cd-gpios = <&tlmm 96 GPIO_ACTIVE_HIGH>; + bus-width = <4>; + no-sdio; + no-mmc; + + status = "okay"; +}; + &tlmm { gpio-reserved-ranges = <126 4>; + gpio-line-names = "NFC_ESE_SPI_MISO", /* GPIO_0 */ + "NFC_ESE_SPI_MOSI", + "NFC_ESE_SPI_SCLK", + "NFC_ESE_SPI_CS_N", + "NC", + "NC", + "DISP_RESET_N", + "DEBUG_GPIO0", + "MDP_VSYNC_P", + "TS_I2C_SDA", + "TS_I2C_SCL", /* GPIO_10 */ + "CAM_SOF", + "CAM2_RST_N", + "CAM_MCLK0", + "CAM_MCLK1", + "CAM_MCLK2", + "CAM_MCLK3", + "CCI_I2C_SDA0", + "CCI_I2C_SCL0", + "CCI_I2C_SDA1", + "CCI_I2C_SCL1", /* GPIO_20 */ + "NC", + "MAIN_CAM_PWR_EN", + "CAM3_RST_N", + "NC", + "CHAT_CAM_PWR_EN", + "NC", + "NC", + "CAM0_RST_N", + "RGBC_IR_PWR_EN", + "CAM1_RST_N", /* GPIO_30 */ + "CCI_I2C_SDA2", + "CCI_I2C_SCL2", + "CCI_I2C_SDA3", + "CCI_I2C_SCL3", + "NC", + "DEBUG_GPIO1", + "RGBC_IR_INT", + "USB_CC_DIR", + "NC", + "NC", /* GPIO_40 */ + "NFC_EN", + "NFC_ESE_PWR_REQ", + "BT_HCI_UART_CTS_N", + "BT_HCI_UART_RFR_N", + "BT_HCI_UART_TXD", + "BT_HCI_UART_RXD", + "NFC_IRQ", + "NFC_DWL_REQ", + "UIM2_DETECT_EN", + "WLAN_SW_CTRL", /* GPIO_50 */ + "APPS_I2C_SDA", + "APPS_I2C_SCL", + "NC", + "TS_RESET_N", + "NC", + "NC", + "NC", + "NC", + "HW_ID_0", + "NC", /* GPIO_60 */ + "QLINK_REQUEST", + "QLINK_ENABLE", + "WMSS_RESET_N", + "SDM_GRFC_8", + "WDOG_DISABLE", + "NC", + "NC", + "PA_INDICATOR_OR", + "MSS_LTE_COXM_TXD", + "MSS_LTE_COXM_RXD", /* GPIO_70 */ + "SDM_RFFE0_DATA", + "SDM_RFFE0_CLK", + "SDM_RFFE1_DATA", + "SDM_RFFE1_CLK", + "SDM_RFFE2_DATA", + "SDM_RFFE2_CLK", + "SDM_RFFE3_DATA", + "SDM_RFFE3_CLK", + "SUB_CAM_PWR_EN", + "FP_RESET_N", /* GPIO_80 */ + "NC", + "NC", + "NC", + "NC", + "DEBUG_UART_TX", + "DEBUG_UART_RX", + "DVDT_WRT_DET_AND", + "NC", + "NC", + "NC", /* GPIO_90 */ + "NC", + "NC", + "NC", + "NC", + "UDON_SWITCH_SEL", + "SD_CARD_DET_N", + "NC", + "CAMSENSOR_I2C_SDA", + "CAMSENSOR_I2C_SCL", + "USB_AUDIO_EN1", /* GPIO_100 */ + "DISP_ERR_FG", + "NC", + "NC", + "NC", + "UIM2_DATA", + "UIM2_CLK", + "UIM2_RESET", + "UIM2_DET", + "UIM1_DATA", + "UIM1_CLK", /* GPIO_110 */ + "UIM1_RESET", + "UIM1_PRESENT", + "NFC_CLK_REQ", + "SW_SERVICE", + "NC", + "RF_ID_EXTENSION", + "ALS_PROX_INT_N", + "FP_INT", + "DVDT_WRT_DET_OR", + "BAROMETER_INT", /* GPIO_120 */ + "ACC_COVER_OPEN", + "TS_INT_N", + "CODEC_INT1_N", + "CODEC_INT2_N", + "TX_GTR_THRES_IN", + "FP_SPI_MISO", + "FP_SPI_MOSI", + "FP_SPI_SCLK", + "FP_SPI_CS_N", + "NC", /* GPIO_130 */ + "DVDT_ENABLE", + "ACCEL_INT", + "NC", + "MAG_INT_N", + "NC", + "FORCED_USB_BOOT", + "NC", + "NC", + "HW_ID_1", + "NC", /* GPIO_140 */ + "NC", + "NC", + "CODEC_RST_N", + "CDC_SPI_MISO", + "CDC_SPI_MOSI", + "CDC_SPI_SCLK", + "CDC_SPI_CS_N", + "NC", + "LPASS_SLIMBUS_CLK", + "LPASS_SLIMBUS_DATA0", /* GPIO_150 */ + "LPASS_SLIMBUS_DATA1", + "USB_AUDIO_EN2", + "BT_FM_SLIMBUS_DATA", + "BT_FM_SLIMBUS_CLK", + "COMPASS_I2C_SDA", + "COMPASS_I2C_SCL", + "SSC_SPI_1_MISO", + "SSC_SPI_1_MOSI", + "SSC_SPI_1_CLK", + "SSC_SPI_1_CS_N", /* GPIO_160 */ + "SSC_SENSOR_I2C_SDA", + "SSC_SENSOR_I2C_SCL", + "NC", + "NC", + "NC", + "NC", + "SSC_UART_1_TX", + "SSC_UART_1_RX", + "WL_CMD_CLK_CHAIN0", + "WL_CMD_DATA_CHAIN0", /* GPIO_170 */ + "WL_CMD_CLK_CHAIN1", + "WL_CMD_DATA_CHAIN1", + "WL_BT_COEX_CLK", + "WL_BT_COEX_DATA"; + + main_cam_pwr_en: main-cam-pwr-en-state { + pins = "gpio22"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + output-low; + }; + + chat_cam_pwr_en: chat-cam-pwr-en-state { + pins = "gpio25"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + output-low; + }; + + rgbc_ir_pwr_en: rgbc-ir-pwr-en-state { + pins = "gpio29"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + output-low; + }; + + sub_cam_pwr_en: sub-cam-pwr-en-state { + pins = "gpio79"; + function = "gpio"; + drive-strength = <2>; + bias-pull-down; + }; }; &uart2 { diff --git a/arch/arm64/boot/dts/qcom/sm8150.dtsi b/arch/arm64/boot/dts/qcom/sm8150.dtsi index 27dcda0d4288fcedcfff7b633761fc6d9ef567b8..18c822abdb88fa546f244e176e617305e6d1676f 100644 --- a/arch/arm64/boot/dts/qcom/sm8150.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8150.dtsi @@ -55,8 +55,8 @@ next-level-cache = <&L2_0>; qcom,freq-domain = <&cpufreq_hw 0>; operating-points-v2 = <&cpu0_opp_table>; - interconnects = <&gem_noc MASTER_AMPSS_M0 &mc_virt SLAVE_EBI_CH0>, - <&osm_l3 MASTER_OSM_L3_APPS &osm_l3 SLAVE_OSM_L3>; + interconnects = <&gem_noc MASTER_AMPSS_M0 0 &mc_virt SLAVE_EBI_CH0 0>, + <&osm_l3 MASTER_OSM_L3_APPS 0 &osm_l3 SLAVE_OSM_L3 0>; power-domains = <&CPU_PD0>; power-domain-names = "psci"; #cooling-cells = <2>; @@ -84,8 +84,8 @@ next-level-cache = <&L2_100>; qcom,freq-domain = <&cpufreq_hw 0>; operating-points-v2 = <&cpu0_opp_table>; - interconnects = <&gem_noc MASTER_AMPSS_M0 &mc_virt SLAVE_EBI_CH0>, - <&osm_l3 MASTER_OSM_L3_APPS &osm_l3 SLAVE_OSM_L3>; + interconnects = <&gem_noc MASTER_AMPSS_M0 0 &mc_virt SLAVE_EBI_CH0 0>, + <&osm_l3 MASTER_OSM_L3_APPS 0 &osm_l3 SLAVE_OSM_L3 0>; power-domains = <&CPU_PD1>; power-domain-names = "psci"; #cooling-cells = <2>; @@ -108,8 +108,8 @@ next-level-cache = <&L2_200>; qcom,freq-domain = <&cpufreq_hw 0>; operating-points-v2 = <&cpu0_opp_table>; - interconnects = <&gem_noc MASTER_AMPSS_M0 &mc_virt SLAVE_EBI_CH0>, - <&osm_l3 MASTER_OSM_L3_APPS &osm_l3 SLAVE_OSM_L3>; + interconnects = <&gem_noc MASTER_AMPSS_M0 0 &mc_virt SLAVE_EBI_CH0 0>, + <&osm_l3 MASTER_OSM_L3_APPS 0 &osm_l3 SLAVE_OSM_L3 0>; power-domains = <&CPU_PD2>; power-domain-names = "psci"; #cooling-cells = <2>; @@ -132,8 +132,8 @@ next-level-cache = <&L2_300>; qcom,freq-domain = <&cpufreq_hw 0>; operating-points-v2 = <&cpu0_opp_table>; - interconnects = <&gem_noc MASTER_AMPSS_M0 &mc_virt SLAVE_EBI_CH0>, - <&osm_l3 MASTER_OSM_L3_APPS &osm_l3 SLAVE_OSM_L3>; + interconnects = <&gem_noc MASTER_AMPSS_M0 0 &mc_virt SLAVE_EBI_CH0 0>, + <&osm_l3 MASTER_OSM_L3_APPS 0 &osm_l3 SLAVE_OSM_L3 0>; power-domains = <&CPU_PD3>; power-domain-names = "psci"; #cooling-cells = <2>; @@ -156,8 +156,8 @@ next-level-cache = <&L2_400>; qcom,freq-domain = <&cpufreq_hw 1>; operating-points-v2 = <&cpu4_opp_table>; - interconnects = <&gem_noc MASTER_AMPSS_M0 &mc_virt SLAVE_EBI_CH0>, - <&osm_l3 MASTER_OSM_L3_APPS &osm_l3 SLAVE_OSM_L3>; + interconnects = <&gem_noc MASTER_AMPSS_M0 0 &mc_virt SLAVE_EBI_CH0 0>, + <&osm_l3 MASTER_OSM_L3_APPS 0 &osm_l3 SLAVE_OSM_L3 0>; power-domains = <&CPU_PD4>; power-domain-names = "psci"; #cooling-cells = <2>; @@ -180,8 +180,8 @@ next-level-cache = <&L2_500>; qcom,freq-domain = <&cpufreq_hw 1>; operating-points-v2 = <&cpu4_opp_table>; - interconnects = <&gem_noc MASTER_AMPSS_M0 &mc_virt SLAVE_EBI_CH0>, - <&osm_l3 MASTER_OSM_L3_APPS &osm_l3 SLAVE_OSM_L3>; + interconnects = <&gem_noc MASTER_AMPSS_M0 0 &mc_virt SLAVE_EBI_CH0 0>, + <&osm_l3 MASTER_OSM_L3_APPS 0 &osm_l3 SLAVE_OSM_L3 0>; power-domains = <&CPU_PD5>; power-domain-names = "psci"; #cooling-cells = <2>; @@ -204,8 +204,8 @@ next-level-cache = <&L2_600>; qcom,freq-domain = <&cpufreq_hw 1>; operating-points-v2 = <&cpu4_opp_table>; - interconnects = <&gem_noc MASTER_AMPSS_M0 &mc_virt SLAVE_EBI_CH0>, - <&osm_l3 MASTER_OSM_L3_APPS &osm_l3 SLAVE_OSM_L3>; + interconnects = <&gem_noc MASTER_AMPSS_M0 0 &mc_virt SLAVE_EBI_CH0 0>, + <&osm_l3 MASTER_OSM_L3_APPS 0 &osm_l3 SLAVE_OSM_L3 0>; power-domains = <&CPU_PD6>; power-domain-names = "psci"; #cooling-cells = <2>; @@ -228,8 +228,8 @@ next-level-cache = <&L2_700>; qcom,freq-domain = <&cpufreq_hw 2>; operating-points-v2 = <&cpu7_opp_table>; - interconnects = <&gem_noc MASTER_AMPSS_M0 &mc_virt SLAVE_EBI_CH0>, - <&osm_l3 MASTER_OSM_L3_APPS &osm_l3 SLAVE_OSM_L3>; + interconnects = <&gem_noc MASTER_AMPSS_M0 0 &mc_virt SLAVE_EBI_CH0 0>, + <&osm_l3 MASTER_OSM_L3_APPS 0 &osm_l3 SLAVE_OSM_L3 0>; power-domains = <&CPU_PD7>; power-domain-names = "psci"; #cooling-cells = <2>; @@ -1362,14 +1362,11 @@ uart9: serial@a84000 { compatible = "qcom,geni-uart"; reg = <0x0 0x00a84000 0x0 0x4000>; - reg-names = "se"; clocks = <&gcc GCC_QUPV3_WRAP1_S1_CLK>; clock-names = "se"; pinctrl-0 = <&qup_uart9_default>; pinctrl-names = "default"; interrupts = ; - #address-cells = <1>; - #size-cells = <0>; status = "disabled"; }; @@ -1763,49 +1760,49 @@ config_noc: interconnect@1500000 { compatible = "qcom,sm8150-config-noc"; reg = <0 0x01500000 0 0x7400>; - #interconnect-cells = <1>; + #interconnect-cells = <2>; qcom,bcm-voters = <&apps_bcm_voter>; }; system_noc: interconnect@1620000 { compatible = "qcom,sm8150-system-noc"; reg = <0 0x01620000 0 0x19400>; - #interconnect-cells = <1>; + #interconnect-cells = <2>; qcom,bcm-voters = <&apps_bcm_voter>; }; mc_virt: interconnect@163a000 { compatible = "qcom,sm8150-mc-virt"; reg = <0 0x0163a000 0 0x1000>; - #interconnect-cells = <1>; + #interconnect-cells = <2>; qcom,bcm-voters = <&apps_bcm_voter>; }; aggre1_noc: interconnect@16e0000 { compatible = "qcom,sm8150-aggre1-noc"; reg = <0 0x016e0000 0 0xd080>; - #interconnect-cells = <1>; + #interconnect-cells = <2>; qcom,bcm-voters = <&apps_bcm_voter>; }; aggre2_noc: interconnect@1700000 { compatible = "qcom,sm8150-aggre2-noc"; reg = <0 0x01700000 0 0x20000>; - #interconnect-cells = <1>; + #interconnect-cells = <2>; qcom,bcm-voters = <&apps_bcm_voter>; }; compute_noc: interconnect@1720000 { compatible = "qcom,sm8150-compute-noc"; reg = <0 0x01720000 0 0x7000>; - #interconnect-cells = <1>; + #interconnect-cells = <2>; qcom,bcm-voters = <&apps_bcm_voter>; }; mmss_noc: interconnect@1740000 { compatible = "qcom,sm8150-mmss-noc"; reg = <0 0x01740000 0 0x1c100>; - #interconnect-cells = <1>; + #interconnect-cells = <2>; qcom,bcm-voters = <&apps_bcm_voter>; }; @@ -1826,7 +1823,7 @@ }; pcie0: pci@1c00000 { - compatible = "qcom,pcie-sm8150", "snps,dw-pcie"; + compatible = "qcom,pcie-sm8150"; reg = <0 0x01c00000 0 0x3000>, <0 0x60000000 0 0xf1d>, <0 0x60000f20 0 0xa8>, @@ -1921,7 +1918,7 @@ }; pcie1: pci@1c08000 { - compatible = "qcom,pcie-sm8150", "snps,dw-pcie"; + compatible = "qcom,pcie-sm8150"; reg = <0 0x01c08000 0 0x3000>, <0 0x40000000 0 0xf1d>, <0 0x40000f20 0 0xa8>, @@ -2097,6 +2094,36 @@ }; }; + cryptobam: dma-controller@1dc4000 { + compatible = "qcom,bam-v1.7.4", "qcom,bam-v1.7.0"; + reg = <0 0x01dc4000 0 0x24000>; + interrupts = ; + #dma-cells = <1>; + qcom,ee = <0>; + qcom,controlled-remotely; + num-channels = <8>; + qcom,num-ees = <2>; + iommus = <&apps_smmu 0x502 0x0641>, + <&apps_smmu 0x504 0x0011>, + <&apps_smmu 0x506 0x0011>, + <&apps_smmu 0x508 0x0011>, + <&apps_smmu 0x512 0x0000>; + }; + + crypto: crypto@1dfa000 { + compatible = "qcom,sm8150-qce", "qcom,qce"; + reg = <0 0x01dfa000 0 0x6000>; + dmas = <&cryptobam 4>, <&cryptobam 5>; + dma-names = "rx", "tx"; + iommus = <&apps_smmu 0x502 0x0641>, + <&apps_smmu 0x504 0x0011>, + <&apps_smmu 0x506 0x0011>, + <&apps_smmu 0x508 0x0011>, + <&apps_smmu 0x512 0x0000>; + interconnects = <&aggre2_noc MASTER_CRYPTO_CORE_0 0 &mc_virt SLAVE_EBI_CH0 0>; + interconnect-names = "memory"; + }; + tcsr_mutex: hwlock@1f40000 { compatible = "qcom,tcsr-mutex"; reg = <0x0 0x01f40000 0x0 0x20000>; @@ -3520,14 +3547,14 @@ dc_noc: interconnect@9160000 { compatible = "qcom,sm8150-dc-noc"; reg = <0 0x09160000 0 0x3200>; - #interconnect-cells = <1>; + #interconnect-cells = <2>; qcom,bcm-voters = <&apps_bcm_voter>; }; gem_noc: interconnect@9680000 { compatible = "qcom,sm8150-gem-noc"; reg = <0 0x09680000 0 0x3e200>; - #interconnect-cells = <1>; + #interconnect-cells = <2>; qcom,bcm-voters = <&apps_bcm_voter>; }; @@ -3568,6 +3595,10 @@ resets = <&gcc GCC_USB30_PRIM_BCR>; + interconnects = <&aggre1_noc MASTER_USB3 0 &mc_virt SLAVE_EBI_CH0 0>, + <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_USB3 0>; + interconnect-names = "usb-ddr", "apps-usb"; + usb_1_dwc3: usb@a600000 { compatible = "snps,dwc3"; reg = <0 0x0a600000 0 0xcd00>; @@ -3617,6 +3648,10 @@ resets = <&gcc GCC_USB30_SEC_BCR>; + interconnects = <&aggre1_noc MASTER_USB3_1 0 &mc_virt SLAVE_EBI_CH0 0>, + <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_USB3_1 0>; + interconnect-names = "usb-ddr", "apps-usb"; + usb_2_dwc3: usb@a800000 { compatible = "snps,dwc3"; reg = <0 0x0a800000 0 0xcd00>; @@ -3632,7 +3667,7 @@ camnoc_virt: interconnect@ac00000 { compatible = "qcom,sm8150-camnoc-virt"; reg = <0 0x0ac00000 0 0x1000>; - #interconnect-cells = <1>; + #interconnect-cells = <2>; qcom,bcm-voters = <&apps_bcm_voter>; }; @@ -3641,8 +3676,8 @@ reg = <0 0x0ae00000 0 0x1000>; reg-names = "mdss"; - interconnects = <&mmss_noc MASTER_MDP_PORT0 &mc_virt SLAVE_EBI_CH0>, - <&mmss_noc MASTER_MDP_PORT1 &mc_virt SLAVE_EBI_CH0>; + interconnects = <&mmss_noc MASTER_MDP_PORT0 0 &mc_virt SLAVE_EBI_CH0 0>, + <&mmss_noc MASTER_MDP_PORT1 0 &mc_virt SLAVE_EBI_CH0 0>; interconnect-names = "mdp0-mem", "mdp1-mem"; power-domains = <&dispcc MDSS_GDSC>; @@ -3986,7 +4021,7 @@ }; apps_smmu: iommu@15000000 { - compatible = "qcom,sm8150-smmu-500", "arm,mmu-500"; + compatible = "qcom,sm8150-smmu-500", "qcom,smmu-500", "arm,mmu-500"; reg = <0 0x15000000 0 0x100000>; #iommu-cells = <2>; #global-interrupts = <1>; @@ -4307,7 +4342,7 @@ clocks = <&rpmhcc RPMH_CXO_CLK>, <&gcc GPLL0>; clock-names = "xo", "alternate"; - #interconnect-cells = <1>; + #interconnect-cells = <2>; }; cpufreq_hw: cpufreq@18323000 { diff --git a/arch/arm64/boot/dts/qcom/sm8250-sony-xperia-edo.dtsi b/arch/arm64/boot/dts/qcom/sm8250-sony-xperia-edo.dtsi index 2f22d348d45d74c7125b2714196eb6770bd18609..8ab82bacba81f4444d4e21bbcb38da06d668648d 100644 --- a/arch/arm64/boot/dts/qcom/sm8250-sony-xperia-edo.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8250-sony-xperia-edo.dtsi @@ -26,9 +26,10 @@ framebuffer: framebuffer@9c000000 { compatible = "simple-framebuffer"; reg = <0 0x9c000000 0 0x2300000>; - width = <1644>; - height = <3840>; - stride = <(1644 * 4)>; + /* pdx203 BL initializes in 2.5k mode, not 4k */ + width = <1096>; + height = <2560>; + stride = <(1096 * 4)>; format = "a8r8g8b8"; /* * That's a lot of clocks, but it's necessary due @@ -672,3 +673,8 @@ vdda-phy-supply = <&vreg_l9a_1p2>; vdda-pll-supply = <&vreg_l18a_0p9>; }; + +&venus { + firmware-name = "qcom/sm8250/Sony/edo/venus.mbn"; + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/qcom/sm8250-xiaomi-elish-common.dtsi b/arch/arm64/boot/dts/qcom/sm8250-xiaomi-elish-common.dtsi index 8af6a0120a500a424305e1d64ebd9976704dcdce..b841ea9192aea3f669223cb11d5fc4e50daf89d4 100644 --- a/arch/arm64/boot/dts/qcom/sm8250-xiaomi-elish-common.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8250-xiaomi-elish-common.dtsi @@ -470,76 +470,6 @@ status = "okay"; }; -&dsi0 { - vdda-supply = <&vreg_l9a_1p2>; - qcom,dual-dsi-mode; - qcom,sync-dual-dsi; - qcom,master-dsi; - status = "okay"; - - display_panel: panel@0 { - reg = <0>; - vddio-supply = <&vreg_l14a_1p88>; - reset-gpios = <&tlmm 75 GPIO_ACTIVE_LOW>; - backlight = <&backlight>; - - status = "disabled"; - - ports { - #address-cells = <1>; - #size-cells = <0>; - - port@0 { - reg = <0>; - - panel_in_0: endpoint { - remote-endpoint = <&dsi0_out>; - }; - }; - - port@1{ - reg = <1>; - - panel_in_1: endpoint { - remote-endpoint = <&dsi1_out>; - }; - }; - - }; - }; -}; - -&dsi0_out { - data-lanes = <0 1 2>; - remote-endpoint = <&panel_in_0>; -}; - -&dsi0_phy { - vdds-supply = <&vreg_l5a_0p88>; - phy-type = ; - status = "okay"; -}; - -&dsi1 { - vdda-supply = <&vreg_l9a_1p2>; - qcom,dual-dsi-mode; - qcom,sync-dual-dsi; - /* DSI1 is slave, so use DSI0 clocks */ - assigned-clock-parents = <&dsi0_phy 0>, <&dsi0_phy 1>; - status = "okay"; -}; - -&dsi1_out { - data-lanes = <0 1 2>; - remote-endpoint = <&panel_in_1>; -}; - -&dsi1_phy { - vdds-supply = <&vreg_l5a_0p88>; - phy-type = ; - status = "okay"; -}; - &gmu { status = "okay"; }; @@ -608,6 +538,75 @@ status = "okay"; }; +&mdss_dsi0 { + vdda-supply = <&vreg_l9a_1p2>; + qcom,dual-dsi-mode; + qcom,sync-dual-dsi; + qcom,master-dsi; + status = "okay"; + + display_panel: panel@0 { + reg = <0>; + vddio-supply = <&vreg_l14a_1p88>; + reset-gpios = <&tlmm 75 GPIO_ACTIVE_LOW>; + backlight = <&backlight>; + + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + panel_in_0: endpoint { + remote-endpoint = <&mdss_dsi0_out>; + }; + }; + + port@1{ + reg = <1>; + + panel_in_1: endpoint { + remote-endpoint = <&mdss_dsi1_out>; + }; + }; + }; + }; +}; + +&mdss_dsi0_out { + data-lanes = <0 1 2>; + remote-endpoint = <&panel_in_0>; +}; + +&mdss_dsi0_phy { + vdds-supply = <&vreg_l5a_0p88>; + phy-type = ; + status = "okay"; +}; + +&mdss_dsi1 { + vdda-supply = <&vreg_l9a_1p2>; + qcom,dual-dsi-mode; + qcom,sync-dual-dsi; + /* DSI1 is slave, so use DSI0 clocks */ + assigned-clock-parents = <&mdss_dsi0_phy 0>, <&mdss_dsi0_phy 1>; + status = "okay"; +}; + +&mdss_dsi1_out { + data-lanes = <0 1 2>; + remote-endpoint = <&panel_in_1>; +}; + +&mdss_dsi1_phy { + vdds-supply = <&vreg_l5a_0p88>; + phy-type = ; + status = "okay"; +}; + &pcie0 { status = "okay"; }; diff --git a/arch/arm64/boot/dts/qcom/sm8250.dtsi b/arch/arm64/boot/dts/qcom/sm8250.dtsi index 7bea916900e2997f6a1d04b62506aa68c2d37da4..83ab6de459bc4469c9e1e7ce08ab7be183020daa 100644 --- a/arch/arm64/boot/dts/qcom/sm8250.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8250.dtsi @@ -106,8 +106,8 @@ power-domain-names = "psci"; qcom,freq-domain = <&cpufreq_hw 0>; operating-points-v2 = <&cpu0_opp_table>; - interconnects = <&gem_noc MASTER_AMPSS_M0 &mc_virt SLAVE_EBI_CH0>, - <&epss_l3 MASTER_OSM_L3_APPS &epss_l3 SLAVE_OSM_L3>; + interconnects = <&gem_noc MASTER_AMPSS_M0 0 &mc_virt SLAVE_EBI_CH0 0>, + <&epss_l3 MASTER_OSM_L3_APPS 0 &epss_l3 SLAVE_OSM_L3 0>; #cooling-cells = <2>; L2_0: l2-cache { compatible = "cache"; @@ -137,8 +137,8 @@ power-domain-names = "psci"; qcom,freq-domain = <&cpufreq_hw 0>; operating-points-v2 = <&cpu0_opp_table>; - interconnects = <&gem_noc MASTER_AMPSS_M0 &mc_virt SLAVE_EBI_CH0>, - <&epss_l3 MASTER_OSM_L3_APPS &epss_l3 SLAVE_OSM_L3>; + interconnects = <&gem_noc MASTER_AMPSS_M0 0 &mc_virt SLAVE_EBI_CH0 0>, + <&epss_l3 MASTER_OSM_L3_APPS 0 &epss_l3 SLAVE_OSM_L3 0>; #cooling-cells = <2>; L2_100: l2-cache { compatible = "cache"; @@ -162,8 +162,8 @@ power-domain-names = "psci"; qcom,freq-domain = <&cpufreq_hw 0>; operating-points-v2 = <&cpu0_opp_table>; - interconnects = <&gem_noc MASTER_AMPSS_M0 &mc_virt SLAVE_EBI_CH0>, - <&epss_l3 MASTER_OSM_L3_APPS &epss_l3 SLAVE_OSM_L3>; + interconnects = <&gem_noc MASTER_AMPSS_M0 0 &mc_virt SLAVE_EBI_CH0 0>, + <&epss_l3 MASTER_OSM_L3_APPS 0 &epss_l3 SLAVE_OSM_L3 0>; #cooling-cells = <2>; L2_200: l2-cache { compatible = "cache"; @@ -187,8 +187,8 @@ power-domain-names = "psci"; qcom,freq-domain = <&cpufreq_hw 0>; operating-points-v2 = <&cpu0_opp_table>; - interconnects = <&gem_noc MASTER_AMPSS_M0 &mc_virt SLAVE_EBI_CH0>, - <&epss_l3 MASTER_OSM_L3_APPS &epss_l3 SLAVE_OSM_L3>; + interconnects = <&gem_noc MASTER_AMPSS_M0 0 &mc_virt SLAVE_EBI_CH0 0>, + <&epss_l3 MASTER_OSM_L3_APPS 0 &epss_l3 SLAVE_OSM_L3 0>; #cooling-cells = <2>; L2_300: l2-cache { compatible = "cache"; @@ -212,8 +212,8 @@ power-domain-names = "psci"; qcom,freq-domain = <&cpufreq_hw 1>; operating-points-v2 = <&cpu4_opp_table>; - interconnects = <&gem_noc MASTER_AMPSS_M0 &mc_virt SLAVE_EBI_CH0>, - <&epss_l3 MASTER_OSM_L3_APPS &epss_l3 SLAVE_OSM_L3>; + interconnects = <&gem_noc MASTER_AMPSS_M0 0 &mc_virt SLAVE_EBI_CH0 0>, + <&epss_l3 MASTER_OSM_L3_APPS 0 &epss_l3 SLAVE_OSM_L3 0>; #cooling-cells = <2>; L2_400: l2-cache { compatible = "cache"; @@ -237,8 +237,8 @@ power-domain-names = "psci"; qcom,freq-domain = <&cpufreq_hw 1>; operating-points-v2 = <&cpu4_opp_table>; - interconnects = <&gem_noc MASTER_AMPSS_M0 &mc_virt SLAVE_EBI_CH0>, - <&epss_l3 MASTER_OSM_L3_APPS &epss_l3 SLAVE_OSM_L3>; + interconnects = <&gem_noc MASTER_AMPSS_M0 0 &mc_virt SLAVE_EBI_CH0 0>, + <&epss_l3 MASTER_OSM_L3_APPS 0 &epss_l3 SLAVE_OSM_L3 0>; #cooling-cells = <2>; L2_500: l2-cache { compatible = "cache"; @@ -262,8 +262,8 @@ power-domain-names = "psci"; qcom,freq-domain = <&cpufreq_hw 1>; operating-points-v2 = <&cpu4_opp_table>; - interconnects = <&gem_noc MASTER_AMPSS_M0 &mc_virt SLAVE_EBI_CH0>, - <&epss_l3 MASTER_OSM_L3_APPS &epss_l3 SLAVE_OSM_L3>; + interconnects = <&gem_noc MASTER_AMPSS_M0 0 &mc_virt SLAVE_EBI_CH0 0>, + <&epss_l3 MASTER_OSM_L3_APPS 0 &epss_l3 SLAVE_OSM_L3 0>; #cooling-cells = <2>; L2_600: l2-cache { compatible = "cache"; @@ -287,8 +287,8 @@ power-domain-names = "psci"; qcom,freq-domain = <&cpufreq_hw 2>; operating-points-v2 = <&cpu7_opp_table>; - interconnects = <&gem_noc MASTER_AMPSS_M0 &mc_virt SLAVE_EBI_CH0>, - <&epss_l3 MASTER_OSM_L3_APPS &epss_l3 SLAVE_OSM_L3>; + interconnects = <&gem_noc MASTER_AMPSS_M0 0 &mc_virt SLAVE_EBI_CH0 0>, + <&epss_l3 MASTER_OSM_L3_APPS 0 &epss_l3 SLAVE_OSM_L3 0>; #cooling-cells = <2>; L2_700: l2-cache { compatible = "cache"; @@ -1789,49 +1789,49 @@ config_noc: interconnect@1500000 { compatible = "qcom,sm8250-config-noc"; reg = <0 0x01500000 0 0xa580>; - #interconnect-cells = <1>; + #interconnect-cells = <2>; qcom,bcm-voters = <&apps_bcm_voter>; }; system_noc: interconnect@1620000 { compatible = "qcom,sm8250-system-noc"; reg = <0 0x01620000 0 0x1c200>; - #interconnect-cells = <1>; + #interconnect-cells = <2>; qcom,bcm-voters = <&apps_bcm_voter>; }; mc_virt: interconnect@163d000 { compatible = "qcom,sm8250-mc-virt"; reg = <0 0x0163d000 0 0x1000>; - #interconnect-cells = <1>; + #interconnect-cells = <2>; qcom,bcm-voters = <&apps_bcm_voter>; }; aggre1_noc: interconnect@16e0000 { compatible = "qcom,sm8250-aggre1-noc"; reg = <0 0x016e0000 0 0x1f180>; - #interconnect-cells = <1>; + #interconnect-cells = <2>; qcom,bcm-voters = <&apps_bcm_voter>; }; aggre2_noc: interconnect@1700000 { compatible = "qcom,sm8250-aggre2-noc"; reg = <0 0x01700000 0 0x33000>; - #interconnect-cells = <1>; + #interconnect-cells = <2>; qcom,bcm-voters = <&apps_bcm_voter>; }; compute_noc: interconnect@1733000 { compatible = "qcom,sm8250-compute-noc"; reg = <0 0x01733000 0 0xa180>; - #interconnect-cells = <1>; + #interconnect-cells = <2>; qcom,bcm-voters = <&apps_bcm_voter>; }; mmss_noc: interconnect@1740000 { compatible = "qcom,sm8250-mmss-noc"; reg = <0 0x01740000 0 0x1f080>; - #interconnect-cells = <1>; + #interconnect-cells = <2>; qcom,bcm-voters = <&apps_bcm_voter>; }; @@ -2232,6 +2232,38 @@ }; }; + cryptobam: dma-controller@1dc4000 { + compatible = "qcom,bam-v1.7.4", "qcom,bam-v1.7.0"; + reg = <0 0x01dc4000 0 0x24000>; + interrupts = ; + #dma-cells = <1>; + qcom,ee = <0>; + qcom,controlled-remotely; + num-channels = <8>; + qcom,num-ees = <2>; + iommus = <&apps_smmu 0x592 0x0000>, + <&apps_smmu 0x598 0x0000>, + <&apps_smmu 0x599 0x0000>, + <&apps_smmu 0x59f 0x0000>, + <&apps_smmu 0x586 0x0011>, + <&apps_smmu 0x596 0x0011>; + }; + + crypto: crypto@1dfa000 { + compatible = "qcom,sm8250-qce", "qcom,sm8150-qce", "qcom,qce"; + reg = <0 0x01dfa000 0 0x6000>; + dmas = <&cryptobam 4>, <&cryptobam 5>; + dma-names = "rx", "tx"; + iommus = <&apps_smmu 0x592 0x0000>, + <&apps_smmu 0x598 0x0000>, + <&apps_smmu 0x599 0x0000>, + <&apps_smmu 0x59f 0x0000>, + <&apps_smmu 0x586 0x0011>, + <&apps_smmu 0x596 0x0011>; + interconnects = <&aggre2_noc MASTER_CRYPTO_CORE_0 0 &mc_virt SLAVE_EBI_CH0 0>; + interconnect-names = "memory"; + }; + tcsr_mutex: hwlock@1f40000 { compatible = "qcom,tcsr-mutex"; reg = <0x0 0x01f40000 0x0 0x40000>; @@ -3661,21 +3693,21 @@ dc_noc: interconnect@90c0000 { compatible = "qcom,sm8250-dc-noc"; reg = <0 0x090c0000 0 0x4200>; - #interconnect-cells = <1>; + #interconnect-cells = <2>; qcom,bcm-voters = <&apps_bcm_voter>; }; gem_noc: interconnect@9100000 { compatible = "qcom,sm8250-gem-noc"; reg = <0 0x09100000 0 0xb4000>; - #interconnect-cells = <1>; + #interconnect-cells = <2>; qcom,bcm-voters = <&apps_bcm_voter>; }; npu_noc: interconnect@9990000 { compatible = "qcom,sm8250-npu-noc"; reg = <0 0x09990000 0 0x1600>; - #interconnect-cells = <1>; + #interconnect-cells = <2>; qcom,bcm-voters = <&apps_bcm_voter>; }; @@ -3718,6 +3750,10 @@ resets = <&gcc GCC_USB30_PRIM_BCR>; + interconnects = <&aggre1_noc MASTER_USB3 0 &mc_virt SLAVE_EBI_CH0 0>, + <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_USB3 0>; + interconnect-names = "usb-ddr", "apps-usb"; + usb_1_dwc3: usb@a600000 { compatible = "snps,dwc3"; reg = <0 0x0a600000 0 0xcd00>; @@ -3778,6 +3814,10 @@ resets = <&gcc GCC_USB30_SEC_BCR>; + interconnects = <&aggre1_noc MASTER_USB3_1 0 &mc_virt SLAVE_EBI_CH0 0>, + <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_USB3_1 0>; + interconnect-names = "usb-ddr", "apps-usb"; + usb_2_dwc3: usb@a800000 { compatible = "snps,dwc3"; reg = <0 0x0a800000 0 0xcd00>; @@ -3805,8 +3845,8 @@ <&videocc VIDEO_CC_MVS0_CLK>; clock-names = "iface", "core", "vcodec0_core"; - interconnects = <&gem_noc MASTER_AMPSS_M0 &config_noc SLAVE_VENUS_CFG>, - <&mmss_noc MASTER_VIDEO_P0 &mc_virt SLAVE_EBI_CH0>; + interconnects = <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_VENUS_CFG 0>, + <&mmss_noc MASTER_VIDEO_P0 0 &mc_virt SLAVE_EBI_CH0 0>; interconnect-names = "cpu-cfg", "video-mem"; iommus = <&apps_smmu 0x2100 0x0400>; @@ -4090,10 +4130,10 @@ <&apps_smmu 0xc40 0x400>, <&apps_smmu 0xc41 0x400>; - interconnects = <&gem_noc MASTER_AMPSS_M0 &config_noc SLAVE_CAMERA_CFG>, - <&mmss_noc MASTER_CAMNOC_HF &mc_virt SLAVE_EBI_CH0>, - <&mmss_noc MASTER_CAMNOC_SF &mc_virt SLAVE_EBI_CH0>, - <&mmss_noc MASTER_CAMNOC_ICP &mc_virt SLAVE_EBI_CH0>; + interconnects = <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_CAMERA_CFG 0>, + <&mmss_noc MASTER_CAMNOC_HF 0 &mc_virt SLAVE_EBI_CH0 0>, + <&mmss_noc MASTER_CAMNOC_SF 0 &mc_virt SLAVE_EBI_CH0 0>, + <&mmss_noc MASTER_CAMNOC_ICP 0 &mc_virt SLAVE_EBI_CH0 0>; interconnect-names = "cam_ahb", "cam_hf_0_mnoc", "cam_sf_0_mnoc", @@ -4150,8 +4190,8 @@ reg = <0 0x0ae00000 0 0x1000>; reg-names = "mdss"; - interconnects = <&mmss_noc MASTER_MDP_PORT0 &mc_virt SLAVE_EBI_CH0>, - <&mmss_noc MASTER_MDP_PORT1 &mc_virt SLAVE_EBI_CH0>; + interconnects = <&mmss_noc MASTER_MDP_PORT0 0 &mc_virt SLAVE_EBI_CH0 0>, + <&mmss_noc MASTER_MDP_PORT1 0 &mc_virt SLAVE_EBI_CH0 0>; interconnect-names = "mdp0-mem", "mdp1-mem"; power-domains = <&dispcc MDSS_GDSC>; @@ -4202,14 +4242,14 @@ port@0 { reg = <0>; dpu_intf1_out: endpoint { - remote-endpoint = <&dsi0_in>; + remote-endpoint = <&mdss_dsi0_in>; }; }; port@1 { reg = <1>; dpu_intf2_out: endpoint { - remote-endpoint = <&dsi1_in>; + remote-endpoint = <&mdss_dsi1_in>; }; }; }; @@ -4239,7 +4279,7 @@ }; }; - dsi0: dsi@ae94000 { + mdss_dsi0: dsi@ae94000 { compatible = "qcom,sm8250-dsi-ctrl", "qcom,mdss-dsi-ctrl"; reg = <0 0x0ae94000 0 0x400>; @@ -4262,12 +4302,12 @@ "bus"; assigned-clocks = <&dispcc DISP_CC_MDSS_BYTE0_CLK_SRC>, <&dispcc DISP_CC_MDSS_PCLK0_CLK_SRC>; - assigned-clock-parents = <&dsi0_phy 0>, <&dsi0_phy 1>; + assigned-clock-parents = <&mdss_dsi0_phy 0>, <&mdss_dsi0_phy 1>; operating-points-v2 = <&dsi_opp_table>; power-domains = <&rpmhpd SM8250_MMCX>; - phys = <&dsi0_phy>; + phys = <&mdss_dsi0_phy>; status = "disabled"; @@ -4280,14 +4320,14 @@ port@0 { reg = <0>; - dsi0_in: endpoint { + mdss_dsi0_in: endpoint { remote-endpoint = <&dpu_intf1_out>; }; }; port@1 { reg = <1>; - dsi0_out: endpoint { + mdss_dsi0_out: endpoint { }; }; }; @@ -4312,7 +4352,7 @@ }; }; - dsi0_phy: phy@ae94400 { + mdss_dsi0_phy: phy@ae94400 { compatible = "qcom,dsi-phy-7nm"; reg = <0 0x0ae94400 0 0x200>, <0 0x0ae94600 0 0x280>, @@ -4331,7 +4371,7 @@ status = "disabled"; }; - dsi1: dsi@ae96000 { + mdss_dsi1: dsi@ae96000 { compatible = "qcom,sm8250-dsi-ctrl", "qcom,mdss-dsi-ctrl"; reg = <0 0x0ae96000 0 0x400>; @@ -4354,12 +4394,12 @@ "bus"; assigned-clocks = <&dispcc DISP_CC_MDSS_BYTE1_CLK_SRC>, <&dispcc DISP_CC_MDSS_PCLK1_CLK_SRC>; - assigned-clock-parents = <&dsi1_phy 0>, <&dsi1_phy 1>; + assigned-clock-parents = <&mdss_dsi1_phy 0>, <&mdss_dsi1_phy 1>; operating-points-v2 = <&dsi_opp_table>; power-domains = <&rpmhpd SM8250_MMCX>; - phys = <&dsi1_phy>; + phys = <&mdss_dsi1_phy>; status = "disabled"; @@ -4372,20 +4412,20 @@ port@0 { reg = <0>; - dsi1_in: endpoint { + mdss_dsi1_in: endpoint { remote-endpoint = <&dpu_intf2_out>; }; }; port@1 { reg = <1>; - dsi1_out: endpoint { + mdss_dsi1_out: endpoint { }; }; }; }; - dsi1_phy: phy@ae96400 { + mdss_dsi1_phy: phy@ae96400 { compatible = "qcom,dsi-phy-7nm"; reg = <0 0x0ae96400 0 0x200>, <0 0x0ae96600 0 0x280>, @@ -4411,10 +4451,10 @@ power-domains = <&rpmhpd SM8250_MMCX>; required-opps = <&rpmhpd_opp_low_svs>; clocks = <&rpmhcc RPMH_CXO_CLK>, - <&dsi0_phy 0>, - <&dsi0_phy 1>, - <&dsi1_phy 0>, - <&dsi1_phy 1>, + <&mdss_dsi0_phy 0>, + <&mdss_dsi0_phy 1>, + <&mdss_dsi1_phy 0>, + <&mdss_dsi1_phy 1>, <&dp_phy 0>, <&dp_phy 1>; clock-names = "bi_tcxo", @@ -5254,7 +5294,7 @@ }; apps_smmu: iommu@15000000 { - compatible = "qcom,sm8250-smmu-500", "arm,mmu-500"; + compatible = "qcom,sm8250-smmu-500", "qcom,smmu-500", "arm,mmu-500"; reg = <0 0x15000000 0 0x100000>; #iommu-cells = <2>; #global-interrupts = <2>; @@ -5639,7 +5679,7 @@ clocks = <&rpmhcc RPMH_CXO_CLK>, <&gcc GPLL0>; clock-names = "xo", "alternate"; - #interconnect-cells = <1>; + #interconnect-cells = <2>; }; cpufreq_hw: cpufreq@18591000 { diff --git a/arch/arm64/boot/dts/qcom/sm8350-hdk.dts b/arch/arm64/boot/dts/qcom/sm8350-hdk.dts index 2ee1b121686ae6fc101dc2d86a39a1d2eba35cef..61dd9663fabe08cc68211ab99e0e15c0e24860ba 100644 --- a/arch/arm64/boot/dts/qcom/sm8350-hdk.dts +++ b/arch/arm64/boot/dts/qcom/sm8350-hdk.dts @@ -58,7 +58,15 @@ reg = <1>; pmic_glink_ss_in: endpoint { - remote-endpoint = <&usb_1_dwc3_ss>; + remote-endpoint = <&usb_1_qmpphy_out>; + }; + }; + + port@2 { + reg = <2>; + + pmic_glink_sbu: endpoint { + remote-endpoint = <&fsa4480_sbu_mux>; }; }; }; @@ -326,6 +334,37 @@ }; }; +&i2c13 { + clock-frequency = <100000>; + + status = "okay"; + + typec-mux@42 { + compatible = "fcs,fsa4480"; + reg = <0x42>; + + interrupts-extended = <&tlmm 2 IRQ_TYPE_LEVEL_LOW>; + + vcc-supply = <&vreg_bob>; + mode-switch; + orientation-switch; + svid = /bits/ 16 <0xff01>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + fsa4480_sbu_mux: endpoint { + remote-endpoint = <&pmic_glink_sbu>; + }; + }; + }; + }; +}; + &i2c15 { clock-frequency = <400000>; status = "okay"; @@ -370,8 +409,19 @@ status = "okay"; }; -&mdss_mdp { +&mdss_dp { status = "okay"; + + ports { + port@1 { + reg = <1>; + + mdss_dp0_out: endpoint { + data-lanes = <0 1>; + remote-endpoint = <&usb_1_qmpphy_dp_in>; + }; + }; + }; }; &mpss { @@ -416,6 +466,10 @@ status = "okay"; }; +&qupv3_id_1 { + status = "okay"; +}; + &qupv3_id_2 { status = "okay"; }; @@ -716,7 +770,7 @@ }; &usb_1_dwc3_ss { - remote-endpoint = <&pmic_glink_ss_in>; + remote-endpoint = <&usb_1_qmpphy_usb_ss_in>; }; &usb_1_hsphy { @@ -732,6 +786,20 @@ vdda-phy-supply = <&vreg_l6b_1p2>; vdda-pll-supply = <&vreg_l1b_0p88>; + + orientation-switch; +}; + +&usb_1_qmpphy_dp_in { + remote-endpoint = <&mdss_dp0_out>; +}; + +&usb_1_qmpphy_out { + remote-endpoint = <&pmic_glink_ss_in>; +}; + +&usb_1_qmpphy_usb_ss_in { + remote-endpoint = <&usb_1_dwc3_ss>; }; &usb_2 { diff --git a/arch/arm64/boot/dts/qcom/sm8350.dtsi b/arch/arm64/boot/dts/qcom/sm8350.dtsi index 3efdc03ed0f1107860f6ef8aa95bcf6a7e31b4fc..88ef478cb5ccb0c137a204ad0e39210710e06c2e 100644 --- a/arch/arm64/boot/dts/qcom/sm8350.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8350.dtsi @@ -907,7 +907,7 @@ }; }; - gpi_dma0: dma-controller@900000 { + gpi_dma0: dma-controller@9800000 { compatible = "qcom,sm8350-gpi-dma", "qcom,sm6350-gpi-dma"; reg = <0 0x09800000 0 0x60000>; interrupts = , @@ -1638,7 +1638,7 @@ status = "disabled"; }; - pcie1_phy: phy@1c0f000 { + pcie1_phy: phy@1c0e000 { compatible = "qcom,sm8350-qmp-gen3x2-pcie-phy"; reg = <0 0x01c0e000 0 0x2000>; clocks = <&gcc GCC_PCIE_1_AUX_CLK>, @@ -1735,6 +1735,28 @@ }; }; + cryptobam: dma-controller@1dc4000 { + compatible = "qcom,bam-v1.7.4", "qcom,bam-v1.7.0"; + reg = <0 0x01dc4000 0 0x24000>; + interrupts = ; + #dma-cells = <1>; + qcom,ee = <0>; + qcom,controlled-remotely; + iommus = <&apps_smmu 0x594 0x0011>, + <&apps_smmu 0x596 0x0011>; + }; + + crypto: crypto@1dfa000 { + compatible = "qcom,sm8350-qce", "qcom,sm8150-qce", "qcom,qce"; + reg = <0 0x01dfa000 0 0x6000>; + dmas = <&cryptobam 4>, <&cryptobam 5>; + dma-names = "rx", "tx"; + iommus = <&apps_smmu 0x594 0x0011>, + <&apps_smmu 0x596 0x0011>; + interconnects = <&aggre2_noc MASTER_CRYPTO 0 &mc_virt SLAVE_EBI1 0>; + interconnect-names = "memory"; + }; + ipa: ipa@1e40000 { compatible = "qcom,sm8350-ipa"; @@ -2140,7 +2162,7 @@ resets = <&gcc GCC_QUSB2PHY_SEC_BCR>; }; - usb_1_qmpphy: phy@88e9000 { + usb_1_qmpphy: phy@88e8000 { compatible = "qcom,sm8350-qmp-usb3-dp-phy"; reg = <0 0x088e8000 0 0x3000>; @@ -2158,6 +2180,32 @@ #phy-cells = <1>; status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + usb_1_qmpphy_out: endpoint { + }; + }; + + port@1 { + reg = <1>; + + usb_1_qmpphy_usb_ss_in: endpoint { + }; + }; + + port@2 { + reg = <2>; + + usb_1_qmpphy_dp_in: endpoint { + }; + }; + }; }; usb_2_qmpphy: phy-wrapper@88eb000 { @@ -2256,6 +2304,10 @@ resets = <&gcc GCC_USB30_PRIM_BCR>; + interconnects = <&aggre1_noc MASTER_USB3_0 0 &mc_virt SLAVE_EBI1 0>, + <&gem_noc MASTER_APPSS_PROC 0 &config_noc SLAVE_USB3_0 0>; + interconnect-names = "usb-ddr", "apps-usb"; + usb_1_dwc3: usb@a600000 { compatible = "snps,dwc3"; reg = <0 0x0a600000 0 0xcd00>; @@ -2325,6 +2377,10 @@ resets = <&gcc GCC_USB30_SEC_BCR>; + interconnects = <&aggre1_noc MASTER_USB3_1 0 &mc_virt SLAVE_EBI1 0>, + <&gem_noc MASTER_APPSS_PROC 0 &config_noc SLAVE_USB3_1 0>; + interconnect-names = "usb-ddr", "apps-usb"; + usb_2_dwc3: usb@a800000 { compatible = "snps,dwc3"; reg = <0 0x0a800000 0 0xcd00>; diff --git a/arch/arm64/boot/dts/qcom/sm8450-hdk.dts b/arch/arm64/boot/dts/qcom/sm8450-hdk.dts index e931545a2cac4dc16e5dd58150daecc826cf1c27..bc4c125d1832eb7ee7943e4b3ef58f3b8d02d477 100644 --- a/arch/arm64/boot/dts/qcom/sm8450-hdk.dts +++ b/arch/arm64/boot/dts/qcom/sm8450-hdk.dts @@ -114,9 +114,18 @@ reg = <1>; pmic_glink_ss_in: endpoint { - remote-endpoint = <&usb_1_dwc3_ss>; + remote-endpoint = <&usb_1_qmpphy_out>; }; }; + + port@2 { + reg = <2>; + + pmic_glink_sbu: endpoint { + remote-endpoint = <&fsa4480_sbu_mux>; + }; + }; + }; }; }; @@ -494,6 +503,37 @@ }; }; +&i2c5 { + clock-frequency = <100000>; + + status = "okay"; + + typec-mux@42 { + compatible = "fcs,fsa4480"; + reg = <0x42>; + + interrupts-extended = <&tlmm 2 IRQ_TYPE_LEVEL_LOW>; + + vcc-supply = <&vreg_bob>; + mode-switch; + orientation-switch; + svid = /bits/ 16 <0xff01>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + fsa4480_sbu_mux: endpoint { + remote-endpoint = <&pmic_glink_sbu>; + }; + }; + }; + }; +}; + &mdss { status = "okay"; }; @@ -513,8 +553,19 @@ status = "okay"; }; -&mdss_mdp { +&mdss_dp0 { status = "okay"; + + ports { + port@1 { + reg = <1>; + + mdss_dp0_out: endpoint { + data-lanes = <0 1>; + remote-endpoint = <&usb_1_qmpphy_dp_in>; + }; + }; + }; }; &pcie0 { @@ -766,7 +817,7 @@ }; &usb_1_dwc3_ss { - remote-endpoint = <&pmic_glink_ss_in>; + remote-endpoint = <&usb_1_qmpphy_usb_ss_in>; }; &usb_1_hsphy { @@ -782,6 +833,20 @@ vdda-phy-supply = <&vreg_l6b_1p2>; vdda-pll-supply = <&vreg_l1b_0p91>; + + orientation-switch; +}; + +&usb_1_qmpphy_dp_in { + remote-endpoint = <&mdss_dp0_out>; +}; + +&usb_1_qmpphy_out { + remote-endpoint = <&pmic_glink_ss_in>; +}; + +&usb_1_qmpphy_usb_ss_in { + remote-endpoint = <&usb_1_dwc3_ss>; }; &vamacro { diff --git a/arch/arm64/boot/dts/qcom/sm8450.dtsi b/arch/arm64/boot/dts/qcom/sm8450.dtsi index d59ea8ee711143ad7aae301c3317d6b2bfb6f14a..5cd7296c76605dc79d10cdd73f308d15a9525274 100644 --- a/arch/arm64/boot/dts/qcom/sm8450.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8450.dtsi @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -2053,6 +2054,32 @@ #phy-cells = <1>; status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + usb_1_qmpphy_out: endpoint { + }; + }; + + port@1 { + reg = <1>; + + usb_1_qmpphy_usb_ss_in: endpoint { + }; + }; + + port@2 { + reg = <2>; + + usb_1_qmpphy_dp_in: endpoint { + }; + }; + }; }; remoteproc_slpi: remoteproc@2400000 { @@ -2581,6 +2608,18 @@ }; }; + videocc: clock-controller@aaf0000 { + compatible = "qcom,sm8450-videocc"; + reg = <0 0x0aaf0000 0 0x10000>; + clocks = <&rpmhcc RPMH_CXO_CLK>, + <&gcc GCC_VIDEO_AHB_CLK>; + power-domains = <&rpmhpd SM8450_MMCX>; + required-opps = <&rpmhpd_opp_low_svs>; + #clock-cells = <1>; + #reset-cells = <1>; + #power-domain-cells = <1>; + }; + cci0: cci@ac15000 { compatible = "qcom,sm8450-cci", "qcom,msm8996-cci"; reg = <0 0x0ac15000 0 0x1000>; @@ -4002,31 +4041,43 @@ opp-level = ; }; - rpmhpd_opp_svs: opp5 { + rpmhpd_opp_low_svs_l1: opp5 { + opp-level = ; + }; + + rpmhpd_opp_svs: opp6 { opp-level = ; }; - rpmhpd_opp_svs_l1: opp6 { + rpmhpd_opp_svs_l0: opp7 { + opp-level = ; + }; + + rpmhpd_opp_svs_l1: opp8 { opp-level = ; }; - rpmhpd_opp_nom: opp7 { + rpmhpd_opp_svs_l2: opp9 { + opp-level = ; + }; + + rpmhpd_opp_nom: opp10 { opp-level = ; }; - rpmhpd_opp_nom_l1: opp8 { + rpmhpd_opp_nom_l1: opp11 { opp-level = ; }; - rpmhpd_opp_nom_l2: opp9 { + rpmhpd_opp_nom_l2: opp12 { opp-level = ; }; - rpmhpd_opp_turbo: opp10 { + rpmhpd_opp_turbo: opp13 { opp-level = ; }; - rpmhpd_opp_turbo_l1: opp11 { + rpmhpd_opp_turbo_l1: opp14 { opp-level = ; }; }; @@ -4147,6 +4198,34 @@ }; }; + cryptobam: dma-controller@1dc4000 { + compatible = "qcom,bam-v1.7.4", "qcom,bam-v1.7.0"; + reg = <0 0x01dc4000 0 0x28000>; + interrupts = ; + #dma-cells = <1>; + qcom,ee = <0>; + qcom,controlled-remotely; + iommus = <&apps_smmu 0x584 0x11>, + <&apps_smmu 0x588 0x0>, + <&apps_smmu 0x598 0x5>, + <&apps_smmu 0x59a 0x0>, + <&apps_smmu 0x59f 0x0>; + }; + + crypto: crypto@1de0000 { + compatible = "qcom,sm8450-qce", "qcom,sm8150-qce", "qcom,qce"; + reg = <0 0x01dfa000 0 0x6000>; + dmas = <&cryptobam 4>, <&cryptobam 5>; + dma-names = "rx", "tx"; + iommus = <&apps_smmu 0x584 0x11>, + <&apps_smmu 0x588 0x0>, + <&apps_smmu 0x598 0x5>, + <&apps_smmu 0x59a 0x0>, + <&apps_smmu 0x59f 0x0>; + interconnects = <&aggre2_noc MASTER_CRYPTO 0 &mc_virt SLAVE_EBI1 0>; + interconnect-names = "memory"; + }; + sdhc_2: mmc@8804000 { compatible = "qcom,sm8450-sdhci", "qcom,sdhci-msm-v5"; reg = <0 0x08804000 0 0x1000>; @@ -4227,6 +4306,10 @@ resets = <&gcc GCC_USB30_PRIM_BCR>; + interconnects = <&aggre1_noc MASTER_USB3_0 0 &mc_virt SLAVE_EBI1 0>, + <&gem_noc MASTER_APPSS_PROC 0 &config_noc SLAVE_USB3_0 0>; + interconnect-names = "usb-ddr", "apps-usb"; + usb_1_dwc3: usb@a600000 { compatible = "snps,dwc3"; reg = <0 0x0a600000 0 0xcd00>; diff --git a/arch/arm64/boot/dts/qcom/sm8550-mtp.dts b/arch/arm64/boot/dts/qcom/sm8550-mtp.dts index e2b9bb6b1e27937bed773a0940e7aa311d5755f3..ec86c5f380450f8c4d2e079abc130bfb2c0bdfa2 100644 --- a/arch/arm64/boot/dts/qcom/sm8550-mtp.dts +++ b/arch/arm64/boot/dts/qcom/sm8550-mtp.dts @@ -23,6 +23,32 @@ serial0 = &uart7; }; + wcd938x: audio-codec { + compatible = "qcom,wcd9385-codec"; + + pinctrl-names = "default"; + pinctrl-0 = <&wcd_default>; + + qcom,micbias1-microvolt = <1800000>; + qcom,micbias2-microvolt = <1800000>; + qcom,micbias3-microvolt = <1800000>; + qcom,micbias4-microvolt = <1800000>; + qcom,mbhc-buttons-vthreshold-microvolt = <75000 150000 237000 500000 500000 500000 500000 500000>; + qcom,mbhc-headset-vthreshold-microvolt = <1700000>; + qcom,mbhc-headphone-vthreshold-microvolt = <50000>; + qcom,rx-device = <&wcd_rx>; + qcom,tx-device = <&wcd_tx>; + + reset-gpios = <&tlmm 108 GPIO_ACTIVE_LOW>; + + vdd-buck-supply = <&vreg_l15b_1p8>; + vdd-rxtx-supply = <&vreg_l15b_1p8>; + vdd-io-supply = <&vreg_l15b_1p8>; + vdd-mic-bias-supply = <&vreg_bob1>; + + #sound-dai-cells = <1>; + }; + chosen { stdout-path = "serial0:115200n8"; }; @@ -61,6 +87,87 @@ }; }; + sound { + compatible = "qcom,sm8550-sndcard", "qcom,sm8450-sndcard"; + model = "SM8550-MTP"; + audio-routing = "SpkrLeft IN", "WSA_SPK1 OUT", + "SpkrRight IN", "WSA_SPK2 OUT", + "IN1_HPHL", "HPHL_OUT", + "IN2_HPHR", "HPHR_OUT", + "AMIC2", "MIC BIAS2", + "VA DMIC0", "MIC BIAS1", + "VA DMIC1", "MIC BIAS1", + "VA DMIC2", "MIC BIAS3", + "TX DMIC0", "MIC BIAS1", + "TX DMIC1", "MIC BIAS2", + "TX DMIC2", "MIC BIAS3", + "TX SWR_ADC1", "ADC2_OUTPUT"; + + wcd-playback-dai-link { + link-name = "WCD Playback"; + + cpu { + sound-dai = <&q6apmbedai RX_CODEC_DMA_RX_0>; + }; + + codec { + sound-dai = <&wcd938x 0>, <&swr1 0>, <&lpass_rxmacro 0>; + }; + + platform { + sound-dai = <&q6apm>; + }; + }; + + wcd-capture-dai-link { + link-name = "WCD Capture"; + + cpu { + sound-dai = <&q6apmbedai TX_CODEC_DMA_TX_3>; + }; + + codec { + sound-dai = <&wcd938x 1>, <&swr2 0>, <&lpass_txmacro 0>; + }; + + platform { + sound-dai = <&q6apm>; + }; + }; + + wsa-dai-link { + link-name = "WSA Playback"; + + cpu { + sound-dai = <&q6apmbedai WSA_CODEC_DMA_RX_0>; + }; + + codec { + sound-dai = <&left_spkr>, <&right_spkr>, <&swr0 0>, <&lpass_wsamacro 0>; + }; + + platform { + sound-dai = <&q6apm>; + }; + }; + + va-dai-link { + link-name = "VA Capture"; + + cpu { + sound-dai = <&q6apmbedai TX_CODEC_DMA_TX_3>; + }; + + codec { + sound-dai = <&lpass_vamacro 0>; + }; + + platform { + sound-dai = <&q6apm>; + }; + }; + }; + vph_pwr: vph-pwr-regulator { compatible = "regulator-fixed"; regulator-name = "vph_pwr"; @@ -393,8 +500,22 @@ }; }; -&dispcc { - status = "okay"; +&lpass_tlmm { + spkr_1_sd_n_active: spkr-1-sd-n-active-state { + pins = "gpio17"; + function = "gpio"; + drive-strength = <16>; + bias-disable; + output-low; + }; + + spkr_2_sd_n_active: spkr-2-sd-n-active-state { + pins = "gpio18"; + function = "gpio"; + drive-strength = <16>; + bias-disable; + output-low; + }; }; &mdss { @@ -437,10 +558,6 @@ status = "okay"; }; -&mdss_mdp { - status = "okay"; -}; - &pcie_1_phy_aux_clk { clock-frequency = <1000>; }; @@ -535,6 +652,58 @@ clock-frequency = <32000>; }; +&swr0 { + status = "okay"; + + /* WSA8845 */ + left_spkr: speaker@0,0 { + compatible = "sdw20217020400"; + reg = <0 0>; + pinctrl-names = "default"; + pinctrl-0 = <&spkr_1_sd_n_active>; + powerdown-gpios = <&lpass_tlmm 17 GPIO_ACTIVE_LOW>; + #sound-dai-cells = <0>; + sound-name-prefix = "SpkrLeft"; + vdd-1p8-supply = <&vreg_l15b_1p8>; + vdd-io-supply = <&vreg_l3g_1p2>; + }; + + /* WSA8845 */ + right_spkr: speaker@0,1 { + compatible = "sdw20217020400"; + reg = <0 1>; + pinctrl-names = "default"; + pinctrl-0 = <&spkr_2_sd_n_active>; + powerdown-gpios = <&lpass_tlmm 18 GPIO_ACTIVE_LOW>; + #sound-dai-cells = <0>; + sound-name-prefix = "SpkrRight"; + vdd-1p8-supply = <&vreg_l15b_1p8>; + vdd-io-supply = <&vreg_l3g_1p2>; + }; +}; + +&swr1 { + status = "okay"; + + /* WCD9385 RX */ + wcd_rx: codec@0,4 { + compatible = "sdw20217010d00"; + reg = <0 4>; + qcom,rx-port-mapping = <1 2 3 4 5>; + }; +}; + +&swr2 { + status = "okay"; + + /* WCD9385 TX */ + wcd_tx: codec@0,3 { + compatible = "sdw20217010d00"; + reg = <0 3>; + qcom,tx-port-mapping = <1 1 2 3>; + }; +}; + &tlmm { gpio-reserved-ranges = <32 8>; @@ -565,6 +734,14 @@ drive-strength = <2>; bias-pull-down; }; + + wcd_default: wcd-reset-n-active-state { + pins = "gpio108"; + function = "gpio"; + drive-strength = <16>; + bias-disable; + output-low; + }; }; &uart7 { diff --git a/arch/arm64/boot/dts/qcom/sm8550-qrd.dts b/arch/arm64/boot/dts/qcom/sm8550-qrd.dts index d5a645ee2a619f594524c58159a57096c86d5e42..ec4feee6837d60f2ba973ba96b6009e331f608be 100644 --- a/arch/arm64/boot/dts/qcom/sm8550-qrd.dts +++ b/arch/arm64/boot/dts/qcom/sm8550-qrd.dts @@ -5,6 +5,7 @@ /dts-v1/; +#include #include #include "sm8550.dtsi" #include "pm8010.dtsi" @@ -23,10 +24,167 @@ serial0 = &uart7; }; + wcd938x: audio-codec { + compatible = "qcom,wcd9385-codec"; + + pinctrl-names = "default"; + pinctrl-0 = <&wcd_default>; + + qcom,micbias1-microvolt = <1800000>; + qcom,micbias2-microvolt = <1800000>; + qcom,micbias3-microvolt = <1800000>; + qcom,micbias4-microvolt = <1800000>; + qcom,mbhc-buttons-vthreshold-microvolt = <75000 150000 237000 500000 500000 500000 500000 500000>; + qcom,mbhc-headset-vthreshold-microvolt = <1700000>; + qcom,mbhc-headphone-vthreshold-microvolt = <50000>; + qcom,rx-device = <&wcd_rx>; + qcom,tx-device = <&wcd_tx>; + + reset-gpios = <&tlmm 108 GPIO_ACTIVE_LOW>; + + vdd-buck-supply = <&vreg_l15b_1p8>; + vdd-rxtx-supply = <&vreg_l15b_1p8>; + vdd-io-supply = <&vreg_l15b_1p8>; + vdd-mic-bias-supply = <&vreg_bob1>; + + #sound-dai-cells = <1>; + }; + chosen { stdout-path = "serial0:115200n8"; }; + gpio-keys { + compatible = "gpio-keys"; + + pinctrl-0 = <&volume_up_n>; + pinctrl-names = "default"; + + key-volume-up { + label = "Volume Up"; + linux,code = ; + gpios = <&pm8550_gpios 6 GPIO_ACTIVE_LOW>; + debounce-interval = <15>; + linux,can-disable; + wakeup-source; + }; + }; + + pmic-glink { + compatible = "qcom,sm8550-pmic-glink", "qcom,pmic-glink"; + #address-cells = <1>; + #size-cells = <0>; + + connector@0 { + compatible = "usb-c-connector"; + reg = <0>; + power-role = "dual"; + data-role = "dual"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + pmic_glink_hs_in: endpoint { + remote-endpoint = <&usb_1_dwc3_hs>; + }; + }; + + port@1 { + reg = <1>; + + pmic_glink_ss_in: endpoint { + remote-endpoint = <&usb_1_dwc3_ss>; + }; + }; + }; + }; + }; + + sound { + compatible = "qcom,sm8550-sndcard", "qcom,sm8450-sndcard"; + model = "SM8550-QRD"; + audio-routing = "SpkrLeft IN", "WSA_SPK1 OUT", + "SpkrRight IN", "WSA_SPK2 OUT", + "IN1_HPHL", "HPHL_OUT", + "IN2_HPHR", "HPHR_OUT", + "AMIC2", "MIC BIAS2", + "VA DMIC0", "MIC BIAS1", + "VA DMIC1", "MIC BIAS1", + "VA DMIC2", "MIC BIAS3", + "TX DMIC0", "MIC BIAS1", + "TX DMIC1", "MIC BIAS2", + "TX DMIC2", "MIC BIAS3", + "TX SWR_ADC1", "ADC2_OUTPUT"; + + wcd-playback-dai-link { + link-name = "WCD Playback"; + + cpu { + sound-dai = <&q6apmbedai RX_CODEC_DMA_RX_0>; + }; + + codec { + sound-dai = <&wcd938x 0>, <&swr1 0>, <&lpass_rxmacro 0>; + }; + + platform { + sound-dai = <&q6apm>; + }; + }; + + wcd-capture-dai-link { + link-name = "WCD Capture"; + + cpu { + sound-dai = <&q6apmbedai TX_CODEC_DMA_TX_3>; + }; + + codec { + sound-dai = <&wcd938x 1>, <&swr2 0>, <&lpass_txmacro 0>; + }; + + platform { + sound-dai = <&q6apm>; + }; + }; + + wsa-dai-link { + link-name = "WSA Playback"; + + cpu { + sound-dai = <&q6apmbedai WSA_CODEC_DMA_RX_0>; + }; + + codec { + sound-dai = <&north_spkr>, <&south_spkr>, <&swr0 0>, <&lpass_wsamacro 0>; + }; + + platform { + sound-dai = <&q6apm>; + }; + }; + + va-dai-link { + link-name = "VA Capture"; + + cpu { + sound-dai = <&q6apmbedai TX_CODEC_DMA_TX_3>; + }; + + codec { + sound-dai = <&lpass_vamacro 0>; + }; + + platform { + sound-dai = <&q6apm>; + }; + }; + }; + vph_pwr: vph-pwr-regulator { compatible = "regulator-fixed"; regulator-name = "vph_pwr"; @@ -359,6 +517,176 @@ }; }; +&gcc { + clocks = <&bi_tcxo_div2>, <&sleep_clk>, + <&pcie0_phy>, + <&pcie1_phy>, + <0>, + <&ufs_mem_phy 0>, + <&ufs_mem_phy 1>, + <&ufs_mem_phy 2>, + <&usb_dp_qmpphy QMP_USB43DP_USB3_PIPE_CLK>; +}; + +&lpass_tlmm { + spkr_1_sd_n_active: spkr-1-sd-n-active-state { + pins = "gpio17"; + function = "gpio"; + drive-strength = <16>; + bias-disable; + output-low; + }; + + spkr_2_sd_n_active: spkr-2-sd-n-active-state { + pins = "gpio18"; + function = "gpio"; + drive-strength = <16>; + bias-disable; + output-low; + }; +}; + +&mdss { + status = "okay"; +}; + +&mdss_dsi0 { + vdda-supply = <&vreg_l3e_1p2>; + status = "okay"; + + panel@0 { + compatible = "visionox,vtdr6130"; + reg = <0>; + + pinctrl-0 = <&sde_dsi_active>, <&sde_te_active>; + pinctrl-1 = <&sde_dsi_suspend>, <&sde_te_suspend>; + pinctrl-names = "default", "sleep"; + + vci-supply = <&vreg_l13b_3p0>; + vdd-supply = <&vreg_l11b_1p2>; + vddio-supply = <&vreg_l12b_1p8>; + + reset-gpios = <&tlmm 133 GPIO_ACTIVE_LOW>; + + port { + panel0_in: endpoint { + remote-endpoint = <&mdss_dsi0_out>; + }; + }; + }; +}; + +&mdss_dsi0_out { + remote-endpoint = <&panel0_in>; + data-lanes = <0 1 2 3>; +}; + +&mdss_dsi0_phy { + vdds-supply = <&vreg_l1e_0p88>; + status = "okay"; +}; + +&pcie_1_phy_aux_clk { + status = "disabled"; +}; + +&pcie0 { + wake-gpios = <&tlmm 96 GPIO_ACTIVE_HIGH>; + perst-gpios = <&tlmm 94 GPIO_ACTIVE_LOW>; + + pinctrl-0 = <&pcie0_default_state>; + pinctrl-names = "default"; + + status = "okay"; +}; + +&pcie0_phy { + vdda-phy-supply = <&vreg_l1e_0p88>; + vdda-pll-supply = <&vreg_l3e_1p2>; + + status = "okay"; +}; + +&pm8550_flash { + status = "okay"; + + led-0 { + function = LED_FUNCTION_FLASH; + color = ; + led-sources = <1>, <4>; + led-max-microamp = <500000>; + flash-max-microamp = <2000000>; + flash-max-timeout-us = <1280000>; + function-enumerator = <0>; + }; + + led-1 { + function = LED_FUNCTION_FLASH; + color = ; + led-sources = <2>, <3>; + led-max-microamp = <500000>; + flash-max-microamp = <2000000>; + flash-max-timeout-us = <1280000>; + function-enumerator = <1>; + }; +}; + +&pm8550_gpios { + volume_up_n: volume-up-n-state { + pins = "gpio6"; + function = "normal"; + power-source = <1>; + bias-pull-up; + input-enable; + }; +}; + +&pm8550_pwm { + status = "okay"; + + multi-led { + color = ; + function = LED_FUNCTION_STATUS; + + #address-cells = <1>; + #size-cells = <0>; + + led@1 { + reg = <1>; + color = ; + }; + + led@2 { + reg = <2>; + color = ; + }; + + led@3 { + reg = <3>; + color = ; + }; + }; +}; + +&pm8550b_eusb2_repeater { + vdd18-supply = <&vreg_l15b_1p8>; + vdd3-supply = <&vreg_l5b_3p1>; +}; + +&pon_pwrkey { + status = "okay"; +}; + +&pon_resin { + linux,code = ; + + status = "okay"; +}; + +&pcie_1_phy_aux_clk { + clock-frequency = <1000>; +}; + &qupv3_id_0 { status = "okay"; }; @@ -385,8 +713,96 @@ clock-frequency = <32000>; }; +&swr0 { + status = "okay"; + + /* WSA8845, Speaker North */ + north_spkr: speaker@0,0 { + compatible = "sdw20217020400"; + reg = <0 0>; + pinctrl-names = "default"; + pinctrl-0 = <&spkr_1_sd_n_active>; + powerdown-gpios = <&lpass_tlmm 17 GPIO_ACTIVE_LOW>; + #sound-dai-cells = <0>; + sound-name-prefix = "SpkrLeft"; + vdd-1p8-supply = <&vreg_l15b_1p8>; + vdd-io-supply = <&vreg_l3g_1p2>; + }; + + /* WSA8845, Speaker South */ + south_spkr: speaker@0,1 { + compatible = "sdw20217020400"; + reg = <0 1>; + pinctrl-names = "default"; + pinctrl-0 = <&spkr_2_sd_n_active>; + powerdown-gpios = <&lpass_tlmm 18 GPIO_ACTIVE_LOW>; + #sound-dai-cells = <0>; + sound-name-prefix = "SpkrRight"; + vdd-1p8-supply = <&vreg_l15b_1p8>; + vdd-io-supply = <&vreg_l3g_1p2>; + }; +}; + +&swr1 { + status = "okay"; + + /* WCD9385 RX */ + wcd_rx: codec@0,4 { + compatible = "sdw20217010d00"; + reg = <0 4>; + qcom,rx-port-mapping = <1 2 3 4 5>; + }; +}; + +&swr2 { + status = "okay"; + + /* WCD9385 TX */ + wcd_tx: codec@0,3 { + compatible = "sdw20217010d00"; + reg = <0 3>; + qcom,tx-port-mapping = <1 1 2 3>; + }; +}; + &tlmm { gpio-reserved-ranges = <32 8>; + + sde_dsi_active: sde-dsi-active-state { + pins = "gpio133"; + function = "gpio"; + drive-strength = <8>; + bias-disable; + }; + + sde_dsi_suspend: sde-dsi-suspend-state { + pins = "gpio133"; + function = "gpio"; + drive-strength = <2>; + bias-pull-down; + }; + + sde_te_active: sde-te-active-state { + pins = "gpio86"; + function = "mdp_vsync"; + drive-strength = <2>; + bias-pull-down; + }; + + sde_te_suspend: sde-te-suspend-state { + pins = "gpio86"; + function = "mdp_vsync"; + drive-strength = <2>; + bias-pull-down; + }; + + wcd_default: wcd-reset-n-active-state { + pins = "gpio108"; + function = "gpio"; + drive-strength = <16>; + bias-disable; + output-low; + }; }; &uart7 { @@ -417,13 +833,24 @@ }; &usb_1_dwc3 { - dr_mode = "peripheral"; + dr_mode = "otg"; + usb-role-switch; +}; + +&usb_1_dwc3_hs { + remote-endpoint = <&pmic_glink_hs_in>; +}; + +&usb_1_dwc3_ss { + remote-endpoint = <&pmic_glink_ss_in>; }; &usb_1_hsphy { vdd-supply = <&vreg_l1e_0p88>; vdda12-supply = <&vreg_l3e_1p2>; + phys = <&pm8550b_eusb2_repeater>; + status = "okay"; }; diff --git a/arch/arm64/boot/dts/qcom/sm8550.dtsi b/arch/arm64/boot/dts/qcom/sm8550.dtsi index 558cbc4307080407e63a63533ed634b31c12bec6..41d60af93692009e269ad92d844a0a76e4c34077 100644 --- a/arch/arm64/boot/dts/qcom/sm8550.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8550.dtsi @@ -4,7 +4,9 @@ */ #include +#include #include +#include #include #include #include @@ -1848,7 +1850,7 @@ }; cryptobam: dma-controller@1dc4000 { - compatible = "qcom,bam-v1.7.0"; + compatible = "qcom,bam-v1.7.4", "qcom,bam-v1.7.0"; reg = <0x0 0x01dc4000 0x0 0x28000>; interrupts = ; #dma-cells = <1>; @@ -1858,7 +1860,7 @@ <&apps_smmu 0x481 0x0>; }; - crypto: crypto@1de0000 { + crypto: crypto@1dfa000 { compatible = "qcom,sm8550-qce", "qcom,sm8150-qce", "qcom,qce"; reg = <0x0 0x01dfa000 0x0 0x6000>; dmas = <&cryptobam 4>, <&cryptobam 5>; @@ -1960,6 +1962,17 @@ #reset-cells = <1>; }; + gpucc: clock-controller@3d90000 { + compatible = "qcom,sm8550-gpucc"; + reg = <0 0x03d90000 0 0xa000>; + clocks = <&bi_tcxo_div2>, + <&gcc GCC_GPU_GPLL0_CLK_SRC>, + <&gcc GCC_GPU_GPLL0_DIV_CLK_SRC>; + #clock-cells = <1>; + #reset-cells = <1>; + #power-domain-cells = <1>; + }; + remoteproc_mpss: remoteproc@4080000 { compatible = "qcom,sm8550-mpss-pas"; reg = <0x0 0x04080000 0x0 0x4040>; @@ -2394,6 +2407,18 @@ }; }; + videocc: clock-controller@aaf0000 { + compatible = "qcom,sm8550-videocc"; + reg = <0 0x0aaf0000 0 0x10000>; + clocks = <&bi_tcxo_div2>, + <&gcc GCC_VIDEO_AHB_CLK>; + power-domains = <&rpmhpd SM8550_MMCX>; + required-opps = <&rpmhpd_opp_low_svs>; + #clock-cells = <1>; + #reset-cells = <1>; + #power-domain-cells = <1>; + }; + mdss: display-subsystem@ae00000 { compatible = "qcom,sm8550-mdss"; reg = <0 0x0ae00000 0 0x1000>; @@ -2470,6 +2495,13 @@ remote-endpoint = <&mdss_dsi1_in>; }; }; + + port@2 { + reg = <2>; + dpu_intf0_out: endpoint { + remote-endpoint = <&mdss_dp0_in>; + }; + }; }; mdp_opp_table: opp-table { @@ -2497,6 +2529,84 @@ }; }; + mdss_dp0: displayport-controller@ae90000 { + compatible = "qcom,sm8550-dp", "qcom,sm8350-dp"; + reg = <0 0xae90000 0 0x200>, + <0 0xae90200 0 0x200>, + <0 0xae90400 0 0xc00>, + <0 0xae91000 0 0x400>, + <0 0xae91400 0 0x400>; + interrupt-parent = <&mdss>; + interrupts = <12>; + clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>, + <&dispcc DISP_CC_MDSS_DPTX0_AUX_CLK>, + <&dispcc DISP_CC_MDSS_DPTX0_LINK_CLK>, + <&dispcc DISP_CC_MDSS_DPTX0_LINK_INTF_CLK>, + <&dispcc DISP_CC_MDSS_DPTX0_PIXEL0_CLK>; + clock-names = "core_iface", + "core_aux", + "ctrl_link", + "ctrl_link_iface", + "stream_pixel"; + + assigned-clocks = <&dispcc DISP_CC_MDSS_DPTX0_LINK_CLK_SRC>, + <&dispcc DISP_CC_MDSS_DPTX0_PIXEL0_CLK_SRC>; + assigned-clock-parents = <&usb_dp_qmpphy QMP_USB43DP_DP_LINK_CLK>, + <&usb_dp_qmpphy QMP_USB43DP_DP_VCO_DIV_CLK>; + + phys = <&usb_dp_qmpphy QMP_USB43DP_DP_PHY>; + phy-names = "dp"; + + #sound-dai-cells = <0>; + + operating-points-v2 = <&dp_opp_table>; + power-domains = <&rpmhpd SM8550_MMCX>; + + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + mdss_dp0_in: endpoint { + remote-endpoint = <&dpu_intf0_out>; + }; + }; + + port@1 { + reg = <1>; + mdss_dp0_out: endpoint { + }; + }; + }; + + dp_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-162000000 { + opp-hz = /bits/ 64 <162000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-270000000 { + opp-hz = /bits/ 64 <270000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-540000000 { + opp-hz = /bits/ 64 <540000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-810000000 { + opp-hz = /bits/ 64 <810000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + mdss_dsi0: dsi@ae94000 { compatible = "qcom,sm8550-dsi-ctrl", "qcom,mdss-dsi-ctrl"; reg = <0 0x0ae94000 0 0x400>; @@ -2680,8 +2790,8 @@ <&mdss_dsi0_phy 1>, <&mdss_dsi1_phy 0>, <&mdss_dsi1_phy 1>, - <0>, /* dp0 */ - <0>, + <&usb_dp_qmpphy QMP_USB43DP_DP_LINK_CLK>, + <&usb_dp_qmpphy QMP_USB43DP_DP_VCO_DIV_CLK>, <0>, /* dp1 */ <0>, <0>, /* dp2 */ @@ -2693,7 +2803,6 @@ #clock-cells = <1>; #reset-cells = <1>; #power-domain-cells = <1>; - status = "disabled"; }; usb_1_hsphy: phy@88e3000 { @@ -2769,6 +2878,10 @@ resets = <&gcc GCC_USB30_PRIM_BCR>; + interconnects = <&aggre1_noc MASTER_USB3_0 0 &mc_virt SLAVE_EBI1 0>, + <&gem_noc MASTER_APPSS_PROC 0 &config_noc SLAVE_USB3_0 0>; + interconnect-names = "usb-ddr", "apps-usb"; + status = "disabled"; usb_1_dwc3: usb@a600000 { @@ -2883,7 +2996,7 @@ #interrupt-cells = <4>; }; - tlmm: pinctrl@f000000 { + tlmm: pinctrl@f100000 { compatible = "qcom,sm8550-tlmm"; reg = <0 0x0f100000 0 0x300000>; interrupts = ; @@ -3597,6 +3710,7 @@ qcom,drv-id = <2>; qcom,tcs-config = , , , ; + power-domains = <&CLUSTER_PD>; apps_bcm_voter: bcm-voter { compatible = "qcom,bcm-voter"; @@ -3617,43 +3731,63 @@ rpmhpd_opp_table: opp-table { compatible = "operating-points-v2"; - rpmhpd_opp_ret: opp1 { + rpmhpd_opp_ret: opp-16 { opp-level = ; }; - rpmhpd_opp_min_svs: opp2 { + rpmhpd_opp_min_svs: opp-48 { opp-level = ; }; - rpmhpd_opp_low_svs: opp3 { + rpmhpd_opp_low_svs_d2: opp-52 { + opp-level = ; + }; + + rpmhpd_opp_low_svs_d1: opp-56 { + opp-level = ; + }; + + rpmhpd_opp_low_svs_d0: opp-60 { + opp-level = ; + }; + + rpmhpd_opp_low_svs: opp-64 { opp-level = ; }; - rpmhpd_opp_svs: opp4 { + rpmhpd_opp_low_svs_l1: opp-80 { + opp-level = ; + }; + + rpmhpd_opp_svs: opp-128 { opp-level = ; }; - rpmhpd_opp_svs_l1: opp5 { + rpmhpd_opp_svs_l0: opp-144 { + opp-level = ; + }; + + rpmhpd_opp_svs_l1: opp-192 { opp-level = ; }; - rpmhpd_opp_nom: opp6 { + rpmhpd_opp_nom: opp-256 { opp-level = ; }; - rpmhpd_opp_nom_l1: opp7 { + rpmhpd_opp_nom_l1: opp-320 { opp-level = ; }; - rpmhpd_opp_nom_l2: opp8 { + rpmhpd_opp_nom_l2: opp-336 { opp-level = ; }; - rpmhpd_opp_turbo: opp9 { + rpmhpd_opp_turbo: opp-384 { opp-level = ; }; - rpmhpd_opp_turbo_l1: opp10 { + rpmhpd_opp_turbo_l1: opp-416 { opp-level = ; }; }; diff --git a/arch/arm64/boot/dts/realtek/rtd1293.dtsi b/arch/arm64/boot/dts/realtek/rtd1293.dtsi index 2d92b56ac94d694a9a2af1f06549e1df54d399af..d0c9387ac17a6db8cf3da1056c444588e160346e 100644 --- a/arch/arm64/boot/dts/realtek/rtd1293.dtsi +++ b/arch/arm64/boot/dts/realtek/rtd1293.dtsi @@ -30,6 +30,8 @@ l2: l2-cache { compatible = "cache"; + cache-level = <2>; + cache-unified; }; }; diff --git a/arch/arm64/boot/dts/realtek/rtd1295.dtsi b/arch/arm64/boot/dts/realtek/rtd1295.dtsi index 1402abe80ea1b20f05d61e48d329f138310a4c85..b7f63102f2ddf5cab398c22cca713f2304fa429f 100644 --- a/arch/arm64/boot/dts/realtek/rtd1295.dtsi +++ b/arch/arm64/boot/dts/realtek/rtd1295.dtsi @@ -44,6 +44,8 @@ l2: l2-cache { compatible = "cache"; + cache-level = <2>; + cache-unified; }; }; diff --git a/arch/arm64/boot/dts/realtek/rtd1296.dtsi b/arch/arm64/boot/dts/realtek/rtd1296.dtsi index fb864a139c97efc3286fc299d3d4a77ede6232e1..4f805f576cef5d058de76fb61ee1775dba8c0f47 100644 --- a/arch/arm64/boot/dts/realtek/rtd1296.dtsi +++ b/arch/arm64/boot/dts/realtek/rtd1296.dtsi @@ -44,6 +44,8 @@ l2: l2-cache { compatible = "cache"; + cache-level = <2>; + cache-unified; }; }; diff --git a/arch/arm64/boot/dts/realtek/rtd1395.dtsi b/arch/arm64/boot/dts/realtek/rtd1395.dtsi index 05c9216a87eef6825ca9b1995d0b820bc792c95d..2efe5b25c83c61a1c528bc1c1ae0493e7572ecc7 100644 --- a/arch/arm64/boot/dts/realtek/rtd1395.dtsi +++ b/arch/arm64/boot/dts/realtek/rtd1395.dtsi @@ -44,6 +44,8 @@ l2: l2-cache { compatible = "cache"; + cache-level = <2>; + cache-unified; }; }; diff --git a/arch/arm64/boot/dts/realtek/rtd16xx.dtsi b/arch/arm64/boot/dts/realtek/rtd16xx.dtsi index bf4d9e91792587037fdcca4d0908d90422ee3dc4..34802cc62983868bfdb68dbe1e0a9f4cda700935 100644 --- a/arch/arm64/boot/dts/realtek/rtd16xx.dtsi +++ b/arch/arm64/boot/dts/realtek/rtd16xx.dtsi @@ -88,11 +88,15 @@ l2: l2-cache { compatible = "cache"; next-level-cache = <&l3>; + cache-level = <2>; + cache-unified; }; l3: l3-cache { compatible = "cache"; + cache-level = <3>; + cache-unified; }; }; diff --git a/arch/arm64/boot/dts/renesas/Makefile b/arch/arm64/boot/dts/renesas/Makefile index f130165577a83cee9a3aec5db56798d05124c5b8..7114cbbd8713011f2a31ad68ab143c25e6bd2b5c 100644 --- a/arch/arm64/boot/dts/renesas/Makefile +++ b/arch/arm64/boot/dts/renesas/Makefile @@ -79,10 +79,12 @@ dtb-$(CONFIG_ARCH_R9A07G043) += r9a07g043u11-smarc.dtb dtb-$(CONFIG_ARCH_R9A07G043) += r9a07g043-smarc-pmod.dtbo dtb-$(CONFIG_ARCH_R9A07G044) += r9a07g044c2-smarc.dtb +dtb-$(CONFIG_ARCH_R9A07G044) += r9a07g044c2-smarc-cru-csi-ov5645.dtbo dtb-$(CONFIG_ARCH_R9A07G044) += r9a07g044l2-smarc.dtb dtb-$(CONFIG_ARCH_R9A07G044) += r9a07g044l2-smarc-cru-csi-ov5645.dtbo dtb-$(CONFIG_ARCH_R9A07G054) += r9a07g054l2-smarc.dtb +dtb-$(CONFIG_ARCH_R9A07G054) += r9a07g054l2-smarc-cru-csi-ov5645.dtbo dtb-$(CONFIG_ARCH_R9A09G011) += r9a09g011-v2mevk2.dtb diff --git a/arch/arm64/boot/dts/renesas/r8a774a1.dtsi b/arch/arm64/boot/dts/renesas/r8a774a1.dtsi index c21b78685123460b790a0395e8475cceea526605..9065dc243428f128bc65c4b4ce3d6f8d976d9973 100644 --- a/arch/arm64/boot/dts/renesas/r8a774a1.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a774a1.dtsi @@ -2359,8 +2359,8 @@ <0x02000000 0 0xfe200000 0 0xfe200000 0 0x00200000>, <0x02000000 0 0x30000000 0 0x30000000 0 0x08000000>, <0x42000000 0 0x38000000 0 0x38000000 0 0x08000000>; - /* Map all possible DDR as inbound ranges */ - dma-ranges = <0x42000000 0 0x40000000 0 0x40000000 0 0x80000000>; + /* Map all possible DDR/IOMMU as inbound ranges */ + dma-ranges = <0x42000000 0 0x00000000 0 0x00000000 1 0x00000000>; interrupts = , , ; @@ -2371,6 +2371,8 @@ clock-names = "pcie", "pcie_bus"; power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>; resets = <&cpg 319>; + iommu-map = <0 &ipmmu_hc 0 1>; + iommu-map-mask = <0>; status = "disabled"; }; @@ -2386,8 +2388,8 @@ <0x02000000 0 0xeea00000 0 0xeea00000 0 0x00200000>, <0x02000000 0 0xc0000000 0 0xc0000000 0 0x08000000>, <0x42000000 0 0xc8000000 0 0xc8000000 0 0x08000000>; - /* Map all possible DDR as inbound ranges */ - dma-ranges = <0x42000000 0 0x40000000 0 0x40000000 0 0x80000000>; + /* Map all possible DDR/IOMMU as inbound ranges */ + dma-ranges = <0x42000000 0 0x00000000 0 0x00000000 1 0x00000000>; interrupts = , , ; @@ -2398,6 +2400,8 @@ clock-names = "pcie", "pcie_bus"; power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>; resets = <&cpg 318>; + iommu-map = <0 &ipmmu_hc 1 1>; + iommu-map-mask = <0>; status = "disabled"; }; diff --git a/arch/arm64/boot/dts/renesas/r8a774b1.dtsi b/arch/arm64/boot/dts/renesas/r8a774b1.dtsi index 82216ce7a92a908907ba2448252eb285c788a480..75776decd2186f7dd586328dbba4cf44a5f538a7 100644 --- a/arch/arm64/boot/dts/renesas/r8a774b1.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a774b1.dtsi @@ -2238,8 +2238,8 @@ <0x02000000 0 0xfe200000 0 0xfe200000 0 0x00200000>, <0x02000000 0 0x30000000 0 0x30000000 0 0x08000000>, <0x42000000 0 0x38000000 0 0x38000000 0 0x08000000>; - /* Map all possible DDR as inbound ranges */ - dma-ranges = <0x42000000 0 0x40000000 0 0x40000000 0 0x80000000>; + /* Map all possible DDR/IOMMU as inbound ranges */ + dma-ranges = <0x42000000 0 0x00000000 0 0x00000000 1 0x00000000>; interrupts = , , ; @@ -2250,6 +2250,8 @@ clock-names = "pcie", "pcie_bus"; power-domains = <&sysc R8A774B1_PD_ALWAYS_ON>; resets = <&cpg 319>; + iommu-map = <0 &ipmmu_hc 0 1>; + iommu-map-mask = <0>; status = "disabled"; }; @@ -2265,8 +2267,8 @@ <0x02000000 0 0xeea00000 0 0xeea00000 0 0x00200000>, <0x02000000 0 0xc0000000 0 0xc0000000 0 0x08000000>, <0x42000000 0 0xc8000000 0 0xc8000000 0 0x08000000>; - /* Map all possible DDR as inbound ranges */ - dma-ranges = <0x42000000 0 0x40000000 0 0x40000000 0 0x80000000>; + /* Map all possible DDR/IOMMU as inbound ranges */ + dma-ranges = <0x42000000 0 0x00000000 0 0x00000000 1 0x00000000>; interrupts = , , ; @@ -2277,6 +2279,8 @@ clock-names = "pcie", "pcie_bus"; power-domains = <&sysc R8A774B1_PD_ALWAYS_ON>; resets = <&cpg 318>; + iommu-map = <0 &ipmmu_hc 1 1>; + iommu-map-mask = <0>; status = "disabled"; }; diff --git a/arch/arm64/boot/dts/renesas/r8a774c0.dtsi b/arch/arm64/boot/dts/renesas/r8a774c0.dtsi index 10abfde329d00b4171f8ef22e29a46017b57a762..ad2e87b039acd7ac07b4c544c00f1d8b9993f677 100644 --- a/arch/arm64/boot/dts/renesas/r8a774c0.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a774c0.dtsi @@ -1704,8 +1704,8 @@ <0x02000000 0 0xfe200000 0 0xfe200000 0 0x00200000>, <0x02000000 0 0x30000000 0 0x30000000 0 0x08000000>, <0x42000000 0 0x38000000 0 0x38000000 0 0x08000000>; - /* Map all possible DDR as inbound ranges */ - dma-ranges = <0x42000000 0 0x40000000 0 0x40000000 0 0x40000000>; + /* Map all possible DDR/IOMMU as inbound ranges */ + dma-ranges = <0x42000000 0 0x00000000 0 0x00000000 1 0x00000000>; interrupts = , , ; @@ -1716,6 +1716,8 @@ clock-names = "pcie", "pcie_bus"; power-domains = <&sysc R8A774C0_PD_ALWAYS_ON>; resets = <&cpg 319>; + iommu-map = <0 &ipmmu_hc 0 1>; + iommu-map-mask = <0>; status = "disabled"; }; diff --git a/arch/arm64/boot/dts/renesas/r8a774e1.dtsi b/arch/arm64/boot/dts/renesas/r8a774e1.dtsi index 2828e05b40b34ea6614003ecc5151e2730210500..2acf4067ab2f23e2b6624d7d39742ee92cecb1be 100644 --- a/arch/arm64/boot/dts/renesas/r8a774e1.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a774e1.dtsi @@ -2471,8 +2471,8 @@ <0x02000000 0 0xfe200000 0 0xfe200000 0 0x00200000>, <0x02000000 0 0x30000000 0 0x30000000 0 0x08000000>, <0x42000000 0 0x38000000 0 0x38000000 0 0x08000000>; - /* Map all possible DDR as inbound ranges */ - dma-ranges = <0x42000000 0 0x40000000 0 0x40000000 0 0x80000000>; + /* Map all possible DDR/IOMMU as inbound ranges */ + dma-ranges = <0x42000000 0 0x00000000 0 0x00000000 1 0x00000000>; interrupts = , , ; @@ -2483,6 +2483,8 @@ clock-names = "pcie", "pcie_bus"; power-domains = <&sysc R8A774E1_PD_ALWAYS_ON>; resets = <&cpg 319>; + iommu-map = <0 &ipmmu_hc 0 1>; + iommu-map-mask = <0>; status = "disabled"; }; @@ -2498,8 +2500,8 @@ <0x02000000 0 0xeea00000 0 0xeea00000 0 0x00200000>, <0x02000000 0 0xc0000000 0 0xc0000000 0 0x08000000>, <0x42000000 0 0xc8000000 0 0xc8000000 0 0x08000000>; - /* Map all possible DDR as inbound ranges */ - dma-ranges = <0x42000000 0 0x40000000 0 0x40000000 0 0x80000000>; + /* Map all possible DDR/IOMMU as inbound ranges */ + dma-ranges = <0x42000000 0 0x00000000 0 0x00000000 1 0x00000000>; interrupts = , , ; @@ -2510,6 +2512,8 @@ clock-names = "pcie", "pcie_bus"; power-domains = <&sysc R8A774E1_PD_ALWAYS_ON>; resets = <&cpg 318>; + iommu-map = <0 &ipmmu_hc 1 1>; + iommu-map-mask = <0>; status = "disabled"; }; diff --git a/arch/arm64/boot/dts/renesas/r8a77951.dtsi b/arch/arm64/boot/dts/renesas/r8a77951.dtsi index 10b91e9733bf6fa174aefc0024f4ff56a17a8ac9..6d15229d25ab101d32436950ecda3f589d7f953b 100644 --- a/arch/arm64/boot/dts/renesas/r8a77951.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a77951.dtsi @@ -2778,8 +2778,8 @@ <0x02000000 0 0xfe200000 0 0xfe200000 0 0x00200000>, <0x02000000 0 0x30000000 0 0x30000000 0 0x08000000>, <0x42000000 0 0x38000000 0 0x38000000 0 0x08000000>; - /* Map all possible DDR as inbound ranges */ - dma-ranges = <0x42000000 0 0x40000000 0 0x40000000 0 0x40000000>; + /* Map all possible DDR/IOMMU as inbound ranges */ + dma-ranges = <0x42000000 0 0x00000000 0 0x00000000 1 0x00000000>; interrupts = , , ; @@ -2790,6 +2790,8 @@ clock-names = "pcie", "pcie_bus"; power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; resets = <&cpg 319>; + iommu-map = <0 &ipmmu_hc 0 1>; + iommu-map-mask = <0>; status = "disabled"; }; @@ -2805,8 +2807,8 @@ <0x02000000 0 0xeea00000 0 0xeea00000 0 0x00200000>, <0x02000000 0 0xc0000000 0 0xc0000000 0 0x08000000>, <0x42000000 0 0xc8000000 0 0xc8000000 0 0x08000000>; - /* Map all possible DDR as inbound ranges */ - dma-ranges = <0x42000000 0 0x40000000 0 0x40000000 0 0x40000000>; + /* Map all possible DDR/IOMMU as inbound ranges */ + dma-ranges = <0x42000000 0 0x00000000 0 0x00000000 1 0x00000000>; interrupts = , , ; @@ -2817,6 +2819,8 @@ clock-names = "pcie", "pcie_bus"; power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; resets = <&cpg 318>; + iommu-map = <0 &ipmmu_hc 1 1>; + iommu-map-mask = <0>; status = "disabled"; }; diff --git a/arch/arm64/boot/dts/renesas/r8a77960.dtsi b/arch/arm64/boot/dts/renesas/r8a77960.dtsi index 3ea8572e917f82ddefcfd32e423d09768844ee2a..17062ec506beabd5a27a51b3958eda28577b09bf 100644 --- a/arch/arm64/boot/dts/renesas/r8a77960.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a77960.dtsi @@ -2565,8 +2565,8 @@ <0x02000000 0 0xfe200000 0 0xfe200000 0 0x00200000>, <0x02000000 0 0x30000000 0 0x30000000 0 0x08000000>, <0x42000000 0 0x38000000 0 0x38000000 0 0x08000000>; - /* Map all possible DDR as inbound ranges */ - dma-ranges = <0x42000000 0 0x40000000 0 0x40000000 0 0x80000000>; + /* Map all possible DDR/IOMMU as inbound ranges */ + dma-ranges = <0x42000000 0 0x00000000 0 0x00000000 1 0x00000000>; interrupts = , , ; @@ -2577,6 +2577,8 @@ clock-names = "pcie", "pcie_bus"; power-domains = <&sysc R8A7796_PD_ALWAYS_ON>; resets = <&cpg 319>; + iommu-map = <0 &ipmmu_hc 0 1>; + iommu-map-mask = <0>; status = "disabled"; }; @@ -2592,8 +2594,8 @@ <0x02000000 0 0xeea00000 0 0xeea00000 0 0x00200000>, <0x02000000 0 0xc0000000 0 0xc0000000 0 0x08000000>, <0x42000000 0 0xc8000000 0 0xc8000000 0 0x08000000>; - /* Map all possible DDR as inbound ranges */ - dma-ranges = <0x42000000 0 0x40000000 0 0x40000000 0 0x80000000>; + /* Map all possible DDR/IOMMU as inbound ranges */ + dma-ranges = <0x42000000 0 0x00000000 0 0x00000000 1 0x00000000>; interrupts = , , ; @@ -2604,6 +2606,8 @@ clock-names = "pcie", "pcie_bus"; power-domains = <&sysc R8A7796_PD_ALWAYS_ON>; resets = <&cpg 318>; + iommu-map = <0 &ipmmu_hc 1 1>; + iommu-map-mask = <0>; status = "disabled"; }; diff --git a/arch/arm64/boot/dts/renesas/r8a77961.dtsi b/arch/arm64/boot/dts/renesas/r8a77961.dtsi index d52cb0b67d80c6fbef33a278057e1f481114bcff..d3f47da1b62673f5835b73095b559656d7195994 100644 --- a/arch/arm64/boot/dts/renesas/r8a77961.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a77961.dtsi @@ -2445,8 +2445,8 @@ <0x02000000 0 0xfe200000 0 0xfe200000 0 0x00200000>, <0x02000000 0 0x30000000 0 0x30000000 0 0x08000000>, <0x42000000 0 0x38000000 0 0x38000000 0 0x08000000>; - /* Map all possible DDR as inbound ranges */ - dma-ranges = <0x42000000 0 0x40000000 0 0x40000000 0 0x80000000>; + /* Map all possible DDR/IOMMU as inbound ranges */ + dma-ranges = <0x42000000 0 0x00000000 0 0x00000000 1 0x00000000>; interrupts = , , ; @@ -2457,6 +2457,8 @@ clock-names = "pcie", "pcie_bus"; power-domains = <&sysc R8A77961_PD_ALWAYS_ON>; resets = <&cpg 319>; + iommu-map = <0 &ipmmu_hc 0 1>; + iommu-map-mask = <0>; status = "disabled"; }; @@ -2472,8 +2474,8 @@ <0x02000000 0 0xeea00000 0 0xeea00000 0 0x00200000>, <0x02000000 0 0xc0000000 0 0xc0000000 0 0x08000000>, <0x42000000 0 0xc8000000 0 0xc8000000 0 0x08000000>; - /* Map all possible DDR as inbound ranges */ - dma-ranges = <0x42000000 0 0x40000000 0 0x40000000 0 0x80000000>; + /* Map all possible DDR/IOMMU as inbound ranges */ + dma-ranges = <0x42000000 0 0x00000000 0 0x00000000 1 0x00000000>; interrupts = , , ; @@ -2484,6 +2486,8 @@ clock-names = "pcie", "pcie_bus"; power-domains = <&sysc R8A77961_PD_ALWAYS_ON>; resets = <&cpg 318>; + iommu-map = <0 &ipmmu_hc 1 1>; + iommu-map-mask = <0>; status = "disabled"; }; diff --git a/arch/arm64/boot/dts/renesas/r8a77965.dtsi b/arch/arm64/boot/dts/renesas/r8a77965.dtsi index 9584115c6b17769be09c9608ab4d4d75cb28cffa..c7582003849135cd0b981a150301e488ead6e864 100644 --- a/arch/arm64/boot/dts/renesas/r8a77965.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a77965.dtsi @@ -2423,8 +2423,8 @@ <0x02000000 0 0xfe200000 0 0xfe200000 0 0x00200000>, <0x02000000 0 0x30000000 0 0x30000000 0 0x08000000>, <0x42000000 0 0x38000000 0 0x38000000 0 0x08000000>; - /* Map all possible DDR as inbound ranges */ - dma-ranges = <0x42000000 0 0x40000000 0 0x40000000 0 0x80000000>; + /* Map all possible DDR/IOMMU as inbound ranges */ + dma-ranges = <0x42000000 0 0x00000000 0 0x00000000 1 0x00000000>; interrupts = , , ; @@ -2435,6 +2435,8 @@ clock-names = "pcie", "pcie_bus"; power-domains = <&sysc R8A77965_PD_ALWAYS_ON>; resets = <&cpg 319>; + iommu-map = <0 &ipmmu_hc 0 1>; + iommu-map-mask = <0>; status = "disabled"; }; @@ -2450,8 +2452,8 @@ <0x02000000 0 0xeea00000 0 0xeea00000 0 0x00200000>, <0x02000000 0 0xc0000000 0 0xc0000000 0 0x08000000>, <0x42000000 0 0xc8000000 0 0xc8000000 0 0x08000000>; - /* Map all possible DDR as inbound ranges */ - dma-ranges = <0x42000000 0 0x40000000 0 0x40000000 0 0x80000000>; + /* Map all possible DDR/IOMMU as inbound ranges */ + dma-ranges = <0x42000000 0 0x00000000 0 0x00000000 1 0x00000000>; interrupts = , , ; @@ -2462,6 +2464,8 @@ clock-names = "pcie", "pcie_bus"; power-domains = <&sysc R8A77965_PD_ALWAYS_ON>; resets = <&cpg 318>; + iommu-map = <0 &ipmmu_hc 1 1>; + iommu-map-mask = <0>; status = "disabled"; }; diff --git a/arch/arm64/boot/dts/renesas/r8a77980.dtsi b/arch/arm64/boot/dts/renesas/r8a77980.dtsi index c4ac28a0f7161d000714571af0cb6b44fa01ec21..5ed2daaca1f006493f037e7e84a782161d904219 100644 --- a/arch/arm64/boot/dts/renesas/r8a77980.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a77980.dtsi @@ -1386,7 +1386,8 @@ <0x02000000 0 0xfe200000 0 0xfe200000 0 0x0200000>, <0x02000000 0 0x30000000 0 0x30000000 0 0x8000000>, <0x42000000 0 0x38000000 0 0x38000000 0 0x8000000>; - dma-ranges = <0x42000000 0 0x40000000 0 0x40000000 0 0x80000000>; + /* Map all possible DDR/IOMMU as inbound ranges */ + dma-ranges = <0x42000000 0 0x00000000 0 0x00000000 1 0x00000000>; interrupts = , , ; @@ -1399,6 +1400,8 @@ resets = <&cpg 319>; phys = <&pcie_phy>; phy-names = "pcie"; + iommu-map = <0 &ipmmu_vi0 5 1>; + iommu-map-mask = <0>; status = "disabled"; }; diff --git a/arch/arm64/boot/dts/renesas/r8a77990.dtsi b/arch/arm64/boot/dts/renesas/r8a77990.dtsi index 4529e9b57c3312f78f75cf07523a69743826f18b..1be0b99c15ed6680a7a3de0aa2c0e37c332894a3 100644 --- a/arch/arm64/boot/dts/renesas/r8a77990.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a77990.dtsi @@ -1870,8 +1870,8 @@ <0x02000000 0 0xfe200000 0 0xfe200000 0 0x00200000>, <0x02000000 0 0x30000000 0 0x30000000 0 0x08000000>, <0x42000000 0 0x38000000 0 0x38000000 0 0x08000000>; - /* Map all possible DDR as inbound ranges */ - dma-ranges = <0x42000000 0 0x40000000 0 0x40000000 0 0x40000000>; + /* Map all possible DDR/IOMMU as inbound ranges */ + dma-ranges = <0x42000000 0 0x00000000 0 0x00000000 1 0x00000000>; interrupts = , , ; @@ -1882,6 +1882,8 @@ clock-names = "pcie", "pcie_bus"; power-domains = <&sysc R8A77990_PD_ALWAYS_ON>; resets = <&cpg 319>; + iommu-map = <0 &ipmmu_hc 0 1>; + iommu-map-mask = <0>; status = "disabled"; }; diff --git a/arch/arm64/boot/dts/renesas/r8a779a0.dtsi b/arch/arm64/boot/dts/renesas/r8a779a0.dtsi index bf587a14ec195c5c8d9526e2558a89bd6162f7ca..4e67a03564971b89a5b2fb7564b2eb93aa549819 100644 --- a/arch/arm64/boot/dts/renesas/r8a779a0.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a779a0.dtsi @@ -943,6 +943,56 @@ status = "disabled"; }; + pwm0: pwm@e6e30000 { + compatible = "renesas,pwm-r8a779a0", "renesas,pwm-rcar"; + reg = <0 0xe6e30000 0 0x10>; + #pwm-cells = <2>; + clocks = <&cpg CPG_MOD 628>; + power-domains = <&sysc R8A779A0_PD_ALWAYS_ON>; + resets = <&cpg 628>; + status = "disabled"; + }; + + pwm1: pwm@e6e31000 { + compatible = "renesas,pwm-r8a779a0", "renesas,pwm-rcar"; + reg = <0 0xe6e31000 0 0x10>; + #pwm-cells = <2>; + clocks = <&cpg CPG_MOD 628>; + power-domains = <&sysc R8A779A0_PD_ALWAYS_ON>; + resets = <&cpg 628>; + status = "disabled"; + }; + + pwm2: pwm@e6e32000 { + compatible = "renesas,pwm-r8a779a0", "renesas,pwm-rcar"; + reg = <0 0xe6e32000 0 0x10>; + #pwm-cells = <2>; + clocks = <&cpg CPG_MOD 628>; + power-domains = <&sysc R8A779A0_PD_ALWAYS_ON>; + resets = <&cpg 628>; + status = "disabled"; + }; + + pwm3: pwm@e6e33000 { + compatible = "renesas,pwm-r8a779a0", "renesas,pwm-rcar"; + reg = <0 0xe6e33000 0 0x10>; + #pwm-cells = <2>; + clocks = <&cpg CPG_MOD 628>; + power-domains = <&sysc R8A779A0_PD_ALWAYS_ON>; + resets = <&cpg 628>; + status = "disabled"; + }; + + pwm4: pwm@e6e34000 { + compatible = "renesas,pwm-r8a779a0", "renesas,pwm-rcar"; + reg = <0 0xe6e34000 0 0x10>; + #pwm-cells = <2>; + clocks = <&cpg CPG_MOD 628>; + power-domains = <&sysc R8A779A0_PD_ALWAYS_ON>; + resets = <&cpg 628>; + status = "disabled"; + }; + scif0: serial@e6e60000 { compatible = "renesas,scif-r8a779a0", "renesas,rcar-gen4-scif", "renesas,scif"; diff --git a/arch/arm64/boot/dts/renesas/r9a07g044.dtsi b/arch/arm64/boot/dts/renesas/r9a07g044.dtsi index 1315be5167b95b6b0f3de19e77527357a79f6a6f..232910e07444eec399c520e52aacf8e76a2aa9d5 100644 --- a/arch/arm64/boot/dts/renesas/r9a07g044.dtsi +++ b/arch/arm64/boot/dts/renesas/r9a07g044.dtsi @@ -174,6 +174,76 @@ #size-cells = <2>; ranges; + mtu3: timer@10001200 { + compatible = "renesas,r9a07g044-mtu3", + "renesas,rz-mtu3"; + reg = <0 0x10001200 0 0xb00>; + interrupts = , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + ; + interrupt-names = "tgia0", "tgib0", "tgic0", "tgid0", + "tgiv0", "tgie0", "tgif0", + "tgia1", "tgib1", "tgiv1", "tgiu1", + "tgia2", "tgib2", "tgiv2", "tgiu2", + "tgia3", "tgib3", "tgic3", "tgid3", + "tgiv3", + "tgia4", "tgib4", "tgic4", "tgid4", + "tgiv4", + "tgiu5", "tgiv5", "tgiw5", + "tgia6", "tgib6", "tgic6", "tgid6", + "tgiv6", + "tgia7", "tgib7", "tgic7", "tgid7", + "tgiv7", + "tgia8", "tgib8", "tgic8", "tgid8", + "tgiv8", "tgiu8"; + clocks = <&cpg CPG_MOD R9A07G044_MTU_X_MCK_MTU3>; + power-domains = <&cpg>; + resets = <&cpg R9A07G044_MTU_X_PRESET_MTU3>; + #pwm-cells = <2>; + status = "disabled"; + }; + ssi0: ssi@10049c00 { compatible = "renesas,r9a07g044-ssi", "renesas,rz-ssi"; @@ -697,6 +767,59 @@ }; }; + dsi: dsi@10850000 { + compatible = "renesas,r9a07g044-mipi-dsi", + "renesas,rzg2l-mipi-dsi"; + reg = <0 0x10850000 0 0x20000>; + interrupts = , + , + , + , + , + , + ; + interrupt-names = "seq0", "seq1", "vin1", "rcv", + "ferr", "ppi", "debug"; + clocks = <&cpg CPG_MOD R9A07G044_MIPI_DSI_PLLCLK>, + <&cpg CPG_MOD R9A07G044_MIPI_DSI_SYSCLK>, + <&cpg CPG_MOD R9A07G044_MIPI_DSI_ACLK>, + <&cpg CPG_MOD R9A07G044_MIPI_DSI_PCLK>, + <&cpg CPG_MOD R9A07G044_MIPI_DSI_VCLK>, + <&cpg CPG_MOD R9A07G044_MIPI_DSI_LPCLK>; + clock-names = "pllclk", "sysclk", "aclk", "pclk", "vclk", "lpclk"; + resets = <&cpg R9A07G044_MIPI_DSI_CMN_RSTB>, + <&cpg R9A07G044_MIPI_DSI_ARESET_N>, + <&cpg R9A07G044_MIPI_DSI_PRESET_N>; + reset-names = "rst", "arst", "prst"; + power-domains = <&cpg>; + status = "disabled"; + }; + + vspd: vsp@10870000 { + compatible = "renesas,r9a07g044-vsp2"; + reg = <0 0x10870000 0 0x10000>; + interrupts = ; + clocks = <&cpg CPG_MOD R9A07G044_LCDC_CLK_A>, + <&cpg CPG_MOD R9A07G044_LCDC_CLK_P>, + <&cpg CPG_MOD R9A07G044_LCDC_CLK_D>; + clock-names = "aclk", "pclk", "vclk"; + power-domains = <&cpg>; + resets = <&cpg R9A07G044_LCDC_RESET_N>; + renesas,fcp = <&fcpvd>; + }; + + fcpvd: fcp@10880000 { + compatible = "renesas,r9a07g044-fcpvd", + "renesas,fcpv"; + reg = <0 0x10880000 0 0x10000>; + clocks = <&cpg CPG_MOD R9A07G044_LCDC_CLK_A>, + <&cpg CPG_MOD R9A07G044_LCDC_CLK_P>, + <&cpg CPG_MOD R9A07G044_LCDC_CLK_D>; + clock-names = "aclk", "pclk", "vclk"; + power-domains = <&cpg>; + resets = <&cpg R9A07G044_LCDC_RESET_N>; + }; + cpg: clock-controller@11010000 { compatible = "renesas,r9a07g044-cpg"; reg = <0 0x11010000 0 0x10000>; diff --git a/arch/arm64/boot/dts/renesas/r9a07g044c2-smarc-cru-csi-ov5645.dtso b/arch/arm64/boot/dts/renesas/r9a07g044c2-smarc-cru-csi-ov5645.dtso new file mode 100644 index 0000000000000000000000000000000000000000..f983bdd3ea307ce921740dccc913eb2ba2f8e88e --- /dev/null +++ b/arch/arm64/boot/dts/renesas/r9a07g044c2-smarc-cru-csi-ov5645.dtso @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Device Tree overlay for the RZ/G2LC SMARC EVK with + * OV5645 camera connected to CSI and CRU enabled. + * + * Copyright (C) 2023 Renesas Electronics Corp. + */ + +/dts-v1/; +/plugin/; + +#include +#include + +#define OV5645_PARENT_I2C i2c0 +#include "rz-smarc-cru-csi-ov5645.dtsi" + +&ov5645 { + enable-gpios = <&pinctrl RZG2L_GPIO(0, 1) GPIO_ACTIVE_HIGH>; + reset-gpios = <&pinctrl RZG2L_GPIO(5, 2) GPIO_ACTIVE_LOW>; +}; diff --git a/arch/arm64/boot/dts/renesas/r9a07g044l2-smarc-cru-csi-ov5645.dtso b/arch/arm64/boot/dts/renesas/r9a07g044l2-smarc-cru-csi-ov5645.dtso index d834bff9bda2cc6d8c79fcb94019ac5e90b3392a..736c1e688cc8b8922ca277a0275ccce71064bb97 100644 --- a/arch/arm64/boot/dts/renesas/r9a07g044l2-smarc-cru-csi-ov5645.dtso +++ b/arch/arm64/boot/dts/renesas/r9a07g044l2-smarc-cru-csi-ov5645.dtso @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Device Tree overlay for the RZ/G2L SMARC EVK with OV5645 camera + * Device Tree overlay for the RZ/{G2L, V2L} SMARC EVK with OV5645 camera * connected to CSI and CRU enabled. * * Copyright (C) 2023 Renesas Electronics Corp. diff --git a/arch/arm64/boot/dts/renesas/r9a07g054.dtsi b/arch/arm64/boot/dts/renesas/r9a07g054.dtsi index cc11e5855d62c5cf30f7f72ef606617e7e1f3907..2eba3a8a100d0e268c9c73bc4994e4f9435a4c14 100644 --- a/arch/arm64/boot/dts/renesas/r9a07g054.dtsi +++ b/arch/arm64/boot/dts/renesas/r9a07g054.dtsi @@ -174,6 +174,76 @@ #size-cells = <2>; ranges; + mtu3: timer@10001200 { + compatible = "renesas,r9a07g054-mtu3", + "renesas,rz-mtu3"; + reg = <0 0x10001200 0 0xb00>; + interrupts = , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + ; + interrupt-names = "tgia0", "tgib0", "tgic0", "tgid0", + "tgiv0", "tgie0", "tgif0", + "tgia1", "tgib1", "tgiv1", "tgiu1", + "tgia2", "tgib2", "tgiv2", "tgiu2", + "tgia3", "tgib3", "tgic3", "tgid3", + "tgiv3", + "tgia4", "tgib4", "tgic4", "tgid4", + "tgiv4", + "tgiu5", "tgiv5", "tgiw5", + "tgia6", "tgib6", "tgic6", "tgid6", + "tgiv6", + "tgia7", "tgib7", "tgic7", "tgid7", + "tgiv7", + "tgia8", "tgib8", "tgic8", "tgid8", + "tgiv8", "tgiu8"; + clocks = <&cpg CPG_MOD R9A07G054_MTU_X_MCK_MTU3>; + power-domains = <&cpg>; + resets = <&cpg R9A07G054_MTU_X_PRESET_MTU3>; + #pwm-cells = <2>; + status = "disabled"; + }; + ssi0: ssi@10049c00 { compatible = "renesas,r9a07g054-ssi", "renesas,rz-ssi"; @@ -623,6 +693,139 @@ status = "disabled"; }; + cru: video@10830000 { + compatible = "renesas,r9a07g054-cru", "renesas,rzg2l-cru"; + reg = <0 0x10830000 0 0x400>; + clocks = <&cpg CPG_MOD R9A07G054_CRU_VCLK>, + <&cpg CPG_MOD R9A07G054_CRU_PCLK>, + <&cpg CPG_MOD R9A07G054_CRU_ACLK>; + clock-names = "video", "apb", "axi"; + interrupts = , + , + ; + interrupt-names = "image_conv", "image_conv_err", "axi_mst_err"; + resets = <&cpg R9A07G054_CRU_PRESETN>, + <&cpg R9A07G054_CRU_ARESETN>; + reset-names = "presetn", "aresetn"; + power-domains = <&cpg>; + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + #address-cells = <1>; + #size-cells = <0>; + + reg = <0>; + cruparallel: endpoint@0 { + reg = <0>; + }; + }; + + port@1 { + #address-cells = <1>; + #size-cells = <0>; + + reg = <1>; + crucsi2: endpoint@0 { + reg = <0>; + remote-endpoint = <&csi2cru>; + }; + }; + }; + }; + + csi2: csi2@10830400 { + compatible = "renesas,r9a07g054-csi2", "renesas,rzg2l-csi2"; + reg = <0 0x10830400 0 0xfc00>; + interrupts = ; + clocks = <&cpg CPG_MOD R9A07G054_CRU_SYSCLK>, + <&cpg CPG_MOD R9A07G054_CRU_VCLK>, + <&cpg CPG_MOD R9A07G054_CRU_PCLK>; + clock-names = "system", "video", "apb"; + resets = <&cpg R9A07G054_CRU_PRESETN>, + <&cpg R9A07G054_CRU_CMN_RSTB>; + reset-names = "presetn", "cmn-rstb"; + power-domains = <&cpg>; + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + }; + + port@1 { + #address-cells = <1>; + #size-cells = <0>; + reg = <1>; + + csi2cru: endpoint@0 { + reg = <0>; + remote-endpoint = <&crucsi2>; + }; + }; + }; + }; + + dsi: dsi@10850000 { + compatible = "renesas,r9a07g054-mipi-dsi", + "renesas,rzg2l-mipi-dsi"; + reg = <0 0x10850000 0 0x20000>; + interrupts = , + , + , + , + , + , + ; + interrupt-names = "seq0", "seq1", "vin1", "rcv", + "ferr", "ppi", "debug"; + clocks = <&cpg CPG_MOD R9A07G054_MIPI_DSI_PLLCLK>, + <&cpg CPG_MOD R9A07G054_MIPI_DSI_SYSCLK>, + <&cpg CPG_MOD R9A07G054_MIPI_DSI_ACLK>, + <&cpg CPG_MOD R9A07G054_MIPI_DSI_PCLK>, + <&cpg CPG_MOD R9A07G054_MIPI_DSI_VCLK>, + <&cpg CPG_MOD R9A07G054_MIPI_DSI_LPCLK>; + clock-names = "pllclk", "sysclk", "aclk", "pclk", "vclk", "lpclk"; + resets = <&cpg R9A07G054_MIPI_DSI_CMN_RSTB>, + <&cpg R9A07G054_MIPI_DSI_ARESET_N>, + <&cpg R9A07G054_MIPI_DSI_PRESET_N>; + reset-names = "rst", "arst", "prst"; + power-domains = <&cpg>; + status = "disabled"; + }; + + vspd: vsp@10870000 { + compatible = "renesas,r9a07g054-vsp2", + "renesas,r9a07g044-vsp2"; + reg = <0 0x10870000 0 0x10000>; + interrupts = ; + clocks = <&cpg CPG_MOD R9A07G054_LCDC_CLK_A>, + <&cpg CPG_MOD R9A07G054_LCDC_CLK_P>, + <&cpg CPG_MOD R9A07G054_LCDC_CLK_D>; + clock-names = "aclk", "pclk", "vclk"; + power-domains = <&cpg>; + resets = <&cpg R9A07G054_LCDC_RESET_N>; + renesas,fcp = <&fcpvd>; + }; + + fcpvd: fcp@10880000 { + compatible = "renesas,r9a07g054-fcpvd", + "renesas,fcpv"; + reg = <0 0x10880000 0 0x10000>; + clocks = <&cpg CPG_MOD R9A07G054_LCDC_CLK_A>, + <&cpg CPG_MOD R9A07G054_LCDC_CLK_P>, + <&cpg CPG_MOD R9A07G054_LCDC_CLK_D>; + clock-names = "aclk", "pclk", "vclk"; + power-domains = <&cpg>; + resets = <&cpg R9A07G054_LCDC_RESET_N>; + }; + cpg: clock-controller@11010000 { compatible = "renesas,r9a07g054-cpg"; reg = <0 0x11010000 0 0x10000>; diff --git a/arch/arm64/boot/dts/renesas/r9a07g054l2-smarc-cru-csi-ov5645.dtso b/arch/arm64/boot/dts/renesas/r9a07g054l2-smarc-cru-csi-ov5645.dtso new file mode 120000 index 0000000000000000000000000000000000000000..0f175341d3ed3d515b656aa58a9c28fdbbfb001c --- /dev/null +++ b/arch/arm64/boot/dts/renesas/r9a07g054l2-smarc-cru-csi-ov5645.dtso @@ -0,0 +1 @@ +r9a07g044l2-smarc-cru-csi-ov5645.dtso \ No newline at end of file diff --git a/arch/arm64/boot/dts/renesas/rzg2l-smarc.dtsi b/arch/arm64/boot/dts/renesas/rzg2l-smarc.dtsi index e180a955b6ac8c20543e7577dcbaabee38472927..2a158a954b2fc7b0bc248c77be410d0e2f0405a0 100644 --- a/arch/arm64/boot/dts/renesas/rzg2l-smarc.dtsi +++ b/arch/arm64/boot/dts/renesas/rzg2l-smarc.dtsi @@ -16,12 +16,91 @@ serial1 = &scif2; i2c3 = &i2c3; }; + + osc1: cec-clock { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <12000000>; + }; + + hdmi-out { + compatible = "hdmi-connector"; + type = "d"; + + port { + hdmi_con_out: endpoint { + remote-endpoint = <&adv7535_out>; + }; + }; + }; }; &cpu_dai { sound-dai = <&ssi0>; }; +&dsi { + status = "okay"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + dsi0_in: endpoint { + }; + }; + + port@1 { + reg = <1>; + dsi0_out: endpoint { + data-lanes = <1 2 3 4>; + remote-endpoint = <&adv7535_in>; + }; + }; + }; +}; + +&i2c1 { + adv7535: hdmi@3d { + compatible = "adi,adv7535"; + reg = <0x3d>; + + interrupt-parent = <&pinctrl>; + interrupts = ; + clocks = <&osc1>; + clock-names = "cec"; + avdd-supply = <®_1p8v>; + dvdd-supply = <®_1p8v>; + pvdd-supply = <®_1p8v>; + a2vdd-supply = <®_1p8v>; + v3p3-supply = <®_3p3v>; + v1p2-supply = <®_1p8v>; + + adi,dsi-lanes = <4>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + adv7535_in: endpoint { + remote-endpoint = <&dsi0_out>; + }; + }; + + port@1 { + reg = <1>; + adv7535_out: endpoint { + remote-endpoint = <&hdmi_con_out>; + }; + }; + }; + }; +}; + &i2c3 { pinctrl-0 = <&i2c3_pins>; pinctrl-names = "default"; diff --git a/arch/arm64/boot/dts/renesas/rzg2lc-smarc.dtsi b/arch/arm64/boot/dts/renesas/rzg2lc-smarc.dtsi index b6bd27196d888a95a842aade7cfdb94d229b8cb7..6818fd49b2bed8a154349d9a20ab9bfd7dd1d7d1 100644 --- a/arch/arm64/boot/dts/renesas/rzg2lc-smarc.dtsi +++ b/arch/arm64/boot/dts/renesas/rzg2lc-smarc.dtsi @@ -17,6 +17,23 @@ serial1 = &scif1; i2c2 = &i2c2; }; + + osc1: cec-clock { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <12000000>; + }; + + hdmi-out { + compatible = "hdmi-connector"; + type = "d"; + + port { + hdmi_con_out: endpoint { + remote-endpoint = <&adv7535_out>; + }; + }; + }; }; #if (SW_SCIF_CAN || SW_RSPI_CAN) @@ -36,6 +53,68 @@ sound-dai = <&ssi0>; }; +&dsi { + status = "okay"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + dsi0_in: endpoint { + }; + }; + + port@1 { + reg = <1>; + dsi0_out: endpoint { + data-lanes = <1 2 3 4>; + remote-endpoint = <&adv7535_in>; + }; + }; + }; +}; + +&i2c1 { + adv7535: hdmi@3d { + compatible = "adi,adv7535"; + reg = <0x3d>; + + interrupt-parent = <&pinctrl>; + interrupts = ; + clocks = <&osc1>; + clock-names = "cec"; + avdd-supply = <®_1p8v>; + dvdd-supply = <®_1p8v>; + pvdd-supply = <®_1p8v>; + a2vdd-supply = <®_1p8v>; + v3p3-supply = <®_3p3v>; + v1p2-supply = <®_1p8v>; + + adi,dsi-lanes = <4>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + adv7535_in: endpoint { + remote-endpoint = <&dsi0_out>; + }; + }; + + port@1 { + reg = <1>; + adv7535_out: endpoint { + remote-endpoint = <&hdmi_con_out>; + }; + }; + }; + }; +}; + &i2c2 { pinctrl-0 = <&i2c2_pins>; pinctrl-names = "default"; diff --git a/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi b/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi index efc80960380f4ca523f9a6265b7a1516394ad0f7..3885ef3454ff6e92d8f0d00509d0f935e7e40fa6 100644 --- a/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi +++ b/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi @@ -10,6 +10,7 @@ aliases { serial1 = &hscif0; serial2 = &scif1; + serial3 = &hscif1; mmc2 = &sdhi3; }; @@ -114,6 +115,14 @@ status = "okay"; }; +&hscif1 { + pinctrl-0 = <&hscif1_pins>; + pinctrl-names = "default"; + uart-has-rtscts; + + status = "okay"; +}; + &hsusb { dr_mode = "otg"; status = "okay"; @@ -366,8 +375,13 @@ function = "hscif0"; }; + hscif1_pins: hscif1 { + groups = "hscif1_data_a", "hscif1_ctrl_a"; + function = "hscif1"; + }; + scif1_pins: scif1 { - groups = "scif1_data_b", "scif1_ctrl"; + groups = "scif1_data_b"; function = "scif1"; }; @@ -397,7 +411,6 @@ &scif1 { pinctrl-0 = <&scif1_pins>; pinctrl-names = "default"; - uart-has-rtscts; status = "okay"; }; diff --git a/arch/arm64/boot/dts/rockchip/Makefile b/arch/arm64/boot/dts/rockchip/Makefile index 2d585bbb8f3a749e6b0056a361a88197ae592a45..b7fb908eb92dbdf8a3fdc3c532c602995d93fcc5 100644 --- a/arch/arm64/boot/dts/rockchip/Makefile +++ b/arch/arm64/boot/dts/rockchip/Makefile @@ -15,6 +15,7 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3326-odroid-go3.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-a1.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-evb.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-nanopi-r2c.dtb +dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-nanopi-r2c-plus.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-nanopi-r2s.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-orangepi-r1-plus.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-orangepi-r1-plus-lts.dtb @@ -69,6 +70,7 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-sapphire.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-sapphire-excavator.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399pro-rock-pi-n10.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-anbernic-rg353p.dtb +dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-anbernic-rg353ps.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-anbernic-rg353v.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-anbernic-rg353vs.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-anbernic-rg503.dtb @@ -85,6 +87,8 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-box-demo.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-lubancat-1.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-bpi-r2-pro.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-evb1-v10.dtb +dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-fastrhino-r66s.dtb +dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-fastrhino-r68s.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-lubancat-2.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-nanopi-r5c.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-nanopi-r5s.dtb @@ -92,7 +96,9 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-odroid-m1.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-radxa-e25.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-rock-3a.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-edgeble-neu6a-io.dtb +dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-edgeble-neu6b-io.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-evb1-v10.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-rock-5b.dtb +dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588s-indiedroid-nova.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588s-khadas-edge2.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588s-rock-5a.dtb diff --git a/arch/arm64/boot/dts/rockchip/rk3308.dtsi b/arch/arm64/boot/dts/rockchip/rk3308.dtsi index dd228a256a32a80230955f7ccc356b6755bc8140..2ae4bb7d5e62a3bb83edf2b3929cc88f880c5902 100644 --- a/arch/arm64/boot/dts/rockchip/rk3308.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3308.dtsi @@ -97,6 +97,7 @@ l2: l2-cache { compatible = "cache"; cache-level = <2>; + cache-unified; }; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2c-plus.dts b/arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2c-plus.dts new file mode 100644 index 0000000000000000000000000000000000000000..16a1958e457277eb8794f71975a8e9ff87b9892b --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2c-plus.dts @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT +/* + * Copyright (c) 2021 FriendlyElec Computer Tech. Co., Ltd. + * (http://www.friendlyarm.com) + * + * Copyright (c) 2023 Tianling Shen + */ + +/dts-v1/; +#include "rk3328-nanopi-r2c.dts" + +/ { + model = "FriendlyElec NanoPi R2C Plus"; + compatible = "friendlyarm,nanopi-r2c-plus", "rockchip,rk3328"; + + aliases { + mmc1 = &emmc; + }; +}; + +&emmc { + bus-width = <8>; + cap-mmc-highspeed; + max-frequency = <150000000>; + mmc-ddr-1_8v; + mmc-hs200-1_8v; + non-removable; + pinctrl-names = "default"; + pinctrl-0 = <&emmc_clk &emmc_cmd &emmc_bus8>; + vmmc-supply = <&vcc_io_33>; + vqmmc-supply = <&vcc18_emmc>; + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts b/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts index f69a38f42d2d54e4e10092c63b16a5775d71f601..0a27fa5271f57684a930d4a0cd9ded6dd74d1eb2 100644 --- a/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts +++ b/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts @@ -37,7 +37,8 @@ vin-supply = <&vcc_io>; }; - vcc_host_5v: vcc-host-5v-regulator { + /* Common enable line for all of the rails mentioned in the labels */ + vcc_host_5v: vcc_host1_5v: vcc_otg_5v: vcc-host-5v-regulator { compatible = "regulator-fixed"; gpio = <&gpio0 RK_PA2 GPIO_ACTIVE_LOW>; pinctrl-names = "default"; @@ -48,17 +49,6 @@ vin-supply = <&vcc_sys>; }; - vcc_host1_5v: vcc_otg_5v: vcc-host1-5v-regulator { - compatible = "regulator-fixed"; - gpio = <&gpio0 RK_PA2 GPIO_ACTIVE_LOW>; - pinctrl-names = "default"; - pinctrl-0 = <&usb20_host_drv>; - regulator-name = "vcc_host1_5v"; - regulator-always-on; - regulator-boot-on; - vin-supply = <&vcc_sys>; - }; - vcc_sys: vcc-sys { compatible = "regulator-fixed"; regulator-name = "vcc_sys"; diff --git a/arch/arm64/boot/dts/rockchip/rk3328.dtsi b/arch/arm64/boot/dts/rockchip/rk3328.dtsi index 6d7a7bf72ac7eeb8992b823a22688a9fdde369c1..e729e7a22b23a6a2e93374665d6f1ce2d03e9596 100644 --- a/arch/arm64/boot/dts/rockchip/rk3328.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3328.dtsi @@ -103,6 +103,7 @@ l2: l2-cache0 { compatible = "cache"; cache-level = <2>; + cache-unified; }; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3399pro-rock-pi-n10.dts b/arch/arm64/boot/dts/rockchip/rk3399pro-rock-pi-n10.dts index 369de5dc0ebdf1766747aa79d092bd548c0c227a..c58fb7658d7a1909191d8d2e92e8f2192431fd12 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399pro-rock-pi-n10.dts +++ b/arch/arm64/boot/dts/rockchip/rk3399pro-rock-pi-n10.dts @@ -8,7 +8,7 @@ /dts-v1/; #include "rk3399.dtsi" #include "rk3399-opp.dtsi" -#include +#include #include "rk3399pro-vmarc-som.dtsi" / { diff --git a/arch/arm64/boot/dts/rockchip/rk3566-anbernic-rg353ps.dts b/arch/arm64/boot/dts/rockchip/rk3566-anbernic-rg353ps.dts new file mode 100644 index 0000000000000000000000000000000000000000..b211973e36c2176b1003fe12c74e376af90b70a8 --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rk3566-anbernic-rg353ps.dts @@ -0,0 +1,116 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) + +/dts-v1/; + +#include +#include +#include +#include "rk3566-anbernic-rg353x.dtsi" + +/ { + model = "RG353PS"; + compatible = "anbernic,rg353ps", "rockchip,rk3566"; + + aliases { + mmc0 = &sdmmc0; + mmc1 = &sdmmc1; + mmc2 = &sdmmc2; + }; + + battery: battery { + compatible = "simple-battery"; + charge-full-design-microamp-hours = <3472000>; + charge-term-current-microamp = <300000>; + constant-charge-current-max-microamp = <2000000>; + constant-charge-voltage-max-microvolt = <4200000>; + factory-internal-resistance-micro-ohms = <117000>; + voltage-max-design-microvolt = <4172000>; + voltage-min-design-microvolt = <3400000>; + + ocv-capacity-celsius = <20>; + ocv-capacity-table-0 = <4172000 100>, <4054000 95>, <3984000 90>, <3926000 85>, + <3874000 80>, <3826000 75>, <3783000 70>, <3746000 65>, + <3714000 60>, <3683000 55>, <3650000 50>, <3628000 45>, + <3612000 40>, <3600000 35>, <3587000 30>, <3571000 25>, + <3552000 20>, <3525000 15>, <3492000 10>, <3446000 5>, + <3400000 0>; + }; + + /* Channels reversed for both headphones and speakers. */ + sound { + compatible = "simple-audio-card"; + simple-audio-card,name = "rk817_ext"; + simple-audio-card,aux-devs = <&spk_amp>; + simple-audio-card,format = "i2s"; + simple-audio-card,hp-det-gpio = <&gpio4 RK_PC6 GPIO_ACTIVE_HIGH>; + simple-audio-card,mclk-fs = <256>; + simple-audio-card,widgets = + "Microphone", "Mic Jack", + "Headphone", "Headphones", + "Speaker", "Internal Speakers"; + simple-audio-card,routing = + "MICL", "Mic Jack", + "Headphones", "HPOL", + "Headphones", "HPOR", + "Internal Speakers", "Speaker Amp OUTL", + "Internal Speakers", "Speaker Amp OUTR", + "Speaker Amp INL", "HPOL", + "Speaker Amp INR", "HPOR"; + simple-audio-card,pin-switches = "Internal Speakers"; + + simple-audio-card,codec { + sound-dai = <&rk817>; + }; + + simple-audio-card,cpu { + sound-dai = <&i2s1_8ch>; + }; + }; + + spk_amp: audio-amplifier { + compatible = "simple-audio-amplifier"; + enable-gpios = <&gpio4 RK_PC2 GPIO_ACTIVE_HIGH>; + pinctrl-0 = <&spk_amp_enable_h>; + pinctrl-names = "default"; + sound-name-prefix = "Speaker Amp"; + }; +}; + +&gpio_keys_control { + button-r1 { + gpios = <&gpio3 RK_PB4 GPIO_ACTIVE_LOW>; + label = "TR"; + linux,code = ; + }; + + button-r2 { + gpios = <&gpio3 RK_PB3 GPIO_ACTIVE_LOW>; + label = "TR2"; + linux,code = ; + }; +}; + +&panel { + compatible = "anbernic,rg353v-panel-v2"; + iovcc-supply = <&vcc3v3_lcd0_n>; + vcc-supply = <&vcc3v3_lcd0_n>; + /delete-property/ vdd-supply; +}; + +&pinctrl { + audio-amplifier { + spk_amp_enable_h: spk-amp-enable-h { + rockchip,pins = + <4 RK_PC2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; +}; + +&rk817 { + rk817_charger: charger { + monitored-battery = <&battery>; + rockchip,resistor-sense-micro-ohms = <10000>; + rockchip,sleep-enter-current-microamp = <300000>; + rockchip,sleep-filter-current-microamp = <100000>; + }; +}; diff --git a/arch/arm64/boot/dts/rockchip/rk3566-anbernic-rgxx3.dtsi b/arch/arm64/boot/dts/rockchip/rk3566-anbernic-rgxx3.dtsi index 8fadd8afb1906b55a4384c62f4594cb4bcd0ec30..a2c31d53b45bc2e09df1a5c627cbf8a8c0449965 100644 --- a/arch/arm64/boot/dts/rockchip/rk3566-anbernic-rgxx3.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3566-anbernic-rgxx3.dtsi @@ -191,30 +191,30 @@ }; }; - leds: gpio-leds { - compatible = "gpio-leds"; - pinctrl-0 = <&led_pins>; - pinctrl-names = "default"; + leds: pwm-leds { + compatible = "pwm-leds"; green_led: led-0 { color = ; default-state = "on"; function = LED_FUNCTION_POWER; - gpios = <&gpio0 RK_PC5 GPIO_ACTIVE_HIGH>; + max-brightness = <255>; + pwms = <&pwm6 0 25000 0>; }; amber_led: led-1 { color = ; function = LED_FUNCTION_CHARGING; - gpios = <&gpio0 RK_PC6 GPIO_ACTIVE_HIGH>; - retain-state-suspended; + max-brightness = <255>; + pwms = <&pwm7 0 25000 0>; }; red_led: led-2 { color = ; default-state = "off"; function = LED_FUNCTION_STATUS; - gpios = <&gpio0 RK_PC7 GPIO_ACTIVE_HIGH>; + max-brightness = <255>; + pwms = <&pwm0 0 25000 0>; }; }; @@ -597,15 +597,6 @@ }; }; - gpio-led { - led_pins: led-pins { - rockchip,pins = - <0 RK_PC5 RK_FUNC_GPIO &pcfg_pull_none>, - <0 RK_PC6 RK_FUNC_GPIO &pcfg_pull_none>, - <0 RK_PC7 RK_FUNC_GPIO &pcfg_pull_none>; - }; - }; - joy-mux { joy_mux_en: joy-mux-en { rockchip,pins = @@ -654,10 +645,24 @@ vccio7-supply = <&vcc_3v3>; }; +&pwm0 { + pinctrl-0 = <&pwm0m1_pins>; + pinctrl-names = "default"; + status = "okay"; +}; + &pwm5 { status = "okay"; }; +&pwm6 { + status = "okay"; +}; + +&pwm7 { + status = "okay"; +}; + &saradc { vref-supply = <&vcc_1v8>; status = "okay"; @@ -716,7 +721,7 @@ status = "okay"; bluetooth { - compatible = "realtek,rtl8821cs-bt", "realtek,rtl8822cs-bt"; + compatible = "realtek,rtl8821cs-bt", "realtek,rtl8723bs-bt"; device-wake-gpios = <&gpio4 4 GPIO_ACTIVE_HIGH>; enable-gpios = <&gpio4 3 GPIO_ACTIVE_HIGH>; host-wake-gpios = <&gpio4 5 GPIO_ACTIVE_HIGH>; diff --git a/arch/arm64/boot/dts/rockchip/rk3566-soquartz-cm4.dts b/arch/arm64/boot/dts/rockchip/rk3566-soquartz-cm4.dts index 263ce40770ddeda22b02c2f2e2f807947c8c0ee4..cddf6cd2fecb1bf34458a98adc93b59560f98fde 100644 --- a/arch/arm64/boot/dts/rockchip/rk3566-soquartz-cm4.dts +++ b/arch/arm64/boot/dts/rockchip/rk3566-soquartz-cm4.dts @@ -28,6 +28,16 @@ regulator-max-microvolt = <5000000>; vin-supply = <&vcc12v_dcin>; }; + + vcc_sd_pwr: vcc-sd-pwr-regulator { + compatible = "regulator-fixed"; + regulator-name = "vcc_sd_pwr"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + vin-supply = <&vcc3v3_sys>; + }; }; /* phy for pcie */ @@ -130,13 +140,7 @@ }; &sdmmc0 { - vmmc-supply = <&sdmmc_pwr>; - status = "okay"; -}; - -&sdmmc_pwr { - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; + vmmc-supply = <&vcc_sd_pwr>; status = "okay"; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3566-soquartz.dtsi b/arch/arm64/boot/dts/rockchip/rk3566-soquartz.dtsi index 102e448bc026a78a3783dd9530c4f12a0aad0e09..31aa2b8efe39314087190027c495cb2b4a26c163 100644 --- a/arch/arm64/boot/dts/rockchip/rk3566-soquartz.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3566-soquartz.dtsi @@ -104,16 +104,6 @@ regulator-max-microvolt = <3300000>; vin-supply = <&vcc5v0_sys>; }; - - sdmmc_pwr: sdmmc-pwr-regulator { - compatible = "regulator-fixed"; - enable-active-high; - gpio = <&gpio0 RK_PA5 GPIO_ACTIVE_HIGH>; - pinctrl-names = "default"; - pinctrl-0 = <&sdmmc_pwr_h>; - regulator-name = "sdmmc_pwr"; - status = "disabled"; - }; }; &cpu0 { @@ -155,6 +145,19 @@ status = "disabled"; }; +&gpio0 { + nextrst-hog { + gpio-hog; + /* + * GPIO_ACTIVE_LOW + output-low here means that the pin is set + * to high, because output-low decides the value pre-inversion. + */ + gpios = ; + line-name = "nEXTRST"; + output-low; + }; +}; + &gpu { mali-supply = <&vdd_gpu>; status = "okay"; @@ -538,12 +541,6 @@ rockchip,pins = <2 RK_PC2 RK_FUNC_GPIO &pcfg_pull_none>; }; }; - - sdmmc-pwr { - sdmmc_pwr_h: sdmmc-pwr-h { - rockchip,pins = <0 RK_PA5 RK_FUNC_GPIO &pcfg_pull_none>; - }; - }; }; &pmu_io_domains { diff --git a/arch/arm64/boot/dts/rockchip/rk3568-fastrhino-r66s.dts b/arch/arm64/boot/dts/rockchip/rk3568-fastrhino-r66s.dts new file mode 100644 index 0000000000000000000000000000000000000000..58ab7e9971dbce99a275a6f9f2cad8380ee3b5eb --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rk3568-fastrhino-r66s.dts @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +#include "rk3568-fastrhino-r66s.dtsi" + +/ { + model = "Lunzn FastRhino R66S"; + compatible = "lunzn,fastrhino-r66s", "rockchip,rk3568"; + + aliases { + mmc0 = &sdmmc0; + }; +}; + +&sdmmc0 { + bus-width = <4>; + cap-mmc-highspeed; + cap-sd-highspeed; + disable-wp; + max-frequency = <150000000>; + no-sdio; + no-mmc; + pinctrl-names = "default"; + pinctrl-0 = <&sdmmc0_bus4 &sdmmc0_clk &sdmmc0_cmd &sdmmc0_det>; + vmmc-supply = <&vcc3v3_sd>; + vqmmc-supply = <&vccio_sd>; + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/rockchip/rk3568-fastrhino-r66s.dtsi b/arch/arm64/boot/dts/rockchip/rk3568-fastrhino-r66s.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..25e205632a686ddaa589b0542e69888242e8c4ac --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rk3568-fastrhino-r66s.dtsi @@ -0,0 +1,484 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +/dts-v1/; +#include +#include +#include +#include +#include +#include "rk3568.dtsi" + +/ { + chosen: chosen { + stdout-path = "serial2:1500000n8"; + }; + + gpio-keys { + compatible = "gpio-keys"; + pinctrl-names = "default"; + pinctrl-0 = <&reset_button_pin>; + + button-reset { + debounce-interval = <50>; + gpios = <&gpio0 RK_PB6 GPIO_ACTIVE_LOW>; + label = "reset"; + linux,code = ; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&status_led_pin>; + + status_led: led-status { + color = ; + function = LED_FUNCTION_STATUS; + gpios = <&gpio0 RK_PC0 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "heartbeat"; + }; + }; + + dc_12v: dc-12v-regulator { + compatible = "regulator-fixed"; + regulator-name = "dc_12v"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + }; + + vcc3v3_pcie: vcc3v3-pcie-regulator { + compatible = "regulator-fixed"; + regulator-name = "vcc3v3_pcie"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + vin-supply = <&vcc5v0_sys>; + }; + + vcc3v3_sys: vcc3v3-sys-regulator { + compatible = "regulator-fixed"; + regulator-name = "vcc3v3_sys"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + vin-supply = <&dc_12v>; + }; + + 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 = <&dc_12v>; + }; + + vcc5v0_usb_host: vcc5v0-usb-host-regulator { + compatible = "regulator-fixed"; + regulator-name = "vcc5v0_usb_host"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + }; + + vcc5v0_usb_otg: vcc5v0-usb-otg-regulator { + compatible = "regulator-fixed"; + enable-active-high; + gpio = <&gpio0 RK_PA5 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&vcc5v0_usb_otg_en>; + regulator-name = "vcc5v0_usb_otg"; + regulator-always-on; + regulator-boot-on; + }; +}; + +&combphy0 { + status = "okay"; +}; + +&combphy1 { + status = "okay"; +}; + +&cpu0 { + cpu-supply = <&vdd_cpu>; +}; + +&cpu1 { + cpu-supply = <&vdd_cpu>; +}; + +&cpu2 { + cpu-supply = <&vdd_cpu>; +}; + +&cpu3 { + cpu-supply = <&vdd_cpu>; +}; + +&gpu { + mali-supply = <&vdd_gpu>; + status = "okay"; +}; + +&i2c0 { + status = "okay"; + + vdd_cpu: regulator@1c { + compatible = "tcs,tcs4525"; + reg = <0x1c>; + fcs,suspend-voltage-selector = <1>; + regulator-name = "vdd_cpu"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <1150000>; + regulator-ramp-delay = <2300>; + vin-supply = <&vcc5v0_sys>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + rk809: pmic@20 { + compatible = "rockchip,rk809"; + reg = <0x20>; + interrupt-parent = <&gpio0>; + interrupts = ; + #clock-cells = <1>; + pinctrl-names = "default"; + pinctrl-0 = <&pmic_int>; + rockchip,system-power-controller; + vcc1-supply = <&vcc3v3_sys>; + vcc2-supply = <&vcc3v3_sys>; + vcc3-supply = <&vcc3v3_sys>; + vcc4-supply = <&vcc3v3_sys>; + vcc5-supply = <&vcc3v3_sys>; + vcc6-supply = <&vcc3v3_sys>; + vcc7-supply = <&vcc3v3_sys>; + vcc8-supply = <&vcc3v3_sys>; + vcc9-supply = <&vcc3v3_sys>; + wakeup-source; + + regulators { + vdd_logic: DCDC_REG1 { + regulator-name = "vdd_logic"; + regulator-always-on; + regulator-boot-on; + regulator-init-microvolt = <900000>; + regulator-initial-mode = <0x2>; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <1350000>; + regulator-ramp-delay = <6001>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_gpu: DCDC_REG2 { + regulator-name = "vdd_gpu"; + regulator-always-on; + regulator-init-microvolt = <900000>; + regulator-initial-mode = <0x2>; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <1350000>; + regulator-ramp-delay = <6001>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_ddr: DCDC_REG3 { + regulator-name = "vcc_ddr"; + regulator-always-on; + regulator-boot-on; + regulator-initial-mode = <0x2>; + + regulator-state-mem { + regulator-on-in-suspend; + }; + }; + + vdd_npu: DCDC_REG4 { + regulator-name = "vdd_npu"; + regulator-init-microvolt = <900000>; + regulator-initial-mode = <0x2>; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <1350000>; + regulator-ramp-delay = <6001>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_1v8: DCDC_REG5 { + regulator-name = "vcc_1v8"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdda0v9_image: LDO_REG1 { + regulator-name = "vdda0v9_image"; + regulator-min-microvolt = <950000>; + regulator-max-microvolt = <950000>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdda_0v9: LDO_REG2 { + regulator-name = "vdda_0v9"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <900000>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdda0v9_pmu: LDO_REG3 { + regulator-name = "vdda0v9_pmu"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <900000>; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <900000>; + }; + }; + + vccio_acodec: LDO_REG4 { + regulator-name = "vccio_acodec"; + regulator-always-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vccio_sd: LDO_REG5 { + regulator-name = "vccio_sd"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc3v3_pmu: LDO_REG6 { + regulator-name = "vcc3v3_pmu"; + 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>; + }; + }; + + vcca_1v8: LDO_REG7 { + regulator-name = "vcca_1v8"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcca1v8_pmu: LDO_REG8 { + regulator-name = "vcca1v8_pmu"; + 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>; + }; + }; + + vcca1v8_image: LDO_REG9 { + regulator-name = "vcca1v8_image"; + regulator-init-microvolt = <950000>; + regulator-min-microvolt = <950000>; + regulator-max-microvolt = <1800000>; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <950000>; + }; + }; + + vcc_3v3: SWITCH_REG1 { + regulator-name = "vcc_3v3"; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc3v3_sd: SWITCH_REG2 { + regulator-name = "vcc3v3_sd"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + }; + }; +}; + +&pcie30phy { + data-lanes = <1 2>; + status = "okay"; +}; + +&pcie3x1 { + num-lanes = <1>; + reset-gpios = <&gpio0 RK_PC3 GPIO_ACTIVE_HIGH>; + vpcie3v3-supply = <&vcc3v3_pcie>; + status = "okay"; +}; + +&pcie3x2 { + num-lanes = <1>; + reset-gpios = <&gpio0 RK_PC6 GPIO_ACTIVE_HIGH>; + vpcie3v3-supply = <&vcc3v3_pcie>; + status = "okay"; +}; + +&pinctrl { + gpio-leds { + status_led_pin: status-led-pin { + rockchip,pins = <0 RK_PC0 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + pmic { + pmic_int: pmic-int { + rockchip,pins = <0 RK_PA3 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + rockchip-key { + reset_button_pin: reset-button-pin { + rockchip,pins = <0 RK_PB6 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + usb { + vcc5v0_usb_otg_en: vcc5v0-usb-otg-en { + rockchip,pins = <0 RK_PA5 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; +}; + +&pmu_io_domains { + pmuio1-supply = <&vcc3v3_pmu>; + pmuio2-supply = <&vcc3v3_pmu>; + vccio1-supply = <&vccio_acodec>; + vccio3-supply = <&vccio_sd>; + vccio4-supply = <&vcc_1v8>; + vccio5-supply = <&vcc_3v3>; + vccio6-supply = <&vcc_1v8>; + vccio7-supply = <&vcc_3v3>; + status = "okay"; +}; + +&saradc { + vref-supply = <&vcca_1v8>; + status = "okay"; +}; + +&tsadc { + rockchip,hw-tshut-mode = <1>; + rockchip,hw-tshut-polarity = <0>; + status = "okay"; +}; + +&uart2 { + status = "okay"; +}; + +&usb_host0_ehci { + status = "okay"; +}; + +&usb_host0_ohci { + status = "okay"; +}; + +&usb_host0_xhci { + dr_mode = "host"; + extcon = <&usb2phy0>; + status = "okay"; +}; + +&usb_host1_ehci { + status = "okay"; +}; + +&usb_host1_ohci { + status = "okay"; +}; + +&usb_host1_xhci { + status = "okay"; +}; + +&usb2phy0 { + status = "okay"; +}; + +&usb2phy0_host { + phy-supply = <&vcc5v0_usb_host>; + status = "okay"; +}; + +&usb2phy0_otg { + phy-supply = <&vcc5v0_usb_otg>; + status = "okay"; +}; + +&vop { + assigned-clocks = <&cru DCLK_VOP0>, <&cru DCLK_VOP1>; + assigned-clock-parents = <&pmucru PLL_HPLL>, <&cru PLL_VPLL>; + status = "okay"; +}; + +&vop_mmu { + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/rockchip/rk3568-fastrhino-r68s.dts b/arch/arm64/boot/dts/rockchip/rk3568-fastrhino-r68s.dts new file mode 100644 index 0000000000000000000000000000000000000000..e1fe5e442689a051b724f7d1e45ed2991db76458 --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rk3568-fastrhino-r68s.dts @@ -0,0 +1,112 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +#include "rk3568-fastrhino-r66s.dtsi" + +/ { + model = "Lunzn FastRhino R68S"; + compatible = "lunzn,fastrhino-r68s", "rockchip,rk3568"; + + aliases { + ethernet0 = &gmac0; + ethernet1 = &gmac1; + mmc0 = &sdhci; + }; + + adc-keys { + compatible = "adc-keys"; + io-channels = <&saradc 0>; + io-channel-names = "buttons"; + keyup-threshold-microvolt = <1800000>; + + button-recovery { + label = "Recovery"; + linux,code = ; + press-threshold-microvolt = <1750>; + }; + }; +}; + +&gmac0 { + assigned-clocks = <&cru SCLK_GMAC0_RX_TX>, <&cru SCLK_GMAC0>; + assigned-clock-parents = <&cru SCLK_GMAC0_RGMII_SPEED>; + assigned-clock-rates = <0>, <125000000>; + clock_in_out = "output"; + phy-handle = <&rgmii_phy0>; + phy-mode = "rgmii-id"; + pinctrl-names = "default"; + pinctrl-0 = <&gmac0_miim + &gmac0_tx_bus2 + &gmac0_rx_bus2 + &gmac0_rgmii_clk + &gmac0_rgmii_bus>; + snps,reset-gpio = <&gpio0 RK_PB0 GPIO_ACTIVE_LOW>; + snps,reset-active-low; + /* Reset time is 15ms, 50ms for rtl8211f */ + snps,reset-delays-us = <0 15000 50000>; + tx_delay = <0x3c>; + rx_delay = <0x2f>; + status = "okay"; +}; + +&gmac1 { + assigned-clocks = <&cru SCLK_GMAC1_RX_TX>, <&cru SCLK_GMAC1>; + assigned-clock-parents = <&cru SCLK_GMAC1_RGMII_SPEED>; + assigned-clock-rates = <0>, <125000000>; + clock_in_out = "output"; + phy-handle = <&rgmii_phy1>; + phy-mode = "rgmii-id"; + pinctrl-names = "default"; + pinctrl-0 = <&gmac1m1_miim + &gmac1m1_tx_bus2 + &gmac1m1_rx_bus2 + &gmac1m1_rgmii_clk + &gmac1m1_rgmii_bus>; + snps,reset-gpio = <&gpio0 RK_PB1 GPIO_ACTIVE_LOW>; + snps,reset-active-low; + /* Reset time is 15ms, 50ms for rtl8211f */ + snps,reset-delays-us = <0 15000 50000>; + tx_delay = <0x4f>; + rx_delay = <0x26>; + status = "okay"; +}; + +&mdio0 { + rgmii_phy0: ethernet-phy@0 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <0>; + pinctrl-0 = <ð_phy0_reset_pin>; + pinctrl-names = "default"; + }; +}; + +&mdio1 { + rgmii_phy1: ethernet-phy@0 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <0>; + pinctrl-0 = <ð_phy1_reset_pin>; + pinctrl-names = "default"; + }; +}; + +&pinctrl { + gmac0 { + eth_phy0_reset_pin: eth-phy0-reset-pin { + rockchip,pins = <1 RK_PB0 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + gmac1 { + eth_phy1_reset_pin: eth-phy1-reset-pin { + rockchip,pins = <1 RK_PB1 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; +}; + +&sdhci { + bus-width = <8>; + max-frequency = <200000000>; + non-removable; + pinctrl-names = "default"; + pinctrl-0 = <&emmc_bus8 &emmc_clk &emmc_cmd &emmc_datastrobe>; + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/rockchip/rk3568-nanopi-r5c.dts b/arch/arm64/boot/dts/rockchip/rk3568-nanopi-r5c.dts index f70ca9f0470ad59dc9ff41a9f9f6a27b423cf7d0..c718b8dbb9c6bc0b5055aafa6286a2925efe4d1c 100644 --- a/arch/arm64/boot/dts/rockchip/rk3568-nanopi-r5c.dts +++ b/arch/arm64/boot/dts/rockchip/rk3568-nanopi-r5c.dts @@ -106,7 +106,7 @@ rockchip-key { reset_button_pin: reset-button-pin { - rockchip,pins = <4 RK_PA0 RK_FUNC_GPIO &pcfg_pull_up>; + rockchip,pins = <0 RK_PB7 RK_FUNC_GPIO &pcfg_pull_up>; }; }; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3568-nanopi-r5s.dts b/arch/arm64/boot/dts/rockchip/rk3568-nanopi-r5s.dts index 2a1118f15c2913f32d96046918f2735625e546fc..b6ad8328c7ebc4102552d6374ea548b5bcd8c9d5 100644 --- a/arch/arm64/boot/dts/rockchip/rk3568-nanopi-r5s.dts +++ b/arch/arm64/boot/dts/rockchip/rk3568-nanopi-r5s.dts @@ -134,4 +134,3 @@ }; }; }; - diff --git a/arch/arm64/boot/dts/rockchip/rk3568.dtsi b/arch/arm64/boot/dts/rockchip/rk3568.dtsi index ba67b58f05b790c55d63427aaa87215441b6f082..f1be76a54ceb0cb0730f444c69c3da73e07194c9 100644 --- a/arch/arm64/boot/dts/rockchip/rk3568.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3568.dtsi @@ -94,9 +94,10 @@ power-domains = <&power RK3568_PD_PIPE>; reg = <0x3 0xc0400000 0x0 0x00400000>, <0x0 0xfe270000 0x0 0x00010000>, - <0x3 0x7f000000 0x0 0x01000000>; - ranges = <0x01000000 0x0 0x3ef00000 0x3 0x7ef00000 0x0 0x00100000>, - <0x02000000 0x0 0x00000000 0x3 0x40000000 0x0 0x3ef00000>; + <0x0 0xf2000000 0x0 0x00100000>; + ranges = <0x01000000 0x0 0xf2100000 0x0 0xf2100000 0x0 0x00100000>, + <0x02000000 0x0 0xf2200000 0x0 0xf2200000 0x0 0x01e00000>, + <0x03000000 0x0 0x40000000 0x3 0x40000000 0x0 0x40000000>; reg-names = "dbi", "apb", "config"; resets = <&cru SRST_PCIE30X1_POWERUP>; reset-names = "pipe"; @@ -146,9 +147,10 @@ power-domains = <&power RK3568_PD_PIPE>; reg = <0x3 0xc0800000 0x0 0x00400000>, <0x0 0xfe280000 0x0 0x00010000>, - <0x3 0xbf000000 0x0 0x01000000>; - ranges = <0x01000000 0x0 0x3ef00000 0x3 0xbef00000 0x0 0x00100000>, - <0x02000000 0x0 0x00000000 0x3 0x80000000 0x0 0x3ef00000>; + <0x0 0xf0000000 0x0 0x00100000>; + ranges = <0x01000000 0x0 0xf0100000 0x0 0xf0100000 0x0 0x00100000>, + <0x02000000 0x0 0xf0200000 0x0 0xf0200000 0x0 0x01e00000>, + <0x03000000 0x0 0x40000000 0x3 0x80000000 0x0 0x40000000>; reg-names = "dbi", "apb", "config"; resets = <&cru SRST_PCIE30X2_POWERUP>; reset-names = "pipe"; diff --git a/arch/arm64/boot/dts/rockchip/rk356x.dtsi b/arch/arm64/boot/dts/rockchip/rk356x.dtsi index f62e0fd881a958bb36d989b9491eefc026d12819..abee88911982d4f4dc5075d7d0ad4ded7da7cdbd 100644 --- a/arch/arm64/boot/dts/rockchip/rk356x.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk356x.dtsi @@ -613,6 +613,17 @@ #iommu-cells = <0>; }; + rga: rga@fdeb0000 { + compatible = "rockchip,rk3568-rga", "rockchip,rk3288-rga"; + reg = <0x0 0xfdeb0000 0x0 0x180>; + interrupts = ; + clocks = <&cru ACLK_RGA>, <&cru HCLK_RGA>, <&cru CLK_RGA_CORE>; + clock-names = "aclk", "hclk", "sclk"; + resets = <&cru SRST_RGA_CORE>, <&cru SRST_A_RGA>, <&cru SRST_H_RGA>; + reset-names = "core", "axi", "ahb"; + power-domains = <&power RK3568_PD_RGA>; + }; + vepu: video-codec@fdee0000 { compatible = "rockchip,rk3568-vepu"; reg = <0x0 0xfdee0000 0x0 0x800>; @@ -952,7 +963,7 @@ compatible = "rockchip,rk3568-pcie"; reg = <0x3 0xc0000000 0x0 0x00400000>, <0x0 0xfe260000 0x0 0x00010000>, - <0x3 0x3f000000 0x0 0x01000000>; + <0x0 0xf4000000 0x0 0x00100000>; reg-names = "dbi", "apb", "config"; interrupts = , , @@ -982,8 +993,9 @@ phys = <&combphy2 PHY_TYPE_PCIE>; phy-names = "pcie-phy"; power-domains = <&power RK3568_PD_PIPE>; - ranges = <0x01000000 0x0 0x3ef00000 0x3 0x3ef00000 0x0 0x00100000 - 0x02000000 0x0 0x00000000 0x3 0x00000000 0x0 0x3ef00000>; + ranges = <0x01000000 0x0 0xf4100000 0x0 0xf4100000 0x0 0x00100000>, + <0x02000000 0x0 0xf4200000 0x0 0xf4200000 0x0 0x01e00000>, + <0x03000000 0x0 0x40000000 0x3 0x00000000 0x0 0x40000000>; resets = <&cru SRST_PCIE20_POWERUP>; reset-names = "pipe"; #address-cells = <3>; diff --git a/arch/arm64/boot/dts/rockchip/rk3588-edgeble-neu6b-io.dts b/arch/arm64/boot/dts/rockchip/rk3588-edgeble-neu6b-io.dts new file mode 100644 index 0000000000000000000000000000000000000000..e9d5a8bab581f6b4ed1d0e7e709457dbf18bb39d --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rk3588-edgeble-neu6b-io.dts @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2023 Edgeble AI Technologies Pvt. Ltd. + */ + +/dts-v1/; +#include "rk3588j.dtsi" +#include "rk3588-edgeble-neu6b.dtsi" + +/ { + model = "Edgeble Neu6B IO Board"; + compatible = "edgeble,neural-compute-module-6b-io", + "edgeble,neural-compute-module-6b", "rockchip,rk3588"; + + aliases { + serial2 = &uart2; + }; + + chosen { + stdout-path = "serial2:1500000n8"; + }; +}; + +&uart2 { + pinctrl-0 = <&uart2m0_xfer>; + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/rockchip/rk3588-edgeble-neu6b.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-edgeble-neu6b.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..1c5bcf1280b48dc9dc15b9787a9e70fd15a19653 --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rk3588-edgeble-neu6b.dtsi @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2023 Edgeble AI Technologies Pvt. Ltd. + */ + +/ { + compatible = "edgeble,neural-compute-module-6b", "rockchip,rk3588"; + + aliases { + mmc0 = &sdhci; + }; + + 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>; + }; +}; + +&sdhci { + bus-width = <8>; + no-sdio; + no-sd; + non-removable; + max-frequency = <200000000>; + mmc-hs400-1_8v; + mmc-hs400-enhanced-strobe; + 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 b91af0204dbe824a896f059a2be9bd6bc3f713b2..4b2d857ee2197e4f08a94bed39e1591811254a7f 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-evb1-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rk3588-evb1-v10.dts @@ -49,6 +49,38 @@ }; }; +&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>; @@ -123,6 +155,611 @@ status = "okay"; }; +&spi2 { + status = "okay"; + assigned-clocks = <&cru CLK_SPI2>; + assigned-clock-rates = <200000000>; + num-cs = <2>; + + pmic@0 { + compatible = "rockchip,rk806"; + reg = <0x0>; + #gpio-cells = <2>; + gpio-controller; + interrupt-parent = <&gpio0>; + interrupts = <7 IRQ_TYPE_LEVEL_LOW>; + pinctrl-0 = <&pmic_pins>, <&rk806_dvs1_null>, + <&rk806_dvs2_null>, <&rk806_dvs3_null>; + pinctrl-names = "default"; + spi-max-frequency = <1000000>; + + 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 = <&vcc5v0_sys>; + 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: 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_npu_s0: dcdc-reg2 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <950000>; + regulator-ramp-delay = <12500>; + regulator-name = "vdd_npu_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: 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_gpu_mem_s0: dcdc-reg5 { + regulator-boot-on; + regulator-min-microvolt = <675000>; + regulator-max-microvolt = <950000>; + regulator-ramp-delay = <12500>; + regulator-enable-ramp-delay = <400>; + regulator-name = "vdd_gpu_mem_s0"; + regulator-state-mem { + regulator-off-in-suspend; + }; + + }; + + vdd_npu_mem_s0: dcdc-reg6 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <675000>; + regulator-max-microvolt = <950000>; + regulator-ramp-delay = <12500>; + regulator-name = "vdd_npu_mem_s0"; + regulator-state-mem { + regulator-off-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>; + }; + }; + + vdd_vdenc_mem_s0: dcdc-reg8 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <675000>; + regulator-max-microvolt = <950000>; + regulator-ramp-delay = <12500>; + regulator-name = "vdd_vdenc_mem_s0"; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd2_ddr_s3: dcdc-reg9 { + regulator-always-on; + regulator-boot-on; + regulator-name = "vdd2_ddr_s3"; + regulator-state-mem { + regulator-on-in-suspend; + }; + }; + + vcc_1v1_nldo_s3: dcdc-reg10 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1100000>; + regulator-max-microvolt = <1100000>; + regulator-ramp-delay = <12500>; + regulator-name = "vcc_1v1_nldo_s3"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1100000>; + }; + }; + + avcc_1v8_s0: pldo-reg1 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-ramp-delay = <12500>; + regulator-name = "avcc_1v8_s0"; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd1_1v8_ddr_s3: pldo-reg2 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-ramp-delay = <12500>; + regulator-name = "vdd1_1v8_ddr_s3"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + avcc_1v8_codec_s0: pldo-reg3 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-ramp-delay = <12500>; + regulator-name = "avcc_1v8_codec_s0"; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_3v3_s3: pldo-reg4 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-ramp-delay = <12500>; + regulator-name = "vcc_3v3_s3"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + 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; + }; + }; + + vccio_1v8_s3: pldo-reg6 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-ramp-delay = <12500>; + regulator-name = "vccio_1v8_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-ramp-delay = <12500>; + regulator-name = "vdd_0v75_s3"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <750000>; + }; + }; + + vdd2l_0v9_ddr_s3: nldo-reg2 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <900000>; + regulator-name = "vdd2l_0v9_ddr_s3"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <900000>; + }; + }; + + vdd_0v75_hdmi_edp_s0: nldo-reg3 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <750000>; + regulator-max-microvolt = <750000>; + regulator-name = "vdd_0v75_hdmi_edp_s0"; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + avdd_0v75_s0: nldo-reg4 { + 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-reg5 { + 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; + }; + }; + }; + }; + + pmic@1 { + compatible = "rockchip,rk806"; + reg = <0x01>; + #gpio-cells = <2>; + gpio-controller; + interrupt-parent = <&gpio0>; + interrupts = <7 IRQ_TYPE_LEVEL_LOW>; + pinctrl-0 = <&rk806_slave_dvs1_null>, <&rk806_slave_dvs2_null>, + <&rk806_slave_dvs3_null>; + pinctrl-names = "default"; + spi-max-frequency = <1000000>; + + 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_2v0_pldo_s3>; + vcca-supply = <&vcc5v0_sys>; + + rk806_slave_dvs1_null: dvs1-null-pins { + pins = "gpio_pwrctrl1"; + function = "pin_fun0"; + }; + + rk806_slave_dvs2_null: dvs2-null-pins { + pins = "gpio_pwrctrl2"; + function = "pin_fun0"; + }; + + rk806_slave_dvs3_null: dvs3-null-pins { + pins = "gpio_pwrctrl3"; + function = "pin_fun0"; + }; + + regulators { + vdd_cpu_big1_s0: dcdc-reg1 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <1050000>; + regulator-ramp-delay = <12500>; + regulator-name = "vdd_cpu_big1_s0"; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_cpu_big0_s0: dcdc-reg2 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <1050000>; + regulator-ramp-delay = <12500>; + regulator-name = "vdd_cpu_big0_s0"; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_cpu_lit_s0: dcdc-reg3 { + 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; + }; + }; + + vcc_3v3_s0: dcdc-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; + }; + }; + + vdd_cpu_big1_mem_s0: dcdc-reg5 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <675000>; + regulator-max-microvolt = <1050000>; + regulator-ramp-delay = <12500>; + regulator-name = "vdd_cpu_big1_mem_s0"; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + + vdd_cpu_big0_mem_s0: dcdc-reg6 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <675000>; + regulator-max-microvolt = <1050000>; + regulator-ramp-delay = <12500>; + regulator-name = "vdd_cpu_big0_mem_s0"; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_1v8_s0: dcdc-reg7 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-ramp-delay = <12500>; + regulator-name = "vcc_1v8_s0"; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_cpu_lit_mem_s0: dcdc-reg8 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <675000>; + regulator-max-microvolt = <950000>; + regulator-ramp-delay = <12500>; + regulator-name = "vdd_cpu_lit_mem_s0"; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vddq_ddr_s0: dcdc-reg9 { + regulator-always-on; + regulator-boot-on; + regulator-name = "vddq_ddr_s0"; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_ddr_s0: dcdc-reg10 { + 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; + }; + }; + + vcc_1v8_cam_s0: pldo-reg1 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-ramp-delay = <12500>; + regulator-name = "vcc_1v8_cam_s0"; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + avdd1v8_ddr_pll_s0: pldo-reg2 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-ramp-delay = <12500>; + regulator-name = "avdd1v8_ddr_pll_s0"; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_1v8_pll_s0: pldo-reg3 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-ramp-delay = <12500>; + regulator-name = "vdd_1v8_pll_s0"; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_3v3_sd_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_sd_s0"; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_2v8_cam_s0: pldo-reg5 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + regulator-ramp-delay = <12500>; + regulator-name = "vcc_2v8_cam_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_pll_s0: nldo-reg1 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <750000>; + regulator-max-microvolt = <750000>; + regulator-ramp-delay = <12500>; + regulator-name = "vdd_0v75_pll_s0"; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + 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; + }; + }; + + avdd_0v85_s0: nldo-reg3 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <850000>; + regulator-max-microvolt = <850000>; + regulator-ramp-delay = <12500>; + regulator-name = "avdd_0v85_s0"; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + avdd_1v2_cam_s0: nldo-reg4 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-ramp-delay = <12500>; + regulator-name = "avdd_1v2_cam_s0"; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + avdd_1v2_s0: nldo-reg5 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-ramp-delay = <12500>; + regulator-name = "avdd_1v2_s0"; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + }; + }; +}; + &uart2 { pinctrl-0 = <&uart2m0_xfer>; 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 3e4aee8f70c1bb5c19b201f9b874e147defb1f63..afda976680bca7b60169cf8140f07f2d41218008 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts +++ b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts @@ -51,6 +51,16 @@ 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 { @@ -69,6 +79,22 @@ 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>; @@ -133,6 +159,8 @@ 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 { @@ -179,6 +207,11 @@ status = "okay"; }; +&saradc { + vref-supply = <&avcc_1v8_s0>; + status = "okay"; +}; + &sdhci { bus-width = <8>; no-sdio; @@ -190,6 +223,344 @@ 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>; + + 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-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; + }; + }; + + 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"; diff --git a/arch/arm64/boot/dts/rockchip/rk3588j.dtsi b/arch/arm64/boot/dts/rockchip/rk3588j.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..38b9dbf38a21853d3693813c0eb835ecb83c5cab --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rk3588j.dtsi @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2022 Rockchip Electronics Co., Ltd. + * + */ + +#include "rk3588.dtsi" diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-indiedroid-nova.dts b/arch/arm64/boot/dts/rockchip/rk3588s-indiedroid-nova.dts new file mode 100644 index 0000000000000000000000000000000000000000..4d9ed2a0273637a32b22ad04a65e81ae34986a89 --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rk3588s-indiedroid-nova.dts @@ -0,0 +1,763 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) + +/dts-v1/; + +#include +#include +#include +#include "rk3588s.dtsi" + +/ { + model = "Indiedroid Nova"; + compatible = "indiedroid,nova", "rockchip,rk3588s"; + + aliases { + mmc0 = &sdhci; + mmc1 = &sdmmc; + mmc2 = &sdio; + serial2 = &uart2; + }; + + chosen { + stdout-path = "serial2:1500000n8"; + }; + + sdio_pwrseq: sdio-pwrseq { + compatible = "mmc-pwrseq-simple"; + clock-names = "ext_clock"; + clocks = <&rtc_hym8563>; + pinctrl-0 = <&wifi_enable_h>; + pinctrl-names = "default"; + post-power-on-delay-ms = <200>; + reset-gpios = <&gpio0 RK_PC7 GPIO_ACTIVE_LOW>; + }; + + sound { + compatible = "audio-graph-card"; + label = "rockchip,es8388-codec"; + widgets = "Microphone", "Mic Jack", + "Headphone", "Headphones"; + routing = "LINPUT2", "Mic Jack", + "Headphones", "LOUT1", + "Headphones", "ROUT1"; + dais = <&i2s0_8ch_p0>; + }; + + vbus5v0_typec: vbus5v0-typec-regulator { + compatible = "regulator-fixed"; + enable-active-high; + gpio = <&gpio4 RK_PA5 GPIO_ACTIVE_HIGH>; + pinctrl-0 = <&typec5v_pwren>; + pinctrl-names = "default"; + regulator-name = "vbus5v0_typec"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + vin-supply = <&vcc5v0_usb>; + }; + + vcc_1v1_nldo_s3: vcc-1v1-nldo-s3-regulator { + compatible = "regulator-fixed"; + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <1100000>; + regulator-min-microvolt = <1100000>; + regulator-name = "vcc_1v1_nldo_s3"; + vin-supply = <&vcc5v0_sys>; + }; + + /* Regulator is enabled whenever vcc_1v8_s0 is above 1.6v */ + vcc_3v3_s0: vcc-3v3-s0-regulator { + compatible = "regulator-fixed"; + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <3300000>; + regulator-min-microvolt = <3300000>; + regulator-name = "vcc_3v3_s0"; + vin-supply = <&vcc_3v3_s3>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc5v0_sys: vcc5v0-sys-regulator { + compatible = "regulator-fixed"; + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <5000000>; + regulator-min-microvolt = <5000000>; + regulator-name = "vcc5v0_sys"; + }; + + vcc5v0_usb: vcc5v0-usb-regulator { + compatible = "regulator-fixed"; + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <5000000>; + regulator-min-microvolt = <5000000>; + regulator-name = "vcc5v0_usb"; + vin-supply = <&vcc5v0_usbdcin>; + }; + + vcc5v0_usbdcin: vcc5v0-usbdcin-regulator { + compatible = "regulator-fixed"; + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <5000000>; + regulator-min-microvolt = <5000000>; + regulator-name = "vcc5v0_usbdcin"; + }; +}; + +&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>; +}; + +/* + * Add labels for each GPIO pin exposed on the 40 pin header. Note that + * voltage of each GPIO pin could be either 3.3v or 1.8v (as noted by + * label). + */ +&gpio0 { + gpio-line-names = /* GPIO0 A0-A7 */ + "", "", "", "", + "", "", "", "", + /* GPIO0 B0-B7 */ + "", "", "", "", + "", "", "", "", + /* GPIO0 C0-C7 */ + "", "", "", "", + "", "", "", "", + /* GPIO0 D0-D7 */ + "HEADER_12_1v8", "", "", "HEADER_24_1v8", + "", "", "", ""; +}; + +&gpio1 { + gpio-line-names = /* GPIO1 A0-A7 */ + "HEADER_27_3v3", "HEADER_28_3v3", "", "", + "HEADER_29_1v8", "", "HEADER_7_1v8", "", + /* GPIO1 B0-B7 */ + "", "HEADER_31_1v8", "HEADER_33_1v8", "", + "HEADER_11_1v8", "HEADER_13_1v8", "", "", + /* GPIO1 C0-C7 */ + "", "", "", "", + "", "", "", "", + /* GPIO1 D0-D7 */ + "", "", "", "", + "", "", "HEADER_5_3v3", "HEADER_3_3v3"; +}; + +&gpio3 { + gpio-line-names = /* GPIO3 A0-A7 */ + "", "", "", "", + "", "", "", "", + /* GPIO3 B0-B7 */ + "HEADER_16_1v8", "HEADER_18_1v8", "", "", + "", "", "", "HEADER_19_1v8", + /* GPIO3 C0-C7 */ + "HEADER_21_1v8", "HEADER_23_1v8", "", "HEADER_26_1v8", + "HEADER_15_1v8", "HEADER_22_1v8", "", "", + /* GPIO3 D0-D7 */ + "", "", "", "", + "", "", "", ""; +}; + +&gpio4 { + gpio-line-names = /* GPIO4 A0-A7 */ + "", "", "HEADER_37_3v3", "HEADER_32_3v3", + "HEADER_36_3v3", "", "HEADER_35_3v3", "HEADER_38_3v3", + /* GPIO4 B0-B7 */ + "", "", "", "HEADER_40_3v3", + "HEADER_8_3v3", "HEADER_10_3v3", "", "", + /* GPIO4 C0-C7 */ + "", "", "", "", + "", "", "", "", + /* GPIO4 D0-D7 */ + "", "", "", "", + "", "", "", ""; +}; + +&i2c0 { + pinctrl-0 = <&i2c0m2_xfer>; + pinctrl-names = "default"; + status = "okay"; + + vdd_cpu_big0_s0: regulator@42 { + compatible = "rockchip,rk8602"; + reg = <0x42>; + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <1050000>; + regulator-min-microvolt = <550000>; + regulator-name = "vdd_cpu_big0_s0"; + regulator-ramp-delay = <2300>; + fcs,suspend-voltage-selector = <1>; + vin-supply = <&vcc5v0_sys>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_cpu_big1_s0: regulator@43 { + compatible = "rockchip,rk8603", "rockchip,rk8602"; + reg = <0x43>; + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <1050000>; + regulator-min-microvolt = <550000>; + regulator-name = "vdd_cpu_big1_s0"; + regulator-ramp-delay = <2300>; + fcs,suspend-voltage-selector = <1>; + vin-supply = <&vcc5v0_sys>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; +}; + +&i2c2 { + status = "okay"; + + vdd_npu_s0: regulator@42 { + compatible = "rockchip,rk8602"; + reg = <0x42>; + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <950000>; + regulator-min-microvolt = <550000>; + regulator-name = "vdd_npu_s0"; + regulator-ramp-delay = <2300>; + fcs,suspend-voltage-selector = <1>; + vin-supply = <&vcc5v0_sys>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; +}; + +&i2c6 { + pinctrl-0 = <&i2c6m3_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 = <&vbus5v0_typec>; + + connector { + compatible = "usb-c-connector"; + data-role = "dual"; + label = "USB-C"; + power-role = "dual"; + try-power-role = "sink"; + source-pdos = ; + sink-pdos = ; + op-sink-microwatt = <1000000>; + }; + }; + + rtc_hym8563: rtc@51 { + compatible = "haoyu,hym8563"; + reg = <0x51>; + #clock-cells = <0>; + clock-output-names = "hym8563"; + interrupt-parent = <&gpio0>; + interrupts = ; + pinctrl-0 = <&hym8563_int>; + pinctrl-names = "default"; + wakeup-source; + }; +}; + +&i2c7 { + pinctrl-0 = <&i2c7m0_xfer>; + status = "okay"; + + es8388: audio-codec@11 { + compatible = "everest,es8388"; + reg = <0x11>; + assigned-clock-rates = <12288000>; + assigned-clocks = <&cru I2S0_8CH_MCLKOUT>; + AVDD-supply = <&vcc_3v3_s3>; + clock-names = "mclk"; + clocks = <&cru I2S0_8CH_MCLKOUT>; + 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>; + }; + }; +}; + +&pinctrl { + bluetooth-pins { + bt_reset: bt-reset { + rockchip,pins = + <0 RK_PD4 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + bt_wake_dev: bt-wake-dev { + rockchip,pins = + <0 RK_PC6 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + bt_wake_host: bt-wake-host { + rockchip,pins = + <0 RK_PC5 RK_FUNC_GPIO &pcfg_pull_down>; + }; + }; + + hym8563 { + + hym8563_int: hym8563-int { + rockchip,pins = + <0 RK_PB0 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + sdio-pwrseq { + wifi_enable_h: wifi-enable-h { + rockchip,pins = + <0 RK_PC7 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + usb-typec { + usbc0_int: usbc0-int { + rockchip,pins = + <0 RK_PC4 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + typec5v_pwren: typec5v-pwren { + rockchip,pins = + <4 RK_PA5 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; +}; + +/* HS400 modes seemed to cause io errors. */ +&sdhci { + bus-width = <8>; + no-mmc-hs400; + no-sd; + no-sdio; + non-removable; + max-frequency = <200000000>; + vmmc-supply = <&vcc_3v3_s0>; + vqmmc-supply = <&vcc_1v8_s3>; + status = "okay"; +}; + +&sdio { + bus-width = <4>; + cap-sd-highspeed; + cap-sdio-irq; + disable-wp; + keep-power-in-suspend; + max-frequency = <100000000>; + mmc-pwrseq = <&sdio_pwrseq>; + no-mmc; + no-sd; + non-removable; + sd-uhs-sdr104; + vmmc-supply = <&vcc_3v3_s3>; + vqmmc-supply = <&vcc_1v8_s3>; + 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 { + #address-cells = <1>; + assigned-clocks = <&cru CLK_SPI2>; + assigned-clock-rates = <200000000>; + num-cs = <1>; + pinctrl-0 = <&spi2m2_pins>, <&spi2m2_cs0>; + pinctrl-names = "default"; + #size-cells = <0>; + status = "okay"; + + pmic@0 { + compatible = "rockchip,rk806"; + reg = <0x0>; + #gpio-cells = <2>; + gpio-controller; + interrupt-parent = <&gpio0>; + interrupts = ; + pinctrl-0 = <&pmic_pins>, <&rk806_dvs1_null>, + <&rk806_dvs2_null>, <&rk806_dvs3_null>; + pinctrl-names = "default"; + spi-max-frequency = <1000000>; + + 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_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: dcdc-reg1 { + regulator-boot-on; + regulator-enable-ramp-delay = <400>; + regulator-max-microvolt = <950000>; + regulator-min-microvolt = <550000>; + regulator-name = "vdd_gpu_s0"; + regulator-ramp-delay = <12500>; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_cpu_lit_s0: dcdc-reg2 { + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <950000>; + regulator-min-microvolt = <550000>; + regulator-ramp-delay = <12500>; + regulator-name = "vdd_cpu_lit_s0"; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_logic_s0: dcdc-reg3 { + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <750000>; + regulator-min-microvolt = <675000>; + regulator-name = "vdd_logic_s0"; + regulator-ramp-delay = <12500>; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <750000>; + }; + }; + + vdd_vdenc_s0: dcdc-reg4 { + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <950000>; + regulator-min-microvolt = <550000>; + regulator-name = "vdd_vdenc_s0"; + regulator-ramp-delay = <12500>; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_ddr_s0: dcdc-reg5 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <750000>; + regulator-max-microvolt = <850000>; + 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-max-microvolt = <1100000>; + regulator-min-microvolt = <1100000>; + 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-max-microvolt = <2000000>; + regulator-min-microvolt = <2000000>; + 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-max-microvolt = <3300000>; + regulator-min-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-max-microvolt = <600000>; + regulator-min-microvolt = <600000>; + regulator-name = "vddq_ddr_s0"; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_1v8_s3: dcdc-reg10 { + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <1800000>; + regulator-min-microvolt = <1800000>; + regulator-name = "vcc_1v8_s3"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vcc_1v8_s0: pldo-reg1 { + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <1800000>; + regulator-min-microvolt = <1800000>; + regulator-name = "vcc_1v8_s0"; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcca_1v8_s0: pldo-reg2 { + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <1800000>; + regulator-min-microvolt = <1800000>; + regulator-name = "vcca_1v8_s0"; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vdda_1v2_s0: pldo-reg3 { + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <1200000>; + regulator-min-microvolt = <1200000>; + regulator-name = "vdda_1v2_s0"; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcca_3v3_s0: pldo-reg4 { + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <3300000>; + regulator-min-microvolt = <3300000>; + regulator-name = "vcca_3v3_s0"; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vccio_sd_s0: pldo-reg5 { + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <3300000>; + regulator-min-microvolt = <1800000>; + regulator-name = "vccio_sd_s0"; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_1v8_s3_pldo6: pldo-reg6 { + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <1800000>; + regulator-min-microvolt = <1800000>; + regulator-name = "vcc_1v8_s3_pldo6"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vdd_0v75_s3: nldo-reg1 { + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <750000>; + regulator-min-microvolt = <750000>; + regulator-name = "vdd_0v75_s3"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <750000>; + }; + }; + + vdda_ddr_pll_s0: nldo-reg2 { + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <850000>; + regulator-min-microvolt = <850000>; + regulator-name = "vdda_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-max-microvolt = <750000>; + regulator-min-microvolt = <750000>; + regulator-name = "avdd_0v75_s0"; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdda_0v85_s0: nldo-reg4 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <850000>; + regulator-max-microvolt = <850000>; + regulator-name = "vdda_0v85_s0"; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + /* Schematics show not in use */ + nldo-reg5 { + }; + }; + }; +}; + +&tsadc { + status = "okay"; +}; + +&uart2 { + pinctrl-0 = <&uart2m0_xfer>; + status = "okay"; +}; + +/* DMA seems to interfere with bluetooth device normal operation. */ +&uart9 { + pinctrl-0 = <&uart9m2_xfer>, <&uart9m2_ctsn>, <&uart9m2_rtsn>; + pinctrl-names = "default"; + /delete-property/ dma-names; + /delete-property/ dmas; + uart-has-rtscts; + status = "okay"; + + bluetooth { + compatible = "realtek,rtl8821cs-bt", + "realtek,rtl8723bs-bt"; + device-wake-gpios = <&gpio0 RK_PC6 GPIO_ACTIVE_HIGH>; + enable-gpios = <&gpio0 RK_PD4 GPIO_ACTIVE_HIGH>; + host-wake-gpios = <&gpio0 RK_PC5 GPIO_ACTIVE_HIGH>; + pinctrl-0 = <&bt_reset>, <&bt_wake_dev>, <&bt_wake_host>; + pinctrl-names = "default"; + }; +}; diff --git a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi index 657c019d27fa9a54012ccbfac0a458656ba1a92d..1576f9bfd6de04ed3324e2d1026bbb070bcb2197 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi @@ -229,6 +229,7 @@ cache-line-size = <64>; cache-sets = <512>; cache-level = <2>; + cache-unified; next-level-cache = <&l3_cache>; }; @@ -238,6 +239,7 @@ cache-line-size = <64>; cache-sets = <512>; cache-level = <2>; + cache-unified; next-level-cache = <&l3_cache>; }; @@ -247,6 +249,7 @@ cache-line-size = <64>; cache-sets = <512>; cache-level = <2>; + cache-unified; next-level-cache = <&l3_cache>; }; @@ -256,6 +259,7 @@ cache-line-size = <64>; cache-sets = <512>; cache-level = <2>; + cache-unified; next-level-cache = <&l3_cache>; }; @@ -265,6 +269,7 @@ cache-line-size = <64>; cache-sets = <1024>; cache-level = <2>; + cache-unified; next-level-cache = <&l3_cache>; }; @@ -274,6 +279,7 @@ cache-line-size = <64>; cache-sets = <1024>; cache-level = <2>; + cache-unified; next-level-cache = <&l3_cache>; }; @@ -283,6 +289,7 @@ cache-line-size = <64>; cache-sets = <1024>; cache-level = <2>; + cache-unified; next-level-cache = <&l3_cache>; }; @@ -292,6 +299,7 @@ cache-line-size = <64>; cache-sets = <1024>; cache-level = <2>; + cache-unified; next-level-cache = <&l3_cache>; }; @@ -301,6 +309,7 @@ cache-line-size = <64>; cache-sets = <4096>; cache-level = <3>; + cache-unified; }; }; @@ -1176,6 +1185,21 @@ status = "disabled"; }; + sdio: mmc@fe2d0000 { + compatible = "rockchip,rk3588-dw-mshc", "rockchip,rk3288-dw-mshc"; + reg = <0x00 0xfe2d0000 0x00 0x4000>; + interrupts = ; + clocks = <&cru HCLK_SDIO>, <&cru CCLK_SRC_SDIO>, + <&cru SCLK_SDIO_DRV>, <&cru SCLK_SDIO_SAMPLE>; + clock-names = "biu", "ciu", "ciu-drive", "ciu-sample"; + fifo-depth = <0x100>; + max-frequency = <200000000>; + pinctrl-names = "default"; + pinctrl-0 = <&sdiom1_pins>; + power-domains = <&power RK3588_PD_SDIO>; + status = "disabled"; + }; + sdhci: mmc@fe2e0000 { compatible = "rockchip,rk3588-dwcmshc"; reg = <0x0 0xfe2e0000 0x0 0x10000>; @@ -1187,6 +1211,9 @@ <&cru TMCLK_EMMC>; clock-names = "core", "bus", "axi", "block", "timer"; max-frequency = <200000000>; + pinctrl-0 = <&emmc_rstnout>, <&emmc_bus8>, <&emmc_clk>, + <&emmc_cmd>, <&emmc_data_strobe>; + pinctrl-names = "default"; resets = <&cru SRST_C_EMMC>, <&cru SRST_H_EMMC>, <&cru SRST_A_EMMC>, <&cru SRST_B_EMMC>, <&cru SRST_T_EMMC>; @@ -1300,7 +1327,24 @@ mbi-alias = <0x0 0xfe610000>; mbi-ranges = <424 56>; msi-controller; + ranges; + #address-cells = <2>; #interrupt-cells = <4>; + #size-cells = <2>; + + its0: msi-controller@fe640000 { + compatible = "arm,gic-v3-its"; + reg = <0x0 0xfe640000 0x0 0x20000>; + msi-controller; + #msi-cells = <1>; + }; + + its1: msi-controller@fe660000 { + compatible = "arm,gic-v3-its"; + reg = <0x0 0xfe660000 0x0 0x20000>; + msi-controller; + #msi-cells = <1>; + }; ppi-partitions { ppi_partition0: interrupt-partition-0 { @@ -1400,6 +1444,14 @@ status = "disabled"; }; + timer0: timer@feae0000 { + compatible = "rockchip,rk3588-timer", "rockchip,rk3288-timer"; + reg = <0x0 0xfeae0000 0x0 0x20>; + interrupts = ; + clocks = <&cru PCLK_BUSTIMER0>, <&cru CLK_BUSTIMER0>; + clock-names = "pclk", "timer"; + }; + wdt: watchdog@feaf0000 { compatible = "rockchip,rk3588-wdt", "snps,dw-wdt"; reg = <0x0 0xfeaf0000 0x0 0x100>; @@ -1759,6 +1811,18 @@ status = "disabled"; }; + saradc: adc@fec10000 { + compatible = "rockchip,rk3588-saradc"; + reg = <0x0 0xfec10000 0x0 0x10000>; + interrupts = ; + #io-channel-cells = <1>; + clocks = <&cru CLK_SARADC>, <&cru PCLK_SARADC>; + clock-names = "saradc", "apb_pclk"; + resets = <&cru SRST_P_SARADC>; + reset-names = "saradc-apb"; + status = "disabled"; + }; + i2c6: i2c@fec80000 { compatible = "rockchip,rk3588-i2c", "rockchip,rk3399-i2c"; reg = <0x0 0xfec80000 0x0 0x1000>; @@ -1814,6 +1878,60 @@ status = "disabled"; }; + otp: efuse@fecc0000 { + compatible = "rockchip,rk3588-otp"; + reg = <0x0 0xfecc0000 0x0 0x400>; + clocks = <&cru CLK_OTPC_NS>, <&cru PCLK_OTPC_NS>, + <&cru CLK_OTP_PHY_G>, <&cru CLK_OTPC_ARB>; + clock-names = "otp", "apb_pclk", "phy", "arb"; + resets = <&cru SRST_OTPC_NS>, <&cru SRST_P_OTPC_NS>, + <&cru SRST_OTPC_ARB>; + reset-names = "otp", "apb", "arb"; + #address-cells = <1>; + #size-cells = <1>; + + cpu_code: cpu-code@2 { + reg = <0x02 0x2>; + }; + + otp_id: id@7 { + reg = <0x07 0x10>; + }; + + cpub0_leakage: cpu-leakage@17 { + reg = <0x17 0x1>; + }; + + cpub1_leakage: cpu-leakage@18 { + reg = <0x18 0x1>; + }; + + cpul_leakage: cpu-leakage@19 { + reg = <0x19 0x1>; + }; + + log_leakage: log-leakage@1a { + reg = <0x1a 0x1>; + }; + + gpu_leakage: gpu-leakage@1b { + reg = <0x1b 0x1>; + }; + + otp_cpu_version: cpu-version@1c { + reg = <0x1c 0x1>; + bits = <3 3>; + }; + + npu_leakage: npu-leakage@28 { + reg = <0x28 0x1>; + }; + + codec_leakage: codec-leakage@29 { + reg = <0x29 0x1>; + }; + }; + dmac2: dma-controller@fed10000 { compatible = "arm,pl330", "arm,primecell"; reg = <0x0 0xfed10000 0x0 0x4000>; diff --git a/arch/arm64/boot/dts/socionext/uniphier-pinctrl.dtsi b/arch/arm64/boot/dts/socionext/uniphier-pinctrl.dtsi index 9caabbb8bae3fdd1d1e17ad8d63b99979aef971d..3e1132204c7d486d54ff0ac9d959a1174f172d69 100644 --- a/arch/arm64/boot/dts/socionext/uniphier-pinctrl.dtsi +++ b/arch/arm64/boot/dts/socionext/uniphier-pinctrl.dtsi @@ -1 +1 @@ -#include +#include diff --git a/arch/arm64/boot/dts/socionext/uniphier-ref-daughter.dtsi b/arch/arm64/boot/dts/socionext/uniphier-ref-daughter.dtsi index e66d999d9f5d3a1ab87fc398ef611ef4cf048be2..8afbe5ce45f2e6aac183ee956e6e84b35c536106 100644 --- a/arch/arm64/boot/dts/socionext/uniphier-ref-daughter.dtsi +++ b/arch/arm64/boot/dts/socionext/uniphier-ref-daughter.dtsi @@ -1 +1 @@ -#include +#include diff --git a/arch/arm64/boot/dts/socionext/uniphier-support-card.dtsi b/arch/arm64/boot/dts/socionext/uniphier-support-card.dtsi index 28c5b4ed1d9500fb283876ba766d826a81c44a8d..6d0e3226a966ee5bb19a73d39a8e4e7c0f10f98f 100644 --- a/arch/arm64/boot/dts/socionext/uniphier-support-card.dtsi +++ b/arch/arm64/boot/dts/socionext/uniphier-support-card.dtsi @@ -1 +1 @@ -#include +#include diff --git a/arch/arm64/boot/dts/st/Makefile b/arch/arm64/boot/dts/st/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..881fe1296c581621f1219dbfbb4b1e03179e0f6f --- /dev/null +++ b/arch/arm64/boot/dts/st/Makefile @@ -0,0 +1,2 @@ +# SPDX-License-Identifier: GPL-2.0-only +dtb-$(CONFIG_ARCH_STM32) += stm32mp257f-ev1.dtb diff --git a/arch/arm64/boot/dts/st/stm32mp25-pinctrl.dtsi b/arch/arm64/boot/dts/st/stm32mp25-pinctrl.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..d34a1d5e79c06b0e07c4d9eb21b21c1434f6cb6e --- /dev/null +++ b/arch/arm64/boot/dts/st/stm32mp25-pinctrl.dtsi @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2023 - All Rights Reserved + * Author: Alexandre Torgue for STMicroelectronics. + */ +#include + +&pinctrl { + usart2_pins_a: usart2-0 { + pins1 { + pinmux = ; /* USART2_TX */ + bias-disable; + drive-push-pull; + slew-rate = <0>; + }; + pins2 { + pinmux = ; /* USART2_RX */ + bias-disable; + }; + }; + + usart2_idle_pins_a: usart2-idle-0 { + pins1 { + pinmux = ; /* USART2_TX */ + }; + pins2 { + pinmux = ; /* USART2_RX */ + bias-disable; + }; + }; + + usart2_sleep_pins_a: usart2-sleep-0 { + pins { + pinmux = , /* USART2_TX */ + ; /* USART2_RX */ + }; + }; +}; diff --git a/arch/arm64/boot/dts/st/stm32mp251.dtsi b/arch/arm64/boot/dts/st/stm32mp251.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..5268a43218415f701a6cda93133fb297ef2f8060 --- /dev/null +++ b/arch/arm64/boot/dts/st/stm32mp251.dtsi @@ -0,0 +1,279 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2023 - All Rights Reserved + * Author: Alexandre Torgue for STMicroelectronics. + */ +#include + +/ { + #address-cells = <2>; + #size-cells = <2>; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu0: cpu@0 { + compatible = "arm,cortex-a35"; + device_type = "cpu"; + reg = <0>; + enable-method = "psci"; + }; + }; + + arm-pmu { + compatible = "arm,cortex-a35-pmu"; + interrupts = ; + interrupt-affinity = <&cpu0>; + interrupt-parent = <&intc>; + }; + + clocks { + ck_flexgen_08: ck-flexgen-08 { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <100000000>; + }; + + ck_flexgen_51: ck-flexgen-51 { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <200000000>; + }; + + ck_icn_ls_mcu: ck-icn-ls-mcu { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <200000000>; + }; + }; + + firmware { + optee { + compatible = "linaro,optee-tz"; + method = "smc"; + }; + + scmi { + compatible = "linaro,scmi-optee"; + #address-cells = <1>; + #size-cells = <0>; + linaro,optee-channel-id = <0>; + + scmi_clk: protocol@14 { + reg = <0x14>; + #clock-cells = <1>; + }; + + scmi_reset: protocol@16 { + reg = <0x16>; + #reset-cells = <1>; + }; + }; + }; + + intc: interrupt-controller@4ac00000 { + compatible = "arm,cortex-a7-gic"; + #interrupt-cells = <3>; + #address-cells = <1>; + interrupt-controller; + reg = <0x0 0x4ac10000 0x0 0x1000>, + <0x0 0x4ac20000 0x0 0x2000>, + <0x0 0x4ac40000 0x0 0x2000>, + <0x0 0x4ac60000 0x0 0x2000>; + }; + + psci { + compatible = "arm,psci-1.0"; + method = "smc"; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupt-parent = <&intc>; + interrupts = , + , + , + ; + always-on; + }; + + soc@0 { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + interrupt-parent = <&intc>; + ranges = <0x0 0x0 0x0 0x80000000>; + + rifsc: rifsc-bus@42080000 { + compatible = "simple-bus"; + reg = <0x42080000 0x1000>; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + usart2: serial@400e0000 { + compatible = "st,stm32h7-uart"; + reg = <0x400e0000 0x400>; + interrupts = ; + clocks = <&ck_flexgen_08>; + status = "disabled"; + }; + }; + + syscfg: syscon@44230000 { + compatible = "st,stm32mp25-syscfg", "syscon"; + reg = <0x44230000 0x10000>; + }; + + pinctrl: pinctrl@44240000 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "st,stm32mp257-pinctrl"; + ranges = <0 0x44240000 0xa0400>; + pins-are-numbered; + + gpioa: gpio@44240000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x0 0x400>; + clocks = <&ck_icn_ls_mcu>; + st,bank-name = "GPIOA"; + status = "disabled"; + }; + + gpiob: gpio@44250000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x10000 0x400>; + clocks = <&ck_icn_ls_mcu>; + st,bank-name = "GPIOB"; + status = "disabled"; + }; + + gpioc: gpio@44260000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x20000 0x400>; + clocks = <&ck_icn_ls_mcu>; + st,bank-name = "GPIOC"; + status = "disabled"; + }; + + gpiod: gpio@44270000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x30000 0x400>; + clocks = <&ck_icn_ls_mcu>; + st,bank-name = "GPIOD"; + status = "disabled"; + }; + + gpioe: gpio@44280000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x40000 0x400>; + clocks = <&ck_icn_ls_mcu>; + st,bank-name = "GPIOE"; + status = "disabled"; + }; + + gpiof: gpio@44290000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x50000 0x400>; + clocks = <&ck_icn_ls_mcu>; + st,bank-name = "GPIOF"; + status = "disabled"; + }; + + gpiog: gpio@442a0000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x60000 0x400>; + clocks = <&ck_icn_ls_mcu>; + st,bank-name = "GPIOG"; + status = "disabled"; + }; + + gpioh: gpio@442b0000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x70000 0x400>; + clocks = <&ck_icn_ls_mcu>; + st,bank-name = "GPIOH"; + status = "disabled"; + }; + + gpioi: gpio@442c0000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x80000 0x400>; + clocks = <&ck_icn_ls_mcu>; + st,bank-name = "GPIOI"; + status = "disabled"; + }; + + gpioj: gpio@442d0000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x90000 0x400>; + clocks = <&ck_icn_ls_mcu>; + st,bank-name = "GPIOJ"; + status = "disabled"; + }; + + gpiok: gpio@442e0000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0xa0000 0x400>; + clocks = <&ck_icn_ls_mcu>; + st,bank-name = "GPIOK"; + status = "disabled"; + }; + }; + + pinctrl_z: pinctrl@46200000 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "st,stm32mp257-z-pinctrl"; + ranges = <0 0x46200000 0x400>; + pins-are-numbered; + + gpioz: gpio@46200000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0 0x400>; + clocks = <&ck_icn_ls_mcu>; + st,bank-name = "GPIOZ"; + st,bank-ioport = <11>; + status = "disabled"; + }; + + }; + }; +}; diff --git a/arch/arm64/boot/dts/st/stm32mp253.dtsi b/arch/arm64/boot/dts/st/stm32mp253.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..af48e82efe8a9abeee671b6d31d8460d4987c194 --- /dev/null +++ b/arch/arm64/boot/dts/st/stm32mp253.dtsi @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2023 - All Rights Reserved + * Author: Alexandre Torgue for STMicroelectronics. + */ +#include "stm32mp251.dtsi" + +/ { + cpus { + cpu1: cpu@1 { + compatible = "arm,cortex-a35"; + device_type = "cpu"; + reg = <1>; + enable-method = "psci"; + }; + }; + + arm-pmu { + interrupts = , + ; + interrupt-affinity = <&cpu0>, <&cpu1>; + }; +}; diff --git a/arch/arm64/boot/dts/st/stm32mp255.dtsi b/arch/arm64/boot/dts/st/stm32mp255.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..e6fa596211f5c0aa5f5b8e338fd354e5ae0ee213 --- /dev/null +++ b/arch/arm64/boot/dts/st/stm32mp255.dtsi @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2023 - All Rights Reserved + * Author: Alexandre Torgue for STMicroelectronics. + */ +#include "stm32mp253.dtsi" + +/ { +}; diff --git a/arch/arm64/boot/dts/st/stm32mp257.dtsi b/arch/arm64/boot/dts/st/stm32mp257.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..5c5000d3d9dbc2064c3f3aad3a349403a64027f4 --- /dev/null +++ b/arch/arm64/boot/dts/st/stm32mp257.dtsi @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2023 - All Rights Reserved + * Author: Alexandre Torgue for STMicroelectronics. + */ +#include "stm32mp255.dtsi" + +/ { +}; diff --git a/arch/arm64/boot/dts/st/stm32mp257f-ev1.dts b/arch/arm64/boot/dts/st/stm32mp257f-ev1.dts new file mode 100644 index 0000000000000000000000000000000000000000..39b4726cc0986867b09c50f8322e0806fe675c81 --- /dev/null +++ b/arch/arm64/boot/dts/st/stm32mp257f-ev1.dts @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2023 - All Rights Reserved + * Author: Alexandre Torgue for STMicroelectronics. + */ + +/dts-v1/; + +#include "stm32mp257.dtsi" +#include "stm32mp25xf.dtsi" +#include "stm32mp25-pinctrl.dtsi" +#include "stm32mp25xxai-pinctrl.dtsi" + +/ { + model = "STMicroelectronics STM32MP257F-EV1 Evaluation Board"; + compatible = "st,stm32mp257f-ev1", "st,stm32mp257"; + + aliases { + serial0 = &usart2; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + memory@80000000 { + device_type = "memory"; + reg = <0x0 0x80000000 0x1 0x0>; + }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + + fw@80000000 { + compatible = "shared-dma-pool"; + reg = <0x0 0x80000000 0x0 0x4000000>; + no-map; + }; + }; +}; + +&usart2 { + pinctrl-names = "default", "idle", "sleep"; + pinctrl-0 = <&usart2_pins_a>; + pinctrl-1 = <&usart2_idle_pins_a>; + pinctrl-2 = <&usart2_sleep_pins_a>; + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/st/stm32mp25xc.dtsi b/arch/arm64/boot/dts/st/stm32mp25xc.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..5e83a6926485f82c911b5553c42927ea5b7b8a0a --- /dev/null +++ b/arch/arm64/boot/dts/st/stm32mp25xc.dtsi @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2023 - All Rights Reserved + * Author: Alexandre Torgue for STMicroelectronics. + */ + +/ { +}; diff --git a/arch/arm64/boot/dts/st/stm32mp25xf.dtsi b/arch/arm64/boot/dts/st/stm32mp25xf.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..5e83a6926485f82c911b5553c42927ea5b7b8a0a --- /dev/null +++ b/arch/arm64/boot/dts/st/stm32mp25xf.dtsi @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2023 - All Rights Reserved + * Author: Alexandre Torgue for STMicroelectronics. + */ + +/ { +}; diff --git a/arch/arm64/boot/dts/st/stm32mp25xxai-pinctrl.dtsi b/arch/arm64/boot/dts/st/stm32mp25xxai-pinctrl.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..abdbc7aebc7f152b36ddd7612ac162e95cd260fc --- /dev/null +++ b/arch/arm64/boot/dts/st/stm32mp25xxai-pinctrl.dtsi @@ -0,0 +1,83 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2023 - All Rights Reserved + * Author: Alexandre Torgue for STMicroelectronics. + */ + +&pinctrl { + st,package = ; + + gpioa: gpio@44240000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 0 16>; + }; + + gpiob: gpio@44250000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 16 16>; + }; + + gpioc: gpio@44260000 { + status = "okay"; + ngpios = <14>; + gpio-ranges = <&pinctrl 0 32 14>; + }; + + gpiod: gpio@44270000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 48 16>; + }; + + gpioe: gpio@44280000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 64 16>; + }; + + gpiof: gpio@44290000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 80 16>; + }; + + gpiog: gpio@442a0000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 96 16>; + }; + + gpioh: gpio@442b0000 { + status = "okay"; + ngpios = <12>; + gpio-ranges = <&pinctrl 2 114 12>; + }; + + gpioi: gpio@442c0000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 128 16>; + }; + + gpioj: gpio@442d0000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 144 16>; + }; + + gpiok: gpio@442e0000 { + status = "okay"; + ngpios = <8>; + gpio-ranges = <&pinctrl 0 160 8>; + }; +}; + +&pinctrl_z { + gpioz: gpio@46200000 { + status = "okay"; + ngpios = <10>; + gpio-ranges = <&pinctrl_z 0 400 10>; + }; +}; diff --git a/arch/arm64/boot/dts/st/stm32mp25xxak-pinctrl.dtsi b/arch/arm64/boot/dts/st/stm32mp25xxak-pinctrl.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..2e0d4d349d143cd3f67a39a2eb3d366774a965dc --- /dev/null +++ b/arch/arm64/boot/dts/st/stm32mp25xxak-pinctrl.dtsi @@ -0,0 +1,71 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2023 - All Rights Reserved + * Author: Alexandre Torgue for STMicroelectronics. + */ + +&pinctrl { + st,package = ; + + gpioa: gpio@44240000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 0 16>; + }; + + gpiob: gpio@44250000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 16 16>; + }; + + gpioc: gpio@44260000 { + status = "okay"; + ngpios = <14>; + gpio-ranges = <&pinctrl 0 32 14>; + }; + + gpiod: gpio@44270000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 48 16>; + }; + + gpioe: gpio@44280000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 64 16>; + }; + + gpiof: gpio@44290000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 80 16>; + }; + + gpiog: gpio@442a0000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 96 16>; + }; + + gpioh: gpio@442b0000 { + status = "okay"; + ngpios = <12>; + gpio-ranges = <&pinctrl 2 114 12>; + }; + + gpioi: gpio@442c0000 { + status = "okay"; + ngpios = <12>; + gpio-ranges = <&pinctrl 0 128 12>; + }; +}; + +&pinctrl_z { + gpioz: gpio@46200000 { + status = "okay"; + ngpios = <10>; + gpio-ranges = <&pinctrl_z 0 400 10>; + }; +}; diff --git a/arch/arm64/boot/dts/st/stm32mp25xxal-pinctrl.dtsi b/arch/arm64/boot/dts/st/stm32mp25xxal-pinctrl.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..2406e972554c1a56bdb27cd6bb97d777dfc8f8f6 --- /dev/null +++ b/arch/arm64/boot/dts/st/stm32mp25xxal-pinctrl.dtsi @@ -0,0 +1,71 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2023 - All Rights Reserved + * Author: Alexandre Torgue for STMicroelectronics. + */ + +&pinctrl { + st,package = ; + + gpioa: gpio@44240000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 0 16>; + }; + + gpiob: gpio@44250000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 16 16>; + }; + + gpioc: gpio@44260000 { + status = "okay"; + ngpios = <14>; + gpio-ranges = <&pinctrl 0 32 14>; + }; + + gpiod: gpio@44270000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 48 16>; + }; + + gpioe: gpio@44280000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 64 16>; + }; + + gpiof: gpio@44290000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 80 16>; + }; + + gpiog: gpio@442a0000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 96 16>; + }; + + gpioh: gpio@442b0000 { + status = "okay"; + ngpios = <12>; + gpio-ranges = <&pinctrl 2 114 12>; + }; + + gpioi: gpio@442c0000 { + status = "okay"; + ngpios = <12>; + gpio-ranges = <&pinctrl 0 128 12>; + }; +}; + +&pinctrl_z { + gpioz: gpio@46200000 { + status = "okay"; + ngpios = <10>; + gpio-ranges = <&pinctrl_z 0 400 10>; + }; +}; diff --git a/arch/arm64/boot/dts/synaptics/berlin4ct.dtsi b/arch/arm64/boot/dts/synaptics/berlin4ct.dtsi index dc12350b9fc8917fa05d872a548c62ac0d1c29de..53d616c3cfed793cf0e0a44e04999ed47fc24cf7 100644 --- a/arch/arm64/boot/dts/synaptics/berlin4ct.dtsi +++ b/arch/arm64/boot/dts/synaptics/berlin4ct.dtsi @@ -64,6 +64,8 @@ l2: cache { compatible = "cache"; + cache-level = <2>; + cache-unified; }; idle-states { diff --git a/arch/arm64/boot/dts/ti/Makefile b/arch/arm64/boot/dts/ti/Makefile index c83c9d772b81ccaeb4fde992b92521a4d59a3737..6dd7b6f1d6ab50f3664f8de9735d66656a54fe10 100644 --- a/arch/arm64/boot/dts/ti/Makefile +++ b/arch/arm64/boot/dts/ti/Makefile @@ -10,7 +10,14 @@ # Boards with AM62x SoC dtb-$(CONFIG_ARCH_K3) += k3-am625-beagleplay.dtb +dtb-$(CONFIG_ARCH_K3) += k3-am625-phyboard-lyra-rdk.dtb dtb-$(CONFIG_ARCH_K3) += k3-am625-sk.dtb +dtb-$(CONFIG_ARCH_K3) += k3-am625-verdin-nonwifi-dahlia.dtb +dtb-$(CONFIG_ARCH_K3) += k3-am625-verdin-nonwifi-dev.dtb +dtb-$(CONFIG_ARCH_K3) += k3-am625-verdin-nonwifi-yavia.dtb +dtb-$(CONFIG_ARCH_K3) += k3-am625-verdin-wifi-dahlia.dtb +dtb-$(CONFIG_ARCH_K3) += k3-am625-verdin-wifi-dev.dtb +dtb-$(CONFIG_ARCH_K3) += k3-am625-verdin-wifi-yavia.dtb dtb-$(CONFIG_ARCH_K3) += k3-am62-lp-sk.dtb # Boards with AM62Ax SoC @@ -22,12 +29,14 @@ dtb-$(CONFIG_ARCH_K3) += k3-am642-phyboard-electra-rdk.dtb dtb-$(CONFIG_ARCH_K3) += k3-am642-sk.dtb # Boards with AM65x SoC +k3-am654-gp-evm-dtbs := k3-am654-base-board.dtb k3-am654-base-board-rocktech-rk101-panel.dtbo dtb-$(CONFIG_ARCH_K3) += k3-am6528-iot2050-basic.dtb dtb-$(CONFIG_ARCH_K3) += k3-am6528-iot2050-basic-pg2.dtb dtb-$(CONFIG_ARCH_K3) += k3-am6548-iot2050-advanced.dtb dtb-$(CONFIG_ARCH_K3) += k3-am6548-iot2050-advanced-m2.dtb dtb-$(CONFIG_ARCH_K3) += k3-am6548-iot2050-advanced-pg2.dtb dtb-$(CONFIG_ARCH_K3) += k3-am654-base-board.dtb +dtb-$(CONFIG_ARCH_K3) += k3-am654-gp-evm.dtb # Boards with J7200 SoC k3-j7200-evm-dtbs := k3-j7200-common-proc-board.dtb k3-j7200-evm-quad-port-eth-exp.dtbo diff --git a/arch/arm64/boot/dts/ti/k3-am62-lp-sk.dts b/arch/arm64/boot/dts/ti/k3-am62-lp-sk.dts index 4b94f7a863166a9b11a823fe7af6d038944f3dcb..5e6feb8cd12552d9aec896d7d5ce5379911e8272 100644 --- a/arch/arm64/boot/dts/ti/k3-am62-lp-sk.dts +++ b/arch/arm64/boot/dts/ti/k3-am62-lp-sk.dts @@ -73,19 +73,19 @@ }; &main_pmx0 { - vddshv_sdio_pins_default: vddshv-sdio-pins-default { + vddshv_sdio_pins_default: vddshv-sdio-default-pins { pinctrl-single,pins = < AM62X_IOPAD(0x07c, PIN_OUTPUT, 7) /* (M19) GPMC0_CLK.GPIO0_31 */ >; }; - main_gpio1_ioexp_intr_pins_default: main-gpio1-ioexp-intr-pins-default { + main_gpio1_ioexp_intr_pins_default: main-gpio1-ioexp-intr-default-pins { pinctrl-single,pins = < AM62X_IOPAD(0x01d4, PIN_INPUT, 7) /* (C13) UART0_RTSn.GPIO1_23 */ >; }; - pmic_irq_pins_default: pmic-irq-pins-default { + pmic_irq_pins_default: pmic-irq-default-pins { pinctrl-single,pins = < AM62X_IOPAD(0x01f4, PIN_INPUT, 0) /* (B16) EXTINTn */ >; diff --git a/arch/arm64/boot/dts/ti/k3-am62-main.dtsi b/arch/arm64/boot/dts/ti/k3-am62-main.dtsi index b3e4857bbbe471722d24e2e939e0e685625a7457..2488e3a537fe4d0acad4ee18fd2d77861e1b59b6 100644 --- a/arch/arm64/boot/dts/ti/k3-am62-main.dtsi +++ b/arch/arm64/boot/dts/ti/k3-am62-main.dtsi @@ -184,6 +184,21 @@ dma-names = "tx", "rx1", "rx2"; }; + secure_proxy_sa3: mailbox@43600000 { + compatible = "ti,am654-secure-proxy"; + #mbox-cells = <1>; + reg-names = "target_data", "rt", "scfg"; + reg = <0x00 0x43600000 0x00 0x10000>, + <0x00 0x44880000 0x00 0x20000>, + <0x00 0x44860000 0x00 0x20000>; + /* + * Marked Disabled: + * Node is incomplete as it is meant for bootloaders and + * firmware on non-MPU processors + */ + status = "disabled"; + }; + main_pmx0: pinctrl@f4000 { compatible = "pinctrl-single"; reg = <0x00 0xf4000 0x00 0x2ac>; @@ -192,6 +207,12 @@ pinctrl-single,function-mask = <0xffffffff>; }; + main_esm: esm@420000 { + compatible = "ti,j721e-esm"; + reg = <0x00 0x420000 0x00 0x1000>; + ti,esm-pins = <160>, <161>, <162>, <163>, <177>, <178>; + }; + main_timer0: timer@2400000 { compatible = "ti,am654-timer"; reg = <0x00 0x2400000 0x00 0x400>; diff --git a/arch/arm64/boot/dts/ti/k3-am62-mcu.dtsi b/arch/arm64/boot/dts/ti/k3-am62-mcu.dtsi index 076601a41e8432f0d58b63322cac89ef6dc79cff..19fc38157d94e45f7dc19c73f3d0b77fd5bcdec4 100644 --- a/arch/arm64/boot/dts/ti/k3-am62-mcu.dtsi +++ b/arch/arm64/boot/dts/ti/k3-am62-mcu.dtsi @@ -14,6 +14,12 @@ pinctrl-single,function-mask = <0xffffffff>; }; + mcu_esm: esm@4100000 { + compatible = "ti,j721e-esm"; + reg = <0x00 0x4100000 0x00 0x1000>; + ti,esm-pins = <0>, <1>, <2>, <85>; + }; + /* * The MCU domain timer interrupts are routed only to the ESM module, * and not currently available for Linux. The MCU domain timers are diff --git a/arch/arm64/boot/dts/ti/k3-am62-phycore-som.dtsi b/arch/arm64/boot/dts/ti/k3-am62-phycore-som.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..aa43e7407eee43df8b5c06cc3194e997c3c4a3a7 --- /dev/null +++ b/arch/arm64/boot/dts/ti/k3-am62-phycore-som.dtsi @@ -0,0 +1,324 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2022 - 2023 PHYTEC Messtechnik GmbH + * Author: Wadim Egorov + * + * Product homepage: + * https://www.phytec.com/product/phycore-am62x + */ + +#include +#include +#include + +/ { + model = "PHYTEC phyCORE-AM62x"; + compatible = "phytec,am62-phycore-som", "ti,am625"; + + aliases { + ethernet0 = &cpsw_port1; + gpio0 = &main_gpio0; + gpio1 = &main_gpio1; + i2c0 = &main_i2c0; + mmc0 = &sdhci0; + rtc0 = &i2c_som_rtc; + rtc1 = &wkup_rtc0; + spi0 = &ospi0; + }; + + memory@80000000 { + device_type = "memory"; + reg = <0x00000000 0x80000000 0x00000000 0x80000000>; + }; + + reserved_memory: reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + + ramoops@9ca00000 { + compatible = "ramoops"; + reg = <0x00 0x9ca00000 0x00 0x00100000>; + record-size = <0x8000>; + console-size = <0x8000>; + ftrace-size = <0x00>; + pmsg-size = <0x8000>; + }; + + secure_tfa_ddr: tfa@9e780000 { + reg = <0x00 0x9e780000 0x00 0x80000>; + alignment = <0x1000>; + no-map; + }; + + secure_ddr: optee@9e800000 { + reg = <0x00 0x9e800000 0x00 0x01800000>; /* for OP-TEE */ + alignment = <0x1000>; + no-map; + }; + + wkup_r5fss0_core0_dma_memory_region: r5f-dma-memory@9db00000 { + compatible = "shared-dma-pool"; + reg = <0x00 0x9db00000 0x00 0x00c00000>; + no-map; + }; + }; + + vcc_5v0_som: regulator-vcc-5v0-som { + compatible = "regulator-fixed"; + regulator-name = "VCC_5V0_SOM"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-always-on; + regulator-boot-on; + }; + + vdd_1v8: regulator-vdd-1v8 { + compatible = "regulator-fixed"; + regulator-name = "VDD_1V8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + vin-supply = <&vcc_5v0_som>; + regulator-always-on; + regulator-boot-on; + }; + + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&leds_pins_default>; + + led-0 { + color = ; + gpios = <&main_gpio0 13 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "heartbeat"; + function = LED_FUNCTION_HEARTBEAT; + }; + }; +}; + +&main_pmx0 { + leds_pins_default: leds-default-pins { + pinctrl-single,pins = < + AM62X_IOPAD(0x034, PIN_OUTPUT, 7) /* (H21) OSPI0_CSN2.GPIO0_13 */ + >; + }; + + main_i2c0_pins_default: main-i2c0-default-pins { + pinctrl-single,pins = < + AM62X_IOPAD(0x1e0, PIN_INPUT_PULLUP, 0) /* (B16) I2C0_SCL */ + AM62X_IOPAD(0x1e4, PIN_INPUT_PULLUP, 0) /* (A16) I2C0_SDA */ + >; + }; + + main_mdio1_pins_default: main-mdio1-default-pins { + pinctrl-single,pins = < + AM62X_IOPAD(0x160, PIN_OUTPUT, 0) /* (AD24) MDIO0_MDC */ + AM62X_IOPAD(0x15c, PIN_INPUT, 0) /* (AB22) MDIO0_MDIO */ + >; + }; + + main_mmc0_pins_default: main-mmc0-default-pins { + pinctrl-single,pins = < + AM62X_IOPAD(0x220, PIN_INPUT_PULLUP, 0) /* (Y3) MMC0_CMD */ + AM62X_IOPAD(0x218, PIN_INPUT_PULLDOWN, 0) /* (AB1) MMC0_CLK */ + AM62X_IOPAD(0x214, PIN_INPUT_PULLUP, 0) /* (AA2) MMC0_DAT0 */ + AM62X_IOPAD(0x210, PIN_INPUT_PULLUP, 0) /* (AA1) MMC0_DAT1 */ + AM62X_IOPAD(0x20c, PIN_INPUT_PULLUP, 0) /* (AA3) MMC0_DAT2 */ + AM62X_IOPAD(0x208, PIN_INPUT_PULLUP, 0) /* (Y4) MMC0_DAT3 */ + AM62X_IOPAD(0x204, PIN_INPUT_PULLUP, 0) /* (AB2) MMC0_DAT4 */ + AM62X_IOPAD(0x200, PIN_INPUT_PULLUP, 0) /* (AC1) MMC0_DAT5 */ + AM62X_IOPAD(0x1fc, PIN_INPUT_PULLUP, 0) /* (AD2) MMC0_DAT6 */ + AM62X_IOPAD(0x1f8, PIN_INPUT_PULLUP, 0) /* (AC2) MMC0_DAT7 */ + >; + }; + + main_rgmii1_pins_default: main-rgmii1-default-pins { + pinctrl-single,pins = < + AM62X_IOPAD(0x14c, PIN_INPUT, 0) /* (AB17) RGMII1_RD0 */ + AM62X_IOPAD(0x150, PIN_INPUT, 0) /* (AC17) RGMII1_RD1 */ + AM62X_IOPAD(0x154, PIN_INPUT, 0) /* (AB16) RGMII1_RD2 */ + AM62X_IOPAD(0x158, PIN_INPUT, 0) /* (AA15) RGMII1_RD3 */ + AM62X_IOPAD(0x148, PIN_INPUT, 0) /* (AD17) RGMII1_RXC */ + AM62X_IOPAD(0x144, PIN_INPUT, 0) /* (AE17) RGMII1_RX_CTL */ + AM62X_IOPAD(0x134, PIN_OUTPUT, 0) /* (AE20) RGMII1_TD0 */ + AM62X_IOPAD(0x138, PIN_OUTPUT, 0) /* (AD20) RGMII1_TD1 */ + AM62X_IOPAD(0x13c, PIN_OUTPUT, 0) /* (AE18) RGMII1_TD2 */ + AM62X_IOPAD(0x140, PIN_OUTPUT, 0) /* (AD18) RGMII1_TD3 */ + AM62X_IOPAD(0x130, PIN_OUTPUT, 0) /* (AE19) RGMII1_TXC */ + AM62X_IOPAD(0x12c, PIN_OUTPUT, 0) /* (AD19) RGMII1_TX_CTL */ + >; + }; + + ospi0_pins_default: ospi0-default-pins { + pinctrl-single,pins = < + AM62X_IOPAD(0x000, PIN_OUTPUT, 0) /* (H24) OSPI0_CLK */ + AM62X_IOPAD(0x02c, PIN_OUTPUT, 0) /* (F23) OSPI0_CSn0 */ + AM62X_IOPAD(0x00c, PIN_INPUT, 0) /* (E25) OSPI0_D0 */ + AM62X_IOPAD(0x010, PIN_INPUT, 0) /* (G24) OSPI0_D1 */ + AM62X_IOPAD(0x014, PIN_INPUT, 0) /* (F25) OSPI0_D2 */ + AM62X_IOPAD(0x018, PIN_INPUT, 0) /* (F24) OSPI0_D3 */ + AM62X_IOPAD(0x01c, PIN_INPUT, 0) /* (J23) OSPI0_D4 */ + AM62X_IOPAD(0x020, PIN_INPUT, 0) /* (J25) OSPI0_D5 */ + AM62X_IOPAD(0x024, PIN_INPUT, 0) /* (H25) OSPI0_D6 */ + AM62X_IOPAD(0x028, PIN_INPUT, 0) /* (J22) OSPI0_D7 */ + AM62X_IOPAD(0x008, PIN_INPUT, 0) /* (J24) OSPI0_DQS */ + >; + }; + + pmic_irq_pins_default: pmic-irq-default-pins { + pinctrl-single,pins = < + AM62X_IOPAD(0x01f4, PIN_INPUT, 0) /* (D16) EXTINTn */ + >; + }; +}; + +&cpsw3g { + pinctrl-names = "default"; + pinctrl-0 = <&main_rgmii1_pins_default>; +}; + +&cpsw_port1 { + phy-mode = "rgmii-rxid"; + phy-handle = <&cpsw3g_phy1>; +}; + +&cpsw3g_mdio { + pinctrl-names = "default"; + pinctrl-0 = <&main_mdio1_pins_default>; + status = "okay"; + + cpsw3g_phy1: ethernet-phy@1 { + compatible = "ethernet-phy-id2000.a231", "ethernet-phy-ieee802.3-c22"; + reg = <1>; + ti,rx-internal-delay = ; + ti,fifo-depth = ; + }; +}; + +&main_i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&main_i2c0_pins_default>; + clock-frequency = <400000>; + status = "okay"; + + pmic@30 { + compatible = "ti,tps65219"; + reg = <0x30>; + buck1-supply = <&vcc_5v0_som>; + buck2-supply = <&vcc_5v0_som>; + buck3-supply = <&vcc_5v0_som>; + ldo1-supply = <&vdd_3v3>; + ldo2-supply = <&vdd_1v8>; + ldo3-supply = <&vcc_5v0_som>; + ldo4-supply = <&vcc_5v0_som>; + + pinctrl-names = "default"; + pinctrl-0 = <&pmic_irq_pins_default>; + interrupt-parent = <&gic500>; + interrupts = ; + interrupt-controller; + #interrupt-cells = <1>; + + ti,power-button; + system-power-controller; + + regulators { + vdd_core: buck1 { + regulator-name = "VDD_CORE"; + regulator-min-microvolt = <750000>; + regulator-max-microvolt = <750000>; + regulator-boot-on; + regulator-always-on; + }; + + vdd_3v3: buck2 { + regulator-name = "VDD_3V3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + regulator-always-on; + }; + + vdd_ddr4: buck3 { + regulator-name = "VDD_DDR4"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-boot-on; + regulator-always-on; + }; + + vddshv5_sdio: ldo1 { + regulator-name = "VDDSHV5_SDIO"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-allow-bypass; + regulator-boot-on; + regulator-always-on; + }; + + vddr_core: ldo2 { + regulator-name = "VDDR_CORE"; + regulator-min-microvolt = <850000>; + regulator-max-microvolt = <850000>; + regulator-boot-on; + regulator-always-on; + }; + + vdda_1v8: ldo3 { + regulator-name = "VDDA_1V8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-boot-on; + regulator-always-on; + }; + + vdd_2v5: ldo4 { + regulator-name = "VDD_2V5"; + regulator-min-microvolt = <2500000>; + regulator-max-microvolt = <2500000>; + regulator-boot-on; + regulator-always-on; + }; + }; + }; + + eeprom@50 { + compatible = "atmel,24c32"; + pagesize = <32>; + reg = <0x50>; + }; + + i2c_som_rtc: rtc@52 { + compatible = "microcrystal,rv3028"; + reg = <0x52>; + }; +}; + +&ospi0 { + pinctrl-names = "default"; + pinctrl-0 = <&ospi0_pins_default>; + status = "okay"; + + serial_flash: flash@0 { + compatible = "jedec,spi-nor"; + reg = <0x0>; + spi-tx-bus-width = <8>; + spi-rx-bus-width = <8>; + spi-max-frequency = <25000000>; + cdns,tshsl-ns = <60>; + cdns,tsd2d-ns = <60>; + cdns,tchsh-ns = <60>; + cdns,tslch-ns = <60>; + cdns,read-delay = <0>; + }; +}; + +&sdhci0 { + pinctrl-names = "default"; + pinctrl-0 = <&main_mmc0_pins_default>; + ti,driver-strength-ohm = <50>; + disable-wp; + non-removable; + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/ti/k3-am62-thermal.dtsi b/arch/arm64/boot/dts/ti/k3-am62-thermal.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..a358757e26f07b8fb470b955d6340ae41d9ad1a8 --- /dev/null +++ b/arch/arm64/boot/dts/ti/k3-am62-thermal.dtsi @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include + +thermal_zones: thermal-zones { + main0_thermal: main0-thermal { + polling-delay-passive = <250>; /* milliSeconds */ + polling-delay = <500>; /* milliSeconds */ + thermal-sensors = <&wkup_vtm0 0>; + + trips { + main0_crit: main0-crit { + temperature = <105000>; /* milliCelsius */ + hysteresis = <2000>; /* milliCelsius */ + type = "critical"; + }; + }; + }; + + main1_thermal: main1-thermal { + polling-delay-passive = <250>; /* milliSeconds */ + polling-delay = <500>; /* milliSeconds */ + thermal-sensors = <&wkup_vtm0 1>; + + trips { + main1_crit: main1-crit { + temperature = <105000>; /* milliCelsius */ + hysteresis = <2000>; /* milliCelsius */ + type = "critical"; + }; + }; + }; +}; diff --git a/arch/arm64/boot/dts/ti/k3-am62-verdin-dahlia.dtsi b/arch/arm64/boot/dts/ti/k3-am62-verdin-dahlia.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..3abd8d1d6761efeeb778a93900a998b367d960e4 --- /dev/null +++ b/arch/arm64/boot/dts/ti/k3-am62-verdin-dahlia.dtsi @@ -0,0 +1,161 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT +/* + * Copyright 2023 Toradex + * + * Common dtsi for Verdin AM62 SoM on Dahlia carrier board + * + * https://www.toradex.com/computer-on-modules/verdin-arm-family/ti-am62 + * https://www.toradex.com/products/carrier-board/dahlia-carrier-board-kit + */ + +/* Verdin ETHs */ +&cpsw3g { + status = "okay"; +}; + +/* MDIO, shared by Verdin ETH_1 (On-module PHY) and Verdin ETH_2_RGMII */ +&cpsw3g_mdio { + status = "okay"; +}; + +/* Verdin ETH_1 (On-module PHY) */ +&cpsw_port1 { + status = "okay"; +}; + +/* Verdin PWM_1, PWM_2 */ +&epwm0 { + status = "okay"; +}; + +/* Verdin PWM_3_DSI */ +&epwm1 { + status = "okay"; +}; + +&main_gpio0 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_ctrl_sleep_moci>, + <&pinctrl_gpio_5>, + <&pinctrl_gpio_6>, + <&pinctrl_gpio_7>, + <&pinctrl_gpio_8>; +}; + +/* Verdin I2C_1 */ +&main_i2c1 { + status = "okay"; + + /* Current measurement into module VCC */ + hwmon@40 { + compatible = "ti,ina219"; + reg = <0x40>; + shunt-resistor = <10000>; + }; + + /* Temperature sensor */ + sensor@4f { + compatible = "ti,tmp75c"; + reg = <0x4f>; + }; + + /* EEPROM */ + eeprom@57 { + compatible = "st,24c02"; + reg = <0x57>; + pagesize = <16>; + }; +}; + +/* Verdin I2C_2_DSI */ +&main_i2c2 { + status = "okay"; +}; + +/* Verdin I2C_4_CSI */ +&main_i2c3 { + status = "okay"; +}; + +/* Verdin CAN_1 */ +&main_mcan0 { + status = "okay"; +}; + +/* Verdin SPI_1 */ +&main_spi1 { + status = "okay"; +}; + +/* Verdin UART_3 */ +&main_uart0 { + status = "okay"; +}; + +/* Verdin UART_1 */ +&main_uart1 { + status = "okay"; +}; + +/* Verdin I2S_1 */ +&mcasp0 { + status = "okay"; +}; + +&mcu_gpio0 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_gpio_1>, + <&pinctrl_gpio_2>, + <&pinctrl_gpio_3>, + <&pinctrl_gpio_4>; +}; + +/* Verdin I2C_3_HDMI */ +&mcu_i2c0 { + status = "okay"; +}; + +/* Verdin UART_4 */ +&mcu_uart0 { + status = "okay"; +}; + +/* Verdin QSPI_1 */ +&ospi0 { + status = "okay"; +}; + +/* Verdin SD_1 */ +&sdhci1 { + ti,driver-strength-ohm = <33>; + status = "okay"; +}; + +/* Verdin USB_1 */ +&usbss0 { + status = "okay"; +}; + +&usb0 { + status = "okay"; +}; + +/* Verdin USB_2 */ +&usbss1 { + status = "okay"; +}; + +&usb1 { + status = "okay"; +}; + +/* Verdin CTRL_WAKE1_MICO# */ +&verdin_gpio_keys { + status = "okay"; +}; + +/* Verdin UART_2 */ +&wkup_uart0 { + /* FIXME: WKUP UART0 is used by DM firmware */ + status = "reserved"; +}; diff --git a/arch/arm64/boot/dts/ti/k3-am62-verdin-dev.dtsi b/arch/arm64/boot/dts/ti/k3-am62-verdin-dev.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..846caee7dfa418c90ede8bea98cbfb6034d14ed3 --- /dev/null +++ b/arch/arm64/boot/dts/ti/k3-am62-verdin-dev.dtsi @@ -0,0 +1,190 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT +/* + * Copyright 2023 Toradex + * + * Common dtsi for Verdin AM62 SoM on Development carrier board + * + * https://www.toradex.com/computer-on-modules/verdin-arm-family/ti-am62 + * https://www.toradex.com/products/carrier-board/verdin-development-board-kit + */ + +/* Verdin ETHs */ +&cpsw3g { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_rgmii1>, <&pinctrl_rgmii2>; + status = "okay"; +}; + +/* MDIO, shared by Verdin ETH_1 (On-module PHY) and Verdin ETH_2_RGMII */ +&cpsw3g_mdio { + status = "okay"; + + cpsw3g_phy1: ethernet-phy@7 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <7>; + interrupt-parent = <&main_gpio0>; + interrupts = <38 IRQ_TYPE_EDGE_FALLING>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_eth2_rgmii_int>; + micrel,led-mode = <0>; + }; +}; + +/* Verdin ETH_1 (On-module PHY) */ +&cpsw_port1 { + status = "okay"; +}; + +/* Verdin ETH_2_RGMII */ +&cpsw_port2 { + phy-handle = <&cpsw3g_phy1>; + phy-mode = "rgmii-rxid"; + status = "okay"; +}; + +/* Verdin PWM_1, PWM_2 */ +&epwm0 { + status = "okay"; +}; + +/* Verdin PWM_3_DSI */ +&epwm1 { + status = "okay"; +}; + +&main_gpio0 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_ctrl_sleep_moci>, + <&pinctrl_gpio_5>, + <&pinctrl_gpio_6>, + <&pinctrl_gpio_7>, + <&pinctrl_gpio_8>; +}; + +/* Verdin I2C_1 */ +&main_i2c1 { + status = "okay"; + + /* IO Expander */ + gpio_expander_21: gpio@21 { + compatible = "nxp,pcal6416"; + reg = <0x21>; + #gpio-cells = <2>; + gpio-controller; + }; + + /* Current measurement into module VCC */ + hwmon@40 { + compatible = "ti,ina219"; + reg = <0x40>; + shunt-resistor = <10000>; + }; + + /* Temperature sensor */ + sensor@4f { + compatible = "ti,tmp75c"; + reg = <0x4f>; + }; + + /* EEPROM */ + eeprom@57 { + compatible = "st,24c02", "atmel,24c02"; + reg = <0x57>; + pagesize = <16>; + }; +}; + +/* Verdin I2C_2_DSI */ +&main_i2c2 { + status = "okay"; +}; + +/* Verdin I2C_4_CSI */ +&main_i2c3 { + status = "okay"; +}; + +/* Verdin CAN_1 */ +&main_mcan0 { + status = "okay"; +}; + +/* Verdin SPI_1 */ +&main_spi1 { + status = "okay"; +}; + +/* Verdin UART_3 */ +&main_uart0 { + status = "okay"; +}; + +/* Verdin UART_1, connector X50 through RS485 transceiver. */ +&main_uart1 { + linux,rs485-enabled-at-boot-time; + rs485-rx-during-tx; + status = "okay"; +}; + +/* Verdin I2S_1 */ +&mcasp0 { + status = "okay"; +}; + +&mcu_gpio0 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_gpio_1>, + <&pinctrl_gpio_2>, + <&pinctrl_gpio_3>, + <&pinctrl_gpio_4>; +}; + +/* Verdin I2C_3_HDMI */ +&mcu_i2c0 { + status = "okay"; +}; + +/* Verdin UART_4 */ +&mcu_uart0 { + status = "okay"; +}; + +/* Verdin QSPI_1 */ +&ospi0 { + status = "okay"; +}; + +/* Verdin SD_1 */ +&sdhci1 { + ti,driver-strength-ohm = <33>; + status = "okay"; +}; + +/* Verdin USB_1 */ +&usbss0 { + status = "okay"; +}; + +&usb0 { + status = "okay"; +}; + +/* Verdin USB_2 */ +&usbss1 { + status = "okay"; +}; + +&usb1 { + status = "okay"; +}; + +/* Verdin CTRL_WAKE1_MICO# */ +&verdin_gpio_keys { + status = "okay"; +}; + +/* Verdin UART_2 */ +&wkup_uart0 { + /* FIXME: WKUP UART0 is used by DM firmware */ + status = "reserved"; +}; diff --git a/arch/arm64/boot/dts/ti/k3-am62-verdin-nonwifi.dtsi b/arch/arm64/boot/dts/ti/k3-am62-verdin-nonwifi.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..68d07695e1db5a5931e679d910bab851dca071d7 --- /dev/null +++ b/arch/arm64/boot/dts/ti/k3-am62-verdin-nonwifi.dtsi @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT +/* + * Copyright 2023 Toradex + * + * Common dtsi for Verdin AM62 SoM non-WB variant + * + * https://www.toradex.com/computer-on-modules/verdin-arm-family/ti-am62 + */ + +&sdhci2 { + pinctrl-0 = <&pinctrl_sdhci2>; + bus-width = <4>; + status = "disabled"; +}; + +&main_uart5 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart5>; + status = "disabled"; +}; diff --git a/arch/arm64/boot/dts/ti/k3-am62-verdin-wifi.dtsi b/arch/arm64/boot/dts/ti/k3-am62-verdin-wifi.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..90ddc71bcd3064aabb630c5457d6197fe3ea2db3 --- /dev/null +++ b/arch/arm64/boot/dts/ti/k3-am62-verdin-wifi.dtsi @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT +/* + * Copyright 2023 Toradex + * + * Common dtsi for Verdin AM62 SoM WB variant + * + * https://www.toradex.com/computer-on-modules/verdin-arm-family/ti-am62 + */ + +/ { + wifi_pwrseq: wifi-pwrseq { + compatible = "mmc-pwrseq-simple"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_wifi_en>; + reset-gpios = <&main_gpio0 22 GPIO_ACTIVE_LOW>; + }; +}; + +/* On-module Wi-Fi */ +&sdhci2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_sdhci2>; + bus-width = <4>; + cap-power-off-card; + keep-power-in-suspend; + mmc-pwrseq = <&wifi_pwrseq>; + non-removable; + ti,fails-without-test-cd; + ti,driver-strength-ohm = <50>; + vmmc-supply = <®_3v3>; + status = "okay"; +}; + +/* On-module Bluetooth */ +&main_uart5 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart5>; + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/ti/k3-am62-verdin-yavia.dtsi b/arch/arm64/boot/dts/ti/k3-am62-verdin-yavia.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..cb11d6e7f5256af32da849cd4d2201e1733956fc --- /dev/null +++ b/arch/arm64/boot/dts/ti/k3-am62-verdin-yavia.dtsi @@ -0,0 +1,207 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT +/* + * Copyright 2023 Toradex + * + * Common dtsi for Verdin AM62 SoM on Yavia carrier board + * + * https://www.toradex.com/computer-on-modules/verdin-arm-family/ti-am62 + * https://www.toradex.com/products/carrier-board/yavia + */ + +#include + +/ { + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_qspi1_clk_gpio>, + <&pinctrl_qspi1_cs_gpio>, + <&pinctrl_qspi1_io0_gpio>, + <&pinctrl_qspi1_io1_gpio>, + <&pinctrl_qspi1_io2_gpio>, + <&pinctrl_qspi1_io3_gpio>; + + /* SODIMM 52 - LD1_RED */ + led-0 { + color = ; + function = LED_FUNCTION_DEBUG; + function-enumerator = <1>; + gpios = <&main_gpio0 0 GPIO_ACTIVE_HIGH>; + }; + /* SODIMM 54 - LD1_GREEN */ + led-1 { + color = ; + function = LED_FUNCTION_DEBUG; + function-enumerator = <1>; + gpios = <&main_gpio0 11 GPIO_ACTIVE_HIGH>; + }; + /* SODIMM 56 - LD1_BLUE */ + led-2 { + color = ; + function = LED_FUNCTION_DEBUG; + function-enumerator = <1>; + gpios = <&main_gpio0 3 GPIO_ACTIVE_HIGH>; + }; + /* SODIMM 58 - LD2_RED */ + led-3 { + color = ; + function = LED_FUNCTION_DEBUG; + function-enumerator = <2>; + gpios = <&main_gpio0 4 GPIO_ACTIVE_HIGH>; + }; + /* SODIMM 60 - LD2_GREEN */ + led-4 { + color = ; + function = LED_FUNCTION_DEBUG; + function-enumerator = <2>; + gpios = <&main_gpio0 5 GPIO_ACTIVE_HIGH>; + }; + /* SODIMM 62 - LD2_BLUE */ + led-5 { + color = ; + function = LED_FUNCTION_DEBUG; + function-enumerator = <2>; + gpios = <&main_gpio0 6 GPIO_ACTIVE_HIGH>; + }; + }; +}; + +/* Verdin ETHs */ +&cpsw3g { + status = "okay"; +}; + +/* MDIO, shared by Verdin ETH_1 (On-module PHY) and Verdin ETH_2_RGMII */ +&cpsw3g_mdio { + status = "okay"; +}; + +/* Verdin ETH_1 (On-module PHY) */ +&cpsw_port1 { + status = "okay"; +}; + +/* Verdin PWM_1, PWM_2 */ +&epwm0 { + status = "okay"; +}; + +/* Verdin PWM_3_DSI */ +&epwm1 { + status = "okay"; +}; + +&main_gpio0 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_ctrl_sleep_moci>, + <&pinctrl_gpio_5>, + <&pinctrl_gpio_6>, + <&pinctrl_gpio_7>, + <&pinctrl_gpio_8>, + <&pinctrl_qspi1_cs2_gpio>; +}; + +&main_gpio1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_qspi1_dqs_gpio>; +}; + +/* Verdin I2C_1 */ +&main_i2c1 { + status = "okay"; + + /* Temperature sensor */ + sensor@4f { + compatible = "ti,tmp75c"; + reg = <0x4f>; + }; + + /* EEPROM */ + eeprom@57 { + compatible = "st,24c02"; + reg = <0x57>; + pagesize = <16>; + }; +}; + +/* Verdin I2C_2_DSI */ +&main_i2c2 { + status = "okay"; +}; + +/* Verdin I2C_4_CSI */ +&main_i2c3 { + status = "okay"; +}; + +/* Verdin CAN_1 */ +&main_mcan0 { + status = "okay"; +}; + +/* Verdin SPI_1 */ +&main_spi1 { + status = "okay"; +}; + +/* Verdin UART_3 */ +&main_uart0 { + status = "okay"; +}; + +/* Verdin UART_1 */ +&main_uart1 { + status = "okay"; +}; + +&mcu_gpio0 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_gpio_1>, + <&pinctrl_gpio_2>, + <&pinctrl_gpio_3>, + <&pinctrl_gpio_4>; +}; + +/* Verdin I2C_3_HDMI */ +&mcu_i2c0 { + status = "okay"; +}; + +/* Verdin UART_4 */ +&mcu_uart0 { + status = "okay"; +}; + +/* Verdin SD_1 */ +&sdhci1 { + status = "okay"; +}; + +/* Verdin USB_1 */ +&usbss0 { + status = "okay"; +}; + +&usb0 { + status = "okay"; +}; + +/* Verdin USB_2 */ +&usbss1 { + status = "okay"; +}; + +&usb1 { + status = "okay"; +}; + +/* Verdin CTRL_WAKE1_MICO# */ +&verdin_gpio_keys { + status = "okay"; +}; + +/* Verdin UART_2 */ +&wkup_uart0 { + /* FIXME: WKUP UART0 is used by DM firmware */ + status = "reserved"; +}; diff --git a/arch/arm64/boot/dts/ti/k3-am62-verdin.dtsi b/arch/arm64/boot/dts/ti/k3-am62-verdin.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..57dd061911abb4c4e25faeabffed4acd80ff07ce --- /dev/null +++ b/arch/arm64/boot/dts/ti/k3-am62-verdin.dtsi @@ -0,0 +1,1401 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT +/* + * Copyright 2023 Toradex + * + * Common dtsi for Verdin AM62 SoM + * + * https://www.toradex.com/computer-on-modules/verdin-arm-family/ti-am62 + */ + +#include +#include +#include +#include +#include + +/ { + chosen { + stdout-path = "serial2:115200n8"; + }; + + aliases { + ethernet0 = &cpsw_port1; + ethernet1 = &cpsw_port2; + i2c0 = &main_i2c0; + i2c1 = &main_i2c1; + i2c2 = &main_i2c2; + i2c3 = &mcu_i2c0; + i2c4 = &main_i2c3; + mmc0 = &sdhci0; + mmc1 = &sdhci1; + mmc2 = &sdhci2; + rtc0 = &rtc_i2c; + rtc1 = &wkup_rtc0; + serial0 = &main_uart1; + serial1 = &wkup_uart0; + serial2 = &main_uart0; + serial3 = &mcu_uart0; + serial4 = &main_uart5; + usb0 = &usb0; + usb1 = &usb1; + }; + + verdin_gpio_keys: gpio-keys { + compatible = "gpio-keys"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_ctrl_wake1_mico>; + status = "disabled"; + + verdin_key_wakeup: key-wakeup { + debounce-interval = <10>; + /* Verdin CTRL_WAKE1_MICO# (SODIMM 252) */ + gpios = <&main_gpio0 32 GPIO_ACTIVE_LOW>; + label = "Wake-Up"; + linux,code = ; + wakeup-source; + }; + }; + + memory@80000000 { + device_type = "memory"; + reg = <0x00000000 0x80000000 0x00000000 0x40000000>; /* 1G RAM */ + }; + + opp-table { + /* Add 1.4GHz OPP. Requires VDD_CORE to be at 0.85V */ + opp-1400000000 { + opp-hz = /bits/ 64 <1400000000>; + opp-supported-hw = <0x01 0x0004>; + clock-latency-ns = <6000000>; + }; + }; + + /* Module Power Supply */ + reg_vsodimm: regulator-vsodimm { + compatible = "regulator-fixed"; + regulator-name = "+V_SODIMM"; + }; + + /* Non PMIC On-module Supplies */ + reg_3v3: regulator-3v3 { + compatible = "regulator-fixed"; + regulator-max-microvolt = <3300000>; + regulator-min-microvolt = <3300000>; + regulator-name = "On-module +V3.3"; + vin-supply = <®_vsodimm>; + }; + + reg_1v2_dsi: regulator-1v2-dsi { + compatible = "regulator-fixed"; + regulator-max-microvolt = <1200000>; + regulator-min-microvolt = <1200000>; + regulator-name = "On-module +V1.2_DSI"; + vin-supply = <®_1v8>; + }; + + /* Enabled by +V1.2_DSI */ + reg_1v8_dsi: regulator-1v8-dsi { + compatible = "regulator-fixed"; + regulator-max-microvolt = <1800000>; + regulator-min-microvolt = <1800000>; + regulator-name = "On-module +V1.8_DSI"; + vin-supply = <®_1v8>; + }; + + /* Enabled by +V2.5_ETH */ + reg_1v0_eth: regulator-1v0-eth { + compatible = "regulator-fixed"; + regulator-max-microvolt = <1000000>; + regulator-min-microvolt = <1000000>; + regulator-name = "On-module +V1.0_ETH"; + vin-supply = <®_1v8>; + }; + + /* Enabled by +V2.5_ETH */ + reg_1v8_eth: regulator-1v8-eth { + compatible = "regulator-fixed"; + regulator-max-microvolt = <1800000>; + regulator-min-microvolt = <1800000>; + regulator-name = "On-module +V1.8_ETH"; + vin-supply = <®_1v8>; + }; + + /* Verdin SD_1 Power Supply */ + reg_sdhc1_vmmc: regulator-sdhci1 { + compatible = "regulator-fixed"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_sd1_pwr_en>; + enable-active-high; + /* Verdin SD_1_PWR_EN (SODIMM 76) */ + gpio = <&main_gpio0 29 GPIO_ACTIVE_HIGH>; + off-on-delay-us = <100000>; + regulator-max-microvolt = <3300000>; + regulator-min-microvolt = <3300000>; + regulator-name = "+V3.3_SD"; + startup-delay-us = <2000>; + }; + + reg_sdhc1_vqmmc: regulator-sdhci1-vqmmc { + compatible = "regulator-gpio"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_vsel_sd>; + /* PMIC_VSEL_SD */ + gpios = <&main_gpio0 21 GPIO_ACTIVE_HIGH>; + regulator-name = "LDO1-VSEL-SD (PMIC)"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + states = <1800000 0x0>, + <3300000 0x1>; + vin-supply = <®_sd_3v3_1v8>; + }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + + secure_tfa_ddr: tfa@9e780000 { + reg = <0x00 0x9e780000 0x00 0x80000>; + alignment = <0x1000>; + no-map; + }; + + secure_ddr: optee@9e800000 { + reg = <0x00 0x9e800000 0x00 0x01800000>; /* for OP-TEE */ + alignment = <0x1000>; + no-map; + }; + + wkup_r5fss0_core0_dma_memory_region: r5f-dma-memory@9db00000 { + compatible = "shared-dma-pool"; + reg = <0x00 0x9db00000 0x00 0xc00000>; + no-map; + }; + }; +}; + +&main_pmx0 { + /* Verdin PWM_1 */ + pinctrl_epwm0_a: main-epwm0a-default-pins { + pinctrl-single,pins = < + AM62X_IOPAD(0x01b4, PIN_OUTPUT, 2) /* (A13) SPI0_CS0.EHRPWM0_A */ /* SODIMM 15 */ + >; + }; + + /* Verdin PWM_2 */ + pinctrl_epwm0_b: main-epwm0b-default-pins { + pinctrl-single,pins = < + AM62X_IOPAD(0x01b8, PIN_OUTPUT, 2) /* (C13) SPI0_CS1.EHRPWM0_B */ /* SODIMM 16 */ + >; + }; + + /* Verdin PWM_3_DSI */ + pinctrl_epwm1_a: main-epwm1a-default-pins { + pinctrl-single,pins = < + AM62X_IOPAD(0x01bc, PIN_OUTPUT, 2) /* (A14) SPI0_CLK.EHRPWM1_A */ /* SODIMM 19 */ + >; + }; + + /* Verdin QSPI_1_CLK as GPIO (conflict with Verdin QSPI_1 interface) */ + pinctrl_qspi1_clk_gpio: main-gpio0-0-default-pins { + pinctrl-single,pins = < + AM62X_IOPAD(0x0000, PIN_INPUT, 7) /* (H24) OSPI0_CLK.GPIO0_0 */ /* SODIMM 52 */ + >; + }; + + /* Verdin QSPI_1_IO0 as GPIO (conflict with Verdin QSPI_1 interface) */ + pinctrl_qspi1_io0_gpio: main-gpio0-3-default-pins { + pinctrl-single,pins = < + AM62X_IOPAD(0x000c, PIN_INPUT, 7) /* (E25) OSPI0_D0.GPIO0_3 */ /* SODIMM 56 */ + >; + }; + + /* Verdin QSPI_1_IO1 as GPIO (conflict with Verdin QSPI_1 interface) */ + pinctrl_qspi1_io1_gpio: main-gpio0-4-default-pins { + pinctrl-single,pins = < + AM62X_IOPAD(0x0010, PIN_INPUT, 7) /* (G24) OSPI0_D1.GPIO0_4 */ /* SODIMM 58 */ + >; + }; + + /* Verdin QSPI_1_IO2 as GPIO (conflict with Verdin QSPI_1 interface) */ + pinctrl_qspi1_io2_gpio: main-gpio0-5-default-pins { + pinctrl-single,pins = < + AM62X_IOPAD(0x0014, PIN_INPUT, 7) /* (F25) OSPI0_D2.GPIO0_5 */ /* SODIMM 60 */ + >; + }; + + /* Verdin QSPI_1_IO3 as GPIO (conflict with Verdin QSPI_1 interface) */ + pinctrl_qspi1_io3_gpio: main-gpio0-6-default-pins { + pinctrl-single,pins = < + AM62X_IOPAD(0x0018, PIN_INPUT, 7) /* (F24) OSPI0_D3.GPIO0_6 */ /* SODIMM 62 */ + >; + }; + + /* Verdin QSPI_1_CS# as GPIO (conflict with Verdin QSPI_1 interface) */ + pinctrl_qspi1_cs_gpio: main-gpio0-11-default-pins { + pinctrl-single,pins = < + AM62X_IOPAD(0x002c, PIN_INPUT, 7) /* (F23) OSPI0_CSn0.GPIO0_11 */ /* SODIMM 54 */ + >; + }; + + /* Verdin QSPI_1_CS2# as GPIO (conflict with Verdin QSPI_1 interface) */ + pinctrl_qspi1_cs2_gpio: main-gpio0-12-default-pins { + pinctrl-single,pins = < + AM62X_IOPAD(0x0030, PIN_INPUT, 7) /* (G21) OSPI0_CSn1.GPIO0_12 */ /* SODIMM 64 */ + >; + }; + + /* WiFi_W_WKUP_HOST# */ + pinctrl_wifi_w_wkup_host: main-gpio0-15-default-pins { + pinctrl-single,pins = < + AM62X_IOPAD(0x003c, PIN_INPUT, 7) /* (M25) GPMC0_AD0.GPIO0_15 */ /* SODIMM 174 */ + >; + }; + + /* WiFi_BT_WKUP_HOST# */ + pinctrl_bt_wkup_host: main-gpio0-16-default-pins { + pinctrl-single,pins = < + AM62X_IOPAD(0x0040, PIN_INPUT, 7) /* (N23) GPMC0_AD1.GPIO0_16 */ /* SODIMM 172 */ + >; + }; + + /* PMIC_ETH_RESET# */ + pinctrl_eth_reset: main-gpio0-17-default-pins { + pinctrl-single,pins = < + AM62X_IOPAD(0x0044, PIN_INPUT, 7) /* (N24) GPMC0_AD2.GPIO0_17 */ + >; + }; + + /* PMIC_BRIDGE_RESET# */ + pinctrl_bridge_reset: main-gpio0-20-default-pins { + pinctrl-single,pins = < + AM62X_IOPAD(0x0050, PIN_INPUT, 7) /* (P22) GPMC0_AD5.GPIO0_20 */ + >; + }; + + /* PMIC_VSEL_SD */ + pinctrl_vsel_sd: main-gpio0-21-default-pins { + pinctrl-single,pins = < + AM62X_IOPAD(0x0054, PIN_INPUT, 7) /* (P21) GPMC0_AD6.GPIO0_21 */ + >; + }; + + /* PMIC_EN_WIFI */ + pinctrl_wifi_en: main-gpio0-22-default-pins { + pinctrl-single,pins = < + AM62X_IOPAD(0x0058, PIN_INPUT, 7) /* (R23) GPMC0_AD7.GPIO0_22 */ + >; + }; + + /* PMIC_ETH_INT# */ + pinctrl_eth_int: main-gpio0-25-default-pins { + pinctrl-single,pins = < + AM62X_IOPAD(0x0064, PIN_INPUT_PULLUP, 7) /* (T25) GPMC0_AD10.GPIO0_25 */ + >; + }; + + /* WiFi_WKUP_BT# */ + pinctrl_wifi_wkup_bt: main-gpio0-26-default-pins { + pinctrl-single,pins = < + AM62X_IOPAD(0x0068, PIN_INPUT, 7) /* (R21) GPMC0_AD11.GPIO0_26 */ + >; + }; + + /* WiFi_WKUP_WLAN# */ + pinctrl_wifi_wkup_wlan: main-gpio0-27-default-pins { + pinctrl-single,pins = < + AM62X_IOPAD(0x006c, PIN_INPUT, 7) /* (T22) GPMC0_AD12.GPIO0_27 */ + >; + }; + + /* Verdin SD_1_PWR_EN */ + pinctrl_sd1_pwr_en: main-gpio0-29-default-pins { + pinctrl-single,pins = < + AM62X_IOPAD(0x0074, PIN_INPUT, 7) /* (U25) GPMC0_AD14.GPIO0_29 */ /* SODIMM 76 */ + >; + }; + + /* Verdin DSI_1_BKL_EN */ + pinctrl_dsi1_bkl_en: main-gpio0-30-default-pins { + pinctrl-single,pins = < + AM62X_IOPAD(0x0078, PIN_INPUT, 7) /* (U24) GPMC0_AD15.GPIO0_30 */ /* SODIMM 21 */ + >; + }; + + /* Verdin CTRL_SLEEP_MOCI# */ + pinctrl_ctrl_sleep_moci: main-gpio0-31-default-pins { + pinctrl-single,pins = < + AM62X_IOPAD(0x007c, PIN_INPUT, 7) /* (P25) GPMC0_CLK.GPIO0_31 */ /* SODIMM 256 */ + >; + }; + + /* Verdin CTRL_WAKE1_MICO# */ + pinctrl_ctrl_wake1_mico: main-gpio0-32-default-pins { + pinctrl-single,pins = < + AM62X_IOPAD(0x0084, PIN_INPUT_PULLUP, 7) /* (L23) GPMC0_ADVn_ALE.GPIO0_32 */ /* SODIMM 252 */ + >; + }; + + /* Verdin I2S_2_D_OUT as GPIO (conflict with Verdin I2S_2 interface) */ + pinctrl_i2s_2_d_out_gpio: main-gpio0-34-default-pins { + pinctrl-single,pins = < + AM62X_IOPAD(0x008c, PIN_INPUT, 7) /* (L25) GPMC0_WEn.GPIO0_34 */ /* SODIMM 46 */ + >; + }; + + /* Verdin I2S_2_BCLK as GPIO (conflict with Verdin I2S_2 interface) */ + pinctrl_i2s_2_bclk_gpio: main-gpio0-35-default-pins { + pinctrl-single,pins = < + AM62X_IOPAD(0x0090, PIN_INPUT, 7) /* (M24) GPMC0_BE0n_CLE.GPIO0_35 */ /* SODIMM 42 */ + >; + }; + + /* Verdin GPIO_6 */ + pinctrl_gpio_6: main-gpio0-36-default-pins { + pinctrl-single,pins = < + AM62X_IOPAD(0x0094, PIN_INPUT, 7) /* (N20) GPMC0_BE1n.GPIO0_36 */ /* SODIMM 218 */ + >; + }; + + /* Verdin ETH_2_RGMII_INT# */ + pinctrl_eth2_rgmii_int: main-gpio0-38-default-pins { + pinctrl-single,pins = < + AM62X_IOPAD(0x009c, PIN_INPUT, 7) /* (V25) GPMC0_WAIT1.GPIO0_38 */ /* SODIMM 189 */ + >; + }; + + /* Verdin GPIO_5 */ + pinctrl_gpio_5: main-gpio0-40-default-pins { + pinctrl-single,pins = < + AM62X_IOPAD(0x00a4, PIN_INPUT, 7) /* (M22) GPMC0_DIR.GPIO0_40 */ /* SODIMM 216 */ + >; + }; + + /* Verdin GPIO_7 */ + pinctrl_gpio_7: main-gpio0-41-default-pins { + pinctrl-single,pins = < + AM62X_IOPAD(0x00a8, PIN_INPUT, 7) /* (M21) GPMC0_CSn0.GPIO0_41 */ /* SODIMM 220 */ + >; + }; + + /* Verdin GPIO_8 */ + pinctrl_gpio_8: main-gpio0-42-default-pins { + pinctrl-single,pins = < + AM62X_IOPAD(0x00ac, PIN_INPUT, 7) /* (L21) GPMC0_CSn1.GPIO0_42 */ /* SODIMM 222 */ + >; + }; + + /* Verdin USB_1_OC# */ + pinctrl_usb1_oc: main-gpio0-71-default-pins { + pinctrl-single,pins = < + AM62X_IOPAD(0x0124, PIN_INPUT, 7) /* (A23) MMC2_SDCD.GPIO0_71 */ /* SODIMM 157 */ + >; + }; + + /* Verdin USB_2_OC# */ + pinctrl_usb2_oc: main-gpio0-72-default-pins { + pinctrl-single,pins = < + AM62X_IOPAD(0x0128, PIN_INPUT, 7) /* (B23) MMC2_SDWP.GPIO0_72 */ /* SODIMM 187 */ + >; + }; + + /* Verdin PWM_3_DSI as GPIO */ + pinctrl_pwm3_dsi_gpio: main-gpio1-17-default-pins { + pinctrl-single,pins = < + AM62X_IOPAD(0x01bc, PIN_INPUT, 7) /* (A14) SPI0_CLK.GPIO1_17 */ /* SODIMM 19 */ + >; + }; + + /* Verdin QSPI_1_DQS as GPIO */ + pinctrl_qspi1_dqs_gpio: main-gpio1-18-default-pins { + pinctrl-single,pins = < + AM62X_IOPAD(0x01c0, PIN_INPUT, 7) /* (B13) SPI0_D0.GPIO1_18 */ /* SODIMM 66 */ + >; + }; + + /* Verdin USB_1_ID */ + pinctrl_usb0_id: main-gpio1-19-default-pins { + pinctrl-single,pins = < + AM62X_IOPAD(0x01c4, PIN_INPUT, 7) /* (B14) SPI0_D1.GPIO1_19 */ /* SODIMM 161 */ + >; + }; + + /* Verdin DSI_1_INT# (pulled-up as active-low) */ + pinctrl_dsi1_int: main-gpio1-49-default-pins { + pinctrl-single,pins = < + AM62X_IOPAD(0x0244, PIN_INPUT_PULLUP, 7) /* (C17) MMC1_SDWP.GPIO1_49 */ /* SODIMM 17 */ + >; + }; + + /* On-module I2C - PMIC_I2C */ + pinctrl_i2c0: main-i2c0-default-pins { + pinctrl-single,pins = < + AM62X_IOPAD(0x01e0, PIN_INPUT, 0) /* (B16) I2C0_SCL */ /* PMIC_I2C_SCL */ + AM62X_IOPAD(0x01e4, PIN_INPUT, 0) /* (A16) I2C0_SDA */ /* PMIC_I2C_SDA */ + >; + }; + + /* Verdin I2C_1 */ + pinctrl_i2c1: main-i2c1-default-pins { + pinctrl-single,pins = < + AM62X_IOPAD(0x01e8, PIN_INPUT_PULLUP, 0) /* (B17) I2C1_SCL */ /* SODIMM 14 */ + AM62X_IOPAD(0x01ec, PIN_INPUT_PULLUP, 0) /* (A17) I2C1_SDA */ /* SODIMM 12 */ + >; + }; + + /* Verdin I2C_2_DSI */ + pinctrl_i2c2: main-i2c2-default-pins { + pinctrl-single,pins = < + AM62X_IOPAD(0x00b0, PIN_INPUT, 1) /* (K22) GPMC0_CSn2.I2C2_SCL */ /* SODIMM 55 */ + AM62X_IOPAD(0x00b4, PIN_INPUT, 1) /* (K24) GPMC0_CSn3.I2C2_SDA */ /* SODIMM 53 */ + >; + }; + + /* Verdin I2C_4_CSI */ + pinctrl_i2c3: main-i2c3-default-pins { + pinctrl-single,pins = < + AM62X_IOPAD(0x01d0, PIN_INPUT, 2) /* (A15) UART0_CTSn.I2C3_SCL */ /* SODIMM 95 */ + AM62X_IOPAD(0x01d4, PIN_INPUT, 2) /* (B15) UART0_RTSn.I2C3_SDA */ /* SODIMM 93 */ + >; + }; + + /* I2S_1_MCLK */ + pinctrl_i2s1_mclk: main-system-audio-ext-reflock1-default-pins { + pinctrl-single,pins = < + AM62X_IOPAD(0x00a0, PIN_OUTPUT, 1) /* (K25) GPMC0_WPn.AUDIO_EXT_REFCLK1 */ /* SODIMM 38 */ + >; + }; + + /* Verdin I2S_1 */ + pinctrl_mcasp0: main-mcasp0-default-pins { + pinctrl-single,pins = < + AM62X_IOPAD(0x01a4, PIN_INPUT, 0) /* (B20) MCASP0_ACLKX */ /* SODIMM 30 */ + AM62X_IOPAD(0x01a8, PIN_INPUT, 0) /* (D20) MCASP0_AFSX */ /* SODIMM 32 */ + AM62X_IOPAD(0x01a0, PIN_OUTPUT, 0) /* (E18) MCASP0_AXR0 */ /* SODIMM 34 */ + AM62X_IOPAD(0x019c, PIN_INPUT, 0) /* (B18) MCASP0_AXR1 */ /* SODIMM 36 */ + >; + }; + + /* Verdin I2S_2 */ + pinctrl_mcasp1: main-mcasp1-default-pins { + pinctrl-single,pins = < + AM62X_IOPAD(0x0090, PIN_INPUT, 2) /* (M24) GPMC0_BE0n_CLE.MCASP1_ACLKX */ /* SODIMM 42 */ + AM62X_IOPAD(0x0098, PIN_INPUT, 2) /* (U23) GPMC0_WAIT0.MCASP1_AFSX */ /* SODIMM 44 */ + AM62X_IOPAD(0x008c, PIN_OUTPUT, 2) /* (L25) GPMC0_WEn.MCASP1_AXR0 */ /* SODIMM 46 */ + AM62X_IOPAD(0x0088, PIN_INPUT, 2) /* (L24) GPMC0_OEn_REn.MCASP1_AXR1 */ /* SODIMM 48 */ + >; + }; + + /* Verdin CAN_1 */ + pinctrl_mcan0: main-mcan0-default-pins { + pinctrl-single,pins = < + AM62X_IOPAD(0x01dc, PIN_INPUT, 0) /* (E15) MCAN0_RX */ /* SODIMM 22 */ + AM62X_IOPAD(0x01d8, PIN_OUTPUT, 0) /* (C15) MCAN0_TX */ /* SODIMM 20 */ + >; + }; + + /* MDIO, shared by Verdin ETH_1 (On-module PHY) and Verdin ETH_2_RGMII */ + pinctrl_mdio: main-mdio1-default-pins { + pinctrl-single,pins = < + AM62X_IOPAD(0x160, PIN_OUTPUT, 0) /* (AD24) MDIO0_MDC */ /* ETH_1_MDC, SODIMM 193 */ + AM62X_IOPAD(0x15c, PIN_INPUT, 0) /* (AB22) MDIO0_MDIO */ /* ETH_1_MDIO, SODIMM 191 */ + >; + }; + + /* On-module eMMC */ + pinctrl_sdhci0: main-mmc0-default-pins { + pinctrl-single,pins = < + AM62X_IOPAD(0x220, PIN_INPUT, 0) /* (Y3) MMC0_CMD */ + AM62X_IOPAD(0x218, PIN_INPUT, 0) /* (AB1) MMC0_CLK */ + AM62X_IOPAD(0x214, PIN_INPUT, 0) /* (AA2) MMC0_DAT0 */ + AM62X_IOPAD(0x210, PIN_INPUT, 0) /* (AA1) MMC0_DAT1 */ + AM62X_IOPAD(0x20c, PIN_INPUT, 0) /* (AA3) MMC0_DAT2 */ + AM62X_IOPAD(0x208, PIN_INPUT, 0) /* (Y4) MMC0_DAT3 */ + AM62X_IOPAD(0x204, PIN_INPUT, 0) /* (AB2) MMC0_DAT4 */ + AM62X_IOPAD(0x200, PIN_INPUT, 0) /* (AC1) MMC0_DAT5 */ + AM62X_IOPAD(0x1fc, PIN_INPUT, 0) /* (AD2) MMC0_DAT6 */ + AM62X_IOPAD(0x1f8, PIN_INPUT, 0) /* (AC2) MMC0_DAT7 */ + >; + }; + + /* Verdin SD_1 */ + pinctrl_sdhci1: main-mmc1-default-pins { + pinctrl-single,pins = < + AM62X_IOPAD(0x23c, PIN_INPUT, 0) /* (A21) MMC1_CMD */ /* SODIMM 74 */ + AM62X_IOPAD(0x234, PIN_INPUT, 0) /* (B22) MMC1_CLK */ /* SODIMM 78 */ + AM62X_IOPAD(0x230, PIN_INPUT, 0) /* (A22) MMC1_DAT0 */ /* SODIMM 80 */ + AM62X_IOPAD(0x22c, PIN_INPUT, 0) /* (B21) MMC1_DAT1 */ /* SODIMM 82 */ + AM62X_IOPAD(0x228, PIN_INPUT, 0) /* (C21) MMC1_DAT2 */ /* SODIMM 70 */ + AM62X_IOPAD(0x224, PIN_INPUT, 0) /* (D22) MMC1_DAT3 */ /* SODIMM 72 */ + AM62X_IOPAD(0x240, PIN_INPUT_PULLUP, 0) /* (D17) MMC1_SDCD */ /* SODIMM 84 */ + >; + }; + + /* On-module Wi-Fi on WB SKUs, module-specific SDIO otherwise */ + pinctrl_sdhci2: main-mmc2-default-pins { + pinctrl-single,pins = < + AM62X_IOPAD(0x120, PIN_INPUT, 0) /* (C24) MMC2_CMD */ /* WiFi_SDIO_CMD */ + AM62X_IOPAD(0x118, PIN_INPUT, 0) /* (D25) MMC2_CLK */ /* WiFi_SDIO_CLK */ + AM62X_IOPAD(0x114, PIN_INPUT, 0) /* (B24) MMC2_DAT0 */ /* WiFi_SDIO_DATA0 */ + AM62X_IOPAD(0x110, PIN_INPUT, 0) /* (C25) MMC2_DAT1 */ /* WiFi_SDIO_DATA1 */ + AM62X_IOPAD(0x10c, PIN_INPUT, 0) /* (E23) MMC2_DAT2 */ /* WiFi_SDIO_DATA2 */ + AM62X_IOPAD(0x108, PIN_INPUT, 0) /* (D24) MMC2_DAT3 */ /* WiFi_SDIO_DATA3 */ + AM62X_IOPAD(0x11c, PIN_INPUT, 0) /* (#N/A) MMC2_CLKB */ + >; + }; + + /* Verdin QSPI_1 */ + pinctrl_ospi0: main-ospi0-default-pins { + pinctrl-single,pins = < + AM62X_IOPAD(0x0000, PIN_OUTPUT, 0) /* (H24) OSPI0_CLK */ /* SODIMM 52 */ + AM62X_IOPAD(0x002c, PIN_OUTPUT, 0) /* (F23) OSPI0_CSn0 */ /* SODIMM 54 */ + AM62X_IOPAD(0x0030, PIN_OUTPUT, 0) /* (G21) OSPI0_CSn1 */ /* SODIMM 64 */ + AM62X_IOPAD(0x000c, PIN_INPUT, 0) /* (E25) OSPI0_D0 */ /* SODIMM 56 */ + AM62X_IOPAD(0x0010, PIN_INPUT, 0) /* (G24) OSPI0_D1 */ /* SODIMM 58 */ + AM62X_IOPAD(0x0014, PIN_INPUT, 0) /* (F25) OSPI0_D2 */ /* SODIMM 60 */ + AM62X_IOPAD(0x0018, PIN_INPUT, 0) /* (F24) OSPI0_D3 */ /* SODIMM 62 */ + >; + }; + + /* Verdin ETH_1 RGMII (On-module PHY) */ + pinctrl_rgmii1: main-rgmii1-default-pins { + pinctrl-single,pins = < + AM62X_IOPAD(0x14c, PIN_INPUT, 0) /* (AB17) RGMII1_RD0 */ + AM62X_IOPAD(0x150, PIN_INPUT, 0) /* (AC17) RGMII1_RD1 */ + AM62X_IOPAD(0x154, PIN_INPUT, 0) /* (AB16) RGMII1_RD2 */ + AM62X_IOPAD(0x158, PIN_INPUT, 0) /* (AA15) RGMII1_RD3 */ + AM62X_IOPAD(0x148, PIN_INPUT, 0) /* (AD17) RGMII1_RXC */ + AM62X_IOPAD(0x144, PIN_INPUT, 0) /* (AE17) RGMII1_RX_CTL */ + AM62X_IOPAD(0x134, PIN_OUTPUT, 0) /* (AE20) RGMII1_TD0 */ + AM62X_IOPAD(0x138, PIN_OUTPUT, 0) /* (AD20) RGMII1_TD1 */ + AM62X_IOPAD(0x13c, PIN_OUTPUT, 0) /* (AE18) RGMII1_TD2 */ + AM62X_IOPAD(0x140, PIN_OUTPUT, 0) /* (AD18) RGMII1_TD3 */ + AM62X_IOPAD(0x130, PIN_OUTPUT, 0) /* (AE19) RGMII1_TXC */ + AM62X_IOPAD(0x12c, PIN_OUTPUT, 0) /* (AD19) RGMII1_TX_CTL */ + >; + }; + + /* Verdin ETH_2 RGMII */ + pinctrl_rgmii2: main-rgmii2-default-pins { + pinctrl-single,pins = < + AM62X_IOPAD(0x184, PIN_INPUT, 0) /* (AE23) RGMII2_RD0 */ /* SODIMM 201 */ + AM62X_IOPAD(0x188, PIN_INPUT, 0) /* (AB20) RGMII2_RD1 */ /* SODIMM 203 */ + AM62X_IOPAD(0x18c, PIN_INPUT, 0) /* (AC21) RGMII2_RD2 */ /* SODIMM 205 */ + AM62X_IOPAD(0x190, PIN_INPUT, 0) /* (AE22) RGMII2_RD3 */ /* SODIMM 207 */ + AM62X_IOPAD(0x180, PIN_INPUT, 0) /* (AD23) RGMII2_RXC */ /* SODIMM 197 */ + AM62X_IOPAD(0x17c, PIN_INPUT, 0) /* (AD22) RGMII2_RX_CTL */ /* SODIMM 199 */ + AM62X_IOPAD(0x16c, PIN_OUTPUT, 0) /* (Y18) RGMII2_TD0 */ /* SODIMM 221 */ + AM62X_IOPAD(0x170, PIN_OUTPUT, 0) /* (AA18) RGMII2_TD1 */ /* SODIMM 219 */ + AM62X_IOPAD(0x174, PIN_OUTPUT, 0) /* (AD21) RGMII2_TD2 */ /* SODIMM 217 */ + AM62X_IOPAD(0x178, PIN_OUTPUT, 0) /* (AC20) RGMII2_TD3 */ /* SODIMM 215 */ + AM62X_IOPAD(0x168, PIN_OUTPUT, 0) /* (AE21) RGMII2_TXC */ /* SODIMM 213 */ + AM62X_IOPAD(0x164, PIN_OUTPUT, 0) /* (AA19) RGMII2_TX_CTL */ /* SODIMM 211 */ + >; + }; + + /* Verdin SPI_1 */ + pinctrl_spi1: main-spi1-default-pins { + pinctrl-single,pins = < + AM62X_IOPAD(0x0020, PIN_INPUT, 1) /* (J25) OSPI0_D5.SPI1_CLK */ /* SODIMM 196 */ + AM62X_IOPAD(0x001c, PIN_INPUT, 1) /* (J23) OSPI0_D4.SPI1_CS0 */ /* SODIMM 202 */ + AM62X_IOPAD(0x0024, PIN_INPUT, 1) /* (H25) OSPI0_D6.SPI1_D0 */ /* SODIMM 200 */ + AM62X_IOPAD(0x0028, PIN_INPUT, 1) /* (J22) OSPI0_D7.SPI1_D1 */ /* SODIMM 198 */ + >; + }; + + /* ETH_25MHz_CLK */ + pinctrl_eth_clock: main-system-clkout0-default-pins { + pinctrl-single,pins = < + AM62X_IOPAD(0x01f0, PIN_OUTPUT_PULLUP, 5) /* (A18) EXT_REFCLK1.CLKOUT0 */ + >; + }; + + /* PMIC_EXTINT# */ + pinctrl_pmic_extint: main-system-extint-default-pins { + pinctrl-single,pins = < + AM62X_IOPAD(0x01f4, PIN_INPUT, 0) /* (D16) EXTINTn */ + >; + }; + + /* Verdin UART_3, used as the Linux console */ + pinctrl_uart0: main-uart0-default-pins { + pinctrl-single,pins = < + AM62X_IOPAD(0x1c8, PIN_INPUT_PULLUP, 0) /* (D14) UART0_RXD */ /* SODIMM 147 */ + AM62X_IOPAD(0x1cc, PIN_OUTPUT, 0) /* (E14) UART0_TXD */ /* SODIMM 149 */ + >; + }; + + /* Verdin UART_1 */ + pinctrl_uart1: main-uart1-default-pins { + pinctrl-single,pins = < + AM62X_IOPAD(0x0194, PIN_INPUT_PULLUP, 2) /* (B19) MCASP0_AXR3.UART1_CTSn */ /* SODIMM 135 */ + AM62X_IOPAD(0x0198, PIN_OUTPUT, 2) /* (A19) MCASP0_AXR2.UART1_RTSn */ /* SODIMM 133 */ + AM62X_IOPAD(0x01ac, PIN_INPUT_PULLUP, 2) /* (E19) MCASP0_AFSR.UART1_RXD */ /* SODIMM 129 */ + AM62X_IOPAD(0x01b0, PIN_OUTPUT, 2) /* (A20) MCASP0_ACLKR.UART1_TXD */ /* SODIMM 131 */ + >; + }; + + /* Bluetooth on WB SKUs, module-specific UART otherwise */ + pinctrl_uart5: main-uart5-default-pins { + pinctrl-single,pins = < + AM62X_IOPAD(0x0008, PIN_INPUT_PULLUP, 5) /* (J24) OSPI0_DQS.UART5_CTSn */ /* WiFi_UART_CTS */ + AM62X_IOPAD(0x0004, PIN_OUTPUT, 5) /* (G25) OSPI0_LBCLKO.UART5_RTSn */ /* WiFi_UART_RTS */ + AM62X_IOPAD(0x0034, PIN_INPUT_PULLUP, 5) /* (H21) OSPI0_CSn2.UART5_RXD */ /* WiFi_UART_RXD */ + AM62X_IOPAD(0x0038, PIN_OUTPUT, 5) /* (E24) OSPI0_CSn3.UART5_TXD */ /* WiFi_UART_TXD */ + >; + }; + + /* Verdin USB_1 */ + pinctrl_usb0: main-usb0-default-pins { + pinctrl-single,pins = < + AM62X_IOPAD(0x0254, PIN_OUTPUT, 0) /* (C20) USB0_DRVVBUS */ /* SODIMM 155 */ + >; + }; + + /* Verdin USB_2 */ + pinctrl_usb1: main-usb1-default-pins { + pinctrl-single,pins = < + AM62X_IOPAD(0x0258, PIN_OUTPUT, 0) /* (F18) USB1_DRVVBUS */ /* SODIMM 185 */ + >; + }; + + /* DSS VOUT0 RGB */ + pinctrl_parallel_rgb: main-vout-default-pins { + pinctrl-single,pins = < + AM62X_IOPAD(0x0100, PIN_OUTPUT, 0) /* (AC25) VOUT0_VSYNC */ + AM62X_IOPAD(0x00f8, PIN_OUTPUT, 0) /* (AB24) VOUT0_HSYNC */ + AM62X_IOPAD(0x0104, PIN_OUTPUT, 0) /* (AC24) VOUT0_PCLK */ + AM62X_IOPAD(0x00fc, PIN_OUTPUT, 0) /* (Y20) VOUT0_DE */ + AM62X_IOPAD(0x00b8, PIN_OUTPUT, 0) /* (U22) VOUT0_DATA0 */ + AM62X_IOPAD(0x00bc, PIN_OUTPUT, 0) /* (V24) VOUT0_DATA1 */ + AM62X_IOPAD(0x00c0, PIN_OUTPUT, 0) /* (W25) VOUT0_DATA2 */ + AM62X_IOPAD(0x00c4, PIN_OUTPUT, 0) /* (W24) VOUT0_DATA3 */ + AM62X_IOPAD(0x00c8, PIN_OUTPUT, 0) /* (Y25) VOUT0_DATA4 */ + AM62X_IOPAD(0x00cc, PIN_OUTPUT, 0) /* (Y24) VOUT0_DATA5 */ + AM62X_IOPAD(0x00d0, PIN_OUTPUT, 0) /* (Y23) VOUT0_DATA6 */ + AM62X_IOPAD(0x00d4, PIN_OUTPUT, 0) /* (AA25) VOUT0_DATA7 */ + AM62X_IOPAD(0x00d8, PIN_OUTPUT, 0) /* (V21) VOUT0_DATA8 */ + AM62X_IOPAD(0x00dc, PIN_OUTPUT, 0) /* (W21) VOUT0_DATA9 */ + AM62X_IOPAD(0x00e0, PIN_OUTPUT, 0) /* (V20) VOUT0_DATA10 */ + AM62X_IOPAD(0x00e4, PIN_OUTPUT, 0) /* (AA23) VOUT0_DATA11 */ + AM62X_IOPAD(0x00e8, PIN_OUTPUT, 0) /* (AB25) VOUT0_DATA12 */ + AM62X_IOPAD(0x00ec, PIN_OUTPUT, 0) /* (AA24) VOUT0_DATA13 */ + AM62X_IOPAD(0x00f0, PIN_OUTPUT, 0) /* (Y22) VOUT0_DATA14 */ + AM62X_IOPAD(0x00f4, PIN_OUTPUT, 0) /* (AA21) VOUT0_DATA15 */ + AM62X_IOPAD(0x005c, PIN_OUTPUT, 1) /* (R24) GPMC0_AD8.VOUT0_DATA16 */ + AM62X_IOPAD(0x0060, PIN_OUTPUT, 1) /* (R25) GPMC0_AD9.VOUT0_DATA17 */ + >; + }; +}; + +&mcu_pmx0 { + /* Verdin PCIE_1_RESET# */ + pinctrl_pcie_1_reset: mcu-gpio0-0-default-pins { + pinctrl-single,pins = < + AM62X_MCU_IOPAD(0x0000, PIN_INPUT, 7) /* (E8) MCU_SPI0_CS0.MCU_GPIO0_0 */ /* SODIMM 244 */ + >; + }; + + /* Verdin GPIO_1 */ + pinctrl_gpio_1: mcu-gpio0-1-default-pins { + pinctrl-single,pins = < + AM62X_MCU_IOPAD(0x0004, PIN_INPUT, 7) /* (B8) MCU_SPI0_CS1.MCU_GPIO0_1 */ /* SODIMM 206 */ + >; + }; + + /* Verdin GPIO_2 */ + pinctrl_gpio_2: mcu-gpio0-2-default-pins { + pinctrl-single,pins = < + AM62X_MCU_IOPAD(0x0008, PIN_INPUT, 7) /* (A7) MCU_SPI0_CLK.MCU_GPIO0_2 */ /* SODIMM 208 */ + >; + }; + + /* Verdin GPIO_3 */ + pinctrl_gpio_3: mcu-gpio0-3-default-pins { + pinctrl-single,pins = < + AM62X_MCU_IOPAD(0x000c, PIN_INPUT, 7) /* (D9) MCU_SPI0_D0.MCU_GPIO0_3 */ /* SODIMM 210 */ + >; + }; + + /* Verdin GPIO_4 */ + pinctrl_gpio_4: mcu-gpio0-4-default-pins { + pinctrl-single,pins = < + AM62X_MCU_IOPAD(0x0010, PIN_INPUT, 7) /* (C9) MCU_SPI0_D1.MCU_GPIO0_4 */ /* SODIMM 212 */ + >; + }; + + /* Verdin I2C_3_HDMI */ + pinctrl_mcu_i2c0: mcu-i2c0-default-pins { + pinctrl-single,pins = < + AM62X_MCU_IOPAD(0x0044, PIN_INPUT, 0) /* (A8) MCU_I2C0_SCL */ /* SODIMM 59 */ + AM62X_MCU_IOPAD(0x0048, PIN_INPUT, 0) /* (D10) MCU_I2C0_SDA */ /* SODIMM 57 */ + >; + }; + + /* Verdin UART_4 - Reserved to Cortex-M4 */ + pinctrl_mcu_uart0: mcu-uart0-default-pins { + pinctrl-single,pins = < + AM62X_MCU_IOPAD(0x0014, PIN_INPUT_PULLUP, 0) /* (B5) MCU_UART0_RXD */ /* SODIMM 151 */ + AM62X_MCU_IOPAD(0x0018, PIN_OUTPUT, 0) /* (A5) MCU_UART0_TXD */ /* SODIMM 153 */ + >; + }; + + /* Verdin CSI_1_MCLK */ + pinctrl_csi1_mclk: wkup-clkout0-default-pins { + pinctrl-single,pins = < + AM62X_MCU_IOPAD(0x0084, PIN_OUTPUT, 0) /* (A12) WKUP_CLKOUT0 */ /* SODIMM 91 */ + >; + }; + + /* Verdin UART_2 */ + pinctrl_wkup_uart0: wkup-uart0-default-pins { + pinctrl-single,pins = < + AM62X_MCU_IOPAD(0x002c, PIN_INPUT_PULLUP, 0) /* (C6) WKUP_UART0_CTSn */ /* SODIMM 143 */ + AM62X_MCU_IOPAD(0x0030, PIN_OUTPUT, 0) /* (A4) WKUP_UART0_RTSn */ /* SODIMM 141 */ + AM62X_MCU_IOPAD(0x0024, PIN_INPUT_PULLUP, 0) /* (B4) WKUP_UART0_RXD */ /* SODIMM 137 */ + AM62X_MCU_IOPAD(0x0028, PIN_OUTPUT, 0) /* (C5) WKUP_UART0_TXD */ /* SODIMM 139 */ + >; + }; +}; + +&cpsw3g { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_rgmii1>; + status = "disabled"; +}; + +/* Verdin ETH_1 (On-module PHY) */ +&cpsw_port1 { + phy-handle = <&cpsw3g_phy0>; + phy-mode = "rgmii-rxid"; + status = "disabled"; +}; + +/* Verdin ETH_2_RGMII */ +&cpsw_port2 { + status = "disabled"; +}; + +/* MDIO, shared by Verdin ETH_1 (On-module PHY) and Verdin ETH_2_RGMII */ +&cpsw3g_mdio { + assigned-clocks = <&k3_clks 157 20>; + assigned-clock-parents = <&k3_clks 157 22>; + assigned-clock-rates = <25000000>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_eth_clock>, <&pinctrl_mdio>; + status = "disabled"; + + cpsw3g_phy0: ethernet-phy@0 { + compatible = "ethernet-phy-id2000.a231"; + reg = <0>; + interrupt-parent = <&main_gpio0>; + interrupts = <25 IRQ_TYPE_EDGE_FALLING>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_eth_int>, <&pinctrl_eth_reset>; + reset-gpios = <&main_gpio0 17 GPIO_ACTIVE_LOW>; + reset-assert-us = <10>; + reset-deassert-us = <1000>; + ti,fifo-depth = ; + ti,rx-internal-delay = ; + }; +}; + +/* Verdin PWM_1, PWM_2 */ +&epwm0 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_epwm0_a>, <&pinctrl_epwm0_b>; + status = "disabled"; +}; + +/* Verdin PWM_3_DSI */ +&epwm1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_epwm1_a>; + status = "disabled"; +}; + +&main_gpio0 { + gpio-line-names = + "SODIMM_52", /* 0 */ + "", + "", + "SODIMM_56", + "SODIMM_58", + "SODIMM_60", + "SODIMM_62", + "", + "", + "", + "", /* 10 */ + "SODIMM_54", + "SODIMM_64", + "", + "", + "SODIMM_174", + "SODIMM_172", + "", + "", + "", + "", /* 20 */ + "", + "", + "", + "", + "", + "", + "", + "", + "SODIMM_76", + "SODIMM_21", /* 30 */ + "SODIMM_256", + "SODIMM_252", + "", + "SODIMM_46", + "SODIMM_42", + "SODIMM_218", + "", + "SODIMM_189", + "", + "SODIMM_216", /* 40 */ + "SODIMM_220", + "SODIMM_222", + "", + "", + "", + "", + "", + "", + "", + "", /* 50 */ + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", /* 60 */ + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", /* 70 */ + "SODIMM_157", + "SODIMM_187", + "", + "", + "", + "", + "", + "", + "", + "", /* 80 */ + "", + "", + "", + "", + "", + ""; + + verdin_ctrl_sleep_moci: ctrl-sleep-moci-hog { + gpio-hog; + /* Verdin CTRL_SLEEP_MOCI# (SODIMM 256) */ + gpios = <31 GPIO_ACTIVE_HIGH>; + line-name = "CTRL_SLEEP_MOCI#"; + output-high; + }; +}; + +&main_gpio1 { + gpio-line-names = + "", /* 0 */ + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", /* 10 */ + "", + "", + "", + "", + "SODIMM_15", + "SODIMM_16", + "SODIMM_19", + "SODIMM_66", + "SODIMM_161", + "", /* 20 */ + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", /* 30 */ + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", /* 40 */ + "", + "", + "", + "", + "", + "", + "", + "", + "SODIMM_17", + "", /* 50 */ + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", /* 60 */ + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", /* 70 */ + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", /* 80 */ + "", + "", + "", + "", + "", + "", + ""; +}; + +/* On-module I2C - PMIC_I2C */ +&main_i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c0>; + clock-frequency = <400000>; + status = "okay"; + + dsi_bridge: dsi@e { + compatible = "toshiba,tc358778"; + reg = <0xe>; + assigned-clocks = <&k3_clks 157 20>; + assigned-clock-parents = <&k3_clks 157 22>; + assigned-clock-rates = <25000000>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_bridge_reset>; + clocks = <&k3_clks 157 20>; + clock-names = "refclk"; + reset-gpios = <&main_gpio0 20 GPIO_ACTIVE_LOW>; + vddc-supply = <®_1v2_dsi>; + vddmipi-supply = <®_1v2_dsi>; + vddio-supply = <®_1v8_dsi>; + + dsi_bridge_ports: ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + rgb_in: endpoint { + data-lines = <18>; + }; + }; + + port@1 { + reg = <1>; + }; + }; + }; + + pmic@30 { + compatible = "ti,tps65219"; + reg = <0x30>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_pmic_extint>; + interrupt-parent = <&gic500>; + interrupts = ; + + buck1-supply = <®_vsodimm>; + buck2-supply = <®_vsodimm>; + buck3-supply = <®_vsodimm>; + ldo1-supply = <®_3v3>; + ldo2-supply = <®_1v8>; + ldo3-supply = <®_3v3>; + ldo4-supply = <®_3v3>; + system-power-controller; + ti,power-button; + + regulators { + reg_vdd_core: buck1 { + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <850000>; + regulator-min-microvolt = <850000>; + regulator-name = "+VDD_CORE (PMIC BUCK1)"; + }; + + reg_1v8: buck2 { + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <1800000>; + regulator-min-microvolt = <1800000>; + regulator-name = "+V1.8 (PMIC BUCK2)"; /* On-module and SODIMM 214 */ + }; + + reg_vdd_ddr: buck3 { + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <1100000>; + regulator-min-microvolt = <1100000>; + regulator-name = "+VDD_DDR (PMIC BUCK3)"; + }; + + reg_sd_3v3_1v8: ldo1 { + regulator-allow-bypass; + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <3300000>; + regulator-min-microvolt = <3300000>; + regulator-name = "+V3.3_1.8_SD (PMIC LDO1)"; + }; + + reg_vddr_core: ldo2 { + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <850000>; + regulator-min-microvolt = <850000>; + regulator-name = "+VDDR_CORE (PMIC LDO2)"; + }; + + reg_1v8a: ldo3 { + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <1800000>; + regulator-min-microvolt = <1800000>; + regulator-name = "+V1.8A (PMIC LDO3)"; + }; + + reg_eth_2v5: ldo4 { + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <2500000>; + regulator-min-microvolt = <2500000>; + regulator-name = "+V2.5_ETH (PMIC LDO4)"; + }; + }; + }; + + rtc_i2c: rtc@32 { + compatible = "epson,rx8130"; + reg = <0x32>; + }; + + sensor@48 { + compatible = "ti,tmp1075"; + reg = <0x48>; + }; + + adc@49 { + compatible = "ti,ads1015"; + reg = <0x49>; + #address-cells = <1>; + #size-cells = <0>; + + /* Verdin PMIC_I2C (ADC_4 - ADC_3) */ + channel@0 { + reg = <0>; + ti,datarate = <4>; + ti,gain = <2>; + }; + + /* Verdin PMIC_I2C (ADC_4 - ADC_1) */ + channel@1 { + reg = <1>; + ti,datarate = <4>; + ti,gain = <2>; + }; + + /* Verdin PMIC_I2C (ADC_3 - ADC_1) */ + channel@2 { + reg = <2>; + ti,datarate = <4>; + ti,gain = <2>; + }; + + /* Verdin PMIC_I2C (ADC_2 - ADC_1) */ + channel@3 { + reg = <3>; + ti,datarate = <4>; + ti,gain = <2>; + }; + + /* Verdin PMIC_I2C ADC_4 */ + channel@4 { + reg = <4>; + ti,datarate = <4>; + ti,gain = <2>; + }; + + /* Verdin PMIC_I2C ADC_3 */ + channel@5 { + reg = <5>; + ti,datarate = <4>; + ti,gain = <2>; + }; + + /* Verdin PMIC_I2C ADC_2 */ + channel@6 { + reg = <6>; + ti,datarate = <4>; + ti,gain = <2>; + }; + + /* Verdin PMIC_I2C ADC_1 */ + channel@7 { + reg = <7>; + ti,datarate = <4>; + ti,gain = <2>; + }; + }; + + eeprom@50 { + compatible = "st,24c02", "atmel,24c02"; + pagesize = <16>; + reg = <0x50>; + }; +}; + +/* Verdin I2C_1 */ +&main_i2c1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c1>; + status = "disabled"; +}; + +/* Verdin I2C_2_DSI */ +&main_i2c2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c2>; + status = "disabled"; +}; + +/* Verdin I2C_4_CSI */ +&main_i2c3 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c3>; + status = "disabled"; +}; + +&mailbox0_cluster0 { + mbox_m4_0: mbox-m4-0 { + ti,mbox-rx = <0 0 0>; + ti,mbox-tx = <1 0 0>; + }; +}; + +/* Verdin CAN_1 */ +&main_mcan0 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_mcan0>; + status = "disabled"; +}; + +/* Verdin CAN_2 - Reserved to Cortex-M4 */ + +/* Verdin SPI_1 */ +&main_spi1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_spi1>; + ti,pindir-d0-out-d1-in; + status = "disabled"; +}; + +/* Verdin UART_3, used as the Linux console */ +&main_uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart0>; + status = "disabled"; +}; + +/* Verdin UART_1 */ +&main_uart1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart1>; + status = "disabled"; +}; + +/* Verdin I2S_1 */ +&mcasp0 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_mcasp0>; + op-mode = <0>; /* I2S mode */ + serial-dir = < /* 0: INACTIVE, 1: TX, 2: RX */ + 1 2 0 0 + 0 0 0 0 + 0 0 0 0 + 0 0 0 0 + >; + tdm-slots = <2>; + rx-num-evt = <32>; + tx-num-evt = <32>; + #sound-dai-cells = <0>; + status = "disabled"; +}; + +/* Verdin I2S_2 */ +&mcasp1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_mcasp1>; + op-mode = <0>; /* I2S mode */ + serial-dir = < /* 0: INACTIVE, 1: TX, 2: RX */ + 1 2 0 0 + 0 0 0 0 + 0 0 0 0 + 0 0 0 0 + >; + tdm-slots = <2>; + rx-num-evt = <32>; + tx-num-evt = <32>; + #sound-dai-cells = <0>; + status = "disabled"; +}; + +/* Verdin I2C_3_HDMI */ +&mcu_i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_mcu_i2c0>; + status = "disabled"; +}; + +&mcu_gpio0 { + gpio-line-names = + "SODIMM_244", + "SODIMM_206", + "SODIMM_208", + "SODIMM_210", + "SODIMM_212", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + ""; +}; + +/* Verdin UART_4 - Cortex-M4 UART */ +&mcu_uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_mcu_uart0>; + status = "disabled"; +}; + +/* Verdin QSPI_1 */ +&ospi0 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_ospi0>; + status = "disabled"; +}; + +/* On-module eMMC */ +&sdhci0 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_sdhci0>; + non-removable; + ti,driver-strength-ohm = <50>; + status = "okay"; +}; + +/* Verdin SD_1 */ +&sdhci1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_sdhci1>; + disable-wp; + ti,driver-strength-ohm = <50>; + vmmc-supply = <®_sdhc1_vmmc>; + vqmmc-supply = <®_sdhc1_vqmmc>; + status = "disabled"; +}; + +/* Verdin USB_1 */ +&usbss0 { + ti,vbus-divider; + status = "disabled"; +}; + +/* TODO: role swich using ID pin */ +&usb0 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usb0>, <&pinctrl_usb0_id>; + status = "disabled"; +}; + +/* Verdin USB_2 */ +&usbss1 { + ti,vbus-divider; + status = "disabled"; +}; + +&usb1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usb1>; + dr_mode = "host"; + status = "disabled"; +}; + +/* Verdin UART_2 */ +&wkup_uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_wkup_uart0>; + status = "disabled"; +}; diff --git a/arch/arm64/boot/dts/ti/k3-am62-wakeup.dtsi b/arch/arm64/boot/dts/ti/k3-am62-wakeup.dtsi index 7726ebae25394ffa70ace837dc328bba83b7ee23..eae0528871862852aa19670fb6f1ccde5e334f56 100644 --- a/arch/arm64/boot/dts/ti/k3-am62-wakeup.dtsi +++ b/arch/arm64/boot/dts/ti/k3-am62-wakeup.dtsi @@ -61,4 +61,12 @@ /* Used by DM firmware */ status = "reserved"; }; + + wkup_vtm0: temperature-sensor@b00000 { + compatible = "ti,j7200-vtm"; + reg = <0x00 0xb00000 0x00 0x400>, + <0x00 0xb01000 0x00 0x400>; + power-domains = <&k3_pds 95 TI_SCI_PD_EXCLUSIVE>; + #thermal-sensor-cells = <1>; + }; }; diff --git a/arch/arm64/boot/dts/ti/k3-am62.dtsi b/arch/arm64/boot/dts/ti/k3-am62.dtsi index a401f5225243930d141de80413a6530341ddd03c..5e72c445f37a9613b81de6ca4ad54b6b66e5f0c8 100644 --- a/arch/arm64/boot/dts/ti/k3-am62.dtsi +++ b/arch/arm64/boot/dts/ti/k3-am62.dtsi @@ -81,6 +81,7 @@ <0x00 0x04000000 0x00 0x04000000 0x00 0x01ff1400>, /* Wakeup Domain Range */ + <0x00 0x00b00000 0x00 0x00b00000 0x00 0x00002400>, /* VTM */ <0x00 0x2b000000 0x00 0x2b000000 0x00 0x00300400>, <0x00 0x43000000 0x00 0x43000000 0x00 0x00020000>; @@ -91,14 +92,17 @@ ranges = <0x00 0x04000000 0x00 0x04000000 0x00 0x01ff1400>; /* Peripheral window */ }; - cbass_wakeup: bus@2b000000 { + cbass_wakeup: bus@b00000 { compatible = "simple-bus"; #address-cells = <2>; #size-cells = <2>; - ranges = <0x00 0x2b000000 0x00 0x2b000000 0x00 0x00300400>, /* Peripheral Window */ + ranges = <0x00 0x00b00000 0x00 0x00b00000 0x00 0x00002400>, /* VTM */ + <0x00 0x2b000000 0x00 0x2b000000 0x00 0x00300400>, /* Peripheral Window */ <0x00 0x43000000 0x00 0x43000000 0x00 0x00020000>; }; }; + + #include "k3-am62-thermal.dtsi" }; /* Now include the peripherals for each bus segments */ diff --git a/arch/arm64/boot/dts/ti/k3-am625-beagleplay.dts b/arch/arm64/boot/dts/ti/k3-am625-beagleplay.dts index cb46c38ce2cc13dd68bf49b2831d87cb8a89252e..589bf998bc5281bf564135b147ffef0810976585 100644 --- a/arch/arm64/boot/dts/ti/k3-am625-beagleplay.dts +++ b/arch/arm64/boot/dts/ti/k3-am625-beagleplay.dts @@ -216,7 +216,7 @@ }; &main_pmx0 { - gpio0_pins_default: gpio0-pins-default { + gpio0_pins_default: gpio0-default-pins { pinctrl-single,pins = < AM62X_IOPAD(0x0004, PIN_INPUT, 7) /* (G25) OSPI0_LBCLKO.GPIO0_1 */ AM62X_IOPAD(0x0008, PIN_INPUT, 7) /* (J24) OSPI0_DQS.GPIO0_2 */ @@ -235,47 +235,47 @@ >; }; - vdd_sd_dv_pins_default: vdd-sd-pins-default { + vdd_sd_dv_pins_default: vdd-sd-default-pins { pinctrl-single,pins = < AM62X_IOPAD(0x0244, PIN_OUTPUT, 7) /* (C17) MMC1_SDWP.GPIO1_49 */ >; }; - usr_button_pins_default: usr-button-pins-default { + usr_button_pins_default: usr-button-default-pins { pinctrl-single,pins = < AM62X_IOPAD(0x0048, PIN_INPUT, 7) /* (N25) GPMC0_AD3.GPIO0_18 */ >; }; - grove_pins_default: grove-pins-default { + grove_pins_default: grove-default-pins { pinctrl-single,pins = < AM62X_IOPAD(0x01e8, PIN_INPUT_PULLUP, 0) /* (B17) I2C1_SCL */ AM62X_IOPAD(0x01ec, PIN_INPUT_PULLUP, 0) /* (A17) I2C1_SDA */ >; }; - local_i2c_pins_default: local-i2c-pins-default { + local_i2c_pins_default: local-i2c-default-pins { pinctrl-single,pins = < AM62X_IOPAD(0x01e0, PIN_INPUT_PULLUP, 0) /* (B16) I2C0_SCL */ AM62X_IOPAD(0x01e4, PIN_INPUT_PULLUP, 0) /* (A16) I2C0_SDA */ >; }; - i2c2_1v8_pins_default: i2c2-pins-default { + i2c2_1v8_pins_default: i2c2-default-pins { pinctrl-single,pins = < AM62X_IOPAD(0x00b0, PIN_INPUT_PULLUP, 1) /* (K22) GPMC0_CSn2.I2C2_SCL */ AM62X_IOPAD(0x00b4, PIN_INPUT_PULLUP, 1) /* (K24) GPMC0_CSn3.I2C2_SDA */ >; }; - mdio0_pins_default: mdio0-pins-default { + mdio0_pins_default: mdio0-default-pins { pinctrl-single,pins = < AM62X_IOPAD(0x0160, PIN_OUTPUT, 7) /* (AD24) MDIO0_MDC.GPIO0_86 */ AM62X_IOPAD(0x015c, PIN_INPUT, 7) /* (AB22) MDIO0_MDIO.GPIO0_85 */ >; }; - rgmii1_pins_default: rgmii1-pins-default { + rgmii1_pins_default: rgmii1-default-pins { pinctrl-single,pins = < AM62X_IOPAD(0x014c, PIN_INPUT, 0) /* (AB17) RGMII1_RD0 */ AM62X_IOPAD(0x0150, PIN_INPUT, 0) /* (AC17) RGMII1_RD1 */ @@ -292,7 +292,7 @@ >; }; - emmc_pins_default: emmc-pins-default { + emmc_pins_default: emmc-default-pins { pinctrl-single,pins = < AM62X_IOPAD(0x0220, PIN_INPUT, 0) /* (Y3) MMC0_CMD */ AM62X_IOPAD(0x0218, PIN_INPUT, 0) /* (AB1) MMC0_CLK */ @@ -307,13 +307,13 @@ >; }; - vdd_3v3_sd_pins_default: vdd-3v3-sd-pins-default { + vdd_3v3_sd_pins_default: vdd-3v3-sd-default-pins { pinctrl-single,pins = < AM62X_IOPAD(0x01c4, PIN_INPUT, 7) /* (B14) SPI0_D1_GPIO1_19 */ >; }; - sd_pins_default: sd-pins-default { + sd_pins_default: sd-default-pins { pinctrl-single,pins = < AM62X_IOPAD(0x023c, PIN_INPUT, 0) /* (A21) MMC1_CMD */ AM62X_IOPAD(0x0234, PIN_INPUT, 0) /* (B22) MMC1_CLK */ @@ -325,7 +325,7 @@ >; }; - wifi_pins_default: wifi-pins-default { + wifi_pins_default: wifi-default-pins { pinctrl-single,pins = < AM62X_IOPAD(0x0120, PIN_INPUT, 0) /* (C24) MMC2_CMD */ AM62X_IOPAD(0x0118, PIN_INPUT, 0) /* (D25) MMC2_CLK */ @@ -338,19 +338,19 @@ >; }; - wifi_en_pins_default: wifi-en-pins-default { + wifi_en_pins_default: wifi-en-default-pins { pinctrl-single,pins = < AM62X_IOPAD(0x009c, PIN_OUTPUT, 7) /* (V25) GPMC0_WAIT1.GPIO0_38 */ >; }; - wifi_wlirq_pins_default: wifi-wlirq-pins-default { + wifi_wlirq_pins_default: wifi-wlirq-default-pins { pinctrl-single,pins = < AM62X_IOPAD(0x00a8, PIN_INPUT, 7) /* (M21) GPMC0_CSn0.GPIO0_41 */ >; }; - spe_pins_default: spe-pins-default { + spe_pins_default: spe-default-pins { pinctrl-single,pins = < AM62X_IOPAD(0x0168, PIN_INPUT, 1) /* (AE21) RGMII2_TXC.RMII2_CRS_DV */ AM62X_IOPAD(0x0180, PIN_INPUT, 1) /* (AD23) RGMII2_RXC.RMII2_REF_CLK */ @@ -366,21 +366,21 @@ >; }; - mikrobus_i2c_pins_default: mikrobus-i2c-pins-default { + mikrobus_i2c_pins_default: mikrobus-i2c-default-pins { pinctrl-single,pins = < AM62X_IOPAD(0x01d0, PIN_INPUT_PULLUP, 2) /* (A15) UART0_CTSn.I2C3_SCL */ AM62X_IOPAD(0x01d4, PIN_INPUT_PULLUP, 2) /* (B15) UART0_RTSn.I2C3_SDA */ >; }; - mikrobus_uart_pins_default: mikrobus-uart-pins-default { + mikrobus_uart_pins_default: mikrobus-uart-default-pins { pinctrl-single,pins = < AM62X_IOPAD(0x01d8, PIN_INPUT, 1) /* (C15) MCAN0_TX.UART5_RXD */ AM62X_IOPAD(0x01dc, PIN_OUTPUT, 1) /* (E15) MCAN0_RX.UART5_TXD */ >; }; - mikrobus_spi_pins_default: mikrobus-spi-pins-default { + mikrobus_spi_pins_default: mikrobus-spi-default-pins { pinctrl-single,pins = < AM62X_IOPAD(0x01b0, PIN_INPUT, 1) /* (A20) MCASP0_ACLKR.SPI2_CLK */ AM62X_IOPAD(0x01ac, PIN_INPUT, 1) /* (E19) MCASP0_AFSR.SPI2_CS0 */ @@ -389,7 +389,7 @@ >; }; - mikrobus_gpio_pins_default: mikrobus-gpio-pins-default { + mikrobus_gpio_pins_default: mikrobus-gpio-default-pins { pinctrl-single,pins = < AM62X_IOPAD(0x019c, PIN_INPUT, 7) /* (B18) MCASP0_AXR1.GPIO1_9 */ AM62X_IOPAD(0x01a0, PIN_INPUT, 7) /* (E18) MCASP0_AXR0.GPIO1_10 */ @@ -397,27 +397,27 @@ >; }; - console_pins_default: console-pins-default { + console_pins_default: console-default-pins { pinctrl-single,pins = < AM62X_IOPAD(0x01c8, PIN_INPUT, 0) /* (D14) UART0_RXD */ AM62X_IOPAD(0x01cc, PIN_OUTPUT, 0) /* (E14) UART0_TXD */ >; }; - wifi_debug_uart_pins_default: wifi-debug-uart-pins-default { + wifi_debug_uart_pins_default: wifi-debug-uart-default-pins { pinctrl-single,pins = < AM62X_IOPAD(0x001c, PIN_INPUT, 3) /* (J23) OSPI0_D4.UART6_RXD */ AM62X_IOPAD(0x0020, PIN_OUTPUT, 3) /* (J25) OSPI0_D5.UART6_TXD */ >; }; - usb1_pins_default: usb1-pins-default { + usb1_pins_default: usb1-default-pins { pinctrl-single,pins = < AM62X_IOPAD(0x0258, PIN_INPUT, 0) /* (F18) USB1_DRVVBUS */ >; }; - pmic_irq_pins_default: pmic-irq-pins-default { + pmic_irq_pins_default: pmic-irq-default-pins { pinctrl-single,pins = < AM62X_IOPAD(0x01f4, PIN_INPUT_PULLUP, 0) /* (D16) EXTINTn */ >; @@ -425,7 +425,7 @@ }; &mcu_pmx0 { - i2c_qwiic_pins_default: i2c-qwiic-pins-default { + i2c_qwiic_pins_default: i2c-qwiic-default-pins { pinctrl-single,pins = < AM62X_MCU_IOPAD(0x0044, PIN_INPUT, 0) /* (A8) MCU_I2C0_SCL */ AM62X_MCU_IOPAD(0x0048, PIN_INPUT, 0) /* (D10) MCU_I2C0_SDA */ @@ -438,14 +438,14 @@ >; }; - i2c_csi_pins_default: i2c-csi-pins-default { + i2c_csi_pins_default: i2c-csi-default-pins { pinctrl-single,pins = < AM62X_MCU_IOPAD(0x004c, PIN_INPUT_PULLUP, 0) /* (B9) WKUP_I2C0_SCL */ AM62X_MCU_IOPAD(0x0050, PIN_INPUT_PULLUP, 0) /* (A9) WKUP_I2C0_SDA */ >; }; - wifi_32k_clk: mcu-clk-out-pins-default { + wifi_32k_clk: mcu-clk-out-default-pins { pinctrl-single,pins = < AM62X_MCU_IOPAD(0x0084, PIN_OUTPUT, 0) /* (A12) WKUP_CLKOUT0 */ >; diff --git a/arch/arm64/boot/dts/ti/k3-am625-phyboard-lyra-rdk.dts b/arch/arm64/boot/dts/ti/k3-am625-phyboard-lyra-rdk.dts new file mode 100644 index 0000000000000000000000000000000000000000..a438baf542c22588ce6d54b65e332095247abd3a --- /dev/null +++ b/arch/arm64/boot/dts/ti/k3-am625-phyboard-lyra-rdk.dts @@ -0,0 +1,266 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2022 - 2023 PHYTEC Messtechnik GmbH + * Author: Wadim Egorov + * + * Product homepage: + * https://www.phytec.com/product/phyboard-am62x + */ + +#include +#include +#include +#include +#include "k3-am625.dtsi" +#include "k3-am62-phycore-som.dtsi" + +/ { + compatible = "phytec,am625-phyboard-lyra-rdk", + "phytec,am62-phycore-som", "ti,am625"; + model = "PHYTEC phyBOARD-Lyra AM625"; + + aliases { + serial2 = &main_uart0; + serial3 = &main_uart1; + mmc1 = &sdhci1; + usb0 = &usb0; + usb1 = &usb1; + ethernet1 = &cpsw_port2; + }; + + can_tc1: can-phy0 { + compatible = "ti,tcan1042"; + #phy-cells = <0>; + max-bitrate = <5000000>; + standby-gpios = <&gpio_exp 1 GPIO_ACTIVE_HIGH>; + }; + + keys { + compatible = "gpio-keys"; + autorepeat; + pinctrl-names = "default"; + pinctrl-0 = <&gpio_keys_pins_default>; + + key-home { + label = "home"; + linux,code = ; + gpios = <&main_gpio1 23 GPIO_ACTIVE_HIGH>; + }; + + key-menu { + label = "menu"; + linux,code = ; + gpios = <&gpio_exp 4 GPIO_ACTIVE_HIGH>; + }; + }; + + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&leds_pins_default>, <&user_leds_pins_default>; + + led-1 { + gpios = <&main_gpio0 32 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "mmc0"; + }; + + led-2 { + gpios = <&gpio_exp 2 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "mmc1"; + }; + }; + + vcc_3v3_mmc: regulator-vcc-3v3-mmc { + compatible = "regulator-fixed"; + regulator-name = "VCC_3V3_MMC"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-boot-on; + }; +}; + +&main_pmx0 { + gpio_keys_pins_default: gpio-keys-default-pins { + pinctrl-single,pins = < + AM62X_IOPAD(0x1d4, PIN_INPUT, 7) /* (B15) UART0_RTSn.GPIO1_23 */ + >; + }; + + gpio_exp_int_pins_default: gpio-exp-int-default-pins { + pinctrl-single,pins = < + AM62X_IOPAD(0x244, PIN_INPUT, 7) /* (C17) MMC1_SDWP.GPIO1_49 */ + >; + }; + + main_i2c1_pins_default: main-i2c1-default-pins { + pinctrl-single,pins = < + AM62X_IOPAD(0x1e8, PIN_INPUT_PULLUP, 0) /* (B17) I2C1_SCL */ + AM62X_IOPAD(0x1ec, PIN_INPUT_PULLUP, 0) /* (A17) I2C1_SDA */ + >; + }; + + main_mcan0_pins_default: main-mcan0-default-pins { + pinctrl-single,pins = < + AM62X_IOPAD(0x1dc, PIN_INPUT, 0) /* (E15) MCAN0_RX */ + AM62X_IOPAD(0x1d8, PIN_OUTPUT, 0) /* (C15) MCAN0_TX */ + >; + }; + + main_mmc1_pins_default: main-mmc1-default-pins { + pinctrl-single,pins = < + AM62X_IOPAD(0x23c, PIN_INPUT_PULLUP, 0) /* (A21) MMC1_CMD */ + AM62X_IOPAD(0x234, PIN_INPUT_PULLDOWN, 0) /* (B22) MMC1_CLK */ + AM62X_IOPAD(0x230, PIN_INPUT_PULLUP, 0) /* (A22) MMC1_DAT0 */ + AM62X_IOPAD(0x22c, PIN_INPUT_PULLUP, 0) /* (B21) MMC1_DAT1 */ + AM62X_IOPAD(0x228, PIN_INPUT_PULLUP, 0) /* (C21) MMC1_DAT2 */ + AM62X_IOPAD(0x224, PIN_INPUT_PULLUP, 0) /* (D22) MMC1_DAT3 */ + AM62X_IOPAD(0x240, PIN_INPUT_PULLUP, 0) /* (D17) MMC1_SDCD */ + >; + }; + + main_rgmii2_pins_default: main-rgmii2-default-pins { + pinctrl-single,pins = < + AM62X_IOPAD(0x184, PIN_INPUT, 0) /* (AE23) RGMII2_RD0 */ + AM62X_IOPAD(0x188, PIN_INPUT, 0) /* (AB20) RGMII2_RD1 */ + AM62X_IOPAD(0x18c, PIN_INPUT, 0) /* (AC21) RGMII2_RD2 */ + AM62X_IOPAD(0x190, PIN_INPUT, 0) /* (AE22) RGMII2_RD3 */ + AM62X_IOPAD(0x180, PIN_INPUT, 0) /* (AD23) RGMII2_RXC */ + AM62X_IOPAD(0x17c, PIN_INPUT, 0) /* (AD22) RGMII2_RX_CTL */ + AM62X_IOPAD(0x16c, PIN_OUTPUT, 0) /* (Y18) RGMII2_TD0 */ + AM62X_IOPAD(0x170, PIN_OUTPUT, 0) /* (AA18) RGMII2_TD1 */ + AM62X_IOPAD(0x174, PIN_OUTPUT, 0) /* (AD21) RGMII2_TD2 */ + AM62X_IOPAD(0x178, PIN_OUTPUT, 0) /* (AC20) RGMII2_TD3 */ + AM62X_IOPAD(0x168, PIN_OUTPUT, 0) /* (AE21) RGMII2_TXC */ + AM62X_IOPAD(0x164, PIN_OUTPUT, 0) /* (AA19) RGMII2_TX_CTL */ + >; + }; + + main_uart0_pins_default: main-uart0-default-pins { + pinctrl-single,pins = < + AM62X_IOPAD(0x1c8, PIN_INPUT, 0) /* (D14) UART0_RXD */ + AM62X_IOPAD(0x1cc, PIN_OUTPUT, 0) /* (E14) UART0_TXD */ + >; + }; + + main_uart1_pins_default: main-uart1-default-pins { + pinctrl-single,pins = < + AM62X_IOPAD(0x194, PIN_INPUT, 2) /* (B19) MCASP0_AXR3.UART1_CTSn */ + AM62X_IOPAD(0x198, PIN_OUTPUT, 2) /* (A19) MCASP0_AXR2.UART1_RTSn */ + AM62X_IOPAD(0x1ac, PIN_INPUT, 2) /* (E19) MCASP0_AFSR.UART1_RXD */ + AM62X_IOPAD(0x1b0, PIN_OUTPUT, 2) /* (A20) MCASP0_ACLKR.UART1_TXD */ + >; + }; + + main_usb1_pins_default: main-usb1-default-pins { + pinctrl-single,pins = < + AM62X_IOPAD(0x258, PIN_OUTPUT, 0) /* (F18) USB1_DRVVBUS */ + >; + }; + + user_leds_pins_default: user-leds-default-pins { + pinctrl-single,pins = < + AM62X_IOPAD(0x084, PIN_OUTPUT, 7) /* (L23) GPMC0_ADVn_ALE.GPIO0_32 */ + >; + }; +}; + +&cpsw3g { + pinctrl-names = "default"; + pinctrl-0 = <&main_rgmii1_pins_default>, <&main_rgmii2_pins_default>; +}; + +&cpsw_port2 { + phy-mode = "rgmii-rxid"; + phy-handle = <&cpsw3g_phy3>; +}; + +&cpsw3g_mdio { + cpsw3g_phy3: ethernet-phy@3 { + compatible = "ethernet-phy-id2000.a231", "ethernet-phy-ieee802.3-c22"; + reg = <3>; + ti,rx-internal-delay = ; + ti,fifo-depth = ; + }; +}; + +&main_i2c1 { + pinctrl-names = "default"; + pinctrl-0 = <&main_i2c1_pins_default>; + clock-frequency = <400000>; + status = "okay"; + + gpio_exp: gpio-expander@21 { + pinctrl-names = "default"; + pinctrl-0 = <&gpio_exp_int_pins_default>; + compatible = "nxp,pcf8574"; + reg = <0x21>; + interrupt-parent = <&main_gpio1>; + interrupts = <49 0>; + #gpio-cells = <2>; + gpio-controller; + interrupt-controller; + #interrupt-cells = <2>; + gpio-line-names = "GPIO0_HDMI_RST", "GPIO1_CAN0_nEN", + "GPIO2_LED2", "GPIO3_LVDS_GPIO", + "GPIO4_BUT2", "GPIO5_LVDS_BKLT_EN", + "GPIO6_ETH1_USER_RESET", "GPIO7_AUDIO_USER_RESET"; + }; + + eeprom@51 { + compatible = "atmel,24c02"; + pagesize = <16>; + reg = <0x51>; + }; +}; + +&main_mcan0 { + pinctrl-names = "default"; + pinctrl-0 = <&main_mcan0_pins_default>; + phys = <&can_tc1>; + status = "okay"; +}; + +&main_uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&main_uart0_pins_default>; + status = "okay"; +}; + +&main_uart1 { + pinctrl-names = "default"; + pinctrl-0 = <&main_uart1_pins_default>; + /* Main UART1 may be used by TIFS firmware */ + status = "okay"; +}; + +&sdhci1 { + vmmc-supply = <&vcc_3v3_mmc>; + vqmmc-supply = <&vddshv5_sdio>; + pinctrl-names = "default"; + pinctrl-0 = <&main_mmc1_pins_default>; + ti,driver-strength-ohm = <50>; + disable-wp; + no-1-8-v; + status = "okay"; +}; + +&usbss0 { + ti,vbus-divider; + status = "okay"; +}; + +&usbss1 { + ti,vbus-divider; + status = "okay"; +}; + +&usb0 { + dr_mode = "peripheral"; +}; + +&usb1 { + dr_mode = "host"; + pinctrl-names = "default"; + pinctrl-0 = <&main_usb1_pins_default>; +}; diff --git a/arch/arm64/boot/dts/ti/k3-am625-sk.dts b/arch/arm64/boot/dts/ti/k3-am625-sk.dts index 2a1adda9bff6a42bdb480daa0da4d3fc1d895209..3f9ef4053aa61e98d268538b8954fe56589bee52 100644 --- a/arch/arm64/boot/dts/ti/k3-am625-sk.dts +++ b/arch/arm64/boot/dts/ti/k3-am625-sk.dts @@ -101,7 +101,7 @@ }; &main_pmx0 { - main_rgmii2_pins_default: main-rgmii2-pins-default { + main_rgmii2_pins_default: main-rgmii2-default-pins { pinctrl-single,pins = < AM62X_IOPAD(0x184, PIN_INPUT, 0) /* (AE23) RGMII2_RD0 */ AM62X_IOPAD(0x188, PIN_INPUT, 0) /* (AB20) RGMII2_RD1 */ @@ -118,7 +118,7 @@ >; }; - ospi0_pins_default: ospi0-pins-default { + ospi0_pins_default: ospi0-default-pins { pinctrl-single,pins = < AM62X_IOPAD(0x000, PIN_OUTPUT, 0) /* (H24) OSPI0_CLK */ AM62X_IOPAD(0x02c, PIN_OUTPUT, 0) /* (F23) OSPI0_CSn0 */ @@ -134,13 +134,13 @@ >; }; - vdd_sd_dv_pins_default: vdd-sd-dv-pins-default { + vdd_sd_dv_pins_default: vdd-sd-dv-default-pins { pinctrl-single,pins = < AM62X_IOPAD(0x07c, PIN_OUTPUT, 7) /* (P25) GPMC0_CLK.GPIO0_31 */ >; }; - main_gpio1_ioexp_intr_pins_default: main-gpio1-ioexp-intr-pins-default { + main_gpio1_ioexp_intr_pins_default: main-gpio1-ioexp-intr-default-pins { pinctrl-single,pins = < AM62X_IOPAD(0x01d4, PIN_INPUT, 7) /* (B15) UART0_RTSn.GPIO1_23 */ >; @@ -161,7 +161,7 @@ "UART1_FET_BUF_EN", "WL_LT_EN", "GPIO_HDMI_RSTn", "CSI_GPIO1", "CSI_GPIO2", "PRU_3V3_EN", - "HDMI_INTn", "TEST_GPIO2", + "HDMI_INTn", "PD_I2C_IRQ", "MCASP1_FET_EN", "MCASP1_BUF_BT_EN", "MCASP1_FET_SEL", "UART1_FET_SEL", "TSINT#", "IO_EXP_TEST_LED"; @@ -183,8 +183,7 @@ &cpsw3g { pinctrl-names = "default"; - pinctrl-0 = <&main_rgmii1_pins_default - &main_rgmii2_pins_default>; + pinctrl-0 = <&main_rgmii1_pins_default>, <&main_rgmii2_pins_default>; }; &cpsw_port2 { diff --git a/arch/arm64/boot/dts/ti/k3-am625-verdin-nonwifi-dahlia.dts b/arch/arm64/boot/dts/ti/k3-am625-verdin-nonwifi-dahlia.dts new file mode 100644 index 0000000000000000000000000000000000000000..d38bfef29d71e9057c33274fc337f7971774c29f --- /dev/null +++ b/arch/arm64/boot/dts/ti/k3-am625-verdin-nonwifi-dahlia.dts @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT +/* + * Copyright 2023 Toradex + * + * https://www.toradex.com/computer-on-modules/verdin-arm-family/ti-am62 + * https://www.toradex.com/products/carrier-board/dahlia-carrier-board-kit + */ + +/dts-v1/; + +#include "k3-am625.dtsi" +#include "k3-am62-verdin.dtsi" +#include "k3-am62-verdin-nonwifi.dtsi" +#include "k3-am62-verdin-dahlia.dtsi" + +/ { + model = "Toradex Verdin AM62 on Dahlia Board"; + compatible = "toradex,verdin-am62-nonwifi-dahlia", + "toradex,verdin-am62-nonwifi", + "toradex,verdin-am62", + "ti,am625"; +}; diff --git a/arch/arm64/boot/dts/ti/k3-am625-verdin-nonwifi-dev.dts b/arch/arm64/boot/dts/ti/k3-am625-verdin-nonwifi-dev.dts new file mode 100644 index 0000000000000000000000000000000000000000..31d2a3066d43b05bb111d157facc07e301bb534c --- /dev/null +++ b/arch/arm64/boot/dts/ti/k3-am625-verdin-nonwifi-dev.dts @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT +/* + * Copyright 2023 Toradex + * + * https://www.toradex.com/computer-on-modules/verdin-arm-family/ti-am62 + * https://www.toradex.com/products/carrier-board/verdin-development-board-kit + */ + +/dts-v1/; + +#include "k3-am625.dtsi" +#include "k3-am62-verdin.dtsi" +#include "k3-am62-verdin-nonwifi.dtsi" +#include "k3-am62-verdin-dev.dtsi" + +/ { + model = "Toradex Verdin AM62 on Verdin Development Board"; + compatible = "toradex,verdin-am62-nonwifi-dev", + "toradex,verdin-am62-nonwifi", + "toradex,verdin-am62", + "ti,am625"; +}; diff --git a/arch/arm64/boot/dts/ti/k3-am625-verdin-nonwifi-yavia.dts b/arch/arm64/boot/dts/ti/k3-am625-verdin-nonwifi-yavia.dts new file mode 100644 index 0000000000000000000000000000000000000000..e80332e1f030bb4d37a63bdd03b3ef6378f5f8be --- /dev/null +++ b/arch/arm64/boot/dts/ti/k3-am625-verdin-nonwifi-yavia.dts @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT +/* + * Copyright 2023 Toradex + * + * https://www.toradex.com/computer-on-modules/verdin-arm-family/ti-am62 + * https://www.toradex.com/products/carrier-board/yavia + */ + +/dts-v1/; + +#include "k3-am625.dtsi" +#include "k3-am62-verdin.dtsi" +#include "k3-am62-verdin-nonwifi.dtsi" +#include "k3-am62-verdin-yavia.dtsi" + +/ { + model = "Toradex Verdin AM62 on Yavia Board"; + compatible = "toradex,verdin-am62-nonwifi-yavia", + "toradex,verdin-am62-nonwifi", + "toradex,verdin-am62", + "ti,am625"; +}; diff --git a/arch/arm64/boot/dts/ti/k3-am625-verdin-wifi-dahlia.dts b/arch/arm64/boot/dts/ti/k3-am625-verdin-wifi-dahlia.dts new file mode 100644 index 0000000000000000000000000000000000000000..3850a706edb77cfe394c13078b29afb7c2a4780f --- /dev/null +++ b/arch/arm64/boot/dts/ti/k3-am625-verdin-wifi-dahlia.dts @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT +/* + * Copyright 2023 Toradex + * + * https://www.toradex.com/computer-on-modules/verdin-arm-family/ti-am62 + * https://www.toradex.com/products/carrier-board/dahlia-carrier-board-kit + */ + +/dts-v1/; + +#include "k3-am625.dtsi" +#include "k3-am62-verdin.dtsi" +#include "k3-am62-verdin-wifi.dtsi" +#include "k3-am62-verdin-dahlia.dtsi" + +/ { + model = "Toradex Verdin AM62 WB on Dahlia Board"; + compatible = "toradex,verdin-am62-wifi-dahlia", + "toradex,verdin-am62-wifi", + "toradex,verdin-am62", + "ti,am625"; +}; diff --git a/arch/arm64/boot/dts/ti/k3-am625-verdin-wifi-dev.dts b/arch/arm64/boot/dts/ti/k3-am625-verdin-wifi-dev.dts new file mode 100644 index 0000000000000000000000000000000000000000..4b657d6d3e0dc47c928bd9c0c10a9d1d32e04905 --- /dev/null +++ b/arch/arm64/boot/dts/ti/k3-am625-verdin-wifi-dev.dts @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT +/* + * Copyright 2023 Toradex + * + * https://www.toradex.com/computer-on-modules/verdin-arm-family/ti-am62 + * https://www.toradex.com/products/carrier-board/verdin-development-board-kit + */ + +/dts-v1/; + +#include "k3-am625.dtsi" +#include "k3-am62-verdin.dtsi" +#include "k3-am62-verdin-wifi.dtsi" +#include "k3-am62-verdin-dev.dtsi" + +/ { + model = "Toradex Verdin AM62 WB on Verdin Development Board"; + compatible = "toradex,verdin-am62-wifi-dev", + "toradex,verdin-am62-wifi", + "toradex,verdin-am62", + "ti,am625"; +}; diff --git a/arch/arm64/boot/dts/ti/k3-am625-verdin-wifi-yavia.dts b/arch/arm64/boot/dts/ti/k3-am625-verdin-wifi-yavia.dts new file mode 100644 index 0000000000000000000000000000000000000000..8a2506068ac463a8c5ed500d53fe7cf953e89eab --- /dev/null +++ b/arch/arm64/boot/dts/ti/k3-am625-verdin-wifi-yavia.dts @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT +/* + * Copyright 2023 Toradex + * + * https://www.toradex.com/computer-on-modules/verdin-arm-family/ti-am62 + * https://www.toradex.com/products/carrier-board/yavia + */ + +/dts-v1/; + +#include "k3-am625.dtsi" +#include "k3-am62-verdin.dtsi" +#include "k3-am62-verdin-wifi.dtsi" +#include "k3-am62-verdin-yavia.dtsi" + +/ { + model = "Toradex Verdin AM62 WB on Yavia Board"; + compatible = "toradex,verdin-am62-wifi-yavia", + "toradex,verdin-am62-wifi", + "toradex,verdin-am62", + "ti,am625"; +}; diff --git a/arch/arm64/boot/dts/ti/k3-am62a-main.dtsi b/arch/arm64/boot/dts/ti/k3-am62a-main.dtsi index 393a1a40b68b8dd7500faee61cea6e5b0cb7b004..8b315cc61550c70bc2a6f96b5855717c88d1a3a7 100644 --- a/arch/arm64/boot/dts/ti/k3-am62a-main.dtsi +++ b/arch/arm64/boot/dts/ti/k3-am62a-main.dtsi @@ -169,6 +169,21 @@ }; }; + secure_proxy_sa3: mailbox@43600000 { + compatible = "ti,am654-secure-proxy"; + #mbox-cells = <1>; + reg-names = "target_data", "rt", "scfg"; + reg = <0x00 0x43600000 0x00 0x10000>, + <0x00 0x44880000 0x00 0x20000>, + <0x00 0x44860000 0x00 0x20000>; + /* + * Marked Disabled: + * Node is incomplete as it is meant for bootloaders and + * firmware on non-MPU processors + */ + status = "disabled"; + }; + main_pmx0: pinctrl@f4000 { compatible = "pinctrl-single"; reg = <0x00 0xf4000 0x00 0x2ac>; @@ -177,6 +192,102 @@ pinctrl-single,function-mask = <0xffffffff>; }; + main_timer0: timer@2400000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x2400000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 36 2>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 36 2>; + assigned-clock-parents = <&k3_clks 36 3>; + power-domains = <&k3_pds 36 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer1: timer@2410000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x2410000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 37 2>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 37 2>; + assigned-clock-parents = <&k3_clks 37 3>; + power-domains = <&k3_pds 37 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer2: timer@2420000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x2420000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 38 2>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 38 2>; + assigned-clock-parents = <&k3_clks 38 3>; + power-domains = <&k3_pds 38 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer3: timer@2430000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x2430000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 39 2>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 39 2>; + assigned-clock-parents = <&k3_clks 39 3>; + power-domains = <&k3_pds 39 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer4: timer@2440000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x2440000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 40 2>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 40 2>; + assigned-clock-parents = <&k3_clks 40 3>; + power-domains = <&k3_pds 40 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer5: timer@2450000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x2450000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 41 2>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 41 2>; + assigned-clock-parents = <&k3_clks 41 3>; + power-domains = <&k3_pds 41 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer6: timer@2460000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x2460000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 42 2>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 42 2>; + assigned-clock-parents = <&k3_clks 42 3>; + power-domains = <&k3_pds 42 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer7: timer@2470000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x2470000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 43 2>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 43 2>; + assigned-clock-parents = <&k3_clks 43 3>; + power-domains = <&k3_pds 43 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + main_uart0: serial@2800000 { compatible = "ti,am64-uart", "ti,am654-uart"; reg = <0x00 0x02800000 0x00 0x100>; @@ -601,6 +712,51 @@ status = "disabled"; }; + main_rti0: watchdog@e000000 { + compatible = "ti,j7-rti-wdt"; + reg = <0x00 0x0e000000 0x00 0x100>; + clocks = <&k3_clks 125 0>; + power-domains = <&k3_pds 125 TI_SCI_PD_EXCLUSIVE>; + assigned-clocks = <&k3_clks 125 0>; + assigned-clock-parents = <&k3_clks 125 2>; + }; + + main_rti1: watchdog@e010000 { + compatible = "ti,j7-rti-wdt"; + reg = <0x00 0x0e010000 0x00 0x100>; + clocks = <&k3_clks 126 0>; + power-domains = <&k3_pds 126 TI_SCI_PD_EXCLUSIVE>; + assigned-clocks = <&k3_clks 126 0>; + assigned-clock-parents = <&k3_clks 126 2>; + }; + + main_rti2: watchdog@e020000 { + compatible = "ti,j7-rti-wdt"; + reg = <0x00 0x0e020000 0x00 0x100>; + clocks = <&k3_clks 127 0>; + power-domains = <&k3_pds 127 TI_SCI_PD_EXCLUSIVE>; + assigned-clocks = <&k3_clks 127 0>; + assigned-clock-parents = <&k3_clks 127 2>; + }; + + main_rti3: watchdog@e030000 { + compatible = "ti,j7-rti-wdt"; + reg = <0x00 0x0e030000 0x00 0x100>; + clocks = <&k3_clks 128 0>; + power-domains = <&k3_pds 128 TI_SCI_PD_EXCLUSIVE>; + assigned-clocks = <&k3_clks 128 0>; + assigned-clock-parents = <&k3_clks 128 2>; + }; + + main_rti4: watchdog@e040000 { + compatible = "ti,j7-rti-wdt"; + reg = <0x00 0x0e040000 0x00 0x100>; + clocks = <&k3_clks 205 0>; + power-domains = <&k3_pds 205 TI_SCI_PD_EXCLUSIVE>; + assigned-clocks = <&k3_clks 205 0>; + assigned-clock-parents = <&k3_clks 205 2>; + }; + epwm0: pwm@23000000 { compatible = "ti,am64-epwm", "ti,am3352-ehrpwm"; #pwm-cells = <3>; diff --git a/arch/arm64/boot/dts/ti/k3-am62a-mcu.dtsi b/arch/arm64/boot/dts/ti/k3-am62a-mcu.dtsi index 2bb813e784a25c550e21bcef3fdd50a673dd7b04..04599762c2b7d28e21764e894d31bf0d00c8aede 100644 --- a/arch/arm64/boot/dts/ti/k3-am62a-mcu.dtsi +++ b/arch/arm64/boot/dts/ti/k3-am62a-mcu.dtsi @@ -15,6 +15,51 @@ status = "disabled"; }; + /* + * The MCU domain timer interrupts are routed only to the ESM module, + * and not currently available for Linux. The MCU domain timers are + * of limited use without interrupts, and likely reserved by the ESM. + */ + mcu_timer0: timer@4800000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x4800000 0x00 0x400>; + clocks = <&k3_clks 35 2>; + clock-names = "fck"; + power-domains = <&k3_pds 35 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + status = "reserved"; + }; + + mcu_timer1: timer@4810000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x4810000 0x00 0x400>; + clocks = <&k3_clks 48 2>; + clock-names = "fck"; + power-domains = <&k3_pds 48 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + status = "reserved"; + }; + + mcu_timer2: timer@4820000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x4820000 0x00 0x400>; + clocks = <&k3_clks 49 2>; + clock-names = "fck"; + power-domains = <&k3_pds 49 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + status = "reserved"; + }; + + mcu_timer3: timer@4830000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x4830000 0x00 0x400>; + clocks = <&k3_clks 50 2>; + clock-names = "fck"; + power-domains = <&k3_pds 50 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + status = "reserved"; + }; + mcu_uart0: serial@4a00000 { compatible = "ti,am64-uart", "ti,am654-uart"; reg = <0x00 0x04a00000 0x00 0x100>; @@ -87,4 +132,15 @@ clock-names = "gpio"; status = "disabled"; }; + + mcu_rti0: watchdog@4880000 { + compatible = "ti,j7-rti-wdt"; + reg = <0x00 0x04880000 0x00 0x100>; + clocks = <&k3_clks 131 0>; + power-domains = <&k3_pds 131 TI_SCI_PD_EXCLUSIVE>; + assigned-clocks = <&k3_clks 131 0>; + assigned-clock-parents = <&k3_clks 131 2>; + /* Tightly coupled to M4F */ + status = "reserved"; + }; }; diff --git a/arch/arm64/boot/dts/ti/k3-am62a-thermal.dtsi b/arch/arm64/boot/dts/ti/k3-am62a-thermal.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..85ce545633ea5f471b0ef824c2f5cc647d5c5dd5 --- /dev/null +++ b/arch/arm64/boot/dts/ti/k3-am62a-thermal.dtsi @@ -0,0 +1,47 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include + +thermal_zones: thermal-zones { + main0_thermal: main0-thermal { + polling-delay-passive = <250>; /* milliSeconds */ + polling-delay = <500>; /* milliSeconds */ + thermal-sensors = <&wkup_vtm0 0>; + + trips { + main0_crit: main0-crit { + temperature = <125000>; /* milliCelsius */ + hysteresis = <2000>; /* milliCelsius */ + type = "critical"; + }; + }; + }; + + main1_thermal: main1-thermal { + polling-delay-passive = <250>; /* milliSeconds */ + polling-delay = <500>; /* milliSeconds */ + thermal-sensors = <&wkup_vtm0 1>; + + trips { + main1_crit: main1-crit { + temperature = <125000>; /* milliCelsius */ + hysteresis = <2000>; /* milliCelsius */ + type = "critical"; + }; + }; + }; + + main2_thermal: main2-thermal { + polling-delay-passive = <250>; /* milliSeconds */ + polling-delay = <500>; /* milliSeconds */ + thermal-sensors = <&wkup_vtm0 2>; + + trips { + main2_crit: main2-crit { + temperature = <125000>; /* milliCelsius */ + hysteresis = <2000>; /* milliCelsius */ + type = "critical"; + }; + }; + }; +}; diff --git a/arch/arm64/boot/dts/ti/k3-am62a-wakeup.dtsi b/arch/arm64/boot/dts/ti/k3-am62a-wakeup.dtsi index 81d984414fd4a680945435e5101511aa5ab1e685..4e8279fa01e15c368afc4458131038d86ee47c1b 100644 --- a/arch/arm64/boot/dts/ti/k3-am62a-wakeup.dtsi +++ b/arch/arm64/boot/dts/ti/k3-am62a-wakeup.dtsi @@ -51,4 +51,23 @@ wakeup-source; status = "disabled"; }; + + wkup_rti0: watchdog@2b000000 { + compatible = "ti,j7-rti-wdt"; + reg = <0x00 0x2b000000 0x00 0x100>; + clocks = <&k3_clks 132 0>; + power-domains = <&k3_pds 132 TI_SCI_PD_EXCLUSIVE>; + assigned-clocks = <&k3_clks 132 0>; + assigned-clock-parents = <&k3_clks 132 2>; + /* Used by DM firmware */ + status = "reserved"; + }; + + wkup_vtm0: temperature-sensor@b00000 { + compatible = "ti,j7200-vtm"; + reg = <0x00 0xb00000 0x00 0x400>, + <0x00 0xb01000 0x00 0x400>; + power-domains = <&k3_pds 95 TI_SCI_PD_EXCLUSIVE>; + #thermal-sensor-cells = <1>; + }; }; diff --git a/arch/arm64/boot/dts/ti/k3-am62a.dtsi b/arch/arm64/boot/dts/ti/k3-am62a.dtsi index fe60c9ce21e3db2a9c6435d904e05e7a2d5ea8b6..61a210ecd5ff10947afa7302fd4480371f395232 100644 --- a/arch/arm64/boot/dts/ti/k3-am62a.dtsi +++ b/arch/arm64/boot/dts/ti/k3-am62a.dtsi @@ -115,6 +115,8 @@ <0x00 0x78100000 0x00 0x78100000 0x00 0x00008000>; /* DM R5 BTCM*/ }; }; + + #include "k3-am62a-thermal.dtsi" }; /* Now include the peripherals for each bus segments */ diff --git a/arch/arm64/boot/dts/ti/k3-am62a7-sk.dts b/arch/arm64/boot/dts/ti/k3-am62a7-sk.dts index f6a67f072dca678067641d268f29957138503a32..ecc0e13331c41cff5e3b429fd3764f0e3827823b 100644 --- a/arch/arm64/boot/dts/ti/k3-am62a7-sk.dts +++ b/arch/arm64/boot/dts/ti/k3-am62a7-sk.dts @@ -17,7 +17,9 @@ model = "Texas Instruments AM62A7 SK"; aliases { + serial0 = &wkup_uart0; serial2 = &main_uart0; + serial3 = &main_uart1; mmc1 = &sdhci1; }; @@ -114,36 +116,63 @@ }; }; +&mcu_pmx0 { + wkup_uart0_pins_default: wkup-uart0-default-pins { + pinctrl-single,pins = < + AM62AX_MCU_IOPAD(0x0024, PIN_INPUT, 0) /* (C9) WKUP_UART0_RXD */ + AM62AX_MCU_IOPAD(0x0028, PIN_OUTPUT, 0) /* (E9) WKUP_UART0_TXD */ + AM62AX_MCU_IOPAD(0x002c, PIN_INPUT, 0) /* (C10) WKUP_UART0_CTSn */ + AM62AX_MCU_IOPAD(0x0030, PIN_OUTPUT, 0) /* (C8) WKUP_UART0_RTSn */ + >; + }; +}; + +/* WKUP UART0 is used for DM firmware logs */ +&wkup_uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&wkup_uart0_pins_default>; + status = "reserved"; +}; + &main_pmx0 { - main_uart0_pins_default: main-uart0-pins-default { + main_uart0_pins_default: main-uart0-default-pins { pinctrl-single,pins = < - AM62AX_IOPAD(0x1c8, PIN_INPUT, 0) /* (D14) UART0_RXD */ - AM62AX_IOPAD(0x1cc, PIN_OUTPUT, 0) /* (E14) UART0_TXD */ + AM62AX_IOPAD(0x1c8, PIN_INPUT, 0) /* (E14) UART0_RXD */ + AM62AX_IOPAD(0x1cc, PIN_OUTPUT, 0) /* (D15) UART0_TXD */ >; }; - main_i2c0_pins_default: main-i2c0-pins-default { + main_uart1_pins_default: main-uart1-default-pins { + pinctrl-single,pins = < + AM62AX_IOPAD(0x01e8, PIN_INPUT, 1) /* (C17) I2C1_SCL.UART1_RXD */ + AM62AX_IOPAD(0x01ec, PIN_OUTPUT, 1) /* (E17) I2C1_SDA.UART1_TXD */ + AM62AX_IOPAD(0x0194, PIN_INPUT, 2) /* (C19) MCASP0_AXR3.UART1_CTSn */ + AM62AX_IOPAD(0x0198, PIN_OUTPUT, 2) /* (B19) MCASP0_AXR2.UART1_RTSn */ + >; + }; + + main_i2c0_pins_default: main-i2c0-default-pins { pinctrl-single,pins = < AM62AX_IOPAD(0x1e0, PIN_INPUT_PULLUP, 0) /* (B16) I2C0_SCL */ AM62AX_IOPAD(0x1e4, PIN_INPUT_PULLUP, 0) /* (A16) I2C0_SDA */ >; }; - main_i2c1_pins_default: main-i2c1-pins-default { + main_i2c1_pins_default: main-i2c1-default-pins { pinctrl-single,pins = < AM62AX_IOPAD(0x1e8, PIN_INPUT_PULLUP, 0) /* (B17) I2C1_SCL */ AM62AX_IOPAD(0x1ec, PIN_INPUT_PULLUP, 0) /* (A17) I2C1_SDA */ >; }; - main_i2c2_pins_default: main-i2c2-pins-default { + main_i2c2_pins_default: main-i2c2-default-pins { pinctrl-single,pins = < AM62AX_IOPAD(0x0b0, PIN_INPUT_PULLUP, 1) /* (K22) GPMC0_CSn2.I2C2_SCL */ AM62AX_IOPAD(0x0b4, PIN_INPUT_PULLUP, 1) /* (K24) GPMC0_CSn3.I2C2_SDA */ >; }; - main_mmc1_pins_default: main-mmc1-pins-default { + main_mmc1_pins_default: main-mmc1-default-pins { pinctrl-single,pins = < AM62AX_IOPAD(0x23c, PIN_INPUT, 0) /* (A21) MMC1_CMD */ AM62AX_IOPAD(0x234, PIN_INPUT, 0) /* (B22) MMC1_CLK */ @@ -155,26 +184,26 @@ >; }; - usr_led_pins_default: usr-led-pins-default { + usr_led_pins_default: usr-led-default-pins { pinctrl-single,pins = < AM62AX_IOPAD(0x244, PIN_OUTPUT, 7) /* (D18) MMC1_SDWP.GPIO1_49 */ >; }; - main_usb1_pins_default: main-usb1-pins-default { + main_usb1_pins_default: main-usb1-default-pins { pinctrl-single,pins = < AM62AX_IOPAD(0x0258, PIN_OUTPUT, 0) /* (F18) USB1_DRVVBUS */ >; }; - main_mdio1_pins_default: main-mdio1-pins-default { + main_mdio1_pins_default: main-mdio1-default-pins { pinctrl-single,pins = < AM62AX_IOPAD(0x160, PIN_OUTPUT, 0) /* (V12) MDIO0_MDC */ AM62AX_IOPAD(0x15c, PIN_INPUT, 0) /* (V13) MDIO0_MDIO */ >; }; - main_rgmii1_pins_default: main-rgmii1-pins-default { + main_rgmii1_pins_default: main-rgmii1-default-pins { pinctrl-single,pins = < AM62AX_IOPAD(0x14c, PIN_INPUT, 0) /* (AB16) RGMII1_RD0 */ AM62AX_IOPAD(0x150, PIN_INPUT, 0) /* (V15) RGMII1_RD1 */ @@ -254,6 +283,13 @@ pinctrl-0 = <&main_uart0_pins_default>; }; +/* Main UART1 is used for TIFS firmware logs */ +&main_uart1 { + pinctrl-names = "default"; + pinctrl-0 = <&main_uart1_pins_default>; + status = "reserved"; +}; + &usbss1 { status = "okay"; }; diff --git a/arch/arm64/boot/dts/ti/k3-am62x-sk-common.dtsi b/arch/arm64/boot/dts/ti/k3-am62x-sk-common.dtsi index 976f8303c84f40c0addb7a817820a352343a4621..34c8ffc553ec3dcc45d8e484fe459364418ce2dc 100644 --- a/arch/arm64/boot/dts/ti/k3-am62x-sk-common.dtsi +++ b/arch/arm64/boot/dts/ti/k3-am62x-sk-common.dtsi @@ -25,14 +25,12 @@ chosen { stdout-path = "serial2:115200n8"; - bootargs = "console=ttyS2,115200n8 earlycon=ns16550a,mmio32,0x02800000"; }; memory@80000000 { device_type = "memory"; /* 2G RAM */ reg = <0x00000000 0x80000000 0x00000000 0x80000000>; - }; reserved-memory { @@ -120,35 +118,44 @@ &main_pmx0 { /* First pad number is ALW package and second is AMC package */ - main_uart0_pins_default: main-uart0-pins-default { + main_uart0_pins_default: main-uart0-default-pins { pinctrl-single,pins = < AM62X_IOPAD(0x1c8, PIN_INPUT, 0) /* (D14/A13) UART0_RXD */ AM62X_IOPAD(0x1cc, PIN_OUTPUT, 0) /* (E14/E11) UART0_TXD */ >; }; - main_i2c0_pins_default: main-i2c0-pins-default { + main_uart1_pins_default: main-uart1-default-pins { + pinctrl-single,pins = < + AM62X_IOPAD(0x194, PIN_INPUT, 2) /* (B19/B18) MCASP0_AXR3.UART1_CTSn */ + AM62X_IOPAD(0x198, PIN_OUTPUT, 2) /* (A19/B17) MCASP0_AXR2.UART1_RTSn */ + AM62X_IOPAD(0x1ac, PIN_INPUT, 2) /* (E19/D15) MCASP0_AFSR.UART1_RXD */ + AM62X_IOPAD(0x1b0, PIN_OUTPUT, 2) /* (A20/D16) MCASP0_ACLKR.UART1_TXD */ + >; + }; + + main_i2c0_pins_default: main-i2c0-default-pins { pinctrl-single,pins = < AM62X_IOPAD(0x1e0, PIN_INPUT_PULLUP, 0) /* (B16/E12) I2C0_SCL */ AM62X_IOPAD(0x1e4, PIN_INPUT_PULLUP, 0) /* (A16/D14) I2C0_SDA */ >; }; - main_i2c1_pins_default: main-i2c1-pins-default { + main_i2c1_pins_default: main-i2c1-default-pins { pinctrl-single,pins = < AM62X_IOPAD(0x1e8, PIN_INPUT_PULLUP, 0) /* (B17/A17) I2C1_SCL */ AM62X_IOPAD(0x1ec, PIN_INPUT_PULLUP, 0) /* (A17/A16) I2C1_SDA */ >; }; - main_i2c2_pins_default: main-i2c2-pins-default { + main_i2c2_pins_default: main-i2c2-default-pins { pinctrl-single,pins = < AM62X_IOPAD(0x0b0, PIN_INPUT_PULLUP, 1) /* (K22/H18) GPMC0_CSn2.I2C2_SCL */ AM62X_IOPAD(0x0b4, PIN_INPUT_PULLUP, 1) /* (K24/H19) GPMC0_CSn3.I2C2_SDA */ >; }; - main_mmc0_pins_default: main-mmc0-pins-default { + main_mmc0_pins_default: main-mmc0-default-pins { pinctrl-single,pins = < AM62X_IOPAD(0x220, PIN_INPUT, 0) /* (Y3/V3) MMC0_CMD */ AM62X_IOPAD(0x218, PIN_INPUT, 0) /* (AB1/Y1) MMC0_CLK */ @@ -163,7 +170,7 @@ >; }; - main_mmc1_pins_default: main-mmc1-pins-default { + main_mmc1_pins_default: main-mmc1-default-pins { pinctrl-single,pins = < AM62X_IOPAD(0x23c, PIN_INPUT, 0) /* (A21/C18) MMC1_CMD */ AM62X_IOPAD(0x234, PIN_INPUT, 0) /* (B22/A20) MMC1_CLK */ @@ -175,20 +182,20 @@ >; }; - usr_led_pins_default: usr-led-pins-default { + usr_led_pins_default: usr-led-default-pins { pinctrl-single,pins = < AM62X_IOPAD(0x244, PIN_OUTPUT, 7) /* (C17/B15) MMC1_SDWP.GPIO1_49 */ >; }; - main_mdio1_pins_default: main-mdio1-pins-default { + main_mdio1_pins_default: main-mdio1-default-pins { pinctrl-single,pins = < AM62X_IOPAD(0x160, PIN_OUTPUT, 0) /* (AD24/V17) MDIO0_MDC */ AM62X_IOPAD(0x15c, PIN_INPUT, 0) /* (AB22/U16) MDIO0_MDIO */ >; }; - main_rgmii1_pins_default: main-rgmii1-pins-default { + main_rgmii1_pins_default: main-rgmii1-default-pins { pinctrl-single,pins = < AM62X_IOPAD(0x14c, PIN_INPUT, 0) /* (AB17/W15) RGMII1_RD0 */ AM62X_IOPAD(0x150, PIN_INPUT, 0) /* (AC17/Y16) RGMII1_RD1 */ @@ -205,18 +212,29 @@ >; }; - main_usb1_pins_default: main-usb1-pins-default { + main_usb1_pins_default: main-usb1-default-pins { pinctrl-single,pins = < AM62X_IOPAD(0x0258, PIN_OUTPUT, 0) /* (F18/E16) USB1_DRVVBUS */ >; }; - main_mcasp1_pins_default: main-mcasp1-pins-default { + main_mcasp1_pins_default: main-mcasp1-default-pins { + pinctrl-single,pins = < + AM62X_IOPAD(0x090, PIN_INPUT, 2) /* (M24/K17) GPMC0_BE0N_CLE.MCASP1_ACLKX */ + AM62X_IOPAD(0x098, PIN_INPUT, 2) /* (U23/P21) GPMC0_WAIT0.MCASP1_AFSX */ + AM62X_IOPAD(0x08c, PIN_OUTPUT, 2) /* (L25/J17) GPMC0_WEN.MCASP1_AXR0 */ + AM62X_IOPAD(0x084, PIN_INPUT, 2) /* (L23/K20) GPMC0_ADVN_ALE.MCASP1_AXR2 */ + >; + }; +}; + +&mcu_pmx0 { + wkup_uart0_pins_default: wkup-uart0-default-pins { pinctrl-single,pins = < - AM62X_IOPAD(0x090, PIN_INPUT, 2) /* (M24) GPMC0_BE0N_CLE.MCASP1_ACLKX */ - AM62X_IOPAD(0x098, PIN_INPUT, 2) /* (U23) GPMC0_WAIT0.MCASP1_AFSX */ - AM62X_IOPAD(0x08c, PIN_OUTPUT, 2) /* (L25) GPMC0_WEN.MCASP1_AXR0 */ - AM62X_IOPAD(0x084, PIN_INPUT, 2) /* (L23) GPMC0_ADVN_ALE.MCASP1_AXR2 */ + AM62X_MCU_IOPAD(0x02c, PIN_INPUT, 0) /* (C6/A7) WKUP_UART0_CTSn */ + AM62X_MCU_IOPAD(0x030, PIN_OUTPUT, 0) /* (A4/B4) WKUP_UART0_RTSn */ + AM62X_MCU_IOPAD(0x024, PIN_INPUT, 0) /* (B4/B5) WKUP_UART0_RXD */ + AM62X_MCU_IOPAD(0x028, PIN_OUTPUT, 0) /* (C5/C6) WKUP_UART0_TXD */ >; }; }; @@ -224,6 +242,8 @@ &wkup_uart0 { /* WKUP UART0 is used by DM firmware */ status = "reserved"; + pinctrl-names = "default"; + pinctrl-0 = <&wkup_uart0_pins_default>; }; &main_uart0 { @@ -235,6 +255,8 @@ &main_uart1 { /* Main UART1 is used by TIFS firmware */ status = "reserved"; + pinctrl-names = "default"; + pinctrl-0 = <&main_uart1_pins_default>; }; &main_i2c0 { @@ -242,6 +264,36 @@ pinctrl-names = "default"; pinctrl-0 = <&main_i2c0_pins_default>; clock-frequency = <400000>; + + eeprom@51 { + /* AT24C512C-MAHM-T or M24512-DFMC6TG */ + compatible = "atmel,24c512"; + reg = <0x51>; + }; + + typec_pd0: tps6598x@3f { + compatible = "ti,tps6598x"; + reg = <0x3f>; + + connector { + compatible = "usb-c-connector"; + label = "USB-C"; + self-powered; + data-role = "dual"; + power-role = "sink"; + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + usb_con_hs: endpoint { + remote-endpoint = <&usb0_hs_ep>; + }; + }; + }; + }; + }; }; &main_i2c1 { @@ -321,7 +373,16 @@ }; &usb0 { - dr_mode = "peripheral"; + #address-cells = <1>; + #size-cells = <0>; + usb-role-switch; + + port@0 { + reg = <0>; + usb0_hs_ep: endpoint { + remote-endpoint = <&usb_con_hs>; + }; + }; }; &usb1 { diff --git a/arch/arm64/boot/dts/ti/k3-am64-main.dtsi b/arch/arm64/boot/dts/ti/k3-am64-main.dtsi index 5e8036f32d79dc15878a9231a74bd746f7661678..1664d9f0241c2464b329724b2c2372219da5ef60 100644 --- a/arch/arm64/boot/dts/ti/k3-am64-main.dtsi +++ b/arch/arm64/boot/dts/ti/k3-am64-main.dtsi @@ -228,12 +228,161 @@ }; }; + main_timer0: timer@2400000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x2400000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 36 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 36 1>; + assigned-clock-parents = <&k3_clks 36 2>; + power-domains = <&k3_pds 36 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer1: timer@2410000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x2410000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 37 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 37 1>; + assigned-clock-parents = <&k3_clks 37 2>; + power-domains = <&k3_pds 37 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer2: timer@2420000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x2420000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 38 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 38 1>; + assigned-clock-parents = <&k3_clks 38 2>; + power-domains = <&k3_pds 38 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer3: timer@2430000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x2430000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 39 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 39 1>; + assigned-clock-parents = <&k3_clks 39 2>; + power-domains = <&k3_pds 39 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer4: timer@2440000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x2440000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 40 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 40 1>; + assigned-clock-parents = <&k3_clks 40 2>; + power-domains = <&k3_pds 40 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer5: timer@2450000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x2450000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 41 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 41 1>; + assigned-clock-parents = <&k3_clks 41 2>; + power-domains = <&k3_pds 41 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer6: timer@2460000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x2460000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 42 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 42 1>; + assigned-clock-parents = <&k3_clks 42 2>; + power-domains = <&k3_pds 42 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer7: timer@2470000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x2470000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 43 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 43 1>; + assigned-clock-parents = <&k3_clks 43 2>; + power-domains = <&k3_pds 43 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer8: timer@2480000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x2480000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 44 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 44 1>; + assigned-clock-parents = <&k3_clks 44 2>; + power-domains = <&k3_pds 44 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer9: timer@2490000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x2490000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 45 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 45 1>; + assigned-clock-parents = <&k3_clks 45 2>; + power-domains = <&k3_pds 45 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer10: timer@24a0000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x24a0000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 46 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 46 1>; + assigned-clock-parents = <&k3_clks 46 2>; + power-domains = <&k3_pds 46 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer11: timer@24b0000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x24b0000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 47 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 47 1>; + assigned-clock-parents = <&k3_clks 47 2>; + power-domains = <&k3_pds 47 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_esm: esm@420000 { + compatible = "ti,j721e-esm"; + reg = <0x00 0x420000 0x00 0x1000>; + ti,esm-pins = <160>, <161>; + }; + main_uart0: serial@2800000 { compatible = "ti,am64-uart", "ti,am654-uart"; reg = <0x00 0x02800000 0x00 0x100>; interrupts = ; clock-frequency = <48000000>; - current-speed = <115200>; power-domains = <&k3_pds 146 TI_SCI_PD_EXCLUSIVE>; clocks = <&k3_clks 146 0>; clock-names = "fclk"; @@ -245,7 +394,6 @@ reg = <0x00 0x02810000 0x00 0x100>; interrupts = ; clock-frequency = <48000000>; - current-speed = <115200>; power-domains = <&k3_pds 152 TI_SCI_PD_EXCLUSIVE>; clocks = <&k3_clks 152 0>; clock-names = "fclk"; @@ -257,7 +405,6 @@ reg = <0x00 0x02820000 0x00 0x100>; interrupts = ; clock-frequency = <48000000>; - current-speed = <115200>; power-domains = <&k3_pds 153 TI_SCI_PD_EXCLUSIVE>; clocks = <&k3_clks 153 0>; clock-names = "fclk"; @@ -269,7 +416,6 @@ reg = <0x00 0x02830000 0x00 0x100>; interrupts = ; clock-frequency = <48000000>; - current-speed = <115200>; power-domains = <&k3_pds 154 TI_SCI_PD_EXCLUSIVE>; clocks = <&k3_clks 154 0>; clock-names = "fclk"; @@ -281,7 +427,6 @@ reg = <0x00 0x02840000 0x00 0x100>; interrupts = ; clock-frequency = <48000000>; - current-speed = <115200>; power-domains = <&k3_pds 155 TI_SCI_PD_EXCLUSIVE>; clocks = <&k3_clks 155 0>; clock-names = "fclk"; @@ -293,7 +438,6 @@ reg = <0x00 0x02850000 0x00 0x100>; interrupts = ; clock-frequency = <48000000>; - current-speed = <115200>; power-domains = <&k3_pds 156 TI_SCI_PD_EXCLUSIVE>; clocks = <&k3_clks 156 0>; clock-names = "fclk"; @@ -305,7 +449,6 @@ reg = <0x00 0x02860000 0x00 0x100>; interrupts = ; clock-frequency = <48000000>; - current-speed = <115200>; power-domains = <&k3_pds 158 TI_SCI_PD_EXCLUSIVE>; clocks = <&k3_clks 158 0>; clock-names = "fclk"; @@ -676,6 +819,7 @@ #mbox-cells = <1>; ti,mbox-num-users = <4>; ti,mbox-num-fifos = <16>; + status = "disabled"; }; mailbox0_cluster3: mailbox@29030000 { @@ -686,6 +830,7 @@ #mbox-cells = <1>; ti,mbox-num-users = <4>; ti,mbox-num-fifos = <16>; + status = "disabled"; }; mailbox0_cluster4: mailbox@29040000 { @@ -696,6 +841,7 @@ #mbox-cells = <1>; ti,mbox-num-users = <4>; ti,mbox-num-fifos = <16>; + status = "disabled"; }; mailbox0_cluster5: mailbox@29050000 { @@ -706,6 +852,7 @@ #mbox-cells = <1>; ti,mbox-num-users = <4>; ti,mbox-num-fifos = <16>; + status = "disabled"; }; mailbox0_cluster6: mailbox@29060000 { @@ -715,6 +862,7 @@ #mbox-cells = <1>; ti,mbox-num-users = <4>; ti,mbox-num-fifos = <16>; + status = "disabled"; }; mailbox0_cluster7: mailbox@29070000 { @@ -724,6 +872,7 @@ #mbox-cells = <1>; ti,mbox-num-users = <4>; ti,mbox-num-fifos = <16>; + status = "disabled"; }; main_r5fss0: r5fss@78000000 { @@ -1392,4 +1541,12 @@ clock-names = "fck"; status = "disabled"; }; + + main_vtm0: temperature-sensor@b00000 { + compatible = "ti,j7200-vtm"; + reg = <0x00 0xb00000 0x00 0x400>, + <0x00 0xb01000 0x00 0x400>; + power-domains = <&k3_pds 95 TI_SCI_PD_EXCLUSIVE>; + #thermal-sensor-cells = <1>; + }; }; diff --git a/arch/arm64/boot/dts/ti/k3-am64-mcu.dtsi b/arch/arm64/boot/dts/ti/k3-am64-mcu.dtsi index 38ddf0b3b8a0c5400c1fa6ef5080b87a42a5fa67..686d4979072188c011698b73931c696f283dbe8f 100644 --- a/arch/arm64/boot/dts/ti/k3-am64-mcu.dtsi +++ b/arch/arm64/boot/dts/ti/k3-am64-mcu.dtsi @@ -6,11 +6,55 @@ */ &cbass_mcu { + /* + * The MCU domain timer interrupts are routed only to the ESM module, + * and not currently available for Linux. The MCU domain timers are + * of limited use without interrupts, and likely reserved by the ESM. + */ + mcu_timer0: timer@4800000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x4800000 0x00 0x400>; + clocks = <&k3_clks 35 1>; + clock-names = "fck"; + power-domains = <&k3_pds 35 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + status = "reserved"; + }; + + mcu_timer1: timer@4810000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x4810000 0x00 0x400>; + clocks = <&k3_clks 48 1>; + clock-names = "fck"; + power-domains = <&k3_pds 48 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + status = "reserved"; + }; + + mcu_timer2: timer@4820000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x4820000 0x00 0x400>; + clocks = <&k3_clks 49 1>; + clock-names = "fck"; + power-domains = <&k3_pds 49 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + status = "reserved"; + }; + + mcu_timer3: timer@4830000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x4830000 0x00 0x400>; + clocks = <&k3_clks 50 1>; + clock-names = "fck"; + power-domains = <&k3_pds 50 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + status = "reserved"; + }; + mcu_uart0: serial@4a00000 { compatible = "ti,am64-uart", "ti,am654-uart"; reg = <0x00 0x04a00000 0x00 0x100>; interrupts = ; - current-speed = <115200>; power-domains = <&k3_pds 149 TI_SCI_PD_EXCLUSIVE>; clocks = <&k3_clks 149 0>; clock-names = "fclk"; @@ -21,7 +65,6 @@ compatible = "ti,am64-uart", "ti,am654-uart"; reg = <0x00 0x04a10000 0x00 0x100>; interrupts = ; - current-speed = <115200>; power-domains = <&k3_pds 160 TI_SCI_PD_EXCLUSIVE>; clocks = <&k3_clks 160 0>; clock-names = "fclk"; @@ -109,4 +152,10 @@ pinctrl-single,register-width = <32>; pinctrl-single,function-mask = <0xffffffff>; }; + + mcu_esm: esm@4100000 { + compatible = "ti,j721e-esm"; + reg = <0x00 0x4100000 0x00 0x1000>; + ti,esm-pins = <0>, <1>; + }; }; diff --git a/arch/arm64/boot/dts/ti/k3-am64-phycore-som.dtsi b/arch/arm64/boot/dts/ti/k3-am64-phycore-som.dtsi index 8dfb6301b17dca255ebc05bf7e011bd3f5708061..5606d775153d4ec46bc333d8a500e4145beebd3c 100644 --- a/arch/arm64/boot/dts/ti/k3-am64-phycore-som.dtsi +++ b/arch/arm64/boot/dts/ti/k3-am64-phycore-som.dtsi @@ -66,7 +66,7 @@ }; &main_pmx0 { - cpsw_mdio_pins_default: cpsw-mdio-pins-default { + cpsw_mdio_pins_default: cpsw-mdio-default-pins { pinctrl-single,pins = < AM64X_IOPAD(0x01f8, PIN_INPUT, 4) /* (P5) PRG0_PRU1_GPO18.MDIO0_MDIO */ AM64X_IOPAD(0x01fc, PIN_OUTPUT, 4) /* (R2) PRG0_PRU1_GPO19.MDIO0_MDC */ @@ -74,7 +74,7 @@ >; }; - cpsw_rgmii1_pins_default: cpsw-rgmii1-pins-default { + cpsw_rgmii1_pins_default: cpsw-rgmii1-default-pins { pinctrl-single,pins = < AM64X_IOPAD(0x0184, PIN_INPUT, 4) /* (W6) PRG0_PRU0_GPO9.RGMII1_RX_CTL */ AM64X_IOPAD(0x0188, PIN_INPUT, 4) /* (AA5) PRG0_PRU0_GPO10.RGMII1_RXC */ @@ -92,26 +92,26 @@ >; }; - eeprom_wp_pins_default: eeprom-wp-pins-default { + eeprom_wp_pins_default: eeprom-wp-default-pins { pinctrl-single,pins = < AM64X_IOPAD(0x0208, PIN_OUTPUT, 7) /* (D12) SPI0_CS0.GPIO1_42 */ >; }; - leds_pins_default: leds-pins-default { + leds_pins_default: leds-default-pins { pinctrl-single,pins = < AM64X_IOPAD(0x0030, PIN_OUTPUT, 7) /* (L18) OSPI0_CSn1.GPIO0_12 */ >; }; - main_i2c0_pins_default: main-i2c0-pins-default { + main_i2c0_pins_default: main-i2c0-default-pins { pinctrl-single,pins = < AM64X_IOPAD(0x0260, PIN_INPUT, 0) /* (A18) I2C0_SCL */ AM64X_IOPAD(0x0264, PIN_INPUT, 0) /* (B18) I2C0_SDA */ >; }; - ospi0_pins_default: ospi0-pins-default { + ospi0_pins_default: ospi0-default-pins { pinctrl-single,pins = < AM64X_IOPAD(0x0000, PIN_OUTPUT, 0) /* (N20) OSPI0_CLK */ AM64X_IOPAD(0x0008, PIN_INPUT, 0) /* (N19) OSPI0_DQS */ @@ -160,30 +160,6 @@ status = "disabled"; }; -&mailbox0_cluster2 { - status = "disabled"; -}; - -&mailbox0_cluster3 { - status = "disabled"; -}; - -&mailbox0_cluster4 { - status = "disabled"; -}; - -&mailbox0_cluster5 { - status = "disabled"; -}; - -&mailbox0_cluster6 { - status = "disabled"; -}; - -&mailbox0_cluster7 { - status = "disabled"; -}; - &main_i2c0 { status = "okay"; pinctrl-names = "default"; diff --git a/arch/arm64/boot/dts/ti/k3-am64-thermal.dtsi b/arch/arm64/boot/dts/ti/k3-am64-thermal.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..036db56ba7977a076449d88c1877ee4eba6ba05e --- /dev/null +++ b/arch/arm64/boot/dts/ti/k3-am64-thermal.dtsi @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include + +thermal_zones: thermal-zones { + main0_thermal: main0-thermal { + polling-delay-passive = <250>; /* milliSeconds */ + polling-delay = <500>; /* milliSeconds */ + thermal-sensors = <&main_vtm0 0>; + + trips { + main0_crit: main0-crit { + temperature = <105000>; /* milliCelsius */ + hysteresis = <2000>; /* milliCelsius */ + type = "critical"; + }; + }; + }; + + main1_thermal: main1-thermal { + polling-delay-passive = <250>; /* milliSeconds */ + polling-delay = <500>; /* milliSeconds */ + thermal-sensors = <&main_vtm0 1>; + + trips { + main1_crit: main1-crit { + temperature = <105000>; /* milliCelsius */ + hysteresis = <2000>; /* milliCelsius */ + type = "critical"; + }; + }; + }; +}; diff --git a/arch/arm64/boot/dts/ti/k3-am64.dtsi b/arch/arm64/boot/dts/ti/k3-am64.dtsi index 60fe95b48312005d0238d67b95017a0a60f5685f..8e9c2bc70f4d7ed87ad3f87f2915e73ee1dfb641 100644 --- a/arch/arm64/boot/dts/ti/k3-am64.dtsi +++ b/arch/arm64/boot/dts/ti/k3-am64.dtsi @@ -19,22 +19,6 @@ #address-cells = <2>; #size-cells = <2>; - aliases { - serial0 = &mcu_uart0; - serial1 = &mcu_uart1; - serial2 = &main_uart0; - serial3 = &main_uart1; - serial4 = &main_uart2; - serial5 = &main_uart3; - serial6 = &main_uart4; - serial7 = &main_uart5; - serial8 = &main_uart6; - ethernet0 = &cpsw_port1; - ethernet1 = &cpsw_port2; - mmc0 = &sdhci0; - mmc1 = &sdhci1; - }; - chosen { }; firmware { @@ -70,6 +54,7 @@ <0x00 0x00420000 0x00 0x00420000 0x00 0x00001000>, /* ESM0 */ <0x00 0x00600000 0x00 0x00600000 0x00 0x00001100>, /* GPIO */ <0x00 0x00a40000 0x00 0x00a40000 0x00 0x00000800>, /* Timesync router */ + <0x00 0x00b00000 0x00 0x00b00000 0x00 0x00002400>, /* VTM */ <0x00 0x01000000 0x00 0x01000000 0x00 0x02330400>, /* First peripheral window */ <0x00 0x08000000 0x00 0x08000000 0x00 0x00200000>, /* Main CPSW */ <0x00 0x0d000000 0x00 0x0d000000 0x00 0x00800000>, /* PCIE_CORE */ @@ -106,6 +91,8 @@ ranges = <0x00 0x04000000 0x00 0x04000000 0x00 0x01ff1400>; /* Peripheral window */ }; }; + + #include "k3-am64-thermal.dtsi" }; /* Now include the peripherals for each bus segments */ diff --git a/arch/arm64/boot/dts/ti/k3-am642-evm.dts b/arch/arm64/boot/dts/ti/k3-am642-evm.dts index 39feea78a084eeee870ae83318c2e30e470fa673..15c282c93467a6ed98274e41e05b0f3fbece25c5 100644 --- a/arch/arm64/boot/dts/ti/k3-am642-evm.dts +++ b/arch/arm64/boot/dts/ti/k3-am642-evm.dts @@ -17,15 +17,26 @@ model = "Texas Instruments AM642 EVM"; chosen { - stdout-path = "serial2:115200n8"; - bootargs = "console=ttyS2,115200n8 earlycon=ns16550a,mmio32,0x02800000"; + stdout-path = &main_uart0; + }; + + aliases { + serial0 = &mcu_uart0; + serial1 = &main_uart1; + serial2 = &main_uart0; + serial3 = &main_uart3; + i2c0 = &main_i2c0; + i2c1 = &main_i2c1; + mmc0 = &sdhci0; + mmc1 = &sdhci1; + ethernet0 = &cpsw_port1; + ethernet1 = &cpsw_port2; }; memory@80000000 { device_type = "memory"; /* 2G RAM */ reg = <0x00000000 0x80000000 0x00000000 0x80000000>; - }; reserved-memory { @@ -94,7 +105,7 @@ }; }; - evm_12v0: fixedregulator-evm12v0 { + evm_12v0: regulator-0 { /* main DC jack */ compatible = "regulator-fixed"; regulator-name = "evm_12v0"; @@ -104,7 +115,7 @@ regulator-boot-on; }; - vsys_5v0: fixedregulator-vsys5v0 { + vsys_5v0: regulator-1 { /* output of LM5140 */ compatible = "regulator-fixed"; regulator-name = "vsys_5v0"; @@ -115,7 +126,7 @@ regulator-boot-on; }; - vsys_3v3: fixedregulator-vsys3v3 { + vsys_3v3: regulator-2 { /* output of LM5140 */ compatible = "regulator-fixed"; regulator-name = "vsys_3v3"; @@ -126,7 +137,7 @@ regulator-boot-on; }; - vdd_mmc1: fixed-regulator-sd { + vdd_mmc1: regulator-3 { /* TPS2051BD */ compatible = "regulator-fixed"; regulator-name = "vdd_mmc1"; @@ -138,7 +149,7 @@ gpio = <&exp1 6 GPIO_ACTIVE_HIGH>; }; - vddb: fixedregulator-vddb { + vddb: regulator-4 { compatible = "regulator-fixed"; regulator-name = "vddb_3v3_display"; regulator-min-microvolt = <3300000>; @@ -148,6 +159,20 @@ regulator-boot-on; }; + vtt_supply: regulator-5 { + compatible = "regulator-fixed"; + regulator-name = "vtt"; + pinctrl-names = "default"; + pinctrl-0 = <&ddr_vtt_pins_default>; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + gpio = <&main_gpio0 12 GPIO_ACTIVE_HIGH>; + vin-supply = <&vsys_3v3>; + enable-active-high; + regulator-always-on; + regulator-boot-on; + }; + leds { compatible = "gpio-leds"; @@ -201,7 +226,7 @@ }; &main_pmx0 { - main_mmc1_pins_default: main-mmc1-pins-default { + main_mmc1_pins_default: main-mmc1-default-pins { pinctrl-single,pins = < AM64X_IOPAD(0x0294, PIN_INPUT_PULLUP, 0) /* (J19) MMC1_CMD */ AM64X_IOPAD(0x028c, PIN_INPUT_PULLDOWN, 0) /* (L20) MMC1_CLK */ @@ -215,7 +240,16 @@ >; }; - main_uart0_pins_default: main-uart0-pins-default { + main_uart1_pins_default: main-uart1-default-pins { + pinctrl-single,pins = < + AM64X_IOPAD(0x0248, PIN_INPUT, 0) /* (D16) UART1_CTSn */ + AM64X_IOPAD(0x024c, PIN_OUTPUT, 0) /* (E16) UART1_RTSn */ + AM64X_IOPAD(0x0240, PIN_INPUT, 0) /* (E15) UART1_RXD */ + AM64X_IOPAD(0x0244, PIN_OUTPUT, 0) /* (E14) UART1_TXD */ + >; + }; + + main_uart0_pins_default: main-uart0-default-pins { pinctrl-single,pins = < AM64X_IOPAD(0x0238, PIN_INPUT, 0) /* (B16) UART0_CTSn */ AM64X_IOPAD(0x023c, PIN_OUTPUT, 0) /* (A16) UART0_RTSn */ @@ -224,7 +258,7 @@ >; }; - main_spi0_pins_default: main-spi0-pins-default { + main_spi0_pins_default: main-spi0-default-pins { pinctrl-single,pins = < AM64X_IOPAD(0x0210, PIN_INPUT, 0) /* (D13) SPI0_CLK */ AM64X_IOPAD(0x0208, PIN_OUTPUT, 0) /* (D12) SPI0_CS0 */ @@ -233,21 +267,28 @@ >; }; - main_i2c1_pins_default: main-i2c1-pins-default { + main_i2c0_pins_default: main-i2c0-default-pins { + pinctrl-single,pins = < + AM64X_IOPAD(0x0260, PIN_INPUT_PULLUP, 0) /* (A18) I2C0_SCL */ + AM64X_IOPAD(0x0264, PIN_INPUT_PULLUP, 0) /* (B18) I2C0_SDA */ + >; + }; + + main_i2c1_pins_default: main-i2c1-default-pins { pinctrl-single,pins = < AM64X_IOPAD(0x0268, PIN_INPUT_PULLUP, 0) /* (C18) I2C1_SCL */ AM64X_IOPAD(0x026c, PIN_INPUT_PULLUP, 0) /* (B19) I2C1_SDA */ >; }; - mdio1_pins_default: mdio1-pins-default { + mdio1_pins_default: mdio1-default-pins { pinctrl-single,pins = < AM64X_IOPAD(0x01fc, PIN_OUTPUT, 4) /* (R2) PRG0_PRU1_GPO19.MDIO0_MDC */ AM64X_IOPAD(0x01f8, PIN_INPUT, 4) /* (P5) PRG0_PRU1_GPO18.MDIO0_MDIO */ >; }; - rgmii1_pins_default: rgmii1-pins-default { + rgmii1_pins_default: rgmii1-default-pins { pinctrl-single,pins = < AM64X_IOPAD(0x01cc, PIN_INPUT, 4) /* (W5) PRG0_PRU1_GPO7.RGMII1_RD0 */ AM64X_IOPAD(0x01d4, PIN_INPUT, 4) /* (Y5) PRG0_PRU1_GPO9.RGMII1_RD1 */ @@ -264,7 +305,7 @@ >; }; - rgmii2_pins_default: rgmii2-pins-default { + rgmii2_pins_default: rgmii2-default-pins { pinctrl-single,pins = < AM64X_IOPAD(0x0108, PIN_INPUT, 4) /* (W11) PRG1_PRU1_GPO0.RGMII2_RD0 */ AM64X_IOPAD(0x010c, PIN_INPUT, 4) /* (V11) PRG1_PRU1_GPO1.RGMII2_RD1 */ @@ -281,13 +322,13 @@ >; }; - main_usb0_pins_default: main-usb0-pins-default { + main_usb0_pins_default: main-usb0-default-pins { pinctrl-single,pins = < AM64X_IOPAD(0x02a8, PIN_OUTPUT, 0) /* (E19) USB0_DRVVBUS */ >; }; - ospi0_pins_default: ospi0-pins-default { + ospi0_pins_default: ospi0-default-pins { pinctrl-single,pins = < AM64X_IOPAD(0x0000, PIN_OUTPUT, 0) /* (N20) OSPI0_CLK */ AM64X_IOPAD(0x002c, PIN_OUTPUT, 0) /* (L19) OSPI0_CSn0 */ @@ -303,36 +344,58 @@ >; }; - main_ecap0_pins_default: main-ecap0-pins-default { + main_ecap0_pins_default: main-ecap0-default-pins { pinctrl-single,pins = < AM64X_IOPAD(0x0270, PIN_INPUT, 0) /* (D18) ECAP0_IN_APWM_OUT */ >; }; - main_mcan0_pins_default: main-mcan0-pins-default { + main_mcan0_pins_default: main-mcan0-default-pins { pinctrl-single,pins = < AM64X_IOPAD(0x0254, PIN_INPUT, 0) /* (B17) MCAN0_RX */ AM64X_IOPAD(0x0250, PIN_OUTPUT, 0) /* (A17) MCAN0_TX */ >; }; - main_mcan1_pins_default: main-mcan1-pins-default { + main_mcan1_pins_default: main-mcan1-default-pins { pinctrl-single,pins = < AM64X_IOPAD(0x025c, PIN_INPUT, 0) /* (D17) MCAN1_RX */ AM64X_IOPAD(0x0258, PIN_OUTPUT, 0) /* (C17) MCAN1_TX */ >; }; + + ddr_vtt_pins_default: ddr-vtt-default-pins { + pinctrl-single,pins = < + AM64X_IOPAD(0x0030, PIN_OUTPUT_PULLUP, 7) /* (L18) OSPI0_CSN1.GPIO0_12 */ + >; + }; }; &main_uart0 { status = "okay"; pinctrl-names = "default"; pinctrl-0 = <&main_uart0_pins_default>; + current-speed = <115200>; }; /* main_uart1 is reserved for firmware usage */ &main_uart1 { status = "reserved"; + pinctrl-names = "default"; + pinctrl-0 = <&main_uart1_pins_default>; +}; + +&main_i2c0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&main_i2c0_pins_default>; + clock-frequency = <400000>; + + eeprom@50 { + /* AT24CM01 */ + compatible = "atmel,24c1024"; + reg = <0x50>; + }; }; &main_i2c1 { @@ -425,8 +488,7 @@ &cpsw3g { pinctrl-names = "default"; - pinctrl-0 = <&rgmii1_pins_default - &rgmii2_pins_default>; + pinctrl-0 = <&rgmii1_pins_default>, <&rgmii2_pins_default>; }; &cpsw_port1 { @@ -471,10 +533,53 @@ cdns,tchsh-ns = <60>; cdns,tslch-ns = <60>; cdns,read-delay = <4>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "ospi.tiboot3"; + reg = <0x0 0x100000>; + }; + + partition@100000 { + label = "ospi.tispl"; + reg = <0x100000 0x200000>; + }; + + partition@300000 { + label = "ospi.u-boot"; + reg = <0x300000 0x400000>; + }; + + partition@700000 { + label = "ospi.env"; + reg = <0x700000 0x40000>; + }; + + partition@740000 { + label = "ospi.env.backup"; + reg = <0x740000 0x40000>; + }; + + partition@800000 { + label = "ospi.rootfs"; + reg = <0x800000 0x37c0000>; + }; + + partition@3fc0000 { + label = "ospi.phypattern"; + reg = <0x3fc0000 0x40000>; + }; + }; }; }; &mailbox0_cluster2 { + status = "okay"; + mbox_main_r5fss0_core0: mbox-main-r5fss0-core0 { ti,mbox-rx = <0 0 2>; ti,mbox-tx = <1 0 2>; @@ -486,11 +591,9 @@ }; }; -&mailbox0_cluster3 { - status = "disabled"; -}; - &mailbox0_cluster4 { + status = "okay"; + mbox_main_r5fss1_core0: mbox-main-r5fss1-core0 { ti,mbox-rx = <0 0 2>; ti,mbox-tx = <1 0 2>; @@ -502,41 +605,35 @@ }; }; -&mailbox0_cluster5 { - status = "disabled"; -}; - &mailbox0_cluster6 { + status = "okay"; + mbox_m4_0: mbox-m4-0 { ti,mbox-rx = <0 0 2>; ti,mbox-tx = <1 0 2>; }; }; -&mailbox0_cluster7 { - status = "disabled"; -}; - &main_r5fss0_core0 { - mboxes = <&mailbox0_cluster2 &mbox_main_r5fss0_core0>; + mboxes = <&mailbox0_cluster2>, <&mbox_main_r5fss0_core0>; memory-region = <&main_r5fss0_core0_dma_memory_region>, <&main_r5fss0_core0_memory_region>; }; &main_r5fss0_core1 { - mboxes = <&mailbox0_cluster2 &mbox_main_r5fss0_core1>; + mboxes = <&mailbox0_cluster2>, <&mbox_main_r5fss0_core1>; memory-region = <&main_r5fss0_core1_dma_memory_region>, <&main_r5fss0_core1_memory_region>; }; &main_r5fss1_core0 { - mboxes = <&mailbox0_cluster4 &mbox_main_r5fss1_core0>; + mboxes = <&mailbox0_cluster4>, <&mbox_main_r5fss1_core0>; memory-region = <&main_r5fss1_core0_dma_memory_region>, <&main_r5fss1_core0_memory_region>; }; &main_r5fss1_core1 { - mboxes = <&mailbox0_cluster4 &mbox_main_r5fss1_core1>; + mboxes = <&mailbox0_cluster4>, <&mbox_main_r5fss1_core1>; memory-region = <&main_r5fss1_core1_dma_memory_region>, <&main_r5fss1_core1_memory_region>; }; diff --git a/arch/arm64/boot/dts/ti/k3-am642-phyboard-electra-rdk.dts b/arch/arm64/boot/dts/ti/k3-am642-phyboard-electra-rdk.dts index 8d3114d14a8b5ffe1c98aaa486e4a68a99ff888e..9c418abd29d860c3a0b5008ed07a12eb5f998631 100644 --- a/arch/arm64/boot/dts/ti/k3-am642-phyboard-electra-rdk.dts +++ b/arch/arm64/boot/dts/ti/k3-am642-phyboard-electra-rdk.dts @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include "k3-am642.dtsi" @@ -75,7 +76,7 @@ leds { compatible = "gpio-leds"; pinctrl-names = "default"; - pinctrl-0 = <&leds_pins_default &user_leds_pins_default>; + pinctrl-0 = <&leds_pins_default>, <&user_leds_pins_default>; led-1 { color = ; @@ -104,47 +105,47 @@ }; &main_pmx0 { - can_tc1_pins_default: can-tc1-pins-default { + can_tc1_pins_default: can-tc1-default-pins { pinctrl-single,pins = < AM64X_IOPAD(0x0084, PIN_OUTPUT, 7) /* (P16) GPMC0_ADVn_ALE.GPIO0_32 */ >; }; - can_tc2_pins_default: can-tc2-pins-default { + can_tc2_pins_default: can-tc2-default-pins { pinctrl-single,pins = < AM64X_IOPAD(0x0090, PIN_OUTPUT, 7) /* (P17) GPMC0_BE0n_CLE.GPIO0_35 */ >; }; - gpio_keys_pins_default: gpio-keys-pins-default { + gpio_keys_pins_default: gpio-keys-default-pins { pinctrl-single,pins = < AM64X_IOPAD(0x0044, PIN_INPUT, 7) /* (T18) GPMC0_AD2.GPIO0_17 */ AM64X_IOPAD(0x0054, PIN_INPUT, 7) /* (V20) GPMC0_AD6.GPIO0_21 */ >; }; - main_i2c1_pins_default: main-i2c1-pins-default { + main_i2c1_pins_default: main-i2c1-default-pins { pinctrl-single,pins = < AM64X_IOPAD(0x0268, PIN_INPUT, 0) /* (C18) I2C1_SCL */ AM64X_IOPAD(0x026c, PIN_INPUT, 0) /* (B19) I2C1_SDA */ >; }; - main_mcan0_pins_default: main-mcan0-pins-default { + main_mcan0_pins_default: main-mcan0-default-pins { pinctrl-single,pins = < AM64X_IOPAD(0x0250, PIN_OUTPUT, 0) /* (A17) MCAN0_TX */ AM64X_IOPAD(0x0254, PIN_INPUT, 0) /* (B17) MCAN0_RX */ >; }; - main_mcan1_pins_default: main-mcan1-pins-default { + main_mcan1_pins_default: main-mcan1-default-pins { pinctrl-single,pins = < AM64X_IOPAD(0x0258, PIN_OUTPUT, 0) /* (C17) MCAN1_TX */ AM64X_IOPAD(0x025c, PIN_INPUT, 0) /* (D17) MCAN1_RX */ >; }; - main_mmc1_pins_default: main-mmc1-pins-default { + main_mmc1_pins_default: main-mmc1-default-pins { pinctrl-single,pins = < AM64X_IOPAD(0x027c, PIN_INPUT_PULLUP, 0) /* (K18) MMC1_DAT3 */ AM64X_IOPAD(0x0280, PIN_INPUT_PULLUP, 0) /* (K19) MMC1_DAT2 */ @@ -157,14 +158,14 @@ >; }; - main_uart0_pins_default: main-uart0-pins-default { + main_uart0_pins_default: main-uart0-default-pins { pinctrl-single,pins = < AM64X_IOPAD(0x0230, PIN_INPUT, 0) /* (D15) UART0_RXD */ AM64X_IOPAD(0x0234, PIN_OUTPUT, 0) /* (C16) UART0_TXD */ >; }; - main_uart1_pins_default: main-uart1-pins-default { + main_uart1_pins_default: main-uart1-default-pins { pinctrl-single,pins = < AM64X_IOPAD(0x0248, PIN_INPUT, 0) /* (D16) UART1_CTSn */ AM64X_IOPAD(0x024C, PIN_OUTPUT, 0) /* (E16) UART1_RTSn */ @@ -173,25 +174,25 @@ >; }; - main_usb0_pins_default: main-usb0-pins-default { + main_usb0_pins_default: main-usb0-default-pins { pinctrl-single,pins = < AM64X_IOPAD(0x02a8, PIN_OUTPUT, 0) /* (E19) USB0_DRVVBUS */ >; }; - pcie_usb_sel_pins_default: pcie-usb-sel-pins-default { + pcie_usb_sel_pins_default: pcie-usb-sel-default-pins { pinctrl-single,pins = < AM64X_IOPAD(0x017c, PIN_OUTPUT, 7) /* (T1) PRG0_PRU0_GPO7.GPIO1_7 */ >; }; - pcie0_pins_default: pcie0-pins-default { + pcie0_pins_default: pcie0-default-pins { pinctrl-single,pins = < AM64X_IOPAD(0x0098, PIN_OUTPUT, 7) /* (W19) GPMC0_WAIT0.GPIO0_37 */ >; }; - user_leds_pins_default: user-leds-pins-default { + user_leds_pins_default: user-leds-default-pins { pinctrl-single,pins = < AM64X_IOPAD(0x003c, PIN_OUTPUT, 7) /* (T20) GPMC0_AD0.GPIO0_15 */ AM64X_IOPAD(0x0040, PIN_OUTPUT, 7) /* (U21) GPMC0_AD1.GPIO0_16 */ @@ -210,6 +211,26 @@ pagesize = <16>; reg = <0x51>; }; + + led-controller@62 { + compatible = "nxp,pca9533"; + reg = <0x62>; + + led-3 { + label = "red:user"; + type = ; + }; + + led-4 { + label = "green:user"; + type = ; + }; + + led-5 { + label = "blue:user"; + type = ; + }; + }; }; &main_mcan0 { @@ -230,6 +251,7 @@ status = "okay"; pinctrl-names = "default"; pinctrl-0 = <&main_uart0_pins_default>; + current-speed = <115200>; }; &main_uart1 { @@ -237,6 +259,7 @@ pinctrl-names = "default"; pinctrl-0 = <&main_uart1_pins_default>; uart-has-rtscts; + current-speed = <115200>; }; &sdhci1 { diff --git a/arch/arm64/boot/dts/ti/k3-am642-sk.dts b/arch/arm64/boot/dts/ti/k3-am642-sk.dts index 2e2d40da360a274e0b2cc9c8164f45b31434b1a7..cbce43dbe3f9c286055b35dd10f6dbffb8bdc4c0 100644 --- a/arch/arm64/boot/dts/ti/k3-am642-sk.dts +++ b/arch/arm64/boot/dts/ti/k3-am642-sk.dts @@ -17,15 +17,25 @@ model = "Texas Instruments AM642 SK"; chosen { - stdout-path = "serial2:115200n8"; - bootargs = "console=ttyS2,115200n8 earlycon=ns16550a,mmio32,0x02800000"; + stdout-path = &main_uart0; + }; + + aliases { + serial0 = &mcu_uart0; + serial1 = &main_uart1; + serial2 = &main_uart0; + i2c0 = &main_i2c0; + i2c1 = &main_i2c1; + mmc0 = &sdhci0; + mmc1 = &sdhci1; + ethernet0 = &cpsw_port1; + ethernet1 = &cpsw_port2; }; memory@80000000 { device_type = "memory"; /* 2G RAM */ reg = <0x00000000 0x80000000 0x00000000 0x80000000>; - }; reserved-memory { @@ -94,7 +104,7 @@ }; }; - vusb_main: fixed-regulator-vusb-main5v0 { + vusb_main: regulator-0 { /* USB MAIN INPUT 5V DC */ compatible = "regulator-fixed"; regulator-name = "vusb_main5v0"; @@ -104,7 +114,7 @@ regulator-boot-on; }; - vcc_3v3_sys: fixedregulator-vcc-3v3-sys { + vcc_3v3_sys: regulator-1 { /* output of LP8733xx */ compatible = "regulator-fixed"; regulator-name = "vcc_3v3_sys"; @@ -115,7 +125,7 @@ regulator-boot-on; }; - vdd_mmc1: fixed-regulator-sd { + vdd_mmc1: regulator-2 { /* TPS2051BD */ compatible = "regulator-fixed"; regulator-name = "vdd_mmc1"; @@ -127,7 +137,7 @@ gpio = <&exp1 3 GPIO_ACTIVE_HIGH>; }; - com8_ls_en: regulator-1 { + com8_ls_en: regulator-3 { compatible = "regulator-fixed"; regulator-name = "com8_ls_en"; regulator-min-microvolt = <3300000>; @@ -139,7 +149,7 @@ gpio = <&main_gpio0 62 GPIO_ACTIVE_LOW>; }; - wlan_en: regulator-2 { + wlan_en: regulator-4 { /* output of SN74AVC4T245RSVR */ compatible = "regulator-fixed"; regulator-name = "wlan_en"; @@ -222,20 +232,21 @@ }; &main_pmx0 { - main_mmc1_pins_default: main-mmc1-pins-default { + main_mmc1_pins_default: main-mmc1-default-pins { pinctrl-single,pins = < - AM64X_IOPAD(0x0294, PIN_INPUT, 0) /* (J19) MMC1_CMD */ + AM64X_IOPAD(0x029c, PIN_INPUT_PULLUP, 0) /* (C20) MMC1_SDWP */ + AM64X_IOPAD(0x0298, PIN_INPUT_PULLUP, 0) /* (D19) MMC1_SDCD */ + AM64X_IOPAD(0x0294, PIN_INPUT_PULLUP, 0) /* (J19) MMC1_CMD */ AM64X_IOPAD(0x0290, PIN_INPUT, 0) /* (#N/A) MMC1_CLKLB */ - AM64X_IOPAD(0x028c, PIN_INPUT, 0) /* (L20) MMC1_CLK */ - AM64X_IOPAD(0x0288, PIN_INPUT, 0) /* (K21) MMC1_DAT0 */ - AM64X_IOPAD(0x0284, PIN_INPUT, 0) /* (L21) MMC1_DAT1 */ - AM64X_IOPAD(0x0280, PIN_INPUT, 0) /* (K19) MMC1_DAT2 */ - AM64X_IOPAD(0x027c, PIN_INPUT, 0) /* (K18) MMC1_DAT3 */ - AM64X_IOPAD(0x0298, PIN_INPUT, 0) /* (D19) MMC1_SDCD */ + AM64X_IOPAD(0x028c, PIN_INPUT_PULLDOWN, 0) /* (L20) MMC1_CLK */ + AM64X_IOPAD(0x0288, PIN_INPUT_PULLUP, 0) /* (K21) MMC1_DAT0 */ + AM64X_IOPAD(0x0284, PIN_INPUT_PULLUP, 0) /* (L21) MMC1_DAT1 */ + AM64X_IOPAD(0x0280, PIN_INPUT_PULLUP, 0) /* (K19) MMC1_DAT2 */ + AM64X_IOPAD(0x027c, PIN_INPUT_PULLUP, 0) /* (K18) MMC1_DAT3 */ >; }; - main_uart0_pins_default: main-uart0-pins-default { + main_uart0_pins_default: main-uart0-default-pins { pinctrl-single,pins = < AM64X_IOPAD(0x0238, PIN_INPUT, 0) /* (B16) UART0_CTSn */ AM64X_IOPAD(0x023c, PIN_OUTPUT, 0) /* (A16) UART0_RTSn */ @@ -244,27 +255,43 @@ >; }; - main_usb0_pins_default: main-usb0-pins-default { + main_uart1_pins_default: main-uart1-default-pins { + pinctrl-single,pins = < + AM64X_IOPAD(0x0248, PIN_INPUT, 0) /* (D16) UART1_CTSn */ + AM64X_IOPAD(0x024c, PIN_OUTPUT, 0) /* (E16) UART1_RTSn */ + AM64X_IOPAD(0x0240, PIN_INPUT, 0) /* (E15) UART1_RXD */ + AM64X_IOPAD(0x0244, PIN_OUTPUT, 0) /* (E14) UART1_TXD */ + >; + }; + + main_usb0_pins_default: main-usb0-default-pins { pinctrl-single,pins = < AM64X_IOPAD(0x02a8, PIN_OUTPUT, 0) /* (E19) USB0_DRVVBUS */ >; }; - main_i2c1_pins_default: main-i2c1-pins-default { + main_i2c0_pins_default: main-i2c0-default-pins { + pinctrl-single,pins = < + AM64X_IOPAD(0x0260, PIN_INPUT_PULLUP, 0) /* (A18) I2C0_SCL */ + AM64X_IOPAD(0x0264, PIN_INPUT_PULLUP, 0) /* (B18) I2C0_SDA */ + >; + }; + + main_i2c1_pins_default: main-i2c1-default-pins { pinctrl-single,pins = < AM64X_IOPAD(0x0268, PIN_INPUT_PULLUP, 0) /* (C18) I2C1_SCL */ AM64X_IOPAD(0x026c, PIN_INPUT_PULLUP, 0) /* (B19) I2C1_SDA */ >; }; - mdio1_pins_default: mdio1-pins-default { + mdio1_pins_default: mdio1-default-pins { pinctrl-single,pins = < AM64X_IOPAD(0x01fc, PIN_OUTPUT, 4) /* (R2) PRG0_PRU1_GPO19.MDIO0_MDC */ AM64X_IOPAD(0x01f8, PIN_INPUT, 4) /* (P5) PRG0_PRU1_GPO18.MDIO0_MDIO */ >; }; - rgmii1_pins_default: rgmii1-pins-default { + rgmii1_pins_default: rgmii1-default-pins { pinctrl-single,pins = < AM64X_IOPAD(0x011c, PIN_INPUT, 4) /* (AA13) PRG1_PRU1_GPO5.RGMII1_RD0 */ AM64X_IOPAD(0x0128, PIN_INPUT, 4) /* (U12) PRG1_PRU1_GPO8.RGMII1_RD1 */ @@ -281,7 +308,7 @@ >; }; - rgmii2_pins_default: rgmii2-pins-default { + rgmii2_pins_default: rgmii2-default-pins { pinctrl-single,pins = < AM64X_IOPAD(0x0108, PIN_INPUT, 4) /* (W11) PRG1_PRU1_GPO0.RGMII2_RD0 */ AM64X_IOPAD(0x010c, PIN_INPUT, 4) /* (V11) PRG1_PRU1_GPO1.RGMII2_RD1 */ @@ -298,7 +325,7 @@ >; }; - ospi0_pins_default: ospi0-pins-default { + ospi0_pins_default: ospi0-default-pins { pinctrl-single,pins = < AM64X_IOPAD(0x0000, PIN_OUTPUT, 0) /* (N20) OSPI0_CLK */ AM64X_IOPAD(0x002c, PIN_OUTPUT, 0) /* (L19) OSPI0_CSn0 */ @@ -314,24 +341,24 @@ >; }; - main_ecap0_pins_default: main-ecap0-pins-default { + main_ecap0_pins_default: main-ecap0-default-pins { pinctrl-single,pins = < AM64X_IOPAD(0x0270, PIN_INPUT, 0) /* (D18) ECAP0_IN_APWM_OUT */ >; }; - main_wlan_en_pins_default: main-wlan-en-pins-default { + main_wlan_en_pins_default: main-wlan-en-default-pins { pinctrl-single,pins = < AM64X_IOPAD(0x00c4, PIN_OUTPUT_PULLUP, 7) /* (V8) GPIO0_48 */ >; }; - main_com8_ls_en_pins_default: main-com8-ls-en-pins-default { + main_com8_ls_en_pins_default: main-com8-ls-en-default-pins { pinctrl-single,pins = < AM64X_IOPAD(0x00fc, PIN_OUTPUT, 7) /* (U7) PRG1_PRU0_GPO17.GPIO0_62 */ >; }; - main_wlan_pins_default: main-wlan-pins-default { + main_wlan_pins_default: main-wlan-default-pins { pinctrl-single,pins = < AM64X_IOPAD(0x00bc, PIN_INPUT, 7) /* (U8) GPIO0_46 */ >; @@ -342,11 +369,26 @@ status = "okay"; pinctrl-names = "default"; pinctrl-0 = <&main_uart0_pins_default>; + current-speed = <115200>; }; &main_uart1 { /* main_uart1 is reserved for firmware usage */ status = "reserved"; + pinctrl-names = "default"; + pinctrl-0 = <&main_uart1_pins_default>; +}; + +&main_i2c0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&main_i2c0_pins_default>; + clock-frequency = <400000>; + + eeprom@51 { + compatible = "atmel,24c512"; + reg = <0x51>; + }; }; &main_i2c1 { @@ -439,8 +481,7 @@ &cpsw3g { pinctrl-names = "default"; - pinctrl-0 = <&rgmii1_pins_default - &rgmii2_pins_default>; + pinctrl-0 = <&rgmii1_pins_default>, <&rgmii2_pins_default>; }; &cpsw_port1 { @@ -490,10 +531,53 @@ cdns,tchsh-ns = <60>; cdns,tslch-ns = <60>; cdns,read-delay = <4>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "ospi.tiboot3"; + reg = <0x0 0x100000>; + }; + + partition@100000 { + label = "ospi.tispl"; + reg = <0x100000 0x200000>; + }; + + partition@300000 { + label = "ospi.u-boot"; + reg = <0x300000 0x400000>; + }; + + partition@700000 { + label = "ospi.env"; + reg = <0x700000 0x40000>; + }; + + partition@740000 { + label = "ospi.env.backup"; + reg = <0x740000 0x40000>; + }; + + partition@800000 { + label = "ospi.rootfs"; + reg = <0x800000 0x37c0000>; + }; + + partition@3fc0000 { + label = "ospi.phypattern"; + reg = <0x3fc0000 0x40000>; + }; + }; }; }; &mailbox0_cluster2 { + status = "okay"; + mbox_main_r5fss0_core0: mbox-main-r5fss0-core0 { ti,mbox-rx = <0 0 2>; ti,mbox-tx = <1 0 2>; @@ -505,11 +589,9 @@ }; }; -&mailbox0_cluster3 { - status = "disabled"; -}; - &mailbox0_cluster4 { + status = "okay"; + mbox_main_r5fss1_core0: mbox-main-r5fss1-core0 { ti,mbox-rx = <0 0 2>; ti,mbox-tx = <1 0 2>; @@ -521,41 +603,35 @@ }; }; -&mailbox0_cluster5 { - status = "disabled"; -}; - &mailbox0_cluster6 { + status = "okay"; + mbox_m4_0: mbox-m4-0 { ti,mbox-rx = <0 0 2>; ti,mbox-tx = <1 0 2>; }; }; -&mailbox0_cluster7 { - status = "disabled"; -}; - &main_r5fss0_core0 { - mboxes = <&mailbox0_cluster2 &mbox_main_r5fss0_core0>; + mboxes = <&mailbox0_cluster2>, <&mbox_main_r5fss0_core0>; memory-region = <&main_r5fss0_core0_dma_memory_region>, <&main_r5fss0_core0_memory_region>; }; &main_r5fss0_core1 { - mboxes = <&mailbox0_cluster2 &mbox_main_r5fss0_core1>; + mboxes = <&mailbox0_cluster2>, <&mbox_main_r5fss0_core1>; memory-region = <&main_r5fss0_core1_dma_memory_region>, <&main_r5fss0_core1_memory_region>; }; &main_r5fss1_core0 { - mboxes = <&mailbox0_cluster4 &mbox_main_r5fss1_core0>; + mboxes = <&mailbox0_cluster4>, <&mbox_main_r5fss1_core0>; memory-region = <&main_r5fss1_core0_dma_memory_region>, <&main_r5fss1_core0_memory_region>; }; &main_r5fss1_core1 { - mboxes = <&mailbox0_cluster4 &mbox_main_r5fss1_core1>; + mboxes = <&mailbox0_cluster4>, <&mbox_main_r5fss1_core1>; memory-region = <&main_r5fss1_core1_dma_memory_region>, <&main_r5fss1_core1_memory_region>; }; diff --git a/arch/arm64/boot/dts/ti/k3-am65-iot2050-common.dtsi b/arch/arm64/boot/dts/ti/k3-am65-iot2050-common.dtsi index 96ac2b476b1160866824b16602ffe19882e9d6fc..e26bd988e5224e8ca7c157c851c0951f3e0ffcc5 100644 --- a/arch/arm64/boot/dts/ti/k3-am65-iot2050-common.dtsi +++ b/arch/arm64/boot/dts/ti/k3-am65-iot2050-common.dtsi @@ -21,7 +21,6 @@ chosen { stdout-path = "serial3:115200n8"; - bootargs = "earlycon=ns16550a,mmio32,0x02810000"; }; reserved-memory { @@ -105,7 +104,7 @@ }; &wkup_pmx0 { - wkup_i2c0_pins_default: wkup-i2c0-pins-default { + wkup_i2c0_pins_default: wkup-i2c0-default-pins { pinctrl-single,pins = < /* (AC7) WKUP_I2C0_SCL */ AM65X_WKUP_IOPAD(0x00e0, PIN_INPUT, 0) @@ -114,7 +113,7 @@ >; }; - mcu_i2c0_pins_default: mcu-i2c0-pins-default { + mcu_i2c0_pins_default: mcu-i2c0-default-pins { pinctrl-single,pins = < /* (AD8) MCU_I2C0_SCL */ AM65X_WKUP_IOPAD(0x00e8, PIN_INPUT, 0) @@ -123,21 +122,21 @@ >; }; - arduino_i2c_aio_switch_pins_default: arduino-i2c-aio-switch-pins-default { + arduino_i2c_aio_switch_pins_default: arduino-i2c-aio-switch-default-pins { pinctrl-single,pins = < /* (R2) WKUP_GPIO0_21 */ AM65X_WKUP_IOPAD(0x0024, PIN_OUTPUT, 7) >; }; - push_button_pins_default: push-button-pins-default { + push_button_pins_default: push-button-default-pins { pinctrl-single,pins = < /* (T1) MCU_OSPI1_CLK.WKUP_GPIO0_25 */ AM65X_WKUP_IOPAD(0x0034, PIN_INPUT, 7) >; }; - arduino_uart_pins_default: arduino-uart-pins-default { + arduino_uart_pins_default: arduino-uart-default-pins { pinctrl-single,pins = < /* (P4) MCU_UART0_RXD */ AM65X_WKUP_IOPAD(0x0044, PIN_INPUT, 4) @@ -146,7 +145,7 @@ >; }; - arduino_io_d2_to_d3_pins_default: arduino-io-d2-to-d3-pins-default { + arduino_io_d2_to_d3_pins_default: arduino-io-d2-to-d3-default-pins { pinctrl-single,pins = < /* (P1) WKUP_GPIO0_31 */ AM65X_WKUP_IOPAD(0x004C, PIN_OUTPUT, 7) @@ -155,7 +154,7 @@ >; }; - arduino_io_oe_pins_default: arduino-io-oe-pins-default { + arduino_io_oe_pins_default: arduino-io-oe-default-pins { pinctrl-single,pins = < /* (N4) WKUP_GPIO0_34 */ AM65X_WKUP_IOPAD(0x0058, PIN_OUTPUT, 7) @@ -170,7 +169,7 @@ >; }; - mcu_fss0_ospi0_pins_default: mcu-fss0-ospi0-pins-default { + mcu_fss0_ospi0_pins_default: mcu-fss0-ospi0-default-pins { pinctrl-single,pins = < /* (V1) MCU_OSPI0_CLK */ AM65X_WKUP_IOPAD(0x0000, PIN_OUTPUT, 0) @@ -185,7 +184,7 @@ >; }; - db9_com_mode_pins_default: db9-com-mode-pins-default { + db9_com_mode_pins_default: db9-com-mode-default-pins { pinctrl-single,pins = < /* (AD3) WKUP_GPIO0_5, used as uart0 mode 0 */ AM65X_WKUP_IOPAD(0x00c4, PIN_OUTPUT, 7) @@ -198,7 +197,7 @@ >; }; - leds_pins_default: leds-pins-default { + leds_pins_default: leds-default-pins { pinctrl-single,pins = < /* (T2) WKUP_GPIO0_17, used as user led1 red */ AM65X_WKUP_IOPAD(0x0014, PIN_OUTPUT, 7) @@ -211,7 +210,7 @@ >; }; - mcu_spi0_pins_default: mcu-spi0-pins-default { + mcu_spi0_pins_default: mcu-spi0-default-pins { pinctrl-single,pins = < /* (Y1) MCU_SPI0_CLK */ AM65X_WKUP_IOPAD(0x0090, PIN_INPUT, 0) @@ -224,7 +223,7 @@ >; }; - minipcie_pins_default: minipcie-pins-default { + minipcie_pins_default: minipcie-default-pins { pinctrl-single,pins = < /* (P2) MCU_OSPI1_DQS.WKUP_GPIO0_27 */ AM65X_WKUP_IOPAD(0x003C, PIN_OUTPUT, 7) @@ -233,7 +232,7 @@ }; &main_pmx0 { - main_uart1_pins_default: main-uart1-pins-default { + main_uart1_pins_default: main-uart1-default-pins { pinctrl-single,pins = < AM65X_IOPAD(0x0174, PIN_INPUT, 6) /* (AE23) UART1_RXD */ AM65X_IOPAD(0x014c, PIN_OUTPUT, 6) /* (AD23) UART1_TXD */ @@ -242,14 +241,14 @@ >; }; - main_i2c3_pins_default: main-i2c3-pins-default { + main_i2c3_pins_default: main-i2c3-default-pins { pinctrl-single,pins = < AM65X_IOPAD(0x01c0, PIN_INPUT, 2) /* (AF13) I2C3_SCL */ AM65X_IOPAD(0x01d4, PIN_INPUT, 2) /* (AG12) I2C3_SDA */ >; }; - main_mmc1_pins_default: main-mmc1-pins-default { + main_mmc1_pins_default: main-mmc1-default-pins { pinctrl-single,pins = < AM65X_IOPAD(0x02d4, PIN_INPUT_PULLDOWN, 0) /* (C27) MMC1_CLK */ AM65X_IOPAD(0x02d8, PIN_INPUT_PULLUP, 0) /* (C28) MMC1_CMD */ @@ -262,19 +261,19 @@ >; }; - usb0_pins_default: usb0-pins-default { + usb0_pins_default: usb0-default-pins { pinctrl-single,pins = < AM65X_IOPAD(0x02bc, PIN_OUTPUT, 0) /* (AD9) USB0_DRVVBUS */ >; }; - usb1_pins_default: usb1-pins-default { + usb1_pins_default: usb1-default-pins { pinctrl-single,pins = < AM65X_IOPAD(0x02c0, PIN_OUTPUT, 0) /* (AC8) USB1_DRVVBUS */ >; }; - arduino_io_d4_to_d9_pins_default: arduino-io-d4-to-d9-pins-default { + arduino_io_d4_to_d9_pins_default: arduino-io-d4-to-d9-default-pins { pinctrl-single,pins = < AM65X_IOPAD(0x0084, PIN_OUTPUT, 7) /* (AG18) GPIO0_33 */ AM65X_IOPAD(0x008C, PIN_OUTPUT, 7) /* (AF17) GPIO0_35 */ @@ -285,7 +284,7 @@ >; }; - dss_vout1_pins_default: dss-vout1-pins-default { + dss_vout1_pins_default: dss-vout1-default-pins { pinctrl-single,pins = < AM65X_IOPAD(0x0000, PIN_OUTPUT, 1) /* VOUT1_DATA0 */ AM65X_IOPAD(0x0004, PIN_OUTPUT, 1) /* VOUT1_DATA1 */ @@ -318,13 +317,13 @@ >; }; - dp_pins_default: dp-pins-default { + dp_pins_default: dp-default-pins { pinctrl-single,pins = < AM65X_IOPAD(0x0078, PIN_OUTPUT, 7) /* (AF18) DP rst_n */ >; }; - main_i2c2_pins_default: main-i2c2-pins-default { + main_i2c2_pins_default: main-i2c2-default-pins { pinctrl-single,pins = < AM65X_IOPAD(0x0074, PIN_INPUT, 5) /* (T27) I2C2_SCL */ AM65X_IOPAD(0x0070, PIN_INPUT, 5) /* (R25) I2C2_SDA */ @@ -333,21 +332,21 @@ }; &main_pmx1 { - main_i2c0_pins_default: main-i2c0-pins-default { + main_i2c0_pins_default: main-i2c0-default-pins { pinctrl-single,pins = < AM65X_IOPAD(0x0000, PIN_INPUT, 0) /* (D20) I2C0_SCL */ AM65X_IOPAD(0x0004, PIN_INPUT, 0) /* (C21) I2C0_SDA */ >; }; - main_i2c1_pins_default: main-i2c1-pins-default { + main_i2c1_pins_default: main-i2c1-default-pins { pinctrl-single,pins = < AM65X_IOPAD(0x0008, PIN_INPUT, 0) /* (B21) I2C1_SCL */ AM65X_IOPAD(0x000c, PIN_INPUT, 0) /* (E21) I2C1_SDA */ >; }; - ecap0_pins_default: ecap0-pins-default { + ecap0_pins_default: ecap0-default-pins { pinctrl-single,pins = < AM65X_IOPAD(0x0010, PIN_INPUT, 0) /* (D21) ECAP0_IN_APWM_OUT */ >; @@ -385,13 +384,12 @@ &wkup_gpio0 { pinctrl-names = "default"; - pinctrl-0 = < - &arduino_io_d2_to_d3_pins_default - &arduino_i2c_aio_switch_pins_default - &arduino_io_oe_pins_default - &push_button_pins_default - &db9_com_mode_pins_default - >; + pinctrl-0 = + <&arduino_io_d2_to_d3_pins_default>, + <&arduino_i2c_aio_switch_pins_default>, + <&arduino_io_oe_pins_default>, + <&push_button_pins_default>, + <&db9_com_mode_pins_default>; gpio-line-names = /* 0..9 */ "wkup_gpio0-base", "", "", "", "UART0-mode1", "UART0-mode0", @@ -483,7 +481,7 @@ pinctrl-0 = <&main_i2c0_pins_default>; clock-frequency = <400000>; - rtc: rtc8564@51 { + rtc: rtc@51 { compatible = "nxp,pcf8563"; reg = <0x51>; }; @@ -712,11 +710,11 @@ &mcu_r5fss0_core0 { memory-region = <&mcu_r5fss0_core0_dma_memory_region>, <&mcu_r5fss0_core0_memory_region>; - mboxes = <&mailbox0_cluster0 &mbox_mcu_r5fss0_core0>; + mboxes = <&mailbox0_cluster0>, <&mbox_mcu_r5fss0_core0>; }; &mcu_r5fss0_core1 { memory-region = <&mcu_r5fss0_core1_dma_memory_region>, <&mcu_r5fss0_core1_memory_region>; - mboxes = <&mailbox0_cluster1 &mbox_mcu_r5fss0_core1>; + mboxes = <&mailbox0_cluster1>, <&mbox_mcu_r5fss0_core1>; }; diff --git a/arch/arm64/boot/dts/ti/k3-am65-main.dtsi b/arch/arm64/boot/dts/ti/k3-am65-main.dtsi index 1adba2f2c153669a5acd89b9be5bcad5f2d1abd7..3f8ff2589842640be98fd0d809d45dd502d609d1 100644 --- a/arch/arm64/boot/dts/ti/k3-am65-main.dtsi +++ b/arch/arm64/boot/dts/ti/k3-am65-main.dtsi @@ -469,7 +469,6 @@ ti,otap-del-sel-ddr52 = <0x4>; ti,otap-del-sel-hs200 = <0x7>; ti,clkbuf-sel = <0x7>; - ti,otap-del-sel = <0x2>; ti,trm-icp = <0x8>; dma-coherent; }; @@ -481,21 +480,6 @@ #size-cells = <1>; ranges = <0x0 0x0 0x00100000 0x1c000>; - pcie0_mode: pcie-mode@4060 { - compatible = "syscon"; - reg = <0x00004060 0x4>; - }; - - pcie1_mode: pcie-mode@4070 { - compatible = "syscon"; - reg = <0x00004070 0x4>; - }; - - pcie_devid: pcie-devid@210 { - compatible = "syscon"; - reg = <0x00000210 0x4>; - }; - serdes0_clk: clock@4080 { compatible = "syscon"; reg = <0x00004080 0x4>; @@ -883,8 +867,8 @@ #size-cells = <2>; ranges = <0x81000000 0 0 0x0 0x10020000 0 0x00010000>, <0x82000000 0 0x10030000 0x0 0x10030000 0 0x07FD0000>; - ti,syscon-pcie-id = <&pcie_devid>; - ti,syscon-pcie-mode = <&pcie0_mode>; + ti,syscon-pcie-id = <&scm_conf 0x210>; + ti,syscon-pcie-mode = <&scm_conf 0x4060>; bus-range = <0x0 0xff>; num-viewport = <16>; max-link-speed = <2>; @@ -900,7 +884,7 @@ reg = <0x0 0x5500000 0x0 0x1000>, <0x0 0x5501000 0x0 0x1000>, <0x0 0x10000000 0x0 0x8000000>, <0x0 0x5506000 0x0 0x1000>; reg-names = "app", "dbics", "addr_space", "atu"; power-domains = <&k3_pds 120 TI_SCI_PD_EXCLUSIVE>; - ti,syscon-pcie-mode = <&pcie0_mode>; + ti,syscon-pcie-mode = <&scm_conf 0x4060>; num-ib-windows = <16>; num-ob-windows = <16>; max-link-speed = <2>; @@ -918,8 +902,8 @@ #size-cells = <2>; ranges = <0x81000000 0 0 0x0 0x18020000 0 0x00010000>, <0x82000000 0 0x18030000 0x0 0x18030000 0 0x07FD0000>; - ti,syscon-pcie-id = <&pcie_devid>; - ti,syscon-pcie-mode = <&pcie1_mode>; + ti,syscon-pcie-id = <&scm_conf 0x210>; + ti,syscon-pcie-mode = <&scm_conf 0x4070>; bus-range = <0x0 0xff>; num-viewport = <16>; max-link-speed = <2>; @@ -935,7 +919,7 @@ reg = <0x0 0x5600000 0x0 0x1000>, <0x0 0x5601000 0x0 0x1000>, <0x0 0x18000000 0x0 0x4000000>, <0x0 0x5606000 0x0 0x1000>; reg-names = "app", "dbics", "addr_space", "atu"; power-domains = <&k3_pds 121 TI_SCI_PD_EXCLUSIVE>; - ti,syscon-pcie-mode = <&pcie1_mode>; + ti,syscon-pcie-mode = <&scm_conf 0x4070>; num-ib-windows = <16>; num-ob-windows = <16>; max-link-speed = <2>; diff --git a/arch/arm64/boot/dts/ti/k3-am65-mcu.dtsi b/arch/arm64/boot/dts/ti/k3-am65-mcu.dtsi index 5dfa31840e9c320a4abb07080b018d1bbb3314d5..b7a4b5a89aaf144e01aba0ca368a936479e56312 100644 --- a/arch/arm64/boot/dts/ti/k3-am65-mcu.dtsi +++ b/arch/arm64/boot/dts/ti/k3-am65-mcu.dtsi @@ -227,7 +227,22 @@ }; }; - m_can0: mcan@40528000 { + secure_proxy_mcu: mailbox@2a480000 { + compatible = "ti,am654-secure-proxy"; + #mbox-cells = <1>; + reg-names = "target_data", "rt", "scfg"; + reg = <0x0 0x2a480000 0x0 0x80000>, + <0x0 0x2a380000 0x0 0x80000>, + <0x0 0x2a400000 0x0 0x80000>; + /* + * Marked Disabled: + * Node is incomplete as it is meant for bootloaders and + * firmware on non-MPU processors + */ + status = "disabled"; + }; + + m_can0: can@40528000 { compatible = "bosch,m_can"; reg = <0x0 0x40528000 0x0 0x400>, <0x0 0x40500000 0x0 0x4400>; @@ -243,7 +258,7 @@ status = "disabled"; }; - m_can1: mcan@40568000 { + m_can1: can@40568000 { compatible = "bosch,m_can"; reg = <0x0 0x40568000 0x0 0x400>, <0x0 0x40540000 0x0 0x4400>; diff --git a/arch/arm64/boot/dts/ti/k3-am65.dtsi b/arch/arm64/boot/dts/ti/k3-am65.dtsi index 3093ef6b9b23f6da280a82469630a1c9cb636a8f..4d7b6155a76b7bb3a0d802e19fc8e6692284083a 100644 --- a/arch/arm64/boot/dts/ti/k3-am65.dtsi +++ b/arch/arm64/boot/dts/ti/k3-am65.dtsi @@ -19,23 +19,6 @@ #address-cells = <2>; #size-cells = <2>; - aliases { - serial0 = &wkup_uart0; - serial1 = &mcu_uart0; - serial2 = &main_uart0; - serial3 = &main_uart1; - serial4 = &main_uart2; - i2c0 = &wkup_i2c0; - i2c1 = &mcu_i2c0; - i2c2 = &main_i2c0; - i2c3 = &main_i2c1; - i2c4 = &main_i2c2; - i2c5 = &main_i2c3; - ethernet0 = &cpsw_port1; - mmc0 = &sdhci0; - mmc1 = &sdhci1; - }; - chosen { }; firmware { diff --git a/arch/arm64/boot/dts/ti/k3-am6528-iot2050-basic-common.dtsi b/arch/arm64/boot/dts/ti/k3-am6528-iot2050-basic-common.dtsi index cd43fd11a5c2c424f841945044677854adacb99d..5ab434c02ab6b44acfaa775d2c84aac2b5cee418 100644 --- a/arch/arm64/boot/dts/ti/k3-am6528-iot2050-basic-common.dtsi +++ b/arch/arm64/boot/dts/ti/k3-am6528-iot2050-basic-common.dtsi @@ -35,7 +35,7 @@ }; &main_pmx0 { - main_uart0_pins_default: main-uart0-pins-default { + main_uart0_pins_default: main-uart0-default-pins { pinctrl-single,pins = < AM65X_IOPAD(0x01e4, PIN_INPUT, 0) /* (AF11) UART0_RXD */ AM65X_IOPAD(0x01e8, PIN_OUTPUT, 0) /* (AE11) UART0_TXD */ diff --git a/arch/arm64/boot/dts/ti/k3-am654-base-board-rocktech-rk101-panel.dtso b/arch/arm64/boot/dts/ti/k3-am654-base-board-rocktech-rk101-panel.dtso new file mode 100644 index 0000000000000000000000000000000000000000..3be92c39ecbae72e6e973a83cb91e7a9b4cc4dc0 --- /dev/null +++ b/arch/arm64/boot/dts/ti/k3-am654-base-board-rocktech-rk101-panel.dtso @@ -0,0 +1,71 @@ +// SPDX-License-Identifier: GPL-2.0 +/** + * OLDI-LCD1EVM Rocktech integrated panel and touch DT overlay for AM654-EVM. + * Panel Link: https://www.digimax.it/en/tft-lcd/20881-RK101II01D-CT + * AM654 LCD EVM: https://www.ti.com/tool/TMDSLCD1EVM + * + * Copyright (C) 2023 Texas Instruments Incorporated - http://www.ti.com/ + */ + +/dts-v1/; +/plugin/; + +#include +#include +#include + +&{/} { + display0 { + compatible = "rocktech,rk101ii01d-ct"; + backlight = <&lcd_bl>; + enable-gpios = <&pca9555 8 GPIO_ACTIVE_HIGH>; + port { + lcd_in0: endpoint { + remote-endpoint = <&oldi_out0>; + }; + }; + }; + + lcd_bl: backlight { + compatible = "pwm-backlight"; + pwms = <&ecap0 0 50000 PWM_POLARITY_INVERTED>; + brightness-levels = + <0 32 64 96 128 160 192 224 255>; + default-brightness-level = <8>; + }; +}; + +&dss { + status = "okay"; +}; + +&dss_ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + oldi_out0: endpoint { + remote-endpoint = <&lcd_in0>; + }; + }; +}; + +&main_i2c1 { + #address-cells = <1>; + #size-cells = <0>; + + touchscreen@14 { + compatible = "goodix,gt928"; + reg = <0x14>; + + interrupt-parent = <&pca9554>; + interrupts = <3 IRQ_TYPE_EDGE_FALLING>; + touchscreen-size-x = <1280>; + touchscreen-size-y = <800>; + + reset-gpios = <&pca9555 9 GPIO_ACTIVE_HIGH>; + irq-gpios = <&pca9554 3 GPIO_ACTIVE_HIGH>; + }; +}; diff --git a/arch/arm64/boot/dts/ti/k3-am654-base-board.dts b/arch/arm64/boot/dts/ti/k3-am654-base-board.dts index 592ab2b54cb3dbbc6c2f09b4e1bc0077645d2c4e..973a89b04a22f0980f800b0e1dbae628679d877f 100644 --- a/arch/arm64/boot/dts/ti/k3-am654-base-board.dts +++ b/arch/arm64/boot/dts/ti/k3-am654-base-board.dts @@ -13,9 +13,22 @@ compatible = "ti,am654-evm", "ti,am654"; model = "Texas Instruments AM654 Base Board"; + aliases { + serial0 = &wkup_uart0; + serial1 = &mcu_uart0; + serial2 = &main_uart0; + i2c0 = &wkup_i2c0; + i2c1 = &mcu_i2c0; + i2c2 = &main_i2c0; + i2c3 = &main_i2c1; + i2c4 = &main_i2c2; + ethernet0 = &cpsw_port1; + mmc0 = &sdhci0; + mmc1 = &sdhci1; + }; + chosen { stdout-path = "serial2:115200n8"; - bootargs = "earlycon=ns16550a,mmio32,0x02800000"; }; memory@80000000 { @@ -86,7 +99,7 @@ }; }; - evm_12v0: fixedregulator-evm12v0 { + evm_12v0: regulator-0 { /* main supply */ compatible = "regulator-fixed"; regulator-name = "evm_12v0"; @@ -96,7 +109,7 @@ regulator-boot-on; }; - vcc3v3_io: fixedregulator-vcc3v3io { + vcc3v3_io: regulator-1 { /* Output of TPS54334 */ compatible = "regulator-fixed"; regulator-name = "vcc3v3_io"; @@ -107,7 +120,7 @@ vin-supply = <&evm_12v0>; }; - vdd_mmc1_sd: fixedregulator-sd { + vdd_mmc1_sd: regulator-2 { compatible = "regulator-fixed"; regulator-name = "vdd_mmc1_sd"; regulator-min-microvolt = <3300000>; @@ -117,24 +130,53 @@ vin-supply = <&vcc3v3_io>; gpio = <&pca9554 4 GPIO_ACTIVE_HIGH>; }; + + vtt_supply: regulator-3 { + compatible = "regulator-fixed"; + regulator-name = "vtt"; + pinctrl-names = "default"; + pinctrl-0 = <&ddr_vtt_pins_default>; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + enable-active-high; + regulator-always-on; + regulator-boot-on; + vin-supply = <&vcc3v3_io>; + gpio = <&wkup_gpio0 28 GPIO_ACTIVE_HIGH>; + }; }; &wkup_pmx0 { - wkup_i2c0_pins_default: wkup-i2c0-pins-default { + wkup_uart0_pins_default: wkup-uart0-default-pins { + pinctrl-single,pins = < + AM65X_WKUP_IOPAD(0x00a0, PIN_INPUT, 0) /* (AB1) WKUP_UART0_RXD */ + AM65X_WKUP_IOPAD(0x00a4, PIN_OUTPUT, 0) /* (AB5) WKUP_UART0_TXD */ + AM65X_WKUP_IOPAD(0x00c8, PIN_INPUT, 1) /* (AC2) WKUP_GPIO0_6.WKUP_UART0_CTSn */ + AM65X_WKUP_IOPAD(0x00cc, PIN_OUTPUT, 1) /* (AC1) WKUP_GPIO0_7.WKUP_UART0_RTSn */ + >; + }; + + ddr_vtt_pins_default: ddr-vtt-default-pins { + pinctrl-single,pins = < + AM65X_WKUP_IOPAD(0x0040, PIN_OUTPUT_PULLUP, 7) /* WKUP_GPIO0_28 */ + >; + }; + + wkup_i2c0_pins_default: wkup-i2c0-default-pins { pinctrl-single,pins = < AM65X_WKUP_IOPAD(0x00e0, PIN_INPUT, 0) /* (AC7) WKUP_I2C0_SCL */ AM65X_WKUP_IOPAD(0x00e4, PIN_INPUT, 0) /* (AD6) WKUP_I2C0_SDA */ >; }; - push_button_pins_default: push-button-pins-default { + push_button_pins_default: push-button-default-pins { pinctrl-single,pins = < AM65X_WKUP_IOPAD(0x0030, PIN_INPUT, 7) /* (R5) WKUP_GPIO0_24 */ AM65X_WKUP_IOPAD(0x003c, PIN_INPUT, 7) /* (P2) WKUP_GPIO0_27 */ >; }; - mcu_fss0_ospi0_pins_default: mcu-fss0-ospi0-pins-default { + mcu_fss0_ospi0_pins_default: mcu-fss0-ospi0-default-pins { pinctrl-single,pins = < AM65X_WKUP_IOPAD(0x0000, PIN_OUTPUT, 0) /* (V1) MCU_OSPI0_CLK */ AM65X_WKUP_IOPAD(0x0008, PIN_INPUT, 0) /* (U2) MCU_OSPI0_DQS */ @@ -156,7 +198,16 @@ >; }; - mcu_cpsw_pins_default: mcu-cpsw-pins-default { + mcu_uart0_pins_default: mcu-uart0-default-pins { + pinctrl-single,pins = < + AM65X_WKUP_IOPAD(0x0044, PIN_INPUT, 4) /* (P4) MCU_OSPI1_D1.MCU_UART0_RXD */ + AM65X_WKUP_IOPAD(0x0048, PIN_OUTPUT, 4) /* (P5) MCU_OSPI1_D2.MCU_UART0_TXD */ + AM65X_WKUP_IOPAD(0x004C, PIN_INPUT, 4) /* (P1) MCU_OSPI1_D3.MCU_UART0_CTSn */ + AM65X_WKUP_IOPAD(0x0054, PIN_OUTPUT, 4) /* (N3) MCU_OSPI1_CSn1.MCU_UART0_RTSn */ + >; + }; + + mcu_cpsw_pins_default: mcu-cpsw-default-pins { pinctrl-single,pins = < AM65X_WKUP_IOPAD(0x0058, PIN_OUTPUT, 0) /* (N4) MCU_RGMII1_TX_CTL */ AM65X_WKUP_IOPAD(0x005c, PIN_INPUT, 0) /* (N5) MCU_RGMII1_RX_CTL */ @@ -173,16 +224,23 @@ >; }; - mcu_mdio_pins_default: mcu-mdio1-pins-default { + mcu_mdio_pins_default: mcu-mdio1-default-pins { pinctrl-single,pins = < AM65X_WKUP_IOPAD(0x008c, PIN_OUTPUT, 0) /* (L1) MCU_MDIO0_MDC */ AM65X_WKUP_IOPAD(0x0088, PIN_INPUT, 0) /* (L4) MCU_MDIO0_MDIO */ >; }; + + mcu_i2c0_pins_default: mcu-i2c0-default-pins { + pinctrl-single,pins = < + AM65X_WKUP_IOPAD(0x00e8, PIN_INPUT, 0) /* (AD8) MCU_I2C0_SCL */ + AM65X_WKUP_IOPAD(0x00ec, PIN_INPUT, 0) /* (AD7) MCU_I2C0_SDA */ + >; + }; }; &main_pmx0 { - main_uart0_pins_default: main-uart0-pins-default { + main_uart0_pins_default: main-uart0-default-pins { pinctrl-single,pins = < AM65X_IOPAD(0x01e4, PIN_INPUT, 0) /* (AF11) UART0_RXD */ AM65X_IOPAD(0x01e8, PIN_OUTPUT, 0) /* (AE11) UART0_TXD */ @@ -191,14 +249,14 @@ >; }; - main_i2c2_pins_default: main-i2c2-pins-default { + main_i2c2_pins_default: main-i2c2-default-pins { pinctrl-single,pins = < AM65X_IOPAD(0x0074, PIN_INPUT, 5) /* (T27) GPMC0_CSn3.I2C2_SCL */ AM65X_IOPAD(0x0070, PIN_INPUT, 5) /* (R25) GPMC0_CSn2.I2C2_SDA */ >; }; - main_spi0_pins_default: main-spi0-pins-default { + main_spi0_pins_default: main-spi0-default-pins { pinctrl-single,pins = < AM65X_IOPAD(0x01c4, PIN_INPUT, 0) /* (AH13) SPI0_CLK */ AM65X_IOPAD(0x01c8, PIN_INPUT, 0) /* (AE13) SPI0_D0 */ @@ -207,7 +265,7 @@ >; }; - main_mmc0_pins_default: main-mmc0-pins-default { + main_mmc0_pins_default: main-mmc0-default-pins { pinctrl-single,pins = < AM65X_IOPAD(0x01a8, PIN_INPUT_PULLDOWN, 0) /* (B25) MMC0_CLK */ AM65X_IOPAD(0x01ac, PIN_INPUT_PULLUP, 0) /* (B27) MMC0_CMD */ @@ -224,7 +282,7 @@ >; }; - main_mmc1_pins_default: main-mmc1-pins-default { + main_mmc1_pins_default: main-mmc1-default-pins { pinctrl-single,pins = < AM65X_IOPAD(0x02d4, PIN_INPUT_PULLDOWN, 0) /* (C27) MMC1_CLK */ AM65X_IOPAD(0x02d8, PIN_INPUT_PULLUP, 0) /* (C28) MMC1_CMD */ @@ -237,7 +295,7 @@ >; }; - usb1_pins_default: usb1-pins-default { + usb1_pins_default: usb1-default-pins { pinctrl-single,pins = < AM65X_IOPAD(0x02c0, PIN_OUTPUT, 0) /* (AC8) USB1_DRVVBUS */ >; @@ -245,21 +303,21 @@ }; &main_pmx1 { - main_i2c0_pins_default: main-i2c0-pins-default { + main_i2c0_pins_default: main-i2c0-default-pins { pinctrl-single,pins = < AM65X_IOPAD(0x0000, PIN_INPUT, 0) /* (D20) I2C0_SCL */ AM65X_IOPAD(0x0004, PIN_INPUT, 0) /* (C21) I2C0_SDA */ >; }; - main_i2c1_pins_default: main-i2c1-pins-default { + main_i2c1_pins_default: main-i2c1-default-pins { pinctrl-single,pins = < AM65X_IOPAD(0x0008, PIN_INPUT, 0) /* (B21) I2C1_SCL */ AM65X_IOPAD(0x000c, PIN_INPUT, 0) /* (E21) I2C1_SDA */ >; }; - ecap0_pins_default: ecap0-pins-default { + ecap0_pins_default: ecap0-default-pins { pinctrl-single,pins = < AM65X_IOPAD(0x0010, PIN_INPUT, 0) /* (D21) ECAP0_IN_APWM_OUT */ >; @@ -269,11 +327,14 @@ &wkup_uart0 { /* Wakeup UART is used by System firmware */ status = "reserved"; + pinctrl-names = "default"; + pinctrl-0 = <&wkup_uart0_pins_default>; }; &mcu_uart0 { status = "okay"; - /* Default pinmux */ + pinctrl-names = "default"; + pinctrl-0 = <&mcu_uart0_pins_default>; }; &main_uart0 { @@ -289,6 +350,25 @@ pinctrl-0 = <&wkup_i2c0_pins_default>; clock-frequency = <400000>; + eeprom@50 { + /* AT24CM01 */ + compatible = "atmel,24c1024"; + reg = <0x50>; + }; + + vdd_mpu: regulator@60 { + compatible = "ti,tps62363"; + reg = <0x60>; + regulator-name = "VDD_MPU"; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <1770000>; + regulator-always-on; + regulator-boot-on; + ti,vsel0-state-high; + ti,vsel1-state-high; + ti,enable-vout-discharge; + }; + pca9554: gpio@39 { compatible = "nxp,pca9554"; reg = <0x39>; @@ -305,7 +385,9 @@ &mcu_i2c0 { status = "okay"; - /* Default pinmux */ + pinctrl-names = "default"; + pinctrl-0 = <&mcu_i2c0_pins_default>; + clock-frequency = <400000>; }; &main_i2c0 { @@ -438,13 +520,13 @@ &mcu_r5fss0_core0 { memory-region = <&mcu_r5fss0_core0_dma_memory_region>, <&mcu_r5fss0_core0_memory_region>; - mboxes = <&mailbox0_cluster0 &mbox_mcu_r5fss0_core0>; + mboxes = <&mailbox0_cluster0>, <&mbox_mcu_r5fss0_core0>; }; &mcu_r5fss0_core1 { memory-region = <&mcu_r5fss0_core1_dma_memory_region>, <&mcu_r5fss0_core1_memory_region>; - mboxes = <&mailbox0_cluster1 &mbox_mcu_r5fss0_core1>; + mboxes = <&mailbox0_cluster1>, <&mbox_mcu_r5fss0_core1>; }; &ospi0 { @@ -462,6 +544,52 @@ cdns,tchsh-ns = <60>; cdns,tslch-ns = <60>; cdns,read-delay = <0>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "ospi.tiboot3"; + reg = <0x0 0x80000>; + }; + + partition@80000 { + label = "ospi.tispl"; + reg = <0x80000 0x200000>; + }; + + partition@280000 { + label = "ospi.u-boot"; + reg = <0x280000 0x400000>; + }; + + partition@680000 { + label = "ospi.env"; + reg = <0x680000 0x20000>; + }; + + partition@6a0000 { + label = "ospi.env.backup"; + reg = <0x6a0000 0x20000>; + }; + + partition@6c0000 { + label = "ospi.sysfw"; + reg = <0x6c0000 0x100000>; + }; + + partition@800000 { + label = "ospi.rootfs"; + reg = <0x800000 0x37c0000>; + }; + + partition@3fe0000 { + label = "ospi.phypattern"; + reg = <0x3fe0000 0x20000>; + }; + }; }; }; diff --git a/arch/arm64/boot/dts/ti/k3-am654.dtsi b/arch/arm64/boot/dts/ti/k3-am654.dtsi index 4cc329b271acaa8cfad7de7fe7c033a4dbba0ed0..888567b921f0ac46530f9a38daeea174e634ad72 100644 --- a/arch/arm64/boot/dts/ti/k3-am654.dtsi +++ b/arch/arm64/boot/dts/ti/k3-am654.dtsi @@ -113,6 +113,7 @@ msmc_l3: l3-cache0 { compatible = "cache"; cache-level = <3>; + cache-unified; }; thermal_zones: thermal-zones { diff --git a/arch/arm64/boot/dts/ti/k3-am6548-iot2050-advanced-common.dtsi b/arch/arm64/boot/dts/ti/k3-am6548-iot2050-advanced-common.dtsi index 0f67e1ec0fb86729c9bc157b27bad232b863c4a5..be55494b1f3fcaa7f1d8a94655abcc4374a2d432 100644 --- a/arch/arm64/boot/dts/ti/k3-am6548-iot2050-advanced-common.dtsi +++ b/arch/arm64/boot/dts/ti/k3-am6548-iot2050-advanced-common.dtsi @@ -22,7 +22,7 @@ }; &main_pmx0 { - main_mmc0_pins_default: main-mmc0-pins-default { + main_mmc0_pins_default: main-mmc0-default-pins { pinctrl-single,pins = < AM65X_IOPAD(0x01a8, PIN_INPUT_PULLDOWN, 0) /* (B25) MMC0_CLK */ AM65X_IOPAD(0x01ac, PIN_INPUT_PULLUP, 0) /* (B27) MMC0_CMD */ diff --git a/arch/arm64/boot/dts/ti/k3-am6548-iot2050-advanced-m2.dts b/arch/arm64/boot/dts/ti/k3-am6548-iot2050-advanced-m2.dts index 9400e35882a6e52bcfe50f28ca80fd0bb707c9aa..cbe44634914fdb01ae4bd59ef43cb4103ba0af15 100644 --- a/arch/arm64/boot/dts/ti/k3-am6548-iot2050-advanced-m2.dts +++ b/arch/arm64/boot/dts/ti/k3-am6548-iot2050-advanced-m2.dts @@ -27,7 +27,7 @@ }; &main_pmx0 { - main_m2_enable_pins_default: main-m2-enable-pins-default { + main_m2_enable_pins_default: main-m2-enable-default-pins { pinctrl-single,pins = < AM65X_IOPAD(0x01c4, PIN_INPUT_PULLUP, 7) /* (AH13) GPIO1_17 */ >; @@ -39,7 +39,7 @@ >; }; - main_pmx0_m2_config_pins_default: main-pmx0-m2-config-pins-default { + main_pmx0_m2_config_pins_default: main-pmx0-m2-config-default-pins { pinctrl-single,pins = < AM65X_IOPAD(0x01c8, PIN_INPUT_PULLUP, 7) /* (AE13) GPIO1_18 */ AM65X_IOPAD(0x01cc, PIN_INPUT_PULLUP, 7) /* (AD13) GPIO1_19 */ @@ -56,7 +56,7 @@ }; &main_pmx1 { - main_pmx1_m2_config_pins_default: main-pmx1-m2-config-pins-default { + main_pmx1_m2_config_pins_default: main-pmx1-m2-config-default-pins { pinctrl-single,pins = < AM65X_IOPAD(0x0018, PIN_INPUT_PULLUP, 7) /* (B22) GPIO1_88 */ AM65X_IOPAD(0x001c, PIN_INPUT_PULLUP, 7) /* (C23) GPIO1_89 */ @@ -66,20 +66,18 @@ &main_gpio0 { pinctrl-names = "default"; - pinctrl-0 = < - &main_m2_pcie_mux_control - &arduino_io_d4_to_d9_pins_default - >; + pinctrl-0 = + <&main_m2_pcie_mux_control>, + <&arduino_io_d4_to_d9_pins_default>; }; &main_gpio1 { pinctrl-names = "default"; - pinctrl-0 = < - &main_m2_enable_pins_default - &main_pmx0_m2_config_pins_default - &main_pmx1_m2_config_pins_default - &cp2102n_reset_pin_default - >; + pinctrl-0 = + <&main_m2_enable_pins_default>, + <&main_pmx0_m2_config_pins_default>, + <&main_pmx1_m2_config_pins_default>, + <&cp2102n_reset_pin_default>; }; /* diff --git a/arch/arm64/boot/dts/ti/k3-am68-sk-base-board.dts b/arch/arm64/boot/dts/ti/k3-am68-sk-base-board.dts index 27a43a8ecffd4e4544036b03b427d462f880091a..d5889ba3fa46733ca44abe01dbac5906dbb4d7a8 100644 --- a/arch/arm64/boot/dts/ti/k3-am68-sk-base-board.dts +++ b/arch/arm64/boot/dts/ti/k3-am68-sk-base-board.dts @@ -22,6 +22,8 @@ }; aliases { + serial0 = &wkup_uart0; + serial1 = &mcu_uart0; serial2 = &main_uart8; mmc1 = &main_sdhci1; can0 = &mcu_mcan0; @@ -122,21 +124,21 @@ }; &main_pmx0 { - main_uart8_pins_default: main-uart8-pins-default { + main_uart8_pins_default: main-uart8-default-pins { pinctrl-single,pins = < J721S2_IOPAD(0x0d0, PIN_INPUT, 11) /* (AF26) SPI0_CS1.UART8_RXD */ J721S2_IOPAD(0x0d4, PIN_OUTPUT, 11) /* (AH27) SPI0_CLK.UART8_TXD */ >; }; - main_i2c0_pins_default: main-i2c0-pins-default { + main_i2c0_pins_default: main-i2c0-default-pins { pinctrl-single,pins = < J721S2_IOPAD(0x0e0, PIN_INPUT, 0) /* (AH25) I2C0_SCL */ J721S2_IOPAD(0x0e4, PIN_INPUT, 0) /* (AE24) I2C0_SDA */ >; }; - main_mmc1_pins_default: main-mmc1-pins-default { + main_mmc1_pins_default: main-mmc1-default-pins { pinctrl-single,pins = < J721S2_IOPAD(0x104, PIN_INPUT, 0) /* (P23) MMC1_CLK */ J721S2_IOPAD(0x108, PIN_INPUT, 0) /* (N24) MMC1_CMD */ @@ -148,80 +150,156 @@ >; }; - vdd_sd_dv_pins_default: vdd-sd-dv-pins-default { + vdd_sd_dv_pins_default: vdd-sd-dv-default-pins { pinctrl-single,pins = < J721S2_IOPAD(0x0c4, PIN_INPUT, 7) /* (AB26) ECAP0_IN_APWM_OUT.GPIO0_49 */ >; }; - main_usbss0_pins_default: main-usbss0-pins-default { + main_usbss0_pins_default: main-usbss0-default-pins { pinctrl-single,pins = < J721S2_IOPAD(0x0ec, PIN_OUTPUT, 6) /* (AG25) TIMER_IO1.USB0_DRVVBUS */ >; }; - main_mcan6_pins_default: main-mcan6-pins-default { + main_mcan6_pins_default: main-mcan6-default-pins { pinctrl-single,pins = < J721S2_IOPAD(0x098, PIN_INPUT, 0) /* (V25) MCASP0_AXR10.MCAN6_RX */ J721S2_IOPAD(0x094, PIN_INPUT, 0) /* (AA25) MCASP0_AXR9.MCAN6_TX */ >; }; - main_mcan7_pins_default: main-mcan7-pins-default { + main_mcan7_pins_default: main-mcan7-default-pins { pinctrl-single,pins = < J721S2_IOPAD(0x0a0, PIN_INPUT, 0) /* (AB25) MCASP0_AXR12.MCAN7_RX */ J721S2_IOPAD(0x09c, PIN_INPUT, 0) /* (T24) MCASP0_AXR11.MCAN7_TX */ >; }; + + main_i2c4_pins_default: main-i2c4-default-pins { + pinctrl-single,pins = < + J721S2_IOPAD(0x010, PIN_INPUT_PULLUP, 8) /* (AF28) MCAN13_RX.I2C4_SDA */ + J721S2_IOPAD(0x014, PIN_INPUT_PULLUP, 8) /* (AD25) MCAN14_TX.I2C4_SCL */ + >; + }; + + rpi_header_gpio0_pins_default: rpi-header-gpio0-default-pins { + pinctrl-single,pins = < + J721S2_IOPAD(0x0a8, PIN_INPUT, 7) /* (U24) MCASP0_AXR14.GPIO0_42 */ + J721S2_IOPAD(0x090, PIN_INPUT, 7) /* (W24) MCASP0_AXR8.GPIO0_36 */ + J721S2_IOPAD(0x0bc, PIN_INPUT, 7) /* (V28) MCASP1_AFSX.GPIO0_47 */ + J721S2_IOPAD(0x06c, PIN_INPUT, 7) /* (V26) MCAN1_TX.GPIO0_27 */ + J721S2_IOPAD(0x004, PIN_INPUT, 7) /* (W25) MCAN12_TX.GPIO0_1 */ + J721S2_IOPAD(0x008, PIN_INPUT, 7) /* (AC24) MCAN12_RX.GPIO0_2 */ + J721S2_IOPAD(0x0b8, PIN_INPUT, 7) /* (AA24) MCASP1_ACLKX.GPIO0_46 */ + J721S2_IOPAD(0x00c, PIN_INPUT, 7) /* (AE28) MCAN13_TX.GPIO0_3 */ + J721S2_IOPAD(0x034, PIN_INPUT, 7) /* (AD24) PMIC_WAKE0.GPIO0_13 */ + J721S2_IOPAD(0x0a4, PIN_INPUT, 7) /* (T23) MCASP0_AXR13.GPIO0_41 */ + J721S2_IOPAD(0x0c0, PIN_INPUT, 7) /* (T28) MCASP1_AXR0.GPIO0_48 */ + J721S2_IOPAD(0x0b4, PIN_INPUT, 7) /* (U25) MCASP1_AXR4.GPIO0_45 */ + J721S2_IOPAD(0x0cc, PIN_INPUT, 7) /* (AE27) SPI0_CS0.GPIO0_51 */ + J721S2_IOPAD(0x08c, PIN_INPUT, 7) /* (T25) MCASP0_AXR7.GPIO0_35 */ + >; + }; }; -&wkup_pmx0 { - mcu_cpsw_pins_default: mcu-cpsw-pins-default { +&wkup_pmx2 { + wkup_uart0_pins_default: wkup-uart0-default-pins { + pinctrl-single,pins = < + J721S2_WKUP_IOPAD(0x070, PIN_INPUT, 0) /* (E25) WKUP_GPIO0_6.WKUP_UART0_CTSn */ + J721S2_WKUP_IOPAD(0x074, PIN_OUTPUT, 0) /* (F28) WKUP_GPIO0_7.WKUP_UART0_RTSn */ + J721S2_WKUP_IOPAD(0x048, PIN_INPUT, 0) /* (D28) WKUP_UART0_RXD */ + J721S2_WKUP_IOPAD(0x04c, PIN_OUTPUT, 0) /* (D27) WKUP_UART0_TXD */ + >; + }; + + mcu_cpsw_pins_default: mcu-cpsw-default-pins { pinctrl-single,pins = < - J721S2_WKUP_IOPAD(0x094, PIN_INPUT, 0) /* (B22) MCU_RGMII1_RD0 */ - J721S2_WKUP_IOPAD(0x090, PIN_INPUT, 0) /* (B21) MCU_RGMII1_RD1 */ - J721S2_WKUP_IOPAD(0x08c, PIN_INPUT, 0) /* (C22) MCU_RGMII1_RD2 */ - J721S2_WKUP_IOPAD(0x088, PIN_INPUT, 0) /* (D23) MCU_RGMII1_RD3 */ - J721S2_WKUP_IOPAD(0x084, PIN_INPUT, 0) /* (D22) MCU_RGMII1_RXC */ - J721S2_WKUP_IOPAD(0x06c, PIN_INPUT, 0) /* (E23) MCU_RGMII1_RX_CTL */ - J721S2_WKUP_IOPAD(0x07c, PIN_OUTPUT, 0) /* (F23) MCU_RGMII1_TD0 */ - J721S2_WKUP_IOPAD(0x078, PIN_OUTPUT, 0) /* (G22) MCU_RGMII1_TD1 */ - J721S2_WKUP_IOPAD(0x074, PIN_OUTPUT, 0) /* (E21) MCU_RGMII1_TD2 */ - J721S2_WKUP_IOPAD(0x070, PIN_OUTPUT, 0) /* (E22) MCU_RGMII1_TD3 */ - J721S2_WKUP_IOPAD(0x080, PIN_OUTPUT, 0) /* (F21) MCU_RGMII1_TXC */ - J721S2_WKUP_IOPAD(0x068, PIN_OUTPUT, 0) /* (F22) MCU_RGMII1_TX_CTL */ + J721S2_WKUP_IOPAD(0x02C, PIN_INPUT, 0) /* (B22) MCU_RGMII1_RD0 */ + J721S2_WKUP_IOPAD(0x028, PIN_INPUT, 0) /* (B21) MCU_RGMII1_RD1 */ + J721S2_WKUP_IOPAD(0x024, PIN_INPUT, 0) /* (C22) MCU_RGMII1_RD2 */ + J721S2_WKUP_IOPAD(0x020, PIN_INPUT, 0) /* (D23) MCU_RGMII1_RD3 */ + J721S2_WKUP_IOPAD(0x01C, PIN_INPUT, 0) /* (D22) MCU_RGMII1_RXC */ + J721S2_WKUP_IOPAD(0x004, PIN_INPUT, 0) /* (E23) MCU_RGMII1_RX_CTL */ + J721S2_WKUP_IOPAD(0x014, PIN_OUTPUT, 0) /* (F23) MCU_RGMII1_TD0 */ + J721S2_WKUP_IOPAD(0x010, PIN_OUTPUT, 0) /* (G22) MCU_RGMII1_TD1 */ + J721S2_WKUP_IOPAD(0x00C, PIN_OUTPUT, 0) /* (E21) MCU_RGMII1_TD2 */ + J721S2_WKUP_IOPAD(0x008, PIN_OUTPUT, 0) /* (E22) MCU_RGMII1_TD3 */ + J721S2_WKUP_IOPAD(0x018, PIN_OUTPUT, 0) /* (F21) MCU_RGMII1_TXC */ + J721S2_WKUP_IOPAD(0x000, PIN_OUTPUT, 0) /* (F22) MCU_RGMII1_TX_CTL */ >; }; - mcu_mdio_pins_default: mcu-mdio-pins-default { + mcu_mdio_pins_default: mcu-mdio-default-pins { pinctrl-single,pins = < - J721S2_WKUP_IOPAD(0x09c, PIN_OUTPUT, 0) /* (A21) MCU_MDIO0_MDC */ - J721S2_WKUP_IOPAD(0x098, PIN_INPUT, 0) /* (A22) MCU_MDIO0_MDIO */ + J721S2_WKUP_IOPAD(0x034, PIN_OUTPUT, 0) /* (A21) MCU_MDIO0_MDC */ + J721S2_WKUP_IOPAD(0x030, PIN_INPUT, 0) /* (A22) MCU_MDIO0_MDIO */ >; }; - mcu_mcan0_pins_default: mcu-mcan0-pins-default { + mcu_mcan0_pins_default: mcu-mcan0-default-pins { pinctrl-single,pins = < - J721S2_WKUP_IOPAD(0x0bc, PIN_INPUT, 0) /* (E28) MCU_MCAN0_RX */ - J721S2_WKUP_IOPAD(0x0b8, PIN_OUTPUT, 0) /* (E27) MCU_MCAN0_TX */ + J721S2_WKUP_IOPAD(0x054, PIN_INPUT, 0) /* (E28) MCU_MCAN0_RX */ + J721S2_WKUP_IOPAD(0x050, PIN_OUTPUT, 0) /* (E27) MCU_MCAN0_TX */ >; }; - mcu_mcan1_pins_default: mcu-mcan1-pins-default { + mcu_mcan1_pins_default: mcu-mcan1-default-pins { pinctrl-single,pins = < - J721S2_WKUP_IOPAD(0x0d4, PIN_INPUT, 0) /* (F26) WKUP_GPIO0_5.MCU_MCAN1_RX */ - J721S2_WKUP_IOPAD(0x0d0, PIN_OUTPUT, 0) /* (C23) WKUP_GPIO0_4.MCU_MCAN1_TX*/ + J721S2_WKUP_IOPAD(0x06C, PIN_INPUT, 0) /* (F26) WKUP_GPIO0_5.MCU_MCAN1_RX */ + J721S2_WKUP_IOPAD(0x068, PIN_OUTPUT, 0) /* (C23) WKUP_GPIO0_4.MCU_MCAN1_TX*/ >; }; - mcu_i2c1_pins_default: mcu-i2c1-pins-default { + mcu_i2c0_pins_default: mcu-i2c0-default-pins { pinctrl-single,pins = < - J721S2_WKUP_IOPAD(0x0e0, PIN_INPUT, 0) /* (F24) WKUP_GPIO0_8.MCU_I2C1_SCL */ - J721S2_WKUP_IOPAD(0x0e4, PIN_INPUT, 0) /* (H26) WKUP_GPIO0_9.MCU_I2C1_SDA */ + J721S2_WKUP_IOPAD(0x0a0, PIN_INPUT, 0) /* (G24) MCU_I2C0_SCL */ + J721S2_WKUP_IOPAD(0x0a4, PIN_INPUT, 0) /* (J25) MCU_I2C0_SDA */ + >; + }; + + mcu_i2c1_pins_default: mcu-i2c1-default-pins { + pinctrl-single,pins = < + J721S2_WKUP_IOPAD(0x078, PIN_INPUT, 0) /* (F24) WKUP_GPIO0_8.MCU_I2C1_SCL */ + J721S2_WKUP_IOPAD(0x07c, PIN_INPUT, 0) /* (H26) WKUP_GPIO0_9.MCU_I2C1_SDA */ + >; + }; + + mcu_uart0_pins_default: mcu-uart0-default-pins { + pinctrl-single,pins = < + J721S2_WKUP_IOPAD(0x08c, PIN_INPUT, 0) /* (C24) WKUP_GPIO0_13.MCU_UART0_RXD */ + J721S2_WKUP_IOPAD(0x088, PIN_OUTPUT, 0) /* (C25) WKUP_GPIO0_12.MCU_UART0_TXD */ + >; + }; + + mcu_rpi_header_gpio0_pins0_default: mcu-rpi-header-gpio0-pins0-default { + pinctrl-single,pins = < + J721S2_WKUP_IOPAD(0x118, PIN_INPUT, 7) /* (G25) WKUP_GPIO0_66 */ + J721S2_WKUP_IOPAD(0x05C, PIN_INPUT, 7) /* (E24) MCU_SPI1_D0.WKUP_GPIO0_1 */ + J721S2_WKUP_IOPAD(0x060, PIN_INPUT, 7) /* (C28) MCU_SPI1_D1.WKUP_GPIO0_2 */ + J721S2_WKUP_IOPAD(0x058, PIN_INPUT, 7) /* (D26) MCU_SPI1_CLK.WKUP_GPIO0_0 */ + J721S2_WKUP_IOPAD(0x094, PIN_INPUT, 7) /* (D25) MCU_SPI1_CS2.WKUP_GPIO0_15*/ + J721S2_WKUP_IOPAD(0x0B8, PIN_INPUT, 7) /* (G27) WKUP_GPIO0_56 */ + J721S2_WKUP_IOPAD(0x114, PIN_INPUT, 7) /* (J26) WKUP_GPIO0_57 */ + J721S2_WKUP_IOPAD(0x11C, PIN_INPUT, 7) /* (J27) WKUP_GPIO0_67 */ + J721S2_WKUP_IOPAD(0x064, PIN_INPUT, 7) /* (C27) MCU_SPI1_CS0.WKUP_GPIO0_3 */ >; }; }; +&wkup_pmx3 { + mcu_rpi_header_gpio0_pins1_default: mcu-rpi-header-gpio0-pins1-default { + pinctrl-single,pins = < + J721S2_WKUP_IOPAD(0x000, PIN_INPUT, 7) /* (K26) WKUP_GPIO0_49 */ + >; + }; +}; + +&main_gpio0 { + pinctrl-names = "default"; + pinctrl-0 = <&rpi_header_gpio0_pins_default>; +}; + &main_gpio2 { status = "disabled"; }; @@ -235,7 +313,8 @@ }; &wkup_gpio0 { - status = "disabled"; + pinctrl-names = "default"; + pinctrl-0 = <&mcu_rpi_header_gpio0_pins0_default>, <&mcu_rpi_header_gpio0_pins1_default>; }; &wkup_gpio1 { @@ -244,6 +323,14 @@ &wkup_uart0 { status = "reserved"; + pinctrl-names = "default"; + pinctrl-0 = <&wkup_uart0_pins_default>; +}; + +&mcu_uart0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&mcu_uart0_pins_default>; }; &main_uart8 { @@ -271,6 +358,20 @@ }; }; +&main_i2c4 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&main_i2c4_pins_default>; + clock-frequency = <400000>; +}; + +&mcu_i2c0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&mcu_i2c0_pins_default>; + clock-frequency = <400000>; +}; + &main_sdhci0 { /* Unused */ status = "disabled"; @@ -287,7 +388,7 @@ &mcu_cpsw { pinctrl-names = "default"; - pinctrl-0 = <&mcu_cpsw_pins_default &mcu_mdio_pins_default>; + pinctrl-0 = <&mcu_cpsw_pins_default>, <&mcu_mdio_pins_default>; }; &davinci_mdio { diff --git a/arch/arm64/boot/dts/ti/k3-am68-sk-som.dtsi b/arch/arm64/boot/dts/ti/k3-am68-sk-som.dtsi index e92431250729a82ff34ded25ae82121d3cc13258..6c9139f73201a9cb780ef0ca3ae5c3b9cb2d8e29 100644 --- a/arch/arm64/boot/dts/ti/k3-am68-sk-som.dtsi +++ b/arch/arm64/boot/dts/ti/k3-am68-sk-som.dtsi @@ -27,3 +27,25 @@ }; }; }; + +&wkup_pmx2 { + wkup_i2c0_pins_default: wkup-i2c0-default-pins { + pinctrl-single,pins = < + J721S2_WKUP_IOPAD(0x098, PIN_INPUT, 0) /* (H24) WKUP_I2C0_SCL */ + J721S2_WKUP_IOPAD(0x09c, PIN_INPUT, 0) /* (H27) WKUP_I2C0_SDA */ + >; + }; +}; + +&wkup_i2c0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&wkup_i2c0_pins_default>; + clock-frequency = <400000>; + + eeprom@51 { + /* AT24C512C-MAHM-T */ + compatible = "atmel,24c512"; + reg = <0x51>; + }; +}; diff --git a/arch/arm64/boot/dts/ti/k3-am69-sk.dts b/arch/arm64/boot/dts/ti/k3-am69-sk.dts index bc49ba534790efad551b95d324ea915cc8ef8cc1..d282c2c633c1cd2c6b3e907074195438bce9c1a7 100644 --- a/arch/arm64/boot/dts/ti/k3-am69-sk.dts +++ b/arch/arm64/boot/dts/ti/k3-am69-sk.dts @@ -21,9 +21,14 @@ }; aliases { + serial0 = &wkup_uart0; + serial1 = &mcu_uart0; serial2 = &main_uart8; + mmc0 = &main_sdhci0; mmc1 = &main_sdhci1; - i2c0 = &main_i2c0; + i2c0 = &wkup_i2c0; + i2c3 = &main_i2c0; + ethernet0 = &mcu_cpsw_port1; }; memory@80000000 { @@ -105,21 +110,21 @@ }; &main_pmx0 { - main_uart8_pins_default: main-uart8-pins-default { + main_uart8_pins_default: main-uart8-default-pins { pinctrl-single,pins = < J784S4_IOPAD(0x0d0, PIN_INPUT, 11) /* (AP38) SPI0_CS1.UART8_RXD */ J784S4_IOPAD(0x0d4, PIN_OUTPUT, 11) /* (AN38) SPI0_CLK.UART8_TXD */ >; }; - main_i2c0_pins_default: main-i2c0-pins-default { + main_i2c0_pins_default: main-i2c0-default-pins { pinctrl-single,pins = < J784S4_IOPAD(0x0e0, PIN_INPUT_PULLUP, 0) /* (AN36) I2C0_SCL */ J784S4_IOPAD(0x0e4, PIN_INPUT_PULLUP, 0) /* (AP37) I2C0_SDA */ >; }; - main_mmc1_pins_default: main-mmc1-pins-default { + main_mmc1_pins_default: main-mmc1-default-pins { pinctrl-single,pins = < J784S4_IOPAD(0x104, PIN_INPUT, 0) /* (AB38) MMC1_CLK */ J784S4_IOPAD(0x108, PIN_INPUT, 0) /* (AB36) MMC1_CMD */ @@ -132,11 +137,147 @@ >; }; - vdd_sd_dv_pins_default: vdd-sd-dv-pins-default { + vdd_sd_dv_pins_default: vdd-sd-dv-default-pins { pinctrl-single,pins = < J784S4_IOPAD(0x0C4, PIN_INPUT, 7) /* (AD36) ECAP0_IN_APWM_OUT.GPIO0_49 */ >; }; + + rpi_header_gpio0_pins_default: rpi-header-gpio0-default-pins { + pinctrl-single,pins = < + J784S4_IOPAD(0x0BC, PIN_INPUT, 7) /* (AD33) MCASP1_AFSX.GPIO0_47 */ + J784S4_IOPAD(0x06C, PIN_INPUT, 7) /* (AJ37) MCASP4_AFSX.GPIO0_27 */ + J784S4_IOPAD(0x0B4, PIN_INPUT, 7) /* (AL34) MCASP1_AXR4.GPIO0_45 */ + J784S4_IOPAD(0x0C0, PIN_INPUT, 7) /* (AD38) MCASP1_AXR0.GPIO0_48 */ + J784S4_IOPAD(0x00C, PIN_INPUT, 7) /* (AF33) MCAN13_TX.GPIO0_3 */ + J784S4_IOPAD(0x0B8, PIN_INPUT, 7) /* (AC34) MCASP1_ACLKX.GPIO0_46 */ + J784S4_IOPAD(0x090, PIN_INPUT, 7) /* (AC35) MCASP0_AXR8.GPIO0_36 */ + J784S4_IOPAD(0x0A8, PIN_INPUT, 7) /* (AF34) MCASP0_AXR14.GPIO0_42 */ + J784S4_IOPAD(0x0A4, PIN_INPUT, 7) /* (AJ36) MCASP0_AXR13.GPIO0_41 */ + J784S4_IOPAD(0x034, PIN_INPUT, 7) /* (AJ34) PMIC_WAKE0n.GPIO0_13 */ + J784S4_IOPAD(0x0CC, PIN_INPUT, 7) /* (AM37) SPI0_CS0.GPIO0_51 */ + J784S4_IOPAD(0x08C, PIN_INPUT, 7) /* (AE35) MCASP0_AXR7.GPIO0_35 */ + J784S4_IOPAD(0x008, PIN_INPUT, 7) /* (AJ33) MCAN12_RX.GPIO0_2 */ + J784S4_IOPAD(0x004, PIN_INPUT, 7) /* (AG36) MCAN12_TX.GPIO0_1 */ + >; + }; +}; + +&wkup_pmx2 { + wkup_uart0_pins_default: wkup-uart0-default-pins { + pinctrl-single,pins = < + J721S2_WKUP_IOPAD(0x070, PIN_INPUT, 0) /* (L37) WKUP_GPIO0_6.WKUP_UART0_CTSn */ + J721S2_WKUP_IOPAD(0x074, PIN_INPUT, 0) /* (L36) WKUP_GPIO0_7.WKUP_UART0_RTSn */ + J721S2_WKUP_IOPAD(0x048, PIN_INPUT, 0) /* (K35) WKUP_UART0_RXD */ + J721S2_WKUP_IOPAD(0x04c, PIN_INPUT, 0) /* (K34) WKUP_UART0_TXD */ + >; + }; + + wkup_i2c0_pins_default: wkup-i2c0-default-pins { + pinctrl-single,pins = < + J721S2_WKUP_IOPAD(0x98, PIN_INPUT, 0) /* (N33) WKUP_I2C0_SCL */ + J721S2_WKUP_IOPAD(0x9c, PIN_INPUT, 0) /* (N35) WKUP_I2C0_SDA */ + >; + }; + + mcu_uart0_pins_default: mcu-uart0-default-pins { + pinctrl-single,pins = < + J784S4_WKUP_IOPAD(0x08c, PIN_INPUT, 0) /* (K38) WKUP_GPIO0_13.MCU_UART0_RXD */ + J784S4_WKUP_IOPAD(0x088, PIN_OUTPUT, 0) /* (J37) WKUP_GPIO0_12.MCU_UART0_TXD */ + >; + }; + + mcu_i2c0_pins_default: mcu-i2c0-default-pins { + pinctrl-single,pins = < + J784S4_WKUP_IOPAD(0x0a0, PIN_INPUT_PULLUP, 0) /* (M35) MCU_I2C0_SCL */ + J784S4_WKUP_IOPAD(0x0a4, PIN_INPUT_PULLUP, 0) /* (G34) MCU_I2C0_SDA */ + >; + }; + + mcu_cpsw_pins_default: mcu-cpsw-default-pins { + pinctrl-single,pins = < + J784S4_WKUP_IOPAD(0x02c, PIN_INPUT, 0) /* (A35) MCU_RGMII1_RD0 */ + J784S4_WKUP_IOPAD(0x028, PIN_INPUT, 0) /* (B36) MCU_RGMII1_RD1 */ + J784S4_WKUP_IOPAD(0x024, PIN_INPUT, 0) /* (C36) MCU_RGMII1_RD2 */ + J784S4_WKUP_IOPAD(0x020, PIN_INPUT, 0) /* (D36) MCU_RGMII1_RD3 */ + J784S4_WKUP_IOPAD(0x01c, PIN_INPUT, 0) /* (B37) MCU_RGMII1_RXC */ + J784S4_WKUP_IOPAD(0x004, PIN_INPUT, 0) /* (C37) MCU_RGMII1_RX_CTL */ + J784S4_WKUP_IOPAD(0x014, PIN_OUTPUT, 0) /* (D37) MCU_RGMII1_TD0 */ + J784S4_WKUP_IOPAD(0x010, PIN_OUTPUT, 0) /* (D38) MCU_RGMII1_TD1 */ + J784S4_WKUP_IOPAD(0x00c, PIN_OUTPUT, 0) /* (E37) MCU_RGMII1_TD2 */ + J784S4_WKUP_IOPAD(0x008, PIN_OUTPUT, 0) /* (E38) MCU_RGMII1_TD3 */ + J784S4_WKUP_IOPAD(0x018, PIN_OUTPUT, 0) /* (E36) MCU_RGMII1_TXC */ + J784S4_WKUP_IOPAD(0x000, PIN_OUTPUT, 0) /* (C38) MCU_RGMII1_TX_CTL */ + >; + }; + + mcu_mdio_pins_default: mcu-mdio-default-pins { + pinctrl-single,pins = < + J784S4_WKUP_IOPAD(0x034, PIN_OUTPUT, 0) /* (A36) MCU_MDIO0_MDC */ + J784S4_WKUP_IOPAD(0x030, PIN_INPUT, 0) /* (B35) MCU_MDIO0_MDIO */ + >; + }; + + mcu_rpi_hdr1_gpio0_pins_default: mcu-rpi-hdr1-gpio0-default-pins { + pinctrl-single,pins = < + J784S4_WKUP_IOPAD(0x118, PIN_INPUT, 7) /* (N34) WKUP_GPIO0_66 */ + J784S4_WKUP_IOPAD(0x05c, PIN_INPUT, 7) /* (J34) WKUP_GPIO0_1 */ + J784S4_WKUP_IOPAD(0x060, PIN_INPUT, 7) /* (J35) WKUP_GPIO0_2 */ + J784S4_WKUP_IOPAD(0x058, PIN_INPUT, 7) /* (H38) WKUP_GPIO0_0 */ + J784S4_WKUP_IOPAD(0x0b8, PIN_INPUT, 7) /* (M37) WKUP_GPIO0_56 */ + J784S4_WKUP_IOPAD(0x114, PIN_INPUT, 7) /* (M36) WKUP_GPIO0_57 */ + J784S4_WKUP_IOPAD(0x094, PIN_INPUT, 7) /* (K37) WKUP_GPIO0_15 */ + J784S4_WKUP_IOPAD(0x064, PIN_INPUT, 7) /* (J36) WKUP_GPIO0_3 */ + J784S4_WKUP_IOPAD(0x11c, PIN_INPUT, 7) /* (M34) WKUP_GPIO0_67 */ + >; + }; +}; + +&wkup_pmx3 { + mcu_rpi_hdr2_gpio0_pins_default: mcu-rpi-hdr2-gpio0-default-pins { + pinctrl-single,pins = < + J784S4_WKUP_IOPAD(0x0, PIN_INPUT, 7) /* (M33) WKUP_GPIO0_49 */ + >; + }; +}; + +&wkup_uart0 { + /* Firmware usage */ + status = "reserved"; + pinctrl-names = "default"; + pinctrl-0 = <&wkup_uart0_pins_default>; +}; + +&wkup_i2c0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&wkup_i2c0_pins_default>; + clock-frequency = <400000>; + + eeprom@51 { + /* AT24C512C-MAHM-T */ + compatible = "atmel,24c512"; + reg = <0x51>; + }; +}; + +&wkup_gpio0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&mcu_rpi_hdr1_gpio0_pins_default>, <&mcu_rpi_hdr2_gpio0_pins_default>; +}; + +&mcu_uart0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&mcu_uart0_pins_default>; +}; + +&mcu_i2c0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&mcu_i2c0_pins_default>; + clock-frequency = <400000>; }; &main_uart8 { @@ -165,6 +306,14 @@ }; }; +&main_sdhci0 { + /* eMMC */ + status = "okay"; + non-removable; + ti,driver-strength-ohm = <50>; + disable-wp; +}; + &main_sdhci1 { /* SD card */ status = "okay"; @@ -177,4 +326,27 @@ &main_gpio0 { status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&rpi_header_gpio0_pins_default>; +}; + +&mcu_cpsw { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&mcu_cpsw_pins_default>, <&mcu_mdio_pins_default>; +}; + +&davinci_mdio { + mcu_phy0: ethernet-phy@0 { + reg = <0>; + ti,rx-internal-delay = ; + ti,fifo-depth = ; + ti,min-output-impedance; + }; +}; + +&mcu_cpsw_port1 { + status = "okay"; + phy-mode = "rgmii-rxid"; + phy-handle = <&mcu_phy0>; }; diff --git a/arch/arm64/boot/dts/ti/k3-j7200-common-proc-board.dts b/arch/arm64/boot/dts/ti/k3-j7200-common-proc-board.dts index 0d39d6b8cc0ca78d0d790280b4350ce368728175..3cf288128c3f4a0c97ce8a2b3f44e2b5f6ad44c8 100644 --- a/arch/arm64/boot/dts/ti/k3-j7200-common-proc-board.dts +++ b/arch/arm64/boot/dts/ti/k3-j7200-common-proc-board.dts @@ -15,9 +15,18 @@ compatible = "ti,j7200-evm", "ti,j7200"; model = "Texas Instruments J7200 EVM"; + aliases { + serial0 = &wkup_uart0; + serial1 = &mcu_uart0; + serial2 = &main_uart0; + serial3 = &main_uart1; + serial5 = &main_uart3; + mmc0 = &main_sdhci0; + mmc1 = &main_sdhci1; + }; + chosen { stdout-path = "serial2:115200n8"; - bootargs = "console=ttyS2,115200n8 earlycon=ns16550a,mmio32,0x02800000"; }; evm_12v0: fixedregulator-evm12v0 { @@ -80,48 +89,88 @@ }; }; +&wkup_pmx0 { + mcu_uart0_pins_default: mcu-uart0-default-pins { + pinctrl-single,pins = < + J721E_WKUP_IOPAD(0xf4, PIN_INPUT, 0) /* (D20) MCU_UART0_RXD */ + J721E_WKUP_IOPAD(0xf0, PIN_OUTPUT, 0) /* (D19) MCU_UART0_TXD */ + J721E_WKUP_IOPAD(0xf8, PIN_INPUT, 0) /* (E20) MCU_UART0_CTSn */ + J721E_WKUP_IOPAD(0xfc, PIN_OUTPUT, 0) /* (E21) MCU_UART0_RTSn */ + >; + }; + + wkup_uart0_pins_default: wkup-uart0-default-pins { + pinctrl-single,pins = < + J721E_WKUP_IOPAD(0xb0, PIN_INPUT, 0) /* (B14) WKUP_UART0_RXD */ + J721E_WKUP_IOPAD(0xb4, PIN_OUTPUT, 0) /* (A14) WKUP_UART0_TXD */ + >; + }; +}; + &wkup_pmx2 { - mcu_cpsw_pins_default: mcu-cpsw-pins-default { + mcu_cpsw_pins_default: mcu-cpsw-default-pins { pinctrl-single,pins = < - J721E_WKUP_IOPAD(0x0068, PIN_OUTPUT, 0) /* MCU_RGMII1_TX_CTL */ - J721E_WKUP_IOPAD(0x006c, PIN_INPUT, 0) /* MCU_RGMII1_RX_CTL */ - J721E_WKUP_IOPAD(0x0070, PIN_OUTPUT, 0) /* MCU_RGMII1_TD3 */ - J721E_WKUP_IOPAD(0x0074, PIN_OUTPUT, 0) /* MCU_RGMII1_TD2 */ - J721E_WKUP_IOPAD(0x0078, PIN_OUTPUT, 0) /* MCU_RGMII1_TD1 */ - J721E_WKUP_IOPAD(0x007c, PIN_OUTPUT, 0) /* MCU_RGMII1_TD0 */ - J721E_WKUP_IOPAD(0x0088, PIN_INPUT, 0) /* MCU_RGMII1_RD3 */ - J721E_WKUP_IOPAD(0x008c, PIN_INPUT, 0) /* MCU_RGMII1_RD2 */ - J721E_WKUP_IOPAD(0x0090, PIN_INPUT, 0) /* MCU_RGMII1_RD1 */ - J721E_WKUP_IOPAD(0x0094, PIN_INPUT, 0) /* MCU_RGMII1_RD0 */ - J721E_WKUP_IOPAD(0x0080, PIN_OUTPUT, 0) /* MCU_RGMII1_TXC */ - J721E_WKUP_IOPAD(0x0084, PIN_INPUT, 0) /* MCU_RGMII1_RXC */ + J721E_WKUP_IOPAD(0x0000, PIN_OUTPUT, 0) /* MCU_RGMII1_TX_CTL */ + J721E_WKUP_IOPAD(0x0004, PIN_INPUT, 0) /* MCU_RGMII1_RX_CTL */ + J721E_WKUP_IOPAD(0x0008, PIN_OUTPUT, 0) /* MCU_RGMII1_TD3 */ + J721E_WKUP_IOPAD(0x000c, PIN_OUTPUT, 0) /* MCU_RGMII1_TD2 */ + J721E_WKUP_IOPAD(0x0010, PIN_OUTPUT, 0) /* MCU_RGMII1_TD1 */ + J721E_WKUP_IOPAD(0x0014, PIN_OUTPUT, 0) /* MCU_RGMII1_TD0 */ + J721E_WKUP_IOPAD(0x0020, PIN_INPUT, 0) /* MCU_RGMII1_RD3 */ + J721E_WKUP_IOPAD(0x0024, PIN_INPUT, 0) /* MCU_RGMII1_RD2 */ + J721E_WKUP_IOPAD(0x0028, PIN_INPUT, 0) /* MCU_RGMII1_RD1 */ + J721E_WKUP_IOPAD(0x002c, PIN_INPUT, 0) /* MCU_RGMII1_RD0 */ + J721E_WKUP_IOPAD(0x0018, PIN_OUTPUT, 0) /* MCU_RGMII1_TXC */ + J721E_WKUP_IOPAD(0x001c, PIN_INPUT, 0) /* MCU_RGMII1_RXC */ >; }; - mcu_mdio_pins_default: mcu-mdio1-pins-default { + wkup_gpio_pins_default: wkup-gpio-default-pins { pinctrl-single,pins = < - J721E_WKUP_IOPAD(0x009c, PIN_OUTPUT, 0) /* (L1) MCU_MDIO0_MDC */ - J721E_WKUP_IOPAD(0x0098, PIN_INPUT, 0) /* (L4) MCU_MDIO0_MDIO */ + J721E_WKUP_IOPAD(0x70, PIN_INPUT, 7) /* (C14) WKUP_GPIO0_6 */ + >; + }; + + mcu_mdio_pins_default: mcu-mdio1-default-pins { + pinctrl-single,pins = < + J721E_WKUP_IOPAD(0x0034, PIN_OUTPUT, 0) /* (L1) MCU_MDIO0_MDC */ + J721E_WKUP_IOPAD(0x0030, PIN_INPUT, 0) /* (L4) MCU_MDIO0_MDIO */ >; }; }; &main_pmx0 { - main_i2c0_pins_default: main-i2c0-pins-default { + main_uart0_pins_default: main-uart0-default-pins { pinctrl-single,pins = < - J721E_IOPAD(0xd4, PIN_INPUT_PULLUP, 0) /* (V3) I2C0_SCL */ - J721E_IOPAD(0xd8, PIN_INPUT_PULLUP, 0) /* (W2) I2C0_SDA */ + J721E_IOPAD(0xb0, PIN_INPUT, 0) /* (T16) UART0_RXD */ + J721E_IOPAD(0xb4, PIN_OUTPUT, 0) /* (T17) UART0_TXD */ + J721E_IOPAD(0xc0, PIN_INPUT, 2) /* (W3) SPI0_CS0.UART0_CTSn */ + J721E_IOPAD(0xc4, PIN_OUTPUT, 2) /* (U5) SPI0_CS1.UART0_RTSn */ >; }; - main_i2c1_pins_default: main-i2c1-pins-default { + main_uart1_pins_default: main-uart1-default-pins { + pinctrl-single,pins = < + J721E_IOPAD(0xb8, PIN_INPUT, 0) /* (T18) UART1_RXD */ + J721E_IOPAD(0xbc, PIN_INPUT, 0) /* (T20) UART1_TXD */ + >; + }; + + main_uart3_pins_default: main-uart3-default-pins { + pinctrl-single,pins = < + J721E_IOPAD(0x60, PIN_INPUT, 11) /* (T15) MCAN8_TX.UART3_CTSn */ + J721E_IOPAD(0x30, PIN_INPUT, 11) /* (Y18) MCAN2_TX.UART3_RXD */ + >; + }; + + main_i2c1_pins_default: main-i2c1-default-pins { pinctrl-single,pins = < J721E_IOPAD(0xdc, PIN_INPUT_PULLUP, 3) /* (U3) ECAP0_IN_APWM_OUT.I2C1_SCL */ J721E_IOPAD(0xe0, PIN_INPUT_PULLUP, 3) /* (T3) EXT_REFCLK1.I2C1_SDA */ >; }; - main_mmc1_pins_default: main-mmc1-pins-default { + main_mmc1_pins_default: main-mmc1-default-pins { pinctrl-single,pins = < J721E_IOPAD(0x104, PIN_INPUT, 0) /* (M20) MMC1_CMD */ J721E_IOPAD(0x100, PIN_INPUT, 0) /* (P21) MMC1_CLK */ @@ -134,7 +183,7 @@ >; }; - vdd_sd_dv_pins_default: vdd-sd-dv-pins-default { + vdd_sd_dv_pins_default: vdd-sd-dv-default-pins { pinctrl-single,pins = < J721E_IOPAD(0xd0, PIN_OUTPUT, 7) /* (T5) SPI0_D1.GPIO0_55 */ >; @@ -142,7 +191,7 @@ }; &main_pmx1 { - main_usbss0_pins_default: main-usbss0-pins-default { + main_usbss0_pins_default: main-usbss0-default-pins { pinctrl-single,pins = < J721E_IOPAD(0x04, PIN_OUTPUT, 0) /* (T4) USB0_DRVVBUS */ >; @@ -152,22 +201,30 @@ &wkup_uart0 { /* Wakeup UART is used by System firmware */ status = "reserved"; + pinctrl-names = "default"; + pinctrl-0 = <&wkup_uart0_pins_default>; }; &mcu_uart0 { status = "okay"; - /* Default pinmux */ + pinctrl-names = "default"; + pinctrl-0 = <&mcu_uart0_pins_default>; + clock-frequency = <96000000>; }; &main_uart0 { status = "okay"; /* Shared with ATF on this platform */ power-domains = <&k3_pds 146 TI_SCI_PD_SHARED>; + pinctrl-names = "default"; + pinctrl-0 = <&main_uart0_pins_default>; }; &main_uart1 { status = "okay"; /* Default pinmux */ + pinctrl-names = "default"; + pinctrl-0 = <&main_uart1_pins_default>; }; &main_uart2 { @@ -175,6 +232,13 @@ status = "reserved"; }; +&main_uart3 { + /* Shared with MCAN Interface */ + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&main_uart3_pins_default>; +}; + &main_gpio2 { status = "disabled"; }; @@ -187,13 +251,18 @@ status = "disabled"; }; +&wkup_gpio0 { + pinctrl-names = "default"; + pinctrl-0 = <&wkup_gpio_pins_default>; +}; + &wkup_gpio1 { status = "disabled"; }; &mcu_cpsw { pinctrl-names = "default"; - pinctrl-0 = <&mcu_cpsw_pins_default &mcu_mdio_pins_default>; + pinctrl-0 = <&mcu_cpsw_pins_default>, <&mcu_mdio_pins_default>; }; &davinci_mdio { diff --git a/arch/arm64/boot/dts/ti/k3-j7200-evm-quad-port-eth-exp.dtso b/arch/arm64/boot/dts/ti/k3-j7200-evm-quad-port-eth-exp.dtso index 31b932eebc0a92c37937a5ed615daa92e78a778d..34a0747cbe6918db347187761d00347373eedb2b 100644 --- a/arch/arm64/boot/dts/ti/k3-j7200-evm-quad-port-eth-exp.dtso +++ b/arch/arm64/boot/dts/ti/k3-j7200-evm-quad-port-eth-exp.dtso @@ -92,7 +92,7 @@ }; &main_pmx0 { - mdio0_pins_default: mdio0-pins-default { + mdio0_pins_default: mdio0-default-pins { pinctrl-single,pins = < J721E_IOPAD(0x00a8, PIN_OUTPUT, 5) /* (W19) UART8_TXD.MDIO0_MDC */ J721E_IOPAD(0x00a4, PIN_INPUT, 5) /* (W14) UART8_RXD.MDIO0_MDIO */ diff --git a/arch/arm64/boot/dts/ti/k3-j7200-main.dtsi b/arch/arm64/boot/dts/ti/k3-j7200-main.dtsi index ef352e32f19d2223052d77a8741db28c1d810e35..ac62bbc1660d51425b3b8296b285a69788e19b55 100644 --- a/arch/arm64/boot/dts/ti/k3-j7200-main.dtsi +++ b/arch/arm64/boot/dts/ti/k3-j7200-main.dtsi @@ -392,6 +392,24 @@ }; }; + /* TIMERIO pad input CTRLMMR_TIMER*_CTRL registers */ + main_timerio_input: pinctrl@104200 { + compatible = "pinctrl-single"; + reg = <0x0 0x104200 0x0 0x50>; + #pinctrl-cells = <1>; + pinctrl-single,register-width = <32>; + pinctrl-single,function-mask = <0x000001ff>; + }; + + /* TIMERIO pad output CTCTRLMMR_TIMERIO*_CTRL registers */ + main_timerio_output: pinctrl@104280 { + compatible = "pinctrl-single"; + reg = <0x0 0x104280 0x0 0x20>; + #pinctrl-cells = <1>; + pinctrl-single,register-width = <32>; + pinctrl-single,function-mask = <0x0000001f>; + }; + main_pmx0: pinctrl@11c000 { compatible = "pinctrl-single"; /* Proxy 0 addressing */ @@ -971,6 +989,246 @@ assigned-clock-parents = <&k3_clks 253 5>; }; + main_timer0: timer@2400000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x2400000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 49 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 49 1>; + assigned-clock-parents = <&k3_clks 49 2>; + power-domains = <&k3_pds 49 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer1: timer@2410000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x2410000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 50 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 50 1>, <&k3_clks 313 0>; + assigned-clock-parents = <&k3_clks 50 2>, <&k3_clks 313 1>; + power-domains = <&k3_pds 50 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer2: timer@2420000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x2420000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 51 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 51 1>; + assigned-clock-parents = <&k3_clks 51 2>; + power-domains = <&k3_pds 49 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer3: timer@2430000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x2430000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 52 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 52 1>, <&k3_clks 314 0>; + assigned-clock-parents = <&k3_clks 52 2>, <&k3_clks 314 1>; + power-domains = <&k3_pds 52 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer4: timer@2440000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x2440000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 53 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 53 1>; + assigned-clock-parents = <&k3_clks 53 2>; + power-domains = <&k3_pds 53 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer5: timer@2450000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x2450000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 54 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 54 1>, <&k3_clks 315 0>; + assigned-clock-parents = <&k3_clks 54 2>, <&k3_clks 315 1>; + power-domains = <&k3_pds 54 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer6: timer@2460000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x2460000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 55 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 55 1>; + assigned-clock-parents = <&k3_clks 55 2>; + power-domains = <&k3_pds 55 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer7: timer@2470000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x2470000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 57 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 57 1>, <&k3_clks 316 0>; + assigned-clock-parents = <&k3_clks 57 2>, <&k3_clks 316 1>; + power-domains = <&k3_pds 57 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer8: timer@2480000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x2480000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 58 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 58 1>; + assigned-clock-parents = <&k3_clks 58 2>; + power-domains = <&k3_pds 58 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer9: timer@2490000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x2490000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 59 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 59 1>, <&k3_clks 317 0>; + assigned-clock-parents = <&k3_clks 59 2>, <&k3_clks 317 1>; + power-domains = <&k3_pds 59 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer10: timer@24a0000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x24a0000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 60 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 60 1>; + assigned-clock-parents = <&k3_clks 60 2>; + power-domains = <&k3_pds 60 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer11: timer@24b0000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x24b0000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 62 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 62 1>, <&k3_clks 318 0>; + assigned-clock-parents = <&k3_clks 62 2>, <&k3_clks 318 1>; + power-domains = <&k3_pds 62 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer12: timer@24c0000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x24c0000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 63 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 63 1>; + assigned-clock-parents = <&k3_clks 63 2>; + power-domains = <&k3_pds 63 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer13: timer@24d0000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x24d0000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 64 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 64 1>, <&k3_clks 319 0>; + assigned-clock-parents = <&k3_clks 64 2>, <&k3_clks 319 1>; + power-domains = <&k3_pds 64 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer14: timer@24e0000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x24e0000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 65 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 65 1>; + assigned-clock-parents = <&k3_clks 65 2>; + power-domains = <&k3_pds 65 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer15: timer@24f0000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x24f0000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 66 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 66 1>, <&k3_clks 320 0>; + assigned-clock-parents = <&k3_clks 66 2>, <&k3_clks 320 1>; + power-domains = <&k3_pds 66 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer16: timer@2500000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x2500000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 67 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 67 1>; + assigned-clock-parents = <&k3_clks 67 2>; + power-domains = <&k3_pds 67 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer17: timer@2510000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x2510000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 68 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 68 1>, <&k3_clks 321 0>; + assigned-clock-parents = <&k3_clks 68 2>, <&k3_clks 321 1>; + power-domains = <&k3_pds 68 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer18: timer@2520000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x2520000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 69 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 69 1>; + assigned-clock-parents = <&k3_clks 69 2>; + power-domains = <&k3_pds 69 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer19: timer@2530000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x2530000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 70 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 70 1>, <&k3_clks 322 0>; + assigned-clock-parents = <&k3_clks 70 2>, <&k3_clks 322 1>; + power-domains = <&k3_pds 70 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + main_r5fss0: r5fss@5c00000 { compatible = "ti,j7200-r5fss"; ti,cluster-mode = <1>; @@ -1010,4 +1268,10 @@ ti,loczrama = <1>; }; }; + + main_esm: esm@700000 { + compatible = "ti,j721e-esm"; + reg = <0x0 0x700000 0x0 0x1000>; + ti,esm-pins = <656>, <657>; + }; }; diff --git a/arch/arm64/boot/dts/ti/k3-j7200-mcu-wakeup.dtsi b/arch/arm64/boot/dts/ti/k3-j7200-mcu-wakeup.dtsi index 331b4e482e41cf71207088e378f8dcf22133d1e5..c5e4c41effd18c25e102082c41079b625fd6adba 100644 --- a/arch/arm64/boot/dts/ti/k3-j7200-mcu-wakeup.dtsi +++ b/arch/arm64/boot/dts/ti/k3-j7200-mcu-wakeup.dtsi @@ -34,6 +34,136 @@ }; }; + mcu_timer0: timer@40400000 { + status = "reserved"; + compatible = "ti,am654-timer"; + reg = <0x00 0x40400000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 35 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 35 1>; + assigned-clock-parents = <&k3_clks 35 2>; + power-domains = <&k3_pds 35 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + mcu_timer1: timer@40410000 { + status = "reserved"; + compatible = "ti,am654-timer"; + reg = <0x00 0x40410000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 71 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 71 1>, <&k3_clks 308 0>; + assigned-clock-parents = <&k3_clks 71 2>, <&k3_clks 308 1>; + power-domains = <&k3_pds 71 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + mcu_timer2: timer@40420000 { + status = "reserved"; + compatible = "ti,am654-timer"; + reg = <0x00 0x40420000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 72 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 72 1>; + assigned-clock-parents = <&k3_clks 72 2>; + power-domains = <&k3_pds 72 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + mcu_timer3: timer@40430000 { + status = "reserved"; + compatible = "ti,am654-timer"; + reg = <0x00 0x40430000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 73 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 73 1>, <&k3_clks 309 0>; + assigned-clock-parents = <&k3_clks 73 2>, <&k3_clks 309 1>; + power-domains = <&k3_pds 73 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + mcu_timer4: timer@40440000 { + status = "reserved"; + compatible = "ti,am654-timer"; + reg = <0x00 0x40440000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 74 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 74 1>; + assigned-clock-parents = <&k3_clks 74 2>; + power-domains = <&k3_pds 74 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + mcu_timer5: timer@40450000 { + status = "reserved"; + compatible = "ti,am654-timer"; + reg = <0x00 0x40450000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 75 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 75 1>, <&k3_clks 310 0>; + assigned-clock-parents = <&k3_clks 75 2>, <&k3_clks 310 1>; + power-domains = <&k3_pds 75 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + mcu_timer6: timer@40460000 { + status = "reserved"; + compatible = "ti,am654-timer"; + reg = <0x00 0x40460000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 76 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 76 1>; + assigned-clock-parents = <&k3_clks 76 2>; + power-domains = <&k3_pds 35 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + mcu_timer7: timer@40470000 { + status = "reserved"; + compatible = "ti,am654-timer"; + reg = <0x00 0x40470000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 77 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 77 1>, <&k3_clks 311 0>; + assigned-clock-parents = <&k3_clks 77 2>, <&k3_clks 311 1>; + power-domains = <&k3_pds 77 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + mcu_timer8: timer@40480000 { + status = "reserved"; + compatible = "ti,am654-timer"; + reg = <0x00 0x40480000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 78 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 78 1>; + assigned-clock-parents = <&k3_clks 78 2>; + power-domains = <&k3_pds 78 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + mcu_timer9: timer@40490000 { + status = "reserved"; + compatible = "ti,am654-timer"; + reg = <0x00 0x40490000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 79 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 79 1>, <&k3_clks 312 0>; + assigned-clock-parents = <&k3_clks 79 2>, <&k3_clks 312 1>; + power-domains = <&k3_pds 79 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + mcu_conf: syscon@40f00000 { compatible = "syscon", "simple-mfd"; reg = <0x00 0x40f00000 0x00 0x20000>; @@ -53,6 +183,26 @@ reg = <0x00 0x43000014 0x00 0x4>; }; + /* MCU_TIMERIO pad input CTRLMMR_MCU_TIMER*_CTRL registers */ + mcu_timerio_input: pinctrl@40f04200 { + compatible = "pinctrl-single"; + reg = <0x0 0x40f04200 0x0 0x28>; + #pinctrl-cells = <1>; + pinctrl-single,register-width = <32>; + pinctrl-single,function-mask = <0x0000000F>; + status = "reserved"; + }; + + /* MCU_TIMERIO pad output CTRLMMR_MCU_TIMERIO*_CTRL registers */ + mcu_timerio_output: pinctrl@40f04280 { + compatible = "pinctrl-single"; + reg = <0x0 0x40f04280 0x0 0x28>; + #pinctrl-cells = <1>; + pinctrl-single,register-width = <32>; + pinctrl-single,function-mask = <0x0000000F>; + status = "reserved"; + }; + wkup_pmx0: pinctrl@4301c000 { compatible = "pinctrl-single"; /* Proxy 0 addressing */ @@ -62,7 +212,7 @@ pinctrl-single,function-mask = <0xffffffff>; }; - wkup_pmx1: pinctrl@0x4301c038 { + wkup_pmx1: pinctrl@4301c038 { compatible = "pinctrl-single"; /* Proxy 0 addressing */ reg = <0x00 0x4301c038 0x00 0x8>; @@ -71,7 +221,7 @@ pinctrl-single,function-mask = <0xffffffff>; }; - wkup_pmx2: pinctrl@0x4301c068 { + wkup_pmx2: pinctrl@4301c068 { compatible = "pinctrl-single"; /* Proxy 0 addressing */ reg = <0x00 0x4301c068 0x00 0xec>; @@ -80,7 +230,7 @@ pinctrl-single,function-mask = <0xffffffff>; }; - wkup_pmx3: pinctrl@0x4301c174 { + wkup_pmx3: pinctrl@4301c174 { compatible = "pinctrl-single"; /* Proxy 0 addressing */ reg = <0x00 0x4301c174 0x00 0x20>; @@ -209,6 +359,21 @@ }; }; + secure_proxy_mcu: mailbox@2a480000 { + compatible = "ti,am654-secure-proxy"; + #mbox-cells = <1>; + reg-names = "target_data", "rt", "scfg"; + reg = <0x0 0x2a480000 0x0 0x80000>, + <0x0 0x2a380000 0x0 0x80000>, + <0x0 0x2a400000 0x0 0x80000>; + /* + * Marked Disabled: + * Node is incomplete as it is meant for bootloaders and + * firmware on non-MPU processors + */ + status = "disabled"; + }; + mcu_cpsw: ethernet@46000000 { compatible = "ti,j721e-cpsw-nuss"; #address-cells = <2>; @@ -459,4 +624,12 @@ status = "disabled"; /* Used by OP-TEE */ }; }; + + wkup_vtm0: temperature-sensor@42040000 { + compatible = "ti,j7200-vtm"; + reg = <0x00 0x42040000 0x00 0x350>, + <0x00 0x42050000 0x00 0x350>; + power-domains = <&k3_pds 154 TI_SCI_PD_EXCLUSIVE>; + #thermal-sensor-cells = <1>; + }; }; diff --git a/arch/arm64/boot/dts/ti/k3-j7200-som-p0.dtsi b/arch/arm64/boot/dts/ti/k3-j7200-som-p0.dtsi index fa44ed4c17d509690649c66dd98a35bffdd02ae9..b37f4f88ece4f6effa68b078f819bd9028793ae8 100644 --- a/arch/arm64/boot/dts/ti/k3-j7200-som-p0.dtsi +++ b/arch/arm64/boot/dts/ti/k3-j7200-som-p0.dtsi @@ -83,7 +83,7 @@ }; &wkup_pmx0 { - mcu_fss0_hpb0_pins_default: mcu-fss0-hpb0-pins-default { + mcu_fss0_hpb0_pins_default: mcu-fss0-hpb0-default-pins { pinctrl-single,pins = < J721E_WKUP_IOPAD(0x0, PIN_OUTPUT, 1) /* (B6) MCU_OSPI0_CLK.MCU_HYPERBUS0_CK */ J721E_WKUP_IOPAD(0x4, PIN_OUTPUT, 1) /* (C8) MCU_OSPI0_LBCLKO.MCU_HYPERBUS0_CKn */ @@ -101,7 +101,7 @@ >; }; - mcu_fss0_ospi0_pins_default: mcu-fss0-ospi0-pins-default { + mcu_fss0_ospi0_pins_default: mcu-fss0-ospi0-default-pins { pinctrl-single,pins = < J721E_WKUP_IOPAD(0x0000, PIN_OUTPUT, 0) /* MCU_OSPI0_CLK */ J721E_WKUP_IOPAD(0x002c, PIN_OUTPUT, 0) /* MCU_OSPI0_CSn0 */ @@ -118,8 +118,17 @@ }; }; +&wkup_pmx2 { + wkup_i2c0_pins_default: wkup-i2c0-default-pins { + pinctrl-single,pins = < + J721E_WKUP_IOPAD(0x98, PIN_INPUT_PULLUP, 0) /* (F20) WKUP_I2C0_SCL */ + J721E_WKUP_IOPAD(0x9c, PIN_INPUT_PULLUP, 0) /* (H21) WKUP_I2C0_SDA */ + >; + }; +}; + &main_pmx0 { - main_i2c0_pins_default: main-i2c0-pins-default { + main_i2c0_pins_default: main-i2c0-default-pins { pinctrl-single,pins = < J721E_IOPAD(0xd4, PIN_INPUT_PULLUP, 0) /* (V3) I2C0_SCL */ J721E_IOPAD(0xd8, PIN_INPUT_PULLUP, 0) /* (W2) I2C0_SDA */ @@ -140,6 +149,37 @@ flash@0,0 { compatible = "cypress,hyperflash", "cfi-flash"; reg = <0x00 0x00 0x4000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "hbmc.tiboot3"; + reg = <0x0 0x100000>; + }; + + partition@100000 { + label = "hbmc.tispl"; + reg = <0x100000 0x200000>; + }; + + partition@300000 { + label = "hbmc.u-boot"; + reg = <0x300000 0x400000>; + }; + + partition@700000 { + label = "hbmc.env"; + reg = <0x700000 0x40000>; + }; + + partition@800000 { + label = "hbmc.rootfs"; + reg = <0x800000 0x3800000>; + }; + }; }; }; @@ -174,25 +214,25 @@ }; &mcu_r5fss0_core0 { - mboxes = <&mailbox0_cluster0 &mbox_mcu_r5fss0_core0>; + mboxes = <&mailbox0_cluster0>, <&mbox_mcu_r5fss0_core0>; memory-region = <&mcu_r5fss0_core0_dma_memory_region>, <&mcu_r5fss0_core0_memory_region>; }; &mcu_r5fss0_core1 { - mboxes = <&mailbox0_cluster0 &mbox_mcu_r5fss0_core1>; + mboxes = <&mailbox0_cluster0>, <&mbox_mcu_r5fss0_core1>; memory-region = <&mcu_r5fss0_core1_dma_memory_region>, <&mcu_r5fss0_core1_memory_region>; }; &main_r5fss0_core0 { - mboxes = <&mailbox0_cluster1 &mbox_main_r5fss0_core0>; + mboxes = <&mailbox0_cluster1>, <&mbox_main_r5fss0_core0>; memory-region = <&main_r5fss0_core0_dma_memory_region>, <&main_r5fss0_core0_memory_region>; }; &main_r5fss0_core1 { - mboxes = <&mailbox0_cluster1 &mbox_main_r5fss0_core1>; + mboxes = <&mailbox0_cluster1>, <&mbox_main_r5fss0_core1>; memory-region = <&main_r5fss0_core1_dma_memory_region>, <&main_r5fss0_core1_memory_region>; }; @@ -214,6 +254,18 @@ }; }; +&wkup_i2c0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&wkup_i2c0_pins_default>; + clock-frequency = <400000>; + + eeprom@50 { + compatible = "atmel,24c256"; + reg = <0x50>; + }; +}; + &ospi0 { pinctrl-names = "default"; pinctrl-0 = <&mcu_fss0_ospi0_pins_default>; @@ -229,5 +281,46 @@ cdns,tchsh-ns = <60>; cdns,tslch-ns = <60>; cdns,read-delay = <4>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "ospi.tiboot3"; + reg = <0x0 0x100000>; + }; + + partition@100000 { + label = "ospi.tispl"; + reg = <0x100000 0x200000>; + }; + + partition@300000 { + label = "ospi.u-boot"; + reg = <0x300000 0x400000>; + }; + + partition@700000 { + label = "ospi.env"; + reg = <0x700000 0x40000>; + }; + + partition@740000 { + label = "ospi.env.backup"; + reg = <0x740000 0x40000>; + }; + + partition@800000 { + label = "ospi.rootfs"; + reg = <0x800000 0x37c0000>; + }; + + partition@3fc0000 { + label = "ospi.phypattern"; + reg = <0x3fc0000 0x40000>; + }; + }; }; }; diff --git a/arch/arm64/boot/dts/ti/k3-j7200-thermal.dtsi b/arch/arm64/boot/dts/ti/k3-j7200-thermal.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..e7e3a643a6f0cc6536548e106d3c29e8b0ca3d1f --- /dev/null +++ b/arch/arm64/boot/dts/ti/k3-j7200-thermal.dtsi @@ -0,0 +1,47 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include + +thermal_zones: thermal-zones { + mcu_thermal: mcu-thermal { + polling-delay-passive = <250>; /* milliseconds */ + polling-delay = <500>; /* milliseconds */ + thermal-sensors = <&wkup_vtm0 0>; + + trips { + wkup_crit: wkup-crit { + temperature = <125000>; /* milliCelsius */ + hysteresis = <2000>; /* milliCelsius */ + type = "critical"; + }; + }; + }; + + mpu_thermal: mpu-thermal { + polling-delay-passive = <250>; /* milliseconds */ + polling-delay = <500>; /* milliseconds */ + thermal-sensors = <&wkup_vtm0 1>; + + trips { + mpu_crit: mpu-crit { + temperature = <125000>; /* milliCelsius */ + hysteresis = <2000>; /* milliCelsius */ + type = "critical"; + }; + }; + }; + + main_thermal: main-thermal { + polling-delay-passive = <250>; /* milliseconds */ + polling-delay = <500>; /* milliseconds */ + thermal-sensors = <&wkup_vtm0 2>; + + trips { + c7x_crit: c7x-crit { + temperature = <125000>; /* milliCelsius */ + hysteresis = <2000>; /* milliCelsius */ + type = "critical"; + }; + }; + }; +}; diff --git a/arch/arm64/boot/dts/ti/k3-j7200.dtsi b/arch/arm64/boot/dts/ti/k3-j7200.dtsi index bbe380c72a7ec513288e4def6aa003b4e65cdbc2..ef73e6d7e85815e026dbd44e00c4c55149bf45c0 100644 --- a/arch/arm64/boot/dts/ti/k3-j7200.dtsi +++ b/arch/arm64/boot/dts/ti/k3-j7200.dtsi @@ -18,23 +18,6 @@ #address-cells = <2>; #size-cells = <2>; - aliases { - serial0 = &wkup_uart0; - serial1 = &mcu_uart0; - serial2 = &main_uart0; - serial3 = &main_uart1; - serial4 = &main_uart2; - serial5 = &main_uart3; - serial6 = &main_uart4; - serial7 = &main_uart5; - serial8 = &main_uart6; - serial9 = &main_uart7; - serial10 = &main_uart8; - serial11 = &main_uart9; - mmc0 = &main_sdhci0; - mmc1 = &main_sdhci1; - }; - chosen { }; cpus { @@ -95,6 +78,7 @@ msmc_l3: l3-cache0 { compatible = "cache"; cache-level = <3>; + cache-unified; }; firmware { @@ -128,6 +112,7 @@ #size-cells = <2>; ranges = <0x00 0x00100000 0x00 0x00100000 0x00 0x00020000>, /* ctrl mmr */ <0x00 0x00600000 0x00 0x00600000 0x00 0x00031100>, /* GPIO */ + <0x00 0x00700000 0x00 0x00700000 0x00 0x00001000>, /* ESM */ <0x00 0x00a40000 0x00 0x00a40000 0x00 0x00000800>, /* timesync router */ <0x00 0x01000000 0x00 0x01000000 0x00 0x0d000000>, /* Most peripherals */ <0x00 0x30000000 0x00 0x30000000 0x00 0x0c400000>, /* MAIN NAVSS */ @@ -170,6 +155,8 @@ <0x07 0x00000000 0x07 0x00000000 0x01 0x00000000>; /* FSS OSPI1 data region 3 */ }; }; + + #include "k3-j7200-thermal.dtsi" }; /* Now include the peripherals for each bus segments */ diff --git a/arch/arm64/boot/dts/ti/k3-j721e-beagleboneai64.dts b/arch/arm64/boot/dts/ti/k3-j721e-beagleboneai64.dts index 37c24b077b6aa814facd286bfaee72464a3ad39e..66aac145e75301008b630cb0d6d4b84ebb9df685 100644 --- a/arch/arm64/boot/dts/ti/k3-j721e-beagleboneai64.dts +++ b/arch/arm64/boot/dts/ti/k3-j721e-beagleboneai64.dts @@ -20,6 +20,7 @@ model = "BeagleBoard.org BeagleBone AI-64"; aliases { + serial0 = &wkup_uart0; serial2 = &main_uart0; mmc0 = &main_sdhci0; mmc1 = &main_sdhci1; @@ -304,7 +305,7 @@ }; &main_pmx0 { - led_pins_default: led-pins-default { + led_pins_default: led-default-pins { pinctrl-single,pins = < J721E_IOPAD(0x184, PIN_INPUT, 7) /* (T23) RGMII5_RD0.GPIO0_96 */ J721E_IOPAD(0x180, PIN_INPUT, 7) /* (R23) RGMII5_RD1.GPIO0_95 */ @@ -314,7 +315,7 @@ >; }; - main_mmc1_pins_default: main-mmc1-pins-default { + main_mmc1_pins_default: main-mmc1-default-pins { pinctrl-single,pins = < J721E_IOPAD(0x254, PIN_INPUT, 0) /* (R29) MMC1_CMD */ J721E_IOPAD(0x250, PIN_INPUT, 0) /* (P25) MMC1_CLK */ @@ -327,64 +328,64 @@ >; }; - main_uart0_pins_default: main-uart0-pins-default { + main_uart0_pins_default: main-uart0-default-pins { pinctrl-single,pins = < J721E_IOPAD(0x1e8, PIN_INPUT, 0) /* (AB2) UART0_RXD */ J721E_IOPAD(0x1ec, PIN_OUTPUT, 0) /* (AB3) UART0_TXD */ >; }; - sd_pwr_en_pins_default: sd-pwr-en-pins-default { + sd_pwr_en_pins_default: sd-pwr-en-default-pins { pinctrl-single,pins = < J721E_IOPAD(0x14c, PIN_INPUT, 7) /* (AA29) PRG0_PRU1_GPO19.GPIO0_82 */ >; }; - vdd_sd_dv_alt_pins_default: vdd-sd-dv-alt-pins-default { + vdd_sd_dv_alt_pins_default: vdd-sd-dv-alt-default-pins { pinctrl-single,pins = < J721E_IOPAD(0x1d8, PIN_INPUT, 7) /* (W4) SPI1_CS1.GPIO0_117 */ >; }; - main_usbss0_pins_default: main-usbss0-pins-default { + main_usbss0_pins_default: main-usbss0-default-pins { pinctrl-single,pins = < J721E_IOPAD(0x210, PIN_INPUT, 7) /* (W3) MCAN1_RX.GPIO1_3 - USBC_DIR */ >; }; - main_usbss1_pins_default: main-usbss1-pins-default { + main_usbss1_pins_default: main-usbss1-default-pins { pinctrl-single,pins = < J721E_IOPAD(0x290, INPUT_DISABLE, 1) /* (U6) USB0_DRVVBUS.USB1_DRVVBUS */ >; }; - dp0_3v3_en_pins_default:dp0-3v3-en-pins-default { + dp0_3v3_en_pins_default:dp0-3v3-en-default-pins { pinctrl-single,pins = < J721E_IOPAD(0xc8, PIN_INPUT, 7) /* (AE26) PRG0_PRU0_GPO6.GPIO0_49 */ >; }; - dp0_pins_default: dp0-pins-default { + dp0_pins_default: dp0-default-pins { pinctrl-single,pins = < J721E_IOPAD(0x1c4, PIN_INPUT, 5) /* (Y4) SPI0_CS1.DP0_HPD */ >; }; - main_i2c0_pins_default: main-i2c0-pins-default { + main_i2c0_pins_default: main-i2c0-default-pins { pinctrl-single,pins = < J721E_IOPAD(0x220, PIN_INPUT_PULLUP, 0) /* (AC5) I2C0_SCL */ J721E_IOPAD(0x224, PIN_INPUT_PULLUP, 0) /* (AA5) I2C0_SDA */ >; }; - main_i2c1_pins_default: main-i2c1-pins-default { + main_i2c1_pins_default: main-i2c1-default-pins { pinctrl-single,pins = < J721E_IOPAD(0x228, PIN_INPUT_PULLUP, 0) /* (Y6) I2C1_SCL */ J721E_IOPAD(0x22c, PIN_INPUT_PULLUP, 0) /* (AA6) I2C1_SDA */ >; }; - main_i2c2_pins_default: main-i2c2-pins-default { + main_i2c2_pins_default: main-i2c2-default-pins { pinctrl-single,pins = < J721E_IOPAD(0x208, PIN_INPUT_PULLUP, 4) /* (W5) MCAN0_RX.I2C2_SCL */ J721E_IOPAD(0x20c, PIN_INPUT_PULLUP, 4) /* (W6) MCAN0_TX.I2C2_SDA */ @@ -393,14 +394,14 @@ >; }; - main_i2c3_pins_default: main-i2c3-pins-default { + main_i2c3_pins_default: main-i2c3-default-pins { pinctrl-single,pins = < J721E_IOPAD(0x270, PIN_INPUT_PULLUP, 4) /* (T26) MMC2_CLK.I2C3_SCL */ J721E_IOPAD(0x274, PIN_INPUT_PULLUP, 4) /* (T25) MMC2_CMD.I2C3_SDA */ >; }; - main_i2c4_pins_default: main-i2c4-pins-default { + main_i2c4_pins_default: main-i2c4-default-pins { pinctrl-single,pins = < J721E_IOPAD(0x1e0, PIN_INPUT_PULLUP, 2) /* (Y5) SPI1_D0.I2C4_SCL */ J721E_IOPAD(0x1dc, PIN_INPUT_PULLUP, 2) /* (Y1) SPI1_CLK.I2C4_SDA */ @@ -409,14 +410,14 @@ >; }; - main_i2c5_pins_default: main-i2c5-pins-default { + main_i2c5_pins_default: main-i2c5-default-pins { pinctrl-single,pins = < J721E_IOPAD(0x150, PIN_INPUT_PULLUP, 2) /* (Y26) PRG0_MDIO0_MDIO.I2C5_SCL */ J721E_IOPAD(0x154, PIN_INPUT_PULLUP, 2) /* (AA27) PRG0_MDIO0_MDC.I2C5_SDA */ >; }; - main_i2c6_pins_default: main-i2c6-pins-default { + main_i2c6_pins_default: main-i2c6-default-pins { pinctrl-single,pins = < J721E_IOPAD(0x1d0, PIN_INPUT_PULLUP, 2) /* (AA3) SPI0_D1.I2C6_SCL */ J721E_IOPAD(0x1e4, PIN_INPUT_PULLUP, 2) /* (Y2) SPI1_D1.I2C6_SDA */ @@ -425,21 +426,21 @@ >; }; - csi0_gpio_pins_default: csi0-gpio-pins-default { + csi0_gpio_pins_default: csi0-gpio-default-pins { pinctrl-single,pins = < J721E_IOPAD(0x19c, PIN_INPUT_PULLDOWN, 7) /* (W27) RGMII6_TD0.GPIO0_102 */ J721E_IOPAD(0x1a0, PIN_INPUT_PULLDOWN, 7) /* (W29) RGMII6_TXC.GPIO0_103 */ >; }; - csi1_gpio_pins_default: csi1-gpio-pins-default { + csi1_gpio_pins_default: csi1-gpio-default-pins { pinctrl-single,pins = < J721E_IOPAD(0x198, PIN_INPUT_PULLDOWN, 7) /* (V25) RGMII6_TD1.GPIO0_101 */ J721E_IOPAD(0x1b0, PIN_INPUT_PULLDOWN, 7) /* (W24) RGMII6_RD1.GPIO0_107 */ >; }; - pcie1_rst_pins_default: pcie1-rst-pins-default { + pcie1_rst_pins_default: pcie1-rst-default-pins { pinctrl-single,pins = < J721E_IOPAD(0x5c, PIN_INPUT, 7) /* (AG23) PRG1_PRU1_GPO1.GPIO0_22 */ >; @@ -447,13 +448,13 @@ }; &wkup_pmx0 { - eeprom_wp_pins_default: eeprom-wp-pins-default { + eeprom_wp_pins_default: eeprom-wp-default-pins { pinctrl-single,pins = < J721E_WKUP_IOPAD(0xc4, PIN_OUTPUT_PULLUP, 7) /* (G24) WKUP_GPIO0_5 */ >; }; - mcu_adc0_pins_default: mcu-adc0-pins-default { + mcu_adc0_pins_default: mcu-adc0-default-pins { pinctrl-single,pins = < J721E_WKUP_IOPAD(0x130, PIN_INPUT, 0) /* (K25) MCU_ADC0_AIN0 */ J721E_WKUP_IOPAD(0x134, PIN_INPUT, 0) /* (K26) MCU_ADC0_AIN1 */ @@ -465,13 +466,13 @@ >; }; - mcu_adc1_pins_default: mcu-adc1-pins-default { + mcu_adc1_pins_default: mcu-adc1-default-pins { pinctrl-single,pins = < J721E_WKUP_IOPAD(0x150, PIN_INPUT, 0) /* (N23) MCU_ADC1_AIN0 */ >; }; - mikro_bus_pins_default: mikro-bus-pins-default { + mikro_bus_pins_default: mikro-bus-default-pins { pinctrl-single,pins = < J721E_WKUP_IOPAD(0x108, PIN_INPUT, 7) /* SDAPULLEN (E26) PMIC_POWER_EN0.WKUP_GPIO0_66 */ J721E_WKUP_IOPAD(0xd4, PIN_INPUT, 7) /* SDA (G26) WKUP_GPIO0_9.MCU_I2C1_SDA */ @@ -494,7 +495,7 @@ >; }; - mcu_cpsw_pins_default: mcu-cpsw-pins-default { + mcu_cpsw_pins_default: mcu-cpsw-default-pins { pinctrl-single,pins = < J721E_WKUP_IOPAD(0x84, PIN_INPUT, 0) /* (B24) MCU_RGMII1_RD0 */ J721E_WKUP_IOPAD(0x80, PIN_INPUT, 0) /* (A24) MCU_RGMII1_RD1 */ @@ -511,27 +512,34 @@ >; }; - mcu_mdio_pins_default: mcu-mdio1-pins-default { + mcu_mdio_pins_default: mcu-mdio1-default-pins { pinctrl-single,pins = < J721E_WKUP_IOPAD(0x8c, PIN_OUTPUT, 0) /* (F23) MCU_MDIO0_MDC */ J721E_WKUP_IOPAD(0x88, PIN_INPUT, 0) /* (E23) MCU_MDIO0_MDIO */ >; }; - sw_pwr_pins_default: sw-pwr-pins-default { + sw_pwr_pins_default: sw-pwr-default-pins { pinctrl-single,pins = < J721E_WKUP_IOPAD(0xc0, PIN_INPUT, 7) /* (G25) WKUP_GPIO0_4 */ >; }; - wkup_i2c0_pins_default: wkup-i2c0-pins-default { + wkup_i2c0_pins_default: wkup-i2c0-default-pins { pinctrl-single,pins = < J721E_WKUP_IOPAD(0xf8, PIN_INPUT_PULLUP, 0) /* (J25) WKUP_I2C0_SCL */ J721E_WKUP_IOPAD(0xfc, PIN_INPUT_PULLUP, 0) /* (H24) WKUP_I2C0_SDA */ >; }; - mcu_usbss1_pins_default: mcu-usbss1-pins-default { + wkup_uart0_pins_default: wkup-uart0-default-pins { + pinctrl-single,pins = < + J721E_WKUP_IOPAD(0xa0, PIN_INPUT, 0) /* (J29) WKUP_UART0_RXD */ + J721E_WKUP_IOPAD(0xa4, PIN_OUTPUT, 0) /* (J28) WKUP_UART0_TXD */ + >; + }; + + mcu_usbss1_pins_default: mcu-usbss1-default-pins { pinctrl-single,pins = < J721E_WKUP_IOPAD(0x3c, PIN_OUTPUT_PULLUP, 5) /* (A23) MCU_OSPI1_LBCLKO.WKUP_GPIO0_30 */ >; @@ -541,6 +549,8 @@ &wkup_uart0 { /* Wakeup UART is used by TIFS firmware. */ status = "reserved"; + pinctrl-names = "default"; + pinctrl-0 = <&wkup_uart0_pins_default>; }; &main_uart0 { @@ -593,7 +603,7 @@ &main_i2c1 { status = "okay"; pinctrl-names = "default"; - pinctrl-0 = <&main_i2c1_pins_default &csi1_gpio_pins_default>; + pinctrl-0 = <&main_i2c1_pins_default>; clock-frequency = <400000>; }; @@ -623,7 +633,7 @@ &main_i2c5 { status = "okay"; pinctrl-names = "default"; - pinctrl-0 = <&main_i2c5_pins_default &csi0_gpio_pins_default>; + pinctrl-0 = <&main_i2c5_pins_default>; clock-frequency = <400000>; }; @@ -639,12 +649,14 @@ &wkup_i2c0 { status = "okay"; pinctrl-names = "default"; - pinctrl-0 = <&wkup_i2c0_pins_default &eeprom_wp_pins_default>; + pinctrl-0 = <&wkup_i2c0_pins_default>; clock-frequency = <400000>; eeprom@50 { compatible = "atmel,24c04"; reg = <0x50>; + pinctrl-names = "default"; + pinctrl-0 = <&eeprom_wp_pins_default>; }; }; @@ -680,7 +692,8 @@ &wkup_gpio0 { pinctrl-names = "default"; - pinctrl-0 = <&mcu_adc0_pins_default &mcu_adc1_pins_default &mikro_bus_pins_default>; + pinctrl-0 = <&mcu_adc0_pins_default>, <&mcu_adc1_pins_default>, + <&mikro_bus_pins_default>; }; &wkup_gpio1 { @@ -688,6 +701,11 @@ status = "disabled"; }; +&main_gpio0 { + pinctrl-names = "default"; + pinctrl-0 = <&csi1_gpio_pins_default>, <&csi0_gpio_pins_default>; +}; + &usb_serdes_mux { idle-states = <1>, <1>; /* USB0 to SERDES3, USB1 to SERDES2 */ }; @@ -759,7 +777,7 @@ &usbss1 { pinctrl-names = "default"; - pinctrl-0 = <&main_usbss1_pins_default &mcu_usbss1_pins_default>; + pinctrl-0 = <&main_usbss1_pins_default>, <&mcu_usbss1_pins_default>; ti,vbus-divider; }; @@ -872,12 +890,8 @@ }; }; -&pcie0_rc { - /* Unused */ - status = "disabled"; -}; - &pcie1_rc { + status = "okay"; pinctrl-names = "default"; pinctrl-0 = <&pcie1_rst_pins_default>; phys = <&serdes1_pcie_link>; @@ -887,55 +901,12 @@ reset-gpios = <&main_gpio0 22 GPIO_ACTIVE_HIGH>; }; -&pcie2_rc { - /* Unused */ - status = "disabled"; -}; - -&pcie0_ep { - status = "disabled"; - phys = <&serdes0_pcie_link>; - phy-names = "pcie-phy"; - num-lanes = <1>; -}; - -&pcie1_ep { - status = "disabled"; - phys = <&serdes1_pcie_link>; - phy-names = "pcie-phy"; - num-lanes = <2>; -}; - -&pcie2_ep { - /* Unused */ - status = "disabled"; -}; - -&pcie3_rc { - /* Unused */ - status = "disabled"; -}; - -&pcie3_ep { - /* Unused */ - status = "disabled"; -}; - -&icssg0_mdio { - /* Unused */ - status = "disabled"; -}; - -&icssg1_mdio { - /* Unused */ - status = "disabled"; -}; - &ufs_wrapper { status = "disabled"; }; &mailbox0_cluster0 { + status = "okay"; interrupts = <436>; mbox_mcu_r5fss0_core0: mbox-mcu-r5fss0-core0 { @@ -950,6 +921,7 @@ }; &mailbox0_cluster1 { + status = "okay"; interrupts = <432>; mbox_main_r5fss0_core0: mbox-main-r5fss0-core0 { @@ -964,6 +936,7 @@ }; &mailbox0_cluster2 { + status = "okay"; interrupts = <428>; mbox_main_r5fss1_core0: mbox-main-r5fss1-core0 { @@ -978,6 +951,7 @@ }; &mailbox0_cluster3 { + status = "okay"; interrupts = <424>; mbox_c66_0: mbox-c66-0 { @@ -992,6 +966,7 @@ }; &mailbox0_cluster4 { + status = "okay"; interrupts = <420>; mbox_c71_0: mbox-c71-0 { @@ -1001,55 +976,55 @@ }; &mcu_r5fss0_core0 { - mboxes = <&mailbox0_cluster0 &mbox_mcu_r5fss0_core0>; + mboxes = <&mailbox0_cluster0>, <&mbox_mcu_r5fss0_core0>; memory-region = <&mcu_r5fss0_core0_dma_memory_region>, <&mcu_r5fss0_core0_memory_region>; }; &mcu_r5fss0_core1 { - mboxes = <&mailbox0_cluster0 &mbox_mcu_r5fss0_core1>; + mboxes = <&mailbox0_cluster0>, <&mbox_mcu_r5fss0_core1>; memory-region = <&mcu_r5fss0_core1_dma_memory_region>, <&mcu_r5fss0_core1_memory_region>; }; &main_r5fss0_core0 { - mboxes = <&mailbox0_cluster1 &mbox_main_r5fss0_core0>; + mboxes = <&mailbox0_cluster1>, <&mbox_main_r5fss0_core0>; memory-region = <&main_r5fss0_core0_dma_memory_region>, <&main_r5fss0_core0_memory_region>; }; &main_r5fss0_core1 { - mboxes = <&mailbox0_cluster1 &mbox_main_r5fss0_core1>; + mboxes = <&mailbox0_cluster1>, <&mbox_main_r5fss0_core1>; memory-region = <&main_r5fss0_core1_dma_memory_region>, <&main_r5fss0_core1_memory_region>; }; &main_r5fss1_core0 { - mboxes = <&mailbox0_cluster2 &mbox_main_r5fss1_core0>; + mboxes = <&mailbox0_cluster2>, <&mbox_main_r5fss1_core0>; memory-region = <&main_r5fss1_core0_dma_memory_region>, <&main_r5fss1_core0_memory_region>; }; &main_r5fss1_core1 { - mboxes = <&mailbox0_cluster2 &mbox_main_r5fss1_core1>; + mboxes = <&mailbox0_cluster2>, <&mbox_main_r5fss1_core1>; memory-region = <&main_r5fss1_core1_dma_memory_region>, <&main_r5fss1_core1_memory_region>; }; &c66_0 { - mboxes = <&mailbox0_cluster3 &mbox_c66_0>; + mboxes = <&mailbox0_cluster3>, <&mbox_c66_0>; memory-region = <&c66_0_dma_memory_region>, <&c66_0_memory_region>; }; &c66_1 { - mboxes = <&mailbox0_cluster3 &mbox_c66_1>; + mboxes = <&mailbox0_cluster3>, <&mbox_c66_1>; memory-region = <&c66_1_dma_memory_region>, <&c66_1_memory_region>; }; &c71_0 { - mboxes = <&mailbox0_cluster4 &mbox_c71_0>; + mboxes = <&mailbox0_cluster4>, <&mbox_c71_0>; memory-region = <&c71_0_dma_memory_region>, <&c71_0_memory_region>; }; diff --git a/arch/arm64/boot/dts/ti/k3-j721e-common-proc-board.dts b/arch/arm64/boot/dts/ti/k3-j721e-common-proc-board.dts index 7db0603125aa2f18807530d08f1a33c9ceb4f59a..c1cbbae761827074773af06318f70c2397e6508d 100644 --- a/arch/arm64/boot/dts/ti/k3-j721e-common-proc-board.dts +++ b/arch/arm64/boot/dts/ti/k3-j721e-common-proc-board.dts @@ -1,6 +1,8 @@ // SPDX-License-Identifier: GPL-2.0 /* * Copyright (C) 2019 Texas Instruments Incorporated - https://www.ti.com/ + * + * Product Link: https://www.ti.com/tool/J721EXCPXEVM */ /dts-v1/; @@ -15,16 +17,27 @@ compatible = "ti,j721e-evm", "ti,j721e"; model = "Texas Instruments J721e EVM"; + aliases { + serial0 = &wkup_uart0; + serial1 = &mcu_uart0; + serial2 = &main_uart0; + serial3 = &main_uart1; + serial4 = &main_uart2; + serial6 = &main_uart4; + ethernet0 = &cpsw_port1; + mmc0 = &main_sdhci0; + mmc1 = &main_sdhci1; + }; + chosen { stdout-path = "serial2:115200n8"; - bootargs = "console=ttyS2,115200n8 earlycon=ns16550a,mmio32,0x02800000"; }; gpio_keys: gpio-keys { compatible = "gpio-keys"; autorepeat; pinctrl-names = "default"; - pinctrl-0 = <&sw10_button_pins_default &sw11_button_pins_default>; + pinctrl-0 = <&sw10_button_pins_default>, <&sw11_button_pins_default>; sw10: switch-10 { label = "GPIO Key USER1"; @@ -173,13 +186,43 @@ }; &main_pmx0 { - sw10_button_pins_default: sw10-button-pins-default { + main_uart0_pins_default: main-uart0-default-pins { + pinctrl-single,pins = < + J721E_IOPAD(0x1d4, PIN_INPUT, 1) /* (Y3) SPI1_CS0.UART0_CTSn */ + J721E_IOPAD(0x1c0, PIN_OUTPUT, 1) /* (AA2) SPI0_CS0.UART0_RTSn */ + J721E_IOPAD(0x1e8, PIN_INPUT, 0) /* (AB2) UART0_RXD */ + J721E_IOPAD(0x1ec, PIN_OUTPUT, 0) /* (AB3) UART0_TXD */ + >; + }; + + main_uart1_pins_default: main-uart1-default-pins { + pinctrl-single,pins = < + J721E_IOPAD(0x1f8, PIN_INPUT, 0) /* (AA4) UART1_RXD */ + J721E_IOPAD(0x1fc, PIN_OUTPUT, 0) /* (AB4) UART1_TXD */ + >; + }; + + main_uart2_pins_default: main-uart2-default-pins { + pinctrl-single,pins = < + J721E_IOPAD(0x1dc, PIN_INPUT, 3) /* (Y1) SPI1_CLK.UART2_RXD */ + J721E_IOPAD(0x1e0, PIN_OUTPUT, 3) /* (Y5) SPI1_D0.UART2_TXD */ + >; + }; + + main_uart4_pins_default: main-uart4-default-pins { + pinctrl-single,pins = < + J721E_IOPAD(0x190, PIN_INPUT, 1) /* (W23) RGMII6_TD3.UART4_RXD */ + J721E_IOPAD(0x194, PIN_OUTPUT, 1) /* (W28) RGMII6_TD2.UART4_TXD */ + >; + }; + + sw10_button_pins_default: sw10-button-default-pins { pinctrl-single,pins = < J721E_IOPAD(0x0, PIN_INPUT, 7) /* (AC18) EXTINTn.GPIO0_0 */ >; }; - main_mmc1_pins_default: main-mmc1-pins-default { + main_mmc1_pins_default: main-mmc1-default-pins { pinctrl-single,pins = < J721E_IOPAD(0x254, PIN_INPUT, 0) /* (R29) MMC1_CMD */ J721E_IOPAD(0x250, PIN_INPUT, 0) /* (P25) MMC1_CLK */ @@ -193,66 +236,66 @@ >; }; - vdd_sd_dv_alt_pins_default: vdd-sd-dv-alt-pins-default { + vdd_sd_dv_alt_pins_default: vdd-sd-dv-alt-default-pins { pinctrl-single,pins = < J721E_IOPAD(0x1d8, PIN_INPUT, 7) /* (W4) SPI1_CS1.GPIO0_117 */ >; }; - main_usbss0_pins_default: main-usbss0-pins-default { + main_usbss0_pins_default: main-usbss0-default-pins { pinctrl-single,pins = < J721E_IOPAD(0x290, PIN_OUTPUT, 0) /* (U6) USB0_DRVVBUS */ J721E_IOPAD(0x210, PIN_INPUT, 7) /* (W3) MCAN1_RX.GPIO1_3 */ >; }; - main_usbss1_pins_default: main-usbss1-pins-default { + main_usbss1_pins_default: main-usbss1-default-pins { pinctrl-single,pins = < J721E_IOPAD(0x214, PIN_OUTPUT, 4) /* (V4) MCAN1_TX.USB1_DRVVBUS */ >; }; - dp0_pins_default: dp0-pins-default { + dp0_pins_default: dp0-default-pins { pinctrl-single,pins = < J721E_IOPAD(0x1c4, PIN_INPUT, 5) /* SPI0_CS1.DP0_HPD */ >; }; - main_i2c1_exp4_pins_default: main-i2c1-exp4-pins-default { + main_i2c1_exp4_pins_default: main-i2c1-exp4-default-pins { pinctrl-single,pins = < J721E_IOPAD(0x230, PIN_INPUT, 7) /* (U2) ECAP0_IN_APWM_OUT.GPIO1_11 */ >; }; - main_i2c0_pins_default: main-i2c0-pins-default { + main_i2c0_pins_default: main-i2c0-default-pins { pinctrl-single,pins = < J721E_IOPAD(0x220, PIN_INPUT_PULLUP, 0) /* (AC5) I2C0_SCL */ J721E_IOPAD(0x224, PIN_INPUT_PULLUP, 0) /* (AA5) I2C0_SDA */ >; }; - main_i2c1_pins_default: main-i2c1-pins-default { + main_i2c1_pins_default: main-i2c1-default-pins { pinctrl-single,pins = < J721E_IOPAD(0x228, PIN_INPUT_PULLUP, 0) /* (Y6) I2C1_SCL */ J721E_IOPAD(0x22c, PIN_INPUT_PULLUP, 0) /* (AA6) I2C1_SDA */ >; }; - main_i2c3_pins_default: main-i2c3-pins-default { + main_i2c3_pins_default: main-i2c3-default-pins { pinctrl-single,pins = < J721E_IOPAD(0x270, PIN_INPUT_PULLUP, 4) /* (T26) MMC2_CLK.I2C3_SCL */ J721E_IOPAD(0x274, PIN_INPUT_PULLUP, 4) /* (T25) MMC2_CMD.I2C3_SDA */ >; }; - main_i2c6_pins_default: main-i2c6-pins-default { + main_i2c6_pins_default: main-i2c6-default-pins { pinctrl-single,pins = < J721E_IOPAD(0x1d0, PIN_INPUT_PULLUP, 2) /* (AA3) SPI0_D1.I2C6_SCL */ J721E_IOPAD(0x1e4, PIN_INPUT_PULLUP, 2) /* (Y2) SPI1_D1.I2C6_SDA */ >; }; - mcasp10_pins_default: mcasp10-pins-default { + mcasp10_pins_default: mcasp10-default-pins { pinctrl-single,pins = < J721E_IOPAD(0x158, PIN_OUTPUT_PULLDOWN, 12) /* (U23) RGMII5_TX_CTL.MCASP10_ACLKX */ J721E_IOPAD(0x15c, PIN_OUTPUT_PULLDOWN, 12) /* (U26) RGMII5_RX_CTL.MCASP10_AFSX */ @@ -266,27 +309,27 @@ >; }; - audi_ext_refclk2_pins_default: audi-ext-refclk2-pins-default { + audi_ext_refclk2_pins_default: audi-ext-refclk2-default-pins { pinctrl-single,pins = < J721E_IOPAD(0x1a4, PIN_OUTPUT, 3) /* (W26) RGMII6_RXC.AUDIO_EXT_REFCLK2 */ >; }; - main_mcan0_pins_default: main-mcan0-pins-default { + main_mcan0_pins_default: main-mcan0-default-pins { pinctrl-single,pins = < J721E_IOPAD(0x208, PIN_INPUT, 0) /* (W5) MCAN0_RX */ J721E_IOPAD(0x20c, PIN_OUTPUT, 0) /* (W6) MCAN0_TX */ >; }; - main_mcan2_pins_default: main-mcan2-pins-default { + main_mcan2_pins_default: main-mcan2-default-pins { pinctrl-single,pins = < J721E_IOPAD(0x01f0, PIN_INPUT, 3) /* (AC2) MCAN2_RX.GPIO0_123 */ J721E_IOPAD(0x01f4, PIN_OUTPUT, 3) /* (AB1) MCAN2_TX.GPIO0_124 */ >; }; - main_mcan2_gpio_pins_default: main-mcan2-gpio-pins-default { + main_mcan2_gpio_pins_default: main-mcan2-gpio-default-pins { pinctrl-single,pins = < J721E_IOPAD(0x200, PIN_INPUT, 7) /* (AC4) UART1_CTSn.GPIO0_127 */ >; @@ -294,13 +337,29 @@ }; &wkup_pmx0 { - sw11_button_pins_default: sw11-button-pins-default { + wkup_uart0_pins_default: wkup-uart0-default-pins { + pinctrl-single,pins = < + J721E_WKUP_IOPAD(0xa0, PIN_INPUT, 0) /* (J29) WKUP_UART0_RXD */ + J721E_WKUP_IOPAD(0xa4, PIN_OUTPUT, 0) /* (J28) WKUP_UART0_TXD */ + >; + }; + + mcu_uart0_pins_default: mcu-uart0-default-pins { + pinctrl-single,pins = < + J721E_WKUP_IOPAD(0xe8, PIN_INPUT, 0) /* (H29) WKUP_GPIO0_14.MCU_UART0_CTSn */ + J721E_WKUP_IOPAD(0xec, PIN_OUTPUT, 0) /* (J27) WKUP_GPIO0_15.MCU_UART0_RTSn */ + J721E_WKUP_IOPAD(0xe4, PIN_INPUT, 0) /* (H28) WKUP_GPIO0_13.MCU_UART0_RXD */ + J721E_WKUP_IOPAD(0xe0, PIN_OUTPUT, 0) /* (G29) WKUP_GPIO0_12.MCU_UART0_TXD */ + >; + }; + + sw11_button_pins_default: sw11-button-default-pins { pinctrl-single,pins = < J721E_WKUP_IOPAD(0xcc, PIN_INPUT, 7) /* (G28) WKUP_GPIO0_7 */ >; }; - mcu_fss0_ospi1_pins_default: mcu-fss0-ospi1-pins-default { + mcu_fss0_ospi1_pins_default: mcu-fss0-ospi1-default-pins { pinctrl-single,pins = < J721E_WKUP_IOPAD(0x34, PIN_OUTPUT, 0) /* (F22) MCU_OSPI1_CLK */ J721E_WKUP_IOPAD(0x50, PIN_OUTPUT, 0) /* (C22) MCU_OSPI1_CSn0 */ @@ -313,7 +372,7 @@ >; }; - mcu_cpsw_pins_default: mcu-cpsw-pins-default { + mcu_cpsw_pins_default: mcu-cpsw-default-pins { pinctrl-single,pins = < J721E_WKUP_IOPAD(0x0058, PIN_OUTPUT, 0) /* MCU_RGMII1_TX_CTL */ J721E_WKUP_IOPAD(0x005c, PIN_INPUT, 0) /* MCU_RGMII1_RX_CTL */ @@ -330,70 +389,84 @@ >; }; - mcu_mdio_pins_default: mcu-mdio1-pins-default { + mcu_mdio_pins_default: mcu-mdio1-default-pins { pinctrl-single,pins = < J721E_WKUP_IOPAD(0x008c, PIN_OUTPUT, 0) /* MCU_MDIO0_MDC */ J721E_WKUP_IOPAD(0x0088, PIN_INPUT, 0) /* MCU_MDIO0_MDIO */ >; }; - mcu_mcan0_pins_default: mcu-mcan0-pins-default { + mcu_mcan0_pins_default: mcu-mcan0-default-pins { pinctrl-single,pins = < J721E_WKUP_IOPAD(0xac, PIN_INPUT, 0) /* (C29) MCU_MCAN0_RX */ J721E_WKUP_IOPAD(0xa8, PIN_OUTPUT, 0) /* (D29) MCU_MCAN0_TX */ >; }; - mcu_mcan0_gpio_pins_default: mcu-mcan0-gpio-pins-default { + mcu_mcan0_gpio_pins_default: mcu-mcan0-gpio-default-pins { pinctrl-single,pins = < J721E_WKUP_IOPAD(0xb0, PIN_INPUT, 7) /* (F26) WKUP_GPIO0_0 */ J721E_WKUP_IOPAD(0x98, PIN_INPUT, 7) /* (E28) MCU_SPI0_D1.WKUP_GPIO0_54 */ >; }; - mcu_mcan1_pins_default: mcu-mcan1-pins-default { + mcu_mcan1_pins_default: mcu-mcan1-default-pins { pinctrl-single,pins = < J721E_WKUP_IOPAD(0xc4, PIN_INPUT, 0) /* (G24) WKUP_GPIO0_5.MCU_MCAN1_RX */ J721E_WKUP_IOPAD(0xc0, PIN_OUTPUT, 0) /* (G25) WKUP_GPIO0_4.MCU_MCAN1_TX */ >; }; - mcu_mcan1_gpio_pins_default: mcu-mcan1-gpio-pins-default { + mcu_mcan1_gpio_pins_default: mcu-mcan1-gpio-default-pins { pinctrl-single,pins = < J721E_WKUP_IOPAD(0xb8, PIN_INPUT, 7) /* (F28) WKUP_GPIO0_2 */ >; }; + + wkup_gpio_pins_default: wkup-gpio-default-pins { + pinctrl-single,pins = < + J721E_WKUP_IOPAD(0xd0, PIN_INPUT, 7) /* (C14) WKUP_GPIO0_8 */ + >; + }; }; &wkup_uart0 { /* Wakeup UART is used by System firmware */ status = "reserved"; + pinctrl-names = "default"; + pinctrl-0 = <&wkup_uart0_pins_default>; }; &mcu_uart0 { status = "okay"; - /* Default pinmux */ + pinctrl-names = "default"; + pinctrl-0 = <&mcu_uart0_pins_default>; }; &main_uart0 { status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&main_uart0_pins_default>; /* Shared with ATF on this platform */ power-domains = <&k3_pds 146 TI_SCI_PD_SHARED>; }; &main_uart1 { status = "okay"; - /* Default pinmux */ + pinctrl-names = "default"; + pinctrl-0 = <&main_uart1_pins_default>; }; &main_uart2 { status = "okay"; - /* Default pinmux */ + pinctrl-names = "default"; + pinctrl-0 = <&main_uart2_pins_default>; }; &main_uart4 { status = "okay"; - /* Default pinmux */ + pinctrl-names = "default"; + pinctrl-0 = <&main_uart4_pins_default>; }; &main_gpio2 { @@ -420,6 +493,11 @@ status = "disabled"; }; +&wkup_gpio0 { + pinctrl-names = "default"; + pinctrl-0 = <&wkup_gpio_pins_default>; +}; + &wkup_gpio1 { status = "disabled"; }; @@ -513,6 +591,52 @@ cdns,tchsh-ns = <60>; cdns,tslch-ns = <60>; cdns,read-delay = <2>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "qspi.tiboot3"; + reg = <0x0 0x80000>; + }; + + partition@80000 { + label = "qspi.tispl"; + reg = <0x80000 0x200000>; + }; + + partition@280000 { + label = "qspi.u-boot"; + reg = <0x280000 0x400000>; + }; + + partition@680000 { + label = "qspi.env"; + reg = <0x680000 0x20000>; + }; + + partition@6a0000 { + label = "qspi.env.backup"; + reg = <0x6a0000 0x20000>; + }; + + partition@6c0000 { + label = "qspi.sysfw"; + reg = <0x6c0000 0x100000>; + }; + + partition@800000 { + label = "qspi.rootfs"; + reg = <0x800000 0x37c0000>; + }; + + partition@3fe0000 { + label = "qspi.phypattern"; + reg = <0x3fe0000 0x20000>; + }; + }; }; }; @@ -646,7 +770,7 @@ &mcu_cpsw { pinctrl-names = "default"; - pinctrl-0 = <&mcu_cpsw_pins_default &mcu_mdio_pins_default>; + pinctrl-0 = <&mcu_cpsw_pins_default>, <&mcu_mdio_pins_default>; }; &davinci_mdio { @@ -820,6 +944,7 @@ }; &pcie0_rc { + status = "okay"; reset-gpios = <&exp1 6 GPIO_ACTIVE_HIGH>; phys = <&serdes0_pcie_link>; phy-names = "pcie-phy"; @@ -827,6 +952,7 @@ }; &pcie1_rc { + status = "okay"; reset-gpios = <&exp1 2 GPIO_ACTIVE_HIGH>; phys = <&serdes1_pcie_link>; phy-names = "pcie-phy"; @@ -834,49 +960,13 @@ }; &pcie2_rc { + status = "okay"; reset-gpios = <&exp2 20 GPIO_ACTIVE_HIGH>; phys = <&serdes2_pcie_link>; phy-names = "pcie-phy"; num-lanes = <2>; }; -&pcie0_ep { - phys = <&serdes0_pcie_link>; - phy-names = "pcie-phy"; - num-lanes = <1>; - status = "disabled"; -}; - -&pcie1_ep { - phys = <&serdes1_pcie_link>; - phy-names = "pcie-phy"; - num-lanes = <2>; - status = "disabled"; -}; - -&pcie2_ep { - phys = <&serdes2_pcie_link>; - phy-names = "pcie-phy"; - num-lanes = <2>; - status = "disabled"; -}; - -&pcie3_rc { - status = "disabled"; -}; - -&pcie3_ep { - status = "disabled"; -}; - -&icssg0_mdio { - status = "disabled"; -}; - -&icssg1_mdio { - status = "disabled"; -}; - &mcu_mcan0 { status = "okay"; pinctrl-names = "default"; diff --git a/arch/arm64/boot/dts/ti/k3-j721e-evm-quad-port-eth-exp.dtso b/arch/arm64/boot/dts/ti/k3-j721e-evm-quad-port-eth-exp.dtso index 6ff7b6ad33ed37c32547f224b731b944b8eecb43..6f0adf591b982ba76d8b670454422a708c5ab02a 100644 --- a/arch/arm64/boot/dts/ti/k3-j721e-evm-quad-port-eth-exp.dtso +++ b/arch/arm64/boot/dts/ti/k3-j721e-evm-quad-port-eth-exp.dtso @@ -94,7 +94,7 @@ }; &main_pmx0 { - mdio0_pins_default: mdio0-pins-default { + mdio0_pins_default: mdio0-default-pins { pinctrl-single,pins = < J721E_IOPAD(0x1bc, PIN_OUTPUT, 0) /* (V24) MDIO0_MDC */ J721E_IOPAD(0x1b8, PIN_INPUT, 0) /* (V26) MDIO0_MDIO */ diff --git a/arch/arm64/boot/dts/ti/k3-j721e-main.dtsi b/arch/arm64/boot/dts/ti/k3-j721e-main.dtsi index 10c8a5fb4ee2927749c5b92413b27926c05be5af..2ded1ee1a85410b33fbc2d90a096be2b0f574353 100644 --- a/arch/arm64/boot/dts/ti/k3-j721e-main.dtsi +++ b/arch/arm64/boot/dts/ti/k3-j721e-main.dtsi @@ -548,6 +548,24 @@ pinctrl-single,function-mask = <0xffffffff>; }; + /* TIMERIO pad input CTRLMMR_TIMER*_CTRL registers */ + main_timerio_input: pinctrl@104200 { + compatible = "pinctrl-single"; + reg = <0x00 0x104200 0x00 0x50>; + #pinctrl-cells = <1>; + pinctrl-single,register-width = <32>; + pinctrl-single,function-mask = <0x00000007>; + }; + + /* TIMERIO pad output CTCTRLMMR_TIMERIO*_CTRL registers */ + main_timerio_output: pinctrl@104280 { + compatible = "pinctrl-single"; + reg = <0x00 0x104280 0x00 0x20>; + #pinctrl-cells = <1>; + pinctrl-single,register-width = <32>; + pinctrl-single,function-mask = <0x0000001f>; + }; + serdes_wiz0: wiz@5000000 { compatible = "ti,j721e-wiz-16g"; #address-cells = <1>; @@ -814,26 +832,7 @@ ranges = <0x01000000 0x0 0x10001000 0x0 0x10001000 0x0 0x0010000>, <0x02000000 0x0 0x10011000 0x0 0x10011000 0x0 0x7fef000>; dma-ranges = <0x02000000 0x0 0x0 0x0 0x0 0x10000 0x0>; - }; - - pcie0_ep: pcie-ep@2900000 { - compatible = "ti,j721e-pcie-ep"; - reg = <0x00 0x02900000 0x00 0x1000>, - <0x00 0x02907000 0x00 0x400>, - <0x00 0x0d000000 0x00 0x00800000>, - <0x00 0x10000000 0x00 0x08000000>; - reg-names = "intd_cfg", "user_cfg", "reg", "mem"; - interrupt-names = "link_state"; - interrupts = ; - ti,syscon-pcie-ctrl = <&scm_conf 0x4070>; - max-link-speed = <3>; - num-lanes = <2>; - power-domains = <&k3_pds 239 TI_SCI_PD_EXCLUSIVE>; - clocks = <&k3_clks 239 1>; - clock-names = "fck"; - max-functions = /bits/ 8 <6>; - max-virtual-functions = /bits/ 8 <4 4 4 4 0 0>; - dma-coherent; + status = "disabled"; }; pcie1_rc: pcie@2910000 { @@ -862,26 +861,7 @@ ranges = <0x01000000 0x0 0x18001000 0x0 0x18001000 0x0 0x0010000>, <0x02000000 0x0 0x18011000 0x0 0x18011000 0x0 0x7fef000>; dma-ranges = <0x02000000 0x0 0x0 0x0 0x0 0x10000 0x0>; - }; - - pcie1_ep: pcie-ep@2910000 { - compatible = "ti,j721e-pcie-ep"; - reg = <0x00 0x02910000 0x00 0x1000>, - <0x00 0x02917000 0x00 0x400>, - <0x00 0x0d800000 0x00 0x00800000>, - <0x00 0x18000000 0x00 0x08000000>; - reg-names = "intd_cfg", "user_cfg", "reg", "mem"; - interrupt-names = "link_state"; - interrupts = ; - ti,syscon-pcie-ctrl = <&scm_conf 0x4074>; - max-link-speed = <3>; - num-lanes = <2>; - power-domains = <&k3_pds 240 TI_SCI_PD_EXCLUSIVE>; - clocks = <&k3_clks 240 1>; - clock-names = "fck"; - max-functions = /bits/ 8 <6>; - max-virtual-functions = /bits/ 8 <4 4 4 4 0 0>; - dma-coherent; + status = "disabled"; }; pcie2_rc: pcie@2920000 { @@ -910,26 +890,7 @@ ranges = <0x01000000 0x0 0x00001000 0x44 0x00001000 0x0 0x0010000>, <0x02000000 0x0 0x00011000 0x44 0x00011000 0x0 0x7fef000>; dma-ranges = <0x02000000 0x0 0x0 0x0 0x0 0x10000 0x0>; - }; - - pcie2_ep: pcie-ep@2920000 { - compatible = "ti,j721e-pcie-ep"; - reg = <0x00 0x02920000 0x00 0x1000>, - <0x00 0x02927000 0x00 0x400>, - <0x00 0x0e000000 0x00 0x00800000>, - <0x44 0x00000000 0x00 0x08000000>; - reg-names = "intd_cfg", "user_cfg", "reg", "mem"; - interrupt-names = "link_state"; - interrupts = ; - ti,syscon-pcie-ctrl = <&scm_conf 0x4078>; - max-link-speed = <3>; - num-lanes = <2>; - power-domains = <&k3_pds 241 TI_SCI_PD_EXCLUSIVE>; - clocks = <&k3_clks 241 1>; - clock-names = "fck"; - max-functions = /bits/ 8 <6>; - max-virtual-functions = /bits/ 8 <4 4 4 4 0 0>; - dma-coherent; + status = "disabled"; }; pcie3_rc: pcie@2930000 { @@ -958,28 +919,7 @@ ranges = <0x01000000 0x0 0x00001000 0x44 0x10001000 0x0 0x0010000>, <0x02000000 0x0 0x00011000 0x44 0x10011000 0x0 0x7fef000>; dma-ranges = <0x02000000 0x0 0x0 0x0 0x0 0x10000 0x0>; - }; - - pcie3_ep: pcie-ep@2930000 { - compatible = "ti,j721e-pcie-ep"; - reg = <0x00 0x02930000 0x00 0x1000>, - <0x00 0x02937000 0x00 0x400>, - <0x00 0x0e800000 0x00 0x00800000>, - <0x44 0x10000000 0x00 0x08000000>; - reg-names = "intd_cfg", "user_cfg", "reg", "mem"; - interrupt-names = "link_state"; - interrupts = ; - ti,syscon-pcie-ctrl = <&scm_conf 0x407c>; - max-link-speed = <3>; - num-lanes = <2>; - power-domains = <&k3_pds 242 TI_SCI_PD_EXCLUSIVE>; - clocks = <&k3_clks 242 1>; - clock-names = "fck"; - max-functions = /bits/ 8 <6>; - max-virtual-functions = /bits/ 8 <4 4 4 4 0 0>; - dma-coherent; - #address-cells = <2>; - #size-cells = <2>; + status = "disabled"; }; serdes_wiz4: wiz@5050000 { @@ -1023,6 +963,246 @@ }; }; + main_timer0: timer@2400000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x2400000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 49 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 49 1>; + assigned-clock-parents = <&k3_clks 49 2>; + power-domains = <&k3_pds 49 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer1: timer@2410000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x2410000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 50 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 50 1>, <&k3_clks 327 0>; + assigned-clock-parents = <&k3_clks 50 2>, <&k3_clks 327 1>; + power-domains = <&k3_pds 50 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer2: timer@2420000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x2420000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 51 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 51 1>; + assigned-clock-parents = <&k3_clks 51 2>; + power-domains = <&k3_pds 51 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer3: timer@2430000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x2430000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 52 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 52 1>, <&k3_clks 328 0>; + assigned-clock-parents = <&k3_clks 52 2>, <&k3_clks 328 1>; + power-domains = <&k3_pds 52 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer4: timer@2440000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x2440000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 53 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 53 1>; + assigned-clock-parents = <&k3_clks 53 2>; + power-domains = <&k3_pds 53 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer5: timer@2450000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x2450000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 54 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 54 1>, <&k3_clks 329 0>; + assigned-clock-parents = <&k3_clks 54 2>, <&k3_clks 329 1>; + power-domains = <&k3_pds 54 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer6: timer@2460000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x2460000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 55 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 55 1>; + assigned-clock-parents = <&k3_clks 55 2>; + power-domains = <&k3_pds 55 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer7: timer@2470000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x2470000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 57 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 57 1>, <&k3_clks 330 0>; + assigned-clock-parents = <&k3_clks 57 2>, <&k3_clks 330 1>; + power-domains = <&k3_pds 57 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer8: timer@2480000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x2480000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 58 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 58 1>; + assigned-clock-parents = <&k3_clks 58 2>; + power-domains = <&k3_pds 58 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer9: timer@2490000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x2490000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 59 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 59 1>, <&k3_clks 331 0>; + assigned-clock-parents = <&k3_clks 59 2>, <&k3_clks 331 1>; + power-domains = <&k3_pds 59 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer10: timer@24a0000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x24a0000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 60 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 60 1>; + assigned-clock-parents = <&k3_clks 60 2>; + power-domains = <&k3_pds 60 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer11: timer@24b0000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x24b0000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 62 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 62 1>, <&k3_clks 332 0>; + assigned-clock-parents = <&k3_clks 62 2>, <&k3_clks 332 1>; + power-domains = <&k3_pds 62 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer12: timer@24c0000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x24c0000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 63 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 63 1>; + assigned-clock-parents = <&k3_clks 63 2>; + power-domains = <&k3_pds 63 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer13: timer@24d0000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x24d0000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 64 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 64 1>, <&k3_clks 333 0>; + assigned-clock-parents = <&k3_clks 64 2>, <&k3_clks 333 1>; + power-domains = <&k3_pds 64 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer14: timer@24e0000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x24e0000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 65 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 65 1>; + assigned-clock-parents = <&k3_clks 65 2>; + power-domains = <&k3_pds 65 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer15: timer@24f0000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x24f0000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 66 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 66 1>, <&k3_clks 334 0>; + assigned-clock-parents = <&k3_clks 66 2>, <&k3_clks 334 1>; + power-domains = <&k3_pds 66 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer16: timer@2500000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x2500000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 67 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 67 1>; + assigned-clock-parents = <&k3_clks 67 2>; + power-domains = <&k3_pds 67 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer17: timer@2510000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x2510000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 68 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 68 1>, <&k3_clks 335 0>; + assigned-clock-parents = <&k3_clks 68 2>, <&k3_clks 335 1>; + power-domains = <&k3_pds 68 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer18: timer@2520000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x2520000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 69 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 69 1>; + assigned-clock-parents = <&k3_clks 69 2>; + power-domains = <&k3_pds 69 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer19: timer@2530000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x2530000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 70 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 70 1>, <&k3_clks 336 0>; + assigned-clock-parents = <&k3_clks 70 2>, <&k3_clks 336 1>; + power-domains = <&k3_pds 70 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + main_uart0: serial@2800000 { compatible = "ti,j721e-uart", "ti,am654-uart"; reg = <0x00 0x02800000 0x00 0x100>; @@ -1287,8 +1467,8 @@ bus-width = <8>; mmc-hs200-1_8v; mmc-ddr-1_8v; - ti,otap-del-sel-legacy = <0xf>; - ti,otap-del-sel-mmc-hs = <0xf>; + ti,otap-del-sel-legacy = <0x0>; + ti,otap-del-sel-mmc-hs = <0x0>; ti,otap-del-sel-ddr52 = <0x5>; ti,otap-del-sel-hs200 = <0x6>; ti,otap-del-sel-hs400 = <0x0>; @@ -1309,11 +1489,12 @@ assigned-clocks = <&k3_clks 92 0>; assigned-clock-parents = <&k3_clks 92 1>; ti,otap-del-sel-legacy = <0x0>; - ti,otap-del-sel-sd-hs = <0xf>; + ti,otap-del-sel-sd-hs = <0x0>; ti,otap-del-sel-sdr12 = <0xf>; ti,otap-del-sel-sdr25 = <0xf>; ti,otap-del-sel-sdr50 = <0xc>; ti,otap-del-sel-ddr50 = <0xc>; + ti,otap-del-sel-sdr104 = <0x5>; ti,itap-del-sel-legacy = <0x0>; ti,itap-del-sel-sd-hs = <0x0>; ti,itap-del-sel-sdr12 = <0x0>; @@ -1335,11 +1516,12 @@ assigned-clocks = <&k3_clks 93 0>; assigned-clock-parents = <&k3_clks 93 1>; ti,otap-del-sel-legacy = <0x0>; - ti,otap-del-sel-sd-hs = <0xf>; + ti,otap-del-sel-sd-hs = <0x0>; ti,otap-del-sel-sdr12 = <0xf>; ti,otap-del-sel-sdr25 = <0xf>; ti,otap-del-sel-sdr50 = <0xc>; ti,otap-del-sel-ddr50 = <0xc>; + ti,otap-del-sel-sdr104 = <0x5>; ti,itap-del-sel-legacy = <0x0>; ti,itap-del-sel-sd-hs = <0x0>; ti,itap-del-sel-sdr12 = <0x0>; @@ -2091,6 +2273,7 @@ #address-cells = <1>; #size-cells = <0>; bus_freq = <1000000>; + status = "disabled"; }; }; @@ -2232,6 +2415,7 @@ #address-cells = <1>; #size-cells = <0>; bus_freq = <1000000>; + status = "disabled"; }; }; @@ -2532,4 +2716,10 @@ clocks = <&k3_clks 273 1>; status = "disabled"; }; + + main_esm: esm@700000 { + compatible = "ti,j721e-esm"; + reg = <0x0 0x700000 0x0 0x1000>; + ti,esm-pins = <344>, <345>; + }; }; diff --git a/arch/arm64/boot/dts/ti/k3-j721e-mcu-wakeup.dtsi b/arch/arm64/boot/dts/ti/k3-j721e-mcu-wakeup.dtsi index 24e8125db8c447c8a4ab7f261da558f9e15d6919..ea5b9e104491f408e31f67c104329738184997b6 100644 --- a/arch/arm64/boot/dts/ti/k3-j721e-mcu-wakeup.dtsi +++ b/arch/arm64/boot/dts/ti/k3-j721e-mcu-wakeup.dtsi @@ -62,6 +62,28 @@ pinctrl-single,function-mask = <0xffffffff>; }; + /* MCU_TIMERIO pad input CTRLMMR_MCU_TIMER*_CTRL registers */ + mcu_timerio_input: pinctrl@40f04200 { + compatible = "pinctrl-single"; + reg = <0x00 0x40f04200 0x00 0x28>; + #pinctrl-cells = <1>; + pinctrl-single,register-width = <32>; + pinctrl-single,function-mask = <0x0000000f>; + /* Non-MPU Firmware usage */ + status = "reserved"; + }; + + /* MCU_TIMERIO pad output CTRLMMR_MCU_TIMERIO*_CTRL registers */ + mcu_timerio_output: pinctrl@40f04280 { + compatible = "pinctrl-single"; + reg = <0x00 0x40f04280 0x00 0x28>; + #pinctrl-cells = <1>; + pinctrl-single,register-width = <32>; + pinctrl-single,function-mask = <0x0000000f>; + /* Non-MPU Firmware usage */ + status = "reserved"; + }; + mcu_ram: sram@41c00000 { compatible = "mmio-sram"; reg = <0x00 0x41c00000 0x00 0x100000>; @@ -70,6 +92,145 @@ #size-cells = <1>; }; + mcu_timer0: timer@40400000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x40400000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 35 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 35 1>; + assigned-clock-parents = <&k3_clks 35 2>; + power-domains = <&k3_pds 35 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + /* Non-MPU Firmware usage */ + status = "reserved"; + }; + + mcu_timer1: timer@40410000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x40410000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 71 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 71 1>, <&k3_clks 322 0>; + assigned-clock-parents = <&k3_clks 71 2>, <&k3_clks 322 1>; + power-domains = <&k3_pds 71 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + /* Non-MPU Firmware usage */ + status = "reserved"; + }; + + mcu_timer2: timer@40420000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x40420000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 72 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 72 1>; + assigned-clock-parents = <&k3_clks 72 2>; + power-domains = <&k3_pds 72 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + /* Non-MPU Firmware usage */ + status = "reserved"; + }; + + mcu_timer3: timer@40430000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x40430000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 73 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 73 1>, <&k3_clks 323 0>; + assigned-clock-parents = <&k3_clks 73 2>, <&k3_clks 323 1>; + power-domains = <&k3_pds 73 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + /* Non-MPU Firmware usage */ + status = "reserved"; + }; + + mcu_timer4: timer@40440000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x40440000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 74 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 74 1>; + assigned-clock-parents = <&k3_clks 74 2>; + power-domains = <&k3_pds 74 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + /* Non-MPU Firmware usage */ + status = "reserved"; + }; + + mcu_timer5: timer@40450000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x40450000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 75 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 75 1>, <&k3_clks 324 0>; + assigned-clock-parents = <&k3_clks 75 2>, <&k3_clks 324 1>; + power-domains = <&k3_pds 75 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + /* Non-MPU Firmware usage */ + status = "reserved"; + }; + + mcu_timer6: timer@40460000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x40460000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 76 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 76 1>; + assigned-clock-parents = <&k3_clks 76 2>; + power-domains = <&k3_pds 76 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + /* Non-MPU Firmware usage */ + status = "reserved"; + }; + + mcu_timer7: timer@40470000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x40470000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 77 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 77 1>, <&k3_clks 325 0>; + assigned-clock-parents = <&k3_clks 77 2>, <&k3_clks 325 1>; + power-domains = <&k3_pds 77 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + /* Non-MPU Firmware usage */ + status = "reserved"; + }; + + mcu_timer8: timer@40480000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x40480000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 78 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 78 1>; + assigned-clock-parents = <&k3_clks 78 2>; + power-domains = <&k3_pds 78 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + /* Non-MPU Firmware usage */ + status = "reserved"; + }; + + mcu_timer9: timer@40490000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x40490000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 79 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 79 1>, <&k3_clks 326 0>; + assigned-clock-parents = <&k3_clks 79 2>, <&k3_clks 326 1>; + power-domains = <&k3_pds 79 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + /* Non-MPU Firmware usage */ + status = "reserved"; + }; wkup_uart0: serial@42300000 { compatible = "ti,j721e-uart", "ti,am654-uart"; reg = <0x00 0x42300000 0x00 0x100>; @@ -181,6 +342,27 @@ #size-cells = <2>; ranges; + hbmc_mux: mux-controller@47000004 { + compatible = "reg-mux"; + reg = <0x00 0x47000004 0x00 0x2>; + #mux-control-cells = <1>; + mux-reg-masks = <0x4 0x2>; /* HBMC select */ + }; + + hbmc: hyperbus@47034000 { + compatible = "ti,am654-hbmc"; + reg = <0x00 0x47034000 0x00 0x100>, + <0x05 0x00000000 0x01 0x0000000>; + power-domains = <&k3_pds 102 TI_SCI_PD_EXCLUSIVE>; + clocks = <&k3_clks 102 0>; + assigned-clocks = <&k3_clks 102 5>; + assigned-clock-rates = <333333333>; + #address-cells = <2>; + #size-cells = <1>; + mux-controls = <&hbmc_mux 0>; + status = "disabled"; + }; + ospi0: spi@47040000 { compatible = "ti,am654-ospi", "cdns,qspi-nor"; reg = <0x0 0x47040000 0x0 0x100>, @@ -296,6 +478,21 @@ }; }; + secure_proxy_mcu: mailbox@2a480000 { + compatible = "ti,am654-secure-proxy"; + #mbox-cells = <1>; + reg-names = "target_data", "rt", "scfg"; + reg = <0x0 0x2a480000 0x0 0x80000>, + <0x0 0x2a380000 0x0 0x80000>, + <0x0 0x2a400000 0x0 0x80000>; + /* + * Marked Disabled: + * Node is incomplete as it is meant for bootloaders and + * firmware on non-MPU processors + */ + status = "disabled"; + }; + mcu_cpsw: ethernet@46000000 { compatible = "ti,j721e-cpsw-nuss"; #address-cells = <2>; @@ -458,4 +655,13 @@ clocks = <&k3_clks 276 0>; status = "disabled"; }; + + wkup_vtm0: temperature-sensor@42040000 { + compatible = "ti,j721e-vtm"; + reg = <0x00 0x42040000 0x00 0x350>, + <0x00 0x42050000 0x00 0x350>, + <0x00 0x43000300 0x00 0x10>; + power-domains = <&k3_pds 154 TI_SCI_PD_EXCLUSIVE>; + #thermal-sensor-cells = <1>; + }; }; diff --git a/arch/arm64/boot/dts/ti/k3-j721e-sk.dts b/arch/arm64/boot/dts/ti/k3-j721e-sk.dts index f650a7fd66b4275773792b27d2dfa346116363a2..0ee4f38ec8f0379a11c9d227b059dd7334df911f 100644 --- a/arch/arm64/boot/dts/ti/k3-j721e-sk.dts +++ b/arch/arm64/boot/dts/ti/k3-j721e-sk.dts @@ -16,9 +16,17 @@ compatible = "ti,j721e-sk", "ti,j721e"; model = "Texas Instruments J721E SK"; + aliases { + serial0 = &wkup_uart0; + serial1 = &mcu_uart0; + serial2 = &main_uart0; + serial3 = &main_uart1; + ethernet0 = &cpsw_port1; + mmc1 = &main_sdhci1; + }; + chosen { stdout-path = "serial2:115200n8"; - bootargs = "console=ttyS2,115200n8 earlycon=ns16550a,mmio32,0x02800000"; }; memory@80000000 { @@ -281,7 +289,7 @@ }; &main_pmx0 { - main_mmc1_pins_default: main-mmc1-pins-default { + main_mmc1_pins_default: main-mmc1-default-pins { pinctrl-single,pins = < J721E_IOPAD(0x254, PIN_INPUT, 0) /* (R29) MMC1_CMD */ J721E_IOPAD(0x250, PIN_INPUT, 0) /* (P25) MMC1_CLK */ @@ -294,7 +302,7 @@ >; }; - main_uart0_pins_default: main-uart0-pins-default { + main_uart0_pins_default: main-uart0-default-pins { pinctrl-single,pins = < J721E_IOPAD(0x1f0, PIN_INPUT, 0) /* (AC2) UART0_CTSn */ J721E_IOPAD(0x1f4, PIN_OUTPUT, 0) /* (AB1) UART0_RTSn */ @@ -303,53 +311,60 @@ >; }; - main_i2c0_pins_default: main-i2c0-pins-default { + main_uart1_pins_default: main-uart1-default-pins { + pinctrl-single,pins = < + J721E_IOPAD(0x1f8, PIN_INPUT, 0) /* (AA4) UART1_RXD */ + J721E_IOPAD(0x1fc, PIN_OUTPUT, 0) /* (AB4) UART1_TXD */ + >; + }; + + main_i2c0_pins_default: main-i2c0-default-pins { pinctrl-single,pins = < J721E_IOPAD(0x220, PIN_INPUT_PULLUP, 0) /* (AC5) I2C0_SCL */ J721E_IOPAD(0x224, PIN_INPUT_PULLUP, 0) /* (AA5) I2C0_SDA */ >; }; - main_i2c1_pins_default: main-i2c1-pins-default { + main_i2c1_pins_default: main-i2c1-default-pins { pinctrl-single,pins = < J721E_IOPAD(0x228, PIN_INPUT_PULLUP, 0) /* (Y6) I2C1_SCL */ J721E_IOPAD(0x22c, PIN_INPUT_PULLUP, 0) /* (AA6) I2C1_SDA */ >; }; - main_i2c3_pins_default: main-i2c3-pins-default { + main_i2c3_pins_default: main-i2c3-default-pins { pinctrl-single,pins = < J721E_IOPAD(0x270, PIN_INPUT_PULLUP, 4) /* (T26) MMC2_CLK.I2C3_SCL */ J721E_IOPAD(0x274, PIN_INPUT_PULLUP, 4) /* (T25) MMC2_CMD.I2C3_SDA */ >; }; - main_usbss0_pins_default: main-usbss0-pins-default { + main_usbss0_pins_default: main-usbss0-default-pins { pinctrl-single,pins = < J721E_IOPAD(0x290, PIN_OUTPUT, 0) /* (U6) USB0_DRVVBUS */ J721E_IOPAD(0x210, PIN_INPUT, 7) /* (W3) MCAN1_RX.GPIO1_3 */ >; }; - main_usbss1_pins_default: main-usbss1-pins-default { + main_usbss1_pins_default: main-usbss1-default-pins { pinctrl-single,pins = < J721E_IOPAD(0x214, PIN_OUTPUT, 4) /* (V4) MCAN1_TX.USB1_DRVVBUS */ >; }; - dp0_pins_default: dp0-pins-default { + dp0_pins_default: dp0-default-pins { pinctrl-single,pins = < J721E_IOPAD(0x1c4, PIN_INPUT, 5) /* SPI0_CS1.DP0_HPD */ >; }; - dp_pwr_en_pins_default: dp-pwr-en-pins-default { + dp_pwr_en_pins_default: dp-pwr-en-default-pins { pinctrl-single,pins = < J721E_IOPAD(0x1c0, PIN_INPUT, 7) /* (AA2) SPI0_CS0.GPIO0_111 */ >; }; - dss_vout0_pins_default: dss-vout0-pins-default { + dss_vout0_pins_default: dss-vout0-default-pins { pinctrl-single,pins = < J721E_IOPAD(0x58, PIN_OUTPUT, 10) /* (AE22) PRG1_PRU1_GPO0.VOUT0_DATA0 */ J721E_IOPAD(0x5c, PIN_OUTPUT, 10) /* (AG23) PRG1_PRU1_GPO1.VOUT0_DATA1 */ @@ -382,33 +397,33 @@ >; }; - hdmi_hpd_pins_default: hdmi-hpd-pins-default { + hdmi_hpd_pins_default: hdmi-hpd-default-pins { pinctrl-single,pins = < J721E_IOPAD(0x204, PIN_INPUT, 7) /* (AD5) UART1_RTSn.GPIO1_0 */ >; }; - hdmi_pdn_pins_default: hdmi-pdn-pins-default { + hdmi_pdn_pins_default: hdmi-pdn-default-pins { pinctrl-single,pins = < J721E_IOPAD(0x200, PIN_INPUT, 7) /* (AC4) UART1_CTSn.GPIO0_127 */ >; }; /* Reset for M.2 E Key slot on PCIe0 */ - ekey_reset_pins_default: ekey-reset-pns-pins-default { + ekey_reset_pins_default: ekey-reset-pns-default-pins { pinctrl-single,pins = < J721E_IOPAD(0x124, PIN_INPUT, 7) /* (Y24) PRG0_PRU1_GPO9.GPIO0_72 */ >; }; - main_i2c5_pins_default: main-i2c5-pins-default { + main_i2c5_pins_default: main-i2c5-default-pins { pinctrl-single,pins = < J721E_IOPAD(0x150, PIN_INPUT_PULLUP, 2) /* (Y26) PRG0_MDIO0_MDIO.I2C5_SCL */ J721E_IOPAD(0x154, PIN_INPUT_PULLUP, 2) /* (AA27) PRG0_MDIO0_MDC.I2C5_SDA */ >; }; - rpi_header_gpio0_pins_default: rpi-header-gpio0-pins-default { + rpi_header_gpio0_pins_default: rpi-header-gpio0-default-pins { pinctrl-single,pins = < J721E_IOPAD(0x01C, PIN_INPUT, 7) /* (AD22) PRG1_PRU0_GPO6.GPIO0_7 */ J721E_IOPAD(0x120, PIN_INPUT, 7) /* (AA28) PRG0_PRU1_GPO8.GPIO0_71 */ @@ -436,7 +451,7 @@ >; }; - rpi_header_gpio1_pins_default: rpi-header-gpio1-pins-default { + rpi_header_gpio1_pins_default: rpi-header-gpio1-default-pins { pinctrl-single,pins = < J721E_IOPAD(0x234, PIN_INPUT, 7) /* (U3) EXT_REFCLK1.GPIO1_12 */ >; @@ -444,7 +459,7 @@ }; &wkup_pmx0 { - mcu_cpsw_pins_default: mcu-cpsw-pins-default { + mcu_cpsw_pins_default: mcu-cpsw-default-pins { pinctrl-single,pins = < J721E_WKUP_IOPAD(0x84, PIN_INPUT, 0) /* (B24) MCU_RGMII1_RD0 */ J721E_WKUP_IOPAD(0x80, PIN_INPUT, 0) /* (A24) MCU_RGMII1_RD1 */ @@ -461,14 +476,14 @@ >; }; - mcu_mdio_pins_default: mcu-mdio1-pins-default { + mcu_mdio_pins_default: mcu-mdio1-default-pins { pinctrl-single,pins = < J721E_WKUP_IOPAD(0x8c, PIN_OUTPUT, 0) /* (F23) MCU_MDIO0_MDC */ J721E_WKUP_IOPAD(0x88, PIN_INPUT, 0) /* (E23) MCU_MDIO0_MDIO */ >; }; - mcu_fss0_ospi0_pins_default: mcu-fss0-ospi0-pins-default { + mcu_fss0_ospi0_pins_default: mcu-fss0-ospi0-default-pins { pinctrl-single,pins = < J721E_WKUP_IOPAD(0x0, PIN_OUTPUT, 0) /* (E20) MCU_OSPI0_CLK */ J721E_WKUP_IOPAD(0x2c, PIN_OUTPUT, 0) /* (F19) MCU_OSPI0_CSn0 */ @@ -484,19 +499,35 @@ >; }; - vdd_mmc1_en_pins_default: vdd-mmc1-en-pins-default { + vdd_mmc1_en_pins_default: vdd-mmc1-en-default-pins { pinctrl-single,pins = < J721E_WKUP_IOPAD(0xd0, PIN_OUTPUT, 7) /* (G27) WKUP_GPIO0_8 */ >; }; - vdd_sd_dv_alt_pins_default: vdd-sd-dv-alt-pins-default { + vdd_sd_dv_alt_pins_default: vdd-sd-dv-alt-default-pins { pinctrl-single,pins = < J721E_WKUP_IOPAD(0xd4, PIN_OUTPUT, 7) /* (G26) WKUP_GPIO0_9 */ >; }; - wkup_i2c0_pins_default: wkup-i2c0-pins-default { + wkup_uart0_pins_default: wkup-uart0-default-pins { + pinctrl-single,pins = < + J721E_WKUP_IOPAD(0xa0, PIN_INPUT, 0) /* (J29) WKUP_UART0_RXD */ + J721E_WKUP_IOPAD(0xa4, PIN_OUTPUT, 0) /* (J28) WKUP_UART0_TXD */ + >; + }; + + mcu_uart0_pins_default: mcu-uart0-default-pins { + pinctrl-single,pins = < + J721E_WKUP_IOPAD(0xf0, PIN_INPUT, 2) /* (D26) MCU_I3C0_SCL.MCU_UART0_CTSn */ + J721E_WKUP_IOPAD(0xf4, PIN_OUTPUT, 2)/* (D25) MCU_I3C0_SDA.MCU_UART0_RTSn */ + J721E_WKUP_IOPAD(0xe4, PIN_INPUT, 0) /* (H28) WKUP_GPIO0_13.MCU_UART0_RXD */ + J721E_WKUP_IOPAD(0xe0, PIN_OUTPUT, 0)/* (G29) WKUP_GPIO0_12.MCU_UART0_TXD */ + >; + }; + + wkup_i2c0_pins_default: wkup-i2c0-default-pins { pinctrl-single,pins = < J721E_WKUP_IOPAD(0xf8, PIN_INPUT_PULLUP, 0) /* (J25) WKUP_I2C0_SCL */ J721E_WKUP_IOPAD(0xfc, PIN_INPUT_PULLUP, 0) /* (H24) WKUP_I2C0_SDA */ @@ -504,7 +535,7 @@ }; /* Reset for M.2 M Key slot on PCIe1 */ - mkey_reset_pins_default: mkey-reset-pns-pins-default { + mkey_reset_pins_default: mkey-reset-pns-default-pins { pinctrl-single,pins = < J721E_WKUP_IOPAD(0xdc, PIN_INPUT, 7) /* (H27) WKUP_GPIO0_11 */ >; @@ -514,11 +545,27 @@ &wkup_uart0 { /* Wakeup UART is used by System firmware */ status = "reserved"; + pinctrl-names = "default"; + pinctrl-0 = <&wkup_uart0_pins_default>; +}; + +&wkup_i2c0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&wkup_i2c0_pins_default>; + clock-frequency = <400000>; + + eeprom@51 { + /* AT24C512C-MAHM-T */ + compatible = "atmel,24c512"; + reg = <0x51>; + }; }; &mcu_uart0 { status = "okay"; - /* Default pinmux */ + pinctrl-names = "default"; + pinctrl-0 = <&mcu_uart0_pins_default>; }; &main_uart0 { @@ -531,7 +578,8 @@ &main_uart1 { status = "okay"; - /* Default pinmux */ + pinctrl-names = "default"; + pinctrl-0 = <&main_uart1_pins_default>; }; &main_sdhci0 { @@ -569,6 +617,52 @@ cdns,tchsh-ns = <60>; cdns,tslch-ns = <60>; cdns,read-delay = <4>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "ospi.tiboot3"; + reg = <0x0 0x80000>; + }; + + partition@80000 { + label = "ospi.tispl"; + reg = <0x80000 0x200000>; + }; + + partition@280000 { + label = "ospi.u-boot"; + reg = <0x280000 0x400000>; + }; + + partition@680000 { + label = "ospi.env"; + reg = <0x680000 0x40000>; + }; + + partition@6c0000 { + label = "ospi.sysfw"; + reg = <0x6c0000 0x100000>; + }; + + partition@7c0000 { + label = "ospi.env.backup"; + reg = <0x7c0000 0x40000>; + }; + + partition@800000 { + label = "ospi.rootfs"; + reg = <0x800000 0x37c0000>; + }; + + partition@3fc0000 { + label = "ospi.phypattern"; + reg = <0x3fc0000 0x40000>; + }; + }; }; }; @@ -781,7 +875,7 @@ &mcu_cpsw { pinctrl-names = "default"; - pinctrl-0 = <&mcu_cpsw_pins_default &mcu_mdio_pins_default>; + pinctrl-0 = <&mcu_cpsw_pins_default>, <&mcu_mdio_pins_default>; }; &davinci_mdio { @@ -872,6 +966,7 @@ }; &pcie0_rc { + status = "okay"; pinctrl-names = "default"; pinctrl-0 = <&ekey_reset_pins_default>; reset-gpios = <&main_gpio0 72 GPIO_ACTIVE_HIGH>; @@ -882,6 +977,7 @@ }; &pcie1_rc { + status = "okay"; pinctrl-names = "default"; pinctrl-0 = <&mkey_reset_pins_default>; reset-gpios = <&wkup_gpio0 11 GPIO_ACTIVE_HIGH>; @@ -891,48 +987,6 @@ num-lanes = <2>; }; -&pcie2_rc { - /* Unused */ - status = "disabled"; -}; - -&pcie0_ep { - status = "disabled"; - phys = <&serdes0_pcie_link>; - phy-names = "pcie-phy"; - num-lanes = <1>; -}; - -&pcie1_ep { - status = "disabled"; - phys = <&serdes1_pcie_link>; - phy-names = "pcie-phy"; - num-lanes = <2>; -}; - -&pcie2_ep { - /* Unused */ - status = "disabled"; -}; - -&pcie3_rc { - /* Unused */ - status = "disabled"; -}; - -&pcie3_ep { - /* Unused */ - status = "disabled"; -}; - -&icssg0_mdio { - status = "disabled"; -}; - -&icssg1_mdio { - status = "disabled"; -}; - &ufs_wrapper { status = "disabled"; }; @@ -1008,55 +1062,55 @@ }; &mcu_r5fss0_core0 { - mboxes = <&mailbox0_cluster0 &mbox_mcu_r5fss0_core0>; + mboxes = <&mailbox0_cluster0>, <&mbox_mcu_r5fss0_core0>; memory-region = <&mcu_r5fss0_core0_dma_memory_region>, <&mcu_r5fss0_core0_memory_region>; }; &mcu_r5fss0_core1 { - mboxes = <&mailbox0_cluster0 &mbox_mcu_r5fss0_core1>; + mboxes = <&mailbox0_cluster0>, <&mbox_mcu_r5fss0_core1>; memory-region = <&mcu_r5fss0_core1_dma_memory_region>, <&mcu_r5fss0_core1_memory_region>; }; &main_r5fss0_core0 { - mboxes = <&mailbox0_cluster1 &mbox_main_r5fss0_core0>; + mboxes = <&mailbox0_cluster1>, <&mbox_main_r5fss0_core0>; memory-region = <&main_r5fss0_core0_dma_memory_region>, <&main_r5fss0_core0_memory_region>; }; &main_r5fss0_core1 { - mboxes = <&mailbox0_cluster1 &mbox_main_r5fss0_core1>; + mboxes = <&mailbox0_cluster1>, <&mbox_main_r5fss0_core1>; memory-region = <&main_r5fss0_core1_dma_memory_region>, <&main_r5fss0_core1_memory_region>; }; &main_r5fss1_core0 { - mboxes = <&mailbox0_cluster2 &mbox_main_r5fss1_core0>; + mboxes = <&mailbox0_cluster2>, <&mbox_main_r5fss1_core0>; memory-region = <&main_r5fss1_core0_dma_memory_region>, <&main_r5fss1_core0_memory_region>; }; &main_r5fss1_core1 { - mboxes = <&mailbox0_cluster2 &mbox_main_r5fss1_core1>; + mboxes = <&mailbox0_cluster2>, <&mbox_main_r5fss1_core1>; memory-region = <&main_r5fss1_core1_dma_memory_region>, <&main_r5fss1_core1_memory_region>; }; &c66_0 { - mboxes = <&mailbox0_cluster3 &mbox_c66_0>; + mboxes = <&mailbox0_cluster3>, <&mbox_c66_0>; memory-region = <&c66_0_dma_memory_region>, <&c66_0_memory_region>; }; &c66_1 { - mboxes = <&mailbox0_cluster3 &mbox_c66_1>; + mboxes = <&mailbox0_cluster3>, <&mbox_c66_1>; memory-region = <&c66_1_dma_memory_region>, <&c66_1_memory_region>; }; &c71_0 { - mboxes = <&mailbox0_cluster4 &mbox_c71_0>; + mboxes = <&mailbox0_cluster4>, <&mbox_c71_0>; memory-region = <&c71_0_dma_memory_region>, <&c71_0_memory_region>; }; diff --git a/arch/arm64/boot/dts/ti/k3-j721e-som-p0.dtsi b/arch/arm64/boot/dts/ti/k3-j721e-som-p0.dtsi index e289d5b443568ec736c041155dbe4e13e2888d7c..38ae13cc3aa3edc32e51c4163acf7df8331ad672 100644 --- a/arch/arm64/boot/dts/ti/k3-j721e-som-p0.dtsi +++ b/arch/arm64/boot/dts/ti/k3-j721e-som-p0.dtsi @@ -1,6 +1,8 @@ // SPDX-License-Identifier: GPL-2.0 /* * Copyright (C) 2019-2020 Texas Instruments Incorporated - https://www.ti.com/ + * + * Product Link: https://www.ti.com/tool/J721EXSOMXEVM */ /dts-v1/; @@ -143,14 +145,14 @@ }; &wkup_pmx0 { - wkup_i2c0_pins_default: wkup-i2c0-pins-default { + wkup_i2c0_pins_default: wkup-i2c0-default-pins { pinctrl-single,pins = < J721E_WKUP_IOPAD(0xf8, PIN_INPUT_PULLUP, 0) /* (J25) WKUP_I2C0_SCL */ J721E_WKUP_IOPAD(0xfc, PIN_INPUT_PULLUP, 0) /* (H24) WKUP_I2C0_SDA */ >; }; - mcu_fss0_ospi0_pins_default: mcu-fss0-ospi0-pins-default { + mcu_fss0_ospi0_pins_default: mcu-fss0-ospi0-default-pins { pinctrl-single,pins = < J721E_WKUP_IOPAD(0x0000, PIN_OUTPUT, 0) /* MCU_OSPI0_CLK */ J721E_WKUP_IOPAD(0x0008, PIN_INPUT, 0) /* MCU_OSPI0_DQS */ @@ -165,6 +167,51 @@ J721E_WKUP_IOPAD(0x002c, PIN_OUTPUT, 0) /* MCU_OSPI0_CSn0 */ >; }; + + mcu_fss0_hpb0_pins_default: mcu-fss0-hpb0-default-pins { + pinctrl-single,pins = < + J721E_WKUP_IOPAD(0x0, PIN_OUTPUT, 1) /* MCU_HYPERBUS0_CK */ + J721E_WKUP_IOPAD(0x4, PIN_OUTPUT, 1) /* MCU_HYPERBUS0_CKn */ + J721E_WKUP_IOPAD(0x2c, PIN_OUTPUT, 1) /* MCU_HYPERBUS0_CSn0 */ + J721E_WKUP_IOPAD(0x54, PIN_OUTPUT, 3) /* MCU_HYPERBUS0_CSn1 */ + J721E_WKUP_IOPAD(0x30, PIN_OUTPUT, 1) /* MCU_HYPERBUS0_RESETn */ + J721E_WKUP_IOPAD(0x8, PIN_INPUT, 1) /* MCU_HYPERBUS0_RWDS */ + J721E_WKUP_IOPAD(0xc, PIN_INPUT, 1) /* MCU_HYPERBUS0_DQ0 */ + J721E_WKUP_IOPAD(0x10, PIN_INPUT, 1) /* MCU_HYPERBUS0_DQ1 */ + J721E_WKUP_IOPAD(0x14, PIN_INPUT, 1) /* MCU_HYPERBUS0_DQ2 */ + J721E_WKUP_IOPAD(0x18, PIN_INPUT, 1) /* MCU_HYPERBUS0_DQ3 */ + J721E_WKUP_IOPAD(0x1c, PIN_INPUT, 1) /* MCU_HYPERBUS0_DQ4 */ + J721E_WKUP_IOPAD(0x20, PIN_INPUT, 1) /* MCU_HYPERBUS0_DQ5 */ + J721E_WKUP_IOPAD(0x24, PIN_INPUT, 1) /* MCU_HYPERBUS0_DQ6 */ + J721E_WKUP_IOPAD(0x28, PIN_INPUT, 1) /* MCU_HYPERBUS0_DQ7 */ + >; + }; +}; + +&wkup_i2c0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&wkup_i2c0_pins_default>; + clock-frequency = <400000>; + + eeprom@50 { + /* CAV24C256WE-GT3 */ + compatible = "atmel,24c256"; + reg = <0x50>; + }; +}; + +&wkup_i2c0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&wkup_i2c0_pins_default>; + clock-frequency = <400000>; + + eeprom@50 { + /* CAV24C256WE-GT3 */ + compatible = "atmel,24c256"; + reg = <0x50>; + }; }; &ospi0 { @@ -182,6 +229,104 @@ cdns,tchsh-ns = <60>; cdns,tslch-ns = <60>; cdns,read-delay = <0>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "ospi.tiboot3"; + reg = <0x0 0x80000>; + }; + + partition@80000 { + label = "ospi.tispl"; + reg = <0x80000 0x200000>; + }; + + partition@280000 { + label = "ospi.u-boot"; + reg = <0x280000 0x400000>; + }; + + partition@680000 { + label = "ospi.env"; + reg = <0x680000 0x20000>; + }; + + partition@6a0000 { + label = "ospi.env.backup"; + reg = <0x6a0000 0x20000>; + }; + + partition@6c0000 { + label = "ospi.sysfw"; + reg = <0x6c0000 0x100000>; + }; + + partition@800000 { + label = "ospi.rootfs"; + reg = <0x800000 0x37c0000>; + }; + + partition@3fe0000 { + label = "ospi.phypattern"; + reg = <0x3fe0000 0x20000>; + }; + }; + }; +}; + +&hbmc { + /* OSPI and HBMC are muxed inside FSS, Bootloader will enable + * appropriate node based on board detection + */ + status = "disabled"; + pinctrl-names = "default"; + pinctrl-0 = <&mcu_fss0_hpb0_pins_default>; + ranges = <0x00 0x00 0x05 0x00000000 0x4000000>, /* 64MB Flash on CS0 */ + <0x01 0x00 0x05 0x04000000 0x800000>; /* 8MB RAM on CS1 */ + + flash@0,0 { + compatible = "cypress,hyperflash", "cfi-flash"; + reg = <0x00 0x00 0x4000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "hbmc.tiboot3"; + reg = <0x0 0x80000>; + }; + + partition@80000 { + label = "hbmc.tispl"; + reg = <0x80000 0x200000>; + }; + + partition@280000 { + label = "hbmc.u-boot"; + reg = <0x280000 0x400000>; + }; + + partition@680000 { + label = "hbmc.env"; + reg = <0x680000 0x40000>; + }; + + partition@6c0000 { + label = "hbmc.sysfw"; + reg = <0x6c0000 0x100000>; + }; + + partition@800000 { + label = "hbmc.rootfs"; + reg = <0x800000 0x3800000>; + }; + }; }; }; @@ -256,55 +401,55 @@ }; &mcu_r5fss0_core0 { - mboxes = <&mailbox0_cluster0 &mbox_mcu_r5fss0_core0>; + mboxes = <&mailbox0_cluster0>, <&mbox_mcu_r5fss0_core0>; memory-region = <&mcu_r5fss0_core0_dma_memory_region>, <&mcu_r5fss0_core0_memory_region>; }; &mcu_r5fss0_core1 { - mboxes = <&mailbox0_cluster0 &mbox_mcu_r5fss0_core1>; + mboxes = <&mailbox0_cluster0>, <&mbox_mcu_r5fss0_core1>; memory-region = <&mcu_r5fss0_core1_dma_memory_region>, <&mcu_r5fss0_core1_memory_region>; }; &main_r5fss0_core0 { - mboxes = <&mailbox0_cluster1 &mbox_main_r5fss0_core0>; + mboxes = <&mailbox0_cluster1>, <&mbox_main_r5fss0_core0>; memory-region = <&main_r5fss0_core0_dma_memory_region>, <&main_r5fss0_core0_memory_region>; }; &main_r5fss0_core1 { - mboxes = <&mailbox0_cluster1 &mbox_main_r5fss0_core1>; + mboxes = <&mailbox0_cluster1>, <&mbox_main_r5fss0_core1>; memory-region = <&main_r5fss0_core1_dma_memory_region>, <&main_r5fss0_core1_memory_region>; }; &main_r5fss1_core0 { - mboxes = <&mailbox0_cluster2 &mbox_main_r5fss1_core0>; + mboxes = <&mailbox0_cluster2>, <&mbox_main_r5fss1_core0>; memory-region = <&main_r5fss1_core0_dma_memory_region>, <&main_r5fss1_core0_memory_region>; }; &main_r5fss1_core1 { - mboxes = <&mailbox0_cluster2 &mbox_main_r5fss1_core1>; + mboxes = <&mailbox0_cluster2>, <&mbox_main_r5fss1_core1>; memory-region = <&main_r5fss1_core1_dma_memory_region>, <&main_r5fss1_core1_memory_region>; }; &c66_0 { - mboxes = <&mailbox0_cluster3 &mbox_c66_0>; + mboxes = <&mailbox0_cluster3>, <&mbox_c66_0>; memory-region = <&c66_0_dma_memory_region>, <&c66_0_memory_region>; }; &c66_1 { - mboxes = <&mailbox0_cluster3 &mbox_c66_1>; + mboxes = <&mailbox0_cluster3>, <&mbox_c66_1>; memory-region = <&c66_1_dma_memory_region>, <&c66_1_memory_region>; }; &c71_0 { - mboxes = <&mailbox0_cluster4 &mbox_c71_0>; + mboxes = <&mailbox0_cluster4>, <&mbox_c71_0>; memory-region = <&c71_0_dma_memory_region>, <&c71_0_memory_region>; }; diff --git a/arch/arm64/boot/dts/ti/k3-j721e-thermal.dtsi b/arch/arm64/boot/dts/ti/k3-j721e-thermal.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..c2523279001bf4730f6950d77503dcc291090b3a --- /dev/null +++ b/arch/arm64/boot/dts/ti/k3-j721e-thermal.dtsi @@ -0,0 +1,75 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include + +thermal_zones: thermal-zones { + wkup_thermal: wkup-thermal { + polling-delay-passive = <250>; /* milliseconds */ + polling-delay = <500>; /* milliseconds */ + thermal-sensors = <&wkup_vtm0 0>; + + trips { + wkup_crit: wkup-crit { + temperature = <125000>; /* milliCelsius */ + hysteresis = <2000>; /* milliCelsius */ + type = "critical"; + }; + }; + }; + + mpu_thermal: mpu-thermal { + polling-delay-passive = <250>; /* milliseconds */ + polling-delay = <500>; /* milliseconds */ + thermal-sensors = <&wkup_vtm0 1>; + + trips { + mpu_crit: mpu-crit { + temperature = <125000>; /* milliCelsius */ + hysteresis = <2000>; /* milliCelsius */ + type = "critical"; + }; + }; + }; + + c7x_thermal: c7x-thermal { + polling-delay-passive = <250>; /* milliseconds */ + polling-delay = <500>; /* milliseconds */ + thermal-sensors = <&wkup_vtm0 2>; + + trips { + c7x_crit: c7x-crit { + temperature = <125000>; /* milliCelsius */ + hysteresis = <2000>; /* milliCelsius */ + type = "critical"; + }; + }; + }; + + gpu_thermal: gpu-thermal { + polling-delay-passive = <250>; /* milliseconds */ + polling-delay = <500>; /* milliseconds */ + thermal-sensors = <&wkup_vtm0 3>; + + trips { + gpu_crit: gpu-crit { + temperature = <125000>; /* milliCelsius */ + hysteresis = <2000>; /* milliCelsius */ + type = "critical"; + }; + }; + }; + + r5f_thermal: r5f-thermal { + polling-delay-passive = <250>; /* milliseconds */ + polling-delay = <500>; /* milliseconds */ + thermal-sensors = <&wkup_vtm0 4>; + + trips { + r5f_crit: r5f-crit { + temperature = <125000>; /* milliCelsius */ + hysteresis = <2000>; /* milliCelsius */ + type = "critical"; + }; + }; + }; +}; diff --git a/arch/arm64/boot/dts/ti/k3-j721e.dtsi b/arch/arm64/boot/dts/ti/k3-j721e.dtsi index b912143b6a110873b9f4d9ec7688ed452d7197e8..a200810df54a548c9bd0d476e3a880e99ee53d2b 100644 --- a/arch/arm64/boot/dts/ti/k3-j721e.dtsi +++ b/arch/arm64/boot/dts/ti/k3-j721e.dtsi @@ -18,25 +18,6 @@ #address-cells = <2>; #size-cells = <2>; - aliases { - serial0 = &wkup_uart0; - serial1 = &mcu_uart0; - serial2 = &main_uart0; - serial3 = &main_uart1; - serial4 = &main_uart2; - serial5 = &main_uart3; - serial6 = &main_uart4; - serial7 = &main_uart5; - serial8 = &main_uart6; - serial9 = &main_uart7; - serial10 = &main_uart8; - serial11 = &main_uart9; - ethernet0 = &cpsw_port1; - mmc0 = &main_sdhci0; - mmc1 = &main_sdhci1; - mmc2 = &main_sdhci2; - }; - chosen { }; cpus { @@ -97,6 +78,7 @@ msmc_l3: l3-cache0 { compatible = "cache"; cache-level = <3>; + cache-unified; }; firmware { @@ -131,6 +113,7 @@ #size-cells = <2>; ranges = <0x00 0x00100000 0x00 0x00100000 0x00 0x00020000>, /* ctrl mmr */ <0x00 0x00600000 0x00 0x00600000 0x00 0x00031100>, /* GPIO */ + <0x00 0x00700000 0x00 0x00700000 0x00 0x00001000>, /* ESM */ <0x00 0x00900000 0x00 0x00900000 0x00 0x00012000>, /* serdes */ <0x00 0x00a40000 0x00 0x00a40000 0x00 0x00000800>, /* timesync router */ <0x00 0x06000000 0x00 0x06000000 0x00 0x00400000>, /* USBSS0 */ @@ -184,6 +167,8 @@ <0x07 0x00000000 0x07 0x00000000 0x01 0x00000000>; /* FSS OSPI1 data region 3*/ }; }; + + #include "k3-j721e-thermal.dtsi" }; /* Now include the peripherals for each bus segments */ diff --git a/arch/arm64/boot/dts/ti/k3-j721s2-common-proc-board.dts b/arch/arm64/boot/dts/ti/k3-j721s2-common-proc-board.dts index b4b9edfe2d12cc94ac5e08f3b7c60d9a07346796..04d4739d72457f5142db5a443e2ae64841fbad14 100644 --- a/arch/arm64/boot/dts/ti/k3-j721s2-common-proc-board.dts +++ b/arch/arm64/boot/dts/ti/k3-j721s2-common-proc-board.dts @@ -9,6 +9,9 @@ #include "k3-j721s2-som-p0.dtsi" #include +#include +#include +#include / { compatible = "ti,j721s2-evm", "ti,j721s2"; @@ -16,7 +19,6 @@ chosen { stdout-path = "serial2:115200n8"; - bootargs = "console=ttyS2,115200n8 earlycon=ns16550a,mmio32,2880000"; }; aliases { @@ -110,7 +112,7 @@ }; &main_pmx0 { - main_uart8_pins_default: main-uart8-pins-default { + main_uart8_pins_default: main-uart8-default-pins { pinctrl-single,pins = < J721S2_IOPAD(0x040, PIN_INPUT, 14) /* (AC28) MCASP0_AXR0.UART8_CTSn */ J721S2_IOPAD(0x044, PIN_OUTPUT, 14) /* (Y26) MCASP0_AXR1.UART8_RTSn */ @@ -119,14 +121,14 @@ >; }; - main_i2c3_pins_default: main-i2c3-pins-default { + main_i2c3_pins_default: main-i2c3-default-pins { pinctrl-single,pins = < J721S2_IOPAD(0x064, PIN_INPUT_PULLUP, 13) /* (W28) MCAN0_TX.I2C3_SCL */ J721S2_IOPAD(0x060, PIN_INPUT_PULLUP, 13) /* (AC27) MCASP2_AXR1.I2C3_SDA */ >; }; - main_mmc1_pins_default: main-mmc1-pins-default { + main_mmc1_pins_default: main-mmc1-default-pins { pinctrl-single,pins = < J721S2_IOPAD(0x104, PIN_INPUT, 0) /* (P23) MMC1_CLK */ J721S2_IOPAD(0x108, PIN_INPUT, 0) /* (N24) MMC1_CMD */ @@ -139,88 +141,126 @@ >; }; - vdd_sd_dv_pins_default: vdd-sd-dv-pins-default { + vdd_sd_dv_pins_default: vdd-sd-dv-default-pins { pinctrl-single,pins = < J721S2_IOPAD(0x020, PIN_INPUT, 7) /* (AA23) MCAN15_RX.GPIO0_8 */ >; }; + + main_usbss0_pins_default: main-usbss0-default-pins { + pinctrl-single,pins = < + J721S2_IOPAD(0x0ec, PIN_OUTPUT, 6) /* (AG25) TIMER_IO1.USB0_DRVVBUS */ + >; + }; }; -&wkup_pmx0 { - mcu_cpsw_pins_default: mcu-cpsw-pins-default { +&wkup_pmx2 { + wkup_uart0_pins_default: wkup-uart0-default-pins { + pinctrl-single,pins = < + J721S2_WKUP_IOPAD(0x070, PIN_INPUT, 0) /* (E25) WKUP_GPIO0_6.WKUP_UART0_CTSn */ + J721S2_WKUP_IOPAD(0x074, PIN_OUTPUT, 0) /* (F28) WKUP_GPIO0_7.WKUP_UART0_RTSn */ + J721S2_WKUP_IOPAD(0x048, PIN_INPUT, 0) /* (D28) WKUP_UART0_RXD */ + J721S2_WKUP_IOPAD(0x04c, PIN_OUTPUT, 0) /* (D27) WKUP_UART0_TXD */ + >; + }; + + mcu_uart0_pins_default: mcu-uart0-default-pins { + pinctrl-single,pins = < + J721S2_WKUP_IOPAD(0x090, PIN_INPUT, 0) /* (B24) WKUP_GPIO0_14.MCU_UART0_CTSn */ + J721S2_WKUP_IOPAD(0x094, PIN_OUTPUT, 0) /* (D25) WKUP_GPIO0_15.MCU_UART0_RTSn */ + J721S2_WKUP_IOPAD(0x08c, PIN_INPUT, 0) /* (C24) WKUP_GPIO0_13.MCU_UART0_RXD */ + J721S2_WKUP_IOPAD(0x088, PIN_OUTPUT, 0) /* (C25) WKUP_GPIO0_12.MCU_UART0_TXD */ + >; + }; + + mcu_cpsw_pins_default: mcu-cpsw-default-pins { + pinctrl-single,pins = < + J721S2_WKUP_IOPAD(0x02c, PIN_INPUT, 0) /* (B22) MCU_RGMII1_RD0 */ + J721S2_WKUP_IOPAD(0x028, PIN_INPUT, 0) /* (B21) MCU_RGMII1_RD1 */ + J721S2_WKUP_IOPAD(0x024, PIN_INPUT, 0) /* (C22) MCU_RGMII1_RD2 */ + J721S2_WKUP_IOPAD(0x020, PIN_INPUT, 0) /* (D23) MCU_RGMII1_RD3 */ + J721S2_WKUP_IOPAD(0x01c, PIN_INPUT, 0) /* (D22) MCU_RGMII1_RXC */ + J721S2_WKUP_IOPAD(0x004, PIN_INPUT, 0) /* (E23) MCU_RGMII1_RX_CTL */ + J721S2_WKUP_IOPAD(0x014, PIN_OUTPUT, 0) /* (F23) MCU_RGMII1_TD0 */ + J721S2_WKUP_IOPAD(0x010, PIN_OUTPUT, 0) /* (G22) MCU_RGMII1_TD1 */ + J721S2_WKUP_IOPAD(0x00c, PIN_OUTPUT, 0) /* (E21) MCU_RGMII1_TD2 */ + J721S2_WKUP_IOPAD(0x008, PIN_OUTPUT, 0) /* (E22) MCU_RGMII1_TD3 */ + J721S2_WKUP_IOPAD(0x018, PIN_OUTPUT, 0) /* (F21) MCU_RGMII1_TXC */ + J721S2_WKUP_IOPAD(0x000, PIN_OUTPUT, 0) /* (F22) MCU_RGMII1_TX_CTL */ + >; + }; + + mcu_mdio_pins_default: mcu-mdio-default-pins { pinctrl-single,pins = < - J721S2_WKUP_IOPAD(0x094, PIN_INPUT, 0) /* (B22) MCU_RGMII1_RD0 */ - J721S2_WKUP_IOPAD(0x090, PIN_INPUT, 0) /* (B21) MCU_RGMII1_RD1 */ - J721S2_WKUP_IOPAD(0x08c, PIN_INPUT, 0) /* (C22) MCU_RGMII1_RD2 */ - J721S2_WKUP_IOPAD(0x088, PIN_INPUT, 0) /* (D23) MCU_RGMII1_RD3 */ - J721S2_WKUP_IOPAD(0x084, PIN_INPUT, 0) /* (D22) MCU_RGMII1_RXC */ - J721S2_WKUP_IOPAD(0x06c, PIN_INPUT, 0) /* (E23) MCU_RGMII1_RX_CTL */ - J721S2_WKUP_IOPAD(0x07c, PIN_OUTPUT, 0) /* (F23) MCU_RGMII1_TD0 */ - J721S2_WKUP_IOPAD(0x078, PIN_OUTPUT, 0) /* (G22) MCU_RGMII1_TD1 */ - J721S2_WKUP_IOPAD(0x074, PIN_OUTPUT, 0) /* (E21) MCU_RGMII1_TD2 */ - J721S2_WKUP_IOPAD(0x070, PIN_OUTPUT, 0) /* (E22) MCU_RGMII1_TD3 */ - J721S2_WKUP_IOPAD(0x080, PIN_OUTPUT, 0) /* (F21) MCU_RGMII1_TXC */ - J721S2_WKUP_IOPAD(0x068, PIN_OUTPUT, 0) /* (F22) MCU_RGMII1_TX_CTL */ + J721S2_WKUP_IOPAD(0x034, PIN_OUTPUT, 0) /* (A21) MCU_MDIO0_MDC */ + J721S2_WKUP_IOPAD(0x030, PIN_INPUT, 0) /* (A22) MCU_MDIO0_MDIO */ >; }; - mcu_mdio_pins_default: mcu-mdio-pins-default { + mcu_mcan0_pins_default: mcu-mcan0-default-pins { pinctrl-single,pins = < - J721S2_WKUP_IOPAD(0x09c, PIN_OUTPUT, 0) /* (A21) MCU_MDIO0_MDC */ - J721S2_WKUP_IOPAD(0x098, PIN_INPUT, 0) /* (A22) MCU_MDIO0_MDIO */ + J721S2_WKUP_IOPAD(0x054, PIN_INPUT, 0) /* (E28) MCU_MCAN0_RX */ + J721S2_WKUP_IOPAD(0x050, PIN_OUTPUT, 0) /* (E27) MCU_MCAN0_TX */ >; }; - mcu_mcan0_pins_default: mcu-mcan0-pins-default { + mcu_mcan1_pins_default: mcu-mcan1-default-pins { pinctrl-single,pins = < - J721S2_WKUP_IOPAD(0x0bc, PIN_INPUT, 0) /* (E28) MCU_MCAN0_RX */ - J721S2_WKUP_IOPAD(0x0b8, PIN_OUTPUT, 0) /* (E27) MCU_MCAN0_TX */ + J721S2_WKUP_IOPAD(0x06c, PIN_INPUT, 0) /* (F26) WKUP_GPIO0_5.MCU_MCAN1_RX */ + J721S2_WKUP_IOPAD(0x068, PIN_OUTPUT, 0) /*(C23) WKUP_GPIO0_4.MCU_MCAN1_TX */ >; }; - mcu_mcan1_pins_default: mcu-mcan1-pins-default { + mcu_mcan0_gpio_pins_default: mcu-mcan0-gpio-default-pins { pinctrl-single,pins = < - J721S2_WKUP_IOPAD(0x0d4, PIN_INPUT, 0) /* (F26) WKUP_GPIO0_5.MCU_MCAN1_RX */ - J721S2_WKUP_IOPAD(0x0d0, PIN_OUTPUT, 0) /* (C23) WKUP_GPIO0_4.MCU_MCAN1_TX */ + J721S2_WKUP_IOPAD(0x058, PIN_INPUT, 7) /* (D26) WKUP_GPIO0_0 */ + J721S2_WKUP_IOPAD(0x040, PIN_INPUT, 7) /* (B25) MCU_SPI0_D1.WKUP_GPIO0_69 */ >; }; - mcu_mcan0_gpio_pins_default: mcu-mcan0-gpio-pins-default { + mcu_mcan1_gpio_pins_default: mcu-mcan1-gpio-default-pins { pinctrl-single,pins = < - J721S2_WKUP_IOPAD(0x0c0, PIN_INPUT, 7) /* (D26) WKUP_GPIO0_0 */ - J721S2_WKUP_IOPAD(0x0a8, PIN_INPUT, 7) /* (B25) MCU_SPI0_D1.WKUP_GPIO0_69 */ + J721S2_WKUP_IOPAD(0x060, PIN_INPUT, 7) /* (C28) WKUP_GPIO0_2 */ >; }; - mcu_mcan1_gpio_pins_default: mcu-mcan1-gpio-pins-default { + mcu_adc0_pins_default: mcu-adc0-default-pins { pinctrl-single,pins = < - J721S2_WKUP_IOPAD(0x0c8, PIN_INPUT, 7) /* (C28) WKUP_GPIO0_2 */ + J721S2_WKUP_IOPAD(0x0cc, PIN_INPUT, 0) /* (L25) MCU_ADC0_AIN0 */ + J721S2_WKUP_IOPAD(0x0d0, PIN_INPUT, 0) /* (K25) MCU_ADC0_AIN1 */ + J721S2_WKUP_IOPAD(0x0d4, PIN_INPUT, 0) /* (M24) MCU_ADC0_AIN2 */ + J721S2_WKUP_IOPAD(0x0d8, PIN_INPUT, 0) /* (L24) MCU_ADC0_AIN3 */ + J721S2_WKUP_IOPAD(0x0dc, PIN_INPUT, 0) /* (L27) MCU_ADC0_AIN4 */ + J721S2_WKUP_IOPAD(0x0e0, PIN_INPUT, 0) /* (K24) MCU_ADC0_AIN5 */ + J721S2_WKUP_IOPAD(0x0e4, PIN_INPUT, 0) /* (M27) MCU_ADC0_AIN6 */ + J721S2_WKUP_IOPAD(0x0e8, PIN_INPUT, 0) /* (M26) MCU_ADC0_AIN7 */ >; }; - mcu_adc0_pins_default: mcu-adc0-pins-default { + mcu_adc1_pins_default: mcu-adc1-default-pins { pinctrl-single,pins = < - J721S2_WKUP_IOPAD(0x134, PIN_INPUT, 0) /* (L25) MCU_ADC0_AIN0 */ - J721S2_WKUP_IOPAD(0x138, PIN_INPUT, 0) /* (K25) MCU_ADC0_AIN1 */ - J721S2_WKUP_IOPAD(0x13c, PIN_INPUT, 0) /* (M24) MCU_ADC0_AIN2 */ - J721S2_WKUP_IOPAD(0x140, PIN_INPUT, 0) /* (L24) MCU_ADC0_AIN3 */ - J721S2_WKUP_IOPAD(0x144, PIN_INPUT, 0) /* (L27) MCU_ADC0_AIN4 */ - J721S2_WKUP_IOPAD(0x148, PIN_INPUT, 0) /* (K24) MCU_ADC0_AIN5 */ - J721S2_WKUP_IOPAD(0x14c, PIN_INPUT, 0) /* (M27) MCU_ADC0_AIN6 */ - J721S2_WKUP_IOPAD(0x150, PIN_INPUT, 0) /* (M26) MCU_ADC0_AIN7 */ + J721S2_WKUP_IOPAD(0x0ec, PIN_INPUT, 0) /* (P25) MCU_ADC1_AIN0 */ + J721S2_WKUP_IOPAD(0x0f0, PIN_INPUT, 0) /* (R25) MCU_ADC1_AIN1 */ + J721S2_WKUP_IOPAD(0x0f4, PIN_INPUT, 0) /* (P28) MCU_ADC1_AIN2 */ + J721S2_WKUP_IOPAD(0x0f8, PIN_INPUT, 0) /* (P27) MCU_ADC1_AIN3 */ + J721S2_WKUP_IOPAD(0x0fc, PIN_INPUT, 0) /* (N25) MCU_ADC1_AIN4 */ + J721S2_WKUP_IOPAD(0x100, PIN_INPUT, 0) /* (P26) MCU_ADC1_AIN5 */ + J721S2_WKUP_IOPAD(0x104, PIN_INPUT, 0) /* (N26) MCU_ADC1_AIN6 */ + J721S2_WKUP_IOPAD(0x108, PIN_INPUT, 0) /* (N27) MCU_ADC1_AIN7 */ >; }; - mcu_adc1_pins_default: mcu-adc1-pins-default { + mcu_fss0_ospi1_pins_default: mcu-fss0-ospi1-default-pins { pinctrl-single,pins = < - J721S2_WKUP_IOPAD(0x154, PIN_INPUT, 0) /* (P25) MCU_ADC1_AIN0 */ - J721S2_WKUP_IOPAD(0x158, PIN_INPUT, 0) /* (R25) MCU_ADC1_AIN1 */ - J721S2_WKUP_IOPAD(0x15c, PIN_INPUT, 0) /* (P28) MCU_ADC1_AIN2 */ - J721S2_WKUP_IOPAD(0x160, PIN_INPUT, 0) /* (P27) MCU_ADC1_AIN3 */ - J721S2_WKUP_IOPAD(0x164, PIN_INPUT, 0) /* (N25) MCU_ADC1_AIN4 */ - J721S2_WKUP_IOPAD(0x168, PIN_INPUT, 0) /* (P26) MCU_ADC1_AIN5 */ - J721S2_WKUP_IOPAD(0x16c, PIN_INPUT, 0) /* (N26) MCU_ADC1_AIN6 */ - J721S2_WKUP_IOPAD(0x170, PIN_INPUT, 0) /* (N27) MCU_ADC1_AIN7 */ + J721S2_WKUP_IOPAD(0x040, PIN_OUTPUT, 0) /* (A19) MCU_OSPI1_CLK */ + J721S2_WKUP_IOPAD(0x05c, PIN_OUTPUT, 0) /* (D20) MCU_OSPI1_CSn0 */ + J721S2_WKUP_IOPAD(0x060, PIN_OUTPUT, 0) /* (C21) MCU_OSPI1_CSn1 */ + J721S2_WKUP_IOPAD(0x04c, PIN_INPUT, 0) /* (D21) MCU_OSPI1_D0 */ + J721S2_WKUP_IOPAD(0x050, PIN_INPUT, 0) /* (G20) MCU_OSPI1_D1 */ + J721S2_WKUP_IOPAD(0x054, PIN_INPUT, 0) /* (C20) MCU_OSPI1_D2 */ + J721S2_WKUP_IOPAD(0x058, PIN_INPUT, 0) /* (A20) MCU_OSPI1_D3 */ + J721S2_WKUP_IOPAD(0x048, PIN_INPUT, 0) /* (B19) MCU_OSPI1_DQS */ + J721S2_WKUP_IOPAD(0x044, PIN_INPUT, 0) /* (B20) MCU_OSPI1_LBCLKO */ >; }; }; @@ -243,11 +283,14 @@ &wkup_uart0 { status = "reserved"; + pinctrl-names = "default"; + pinctrl-0 = <&wkup_uart0_pins_default>; }; &mcu_uart0 { status = "okay"; - /* Default pinmux */ + pinctrl-names = "default"; + pinctrl-0 = <&mcu_uart0_pins_default>; }; &main_uart8 { @@ -305,7 +348,7 @@ &mcu_cpsw { pinctrl-names = "default"; - pinctrl-0 = <&mcu_cpsw_pins_default &mcu_mdio_pins_default>; + pinctrl-0 = <&mcu_cpsw_pins_default>, <&mcu_mdio_pins_default>; }; &davinci_mdio { @@ -322,6 +365,70 @@ phy-handle = <&phy0>; }; +&serdes_ln_ctrl { + idle-states = , , + , ; +}; + +&serdes_refclk { + clock-frequency = <100000000>; +}; + +&serdes0 { + status = "okay"; + serdes0_pcie_link: phy@0 { + reg = <0>; + cdns,num-lanes = <1>; + #phy-cells = <0>; + cdns,phy-type = ; + resets = <&serdes_wiz0 1>; + }; +}; + +&usb_serdes_mux { + idle-states = <1>; /* USB0 to SERDES lane 1 */ +}; + +&usbss0 { + status = "okay"; + pinctrl-0 = <&main_usbss0_pins_default>; + pinctrl-names = "default"; + ti,vbus-divider; + ti,usb2-only; +}; + +&usb0 { + dr_mode = "otg"; + maximum-speed = "high-speed"; +}; + +&ospi1 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&mcu_fss0_ospi1_pins_default>; + + flash@0{ + compatible = "jedec,spi-nor"; + reg = <0x0>; + spi-tx-bus-width = <1>; + spi-rx-bus-width = <4>; + spi-max-frequency = <40000000>; + cdns,tshsl-ns = <60>; + cdns,tsd2d-ns = <60>; + cdns,tchsh-ns = <60>; + cdns,tslch-ns = <60>; + cdns,read-delay = <2>; + }; +}; + +&pcie1_rc { + status = "okay"; + reset-gpios = <&exp1 2 GPIO_ACTIVE_HIGH>; + phys = <&serdes0_pcie_link>; + phy-names = "pcie-phy"; + num-lanes = <1>; +}; + &mcu_mcan0 { status = "okay"; pinctrl-names = "default"; diff --git a/arch/arm64/boot/dts/ti/k3-j721s2-main.dtsi b/arch/arm64/boot/dts/ti/k3-j721s2-main.dtsi index 2dd7865f76548dbd2fe93cfbd7de33828dff2e45..ed79ab3a32718f7d55e9c288441ea2e9cbb519a7 100644 --- a/arch/arm64/boot/dts/ti/k3-j721s2-main.dtsi +++ b/arch/arm64/boot/dts/ti/k3-j721s2-main.dtsi @@ -5,6 +5,17 @@ * Copyright (C) 2021 Texas Instruments Incorporated - https://www.ti.com/ */ +#include +#include + +/ { + serdes_refclk: clock-cmnrefclk { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <0>; + }; +}; + &cbass_main { msmc_ram: sram@70000000 { compatible = "mmio-sram"; @@ -26,6 +37,29 @@ }; }; + scm_conf: syscon@104000 { + compatible = "ti,j721e-system-controller", "syscon", "simple-mfd"; + reg = <0x00 0x00104000 0x00 0x18000>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x00 0x00 0x00104000 0x18000>; + + usb_serdes_mux: mux-controller@0 { + compatible = "mmio-mux"; + reg = <0x0 0x4>; + #mux-control-cells = <1>; + mux-reg-masks = <0x0 0x8000000>; /* USB0 to SERDES0 lane 1/3 mux */ + }; + + serdes_ln_ctrl: mux-controller@80 { + compatible = "mmio-mux"; + reg = <0x80 0x10>; + #mux-control-cells = <1>; + mux-reg-masks = <0x80 0x3>, <0x84 0x3>, /* SERDES0 lane0/1 select */ + <0x88 0x3>, <0x8c 0x3>; /* SERDES0 lane2/3 select */ + }; + }; + gic500: interrupt-controller@1800000 { compatible = "arm,gic-v3"; #address-cells = <2>; @@ -72,6 +106,24 @@ pinctrl-single,function-mask = <0xffffffff>; }; + /* TIMERIO pad input CTRLMMR_TIMER*_CTRL registers */ + main_timerio_input: pinctrl@104200 { + compatible = "pinctrl-single"; + reg = <0x00 0x104200 0x00 0x50>; + #pinctrl-cells = <1>; + pinctrl-single,register-width = <32>; + pinctrl-single,function-mask = <0x00000007>; + }; + + /* TIMERIO pad output CTCTRLMMR_TIMERIO*_CTRL registers */ + main_timerio_output: pinctrl@104280 { + compatible = "pinctrl-single"; + reg = <0x00 0x104280 0x00 0x20>; + #pinctrl-cells = <1>; + pinctrl-single,register-width = <32>; + pinctrl-single,function-mask = <0x0000001f>; + }; + main_crypto: crypto@4e00000 { compatible = "ti,j721e-sa2ul"; reg = <0x00 0x04e00000 0x00 0x1200>; @@ -91,6 +143,246 @@ }; }; + main_timer0: timer@2400000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x2400000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 63 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 63 1>; + assigned-clock-parents = <&k3_clks 63 2>; + power-domains = <&k3_pds 63 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer1: timer@2410000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x2410000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 64 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 64 1>; + assigned-clock-parents = <&k3_clks 64 2>; + power-domains = <&k3_pds 64 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer2: timer@2420000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x2420000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 65 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 65 1>; + assigned-clock-parents = <&k3_clks 65 2>; + power-domains = <&k3_pds 65 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer3: timer@2430000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x2430000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 66 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 66 1>; + assigned-clock-parents = <&k3_clks 66 2>; + power-domains = <&k3_pds 66 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer4: timer@2440000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x2440000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 67 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 67 1>; + assigned-clock-parents = <&k3_clks 67 2>; + power-domains = <&k3_pds 67 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer5: timer@2450000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x2450000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 68 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 68 1>; + assigned-clock-parents = <&k3_clks 68 2>; + power-domains = <&k3_pds 68 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer6: timer@2460000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x2460000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 69 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 69 1>; + assigned-clock-parents = <&k3_clks 69 2>; + power-domains = <&k3_pds 69 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer7: timer@2470000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x2470000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 70 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 70 1>; + assigned-clock-parents = <&k3_clks 70 2>; + power-domains = <&k3_pds 70 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer8: timer@2480000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x2480000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 71 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 71 1>; + assigned-clock-parents = <&k3_clks 71 2>; + power-domains = <&k3_pds 71 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer9: timer@2490000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x2490000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 72 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 72 1>; + assigned-clock-parents = <&k3_clks 72 2>; + power-domains = <&k3_pds 72 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer10: timer@24a0000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x24a0000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 73 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 73 1>; + assigned-clock-parents = <&k3_clks 73 2>; + power-domains = <&k3_pds 73 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer11: timer@24b0000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x24b0000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 74 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 74 1>; + assigned-clock-parents = <&k3_clks 74 2>; + power-domains = <&k3_pds 74 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer12: timer@24c0000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x24c0000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 75 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 75 1>; + assigned-clock-parents = <&k3_clks 75 2>; + power-domains = <&k3_pds 75 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer13: timer@24d0000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x24d0000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 76 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 76 1>; + assigned-clock-parents = <&k3_clks 76 2>; + power-domains = <&k3_pds 76 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer14: timer@24e0000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x24e0000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 77 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 77 1>; + assigned-clock-parents = <&k3_clks 77 2>; + power-domains = <&k3_pds 77 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer15: timer@24f0000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x24f0000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 78 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 78 1>; + assigned-clock-parents = <&k3_clks 78 2>; + power-domains = <&k3_pds 78 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer16: timer@2500000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x2500000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 79 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 79 1>; + assigned-clock-parents = <&k3_clks 79 2>; + power-domains = <&k3_pds 79 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer17: timer@2510000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x2510000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 80 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 80 1>; + assigned-clock-parents = <&k3_clks 80 2>; + power-domains = <&k3_pds 80 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer18: timer@2520000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x2520000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 81 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 81 1>; + assigned-clock-parents = <&k3_clks 81 2>; + power-domains = <&k3_pds 81 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer19: timer@2530000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x2530000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 82 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 82 1>; + assigned-clock-parents = <&k3_clks 82 2>; + power-domains = <&k3_pds 82 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + main_uart0: serial@2800000 { compatible = "ti,j721e-uart", "ti,am654-uart"; reg = <0x00 0x02800000 0x00 0x200>; @@ -738,6 +1030,8 @@ reg-names = "cpts"; clocks = <&k3_clks 226 5>; clock-names = "cpts"; + assigned-clocks = <&k3_clks 226 5>; /* NAVSS0_CPTS_0_RCLK */ + assigned-clock-parents = <&k3_clks 226 7>; /* MAIN_0_HSDIVOUT6_CLK */ interrupts-extended = <&main_navss_intr 391>; interrupt-names = "cpts"; ti,cpts-periodic-outputs = <6>; @@ -745,6 +1039,117 @@ }; }; + usbss0: cdns-usb@4104000 { + compatible = "ti,j721e-usb"; + reg = <0x00 0x04104000 0x00 0x100>; + clocks = <&k3_clks 360 16>, <&k3_clks 360 15>; + clock-names = "ref", "lpm"; + assigned-clocks = <&k3_clks 360 16>; /* USB2_REFCLK */ + assigned-clock-parents = <&k3_clks 360 17>; + power-domains = <&k3_pds 360 TI_SCI_PD_EXCLUSIVE>; + #address-cells = <2>; + #size-cells = <2>; + ranges; + dma-coherent; + + status = "disabled"; /* Needs pinmux */ + + usb0: usb@6000000 { + compatible = "cdns,usb3"; + reg = <0x00 0x06000000 0x00 0x10000>, + <0x00 0x06010000 0x00 0x10000>, + <0x00 0x06020000 0x00 0x10000>; + reg-names = "otg", "xhci", "dev"; + interrupts = , + , + ; + interrupt-names = "host", "peripheral", "otg"; + maximum-speed = "super-speed"; + dr_mode = "otg"; + }; + }; + + serdes_wiz0: wiz@5060000 { + compatible = "ti,j721s2-wiz-10g"; + #address-cells = <1>; + #size-cells = <1>; + power-domains = <&k3_pds 365 TI_SCI_PD_EXCLUSIVE>; + clocks = <&k3_clks 365 0>, <&k3_clks 365 3>, <&serdes_refclk>; + clock-names = "fck", "core_ref_clk", "ext_ref_clk"; + num-lanes = <4>; + #reset-cells = <1>; + #clock-cells = <1>; + ranges = <0x5060000 0x0 0x5060000 0x10000>; + + assigned-clocks = <&k3_clks 365 3>; + assigned-clock-parents = <&k3_clks 365 7>; + + serdes0: serdes@5060000 { + compatible = "ti,j721e-serdes-10g"; + reg = <0x05060000 0x00010000>; + reg-names = "torrent_phy"; + resets = <&serdes_wiz0 0>; + reset-names = "torrent_reset"; + clocks = <&serdes_wiz0 TI_WIZ_PLL0_REFCLK>, + <&serdes_wiz0 TI_WIZ_PHY_EN_REFCLK>; + clock-names = "refclk", "phy_en_refclk"; + assigned-clocks = <&serdes_wiz0 TI_WIZ_PLL0_REFCLK>, + <&serdes_wiz0 TI_WIZ_PLL1_REFCLK>, + <&serdes_wiz0 TI_WIZ_REFCLK_DIG>; + assigned-clock-parents = <&k3_clks 365 3>, + <&k3_clks 365 3>, + <&k3_clks 365 3>; + #address-cells = <1>; + #size-cells = <0>; + #clock-cells = <1>; + + status = "disabled"; /* Needs lane config */ + }; + }; + + pcie1_rc: pcie@2910000 { + compatible = "ti,j7200-pcie-host", "ti,j721e-pcie-host"; + reg = <0x00 0x02910000 0x00 0x1000>, + <0x00 0x02917000 0x00 0x400>, + <0x00 0x0d800000 0x00 0x800000>, + <0x00 0x18000000 0x00 0x1000>; + reg-names = "intd_cfg", "user_cfg", "reg", "cfg"; + interrupt-names = "link_state"; + interrupts = ; + device_type = "pci"; + ti,syscon-pcie-ctrl = <&scm_conf 0x074>; + max-link-speed = <3>; + num-lanes = <4>; + power-domains = <&k3_pds 276 TI_SCI_PD_EXCLUSIVE>; + clocks = <&k3_clks 276 41>; + clock-names = "fck"; + #address-cells = <3>; + #size-cells = <2>; + bus-range = <0x0 0xff>; + vendor-id = <0x104c>; + device-id = <0xb013>; + msi-map = <0x0 &gic_its 0x0 0x10000>; + dma-coherent; + ranges = <0x01000000 0x0 0x18001000 0x00 0x18001000 0x0 0x0010000>, + <0x02000000 0x0 0x18011000 0x00 0x18011000 0x0 0x7fef000>; + dma-ranges = <0x02000000 0x0 0x0 0x0 0x0 0x10000 0x0>; + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 0 7>; + interrupt-map = <0 0 0 1 &pcie1_intc 0>, /* INT A */ + <0 0 0 2 &pcie1_intc 0>, /* INT B */ + <0 0 0 3 &pcie1_intc 0>, /* INT C */ + <0 0 0 4 &pcie1_intc 0>; /* INT D */ + + status = "disabled"; /* Needs gpio and serdes info */ + + pcie1_intc: interrupt-controller { + interrupt-controller; + #interrupt-cells = <1>; + interrupt-parent = <&gic500>; + interrupts = ; + }; + }; + main_mcan0: can@2701000 { compatible = "bosch,m_can"; reg = <0x00 0x02701000 0x00 0x200>, diff --git a/arch/arm64/boot/dts/ti/k3-j721s2-mcu-wakeup.dtsi b/arch/arm64/boot/dts/ti/k3-j721s2-mcu-wakeup.dtsi index a353705a7463eb3c1a7e73ccf033a94bafa81600..e7dd947a1814b06e6bdd4e9046b238fd52d804a5 100644 --- a/arch/arm64/boot/dts/ti/k3-j721s2-mcu-wakeup.dtsi +++ b/arch/arm64/boot/dts/ti/k3-j721s2-mcu-wakeup.dtsi @@ -39,6 +39,21 @@ reg = <0x00 0x43000014 0x00 0x4>; }; + secure_proxy_sa3: mailbox@43600000 { + compatible = "ti,am654-secure-proxy"; + #mbox-cells = <1>; + reg-names = "target_data", "rt", "scfg"; + reg = <0x00 0x43600000 0x00 0x10000>, + <0x00 0x44880000 0x00 0x20000>, + <0x00 0x44860000 0x00 0x20000>; + /* + * Marked Disabled: + * Node is incomplete as it is meant for bootloaders and + * firmware on non-MPU processors + */ + status = "disabled"; + }; + mcu_ram: sram@41c00000 { compatible = "mmio-sram"; reg = <0x00 0x41c00000 0x00 0x100000>; @@ -50,12 +65,61 @@ wkup_pmx0: pinctrl@4301c000 { compatible = "pinctrl-single"; /* Proxy 0 addressing */ - reg = <0x00 0x4301c000 0x00 0x178>; + reg = <0x00 0x4301c000 0x00 0x034>; #pinctrl-cells = <1>; pinctrl-single,register-width = <32>; pinctrl-single,function-mask = <0xffffffff>; }; + wkup_pmx1: pinctrl@4301c038 { + compatible = "pinctrl-single"; + /* Proxy 0 addressing */ + reg = <0x00 0x4301c038 0x00 0x02C>; + #pinctrl-cells = <1>; + pinctrl-single,register-width = <32>; + pinctrl-single,function-mask = <0xffffffff>; + }; + + wkup_pmx2: pinctrl@4301c068 { + compatible = "pinctrl-single"; + /* Proxy 0 addressing */ + reg = <0x00 0x4301c068 0x00 0x120>; + #pinctrl-cells = <1>; + pinctrl-single,register-width = <32>; + pinctrl-single,function-mask = <0xffffffff>; + }; + + wkup_pmx3: pinctrl@4301c190 { + compatible = "pinctrl-single"; + /* Proxy 0 addressing */ + reg = <0x00 0x4301c190 0x00 0x004>; + #pinctrl-cells = <1>; + pinctrl-single,register-width = <32>; + pinctrl-single,function-mask = <0xffffffff>; + }; + + /* MCU_TIMERIO pad input CTRLMMR_MCU_TIMER*_CTRL registers */ + mcu_timerio_input: pinctrl@40f04200 { + compatible = "pinctrl-single"; + reg = <0x00 0x40f04200 0x00 0x28>; + #pinctrl-cells = <1>; + pinctrl-single,register-width = <32>; + pinctrl-single,function-mask = <0x0000000f>; + /* Non-MPU Firmware usage */ + status = "reserved"; + }; + + /* MCU_TIMERIO pad output CTRLMMR_MCU_TIMERIO*_CTRL registers */ + mcu_timerio_output: pinctrl@40f04280 { + compatible = "pinctrl-single"; + reg = <0x00 0x40f04280 0x00 0x28>; + #pinctrl-cells = <1>; + pinctrl-single,register-width = <32>; + pinctrl-single,function-mask = <0x0000000f>; + /* Non-MPU Firmware usage */ + status = "reserved"; + }; + wkup_gpio_intr: interrupt-controller@42200000 { compatible = "ti,sci-intr"; reg = <0x00 0x42200000 0x00 0x400>; @@ -83,6 +147,146 @@ }; + mcu_timer0: timer@40400000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x40400000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 35 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 35 1>; + assigned-clock-parents = <&k3_clks 35 2>; + power-domains = <&k3_pds 35 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + /* Non-MPU Firmware usage */ + status = "reserved"; + }; + + mcu_timer1: timer@40410000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x40410000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 83 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 83 1>; + assigned-clock-parents = <&k3_clks 83 2>; + power-domains = <&k3_pds 83 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + /* Non-MPU Firmware usage */ + status = "reserved"; + }; + + mcu_timer2: timer@40420000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x40420000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 84 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 84 1>; + assigned-clock-parents = <&k3_clks 84 2>; + power-domains = <&k3_pds 84 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + /* Non-MPU Firmware usage */ + status = "reserved"; + }; + + mcu_timer3: timer@40430000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x40430000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 85 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 85 1>; + assigned-clock-parents = <&k3_clks 85 2>; + power-domains = <&k3_pds 85 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + /* Non-MPU Firmware usage */ + status = "reserved"; + }; + + mcu_timer4: timer@40440000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x40440000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 86 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 86 1>; + assigned-clock-parents = <&k3_clks 86 2>; + power-domains = <&k3_pds 86 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + /* Non-MPU Firmware usage */ + status = "reserved"; + }; + + mcu_timer5: timer@40450000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x40450000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 87 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 87 1>; + assigned-clock-parents = <&k3_clks 87 2>; + power-domains = <&k3_pds 87 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + /* Non-MPU Firmware usage */ + status = "reserved"; + }; + + mcu_timer6: timer@40460000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x40460000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 88 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 88 1>; + assigned-clock-parents = <&k3_clks 88 2>; + power-domains = <&k3_pds 88 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + /* Non-MPU Firmware usage */ + status = "reserved"; + }; + + mcu_timer7: timer@40470000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x40470000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 89 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 89 1>; + assigned-clock-parents = <&k3_clks 89 2>; + power-domains = <&k3_pds 89 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + /* Non-MPU Firmware usage */ + status = "reserved"; + }; + + mcu_timer8: timer@40480000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x40480000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 90 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 90 1>; + assigned-clock-parents = <&k3_clks 90 2>; + power-domains = <&k3_pds 90 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + /* Non-MPU Firmware usage */ + status = "reserved"; + }; + + mcu_timer9: timer@40490000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x40490000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 91 1>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 91 1>; + assigned-clock-parents = <&k3_clks 91 2>; + power-domains = <&k3_pds 91 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + /* Non-MPU Firmware usage */ + status = "reserved"; + }; + wkup_uart0: serial@42300000 { compatible = "ti,j721e-uart", "ti,am654-uart"; reg = <0x00 0x42300000 0x00 0x200>; @@ -280,6 +484,21 @@ }; }; + secure_proxy_mcu: mailbox@2a480000 { + compatible = "ti,am654-secure-proxy"; + #mbox-cells = <1>; + reg-names = "target_data", "rt", "scfg"; + reg = <0x00 0x2a480000 0x00 0x80000>, + <0x00 0x2a380000 0x00 0x80000>, + <0x00 0x2a400000 0x00 0x80000>; + /* + * Marked Disabled: + * Node is incomplete as it is meant for bootloaders and + * firmware on non-MPU processors + */ + status = "disabled"; + }; + mcu_cpsw: ethernet@46000000 { compatible = "ti,j721e-cpsw-nuss"; #address-cells = <2>; @@ -333,6 +552,8 @@ reg = <0x0 0x3d000 0x0 0x400>; clocks = <&k3_clks 29 3>; clock-names = "cpts"; + assigned-clocks = <&k3_clks 29 3>; /* CPTS_RFT_CLK */ + assigned-clock-parents = <&k3_clks 29 5>; /* MAIN_0_HSDIVOUT6_CLK */ interrupts-extended = <&gic500 GIC_SPI 858 IRQ_TYPE_LEVEL_HIGH>; interrupt-names = "cpts"; ti,cpts-ext-ts-inputs = <4>; @@ -379,4 +600,56 @@ compatible = "ti,am3359-adc"; }; }; + + fss: bus@47000000 { + compatible = "simple-bus"; + #address-cells = <2>; + #size-cells = <2>; + ranges = <0x00 0x47000000 0x00 0x47000000 0x00 0x00068400>, + <0x05 0x00000000 0x05 0x00000000 0x01 0x00000000>, + <0x07 0x00000000 0x07 0x00000000 0x01 0x00000000>; + + ospi0: spi@47040000 { + compatible = "ti,am654-ospi", "cdns,qspi-nor"; + reg = <0x00 0x47040000 0x00 0x100>, + <0x05 0x00000000 0x01 0x00000000>; + interrupts = ; + cdns,fifo-depth = <256>; + cdns,fifo-width = <4>; + cdns,trigger-address = <0x0>; + clocks = <&k3_clks 109 5>; + assigned-clocks = <&k3_clks 109 5>; + assigned-clock-parents = <&k3_clks 109 7>; + assigned-clock-rates = <166666666>; + power-domains = <&k3_pds 109 TI_SCI_PD_EXCLUSIVE>; + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; /* Needs pinmux */ + }; + + ospi1: spi@47050000 { + compatible = "ti,am654-ospi", "cdns,qspi-nor"; + reg = <0x00 0x47050000 0x00 0x100>, + <0x07 0x00000000 0x01 0x00000000>; + interrupts = ; + cdns,fifo-depth = <256>; + cdns,fifo-width = <4>; + cdns,trigger-address = <0x0>; + clocks = <&k3_clks 110 5>; + power-domains = <&k3_pds 110 TI_SCI_PD_EXCLUSIVE>; + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; /* Needs pinmux */ + }; + }; + + wkup_vtm0: temperature-sensor@42040000 { + compatible = "ti,j7200-vtm"; + reg = <0x00 0x42040000 0x0 0x350>, + <0x00 0x42050000 0x0 0x350>; + power-domains = <&k3_pds 154 TI_SCI_PD_SHARED>; + #thermal-sensor-cells = <1>; + }; }; diff --git a/arch/arm64/boot/dts/ti/k3-j721s2-som-p0.dtsi b/arch/arm64/boot/dts/ti/k3-j721s2-som-p0.dtsi index 6930efff8a5a3cf1d493a95de87e7ce1355511ad..d57dd43da0ef4141c4b412337b6c4fc3fe59534b 100644 --- a/arch/arm64/boot/dts/ti/k3-j721s2-som-p0.dtsi +++ b/arch/arm64/boot/dts/ti/k3-j721s2-som-p0.dtsi @@ -39,15 +39,46 @@ }; }; +&wkup_pmx0 { + mcu_fss0_ospi0_pins_default: mcu-fss0-ospi0-default-pins { + pinctrl-single,pins = < + J721S2_WKUP_IOPAD(0x000, PIN_OUTPUT, 0) /* (D19) MCU_OSPI0_CLK */ + J721S2_WKUP_IOPAD(0x02c, PIN_OUTPUT, 0) /* (F15) MCU_OSPI0_CSn0 */ + J721S2_WKUP_IOPAD(0x030, PIN_OUTPUT, 0) /* (G17) MCU_OSPI0_CSn1 */ + J721S2_WKUP_IOPAD(0x038, PIN_OUTPUT, 0) /* (F14) MCU_OSPI0_CSn2 */ + J721S2_WKUP_IOPAD(0x03c, PIN_OUTPUT, 0) /* (F17) MCU_OSPI0_CSn3 */ + J721S2_WKUP_IOPAD(0x00c, PIN_INPUT, 0) /* (C19) MCU_OSPI0_D0 */ + J721S2_WKUP_IOPAD(0x010, PIN_INPUT, 0) /* (F16) MCU_OSPI0_D1 */ + J721S2_WKUP_IOPAD(0x014, PIN_INPUT, 0) /* (G15) MCU_OSPI0_D2 */ + J721S2_WKUP_IOPAD(0x018, PIN_INPUT, 0) /* (F18) MCU_OSPI0_D3 */ + J721S2_WKUP_IOPAD(0x01c, PIN_INPUT, 0) /* (E19) MCU_OSPI0_D4 */ + J721S2_WKUP_IOPAD(0x020, PIN_INPUT, 0) /* (G19) MCU_OSPI0_D5 */ + J721S2_WKUP_IOPAD(0x024, PIN_INPUT, 0) /* (F19) MCU_OSPI0_D6 */ + J721S2_WKUP_IOPAD(0x028, PIN_INPUT, 0) /* (F20) MCU_OSPI0_D7 */ + J721S2_WKUP_IOPAD(0x008, PIN_INPUT, 0) /* (E18) MCU_OSPI0_DQS */ + J721S2_WKUP_IOPAD(0x004, PIN_INPUT, 0) /* (E20) MCU_OSPI0_LBCLKO */ + >; + }; +}; + +&wkup_pmx2 { + wkup_i2c0_pins_default: wkup-i2c0-default-pins { + pinctrl-single,pins = < + J721S2_WKUP_IOPAD(0x98, PIN_INPUT, 0) /* (H24) WKUP_I2C0_SCL */ + J721S2_WKUP_IOPAD(0x9c, PIN_INPUT, 0) /* (H27) WKUP_I2C0_SDA */ + >; + }; +}; + &main_pmx0 { - main_i2c0_pins_default: main-i2c0-pins-default { + main_i2c0_pins_default: main-i2c0-default-pins { pinctrl-single,pins = < J721S2_IOPAD(0x0e0, PIN_INPUT_PULLUP, 0) /* (AH25) I2C0_SCL */ J721S2_IOPAD(0x0e4, PIN_INPUT_PULLUP, 0) /* (AE24) I2C0_SDA */ >; }; - main_mcan16_pins_default: main-mcan16-pins-default { + main_mcan16_pins_default: main-mcan16-default-pins { pinctrl-single,pins = < J721S2_IOPAD(0x028, PIN_INPUT, 0) /* (AB24) MCAN16_RX */ J721S2_IOPAD(0x024, PIN_OUTPUT, 0) /* (Y28) MCAN16_TX */ @@ -55,6 +86,19 @@ }; }; +&wkup_i2c0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&wkup_i2c0_pins_default>; + clock-frequency = <400000>; + + eeprom@50 { + /* CAV24C256WE-GT3 */ + compatible = "atmel,24c256"; + reg = <0x50>; + }; +}; + &main_i2c0 { status = "okay"; pinctrl-names = "default"; @@ -79,3 +123,22 @@ pinctrl-names = "default"; phys = <&transceiver0>; }; + +&ospi0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&mcu_fss0_ospi0_pins_default>; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0x0>; + spi-tx-bus-width = <8>; + spi-rx-bus-width = <8>; + spi-max-frequency = <25000000>; + cdns,tshsl-ns = <60>; + cdns,tsd2d-ns = <60>; + cdns,tchsh-ns = <60>; + cdns,tslch-ns = <60>; + cdns,read-delay = <4>; + }; +}; diff --git a/arch/arm64/boot/dts/ti/k3-j721s2-thermal.dtsi b/arch/arm64/boot/dts/ti/k3-j721s2-thermal.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..f7b1a15b8fa0a29083ff2727af6223e44ff7f9f5 --- /dev/null +++ b/arch/arm64/boot/dts/ti/k3-j721s2-thermal.dtsi @@ -0,0 +1,101 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include + +wkup0_thermal: wkup0-thermal { + polling-delay-passive = <250>; /* milliseconds */ + polling-delay = <500>; /* milliseconds */ + thermal-sensors = <&wkup_vtm0 0>; + + trips { + wkup0_crit: wkup0-crit { + temperature = <125000>; /* milliCelsius */ + hysteresis = <2000>; /* milliCelsius */ + type = "critical"; + }; + }; +}; + +wkup1_thermal: wkup1-thermal { + polling-delay-passive = <250>; /* milliseconds */ + polling-delay = <500>; /* milliseconds */ + thermal-sensors = <&wkup_vtm0 1>; + + trips { + wkup1_crit: wkup1-crit { + temperature = <125000>; /* milliCelsius */ + hysteresis = <2000>; /* milliCelsius */ + type = "critical"; + }; + }; +}; + +main0_thermal: main0-thermal { + polling-delay-passive = <250>; /* milliseconds */ + polling-delay = <500>; /* milliseconds */ + thermal-sensors = <&wkup_vtm0 2>; + + trips { + main0_crit: main0-crit { + temperature = <125000>; /* milliCelsius */ + hysteresis = <2000>; /* milliCelsius */ + type = "critical"; + }; + }; +}; + +main1_thermal: main1-thermal { + polling-delay-passive = <250>; /* milliseconds */ + polling-delay = <500>; /* milliseconds */ + thermal-sensors = <&wkup_vtm0 3>; + + trips { + main1_crit: main1-crit { + temperature = <125000>; /* milliCelsius */ + hysteresis = <2000>; /* milliCelsius */ + type = "critical"; + }; + }; +}; + +main2_thermal: main2-thermal { + polling-delay-passive = <250>; /* milliseconds */ + polling-delay = <500>; /* milliseconds */ + thermal-sensors = <&wkup_vtm0 4>; + + trips { + main2_crit: main2-crit { + temperature = <125000>; /* milliCelsius */ + hysteresis = <2000>; /* milliCelsius */ + type = "critical"; + }; + }; +}; + +main3_thermal: main3-thermal { + polling-delay-passive = <250>; /* milliseconds */ + polling-delay = <500>; /* milliseconds */ + thermal-sensors = <&wkup_vtm0 5>; + + trips { + main3_crit: main3-crit { + temperature = <125000>; /* milliCelsius */ + hysteresis = <2000>; /* milliCelsius */ + type = "critical"; + }; + }; +}; + +main4_thermal: main4-thermal { + polling-delay-passive = <250>; /* milliseconds */ + polling-delay = <500>; /* milliseconds */ + thermal-sensors = <&wkup_vtm0 6>; + + trips { + main4_crit: main4-crit { + temperature = <125000>; /* milliCelsius */ + hysteresis = <2000>; /* milliCelsius */ + type = "critical"; + }; + }; +}; diff --git a/arch/arm64/boot/dts/ti/k3-j721s2.dtsi b/arch/arm64/boot/dts/ti/k3-j721s2.dtsi index 376924726f1f36ac9fb5cd9d09c3745371dcb239..1f636acd4eee4f648d5b7cffdeeae8be01764d43 100644 --- a/arch/arm64/boot/dts/ti/k3-j721s2.dtsi +++ b/arch/arm64/boot/dts/ti/k3-j721s2.dtsi @@ -2,7 +2,7 @@ /* * Device Tree Source for J721S2 SoC Family * - * TRM (SPRUJ28 – NOVEMBER 2021) : http://www.ti.com/lit/pdf/spruj28 + * TRM (SPRUJ28 NOVEMBER 2021): https://www.ti.com/lit/pdf/spruj28 * * Copyright (C) 2021 Texas Instruments Incorporated - https://www.ti.com/ * @@ -81,6 +81,7 @@ msmc_l3: l3-cache0 { compatible = "cache"; cache-level = <3>; + cache-unified; }; firmware { @@ -163,6 +164,10 @@ }; }; + + thermal_zones: thermal-zones { + #include "k3-j721s2-thermal.dtsi" + }; }; /* Now include peripherals from each bus segment */ diff --git a/arch/arm64/boot/dts/ti/k3-j784s4-evm.dts b/arch/arm64/boot/dts/ti/k3-j784s4-evm.dts index f33815953e7792b9d4e9962966bcf5eb665ad995..430b8a2c5df57ec14f0933b74a49b19f3bc107d0 100644 --- a/arch/arm64/boot/dts/ti/k3-j784s4-evm.dts +++ b/arch/arm64/boot/dts/ti/k3-j784s4-evm.dts @@ -20,10 +20,13 @@ }; aliases { + serial0 = &wkup_uart0; + serial1 = &mcu_uart0; serial2 = &main_uart8; mmc0 = &main_sdhci0; mmc1 = &main_sdhci1; - i2c0 = &main_i2c0; + i2c0 = &wkup_i2c0; + i2c3 = &main_i2c0; }; memory@80000000 { @@ -42,6 +45,150 @@ reg = <0x00 0x9e800000 0x00 0x01800000>; no-map; }; + + mcu_r5fss0_core0_dma_memory_region: r5f-dma-memory@a0000000 { + compatible = "shared-dma-pool"; + reg = <0x00 0xa0000000 0x00 0x100000>; + no-map; + }; + + mcu_r5fss0_core0_memory_region: r5f-memory@a0100000 { + compatible = "shared-dma-pool"; + reg = <0x00 0xa0100000 0x00 0xf00000>; + no-map; + }; + + mcu_r5fss0_core1_dma_memory_region: r5f-dma-memory@a1000000 { + compatible = "shared-dma-pool"; + reg = <0x00 0xa1000000 0x00 0x100000>; + no-map; + }; + + mcu_r5fss0_core1_memory_region: r5f-memory@a1100000 { + compatible = "shared-dma-pool"; + reg = <0x00 0xa1100000 0x00 0xf00000>; + no-map; + }; + + main_r5fss0_core0_dma_memory_region: r5f-dma-memory@a2000000 { + compatible = "shared-dma-pool"; + reg = <0x00 0xa2000000 0x00 0x100000>; + no-map; + }; + + main_r5fss0_core0_memory_region: r5f-memory@a2100000 { + compatible = "shared-dma-pool"; + reg = <0x00 0xa2100000 0x00 0xf00000>; + no-map; + }; + + main_r5fss0_core1_dma_memory_region: r5f-dma-memory@a3000000 { + compatible = "shared-dma-pool"; + reg = <0x00 0xa3000000 0x00 0x100000>; + no-map; + }; + + main_r5fss0_core1_memory_region: r5f-memory@a3100000 { + compatible = "shared-dma-pool"; + reg = <0x00 0xa3100000 0x00 0xf00000>; + no-map; + }; + + main_r5fss1_core0_dma_memory_region: r5f-dma-memory@a4000000 { + compatible = "shared-dma-pool"; + reg = <0x00 0xa4000000 0x00 0x100000>; + no-map; + }; + + main_r5fss1_core0_memory_region: r5f-memory@a4100000 { + compatible = "shared-dma-pool"; + reg = <0x00 0xa4100000 0x00 0xf00000>; + no-map; + }; + + main_r5fss1_core1_dma_memory_region: r5f-dma-memory@a5000000 { + compatible = "shared-dma-pool"; + reg = <0x00 0xa5000000 0x00 0x100000>; + no-map; + }; + + main_r5fss1_core1_memory_region: r5f-memory@a5100000 { + compatible = "shared-dma-pool"; + reg = <0x00 0xa5100000 0x00 0xf00000>; + no-map; + }; + + main_r5fss2_core0_dma_memory_region: r5f-dma-memory@a6000000 { + compatible = "shared-dma-pool"; + reg = <0x00 0xa6000000 0x00 0x100000>; + no-map; + }; + + main_r5fss2_core0_memory_region: r5f-memory@a6100000 { + compatible = "shared-dma-pool"; + reg = <0x00 0xa6100000 0x00 0xf00000>; + no-map; + }; + + main_r5fss2_core1_dma_memory_region: r5f-dma-memory@a7000000 { + compatible = "shared-dma-pool"; + reg = <0x00 0xa7000000 0x00 0x100000>; + no-map; + }; + + main_r5fss2_core1_memory_region: r5f-memory@a7100000 { + compatible = "shared-dma-pool"; + reg = <0x00 0xa7100000 0x00 0xf00000>; + no-map; + }; + + c71_0_dma_memory_region: c71-dma-memory@a8000000 { + compatible = "shared-dma-pool"; + reg = <0x00 0xa8000000 0x00 0x100000>; + no-map; + }; + + c71_0_memory_region: c71-memory@a8100000 { + compatible = "shared-dma-pool"; + reg = <0x00 0xa8100000 0x00 0xf00000>; + no-map; + }; + + c71_1_dma_memory_region: c71-dma-memory@a9000000 { + compatible = "shared-dma-pool"; + reg = <0x00 0xa9000000 0x00 0x100000>; + no-map; + }; + + c71_1_memory_region: c71-memory@a9100000 { + compatible = "shared-dma-pool"; + reg = <0x00 0xa9100000 0x00 0xf00000>; + no-map; + }; + + c71_2_dma_memory_region: c71-dma-memory@aa000000 { + compatible = "shared-dma-pool"; + reg = <0x00 0xaa000000 0x00 0x100000>; + no-map; + }; + + c71_2_memory_region: c71-memory@aa100000 { + compatible = "shared-dma-pool"; + reg = <0x00 0xaa100000 0x00 0xf00000>; + no-map; + }; + + c71_3_dma_memory_region: c71-dma-memory@ab000000 { + compatible = "shared-dma-pool"; + reg = <0x00 0xab000000 0x00 0x100000>; + no-map; + }; + + c71_3_memory_region: c71-memory@ab100000 { + compatible = "shared-dma-pool"; + reg = <0x00 0xab100000 0x00 0xf00000>; + no-map; + }; }; evm_12v0: regulator-evm12v0 { @@ -105,7 +252,7 @@ }; &main_pmx0 { - main_uart8_pins_default: main-uart8-pins-default { + main_uart8_pins_default: main-uart8-default-pins { pinctrl-single,pins = < J784S4_IOPAD(0x040, PIN_INPUT, 14) /* (AF37) MCASP0_AXR0.UART8_CTSn */ J784S4_IOPAD(0x044, PIN_OUTPUT, 14) /* (AG37) MCASP0_AXR1.UART8_RTSn */ @@ -114,14 +261,14 @@ >; }; - main_i2c0_pins_default: main-i2c0-pins-default { + main_i2c0_pins_default: main-i2c0-default-pins { pinctrl-single,pins = < J784S4_IOPAD(0x0e0, PIN_INPUT_PULLUP, 0) /* (AN36) I2C0_SCL */ J784S4_IOPAD(0x0e4, PIN_INPUT_PULLUP, 0) /* (AP37) I2C0_SDA */ >; }; - main_mmc1_pins_default: main-mmc1-pins-default { + main_mmc1_pins_default: main-mmc1-default-pins { pinctrl-single,pins = < J784S4_IOPAD(0x104, PIN_INPUT, 0) /* (AB38) MMC1_CLK */ J784S4_IOPAD(0x108, PIN_INPUT, 0) /* (AB36) MMC1_CMD */ @@ -134,45 +281,280 @@ >; }; - vdd_sd_dv_pins_default: vdd-sd-dv-pins-default { + vdd_sd_dv_pins_default: vdd-sd-dv-default-pins { pinctrl-single,pins = < J784S4_IOPAD(0x020, PIN_INPUT, 7) /* (AJ35) MCAN15_RX.GPIO0_8 */ >; }; }; +&wkup_pmx2 { + wkup_uart0_pins_default: wkup-uart0-default-pins { + pinctrl-single,pins = < + J721S2_WKUP_IOPAD(0x070, PIN_INPUT, 0) /* (L37) WKUP_GPIO0_6.WKUP_UART0_CTSn */ + J721S2_WKUP_IOPAD(0x074, PIN_INPUT, 0) /* (L36) WKUP_GPIO0_7.WKUP_UART0_RTSn */ + J721S2_WKUP_IOPAD(0x048, PIN_INPUT, 0) /* (K35) WKUP_UART0_RXD */ + J721S2_WKUP_IOPAD(0x04c, PIN_INPUT, 0) /* (K34) WKUP_UART0_TXD */ + >; + }; + + wkup_i2c0_pins_default: wkup-i2c0-default-pins { + pinctrl-single,pins = < + J721S2_WKUP_IOPAD(0x98, PIN_INPUT, 0) /* (N33) WKUP_I2C0_SCL */ + J721S2_WKUP_IOPAD(0x9c, PIN_INPUT, 0) /* (N35) WKUP_I2C0_SDA */ + >; + }; + + mcu_uart0_pins_default: mcu-uart0-default-pins { + pinctrl-single,pins = < + J784S4_WKUP_IOPAD(0x090, PIN_INPUT, 0) /* (H37) WKUP_GPIO0_14.MCU_UART0_CTSn */ + J784S4_WKUP_IOPAD(0x094, PIN_OUTPUT, 0) /* (K37) WKUP_GPIO0_15.MCU_UART0_RTSn */ + J784S4_WKUP_IOPAD(0x08c, PIN_INPUT, 0) /* (K38) WKUP_GPIO0_13.MCU_UART0_RXD */ + J784S4_WKUP_IOPAD(0x088, PIN_OUTPUT, 0) /* (J37) WKUP_GPIO0_12.MCU_UART0_TXD */ + >; + }; + + mcu_cpsw_pins_default: mcu-cpsw-default-pins { + pinctrl-single,pins = < + J784S4_WKUP_IOPAD(0x02c, PIN_INPUT, 0) /* (A35) MCU_RGMII1_RD0 */ + J784S4_WKUP_IOPAD(0x028, PIN_INPUT, 0) /* (B36) MCU_RGMII1_RD1 */ + J784S4_WKUP_IOPAD(0x024, PIN_INPUT, 0) /* (C36) MCU_RGMII1_RD2 */ + J784S4_WKUP_IOPAD(0x020, PIN_INPUT, 0) /* (D36) MCU_RGMII1_RD3 */ + J784S4_WKUP_IOPAD(0x01c, PIN_INPUT, 0) /* (B37) MCU_RGMII1_RXC */ + J784S4_WKUP_IOPAD(0x004, PIN_INPUT, 0) /* (C37) MCU_RGMII1_RX_CTL */ + J784S4_WKUP_IOPAD(0x014, PIN_OUTPUT, 0) /* (D37) MCU_RGMII1_TD0 */ + J784S4_WKUP_IOPAD(0x010, PIN_OUTPUT, 0) /* (D38) MCU_RGMII1_TD1 */ + J784S4_WKUP_IOPAD(0x00c, PIN_OUTPUT, 0) /* (E37) MCU_RGMII1_TD2 */ + J784S4_WKUP_IOPAD(0x008, PIN_OUTPUT, 0) /* (E38) MCU_RGMII1_TD3 */ + J784S4_WKUP_IOPAD(0x018, PIN_OUTPUT, 0) /* (E36) MCU_RGMII1_TXC */ + J784S4_WKUP_IOPAD(0x000, PIN_OUTPUT, 0) /* (C38) MCU_RGMII1_TX_CTL */ + >; + }; + + mcu_mdio_pins_default: mcu-mdio-default-pins { + pinctrl-single,pins = < + J784S4_WKUP_IOPAD(0x034, PIN_OUTPUT, 0) /* (A36) MCU_MDIO0_MDC */ + J784S4_WKUP_IOPAD(0x030, PIN_INPUT, 0) /* (B35) MCU_MDIO0_MDIO */ + >; + }; + + mcu_adc0_pins_default: mcu-adc0-default-pins { + pinctrl-single,pins = < + J784S4_WKUP_IOPAD(0x134, PIN_INPUT, 0) /* (P36) MCU_ADC0_AIN0 */ + J784S4_WKUP_IOPAD(0x138, PIN_INPUT, 0) /* (V36) MCU_ADC0_AIN1 */ + J784S4_WKUP_IOPAD(0x13c, PIN_INPUT, 0) /* (T34) MCU_ADC0_AIN2 */ + J784S4_WKUP_IOPAD(0x140, PIN_INPUT, 0) /* (T36) MCU_ADC0_AIN3 */ + J784S4_WKUP_IOPAD(0x144, PIN_INPUT, 0) /* (P34) MCU_ADC0_AIN4 */ + J784S4_WKUP_IOPAD(0x148, PIN_INPUT, 0) /* (R37) MCU_ADC0_AIN5 */ + J784S4_WKUP_IOPAD(0x14c, PIN_INPUT, 0) /* (R33) MCU_ADC0_AIN6 */ + J784S4_WKUP_IOPAD(0x150, PIN_INPUT, 0) /* (V38) MCU_ADC0_AIN7 */ + >; + }; + + mcu_adc1_pins_default: mcu-adc1-default-pins { + pinctrl-single,pins = < + J784S4_WKUP_IOPAD(0x154, PIN_INPUT, 0) /* (Y38) MCU_ADC1_AIN0 */ + J784S4_WKUP_IOPAD(0x158, PIN_INPUT, 0) /* (Y34) MCU_ADC1_AIN1 */ + J784S4_WKUP_IOPAD(0x15c, PIN_INPUT, 0) /* (V34) MCU_ADC1_AIN2 */ + J784S4_WKUP_IOPAD(0x160, PIN_INPUT, 0) /* (W37) MCU_ADC1_AIN3 */ + J784S4_WKUP_IOPAD(0x164, PIN_INPUT, 0) /* (AA37) MCU_ADC1_AIN4 */ + J784S4_WKUP_IOPAD(0x168, PIN_INPUT, 0) /* (W33) MCU_ADC1_AIN5 */ + J784S4_WKUP_IOPAD(0x16c, PIN_INPUT, 0) /* (U33) MCU_ADC1_AIN6 */ + J784S4_WKUP_IOPAD(0x170, PIN_INPUT, 0) /* (Y36) MCU_ADC1_AIN7 */ + >; + }; +}; + &wkup_pmx0 { - mcu_cpsw_pins_default: mcu-cpsw-pins-default { + mcu_fss0_ospi0_pins_default: mcu-fss0-ospi0-default-pins { pinctrl-single,pins = < - J784S4_WKUP_IOPAD(0x094, PIN_INPUT, 0) /* (A35) MCU_RGMII1_RD0 */ - J784S4_WKUP_IOPAD(0x090, PIN_INPUT, 0) /* (B36) MCU_RGMII1_RD1 */ - J784S4_WKUP_IOPAD(0x08c, PIN_INPUT, 0) /* (C36) MCU_RGMII1_RD2 */ - J784S4_WKUP_IOPAD(0x088, PIN_INPUT, 0) /* (D36) MCU_RGMII1_RD3 */ - J784S4_WKUP_IOPAD(0x084, PIN_INPUT, 0) /* (B37) MCU_RGMII1_RXC */ - J784S4_WKUP_IOPAD(0x06c, PIN_INPUT, 0) /* (C37) MCU_RGMII1_RX_CTL */ - J784S4_WKUP_IOPAD(0x07c, PIN_OUTPUT, 0) /* (D37) MCU_RGMII1_TD0 */ - J784S4_WKUP_IOPAD(0x078, PIN_OUTPUT, 0) /* (D38) MCU_RGMII1_TD1 */ - J784S4_WKUP_IOPAD(0x074, PIN_OUTPUT, 0) /* (E37) MCU_RGMII1_TD2 */ - J784S4_WKUP_IOPAD(0x070, PIN_OUTPUT, 0) /* (E38) MCU_RGMII1_TD3 */ - J784S4_WKUP_IOPAD(0x080, PIN_OUTPUT, 0) /* (E36) MCU_RGMII1_TXC */ - J784S4_WKUP_IOPAD(0x068, PIN_OUTPUT, 0) /* (C38) MCU_RGMII1_TX_CTL */ + J784S4_WKUP_IOPAD(0x000, PIN_OUTPUT, 0) /* (E32) MCU_OSPI0_CLK */ + J784S4_WKUP_IOPAD(0x02c, PIN_OUTPUT, 0) /* (A32) MCU_OSPI0_CSn0 */ + J784S4_WKUP_IOPAD(0x00c, PIN_INPUT, 0) /* (B33) MCU_OSPI0_D0 */ + J784S4_WKUP_IOPAD(0x010, PIN_INPUT, 0) /* (B32) MCU_OSPI0_D1 */ + J784S4_WKUP_IOPAD(0x014, PIN_INPUT, 0) /* (C33) MCU_OSPI0_D2 */ + J784S4_WKUP_IOPAD(0x018, PIN_INPUT, 0) /* (C35) MCU_OSPI0_D3 */ + J784S4_WKUP_IOPAD(0x01c, PIN_INPUT, 0) /* (D33) MCU_OSPI0_D4 */ + J784S4_WKUP_IOPAD(0x020, PIN_INPUT, 0) /* (D34) MCU_OSPI0_D5 */ + J784S4_WKUP_IOPAD(0x024, PIN_INPUT, 0) /* (E34) MCU_OSPI0_D6 */ + J784S4_WKUP_IOPAD(0x028, PIN_INPUT, 0) /* (E33) MCU_OSPI0_D7 */ + J784S4_WKUP_IOPAD(0x008, PIN_INPUT, 0) /* (C34) MCU_OSPI0_DQS */ + J784S4_WKUP_IOPAD(0x03c, PIN_OUTPUT, 6) /* (C32) MCU_OSPI0_CSn3.MCU_OSPI0_ECC_FAIL */ + J784S4_WKUP_IOPAD(0x038, PIN_OUTPUT, 6) /* (B34) MCU_OSPI0_CSn2.MCU_OSPI0_RESET_OUT0 */ >; }; - mcu_mdio_pins_default: mcu-mdio-pins-default { + mcu_fss0_ospi1_pins_default: mcu-fss0-ospi1-default-pins { pinctrl-single,pins = < - J784S4_WKUP_IOPAD(0x09c, PIN_OUTPUT, 0) /* (A36) MCU_MDIO0_MDC */ - J784S4_WKUP_IOPAD(0x098, PIN_INPUT, 0) /* (B35) MCU_MDIO0_MDIO */ + J784S4_WKUP_IOPAD(0x040, PIN_OUTPUT, 0) /* (F32) MCU_OSPI1_CLK */ + J784S4_WKUP_IOPAD(0x05c, PIN_OUTPUT, 0) /* (G32) MCU_OSPI1_CSn0 */ + J784S4_WKUP_IOPAD(0x04c, PIN_INPUT, 0) /* (E35) MCU_OSPI1_D0 */ + J784S4_WKUP_IOPAD(0x050, PIN_INPUT, 0) /* (D31) MCU_OSPI1_D1 */ + J784S4_WKUP_IOPAD(0x054, PIN_INPUT, 0) /* (G31) MCU_OSPI1_D2 */ + J784S4_WKUP_IOPAD(0x058, PIN_INPUT, 0) /* (F33) MCU_OSPI1_D3 */ + J784S4_WKUP_IOPAD(0x048, PIN_INPUT, 0) /* (F31) MCU_OSPI1_DQS */ + J784S4_WKUP_IOPAD(0x044, PIN_INPUT, 0) /* (C31) MCU_OSPI1_LBCLKO */ >; }; }; +&wkup_uart0 { + /* Firmware usage */ + status = "reserved"; + pinctrl-names = "default"; + pinctrl-0 = <&wkup_uart0_pins_default>; +}; + +&wkup_i2c0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&wkup_i2c0_pins_default>; + clock-frequency = <400000>; + + eeprom@50 { + /* CAV24C256WE-GT3 */ + compatible = "atmel,24c256"; + reg = <0x50>; + }; +}; + +&mcu_uart0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&mcu_uart0_pins_default>; +}; + &main_uart8 { status = "okay"; pinctrl-names = "default"; pinctrl-0 = <&main_uart8_pins_default>; }; +&fss { + status = "okay"; +}; + +&ospi0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&mcu_fss0_ospi0_pins_default>; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0x0>; + spi-tx-bus-width = <8>; + spi-rx-bus-width = <8>; + spi-max-frequency = <25000000>; + cdns,tshsl-ns = <60>; + cdns,tsd2d-ns = <60>; + cdns,tchsh-ns = <60>; + cdns,tslch-ns = <60>; + cdns,read-delay = <4>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "ospi.tiboot3"; + reg = <0x0 0x80000>; + }; + + partition@80000 { + label = "ospi.tispl"; + reg = <0x80000 0x200000>; + }; + + partition@280000 { + label = "ospi.u-boot"; + reg = <0x280000 0x400000>; + }; + + partition@680000 { + label = "ospi.env"; + reg = <0x680000 0x40000>; + }; + + partition@6c0000 { + label = "ospi.env.backup"; + reg = <0x6c0000 0x40000>; + }; + + partition@800000 { + label = "ospi.rootfs"; + reg = <0x800000 0x37c0000>; + }; + + partition@3fc0000 { + label = "ospi.phypattern"; + reg = <0x3fc0000 0x40000>; + }; + }; + }; +}; + +&ospi1 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&mcu_fss0_ospi1_pins_default>; + + flash@0{ + compatible = "jedec,spi-nor"; + reg = <0x0>; + spi-tx-bus-width = <1>; + spi-rx-bus-width = <4>; + spi-max-frequency = <40000000>; + cdns,tshsl-ns = <60>; + cdns,tsd2d-ns = <60>; + cdns,tchsh-ns = <60>; + cdns,tslch-ns = <60>; + cdns,read-delay = <2>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "qspi.tiboot3"; + reg = <0x0 0x80000>; + }; + + partition@80000 { + label = "qspi.tispl"; + reg = <0x80000 0x200000>; + }; + + partition@280000 { + label = "qspi.u-boot"; + reg = <0x280000 0x400000>; + }; + + partition@680000 { + label = "qspi.env"; + reg = <0x680000 0x40000>; + }; + + partition@6c0000 { + label = "qspi.env.backup"; + reg = <0x6c0000 0x40000>; + }; + + partition@800000 { + label = "qspi.rootfs"; + reg = <0x800000 0x37c0000>; + }; + + partition@3fc0000 { + label = "qspi.phypattern"; + reg = <0x3fc0000 0x40000>; + }; + }; + + }; +}; + &main_i2c0 { status = "okay"; pinctrl-names = "default"; @@ -253,3 +635,195 @@ phy-mode = "rgmii-rxid"; phy-handle = <&mcu_phy0>; }; + +&mailbox0_cluster0 { + status = "okay"; + interrupts = <436>; + + mbox_mcu_r5fss0_core0: mbox-mcu-r5fss0-core0 { + ti,mbox-rx = <0 0 0>; + ti,mbox-tx = <1 0 0>; + }; + + mbox_mcu_r5fss0_core1: mbox-mcu-r5fss0-core1 { + ti,mbox-rx = <2 0 0>; + ti,mbox-tx = <3 0 0>; + }; +}; + +&mailbox0_cluster1 { + status = "okay"; + interrupts = <432>; + + mbox_main_r5fss0_core0: mbox-main-r5fss0-core0 { + ti,mbox-rx = <0 0 0>; + ti,mbox-tx = <1 0 0>; + }; + + mbox_main_r5fss0_core1: mbox-main-r5fss0-core1 { + ti,mbox-rx = <2 0 0>; + ti,mbox-tx = <3 0 0>; + }; +}; + +&mailbox0_cluster2 { + status = "okay"; + interrupts = <428>; + + mbox_main_r5fss1_core0: mbox-main-r5fss1-core0 { + ti,mbox-rx = <0 0 0>; + ti,mbox-tx = <1 0 0>; + }; + + mbox_main_r5fss1_core1: mbox-main-r5fss1-core1 { + ti,mbox-rx = <2 0 0>; + ti,mbox-tx = <3 0 0>; + }; +}; + +&mailbox0_cluster3 { + status = "okay"; + interrupts = <424>; + + mbox_main_r5fss2_core0: mbox-main-r5fss2-core0 { + ti,mbox-rx = <0 0 0>; + ti,mbox-tx = <1 0 0>; + }; + + mbox_main_r5fss2_core1: mbox-main-r5fss2-core1 { + ti,mbox-rx = <2 0 0>; + ti,mbox-tx = <3 0 0>; + }; +}; + +&mailbox0_cluster4 { + status = "okay"; + interrupts = <420>; + + mbox_c71_0: mbox-c71-0 { + ti,mbox-rx = <0 0 0>; + ti,mbox-tx = <1 0 0>; + }; + + mbox_c71_1: mbox-c71-1 { + ti,mbox-rx = <2 0 0>; + ti,mbox-tx = <3 0 0>; + }; +}; + +&mailbox0_cluster5 { + status = "okay"; + interrupts = <416>; + + mbox_c71_2: mbox-c71-2 { + ti,mbox-rx = <0 0 0>; + ti,mbox-tx = <1 0 0>; + }; + + mbox_c71_3: mbox-c71-3 { + ti,mbox-rx = <2 0 0>; + ti,mbox-tx = <3 0 0>; + }; +}; + +&mcu_r5fss0_core0 { + status = "okay"; + mboxes = <&mailbox0_cluster0 &mbox_mcu_r5fss0_core0>; + memory-region = <&mcu_r5fss0_core0_dma_memory_region>, + <&mcu_r5fss0_core0_memory_region>; +}; + +&mcu_r5fss0_core1 { + status = "okay"; + mboxes = <&mailbox0_cluster0 &mbox_mcu_r5fss0_core1>; + memory-region = <&mcu_r5fss0_core1_dma_memory_region>, + <&mcu_r5fss0_core1_memory_region>; +}; + +&main_r5fss0_core0 { + status = "okay"; + mboxes = <&mailbox0_cluster1 &mbox_main_r5fss0_core0>; + memory-region = <&main_r5fss0_core0_dma_memory_region>, + <&main_r5fss0_core0_memory_region>; +}; + +&main_r5fss0_core1 { + status = "okay"; + mboxes = <&mailbox0_cluster1 &mbox_main_r5fss0_core1>; + memory-region = <&main_r5fss0_core1_dma_memory_region>, + <&main_r5fss0_core1_memory_region>; +}; + +&main_r5fss1_core0 { + status = "okay"; + mboxes = <&mailbox0_cluster2 &mbox_main_r5fss1_core0>; + memory-region = <&main_r5fss1_core0_dma_memory_region>, + <&main_r5fss1_core0_memory_region>; +}; + +&main_r5fss1_core1 { + status = "okay"; + mboxes = <&mailbox0_cluster2 &mbox_main_r5fss1_core1>; + memory-region = <&main_r5fss1_core1_dma_memory_region>, + <&main_r5fss1_core1_memory_region>; +}; + +&main_r5fss2_core0 { + status = "okay"; + mboxes = <&mailbox0_cluster3 &mbox_main_r5fss2_core0>; + memory-region = <&main_r5fss2_core0_dma_memory_region>, + <&main_r5fss2_core0_memory_region>; +}; + +&main_r5fss2_core1 { + status = "okay"; + mboxes = <&mailbox0_cluster3 &mbox_main_r5fss2_core1>; + memory-region = <&main_r5fss2_core1_dma_memory_region>, + <&main_r5fss2_core1_memory_region>; +}; + +&c71_0 { + status = "okay"; + mboxes = <&mailbox0_cluster4 &mbox_c71_0>; + memory-region = <&c71_0_dma_memory_region>, + <&c71_0_memory_region>; +}; + +&c71_1 { + status = "okay"; + mboxes = <&mailbox0_cluster4 &mbox_c71_1>; + memory-region = <&c71_1_dma_memory_region>, + <&c71_1_memory_region>; +}; + +&c71_2 { + status = "okay"; + mboxes = <&mailbox0_cluster5 &mbox_c71_2>; + memory-region = <&c71_2_dma_memory_region>, + <&c71_2_memory_region>; +}; + +&c71_3 { + status = "okay"; + mboxes = <&mailbox0_cluster5 &mbox_c71_3>; + memory-region = <&c71_3_dma_memory_region>, + <&c71_3_memory_region>; +}; + +&tscadc0 { + pinctrl-0 = <&mcu_adc0_pins_default>; + pinctrl-names = "default"; + status = "okay"; + adc { + ti,adc-channels = <0 1 2 3 4 5 6 7>; + }; +}; + +&tscadc1 { + pinctrl-0 = <&mcu_adc1_pins_default>; + pinctrl-names = "default"; + status = "okay"; + adc { + ti,adc-channels = <0 1 2 3 4 5 6 7>; + }; +}; diff --git a/arch/arm64/boot/dts/ti/k3-j784s4-main.dtsi b/arch/arm64/boot/dts/ti/k3-j784s4-main.dtsi index e9169eb358c1613feef046360fc7af9fc5bd30a2..2ea0adae6832f7f882f8911f9e7c97233e1a40c5 100644 --- a/arch/arm64/boot/dts/ti/k3-j784s4-main.dtsi +++ b/arch/arm64/boot/dts/ti/k3-j784s4-main.dtsi @@ -72,6 +72,24 @@ pinctrl-single,function-mask = <0xffffffff>; }; + /* TIMERIO pad input CTRLMMR_TIMER*_CTRL registers */ + main_timerio_input: pinctrl@104200 { + compatible = "pinctrl-single"; + reg = <0x00 0x104200 0x00 0x50>; + #pinctrl-cells = <1>; + pinctrl-single,register-width = <32>; + pinctrl-single,function-mask = <0x00000007>; + }; + + /* TIMERIO pad output CTCTRLMMR_TIMERIO*_CTRL registers */ + main_timerio_output: pinctrl@104280 { + compatible = "pinctrl-single"; + reg = <0x00 0x104280 0x00 0x20>; + #pinctrl-cells = <1>; + pinctrl-single,register-width = <32>; + pinctrl-single,function-mask = <0x0000001f>; + }; + main_crypto: crypto@4e00000 { compatible = "ti,j721e-sa2ul"; reg = <0x00 0x4e00000 0x00 0x1200>; @@ -91,6 +109,246 @@ }; }; + main_timer0: timer@2400000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x2400000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 97 2>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 97 2>; + assigned-clock-parents = <&k3_clks 97 3>; + power-domains = <&k3_pds 97 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer1: timer@2410000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x2410000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 98 2>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 98 2>; + assigned-clock-parents = <&k3_clks 98 3>; + power-domains = <&k3_pds 98 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer2: timer@2420000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x2420000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 99 2>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 99 2>; + assigned-clock-parents = <&k3_clks 99 3>; + power-domains = <&k3_pds 99 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer3: timer@2430000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x2430000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 100 2>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 100 2>; + assigned-clock-parents = <&k3_clks 100 3>; + power-domains = <&k3_pds 100 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer4: timer@2440000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x2440000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 101 2>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 101 2>; + assigned-clock-parents = <&k3_clks 101 3>; + power-domains = <&k3_pds 101 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer5: timer@2450000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x2450000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 102 2>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 102 2>; + assigned-clock-parents = <&k3_clks 102 3>; + power-domains = <&k3_pds 102 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer6: timer@2460000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x2460000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 103 2>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 103 2>; + assigned-clock-parents = <&k3_clks 103 3>; + power-domains = <&k3_pds 103 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer7: timer@2470000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x2470000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 104 2>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 104 2>; + assigned-clock-parents = <&k3_clks 104 3>; + power-domains = <&k3_pds 104 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer8: timer@2480000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x2480000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 105 2>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 105 2>; + assigned-clock-parents = <&k3_clks 105 3>; + power-domains = <&k3_pds 105 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer9: timer@2490000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x2490000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 106 2>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 106 2>; + assigned-clock-parents = <&k3_clks 106 3>; + power-domains = <&k3_pds 106 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer10: timer@24a0000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x24a0000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 107 2>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 107 2>; + assigned-clock-parents = <&k3_clks 107 3>; + power-domains = <&k3_pds 107 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer11: timer@24b0000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x24b0000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 108 2>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 108 2>; + assigned-clock-parents = <&k3_clks 108 3>; + power-domains = <&k3_pds 108 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer12: timer@24c0000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x24c0000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 109 2>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 109 2>; + assigned-clock-parents = <&k3_clks 109 3>; + power-domains = <&k3_pds 109 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer13: timer@24d0000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x24d0000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 110 2>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 110 2>; + assigned-clock-parents = <&k3_clks 110 3>; + power-domains = <&k3_pds 110 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer14: timer@24e0000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x24e0000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 111 2>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 111 2>; + assigned-clock-parents = <&k3_clks 111 3>; + power-domains = <&k3_pds 111 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer15: timer@24f0000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x24f0000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 112 2>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 112 2>; + assigned-clock-parents = <&k3_clks 112 3>; + power-domains = <&k3_pds 112 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer16: timer@2500000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x2500000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 113 2>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 113 2>; + assigned-clock-parents = <&k3_clks 113 3>; + power-domains = <&k3_pds 113 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer17: timer@2510000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x2510000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 114 2>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 114 2>; + assigned-clock-parents = <&k3_clks 114 3>; + power-domains = <&k3_pds 114 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer18: timer@2520000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x2520000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 115 2>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 115 2>; + assigned-clock-parents = <&k3_clks 115 3>; + power-domains = <&k3_pds 115 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + + main_timer19: timer@2530000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x2530000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 116 2>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 116 2>; + assigned-clock-parents = <&k3_clks 116 3>; + power-domains = <&k3_pds 116 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + }; + main_uart0: serial@2800000 { compatible = "ti,j721e-uart", "ti,am654-uart"; reg = <0x00 0x02800000 0x00 0x200>; @@ -378,7 +636,6 @@ mmc-hs200-1_8v; mmc-hs400-1_8v; dma-coherent; - no-1-8-v; status = "disabled"; }; @@ -1112,4 +1369,172 @@ clocks = <&k3_clks 383 1>; status = "disabled"; }; + + main_r5fss0: r5fss@5c00000 { + compatible = "ti,j721s2-r5fss"; + ti,cluster-mode = <1>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x5c00000 0x00 0x5c00000 0x20000>, + <0x5d00000 0x00 0x5d00000 0x20000>; + power-domains = <&k3_pds 336 TI_SCI_PD_EXCLUSIVE>; + + main_r5fss0_core0: r5f@5c00000 { + compatible = "ti,j721s2-r5f"; + reg = <0x5c00000 0x00010000>, + <0x5c10000 0x00010000>; + reg-names = "atcm", "btcm"; + ti,sci = <&sms>; + ti,sci-dev-id = <339>; + ti,sci-proc-ids = <0x06 0xff>; + resets = <&k3_reset 339 1>; + firmware-name = "j784s4-main-r5f0_0-fw"; + ti,atcm-enable = <1>; + ti,btcm-enable = <1>; + ti,loczrama = <1>; + }; + + main_r5fss0_core1: r5f@5d00000 { + compatible = "ti,j721s2-r5f"; + reg = <0x5d00000 0x00010000>, + <0x5d10000 0x00010000>; + reg-names = "atcm", "btcm"; + ti,sci = <&sms>; + ti,sci-dev-id = <340>; + ti,sci-proc-ids = <0x07 0xff>; + resets = <&k3_reset 340 1>; + firmware-name = "j784s4-main-r5f0_1-fw"; + ti,atcm-enable = <1>; + ti,btcm-enable = <1>; + ti,loczrama = <1>; + }; + }; + + main_r5fss1: r5fss@5e00000 { + compatible = "ti,j721s2-r5fss"; + ti,cluster-mode = <1>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x5e00000 0x00 0x5e00000 0x20000>, + <0x5f00000 0x00 0x5f00000 0x20000>; + power-domains = <&k3_pds 337 TI_SCI_PD_EXCLUSIVE>; + + main_r5fss1_core0: r5f@5e00000 { + compatible = "ti,j721s2-r5f"; + reg = <0x5e00000 0x00010000>, + <0x5e10000 0x00010000>; + reg-names = "atcm", "btcm"; + ti,sci = <&sms>; + ti,sci-dev-id = <341>; + ti,sci-proc-ids = <0x08 0xff>; + resets = <&k3_reset 341 1>; + firmware-name = "j784s4-main-r5f1_0-fw"; + ti,atcm-enable = <1>; + ti,btcm-enable = <1>; + ti,loczrama = <1>; + }; + + main_r5fss1_core1: r5f@5f00000 { + compatible = "ti,j721s2-r5f"; + reg = <0x5f00000 0x00010000>, + <0x5f10000 0x00010000>; + reg-names = "atcm", "btcm"; + ti,sci = <&sms>; + ti,sci-dev-id = <342>; + ti,sci-proc-ids = <0x09 0xff>; + resets = <&k3_reset 342 1>; + firmware-name = "j784s4-main-r5f1_1-fw"; + ti,atcm-enable = <1>; + ti,btcm-enable = <1>; + ti,loczrama = <1>; + }; + }; + + main_r5fss2: r5fss@5900000 { + compatible = "ti,j721s2-r5fss"; + ti,cluster-mode = <1>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x5900000 0x00 0x5900000 0x20000>, + <0x5a00000 0x00 0x5a00000 0x20000>; + power-domains = <&k3_pds 338 TI_SCI_PD_EXCLUSIVE>; + + main_r5fss2_core0: r5f@5900000 { + compatible = "ti,j721s2-r5f"; + reg = <0x5900000 0x00010000>, + <0x5910000 0x00010000>; + reg-names = "atcm", "btcm"; + ti,sci = <&sms>; + ti,sci-dev-id = <343>; + ti,sci-proc-ids = <0x0a 0xff>; + resets = <&k3_reset 343 1>; + firmware-name = "j784s4-main-r5f2_0-fw"; + ti,atcm-enable = <1>; + ti,btcm-enable = <1>; + ti,loczrama = <1>; + }; + + main_r5fss2_core1: r5f@5a00000 { + compatible = "ti,j721s2-r5f"; + reg = <0x5a00000 0x00010000>, + <0x5a10000 0x00010000>; + reg-names = "atcm", "btcm"; + ti,sci = <&sms>; + ti,sci-dev-id = <344>; + ti,sci-proc-ids = <0x0b 0xff>; + resets = <&k3_reset 344 1>; + firmware-name = "j784s4-main-r5f2_1-fw"; + ti,atcm-enable = <1>; + ti,btcm-enable = <1>; + ti,loczrama = <1>; + }; + }; + + c71_0: dsp@64800000 { + compatible = "ti,j721s2-c71-dsp"; + reg = <0x00 0x64800000 0x00 0x00080000>, + <0x00 0x64e00000 0x00 0x0000c000>; + reg-names = "l2sram", "l1dram"; + ti,sci = <&sms>; + ti,sci-dev-id = <30>; + ti,sci-proc-ids = <0x30 0xff>; + resets = <&k3_reset 30 1>; + firmware-name = "j784s4-c71_0-fw"; + }; + + c71_1: dsp@65800000 { + compatible = "ti,j721s2-c71-dsp"; + reg = <0x00 0x65800000 0x00 0x00080000>, + <0x00 0x65e00000 0x00 0x0000c000>; + reg-names = "l2sram", "l1dram"; + ti,sci = <&sms>; + ti,sci-dev-id = <33>; + ti,sci-proc-ids = <0x31 0xff>; + resets = <&k3_reset 33 1>; + firmware-name = "j784s4-c71_1-fw"; + }; + + c71_2: dsp@66800000 { + compatible = "ti,j721s2-c71-dsp"; + reg = <0x00 0x66800000 0x00 0x00080000>, + <0x00 0x66e00000 0x00 0x0000c000>; + reg-names = "l2sram", "l1dram"; + ti,sci = <&sms>; + ti,sci-dev-id = <37>; + ti,sci-proc-ids = <0x32 0xff>; + resets = <&k3_reset 37 1>; + firmware-name = "j784s4-c71_2-fw"; + }; + + c71_3: dsp@67800000 { + compatible = "ti,j721s2-c71-dsp"; + reg = <0x00 0x67800000 0x00 0x00080000>, + <0x00 0x67e00000 0x00 0x0000c000>; + reg-names = "l2sram", "l1dram"; + ti,sci = <&sms>; + ti,sci-dev-id = <40>; + ti,sci-proc-ids = <0x33 0xff>; + resets = <&k3_reset 40 1>; + firmware-name = "j784s4-c71_3-fw"; + }; }; diff --git a/arch/arm64/boot/dts/ti/k3-j784s4-mcu-wakeup.dtsi b/arch/arm64/boot/dts/ti/k3-j784s4-mcu-wakeup.dtsi index f04fcb614cbe4f64a9bf8a7d9d996967b0ec4832..657fb1d72512cee4cb18ea2e82492313646169ad 100644 --- a/arch/arm64/boot/dts/ti/k3-j784s4-mcu-wakeup.dtsi +++ b/arch/arm64/boot/dts/ti/k3-j784s4-mcu-wakeup.dtsi @@ -39,6 +39,21 @@ reg = <0x00 0x43000014 0x00 0x4>; }; + secure_proxy_sa3: mailbox@43600000 { + compatible = "ti,am654-secure-proxy"; + #mbox-cells = <1>; + reg-names = "target_data", "rt", "scfg"; + reg = <0x00 0x43600000 0x00 0x10000>, + <0x00 0x44880000 0x00 0x20000>, + <0x00 0x44860000 0x00 0x20000>; + /* + * Marked Disabled: + * Node is incomplete as it is meant for bootloaders and + * firmware on non-MPU processors + */ + status = "disabled"; + }; + mcu_ram: sram@41c00000 { compatible = "mmio-sram"; reg = <0x00 0x41c00000 0x00 0x100000>; @@ -50,7 +65,34 @@ wkup_pmx0: pinctrl@4301c000 { compatible = "pinctrl-single"; /* Proxy 0 addressing */ - reg = <0x00 0x4301c000 0x00 0x178>; + reg = <0x00 0x4301c000 0x00 0x034>; + #pinctrl-cells = <1>; + pinctrl-single,register-width = <32>; + pinctrl-single,function-mask = <0xffffffff>; + }; + + wkup_pmx1: pinctrl@4301c038 { + compatible = "pinctrl-single"; + /* Proxy 0 addressing */ + reg = <0x00 0x4301c038 0x00 0x02c>; + #pinctrl-cells = <1>; + pinctrl-single,register-width = <32>; + pinctrl-single,function-mask = <0xffffffff>; + }; + + wkup_pmx2: pinctrl@4301c068 { + compatible = "pinctrl-single"; + /* Proxy 0 addressing */ + reg = <0x00 0x4301c068 0x00 0x120>; + #pinctrl-cells = <1>; + pinctrl-single,register-width = <32>; + pinctrl-single,function-mask = <0xffffffff>; + }; + + wkup_pmx3: pinctrl@4301c190 { + compatible = "pinctrl-single"; + /* Proxy 0 addressing */ + reg = <0x00 0x4301c190 0x00 0x004>; #pinctrl-cells = <1>; pinctrl-single,register-width = <32>; pinctrl-single,function-mask = <0xffffffff>; @@ -68,6 +110,28 @@ ti,interrupt-ranges = <16 928 16>; }; + /* MCU_TIMERIO pad input CTRLMMR_MCU_TIMER*_CTRL registers */ + mcu_timerio_input: pinctrl@40f04200 { + compatible = "pinctrl-single"; + reg = <0x00 0x40f04200 0x00 0x28>; + #pinctrl-cells = <1>; + pinctrl-single,register-width = <32>; + pinctrl-single,function-mask = <0x0000000f>; + /* Non-MPU Firmware usage */ + status = "reserved"; + }; + + /* MCU_TIMERIO pad output CTRLMMR_MCU_TIMERIO*_CTRL registers */ + mcu_timerio_output: pinctrl@40f04280 { + compatible = "pinctrl-single"; + reg = <0x00 0x40f04280 0x00 0x28>; + #pinctrl-cells = <1>; + pinctrl-single,register-width = <32>; + pinctrl-single,function-mask = <0x0000000f>; + /* Non-MPU Firmware usage */ + status = "reserved"; + }; + mcu_conf: syscon@40f00000 { compatible = "ti,j721e-system-controller", "syscon", "simple-mfd"; reg = <0x00 0x40f00000 0x00 0x20000>; @@ -82,6 +146,146 @@ }; }; + mcu_timer0: timer@40400000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x40400000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 35 2>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 35 2>; + assigned-clock-parents = <&k3_clks 35 3>; + power-domains = <&k3_pds 35 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + /* Non-MPU Firmware usage */ + status = "reserved"; + }; + + mcu_timer1: timer@40410000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x40410000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 117 2>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 117 2>; + assigned-clock-parents = <&k3_clks 117 3>; + power-domains = <&k3_pds 117 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + /* Non-MPU Firmware usage */ + status = "reserved"; + }; + + mcu_timer2: timer@40420000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x40420000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 118 2>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 118 2>; + assigned-clock-parents = <&k3_clks 118 3>; + power-domains = <&k3_pds 118 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + /* Non-MPU Firmware usage */ + status = "reserved"; + }; + + mcu_timer3: timer@40430000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x40430000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 119 2>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 119 2>; + assigned-clock-parents = <&k3_clks 119 3>; + power-domains = <&k3_pds 119 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + /* Non-MPU Firmware usage */ + status = "reserved"; + }; + + mcu_timer4: timer@40440000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x40440000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 120 2>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 120 2>; + assigned-clock-parents = <&k3_clks 120 3>; + power-domains = <&k3_pds 120 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + /* Non-MPU Firmware usage */ + status = "reserved"; + }; + + mcu_timer5: timer@40450000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x40450000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 121 2>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 121 2>; + assigned-clock-parents = <&k3_clks 121 3>; + power-domains = <&k3_pds 121 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + /* Non-MPU Firmware usage */ + status = "reserved"; + }; + + mcu_timer6: timer@40460000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x40460000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 122 2>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 122 2>; + assigned-clock-parents = <&k3_clks 122 3>; + power-domains = <&k3_pds 122 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + /* Non-MPU Firmware usage */ + status = "reserved"; + }; + + mcu_timer7: timer@40470000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x40470000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 123 2>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 123 2>; + assigned-clock-parents = <&k3_clks 123 3>; + power-domains = <&k3_pds 123 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + /* Non-MPU Firmware usage */ + status = "reserved"; + }; + + mcu_timer8: timer@40480000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x40480000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 124 2>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 124 2>; + assigned-clock-parents = <&k3_clks 124 3>; + power-domains = <&k3_pds 124 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + /* Non-MPU Firmware usage */ + status = "reserved"; + }; + + mcu_timer9: timer@40490000 { + compatible = "ti,am654-timer"; + reg = <0x00 0x40490000 0x00 0x400>; + interrupts = ; + clocks = <&k3_clks 125 2>; + clock-names = "fck"; + assigned-clocks = <&k3_clks 125 2>; + assigned-clock-parents = <&k3_clks 125 3>; + power-domains = <&k3_pds 125 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; + /* Non-MPU Firmware usage */ + status = "reserved"; + }; + wkup_uart0: serial@42300000 { compatible = "ti,j721e-uart", "ti,am654-uart"; reg = <0x00 0x42300000 0x00 0x200>; @@ -280,6 +484,21 @@ }; }; + secure_proxy_mcu: mailbox@2a480000 { + compatible = "ti,am654-secure-proxy"; + #mbox-cells = <1>; + reg-names = "target_data", "rt", "scfg"; + reg = <0x00 0x2a480000 0x00 0x80000>, + <0x00 0x2a380000 0x00 0x80000>, + <0x00 0x2a400000 0x00 0x80000>; + /* + * Marked Disabled: + * Node is incomplete as it is meant for bootloaders and + * firmware on non-MPU processors + */ + status = "disabled"; + }; + mcu_cpsw: ethernet@46000000 { compatible = "ti,j721e-cpsw-nuss"; #address-cells = <2>; @@ -342,4 +561,133 @@ ti,cpts-periodic-outputs = <2>; }; }; + + mcu_r5fss0: r5fss@41000000 { + compatible = "ti,j721s2-r5fss"; + ti,cluster-mode = <1>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x41000000 0x00 0x41000000 0x20000>, + <0x41400000 0x00 0x41400000 0x20000>; + power-domains = <&k3_pds 345 TI_SCI_PD_EXCLUSIVE>; + + mcu_r5fss0_core0: r5f@41000000 { + compatible = "ti,j721s2-r5f"; + reg = <0x41000000 0x00010000>, + <0x41010000 0x00010000>; + reg-names = "atcm", "btcm"; + ti,sci = <&sms>; + ti,sci-dev-id = <346>; + ti,sci-proc-ids = <0x01 0xff>; + resets = <&k3_reset 346 1>; + firmware-name = "j784s4-mcu-r5f0_0-fw"; + ti,atcm-enable = <1>; + ti,btcm-enable = <1>; + ti,loczrama = <1>; + }; + + mcu_r5fss0_core1: r5f@41400000 { + compatible = "ti,j721s2-r5f"; + reg = <0x41400000 0x00010000>, + <0x41410000 0x00010000>; + reg-names = "atcm", "btcm"; + ti,sci = <&sms>; + ti,sci-dev-id = <347>; + ti,sci-proc-ids = <0x02 0xff>; + resets = <&k3_reset 347 1>; + firmware-name = "j784s4-mcu-r5f0_1-fw"; + ti,atcm-enable = <1>; + ti,btcm-enable = <1>; + ti,loczrama = <1>; + }; + }; + + wkup_vtm0: temperature-sensor@42040000 { + compatible = "ti,j7200-vtm"; + reg = <0x00 0x42040000 0x00 0x350>, + <0x00 0x42050000 0x00 0x350>; + power-domains = <&k3_pds 154 TI_SCI_PD_SHARED>; + #thermal-sensor-cells = <1>; + }; + + tscadc0: tscadc@40200000 { + compatible = "ti,am3359-tscadc"; + reg = <0x00 0x40200000 0x00 0x1000>; + interrupts = ; + power-domains = <&k3_pds 0 TI_SCI_PD_EXCLUSIVE>; + clocks = <&k3_clks 0 0>; + assigned-clocks = <&k3_clks 0 2>; + assigned-clock-rates = <60000000>; + clock-names = "fck"; + dmas = <&main_udmap 0x7400>, + <&main_udmap 0x7401>; + dma-names = "fifo0", "fifo1"; + status = "disabled"; + + adc { + #io-channel-cells = <1>; + compatible = "ti,am3359-adc"; + }; + }; + + tscadc1: tscadc@40210000 { + compatible = "ti,am3359-tscadc"; + reg = <0x00 0x40210000 0x00 0x1000>; + interrupts = ; + power-domains = <&k3_pds 1 TI_SCI_PD_EXCLUSIVE>; + clocks = <&k3_clks 1 0>; + assigned-clocks = <&k3_clks 1 2>; + assigned-clock-rates = <60000000>; + clock-names = "fck"; + dmas = <&main_udmap 0x7402>, + <&main_udmap 0x7403>; + dma-names = "fifo0", "fifo1"; + status = "disabled"; + + adc { + #io-channel-cells = <1>; + compatible = "ti,am3359-adc"; + }; + }; + + fss: bus@47000000 { + compatible = "simple-bus"; + reg = <0x00 0x47000000 0x00 0x100>; + #address-cells = <2>; + #size-cells = <2>; + ranges; + + ospi0: spi@47040000 { + compatible = "ti,am654-ospi", "cdns,qspi-nor"; + reg = <0x00 0x47040000 0x00 0x100>, + <0x05 0x0000000 0x01 0x0000000>; + interrupts = ; + cdns,fifo-depth = <256>; + cdns,fifo-width = <4>; + cdns,trigger-address = <0x0>; + clocks = <&k3_clks 161 7>; + assigned-clocks = <&k3_clks 161 7>; + assigned-clock-parents = <&k3_clks 161 9>; + assigned-clock-rates = <166666666>; + power-domains = <&k3_pds 161 TI_SCI_PD_EXCLUSIVE>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + ospi1: spi@47050000 { + compatible = "ti,am654-ospi", "cdns,qspi-nor"; + reg = <0x00 0x47050000 0x00 0x100>, + <0x07 0x0000000 0x01 0x0000000>; + interrupts = ; + cdns,fifo-depth = <256>; + cdns,fifo-width = <4>; + cdns,trigger-address = <0x0>; + clocks = <&k3_clks 162 7>; + power-domains = <&k3_pds 162 TI_SCI_PD_EXCLUSIVE>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + }; }; diff --git a/arch/arm64/boot/dts/ti/k3-j784s4-thermal.dtsi b/arch/arm64/boot/dts/ti/k3-j784s4-thermal.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..f7b1a15b8fa0a29083ff2727af6223e44ff7f9f5 --- /dev/null +++ b/arch/arm64/boot/dts/ti/k3-j784s4-thermal.dtsi @@ -0,0 +1,101 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include + +wkup0_thermal: wkup0-thermal { + polling-delay-passive = <250>; /* milliseconds */ + polling-delay = <500>; /* milliseconds */ + thermal-sensors = <&wkup_vtm0 0>; + + trips { + wkup0_crit: wkup0-crit { + temperature = <125000>; /* milliCelsius */ + hysteresis = <2000>; /* milliCelsius */ + type = "critical"; + }; + }; +}; + +wkup1_thermal: wkup1-thermal { + polling-delay-passive = <250>; /* milliseconds */ + polling-delay = <500>; /* milliseconds */ + thermal-sensors = <&wkup_vtm0 1>; + + trips { + wkup1_crit: wkup1-crit { + temperature = <125000>; /* milliCelsius */ + hysteresis = <2000>; /* milliCelsius */ + type = "critical"; + }; + }; +}; + +main0_thermal: main0-thermal { + polling-delay-passive = <250>; /* milliseconds */ + polling-delay = <500>; /* milliseconds */ + thermal-sensors = <&wkup_vtm0 2>; + + trips { + main0_crit: main0-crit { + temperature = <125000>; /* milliCelsius */ + hysteresis = <2000>; /* milliCelsius */ + type = "critical"; + }; + }; +}; + +main1_thermal: main1-thermal { + polling-delay-passive = <250>; /* milliseconds */ + polling-delay = <500>; /* milliseconds */ + thermal-sensors = <&wkup_vtm0 3>; + + trips { + main1_crit: main1-crit { + temperature = <125000>; /* milliCelsius */ + hysteresis = <2000>; /* milliCelsius */ + type = "critical"; + }; + }; +}; + +main2_thermal: main2-thermal { + polling-delay-passive = <250>; /* milliseconds */ + polling-delay = <500>; /* milliseconds */ + thermal-sensors = <&wkup_vtm0 4>; + + trips { + main2_crit: main2-crit { + temperature = <125000>; /* milliCelsius */ + hysteresis = <2000>; /* milliCelsius */ + type = "critical"; + }; + }; +}; + +main3_thermal: main3-thermal { + polling-delay-passive = <250>; /* milliseconds */ + polling-delay = <500>; /* milliseconds */ + thermal-sensors = <&wkup_vtm0 5>; + + trips { + main3_crit: main3-crit { + temperature = <125000>; /* milliCelsius */ + hysteresis = <2000>; /* milliCelsius */ + type = "critical"; + }; + }; +}; + +main4_thermal: main4-thermal { + polling-delay-passive = <250>; /* milliseconds */ + polling-delay = <500>; /* milliseconds */ + thermal-sensors = <&wkup_vtm0 6>; + + trips { + main4_crit: main4-crit { + temperature = <125000>; /* milliCelsius */ + hysteresis = <2000>; /* milliCelsius */ + type = "critical"; + }; + }; +}; diff --git a/arch/arm64/boot/dts/ti/k3-j784s4.dtsi b/arch/arm64/boot/dts/ti/k3-j784s4.dtsi index 2e03d84da7d2e79bab826b0d593c16762dc514c1..8b5974d92e33af3a3a92ea9f06d8ffef8fbc64a0 100644 --- a/arch/arm64/boot/dts/ti/k3-j784s4.dtsi +++ b/arch/arm64/boot/dts/ti/k3-j784s4.dtsi @@ -2,7 +2,7 @@ /* * Device Tree Source for J784S4 SoC Family * - * TRM (SPRUJ43 JULY 2022) : http://www.ti.com/lit/zip/spruj52 + * TRM (SPRUJ43 JULY 2022): https://www.ti.com/lit/zip/spruj52 * * Copyright (C) 2022 Texas Instruments Incorporated - https://www.ti.com/ * @@ -281,6 +281,10 @@ <0x07 0x00000000 0x07 0x00000000 0x01 0x00000000>; /* FSS OSPI1 data region 3*/ }; }; + + thermal_zones: thermal-zones { + #include "k3-j784s4-thermal.dtsi" + }; }; /* Now include peripherals from each bus segment */ diff --git a/arch/arm64/boot/dts/xilinx/Makefile b/arch/arm64/boot/dts/xilinx/Makefile index 4e159540d0314cb3395e4e45b1b3f2852001c6fc..5e40c0b4fa0a9087f9bdb082d14c5c9bcc5af3aa 100644 --- a/arch/arm64/boot/dts/xilinx/Makefile +++ b/arch/arm64/boot/dts/xilinx/Makefile @@ -2,7 +2,6 @@ dtb-$(CONFIG_ARCH_ZYNQMP) += avnet-ultra96-rev1.dtb dtb-$(CONFIG_ARCH_ZYNQMP) += zynqmp-zc1232-revA.dtb dtb-$(CONFIG_ARCH_ZYNQMP) += zynqmp-zc1254-revA.dtb -dtb-$(CONFIG_ARCH_ZYNQMP) += zynqmp-zc1275-revA.dtb dtb-$(CONFIG_ARCH_ZYNQMP) += zynqmp-zc1751-xm015-dc1.dtb dtb-$(CONFIG_ARCH_ZYNQMP) += zynqmp-zc1751-xm016-dc2.dtb dtb-$(CONFIG_ARCH_ZYNQMP) += zynqmp-zc1751-xm017-dc3.dtb @@ -17,16 +16,17 @@ dtb-$(CONFIG_ARCH_ZYNQMP) += zynqmp-zcu104-revA.dtb dtb-$(CONFIG_ARCH_ZYNQMP) += zynqmp-zcu104-revC.dtb dtb-$(CONFIG_ARCH_ZYNQMP) += zynqmp-zcu106-revA.dtb dtb-$(CONFIG_ARCH_ZYNQMP) += zynqmp-zcu111-revA.dtb +dtb-$(CONFIG_ARCH_ZYNQMP) += zynqmp-zcu1275-revA.dtb dtb-$(CONFIG_ARCH_ZYNQMP) += zynqmp-sm-k26-revA.dtb dtb-$(CONFIG_ARCH_ZYNQMP) += zynqmp-smk-k26-revA.dtb -sm-k26-revA-sck-kv-g-revA-dtbs := zynqmp-sm-k26-revA.dtb zynqmp-sck-kv-g-revA.dtbo -sm-k26-revA-sck-kv-g-revB-dtbs := zynqmp-sm-k26-revA.dtb zynqmp-sck-kv-g-revB.dtbo -smk-k26-revA-sm-k26-revA-sck-kv-g-revA-dtbs := zynqmp-smk-k26-revA.dtb zynqmp-sck-kv-g-revA.dtbo -smk-k26-revA-sm-k26-revA-sck-kv-g-revB-dtbs := zynqmp-smk-k26-revA.dtb zynqmp-sck-kv-g-revB.dtbo +zynqmp-sm-k26-revA-sck-kv-g-revA-dtbs := zynqmp-sm-k26-revA.dtb zynqmp-sck-kv-g-revA.dtbo +zynqmp-sm-k26-revA-sck-kv-g-revB-dtbs := zynqmp-sm-k26-revA.dtb zynqmp-sck-kv-g-revB.dtbo +zynqmp-smk-k26-revA-sck-kv-g-revA-dtbs := zynqmp-smk-k26-revA.dtb zynqmp-sck-kv-g-revA.dtbo +zynqmp-smk-k26-revA-sck-kv-g-revB-dtbs := zynqmp-smk-k26-revA.dtb zynqmp-sck-kv-g-revB.dtbo -dtb-$(CONFIG_ARCH_ZYNQMP) += sm-k26-revA-sck-kv-g-revA.dtb -dtb-$(CONFIG_ARCH_ZYNQMP) += sm-k26-revA-sck-kv-g-revB.dtb -dtb-$(CONFIG_ARCH_ZYNQMP) += smk-k26-revA-sm-k26-revA-sck-kv-g-revA.dtb -dtb-$(CONFIG_ARCH_ZYNQMP) += smk-k26-revA-sm-k26-revA-sck-kv-g-revB.dtb +zynqmp-sm-k26-revA-sck-kr-g-revA-dtbs := zynqmp-sm-k26-revA.dtb zynqmp-sck-kr-g-revA.dtbo +zynqmp-sm-k26-revA-sck-kr-g-revB-dtbs := zynqmp-sm-k26-revA.dtb zynqmp-sck-kr-g-revB.dtbo +zynqmp-smk-k26-revA-sck-kr-g-revA-dtbs := zynqmp-smk-k26-revA.dtb zynqmp-sck-kr-g-revA.dtbo +zynqmp-smk-k26-revA-sck-kr-g-revB-dtbs := zynqmp-smk-k26-revA.dtb zynqmp-sck-kr-g-revB.dtbo diff --git a/arch/arm64/boot/dts/xilinx/avnet-ultra96-rev1.dts b/arch/arm64/boot/dts/xilinx/avnet-ultra96-rev1.dts index 88aa06fa78a8c57315d51495c194cc7be5e1337e..4c1bd69e7553e288fb20deeda4accb3ecd983d63 100644 --- a/arch/arm64/boot/dts/xilinx/avnet-ultra96-rev1.dts +++ b/arch/arm64/boot/dts/xilinx/avnet-ultra96-rev1.dts @@ -4,7 +4,7 @@ * * (C) Copyright 2018, Xilinx, Inc. * - * Michal Simek + * Michal Simek */ /dts-v1/; diff --git a/arch/arm64/boot/dts/xilinx/zynqmp-clk-ccf.dtsi b/arch/arm64/boot/dts/xilinx/zynqmp-clk-ccf.dtsi index 3e9979ab60bbcdf1b0e9381738988ca7b1362177..f04716841a0c0e65dc4c3ed18884c5a381511bbf 100644 --- a/arch/arm64/boot/dts/xilinx/zynqmp-clk-ccf.dtsi +++ b/arch/arm64/boot/dts/xilinx/zynqmp-clk-ccf.dtsi @@ -2,38 +2,44 @@ /* * Clock specification for Xilinx ZynqMP * - * (C) Copyright 2017 - 2021, Xilinx, Inc. + * (C) Copyright 2017 - 2022, Xilinx, Inc. + * (C) Copyright 2022 - 2023, Advanced Micro Devices, Inc. * - * Michal Simek + * Michal Simek */ #include / { pss_ref_clk: pss_ref_clk { + bootph-all; compatible = "fixed-clock"; #clock-cells = <0>; clock-frequency = <33333333>; }; video_clk: video_clk { + bootph-all; compatible = "fixed-clock"; #clock-cells = <0>; clock-frequency = <27000000>; }; pss_alt_ref_clk: pss_alt_ref_clk { + bootph-all; compatible = "fixed-clock"; #clock-cells = <0>; clock-frequency = <0>; }; gt_crx_ref_clk: gt_crx_ref_clk { + bootph-all; compatible = "fixed-clock"; #clock-cells = <0>; clock-frequency = <108000000>; }; aux_ref_clk: aux_ref_clk { + bootph-all; compatible = "fixed-clock"; #clock-cells = <0>; clock-frequency = <27000000>; @@ -42,6 +48,7 @@ &zynqmp_firmware { zynqmp_clk: clock-controller { + bootph-all; #clock-cells = <1>; compatible = "xlnx,zynqmp-clk"; clocks = <&pss_ref_clk>, <&video_clk>, <&pss_alt_ref_clk>, @@ -95,6 +102,10 @@ clocks = <&zynqmp_clk GDMA_REF>, <&zynqmp_clk LPD_LSBUS>; }; +&gpu { + clocks = <&zynqmp_clk GPU_REF>, <&zynqmp_clk GPU_PP0_REF>; +}; + &lpd_dma_chan1 { clocks = <&zynqmp_clk ADMA_REF>, <&zynqmp_clk LPD_LSBUS>; }; @@ -181,10 +192,12 @@ &sdhci0 { clocks = <&zynqmp_clk SDIO0_REF>, <&zynqmp_clk LPD_LSBUS>; + assigned-clocks = <&zynqmp_clk SDIO0_REF>; }; &sdhci1 { clocks = <&zynqmp_clk SDIO1_REF>, <&zynqmp_clk LPD_LSBUS>; + assigned-clocks = <&zynqmp_clk SDIO1_REF>; }; &spi0 { @@ -241,10 +254,14 @@ &zynqmp_dpdma { clocks = <&zynqmp_clk DPDMA_REF>; + assigned-clocks = <&zynqmp_clk DPDMA_REF>; /* apll */ }; &zynqmp_dpsub { clocks = <&zynqmp_clk TOPSW_LSBUS>, <&zynqmp_clk DP_AUDIO_REF>, <&zynqmp_clk DP_VIDEO_REF>; + assigned-clocks = <&zynqmp_clk DP_STC_REF>, + <&zynqmp_clk DP_AUDIO_REF>, + <&zynqmp_clk DP_VIDEO_REF>; /* rpll, rpll, vpll */ }; diff --git a/arch/arm64/boot/dts/xilinx/zynqmp-sck-kv-g-revA.dtso b/arch/arm64/boot/dts/xilinx/zynqmp-sck-kv-g-revA.dtso index b610e65e0cdfee767fe7a2b5235935bdb9b83dfc..603839c8259917a07d81d423ffe3147850d2bffa 100644 --- a/arch/arm64/boot/dts/xilinx/zynqmp-sck-kv-g-revA.dtso +++ b/arch/arm64/boot/dts/xilinx/zynqmp-sck-kv-g-revA.dtso @@ -2,14 +2,15 @@ /* * dts file for KV260 revA Carrier Card * - * (C) Copyright 2020 - 2021, Xilinx, Inc. + * (C) Copyright 2020 - 2022, Xilinx, Inc. + * (C) Copyright 2022 - 2023, Advanced Micro Devices, Inc. * * SD level shifter: - * "A" – A01 board un-modified (NXP) - * "Y" – A01 board modified with legacy interposer (Nexperia) - * "Z" – A01 board modified with Diode interposer + * "A" - A01 board un-modified (NXP) + * "Y" - A01 board modified with legacy interposer (Nexperia) + * "Z" - A01 board modified with Diode interposer * - * Michal Simek + * Michal Simek */ #include @@ -95,13 +96,15 @@ }; &zynqmp_dpsub { - status = "disabled"; + status = "okay"; phy-names = "dp-phy0", "dp-phy1"; phys = <&psgtr 1 PHY_TYPE_DP 0 0>, <&psgtr 0 PHY_TYPE_DP 1 0>; + assigned-clock-rates = <27000000>, <25000000>, <300000000>; }; &zynqmp_dpdma { status = "okay"; + assigned-clock-rates = <600000000>; }; &usb0 { @@ -132,6 +135,8 @@ no-1-8-v; disable-wp; xlnx,mio-bank = <1>; + assigned-clock-rates = <187498123>; + bus-width = <4>; }; &gem3 { /* required by spec */ @@ -144,16 +149,18 @@ mdio: mdio { #address-cells = <1>; #size-cells = <0>; - reset-gpios = <&gpio 38 GPIO_ACTIVE_LOW>; - reset-delay-us = <2>; phy0: ethernet-phy@1 { #phy-cells = <1>; reg = <1>; + compatible = "ethernet-phy-id2000.a231"; ti,rx-internal-delay = ; ti,tx-internal-delay = ; ti,fifo-depth = ; ti,dp83867-rxctrl-strap-quirk; + reset-assert-us = <100>; + reset-deassert-us = <280>; + reset-gpios = <&gpio 38 GPIO_ACTIVE_LOW>; }; }; }; @@ -259,19 +266,22 @@ pinctrl_usb0_default: usb0-default { conf { groups = "usb0_0_grp"; - slew-rate = ; power-source = ; }; conf-rx { pins = "MIO52", "MIO53", "MIO55"; bias-high-impedance; + drive-strength = <12>; + slew-rate = ; }; conf-tx { pins = "MIO54", "MIO56", "MIO57", "MIO58", "MIO59", "MIO60", "MIO61", "MIO62", "MIO63"; bias-disable; + drive-strength = <4>; + slew-rate = ; }; mux { diff --git a/arch/arm64/boot/dts/xilinx/zynqmp-sck-kv-g-revB.dtso b/arch/arm64/boot/dts/xilinx/zynqmp-sck-kv-g-revB.dtso index a52dafbfd59e70e0924a73044c97b04c30945cc2..a91d09e7da4bca14916e588b4a0b4231a765fb5c 100644 --- a/arch/arm64/boot/dts/xilinx/zynqmp-sck-kv-g-revB.dtso +++ b/arch/arm64/boot/dts/xilinx/zynqmp-sck-kv-g-revB.dtso @@ -2,9 +2,10 @@ /* * dts file for KV260 revA Carrier Card * - * (C) Copyright 2020 - 2021, Xilinx, Inc. + * (C) Copyright 2020 - 2022, Xilinx, Inc. + * (C) Copyright 2022 - 2023, Advanced Micro Devices, Inc. * - * Michal Simek + * Michal Simek */ #include @@ -76,13 +77,15 @@ }; &zynqmp_dpsub { - status = "disabled"; + status = "okay"; phy-names = "dp-phy0", "dp-phy1"; phys = <&psgtr 1 PHY_TYPE_DP 0 0>, <&psgtr 0 PHY_TYPE_DP 1 0>; + assigned-clock-rates = <27000000>, <25000000>, <300000000>; }; &zynqmp_dpdma { status = "okay"; + assigned-clock-rates = <600000000>; }; &usb0 { @@ -115,6 +118,8 @@ clk-phase-sd-hs = <126>, <60>; clk-phase-uhs-sdr25 = <120>, <60>; clk-phase-uhs-ddr50 = <126>, <48>; + assigned-clock-rates = <187498123>; + bus-width = <4>; }; &gem3 { /* required by spec */ @@ -127,16 +132,18 @@ mdio: mdio { #address-cells = <1>; #size-cells = <0>; - reset-gpios = <&gpio 38 GPIO_ACTIVE_LOW>; - reset-delay-us = <2>; phy0: ethernet-phy@1 { #phy-cells = <1>; reg = <1>; + compatible = "ethernet-phy-id2000.a231"; ti,rx-internal-delay = ; ti,tx-internal-delay = ; ti,fifo-depth = ; ti,dp83867-rxctrl-strap-quirk; + reset-assert-us = <100>; + reset-deassert-us = <280>; + reset-gpios = <&gpio 38 GPIO_ACTIVE_LOW>; }; }; }; @@ -242,19 +249,22 @@ pinctrl_usb0_default: usb0-default { conf { groups = "usb0_0_grp"; - slew-rate = ; power-source = ; }; conf-rx { pins = "MIO52", "MIO53", "MIO55"; bias-high-impedance; + drive-strength = <12>; + slew-rate = ; }; conf-tx { pins = "MIO54", "MIO56", "MIO57", "MIO58", "MIO59", "MIO60", "MIO61", "MIO62", "MIO63"; bias-disable; + drive-strength = <4>; + slew-rate = ; }; mux { diff --git a/arch/arm64/boot/dts/xilinx/zynqmp-sm-k26-revA.dts b/arch/arm64/boot/dts/xilinx/zynqmp-sm-k26-revA.dts index 20e83ca47b5dba9e6ef9ddd761e396d8987a5a06..dfd1a18f5a10b23173d18936af435c0114f7c453 100644 --- a/arch/arm64/boot/dts/xilinx/zynqmp-sm-k26-revA.dts +++ b/arch/arm64/boot/dts/xilinx/zynqmp-sm-k26-revA.dts @@ -4,7 +4,7 @@ * * (C) Copyright 2020 - 2021, Xilinx, Inc. * - * Michal Simek + * Michal Simek */ /dts-v1/; @@ -14,6 +14,7 @@ #include #include #include +#include / { model = "ZynqMP SM-K26 Rev1/B/A"; @@ -55,6 +56,9 @@ key-fwuen { label = "fwuen"; gpios = <&gpio 12 GPIO_ACTIVE_LOW>; + linux,code = ; + wakeup-source; + autorepeat; }; }; @@ -72,109 +76,158 @@ default-state = "on"; }; }; + + ams { + compatible = "iio-hwmon"; + io-channels = <&xilinx_ams 0>, <&xilinx_ams 1>, <&xilinx_ams 2>, + <&xilinx_ams 3>, <&xilinx_ams 4>, <&xilinx_ams 5>, + <&xilinx_ams 6>, <&xilinx_ams 7>, <&xilinx_ams 8>, + <&xilinx_ams 9>, <&xilinx_ams 10>, <&xilinx_ams 11>, + <&xilinx_ams 12>, <&xilinx_ams 13>, <&xilinx_ams 14>, + <&xilinx_ams 15>, <&xilinx_ams 16>, <&xilinx_ams 17>, + <&xilinx_ams 18>, <&xilinx_ams 19>, <&xilinx_ams 20>, + <&xilinx_ams 21>, <&xilinx_ams 22>, <&xilinx_ams 23>, + <&xilinx_ams 24>, <&xilinx_ams 25>, <&xilinx_ams 26>, + <&xilinx_ams 27>, <&xilinx_ams 28>, <&xilinx_ams 29>; + }; +}; + +&modepin_gpio { + label = "modepin"; }; &uart1 { /* MIO36/MIO37 */ status = "okay"; }; +&pinctrl0 { + status = "okay"; + pinctrl_sdhci0_default: sdhci0-default { + conf { + groups = "sdio0_0_grp"; + slew-rate = ; + power-source = ; + bias-disable; + }; + + mux { + groups = "sdio0_0_grp"; + function = "sdio0"; + }; + }; +}; + &qspi { /* MIO 0-5 - U143 */ status = "okay"; - flash@0 { /* MT25QU512A */ + spi_flash: flash@0 { /* MT25QU512A */ compatible = "mt25qu512a", "jedec,spi-nor"; /* 64MB */ #address-cells = <1>; #size-cells = <1>; reg = <0>; - spi-tx-bus-width = <1>; + spi-tx-bus-width = <4>; spi-rx-bus-width = <4>; spi-max-frequency = <40000000>; /* 40MHz */ - partition@0 { - label = "Image Selector"; - reg = <0x0 0x80000>; /* 512KB */ - read-only; - lock; - }; - partition@80000 { - label = "Image Selector Golden"; - reg = <0x80000 0x80000>; /* 512KB */ - read-only; - lock; - }; - partition@100000 { - label = "Persistent Register"; - reg = <0x100000 0x20000>; /* 128KB */ - }; - partition@120000 { - label = "Persistent Register Backup"; - reg = <0x120000 0x20000>; /* 128KB */ - }; - partition@140000 { - label = "Open_1"; - reg = <0x140000 0xC0000>; /* 768KB */ - }; - partition@200000 { - label = "Image A (FSBL, PMU, ATF, U-Boot)"; - reg = <0x200000 0xD00000>; /* 13MB */ - }; - partition@f00000 { - label = "ImgSel Image A Catch"; - reg = <0xF00000 0x80000>; /* 512KB */ - read-only; - lock; - }; - partition@f80000 { - label = "Image B (FSBL, PMU, ATF, U-Boot)"; - reg = <0xF80000 0xD00000>; /* 13MB */ - }; - partition@1c80000 { - label = "ImgSel Image B Catch"; - reg = <0x1C80000 0x80000>; /* 512KB */ - read-only; - lock; - }; - partition@1d00000 { - label = "Open_2"; - reg = <0x1D00000 0x100000>; /* 1MB */ - }; - partition@1e00000 { - label = "Recovery Image"; - reg = <0x1E00000 0x200000>; /* 2MB */ - read-only; - lock; - }; - partition@2000000 { - label = "Recovery Image Backup"; - reg = <0x2000000 0x200000>; /* 2MB */ - read-only; - lock; - }; - partition@2200000 { - label = "U-Boot storage variables"; - reg = <0x2200000 0x20000>; /* 128KB */ - }; - partition@2220000 { - label = "U-Boot storage variables backup"; - reg = <0x2220000 0x20000>; /* 128KB */ - }; - partition@2240000 { - label = "SHA256"; - reg = <0x2240000 0x10000>; /* 256B but 64KB sector */ - read-only; - lock; - }; - partition@2250000 { - label = "User"; - reg = <0x2250000 0x1db0000>; /* 29.5 MB */ + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "Image Selector"; + reg = <0x0 0x80000>; /* 512KB */ + read-only; + lock; + }; + partition@80000 { + label = "Image Selector Golden"; + reg = <0x80000 0x80000>; /* 512KB */ + read-only; + lock; + }; + partition@100000 { + label = "Persistent Register"; + reg = <0x100000 0x20000>; /* 128KB */ + }; + partition@120000 { + label = "Persistent Register Backup"; + reg = <0x120000 0x20000>; /* 128KB */ + }; + partition@140000 { + label = "Open_1"; + reg = <0x140000 0xC0000>; /* 768KB */ + }; + partition@200000 { + label = "Image A (FSBL, PMU, ATF, U-Boot)"; + reg = <0x200000 0xD00000>; /* 13MB */ + }; + partition@f00000 { + label = "ImgSel Image A Catch"; + reg = <0xF00000 0x80000>; /* 512KB */ + read-only; + lock; + }; + partition@f80000 { + label = "Image B (FSBL, PMU, ATF, U-Boot)"; + reg = <0xF80000 0xD00000>; /* 13MB */ + }; + partition@1c80000 { + label = "ImgSel Image B Catch"; + reg = <0x1C80000 0x80000>; /* 512KB */ + read-only; + lock; + }; + partition@1d00000 { + label = "Open_2"; + reg = <0x1D00000 0x100000>; /* 1MB */ + }; + partition@1e00000 { + label = "Recovery Image"; + reg = <0x1E00000 0x200000>; /* 2MB */ + read-only; + lock; + }; + partition@2000000 { + label = "Recovery Image Backup"; + reg = <0x2000000 0x200000>; /* 2MB */ + read-only; + lock; + }; + partition@2200000 { + label = "U-Boot storage variables"; + reg = <0x2200000 0x20000>; /* 128KB */ + }; + partition@2220000 { + label = "U-Boot storage variables backup"; + reg = <0x2220000 0x20000>; /* 128KB */ + }; + partition@2240000 { + label = "SHA256"; + reg = <0x2240000 0x40000>; /* 256B but 256KB sector */ + read-only; + lock; + }; + partition@2280000 { + label = "Secure OS Storage"; + reg = <0x2280000 0x20000>; /* 128KB */ + }; + partition@22A0000 { + label = "User"; + reg = <0x22A0000 0x1d60000>; /* 29.375 MB */ + }; }; }; }; &sdhci0 { /* MIO13-23 - 16GB emmc MTFC16GAPALBH-IT - U133A */ status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_sdhci0_default>; non-removable; disable-wp; bus-width = <8>; xlnx,mio-bank = <0>; + assigned-clock-rates = <187498123>; }; &spi1 { /* MIO6, 9-11 */ @@ -190,17 +243,20 @@ &i2c1 { status = "okay"; + bootph-all; clock-frequency = <400000>; scl-gpios = <&gpio 24 GPIO_ACTIVE_HIGH>; sda-gpios = <&gpio 25 GPIO_ACTIVE_HIGH>; eeprom: eeprom@50 { /* u46 - also at address 0x58 */ + bootph-all; compatible = "st,24c64", "atmel,24c64"; /* st m24c64 */ reg = <0x50>; /* WP pin EE_WP_EN connected to slg7x644092@68 */ }; eeprom_cc: eeprom@51 { /* required by spec - also at address 0x59 */ + bootph-all; compatible = "st,24c64", "atmel,24c64"; /* st m24c64 */ reg = <0x51>; }; @@ -287,3 +343,114 @@ "", "", "", "", "", /* 165 - 169 */ "", "", "", ""; /* 170 - 173 */ }; + +&xilinx_ams { + status = "okay"; +}; + +&ams_ps { + status = "okay"; +}; + +&ams_pl { + status = "okay"; +}; + +&zynqmp_dpsub { + status = "okay"; +}; + +&rtc { + status = "okay"; +}; + +&lpd_dma_chan1 { + status = "okay"; +}; + +&lpd_dma_chan2 { + status = "okay"; +}; + +&lpd_dma_chan3 { + status = "okay"; +}; + +&lpd_dma_chan4 { + status = "okay"; +}; + +&lpd_dma_chan5 { + status = "okay"; +}; + +&lpd_dma_chan6 { + status = "okay"; +}; + +&lpd_dma_chan7 { + status = "okay"; +}; + +&lpd_dma_chan8 { + status = "okay"; +}; + +&fpd_dma_chan1 { + status = "okay"; +}; + +&fpd_dma_chan2 { + status = "okay"; +}; + +&fpd_dma_chan3 { + status = "okay"; +}; + +&fpd_dma_chan4 { + status = "okay"; +}; + +&fpd_dma_chan5 { + status = "okay"; +}; + +&fpd_dma_chan6 { + status = "okay"; +}; + +&fpd_dma_chan7 { + status = "okay"; +}; + +&fpd_dma_chan8 { + status = "okay"; +}; + +&gpu { + status = "okay"; +}; + +&lpd_watchdog { + status = "okay"; +}; + +&watchdog0 { + status = "okay"; +}; + +&cpu_opp_table { + opp00 { + opp-hz = /bits/ 64 <1333333333>; + }; + opp01 { + opp-hz = /bits/ 64 <666666666>; + }; + opp02 { + opp-hz = /bits/ 64 <444444444>; + }; + opp03 { + opp-hz = /bits/ 64 <333333333>; + }; +}; diff --git a/arch/arm64/boot/dts/xilinx/zynqmp-smk-k26-revA.dts b/arch/arm64/boot/dts/xilinx/zynqmp-smk-k26-revA.dts index c70966c1f344953b1667f05719bb256a7760ccc7..85b0d1677240657e73437d6465b1fe1fcd8def78 100644 --- a/arch/arm64/boot/dts/xilinx/zynqmp-smk-k26-revA.dts +++ b/arch/arm64/boot/dts/xilinx/zynqmp-smk-k26-revA.dts @@ -4,7 +4,7 @@ * * (C) Copyright 2020 - 2021, Xilinx, Inc. * - * Michal Simek + * Michal Simek */ #include "zynqmp-sm-k26-revA.dts" diff --git a/arch/arm64/boot/dts/xilinx/zynqmp-zc1232-revA.dts b/arch/arm64/boot/dts/xilinx/zynqmp-zc1232-revA.dts index f1598527e5eccbdca3d6ddbb46fdcc532a2deb4d..04079d1704f1f61dadf89c0c251c92c8735dd642 100644 --- a/arch/arm64/boot/dts/xilinx/zynqmp-zc1232-revA.dts +++ b/arch/arm64/boot/dts/xilinx/zynqmp-zc1232-revA.dts @@ -4,7 +4,7 @@ * * (C) Copyright 2017 - 2021, Xilinx, Inc. * - * Michal Simek + * Michal Simek */ /dts-v1/; @@ -44,7 +44,7 @@ #address-cells = <1>; #size-cells = <1>; reg = <0x0>; - spi-tx-bus-width = <1>; + spi-tx-bus-width = <4>; spi-rx-bus-width = <4>; spi-max-frequency = <108000000>; /* Based on DC1 spec */ }; diff --git a/arch/arm64/boot/dts/xilinx/zynqmp-zc1254-revA.dts b/arch/arm64/boot/dts/xilinx/zynqmp-zc1254-revA.dts index 04efa1683eaa918a249dd056a0302d40487ab5aa..3dec57cf18be061376f0cecfdacdd1cedd1d2ae4 100644 --- a/arch/arm64/boot/dts/xilinx/zynqmp-zc1254-revA.dts +++ b/arch/arm64/boot/dts/xilinx/zynqmp-zc1254-revA.dts @@ -4,8 +4,8 @@ * * (C) Copyright 2015 - 2021, Xilinx, Inc. * - * Michal Simek - * Siva Durga Prasad Paladugu + * Michal Simek + * Siva Durga Prasad Paladugu */ /dts-v1/; @@ -45,7 +45,7 @@ #address-cells = <1>; #size-cells = <1>; reg = <0x0>; - spi-tx-bus-width = <1>; + spi-tx-bus-width = <4>; spi-rx-bus-width = <4>; /* FIXME also DUAL configuration possible */ spi-max-frequency = <108000000>; /* Based on DC1 spec */ }; diff --git a/arch/arm64/boot/dts/xilinx/zynqmp-zc1751-xm015-dc1.dts b/arch/arm64/boot/dts/xilinx/zynqmp-zc1751-xm015-dc1.dts index b05be2552826574b787782689b63c3bf5723f275..d9d1de5f313c1f8d5175622c7331686d758da9cb 100644 --- a/arch/arm64/boot/dts/xilinx/zynqmp-zc1751-xm015-dc1.dts +++ b/arch/arm64/boot/dts/xilinx/zynqmp-zc1751-xm015-dc1.dts @@ -2,9 +2,10 @@ /* * dts file for Xilinx ZynqMP zc1751-xm015-dc1 * - * (C) Copyright 2015 - 2021, Xilinx, Inc. + * (C) Copyright 2015 - 2022, Xilinx, Inc. + * (C) Copyright 2022 - 2023, Advanced Micro Devices, Inc. * - * Michal Simek + * Michal Simek */ /dts-v1/; @@ -108,6 +109,9 @@ pinctrl-0 = <&pinctrl_gpio_default>; }; +&gpu { + status = "okay"; +}; &i2c1 { status = "okay"; @@ -184,19 +188,22 @@ conf { groups = "usb0_0_grp"; - slew-rate = ; power-source = ; }; conf-rx { pins = "MIO52", "MIO53", "MIO55"; bias-high-impedance; + drive-strength = <12>; + slew-rate = ; }; conf-tx { pins = "MIO54", "MIO56", "MIO57", "MIO58", "MIO59", "MIO60", "MIO61", "MIO62", "MIO63"; bias-disable; + drive-strength = <4>; + slew-rate = ; }; }; @@ -348,7 +355,7 @@ #address-cells = <1>; #size-cells = <1>; reg = <0x0>; - spi-tx-bus-width = <1>; + spi-tx-bus-width = <4>; spi-rx-bus-width = <4>; spi-max-frequency = <108000000>; /* Based on DC1 spec */ }; diff --git a/arch/arm64/boot/dts/xilinx/zynqmp-zc1751-xm016-dc2.dts b/arch/arm64/boot/dts/xilinx/zynqmp-zc1751-xm016-dc2.dts index 938b76bd052742c7fa9977e59918fe52ba33dead..6503f4985f8d67dbafdcc7e24b147372e2f28990 100644 --- a/arch/arm64/boot/dts/xilinx/zynqmp-zc1751-xm016-dc2.dts +++ b/arch/arm64/boot/dts/xilinx/zynqmp-zc1751-xm016-dc2.dts @@ -2,9 +2,10 @@ /* * dts file for Xilinx ZynqMP zc1751-xm016-dc2 * - * (C) Copyright 2015 - 2021, Xilinx, Inc. + * (C) Copyright 2015 - 2022, Xilinx, Inc. + * (C) Copyright 2022 - 2023, Advanced Micro Devices, Inc. * - * Michal Simek + * Michal Simek */ /dts-v1/; @@ -281,19 +282,22 @@ conf { groups = "usb1_0_grp"; - slew-rate = ; power-source = ; }; conf-rx { pins = "MIO64", "MIO65", "MIO67"; bias-high-impedance; + drive-strength = <12>; + slew-rate = ; }; conf-tx { pins = "MIO66", "MIO68", "MIO69", "MIO70", "MIO71", "MIO72", "MIO73", "MIO74", "MIO75"; bias-disable; + drive-strength = <4>; + slew-rate = ; }; }; @@ -485,8 +489,6 @@ &dwc3_1 { status = "okay"; dr_mode = "host"; - snps,usb3_lpm_capable; - maximum-speed = "super-speed"; }; &uart0 { diff --git a/arch/arm64/boot/dts/xilinx/zynqmp-zc1751-xm017-dc3.dts b/arch/arm64/boot/dts/xilinx/zynqmp-zc1751-xm017-dc3.dts index 381cc682cef9a35da6adfed6f8dacf00d9e63250..38b0a312171b70b7cb0147f754d1be8d8f7edb5f 100644 --- a/arch/arm64/boot/dts/xilinx/zynqmp-zc1751-xm017-dc3.dts +++ b/arch/arm64/boot/dts/xilinx/zynqmp-zc1751-xm017-dc3.dts @@ -4,7 +4,7 @@ * * (C) Copyright 2016 - 2021, Xilinx, Inc. * - * Michal Simek + * Michal Simek */ /dts-v1/; diff --git a/arch/arm64/boot/dts/xilinx/zynqmp-zc1751-xm018-dc4.dts b/arch/arm64/boot/dts/xilinx/zynqmp-zc1751-xm018-dc4.dts index 05a2b79738afb41dd8b3ff3d6935d0877d288093..6636e76545a5d9f977dbcc5755da6b427e1aa612 100644 --- a/arch/arm64/boot/dts/xilinx/zynqmp-zc1751-xm018-dc4.dts +++ b/arch/arm64/boot/dts/xilinx/zynqmp-zc1751-xm018-dc4.dts @@ -4,7 +4,7 @@ * * (C) Copyright 2015 - 2021, Xilinx, Inc. * - * Michal Simek + * Michal Simek */ /dts-v1/; @@ -152,6 +152,10 @@ status = "okay"; }; +&gpu { + status = "okay"; +}; + &i2c0 { clock-frequency = <400000>; status = "okay"; @@ -169,7 +173,7 @@ #address-cells = <1>; #size-cells = <1>; reg = <0x0>; - spi-tx-bus-width = <1>; + spi-tx-bus-width = <4>; spi-rx-bus-width = <4>; /* also DUAL configuration possible */ spi-max-frequency = <108000000>; /* Based on DC1 spec */ }; diff --git a/arch/arm64/boot/dts/xilinx/zynqmp-zc1751-xm019-dc5.dts b/arch/arm64/boot/dts/xilinx/zynqmp-zc1751-xm019-dc5.dts index ae2d03d98322cf9bde7cc1afc6e6d01af9800eea..b1e933b8a2cdb86c7072382ad731ca736673e0e5 100644 --- a/arch/arm64/boot/dts/xilinx/zynqmp-zc1751-xm019-dc5.dts +++ b/arch/arm64/boot/dts/xilinx/zynqmp-zc1751-xm019-dc5.dts @@ -4,8 +4,8 @@ * * (C) Copyright 2015 - 2021, Xilinx, Inc. * - * Siva Durga Prasad - * Michal Simek + * Siva Durga Prasad Paladugu + * Michal Simek */ /dts-v1/; diff --git a/arch/arm64/boot/dts/xilinx/zynqmp-zcu100-revC.dts b/arch/arm64/boot/dts/xilinx/zynqmp-zcu100-revC.dts index 6948fd40554b3f344566db63f47cde03a0561d78..44d1f351bb757d8ba648b000cb93dcd95031c626 100644 --- a/arch/arm64/boot/dts/xilinx/zynqmp-zcu100-revC.dts +++ b/arch/arm64/boot/dts/xilinx/zynqmp-zcu100-revC.dts @@ -2,9 +2,10 @@ /* * dts file for Xilinx ZynqMP ZCU100 revC * - * (C) Copyright 2016 - 2021, Xilinx, Inc. + * (C) Copyright 2016 - 2022, Xilinx, Inc. + * (C) Copyright 2022 - 2023, Advanced Micro Devices, Inc. * - * Michal Simek + * Michal Simek * Nathalie Chan King Choy */ @@ -58,6 +59,15 @@ }; }; + iio-hwmon { + compatible = "iio-hwmon"; + io-channels = <&xilinx_ams 0>, <&xilinx_ams 1>, <&xilinx_ams 2>, + <&xilinx_ams 3>, <&xilinx_ams 4>, <&xilinx_ams 5>, + <&xilinx_ams 6>, <&xilinx_ams 7>, <&xilinx_ams 8>, + <&xilinx_ams 9>, <&xilinx_ams 10>, + <&xilinx_ams 11>, <&xilinx_ams 12>; + }; + leds { compatible = "gpio-leds"; led-ds2 { @@ -161,6 +171,10 @@ "", "", "", ""; }; +&gpu { + status = "okay"; +}; + &i2c1 { status = "okay"; pinctrl-names = "default", "gpio"; @@ -419,19 +433,22 @@ conf { groups = "usb0_0_grp"; - slew-rate = ; power-source = ; }; conf-rx { pins = "MIO52", "MIO53", "MIO55"; bias-high-impedance; + drive-strength = <12>; + slew-rate = ; }; conf-tx { pins = "MIO54", "MIO56", "MIO57", "MIO58", "MIO59", "MIO60", "MIO61", "MIO62", "MIO63"; bias-disable; + drive-strength = <4>; + slew-rate = ; }; }; @@ -443,19 +460,22 @@ conf { groups = "usb1_0_grp"; - slew-rate = ; power-source = ; }; conf-rx { pins = "MIO64", "MIO65", "MIO67"; bias-high-impedance; + drive-strength = <12>; + slew-rate = ; }; conf-tx { pins = "MIO66", "MIO68", "MIO69", "MIO70", "MIO71", "MIO72", "MIO73", "MIO74", "MIO75"; bias-disable; + drive-strength = <4>; + slew-rate = ; }; }; }; @@ -541,6 +561,7 @@ pinctrl-0 = <&pinctrl_usb0_default>; phy-names = "usb3-phy"; phys = <&psgtr 2 PHY_TYPE_USB3 0 0>; + /delete-property/ reset-gpios; }; &dwc3_0 { @@ -556,6 +577,7 @@ pinctrl-0 = <&pinctrl_usb1_default>; phy-names = "usb3-phy"; phys = <&psgtr 3 PHY_TYPE_USB3 1 0>; + reset-gpios = <&modepin_gpio 1 GPIO_ACTIVE_LOW>; }; &dwc3_1 { @@ -568,6 +590,14 @@ status = "okay"; }; +&xilinx_ams { + status = "okay"; +}; + +&ams_ps { + status = "okay"; +}; + &zynqmp_dpdma { status = "okay"; }; diff --git a/arch/arm64/boot/dts/xilinx/zynqmp-zcu102-rev1.0.dts b/arch/arm64/boot/dts/xilinx/zynqmp-zcu102-rev1.0.dts index 6647e97edba36732462e1050629aa05539dff554..c8f71a1aec895679ec0e90226402e690f410b65b 100644 --- a/arch/arm64/boot/dts/xilinx/zynqmp-zcu102-rev1.0.dts +++ b/arch/arm64/boot/dts/xilinx/zynqmp-zcu102-rev1.0.dts @@ -4,7 +4,7 @@ * * (C) Copyright 2016 - 2018, Xilinx, Inc. * - * Michal Simek + * Michal Simek */ #include "zynqmp-zcu102-revB.dts" diff --git a/arch/arm64/boot/dts/xilinx/zynqmp-zcu102-rev1.1.dts b/arch/arm64/boot/dts/xilinx/zynqmp-zcu102-rev1.1.dts index b6798394fcf4b1831e34f7227dde42504d19ec5e..705369766a55010794405d612740f43a0d7f254d 100644 --- a/arch/arm64/boot/dts/xilinx/zynqmp-zcu102-rev1.1.dts +++ b/arch/arm64/boot/dts/xilinx/zynqmp-zcu102-rev1.1.dts @@ -4,7 +4,7 @@ * * (C) Copyright 2016 - 2020, Xilinx, Inc. * - * Michal Simek + * Michal Simek */ #include "zynqmp-zcu102-rev1.0.dts" diff --git a/arch/arm64/boot/dts/xilinx/zynqmp-zcu102-revA.dts b/arch/arm64/boot/dts/xilinx/zynqmp-zcu102-revA.dts index 5fd6b70a154a9af74da89c584c1b40686c0b9aa2..8767f147cbe33ffca3f9928ca2d1b1dfbaf9881b 100644 --- a/arch/arm64/boot/dts/xilinx/zynqmp-zcu102-revA.dts +++ b/arch/arm64/boot/dts/xilinx/zynqmp-zcu102-revA.dts @@ -2,9 +2,10 @@ /* * dts file for Xilinx ZynqMP ZCU102 RevA * - * (C) Copyright 2015 - 2021, Xilinx, Inc. + * (C) Copyright 2015 - 2022, Xilinx, Inc. + * (C) Copyright 2022 - 2023, Advanced Micro Devices, Inc. * - * Michal Simek + * Michal Simek */ /dts-v1/; @@ -200,13 +201,19 @@ phy-mode = "rgmii-id"; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_gem3_default>; - phy0: ethernet-phy@21 { - reg = <21>; - ti,rx-internal-delay = <0x8>; - ti,tx-internal-delay = <0xa>; - ti,fifo-depth = <0x1>; - ti,dp83867-rxctrl-strap-quirk; - /* reset-gpios = <&tca6416_u97 6 GPIO_ACTIVE_LOW>; */ + mdio: mdio { + #address-cells = <1>; + #size-cells = <0>; + phy0: ethernet-phy@21 { + #phy-cells = <1>; + compatible = "ethernet-phy-id2000.a231"; + reg = <21>; + ti,rx-internal-delay = <0x8>; + ti,tx-internal-delay = <0xa>; + ti,fifo-depth = <0x1>; + ti,dp83867-rxctrl-strap-quirk; + reset-gpios = <&tca6416_u97 6 GPIO_ACTIVE_LOW>; + }; }; }; @@ -216,6 +223,10 @@ pinctrl-0 = <&pinctrl_gpio_default>; }; +&gpu { + status = "okay"; +}; + &i2c0 { status = "okay"; clock-frequency = <400000>; @@ -772,19 +783,22 @@ conf { groups = "usb0_0_grp"; - slew-rate = ; power-source = ; }; conf-rx { pins = "MIO52", "MIO53", "MIO55"; bias-high-impedance; + drive-strength = <12>; + slew-rate = ; }; conf-tx { pins = "MIO54", "MIO56", "MIO57", "MIO58", "MIO59", "MIO60", "MIO61", "MIO62", "MIO63"; bias-disable; + drive-strength = <4>; + slew-rate = ; }; }; @@ -943,7 +957,7 @@ #address-cells = <1>; #size-cells = <1>; reg = <0x0>; - spi-tx-bus-width = <1>; + spi-tx-bus-width = <4>; spi-rx-bus-width = <4>; /* FIXME also DUAL configuration possible */ spi-max-frequency = <108000000>; /* Based on DC1 spec */ }; @@ -1013,6 +1027,18 @@ status = "okay"; }; +&xilinx_ams { + status = "okay"; +}; + +&ams_ps { + status = "okay"; +}; + +&ams_pl { + status = "okay"; +}; + &zynqmp_dpdma { status = "okay"; }; diff --git a/arch/arm64/boot/dts/xilinx/zynqmp-zcu102-revB.dts b/arch/arm64/boot/dts/xilinx/zynqmp-zcu102-revB.dts index f7d718ff116b6536881405e62bd9a36a045f3a06..3c28130909bc60268e26315367037db63161e3bb 100644 --- a/arch/arm64/boot/dts/xilinx/zynqmp-zcu102-revB.dts +++ b/arch/arm64/boot/dts/xilinx/zynqmp-zcu102-revB.dts @@ -2,9 +2,10 @@ /* * dts file for Xilinx ZynqMP ZCU102 RevB * - * (C) Copyright 2016 - 2021, Xilinx, Inc. + * (C) Copyright 2016 - 2022, Xilinx, Inc. + * (C) Copyright 2022 - 2023, Advanced Micro Devices, Inc. * - * Michal Simek + * Michal Simek */ #include "zynqmp-zcu102-revA.dts" @@ -16,16 +17,20 @@ &gem3 { phy-handle = <&phyc>; - phyc: ethernet-phy@c { - reg = <0xc>; - ti,rx-internal-delay = <0x8>; - ti,tx-internal-delay = <0xa>; - ti,fifo-depth = <0x1>; - ti,dp83867-rxctrl-strap-quirk; - /* reset-gpios = <&tca6416_u97 6 GPIO_ACTIVE_LOW>; */ + mdio: mdio { + phyc: ethernet-phy@c { + #phy-cells = <0x1>; + compatible = "ethernet-phy-id2000.a231"; + reg = <0xc>; + ti,rx-internal-delay = <0x8>; + ti,tx-internal-delay = <0xa>; + ti,fifo-depth = <0x1>; + ti,dp83867-rxctrl-strap-quirk; + reset-gpios = <&tca6416_u97 6 GPIO_ACTIVE_LOW>; + }; + /* Cleanup from RevA */ + /delete-node/ ethernet-phy@21; }; - /* Cleanup from RevA */ - /delete-node/ ethernet-phy@21; }; /* Fix collision with u61 */ diff --git a/arch/arm64/boot/dts/xilinx/zynqmp-zcu104-revA.dts b/arch/arm64/boot/dts/xilinx/zynqmp-zcu104-revA.dts index bd8f20f3223d7e5d127e0116739f0b041e799eb3..e185709c0d8423fc3f48c0535f877397e7b419c0 100644 --- a/arch/arm64/boot/dts/xilinx/zynqmp-zcu104-revA.dts +++ b/arch/arm64/boot/dts/xilinx/zynqmp-zcu104-revA.dts @@ -2,9 +2,10 @@ /* * dts file for Xilinx ZynqMP ZCU104 * - * (C) Copyright 2017 - 2021, Xilinx, Inc. + * (C) Copyright 2017 - 2022, Xilinx, Inc. + * (C) Copyright 2022 - 2023, Advanced Micro Devices, Inc. * - * Michal Simek + * Michal Simek */ /dts-v1/; @@ -109,12 +110,19 @@ phy-mode = "rgmii-id"; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_gem3_default>; - phy0: ethernet-phy@c { - reg = <0xc>; - ti,rx-internal-delay = <0x8>; - ti,tx-internal-delay = <0xa>; - ti,fifo-depth = <0x1>; - ti,dp83867-rxctrl-strap-quirk; + mdio: mdio { + #address-cells = <1>; + #size-cells = <0>; + phy0: ethernet-phy@c { + #phy-cells = <1>; + compatible = "ethernet-phy-id2000.a231"; + reg = <0xc>; + ti,rx-internal-delay = <0x8>; + ti,tx-internal-delay = <0xa>; + ti,fifo-depth = <0x1>; + ti,dp83867-rxctrl-strap-quirk; + reset-gpios = <&tca6416_u97 6 GPIO_ACTIVE_LOW>; + }; }; }; @@ -122,6 +130,10 @@ status = "okay"; }; +&gpu { + status = "okay"; +}; + &i2c1 { status = "okay"; clock-frequency = <400000>; @@ -398,20 +410,22 @@ conf { groups = "usb0_0_grp"; - slew-rate = ; power-source = ; - drive-strength = <12>; }; conf-rx { pins = "MIO52", "MIO53", "MIO55"; bias-high-impedance; + drive-strength = <12>; + slew-rate = ; }; conf-tx { pins = "MIO54", "MIO56", "MIO57", "MIO58", "MIO59", "MIO60", "MIO61", "MIO62", "MIO63"; bias-disable; + drive-strength = <4>; + slew-rate = ; }; }; }; @@ -430,7 +444,7 @@ #address-cells = <1>; #size-cells = <1>; reg = <0x0>; - spi-tx-bus-width = <1>; + spi-tx-bus-width = <4>; spi-rx-bus-width = <4>; spi-max-frequency = <108000000>; /* Based on DC1 spec */ }; @@ -497,6 +511,18 @@ status = "okay"; }; +&xilinx_ams { + status = "okay"; +}; + +&ams_ps { + status = "okay"; +}; + +&ams_pl { + status = "okay"; +}; + &zynqmp_dpdma { status = "okay"; }; diff --git a/arch/arm64/boot/dts/xilinx/zynqmp-zcu104-revC.dts b/arch/arm64/boot/dts/xilinx/zynqmp-zcu104-revC.dts index 96feaad30166345b2269595adb3665360c121318..7fceebd1815cf97f32268ddbb408ac5425ce04bb 100644 --- a/arch/arm64/boot/dts/xilinx/zynqmp-zcu104-revC.dts +++ b/arch/arm64/boot/dts/xilinx/zynqmp-zcu104-revC.dts @@ -2,9 +2,10 @@ /* * dts file for Xilinx ZynqMP ZCU104 * - * (C) Copyright 2017 - 2021, Xilinx, Inc. + * (C) Copyright 2017 - 2022, Xilinx, Inc. + * (C) Copyright 2022 - 2023, Advanced Micro Devices, Inc. * - * Michal Simek + * Michal Simek */ /dts-v1/; @@ -114,12 +115,19 @@ phy-mode = "rgmii-id"; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_gem3_default>; - phy0: ethernet-phy@c { - reg = <0xc>; - ti,rx-internal-delay = <0x8>; - ti,tx-internal-delay = <0xa>; - ti,fifo-depth = <0x1>; - ti,dp83867-rxctrl-strap-quirk; + mdio: mdio { + #address-cells = <1>; + #size-cells = <0>; + phy0: ethernet-phy@c { + #phy-cells = <1>; + compatible = "ethernet-phy-id2000.a231"; + reg = <0xc>; + ti,rx-internal-delay = <0x8>; + ti,tx-internal-delay = <0xa>; + ti,fifo-depth = <0x1>; + ti,dp83867-rxctrl-strap-quirk; + reset-gpios = <&tca6416_u97 6 GPIO_ACTIVE_LOW>; + }; }; }; @@ -127,6 +135,10 @@ status = "okay"; }; +&gpu { + status = "okay"; +}; + &i2c1 { status = "okay"; clock-frequency = <400000>; @@ -410,20 +422,22 @@ conf { groups = "usb0_0_grp"; - slew-rate = ; power-source = ; - drive-strength = <12>; }; conf-rx { pins = "MIO52", "MIO53", "MIO55"; bias-high-impedance; + drive-strength = <12>; + slew-rate = ; }; conf-tx { pins = "MIO54", "MIO56", "MIO57", "MIO58", "MIO59", "MIO60", "MIO61", "MIO62", "MIO63"; bias-disable; + drive-strength = <4>; + slew-rate = ; }; }; }; @@ -442,7 +456,7 @@ #address-cells = <1>; #size-cells = <1>; reg = <0x0>; - spi-tx-bus-width = <1>; + spi-tx-bus-width = <4>; spi-rx-bus-width = <4>; spi-max-frequency = <108000000>; /* Based on DC1 spec */ }; @@ -509,6 +523,18 @@ status = "okay"; }; +&xilinx_ams { + status = "okay"; +}; + +&ams_ps { + status = "okay"; +}; + +&ams_pl { + status = "okay"; +}; + &zynqmp_dpdma { status = "okay"; }; diff --git a/arch/arm64/boot/dts/xilinx/zynqmp-zcu106-revA.dts b/arch/arm64/boot/dts/xilinx/zynqmp-zcu106-revA.dts index 24a252317150f0e9fbe617977229b7407f46e7e4..27b2416cb6d8b434c842f447861197bab38eeeb5 100644 --- a/arch/arm64/boot/dts/xilinx/zynqmp-zcu106-revA.dts +++ b/arch/arm64/boot/dts/xilinx/zynqmp-zcu106-revA.dts @@ -2,9 +2,10 @@ /* * dts file for Xilinx ZynqMP ZCU106 * - * (C) Copyright 2016 - 2021, Xilinx, Inc. + * (C) Copyright 2016 - 2022, Xilinx, Inc. + * (C) Copyright 2022 - 2023, Advanced Micro Devices, Inc. * - * Michal Simek + * Michal Simek */ /dts-v1/; @@ -212,12 +213,19 @@ phy-mode = "rgmii-id"; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_gem3_default>; - phy0: ethernet-phy@c { - reg = <0xc>; - ti,rx-internal-delay = <0x8>; - ti,tx-internal-delay = <0xa>; - ti,fifo-depth = <0x1>; - ti,dp83867-rxctrl-strap-quirk; + mdio: mdio { + #address-cells = <1>; + #size-cells = <0>; + phy0: ethernet-phy@c { + #phy-cells = <1>; + reg = <0xc>; + compatible = "ethernet-phy-id2000.a231"; + ti,rx-internal-delay = <0x8>; + ti,tx-internal-delay = <0xa>; + ti,fifo-depth = <0x1>; + ti,dp83867-rxctrl-strap-quirk; + reset-gpios = <&tca6416_u97 6 GPIO_ACTIVE_LOW>; + }; }; }; @@ -227,6 +235,10 @@ pinctrl-0 = <&pinctrl_gpio_default>; }; +&gpu { + status = "okay"; +}; + &i2c0 { status = "okay"; clock-frequency = <400000>; @@ -782,19 +794,22 @@ conf { groups = "usb0_0_grp"; - slew-rate = ; power-source = ; }; conf-rx { pins = "MIO52", "MIO53", "MIO55"; bias-high-impedance; + drive-strength = <12>; + slew-rate = ; }; conf-tx { pins = "MIO54", "MIO56", "MIO57", "MIO58", "MIO59", "MIO60", "MIO61", "MIO62", "MIO63"; bias-disable; + drive-strength = <4>; + slew-rate = ; }; }; @@ -949,7 +964,7 @@ #address-cells = <1>; #size-cells = <1>; reg = <0x0>; - spi-tx-bus-width = <1>; + spi-tx-bus-width = <4>; spi-rx-bus-width = <4>; /* FIXME also DUAL configuration possible */ spi-max-frequency = <108000000>; /* Based on DC1 spec */ }; diff --git a/arch/arm64/boot/dts/xilinx/zynqmp-zcu111-revA.dts b/arch/arm64/boot/dts/xilinx/zynqmp-zcu111-revA.dts index d685d8fbc36a1a853d18b9ccb714fc0581d14f1c..6224365826d8cee83c781e4f9388b52a04450c4f 100644 --- a/arch/arm64/boot/dts/xilinx/zynqmp-zcu111-revA.dts +++ b/arch/arm64/boot/dts/xilinx/zynqmp-zcu111-revA.dts @@ -2,9 +2,10 @@ /* * dts file for Xilinx ZynqMP ZCU111 * - * (C) Copyright 2017 - 2021, Xilinx, Inc. + * (C) Copyright 2017 - 2022, Xilinx, Inc. + * (C) Copyright 2022 - 2023, Advanced Micro Devices, Inc. * - * Michal Simek + * Michal Simek */ /dts-v1/; @@ -172,12 +173,19 @@ phy-mode = "rgmii-id"; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_gem3_default>; - phy0: ethernet-phy@c { - reg = <0xc>; - ti,rx-internal-delay = <0x8>; - ti,tx-internal-delay = <0xa>; - ti,fifo-depth = <0x1>; - ti,dp83867-rxctrl-strap-quirk; + mdio: mdio { + #address-cells = <1>; + #size-cells = <0>; + phy0: ethernet-phy@c { + #phy-cells = <1>; + compatible = "ethernet-phy-id2000.a231"; + reg = <0xc>; + ti,rx-internal-delay = <0x8>; + ti,tx-internal-delay = <0xa>; + ti,fifo-depth = <0x1>; + ti,dp83867-rxctrl-strap-quirk; + reset-gpios = <&tca6416_u22 6 GPIO_ACTIVE_LOW>; + }; }; }; @@ -187,6 +195,10 @@ pinctrl-0 = <&pinctrl_gpio_default>; }; +&gpu { + status = "okay"; +}; + &i2c0 { status = "okay"; clock-frequency = <400000>; @@ -648,19 +660,22 @@ conf { groups = "usb0_0_grp"; - slew-rate = ; power-source = ; }; conf-rx { pins = "MIO52", "MIO53", "MIO55"; bias-high-impedance; + drive-strength = <12>; + slew-rate = ; }; conf-tx { pins = "MIO54", "MIO56", "MIO57", "MIO58", "MIO59", "MIO60", "MIO61", "MIO62", "MIO63"; bias-disable; + drive-strength = <4>; + slew-rate = ; }; }; @@ -779,7 +794,7 @@ #address-cells = <1>; #size-cells = <1>; reg = <0x0>; - spi-tx-bus-width = <1>; + spi-tx-bus-width = <4>; spi-rx-bus-width = <4>; /* FIXME also DUAL configuration possible */ spi-max-frequency = <108000000>; /* Based on DC1 spec */ }; diff --git a/arch/arm64/boot/dts/xilinx/zynqmp-zc1275-revA.dts b/arch/arm64/boot/dts/xilinx/zynqmp-zcu1275-revA.dts similarity index 73% rename from arch/arm64/boot/dts/xilinx/zynqmp-zc1275-revA.dts rename to arch/arm64/boot/dts/xilinx/zynqmp-zcu1275-revA.dts index e971ba8c14187db67a1b2dc270b5b77d94494ee0..c406017b0348f240393cd6ffaf14864e53babd1b 100644 --- a/arch/arm64/boot/dts/xilinx/zynqmp-zc1275-revA.dts +++ b/arch/arm64/boot/dts/xilinx/zynqmp-zcu1275-revA.dts @@ -4,8 +4,8 @@ * * (C) Copyright 2017 - 2021, Xilinx, Inc. * - * Michal Simek - * Siva Durga Prasad Paladugu + * Michal Simek + * Siva Durga Prasad Paladugu */ /dts-v1/; @@ -14,8 +14,8 @@ #include "zynqmp-clk-ccf.dtsi" / { - model = "ZynqMP ZC1275 RevA"; - compatible = "xlnx,zynqmp-zc1275-revA", "xlnx,zynqmp-zc1275", "xlnx,zynqmp"; + model = "ZynqMP ZCU1275 RevA"; + compatible = "xlnx,zynqmp-zcu1275-revA", "xlnx,zynqmp-zcu1275", "xlnx,zynqmp"; aliases { serial0 = &uart0; @@ -47,7 +47,7 @@ flash@0 { compatible = "m25p80", "jedec,spi-nor"; reg = <0x0>; - spi-tx-bus-width = <1>; + spi-tx-bus-width = <4>; spi-rx-bus-width = <4>; spi-max-frequency = <108000000>; }; diff --git a/arch/arm64/boot/dts/xilinx/zynqmp.dtsi b/arch/arm64/boot/dts/xilinx/zynqmp.dtsi index 153db59dc4b3e4051dc17f4088581caf77d35c76..02cfcc7169368a9000735e947e28f5542316822d 100644 --- a/arch/arm64/boot/dts/xilinx/zynqmp.dtsi +++ b/arch/arm64/boot/dts/xilinx/zynqmp.dtsi @@ -4,7 +4,7 @@ * * (C) Copyright 2014 - 2021, Xilinx, Inc. * - * Michal Simek + * Michal Simek * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -118,6 +118,7 @@ }; zynqmp_ipi: zynqmp_ipi { + bootph-all; compatible = "xlnx,zynqmp-ipi-mailbox"; interrupt-parent = <&gic>; interrupts = <0 35 4>; @@ -126,7 +127,8 @@ #size-cells = <2>; ranges; - ipi_mailbox_pmu1: mailbox@ff990400 { + ipi_mailbox_pmu1: mailbox@ff9905c0 { + bootph-all; reg = <0x0 0xff9905c0 0x0 0x20>, <0x0 0xff9905e0 0x0 0x20>, <0x0 0xff990e80 0x0 0x20>, @@ -143,6 +145,7 @@ dcc: dcc { compatible = "arm,dcc"; status = "disabled"; + bootph-all; }; pmu { @@ -152,6 +155,10 @@ <0 144 4>, <0 145 4>, <0 146 4>; + interrupt-affinity = <&cpu0>, + <&cpu1>, + <&cpu2>, + <&cpu3>; }; psci { @@ -164,8 +171,10 @@ compatible = "xlnx,zynqmp-firmware"; #power-domain-cells = <1>; method = "smc"; + bootph-all; zynqmp_power: zynqmp-power { + bootph-all; compatible = "xlnx,zynqmp-power"; interrupt-parent = <&gic>; interrupts = <0 35 4>; @@ -245,6 +254,7 @@ amba: axi { compatible = "simple-bus"; + bootph-all; #address-cells = <2>; #size-cells = <2>; ranges; @@ -400,7 +410,6 @@ gic: interrupt-controller@f9010000 { compatible = "arm,gic-400"; - #address-cells = <0>; #interrupt-cells = <3>; reg = <0x0 0xf9010000 0x0 0x10000>, <0x0 0xf9020000 0x0 0x20000>, @@ -411,6 +420,18 @@ interrupts = <1 9 0xf04>; }; + gpu: gpu@fd4b0000 { + status = "disabled"; + compatible = "xlnx,zynqmp-mali", "arm,mali-400"; + reg = <0x0 0xfd4b0000 0x0 0x10000>; + interrupt-parent = <&gic>; + interrupts = <0 132 4>, <0 132 4>, <0 132 4>, + <0 132 4>, <0 132 4>, <0 132 4>; + interrupt-names = "gp", "gpmmu", "pp0", "ppmmu0", "pp1", "ppmmu1"; + clock-names = "bus", "core"; + power-domains = <&zynqmp_firmware PD_GPU>; + }; + /* LPDDMA default allows only secured access. inorder to enable * These dma channels, Users should ensure that these dma * Channels are allowed for non secure access. @@ -602,7 +623,6 @@ gpio: gpio@ff0a0000 { compatible = "xlnx,zynqmp-gpio-1.0"; status = "disabled"; - #address-cells = <0>; #gpio-cells = <0x2>; gpio-controller; interrupt-parent = <&gic>; @@ -674,6 +694,7 @@ }; qspi: spi@ff0f0000 { + bootph-all; compatible = "xlnx,zynqmp-qspi-1.0"; status = "disabled"; clock-names = "ref_clk", "pclk"; @@ -720,6 +741,7 @@ }; sdhci0: mmc@ff160000 { + bootph-all; compatible = "xlnx,zynqmp-8.9a", "arasan,sdhci-8.9a"; status = "disabled"; interrupt-parent = <&gic>; @@ -730,9 +752,11 @@ #clock-cells = <1>; clock-output-names = "clk_out_sd0", "clk_in_sd0"; power-domains = <&zynqmp_firmware PD_SD_0>; + resets = <&zynqmp_reset ZYNQMP_RESET_SDIO0>; }; sdhci1: mmc@ff170000 { + bootph-all; compatible = "xlnx,zynqmp-8.9a", "arasan,sdhci-8.9a"; status = "disabled"; interrupt-parent = <&gic>; @@ -743,6 +767,7 @@ #clock-cells = <1>; clock-output-names = "clk_out_sd1", "clk_in_sd1"; power-domains = <&zynqmp_firmware PD_SD_1>; + resets = <&zynqmp_reset ZYNQMP_RESET_SDIO1>; }; smmu: iommu@fd800000 { @@ -824,6 +849,7 @@ }; uart0: serial@ff000000 { + bootph-all; compatible = "xlnx,zynqmp-uart", "cdns,uart-r1p12"; status = "disabled"; interrupt-parent = <&gic>; @@ -834,6 +860,7 @@ }; uart1: serial@ff010000 { + bootph-all; compatible = "xlnx,zynqmp-uart", "cdns,uart-r1p12"; status = "disabled"; interrupt-parent = <&gic>; @@ -928,13 +955,13 @@ #io-channel-cells = <1>; ranges = <0 0 0xffa50800 0x800>; - ams_ps: ams_ps@0 { + ams_ps: ams-ps@0 { compatible = "xlnx,zynqmp-ams-ps"; status = "disabled"; reg = <0x0 0x400>; }; - ams_pl: ams_pl@400 { + ams_pl: ams-pl@400 { compatible = "xlnx,zynqmp-ams-pl"; status = "disabled"; reg = <0x400 0x400>; @@ -955,6 +982,7 @@ }; zynqmp_dpsub: display@fd4a0000 { + bootph-all; compatible = "xlnx,zynqmp-dpsub-1.7"; status = "disabled"; reg = <0x0 0xfd4a0000 0x0 0x1000>, diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index a24609e14d50ee77244dd2e23fc3b45884c434c5..0777bcae9104b29f031e912de43d671a015914f9 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -41,6 +41,7 @@ CONFIG_ARCH_BCMBCA=y CONFIG_ARCH_BRCMSTB=y CONFIG_ARCH_BERLIN=y CONFIG_ARCH_EXYNOS=y +CONFIG_ARCH_SPARX5=y CONFIG_ARCH_K3=y CONFIG_ARCH_LG1K=y CONFIG_ARCH_HISI=y @@ -52,12 +53,15 @@ CONFIG_ARCH_NXP=y CONFIG_ARCH_LAYERSCAPE=y CONFIG_ARCH_MXC=y CONFIG_ARCH_S32=y +CONFIG_ARCH_MA35=y CONFIG_ARCH_NPCM=y CONFIG_ARCH_QCOM=y +CONFIG_ARCH_REALTEK=y CONFIG_ARCH_RENESAS=y CONFIG_ARCH_ROCKCHIP=y CONFIG_ARCH_SEATTLE=y CONFIG_ARCH_INTEL_SOCFPGA=y +CONFIG_ARCH_STM32=y CONFIG_ARCH_SYNQUACER=y CONFIG_ARCH_TEGRA=y CONFIG_ARCH_TESLA_FSD=y @@ -267,6 +271,8 @@ CONFIG_MTD_NAND_BRCMNAND=m CONFIG_MTD_NAND_FSL_IFC=y CONFIG_MTD_NAND_QCOM=y CONFIG_MTD_SPI_NOR=y +CONFIG_MTD_UBI=m +CONFIG_UBIFS_FS=m CONFIG_BLK_DEV_LOOP=y CONFIG_BLK_DEV_NBD=m CONFIG_VIRTIO_BLK=y @@ -413,6 +419,7 @@ CONFIG_KEYBOARD_GPIO=y CONFIG_KEYBOARD_SNVS_PWRKEY=m CONFIG_KEYBOARD_IMX_SC_KEY=m CONFIG_KEYBOARD_CROS_EC=y +CONFIG_KEYBOARD_MTK_PMIC=m CONFIG_MOUSE_ELAN_I2C=m CONFIG_INPUT_TOUCHSCREEN=y CONFIG_TOUCHSCREEN_ATMEL_MXT=m @@ -461,6 +468,8 @@ CONFIG_SERIAL_FSL_LPUART=y CONFIG_SERIAL_FSL_LPUART_CONSOLE=y CONFIG_SERIAL_FSL_LINFLEXUART=y CONFIG_SERIAL_FSL_LINFLEXUART_CONSOLE=y +CONFIG_SERIAL_STM32=y +CONFIG_SERIAL_STM32_CONSOLE=y CONFIG_SERIAL_MVEBU_UART=y CONFIG_SERIAL_OWL=y CONFIG_SERIAL_DEV_BUS=y @@ -688,9 +697,11 @@ CONFIG_MFD_MAX77620=y CONFIG_MFD_MT6360=y CONFIG_MFD_MT6397=y CONFIG_MFD_SPMI_PMIC=y -CONFIG_MFD_RK808=y +CONFIG_MFD_RK8XX_I2C=y +CONFIG_MFD_RK8XX_SPI=y CONFIG_MFD_SEC_CORE=y CONFIG_MFD_SL28CPLD=y +CONFIG_RZ_MTU3=y CONFIG_MFD_TPS65219=y CONFIG_MFD_TI_AM335X_TSCADC=m CONFIG_MFD_ROHM_BD718XX=y @@ -708,6 +719,7 @@ CONFIG_REGULATOR_MAX77620=y CONFIG_REGULATOR_MAX8973=y CONFIG_REGULATOR_MP8859=y CONFIG_REGULATOR_MT6315=m +CONFIG_REGULATOR_MT6357=y CONFIG_REGULATOR_MT6358=y CONFIG_REGULATOR_MT6359=y CONFIG_REGULATOR_MT6360=y @@ -743,6 +755,10 @@ CONFIG_SDR_PLATFORM_DRIVERS=y CONFIG_V4L_MEM2MEM_DRIVERS=y CONFIG_VIDEO_MEDIATEK_JPEG=m CONFIG_VIDEO_MEDIATEK_VCODEC=m +CONFIG_VIDEO_IMX7_CSI=m +CONFIG_VIDEO_IMX_MIPI_CSIS=m +CONFIG_VIDEO_IMX8_ISI=m +CONFIG_VIDEO_IMX8_ISI_M2M=y CONFIG_VIDEO_QCOM_CAMSS=m CONFIG_VIDEO_QCOM_VENUS=m CONFIG_VIDEO_RCAR_ISP=m @@ -810,7 +826,9 @@ CONFIG_DRM_PARADE_PS8640=m CONFIG_DRM_SII902X=m CONFIG_DRM_SIMPLE_BRIDGE=m CONFIG_DRM_THINE_THC63LVD1024=m +CONFIG_DRM_TOSHIBA_TC358768=m CONFIG_DRM_TI_TFP410=m +CONFIG_DRM_TI_SN65DSI83=m CONFIG_DRM_TI_SN65DSI86=m CONFIG_DRM_ANALOGIX_ANX7625=m CONFIG_DRM_I2C_ADV7511=m @@ -870,6 +888,7 @@ CONFIG_SND_SOC_SM8250=m CONFIG_SND_SOC_SC7180=m CONFIG_SND_SOC_SC7280=m CONFIG_SND_SOC_ROCKCHIP=m +CONFIG_SND_SOC_ROCKCHIP_I2S_TDM=m CONFIG_SND_SOC_ROCKCHIP_SPDIF=m CONFIG_SND_SOC_ROCKCHIP_RT5645=m CONFIG_SND_SOC_RK3399_GRU_SOUND=m @@ -900,6 +919,7 @@ CONFIG_SND_SOC_AK4613=m CONFIG_SND_SOC_DA7213=m CONFIG_SND_SOC_ES7134=m CONFIG_SND_SOC_ES7241=m +CONFIG_SND_SOC_ES8316=m CONFIG_SND_SOC_GTM601=m CONFIG_SND_SOC_MSM8916_WCD_ANALOG=m CONFIG_SND_SOC_MSM8916_WCD_DIGITAL=m @@ -992,6 +1012,7 @@ CONFIG_TYPEC_FUSB302=m CONFIG_TYPEC_TPS6598X=m CONFIG_TYPEC_HD3SS3220=m CONFIG_TYPEC_UCSI=m +CONFIG_TYPEC_MUX_FSA4480=m CONFIG_UCSI_CCG=m CONFIG_TYPEC_MUX_GPIO_SBU=m CONFIG_MMC=y @@ -1003,6 +1024,7 @@ CONFIG_MMC_SDHCI_PLTFM=y CONFIG_MMC_SDHCI_OF_ARASAN=y CONFIG_MMC_SDHCI_OF_ESDHC=y CONFIG_MMC_SDHCI_OF_DWCMSHC=y +CONFIG_MMC_SDHCI_OF_SPARX5=y CONFIG_MMC_SDHCI_CADENCE=y CONFIG_MMC_SDHCI_ESDHC_IMX=y CONFIG_MMC_SDHCI_TEGRA=y @@ -1153,6 +1175,7 @@ CONFIG_QCOM_CLK_APCS_MSM8916=y CONFIG_QCOM_CLK_APCC_MSM8996=y CONFIG_QCOM_CLK_SMD_RPM=y CONFIG_QCOM_CLK_RPMH=y +CONFIG_IPQ_APSS_6018=y CONFIG_IPQ_GCC_5332=y CONFIG_IPQ_GCC_6018=y CONFIG_IPQ_GCC_8074=y @@ -1163,19 +1186,24 @@ CONFIG_MSM_MMCC_8994=m CONFIG_MSM_MMCC_8996=m CONFIG_MSM_MMCC_8998=m CONFIG_MSM_GCC_8998=y +CONFIG_QCM_GCC_2290=y +CONFIG_QCM_DISPCC_2290=m CONFIG_QCS_GCC_404=y CONFIG_SA_GCC_8775P=y CONFIG_SC_DISPCC_8280XP=m +CONFIG_SA_GPUCC_8775P=m CONFIG_SC_GCC_7180=y CONFIG_SC_GCC_7280=y CONFIG_SC_GCC_8180X=y CONFIG_SC_GCC_8280XP=y +CONFIG_SC_LPASSCC_8280XP=m CONFIG_SDM_CAMCC_845=m CONFIG_SDM_GPUCC_845=y CONFIG_SDM_VIDEOCC_845=y CONFIG_SDM_DISPCC_845=y CONFIG_SDM_LPASSCC_845=m CONFIG_SM_CAMCC_8250=m +CONFIG_SM_DISPCC_6115=m CONFIG_SM_DISPCC_8250=y CONFIG_SM_DISPCC_8450=m CONFIG_SM_DISPCC_8550=m @@ -1184,6 +1212,7 @@ CONFIG_SM_GCC_8350=y CONFIG_SM_GCC_8450=y CONFIG_SM_GCC_8550=y CONFIG_SM_TCSRCC_8550=y +CONFIG_SM_GPUCC_6115=m CONFIG_SM_GPUCC_8150=y CONFIG_SM_GPUCC_8250=y CONFIG_SM_VIDEOCC_8250=y @@ -1319,9 +1348,11 @@ CONFIG_PWM_SAMSUNG=y CONFIG_PWM_SL28CPLD=m CONFIG_PWM_SUN4I=m CONFIG_PWM_TEGRA=m +CONFIG_PWM_TIEHRPWM=m CONFIG_PWM_VISCONTI=m CONFIG_SL28CPLD_INTC=y CONFIG_QCOM_PDC=y +CONFIG_QCOM_MPM=y CONFIG_RESET_IMX7=y CONFIG_RESET_QCOM_AOSS=y CONFIG_RESET_QCOM_PDC=m @@ -1412,6 +1443,7 @@ CONFIG_INTERCONNECT_QCOM=y CONFIG_INTERCONNECT_QCOM_MSM8916=m CONFIG_INTERCONNECT_QCOM_MSM8996=m CONFIG_INTERCONNECT_QCOM_OSM_L3=m +CONFIG_INTERCONNECT_QCOM_QCM2290=m CONFIG_INTERCONNECT_QCOM_QCS404=m CONFIG_INTERCONNECT_QCOM_SA8775P=y CONFIG_INTERCONNECT_QCOM_SC7180=y @@ -1424,6 +1456,8 @@ CONFIG_INTERCONNECT_QCOM_SM8250=m CONFIG_INTERCONNECT_QCOM_SM8350=m CONFIG_INTERCONNECT_QCOM_SM8450=y CONFIG_INTERCONNECT_QCOM_SM8550=y +CONFIG_COUNTER=m +CONFIG_RZ_MTU3_CNT=m CONFIG_HTE=y CONFIG_HTE_TEGRA194=y CONFIG_HTE_TEGRA194_TEST=m diff --git a/arch/arm64/crypto/sha256-glue.c b/arch/arm64/crypto/sha256-glue.c index 9462f6088b3f424c949e6c3b29eba2120f8e61a8..9b5c86e07a9af3db024c34bedeedf88a7c94b447 100644 --- a/arch/arm64/crypto/sha256-glue.c +++ b/arch/arm64/crypto/sha256-glue.c @@ -12,8 +12,9 @@ #include #include #include -#include +#include #include +#include MODULE_DESCRIPTION("SHA-224/SHA-256 secure hash for arm64"); MODULE_AUTHOR("Andy Polyakov "); diff --git a/arch/arm64/hyperv/mshyperv.c b/arch/arm64/hyperv/mshyperv.c index a406454578f07e2a59c5a34639503ea0692f8fa6..f1b8a04ee9f26364bdebe33510cd135781d3f63b 100644 --- a/arch/arm64/hyperv/mshyperv.c +++ b/arch/arm64/hyperv/mshyperv.c @@ -67,7 +67,7 @@ static int __init hyperv_init(void) if (ret) return ret; - ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "arm64/hyperv_init:online", + ret = cpuhp_setup_state(CPUHP_AP_HYPERV_ONLINE, "arm64/hyperv_init:online", hv_common_cpu_init, hv_common_cpu_die); if (ret < 0) { hv_common_free(); diff --git a/arch/arm64/include/asm/alternative-macros.h b/arch/arm64/include/asm/alternative-macros.h index bdf1f6bcd010351700ee13585e4d0f9f207300d5..94b486192e1f154aa4e1e31111b45885f2b57a7b 100644 --- a/arch/arm64/include/asm/alternative-macros.h +++ b/arch/arm64/include/asm/alternative-macros.h @@ -23,17 +23,17 @@ #include -#define ALTINSTR_ENTRY(feature) \ +#define ALTINSTR_ENTRY(cpucap) \ " .word 661b - .\n" /* label */ \ " .word 663f - .\n" /* new instruction */ \ - " .hword " __stringify(feature) "\n" /* feature bit */ \ + " .hword " __stringify(cpucap) "\n" /* cpucap */ \ " .byte 662b-661b\n" /* source len */ \ " .byte 664f-663f\n" /* replacement len */ -#define ALTINSTR_ENTRY_CB(feature, cb) \ +#define ALTINSTR_ENTRY_CB(cpucap, cb) \ " .word 661b - .\n" /* label */ \ - " .word " __stringify(cb) "- .\n" /* callback */ \ - " .hword " __stringify(feature) "\n" /* feature bit */ \ + " .word " __stringify(cb) "- .\n" /* callback */ \ + " .hword " __stringify(cpucap) "\n" /* cpucap */ \ " .byte 662b-661b\n" /* source len */ \ " .byte 664f-663f\n" /* replacement len */ @@ -53,13 +53,13 @@ * * Alternatives with callbacks do not generate replacement instructions. */ -#define __ALTERNATIVE_CFG(oldinstr, newinstr, feature, cfg_enabled) \ +#define __ALTERNATIVE_CFG(oldinstr, newinstr, cpucap, cfg_enabled) \ ".if "__stringify(cfg_enabled)" == 1\n" \ "661:\n\t" \ oldinstr "\n" \ "662:\n" \ ".pushsection .altinstructions,\"a\"\n" \ - ALTINSTR_ENTRY(feature) \ + ALTINSTR_ENTRY(cpucap) \ ".popsection\n" \ ".subsection 1\n" \ "663:\n\t" \ @@ -70,31 +70,31 @@ ".previous\n" \ ".endif\n" -#define __ALTERNATIVE_CFG_CB(oldinstr, feature, cfg_enabled, cb) \ +#define __ALTERNATIVE_CFG_CB(oldinstr, cpucap, cfg_enabled, cb) \ ".if "__stringify(cfg_enabled)" == 1\n" \ "661:\n\t" \ oldinstr "\n" \ "662:\n" \ ".pushsection .altinstructions,\"a\"\n" \ - ALTINSTR_ENTRY_CB(feature, cb) \ + ALTINSTR_ENTRY_CB(cpucap, cb) \ ".popsection\n" \ "663:\n\t" \ "664:\n\t" \ ".endif\n" -#define _ALTERNATIVE_CFG(oldinstr, newinstr, feature, cfg, ...) \ - __ALTERNATIVE_CFG(oldinstr, newinstr, feature, IS_ENABLED(cfg)) +#define _ALTERNATIVE_CFG(oldinstr, newinstr, cpucap, cfg, ...) \ + __ALTERNATIVE_CFG(oldinstr, newinstr, cpucap, IS_ENABLED(cfg)) -#define ALTERNATIVE_CB(oldinstr, feature, cb) \ - __ALTERNATIVE_CFG_CB(oldinstr, (1 << ARM64_CB_SHIFT) | (feature), 1, cb) +#define ALTERNATIVE_CB(oldinstr, cpucap, cb) \ + __ALTERNATIVE_CFG_CB(oldinstr, (1 << ARM64_CB_SHIFT) | (cpucap), 1, cb) #else #include -.macro altinstruction_entry orig_offset alt_offset feature orig_len alt_len +.macro altinstruction_entry orig_offset alt_offset cpucap orig_len alt_len .word \orig_offset - . .word \alt_offset - . - .hword (\feature) + .hword (\cpucap) .byte \orig_len .byte \alt_len .endm @@ -210,9 +210,9 @@ alternative_endif #endif /* __ASSEMBLY__ */ /* - * Usage: asm(ALTERNATIVE(oldinstr, newinstr, feature)); + * Usage: asm(ALTERNATIVE(oldinstr, newinstr, cpucap)); * - * Usage: asm(ALTERNATIVE(oldinstr, newinstr, feature, CONFIG_FOO)); + * Usage: asm(ALTERNATIVE(oldinstr, newinstr, cpucap, CONFIG_FOO)); * N.B. If CONFIG_FOO is specified, but not selected, the whole block * will be omitted, including oldinstr. */ @@ -224,15 +224,15 @@ alternative_endif #include static __always_inline bool -alternative_has_feature_likely(const unsigned long feature) +alternative_has_cap_likely(const unsigned long cpucap) { - compiletime_assert(feature < ARM64_NCAPS, - "feature must be < ARM64_NCAPS"); + compiletime_assert(cpucap < ARM64_NCAPS, + "cpucap must be < ARM64_NCAPS"); asm_volatile_goto( - ALTERNATIVE_CB("b %l[l_no]", %[feature], alt_cb_patch_nops) + ALTERNATIVE_CB("b %l[l_no]", %[cpucap], alt_cb_patch_nops) : - : [feature] "i" (feature) + : [cpucap] "i" (cpucap) : : l_no); @@ -242,15 +242,15 @@ alternative_has_feature_likely(const unsigned long feature) } static __always_inline bool -alternative_has_feature_unlikely(const unsigned long feature) +alternative_has_cap_unlikely(const unsigned long cpucap) { - compiletime_assert(feature < ARM64_NCAPS, - "feature must be < ARM64_NCAPS"); + compiletime_assert(cpucap < ARM64_NCAPS, + "cpucap must be < ARM64_NCAPS"); asm_volatile_goto( - ALTERNATIVE("nop", "b %l[l_yes]", %[feature]) + ALTERNATIVE("nop", "b %l[l_yes]", %[cpucap]) : - : [feature] "i" (feature) + : [cpucap] "i" (cpucap) : : l_yes); diff --git a/arch/arm64/include/asm/alternative.h b/arch/arm64/include/asm/alternative.h index a38b92e11811e8b1ce379df536e11545bff4f1cc..00d97b8a757f4250b818691813d0f1bbdcc41026 100644 --- a/arch/arm64/include/asm/alternative.h +++ b/arch/arm64/include/asm/alternative.h @@ -13,7 +13,7 @@ struct alt_instr { s32 orig_offset; /* offset to original instruction */ s32 alt_offset; /* offset to replacement instruction */ - u16 cpufeature; /* cpufeature bit set for replacement */ + u16 cpucap; /* cpucap bit set for replacement */ u8 orig_len; /* size of original instruction(s) */ u8 alt_len; /* size of new instruction(s), <= orig_len */ }; @@ -23,7 +23,7 @@ typedef void (*alternative_cb_t)(struct alt_instr *alt, void __init apply_boot_alternatives(void); void __init apply_alternatives_all(void); -bool alternative_is_applied(u16 cpufeature); +bool alternative_is_applied(u16 cpucap); #ifdef CONFIG_MODULES void apply_alternatives_module(void *start, size_t length); @@ -31,5 +31,8 @@ void apply_alternatives_module(void *start, size_t length); static inline void apply_alternatives_module(void *start, size_t length) { } #endif +void alt_cb_patch_nops(struct alt_instr *alt, __le32 *origptr, + __le32 *updptr, int nr_inst); + #endif /* __ASSEMBLY__ */ #endif /* __ASM_ALTERNATIVE_H */ diff --git a/arch/arm64/include/asm/arch_timer.h b/arch/arm64/include/asm/arch_timer.h index af1fafbe7e1d367890d303f688dd7c93fa058928..934c658ee947ce9c51838132994d54fdd4dc46e2 100644 --- a/arch/arm64/include/asm/arch_timer.h +++ b/arch/arm64/include/asm/arch_timer.h @@ -88,13 +88,7 @@ static inline notrace u64 arch_timer_read_cntvct_el0(void) #define arch_timer_reg_read_stable(reg) \ ({ \ - u64 _val; \ - \ - preempt_disable_notrace(); \ - _val = erratum_handler(read_ ## reg)(); \ - preempt_enable_notrace(); \ - \ - _val; \ + erratum_handler(read_ ## reg)(); \ }) /* diff --git a/arch/arm64/include/asm/archrandom.h b/arch/arm64/include/asm/archrandom.h index 2f5f3da3478288af69509f6f9a40ae7fa6455064..b0abc64f86b038e97968ad8d7080dbfcb3ac3618 100644 --- a/arch/arm64/include/asm/archrandom.h +++ b/arch/arm64/include/asm/archrandom.h @@ -129,4 +129,6 @@ static inline bool __init __early_cpu_has_rndr(void) return (ftr >> ID_AA64ISAR0_EL1_RNDR_SHIFT) & 0xf; } +u64 kaslr_early_init(void *fdt); + #endif /* _ASM_ARCHRANDOM_H */ diff --git a/arch/arm64/include/asm/asm-uaccess.h b/arch/arm64/include/asm/asm-uaccess.h index 75b211c98dead5e6863718bb12f6584d8d4a2243..5b6efe8abeeb4462ccfb033bdf71663f3aedfb5d 100644 --- a/arch/arm64/include/asm/asm-uaccess.h +++ b/arch/arm64/include/asm/asm-uaccess.h @@ -18,7 +18,6 @@ bic \tmp1, \tmp1, #TTBR_ASID_MASK sub \tmp1, \tmp1, #RESERVED_SWAPPER_OFFSET // reserved_pg_dir msr ttbr0_el1, \tmp1 // set reserved TTBR0_EL1 - isb add \tmp1, \tmp1, #RESERVED_SWAPPER_OFFSET msr ttbr1_el1, \tmp1 // set reserved ASID isb @@ -31,7 +30,6 @@ extr \tmp2, \tmp2, \tmp1, #48 ror \tmp2, \tmp2, #16 msr ttbr1_el1, \tmp2 // set the active ASID - isb msr ttbr0_el1, \tmp1 // set the non-PAN TTBR0_EL1 isb .endm diff --git a/arch/arm64/include/asm/atomic.h b/arch/arm64/include/asm/atomic.h index c9979273d38981164bdfb6016760a9c77774f6aa..400d279e0f8d0237d69eddd42ca7d9b12f26fca0 100644 --- a/arch/arm64/include/asm/atomic.h +++ b/arch/arm64/include/asm/atomic.h @@ -142,24 +142,6 @@ static __always_inline long arch_atomic64_dec_if_positive(atomic64_t *v) #define arch_atomic_fetch_xor_release arch_atomic_fetch_xor_release #define arch_atomic_fetch_xor arch_atomic_fetch_xor -#define arch_atomic_xchg_relaxed(v, new) \ - arch_xchg_relaxed(&((v)->counter), (new)) -#define arch_atomic_xchg_acquire(v, new) \ - arch_xchg_acquire(&((v)->counter), (new)) -#define arch_atomic_xchg_release(v, new) \ - arch_xchg_release(&((v)->counter), (new)) -#define arch_atomic_xchg(v, new) \ - arch_xchg(&((v)->counter), (new)) - -#define arch_atomic_cmpxchg_relaxed(v, old, new) \ - arch_cmpxchg_relaxed(&((v)->counter), (old), (new)) -#define arch_atomic_cmpxchg_acquire(v, old, new) \ - arch_cmpxchg_acquire(&((v)->counter), (old), (new)) -#define arch_atomic_cmpxchg_release(v, old, new) \ - arch_cmpxchg_release(&((v)->counter), (old), (new)) -#define arch_atomic_cmpxchg(v, old, new) \ - arch_cmpxchg(&((v)->counter), (old), (new)) - #define arch_atomic_andnot arch_atomic_andnot /* @@ -209,16 +191,6 @@ static __always_inline long arch_atomic64_dec_if_positive(atomic64_t *v) #define arch_atomic64_fetch_xor_release arch_atomic64_fetch_xor_release #define arch_atomic64_fetch_xor arch_atomic64_fetch_xor -#define arch_atomic64_xchg_relaxed arch_atomic_xchg_relaxed -#define arch_atomic64_xchg_acquire arch_atomic_xchg_acquire -#define arch_atomic64_xchg_release arch_atomic_xchg_release -#define arch_atomic64_xchg arch_atomic_xchg - -#define arch_atomic64_cmpxchg_relaxed arch_atomic_cmpxchg_relaxed -#define arch_atomic64_cmpxchg_acquire arch_atomic_cmpxchg_acquire -#define arch_atomic64_cmpxchg_release arch_atomic_cmpxchg_release -#define arch_atomic64_cmpxchg arch_atomic_cmpxchg - #define arch_atomic64_andnot arch_atomic64_andnot #define arch_atomic64_dec_if_positive arch_atomic64_dec_if_positive diff --git a/arch/arm64/include/asm/atomic_ll_sc.h b/arch/arm64/include/asm/atomic_ll_sc.h index cbb3d961123b17aba398f29c2a346ac2e7f5bf47..89d2ba2723590d7908e01f27c2ffe1022d638b14 100644 --- a/arch/arm64/include/asm/atomic_ll_sc.h +++ b/arch/arm64/include/asm/atomic_ll_sc.h @@ -294,38 +294,46 @@ __CMPXCHG_CASE( , , mb_, 64, dmb ish, , l, "memory", L) #undef __CMPXCHG_CASE -#define __CMPXCHG_DBL(name, mb, rel, cl) \ -static __always_inline long \ -__ll_sc__cmpxchg_double##name(unsigned long old1, \ - unsigned long old2, \ - unsigned long new1, \ - unsigned long new2, \ - volatile void *ptr) \ +union __u128_halves { + u128 full; + struct { + u64 low, high; + }; +}; + +#define __CMPXCHG128(name, mb, rel, cl...) \ +static __always_inline u128 \ +__ll_sc__cmpxchg128##name(volatile u128 *ptr, u128 old, u128 new) \ { \ - unsigned long tmp, ret; \ + union __u128_halves r, o = { .full = (old) }, \ + n = { .full = (new) }; \ + unsigned int tmp; \ \ - asm volatile("// __cmpxchg_double" #name "\n" \ - " prfm pstl1strm, %2\n" \ - "1: ldxp %0, %1, %2\n" \ - " eor %0, %0, %3\n" \ - " eor %1, %1, %4\n" \ - " orr %1, %0, %1\n" \ - " cbnz %1, 2f\n" \ - " st" #rel "xp %w0, %5, %6, %2\n" \ - " cbnz %w0, 1b\n" \ + asm volatile("// __cmpxchg128" #name "\n" \ + " prfm pstl1strm, %[v]\n" \ + "1: ldxp %[rl], %[rh], %[v]\n" \ + " cmp %[rl], %[ol]\n" \ + " ccmp %[rh], %[oh], 0, eq\n" \ + " b.ne 2f\n" \ + " st" #rel "xp %w[tmp], %[nl], %[nh], %[v]\n" \ + " cbnz %w[tmp], 1b\n" \ " " #mb "\n" \ "2:" \ - : "=&r" (tmp), "=&r" (ret), "+Q" (*(__uint128_t *)ptr) \ - : "r" (old1), "r" (old2), "r" (new1), "r" (new2) \ - : cl); \ + : [v] "+Q" (*(u128 *)ptr), \ + [rl] "=&r" (r.low), [rh] "=&r" (r.high), \ + [tmp] "=&r" (tmp) \ + : [ol] "r" (o.low), [oh] "r" (o.high), \ + [nl] "r" (n.low), [nh] "r" (n.high) \ + : "cc", ##cl); \ \ - return ret; \ + return r.full; \ } -__CMPXCHG_DBL( , , , ) -__CMPXCHG_DBL(_mb, dmb ish, l, "memory") +__CMPXCHG128( , , ) +__CMPXCHG128(_mb, dmb ish, l, "memory") + +#undef __CMPXCHG128 -#undef __CMPXCHG_DBL #undef K #endif /* __ASM_ATOMIC_LL_SC_H */ diff --git a/arch/arm64/include/asm/atomic_lse.h b/arch/arm64/include/asm/atomic_lse.h index 319958b95cfd82c7f3edd48db403efbe2eefcaba..87f568a94e558716c9ced5459803947bffd81adf 100644 --- a/arch/arm64/include/asm/atomic_lse.h +++ b/arch/arm64/include/asm/atomic_lse.h @@ -281,40 +281,35 @@ __CMPXCHG_CASE(x, , mb_, 64, al, "memory") #undef __CMPXCHG_CASE -#define __CMPXCHG_DBL(name, mb, cl...) \ -static __always_inline long \ -__lse__cmpxchg_double##name(unsigned long old1, \ - unsigned long old2, \ - unsigned long new1, \ - unsigned long new2, \ - volatile void *ptr) \ +#define __CMPXCHG128(name, mb, cl...) \ +static __always_inline u128 \ +__lse__cmpxchg128##name(volatile u128 *ptr, u128 old, u128 new) \ { \ - unsigned long oldval1 = old1; \ - unsigned long oldval2 = old2; \ - register unsigned long x0 asm ("x0") = old1; \ - register unsigned long x1 asm ("x1") = old2; \ - register unsigned long x2 asm ("x2") = new1; \ - register unsigned long x3 asm ("x3") = new2; \ + union __u128_halves r, o = { .full = (old) }, \ + n = { .full = (new) }; \ + register unsigned long x0 asm ("x0") = o.low; \ + register unsigned long x1 asm ("x1") = o.high; \ + register unsigned long x2 asm ("x2") = n.low; \ + register unsigned long x3 asm ("x3") = n.high; \ register unsigned long x4 asm ("x4") = (unsigned long)ptr; \ \ asm volatile( \ __LSE_PREAMBLE \ " casp" #mb "\t%[old1], %[old2], %[new1], %[new2], %[v]\n"\ - " eor %[old1], %[old1], %[oldval1]\n" \ - " eor %[old2], %[old2], %[oldval2]\n" \ - " orr %[old1], %[old1], %[old2]" \ : [old1] "+&r" (x0), [old2] "+&r" (x1), \ - [v] "+Q" (*(__uint128_t *)ptr) \ + [v] "+Q" (*(u128 *)ptr) \ : [new1] "r" (x2), [new2] "r" (x3), [ptr] "r" (x4), \ - [oldval1] "r" (oldval1), [oldval2] "r" (oldval2) \ + [oldval1] "r" (o.low), [oldval2] "r" (o.high) \ : cl); \ \ - return x0; \ + r.low = x0; r.high = x1; \ + \ + return r.full; \ } -__CMPXCHG_DBL( , ) -__CMPXCHG_DBL(_mb, al, "memory") +__CMPXCHG128( , ) +__CMPXCHG128(_mb, al, "memory") -#undef __CMPXCHG_DBL +#undef __CMPXCHG128 #endif /* __ASM_ATOMIC_LSE_H */ diff --git a/arch/arm64/include/asm/cache.h b/arch/arm64/include/asm/cache.h index a51e6e8f31711014a73ac1d1e6b634f9e0b1d951..ceb368d33bf4eae8a054c16e54d578afde28e2f5 100644 --- a/arch/arm64/include/asm/cache.h +++ b/arch/arm64/include/asm/cache.h @@ -33,6 +33,7 @@ * the CPU. */ #define ARCH_DMA_MINALIGN (128) +#define ARCH_KMALLOC_MINALIGN (8) #ifndef __ASSEMBLY__ @@ -90,6 +91,8 @@ static inline int cache_line_size_of_cpu(void) int cache_line_size(void); +#define dma_get_cache_alignment cache_line_size + /* * Read the effective value of CTR_EL0. * diff --git a/arch/arm64/include/asm/cmpxchg.h b/arch/arm64/include/asm/cmpxchg.h index c6bc5d8ec3ca41b912253fdb96416089cd241a4b..d7a5407367414df69a898bef948f7c896778f38b 100644 --- a/arch/arm64/include/asm/cmpxchg.h +++ b/arch/arm64/include/asm/cmpxchg.h @@ -130,21 +130,18 @@ __CMPXCHG_CASE(mb_, 64) #undef __CMPXCHG_CASE -#define __CMPXCHG_DBL(name) \ -static inline long __cmpxchg_double##name(unsigned long old1, \ - unsigned long old2, \ - unsigned long new1, \ - unsigned long new2, \ - volatile void *ptr) \ +#define __CMPXCHG128(name) \ +static inline u128 __cmpxchg128##name(volatile u128 *ptr, \ + u128 old, u128 new) \ { \ - return __lse_ll_sc_body(_cmpxchg_double##name, \ - old1, old2, new1, new2, ptr); \ + return __lse_ll_sc_body(_cmpxchg128##name, \ + ptr, old, new); \ } -__CMPXCHG_DBL( ) -__CMPXCHG_DBL(_mb) +__CMPXCHG128( ) +__CMPXCHG128(_mb) -#undef __CMPXCHG_DBL +#undef __CMPXCHG128 #define __CMPXCHG_GEN(sfx) \ static __always_inline unsigned long __cmpxchg##sfx(volatile void *ptr, \ @@ -198,34 +195,17 @@ __CMPXCHG_GEN(_mb) #define arch_cmpxchg64 arch_cmpxchg #define arch_cmpxchg64_local arch_cmpxchg_local -/* cmpxchg_double */ -#define system_has_cmpxchg_double() 1 - -#define __cmpxchg_double_check(ptr1, ptr2) \ -({ \ - if (sizeof(*(ptr1)) != 8) \ - BUILD_BUG(); \ - VM_BUG_ON((unsigned long *)(ptr2) - (unsigned long *)(ptr1) != 1); \ -}) +/* cmpxchg128 */ +#define system_has_cmpxchg128() 1 -#define arch_cmpxchg_double(ptr1, ptr2, o1, o2, n1, n2) \ +#define arch_cmpxchg128(ptr, o, n) \ ({ \ - int __ret; \ - __cmpxchg_double_check(ptr1, ptr2); \ - __ret = !__cmpxchg_double_mb((unsigned long)(o1), (unsigned long)(o2), \ - (unsigned long)(n1), (unsigned long)(n2), \ - ptr1); \ - __ret; \ + __cmpxchg128_mb((ptr), (o), (n)); \ }) -#define arch_cmpxchg_double_local(ptr1, ptr2, o1, o2, n1, n2) \ +#define arch_cmpxchg128_local(ptr, o, n) \ ({ \ - int __ret; \ - __cmpxchg_double_check(ptr1, ptr2); \ - __ret = !__cmpxchg_double((unsigned long)(o1), (unsigned long)(o2), \ - (unsigned long)(n1), (unsigned long)(n2), \ - ptr1); \ - __ret; \ + __cmpxchg128((ptr), (o), (n)); \ }) #define __CMPWAIT_CASE(w, sfx, sz) \ diff --git a/arch/arm64/include/asm/compat.h b/arch/arm64/include/asm/compat.h index 74575c3d6987069f634e956760a553fbb23f317b..ae904a1ad5293bb3f85c5631ed6c0e8fe0e96853 100644 --- a/arch/arm64/include/asm/compat.h +++ b/arch/arm64/include/asm/compat.h @@ -96,6 +96,8 @@ static inline int is_compat_thread(struct thread_info *thread) return test_ti_thread_flag(thread, TIF_32BIT); } +long compat_arm_syscall(struct pt_regs *regs, int scno); + #else /* !CONFIG_COMPAT */ static inline int is_compat_thread(struct thread_info *thread) diff --git a/arch/arm64/include/asm/cpu.h b/arch/arm64/include/asm/cpu.h index fd7a92219eea99697a64b0cbcc794c275ef5241c..e749838b9c5d4e03517f0e9261f3c6740555845c 100644 --- a/arch/arm64/include/asm/cpu.h +++ b/arch/arm64/include/asm/cpu.h @@ -56,6 +56,7 @@ struct cpuinfo_arm64 { u64 reg_id_aa64mmfr0; u64 reg_id_aa64mmfr1; u64 reg_id_aa64mmfr2; + u64 reg_id_aa64mmfr3; u64 reg_id_aa64pfr0; u64 reg_id_aa64pfr1; u64 reg_id_aa64zfr0; diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h index 6bf013fb110d792304205a4494f9ee6208bcdf7a..96e50227f940ecbde381ccc422d9d8c1433e5e2c 100644 --- a/arch/arm64/include/asm/cpufeature.h +++ b/arch/arm64/include/asm/cpufeature.h @@ -15,6 +15,9 @@ #define MAX_CPU_FEATURES 128 #define cpu_feature(x) KERNEL_HWCAP_ ## x +#define ARM64_SW_FEATURE_OVERRIDE_NOKASLR 0 +#define ARM64_SW_FEATURE_OVERRIDE_HVHE 4 + #ifndef __ASSEMBLY__ #include @@ -107,7 +110,7 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0; * CPU capabilities: * * We use arm64_cpu_capabilities to represent system features, errata work - * arounds (both used internally by kernel and tracked in cpu_hwcaps) and + * arounds (both used internally by kernel and tracked in system_cpucaps) and * ELF HWCAPs (which are exposed to user). * * To support systems with heterogeneous CPUs, we need to make sure that we @@ -419,12 +422,12 @@ static __always_inline bool is_hyp_code(void) return is_vhe_hyp_code() || is_nvhe_hyp_code(); } -extern DECLARE_BITMAP(cpu_hwcaps, ARM64_NCAPS); +extern DECLARE_BITMAP(system_cpucaps, ARM64_NCAPS); -extern DECLARE_BITMAP(boot_capabilities, ARM64_NCAPS); +extern DECLARE_BITMAP(boot_cpucaps, ARM64_NCAPS); #define for_each_available_cap(cap) \ - for_each_set_bit(cap, cpu_hwcaps, ARM64_NCAPS) + for_each_set_bit(cap, system_cpucaps, ARM64_NCAPS) bool this_cpu_has_cap(unsigned int cap); void cpu_set_feature(unsigned int num); @@ -437,7 +440,7 @@ unsigned long cpu_get_elf_hwcap2(void); static __always_inline bool system_capabilities_finalized(void) { - return alternative_has_feature_likely(ARM64_ALWAYS_SYSTEM); + return alternative_has_cap_likely(ARM64_ALWAYS_SYSTEM); } /* @@ -449,7 +452,7 @@ static __always_inline bool cpus_have_cap(unsigned int num) { if (num >= ARM64_NCAPS) return false; - return arch_test_bit(num, cpu_hwcaps); + return arch_test_bit(num, system_cpucaps); } /* @@ -464,7 +467,7 @@ static __always_inline bool __cpus_have_const_cap(int num) { if (num >= ARM64_NCAPS) return false; - return alternative_has_feature_unlikely(num); + return alternative_has_cap_unlikely(num); } /* @@ -504,16 +507,6 @@ static __always_inline bool cpus_have_const_cap(int num) return cpus_have_cap(num); } -static inline void cpus_set_cap(unsigned int num) -{ - if (num >= ARM64_NCAPS) { - pr_warn("Attempt to set an illegal CPU capability (%d >= %d)\n", - num, ARM64_NCAPS); - } else { - __set_bit(num, cpu_hwcaps); - } -} - static inline int __attribute_const__ cpuid_feature_extract_signed_field_width(u64 features, int field, int width) { @@ -915,6 +908,7 @@ static inline unsigned int get_vmid_bits(u64 mmfr1) return 8; } +s64 arm64_ftr_safe_value(const struct arm64_ftr_bits *ftrp, s64 new, s64 cur); struct arm64_ftr_reg *get_arm64_ftr_reg(u32 sys_id); extern struct arm64_ftr_override id_aa64mmfr1_override; @@ -925,6 +919,8 @@ extern struct arm64_ftr_override id_aa64smfr0_override; extern struct arm64_ftr_override id_aa64isar1_override; extern struct arm64_ftr_override id_aa64isar2_override; +extern struct arm64_ftr_override arm64_sw_feature_override; + u32 get_kvm_ipa_limit(void); void dump_cpu_features(void); diff --git a/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h index f86b157a5da39c914fbf5d7b9dff31ff0299e324..4cf2cb053bc8df95bef51d70ccf799039969161d 100644 --- a/arch/arm64/include/asm/efi.h +++ b/arch/arm64/include/asm/efi.h @@ -88,7 +88,7 @@ efi_status_t __efi_rt_asm_wrapper(void *, const char *, ...); * guaranteed to cover the kernel Image. * * Since the EFI stub is part of the kernel Image, we can relax the - * usual requirements in Documentation/arm64/booting.rst, which still + * usual requirements in Documentation/arch/arm64/booting.rst, which still * apply to other bootloaders, and are required for some kernel * configurations. */ @@ -166,4 +166,6 @@ static inline void efi_capsule_flush_cache_range(void *addr, int size) dcache_clean_inval_poc((unsigned long)addr, (unsigned long)addr + size); } +efi_status_t efi_handle_corrupted_x18(efi_status_t s, const char *f); + #endif /* _ASM_EFI_H */ diff --git a/arch/arm64/include/asm/el2_setup.h b/arch/arm64/include/asm/el2_setup.h index 037724b19c5c84d391dcc92d175a2c30559206e8..8e5ffb58f83ea56d634e791521025ec744e0fa16 100644 --- a/arch/arm64/include/asm/el2_setup.h +++ b/arch/arm64/include/asm/el2_setup.h @@ -22,6 +22,15 @@ isb .endm +.macro __init_el2_hcrx + mrs x0, id_aa64mmfr1_el1 + ubfx x0, x0, #ID_AA64MMFR1_EL1_HCX_SHIFT, #4 + cbz x0, .Lskip_hcrx_\@ + mov_q x0, HCRX_HOST_FLAGS + msr_s SYS_HCRX_EL2, x0 +.Lskip_hcrx_\@: +.endm + /* * Allow Non-secure EL1 and EL0 to access physical timer and counter. * This is not necessary for VHE, since the host kernel runs in EL2, @@ -34,6 +43,11 @@ */ .macro __init_el2_timers mov x0, #3 // Enable EL1 physical timers + mrs x1, hcr_el2 + and x1, x1, #HCR_E2H + cbz x1, .LnVHE_\@ + lsl x0, x0, #10 +.LnVHE_\@: msr cnthctl_el2, x0 msr cntvoff_el2, xzr // Clear virtual offset .endm @@ -69,7 +83,7 @@ cbz x0, .Lskip_trace_\@ // Skip if TraceBuffer is not present mrs_s x0, SYS_TRBIDR_EL1 - and x0, x0, TRBIDR_PROG + and x0, x0, TRBIDR_EL1_P cbnz x0, .Lskip_trace_\@ // If TRBE is available at EL2 mov x0, #(MDCR_EL2_E2TB_MASK << MDCR_EL2_E2TB_SHIFT) @@ -124,8 +138,15 @@ .endm /* Coprocessor traps */ -.macro __init_el2_nvhe_cptr +.macro __init_el2_cptr + mrs x1, hcr_el2 + and x1, x1, #HCR_E2H + cbz x1, .LnVHE_\@ + mov x0, #(CPACR_EL1_FPEN_EL1EN | CPACR_EL1_FPEN_EL0EN) + b .Lset_cptr_\@ +.LnVHE_\@: mov x0, #0x33ff +.Lset_cptr_\@: msr cptr_el2, x0 // Disable copro. traps to EL2 .endm @@ -150,12 +171,21 @@ mov x0, xzr mrs x1, id_aa64pfr1_el1 ubfx x1, x1, #ID_AA64PFR1_EL1_SME_SHIFT, #4 - cbz x1, .Lset_fgt_\@ + cbz x1, .Lset_pie_fgt_\@ /* Disable nVHE traps of TPIDR2 and SMPRI */ orr x0, x0, #HFGxTR_EL2_nSMPRI_EL1_MASK orr x0, x0, #HFGxTR_EL2_nTPIDR2_EL0_MASK +.Lset_pie_fgt_\@: + mrs_s x1, SYS_ID_AA64MMFR3_EL1 + ubfx x1, x1, #ID_AA64MMFR3_EL1_S1PIE_SHIFT, #4 + cbz x1, .Lset_fgt_\@ + + /* Disable trapping of PIR_EL1 / PIRE0_EL1 */ + orr x0, x0, #HFGxTR_EL2_nPIR_EL1 + orr x0, x0, #HFGxTR_EL2_nPIRE0_EL1 + .Lset_fgt_\@: msr_s SYS_HFGRTR_EL2, x0 msr_s SYS_HFGWTR_EL2, x0 @@ -184,6 +214,7 @@ */ .macro init_el2_state __init_el2_sctlr + __init_el2_hcrx __init_el2_timers __init_el2_debug __init_el2_lor @@ -191,9 +222,8 @@ __init_el2_gicv3 __init_el2_hstr __init_el2_nvhe_idregs - __init_el2_nvhe_cptr + __init_el2_cptr __init_el2_fgt - __init_el2_nvhe_prepare_eret .endm #ifndef __KVM_NVHE_HYPERVISOR__ @@ -239,7 +269,17 @@ .Linit_sve_\@: /* SVE register access */ mrs x0, cptr_el2 // Disable SVE traps + mrs x1, hcr_el2 + and x1, x1, #HCR_E2H + cbz x1, .Lcptr_nvhe_\@ + + // VHE case + orr x0, x0, #(CPACR_EL1_ZEN_EL1EN | CPACR_EL1_ZEN_EL0EN) + b .Lset_cptr_\@ + +.Lcptr_nvhe_\@: // nVHE case bic x0, x0, #CPTR_EL2_TZ +.Lset_cptr_\@: msr cptr_el2, x0 isb mov x1, #ZCR_ELx_LEN_MASK // SVE: Enable full vector @@ -284,14 +324,6 @@ cbz x1, .Lskip_sme_\@ msr_s SYS_SMPRIMAP_EL2, xzr // Make all priorities equal - - mrs x1, id_aa64mmfr1_el1 // HCRX_EL2 present? - ubfx x1, x1, #ID_AA64MMFR1_EL1_HCX_SHIFT, #4 - cbz x1, .Lskip_sme_\@ - - mrs_s x1, SYS_HCRX_EL2 - orr x1, x1, #HCRX_EL2_SMPME_MASK // Enable priority mapping - msr_s SYS_HCRX_EL2, x1 .Lskip_sme_\@: .endm diff --git a/arch/arm64/include/asm/esr.h b/arch/arm64/include/asm/esr.h index 8487aec9b6587759eb6a57a9bd8df054785bd9a8..ae35939f395bb18e2e1c8862046edd8379113985 100644 --- a/arch/arm64/include/asm/esr.h +++ b/arch/arm64/include/asm/esr.h @@ -47,7 +47,7 @@ #define ESR_ELx_EC_DABT_LOW (0x24) #define ESR_ELx_EC_DABT_CUR (0x25) #define ESR_ELx_EC_SP_ALIGN (0x26) -/* Unallocated EC: 0x27 */ +#define ESR_ELx_EC_MOPS (0x27) #define ESR_ELx_EC_FP_EXC32 (0x28) /* Unallocated EC: 0x29 - 0x2B */ #define ESR_ELx_EC_FP_EXC64 (0x2C) @@ -75,8 +75,11 @@ #define ESR_ELx_IL_SHIFT (25) #define ESR_ELx_IL (UL(1) << ESR_ELx_IL_SHIFT) -#define ESR_ELx_ISS_MASK (ESR_ELx_IL - 1) +#define ESR_ELx_ISS_MASK (GENMASK(24, 0)) #define ESR_ELx_ISS(esr) ((esr) & ESR_ELx_ISS_MASK) +#define ESR_ELx_ISS2_SHIFT (32) +#define ESR_ELx_ISS2_MASK (GENMASK_ULL(55, 32)) +#define ESR_ELx_ISS2(esr) (((esr) & ESR_ELx_ISS2_MASK) >> ESR_ELx_ISS2_SHIFT) /* ISS field definitions shared by different classes */ #define ESR_ELx_WNR_SHIFT (6) @@ -140,6 +143,20 @@ #define ESR_ELx_CM_SHIFT (8) #define ESR_ELx_CM (UL(1) << ESR_ELx_CM_SHIFT) +/* ISS2 field definitions for Data Aborts */ +#define ESR_ELx_TnD_SHIFT (10) +#define ESR_ELx_TnD (UL(1) << ESR_ELx_TnD_SHIFT) +#define ESR_ELx_TagAccess_SHIFT (9) +#define ESR_ELx_TagAccess (UL(1) << ESR_ELx_TagAccess_SHIFT) +#define ESR_ELx_GCS_SHIFT (8) +#define ESR_ELx_GCS (UL(1) << ESR_ELx_GCS_SHIFT) +#define ESR_ELx_Overlay_SHIFT (6) +#define ESR_ELx_Overlay (UL(1) << ESR_ELx_Overlay_SHIFT) +#define ESR_ELx_DirtyBit_SHIFT (5) +#define ESR_ELx_DirtyBit (UL(1) << ESR_ELx_DirtyBit_SHIFT) +#define ESR_ELx_Xs_SHIFT (0) +#define ESR_ELx_Xs_MASK (GENMASK_ULL(4, 0)) + /* ISS field definitions for exceptions taken in to Hyp */ #define ESR_ELx_CV (UL(1) << 24) #define ESR_ELx_COND_SHIFT (20) @@ -356,6 +373,15 @@ #define ESR_ELx_SME_ISS_ZA_DISABLED 3 #define ESR_ELx_SME_ISS_ZT_DISABLED 4 +/* ISS field definitions for MOPS exceptions */ +#define ESR_ELx_MOPS_ISS_MEM_INST (UL(1) << 24) +#define ESR_ELx_MOPS_ISS_FROM_EPILOGUE (UL(1) << 18) +#define ESR_ELx_MOPS_ISS_WRONG_OPTION (UL(1) << 17) +#define ESR_ELx_MOPS_ISS_OPTION_A (UL(1) << 16) +#define ESR_ELx_MOPS_ISS_DESTREG(esr) (((esr) & (UL(0x1f) << 10)) >> 10) +#define ESR_ELx_MOPS_ISS_SRCREG(esr) (((esr) & (UL(0x1f) << 5)) >> 5) +#define ESR_ELx_MOPS_ISS_SIZEREG(esr) (((esr) & (UL(0x1f) << 0)) >> 0) + #ifndef __ASSEMBLY__ #include diff --git a/arch/arm64/include/asm/exception.h b/arch/arm64/include/asm/exception.h index e73af709cb7ad646b4cddd05619f5e45c8723957..ad688e157c9bed3663f74c427558f870b7159565 100644 --- a/arch/arm64/include/asm/exception.h +++ b/arch/arm64/include/asm/exception.h @@ -8,16 +8,11 @@ #define __ASM_EXCEPTION_H #include -#include #include #include -#ifdef CONFIG_FUNCTION_GRAPH_TRACER #define __exception_irq_entry __irq_entry -#else -#define __exception_irq_entry __kprobes -#endif static inline unsigned long disr_to_esr(u64 disr) { @@ -77,6 +72,7 @@ void do_el0_svc(struct pt_regs *regs); void do_el0_svc_compat(struct pt_regs *regs); void do_el0_fpac(struct pt_regs *regs, unsigned long esr); void do_el1_fpac(struct pt_regs *regs, unsigned long esr); +void do_el0_mops(struct pt_regs *regs, unsigned long esr); void do_serror(struct pt_regs *regs, unsigned long esr); void do_notify_resume(struct pt_regs *regs, unsigned long thread_flags); diff --git a/arch/arm64/include/asm/fpsimdmacros.h b/arch/arm64/include/asm/fpsimdmacros.h index cd03819a3b686be41883f5f63ca4d74c882e9a71..cdf6a35e399440e738d7f63932fe917784a2f416 100644 --- a/arch/arm64/include/asm/fpsimdmacros.h +++ b/arch/arm64/include/asm/fpsimdmacros.h @@ -316,12 +316,12 @@ _for n, 0, 15, _sve_str_p \n, \nxbase, \n - 16 cbz \save_ffr, 921f _sve_rdffr 0 - _sve_str_p 0, \nxbase - _sve_ldr_p 0, \nxbase, -16 b 922f 921: - str xzr, [x\nxbase] // Zero out FFR + _sve_pfalse 0 // Zero out FFR 922: + _sve_str_p 0, \nxbase + _sve_ldr_p 0, \nxbase, -16 mrs x\nxtmp, fpsr str w\nxtmp, [\xpfpsr] mrs x\nxtmp, fpcr diff --git a/arch/arm64/include/asm/ftrace.h b/arch/arm64/include/asm/ftrace.h index b87d70b693c6a44b568d8046fbb6e33edd137ae2..ab158196480c391f78adc97649c5b17b524d2abc 100644 --- a/arch/arm64/include/asm/ftrace.h +++ b/arch/arm64/include/asm/ftrace.h @@ -192,4 +192,30 @@ static inline bool arch_syscall_match_sym_name(const char *sym, } #endif /* ifndef __ASSEMBLY__ */ +#ifndef __ASSEMBLY__ +#ifdef CONFIG_FUNCTION_GRAPH_TRACER +struct fgraph_ret_regs { + /* x0 - x7 */ + unsigned long regs[8]; + + unsigned long fp; + unsigned long __unused; +}; + +static inline unsigned long fgraph_ret_regs_return_value(struct fgraph_ret_regs *ret_regs) +{ + return ret_regs->regs[0]; +} + +static inline unsigned long fgraph_ret_regs_frame_pointer(struct fgraph_ret_regs *ret_regs) +{ + return ret_regs->fp; +} + +void prepare_ftrace_return(unsigned long self_addr, unsigned long *parent, + unsigned long frame_pointer); + +#endif /* ifdef CONFIG_FUNCTION_GRAPH_TRACER */ +#endif + #endif /* __ASM_FTRACE_H */ diff --git a/arch/arm64/include/asm/hw_breakpoint.h b/arch/arm64/include/asm/hw_breakpoint.h index fa4c6ff3aa9bde5e117a37f123c8268a605b186f..84055329cd8b1329fa4ddcdc7ab1f079834945ca 100644 --- a/arch/arm64/include/asm/hw_breakpoint.h +++ b/arch/arm64/include/asm/hw_breakpoint.h @@ -154,4 +154,12 @@ static inline int get_num_wrps(void) ID_AA64DFR0_EL1_WRPs_SHIFT); } +#ifdef CONFIG_CPU_PM +extern void cpu_suspend_set_dbg_restorer(int (*hw_bp_restore)(unsigned int)); +#else +static inline void cpu_suspend_set_dbg_restorer(int (*hw_bp_restore)(unsigned int)) +{ +} +#endif + #endif /* __ASM_BREAKPOINT_H */ diff --git a/arch/arm64/include/asm/hwcap.h b/arch/arm64/include/asm/hwcap.h index 5d45f19fda7f5f39fbcbb28628778ab5987d8374..692b1ec663b279cb261f367a32b1028c33632cd4 100644 --- a/arch/arm64/include/asm/hwcap.h +++ b/arch/arm64/include/asm/hwcap.h @@ -137,6 +137,7 @@ #define KERNEL_HWCAP_SME_BI32I32 __khwcap2_feature(SME_BI32I32) #define KERNEL_HWCAP_SME_B16B16 __khwcap2_feature(SME_B16B16) #define KERNEL_HWCAP_SME_F16F16 __khwcap2_feature(SME_F16F16) +#define KERNEL_HWCAP_MOPS __khwcap2_feature(MOPS) /* * This yields a mask that user programs can use to figure out what diff --git a/arch/arm64/include/asm/image.h b/arch/arm64/include/asm/image.h index c2b13213c7207c02f47474deb0e58bf49d31dc06..c09cf942dc92ead361b4371e5ab99f452ade050e 100644 --- a/arch/arm64/include/asm/image.h +++ b/arch/arm64/include/asm/image.h @@ -27,7 +27,7 @@ /* * struct arm64_image_header - arm64 kernel image header - * See Documentation/arm64/booting.rst for details + * See Documentation/arch/arm64/booting.rst for details * * @code0: Executable code, or * @mz_header alternatively used for part of MZ header diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h index 877495a0fd0c11142f3ccc6fc3ee8665681d7fd4..51d92abf945edd93b6356762f9fc5344e07500ff 100644 --- a/arch/arm64/include/asm/io.h +++ b/arch/arm64/include/asm/io.h @@ -22,13 +22,13 @@ * Generic IO read/write. These perform native-endian accesses. */ #define __raw_writeb __raw_writeb -static inline void __raw_writeb(u8 val, volatile void __iomem *addr) +static __always_inline void __raw_writeb(u8 val, volatile void __iomem *addr) { asm volatile("strb %w0, [%1]" : : "rZ" (val), "r" (addr)); } #define __raw_writew __raw_writew -static inline void __raw_writew(u16 val, volatile void __iomem *addr) +static __always_inline void __raw_writew(u16 val, volatile void __iomem *addr) { asm volatile("strh %w0, [%1]" : : "rZ" (val), "r" (addr)); } @@ -40,13 +40,13 @@ static __always_inline void __raw_writel(u32 val, volatile void __iomem *addr) } #define __raw_writeq __raw_writeq -static inline void __raw_writeq(u64 val, volatile void __iomem *addr) +static __always_inline void __raw_writeq(u64 val, volatile void __iomem *addr) { asm volatile("str %x0, [%1]" : : "rZ" (val), "r" (addr)); } #define __raw_readb __raw_readb -static inline u8 __raw_readb(const volatile void __iomem *addr) +static __always_inline u8 __raw_readb(const volatile void __iomem *addr) { u8 val; asm volatile(ALTERNATIVE("ldrb %w0, [%1]", @@ -57,7 +57,7 @@ static inline u8 __raw_readb(const volatile void __iomem *addr) } #define __raw_readw __raw_readw -static inline u16 __raw_readw(const volatile void __iomem *addr) +static __always_inline u16 __raw_readw(const volatile void __iomem *addr) { u16 val; @@ -80,7 +80,7 @@ static __always_inline u32 __raw_readl(const volatile void __iomem *addr) } #define __raw_readq __raw_readq -static inline u64 __raw_readq(const volatile void __iomem *addr) +static __always_inline u64 __raw_readq(const volatile void __iomem *addr) { u64 val; asm volatile(ALTERNATIVE("ldr %0, [%1]", diff --git a/arch/arm64/include/asm/irqflags.h b/arch/arm64/include/asm/irqflags.h index e0f5f6b73edd75bf92b71e5eef24509f27eec77b..1f31ec146d161eb8e0fcac132d0293b0c8303783 100644 --- a/arch/arm64/include/asm/irqflags.h +++ b/arch/arm64/include/asm/irqflags.h @@ -24,7 +24,7 @@ static __always_inline bool __irqflags_uses_pmr(void) { return IS_ENABLED(CONFIG_ARM64_PSEUDO_NMI) && - alternative_has_feature_unlikely(ARM64_HAS_GIC_PRIO_MASKING); + alternative_has_cap_unlikely(ARM64_HAS_GIC_PRIO_MASKING); } static __always_inline void __daif_local_irq_enable(void) diff --git a/arch/arm64/include/asm/kernel-pgtable.h b/arch/arm64/include/asm/kernel-pgtable.h index 186dd7f85b146d7e47390d8b8d9dad2a1438665a..577773870b66ffd2df49933db93c9e9846ed1bb5 100644 --- a/arch/arm64/include/asm/kernel-pgtable.h +++ b/arch/arm64/include/asm/kernel-pgtable.h @@ -107,14 +107,14 @@ /* * Initial memory map attributes. */ -#define SWAPPER_PTE_FLAGS (PTE_TYPE_PAGE | PTE_AF | PTE_SHARED) -#define SWAPPER_PMD_FLAGS (PMD_TYPE_SECT | PMD_SECT_AF | PMD_SECT_S) +#define SWAPPER_PTE_FLAGS (PTE_TYPE_PAGE | PTE_AF | PTE_SHARED | PTE_UXN) +#define SWAPPER_PMD_FLAGS (PMD_TYPE_SECT | PMD_SECT_AF | PMD_SECT_S | PTE_UXN) #ifdef CONFIG_ARM64_4K_PAGES -#define SWAPPER_RW_MMUFLAGS (PMD_ATTRINDX(MT_NORMAL) | SWAPPER_PMD_FLAGS) +#define SWAPPER_RW_MMUFLAGS (PMD_ATTRINDX(MT_NORMAL) | SWAPPER_PMD_FLAGS | PTE_WRITE) #define SWAPPER_RX_MMUFLAGS (SWAPPER_RW_MMUFLAGS | PMD_SECT_RDONLY) #else -#define SWAPPER_RW_MMUFLAGS (PTE_ATTRINDX(MT_NORMAL) | SWAPPER_PTE_FLAGS) +#define SWAPPER_RW_MMUFLAGS (PTE_ATTRINDX(MT_NORMAL) | SWAPPER_PTE_FLAGS | PTE_WRITE) #define SWAPPER_RX_MMUFLAGS (SWAPPER_RW_MMUFLAGS | PTE_RDONLY) #endif diff --git a/arch/arm64/include/asm/kvm_arm.h b/arch/arm64/include/asm/kvm_arm.h index baef29fcbeeedc9a978a8ee2aa2346ad7382f314..58e5eb27da68d67418ab54c177ac033a264a4aad 100644 --- a/arch/arm64/include/asm/kvm_arm.h +++ b/arch/arm64/include/asm/kvm_arm.h @@ -9,6 +9,7 @@ #include #include +#include #include /* Hyp Configuration Register (HCR) bits */ @@ -18,6 +19,7 @@ #define HCR_ATA_SHIFT 56 #define HCR_ATA (UL(1) << HCR_ATA_SHIFT) #define HCR_AMVOFFEN (UL(1) << 51) +#define HCR_TID4 (UL(1) << 49) #define HCR_FIEN (UL(1) << 47) #define HCR_FWB (UL(1) << 46) #define HCR_API (UL(1) << 41) @@ -86,12 +88,15 @@ #define HCR_GUEST_FLAGS (HCR_TSC | HCR_TSW | HCR_TWE | HCR_TWI | HCR_VM | \ HCR_BSU_IS | HCR_FB | HCR_TACR | \ HCR_AMO | HCR_SWIO | HCR_TIDCP | HCR_RW | HCR_TLOR | \ - HCR_FMO | HCR_IMO | HCR_PTW | HCR_TID3 | HCR_TID2) + HCR_FMO | HCR_IMO | HCR_PTW | HCR_TID3) #define HCR_VIRT_EXCP_MASK (HCR_VSE | HCR_VI | HCR_VF) #define HCR_HOST_NVHE_FLAGS (HCR_RW | HCR_API | HCR_APK | HCR_ATA) #define HCR_HOST_NVHE_PROTECTED_FLAGS (HCR_HOST_NVHE_FLAGS | HCR_TSC) #define HCR_HOST_VHE_FLAGS (HCR_RW | HCR_TGE | HCR_E2H) +#define HCRX_GUEST_FLAGS (HCRX_EL2_SMPME | HCRX_EL2_TCR2En) +#define HCRX_HOST_FLAGS (HCRX_EL2_MSCEn | HCRX_EL2_TCR2En) + /* TCR_EL2 Registers bits */ #define TCR_EL2_RES1 ((1U << 31) | (1 << 23)) #define TCR_EL2_TBI (1 << 20) @@ -285,7 +290,6 @@ #define CPTR_EL2_TFP (1 << CPTR_EL2_TFP_SHIFT) #define CPTR_EL2_TZ (1 << 8) #define CPTR_NVHE_EL2_RES1 0x000032ff /* known RES1 bits in CPTR_EL2 (nVHE) */ -#define CPTR_EL2_DEFAULT CPTR_NVHE_EL2_RES1 #define CPTR_NVHE_EL2_RES0 (GENMASK(63, 32) | \ GENMASK(29, 21) | \ GENMASK(19, 14) | \ @@ -347,8 +351,7 @@ ECN(SOFTSTP_CUR), ECN(WATCHPT_LOW), ECN(WATCHPT_CUR), \ ECN(BKPT32), ECN(VECTOR32), ECN(BRK64), ECN(ERET) -#define CPACR_EL1_DEFAULT (CPACR_EL1_FPEN_EL0EN | CPACR_EL1_FPEN_EL1EN |\ - CPACR_EL1_ZEN_EL1EN) +#define CPACR_EL1_TTA (1 << 28) #define kvm_mode_names \ { PSR_MODE_EL0t, "EL0t" }, \ diff --git a/arch/arm64/include/asm/kvm_asm.h b/arch/arm64/include/asm/kvm_asm.h index 43c3bc0f9544d9a3f477427315d07e6d17fafb94..7d170aaa2db4195b5405a46caf6bcbcb22f0fe38 100644 --- a/arch/arm64/include/asm/kvm_asm.h +++ b/arch/arm64/include/asm/kvm_asm.h @@ -68,6 +68,7 @@ enum __kvm_host_smccc_func { __KVM_HOST_SMCCC_FUNC___kvm_vcpu_run, __KVM_HOST_SMCCC_FUNC___kvm_flush_vm_context, __KVM_HOST_SMCCC_FUNC___kvm_tlb_flush_vmid_ipa, + __KVM_HOST_SMCCC_FUNC___kvm_tlb_flush_vmid_ipa_nsh, __KVM_HOST_SMCCC_FUNC___kvm_tlb_flush_vmid, __KVM_HOST_SMCCC_FUNC___kvm_flush_cpu_context, __KVM_HOST_SMCCC_FUNC___kvm_timer_set_cntvoff, @@ -225,6 +226,9 @@ extern void __kvm_flush_vm_context(void); extern void __kvm_flush_cpu_context(struct kvm_s2_mmu *mmu); extern void __kvm_tlb_flush_vmid_ipa(struct kvm_s2_mmu *mmu, phys_addr_t ipa, int level); +extern void __kvm_tlb_flush_vmid_ipa_nsh(struct kvm_s2_mmu *mmu, + phys_addr_t ipa, + int level); extern void __kvm_tlb_flush_vmid(struct kvm_s2_mmu *mmu); extern void __kvm_timer_set_cntvoff(u64 cntvoff); @@ -267,6 +271,24 @@ extern u64 __kvm_get_mdcr_el2(void); __kvm_at_err; \ } ) +void __noreturn hyp_panic(void); +asmlinkage void kvm_unexpected_el2_exception(void); +asmlinkage void __noreturn hyp_panic(void); +asmlinkage void __noreturn hyp_panic_bad_stack(void); +asmlinkage void kvm_unexpected_el2_exception(void); +struct kvm_cpu_context; +void handle_trap(struct kvm_cpu_context *host_ctxt); +asmlinkage void __noreturn kvm_host_psci_cpu_entry(bool is_cpu_on); +void __noreturn __pkvm_init_finalise(void); +void kvm_nvhe_prepare_backtrace(unsigned long fp, unsigned long pc); +void kvm_patch_vector_branch(struct alt_instr *alt, + __le32 *origptr, __le32 *updptr, int nr_inst); +void kvm_get_kimage_voffset(struct alt_instr *alt, + __le32 *origptr, __le32 *updptr, int nr_inst); +void kvm_compute_final_ctr_el0(struct alt_instr *alt, + __le32 *origptr, __le32 *updptr, int nr_inst); +void __noreturn __cold nvhe_hyp_panic_handler(u64 esr, u64 spsr, u64 elr_virt, + u64 elr_phys, u64 par, uintptr_t vcpu, u64 far, u64 hpfar); #else /* __ASSEMBLY__ */ diff --git a/arch/arm64/include/asm/kvm_emulate.h b/arch/arm64/include/asm/kvm_emulate.h index b31b32ecbe2d12697dd8c686a6e72de3ee0da79f..efc0b45d79c36083ba1b4ca0ace283cee983ec4c 100644 --- a/arch/arm64/include/asm/kvm_emulate.h +++ b/arch/arm64/include/asm/kvm_emulate.h @@ -62,19 +62,14 @@ static __always_inline bool vcpu_el1_is_32bit(struct kvm_vcpu *vcpu) #else static __always_inline bool vcpu_el1_is_32bit(struct kvm_vcpu *vcpu) { - struct kvm *kvm = vcpu->kvm; - - WARN_ON_ONCE(!test_bit(KVM_ARCH_FLAG_REG_WIDTH_CONFIGURED, - &kvm->arch.flags)); - - return test_bit(KVM_ARCH_FLAG_EL1_32BIT, &kvm->arch.flags); + return test_bit(KVM_ARM_VCPU_EL1_32BIT, vcpu->arch.features); } #endif static inline void vcpu_reset_hcr(struct kvm_vcpu *vcpu) { vcpu->arch.hcr_el2 = HCR_GUEST_FLAGS; - if (is_kernel_in_hyp_mode()) + if (has_vhe() || has_hvhe()) vcpu->arch.hcr_el2 |= HCR_E2H; if (cpus_have_const_cap(ARM64_HAS_RAS_EXTN)) { /* route synchronous external abort exceptions to EL2 */ @@ -95,6 +90,12 @@ static inline void vcpu_reset_hcr(struct kvm_vcpu *vcpu) vcpu->arch.hcr_el2 |= HCR_TVM; } + if (cpus_have_final_cap(ARM64_HAS_EVT) && + !cpus_have_final_cap(ARM64_MISMATCHED_CACHE_TYPE)) + vcpu->arch.hcr_el2 |= HCR_TID4; + else + vcpu->arch.hcr_el2 |= HCR_TID2; + if (vcpu_el1_is_32bit(vcpu)) vcpu->arch.hcr_el2 &= ~HCR_RW; @@ -570,4 +571,35 @@ static inline bool vcpu_has_feature(struct kvm_vcpu *vcpu, int feature) return test_bit(feature, vcpu->arch.features); } +static __always_inline u64 kvm_get_reset_cptr_el2(struct kvm_vcpu *vcpu) +{ + u64 val; + + if (has_vhe()) { + val = (CPACR_EL1_FPEN_EL0EN | CPACR_EL1_FPEN_EL1EN | + CPACR_EL1_ZEN_EL1EN); + } else if (has_hvhe()) { + val = (CPACR_EL1_FPEN_EL0EN | CPACR_EL1_FPEN_EL1EN); + } else { + val = CPTR_NVHE_EL2_RES1; + + if (vcpu_has_sve(vcpu) && + (vcpu->arch.fp_state == FP_STATE_GUEST_OWNED)) + val |= CPTR_EL2_TZ; + if (cpus_have_final_cap(ARM64_SME)) + val &= ~CPTR_EL2_TSM; + } + + return val; +} + +static __always_inline void kvm_reset_cptr_el2(struct kvm_vcpu *vcpu) +{ + u64 val = kvm_get_reset_cptr_el2(vcpu); + + if (has_vhe() || has_hvhe()) + write_sysreg(val, cpacr_el1); + else + write_sysreg(val, cptr_el2); +} #endif /* __ARM64_KVM_EMULATE_H__ */ diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index 7e7e19ef6993ede45aea71c6f19b624731290fbe..8b6096753740ccce477ae60aa195bd8ff088da20 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -39,6 +39,7 @@ #define KVM_MAX_VCPUS VGIC_V3_MAX_CPUS #define KVM_VCPU_MAX_FEATURES 7 +#define KVM_VCPU_VALID_FEATURES (BIT(KVM_VCPU_MAX_FEATURES) - 1) #define KVM_REQ_SLEEP \ KVM_ARCH_REQ_FLAGS(0, KVM_REQUEST_WAIT | KVM_REQUEST_NO_WAKEUP) @@ -159,6 +160,21 @@ struct kvm_s2_mmu { /* The last vcpu id that ran on each physical CPU */ int __percpu *last_vcpu_ran; +#define KVM_ARM_EAGER_SPLIT_CHUNK_SIZE_DEFAULT 0 + /* + * Memory cache used to split + * KVM_CAP_ARM_EAGER_SPLIT_CHUNK_SIZE worth of huge pages. It + * is used to allocate stage2 page tables while splitting huge + * pages. The choice of KVM_CAP_ARM_EAGER_SPLIT_CHUNK_SIZE + * influences both the capacity of the split page cache, and + * how often KVM reschedules. Be wary of raising CHUNK_SIZE + * too high. + * + * Protected by kvm->slots_lock. + */ + struct kvm_mmu_memory_cache split_page_cache; + uint64_t split_page_chunk_size; + struct kvm_arch *arch; }; @@ -214,25 +230,23 @@ struct kvm_arch { #define KVM_ARCH_FLAG_MTE_ENABLED 1 /* At least one vCPU has ran in the VM */ #define KVM_ARCH_FLAG_HAS_RAN_ONCE 2 - /* - * The following two bits are used to indicate the guest's EL1 - * register width configuration. A value of KVM_ARCH_FLAG_EL1_32BIT - * bit is valid only when KVM_ARCH_FLAG_REG_WIDTH_CONFIGURED is set. - * Otherwise, the guest's EL1 register width has not yet been - * determined yet. - */ -#define KVM_ARCH_FLAG_REG_WIDTH_CONFIGURED 3 -#define KVM_ARCH_FLAG_EL1_32BIT 4 + /* The vCPU feature set for the VM is configured */ +#define KVM_ARCH_FLAG_VCPU_FEATURES_CONFIGURED 3 /* PSCI SYSTEM_SUSPEND enabled for the guest */ -#define KVM_ARCH_FLAG_SYSTEM_SUSPEND_ENABLED 5 +#define KVM_ARCH_FLAG_SYSTEM_SUSPEND_ENABLED 4 /* VM counter offset */ -#define KVM_ARCH_FLAG_VM_COUNTER_OFFSET 6 +#define KVM_ARCH_FLAG_VM_COUNTER_OFFSET 5 /* Timer PPIs made immutable */ -#define KVM_ARCH_FLAG_TIMER_PPIS_IMMUTABLE 7 +#define KVM_ARCH_FLAG_TIMER_PPIS_IMMUTABLE 6 /* SMCCC filter initialized for the VM */ -#define KVM_ARCH_FLAG_SMCCC_FILTER_CONFIGURED 8 +#define KVM_ARCH_FLAG_SMCCC_FILTER_CONFIGURED 7 + /* Initial ID reg values loaded */ +#define KVM_ARCH_FLAG_ID_REGS_INITIALIZED 8 unsigned long flags; + /* VM-wide vCPU feature set */ + DECLARE_BITMAP(vcpu_features, KVM_VCPU_MAX_FEATURES); + /* * VM-wide PMU filter, implemented as a bitmap and big enough for * up to 2^10 events (ARMv8.0) or 2^16 events (ARMv8.1+). @@ -242,17 +256,23 @@ struct kvm_arch { cpumask_var_t supported_cpus; - u8 pfr0_csv2; - u8 pfr0_csv3; - struct { - u8 imp:4; - u8 unimp:4; - } dfr0_pmuver; - /* Hypercall features firmware registers' descriptor */ struct kvm_smccc_features smccc_feat; struct maple_tree smccc_filter; + /* + * Emulated CPU ID registers per VM + * (Op0, Op1, CRn, CRm, Op2) of the ID registers to be saved in it + * is (3, 0, 0, crm, op2), where 1<=crm<8, 0<=op2<8. + * + * These emulated idregs are VM-wide, but accessed from the context of a vCPU. + * Atomic access to multiple idregs are guarded by kvm_arch.config_lock. + */ +#define IDREG_IDX(id) (((sys_reg_CRm(id) - 1) << 3) | sys_reg_Op2(id)) +#define IDREG(kvm, id) ((kvm)->arch.id_regs[IDREG_IDX(id)]) +#define KVM_ARM_ID_REG_NUM (IDREG_IDX(sys_reg(3, 0, 0, 7, 7)) + 1) + u64 id_regs[KVM_ARM_ID_REG_NUM]; + /* * For an untrusted host VM, 'pkvm.handle' is used to lookup * the associated pKVM instance in the hypervisor. @@ -279,6 +299,7 @@ enum vcpu_sysreg { TTBR0_EL1, /* Translation Table Base Register 0 */ TTBR1_EL1, /* Translation Table Base Register 1 */ TCR_EL1, /* Translation Control Register */ + TCR2_EL1, /* Extended Translation Control Register */ ESR_EL1, /* Exception Syndrome Register */ AFSR0_EL1, /* Auxiliary Fault Status Register 0 */ AFSR1_EL1, /* Auxiliary Fault Status Register 1 */ @@ -339,6 +360,10 @@ enum vcpu_sysreg { TFSR_EL1, /* Tag Fault Status Register (EL1) */ TFSRE0_EL1, /* Tag Fault Status Register (EL0) */ + /* Permission Indirection Extension registers */ + PIR_EL1, /* Permission Indirection Register 1 (EL1) */ + PIRE0_EL1, /* Permission Indirection Register 0 (EL1) */ + /* 32bit specific registers. */ DACR32_EL2, /* Domain Access Control Register */ IFSR32_EL2, /* Instruction Fault Status Register */ @@ -405,6 +430,7 @@ struct kvm_host_data { struct kvm_host_psci_config { /* PSCI version used by host. */ u32 version; + u32 smccc_version; /* Function IDs used by host if version is v0.1. */ struct psci_0_1_function_ids function_ids_0_1; @@ -699,6 +725,8 @@ struct kvm_vcpu_arch { #define SYSREGS_ON_CPU __vcpu_single_flag(sflags, BIT(4)) /* Software step state is Active-pending */ #define DBG_SS_ACTIVE_PENDING __vcpu_single_flag(sflags, BIT(5)) +/* PMUSERENR for the guest EL0 is on physical CPU */ +#define PMUSERENR_ON_CPU __vcpu_single_flag(sflags, BIT(6)) /* Pointer to the vcpu's SVE FFR for sve_{save,load}_state() */ @@ -1031,7 +1059,7 @@ void kvm_arm_clear_debug(struct kvm_vcpu *vcpu); void kvm_arm_reset_debug_ptr(struct kvm_vcpu *vcpu); #define kvm_vcpu_os_lock_enabled(vcpu) \ - (!!(__vcpu_sys_reg(vcpu, OSLSR_EL1) & SYS_OSLSR_OSLK)) + (!!(__vcpu_sys_reg(vcpu, OSLSR_EL1) & OSLSR_EL1_OSLK)) int kvm_arm_vcpu_arch_set_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr); @@ -1065,9 +1093,14 @@ void kvm_arch_vcpu_put_debug_state_flags(struct kvm_vcpu *vcpu); #ifdef CONFIG_KVM void kvm_set_pmu_events(u32 set, struct perf_event_attr *attr); void kvm_clr_pmu_events(u32 clr); +bool kvm_set_pmuserenr(u64 val); #else static inline void kvm_set_pmu_events(u32 set, struct perf_event_attr *attr) {} static inline void kvm_clr_pmu_events(u32 clr) {} +static inline bool kvm_set_pmuserenr(u64 val) +{ + return false; +} #endif void kvm_vcpu_load_sysregs_vhe(struct kvm_vcpu *vcpu); diff --git a/arch/arm64/include/asm/kvm_hyp.h b/arch/arm64/include/asm/kvm_hyp.h index bdd9cf546d95585814bed3151a021d553aad8320..b7238c72a04cfaee4cdd4510e408e5f0a6c4df6f 100644 --- a/arch/arm64/include/asm/kvm_hyp.h +++ b/arch/arm64/include/asm/kvm_hyp.h @@ -16,12 +16,35 @@ DECLARE_PER_CPU(struct kvm_cpu_context, kvm_hyp_ctxt); DECLARE_PER_CPU(unsigned long, kvm_hyp_vector); DECLARE_PER_CPU(struct kvm_nvhe_init_params, kvm_init_params); +/* + * Unified accessors for registers that have a different encoding + * between VHE and non-VHE. They must be specified without their "ELx" + * encoding, but with the SYS_ prefix, as defined in asm/sysreg.h. + */ + +#if defined(__KVM_VHE_HYPERVISOR__) + +#define read_sysreg_el0(r) read_sysreg_s(r##_EL02) +#define write_sysreg_el0(v,r) write_sysreg_s(v, r##_EL02) +#define read_sysreg_el1(r) read_sysreg_s(r##_EL12) +#define write_sysreg_el1(v,r) write_sysreg_s(v, r##_EL12) +#define read_sysreg_el2(r) read_sysreg_s(r##_EL1) +#define write_sysreg_el2(v,r) write_sysreg_s(v, r##_EL1) + +#else // !__KVM_VHE_HYPERVISOR__ + +#if defined(__KVM_NVHE_HYPERVISOR__) +#define VHE_ALT_KEY ARM64_KVM_HVHE +#else +#define VHE_ALT_KEY ARM64_HAS_VIRT_HOST_EXTN +#endif + #define read_sysreg_elx(r,nvh,vh) \ ({ \ u64 reg; \ - asm volatile(ALTERNATIVE(__mrs_s("%0", r##nvh), \ + asm volatile(ALTERNATIVE(__mrs_s("%0", r##nvh), \ __mrs_s("%0", r##vh), \ - ARM64_HAS_VIRT_HOST_EXTN) \ + VHE_ALT_KEY) \ : "=r" (reg)); \ reg; \ }) @@ -31,16 +54,10 @@ DECLARE_PER_CPU(struct kvm_nvhe_init_params, kvm_init_params); u64 __val = (u64)(v); \ asm volatile(ALTERNATIVE(__msr_s(r##nvh, "%x0"), \ __msr_s(r##vh, "%x0"), \ - ARM64_HAS_VIRT_HOST_EXTN) \ + VHE_ALT_KEY) \ : : "rZ" (__val)); \ } while (0) -/* - * Unified accessors for registers that have a different encoding - * between VHE and non-VHE. They must be specified without their "ELx" - * encoding, but with the SYS_ prefix, as defined in asm/sysreg.h. - */ - #define read_sysreg_el0(r) read_sysreg_elx(r, _EL0, _EL02) #define write_sysreg_el0(v,r) write_sysreg_elx(v, r, _EL0, _EL02) #define read_sysreg_el1(r) read_sysreg_elx(r, _EL1, _EL12) @@ -48,6 +65,8 @@ DECLARE_PER_CPU(struct kvm_nvhe_init_params, kvm_init_params); #define read_sysreg_el2(r) read_sysreg_elx(r, _EL2, _EL1) #define write_sysreg_el2(v,r) write_sysreg_elx(v, r, _EL2, _EL1) +#endif // __KVM_VHE_HYPERVISOR__ + /* * Without an __arch_swab32(), we fall back to ___constant_swab32(), but the * static inline can allow the compiler to out-of-line this. KVM always wants diff --git a/arch/arm64/include/asm/kvm_mmu.h b/arch/arm64/include/asm/kvm_mmu.h index 27e63c111f78abc375a5dfbbf22cdfd565fadfe4..0e1e1ab17b4d6e3e858684ff1b602d7b3516ae34 100644 --- a/arch/arm64/include/asm/kvm_mmu.h +++ b/arch/arm64/include/asm/kvm_mmu.h @@ -172,6 +172,7 @@ void __init free_hyp_pgds(void); void stage2_unmap_vm(struct kvm *kvm); int kvm_init_stage2_mmu(struct kvm *kvm, struct kvm_s2_mmu *mmu, unsigned long type); +void kvm_uninit_stage2_mmu(struct kvm *kvm); void kvm_free_stage2_pgd(struct kvm_s2_mmu *mmu); int kvm_phys_addr_ioremap(struct kvm *kvm, phys_addr_t guest_ipa, phys_addr_t pa, unsigned long size, bool writable); @@ -227,7 +228,8 @@ static inline void __invalidate_icache_guest_page(void *va, size_t size) if (icache_is_aliasing()) { /* any kind of VIPT cache */ icache_inval_all_pou(); - } else if (is_kernel_in_hyp_mode() || !icache_is_vpipt()) { + } else if (read_sysreg(CurrentEL) != CurrentEL_EL1 || + !icache_is_vpipt()) { /* PIPT or VPIPT at EL2 (see comment in __kvm_tlb_flush_vmid_ipa) */ icache_inval_pou((unsigned long)va, (unsigned long)va + size); } diff --git a/arch/arm64/include/asm/kvm_pgtable.h b/arch/arm64/include/asm/kvm_pgtable.h index 93bd0975b15f5545d5a408fd177ce35e780204ad..8294a9a7e566d4cb6af6840c1c9f0739175eef73 100644 --- a/arch/arm64/include/asm/kvm_pgtable.h +++ b/arch/arm64/include/asm/kvm_pgtable.h @@ -92,6 +92,24 @@ static inline bool kvm_level_supports_block_mapping(u32 level) return level >= KVM_PGTABLE_MIN_BLOCK_LEVEL; } +static inline u32 kvm_supported_block_sizes(void) +{ + u32 level = KVM_PGTABLE_MIN_BLOCK_LEVEL; + u32 r = 0; + + for (; level < KVM_PGTABLE_MAX_LEVELS; level++) + r |= BIT(kvm_granule_shift(level)); + + return r; +} + +static inline bool kvm_is_block_size_supported(u64 size) +{ + bool is_power_of_two = IS_ALIGNED(size, size); + + return is_power_of_two && (size & kvm_supported_block_sizes()); +} + /** * struct kvm_pgtable_mm_ops - Memory management callbacks. * @zalloc_page: Allocate a single zeroed memory page. @@ -104,7 +122,7 @@ static inline bool kvm_level_supports_block_mapping(u32 level) * allocation is physically contiguous. * @free_pages_exact: Free an exact number of memory pages previously * allocated by zalloc_pages_exact. - * @free_removed_table: Free a removed paging structure by unlinking and + * @free_unlinked_table: Free an unlinked paging structure by unlinking and * dropping references. * @get_page: Increment the refcount on a page. * @put_page: Decrement the refcount on a page. When the @@ -124,7 +142,7 @@ struct kvm_pgtable_mm_ops { void* (*zalloc_page)(void *arg); void* (*zalloc_pages_exact)(size_t size); void (*free_pages_exact)(void *addr, size_t size); - void (*free_removed_table)(void *addr, u32 level); + void (*free_unlinked_table)(void *addr, u32 level); void (*get_page)(void *addr); void (*put_page)(void *addr); int (*page_count)(void *addr); @@ -195,6 +213,12 @@ typedef bool (*kvm_pgtable_force_pte_cb_t)(u64 addr, u64 end, * with other software walkers. * @KVM_PGTABLE_WALK_HANDLE_FAULT: Indicates the page-table walk was * invoked from a fault handler. + * @KVM_PGTABLE_WALK_SKIP_BBM_TLBI: Visit and update table entries + * without Break-before-make's + * TLB invalidation. + * @KVM_PGTABLE_WALK_SKIP_CMO: Visit and update table entries + * without Cache maintenance + * operations required. */ enum kvm_pgtable_walk_flags { KVM_PGTABLE_WALK_LEAF = BIT(0), @@ -202,6 +226,8 @@ enum kvm_pgtable_walk_flags { KVM_PGTABLE_WALK_TABLE_POST = BIT(2), KVM_PGTABLE_WALK_SHARED = BIT(3), KVM_PGTABLE_WALK_HANDLE_FAULT = BIT(4), + KVM_PGTABLE_WALK_SKIP_BBM_TLBI = BIT(5), + KVM_PGTABLE_WALK_SKIP_CMO = BIT(6), }; struct kvm_pgtable_visit_ctx { @@ -441,7 +467,7 @@ int __kvm_pgtable_stage2_init(struct kvm_pgtable *pgt, struct kvm_s2_mmu *mmu, void kvm_pgtable_stage2_destroy(struct kvm_pgtable *pgt); /** - * kvm_pgtable_stage2_free_removed() - Free a removed stage-2 paging structure. + * kvm_pgtable_stage2_free_unlinked() - Free an unlinked stage-2 paging structure. * @mm_ops: Memory management callbacks. * @pgtable: Unlinked stage-2 paging structure to be freed. * @level: Level of the stage-2 paging structure to be freed. @@ -449,7 +475,33 @@ void kvm_pgtable_stage2_destroy(struct kvm_pgtable *pgt); * The page-table is assumed to be unreachable by any hardware walkers prior to * freeing and therefore no TLB invalidation is performed. */ -void kvm_pgtable_stage2_free_removed(struct kvm_pgtable_mm_ops *mm_ops, void *pgtable, u32 level); +void kvm_pgtable_stage2_free_unlinked(struct kvm_pgtable_mm_ops *mm_ops, void *pgtable, u32 level); + +/** + * kvm_pgtable_stage2_create_unlinked() - Create an unlinked stage-2 paging structure. + * @pgt: Page-table structure initialised by kvm_pgtable_stage2_init*(). + * @phys: Physical address of the memory to map. + * @level: Starting level of the stage-2 paging structure to be created. + * @prot: Permissions and attributes for the mapping. + * @mc: Cache of pre-allocated and zeroed memory from which to allocate + * page-table pages. + * @force_pte: Force mappings to PAGE_SIZE granularity. + * + * Returns an unlinked page-table tree. This new page-table tree is + * not reachable (i.e., it is unlinked) from the root pgd and it's + * therefore unreachableby the hardware page-table walker. No TLB + * invalidation or CMOs are performed. + * + * If device attributes are not explicitly requested in @prot, then the + * mapping will be normal, cacheable. + * + * Return: The fully populated (unlinked) stage-2 paging structure, or + * an ERR_PTR(error) on failure. + */ +kvm_pte_t *kvm_pgtable_stage2_create_unlinked(struct kvm_pgtable *pgt, + u64 phys, u32 level, + enum kvm_pgtable_prot prot, + void *mc, bool force_pte); /** * kvm_pgtable_stage2_map() - Install a mapping in a guest stage-2 page-table. @@ -620,6 +672,25 @@ bool kvm_pgtable_stage2_is_young(struct kvm_pgtable *pgt, u64 addr); */ int kvm_pgtable_stage2_flush(struct kvm_pgtable *pgt, u64 addr, u64 size); +/** + * kvm_pgtable_stage2_split() - Split a range of huge pages into leaf PTEs pointing + * to PAGE_SIZE guest pages. + * @pgt: Page-table structure initialised by kvm_pgtable_stage2_init(). + * @addr: Intermediate physical address from which to split. + * @size: Size of the range. + * @mc: Cache of pre-allocated and zeroed memory from which to allocate + * page-table pages. + * + * The function tries to split any level 1 or 2 entry that overlaps + * with the input range (given by @addr and @size). + * + * Return: 0 on success, negative error code on failure. Note that + * kvm_pgtable_stage2_split() is best effort: it tries to break as many + * blocks in the input range as allowed by @mc_capacity. + */ +int kvm_pgtable_stage2_split(struct kvm_pgtable *pgt, u64 addr, u64 size, + struct kvm_mmu_memory_cache *mc); + /** * kvm_pgtable_walk() - Walk a page-table. * @pgt: Page-table structure initialised by kvm_pgtable_*_init(). diff --git a/arch/arm64/include/asm/kvm_pkvm.h b/arch/arm64/include/asm/kvm_pkvm.h index 01129b0d4c689e46c149b6d91dd5b3bce99f64d6..e46250a0201721656ffeb81f231bf91bdcb3d239 100644 --- a/arch/arm64/include/asm/kvm_pkvm.h +++ b/arch/arm64/include/asm/kvm_pkvm.h @@ -6,7 +6,9 @@ #ifndef __ARM64_KVM_PKVM_H__ #define __ARM64_KVM_PKVM_H__ +#include #include +#include #include /* Maximum number of VMs that can co-exist under pKVM. */ @@ -106,4 +108,23 @@ static inline unsigned long host_s2_pgtable_pages(void) return res; } +#define KVM_FFA_MBOX_NR_PAGES 1 + +static inline unsigned long hyp_ffa_proxy_pages(void) +{ + size_t desc_max; + + /* + * The hypervisor FFA proxy needs enough memory to buffer a fragmented + * descriptor returned from EL3 in response to a RETRIEVE_REQ call. + */ + desc_max = sizeof(struct ffa_mem_region) + + sizeof(struct ffa_mem_region_attributes) + + sizeof(struct ffa_composite_mem_region) + + SG_MAX_SEGMENTS * sizeof(struct ffa_mem_region_addr_range); + + /* Plus a page each for the hypervisor's RX and TX mailboxes. */ + return (2 * KVM_FFA_MBOX_NR_PAGES) + DIV_ROUND_UP(desc_max, PAGE_SIZE); +} + #endif /* __ARM64_KVM_PKVM_H__ */ diff --git a/arch/arm64/include/asm/lse.h b/arch/arm64/include/asm/lse.h index f99d74826a7ef8a98314bc6c5fa7793d4aba63e6..cbbcdc35c4cd776291719ccb5e1e08418efd34bb 100644 --- a/arch/arm64/include/asm/lse.h +++ b/arch/arm64/include/asm/lse.h @@ -18,7 +18,7 @@ static __always_inline bool system_uses_lse_atomics(void) { - return alternative_has_feature_likely(ARM64_HAS_LSE_ATOMICS); + return alternative_has_cap_likely(ARM64_HAS_LSE_ATOMICS); } #define __lse_ll_sc_body(op, ...) \ diff --git a/arch/arm64/include/asm/memory.h b/arch/arm64/include/asm/memory.h index c735afdf639b191519b4d68ea6d70e276c46010e..fde4186cc3870894aa21f736f1bbeefdd63499c3 100644 --- a/arch/arm64/include/asm/memory.h +++ b/arch/arm64/include/asm/memory.h @@ -46,7 +46,7 @@ #define KIMAGE_VADDR (MODULES_END) #define MODULES_END (MODULES_VADDR + MODULES_VSIZE) #define MODULES_VADDR (_PAGE_END(VA_BITS_MIN)) -#define MODULES_VSIZE (SZ_128M) +#define MODULES_VSIZE (SZ_2G) #define VMEMMAP_START (-(UL(1) << (VA_BITS - VMEMMAP_SHIFT))) #define VMEMMAP_END (VMEMMAP_START + VMEMMAP_SIZE) #define PCI_IO_END (VMEMMAP_START - SZ_8M) @@ -204,15 +204,17 @@ static inline unsigned long kaslr_offset(void) return kimage_vaddr - KIMAGE_VADDR; } +#ifdef CONFIG_RANDOMIZE_BASE +void kaslr_init(void); static inline bool kaslr_enabled(void) { - /* - * The KASLR offset modulo MIN_KIMG_ALIGN is taken from the physical - * placement of the image rather than from the seed, so a displacement - * of less than MIN_KIMG_ALIGN means that no seed was provided. - */ - return kaslr_offset() >= MIN_KIMG_ALIGN; + extern bool __kaslr_is_enabled; + return __kaslr_is_enabled; } +#else +static inline void kaslr_init(void) { } +static inline bool kaslr_enabled(void) { return false; } +#endif /* * Allow all memory at the discovery stage. We will clip it later. @@ -331,6 +333,14 @@ static inline void *phys_to_virt(phys_addr_t x) return (void *)(__phys_to_virt(x)); } +/* Needed already here for resolving __phys_to_pfn() in virt_to_pfn() */ +#include + +static inline unsigned long virt_to_pfn(const void *kaddr) +{ + return __phys_to_pfn(virt_to_phys(kaddr)); +} + /* * Drivers should NOT use these either. */ @@ -339,7 +349,6 @@ static inline void *phys_to_virt(phys_addr_t x) #define __pa_nodebug(x) __virt_to_phys_nodebug((unsigned long)(x)) #define __va(x) ((void *)__phys_to_virt((phys_addr_t)(x))) #define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT) -#define virt_to_pfn(x) __phys_to_pfn(__virt_to_phys((unsigned long)(x))) #define sym_to_pfn(x) __phys_to_pfn(__pa_symbol(x)) /* diff --git a/arch/arm64/include/asm/mmu_context.h b/arch/arm64/include/asm/mmu_context.h index 56911691bef05207d88496f665d1df5e7edb66ee..a6fb325424e7a990313dc6419a198155e5205b5c 100644 --- a/arch/arm64/include/asm/mmu_context.h +++ b/arch/arm64/include/asm/mmu_context.h @@ -39,11 +39,16 @@ static inline void contextidr_thread_switch(struct task_struct *next) /* * Set TTBR0 to reserved_pg_dir. No translations will be possible via TTBR0. */ -static inline void cpu_set_reserved_ttbr0(void) +static inline void cpu_set_reserved_ttbr0_nosync(void) { unsigned long ttbr = phys_to_ttbr(__pa_symbol(reserved_pg_dir)); write_sysreg(ttbr, ttbr0_el1); +} + +static inline void cpu_set_reserved_ttbr0(void) +{ + cpu_set_reserved_ttbr0_nosync(); isb(); } @@ -52,7 +57,6 @@ void cpu_do_switch_mm(phys_addr_t pgd_phys, struct mm_struct *mm); static inline void cpu_switch_mm(pgd_t *pgd, struct mm_struct *mm) { BUG_ON(pgd == swapper_pg_dir); - cpu_set_reserved_ttbr0(); cpu_do_switch_mm(virt_to_phys(pgd),mm); } @@ -164,7 +168,7 @@ static inline void cpu_replace_ttbr1(pgd_t *pgdp, pgd_t *idmap) * up (i.e. cpufeature framework is not up yet) and * latter only when we enable CNP via cpufeature's * enable() callback. - * Also we rely on the cpu_hwcap bit being set before + * Also we rely on the system_cpucaps bit being set before * calling the enable() function. */ ttbr1 |= TTBR_CNP_BIT; diff --git a/arch/arm64/include/asm/module.h b/arch/arm64/include/asm/module.h index 18734fed3bdd7609bf02b6ebbffc338e80591206..bfa6638b4c930ce11cc2b3462a802581a141fcfe 100644 --- a/arch/arm64/include/asm/module.h +++ b/arch/arm64/include/asm/module.h @@ -7,7 +7,6 @@ #include -#ifdef CONFIG_ARM64_MODULE_PLTS struct mod_plt_sec { int plt_shndx; int plt_num_entries; @@ -21,7 +20,6 @@ struct mod_arch_specific { /* for CONFIG_DYNAMIC_FTRACE */ struct plt_entry *ftrace_trampolines; }; -#endif u64 module_emit_plt_entry(struct module *mod, Elf64_Shdr *sechdrs, void *loc, const Elf64_Rela *rela, @@ -30,12 +28,6 @@ u64 module_emit_plt_entry(struct module *mod, Elf64_Shdr *sechdrs, u64 module_emit_veneer_for_adrp(struct module *mod, Elf64_Shdr *sechdrs, void *loc, u64 val); -#ifdef CONFIG_RANDOMIZE_BASE -extern u64 module_alloc_base; -#else -#define module_alloc_base ((u64)_etext - MODULES_VSIZE) -#endif - struct plt_entry { /* * A program that conforms to the AArch64 Procedure Call Standard diff --git a/arch/arm64/include/asm/module.lds.h b/arch/arm64/include/asm/module.lds.h index dbba4b7559aa0db9f45ab7531416f104a50644ff..b9ae8349e35dbb79b9192a23b2e71a0f73b25f63 100644 --- a/arch/arm64/include/asm/module.lds.h +++ b/arch/arm64/include/asm/module.lds.h @@ -1,9 +1,7 @@ SECTIONS { -#ifdef CONFIG_ARM64_MODULE_PLTS .plt 0 : { BYTE(0) } .init.plt 0 : { BYTE(0) } .text.ftrace_trampoline 0 : { BYTE(0) } -#endif #ifdef CONFIG_KASAN_SW_TAGS /* diff --git a/arch/arm64/include/asm/percpu.h b/arch/arm64/include/asm/percpu.h index b9ba19dbdb6943a187d3873b84228eb76060d254..9abcc8ef3087b7066c82db983ae2753f30607f7f 100644 --- a/arch/arm64/include/asm/percpu.h +++ b/arch/arm64/include/asm/percpu.h @@ -140,17 +140,11 @@ PERCPU_RET_OP(add, add, ldadd) * re-enabling preemption for preemptible kernels, but doing that in a way * which builds inside a module would mean messing directly with the preempt * count. If you do this, peterz and tglx will hunt you down. + * + * Not to mention it'll break the actual preemption model for missing a + * preemption point when TIF_NEED_RESCHED gets set while preemption is + * disabled. */ -#define this_cpu_cmpxchg_double_8(ptr1, ptr2, o1, o2, n1, n2) \ -({ \ - int __ret; \ - preempt_disable_notrace(); \ - __ret = cmpxchg_double_local( raw_cpu_ptr(&(ptr1)), \ - raw_cpu_ptr(&(ptr2)), \ - o1, o2, n1, n2); \ - preempt_enable_notrace(); \ - __ret; \ -}) #define _pcp_protect(op, pcp, ...) \ ({ \ @@ -240,6 +234,22 @@ PERCPU_RET_OP(add, add, ldadd) #define this_cpu_cmpxchg_8(pcp, o, n) \ _pcp_protect_return(cmpxchg_relaxed, pcp, o, n) +#define this_cpu_cmpxchg64(pcp, o, n) this_cpu_cmpxchg_8(pcp, o, n) + +#define this_cpu_cmpxchg128(pcp, o, n) \ +({ \ + typedef typeof(pcp) pcp_op_T__; \ + u128 old__, new__, ret__; \ + pcp_op_T__ *ptr__; \ + old__ = o; \ + new__ = n; \ + preempt_disable_notrace(); \ + ptr__ = raw_cpu_ptr(&(pcp)); \ + ret__ = cmpxchg128_local((void *)ptr__, old__, new__); \ + preempt_enable_notrace(); \ + ret__; \ +}) + #ifdef __KVM_NVHE_HYPERVISOR__ extern unsigned long __hyp_per_cpu_offset(unsigned int cpu); #define __per_cpu_offset diff --git a/arch/arm64/include/asm/pgtable-hwdef.h b/arch/arm64/include/asm/pgtable-hwdef.h index f658aafc47dfa29abde0bb4a5afb0ca8db511b40..e4944d517c9995a4c5fc21eb0cf261bff8ec0181 100644 --- a/arch/arm64/include/asm/pgtable-hwdef.h +++ b/arch/arm64/include/asm/pgtable-hwdef.h @@ -170,6 +170,14 @@ #define PTE_ATTRINDX(t) (_AT(pteval_t, (t)) << 2) #define PTE_ATTRINDX_MASK (_AT(pteval_t, 7) << 2) +/* + * PIIndex[3:0] encoding (Permission Indirection Extension) + */ +#define PTE_PI_IDX_0 6 /* AP[1], USER */ +#define PTE_PI_IDX_1 51 /* DBM */ +#define PTE_PI_IDX_2 53 /* PXN */ +#define PTE_PI_IDX_3 54 /* UXN */ + /* * Memory Attribute override for Stage-2 (MemAttr[3:0]) */ diff --git a/arch/arm64/include/asm/pgtable-prot.h b/arch/arm64/include/asm/pgtable-prot.h index 9b165117a454595a3b232c6857efb13619c54286..eed814b00a389755e050afa4c1d6eae908a42d4d 100644 --- a/arch/arm64/include/asm/pgtable-prot.h +++ b/arch/arm64/include/asm/pgtable-prot.h @@ -27,6 +27,40 @@ */ #define PMD_PRESENT_INVALID (_AT(pteval_t, 1) << 59) /* only when !PMD_SECT_VALID */ +#define _PROT_DEFAULT (PTE_TYPE_PAGE | PTE_AF | PTE_SHARED) +#define _PROT_SECT_DEFAULT (PMD_TYPE_SECT | PMD_SECT_AF | PMD_SECT_S) + +#define PROT_DEFAULT (_PROT_DEFAULT | PTE_MAYBE_NG) +#define PROT_SECT_DEFAULT (_PROT_SECT_DEFAULT | PMD_MAYBE_NG) + +#define PROT_DEVICE_nGnRnE (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_WRITE | PTE_ATTRINDX(MT_DEVICE_nGnRnE)) +#define PROT_DEVICE_nGnRE (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_WRITE | PTE_ATTRINDX(MT_DEVICE_nGnRE)) +#define PROT_NORMAL_NC (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_WRITE | PTE_ATTRINDX(MT_NORMAL_NC)) +#define PROT_NORMAL (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_WRITE | PTE_ATTRINDX(MT_NORMAL)) +#define PROT_NORMAL_TAGGED (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_WRITE | PTE_ATTRINDX(MT_NORMAL_TAGGED)) + +#define PROT_SECT_DEVICE_nGnRE (PROT_SECT_DEFAULT | PMD_SECT_PXN | PMD_SECT_UXN | PMD_ATTRINDX(MT_DEVICE_nGnRE)) +#define PROT_SECT_NORMAL (PROT_SECT_DEFAULT | PMD_SECT_PXN | PMD_SECT_UXN | PTE_WRITE | PMD_ATTRINDX(MT_NORMAL)) +#define PROT_SECT_NORMAL_EXEC (PROT_SECT_DEFAULT | PMD_SECT_UXN | PMD_ATTRINDX(MT_NORMAL)) + +#define _PAGE_DEFAULT (_PROT_DEFAULT | PTE_ATTRINDX(MT_NORMAL)) + +#define _PAGE_KERNEL (PROT_NORMAL) +#define _PAGE_KERNEL_RO ((PROT_NORMAL & ~PTE_WRITE) | PTE_RDONLY) +#define _PAGE_KERNEL_ROX ((PROT_NORMAL & ~(PTE_WRITE | PTE_PXN)) | PTE_RDONLY) +#define _PAGE_KERNEL_EXEC (PROT_NORMAL & ~PTE_PXN) +#define _PAGE_KERNEL_EXEC_CONT ((PROT_NORMAL & ~PTE_PXN) | PTE_CONT) + +#define _PAGE_SHARED (_PAGE_DEFAULT | PTE_USER | PTE_RDONLY | PTE_NG | PTE_PXN | PTE_UXN | PTE_WRITE) +#define _PAGE_SHARED_EXEC (_PAGE_DEFAULT | PTE_USER | PTE_RDONLY | PTE_NG | PTE_PXN | PTE_WRITE) +#define _PAGE_READONLY (_PAGE_DEFAULT | PTE_USER | PTE_RDONLY | PTE_NG | PTE_PXN | PTE_UXN) +#define _PAGE_READONLY_EXEC (_PAGE_DEFAULT | PTE_USER | PTE_RDONLY | PTE_NG | PTE_PXN) +#define _PAGE_EXECONLY (_PAGE_DEFAULT | PTE_RDONLY | PTE_NG | PTE_PXN) + +#ifdef __ASSEMBLY__ +#define PTE_MAYBE_NG 0 +#endif + #ifndef __ASSEMBLY__ #include @@ -34,9 +68,6 @@ extern bool arm64_use_ng_mappings; -#define _PROT_DEFAULT (PTE_TYPE_PAGE | PTE_AF | PTE_SHARED) -#define _PROT_SECT_DEFAULT (PMD_TYPE_SECT | PMD_SECT_AF | PMD_SECT_S) - #define PTE_MAYBE_NG (arm64_use_ng_mappings ? PTE_NG : 0) #define PMD_MAYBE_NG (arm64_use_ng_mappings ? PMD_SECT_NG : 0) @@ -50,26 +81,11 @@ extern bool arm64_use_ng_mappings; #define PTE_MAYBE_GP 0 #endif -#define PROT_DEFAULT (_PROT_DEFAULT | PTE_MAYBE_NG) -#define PROT_SECT_DEFAULT (_PROT_SECT_DEFAULT | PMD_MAYBE_NG) - -#define PROT_DEVICE_nGnRnE (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_WRITE | PTE_ATTRINDX(MT_DEVICE_nGnRnE)) -#define PROT_DEVICE_nGnRE (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_WRITE | PTE_ATTRINDX(MT_DEVICE_nGnRE)) -#define PROT_NORMAL_NC (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_WRITE | PTE_ATTRINDX(MT_NORMAL_NC)) -#define PROT_NORMAL (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_WRITE | PTE_ATTRINDX(MT_NORMAL)) -#define PROT_NORMAL_TAGGED (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_WRITE | PTE_ATTRINDX(MT_NORMAL_TAGGED)) - -#define PROT_SECT_DEVICE_nGnRE (PROT_SECT_DEFAULT | PMD_SECT_PXN | PMD_SECT_UXN | PMD_ATTRINDX(MT_DEVICE_nGnRE)) -#define PROT_SECT_NORMAL (PROT_SECT_DEFAULT | PMD_SECT_PXN | PMD_SECT_UXN | PMD_ATTRINDX(MT_NORMAL)) -#define PROT_SECT_NORMAL_EXEC (PROT_SECT_DEFAULT | PMD_SECT_UXN | PMD_ATTRINDX(MT_NORMAL)) - -#define _PAGE_DEFAULT (_PROT_DEFAULT | PTE_ATTRINDX(MT_NORMAL)) - -#define PAGE_KERNEL __pgprot(PROT_NORMAL) -#define PAGE_KERNEL_RO __pgprot((PROT_NORMAL & ~PTE_WRITE) | PTE_RDONLY) -#define PAGE_KERNEL_ROX __pgprot((PROT_NORMAL & ~(PTE_WRITE | PTE_PXN)) | PTE_RDONLY) -#define PAGE_KERNEL_EXEC __pgprot(PROT_NORMAL & ~PTE_PXN) -#define PAGE_KERNEL_EXEC_CONT __pgprot((PROT_NORMAL & ~PTE_PXN) | PTE_CONT) +#define PAGE_KERNEL __pgprot(_PAGE_KERNEL) +#define PAGE_KERNEL_RO __pgprot(_PAGE_KERNEL_RO) +#define PAGE_KERNEL_ROX __pgprot(_PAGE_KERNEL_ROX) +#define PAGE_KERNEL_EXEC __pgprot(_PAGE_KERNEL_EXEC) +#define PAGE_KERNEL_EXEC_CONT __pgprot(_PAGE_KERNEL_EXEC_CONT) #define PAGE_S2_MEMATTR(attr, has_fwb) \ ({ \ @@ -83,12 +99,62 @@ extern bool arm64_use_ng_mappings; #define PAGE_NONE __pgprot(((_PAGE_DEFAULT) & ~PTE_VALID) | PTE_PROT_NONE | PTE_RDONLY | PTE_NG | PTE_PXN | PTE_UXN) /* shared+writable pages are clean by default, hence PTE_RDONLY|PTE_WRITE */ -#define PAGE_SHARED __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_RDONLY | PTE_NG | PTE_PXN | PTE_UXN | PTE_WRITE) -#define PAGE_SHARED_EXEC __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_RDONLY | PTE_NG | PTE_PXN | PTE_WRITE) -#define PAGE_READONLY __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_RDONLY | PTE_NG | PTE_PXN | PTE_UXN) -#define PAGE_READONLY_EXEC __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_RDONLY | PTE_NG | PTE_PXN) -#define PAGE_EXECONLY __pgprot(_PAGE_DEFAULT | PTE_RDONLY | PTE_NG | PTE_PXN) +#define PAGE_SHARED __pgprot(_PAGE_SHARED) +#define PAGE_SHARED_EXEC __pgprot(_PAGE_SHARED_EXEC) +#define PAGE_READONLY __pgprot(_PAGE_READONLY) +#define PAGE_READONLY_EXEC __pgprot(_PAGE_READONLY_EXEC) +#define PAGE_EXECONLY __pgprot(_PAGE_EXECONLY) #endif /* __ASSEMBLY__ */ +#define pte_pi_index(pte) ( \ + ((pte & BIT(PTE_PI_IDX_3)) >> (PTE_PI_IDX_3 - 3)) | \ + ((pte & BIT(PTE_PI_IDX_2)) >> (PTE_PI_IDX_2 - 2)) | \ + ((pte & BIT(PTE_PI_IDX_1)) >> (PTE_PI_IDX_1 - 1)) | \ + ((pte & BIT(PTE_PI_IDX_0)) >> (PTE_PI_IDX_0 - 0))) + +/* + * Page types used via Permission Indirection Extension (PIE). PIE uses + * the USER, DBM, PXN and UXN bits to to generate an index which is used + * to look up the actual permission in PIR_ELx and PIRE0_EL1. We define + * combinations we use on non-PIE systems with the same encoding, for + * convenience these are listed here as comments as are the unallocated + * encodings. + */ + +/* 0: PAGE_DEFAULT */ +/* 1: PTE_USER */ +/* 2: PTE_WRITE */ +/* 3: PTE_WRITE | PTE_USER */ +/* 4: PAGE_EXECONLY PTE_PXN */ +/* 5: PAGE_READONLY_EXEC PTE_PXN | PTE_USER */ +/* 6: PTE_PXN | PTE_WRITE */ +/* 7: PAGE_SHARED_EXEC PTE_PXN | PTE_WRITE | PTE_USER */ +/* 8: PAGE_KERNEL_ROX PTE_UXN */ +/* 9: PTE_UXN | PTE_USER */ +/* a: PAGE_KERNEL_EXEC PTE_UXN | PTE_WRITE */ +/* b: PTE_UXN | PTE_WRITE | PTE_USER */ +/* c: PAGE_KERNEL_RO PTE_UXN | PTE_PXN */ +/* d: PAGE_READONLY PTE_UXN | PTE_PXN | PTE_USER */ +/* e: PAGE_KERNEL PTE_UXN | PTE_PXN | PTE_WRITE */ +/* f: PAGE_SHARED PTE_UXN | PTE_PXN | PTE_WRITE | PTE_USER */ + +#define PIE_E0 ( \ + PIRx_ELx_PERM(pte_pi_index(_PAGE_EXECONLY), PIE_X_O) | \ + PIRx_ELx_PERM(pte_pi_index(_PAGE_READONLY_EXEC), PIE_RX) | \ + PIRx_ELx_PERM(pte_pi_index(_PAGE_SHARED_EXEC), PIE_RWX) | \ + PIRx_ELx_PERM(pte_pi_index(_PAGE_READONLY), PIE_R) | \ + PIRx_ELx_PERM(pte_pi_index(_PAGE_SHARED), PIE_RW)) + +#define PIE_E1 ( \ + PIRx_ELx_PERM(pte_pi_index(_PAGE_EXECONLY), PIE_NONE_O) | \ + PIRx_ELx_PERM(pte_pi_index(_PAGE_READONLY_EXEC), PIE_R) | \ + PIRx_ELx_PERM(pte_pi_index(_PAGE_SHARED_EXEC), PIE_RW) | \ + PIRx_ELx_PERM(pte_pi_index(_PAGE_READONLY), PIE_R) | \ + PIRx_ELx_PERM(pte_pi_index(_PAGE_SHARED), PIE_RW) | \ + PIRx_ELx_PERM(pte_pi_index(_PAGE_KERNEL_ROX), PIE_RX) | \ + PIRx_ELx_PERM(pte_pi_index(_PAGE_KERNEL_EXEC), PIE_RWX) | \ + PIRx_ELx_PERM(pte_pi_index(_PAGE_KERNEL_RO), PIE_R) | \ + PIRx_ELx_PERM(pte_pi_index(_PAGE_KERNEL), PIE_RW)) + #endif /* __ASM_PGTABLE_PROT_H */ diff --git a/arch/arm64/include/asm/scs.h b/arch/arm64/include/asm/scs.h index 13df982a080805e6a747c09345f5cd183b7289ec..3fdae5fe3142f625ffabd19ab26ea02637c06f8a 100644 --- a/arch/arm64/include/asm/scs.h +++ b/arch/arm64/include/asm/scs.h @@ -73,6 +73,7 @@ static inline void dynamic_scs_init(void) {} #endif int scs_patch(const u8 eh_frame[], int size); +asmlinkage void scs_patch_vmlinux(void); #endif /* __ASSEMBLY __ */ diff --git a/arch/arm64/include/asm/smp.h b/arch/arm64/include/asm/smp.h index f2d26235bfb4eef6bbe2b17ef31c06c27531284a..9b31e6d0da17441b08dbbe583b7b5a35f6b82dcb 100644 --- a/arch/arm64/include/asm/smp.h +++ b/arch/arm64/include/asm/smp.h @@ -99,7 +99,7 @@ static inline void arch_send_wakeup_ipi_mask(const struct cpumask *mask) extern int __cpu_disable(void); -extern void __cpu_die(unsigned int cpu); +static inline void __cpu_die(unsigned int cpu) { } extern void __noreturn cpu_die(void); extern void __noreturn cpu_die_early(void); diff --git a/arch/arm64/include/asm/spectre.h b/arch/arm64/include/asm/spectre.h index db7b371b367c0a0d294fe96ee38344deebf15db9..9cc501450486d83ac9b3bd1bf6fa3375d0bba6f3 100644 --- a/arch/arm64/include/asm/spectre.h +++ b/arch/arm64/include/asm/spectre.h @@ -100,5 +100,21 @@ bool is_spectre_bhb_affected(const struct arm64_cpu_capabilities *entry, int sco u8 spectre_bhb_loop_affected(int scope); void spectre_bhb_enable_mitigation(const struct arm64_cpu_capabilities *__unused); bool try_emulate_el1_ssbs(struct pt_regs *regs, u32 instr); + +void spectre_v4_patch_fw_mitigation_enable(struct alt_instr *alt, __le32 *origptr, + __le32 *updptr, int nr_inst); +void smccc_patch_fw_mitigation_conduit(struct alt_instr *alt, __le32 *origptr, + __le32 *updptr, int nr_inst); +void spectre_bhb_patch_loop_mitigation_enable(struct alt_instr *alt, __le32 *origptr, + __le32 *updptr, int nr_inst); +void spectre_bhb_patch_fw_mitigation_enabled(struct alt_instr *alt, __le32 *origptr, + __le32 *updptr, int nr_inst); +void spectre_bhb_patch_loop_iter(struct alt_instr *alt, + __le32 *origptr, __le32 *updptr, int nr_inst); +void spectre_bhb_patch_wa3(struct alt_instr *alt, + __le32 *origptr, __le32 *updptr, int nr_inst); +void spectre_bhb_patch_clearbhb(struct alt_instr *alt, + __le32 *origptr, __le32 *updptr, int nr_inst); + #endif /* __ASSEMBLY__ */ #endif /* __ASM_SPECTRE_H */ diff --git a/arch/arm64/include/asm/syscall.h b/arch/arm64/include/asm/syscall.h index 4cfe9b49709ba9c4a9f08e22d6c4b5c2f0fd69ab..ab8e14b96f68172e30d7783ad2d98449ffd21c23 100644 --- a/arch/arm64/include/asm/syscall.h +++ b/arch/arm64/include/asm/syscall.h @@ -85,4 +85,7 @@ static inline int syscall_get_arch(struct task_struct *task) return AUDIT_ARCH_AARCH64; } +int syscall_trace_enter(struct pt_regs *regs); +void syscall_trace_exit(struct pt_regs *regs); + #endif /* __ASM_SYSCALL_H */ diff --git a/arch/arm64/include/asm/syscall_wrapper.h b/arch/arm64/include/asm/syscall_wrapper.h index d30217c21eff78f99fbefdb20a85e3c6bae06b14..17f687510c4851ac7c0838c5cb76e5637275e341 100644 --- a/arch/arm64/include/asm/syscall_wrapper.h +++ b/arch/arm64/include/asm/syscall_wrapper.h @@ -38,6 +38,7 @@ asmlinkage long __arm64_compat_sys_##sname(const struct pt_regs *__unused) #define COND_SYSCALL_COMPAT(name) \ + asmlinkage long __arm64_compat_sys_##name(const struct pt_regs *regs); \ asmlinkage long __weak __arm64_compat_sys_##name(const struct pt_regs *regs) \ { \ return sys_ni_syscall(); \ @@ -53,6 +54,7 @@ ALLOW_ERROR_INJECTION(__arm64_sys##name, ERRNO); \ static long __se_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__)); \ static inline long __do_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__)); \ + asmlinkage long __arm64_sys##name(const struct pt_regs *regs); \ asmlinkage long __arm64_sys##name(const struct pt_regs *regs) \ { \ return __se_sys##name(SC_ARM64_REGS_TO_ARGS(x,__VA_ARGS__)); \ @@ -73,11 +75,13 @@ asmlinkage long __arm64_sys_##sname(const struct pt_regs *__unused) #define COND_SYSCALL(name) \ + asmlinkage long __arm64_sys_##name(const struct pt_regs *regs); \ asmlinkage long __weak __arm64_sys_##name(const struct pt_regs *regs) \ { \ return sys_ni_syscall(); \ } +asmlinkage long __arm64_sys_ni_syscall(const struct pt_regs *__unused); #define SYS_NI(name) SYSCALL_ALIAS(__arm64_sys_##name, sys_ni_posix_timers); #endif /* __ASM_SYSCALL_WRAPPER_H */ diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h index eefd712f2430353f5800df0b06333dd0460f22c0..b481935e9314e5e13fa5543597d2b34558844c47 100644 --- a/arch/arm64/include/asm/sysreg.h +++ b/arch/arm64/include/asm/sysreg.h @@ -140,25 +140,17 @@ #define SYS_SVCR_SMSTART_SM_EL0 sys_reg(0, 3, 4, 3, 3) #define SYS_SVCR_SMSTOP_SMZA_EL0 sys_reg(0, 3, 4, 6, 3) -#define SYS_OSDTRRX_EL1 sys_reg(2, 0, 0, 0, 2) -#define SYS_MDCCINT_EL1 sys_reg(2, 0, 0, 2, 0) -#define SYS_MDSCR_EL1 sys_reg(2, 0, 0, 2, 2) -#define SYS_OSDTRTX_EL1 sys_reg(2, 0, 0, 3, 2) -#define SYS_OSECCR_EL1 sys_reg(2, 0, 0, 6, 2) #define SYS_DBGBVRn_EL1(n) sys_reg(2, 0, 0, n, 4) #define SYS_DBGBCRn_EL1(n) sys_reg(2, 0, 0, n, 5) #define SYS_DBGWVRn_EL1(n) sys_reg(2, 0, 0, n, 6) #define SYS_DBGWCRn_EL1(n) sys_reg(2, 0, 0, n, 7) #define SYS_MDRAR_EL1 sys_reg(2, 0, 1, 0, 0) -#define SYS_OSLAR_EL1 sys_reg(2, 0, 1, 0, 4) -#define SYS_OSLAR_OSLK BIT(0) - #define SYS_OSLSR_EL1 sys_reg(2, 0, 1, 1, 4) -#define SYS_OSLSR_OSLM_MASK (BIT(3) | BIT(0)) -#define SYS_OSLSR_OSLM_NI 0 -#define SYS_OSLSR_OSLM_IMPLEMENTED BIT(3) -#define SYS_OSLSR_OSLK BIT(1) +#define OSLSR_EL1_OSLM_MASK (BIT(3) | BIT(0)) +#define OSLSR_EL1_OSLM_NI 0 +#define OSLSR_EL1_OSLM_IMPLEMENTED BIT(3) +#define OSLSR_EL1_OSLK BIT(1) #define SYS_OSDLR_EL1 sys_reg(2, 0, 1, 3, 4) #define SYS_DBGPRCR_EL1 sys_reg(2, 0, 1, 4, 4) @@ -241,54 +233,8 @@ /*** End of Statistical Profiling Extension ***/ -/* - * TRBE Registers - */ -#define SYS_TRBLIMITR_EL1 sys_reg(3, 0, 9, 11, 0) -#define SYS_TRBPTR_EL1 sys_reg(3, 0, 9, 11, 1) -#define SYS_TRBBASER_EL1 sys_reg(3, 0, 9, 11, 2) -#define SYS_TRBSR_EL1 sys_reg(3, 0, 9, 11, 3) -#define SYS_TRBMAR_EL1 sys_reg(3, 0, 9, 11, 4) -#define SYS_TRBTRG_EL1 sys_reg(3, 0, 9, 11, 6) -#define SYS_TRBIDR_EL1 sys_reg(3, 0, 9, 11, 7) - -#define TRBLIMITR_LIMIT_MASK GENMASK_ULL(51, 0) -#define TRBLIMITR_LIMIT_SHIFT 12 -#define TRBLIMITR_NVM BIT(5) -#define TRBLIMITR_TRIG_MODE_MASK GENMASK(1, 0) -#define TRBLIMITR_TRIG_MODE_SHIFT 3 -#define TRBLIMITR_FILL_MODE_MASK GENMASK(1, 0) -#define TRBLIMITR_FILL_MODE_SHIFT 1 -#define TRBLIMITR_ENABLE BIT(0) -#define TRBPTR_PTR_MASK GENMASK_ULL(63, 0) -#define TRBPTR_PTR_SHIFT 0 -#define TRBBASER_BASE_MASK GENMASK_ULL(51, 0) -#define TRBBASER_BASE_SHIFT 12 -#define TRBSR_EC_MASK GENMASK(5, 0) -#define TRBSR_EC_SHIFT 26 -#define TRBSR_IRQ BIT(22) -#define TRBSR_TRG BIT(21) -#define TRBSR_WRAP BIT(20) -#define TRBSR_ABORT BIT(18) -#define TRBSR_STOP BIT(17) -#define TRBSR_MSS_MASK GENMASK(15, 0) -#define TRBSR_MSS_SHIFT 0 -#define TRBSR_BSC_MASK GENMASK(5, 0) -#define TRBSR_BSC_SHIFT 0 -#define TRBSR_FSC_MASK GENMASK(5, 0) -#define TRBSR_FSC_SHIFT 0 -#define TRBMAR_SHARE_MASK GENMASK(1, 0) -#define TRBMAR_SHARE_SHIFT 8 -#define TRBMAR_OUTER_MASK GENMASK(3, 0) -#define TRBMAR_OUTER_SHIFT 4 -#define TRBMAR_INNER_MASK GENMASK(3, 0) -#define TRBMAR_INNER_SHIFT 0 -#define TRBTRG_TRG_MASK GENMASK(31, 0) -#define TRBTRG_TRG_SHIFT 0 -#define TRBIDR_FLAG BIT(5) -#define TRBIDR_PROG BIT(4) -#define TRBIDR_ALIGN_MASK GENMASK(3, 0) -#define TRBIDR_ALIGN_SHIFT 0 +#define TRBSR_EL1_BSC_MASK GENMASK(5, 0) +#define TRBSR_EL1_BSC_SHIFT 0 #define SYS_PMINTENSET_EL1 sys_reg(3, 0, 9, 14, 1) #define SYS_PMINTENCLR_EL1 sys_reg(3, 0, 9, 14, 2) @@ -564,6 +510,7 @@ (BIT(18)) | (BIT(22)) | (BIT(23)) | (BIT(28)) | \ (BIT(29))) +#define SCTLR_EL2_BT (BIT(36)) #ifdef CONFIG_CPU_BIG_ENDIAN #define ENDIAN_SET_EL2 SCTLR_ELx_EE #else @@ -764,6 +711,25 @@ #define ICH_VTR_TDS_SHIFT 19 #define ICH_VTR_TDS_MASK (1 << ICH_VTR_TDS_SHIFT) +/* + * Permission Indirection Extension (PIE) permission encodings. + * Encodings with the _O suffix, have overlays applied (Permission Overlay Extension). + */ +#define PIE_NONE_O 0x0 +#define PIE_R_O 0x1 +#define PIE_X_O 0x2 +#define PIE_RX_O 0x3 +#define PIE_RW_O 0x5 +#define PIE_RWnX_O 0x6 +#define PIE_RWX_O 0x7 +#define PIE_R 0x8 +#define PIE_GCS 0x9 +#define PIE_RX 0xa +#define PIE_RW 0xc +#define PIE_RWX 0xe + +#define PIRx_ELx_PERM(idx, perm) ((perm) << ((idx) * 4)) + #define ARM64_FEATURE_FIELD_BITS 4 /* Defined for compatibility only, do not add new users. */ diff --git a/arch/arm64/include/asm/thread_info.h b/arch/arm64/include/asm/thread_info.h index 848739c15de8274e098af57dae60bda1423a1509..553d1bc559c603f5d9933651463b9025a663e7d6 100644 --- a/arch/arm64/include/asm/thread_info.h +++ b/arch/arm64/include/asm/thread_info.h @@ -55,10 +55,6 @@ struct thread_info { void arch_setup_new_exec(void); #define arch_setup_new_exec arch_setup_new_exec -void arch_release_task_struct(struct task_struct *tsk); -int arch_dup_task_struct(struct task_struct *dst, - struct task_struct *src); - #endif #define TIF_SIGPENDING 0 /* signal pending */ diff --git a/arch/arm64/include/asm/traps.h b/arch/arm64/include/asm/traps.h index 1f361e2da516fe532974e6301d828f81f8442889..d66dfb3a72ddc2ba37a6a4884975c6c0ae9f54f9 100644 --- a/arch/arm64/include/asm/traps.h +++ b/arch/arm64/include/asm/traps.h @@ -29,6 +29,8 @@ void arm64_force_sig_fault(int signo, int code, unsigned long far, const char *s void arm64_force_sig_mceerr(int code, unsigned long far, short lsb, const char *str); void arm64_force_sig_ptrace_errno_trap(int errno, unsigned long far, const char *str); +int early_brk64(unsigned long addr, unsigned long esr, struct pt_regs *regs); + /* * Move regs->pc to next instruction and do necessary setup before it * is executed. diff --git a/arch/arm64/include/asm/uaccess.h b/arch/arm64/include/asm/uaccess.h index 05f4fc265428457b8316859f7bab81622aacc994..14be5000c5a0cec1a65503137dba929da314077b 100644 --- a/arch/arm64/include/asm/uaccess.h +++ b/arch/arm64/include/asm/uaccess.h @@ -65,7 +65,6 @@ static inline void __uaccess_ttbr0_disable(void) ttbr &= ~TTBR_ASID_MASK; /* reserved_pg_dir placed before swapper_pg_dir */ write_sysreg(ttbr - RESERVED_SWAPPER_OFFSET, ttbr0_el1); - isb(); /* Set reserved ASID */ write_sysreg(ttbr, ttbr1_el1); isb(); @@ -89,7 +88,6 @@ static inline void __uaccess_ttbr0_enable(void) ttbr1 &= ~TTBR_ASID_MASK; /* safety measure */ ttbr1 |= ttbr0 & TTBR_ASID_MASK; write_sysreg(ttbr1, ttbr1_el1); - isb(); /* Restore user page table */ write_sysreg(ttbr0, ttbr0_el1); diff --git a/arch/arm64/include/asm/unistd.h b/arch/arm64/include/asm/unistd.h index 037feba03a51d85de6b3bdbf580d18baa7a8afcb..64a514f90131b8997c04c01d443dec2335e190f0 100644 --- a/arch/arm64/include/asm/unistd.h +++ b/arch/arm64/include/asm/unistd.h @@ -39,7 +39,7 @@ #define __ARM_NR_compat_set_tls (__ARM_NR_COMPAT_BASE + 5) #define __ARM_NR_COMPAT_END (__ARM_NR_COMPAT_BASE + 0x800) -#define __NR_compat_syscalls 451 +#define __NR_compat_syscalls 452 #endif #define __ARCH_WANT_SYS_CLONE diff --git a/arch/arm64/include/asm/unistd32.h b/arch/arm64/include/asm/unistd32.h index 604a2053d00670b73c0da75a224d8aaf13828e25..d952a28463e0180194a1aba744dd2371f74506a5 100644 --- a/arch/arm64/include/asm/unistd32.h +++ b/arch/arm64/include/asm/unistd32.h @@ -907,6 +907,8 @@ __SYSCALL(__NR_process_mrelease, sys_process_mrelease) __SYSCALL(__NR_futex_waitv, sys_futex_waitv) #define __NR_set_mempolicy_home_node 450 __SYSCALL(__NR_set_mempolicy_home_node, sys_set_mempolicy_home_node) +#define __NR_cachestat 451 +__SYSCALL(__NR_cachestat, sys_cachestat) /* * Please add new compat syscalls above this comment and update diff --git a/arch/arm64/include/asm/virt.h b/arch/arm64/include/asm/virt.h index 4eb601e7de507615de61e1925c460f8856b5b00d..5227db7640c8d0d68d4e66716fc57dcb3701d29f 100644 --- a/arch/arm64/include/asm/virt.h +++ b/arch/arm64/include/asm/virt.h @@ -110,8 +110,10 @@ static inline bool is_hyp_mode_mismatched(void) return __boot_cpu_mode[0] != __boot_cpu_mode[1]; } -static inline bool is_kernel_in_hyp_mode(void) +static __always_inline bool is_kernel_in_hyp_mode(void) { + BUILD_BUG_ON(__is_defined(__KVM_NVHE_HYPERVISOR__) || + __is_defined(__KVM_VHE_HYPERVISOR__)); return read_sysreg(CurrentEL) == CurrentEL_EL2; } @@ -140,6 +142,14 @@ static __always_inline bool is_protected_kvm_enabled(void) return cpus_have_final_cap(ARM64_KVM_PROTECTED_MODE); } +static __always_inline bool has_hvhe(void) +{ + if (is_vhe_hyp_code()) + return false; + + return cpus_have_final_cap(ARM64_KVM_HVHE); +} + static inline bool is_hyp_nvhe(void) { return is_hyp_mode_available() && !is_kernel_in_hyp_mode(); diff --git a/arch/arm64/include/uapi/asm/bitsperlong.h b/arch/arm64/include/uapi/asm/bitsperlong.h deleted file mode 100644 index 485d60bee26ca313ad15797f230efe10072befc9..0000000000000000000000000000000000000000 --- a/arch/arm64/include/uapi/asm/bitsperlong.h +++ /dev/null @@ -1,24 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -/* - * Copyright (C) 2012 ARM Ltd. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#ifndef __ASM_BITSPERLONG_H -#define __ASM_BITSPERLONG_H - -#define __BITS_PER_LONG 64 - -#include - -#endif /* __ASM_BITSPERLONG_H */ diff --git a/arch/arm64/include/uapi/asm/hwcap.h b/arch/arm64/include/uapi/asm/hwcap.h index 69a4fb749c65d42197a7696a93756eb861caf227..a2cac4305b1e0b48581f816af8bb7339dd7c1cd4 100644 --- a/arch/arm64/include/uapi/asm/hwcap.h +++ b/arch/arm64/include/uapi/asm/hwcap.h @@ -102,5 +102,6 @@ #define HWCAP2_SME_BI32I32 (1UL << 40) #define HWCAP2_SME_B16B16 (1UL << 41) #define HWCAP2_SME_F16F16 (1UL << 42) +#define HWCAP2_MOPS (1UL << 43) #endif /* _UAPI__ASM_HWCAP_H */ diff --git a/arch/arm64/include/uapi/asm/sigcontext.h b/arch/arm64/include/uapi/asm/sigcontext.h index 656a10ea6c6797992e800ee4ecaa9ae322103278..f23c1dc3f002fe44a241bb3064391afc658f61ac 100644 --- a/arch/arm64/include/uapi/asm/sigcontext.h +++ b/arch/arm64/include/uapi/asm/sigcontext.h @@ -177,7 +177,7 @@ struct zt_context { * vector length beyond its initial architectural limit of 2048 bits * (16 quadwords). * - * See linux/Documentation/arm64/sve.rst for a description of the VL/VQ + * See linux/Documentation/arch/arm64/sve.rst for a description of the VL/VQ * terminology. */ #define SVE_VQ_BYTES __SVE_VQ_BYTES /* bytes per quadword */ diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile index 7c2bb4e724767bc3e51e0e335be51e616f5809f7..d95b3d6b471a7d63957c47151fd6cb404ca0f4c7 100644 --- a/arch/arm64/kernel/Makefile +++ b/arch/arm64/kernel/Makefile @@ -42,9 +42,9 @@ obj-$(CONFIG_COMPAT) += sigreturn32.o obj-$(CONFIG_COMPAT_ALIGNMENT_FIXUPS) += compat_alignment.o obj-$(CONFIG_KUSER_HELPERS) += kuser32.o obj-$(CONFIG_FUNCTION_TRACER) += ftrace.o entry-ftrace.o -obj-$(CONFIG_MODULES) += module.o -obj-$(CONFIG_ARM64_MODULE_PLTS) += module-plts.o +obj-$(CONFIG_MODULES) += module.o module-plts.o obj-$(CONFIG_PERF_EVENTS) += perf_regs.o perf_callchain.o +obj-$(CONFIG_HARDLOCKUP_DETECTOR_PERF) += watchdog_hld.o obj-$(CONFIG_HAVE_HW_BREAKPOINT) += hw_breakpoint.o obj-$(CONFIG_CPU_PM) += sleep.o suspend.o obj-$(CONFIG_CPU_IDLE) += cpuidle.o diff --git a/arch/arm64/kernel/alternative.c b/arch/arm64/kernel/alternative.c index d32d4ed5519bd3066a5a5a15646744648113f6d1..8ff6610af49664f01ceef2a5e8f6fae52e861a43 100644 --- a/arch/arm64/kernel/alternative.c +++ b/arch/arm64/kernel/alternative.c @@ -24,8 +24,8 @@ #define ALT_ORIG_PTR(a) __ALT_PTR(a, orig_offset) #define ALT_REPL_PTR(a) __ALT_PTR(a, alt_offset) -#define ALT_CAP(a) ((a)->cpufeature & ~ARM64_CB_BIT) -#define ALT_HAS_CB(a) ((a)->cpufeature & ARM64_CB_BIT) +#define ALT_CAP(a) ((a)->cpucap & ~ARM64_CB_BIT) +#define ALT_HAS_CB(a) ((a)->cpucap & ARM64_CB_BIT) /* Volatile, as we may be patching the guts of READ_ONCE() */ static volatile int all_alternatives_applied; @@ -37,12 +37,12 @@ struct alt_region { struct alt_instr *end; }; -bool alternative_is_applied(u16 cpufeature) +bool alternative_is_applied(u16 cpucap) { - if (WARN_ON(cpufeature >= ARM64_NCAPS)) + if (WARN_ON(cpucap >= ARM64_NCAPS)) return false; - return test_bit(cpufeature, applied_alternatives); + return test_bit(cpucap, applied_alternatives); } /* @@ -121,11 +121,11 @@ static noinstr void patch_alternative(struct alt_instr *alt, * accidentally call into the cache.S code, which is patched by us at * runtime. */ -static void clean_dcache_range_nopatch(u64 start, u64 end) +static noinstr void clean_dcache_range_nopatch(u64 start, u64 end) { u64 cur, d_size, ctr_el0; - ctr_el0 = read_sanitised_ftr_reg(SYS_CTR_EL0); + ctr_el0 = arm64_ftr_reg_ctrel0.sys_val; d_size = 4 << cpuid_feature_extract_unsigned_field(ctr_el0, CTR_EL0_DminLine_SHIFT); cur = start & ~(d_size - 1); @@ -141,7 +141,7 @@ static void clean_dcache_range_nopatch(u64 start, u64 end) static void __apply_alternatives(const struct alt_region *region, bool is_module, - unsigned long *feature_mask) + unsigned long *cpucap_mask) { struct alt_instr *alt; __le32 *origptr, *updptr; @@ -151,7 +151,7 @@ static void __apply_alternatives(const struct alt_region *region, int nr_inst; int cap = ALT_CAP(alt); - if (!test_bit(cap, feature_mask)) + if (!test_bit(cap, cpucap_mask)) continue; if (!cpus_have_cap(cap)) @@ -188,11 +188,10 @@ static void __apply_alternatives(const struct alt_region *region, icache_inval_all_pou(); isb(); - /* Ignore ARM64_CB bit from feature mask */ bitmap_or(applied_alternatives, applied_alternatives, - feature_mask, ARM64_NCAPS); + cpucap_mask, ARM64_NCAPS); bitmap_and(applied_alternatives, applied_alternatives, - cpu_hwcaps, ARM64_NCAPS); + system_cpucaps, ARM64_NCAPS); } } @@ -239,7 +238,7 @@ static int __init __apply_alternatives_multi_stop(void *unused) } else { DECLARE_BITMAP(remaining_capabilities, ARM64_NCAPS); - bitmap_complement(remaining_capabilities, boot_capabilities, + bitmap_complement(remaining_capabilities, boot_cpucaps, ARM64_NCAPS); BUG_ON(all_alternatives_applied); @@ -274,7 +273,7 @@ void __init apply_boot_alternatives(void) pr_info("applying boot alternatives\n"); __apply_alternatives(&kernel_alternatives, false, - &boot_capabilities[0]); + &boot_cpucaps[0]); } #ifdef CONFIG_MODULES diff --git a/arch/arm64/kernel/asm-offsets.c b/arch/arm64/kernel/asm-offsets.c index 0996094b0d2234067c7068c55cfd675ba4b17421..5ff1942b04fcfd94e334b6b204f7f3885647c68d 100644 --- a/arch/arm64/kernel/asm-offsets.c +++ b/arch/arm64/kernel/asm-offsets.c @@ -200,9 +200,22 @@ int main(void) #endif #ifdef CONFIG_FUNCTION_TRACER DEFINE(FTRACE_OPS_FUNC, offsetof(struct ftrace_ops, func)); +#endif + BLANK(); +#ifdef CONFIG_FUNCTION_GRAPH_TRACER + DEFINE(FGRET_REGS_X0, offsetof(struct fgraph_ret_regs, regs[0])); + DEFINE(FGRET_REGS_X1, offsetof(struct fgraph_ret_regs, regs[1])); + DEFINE(FGRET_REGS_X2, offsetof(struct fgraph_ret_regs, regs[2])); + DEFINE(FGRET_REGS_X3, offsetof(struct fgraph_ret_regs, regs[3])); + DEFINE(FGRET_REGS_X4, offsetof(struct fgraph_ret_regs, regs[4])); + DEFINE(FGRET_REGS_X5, offsetof(struct fgraph_ret_regs, regs[5])); + DEFINE(FGRET_REGS_X6, offsetof(struct fgraph_ret_regs, regs[6])); + DEFINE(FGRET_REGS_X7, offsetof(struct fgraph_ret_regs, regs[7])); + DEFINE(FGRET_REGS_FP, offsetof(struct fgraph_ret_regs, fp)); + DEFINE(FGRET_REGS_SIZE, sizeof(struct fgraph_ret_regs)); +#endif #ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS DEFINE(FTRACE_OPS_DIRECT_CALL, offsetof(struct ftrace_ops, direct_call)); -#endif #endif return 0; } diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c index 307faa2b4395ed9fcacdbf9f992111cd376dc601..be66e94a21bda37ff271ea7cd8204019f74b08aa 100644 --- a/arch/arm64/kernel/cpu_errata.c +++ b/arch/arm64/kernel/cpu_errata.c @@ -729,6 +729,13 @@ const struct arm64_cpu_capabilities arm64_errata[] = { MIDR_FIXED(MIDR_CPU_VAR_REV(1,1), BIT(25)), .cpu_enable = cpu_clear_bf16_from_user_emulation, }, +#endif +#ifdef CONFIG_AMPERE_ERRATUM_AC03_CPU_38 + { + .desc = "AmpereOne erratum AC03_CPU_38", + .capability = ARM64_WORKAROUND_AMPERE_AC03_CPU_38, + ERRATA_MIDR_ALL_VERSIONS(MIDR_AMPERE1), + }, #endif { } diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c index 7d7128c651614533a8b81fc52c20353b88c3250f..f9d456fe132d87195e2e9b6f0483a1d6d1b360eb 100644 --- a/arch/arm64/kernel/cpufeature.c +++ b/arch/arm64/kernel/cpufeature.c @@ -105,11 +105,11 @@ unsigned int compat_elf_hwcap __read_mostly = COMPAT_ELF_HWCAP_DEFAULT; unsigned int compat_elf_hwcap2 __read_mostly; #endif -DECLARE_BITMAP(cpu_hwcaps, ARM64_NCAPS); -EXPORT_SYMBOL(cpu_hwcaps); -static struct arm64_cpu_capabilities const __ro_after_init *cpu_hwcaps_ptrs[ARM64_NCAPS]; +DECLARE_BITMAP(system_cpucaps, ARM64_NCAPS); +EXPORT_SYMBOL(system_cpucaps); +static struct arm64_cpu_capabilities const __ro_after_init *cpucap_ptrs[ARM64_NCAPS]; -DECLARE_BITMAP(boot_capabilities, ARM64_NCAPS); +DECLARE_BITMAP(boot_cpucaps, ARM64_NCAPS); bool arm64_use_ng_mappings = false; EXPORT_SYMBOL(arm64_use_ng_mappings); @@ -137,7 +137,7 @@ static cpumask_var_t cpu_32bit_el0_mask __cpumask_var_read_mostly; void dump_cpu_features(void) { /* file-wide pr_fmt adds "CPU features: " prefix */ - pr_emerg("0x%*pb\n", ARM64_NCAPS, &cpu_hwcaps); + pr_emerg("0x%*pb\n", ARM64_NCAPS, &system_cpucaps); } #define ARM64_CPUID_FIELDS(reg, field, min_value) \ @@ -223,6 +223,7 @@ static const struct arm64_ftr_bits ftr_id_aa64isar2[] = { ARM64_FTR_BITS(FTR_VISIBLE, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64ISAR2_EL1_CSSC_SHIFT, 4, 0), ARM64_FTR_BITS(FTR_VISIBLE, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64ISAR2_EL1_RPRFM_SHIFT, 4, 0), ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_HIGHER_SAFE, ID_AA64ISAR2_EL1_BC_SHIFT, 4, 0), + ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR2_EL1_MOPS_SHIFT, 4, 0), ARM64_FTR_BITS(FTR_VISIBLE_IF_IS_ENABLED(CONFIG_ARM64_PTR_AUTH), FTR_STRICT, FTR_EXACT, ID_AA64ISAR2_EL1_APA3_SHIFT, 4, 0), ARM64_FTR_BITS(FTR_VISIBLE_IF_IS_ENABLED(CONFIG_ARM64_PTR_AUTH), @@ -364,6 +365,7 @@ static const struct arm64_ftr_bits ftr_id_aa64mmfr0[] = { static const struct arm64_ftr_bits ftr_id_aa64mmfr1[] = { ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64MMFR1_EL1_TIDCP1_SHIFT, 4, 0), ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR1_EL1_AFP_SHIFT, 4, 0), + ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR1_EL1_HCX_SHIFT, 4, 0), ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR1_EL1_ETS_SHIFT, 4, 0), ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR1_EL1_TWED_SHIFT, 4, 0), ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR1_EL1_XNX_SHIFT, 4, 0), @@ -396,6 +398,12 @@ static const struct arm64_ftr_bits ftr_id_aa64mmfr2[] = { ARM64_FTR_END, }; +static const struct arm64_ftr_bits ftr_id_aa64mmfr3[] = { + ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64MMFR3_EL1_S1PIE_SHIFT, 4, 0), + ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64MMFR3_EL1_TCRX_SHIFT, 4, 0), + ARM64_FTR_END, +}; + static const struct arm64_ftr_bits ftr_ctr[] = { ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_EXACT, 31, 1, 1), /* RES1 */ ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, CTR_EL0_DIC_SHIFT, 1, 1), @@ -664,6 +672,8 @@ struct arm64_ftr_override __ro_after_init id_aa64smfr0_override; struct arm64_ftr_override __ro_after_init id_aa64isar1_override; struct arm64_ftr_override __ro_after_init id_aa64isar2_override; +struct arm64_ftr_override arm64_sw_feature_override; + static const struct __ftr_reg_entry { u32 sys_id; struct arm64_ftr_reg *reg; @@ -722,6 +732,7 @@ static const struct __ftr_reg_entry { ARM64_FTR_REG_OVERRIDE(SYS_ID_AA64MMFR1_EL1, ftr_id_aa64mmfr1, &id_aa64mmfr1_override), ARM64_FTR_REG(SYS_ID_AA64MMFR2_EL1, ftr_id_aa64mmfr2), + ARM64_FTR_REG(SYS_ID_AA64MMFR3_EL1, ftr_id_aa64mmfr3), /* Op1 = 0, CRn = 1, CRm = 2 */ ARM64_FTR_REG(SYS_ZCR_EL1, ftr_zcr), @@ -798,7 +809,7 @@ static u64 arm64_ftr_set_value(const struct arm64_ftr_bits *ftrp, s64 reg, return reg; } -static s64 arm64_ftr_safe_value(const struct arm64_ftr_bits *ftrp, s64 new, +s64 arm64_ftr_safe_value(const struct arm64_ftr_bits *ftrp, s64 new, s64 cur) { s64 ret = 0; @@ -954,24 +965,24 @@ extern const struct arm64_cpu_capabilities arm64_errata[]; static const struct arm64_cpu_capabilities arm64_features[]; static void __init -init_cpu_hwcaps_indirect_list_from_array(const struct arm64_cpu_capabilities *caps) +init_cpucap_indirect_list_from_array(const struct arm64_cpu_capabilities *caps) { for (; caps->matches; caps++) { if (WARN(caps->capability >= ARM64_NCAPS, "Invalid capability %d\n", caps->capability)) continue; - if (WARN(cpu_hwcaps_ptrs[caps->capability], + if (WARN(cpucap_ptrs[caps->capability], "Duplicate entry for capability %d\n", caps->capability)) continue; - cpu_hwcaps_ptrs[caps->capability] = caps; + cpucap_ptrs[caps->capability] = caps; } } -static void __init init_cpu_hwcaps_indirect_list(void) +static void __init init_cpucap_indirect_list(void) { - init_cpu_hwcaps_indirect_list_from_array(arm64_features); - init_cpu_hwcaps_indirect_list_from_array(arm64_errata); + init_cpucap_indirect_list_from_array(arm64_features); + init_cpucap_indirect_list_from_array(arm64_errata); } static void __init setup_boot_cpu_capabilities(void); @@ -1017,6 +1028,7 @@ void __init init_cpu_features(struct cpuinfo_arm64 *info) init_cpu_ftr_reg(SYS_ID_AA64MMFR0_EL1, info->reg_id_aa64mmfr0); init_cpu_ftr_reg(SYS_ID_AA64MMFR1_EL1, info->reg_id_aa64mmfr1); init_cpu_ftr_reg(SYS_ID_AA64MMFR2_EL1, info->reg_id_aa64mmfr2); + init_cpu_ftr_reg(SYS_ID_AA64MMFR3_EL1, info->reg_id_aa64mmfr3); init_cpu_ftr_reg(SYS_ID_AA64PFR0_EL1, info->reg_id_aa64pfr0); init_cpu_ftr_reg(SYS_ID_AA64PFR1_EL1, info->reg_id_aa64pfr1); init_cpu_ftr_reg(SYS_ID_AA64ZFR0_EL1, info->reg_id_aa64zfr0); @@ -1049,10 +1061,10 @@ void __init init_cpu_features(struct cpuinfo_arm64 *info) init_cpu_ftr_reg(SYS_GMID_EL1, info->reg_gmid); /* - * Initialize the indirect array of CPU hwcaps capabilities pointers - * before we handle the boot CPU below. + * Initialize the indirect array of CPU capabilities pointers before we + * handle the boot CPU below. */ - init_cpu_hwcaps_indirect_list(); + init_cpucap_indirect_list(); /* * Detect and enable early CPU capabilities based on the boot CPU, @@ -1262,6 +1274,8 @@ void update_cpu_features(int cpu, info->reg_id_aa64mmfr1, boot->reg_id_aa64mmfr1); taint |= check_update_ftr_reg(SYS_ID_AA64MMFR2_EL1, cpu, info->reg_id_aa64mmfr2, boot->reg_id_aa64mmfr2); + taint |= check_update_ftr_reg(SYS_ID_AA64MMFR3_EL1, cpu, + info->reg_id_aa64mmfr3, boot->reg_id_aa64mmfr3); taint |= check_update_ftr_reg(SYS_ID_AA64PFR0_EL1, cpu, info->reg_id_aa64pfr0, boot->reg_id_aa64pfr0); @@ -1391,6 +1405,7 @@ u64 __read_sysreg_by_encoding(u32 sys_id) read_sysreg_case(SYS_ID_AA64MMFR0_EL1); read_sysreg_case(SYS_ID_AA64MMFR1_EL1); read_sysreg_case(SYS_ID_AA64MMFR2_EL1); + read_sysreg_case(SYS_ID_AA64MMFR3_EL1); read_sysreg_case(SYS_ID_AA64ISAR0_EL1); read_sysreg_case(SYS_ID_AA64ISAR1_EL1); read_sysreg_case(SYS_ID_AA64ISAR2_EL1); @@ -1996,6 +2011,19 @@ static bool has_nested_virt_support(const struct arm64_cpu_capabilities *cap, return true; } +static bool hvhe_possible(const struct arm64_cpu_capabilities *entry, + int __unused) +{ + u64 val; + + val = read_sysreg(id_aa64mmfr1_el1); + if (!cpuid_feature_extract_unsigned_field(val, ID_AA64MMFR1_EL1_VH_SHIFT)) + return false; + + val = arm64_sw_feature_override.val & arm64_sw_feature_override.mask; + return cpuid_feature_extract_unsigned_field(val, ARM64_SW_FEATURE_OVERRIDE_HVHE); +} + #ifdef CONFIG_ARM64_PAN static void cpu_enable_pan(const struct arm64_cpu_capabilities *__unused) { @@ -2048,9 +2076,9 @@ static bool has_address_auth_cpucap(const struct arm64_cpu_capabilities *entry, static bool has_address_auth_metacap(const struct arm64_cpu_capabilities *entry, int scope) { - bool api = has_address_auth_cpucap(cpu_hwcaps_ptrs[ARM64_HAS_ADDRESS_AUTH_IMP_DEF], scope); - bool apa = has_address_auth_cpucap(cpu_hwcaps_ptrs[ARM64_HAS_ADDRESS_AUTH_ARCH_QARMA5], scope); - bool apa3 = has_address_auth_cpucap(cpu_hwcaps_ptrs[ARM64_HAS_ADDRESS_AUTH_ARCH_QARMA3], scope); + bool api = has_address_auth_cpucap(cpucap_ptrs[ARM64_HAS_ADDRESS_AUTH_IMP_DEF], scope); + bool apa = has_address_auth_cpucap(cpucap_ptrs[ARM64_HAS_ADDRESS_AUTH_ARCH_QARMA5], scope); + bool apa3 = has_address_auth_cpucap(cpucap_ptrs[ARM64_HAS_ADDRESS_AUTH_ARCH_QARMA3], scope); return apa || apa3 || api; } @@ -2186,6 +2214,11 @@ static void cpu_enable_dit(const struct arm64_cpu_capabilities *__unused) set_pstate_dit(1); } +static void cpu_enable_mops(const struct arm64_cpu_capabilities *__unused) +{ + sysreg_clear_set(sctlr_el1, 0, SCTLR_EL1_MSCEn); +} + /* Internal helper functions to match cpu capability type */ static bool cpucap_late_cpu_optional(const struct arm64_cpu_capabilities *cap) @@ -2235,11 +2268,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = { .capability = ARM64_HAS_ECV_CNTPOFF, .type = ARM64_CPUCAP_SYSTEM_FEATURE, .matches = has_cpuid_feature, - .sys_reg = SYS_ID_AA64MMFR0_EL1, - .field_pos = ID_AA64MMFR0_EL1_ECV_SHIFT, - .field_width = 4, - .sign = FTR_UNSIGNED, - .min_field_value = ID_AA64MMFR0_EL1_ECV_CNTPOFF, + ARM64_CPUID_FIELDS(ID_AA64MMFR0_EL1, ECV, CNTPOFF) }, #ifdef CONFIG_ARM64_PAN { @@ -2309,6 +2338,13 @@ static const struct arm64_cpu_capabilities arm64_features[] = { .type = ARM64_CPUCAP_SYSTEM_FEATURE, .matches = is_kvm_protected_mode, }, + { + .desc = "HCRX_EL2 register", + .capability = ARM64_HAS_HCX, + .type = ARM64_CPUCAP_STRICT_BOOT_CPU_FEATURE, + .matches = has_cpuid_feature, + ARM64_CPUID_FIELDS(ID_AA64MMFR1_EL1, HCX, IMP) + }, #endif { .desc = "Kernel page table isolation (KPTI)", @@ -2641,6 +2677,44 @@ static const struct arm64_cpu_capabilities arm64_features[] = { .cpu_enable = cpu_enable_dit, ARM64_CPUID_FIELDS(ID_AA64PFR0_EL1, DIT, IMP) }, + { + .desc = "Memory Copy and Memory Set instructions", + .capability = ARM64_HAS_MOPS, + .type = ARM64_CPUCAP_SYSTEM_FEATURE, + .matches = has_cpuid_feature, + .cpu_enable = cpu_enable_mops, + ARM64_CPUID_FIELDS(ID_AA64ISAR2_EL1, MOPS, IMP) + }, + { + .capability = ARM64_HAS_TCR2, + .type = ARM64_CPUCAP_SYSTEM_FEATURE, + .matches = has_cpuid_feature, + ARM64_CPUID_FIELDS(ID_AA64MMFR3_EL1, TCRX, IMP) + }, + { + .desc = "Stage-1 Permission Indirection Extension (S1PIE)", + .capability = ARM64_HAS_S1PIE, + .type = ARM64_CPUCAP_BOOT_CPU_FEATURE, + .matches = has_cpuid_feature, + ARM64_CPUID_FIELDS(ID_AA64MMFR3_EL1, S1PIE, IMP) + }, + { + .desc = "VHE for hypervisor only", + .capability = ARM64_KVM_HVHE, + .type = ARM64_CPUCAP_SYSTEM_FEATURE, + .matches = hvhe_possible, + }, + { + .desc = "Enhanced Virtualization Traps", + .capability = ARM64_HAS_EVT, + .type = ARM64_CPUCAP_SYSTEM_FEATURE, + .sys_reg = SYS_ID_AA64MMFR2_EL1, + .sign = FTR_UNSIGNED, + .field_pos = ID_AA64MMFR2_EL1_EVT_SHIFT, + .field_width = 4, + .min_field_value = ID_AA64MMFR2_EL1_EVT_IMP, + .matches = has_cpuid_feature, + }, {}, }; @@ -2769,6 +2843,7 @@ static const struct arm64_cpu_capabilities arm64_elf_hwcaps[] = { HWCAP_CAP(ID_AA64ISAR2_EL1, RPRFM, IMP, CAP_HWCAP, KERNEL_HWCAP_RPRFM), HWCAP_CAP(ID_AA64ISAR2_EL1, RPRES, IMP, CAP_HWCAP, KERNEL_HWCAP_RPRES), HWCAP_CAP(ID_AA64ISAR2_EL1, WFxT, IMP, CAP_HWCAP, KERNEL_HWCAP_WFXT), + HWCAP_CAP(ID_AA64ISAR2_EL1, MOPS, IMP, CAP_HWCAP, KERNEL_HWCAP_MOPS), #ifdef CONFIG_ARM64_SME HWCAP_CAP(ID_AA64PFR1_EL1, SME, IMP, CAP_HWCAP, KERNEL_HWCAP_SME), HWCAP_CAP(ID_AA64SMFR0_EL1, FA64, IMP, CAP_HWCAP, KERNEL_HWCAP_SME_FA64), @@ -2895,7 +2970,7 @@ static void update_cpu_capabilities(u16 scope_mask) scope_mask &= ARM64_CPUCAP_SCOPE_MASK; for (i = 0; i < ARM64_NCAPS; i++) { - caps = cpu_hwcaps_ptrs[i]; + caps = cpucap_ptrs[i]; if (!caps || !(caps->type & scope_mask) || cpus_have_cap(caps->capability) || !caps->matches(caps, cpucap_default_scope(caps))) @@ -2903,10 +2978,11 @@ static void update_cpu_capabilities(u16 scope_mask) if (caps->desc) pr_info("detected: %s\n", caps->desc); - cpus_set_cap(caps->capability); + + __set_bit(caps->capability, system_cpucaps); if ((scope_mask & SCOPE_BOOT_CPU) && (caps->type & SCOPE_BOOT_CPU)) - set_bit(caps->capability, boot_capabilities); + set_bit(caps->capability, boot_cpucaps); } } @@ -2920,7 +2996,7 @@ static int cpu_enable_non_boot_scope_capabilities(void *__unused) u16 non_boot_scope = SCOPE_ALL & ~SCOPE_BOOT_CPU; for_each_available_cap(i) { - const struct arm64_cpu_capabilities *cap = cpu_hwcaps_ptrs[i]; + const struct arm64_cpu_capabilities *cap = cpucap_ptrs[i]; if (WARN_ON(!cap)) continue; @@ -2950,7 +3026,7 @@ static void __init enable_cpu_capabilities(u16 scope_mask) for (i = 0; i < ARM64_NCAPS; i++) { unsigned int num; - caps = cpu_hwcaps_ptrs[i]; + caps = cpucap_ptrs[i]; if (!caps || !(caps->type & scope_mask)) continue; num = caps->capability; @@ -2995,7 +3071,7 @@ static void verify_local_cpu_caps(u16 scope_mask) scope_mask &= ARM64_CPUCAP_SCOPE_MASK; for (i = 0; i < ARM64_NCAPS; i++) { - caps = cpu_hwcaps_ptrs[i]; + caps = cpucap_ptrs[i]; if (!caps || !(caps->type & scope_mask)) continue; @@ -3194,7 +3270,7 @@ static void __init setup_boot_cpu_capabilities(void) bool this_cpu_has_cap(unsigned int n) { if (!WARN_ON(preemptible()) && n < ARM64_NCAPS) { - const struct arm64_cpu_capabilities *cap = cpu_hwcaps_ptrs[n]; + const struct arm64_cpu_capabilities *cap = cpucap_ptrs[n]; if (cap) return cap->matches(cap, SCOPE_LOCAL_CPU); @@ -3207,13 +3283,13 @@ EXPORT_SYMBOL_GPL(this_cpu_has_cap); /* * This helper function is used in a narrow window when, * - The system wide safe registers are set with all the SMP CPUs and, - * - The SYSTEM_FEATURE cpu_hwcaps may not have been set. + * - The SYSTEM_FEATURE system_cpucaps may not have been set. * In all other cases cpus_have_{const_}cap() should be used. */ static bool __maybe_unused __system_matches_cap(unsigned int n) { if (n < ARM64_NCAPS) { - const struct arm64_cpu_capabilities *cap = cpu_hwcaps_ptrs[n]; + const struct arm64_cpu_capabilities *cap = cpucap_ptrs[n]; if (cap) return cap->matches(cap, SCOPE_SYSTEM); diff --git a/arch/arm64/kernel/cpuidle.c b/arch/arm64/kernel/cpuidle.c index 42e19fff40ee6561bed424de57f00b0ecf46e01b..d1f68599c29fe2826d8caca15f0c85bfa703f3fd 100644 --- a/arch/arm64/kernel/cpuidle.c +++ b/arch/arm64/kernel/cpuidle.c @@ -13,7 +13,7 @@ #include #include -#ifdef CONFIG_ACPI +#ifdef CONFIG_ACPI_PROCESSOR_IDLE #include diff --git a/arch/arm64/kernel/cpuinfo.c b/arch/arm64/kernel/cpuinfo.c index eb4378c23b3c3ed13287cb8df2b4f89987c4f6c2..58622dc859177d17a0db3f81bb5df594aac03114 100644 --- a/arch/arm64/kernel/cpuinfo.c +++ b/arch/arm64/kernel/cpuinfo.c @@ -125,6 +125,7 @@ static const char *const hwcap_str[] = { [KERNEL_HWCAP_SME_BI32I32] = "smebi32i32", [KERNEL_HWCAP_SME_B16B16] = "smeb16b16", [KERNEL_HWCAP_SME_F16F16] = "smef16f16", + [KERNEL_HWCAP_MOPS] = "mops", }; #ifdef CONFIG_COMPAT @@ -446,6 +447,7 @@ static void __cpuinfo_store_cpu(struct cpuinfo_arm64 *info) info->reg_id_aa64mmfr0 = read_cpuid(ID_AA64MMFR0_EL1); info->reg_id_aa64mmfr1 = read_cpuid(ID_AA64MMFR1_EL1); info->reg_id_aa64mmfr2 = read_cpuid(ID_AA64MMFR2_EL1); + info->reg_id_aa64mmfr3 = read_cpuid(ID_AA64MMFR3_EL1); info->reg_id_aa64pfr0 = read_cpuid(ID_AA64PFR0_EL1); info->reg_id_aa64pfr1 = read_cpuid(ID_AA64PFR1_EL1); info->reg_id_aa64zfr0 = read_cpuid(ID_AA64ZFR0_EL1); diff --git a/arch/arm64/kernel/entry-common.c b/arch/arm64/kernel/entry-common.c index 3af3c01c93a65ad5f1b7a70b6c627722f68594d8..6b2e0c367702c17c3185c319e350940ebfe43039 100644 --- a/arch/arm64/kernel/entry-common.c +++ b/arch/arm64/kernel/entry-common.c @@ -126,7 +126,7 @@ static __always_inline void __exit_to_user_mode(void) lockdep_hardirqs_on(CALLER_ADDR0); } -static __always_inline void prepare_exit_to_user_mode(struct pt_regs *regs) +static __always_inline void exit_to_user_mode_prepare(struct pt_regs *regs) { unsigned long flags; @@ -135,11 +135,13 @@ static __always_inline void prepare_exit_to_user_mode(struct pt_regs *regs) flags = read_thread_flags(); if (unlikely(flags & _TIF_WORK_MASK)) do_notify_resume(regs, flags); + + lockdep_sys_exit(); } static __always_inline void exit_to_user_mode(struct pt_regs *regs) { - prepare_exit_to_user_mode(regs); + exit_to_user_mode_prepare(regs); mte_check_tfsr_exit(); __exit_to_user_mode(); } @@ -611,6 +613,14 @@ static void noinstr el0_bti(struct pt_regs *regs) exit_to_user_mode(regs); } +static void noinstr el0_mops(struct pt_regs *regs, unsigned long esr) +{ + enter_from_user_mode(regs); + local_daif_restore(DAIF_PROCCTX); + do_el0_mops(regs, esr); + exit_to_user_mode(regs); +} + static void noinstr el0_inv(struct pt_regs *regs, unsigned long esr) { enter_from_user_mode(regs); @@ -688,6 +698,9 @@ asmlinkage void noinstr el0t_64_sync_handler(struct pt_regs *regs) case ESR_ELx_EC_BTI: el0_bti(regs); break; + case ESR_ELx_EC_MOPS: + el0_mops(regs, esr); + break; case ESR_ELx_EC_BREAKPT_LOW: case ESR_ELx_EC_SOFTSTP_LOW: case ESR_ELx_EC_WATCHPT_LOW: diff --git a/arch/arm64/kernel/entry-ftrace.S b/arch/arm64/kernel/entry-ftrace.S index 1c38a60575aa39049e45b3cfc9b33c1ffe22bd57..f0c16640ef215ab5e34846a9ad950e351e2a6dda 100644 --- a/arch/arm64/kernel/entry-ftrace.S +++ b/arch/arm64/kernel/entry-ftrace.S @@ -330,22 +330,23 @@ SYM_FUNC_END(ftrace_stub_graph) */ SYM_CODE_START(return_to_handler) /* save return value regs */ - sub sp, sp, #64 - stp x0, x1, [sp] - stp x2, x3, [sp, #16] - stp x4, x5, [sp, #32] - stp x6, x7, [sp, #48] + sub sp, sp, #FGRET_REGS_SIZE + stp x0, x1, [sp, #FGRET_REGS_X0] + stp x2, x3, [sp, #FGRET_REGS_X2] + stp x4, x5, [sp, #FGRET_REGS_X4] + stp x6, x7, [sp, #FGRET_REGS_X6] + str x29, [sp, #FGRET_REGS_FP] // parent's fp - mov x0, x29 // parent's fp - bl ftrace_return_to_handler// addr = ftrace_return_to_hander(fp); - mov x30, x0 // restore the original return address + mov x0, sp + bl ftrace_return_to_handler // addr = ftrace_return_to_hander(regs); + mov x30, x0 // restore the original return address /* restore return value regs */ - ldp x0, x1, [sp] - ldp x2, x3, [sp, #16] - ldp x4, x5, [sp, #32] - ldp x6, x7, [sp, #48] - add sp, sp, #64 + ldp x0, x1, [sp, #FGRET_REGS_X0] + ldp x2, x3, [sp, #FGRET_REGS_X2] + ldp x4, x5, [sp, #FGRET_REGS_X4] + ldp x6, x7, [sp, #FGRET_REGS_X6] + add sp, sp, #FGRET_REGS_SIZE ret SYM_CODE_END(return_to_handler) diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S index ab2a6e33c0528d82d4792ebe48385f0e7ca485a0..a40e5e50fa55232e1e06557daca255ae3741cd5f 100644 --- a/arch/arm64/kernel/entry.S +++ b/arch/arm64/kernel/entry.S @@ -101,12 +101,11 @@ .org .Lventry_start\@ + 128 // Did we overflow the ventry slot? .endm - .macro tramp_alias, dst, sym, tmp - mov_q \dst, TRAMP_VALIAS - adr_l \tmp, \sym - add \dst, \dst, \tmp - adr_l \tmp, .entry.tramp.text - sub \dst, \dst, \tmp + .macro tramp_alias, dst, sym + .set .Lalias\@, TRAMP_VALIAS + \sym - .entry.tramp.text + movz \dst, :abs_g2_s:.Lalias\@ + movk \dst, :abs_g1_nc:.Lalias\@ + movk \dst, :abs_g0_nc:.Lalias\@ .endm /* @@ -435,13 +434,14 @@ alternative_if_not ARM64_UNMAP_KERNEL_AT_EL0 eret alternative_else_nop_endif #ifdef CONFIG_UNMAP_KERNEL_AT_EL0 - bne 4f msr far_el1, x29 - tramp_alias x30, tramp_exit_native, x29 - br x30 -4: - tramp_alias x30, tramp_exit_compat, x29 - br x30 + + ldr_this_cpu x30, this_cpu_vector, x29 + tramp_alias x29, tramp_exit + msr vbar_el1, x30 // install vector table + ldr lr, [sp, #S_LR] // restore x30 + add sp, sp, #PT_REGS_SIZE // restore sp + br x29 #endif .else ldr lr, [sp, #S_LR] @@ -732,22 +732,6 @@ alternative_else_nop_endif .org 1b + 128 // Did we overflow the ventry slot? .endm - .macro tramp_exit, regsize = 64 - tramp_data_read_var x30, this_cpu_vector - get_this_cpu_offset x29 - ldr x30, [x30, x29] - - msr vbar_el1, x30 - ldr lr, [sp, #S_LR] - tramp_unmap_kernel x29 - .if \regsize == 64 - mrs x29, far_el1 - .endif - add sp, sp, #PT_REGS_SIZE // restore sp - eret - sb - .endm - .macro generate_tramp_vector, kpti, bhb .Lvector_start\@: .space 0x400 @@ -768,7 +752,7 @@ alternative_else_nop_endif */ .pushsection ".entry.tramp.text", "ax" .align 11 -SYM_CODE_START_NOALIGN(tramp_vectors) +SYM_CODE_START_LOCAL_NOALIGN(tramp_vectors) #ifdef CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY generate_tramp_vector kpti=1, bhb=BHB_MITIGATION_LOOP generate_tramp_vector kpti=1, bhb=BHB_MITIGATION_FW @@ -777,13 +761,12 @@ SYM_CODE_START_NOALIGN(tramp_vectors) generate_tramp_vector kpti=1, bhb=BHB_MITIGATION_NONE SYM_CODE_END(tramp_vectors) -SYM_CODE_START(tramp_exit_native) - tramp_exit -SYM_CODE_END(tramp_exit_native) - -SYM_CODE_START(tramp_exit_compat) - tramp_exit 32 -SYM_CODE_END(tramp_exit_compat) +SYM_CODE_START_LOCAL(tramp_exit) + tramp_unmap_kernel x29 + mrs x29, far_el1 // restore x29 + eret + sb +SYM_CODE_END(tramp_exit) .popsection // .entry.tramp.text #endif /* CONFIG_UNMAP_KERNEL_AT_EL0 */ @@ -1077,7 +1060,7 @@ alternative_if_not ARM64_UNMAP_KERNEL_AT_EL0 alternative_else_nop_endif #ifdef CONFIG_UNMAP_KERNEL_AT_EL0 - tramp_alias dst=x5, sym=__sdei_asm_exit_trampoline, tmp=x3 + tramp_alias dst=x5, sym=__sdei_asm_exit_trampoline br x5 #endif SYM_CODE_END(__sdei_asm_handler) diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c index 2fbafa5cc7ac101d635a8763a105da8f1831d826..7a1aeb95d7c3d416251c8ad3489d68a54cb60e8d 100644 --- a/arch/arm64/kernel/fpsimd.c +++ b/arch/arm64/kernel/fpsimd.c @@ -1649,6 +1649,7 @@ void fpsimd_flush_thread(void) fpsimd_flush_thread_vl(ARM64_VEC_SME); current->thread.svcr = 0; + sme_smstop(); } current->thread.fp_type = FP_STATE_FPSIMD; diff --git a/arch/arm64/kernel/ftrace.c b/arch/arm64/kernel/ftrace.c index 432626c866a87d2c49b61c8ee05d120f2b4a35fe..a650f5e11fc5d8614a4656b92cce3c4c446eb16f 100644 --- a/arch/arm64/kernel/ftrace.c +++ b/arch/arm64/kernel/ftrace.c @@ -197,7 +197,7 @@ int ftrace_update_ftrace_func(ftrace_func_t func) static struct plt_entry *get_ftrace_plt(struct module *mod) { -#ifdef CONFIG_ARM64_MODULE_PLTS +#ifdef CONFIG_MODULES struct plt_entry *plt = mod->arch.ftrace_trampolines; return &plt[FTRACE_PLT_IDX]; @@ -249,7 +249,7 @@ static bool ftrace_find_callable_addr(struct dyn_ftrace *rec, * must use a PLT to reach it. We can only place PLTs for modules, and * only when module PLT support is built-in. */ - if (!IS_ENABLED(CONFIG_ARM64_MODULE_PLTS)) + if (!IS_ENABLED(CONFIG_MODULES)) return false; /* @@ -431,10 +431,8 @@ int ftrace_make_nop(struct module *mod, struct dyn_ftrace *rec, * * Note: 'mod' is only set at module load time. */ - if (!IS_ENABLED(CONFIG_DYNAMIC_FTRACE_WITH_ARGS) && - IS_ENABLED(CONFIG_ARM64_MODULE_PLTS) && mod) { + if (!IS_ENABLED(CONFIG_DYNAMIC_FTRACE_WITH_ARGS) && mod) return aarch64_insn_patch_text_nosync((void *)pc, new); - } if (!ftrace_find_callable_addr(rec, mod, &addr)) return -EINVAL; diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S index e92caebff46a03479c17fbd8001bf9c69789923f..757a0de07f91bbe0ad6261d11bcab9a5ddcd2cac 100644 --- a/arch/arm64/kernel/head.S +++ b/arch/arm64/kernel/head.S @@ -382,7 +382,7 @@ SYM_FUNC_START_LOCAL(create_idmap) adrp x0, init_idmap_pg_dir adrp x3, _text adrp x6, _end + MAX_FDT_SIZE + SWAPPER_BLOCK_SIZE - mov x7, SWAPPER_RX_MMUFLAGS + mov_q x7, SWAPPER_RX_MMUFLAGS map_memory x0, x1, x3, x6, x7, x3, IDMAP_PGD_ORDER, x10, x11, x12, x13, x14, EXTRA_SHIFT @@ -391,7 +391,7 @@ SYM_FUNC_START_LOCAL(create_idmap) adrp x2, init_pg_dir adrp x3, init_pg_end bic x4, x2, #SWAPPER_BLOCK_SIZE - 1 - mov x5, SWAPPER_RW_MMUFLAGS + mov_q x5, SWAPPER_RW_MMUFLAGS mov x6, #SWAPPER_BLOCK_SHIFT bl remap_region @@ -402,7 +402,7 @@ SYM_FUNC_START_LOCAL(create_idmap) bfi x22, x21, #0, #SWAPPER_BLOCK_SHIFT // remapped FDT address add x3, x2, #MAX_FDT_SIZE + SWAPPER_BLOCK_SIZE bic x4, x21, #SWAPPER_BLOCK_SIZE - 1 - mov x5, SWAPPER_RW_MMUFLAGS + mov_q x5, SWAPPER_RW_MMUFLAGS mov x6, #SWAPPER_BLOCK_SHIFT bl remap_region @@ -430,7 +430,7 @@ SYM_FUNC_START_LOCAL(create_kernel_mapping) adrp x3, _text // runtime __pa(_text) sub x6, x6, x3 // _end - _text add x6, x6, x5 // runtime __va(_end) - mov x7, SWAPPER_RW_MMUFLAGS + mov_q x7, SWAPPER_RW_MMUFLAGS map_memory x0, x1, x5, x6, x7, x3, (VA_BITS - PGDIR_SHIFT), x10, x11, x12, x13, x14 @@ -603,6 +603,8 @@ SYM_INNER_LABEL(init_el2, SYM_L_LOCAL) msr sctlr_el1, x1 mov x2, xzr 2: + __init_el2_nvhe_prepare_eret + mov w0, #BOOT_CPU_MODE_EL2 orr x0, x0, x2 eret diff --git a/arch/arm64/kernel/hibernate.c b/arch/arm64/kernel/hibernate.c index 788597a6b6a2f01ddfa7eae4c67802b3d50d359e..02870beb271ed35ccbbb7a3dad71399502974946 100644 --- a/arch/arm64/kernel/hibernate.c +++ b/arch/arm64/kernel/hibernate.c @@ -99,7 +99,6 @@ int pfn_is_nosave(unsigned long pfn) void notrace save_processor_state(void) { - WARN_ON(num_online_cpus() != 1); } void notrace restore_processor_state(void) diff --git a/arch/arm64/kernel/hw_breakpoint.c b/arch/arm64/kernel/hw_breakpoint.c index b29a311bb055216aa4ab111cf10c322e4042c923..db2a1861bb97810155b86af52c1a083b442ba50b 100644 --- a/arch/arm64/kernel/hw_breakpoint.c +++ b/arch/arm64/kernel/hw_breakpoint.c @@ -973,14 +973,6 @@ static int hw_breakpoint_reset(unsigned int cpu) return 0; } -#ifdef CONFIG_CPU_PM -extern void cpu_suspend_set_dbg_restorer(int (*hw_bp_restore)(unsigned int)); -#else -static inline void cpu_suspend_set_dbg_restorer(int (*hw_bp_restore)(unsigned int)) -{ -} -#endif - /* * One-time initialisation. */ diff --git a/arch/arm64/kernel/hyp-stub.S b/arch/arm64/kernel/hyp-stub.S index 9439240c3fcf37dca6e043958f2da25ecb8c0e64..65f76064c86b24db53795ea420efe56f4a21172d 100644 --- a/arch/arm64/kernel/hyp-stub.S +++ b/arch/arm64/kernel/hyp-stub.S @@ -82,7 +82,15 @@ SYM_CODE_START_LOCAL(__finalise_el2) tbnz x1, #0, 1f // Needs to be VHE capable, obviously - check_override id_aa64mmfr1 ID_AA64MMFR1_EL1_VH_SHIFT 2f 1f x1 x2 + check_override id_aa64mmfr1 ID_AA64MMFR1_EL1_VH_SHIFT 0f 1f x1 x2 + +0: // Check whether we only want the hypervisor to run VHE, not the kernel + adr_l x1, arm64_sw_feature_override + ldr x2, [x1, FTR_OVR_VAL_OFFSET] + ldr x1, [x1, FTR_OVR_MASK_OFFSET] + and x2, x2, x1 + ubfx x2, x2, #ARM64_SW_FEATURE_OVERRIDE_HVHE, #4 + cbz x2, 2f 1: mov_q x0, HVC_STUB_ERR eret @@ -119,6 +127,24 @@ SYM_CODE_START_LOCAL(__finalise_el2) msr ttbr1_el1, x0 mrs_s x0, SYS_MAIR_EL12 msr mair_el1, x0 + mrs x1, REG_ID_AA64MMFR3_EL1 + ubfx x1, x1, #ID_AA64MMFR3_EL1_TCRX_SHIFT, #4 + cbz x1, .Lskip_tcr2 + mrs x0, REG_TCR2_EL12 + msr REG_TCR2_EL1, x0 + + // Transfer permission indirection state + mrs x1, REG_ID_AA64MMFR3_EL1 + ubfx x1, x1, #ID_AA64MMFR3_EL1_S1PIE_SHIFT, #4 + cbz x1, .Lskip_indirection + mrs x0, REG_PIRE0_EL12 + msr REG_PIRE0_EL1, x0 + mrs x0, REG_PIR_EL12 + msr REG_PIR_EL1, x0 + +.Lskip_indirection: +.Lskip_tcr2: + isb // Hack the exception return to stay at EL2 diff --git a/arch/arm64/kernel/idreg-override.c b/arch/arm64/kernel/idreg-override.c index 370ab84fd06e2eaca9a057ec52d2bd94b50df5d3..2fe2491b692cd767f902f8f71d05fdcb751e68d2 100644 --- a/arch/arm64/kernel/idreg-override.c +++ b/arch/arm64/kernel/idreg-override.c @@ -123,6 +123,7 @@ static const struct ftr_set_desc isar2 __initconst = { .fields = { FIELD("gpa3", ID_AA64ISAR2_EL1_GPA3_SHIFT, NULL), FIELD("apa3", ID_AA64ISAR2_EL1_APA3_SHIFT, NULL), + FIELD("mops", ID_AA64ISAR2_EL1_MOPS_SHIFT, NULL), {} }, }; @@ -138,15 +139,22 @@ static const struct ftr_set_desc smfr0 __initconst = { }, }; -extern struct arm64_ftr_override kaslr_feature_override; +static bool __init hvhe_filter(u64 val) +{ + u64 mmfr1 = read_sysreg(id_aa64mmfr1_el1); + + return (val == 1 && + lower_32_bits(__boot_status) == BOOT_CPU_MODE_EL2 && + cpuid_feature_extract_unsigned_field(mmfr1, + ID_AA64MMFR1_EL1_VH_SHIFT)); +} -static const struct ftr_set_desc kaslr __initconst = { - .name = "kaslr", -#ifdef CONFIG_RANDOMIZE_BASE - .override = &kaslr_feature_override, -#endif +static const struct ftr_set_desc sw_features __initconst = { + .name = "arm64_sw", + .override = &arm64_sw_feature_override, .fields = { - FIELD("disabled", 0, NULL), + FIELD("nokaslr", ARM64_SW_FEATURE_OVERRIDE_NOKASLR, NULL), + FIELD("hvhe", ARM64_SW_FEATURE_OVERRIDE_HVHE, hvhe_filter), {} }, }; @@ -158,7 +166,7 @@ static const struct ftr_set_desc * const regs[] __initconst = { &isar1, &isar2, &smfr0, - &kaslr, + &sw_features, }; static const struct { @@ -174,8 +182,9 @@ static const struct { "id_aa64isar1.gpi=0 id_aa64isar1.gpa=0 " "id_aa64isar1.api=0 id_aa64isar1.apa=0 " "id_aa64isar2.gpa3=0 id_aa64isar2.apa3=0" }, + { "arm64.nomops", "id_aa64isar2.mops=0" }, { "arm64.nomte", "id_aa64pfr1.mte=0" }, - { "nokaslr", "kaslr.disabled=1" }, + { "nokaslr", "arm64_sw.nokaslr=1" }, }; static int __init parse_nokaslr(char *unused) diff --git a/arch/arm64/kernel/kaslr.c b/arch/arm64/kernel/kaslr.c index e7477f21a4c9d062ee4909d6bcc72cdf555ab02a..94a269cd1f07a0e9b2fa7d338f8232318c298449 100644 --- a/arch/arm64/kernel/kaslr.c +++ b/arch/arm64/kernel/kaslr.c @@ -4,90 +4,35 @@ */ #include -#include #include -#include -#include -#include -#include -#include -#include +#include -#include -#include +#include #include -#include -#include -#include -u64 __ro_after_init module_alloc_base; u16 __initdata memstart_offset_seed; -struct arm64_ftr_override kaslr_feature_override __initdata; +bool __ro_after_init __kaslr_is_enabled = false; -static int __init kaslr_init(void) +void __init kaslr_init(void) { - u64 module_range; - u32 seed; - - /* - * Set a reasonable default for module_alloc_base in case - * we end up running with module randomization disabled. - */ - module_alloc_base = (u64)_etext - MODULES_VSIZE; - - if (kaslr_feature_override.val & kaslr_feature_override.mask & 0xf) { + if (cpuid_feature_extract_unsigned_field(arm64_sw_feature_override.val & + arm64_sw_feature_override.mask, + ARM64_SW_FEATURE_OVERRIDE_NOKASLR)) { pr_info("KASLR disabled on command line\n"); - return 0; - } - - if (!kaslr_enabled()) { - pr_warn("KASLR disabled due to lack of seed\n"); - return 0; + return; } - pr_info("KASLR enabled\n"); - /* - * KASAN without KASAN_VMALLOC does not expect the module region to - * intersect the vmalloc region, since shadow memory is allocated for - * each module at load time, whereas the vmalloc region will already be - * shadowed by KASAN zero pages. + * The KASLR offset modulo MIN_KIMG_ALIGN is taken from the physical + * placement of the image rather than from the seed, so a displacement + * of less than MIN_KIMG_ALIGN means that no seed was provided. */ - BUILD_BUG_ON((IS_ENABLED(CONFIG_KASAN_GENERIC) || - IS_ENABLED(CONFIG_KASAN_SW_TAGS)) && - !IS_ENABLED(CONFIG_KASAN_VMALLOC)); - - seed = get_random_u32(); - - if (IS_ENABLED(CONFIG_RANDOMIZE_MODULE_REGION_FULL)) { - /* - * Randomize the module region over a 2 GB window covering the - * kernel. This reduces the risk of modules leaking information - * about the address of the kernel itself, but results in - * branches between modules and the core kernel that are - * resolved via PLTs. (Branches between modules will be - * resolved normally.) - */ - module_range = SZ_2G - (u64)(_end - _stext); - module_alloc_base = max((u64)_end - SZ_2G, (u64)MODULES_VADDR); - } else { - /* - * Randomize the module region by setting module_alloc_base to - * a PAGE_SIZE multiple in the range [_etext - MODULES_VSIZE, - * _stext) . This guarantees that the resulting region still - * covers [_stext, _etext], and that all relative branches can - * be resolved without veneers unless this region is exhausted - * and we fall back to a larger 2GB window in module_alloc() - * when ARM64_MODULE_PLTS is enabled. - */ - module_range = MODULES_VSIZE - (u64)(_etext - _stext); + if (kaslr_offset() < MIN_KIMG_ALIGN) { + pr_warn("KASLR disabled due to lack of seed\n"); + return; } - /* use the lower 21 bits to randomize the base of the module region */ - module_alloc_base += (module_range * (seed & ((1 << 21) - 1))) >> 21; - module_alloc_base &= PAGE_MASK; - - return 0; + pr_info("KASLR enabled\n"); + __kaslr_is_enabled = true; } -subsys_initcall(kaslr_init) diff --git a/arch/arm64/kernel/kexec_image.c b/arch/arm64/kernel/kexec_image.c index 5ed6a585f21fdedfa99deeddb07a05f27c2d2060..636be671515575c677cb1743b61d444a088daac2 100644 --- a/arch/arm64/kernel/kexec_image.c +++ b/arch/arm64/kernel/kexec_image.c @@ -48,7 +48,7 @@ static void *image_load(struct kimage *image, /* * We require a kernel with an unambiguous Image header. Per - * Documentation/arm64/booting.rst, this is the case when image_size + * Documentation/arch/arm64/booting.rst, this is the case when image_size * is non-zero (practically speaking, since v3.17). */ h = (struct arm64_image_header *)kernel; diff --git a/arch/arm64/kernel/kuser32.S b/arch/arm64/kernel/kuser32.S index 692e9d2e31e5d8eeb912ae603d83a27012904f5b..af046ceac22deabbd7c5cd61adeecaba86f117b3 100644 --- a/arch/arm64/kernel/kuser32.S +++ b/arch/arm64/kernel/kuser32.S @@ -10,7 +10,7 @@ * aarch32_setup_additional_pages() and are provided for compatibility * reasons with 32 bit (aarch32) applications that need them. * - * See Documentation/arm/kernel_user_helpers.rst for formal definitions. + * See Documentation/arch/arm/kernel_user_helpers.rst for formal definitions. */ #include diff --git a/arch/arm64/kernel/module-plts.c b/arch/arm64/kernel/module-plts.c index 543493bf924d2456eae425ca4dd20e46a4e15b6d..ad02058756b5083329cc004c5bf1586c158416a4 100644 --- a/arch/arm64/kernel/module-plts.c +++ b/arch/arm64/kernel/module-plts.c @@ -7,6 +7,7 @@ #include #include #include +#include #include static struct plt_entry __get_adrp_add_pair(u64 dst, u64 pc, diff --git a/arch/arm64/kernel/module.c b/arch/arm64/kernel/module.c index 5af4975caeb58ff7a15ce14444cda1258ab2bc56..dd851297596e5e9372bf4f64f640283181e86395 100644 --- a/arch/arm64/kernel/module.c +++ b/arch/arm64/kernel/module.c @@ -7,6 +7,8 @@ * Author: Will Deacon */ +#define pr_fmt(fmt) "Modules: " fmt + #include #include #include @@ -15,52 +17,131 @@ #include #include #include +#include #include #include + #include #include #include #include +static u64 module_direct_base __ro_after_init = 0; +static u64 module_plt_base __ro_after_init = 0; + +/* + * Choose a random page-aligned base address for a window of 'size' bytes which + * entirely contains the interval [start, end - 1]. + */ +static u64 __init random_bounding_box(u64 size, u64 start, u64 end) +{ + u64 max_pgoff, pgoff; + + if ((end - start) >= size) + return 0; + + max_pgoff = (size - (end - start)) / PAGE_SIZE; + pgoff = get_random_u32_inclusive(0, max_pgoff); + + return start - pgoff * PAGE_SIZE; +} + +/* + * Modules may directly reference data and text anywhere within the kernel + * image and other modules. References using PREL32 relocations have a +/-2G + * range, and so we need to ensure that the entire kernel image and all modules + * fall within a 2G window such that these are always within range. + * + * Modules may directly branch to functions and code within the kernel text, + * and to functions and code within other modules. These branches will use + * CALL26/JUMP26 relocations with a +/-128M range. Without PLTs, we must ensure + * that the entire kernel text and all module text falls within a 128M window + * such that these are always within range. With PLTs, we can expand this to a + * 2G window. + * + * We chose the 128M region to surround the entire kernel image (rather than + * just the text) as using the same bounds for the 128M and 2G regions ensures + * by construction that we never select a 128M region that is not a subset of + * the 2G region. For very large and unusual kernel configurations this means + * we may fall back to PLTs where they could have been avoided, but this keeps + * the logic significantly simpler. + */ +static int __init module_init_limits(void) +{ + u64 kernel_end = (u64)_end; + u64 kernel_start = (u64)_text; + u64 kernel_size = kernel_end - kernel_start; + + /* + * The default modules region is placed immediately below the kernel + * image, and is large enough to use the full 2G relocation range. + */ + BUILD_BUG_ON(KIMAGE_VADDR != MODULES_END); + BUILD_BUG_ON(MODULES_VSIZE < SZ_2G); + + if (!kaslr_enabled()) { + if (kernel_size < SZ_128M) + module_direct_base = kernel_end - SZ_128M; + if (kernel_size < SZ_2G) + module_plt_base = kernel_end - SZ_2G; + } else { + u64 min = kernel_start; + u64 max = kernel_end; + + if (IS_ENABLED(CONFIG_RANDOMIZE_MODULE_REGION_FULL)) { + pr_info("2G module region forced by RANDOMIZE_MODULE_REGION_FULL\n"); + } else { + module_direct_base = random_bounding_box(SZ_128M, min, max); + if (module_direct_base) { + min = module_direct_base; + max = module_direct_base + SZ_128M; + } + } + + module_plt_base = random_bounding_box(SZ_2G, min, max); + } + + pr_info("%llu pages in range for non-PLT usage", + module_direct_base ? (SZ_128M - kernel_size) / PAGE_SIZE : 0); + pr_info("%llu pages in range for PLT usage", + module_plt_base ? (SZ_2G - kernel_size) / PAGE_SIZE : 0); + + return 0; +} +subsys_initcall(module_init_limits); + void *module_alloc(unsigned long size) { - u64 module_alloc_end = module_alloc_base + MODULES_VSIZE; - gfp_t gfp_mask = GFP_KERNEL; - void *p; - - /* Silence the initial allocation */ - if (IS_ENABLED(CONFIG_ARM64_MODULE_PLTS)) - gfp_mask |= __GFP_NOWARN; - - if (IS_ENABLED(CONFIG_KASAN_GENERIC) || - IS_ENABLED(CONFIG_KASAN_SW_TAGS)) - /* don't exceed the static module region - see below */ - module_alloc_end = MODULES_END; - - p = __vmalloc_node_range(size, MODULE_ALIGN, module_alloc_base, - module_alloc_end, gfp_mask, PAGE_KERNEL, VM_DEFER_KMEMLEAK, - NUMA_NO_NODE, __builtin_return_address(0)); - - if (!p && IS_ENABLED(CONFIG_ARM64_MODULE_PLTS) && - (IS_ENABLED(CONFIG_KASAN_VMALLOC) || - (!IS_ENABLED(CONFIG_KASAN_GENERIC) && - !IS_ENABLED(CONFIG_KASAN_SW_TAGS)))) - /* - * KASAN without KASAN_VMALLOC can only deal with module - * allocations being served from the reserved module region, - * since the remainder of the vmalloc region is already - * backed by zero shadow pages, and punching holes into it - * is non-trivial. Since the module region is not randomized - * when KASAN is enabled without KASAN_VMALLOC, it is even - * less likely that the module region gets exhausted, so we - * can simply omit this fallback in that case. - */ - p = __vmalloc_node_range(size, MODULE_ALIGN, module_alloc_base, - module_alloc_base + SZ_2G, GFP_KERNEL, - PAGE_KERNEL, 0, NUMA_NO_NODE, - __builtin_return_address(0)); + void *p = NULL; + + /* + * Where possible, prefer to allocate within direct branch range of the + * kernel such that no PLTs are necessary. + */ + if (module_direct_base) { + p = __vmalloc_node_range(size, MODULE_ALIGN, + module_direct_base, + module_direct_base + SZ_128M, + GFP_KERNEL | __GFP_NOWARN, + PAGE_KERNEL, 0, NUMA_NO_NODE, + __builtin_return_address(0)); + } - if (p && (kasan_alloc_module_shadow(p, size, gfp_mask) < 0)) { + if (!p && module_plt_base) { + p = __vmalloc_node_range(size, MODULE_ALIGN, + module_plt_base, + module_plt_base + SZ_2G, + GFP_KERNEL | __GFP_NOWARN, + PAGE_KERNEL, 0, NUMA_NO_NODE, + __builtin_return_address(0)); + } + + if (!p) { + pr_warn_ratelimited("%s: unable to allocate memory\n", + __func__); + } + + if (p && (kasan_alloc_module_shadow(p, size, GFP_KERNEL) < 0)) { vfree(p); return NULL; } @@ -448,9 +529,7 @@ int apply_relocate_add(Elf64_Shdr *sechdrs, case R_AARCH64_CALL26: ovf = reloc_insn_imm(RELOC_OP_PREL, loc, val, 2, 26, AARCH64_INSN_IMM_26); - - if (IS_ENABLED(CONFIG_ARM64_MODULE_PLTS) && - ovf == -ERANGE) { + if (ovf == -ERANGE) { val = module_emit_plt_entry(me, sechdrs, loc, &rel[i], sym); if (!val) return -ENOEXEC; @@ -487,7 +566,7 @@ static int module_init_ftrace_plt(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs, struct module *mod) { -#if defined(CONFIG_ARM64_MODULE_PLTS) && defined(CONFIG_DYNAMIC_FTRACE) +#if defined(CONFIG_DYNAMIC_FTRACE) const Elf_Shdr *s; struct plt_entry *plts; diff --git a/arch/arm64/kernel/mte.c b/arch/arm64/kernel/mte.c index 7e89968bd28244ced303586a35bb2e81dc1ffad6..4c5ef9b2006500698c0257bd7899362532613eea 100644 --- a/arch/arm64/kernel/mte.c +++ b/arch/arm64/kernel/mte.c @@ -416,10 +416,9 @@ long get_mte_ctrl(struct task_struct *task) static int __access_remote_tags(struct mm_struct *mm, unsigned long addr, struct iovec *kiov, unsigned int gup_flags) { - struct vm_area_struct *vma; void __user *buf = kiov->iov_base; size_t len = kiov->iov_len; - int ret; + int err = 0; int write = gup_flags & FOLL_WRITE; if (!access_ok(buf, len)) @@ -429,14 +428,16 @@ static int __access_remote_tags(struct mm_struct *mm, unsigned long addr, return -EIO; while (len) { + struct vm_area_struct *vma; unsigned long tags, offset; void *maddr; - struct page *page = NULL; + struct page *page = get_user_page_vma_remote(mm, addr, + gup_flags, &vma); - ret = get_user_pages_remote(mm, addr, 1, gup_flags, &page, - &vma, NULL); - if (ret <= 0) + if (IS_ERR_OR_NULL(page)) { + err = page == NULL ? -EIO : PTR_ERR(page); break; + } /* * Only copy tags if the page has been mapped as PROT_MTE @@ -446,7 +447,7 @@ static int __access_remote_tags(struct mm_struct *mm, unsigned long addr, * was never mapped with PROT_MTE. */ if (!(vma->vm_flags & VM_MTE)) { - ret = -EOPNOTSUPP; + err = -EOPNOTSUPP; put_page(page); break; } @@ -479,7 +480,7 @@ static int __access_remote_tags(struct mm_struct *mm, unsigned long addr, kiov->iov_len = buf - kiov->iov_base; if (!kiov->iov_len) { /* check for error accessing the tracee's address space */ - if (ret <= 0) + if (err) return -EIO; else return -EFAULT; diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c index b8ec7b3ac9cbe8a8c207aab0b385926d910c45b1..417a8a86b2db595b5741b77a6c362502bb2f3617 100644 --- a/arch/arm64/kernel/setup.c +++ b/arch/arm64/kernel/setup.c @@ -296,6 +296,8 @@ void __init __no_sanitize_address setup_arch(char **cmdline_p) *cmdline_p = boot_command_line; + kaslr_init(); + /* * If know now we are going to need KPTI then use non-global * mappings from the start, avoiding the cost of rewriting diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c index 2cfc810d0a5b16493608e5c6f8925cdd3521af13..e304f7ebec2a91ff88c83afa20d8722a61f99cfa 100644 --- a/arch/arm64/kernel/signal.c +++ b/arch/arm64/kernel/signal.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -398,7 +399,7 @@ static int restore_tpidr2_context(struct user_ctxs *user) __get_user_error(tpidr2_el0, &user->tpidr2->tpidr2, err); if (!err) - current->thread.tpidr2_el0 = tpidr2_el0; + write_sysreg_s(tpidr2_el0, SYS_TPIDR2_EL0); return err; } diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c index d00d4cbb31b1671c46379cb09674561483ef31b3..edd63894d61e85b105f53e69d9b94e037210d2fc 100644 --- a/arch/arm64/kernel/smp.c +++ b/arch/arm64/kernel/smp.c @@ -332,17 +332,13 @@ static int op_cpu_kill(unsigned int cpu) } /* - * called on the thread which is asking for a CPU to be shutdown - - * waits until shutdown has completed, or it is timed out. + * Called on the thread which is asking for a CPU to be shutdown after the + * shutdown completed. */ -void __cpu_die(unsigned int cpu) +void arch_cpuhp_cleanup_dead_cpu(unsigned int cpu) { int err; - if (!cpu_wait_death(cpu, 5)) { - pr_crit("CPU%u: cpu didn't die\n", cpu); - return; - } pr_debug("CPU%u: shutdown\n", cpu); /* @@ -369,8 +365,8 @@ void __noreturn cpu_die(void) local_daif_mask(); - /* Tell __cpu_die() that this CPU is now safe to dispose of */ - (void)cpu_report_death(); + /* Tell cpuhp_bp_sync_dead() that this CPU is now safe to dispose of */ + cpuhp_ap_report_dead(); /* * Actually shutdown the CPU. This must never fail. The specific hotplug diff --git a/arch/arm64/kernel/syscall.c b/arch/arm64/kernel/syscall.c index da84cf855c4446a30057e2fd5db921c997ca106e..b1ae2f2eaf77ec3c88c95cece7f4b802f87046d6 100644 --- a/arch/arm64/kernel/syscall.c +++ b/arch/arm64/kernel/syscall.c @@ -75,9 +75,6 @@ static inline bool has_syscall_work(unsigned long flags) return unlikely(flags & _TIF_SYSCALL_WORK); } -int syscall_trace_enter(struct pt_regs *regs); -void syscall_trace_exit(struct pt_regs *regs); - static void el0_svc_common(struct pt_regs *regs, int scno, int sc_nr, const syscall_fn_t syscall_table[]) { @@ -147,11 +144,9 @@ static void el0_svc_common(struct pt_regs *regs, int scno, int sc_nr, * exit regardless, as the old entry assembly did. */ if (!has_syscall_work(flags) && !IS_ENABLED(CONFIG_DEBUG_RSEQ)) { - local_daif_mask(); flags = read_thread_flags(); if (!has_syscall_work(flags) && !(flags & _TIF_SINGLESTEP)) return; - local_daif_restore(DAIF_PROCCTX); } trace_exit: diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c index 4bb1b8f472982004e9171956c0b581d10be058b0..8b70759cdbb90c2d77192a32270e104fbba89ae5 100644 --- a/arch/arm64/kernel/traps.c +++ b/arch/arm64/kernel/traps.c @@ -514,6 +514,63 @@ void do_el1_fpac(struct pt_regs *regs, unsigned long esr) die("Oops - FPAC", regs, esr); } +void do_el0_mops(struct pt_regs *regs, unsigned long esr) +{ + bool wrong_option = esr & ESR_ELx_MOPS_ISS_WRONG_OPTION; + bool option_a = esr & ESR_ELx_MOPS_ISS_OPTION_A; + int dstreg = ESR_ELx_MOPS_ISS_DESTREG(esr); + int srcreg = ESR_ELx_MOPS_ISS_SRCREG(esr); + int sizereg = ESR_ELx_MOPS_ISS_SIZEREG(esr); + unsigned long dst, src, size; + + dst = pt_regs_read_reg(regs, dstreg); + src = pt_regs_read_reg(regs, srcreg); + size = pt_regs_read_reg(regs, sizereg); + + /* + * Put the registers back in the original format suitable for a + * prologue instruction, using the generic return routine from the + * Arm ARM (DDI 0487I.a) rules CNTMJ and MWFQH. + */ + if (esr & ESR_ELx_MOPS_ISS_MEM_INST) { + /* SET* instruction */ + if (option_a ^ wrong_option) { + /* Format is from Option A; forward set */ + pt_regs_write_reg(regs, dstreg, dst + size); + pt_regs_write_reg(regs, sizereg, -size); + } + } else { + /* CPY* instruction */ + if (!(option_a ^ wrong_option)) { + /* Format is from Option B */ + if (regs->pstate & PSR_N_BIT) { + /* Backward copy */ + pt_regs_write_reg(regs, dstreg, dst - size); + pt_regs_write_reg(regs, srcreg, src - size); + } + } else { + /* Format is from Option A */ + if (size & BIT(63)) { + /* Forward copy */ + pt_regs_write_reg(regs, dstreg, dst + size); + pt_regs_write_reg(regs, srcreg, src + size); + pt_regs_write_reg(regs, sizereg, -size); + } + } + } + + if (esr & ESR_ELx_MOPS_ISS_FROM_EPILOGUE) + regs->pc -= 8; + else + regs->pc -= 4; + + /* + * If single stepping then finish the step before executing the + * prologue instruction. + */ + user_fastforward_single_step(current); +} + #define __user_cache_maint(insn, address, res) \ if (address >= TASK_SIZE_MAX) { \ res = -EFAULT; \ @@ -824,6 +881,7 @@ static const char *esr_class_str[] = { [ESR_ELx_EC_DABT_LOW] = "DABT (lower EL)", [ESR_ELx_EC_DABT_CUR] = "DABT (current EL)", [ESR_ELx_EC_SP_ALIGN] = "SP Alignment", + [ESR_ELx_EC_MOPS] = "MOPS", [ESR_ELx_EC_FP_EXC32] = "FP (AArch32)", [ESR_ELx_EC_FP_EXC64] = "FP (AArch64)", [ESR_ELx_EC_SERROR] = "SError", @@ -947,7 +1005,7 @@ void do_serror(struct pt_regs *regs, unsigned long esr) } /* GENERIC_BUG traps */ - +#ifdef CONFIG_GENERIC_BUG int is_valid_bugaddr(unsigned long addr) { /* @@ -959,6 +1017,7 @@ int is_valid_bugaddr(unsigned long addr) */ return 1; } +#endif static int bug_handler(struct pt_regs *regs, unsigned long esr) { @@ -1044,7 +1103,7 @@ static int kasan_handler(struct pt_regs *regs, unsigned long esr) bool recover = esr & KASAN_ESR_RECOVER; bool write = esr & KASAN_ESR_WRITE; size_t size = KASAN_ESR_SIZE(esr); - u64 addr = regs->regs[0]; + void *addr = (void *)regs->regs[0]; u64 pc = regs->pc; kasan_report(addr, size, write, pc); diff --git a/arch/arm64/kernel/vdso32/Makefile b/arch/arm64/kernel/vdso32/Makefile index d014162c5c7134688b441734899b0ef028cf87ef..2f73e5bca213f827bdf1abad2b7522b128371f60 100644 --- a/arch/arm64/kernel/vdso32/Makefile +++ b/arch/arm64/kernel/vdso32/Makefile @@ -65,11 +65,9 @@ VDSO_CFLAGS += -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \ -fno-strict-aliasing -fno-common \ -Werror-implicit-function-declaration \ -Wno-format-security \ - -Wdeclaration-after-statement \ -std=gnu11 VDSO_CFLAGS += -O2 # Some useful compiler-dependent flags from top-level Makefile -VDSO_CFLAGS += $(call cc32-option,-Wdeclaration-after-statement,) VDSO_CFLAGS += $(call cc32-option,-Wno-pointer-sign) VDSO_CFLAGS += -fno-strict-overflow VDSO_CFLAGS += $(call cc32-option,-Werror=strict-prototypes) diff --git a/arch/arm64/kernel/watchdog_hld.c b/arch/arm64/kernel/watchdog_hld.c new file mode 100644 index 0000000000000000000000000000000000000000..dcd25322127c35293e5e39251d162845d8848681 --- /dev/null +++ b/arch/arm64/kernel/watchdog_hld.c @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include + +/* + * Safe maximum CPU frequency in case a particular platform doesn't implement + * cpufreq driver. Although, architecture doesn't put any restrictions on + * maximum frequency but 5 GHz seems to be safe maximum given the available + * Arm CPUs in the market which are clocked much less than 5 GHz. On the other + * hand, we can't make it much higher as it would lead to a large hard-lockup + * detection timeout on parts which are running slower (eg. 1GHz on + * Developerbox) and doesn't possess a cpufreq driver. + */ +#define SAFE_MAX_CPU_FREQ 5000000000UL // 5 GHz +u64 hw_nmi_get_sample_period(int watchdog_thresh) +{ + unsigned int cpu = smp_processor_id(); + unsigned long max_cpu_freq; + + max_cpu_freq = cpufreq_get_hw_max_freq(cpu) * 1000UL; + if (!max_cpu_freq) + max_cpu_freq = SAFE_MAX_CPU_FREQ; + + return (u64)max_cpu_freq * watchdog_thresh; +} + +bool __init arch_perf_nmi_is_available(void) +{ + /* + * hardlockup_detector_perf_init() will success even if Pseudo-NMI turns off, + * however, the pmu interrupts will act like a normal interrupt instead of + * NMI and the hardlockup detector would be broken. + */ + return arm_pmu_irq_is_nmi(); +} diff --git a/arch/arm64/kvm/arch_timer.c b/arch/arm64/kvm/arch_timer.c index 05b022be885b6718f23c53e3be50c278befd6611..0696732fa38cdab6488ea49dd4f15d720836ea3a 100644 --- a/arch/arm64/kvm/arch_timer.c +++ b/arch/arm64/kvm/arch_timer.c @@ -1406,7 +1406,7 @@ int __init kvm_timer_hyp_init(bool has_gic) kvm_get_running_vcpus()); if (err) { kvm_err("kvm_arch_timer: error setting vcpu affinity\n"); - goto out_free_irq; + goto out_free_vtimer_irq; } static_branch_enable(&has_gic_active_state); @@ -1422,7 +1422,7 @@ int __init kvm_timer_hyp_init(bool has_gic) if (err) { kvm_err("kvm_arch_timer: can't request ptimer interrupt %d (%d)\n", host_ptimer_irq, err); - return err; + goto out_free_vtimer_irq; } if (has_gic) { @@ -1430,7 +1430,7 @@ int __init kvm_timer_hyp_init(bool has_gic) kvm_get_running_vcpus()); if (err) { kvm_err("kvm_arch_timer: error setting vcpu affinity\n"); - goto out_free_irq; + goto out_free_ptimer_irq; } } @@ -1439,11 +1439,15 @@ int __init kvm_timer_hyp_init(bool has_gic) kvm_err("kvm_arch_timer: invalid physical timer IRQ: %d\n", info->physical_irq); err = -ENODEV; - goto out_free_irq; + goto out_free_vtimer_irq; } return 0; -out_free_irq: + +out_free_ptimer_irq: + if (info->physical_irq > 0) + free_percpu_irq(host_ptimer_irq, kvm_get_running_vcpus()); +out_free_vtimer_irq: free_percpu_irq(host_vtimer_irq, kvm_get_running_vcpus()); return err; } diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c index 14391826241c8ca689232506144d681295482996..c2c14059f6a8ca19083c113d536cdd6a847d65b8 100644 --- a/arch/arm64/kvm/arm.c +++ b/arch/arm64/kvm/arm.c @@ -51,6 +51,8 @@ DECLARE_KVM_HYP_PER_CPU(unsigned long, kvm_hyp_vector); DEFINE_PER_CPU(unsigned long, kvm_arm_hyp_stack_page); DECLARE_KVM_NVHE_PER_CPU(struct kvm_nvhe_init_params, kvm_init_params); +DECLARE_KVM_NVHE_PER_CPU(struct kvm_cpu_context, kvm_hyp_ctxt); + static bool vgic_present; static DEFINE_PER_CPU(unsigned char, kvm_arm_hardware_enabled); @@ -65,6 +67,7 @@ int kvm_vm_ioctl_enable_cap(struct kvm *kvm, struct kvm_enable_cap *cap) { int r; + u64 new_cap; if (cap->flags) return -EINVAL; @@ -89,6 +92,24 @@ int kvm_vm_ioctl_enable_cap(struct kvm *kvm, r = 0; set_bit(KVM_ARCH_FLAG_SYSTEM_SUSPEND_ENABLED, &kvm->arch.flags); break; + case KVM_CAP_ARM_EAGER_SPLIT_CHUNK_SIZE: + new_cap = cap->args[0]; + + mutex_lock(&kvm->slots_lock); + /* + * To keep things simple, allow changing the chunk + * size only when no memory slots have been created. + */ + if (!kvm_are_all_memslots_empty(kvm)) { + r = -EINVAL; + } else if (new_cap && !kvm_is_block_size_supported(new_cap)) { + r = -EINVAL; + } else { + r = 0; + kvm->arch.mmu.split_page_chunk_size = new_cap; + } + mutex_unlock(&kvm->slots_lock); + break; default: r = -EINVAL; break; @@ -102,22 +123,6 @@ static int kvm_arm_default_max_vcpus(void) return vgic_present ? kvm_vgic_get_max_vcpus() : KVM_MAX_VCPUS; } -static void set_default_spectre(struct kvm *kvm) -{ - /* - * The default is to expose CSV2 == 1 if the HW isn't affected. - * Although this is a per-CPU feature, we make it global because - * asymmetric systems are just a nuisance. - * - * Userspace can override this as long as it doesn't promise - * the impossible. - */ - if (arm64_get_spectre_v2_state() == SPECTRE_UNAFFECTED) - kvm->arch.pfr0_csv2 = 1; - if (arm64_get_meltdown_state() == SPECTRE_UNAFFECTED) - kvm->arch.pfr0_csv3 = 1; -} - /** * kvm_arch_init_vm - initializes a VM data structure * @kvm: pointer to the KVM struct @@ -161,14 +166,9 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type) /* The maximum number of VCPUs is limited by the host's GIC model */ kvm->max_vcpus = kvm_arm_default_max_vcpus(); - set_default_spectre(kvm); kvm_arm_init_hypercalls(kvm); - /* - * Initialise the default PMUver before there is a chance to - * create an actual PMU. - */ - kvm->arch.dfr0_pmuver.imp = kvm_arm_pmu_get_pmuver_limit(); + bitmap_zero(kvm->arch.vcpu_features, KVM_VCPU_MAX_FEATURES); return 0; @@ -302,6 +302,15 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) case KVM_CAP_ARM_PTRAUTH_GENERIC: r = system_has_full_ptr_auth(); break; + case KVM_CAP_ARM_EAGER_SPLIT_CHUNK_SIZE: + if (kvm) + r = kvm->arch.mmu.split_page_chunk_size; + else + r = KVM_ARM_EAGER_SPLIT_CHUNK_SIZE_DEFAULT; + break; + case KVM_CAP_ARM_SUPPORTED_BLOCK_SIZES: + r = kvm_supported_block_sizes(); + break; default: r = 0; } @@ -1167,58 +1176,115 @@ int kvm_vm_ioctl_irq_line(struct kvm *kvm, struct kvm_irq_level *irq_level, return -EINVAL; } -static int kvm_vcpu_set_target(struct kvm_vcpu *vcpu, - const struct kvm_vcpu_init *init) +static int kvm_vcpu_init_check_features(struct kvm_vcpu *vcpu, + const struct kvm_vcpu_init *init) { - unsigned int i, ret; - u32 phys_target = kvm_target_cpu(); + unsigned long features = init->features[0]; + int i; + + if (features & ~KVM_VCPU_VALID_FEATURES) + return -ENOENT; + + for (i = 1; i < ARRAY_SIZE(init->features); i++) { + if (init->features[i]) + return -ENOENT; + } + + if (!test_bit(KVM_ARM_VCPU_EL1_32BIT, &features)) + return 0; - if (init->target != phys_target) + if (!cpus_have_const_cap(ARM64_HAS_32BIT_EL1)) return -EINVAL; - /* - * Secondary and subsequent calls to KVM_ARM_VCPU_INIT must - * use the same target. - */ - if (vcpu->arch.target != -1 && vcpu->arch.target != init->target) + /* MTE is incompatible with AArch32 */ + if (kvm_has_mte(vcpu->kvm)) return -EINVAL; - /* -ENOENT for unknown features, -EINVAL for invalid combinations. */ - for (i = 0; i < sizeof(init->features) * 8; i++) { - bool set = (init->features[i / 32] & (1 << (i % 32))); + /* NV is incompatible with AArch32 */ + if (test_bit(KVM_ARM_VCPU_HAS_EL2, &features)) + return -EINVAL; - if (set && i >= KVM_VCPU_MAX_FEATURES) - return -ENOENT; + return 0; +} - /* - * Secondary and subsequent calls to KVM_ARM_VCPU_INIT must - * use the same feature set. - */ - if (vcpu->arch.target != -1 && i < KVM_VCPU_MAX_FEATURES && - test_bit(i, vcpu->arch.features) != set) - return -EINVAL; +static bool kvm_vcpu_init_changed(struct kvm_vcpu *vcpu, + const struct kvm_vcpu_init *init) +{ + unsigned long features = init->features[0]; - if (set) - set_bit(i, vcpu->arch.features); - } + return !bitmap_equal(vcpu->arch.features, &features, KVM_VCPU_MAX_FEATURES) || + vcpu->arch.target != init->target; +} + +static int __kvm_vcpu_set_target(struct kvm_vcpu *vcpu, + const struct kvm_vcpu_init *init) +{ + unsigned long features = init->features[0]; + struct kvm *kvm = vcpu->kvm; + int ret = -EINVAL; + + mutex_lock(&kvm->arch.config_lock); - vcpu->arch.target = phys_target; + if (test_bit(KVM_ARCH_FLAG_VCPU_FEATURES_CONFIGURED, &kvm->arch.flags) && + !bitmap_equal(kvm->arch.vcpu_features, &features, KVM_VCPU_MAX_FEATURES)) + goto out_unlock; + + vcpu->arch.target = init->target; + bitmap_copy(vcpu->arch.features, &features, KVM_VCPU_MAX_FEATURES); /* Now we know what it is, we can reset it. */ ret = kvm_reset_vcpu(vcpu); if (ret) { vcpu->arch.target = -1; bitmap_zero(vcpu->arch.features, KVM_VCPU_MAX_FEATURES); + goto out_unlock; } + bitmap_copy(kvm->arch.vcpu_features, &features, KVM_VCPU_MAX_FEATURES); + set_bit(KVM_ARCH_FLAG_VCPU_FEATURES_CONFIGURED, &kvm->arch.flags); + +out_unlock: + mutex_unlock(&kvm->arch.config_lock); return ret; } +static int kvm_vcpu_set_target(struct kvm_vcpu *vcpu, + const struct kvm_vcpu_init *init) +{ + int ret; + + if (init->target != kvm_target_cpu()) + return -EINVAL; + + ret = kvm_vcpu_init_check_features(vcpu, init); + if (ret) + return ret; + + if (vcpu->arch.target == -1) + return __kvm_vcpu_set_target(vcpu, init); + + if (kvm_vcpu_init_changed(vcpu, init)) + return -EINVAL; + + return kvm_reset_vcpu(vcpu); +} + static int kvm_arch_vcpu_ioctl_vcpu_init(struct kvm_vcpu *vcpu, struct kvm_vcpu_init *init) { + bool power_off = false; int ret; + /* + * Treat the power-off vCPU feature as ephemeral. Clear the bit to avoid + * reflecting it in the finalized feature set, thus limiting its scope + * to a single KVM_ARM_VCPU_INIT call. + */ + if (init->features[0] & BIT(KVM_ARM_VCPU_POWER_OFF)) { + init->features[0] &= ~BIT(KVM_ARM_VCPU_POWER_OFF); + power_off = true; + } + ret = kvm_vcpu_set_target(vcpu, init); if (ret) return ret; @@ -1240,14 +1306,14 @@ static int kvm_arch_vcpu_ioctl_vcpu_init(struct kvm_vcpu *vcpu, } vcpu_reset_hcr(vcpu); - vcpu->arch.cptr_el2 = CPTR_EL2_DEFAULT; + vcpu->arch.cptr_el2 = kvm_get_reset_cptr_el2(vcpu); /* * Handle the "start in power-off" case. */ spin_lock(&vcpu->arch.mp_state_lock); - if (test_bit(KVM_ARM_VCPU_POWER_OFF, vcpu->arch.features)) + if (power_off) __kvm_arm_vcpu_power_off(vcpu); else WRITE_ONCE(vcpu->arch.mp_state.mp_state, KVM_MP_STATE_RUNNABLE); @@ -1666,7 +1732,13 @@ static void __init cpu_prepare_hyp_mode(int cpu, u32 hyp_va_bits) params->mair_el2 = read_sysreg(mair_el1); - tcr = (read_sysreg(tcr_el1) & TCR_EL2_MASK) | TCR_EL2_RES1; + tcr = read_sysreg(tcr_el1); + if (cpus_have_final_cap(ARM64_KVM_HVHE)) { + tcr |= TCR_EPD1_MASK; + } else { + tcr &= TCR_EL2_MASK; + tcr |= TCR_EL2_RES1; + } tcr &= ~TCR_T0SZ_MASK; tcr |= TCR_T0SZ(hyp_va_bits); params->tcr_el2 = tcr; @@ -1676,6 +1748,8 @@ static void __init cpu_prepare_hyp_mode(int cpu, u32 hyp_va_bits) params->hcr_el2 = HCR_HOST_NVHE_PROTECTED_FLAGS; else params->hcr_el2 = HCR_HOST_NVHE_FLAGS; + if (cpus_have_final_cap(ARM64_KVM_HVHE)) + params->hcr_el2 |= HCR_E2H; params->vttbr = params->vtcr = 0; /* @@ -1910,6 +1984,7 @@ static bool __init init_psci_relay(void) } kvm_host_psci_config.version = psci_ops.get_version(); + kvm_host_psci_config.smccc_version = arm_smccc_get_version(); if (kvm_host_psci_config.version == PSCI_VERSION(0, 1)) { kvm_host_psci_config.function_ids_0_1 = get_psci_0_1_function_ids(); @@ -2067,6 +2142,26 @@ static int __init kvm_hyp_init_protection(u32 hyp_va_bits) return 0; } +static void pkvm_hyp_init_ptrauth(void) +{ + struct kvm_cpu_context *hyp_ctxt; + int cpu; + + for_each_possible_cpu(cpu) { + hyp_ctxt = per_cpu_ptr_nvhe_sym(kvm_hyp_ctxt, cpu); + hyp_ctxt->sys_regs[APIAKEYLO_EL1] = get_random_long(); + hyp_ctxt->sys_regs[APIAKEYHI_EL1] = get_random_long(); + hyp_ctxt->sys_regs[APIBKEYLO_EL1] = get_random_long(); + hyp_ctxt->sys_regs[APIBKEYHI_EL1] = get_random_long(); + hyp_ctxt->sys_regs[APDAKEYLO_EL1] = get_random_long(); + hyp_ctxt->sys_regs[APDAKEYHI_EL1] = get_random_long(); + hyp_ctxt->sys_regs[APDBKEYLO_EL1] = get_random_long(); + hyp_ctxt->sys_regs[APDBKEYHI_EL1] = get_random_long(); + hyp_ctxt->sys_regs[APGAKEYLO_EL1] = get_random_long(); + hyp_ctxt->sys_regs[APGAKEYHI_EL1] = get_random_long(); + } +} + /* Inits Hyp-mode on all online CPUs */ static int __init init_hyp_mode(void) { @@ -2228,6 +2323,10 @@ static int __init init_hyp_mode(void) kvm_hyp_init_symbols(); if (is_protected_kvm_enabled()) { + if (IS_ENABLED(CONFIG_ARM64_PTR_AUTH_KERNEL) && + cpus_have_const_cap(ARM64_HAS_ADDRESS_AUTH)) + pkvm_hyp_init_ptrauth(); + init_cpu_logical_map(); if (!init_psci_relay()) { diff --git a/arch/arm64/kvm/debug.c b/arch/arm64/kvm/debug.c index 55f80fb93925e9e827de7dc1e6d8c5a5302755cf..8725291cb00a185780ed1d795ff4ef0dcef31d36 100644 --- a/arch/arm64/kvm/debug.c +++ b/arch/arm64/kvm/debug.c @@ -333,7 +333,7 @@ void kvm_arch_vcpu_load_debug_state_flags(struct kvm_vcpu *vcpu) /* Check if we have TRBE implemented and available at the host */ if (cpuid_feature_extract_unsigned_field(dfr0, ID_AA64DFR0_EL1_TraceBuffer_SHIFT) && - !(read_sysreg_s(SYS_TRBIDR_EL1) & TRBIDR_PROG)) + !(read_sysreg_s(SYS_TRBIDR_EL1) & TRBIDR_EL1_P)) vcpu_set_flag(vcpu, DEBUG_STATE_SAVE_TRBE); } diff --git a/arch/arm64/kvm/fpsimd.c b/arch/arm64/kvm/fpsimd.c index 4c9dcd8fc93950d2927725ef23e21275267dd0c0..8c1d0d4853df48abf4d089bbde153bcee8d0e6d0 100644 --- a/arch/arm64/kvm/fpsimd.c +++ b/arch/arm64/kvm/fpsimd.c @@ -180,7 +180,7 @@ void kvm_arch_vcpu_put_fp(struct kvm_vcpu *vcpu) /* * If we have VHE then the Hyp code will reset CPACR_EL1 to - * CPACR_EL1_DEFAULT and we need to reenable SME. + * the default value and we need to reenable SME. */ if (has_vhe() && system_supports_sme()) { /* Also restore EL0 state seen on entry */ @@ -210,7 +210,7 @@ void kvm_arch_vcpu_put_fp(struct kvm_vcpu *vcpu) /* * The FPSIMD/SVE state in the CPU has not been touched, and we * have SVE (and VHE): CPACR_EL1 (alias CPTR_EL2) has been - * reset to CPACR_EL1_DEFAULT by the Hyp code, disabling SVE + * reset by kvm_reset_cptr_el2() in the Hyp code, disabling SVE * for EL0. To avoid spurious traps, restore the trap state * seen by kvm_arch_vcpu_load_fp(): */ diff --git a/arch/arm64/kvm/hyp/include/hyp/switch.h b/arch/arm64/kvm/hyp/include/hyp/switch.h index 5c15c58f90ccebb1afe2c364a5fec23559dfad03..4bddb8541bece001f45c3669a79b631441dcd7f3 100644 --- a/arch/arm64/kvm/hyp/include/hyp/switch.h +++ b/arch/arm64/kvm/hyp/include/hyp/switch.h @@ -70,6 +70,56 @@ static inline void __activate_traps_fpsimd32(struct kvm_vcpu *vcpu) } } +static inline bool __hfgxtr_traps_required(void) +{ + if (cpus_have_final_cap(ARM64_SME)) + return true; + + if (cpus_have_final_cap(ARM64_WORKAROUND_AMPERE_AC03_CPU_38)) + return true; + + return false; +} + +static inline void __activate_traps_hfgxtr(void) +{ + u64 r_clr = 0, w_clr = 0, r_set = 0, w_set = 0, tmp; + + if (cpus_have_final_cap(ARM64_SME)) { + tmp = HFGxTR_EL2_nSMPRI_EL1_MASK | HFGxTR_EL2_nTPIDR2_EL0_MASK; + + r_clr |= tmp; + w_clr |= tmp; + } + + /* + * Trap guest writes to TCR_EL1 to prevent it from enabling HA or HD. + */ + if (cpus_have_final_cap(ARM64_WORKAROUND_AMPERE_AC03_CPU_38)) + w_set |= HFGxTR_EL2_TCR_EL1_MASK; + + sysreg_clear_set_s(SYS_HFGRTR_EL2, r_clr, r_set); + sysreg_clear_set_s(SYS_HFGWTR_EL2, w_clr, w_set); +} + +static inline void __deactivate_traps_hfgxtr(void) +{ + u64 r_clr = 0, w_clr = 0, r_set = 0, w_set = 0, tmp; + + if (cpus_have_final_cap(ARM64_SME)) { + tmp = HFGxTR_EL2_nSMPRI_EL1_MASK | HFGxTR_EL2_nTPIDR2_EL0_MASK; + + r_set |= tmp; + w_set |= tmp; + } + + if (cpus_have_final_cap(ARM64_WORKAROUND_AMPERE_AC03_CPU_38)) + w_clr |= HFGxTR_EL2_TCR_EL1_MASK; + + sysreg_clear_set_s(SYS_HFGRTR_EL2, r_clr, r_set); + sysreg_clear_set_s(SYS_HFGWTR_EL2, w_clr, w_set); +} + static inline void __activate_traps_common(struct kvm_vcpu *vcpu) { /* Trap on AArch32 cp15 c15 (impdef sysregs) accesses (EL1 or EL0) */ @@ -82,23 +132,21 @@ static inline void __activate_traps_common(struct kvm_vcpu *vcpu) * EL1 instead of being trapped to EL2. */ if (kvm_arm_support_pmu_v3()) { + struct kvm_cpu_context *hctxt; + write_sysreg(0, pmselr_el0); + + hctxt = &this_cpu_ptr(&kvm_host_data)->host_ctxt; + ctxt_sys_reg(hctxt, PMUSERENR_EL0) = read_sysreg(pmuserenr_el0); write_sysreg(ARMV8_PMU_USERENR_MASK, pmuserenr_el0); + vcpu_set_flag(vcpu, PMUSERENR_ON_CPU); } vcpu->arch.mdcr_el2_host = read_sysreg(mdcr_el2); write_sysreg(vcpu->arch.mdcr_el2, mdcr_el2); - if (cpus_have_final_cap(ARM64_SME)) { - sysreg_clear_set_s(SYS_HFGRTR_EL2, - HFGxTR_EL2_nSMPRI_EL1_MASK | - HFGxTR_EL2_nTPIDR2_EL0_MASK, - 0); - sysreg_clear_set_s(SYS_HFGWTR_EL2, - HFGxTR_EL2_nSMPRI_EL1_MASK | - HFGxTR_EL2_nTPIDR2_EL0_MASK, - 0); - } + if (__hfgxtr_traps_required()) + __activate_traps_hfgxtr(); } static inline void __deactivate_traps_common(struct kvm_vcpu *vcpu) @@ -106,17 +154,16 @@ static inline void __deactivate_traps_common(struct kvm_vcpu *vcpu) write_sysreg(vcpu->arch.mdcr_el2_host, mdcr_el2); write_sysreg(0, hstr_el2); - if (kvm_arm_support_pmu_v3()) - write_sysreg(0, pmuserenr_el0); + if (kvm_arm_support_pmu_v3()) { + struct kvm_cpu_context *hctxt; - if (cpus_have_final_cap(ARM64_SME)) { - sysreg_clear_set_s(SYS_HFGRTR_EL2, 0, - HFGxTR_EL2_nSMPRI_EL1_MASK | - HFGxTR_EL2_nTPIDR2_EL0_MASK); - sysreg_clear_set_s(SYS_HFGWTR_EL2, 0, - HFGxTR_EL2_nSMPRI_EL1_MASK | - HFGxTR_EL2_nTPIDR2_EL0_MASK); + hctxt = &this_cpu_ptr(&kvm_host_data)->host_ctxt; + write_sysreg(ctxt_sys_reg(hctxt, PMUSERENR_EL0), pmuserenr_el0); + vcpu_clear_flag(vcpu, PMUSERENR_ON_CPU); } + + if (__hfgxtr_traps_required()) + __deactivate_traps_hfgxtr(); } static inline void ___activate_traps(struct kvm_vcpu *vcpu) @@ -130,6 +177,9 @@ static inline void ___activate_traps(struct kvm_vcpu *vcpu) if (cpus_have_final_cap(ARM64_HAS_RAS_EXTN) && (hcr & HCR_VSE)) write_sysreg_s(vcpu->arch.vsesr_el2, SYS_VSESR_EL2); + + if (cpus_have_final_cap(ARM64_HAS_HCX)) + write_sysreg_s(HCRX_GUEST_FLAGS, SYS_HCRX_EL2); } static inline void ___deactivate_traps(struct kvm_vcpu *vcpu) @@ -144,6 +194,9 @@ static inline void ___deactivate_traps(struct kvm_vcpu *vcpu) vcpu->arch.hcr_el2 &= ~HCR_VSE; vcpu->arch.hcr_el2 |= read_sysreg(hcr_el2) & HCR_VSE; } + + if (cpus_have_final_cap(ARM64_HAS_HCX)) + write_sysreg_s(HCRX_HOST_FLAGS, SYS_HCRX_EL2); } static inline bool __populate_fault_info(struct kvm_vcpu *vcpu) @@ -192,7 +245,7 @@ static bool kvm_hyp_handle_fpsimd(struct kvm_vcpu *vcpu, u64 *exit_code) /* Valid trap. Switch the context: */ /* First disable enough traps to allow us to update the registers */ - if (has_vhe()) { + if (has_vhe() || has_hvhe()) { reg = CPACR_EL1_FPEN_EL0EN | CPACR_EL1_FPEN_EL1EN; if (sve_guest) reg |= CPACR_EL1_ZEN_EL0EN | CPACR_EL1_ZEN_EL1EN; @@ -384,12 +437,39 @@ static bool kvm_hyp_handle_cntpct(struct kvm_vcpu *vcpu) return true; } +static bool handle_ampere1_tcr(struct kvm_vcpu *vcpu) +{ + u32 sysreg = esr_sys64_to_sysreg(kvm_vcpu_get_esr(vcpu)); + int rt = kvm_vcpu_sys_get_rt(vcpu); + u64 val = vcpu_get_reg(vcpu, rt); + + if (sysreg != SYS_TCR_EL1) + return false; + + /* + * Affected parts do not advertise support for hardware Access Flag / + * Dirty state management in ID_AA64MMFR1_EL1.HAFDBS, but the underlying + * control bits are still functional. The architecture requires these be + * RES0 on systems that do not implement FEAT_HAFDBS. + * + * Uphold the requirements of the architecture by masking guest writes + * to TCR_EL1.{HA,HD} here. + */ + val &= ~(TCR_HD | TCR_HA); + write_sysreg_el1(val, SYS_TCR); + return true; +} + static bool kvm_hyp_handle_sysreg(struct kvm_vcpu *vcpu, u64 *exit_code) { if (cpus_have_final_cap(ARM64_WORKAROUND_CAVIUM_TX2_219_TVM) && handle_tx2_tvm(vcpu)) return true; + if (cpus_have_final_cap(ARM64_WORKAROUND_AMPERE_AC03_CPU_38) && + handle_ampere1_tcr(vcpu)) + return true; + if (static_branch_unlikely(&vgic_v3_cpuif_trap) && __vgic_v3_perform_cpuif_access(vcpu) == 1) return true; diff --git a/arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h b/arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h index 699ea1f8d409c7de996906a6522a41da08475dc8..bb6b571ec627dede466c5fa1d05785a9c9f78764 100644 --- a/arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h +++ b/arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h @@ -44,6 +44,8 @@ static inline void __sysreg_save_el1_state(struct kvm_cpu_context *ctxt) ctxt_sys_reg(ctxt, TTBR0_EL1) = read_sysreg_el1(SYS_TTBR0); ctxt_sys_reg(ctxt, TTBR1_EL1) = read_sysreg_el1(SYS_TTBR1); ctxt_sys_reg(ctxt, TCR_EL1) = read_sysreg_el1(SYS_TCR); + if (cpus_have_final_cap(ARM64_HAS_TCR2)) + ctxt_sys_reg(ctxt, TCR2_EL1) = read_sysreg_el1(SYS_TCR2); ctxt_sys_reg(ctxt, ESR_EL1) = read_sysreg_el1(SYS_ESR); ctxt_sys_reg(ctxt, AFSR0_EL1) = read_sysreg_el1(SYS_AFSR0); ctxt_sys_reg(ctxt, AFSR1_EL1) = read_sysreg_el1(SYS_AFSR1); @@ -53,6 +55,10 @@ static inline void __sysreg_save_el1_state(struct kvm_cpu_context *ctxt) ctxt_sys_reg(ctxt, CONTEXTIDR_EL1) = read_sysreg_el1(SYS_CONTEXTIDR); ctxt_sys_reg(ctxt, AMAIR_EL1) = read_sysreg_el1(SYS_AMAIR); ctxt_sys_reg(ctxt, CNTKCTL_EL1) = read_sysreg_el1(SYS_CNTKCTL); + if (cpus_have_final_cap(ARM64_HAS_S1PIE)) { + ctxt_sys_reg(ctxt, PIR_EL1) = read_sysreg_el1(SYS_PIR); + ctxt_sys_reg(ctxt, PIRE0_EL1) = read_sysreg_el1(SYS_PIRE0); + } ctxt_sys_reg(ctxt, PAR_EL1) = read_sysreg_par(); ctxt_sys_reg(ctxt, TPIDR_EL1) = read_sysreg(tpidr_el1); @@ -114,6 +120,8 @@ static inline void __sysreg_restore_el1_state(struct kvm_cpu_context *ctxt) write_sysreg_el1(ctxt_sys_reg(ctxt, CPACR_EL1), SYS_CPACR); write_sysreg_el1(ctxt_sys_reg(ctxt, TTBR0_EL1), SYS_TTBR0); write_sysreg_el1(ctxt_sys_reg(ctxt, TTBR1_EL1), SYS_TTBR1); + if (cpus_have_final_cap(ARM64_HAS_TCR2)) + write_sysreg_el1(ctxt_sys_reg(ctxt, TCR2_EL1), SYS_TCR2); write_sysreg_el1(ctxt_sys_reg(ctxt, ESR_EL1), SYS_ESR); write_sysreg_el1(ctxt_sys_reg(ctxt, AFSR0_EL1), SYS_AFSR0); write_sysreg_el1(ctxt_sys_reg(ctxt, AFSR1_EL1), SYS_AFSR1); @@ -123,6 +131,10 @@ static inline void __sysreg_restore_el1_state(struct kvm_cpu_context *ctxt) write_sysreg_el1(ctxt_sys_reg(ctxt, CONTEXTIDR_EL1), SYS_CONTEXTIDR); write_sysreg_el1(ctxt_sys_reg(ctxt, AMAIR_EL1), SYS_AMAIR); write_sysreg_el1(ctxt_sys_reg(ctxt, CNTKCTL_EL1), SYS_CNTKCTL); + if (cpus_have_final_cap(ARM64_HAS_S1PIE)) { + write_sysreg_el1(ctxt_sys_reg(ctxt, PIR_EL1), SYS_PIR); + write_sysreg_el1(ctxt_sys_reg(ctxt, PIRE0_EL1), SYS_PIRE0); + } write_sysreg(ctxt_sys_reg(ctxt, PAR_EL1), par_el1); write_sysreg(ctxt_sys_reg(ctxt, TPIDR_EL1), tpidr_el1); diff --git a/arch/arm64/kvm/hyp/include/nvhe/ffa.h b/arch/arm64/kvm/hyp/include/nvhe/ffa.h new file mode 100644 index 0000000000000000000000000000000000000000..1becb10ecd8057d49dac1730409bfb10077cd1e0 --- /dev/null +++ b/arch/arm64/kvm/hyp/include/nvhe/ffa.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (C) 2022 - Google LLC + * Author: Andrew Walbran + */ +#ifndef __KVM_HYP_FFA_H +#define __KVM_HYP_FFA_H + +#include + +#define FFA_MIN_FUNC_NUM 0x60 +#define FFA_MAX_FUNC_NUM 0x7F + +int hyp_ffa_init(void *pages); +bool kvm_host_ffa_handler(struct kvm_cpu_context *host_ctxt); + +#endif /* __KVM_HYP_FFA_H */ diff --git a/arch/arm64/kvm/hyp/include/nvhe/mem_protect.h b/arch/arm64/kvm/hyp/include/nvhe/mem_protect.h index b7bdbe63deed876f238f97cfd1f03f98497d8aaa..0972faccc2af0764d00deff099662738c6e5a1e4 100644 --- a/arch/arm64/kvm/hyp/include/nvhe/mem_protect.h +++ b/arch/arm64/kvm/hyp/include/nvhe/mem_protect.h @@ -57,6 +57,7 @@ extern struct host_mmu host_mmu; enum pkvm_component_id { PKVM_ID_HOST, PKVM_ID_HYP, + PKVM_ID_FFA, }; extern unsigned long hyp_nr_cpus; @@ -66,6 +67,8 @@ int __pkvm_host_share_hyp(u64 pfn); int __pkvm_host_unshare_hyp(u64 pfn); int __pkvm_host_donate_hyp(u64 pfn, u64 nr_pages); int __pkvm_hyp_donate_host(u64 pfn, u64 nr_pages); +int __pkvm_host_share_ffa(u64 pfn, u64 nr_pages); +int __pkvm_host_unshare_ffa(u64 pfn, u64 nr_pages); bool addr_is_memory(phys_addr_t phys); int host_stage2_idmap_locked(phys_addr_t addr, u64 size, enum kvm_pgtable_prot prot); diff --git a/arch/arm64/kvm/hyp/nvhe/Makefile b/arch/arm64/kvm/hyp/nvhe/Makefile index 530347cdebe3aa489095116a66d204b20abf7ba5..9ddc025e4b8651de47510edfe0f500ae47a173c7 100644 --- a/arch/arm64/kvm/hyp/nvhe/Makefile +++ b/arch/arm64/kvm/hyp/nvhe/Makefile @@ -22,7 +22,7 @@ lib-objs := $(addprefix ../../../lib/, $(lib-objs)) hyp-obj-y := timer-sr.o sysreg-sr.o debug-sr.o switch.o tlb.o hyp-init.o host.o \ hyp-main.o hyp-smp.o psci-relay.o early_alloc.o page_alloc.o \ - cache.o setup.o mm.o mem_protect.o sys_regs.o pkvm.o stacktrace.o + cache.o setup.o mm.o mem_protect.o sys_regs.o pkvm.o stacktrace.o ffa.o hyp-obj-y += ../vgic-v3-sr.o ../aarch32.o ../vgic-v2-cpuif-proxy.o ../entry.o \ ../fpsimd.o ../hyp-entry.o ../exception.o ../pgtable.o hyp-obj-$(CONFIG_DEBUG_LIST) += list_debug.o diff --git a/arch/arm64/kvm/hyp/nvhe/debug-sr.c b/arch/arm64/kvm/hyp/nvhe/debug-sr.c index d756b939f296913000551d8d0645a5c68d1b828d..4558c02eb352d06be1c5861ea22a956c2c05954f 100644 --- a/arch/arm64/kvm/hyp/nvhe/debug-sr.c +++ b/arch/arm64/kvm/hyp/nvhe/debug-sr.c @@ -56,7 +56,7 @@ static void __debug_save_trace(u64 *trfcr_el1) *trfcr_el1 = 0; /* Check if the TRBE is enabled */ - if (!(read_sysreg_s(SYS_TRBLIMITR_EL1) & TRBLIMITR_ENABLE)) + if (!(read_sysreg_s(SYS_TRBLIMITR_EL1) & TRBLIMITR_EL1_E)) return; /* * Prohibit trace generation while we are in guest. diff --git a/arch/arm64/kvm/hyp/nvhe/ffa.c b/arch/arm64/kvm/hyp/nvhe/ffa.c new file mode 100644 index 0000000000000000000000000000000000000000..58dcd92bf346e15653cf64931c274888aef9607d --- /dev/null +++ b/arch/arm64/kvm/hyp/nvhe/ffa.c @@ -0,0 +1,762 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * FF-A v1.0 proxy to filter out invalid memory-sharing SMC calls issued by + * the host. FF-A is a slightly more palatable abbreviation of "Arm Firmware + * Framework for Arm A-profile", which is specified by Arm in document + * number DEN0077. + * + * Copyright (C) 2022 - Google LLC + * Author: Andrew Walbran + * + * This driver hooks into the SMC trapping logic for the host and intercepts + * all calls falling within the FF-A range. Each call is either: + * + * - Forwarded on unmodified to the SPMD at EL3 + * - Rejected as "unsupported" + * - Accompanied by a host stage-2 page-table check/update and reissued + * + * Consequently, any attempts by the host to make guest memory pages + * accessible to the secure world using FF-A will be detected either here + * (in the case that the memory is already owned by the guest) or during + * donation to the guest (in the case that the memory was previously shared + * with the secure world). + * + * To allow the rolling-back of page-table updates and FF-A calls in the + * event of failure, operations involving the RXTX buffers are locked for + * the duration and are therefore serialised. + */ + +#include +#include +#include + +#include +#include +#include +#include +#include + +/* + * "ID value 0 must be returned at the Non-secure physical FF-A instance" + * We share this ID with the host. + */ +#define HOST_FFA_ID 0 + +/* + * A buffer to hold the maximum descriptor size we can see from the host, + * which is required when the SPMD returns a fragmented FFA_MEM_RETRIEVE_RESP + * when resolving the handle on the reclaim path. + */ +struct kvm_ffa_descriptor_buffer { + void *buf; + size_t len; +}; + +static struct kvm_ffa_descriptor_buffer ffa_desc_buf; + +struct kvm_ffa_buffers { + hyp_spinlock_t lock; + void *tx; + void *rx; +}; + +/* + * Note that we don't currently lock these buffers explicitly, instead + * relying on the locking of the host FFA buffers as we only have one + * client. + */ +static struct kvm_ffa_buffers hyp_buffers; +static struct kvm_ffa_buffers host_buffers; + +static void ffa_to_smccc_error(struct arm_smccc_res *res, u64 ffa_errno) +{ + *res = (struct arm_smccc_res) { + .a0 = FFA_ERROR, + .a2 = ffa_errno, + }; +} + +static void ffa_to_smccc_res_prop(struct arm_smccc_res *res, int ret, u64 prop) +{ + if (ret == FFA_RET_SUCCESS) { + *res = (struct arm_smccc_res) { .a0 = FFA_SUCCESS, + .a2 = prop }; + } else { + ffa_to_smccc_error(res, ret); + } +} + +static void ffa_to_smccc_res(struct arm_smccc_res *res, int ret) +{ + ffa_to_smccc_res_prop(res, ret, 0); +} + +static void ffa_set_retval(struct kvm_cpu_context *ctxt, + struct arm_smccc_res *res) +{ + cpu_reg(ctxt, 0) = res->a0; + cpu_reg(ctxt, 1) = res->a1; + cpu_reg(ctxt, 2) = res->a2; + cpu_reg(ctxt, 3) = res->a3; +} + +static bool is_ffa_call(u64 func_id) +{ + return ARM_SMCCC_IS_FAST_CALL(func_id) && + ARM_SMCCC_OWNER_NUM(func_id) == ARM_SMCCC_OWNER_STANDARD && + ARM_SMCCC_FUNC_NUM(func_id) >= FFA_MIN_FUNC_NUM && + ARM_SMCCC_FUNC_NUM(func_id) <= FFA_MAX_FUNC_NUM; +} + +static int ffa_map_hyp_buffers(u64 ffa_page_count) +{ + struct arm_smccc_res res; + + arm_smccc_1_1_smc(FFA_FN64_RXTX_MAP, + hyp_virt_to_phys(hyp_buffers.tx), + hyp_virt_to_phys(hyp_buffers.rx), + ffa_page_count, + 0, 0, 0, 0, + &res); + + return res.a0 == FFA_SUCCESS ? FFA_RET_SUCCESS : res.a2; +} + +static int ffa_unmap_hyp_buffers(void) +{ + struct arm_smccc_res res; + + arm_smccc_1_1_smc(FFA_RXTX_UNMAP, + HOST_FFA_ID, + 0, 0, 0, 0, 0, 0, + &res); + + return res.a0 == FFA_SUCCESS ? FFA_RET_SUCCESS : res.a2; +} + +static void ffa_mem_frag_tx(struct arm_smccc_res *res, u32 handle_lo, + u32 handle_hi, u32 fraglen, u32 endpoint_id) +{ + arm_smccc_1_1_smc(FFA_MEM_FRAG_TX, + handle_lo, handle_hi, fraglen, endpoint_id, + 0, 0, 0, + res); +} + +static void ffa_mem_frag_rx(struct arm_smccc_res *res, u32 handle_lo, + u32 handle_hi, u32 fragoff) +{ + arm_smccc_1_1_smc(FFA_MEM_FRAG_RX, + handle_lo, handle_hi, fragoff, HOST_FFA_ID, + 0, 0, 0, + res); +} + +static void ffa_mem_xfer(struct arm_smccc_res *res, u64 func_id, u32 len, + u32 fraglen) +{ + arm_smccc_1_1_smc(func_id, len, fraglen, + 0, 0, 0, 0, 0, + res); +} + +static void ffa_mem_reclaim(struct arm_smccc_res *res, u32 handle_lo, + u32 handle_hi, u32 flags) +{ + arm_smccc_1_1_smc(FFA_MEM_RECLAIM, + handle_lo, handle_hi, flags, + 0, 0, 0, 0, + res); +} + +static void ffa_retrieve_req(struct arm_smccc_res *res, u32 len) +{ + arm_smccc_1_1_smc(FFA_FN64_MEM_RETRIEVE_REQ, + len, len, + 0, 0, 0, 0, 0, + res); +} + +static void do_ffa_rxtx_map(struct arm_smccc_res *res, + struct kvm_cpu_context *ctxt) +{ + DECLARE_REG(phys_addr_t, tx, ctxt, 1); + DECLARE_REG(phys_addr_t, rx, ctxt, 2); + DECLARE_REG(u32, npages, ctxt, 3); + int ret = 0; + void *rx_virt, *tx_virt; + + if (npages != (KVM_FFA_MBOX_NR_PAGES * PAGE_SIZE) / FFA_PAGE_SIZE) { + ret = FFA_RET_INVALID_PARAMETERS; + goto out; + } + + if (!PAGE_ALIGNED(tx) || !PAGE_ALIGNED(rx)) { + ret = FFA_RET_INVALID_PARAMETERS; + goto out; + } + + hyp_spin_lock(&host_buffers.lock); + if (host_buffers.tx) { + ret = FFA_RET_DENIED; + goto out_unlock; + } + + /* + * Map our hypervisor buffers into the SPMD before mapping and + * pinning the host buffers in our own address space. + */ + ret = ffa_map_hyp_buffers(npages); + if (ret) + goto out_unlock; + + ret = __pkvm_host_share_hyp(hyp_phys_to_pfn(tx)); + if (ret) { + ret = FFA_RET_INVALID_PARAMETERS; + goto err_unmap; + } + + ret = __pkvm_host_share_hyp(hyp_phys_to_pfn(rx)); + if (ret) { + ret = FFA_RET_INVALID_PARAMETERS; + goto err_unshare_tx; + } + + tx_virt = hyp_phys_to_virt(tx); + ret = hyp_pin_shared_mem(tx_virt, tx_virt + 1); + if (ret) { + ret = FFA_RET_INVALID_PARAMETERS; + goto err_unshare_rx; + } + + rx_virt = hyp_phys_to_virt(rx); + ret = hyp_pin_shared_mem(rx_virt, rx_virt + 1); + if (ret) { + ret = FFA_RET_INVALID_PARAMETERS; + goto err_unpin_tx; + } + + host_buffers.tx = tx_virt; + host_buffers.rx = rx_virt; + +out_unlock: + hyp_spin_unlock(&host_buffers.lock); +out: + ffa_to_smccc_res(res, ret); + return; + +err_unpin_tx: + hyp_unpin_shared_mem(tx_virt, tx_virt + 1); +err_unshare_rx: + __pkvm_host_unshare_hyp(hyp_phys_to_pfn(rx)); +err_unshare_tx: + __pkvm_host_unshare_hyp(hyp_phys_to_pfn(tx)); +err_unmap: + ffa_unmap_hyp_buffers(); + goto out_unlock; +} + +static void do_ffa_rxtx_unmap(struct arm_smccc_res *res, + struct kvm_cpu_context *ctxt) +{ + DECLARE_REG(u32, id, ctxt, 1); + int ret = 0; + + if (id != HOST_FFA_ID) { + ret = FFA_RET_INVALID_PARAMETERS; + goto out; + } + + hyp_spin_lock(&host_buffers.lock); + if (!host_buffers.tx) { + ret = FFA_RET_INVALID_PARAMETERS; + goto out_unlock; + } + + hyp_unpin_shared_mem(host_buffers.tx, host_buffers.tx + 1); + WARN_ON(__pkvm_host_unshare_hyp(hyp_virt_to_pfn(host_buffers.tx))); + host_buffers.tx = NULL; + + hyp_unpin_shared_mem(host_buffers.rx, host_buffers.rx + 1); + WARN_ON(__pkvm_host_unshare_hyp(hyp_virt_to_pfn(host_buffers.rx))); + host_buffers.rx = NULL; + + ffa_unmap_hyp_buffers(); + +out_unlock: + hyp_spin_unlock(&host_buffers.lock); +out: + ffa_to_smccc_res(res, ret); +} + +static u32 __ffa_host_share_ranges(struct ffa_mem_region_addr_range *ranges, + u32 nranges) +{ + u32 i; + + for (i = 0; i < nranges; ++i) { + struct ffa_mem_region_addr_range *range = &ranges[i]; + u64 sz = (u64)range->pg_cnt * FFA_PAGE_SIZE; + u64 pfn = hyp_phys_to_pfn(range->address); + + if (!PAGE_ALIGNED(sz)) + break; + + if (__pkvm_host_share_ffa(pfn, sz / PAGE_SIZE)) + break; + } + + return i; +} + +static u32 __ffa_host_unshare_ranges(struct ffa_mem_region_addr_range *ranges, + u32 nranges) +{ + u32 i; + + for (i = 0; i < nranges; ++i) { + struct ffa_mem_region_addr_range *range = &ranges[i]; + u64 sz = (u64)range->pg_cnt * FFA_PAGE_SIZE; + u64 pfn = hyp_phys_to_pfn(range->address); + + if (!PAGE_ALIGNED(sz)) + break; + + if (__pkvm_host_unshare_ffa(pfn, sz / PAGE_SIZE)) + break; + } + + return i; +} + +static int ffa_host_share_ranges(struct ffa_mem_region_addr_range *ranges, + u32 nranges) +{ + u32 nshared = __ffa_host_share_ranges(ranges, nranges); + int ret = 0; + + if (nshared != nranges) { + WARN_ON(__ffa_host_unshare_ranges(ranges, nshared) != nshared); + ret = FFA_RET_DENIED; + } + + return ret; +} + +static int ffa_host_unshare_ranges(struct ffa_mem_region_addr_range *ranges, + u32 nranges) +{ + u32 nunshared = __ffa_host_unshare_ranges(ranges, nranges); + int ret = 0; + + if (nunshared != nranges) { + WARN_ON(__ffa_host_share_ranges(ranges, nunshared) != nunshared); + ret = FFA_RET_DENIED; + } + + return ret; +} + +static void do_ffa_mem_frag_tx(struct arm_smccc_res *res, + struct kvm_cpu_context *ctxt) +{ + DECLARE_REG(u32, handle_lo, ctxt, 1); + DECLARE_REG(u32, handle_hi, ctxt, 2); + DECLARE_REG(u32, fraglen, ctxt, 3); + DECLARE_REG(u32, endpoint_id, ctxt, 4); + struct ffa_mem_region_addr_range *buf; + int ret = FFA_RET_INVALID_PARAMETERS; + u32 nr_ranges; + + if (fraglen > KVM_FFA_MBOX_NR_PAGES * PAGE_SIZE) + goto out; + + if (fraglen % sizeof(*buf)) + goto out; + + hyp_spin_lock(&host_buffers.lock); + if (!host_buffers.tx) + goto out_unlock; + + buf = hyp_buffers.tx; + memcpy(buf, host_buffers.tx, fraglen); + nr_ranges = fraglen / sizeof(*buf); + + ret = ffa_host_share_ranges(buf, nr_ranges); + if (ret) { + /* + * We're effectively aborting the transaction, so we need + * to restore the global state back to what it was prior to + * transmission of the first fragment. + */ + ffa_mem_reclaim(res, handle_lo, handle_hi, 0); + WARN_ON(res->a0 != FFA_SUCCESS); + goto out_unlock; + } + + ffa_mem_frag_tx(res, handle_lo, handle_hi, fraglen, endpoint_id); + if (res->a0 != FFA_SUCCESS && res->a0 != FFA_MEM_FRAG_RX) + WARN_ON(ffa_host_unshare_ranges(buf, nr_ranges)); + +out_unlock: + hyp_spin_unlock(&host_buffers.lock); +out: + if (ret) + ffa_to_smccc_res(res, ret); + + /* + * If for any reason this did not succeed, we're in trouble as we have + * now lost the content of the previous fragments and we can't rollback + * the host stage-2 changes. The pages previously marked as shared will + * remain stuck in that state forever, hence preventing the host from + * sharing/donating them again and may possibly lead to subsequent + * failures, but this will not compromise confidentiality. + */ + return; +} + +static __always_inline void do_ffa_mem_xfer(const u64 func_id, + struct arm_smccc_res *res, + struct kvm_cpu_context *ctxt) +{ + DECLARE_REG(u32, len, ctxt, 1); + DECLARE_REG(u32, fraglen, ctxt, 2); + DECLARE_REG(u64, addr_mbz, ctxt, 3); + DECLARE_REG(u32, npages_mbz, ctxt, 4); + struct ffa_composite_mem_region *reg; + struct ffa_mem_region *buf; + u32 offset, nr_ranges; + int ret = 0; + + BUILD_BUG_ON(func_id != FFA_FN64_MEM_SHARE && + func_id != FFA_FN64_MEM_LEND); + + if (addr_mbz || npages_mbz || fraglen > len || + fraglen > KVM_FFA_MBOX_NR_PAGES * PAGE_SIZE) { + ret = FFA_RET_INVALID_PARAMETERS; + goto out; + } + + if (fraglen < sizeof(struct ffa_mem_region) + + sizeof(struct ffa_mem_region_attributes)) { + ret = FFA_RET_INVALID_PARAMETERS; + goto out; + } + + hyp_spin_lock(&host_buffers.lock); + if (!host_buffers.tx) { + ret = FFA_RET_INVALID_PARAMETERS; + goto out_unlock; + } + + buf = hyp_buffers.tx; + memcpy(buf, host_buffers.tx, fraglen); + + offset = buf->ep_mem_access[0].composite_off; + if (!offset || buf->ep_count != 1 || buf->sender_id != HOST_FFA_ID) { + ret = FFA_RET_INVALID_PARAMETERS; + goto out_unlock; + } + + if (fraglen < offset + sizeof(struct ffa_composite_mem_region)) { + ret = FFA_RET_INVALID_PARAMETERS; + goto out_unlock; + } + + reg = (void *)buf + offset; + nr_ranges = ((void *)buf + fraglen) - (void *)reg->constituents; + if (nr_ranges % sizeof(reg->constituents[0])) { + ret = FFA_RET_INVALID_PARAMETERS; + goto out_unlock; + } + + nr_ranges /= sizeof(reg->constituents[0]); + ret = ffa_host_share_ranges(reg->constituents, nr_ranges); + if (ret) + goto out_unlock; + + ffa_mem_xfer(res, func_id, len, fraglen); + if (fraglen != len) { + if (res->a0 != FFA_MEM_FRAG_RX) + goto err_unshare; + + if (res->a3 != fraglen) + goto err_unshare; + } else if (res->a0 != FFA_SUCCESS) { + goto err_unshare; + } + +out_unlock: + hyp_spin_unlock(&host_buffers.lock); +out: + if (ret) + ffa_to_smccc_res(res, ret); + return; + +err_unshare: + WARN_ON(ffa_host_unshare_ranges(reg->constituents, nr_ranges)); + goto out_unlock; +} + +static void do_ffa_mem_reclaim(struct arm_smccc_res *res, + struct kvm_cpu_context *ctxt) +{ + DECLARE_REG(u32, handle_lo, ctxt, 1); + DECLARE_REG(u32, handle_hi, ctxt, 2); + DECLARE_REG(u32, flags, ctxt, 3); + struct ffa_composite_mem_region *reg; + u32 offset, len, fraglen, fragoff; + struct ffa_mem_region *buf; + int ret = 0; + u64 handle; + + handle = PACK_HANDLE(handle_lo, handle_hi); + + hyp_spin_lock(&host_buffers.lock); + + buf = hyp_buffers.tx; + *buf = (struct ffa_mem_region) { + .sender_id = HOST_FFA_ID, + .handle = handle, + }; + + ffa_retrieve_req(res, sizeof(*buf)); + buf = hyp_buffers.rx; + if (res->a0 != FFA_MEM_RETRIEVE_RESP) + goto out_unlock; + + len = res->a1; + fraglen = res->a2; + + offset = buf->ep_mem_access[0].composite_off; + /* + * We can trust the SPMD to get this right, but let's at least + * check that we end up with something that doesn't look _completely_ + * bogus. + */ + if (WARN_ON(offset > len || + fraglen > KVM_FFA_MBOX_NR_PAGES * PAGE_SIZE)) { + ret = FFA_RET_ABORTED; + goto out_unlock; + } + + if (len > ffa_desc_buf.len) { + ret = FFA_RET_NO_MEMORY; + goto out_unlock; + } + + buf = ffa_desc_buf.buf; + memcpy(buf, hyp_buffers.rx, fraglen); + + for (fragoff = fraglen; fragoff < len; fragoff += fraglen) { + ffa_mem_frag_rx(res, handle_lo, handle_hi, fragoff); + if (res->a0 != FFA_MEM_FRAG_TX) { + ret = FFA_RET_INVALID_PARAMETERS; + goto out_unlock; + } + + fraglen = res->a3; + memcpy((void *)buf + fragoff, hyp_buffers.rx, fraglen); + } + + ffa_mem_reclaim(res, handle_lo, handle_hi, flags); + if (res->a0 != FFA_SUCCESS) + goto out_unlock; + + reg = (void *)buf + offset; + /* If the SPMD was happy, then we should be too. */ + WARN_ON(ffa_host_unshare_ranges(reg->constituents, + reg->addr_range_cnt)); +out_unlock: + hyp_spin_unlock(&host_buffers.lock); + + if (ret) + ffa_to_smccc_res(res, ret); +} + +/* + * Is a given FFA function supported, either by forwarding on directly + * or by handling at EL2? + */ +static bool ffa_call_supported(u64 func_id) +{ + switch (func_id) { + /* Unsupported memory management calls */ + case FFA_FN64_MEM_RETRIEVE_REQ: + case FFA_MEM_RETRIEVE_RESP: + case FFA_MEM_RELINQUISH: + case FFA_MEM_OP_PAUSE: + case FFA_MEM_OP_RESUME: + case FFA_MEM_FRAG_RX: + case FFA_FN64_MEM_DONATE: + /* Indirect message passing via RX/TX buffers */ + case FFA_MSG_SEND: + case FFA_MSG_POLL: + case FFA_MSG_WAIT: + /* 32-bit variants of 64-bit calls */ + case FFA_MSG_SEND_DIRECT_REQ: + case FFA_MSG_SEND_DIRECT_RESP: + case FFA_RXTX_MAP: + case FFA_MEM_DONATE: + case FFA_MEM_RETRIEVE_REQ: + return false; + } + + return true; +} + +static bool do_ffa_features(struct arm_smccc_res *res, + struct kvm_cpu_context *ctxt) +{ + DECLARE_REG(u32, id, ctxt, 1); + u64 prop = 0; + int ret = 0; + + if (!ffa_call_supported(id)) { + ret = FFA_RET_NOT_SUPPORTED; + goto out_handled; + } + + switch (id) { + case FFA_MEM_SHARE: + case FFA_FN64_MEM_SHARE: + case FFA_MEM_LEND: + case FFA_FN64_MEM_LEND: + ret = FFA_RET_SUCCESS; + prop = 0; /* No support for dynamic buffers */ + goto out_handled; + default: + return false; + } + +out_handled: + ffa_to_smccc_res_prop(res, ret, prop); + return true; +} + +bool kvm_host_ffa_handler(struct kvm_cpu_context *host_ctxt) +{ + DECLARE_REG(u64, func_id, host_ctxt, 0); + struct arm_smccc_res res; + + /* + * There's no way we can tell what a non-standard SMC call might + * be up to. Ideally, we would terminate these here and return + * an error to the host, but sadly devices make use of custom + * firmware calls for things like power management, debugging, + * RNG access and crash reporting. + * + * Given that the architecture requires us to trust EL3 anyway, + * we forward unrecognised calls on under the assumption that + * the firmware doesn't expose a mechanism to access arbitrary + * non-secure memory. Short of a per-device table of SMCs, this + * is the best we can do. + */ + if (!is_ffa_call(func_id)) + return false; + + switch (func_id) { + case FFA_FEATURES: + if (!do_ffa_features(&res, host_ctxt)) + return false; + goto out_handled; + /* Memory management */ + case FFA_FN64_RXTX_MAP: + do_ffa_rxtx_map(&res, host_ctxt); + goto out_handled; + case FFA_RXTX_UNMAP: + do_ffa_rxtx_unmap(&res, host_ctxt); + goto out_handled; + case FFA_MEM_SHARE: + case FFA_FN64_MEM_SHARE: + do_ffa_mem_xfer(FFA_FN64_MEM_SHARE, &res, host_ctxt); + goto out_handled; + case FFA_MEM_RECLAIM: + do_ffa_mem_reclaim(&res, host_ctxt); + goto out_handled; + case FFA_MEM_LEND: + case FFA_FN64_MEM_LEND: + do_ffa_mem_xfer(FFA_FN64_MEM_LEND, &res, host_ctxt); + goto out_handled; + case FFA_MEM_FRAG_TX: + do_ffa_mem_frag_tx(&res, host_ctxt); + goto out_handled; + } + + if (ffa_call_supported(func_id)) + return false; /* Pass through */ + + ffa_to_smccc_error(&res, FFA_RET_NOT_SUPPORTED); +out_handled: + ffa_set_retval(host_ctxt, &res); + return true; +} + +int hyp_ffa_init(void *pages) +{ + struct arm_smccc_res res; + size_t min_rxtx_sz; + void *tx, *rx; + + if (kvm_host_psci_config.smccc_version < ARM_SMCCC_VERSION_1_2) + return 0; + + arm_smccc_1_1_smc(FFA_VERSION, FFA_VERSION_1_0, 0, 0, 0, 0, 0, 0, &res); + if (res.a0 == FFA_RET_NOT_SUPPORTED) + return 0; + + if (res.a0 != FFA_VERSION_1_0) + return -EOPNOTSUPP; + + arm_smccc_1_1_smc(FFA_ID_GET, 0, 0, 0, 0, 0, 0, 0, &res); + if (res.a0 != FFA_SUCCESS) + return -EOPNOTSUPP; + + if (res.a2 != HOST_FFA_ID) + return -EINVAL; + + arm_smccc_1_1_smc(FFA_FEATURES, FFA_FN64_RXTX_MAP, + 0, 0, 0, 0, 0, 0, &res); + if (res.a0 != FFA_SUCCESS) + return -EOPNOTSUPP; + + switch (res.a2) { + case FFA_FEAT_RXTX_MIN_SZ_4K: + min_rxtx_sz = SZ_4K; + break; + case FFA_FEAT_RXTX_MIN_SZ_16K: + min_rxtx_sz = SZ_16K; + break; + case FFA_FEAT_RXTX_MIN_SZ_64K: + min_rxtx_sz = SZ_64K; + break; + default: + return -EINVAL; + } + + if (min_rxtx_sz > PAGE_SIZE) + return -EOPNOTSUPP; + + tx = pages; + pages += KVM_FFA_MBOX_NR_PAGES * PAGE_SIZE; + rx = pages; + pages += KVM_FFA_MBOX_NR_PAGES * PAGE_SIZE; + + ffa_desc_buf = (struct kvm_ffa_descriptor_buffer) { + .buf = pages, + .len = PAGE_SIZE * + (hyp_ffa_proxy_pages() - (2 * KVM_FFA_MBOX_NR_PAGES)), + }; + + hyp_buffers = (struct kvm_ffa_buffers) { + .lock = __HYP_SPIN_LOCK_UNLOCKED, + .tx = tx, + .rx = rx, + }; + + host_buffers = (struct kvm_ffa_buffers) { + .lock = __HYP_SPIN_LOCK_UNLOCKED, + }; + + return 0; +} diff --git a/arch/arm64/kvm/hyp/nvhe/host.S b/arch/arm64/kvm/hyp/nvhe/host.S index b6c0188c4b35a9d6f92d061be09b59030c7cc962..c87c63133e10cd94a9c8c9e06b5c5c201298393e 100644 --- a/arch/arm64/kvm/hyp/nvhe/host.S +++ b/arch/arm64/kvm/hyp/nvhe/host.S @@ -10,6 +10,7 @@ #include #include #include +#include .text @@ -37,10 +38,43 @@ SYM_FUNC_START(__host_exit) /* Save the host context pointer in x29 across the function call */ mov x29, x0 + +#ifdef CONFIG_ARM64_PTR_AUTH_KERNEL +alternative_if_not ARM64_HAS_ADDRESS_AUTH +b __skip_pauth_save +alternative_else_nop_endif + +alternative_if ARM64_KVM_PROTECTED_MODE + /* Save kernel ptrauth keys. */ + add x18, x29, #CPU_APIAKEYLO_EL1 + ptrauth_save_state x18, x19, x20 + + /* Use hyp keys. */ + adr_this_cpu x18, kvm_hyp_ctxt, x19 + add x18, x18, #CPU_APIAKEYLO_EL1 + ptrauth_restore_state x18, x19, x20 + isb +alternative_else_nop_endif +__skip_pauth_save: +#endif /* CONFIG_ARM64_PTR_AUTH_KERNEL */ + bl handle_trap - /* Restore host regs x0-x17 */ __host_enter_restore_full: + /* Restore kernel keys. */ +#ifdef CONFIG_ARM64_PTR_AUTH_KERNEL +alternative_if_not ARM64_HAS_ADDRESS_AUTH +b __skip_pauth_restore +alternative_else_nop_endif + +alternative_if ARM64_KVM_PROTECTED_MODE + add x18, x29, #CPU_APIAKEYLO_EL1 + ptrauth_restore_state x18, x19, x20 +alternative_else_nop_endif +__skip_pauth_restore: +#endif /* CONFIG_ARM64_PTR_AUTH_KERNEL */ + + /* Restore host regs x0-x17 */ ldp x0, x1, [x29, #CPU_XREG_OFFSET(0)] ldp x2, x3, [x29, #CPU_XREG_OFFSET(2)] ldp x4, x5, [x29, #CPU_XREG_OFFSET(4)] diff --git a/arch/arm64/kvm/hyp/nvhe/hyp-init.S b/arch/arm64/kvm/hyp/nvhe/hyp-init.S index a6d67c2bb5ae9fc8eb4e74e0ef0b154f6977c887..90fade1b032e4bc614861ebd49e8738042768d65 100644 --- a/arch/arm64/kvm/hyp/nvhe/hyp-init.S +++ b/arch/arm64/kvm/hyp/nvhe/hyp-init.S @@ -83,9 +83,6 @@ SYM_CODE_END(__kvm_hyp_init) * x0: struct kvm_nvhe_init_params PA */ SYM_CODE_START_LOCAL(___kvm_hyp_init) - ldr x1, [x0, #NVHE_INIT_TPIDR_EL2] - msr tpidr_el2, x1 - ldr x1, [x0, #NVHE_INIT_STACK_HYP_VA] mov sp, x1 @@ -95,6 +92,22 @@ SYM_CODE_START_LOCAL(___kvm_hyp_init) ldr x1, [x0, #NVHE_INIT_HCR_EL2] msr hcr_el2, x1 + mov x2, #HCR_E2H + and x2, x1, x2 + cbz x2, 1f + + // hVHE: Replay the EL2 setup to account for the E2H bit + // TPIDR_EL2 is used to preserve x0 across the macro maze... + isb + msr tpidr_el2, x0 + init_el2_state + finalise_el2_state + mrs x0, tpidr_el2 + +1: + ldr x1, [x0, #NVHE_INIT_TPIDR_EL2] + msr tpidr_el2, x1 + ldr x1, [x0, #NVHE_INIT_VTTBR] msr vttbr_el2, x1 @@ -128,6 +141,13 @@ alternative_if ARM64_HAS_ADDRESS_AUTH SCTLR_ELx_ENDA | SCTLR_ELx_ENDB) orr x0, x0, x1 alternative_else_nop_endif + +#ifdef CONFIG_ARM64_BTI_KERNEL +alternative_if ARM64_BTI + orr x0, x0, #SCTLR_EL2_BT +alternative_else_nop_endif +#endif /* CONFIG_ARM64_BTI_KERNEL */ + msr sctlr_el2, x0 isb @@ -184,6 +204,7 @@ SYM_CODE_START_LOCAL(__kvm_hyp_init_cpu) /* Initialize EL2 CPU state to sane values. */ init_el2_state // Clobbers x0..x2 finalise_el2_state + __init_el2_nvhe_prepare_eret /* Enable MMU, set vectors and stack. */ mov x0, x28 @@ -196,6 +217,11 @@ SYM_CODE_START_LOCAL(__kvm_hyp_init_cpu) SYM_CODE_END(__kvm_hyp_init_cpu) SYM_CODE_START(__kvm_handle_stub_hvc) + /* + * __kvm_handle_stub_hvc called from __host_hvc through branch instruction(br) so + * we need bti j at beginning. + */ + bti j cmp x0, #HVC_SOFT_RESTART b.ne 1f diff --git a/arch/arm64/kvm/hyp/nvhe/hyp-main.c b/arch/arm64/kvm/hyp/nvhe/hyp-main.c index 728e01d4536b02d519a591c7aecbc61a75642d47..a169c619db60b85e92f33c631ceb84d27173c674 100644 --- a/arch/arm64/kvm/hyp/nvhe/hyp-main.c +++ b/arch/arm64/kvm/hyp/nvhe/hyp-main.c @@ -13,6 +13,7 @@ #include #include +#include #include #include #include @@ -125,6 +126,15 @@ static void handle___kvm_tlb_flush_vmid_ipa(struct kvm_cpu_context *host_ctxt) __kvm_tlb_flush_vmid_ipa(kern_hyp_va(mmu), ipa, level); } +static void handle___kvm_tlb_flush_vmid_ipa_nsh(struct kvm_cpu_context *host_ctxt) +{ + DECLARE_REG(struct kvm_s2_mmu *, mmu, host_ctxt, 1); + DECLARE_REG(phys_addr_t, ipa, host_ctxt, 2); + DECLARE_REG(int, level, host_ctxt, 3); + + __kvm_tlb_flush_vmid_ipa_nsh(kern_hyp_va(mmu), ipa, level); +} + static void handle___kvm_tlb_flush_vmid(struct kvm_cpu_context *host_ctxt) { DECLARE_REG(struct kvm_s2_mmu *, mmu, host_ctxt, 1); @@ -315,6 +325,7 @@ static const hcall_t host_hcall[] = { HANDLE_FUNC(__kvm_vcpu_run), HANDLE_FUNC(__kvm_flush_vm_context), HANDLE_FUNC(__kvm_tlb_flush_vmid_ipa), + HANDLE_FUNC(__kvm_tlb_flush_vmid_ipa_nsh), HANDLE_FUNC(__kvm_tlb_flush_vmid), HANDLE_FUNC(__kvm_flush_cpu_context), HANDLE_FUNC(__kvm_timer_set_cntvoff), @@ -373,6 +384,8 @@ static void handle_host_smc(struct kvm_cpu_context *host_ctxt) bool handled; handled = kvm_host_psci_handler(host_ctxt); + if (!handled) + handled = kvm_host_ffa_handler(host_ctxt); if (!handled) default_host_smc_handler(host_ctxt); @@ -392,7 +405,11 @@ void handle_trap(struct kvm_cpu_context *host_ctxt) handle_host_smc(host_ctxt); break; case ESR_ELx_EC_SVE: - sysreg_clear_set(cptr_el2, CPTR_EL2_TZ, 0); + if (has_hvhe()) + sysreg_clear_set(cpacr_el1, 0, (CPACR_EL1_ZEN_EL1EN | + CPACR_EL1_ZEN_EL0EN)); + else + sysreg_clear_set(cptr_el2, CPTR_EL2_TZ, 0); isb(); sve_cond_update_zcr_vq(ZCR_ELx_LEN_MASK, SYS_ZCR_EL2); break; diff --git a/arch/arm64/kvm/hyp/nvhe/mem_protect.c b/arch/arm64/kvm/hyp/nvhe/mem_protect.c index a8813b2129966d094e54154dec71c92781c032bb..9d703441278bd72e33cec10adba5b9b0afb145bf 100644 --- a/arch/arm64/kvm/hyp/nvhe/mem_protect.c +++ b/arch/arm64/kvm/hyp/nvhe/mem_protect.c @@ -91,9 +91,9 @@ static void host_s2_put_page(void *addr) hyp_put_page(&host_s2_pool, addr); } -static void host_s2_free_removed_table(void *addr, u32 level) +static void host_s2_free_unlinked_table(void *addr, u32 level) { - kvm_pgtable_stage2_free_removed(&host_mmu.mm_ops, addr, level); + kvm_pgtable_stage2_free_unlinked(&host_mmu.mm_ops, addr, level); } static int prepare_s2_pool(void *pgt_pool_base) @@ -110,7 +110,7 @@ static int prepare_s2_pool(void *pgt_pool_base) host_mmu.mm_ops = (struct kvm_pgtable_mm_ops) { .zalloc_pages_exact = host_s2_zalloc_pages_exact, .zalloc_page = host_s2_zalloc_page, - .free_removed_table = host_s2_free_removed_table, + .free_unlinked_table = host_s2_free_unlinked_table, .phys_to_virt = hyp_phys_to_virt, .virt_to_phys = hyp_virt_to_phys, .page_count = hyp_page_count, @@ -842,6 +842,13 @@ static int check_share(struct pkvm_mem_share *share) case PKVM_ID_HYP: ret = hyp_ack_share(completer_addr, tx, share->completer_prot); break; + case PKVM_ID_FFA: + /* + * We only check the host; the secure side will check the other + * end when we forward the FFA call. + */ + ret = 0; + break; default: ret = -EINVAL; } @@ -870,6 +877,13 @@ static int __do_share(struct pkvm_mem_share *share) case PKVM_ID_HYP: ret = hyp_complete_share(completer_addr, tx, share->completer_prot); break; + case PKVM_ID_FFA: + /* + * We're not responsible for any secure page-tables, so there's + * nothing to do here. + */ + ret = 0; + break; default: ret = -EINVAL; } @@ -918,6 +932,10 @@ static int check_unshare(struct pkvm_mem_share *share) case PKVM_ID_HYP: ret = hyp_ack_unshare(completer_addr, tx); break; + case PKVM_ID_FFA: + /* See check_share() */ + ret = 0; + break; default: ret = -EINVAL; } @@ -946,6 +964,10 @@ static int __do_unshare(struct pkvm_mem_share *share) case PKVM_ID_HYP: ret = hyp_complete_unshare(completer_addr, tx); break; + case PKVM_ID_FFA: + /* See __do_share() */ + ret = 0; + break; default: ret = -EINVAL; } @@ -1235,3 +1257,49 @@ void hyp_unpin_shared_mem(void *from, void *to) hyp_unlock_component(); host_unlock_component(); } + +int __pkvm_host_share_ffa(u64 pfn, u64 nr_pages) +{ + int ret; + struct pkvm_mem_share share = { + .tx = { + .nr_pages = nr_pages, + .initiator = { + .id = PKVM_ID_HOST, + .addr = hyp_pfn_to_phys(pfn), + }, + .completer = { + .id = PKVM_ID_FFA, + }, + }, + }; + + host_lock_component(); + ret = do_share(&share); + host_unlock_component(); + + return ret; +} + +int __pkvm_host_unshare_ffa(u64 pfn, u64 nr_pages) +{ + int ret; + struct pkvm_mem_share share = { + .tx = { + .nr_pages = nr_pages, + .initiator = { + .id = PKVM_ID_HOST, + .addr = hyp_pfn_to_phys(pfn), + }, + .completer = { + .id = PKVM_ID_FFA, + }, + }, + }; + + host_lock_component(); + ret = do_unshare(&share); + host_unlock_component(); + + return ret; +} diff --git a/arch/arm64/kvm/hyp/nvhe/pkvm.c b/arch/arm64/kvm/hyp/nvhe/pkvm.c index a06ece14a6d8ef63fefb15684d6fcacf3876b928..8033ef353a5da406dba355ab73854dfa39e93c27 100644 --- a/arch/arm64/kvm/hyp/nvhe/pkvm.c +++ b/arch/arm64/kvm/hyp/nvhe/pkvm.c @@ -27,6 +27,7 @@ static void pvm_init_traps_aa64pfr0(struct kvm_vcpu *vcpu) u64 hcr_set = HCR_RW; u64 hcr_clear = 0; u64 cptr_set = 0; + u64 cptr_clear = 0; /* Protected KVM does not support AArch32 guests. */ BUILD_BUG_ON(FIELD_GET(ARM64_FEATURE_MASK(ID_AA64PFR0_EL1_EL0), @@ -43,6 +44,9 @@ static void pvm_init_traps_aa64pfr0(struct kvm_vcpu *vcpu) BUILD_BUG_ON(!FIELD_GET(ARM64_FEATURE_MASK(ID_AA64PFR0_EL1_AdvSIMD), PVM_ID_AA64PFR0_ALLOW)); + if (has_hvhe()) + hcr_set |= HCR_E2H; + /* Trap RAS unless all current versions are supported */ if (FIELD_GET(ARM64_FEATURE_MASK(ID_AA64PFR0_EL1_RAS), feature_ids) < ID_AA64PFR0_EL1_RAS_V1P1) { @@ -57,12 +61,17 @@ static void pvm_init_traps_aa64pfr0(struct kvm_vcpu *vcpu) } /* Trap SVE */ - if (!FIELD_GET(ARM64_FEATURE_MASK(ID_AA64PFR0_EL1_SVE), feature_ids)) - cptr_set |= CPTR_EL2_TZ; + if (!FIELD_GET(ARM64_FEATURE_MASK(ID_AA64PFR0_EL1_SVE), feature_ids)) { + if (has_hvhe()) + cptr_clear |= CPACR_EL1_ZEN_EL0EN | CPACR_EL1_ZEN_EL1EN; + else + cptr_set |= CPTR_EL2_TZ; + } vcpu->arch.hcr_el2 |= hcr_set; vcpu->arch.hcr_el2 &= ~hcr_clear; vcpu->arch.cptr_el2 |= cptr_set; + vcpu->arch.cptr_el2 &= ~cptr_clear; } /* @@ -120,8 +129,12 @@ static void pvm_init_traps_aa64dfr0(struct kvm_vcpu *vcpu) mdcr_set |= MDCR_EL2_TTRF; /* Trap Trace */ - if (!FIELD_GET(ARM64_FEATURE_MASK(ID_AA64DFR0_EL1_TraceVer), feature_ids)) - cptr_set |= CPTR_EL2_TTA; + if (!FIELD_GET(ARM64_FEATURE_MASK(ID_AA64DFR0_EL1_TraceVer), feature_ids)) { + if (has_hvhe()) + cptr_set |= CPACR_EL1_TTA; + else + cptr_set |= CPTR_EL2_TTA; + } vcpu->arch.mdcr_el2 |= mdcr_set; vcpu->arch.mdcr_el2 &= ~mdcr_clear; @@ -176,8 +189,10 @@ static void pvm_init_trap_regs(struct kvm_vcpu *vcpu) /* Clear res0 and set res1 bits to trap potential new features. */ vcpu->arch.hcr_el2 &= ~(HCR_RES0); vcpu->arch.mdcr_el2 &= ~(MDCR_EL2_RES0); - vcpu->arch.cptr_el2 |= CPTR_NVHE_EL2_RES1; - vcpu->arch.cptr_el2 &= ~(CPTR_NVHE_EL2_RES0); + if (!has_hvhe()) { + vcpu->arch.cptr_el2 |= CPTR_NVHE_EL2_RES1; + vcpu->arch.cptr_el2 &= ~(CPTR_NVHE_EL2_RES0); + } } /* diff --git a/arch/arm64/kvm/hyp/nvhe/setup.c b/arch/arm64/kvm/hyp/nvhe/setup.c index 110f04627785c8dd0dccebbd2cd674478b255e7b..bb98630dfeafc5013ad942940e3101dee934237f 100644 --- a/arch/arm64/kvm/hyp/nvhe/setup.c +++ b/arch/arm64/kvm/hyp/nvhe/setup.c @@ -11,6 +11,7 @@ #include #include +#include #include #include #include @@ -28,6 +29,7 @@ static void *vmemmap_base; static void *vm_table_base; static void *hyp_pgt_base; static void *host_s2_pgt_base; +static void *ffa_proxy_pages; static struct kvm_pgtable_mm_ops pkvm_pgtable_mm_ops; static struct hyp_pool hpool; @@ -57,6 +59,11 @@ static int divide_memory_pool(void *virt, unsigned long size) if (!host_s2_pgt_base) return -ENOMEM; + nr_pages = hyp_ffa_proxy_pages(); + ffa_proxy_pages = hyp_early_alloc_contig(nr_pages); + if (!ffa_proxy_pages) + return -ENOMEM; + return 0; } @@ -314,6 +321,10 @@ void __noreturn __pkvm_init_finalise(void) if (ret) goto out; + ret = hyp_ffa_init(ffa_proxy_pages); + if (ret) + goto out; + pkvm_hyp_vm_table_init(vm_table_base); out: /* diff --git a/arch/arm64/kvm/hyp/nvhe/switch.c b/arch/arm64/kvm/hyp/nvhe/switch.c index 77791495c9951d60e18fa8f80fd5c22385d65840..0a6271052def0a9c2198d2578c3993ba2b606b81 100644 --- a/arch/arm64/kvm/hyp/nvhe/switch.c +++ b/arch/arm64/kvm/hyp/nvhe/switch.c @@ -44,13 +44,24 @@ static void __activate_traps(struct kvm_vcpu *vcpu) __activate_traps_common(vcpu); val = vcpu->arch.cptr_el2; - val |= CPTR_EL2_TTA | CPTR_EL2_TAM; + val |= CPTR_EL2_TAM; /* Same bit irrespective of E2H */ + val |= has_hvhe() ? CPACR_EL1_TTA : CPTR_EL2_TTA; + if (cpus_have_final_cap(ARM64_SME)) { + if (has_hvhe()) + val &= ~(CPACR_EL1_SMEN_EL1EN | CPACR_EL1_SMEN_EL0EN); + else + val |= CPTR_EL2_TSM; + } + if (!guest_owns_fp_regs(vcpu)) { - val |= CPTR_EL2_TFP | CPTR_EL2_TZ; + if (has_hvhe()) + val &= ~(CPACR_EL1_FPEN_EL0EN | CPACR_EL1_FPEN_EL1EN | + CPACR_EL1_ZEN_EL0EN | CPACR_EL1_ZEN_EL1EN); + else + val |= CPTR_EL2_TFP | CPTR_EL2_TZ; + __activate_traps_fpsimd32(vcpu); } - if (cpus_have_final_cap(ARM64_SME)) - val |= CPTR_EL2_TSM; write_sysreg(val, cptr_el2); write_sysreg(__this_cpu_read(kvm_hyp_vector), vbar_el2); @@ -73,7 +84,6 @@ static void __activate_traps(struct kvm_vcpu *vcpu) static void __deactivate_traps(struct kvm_vcpu *vcpu) { extern char __kvm_hyp_host_vector[]; - u64 cptr; ___deactivate_traps(vcpu); @@ -98,13 +108,7 @@ static void __deactivate_traps(struct kvm_vcpu *vcpu) write_sysreg(this_cpu_ptr(&kvm_init_params)->hcr_el2, hcr_el2); - cptr = CPTR_EL2_DEFAULT; - if (vcpu_has_sve(vcpu) && (vcpu->arch.fp_state == FP_STATE_GUEST_OWNED)) - cptr |= CPTR_EL2_TZ; - if (cpus_have_final_cap(ARM64_SME)) - cptr &= ~CPTR_EL2_TSM; - - write_sysreg(cptr, cptr_el2); + kvm_reset_cptr_el2(vcpu); write_sysreg(__kvm_hyp_host_vector, vbar_el2); } diff --git a/arch/arm64/kvm/hyp/nvhe/timer-sr.c b/arch/arm64/kvm/hyp/nvhe/timer-sr.c index b185ac0dbd4707f612389c1dc6017f3bf0ec764d..3aaab20ae5b4797182de112d1e641112c3f799c7 100644 --- a/arch/arm64/kvm/hyp/nvhe/timer-sr.c +++ b/arch/arm64/kvm/hyp/nvhe/timer-sr.c @@ -17,21 +17,24 @@ void __kvm_timer_set_cntvoff(u64 cntvoff) } /* - * Should only be called on non-VHE systems. + * Should only be called on non-VHE or hVHE setups. * VHE systems use EL2 timers and configure EL1 timers in kvm_timer_init_vhe(). */ void __timer_disable_traps(struct kvm_vcpu *vcpu) { - u64 val; + u64 val, shift = 0; + + if (has_hvhe()) + shift = 10; /* Allow physical timer/counter access for the host */ val = read_sysreg(cnthctl_el2); - val |= CNTHCTL_EL1PCTEN | CNTHCTL_EL1PCEN; + val |= (CNTHCTL_EL1PCTEN | CNTHCTL_EL1PCEN) << shift; write_sysreg(val, cnthctl_el2); } /* - * Should only be called on non-VHE systems. + * Should only be called on non-VHE or hVHE setups. * VHE systems use EL2 timers and configure EL1 timers in kvm_timer_init_vhe(). */ void __timer_enable_traps(struct kvm_vcpu *vcpu) @@ -50,5 +53,10 @@ void __timer_enable_traps(struct kvm_vcpu *vcpu) else clr |= CNTHCTL_EL1PCTEN; + if (has_hvhe()) { + clr <<= 10; + set <<= 10; + } + sysreg_clear_set(cnthctl_el2, clr, set); } diff --git a/arch/arm64/kvm/hyp/nvhe/tlb.c b/arch/arm64/kvm/hyp/nvhe/tlb.c index 978179133f4b97665ae6468b9e69939ac52f86c6..b9991bbd8e3fd47baf911ef84dd7402173603879 100644 --- a/arch/arm64/kvm/hyp/nvhe/tlb.c +++ b/arch/arm64/kvm/hyp/nvhe/tlb.c @@ -130,6 +130,58 @@ void __kvm_tlb_flush_vmid_ipa(struct kvm_s2_mmu *mmu, __tlb_switch_to_host(&cxt); } +void __kvm_tlb_flush_vmid_ipa_nsh(struct kvm_s2_mmu *mmu, + phys_addr_t ipa, int level) +{ + struct tlb_inv_context cxt; + + /* Switch to requested VMID */ + __tlb_switch_to_guest(mmu, &cxt, true); + + /* + * We could do so much better if we had the VA as well. + * Instead, we invalidate Stage-2 for this IPA, and the + * whole of Stage-1. Weep... + */ + ipa >>= 12; + __tlbi_level(ipas2e1, ipa, level); + + /* + * We have to ensure completion of the invalidation at Stage-2, + * since a table walk on another CPU could refill a TLB with a + * complete (S1 + S2) walk based on the old Stage-2 mapping if + * the Stage-1 invalidation happened first. + */ + dsb(nsh); + __tlbi(vmalle1); + dsb(nsh); + isb(); + + /* + * If the host is running at EL1 and we have a VPIPT I-cache, + * then we must perform I-cache maintenance at EL2 in order for + * it to have an effect on the guest. Since the guest cannot hit + * I-cache lines allocated with a different VMID, we don't need + * to worry about junk out of guest reset (we nuke the I-cache on + * VMID rollover), but we do need to be careful when remapping + * executable pages for the same guest. This can happen when KSM + * takes a CoW fault on an executable page, copies the page into + * a page that was previously mapped in the guest and then needs + * to invalidate the guest view of the I-cache for that page + * from EL1. To solve this, we invalidate the entire I-cache when + * unmapping a page from a guest if we have a VPIPT I-cache but + * the host is running at EL1. As above, we could do better if + * we had the VA. + * + * The moral of this story is: if you have a VPIPT I-cache, then + * you should be running with VHE enabled. + */ + if (icache_is_vpipt()) + icache_inval_all_pou(); + + __tlb_switch_to_host(&cxt); +} + void __kvm_tlb_flush_vmid(struct kvm_s2_mmu *mmu) { struct tlb_inv_context cxt; diff --git a/arch/arm64/kvm/hyp/pgtable.c b/arch/arm64/kvm/hyp/pgtable.c index 95dae02ccc2e60c2a830061a23b2e9d8c16e6246..aa740a974e024e28898332a5192d90722b9c0092 100644 --- a/arch/arm64/kvm/hyp/pgtable.c +++ b/arch/arm64/kvm/hyp/pgtable.c @@ -21,8 +21,10 @@ #define KVM_PTE_LEAF_ATTR_LO_S1_ATTRIDX GENMASK(4, 2) #define KVM_PTE_LEAF_ATTR_LO_S1_AP GENMASK(7, 6) -#define KVM_PTE_LEAF_ATTR_LO_S1_AP_RO 3 -#define KVM_PTE_LEAF_ATTR_LO_S1_AP_RW 1 +#define KVM_PTE_LEAF_ATTR_LO_S1_AP_RO \ + ({ cpus_have_final_cap(ARM64_KVM_HVHE) ? 2 : 3; }) +#define KVM_PTE_LEAF_ATTR_LO_S1_AP_RW \ + ({ cpus_have_final_cap(ARM64_KVM_HVHE) ? 0 : 1; }) #define KVM_PTE_LEAF_ATTR_LO_S1_SH GENMASK(9, 8) #define KVM_PTE_LEAF_ATTR_LO_S1_SH_IS 3 #define KVM_PTE_LEAF_ATTR_LO_S1_AF BIT(10) @@ -34,7 +36,7 @@ #define KVM_PTE_LEAF_ATTR_LO_S2_SH_IS 3 #define KVM_PTE_LEAF_ATTR_LO_S2_AF BIT(10) -#define KVM_PTE_LEAF_ATTR_HI GENMASK(63, 51) +#define KVM_PTE_LEAF_ATTR_HI GENMASK(63, 50) #define KVM_PTE_LEAF_ATTR_HI_SW GENMASK(58, 55) @@ -42,6 +44,8 @@ #define KVM_PTE_LEAF_ATTR_HI_S2_XN BIT(54) +#define KVM_PTE_LEAF_ATTR_HI_S1_GP BIT(50) + #define KVM_PTE_LEAF_ATTR_S2_PERMS (KVM_PTE_LEAF_ATTR_LO_S2_S2AP_R | \ KVM_PTE_LEAF_ATTR_LO_S2_S2AP_W | \ KVM_PTE_LEAF_ATTR_HI_S2_XN) @@ -63,6 +67,16 @@ struct kvm_pgtable_walk_data { const u64 end; }; +static bool kvm_pgtable_walk_skip_bbm_tlbi(const struct kvm_pgtable_visit_ctx *ctx) +{ + return unlikely(ctx->flags & KVM_PGTABLE_WALK_SKIP_BBM_TLBI); +} + +static bool kvm_pgtable_walk_skip_cmo(const struct kvm_pgtable_visit_ctx *ctx) +{ + return unlikely(ctx->flags & KVM_PGTABLE_WALK_SKIP_CMO); +} + static bool kvm_phys_is_valid(u64 phys) { return phys < BIT(id_aa64mmfr0_parange_to_phys_shift(ID_AA64MMFR0_EL1_PARANGE_MAX)); @@ -386,6 +400,9 @@ static int hyp_set_prot_attr(enum kvm_pgtable_prot prot, kvm_pte_t *ptep) if (device) return -EINVAL; + + if (IS_ENABLED(CONFIG_ARM64_BTI_KERNEL) && system_supports_bti()) + attr |= KVM_PTE_LEAF_ATTR_HI_S1_GP; } else { attr |= KVM_PTE_LEAF_ATTR_HI_S1_XN; } @@ -623,10 +640,18 @@ u64 kvm_get_vtcr(u64 mmfr0, u64 mmfr1, u32 phys_shift) #ifdef CONFIG_ARM64_HW_AFDBM /* * Enable the Hardware Access Flag management, unconditionally - * on all CPUs. The features is RES0 on CPUs without the support - * and must be ignored by the CPUs. + * on all CPUs. In systems that have asymmetric support for the feature + * this allows KVM to leverage hardware support on the subset of cores + * that implement the feature. + * + * The architecture requires VTCR_EL2.HA to be RES0 (thus ignored by + * hardware) on implementations that do not advertise support for the + * feature. As such, setting HA unconditionally is safe, unless you + * happen to be running on a design that has unadvertised support for + * HAFDBS. Here be dragons. */ - vtcr |= VTCR_EL2_HA; + if (!cpus_have_final_cap(ARM64_WORKAROUND_AMPERE_AC03_CPU_38)) + vtcr |= VTCR_EL2_HA; #endif /* CONFIG_ARM64_HW_AFDBM */ /* Set the vmid bits */ @@ -755,14 +780,17 @@ static bool stage2_try_break_pte(const struct kvm_pgtable_visit_ctx *ctx, if (!stage2_try_set_pte(ctx, KVM_INVALID_PTE_LOCKED)) return false; - /* - * Perform the appropriate TLB invalidation based on the evicted pte - * value (if any). - */ - if (kvm_pte_table(ctx->old, ctx->level)) - kvm_call_hyp(__kvm_tlb_flush_vmid, mmu); - else if (kvm_pte_valid(ctx->old)) - kvm_call_hyp(__kvm_tlb_flush_vmid_ipa, mmu, ctx->addr, ctx->level); + if (!kvm_pgtable_walk_skip_bbm_tlbi(ctx)) { + /* + * Perform the appropriate TLB invalidation based on the + * evicted pte value (if any). + */ + if (kvm_pte_table(ctx->old, ctx->level)) + kvm_call_hyp(__kvm_tlb_flush_vmid, mmu); + else if (kvm_pte_valid(ctx->old)) + kvm_call_hyp(__kvm_tlb_flush_vmid_ipa, mmu, + ctx->addr, ctx->level); + } if (stage2_pte_is_counted(ctx->old)) mm_ops->put_page(ctx->ptep); @@ -869,11 +897,13 @@ static int stage2_map_walker_try_leaf(const struct kvm_pgtable_visit_ctx *ctx, return -EAGAIN; /* Perform CMOs before installation of the guest stage-2 PTE */ - if (mm_ops->dcache_clean_inval_poc && stage2_pte_cacheable(pgt, new)) + if (!kvm_pgtable_walk_skip_cmo(ctx) && mm_ops->dcache_clean_inval_poc && + stage2_pte_cacheable(pgt, new)) mm_ops->dcache_clean_inval_poc(kvm_pte_follow(new, mm_ops), - granule); + granule); - if (mm_ops->icache_inval_pou && stage2_pte_executable(new)) + if (!kvm_pgtable_walk_skip_cmo(ctx) && mm_ops->icache_inval_pou && + stage2_pte_executable(new)) mm_ops->icache_inval_pou(kvm_pte_follow(new, mm_ops), granule); stage2_make_pte(ctx, new); @@ -895,7 +925,7 @@ static int stage2_map_walk_table_pre(const struct kvm_pgtable_visit_ctx *ctx, if (ret) return ret; - mm_ops->free_removed_table(childp, ctx->level); + mm_ops->free_unlinked_table(childp, ctx->level); return 0; } @@ -940,7 +970,7 @@ static int stage2_map_walk_leaf(const struct kvm_pgtable_visit_ctx *ctx, * The TABLE_PRE callback runs for table entries on the way down, looking * for table entries which we could conceivably replace with a block entry * for this mapping. If it finds one it replaces the entry and calls - * kvm_pgtable_mm_ops::free_removed_table() to tear down the detached table. + * kvm_pgtable_mm_ops::free_unlinked_table() to tear down the detached table. * * Otherwise, the LEAF callback performs the mapping at the existing leaves * instead. @@ -1209,7 +1239,7 @@ int kvm_pgtable_stage2_relax_perms(struct kvm_pgtable *pgt, u64 addr, KVM_PGTABLE_WALK_HANDLE_FAULT | KVM_PGTABLE_WALK_SHARED); if (!ret) - kvm_call_hyp(__kvm_tlb_flush_vmid_ipa, pgt->mmu, addr, level); + kvm_call_hyp(__kvm_tlb_flush_vmid_ipa_nsh, pgt->mmu, addr, level); return ret; } @@ -1242,6 +1272,162 @@ int kvm_pgtable_stage2_flush(struct kvm_pgtable *pgt, u64 addr, u64 size) return kvm_pgtable_walk(pgt, addr, size, &walker); } +kvm_pte_t *kvm_pgtable_stage2_create_unlinked(struct kvm_pgtable *pgt, + u64 phys, u32 level, + enum kvm_pgtable_prot prot, + void *mc, bool force_pte) +{ + struct stage2_map_data map_data = { + .phys = phys, + .mmu = pgt->mmu, + .memcache = mc, + .force_pte = force_pte, + }; + struct kvm_pgtable_walker walker = { + .cb = stage2_map_walker, + .flags = KVM_PGTABLE_WALK_LEAF | + KVM_PGTABLE_WALK_SKIP_BBM_TLBI | + KVM_PGTABLE_WALK_SKIP_CMO, + .arg = &map_data, + }; + /* + * The input address (.addr) is irrelevant for walking an + * unlinked table. Construct an ambiguous IA range to map + * kvm_granule_size(level) worth of memory. + */ + struct kvm_pgtable_walk_data data = { + .walker = &walker, + .addr = 0, + .end = kvm_granule_size(level), + }; + struct kvm_pgtable_mm_ops *mm_ops = pgt->mm_ops; + kvm_pte_t *pgtable; + int ret; + + if (!IS_ALIGNED(phys, kvm_granule_size(level))) + return ERR_PTR(-EINVAL); + + ret = stage2_set_prot_attr(pgt, prot, &map_data.attr); + if (ret) + return ERR_PTR(ret); + + pgtable = mm_ops->zalloc_page(mc); + if (!pgtable) + return ERR_PTR(-ENOMEM); + + ret = __kvm_pgtable_walk(&data, mm_ops, (kvm_pteref_t)pgtable, + level + 1); + if (ret) { + kvm_pgtable_stage2_free_unlinked(mm_ops, pgtable, level); + mm_ops->put_page(pgtable); + return ERR_PTR(ret); + } + + return pgtable; +} + +/* + * Get the number of page-tables needed to replace a block with a + * fully populated tree up to the PTE entries. Note that @level is + * interpreted as in "level @level entry". + */ +static int stage2_block_get_nr_page_tables(u32 level) +{ + switch (level) { + case 1: + return PTRS_PER_PTE + 1; + case 2: + return 1; + case 3: + return 0; + default: + WARN_ON_ONCE(level < KVM_PGTABLE_MIN_BLOCK_LEVEL || + level >= KVM_PGTABLE_MAX_LEVELS); + return -EINVAL; + }; +} + +static int stage2_split_walker(const struct kvm_pgtable_visit_ctx *ctx, + enum kvm_pgtable_walk_flags visit) +{ + struct kvm_pgtable_mm_ops *mm_ops = ctx->mm_ops; + struct kvm_mmu_memory_cache *mc = ctx->arg; + struct kvm_s2_mmu *mmu; + kvm_pte_t pte = ctx->old, new, *childp; + enum kvm_pgtable_prot prot; + u32 level = ctx->level; + bool force_pte; + int nr_pages; + u64 phys; + + /* No huge-pages exist at the last level */ + if (level == KVM_PGTABLE_MAX_LEVELS - 1) + return 0; + + /* We only split valid block mappings */ + if (!kvm_pte_valid(pte)) + return 0; + + nr_pages = stage2_block_get_nr_page_tables(level); + if (nr_pages < 0) + return nr_pages; + + if (mc->nobjs >= nr_pages) { + /* Build a tree mapped down to the PTE granularity. */ + force_pte = true; + } else { + /* + * Don't force PTEs, so create_unlinked() below does + * not populate the tree up to the PTE level. The + * consequence is that the call will require a single + * page of level 2 entries at level 1, or a single + * page of PTEs at level 2. If we are at level 1, the + * PTEs will be created recursively. + */ + force_pte = false; + nr_pages = 1; + } + + if (mc->nobjs < nr_pages) + return -ENOMEM; + + mmu = container_of(mc, struct kvm_s2_mmu, split_page_cache); + phys = kvm_pte_to_phys(pte); + prot = kvm_pgtable_stage2_pte_prot(pte); + + childp = kvm_pgtable_stage2_create_unlinked(mmu->pgt, phys, + level, prot, mc, force_pte); + if (IS_ERR(childp)) + return PTR_ERR(childp); + + if (!stage2_try_break_pte(ctx, mmu)) { + kvm_pgtable_stage2_free_unlinked(mm_ops, childp, level); + mm_ops->put_page(childp); + return -EAGAIN; + } + + /* + * Note, the contents of the page table are guaranteed to be made + * visible before the new PTE is assigned because stage2_make_pte() + * writes the PTE using smp_store_release(). + */ + new = kvm_init_table_pte(childp, mm_ops); + stage2_make_pte(ctx, new); + dsb(ishst); + return 0; +} + +int kvm_pgtable_stage2_split(struct kvm_pgtable *pgt, u64 addr, u64 size, + struct kvm_mmu_memory_cache *mc) +{ + struct kvm_pgtable_walker walker = { + .cb = stage2_split_walker, + .flags = KVM_PGTABLE_WALK_LEAF, + .arg = mc, + }; + + return kvm_pgtable_walk(pgt, addr, size, &walker); +} int __kvm_pgtable_stage2_init(struct kvm_pgtable *pgt, struct kvm_s2_mmu *mmu, struct kvm_pgtable_mm_ops *mm_ops, @@ -1311,7 +1497,7 @@ void kvm_pgtable_stage2_destroy(struct kvm_pgtable *pgt) pgt->pgd = NULL; } -void kvm_pgtable_stage2_free_removed(struct kvm_pgtable_mm_ops *mm_ops, void *pgtable, u32 level) +void kvm_pgtable_stage2_free_unlinked(struct kvm_pgtable_mm_ops *mm_ops, void *pgtable, u32 level) { kvm_pteref_t ptep = (kvm_pteref_t)pgtable; struct kvm_pgtable_walker walker = { diff --git a/arch/arm64/kvm/hyp/vhe/switch.c b/arch/arm64/kvm/hyp/vhe/switch.c index 7a1aa511e7da6f68fc88eb4a6b39dcb7927ded09..6537f58b1a8cc026f087f4f73affe42e8f38873b 100644 --- a/arch/arm64/kvm/hyp/vhe/switch.c +++ b/arch/arm64/kvm/hyp/vhe/switch.c @@ -84,7 +84,7 @@ static void __deactivate_traps(struct kvm_vcpu *vcpu) */ asm(ALTERNATIVE("nop", "isb", ARM64_WORKAROUND_SPECULATIVE_AT)); - write_sysreg(CPACR_EL1_DEFAULT, cpacr_el1); + kvm_reset_cptr_el2(vcpu); if (!arm64_kernel_unmapped_at_el0()) host_vectors = __this_cpu_read(this_cpu_vector); @@ -92,14 +92,28 @@ static void __deactivate_traps(struct kvm_vcpu *vcpu) } NOKPROBE_SYMBOL(__deactivate_traps); +/* + * Disable IRQs in {activate,deactivate}_traps_vhe_{load,put}() to + * prevent a race condition between context switching of PMUSERENR_EL0 + * in __{activate,deactivate}_traps_common() and IPIs that attempts to + * update PMUSERENR_EL0. See also kvm_set_pmuserenr(). + */ void activate_traps_vhe_load(struct kvm_vcpu *vcpu) { + unsigned long flags; + + local_irq_save(flags); __activate_traps_common(vcpu); + local_irq_restore(flags); } void deactivate_traps_vhe_put(struct kvm_vcpu *vcpu) { + unsigned long flags; + + local_irq_save(flags); __deactivate_traps_common(vcpu); + local_irq_restore(flags); } static const exit_handler_fn hyp_exit_handlers[] = { diff --git a/arch/arm64/kvm/hyp/vhe/tlb.c b/arch/arm64/kvm/hyp/vhe/tlb.c index 24cef9b87f9e9cee40e7e85e38236931a9d5a29a..e69da550cdc5b50b5dce1de0283608ac063e7d27 100644 --- a/arch/arm64/kvm/hyp/vhe/tlb.c +++ b/arch/arm64/kvm/hyp/vhe/tlb.c @@ -111,6 +111,38 @@ void __kvm_tlb_flush_vmid_ipa(struct kvm_s2_mmu *mmu, __tlb_switch_to_host(&cxt); } +void __kvm_tlb_flush_vmid_ipa_nsh(struct kvm_s2_mmu *mmu, + phys_addr_t ipa, int level) +{ + struct tlb_inv_context cxt; + + dsb(nshst); + + /* Switch to requested VMID */ + __tlb_switch_to_guest(mmu, &cxt); + + /* + * We could do so much better if we had the VA as well. + * Instead, we invalidate Stage-2 for this IPA, and the + * whole of Stage-1. Weep... + */ + ipa >>= 12; + __tlbi_level(ipas2e1, ipa, level); + + /* + * We have to ensure completion of the invalidation at Stage-2, + * since a table walk on another CPU could refill a TLB with a + * complete (S1 + S2) walk based on the old Stage-2 mapping if + * the Stage-1 invalidation happened first. + */ + dsb(nsh); + __tlbi(vmalle1); + dsb(nsh); + isb(); + + __tlb_switch_to_host(&cxt); +} + void __kvm_tlb_flush_vmid(struct kvm_s2_mmu *mmu) { struct tlb_inv_context cxt; diff --git a/arch/arm64/kvm/mmu.c b/arch/arm64/kvm/mmu.c index 3b9d4d24c361ae4f903e12c19df146dcb90c9db8..6db9ef288ec388ed62e4275a3b6b63d17f6d022d 100644 --- a/arch/arm64/kvm/mmu.c +++ b/arch/arm64/kvm/mmu.c @@ -31,14 +31,21 @@ static phys_addr_t __ro_after_init hyp_idmap_vector; static unsigned long __ro_after_init io_map_base; -static phys_addr_t stage2_range_addr_end(phys_addr_t addr, phys_addr_t end) +static phys_addr_t __stage2_range_addr_end(phys_addr_t addr, phys_addr_t end, + phys_addr_t size) { - phys_addr_t size = kvm_granule_size(KVM_PGTABLE_MIN_BLOCK_LEVEL); phys_addr_t boundary = ALIGN_DOWN(addr + size, size); return (boundary - 1 < end - 1) ? boundary : end; } +static phys_addr_t stage2_range_addr_end(phys_addr_t addr, phys_addr_t end) +{ + phys_addr_t size = kvm_granule_size(KVM_PGTABLE_MIN_BLOCK_LEVEL); + + return __stage2_range_addr_end(addr, end, size); +} + /* * Release kvm_mmu_lock periodically if the memory region is large. Otherwise, * we may see kernel panics with CONFIG_DETECT_HUNG_TASK, @@ -75,6 +82,79 @@ static int stage2_apply_range(struct kvm_s2_mmu *mmu, phys_addr_t addr, #define stage2_apply_range_resched(mmu, addr, end, fn) \ stage2_apply_range(mmu, addr, end, fn, true) +/* + * Get the maximum number of page-tables pages needed to split a range + * of blocks into PAGE_SIZE PTEs. It assumes the range is already + * mapped at level 2, or at level 1 if allowed. + */ +static int kvm_mmu_split_nr_page_tables(u64 range) +{ + int n = 0; + + if (KVM_PGTABLE_MIN_BLOCK_LEVEL < 2) + n += DIV_ROUND_UP(range, PUD_SIZE); + n += DIV_ROUND_UP(range, PMD_SIZE); + return n; +} + +static bool need_split_memcache_topup_or_resched(struct kvm *kvm) +{ + struct kvm_mmu_memory_cache *cache; + u64 chunk_size, min; + + if (need_resched() || rwlock_needbreak(&kvm->mmu_lock)) + return true; + + chunk_size = kvm->arch.mmu.split_page_chunk_size; + min = kvm_mmu_split_nr_page_tables(chunk_size); + cache = &kvm->arch.mmu.split_page_cache; + return kvm_mmu_memory_cache_nr_free_objects(cache) < min; +} + +static int kvm_mmu_split_huge_pages(struct kvm *kvm, phys_addr_t addr, + phys_addr_t end) +{ + struct kvm_mmu_memory_cache *cache; + struct kvm_pgtable *pgt; + int ret, cache_capacity; + u64 next, chunk_size; + + lockdep_assert_held_write(&kvm->mmu_lock); + + chunk_size = kvm->arch.mmu.split_page_chunk_size; + cache_capacity = kvm_mmu_split_nr_page_tables(chunk_size); + + if (chunk_size == 0) + return 0; + + cache = &kvm->arch.mmu.split_page_cache; + + do { + if (need_split_memcache_topup_or_resched(kvm)) { + write_unlock(&kvm->mmu_lock); + cond_resched(); + /* Eager page splitting is best-effort. */ + ret = __kvm_mmu_topup_memory_cache(cache, + cache_capacity, + cache_capacity); + write_lock(&kvm->mmu_lock); + if (ret) + break; + } + + pgt = kvm->arch.mmu.pgt; + if (!pgt) + return -EINVAL; + + next = __stage2_range_addr_end(addr, end, chunk_size); + ret = kvm_pgtable_stage2_split(pgt, addr, next - addr, cache); + if (ret) + break; + } while (addr = next, addr != end); + + return ret; +} + static bool memslot_is_logging(struct kvm_memory_slot *memslot) { return memslot->dirty_bitmap && !(memslot->flags & KVM_MEM_READONLY); @@ -131,21 +211,21 @@ static void kvm_s2_free_pages_exact(void *virt, size_t size) static struct kvm_pgtable_mm_ops kvm_s2_mm_ops; -static void stage2_free_removed_table_rcu_cb(struct rcu_head *head) +static void stage2_free_unlinked_table_rcu_cb(struct rcu_head *head) { struct page *page = container_of(head, struct page, rcu_head); void *pgtable = page_to_virt(page); u32 level = page_private(page); - kvm_pgtable_stage2_free_removed(&kvm_s2_mm_ops, pgtable, level); + kvm_pgtable_stage2_free_unlinked(&kvm_s2_mm_ops, pgtable, level); } -static void stage2_free_removed_table(void *addr, u32 level) +static void stage2_free_unlinked_table(void *addr, u32 level) { struct page *page = virt_to_page(addr); set_page_private(page, (unsigned long)level); - call_rcu(&page->rcu_head, stage2_free_removed_table_rcu_cb); + call_rcu(&page->rcu_head, stage2_free_unlinked_table_rcu_cb); } static void kvm_host_get_page(void *addr) @@ -701,7 +781,7 @@ static struct kvm_pgtable_mm_ops kvm_s2_mm_ops = { .zalloc_page = stage2_memcache_zalloc_page, .zalloc_pages_exact = kvm_s2_zalloc_pages_exact, .free_pages_exact = kvm_s2_free_pages_exact, - .free_removed_table = stage2_free_removed_table, + .free_unlinked_table = stage2_free_unlinked_table, .get_page = kvm_host_get_page, .put_page = kvm_s2_put_page, .page_count = kvm_host_page_count, @@ -775,6 +855,10 @@ int kvm_init_stage2_mmu(struct kvm *kvm, struct kvm_s2_mmu *mmu, unsigned long t for_each_possible_cpu(cpu) *per_cpu_ptr(mmu->last_vcpu_ran, cpu) = -1; + /* The eager page splitting is disabled by default */ + mmu->split_page_chunk_size = KVM_ARM_EAGER_SPLIT_CHUNK_SIZE_DEFAULT; + mmu->split_page_cache.gfp_zero = __GFP_ZERO; + mmu->pgt = pgt; mmu->pgd_phys = __pa(pgt->pgd); return 0; @@ -786,6 +870,12 @@ int kvm_init_stage2_mmu(struct kvm *kvm, struct kvm_s2_mmu *mmu, unsigned long t return err; } +void kvm_uninit_stage2_mmu(struct kvm *kvm) +{ + kvm_free_stage2_pgd(&kvm->arch.mmu); + kvm_mmu_free_memory_cache(&kvm->arch.mmu.split_page_cache); +} + static void stage2_unmap_memslot(struct kvm *kvm, struct kvm_memory_slot *memslot) { @@ -989,39 +1079,66 @@ static void kvm_mmu_wp_memory_region(struct kvm *kvm, int slot) } /** - * kvm_mmu_write_protect_pt_masked() - write protect dirty pages + * kvm_mmu_split_memory_region() - split the stage 2 blocks into PAGE_SIZE + * pages for memory slot * @kvm: The KVM pointer - * @slot: The memory slot associated with mask - * @gfn_offset: The gfn offset in memory slot - * @mask: The mask of dirty pages at offset 'gfn_offset' in this memory - * slot to be write protected + * @slot: The memory slot to split * - * Walks bits set in mask write protects the associated pte's. Caller must - * acquire kvm_mmu_lock. + * Acquires kvm->mmu_lock. Called with kvm->slots_lock mutex acquired, + * serializing operations for VM memory regions. */ -static void kvm_mmu_write_protect_pt_masked(struct kvm *kvm, - struct kvm_memory_slot *slot, - gfn_t gfn_offset, unsigned long mask) +static void kvm_mmu_split_memory_region(struct kvm *kvm, int slot) { - phys_addr_t base_gfn = slot->base_gfn + gfn_offset; - phys_addr_t start = (base_gfn + __ffs(mask)) << PAGE_SHIFT; - phys_addr_t end = (base_gfn + __fls(mask) + 1) << PAGE_SHIFT; + struct kvm_memslots *slots; + struct kvm_memory_slot *memslot; + phys_addr_t start, end; - stage2_wp_range(&kvm->arch.mmu, start, end); + lockdep_assert_held(&kvm->slots_lock); + + slots = kvm_memslots(kvm); + memslot = id_to_memslot(slots, slot); + + start = memslot->base_gfn << PAGE_SHIFT; + end = (memslot->base_gfn + memslot->npages) << PAGE_SHIFT; + + write_lock(&kvm->mmu_lock); + kvm_mmu_split_huge_pages(kvm, start, end); + write_unlock(&kvm->mmu_lock); } /* - * kvm_arch_mmu_enable_log_dirty_pt_masked - enable dirty logging for selected - * dirty pages. + * kvm_arch_mmu_enable_log_dirty_pt_masked() - enable dirty logging for selected pages. + * @kvm: The KVM pointer + * @slot: The memory slot associated with mask + * @gfn_offset: The gfn offset in memory slot + * @mask: The mask of pages at offset 'gfn_offset' in this memory + * slot to enable dirty logging on * - * It calls kvm_mmu_write_protect_pt_masked to write protect selected pages to - * enable dirty logging for them. + * Writes protect selected pages to enable dirty logging, and then + * splits them to PAGE_SIZE. Caller must acquire kvm->mmu_lock. */ void kvm_arch_mmu_enable_log_dirty_pt_masked(struct kvm *kvm, struct kvm_memory_slot *slot, gfn_t gfn_offset, unsigned long mask) { - kvm_mmu_write_protect_pt_masked(kvm, slot, gfn_offset, mask); + phys_addr_t base_gfn = slot->base_gfn + gfn_offset; + phys_addr_t start = (base_gfn + __ffs(mask)) << PAGE_SHIFT; + phys_addr_t end = (base_gfn + __fls(mask) + 1) << PAGE_SHIFT; + + lockdep_assert_held_write(&kvm->mmu_lock); + + stage2_wp_range(&kvm->arch.mmu, start, end); + + /* + * Eager-splitting is done when manual-protect is set. We + * also check for initially-all-set because we can avoid + * eager-splitting if initially-all-set is false. + * Initially-all-set equal false implies that huge-pages were + * already split when enabling dirty logging: no need to do it + * again. + */ + if (kvm_dirty_log_manual_protect_and_init_set(kvm)) + kvm_mmu_split_huge_pages(kvm, start, end); } static void kvm_send_hwpoison_signal(unsigned long address, short lsb) @@ -1790,20 +1907,42 @@ void kvm_arch_commit_memory_region(struct kvm *kvm, const struct kvm_memory_slot *new, enum kvm_mr_change change) { + bool log_dirty_pages = new && new->flags & KVM_MEM_LOG_DIRTY_PAGES; + /* * At this point memslot has been committed and there is an * allocated dirty_bitmap[], dirty pages will be tracked while the * memory slot is write protected. */ - if (change != KVM_MR_DELETE && new->flags & KVM_MEM_LOG_DIRTY_PAGES) { + if (log_dirty_pages) { + + if (change == KVM_MR_DELETE) + return; + /* - * If we're with initial-all-set, we don't need to write - * protect any pages because they're all reported as dirty. - * Huge pages and normal pages will be write protect gradually. + * Huge and normal pages are write-protected and split + * on either of these two cases: + * + * 1. with initial-all-set: gradually with CLEAR ioctls, */ - if (!kvm_dirty_log_manual_protect_and_init_set(kvm)) { - kvm_mmu_wp_memory_region(kvm, new->id); - } + if (kvm_dirty_log_manual_protect_and_init_set(kvm)) + return; + /* + * or + * 2. without initial-all-set: all in one shot when + * enabling dirty logging. + */ + kvm_mmu_wp_memory_region(kvm, new->id); + kvm_mmu_split_memory_region(kvm, new->id); + } else { + /* + * Free any leftovers from the eager page splitting cache. Do + * this when deleting, moving, disabling dirty logging, or + * creating the memslot (a nop). Doing it for deletes makes + * sure we don't leak memory, and there's no need to keep the + * cache around for any of the other cases. + */ + kvm_mmu_free_memory_cache(&kvm->arch.mmu.split_page_cache); } } @@ -1877,7 +2016,7 @@ void kvm_arch_memslots_updated(struct kvm *kvm, u64 gen) void kvm_arch_flush_shadow_all(struct kvm *kvm) { - kvm_free_stage2_pgd(&kvm->arch.mmu); + kvm_uninit_stage2_mmu(kvm); } void kvm_arch_flush_shadow_memslot(struct kvm *kvm, diff --git a/arch/arm64/kvm/pkvm.c b/arch/arm64/kvm/pkvm.c index 6e9ece1ebbe728163bf69303cccf7335905c2c5f..994a494703c3c05b132d6d23c354fc09fd1cb386 100644 --- a/arch/arm64/kvm/pkvm.c +++ b/arch/arm64/kvm/pkvm.c @@ -78,6 +78,7 @@ void __init kvm_hyp_reserve(void) hyp_mem_pages += host_s2_pgtable_pages(); hyp_mem_pages += hyp_vm_table_pages(); hyp_mem_pages += hyp_vmemmap_pages(STRUCT_HYP_PAGE_SIZE); + hyp_mem_pages += hyp_ffa_proxy_pages(); /* * Try to allocate a PMD-aligned region to reduce TLB pressure once diff --git a/arch/arm64/kvm/pmu-emul.c b/arch/arm64/kvm/pmu-emul.c index 491ca7eb2a4c6e186abbbae9112942e0420f0116..5606509724787383ef90fb87e30ec4008303e6f9 100644 --- a/arch/arm64/kvm/pmu-emul.c +++ b/arch/arm64/kvm/pmu-emul.c @@ -700,7 +700,25 @@ static struct arm_pmu *kvm_pmu_probe_armpmu(void) mutex_lock(&arm_pmus_lock); - cpu = smp_processor_id(); + /* + * It is safe to use a stale cpu to iterate the list of PMUs so long as + * the same value is used for the entirety of the loop. Given this, and + * the fact that no percpu data is used for the lookup there is no need + * to disable preemption. + * + * It is still necessary to get a valid cpu, though, to probe for the + * default PMU instance as userspace is not required to specify a PMU + * type. In order to uphold the preexisting behavior KVM selects the + * PMU instance for the core where the first call to the + * KVM_ARM_VCPU_PMU_V3_CTRL attribute group occurs. A dependent use case + * would be a user with disdain of all things big.LITTLE that affines + * the VMM to a particular cluster of cores. + * + * In any case, userspace should just do the sane thing and use the UAPI + * to select a PMU type directly. But, be wary of the baggage being + * carried here. + */ + cpu = raw_smp_processor_id(); list_for_each_entry(entry, &arm_pmus, entry) { tmp = entry->arm_pmu; diff --git a/arch/arm64/kvm/pmu.c b/arch/arm64/kvm/pmu.c index 7887133d15f0b67f8b04c2c01b8c17ed2d9cb5d8..121f1a14c829c2804127427d4331d91d84d1ab13 100644 --- a/arch/arm64/kvm/pmu.c +++ b/arch/arm64/kvm/pmu.c @@ -209,3 +209,30 @@ void kvm_vcpu_pmu_restore_host(struct kvm_vcpu *vcpu) kvm_vcpu_pmu_enable_el0(events_host); kvm_vcpu_pmu_disable_el0(events_guest); } + +/* + * With VHE, keep track of the PMUSERENR_EL0 value for the host EL0 on the pCPU + * where PMUSERENR_EL0 for the guest is loaded, since PMUSERENR_EL0 is switched + * to the value for the guest on vcpu_load(). The value for the host EL0 + * will be restored on vcpu_put(), before returning to userspace. + * This isn't necessary for nVHE, as the register is context switched for + * every guest enter/exit. + * + * Return true if KVM takes care of the register. Otherwise return false. + */ +bool kvm_set_pmuserenr(u64 val) +{ + struct kvm_cpu_context *hctxt; + struct kvm_vcpu *vcpu; + + if (!kvm_arm_support_pmu_v3() || !has_vhe()) + return false; + + vcpu = kvm_get_running_vcpu(); + if (!vcpu || !vcpu_get_flag(vcpu, PMUSERENR_ON_CPU)) + return false; + + hctxt = &this_cpu_ptr(&kvm_host_data)->host_ctxt; + ctxt_sys_reg(hctxt, PMUSERENR_EL0) = val; + return true; +} diff --git a/arch/arm64/kvm/reset.c b/arch/arm64/kvm/reset.c index b5dee8e57e77a4e8cf27262b65242be3f3c63b0c..bc8556b6f459063d6e3f03ee9c56d4806751611c 100644 --- a/arch/arm64/kvm/reset.c +++ b/arch/arm64/kvm/reset.c @@ -186,57 +186,6 @@ static int kvm_vcpu_enable_ptrauth(struct kvm_vcpu *vcpu) return 0; } -/** - * kvm_set_vm_width() - set the register width for the guest - * @vcpu: Pointer to the vcpu being configured - * - * Set both KVM_ARCH_FLAG_EL1_32BIT and KVM_ARCH_FLAG_REG_WIDTH_CONFIGURED - * in the VM flags based on the vcpu's requested register width, the HW - * capabilities and other options (such as MTE). - * When REG_WIDTH_CONFIGURED is already set, the vcpu settings must be - * consistent with the value of the FLAG_EL1_32BIT bit in the flags. - * - * Return: 0 on success, negative error code on failure. - */ -static int kvm_set_vm_width(struct kvm_vcpu *vcpu) -{ - struct kvm *kvm = vcpu->kvm; - bool is32bit; - - is32bit = vcpu_has_feature(vcpu, KVM_ARM_VCPU_EL1_32BIT); - - lockdep_assert_held(&kvm->arch.config_lock); - - if (test_bit(KVM_ARCH_FLAG_REG_WIDTH_CONFIGURED, &kvm->arch.flags)) { - /* - * The guest's register width is already configured. - * Make sure that the vcpu is consistent with it. - */ - if (is32bit == test_bit(KVM_ARCH_FLAG_EL1_32BIT, &kvm->arch.flags)) - return 0; - - return -EINVAL; - } - - if (!cpus_have_const_cap(ARM64_HAS_32BIT_EL1) && is32bit) - return -EINVAL; - - /* MTE is incompatible with AArch32 */ - if (kvm_has_mte(kvm) && is32bit) - return -EINVAL; - - /* NV is incompatible with AArch32 */ - if (vcpu_has_nv(vcpu) && is32bit) - return -EINVAL; - - if (is32bit) - set_bit(KVM_ARCH_FLAG_EL1_32BIT, &kvm->arch.flags); - - set_bit(KVM_ARCH_FLAG_REG_WIDTH_CONFIGURED, &kvm->arch.flags); - - return 0; -} - /** * kvm_reset_vcpu - sets core registers and sys_regs to reset value * @vcpu: The VCPU pointer @@ -262,13 +211,6 @@ int kvm_reset_vcpu(struct kvm_vcpu *vcpu) bool loaded; u32 pstate; - mutex_lock(&vcpu->kvm->arch.config_lock); - ret = kvm_set_vm_width(vcpu); - mutex_unlock(&vcpu->kvm->arch.config_lock); - - if (ret) - return ret; - spin_lock(&vcpu->arch.mp_state_lock); reset_state = vcpu->arch.reset_state; vcpu->arch.reset_state.reset = false; diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index 753aa741814977728778648fc7e3c7e05644ab51..bd3431823ec547d7dc1a945e20b00fd6f87c4cae 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -42,6 +42,8 @@ */ static u64 sys_reg_to_index(const struct sys_reg_desc *reg); +static int set_id_reg(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd, + u64 val); static bool read_from_write_only(struct kvm_vcpu *vcpu, struct sys_reg_params *params, @@ -401,9 +403,9 @@ static bool trap_oslar_el1(struct kvm_vcpu *vcpu, return read_from_write_only(vcpu, p, r); /* Forward the OSLK bit to OSLSR */ - oslsr = __vcpu_sys_reg(vcpu, OSLSR_EL1) & ~SYS_OSLSR_OSLK; - if (p->regval & SYS_OSLAR_OSLK) - oslsr |= SYS_OSLSR_OSLK; + oslsr = __vcpu_sys_reg(vcpu, OSLSR_EL1) & ~OSLSR_EL1_OSLK; + if (p->regval & OSLAR_EL1_OSLK) + oslsr |= OSLSR_EL1_OSLK; __vcpu_sys_reg(vcpu, OSLSR_EL1) = oslsr; return true; @@ -427,7 +429,7 @@ static int set_oslsr_el1(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd, * The only modifiable bit is the OSLK bit. Refuse the write if * userspace attempts to change any other bit in the register. */ - if ((val ^ rd->val) & ~SYS_OSLSR_OSLK) + if ((val ^ rd->val) & ~OSLSR_EL1_OSLK) return -EINVAL; __vcpu_sys_reg(vcpu, rd->reg) = val; @@ -553,10 +555,11 @@ static int get_bvr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd, return 0; } -static void reset_bvr(struct kvm_vcpu *vcpu, +static u64 reset_bvr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd) { vcpu->arch.vcpu_debug_state.dbg_bvr[rd->CRm] = rd->val; + return rd->val; } static bool trap_bcr(struct kvm_vcpu *vcpu, @@ -589,10 +592,11 @@ static int get_bcr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd, return 0; } -static void reset_bcr(struct kvm_vcpu *vcpu, +static u64 reset_bcr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd) { vcpu->arch.vcpu_debug_state.dbg_bcr[rd->CRm] = rd->val; + return rd->val; } static bool trap_wvr(struct kvm_vcpu *vcpu, @@ -626,10 +630,11 @@ static int get_wvr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd, return 0; } -static void reset_wvr(struct kvm_vcpu *vcpu, +static u64 reset_wvr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd) { vcpu->arch.vcpu_debug_state.dbg_wvr[rd->CRm] = rd->val; + return rd->val; } static bool trap_wcr(struct kvm_vcpu *vcpu, @@ -662,25 +667,28 @@ static int get_wcr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd, return 0; } -static void reset_wcr(struct kvm_vcpu *vcpu, +static u64 reset_wcr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd) { vcpu->arch.vcpu_debug_state.dbg_wcr[rd->CRm] = rd->val; + return rd->val; } -static void reset_amair_el1(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) +static u64 reset_amair_el1(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) { u64 amair = read_sysreg(amair_el1); vcpu_write_sys_reg(vcpu, amair, AMAIR_EL1); + return amair; } -static void reset_actlr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) +static u64 reset_actlr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) { u64 actlr = read_sysreg(actlr_el1); vcpu_write_sys_reg(vcpu, actlr, ACTLR_EL1); + return actlr; } -static void reset_mpidr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) +static u64 reset_mpidr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) { u64 mpidr; @@ -694,7 +702,10 @@ static void reset_mpidr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) mpidr = (vcpu->vcpu_id & 0x0f) << MPIDR_LEVEL_SHIFT(0); mpidr |= ((vcpu->vcpu_id >> 4) & 0xff) << MPIDR_LEVEL_SHIFT(1); mpidr |= ((vcpu->vcpu_id >> 12) & 0xff) << MPIDR_LEVEL_SHIFT(2); - vcpu_write_sys_reg(vcpu, (1ULL << 31) | mpidr, MPIDR_EL1); + mpidr |= (1ULL << 31); + vcpu_write_sys_reg(vcpu, mpidr, MPIDR_EL1); + + return mpidr; } static unsigned int pmu_visibility(const struct kvm_vcpu *vcpu, @@ -706,13 +717,13 @@ static unsigned int pmu_visibility(const struct kvm_vcpu *vcpu, return REG_HIDDEN; } -static void reset_pmu_reg(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) +static u64 reset_pmu_reg(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) { u64 n, mask = BIT(ARMV8_PMU_CYCLE_IDX); /* No PMU available, any PMU reg may UNDEF... */ if (!kvm_arm_support_pmu_v3()) - return; + return 0; n = read_sysreg(pmcr_el0) >> ARMV8_PMU_PMCR_N_SHIFT; n &= ARMV8_PMU_PMCR_N_MASK; @@ -721,33 +732,41 @@ static void reset_pmu_reg(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) reset_unknown(vcpu, r); __vcpu_sys_reg(vcpu, r->reg) &= mask; + + return __vcpu_sys_reg(vcpu, r->reg); } -static void reset_pmevcntr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) +static u64 reset_pmevcntr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) { reset_unknown(vcpu, r); __vcpu_sys_reg(vcpu, r->reg) &= GENMASK(31, 0); + + return __vcpu_sys_reg(vcpu, r->reg); } -static void reset_pmevtyper(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) +static u64 reset_pmevtyper(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) { reset_unknown(vcpu, r); __vcpu_sys_reg(vcpu, r->reg) &= ARMV8_PMU_EVTYPE_MASK; + + return __vcpu_sys_reg(vcpu, r->reg); } -static void reset_pmselr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) +static u64 reset_pmselr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) { reset_unknown(vcpu, r); __vcpu_sys_reg(vcpu, r->reg) &= ARMV8_PMU_COUNTER_MASK; + + return __vcpu_sys_reg(vcpu, r->reg); } -static void reset_pmcr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) +static u64 reset_pmcr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) { u64 pmcr; /* No PMU available, PMCR_EL0 may UNDEF... */ if (!kvm_arm_support_pmu_v3()) - return; + return 0; /* Only preserve PMCR_EL0.N, and reset the rest to 0 */ pmcr = read_sysreg(pmcr_el0) & (ARMV8_PMU_PMCR_N_MASK << ARMV8_PMU_PMCR_N_SHIFT); @@ -755,6 +774,8 @@ static void reset_pmcr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) pmcr |= ARMV8_PMU_PMCR_LC; __vcpu_sys_reg(vcpu, r->reg) = pmcr; + + return __vcpu_sys_reg(vcpu, r->reg); } static bool check_pmu_access_disabled(struct kvm_vcpu *vcpu, u64 flags) @@ -1187,25 +1208,89 @@ static bool access_arch_timer(struct kvm_vcpu *vcpu, return true; } -static u8 vcpu_pmuver(const struct kvm_vcpu *vcpu) +static s64 kvm_arm64_ftr_safe_value(u32 id, const struct arm64_ftr_bits *ftrp, + s64 new, s64 cur) { - if (kvm_vcpu_has_pmu(vcpu)) - return vcpu->kvm->arch.dfr0_pmuver.imp; + struct arm64_ftr_bits kvm_ftr = *ftrp; + + /* Some features have different safe value type in KVM than host features */ + switch (id) { + case SYS_ID_AA64DFR0_EL1: + if (kvm_ftr.shift == ID_AA64DFR0_EL1_PMUVer_SHIFT) + kvm_ftr.type = FTR_LOWER_SAFE; + break; + case SYS_ID_DFR0_EL1: + if (kvm_ftr.shift == ID_DFR0_EL1_PerfMon_SHIFT) + kvm_ftr.type = FTR_LOWER_SAFE; + break; + } - return vcpu->kvm->arch.dfr0_pmuver.unimp; + return arm64_ftr_safe_value(&kvm_ftr, new, cur); } -static u8 perfmon_to_pmuver(u8 perfmon) +/** + * arm64_check_features() - Check if a feature register value constitutes + * a subset of features indicated by the idreg's KVM sanitised limit. + * + * This function will check if each feature field of @val is the "safe" value + * against idreg's KVM sanitised limit return from reset() callback. + * If a field value in @val is the same as the one in limit, it is always + * considered the safe value regardless For register fields that are not in + * writable, only the value in limit is considered the safe value. + * + * Return: 0 if all the fields are safe. Otherwise, return negative errno. + */ +static int arm64_check_features(struct kvm_vcpu *vcpu, + const struct sys_reg_desc *rd, + u64 val) { - switch (perfmon) { - case ID_DFR0_EL1_PerfMon_PMUv3: - return ID_AA64DFR0_EL1_PMUVer_IMP; - case ID_DFR0_EL1_PerfMon_IMPDEF: - return ID_AA64DFR0_EL1_PMUVer_IMP_DEF; - default: - /* Anything ARMv8.1+ and NI have the same value. For now. */ - return perfmon; + const struct arm64_ftr_reg *ftr_reg; + const struct arm64_ftr_bits *ftrp = NULL; + u32 id = reg_to_encoding(rd); + u64 writable_mask = rd->val; + u64 limit = rd->reset(vcpu, rd); + u64 mask = 0; + + /* + * Hidden and unallocated ID registers may not have a corresponding + * struct arm64_ftr_reg. Of course, if the register is RAZ we know the + * only safe value is 0. + */ + if (sysreg_visible_as_raz(vcpu, rd)) + return val ? -E2BIG : 0; + + ftr_reg = get_arm64_ftr_reg(id); + if (!ftr_reg) + return -EINVAL; + + ftrp = ftr_reg->ftr_bits; + + for (; ftrp && ftrp->width; ftrp++) { + s64 f_val, f_lim, safe_val; + u64 ftr_mask; + + ftr_mask = arm64_ftr_mask(ftrp); + if ((ftr_mask & writable_mask) != ftr_mask) + continue; + + f_val = arm64_ftr_value(ftrp, val); + f_lim = arm64_ftr_value(ftrp, limit); + mask |= ftr_mask; + + if (f_val == f_lim) + safe_val = f_val; + else + safe_val = kvm_arm64_ftr_safe_value(id, ftrp, f_val, f_lim); + + if (safe_val != f_val) + return -E2BIG; } + + /* For fields that are not writable, values in limit are the safe values. */ + if ((val & ~mask) != (limit & ~mask)) + return -E2BIG; + + return 0; } static u8 pmuver_to_perfmon(u8 pmuver) @@ -1222,7 +1307,8 @@ static u8 pmuver_to_perfmon(u8 pmuver) } /* Read a sanitised cpufeature ID register by sys_reg_desc */ -static u64 read_id_reg(const struct kvm_vcpu *vcpu, struct sys_reg_desc const *r) +static u64 __kvm_read_sanitised_id_reg(const struct kvm_vcpu *vcpu, + const struct sys_reg_desc *r) { u32 id = reg_to_encoding(r); u64 val; @@ -1233,19 +1319,6 @@ static u64 read_id_reg(const struct kvm_vcpu *vcpu, struct sys_reg_desc const *r val = read_sanitised_ftr_reg(id); switch (id) { - case SYS_ID_AA64PFR0_EL1: - if (!vcpu_has_sve(vcpu)) - val &= ~ARM64_FEATURE_MASK(ID_AA64PFR0_EL1_SVE); - val &= ~ARM64_FEATURE_MASK(ID_AA64PFR0_EL1_AMU); - val &= ~ARM64_FEATURE_MASK(ID_AA64PFR0_EL1_CSV2); - val |= FIELD_PREP(ARM64_FEATURE_MASK(ID_AA64PFR0_EL1_CSV2), (u64)vcpu->kvm->arch.pfr0_csv2); - val &= ~ARM64_FEATURE_MASK(ID_AA64PFR0_EL1_CSV3); - val |= FIELD_PREP(ARM64_FEATURE_MASK(ID_AA64PFR0_EL1_CSV3), (u64)vcpu->kvm->arch.pfr0_csv3); - if (kvm_vgic_global_state.type == VGIC_V3) { - val &= ~ARM64_FEATURE_MASK(ID_AA64PFR0_EL1_GIC); - val |= FIELD_PREP(ARM64_FEATURE_MASK(ID_AA64PFR0_EL1_GIC), 1); - } - break; case SYS_ID_AA64PFR1_EL1: if (!kvm_has_mte(vcpu->kvm)) val &= ~ARM64_FEATURE_MASK(ID_AA64PFR1_EL1_MTE); @@ -1265,22 +1338,7 @@ static u64 read_id_reg(const struct kvm_vcpu *vcpu, struct sys_reg_desc const *r ARM64_FEATURE_MASK(ID_AA64ISAR2_EL1_GPA3)); if (!cpus_have_final_cap(ARM64_HAS_WFXT)) val &= ~ARM64_FEATURE_MASK(ID_AA64ISAR2_EL1_WFxT); - break; - case SYS_ID_AA64DFR0_EL1: - /* Limit debug to ARMv8.0 */ - val &= ~ARM64_FEATURE_MASK(ID_AA64DFR0_EL1_DebugVer); - val |= FIELD_PREP(ARM64_FEATURE_MASK(ID_AA64DFR0_EL1_DebugVer), 6); - /* Set PMUver to the required version */ - val &= ~ARM64_FEATURE_MASK(ID_AA64DFR0_EL1_PMUVer); - val |= FIELD_PREP(ARM64_FEATURE_MASK(ID_AA64DFR0_EL1_PMUVer), - vcpu_pmuver(vcpu)); - /* Hide SPE from guests */ - val &= ~ARM64_FEATURE_MASK(ID_AA64DFR0_EL1_PMSVer); - break; - case SYS_ID_DFR0_EL1: - val &= ~ARM64_FEATURE_MASK(ID_DFR0_EL1_PerfMon); - val |= FIELD_PREP(ARM64_FEATURE_MASK(ID_DFR0_EL1_PerfMon), - pmuver_to_perfmon(vcpu_pmuver(vcpu))); + val &= ~ARM64_FEATURE_MASK(ID_AA64ISAR2_EL1_MOPS); break; case SYS_ID_AA64MMFR2_EL1: val &= ~ID_AA64MMFR2_EL1_CCIDX_MASK; @@ -1293,6 +1351,28 @@ static u64 read_id_reg(const struct kvm_vcpu *vcpu, struct sys_reg_desc const *r return val; } +static u64 kvm_read_sanitised_id_reg(struct kvm_vcpu *vcpu, + const struct sys_reg_desc *r) +{ + return __kvm_read_sanitised_id_reg(vcpu, r); +} + +static u64 read_id_reg(const struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) +{ + return IDREG(vcpu->kvm, reg_to_encoding(r)); +} + +/* + * Return true if the register's (Op0, Op1, CRn, CRm, Op2) is + * (3, 0, 0, crm, op2), where 1<=crm<8, 0<=op2<8. + */ +static inline bool is_id_reg(u32 id) +{ + return (sys_reg_Op0(id) == 3 && sys_reg_Op1(id) == 0 && + sys_reg_CRn(id) == 0 && sys_reg_CRm(id) >= 1 && + sys_reg_CRm(id) < 8); +} + static unsigned int id_visibility(const struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) { @@ -1354,88 +1434,113 @@ static unsigned int sve_visibility(const struct kvm_vcpu *vcpu, return REG_HIDDEN; } -static int set_id_aa64pfr0_el1(struct kvm_vcpu *vcpu, - const struct sys_reg_desc *rd, - u64 val) +static u64 read_sanitised_id_aa64pfr0_el1(struct kvm_vcpu *vcpu, + const struct sys_reg_desc *rd) { - u8 csv2, csv3; + u64 val = read_sanitised_ftr_reg(SYS_ID_AA64PFR0_EL1); + + if (!vcpu_has_sve(vcpu)) + val &= ~ID_AA64PFR0_EL1_SVE_MASK; /* - * Allow AA64PFR0_EL1.CSV2 to be set from userspace as long as - * it doesn't promise more than what is actually provided (the - * guest could otherwise be covered in ectoplasmic residue). + * The default is to expose CSV2 == 1 if the HW isn't affected. + * Although this is a per-CPU feature, we make it global because + * asymmetric systems are just a nuisance. + * + * Userspace can override this as long as it doesn't promise + * the impossible. */ - csv2 = cpuid_feature_extract_unsigned_field(val, ID_AA64PFR0_EL1_CSV2_SHIFT); - if (csv2 > 1 || - (csv2 && arm64_get_spectre_v2_state() != SPECTRE_UNAFFECTED)) - return -EINVAL; + if (arm64_get_spectre_v2_state() == SPECTRE_UNAFFECTED) { + val &= ~ID_AA64PFR0_EL1_CSV2_MASK; + val |= SYS_FIELD_PREP_ENUM(ID_AA64PFR0_EL1, CSV2, IMP); + } + if (arm64_get_meltdown_state() == SPECTRE_UNAFFECTED) { + val &= ~ID_AA64PFR0_EL1_CSV3_MASK; + val |= SYS_FIELD_PREP_ENUM(ID_AA64PFR0_EL1, CSV3, IMP); + } - /* Same thing for CSV3 */ - csv3 = cpuid_feature_extract_unsigned_field(val, ID_AA64PFR0_EL1_CSV3_SHIFT); - if (csv3 > 1 || - (csv3 && arm64_get_meltdown_state() != SPECTRE_UNAFFECTED)) - return -EINVAL; + if (kvm_vgic_global_state.type == VGIC_V3) { + val &= ~ID_AA64PFR0_EL1_GIC_MASK; + val |= SYS_FIELD_PREP_ENUM(ID_AA64PFR0_EL1, GIC, IMP); + } - /* We can only differ with CSV[23], and anything else is an error */ - val ^= read_id_reg(vcpu, rd); - val &= ~(ARM64_FEATURE_MASK(ID_AA64PFR0_EL1_CSV2) | - ARM64_FEATURE_MASK(ID_AA64PFR0_EL1_CSV3)); - if (val) - return -EINVAL; + val &= ~ID_AA64PFR0_EL1_AMU_MASK; - vcpu->kvm->arch.pfr0_csv2 = csv2; - vcpu->kvm->arch.pfr0_csv3 = csv3; + return val; +} - return 0; +static u64 read_sanitised_id_aa64dfr0_el1(struct kvm_vcpu *vcpu, + const struct sys_reg_desc *rd) +{ + u64 val = read_sanitised_ftr_reg(SYS_ID_AA64DFR0_EL1); + + /* Limit debug to ARMv8.0 */ + val &= ~ID_AA64DFR0_EL1_DebugVer_MASK; + val |= SYS_FIELD_PREP_ENUM(ID_AA64DFR0_EL1, DebugVer, IMP); + + /* + * Only initialize the PMU version if the vCPU was configured with one. + */ + val &= ~ID_AA64DFR0_EL1_PMUVer_MASK; + if (kvm_vcpu_has_pmu(vcpu)) + val |= SYS_FIELD_PREP(ID_AA64DFR0_EL1, PMUVer, + kvm_arm_pmu_get_pmuver_limit()); + + /* Hide SPE from guests */ + val &= ~ID_AA64DFR0_EL1_PMSVer_MASK; + + return val; } static int set_id_aa64dfr0_el1(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd, u64 val) { - u8 pmuver, host_pmuver; - bool valid_pmu; - - host_pmuver = kvm_arm_pmu_get_pmuver_limit(); + u8 pmuver = SYS_FIELD_GET(ID_AA64DFR0_EL1, PMUVer, val); /* - * Allow AA64DFR0_EL1.PMUver to be set from userspace as long - * as it doesn't promise more than what the HW gives us. We - * allow an IMPDEF PMU though, only if no PMU is supported - * (KVM backward compatibility handling). + * Prior to commit 3d0dba5764b9 ("KVM: arm64: PMU: Move the + * ID_AA64DFR0_EL1.PMUver limit to VM creation"), KVM erroneously + * exposed an IMP_DEF PMU to userspace and the guest on systems w/ + * non-architectural PMUs. Of course, PMUv3 is the only game in town for + * PMU virtualization, so the IMP_DEF value was rather user-hostile. + * + * At minimum, we're on the hook to allow values that were given to + * userspace by KVM. Cover our tracks here and replace the IMP_DEF value + * with a more sensible NI. The value of an ID register changing under + * the nose of the guest is unfortunate, but is certainly no more + * surprising than an ill-guided PMU driver poking at impdef system + * registers that end in an UNDEF... */ - pmuver = FIELD_GET(ARM64_FEATURE_MASK(ID_AA64DFR0_EL1_PMUVer), val); - if ((pmuver != ID_AA64DFR0_EL1_PMUVer_IMP_DEF && pmuver > host_pmuver)) - return -EINVAL; + if (pmuver == ID_AA64DFR0_EL1_PMUVer_IMP_DEF) + val &= ~ID_AA64DFR0_EL1_PMUVer_MASK; - valid_pmu = (pmuver != 0 && pmuver != ID_AA64DFR0_EL1_PMUVer_IMP_DEF); - - /* Make sure view register and PMU support do match */ - if (kvm_vcpu_has_pmu(vcpu) != valid_pmu) - return -EINVAL; + return set_id_reg(vcpu, rd, val); +} - /* We can only differ with PMUver, and anything else is an error */ - val ^= read_id_reg(vcpu, rd); - val &= ~ARM64_FEATURE_MASK(ID_AA64DFR0_EL1_PMUVer); - if (val) - return -EINVAL; +static u64 read_sanitised_id_dfr0_el1(struct kvm_vcpu *vcpu, + const struct sys_reg_desc *rd) +{ + u8 perfmon = pmuver_to_perfmon(kvm_arm_pmu_get_pmuver_limit()); + u64 val = read_sanitised_ftr_reg(SYS_ID_DFR0_EL1); - if (valid_pmu) - vcpu->kvm->arch.dfr0_pmuver.imp = pmuver; - else - vcpu->kvm->arch.dfr0_pmuver.unimp = pmuver; + val &= ~ID_DFR0_EL1_PerfMon_MASK; + if (kvm_vcpu_has_pmu(vcpu)) + val |= SYS_FIELD_PREP(ID_DFR0_EL1, PerfMon, perfmon); - return 0; + return val; } static int set_id_dfr0_el1(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd, u64 val) { - u8 perfmon, host_perfmon; - bool valid_pmu; + u8 perfmon = SYS_FIELD_GET(ID_DFR0_EL1, PerfMon, val); - host_perfmon = pmuver_to_perfmon(kvm_arm_pmu_get_pmuver_limit()); + if (perfmon == ID_DFR0_EL1_PerfMon_IMPDEF) { + val &= ~ID_DFR0_EL1_PerfMon_MASK; + perfmon = 0; + } /* * Allow DFR0_EL1.PerfMon to be set from userspace as long as @@ -1443,29 +1548,10 @@ static int set_id_dfr0_el1(struct kvm_vcpu *vcpu, * AArch64 side (as everything is emulated with that), and * that this is a PMUv3. */ - perfmon = FIELD_GET(ARM64_FEATURE_MASK(ID_DFR0_EL1_PerfMon), val); - if ((perfmon != ID_DFR0_EL1_PerfMon_IMPDEF && perfmon > host_perfmon) || - (perfmon != 0 && perfmon < ID_DFR0_EL1_PerfMon_PMUv3)) + if (perfmon != 0 && perfmon < ID_DFR0_EL1_PerfMon_PMUv3) return -EINVAL; - valid_pmu = (perfmon != 0 && perfmon != ID_DFR0_EL1_PerfMon_IMPDEF); - - /* Make sure view register and PMU support do match */ - if (kvm_vcpu_has_pmu(vcpu) != valid_pmu) - return -EINVAL; - - /* We can only differ with PerfMon, and anything else is an error */ - val ^= read_id_reg(vcpu, rd); - val &= ~ARM64_FEATURE_MASK(ID_DFR0_EL1_PerfMon); - if (val) - return -EINVAL; - - if (valid_pmu) - vcpu->kvm->arch.dfr0_pmuver.imp = perfmon_to_pmuver(perfmon); - else - vcpu->kvm->arch.dfr0_pmuver.unimp = perfmon_to_pmuver(perfmon); - - return 0; + return set_id_reg(vcpu, rd, val); } /* @@ -1478,18 +1564,60 @@ static int set_id_dfr0_el1(struct kvm_vcpu *vcpu, static int get_id_reg(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd, u64 *val) { + /* + * Avoid locking if the VM has already started, as the ID registers are + * guaranteed to be invariant at that point. + */ + if (kvm_vm_has_ran_once(vcpu->kvm)) { + *val = read_id_reg(vcpu, rd); + return 0; + } + + mutex_lock(&vcpu->kvm->arch.config_lock); *val = read_id_reg(vcpu, rd); + mutex_unlock(&vcpu->kvm->arch.config_lock); + return 0; } static int set_id_reg(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd, u64 val) { - /* This is what we mean by invariant: you can't change it. */ - if (val != read_id_reg(vcpu, rd)) - return -EINVAL; + u32 id = reg_to_encoding(rd); + int ret; - return 0; + mutex_lock(&vcpu->kvm->arch.config_lock); + + /* + * Once the VM has started the ID registers are immutable. Reject any + * write that does not match the final register value. + */ + if (kvm_vm_has_ran_once(vcpu->kvm)) { + if (val != read_id_reg(vcpu, rd)) + ret = -EBUSY; + else + ret = 0; + + mutex_unlock(&vcpu->kvm->arch.config_lock); + return ret; + } + + ret = arm64_check_features(vcpu, rd, val); + if (!ret) + IDREG(vcpu->kvm, id) = val; + + mutex_unlock(&vcpu->kvm->arch.config_lock); + + /* + * arm64_check_features() returns -E2BIG to indicate the register's + * feature set is a superset of the maximally-allowed register value. + * While it would be nice to precisely describe this to userspace, the + * existing UAPI for KVM_SET_ONE_REG has it that invalid register + * writes return -EINVAL. + */ + if (ret == -E2BIG) + ret = -EINVAL; + return ret; } static int get_raz_reg(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd, @@ -1529,7 +1657,7 @@ static bool access_clidr(struct kvm_vcpu *vcpu, struct sys_reg_params *p, * Fabricate a CLIDR_EL1 value instead of using the real value, which can vary * by the physical CPU which the vcpu currently resides in. */ -static void reset_clidr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) +static u64 reset_clidr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) { u64 ctr_el0 = read_sanitised_ftr_reg(SYS_CTR_EL0); u64 clidr; @@ -1577,6 +1705,8 @@ static void reset_clidr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) clidr |= 2 << CLIDR_TTYPE_SHIFT(loc); __vcpu_sys_reg(vcpu, r->reg) = clidr; + + return __vcpu_sys_reg(vcpu, r->reg); } static int set_clidr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd, @@ -1676,6 +1806,17 @@ static unsigned int elx2_visibility(const struct kvm_vcpu *vcpu, .visibility = elx2_visibility, \ } +/* + * Since reset() callback and field val are not used for idregs, they will be + * used for specific purposes for idregs. + * The reset() would return KVM sanitised register value. The value would be the + * same as the host kernel sanitised value if there is no KVM sanitisation. + * The val would be used as a mask indicating writable fields for the idreg. + * Only bits with 1 are writable from userspace. This mask might not be + * necessary in the future whenever all ID registers are enabled as writable + * from userspace. + */ + /* sys_reg_desc initialiser for known cpufeature ID registers */ #define ID_SANITISED(name) { \ SYS_DESC(SYS_##name), \ @@ -1683,6 +1824,8 @@ static unsigned int elx2_visibility(const struct kvm_vcpu *vcpu, .get_user = get_id_reg, \ .set_user = set_id_reg, \ .visibility = id_visibility, \ + .reset = kvm_read_sanitised_id_reg, \ + .val = 0, \ } /* sys_reg_desc initialiser for known cpufeature ID registers */ @@ -1692,6 +1835,8 @@ static unsigned int elx2_visibility(const struct kvm_vcpu *vcpu, .get_user = get_id_reg, \ .set_user = set_id_reg, \ .visibility = aa32_id_visibility, \ + .reset = kvm_read_sanitised_id_reg, \ + .val = 0, \ } /* @@ -1704,7 +1849,9 @@ static unsigned int elx2_visibility(const struct kvm_vcpu *vcpu, .access = access_id_reg, \ .get_user = get_id_reg, \ .set_user = set_id_reg, \ - .visibility = raz_visibility \ + .visibility = raz_visibility, \ + .reset = kvm_read_sanitised_id_reg, \ + .val = 0, \ } /* @@ -1718,6 +1865,8 @@ static unsigned int elx2_visibility(const struct kvm_vcpu *vcpu, .get_user = get_id_reg, \ .set_user = set_id_reg, \ .visibility = raz_visibility, \ + .reset = kvm_read_sanitised_id_reg, \ + .val = 0, \ } static bool access_sp_el1(struct kvm_vcpu *vcpu, @@ -1800,7 +1949,7 @@ static const struct sys_reg_desc sys_reg_descs[] = { { SYS_DESC(SYS_MDRAR_EL1), trap_raz_wi }, { SYS_DESC(SYS_OSLAR_EL1), trap_oslar_el1 }, { SYS_DESC(SYS_OSLSR_EL1), trap_oslsr_el1, reset_val, OSLSR_EL1, - SYS_OSLSR_OSLM_IMPLEMENTED, .set_user = set_oslsr_el1, }, + OSLSR_EL1_OSLM_IMPLEMENTED, .set_user = set_oslsr_el1, }, { SYS_DESC(SYS_OSDLR_EL1), trap_raz_wi }, { SYS_DESC(SYS_DBGPRCR_EL1), trap_raz_wi }, { SYS_DESC(SYS_DBGCLAIMSET_EL1), trap_raz_wi }, @@ -1825,9 +1974,13 @@ static const struct sys_reg_desc sys_reg_descs[] = { /* CRm=1 */ AA32_ID_SANITISED(ID_PFR0_EL1), AA32_ID_SANITISED(ID_PFR1_EL1), - { SYS_DESC(SYS_ID_DFR0_EL1), .access = access_id_reg, - .get_user = get_id_reg, .set_user = set_id_dfr0_el1, - .visibility = aa32_id_visibility, }, + { SYS_DESC(SYS_ID_DFR0_EL1), + .access = access_id_reg, + .get_user = get_id_reg, + .set_user = set_id_dfr0_el1, + .visibility = aa32_id_visibility, + .reset = read_sanitised_id_dfr0_el1, + .val = ID_DFR0_EL1_PerfMon_MASK, }, ID_HIDDEN(ID_AFR0_EL1), AA32_ID_SANITISED(ID_MMFR0_EL1), AA32_ID_SANITISED(ID_MMFR1_EL1), @@ -1856,8 +2009,12 @@ static const struct sys_reg_desc sys_reg_descs[] = { /* AArch64 ID registers */ /* CRm=4 */ - { SYS_DESC(SYS_ID_AA64PFR0_EL1), .access = access_id_reg, - .get_user = get_id_reg, .set_user = set_id_aa64pfr0_el1, }, + { SYS_DESC(SYS_ID_AA64PFR0_EL1), + .access = access_id_reg, + .get_user = get_id_reg, + .set_user = set_id_reg, + .reset = read_sanitised_id_aa64pfr0_el1, + .val = ID_AA64PFR0_EL1_CSV2_MASK | ID_AA64PFR0_EL1_CSV3_MASK, }, ID_SANITISED(ID_AA64PFR1_EL1), ID_UNALLOCATED(4,2), ID_UNALLOCATED(4,3), @@ -1867,8 +2024,12 @@ static const struct sys_reg_desc sys_reg_descs[] = { ID_UNALLOCATED(4,7), /* CRm=5 */ - { SYS_DESC(SYS_ID_AA64DFR0_EL1), .access = access_id_reg, - .get_user = get_id_reg, .set_user = set_id_aa64dfr0_el1, }, + { SYS_DESC(SYS_ID_AA64DFR0_EL1), + .access = access_id_reg, + .get_user = get_id_reg, + .set_user = set_id_aa64dfr0_el1, + .reset = read_sanitised_id_aa64dfr0_el1, + .val = ID_AA64DFR0_EL1_PMUVer_MASK, }, ID_SANITISED(ID_AA64DFR1_EL1), ID_UNALLOCATED(5,2), ID_UNALLOCATED(5,3), @@ -1891,7 +2052,7 @@ static const struct sys_reg_desc sys_reg_descs[] = { ID_SANITISED(ID_AA64MMFR0_EL1), ID_SANITISED(ID_AA64MMFR1_EL1), ID_SANITISED(ID_AA64MMFR2_EL1), - ID_UNALLOCATED(7,3), + ID_SANITISED(ID_AA64MMFR3_EL1), ID_UNALLOCATED(7,4), ID_UNALLOCATED(7,5), ID_UNALLOCATED(7,6), @@ -1911,6 +2072,7 @@ static const struct sys_reg_desc sys_reg_descs[] = { { SYS_DESC(SYS_TTBR0_EL1), access_vm_reg, reset_unknown, TTBR0_EL1 }, { SYS_DESC(SYS_TTBR1_EL1), access_vm_reg, reset_unknown, TTBR1_EL1 }, { SYS_DESC(SYS_TCR_EL1), access_vm_reg, reset_val, TCR_EL1, 0 }, + { SYS_DESC(SYS_TCR2_EL1), access_vm_reg, reset_val, TCR2_EL1, 0 }, PTRAUTH_KEY(APIA), PTRAUTH_KEY(APIB), @@ -1960,6 +2122,8 @@ static const struct sys_reg_desc sys_reg_descs[] = { { SYS_DESC(SYS_PMMIR_EL1), trap_raz_wi }, { SYS_DESC(SYS_MAIR_EL1), access_vm_reg, reset_unknown, MAIR_EL1 }, + { SYS_DESC(SYS_PIRE0_EL1), access_vm_reg, reset_unknown, PIRE0_EL1 }, + { SYS_DESC(SYS_PIR_EL1), access_vm_reg, reset_unknown, PIR_EL1 }, { SYS_DESC(SYS_AMAIR_EL1), access_vm_reg, reset_amair_el1, AMAIR_EL1 }, { SYS_DESC(SYS_LORSA_EL1), trap_loregion }, @@ -2199,7 +2363,7 @@ static const struct sys_reg_desc sys_reg_descs[] = { EL2_REG(ACTLR_EL2, access_rw, reset_val, 0), EL2_REG(HCR_EL2, access_rw, reset_val, 0), EL2_REG(MDCR_EL2, access_rw, reset_val, 0), - EL2_REG(CPTR_EL2, access_rw, reset_val, CPTR_EL2_DEFAULT ), + EL2_REG(CPTR_EL2, access_rw, reset_val, CPTR_NVHE_EL2_RES1), EL2_REG(HSTR_EL2, access_rw, reset_val, 0), EL2_REG(HACR_EL2, access_rw, reset_val, 0), @@ -2256,6 +2420,8 @@ static const struct sys_reg_desc sys_reg_descs[] = { EL2_REG(SP_EL2, NULL, reset_unknown, 0), }; +static const struct sys_reg_desc *first_idreg; + static bool trap_dbgdidr(struct kvm_vcpu *vcpu, struct sys_reg_params *p, const struct sys_reg_desc *r) @@ -2946,6 +3112,28 @@ static bool emulate_sys_reg(struct kvm_vcpu *vcpu, return false; } +static void kvm_reset_id_regs(struct kvm_vcpu *vcpu) +{ + const struct sys_reg_desc *idreg = first_idreg; + u32 id = reg_to_encoding(idreg); + struct kvm *kvm = vcpu->kvm; + + if (test_bit(KVM_ARCH_FLAG_ID_REGS_INITIALIZED, &kvm->arch.flags)) + return; + + lockdep_assert_held(&kvm->arch.config_lock); + + /* Initialize all idregs */ + while (is_id_reg(id)) { + IDREG(kvm, id) = idreg->reset(vcpu, idreg); + + idreg++; + id = reg_to_encoding(idreg); + } + + set_bit(KVM_ARCH_FLAG_ID_REGS_INITIALIZED, &kvm->arch.flags); +} + /** * kvm_reset_sys_regs - sets system registers to reset value * @vcpu: The VCPU pointer @@ -2957,9 +3145,17 @@ void kvm_reset_sys_regs(struct kvm_vcpu *vcpu) { unsigned long i; - for (i = 0; i < ARRAY_SIZE(sys_reg_descs); i++) - if (sys_reg_descs[i].reset) - sys_reg_descs[i].reset(vcpu, &sys_reg_descs[i]); + kvm_reset_id_regs(vcpu); + + for (i = 0; i < ARRAY_SIZE(sys_reg_descs); i++) { + const struct sys_reg_desc *r = &sys_reg_descs[i]; + + if (is_id_reg(reg_to_encoding(r))) + continue; + + if (r->reset) + r->reset(vcpu, r); + } } /** @@ -3060,19 +3256,21 @@ id_to_sys_reg_desc(struct kvm_vcpu *vcpu, u64 id, */ #define FUNCTION_INVARIANT(reg) \ - static void get_##reg(struct kvm_vcpu *v, \ + static u64 get_##reg(struct kvm_vcpu *v, \ const struct sys_reg_desc *r) \ { \ ((struct sys_reg_desc *)r)->val = read_sysreg(reg); \ + return ((struct sys_reg_desc *)r)->val; \ } FUNCTION_INVARIANT(midr_el1) FUNCTION_INVARIANT(revidr_el1) FUNCTION_INVARIANT(aidr_el1) -static void get_ctr_el0(struct kvm_vcpu *v, const struct sys_reg_desc *r) +static u64 get_ctr_el0(struct kvm_vcpu *v, const struct sys_reg_desc *r) { ((struct sys_reg_desc *)r)->val = read_sanitised_ftr_reg(SYS_CTR_EL0); + return ((struct sys_reg_desc *)r)->val; } /* ->val is filled in by kvm_sys_reg_table_init() */ @@ -3364,6 +3562,7 @@ int kvm_arm_copy_sys_reg_indices(struct kvm_vcpu *vcpu, u64 __user *uindices) int __init kvm_sys_reg_table_init(void) { + struct sys_reg_params params; bool valid = true; unsigned int i; @@ -3382,5 +3581,11 @@ int __init kvm_sys_reg_table_init(void) for (i = 0; i < ARRAY_SIZE(invariant_sys_regs); i++) invariant_sys_regs[i].reset(NULL, &invariant_sys_regs[i]); + /* Find the first idreg (SYS_ID_PFR0_EL1) in sys_reg_descs. */ + params = encoding_to_params(SYS_ID_PFR0_EL1); + first_idreg = find_reg(¶ms, sys_reg_descs, ARRAY_SIZE(sys_reg_descs)); + if (!first_idreg) + return -EINVAL; + return 0; } diff --git a/arch/arm64/kvm/sys_regs.h b/arch/arm64/kvm/sys_regs.h index 6b11f2cc71467281620dc9b5d6bae2151b340cda..c65c129b35001049ed4b14c02ec6fcfb8e37b1fa 100644 --- a/arch/arm64/kvm/sys_regs.h +++ b/arch/arm64/kvm/sys_regs.h @@ -27,6 +27,13 @@ struct sys_reg_params { bool is_write; }; +#define encoding_to_params(reg) \ + ((struct sys_reg_params){ .Op0 = sys_reg_Op0(reg), \ + .Op1 = sys_reg_Op1(reg), \ + .CRn = sys_reg_CRn(reg), \ + .CRm = sys_reg_CRm(reg), \ + .Op2 = sys_reg_Op2(reg) }) + #define esr_sys64_to_params(esr) \ ((struct sys_reg_params){ .Op0 = ((esr) >> 20) & 3, \ .Op1 = ((esr) >> 14) & 0x7, \ @@ -64,13 +71,16 @@ struct sys_reg_desc { struct sys_reg_params *, const struct sys_reg_desc *); - /* Initialization for vcpu. */ - void (*reset)(struct kvm_vcpu *, const struct sys_reg_desc *); + /* + * Initialization for vcpu. Return initialized value, or KVM + * sanitized value for ID registers. + */ + u64 (*reset)(struct kvm_vcpu *, const struct sys_reg_desc *); /* Index into sys_reg[], or 0 if we don't need to save it. */ int reg; - /* Value (usually reset value) */ + /* Value (usually reset value), or write mask for idregs */ u64 val; /* Custom get/set_user functions, fallback to generic if NULL */ @@ -123,19 +133,21 @@ static inline bool read_zero(struct kvm_vcpu *vcpu, } /* Reset functions */ -static inline void reset_unknown(struct kvm_vcpu *vcpu, +static inline u64 reset_unknown(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) { BUG_ON(!r->reg); BUG_ON(r->reg >= NR_SYS_REGS); __vcpu_sys_reg(vcpu, r->reg) = 0x1de7ec7edbadc0deULL; + return __vcpu_sys_reg(vcpu, r->reg); } -static inline void reset_val(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) +static inline u64 reset_val(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) { BUG_ON(!r->reg); BUG_ON(r->reg >= NR_SYS_REGS); __vcpu_sys_reg(vcpu, r->reg) = r->val; + return __vcpu_sys_reg(vcpu, r->reg); } static inline unsigned int sysreg_visibility(const struct kvm_vcpu *vcpu, diff --git a/arch/arm64/kvm/vgic/vgic-init.c b/arch/arm64/kvm/vgic/vgic-init.c index 6eafc2c45cfcf73e1bb5d817545ec4f290a388e9..c8c3cb812783218e93065d157291d09c7a4a0812 100644 --- a/arch/arm64/kvm/vgic/vgic-init.c +++ b/arch/arm64/kvm/vgic/vgic-init.c @@ -446,6 +446,7 @@ int vgic_lazy_init(struct kvm *kvm) int kvm_vgic_map_resources(struct kvm *kvm) { struct vgic_dist *dist = &kvm->arch.vgic; + enum vgic_type type; gpa_t dist_base; int ret = 0; @@ -460,10 +461,13 @@ int kvm_vgic_map_resources(struct kvm *kvm) if (!irqchip_in_kernel(kvm)) goto out; - if (dist->vgic_model == KVM_DEV_TYPE_ARM_VGIC_V2) + if (dist->vgic_model == KVM_DEV_TYPE_ARM_VGIC_V2) { ret = vgic_v2_map_resources(kvm); - else + type = VGIC_V2; + } else { ret = vgic_v3_map_resources(kvm); + type = VGIC_V3; + } if (ret) { __kvm_vgic_destroy(kvm); @@ -473,8 +477,7 @@ int kvm_vgic_map_resources(struct kvm *kvm) dist_base = dist->vgic_dist_base; mutex_unlock(&kvm->arch.config_lock); - ret = vgic_register_dist_iodev(kvm, dist_base, - kvm_vgic_global_state.type); + ret = vgic_register_dist_iodev(kvm, dist_base, type); if (ret) { kvm_err("Unable to register VGIC dist MMIO regions\n"); kvm_vgic_destroy(kvm); diff --git a/arch/arm64/lib/xor-neon.c b/arch/arm64/lib/xor-neon.c index 96b171995d198fe9278e615a3a04588c50594880..f9a53b7f9842f22f309c572176ee3c772f97bef9 100644 --- a/arch/arm64/lib/xor-neon.c +++ b/arch/arm64/lib/xor-neon.c @@ -10,7 +10,7 @@ #include #include -void xor_arm64_neon_2(unsigned long bytes, unsigned long * __restrict p1, +static void xor_arm64_neon_2(unsigned long bytes, unsigned long * __restrict p1, const unsigned long * __restrict p2) { uint64_t *dp1 = (uint64_t *)p1; @@ -37,7 +37,7 @@ void xor_arm64_neon_2(unsigned long bytes, unsigned long * __restrict p1, } while (--lines > 0); } -void xor_arm64_neon_3(unsigned long bytes, unsigned long * __restrict p1, +static void xor_arm64_neon_3(unsigned long bytes, unsigned long * __restrict p1, const unsigned long * __restrict p2, const unsigned long * __restrict p3) { @@ -73,7 +73,7 @@ void xor_arm64_neon_3(unsigned long bytes, unsigned long * __restrict p1, } while (--lines > 0); } -void xor_arm64_neon_4(unsigned long bytes, unsigned long * __restrict p1, +static void xor_arm64_neon_4(unsigned long bytes, unsigned long * __restrict p1, const unsigned long * __restrict p2, const unsigned long * __restrict p3, const unsigned long * __restrict p4) @@ -118,7 +118,7 @@ void xor_arm64_neon_4(unsigned long bytes, unsigned long * __restrict p1, } while (--lines > 0); } -void xor_arm64_neon_5(unsigned long bytes, unsigned long * __restrict p1, +static void xor_arm64_neon_5(unsigned long bytes, unsigned long * __restrict p1, const unsigned long * __restrict p2, const unsigned long * __restrict p3, const unsigned long * __restrict p4, diff --git a/arch/arm64/mm/context.c b/arch/arm64/mm/context.c index e1e0dca01839232dd186e1a9bd7b2264f15f8be6..188197590fc9ce44da04246455571fc9ee47c57c 100644 --- a/arch/arm64/mm/context.c +++ b/arch/arm64/mm/context.c @@ -364,8 +364,8 @@ void cpu_do_switch_mm(phys_addr_t pgd_phys, struct mm_struct *mm) ttbr1 &= ~TTBR_ASID_MASK; ttbr1 |= FIELD_PREP(TTBR_ASID_MASK, asid); + cpu_set_reserved_ttbr0_nosync(); write_sysreg(ttbr1, ttbr1_el1); - isb(); write_sysreg(ttbr0, ttbr0_el1); isb(); post_ttbr_update_workaround(); diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c index 6045a5117ac15bca1fe0cceba12509e13003df87..3fe516b325772c25d6475f00e5700f0f061d1340 100644 --- a/arch/arm64/mm/fault.c +++ b/arch/arm64/mm/fault.c @@ -66,6 +66,8 @@ static inline const struct fault_info *esr_to_debug_fault_info(unsigned long esr static void data_abort_decode(unsigned long esr) { + unsigned long iss2 = ESR_ELx_ISS2(esr); + pr_alert("Data abort info:\n"); if (esr & ESR_ELx_ISV) { @@ -78,12 +80,21 @@ static void data_abort_decode(unsigned long esr) (esr & ESR_ELx_SF) >> ESR_ELx_SF_SHIFT, (esr & ESR_ELx_AR) >> ESR_ELx_AR_SHIFT); } else { - pr_alert(" ISV = 0, ISS = 0x%08lx\n", esr & ESR_ELx_ISS_MASK); + pr_alert(" ISV = 0, ISS = 0x%08lx, ISS2 = 0x%08lx\n", + esr & ESR_ELx_ISS_MASK, iss2); } - pr_alert(" CM = %lu, WnR = %lu\n", + pr_alert(" CM = %lu, WnR = %lu, TnD = %lu, TagAccess = %lu\n", (esr & ESR_ELx_CM) >> ESR_ELx_CM_SHIFT, - (esr & ESR_ELx_WNR) >> ESR_ELx_WNR_SHIFT); + (esr & ESR_ELx_WNR) >> ESR_ELx_WNR_SHIFT, + (iss2 & ESR_ELx_TnD) >> ESR_ELx_TnD_SHIFT, + (iss2 & ESR_ELx_TagAccess) >> ESR_ELx_TagAccess_SHIFT); + + pr_alert(" GCS = %ld, Overlay = %lu, DirtyBit = %lu, Xs = %llu\n", + (iss2 & ESR_ELx_GCS) >> ESR_ELx_GCS_SHIFT, + (iss2 & ESR_ELx_Overlay) >> ESR_ELx_Overlay_SHIFT, + (iss2 & ESR_ELx_DirtyBit) >> ESR_ELx_DirtyBit_SHIFT, + (iss2 & ESR_ELx_Xs_MASK) >> ESR_ELx_Xs_SHIFT); } static void mem_abort_decode(unsigned long esr) @@ -177,6 +188,9 @@ static void show_pte(unsigned long addr) break; ptep = pte_offset_map(pmdp, addr); + if (!ptep) + break; + pte = READ_ONCE(*ptep); pr_cont(", pte=%016llx", pte_val(pte)); pte_unmap(ptep); @@ -317,7 +331,7 @@ static void report_tag_fault(unsigned long addr, unsigned long esr, * find out access size. */ bool is_write = !!(esr & ESR_ELx_WNR); - kasan_report(addr, 0, is_write, regs->pc); + kasan_report((void *)addr, 0, is_write, regs->pc); } #else /* Tag faults aren't enabled without CONFIG_KASAN_HW_TAGS. */ @@ -483,27 +497,14 @@ static void do_bad_area(unsigned long far, unsigned long esr, #define VM_FAULT_BADMAP ((__force vm_fault_t)0x010000) #define VM_FAULT_BADACCESS ((__force vm_fault_t)0x020000) -static vm_fault_t __do_page_fault(struct mm_struct *mm, unsigned long addr, +static vm_fault_t __do_page_fault(struct mm_struct *mm, + struct vm_area_struct *vma, unsigned long addr, unsigned int mm_flags, unsigned long vm_flags, struct pt_regs *regs) { - struct vm_area_struct *vma = find_vma(mm, addr); - - if (unlikely(!vma)) - return VM_FAULT_BADMAP; - /* * Ok, we have a good vm_area for this memory access, so we can handle * it. - */ - if (unlikely(vma->vm_start > addr)) { - if (!(vma->vm_flags & VM_GROWSDOWN)) - return VM_FAULT_BADMAP; - if (expand_stack(vma, addr)) - return VM_FAULT_BADMAP; - } - - /* * Check that the permissions on the VMA allow for the fault which * occurred. */ @@ -535,9 +536,7 @@ static int __kprobes do_page_fault(unsigned long far, unsigned long esr, unsigned long vm_flags; unsigned int mm_flags = FAULT_FLAG_DEFAULT; unsigned long addr = untagged_addr(far); -#ifdef CONFIG_PER_VMA_LOCK struct vm_area_struct *vma; -#endif if (kprobe_page_fault(regs, esr)) return 0; @@ -617,31 +616,15 @@ static int __kprobes do_page_fault(unsigned long far, unsigned long esr, } lock_mmap: #endif /* CONFIG_PER_VMA_LOCK */ - /* - * As per x86, we may deadlock here. However, since the kernel only - * validly references user space from well defined areas of the code, - * we can bug out early if this is from code which shouldn't. - */ - if (!mmap_read_trylock(mm)) { - if (!user_mode(regs) && !search_exception_tables(regs->pc)) - goto no_context; + retry: - mmap_read_lock(mm); - } else { - /* - * The above mmap_read_trylock() might have succeeded in which - * case, we'll have missed the might_sleep() from down_read(). - */ - might_sleep(); -#ifdef CONFIG_DEBUG_VM - if (!user_mode(regs) && !search_exception_tables(regs->pc)) { - mmap_read_unlock(mm); - goto no_context; - } -#endif + vma = lock_mm_and_find_vma(mm, addr, regs); + if (unlikely(!vma)) { + fault = VM_FAULT_BADMAP; + goto done; } - fault = __do_page_fault(mm, addr, mm_flags, vm_flags, regs); + fault = __do_page_fault(mm, vma, addr, mm_flags, vm_flags, regs); /* Quick path to respond to signals */ if (fault_signal_pending(fault, regs)) { @@ -660,9 +643,7 @@ static int __kprobes do_page_fault(unsigned long far, unsigned long esr, } mmap_read_unlock(mm); -#ifdef CONFIG_PER_VMA_LOCK done: -#endif /* * Handle the "normal" (no error) case first. */ @@ -885,9 +866,6 @@ void do_sp_pc_abort(unsigned long addr, unsigned long esr, struct pt_regs *regs) } NOKPROBE_SYMBOL(do_sp_pc_abort); -int __init early_brk64(unsigned long addr, unsigned long esr, - struct pt_regs *regs); - /* * __refdata because early_brk64 is __init, but the reference to it is * clobbered at arch_initcall time. diff --git a/arch/arm64/mm/flush.c b/arch/arm64/mm/flush.c index 5f9379b3c8c877a363eaa3c56d4693e356a3a53e..4e647609495222caf6c8d749a8e8431fbf1dd767 100644 --- a/arch/arm64/mm/flush.c +++ b/arch/arm64/mm/flush.c @@ -8,6 +8,7 @@ #include #include +#include #include #include diff --git a/arch/arm64/mm/hugetlbpage.c b/arch/arm64/mm/hugetlbpage.c index 95364e8bdc194491ce298197d1a52896af511c53..21716c9406821ec43c918bdf1dc3453948f6ad41 100644 --- a/arch/arm64/mm/hugetlbpage.c +++ b/arch/arm64/mm/hugetlbpage.c @@ -307,14 +307,7 @@ pte_t *huge_pte_alloc(struct mm_struct *mm, struct vm_area_struct *vma, return NULL; WARN_ON(addr & (sz - 1)); - /* - * Note that if this code were ever ported to the - * 32-bit arm platform then it will cause trouble in - * the case where CONFIG_HIGHPTE is set, since there - * will be no pte_unmap() to correspond with this - * pte_alloc_map(). - */ - ptep = pte_alloc_map(mm, pmdp, addr); + ptep = pte_alloc_huge(mm, pmdp, addr); } else if (sz == PMD_SIZE) { if (want_pmd_share(vma, addr) && pud_none(READ_ONCE(*pudp))) ptep = huge_pmd_share(mm, vma, addr, pudp); @@ -366,7 +359,7 @@ pte_t *huge_pte_offset(struct mm_struct *mm, return (pte_t *)pmdp; if (sz == CONT_PTE_SIZE) - return pte_offset_kernel(pmdp, (addr & CONT_PTE_MASK)); + return pte_offset_huge(pmdp, (addr & CONT_PTE_MASK)); return NULL; } diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c index 66e70ca476805398829931f9ccf20571de75d9bd..d31c3a9290c5524271ba322f6d48d39ce6ce0f6b 100644 --- a/arch/arm64/mm/init.c +++ b/arch/arm64/mm/init.c @@ -69,6 +69,7 @@ phys_addr_t __ro_after_init arm64_dma_phys_limit; #define CRASH_ADDR_LOW_MAX arm64_dma_phys_limit #define CRASH_ADDR_HIGH_MAX (PHYS_MASK + 1) +#define CRASH_HIGH_SEARCH_BASE SZ_4G #define DEFAULT_CRASH_KERNEL_LOW_SIZE (128UL << 20) @@ -101,12 +102,13 @@ static int __init reserve_crashkernel_low(unsigned long long low_size) */ static void __init reserve_crashkernel(void) { - unsigned long long crash_base, crash_size; - unsigned long long crash_low_size = 0; + unsigned long long crash_low_size = 0, search_base = 0; unsigned long long crash_max = CRASH_ADDR_LOW_MAX; + unsigned long long crash_base, crash_size; char *cmdline = boot_command_line; - int ret; bool fixed_base = false; + bool high = false; + int ret; if (!IS_ENABLED(CONFIG_KEXEC_CORE)) return; @@ -129,7 +131,9 @@ static void __init reserve_crashkernel(void) else if (ret) return; + search_base = CRASH_HIGH_SEARCH_BASE; crash_max = CRASH_ADDR_HIGH_MAX; + high = true; } else if (ret || !crash_size) { /* The specified value is invalid */ return; @@ -140,31 +144,51 @@ static void __init reserve_crashkernel(void) /* User specifies base address explicitly. */ if (crash_base) { fixed_base = true; + search_base = crash_base; crash_max = crash_base + crash_size; } retry: crash_base = memblock_phys_alloc_range(crash_size, CRASH_ALIGN, - crash_base, crash_max); + search_base, crash_max); if (!crash_base) { /* - * If the first attempt was for low memory, fall back to - * high memory, the minimum required low memory will be - * reserved later. + * For crashkernel=size[KMG]@offset[KMG], print out failure + * message if can't reserve the specified region. */ - if (!fixed_base && (crash_max == CRASH_ADDR_LOW_MAX)) { + if (fixed_base) { + pr_warn("crashkernel reservation failed - memory is in use.\n"); + return; + } + + /* + * For crashkernel=size[KMG], if the first attempt was for + * low memory, fall back to high memory, the minimum required + * low memory will be reserved later. + */ + if (!high && crash_max == CRASH_ADDR_LOW_MAX) { crash_max = CRASH_ADDR_HIGH_MAX; + search_base = CRASH_ADDR_LOW_MAX; crash_low_size = DEFAULT_CRASH_KERNEL_LOW_SIZE; goto retry; } + /* + * For crashkernel=size[KMG],high, if the first attempt was + * for high memory, fall back to low memory. + */ + if (high && crash_max == CRASH_ADDR_HIGH_MAX) { + crash_max = CRASH_ADDR_LOW_MAX; + search_base = 0; + goto retry; + } pr_warn("cannot allocate crashkernel (size:0x%llx)\n", crash_size); return; } - if ((crash_base > CRASH_ADDR_LOW_MAX - crash_low_size) && - crash_low_size && reserve_crashkernel_low(crash_low_size)) { + if ((crash_base >= CRASH_ADDR_LOW_MAX) && crash_low_size && + reserve_crashkernel_low(crash_low_size)) { memblock_phys_free(crash_base, crash_size); return; } @@ -442,7 +466,12 @@ void __init bootmem_init(void) */ void __init mem_init(void) { - swiotlb_init(max_pfn > PFN_DOWN(arm64_dma_phys_limit), SWIOTLB_VERBOSE); + bool swiotlb = max_pfn > PFN_DOWN(arm64_dma_phys_limit); + + if (IS_ENABLED(CONFIG_DMA_BOUNCE_UNALIGNED_KMALLOC)) + swiotlb = true; + + swiotlb_init(swiotlb, SWIOTLB_VERBOSE); /* this will put all unused low memory onto the freelists */ memblock_free_all(); diff --git a/arch/arm64/mm/kasan_init.c b/arch/arm64/mm/kasan_init.c index e969e68de005fd2abf0aee91d51a03fc4e2eeebd..f17d066e85eb854a06a8949da954ff704137746f 100644 --- a/arch/arm64/mm/kasan_init.c +++ b/arch/arm64/mm/kasan_init.c @@ -214,7 +214,7 @@ static void __init clear_pgds(unsigned long start, static void __init kasan_init_shadow(void) { u64 kimg_shadow_start, kimg_shadow_end; - u64 mod_shadow_start, mod_shadow_end; + u64 mod_shadow_start; u64 vmalloc_shadow_end; phys_addr_t pa_start, pa_end; u64 i; @@ -223,7 +223,6 @@ static void __init kasan_init_shadow(void) kimg_shadow_end = PAGE_ALIGN((u64)kasan_mem_to_shadow(KERNEL_END)); mod_shadow_start = (u64)kasan_mem_to_shadow((void *)MODULES_VADDR); - mod_shadow_end = (u64)kasan_mem_to_shadow((void *)MODULES_END); vmalloc_shadow_end = (u64)kasan_mem_to_shadow((void *)VMALLOC_END); @@ -246,17 +245,9 @@ static void __init kasan_init_shadow(void) kasan_populate_early_shadow(kasan_mem_to_shadow((void *)PAGE_END), (void *)mod_shadow_start); - if (IS_ENABLED(CONFIG_KASAN_VMALLOC)) { - BUILD_BUG_ON(VMALLOC_START != MODULES_END); - kasan_populate_early_shadow((void *)vmalloc_shadow_end, - (void *)KASAN_SHADOW_END); - } else { - kasan_populate_early_shadow((void *)kimg_shadow_end, - (void *)KASAN_SHADOW_END); - if (kimg_shadow_start > mod_shadow_end) - kasan_populate_early_shadow((void *)mod_shadow_end, - (void *)kimg_shadow_start); - } + BUILD_BUG_ON(VMALLOC_START != MODULES_END); + kasan_populate_early_shadow((void *)vmalloc_shadow_end, + (void *)KASAN_SHADOW_END); for_each_mem_range(i, &pa_start, &pa_end) { void *start = (void *)__phys_to_virt(pa_start); diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c index af6bc8403ee4617bdcc26e0c3bee1276bad5e5b5..95d360805f8aeb3e8f0d7e0c8fef26dfd277060f 100644 --- a/arch/arm64/mm/mmu.c +++ b/arch/arm64/mm/mmu.c @@ -451,7 +451,7 @@ static phys_addr_t pgd_pgtable_alloc(int shift) void __init create_mapping_noalloc(phys_addr_t phys, unsigned long virt, phys_addr_t size, pgprot_t prot) { - if ((virt >= PAGE_END) && (virt < VMALLOC_START)) { + if (virt < PAGE_OFFSET) { pr_warn("BUG: not creating mapping for %pa at 0x%016lx - outside kernel range\n", &phys, virt); return; @@ -478,7 +478,7 @@ void __init create_pgd_mapping(struct mm_struct *mm, phys_addr_t phys, static void update_mapping_prot(phys_addr_t phys, unsigned long virt, phys_addr_t size, pgprot_t prot) { - if ((virt >= PAGE_END) && (virt < VMALLOC_START)) { + if (virt < PAGE_OFFSET) { pr_warn("BUG: not updating mapping for %pa at 0x%016lx - outside kernel range\n", &phys, virt); return; @@ -663,12 +663,17 @@ static void __init map_kernel_segment(pgd_t *pgdp, void *va_start, void *va_end, vm_area_add_early(vma); } +static pgprot_t kernel_exec_prot(void) +{ + return rodata_enabled ? PAGE_KERNEL_ROX : PAGE_KERNEL_EXEC; +} + #ifdef CONFIG_UNMAP_KERNEL_AT_EL0 static int __init map_entry_trampoline(void) { int i; - pgprot_t prot = rodata_enabled ? PAGE_KERNEL_ROX : PAGE_KERNEL_EXEC; + pgprot_t prot = kernel_exec_prot(); phys_addr_t pa_start = __pa_symbol(__entry_tramp_text_start); /* The trampoline is always mapped and can therefore be global */ @@ -723,7 +728,7 @@ static void __init map_kernel(pgd_t *pgdp) * mapping to install SW breakpoints. Allow this (only) when * explicitly requested with rodata=off. */ - pgprot_t text_prot = rodata_enabled ? PAGE_KERNEL_ROX : PAGE_KERNEL_EXEC; + pgprot_t text_prot = kernel_exec_prot(); /* * If we have a CPU that supports BTI and a kernel built for diff --git a/arch/arm64/mm/proc.S b/arch/arm64/mm/proc.S index c2cb437821ca4c2ad07ec6bbe0e9a31b6d44a1b2..2baeec419f62d19e4c0196a11dce83618aa08065 100644 --- a/arch/arm64/mm/proc.S +++ b/arch/arm64/mm/proc.S @@ -199,7 +199,7 @@ SYM_FUNC_END(idmap_cpu_replace_ttbr1) #ifdef CONFIG_UNMAP_KERNEL_AT_EL0 -#define KPTI_NG_PTE_FLAGS (PTE_ATTRINDX(MT_NORMAL) | SWAPPER_PTE_FLAGS) +#define KPTI_NG_PTE_FLAGS (PTE_ATTRINDX(MT_NORMAL) | SWAPPER_PTE_FLAGS | PTE_WRITE) .pushsection ".idmap.text", "a" @@ -290,7 +290,7 @@ SYM_TYPED_FUNC_START(idmap_kpti_install_ng_mappings) isb mov temp_pte, x5 - mov pte_flags, #KPTI_NG_PTE_FLAGS + mov_q pte_flags, KPTI_NG_PTE_FLAGS /* Everybody is enjoying the idmap, so we can rewrite swapper. */ /* PGD */ @@ -454,6 +454,21 @@ SYM_FUNC_START(__cpu_setup) #endif /* CONFIG_ARM64_HW_AFDBM */ msr mair_el1, mair msr tcr_el1, tcr + + mrs_s x1, SYS_ID_AA64MMFR3_EL1 + ubfx x1, x1, #ID_AA64MMFR3_EL1_S1PIE_SHIFT, #4 + cbz x1, .Lskip_indirection + + mov_q x0, PIE_E0 + msr REG_PIRE0_EL1, x0 + mov_q x0, PIE_E1 + msr REG_PIR_EL1, x0 + + mov x0, TCR2_EL1x_PIE + msr REG_TCR2_EL1, x0 + +.Lskip_indirection: + /* * Prepare SCTLR */ diff --git a/arch/arm64/net/bpf_jit_comp.c b/arch/arm64/net/bpf_jit_comp.c index b26da8efa616ec133b23b0d4cacd54192ea7c6af..145b540ec34ffd1dfcb98144f25ab52e2c420dc2 100644 --- a/arch/arm64/net/bpf_jit_comp.c +++ b/arch/arm64/net/bpf_jit_comp.c @@ -1731,21 +1731,21 @@ static void invoke_bpf_mod_ret(struct jit_ctx *ctx, struct bpf_tramp_links *tl, } } -static void save_args(struct jit_ctx *ctx, int args_off, int nargs) +static void save_args(struct jit_ctx *ctx, int args_off, int nregs) { int i; - for (i = 0; i < nargs; i++) { + for (i = 0; i < nregs; i++) { emit(A64_STR64I(i, A64_SP, args_off), ctx); args_off += 8; } } -static void restore_args(struct jit_ctx *ctx, int args_off, int nargs) +static void restore_args(struct jit_ctx *ctx, int args_off, int nregs) { int i; - for (i = 0; i < nargs; i++) { + for (i = 0; i < nregs; i++) { emit(A64_LDR64I(i, A64_SP, args_off), ctx); args_off += 8; } @@ -1764,7 +1764,7 @@ static void restore_args(struct jit_ctx *ctx, int args_off, int nargs) */ static int prepare_trampoline(struct jit_ctx *ctx, struct bpf_tramp_image *im, struct bpf_tramp_links *tlinks, void *orig_call, - int nargs, u32 flags) + int nregs, u32 flags) { int i; int stack_size; @@ -1772,7 +1772,7 @@ static int prepare_trampoline(struct jit_ctx *ctx, struct bpf_tramp_image *im, int regs_off; int retval_off; int args_off; - int nargs_off; + int nregs_off; int ip_off; int run_ctx_off; struct bpf_tramp_links *fentry = &tlinks[BPF_TRAMP_FENTRY]; @@ -1795,11 +1795,11 @@ static int prepare_trampoline(struct jit_ctx *ctx, struct bpf_tramp_image *im, * SP + retval_off [ return value ] BPF_TRAMP_F_CALL_ORIG or * BPF_TRAMP_F_RET_FENTRY_RET * - * [ argN ] + * [ arg reg N ] * [ ... ] - * SP + args_off [ arg1 ] + * SP + args_off [ arg reg 1 ] * - * SP + nargs_off [ args count ] + * SP + nregs_off [ arg regs count ] * * SP + ip_off [ traced function ] BPF_TRAMP_F_IP_ARG flag * @@ -1816,13 +1816,13 @@ static int prepare_trampoline(struct jit_ctx *ctx, struct bpf_tramp_image *im, if (flags & BPF_TRAMP_F_IP_ARG) stack_size += 8; - nargs_off = stack_size; + nregs_off = stack_size; /* room for args count */ stack_size += 8; args_off = stack_size; /* room for args */ - stack_size += nargs * 8; + stack_size += nregs * 8; /* room for return value */ retval_off = stack_size; @@ -1865,12 +1865,12 @@ static int prepare_trampoline(struct jit_ctx *ctx, struct bpf_tramp_image *im, emit(A64_STR64I(A64_R(10), A64_SP, ip_off), ctx); } - /* save args count*/ - emit(A64_MOVZ(1, A64_R(10), nargs, 0), ctx); - emit(A64_STR64I(A64_R(10), A64_SP, nargs_off), ctx); + /* save arg regs count*/ + emit(A64_MOVZ(1, A64_R(10), nregs, 0), ctx); + emit(A64_STR64I(A64_R(10), A64_SP, nregs_off), ctx); - /* save args */ - save_args(ctx, args_off, nargs); + /* save arg regs */ + save_args(ctx, args_off, nregs); /* save callee saved registers */ emit(A64_STR64I(A64_R(19), A64_SP, regs_off), ctx); @@ -1897,7 +1897,7 @@ static int prepare_trampoline(struct jit_ctx *ctx, struct bpf_tramp_image *im, } if (flags & BPF_TRAMP_F_CALL_ORIG) { - restore_args(ctx, args_off, nargs); + restore_args(ctx, args_off, nregs); /* call original func */ emit(A64_LDR64I(A64_R(10), A64_SP, retaddr_off), ctx); emit(A64_ADR(A64_LR, AARCH64_INSN_SIZE * 2), ctx); @@ -1926,7 +1926,7 @@ static int prepare_trampoline(struct jit_ctx *ctx, struct bpf_tramp_image *im, } if (flags & BPF_TRAMP_F_RESTORE_REGS) - restore_args(ctx, args_off, nargs); + restore_args(ctx, args_off, nregs); /* restore callee saved register x19 and x20 */ emit(A64_LDR64I(A64_R(19), A64_SP, regs_off), ctx); @@ -1967,24 +1967,25 @@ int arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *image, void *orig_call) { int i, ret; - int nargs = m->nr_args; + int nregs = m->nr_args; int max_insns = ((long)image_end - (long)image) / AARCH64_INSN_SIZE; struct jit_ctx ctx = { .image = NULL, .idx = 0, }; - /* the first 8 arguments are passed by registers */ - if (nargs > 8) - return -ENOTSUPP; - - /* don't support struct argument */ + /* extra registers needed for struct argument */ for (i = 0; i < MAX_BPF_FUNC_ARGS; i++) { + /* The arg_size is at most 16 bytes, enforced by the verifier. */ if (m->arg_flags[i] & BTF_FMODEL_STRUCT_ARG) - return -ENOTSUPP; + nregs += (m->arg_size[i] + 7) / 8 - 1; } - ret = prepare_trampoline(&ctx, im, tlinks, orig_call, nargs, flags); + /* the first 8 registers are used for arguments */ + if (nregs > 8) + return -ENOTSUPP; + + ret = prepare_trampoline(&ctx, im, tlinks, orig_call, nregs, flags); if (ret < 0) return ret; @@ -1995,7 +1996,7 @@ int arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *image, ctx.idx = 0; jit_fill_hole(image, (unsigned int)(image_end - image)); - ret = prepare_trampoline(&ctx, im, tlinks, orig_call, nargs, flags); + ret = prepare_trampoline(&ctx, im, tlinks, orig_call, nregs, flags); if (ret > 0 && validate_code(&ctx) < 0) ret = -EINVAL; diff --git a/arch/arm64/tools/cpucaps b/arch/arm64/tools/cpucaps index 40ba95472594db7f053ec19b0d10af5088991e95..c80ed4f3cbcee29bebd70bc3071ba3c39b3689d3 100644 --- a/arch/arm64/tools/cpucaps +++ b/arch/arm64/tools/cpucaps @@ -25,6 +25,7 @@ HAS_E0PD HAS_ECV HAS_ECV_CNTPOFF HAS_EPAN +HAS_EVT HAS_GENERIC_AUTH HAS_GENERIC_AUTH_ARCH_QARMA3 HAS_GENERIC_AUTH_ARCH_QARMA5 @@ -32,21 +33,26 @@ HAS_GENERIC_AUTH_IMP_DEF HAS_GIC_CPUIF_SYSREGS HAS_GIC_PRIO_MASKING HAS_GIC_PRIO_RELAXED_SYNC +HAS_HCX HAS_LDAPR HAS_LSE_ATOMICS +HAS_MOPS HAS_NESTED_VIRT HAS_NO_FPSIMD HAS_NO_HW_PREFETCH HAS_PAN +HAS_S1PIE HAS_RAS_EXTN HAS_RNG HAS_SB HAS_STAGE2_FWB +HAS_TCR2 HAS_TIDCP1 HAS_TLB_RANGE HAS_VIRT_HOST_EXTN HAS_WFXT HW_DBM +KVM_HVHE KVM_PROTECTED_MODE MISMATCHED_CACHE_TYPE MTE @@ -77,6 +83,7 @@ WORKAROUND_2077057 WORKAROUND_2457168 WORKAROUND_2645198 WORKAROUND_2658417 +WORKAROUND_AMPERE_AC03_CPU_38 WORKAROUND_TRBE_OVERWRITE_FILL_MODE WORKAROUND_TSB_FLUSH_FAILURE WORKAROUND_TRBE_WRITE_OUT_OF_RANGE diff --git a/arch/arm64/tools/gen-cpucaps.awk b/arch/arm64/tools/gen-cpucaps.awk index 00c9e72a200a5d9e126561dd4790ec76377474f1..8525980379d715bc2bc37b574c385aa8049adce4 100755 --- a/arch/arm64/tools/gen-cpucaps.awk +++ b/arch/arm64/tools/gen-cpucaps.awk @@ -24,12 +24,12 @@ BEGIN { } /^[vA-Z0-9_]+$/ { - printf("#define ARM64_%-30s\t%d\n", $0, cap_num++) + printf("#define ARM64_%-40s\t%d\n", $0, cap_num++) next } END { - printf("#define ARM64_NCAPS\t\t\t\t%d\n", cap_num) + printf("#define ARM64_NCAPS\t\t\t\t\t%d\n", cap_num) print "" print "#endif /* __ASM_CPUCAPS_H */" } diff --git a/arch/arm64/tools/sysreg b/arch/arm64/tools/sysreg index c9a0d1fa3209093edfff53aca58f185300c12de0..1ea4a3dc68f886d50429fb76e6f5145ff563f843 100644 --- a/arch/arm64/tools/sysreg +++ b/arch/arm64/tools/sysreg @@ -48,6 +48,61 @@ # feature that introduces them (eg, FEAT_LS64_ACCDATA introduces enumeration # item ACCDATA) though it may be more taseful to do something else. +Sysreg OSDTRRX_EL1 2 0 0 0 2 +Res0 63:32 +Field 31:0 DTRRX +EndSysreg + +Sysreg MDCCINT_EL1 2 0 0 2 0 +Res0 63:31 +Field 30 RX +Field 29 TX +Res0 28:0 +EndSysreg + +Sysreg MDSCR_EL1 2 0 0 2 2 +Res0 63:36 +Field 35 EHBWE +Field 34 EnSPM +Field 33 TTA +Field 32 EMBWE +Field 31 TFO +Field 30 RXfull +Field 29 TXfull +Res0 28 +Field 27 RXO +Field 26 TXU +Res0 25:24 +Field 23:22 INTdis +Field 21 TDA +Res0 20 +Field 19 SC2 +Res0 18:16 +Field 15 MDE +Field 14 HDE +Field 13 KDE +Field 12 TDCC +Res0 11:7 +Field 6 ERR +Res0 5:1 +Field 0 SS +EndSysreg + +Sysreg OSDTRTX_EL1 2 0 0 3 2 +Res0 63:32 +Field 31:0 DTRTX +EndSysreg + +Sysreg OSECCR_EL1 2 0 0 6 2 +Res0 63:32 +Field 31:0 EDECCR +EndSysreg + +Sysreg OSLAR_EL1 2 0 1 0 4 +Res0 63:1 +Field 0 OSLK +EndSysreg + Sysreg ID_PFR0_EL1 3 0 0 1 0 Res0 63:32 UnsignedEnum 31:28 RAS @@ -1538,6 +1593,78 @@ UnsignedEnum 3:0 CnP EndEnum EndSysreg +Sysreg ID_AA64MMFR3_EL1 3 0 0 7 3 +UnsignedEnum 63:60 Spec_FPACC + 0b0000 NI + 0b0001 IMP +EndEnum +UnsignedEnum 59:56 ADERR + 0b0000 NI + 0b0001 DEV_ASYNC + 0b0010 FEAT_ADERR + 0b0011 FEAT_ADERR_IND +EndEnum +UnsignedEnum 55:52 SDERR + 0b0000 NI + 0b0001 DEV_SYNC + 0b0010 FEAT_ADERR + 0b0011 FEAT_ADERR_IND +EndEnum +Res0 51:48 +UnsignedEnum 47:44 ANERR + 0b0000 NI + 0b0001 ASYNC + 0b0010 FEAT_ANERR + 0b0011 FEAT_ANERR_IND +EndEnum +UnsignedEnum 43:40 SNERR + 0b0000 NI + 0b0001 SYNC + 0b0010 FEAT_ANERR + 0b0011 FEAT_ANERR_IND +EndEnum +UnsignedEnum 39:36 D128_2 + 0b0000 NI + 0b0001 IMP +EndEnum +UnsignedEnum 35:32 D128 + 0b0000 NI + 0b0001 IMP +EndEnum +UnsignedEnum 31:28 MEC + 0b0000 NI + 0b0001 IMP +EndEnum +UnsignedEnum 27:24 AIE + 0b0000 NI + 0b0001 IMP +EndEnum +UnsignedEnum 23:20 S2POE + 0b0000 NI + 0b0001 IMP +EndEnum +UnsignedEnum 19:16 S1POE + 0b0000 NI + 0b0001 IMP +EndEnum +UnsignedEnum 15:12 S2PIE + 0b0000 NI + 0b0001 IMP +EndEnum +UnsignedEnum 11:8 S1PIE + 0b0000 NI + 0b0001 IMP +EndEnum +UnsignedEnum 7:4 SCTLRX + 0b0000 NI + 0b0001 IMP +EndEnum +UnsignedEnum 3:0 TCRX + 0b0000 NI + 0b0001 IMP +EndEnum +EndSysreg + Sysreg SCTLR_EL1 3 0 1 0 0 Field 63 TIDCP Field 62 SPINTMASK @@ -2034,7 +2161,17 @@ Fields ZCR_ELx EndSysreg Sysreg HCRX_EL2 3 4 1 2 2 -Res0 63:12 +Res0 63:23 +Field 22 GCSEn +Field 21 EnIDCP128 +Field 20 EnSDERR +Field 19 TMEA +Field 18 EnSNERR +Field 17 D128En +Field 16 PTTWI +Field 15 SCTLR2En +Field 14 TCR2En +Res0 13:12 Field 11 MSCEn Field 10 MCE2 Field 9 CMOW @@ -2153,6 +2290,87 @@ Sysreg TTBR1_EL1 3 0 2 0 1 Fields TTBRx_EL1 EndSysreg +SysregFields TCR2_EL1x +Res0 63:16 +Field 15 DisCH1 +Field 14 DisCH0 +Res0 13:12 +Field 11 HAFT +Field 10 PTTWI +Res0 9:6 +Field 5 D128 +Field 4 AIE +Field 3 POE +Field 2 E0POE +Field 1 PIE +Field 0 PnCH +EndSysregFields + +Sysreg TCR2_EL1 3 0 2 0 3 +Fields TCR2_EL1x +EndSysreg + +Sysreg TCR2_EL12 3 5 2 0 3 +Fields TCR2_EL1x +EndSysreg + +Sysreg TCR2_EL2 3 4 2 0 3 +Res0 63:16 +Field 15 DisCH1 +Field 14 DisCH0 +Field 13 AMEC1 +Field 12 AMEC0 +Field 11 HAFT +Field 10 PTTWI +Field 9:8 SKL1 +Field 7:6 SKL0 +Field 5 D128 +Field 4 AIE +Field 3 POE +Field 2 E0POE +Field 1 PIE +Field 0 PnCH +EndSysreg + +SysregFields PIRx_ELx +Field 63:60 Perm15 +Field 59:56 Perm14 +Field 55:52 Perm13 +Field 51:48 Perm12 +Field 47:44 Perm11 +Field 43:40 Perm10 +Field 39:36 Perm9 +Field 35:32 Perm8 +Field 31:28 Perm7 +Field 27:24 Perm6 +Field 23:20 Perm5 +Field 19:16 Perm4 +Field 15:12 Perm3 +Field 11:8 Perm2 +Field 7:4 Perm1 +Field 3:0 Perm0 +EndSysregFields + +Sysreg PIRE0_EL1 3 0 10 2 2 +Fields PIRx_ELx +EndSysreg + +Sysreg PIRE0_EL12 3 5 10 2 2 +Fields PIRx_ELx +EndSysreg + +Sysreg PIR_EL1 3 0 10 2 3 +Fields PIRx_ELx +EndSysreg + +Sysreg PIR_EL12 3 5 10 2 3 +Fields PIRx_ELx +EndSysreg + +Sysreg PIR_EL2 3 4 10 2 3 +Fields PIRx_ELx +EndSysreg + Sysreg LORSA_EL1 3 0 10 4 0 Res0 63:52 Field 51:16 SA @@ -2200,3 +2418,80 @@ Sysreg ICC_NMIAR1_EL1 3 0 12 9 5 Res0 63:24 Field 23:0 INTID EndSysreg + +Sysreg TRBLIMITR_EL1 3 0 9 11 0 +Field 63:12 LIMIT +Res0 11:7 +Field 6 XE +Field 5 nVM +Enum 4:3 TM + 0b00 STOP + 0b01 IRQ + 0b11 IGNR +EndEnum +Enum 2:1 FM + 0b00 FILL + 0b01 WRAP + 0b11 CBUF +EndEnum +Field 0 E +EndSysreg + +Sysreg TRBPTR_EL1 3 0 9 11 1 +Field 63:0 PTR +EndSysreg + +Sysreg TRBBASER_EL1 3 0 9 11 2 +Field 63:12 BASE +Res0 11:0 +EndSysreg + +Sysreg TRBSR_EL1 3 0 9 11 3 +Res0 63:56 +Field 55:32 MSS2 +Field 31:26 EC +Res0 25:24 +Field 23 DAT +Field 22 IRQ +Field 21 TRG +Field 20 WRAP +Res0 19 +Field 18 EA +Field 17 S +Res0 16 +Field 15:0 MSS +EndSysreg + +Sysreg TRBMAR_EL1 3 0 9 11 4 +Res0 63:12 +Enum 11:10 PAS + 0b00 SECURE + 0b01 NON_SECURE + 0b10 ROOT + 0b11 REALM +EndEnum +Enum 9:8 SH + 0b00 NON_SHAREABLE + 0b10 OUTER_SHAREABLE + 0b11 INNER_SHAREABLE +EndEnum +Field 7:0 Attr +EndSysreg + +Sysreg TRBTRG_EL1 3 0 9 11 6 +Res0 63:32 +Field 31:0 TRG +EndSysreg + +Sysreg TRBIDR_EL1 3 0 9 11 7 +Res0 63:12 +Enum 11:8 EA + 0b0000 NON_DESC + 0b0001 IGNORE + 0b0010 SERROR +EndEnum +Res0 7:6 +Field 5 F +Field 4 P +Field 3:0 Align +EndSysreg diff --git a/arch/csky/Kconfig b/arch/csky/Kconfig index 4df1f8c9d170b3359d3759d1ce1640bf76a422af..cf2a6fd7dff8715529a7365867c1819f01bf7dbf 100644 --- a/arch/csky/Kconfig +++ b/arch/csky/Kconfig @@ -96,6 +96,8 @@ config CSKY select HAVE_REGS_AND_STACK_ACCESS_API select HAVE_STACKPROTECTOR select HAVE_SYSCALL_TRACEPOINTS + select HOTPLUG_CORE_SYNC_DEAD if HOTPLUG_CPU + select LOCK_MM_AND_FIND_VMA select MAY_HAVE_SPARSE_IRQ select MODULES_USE_ELF_RELA if MODULES select OF diff --git a/arch/csky/include/asm/atomic.h b/arch/csky/include/asm/atomic.h index 60406ef9c2bbcb573f7ad6f7b5b8bdbe4e55e000..4dab44f6143a5fe6f2fc10dae0f2d76284261839 100644 --- a/arch/csky/include/asm/atomic.h +++ b/arch/csky/include/asm/atomic.h @@ -195,41 +195,6 @@ arch_atomic_dec_if_positive(atomic_t *v) } #define arch_atomic_dec_if_positive arch_atomic_dec_if_positive -#define ATOMIC_OP() \ -static __always_inline \ -int arch_atomic_xchg_relaxed(atomic_t *v, int n) \ -{ \ - return __xchg_relaxed(n, &(v->counter), 4); \ -} \ -static __always_inline \ -int arch_atomic_cmpxchg_relaxed(atomic_t *v, int o, int n) \ -{ \ - return __cmpxchg_relaxed(&(v->counter), o, n, 4); \ -} \ -static __always_inline \ -int arch_atomic_cmpxchg_acquire(atomic_t *v, int o, int n) \ -{ \ - return __cmpxchg_acquire(&(v->counter), o, n, 4); \ -} \ -static __always_inline \ -int arch_atomic_cmpxchg(atomic_t *v, int o, int n) \ -{ \ - return __cmpxchg(&(v->counter), o, n, 4); \ -} - -#define ATOMIC_OPS() \ - ATOMIC_OP() - -ATOMIC_OPS() - -#define arch_atomic_xchg_relaxed arch_atomic_xchg_relaxed -#define arch_atomic_cmpxchg_relaxed arch_atomic_cmpxchg_relaxed -#define arch_atomic_cmpxchg_acquire arch_atomic_cmpxchg_acquire -#define arch_atomic_cmpxchg arch_atomic_cmpxchg - -#undef ATOMIC_OPS -#undef ATOMIC_OP - #else #include #endif diff --git a/arch/csky/include/asm/smp.h b/arch/csky/include/asm/smp.h index 668b79ce29ea111d700f66d4ccf348acd85a3f7b..d3db334f319648d9ed500cf56b4f60181ce3597c 100644 --- a/arch/csky/include/asm/smp.h +++ b/arch/csky/include/asm/smp.h @@ -23,7 +23,7 @@ void __init set_send_ipi(void (*func)(const struct cpumask *mask), int irq); int __cpu_disable(void); -void __cpu_die(unsigned int cpu); +static inline void __cpu_die(unsigned int cpu) { } #endif /* CONFIG_SMP */ diff --git a/arch/csky/kernel/probes/uprobes.c b/arch/csky/kernel/probes/uprobes.c index 2d31a12e46cfee0bcb202957a4c4b8eb3bcca223..936bea6fd32d191d349a288c8874db0eebc7c4bf 100644 --- a/arch/csky/kernel/probes/uprobes.c +++ b/arch/csky/kernel/probes/uprobes.c @@ -64,6 +64,7 @@ int arch_uprobe_post_xol(struct arch_uprobe *auprobe, struct pt_regs *regs) struct uprobe_task *utask = current->utask; WARN_ON_ONCE(current->thread.trap_no != UPROBE_TRAP_NR); + current->thread.trap_no = utask->autask.saved_trap_no; instruction_pointer_set(regs, utask->vaddr + auprobe->insn_size); @@ -101,6 +102,8 @@ void arch_uprobe_abort_xol(struct arch_uprobe *auprobe, struct pt_regs *regs) { struct uprobe_task *utask = current->utask; + current->thread.trap_no = utask->autask.saved_trap_no; + /* * Task has received a fatal signal, so reset back to probed * address. diff --git a/arch/csky/kernel/smp.c b/arch/csky/kernel/smp.c index b12e2c3c387f89582edc9a3e08155ec4f86a159f..8e42352cbf123f4bc771dfefda013bf12d818cfa 100644 --- a/arch/csky/kernel/smp.c +++ b/arch/csky/kernel/smp.c @@ -291,12 +291,8 @@ int __cpu_disable(void) return 0; } -void __cpu_die(unsigned int cpu) +void arch_cpuhp_cleanup_dead_cpu(unsigned int cpu) { - if (!cpu_wait_death(cpu, 5)) { - pr_crit("CPU%u: shutdown failed\n", cpu); - return; - } pr_notice("CPU%u: shutdown\n", cpu); } @@ -304,7 +300,7 @@ void __noreturn arch_cpu_idle_dead(void) { idle_task_exit(); - cpu_report_death(); + cpuhp_ap_report_dead(); while (!secondary_stack) arch_cpu_idle(); diff --git a/arch/csky/mm/fault.c b/arch/csky/mm/fault.c index e15f736cca4b4a43fb14989e099051fbdbf0a082..a885518ce1dd285671e1e06d548cd91aa7f855f5 100644 --- a/arch/csky/mm/fault.c +++ b/arch/csky/mm/fault.c @@ -97,13 +97,12 @@ static inline void mm_fault_error(struct pt_regs *regs, unsigned long addr, vm_f BUG(); } -static inline void bad_area(struct pt_regs *regs, struct mm_struct *mm, int code, unsigned long addr) +static inline void bad_area_nosemaphore(struct pt_regs *regs, struct mm_struct *mm, int code, unsigned long addr) { /* * Something tried to access memory that isn't in our memory map. * Fix it, but check if it's kernel or user first. */ - mmap_read_unlock(mm); /* User mode accesses just cause a SIGSEGV */ if (user_mode(regs)) { do_trap(regs, SIGSEGV, code, addr); @@ -238,20 +237,9 @@ asmlinkage void do_page_fault(struct pt_regs *regs) if (is_write(regs)) flags |= FAULT_FLAG_WRITE; retry: - mmap_read_lock(mm); - vma = find_vma(mm, addr); + vma = lock_mm_and_find_vma(mm, addr, regs); if (unlikely(!vma)) { - bad_area(regs, mm, code, addr); - return; - } - if (likely(vma->vm_start <= addr)) - goto good_area; - if (unlikely(!(vma->vm_flags & VM_GROWSDOWN))) { - bad_area(regs, mm, code, addr); - return; - } - if (unlikely(expand_stack(vma, addr))) { - bad_area(regs, mm, code, addr); + bad_area_nosemaphore(regs, mm, code, addr); return; } @@ -259,11 +247,11 @@ asmlinkage void do_page_fault(struct pt_regs *regs) * Ok, we have a good vm_area for this memory access, so * we can handle it. */ -good_area: code = SEGV_ACCERR; if (unlikely(access_error(regs, vma))) { - bad_area(regs, mm, code, addr); + mmap_read_unlock(mm); + bad_area_nosemaphore(regs, mm, code, addr); return; } diff --git a/arch/hexagon/Kconfig b/arch/hexagon/Kconfig index 54eadf26517868f8cd575a1d5b777be700e35354..6726f4941015f353624a81838f6368c85508a0a7 100644 --- a/arch/hexagon/Kconfig +++ b/arch/hexagon/Kconfig @@ -28,6 +28,7 @@ config HEXAGON select GENERIC_SMP_IDLE_THREAD select STACKTRACE_SUPPORT select GENERIC_CLOCKEVENTS_BROADCAST + select LOCK_MM_AND_FIND_VMA select MODULES_USE_ELF_RELA select GENERIC_CPU_DEVICES select ARCH_WANT_LD_ORPHAN_WARN diff --git a/arch/hexagon/include/asm/atomic.h b/arch/hexagon/include/asm/atomic.h index 6e94f8d04146f4e0e2b0de37544181556e08f4d6..2447d083c432f819dd0523bbbcd05ee498db3cf3 100644 --- a/arch/hexagon/include/asm/atomic.h +++ b/arch/hexagon/include/asm/atomic.h @@ -28,58 +28,8 @@ static inline void arch_atomic_set(atomic_t *v, int new) #define arch_atomic_set_release(v, i) arch_atomic_set((v), (i)) -/** - * arch_atomic_read - reads a word, atomically - * @v: pointer to atomic value - * - * Assumes all word reads on our architecture are atomic. - */ #define arch_atomic_read(v) READ_ONCE((v)->counter) -/** - * arch_atomic_xchg - atomic - * @v: pointer to memory to change - * @new: new value (technically passed in a register -- see xchg) - */ -#define arch_atomic_xchg(v, new) (arch_xchg(&((v)->counter), (new))) - - -/** - * arch_atomic_cmpxchg - atomic compare-and-exchange values - * @v: pointer to value to change - * @old: desired old value to match - * @new: new value to put in - * - * Parameters are then pointer, value-in-register, value-in-register, - * and the output is the old value. - * - * Apparently this is complicated for archs that don't support - * the memw_locked like we do (or it's broken or whatever). - * - * Kind of the lynchpin of the rest of the generically defined routines. - * Remember V2 had that bug with dotnew predicate set by memw_locked. - * - * "old" is "expected" old val, __oldval is actual old value - */ -static inline int arch_atomic_cmpxchg(atomic_t *v, int old, int new) -{ - int __oldval; - - asm volatile( - "1: %0 = memw_locked(%1);\n" - " { P0 = cmp.eq(%0,%2);\n" - " if (!P0.new) jump:nt 2f; }\n" - " memw_locked(%1,P0) = %3;\n" - " if (!P0) jump 1b;\n" - "2:\n" - : "=&r" (__oldval) - : "r" (&v->counter), "r" (old), "r" (new) - : "memory", "p0" - ); - - return __oldval; -} - #define ATOMIC_OP(op) \ static inline void arch_atomic_##op(int i, atomic_t *v) \ { \ @@ -135,6 +85,11 @@ static inline int arch_atomic_fetch_##op(int i, atomic_t *v) \ ATOMIC_OPS(add) ATOMIC_OPS(sub) +#define arch_atomic_add_return arch_atomic_add_return +#define arch_atomic_sub_return arch_atomic_sub_return +#define arch_atomic_fetch_add arch_atomic_fetch_add +#define arch_atomic_fetch_sub arch_atomic_fetch_sub + #undef ATOMIC_OPS #define ATOMIC_OPS(op) ATOMIC_OP(op) ATOMIC_FETCH_OP(op) @@ -142,21 +97,15 @@ ATOMIC_OPS(and) ATOMIC_OPS(or) ATOMIC_OPS(xor) +#define arch_atomic_fetch_and arch_atomic_fetch_and +#define arch_atomic_fetch_or arch_atomic_fetch_or +#define arch_atomic_fetch_xor arch_atomic_fetch_xor + #undef ATOMIC_OPS #undef ATOMIC_FETCH_OP #undef ATOMIC_OP_RETURN #undef ATOMIC_OP -/** - * arch_atomic_fetch_add_unless - add unless the number is a given value - * @v: pointer to value - * @a: amount to add - * @u: unless value is equal to u - * - * Returns old value. - * - */ - static inline int arch_atomic_fetch_add_unless(atomic_t *v, int a, int u) { int __oldval; diff --git a/arch/hexagon/kernel/setup.c b/arch/hexagon/kernel/setup.c index 1880d9beaf2b670a7959f813ed34b2e983703bd6..621674e86232acf0d5433dc8919c47083f629708 100644 --- a/arch/hexagon/kernel/setup.c +++ b/arch/hexagon/kernel/setup.c @@ -66,9 +66,9 @@ void __init setup_arch(char **cmdline_p) on_simulator = 0; if (p[0] != '\0') - strlcpy(boot_command_line, p, COMMAND_LINE_SIZE); + strscpy(boot_command_line, p, COMMAND_LINE_SIZE); else - strlcpy(boot_command_line, default_command_line, + strscpy(boot_command_line, default_command_line, COMMAND_LINE_SIZE); /* @@ -76,7 +76,7 @@ void __init setup_arch(char **cmdline_p) * are both picked up by the init code. If no reason to * make them different, pass the same pointer back. */ - strlcpy(cmd_line, boot_command_line, COMMAND_LINE_SIZE); + strscpy(cmd_line, boot_command_line, COMMAND_LINE_SIZE); *cmdline_p = cmd_line; parse_early_param(); diff --git a/arch/hexagon/mm/vm_fault.c b/arch/hexagon/mm/vm_fault.c index 4b578d02fd01a9eb1513d34b708a84f6e5af31b5..7295ea3f8cc8d3c6f7cdec6fdcded75f11facb7a 100644 --- a/arch/hexagon/mm/vm_fault.c +++ b/arch/hexagon/mm/vm_fault.c @@ -57,21 +57,10 @@ void do_page_fault(unsigned long address, long cause, struct pt_regs *regs) perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address); retry: - mmap_read_lock(mm); - vma = find_vma(mm, address); - if (!vma) - goto bad_area; + vma = lock_mm_and_find_vma(mm, address, regs); + if (unlikely(!vma)) + goto bad_area_nosemaphore; - if (vma->vm_start <= address) - goto good_area; - - if (!(vma->vm_flags & VM_GROWSDOWN)) - goto bad_area; - - if (expand_stack(vma, address)) - goto bad_area; - -good_area: /* Address space is OK. Now check access rights. */ si_code = SEGV_ACCERR; @@ -143,6 +132,7 @@ void do_page_fault(unsigned long address, long cause, struct pt_regs *regs) bad_area: mmap_read_unlock(mm); +bad_area_nosemaphore: if (user_mode(regs)) { force_sig_fault(SIGSEGV, si_code, (void __user *)address); return; diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig index 21fa63ce5ffc05e1cd65ede412f3015cab3132f6..2cd93e6bf0fec6979b7e54139e77e5f2f40f0f0f 100644 --- a/arch/ia64/Kconfig +++ b/arch/ia64/Kconfig @@ -9,6 +9,7 @@ menu "Processor type and features" config IA64 bool select ARCH_BINFMT_ELF_EXTRA_PHDRS + select ARCH_HAS_CPU_FINALIZE_INIT select ARCH_HAS_DMA_MARK_CLEAN select ARCH_HAS_STRNCPY_FROM_USER select ARCH_HAS_STRNLEN_USER diff --git a/arch/ia64/include/asm/Kbuild b/arch/ia64/include/asm/Kbuild index aefae2efde9f323d5223fad507a996bc5abcdeb5..33733245f42ba1eb7284e23cd7fbd968cf1383c7 100644 --- a/arch/ia64/include/asm/Kbuild +++ b/arch/ia64/include/asm/Kbuild @@ -1,6 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 generated-y += syscall_table.h generic-y += agp.h +generic-y += export.h generic-y += kvm_para.h generic-y += mcs_spinlock.h generic-y += vtime.h diff --git a/arch/ia64/include/asm/atomic.h b/arch/ia64/include/asm/atomic.h index 266c429b91372e9302d373ccbd00684df414d6e9..6540a628d2573cb536949aefa1eb8b1141e99c67 100644 --- a/arch/ia64/include/asm/atomic.h +++ b/arch/ia64/include/asm/atomic.h @@ -207,13 +207,6 @@ ATOMIC64_FETCH_OP(xor, ^) #undef ATOMIC64_FETCH_OP #undef ATOMIC64_OP -#define arch_atomic_cmpxchg(v, old, new) (arch_cmpxchg(&((v)->counter), old, new)) -#define arch_atomic_xchg(v, new) (arch_xchg(&((v)->counter), new)) - -#define arch_atomic64_cmpxchg(v, old, new) \ - (arch_cmpxchg(&((v)->counter), old, new)) -#define arch_atomic64_xchg(v, new) (arch_xchg(&((v)->counter), new)) - #define arch_atomic_add(i,v) (void)arch_atomic_add_return((i), (v)) #define arch_atomic_sub(i,v) (void)arch_atomic_sub_return((i), (v)) diff --git a/arch/ia64/include/asm/bugs.h b/arch/ia64/include/asm/bugs.h deleted file mode 100644 index 0d6b9bded56c6ba2d9c1e381fd05496cf25f86ff..0000000000000000000000000000000000000000 --- a/arch/ia64/include/asm/bugs.h +++ /dev/null @@ -1,20 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * This is included by init/main.c to check for architecture-dependent bugs. - * - * Needs: - * void check_bugs(void); - * - * Based on . - * - * Modified 1998, 1999, 2003 - * David Mosberger-Tang , Hewlett-Packard Co. - */ -#ifndef _ASM_IA64_BUGS_H -#define _ASM_IA64_BUGS_H - -#include - -extern void check_bugs (void); - -#endif /* _ASM_IA64_BUGS_H */ diff --git a/arch/ia64/include/asm/export.h b/arch/ia64/include/asm/export.h deleted file mode 100644 index ad18c65832520b847d71cbc365f82e2f0bc3b235..0000000000000000000000000000000000000000 --- a/arch/ia64/include/asm/export.h +++ /dev/null @@ -1,3 +0,0 @@ -/* EXPORT_DATA_SYMBOL != EXPORT_SYMBOL here */ -#define KSYM_FUNC(name) @fptr(name) -#include diff --git a/arch/ia64/kernel/head.S b/arch/ia64/kernel/head.S index f22469f1c1fcccd5bbeeecb3d56013e8a5788b68..c096500590e9623aa6087d1bca30cb3c6d001c1d 100644 --- a/arch/ia64/kernel/head.S +++ b/arch/ia64/kernel/head.S @@ -170,7 +170,7 @@ RestRR: \ __PAGE_ALIGNED_DATA .global empty_zero_page -EXPORT_DATA_SYMBOL_GPL(empty_zero_page) +EXPORT_SYMBOL_GPL(empty_zero_page) empty_zero_page: .skip PAGE_SIZE diff --git a/arch/ia64/kernel/ivt.S b/arch/ia64/kernel/ivt.S index d6d4229b28db8ba11a96199c0ab4297133453224..7a418e324d3000786e926547ef2e4fcffb38710e 100644 --- a/arch/ia64/kernel/ivt.S +++ b/arch/ia64/kernel/ivt.S @@ -87,7 +87,7 @@ .align 32768 // align on 32KB boundary .global ia64_ivt - EXPORT_DATA_SYMBOL(ia64_ivt) + EXPORT_SYMBOL(ia64_ivt) ia64_ivt: ///////////////////////////////////////////////////////////////////////////////////////// // 0x0000 Entry 0 (size 64 bundles) VHPT Translation (8,20,47) diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c index c0572804427275e7837c8b6524411f16e453fafc..5a55ac82c13a47e86ca6e79db1469ce508edbdce 100644 --- a/arch/ia64/kernel/setup.c +++ b/arch/ia64/kernel/setup.c @@ -627,7 +627,7 @@ setup_arch (char **cmdline_p) * is physical disk 1 partition 1 and the Linux root disk is * physical disk 1 partition 2. */ - ROOT_DEV = Root_SDA2; /* default to second partition on first drive */ + ROOT_DEV = MKDEV(SCSI_DISK0_MAJOR, 2); if (is_uv_system()) uv_setup(cmdline_p); @@ -1067,8 +1067,7 @@ cpu_init (void) } } -void __init -check_bugs (void) +void __init arch_cpu_finalize_init(void) { ia64_patch_mckinley_e9((unsigned long) __start___mckinley_e9_bundles, (unsigned long) __end___mckinley_e9_bundles); diff --git a/arch/ia64/kernel/syscalls/syscall.tbl b/arch/ia64/kernel/syscalls/syscall.tbl index 72c929d9902b99601ed98f25f89ed88cc2d9935e..f8c74ffeeefbe5d0a01ac5e4ec5794b4dbdaa4d1 100644 --- a/arch/ia64/kernel/syscalls/syscall.tbl +++ b/arch/ia64/kernel/syscalls/syscall.tbl @@ -371,3 +371,4 @@ 448 common process_mrelease sys_process_mrelease 449 common futex_waitv sys_futex_waitv 450 common set_mempolicy_home_node sys_set_mempolicy_home_node +451 common cachestat sys_cachestat diff --git a/arch/ia64/mm/fault.c b/arch/ia64/mm/fault.c index 85c4d9ac8686d805399b926929a59ed19dc2c506..5458b52b4009967fcc07cbc752ce7ac3b9d2dc32 100644 --- a/arch/ia64/mm/fault.c +++ b/arch/ia64/mm/fault.c @@ -110,10 +110,12 @@ ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *re * register backing store that needs to expand upwards, in * this case vma will be null, but prev_vma will ne non-null */ - if (( !vma && prev_vma ) || (address < vma->vm_start) ) - goto check_expansion; + if (( !vma && prev_vma ) || (address < vma->vm_start) ) { + vma = expand_stack(mm, address); + if (!vma) + goto bad_area_nosemaphore; + } - good_area: code = SEGV_ACCERR; /* OK, we've got a good vm_area for this memory area. Check the access permissions: */ @@ -177,35 +179,9 @@ ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *re mmap_read_unlock(mm); return; - check_expansion: - if (!(prev_vma && (prev_vma->vm_flags & VM_GROWSUP) && (address == prev_vma->vm_end))) { - if (!vma) - goto bad_area; - if (!(vma->vm_flags & VM_GROWSDOWN)) - goto bad_area; - if (REGION_NUMBER(address) != REGION_NUMBER(vma->vm_start) - || REGION_OFFSET(address) >= RGN_MAP_LIMIT) - goto bad_area; - if (expand_stack(vma, address)) - goto bad_area; - } else { - vma = prev_vma; - if (REGION_NUMBER(address) != REGION_NUMBER(vma->vm_start) - || REGION_OFFSET(address) >= RGN_MAP_LIMIT) - goto bad_area; - /* - * Since the register backing store is accessed sequentially, - * we disallow growing it by more than a page at a time. - */ - if (address > vma->vm_end + PAGE_SIZE - sizeof(long)) - goto bad_area; - if (expand_upwards(vma, address)) - goto bad_area; - } - goto good_area; - bad_area: mmap_read_unlock(mm); + bad_area_nosemaphore: if ((isr & IA64_ISR_SP) || ((isr & IA64_ISR_NA) && (isr & IA64_ISR_CODE_MASK) == IA64_ISR_CODE_LFETCH)) { diff --git a/arch/ia64/mm/hugetlbpage.c b/arch/ia64/mm/hugetlbpage.c index 78a02e02616495cbe1567a4fd6fb91c4ed62e2c0..adc49f2d22e89b9c691426b159458f7ac9e87371 100644 --- a/arch/ia64/mm/hugetlbpage.c +++ b/arch/ia64/mm/hugetlbpage.c @@ -41,7 +41,7 @@ huge_pte_alloc(struct mm_struct *mm, struct vm_area_struct *vma, if (pud) { pmd = pmd_alloc(mm, pud, taddr); if (pmd) - pte = pte_alloc_map(mm, pmd, taddr); + pte = pte_alloc_huge(mm, pmd, taddr); } return pte; } @@ -64,7 +64,7 @@ huge_pte_offset (struct mm_struct *mm, unsigned long addr, unsigned long sz) if (pud_present(*pud)) { pmd = pmd_offset(pud, taddr); if (pmd_present(*pmd)) - pte = pte_offset_map(pmd, taddr); + pte = pte_offset_huge(pmd, taddr); } } } diff --git a/arch/loongarch/Kconfig b/arch/loongarch/Kconfig index d38b066fc931bc31758ee12d3c3800b6154d0641..e55511af4c77d96b22e0df904138951eefe69326 100644 --- a/arch/loongarch/Kconfig +++ b/arch/loongarch/Kconfig @@ -5,11 +5,13 @@ config LOONGARCH select ACPI select ACPI_GENERIC_GSI if ACPI select ACPI_MCFG if ACPI + select ACPI_PPTT if ACPI select ACPI_SYSTEM_POWER_STATES_SUPPORT if ACPI select ARCH_BINFMT_ELF_STATE select ARCH_ENABLE_MEMORY_HOTPLUG select ARCH_ENABLE_MEMORY_HOTREMOVE select ARCH_HAS_ACPI_TABLE_UPGRADE if ACPI + select ARCH_HAS_CPU_FINALIZE_INIT select ARCH_HAS_FORTIFY_SOURCE select ARCH_HAS_NMI_SAFE_THIS_CPU_OPS select ARCH_HAS_PTE_SPECIAL @@ -48,6 +50,8 @@ config LOONGARCH select ARCH_SUPPORTS_ACPI select ARCH_SUPPORTS_ATOMIC_RMW select ARCH_SUPPORTS_HUGETLBFS + select ARCH_SUPPORTS_LTO_CLANG + select ARCH_SUPPORTS_LTO_CLANG_THIN select ARCH_SUPPORTS_NUMA_BALANCING select ARCH_USE_BUILTIN_BSWAP select ARCH_USE_CMPXCHG_LOCKREF @@ -80,9 +84,12 @@ config LOONGARCH select GENERIC_SCHED_CLOCK select GENERIC_SMP_IDLE_THREAD select GENERIC_TIME_VSYSCALL + select GENERIC_VDSO_TIME_NS select GPIOLIB select HAS_IOPORT select HAVE_ARCH_AUDITSYSCALL + select HAVE_ARCH_JUMP_LABEL + select HAVE_ARCH_JUMP_LABEL_RELATIVE select HAVE_ARCH_MMAP_RND_BITS if MMU select HAVE_ARCH_SECCOMP_FILTER select HAVE_ARCH_TRACEHOOK @@ -90,6 +97,7 @@ config LOONGARCH select HAVE_ASM_MODVERSIONS select HAVE_CONTEXT_TRACKING_USER select HAVE_C_RECORDMCOUNT + select HAVE_DEBUG_KMEMLEAK select HAVE_DEBUG_STACKOVERFLOW select HAVE_DMA_CONTIGUOUS select HAVE_DYNAMIC_FTRACE @@ -103,6 +111,7 @@ config LOONGARCH select HAVE_FTRACE_MCOUNT_RECORD select HAVE_FUNCTION_ARG_ACCESS_API select HAVE_FUNCTION_ERROR_INJECTION + select HAVE_FUNCTION_GRAPH_RETVAL if HAVE_FUNCTION_GRAPH_TRACER select HAVE_FUNCTION_GRAPH_TRACER select HAVE_FUNCTION_TRACER select HAVE_GENERIC_VDSO @@ -120,6 +129,7 @@ config LOONGARCH select HAVE_PERF_REGS select HAVE_PERF_USER_STACK_DUMP select HAVE_REGS_AND_STACK_ACCESS_API + select HAVE_RETHOOK select HAVE_RSEQ select HAVE_SAMPLE_FTRACE_DIRECT select HAVE_SAMPLE_FTRACE_DIRECT_MULTI @@ -130,6 +140,7 @@ config LOONGARCH select HAVE_VIRT_CPU_ACCOUNTING_GEN if !SMP select IRQ_FORCED_THREADING select IRQ_LOONGARCH_CPU + select LOCK_MM_AND_FIND_VMA select MMU_GATHER_MERGE_VMAS if MMU select MODULES_USE_ELF_RELA if MODULES select NEED_PER_CPU_EMBED_FIRST_CHUNK @@ -161,14 +172,6 @@ config 32BIT config 64BIT def_bool y -config CPU_HAS_FPU - bool - default y - -config CPU_HAS_PREFETCH - bool - default y - config GENERIC_BUG def_bool y depends on BUG @@ -241,6 +244,15 @@ config SCHED_OMIT_FRAME_POINTER config AS_HAS_EXPLICIT_RELOCS def_bool $(as-instr,x:pcalau12i \$t0$(comma)%pc_hi20(x)) +config AS_HAS_FCSR_CLASS + def_bool $(as-instr,movfcsr2gr \$t0$(comma)\$fcsr0) + +config AS_HAS_LSX_EXTENSION + def_bool $(as-instr,vld \$vr0$(comma)\$a0$(comma)0) + +config AS_HAS_LASX_EXTENSION + def_bool $(as-instr,xvld \$xr0$(comma)\$a0$(comma)0) + menu "Kernel type and options" source "kernel/Kconfig.hz" @@ -372,6 +384,13 @@ config EFI_STUB This kernel feature allows the kernel to be loaded directly by EFI firmware without the use of a bootloader. +config SCHED_SMT + bool "SMT scheduler support" + default y + help + Improves scheduler's performance when there are multiple + threads in one physical core. + config SMP bool "Multi-Processing support" help @@ -481,6 +500,43 @@ config ARCH_STRICT_ALIGN to run kernel only on systems with h/w unaligned access support in order to optimise for performance. +config CPU_HAS_FPU + bool + default y + +config CPU_HAS_LSX + bool "Support for the Loongson SIMD Extension" + depends on AS_HAS_LSX_EXTENSION + help + Loongson SIMD Extension (LSX) introduces 128 bit wide vector registers + and a set of SIMD instructions to operate on them. When this option + is enabled the kernel will support allocating & switching LSX + vector register contexts. If you know that your kernel will only be + running on CPUs which do not support LSX or that your userland will + not be making use of it then you may wish to say N here to reduce + the size & complexity of your kernel. + + If unsure, say Y. + +config CPU_HAS_LASX + bool "Support for the Loongson Advanced SIMD Extension" + depends on CPU_HAS_LSX + depends on AS_HAS_LASX_EXTENSION + help + Loongson Advanced SIMD Extension (LASX) introduces 256 bit wide vector + registers and a set of SIMD instructions to operate on them. When this + option is enabled the kernel will support allocating & switching LASX + vector register contexts. If you know that your kernel will only be + running on CPUs which do not support LASX or that your userland will + not be making use of it then you may wish to say N here to reduce + the size & complexity of your kernel. + + If unsure, say Y. + +config CPU_HAS_PREFETCH + bool + default y + config KEXEC bool "Kexec system call" select KEXEC_CORE @@ -590,6 +646,9 @@ config ARCH_MMAP_RND_BITS_MIN config ARCH_MMAP_RND_BITS_MAX default 18 +config ARCH_SUPPORTS_UPROBES + def_bool y + menu "Power management options" config ARCH_SUSPEND_POSSIBLE diff --git a/arch/loongarch/Makefile b/arch/loongarch/Makefile index a27e264bdaa5a2b23d94eac36d56fd693a50e1f3..09ba338a64dec4f4abd91cf0e1548991f50f6ccd 100644 --- a/arch/loongarch/Makefile +++ b/arch/loongarch/Makefile @@ -46,8 +46,8 @@ ld-emul = $(64bit-emul) cflags-y += -mabi=lp64s endif -cflags-y += -G0 -pipe -msoft-float -LDFLAGS_vmlinux += -G0 -static -n -nostdlib +cflags-y += -pipe -msoft-float +LDFLAGS_vmlinux += -static -n -nostdlib # When the assembler supports explicit relocation hint, we must use it. # GCC may have -mexplicit-relocs off by default if it was built with an old @@ -56,13 +56,18 @@ LDFLAGS_vmlinux += -G0 -static -n -nostdlib # When the assembler does not supports explicit relocation hint, we can't use # it. Disable it if the compiler supports it. # -# If you've seen "unknown reloc hint" message building the kernel and you are -# now wondering why "-mexplicit-relocs" is not wrapped with cc-option: the -# combination of a "new" assembler and "old" compiler is not supported. Either -# upgrade the compiler or downgrade the assembler. +# The combination of a "new" assembler and "old" GCC is not supported, given +# the rarity of this combo and the extra complexity needed to make it work. +# Either upgrade the compiler or downgrade the assembler; the build will error +# out if it is the case (by probing for the model attribute; all supported +# compilers in this case would have support). +# +# Also, -mdirect-extern-access is useful in case of building with explicit +# relocs, for avoiding unnecessary GOT accesses. It is harmless to not have +# support though. ifdef CONFIG_AS_HAS_EXPLICIT_RELOCS -cflags-y += -mexplicit-relocs -KBUILD_CFLAGS_KERNEL += -mdirect-extern-access +cflags-y += $(call cc-option,-mexplicit-relocs) +KBUILD_CFLAGS_KERNEL += $(call cc-option,-mdirect-extern-access) else cflags-y += $(call cc-option,-mno-explicit-relocs) KBUILD_AFLAGS_KERNEL += -Wa,-mla-global-with-pcrel @@ -107,7 +112,7 @@ KBUILD_CFLAGS += -isystem $(shell $(CC) -print-file-name=include) KBUILD_LDFLAGS += -m $(ld-emul) ifdef CONFIG_LOONGARCH -CHECKFLAGS += $(shell $(CC) $(KBUILD_CFLAGS) -dM -E -x c /dev/null | \ +CHECKFLAGS += $(shell $(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) -dM -E -x c /dev/null | \ grep -E -vw '__GNUC_(MINOR_|PATCHLEVEL_)?_' | \ sed -e "s/^\#define /-D'/" -e "s/ /'='/" -e "s/$$/'/" -e 's/\$$/&&/g') endif diff --git a/arch/loongarch/include/asm/Kbuild b/arch/loongarch/include/asm/Kbuild index 77ad8e6f0906c4be1e7e1b52c568de5ac977f416..6b222f227342b4a3c22cbdfc5bfe59a7458cd5ae 100644 --- a/arch/loongarch/include/asm/Kbuild +++ b/arch/loongarch/include/asm/Kbuild @@ -5,7 +5,6 @@ generic-y += mcs_spinlock.h generic-y += parport.h generic-y += early_ioremap.h generic-y += qrwlock.h -generic-y += qspinlock.h generic-y += rwsem.h generic-y += segment.h generic-y += user.h diff --git a/arch/loongarch/include/asm/acpi.h b/arch/loongarch/include/asm/acpi.h index 976a810352c601ddb7bd286a2bf732a1b46b5ae0..8de6c4b83a61a8088903abc67ddc50beb35233d5 100644 --- a/arch/loongarch/include/asm/acpi.h +++ b/arch/loongarch/include/asm/acpi.h @@ -8,11 +8,14 @@ #ifndef _ASM_LOONGARCH_ACPI_H #define _ASM_LOONGARCH_ACPI_H +#include + #ifdef CONFIG_ACPI extern int acpi_strict; extern int acpi_disabled; extern int acpi_pci_disabled; extern int acpi_noirq; +extern int pptt_enabled; #define acpi_os_ioremap acpi_os_ioremap void __iomem *acpi_os_ioremap(acpi_physical_address phys, acpi_size size); @@ -30,6 +33,14 @@ static inline bool acpi_has_cpu_in_madt(void) } extern struct list_head acpi_wakeup_device_list; +extern struct acpi_madt_core_pic acpi_core_pic[NR_CPUS]; + +extern int __init parse_acpi_topology(void); + +static inline u32 get_acpi_id_for_cpu(unsigned int cpu) +{ + return acpi_core_pic[cpu_logical_map(cpu)].processor_id; +} #endif /* !CONFIG_ACPI */ @@ -37,12 +48,10 @@ extern struct list_head acpi_wakeup_device_list; extern int loongarch_acpi_suspend(void); extern int (*acpi_suspend_lowlevel)(void); -extern void loongarch_suspend_enter(void); static inline unsigned long acpi_get_wakeup_address(void) { #ifdef CONFIG_SUSPEND - extern void loongarch_wakeup_start(void); return (unsigned long)loongarch_wakeup_start; #endif return 0UL; diff --git a/arch/loongarch/include/asm/asmmacro.h b/arch/loongarch/include/asm/asmmacro.h index c51a1b43acb4458da6bddb6a5952b3448d036c4b..79e1d53fea89cb998f973ff557d20fb845968128 100644 --- a/arch/loongarch/include/asm/asmmacro.h +++ b/arch/loongarch/include/asm/asmmacro.h @@ -270,6 +270,399 @@ fld.d $f31, \tmp, THREAD_FPR31 - THREAD_FPR0 .endm + .macro lsx_save_data thread tmp + li.w \tmp, THREAD_FPR0 + PTR_ADD \tmp, \thread, \tmp + vst $vr0, \tmp, THREAD_FPR0 - THREAD_FPR0 + vst $vr1, \tmp, THREAD_FPR1 - THREAD_FPR0 + vst $vr2, \tmp, THREAD_FPR2 - THREAD_FPR0 + vst $vr3, \tmp, THREAD_FPR3 - THREAD_FPR0 + vst $vr4, \tmp, THREAD_FPR4 - THREAD_FPR0 + vst $vr5, \tmp, THREAD_FPR5 - THREAD_FPR0 + vst $vr6, \tmp, THREAD_FPR6 - THREAD_FPR0 + vst $vr7, \tmp, THREAD_FPR7 - THREAD_FPR0 + vst $vr8, \tmp, THREAD_FPR8 - THREAD_FPR0 + vst $vr9, \tmp, THREAD_FPR9 - THREAD_FPR0 + vst $vr10, \tmp, THREAD_FPR10 - THREAD_FPR0 + vst $vr11, \tmp, THREAD_FPR11 - THREAD_FPR0 + vst $vr12, \tmp, THREAD_FPR12 - THREAD_FPR0 + vst $vr13, \tmp, THREAD_FPR13 - THREAD_FPR0 + vst $vr14, \tmp, THREAD_FPR14 - THREAD_FPR0 + vst $vr15, \tmp, THREAD_FPR15 - THREAD_FPR0 + vst $vr16, \tmp, THREAD_FPR16 - THREAD_FPR0 + vst $vr17, \tmp, THREAD_FPR17 - THREAD_FPR0 + vst $vr18, \tmp, THREAD_FPR18 - THREAD_FPR0 + vst $vr19, \tmp, THREAD_FPR19 - THREAD_FPR0 + vst $vr20, \tmp, THREAD_FPR20 - THREAD_FPR0 + vst $vr21, \tmp, THREAD_FPR21 - THREAD_FPR0 + vst $vr22, \tmp, THREAD_FPR22 - THREAD_FPR0 + vst $vr23, \tmp, THREAD_FPR23 - THREAD_FPR0 + vst $vr24, \tmp, THREAD_FPR24 - THREAD_FPR0 + vst $vr25, \tmp, THREAD_FPR25 - THREAD_FPR0 + vst $vr26, \tmp, THREAD_FPR26 - THREAD_FPR0 + vst $vr27, \tmp, THREAD_FPR27 - THREAD_FPR0 + vst $vr28, \tmp, THREAD_FPR28 - THREAD_FPR0 + vst $vr29, \tmp, THREAD_FPR29 - THREAD_FPR0 + vst $vr30, \tmp, THREAD_FPR30 - THREAD_FPR0 + vst $vr31, \tmp, THREAD_FPR31 - THREAD_FPR0 + .endm + + .macro lsx_restore_data thread tmp + li.w \tmp, THREAD_FPR0 + PTR_ADD \tmp, \thread, \tmp + vld $vr0, \tmp, THREAD_FPR0 - THREAD_FPR0 + vld $vr1, \tmp, THREAD_FPR1 - THREAD_FPR0 + vld $vr2, \tmp, THREAD_FPR2 - THREAD_FPR0 + vld $vr3, \tmp, THREAD_FPR3 - THREAD_FPR0 + vld $vr4, \tmp, THREAD_FPR4 - THREAD_FPR0 + vld $vr5, \tmp, THREAD_FPR5 - THREAD_FPR0 + vld $vr6, \tmp, THREAD_FPR6 - THREAD_FPR0 + vld $vr7, \tmp, THREAD_FPR7 - THREAD_FPR0 + vld $vr8, \tmp, THREAD_FPR8 - THREAD_FPR0 + vld $vr9, \tmp, THREAD_FPR9 - THREAD_FPR0 + vld $vr10, \tmp, THREAD_FPR10 - THREAD_FPR0 + vld $vr11, \tmp, THREAD_FPR11 - THREAD_FPR0 + vld $vr12, \tmp, THREAD_FPR12 - THREAD_FPR0 + vld $vr13, \tmp, THREAD_FPR13 - THREAD_FPR0 + vld $vr14, \tmp, THREAD_FPR14 - THREAD_FPR0 + vld $vr15, \tmp, THREAD_FPR15 - THREAD_FPR0 + vld $vr16, \tmp, THREAD_FPR16 - THREAD_FPR0 + vld $vr17, \tmp, THREAD_FPR17 - THREAD_FPR0 + vld $vr18, \tmp, THREAD_FPR18 - THREAD_FPR0 + vld $vr19, \tmp, THREAD_FPR19 - THREAD_FPR0 + vld $vr20, \tmp, THREAD_FPR20 - THREAD_FPR0 + vld $vr21, \tmp, THREAD_FPR21 - THREAD_FPR0 + vld $vr22, \tmp, THREAD_FPR22 - THREAD_FPR0 + vld $vr23, \tmp, THREAD_FPR23 - THREAD_FPR0 + vld $vr24, \tmp, THREAD_FPR24 - THREAD_FPR0 + vld $vr25, \tmp, THREAD_FPR25 - THREAD_FPR0 + vld $vr26, \tmp, THREAD_FPR26 - THREAD_FPR0 + vld $vr27, \tmp, THREAD_FPR27 - THREAD_FPR0 + vld $vr28, \tmp, THREAD_FPR28 - THREAD_FPR0 + vld $vr29, \tmp, THREAD_FPR29 - THREAD_FPR0 + vld $vr30, \tmp, THREAD_FPR30 - THREAD_FPR0 + vld $vr31, \tmp, THREAD_FPR31 - THREAD_FPR0 + .endm + + .macro lsx_save_all thread tmp0 tmp1 + fpu_save_cc \thread, \tmp0, \tmp1 + fpu_save_csr \thread, \tmp0 + lsx_save_data \thread, \tmp0 + .endm + + .macro lsx_restore_all thread tmp0 tmp1 + lsx_restore_data \thread, \tmp0 + fpu_restore_cc \thread, \tmp0, \tmp1 + fpu_restore_csr \thread, \tmp0 + .endm + + .macro lsx_save_upper vd base tmp off + vpickve2gr.d \tmp, \vd, 1 + st.d \tmp, \base, (\off+8) + .endm + + .macro lsx_save_all_upper thread base tmp + li.w \tmp, THREAD_FPR0 + PTR_ADD \base, \thread, \tmp + lsx_save_upper $vr0, \base, \tmp, (THREAD_FPR0-THREAD_FPR0) + lsx_save_upper $vr1, \base, \tmp, (THREAD_FPR1-THREAD_FPR0) + lsx_save_upper $vr2, \base, \tmp, (THREAD_FPR2-THREAD_FPR0) + lsx_save_upper $vr3, \base, \tmp, (THREAD_FPR3-THREAD_FPR0) + lsx_save_upper $vr4, \base, \tmp, (THREAD_FPR4-THREAD_FPR0) + lsx_save_upper $vr5, \base, \tmp, (THREAD_FPR5-THREAD_FPR0) + lsx_save_upper $vr6, \base, \tmp, (THREAD_FPR6-THREAD_FPR0) + lsx_save_upper $vr7, \base, \tmp, (THREAD_FPR7-THREAD_FPR0) + lsx_save_upper $vr8, \base, \tmp, (THREAD_FPR8-THREAD_FPR0) + lsx_save_upper $vr9, \base, \tmp, (THREAD_FPR9-THREAD_FPR0) + lsx_save_upper $vr10, \base, \tmp, (THREAD_FPR10-THREAD_FPR0) + lsx_save_upper $vr11, \base, \tmp, (THREAD_FPR11-THREAD_FPR0) + lsx_save_upper $vr12, \base, \tmp, (THREAD_FPR12-THREAD_FPR0) + lsx_save_upper $vr13, \base, \tmp, (THREAD_FPR13-THREAD_FPR0) + lsx_save_upper $vr14, \base, \tmp, (THREAD_FPR14-THREAD_FPR0) + lsx_save_upper $vr15, \base, \tmp, (THREAD_FPR15-THREAD_FPR0) + lsx_save_upper $vr16, \base, \tmp, (THREAD_FPR16-THREAD_FPR0) + lsx_save_upper $vr17, \base, \tmp, (THREAD_FPR17-THREAD_FPR0) + lsx_save_upper $vr18, \base, \tmp, (THREAD_FPR18-THREAD_FPR0) + lsx_save_upper $vr19, \base, \tmp, (THREAD_FPR19-THREAD_FPR0) + lsx_save_upper $vr20, \base, \tmp, (THREAD_FPR20-THREAD_FPR0) + lsx_save_upper $vr21, \base, \tmp, (THREAD_FPR21-THREAD_FPR0) + lsx_save_upper $vr22, \base, \tmp, (THREAD_FPR22-THREAD_FPR0) + lsx_save_upper $vr23, \base, \tmp, (THREAD_FPR23-THREAD_FPR0) + lsx_save_upper $vr24, \base, \tmp, (THREAD_FPR24-THREAD_FPR0) + lsx_save_upper $vr25, \base, \tmp, (THREAD_FPR25-THREAD_FPR0) + lsx_save_upper $vr26, \base, \tmp, (THREAD_FPR26-THREAD_FPR0) + lsx_save_upper $vr27, \base, \tmp, (THREAD_FPR27-THREAD_FPR0) + lsx_save_upper $vr28, \base, \tmp, (THREAD_FPR28-THREAD_FPR0) + lsx_save_upper $vr29, \base, \tmp, (THREAD_FPR29-THREAD_FPR0) + lsx_save_upper $vr30, \base, \tmp, (THREAD_FPR30-THREAD_FPR0) + lsx_save_upper $vr31, \base, \tmp, (THREAD_FPR31-THREAD_FPR0) + .endm + + .macro lsx_restore_upper vd base tmp off + ld.d \tmp, \base, (\off+8) + vinsgr2vr.d \vd, \tmp, 1 + .endm + + .macro lsx_restore_all_upper thread base tmp + li.w \tmp, THREAD_FPR0 + PTR_ADD \base, \thread, \tmp + lsx_restore_upper $vr0, \base, \tmp, (THREAD_FPR0-THREAD_FPR0) + lsx_restore_upper $vr1, \base, \tmp, (THREAD_FPR1-THREAD_FPR0) + lsx_restore_upper $vr2, \base, \tmp, (THREAD_FPR2-THREAD_FPR0) + lsx_restore_upper $vr3, \base, \tmp, (THREAD_FPR3-THREAD_FPR0) + lsx_restore_upper $vr4, \base, \tmp, (THREAD_FPR4-THREAD_FPR0) + lsx_restore_upper $vr5, \base, \tmp, (THREAD_FPR5-THREAD_FPR0) + lsx_restore_upper $vr6, \base, \tmp, (THREAD_FPR6-THREAD_FPR0) + lsx_restore_upper $vr7, \base, \tmp, (THREAD_FPR7-THREAD_FPR0) + lsx_restore_upper $vr8, \base, \tmp, (THREAD_FPR8-THREAD_FPR0) + lsx_restore_upper $vr9, \base, \tmp, (THREAD_FPR9-THREAD_FPR0) + lsx_restore_upper $vr10, \base, \tmp, (THREAD_FPR10-THREAD_FPR0) + lsx_restore_upper $vr11, \base, \tmp, (THREAD_FPR11-THREAD_FPR0) + lsx_restore_upper $vr12, \base, \tmp, (THREAD_FPR12-THREAD_FPR0) + lsx_restore_upper $vr13, \base, \tmp, (THREAD_FPR13-THREAD_FPR0) + lsx_restore_upper $vr14, \base, \tmp, (THREAD_FPR14-THREAD_FPR0) + lsx_restore_upper $vr15, \base, \tmp, (THREAD_FPR15-THREAD_FPR0) + lsx_restore_upper $vr16, \base, \tmp, (THREAD_FPR16-THREAD_FPR0) + lsx_restore_upper $vr17, \base, \tmp, (THREAD_FPR17-THREAD_FPR0) + lsx_restore_upper $vr18, \base, \tmp, (THREAD_FPR18-THREAD_FPR0) + lsx_restore_upper $vr19, \base, \tmp, (THREAD_FPR19-THREAD_FPR0) + lsx_restore_upper $vr20, \base, \tmp, (THREAD_FPR20-THREAD_FPR0) + lsx_restore_upper $vr21, \base, \tmp, (THREAD_FPR21-THREAD_FPR0) + lsx_restore_upper $vr22, \base, \tmp, (THREAD_FPR22-THREAD_FPR0) + lsx_restore_upper $vr23, \base, \tmp, (THREAD_FPR23-THREAD_FPR0) + lsx_restore_upper $vr24, \base, \tmp, (THREAD_FPR24-THREAD_FPR0) + lsx_restore_upper $vr25, \base, \tmp, (THREAD_FPR25-THREAD_FPR0) + lsx_restore_upper $vr26, \base, \tmp, (THREAD_FPR26-THREAD_FPR0) + lsx_restore_upper $vr27, \base, \tmp, (THREAD_FPR27-THREAD_FPR0) + lsx_restore_upper $vr28, \base, \tmp, (THREAD_FPR28-THREAD_FPR0) + lsx_restore_upper $vr29, \base, \tmp, (THREAD_FPR29-THREAD_FPR0) + lsx_restore_upper $vr30, \base, \tmp, (THREAD_FPR30-THREAD_FPR0) + lsx_restore_upper $vr31, \base, \tmp, (THREAD_FPR31-THREAD_FPR0) + .endm + + .macro lsx_init_upper vd tmp + vinsgr2vr.d \vd, \tmp, 1 + .endm + + .macro lsx_init_all_upper tmp + not \tmp, zero + lsx_init_upper $vr0 \tmp + lsx_init_upper $vr1 \tmp + lsx_init_upper $vr2 \tmp + lsx_init_upper $vr3 \tmp + lsx_init_upper $vr4 \tmp + lsx_init_upper $vr5 \tmp + lsx_init_upper $vr6 \tmp + lsx_init_upper $vr7 \tmp + lsx_init_upper $vr8 \tmp + lsx_init_upper $vr9 \tmp + lsx_init_upper $vr10 \tmp + lsx_init_upper $vr11 \tmp + lsx_init_upper $vr12 \tmp + lsx_init_upper $vr13 \tmp + lsx_init_upper $vr14 \tmp + lsx_init_upper $vr15 \tmp + lsx_init_upper $vr16 \tmp + lsx_init_upper $vr17 \tmp + lsx_init_upper $vr18 \tmp + lsx_init_upper $vr19 \tmp + lsx_init_upper $vr20 \tmp + lsx_init_upper $vr21 \tmp + lsx_init_upper $vr22 \tmp + lsx_init_upper $vr23 \tmp + lsx_init_upper $vr24 \tmp + lsx_init_upper $vr25 \tmp + lsx_init_upper $vr26 \tmp + lsx_init_upper $vr27 \tmp + lsx_init_upper $vr28 \tmp + lsx_init_upper $vr29 \tmp + lsx_init_upper $vr30 \tmp + lsx_init_upper $vr31 \tmp + .endm + + .macro lasx_save_data thread tmp + li.w \tmp, THREAD_FPR0 + PTR_ADD \tmp, \thread, \tmp + xvst $xr0, \tmp, THREAD_FPR0 - THREAD_FPR0 + xvst $xr1, \tmp, THREAD_FPR1 - THREAD_FPR0 + xvst $xr2, \tmp, THREAD_FPR2 - THREAD_FPR0 + xvst $xr3, \tmp, THREAD_FPR3 - THREAD_FPR0 + xvst $xr4, \tmp, THREAD_FPR4 - THREAD_FPR0 + xvst $xr5, \tmp, THREAD_FPR5 - THREAD_FPR0 + xvst $xr6, \tmp, THREAD_FPR6 - THREAD_FPR0 + xvst $xr7, \tmp, THREAD_FPR7 - THREAD_FPR0 + xvst $xr8, \tmp, THREAD_FPR8 - THREAD_FPR0 + xvst $xr9, \tmp, THREAD_FPR9 - THREAD_FPR0 + xvst $xr10, \tmp, THREAD_FPR10 - THREAD_FPR0 + xvst $xr11, \tmp, THREAD_FPR11 - THREAD_FPR0 + xvst $xr12, \tmp, THREAD_FPR12 - THREAD_FPR0 + xvst $xr13, \tmp, THREAD_FPR13 - THREAD_FPR0 + xvst $xr14, \tmp, THREAD_FPR14 - THREAD_FPR0 + xvst $xr15, \tmp, THREAD_FPR15 - THREAD_FPR0 + xvst $xr16, \tmp, THREAD_FPR16 - THREAD_FPR0 + xvst $xr17, \tmp, THREAD_FPR17 - THREAD_FPR0 + xvst $xr18, \tmp, THREAD_FPR18 - THREAD_FPR0 + xvst $xr19, \tmp, THREAD_FPR19 - THREAD_FPR0 + xvst $xr20, \tmp, THREAD_FPR20 - THREAD_FPR0 + xvst $xr21, \tmp, THREAD_FPR21 - THREAD_FPR0 + xvst $xr22, \tmp, THREAD_FPR22 - THREAD_FPR0 + xvst $xr23, \tmp, THREAD_FPR23 - THREAD_FPR0 + xvst $xr24, \tmp, THREAD_FPR24 - THREAD_FPR0 + xvst $xr25, \tmp, THREAD_FPR25 - THREAD_FPR0 + xvst $xr26, \tmp, THREAD_FPR26 - THREAD_FPR0 + xvst $xr27, \tmp, THREAD_FPR27 - THREAD_FPR0 + xvst $xr28, \tmp, THREAD_FPR28 - THREAD_FPR0 + xvst $xr29, \tmp, THREAD_FPR29 - THREAD_FPR0 + xvst $xr30, \tmp, THREAD_FPR30 - THREAD_FPR0 + xvst $xr31, \tmp, THREAD_FPR31 - THREAD_FPR0 + .endm + + .macro lasx_restore_data thread tmp + li.w \tmp, THREAD_FPR0 + PTR_ADD \tmp, \thread, \tmp + xvld $xr0, \tmp, THREAD_FPR0 - THREAD_FPR0 + xvld $xr1, \tmp, THREAD_FPR1 - THREAD_FPR0 + xvld $xr2, \tmp, THREAD_FPR2 - THREAD_FPR0 + xvld $xr3, \tmp, THREAD_FPR3 - THREAD_FPR0 + xvld $xr4, \tmp, THREAD_FPR4 - THREAD_FPR0 + xvld $xr5, \tmp, THREAD_FPR5 - THREAD_FPR0 + xvld $xr6, \tmp, THREAD_FPR6 - THREAD_FPR0 + xvld $xr7, \tmp, THREAD_FPR7 - THREAD_FPR0 + xvld $xr8, \tmp, THREAD_FPR8 - THREAD_FPR0 + xvld $xr9, \tmp, THREAD_FPR9 - THREAD_FPR0 + xvld $xr10, \tmp, THREAD_FPR10 - THREAD_FPR0 + xvld $xr11, \tmp, THREAD_FPR11 - THREAD_FPR0 + xvld $xr12, \tmp, THREAD_FPR12 - THREAD_FPR0 + xvld $xr13, \tmp, THREAD_FPR13 - THREAD_FPR0 + xvld $xr14, \tmp, THREAD_FPR14 - THREAD_FPR0 + xvld $xr15, \tmp, THREAD_FPR15 - THREAD_FPR0 + xvld $xr16, \tmp, THREAD_FPR16 - THREAD_FPR0 + xvld $xr17, \tmp, THREAD_FPR17 - THREAD_FPR0 + xvld $xr18, \tmp, THREAD_FPR18 - THREAD_FPR0 + xvld $xr19, \tmp, THREAD_FPR19 - THREAD_FPR0 + xvld $xr20, \tmp, THREAD_FPR20 - THREAD_FPR0 + xvld $xr21, \tmp, THREAD_FPR21 - THREAD_FPR0 + xvld $xr22, \tmp, THREAD_FPR22 - THREAD_FPR0 + xvld $xr23, \tmp, THREAD_FPR23 - THREAD_FPR0 + xvld $xr24, \tmp, THREAD_FPR24 - THREAD_FPR0 + xvld $xr25, \tmp, THREAD_FPR25 - THREAD_FPR0 + xvld $xr26, \tmp, THREAD_FPR26 - THREAD_FPR0 + xvld $xr27, \tmp, THREAD_FPR27 - THREAD_FPR0 + xvld $xr28, \tmp, THREAD_FPR28 - THREAD_FPR0 + xvld $xr29, \tmp, THREAD_FPR29 - THREAD_FPR0 + xvld $xr30, \tmp, THREAD_FPR30 - THREAD_FPR0 + xvld $xr31, \tmp, THREAD_FPR31 - THREAD_FPR0 + .endm + + .macro lasx_save_all thread tmp0 tmp1 + fpu_save_cc \thread, \tmp0, \tmp1 + fpu_save_csr \thread, \tmp0 + lasx_save_data \thread, \tmp0 + .endm + + .macro lasx_restore_all thread tmp0 tmp1 + lasx_restore_data \thread, \tmp0 + fpu_restore_cc \thread, \tmp0, \tmp1 + fpu_restore_csr \thread, \tmp0 + .endm + + .macro lasx_save_upper xd base tmp off + /* Nothing */ + .endm + + .macro lasx_save_all_upper thread base tmp + /* Nothing */ + .endm + + .macro lasx_restore_upper xd base tmp0 tmp1 off + vld \tmp0, \base, (\off+16) + xvpermi.q \xd, \tmp1, 0x2 + .endm + + .macro lasx_restore_all_upper thread base tmp + li.w \tmp, THREAD_FPR0 + PTR_ADD \base, \thread, \tmp + /* Save $vr31 ($xr31 lower bits) with xvpickve2gr */ + xvpickve2gr.d $r17, $xr31, 0 + xvpickve2gr.d $r18, $xr31, 1 + lasx_restore_upper $xr0, \base, $vr31, $xr31, (THREAD_FPR0-THREAD_FPR0) + lasx_restore_upper $xr1, \base, $vr31, $xr31, (THREAD_FPR1-THREAD_FPR0) + lasx_restore_upper $xr2, \base, $vr31, $xr31, (THREAD_FPR2-THREAD_FPR0) + lasx_restore_upper $xr3, \base, $vr31, $xr31, (THREAD_FPR3-THREAD_FPR0) + lasx_restore_upper $xr4, \base, $vr31, $xr31, (THREAD_FPR4-THREAD_FPR0) + lasx_restore_upper $xr5, \base, $vr31, $xr31, (THREAD_FPR5-THREAD_FPR0) + lasx_restore_upper $xr6, \base, $vr31, $xr31, (THREAD_FPR6-THREAD_FPR0) + lasx_restore_upper $xr7, \base, $vr31, $xr31, (THREAD_FPR7-THREAD_FPR0) + lasx_restore_upper $xr8, \base, $vr31, $xr31, (THREAD_FPR8-THREAD_FPR0) + lasx_restore_upper $xr9, \base, $vr31, $xr31, (THREAD_FPR9-THREAD_FPR0) + lasx_restore_upper $xr10, \base, $vr31, $xr31, (THREAD_FPR10-THREAD_FPR0) + lasx_restore_upper $xr11, \base, $vr31, $xr31, (THREAD_FPR11-THREAD_FPR0) + lasx_restore_upper $xr12, \base, $vr31, $xr31, (THREAD_FPR12-THREAD_FPR0) + lasx_restore_upper $xr13, \base, $vr31, $xr31, (THREAD_FPR13-THREAD_FPR0) + lasx_restore_upper $xr14, \base, $vr31, $xr31, (THREAD_FPR14-THREAD_FPR0) + lasx_restore_upper $xr15, \base, $vr31, $xr31, (THREAD_FPR15-THREAD_FPR0) + lasx_restore_upper $xr16, \base, $vr31, $xr31, (THREAD_FPR16-THREAD_FPR0) + lasx_restore_upper $xr17, \base, $vr31, $xr31, (THREAD_FPR17-THREAD_FPR0) + lasx_restore_upper $xr18, \base, $vr31, $xr31, (THREAD_FPR18-THREAD_FPR0) + lasx_restore_upper $xr19, \base, $vr31, $xr31, (THREAD_FPR19-THREAD_FPR0) + lasx_restore_upper $xr20, \base, $vr31, $xr31, (THREAD_FPR20-THREAD_FPR0) + lasx_restore_upper $xr21, \base, $vr31, $xr31, (THREAD_FPR21-THREAD_FPR0) + lasx_restore_upper $xr22, \base, $vr31, $xr31, (THREAD_FPR22-THREAD_FPR0) + lasx_restore_upper $xr23, \base, $vr31, $xr31, (THREAD_FPR23-THREAD_FPR0) + lasx_restore_upper $xr24, \base, $vr31, $xr31, (THREAD_FPR24-THREAD_FPR0) + lasx_restore_upper $xr25, \base, $vr31, $xr31, (THREAD_FPR25-THREAD_FPR0) + lasx_restore_upper $xr26, \base, $vr31, $xr31, (THREAD_FPR26-THREAD_FPR0) + lasx_restore_upper $xr27, \base, $vr31, $xr31, (THREAD_FPR27-THREAD_FPR0) + lasx_restore_upper $xr28, \base, $vr31, $xr31, (THREAD_FPR28-THREAD_FPR0) + lasx_restore_upper $xr29, \base, $vr31, $xr31, (THREAD_FPR29-THREAD_FPR0) + lasx_restore_upper $xr30, \base, $vr31, $xr31, (THREAD_FPR30-THREAD_FPR0) + lasx_restore_upper $xr31, \base, $vr31, $xr31, (THREAD_FPR31-THREAD_FPR0) + /* Restore $vr31 ($xr31 lower bits) with xvinsgr2vr */ + xvinsgr2vr.d $xr31, $r17, 0 + xvinsgr2vr.d $xr31, $r18, 1 + .endm + + .macro lasx_init_upper xd tmp + xvinsgr2vr.d \xd, \tmp, 2 + xvinsgr2vr.d \xd, \tmp, 3 + .endm + + .macro lasx_init_all_upper tmp + not \tmp, zero + lasx_init_upper $xr0 \tmp + lasx_init_upper $xr1 \tmp + lasx_init_upper $xr2 \tmp + lasx_init_upper $xr3 \tmp + lasx_init_upper $xr4 \tmp + lasx_init_upper $xr5 \tmp + lasx_init_upper $xr6 \tmp + lasx_init_upper $xr7 \tmp + lasx_init_upper $xr8 \tmp + lasx_init_upper $xr9 \tmp + lasx_init_upper $xr10 \tmp + lasx_init_upper $xr11 \tmp + lasx_init_upper $xr12 \tmp + lasx_init_upper $xr13 \tmp + lasx_init_upper $xr14 \tmp + lasx_init_upper $xr15 \tmp + lasx_init_upper $xr16 \tmp + lasx_init_upper $xr17 \tmp + lasx_init_upper $xr18 \tmp + lasx_init_upper $xr19 \tmp + lasx_init_upper $xr20 \tmp + lasx_init_upper $xr21 \tmp + lasx_init_upper $xr22 \tmp + lasx_init_upper $xr23 \tmp + lasx_init_upper $xr24 \tmp + lasx_init_upper $xr25 \tmp + lasx_init_upper $xr26 \tmp + lasx_init_upper $xr27 \tmp + lasx_init_upper $xr28 \tmp + lasx_init_upper $xr29 \tmp + lasx_init_upper $xr30 \tmp + lasx_init_upper $xr31 \tmp + .endm + .macro not dst src nor \dst, \src, zero .endm diff --git a/arch/loongarch/include/asm/atomic.h b/arch/loongarch/include/asm/atomic.h index 6b9aca9ab6e9f284e64d57d1d43f61b97726c166..e27f0c72d3242b58aec094d40199ab30160583a5 100644 --- a/arch/loongarch/include/asm/atomic.h +++ b/arch/loongarch/include/asm/atomic.h @@ -29,21 +29,7 @@ #define ATOMIC_INIT(i) { (i) } -/* - * arch_atomic_read - read atomic variable - * @v: pointer of type atomic_t - * - * Atomically reads the value of @v. - */ #define arch_atomic_read(v) READ_ONCE((v)->counter) - -/* - * arch_atomic_set - set atomic variable - * @v: pointer of type atomic_t - * @i: required value - * - * Atomically sets the value of @v to @i. - */ #define arch_atomic_set(v, i) WRITE_ONCE((v)->counter, (i)) #define ATOMIC_OP(op, I, asm_op) \ @@ -139,14 +125,6 @@ static inline int arch_atomic_fetch_add_unless(atomic_t *v, int a, int u) } #define arch_atomic_fetch_add_unless arch_atomic_fetch_add_unless -/* - * arch_atomic_sub_if_positive - conditionally subtract integer from atomic variable - * @i: integer value to subtract - * @v: pointer of type atomic_t - * - * Atomically test @v and subtract @i if @v is greater or equal than @i. - * The function returns the old value of @v minus @i. - */ static inline int arch_atomic_sub_if_positive(int i, atomic_t *v) { int result; @@ -181,31 +159,13 @@ static inline int arch_atomic_sub_if_positive(int i, atomic_t *v) return result; } -#define arch_atomic_cmpxchg(v, o, n) (arch_cmpxchg(&((v)->counter), (o), (n))) -#define arch_atomic_xchg(v, new) (arch_xchg(&((v)->counter), (new))) - -/* - * arch_atomic_dec_if_positive - decrement by 1 if old value positive - * @v: pointer of type atomic_t - */ #define arch_atomic_dec_if_positive(v) arch_atomic_sub_if_positive(1, v) #ifdef CONFIG_64BIT #define ATOMIC64_INIT(i) { (i) } -/* - * arch_atomic64_read - read atomic variable - * @v: pointer of type atomic64_t - * - */ #define arch_atomic64_read(v) READ_ONCE((v)->counter) - -/* - * arch_atomic64_set - set atomic variable - * @v: pointer of type atomic64_t - * @i: required value - */ #define arch_atomic64_set(v, i) WRITE_ONCE((v)->counter, (i)) #define ATOMIC64_OP(op, I, asm_op) \ @@ -300,14 +260,6 @@ static inline long arch_atomic64_fetch_add_unless(atomic64_t *v, long a, long u) } #define arch_atomic64_fetch_add_unless arch_atomic64_fetch_add_unless -/* - * arch_atomic64_sub_if_positive - conditionally subtract integer from atomic variable - * @i: integer value to subtract - * @v: pointer of type atomic64_t - * - * Atomically test @v and subtract @i if @v is greater or equal than @i. - * The function returns the old value of @v minus @i. - */ static inline long arch_atomic64_sub_if_positive(long i, atomic64_t *v) { long result; @@ -342,14 +294,6 @@ static inline long arch_atomic64_sub_if_positive(long i, atomic64_t *v) return result; } -#define arch_atomic64_cmpxchg(v, o, n) \ - ((__typeof__((v)->counter))arch_cmpxchg(&((v)->counter), (o), (n))) -#define arch_atomic64_xchg(v, new) (arch_xchg(&((v)->counter), (new))) - -/* - * arch_atomic64_dec_if_positive - decrement by 1 if old value positive - * @v: pointer of type atomic64_t - */ #define arch_atomic64_dec_if_positive(v) arch_atomic64_sub_if_positive(1, v) #endif /* CONFIG_64BIT */ diff --git a/arch/loongarch/include/asm/barrier.h b/arch/loongarch/include/asm/barrier.h index cda9776758544e5e72f8f42b9bf4862a67ce8a1a..4b663f19770611b7cb5d1d0aa88a4a4de1d9b48a 100644 --- a/arch/loongarch/include/asm/barrier.h +++ b/arch/loongarch/include/asm/barrier.h @@ -5,27 +5,56 @@ #ifndef __ASM_BARRIER_H #define __ASM_BARRIER_H -#define __sync() __asm__ __volatile__("dbar 0" : : : "memory") +/* + * Hint encoding: + * + * Bit4: ordering or completion (0: completion, 1: ordering) + * Bit3: barrier for previous read (0: true, 1: false) + * Bit2: barrier for previous write (0: true, 1: false) + * Bit1: barrier for succeeding read (0: true, 1: false) + * Bit0: barrier for succeeding write (0: true, 1: false) + * + * Hint 0x700: barrier for "read after read" from the same address + */ + +#define DBAR(hint) __asm__ __volatile__("dbar %0 " : : "I"(hint) : "memory") + +#define crwrw 0b00000 +#define cr_r_ 0b00101 +#define c_w_w 0b01010 -#define fast_wmb() __sync() -#define fast_rmb() __sync() -#define fast_mb() __sync() -#define fast_iob() __sync() -#define wbflush() __sync() +#define orwrw 0b10000 +#define or_r_ 0b10101 +#define o_w_w 0b11010 -#define wmb() fast_wmb() -#define rmb() fast_rmb() -#define mb() fast_mb() -#define iob() fast_iob() +#define orw_w 0b10010 +#define or_rw 0b10100 -#define __smp_mb() __asm__ __volatile__("dbar 0" : : : "memory") -#define __smp_rmb() __asm__ __volatile__("dbar 0" : : : "memory") -#define __smp_wmb() __asm__ __volatile__("dbar 0" : : : "memory") +#define c_sync() DBAR(crwrw) +#define c_rsync() DBAR(cr_r_) +#define c_wsync() DBAR(c_w_w) + +#define o_sync() DBAR(orwrw) +#define o_rsync() DBAR(or_r_) +#define o_wsync() DBAR(o_w_w) + +#define ldacq_mb() DBAR(or_rw) +#define strel_mb() DBAR(orw_w) + +#define mb() c_sync() +#define rmb() c_rsync() +#define wmb() c_wsync() +#define iob() c_sync() +#define wbflush() c_sync() + +#define __smp_mb() o_sync() +#define __smp_rmb() o_rsync() +#define __smp_wmb() o_wsync() #ifdef CONFIG_SMP -#define __WEAK_LLSC_MB " dbar 0 \n" +#define __WEAK_LLSC_MB " dbar 0x700 \n" #else -#define __WEAK_LLSC_MB " \n" +#define __WEAK_LLSC_MB " \n" #endif #define __smp_mb__before_atomic() barrier() @@ -59,68 +88,19 @@ static inline unsigned long array_index_mask_nospec(unsigned long index, return mask; } -#define __smp_load_acquire(p) \ -({ \ - union { typeof(*p) __val; char __c[1]; } __u; \ - unsigned long __tmp = 0; \ - compiletime_assert_atomic_type(*p); \ - switch (sizeof(*p)) { \ - case 1: \ - *(__u8 *)__u.__c = *(volatile __u8 *)p; \ - __smp_mb(); \ - break; \ - case 2: \ - *(__u16 *)__u.__c = *(volatile __u16 *)p; \ - __smp_mb(); \ - break; \ - case 4: \ - __asm__ __volatile__( \ - "amor_db.w %[val], %[tmp], %[mem] \n" \ - : [val] "=&r" (*(__u32 *)__u.__c) \ - : [mem] "ZB" (*(u32 *) p), [tmp] "r" (__tmp) \ - : "memory"); \ - break; \ - case 8: \ - __asm__ __volatile__( \ - "amor_db.d %[val], %[tmp], %[mem] \n" \ - : [val] "=&r" (*(__u64 *)__u.__c) \ - : [mem] "ZB" (*(u64 *) p), [tmp] "r" (__tmp) \ - : "memory"); \ - break; \ - } \ - (typeof(*p))__u.__val; \ +#define __smp_load_acquire(p) \ +({ \ + typeof(*p) ___p1 = READ_ONCE(*p); \ + compiletime_assert_atomic_type(*p); \ + ldacq_mb(); \ + ___p1; \ }) -#define __smp_store_release(p, v) \ -do { \ - union { typeof(*p) __val; char __c[1]; } __u = \ - { .__val = (__force typeof(*p)) (v) }; \ - unsigned long __tmp; \ - compiletime_assert_atomic_type(*p); \ - switch (sizeof(*p)) { \ - case 1: \ - __smp_mb(); \ - *(volatile __u8 *)p = *(__u8 *)__u.__c; \ - break; \ - case 2: \ - __smp_mb(); \ - *(volatile __u16 *)p = *(__u16 *)__u.__c; \ - break; \ - case 4: \ - __asm__ __volatile__( \ - "amswap_db.w %[tmp], %[val], %[mem] \n" \ - : [mem] "+ZB" (*(u32 *)p), [tmp] "=&r" (__tmp) \ - : [val] "r" (*(__u32 *)__u.__c) \ - : ); \ - break; \ - case 8: \ - __asm__ __volatile__( \ - "amswap_db.d %[tmp], %[val], %[mem] \n" \ - : [mem] "+ZB" (*(u64 *)p), [tmp] "=&r" (__tmp) \ - : [val] "r" (*(__u64 *)__u.__c) \ - : ); \ - break; \ - } \ +#define __smp_store_release(p, v) \ +do { \ + compiletime_assert_atomic_type(*p); \ + strel_mb(); \ + WRITE_ONCE(*p, v); \ } while (0) #define __smp_store_mb(p, v) \ diff --git a/arch/loongarch/include/asm/bugs.h b/arch/loongarch/include/asm/bugs.h deleted file mode 100644 index 98396535163b34d1468384914a893df8be627707..0000000000000000000000000000000000000000 --- a/arch/loongarch/include/asm/bugs.h +++ /dev/null @@ -1,15 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * This is included by init/main.c to check for architecture-dependent bugs. - * - * Copyright (C) 2020-2022 Loongson Technology Corporation Limited - */ -#ifndef _ASM_BUGS_H -#define _ASM_BUGS_H - -#include -#include - -extern void check_bugs(void); - -#endif /* _ASM_BUGS_H */ diff --git a/arch/loongarch/include/asm/cpu-features.h b/arch/loongarch/include/asm/cpu-features.h index f6177f133477670edc2b5f955d379101e8147032..2eafe6a6aca8189c88617c18da45c373294a6aa8 100644 --- a/arch/loongarch/include/asm/cpu-features.h +++ b/arch/loongarch/include/asm/cpu-features.h @@ -64,6 +64,6 @@ #define cpu_has_eiodecode cpu_opt(LOONGARCH_CPU_EIODECODE) #define cpu_has_guestid cpu_opt(LOONGARCH_CPU_GUESTID) #define cpu_has_hypervisor cpu_opt(LOONGARCH_CPU_HYPERVISOR) - +#define cpu_has_ptw cpu_opt(LOONGARCH_CPU_PTW) #endif /* __ASM_CPU_FEATURES_H */ diff --git a/arch/loongarch/include/asm/cpu-info.h b/arch/loongarch/include/asm/cpu-info.h index cd73a6f57fe37c13600aa3e1b7a6f8ea1b087302..900589cb159de4e5997358443c5b5e3e50f92239 100644 --- a/arch/loongarch/include/asm/cpu-info.h +++ b/arch/loongarch/include/asm/cpu-info.h @@ -54,6 +54,7 @@ struct cpuinfo_loongarch { struct cache_desc cache_leaves[CACHE_LEAVES_MAX]; int core; /* physical core number in package */ int package;/* physical package number */ + int global_id; /* physical global thread number */ int vabits; /* Virtual Address size in bits */ int pabits; /* Physical Address size in bits */ unsigned int ksave_mask; /* Usable KSave mask. */ diff --git a/arch/loongarch/include/asm/cpu.h b/arch/loongarch/include/asm/cpu.h index 88773d849e332f08047460efecf97fb429976505..48b9f7168bcca03f92a63f891a346f88055b7bfc 100644 --- a/arch/loongarch/include/asm/cpu.h +++ b/arch/loongarch/include/asm/cpu.h @@ -98,6 +98,7 @@ enum cpu_type_enum { #define CPU_FEATURE_EIODECODE 23 /* CPU has EXTIOI interrupt pin decode mode */ #define CPU_FEATURE_GUESTID 24 /* CPU has GuestID feature */ #define CPU_FEATURE_HYPERVISOR 25 /* CPU has hypervisor (running in VM) */ +#define CPU_FEATURE_PTW 26 /* CPU has hardware page table walker */ #define LOONGARCH_CPU_CPUCFG BIT_ULL(CPU_FEATURE_CPUCFG) #define LOONGARCH_CPU_LAM BIT_ULL(CPU_FEATURE_LAM) @@ -125,5 +126,6 @@ enum cpu_type_enum { #define LOONGARCH_CPU_EIODECODE BIT_ULL(CPU_FEATURE_EIODECODE) #define LOONGARCH_CPU_GUESTID BIT_ULL(CPU_FEATURE_GUESTID) #define LOONGARCH_CPU_HYPERVISOR BIT_ULL(CPU_FEATURE_HYPERVISOR) +#define LOONGARCH_CPU_PTW BIT_ULL(CPU_FEATURE_PTW) #endif /* _ASM_CPU_H */ diff --git a/arch/loongarch/include/asm/fpregdef.h b/arch/loongarch/include/asm/fpregdef.h index b6be527831dd9cc057215b39847470242a23019c..e56610ae859275b9c5a71c91cbf4f1d9f5e2bcba 100644 --- a/arch/loongarch/include/asm/fpregdef.h +++ b/arch/loongarch/include/asm/fpregdef.h @@ -40,6 +40,7 @@ #define fs6 $f30 #define fs7 $f31 +#ifndef CONFIG_AS_HAS_FCSR_CLASS /* * Current binutils expects *GPRs* at FCSR position for the FCSR * operation instructions, so define aliases for those used. @@ -48,5 +49,11 @@ #define fcsr1 $r1 #define fcsr2 $r2 #define fcsr3 $r3 +#else +#define fcsr0 $fcsr0 +#define fcsr1 $fcsr1 +#define fcsr2 $fcsr2 +#define fcsr3 $fcsr3 +#endif #endif /* _ASM_FPREGDEF_H */ diff --git a/arch/loongarch/include/asm/fpu.h b/arch/loongarch/include/asm/fpu.h index 192f8e35d9126bbb40b29bcd6fb18d20b5b22e40..e4193d637f664eecae6d47b8d2bbc15f2b2e3200 100644 --- a/arch/loongarch/include/asm/fpu.h +++ b/arch/loongarch/include/asm/fpu.h @@ -28,6 +28,26 @@ extern void _init_fpu(unsigned int); extern void _save_fp(struct loongarch_fpu *); extern void _restore_fp(struct loongarch_fpu *); +extern void _save_lsx(struct loongarch_fpu *fpu); +extern void _restore_lsx(struct loongarch_fpu *fpu); +extern void _init_lsx_upper(void); +extern void _restore_lsx_upper(struct loongarch_fpu *fpu); + +extern void _save_lasx(struct loongarch_fpu *fpu); +extern void _restore_lasx(struct loongarch_fpu *fpu); +extern void _init_lasx_upper(void); +extern void _restore_lasx_upper(struct loongarch_fpu *fpu); + +static inline void enable_lsx(void); +static inline void disable_lsx(void); +static inline void save_lsx(struct task_struct *t); +static inline void restore_lsx(struct task_struct *t); + +static inline void enable_lasx(void); +static inline void disable_lasx(void); +static inline void save_lasx(struct task_struct *t); +static inline void restore_lasx(struct task_struct *t); + /* * Mask the FCSR Cause bits according to the Enable bits, observing * that Unimplemented is always enabled. @@ -44,6 +64,29 @@ static inline int is_fp_enabled(void) 1 : 0; } +static inline int is_lsx_enabled(void) +{ + if (!cpu_has_lsx) + return 0; + + return (csr_read32(LOONGARCH_CSR_EUEN) & CSR_EUEN_LSXEN) ? + 1 : 0; +} + +static inline int is_lasx_enabled(void) +{ + if (!cpu_has_lasx) + return 0; + + return (csr_read32(LOONGARCH_CSR_EUEN) & CSR_EUEN_LASXEN) ? + 1 : 0; +} + +static inline int is_simd_enabled(void) +{ + return is_lsx_enabled() | is_lasx_enabled(); +} + #define enable_fpu() set_csr_euen(CSR_EUEN_FPEN) #define disable_fpu() clear_csr_euen(CSR_EUEN_FPEN) @@ -81,9 +124,22 @@ static inline void own_fpu(int restore) static inline void lose_fpu_inatomic(int save, struct task_struct *tsk) { if (is_fpu_owner()) { - if (save) - _save_fp(&tsk->thread.fpu); - disable_fpu(); + if (!is_simd_enabled()) { + if (save) + _save_fp(&tsk->thread.fpu); + disable_fpu(); + } else { + if (save) { + if (!is_lasx_enabled()) + save_lsx(tsk); + else + save_lasx(tsk); + } + disable_fpu(); + disable_lsx(); + disable_lasx(); + clear_tsk_thread_flag(tsk, TIF_USEDSIMD); + } clear_tsk_thread_flag(tsk, TIF_USEDFPU); } KSTK_EUEN(tsk) &= ~(CSR_EUEN_FPEN | CSR_EUEN_LSXEN | CSR_EUEN_LASXEN); @@ -129,4 +185,127 @@ static inline union fpureg *get_fpu_regs(struct task_struct *tsk) return tsk->thread.fpu.fpr; } +static inline int is_simd_owner(void) +{ + return test_thread_flag(TIF_USEDSIMD); +} + +#ifdef CONFIG_CPU_HAS_LSX + +static inline void enable_lsx(void) +{ + if (cpu_has_lsx) + csr_xchg32(CSR_EUEN_LSXEN, CSR_EUEN_LSXEN, LOONGARCH_CSR_EUEN); +} + +static inline void disable_lsx(void) +{ + if (cpu_has_lsx) + csr_xchg32(0, CSR_EUEN_LSXEN, LOONGARCH_CSR_EUEN); +} + +static inline void save_lsx(struct task_struct *t) +{ + if (cpu_has_lsx) + _save_lsx(&t->thread.fpu); +} + +static inline void restore_lsx(struct task_struct *t) +{ + if (cpu_has_lsx) + _restore_lsx(&t->thread.fpu); +} + +static inline void init_lsx_upper(void) +{ + /* + * Check cpu_has_lsx only if it's a constant. This will allow the + * compiler to optimise out code for CPUs without LSX without adding + * an extra redundant check for CPUs with LSX. + */ + if (__builtin_constant_p(cpu_has_lsx) && !cpu_has_lsx) + return; + + _init_lsx_upper(); +} + +static inline void restore_lsx_upper(struct task_struct *t) +{ + if (cpu_has_lsx) + _restore_lsx_upper(&t->thread.fpu); +} + +#else +static inline void enable_lsx(void) {} +static inline void disable_lsx(void) {} +static inline void save_lsx(struct task_struct *t) {} +static inline void restore_lsx(struct task_struct *t) {} +static inline void init_lsx_upper(void) {} +static inline void restore_lsx_upper(struct task_struct *t) {} +#endif + +#ifdef CONFIG_CPU_HAS_LASX + +static inline void enable_lasx(void) +{ + + if (cpu_has_lasx) + csr_xchg32(CSR_EUEN_LASXEN, CSR_EUEN_LASXEN, LOONGARCH_CSR_EUEN); +} + +static inline void disable_lasx(void) +{ + if (cpu_has_lasx) + csr_xchg32(0, CSR_EUEN_LASXEN, LOONGARCH_CSR_EUEN); +} + +static inline void save_lasx(struct task_struct *t) +{ + if (cpu_has_lasx) + _save_lasx(&t->thread.fpu); +} + +static inline void restore_lasx(struct task_struct *t) +{ + if (cpu_has_lasx) + _restore_lasx(&t->thread.fpu); +} + +static inline void init_lasx_upper(void) +{ + if (cpu_has_lasx) + _init_lasx_upper(); +} + +static inline void restore_lasx_upper(struct task_struct *t) +{ + if (cpu_has_lasx) + _restore_lasx_upper(&t->thread.fpu); +} + +#else +static inline void enable_lasx(void) {} +static inline void disable_lasx(void) {} +static inline void save_lasx(struct task_struct *t) {} +static inline void restore_lasx(struct task_struct *t) {} +static inline void init_lasx_upper(void) {} +static inline void restore_lasx_upper(struct task_struct *t) {} +#endif + +static inline int thread_lsx_context_live(void) +{ + if (__builtin_constant_p(cpu_has_lsx) && !cpu_has_lsx) + return 0; + + return test_thread_flag(TIF_LSX_CTX_LIVE); +} + +static inline int thread_lasx_context_live(void) +{ + if (__builtin_constant_p(cpu_has_lasx) && !cpu_has_lasx) + return 0; + + return test_thread_flag(TIF_LASX_CTX_LIVE); +} + #endif /* _ASM_FPU_H */ diff --git a/arch/loongarch/include/asm/ftrace.h b/arch/loongarch/include/asm/ftrace.h index 23e2ba78dcb08e2d3a19f2e553e288af264da786..a11996eb5892dd169a1e5a0ba9ad20fb854f4be8 100644 --- a/arch/loongarch/include/asm/ftrace.h +++ b/arch/loongarch/include/asm/ftrace.h @@ -100,4 +100,26 @@ __arch_ftrace_set_direct_caller(struct pt_regs *regs, unsigned long addr) #endif /* CONFIG_FUNCTION_TRACER */ +#ifndef __ASSEMBLY__ +#ifdef CONFIG_FUNCTION_GRAPH_TRACER +struct fgraph_ret_regs { + /* a0 - a1 */ + unsigned long regs[2]; + + unsigned long fp; + unsigned long __unused; +}; + +static inline unsigned long fgraph_ret_regs_return_value(struct fgraph_ret_regs *ret_regs) +{ + return ret_regs->regs[0]; +} + +static inline unsigned long fgraph_ret_regs_frame_pointer(struct fgraph_ret_regs *ret_regs) +{ + return ret_regs->fp; +} +#endif /* ifdef CONFIG_FUNCTION_GRAPH_TRACER */ +#endif + #endif /* _ASM_LOONGARCH_FTRACE_H */ diff --git a/arch/loongarch/include/asm/gpr-num.h b/arch/loongarch/include/asm/gpr-num.h index e0941af20c7e77b380b15696e6aecf7d629ee18b..996038da806d1b634be64969717d9d07a7b2e687 100644 --- a/arch/loongarch/include/asm/gpr-num.h +++ b/arch/loongarch/include/asm/gpr-num.h @@ -9,6 +9,22 @@ .equ .L__gpr_num_$r\num, \num .endr + /* ABI names of registers */ + .equ .L__gpr_num_$ra, 1 + .equ .L__gpr_num_$tp, 2 + .equ .L__gpr_num_$sp, 3 + .irp num,0,1,2,3,4,5,6,7 + .equ .L__gpr_num_$a\num, 4 + \num + .endr + .irp num,0,1,2,3,4,5,6,7,8 + .equ .L__gpr_num_$t\num, 12 + \num + .endr + .equ .L__gpr_num_$s9, 22 + .equ .L__gpr_num_$fp, 22 + .irp num,0,1,2,3,4,5,6,7,8 + .equ .L__gpr_num_$s\num, 23 + \num + .endr + #else /* __ASSEMBLY__ */ #define __DEFINE_ASM_GPR_NUMS \ @@ -16,6 +32,20 @@ " .irp num,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31\n" \ " .equ .L__gpr_num_$r\\num, \\num\n" \ " .endr\n" \ +" .equ .L__gpr_num_$ra, 1\n" \ +" .equ .L__gpr_num_$tp, 2\n" \ +" .equ .L__gpr_num_$sp, 3\n" \ +" .irp num,0,1,2,3,4,5,6,7\n" \ +" .equ .L__gpr_num_$a\\num, 4 + \\num\n" \ +" .endr\n" \ +" .irp num,0,1,2,3,4,5,6,7,8\n" \ +" .equ .L__gpr_num_$t\\num, 12 + \\num\n" \ +" .endr\n" \ +" .equ .L__gpr_num_$s9, 22\n" \ +" .equ .L__gpr_num_$fp, 22\n" \ +" .irp num,0,1,2,3,4,5,6,7,8\n" \ +" .equ .L__gpr_num_$s\\num, 23 + \\num\n" \ +" .endr\n" \ #endif /* __ASSEMBLY__ */ diff --git a/arch/loongarch/include/asm/inst.h b/arch/loongarch/include/asm/inst.h index b09887ffcd15d89a97af42c9dacbda94ef3fe449..71e1ed4165c80d8a753309fcb381b394dfa85665 100644 --- a/arch/loongarch/include/asm/inst.h +++ b/arch/loongarch/include/asm/inst.h @@ -5,6 +5,7 @@ #ifndef _ASM_INST_H #define _ASM_INST_H +#include #include #include #include @@ -15,14 +16,22 @@ #define ADDR_IMMMASK_LU52ID 0xFFF0000000000000 #define ADDR_IMMMASK_LU32ID 0x000FFFFF00000000 #define ADDR_IMMMASK_LU12IW 0x00000000FFFFF000 +#define ADDR_IMMMASK_ORI 0x0000000000000FFF #define ADDR_IMMMASK_ADDU16ID 0x00000000FFFF0000 #define ADDR_IMMSHIFT_LU52ID 52 +#define ADDR_IMMSBIDX_LU52ID 11 #define ADDR_IMMSHIFT_LU32ID 32 +#define ADDR_IMMSBIDX_LU32ID 19 #define ADDR_IMMSHIFT_LU12IW 12 +#define ADDR_IMMSBIDX_LU12IW 19 +#define ADDR_IMMSHIFT_ORI 0 +#define ADDR_IMMSBIDX_ORI 63 #define ADDR_IMMSHIFT_ADDU16ID 16 +#define ADDR_IMMSBIDX_ADDU16ID 15 -#define ADDR_IMM(addr, INSN) ((addr & ADDR_IMMMASK_##INSN) >> ADDR_IMMSHIFT_##INSN) +#define ADDR_IMM(addr, INSN) \ + (sign_extend64(((addr & ADDR_IMMMASK_##INSN) >> ADDR_IMMSHIFT_##INSN), ADDR_IMMSBIDX_##INSN)) enum reg0i15_op { break_op = 0x54, @@ -178,6 +187,32 @@ enum reg3_op { amord_op = 0x70c7, amxorw_op = 0x70c8, amxord_op = 0x70c9, + ammaxw_op = 0x70ca, + ammaxd_op = 0x70cb, + amminw_op = 0x70cc, + ammind_op = 0x70cd, + ammaxwu_op = 0x70ce, + ammaxdu_op = 0x70cf, + amminwu_op = 0x70d0, + ammindu_op = 0x70d1, + amswapdbw_op = 0x70d2, + amswapdbd_op = 0x70d3, + amadddbw_op = 0x70d4, + amadddbd_op = 0x70d5, + amanddbw_op = 0x70d6, + amanddbd_op = 0x70d7, + amordbw_op = 0x70d8, + amordbd_op = 0x70d9, + amxordbw_op = 0x70da, + amxordbd_op = 0x70db, + ammaxdbw_op = 0x70dc, + ammaxdbd_op = 0x70dd, + ammindbw_op = 0x70de, + ammindbd_op = 0x70df, + ammaxdbwu_op = 0x70e0, + ammaxdbdu_op = 0x70e1, + ammindbwu_op = 0x70e2, + ammindbdu_op = 0x70e3, fldgts_op = 0x70e8, fldgtd_op = 0x70e9, fldles_op = 0x70ea, @@ -435,6 +470,10 @@ static inline bool is_self_loop_ins(union loongarch_instruction *ip, struct pt_r void simu_pc(struct pt_regs *regs, union loongarch_instruction insn); void simu_branch(struct pt_regs *regs, union loongarch_instruction insn); +bool insns_not_supported(union loongarch_instruction insn); +bool insns_need_simulation(union loongarch_instruction insn); +void arch_simulate_insn(union loongarch_instruction insn, struct pt_regs *regs); + int larch_insn_read(void *addr, u32 *insnp); int larch_insn_write(void *addr, u32 insn); int larch_insn_patch_text(void *addr, u32 insn); @@ -443,13 +482,15 @@ u32 larch_insn_gen_nop(void); u32 larch_insn_gen_b(unsigned long pc, unsigned long dest); u32 larch_insn_gen_bl(unsigned long pc, unsigned long dest); +u32 larch_insn_gen_break(int imm); + u32 larch_insn_gen_or(enum loongarch_gpr rd, enum loongarch_gpr rj, enum loongarch_gpr rk); u32 larch_insn_gen_move(enum loongarch_gpr rd, enum loongarch_gpr rj); u32 larch_insn_gen_lu12iw(enum loongarch_gpr rd, int imm); u32 larch_insn_gen_lu32id(enum loongarch_gpr rd, int imm); u32 larch_insn_gen_lu52id(enum loongarch_gpr rd, enum loongarch_gpr rj, int imm); -u32 larch_insn_gen_jirl(enum loongarch_gpr rd, enum loongarch_gpr rj, unsigned long pc, unsigned long dest); +u32 larch_insn_gen_jirl(enum loongarch_gpr rd, enum loongarch_gpr rj, int imm); static inline bool signed_imm_check(long val, unsigned int bit) { @@ -461,6 +502,16 @@ static inline bool unsigned_imm_check(unsigned long val, unsigned int bit) return val < (1UL << bit); } +#define DEF_EMIT_REG0I15_FORMAT(NAME, OP) \ +static inline void emit_##NAME(union loongarch_instruction *insn, \ + int imm) \ +{ \ + insn->reg0i15_format.opcode = OP; \ + insn->reg0i15_format.immediate = imm; \ +} + +DEF_EMIT_REG0I15_FORMAT(break, break_op) + #define DEF_EMIT_REG0I26_FORMAT(NAME, OP) \ static inline void emit_##NAME(union loongarch_instruction *insn, \ int offset) \ diff --git a/arch/loongarch/include/asm/io.h b/arch/loongarch/include/asm/io.h index 545e2708fbf7042f6a61f29c1423be1f11de7a7e..1c94102200407f2f62f573bcbb923614db1b52e1 100644 --- a/arch/loongarch/include/asm/io.h +++ b/arch/loongarch/include/asm/io.h @@ -62,7 +62,7 @@ extern pgprot_t pgprot_wc; #define ioremap_cache(offset, size) \ ioremap_prot((offset), (size), pgprot_val(PAGE_KERNEL)) -#define mmiowb() asm volatile ("dbar 0" ::: "memory") +#define mmiowb() wmb() /* * String version of I/O memory access operations. diff --git a/arch/loongarch/include/asm/jump_label.h b/arch/loongarch/include/asm/jump_label.h new file mode 100644 index 0000000000000000000000000000000000000000..3cea299a5ef58313a305f7d5a086ae9a32e8aa95 --- /dev/null +++ b/arch/loongarch/include/asm/jump_label.h @@ -0,0 +1,50 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (C) 2023 Loongson Technology Corporation Limited + * + * Based on arch/arm64/include/asm/jump_label.h + */ +#ifndef __ASM_JUMP_LABEL_H +#define __ASM_JUMP_LABEL_H + +#ifndef __ASSEMBLY__ + +#include + +#define JUMP_LABEL_NOP_SIZE 4 + +#define JUMP_TABLE_ENTRY \ + ".pushsection __jump_table, \"aw\" \n\t" \ + ".align 3 \n\t" \ + ".long 1b - ., %l[l_yes] - . \n\t" \ + ".quad %0 - . \n\t" \ + ".popsection \n\t" + +static __always_inline bool arch_static_branch(struct static_key * const key, const bool branch) +{ + asm_volatile_goto( + "1: nop \n\t" + JUMP_TABLE_ENTRY + : : "i"(&((char *)key)[branch]) : : l_yes); + + return false; + +l_yes: + return true; +} + +static __always_inline bool arch_static_branch_jump(struct static_key * const key, const bool branch) +{ + asm_volatile_goto( + "1: b %l[l_yes] \n\t" + JUMP_TABLE_ENTRY + : : "i"(&((char *)key)[branch]) : : l_yes); + + return false; + +l_yes: + return true; +} + +#endif /* __ASSEMBLY__ */ +#endif /* __ASM_JUMP_LABEL_H */ diff --git a/arch/loongarch/include/asm/kdebug.h b/arch/loongarch/include/asm/kdebug.h index d721b4b82fae094878361d1f0adccb991c0388df..c00ed874bf0619481b4eb3a0454bdd358d2c5f83 100644 --- a/arch/loongarch/include/asm/kdebug.h +++ b/arch/loongarch/include/asm/kdebug.h @@ -13,11 +13,6 @@ enum die_val { DIE_FP, DIE_SIMD, DIE_TRAP, - DIE_PAGE_FAULT, - DIE_BREAK, - DIE_SSTEPBP, - DIE_UPROBE, - DIE_UPROBE_XOL, }; #endif /* _ASM_LOONGARCH_KDEBUG_H */ diff --git a/arch/loongarch/include/asm/kprobes.h b/arch/loongarch/include/asm/kprobes.h index 798020ae02c694b8623206383ebb5d1417e6683c..60fa753a010d96f3f198fc22ff8579946e3d0a84 100644 --- a/arch/loongarch/include/asm/kprobes.h +++ b/arch/loongarch/include/asm/kprobes.h @@ -22,7 +22,7 @@ do { \ #define kretprobe_blacklist_size 0 -typedef union loongarch_instruction kprobe_opcode_t; +typedef u32 kprobe_opcode_t; /* Architecture specific copy of original instruction */ struct arch_specific_insn { @@ -49,9 +49,6 @@ bool kprobe_fault_handler(struct pt_regs *regs, int trapnr); bool kprobe_breakpoint_handler(struct pt_regs *regs); bool kprobe_singlestep_handler(struct pt_regs *regs); -void __kretprobe_trampoline(void); -void *trampoline_probe_handler(struct pt_regs *regs); - #else /* !CONFIG_KPROBES */ static inline bool kprobe_breakpoint_handler(struct pt_regs *regs) { return false; } diff --git a/arch/loongarch/include/asm/loongarch.h b/arch/loongarch/include/asm/loongarch.h index 35e8a52fea11a71004e1a79e092f4ec6c0e2d10e..10748a20a2ab5593f5a19b5b2cbc5dba8ebdda2b 100644 --- a/arch/loongarch/include/asm/loongarch.h +++ b/arch/loongarch/include/asm/loongarch.h @@ -56,10 +56,7 @@ __asm__(".macro parse_r var r\n\t" #undef _IFC_REG /* CPUCFG */ -static inline u32 read_cpucfg(u32 reg) -{ - return __cpucfg(reg); -} +#define read_cpucfg(reg) __cpucfg(reg) #endif /* !__ASSEMBLY__ */ @@ -138,6 +135,7 @@ static inline u32 read_cpucfg(u32 reg) #define CPUCFG2_MIPSBT BIT(20) #define CPUCFG2_LSPW BIT(21) #define CPUCFG2_LAM BIT(22) +#define CPUCFG2_PTW BIT(24) #define LOONGARCH_CPUCFG3 0x3 #define CPUCFG3_CCDMA BIT(0) @@ -206,56 +204,18 @@ static inline u32 read_cpucfg(u32 reg) #ifndef __ASSEMBLY__ /* CSR */ -static __always_inline u32 csr_read32(u32 reg) -{ - return __csrrd_w(reg); -} - -static __always_inline u64 csr_read64(u32 reg) -{ - return __csrrd_d(reg); -} - -static __always_inline void csr_write32(u32 val, u32 reg) -{ - __csrwr_w(val, reg); -} - -static __always_inline void csr_write64(u64 val, u32 reg) -{ - __csrwr_d(val, reg); -} - -static __always_inline u32 csr_xchg32(u32 val, u32 mask, u32 reg) -{ - return __csrxchg_w(val, mask, reg); -} - -static __always_inline u64 csr_xchg64(u64 val, u64 mask, u32 reg) -{ - return __csrxchg_d(val, mask, reg); -} +#define csr_read32(reg) __csrrd_w(reg) +#define csr_read64(reg) __csrrd_d(reg) +#define csr_write32(val, reg) __csrwr_w(val, reg) +#define csr_write64(val, reg) __csrwr_d(val, reg) +#define csr_xchg32(val, mask, reg) __csrxchg_w(val, mask, reg) +#define csr_xchg64(val, mask, reg) __csrxchg_d(val, mask, reg) /* IOCSR */ -static __always_inline u32 iocsr_read32(u32 reg) -{ - return __iocsrrd_w(reg); -} - -static __always_inline u64 iocsr_read64(u32 reg) -{ - return __iocsrrd_d(reg); -} - -static __always_inline void iocsr_write32(u32 val, u32 reg) -{ - __iocsrwr_w(val, reg); -} - -static __always_inline void iocsr_write64(u64 val, u32 reg) -{ - __iocsrwr_d(val, reg); -} +#define iocsr_read32(reg) __iocsrrd_w(reg) +#define iocsr_read64(reg) __iocsrrd_d(reg) +#define iocsr_write32(val, reg) __iocsrwr_w(val, reg) +#define iocsr_write64(val, reg) __iocsrwr_d(val, reg) #endif /* !__ASSEMBLY__ */ @@ -453,6 +413,9 @@ static __always_inline void iocsr_write64(u64 val, u32 reg) #define CSR_PWCTL0_PTBASE (_ULCAST_(0x1f) << CSR_PWCTL0_PTBASE_SHIFT) #define LOONGARCH_CSR_PWCTL1 0x1d /* PWCtl1 */ +#define CSR_PWCTL1_PTW_SHIFT 24 +#define CSR_PWCTL1_PTW_WIDTH 1 +#define CSR_PWCTL1_PTW (_ULCAST_(0x1) << CSR_PWCTL1_PTW_SHIFT) #define CSR_PWCTL1_DIR3WIDTH_SHIFT 18 #define CSR_PWCTL1_DIR3WIDTH_WIDTH 5 #define CSR_PWCTL1_DIR3WIDTH (_ULCAST_(0x1f) << CSR_PWCTL1_DIR3WIDTH_SHIFT) @@ -1167,7 +1130,7 @@ static __always_inline void iocsr_write64(u64 val, u32 reg) #ifndef __ASSEMBLY__ -static inline u64 drdtime(void) +static __always_inline u64 drdtime(void) { int rID = 0; u64 val = 0; @@ -1441,11 +1404,18 @@ __BUILD_CSR_OP(tlbidx) #define EXCCODE_INT_START 64 #define EXCCODE_INT_END (EXCCODE_INT_START + EXCCODE_INT_NUM - 1) -/* FPU register names */ +/* FPU Status Register Names */ +#ifndef CONFIG_AS_HAS_FCSR_CLASS #define LOONGARCH_FCSR0 $r0 #define LOONGARCH_FCSR1 $r1 #define LOONGARCH_FCSR2 $r2 #define LOONGARCH_FCSR3 $r3 +#else +#define LOONGARCH_FCSR0 $fcsr0 +#define LOONGARCH_FCSR1 $fcsr1 +#define LOONGARCH_FCSR2 $fcsr2 +#define LOONGARCH_FCSR3 $fcsr3 +#endif /* FPU Status Register Values */ #define FPU_CSR_RSVD 0xe0e0fce0 diff --git a/arch/loongarch/include/asm/module.h b/arch/loongarch/include/asm/module.h index 12a0f1e66916d0c9b6cab0438349228aca3cabfa..2ecd82bb64e1322cec7666cfaded4d6da2421185 100644 --- a/arch/loongarch/include/asm/module.h +++ b/arch/loongarch/include/asm/module.h @@ -55,7 +55,7 @@ static inline struct plt_entry emit_plt_entry(unsigned long val) lu12iw = larch_insn_gen_lu12iw(LOONGARCH_GPR_T1, ADDR_IMM(val, LU12IW)); lu32id = larch_insn_gen_lu32id(LOONGARCH_GPR_T1, ADDR_IMM(val, LU32ID)); lu52id = larch_insn_gen_lu52id(LOONGARCH_GPR_T1, LOONGARCH_GPR_T1, ADDR_IMM(val, LU52ID)); - jirl = larch_insn_gen_jirl(0, LOONGARCH_GPR_T1, 0, (val & 0xfff)); + jirl = larch_insn_gen_jirl(0, LOONGARCH_GPR_T1, ADDR_IMM(val, ORI)); return (struct plt_entry) { lu12iw, lu32id, lu52id, jirl }; } diff --git a/arch/loongarch/include/asm/page.h b/arch/loongarch/include/asm/page.h index fb5338b352e6573fa70c34efa140504c9c2dbe3c..26e8dccb661909c2f306f2f002c730abdddaf5af 100644 --- a/arch/loongarch/include/asm/page.h +++ b/arch/loongarch/include/asm/page.h @@ -81,6 +81,7 @@ typedef struct { unsigned long pgprot; } pgprot_t; #define __va(x) ((void *)((unsigned long)(x) + PAGE_OFFSET - PHYS_OFFSET)) #define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT) +#define sym_to_pfn(x) __phys_to_pfn(__pa_symbol(x)) #define virt_to_pfn(kaddr) PFN_DOWN(PHYSADDR(kaddr)) #define virt_to_page(kaddr) pfn_to_page(virt_to_pfn(kaddr)) diff --git a/arch/loongarch/include/asm/percpu.h b/arch/loongarch/include/asm/percpu.h index ad8d88494554a73951ac1c7b12c5b322c9750ab5..b9f567e6601668f8e06038f4c15011f7ff7c4798 100644 --- a/arch/loongarch/include/asm/percpu.h +++ b/arch/loongarch/include/asm/percpu.h @@ -14,7 +14,11 @@ * loaded. Tell the compiler this fact when using explicit relocs. */ #if defined(MODULE) && defined(CONFIG_AS_HAS_EXPLICIT_RELOCS) -#define PER_CPU_ATTRIBUTES __attribute__((model("extreme"))) +# if __has_attribute(model) +# define PER_CPU_ATTRIBUTES __attribute__((model("extreme"))) +# else +# error compiler support for the model attribute is necessary when a recent assembler is used +# endif #endif /* Use r21 for fast access */ diff --git a/arch/loongarch/include/asm/pgtable.h b/arch/loongarch/include/asm/pgtable.h index 9a9f9ff9b7098000002c3ed029e54c62a7ba05b1..38afeb7dd58b6b084b7194eff69d215241d9f663 100644 --- a/arch/loongarch/include/asm/pgtable.h +++ b/arch/loongarch/include/asm/pgtable.h @@ -362,7 +362,7 @@ extern pgd_t invalid_pg_dir[]; */ static inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_WRITE; } static inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; } -static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_MODIFIED; } +static inline int pte_dirty(pte_t pte) { return pte_val(pte) & (_PAGE_DIRTY | _PAGE_MODIFIED); } static inline pte_t pte_mkold(pte_t pte) { @@ -506,7 +506,7 @@ static inline pmd_t pmd_wrprotect(pmd_t pmd) static inline int pmd_dirty(pmd_t pmd) { - return !!(pmd_val(pmd) & _PAGE_MODIFIED); + return !!(pmd_val(pmd) & (_PAGE_DIRTY | _PAGE_MODIFIED)); } static inline pmd_t pmd_mkclean(pmd_t pmd) diff --git a/arch/loongarch/include/asm/qspinlock.h b/arch/loongarch/include/asm/qspinlock.h new file mode 100644 index 0000000000000000000000000000000000000000..34f43f8ad5912b657d86c96280ca1e6f104f81c9 --- /dev/null +++ b/arch/loongarch/include/asm/qspinlock.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _ASM_QSPINLOCK_H +#define _ASM_QSPINLOCK_H + +#include + +#define queued_spin_unlock queued_spin_unlock + +static inline void queued_spin_unlock(struct qspinlock *lock) +{ + compiletime_assert_atomic_type(lock->locked); + c_sync(); + WRITE_ONCE(lock->locked, 0); +} + +#include + +#endif /* _ASM_QSPINLOCK_H */ diff --git a/arch/loongarch/include/asm/suspend.h b/arch/loongarch/include/asm/suspend.h new file mode 100644 index 0000000000000000000000000000000000000000..4025c9d5d7cf041cca1e3ef07001fce6baf244e1 --- /dev/null +++ b/arch/loongarch/include/asm/suspend.h @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __ASM_SUSPEND_H +#define __ASM_SUSPEND_H + +void loongarch_common_suspend(void); +void loongarch_common_resume(void); +void loongarch_suspend_enter(void); +void loongarch_wakeup_start(void); + +#endif diff --git a/arch/loongarch/include/asm/tlb.h b/arch/loongarch/include/asm/tlb.h index f5e4deb97402f7417b4286bd70b7269fa44d7edc..da7a3b5b9374aeaf8bc1009d49d3ee0265938e9e 100644 --- a/arch/loongarch/include/asm/tlb.h +++ b/arch/loongarch/include/asm/tlb.h @@ -88,52 +88,47 @@ enum invtlb_ops { INVTLB_GID_ADDR = 0x16, }; -/* - * invtlb op info addr - * (0x1 << 26) | (0x24 << 20) | (0x13 << 15) | - * (addr << 10) | (info << 5) | op - */ -static inline void invtlb(u32 op, u32 info, u64 addr) +static __always_inline void invtlb(u32 op, u32 info, u64 addr) { __asm__ __volatile__( - "parse_r addr,%0\n\t" - "parse_r info,%1\n\t" - ".word ((0x6498000) | (addr << 10) | (info << 5) | %2)\n\t" - : - : "r"(addr), "r"(info), "i"(op) + "invtlb %0, %1, %2\n\t" : + : "i"(op), "r"(info), "r"(addr) + : "memory" ); } -static inline void invtlb_addr(u32 op, u32 info, u64 addr) +static __always_inline void invtlb_addr(u32 op, u32 info, u64 addr) { + BUILD_BUG_ON(!__builtin_constant_p(info) || info != 0); __asm__ __volatile__( - "parse_r addr,%0\n\t" - ".word ((0x6498000) | (addr << 10) | (0 << 5) | %1)\n\t" - : - : "r"(addr), "i"(op) + "invtlb %0, $zero, %1\n\t" : + : "i"(op), "r"(addr) + : "memory" ); } -static inline void invtlb_info(u32 op, u32 info, u64 addr) +static __always_inline void invtlb_info(u32 op, u32 info, u64 addr) { + BUILD_BUG_ON(!__builtin_constant_p(addr) || addr != 0); __asm__ __volatile__( - "parse_r info,%0\n\t" - ".word ((0x6498000) | (0 << 10) | (info << 5) | %1)\n\t" - : - : "r"(info), "i"(op) + "invtlb %0, %1, $zero\n\t" : + : "i"(op), "r"(info) + : "memory" ); } -static inline void invtlb_all(u32 op, u32 info, u64 addr) +static __always_inline void invtlb_all(u32 op, u32 info, u64 addr) { + BUILD_BUG_ON(!__builtin_constant_p(info) || info != 0); + BUILD_BUG_ON(!__builtin_constant_p(addr) || addr != 0); __asm__ __volatile__( - ".word ((0x6498000) | (0 << 10) | (0 << 5) | %0)\n\t" + "invtlb %0, $zero, $zero\n\t" : : "i"(op) - : + : "memory" ); } @@ -163,6 +158,9 @@ extern void handle_tlb_store(void); extern void handle_tlb_modify(void); extern void handle_tlb_refill(void); extern void handle_tlb_protect(void); +extern void handle_tlb_load_ptw(void); +extern void handle_tlb_store_ptw(void); +extern void handle_tlb_modify_ptw(void); extern void dump_tlb_all(void); extern void dump_tlb_regs(void); diff --git a/arch/loongarch/include/asm/uprobes.h b/arch/loongarch/include/asm/uprobes.h new file mode 100644 index 0000000000000000000000000000000000000000..c8f59983f702dfaca208c25047d591b434bacf58 --- /dev/null +++ b/arch/loongarch/include/asm/uprobes.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +#ifndef __ASM_LOONGARCH_UPROBES_H +#define __ASM_LOONGARCH_UPROBES_H + +#include + +typedef u32 uprobe_opcode_t; + +#define MAX_UINSN_BYTES 8 +#define UPROBE_XOL_SLOT_BYTES MAX_UINSN_BYTES + +#define UPROBE_SWBP_INSN larch_insn_gen_break(BRK_UPROBE_BP) +#define UPROBE_SWBP_INSN_SIZE LOONGARCH_INSN_SIZE + +#define UPROBE_XOLBP_INSN larch_insn_gen_break(BRK_UPROBE_XOLBP) + +struct arch_uprobe { + unsigned long resume_era; + u32 insn[2]; + u32 ixol[2]; + bool simulate; +}; + +struct arch_uprobe_task { + unsigned long saved_trap_nr; +}; + +#ifdef CONFIG_UPROBES +bool uprobe_breakpoint_handler(struct pt_regs *regs); +bool uprobe_singlestep_handler(struct pt_regs *regs); +#else /* !CONFIG_UPROBES */ +static inline bool uprobe_breakpoint_handler(struct pt_regs *regs) { return false; } +static inline bool uprobe_singlestep_handler(struct pt_regs *regs) { return false; } +#endif /* CONFIG_UPROBES */ + +#endif /* __ASM_LOONGARCH_UPROBES_H */ diff --git a/arch/loongarch/include/asm/vdso/gettimeofday.h b/arch/loongarch/include/asm/vdso/gettimeofday.h index 7b2cd37641e2a414af766f10a6bc6d6c372015f7..89e6b222c2f2d1ce240198f2fbc14553d0d6b94d 100644 --- a/arch/loongarch/include/asm/vdso/gettimeofday.h +++ b/arch/loongarch/include/asm/vdso/gettimeofday.h @@ -91,9 +91,16 @@ static inline bool loongarch_vdso_hres_capable(void) static __always_inline const struct vdso_data *__arch_get_vdso_data(void) { - return get_vdso_data(); + return (const struct vdso_data *)get_vdso_data(); } +#ifdef CONFIG_TIME_NS +static __always_inline +const struct vdso_data *__arch_get_timens_vdso_data(const struct vdso_data *vd) +{ + return (const struct vdso_data *)(get_vdso_data() + VVAR_TIMENS_PAGE_OFFSET * PAGE_SIZE); +} +#endif #endif /* !__ASSEMBLY__ */ #endif /* __ASM_VDSO_GETTIMEOFDAY_H */ diff --git a/arch/loongarch/include/asm/vdso/vdso.h b/arch/loongarch/include/asm/vdso/vdso.h index 3b55d32a0619cc861c52354db8a0acb7ad5a18f4..5a12309d9fb55556819e976dfaada3ac7c0240ed 100644 --- a/arch/loongarch/include/asm/vdso/vdso.h +++ b/arch/loongarch/include/asm/vdso/vdso.h @@ -16,10 +16,33 @@ struct vdso_pcpu_data { struct loongarch_vdso_data { struct vdso_pcpu_data pdata[NR_CPUS]; - struct vdso_data data[CS_BASES]; /* Arch-independent data */ }; -#define VDSO_DATA_SIZE PAGE_ALIGN(sizeof(struct loongarch_vdso_data)) +/* + * The layout of vvar: + * + * high + * +---------------------+--------------------------+ + * | loongarch vdso data | LOONGARCH_VDSO_DATA_SIZE | + * +---------------------+--------------------------+ + * | time-ns vdso data | PAGE_SIZE | + * +---------------------+--------------------------+ + * | generic vdso data | PAGE_SIZE | + * +---------------------+--------------------------+ + * low + */ +#define LOONGARCH_VDSO_DATA_SIZE PAGE_ALIGN(sizeof(struct loongarch_vdso_data)) +#define LOONGARCH_VDSO_DATA_PAGES (LOONGARCH_VDSO_DATA_SIZE >> PAGE_SHIFT) + +enum vvar_pages { + VVAR_GENERIC_PAGE_OFFSET, + VVAR_TIMENS_PAGE_OFFSET, + VVAR_LOONGARCH_PAGES_START, + VVAR_LOONGARCH_PAGES_END = VVAR_LOONGARCH_PAGES_START + LOONGARCH_VDSO_DATA_PAGES - 1, + VVAR_NR_PAGES, +}; + +#define VVAR_SIZE (VVAR_NR_PAGES << PAGE_SHIFT) static inline unsigned long get_vdso_base(void) { @@ -34,10 +57,9 @@ static inline unsigned long get_vdso_base(void) return addr; } -static inline const struct vdso_data *get_vdso_data(void) +static inline unsigned long get_vdso_data(void) { - return (const struct vdso_data *)(get_vdso_base() - - VDSO_DATA_SIZE + SMP_CACHE_BYTES * NR_CPUS); + return get_vdso_base() - VVAR_SIZE; } #endif /* __ASSEMBLY__ */ diff --git a/arch/loongarch/include/uapi/asm/bitsperlong.h b/arch/loongarch/include/uapi/asm/bitsperlong.h deleted file mode 100644 index 00b4ba1e5cdf032f81aff9f728dcffea68571880..0000000000000000000000000000000000000000 --- a/arch/loongarch/include/uapi/asm/bitsperlong.h +++ /dev/null @@ -1,9 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -#ifndef __ASM_LOONGARCH_BITSPERLONG_H -#define __ASM_LOONGARCH_BITSPERLONG_H - -#define __BITS_PER_LONG (__SIZEOF_LONG__ * 8) - -#include - -#endif /* __ASM_LOONGARCH_BITSPERLONG_H */ diff --git a/arch/loongarch/include/uapi/asm/hwcap.h b/arch/loongarch/include/uapi/asm/hwcap.h index 8840b72fa8e8c58b449bab2ff221ffe678982ad5..6955a7cb2c65d1b575dd9ef9af3b1616fdd3cbab 100644 --- a/arch/loongarch/include/uapi/asm/hwcap.h +++ b/arch/loongarch/include/uapi/asm/hwcap.h @@ -16,5 +16,6 @@ #define HWCAP_LOONGARCH_LBT_X86 (1 << 10) #define HWCAP_LOONGARCH_LBT_ARM (1 << 11) #define HWCAP_LOONGARCH_LBT_MIPS (1 << 12) +#define HWCAP_LOONGARCH_PTW (1 << 13) #endif /* _UAPI_ASM_HWCAP_H */ diff --git a/arch/loongarch/include/uapi/asm/ptrace.h b/arch/loongarch/include/uapi/asm/ptrace.h index 82d811b5c6e972fe06771948b4f8b5d0a2c2791b..06e3be52cb0427c91e03ac2fdddcb85b28ca860c 100644 --- a/arch/loongarch/include/uapi/asm/ptrace.h +++ b/arch/loongarch/include/uapi/asm/ptrace.h @@ -41,9 +41,19 @@ struct user_pt_regs { } __attribute__((aligned(8))); struct user_fp_state { - uint64_t fpr[32]; - uint64_t fcc; - uint32_t fcsr; + uint64_t fpr[32]; + uint64_t fcc; + uint32_t fcsr; +}; + +struct user_lsx_state { + /* 32 registers, 128 bits width per register. */ + uint64_t vregs[32*2]; +}; + +struct user_lasx_state { + /* 32 registers, 256 bits width per register. */ + uint64_t vregs[32*4]; }; struct user_watch_state { diff --git a/arch/loongarch/include/uapi/asm/sigcontext.h b/arch/loongarch/include/uapi/asm/sigcontext.h index 52e49b8bf4be04faf5d2009c16151e5828960af3..4cd7d16f70377586a1d209dca634367c89713ffa 100644 --- a/arch/loongarch/include/uapi/asm/sigcontext.h +++ b/arch/loongarch/include/uapi/asm/sigcontext.h @@ -41,4 +41,22 @@ struct fpu_context { __u32 fcsr; }; +/* LSX context */ +#define LSX_CTX_MAGIC 0x53580001 +#define LSX_CTX_ALIGN 16 +struct lsx_context { + __u64 regs[2*32]; + __u64 fcc; + __u32 fcsr; +}; + +/* LASX context */ +#define LASX_CTX_MAGIC 0x41535801 +#define LASX_CTX_ALIGN 32 +struct lasx_context { + __u64 regs[4*32]; + __u64 fcc; + __u32 fcsr; +}; + #endif /* _UAPI_ASM_SIGCONTEXT_H */ diff --git a/arch/loongarch/kernel/Makefile b/arch/loongarch/kernel/Makefile index 9a72d91cd10497407264ee0392434ed5e9b6ebce..8e279f04f9e7a8031784fc46f0a8a41148e1337b 100644 --- a/arch/loongarch/kernel/Makefile +++ b/arch/loongarch/kernel/Makefile @@ -28,6 +28,8 @@ ifdef CONFIG_FUNCTION_TRACER CFLAGS_REMOVE_inst.o = $(CC_FLAGS_FTRACE) CFLAGS_REMOVE_time.o = $(CC_FLAGS_FTRACE) CFLAGS_REMOVE_perf_event.o = $(CC_FLAGS_FTRACE) + CFLAGS_REMOVE_rethook.o = $(CC_FLAGS_FTRACE) + CFLAGS_REMOVE_rethook_trampoline.o = $(CC_FLAGS_FTRACE) endif obj-$(CONFIG_MODULES) += module.o module-sections.o @@ -52,6 +54,10 @@ obj-$(CONFIG_UNWINDER_PROLOGUE) += unwind_prologue.o obj-$(CONFIG_PERF_EVENTS) += perf_event.o perf_regs.o obj-$(CONFIG_HAVE_HW_BREAKPOINT) += hw_breakpoint.o -obj-$(CONFIG_KPROBES) += kprobes.o kprobes_trampoline.o +obj-$(CONFIG_KPROBES) += kprobes.o +obj-$(CONFIG_RETHOOK) += rethook.o rethook_trampoline.o +obj-$(CONFIG_UPROBES) += uprobes.o + +obj-$(CONFIG_JUMP_LABEL) += jump_label.o CPPFLAGS_vmlinux.lds := $(KBUILD_CFLAGS) diff --git a/arch/loongarch/kernel/acpi.c b/arch/loongarch/kernel/acpi.c index 98f431157e4c1c1815fc08b2a6df06a2c432c363..9450e09073ebf7411e200a21a5a666c7dad092be 100644 --- a/arch/loongarch/kernel/acpi.c +++ b/arch/loongarch/kernel/acpi.c @@ -33,6 +33,8 @@ u64 acpi_saved_sp; #define PREFIX "ACPI: " +struct acpi_madt_core_pic acpi_core_pic[NR_CPUS]; + void __init __iomem * __acpi_map_table(unsigned long phys, unsigned long size) { @@ -99,6 +101,7 @@ acpi_parse_processor(union acpi_subtable_headers *header, const unsigned long en acpi_table_print_madt_entry(&header->common); #ifdef CONFIG_SMP + acpi_core_pic[processor->core_id] = *processor; set_processor_mask(processor->core_id, processor->flags); #endif @@ -140,6 +143,35 @@ static void __init acpi_process_madt(void) loongson_sysconf.nr_cpus = num_processors; } +int pptt_enabled; + +int __init parse_acpi_topology(void) +{ + int cpu, topology_id; + + for_each_possible_cpu(cpu) { + topology_id = find_acpi_cpu_topology(cpu, 0); + if (topology_id < 0) { + pr_warn("Invalid BIOS PPTT\n"); + return -ENOENT; + } + + if (acpi_pptt_cpu_is_thread(cpu) <= 0) + cpu_data[cpu].core = topology_id; + else { + topology_id = find_acpi_cpu_topology(cpu, 1); + if (topology_id < 0) + return -ENOENT; + + cpu_data[cpu].core = topology_id; + } + } + + pptt_enabled = 1; + + return 0; +} + #ifndef CONFIG_SUSPEND int (*acpi_suspend_lowlevel)(void); #else diff --git a/arch/loongarch/kernel/asm-offsets.c b/arch/loongarch/kernel/asm-offsets.c index 4bdb203fc66e145405667a6fca09e57b786c1b8b..505e4bf59603148ba85ab979073b36933e6a9927 100644 --- a/arch/loongarch/kernel/asm-offsets.c +++ b/arch/loongarch/kernel/asm-offsets.c @@ -12,6 +12,7 @@ #include #include #include +#include void output_ptreg_defines(void) { @@ -264,7 +265,7 @@ void output_smpboot_defines(void) #ifdef CONFIG_HIBERNATION void output_pbe_defines(void) { - COMMENT(" Linux struct pbe offsets. "); + COMMENT("Linux struct pbe offsets."); OFFSET(PBE_ADDRESS, pbe, address); OFFSET(PBE_ORIG_ADDRESS, pbe, orig_address); OFFSET(PBE_NEXT, pbe, next); @@ -272,3 +273,15 @@ void output_pbe_defines(void) BLANK(); } #endif + +#ifdef CONFIG_FUNCTION_GRAPH_TRACER +void output_fgraph_ret_regs_defines(void) +{ + COMMENT("LoongArch fgraph_ret_regs offsets."); + OFFSET(FGRET_REGS_A0, fgraph_ret_regs, regs[0]); + OFFSET(FGRET_REGS_A1, fgraph_ret_regs, regs[1]); + OFFSET(FGRET_REGS_FP, fgraph_ret_regs, fp); + DEFINE(FGRET_REGS_SIZE, sizeof(struct fgraph_ret_regs)); + BLANK(); +} +#endif diff --git a/arch/loongarch/kernel/cpu-probe.c b/arch/loongarch/kernel/cpu-probe.c index 5adf0f736c6d74b132b9c24d6a154b12db77d309..e925579c7a71eab8822ff683dd8444f8982e42d6 100644 --- a/arch/loongarch/kernel/cpu-probe.c +++ b/arch/loongarch/kernel/cpu-probe.c @@ -116,6 +116,18 @@ static void cpu_probe_common(struct cpuinfo_loongarch *c) c->options |= LOONGARCH_CPU_FPU; elf_hwcap |= HWCAP_LOONGARCH_FPU; } +#ifdef CONFIG_CPU_HAS_LSX + if (config & CPUCFG2_LSX) { + c->options |= LOONGARCH_CPU_LSX; + elf_hwcap |= HWCAP_LOONGARCH_LSX; + } +#endif +#ifdef CONFIG_CPU_HAS_LASX + if (config & CPUCFG2_LASX) { + c->options |= LOONGARCH_CPU_LASX; + elf_hwcap |= HWCAP_LOONGARCH_LASX; + } +#endif if (config & CPUCFG2_COMPLEX) { c->options |= LOONGARCH_CPU_COMPLEX; elf_hwcap |= HWCAP_LOONGARCH_COMPLEX; @@ -124,6 +136,10 @@ static void cpu_probe_common(struct cpuinfo_loongarch *c) c->options |= LOONGARCH_CPU_CRYPTO; elf_hwcap |= HWCAP_LOONGARCH_CRYPTO; } + if (config & CPUCFG2_PTW) { + c->options |= LOONGARCH_CPU_PTW; + elf_hwcap |= HWCAP_LOONGARCH_PTW; + } if (config & CPUCFG2_LVZP) { c->options |= LOONGARCH_CPU_LVZ; elf_hwcap |= HWCAP_LOONGARCH_LVZ; diff --git a/arch/loongarch/kernel/efi-header.S b/arch/loongarch/kernel/efi-header.S index 8c1d229a2afa10b69f2a3f3688c0900ff3399f78..5f23b85d78cad84067b48a38cb7c5acbfa0f02bd 100644 --- a/arch/loongarch/kernel/efi-header.S +++ b/arch/loongarch/kernel/efi-header.S @@ -24,7 +24,7 @@ .byte 0x02 /* MajorLinkerVersion */ .byte 0x14 /* MinorLinkerVersion */ .long __inittext_end - .Lefi_header_end /* SizeOfCode */ - .long _end - __initdata_begin /* SizeOfInitializedData */ + .long _kernel_vsize /* SizeOfInitializedData */ .long 0 /* SizeOfUninitializedData */ .long __efistub_efi_pe_entry - _head /* AddressOfEntryPoint */ .long .Lefi_header_end - _head /* BaseOfCode */ @@ -79,9 +79,9 @@ IMAGE_SCN_MEM_EXECUTE /* Characteristics */ .ascii ".data\0\0\0" - .long _end - __initdata_begin /* VirtualSize */ + .long _kernel_vsize /* VirtualSize */ .long __initdata_begin - _head /* VirtualAddress */ - .long _edata - __initdata_begin /* SizeOfRawData */ + .long _kernel_rsize /* SizeOfRawData */ .long __initdata_begin - _head /* PointerToRawData */ .long 0 /* PointerToRelocations */ diff --git a/arch/loongarch/kernel/fpu.S b/arch/loongarch/kernel/fpu.S index ccde94140c896d84e746b02fc16b9ba51d9ee6fa..f3df5f0a45094132d0172c32f275dcc92637203e 100644 --- a/arch/loongarch/kernel/fpu.S +++ b/arch/loongarch/kernel/fpu.S @@ -145,6 +145,154 @@ movgr2fcsr fcsr0, \tmp0 .endm + .macro sc_save_lsx base +#ifdef CONFIG_CPU_HAS_LSX + EX vst $vr0, \base, (0 * LSX_REG_WIDTH) + EX vst $vr1, \base, (1 * LSX_REG_WIDTH) + EX vst $vr2, \base, (2 * LSX_REG_WIDTH) + EX vst $vr3, \base, (3 * LSX_REG_WIDTH) + EX vst $vr4, \base, (4 * LSX_REG_WIDTH) + EX vst $vr5, \base, (5 * LSX_REG_WIDTH) + EX vst $vr6, \base, (6 * LSX_REG_WIDTH) + EX vst $vr7, \base, (7 * LSX_REG_WIDTH) + EX vst $vr8, \base, (8 * LSX_REG_WIDTH) + EX vst $vr9, \base, (9 * LSX_REG_WIDTH) + EX vst $vr10, \base, (10 * LSX_REG_WIDTH) + EX vst $vr11, \base, (11 * LSX_REG_WIDTH) + EX vst $vr12, \base, (12 * LSX_REG_WIDTH) + EX vst $vr13, \base, (13 * LSX_REG_WIDTH) + EX vst $vr14, \base, (14 * LSX_REG_WIDTH) + EX vst $vr15, \base, (15 * LSX_REG_WIDTH) + EX vst $vr16, \base, (16 * LSX_REG_WIDTH) + EX vst $vr17, \base, (17 * LSX_REG_WIDTH) + EX vst $vr18, \base, (18 * LSX_REG_WIDTH) + EX vst $vr19, \base, (19 * LSX_REG_WIDTH) + EX vst $vr20, \base, (20 * LSX_REG_WIDTH) + EX vst $vr21, \base, (21 * LSX_REG_WIDTH) + EX vst $vr22, \base, (22 * LSX_REG_WIDTH) + EX vst $vr23, \base, (23 * LSX_REG_WIDTH) + EX vst $vr24, \base, (24 * LSX_REG_WIDTH) + EX vst $vr25, \base, (25 * LSX_REG_WIDTH) + EX vst $vr26, \base, (26 * LSX_REG_WIDTH) + EX vst $vr27, \base, (27 * LSX_REG_WIDTH) + EX vst $vr28, \base, (28 * LSX_REG_WIDTH) + EX vst $vr29, \base, (29 * LSX_REG_WIDTH) + EX vst $vr30, \base, (30 * LSX_REG_WIDTH) + EX vst $vr31, \base, (31 * LSX_REG_WIDTH) +#endif + .endm + + .macro sc_restore_lsx base +#ifdef CONFIG_CPU_HAS_LSX + EX vld $vr0, \base, (0 * LSX_REG_WIDTH) + EX vld $vr1, \base, (1 * LSX_REG_WIDTH) + EX vld $vr2, \base, (2 * LSX_REG_WIDTH) + EX vld $vr3, \base, (3 * LSX_REG_WIDTH) + EX vld $vr4, \base, (4 * LSX_REG_WIDTH) + EX vld $vr5, \base, (5 * LSX_REG_WIDTH) + EX vld $vr6, \base, (6 * LSX_REG_WIDTH) + EX vld $vr7, \base, (7 * LSX_REG_WIDTH) + EX vld $vr8, \base, (8 * LSX_REG_WIDTH) + EX vld $vr9, \base, (9 * LSX_REG_WIDTH) + EX vld $vr10, \base, (10 * LSX_REG_WIDTH) + EX vld $vr11, \base, (11 * LSX_REG_WIDTH) + EX vld $vr12, \base, (12 * LSX_REG_WIDTH) + EX vld $vr13, \base, (13 * LSX_REG_WIDTH) + EX vld $vr14, \base, (14 * LSX_REG_WIDTH) + EX vld $vr15, \base, (15 * LSX_REG_WIDTH) + EX vld $vr16, \base, (16 * LSX_REG_WIDTH) + EX vld $vr17, \base, (17 * LSX_REG_WIDTH) + EX vld $vr18, \base, (18 * LSX_REG_WIDTH) + EX vld $vr19, \base, (19 * LSX_REG_WIDTH) + EX vld $vr20, \base, (20 * LSX_REG_WIDTH) + EX vld $vr21, \base, (21 * LSX_REG_WIDTH) + EX vld $vr22, \base, (22 * LSX_REG_WIDTH) + EX vld $vr23, \base, (23 * LSX_REG_WIDTH) + EX vld $vr24, \base, (24 * LSX_REG_WIDTH) + EX vld $vr25, \base, (25 * LSX_REG_WIDTH) + EX vld $vr26, \base, (26 * LSX_REG_WIDTH) + EX vld $vr27, \base, (27 * LSX_REG_WIDTH) + EX vld $vr28, \base, (28 * LSX_REG_WIDTH) + EX vld $vr29, \base, (29 * LSX_REG_WIDTH) + EX vld $vr30, \base, (30 * LSX_REG_WIDTH) + EX vld $vr31, \base, (31 * LSX_REG_WIDTH) +#endif + .endm + + .macro sc_save_lasx base +#ifdef CONFIG_CPU_HAS_LASX + EX xvst $xr0, \base, (0 * LASX_REG_WIDTH) + EX xvst $xr1, \base, (1 * LASX_REG_WIDTH) + EX xvst $xr2, \base, (2 * LASX_REG_WIDTH) + EX xvst $xr3, \base, (3 * LASX_REG_WIDTH) + EX xvst $xr4, \base, (4 * LASX_REG_WIDTH) + EX xvst $xr5, \base, (5 * LASX_REG_WIDTH) + EX xvst $xr6, \base, (6 * LASX_REG_WIDTH) + EX xvst $xr7, \base, (7 * LASX_REG_WIDTH) + EX xvst $xr8, \base, (8 * LASX_REG_WIDTH) + EX xvst $xr9, \base, (9 * LASX_REG_WIDTH) + EX xvst $xr10, \base, (10 * LASX_REG_WIDTH) + EX xvst $xr11, \base, (11 * LASX_REG_WIDTH) + EX xvst $xr12, \base, (12 * LASX_REG_WIDTH) + EX xvst $xr13, \base, (13 * LASX_REG_WIDTH) + EX xvst $xr14, \base, (14 * LASX_REG_WIDTH) + EX xvst $xr15, \base, (15 * LASX_REG_WIDTH) + EX xvst $xr16, \base, (16 * LASX_REG_WIDTH) + EX xvst $xr17, \base, (17 * LASX_REG_WIDTH) + EX xvst $xr18, \base, (18 * LASX_REG_WIDTH) + EX xvst $xr19, \base, (19 * LASX_REG_WIDTH) + EX xvst $xr20, \base, (20 * LASX_REG_WIDTH) + EX xvst $xr21, \base, (21 * LASX_REG_WIDTH) + EX xvst $xr22, \base, (22 * LASX_REG_WIDTH) + EX xvst $xr23, \base, (23 * LASX_REG_WIDTH) + EX xvst $xr24, \base, (24 * LASX_REG_WIDTH) + EX xvst $xr25, \base, (25 * LASX_REG_WIDTH) + EX xvst $xr26, \base, (26 * LASX_REG_WIDTH) + EX xvst $xr27, \base, (27 * LASX_REG_WIDTH) + EX xvst $xr28, \base, (28 * LASX_REG_WIDTH) + EX xvst $xr29, \base, (29 * LASX_REG_WIDTH) + EX xvst $xr30, \base, (30 * LASX_REG_WIDTH) + EX xvst $xr31, \base, (31 * LASX_REG_WIDTH) +#endif + .endm + + .macro sc_restore_lasx base +#ifdef CONFIG_CPU_HAS_LASX + EX xvld $xr0, \base, (0 * LASX_REG_WIDTH) + EX xvld $xr1, \base, (1 * LASX_REG_WIDTH) + EX xvld $xr2, \base, (2 * LASX_REG_WIDTH) + EX xvld $xr3, \base, (3 * LASX_REG_WIDTH) + EX xvld $xr4, \base, (4 * LASX_REG_WIDTH) + EX xvld $xr5, \base, (5 * LASX_REG_WIDTH) + EX xvld $xr6, \base, (6 * LASX_REG_WIDTH) + EX xvld $xr7, \base, (7 * LASX_REG_WIDTH) + EX xvld $xr8, \base, (8 * LASX_REG_WIDTH) + EX xvld $xr9, \base, (9 * LASX_REG_WIDTH) + EX xvld $xr10, \base, (10 * LASX_REG_WIDTH) + EX xvld $xr11, \base, (11 * LASX_REG_WIDTH) + EX xvld $xr12, \base, (12 * LASX_REG_WIDTH) + EX xvld $xr13, \base, (13 * LASX_REG_WIDTH) + EX xvld $xr14, \base, (14 * LASX_REG_WIDTH) + EX xvld $xr15, \base, (15 * LASX_REG_WIDTH) + EX xvld $xr16, \base, (16 * LASX_REG_WIDTH) + EX xvld $xr17, \base, (17 * LASX_REG_WIDTH) + EX xvld $xr18, \base, (18 * LASX_REG_WIDTH) + EX xvld $xr19, \base, (19 * LASX_REG_WIDTH) + EX xvld $xr20, \base, (20 * LASX_REG_WIDTH) + EX xvld $xr21, \base, (21 * LASX_REG_WIDTH) + EX xvld $xr22, \base, (22 * LASX_REG_WIDTH) + EX xvld $xr23, \base, (23 * LASX_REG_WIDTH) + EX xvld $xr24, \base, (24 * LASX_REG_WIDTH) + EX xvld $xr25, \base, (25 * LASX_REG_WIDTH) + EX xvld $xr26, \base, (26 * LASX_REG_WIDTH) + EX xvld $xr27, \base, (27 * LASX_REG_WIDTH) + EX xvld $xr28, \base, (28 * LASX_REG_WIDTH) + EX xvld $xr29, \base, (29 * LASX_REG_WIDTH) + EX xvld $xr30, \base, (30 * LASX_REG_WIDTH) + EX xvld $xr31, \base, (31 * LASX_REG_WIDTH) +#endif + .endm + /* * Save a thread's fp context. */ @@ -166,6 +314,76 @@ SYM_FUNC_START(_restore_fp) jr ra SYM_FUNC_END(_restore_fp) +#ifdef CONFIG_CPU_HAS_LSX + +/* + * Save a thread's LSX vector context. + */ +SYM_FUNC_START(_save_lsx) + lsx_save_all a0 t1 t2 + jr ra +SYM_FUNC_END(_save_lsx) +EXPORT_SYMBOL(_save_lsx) + +/* + * Restore a thread's LSX vector context. + */ +SYM_FUNC_START(_restore_lsx) + lsx_restore_all a0 t1 t2 + jr ra +SYM_FUNC_END(_restore_lsx) + +SYM_FUNC_START(_save_lsx_upper) + lsx_save_all_upper a0 t0 t1 + jr ra +SYM_FUNC_END(_save_lsx_upper) + +SYM_FUNC_START(_restore_lsx_upper) + lsx_restore_all_upper a0 t0 t1 + jr ra +SYM_FUNC_END(_restore_lsx_upper) + +SYM_FUNC_START(_init_lsx_upper) + lsx_init_all_upper t1 + jr ra +SYM_FUNC_END(_init_lsx_upper) +#endif + +#ifdef CONFIG_CPU_HAS_LASX + +/* + * Save a thread's LASX vector context. + */ +SYM_FUNC_START(_save_lasx) + lasx_save_all a0 t1 t2 + jr ra +SYM_FUNC_END(_save_lasx) +EXPORT_SYMBOL(_save_lasx) + +/* + * Restore a thread's LASX vector context. + */ +SYM_FUNC_START(_restore_lasx) + lasx_restore_all a0 t1 t2 + jr ra +SYM_FUNC_END(_restore_lasx) + +SYM_FUNC_START(_save_lasx_upper) + lasx_save_all_upper a0 t0 t1 + jr ra +SYM_FUNC_END(_save_lasx_upper) + +SYM_FUNC_START(_restore_lasx_upper) + lasx_restore_all_upper a0 t0 t1 + jr ra +SYM_FUNC_END(_restore_lasx_upper) + +SYM_FUNC_START(_init_lasx_upper) + lasx_init_all_upper t1 + jr ra +SYM_FUNC_END(_init_lasx_upper) +#endif + /* * Load the FPU with signalling NANS. This bit pattern we're using has * the property that no matter whether considered as single or as double @@ -244,6 +462,58 @@ SYM_FUNC_START(_restore_fp_context) jr ra SYM_FUNC_END(_restore_fp_context) +/* + * a0: fpregs + * a1: fcc + * a2: fcsr + */ +SYM_FUNC_START(_save_lsx_context) + sc_save_fcc a1, t0, t1 + sc_save_fcsr a2, t0 + sc_save_lsx a0 + li.w a0, 0 # success + jr ra +SYM_FUNC_END(_save_lsx_context) + +/* + * a0: fpregs + * a1: fcc + * a2: fcsr + */ +SYM_FUNC_START(_restore_lsx_context) + sc_restore_lsx a0 + sc_restore_fcc a1, t1, t2 + sc_restore_fcsr a2, t1 + li.w a0, 0 # success + jr ra +SYM_FUNC_END(_restore_lsx_context) + +/* + * a0: fpregs + * a1: fcc + * a2: fcsr + */ +SYM_FUNC_START(_save_lasx_context) + sc_save_fcc a1, t0, t1 + sc_save_fcsr a2, t0 + sc_save_lasx a0 + li.w a0, 0 # success + jr ra +SYM_FUNC_END(_save_lasx_context) + +/* + * a0: fpregs + * a1: fcc + * a2: fcsr + */ +SYM_FUNC_START(_restore_lasx_context) + sc_restore_lasx a0 + sc_restore_fcc a1, t1, t2 + sc_restore_fcsr a2, t1 + li.w a0, 0 # success + jr ra +SYM_FUNC_END(_restore_lasx_context) + SYM_FUNC_START(fault) li.w a0, -EFAULT # failure jr ra diff --git a/arch/loongarch/kernel/head.S b/arch/loongarch/kernel/head.S index aa64b179744f52ac4332bfe82302490e14a8210a..5e828a8bc0a0e0b95006449d2a1ab10b14ca2d4a 100644 --- a/arch/loongarch/kernel/head.S +++ b/arch/loongarch/kernel/head.S @@ -23,7 +23,7 @@ _head: .word MZ_MAGIC /* "MZ", MS-DOS header */ .org 0x8 .dword kernel_entry /* Kernel entry point */ - .dword _end - _text /* Kernel image effective size */ + .dword _kernel_asize /* Kernel image effective size */ .quad PHYS_LINK_KADDR /* Kernel image load offset from start of RAM */ .org 0x38 /* 0x20 ~ 0x37 reserved */ .long LINUX_PE_MAGIC @@ -32,9 +32,9 @@ _head: pe_header: __EFI_PE_HEADER -SYM_DATA(kernel_asize, .long _end - _text); -SYM_DATA(kernel_fsize, .long _edata - _text); -SYM_DATA(kernel_offset, .long kernel_offset - _text); +SYM_DATA(kernel_asize, .long _kernel_asize); +SYM_DATA(kernel_fsize, .long _kernel_fsize); +SYM_DATA(kernel_offset, .long _kernel_offset); #endif diff --git a/arch/loongarch/kernel/inst.c b/arch/loongarch/kernel/inst.c index 258ef267cd306fd97a27f8aced0931634b518561..3050329556d118c0933032739bc0662cc47ef29d 100644 --- a/arch/loongarch/kernel/inst.c +++ b/arch/loongarch/kernel/inst.c @@ -133,6 +133,51 @@ void simu_branch(struct pt_regs *regs, union loongarch_instruction insn) } } +bool insns_not_supported(union loongarch_instruction insn) +{ + switch (insn.reg3_format.opcode) { + case amswapw_op ... ammindbdu_op: + pr_notice("atomic memory access instructions are not supported\n"); + return true; + } + + switch (insn.reg2i14_format.opcode) { + case llw_op: + case lld_op: + case scw_op: + case scd_op: + pr_notice("ll and sc instructions are not supported\n"); + return true; + } + + switch (insn.reg1i21_format.opcode) { + case bceqz_op: + pr_notice("bceqz and bcnez instructions are not supported\n"); + return true; + } + + return false; +} + +bool insns_need_simulation(union loongarch_instruction insn) +{ + if (is_pc_ins(&insn)) + return true; + + if (is_branch_ins(&insn)) + return true; + + return false; +} + +void arch_simulate_insn(union loongarch_instruction insn, struct pt_regs *regs) +{ + if (is_pc_ins(&insn)) + simu_pc(regs, insn); + else if (is_branch_ins(&insn)) + simu_branch(regs, insn); +} + int larch_insn_read(void *addr, u32 *insnp) { int ret; @@ -208,6 +253,20 @@ u32 larch_insn_gen_bl(unsigned long pc, unsigned long dest) return insn.word; } +u32 larch_insn_gen_break(int imm) +{ + union loongarch_instruction insn; + + if (imm < 0 || imm >= SZ_32K) { + pr_warn("The generated break instruction is out of range.\n"); + return INSN_BREAK; + } + + emit_break(&insn, imm); + + return insn.word; +} + u32 larch_insn_gen_or(enum loongarch_gpr rd, enum loongarch_gpr rj, enum loongarch_gpr rk) { union loongarch_instruction insn; @@ -226,6 +285,11 @@ u32 larch_insn_gen_lu12iw(enum loongarch_gpr rd, int imm) { union loongarch_instruction insn; + if (imm < -SZ_512K || imm >= SZ_512K) { + pr_warn("The generated lu12i.w instruction is out of range.\n"); + return INSN_BREAK; + } + emit_lu12iw(&insn, rd, imm); return insn.word; @@ -235,6 +299,11 @@ u32 larch_insn_gen_lu32id(enum loongarch_gpr rd, int imm) { union loongarch_instruction insn; + if (imm < -SZ_512K || imm >= SZ_512K) { + pr_warn("The generated lu32i.d instruction is out of range.\n"); + return INSN_BREAK; + } + emit_lu32id(&insn, rd, imm); return insn.word; @@ -244,16 +313,26 @@ u32 larch_insn_gen_lu52id(enum loongarch_gpr rd, enum loongarch_gpr rj, int imm) { union loongarch_instruction insn; + if (imm < -SZ_2K || imm >= SZ_2K) { + pr_warn("The generated lu52i.d instruction is out of range.\n"); + return INSN_BREAK; + } + emit_lu52id(&insn, rd, rj, imm); return insn.word; } -u32 larch_insn_gen_jirl(enum loongarch_gpr rd, enum loongarch_gpr rj, unsigned long pc, unsigned long dest) +u32 larch_insn_gen_jirl(enum loongarch_gpr rd, enum loongarch_gpr rj, int imm) { union loongarch_instruction insn; - emit_jirl(&insn, rj, rd, (dest - pc) >> 2); + if ((imm & 3) || imm < -SZ_128K || imm >= SZ_128K) { + pr_warn("The generated jirl instruction is out of range.\n"); + return INSN_BREAK; + } + + emit_jirl(&insn, rj, rd, imm >> 2); return insn.word; } diff --git a/arch/loongarch/kernel/jump_label.c b/arch/loongarch/kernel/jump_label.c new file mode 100644 index 0000000000000000000000000000000000000000..31891214b767e71c96590bf6d58317bdc4874d54 --- /dev/null +++ b/arch/loongarch/kernel/jump_label.c @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2023 Loongson Technology Corporation Limited + * + * Based on arch/arm64/kernel/jump_label.c + */ +#include +#include +#include + +void arch_jump_label_transform(struct jump_entry *entry, enum jump_label_type type) +{ + u32 insn; + void *addr = (void *)jump_entry_code(entry); + + if (type == JUMP_LABEL_JMP) + insn = larch_insn_gen_b(jump_entry_code(entry), jump_entry_target(entry)); + else + insn = larch_insn_gen_nop(); + + larch_insn_patch_text(addr, insn); +} diff --git a/arch/loongarch/kernel/kprobes.c b/arch/loongarch/kernel/kprobes.c index 56c8c4b09a4299652e10cf65c9073a016a93891f..17b040bd6067c511fd1ae879aad6edc8c71696ff 100644 --- a/arch/loongarch/kernel/kprobes.c +++ b/arch/loongarch/kernel/kprobes.c @@ -4,69 +4,16 @@ #include #include -static const union loongarch_instruction breakpoint_insn = { - .reg0i15_format = { - .opcode = break_op, - .immediate = BRK_KPROBE_BP, - } -}; - -static const union loongarch_instruction singlestep_insn = { - .reg0i15_format = { - .opcode = break_op, - .immediate = BRK_KPROBE_SSTEPBP, - } -}; +#define KPROBE_BP_INSN larch_insn_gen_break(BRK_KPROBE_BP) +#define KPROBE_SSTEPBP_INSN larch_insn_gen_break(BRK_KPROBE_SSTEPBP) DEFINE_PER_CPU(struct kprobe *, current_kprobe); DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk); -static bool insns_not_supported(union loongarch_instruction insn) -{ - switch (insn.reg2i14_format.opcode) { - case llw_op: - case lld_op: - case scw_op: - case scd_op: - pr_notice("kprobe: ll and sc instructions are not supported\n"); - return true; - } - - switch (insn.reg1i21_format.opcode) { - case bceqz_op: - pr_notice("kprobe: bceqz and bcnez instructions are not supported\n"); - return true; - } - - return false; -} -NOKPROBE_SYMBOL(insns_not_supported); - -static bool insns_need_simulation(struct kprobe *p) -{ - if (is_pc_ins(&p->opcode)) - return true; - - if (is_branch_ins(&p->opcode)) - return true; - - return false; -} -NOKPROBE_SYMBOL(insns_need_simulation); - -static void arch_simulate_insn(struct kprobe *p, struct pt_regs *regs) -{ - if (is_pc_ins(&p->opcode)) - simu_pc(regs, p->opcode); - else if (is_branch_ins(&p->opcode)) - simu_branch(regs, p->opcode); -} -NOKPROBE_SYMBOL(arch_simulate_insn); - static void arch_prepare_ss_slot(struct kprobe *p) { p->ainsn.insn[0] = *p->addr; - p->ainsn.insn[1] = singlestep_insn; + p->ainsn.insn[1] = KPROBE_SSTEPBP_INSN; p->ainsn.restore = (unsigned long)p->addr + LOONGARCH_INSN_SIZE; } NOKPROBE_SYMBOL(arch_prepare_ss_slot); @@ -79,17 +26,20 @@ NOKPROBE_SYMBOL(arch_prepare_simulate); int arch_prepare_kprobe(struct kprobe *p) { + union loongarch_instruction insn; + if ((unsigned long)p->addr & 0x3) return -EILSEQ; /* copy instruction */ p->opcode = *p->addr; + insn.word = p->opcode; /* decode instruction */ - if (insns_not_supported(p->opcode)) + if (insns_not_supported(insn)) return -EINVAL; - if (insns_need_simulation(p)) { + if (insns_need_simulation(insn)) { p->ainsn.insn = NULL; } else { p->ainsn.insn = get_insn_slot(); @@ -110,7 +60,7 @@ NOKPROBE_SYMBOL(arch_prepare_kprobe); /* Install breakpoint in text */ void arch_arm_kprobe(struct kprobe *p) { - *p->addr = breakpoint_insn; + *p->addr = KPROBE_BP_INSN; flush_insn_slot(p); } NOKPROBE_SYMBOL(arch_arm_kprobe); @@ -205,6 +155,8 @@ NOKPROBE_SYMBOL(post_kprobe_handler); static void setup_singlestep(struct kprobe *p, struct pt_regs *regs, struct kprobe_ctlblk *kcb, int reenter) { + union loongarch_instruction insn; + if (reenter) { save_previous_kprobe(kcb); set_current_kprobe(p); @@ -220,7 +172,8 @@ static void setup_singlestep(struct kprobe *p, struct pt_regs *regs, regs->csr_era = (unsigned long)p->ainsn.insn; } else { /* simulate single steping */ - arch_simulate_insn(p, regs); + insn.word = p->opcode; + arch_simulate_insn(insn, regs); /* now go for post processing */ post_kprobe_handler(p, kcb, regs); } @@ -295,7 +248,7 @@ bool kprobe_breakpoint_handler(struct pt_regs *regs) } } - if (addr->word != breakpoint_insn.word) { + if (*addr != KPROBE_BP_INSN) { /* * The breakpoint instruction was removed right * after we hit it. Another cpu has removed @@ -378,27 +331,6 @@ int __init arch_init_kprobes(void) return 0; } -/* ASM function that handles the kretprobes must not be probed */ -NOKPROBE_SYMBOL(__kretprobe_trampoline); - -/* Called from __kretprobe_trampoline */ -void __used *trampoline_probe_handler(struct pt_regs *regs) -{ - return (void *)kretprobe_trampoline_handler(regs, NULL); -} -NOKPROBE_SYMBOL(trampoline_probe_handler); - -void arch_prepare_kretprobe(struct kretprobe_instance *ri, - struct pt_regs *regs) -{ - ri->ret_addr = (kprobe_opcode_t *)regs->regs[1]; - ri->fp = NULL; - - /* Replace the return addr with trampoline addr */ - regs->regs[1] = (unsigned long)&__kretprobe_trampoline; -} -NOKPROBE_SYMBOL(arch_prepare_kretprobe); - int arch_trampoline_kprobe(struct kprobe *p) { return 0; diff --git a/arch/loongarch/kernel/mcount.S b/arch/loongarch/kernel/mcount.S index 8cdc1563cd33f246bf324137116a55e37a2e84f8..cb8e5803de4b02b2c5ee92b8dd52ea792f50dc6d 100644 --- a/arch/loongarch/kernel/mcount.S +++ b/arch/loongarch/kernel/mcount.S @@ -79,18 +79,20 @@ SYM_FUNC_START(ftrace_graph_caller) SYM_FUNC_END(ftrace_graph_caller) SYM_FUNC_START(return_to_handler) - PTR_ADDI sp, sp, -2 * SZREG - PTR_S a0, sp, 0 - PTR_S a1, sp, SZREG + PTR_ADDI sp, sp, -FGRET_REGS_SIZE + PTR_S a0, sp, FGRET_REGS_A0 + PTR_S a1, sp, FGRET_REGS_A1 + PTR_S zero, sp, FGRET_REGS_FP + move a0, sp bl ftrace_return_to_handler /* Restore the real parent address: a0 -> ra */ move ra, a0 - PTR_L a0, sp, 0 - PTR_L a1, sp, SZREG - PTR_ADDI sp, sp, 2 * SZREG + PTR_L a0, sp, FGRET_REGS_A0 + PTR_L a1, sp, FGRET_REGS_A1 + PTR_ADDI sp, sp, FGRET_REGS_SIZE jr ra SYM_FUNC_END(return_to_handler) #endif /* CONFIG_FUNCTION_GRAPH_TRACER */ diff --git a/arch/loongarch/kernel/mcount_dyn.S b/arch/loongarch/kernel/mcount_dyn.S index c7d961fc72c257a6fbcd860095b9d2dc8bc581bc..e16ab0b98e5a919ed35bc750ca2902a67af0aa71 100644 --- a/arch/loongarch/kernel/mcount_dyn.S +++ b/arch/loongarch/kernel/mcount_dyn.S @@ -136,18 +136,19 @@ SYM_CODE_END(ftrace_graph_caller) SYM_CODE_START(return_to_handler) /* Save return value regs */ - PTR_ADDI sp, sp, -2 * SZREG - PTR_S a0, sp, 0 - PTR_S a1, sp, SZREG + PTR_ADDI sp, sp, -FGRET_REGS_SIZE + PTR_S a0, sp, FGRET_REGS_A0 + PTR_S a1, sp, FGRET_REGS_A1 + PTR_S zero, sp, FGRET_REGS_FP - move a0, zero + move a0, sp bl ftrace_return_to_handler move ra, a0 /* Restore return value regs */ - PTR_L a0, sp, 0 - PTR_L a1, sp, SZREG - PTR_ADDI sp, sp, 2 * SZREG + PTR_L a0, sp, FGRET_REGS_A0 + PTR_L a1, sp, FGRET_REGS_A1 + PTR_ADDI sp, sp, FGRET_REGS_SIZE jr ra SYM_CODE_END(return_to_handler) diff --git a/arch/loongarch/kernel/proc.c b/arch/loongarch/kernel/proc.c index 0d82907b5404c31d0965df34a4220157e99d5e8e..0d33cbc47e511093abbea31f205577875bef0c30 100644 --- a/arch/loongarch/kernel/proc.c +++ b/arch/loongarch/kernel/proc.c @@ -49,6 +49,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) seq_printf(m, "processor\t\t: %ld\n", n); seq_printf(m, "package\t\t\t: %d\n", cpu_data[n].package); seq_printf(m, "core\t\t\t: %d\n", cpu_data[n].core); + seq_printf(m, "global_id\t\t: %d\n", cpu_data[n].global_id); seq_printf(m, "CPU Family\t\t: %s\n", __cpu_family[n]); seq_printf(m, "Model Name\t\t: %s\n", __cpu_full_name[n]); seq_printf(m, "CPU Revision\t\t: 0x%02x\n", version); @@ -79,6 +80,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) if (cpu_has_crc32) seq_printf(m, " crc32"); if (cpu_has_complex) seq_printf(m, " complex"); if (cpu_has_crypto) seq_printf(m, " crypto"); + if (cpu_has_ptw) seq_printf(m, " ptw"); if (cpu_has_lvz) seq_printf(m, " lvz"); if (cpu_has_lbt_x86) seq_printf(m, " lbt_x86"); if (cpu_has_lbt_arm) seq_printf(m, " lbt_arm"); diff --git a/arch/loongarch/kernel/process.c b/arch/loongarch/kernel/process.c index b71e17c1cc0c094b8ffe4a340f72676c727f8c3b..2e04eb07abb6e0e13f0887580eb264affbfdc7bb 100644 --- a/arch/loongarch/kernel/process.c +++ b/arch/loongarch/kernel/process.c @@ -117,8 +117,14 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) */ preempt_disable(); - if (is_fpu_owner()) - save_fp(current); + if (is_fpu_owner()) { + if (is_lasx_enabled()) + save_lasx(current); + else if (is_lsx_enabled()) + save_lsx(current); + else + save_fp(current); + } preempt_enable(); @@ -285,7 +291,7 @@ unsigned long stack_top(void) /* Space for the VDSO & data page */ top -= PAGE_ALIGN(current->thread.vdso->size); - top -= PAGE_SIZE; + top -= VVAR_SIZE; /* Space to randomize the VDSO base */ if (current->flags & PF_RANDOMIZE) diff --git a/arch/loongarch/kernel/ptrace.c b/arch/loongarch/kernel/ptrace.c index 5fcffb45236764ee75fce64c2508003b5773bffc..a0767c3a0f0a95f1682e7c802a57430830ce0fb1 100644 --- a/arch/loongarch/kernel/ptrace.c +++ b/arch/loongarch/kernel/ptrace.c @@ -250,6 +250,90 @@ static int cfg_set(struct task_struct *target, return 0; } +#ifdef CONFIG_CPU_HAS_LSX + +static void copy_pad_fprs(struct task_struct *target, + const struct user_regset *regset, + struct membuf *to, unsigned int live_sz) +{ + int i, j; + unsigned long long fill = ~0ull; + unsigned int cp_sz, pad_sz; + + cp_sz = min(regset->size, live_sz); + pad_sz = regset->size - cp_sz; + WARN_ON(pad_sz % sizeof(fill)); + + for (i = 0; i < NUM_FPU_REGS; i++) { + membuf_write(to, &target->thread.fpu.fpr[i], cp_sz); + for (j = 0; j < (pad_sz / sizeof(fill)); j++) { + membuf_store(to, fill); + } + } +} + +static int simd_get(struct task_struct *target, + const struct user_regset *regset, + struct membuf to) +{ + const unsigned int wr_size = NUM_FPU_REGS * regset->size; + + if (!tsk_used_math(target)) { + /* The task hasn't used FP or LSX, fill with 0xff */ + copy_pad_fprs(target, regset, &to, 0); + } else if (!test_tsk_thread_flag(target, TIF_LSX_CTX_LIVE)) { + /* Copy scalar FP context, fill the rest with 0xff */ + copy_pad_fprs(target, regset, &to, 8); +#ifdef CONFIG_CPU_HAS_LASX + } else if (!test_tsk_thread_flag(target, TIF_LASX_CTX_LIVE)) { + /* Copy LSX 128 Bit context, fill the rest with 0xff */ + copy_pad_fprs(target, regset, &to, 16); +#endif + } else if (sizeof(target->thread.fpu.fpr[0]) == regset->size) { + /* Trivially copy the vector registers */ + membuf_write(&to, &target->thread.fpu.fpr, wr_size); + } else { + /* Copy as much context as possible, fill the rest with 0xff */ + copy_pad_fprs(target, regset, &to, sizeof(target->thread.fpu.fpr[0])); + } + + return 0; +} + +static int simd_set(struct task_struct *target, + const struct user_regset *regset, + unsigned int pos, unsigned int count, + const void *kbuf, const void __user *ubuf) +{ + const unsigned int wr_size = NUM_FPU_REGS * regset->size; + unsigned int cp_sz; + int i, err, start; + + init_fp_ctx(target); + + if (sizeof(target->thread.fpu.fpr[0]) == regset->size) { + /* Trivially copy the vector registers */ + err = user_regset_copyin(&pos, &count, &kbuf, &ubuf, + &target->thread.fpu.fpr, + 0, wr_size); + } else { + /* Copy as much context as possible */ + cp_sz = min_t(unsigned int, regset->size, + sizeof(target->thread.fpu.fpr[0])); + + i = start = err = 0; + for (; i < NUM_FPU_REGS; i++, start += regset->size) { + err |= user_regset_copyin(&pos, &count, &kbuf, &ubuf, + &target->thread.fpu.fpr[i], + start, start + cp_sz); + } + } + + return err; +} + +#endif /* CONFIG_CPU_HAS_LSX */ + #ifdef CONFIG_HAVE_HW_BREAKPOINT /* @@ -708,6 +792,12 @@ enum loongarch_regset { REGSET_GPR, REGSET_FPR, REGSET_CPUCFG, +#ifdef CONFIG_CPU_HAS_LSX + REGSET_LSX, +#endif +#ifdef CONFIG_CPU_HAS_LASX + REGSET_LASX, +#endif #ifdef CONFIG_HAVE_HW_BREAKPOINT REGSET_HW_BREAK, REGSET_HW_WATCH, @@ -739,6 +829,26 @@ static const struct user_regset loongarch64_regsets[] = { .regset_get = cfg_get, .set = cfg_set, }, +#ifdef CONFIG_CPU_HAS_LSX + [REGSET_LSX] = { + .core_note_type = NT_LOONGARCH_LSX, + .n = NUM_FPU_REGS, + .size = 16, + .align = 16, + .regset_get = simd_get, + .set = simd_set, + }, +#endif +#ifdef CONFIG_CPU_HAS_LASX + [REGSET_LASX] = { + .core_note_type = NT_LOONGARCH_LASX, + .n = NUM_FPU_REGS, + .size = 32, + .align = 32, + .regset_get = simd_get, + .set = simd_set, + }, +#endif #ifdef CONFIG_HAVE_HW_BREAKPOINT [REGSET_HW_BREAK] = { .core_note_type = NT_LOONGARCH_HW_BREAK, diff --git a/arch/loongarch/kernel/rethook.c b/arch/loongarch/kernel/rethook.c new file mode 100644 index 0000000000000000000000000000000000000000..db1c5f5024fd5a3a8066ff4351a98a8becbdaf86 --- /dev/null +++ b/arch/loongarch/kernel/rethook.c @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Generic return hook for LoongArch. + */ + +#include +#include +#include "rethook.h" + +/* This is called from arch_rethook_trampoline() */ +unsigned long __used arch_rethook_trampoline_callback(struct pt_regs *regs) +{ + return rethook_trampoline_handler(regs, 0); +} +NOKPROBE_SYMBOL(arch_rethook_trampoline_callback); + +void arch_rethook_prepare(struct rethook_node *rhn, struct pt_regs *regs, bool mcount) +{ + rhn->frame = 0; + rhn->ret_addr = regs->regs[1]; + + /* replace return addr with trampoline */ + regs->regs[1] = (unsigned long)arch_rethook_trampoline; +} +NOKPROBE_SYMBOL(arch_rethook_prepare); + +/* ASM function that handles the rethook must not be probed itself */ +NOKPROBE_SYMBOL(arch_rethook_trampoline); diff --git a/arch/loongarch/kernel/rethook.h b/arch/loongarch/kernel/rethook.h new file mode 100644 index 0000000000000000000000000000000000000000..3f1c1edf0d0b295a598313f65914c2cbad62ffdd --- /dev/null +++ b/arch/loongarch/kernel/rethook.h @@ -0,0 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __LOONGARCH_RETHOOK_H +#define __LOONGARCH_RETHOOK_H + +unsigned long arch_rethook_trampoline_callback(struct pt_regs *regs); +void arch_rethook_prepare(struct rethook_node *rhn, struct pt_regs *regs, bool mcount); + +#endif diff --git a/arch/loongarch/kernel/kprobes_trampoline.S b/arch/loongarch/kernel/rethook_trampoline.S similarity index 93% rename from arch/loongarch/kernel/kprobes_trampoline.S rename to arch/loongarch/kernel/rethook_trampoline.S index af94b0d213fa950083e7d9375bd5b402ff1db20d..bd5772c963382f7bc475c142d4af9ca985357f65 100644 --- a/arch/loongarch/kernel/kprobes_trampoline.S +++ b/arch/loongarch/kernel/rethook_trampoline.S @@ -75,7 +75,7 @@ csrxchg t0, t1, LOONGARCH_CSR_CRMD .endm -SYM_CODE_START(__kretprobe_trampoline) +SYM_CODE_START(arch_rethook_trampoline) addi.d sp, sp, -PT_SIZE save_all_base_regs @@ -84,7 +84,7 @@ SYM_CODE_START(__kretprobe_trampoline) move a0, sp /* pt_regs */ - bl trampoline_probe_handler + bl arch_rethook_trampoline_callback /* use the result as the return-address */ move ra, a0 @@ -93,4 +93,4 @@ SYM_CODE_START(__kretprobe_trampoline) addi.d sp, sp, PT_SIZE jr ra -SYM_CODE_END(__kretprobe_trampoline) +SYM_CODE_END(arch_rethook_trampoline) diff --git a/arch/loongarch/kernel/setup.c b/arch/loongarch/kernel/setup.c index 4444b13418f0e0621d56d339ba4302c4d0ec2f29..78a00359bde3c01c84bff58bd376701c2cbaa328 100644 --- a/arch/loongarch/kernel/setup.c +++ b/arch/loongarch/kernel/setup.c @@ -12,6 +12,7 @@ */ #include #include +#include #include #include #include @@ -37,7 +38,6 @@ #include #include #include -#include #include #include #include @@ -87,7 +87,7 @@ const char *get_system_type(void) return "generic-loongson-machine"; } -void __init check_bugs(void) +void __init arch_cpu_finalize_init(void) { alternative_instructions(); } diff --git a/arch/loongarch/kernel/signal.c b/arch/loongarch/kernel/signal.c index 8f5b7986374b52afc237853cc743a61695d079ac..ceb899366c0a7b2ba2793e8631792f8aaaa03ab3 100644 --- a/arch/loongarch/kernel/signal.c +++ b/arch/loongarch/kernel/signal.c @@ -50,6 +50,14 @@ extern asmlinkage int _save_fp_context(void __user *fpregs, void __user *fcc, void __user *csr); extern asmlinkage int _restore_fp_context(void __user *fpregs, void __user *fcc, void __user *csr); +extern asmlinkage int +_save_lsx_context(void __user *fpregs, void __user *fcc, void __user *fcsr); +extern asmlinkage int +_restore_lsx_context(void __user *fpregs, void __user *fcc, void __user *fcsr); +extern asmlinkage int +_save_lasx_context(void __user *fpregs, void __user *fcc, void __user *fcsr); +extern asmlinkage int +_restore_lasx_context(void __user *fpregs, void __user *fcc, void __user *fcsr); struct rt_sigframe { struct siginfo rs_info; @@ -65,6 +73,8 @@ struct extctx_layout { unsigned long size; unsigned int flags; struct _ctx_layout fpu; + struct _ctx_layout lsx; + struct _ctx_layout lasx; struct _ctx_layout end; }; @@ -115,6 +125,96 @@ static int copy_fpu_from_sigcontext(struct fpu_context __user *ctx) return err; } +static int copy_lsx_to_sigcontext(struct lsx_context __user *ctx) +{ + int i; + int err = 0; + uint64_t __user *regs = (uint64_t *)&ctx->regs; + uint64_t __user *fcc = &ctx->fcc; + uint32_t __user *fcsr = &ctx->fcsr; + + for (i = 0; i < NUM_FPU_REGS; i++) { + err |= __put_user(get_fpr64(¤t->thread.fpu.fpr[i], 0), + ®s[2*i]); + err |= __put_user(get_fpr64(¤t->thread.fpu.fpr[i], 1), + ®s[2*i+1]); + } + err |= __put_user(current->thread.fpu.fcc, fcc); + err |= __put_user(current->thread.fpu.fcsr, fcsr); + + return err; +} + +static int copy_lsx_from_sigcontext(struct lsx_context __user *ctx) +{ + int i; + int err = 0; + u64 fpr_val; + uint64_t __user *regs = (uint64_t *)&ctx->regs; + uint64_t __user *fcc = &ctx->fcc; + uint32_t __user *fcsr = &ctx->fcsr; + + for (i = 0; i < NUM_FPU_REGS; i++) { + err |= __get_user(fpr_val, ®s[2*i]); + set_fpr64(¤t->thread.fpu.fpr[i], 0, fpr_val); + err |= __get_user(fpr_val, ®s[2*i+1]); + set_fpr64(¤t->thread.fpu.fpr[i], 1, fpr_val); + } + err |= __get_user(current->thread.fpu.fcc, fcc); + err |= __get_user(current->thread.fpu.fcsr, fcsr); + + return err; +} + +static int copy_lasx_to_sigcontext(struct lasx_context __user *ctx) +{ + int i; + int err = 0; + uint64_t __user *regs = (uint64_t *)&ctx->regs; + uint64_t __user *fcc = &ctx->fcc; + uint32_t __user *fcsr = &ctx->fcsr; + + for (i = 0; i < NUM_FPU_REGS; i++) { + err |= __put_user(get_fpr64(¤t->thread.fpu.fpr[i], 0), + ®s[4*i]); + err |= __put_user(get_fpr64(¤t->thread.fpu.fpr[i], 1), + ®s[4*i+1]); + err |= __put_user(get_fpr64(¤t->thread.fpu.fpr[i], 2), + ®s[4*i+2]); + err |= __put_user(get_fpr64(¤t->thread.fpu.fpr[i], 3), + ®s[4*i+3]); + } + err |= __put_user(current->thread.fpu.fcc, fcc); + err |= __put_user(current->thread.fpu.fcsr, fcsr); + + return err; +} + +static int copy_lasx_from_sigcontext(struct lasx_context __user *ctx) +{ + int i; + int err = 0; + u64 fpr_val; + uint64_t __user *regs = (uint64_t *)&ctx->regs; + uint64_t __user *fcc = &ctx->fcc; + uint32_t __user *fcsr = &ctx->fcsr; + + for (i = 0; i < NUM_FPU_REGS; i++) { + err |= __get_user(fpr_val, ®s[4*i]); + set_fpr64(¤t->thread.fpu.fpr[i], 0, fpr_val); + err |= __get_user(fpr_val, ®s[4*i+1]); + set_fpr64(¤t->thread.fpu.fpr[i], 1, fpr_val); + err |= __get_user(fpr_val, ®s[4*i+2]); + set_fpr64(¤t->thread.fpu.fpr[i], 2, fpr_val); + err |= __get_user(fpr_val, ®s[4*i+3]); + set_fpr64(¤t->thread.fpu.fpr[i], 3, fpr_val); + } + err |= __get_user(current->thread.fpu.fcc, fcc); + err |= __get_user(current->thread.fpu.fcsr, fcsr); + + return err; +} + /* * Wrappers for the assembly _{save,restore}_fp_context functions. */ @@ -136,6 +236,42 @@ static int restore_hw_fpu_context(struct fpu_context __user *ctx) return _restore_fp_context(regs, fcc, fcsr); } +static int save_hw_lsx_context(struct lsx_context __user *ctx) +{ + uint64_t __user *regs = (uint64_t *)&ctx->regs; + uint64_t __user *fcc = &ctx->fcc; + uint32_t __user *fcsr = &ctx->fcsr; + + return _save_lsx_context(regs, fcc, fcsr); +} + +static int restore_hw_lsx_context(struct lsx_context __user *ctx) +{ + uint64_t __user *regs = (uint64_t *)&ctx->regs; + uint64_t __user *fcc = &ctx->fcc; + uint32_t __user *fcsr = &ctx->fcsr; + + return _restore_lsx_context(regs, fcc, fcsr); +} + +static int save_hw_lasx_context(struct lasx_context __user *ctx) +{ + uint64_t __user *regs = (uint64_t *)&ctx->regs; + uint64_t __user *fcc = &ctx->fcc; + uint32_t __user *fcsr = &ctx->fcsr; + + return _save_lasx_context(regs, fcc, fcsr); +} + +static int restore_hw_lasx_context(struct lasx_context __user *ctx) +{ + uint64_t __user *regs = (uint64_t *)&ctx->regs; + uint64_t __user *fcc = &ctx->fcc; + uint32_t __user *fcsr = &ctx->fcsr; + + return _restore_lasx_context(regs, fcc, fcsr); +} + static int fcsr_pending(unsigned int __user *fcsr) { int err, sig = 0; @@ -227,6 +363,162 @@ static int protected_restore_fpu_context(struct extctx_layout *extctx) return err ?: sig; } +static int protected_save_lsx_context(struct extctx_layout *extctx) +{ + int err = 0; + struct sctx_info __user *info = extctx->lsx.addr; + struct lsx_context __user *lsx_ctx = (struct lsx_context *)get_ctx_through_ctxinfo(info); + uint64_t __user *regs = (uint64_t *)&lsx_ctx->regs; + uint64_t __user *fcc = &lsx_ctx->fcc; + uint32_t __user *fcsr = &lsx_ctx->fcsr; + + while (1) { + lock_fpu_owner(); + if (is_lsx_enabled()) + err = save_hw_lsx_context(lsx_ctx); + else { + if (is_fpu_owner()) + save_fp(current); + err = copy_lsx_to_sigcontext(lsx_ctx); + } + unlock_fpu_owner(); + + err |= __put_user(LSX_CTX_MAGIC, &info->magic); + err |= __put_user(extctx->lsx.size, &info->size); + + if (likely(!err)) + break; + /* Touch the LSX context and try again */ + err = __put_user(0, ®s[0]) | + __put_user(0, ®s[32*2-1]) | + __put_user(0, fcc) | + __put_user(0, fcsr); + if (err) + return err; /* really bad sigcontext */ + } + + return err; +} + +static int protected_restore_lsx_context(struct extctx_layout *extctx) +{ + int err = 0, sig = 0, tmp __maybe_unused; + struct sctx_info __user *info = extctx->lsx.addr; + struct lsx_context __user *lsx_ctx = (struct lsx_context *)get_ctx_through_ctxinfo(info); + uint64_t __user *regs = (uint64_t *)&lsx_ctx->regs; + uint64_t __user *fcc = &lsx_ctx->fcc; + uint32_t __user *fcsr = &lsx_ctx->fcsr; + + err = sig = fcsr_pending(fcsr); + if (err < 0) + return err; + + while (1) { + lock_fpu_owner(); + if (is_lsx_enabled()) + err = restore_hw_lsx_context(lsx_ctx); + else { + err = copy_lsx_from_sigcontext(lsx_ctx); + if (is_fpu_owner()) + restore_fp(current); + } + unlock_fpu_owner(); + + if (likely(!err)) + break; + /* Touch the LSX context and try again */ + err = __get_user(tmp, ®s[0]) | + __get_user(tmp, ®s[32*2-1]) | + __get_user(tmp, fcc) | + __get_user(tmp, fcsr); + if (err) + break; /* really bad sigcontext */ + } + + return err ?: sig; +} + +static int protected_save_lasx_context(struct extctx_layout *extctx) +{ + int err = 0; + struct sctx_info __user *info = extctx->lasx.addr; + struct lasx_context __user *lasx_ctx = + (struct lasx_context *)get_ctx_through_ctxinfo(info); + uint64_t __user *regs = (uint64_t *)&lasx_ctx->regs; + uint64_t __user *fcc = &lasx_ctx->fcc; + uint32_t __user *fcsr = &lasx_ctx->fcsr; + + while (1) { + lock_fpu_owner(); + if (is_lasx_enabled()) + err = save_hw_lasx_context(lasx_ctx); + else { + if (is_lsx_enabled()) + save_lsx(current); + else if (is_fpu_owner()) + save_fp(current); + err = copy_lasx_to_sigcontext(lasx_ctx); + } + unlock_fpu_owner(); + + err |= __put_user(LASX_CTX_MAGIC, &info->magic); + err |= __put_user(extctx->lasx.size, &info->size); + + if (likely(!err)) + break; + /* Touch the LASX context and try again */ + err = __put_user(0, ®s[0]) | + __put_user(0, ®s[32*4-1]) | + __put_user(0, fcc) | + __put_user(0, fcsr); + if (err) + return err; /* really bad sigcontext */ + } + + return err; +} + +static int protected_restore_lasx_context(struct extctx_layout *extctx) +{ + int err = 0, sig = 0, tmp __maybe_unused; + struct sctx_info __user *info = extctx->lasx.addr; + struct lasx_context __user *lasx_ctx = + (struct lasx_context *)get_ctx_through_ctxinfo(info); + uint64_t __user *regs = (uint64_t *)&lasx_ctx->regs; + uint64_t __user *fcc = &lasx_ctx->fcc; + uint32_t __user *fcsr = &lasx_ctx->fcsr; + + err = sig = fcsr_pending(fcsr); + if (err < 0) + return err; + + while (1) { + lock_fpu_owner(); + if (is_lasx_enabled()) + err = restore_hw_lasx_context(lasx_ctx); + else { + err = copy_lasx_from_sigcontext(lasx_ctx); + if (is_lsx_enabled()) + restore_lsx(current); + else if (is_fpu_owner()) + restore_fp(current); + } + unlock_fpu_owner(); + + if (likely(!err)) + break; + /* Touch the LASX context and try again */ + err = __get_user(tmp, ®s[0]) | + __get_user(tmp, ®s[32*4-1]) | + __get_user(tmp, fcc) | + __get_user(tmp, fcsr); + if (err) + break; /* really bad sigcontext */ + } + + return err ?: sig; +} + static int setup_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, struct extctx_layout *extctx) { @@ -240,7 +532,11 @@ static int setup_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, for (i = 1; i < 32; i++) err |= __put_user(regs->regs[i], &sc->sc_regs[i]); - if (extctx->fpu.addr) + if (extctx->lasx.addr) + err |= protected_save_lasx_context(extctx); + else if (extctx->lsx.addr) + err |= protected_save_lsx_context(extctx); + else if (extctx->fpu.addr) err |= protected_save_fpu_context(extctx); /* Set the "end" magic */ @@ -274,6 +570,20 @@ static int parse_extcontext(struct sigcontext __user *sc, struct extctx_layout * extctx->fpu.addr = info; break; + case LSX_CTX_MAGIC: + if (size < (sizeof(struct sctx_info) + + sizeof(struct lsx_context))) + goto invalid; + extctx->lsx.addr = info; + break; + + case LASX_CTX_MAGIC: + if (size < (sizeof(struct sctx_info) + + sizeof(struct lasx_context))) + goto invalid; + extctx->lasx.addr = info; + break; + default: goto invalid; } @@ -319,7 +629,11 @@ static int restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc for (i = 1; i < 32; i++) err |= __get_user(regs->regs[i], &sc->sc_regs[i]); - if (extctx.fpu.addr) + if (extctx.lasx.addr) + err |= protected_restore_lasx_context(&extctx); + else if (extctx.lsx.addr) + err |= protected_restore_lsx_context(&extctx); + else if (extctx.fpu.addr) err |= protected_restore_fpu_context(&extctx); bad: @@ -375,7 +689,13 @@ static unsigned long setup_extcontext(struct extctx_layout *extctx, unsigned lon extctx->size += extctx->end.size; if (extctx->flags & SC_USED_FP) { - if (cpu_has_fpu) + if (cpu_has_lasx && thread_lasx_context_live()) + new_sp = extframe_alloc(extctx, &extctx->lasx, + sizeof(struct lasx_context), LASX_CTX_ALIGN, new_sp); + else if (cpu_has_lsx && thread_lsx_context_live()) + new_sp = extframe_alloc(extctx, &extctx->lsx, + sizeof(struct lsx_context), LSX_CTX_ALIGN, new_sp); + else if (cpu_has_fpu) new_sp = extframe_alloc(extctx, &extctx->fpu, sizeof(struct fpu_context), FPU_CTX_ALIGN, new_sp); } diff --git a/arch/loongarch/kernel/smp.c b/arch/loongarch/kernel/smp.c index ed167e244cdae080be673a47df0e87c9c573ee16..8ea1bbcf13a7e3287e50ba7366ef2151aad72277 100644 --- a/arch/loongarch/kernel/smp.c +++ b/arch/loongarch/kernel/smp.c @@ -8,6 +8,7 @@ * Copyright (C) 2000, 2001 Silicon Graphics, Inc. * Copyright (C) 2000, 2001, 2003 Broadcom Corporation */ +#include #include #include #include @@ -37,10 +38,6 @@ EXPORT_SYMBOL(__cpu_number_map); int __cpu_logical_map[NR_CPUS]; /* Map logical to physical */ EXPORT_SYMBOL(__cpu_logical_map); -/* Number of threads (siblings) per CPU core */ -int smp_num_siblings = 1; -EXPORT_SYMBOL(smp_num_siblings); - /* Representing the threads (siblings) of each logical CPU */ cpumask_t cpu_sibling_map[NR_CPUS] __read_mostly; EXPORT_SYMBOL(cpu_sibling_map); @@ -118,7 +115,7 @@ static u32 ipi_read_clear(int cpu) action = iocsr_read32(LOONGARCH_IOCSR_IPI_STATUS); /* Clear the ipi register to clear the interrupt */ iocsr_write32(action, LOONGARCH_IOCSR_IPI_CLEAR); - smp_mb(); + wbflush(); return action; } @@ -210,6 +207,7 @@ static void __init fdt_smp_setup(void) } loongson_sysconf.nr_cpus = num_processors; + set_bit(0, &(loongson_sysconf.cores_io_master)); #endif } @@ -228,9 +226,12 @@ void __init loongson_prepare_cpus(unsigned int max_cpus) { int i = 0; + parse_acpi_topology(); + for (i = 0; i < loongson_sysconf.nr_cpus; i++) { set_cpu_present(i, true); csr_mail_send(0, __cpu_logical_map[i], 0); + cpu_data[i].global_id = __cpu_logical_map[i]; } per_cpu(cpu_state, smp_processor_id()) = CPU_ONLINE; @@ -271,10 +272,10 @@ void loongson_init_secondary(void) numa_add_cpu(cpu); #endif per_cpu(cpu_state, cpu) = CPU_ONLINE; - cpu_data[cpu].core = - cpu_logical_map(cpu) % loongson_sysconf.cores_per_package; cpu_data[cpu].package = cpu_logical_map(cpu) / loongson_sysconf.cores_per_package; + cpu_data[cpu].core = pptt_enabled ? cpu_data[cpu].core : + cpu_logical_map(cpu) % loongson_sysconf.cores_per_package; } void loongson_smp_finish(void) @@ -380,14 +381,10 @@ static inline void set_cpu_sibling_map(int cpu) cpumask_set_cpu(cpu, &cpu_sibling_setup_map); - if (smp_num_siblings <= 1) - cpumask_set_cpu(cpu, &cpu_sibling_map[cpu]); - else { - for_each_cpu(i, &cpu_sibling_setup_map) { - if (cpus_are_siblings(cpu, i)) { - cpumask_set_cpu(i, &cpu_sibling_map[cpu]); - cpumask_set_cpu(cpu, &cpu_sibling_map[i]); - } + for_each_cpu(i, &cpu_sibling_setup_map) { + if (cpus_are_siblings(cpu, i)) { + cpumask_set_cpu(i, &cpu_sibling_map[cpu]); + cpumask_set_cpu(cpu, &cpu_sibling_map[i]); } } } diff --git a/arch/loongarch/kernel/time.c b/arch/loongarch/kernel/time.c index f377e50f3c66c83e8d084281380f1c35652bd553..c189e03cd5da84b6ebcde9533560d66f98010b5e 100644 --- a/arch/loongarch/kernel/time.c +++ b/arch/loongarch/kernel/time.c @@ -190,9 +190,9 @@ static u64 read_const_counter(struct clocksource *clk) return drdtime(); } -static u64 native_sched_clock(void) +static noinstr u64 sched_clock_read(void) { - return read_const_counter(NULL); + return drdtime(); } static struct clocksource clocksource_const = { @@ -211,7 +211,7 @@ int __init constant_clocksource_init(void) res = clocksource_register_hz(&clocksource_const, freq); - sched_clock_register(native_sched_clock, 64, freq); + sched_clock_register(sched_clock_read, 64, freq); pr_info("Constant clock source device register\n"); diff --git a/arch/loongarch/kernel/traps.c b/arch/loongarch/kernel/traps.c index 8db26e4ca447f5c4b123f8dda60fc9500192a94f..8fb5e7a77145078ab3687d1e687ac00f01104663 100644 --- a/arch/loongarch/kernel/traps.c +++ b/arch/loongarch/kernel/traps.c @@ -47,6 +47,7 @@ #include #include #include +#include #include "access-helper.h" @@ -689,7 +690,6 @@ asmlinkage void noinstr do_bp(struct pt_regs *regs) if (regs->csr_prmd & CSR_PRMD_PIE) local_irq_enable(); - current->thread.trap_nr = read_csr_excode(); if (__get_inst(&opcode, (u32 *)era, user)) goto out_sigsegv; @@ -711,18 +711,17 @@ asmlinkage void noinstr do_bp(struct pt_regs *regs) else break; case BRK_UPROBE_BP: - if (notify_die(DIE_UPROBE, "Uprobe", regs, bcode, - current->thread.trap_nr, SIGTRAP) == NOTIFY_STOP) + if (uprobe_breakpoint_handler(regs)) goto out; else break; case BRK_UPROBE_XOLBP: - if (notify_die(DIE_UPROBE_XOL, "Uprobe_XOL", regs, bcode, - current->thread.trap_nr, SIGTRAP) == NOTIFY_STOP) + if (uprobe_singlestep_handler(regs)) goto out; else break; default: + current->thread.trap_nr = read_csr_excode(); if (notify_die(DIE_TRAP, "Break", regs, bcode, current->thread.trap_nr, SIGTRAP) == NOTIFY_STOP) goto out; @@ -852,12 +851,67 @@ static void init_restore_fp(void) BUG_ON(!is_fp_enabled()); } +static void init_restore_lsx(void) +{ + enable_lsx(); + + if (!thread_lsx_context_live()) { + /* First time LSX context user */ + init_restore_fp(); + init_lsx_upper(); + set_thread_flag(TIF_LSX_CTX_LIVE); + } else { + if (!is_simd_owner()) { + if (is_fpu_owner()) { + restore_lsx_upper(current); + } else { + __own_fpu(); + restore_lsx(current); + } + } + } + + set_thread_flag(TIF_USEDSIMD); + + BUG_ON(!is_fp_enabled()); + BUG_ON(!is_lsx_enabled()); +} + +static void init_restore_lasx(void) +{ + enable_lasx(); + + if (!thread_lasx_context_live()) { + /* First time LASX context user */ + init_restore_lsx(); + init_lasx_upper(); + set_thread_flag(TIF_LASX_CTX_LIVE); + } else { + if (is_fpu_owner() || is_simd_owner()) { + init_restore_lsx(); + restore_lasx_upper(current); + } else { + __own_fpu(); + enable_lsx(); + restore_lasx(current); + } + } + + set_thread_flag(TIF_USEDSIMD); + + BUG_ON(!is_fp_enabled()); + BUG_ON(!is_lsx_enabled()); + BUG_ON(!is_lasx_enabled()); +} + asmlinkage void noinstr do_fpu(struct pt_regs *regs) { irqentry_state_t state = irqentry_enter(regs); local_irq_enable(); die_if_kernel("do_fpu invoked from kernel context!", regs); + BUG_ON(is_lsx_enabled()); + BUG_ON(is_lasx_enabled()); preempt_disable(); init_restore_fp(); @@ -872,9 +926,20 @@ asmlinkage void noinstr do_lsx(struct pt_regs *regs) irqentry_state_t state = irqentry_enter(regs); local_irq_enable(); - force_sig(SIGILL); - local_irq_disable(); + if (!cpu_has_lsx) { + force_sig(SIGILL); + goto out; + } + die_if_kernel("do_lsx invoked from kernel context!", regs); + BUG_ON(is_lasx_enabled()); + + preempt_disable(); + init_restore_lsx(); + preempt_enable(); + +out: + local_irq_disable(); irqentry_exit(regs, state); } @@ -883,9 +948,19 @@ asmlinkage void noinstr do_lasx(struct pt_regs *regs) irqentry_state_t state = irqentry_enter(regs); local_irq_enable(); - force_sig(SIGILL); - local_irq_disable(); + if (!cpu_has_lasx) { + force_sig(SIGILL); + goto out; + } + + die_if_kernel("do_lasx invoked from kernel context!", regs); + preempt_disable(); + init_restore_lasx(); + preempt_enable(); + +out: + local_irq_disable(); irqentry_exit(regs, state); } @@ -924,7 +999,7 @@ asmlinkage void cache_parity_error(void) /* For the moment, report the problem and hang. */ pr_err("Cache error exception:\n"); pr_err("csr_merrctl == %08x\n", csr_read32(LOONGARCH_CSR_MERRCTL)); - pr_err("csr_merrera == %016llx\n", csr_read64(LOONGARCH_CSR_MERRERA)); + pr_err("csr_merrera == %016lx\n", csr_read64(LOONGARCH_CSR_MERRERA)); panic("Can't handle the cache error!"); } diff --git a/arch/loongarch/kernel/unaligned.c b/arch/loongarch/kernel/unaligned.c index 85fae3d2d71aebc5691686cfe67214561fd8d6fe..3abf163dda056b681494a74916570866a6f1ec7b 100644 --- a/arch/loongarch/kernel/unaligned.c +++ b/arch/loongarch/kernel/unaligned.c @@ -485,8 +485,6 @@ static int __init debugfs_unaligned(void) struct dentry *d; d = debugfs_create_dir("loongarch", NULL); - if (IS_ERR_OR_NULL(d)) - return -ENOMEM; debugfs_create_u32("unaligned_instructions_user", S_IRUGO, d, &unaligned_instructions_user); diff --git a/arch/loongarch/kernel/uprobes.c b/arch/loongarch/kernel/uprobes.c new file mode 100644 index 0000000000000000000000000000000000000000..87abc7137b738e185a0767882ab4d92f9e7531c4 --- /dev/null +++ b/arch/loongarch/kernel/uprobes.c @@ -0,0 +1,153 @@ +// SPDX-License-Identifier: GPL-2.0-only +#include +#include +#include +#include +#include + +#define UPROBE_TRAP_NR UINT_MAX + +int arch_uprobe_analyze_insn(struct arch_uprobe *auprobe, + struct mm_struct *mm, unsigned long addr) +{ + int idx; + union loongarch_instruction insn; + + if (addr & 0x3) + return -EILSEQ; + + for (idx = ARRAY_SIZE(auprobe->insn) - 1; idx >= 0; idx--) { + insn.word = auprobe->insn[idx]; + if (insns_not_supported(insn)) + return -EINVAL; + } + + if (insns_need_simulation(insn)) { + auprobe->ixol[0] = larch_insn_gen_nop(); + auprobe->simulate = true; + } else { + auprobe->ixol[0] = auprobe->insn[0]; + auprobe->simulate = false; + } + + auprobe->ixol[1] = UPROBE_XOLBP_INSN; + + return 0; +} + +int arch_uprobe_pre_xol(struct arch_uprobe *auprobe, struct pt_regs *regs) +{ + struct uprobe_task *utask = current->utask; + + utask->autask.saved_trap_nr = current->thread.trap_nr; + current->thread.trap_nr = UPROBE_TRAP_NR; + instruction_pointer_set(regs, utask->xol_vaddr); + user_enable_single_step(current); + + return 0; +} + +int arch_uprobe_post_xol(struct arch_uprobe *auprobe, struct pt_regs *regs) +{ + struct uprobe_task *utask = current->utask; + + WARN_ON_ONCE(current->thread.trap_nr != UPROBE_TRAP_NR); + current->thread.trap_nr = utask->autask.saved_trap_nr; + + if (auprobe->simulate) + instruction_pointer_set(regs, auprobe->resume_era); + else + instruction_pointer_set(regs, utask->vaddr + LOONGARCH_INSN_SIZE); + + user_disable_single_step(current); + + return 0; +} + +void arch_uprobe_abort_xol(struct arch_uprobe *auprobe, struct pt_regs *regs) +{ + struct uprobe_task *utask = current->utask; + + current->thread.trap_nr = utask->autask.saved_trap_nr; + instruction_pointer_set(regs, utask->vaddr); + user_disable_single_step(current); +} + +bool arch_uprobe_xol_was_trapped(struct task_struct *t) +{ + if (t->thread.trap_nr != UPROBE_TRAP_NR) + return true; + + return false; +} + +bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs) +{ + union loongarch_instruction insn; + + if (!auprobe->simulate) + return false; + + insn.word = auprobe->insn[0]; + arch_simulate_insn(insn, regs); + auprobe->resume_era = regs->csr_era; + + return true; +} + +unsigned long arch_uretprobe_hijack_return_addr(unsigned long trampoline_vaddr, + struct pt_regs *regs) +{ + unsigned long ra = regs->regs[1]; + + regs->regs[1] = trampoline_vaddr; + + return ra; +} + +bool arch_uretprobe_is_alive(struct return_instance *ret, + enum rp_check ctx, struct pt_regs *regs) +{ + if (ctx == RP_CHECK_CHAIN_CALL) + return regs->regs[3] <= ret->stack; + else + return regs->regs[3] < ret->stack; +} + +int arch_uprobe_exception_notify(struct notifier_block *self, + unsigned long val, void *data) +{ + return NOTIFY_DONE; +} + +bool uprobe_breakpoint_handler(struct pt_regs *regs) +{ + if (uprobe_pre_sstep_notifier(regs)) + return true; + + return false; +} + +bool uprobe_singlestep_handler(struct pt_regs *regs) +{ + if (uprobe_post_sstep_notifier(regs)) + return true; + + return false; +} + +unsigned long uprobe_get_swbp_addr(struct pt_regs *regs) +{ + return instruction_pointer(regs); +} + +void arch_uprobe_copy_ixol(struct page *page, unsigned long vaddr, + void *src, unsigned long len) +{ + void *kaddr = kmap_local_page(page); + void *dst = kaddr + (vaddr & ~PAGE_MASK); + + memcpy(dst, src, len); + flush_icache_range((unsigned long)dst, (unsigned long)dst + len); + kunmap_local(kaddr); +} diff --git a/arch/loongarch/kernel/vdso.c b/arch/loongarch/kernel/vdso.c index eaebd2e0f725652bbc60b5ffbfae93b067a7f01f..14941e4be66d8273adaebb7de388e8782e07a892 100644 --- a/arch/loongarch/kernel/vdso.c +++ b/arch/loongarch/kernel/vdso.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -26,12 +27,17 @@ extern char vdso_start[], vdso_end[]; /* Kernel-provided data used by the VDSO. */ static union { - u8 page[VDSO_DATA_SIZE]; + u8 page[PAGE_SIZE]; + struct vdso_data data[CS_BASES]; +} generic_vdso_data __page_aligned_data; + +static union { + u8 page[LOONGARCH_VDSO_DATA_SIZE]; struct loongarch_vdso_data vdata; } loongarch_vdso_data __page_aligned_data; static struct page *vdso_pages[] = { NULL }; -struct vdso_data *vdso_data = loongarch_vdso_data.vdata.data; +struct vdso_data *vdso_data = generic_vdso_data.data; struct vdso_pcpu_data *vdso_pdata = loongarch_vdso_data.vdata.pdata; static int vdso_mremap(const struct vm_special_mapping *sm, struct vm_area_struct *new_vma) @@ -41,6 +47,43 @@ static int vdso_mremap(const struct vm_special_mapping *sm, struct vm_area_struc return 0; } +static vm_fault_t vvar_fault(const struct vm_special_mapping *sm, + struct vm_area_struct *vma, struct vm_fault *vmf) +{ + unsigned long pfn; + struct page *timens_page = find_timens_vvar_page(vma); + + switch (vmf->pgoff) { + case VVAR_GENERIC_PAGE_OFFSET: + if (!timens_page) + pfn = sym_to_pfn(vdso_data); + else + pfn = page_to_pfn(timens_page); + break; +#ifdef CONFIG_TIME_NS + case VVAR_TIMENS_PAGE_OFFSET: + /* + * If a task belongs to a time namespace then a namespace specific + * VVAR is mapped with the VVAR_GENERIC_PAGE_OFFSET and the real + * VVAR page is mapped with the VVAR_TIMENS_PAGE_OFFSET offset. + * See also the comment near timens_setup_vdso_data(). + */ + if (!timens_page) + return VM_FAULT_SIGBUS; + else + pfn = sym_to_pfn(vdso_data); + break; +#endif /* CONFIG_TIME_NS */ + case VVAR_LOONGARCH_PAGES_START ... VVAR_LOONGARCH_PAGES_END: + pfn = sym_to_pfn(&loongarch_vdso_data) + vmf->pgoff - VVAR_LOONGARCH_PAGES_START; + break; + default: + return VM_FAULT_SIGBUS; + } + + return vmf_insert_pfn(vma, vmf->address, pfn); +} + struct loongarch_vdso_info vdso_info = { .vdso = vdso_start, .size = PAGE_SIZE, @@ -51,6 +94,7 @@ struct loongarch_vdso_info vdso_info = { }, .data_mapping = { .name = "[vvar]", + .fault = vvar_fault, }, .offset_sigreturn = vdso_offset_sigreturn, }; @@ -73,6 +117,37 @@ static int __init init_vdso(void) } subsys_initcall(init_vdso); +#ifdef CONFIG_TIME_NS +struct vdso_data *arch_get_vdso_data(void *vvar_page) +{ + return (struct vdso_data *)(vvar_page); +} + +/* + * The vvar mapping contains data for a specific time namespace, so when a + * task changes namespace we must unmap its vvar data for the old namespace. + * Subsequent faults will map in data for the new namespace. + * + * For more details see timens_setup_vdso_data(). + */ +int vdso_join_timens(struct task_struct *task, struct time_namespace *ns) +{ + struct mm_struct *mm = task->mm; + struct vm_area_struct *vma; + + VMA_ITERATOR(vmi, mm, 0); + + mmap_read_lock(mm); + for_each_vma(vmi, vma) { + if (vma_is_special_mapping(vma, &vdso_info.data_mapping)) + zap_vma_pages(vma); + } + mmap_read_unlock(mm); + + return 0; +} +#endif + static unsigned long vdso_base(void) { unsigned long base = STACK_TOP; @@ -88,7 +163,7 @@ static unsigned long vdso_base(void) int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp) { int ret; - unsigned long vvar_size, size, data_addr, vdso_addr; + unsigned long size, data_addr, vdso_addr; struct mm_struct *mm = current->mm; struct vm_area_struct *vma; struct loongarch_vdso_info *info = current->thread.vdso; @@ -100,32 +175,23 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp) * Determine total area size. This includes the VDSO data itself * and the data pages. */ - vvar_size = VDSO_DATA_SIZE; - size = vvar_size + info->size; + size = VVAR_SIZE + info->size; data_addr = get_unmapped_area(NULL, vdso_base(), size, 0, 0); if (IS_ERR_VALUE(data_addr)) { ret = data_addr; goto out; } - vdso_addr = data_addr + VDSO_DATA_SIZE; - vma = _install_special_mapping(mm, data_addr, vvar_size, - VM_READ | VM_MAYREAD, + vma = _install_special_mapping(mm, data_addr, VVAR_SIZE, + VM_READ | VM_MAYREAD | VM_PFNMAP, &info->data_mapping); if (IS_ERR(vma)) { ret = PTR_ERR(vma); goto out; } - /* Map VDSO data page. */ - ret = remap_pfn_range(vma, data_addr, - virt_to_phys(&loongarch_vdso_data) >> PAGE_SHIFT, - vvar_size, PAGE_READONLY); - if (ret) - goto out; - - /* Map VDSO code page. */ + vdso_addr = data_addr + VVAR_SIZE; vma = _install_special_mapping(mm, vdso_addr, info->size, VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC, &info->code_mapping); diff --git a/arch/loongarch/kernel/vmlinux.lds.S b/arch/loongarch/kernel/vmlinux.lds.S index 0c7b041be9d8de9ef82e878fa0904c88818044f0..b1686afcf876663c99e010c40ec84f44d8d55a88 100644 --- a/arch/loongarch/kernel/vmlinux.lds.S +++ b/arch/loongarch/kernel/vmlinux.lds.S @@ -136,6 +136,15 @@ SECTIONS DWARF_DEBUG ELF_DETAILS +#ifdef CONFIG_EFI_STUB + /* header symbols */ + _kernel_asize = _end - _text; + _kernel_fsize = _edata - _text; + _kernel_vsize = _end - __initdata_begin; + _kernel_rsize = _edata - __initdata_begin; + _kernel_offset = kernel_offset - _text; +#endif + .gptab.sdata : { *(.gptab.data) *(.gptab.sdata) diff --git a/arch/loongarch/lib/dump_tlb.c b/arch/loongarch/lib/dump_tlb.c index c2cc7ce343c9bb3c914bb531bd44bb80d79be425..0b886a6e260fafa75a1098e037ece7af29c71c17 100644 --- a/arch/loongarch/lib/dump_tlb.c +++ b/arch/loongarch/lib/dump_tlb.c @@ -20,9 +20,9 @@ void dump_tlb_regs(void) pr_info("Index : 0x%0x\n", read_csr_tlbidx()); pr_info("PageSize : 0x%0x\n", read_csr_pagesize()); - pr_info("EntryHi : 0x%0*llx\n", field, read_csr_entryhi()); - pr_info("EntryLo0 : 0x%0*llx\n", field, read_csr_entrylo0()); - pr_info("EntryLo1 : 0x%0*llx\n", field, read_csr_entrylo1()); + pr_info("EntryHi : 0x%0*lx\n", field, read_csr_entryhi()); + pr_info("EntryLo0 : 0x%0*lx\n", field, read_csr_entrylo0()); + pr_info("EntryLo1 : 0x%0*lx\n", field, read_csr_entrylo1()); } static void dump_tlb(int first, int last) diff --git a/arch/loongarch/mm/fault.c b/arch/loongarch/mm/fault.c index 449087bd589d339dba1b27f66cc07f170085cff7..da5b6d518cdb1d6c5ec550083f52f588ccf29066 100644 --- a/arch/loongarch/mm/fault.c +++ b/arch/loongarch/mm/fault.c @@ -169,22 +169,18 @@ static void __kprobes __do_page_fault(struct pt_regs *regs, perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address); retry: - mmap_read_lock(mm); - vma = find_vma(mm, address); - if (!vma) - goto bad_area; - if (vma->vm_start <= address) - goto good_area; - if (!(vma->vm_flags & VM_GROWSDOWN)) - goto bad_area; - if (!expand_stack(vma, address)) - goto good_area; + vma = lock_mm_and_find_vma(mm, address, regs); + if (unlikely(!vma)) + goto bad_area_nosemaphore; + goto good_area; + /* * Something tried to access memory that isn't in our memory map.. * Fix it, but check if it's kernel or user first.. */ bad_area: mmap_read_unlock(mm); +bad_area_nosemaphore: do_sigsegv(regs, write, address, si_code); return; diff --git a/arch/loongarch/mm/tlb.c b/arch/loongarch/mm/tlb.c index 8bad6b0cff59b96b2ebdda34214fdc1e4758e27e..00bb563e3c89473f460113df9c55f8c860c48e8a 100644 --- a/arch/loongarch/mm/tlb.c +++ b/arch/loongarch/mm/tlb.c @@ -167,6 +167,9 @@ void __update_tlb(struct vm_area_struct *vma, unsigned long address, pte_t *ptep int idx; unsigned long flags; + if (cpu_has_ptw) + return; + /* * Handle debugger faulting in for debugee. */ @@ -222,6 +225,9 @@ static void setup_ptwalker(void) pwctl0 = pte_i | pte_w << 5 | pmd_i << 10 | pmd_w << 15 | pud_i << 20 | pud_w << 25; pwctl1 = pgd_i | pgd_w << 6; + if (cpu_has_ptw) + pwctl1 |= CSR_PWCTL1_PTW; + csr_write64(pwctl0, LOONGARCH_CSR_PWCTL0); csr_write64(pwctl1, LOONGARCH_CSR_PWCTL1); csr_write64((long)swapper_pg_dir, LOONGARCH_CSR_PGDH); @@ -264,10 +270,17 @@ void setup_tlb_handler(int cpu) if (cpu == 0) { memcpy((void *)tlbrentry, handle_tlb_refill, 0x80); local_flush_icache_range(tlbrentry, tlbrentry + 0x80); - set_handler(EXCCODE_TLBI * VECSIZE, handle_tlb_load, VECSIZE); - set_handler(EXCCODE_TLBL * VECSIZE, handle_tlb_load, VECSIZE); - set_handler(EXCCODE_TLBS * VECSIZE, handle_tlb_store, VECSIZE); - set_handler(EXCCODE_TLBM * VECSIZE, handle_tlb_modify, VECSIZE); + if (!cpu_has_ptw) { + set_handler(EXCCODE_TLBI * VECSIZE, handle_tlb_load, VECSIZE); + set_handler(EXCCODE_TLBL * VECSIZE, handle_tlb_load, VECSIZE); + set_handler(EXCCODE_TLBS * VECSIZE, handle_tlb_store, VECSIZE); + set_handler(EXCCODE_TLBM * VECSIZE, handle_tlb_modify, VECSIZE); + } else { + set_handler(EXCCODE_TLBI * VECSIZE, handle_tlb_load_ptw, VECSIZE); + set_handler(EXCCODE_TLBL * VECSIZE, handle_tlb_load_ptw, VECSIZE); + set_handler(EXCCODE_TLBS * VECSIZE, handle_tlb_store_ptw, VECSIZE); + set_handler(EXCCODE_TLBM * VECSIZE, handle_tlb_modify_ptw, VECSIZE); + } set_handler(EXCCODE_TLBNR * VECSIZE, handle_tlb_protect, VECSIZE); set_handler(EXCCODE_TLBNX * VECSIZE, handle_tlb_protect, VECSIZE); set_handler(EXCCODE_TLBPE * VECSIZE, handle_tlb_protect, VECSIZE); diff --git a/arch/loongarch/mm/tlbex.S b/arch/loongarch/mm/tlbex.S index 244e2f5aeee564c75c0459569caf4f879876cbe3..4ad78703de6f4c4a1a55bd9d73aa89181cbef9ee 100644 --- a/arch/loongarch/mm/tlbex.S +++ b/arch/loongarch/mm/tlbex.S @@ -184,12 +184,19 @@ tlb_huge_update_load: ertn nopage_tlb_load: - dbar 0 + dbar 0x700 csrrd ra, EXCEPTION_KS2 la_abs t0, tlb_do_page_fault_0 jr t0 SYM_FUNC_END(handle_tlb_load) +SYM_FUNC_START(handle_tlb_load_ptw) + csrwr t0, LOONGARCH_CSR_KS0 + csrwr t1, LOONGARCH_CSR_KS1 + la_abs t0, tlb_do_page_fault_0 + jr t0 +SYM_FUNC_END(handle_tlb_load_ptw) + SYM_FUNC_START(handle_tlb_store) csrwr t0, EXCEPTION_KS0 csrwr t1, EXCEPTION_KS1 @@ -333,12 +340,19 @@ tlb_huge_update_store: ertn nopage_tlb_store: - dbar 0 + dbar 0x700 csrrd ra, EXCEPTION_KS2 la_abs t0, tlb_do_page_fault_1 jr t0 SYM_FUNC_END(handle_tlb_store) +SYM_FUNC_START(handle_tlb_store_ptw) + csrwr t0, LOONGARCH_CSR_KS0 + csrwr t1, LOONGARCH_CSR_KS1 + la_abs t0, tlb_do_page_fault_1 + jr t0 +SYM_FUNC_END(handle_tlb_store_ptw) + SYM_FUNC_START(handle_tlb_modify) csrwr t0, EXCEPTION_KS0 csrwr t1, EXCEPTION_KS1 @@ -480,12 +494,19 @@ tlb_huge_update_modify: ertn nopage_tlb_modify: - dbar 0 + dbar 0x700 csrrd ra, EXCEPTION_KS2 la_abs t0, tlb_do_page_fault_1 jr t0 SYM_FUNC_END(handle_tlb_modify) +SYM_FUNC_START(handle_tlb_modify_ptw) + csrwr t0, LOONGARCH_CSR_KS0 + csrwr t1, LOONGARCH_CSR_KS1 + la_abs t0, tlb_do_page_fault_1 + jr t0 +SYM_FUNC_END(handle_tlb_modify_ptw) + SYM_FUNC_START(handle_tlb_refill) csrwr t0, LOONGARCH_CSR_TLBRSAVE csrrd t0, LOONGARCH_CSR_PGD diff --git a/arch/loongarch/power/suspend.c b/arch/loongarch/power/suspend.c index 5e19733e5e05f4397ad288d2acfd0e4c51284d65..166d9e06a64bdf1d52217d52ec0a00a53ce904fc 100644 --- a/arch/loongarch/power/suspend.c +++ b/arch/loongarch/power/suspend.c @@ -27,7 +27,7 @@ struct saved_registers { }; static struct saved_registers saved_regs; -static void arch_common_suspend(void) +void loongarch_common_suspend(void) { save_counter(); saved_regs.pgd = csr_read64(LOONGARCH_CSR_PGDL); @@ -40,7 +40,7 @@ static void arch_common_suspend(void) loongarch_suspend_addr = loongson_sysconf.suspend_addr; } -static void arch_common_resume(void) +void loongarch_common_resume(void) { sync_counter(); local_flush_tlb_all(); @@ -62,12 +62,12 @@ int loongarch_acpi_suspend(void) enable_gpe_wakeup(); enable_pci_wakeup(); - arch_common_suspend(); + loongarch_common_suspend(); /* processor specific suspend */ loongarch_suspend_enter(); - arch_common_resume(); + loongarch_common_resume(); return 0; } diff --git a/arch/loongarch/vdso/Makefile b/arch/loongarch/vdso/Makefile index 461240ab44365f2a1d75b9f870a7a5540c2036e5..a50308b6fc259082fb61e29e7b5b9fb99082fb83 100644 --- a/arch/loongarch/vdso/Makefile +++ b/arch/loongarch/vdso/Makefile @@ -12,16 +12,13 @@ ccflags-vdso := \ $(filter -E%,$(KBUILD_CFLAGS)) \ $(filter -march=%,$(KBUILD_CFLAGS)) \ $(filter -m%-float,$(KBUILD_CFLAGS)) \ + $(CLANG_FLAGS) \ -D__VDSO__ -ifeq ($(cc-name),clang) -ccflags-vdso += $(filter --target=%,$(KBUILD_CFLAGS)) -endif - cflags-vdso := $(ccflags-vdso) \ -isystem $(shell $(CC) -print-file-name=include) \ $(filter -W%,$(filter-out -Wa$(comma)%,$(KBUILD_CFLAGS))) \ - -O2 -g -fno-strict-aliasing -fno-common -fno-builtin -G0 \ + -O2 -g -fno-strict-aliasing -fno-common -fno-builtin \ -fno-stack-protector -fno-jump-tables -DDISABLE_BRANCH_PROFILING \ $(call cc-option, -fno-asynchronous-unwind-tables) \ $(call cc-option, -fno-stack-protector) diff --git a/arch/loongarch/vdso/vgetcpu.c b/arch/loongarch/vdso/vgetcpu.c index e02e775f53608119ccd32969398f8279634ea814..9e445be39763aebc75e9e97d77b40e14a018deea 100644 --- a/arch/loongarch/vdso/vgetcpu.c +++ b/arch/loongarch/vdso/vgetcpu.c @@ -21,7 +21,7 @@ static __always_inline int read_cpu_id(void) static __always_inline const struct vdso_pcpu_data *get_pcpu_data(void) { - return (struct vdso_pcpu_data *)(get_vdso_base() - VDSO_DATA_SIZE); + return (struct vdso_pcpu_data *)(get_vdso_data() + VVAR_LOONGARCH_PAGES_START * PAGE_SIZE); } extern diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig index 40198a1ebe274f62024b7c3943eb273ba3f34d43..dc792b321f1e9a6d2b3e8082a3711a7d44ca636c 100644 --- a/arch/m68k/Kconfig +++ b/arch/m68k/Kconfig @@ -4,6 +4,7 @@ config M68K default y select ARCH_32BIT_OFF_T select ARCH_HAS_BINFMT_FLAT + select ARCH_HAS_CPU_FINALIZE_INIT if MMU select ARCH_HAS_CURRENT_STACK_POINTER select ARCH_HAS_DMA_PREP_COHERENT if HAS_DMA && MMU && !COLDFIRE select ARCH_HAS_SYNC_DMA_FOR_DEVICE if HAS_DMA diff --git a/arch/m68k/configs/amiga_defconfig b/arch/m68k/configs/amiga_defconfig index b26469a65bc11ed45622096d42680b35ee310e44..4383ed85106335fd494b6d248f60fdc371d21e1b 100644 --- a/arch/m68k/configs/amiga_defconfig +++ b/arch/m68k/configs/amiga_defconfig @@ -41,8 +41,8 @@ CONFIG_MQ_IOSCHED_KYBER=m CONFIG_IOSCHED_BFQ=m # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set CONFIG_BINFMT_MISC=m -CONFIG_SLAB=y # CONFIG_COMPACTION is not set +CONFIG_DMAPOOL_TEST=m CONFIG_USERFAULTFD=y CONFIG_NET=y CONFIG_PACKET=y @@ -454,7 +454,6 @@ CONFIG_OCFS2_FS=m # CONFIG_OCFS2_DEBUG_MASKLOG is not set CONFIG_FANOTIFY=y CONFIG_QUOTA_NETLINK_INTERFACE=y -# CONFIG_PRINT_QUOTA_WARNING is not set CONFIG_AUTOFS_FS=m CONFIG_FUSE_FS=m CONFIG_CUSE=m diff --git a/arch/m68k/configs/apollo_defconfig b/arch/m68k/configs/apollo_defconfig index 944a49a129bedab08af9795f196b1168c2a47fed..ec0f9c9f9562147b7b87b4d866b1f7ad962d5f89 100644 --- a/arch/m68k/configs/apollo_defconfig +++ b/arch/m68k/configs/apollo_defconfig @@ -37,8 +37,8 @@ CONFIG_MQ_IOSCHED_KYBER=m CONFIG_IOSCHED_BFQ=m # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set CONFIG_BINFMT_MISC=m -CONFIG_SLAB=y # CONFIG_COMPACTION is not set +CONFIG_DMAPOOL_TEST=m CONFIG_USERFAULTFD=y CONFIG_NET=y CONFIG_PACKET=y @@ -411,7 +411,6 @@ CONFIG_OCFS2_FS=m # CONFIG_OCFS2_DEBUG_MASKLOG is not set CONFIG_FANOTIFY=y CONFIG_QUOTA_NETLINK_INTERFACE=y -# CONFIG_PRINT_QUOTA_WARNING is not set CONFIG_AUTOFS_FS=m CONFIG_FUSE_FS=m CONFIG_CUSE=m diff --git a/arch/m68k/configs/atari_defconfig b/arch/m68k/configs/atari_defconfig index a32dd884fcce236ae739f5138d7994246fc8ecfa..8656ae1f239e94ce28e5468b5bedfe5d59ee1c21 100644 --- a/arch/m68k/configs/atari_defconfig +++ b/arch/m68k/configs/atari_defconfig @@ -44,8 +44,8 @@ CONFIG_MQ_IOSCHED_KYBER=m CONFIG_IOSCHED_BFQ=m # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set CONFIG_BINFMT_MISC=m -CONFIG_SLAB=y # CONFIG_COMPACTION is not set +CONFIG_DMAPOOL_TEST=m CONFIG_USERFAULTFD=y CONFIG_NET=y CONFIG_PACKET=y @@ -431,7 +431,6 @@ CONFIG_OCFS2_FS=m # CONFIG_OCFS2_DEBUG_MASKLOG is not set CONFIG_FANOTIFY=y CONFIG_QUOTA_NETLINK_INTERFACE=y -# CONFIG_PRINT_QUOTA_WARNING is not set CONFIG_AUTOFS_FS=m CONFIG_FUSE_FS=m CONFIG_CUSE=m diff --git a/arch/m68k/configs/bvme6000_defconfig b/arch/m68k/configs/bvme6000_defconfig index 23b7805309bd4407508a43e53c431c8512dc92d6..496fb6a415eaf7da06d6f4f59195576eed44ac7c 100644 --- a/arch/m68k/configs/bvme6000_defconfig +++ b/arch/m68k/configs/bvme6000_defconfig @@ -34,8 +34,8 @@ CONFIG_MQ_IOSCHED_KYBER=m CONFIG_IOSCHED_BFQ=m # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set CONFIG_BINFMT_MISC=m -CONFIG_SLAB=y # CONFIG_COMPACTION is not set +CONFIG_DMAPOOL_TEST=m CONFIG_USERFAULTFD=y CONFIG_NET=y CONFIG_PACKET=y @@ -403,7 +403,6 @@ CONFIG_OCFS2_FS=m # CONFIG_OCFS2_DEBUG_MASKLOG is not set CONFIG_FANOTIFY=y CONFIG_QUOTA_NETLINK_INTERFACE=y -# CONFIG_PRINT_QUOTA_WARNING is not set CONFIG_AUTOFS_FS=m CONFIG_FUSE_FS=m CONFIG_CUSE=m diff --git a/arch/m68k/configs/hp300_defconfig b/arch/m68k/configs/hp300_defconfig index 5605ab5c3dcfc25f71ce7ef4e5335f9c173f6628..4add7ab9973b1497e5adfff132a12dbb889c8981 100644 --- a/arch/m68k/configs/hp300_defconfig +++ b/arch/m68k/configs/hp300_defconfig @@ -36,8 +36,8 @@ CONFIG_MQ_IOSCHED_KYBER=m CONFIG_IOSCHED_BFQ=m # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set CONFIG_BINFMT_MISC=m -CONFIG_SLAB=y # CONFIG_COMPACTION is not set +CONFIG_DMAPOOL_TEST=m CONFIG_USERFAULTFD=y CONFIG_NET=y CONFIG_PACKET=y @@ -413,7 +413,6 @@ CONFIG_OCFS2_FS=m # CONFIG_OCFS2_DEBUG_MASKLOG is not set CONFIG_FANOTIFY=y CONFIG_QUOTA_NETLINK_INTERFACE=y -# CONFIG_PRINT_QUOTA_WARNING is not set CONFIG_AUTOFS_FS=m CONFIG_FUSE_FS=m CONFIG_CUSE=m diff --git a/arch/m68k/configs/mac_defconfig b/arch/m68k/configs/mac_defconfig index d0d1f9c33756d795f66905dc4442dbd71e41f053..5845f1f71fd11cd2d7b11dc8a8a4e223e97baa83 100644 --- a/arch/m68k/configs/mac_defconfig +++ b/arch/m68k/configs/mac_defconfig @@ -35,8 +35,8 @@ CONFIG_MQ_IOSCHED_KYBER=m CONFIG_IOSCHED_BFQ=m # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set CONFIG_BINFMT_MISC=m -CONFIG_SLAB=y # CONFIG_COMPACTION is not set +CONFIG_DMAPOOL_TEST=m CONFIG_USERFAULTFD=y CONFIG_NET=y CONFIG_PACKET=y @@ -433,7 +433,6 @@ CONFIG_OCFS2_FS=m # CONFIG_OCFS2_DEBUG_MASKLOG is not set CONFIG_FANOTIFY=y CONFIG_QUOTA_NETLINK_INTERFACE=y -# CONFIG_PRINT_QUOTA_WARNING is not set CONFIG_AUTOFS_FS=m CONFIG_FUSE_FS=m CONFIG_CUSE=m diff --git a/arch/m68k/configs/multi_defconfig b/arch/m68k/configs/multi_defconfig index 6d04314ce7eafb39a5045bfe0bc6535a36875f5b..bbb251bab81addfe670d5e83360b3dec867407f4 100644 --- a/arch/m68k/configs/multi_defconfig +++ b/arch/m68k/configs/multi_defconfig @@ -55,8 +55,8 @@ CONFIG_MQ_IOSCHED_KYBER=m CONFIG_IOSCHED_BFQ=m # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set CONFIG_BINFMT_MISC=m -CONFIG_SLAB=y # CONFIG_COMPACTION is not set +CONFIG_DMAPOOL_TEST=m CONFIG_USERFAULTFD=y CONFIG_NET=y CONFIG_PACKET=y @@ -519,7 +519,6 @@ CONFIG_OCFS2_FS=m # CONFIG_OCFS2_DEBUG_MASKLOG is not set CONFIG_FANOTIFY=y CONFIG_QUOTA_NETLINK_INTERFACE=y -# CONFIG_PRINT_QUOTA_WARNING is not set CONFIG_AUTOFS_FS=m CONFIG_FUSE_FS=m CONFIG_CUSE=m diff --git a/arch/m68k/configs/mvme147_defconfig b/arch/m68k/configs/mvme147_defconfig index e6f5ae526d0893393e5804ef4d45495126ce16ba..4f9cfc70c66dbe43146124541e30357b6aa08d90 100644 --- a/arch/m68k/configs/mvme147_defconfig +++ b/arch/m68k/configs/mvme147_defconfig @@ -33,8 +33,8 @@ CONFIG_MQ_IOSCHED_KYBER=m CONFIG_IOSCHED_BFQ=m # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set CONFIG_BINFMT_MISC=m -CONFIG_SLAB=y # CONFIG_COMPACTION is not set +CONFIG_DMAPOOL_TEST=m CONFIG_USERFAULTFD=y CONFIG_NET=y CONFIG_PACKET=y @@ -402,7 +402,6 @@ CONFIG_OCFS2_FS=m # CONFIG_OCFS2_DEBUG_MASKLOG is not set CONFIG_FANOTIFY=y CONFIG_QUOTA_NETLINK_INTERFACE=y -# CONFIG_PRINT_QUOTA_WARNING is not set CONFIG_AUTOFS_FS=m CONFIG_FUSE_FS=m CONFIG_CUSE=m diff --git a/arch/m68k/configs/mvme16x_defconfig b/arch/m68k/configs/mvme16x_defconfig index f2d4dff4787aade7b4510078104899604b24c24e..67c42b4822f02688359c2bc43be37d7cd3a5df7e 100644 --- a/arch/m68k/configs/mvme16x_defconfig +++ b/arch/m68k/configs/mvme16x_defconfig @@ -34,8 +34,8 @@ CONFIG_MQ_IOSCHED_KYBER=m CONFIG_IOSCHED_BFQ=m # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set CONFIG_BINFMT_MISC=m -CONFIG_SLAB=y # CONFIG_COMPACTION is not set +CONFIG_DMAPOOL_TEST=m CONFIG_USERFAULTFD=y CONFIG_NET=y CONFIG_PACKET=y @@ -403,7 +403,6 @@ CONFIG_OCFS2_FS=m # CONFIG_OCFS2_DEBUG_MASKLOG is not set CONFIG_FANOTIFY=y CONFIG_QUOTA_NETLINK_INTERFACE=y -# CONFIG_PRINT_QUOTA_WARNING is not set CONFIG_AUTOFS_FS=m CONFIG_FUSE_FS=m CONFIG_CUSE=m diff --git a/arch/m68k/configs/q40_defconfig b/arch/m68k/configs/q40_defconfig index 907eedecd040262c71c6ce7d1b125c8464312b9d..85f19515200bee213b19df54410591c70bfab871 100644 --- a/arch/m68k/configs/q40_defconfig +++ b/arch/m68k/configs/q40_defconfig @@ -35,8 +35,8 @@ CONFIG_MQ_IOSCHED_KYBER=m CONFIG_IOSCHED_BFQ=m # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set CONFIG_BINFMT_MISC=m -CONFIG_SLAB=y # CONFIG_COMPACTION is not set +CONFIG_DMAPOOL_TEST=m CONFIG_USERFAULTFD=y CONFIG_NET=y CONFIG_PACKET=y @@ -420,7 +420,6 @@ CONFIG_OCFS2_FS=m # CONFIG_OCFS2_DEBUG_MASKLOG is not set CONFIG_FANOTIFY=y CONFIG_QUOTA_NETLINK_INTERFACE=y -# CONFIG_PRINT_QUOTA_WARNING is not set CONFIG_AUTOFS_FS=m CONFIG_FUSE_FS=m CONFIG_CUSE=m diff --git a/arch/m68k/configs/sun3_defconfig b/arch/m68k/configs/sun3_defconfig index 9e3d47008f2186756b99ee9053bd6b0fa4fcc5e9..b1b15acb5d5fb3dbffa687223fc9b0c195273d64 100644 --- a/arch/m68k/configs/sun3_defconfig +++ b/arch/m68k/configs/sun3_defconfig @@ -31,7 +31,6 @@ CONFIG_MQ_IOSCHED_KYBER=m CONFIG_IOSCHED_BFQ=m # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set CONFIG_BINFMT_MISC=m -CONFIG_SLAB=y # CONFIG_COMPACTION is not set CONFIG_USERFAULTFD=y CONFIG_NET=y @@ -402,7 +401,6 @@ CONFIG_OCFS2_FS=m # CONFIG_OCFS2_DEBUG_MASKLOG is not set CONFIG_FANOTIFY=y CONFIG_QUOTA_NETLINK_INTERFACE=y -# CONFIG_PRINT_QUOTA_WARNING is not set CONFIG_AUTOFS_FS=m CONFIG_FUSE_FS=m CONFIG_CUSE=m diff --git a/arch/m68k/configs/sun3x_defconfig b/arch/m68k/configs/sun3x_defconfig index f6540078cb4beb48a0a9236c1f85cf050111ccc8..91d66c0f5ab6c4844ea3f5fa0692f5e3bf0e040a 100644 --- a/arch/m68k/configs/sun3x_defconfig +++ b/arch/m68k/configs/sun3x_defconfig @@ -31,8 +31,8 @@ CONFIG_MQ_IOSCHED_KYBER=m CONFIG_IOSCHED_BFQ=m # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set CONFIG_BINFMT_MISC=m -CONFIG_SLAB=y # CONFIG_COMPACTION is not set +CONFIG_DMAPOOL_TEST=m CONFIG_USERFAULTFD=y CONFIG_NET=y CONFIG_PACKET=y @@ -401,7 +401,6 @@ CONFIG_OCFS2_FS=m # CONFIG_OCFS2_DEBUG_MASKLOG is not set CONFIG_FANOTIFY=y CONFIG_QUOTA_NETLINK_INTERFACE=y -# CONFIG_PRINT_QUOTA_WARNING is not set CONFIG_AUTOFS_FS=m CONFIG_FUSE_FS=m CONFIG_CUSE=m diff --git a/arch/m68k/configs/virt_defconfig b/arch/m68k/configs/virt_defconfig index 8059bd618370dc76e90fc5d59668c0e204bd922d..311b57e73316884df4e0b326223ec9a4566b78c0 100644 --- a/arch/m68k/configs/virt_defconfig +++ b/arch/m68k/configs/virt_defconfig @@ -24,8 +24,6 @@ CONFIG_SUN_PARTITION=y CONFIG_SYSV68_PARTITION=y CONFIG_NET=y CONFIG_PACKET=y -CONFIG_UNIX=y -CONFIG_INET=y CONFIG_IP_PNP=y CONFIG_IP_PNP_DHCP=y CONFIG_IP_PNP_BOOTP=y diff --git a/arch/m68k/include/asm/atomic.h b/arch/m68k/include/asm/atomic.h index cfba83d230fdec37b34685e914be435e0eafec5d..4bfbc25f6ecf43348ea577c36ce7dcd6af093e54 100644 --- a/arch/m68k/include/asm/atomic.h +++ b/arch/m68k/include/asm/atomic.h @@ -106,6 +106,11 @@ static inline int arch_atomic_fetch_##op(int i, atomic_t * v) \ ATOMIC_OPS(add, +=, add) ATOMIC_OPS(sub, -=, sub) +#define arch_atomic_add_return arch_atomic_add_return +#define arch_atomic_sub_return arch_atomic_sub_return +#define arch_atomic_fetch_add arch_atomic_fetch_add +#define arch_atomic_fetch_sub arch_atomic_fetch_sub + #undef ATOMIC_OPS #define ATOMIC_OPS(op, c_op, asm_op) \ ATOMIC_OP(op, c_op, asm_op) \ @@ -115,6 +120,10 @@ ATOMIC_OPS(and, &=, and) ATOMIC_OPS(or, |=, or) ATOMIC_OPS(xor, ^=, eor) +#define arch_atomic_fetch_and arch_atomic_fetch_and +#define arch_atomic_fetch_or arch_atomic_fetch_or +#define arch_atomic_fetch_xor arch_atomic_fetch_xor + #undef ATOMIC_OPS #undef ATOMIC_FETCH_OP #undef ATOMIC_OP_RETURN @@ -158,12 +167,7 @@ static inline int arch_atomic_inc_and_test(atomic_t *v) } #define arch_atomic_inc_and_test arch_atomic_inc_and_test -#ifdef CONFIG_RMW_INSNS - -#define arch_atomic_cmpxchg(v, o, n) ((int)arch_cmpxchg(&((v)->counter), (o), (n))) -#define arch_atomic_xchg(v, new) (arch_xchg(&((v)->counter), new)) - -#else /* !CONFIG_RMW_INSNS */ +#ifndef CONFIG_RMW_INSNS static inline int arch_atomic_cmpxchg(atomic_t *v, int old, int new) { @@ -177,6 +181,7 @@ static inline int arch_atomic_cmpxchg(atomic_t *v, int old, int new) local_irq_restore(flags); return prev; } +#define arch_atomic_cmpxchg arch_atomic_cmpxchg static inline int arch_atomic_xchg(atomic_t *v, int new) { @@ -189,6 +194,7 @@ static inline int arch_atomic_xchg(atomic_t *v, int new) local_irq_restore(flags); return prev; } +#define arch_atomic_xchg arch_atomic_xchg #endif /* !CONFIG_RMW_INSNS */ diff --git a/arch/m68k/include/asm/bugs.h b/arch/m68k/include/asm/bugs.h deleted file mode 100644 index 745530651e0bfd39a6b1c06c464eb8e4cbdd66ee..0000000000000000000000000000000000000000 --- a/arch/m68k/include/asm/bugs.h +++ /dev/null @@ -1,21 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * include/asm-m68k/bugs.h - * - * Copyright (C) 1994 Linus Torvalds - */ - -/* - * This is included by init/main.c to check for architecture-dependent bugs. - * - * Needs: - * void check_bugs(void); - */ - -#ifdef CONFIG_MMU -extern void check_bugs(void); /* in arch/m68k/kernel/setup.c */ -#else -static void check_bugs(void) -{ -} -#endif diff --git a/arch/m68k/include/asm/mcf_pgtable.h b/arch/m68k/include/asm/mcf_pgtable.h index d97fbb812f63ee1d0e2a059ee04bc2d857e26ef2..43e8da8465f9e461c714ffd8cab92ab6f2f665c3 100644 --- a/arch/m68k/include/asm/mcf_pgtable.h +++ b/arch/m68k/include/asm/mcf_pgtable.h @@ -115,7 +115,7 @@ static inline void pgd_set(pgd_t *pgdp, pmd_t *pmdp) pgd_val(*pgdp) = virt_to_phys(pmdp); } -#define __pte_page(pte) ((unsigned long) (pte_val(pte) & PAGE_MASK)) +#define __pte_page(pte) ((void *) (pte_val(pte) & PAGE_MASK)) #define pmd_page_vaddr(pmd) ((unsigned long) (pmd_val(pmd))) static inline int pte_none(pte_t pte) @@ -134,7 +134,6 @@ static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_val(*ptep) = 0; } -#define pte_pagenr(pte) ((__pte_page(pte) - PAGE_OFFSET) >> PAGE_SHIFT) #define pte_page(pte) virt_to_page(__pte_page(pte)) static inline int pmd_none2(pmd_t *pmd) { return !pmd_val(*pmd); } diff --git a/arch/m68k/include/asm/mcfgpio.h b/arch/m68k/include/asm/mcfgpio.h index 2cefe8445980bd35b20605026ef2b235e8fc88ed..7abd322c019fc16f66076d4897558840b132f2df 100644 --- a/arch/m68k/include/asm/mcfgpio.h +++ b/arch/m68k/include/asm/mcfgpio.h @@ -34,14 +34,6 @@ static inline void __gpio_set_value(unsigned gpio, int value) __mcfgpio_set_value(gpio, value); } -static inline int __gpio_cansleep(unsigned gpio) -{ - if (gpio < MCFGPIO_PIN_MAX) - return 0; - else - return -EINVAL; -} - static inline int __gpio_to_irq(unsigned gpio) { return -EINVAL; diff --git a/arch/m68k/include/asm/mmu_context.h b/arch/m68k/include/asm/mmu_context.h index 8ed6ac14d99ff2392e2998a6b08ecd72bc879e89..141bbdfad9601996312d3f5de241a9d5b48db669 100644 --- a/arch/m68k/include/asm/mmu_context.h +++ b/arch/m68k/include/asm/mmu_context.h @@ -99,7 +99,7 @@ static inline void load_ksp_mmu(struct task_struct *task) p4d_t *p4d; pud_t *pud; pmd_t *pmd; - pte_t *pte; + pte_t *pte = NULL; unsigned long mmuar; local_irq_save(flags); @@ -139,7 +139,7 @@ static inline void load_ksp_mmu(struct task_struct *task) pte = (mmuar >= PAGE_OFFSET) ? pte_offset_kernel(pmd, mmuar) : pte_offset_map(pmd, mmuar); - if (pte_none(*pte) || !pte_present(*pte)) + if (!pte || pte_none(*pte) || !pte_present(*pte)) goto bug; set_pte(pte, pte_mkyoung(*pte)); @@ -161,6 +161,8 @@ static inline void load_ksp_mmu(struct task_struct *task) bug: pr_info("ksp load failed: mm=0x%p ksp=0x08%lx\n", mm, mmuar); end: + if (pte && mmuar < PAGE_OFFSET) + pte_unmap(pte); local_irq_restore(flags); } diff --git a/arch/m68k/include/asm/page_mm.h b/arch/m68k/include/asm/page_mm.h index 3903db2e8da771313d3c1fe9dd5f2fd34be55cda..363aa0f9ba8ae6919384e75bc4991d4f0a5f68f7 100644 --- a/arch/m68k/include/asm/page_mm.h +++ b/arch/m68k/include/asm/page_mm.h @@ -121,8 +121,15 @@ static inline void *__va(unsigned long x) * TODO: implement (fast) pfn<->pgdat_idx conversion functions, this makes lots * of the shifts unnecessary. */ -#define virt_to_pfn(kaddr) (__pa(kaddr) >> PAGE_SHIFT) -#define pfn_to_virt(pfn) __va((pfn) << PAGE_SHIFT) +static inline unsigned long virt_to_pfn(const void *kaddr) +{ + return __pa(kaddr) >> PAGE_SHIFT; +} + +static inline void *pfn_to_virt(unsigned long pfn) +{ + return __va(pfn << PAGE_SHIFT); +} extern int m68k_virt_to_node_shift; diff --git a/arch/m68k/include/asm/page_no.h b/arch/m68k/include/asm/page_no.h index 060e4c0e7605330f159d245941a3ee003d792cd1..af3a10973233cf240470153cfee907b4bef5c5ea 100644 --- a/arch/m68k/include/asm/page_no.h +++ b/arch/m68k/include/asm/page_no.h @@ -19,8 +19,15 @@ extern unsigned long memory_end; #define __pa(vaddr) ((unsigned long)(vaddr)) #define __va(paddr) ((void *)((unsigned long)(paddr))) -#define virt_to_pfn(kaddr) (__pa(kaddr) >> PAGE_SHIFT) -#define pfn_to_virt(pfn) __va((pfn) << PAGE_SHIFT) +static inline unsigned long virt_to_pfn(const void *kaddr) +{ + return __pa(kaddr) >> PAGE_SHIFT; +} + +static inline void *pfn_to_virt(unsigned long pfn) +{ + return __va(pfn << PAGE_SHIFT); +} #define virt_to_page(addr) (mem_map + (((unsigned long)(addr)-PAGE_OFFSET) >> PAGE_SHIFT)) #define page_to_virt(page) __va(((((page) - mem_map) << PAGE_SHIFT) + PAGE_OFFSET)) diff --git a/arch/m68k/include/asm/sun3_pgtable.h b/arch/m68k/include/asm/sun3_pgtable.h index e582b0484a55cd82e2a2a5a1ee958099cff04afb..9e7bf8a5f8f8824e4fb724cd648e81b165369f9d 100644 --- a/arch/m68k/include/asm/sun3_pgtable.h +++ b/arch/m68k/include/asm/sun3_pgtable.h @@ -91,7 +91,7 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) #define pmd_set(pmdp,ptep) do {} while (0) #define __pte_page(pte) \ -((unsigned long) __va ((pte_val (pte) & SUN3_PAGE_PGNUM_MASK) << PAGE_SHIFT)) +(__va ((pte_val (pte) & SUN3_PAGE_PGNUM_MASK) << PAGE_SHIFT)) static inline unsigned long pmd_page_vaddr(pmd_t pmd) { @@ -111,7 +111,7 @@ static inline void pte_clear (struct mm_struct *mm, unsigned long addr, pte_t *p #define pte_page(pte) virt_to_page(__pte_page(pte)) #define pmd_pfn(pmd) (pmd_val(pmd) >> PAGE_SHIFT) -#define pmd_page(pmd) virt_to_page(pmd_page_vaddr(pmd)) +#define pmd_page(pmd) virt_to_page((void *)pmd_page_vaddr(pmd)) static inline int pmd_none2 (pmd_t *pmd) { return !pmd_val (*pmd); } diff --git a/arch/m68k/kernel/setup_mm.c b/arch/m68k/kernel/setup_mm.c index fbff1cea62caac23c0463270f320394fabb235b2..6f1ae01f322cf2316ef9789e0e95ac3f8ce1a22b 100644 --- a/arch/m68k/kernel/setup_mm.c +++ b/arch/m68k/kernel/setup_mm.c @@ -10,6 +10,7 @@ */ #include +#include #include #include #include @@ -504,7 +505,7 @@ static int __init proc_hardware_init(void) module_init(proc_hardware_init); #endif -void check_bugs(void) +void __init arch_cpu_finalize_init(void) { #if defined(CONFIG_FPU) && !defined(CONFIG_M68KFPU_EMU) if (m68k_fputype == 0) { diff --git a/arch/m68k/kernel/sys_m68k.c b/arch/m68k/kernel/sys_m68k.c index bd0274c7592e0c14921d638e939fc509e0502c2b..c586034d2a7ac85dcd1eab993dab14ae0dd4abe4 100644 --- a/arch/m68k/kernel/sys_m68k.c +++ b/arch/m68k/kernel/sys_m68k.c @@ -488,6 +488,8 @@ sys_atomic_cmpxchg_32(unsigned long newval, int oldval, int d3, int d4, int d5, if (!pmd_present(*pmd)) goto bad_access; pte = pte_offset_map_lock(mm, pmd, (unsigned long)mem, &ptl); + if (!pte) + goto bad_access; if (!pte_present(*pte) || !pte_dirty(*pte) || !pte_write(*pte)) { pte_unmap_unlock(pte, ptl); diff --git a/arch/m68k/kernel/syscalls/syscall.tbl b/arch/m68k/kernel/syscalls/syscall.tbl index b1f3940bc29816ec07a31483f2d6b716a8ba1e2c..4f504783371fc7b953632557a2afb73bfde118ae 100644 --- a/arch/m68k/kernel/syscalls/syscall.tbl +++ b/arch/m68k/kernel/syscalls/syscall.tbl @@ -450,3 +450,4 @@ 448 common process_mrelease sys_process_mrelease 449 common futex_waitv sys_futex_waitv 450 common set_mempolicy_home_node sys_set_mempolicy_home_node +451 common cachestat sys_cachestat diff --git a/arch/m68k/mm/fault.c b/arch/m68k/mm/fault.c index 228128e45c673b0b6dea3ed8a4deb63afe182985..c290c5c0cfb93a8128d88ce29de3bbe2b54d511f 100644 --- a/arch/m68k/mm/fault.c +++ b/arch/m68k/mm/fault.c @@ -105,8 +105,9 @@ int do_page_fault(struct pt_regs *regs, unsigned long address, if (address + 256 < rdusp()) goto map_err; } - if (expand_stack(vma, address)) - goto map_err; + vma = expand_stack(mm, address); + if (!vma) + goto map_err_nosemaphore; /* * Ok, we have a good vm_area for this memory access, so @@ -196,10 +197,12 @@ int do_page_fault(struct pt_regs *regs, unsigned long address, goto send_sig; map_err: + mmap_read_unlock(mm); +map_err_nosemaphore: current->thread.signo = SIGSEGV; current->thread.code = SEGV_MAPERR; current->thread.faddr = address; - goto send_sig; + return send_fault_sig(regs); acc_err: current->thread.signo = SIGSEGV; diff --git a/arch/m68k/mm/mcfmmu.c b/arch/m68k/mm/mcfmmu.c index 70aa0979e02710a8d1db820b84f05dcffc93a9f6..a6efaa7cacde274e9496f9db47bca5b4efc447c1 100644 --- a/arch/m68k/mm/mcfmmu.c +++ b/arch/m68k/mm/mcfmmu.c @@ -69,7 +69,8 @@ void __init paging_init(void) /* now change pg_table to kernel virtual addresses */ for (i = 0; i < PTRS_PER_PTE; ++i, ++pg_table) { - pte_t pte = pfn_pte(virt_to_pfn(address), PAGE_INIT); + pte_t pte = pfn_pte(virt_to_pfn((void *)address), + PAGE_INIT); if (address >= (unsigned long) high_memory) pte_val(pte) = 0; @@ -91,7 +92,8 @@ int cf_tlb_miss(struct pt_regs *regs, int write, int dtlb, int extension_word) p4d_t *p4d; pud_t *pud; pmd_t *pmd; - pte_t *pte; + pte_t *pte = NULL; + int ret = -1; int asid; local_irq_save(flags); @@ -100,47 +102,33 @@ int cf_tlb_miss(struct pt_regs *regs, int write, int dtlb, int extension_word) regs->pc + (extension_word * sizeof(long)); mm = (!user_mode(regs) && KMAPAREA(mmuar)) ? &init_mm : current->mm; - if (!mm) { - local_irq_restore(flags); - return -1; - } + if (!mm) + goto out; pgd = pgd_offset(mm, mmuar); - if (pgd_none(*pgd)) { - local_irq_restore(flags); - return -1; - } + if (pgd_none(*pgd)) + goto out; p4d = p4d_offset(pgd, mmuar); - if (p4d_none(*p4d)) { - local_irq_restore(flags); - return -1; - } + if (p4d_none(*p4d)) + goto out; pud = pud_offset(p4d, mmuar); - if (pud_none(*pud)) { - local_irq_restore(flags); - return -1; - } + if (pud_none(*pud)) + goto out; pmd = pmd_offset(pud, mmuar); - if (pmd_none(*pmd)) { - local_irq_restore(flags); - return -1; - } + if (pmd_none(*pmd)) + goto out; pte = (KMAPAREA(mmuar)) ? pte_offset_kernel(pmd, mmuar) : pte_offset_map(pmd, mmuar); - if (pte_none(*pte) || !pte_present(*pte)) { - local_irq_restore(flags); - return -1; - } + if (!pte || pte_none(*pte) || !pte_present(*pte)) + goto out; if (write) { - if (!pte_write(*pte)) { - local_irq_restore(flags); - return -1; - } + if (!pte_write(*pte)) + goto out; set_pte(pte, pte_mkdirty(*pte)); } @@ -161,9 +149,12 @@ int cf_tlb_miss(struct pt_regs *regs, int write, int dtlb, int extension_word) mmu_write(MMUOR, MMUOR_ACC | MMUOR_UAA); else mmu_write(MMUOR, MMUOR_ITLB | MMUOR_ACC | MMUOR_UAA); - + ret = 0; +out: + if (pte && !KMAPAREA(mmuar)) + pte_unmap(pte); local_irq_restore(flags); - return 0; + return ret; } void __init cf_bootmem_alloc(void) diff --git a/arch/m68k/mm/motorola.c b/arch/m68k/mm/motorola.c index 9113012240789469e20f7360583e861d4d3c3c65..c75984e2d86b9fa8109a44511083f429b99a6486 100644 --- a/arch/m68k/mm/motorola.c +++ b/arch/m68k/mm/motorola.c @@ -102,7 +102,7 @@ static struct list_head ptable_list[2] = { LIST_HEAD_INIT(ptable_list[1]), }; -#define PD_PTABLE(page) ((ptable_desc *)&(virt_to_page(page)->lru)) +#define PD_PTABLE(page) ((ptable_desc *)&(virt_to_page((void *)(page))->lru)) #define PD_PAGE(ptable) (list_entry(ptable, struct page, lru)) #define PD_MARKBITS(dp) (*(unsigned int *)&PD_PAGE(dp)->index) @@ -201,7 +201,7 @@ int free_pointer_table(void *table, int type) list_del(dp); mmu_page_dtor((void *)page); if (type == TABLE_PTE) - pgtable_pte_page_dtor(virt_to_page(page)); + pgtable_pte_page_dtor(virt_to_page((void *)page)); free_page (page); return 1; } else if (ptable_list[type].next != dp) { diff --git a/arch/m68k/mm/sun3mmu.c b/arch/m68k/mm/sun3mmu.c index b619d0d4319cc2595c032b7f8604ec1d6c33f800..c5e6a23e0262128de2386e65246b52c66510af51 100644 --- a/arch/m68k/mm/sun3mmu.c +++ b/arch/m68k/mm/sun3mmu.c @@ -75,7 +75,7 @@ void __init paging_init(void) /* now change pg_table to kernel virtual addresses */ pg_table = (pte_t *) __va ((unsigned long) pg_table); for (i=0; i= (unsigned long)high_memory) pte_val (pte) = 0; set_pte (pg_table, pte); diff --git a/arch/m68k/sun3/dvma.c b/arch/m68k/sun3/dvma.c index f15ff16b99974a7ab78fa77205a6f92cfc39b57f..83fcae6a0e79c5d8e3cb1430fdfdcfaeb7f9b5e7 100644 --- a/arch/m68k/sun3/dvma.c +++ b/arch/m68k/sun3/dvma.c @@ -29,7 +29,7 @@ static unsigned long dvma_page(unsigned long kaddr, unsigned long vaddr) j = *(volatile unsigned long *)kaddr; *(volatile unsigned long *)kaddr = j; - ptep = pfn_pte(virt_to_pfn(kaddr), PAGE_KERNEL); + ptep = pfn_pte(virt_to_pfn((void *)kaddr), PAGE_KERNEL); pte = pte_val(ptep); // pr_info("dvma_remap: addr %lx -> %lx pte %08lx\n", kaddr, vaddr, pte); if(ptelist[(vaddr & 0xff000) >> PAGE_SHIFT] != pte) { diff --git a/arch/m68k/sun3x/dvma.c b/arch/m68k/sun3x/dvma.c index 08bb92113026a7bb979ec0f50eff4abbb7ac29a5..a6034ba05845464216a965fb2a66922a509c30ec 100644 --- a/arch/m68k/sun3x/dvma.c +++ b/arch/m68k/sun3x/dvma.c @@ -125,7 +125,7 @@ inline int dvma_map_cpu(unsigned long kaddr, do { pr_debug("mapping %08lx phys to %08lx\n", __pa(kaddr), vaddr); - set_pte(pte, pfn_pte(virt_to_pfn(kaddr), + set_pte(pte, pfn_pte(virt_to_pfn((void *)kaddr), PAGE_KERNEL)); pte++; kaddr += PAGE_SIZE; diff --git a/arch/microblaze/configs/mmu_defconfig b/arch/microblaze/configs/mmu_defconfig index 756feb9369a600fa50b14f7919b6866ba8ca0e18..38dcdce367ec25c35e29fd17d9ec3aca0970993d 100644 --- a/arch/microblaze/configs/mmu_defconfig +++ b/arch/microblaze/configs/mmu_defconfig @@ -8,7 +8,6 @@ CONFIG_SYSFS_DEPRECATED_V2=y # CONFIG_BASE_FULL is not set CONFIG_KALLSYMS_ALL=y CONFIG_EMBEDDED=y -CONFIG_SLAB=y CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR=1 CONFIG_XILINX_MICROBLAZE0_USE_PCMP_INSTR=1 CONFIG_XILINX_MICROBLAZE0_USE_BARREL=1 diff --git a/arch/microblaze/include/asm/cache.h b/arch/microblaze/include/asm/cache.h index a149b3e711ec9c585ebbf9cfe07ed2e44e882474..1903988b9e23470cda621f4461b2a3b758946396 100644 --- a/arch/microblaze/include/asm/cache.h +++ b/arch/microblaze/include/asm/cache.h @@ -18,4 +18,9 @@ #define SMP_CACHE_BYTES L1_CACHE_BYTES +/* MS be sure that SLAB allocates aligned objects */ +#define ARCH_DMA_MINALIGN L1_CACHE_BYTES + +#define ARCH_SLAB_MINALIGN L1_CACHE_BYTES + #endif /* _ASM_MICROBLAZE_CACHE_H */ diff --git a/arch/microblaze/include/asm/page.h b/arch/microblaze/include/asm/page.h index 7b9861bcd4581a93bc80c1471433c9ee0b31897d..337f23eabc71b2b47bd3d5a56254a4520187019f 100644 --- a/arch/microblaze/include/asm/page.h +++ b/arch/microblaze/include/asm/page.h @@ -30,11 +30,6 @@ #ifndef __ASSEMBLY__ -/* MS be sure that SLAB allocates aligned objects */ -#define ARCH_DMA_MINALIGN L1_CACHE_BYTES - -#define ARCH_SLAB_MINALIGN L1_CACHE_BYTES - /* * PAGE_OFFSET -- the first address of the first page of memory. With MMU * it is set to the kernel start address (aligned on a page boundary). diff --git a/arch/microblaze/include/asm/setup.h b/arch/microblaze/include/asm/setup.h index a06cc1f97aa91536c971b9b73570c48e1311a65c..3657f5e78a3d0e2cb96a8fe2a169dc8126b4c77b 100644 --- a/arch/microblaze/include/asm/setup.h +++ b/arch/microblaze/include/asm/setup.h @@ -16,8 +16,6 @@ extern char *klimit; extern void mmu_reset(void); -void time_init(void); -void init_IRQ(void); void machine_early_init(const char *cmdline, unsigned int ram, unsigned int fdt, unsigned int msr, unsigned int tlb0, unsigned int tlb1); diff --git a/arch/microblaze/kernel/prom.c b/arch/microblaze/kernel/prom.c index c5c6186a7e8b3fdfe896693da19794b3c4943f1f..e424c796e297c54ae60d73e4854fb78cd626708e 100644 --- a/arch/microblaze/kernel/prom.c +++ b/arch/microblaze/kernel/prom.c @@ -20,7 +20,7 @@ void __init early_init_devtree(void *params) early_init_dt_scan(params); if (!strlen(boot_command_line)) - strlcpy(boot_command_line, cmd_line, COMMAND_LINE_SIZE); + strscpy(boot_command_line, cmd_line, COMMAND_LINE_SIZE); memblock_allow_resize(); diff --git a/arch/microblaze/kernel/signal.c b/arch/microblaze/kernel/signal.c index c3aebec71c0ce25aaff9ea287a32950df254d396..c78a0ff480660d103bd7c19ee2bcfa4cfa078c45 100644 --- a/arch/microblaze/kernel/signal.c +++ b/arch/microblaze/kernel/signal.c @@ -194,7 +194,7 @@ static int setup_rt_frame(struct ksignal *ksig, sigset_t *set, preempt_disable(); ptep = pte_offset_map(pmdp, address); - if (pte_present(*ptep)) { + if (ptep && pte_present(*ptep)) { address = (unsigned long) page_address(pte_page(*ptep)); /* MS: I need add offset in page */ address += ((unsigned long)frame->tramp) & ~PAGE_MASK; @@ -203,7 +203,8 @@ static int setup_rt_frame(struct ksignal *ksig, sigset_t *set, invalidate_icache_range(address, address + 8); flush_dcache_range(address, address + 8); } - pte_unmap(ptep); + if (ptep) + pte_unmap(ptep); preempt_enable(); if (err) return -EFAULT; diff --git a/arch/microblaze/kernel/syscalls/syscall.tbl b/arch/microblaze/kernel/syscalls/syscall.tbl index 820145e473501ee97056beda9720991358cd3a52..858d22bf275c2880422b760337bc3810a8aa05bc 100644 --- a/arch/microblaze/kernel/syscalls/syscall.tbl +++ b/arch/microblaze/kernel/syscalls/syscall.tbl @@ -456,3 +456,4 @@ 448 common process_mrelease sys_process_mrelease 449 common futex_waitv sys_futex_waitv 450 common set_mempolicy_home_node sys_set_mempolicy_home_node +451 common cachestat sys_cachestat diff --git a/arch/microblaze/mm/fault.c b/arch/microblaze/mm/fault.c index 687714db6f4d0c2c9909613df5edf973a8a532c1..d3c3c33b73a6ed7314eefef42f9d93c3f17108bf 100644 --- a/arch/microblaze/mm/fault.c +++ b/arch/microblaze/mm/fault.c @@ -192,8 +192,9 @@ void do_page_fault(struct pt_regs *regs, unsigned long address, && (kernel_mode(regs) || !store_updates_sp(regs))) goto bad_area; } - if (expand_stack(vma, address)) - goto bad_area; + vma = expand_stack(mm, address); + if (!vma) + goto bad_area_nosemaphore; good_area: code = SEGV_ACCERR; diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 675a8660cb85a033792d9622040ea48a8b800cb0..fc6fba925aea05eacfcc0ae363e0029c5ed78928 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -4,6 +4,7 @@ config MIPS default y select ARCH_32BIT_OFF_T if !64BIT select ARCH_BINFMT_ELF_STATE if MIPS_FP_SUPPORT + select ARCH_HAS_CPU_FINALIZE_INIT select ARCH_HAS_CURRENT_STACK_POINTER if !CC_IS_CLANG || CLANG_VERSION >= 140000 select ARCH_HAS_DEBUG_VIRTUAL if !64BIT select ARCH_HAS_FORTIFY_SOURCE @@ -44,6 +45,7 @@ config MIPS select GENERIC_LIB_UCMPDI2 select GENERIC_SCHED_CLOCK if !CAVIUM_OCTEON_SOC select GENERIC_SMP_IDLE_THREAD + select GENERIC_IDLE_POLL_SETUP select GENERIC_TIME_VSYSCALL select GUP_GET_PXX_LOW_HIGH if CPU_MIPS32 && PHYS_ADDR_T_64BIT select HAS_IOPORT if !NO_IOPORT_MAP || ISA @@ -79,7 +81,6 @@ config MIPS select HAVE_LD_DEAD_CODE_DATA_ELIMINATION select HAVE_MOD_ARCH_SPECIFIC select HAVE_NMI - select HAVE_PATA_PLATFORM select HAVE_PERF_EVENTS select HAVE_PERF_REGS select HAVE_PERF_USER_STACK_DUMP @@ -91,6 +92,7 @@ config MIPS select HAVE_VIRT_CPU_ACCOUNTING_GEN if 64BIT || !SMP select IRQ_FORCED_THREADING select ISA if EISA + select LOCK_MM_AND_FIND_VMA select MODULES_USE_ELF_REL if MODULES select MODULES_USE_ELF_RELA if MODULES && 64BIT select PERF_USE_VMALLOC @@ -153,9 +155,11 @@ config MIPS_GENERIC_KERNEL select SWAP_IO_SPACE select SYS_HAS_CPU_MIPS32_R1 select SYS_HAS_CPU_MIPS32_R2 + select SYS_HAS_CPU_MIPS32_R5 select SYS_HAS_CPU_MIPS32_R6 select SYS_HAS_CPU_MIPS64_R1 select SYS_HAS_CPU_MIPS64_R2 + select SYS_HAS_CPU_MIPS64_R5 select SYS_HAS_CPU_MIPS64_R6 select SYS_SUPPORTS_32BIT_KERNEL select SYS_SUPPORTS_64BIT_KERNEL @@ -2286,6 +2290,7 @@ config MIPS_CPS select MIPS_CM select MIPS_CPS_PM if HOTPLUG_CPU select SMP + select HOTPLUG_CORE_SYNC_DEAD if HOTPLUG_CPU select SYNC_R4K if (CEVT_R4K || CSRC_R4K) select SYS_SUPPORTS_HOTPLUG_CPU select SYS_SUPPORTS_SCHED_SMT if CPU_MIPSR6 diff --git a/arch/mips/Makefile b/arch/mips/Makefile index a7a4ee66a9d3732c4f193652e39a3bbee2c6c41c..a47593d72f6f5f3d4561481894eb8a1bb1f5c045 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -181,16 +181,12 @@ endif cflags-$(CONFIG_CAVIUM_CN63XXP1) += -Wa,-mfix-cn63xxp1 cflags-$(CONFIG_CPU_BMIPS) += -march=mips32 -Wa,-mips32 -Wa,--trap -cflags-$(CONFIG_CPU_LOONGSON2E) += -march=loongson2e -Wa,--trap -cflags-$(CONFIG_CPU_LOONGSON2F) += -march=loongson2f -Wa,--trap +cflags-$(CONFIG_CPU_LOONGSON2E) += $(call cc-option,-march=loongson2e) -Wa,--trap +cflags-$(CONFIG_CPU_LOONGSON2F) += $(call cc-option,-march=loongson2f) -Wa,--trap +cflags-$(CONFIG_CPU_LOONGSON64) += $(call cc-option,-march=loongson3a,-march=mips64r2) -Wa,--trap # Some -march= flags enable MMI instructions, and GCC complains about that # support being enabled alongside -msoft-float. Thus explicitly disable MMI. cflags-$(CONFIG_CPU_LOONGSON2EF) += $(call cc-option,-mno-loongson-mmi) -ifdef CONFIG_CPU_LOONGSON64 -cflags-$(CONFIG_CPU_LOONGSON64) += -Wa,--trap -cflags-$(CONFIG_CC_IS_GCC) += -march=loongson3a -cflags-$(CONFIG_CC_IS_CLANG) += -march=mips64r2 -endif cflags-$(CONFIG_CPU_LOONGSON64) += $(call cc-option,-mno-loongson-mmi) cflags-$(CONFIG_CPU_R4000_WORKAROUNDS) += $(call cc-option,-mfix-r4000,) @@ -346,7 +342,7 @@ KBUILD_CFLAGS += -fno-asynchronous-unwind-tables KBUILD_LDFLAGS += -m $(ld-emul) ifdef CONFIG_MIPS -CHECKFLAGS += $(shell $(CC) $(KBUILD_CFLAGS) -dM -E -x c /dev/null | \ +CHECKFLAGS += $(shell $(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) -dM -E -x c /dev/null | \ grep -E -vw '__GNUC_(MINOR_|PATCHLEVEL_)?_' | \ sed -e "s/^\#define /-D'/" -e "s/ /'='/" -e "s/$$/'/" -e 's/\$$/&&/g') endif diff --git a/arch/mips/alchemy/Kconfig b/arch/mips/alchemy/Kconfig index 69734120ada1592f9948cb1a792b82e4ddc5f1af..6ca81e1bd35c551113c9f05a19e9b82b819e2de8 100644 --- a/arch/mips/alchemy/Kconfig +++ b/arch/mips/alchemy/Kconfig @@ -14,6 +14,7 @@ config MIPS_DB1XXX bool "Alchemy DB1XXX / PB1XXX boards" select GPIOLIB select HAVE_PCI + select HAVE_PATA_PLATFORM select SYS_SUPPORTS_LITTLE_ENDIAN select SYS_HAS_EARLY_PRINTK help diff --git a/arch/mips/alchemy/common/platform.c b/arch/mips/alchemy/common/platform.c index b8f3397c59c92a7cc61563017eb2e97ac71fec5a..d4ab34b3b404efbda2083472210bc8e78efdd8e1 100644 --- a/arch/mips/alchemy/common/platform.c +++ b/arch/mips/alchemy/common/platform.c @@ -51,9 +51,9 @@ static void alchemy_8250_pm(struct uart_port *port, unsigned int state, #define PORT(_base, _irq) \ { \ .mapbase = _base, \ + .mapsize = 0x1000, \ .irq = _irq, \ .regshift = 2, \ - .iotype = UPIO_AU, \ .flags = UPF_SKIP_TEST | UPF_IOREMAP | \ UPF_FIXED_TYPE, \ .type = PORT_16550A, \ @@ -124,8 +124,14 @@ static void __init alchemy_setup_uarts(int ctype) au1xx0_uart_device.dev.platform_data = ports; /* Fill up uartclk. */ - for (s = 0; s < c; s++) + for (s = 0; s < c; s++) { ports[s].uartclk = uartclk; + if (au_platform_setup(&ports[s]) < 0) { + kfree(ports); + printk(KERN_INFO "Alchemy: missing support for UARTs\n"); + return; + } + } if (platform_device_register(&au1xx0_uart_device)) printk(KERN_INFO "Alchemy: failed to register UARTs\n"); } diff --git a/arch/mips/alchemy/devboards/db1000.c b/arch/mips/alchemy/devboards/db1000.c index 2c52ee27b4f2564bcf9090c0ddf2cb763b87c3bf..79d66faa84828ddc248c35b1b023ddb891f25a88 100644 --- a/arch/mips/alchemy/devboards/db1000.c +++ b/arch/mips/alchemy/devboards/db1000.c @@ -381,13 +381,21 @@ static struct platform_device db1100_mmc1_dev = { static struct ads7846_platform_data db1100_touch_pd = { .model = 7846, .vref_mv = 3300, - .gpio_pendown = 21, }; static struct spi_gpio_platform_data db1100_spictl_pd = { .num_chipselect = 1, }; +static struct gpiod_lookup_table db1100_touch_gpio_table = { + .dev_id = "spi0.0", + .table = { + GPIO_LOOKUP("alchemy-gpio2", 21, + "pendown", GPIO_ACTIVE_LOW), + { } + }, +}; + static struct spi_board_info db1100_spi_info[] __initdata = { [0] = { .modalias = "ads7846", @@ -474,6 +482,7 @@ int __init db1000_dev_setup(void) pfc |= (1 << 0); /* SSI0 pins as GPIOs */ alchemy_wrsys(pfc, AU1000_SYS_PINFUNC); + gpiod_add_lookup_table(&db1100_touch_gpio_table); spi_register_board_info(db1100_spi_info, ARRAY_SIZE(db1100_spi_info)); diff --git a/arch/mips/bmips/setup.c b/arch/mips/bmips/setup.c index 549a6392a3d2d3c6c6f890cb9a59b7ebb03d4922..053805cb741c3d789ffcba82d49e0c5ab74b3c1d 100644 --- a/arch/mips/bmips/setup.c +++ b/arch/mips/bmips/setup.c @@ -178,7 +178,10 @@ void __init plat_mem_setup(void) ioport_resource.start = 0; ioport_resource.end = ~0; - /* intended to somewhat resemble ARM; see Documentation/arm/booting.rst */ + /* + * intended to somewhat resemble ARM; see + * Documentation/arch/arm/booting.rst + */ if (fw_arg0 == 0 && fw_arg1 == 0xffffffff) dtb = phys_to_virt(fw_arg2); else diff --git a/arch/mips/boot/dts/ingenic/ci20.dts b/arch/mips/boot/dts/ingenic/ci20.dts index 239c4537484d071209fb6914b9f9a07ef81c4ef0..a141a699b790f4a5ba355c396a7c45aa4e1c9e0c 100644 --- a/arch/mips/boot/dts/ingenic/ci20.dts +++ b/arch/mips/boot/dts/ingenic/ci20.dts @@ -67,14 +67,14 @@ }; }; - eth0_power: fixedregulator@0 { + eth0_power: fixedregulator-0 { compatible = "regulator-fixed"; regulator-name = "eth0_power"; regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; - gpio = <&gpb 25 GPIO_ACTIVE_LOW>; + gpio = <&gpb 25 0>; enable-active-high; }; @@ -97,25 +97,64 @@ gpios = <&gpe 3 GPIO_ACTIVE_LOW>; }; - wlan0_power: fixedregulator@1 { + bt_power: fixedregulator-1 { compatible = "regulator-fixed"; - regulator-name = "wlan0_power"; + regulator-name = "bt_power"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-settling-time-us = <1400>; + + vin-supply = <&vcc_50>; - gpio = <&gpb 19 GPIO_ACTIVE_LOW>; + gpio = <&gpb 19 0>; enable-active-high; }; - otg_power: fixedregulator@2 { + otg_power: fixedregulator-2 { compatible = "regulator-fixed"; regulator-name = "otg_power"; regulator-min-microvolt = <5000000>; regulator-max-microvolt = <5000000>; - gpio = <&gpf 15 GPIO_ACTIVE_LOW>; + gpio = <&gpf 15 0>; enable-active-high; }; + + wifi_power: fixedregulator-4 { + compatible = "regulator-fixed"; + + regulator-name = "wifi_power"; + + /* + * Technically it's 5V, the WiFi chip has its own internal + * regulators; but the MMC/SD subsystem won't accept such a + * value. + */ + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-settling-time-us = <150000>; + + vin-supply = <&bt_power>; + }; + + vcc_33v: fixedregulator-5 { + compatible = "regulator-fixed"; + + regulator-name = "vcc_33v"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + + wifi_pwrseq: pwrseq { + compatible = "mmc-pwrseq-simple"; + reset-gpios = <&gpf 7 GPIO_ACTIVE_LOW>; + + clocks = <&rtc_dev>; + clock-names = "ext_clock"; + }; }; &ext { @@ -129,10 +168,11 @@ */ assigned-clocks = <&cgu JZ4780_CLK_OTGPHY>, <&cgu JZ4780_CLK_RTC>, <&cgu JZ4780_CLK_SSIPLL>, <&cgu JZ4780_CLK_SSI>, - <&cgu JZ4780_CLK_HDMI>; + <&cgu JZ4780_CLK_HDMI>, <&cgu JZ4780_CLK_MSCMUX>; assigned-clock-parents = <0>, <&cgu JZ4780_CLK_RTCLK>, <&cgu JZ4780_CLK_MPLL>, - <&cgu JZ4780_CLK_SSIPLL>; + <&cgu JZ4780_CLK_SSIPLL>, + <0>, <&cgu JZ4780_CLK_MPLL>; assigned-clock-rates = <48000000>, <0>, <54000000>, <0>, <27000000>; }; @@ -160,24 +200,33 @@ pinctrl-0 = <&pins_mmc0>; cd-gpios = <&gpf 20 GPIO_ACTIVE_LOW>; + vmmc-supply = <&vcc_33v>; + vqmmc-supply = <&vcc_33v>; }; &mmc1 { status = "okay"; bus-width = <4>; - max-frequency = <50000000>; + max-frequency = <25000000>; + mmc-pwrseq = <&wifi_pwrseq>; + vmmc-supply = <&wifi_power>; + vqmmc-supply = <&wifi_io>; non-removable; pinctrl-names = "default"; pinctrl-0 = <&pins_mmc1>; - brcmf: wifi@1 { -/* reg = <4>;*/ - compatible = "brcm,bcm4330-fmac"; - vcc-supply = <&wlan0_power>; - device-wakeup-gpios = <&gpd 9 GPIO_ACTIVE_HIGH>; - shutdown-gpios = <&gpf 7 GPIO_ACTIVE_LOW>; + #address-cells = <1>; + #size-cells = <0>; + + wifi@1 { + compatible = "brcm,bcm4329-fmac"; + reg = <1>; + + interrupt-parent = <&gpd>; + interrupts = <9 IRQ_TYPE_EDGE_FALLING>; + interrupt-names = "host-wake"; }; }; @@ -204,11 +253,20 @@ bluetooth { compatible = "brcm,bcm4330-bt"; - reset-gpios = <&gpf 8 GPIO_ACTIVE_HIGH>; - vcc-supply = <&wlan0_power>; + + vbat-supply = <&bt_power>; + vddio-supply = <&wifi_io>; + + interrupt-parent = <&gpf>; + interrupts = <6 IRQ_TYPE_EDGE_RISING>; + interrupt-names = "host-wakeup"; + + clocks = <&rtc_dev>; + clock-names = "lpo"; + + reset-gpios = <&gpf 8 GPIO_ACTIVE_LOW>; device-wakeup-gpios = <&gpf 5 GPIO_ACTIVE_HIGH>; - host-wakeup-gpios = <&gpf 6 GPIO_ACTIVE_HIGH>; - shutdown-gpios = <&gpf 4 GPIO_ACTIVE_LOW>; + shutdown-gpios = <&gpf 4 GPIO_ACTIVE_HIGH>; }; }; @@ -237,59 +295,54 @@ act8600: act8600@5a { compatible = "active-semi,act8600"; reg = <0x5a>; - status = "okay"; regulators { - vddcore: SUDCDC1 { - regulator-name = "DCDC_REG1"; - regulator-min-microvolt = <1100000>; - regulator-max-microvolt = <1100000>; + vddcore: DCDC1 { + regulator-min-microvolt = <1125000>; + regulator-max-microvolt = <1125000>; + vp1-supply = <&vcc_33v>; regulator-always-on; }; - vddmem: SUDCDC2 { - regulator-name = "DCDC_REG2"; + vddmem: DCDC2 { regulator-min-microvolt = <1500000>; regulator-max-microvolt = <1500000>; + vp2-supply = <&vcc_33v>; regulator-always-on; }; - vcc_33: SUDCDC3 { - regulator-name = "DCDC_REG3"; + vcc_33: DCDC3 { regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; + vp3-supply = <&vcc_33v>; regulator-always-on; }; - vcc_50: SUDCDC4 { - regulator-name = "SUDCDC_REG4"; + vcc_50: SUDCDC_REG4 { regulator-min-microvolt = <5000000>; regulator-max-microvolt = <5000000>; regulator-always-on; }; - vcc_25: LDO_REG5 { - regulator-name = "LDO_REG5"; + vcc_25: LDO5 { regulator-min-microvolt = <2500000>; regulator-max-microvolt = <2500000>; + inl-supply = <&vcc_33v>; regulator-always-on; }; - wifi_io: LDO_REG6 { - regulator-name = "LDO_REG6"; - regulator-min-microvolt = <2500000>; - regulator-max-microvolt = <2500000>; - regulator-always-on; + wifi_io: LDO6 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-settling-time-us = <150000>; + inl-supply = <&vcc_33v>; }; - vcc_28: LDO_REG7 { - regulator-name = "LDO_REG7"; + cim_io_28: LDO7 { regulator-min-microvolt = <2800000>; regulator-max-microvolt = <2800000>; - regulator-always-on; + inl-supply = <&vcc_33v>; }; - vcc_15: LDO_REG8 { - regulator-name = "LDO_REG8"; + cim_io_15: LDO8 { regulator-min-microvolt = <1500000>; regulator-max-microvolt = <1500000>; - regulator-always-on; + inl-supply = <&vcc_33v>; }; vrtc_18: LDO_REG9 { - regulator-name = "LDO_REG9"; /* Despite the datasheet stating 3.3V * for REG9 and the driver expecting that, * REG9 outputs 1.8V. @@ -303,7 +356,6 @@ regulator-always-on; }; vcc_11: LDO_REG10 { - regulator-name = "LDO_REG10"; regulator-min-microvolt = <1200000>; regulator-max-microvolt = <1200000>; regulator-always-on; @@ -363,7 +415,7 @@ #address-cells = <1>; #size-cells = <0>; - ingenic,bch-controller = <&bch>; + ecc-engine = <&bch>; ingenic,nemc-tAS = <10>; ingenic,nemc-tAH = <5>; @@ -429,8 +481,8 @@ pinctrl-names = "default"; pinctrl-0 = <&pins_nemc_cs6>; - reg = <6 0 1 /* addr */ - 6 2 1>; /* data */ + reg = <6 0 1>, /* addr */ + <6 2 1>; /* data */ ingenic,nemc-tAS = <15>; ingenic,nemc-tAH = <10>; @@ -442,7 +494,7 @@ vcc-supply = <ð0_power>; interrupt-parent = <&gpe>; - interrupts = <19 4>; + interrupts = <19 IRQ_TYPE_EDGE_RISING>; nvmem-cells = <ð0_addr>; nvmem-cell-names = "mac-address"; diff --git a/arch/mips/boot/dts/ingenic/jz4725b.dtsi b/arch/mips/boot/dts/ingenic/jz4725b.dtsi index e9e48022f6316fcfec89307e36ad433a0b5a2414..acbbe8c4664c110e9f978c4555ab8c814e3482f7 100644 --- a/arch/mips/boot/dts/ingenic/jz4725b.dtsi +++ b/arch/mips/boot/dts/ingenic/jz4725b.dtsi @@ -198,11 +198,8 @@ #sound-dai-cells = <0>; - clocks = <&cgu JZ4725B_CLK_AIC>, - <&cgu JZ4725B_CLK_I2S>, - <&cgu JZ4725B_CLK_EXT>, - <&cgu JZ4725B_CLK_PLL_HALF>; - clock-names = "aic", "i2s", "ext", "pll half"; + clocks = <&cgu JZ4725B_CLK_AIC>, <&cgu JZ4725B_CLK_I2S>; + clock-names = "aic", "i2s"; interrupt-parent = <&intc>; interrupts = <10>; diff --git a/arch/mips/boot/dts/ingenic/jz4740.dtsi b/arch/mips/boot/dts/ingenic/jz4740.dtsi index 7f76cba03a089bcc7e241fa7a048f808d50042fc..bdd6f4d82ec93a855b5a6a059098783ec3fcfd7c 100644 --- a/arch/mips/boot/dts/ingenic/jz4740.dtsi +++ b/arch/mips/boot/dts/ingenic/jz4740.dtsi @@ -192,11 +192,8 @@ interrupt-parent = <&intc>; interrupts = <18>; - clocks = <&cgu JZ4740_CLK_AIC>, - <&cgu JZ4740_CLK_I2S>, - <&cgu JZ4740_CLK_EXT>, - <&cgu JZ4740_CLK_PLL_HALF>; - clock-names = "aic", "i2s", "ext", "pll half"; + clocks = <&cgu JZ4740_CLK_AIC>, <&cgu JZ4740_CLK_I2S>; + clock-names = "aic", "i2s"; dmas = <&dmac 25 0xffffffff>, <&dmac 24 0xffffffff>; dma-names = "rx", "tx"; diff --git a/arch/mips/boot/dts/ingenic/jz4770.dtsi b/arch/mips/boot/dts/ingenic/jz4770.dtsi index bda0a3a86ed5f30ddfb414b973fc1a30517e4c2f..9c0099919db7aba9b231fcc6722a0c06df0091ce 100644 --- a/arch/mips/boot/dts/ingenic/jz4770.dtsi +++ b/arch/mips/boot/dts/ingenic/jz4770.dtsi @@ -238,9 +238,8 @@ #sound-dai-cells = <0>; - clocks = <&cgu JZ4770_CLK_AIC>, <&cgu JZ4770_CLK_I2S>, - <&cgu JZ4770_CLK_EXT>, <&cgu JZ4770_CLK_PLL0>; - clock-names = "aic", "i2s", "ext", "pll half"; + clocks = <&cgu JZ4770_CLK_AIC>, <&cgu JZ4770_CLK_I2S>; + clock-names = "aic", "i2s"; interrupt-parent = <&intc>; interrupts = <34>; diff --git a/arch/mips/boot/dts/ingenic/qi_lb60.dts b/arch/mips/boot/dts/ingenic/qi_lb60.dts index ba021897157235f74022523cb93ffa45d3d26e6f..24f987244a12263739131d2cc47c86037b8a5e79 100644 --- a/arch/mips/boot/dts/ingenic/qi_lb60.dts +++ b/arch/mips/boot/dts/ingenic/qi_lb60.dts @@ -27,7 +27,7 @@ stdout-path = &uart0; }; - vcc: regulator@0 { + vcc: regulator-0 { compatible = "regulator-fixed"; regulator-name = "vcc"; @@ -36,7 +36,7 @@ regulator-always-on; }; - mmc_power: regulator@1 { + mmc_power: regulator-1 { compatible = "regulator-fixed"; regulator-name = "mmc_vcc"; gpio = <&gpd 2 0>; @@ -45,7 +45,7 @@ regulator-max-microvolt = <3300000>; }; - amp_supply: regulator@2 { + amp_supply: regulator-2 { compatible = "regulator-fixed"; regulator-name = "amp_supply"; gpio = <&gpd 4 0>; diff --git a/arch/mips/boot/dts/ingenic/x1000.dtsi b/arch/mips/boot/dts/ingenic/x1000.dtsi index 42e69664efd93147b068adf9c8711757db54bedb..cc264cfff826e75043204631922250d86d81986d 100644 --- a/arch/mips/boot/dts/ingenic/x1000.dtsi +++ b/arch/mips/boot/dts/ingenic/x1000.dtsi @@ -417,4 +417,22 @@ status = "disabled"; }; + + aic: audio-controller@10020000 { + compatible = "ingenic,x1000-i2s"; + reg = <0x10020000 0x38>; + + #sound-dai-cells = <0>; + + interrupt-parent = <&intc>; + interrupts = <1>; + + clocks = <&cgu X1000_CLK_AIC>, + <&cgu X1000_CLK_I2S>; + clock-names = "aic", "i2s"; + + dmas = <&pdma X1000_DMA_I2S0_RX 0xffffffff>, + <&pdma X1000_DMA_I2S0_TX 0xffffffff>; + dma-names = "rx", "tx"; + }; }; diff --git a/arch/mips/boot/dts/loongson/loongson64-2k1000.dtsi b/arch/mips/boot/dts/loongson/loongson64-2k1000.dtsi index 8143a61111e33aa07bd1abe1e5594cedbca4f73f..f878f47e4501bcd90e6e6faac10e50ef44b4c2ae 100644 --- a/arch/mips/boot/dts/loongson/loongson64-2k1000.dtsi +++ b/arch/mips/boot/dts/loongson/loongson64-2k1000.dtsi @@ -97,6 +97,13 @@ <0x00000000>; /* int3 */ }; + rtc0: rtc@1fe07800 { + compatible = "loongson,ls2k1000-rtc"; + reg = <0 0x1fe07800 0 0x78>; + interrupt-parent = <&liointc0>; + interrupts = <60 IRQ_TYPE_LEVEL_LOW>; + }; + uart0: serial@1fe00000 { compatible = "ns16550a"; reg = <0 0x1fe00000 0 0x8>; diff --git a/arch/mips/boot/dts/loongson/ls7a-pch.dtsi b/arch/mips/boot/dts/loongson/ls7a-pch.dtsi index 2f45fce2cdc4a3cc4a7404679ced8a651a791e33..7c69e8245c2f10aa30a98fef4601e271ac640d34 100644 --- a/arch/mips/boot/dts/loongson/ls7a-pch.dtsi +++ b/arch/mips/boot/dts/loongson/ls7a-pch.dtsi @@ -19,6 +19,13 @@ #interrupt-cells = <2>; }; + rtc0: rtc@100d0100 { + compatible = "loongson,ls7a-rtc"; + reg = <0 0x100d0100 0 0x78>; + interrupt-parent = <&pic>; + interrupts = <52 IRQ_TYPE_LEVEL_HIGH>; + }; + ls7a_uart0: serial@10080000 { compatible = "ns16550a"; reg = <0 0x10080000 0 0x100>; diff --git a/arch/mips/boot/dts/mscc/serval_common.dtsi b/arch/mips/boot/dts/mscc/serval_common.dtsi index 0893de420e2750c1b3714cf616b437a72c572288..5dc1eac49e50217bbcf6d78b94a1e918e58a7f58 100644 --- a/arch/mips/boot/dts/mscc/serval_common.dtsi +++ b/arch/mips/boot/dts/mscc/serval_common.dtsi @@ -20,7 +20,7 @@ stdout-path = "serial0:115200n8"; }; - i2c0_imux: i2c0-imux{ + i2c0_imux: i2c0-imux { compatible = "i2c-mux-pinctrl"; #address-cells = <1>; #size-cells = <0>; diff --git a/arch/mips/boot/dts/pic32/pic32mzda.dtsi b/arch/mips/boot/dts/pic32/pic32mzda.dtsi index f1e3dad6beaddfb58f476dfc4a2f0f6c39f23e32..fdc721b414a88a12050497cd2ddf98ae2fbce035 100644 --- a/arch/mips/boot/dts/pic32/pic32mzda.dtsi +++ b/arch/mips/boot/dts/pic32/pic32mzda.dtsi @@ -75,7 +75,7 @@ microchip,external-irqs = <3 8 13 18 23>; }; - pic32_pinctrl: pinctrl@1f801400{ + pic32_pinctrl: pinctrl@1f801400 { #address-cells = <1>; #size-cells = <1>; compatible = "microchip,pic32mzda-pinctrl"; diff --git a/arch/mips/boot/dts/ralink/Makefile b/arch/mips/boot/dts/ralink/Makefile index 11732b8c8163a1b462e7bc9a9fcd96b17fcfe2bb..d27d7e8c700fe4debbd07fc3b8a3e4e4d27b9519 100644 --- a/arch/mips/boot/dts/ralink/Makefile +++ b/arch/mips/boot/dts/ralink/Makefile @@ -8,6 +8,7 @@ dtb-$(CONFIG_DTB_VOCORE2) += vocore2.dtb dtb-$(CONFIG_SOC_MT7621) += \ mt7621-gnubee-gb-pc1.dtb \ - mt7621-gnubee-gb-pc2.dtb + mt7621-gnubee-gb-pc2.dtb \ + mt7621-tplink-hc220-g5-v1.dtb obj-$(CONFIG_BUILTIN_DTB) += $(addsuffix .o, $(dtb-y)) diff --git a/arch/mips/boot/dts/ralink/mt7621-tplink-hc220-g5-v1.dts b/arch/mips/boot/dts/ralink/mt7621-tplink-hc220-g5-v1.dts new file mode 100644 index 0000000000000000000000000000000000000000..2d2eadc6b95f31b4e73f4ce2b89ad92d4311eae2 --- /dev/null +++ b/arch/mips/boot/dts/ralink/mt7621-tplink-hc220-g5-v1.dts @@ -0,0 +1,84 @@ +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +/dts-v1/; + +#include "mt7621.dtsi" + +#include +#include +#include + +/ { + compatible = "tplink,hc220-g5-v1", "mediatek,mt7621-soc"; + model = "TP-Link HC220 G5 v1"; + + memory@0 { + device_type = "memory"; + reg = <0x00000000 0x08000000>; + }; + + chosen { + bootargs = "earlycon console=ttyS0,115200"; + }; + + gpio-keys { + compatible = "gpio-keys"; + + key-reset { + label = "reset"; + gpios = <&gpio 8 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + + key-wps { + label = "wps"; + gpios = <&gpio 16 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + leds { + compatible = "gpio-leds"; + + led-fault { + color = ; + function = LED_FUNCTION_FAULT; + gpios = <&gpio 13 GPIO_ACTIVE_HIGH>; + }; + + led-power { + color = ; + function = LED_FUNCTION_POWER; + gpios = <&gpio 14 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "default-on"; + }; + + led-wps { + color = ; + function = LED_FUNCTION_WPS; + gpios = <&gpio 15 GPIO_ACTIVE_HIGH>; + }; + }; +}; + +&pcie { + status = "okay"; +}; + +&switch0 { + ports { + port@0 { + status = "okay"; + label = "lan2"; + }; + + port@1 { + status = "okay"; + label = "lan1"; + }; + + port@2 { + status = "okay"; + label = "wan"; + }; + }; +}; diff --git a/arch/mips/boot/dts/ralink/mt7628a.dtsi b/arch/mips/boot/dts/ralink/mt7628a.dtsi index 45bf96a3d17aa46d9893a6cd5e30015a079a4bd3..45a15e005cc4524d482849cee324bab240fb1a23 100644 --- a/arch/mips/boot/dts/ralink/mt7628a.dtsi +++ b/arch/mips/boot/dts/ralink/mt7628a.dtsi @@ -51,85 +51,85 @@ pinctrl-single,register-width = <32>; pinctrl-single,function-mask = <0x1>; - pinmux_gpio_gpio: pinmux_gpio_gpio { + pinmux_gpio_gpio: gpio-gpio-pins { pinctrl-single,bits = <0x0 0x0 0x3>; }; - pinmux_spi_cs1_cs: pinmux_spi_cs1_cs { + pinmux_spi_cs1_cs: spi-cs1-cs-pins { pinctrl-single,bits = <0x0 0x0 0x30>; }; - pinmux_i2s_gpio: pinmux_i2s_gpio { + pinmux_i2s_gpio: i2s-gpio-pins { pinctrl-single,bits = <0x0 0x40 0xc0>; }; - pinmux_uart0_uart: pinmux_uart0_uart0 { + pinmux_uart0_uart: uart0-uart0-pins { pinctrl-single,bits = <0x0 0x0 0x300>; }; - pinmux_sdmode_sdxc: pinmux_sdmode_sdxc { + pinmux_sdmode_sdxc: sdmode-sdxc-pins { pinctrl-single,bits = <0x0 0x0 0xc00>; }; - pinmux_sdmode_gpio: pinmux_sdmode_gpio { + pinmux_sdmode_gpio: sdmode-gpio-pins { pinctrl-single,bits = <0x0 0x400 0xc00>; }; - pinmux_spi_spi: pinmux_spi_spi { + pinmux_spi_spi: spi-spi-pins { pinctrl-single,bits = <0x0 0x0 0x1000>; }; - pinmux_refclk_gpio: pinmux_refclk_gpio { + pinmux_refclk_gpio: refclk-gpio-pins { pinctrl-single,bits = <0x0 0x40000 0x40000>; }; - pinmux_i2c_i2c: pinmux_i2c_i2c { + pinmux_i2c_i2c: i2c-i2c-pins { pinctrl-single,bits = <0x0 0x0 0x300000>; }; - pinmux_uart1_uart: pinmux_uart1_uart1 { + pinmux_uart1_uart: uart1-uart1-pins { pinctrl-single,bits = <0x0 0x0 0x3000000>; }; - pinmux_uart2_uart: pinmux_uart2_uart { + pinmux_uart2_uart: uart2-uart-pins { pinctrl-single,bits = <0x0 0x0 0xc000000>; }; - pinmux_pwm0_pwm: pinmux_pwm0_pwm { + pinmux_pwm0_pwm: pwm0-pwm-pins { pinctrl-single,bits = <0x0 0x0 0x30000000>; }; - pinmux_pwm0_gpio: pinmux_pwm0_gpio { + pinmux_pwm0_gpio: pwm0-gpio-pins { pinctrl-single,bits = <0x0 0x10000000 0x30000000>; }; - pinmux_pwm1_pwm: pinmux_pwm1_pwm { + pinmux_pwm1_pwm: pwm1-pwm-pins { pinctrl-single,bits = <0x0 0x0 0xc0000000>; }; - pinmux_pwm1_gpio: pinmux_pwm1_gpio { + pinmux_pwm1_gpio: pwm1-gpio-pins { pinctrl-single,bits = <0x0 0x40000000 0xc0000000>; }; - pinmux_p0led_an_gpio: pinmux_p0led_an_gpio { + pinmux_p0led_an_gpio: p0led-an-gpio-pins { pinctrl-single,bits = <0x4 0x4 0xc>; }; - pinmux_p1led_an_gpio: pinmux_p1led_an_gpio { + pinmux_p1led_an_gpio: p1led-an-gpio-pins { pinctrl-single,bits = <0x4 0x10 0x30>; }; - pinmux_p2led_an_gpio: pinmux_p2led_an_gpio { + pinmux_p2led_an_gpio: p2led-an-gpio-pins { pinctrl-single,bits = <0x4 0x40 0xc0>; }; - pinmux_p3led_an_gpio: pinmux_p3led_an_gpio { + pinmux_p3led_an_gpio: p3led-an-gpio-pins { pinctrl-single,bits = <0x4 0x100 0x300>; }; - pinmux_p4led_an_gpio: pinmux_p4led_an_gpio { + pinmux_p4led_an_gpio: p4led-an-gpio-pins { pinctrl-single,bits = <0x4 0x400 0xc00>; }; }; diff --git a/arch/mips/cavium-octeon/octeon-usb.c b/arch/mips/cavium-octeon/octeon-usb.c index 28677c615175c90fbfdb5e9547a92c7d7c28acd2..2add435ad03872f0b1465fcc9e88d13711b5c4e9 100644 --- a/arch/mips/cavium-octeon/octeon-usb.c +++ b/arch/mips/cavium-octeon/octeon-usb.c @@ -8,232 +8,255 @@ * for more details. */ -#include +#include +#include #include -#include #include -#include #include +#include +#include +#include -#include +/* + * USB Control Register + */ +#define USBDRD_UCTL_CTL 0x00 +/* BIST fast-clear mode select. A BIST run with this bit set + * clears all entries in USBH RAMs to 0x0. + */ +# define USBDRD_UCTL_CTL_CLEAR_BIST BIT(63) +/* 1 = Start BIST and cleared by hardware */ +# define USBDRD_UCTL_CTL_START_BIST BIT(62) +/* Reference clock select for SuperSpeed and HighSpeed PLLs: + * 0x0 = Both PLLs use DLMC_REF_CLK0 for reference clock + * 0x1 = Both PLLs use DLMC_REF_CLK1 for reference clock + * 0x2 = SuperSpeed PLL uses DLMC_REF_CLK0 for reference clock & + * HighSpeed PLL uses PLL_REF_CLK for reference clck + * 0x3 = SuperSpeed PLL uses DLMC_REF_CLK1 for reference clock & + * HighSpeed PLL uses PLL_REF_CLK for reference clck + */ +# define USBDRD_UCTL_CTL_REF_CLK_SEL GENMASK(61, 60) +/* 1 = Spread-spectrum clock enable, 0 = SS clock disable */ +# define USBDRD_UCTL_CTL_SSC_EN BIT(59) +/* Spread-spectrum clock modulation range: + * 0x0 = -4980 ppm downspread + * 0x1 = -4492 ppm downspread + * 0x2 = -4003 ppm downspread + * 0x3 - 0x7 = Reserved + */ +# define USBDRD_UCTL_CTL_SSC_RANGE GENMASK(58, 56) +/* Enable non-standard oscillator frequencies: + * [55:53] = modules -1 + * [52:47] = 2's complement push amount, 0 = Feature disabled + */ +# define USBDRD_UCTL_CTL_SSC_REF_CLK_SEL GENMASK(55, 47) +/* Reference clock multiplier for non-standard frequencies: + * 0x19 = 100MHz on DLMC_REF_CLK* if REF_CLK_SEL = 0x0 or 0x1 + * 0x28 = 125MHz on DLMC_REF_CLK* if REF_CLK_SEL = 0x0 or 0x1 + * 0x32 = 50MHz on DLMC_REF_CLK* if REF_CLK_SEL = 0x0 or 0x1 + * Other Values = Reserved + */ +# define USBDRD_UCTL_CTL_MPLL_MULTIPLIER GENMASK(46, 40) +/* Enable reference clock to prescaler for SuperSpeed functionality. + * Should always be set to "1" + */ +# define USBDRD_UCTL_CTL_REF_SSP_EN BIT(39) +/* Divide the reference clock by 2 before entering the + * REF_CLK_FSEL divider: + * If REF_CLK_SEL = 0x0 or 0x1, then only 0x0 is legal + * If REF_CLK_SEL = 0x2 or 0x3, then: + * 0x1 = DLMC_REF_CLK* is 125MHz + * 0x0 = DLMC_REF_CLK* is another supported frequency + */ +# define USBDRD_UCTL_CTL_REF_CLK_DIV2 BIT(38) +/* Select reference clock freqnuency for both PLL blocks: + * 0x27 = REF_CLK_SEL is 0x0 or 0x1 + * 0x07 = REF_CLK_SEL is 0x2 or 0x3 + */ +# define USBDRD_UCTL_CTL_REF_CLK_FSEL GENMASK(37, 32) +/* Controller clock enable. */ +# define USBDRD_UCTL_CTL_H_CLK_EN BIT(30) +/* Select bypass input to controller clock divider: + * 0x0 = Use divided coprocessor clock from H_CLKDIV + * 0x1 = Use clock from GPIO pins + */ +# define USBDRD_UCTL_CTL_H_CLK_BYP_SEL BIT(29) +/* Reset controller clock divider. */ +# define USBDRD_UCTL_CTL_H_CLKDIV_RST BIT(28) +/* Clock divider select: + * 0x0 = divide by 1 + * 0x1 = divide by 2 + * 0x2 = divide by 4 + * 0x3 = divide by 6 + * 0x4 = divide by 8 + * 0x5 = divide by 16 + * 0x6 = divide by 24 + * 0x7 = divide by 32 + */ +# define USBDRD_UCTL_CTL_H_CLKDIV_SEL GENMASK(26, 24) +/* USB3 port permanently attached: 0x0 = No, 0x1 = Yes */ +# define USBDRD_UCTL_CTL_USB3_PORT_PERM_ATTACH BIT(21) +/* USB2 port permanently attached: 0x0 = No, 0x1 = Yes */ +# define USBDRD_UCTL_CTL_USB2_PORT_PERM_ATTACH BIT(20) +/* Disable SuperSpeed PHY: 0x0 = No, 0x1 = Yes */ +# define USBDRD_UCTL_CTL_USB3_PORT_DISABLE BIT(18) +/* Disable HighSpeed PHY: 0x0 = No, 0x1 = Yes */ +# define USBDRD_UCTL_CTL_USB2_PORT_DISABLE BIT(16) +/* Enable PHY SuperSpeed block power: 0x0 = No, 0x1 = Yes */ +# define USBDRD_UCTL_CTL_SS_POWER_EN BIT(14) +/* Enable PHY HighSpeed block power: 0x0 = No, 0x1 = Yes */ +# define USBDRD_UCTL_CTL_HS_POWER_EN BIT(12) +/* Enable USB UCTL interface clock: 0xx = No, 0x1 = Yes */ +# define USBDRD_UCTL_CTL_CSCLK_EN BIT(4) +/* Controller mode: 0x0 = Host, 0x1 = Device */ +# define USBDRD_UCTL_CTL_DRD_MODE BIT(3) +/* PHY reset */ +# define USBDRD_UCTL_CTL_UPHY_RST BIT(2) +/* Software reset UAHC */ +# define USBDRD_UCTL_CTL_UAHC_RST BIT(1) +/* Software resets UCTL */ +# define USBDRD_UCTL_CTL_UCTL_RST BIT(0) + +#define USBDRD_UCTL_BIST_STATUS 0x08 +#define USBDRD_UCTL_SPARE0 0x10 +#define USBDRD_UCTL_INTSTAT 0x30 +#define USBDRD_UCTL_PORT_CFG_HS(port) (0x40 + (0x20 * port)) +#define USBDRD_UCTL_PORT_CFG_SS(port) (0x48 + (0x20 * port)) +#define USBDRD_UCTL_PORT_CR_DBG_CFG(port) (0x50 + (0x20 * port)) +#define USBDRD_UCTL_PORT_CR_DBG_STATUS(port) (0x58 + (0x20 * port)) -/* USB Control Register */ -union cvm_usbdrd_uctl_ctl { - uint64_t u64; - struct cvm_usbdrd_uctl_ctl_s { - /* 1 = BIST and set all USB RAMs to 0x0, 0 = BIST */ - __BITFIELD_FIELD(uint64_t clear_bist:1, - /* 1 = Start BIST and cleared by hardware */ - __BITFIELD_FIELD(uint64_t start_bist:1, - /* Reference clock select for SuperSpeed and HighSpeed PLLs: - * 0x0 = Both PLLs use DLMC_REF_CLK0 for reference clock - * 0x1 = Both PLLs use DLMC_REF_CLK1 for reference clock - * 0x2 = SuperSpeed PLL uses DLMC_REF_CLK0 for reference clock & - * HighSpeed PLL uses PLL_REF_CLK for reference clck - * 0x3 = SuperSpeed PLL uses DLMC_REF_CLK1 for reference clock & - * HighSpeed PLL uses PLL_REF_CLK for reference clck - */ - __BITFIELD_FIELD(uint64_t ref_clk_sel:2, - /* 1 = Spread-spectrum clock enable, 0 = SS clock disable */ - __BITFIELD_FIELD(uint64_t ssc_en:1, - /* Spread-spectrum clock modulation range: - * 0x0 = -4980 ppm downspread - * 0x1 = -4492 ppm downspread - * 0x2 = -4003 ppm downspread - * 0x3 - 0x7 = Reserved - */ - __BITFIELD_FIELD(uint64_t ssc_range:3, - /* Enable non-standard oscillator frequencies: - * [55:53] = modules -1 - * [52:47] = 2's complement push amount, 0 = Feature disabled - */ - __BITFIELD_FIELD(uint64_t ssc_ref_clk_sel:9, - /* Reference clock multiplier for non-standard frequencies: - * 0x19 = 100MHz on DLMC_REF_CLK* if REF_CLK_SEL = 0x0 or 0x1 - * 0x28 = 125MHz on DLMC_REF_CLK* if REF_CLK_SEL = 0x0 or 0x1 - * 0x32 = 50MHz on DLMC_REF_CLK* if REF_CLK_SEL = 0x0 or 0x1 - * Other Values = Reserved - */ - __BITFIELD_FIELD(uint64_t mpll_multiplier:7, - /* Enable reference clock to prescaler for SuperSpeed functionality. - * Should always be set to "1" - */ - __BITFIELD_FIELD(uint64_t ref_ssp_en:1, - /* Divide the reference clock by 2 before entering the - * REF_CLK_FSEL divider: - * If REF_CLK_SEL = 0x0 or 0x1, then only 0x0 is legal - * If REF_CLK_SEL = 0x2 or 0x3, then: - * 0x1 = DLMC_REF_CLK* is 125MHz - * 0x0 = DLMC_REF_CLK* is another supported frequency - */ - __BITFIELD_FIELD(uint64_t ref_clk_div2:1, - /* Select reference clock freqnuency for both PLL blocks: - * 0x27 = REF_CLK_SEL is 0x0 or 0x1 - * 0x07 = REF_CLK_SEL is 0x2 or 0x3 - */ - __BITFIELD_FIELD(uint64_t ref_clk_fsel:6, - /* Reserved */ - __BITFIELD_FIELD(uint64_t reserved_31_31:1, - /* Controller clock enable. */ - __BITFIELD_FIELD(uint64_t h_clk_en:1, - /* Select bypass input to controller clock divider: - * 0x0 = Use divided coprocessor clock from H_CLKDIV - * 0x1 = Use clock from GPIO pins - */ - __BITFIELD_FIELD(uint64_t h_clk_byp_sel:1, - /* Reset controller clock divider. */ - __BITFIELD_FIELD(uint64_t h_clkdiv_rst:1, - /* Reserved */ - __BITFIELD_FIELD(uint64_t reserved_27_27:1, - /* Clock divider select: - * 0x0 = divide by 1 - * 0x1 = divide by 2 - * 0x2 = divide by 4 - * 0x3 = divide by 6 - * 0x4 = divide by 8 - * 0x5 = divide by 16 - * 0x6 = divide by 24 - * 0x7 = divide by 32 - */ - __BITFIELD_FIELD(uint64_t h_clkdiv_sel:3, - /* Reserved */ - __BITFIELD_FIELD(uint64_t reserved_22_23:2, - /* USB3 port permanently attached: 0x0 = No, 0x1 = Yes */ - __BITFIELD_FIELD(uint64_t usb3_port_perm_attach:1, - /* USB2 port permanently attached: 0x0 = No, 0x1 = Yes */ - __BITFIELD_FIELD(uint64_t usb2_port_perm_attach:1, - /* Reserved */ - __BITFIELD_FIELD(uint64_t reserved_19_19:1, - /* Disable SuperSpeed PHY: 0x0 = No, 0x1 = Yes */ - __BITFIELD_FIELD(uint64_t usb3_port_disable:1, - /* Reserved */ - __BITFIELD_FIELD(uint64_t reserved_17_17:1, - /* Disable HighSpeed PHY: 0x0 = No, 0x1 = Yes */ - __BITFIELD_FIELD(uint64_t usb2_port_disable:1, - /* Reserved */ - __BITFIELD_FIELD(uint64_t reserved_15_15:1, - /* Enable PHY SuperSpeed block power: 0x0 = No, 0x1 = Yes */ - __BITFIELD_FIELD(uint64_t ss_power_en:1, - /* Reserved */ - __BITFIELD_FIELD(uint64_t reserved_13_13:1, - /* Enable PHY HighSpeed block power: 0x0 = No, 0x1 = Yes */ - __BITFIELD_FIELD(uint64_t hs_power_en:1, - /* Reserved */ - __BITFIELD_FIELD(uint64_t reserved_5_11:7, - /* Enable USB UCTL interface clock: 0xx = No, 0x1 = Yes */ - __BITFIELD_FIELD(uint64_t csclk_en:1, - /* Controller mode: 0x0 = Host, 0x1 = Device */ - __BITFIELD_FIELD(uint64_t drd_mode:1, - /* PHY reset */ - __BITFIELD_FIELD(uint64_t uphy_rst:1, - /* Software reset UAHC */ - __BITFIELD_FIELD(uint64_t uahc_rst:1, - /* Software resets UCTL */ - __BITFIELD_FIELD(uint64_t uctl_rst:1, - ;))))))))))))))))))))))))))))))))) - } s; -}; - -/* UAHC Configuration Register */ -union cvm_usbdrd_uctl_host_cfg { - uint64_t u64; - struct cvm_usbdrd_uctl_host_cfg_s { - /* Reserved */ - __BITFIELD_FIELD(uint64_t reserved_60_63:4, - /* Indicates minimum value of all received BELT values */ - __BITFIELD_FIELD(uint64_t host_current_belt:12, - /* Reserved */ - __BITFIELD_FIELD(uint64_t reserved_38_47:10, - /* HS jitter adjustment */ - __BITFIELD_FIELD(uint64_t fla:6, - /* Reserved */ - __BITFIELD_FIELD(uint64_t reserved_29_31:3, - /* Bus-master enable: 0x0 = Disabled (stall DMAs), 0x1 = enabled */ - __BITFIELD_FIELD(uint64_t bme:1, - /* Overcurrent protection enable: 0x0 = unavailable, 0x1 = available */ - __BITFIELD_FIELD(uint64_t oci_en:1, - /* Overcurrent sene selection: - * 0x0 = Overcurrent indication from off-chip is active-low - * 0x1 = Overcurrent indication from off-chip is active-high - */ - __BITFIELD_FIELD(uint64_t oci_active_high_en:1, - /* Port power control enable: 0x0 = unavailable, 0x1 = available */ - __BITFIELD_FIELD(uint64_t ppc_en:1, - /* Port power control sense selection: - * 0x0 = Port power to off-chip is active-low - * 0x1 = Port power to off-chip is active-high - */ - __BITFIELD_FIELD(uint64_t ppc_active_high_en:1, - /* Reserved */ - __BITFIELD_FIELD(uint64_t reserved_0_23:24, - ;))))))))))) - } s; -}; - -/* UCTL Shim Features Register */ -union cvm_usbdrd_uctl_shim_cfg { - uint64_t u64; - struct cvm_usbdrd_uctl_shim_cfg_s { - /* Out-of-bound UAHC register access: 0 = read, 1 = write */ - __BITFIELD_FIELD(uint64_t xs_ncb_oob_wrn:1, - /* Reserved */ - __BITFIELD_FIELD(uint64_t reserved_60_62:3, - /* SRCID error log for out-of-bound UAHC register access: - * [59:58] = chipID - * [57] = Request source: 0 = core, 1 = NCB-device - * [56:51] = Core/NCB-device number, [56] always 0 for NCB devices - * [50:48] = SubID - */ - __BITFIELD_FIELD(uint64_t xs_ncb_oob_osrc:12, - /* Error log for bad UAHC DMA access: 0 = Read log, 1 = Write log */ - __BITFIELD_FIELD(uint64_t xm_bad_dma_wrn:1, - /* Reserved */ - __BITFIELD_FIELD(uint64_t reserved_44_46:3, - /* Encoded error type for bad UAHC DMA */ - __BITFIELD_FIELD(uint64_t xm_bad_dma_type:4, - /* Reserved */ - __BITFIELD_FIELD(uint64_t reserved_13_39:27, - /* Select the IOI read command used by DMA accesses */ - __BITFIELD_FIELD(uint64_t dma_read_cmd:1, - /* Reserved */ - __BITFIELD_FIELD(uint64_t reserved_10_11:2, - /* Select endian format for DMA accesses to the L2c: - * 0x0 = Little endian - *` 0x1 = Big endian - * 0x2 = Reserved - * 0x3 = Reserved - */ - __BITFIELD_FIELD(uint64_t dma_endian_mode:2, - /* Reserved */ - __BITFIELD_FIELD(uint64_t reserved_2_7:6, - /* Select endian format for IOI CSR access to UAHC: - * 0x0 = Little endian - *` 0x1 = Big endian - * 0x2 = Reserved - * 0x3 = Reserved - */ - __BITFIELD_FIELD(uint64_t csr_endian_mode:2, - ;)))))))))))) - } s; -}; +/* + * UCTL Configuration Register + */ +#define USBDRD_UCTL_HOST_CFG 0xe0 +/* Indicates minimum value of all received BELT values */ +# define USBDRD_UCTL_HOST_CFG_HOST_CURRENT_BELT GENMASK(59, 48) +/* HS jitter adjustment */ +# define USBDRD_UCTL_HOST_CFG_FLA GENMASK(37, 32) +/* Bus-master enable: 0x0 = Disabled (stall DMAs), 0x1 = enabled */ +# define USBDRD_UCTL_HOST_CFG_BME BIT(28) +/* Overcurrent protection enable: 0x0 = unavailable, 0x1 = available */ +# define USBDRD_UCTL_HOST_OCI_EN BIT(27) +/* Overcurrent sene selection: + * 0x0 = Overcurrent indication from off-chip is active-low + * 0x1 = Overcurrent indication from off-chip is active-high + */ +# define USBDRD_UCTL_HOST_OCI_ACTIVE_HIGH_EN BIT(26) +/* Port power control enable: 0x0 = unavailable, 0x1 = available */ +# define USBDRD_UCTL_HOST_PPC_EN BIT(25) +/* Port power control sense selection: + * 0x0 = Port power to off-chip is active-low + * 0x1 = Port power to off-chip is active-high + */ +# define USBDRD_UCTL_HOST_PPC_ACTIVE_HIGH_EN BIT(24) + +/* + * UCTL Shim Features Register + */ +#define USBDRD_UCTL_SHIM_CFG 0xe8 +/* Out-of-bound UAHC register access: 0 = read, 1 = write */ +# define USBDRD_UCTL_SHIM_CFG_XS_NCB_OOB_WRN BIT(63) +/* SRCID error log for out-of-bound UAHC register access: + * [59:58] = chipID + * [57] = Request source: 0 = core, 1 = NCB-device + * [56:51] = Core/NCB-device number, [56] always 0 for NCB devices + * [50:48] = SubID + */ +# define USBDRD_UCTL_SHIM_CFG_XS_NCB_OOB_OSRC GENMASK(59, 48) +/* Error log for bad UAHC DMA access: 0 = Read log, 1 = Write log */ +# define USBDRD_UCTL_SHIM_CFG_XM_BAD_DMA_WRN BIT(47) +/* Encoded error type for bad UAHC DMA */ +# define USBDRD_UCTL_SHIM_CFG_XM_BAD_DMA_TYPE GENMASK(43, 40) +/* Select the IOI read command used by DMA accesses */ +# define USBDRD_UCTL_SHIM_CFG_DMA_READ_CMD BIT(12) +/* Select endian format for DMA accesses to the L2C: + * 0x0 = Little endian + * 0x1 = Big endian + * 0x2 = Reserved + * 0x3 = Reserved + */ +# define USBDRD_UCTL_SHIM_CFG_DMA_ENDIAN_MODE GENMASK(9, 8) +/* Select endian format for IOI CSR access to UAHC: + * 0x0 = Little endian + * 0x1 = Big endian + * 0x2 = Reserved + * 0x3 = Reserved + */ +# define USBDRD_UCTL_SHIM_CFG_CSR_ENDIAN_MODE GENMASK(1, 0) -#define OCTEON_H_CLKDIV_SEL 8 -#define OCTEON_MIN_H_CLK_RATE 150000000 -#define OCTEON_MAX_H_CLK_RATE 300000000 +#define USBDRD_UCTL_ECC 0xf0 +#define USBDRD_UCTL_SPARE1 0xf8 static DEFINE_MUTEX(dwc3_octeon_clocks_mutex); -static uint8_t clk_div[OCTEON_H_CLKDIV_SEL] = {1, 2, 4, 6, 8, 16, 24, 32}; +#ifdef CONFIG_CAVIUM_OCTEON_SOC +#include +static inline uint64_t dwc3_octeon_readq(void __iomem *addr) +{ + return cvmx_readq_csr(addr); +} -static int dwc3_octeon_config_power(struct device *dev, u64 base) +static inline void dwc3_octeon_writeq(void __iomem *base, uint64_t val) +{ + cvmx_writeq_csr(base, val); +} + +static void dwc3_octeon_config_gpio(int index, int gpio) { -#define UCTL_HOST_CFG 0xe0 - union cvm_usbdrd_uctl_host_cfg uctl_host_cfg; union cvmx_gpio_bit_cfgx gpio_bit; + + if ((OCTEON_IS_MODEL(OCTEON_CN73XX) || + OCTEON_IS_MODEL(OCTEON_CNF75XX)) + && gpio <= 31) { + gpio_bit.u64 = cvmx_read_csr(CVMX_GPIO_BIT_CFGX(gpio)); + gpio_bit.s.tx_oe = 1; + gpio_bit.s.output_sel = (index == 0 ? 0x14 : 0x15); + cvmx_write_csr(CVMX_GPIO_BIT_CFGX(gpio), gpio_bit.u64); + } else if (gpio <= 15) { + gpio_bit.u64 = cvmx_read_csr(CVMX_GPIO_BIT_CFGX(gpio)); + gpio_bit.s.tx_oe = 1; + gpio_bit.s.output_sel = (index == 0 ? 0x14 : 0x19); + cvmx_write_csr(CVMX_GPIO_BIT_CFGX(gpio), gpio_bit.u64); + } else { + gpio_bit.u64 = cvmx_read_csr(CVMX_GPIO_XBIT_CFGX(gpio)); + gpio_bit.s.tx_oe = 1; + gpio_bit.s.output_sel = (index == 0 ? 0x14 : 0x19); + cvmx_write_csr(CVMX_GPIO_XBIT_CFGX(gpio), gpio_bit.u64); + } +} +#else +static inline uint64_t dwc3_octeon_readq(void __iomem *addr) +{ + return 0; +} + +static inline void dwc3_octeon_writeq(void __iomem *base, uint64_t val) { } + +static inline void dwc3_octeon_config_gpio(int index, int gpio) { } +#endif + +static int dwc3_octeon_get_divider(void) +{ + static const uint8_t clk_div[] = { 1, 2, 4, 6, 8, 16, 24, 32 }; + int div = 0; + + while (div < ARRAY_SIZE(clk_div)) { + uint64_t rate = octeon_get_io_clock_rate() / clk_div[div]; + if (rate <= 300000000 && rate >= 150000000) + break; + div++; + } + + return div; +} + +static int dwc3_octeon_config_power(struct device *dev, void __iomem *base) +{ uint32_t gpio_pwr[3]; int gpio, len, power_active_low; struct device_node *node = dev->of_node; - int index = (base >> 24) & 1; + u64 val; + void __iomem *uctl_host_cfg_reg = base + USBDRD_UCTL_HOST_CFG; if (of_find_property(node, "power", &len) != NULL) { if (len == 12) { @@ -248,51 +271,33 @@ static int dwc3_octeon_config_power(struct device *dev, u64 base) dev_err(dev, "invalid power configuration\n"); return -EINVAL; } - if ((OCTEON_IS_MODEL(OCTEON_CN73XX) || - OCTEON_IS_MODEL(OCTEON_CNF75XX)) - && gpio <= 31) { - gpio_bit.u64 = cvmx_read_csr(CVMX_GPIO_BIT_CFGX(gpio)); - gpio_bit.s.tx_oe = 1; - gpio_bit.s.output_sel = (index == 0 ? 0x14 : 0x15); - cvmx_write_csr(CVMX_GPIO_BIT_CFGX(gpio), gpio_bit.u64); - } else if (gpio <= 15) { - gpio_bit.u64 = cvmx_read_csr(CVMX_GPIO_BIT_CFGX(gpio)); - gpio_bit.s.tx_oe = 1; - gpio_bit.s.output_sel = (index == 0 ? 0x14 : 0x19); - cvmx_write_csr(CVMX_GPIO_BIT_CFGX(gpio), gpio_bit.u64); - } else { - gpio_bit.u64 = cvmx_read_csr(CVMX_GPIO_XBIT_CFGX(gpio)); - gpio_bit.s.tx_oe = 1; - gpio_bit.s.output_sel = (index == 0 ? 0x14 : 0x19); - cvmx_write_csr(CVMX_GPIO_XBIT_CFGX(gpio), gpio_bit.u64); - } + dwc3_octeon_config_gpio(((u64)base >> 24) & 1, gpio); /* Enable XHCI power control and set if active high or low. */ - uctl_host_cfg.u64 = cvmx_read_csr(base + UCTL_HOST_CFG); - uctl_host_cfg.s.ppc_en = 1; - uctl_host_cfg.s.ppc_active_high_en = !power_active_low; - cvmx_write_csr(base + UCTL_HOST_CFG, uctl_host_cfg.u64); + val = dwc3_octeon_readq(uctl_host_cfg_reg); + val |= USBDRD_UCTL_HOST_PPC_EN; + if (power_active_low) + val &= ~USBDRD_UCTL_HOST_PPC_ACTIVE_HIGH_EN; + else + val |= USBDRD_UCTL_HOST_PPC_ACTIVE_HIGH_EN; + dwc3_octeon_writeq(uctl_host_cfg_reg, val); } else { /* Disable XHCI power control and set if active high. */ - uctl_host_cfg.u64 = cvmx_read_csr(base + UCTL_HOST_CFG); - uctl_host_cfg.s.ppc_en = 0; - uctl_host_cfg.s.ppc_active_high_en = 0; - cvmx_write_csr(base + UCTL_HOST_CFG, uctl_host_cfg.u64); + val = dwc3_octeon_readq(uctl_host_cfg_reg); + val &= ~USBDRD_UCTL_HOST_PPC_EN; + val &= ~USBDRD_UCTL_HOST_PPC_ACTIVE_HIGH_EN; + dwc3_octeon_writeq(uctl_host_cfg_reg, val); dev_info(dev, "power control disabled\n"); } return 0; } -static int dwc3_octeon_clocks_start(struct device *dev, u64 base) +static int dwc3_octeon_clocks_start(struct device *dev, void __iomem *base) { - union cvm_usbdrd_uctl_ctl uctl_ctl; - int ref_clk_sel = 2; - u64 div; + int i, div, mpll_mul, ref_clk_fsel, ref_clk_sel = 2; u32 clock_rate; - int mpll_mul; - int i; - u64 h_clk_rate; - u64 uctl_ctl_reg = base; + u64 val; + void __iomem *uctl_ctl_reg = base + USBDRD_UCTL_CTL; if (dev->of_node) { const char *ss_clock_type; @@ -356,44 +361,42 @@ static int dwc3_octeon_clocks_start(struct device *dev, u64 base) /* Step 2: Select GPIO for overcurrent indication, if desired. SKIP */ /* Step 3: Assert all resets. */ - uctl_ctl.u64 = cvmx_read_csr(uctl_ctl_reg); - uctl_ctl.s.uphy_rst = 1; - uctl_ctl.s.uahc_rst = 1; - uctl_ctl.s.uctl_rst = 1; - cvmx_write_csr(uctl_ctl_reg, uctl_ctl.u64); + val = dwc3_octeon_readq(uctl_ctl_reg); + val |= USBDRD_UCTL_CTL_UPHY_RST | + USBDRD_UCTL_CTL_UAHC_RST | + USBDRD_UCTL_CTL_UCTL_RST; + dwc3_octeon_writeq(uctl_ctl_reg, val); /* Step 4a: Reset the clock dividers. */ - uctl_ctl.u64 = cvmx_read_csr(uctl_ctl_reg); - uctl_ctl.s.h_clkdiv_rst = 1; - cvmx_write_csr(uctl_ctl_reg, uctl_ctl.u64); + val = dwc3_octeon_readq(uctl_ctl_reg); + val |= USBDRD_UCTL_CTL_H_CLKDIV_RST; + dwc3_octeon_writeq(uctl_ctl_reg, val); /* Step 4b: Select controller clock frequency. */ - for (div = 0; div < OCTEON_H_CLKDIV_SEL; div++) { - h_clk_rate = octeon_get_io_clock_rate() / clk_div[div]; - if (h_clk_rate <= OCTEON_MAX_H_CLK_RATE && - h_clk_rate >= OCTEON_MIN_H_CLK_RATE) - break; - } - uctl_ctl.u64 = cvmx_read_csr(uctl_ctl_reg); - uctl_ctl.s.h_clkdiv_sel = div; - uctl_ctl.s.h_clk_en = 1; - cvmx_write_csr(uctl_ctl_reg, uctl_ctl.u64); - uctl_ctl.u64 = cvmx_read_csr(uctl_ctl_reg); - if ((div != uctl_ctl.s.h_clkdiv_sel) || (!uctl_ctl.s.h_clk_en)) { + div = dwc3_octeon_get_divider(); + val = dwc3_octeon_readq(uctl_ctl_reg); + val &= ~USBDRD_UCTL_CTL_H_CLKDIV_SEL; + val |= FIELD_PREP(USBDRD_UCTL_CTL_H_CLKDIV_SEL, div); + val |= USBDRD_UCTL_CTL_H_CLK_EN; + dwc3_octeon_writeq(uctl_ctl_reg, val); + val = dwc3_octeon_readq(uctl_ctl_reg); + if ((div != FIELD_GET(USBDRD_UCTL_CTL_H_CLKDIV_SEL, val)) || + (!(FIELD_GET(USBDRD_UCTL_CTL_H_CLK_EN, val)))) { dev_err(dev, "dwc3 controller clock init failure.\n"); return -EINVAL; } /* Step 4c: Deassert the controller clock divider reset. */ - uctl_ctl.u64 = cvmx_read_csr(uctl_ctl_reg); - uctl_ctl.s.h_clkdiv_rst = 0; - cvmx_write_csr(uctl_ctl_reg, uctl_ctl.u64); + val &= ~USBDRD_UCTL_CTL_H_CLKDIV_RST; + dwc3_octeon_writeq(uctl_ctl_reg, val); /* Step 5a: Reference clock configuration. */ - uctl_ctl.u64 = cvmx_read_csr(uctl_ctl_reg); - uctl_ctl.s.ref_clk_sel = ref_clk_sel; - uctl_ctl.s.ref_clk_fsel = 0x07; - uctl_ctl.s.ref_clk_div2 = 0; + val = dwc3_octeon_readq(uctl_ctl_reg); + val &= ~USBDRD_UCTL_CTL_REF_CLK_DIV2; + val &= ~USBDRD_UCTL_CTL_REF_CLK_SEL; + val |= FIELD_PREP(USBDRD_UCTL_CTL_REF_CLK_SEL, ref_clk_sel); + + ref_clk_fsel = 0x07; switch (clock_rate) { default: dev_warn(dev, "Invalid ref_clk %u, using 100000000 instead\n", @@ -402,7 +405,7 @@ static int dwc3_octeon_clocks_start(struct device *dev, u64 base) case 100000000: mpll_mul = 0x19; if (ref_clk_sel < 2) - uctl_ctl.s.ref_clk_fsel = 0x27; + ref_clk_fsel = 0x27; break; case 50000000: mpll_mul = 0x32; @@ -411,28 +414,32 @@ static int dwc3_octeon_clocks_start(struct device *dev, u64 base) mpll_mul = 0x28; break; } - uctl_ctl.s.mpll_multiplier = mpll_mul; + val &= ~USBDRD_UCTL_CTL_REF_CLK_FSEL; + val |= FIELD_PREP(USBDRD_UCTL_CTL_REF_CLK_FSEL, ref_clk_fsel); + + val &= ~USBDRD_UCTL_CTL_MPLL_MULTIPLIER; + val |= FIELD_PREP(USBDRD_UCTL_CTL_MPLL_MULTIPLIER, mpll_mul); /* Step 5b: Configure and enable spread-spectrum for SuperSpeed. */ - uctl_ctl.s.ssc_en = 1; + val |= USBDRD_UCTL_CTL_SSC_EN; /* Step 5c: Enable SuperSpeed. */ - uctl_ctl.s.ref_ssp_en = 1; + val |= USBDRD_UCTL_CTL_REF_SSP_EN; /* Step 5d: Configure PHYs. SKIP */ /* Step 6a & 6b: Power up PHYs. */ - uctl_ctl.s.hs_power_en = 1; - uctl_ctl.s.ss_power_en = 1; - cvmx_write_csr(uctl_ctl_reg, uctl_ctl.u64); + val |= USBDRD_UCTL_CTL_HS_POWER_EN; + val |= USBDRD_UCTL_CTL_SS_POWER_EN; + dwc3_octeon_writeq(uctl_ctl_reg, val); /* Step 7: Wait 10 controller-clock cycles to take effect. */ udelay(10); /* Step 8a: Deassert UCTL reset signal. */ - uctl_ctl.u64 = cvmx_read_csr(uctl_ctl_reg); - uctl_ctl.s.uctl_rst = 0; - cvmx_write_csr(uctl_ctl_reg, uctl_ctl.u64); + val = dwc3_octeon_readq(uctl_ctl_reg); + val &= ~USBDRD_UCTL_CTL_UCTL_RST; + dwc3_octeon_writeq(uctl_ctl_reg, val); /* Step 8b: Wait 10 controller-clock cycles. */ udelay(10); @@ -442,53 +449,49 @@ static int dwc3_octeon_clocks_start(struct device *dev, u64 base) return -EINVAL; /* Step 8d: Deassert UAHC reset signal. */ - uctl_ctl.u64 = cvmx_read_csr(uctl_ctl_reg); - uctl_ctl.s.uahc_rst = 0; - cvmx_write_csr(uctl_ctl_reg, uctl_ctl.u64); + val = dwc3_octeon_readq(uctl_ctl_reg); + val &= ~USBDRD_UCTL_CTL_UAHC_RST; + dwc3_octeon_writeq(uctl_ctl_reg, val); /* Step 8e: Wait 10 controller-clock cycles. */ udelay(10); /* Step 9: Enable conditional coprocessor clock of UCTL. */ - uctl_ctl.u64 = cvmx_read_csr(uctl_ctl_reg); - uctl_ctl.s.csclk_en = 1; - cvmx_write_csr(uctl_ctl_reg, uctl_ctl.u64); + val = dwc3_octeon_readq(uctl_ctl_reg); + val |= USBDRD_UCTL_CTL_CSCLK_EN; + dwc3_octeon_writeq(uctl_ctl_reg, val); /*Step 10: Set for host mode only. */ - uctl_ctl.u64 = cvmx_read_csr(uctl_ctl_reg); - uctl_ctl.s.drd_mode = 0; - cvmx_write_csr(uctl_ctl_reg, uctl_ctl.u64); + val = dwc3_octeon_readq(uctl_ctl_reg); + val &= ~USBDRD_UCTL_CTL_DRD_MODE; + dwc3_octeon_writeq(uctl_ctl_reg, val); return 0; } -static void __init dwc3_octeon_set_endian_mode(u64 base) +static void __init dwc3_octeon_set_endian_mode(void __iomem *base) { -#define UCTL_SHIM_CFG 0xe8 - union cvm_usbdrd_uctl_shim_cfg shim_cfg; + u64 val; + void __iomem *uctl_shim_cfg_reg = base + USBDRD_UCTL_SHIM_CFG; - shim_cfg.u64 = cvmx_read_csr(base + UCTL_SHIM_CFG); + val = dwc3_octeon_readq(uctl_shim_cfg_reg); + val &= ~USBDRD_UCTL_SHIM_CFG_DMA_ENDIAN_MODE; + val &= ~USBDRD_UCTL_SHIM_CFG_CSR_ENDIAN_MODE; #ifdef __BIG_ENDIAN - shim_cfg.s.dma_endian_mode = 1; - shim_cfg.s.csr_endian_mode = 1; -#else - shim_cfg.s.dma_endian_mode = 0; - shim_cfg.s.csr_endian_mode = 0; + val |= FIELD_PREP(USBDRD_UCTL_SHIM_CFG_DMA_ENDIAN_MODE, 1); + val |= FIELD_PREP(USBDRD_UCTL_SHIM_CFG_CSR_ENDIAN_MODE, 1); #endif - cvmx_write_csr(base + UCTL_SHIM_CFG, shim_cfg.u64); + dwc3_octeon_writeq(uctl_shim_cfg_reg, val); } -#define CVMX_USBDRDX_UCTL_CTL(index) \ - (CVMX_ADD_IO_SEG(0x0001180068000000ull) + \ - ((index & 1) * 0x1000000ull)) -static void __init dwc3_octeon_phy_reset(u64 base) +static void __init dwc3_octeon_phy_reset(void __iomem *base) { - union cvm_usbdrd_uctl_ctl uctl_ctl; - int index = (base >> 24) & 1; + u64 val; + void __iomem *uctl_ctl_reg = base + USBDRD_UCTL_CTL; - uctl_ctl.u64 = cvmx_read_csr(CVMX_USBDRDX_UCTL_CTL(index)); - uctl_ctl.s.uphy_rst = 0; - cvmx_write_csr(CVMX_USBDRDX_UCTL_CTL(index), uctl_ctl.u64); + val = dwc3_octeon_readq(uctl_ctl_reg); + val &= ~USBDRD_UCTL_CTL_UPHY_RST; + dwc3_octeon_writeq(uctl_ctl_reg, val); } static int __init dwc3_octeon_device_init(void) @@ -527,10 +530,10 @@ static int __init dwc3_octeon_device_init(void) } mutex_lock(&dwc3_octeon_clocks_mutex); - if (dwc3_octeon_clocks_start(&pdev->dev, (u64)base) == 0) + if (dwc3_octeon_clocks_start(&pdev->dev, base) == 0) dev_info(&pdev->dev, "clocks initialized.\n"); - dwc3_octeon_set_endian_mode((u64)base); - dwc3_octeon_phy_reset((u64)base); + dwc3_octeon_set_endian_mode(base); + dwc3_octeon_phy_reset(base); mutex_unlock(&dwc3_octeon_clocks_mutex); devm_iounmap(&pdev->dev, base); devm_release_mem_region(&pdev->dev, res->start, diff --git a/arch/mips/cavium-octeon/smp.c b/arch/mips/cavium-octeon/smp.c index 4212584e6efa9f255f25b71f642e8ad25df5c851..33c09688210fff313b48e438986b95da0f53be6c 100644 --- a/arch/mips/cavium-octeon/smp.c +++ b/arch/mips/cavium-octeon/smp.c @@ -345,6 +345,7 @@ void play_dead(void) int cpu = cpu_number_map(cvmx_get_core_num()); idle_task_exit(); + cpuhp_ap_report_dead(); octeon_processor_boot = 0xff; per_cpu(cpu_state, cpu) = CPU_DEAD; diff --git a/arch/mips/configs/ar7_defconfig b/arch/mips/configs/ar7_defconfig index ed4a6388791ee493c80a466ed9ed73a449ec0cb7..329c60aa570ab4a2d21a6e0ce1b6e4cccd457641 100644 --- a/arch/mips/configs/ar7_defconfig +++ b/arch/mips/configs/ar7_defconfig @@ -11,7 +11,6 @@ CONFIG_EXPERT=y # CONFIG_KALLSYMS is not set # CONFIG_VM_EVENT_COUNTERS is not set # CONFIG_COMPAT_BRK is not set -CONFIG_SLAB=y CONFIG_AR7=y CONFIG_HZ_100=y CONFIG_KEXEC=y diff --git a/arch/mips/configs/bcm47xx_defconfig b/arch/mips/configs/bcm47xx_defconfig index 22ffde722bb9e031c100180ed7fb90d0a88b3b12..62c462a23edc64ceaf18a944bf365a3e1d69b496 100644 --- a/arch/mips/configs/bcm47xx_defconfig +++ b/arch/mips/configs/bcm47xx_defconfig @@ -3,7 +3,6 @@ CONFIG_HIGH_RES_TIMERS=y CONFIG_BLK_DEV_INITRD=y CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_EMBEDDED=y -CONFIG_SLAB=y CONFIG_BCM47XX=y CONFIG_PCI=y # CONFIG_SUSPEND is not set diff --git a/arch/mips/configs/bigsur_defconfig b/arch/mips/configs/bigsur_defconfig index d15961f00ece2d26dcfa2168571bac1e0a148d1d..b0cbfa781ffc9a1cc4def55d40cac9d53d80b680 100644 --- a/arch/mips/configs/bigsur_defconfig +++ b/arch/mips/configs/bigsur_defconfig @@ -17,7 +17,6 @@ CONFIG_USER_NS=y CONFIG_RELAY=y CONFIG_BLK_DEV_INITRD=y CONFIG_EXPERT=y -CONFIG_SLAB=y CONFIG_SIBYTE_BIGSUR=y CONFIG_64BIT=y CONFIG_SMP=y diff --git a/arch/mips/configs/cavium_octeon_defconfig b/arch/mips/configs/cavium_octeon_defconfig index 0bc2e3cc573b6164a239d6fa487fff88406e48a9..f523ee6f25bfef85337046d64facd308e2b237a7 100644 --- a/arch/mips/configs/cavium_octeon_defconfig +++ b/arch/mips/configs/cavium_octeon_defconfig @@ -9,7 +9,6 @@ CONFIG_LOG_BUF_SHIFT=14 CONFIG_RELAY=y CONFIG_BLK_DEV_INITRD=y CONFIG_EXPERT=y -CONFIG_SLAB=y CONFIG_CAVIUM_OCTEON_SOC=y CONFIG_CAVIUM_CN63XXP1=y CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE=2 diff --git a/arch/mips/configs/ci20_defconfig b/arch/mips/configs/ci20_defconfig index 11f08b6a3013f1d71fc58fa771cbc701c3a7a2be..812287a5b4fdce388bf123e325398cc0c454122b 100644 --- a/arch/mips/configs/ci20_defconfig +++ b/arch/mips/configs/ci20_defconfig @@ -19,19 +19,18 @@ CONFIG_USER_NS=y CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_KALLSYMS_ALL=y CONFIG_EMBEDDED=y -# CONFIG_VM_EVENT_COUNTERS is not set -# CONFIG_COMPAT_BRK is not set -CONFIG_SLAB=y CONFIG_MACH_INGENIC_SOC=y CONFIG_JZ4780_CI20=y CONFIG_HIGHMEM=y CONFIG_HZ_100=y -# CONFIG_SECCOMP is not set # CONFIG_SUSPEND is not set +# CONFIG_SECCOMP is not set CONFIG_MODULES=y # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +# CONFIG_COMPAT_BRK is not set # CONFIG_COMPACTION is not set CONFIG_CMA=y +# CONFIG_VM_EVENT_COUNTERS is not set CONFIG_NET=y CONFIG_PACKET=y CONFIG_UNIX=y @@ -40,7 +39,12 @@ CONFIG_IP_PNP=y CONFIG_IP_PNP_DHCP=y # CONFIG_INET_DIAG is not set # CONFIG_IPV6 is not set -# CONFIG_WIRELESS is not set +CONFIG_BT=m +# CONFIG_BT_LE is not set +CONFIG_BT_HCIUART=m +CONFIG_BT_HCIUART_BCM=y +CONFIG_CFG80211=m +CONFIG_CFG80211_WEXT=y CONFIG_DEVTMPFS=y CONFIG_FW_LOADER=m # CONFIG_ALLOW_DEV_COREDUMP is not set @@ -68,10 +72,27 @@ CONFIG_DM9000_FORCE_SIMPLE_PHY_POLL=y # CONFIG_NET_VENDOR_STMICRO is not set # CONFIG_NET_VENDOR_VIA is not set # CONFIG_NET_VENDOR_WIZNET is not set -# CONFIG_WLAN is not set +# CONFIG_WLAN_VENDOR_ADMTEK is not set +# CONFIG_WLAN_VENDOR_ATH is not set +# CONFIG_WLAN_VENDOR_ATMEL is not set +CONFIG_BRCMFMAC=m +# CONFIG_WLAN_VENDOR_CISCO is not set +# CONFIG_WLAN_VENDOR_INTEL is not set +# CONFIG_WLAN_VENDOR_INTERSIL is not set +# CONFIG_WLAN_VENDOR_MARVELL is not set +# CONFIG_WLAN_VENDOR_MEDIATEK is not set +# CONFIG_WLAN_VENDOR_MICROCHIP is not set +# CONFIG_WLAN_VENDOR_PURELIFI is not set +# CONFIG_WLAN_VENDOR_RALINK is not set +# CONFIG_WLAN_VENDOR_REALTEK is not set +# CONFIG_WLAN_VENDOR_RSI is not set +# CONFIG_WLAN_VENDOR_SILABS is not set +# CONFIG_WLAN_VENDOR_ST is not set +# CONFIG_WLAN_VENDOR_TI is not set +# CONFIG_WLAN_VENDOR_ZYDAS is not set +# CONFIG_WLAN_VENDOR_QUANTENNA is not set CONFIG_KEYBOARD_GPIO=m # CONFIG_INPUT_MOUSE is not set -CONFIG_VT_HW_CONSOLE_BINDING=y CONFIG_LEGACY_PTY_COUNT=2 CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250_CONSOLE=y @@ -79,6 +100,7 @@ CONFIG_SERIAL_8250_NR_UARTS=5 CONFIG_SERIAL_8250_RUNTIME_UARTS=5 CONFIG_SERIAL_8250_INGENIC=y CONFIG_SERIAL_OF_PLATFORM=y +CONFIG_SERIAL_DEV_BUS=y CONFIG_I2C=y CONFIG_I2C_JZ4780=y CONFIG_SPI=y @@ -99,13 +121,12 @@ CONFIG_IR_GPIO_CIR=m CONFIG_IR_GPIO_TX=m CONFIG_MEDIA_SUPPORT=m CONFIG_DRM=m +CONFIG_DRM_DISPLAY_CONNECTOR=m CONFIG_DRM_INGENIC=m CONFIG_DRM_INGENIC_DW_HDMI=m -CONFIG_DRM_DISPLAY_CONNECTOR=m -# CONFIG_VGA_CONSOLE is not set CONFIG_FB=y +# CONFIG_VGA_CONSOLE is not set CONFIG_FRAMEBUFFER_CONSOLE=y -# CONFIG_HID is not set CONFIG_USB=y CONFIG_USB_STORAGE=y CONFIG_USB_DWC2=y @@ -125,7 +146,6 @@ CONFIG_LEDS_TRIGGER_HEARTBEAT=y CONFIG_LEDS_TRIGGER_BACKLIGHT=m CONFIG_LEDS_TRIGGER_CPU=y CONFIG_LEDS_TRIGGER_ACTIVITY=y -CONFIG_LEDS_TRIGGER_GPIO=y CONFIG_LEDS_TRIGGER_DEFAULT_ON=y CONFIG_LEDS_TRIGGER_TRANSIENT=y CONFIG_LEDS_TRIGGER_CAMERA=m @@ -144,7 +164,6 @@ CONFIG_JZ4780_NEMC=y CONFIG_PWM=y CONFIG_PWM_JZ4740=m CONFIG_NVMEM_JZ4780_EFUSE=y -CONFIG_JZ4770_PHY=y CONFIG_EXT4_FS=y # CONFIG_DNOTIFY is not set CONFIG_AUTOFS_FS=y @@ -157,7 +176,6 @@ CONFIG_CONFIGFS_FS=y CONFIG_UBIFS_FS=y CONFIG_NFS_FS=y CONFIG_ROOT_NFS=y -CONFIG_NLS=y CONFIG_NLS_CODEPAGE_437=y CONFIG_NLS_CODEPAGE_737=y CONFIG_NLS_CODEPAGE_775=y @@ -196,6 +214,7 @@ CONFIG_NLS_ISO8859_15=y CONFIG_NLS_KOI8_R=y CONFIG_NLS_KOI8_U=y CONFIG_NLS_UTF8=y +# CONFIG_CRYPTO_AES is not set CONFIG_DMA_CMA=y CONFIG_CMA_SIZE_MBYTES=32 CONFIG_PRINTK_TIME=y @@ -206,7 +225,6 @@ CONFIG_DEBUG_FS=y CONFIG_PANIC_ON_OOPS=y CONFIG_PANIC_TIMEOUT=10 # CONFIG_SCHED_DEBUG is not set -# CONFIG_DEBUG_PREEMPT is not set CONFIG_STACKTRACE=y # CONFIG_FTRACE is not set CONFIG_CMDLINE_BOOL=y diff --git a/arch/mips/configs/cu1000-neo_defconfig b/arch/mips/configs/cu1000-neo_defconfig index 1cbc9302e1d140ba6b1a06efd29b2d9c3066ad86..afe39ce7568e6e934bce9a6c3edb8924a65ed319 100644 --- a/arch/mips/configs/cu1000-neo_defconfig +++ b/arch/mips/configs/cu1000-neo_defconfig @@ -18,7 +18,6 @@ CONFIG_KALLSYMS_ALL=y CONFIG_EMBEDDED=y # CONFIG_VM_EVENT_COUNTERS is not set # CONFIG_COMPAT_BRK is not set -CONFIG_SLAB=y CONFIG_MACH_INGENIC_SOC=y CONFIG_X1000_CU1000_NEO=y CONFIG_HIGHMEM=y diff --git a/arch/mips/configs/cu1830-neo_defconfig b/arch/mips/configs/cu1830-neo_defconfig index a0f73f3cd6ce7b787bf6c584ea9ef8ec8a005c13..347c9fd1c21d7ade486794be361a8ffbae98924c 100644 --- a/arch/mips/configs/cu1830-neo_defconfig +++ b/arch/mips/configs/cu1830-neo_defconfig @@ -18,7 +18,6 @@ CONFIG_KALLSYMS_ALL=y CONFIG_EMBEDDED=y # CONFIG_VM_EVENT_COUNTERS is not set # CONFIG_COMPAT_BRK is not set -CONFIG_SLAB=y CONFIG_MACH_INGENIC_SOC=y CONFIG_X1830_CU1830_NEO=y CONFIG_HIGHMEM=y diff --git a/arch/mips/configs/db1xxx_defconfig b/arch/mips/configs/db1xxx_defconfig index af070be1b583ae087f8f25dfacac2214c6eabd08..08d29b56e175358217cc823557157442b893e81c 100644 --- a/arch/mips/configs/db1xxx_defconfig +++ b/arch/mips/configs/db1xxx_defconfig @@ -18,7 +18,6 @@ CONFIG_CGROUP_DEVICE=y CONFIG_CGROUP_CPUACCT=y CONFIG_KALLSYMS_ALL=y CONFIG_EMBEDDED=y -CONFIG_SLAB=y CONFIG_MIPS_ALCHEMY=y CONFIG_HZ_100=y CONFIG_PCI=y diff --git a/arch/mips/configs/decstation_64_defconfig b/arch/mips/configs/decstation_64_defconfig index 49ec1575234ee31a68ed265015fd133ebfe7a187..92a1d0aea38c5afce192619ffdb9277635b0f0e3 100644 --- a/arch/mips/configs/decstation_64_defconfig +++ b/arch/mips/configs/decstation_64_defconfig @@ -9,7 +9,6 @@ CONFIG_EXPERT=y # CONFIG_SYSFS_SYSCALL is not set CONFIG_BPF_SYSCALL=y # CONFIG_COMPAT_BRK is not set -CONFIG_SLAB=y CONFIG_MACH_DECSTATION=y CONFIG_64BIT=y CONFIG_PAGE_SIZE_16KB=y diff --git a/arch/mips/configs/decstation_defconfig b/arch/mips/configs/decstation_defconfig index 5cec4c096e2c220c7759d9eda8fc24f66364e974..db214fcebcbe8b1ee79b923ba64a7bf18d2267fe 100644 --- a/arch/mips/configs/decstation_defconfig +++ b/arch/mips/configs/decstation_defconfig @@ -9,7 +9,6 @@ CONFIG_EXPERT=y # CONFIG_SYSFS_SYSCALL is not set CONFIG_BPF_SYSCALL=y # CONFIG_COMPAT_BRK is not set -CONFIG_SLAB=y CONFIG_MACH_DECSTATION=y CONFIG_CPU_R3000=y CONFIG_TC=y diff --git a/arch/mips/configs/decstation_r4k_defconfig b/arch/mips/configs/decstation_r4k_defconfig index af37e26d9b5b65607b46758145f736c337eb1d67..15b769e96d5b0b94088093a2ff438c22efedb2cc 100644 --- a/arch/mips/configs/decstation_r4k_defconfig +++ b/arch/mips/configs/decstation_r4k_defconfig @@ -9,7 +9,6 @@ CONFIG_EXPERT=y # CONFIG_SYSFS_SYSCALL is not set CONFIG_BPF_SYSCALL=y # CONFIG_COMPAT_BRK is not set -CONFIG_SLAB=y CONFIG_MACH_DECSTATION=y CONFIG_TC=y # CONFIG_SUSPEND is not set diff --git a/arch/mips/configs/fuloong2e_defconfig b/arch/mips/configs/fuloong2e_defconfig index 843d6a5a4f61581b77288d5da833ef7f0b2e3fc6..5458573286a2d847c32b03d04e4e0c8c7245e592 100644 --- a/arch/mips/configs/fuloong2e_defconfig +++ b/arch/mips/configs/fuloong2e_defconfig @@ -13,7 +13,6 @@ CONFIG_NAMESPACES=y CONFIG_USER_NS=y CONFIG_EXPERT=y # CONFIG_COMPAT_BRK is not set -CONFIG_SLAB=y CONFIG_PROFILING=y CONFIG_MACH_LOONGSON2EF=y CONFIG_PCI=y diff --git a/arch/mips/configs/gpr_defconfig b/arch/mips/configs/gpr_defconfig index eb755650f8212daaef7fc2fc6bdef1472302eae5..92fc0edbac474ee3a1d5b1131bbc9e83be112306 100644 --- a/arch/mips/configs/gpr_defconfig +++ b/arch/mips/configs/gpr_defconfig @@ -8,7 +8,6 @@ CONFIG_BSD_PROCESS_ACCT_V3=y CONFIG_RELAY=y CONFIG_BLK_DEV_INITRD=y CONFIG_EXPERT=y -CONFIG_SLAB=y CONFIG_PROFILING=y CONFIG_MIPS_ALCHEMY=y CONFIG_MIPS_GPR=y diff --git a/arch/mips/configs/ip22_defconfig b/arch/mips/configs/ip22_defconfig index 13df299012378780234c521da984e29dae7c1eb4..897e55579af09cd0b8a57dc2514219231d81823b 100644 --- a/arch/mips/configs/ip22_defconfig +++ b/arch/mips/configs/ip22_defconfig @@ -10,7 +10,6 @@ CONFIG_USER_NS=y CONFIG_RELAY=y CONFIG_EXPERT=y # CONFIG_COMPAT_BRK is not set -CONFIG_SLAB=y CONFIG_SGI_IP22=y CONFIG_ARC_CONSOLE=y CONFIG_CPU_R5000=y diff --git a/arch/mips/configs/ip27_defconfig b/arch/mips/configs/ip27_defconfig index 3e86f8106ba054d0d118969247737d92b9b57e00..b51f738a39a05ad9bd4c41971027774365ec30da 100644 --- a/arch/mips/configs/ip27_defconfig +++ b/arch/mips/configs/ip27_defconfig @@ -9,7 +9,6 @@ CONFIG_CGROUPS=y CONFIG_CPUSETS=y CONFIG_RELAY=y CONFIG_EXPERT=y -CONFIG_SLAB=y CONFIG_SGI_IP27=y CONFIG_NUMA=y CONFIG_SMP=y diff --git a/arch/mips/configs/ip28_defconfig b/arch/mips/configs/ip28_defconfig index ba13eea0509fd7f05dd50684b8a22fdfb450f6d0..e0040110a3eeb8787c0a80b9a0e3e0383a682091 100644 --- a/arch/mips/configs/ip28_defconfig +++ b/arch/mips/configs/ip28_defconfig @@ -5,7 +5,6 @@ CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=14 CONFIG_RELAY=y CONFIG_EXPERT=y -CONFIG_SLAB=y CONFIG_SGI_IP28=y CONFIG_ARC_CONSOLE=y CONFIG_EISA=y diff --git a/arch/mips/configs/ip32_defconfig b/arch/mips/configs/ip32_defconfig index 8ced2224c328b6485086b503e50c6d44f8d33078..418a4181e2fe7e63ecf76fa1cf16f3806bf98b72 100644 --- a/arch/mips/configs/ip32_defconfig +++ b/arch/mips/configs/ip32_defconfig @@ -7,7 +7,6 @@ CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=14 CONFIG_RELAY=y CONFIG_EXPERT=y -CONFIG_SLAB=y CONFIG_PROFILING=y CONFIG_SGI_IP32=y # CONFIG_SECCOMP is not set diff --git a/arch/mips/configs/jazz_defconfig b/arch/mips/configs/jazz_defconfig index 106b21cb677fca61eb9cfd09d8f97e32691ad0b0..6b5d7e963ed9bc79c16238678ef57da1b4a92791 100644 --- a/arch/mips/configs/jazz_defconfig +++ b/arch/mips/configs/jazz_defconfig @@ -7,7 +7,6 @@ CONFIG_BSD_PROCESS_ACCT=y CONFIG_LOG_BUF_SHIFT=14 CONFIG_RELAY=y CONFIG_EXPERT=y -CONFIG_SLAB=y CONFIG_MACH_JAZZ=y CONFIG_OLIVETTI_M700=y CONFIG_MIPS_MAGNUM_4000=y diff --git a/arch/mips/configs/loongson3_defconfig b/arch/mips/configs/loongson3_defconfig index 6f4a52608ea4be442b77e53b07840d3f08fdecd5..3087e64e6ebe75b67b48a23c25d6cac277c3f6b4 100644 --- a/arch/mips/configs/loongson3_defconfig +++ b/arch/mips/configs/loongson3_defconfig @@ -276,6 +276,13 @@ CONFIG_MEDIA_SUPPORT=m CONFIG_MEDIA_USB_SUPPORT=y CONFIG_USB_VIDEO_CLASS=m CONFIG_DRM=y +CONFIG_DRM_AMDGPU=m +CONFIG_DRM_AMDGPU_SI=y +CONFIG_DRM_AMDGPU_CIK=y +CONFIG_DRM_AMDGPU_USERPTR=y +CONFIG_DRM_AMD_ACP=y +CONFIG_DRM_AMD_DC=y +CONFIG_DRM_AMD_DC_SI=y CONFIG_DRM_RADEON=m CONFIG_DRM_QXL=y CONFIG_DRM_VIRTIO_GPU=y diff --git a/arch/mips/configs/malta_defconfig b/arch/mips/configs/malta_defconfig index 265d38dffbf6e17eb01565fe341ca30a425d431c..7432090477920389cc6157c17c11453c8c3f837e 100644 --- a/arch/mips/configs/malta_defconfig +++ b/arch/mips/configs/malta_defconfig @@ -7,7 +7,6 @@ CONFIG_RELAY=y CONFIG_BLK_DEV_INITRD=y CONFIG_EXPERT=y # CONFIG_COMPAT_BRK is not set -CONFIG_SLAB=y CONFIG_MIPS_MALTA=y CONFIG_CPU_LITTLE_ENDIAN=y CONFIG_CPU_MIPS32_R2=y diff --git a/arch/mips/configs/malta_kvm_defconfig b/arch/mips/configs/malta_kvm_defconfig index 1d2b248c7cd3f7450cdd8031010a39df73f9e42a..dd2b9c181f32a0f69234efd5d2444c8b5a0f8652 100644 --- a/arch/mips/configs/malta_kvm_defconfig +++ b/arch/mips/configs/malta_kvm_defconfig @@ -7,7 +7,6 @@ CONFIG_RELAY=y CONFIG_EXPERT=y CONFIG_PERF_EVENTS=y # CONFIG_COMPAT_BRK is not set -CONFIG_SLAB=y CONFIG_MIPS_MALTA=y CONFIG_CPU_LITTLE_ENDIAN=y CONFIG_CPU_MIPS32_R2=y diff --git a/arch/mips/configs/malta_qemu_32r6_defconfig b/arch/mips/configs/malta_qemu_32r6_defconfig index fd63a2b152f689945f269a31d672b561f607b88b..82183ec6bc318cf30e47e378b961ba62cf2868fb 100644 --- a/arch/mips/configs/malta_qemu_32r6_defconfig +++ b/arch/mips/configs/malta_qemu_32r6_defconfig @@ -6,7 +6,6 @@ CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=15 CONFIG_EMBEDDED=y -CONFIG_SLAB=y CONFIG_MIPS_MALTA=y CONFIG_CPU_LITTLE_ENDIAN=y CONFIG_CPU_MIPS32_R6=y diff --git a/arch/mips/configs/maltaaprp_defconfig b/arch/mips/configs/maltaaprp_defconfig index 1f07e354c9544d8495962ea2af96f4cf4ac250ad..9a199867a5e73d48461860b4539958c3b4c6ee83 100644 --- a/arch/mips/configs/maltaaprp_defconfig +++ b/arch/mips/configs/maltaaprp_defconfig @@ -6,7 +6,6 @@ CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=15 CONFIG_EMBEDDED=y -CONFIG_SLAB=y CONFIG_MIPS_MALTA=y CONFIG_CPU_LITTLE_ENDIAN=y CONFIG_CPU_MIPS32_R2=y diff --git a/arch/mips/configs/maltasmvp_defconfig b/arch/mips/configs/maltasmvp_defconfig index 5cd3eca236de2c57761f559e46374cedd803331c..e5502d66a47411d372ab15bad7d33275454ee42b 100644 --- a/arch/mips/configs/maltasmvp_defconfig +++ b/arch/mips/configs/maltasmvp_defconfig @@ -6,7 +6,6 @@ CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=15 CONFIG_EMBEDDED=y -CONFIG_SLAB=y CONFIG_MIPS_MALTA=y CONFIG_CPU_LITTLE_ENDIAN=y CONFIG_CPU_MIPS32_R2=y diff --git a/arch/mips/configs/maltasmvp_eva_defconfig b/arch/mips/configs/maltasmvp_eva_defconfig index 45688e742a15a35cbf0a4c85bdd8b595eb9361fb..a378aad97138df7706a51a30f18cbf1cd4523fb3 100644 --- a/arch/mips/configs/maltasmvp_eva_defconfig +++ b/arch/mips/configs/maltasmvp_eva_defconfig @@ -6,7 +6,6 @@ CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=15 CONFIG_EMBEDDED=y -CONFIG_SLAB=y CONFIG_MIPS_MALTA=y CONFIG_CPU_LITTLE_ENDIAN=y CONFIG_CPU_MIPS32_R2=y diff --git a/arch/mips/configs/maltaup_defconfig b/arch/mips/configs/maltaup_defconfig index 136f965784db47def816b8ce5f032782b5bacf9c..fc6f88cae7be5f4946db7d8ec35b1ad6b8464da0 100644 --- a/arch/mips/configs/maltaup_defconfig +++ b/arch/mips/configs/maltaup_defconfig @@ -7,7 +7,6 @@ CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=15 CONFIG_EMBEDDED=y -CONFIG_SLAB=y CONFIG_MIPS_MALTA=y CONFIG_CPU_LITTLE_ENDIAN=y CONFIG_CPU_MIPS32_R2=y diff --git a/arch/mips/configs/maltaup_xpa_defconfig b/arch/mips/configs/maltaup_xpa_defconfig index 75b8da8d992714f9c4e8fbec135dc69933c15b5a..97c2d7f530b39a3dd8eadce2767a3c919692d131 100644 --- a/arch/mips/configs/maltaup_xpa_defconfig +++ b/arch/mips/configs/maltaup_xpa_defconfig @@ -8,7 +8,6 @@ CONFIG_NAMESPACES=y CONFIG_RELAY=y CONFIG_EXPERT=y # CONFIG_COMPAT_BRK is not set -CONFIG_SLAB=y CONFIG_MIPS_MALTA=y CONFIG_CPU_LITTLE_ENDIAN=y CONFIG_CPU_MIPS32_R2=y diff --git a/arch/mips/configs/mtx1_defconfig b/arch/mips/configs/mtx1_defconfig index a5c68e9b0482dcedc3c3b8a8516c5e5190b53728..b6417217916027869a3fd1d218f73e984cf3184c 100644 --- a/arch/mips/configs/mtx1_defconfig +++ b/arch/mips/configs/mtx1_defconfig @@ -8,7 +8,6 @@ CONFIG_BSD_PROCESS_ACCT_V3=y CONFIG_RELAY=y CONFIG_BLK_DEV_INITRD=y CONFIG_EXPERT=y -CONFIG_SLAB=y CONFIG_PROFILING=y CONFIG_MIPS_ALCHEMY=y CONFIG_MIPS_MTX1=y diff --git a/arch/mips/configs/pic32mzda_defconfig b/arch/mips/configs/pic32mzda_defconfig index 48dd02d01ac192fa570a75559e3f3d0143442619..8397f28355d5fb31ea04a5a0eec90a9de18323ca 100644 --- a/arch/mips/configs/pic32mzda_defconfig +++ b/arch/mips/configs/pic32mzda_defconfig @@ -9,7 +9,6 @@ CONFIG_RELAY=y CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_EMBEDDED=y # CONFIG_COMPAT_BRK is not set -CONFIG_SLAB=y CONFIG_MACH_PIC32=y CONFIG_DTB_PIC32_MZDA_SK=y CONFIG_HZ_100=y diff --git a/arch/mips/configs/qi_lb60_defconfig b/arch/mips/configs/qi_lb60_defconfig index 7e5d9741bd5ddb53f5631d1747b50046baa033fc..c27c8c7151a1d5c14331f4c949b09340d0e3794a 100644 --- a/arch/mips/configs/qi_lb60_defconfig +++ b/arch/mips/configs/qi_lb60_defconfig @@ -6,7 +6,6 @@ CONFIG_KALLSYMS_ALL=y CONFIG_EMBEDDED=y # CONFIG_VM_EVENT_COUNTERS is not set # CONFIG_COMPAT_BRK is not set -CONFIG_SLAB=y CONFIG_MACH_INGENIC_SOC=y CONFIG_JZ4740_QI_LB60=y CONFIG_HZ_100=y diff --git a/arch/mips/configs/rb532_defconfig b/arch/mips/configs/rb532_defconfig index 93306f5e045b41e689e79dd3ec1f654440a14fba..02ec6c1a51163e70a7ec89cd5a1b0aa95fc3abf1 100644 --- a/arch/mips/configs/rb532_defconfig +++ b/arch/mips/configs/rb532_defconfig @@ -11,7 +11,6 @@ CONFIG_EXPERT=y # CONFIG_ELF_CORE is not set # CONFIG_KALLSYMS is not set # CONFIG_VM_EVENT_COUNTERS is not set -CONFIG_SLAB=y CONFIG_MIKROTIK_RB532=y CONFIG_HZ_100=y # CONFIG_SECCOMP is not set diff --git a/arch/mips/configs/rbtx49xx_defconfig b/arch/mips/configs/rbtx49xx_defconfig index 30c195f2827816b345fb2fe7dc9c2f3eb94ff0b5..03a7bbe28a532d81f4afe3e22c449c538c660b6c 100644 --- a/arch/mips/configs/rbtx49xx_defconfig +++ b/arch/mips/configs/rbtx49xx_defconfig @@ -7,7 +7,6 @@ CONFIG_LOG_BUF_SHIFT=14 CONFIG_BLK_DEV_INITRD=y CONFIG_EXPERT=y # CONFIG_EPOLL is not set -CONFIG_SLAB=y CONFIG_MACH_TX49XX=y CONFIG_TOSHIBA_RBTX4927=y # CONFIG_SECCOMP is not set diff --git a/arch/mips/configs/rm200_defconfig b/arch/mips/configs/rm200_defconfig index 9932a593e3c39604e932333290ac6b0d45c20310..7475c2cbea898adede9527499907b1a53f6ac3c9 100644 --- a/arch/mips/configs/rm200_defconfig +++ b/arch/mips/configs/rm200_defconfig @@ -7,7 +7,6 @@ CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=14 CONFIG_RELAY=y CONFIG_EXPERT=y -CONFIG_SLAB=y CONFIG_SNI_RM=y CONFIG_CPU_LITTLE_ENDIAN=y CONFIG_ARC_CONSOLE=y diff --git a/arch/mips/configs/rs90_defconfig b/arch/mips/configs/rs90_defconfig index 7ce3b814fdc847d51f91e1c2fe27057b72190b0f..85ea2a6775f52fc708688be437e661ca4560ea0a 100644 --- a/arch/mips/configs/rs90_defconfig +++ b/arch/mips/configs/rs90_defconfig @@ -17,7 +17,6 @@ CONFIG_LD_DEAD_CODE_DATA_ELIMINATION=y # CONFIG_KALLSYMS is not set CONFIG_EMBEDDED=y # CONFIG_PERF_EVENTS is not set -CONFIG_SLAB=y CONFIG_PROFILING=y CONFIG_MACH_INGENIC_SOC=y CONFIG_JZ4740_RS90=y diff --git a/arch/mips/configs/sb1250_swarm_defconfig b/arch/mips/configs/sb1250_swarm_defconfig index 030186f895016ad227ebe72ccaa13991e5251650..ce855b644bb03dbfada16944351395321ee989d2 100644 --- a/arch/mips/configs/sb1250_swarm_defconfig +++ b/arch/mips/configs/sb1250_swarm_defconfig @@ -10,7 +10,6 @@ CONFIG_RELAY=y CONFIG_BLK_DEV_INITRD=y CONFIG_EXPERT=y # CONFIG_COMPAT_BRK is not set -CONFIG_SLAB=y CONFIG_SIBYTE_SWARM=y CONFIG_CPU_SB1_PASS_2_2=y CONFIG_64BIT=y diff --git a/arch/mips/generic/board-ingenic.c b/arch/mips/generic/board-ingenic.c index c422bbc890eda3f2ceb0455260058f2d8a0907b0..1f4906875e7bc2ce5644438f7bd417261f4f1ed9 100644 --- a/arch/mips/generic/board-ingenic.c +++ b/arch/mips/generic/board-ingenic.c @@ -17,6 +17,7 @@ #include #include +#include #include #include @@ -60,6 +61,50 @@ static __init char *ingenic_get_system_type(unsigned long machtype) } } +#define INGENIC_CGU_BASE 0x10000000 +#define JZ4750_CGU_CPCCR_ECS BIT(30) +#define JZ4760_CGU_CPCCR_ECS BIT(31) + +static __init void ingenic_force_12M_ext(const void *fdt, unsigned int mask) +{ + const __be32 *prop; + unsigned int cpccr; + void __iomem *cgu; + bool use_div; + int offset; + + offset = fdt_path_offset(fdt, "/ext"); + if (offset < 0) + return; + + prop = fdt_getprop(fdt, offset, "clock-frequency", NULL); + if (!prop) + return; + + /* + * If the external oscillator is 24 MHz, enable the /2 divider to + * drive it down to 12 MHz, since this is what the hardware can work + * with. + * The 16 MHz cutoff value is arbitrary; setting it to 12 MHz would not + * work as the crystal frequency (as reported in the Device Tree) might + * be slightly above this value. + */ + use_div = be32_to_cpup(prop) >= 16000000; + + cgu = ioremap(INGENIC_CGU_BASE, 0x4); + if (!cgu) + return; + + cpccr = ioread32(cgu); + if (use_div) + cpccr |= mask; + else + cpccr &= ~mask; + iowrite32(cpccr, cgu); + + iounmap(cgu); +} + static __init const void *ingenic_fixup_fdt(const void *fdt, const void *match_data) { /* @@ -73,6 +118,18 @@ static __init const void *ingenic_fixup_fdt(const void *fdt, const void *match_d mips_machtype = (unsigned long)match_data; system_type = ingenic_get_system_type(mips_machtype); + switch (mips_machtype) { + case MACH_INGENIC_JZ4750: + case MACH_INGENIC_JZ4755: + ingenic_force_12M_ext(fdt, JZ4750_CGU_CPCCR_ECS); + break; + case MACH_INGENIC_JZ4760: + ingenic_force_12M_ext(fdt, JZ4760_CGU_CPCCR_ECS); + break; + default: + break; + } + return fdt; } @@ -117,14 +174,14 @@ static void ingenic_halt(void) ingenic_wait_instr(); } -static int __maybe_unused ingenic_pm_enter(suspend_state_t state) +static int ingenic_pm_enter(suspend_state_t state) { ingenic_wait_instr(); return 0; } -static const struct platform_suspend_ops ingenic_pm_ops __maybe_unused = { +static const struct platform_suspend_ops ingenic_pm_ops = { .valid = suspend_valid_only_mem, .enter = ingenic_pm_enter, }; diff --git a/arch/mips/include/asm/atomic.h b/arch/mips/include/asm/atomic.h index 712fb5a6a5682b26d0e78a862796deecc4130b05..ba188e77768b28785fa5d453b9189ffd5a0627d2 100644 --- a/arch/mips/include/asm/atomic.h +++ b/arch/mips/include/asm/atomic.h @@ -33,17 +33,6 @@ static __always_inline void arch_##pfx##_set(pfx##_t *v, type i) \ { \ WRITE_ONCE(v->counter, i); \ } \ - \ -static __always_inline type \ -arch_##pfx##_cmpxchg(pfx##_t *v, type o, type n) \ -{ \ - return arch_cmpxchg(&v->counter, o, n); \ -} \ - \ -static __always_inline type arch_##pfx##_xchg(pfx##_t *v, type n) \ -{ \ - return arch_xchg(&v->counter, n); \ -} ATOMIC_OPS(atomic, int) diff --git a/arch/mips/include/asm/bugs.h b/arch/mips/include/asm/bugs.h index 653f78f3a6852e443ff82f520e9dba477d51a696..84be74afcb9a354669e451b5153baf01f2eb4f6e 100644 --- a/arch/mips/include/asm/bugs.h +++ b/arch/mips/include/asm/bugs.h @@ -1,17 +1,11 @@ /* SPDX-License-Identifier: GPL-2.0 */ /* - * This is included by init/main.c to check for architecture-dependent bugs. - * * Copyright (C) 2007 Maciej W. Rozycki - * - * Needs: - * void check_bugs(void); */ #ifndef _ASM_BUGS_H #define _ASM_BUGS_H #include -#include #include #include @@ -24,17 +18,6 @@ extern void check_bugs64_early(void); extern void check_bugs32(void); extern void check_bugs64(void); -static inline void __init check_bugs(void) -{ - unsigned int cpu = smp_processor_id(); - - cpu_data[cpu].udelay_val = loops_per_jiffy; - check_bugs32(); - - if (IS_ENABLED(CONFIG_CPU_R4X00_BUGS64)) - check_bugs64(); -} - static inline int r4k_daddiu_bug(void) { if (!IS_ENABLED(CONFIG_CPU_R4X00_BUGS64)) diff --git a/arch/mips/include/asm/cpu-features.h b/arch/mips/include/asm/cpu-features.h index 51a1737b03d0cc718960da170cb3996ff585f273..404390bb87eaf5b3391b3d38be7cd3e43849dde2 100644 --- a/arch/mips/include/asm/cpu-features.h +++ b/arch/mips/include/asm/cpu-features.h @@ -125,7 +125,7 @@ ({ \ int __res; \ \ - switch (current_cpu_type()) { \ + switch (boot_cpu_type()) { \ case CPU_CAVIUM_OCTEON: \ case CPU_CAVIUM_OCTEON_PLUS: \ case CPU_CAVIUM_OCTEON2: \ @@ -368,7 +368,7 @@ ({ \ int __res; \ \ - switch (current_cpu_type()) { \ + switch (boot_cpu_type()) { \ case CPU_M14KC: \ case CPU_74K: \ case CPU_1074K: \ diff --git a/arch/mips/include/asm/dec/prom.h b/arch/mips/include/asm/dec/prom.h index 1e1247add1cf802b9abe3a5216b3a785f83e5988..908e96e3a3117e6d738e86e26596077778963f5a 100644 --- a/arch/mips/include/asm/dec/prom.h +++ b/arch/mips/include/asm/dec/prom.h @@ -70,7 +70,7 @@ static inline bool prom_is_rex(u32 magic) */ typedef struct { int pagesize; - unsigned char bitmap[0]; + unsigned char bitmap[]; } memmap; diff --git a/arch/mips/include/asm/fw/cfe/cfe_api.h b/arch/mips/include/asm/fw/cfe/cfe_api.h index 25df2f4deb31f1ef612d4141c877916c68fb12ba..b52a6a9c26f19a37da521dfa223f81bed995717d 100644 --- a/arch/mips/include/asm/fw/cfe/cfe_api.h +++ b/arch/mips/include/asm/fw/cfe/cfe_api.h @@ -17,9 +17,6 @@ #include #include -typedef long intptr_t; - - /* * Constants */ diff --git a/arch/mips/include/asm/io.h b/arch/mips/include/asm/io.h index cc28d207a06106fec1e375fb92e74639857ab606..affd21e9c20b42b749eefdfa9765932fe0245d47 100644 --- a/arch/mips/include/asm/io.h +++ b/arch/mips/include/asm/io.h @@ -554,6 +554,7 @@ extern void (*_dma_cache_inv)(unsigned long start, unsigned long size); * access */ #define xlate_dev_mem_ptr(p) __va(p) +#define unxlate_dev_mem_ptr(p, v) do { } while (0) void __ioread64_copy(void *to, const void __iomem *from, size_t count); diff --git a/arch/mips/include/asm/irq.h b/arch/mips/include/asm/irq.h index 44f9824c1d8c3b855fcf4b5c6a814476d3e9452a..75abfa834ab7ac7dc9caa66a7ec2da62acc020df 100644 --- a/arch/mips/include/asm/irq.h +++ b/arch/mips/include/asm/irq.h @@ -19,7 +19,6 @@ #define IRQ_STACK_SIZE THREAD_SIZE #define IRQ_STACK_START (IRQ_STACK_SIZE - 16) -extern void __init init_IRQ(void); extern void *irq_stack[NR_CPUS]; /* diff --git a/arch/mips/include/asm/kvm_host.h b/arch/mips/include/asm/kvm_host.h index 957121a495f0b744d3881f9d59627a89e269bb6c..04cedf9f88115e0f25a7b7731a725a1a64e72739 100644 --- a/arch/mips/include/asm/kvm_host.h +++ b/arch/mips/include/asm/kvm_host.h @@ -317,7 +317,7 @@ struct kvm_vcpu_arch { unsigned int aux_inuse; /* COP0 State */ - struct mips_coproc *cop0; + struct mips_coproc cop0; /* Resume PC after MMIO completion */ unsigned long io_pc; @@ -698,7 +698,7 @@ static inline bool kvm_mips_guest_can_have_fpu(struct kvm_vcpu_arch *vcpu) static inline bool kvm_mips_guest_has_fpu(struct kvm_vcpu_arch *vcpu) { return kvm_mips_guest_can_have_fpu(vcpu) && - kvm_read_c0_guest_config1(vcpu->cop0) & MIPS_CONF1_FP; + kvm_read_c0_guest_config1(&vcpu->cop0) & MIPS_CONF1_FP; } static inline bool kvm_mips_guest_can_have_msa(struct kvm_vcpu_arch *vcpu) @@ -710,7 +710,7 @@ static inline bool kvm_mips_guest_can_have_msa(struct kvm_vcpu_arch *vcpu) static inline bool kvm_mips_guest_has_msa(struct kvm_vcpu_arch *vcpu) { return kvm_mips_guest_can_have_msa(vcpu) && - kvm_read_c0_guest_config3(vcpu->cop0) & MIPS_CONF3_MSA; + kvm_read_c0_guest_config3(&vcpu->cop0) & MIPS_CONF3_MSA; } struct kvm_mips_callbacks { diff --git a/arch/mips/include/asm/mach-au1x00/gpio-au1000.h b/arch/mips/include/asm/mach-au1x00/gpio-au1000.h index adde1fa5097e6c34dd85cfa96146d97e21647135..82bc2766e2ec1386f3fa2492670650795e902d8a 100644 --- a/arch/mips/include/asm/mach-au1x00/gpio-au1000.h +++ b/arch/mips/include/asm/mach-au1x00/gpio-au1000.h @@ -500,11 +500,6 @@ static inline int alchemy_gpio_is_valid(int gpio) alchemy_gpio1_is_valid(gpio); } -static inline int alchemy_gpio_cansleep(int gpio) -{ - return 0; /* Alchemy never gets tired */ -} - static inline int alchemy_gpio_to_irq(int gpio) { return (gpio >= ALCHEMY_GPIO2_BASE) ? diff --git a/arch/mips/include/asm/mach-au1x00/gpio-au1300.h b/arch/mips/include/asm/mach-au1x00/gpio-au1300.h index d16add7ba49d5d29e7f8986806f44ace4540b825..43d44f384f974b9967c2064d5cf6fb9212e513cb 100644 --- a/arch/mips/include/asm/mach-au1x00/gpio-au1300.h +++ b/arch/mips/include/asm/mach-au1x00/gpio-au1300.h @@ -98,11 +98,6 @@ static inline int au1300_gpio_is_valid(unsigned int gpio) return ret; } -static inline int au1300_gpio_cansleep(unsigned int gpio) -{ - return 0; -} - /* hardware remembers gpio 0-63 levels on powerup */ static inline int au1300_gpio_getinitlvl(unsigned int gpio) { diff --git a/arch/mips/include/asm/mach-loongson32/loongson1.h b/arch/mips/include/asm/mach-loongson32/loongson1.h index eb3ddbec1752f8ef947d760a9d61d35cde1ae612..7971272345d31bbaed3e816d0c7e60f8300bc33f 100644 --- a/arch/mips/include/asm/mach-loongson32/loongson1.h +++ b/arch/mips/include/asm/mach-loongson32/loongson1.h @@ -47,8 +47,6 @@ #include #include -#include #include -#include #endif /* __ASM_MACH_LOONGSON32_LOONGSON1_H */ diff --git a/arch/mips/include/asm/mach-loongson32/regs-pwm.h b/arch/mips/include/asm/mach-loongson32/regs-pwm.h deleted file mode 100644 index ec870c82d492b9434d24a9f58d5c775340118441..0000000000000000000000000000000000000000 --- a/arch/mips/include/asm/mach-loongson32/regs-pwm.h +++ /dev/null @@ -1,25 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * Copyright (c) 2014 Zhang, Keguang - * - * Loongson 1 PWM Register Definitions. - */ - -#ifndef __ASM_MACH_LOONGSON32_REGS_PWM_H -#define __ASM_MACH_LOONGSON32_REGS_PWM_H - -/* Loongson 1 PWM Timer Register Definitions */ -#define PWM_CNT 0x0 -#define PWM_HRC 0x4 -#define PWM_LRC 0x8 -#define PWM_CTRL 0xc - -/* PWM Control Register Bits */ -#define CNT_RST BIT(7) -#define INT_SR BIT(6) -#define INT_EN BIT(5) -#define PWM_SINGLE BIT(4) -#define PWM_OE BIT(3) -#define CNT_EN BIT(0) - -#endif /* __ASM_MACH_LOONGSON32_REGS_PWM_H */ diff --git a/arch/mips/include/asm/mach-loongson32/regs-wdt.h b/arch/mips/include/asm/mach-loongson32/regs-wdt.h deleted file mode 100644 index c6d345fe13f23785d47a8bd8736ac4fceb811b8e..0000000000000000000000000000000000000000 --- a/arch/mips/include/asm/mach-loongson32/regs-wdt.h +++ /dev/null @@ -1,15 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * Copyright (c) 2011 Zhang, Keguang - * - * Loongson 1 Watchdog Register Definitions. - */ - -#ifndef __ASM_MACH_LOONGSON32_REGS_WDT_H -#define __ASM_MACH_LOONGSON32_REGS_WDT_H - -#define WDT_EN 0x0 -#define WDT_TIMER 0x4 -#define WDT_SET 0x8 - -#endif /* __ASM_MACH_LOONGSON32_REGS_WDT_H */ diff --git a/arch/mips/include/asm/mach-ralink/mt7620.h b/arch/mips/include/asm/mach-ralink/mt7620.h index 3e37705ea9cf5bb65959185d30fa71f23c4938ce..62f4f072c0031d913469ba9ec8b9205fb6c212c7 100644 --- a/arch/mips/include/asm/mach-ralink/mt7620.h +++ b/arch/mips/include/asm/mach-ralink/mt7620.h @@ -20,52 +20,17 @@ #define SYSC_REG_CHIP_REV 0x0c #define SYSC_REG_SYSTEM_CONFIG0 0x10 #define SYSC_REG_SYSTEM_CONFIG1 0x14 -#define SYSC_REG_CLKCFG0 0x2c -#define SYSC_REG_CPU_SYS_CLKCFG 0x3c -#define SYSC_REG_CPLL_CONFIG0 0x54 -#define SYSC_REG_CPLL_CONFIG1 0x58 #define MT7620_CHIP_NAME0 0x3637544d #define MT7620_CHIP_NAME1 0x20203032 #define MT7628_CHIP_NAME1 0x20203832 -#define SYSCFG0_XTAL_FREQ_SEL BIT(6) - #define CHIP_REV_PKG_MASK 0x1 #define CHIP_REV_PKG_SHIFT 16 #define CHIP_REV_VER_MASK 0xf #define CHIP_REV_VER_SHIFT 8 #define CHIP_REV_ECO_MASK 0xf -#define CLKCFG0_PERI_CLK_SEL BIT(4) - -#define CPU_SYS_CLKCFG_OCP_RATIO_SHIFT 16 -#define CPU_SYS_CLKCFG_OCP_RATIO_MASK 0xf -#define CPU_SYS_CLKCFG_OCP_RATIO_1 0 /* 1:1 (Reserved) */ -#define CPU_SYS_CLKCFG_OCP_RATIO_1_5 1 /* 1:1.5 (Reserved) */ -#define CPU_SYS_CLKCFG_OCP_RATIO_2 2 /* 1:2 */ -#define CPU_SYS_CLKCFG_OCP_RATIO_2_5 3 /* 1:2.5 (Reserved) */ -#define CPU_SYS_CLKCFG_OCP_RATIO_3 4 /* 1:3 */ -#define CPU_SYS_CLKCFG_OCP_RATIO_3_5 5 /* 1:3.5 (Reserved) */ -#define CPU_SYS_CLKCFG_OCP_RATIO_4 6 /* 1:4 */ -#define CPU_SYS_CLKCFG_OCP_RATIO_5 7 /* 1:5 */ -#define CPU_SYS_CLKCFG_OCP_RATIO_10 8 /* 1:10 */ -#define CPU_SYS_CLKCFG_CPU_FDIV_SHIFT 8 -#define CPU_SYS_CLKCFG_CPU_FDIV_MASK 0x1f -#define CPU_SYS_CLKCFG_CPU_FFRAC_SHIFT 0 -#define CPU_SYS_CLKCFG_CPU_FFRAC_MASK 0x1f - -#define CPLL_CFG0_SW_CFG BIT(31) -#define CPLL_CFG0_PLL_MULT_RATIO_SHIFT 16 -#define CPLL_CFG0_PLL_MULT_RATIO_MASK 0x7 -#define CPLL_CFG0_LC_CURFCK BIT(15) -#define CPLL_CFG0_BYPASS_REF_CLK BIT(14) -#define CPLL_CFG0_PLL_DIV_RATIO_SHIFT 10 -#define CPLL_CFG0_PLL_DIV_RATIO_MASK 0x3 - -#define CPLL_CFG1_CPU_AUX1 BIT(25) -#define CPLL_CFG1_CPU_AUX0 BIT(24) - #define SYSCFG0_DRAM_TYPE_MASK 0x3 #define SYSCFG0_DRAM_TYPE_SHIFT 4 #define SYSCFG0_DRAM_TYPE_SDRAM 0 diff --git a/arch/mips/include/asm/mach-ralink/rt288x.h b/arch/mips/include/asm/mach-ralink/rt288x.h index 66a999cd1d8002a0b924a11c962ecad140509f15..66d190358e3a247a1a912bf762a1d29a714fd268 100644 --- a/arch/mips/include/asm/mach-ralink/rt288x.h +++ b/arch/mips/include/asm/mach-ralink/rt288x.h @@ -18,7 +18,6 @@ #define SYSC_REG_CHIP_NAME1 0x04 #define SYSC_REG_CHIP_ID 0x0c #define SYSC_REG_SYSTEM_CONFIG 0x10 -#define SYSC_REG_CLKCFG 0x30 #define RT2880_CHIP_NAME0 0x38325452 #define RT2880_CHIP_NAME1 0x20203038 @@ -27,15 +26,6 @@ #define CHIP_ID_ID_SHIFT 8 #define CHIP_ID_REV_MASK 0xff -#define SYSTEM_CONFIG_CPUCLK_SHIFT 20 -#define SYSTEM_CONFIG_CPUCLK_MASK 0x3 -#define SYSTEM_CONFIG_CPUCLK_250 0x0 -#define SYSTEM_CONFIG_CPUCLK_266 0x1 -#define SYSTEM_CONFIG_CPUCLK_280 0x2 -#define SYSTEM_CONFIG_CPUCLK_300 0x3 - -#define CLKCFG_SRAM_CS_N_WDT BIT(9) - #define RT2880_SDRAM_BASE 0x08000000 #define RT2880_MEM_SIZE_MIN 2 #define RT2880_MEM_SIZE_MAX 128 diff --git a/arch/mips/include/asm/mach-ralink/rt305x.h b/arch/mips/include/asm/mach-ralink/rt305x.h index ef58f7bff95788dbac0f3c1973354b47990a51a7..4fc5c279cd75c3cc123360092d90fa0765b32a06 100644 --- a/arch/mips/include/asm/mach-ralink/rt305x.h +++ b/arch/mips/include/asm/mach-ralink/rt305x.h @@ -67,26 +67,9 @@ static inline int soc_is_rt5350(void) #define CHIP_ID_ID_SHIFT 8 #define CHIP_ID_REV_MASK 0xff -#define RT305X_SYSCFG_CPUCLK_SHIFT 18 -#define RT305X_SYSCFG_CPUCLK_MASK 0x1 -#define RT305X_SYSCFG_CPUCLK_LOW 0x0 -#define RT305X_SYSCFG_CPUCLK_HIGH 0x1 - #define RT305X_SYSCFG_SRAM_CS0_MODE_SHIFT 2 -#define RT305X_SYSCFG_CPUCLK_MASK 0x1 #define RT305X_SYSCFG_SRAM_CS0_MODE_WDT 0x1 -#define RT3352_SYSCFG0_CPUCLK_SHIFT 8 -#define RT3352_SYSCFG0_CPUCLK_MASK 0x1 -#define RT3352_SYSCFG0_CPUCLK_LOW 0x0 -#define RT3352_SYSCFG0_CPUCLK_HIGH 0x1 - -#define RT5350_SYSCFG0_CPUCLK_SHIFT 8 -#define RT5350_SYSCFG0_CPUCLK_MASK 0x3 -#define RT5350_SYSCFG0_CPUCLK_360 0x0 -#define RT5350_SYSCFG0_CPUCLK_320 0x2 -#define RT5350_SYSCFG0_CPUCLK_300 0x3 - #define RT5350_SYSCFG0_DRAM_SIZE_SHIFT 12 #define RT5350_SYSCFG0_DRAM_SIZE_MASK 7 #define RT5350_SYSCFG0_DRAM_SIZE_2M 0 @@ -117,13 +100,9 @@ static inline int soc_is_rt5350(void) #define RT3352_SYSC_REG_SYSCFG0 0x010 #define RT3352_SYSC_REG_SYSCFG1 0x014 -#define RT3352_SYSC_REG_CLKCFG1 0x030 #define RT3352_SYSC_REG_RSTCTRL 0x034 #define RT3352_SYSC_REG_USB_PS 0x05c -#define RT3352_CLKCFG0_XTAL_SEL BIT(20) -#define RT3352_CLKCFG1_UPHY0_CLK_EN BIT(18) -#define RT3352_CLKCFG1_UPHY1_CLK_EN BIT(20) #define RT3352_RSTCTRL_UHST BIT(22) #define RT3352_RSTCTRL_UDEV BIT(25) #define RT3352_SYSCFG1_USB0_HOST_MODE BIT(10) diff --git a/arch/mips/include/asm/mach-ralink/rt3883.h b/arch/mips/include/asm/mach-ralink/rt3883.h index ad25d5e8d2dc0f1198cafcb17d79d43e380b1b0e..4a835b1789253f1b3c8897abb6445b0cea312f31 100644 --- a/arch/mips/include/asm/mach-ralink/rt3883.h +++ b/arch/mips/include/asm/mach-ralink/rt3883.h @@ -92,14 +92,6 @@ #define RT3883_REVID_VER_ID_SHIFT 8 #define RT3883_REVID_ECO_ID_MASK 0x0f -#define RT3883_SYSCFG0_DRAM_TYPE_DDR2 BIT(17) -#define RT3883_SYSCFG0_CPUCLK_SHIFT 8 -#define RT3883_SYSCFG0_CPUCLK_MASK 0x3 -#define RT3883_SYSCFG0_CPUCLK_250 0x0 -#define RT3883_SYSCFG0_CPUCLK_384 0x1 -#define RT3883_SYSCFG0_CPUCLK_480 0x2 -#define RT3883_SYSCFG0_CPUCLK_500 0x3 - #define RT3883_SYSCFG1_USB0_HOST_MODE BIT(10) #define RT3883_SYSCFG1_PCIE_RC_MODE BIT(8) #define RT3883_SYSCFG1_PCI_HOST_MODE BIT(7) diff --git a/arch/mips/include/asm/smp-ops.h b/arch/mips/include/asm/smp-ops.h index 0145bbfb5efb789fa9b085000359c1af1283ac0f..5719ff49eff1c88f0e3b44ee6f23287c6c4862e8 100644 --- a/arch/mips/include/asm/smp-ops.h +++ b/arch/mips/include/asm/smp-ops.h @@ -33,6 +33,7 @@ struct plat_smp_ops { #ifdef CONFIG_HOTPLUG_CPU int (*cpu_disable)(void); void (*cpu_die)(unsigned int cpu); + void (*cleanup_dead_cpu)(unsigned cpu); #endif #ifdef CONFIG_KEXEC void (*kexec_nonboot_cpu)(void); diff --git a/arch/mips/include/asm/smp.h b/arch/mips/include/asm/smp.h index aab8981bc32ce10c0f5d445f83e927622c9b3b08..a40d8c0e4b879b2a12ad055c1940b0f63f3112fb 100644 --- a/arch/mips/include/asm/smp.h +++ b/arch/mips/include/asm/smp.h @@ -57,6 +57,8 @@ extern int __cpu_logical_map[NR_CPUS]; /* Mask of CPUs which are currently definitely operating coherently */ extern cpumask_t cpu_coherent_mask; +extern unsigned int smp_max_threads __initdata; + extern asmlinkage void smp_bootstrap(void); extern void calculate_cpu_foreign_map(void); diff --git a/arch/mips/include/uapi/asm/inst.h b/arch/mips/include/uapi/asm/inst.h index 43d1faa02933c8428eb9f2c48c6cb62d28ffeb68..c29dbc8c1d491e96b7a95525bf50b8df1b03712a 100644 --- a/arch/mips/include/uapi/asm/inst.h +++ b/arch/mips/include/uapi/asm/inst.h @@ -272,6 +272,27 @@ enum lx_func { lbx_op = 0x16, }; +/* + * func field for special2 MXU opcodes (Ingenic XBurst MXU). + */ +enum mxu_func { + /* TODO, other MXU funcs */ + mxu_lx_op = 0x28, +}; + +/* + * op field for special2 MXU LX opcodes (Ingenic XBurst MXU). + */ +enum lx_ingenic_func { + mxu_lxb_op, + mxu_lxh_op, + /* reserved */ + mxu_lxw_op = 3, + mxu_lxbu_op, + mxu_lxhu_op, + /* more reserved */ +}; + /* * BSHFL opcodes */ @@ -774,6 +795,17 @@ struct dsp_format { /* SPEC3 DSP format instructions */ ;)))))) }; +struct mxu_lx_format { /* SPEC2 MXU LX format instructions */ + __BITFIELD_FIELD(unsigned int opcode : 6, + __BITFIELD_FIELD(unsigned int rs : 5, + __BITFIELD_FIELD(unsigned int rt : 5, + __BITFIELD_FIELD(unsigned int rd : 5, + __BITFIELD_FIELD(unsigned int strd : 2, + __BITFIELD_FIELD(unsigned int op : 3, + __BITFIELD_FIELD(unsigned int func : 6, + ;))))))) +}; + struct spec3_format { /* SPEC3 */ __BITFIELD_FIELD(unsigned int opcode:6, __BITFIELD_FIELD(unsigned int rs:5, @@ -1125,6 +1157,7 @@ union mips_instruction { struct loongson3_lswc2_format loongson3_lswc2_format; struct loongson3_lsdc2_format loongson3_lsdc2_format; struct loongson3_lscsr_format loongson3_lscsr_format; + struct mxu_lx_format mxu_lx_format; }; union mips16e_instruction { diff --git a/arch/mips/include/uapi/asm/socket.h b/arch/mips/include/uapi/asm/socket.h index 18f3d95ecfec1d9e14e2aa60703a8ab0a875c378..60ebaed28a4cab388997e3567c8df45cc06d02e5 100644 --- a/arch/mips/include/uapi/asm/socket.h +++ b/arch/mips/include/uapi/asm/socket.h @@ -148,6 +148,9 @@ #define SO_RCVMARK 75 +#define SO_PASSPIDFD 76 +#define SO_PEERPIDFD 77 + #if !defined(__KERNEL__) #if __BITS_PER_LONG == 64 diff --git a/arch/mips/kernel/asm-offsets.c b/arch/mips/kernel/asm-offsets.c index 40fd4051bb3d40380d70643dcc49b08c43cb9471..d1b11f66f748f06483edbc08e48d1b4e5e684156 100644 --- a/arch/mips/kernel/asm-offsets.c +++ b/arch/mips/kernel/asm-offsets.c @@ -23,6 +23,7 @@ #include +void output_ptreg_defines(void); void output_ptreg_defines(void) { COMMENT("MIPS pt_regs offsets."); @@ -75,6 +76,7 @@ void output_ptreg_defines(void) BLANK(); } +void output_task_defines(void); void output_task_defines(void) { COMMENT("MIPS task_struct offsets."); @@ -89,6 +91,7 @@ void output_task_defines(void) BLANK(); } +void output_thread_info_defines(void); void output_thread_info_defines(void) { COMMENT("MIPS thread_info offsets."); @@ -105,6 +108,7 @@ void output_thread_info_defines(void) BLANK(); } +void output_thread_defines(void); void output_thread_defines(void) { COMMENT("MIPS specific thread_struct offsets."); @@ -133,6 +137,7 @@ void output_thread_defines(void) } #ifdef CONFIG_MIPS_FP_SUPPORT +void output_thread_fpu_defines(void); void output_thread_fpu_defines(void) { OFFSET(THREAD_FPU, task_struct, thread.fpu); @@ -176,6 +181,7 @@ void output_thread_fpu_defines(void) } #endif +void output_mm_defines(void); void output_mm_defines(void) { COMMENT("Size of struct page"); @@ -210,6 +216,7 @@ void output_mm_defines(void) } #ifdef CONFIG_32BIT +void output_sc_defines(void); void output_sc_defines(void) { COMMENT("Linux sigcontext offsets."); @@ -232,6 +239,7 @@ void output_sc_defines(void) #endif #ifdef CONFIG_64BIT +void output_sc_defines(void); void output_sc_defines(void) { COMMENT("Linux sigcontext offsets."); @@ -245,6 +253,7 @@ void output_sc_defines(void) } #endif +void output_signal_defined(void); void output_signal_defined(void) { COMMENT("Linux signal numbers."); @@ -284,6 +293,7 @@ void output_signal_defined(void) } #ifdef CONFIG_CPU_CAVIUM_OCTEON +void output_octeon_cop2_state_defines(void); void output_octeon_cop2_state_defines(void) { COMMENT("Octeon specific octeon_cop2_state offsets."); @@ -315,6 +325,7 @@ void output_octeon_cop2_state_defines(void) #endif #ifdef CONFIG_HIBERNATION +void output_pbe_defines(void); void output_pbe_defines(void) { COMMENT(" Linux struct pbe offsets. "); @@ -327,6 +338,7 @@ void output_pbe_defines(void) #endif #ifdef CONFIG_CPU_PM +void output_pm_defines(void); void output_pm_defines(void) { COMMENT(" PM offsets. "); @@ -341,6 +353,7 @@ void output_pm_defines(void) #endif #ifdef CONFIG_MIPS_FP_SUPPORT +void output_kvm_defines(void); void output_kvm_defines(void) { COMMENT(" KVM/MIPS Specific offsets. "); @@ -385,6 +398,7 @@ void output_kvm_defines(void) #endif #ifdef CONFIG_MIPS_CPS +void output_cps_defines(void); void output_cps_defines(void) { COMMENT(" MIPS CPS offsets. "); diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index e79adcb128e67df5a13dfc30740e555b4697554c..b406d8bfb15a36b18844b843a5906487f84a6b23 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -1677,7 +1677,10 @@ static inline void decode_cpucfg(struct cpuinfo_mips *c) static inline void cpu_probe_loongson(struct cpuinfo_mips *c, unsigned int cpu) { + c->cputype = CPU_LOONGSON64; + /* All Loongson processors covered here define ExcCode 16 as GSExc. */ + decode_configs(c); c->options |= MIPS_CPU_GSEXCEX; switch (c->processor_id & PRID_IMP_MASK) { @@ -1687,7 +1690,6 @@ static inline void cpu_probe_loongson(struct cpuinfo_mips *c, unsigned int cpu) case PRID_REV_LOONGSON2K_R1_1: case PRID_REV_LOONGSON2K_R1_2: case PRID_REV_LOONGSON2K_R1_3: - c->cputype = CPU_LOONGSON64; __cpu_name[cpu] = "Loongson-2K"; set_elf_platform(cpu, "gs264e"); set_isa(c, MIPS_CPU_ISA_M64R2); @@ -1700,14 +1702,12 @@ static inline void cpu_probe_loongson(struct cpuinfo_mips *c, unsigned int cpu) switch (c->processor_id & PRID_REV_MASK) { case PRID_REV_LOONGSON3A_R2_0: case PRID_REV_LOONGSON3A_R2_1: - c->cputype = CPU_LOONGSON64; __cpu_name[cpu] = "ICT Loongson-3"; set_elf_platform(cpu, "loongson3a"); set_isa(c, MIPS_CPU_ISA_M64R2); break; case PRID_REV_LOONGSON3A_R3_0: case PRID_REV_LOONGSON3A_R3_1: - c->cputype = CPU_LOONGSON64; __cpu_name[cpu] = "ICT Loongson-3"; set_elf_platform(cpu, "loongson3a"); set_isa(c, MIPS_CPU_ISA_M64R2); @@ -1727,7 +1727,6 @@ static inline void cpu_probe_loongson(struct cpuinfo_mips *c, unsigned int cpu) c->ases &= ~MIPS_ASE_VZ; /* VZ of Loongson-3A2000/3000 is incomplete */ break; case PRID_IMP_LOONGSON_64G: - c->cputype = CPU_LOONGSON64; __cpu_name[cpu] = "ICT Loongson-3"; set_elf_platform(cpu, "loongson3a"); set_isa(c, MIPS_CPU_ISA_M64R2); @@ -1737,8 +1736,6 @@ static inline void cpu_probe_loongson(struct cpuinfo_mips *c, unsigned int cpu) panic("Unknown Loongson Processor ID!"); break; } - - decode_configs(c); } #else static inline void cpu_probe_loongson(struct cpuinfo_mips *c, unsigned int cpu) { } diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c index c0e65135481b74bfb102f09dd56607c634f45b55..cb871eb784a7c12819666e50bd45cd576bc0e363 100644 --- a/arch/mips/kernel/setup.c +++ b/arch/mips/kernel/setup.c @@ -11,6 +11,8 @@ * Copyright (C) 2000, 2001, 2002, 2007 Maciej W. Rozycki */ #include +#include +#include #include #include #include @@ -841,3 +843,14 @@ static int __init setnocoherentio(char *str) } early_param("nocoherentio", setnocoherentio); #endif + +void __init arch_cpu_finalize_init(void) +{ + unsigned int cpu = smp_processor_id(); + + cpu_data[cpu].udelay_val = loops_per_jiffy; + check_bugs32(); + + if (IS_ENABLED(CONFIG_CPU_R4X00_BUGS64)) + check_bugs64(); +} diff --git a/arch/mips/kernel/smp-bmips.c b/arch/mips/kernel/smp-bmips.c index 15466d4cf4a0e567256bb37afde1546ec46fb243..c074ecce3fbf29a313c1ddc9573967d21ce5d7e3 100644 --- a/arch/mips/kernel/smp-bmips.c +++ b/arch/mips/kernel/smp-bmips.c @@ -392,6 +392,7 @@ static void bmips_cpu_die(unsigned int cpu) void __ref play_dead(void) { idle_task_exit(); + cpuhp_ap_report_dead(); /* flush data cache */ _dma_cache_wback_inv(0, ~0); diff --git a/arch/mips/kernel/smp-cps.c b/arch/mips/kernel/smp-cps.c index 62f677b2306ff31c33c357b140b3d2dec2154554..dd55d59b88db34e07924e1f64b7e139a8e56274b 100644 --- a/arch/mips/kernel/smp-cps.c +++ b/arch/mips/kernel/smp-cps.c @@ -25,24 +25,13 @@ #include #include -static bool threads_disabled; static DECLARE_BITMAP(core_power, NR_CPUS); struct core_boot_config *mips_cps_core_bootcfg; -static int __init setup_nothreads(char *s) +static unsigned __init core_vpe_count(unsigned int cluster, unsigned core) { - threads_disabled = true; - return 0; -} -early_param("nothreads", setup_nothreads); - -static unsigned core_vpe_count(unsigned int cluster, unsigned core) -{ - if (threads_disabled) - return 1; - - return mips_cps_numvps(cluster, core); + return min(smp_max_threads, mips_cps_numvps(cluster, core)); } static void __init cps_smp_setup(void) @@ -503,8 +492,7 @@ void play_dead(void) } } - /* This CPU has chosen its way out */ - (void)cpu_report_death(); + cpuhp_ap_report_dead(); cps_shutdown_this_cpu(cpu_death); @@ -527,7 +515,9 @@ static void wait_for_sibling_halt(void *ptr_cpu) } while (!(halted & TCHALT_H)); } -static void cps_cpu_die(unsigned int cpu) +static void cps_cpu_die(unsigned int cpu) { } + +static void cps_cleanup_dead_cpu(unsigned cpu) { unsigned core = cpu_core(&cpu_data[cpu]); unsigned int vpe_id = cpu_vpe_id(&cpu_data[cpu]); @@ -535,12 +525,6 @@ static void cps_cpu_die(unsigned int cpu) unsigned stat; int err; - /* Wait for the cpu to choose its way out */ - if (!cpu_wait_death(cpu, 5)) { - pr_err("CPU%u: didn't offline\n", cpu); - return; - } - /* * Now wait for the CPU to actually offline. Without doing this that * offlining may race with one or more of: @@ -624,6 +608,7 @@ static const struct plat_smp_ops cps_smp_ops = { #ifdef CONFIG_HOTPLUG_CPU .cpu_disable = cps_cpu_disable, .cpu_die = cps_cpu_die, + .cleanup_dead_cpu = cps_cleanup_dead_cpu, #endif #ifdef CONFIG_KEXEC .kexec_nonboot_cpu = cps_kexec_nonboot_cpu, diff --git a/arch/mips/kernel/smp-mt.c b/arch/mips/kernel/smp-mt.c index 5f04a01410682e511e134fdc66f9c9af75e3104e..7729cc73342160ebd64d2098e606397248561010 100644 --- a/arch/mips/kernel/smp-mt.c +++ b/arch/mips/kernel/smp-mt.c @@ -46,7 +46,8 @@ static void __init smvp_copy_vpe_config(void) static unsigned int __init smvp_vpe_init(unsigned int tc, unsigned int mvpconf0, unsigned int ncpu) { - if (tc > ((mvpconf0 & MVPCONF0_PVPE) >> MVPCONF0_PVPE_SHIFT)) + if (tc >= smp_max_threads || + (tc > ((mvpconf0 & MVPCONF0_PVPE) >> MVPCONF0_PVPE_SHIFT))) return ncpu; /* Deactivate all but VPE 0 */ diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c index 1d93b85271ba887a4dc0ea88ab9220b96f90265e..8fbef537fb8859099da21db3d79c4379e27e5e88 100644 --- a/arch/mips/kernel/smp.c +++ b/arch/mips/kernel/smp.c @@ -73,6 +73,24 @@ static cpumask_t cpu_core_setup_map; cpumask_t cpu_coherent_mask; +unsigned int smp_max_threads __initdata = UINT_MAX; + +static int __init early_nosmt(char *s) +{ + smp_max_threads = 1; + return 0; +} +early_param("nosmt", early_nosmt); + +static int __init early_smt(char *s) +{ + get_option(&s, &smp_max_threads); + /* Ensure at least one thread is available */ + smp_max_threads = clamp_val(smp_max_threads, 1U, UINT_MAX); + return 0; +} +early_param("smt", early_smt); + #ifdef CONFIG_GENERIC_IRQ_IPI static struct irq_desc *call_desc; static struct irq_desc *sched_desc; @@ -690,6 +708,14 @@ void flush_tlb_one(unsigned long vaddr) EXPORT_SYMBOL(flush_tlb_page); EXPORT_SYMBOL(flush_tlb_one); +#ifdef CONFIG_HOTPLUG_CORE_SYNC_DEAD +void arch_cpuhp_cleanup_dead_cpu(unsigned int cpu) +{ + if (mp_ops->cleanup_dead_cpu) + mp_ops->cleanup_dead_cpu(cpu); +} +#endif + #ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST static void tick_broadcast_callee(void *info) diff --git a/arch/mips/kernel/syscalls/syscall_n32.tbl b/arch/mips/kernel/syscalls/syscall_n32.tbl index 253ff994ed2eceddb1b20c9bf813aa9bcf49c48e..1976317d4e8b0eecd27e1be98c8247f2c456fc7c 100644 --- a/arch/mips/kernel/syscalls/syscall_n32.tbl +++ b/arch/mips/kernel/syscalls/syscall_n32.tbl @@ -389,3 +389,4 @@ 448 n32 process_mrelease sys_process_mrelease 449 n32 futex_waitv sys_futex_waitv 450 n32 set_mempolicy_home_node sys_set_mempolicy_home_node +451 n32 cachestat sys_cachestat diff --git a/arch/mips/kernel/syscalls/syscall_n64.tbl b/arch/mips/kernel/syscalls/syscall_n64.tbl index 3f1886ad9d8060b48522e5af59aeac2b61fbfd34..cfda2511badf3ad0f4ca561eab0b01fd538495f5 100644 --- a/arch/mips/kernel/syscalls/syscall_n64.tbl +++ b/arch/mips/kernel/syscalls/syscall_n64.tbl @@ -365,3 +365,4 @@ 448 n64 process_mrelease sys_process_mrelease 449 n64 futex_waitv sys_futex_waitv 450 common set_mempolicy_home_node sys_set_mempolicy_home_node +451 n64 cachestat sys_cachestat diff --git a/arch/mips/kernel/syscalls/syscall_o32.tbl b/arch/mips/kernel/syscalls/syscall_o32.tbl index 8f243e35a7b209ff2771b283a5d8261c12b2345d..7692234c37683a6310151812de6f735d0383c842 100644 --- a/arch/mips/kernel/syscalls/syscall_o32.tbl +++ b/arch/mips/kernel/syscalls/syscall_o32.tbl @@ -438,3 +438,4 @@ 448 o32 process_mrelease sys_process_mrelease 449 o32 futex_waitv sys_futex_waitv 450 o32 set_mempolicy_home_node sys_set_mempolicy_home_node +451 o32 cachestat sys_cachestat diff --git a/arch/mips/kernel/unaligned.c b/arch/mips/kernel/unaligned.c index 7b5aba5df02ebdbe3e946dc7cfbacd3a0478f96f..f4cf94e92ec3ab64d2fd6af48cefddec7547d5d3 100644 --- a/arch/mips/kernel/unaligned.c +++ b/arch/mips/kernel/unaligned.c @@ -160,6 +160,47 @@ static void emulate_load_store_insn(struct pt_regs *regs, * The remaining opcodes are the ones that are really of * interest. */ +#ifdef CONFIG_MACH_INGENIC + case spec2_op: + if (insn.mxu_lx_format.func != mxu_lx_op) + goto sigbus; /* other MXU instructions we don't care */ + + switch (insn.mxu_lx_format.op) { + case mxu_lxw_op: + if (user && !access_ok(addr, 4)) + goto sigbus; + LoadW(addr, value, res); + if (res) + goto fault; + compute_return_epc(regs); + regs->regs[insn.mxu_lx_format.rd] = value; + break; + case mxu_lxh_op: + if (user && !access_ok(addr, 2)) + goto sigbus; + LoadHW(addr, value, res); + if (res) + goto fault; + compute_return_epc(regs); + regs->regs[insn.dsp_format.rd] = value; + break; + case mxu_lxhu_op: + if (user && !access_ok(addr, 2)) + goto sigbus; + LoadHWU(addr, value, res); + if (res) + goto fault; + compute_return_epc(regs); + regs->regs[insn.dsp_format.rd] = value; + break; + case mxu_lxb_op: + case mxu_lxbu_op: + goto sigbus; + default: + goto sigill; + } + break; +#endif case spec3_op: if (insn.dsp_format.func == lx_op) { switch (insn.dsp_format.op) { diff --git a/arch/mips/kvm/emulate.c b/arch/mips/kvm/emulate.c index edaec93a1a1feb6737e0ba8467ff76d2d66c6893..e64372b8f66afca427b78389f37b128e305c5cc2 100644 --- a/arch/mips/kvm/emulate.c +++ b/arch/mips/kvm/emulate.c @@ -312,7 +312,7 @@ int kvm_get_badinstrp(u32 *opc, struct kvm_vcpu *vcpu, u32 *out) */ int kvm_mips_count_disabled(struct kvm_vcpu *vcpu) { - struct mips_coproc *cop0 = vcpu->arch.cop0; + struct mips_coproc *cop0 = &vcpu->arch.cop0; return (vcpu->arch.count_ctl & KVM_REG_MIPS_COUNT_CTL_DC) || (kvm_read_c0_guest_cause(cop0) & CAUSEF_DC); @@ -384,7 +384,7 @@ static inline ktime_t kvm_mips_count_time(struct kvm_vcpu *vcpu) */ static u32 kvm_mips_read_count_running(struct kvm_vcpu *vcpu, ktime_t now) { - struct mips_coproc *cop0 = vcpu->arch.cop0; + struct mips_coproc *cop0 = &vcpu->arch.cop0; ktime_t expires, threshold; u32 count, compare; int running; @@ -444,7 +444,7 @@ static u32 kvm_mips_read_count_running(struct kvm_vcpu *vcpu, ktime_t now) */ u32 kvm_mips_read_count(struct kvm_vcpu *vcpu) { - struct mips_coproc *cop0 = vcpu->arch.cop0; + struct mips_coproc *cop0 = &vcpu->arch.cop0; /* If count disabled just read static copy of count */ if (kvm_mips_count_disabled(vcpu)) @@ -502,7 +502,7 @@ ktime_t kvm_mips_freeze_hrtimer(struct kvm_vcpu *vcpu, u32 *count) static void kvm_mips_resume_hrtimer(struct kvm_vcpu *vcpu, ktime_t now, u32 count) { - struct mips_coproc *cop0 = vcpu->arch.cop0; + struct mips_coproc *cop0 = &vcpu->arch.cop0; u32 compare; u64 delta; ktime_t expire; @@ -603,7 +603,7 @@ int kvm_mips_restore_hrtimer(struct kvm_vcpu *vcpu, ktime_t before, */ void kvm_mips_write_count(struct kvm_vcpu *vcpu, u32 count) { - struct mips_coproc *cop0 = vcpu->arch.cop0; + struct mips_coproc *cop0 = &vcpu->arch.cop0; ktime_t now; /* Calculate bias */ @@ -649,7 +649,7 @@ void kvm_mips_init_count(struct kvm_vcpu *vcpu, unsigned long count_hz) */ int kvm_mips_set_count_hz(struct kvm_vcpu *vcpu, s64 count_hz) { - struct mips_coproc *cop0 = vcpu->arch.cop0; + struct mips_coproc *cop0 = &vcpu->arch.cop0; int dc; ktime_t now; u32 count; @@ -696,7 +696,7 @@ int kvm_mips_set_count_hz(struct kvm_vcpu *vcpu, s64 count_hz) */ void kvm_mips_write_compare(struct kvm_vcpu *vcpu, u32 compare, bool ack) { - struct mips_coproc *cop0 = vcpu->arch.cop0; + struct mips_coproc *cop0 = &vcpu->arch.cop0; int dc; u32 old_compare = kvm_read_c0_guest_compare(cop0); s32 delta = compare - old_compare; @@ -779,7 +779,7 @@ void kvm_mips_write_compare(struct kvm_vcpu *vcpu, u32 compare, bool ack) */ static ktime_t kvm_mips_count_disable(struct kvm_vcpu *vcpu) { - struct mips_coproc *cop0 = vcpu->arch.cop0; + struct mips_coproc *cop0 = &vcpu->arch.cop0; u32 count; ktime_t now; @@ -806,7 +806,7 @@ static ktime_t kvm_mips_count_disable(struct kvm_vcpu *vcpu) */ void kvm_mips_count_disable_cause(struct kvm_vcpu *vcpu) { - struct mips_coproc *cop0 = vcpu->arch.cop0; + struct mips_coproc *cop0 = &vcpu->arch.cop0; kvm_set_c0_guest_cause(cop0, CAUSEF_DC); if (!(vcpu->arch.count_ctl & KVM_REG_MIPS_COUNT_CTL_DC)) @@ -826,7 +826,7 @@ void kvm_mips_count_disable_cause(struct kvm_vcpu *vcpu) */ void kvm_mips_count_enable_cause(struct kvm_vcpu *vcpu) { - struct mips_coproc *cop0 = vcpu->arch.cop0; + struct mips_coproc *cop0 = &vcpu->arch.cop0; u32 count; kvm_clear_c0_guest_cause(cop0, CAUSEF_DC); @@ -852,7 +852,7 @@ void kvm_mips_count_enable_cause(struct kvm_vcpu *vcpu) */ int kvm_mips_set_count_ctl(struct kvm_vcpu *vcpu, s64 count_ctl) { - struct mips_coproc *cop0 = vcpu->arch.cop0; + struct mips_coproc *cop0 = &vcpu->arch.cop0; s64 changed = count_ctl ^ vcpu->arch.count_ctl; s64 delta; ktime_t expire, now; diff --git a/arch/mips/kvm/mips.c b/arch/mips/kvm/mips.c index 884be4ef99dc1b553fa4a71bb25d6f1b0a617c43..aa5583a7b05be136ddb0ee3dac85f387ee41077a 100644 --- a/arch/mips/kvm/mips.c +++ b/arch/mips/kvm/mips.c @@ -649,7 +649,7 @@ static int kvm_mips_copy_reg_indices(struct kvm_vcpu *vcpu, u64 __user *indices) static int kvm_mips_get_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg) { - struct mips_coproc *cop0 = vcpu->arch.cop0; + struct mips_coproc *cop0 = &vcpu->arch.cop0; struct mips_fpu_struct *fpu = &vcpu->arch.fpu; int ret; s64 v; @@ -761,7 +761,7 @@ static int kvm_mips_get_reg(struct kvm_vcpu *vcpu, static int kvm_mips_set_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg) { - struct mips_coproc *cop0 = vcpu->arch.cop0; + struct mips_coproc *cop0 = &vcpu->arch.cop0; struct mips_fpu_struct *fpu = &vcpu->arch.fpu; s64 v; s64 vs[2]; @@ -1086,7 +1086,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu) { return kvm_mips_pending_timer(vcpu) || - kvm_read_c0_guest_cause(vcpu->arch.cop0) & C_TI; + kvm_read_c0_guest_cause(&vcpu->arch.cop0) & C_TI; } int kvm_arch_vcpu_dump_regs(struct kvm_vcpu *vcpu) @@ -1110,7 +1110,7 @@ int kvm_arch_vcpu_dump_regs(struct kvm_vcpu *vcpu) kvm_debug("\thi: 0x%08lx\n", vcpu->arch.hi); kvm_debug("\tlo: 0x%08lx\n", vcpu->arch.lo); - cop0 = vcpu->arch.cop0; + cop0 = &vcpu->arch.cop0; kvm_debug("\tStatus: 0x%08x, Cause: 0x%08x\n", kvm_read_c0_guest_status(cop0), kvm_read_c0_guest_cause(cop0)); @@ -1232,7 +1232,7 @@ static int __kvm_mips_handle_exit(struct kvm_vcpu *vcpu) case EXCCODE_TLBS: kvm_debug("TLB ST fault: cause %#x, status %#x, PC: %p, BadVaddr: %#lx\n", - cause, kvm_read_c0_guest_status(vcpu->arch.cop0), opc, + cause, kvm_read_c0_guest_status(&vcpu->arch.cop0), opc, badvaddr); ++vcpu->stat.tlbmiss_st_exits; @@ -1304,7 +1304,7 @@ static int __kvm_mips_handle_exit(struct kvm_vcpu *vcpu) kvm_get_badinstr(opc, vcpu, &inst); kvm_err("Exception Code: %d, not yet handled, @ PC: %p, inst: 0x%08x BadVaddr: %#lx Status: %#x\n", exccode, opc, inst, badvaddr, - kvm_read_c0_guest_status(vcpu->arch.cop0)); + kvm_read_c0_guest_status(&vcpu->arch.cop0)); kvm_arch_vcpu_dump_regs(vcpu); run->exit_reason = KVM_EXIT_INTERNAL_ERROR; ret = RESUME_HOST; @@ -1377,7 +1377,7 @@ int noinstr kvm_mips_handle_exit(struct kvm_vcpu *vcpu) /* Enable FPU for guest and restore context */ void kvm_own_fpu(struct kvm_vcpu *vcpu) { - struct mips_coproc *cop0 = vcpu->arch.cop0; + struct mips_coproc *cop0 = &vcpu->arch.cop0; unsigned int sr, cfg5; preempt_disable(); @@ -1421,7 +1421,7 @@ void kvm_own_fpu(struct kvm_vcpu *vcpu) /* Enable MSA for guest and restore context */ void kvm_own_msa(struct kvm_vcpu *vcpu) { - struct mips_coproc *cop0 = vcpu->arch.cop0; + struct mips_coproc *cop0 = &vcpu->arch.cop0; unsigned int sr, cfg5; preempt_disable(); diff --git a/arch/mips/kvm/stats.c b/arch/mips/kvm/stats.c index 53f851a615542ae049383a252af326218bff412a..3e6682018fbe68d298f79832861a92c550fb17ca 100644 --- a/arch/mips/kvm/stats.c +++ b/arch/mips/kvm/stats.c @@ -54,9 +54,9 @@ void kvm_mips_dump_stats(struct kvm_vcpu *vcpu) kvm_info("\nKVM VCPU[%d] COP0 Access Profile:\n", vcpu->vcpu_id); for (i = 0; i < N_MIPS_COPROC_REGS; i++) { for (j = 0; j < N_MIPS_COPROC_SEL; j++) { - if (vcpu->arch.cop0->stat[i][j]) + if (vcpu->arch.cop0.stat[i][j]) kvm_info("%s[%d]: %lu\n", kvm_cop0_str[i], j, - vcpu->arch.cop0->stat[i][j]); + vcpu->arch.cop0.stat[i][j]); } } #endif diff --git a/arch/mips/kvm/trace.h b/arch/mips/kvm/trace.h index a8c7fd7bf6d267bccfbba172f58ae300826330c1..136c3535a1cbb2baf38958f2d15064214aac9137 100644 --- a/arch/mips/kvm/trace.h +++ b/arch/mips/kvm/trace.h @@ -322,11 +322,11 @@ TRACE_EVENT_FN(kvm_guest_mode_change, ), TP_fast_assign( - __entry->epc = kvm_read_c0_guest_epc(vcpu->arch.cop0); + __entry->epc = kvm_read_c0_guest_epc(&vcpu->arch.cop0); __entry->pc = vcpu->arch.pc; - __entry->badvaddr = kvm_read_c0_guest_badvaddr(vcpu->arch.cop0); - __entry->status = kvm_read_c0_guest_status(vcpu->arch.cop0); - __entry->cause = kvm_read_c0_guest_cause(vcpu->arch.cop0); + __entry->badvaddr = kvm_read_c0_guest_badvaddr(&vcpu->arch.cop0); + __entry->status = kvm_read_c0_guest_status(&vcpu->arch.cop0); + __entry->cause = kvm_read_c0_guest_cause(&vcpu->arch.cop0); ), TP_printk("EPC: 0x%08lx PC: 0x%08lx Status: 0x%08x Cause: 0x%08x BadVAddr: 0x%08lx", diff --git a/arch/mips/kvm/vz.c b/arch/mips/kvm/vz.c index 3d21cbfa74435fe7739eeaea457810b129337d43..99d5a71e430007e168d357409d502a17329ab8ff 100644 --- a/arch/mips/kvm/vz.c +++ b/arch/mips/kvm/vz.c @@ -422,7 +422,7 @@ static void _kvm_vz_restore_htimer(struct kvm_vcpu *vcpu, */ static void kvm_vz_restore_timer(struct kvm_vcpu *vcpu) { - struct mips_coproc *cop0 = vcpu->arch.cop0; + struct mips_coproc *cop0 = &vcpu->arch.cop0; u32 cause, compare; compare = kvm_read_sw_gc0_compare(cop0); @@ -517,7 +517,7 @@ static void _kvm_vz_save_htimer(struct kvm_vcpu *vcpu, */ static void kvm_vz_save_timer(struct kvm_vcpu *vcpu) { - struct mips_coproc *cop0 = vcpu->arch.cop0; + struct mips_coproc *cop0 = &vcpu->arch.cop0; u32 gctl0, compare, cause; gctl0 = read_c0_guestctl0(); @@ -863,7 +863,7 @@ static unsigned long mips_process_maar(unsigned int op, unsigned long val) static void kvm_write_maari(struct kvm_vcpu *vcpu, unsigned long val) { - struct mips_coproc *cop0 = vcpu->arch.cop0; + struct mips_coproc *cop0 = &vcpu->arch.cop0; val &= MIPS_MAARI_INDEX; if (val == MIPS_MAARI_INDEX) @@ -876,7 +876,7 @@ static enum emulation_result kvm_vz_gpsi_cop0(union mips_instruction inst, u32 *opc, u32 cause, struct kvm_vcpu *vcpu) { - struct mips_coproc *cop0 = vcpu->arch.cop0; + struct mips_coproc *cop0 = &vcpu->arch.cop0; enum emulation_result er = EMULATE_DONE; u32 rt, rd, sel; unsigned long curr_pc; @@ -1911,7 +1911,7 @@ static int kvm_vz_get_one_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg, s64 *v) { - struct mips_coproc *cop0 = vcpu->arch.cop0; + struct mips_coproc *cop0 = &vcpu->arch.cop0; unsigned int idx; switch (reg->id) { @@ -2081,7 +2081,7 @@ static int kvm_vz_get_one_reg(struct kvm_vcpu *vcpu, case KVM_REG_MIPS_CP0_MAARI: if (!cpu_guest_has_maar || cpu_guest_has_dyn_maar) return -EINVAL; - *v = kvm_read_sw_gc0_maari(vcpu->arch.cop0); + *v = kvm_read_sw_gc0_maari(&vcpu->arch.cop0); break; #ifdef CONFIG_64BIT case KVM_REG_MIPS_CP0_XCONTEXT: @@ -2135,7 +2135,7 @@ static int kvm_vz_set_one_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg, s64 v) { - struct mips_coproc *cop0 = vcpu->arch.cop0; + struct mips_coproc *cop0 = &vcpu->arch.cop0; unsigned int idx; int ret = 0; unsigned int cur, change; @@ -2562,7 +2562,7 @@ static void kvm_vz_vcpu_load_tlb(struct kvm_vcpu *vcpu, int cpu) static int kvm_vz_vcpu_load(struct kvm_vcpu *vcpu, int cpu) { - struct mips_coproc *cop0 = vcpu->arch.cop0; + struct mips_coproc *cop0 = &vcpu->arch.cop0; bool migrated, all; /* @@ -2704,7 +2704,7 @@ static int kvm_vz_vcpu_load(struct kvm_vcpu *vcpu, int cpu) static int kvm_vz_vcpu_put(struct kvm_vcpu *vcpu, int cpu) { - struct mips_coproc *cop0 = vcpu->arch.cop0; + struct mips_coproc *cop0 = &vcpu->arch.cop0; if (current->flags & PF_VCPU) kvm_vz_vcpu_save_wired(vcpu); @@ -3076,7 +3076,7 @@ static void kvm_vz_vcpu_uninit(struct kvm_vcpu *vcpu) static int kvm_vz_vcpu_setup(struct kvm_vcpu *vcpu) { - struct mips_coproc *cop0 = vcpu->arch.cop0; + struct mips_coproc *cop0 = &vcpu->arch.cop0; unsigned long count_hz = 100*1000*1000; /* default to 100 MHz */ /* diff --git a/arch/mips/loongson32/Kconfig b/arch/mips/loongson32/Kconfig index 2ef9da0016df1b2b561b17843c85fdd37c3d7eff..a7c5009595779ecabc149049509b9982ece38d7d 100644 --- a/arch/mips/loongson32/Kconfig +++ b/arch/mips/loongson32/Kconfig @@ -35,41 +35,4 @@ config LOONGSON1_LS1C select COMMON_CLK endchoice -menuconfig CEVT_CSRC_LS1X - bool "Use PWM Timer for clockevent/clocksource" - select MIPS_EXTERNAL_TIMER - depends on CPU_LOONGSON32 - help - This option changes the default clockevent/clocksource to PWM Timer, - and is required by Loongson1 CPUFreq support. - - If unsure, say N. - -choice - prompt "Select clockevent/clocksource" - depends on CEVT_CSRC_LS1X - default TIMER_USE_PWM0 - -config TIMER_USE_PWM0 - bool "Use PWM Timer 0" - help - Use PWM Timer 0 as the default clockevent/clocksourcer. - -config TIMER_USE_PWM1 - bool "Use PWM Timer 1" - help - Use PWM Timer 1 as the default clockevent/clocksourcer. - -config TIMER_USE_PWM2 - bool "Use PWM Timer 2" - help - Use PWM Timer 2 as the default clockevent/clocksourcer. - -config TIMER_USE_PWM3 - bool "Use PWM Timer 3" - help - Use PWM Timer 3 as the default clockevent/clocksourcer. - -endchoice - endif # MACH_LOONGSON32 diff --git a/arch/mips/loongson32/common/Makefile b/arch/mips/loongson32/common/Makefile index 7b49c8260706a3bd758698ad35ae459de63a05a9..f3950d308187700b44600108776173933dc2e5cc 100644 --- a/arch/mips/loongson32/common/Makefile +++ b/arch/mips/loongson32/common/Makefile @@ -3,4 +3,4 @@ # Makefile for common code of loongson1 based machines. # -obj-y += time.o irq.o platform.o prom.o reset.o setup.o +obj-y += time.o irq.o platform.o prom.o setup.o diff --git a/arch/mips/loongson32/common/reset.c b/arch/mips/loongson32/common/reset.c deleted file mode 100644 index 0c7399b303fbe7b073929ec4f7f181f0ec4c5619..0000000000000000000000000000000000000000 --- a/arch/mips/loongson32/common/reset.c +++ /dev/null @@ -1,51 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * Copyright (c) 2011 Zhang, Keguang - */ - -#include -#include -#include -#include -#include - -#include - -static void __iomem *wdt_reg_base; - -static void ls1x_halt(void) -{ - while (1) { - if (cpu_wait) - cpu_wait(); - } -} - -static void ls1x_restart(char *command) -{ - __raw_writel(0x1, wdt_reg_base + WDT_EN); - __raw_writel(0x1, wdt_reg_base + WDT_TIMER); - __raw_writel(0x1, wdt_reg_base + WDT_SET); - - ls1x_halt(); -} - -static void ls1x_power_off(void) -{ - ls1x_halt(); -} - -static int __init ls1x_reboot_setup(void) -{ - wdt_reg_base = ioremap(LS1X_WDT_BASE, (SZ_4 + SZ_8)); - if (!wdt_reg_base) - panic("Failed to remap watchdog registers"); - - _machine_restart = ls1x_restart; - _machine_halt = ls1x_halt; - pm_power_off = ls1x_power_off; - - return 0; -} - -arch_initcall(ls1x_reboot_setup); diff --git a/arch/mips/loongson32/common/time.c b/arch/mips/loongson32/common/time.c index 965c04aa56fd6f8b7cf974fab15fd08a4922d768..74ad2b17918d2deb893895fc6d9a1b7f3a083df4 100644 --- a/arch/mips/loongson32/common/time.c +++ b/arch/mips/loongson32/common/time.c @@ -5,208 +5,8 @@ #include #include -#include -#include #include -#include -#include - -#ifdef CONFIG_CEVT_CSRC_LS1X - -#if defined(CONFIG_TIMER_USE_PWM1) -#define LS1X_TIMER_BASE LS1X_PWM1_BASE -#define LS1X_TIMER_IRQ LS1X_PWM1_IRQ - -#elif defined(CONFIG_TIMER_USE_PWM2) -#define LS1X_TIMER_BASE LS1X_PWM2_BASE -#define LS1X_TIMER_IRQ LS1X_PWM2_IRQ - -#elif defined(CONFIG_TIMER_USE_PWM3) -#define LS1X_TIMER_BASE LS1X_PWM3_BASE -#define LS1X_TIMER_IRQ LS1X_PWM3_IRQ - -#else -#define LS1X_TIMER_BASE LS1X_PWM0_BASE -#define LS1X_TIMER_IRQ LS1X_PWM0_IRQ -#endif - -DEFINE_RAW_SPINLOCK(ls1x_timer_lock); - -static void __iomem *timer_reg_base; -static uint32_t ls1x_jiffies_per_tick; - -static inline void ls1x_pwmtimer_set_period(uint32_t period) -{ - __raw_writel(period, timer_reg_base + PWM_HRC); - __raw_writel(period, timer_reg_base + PWM_LRC); -} - -static inline void ls1x_pwmtimer_restart(void) -{ - __raw_writel(0x0, timer_reg_base + PWM_CNT); - __raw_writel(INT_EN | CNT_EN, timer_reg_base + PWM_CTRL); -} - -void __init ls1x_pwmtimer_init(void) -{ - timer_reg_base = ioremap(LS1X_TIMER_BASE, SZ_16); - if (!timer_reg_base) - panic("Failed to remap timer registers"); - - ls1x_jiffies_per_tick = DIV_ROUND_CLOSEST(mips_hpt_frequency, HZ); - - ls1x_pwmtimer_set_period(ls1x_jiffies_per_tick); - ls1x_pwmtimer_restart(); -} - -static u64 ls1x_clocksource_read(struct clocksource *cs) -{ - unsigned long flags; - int count; - u32 jifs; - static int old_count; - static u32 old_jifs; - - raw_spin_lock_irqsave(&ls1x_timer_lock, flags); - /* - * Although our caller may have the read side of xtime_lock, - * this is now a seqlock, and we are cheating in this routine - * by having side effects on state that we cannot undo if - * there is a collision on the seqlock and our caller has to - * retry. (Namely, old_jifs and old_count.) So we must treat - * jiffies as volatile despite the lock. We read jiffies - * before latching the timer count to guarantee that although - * the jiffies value might be older than the count (that is, - * the counter may underflow between the last point where - * jiffies was incremented and the point where we latch the - * count), it cannot be newer. - */ - jifs = jiffies; - /* read the count */ - count = __raw_readl(timer_reg_base + PWM_CNT); - - /* - * It's possible for count to appear to go the wrong way for this - * reason: - * - * The timer counter underflows, but we haven't handled the resulting - * interrupt and incremented jiffies yet. - * - * Previous attempts to handle these cases intelligently were buggy, so - * we just do the simple thing now. - */ - if (count < old_count && jifs == old_jifs) - count = old_count; - - old_count = count; - old_jifs = jifs; - - raw_spin_unlock_irqrestore(&ls1x_timer_lock, flags); - - return (u64) (jifs * ls1x_jiffies_per_tick) + count; -} - -static struct clocksource ls1x_clocksource = { - .name = "ls1x-pwmtimer", - .read = ls1x_clocksource_read, - .mask = CLOCKSOURCE_MASK(24), - .flags = CLOCK_SOURCE_IS_CONTINUOUS, -}; - -static irqreturn_t ls1x_clockevent_isr(int irq, void *devid) -{ - struct clock_event_device *cd = devid; - - ls1x_pwmtimer_restart(); - cd->event_handler(cd); - - return IRQ_HANDLED; -} - -static int ls1x_clockevent_set_state_periodic(struct clock_event_device *cd) -{ - raw_spin_lock(&ls1x_timer_lock); - ls1x_pwmtimer_set_period(ls1x_jiffies_per_tick); - ls1x_pwmtimer_restart(); - __raw_writel(INT_EN | CNT_EN, timer_reg_base + PWM_CTRL); - raw_spin_unlock(&ls1x_timer_lock); - - return 0; -} - -static int ls1x_clockevent_tick_resume(struct clock_event_device *cd) -{ - raw_spin_lock(&ls1x_timer_lock); - __raw_writel(INT_EN | CNT_EN, timer_reg_base + PWM_CTRL); - raw_spin_unlock(&ls1x_timer_lock); - - return 0; -} - -static int ls1x_clockevent_set_state_shutdown(struct clock_event_device *cd) -{ - raw_spin_lock(&ls1x_timer_lock); - __raw_writel(__raw_readl(timer_reg_base + PWM_CTRL) & ~CNT_EN, - timer_reg_base + PWM_CTRL); - raw_spin_unlock(&ls1x_timer_lock); - - return 0; -} - -static int ls1x_clockevent_set_next(unsigned long evt, - struct clock_event_device *cd) -{ - raw_spin_lock(&ls1x_timer_lock); - ls1x_pwmtimer_set_period(evt); - ls1x_pwmtimer_restart(); - raw_spin_unlock(&ls1x_timer_lock); - - return 0; -} - -static struct clock_event_device ls1x_clockevent = { - .name = "ls1x-pwmtimer", - .features = CLOCK_EVT_FEAT_PERIODIC, - .rating = 300, - .irq = LS1X_TIMER_IRQ, - .set_next_event = ls1x_clockevent_set_next, - .set_state_shutdown = ls1x_clockevent_set_state_shutdown, - .set_state_periodic = ls1x_clockevent_set_state_periodic, - .set_state_oneshot = ls1x_clockevent_set_state_shutdown, - .tick_resume = ls1x_clockevent_tick_resume, -}; - -static void __init ls1x_time_init(void) -{ - struct clock_event_device *cd = &ls1x_clockevent; - int ret; - - if (!mips_hpt_frequency) - panic("Invalid timer clock rate"); - - ls1x_pwmtimer_init(); - - clockevent_set_clock(cd, mips_hpt_frequency); - cd->max_delta_ns = clockevent_delta2ns(0xffffff, cd); - cd->max_delta_ticks = 0xffffff; - cd->min_delta_ns = clockevent_delta2ns(0x000300, cd); - cd->min_delta_ticks = 0x000300; - cd->cpumask = cpumask_of(smp_processor_id()); - clockevents_register_device(cd); - - ls1x_clocksource.rating = 200 + mips_hpt_frequency / 10000000; - ret = clocksource_register_hz(&ls1x_clocksource, mips_hpt_frequency); - if (ret) - panic(KERN_ERR "Failed to register clocksource: %d\n", ret); - - if (request_irq(LS1X_TIMER_IRQ, ls1x_clockevent_isr, - IRQF_PERCPU | IRQF_TIMER, "ls1x-pwmtimer", - &ls1x_clockevent)) - pr_err("Failed to register ls1x-pwmtimer interrupt\n"); -} -#endif /* CONFIG_CEVT_CSRC_LS1X */ - void __init plat_time_init(void) { struct clk *clk = NULL; @@ -214,20 +14,10 @@ void __init plat_time_init(void) /* initialize LS1X clocks */ of_clk_init(NULL); -#ifdef CONFIG_CEVT_CSRC_LS1X - /* setup LS1X PWM timer */ - clk = clk_get(NULL, "ls1x-pwmtimer"); - if (IS_ERR(clk)) - panic("unable to get timer clock, err=%ld", PTR_ERR(clk)); - - mips_hpt_frequency = clk_get_rate(clk); - ls1x_time_init(); -#else /* setup mips r4k timer */ clk = clk_get(NULL, "cpu_clk"); if (IS_ERR(clk)) panic("unable to get cpu clock, err=%ld", PTR_ERR(clk)); mips_hpt_frequency = clk_get_rate(clk) / 2; -#endif /* CONFIG_CEVT_CSRC_LS1X */ } diff --git a/arch/mips/loongson64/smp.c b/arch/mips/loongson64/smp.c index b0e8bb9fa036fd7b4b9c800fd8f2996f4ae48950..cdecd7af11a6a0d8fe87f2c15c6e917148a5e97a 100644 --- a/arch/mips/loongson64/smp.c +++ b/arch/mips/loongson64/smp.c @@ -775,6 +775,7 @@ void play_dead(void) void (*play_dead_at_ckseg1)(int *); idle_task_exit(); + cpuhp_ap_report_dead(); prid_imp = read_c0_prid() & PRID_IMP_MASK; prid_rev = read_c0_prid() & PRID_REV_MASK; diff --git a/arch/mips/mm/fault.c b/arch/mips/mm/fault.c index a27045f5a556dfead73cef3c54151674a8565152..d7878208bd3fa9f63e53b491a16e613e1c3e899f 100644 --- a/arch/mips/mm/fault.c +++ b/arch/mips/mm/fault.c @@ -99,21 +99,13 @@ static void __do_page_fault(struct pt_regs *regs, unsigned long write, perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address); retry: - mmap_read_lock(mm); - vma = find_vma(mm, address); + vma = lock_mm_and_find_vma(mm, address, regs); if (!vma) - goto bad_area; - if (vma->vm_start <= address) - goto good_area; - if (!(vma->vm_flags & VM_GROWSDOWN)) - goto bad_area; - if (expand_stack(vma, address)) - goto bad_area; + goto bad_area_nosemaphore; /* * Ok, we have a good vm_area for this memory access, so * we can handle it.. */ -good_area: si_code = SEGV_ACCERR; if (write) { diff --git a/arch/mips/mm/tlb-r4k.c b/arch/mips/mm/tlb-r4k.c index 1b939abbe4caaf5c0406c9550d3c3dc05d1ccf82..93c2d695588a1c2fc8c8065a637cb787b18ac04c 100644 --- a/arch/mips/mm/tlb-r4k.c +++ b/arch/mips/mm/tlb-r4k.c @@ -297,7 +297,7 @@ void __update_tlb(struct vm_area_struct * vma, unsigned long address, pte_t pte) p4d_t *p4dp; pud_t *pudp; pmd_t *pmdp; - pte_t *ptep; + pte_t *ptep, *ptemap = NULL; int idx, pid; /* @@ -344,7 +344,12 @@ void __update_tlb(struct vm_area_struct * vma, unsigned long address, pte_t pte) } else #endif { - ptep = pte_offset_map(pmdp, address); + ptemap = ptep = pte_offset_map(pmdp, address); + /* + * update_mmu_cache() is called between pte_offset_map_lock() + * and pte_unmap_unlock(), so we can assume that ptep is not + * NULL here: and what should be done below if it were NULL? + */ #if defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32) #ifdef CONFIG_XPA @@ -373,6 +378,9 @@ void __update_tlb(struct vm_area_struct * vma, unsigned long address, pte_t pte) tlbw_use_hazard(); htw_start(); flush_micro_tlb_vm(vma); + + if (ptemap) + pte_unmap(ptemap); local_irq_restore(flags); } diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c index 80e05ee98d62f07c23fb3edece292aa571abe2b7..8d514a9082c623dc91c51afbdc9777621fc99c26 100644 --- a/arch/mips/mm/tlbex.c +++ b/arch/mips/mm/tlbex.c @@ -2123,16 +2123,8 @@ static void build_r4000_tlb_load_handler(void) uasm_i_tlbr(&p); - switch (current_cpu_type()) { - case CPU_CAVIUM_OCTEON: - case CPU_CAVIUM_OCTEON_PLUS: - case CPU_CAVIUM_OCTEON2: - break; - default: - if (cpu_has_mips_r2_exec_hazard) - uasm_i_ehb(&p); - break; - } + if (cpu_has_mips_r2_exec_hazard) + uasm_i_ehb(&p); /* Examine entrylo 0 or 1 based on ptr. */ if (use_bbit_insns()) { @@ -2197,16 +2189,8 @@ static void build_r4000_tlb_load_handler(void) uasm_i_tlbr(&p); - switch (current_cpu_type()) { - case CPU_CAVIUM_OCTEON: - case CPU_CAVIUM_OCTEON_PLUS: - case CPU_CAVIUM_OCTEON2: - break; - default: - if (cpu_has_mips_r2_exec_hazard) - uasm_i_ehb(&p); - break; - } + if (cpu_has_mips_r2_exec_hazard) + uasm_i_ehb(&p); /* Examine entrylo 0 or 1 based on ptr. */ if (use_bbit_insns()) { diff --git a/arch/mips/pci/pci-mt7620.c b/arch/mips/pci/pci-mt7620.c index 2700d75d41c53d023661bfe0b2bb4cb8912f6b16..5c4bdf6919e50081cfbddd26543742714103e105 100644 --- a/arch/mips/pci/pci-mt7620.c +++ b/arch/mips/pci/pci-mt7620.c @@ -274,9 +274,6 @@ static int mt7628_pci_hw_init(struct platform_device *pdev) val |= 0x50 << 8; pci_config_write(NULL, 0, 0x70c, 4, val); - pci_config_read(NULL, 0, 0x70c, 4, &val); - dev_err(&pdev->dev, "Port 0 N_FTS = %x\n", (unsigned int) val); - return 0; } @@ -330,7 +327,7 @@ static int mt7620_pci_probe(struct platform_device *pdev) rt_sysc_m32(RALINK_PCIE0_CLK_EN, 0, RALINK_CLKCFG1); if (ralink_soc == MT762X_SOC_MT7620A) rt_sysc_m32(LC_CKDRVPD, PDRV_SW_SET, PPLL_DRV); - dev_err(&pdev->dev, "PCIE0 no card, disable it(RST&CLK)\n"); + dev_info(&pdev->dev, "PCIE0 no card, disable it(RST&CLK)\n"); return -1; } @@ -373,7 +370,7 @@ int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) dev->bus->number, slot); return 0; } - dev_err(&dev->dev, "card - bus=0x%x, slot = 0x%x irq=%d\n", + dev_info(&dev->dev, "card - bus=0x%x, slot = 0x%x irq=%d\n", dev->bus->number, slot, irq); /* configure the cache line size to 0x14 */ diff --git a/arch/mips/pci/pci-xtalk-bridge.c b/arch/mips/pci/pci-xtalk-bridge.c index ab9bedb82b282126aebc1ec9a630dbd6d305cfb1..68d5211afea8b4004b6c1d1ec4ff186d61a6cc45 100644 --- a/arch/mips/pci/pci-xtalk-bridge.c +++ b/arch/mips/pci/pci-xtalk-bridge.c @@ -733,7 +733,7 @@ static int bridge_probe(struct platform_device *pdev) return err; } -static int bridge_remove(struct platform_device *pdev) +static void bridge_remove(struct platform_device *pdev) { struct pci_bus *bus = platform_get_drvdata(pdev); struct bridge_controller *bc = BRIDGE_CONTROLLER(bus); @@ -745,13 +745,11 @@ static int bridge_remove(struct platform_device *pdev) pci_stop_root_bus(bus); pci_remove_root_bus(bus); pci_unlock_rescan_remove(); - - return 0; } static struct platform_driver bridge_driver = { - .probe = bridge_probe, - .remove = bridge_remove, + .probe = bridge_probe, + .remove_new = bridge_remove, .driver = { .name = "xtalk-bridge", } diff --git a/arch/mips/ralink/clk.c b/arch/mips/ralink/clk.c index 5b02bb7e0829c69854bee41639286dfb95aa00b2..9db73fcac522ebc76240c2f17fc6fb676dc78821 100644 --- a/arch/mips/ralink/clk.c +++ b/arch/mips/ralink/clk.c @@ -11,29 +11,72 @@ #include #include #include +#include #include #include "common.h" -void ralink_clk_add(const char *dev, unsigned long rate) +static const char *clk_cpu(int *idx) { - struct clk *clk = clk_register_fixed_rate(NULL, dev, NULL, 0, rate); - - if (!clk) - panic("failed to add clock"); - - clkdev_create(clk, NULL, "%s", dev); + switch (ralink_soc) { + case RT2880_SOC: + *idx = 0; + return "ralink,rt2880-sysc"; + case RT3883_SOC: + *idx = 0; + return "ralink,rt3883-sysc"; + case RT305X_SOC_RT3050: + *idx = 0; + return "ralink,rt3050-sysc"; + case RT305X_SOC_RT3052: + *idx = 0; + return "ralink,rt3052-sysc"; + case RT305X_SOC_RT3350: + *idx = 1; + return "ralink,rt3350-sysc"; + case RT305X_SOC_RT3352: + *idx = 1; + return "ralink,rt3352-sysc"; + case RT305X_SOC_RT5350: + *idx = 1; + return "ralink,rt5350-sysc"; + case MT762X_SOC_MT7620A: + *idx = 2; + return "ralink,mt7620-sysc"; + case MT762X_SOC_MT7620N: + *idx = 2; + return "ralink,mt7620-sysc"; + case MT762X_SOC_MT7628AN: + *idx = 1; + return "ralink,mt7628-sysc"; + case MT762X_SOC_MT7688: + *idx = 1; + return "ralink,mt7688-sysc"; + default: + *idx = -1; + return "invalid"; + } } void __init plat_time_init(void) { + struct of_phandle_args clkspec; + const char *compatible; struct clk *clk; + int cpu_clk_idx; ralink_of_remap(); - ralink_clk_init(); - clk = clk_get_sys("cpu", NULL); + compatible = clk_cpu(&cpu_clk_idx); + if (cpu_clk_idx == -1) + panic("unable to get CPU clock index"); + + of_clk_init(NULL); + clkspec.np = of_find_compatible_node(NULL, NULL, compatible); + clkspec.args_count = 1; + clkspec.args[0] = cpu_clk_idx; + clk = of_clk_get_from_provider(&clkspec); if (IS_ERR(clk)) panic("unable to get CPU clock, err=%ld", PTR_ERR(clk)); pr_info("CPU Clock: %ldMHz\n", clk_get_rate(clk) / 1000000); diff --git a/arch/mips/ralink/common.h b/arch/mips/ralink/common.h index 87fc16751281ed0363d050d145e5441d83626aad..893981a0ca7da37b57355867b4e6360e5738b0fa 100644 --- a/arch/mips/ralink/common.h +++ b/arch/mips/ralink/common.h @@ -23,13 +23,6 @@ extern struct ralink_soc_info soc_info; extern void ralink_of_remap(void); -extern void ralink_clk_init(void); -extern void ralink_clk_add(const char *dev, unsigned long rate); - -extern void ralink_rst_init(void); - extern void __init prom_soc_init(struct ralink_soc_info *soc_info); -__iomem void *plat_of_remap_node(const char *node); - #endif /* _RALINK_COMMON_H__ */ diff --git a/arch/mips/ralink/mt7620.c b/arch/mips/ralink/mt7620.c index 4435f50b8d243d80fec5a5e5efdc15f8a5e1fbfa..672249a13a09a409bc54cc9d3d8704b70f57f624 100644 --- a/arch/mips/ralink/mt7620.c +++ b/arch/mips/ralink/mt7620.c @@ -36,12 +36,6 @@ #define PMU1_CFG 0x8C #define DIG_SW_SEL BIT(25) -/* clock scaling */ -#define CLKCFG_FDIV_MASK 0x1f00 -#define CLKCFG_FDIV_USB_VAL 0x0300 -#define CLKCFG_FFRAC_MASK 0x001f -#define CLKCFG_FFRAC_USB_VAL 0x0003 - /* EFUSE bits */ #define EFUSE_MT7688 0x100000 @@ -53,235 +47,6 @@ static int dram_type; static struct ralink_soc_info *soc_info_ptr; -static __init u32 -mt7620_calc_rate(u32 ref_rate, u32 mul, u32 div) -{ - u64 t; - - t = ref_rate; - t *= mul; - do_div(t, div); - - return t; -} - -#define MHZ(x) ((x) * 1000 * 1000) - -static __init unsigned long -mt7620_get_xtal_rate(void) -{ - u32 reg; - - reg = rt_sysc_r32(SYSC_REG_SYSTEM_CONFIG0); - if (reg & SYSCFG0_XTAL_FREQ_SEL) - return MHZ(40); - - return MHZ(20); -} - -static __init unsigned long -mt7620_get_periph_rate(unsigned long xtal_rate) -{ - u32 reg; - - reg = rt_sysc_r32(SYSC_REG_CLKCFG0); - if (reg & CLKCFG0_PERI_CLK_SEL) - return xtal_rate; - - return MHZ(40); -} - -static const u32 mt7620_clk_divider[] __initconst = { 2, 3, 4, 8 }; - -static __init unsigned long -mt7620_get_cpu_pll_rate(unsigned long xtal_rate) -{ - u32 reg; - u32 mul; - u32 div; - - reg = rt_sysc_r32(SYSC_REG_CPLL_CONFIG0); - if (reg & CPLL_CFG0_BYPASS_REF_CLK) - return xtal_rate; - - if ((reg & CPLL_CFG0_SW_CFG) == 0) - return MHZ(600); - - mul = (reg >> CPLL_CFG0_PLL_MULT_RATIO_SHIFT) & - CPLL_CFG0_PLL_MULT_RATIO_MASK; - mul += 24; - if (reg & CPLL_CFG0_LC_CURFCK) - mul *= 2; - - div = (reg >> CPLL_CFG0_PLL_DIV_RATIO_SHIFT) & - CPLL_CFG0_PLL_DIV_RATIO_MASK; - - WARN_ON(div >= ARRAY_SIZE(mt7620_clk_divider)); - - return mt7620_calc_rate(xtal_rate, mul, mt7620_clk_divider[div]); -} - -static __init unsigned long -mt7620_get_pll_rate(unsigned long xtal_rate, unsigned long cpu_pll_rate) -{ - u32 reg; - - reg = rt_sysc_r32(SYSC_REG_CPLL_CONFIG1); - if (reg & CPLL_CFG1_CPU_AUX1) - return xtal_rate; - - if (reg & CPLL_CFG1_CPU_AUX0) - return MHZ(480); - - return cpu_pll_rate; -} - -static __init unsigned long -mt7620_get_cpu_rate(unsigned long pll_rate) -{ - u32 reg; - u32 mul; - u32 div; - - reg = rt_sysc_r32(SYSC_REG_CPU_SYS_CLKCFG); - - mul = reg & CPU_SYS_CLKCFG_CPU_FFRAC_MASK; - div = (reg >> CPU_SYS_CLKCFG_CPU_FDIV_SHIFT) & - CPU_SYS_CLKCFG_CPU_FDIV_MASK; - - return mt7620_calc_rate(pll_rate, mul, div); -} - -static const u32 mt7620_ocp_dividers[16] __initconst = { - [CPU_SYS_CLKCFG_OCP_RATIO_2] = 2, - [CPU_SYS_CLKCFG_OCP_RATIO_3] = 3, - [CPU_SYS_CLKCFG_OCP_RATIO_4] = 4, - [CPU_SYS_CLKCFG_OCP_RATIO_5] = 5, - [CPU_SYS_CLKCFG_OCP_RATIO_10] = 10, -}; - -static __init unsigned long -mt7620_get_dram_rate(unsigned long pll_rate) -{ - if (dram_type == SYSCFG0_DRAM_TYPE_SDRAM) - return pll_rate / 4; - - return pll_rate / 3; -} - -static __init unsigned long -mt7620_get_sys_rate(unsigned long cpu_rate) -{ - u32 reg; - u32 ocp_ratio; - u32 div; - - reg = rt_sysc_r32(SYSC_REG_CPU_SYS_CLKCFG); - - ocp_ratio = (reg >> CPU_SYS_CLKCFG_OCP_RATIO_SHIFT) & - CPU_SYS_CLKCFG_OCP_RATIO_MASK; - - if (WARN_ON(ocp_ratio >= ARRAY_SIZE(mt7620_ocp_dividers))) - return cpu_rate; - - div = mt7620_ocp_dividers[ocp_ratio]; - if (WARN(!div, "invalid divider for OCP ratio %u", ocp_ratio)) - return cpu_rate; - - return cpu_rate / div; -} - -void __init ralink_clk_init(void) -{ - unsigned long xtal_rate; - unsigned long cpu_pll_rate; - unsigned long pll_rate; - unsigned long cpu_rate; - unsigned long sys_rate; - unsigned long dram_rate; - unsigned long periph_rate; - unsigned long pcmi2s_rate; - - xtal_rate = mt7620_get_xtal_rate(); - -#define RFMT(label) label ":%lu.%03luMHz " -#define RINT(x) ((x) / 1000000) -#define RFRAC(x) (((x) / 1000) % 1000) - - if (is_mt76x8()) { - if (xtal_rate == MHZ(40)) - cpu_rate = MHZ(580); - else - cpu_rate = MHZ(575); - dram_rate = sys_rate = cpu_rate / 3; - periph_rate = MHZ(40); - pcmi2s_rate = MHZ(480); - - ralink_clk_add("10000d00.uartlite", periph_rate); - ralink_clk_add("10000e00.uartlite", periph_rate); - } else { - cpu_pll_rate = mt7620_get_cpu_pll_rate(xtal_rate); - pll_rate = mt7620_get_pll_rate(xtal_rate, cpu_pll_rate); - - cpu_rate = mt7620_get_cpu_rate(pll_rate); - dram_rate = mt7620_get_dram_rate(pll_rate); - sys_rate = mt7620_get_sys_rate(cpu_rate); - periph_rate = mt7620_get_periph_rate(xtal_rate); - pcmi2s_rate = periph_rate; - - pr_debug(RFMT("XTAL") RFMT("CPU_PLL") RFMT("PLL"), - RINT(xtal_rate), RFRAC(xtal_rate), - RINT(cpu_pll_rate), RFRAC(cpu_pll_rate), - RINT(pll_rate), RFRAC(pll_rate)); - - ralink_clk_add("10000500.uart", periph_rate); - } - - pr_debug(RFMT("CPU") RFMT("DRAM") RFMT("SYS") RFMT("PERIPH"), - RINT(cpu_rate), RFRAC(cpu_rate), - RINT(dram_rate), RFRAC(dram_rate), - RINT(sys_rate), RFRAC(sys_rate), - RINT(periph_rate), RFRAC(periph_rate)); -#undef RFRAC -#undef RINT -#undef RFMT - - ralink_clk_add("cpu", cpu_rate); - ralink_clk_add("10000100.timer", periph_rate); - ralink_clk_add("10000120.watchdog", periph_rate); - ralink_clk_add("10000900.i2c", periph_rate); - ralink_clk_add("10000a00.i2s", pcmi2s_rate); - ralink_clk_add("10000b00.spi", sys_rate); - ralink_clk_add("10000b40.spi", sys_rate); - ralink_clk_add("10000c00.uartlite", periph_rate); - ralink_clk_add("10000d00.uart1", periph_rate); - ralink_clk_add("10000e00.uart2", periph_rate); - ralink_clk_add("10180000.wmac", xtal_rate); - - if (IS_ENABLED(CONFIG_USB) && !is_mt76x8()) { - /* - * When the CPU goes into sleep mode, the BUS clock will be - * too low for USB to function properly. Adjust the busses - * fractional divider to fix this - */ - u32 val = rt_sysc_r32(SYSC_REG_CPU_SYS_CLKCFG); - - val &= ~(CLKCFG_FDIV_MASK | CLKCFG_FFRAC_MASK); - val |= CLKCFG_FDIV_USB_VAL | CLKCFG_FFRAC_USB_VAL; - - rt_sysc_w32(val, SYSC_REG_CPU_SYS_CLKCFG); - } -} - -void __init ralink_of_remap(void) -{ - rt_sysc_membase = plat_of_remap_node("ralink,mt7620a-sysc"); - rt_memc_membase = plat_of_remap_node("ralink,mt7620a-memc"); - - if (!rt_sysc_membase || !rt_memc_membase) - panic("Failed to remap core resources"); -} - static __init void mt7620_dram_init(struct ralink_soc_info *soc_info) { diff --git a/arch/mips/ralink/mt7621.c b/arch/mips/ralink/mt7621.c index c3fbab50b95ca78d52ba083dc76a223d3ff91ec0..137781d0bd0a12a00ad9ab15f002e190bffa9c7e 100644 --- a/arch/mips/ralink/mt7621.c +++ b/arch/mips/ralink/mt7621.c @@ -89,15 +89,6 @@ static void __init mt7621_memory_detect(void) memblock_add(MT7621_HIGHMEM_BASE, MT7621_HIGHMEM_SIZE); } -void __init ralink_of_remap(void) -{ - rt_sysc_membase = plat_of_remap_node("mediatek,mt7621-sysc"); - rt_memc_membase = plat_of_remap_node("mediatek,mt7621-memc"); - - if (!rt_sysc_membase || !rt_memc_membase) - panic("Failed to remap core resources"); -} - static unsigned int __init mt7621_get_soc_name0(void) { return __raw_readl(MT7621_SYSC_BASE + SYSC_REG_CHIP_NAME0); diff --git a/arch/mips/ralink/of.c b/arch/mips/ralink/of.c index 4d06de77d92a69a80af6a1e996b9d8a47a2e1f0d..45d60c094496f15318847d0ab9b64deba870056b 100644 --- a/arch/mips/ralink/of.c +++ b/arch/mips/ralink/of.c @@ -29,28 +29,61 @@ __iomem void *rt_sysc_membase; __iomem void *rt_memc_membase; EXPORT_SYMBOL_GPL(rt_sysc_membase); -__iomem void *plat_of_remap_node(const char *node) +static const struct of_device_id mtmips_memc_match[] = { + { .compatible = "mediatek,mt7621-memc" }, + { .compatible = "ralink,mt7620a-memc" }, + { .compatible = "ralink,rt2880-memc" }, + { .compatible = "ralink,rt3050-memc" }, + { .compatible = "ralink,rt3883-memc" }, + {} +}; + +static const struct of_device_id mtmips_sysc_match[] = { + { .compatible = "mediatek,mt7621-sysc" }, + { .compatible = "ralink,mt7620-sysc" }, + { .compatible = "ralink,mt7628-sysc" }, + { .compatible = "ralink,mt7688-sysc" }, + { .compatible = "ralink,rt2880-sysc" }, + { .compatible = "ralink,rt3050-sysc" }, + { .compatible = "ralink,rt3052-sysc" }, + { .compatible = "ralink,rt3352-sysc" }, + { .compatible = "ralink,rt3883-sysc" }, + { .compatible = "ralink,rt5350-sysc" }, + {} +}; + +static __iomem void * +mtmips_of_remap_node(const struct of_device_id *match, const char *type) { struct resource res; struct device_node *np; - np = of_find_compatible_node(NULL, NULL, node); + np = of_find_matching_node(NULL, match); if (!np) - panic("Failed to find %s node", node); + panic("Failed to find %s controller node", type); if (of_address_to_resource(np, 0, &res)) - panic("Failed to get resource for %s", node); - - of_node_put(np); + panic("Failed to get resource for %s node", np->name); if (!request_mem_region(res.start, resource_size(&res), res.name)) - panic("Failed to request resources for %s", node); + panic("Failed to request resources for %s node", np->name); + + of_node_put(np); return ioremap(res.start, resource_size(&res)); } +void __init ralink_of_remap(void) +{ + rt_sysc_membase = mtmips_of_remap_node(mtmips_sysc_match, "system"); + rt_memc_membase = mtmips_of_remap_node(mtmips_memc_match, "memory"); + + if (!rt_sysc_membase || !rt_memc_membase) + panic("Failed to remap core resources"); +} + void __init plat_mem_setup(void) { void *dtb; @@ -81,10 +114,6 @@ static int __init plat_of_setup(void) { __dt_register_buses(soc_info.compatible, "palmbus"); - /* make sure that the reset controller is setup early */ - if (ralink_soc != MT762X_SOC_MT7621AT) - ralink_rst_init(); - return 0; } diff --git a/arch/mips/ralink/reset.c b/arch/mips/ralink/reset.c index 274d33078c5eb2300cb82228168312ea1e8cad97..4875637ef46977c3fa4569ed8e92d3d68945e59b 100644 --- a/arch/mips/ralink/reset.c +++ b/arch/mips/ralink/reset.c @@ -10,7 +10,6 @@ #include #include #include -#include #include @@ -22,66 +21,6 @@ #define RSTCTL_RESET_PCI BIT(26) #define RSTCTL_RESET_SYSTEM BIT(0) -static int ralink_assert_device(struct reset_controller_dev *rcdev, - unsigned long id) -{ - u32 val; - - if (id == 0) - return -1; - - val = rt_sysc_r32(SYSC_REG_RESET_CTRL); - val |= BIT(id); - rt_sysc_w32(val, SYSC_REG_RESET_CTRL); - - return 0; -} - -static int ralink_deassert_device(struct reset_controller_dev *rcdev, - unsigned long id) -{ - u32 val; - - if (id == 0) - return -1; - - val = rt_sysc_r32(SYSC_REG_RESET_CTRL); - val &= ~BIT(id); - rt_sysc_w32(val, SYSC_REG_RESET_CTRL); - - return 0; -} - -static int ralink_reset_device(struct reset_controller_dev *rcdev, - unsigned long id) -{ - ralink_assert_device(rcdev, id); - return ralink_deassert_device(rcdev, id); -} - -static const struct reset_control_ops reset_ops = { - .reset = ralink_reset_device, - .assert = ralink_assert_device, - .deassert = ralink_deassert_device, -}; - -static struct reset_controller_dev reset_dev = { - .ops = &reset_ops, - .owner = THIS_MODULE, - .nr_resets = 32, - .of_reset_n_cells = 1, -}; - -void ralink_rst_init(void) -{ - reset_dev.of_node = of_find_compatible_node(NULL, NULL, - "ralink,rt2880-reset"); - if (!reset_dev.of_node) - pr_err("Failed to find reset controller node"); - else - reset_controller_register(&reset_dev); -} - static void ralink_restart(char *command) { if (IS_ENABLED(CONFIG_PCI)) { diff --git a/arch/mips/ralink/rt288x.c b/arch/mips/ralink/rt288x.c index 456ba0b2599ebca084e74e268fe21e198fd34293..ce8b5b6025bb4ef52c8511beb7b159727440f280 100644 --- a/arch/mips/ralink/rt288x.c +++ b/arch/mips/ralink/rt288x.c @@ -21,46 +21,6 @@ static struct ralink_soc_info *soc_info_ptr; -void __init ralink_clk_init(void) -{ - unsigned long cpu_rate, wmac_rate = 40000000; - u32 t = rt_sysc_r32(SYSC_REG_SYSTEM_CONFIG); - t = ((t >> SYSTEM_CONFIG_CPUCLK_SHIFT) & SYSTEM_CONFIG_CPUCLK_MASK); - - switch (t) { - case SYSTEM_CONFIG_CPUCLK_250: - cpu_rate = 250000000; - break; - case SYSTEM_CONFIG_CPUCLK_266: - cpu_rate = 266666667; - break; - case SYSTEM_CONFIG_CPUCLK_280: - cpu_rate = 280000000; - break; - case SYSTEM_CONFIG_CPUCLK_300: - cpu_rate = 300000000; - break; - } - - ralink_clk_add("cpu", cpu_rate); - ralink_clk_add("300100.timer", cpu_rate / 2); - ralink_clk_add("300120.watchdog", cpu_rate / 2); - ralink_clk_add("300500.uart", cpu_rate / 2); - ralink_clk_add("300900.i2c", cpu_rate / 2); - ralink_clk_add("300c00.uartlite", cpu_rate / 2); - ralink_clk_add("400000.ethernet", cpu_rate / 2); - ralink_clk_add("480000.wmac", wmac_rate); -} - -void __init ralink_of_remap(void) -{ - rt_sysc_membase = plat_of_remap_node("ralink,rt2880-sysc"); - rt_memc_membase = plat_of_remap_node("ralink,rt2880-memc"); - - if (!rt_sysc_membase || !rt_memc_membase) - panic("Failed to remap core resources"); -} - static unsigned int __init rt2880_get_soc_name0(void) { return __raw_readl(RT2880_SYSC_BASE + SYSC_REG_CHIP_NAME0); diff --git a/arch/mips/ralink/rt305x.c b/arch/mips/ralink/rt305x.c index d8dcc5cc66cc84ae75be7f2adc10e3e526e970ae..1f422470b02900755333412ccb11d98f7b9a17d2 100644 --- a/arch/mips/ralink/rt305x.c +++ b/arch/mips/ralink/rt305x.c @@ -56,93 +56,6 @@ static unsigned long rt5350_get_mem_size(void) return ret; } -void __init ralink_clk_init(void) -{ - unsigned long cpu_rate, sys_rate, wdt_rate, uart_rate; - unsigned long wmac_rate = 40000000; - - u32 t = rt_sysc_r32(SYSC_REG_SYSTEM_CONFIG); - - if (soc_is_rt305x() || soc_is_rt3350()) { - t = (t >> RT305X_SYSCFG_CPUCLK_SHIFT) & - RT305X_SYSCFG_CPUCLK_MASK; - switch (t) { - case RT305X_SYSCFG_CPUCLK_LOW: - cpu_rate = 320000000; - break; - case RT305X_SYSCFG_CPUCLK_HIGH: - cpu_rate = 384000000; - break; - } - sys_rate = uart_rate = wdt_rate = cpu_rate / 3; - } else if (soc_is_rt3352()) { - t = (t >> RT3352_SYSCFG0_CPUCLK_SHIFT) & - RT3352_SYSCFG0_CPUCLK_MASK; - switch (t) { - case RT3352_SYSCFG0_CPUCLK_LOW: - cpu_rate = 384000000; - break; - case RT3352_SYSCFG0_CPUCLK_HIGH: - cpu_rate = 400000000; - break; - } - sys_rate = wdt_rate = cpu_rate / 3; - uart_rate = 40000000; - } else if (soc_is_rt5350()) { - t = (t >> RT5350_SYSCFG0_CPUCLK_SHIFT) & - RT5350_SYSCFG0_CPUCLK_MASK; - switch (t) { - case RT5350_SYSCFG0_CPUCLK_360: - cpu_rate = 360000000; - sys_rate = cpu_rate / 3; - break; - case RT5350_SYSCFG0_CPUCLK_320: - cpu_rate = 320000000; - sys_rate = cpu_rate / 4; - break; - case RT5350_SYSCFG0_CPUCLK_300: - cpu_rate = 300000000; - sys_rate = cpu_rate / 3; - break; - default: - BUG(); - } - uart_rate = 40000000; - wdt_rate = sys_rate; - } else { - BUG(); - } - - if (soc_is_rt3352() || soc_is_rt5350()) { - u32 val = rt_sysc_r32(RT3352_SYSC_REG_SYSCFG0); - - if (!(val & RT3352_CLKCFG0_XTAL_SEL)) - wmac_rate = 20000000; - } - - ralink_clk_add("cpu", cpu_rate); - ralink_clk_add("sys", sys_rate); - ralink_clk_add("10000900.i2c", uart_rate); - ralink_clk_add("10000a00.i2s", uart_rate); - ralink_clk_add("10000b00.spi", sys_rate); - ralink_clk_add("10000b40.spi", sys_rate); - ralink_clk_add("10000100.timer", wdt_rate); - ralink_clk_add("10000120.watchdog", wdt_rate); - ralink_clk_add("10000500.uart", uart_rate); - ralink_clk_add("10000c00.uartlite", uart_rate); - ralink_clk_add("10100000.ethernet", sys_rate); - ralink_clk_add("10180000.wmac", wmac_rate); -} - -void __init ralink_of_remap(void) -{ - rt_sysc_membase = plat_of_remap_node("ralink,rt3050-sysc"); - rt_memc_membase = plat_of_remap_node("ralink,rt3050-memc"); - - if (!rt_sysc_membase || !rt_memc_membase) - panic("Failed to remap core resources"); -} - static unsigned int __init rt305x_get_soc_name0(void) { return __raw_readl(RT305X_SYSC_BASE + SYSC_REG_CHIP_NAME0); diff --git a/arch/mips/ralink/rt3883.c b/arch/mips/ralink/rt3883.c index cca887af378fb7cd2517013296e42bd9193354f8..21ce00da5758bfc807fa6f8f59fb590627e336c7 100644 --- a/arch/mips/ralink/rt3883.c +++ b/arch/mips/ralink/rt3883.c @@ -21,59 +21,6 @@ static struct ralink_soc_info *soc_info_ptr; -void __init ralink_clk_init(void) -{ - unsigned long cpu_rate, sys_rate; - u32 syscfg0; - u32 clksel; - u32 ddr2; - - syscfg0 = rt_sysc_r32(RT3883_SYSC_REG_SYSCFG0); - clksel = ((syscfg0 >> RT3883_SYSCFG0_CPUCLK_SHIFT) & - RT3883_SYSCFG0_CPUCLK_MASK); - ddr2 = syscfg0 & RT3883_SYSCFG0_DRAM_TYPE_DDR2; - - switch (clksel) { - case RT3883_SYSCFG0_CPUCLK_250: - cpu_rate = 250000000; - sys_rate = (ddr2) ? 125000000 : 83000000; - break; - case RT3883_SYSCFG0_CPUCLK_384: - cpu_rate = 384000000; - sys_rate = (ddr2) ? 128000000 : 96000000; - break; - case RT3883_SYSCFG0_CPUCLK_480: - cpu_rate = 480000000; - sys_rate = (ddr2) ? 160000000 : 120000000; - break; - case RT3883_SYSCFG0_CPUCLK_500: - cpu_rate = 500000000; - sys_rate = (ddr2) ? 166000000 : 125000000; - break; - } - - ralink_clk_add("cpu", cpu_rate); - ralink_clk_add("10000100.timer", sys_rate); - ralink_clk_add("10000120.watchdog", sys_rate); - ralink_clk_add("10000500.uart", 40000000); - ralink_clk_add("10000900.i2c", 40000000); - ralink_clk_add("10000a00.i2s", 40000000); - ralink_clk_add("10000b00.spi", sys_rate); - ralink_clk_add("10000b40.spi", sys_rate); - ralink_clk_add("10000c00.uartlite", 40000000); - ralink_clk_add("10100000.ethernet", sys_rate); - ralink_clk_add("10180000.wmac", 40000000); -} - -void __init ralink_of_remap(void) -{ - rt_sysc_membase = plat_of_remap_node("ralink,rt3883-sysc"); - rt_memc_membase = plat_of_remap_node("ralink,rt3883-memc"); - - if (!rt_sysc_membase || !rt_memc_membase) - panic("Failed to remap core resources"); -} - static unsigned int __init rt3883_get_soc_name0(void) { return __raw_readl(RT3883_SYSC_BASE + RT3883_SYSC_REG_CHIPID0_3); diff --git a/arch/mips/sibyte/swarm/platform.c b/arch/mips/sibyte/swarm/platform.c index 484969db77136178acf9025e862ae9eaa8f07a04..339d77a0a08ffe0c4ceeee1057f6f63dca7caa5d 100644 --- a/arch/mips/sibyte/swarm/platform.c +++ b/arch/mips/sibyte/swarm/platform.c @@ -88,15 +88,15 @@ device_initcall(swarm_pata_init); #define sb1250_dev_struct(num) \ static struct resource sb1250_res##num = { \ .name = "SB1250 MAC " __stringify(num), \ - .flags = IORESOURCE_MEM, \ - .start = A_MAC_CHANNEL_BASE(num), \ - .end = A_MAC_CHANNEL_BASE(num + 1) -1, \ + .flags = IORESOURCE_MEM, \ + .start = A_MAC_CHANNEL_BASE(num), \ + .end = A_MAC_CHANNEL_BASE(num + 1) - 1, \ };\ static struct platform_device sb1250_dev##num = { \ - .name = "sb1250-mac", \ - .id = num, \ - .resource = &sb1250_res##num, \ - .num_resources = 1, \ + .name = "sb1250-mac", \ + .id = num, \ + .resource = &sb1250_res##num, \ + .num_resources = 1, \ } sb1250_dev_struct(0); diff --git a/arch/nios2/Kconfig b/arch/nios2/Kconfig index e5936417d3cd3ced8cb159d477202e23da5b54bc..d54464021a618ecd20c7bd23cbf52bce65208592 100644 --- a/arch/nios2/Kconfig +++ b/arch/nios2/Kconfig @@ -16,6 +16,7 @@ config NIOS2 select HAVE_ARCH_TRACEHOOK select HAVE_ARCH_KGDB select IRQ_DOMAIN + select LOCK_MM_AND_FIND_VMA select MODULES_USE_ELF_RELA select OF select OF_EARLY_FLATTREE diff --git a/arch/nios2/configs/10m50_defconfig b/arch/nios2/configs/10m50_defconfig index 91c3fce4dc7fec49cf051819ae5bb3bc02841eed..63151ebf14709d2b0c59481cbd4eb66920406e55 100644 --- a/arch/nios2/configs/10m50_defconfig +++ b/arch/nios2/configs/10m50_defconfig @@ -10,7 +10,6 @@ CONFIG_LOG_BUF_SHIFT=14 # CONFIG_SHMEM is not set # CONFIG_AIO is not set CONFIG_EMBEDDED=y -CONFIG_SLAB=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y CONFIG_NIOS2_MEM_BASE=0x8000000 diff --git a/arch/nios2/configs/3c120_defconfig b/arch/nios2/configs/3c120_defconfig index c42ad7e162a3640d2476b30b8e468f55e696a3fe..0daf3038d7aa20e4895a33a749053466453076c4 100644 --- a/arch/nios2/configs/3c120_defconfig +++ b/arch/nios2/configs/3c120_defconfig @@ -10,7 +10,6 @@ CONFIG_LOG_BUF_SHIFT=14 # CONFIG_SHMEM is not set # CONFIG_AIO is not set CONFIG_EMBEDDED=y -CONFIG_SLAB=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y CONFIG_NIOS2_MEM_BASE=0x10000000 diff --git a/arch/nios2/kernel/cpuinfo.c b/arch/nios2/kernel/cpuinfo.c index 203870c4b86d9347840798118a218e31923e617f..338849c430a52f504806b3df025fd343eb7597e8 100644 --- a/arch/nios2/kernel/cpuinfo.c +++ b/arch/nios2/kernel/cpuinfo.c @@ -47,7 +47,7 @@ void __init setup_cpuinfo(void) str = of_get_property(cpu, "altr,implementation", &len); if (str) - strlcpy(cpuinfo.cpu_impl, str, sizeof(cpuinfo.cpu_impl)); + strscpy(cpuinfo.cpu_impl, str, sizeof(cpuinfo.cpu_impl)); else strcpy(cpuinfo.cpu_impl, ""); diff --git a/arch/nios2/kernel/setup.c b/arch/nios2/kernel/setup.c index 40bc8fb75e0b50fbb6fcc026169537e908d12390..8582ed9658447bc33657b84bc96b7b28039cd0f6 100644 --- a/arch/nios2/kernel/setup.c +++ b/arch/nios2/kernel/setup.c @@ -121,7 +121,7 @@ asmlinkage void __init nios2_boot_init(unsigned r4, unsigned r5, unsigned r6, dtb_passed = r6; if (r7) - strlcpy(cmdline_passed, (char *)r7, COMMAND_LINE_SIZE); + strscpy(cmdline_passed, (char *)r7, COMMAND_LINE_SIZE); } #endif @@ -129,10 +129,10 @@ asmlinkage void __init nios2_boot_init(unsigned r4, unsigned r5, unsigned r6, #ifndef CONFIG_CMDLINE_FORCE if (cmdline_passed[0]) - strlcpy(boot_command_line, cmdline_passed, COMMAND_LINE_SIZE); + strscpy(boot_command_line, cmdline_passed, COMMAND_LINE_SIZE); #ifdef CONFIG_NIOS2_CMDLINE_IGNORE_DTB else - strlcpy(boot_command_line, CONFIG_CMDLINE, COMMAND_LINE_SIZE); + strscpy(boot_command_line, CONFIG_CMDLINE, COMMAND_LINE_SIZE); #endif #endif diff --git a/arch/nios2/mm/fault.c b/arch/nios2/mm/fault.c index ca64eccea5511d223add396c5f92d486703858b0..e3fa9c15181df23e01085416dec3de5e41b922cf 100644 --- a/arch/nios2/mm/fault.c +++ b/arch/nios2/mm/fault.c @@ -86,27 +86,14 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long cause, perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address); - if (!mmap_read_trylock(mm)) { - if (!user_mode(regs) && !search_exception_tables(regs->ea)) - goto bad_area_nosemaphore; retry: - mmap_read_lock(mm); - } - - vma = find_vma(mm, address); + vma = lock_mm_and_find_vma(mm, address, regs); if (!vma) - goto bad_area; - if (vma->vm_start <= address) - goto good_area; - if (!(vma->vm_flags & VM_GROWSDOWN)) - goto bad_area; - if (expand_stack(vma, address)) - goto bad_area; + goto bad_area_nosemaphore; /* * Ok, we have a good vm_area for this memory access, so * we can handle it.. */ -good_area: code = SEGV_ACCERR; switch (cause) { diff --git a/arch/openrisc/include/asm/atomic.h b/arch/openrisc/include/asm/atomic.h index 326167e4783a9942770d0dd19bed922c7b051100..8ce67ec7c9a302b7b742a342704aa7c943f681b0 100644 --- a/arch/openrisc/include/asm/atomic.h +++ b/arch/openrisc/include/asm/atomic.h @@ -130,7 +130,4 @@ static inline int arch_atomic_fetch_add_unless(atomic_t *v, int a, int u) #include -#define arch_atomic_xchg(ptr, v) (arch_xchg(&(ptr)->counter, (v))) -#define arch_atomic_cmpxchg(v, old, new) (arch_cmpxchg(&((v)->counter), (old), (new))) - #endif /* __ASM_OPENRISC_ATOMIC_H */ diff --git a/arch/openrisc/include/uapi/asm/sigcontext.h b/arch/openrisc/include/uapi/asm/sigcontext.h index ca585e4af6b8eac431e100b229e938e49d274c35..e7ffb58ff58fb003c67e281b6697d98985c717cc 100644 --- a/arch/openrisc/include/uapi/asm/sigcontext.h +++ b/arch/openrisc/include/uapi/asm/sigcontext.h @@ -28,8 +28,10 @@ struct sigcontext { struct user_regs_struct regs; /* needs to be first */ - struct __or1k_fpu_state fpu; - unsigned long oldmask; + union { + unsigned long fpcsr; + unsigned long oldmask; /* unused */ + }; }; #endif /* __ASM_OPENRISC_SIGCONTEXT_H */ diff --git a/arch/openrisc/kernel/signal.c b/arch/openrisc/kernel/signal.c index 4664a18f0787d4e40e86061831aed605a82846c9..2e7257a433ff4f94a58c1562614b7e1e63b22f2c 100644 --- a/arch/openrisc/kernel/signal.c +++ b/arch/openrisc/kernel/signal.c @@ -50,7 +50,7 @@ static int restore_sigcontext(struct pt_regs *regs, err |= __copy_from_user(regs, sc->regs.gpr, 32 * sizeof(unsigned long)); err |= __copy_from_user(®s->pc, &sc->regs.pc, sizeof(unsigned long)); err |= __copy_from_user(®s->sr, &sc->regs.sr, sizeof(unsigned long)); - err |= __copy_from_user(®s->fpcsr, &sc->fpu.fpcsr, sizeof(unsigned long)); + err |= __copy_from_user(®s->fpcsr, &sc->fpcsr, sizeof(unsigned long)); /* make sure the SM-bit is cleared so user-mode cannot fool us */ regs->sr &= ~SPR_SR_SM; @@ -113,7 +113,7 @@ static int setup_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc) err |= __copy_to_user(sc->regs.gpr, regs, 32 * sizeof(unsigned long)); err |= __copy_to_user(&sc->regs.pc, ®s->pc, sizeof(unsigned long)); err |= __copy_to_user(&sc->regs.sr, ®s->sr, sizeof(unsigned long)); - err |= __copy_to_user(&sc->fpu.fpcsr, ®s->fpcsr, sizeof(unsigned long)); + err |= __copy_to_user(&sc->fpcsr, ®s->fpcsr, sizeof(unsigned long)); return err; } diff --git a/arch/openrisc/mm/fault.c b/arch/openrisc/mm/fault.c index 6734fee3134f4fc285b575d151f2f1bf35133c7c..a9dcd4381d1a11a7c62fa72ee358fb1cf4c5e852 100644 --- a/arch/openrisc/mm/fault.c +++ b/arch/openrisc/mm/fault.c @@ -127,8 +127,9 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long address, if (address + PAGE_SIZE < regs->sp) goto bad_area; } - if (expand_stack(vma, address)) - goto bad_area; + vma = expand_stack(mm, address); + if (!vma) + goto bad_area_nosemaphore; /* * Ok, we have a good vm_area for this memory access, so diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig index 967bde65dd0ec895d78b2314a49aa8cb043e28c0..4cb46d5c64a270ad37ae2a568c0f2cb3804a495e 100644 --- a/arch/parisc/Kconfig +++ b/arch/parisc/Kconfig @@ -57,6 +57,7 @@ config PARISC select HAVE_ARCH_SECCOMP_FILTER select HAVE_ARCH_TRACEHOOK select HAVE_REGS_AND_STACK_ACCESS_API + select HOTPLUG_CORE_SYNC_DEAD if HOTPLUG_CPU select GENERIC_SCHED_CLOCK select GENERIC_IRQ_MIGRATION if SMP select HAVE_UNSTABLE_SCHED_CLOCK if SMP @@ -303,16 +304,6 @@ config IRQSTACKS for handling hard and soft interrupts. This can help avoid overflowing the process kernel stacks. -config TLB_PTLOCK - bool "Use page table locks in TLB fault handler" - depends on SMP - default n - help - Select this option to enable page table locking in the TLB - fault handler. This ensures that page table entries are - updated consistently on SMP machines at the expense of some - loss in performance. - config HOTPLUG_CPU bool default y if SMP @@ -345,7 +336,7 @@ config NR_CPUS int "Maximum number of CPUs (2-32)" range 2 32 depends on SMP - default "4" if 64BIT + default "8" if 64BIT default "16" config KEXEC diff --git a/arch/parisc/Kconfig.debug b/arch/parisc/Kconfig.debug index 3a059cb5e112fb09fe701fe362c07c84cec247e2..1401e4c5fe5f7ab1c6d77f9e033e9bbe1749b9b3 100644 --- a/arch/parisc/Kconfig.debug +++ b/arch/parisc/Kconfig.debug @@ -10,3 +10,14 @@ config LIGHTWEIGHT_SPINLOCK_CHECK spinlock debugging you should choose the DEBUG_SPINLOCK option which will detect unitialized spinlocks too. If unsure say Y here. + +config TLB_PTLOCK + bool "Use page table locks in TLB fault handler" + depends on SMP + default n + help + Select this option to enable page table locking in the TLB + fault handler. This ensures that page table entries are + updated consistently on SMP machines at the expense of some + loss in performance. + diff --git a/arch/parisc/configs/generic-32bit_defconfig b/arch/parisc/configs/generic-32bit_defconfig index 8ce0ae3706804defdc1cc6428befd709038a262a..9651f4390029887b9f611cbee2c1cb01877c21fb 100644 --- a/arch/parisc/configs/generic-32bit_defconfig +++ b/arch/parisc/configs/generic-32bit_defconfig @@ -12,7 +12,6 @@ CONFIG_USER_NS=y CONFIG_BLK_DEV_INITRD=y CONFIG_EXPERT=y CONFIG_PERF_EVENTS=y -CONFIG_SLAB=y CONFIG_PA7100LC=y CONFIG_SMP=y CONFIG_HZ_100=y @@ -83,7 +82,6 @@ CONFIG_TUN=m # CONFIG_NET_VENDOR_AMD is not set # CONFIG_NET_VENDOR_ATHEROS is not set # CONFIG_NET_VENDOR_BROADCOM is not set -# CONFIG_NET_VENDOR_BROCADE is not set # CONFIG_NET_VENDOR_CHELSIO is not set # CONFIG_NET_VENDOR_CISCO is not set CONFIG_NET_TULIP=y @@ -98,6 +96,7 @@ CONFIG_LASI_82596=y # CONFIG_NET_VENDOR_NVIDIA is not set # CONFIG_NET_VENDOR_OKI is not set # CONFIG_NET_VENDOR_QLOGIC is not set +# CONFIG_NET_VENDOR_BROCADE is not set # CONFIG_NET_VENDOR_RDC is not set # CONFIG_NET_VENDOR_REALTEK is not set # CONFIG_NET_VENDOR_SEEQ is not set @@ -130,17 +129,53 @@ CONFIG_PRINTER=m CONFIG_PPDEV=m # CONFIG_HW_RANDOM is not set CONFIG_I2C=y -# CONFIG_HWMON is not set +CONFIG_HWMON=m +CONFIG_DRM=m +CONFIG_DRM_DP_CEC=y +# CONFIG_DRM_I2C_CH7006 is not set +# CONFIG_DRM_I2C_SIL164 is not set +CONFIG_DRM_RADEON=m +CONFIG_DRM_NOUVEAU=m +# CONFIG_DRM_NOUVEAU_BACKLIGHT is not set +CONFIG_DRM_VGEM=m +CONFIG_DRM_UDL=m +CONFIG_DRM_MGAG200=m CONFIG_FB=y CONFIG_FB_FOREIGN_ENDIAN=y -CONFIG_FB_MODE_HELPERS=y +CONFIG_FB_PM2=m +CONFIG_FB_PM2_FIFO_DISCONNECT=y +CONFIG_FB_NVIDIA=m +CONFIG_FB_NVIDIA_I2C=y +# CONFIG_FB_NVIDIA_BACKLIGHT is not set +CONFIG_FB_RIVA=m +CONFIG_FB_RIVA_I2C=y +# CONFIG_FB_RIVA_BACKLIGHT is not set CONFIG_FB_MATROX=m +CONFIG_FB_MATROX_MILLENIUM=y +CONFIG_FB_MATROX_MYSTIQUE=y CONFIG_FB_MATROX_G=y +CONFIG_FB_MATROX_I2C=m +CONFIG_FB_MATROX_MAVEN=m +CONFIG_FB_ATY128=m +# CONFIG_FB_ATY128_BACKLIGHT is not set +CONFIG_FB_ATY=m +CONFIG_FB_ATY_CT=y +CONFIG_FB_ATY_GX=y +# CONFIG_FB_ATY_BACKLIGHT is not set +CONFIG_FB_S3=m +CONFIG_FB_SAVAGE=m +CONFIG_FB_SAVAGE_I2C=y +CONFIG_FB_SAVAGE_ACCEL=y +CONFIG_FB_SIS=m +CONFIG_FB_SIS_300=y +CONFIG_FB_SIS_315=y CONFIG_FB_VOODOO1=m +CONFIG_FB_TRIDENT=m +CONFIG_FB_SMSCUFX=m +CONFIG_FB_UDL=m CONFIG_DUMMY_CONSOLE_COLUMNS=128 CONFIG_DUMMY_CONSOLE_ROWS=48 CONFIG_FRAMEBUFFER_CONSOLE=y -CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y CONFIG_LOGO=y # CONFIG_LOGO_LINUX_MONO is not set # CONFIG_LOGO_LINUX_VGA16 is not set @@ -217,17 +252,17 @@ CONFIG_CIFS_XATTR=y CONFIG_CIFS_POSIX=y # CONFIG_CIFS_DEBUG is not set CONFIG_CRYPTO_TEST=m -CONFIG_CRYPTO_HMAC=y -CONFIG_CRYPTO_MD5=y -CONFIG_CRYPTO_MICHAEL_MIC=m -CONFIG_CRYPTO_SHA1=y -CONFIG_CRYPTO_WP512=m CONFIG_CRYPTO_BLOWFISH=m CONFIG_CRYPTO_CAST5=m CONFIG_CRYPTO_CAST6=m CONFIG_CRYPTO_DES=y CONFIG_CRYPTO_SERPENT=m CONFIG_CRYPTO_TWOFISH=m +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_MD5=y +CONFIG_CRYPTO_MICHAEL_MIC=m +CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_WP512=m CONFIG_CRYPTO_DEFLATE=y CONFIG_CRC_CCITT=m CONFIG_CRC_T10DIF=y diff --git a/arch/parisc/configs/generic-64bit_defconfig b/arch/parisc/configs/generic-64bit_defconfig index 57501b0aed92ef0a7eddf1e4331c57618c8d6467..6758c030b09d391eef09a5d8477fd7f9b1208f2d 100644 --- a/arch/parisc/configs/generic-64bit_defconfig +++ b/arch/parisc/configs/generic-64bit_defconfig @@ -20,9 +20,6 @@ CONFIG_USER_NS=y CONFIG_RELAY=y CONFIG_BLK_DEV_INITRD=y CONFIG_CC_OPTIMIZE_FOR_SIZE=y -# CONFIG_COMPAT_BRK is not set -CONFIG_PA8X00=y -CONFIG_64BIT=y CONFIG_SMP=y CONFIG_HPPB=y CONFIG_IOMMU_CCIO=y @@ -37,6 +34,7 @@ CONFIG_MODULE_FORCE_UNLOAD=y CONFIG_MODVERSIONS=y CONFIG_BLK_DEV_INTEGRITY=y CONFIG_BINFMT_MISC=m +# CONFIG_COMPAT_BRK is not set # CONFIG_COMPACTION is not set CONFIG_MEMORY_FAILURE=y CONFIG_NET=y @@ -103,7 +101,6 @@ CONFIG_TUN=y # CONFIG_NET_VENDOR_AMD is not set # CONFIG_NET_VENDOR_ATHEROS is not set # CONFIG_NET_VENDOR_BROADCOM is not set -# CONFIG_NET_VENDOR_BROCADE is not set # CONFIG_NET_VENDOR_CHELSIO is not set # CONFIG_NET_VENDOR_CISCO is not set CONFIG_NET_TULIP=y @@ -121,6 +118,7 @@ CONFIG_E1000=y # CONFIG_NET_VENDOR_OKI is not set CONFIG_QLA3XXX=m CONFIG_QLCNIC=m +# CONFIG_NET_VENDOR_BROCADE is not set # CONFIG_NET_VENDOR_RDC is not set # CONFIG_NET_VENDOR_REALTEK is not set # CONFIG_NET_VENDOR_SEEQ is not set @@ -186,7 +184,6 @@ CONFIG_WATCHDOG=y CONFIG_SOFT_WATCHDOG=m CONFIG_SSB=m CONFIG_SSB_DRIVER_PCICORE=y -CONFIG_HTC_PASIC3=m CONFIG_LPC_SCH=m CONFIG_MFD_SM501=m CONFIG_REGULATOR=y @@ -196,14 +193,46 @@ CONFIG_MEDIA_SUPPORT=m CONFIG_AGP=y CONFIG_AGP_PARISC=y CONFIG_DRM=y +# CONFIG_DRM_I2C_CH7006 is not set +# CONFIG_DRM_I2C_SIL164 is not set CONFIG_DRM_RADEON=y +CONFIG_DRM_NOUVEAU=m +# CONFIG_DRM_NOUVEAU_BACKLIGHT is not set +CONFIG_DRM_MGAG200=m CONFIG_FB=y -CONFIG_FB_MATROX=y +CONFIG_FB_PM2=m +CONFIG_FB_PM2_FIFO_DISCONNECT=y +CONFIG_FB_NVIDIA=m +CONFIG_FB_NVIDIA_I2C=y +# CONFIG_FB_NVIDIA_BACKLIGHT is not set +CONFIG_FB_RIVA=m +CONFIG_FB_RIVA_I2C=y +# CONFIG_FB_RIVA_BACKLIGHT is not set +CONFIG_FB_MATROX=m +CONFIG_FB_MATROX_MILLENIUM=y CONFIG_FB_MATROX_MYSTIQUE=y CONFIG_FB_MATROX_G=y -CONFIG_FB_MATROX_I2C=y -CONFIG_FB_MATROX_MAVEN=y +CONFIG_FB_MATROX_I2C=m +CONFIG_FB_MATROX_MAVEN=m CONFIG_FB_RADEON=y +# CONFIG_FB_RADEON_BACKLIGHT is not set +CONFIG_FB_ATY128=m +# CONFIG_FB_ATY128_BACKLIGHT is not set +CONFIG_FB_ATY=m +CONFIG_FB_ATY_CT=y +CONFIG_FB_ATY_GX=y +# CONFIG_FB_ATY_BACKLIGHT is not set +CONFIG_FB_S3=m +CONFIG_FB_SAVAGE=m +CONFIG_FB_SAVAGE_I2C=y +CONFIG_FB_SAVAGE_ACCEL=y +CONFIG_FB_SIS=m +CONFIG_FB_SIS_300=y +CONFIG_FB_SIS_315=y +CONFIG_FB_VOODOO1=m +CONFIG_FB_TRIDENT=m +CONFIG_FB_SMSCUFX=m +CONFIG_FB_UDL=m CONFIG_LOGO=y # CONFIG_LOGO_LINUX_CLUT224 is not set CONFIG_HIDRAW=y @@ -257,12 +286,12 @@ CONFIG_NLS_ISO8859_1=m CONFIG_NLS_ISO8859_2=m CONFIG_NLS_UTF8=m CONFIG_CRYPTO_MANAGER=y +CONFIG_CRYPTO_FCRYPT=m CONFIG_CRYPTO_ECB=m CONFIG_CRYPTO_PCBC=m CONFIG_CRYPTO_MD4=m CONFIG_CRYPTO_MD5=y CONFIG_CRYPTO_MICHAEL_MIC=m -CONFIG_CRYPTO_FCRYPT=m CONFIG_CRYPTO_DEFLATE=m # CONFIG_CRYPTO_HW is not set CONFIG_CRC_CCITT=m diff --git a/arch/parisc/include/asm/atomic.h b/arch/parisc/include/asm/atomic.h index dd5a299ada6951fe486cea3f16b6a47f3a931428..d4f023887ff870de5be3d3dc4b89375f564912a7 100644 --- a/arch/parisc/include/asm/atomic.h +++ b/arch/parisc/include/asm/atomic.h @@ -73,10 +73,6 @@ static __inline__ int arch_atomic_read(const atomic_t *v) return READ_ONCE((v)->counter); } -/* exported interface */ -#define arch_atomic_cmpxchg(v, o, n) (arch_cmpxchg(&((v)->counter), (o), (n))) -#define arch_atomic_xchg(v, new) (arch_xchg(&((v)->counter), new)) - #define ATOMIC_OP(op, c_op) \ static __inline__ void arch_atomic_##op(int i, atomic_t *v) \ { \ @@ -122,6 +118,11 @@ static __inline__ int arch_atomic_fetch_##op(int i, atomic_t *v) \ ATOMIC_OPS(add, +=) ATOMIC_OPS(sub, -=) +#define arch_atomic_add_return arch_atomic_add_return +#define arch_atomic_sub_return arch_atomic_sub_return +#define arch_atomic_fetch_add arch_atomic_fetch_add +#define arch_atomic_fetch_sub arch_atomic_fetch_sub + #undef ATOMIC_OPS #define ATOMIC_OPS(op, c_op) \ ATOMIC_OP(op, c_op) \ @@ -131,6 +132,10 @@ ATOMIC_OPS(and, &=) ATOMIC_OPS(or, |=) ATOMIC_OPS(xor, ^=) +#define arch_atomic_fetch_and arch_atomic_fetch_and +#define arch_atomic_fetch_or arch_atomic_fetch_or +#define arch_atomic_fetch_xor arch_atomic_fetch_xor + #undef ATOMIC_OPS #undef ATOMIC_FETCH_OP #undef ATOMIC_OP_RETURN @@ -185,6 +190,11 @@ static __inline__ s64 arch_atomic64_fetch_##op(s64 i, atomic64_t *v) \ ATOMIC64_OPS(add, +=) ATOMIC64_OPS(sub, -=) +#define arch_atomic64_add_return arch_atomic64_add_return +#define arch_atomic64_sub_return arch_atomic64_sub_return +#define arch_atomic64_fetch_add arch_atomic64_fetch_add +#define arch_atomic64_fetch_sub arch_atomic64_fetch_sub + #undef ATOMIC64_OPS #define ATOMIC64_OPS(op, c_op) \ ATOMIC64_OP(op, c_op) \ @@ -194,6 +204,10 @@ ATOMIC64_OPS(and, &=) ATOMIC64_OPS(or, |=) ATOMIC64_OPS(xor, ^=) +#define arch_atomic64_fetch_and arch_atomic64_fetch_and +#define arch_atomic64_fetch_or arch_atomic64_fetch_or +#define arch_atomic64_fetch_xor arch_atomic64_fetch_xor + #undef ATOMIC64_OPS #undef ATOMIC64_FETCH_OP #undef ATOMIC64_OP_RETURN @@ -218,11 +232,6 @@ arch_atomic64_read(const atomic64_t *v) return READ_ONCE((v)->counter); } -/* exported interface */ -#define arch_atomic64_cmpxchg(v, o, n) \ - ((__typeof__((v)->counter))arch_cmpxchg(&((v)->counter), (o), (n))) -#define arch_atomic64_xchg(v, new) (arch_xchg(&((v)->counter), new)) - #endif /* !CONFIG_64BIT */ diff --git a/arch/parisc/include/asm/bugs.h b/arch/parisc/include/asm/bugs.h deleted file mode 100644 index 0a7f9db6bd1c7c0b93e5e12f0aa25a2dc7162b4e..0000000000000000000000000000000000000000 --- a/arch/parisc/include/asm/bugs.h +++ /dev/null @@ -1,20 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * include/asm-parisc/bugs.h - * - * Copyright (C) 1999 Mike Shaver - */ - -/* - * This is included by init/main.c to check for architecture-dependent bugs. - * - * Needs: - * void check_bugs(void); - */ - -#include - -static inline void check_bugs(void) -{ -// identify_cpu(&boot_cpu_data); -} diff --git a/arch/parisc/include/asm/irqflags.h b/arch/parisc/include/asm/irqflags.h index 38a19c0bac3ac5cd24f2b89bf08b59522b61d76e..00fd87724588031defd4fcc40081379b07d4d48c 100644 --- a/arch/parisc/include/asm/irqflags.h +++ b/arch/parisc/include/asm/irqflags.h @@ -31,6 +31,11 @@ static inline unsigned long arch_local_irq_save(void) static inline void arch_local_irq_restore(unsigned long flags) { + /* warn if IRQs are on although they should be off */ + if (IS_ENABLED(CONFIG_LIGHTWEIGHT_SPINLOCK_CHECK)) + if (arch_local_save_flags() & PSW_I) + asm volatile("break 6,6\n"); /* SPINLOCK_BREAK_INSN */ + asm volatile("mtsm %0" : : "r" (flags) : "memory"); } diff --git a/arch/parisc/include/asm/pdc.h b/arch/parisc/include/asm/pdc.h index 2b4fad8328e859b3ba0d421701538389ca4d29db..269b9a159f01fbec54e164d7baaffcf629c1ce6e 100644 --- a/arch/parisc/include/asm/pdc.h +++ b/arch/parisc/include/asm/pdc.h @@ -88,8 +88,8 @@ int pdc_iodc_print(const unsigned char *str, unsigned count); void pdc_emergency_unlock(void); int pdc_sti_call(unsigned long func, unsigned long flags, - unsigned long inptr, unsigned long outputr, - unsigned long glob_cfg); + unsigned long inptr, unsigned long outputr, + unsigned long glob_cfg, int do_call64); int __pdc_cpu_rendezvous(void); void pdc_cpu_rendezvous_lock(void); diff --git a/arch/parisc/include/asm/pgtable.h b/arch/parisc/include/asm/pgtable.h index e715df5385d6e5c415decd20f89d8c47f8ee5567..5656395c95eef126283f59f813f566a8c2d9af9e 100644 --- a/arch/parisc/include/asm/pgtable.h +++ b/arch/parisc/include/asm/pgtable.h @@ -472,9 +472,6 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, #define pte_same(A,B) (pte_val(A) == pte_val(B)) -struct seq_file; -extern void arch_report_meminfo(struct seq_file *m); - #endif /* !__ASSEMBLY__ */ diff --git a/arch/parisc/include/asm/processor.h b/arch/parisc/include/asm/processor.h index a608970b249af7fbbf3cef99a22fe9549f6c0c22..e132b2819fc905c32a81680440eabee0dc9421d4 100644 --- a/arch/parisc/include/asm/processor.h +++ b/arch/parisc/include/asm/processor.h @@ -11,6 +11,7 @@ #ifndef __ASSEMBLY__ #include +#include #include #include @@ -291,6 +292,42 @@ extern void __noreturn toc_intr(struct pt_regs *regs); extern void toc_handler(void); extern unsigned int toc_handler_size; extern unsigned int toc_handler_csum; +extern void do_cpu_irq_mask(struct pt_regs *); +extern irqreturn_t timer_interrupt(int, void *); +extern irqreturn_t ipi_interrupt(int, void *); +extern void start_cpu_itimer(void); +extern void handle_interruption(int, struct pt_regs *); + +/* called from assembly code: */ +extern void start_parisc(void); +extern void smp_callin(unsigned long); +extern void sys_rt_sigreturn(struct pt_regs *, int); +extern void do_notify_resume(struct pt_regs *, long); +extern long do_syscall_trace_enter(struct pt_regs *); +extern void do_syscall_trace_exit(struct pt_regs *); + +/* CPU startup and info */ +struct seq_file; +extern void early_trap_init(void); +extern void collect_boot_cpu_data(void); +extern int show_cpuinfo (struct seq_file *m, void *v); + +/* driver code in driver/parisc */ +extern void gsc_init(void); +extern void processor_init(void); +extern void ccio_init(void); +extern void hppb_init(void); +extern void dino_init(void); +extern void iosapic_init(void); +extern void lba_init(void); +extern void sba_init(void); +extern void parisc_eisa_init(void); +struct parisc_device; +struct resource; +extern void sba_distributed_lmmio(struct parisc_device *, struct resource *); +extern void sba_directed_lmmio(struct parisc_device *, struct resource *); +extern void lba_set_iregs(struct parisc_device *lba, u32 ibase, u32 imask); +extern void ccio_cujo20_fixup(struct parisc_device *dev, u32 iovp); #endif /* __ASSEMBLY__ */ diff --git a/arch/parisc/include/uapi/asm/cachectl.h b/arch/parisc/include/uapi/asm/cachectl.h new file mode 100644 index 0000000000000000000000000000000000000000..68d6b455498bddf0296c6b916ff3ff88249debf2 --- /dev/null +++ b/arch/parisc/include/uapi/asm/cachectl.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef _ASM_CACHECTL +#define _ASM_CACHECTL + +/* + * Options for cacheflush system call + */ +#define ICACHE (1<<0) /* flush instruction cache */ +#define DCACHE (1<<1) /* writeback and flush data cache */ +#define BCACHE (ICACHE|DCACHE) /* flush both caches */ + +#endif /* _ASM_CACHECTL */ diff --git a/arch/parisc/include/uapi/asm/socket.h b/arch/parisc/include/uapi/asm/socket.h index f486d3dfb6bb6245c7badb863dc5354b2049e45b..be264c2b1a1178806133eb651cf452fcf0b6523a 100644 --- a/arch/parisc/include/uapi/asm/socket.h +++ b/arch/parisc/include/uapi/asm/socket.h @@ -129,6 +129,9 @@ #define SO_RCVMARK 0x4049 +#define SO_PASSPIDFD 0x404A +#define SO_PEERPIDFD 0x404B + #if !defined(__KERNEL__) #if __BITS_PER_LONG == 64 diff --git a/arch/parisc/kernel/Makefile b/arch/parisc/kernel/Makefile index 3d138c9cf9ce9ebe9a68591831e676d605164dc3..2d1478fc4aa5b1dfa25e39c53edac4e5c34c7d92 100644 --- a/arch/parisc/kernel/Makefile +++ b/arch/parisc/kernel/Makefile @@ -21,6 +21,9 @@ CFLAGS_REMOVE_unwind.o = $(CC_FLAGS_FTRACE) CFLAGS_REMOVE_patch.o = $(CC_FLAGS_FTRACE) endif +CFLAGS_REMOVE_sys_parisc.o = -Wmissing-prototypes -Wmissing-declarations +CFLAGS_REMOVE_sys_parisc32.o = -Wmissing-prototypes -Wmissing-declarations + obj-$(CONFIG_SMP) += smp.o obj-$(CONFIG_PA11) += pci-dma.o obj-$(CONFIG_PCI) += pci.o diff --git a/arch/parisc/kernel/audit.c b/arch/parisc/kernel/audit.c index f420b55521402b4ffee9c08949c68903d553b814..375cd73b52814ccd0df23d70b3697e792c9727d0 100644 --- a/arch/parisc/kernel/audit.c +++ b/arch/parisc/kernel/audit.c @@ -40,11 +40,6 @@ int audit_classify_arch(int arch) int audit_classify_syscall(int abi, unsigned syscall) { -#ifdef CONFIG_COMPAT - extern int parisc32_classify_syscall(unsigned); - if (abi == AUDIT_ARCH_PARISC) - return parisc32_classify_syscall(syscall); -#endif switch (syscall) { case __NR_open: return AUDITSC_OPEN; @@ -55,6 +50,10 @@ int audit_classify_syscall(int abi, unsigned syscall) case __NR_openat2: return AUDITSC_OPENAT2; default: +#ifdef CONFIG_COMPAT + if (abi == AUDIT_ARCH_PARISC) + return AUDITSC_COMPAT; +#endif return AUDITSC_NATIVE; } } diff --git a/arch/parisc/kernel/cache.c b/arch/parisc/kernel/cache.c index ca4a302d4365fe9e7472d3c748b69369233610af..b55b35c89d6ac14f21025b549abaeb27ace00fbd 100644 --- a/arch/parisc/kernel/cache.c +++ b/arch/parisc/kernel/cache.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -28,6 +29,7 @@ #include #include #include +#include int split_tlb __ro_after_init; int dcache_stride __ro_after_init; @@ -426,10 +428,15 @@ void flush_dcache_page(struct page *page) offset = (pgoff - mpnt->vm_pgoff) << PAGE_SHIFT; addr = mpnt->vm_start + offset; if (parisc_requires_coherency()) { + bool needs_flush = false; pte_t *ptep; ptep = get_ptep(mpnt->vm_mm, addr); - if (ptep && pte_needs_flush(*ptep)) + if (ptep) { + needs_flush = pte_needs_flush(*ptep); + pte_unmap(ptep); + } + if (needs_flush) flush_user_cache_page(mpnt, addr); } else { /* @@ -561,14 +568,20 @@ EXPORT_SYMBOL(flush_kernel_dcache_page_addr); static void flush_cache_page_if_present(struct vm_area_struct *vma, unsigned long vmaddr, unsigned long pfn) { - pte_t *ptep = get_ptep(vma->vm_mm, vmaddr); + bool needs_flush = false; + pte_t *ptep; /* * The pte check is racy and sometimes the flush will trigger * a non-access TLB miss. Hopefully, the page has already been * flushed. */ - if (ptep && pte_needs_flush(*ptep)) + ptep = get_ptep(vma->vm_mm, vmaddr); + if (ptep) { + needs_flush = pte_needs_flush(*ptep); + pte_unmap(ptep); + } + if (needs_flush) flush_cache_page(vma, vmaddr, pfn); } @@ -635,17 +648,22 @@ static void flush_cache_pages(struct vm_area_struct *vma, unsigned long start, u pte_t *ptep; for (addr = start; addr < end; addr += PAGE_SIZE) { + bool needs_flush = false; /* * The vma can contain pages that aren't present. Although * the pte search is expensive, we need the pte to find the * page pfn and to check whether the page should be flushed. */ ptep = get_ptep(vma->vm_mm, addr); - if (ptep && pte_needs_flush(*ptep)) { + if (ptep) { + needs_flush = pte_needs_flush(*ptep); + pfn = pte_pfn(*ptep); + pte_unmap(ptep); + } + if (needs_flush) { if (parisc_requires_coherency()) { flush_user_cache_page(vma, addr); } else { - pfn = pte_pfn(*ptep); if (WARN_ON(!pfn_valid(pfn))) return; __flush_cache_page(vma, addr, PFN_PHYS(pfn)); @@ -774,3 +792,50 @@ void invalidate_kernel_vmap_range(void *vaddr, int size) flush_tlb_kernel_range(start, end); } EXPORT_SYMBOL(invalidate_kernel_vmap_range); + + +SYSCALL_DEFINE3(cacheflush, unsigned long, addr, unsigned long, bytes, + unsigned int, cache) +{ + unsigned long start, end; + ASM_EXCEPTIONTABLE_VAR(error); + + if (bytes == 0) + return 0; + if (!access_ok((void __user *) addr, bytes)) + return -EFAULT; + + end = addr + bytes; + + if (cache & DCACHE) { + start = addr; + __asm__ __volatile__ ( +#ifdef CONFIG_64BIT + "1: cmpb,*<<,n %0,%2,1b\n" +#else + "1: cmpb,<<,n %0,%2,1b\n" +#endif + " fic,m %3(%4,%0)\n" + "2: sync\n" + ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 2b) + : "+r" (start), "+r" (error) + : "r" (end), "r" (dcache_stride), "i" (SR_USER)); + } + + if (cache & ICACHE && error == 0) { + start = addr; + __asm__ __volatile__ ( +#ifdef CONFIG_64BIT + "1: cmpb,*<<,n %0,%2,1b\n" +#else + "1: cmpb,<<,n %0,%2,1b\n" +#endif + " fdc,m %3(%4,%0)\n" + "2: sync\n" + ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 2b) + : "+r" (start), "+r" (error) + : "r" (end), "r" (icache_stride), "i" (SR_USER)); + } + + return error; +} diff --git a/arch/parisc/kernel/compat_audit.c b/arch/parisc/kernel/compat_audit.c index 539b16891bdf4609d019949436f11a45be270624..3ac53f1ab8609ab688c4698aa7ec4b55ab2cf357 100644 --- a/arch/parisc/kernel/compat_audit.c +++ b/arch/parisc/kernel/compat_audit.c @@ -26,19 +26,3 @@ unsigned int parisc32_signal_class[] = { #include ~0U }; - -int parisc32_classify_syscall(unsigned syscall) -{ - switch (syscall) { - case __NR_open: - return AUDITSC_OPEN; - case __NR_openat: - return AUDITSC_OPENAT; - case __NR_execve: - return AUDITSC_EXECVE; - case __NR_openat2: - return AUDITSC_OPENAT2; - default: - return AUDITSC_COMPAT; - } -} diff --git a/arch/parisc/kernel/drivers.c b/arch/parisc/kernel/drivers.c index 28f47285d448c0ab5f8cb640d2ca4ebdc451eb0f..8f4b77648491a4b38f15bc1df1c12cfe9c1b0c8e 100644 --- a/arch/parisc/kernel/drivers.c +++ b/arch/parisc/kernel/drivers.c @@ -4,7 +4,7 @@ * * Copyright (c) 1999 The Puffin Group * Copyright (c) 2001 Matthew Wilcox for Hewlett Packard - * Copyright (c) 2001 Helge Deller + * Copyright (c) 2001-2023 Helge Deller * Copyright (c) 2001,2002 Ryan Bradetich * Copyright (c) 2004-2005 Thibaut VARENE * @@ -74,13 +74,13 @@ static int descend_children(struct device * dev, void * data) } /** - * for_each_padev - Iterate over all devices in the tree - * @fn: Function to call for each device. - * @data: Data to pass to the called function. + * for_each_padev - Iterate over all devices in the tree + * @fn: Function to call for each device. + * @data: Data to pass to the called function. * - * This performs a depth-first traversal of the tree, calling the - * function passed for each node. It calls the function for parents - * before children. + * This performs a depth-first traversal of the tree, calling the + * function passed for each node. It calls the function for parents + * before children. */ static int for_each_padev(int (*fn)(struct device *, void *), void * data) @@ -280,7 +280,7 @@ int __init machine_has_merced_bus(void) /** * find_pa_parent_type - Find a parent of a specific type - * @dev: The device to start searching from + * @padev: The device to start searching from * @type: The device type to search for. * * Walks up the device tree looking for a device of the specified type. @@ -344,8 +344,8 @@ static char *print_hwpath(struct hardware_path *path, char *output) /** * print_pa_hwpath - Returns hardware path for PA devices - * dev: The device to return the path for - * output: Pointer to a previously-allocated array to place the path in. + * @dev: The device to return the path for + * @output: Pointer to a previously-allocated array to place the path in. * * This function fills in the output array with a human-readable path * to a PA device. This string is compatible with that used by PDC, and @@ -379,8 +379,8 @@ EXPORT_SYMBOL(get_pci_node_path); /** * print_pci_hwpath - Returns hardware path for PCI devices - * dev: The device to return the path for - * output: Pointer to a previously-allocated array to place the path in. + * @dev: The device to return the path for + * @output: Pointer to a previously-allocated array to place the path in. * * This function fills in the output array with a human-readable path * to a PCI device. This string is compatible with that used by PDC, and @@ -415,7 +415,8 @@ static void setup_bus_id(struct parisc_device *padev) dev_set_name(&padev->dev, name); } -struct parisc_device * __init create_tree_node(char id, struct device *parent) +static struct parisc_device * __init create_tree_node(char id, + struct device *parent) { struct parisc_device *dev = kzalloc(sizeof(*dev), GFP_KERNEL); if (!dev) @@ -741,7 +742,7 @@ parse_tree_node(struct device *parent, int index, struct hardware_path *modpath) }; if (device_for_each_child(parent, &recurse_data, descend_children)) - /* nothing */; + { /* nothing */ }; return d.dev; } @@ -771,8 +772,8 @@ EXPORT_SYMBOL(hwpath_to_device); /** * device_to_hwpath - Populates the hwpath corresponding to the given device. - * @param dev the target device - * @param path pointer to a previously allocated hwpath struct to be filled in + * @dev: the target device + * @path: pointer to a previously allocated hwpath struct to be filled in */ void device_to_hwpath(struct device *dev, struct hardware_path *path) { diff --git a/arch/parisc/kernel/firmware.c b/arch/parisc/kernel/firmware.c index cc124d9f1f7f70f3bb66d777c85d77db058f4900..6d1c781eb1dbd88ff91d9aa59a301b86b3cf929a 100644 --- a/arch/parisc/kernel/firmware.c +++ b/arch/parisc/kernel/firmware.c @@ -134,7 +134,7 @@ static unsigned long f_extend(unsigned long address) /** * convert_to_wide - Convert the return buffer addresses into kernel addresses. - * @address: The return buffer from PDC. + * @addr: The return buffer from PDC. * * This function is used to convert the return buffer addresses retrieved from PDC * into kernel addresses when the PDC address size and kernel address size are @@ -160,6 +160,8 @@ void set_firmware_width_unlocked(void) ret = mem_pdc_call(PDC_MODEL, PDC_MODEL_CAPABILITIES, __pa(pdc_result), 0); + if (ret < 0) + return; convert_to_wide(pdc_result); if (pdc_result[0] != NARROW_FIRMWARE) parisc_narrow_firmware = 0; @@ -255,8 +257,8 @@ int __init pdc_instr(unsigned int *instr) /** * pdc_chassis_info - Return chassis information. - * @result: The return buffer. * @chassis_info: The memory buffer address. + * @led_info: The size of the memory buffer address. * @len: The size of the memory buffer address. * * An HVERSION dependent call for returning the chassis information. @@ -280,7 +282,8 @@ int __init pdc_chassis_info(struct pdc_chassis_info *chassis_info, void *led_inf /** * pdc_pat_chassis_send_log - Sends a PDC PAT CHASSIS log message. - * @retval: -1 on error, 0 on success. Other value are PDC errors + * @state: state of the machine + * @data: value for that state * * Must be correctly formatted or expect system crash */ @@ -303,7 +306,7 @@ int pdc_pat_chassis_send_log(unsigned long state, unsigned long data) /** * pdc_chassis_disp - Updates chassis code - * @retval: -1 on error, 0 on success + * @disp: value to show on display */ int pdc_chassis_disp(unsigned long disp) { @@ -318,8 +321,7 @@ int pdc_chassis_disp(unsigned long disp) } /** - * pdc_cpu_rendenzvous - Stop currently executing CPU - * @retval: -1 on error, 0 on success + * __pdc_cpu_rendezvous - Stop currently executing CPU and do not return. */ int __pdc_cpu_rendezvous(void) { @@ -347,7 +349,7 @@ void pdc_cpu_rendezvous_unlock(void) /** * pdc_pat_get_PDC_entrypoint - Get PDC entry point for current CPU - * @retval: -1 on error, 0 on success + * @pdc_entry: pointer to where the PDC entry point should be stored */ int pdc_pat_get_PDC_entrypoint(unsigned long *pdc_entry) { @@ -369,7 +371,7 @@ int pdc_pat_get_PDC_entrypoint(unsigned long *pdc_entry) } /** * pdc_chassis_warn - Fetches chassis warnings - * @retval: -1 on error, 0 on success + * @warn: The warning value to be shown */ int pdc_chassis_warn(unsigned long *warn) { @@ -521,6 +523,7 @@ int pdc_model_info(struct pdc_model *model) /** * pdc_model_sysmodel - Get the system model name. + * @os_id: The operating system ID asked for (an OS_ID_* value) * @name: A char array of at least 81 characters. * * Get system model name from PDC ROM (e.g. 9000/715 or 9000/778/B160L). @@ -549,7 +552,7 @@ int pdc_model_sysmodel(unsigned int os_id, char *name) /** * pdc_model_versions - Identify the version number of each processor. - * @cpu_id: The return buffer. + * @versions: The return buffer. * @id: The id of the processor to check. * * Returns the version number for each processor component. @@ -996,8 +999,8 @@ int pdc_pci_irt(unsigned long num_entries, unsigned long hpa, void *tbl) /** * pdc_pci_config_read - read PCI config space. - * @hpa token from PDC to indicate which PCI device - * @pci_addr configuration space address to read from + * @hpa: Token from PDC to indicate which PCI device + * @cfg_addr: Configuration space address to read from * * Read PCI Configuration space *before* linux PCI subsystem is running. */ @@ -1019,9 +1022,9 @@ unsigned int pdc_pci_config_read(void *hpa, unsigned long cfg_addr) /** * pdc_pci_config_write - read PCI config space. - * @hpa token from PDC to indicate which PCI device - * @pci_addr configuration space address to write - * @val value we want in the 32-bit register + * @hpa: Token from PDC to indicate which PCI device + * @cfg_addr: Configuration space address to write + * @val: Value we want in the 32-bit register * * Write PCI Configuration space *before* linux PCI subsystem is running. */ @@ -1389,17 +1392,25 @@ int pdc_iodc_getc(void) } int pdc_sti_call(unsigned long func, unsigned long flags, - unsigned long inptr, unsigned long outputr, - unsigned long glob_cfg) + unsigned long inptr, unsigned long outputr, + unsigned long glob_cfg, int do_call64) { - int retval; + int retval = 0; unsigned long irqflags; - spin_lock_irqsave(&pdc_lock, irqflags); - retval = real32_call(func, flags, inptr, outputr, glob_cfg); - spin_unlock_irqrestore(&pdc_lock, irqflags); + spin_lock_irqsave(&pdc_lock, irqflags); + if (IS_ENABLED(CONFIG_64BIT) && do_call64) { +#ifdef CONFIG_64BIT + retval = real64_call(func, flags, inptr, outputr, glob_cfg); +#else + WARN_ON(1); +#endif + } else { + retval = real32_call(func, flags, inptr, outputr, glob_cfg); + } + spin_unlock_irqrestore(&pdc_lock, irqflags); - return retval; + return retval; } EXPORT_SYMBOL(pdc_sti_call); @@ -1549,7 +1560,7 @@ int pdc_pat_get_irt(void *r_addr, unsigned long cell_num) /** * pdc_pat_pd_get_addr_map - Retrieve information about memory address ranges. - * @actlen: The return buffer. + * @actual_len: The return buffer. * @mem_addr: Pointer to the memory buffer. * @count: The number of bytes to read from the buffer. * @offset: The offset with respect to the beginning of the buffer. @@ -1572,7 +1583,7 @@ int pdc_pat_pd_get_addr_map(unsigned long *actual_len, void *mem_addr, } /** - * pdc_pat_pd_get_PDC_interface_revisions - Retrieve PDC interface revisions. + * pdc_pat_pd_get_pdc_revisions - Retrieve PDC interface revisions. * @legacy_rev: The legacy revision. * @pat_rev: The PAT revision. * @pdc_cap: The PDC capabilities. @@ -1627,7 +1638,7 @@ int pdc_pat_io_pci_cfg_read(unsigned long pci_addr, int pci_size, u32 *mem_addr) * pdc_pat_io_pci_cfg_write - Retrieve information about memory address ranges. * @pci_addr: PCI configuration space address for which the write request is being made. * @pci_size: Size of write in bytes. Valid values are 1, 2, and 4. - * @value: Pointer to 1, 2, or 4 byte value in low order end of argument to be + * @val: Pointer to 1, 2, or 4 byte value in low order end of argument to be * written to PCI Config space. * */ @@ -1645,7 +1656,7 @@ int pdc_pat_io_pci_cfg_write(unsigned long pci_addr, int pci_size, u32 val) } /** - * pdc_pat_mem_pdc_info - Retrieve information about page deallocation table + * pdc_pat_mem_pdt_info - Retrieve information about page deallocation table * @rinfo: memory pdt information * */ diff --git a/arch/parisc/kernel/irq.c b/arch/parisc/kernel/irq.c index b05055f3ba4b8aa406c3a0881bb65b5984ce51f7..12c4d4104ade4a6fbb9504cd5a7ad5e06083f587 100644 --- a/arch/parisc/kernel/irq.c +++ b/arch/parisc/kernel/irq.c @@ -24,9 +24,6 @@ #undef PARISC_IRQ_CR16_COUNTS -extern irqreturn_t timer_interrupt(int, void *); -extern irqreturn_t ipi_interrupt(int, void *); - #define EIEM_MASK(irq) (1UL<<(CPU_IRQ_MAX - irq)) /* Bits in EIEM correlate with cpu_irq_action[]. @@ -489,7 +486,7 @@ void do_softirq_own_stack(void) #endif /* CONFIG_IRQSTACKS */ /* ONLY called from entry.S:intr_extint() */ -void do_cpu_irq_mask(struct pt_regs *regs) +asmlinkage void do_cpu_irq_mask(struct pt_regs *regs) { struct pt_regs *old_regs; unsigned long eirr_val; diff --git a/arch/parisc/kernel/module.c b/arch/parisc/kernel/module.c index f6e38c4d390499292b0e1a71b7078ec6b5678d0f..d214bbe3c2afc19b436618f729ece46d3ea3199e 100644 --- a/arch/parisc/kernel/module.c +++ b/arch/parisc/kernel/module.c @@ -845,7 +845,7 @@ int module_finalize(const Elf_Ehdr *hdr, const char *strtab = NULL; const Elf_Shdr *s; char *secstrings; - int symindex = -1; + int symindex __maybe_unused = -1; Elf_Sym *newptr, *oldptr; Elf_Shdr *symhdr = NULL; #ifdef DEBUG diff --git a/arch/parisc/kernel/pci-dma.c b/arch/parisc/kernel/pci-dma.c index 71ed5391f29d6f00ec85168b02cce2fe4eccb097..d818ece23b4a0cdf2711230c6a084b6ec82abfd1 100644 --- a/arch/parisc/kernel/pci-dma.c +++ b/arch/parisc/kernel/pci-dma.c @@ -164,7 +164,7 @@ static inline void unmap_uncached_pte(pmd_t * pmd, unsigned long vaddr, pmd_clear(pmd); return; } - pte = pte_offset_map(pmd, vaddr); + pte = pte_offset_kernel(pmd, vaddr); vaddr &= ~PMD_MASK; end = vaddr + size; if (end > PMD_SIZE) @@ -245,7 +245,7 @@ static void unmap_uncached_pages(unsigned long vaddr, unsigned long size) PCXL_SEARCH_LOOP(idx, mask, size); \ } -unsigned long +static unsigned long pcxl_alloc_range(size_t size) { int res_idx; diff --git a/arch/parisc/kernel/pdc_chassis.c b/arch/parisc/kernel/pdc_chassis.c index da154406d368d7d2bbd0d045a931ea9637aa92c7..0a9d7008ef2a9ae04f46bc4ed639b2208044ceb3 100644 --- a/arch/parisc/kernel/pdc_chassis.c +++ b/arch/parisc/kernel/pdc_chassis.c @@ -40,7 +40,7 @@ static unsigned int pdc_chassis_enabled __read_mostly = 1; /** * pdc_chassis_setup() - Enable/disable pdc_chassis code at boot time. - * @str configuration param: 0 to disable chassis log + * @str: configuration param: 0 to disable chassis log * @return 1 */ @@ -55,7 +55,6 @@ __setup("pdcchassis=", pdc_chassis_setup); /** * pdc_chassis_checkold() - Checks for old PDC_CHASSIS compatibility - * @pdc_chassis_old: 1 if old pdc chassis style * * Currently, only E class and A180 are known to work with this. * Inspired by Christoph Plattner @@ -80,6 +79,9 @@ static void __init pdc_chassis_checkold(void) /** * pdc_chassis_panic_event() - Called by the panic handler. + * @this: unused + * @event: unused + * @ptr: unused * * As soon as a panic occurs, we should inform the PDC. */ @@ -88,7 +90,7 @@ static int pdc_chassis_panic_event(struct notifier_block *this, unsigned long event, void *ptr) { pdc_chassis_send_status(PDC_CHASSIS_DIRECT_PANIC); - return NOTIFY_DONE; + return NOTIFY_DONE; } @@ -99,7 +101,10 @@ static struct notifier_block pdc_chassis_panic_block = { /** - * parisc_reboot_event() - Called by the reboot handler. + * pdc_chassis_reboot_event() - Called by the reboot handler. + * @this: unused + * @event: unused + * @ptr: unused * * As soon as a reboot occurs, we should inform the PDC. */ @@ -108,7 +113,7 @@ static int pdc_chassis_reboot_event(struct notifier_block *this, unsigned long event, void *ptr) { pdc_chassis_send_status(PDC_CHASSIS_DIRECT_SHUTDOWN); - return NOTIFY_DONE; + return NOTIFY_DONE; } @@ -148,7 +153,7 @@ void __init parisc_pdc_chassis_init(void) /** * pdc_chassis_send_status() - Sends a predefined message to the chassis, * and changes the front panel LEDs according to the new system state - * @retval: PDC call return value. + * @message: Type of message, one of PDC_CHASSIS_DIRECT_* values. * * Only machines with 64 bits PDC PAT and those reported in * pdc_chassis_checkold() are supported atm. diff --git a/arch/parisc/kernel/pdt.c b/arch/parisc/kernel/pdt.c index 80943a00e2459425c9988562b3d684960317917f..0d24735bd9182af0e6149b5ef1faa85d705e4ec2 100644 --- a/arch/parisc/kernel/pdt.c +++ b/arch/parisc/kernel/pdt.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -23,6 +24,7 @@ #include #include #include +#include enum pdt_access_type { PDT_NONE, diff --git a/arch/parisc/kernel/perf.c b/arch/parisc/kernel/perf.c index d46b6709ec56c415ec9d6965ff9ae1de52b0e3f9..90b04d8af21208e6206242b402d5caf20ba415e5 100644 --- a/arch/parisc/kernel/perf.c +++ b/arch/parisc/kernel/perf.c @@ -288,7 +288,7 @@ static ssize_t perf_read(struct file *file, char __user *buf, size_t cnt, loff_t static ssize_t perf_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { - size_t image_size; + size_t image_size __maybe_unused; uint32_t image_type; uint32_t interface_type; uint32_t test; diff --git a/arch/parisc/kernel/process.c b/arch/parisc/kernel/process.c index 24411ab79c307d4ab78f33303a7b1d8afb7d1c1d..abdbf038d6435d48f64e723f6dbcfcc871f0e1ce 100644 --- a/arch/parisc/kernel/process.c +++ b/arch/parisc/kernel/process.c @@ -171,8 +171,8 @@ void __noreturn arch_cpu_idle_dead(void) local_irq_disable(); - /* Tell __cpu_die() that this CPU is now safe to dispose of. */ - (void)cpu_report_death(); + /* Tell the core that this CPU is now safe to dispose of. */ + cpuhp_ap_report_dead(); /* Ensure that the cache lines are written out. */ flush_cache_all_local(); diff --git a/arch/parisc/kernel/processor.c b/arch/parisc/kernel/processor.c index ba07e760d3c762f1251c3d23b865ef9875723ea1..00b0df97afb1455287103c8590a0e987875ef17b 100644 --- a/arch/parisc/kernel/processor.c +++ b/arch/parisc/kernel/processor.c @@ -58,7 +58,7 @@ DEFINE_PER_CPU(struct cpuinfo_parisc, cpu_data); */ /** - * init_cpu_profiler - enable/setup per cpu profiling hooks. + * init_percpu_prof - enable/setup per cpu profiling hooks. * @cpunum: The processor instance. * * FIXME: doesn't do much yet... diff --git a/arch/parisc/kernel/setup.c b/arch/parisc/kernel/setup.c index 0797db617962b629eb5a5cff00bfccfc1d68c727..573f8303e2b05c684e9343cc1020bb77195d7e06 100644 --- a/arch/parisc/kernel/setup.c +++ b/arch/parisc/kernel/setup.c @@ -45,7 +45,7 @@ struct proc_dir_entry * proc_runway_root __read_mostly = NULL; struct proc_dir_entry * proc_gsc_root __read_mostly = NULL; struct proc_dir_entry * proc_mckinley_root __read_mostly = NULL; -void __init setup_cmdline(char **cmdline_p) +static void __init setup_cmdline(char **cmdline_p) { extern unsigned int boot_args[]; char *p; @@ -86,7 +86,7 @@ void __init setup_cmdline(char **cmdline_p) } #ifdef CONFIG_PA11 -void __init dma_ops_init(void) +static void __init dma_ops_init(void) { switch (boot_cpu_data.cpu_type) { case pcx: @@ -106,8 +106,6 @@ void __init dma_ops_init(void) } #endif -extern void collect_boot_cpu_data(void); - void __init setup_arch(char **cmdline_p) { #ifdef CONFIG_64BIT @@ -167,10 +165,7 @@ void __init setup_arch(char **cmdline_p) /* * Display CPU info for all CPUs. - * for parisc this is in processor.c */ -extern int show_cpuinfo (struct seq_file *m, void *v); - static void * c_start (struct seq_file *m, loff_t *pos) { @@ -295,16 +290,6 @@ static int __init parisc_init_resources(void) return 0; } -extern void gsc_init(void); -extern void processor_init(void); -extern void ccio_init(void); -extern void hppb_init(void); -extern void dino_init(void); -extern void iosapic_init(void); -extern void lba_init(void); -extern void sba_init(void); -extern void eisa_init(void); - static int __init parisc_init(void) { u32 osid = (OS_ID_LINUX << 16); @@ -370,7 +355,7 @@ static int __init parisc_init(void) gsc_init(); #endif #ifdef CONFIG_EISA - eisa_init(); + parisc_eisa_init(); #endif #if defined(CONFIG_HPPB) @@ -391,8 +376,6 @@ arch_initcall(parisc_init); void __init start_parisc(void) { - extern void early_trap_init(void); - int ret, cpunum; struct pdc_coproc_cfg coproc_cfg; diff --git a/arch/parisc/kernel/signal.c b/arch/parisc/kernel/signal.c index 8bc0ddaa62198195fca039774c6590f992cd908c..f886ff0c75df2d06e0df6f7ee25099b1b5413897 100644 --- a/arch/parisc/kernel/signal.c +++ b/arch/parisc/kernel/signal.c @@ -73,7 +73,7 @@ restore_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs) return err; } -void +asmlinkage void sys_rt_sigreturn(struct pt_regs *regs, int in_syscall) { struct rt_sigframe __user *frame; @@ -176,7 +176,7 @@ get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size) } static long -setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, int in_syscall) +setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, long in_syscall) { unsigned long flags = 0; @@ -211,7 +211,7 @@ setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, int in_sysc static long setup_rt_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs, - int in_syscall) + long in_syscall) { struct rt_sigframe __user *frame; unsigned long rp, usp; @@ -380,7 +380,7 @@ setup_rt_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs, */ static void -handle_signal(struct ksignal *ksig, struct pt_regs *regs, int in_syscall) +handle_signal(struct ksignal *ksig, struct pt_regs *regs, long in_syscall) { int ret; sigset_t *oldset = sigmask_to_save(); @@ -578,7 +578,7 @@ static void do_signal(struct pt_regs *regs, long in_syscall) restore_saved_sigmask(); } -void do_notify_resume(struct pt_regs *regs, long in_syscall) +asmlinkage void do_notify_resume(struct pt_regs *regs, long in_syscall) { if (test_thread_flag(TIF_SIGPENDING) || test_thread_flag(TIF_NOTIFY_SIGNAL)) diff --git a/arch/parisc/kernel/smp.c b/arch/parisc/kernel/smp.c index b7fc859fa87dbae3270b4dd692e28357d8879595..4098f9a0964b9b8741c533acce88cb018b844c6a 100644 --- a/arch/parisc/kernel/smp.c +++ b/arch/parisc/kernel/smp.c @@ -271,9 +271,6 @@ void arch_send_call_function_single_ipi(int cpu) static void smp_cpu_init(int cpunum) { - extern void init_IRQ(void); /* arch/parisc/kernel/irq.c */ - extern void start_cpu_itimer(void); /* arch/parisc/kernel/time.c */ - /* Set modes and Enable floating point coprocessor */ init_per_cpu(cpunum); @@ -500,11 +497,10 @@ int __cpu_disable(void) void __cpu_die(unsigned int cpu) { pdc_cpu_rendezvous_lock(); +} - if (!cpu_wait_death(cpu, 5)) { - pr_crit("CPU%u: cpu didn't die\n", cpu); - return; - } +void arch_cpuhp_cleanup_dead_cpu(unsigned int cpu) +{ pr_info("CPU%u: is shutting down\n", cpu); /* set task's state to interruptible sleep */ diff --git a/arch/parisc/kernel/sys_parisc.c b/arch/parisc/kernel/sys_parisc.c index 39acccabf2eded8a148fe9fbd95332c614515f66..9915062d5243c38776dcb2296faa9165e32d55bd 100644 --- a/arch/parisc/kernel/sys_parisc.c +++ b/arch/parisc/kernel/sys_parisc.c @@ -24,6 +24,7 @@ #include #include #include +#include /* * Construct an artificial page offset for the mapping based on the physical @@ -339,7 +340,7 @@ asmlinkage long parisc_fallocate(int fd, int mode, u32 offhi, u32 offlo, ((u64)lenhi << 32) | lenlo); } -long parisc_personality(unsigned long personality) +asmlinkage long parisc_personality(unsigned long personality) { long err; diff --git a/arch/parisc/kernel/syscalls/syscall.tbl b/arch/parisc/kernel/syscalls/syscall.tbl index 0e42fceb2d5e2d574b6ab4e69f69bf891ab035c0..a0a9145b6dd4fa0b82a405417299530aa748857c 100644 --- a/arch/parisc/kernel/syscalls/syscall.tbl +++ b/arch/parisc/kernel/syscalls/syscall.tbl @@ -400,6 +400,7 @@ 353 common pkey_free sys_pkey_free 354 common rseq sys_rseq 355 common kexec_file_load sys_kexec_file_load sys_kexec_file_load +356 common cacheflush sys_cacheflush # up to 402 is unassigned and reserved for arch specific syscalls 403 32 clock_gettime64 sys_clock_gettime sys_clock_gettime 404 32 clock_settime64 sys_clock_settime sys_clock_settime @@ -448,3 +449,4 @@ 448 common process_mrelease sys_process_mrelease 449 common futex_waitv sys_futex_waitv 450 common set_mempolicy_home_node sys_set_mempolicy_home_node +451 common cachestat sys_cachestat diff --git a/arch/parisc/kernel/traps.c b/arch/parisc/kernel/traps.c index 304eebd1c83e7d802fd9b1d726d479fbaeefa175..3b97944c7291d4067951e0bdafcd175dc37ef123 100644 --- a/arch/parisc/kernel/traps.c +++ b/arch/parisc/kernel/traps.c @@ -338,7 +338,7 @@ static void default_trap(int code, struct pt_regs *regs) void (*cpu_lpmc) (int code, struct pt_regs *regs) __read_mostly = default_trap; -void transfer_pim_to_trap_frame(struct pt_regs *regs) +static void transfer_pim_to_trap_frame(struct pt_regs *regs) { register int i; extern unsigned int hpmc_pim_data[]; @@ -800,14 +800,13 @@ void notrace handle_interruption(int code, struct pt_regs *regs) } -void __init initialize_ivt(const void *iva) +static void __init initialize_ivt(const void *iva) { extern const u32 os_hpmc[]; int i; u32 check = 0; u32 *ivap; - u32 *hpmcp; u32 instr; if (strcmp((const char *)iva, "cows can fly")) @@ -840,8 +839,6 @@ void __init initialize_ivt(const void *iva) /* Setup IVA and compute checksum for HPMC handler */ ivap[6] = (u32)__pa(os_hpmc); - hpmcp = (u32 *)os_hpmc; - for (i=0; i<8; i++) check += ivap[i]; diff --git a/arch/parisc/kernel/unaligned.c b/arch/parisc/kernel/unaligned.c index e8a4d77cff53a77ee20d0e0319fa360d208cdd6d..033b9e50b44aebc4ccaff074729890d9238247d6 100644 --- a/arch/parisc/kernel/unaligned.c +++ b/arch/parisc/kernel/unaligned.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include diff --git a/arch/parisc/kernel/unwind.c b/arch/parisc/kernel/unwind.c index 42acc3b520174faf47cb27e22a6719201e3465a2..27ae40a443b80c5fa575e8579bca7f08ef6d36ab 100644 --- a/arch/parisc/kernel/unwind.c +++ b/arch/parisc/kernel/unwind.c @@ -24,12 +24,13 @@ #include #include #include +#include /* #define DEBUG 1 */ #ifdef DEBUG #define dbg(x...) pr_debug(x) #else -#define dbg(x...) +#define dbg(x...) do { } while (0) #endif #define KERNEL_START (KERNEL_BINARY_TEXT_START) @@ -179,7 +180,7 @@ void unwind_table_remove(struct unwind_table *table) /* Called from setup_arch to import the kernel unwind info */ int __init unwind_init(void) { - long start, stop; + long start __maybe_unused, stop __maybe_unused; register unsigned long gp __asm__ ("r27"); start = (long)&__start___unwind[0]; @@ -220,7 +221,6 @@ static int unwind_special(struct unwind_frame_info *info, unsigned long pc, int * Note: We could use dereference_kernel_function_descriptor() * instead but we want to keep it simple here. */ - extern void * const handle_interruption; extern void * const ret_from_kernel_thread; extern void * const syscall_exit; extern void * const intr_return; @@ -228,8 +228,10 @@ static int unwind_special(struct unwind_frame_info *info, unsigned long pc, int #ifdef CONFIG_IRQSTACKS extern void * const _call_on_stack; #endif /* CONFIG_IRQSTACKS */ + void *ptr; - if (pc_is_kernel_fn(pc, handle_interruption)) { + ptr = dereference_kernel_function_descriptor(&handle_interruption); + if (pc_is_kernel_fn(pc, ptr)) { struct pt_regs *regs = (struct pt_regs *)(info->sp - frame_size - PT_SZ_ALGN); dbg("Unwinding through handle_interruption()\n"); info->prev_sp = regs->gr[30]; diff --git a/arch/parisc/math-emu/Makefile b/arch/parisc/math-emu/Makefile index 3747a0cbd3b8fc1b150e67fb067c3994149119e1..7b64740e150a520c8806d0c9c0302fc856ae59a6 100644 --- a/arch/parisc/math-emu/Makefile +++ b/arch/parisc/math-emu/Makefile @@ -6,7 +6,8 @@ # See arch/parisc/math-emu/README ccflags-y := -Wno-parentheses -Wno-implicit-function-declaration \ -Wno-uninitialized -Wno-strict-prototypes -Wno-return-type \ - -Wno-implicit-int + -Wno-implicit-int -Wno-missing-prototypes -Wno-missing-declarations \ + -Wno-old-style-definition -Wno-unused-but-set-variable obj-y := frnd.o driver.o decode_exc.o fpudispatch.o denormal.o \ dfmpy.o sfmpy.o sfsqrt.o dfsqrt.o dfadd.o fmpyfadd.o \ diff --git a/arch/parisc/mm/fault.c b/arch/parisc/mm/fault.c index 6941fdbf251738c8158e4da736d21033379a4766..a4c7c7630f48b1745a58a3e3cc8928faa7ef4120 100644 --- a/arch/parisc/mm/fault.c +++ b/arch/parisc/mm/fault.c @@ -288,15 +288,19 @@ void do_page_fault(struct pt_regs *regs, unsigned long code, retry: mmap_read_lock(mm); vma = find_vma_prev(mm, address, &prev_vma); - if (!vma || address < vma->vm_start) - goto check_expansion; + if (!vma || address < vma->vm_start) { + if (!prev_vma || !(prev_vma->vm_flags & VM_GROWSUP)) + goto bad_area; + vma = expand_stack(mm, address); + if (!vma) + goto bad_area_nosemaphore; + } + /* * Ok, we have a good vm_area for this memory access. We still need to * check the access permissions. */ -good_area: - if ((vma->vm_flags & acc_type) != acc_type) goto bad_area; @@ -347,17 +351,13 @@ void do_page_fault(struct pt_regs *regs, unsigned long code, mmap_read_unlock(mm); return; -check_expansion: - vma = prev_vma; - if (vma && (expand_stack(vma, address) == 0)) - goto good_area; - /* * Something tried to access memory that isn't in our memory map.. */ bad_area: mmap_read_unlock(mm); +bad_area_nosemaphore: if (user_mode(regs)) { int signo, si_code; @@ -449,7 +449,7 @@ handle_nadtlb_fault(struct pt_regs *regs) { unsigned long insn = regs->iir; int breg, treg, xreg, val = 0; - struct vm_area_struct *vma, *prev_vma; + struct vm_area_struct *vma; struct task_struct *tsk; struct mm_struct *mm; unsigned long address; @@ -485,7 +485,7 @@ handle_nadtlb_fault(struct pt_regs *regs) /* Search for VMA */ address = regs->ior; mmap_read_lock(mm); - vma = find_vma_prev(mm, address, &prev_vma); + vma = vma_lookup(mm, address); mmap_read_unlock(mm); /* @@ -494,7 +494,6 @@ handle_nadtlb_fault(struct pt_regs *regs) */ acc_type = (insn & 0x40) ? VM_WRITE : VM_READ; if (vma - && address >= vma->vm_start && (vma->vm_flags & acc_type) == acc_type) val = 1; } diff --git a/arch/parisc/mm/hugetlbpage.c b/arch/parisc/mm/hugetlbpage.c index d1d3990b83f65593494d955d8b97d8dbab9c3106..a8a1a7c1e16eb4ef1b751144377a943be3eecaa9 100644 --- a/arch/parisc/mm/hugetlbpage.c +++ b/arch/parisc/mm/hugetlbpage.c @@ -66,7 +66,7 @@ pte_t *huge_pte_alloc(struct mm_struct *mm, struct vm_area_struct *vma, if (pud) { pmd = pmd_alloc(mm, pud, addr); if (pmd) - pte = pte_alloc_map(mm, pmd, addr); + pte = pte_alloc_huge(mm, pmd, addr); } return pte; } @@ -90,7 +90,7 @@ pte_t *huge_pte_offset(struct mm_struct *mm, if (!pud_none(*pud)) { pmd = pmd_offset(pud, addr); if (!pmd_none(*pmd)) - pte = pte_offset_map(pmd, addr); + pte = pte_offset_huge(pmd, addr); } } } diff --git a/arch/parisc/mm/init.c b/arch/parisc/mm/init.c index b0c43f3b0a5f89a183188e85378b8009ab526f23..406c52fe23d549a7c792813020f2fbc0771c989d 100644 --- a/arch/parisc/mm/init.c +++ b/arch/parisc/mm/init.c @@ -626,12 +626,10 @@ static void __init pagetable_init(void) for (range = 0; range < npmem_ranges; range++) { unsigned long start_paddr; - unsigned long end_paddr; unsigned long size; start_paddr = pmem_ranges[range].start_pfn << PAGE_SHIFT; size = pmem_ranges[range].pages << PAGE_SHIFT; - end_paddr = start_paddr + size; map_pages((unsigned long)__va(start_paddr), start_paddr, size, PAGE_KERNEL, 0); diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index bff5820b7cda14714f6b76da3bac2de92c8f740f..0b1172cbeccb302191362b9f288c6f5ed01d36a2 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -90,8 +90,7 @@ config NMI_IPI config PPC_WATCHDOG bool - depends on HARDLOCKUP_DETECTOR - depends on HAVE_HARDLOCKUP_DETECTOR_ARCH + depends on HARDLOCKUP_DETECTOR_ARCH default y help This is a placeholder when the powerpc hardlockup detector @@ -211,7 +210,7 @@ config PPC select HAVE_ARCH_KASAN if PPC_RADIX_MMU select HAVE_ARCH_KASAN if PPC_BOOK3E_64 select HAVE_ARCH_KASAN_VMALLOC if HAVE_ARCH_KASAN - select HAVE_ARCH_KCSAN if PPC_BOOK3S_64 + select HAVE_ARCH_KCSAN select HAVE_ARCH_KFENCE if ARCH_SUPPORTS_DEBUG_PAGEALLOC select HAVE_ARCH_RANDOMIZE_KSTACK_OFFSET select HAVE_ARCH_WITHIN_STACK_FRAMES @@ -236,11 +235,11 @@ config PPC select HAVE_FUNCTION_DESCRIPTORS if PPC64_ELF_ABI_V1 select HAVE_FUNCTION_ERROR_INJECTION select HAVE_FUNCTION_GRAPH_TRACER - select HAVE_FUNCTION_TRACER + select HAVE_FUNCTION_TRACER if PPC64 || (PPC32 && CC_IS_GCC) select HAVE_GCC_PLUGINS if GCC_VERSION >= 50200 # plugin support on gcc <= 5.1 is buggy on PPC select HAVE_GENERIC_VDSO select HAVE_HARDLOCKUP_DETECTOR_ARCH if PPC_BOOK3S_64 && SMP - select HAVE_HARDLOCKUP_DETECTOR_PERF if PERF_EVENTS && HAVE_PERF_EVENTS_NMI && !HAVE_HARDLOCKUP_DETECTOR_ARCH + select HAVE_HARDLOCKUP_DETECTOR_PERF if PERF_EVENTS && HAVE_PERF_EVENTS_NMI select HAVE_HW_BREAKPOINT if PERF_EVENTS && (PPC_BOOK3S || PPC_8xx) select HAVE_IOREMAP_PROT select HAVE_IRQ_TIME_ACCOUNTING @@ -278,6 +277,7 @@ config PPC select IRQ_DOMAIN select IRQ_FORCED_THREADING select KASAN_VMALLOC if KASAN && MODULES + select LOCK_MM_AND_FIND_VMA select MMU_GATHER_PAGE_SIZE select MMU_GATHER_RCU_TABLE_FREE select MMU_GATHER_MERGE_VMAS @@ -547,8 +547,9 @@ config LD_HEAD_STUB_CATCH If unsure, say "N". config MPROFILE_KERNEL - depends on PPC64 && CPU_LITTLE_ENDIAN && FUNCTION_TRACER - def_bool $(success,$(srctree)/arch/powerpc/tools/gcc-check-mprofile-kernel.sh $(CC) -I$(srctree)/include -D__KERNEL__) + depends on PPC64_ELF_ABI_V2 && FUNCTION_TRACER + def_bool $(success,$(srctree)/arch/powerpc/tools/gcc-check-mprofile-kernel.sh $(CC) -mlittle-endian) if CPU_LITTLE_ENDIAN + def_bool $(success,$(srctree)/arch/powerpc/tools/gcc-check-mprofile-kernel.sh $(CC) -mbig-endian) if CPU_BIG_ENDIAN config HOTPLUG_CPU bool "Support for enabling/disabling CPUs" @@ -624,10 +625,12 @@ config ARCH_HAS_KEXEC_PURGATORY def_bool KEXEC_FILE config PPC64_BIG_ENDIAN_ELF_ABI_V2 - bool "Build big-endian kernel using ELF ABI V2 (EXPERIMENTAL)" + # Option is available to BFD, but LLD does not support ELFv1 so this is + # always true there. + prompt "Build big-endian kernel using ELF ABI V2" if LD_IS_BFD && EXPERT + def_bool y depends on PPC64 && CPU_BIG_ENDIAN depends on CC_HAS_ELFV2 - depends on LD_VERSION >= 22400 || LLD_VERSION >= 150000 help This builds the kernel image using the "Power Architecture 64-Bit ELF V2 ABI Specification", which has a reduced stack overhead and faster @@ -638,8 +641,6 @@ config PPC64_BIG_ENDIAN_ELF_ABI_V2 it is less well tested by kernel and toolchain. However some distros build userspace this way, and it can produce a functioning kernel. - This requires GCC and binutils 2.24 or newer. - config RELOCATABLE bool "Build a relocatable kernel" depends on PPC64 || (FLATMEM && (44x || PPC_85xx)) diff --git a/arch/powerpc/Kconfig.debug b/arch/powerpc/Kconfig.debug index 6aaf8dc60610d1ce9be9be4680672c8a86096781..2a54fadbeaf513153a220b59ad75caee652cb97e 100644 --- a/arch/powerpc/Kconfig.debug +++ b/arch/powerpc/Kconfig.debug @@ -240,7 +240,7 @@ config PPC_EARLY_DEBUG_40x config PPC_EARLY_DEBUG_CPM bool "Early serial debugging for Freescale CPM-based serial ports" - depends on SERIAL_CPM + depends on SERIAL_CPM=y help Select this to enable early debugging for Freescale chips using a CPM-based serial port. This assumes that the bootwrapper diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile index dca73f673d7046eb831f94763fa8980321842e26..dac7ca153886b066c0c3ba671a7bc913c9b70c02 100644 --- a/arch/powerpc/Makefile +++ b/arch/powerpc/Makefile @@ -42,18 +42,13 @@ machine-$(CONFIG_PPC64) += 64 machine-$(CONFIG_CPU_LITTLE_ENDIAN) += le UTS_MACHINE := $(subst $(space),,$(machine-y)) -# XXX This needs to be before we override LD below -ifdef CONFIG_PPC32 -KBUILD_LDFLAGS_MODULE += arch/powerpc/lib/crtsavres.o -else -ifeq ($(call ld-ifversion, -ge, 22500, y),y) +ifeq ($(CONFIG_PPC64)$(CONFIG_LD_IS_BFD),yy) # Have the linker provide sfpr if possible. # There is a corresponding test in arch/powerpc/lib/Makefile KBUILD_LDFLAGS_MODULE += --save-restore-funcs else KBUILD_LDFLAGS_MODULE += arch/powerpc/lib/crtsavres.o endif -endif ifdef CONFIG_CPU_LITTLE_ENDIAN KBUILD_CFLAGS += -mlittle-endian @@ -166,7 +161,7 @@ asinstr := $(call as-instr,lis 9$(comma)foo@high,-DHAVE_AS_ATHIGH=1) KBUILD_CPPFLAGS += -I $(srctree)/arch/$(ARCH) $(asinstr) KBUILD_AFLAGS += $(AFLAGS-y) KBUILD_CFLAGS += $(call cc-option,-msoft-float) -KBUILD_CFLAGS += -pipe $(CFLAGS-y) +KBUILD_CFLAGS += $(CFLAGS-y) CPP = $(CC) -E $(KBUILD_CFLAGS) CHECKFLAGS += -m$(BITS) -D__powerpc__ -D__powerpc$(BITS)__ @@ -398,14 +393,12 @@ endif endif PHONY += checkbin -# Check toolchain versions: -# - gcc-4.6 is the minimum kernel-wide version so nothing required. checkbin: - @if test "x${CONFIG_LD_IS_LLD}" != "xy" -a \ - "x$(call ld-ifversion, -le, 22400, y)" = "xy" ; then \ - echo -n '*** binutils 2.24 miscompiles weak symbols ' ; \ - echo 'in some circumstances.' ; \ - echo '*** binutils 2.23 do not define the TOC symbol ' ; \ - echo -n '*** Please use a different binutils version.' ; \ + @if test "x${CONFIG_FTRACE_MCOUNT_USE_RECORDMCOUNT}" = "xy" -a \ + "x${CONFIG_LD_IS_BFD}" = "xy" -a \ + "${CONFIG_LD_VERSION}" = "23700" ; then \ + echo -n '*** binutils 2.37 drops unused section symbols, which recordmcount ' ; \ + echo 'is unable to handle.' ; \ + echo '*** Please use a different binutils version.' ; \ false ; \ fi diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile index 771b79423bbc2b4ea4ee4d5a5fa3c07b0a14d53c..968aee2025b8198976e740b74445818bc44a95e0 100644 --- a/arch/powerpc/boot/Makefile +++ b/arch/powerpc/boot/Makefile @@ -32,46 +32,58 @@ else BOOTAR := $(AR) endif -BOOTCFLAGS := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \ - -fno-strict-aliasing -O2 -msoft-float -mno-altivec -mno-vsx \ - $(call cc-option,-mno-spe) $(call cc-option,-mspe=no) \ - -pipe -fomit-frame-pointer -fno-builtin -fPIC -nostdinc \ - $(LINUXINCLUDE) - ifdef CONFIG_PPC64_BOOT_WRAPPER -BOOTCFLAGS += -m64 +BOOTTARGETFLAGS += -m64 +BOOTTARGETFLAGS += -mabi=elfv2 ifdef CONFIG_PPC64_ELF_ABI_V2 -BOOTCFLAGS += $(call cc-option,-mabi=elfv2) +BOOTTARGETFLAGS += $(call cc-option,-mabi=elfv2) endif else -BOOTCFLAGS += -m32 +BOOTTARGETFLAGS := -m32 endif ifdef CONFIG_TARGET_CPU_BOOL -BOOTCFLAGS += -mcpu=$(CONFIG_TARGET_CPU) +BOOTTARGETFLAGS += -mcpu=$(CONFIG_TARGET_CPU) else ifdef CONFIG_PPC64_BOOT_WRAPPER ifdef CONFIG_CPU_LITTLE_ENDIAN -BOOTCFLAGS += -mcpu=powerpc64le +BOOTTARGETFLAGS += -mcpu=powerpc64le else -BOOTCFLAGS += -mcpu=powerpc64 +BOOTTARGETFLAGS += -mcpu=powerpc64 endif endif -BOOTCFLAGS += -isystem $(shell $(BOOTCC) -print-file-name=include) +$(obj)/4xx.o: BOOTTARGETFLAGS += -mcpu=405 +$(obj)/ebony.o: BOOTTARGETFLAGS += -mcpu=440 +$(obj)/cuboot-hotfoot.o: BOOTTARGETFLAGS += -mcpu=405 +$(obj)/cuboot-taishan.o: BOOTTARGETFLAGS += -mcpu=440 +$(obj)/cuboot-katmai.o: BOOTTARGETFLAGS += -mcpu=440 +$(obj)/cuboot-acadia.o: BOOTTARGETFLAGS += -mcpu=405 +$(obj)/treeboot-iss4xx.o: BOOTTARGETFLAGS += -mcpu=405 +$(obj)/treeboot-currituck.o: BOOTTARGETFLAGS += -mcpu=405 +$(obj)/treeboot-akebono.o: BOOTTARGETFLAGS += -mcpu=405 ifdef CONFIG_CPU_BIG_ENDIAN -BOOTCFLAGS += -mbig-endian +BOOTTARGETFLAGS += -mbig-endian else -BOOTCFLAGS += -mlittle-endian +BOOTTARGETFLAGS += -mlittle-endian endif -BOOTAFLAGS := -D__ASSEMBLY__ $(BOOTCFLAGS) -nostdinc - -BOOTARFLAGS := -crD +BOOTCPPFLAGS := -nostdinc $(LINUXINCLUDE) +BOOTCPPFLAGS += -isystem $(shell $(BOOTCC) -print-file-name=include) -BOOTCFLAGS += $(call cc-option,-mno-prefixed) \ +BOOTCFLAGS := $(BOOTTARGETFLAGS) \ + -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \ + -fno-strict-aliasing -O2 \ + -msoft-float -mno-altivec -mno-vsx \ + $(call cc-option,-mno-prefixed) \ $(call cc-option,-mno-pcrel) \ - $(call cc-option,-mno-mma) + $(call cc-option,-mno-mma) \ + $(call cc-option,-mno-spe) $(call cc-option,-mspe=no) \ + -fomit-frame-pointer -fno-builtin -fPIC + +BOOTAFLAGS := $(BOOTTARGETFLAGS) -D__ASSEMBLY__ + +BOOTARFLAGS := -crD ifdef CONFIG_CC_IS_CLANG BOOTCFLAGS += $(CLANG_FLAGS) @@ -91,16 +103,6 @@ BOOTCFLAGS += -I$(objtree)/$(obj) -I$(srctree)/$(obj) DTC_FLAGS ?= -p 1024 -$(obj)/4xx.o: BOOTCFLAGS += -mcpu=405 -$(obj)/ebony.o: BOOTCFLAGS += -mcpu=440 -$(obj)/cuboot-hotfoot.o: BOOTCFLAGS += -mcpu=405 -$(obj)/cuboot-taishan.o: BOOTCFLAGS += -mcpu=440 -$(obj)/cuboot-katmai.o: BOOTCFLAGS += -mcpu=440 -$(obj)/cuboot-acadia.o: BOOTCFLAGS += -mcpu=405 -$(obj)/treeboot-iss4xx.o: BOOTCFLAGS += -mcpu=405 -$(obj)/treeboot-currituck.o: BOOTCFLAGS += -mcpu=405 -$(obj)/treeboot-akebono.o: BOOTCFLAGS += -mcpu=405 - # The pre-boot decompressors pull in a lot of kernel headers and other source # files. This creates a bit of a dependency headache since we need to copy # these files into the build dir, fix up any includes and ensure that dependent @@ -224,10 +226,10 @@ clean-files := $(zlib-) $(zlibheader-) $(zliblinuxheader-) \ empty.c zImage.coff.lds zImage.ps3.lds zImage.lds quiet_cmd_bootcc = BOOTCC $@ - cmd_bootcc = $(BOOTCC) -Wp,-MD,$(depfile) $(BOOTCFLAGS) -c -o $@ $< + cmd_bootcc = $(BOOTCC) -Wp,-MD,$(depfile) $(BOOTCPPFLAGS) $(BOOTCFLAGS) -c -o $@ $< quiet_cmd_bootas = BOOTAS $@ - cmd_bootas = $(BOOTCC) -Wp,-MD,$(depfile) $(BOOTAFLAGS) -c -o $@ $< + cmd_bootas = $(BOOTCC) -Wp,-MD,$(depfile) $(BOOTCPPFLAGS) $(BOOTAFLAGS) -c -o $@ $< quiet_cmd_bootar = BOOTAR $@ cmd_bootar = $(BOOTAR) $(BOOTARFLAGS) $@.$$$$ $(real-prereqs); mv $@.$$$$ $@ @@ -340,11 +342,6 @@ image-$(CONFIG_MPC834x_ITX) += cuImage.mpc8349emitx \ image-$(CONFIG_ASP834x) += dtbImage.asp834x-redboot # Board ports in arch/powerpc/platform/85xx/Kconfig -image-$(CONFIG_MPC8540_ADS) += cuImage.mpc8540ads -image-$(CONFIG_MPC8560_ADS) += cuImage.mpc8560ads -image-$(CONFIG_MPC85xx_CDS) += cuImage.mpc8541cds \ - cuImage.mpc8548cds_32b \ - cuImage.mpc8555cds image-$(CONFIG_MPC85xx_MDS) += cuImage.mpc8568mds image-$(CONFIG_MPC85xx_DS) += cuImage.mpc8544ds \ cuImage.mpc8572ds diff --git a/arch/powerpc/boot/dts/fsl/mpc8540ads.dts b/arch/powerpc/boot/dts/fsl/mpc8540ads.dts deleted file mode 100644 index e03ae130162baa407e03a0cda01311842301903d..0000000000000000000000000000000000000000 --- a/arch/powerpc/boot/dts/fsl/mpc8540ads.dts +++ /dev/null @@ -1,355 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * MPC8540 ADS Device Tree Source - * - * Copyright 2006, 2008 Freescale Semiconductor Inc. - */ - -/dts-v1/; - -/include/ "e500v1_power_isa.dtsi" - -/ { - model = "MPC8540ADS"; - compatible = "MPC8540ADS", "MPC85xxADS"; - #address-cells = <1>; - #size-cells = <1>; - - aliases { - ethernet0 = &enet0; - ethernet1 = &enet1; - ethernet2 = &enet2; - serial0 = &serial0; - serial1 = &serial1; - pci0 = &pci0; - }; - - cpus { - #address-cells = <1>; - #size-cells = <0>; - - PowerPC,8540@0 { - device_type = "cpu"; - reg = <0x0>; - d-cache-line-size = <32>; // 32 bytes - i-cache-line-size = <32>; // 32 bytes - d-cache-size = <0x8000>; // L1, 32K - i-cache-size = <0x8000>; // L1, 32K - timebase-frequency = <0>; // 33 MHz, from uboot - bus-frequency = <0>; // 166 MHz - clock-frequency = <0>; // 825 MHz, from uboot - next-level-cache = <&L2>; - }; - }; - - memory { - device_type = "memory"; - reg = <0x0 0x8000000>; // 128M at 0x0 - }; - - soc8540@e0000000 { - #address-cells = <1>; - #size-cells = <1>; - device_type = "soc"; - compatible = "simple-bus"; - ranges = <0x0 0xe0000000 0x100000>; - bus-frequency = <0>; - - ecm-law@0 { - compatible = "fsl,ecm-law"; - reg = <0x0 0x1000>; - fsl,num-laws = <8>; - }; - - ecm@1000 { - compatible = "fsl,mpc8540-ecm", "fsl,ecm"; - reg = <0x1000 0x1000>; - interrupts = <17 2>; - interrupt-parent = <&mpic>; - }; - - memory-controller@2000 { - compatible = "fsl,mpc8540-memory-controller"; - reg = <0x2000 0x1000>; - interrupt-parent = <&mpic>; - interrupts = <18 2>; - }; - - L2: l2-cache-controller@20000 { - compatible = "fsl,mpc8540-l2-cache-controller"; - reg = <0x20000 0x1000>; - cache-line-size = <32>; // 32 bytes - cache-size = <0x40000>; // L2, 256K - interrupt-parent = <&mpic>; - interrupts = <16 2>; - }; - - i2c@3000 { - #address-cells = <1>; - #size-cells = <0>; - cell-index = <0>; - compatible = "fsl-i2c"; - reg = <0x3000 0x100>; - interrupts = <43 2>; - interrupt-parent = <&mpic>; - dfsrr; - }; - - dma@21300 { - #address-cells = <1>; - #size-cells = <1>; - compatible = "fsl,mpc8540-dma", "fsl,eloplus-dma"; - reg = <0x21300 0x4>; - ranges = <0x0 0x21100 0x200>; - cell-index = <0>; - dma-channel@0 { - compatible = "fsl,mpc8540-dma-channel", - "fsl,eloplus-dma-channel"; - reg = <0x0 0x80>; - cell-index = <0>; - interrupt-parent = <&mpic>; - interrupts = <20 2>; - }; - dma-channel@80 { - compatible = "fsl,mpc8540-dma-channel", - "fsl,eloplus-dma-channel"; - reg = <0x80 0x80>; - cell-index = <1>; - interrupt-parent = <&mpic>; - interrupts = <21 2>; - }; - dma-channel@100 { - compatible = "fsl,mpc8540-dma-channel", - "fsl,eloplus-dma-channel"; - reg = <0x100 0x80>; - cell-index = <2>; - interrupt-parent = <&mpic>; - interrupts = <22 2>; - }; - dma-channel@180 { - compatible = "fsl,mpc8540-dma-channel", - "fsl,eloplus-dma-channel"; - reg = <0x180 0x80>; - cell-index = <3>; - interrupt-parent = <&mpic>; - interrupts = <23 2>; - }; - }; - - enet0: ethernet@24000 { - #address-cells = <1>; - #size-cells = <1>; - cell-index = <0>; - device_type = "network"; - model = "TSEC"; - compatible = "gianfar"; - reg = <0x24000 0x1000>; - ranges = <0x0 0x24000 0x1000>; - local-mac-address = [ 00 00 00 00 00 00 ]; - interrupts = <29 2 30 2 34 2>; - interrupt-parent = <&mpic>; - tbi-handle = <&tbi0>; - phy-handle = <&phy0>; - - mdio@520 { - #address-cells = <1>; - #size-cells = <0>; - compatible = "fsl,gianfar-mdio"; - reg = <0x520 0x20>; - - phy0: ethernet-phy@0 { - interrupt-parent = <&mpic>; - interrupts = <5 1>; - reg = <0x0>; - }; - phy1: ethernet-phy@1 { - interrupt-parent = <&mpic>; - interrupts = <5 1>; - reg = <0x1>; - }; - phy3: ethernet-phy@3 { - interrupt-parent = <&mpic>; - interrupts = <7 1>; - reg = <0x3>; - }; - tbi0: tbi-phy@11 { - reg = <0x11>; - device_type = "tbi-phy"; - }; - }; - }; - - enet1: ethernet@25000 { - #address-cells = <1>; - #size-cells = <1>; - cell-index = <1>; - device_type = "network"; - model = "TSEC"; - compatible = "gianfar"; - reg = <0x25000 0x1000>; - ranges = <0x0 0x25000 0x1000>; - local-mac-address = [ 00 00 00 00 00 00 ]; - interrupts = <35 2 36 2 40 2>; - interrupt-parent = <&mpic>; - tbi-handle = <&tbi1>; - phy-handle = <&phy1>; - - mdio@520 { - #address-cells = <1>; - #size-cells = <0>; - compatible = "fsl,gianfar-tbi"; - reg = <0x520 0x20>; - - tbi1: tbi-phy@11 { - reg = <0x11>; - device_type = "tbi-phy"; - }; - }; - }; - - enet2: ethernet@26000 { - #address-cells = <1>; - #size-cells = <1>; - cell-index = <2>; - device_type = "network"; - model = "FEC"; - compatible = "gianfar"; - reg = <0x26000 0x1000>; - ranges = <0x0 0x26000 0x1000>; - local-mac-address = [ 00 00 00 00 00 00 ]; - interrupts = <41 2>; - interrupt-parent = <&mpic>; - tbi-handle = <&tbi2>; - phy-handle = <&phy3>; - - mdio@520 { - #address-cells = <1>; - #size-cells = <0>; - compatible = "fsl,gianfar-tbi"; - reg = <0x520 0x20>; - - tbi2: tbi-phy@11 { - reg = <0x11>; - device_type = "tbi-phy"; - }; - }; - }; - - serial0: serial@4500 { - cell-index = <0>; - device_type = "serial"; - compatible = "fsl,ns16550", "ns16550"; - reg = <0x4500 0x100>; // reg base, size - clock-frequency = <0>; // should we fill in in uboot? - interrupts = <42 2>; - interrupt-parent = <&mpic>; - }; - - serial1: serial@4600 { - cell-index = <1>; - device_type = "serial"; - compatible = "fsl,ns16550", "ns16550"; - reg = <0x4600 0x100>; // reg base, size - clock-frequency = <0>; // should we fill in in uboot? - interrupts = <42 2>; - interrupt-parent = <&mpic>; - }; - mpic: pic@40000 { - interrupt-controller; - #address-cells = <0>; - #interrupt-cells = <2>; - reg = <0x40000 0x40000>; - compatible = "chrp,open-pic"; - device_type = "open-pic"; - }; - }; - - pci0: pci@e0008000 { - interrupt-map-mask = <0xf800 0x0 0x0 0x7>; - interrupt-map = < - - /* IDSEL 0x02 */ - 0x1000 0x0 0x0 0x1 &mpic 0x1 0x1 - 0x1000 0x0 0x0 0x2 &mpic 0x2 0x1 - 0x1000 0x0 0x0 0x3 &mpic 0x3 0x1 - 0x1000 0x0 0x0 0x4 &mpic 0x4 0x1 - - /* IDSEL 0x03 */ - 0x1800 0x0 0x0 0x1 &mpic 0x4 0x1 - 0x1800 0x0 0x0 0x2 &mpic 0x1 0x1 - 0x1800 0x0 0x0 0x3 &mpic 0x2 0x1 - 0x1800 0x0 0x0 0x4 &mpic 0x3 0x1 - - /* IDSEL 0x04 */ - 0x2000 0x0 0x0 0x1 &mpic 0x3 0x1 - 0x2000 0x0 0x0 0x2 &mpic 0x4 0x1 - 0x2000 0x0 0x0 0x3 &mpic 0x1 0x1 - 0x2000 0x0 0x0 0x4 &mpic 0x2 0x1 - - /* IDSEL 0x05 */ - 0x2800 0x0 0x0 0x1 &mpic 0x2 0x1 - 0x2800 0x0 0x0 0x2 &mpic 0x3 0x1 - 0x2800 0x0 0x0 0x3 &mpic 0x4 0x1 - 0x2800 0x0 0x0 0x4 &mpic 0x1 0x1 - - /* IDSEL 0x0c */ - 0x6000 0x0 0x0 0x1 &mpic 0x1 0x1 - 0x6000 0x0 0x0 0x2 &mpic 0x2 0x1 - 0x6000 0x0 0x0 0x3 &mpic 0x3 0x1 - 0x6000 0x0 0x0 0x4 &mpic 0x4 0x1 - - /* IDSEL 0x0d */ - 0x6800 0x0 0x0 0x1 &mpic 0x4 0x1 - 0x6800 0x0 0x0 0x2 &mpic 0x1 0x1 - 0x6800 0x0 0x0 0x3 &mpic 0x2 0x1 - 0x6800 0x0 0x0 0x4 &mpic 0x3 0x1 - - /* IDSEL 0x0e */ - 0x7000 0x0 0x0 0x1 &mpic 0x3 0x1 - 0x7000 0x0 0x0 0x2 &mpic 0x4 0x1 - 0x7000 0x0 0x0 0x3 &mpic 0x1 0x1 - 0x7000 0x0 0x0 0x4 &mpic 0x2 0x1 - - /* IDSEL 0x0f */ - 0x7800 0x0 0x0 0x1 &mpic 0x2 0x1 - 0x7800 0x0 0x0 0x2 &mpic 0x3 0x1 - 0x7800 0x0 0x0 0x3 &mpic 0x4 0x1 - 0x7800 0x0 0x0 0x4 &mpic 0x1 0x1 - - /* IDSEL 0x12 */ - 0x9000 0x0 0x0 0x1 &mpic 0x1 0x1 - 0x9000 0x0 0x0 0x2 &mpic 0x2 0x1 - 0x9000 0x0 0x0 0x3 &mpic 0x3 0x1 - 0x9000 0x0 0x0 0x4 &mpic 0x4 0x1 - - /* IDSEL 0x13 */ - 0x9800 0x0 0x0 0x1 &mpic 0x4 0x1 - 0x9800 0x0 0x0 0x2 &mpic 0x1 0x1 - 0x9800 0x0 0x0 0x3 &mpic 0x2 0x1 - 0x9800 0x0 0x0 0x4 &mpic 0x3 0x1 - - /* IDSEL 0x14 */ - 0xa000 0x0 0x0 0x1 &mpic 0x3 0x1 - 0xa000 0x0 0x0 0x2 &mpic 0x4 0x1 - 0xa000 0x0 0x0 0x3 &mpic 0x1 0x1 - 0xa000 0x0 0x0 0x4 &mpic 0x2 0x1 - - /* IDSEL 0x15 */ - 0xa800 0x0 0x0 0x1 &mpic 0x2 0x1 - 0xa800 0x0 0x0 0x2 &mpic 0x3 0x1 - 0xa800 0x0 0x0 0x3 &mpic 0x4 0x1 - 0xa800 0x0 0x0 0x4 &mpic 0x1 0x1>; - interrupt-parent = <&mpic>; - interrupts = <24 2>; - bus-range = <0 0>; - ranges = <0x2000000 0x0 0x80000000 0x80000000 0x0 0x20000000 - 0x1000000 0x0 0x0 0xe2000000 0x0 0x100000>; - clock-frequency = <66666666>; - #interrupt-cells = <1>; - #size-cells = <2>; - #address-cells = <3>; - reg = <0xe0008000 0x1000>; - compatible = "fsl,mpc8540-pcix", "fsl,mpc8540-pci"; - device_type = "pci"; - }; -}; diff --git a/arch/powerpc/boot/dts/fsl/mpc8541cds.dts b/arch/powerpc/boot/dts/fsl/mpc8541cds.dts deleted file mode 100644 index a2a6c5cf852e971f7ce6928f572dd93b4c5699cb..0000000000000000000000000000000000000000 --- a/arch/powerpc/boot/dts/fsl/mpc8541cds.dts +++ /dev/null @@ -1,375 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * MPC8541 CDS Device Tree Source - * - * Copyright 2006, 2008 Freescale Semiconductor Inc. - */ - -/dts-v1/; - -/include/ "e500v1_power_isa.dtsi" - -/ { - model = "MPC8541CDS"; - compatible = "MPC8541CDS", "MPC85xxCDS"; - #address-cells = <1>; - #size-cells = <1>; - - aliases { - ethernet0 = &enet0; - ethernet1 = &enet1; - serial0 = &serial0; - serial1 = &serial1; - pci0 = &pci0; - pci1 = &pci1; - }; - - cpus { - #address-cells = <1>; - #size-cells = <0>; - - PowerPC,8541@0 { - device_type = "cpu"; - reg = <0x0>; - d-cache-line-size = <32>; // 32 bytes - i-cache-line-size = <32>; // 32 bytes - d-cache-size = <0x8000>; // L1, 32K - i-cache-size = <0x8000>; // L1, 32K - timebase-frequency = <0>; // 33 MHz, from uboot - bus-frequency = <0>; // 166 MHz - clock-frequency = <0>; // 825 MHz, from uboot - next-level-cache = <&L2>; - }; - }; - - memory { - device_type = "memory"; - reg = <0x0 0x8000000>; // 128M at 0x0 - }; - - soc8541@e0000000 { - #address-cells = <1>; - #size-cells = <1>; - device_type = "soc"; - compatible = "simple-bus"; - ranges = <0x0 0xe0000000 0x100000>; - bus-frequency = <0>; - - ecm-law@0 { - compatible = "fsl,ecm-law"; - reg = <0x0 0x1000>; - fsl,num-laws = <8>; - }; - - ecm@1000 { - compatible = "fsl,mpc8541-ecm", "fsl,ecm"; - reg = <0x1000 0x1000>; - interrupts = <17 2>; - interrupt-parent = <&mpic>; - }; - - memory-controller@2000 { - compatible = "fsl,mpc8541-memory-controller"; - reg = <0x2000 0x1000>; - interrupt-parent = <&mpic>; - interrupts = <18 2>; - }; - - L2: l2-cache-controller@20000 { - compatible = "fsl,mpc8541-l2-cache-controller"; - reg = <0x20000 0x1000>; - cache-line-size = <32>; // 32 bytes - cache-size = <0x40000>; // L2, 256K - interrupt-parent = <&mpic>; - interrupts = <16 2>; - }; - - i2c@3000 { - #address-cells = <1>; - #size-cells = <0>; - cell-index = <0>; - compatible = "fsl-i2c"; - reg = <0x3000 0x100>; - interrupts = <43 2>; - interrupt-parent = <&mpic>; - dfsrr; - }; - - dma@21300 { - #address-cells = <1>; - #size-cells = <1>; - compatible = "fsl,mpc8541-dma", "fsl,eloplus-dma"; - reg = <0x21300 0x4>; - ranges = <0x0 0x21100 0x200>; - cell-index = <0>; - dma-channel@0 { - compatible = "fsl,mpc8541-dma-channel", - "fsl,eloplus-dma-channel"; - reg = <0x0 0x80>; - cell-index = <0>; - interrupt-parent = <&mpic>; - interrupts = <20 2>; - }; - dma-channel@80 { - compatible = "fsl,mpc8541-dma-channel", - "fsl,eloplus-dma-channel"; - reg = <0x80 0x80>; - cell-index = <1>; - interrupt-parent = <&mpic>; - interrupts = <21 2>; - }; - dma-channel@100 { - compatible = "fsl,mpc8541-dma-channel", - "fsl,eloplus-dma-channel"; - reg = <0x100 0x80>; - cell-index = <2>; - interrupt-parent = <&mpic>; - interrupts = <22 2>; - }; - dma-channel@180 { - compatible = "fsl,mpc8541-dma-channel", - "fsl,eloplus-dma-channel"; - reg = <0x180 0x80>; - cell-index = <3>; - interrupt-parent = <&mpic>; - interrupts = <23 2>; - }; - }; - - enet0: ethernet@24000 { - #address-cells = <1>; - #size-cells = <1>; - cell-index = <0>; - device_type = "network"; - model = "TSEC"; - compatible = "gianfar"; - reg = <0x24000 0x1000>; - ranges = <0x0 0x24000 0x1000>; - local-mac-address = [ 00 00 00 00 00 00 ]; - interrupts = <29 2 30 2 34 2>; - interrupt-parent = <&mpic>; - tbi-handle = <&tbi0>; - phy-handle = <&phy0>; - - mdio@520 { - #address-cells = <1>; - #size-cells = <0>; - compatible = "fsl,gianfar-mdio"; - reg = <0x520 0x20>; - - phy0: ethernet-phy@0 { - interrupt-parent = <&mpic>; - interrupts = <5 1>; - reg = <0x0>; - }; - phy1: ethernet-phy@1 { - interrupt-parent = <&mpic>; - interrupts = <5 1>; - reg = <0x1>; - }; - tbi0: tbi-phy@11 { - reg = <0x11>; - device_type = "tbi-phy"; - }; - }; - }; - - enet1: ethernet@25000 { - #address-cells = <1>; - #size-cells = <1>; - cell-index = <1>; - device_type = "network"; - model = "TSEC"; - compatible = "gianfar"; - reg = <0x25000 0x1000>; - ranges = <0x0 0x25000 0x1000>; - local-mac-address = [ 00 00 00 00 00 00 ]; - interrupts = <35 2 36 2 40 2>; - interrupt-parent = <&mpic>; - tbi-handle = <&tbi1>; - phy-handle = <&phy1>; - - mdio@520 { - #address-cells = <1>; - #size-cells = <0>; - compatible = "fsl,gianfar-tbi"; - reg = <0x520 0x20>; - - tbi1: tbi-phy@11 { - reg = <0x11>; - device_type = "tbi-phy"; - }; - }; - }; - - serial0: serial@4500 { - cell-index = <0>; - device_type = "serial"; - compatible = "fsl,ns16550", "ns16550"; - reg = <0x4500 0x100>; // reg base, size - clock-frequency = <0>; // should we fill in in uboot? - interrupts = <42 2>; - interrupt-parent = <&mpic>; - }; - - serial1: serial@4600 { - cell-index = <1>; - device_type = "serial"; - compatible = "fsl,ns16550", "ns16550"; - reg = <0x4600 0x100>; // reg base, size - clock-frequency = <0>; // should we fill in in uboot? - interrupts = <42 2>; - interrupt-parent = <&mpic>; - }; - - crypto@30000 { - compatible = "fsl,sec2.0"; - reg = <0x30000 0x10000>; - interrupts = <45 2>; - interrupt-parent = <&mpic>; - fsl,num-channels = <4>; - fsl,channel-fifo-len = <24>; - fsl,exec-units-mask = <0x7e>; - fsl,descriptor-types-mask = <0x01010ebf>; - }; - - mpic: pic@40000 { - interrupt-controller; - #address-cells = <0>; - #interrupt-cells = <2>; - reg = <0x40000 0x40000>; - compatible = "chrp,open-pic"; - device_type = "open-pic"; - }; - - cpm@919c0 { - #address-cells = <1>; - #size-cells = <1>; - compatible = "fsl,mpc8541-cpm", "fsl,cpm2"; - reg = <0x919c0 0x30>; - ranges; - - muram@80000 { - #address-cells = <1>; - #size-cells = <1>; - ranges = <0x0 0x80000 0x10000>; - - data@0 { - compatible = "fsl,cpm-muram-data"; - reg = <0x0 0x2000 0x9000 0x1000>; - }; - }; - - brg@919f0 { - compatible = "fsl,mpc8541-brg", - "fsl,cpm2-brg", - "fsl,cpm-brg"; - reg = <0x919f0 0x10 0x915f0 0x10>; - }; - - cpmpic: pic@90c00 { - interrupt-controller; - #address-cells = <0>; - #interrupt-cells = <2>; - interrupts = <46 2>; - interrupt-parent = <&mpic>; - reg = <0x90c00 0x80>; - compatible = "fsl,mpc8541-cpm-pic", "fsl,cpm2-pic"; - }; - }; - }; - - pci0: pci@e0008000 { - interrupt-map-mask = <0x1f800 0x0 0x0 0x7>; - interrupt-map = < - - /* IDSEL 0x10 */ - 0x8000 0x0 0x0 0x1 &mpic 0x0 0x1 - 0x8000 0x0 0x0 0x2 &mpic 0x1 0x1 - 0x8000 0x0 0x0 0x3 &mpic 0x2 0x1 - 0x8000 0x0 0x0 0x4 &mpic 0x3 0x1 - - /* IDSEL 0x11 */ - 0x8800 0x0 0x0 0x1 &mpic 0x0 0x1 - 0x8800 0x0 0x0 0x2 &mpic 0x1 0x1 - 0x8800 0x0 0x0 0x3 &mpic 0x2 0x1 - 0x8800 0x0 0x0 0x4 &mpic 0x3 0x1 - - /* IDSEL 0x12 (Slot 1) */ - 0x9000 0x0 0x0 0x1 &mpic 0x0 0x1 - 0x9000 0x0 0x0 0x2 &mpic 0x1 0x1 - 0x9000 0x0 0x0 0x3 &mpic 0x2 0x1 - 0x9000 0x0 0x0 0x4 &mpic 0x3 0x1 - - /* IDSEL 0x13 (Slot 2) */ - 0x9800 0x0 0x0 0x1 &mpic 0x1 0x1 - 0x9800 0x0 0x0 0x2 &mpic 0x2 0x1 - 0x9800 0x0 0x0 0x3 &mpic 0x3 0x1 - 0x9800 0x0 0x0 0x4 &mpic 0x0 0x1 - - /* IDSEL 0x14 (Slot 3) */ - 0xa000 0x0 0x0 0x1 &mpic 0x2 0x1 - 0xa000 0x0 0x0 0x2 &mpic 0x3 0x1 - 0xa000 0x0 0x0 0x3 &mpic 0x0 0x1 - 0xa000 0x0 0x0 0x4 &mpic 0x1 0x1 - - /* IDSEL 0x15 (Slot 4) */ - 0xa800 0x0 0x0 0x1 &mpic 0x3 0x1 - 0xa800 0x0 0x0 0x2 &mpic 0x0 0x1 - 0xa800 0x0 0x0 0x3 &mpic 0x1 0x1 - 0xa800 0x0 0x0 0x4 &mpic 0x2 0x1 - - /* Bus 1 (Tundra Bridge) */ - /* IDSEL 0x12 (ISA bridge) */ - 0x19000 0x0 0x0 0x1 &mpic 0x0 0x1 - 0x19000 0x0 0x0 0x2 &mpic 0x1 0x1 - 0x19000 0x0 0x0 0x3 &mpic 0x2 0x1 - 0x19000 0x0 0x0 0x4 &mpic 0x3 0x1>; - interrupt-parent = <&mpic>; - interrupts = <24 2>; - bus-range = <0 0>; - ranges = <0x2000000 0x0 0x80000000 0x80000000 0x0 0x20000000 - 0x1000000 0x0 0x0 0xe2000000 0x0 0x100000>; - clock-frequency = <66666666>; - #interrupt-cells = <1>; - #size-cells = <2>; - #address-cells = <3>; - reg = <0xe0008000 0x1000>; - compatible = "fsl,mpc8540-pci"; - device_type = "pci"; - - i8259@19000 { - interrupt-controller; - device_type = "interrupt-controller"; - reg = <0x19000 0x0 0x0 0x0 0x1>; - #address-cells = <0>; - #interrupt-cells = <2>; - compatible = "chrp,iic"; - interrupts = <1>; - interrupt-parent = <&pci0>; - }; - }; - - pci1: pci@e0009000 { - interrupt-map-mask = <0xf800 0x0 0x0 0x7>; - interrupt-map = < - - /* IDSEL 0x15 */ - 0xa800 0x0 0x0 0x1 &mpic 0xb 0x1 - 0xa800 0x0 0x0 0x2 &mpic 0xb 0x1 - 0xa800 0x0 0x0 0x3 &mpic 0xb 0x1 - 0xa800 0x0 0x0 0x4 &mpic 0xb 0x1>; - interrupt-parent = <&mpic>; - interrupts = <25 2>; - bus-range = <0 0>; - ranges = <0x2000000 0x0 0xa0000000 0xa0000000 0x0 0x20000000 - 0x1000000 0x0 0x0 0xe3000000 0x0 0x100000>; - clock-frequency = <66666666>; - #interrupt-cells = <1>; - #size-cells = <2>; - #address-cells = <3>; - reg = <0xe0009000 0x1000>; - compatible = "fsl,mpc8540-pci"; - device_type = "pci"; - }; -}; diff --git a/arch/powerpc/boot/dts/fsl/mpc8548cds.dtsi b/arch/powerpc/boot/dts/fsl/mpc8548cds.dtsi deleted file mode 100644 index 3bc7d4711220f41e27d1cf08ca08541da882b798..0000000000000000000000000000000000000000 --- a/arch/powerpc/boot/dts/fsl/mpc8548cds.dtsi +++ /dev/null @@ -1,302 +0,0 @@ -/* - * MPC8548CDS Device Tree Source stub (no addresses or top-level ranges) - * - * Copyright 2012 Freescale Semiconductor Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Freescale Semiconductor nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * - * ALTERNATIVELY, this software may be distributed under the terms of the - * GNU General Public License ("GPL") as published by the Free Software - * Foundation, either version 2 of that License or (at your option) any - * later version. - * - * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -&board_lbc { - nor@0,0 { - #address-cells = <1>; - #size-cells = <1>; - compatible = "cfi-flash"; - reg = <0x0 0x0 0x01000000>; - bank-width = <2>; - device-width = <2>; - - partition@0 { - reg = <0x0 0x0b00000>; - label = "ramdisk-nor"; - }; - - partition@300000 { - reg = <0x0b00000 0x0400000>; - label = "kernel-nor"; - }; - - partition@700000 { - reg = <0x0f00000 0x060000>; - label = "dtb-nor"; - }; - - partition@760000 { - reg = <0x0f60000 0x020000>; - label = "env-nor"; - read-only; - }; - - partition@780000 { - reg = <0x0f80000 0x080000>; - label = "u-boot-nor"; - read-only; - }; - }; - - board-control@1,0 { - compatible = "fsl,mpc8548cds-fpga"; - reg = <0x1 0x0 0x1000>; - }; -}; - -&board_soc { - i2c@3000 { - eeprom@50 { - compatible = "atmel,24c64"; - reg = <0x50>; - }; - - eeprom@56 { - compatible = "atmel,24c64"; - reg = <0x56>; - }; - - eeprom@57 { - compatible = "atmel,24c64"; - reg = <0x57>; - }; - }; - - i2c@3100 { - eeprom@50 { - compatible = "atmel,24c64"; - reg = <0x50>; - }; - }; - - enet0: ethernet@24000 { - tbi-handle = <&tbi0>; - phy-handle = <&phy0>; - }; - - mdio@24520 { - phy0: ethernet-phy@0 { - interrupts = <5 1 0 0>; - reg = <0x0>; - }; - phy1: ethernet-phy@1 { - interrupts = <5 1 0 0>; - reg = <0x1>; - }; - phy2: ethernet-phy@2 { - interrupts = <5 1 0 0>; - reg = <0x2>; - }; - phy3: ethernet-phy@3 { - interrupts = <5 1 0 0>; - reg = <0x3>; - }; - tbi0: tbi-phy@11 { - reg = <0x11>; - device_type = "tbi-phy"; - }; - }; - - enet1: ethernet@25000 { - tbi-handle = <&tbi1>; - phy-handle = <&phy1>; - }; - - mdio@25520 { - tbi1: tbi-phy@11 { - reg = <0x11>; - device_type = "tbi-phy"; - }; - }; - - enet2: ethernet@26000 { - tbi-handle = <&tbi2>; - phy-handle = <&phy2>; - }; - - mdio@26520 { - tbi2: tbi-phy@11 { - reg = <0x11>; - device_type = "tbi-phy"; - }; - }; - - enet3: ethernet@27000 { - tbi-handle = <&tbi3>; - phy-handle = <&phy3>; - }; - - mdio@27520 { - tbi3: tbi-phy@11 { - reg = <0x11>; - device_type = "tbi-phy"; - }; - }; -}; - -&board_pci0 { - interrupt-map-mask = <0xf800 0x0 0x0 0x7>; - interrupt-map = < - /* IDSEL 0x4 (PCIX Slot 2) */ - 0x2000 0x0 0x0 0x1 &mpic 0x0 0x1 0 0 - 0x2000 0x0 0x0 0x2 &mpic 0x1 0x1 0 0 - 0x2000 0x0 0x0 0x3 &mpic 0x2 0x1 0 0 - 0x2000 0x0 0x0 0x4 &mpic 0x3 0x1 0 0 - - /* IDSEL 0x5 (PCIX Slot 3) */ - 0x2800 0x0 0x0 0x1 &mpic 0x1 0x1 0 0 - 0x2800 0x0 0x0 0x2 &mpic 0x2 0x1 0 0 - 0x2800 0x0 0x0 0x3 &mpic 0x3 0x1 0 0 - 0x2800 0x0 0x0 0x4 &mpic 0x0 0x1 0 0 - - /* IDSEL 0x6 (PCIX Slot 4) */ - 0x3000 0x0 0x0 0x1 &mpic 0x2 0x1 0 0 - 0x3000 0x0 0x0 0x2 &mpic 0x3 0x1 0 0 - 0x3000 0x0 0x0 0x3 &mpic 0x0 0x1 0 0 - 0x3000 0x0 0x0 0x4 &mpic 0x1 0x1 0 0 - - /* IDSEL 0x8 (PCIX Slot 5) */ - 0x4000 0x0 0x0 0x1 &mpic 0x0 0x1 0 0 - 0x4000 0x0 0x0 0x2 &mpic 0x1 0x1 0 0 - 0x4000 0x0 0x0 0x3 &mpic 0x2 0x1 0 0 - 0x4000 0x0 0x0 0x4 &mpic 0x3 0x1 0 0 - - /* IDSEL 0xC (Tsi310 bridge) */ - 0x6000 0x0 0x0 0x1 &mpic 0x0 0x1 0 0 - 0x6000 0x0 0x0 0x2 &mpic 0x1 0x1 0 0 - 0x6000 0x0 0x0 0x3 &mpic 0x2 0x1 0 0 - 0x6000 0x0 0x0 0x4 &mpic 0x3 0x1 0 0 - - /* IDSEL 0x14 (Slot 2) */ - 0xa000 0x0 0x0 0x1 &mpic 0x0 0x1 0 0 - 0xa000 0x0 0x0 0x2 &mpic 0x1 0x1 0 0 - 0xa000 0x0 0x0 0x3 &mpic 0x2 0x1 0 0 - 0xa000 0x0 0x0 0x4 &mpic 0x3 0x1 0 0 - - /* IDSEL 0x15 (Slot 3) */ - 0xa800 0x0 0x0 0x1 &mpic 0x1 0x1 0 0 - 0xa800 0x0 0x0 0x2 &mpic 0x2 0x1 0 0 - 0xa800 0x0 0x0 0x3 &mpic 0x3 0x1 0 0 - 0xa800 0x0 0x0 0x4 &mpic 0x0 0x1 0 0 - - /* IDSEL 0x16 (Slot 4) */ - 0xb000 0x0 0x0 0x1 &mpic 0x2 0x1 0 0 - 0xb000 0x0 0x0 0x2 &mpic 0x3 0x1 0 0 - 0xb000 0x0 0x0 0x3 &mpic 0x0 0x1 0 0 - 0xb000 0x0 0x0 0x4 &mpic 0x1 0x1 0 0 - - /* IDSEL 0x18 (Slot 5) */ - 0xc000 0x0 0x0 0x1 &mpic 0x0 0x1 0 0 - 0xc000 0x0 0x0 0x2 &mpic 0x1 0x1 0 0 - 0xc000 0x0 0x0 0x3 &mpic 0x2 0x1 0 0 - 0xc000 0x0 0x0 0x4 &mpic 0x3 0x1 0 0 - - /* IDSEL 0x1C (Tsi310 bridge PCI primary) */ - 0xe000 0x0 0x0 0x1 &mpic 0x0 0x1 0 0 - 0xe000 0x0 0x0 0x2 &mpic 0x1 0x1 0 0 - 0xe000 0x0 0x0 0x3 &mpic 0x2 0x1 0 0 - 0xe000 0x0 0x0 0x4 &mpic 0x3 0x1 0 0>; - - pci_bridge@1c { - interrupt-map-mask = <0xf800 0x0 0x0 0x7>; - interrupt-map = < - - /* IDSEL 0x00 (PrPMC Site) */ - 0000 0x0 0x0 0x1 &mpic 0x0 0x1 0 0 - 0000 0x0 0x0 0x2 &mpic 0x1 0x1 0 0 - 0000 0x0 0x0 0x3 &mpic 0x2 0x1 0 0 - 0000 0x0 0x0 0x4 &mpic 0x3 0x1 0 0 - - /* IDSEL 0x04 (VIA chip) */ - 0x2000 0x0 0x0 0x1 &mpic 0x0 0x1 0 0 - 0x2000 0x0 0x0 0x2 &mpic 0x1 0x1 0 0 - 0x2000 0x0 0x0 0x3 &mpic 0x2 0x1 0 0 - 0x2000 0x0 0x0 0x4 &mpic 0x3 0x1 0 0 - - /* IDSEL 0x05 (8139) */ - 0x2800 0x0 0x0 0x1 &mpic 0x1 0x1 0 0 - - /* IDSEL 0x06 (Slot 6) */ - 0x3000 0x0 0x0 0x1 &mpic 0x2 0x1 0 0 - 0x3000 0x0 0x0 0x2 &mpic 0x3 0x1 0 0 - 0x3000 0x0 0x0 0x3 &mpic 0x0 0x1 0 0 - 0x3000 0x0 0x0 0x4 &mpic 0x1 0x1 0 0 - - /* IDESL 0x07 (Slot 7) */ - 0x3800 0x0 0x0 0x1 &mpic 0x3 0x1 0 0 - 0x3800 0x0 0x0 0x2 &mpic 0x0 0x1 0 0 - 0x3800 0x0 0x0 0x3 &mpic 0x1 0x1 0 0 - 0x3800 0x0 0x0 0x4 &mpic 0x2 0x1 0 0>; - - reg = <0xe000 0x0 0x0 0x0 0x0>; - #interrupt-cells = <1>; - #size-cells = <2>; - #address-cells = <3>; - ranges = <0x2000000 0x0 0x80000000 - 0x2000000 0x0 0x80000000 - 0x0 0x20000000 - 0x1000000 0x0 0x0 - 0x1000000 0x0 0x0 - 0x0 0x80000>; - clock-frequency = <33333333>; - - isa@4 { - device_type = "isa"; - #interrupt-cells = <2>; - #size-cells = <1>; - #address-cells = <2>; - reg = <0x2000 0x0 0x0 0x0 0x0>; - ranges = <0x1 0x0 0x1000000 0x0 0x0 0x1000>; - interrupt-parent = <&i8259>; - - i8259: interrupt-controller@20 { - interrupt-controller; - device_type = "interrupt-controller"; - reg = <0x1 0x20 0x2 - 0x1 0xa0 0x2 - 0x1 0x4d0 0x2>; - #address-cells = <0>; - #interrupt-cells = <2>; - compatible = "chrp,iic"; - interrupts = <0 1 0 0>; - interrupt-parent = <&mpic>; - }; - - rtc@70 { - compatible = "pnpPNP,b00"; - reg = <0x1 0x70 0x2>; - }; - }; - }; -}; diff --git a/arch/powerpc/boot/dts/fsl/mpc8548cds_32b.dts b/arch/powerpc/boot/dts/fsl/mpc8548cds_32b.dts deleted file mode 100644 index f6ba4a9827665dd293b6360531c837ce95831249..0000000000000000000000000000000000000000 --- a/arch/powerpc/boot/dts/fsl/mpc8548cds_32b.dts +++ /dev/null @@ -1,82 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * MPC8548 CDS Device Tree Source (32-bit address map) - * - * Copyright 2006, 2008, 2011-2012 Freescale Semiconductor Inc. - */ - -/include/ "mpc8548si-pre.dtsi" - -/ { - model = "MPC8548CDS"; - compatible = "MPC8548CDS", "MPC85xxCDS"; - - memory { - device_type = "memory"; - reg = <0 0 0x0 0x8000000>; // 128M at 0x0 - }; - - board_lbc: lbc: localbus@e0005000 { - reg = <0 0xe0005000 0 0x1000>; - - ranges = <0x0 0x0 0x0 0xff000000 0x01000000 - 0x1 0x0 0x0 0xf8004000 0x00001000>; - - }; - - board_soc: soc: soc8548@e0000000 { - ranges = <0 0x0 0xe0000000 0x100000>; - }; - - board_pci0: pci0: pci@e0008000 { - reg = <0 0xe0008000 0 0x1000>; - ranges = <0x2000000 0x0 0x80000000 0 0x80000000 0x0 0x10000000 - 0x1000000 0x0 0x00000000 0 0xe2000000 0x0 0x800000>; - clock-frequency = <66666666>; - }; - - pci1: pci@e0009000 { - reg = <0 0xe0009000 0 0x1000>; - ranges = <0x2000000 0x0 0x90000000 0 0x90000000 0x0 0x10000000 - 0x1000000 0x0 0x00000000 0 0xe2800000 0x0 0x800000>; - clock-frequency = <66666666>; - interrupt-map-mask = <0xf800 0x0 0x0 0x7>; - interrupt-map = < - - /* IDSEL 0x15 */ - 0xa800 0x0 0x0 0x1 &mpic 0xb 0x1 0 0 - 0xa800 0x0 0x0 0x2 &mpic 0x1 0x1 0 0 - 0xa800 0x0 0x0 0x3 &mpic 0x2 0x1 0 0 - 0xa800 0x0 0x0 0x4 &mpic 0x3 0x1 0 0>; - }; - - pci2: pcie@e000a000 { - reg = <0 0xe000a000 0 0x1000>; - ranges = <0x2000000 0x0 0xa0000000 0 0xa0000000 0x0 0x20000000 - 0x1000000 0x0 0x00000000 0 0xe3000000 0x0 0x100000>; - pcie@0 { - ranges = <0x2000000 0x0 0xa0000000 - 0x2000000 0x0 0xa0000000 - 0x0 0x20000000 - - 0x1000000 0x0 0x0 - 0x1000000 0x0 0x0 - 0x0 0x100000>; - }; - }; - - rio: rapidio@e00c0000 { - reg = <0x0 0xe00c0000 0x0 0x20000>; - port1 { - ranges = <0x0 0x0 0x0 0xc0000000 0x0 0x20000000>; - }; - }; -}; - -/* - * mpc8548cds.dtsi must be last to ensure board_pci0 overrides pci0 settings - * for interrupt-map & interrupt-map-mask. - */ - -/include/ "mpc8548si-post.dtsi" -/include/ "mpc8548cds.dtsi" diff --git a/arch/powerpc/boot/dts/fsl/mpc8548cds_36b.dts b/arch/powerpc/boot/dts/fsl/mpc8548cds_36b.dts deleted file mode 100644 index 32e9076375ae3f216718733ac29207b98f651000..0000000000000000000000000000000000000000 --- a/arch/powerpc/boot/dts/fsl/mpc8548cds_36b.dts +++ /dev/null @@ -1,82 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * MPC8548 CDS Device Tree Source (36-bit address map) - * - * Copyright 2012 Freescale Semiconductor Inc. - */ - -/include/ "mpc8548si-pre.dtsi" - -/ { - model = "MPC8548CDS"; - compatible = "MPC8548CDS", "MPC85xxCDS"; - - memory { - device_type = "memory"; - reg = <0 0 0x0 0x8000000>; // 128M at 0x0 - }; - - board_lbc: lbc: localbus@fe0005000 { - reg = <0xf 0xe0005000 0 0x1000>; - - ranges = <0x0 0x0 0xf 0xff000000 0x01000000 - 0x1 0x0 0xf 0xf8004000 0x00001000>; - - }; - - board_soc: soc: soc8548@fe0000000 { - ranges = <0 0xf 0xe0000000 0x100000>; - }; - - board_pci0: pci0: pci@fe0008000 { - reg = <0xf 0xe0008000 0 0x1000>; - ranges = <0x2000000 0x0 0xe0000000 0xc 0x00000000 0x0 0x10000000 - 0x1000000 0x0 0x00000000 0xf 0xe2000000 0x0 0x800000>; - clock-frequency = <66666666>; - }; - - pci1: pci@fe0009000 { - reg = <0xf 0xe0009000 0 0x1000>; - ranges = <0x2000000 0x0 0xe0000000 0xc 0x10000000 0x0 0x10000000 - 0x1000000 0x0 0x00000000 0xf 0xe2800000 0x0 0x800000>; - clock-frequency = <66666666>; - interrupt-map-mask = <0xf800 0x0 0x0 0x7>; - interrupt-map = < - - /* IDSEL 0x15 */ - 0xa800 0x0 0x0 0x1 &mpic 0xb 0x1 0 0 - 0xa800 0x0 0x0 0x2 &mpic 0x1 0x1 0 0 - 0xa800 0x0 0x0 0x3 &mpic 0x2 0x1 0 0 - 0xa800 0x0 0x0 0x4 &mpic 0x3 0x1 0 0>; - }; - - pci2: pcie@fe000a000 { - reg = <0xf 0xe000a000 0 0x1000>; - ranges = <0x2000000 0x0 0xe0000000 0xc 0x20000000 0x0 0x20000000 - 0x1000000 0x0 0x00000000 0xf 0xe3000000 0x0 0x100000>; - pcie@0 { - ranges = <0x2000000 0x0 0xa0000000 - 0x2000000 0x0 0xa0000000 - 0x0 0x20000000 - - 0x1000000 0x0 0x0 - 0x1000000 0x0 0x0 - 0x0 0x100000>; - }; - }; - - rio: rapidio@fe00c0000 { - reg = <0xf 0xe00c0000 0x0 0x20000>; - port1 { - ranges = <0x0 0x0 0xc 0x40000000 0x0 0x20000000>; - }; - }; -}; - -/* - * mpc8548cds.dtsi must be last to ensure board_pci0 overrides pci0 settings - * for interrupt-map & interrupt-map-mask. - */ - -/include/ "mpc8548si-post.dtsi" -/include/ "mpc8548cds.dtsi" diff --git a/arch/powerpc/boot/dts/fsl/mpc8555cds.dts b/arch/powerpc/boot/dts/fsl/mpc8555cds.dts deleted file mode 100644 index 901b6ff06dfbb4b7e4a8b3c81bc6ddb338879283..0000000000000000000000000000000000000000 --- a/arch/powerpc/boot/dts/fsl/mpc8555cds.dts +++ /dev/null @@ -1,375 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * MPC8555 CDS Device Tree Source - * - * Copyright 2006, 2008 Freescale Semiconductor Inc. - */ - -/dts-v1/; - -/include/ "e500v1_power_isa.dtsi" - -/ { - model = "MPC8555CDS"; - compatible = "MPC8555CDS", "MPC85xxCDS"; - #address-cells = <1>; - #size-cells = <1>; - - aliases { - ethernet0 = &enet0; - ethernet1 = &enet1; - serial0 = &serial0; - serial1 = &serial1; - pci0 = &pci0; - pci1 = &pci1; - }; - - cpus { - #address-cells = <1>; - #size-cells = <0>; - - PowerPC,8555@0 { - device_type = "cpu"; - reg = <0x0>; - d-cache-line-size = <32>; // 32 bytes - i-cache-line-size = <32>; // 32 bytes - d-cache-size = <0x8000>; // L1, 32K - i-cache-size = <0x8000>; // L1, 32K - timebase-frequency = <0>; // 33 MHz, from uboot - bus-frequency = <0>; // 166 MHz - clock-frequency = <0>; // 825 MHz, from uboot - next-level-cache = <&L2>; - }; - }; - - memory { - device_type = "memory"; - reg = <0x0 0x8000000>; // 128M at 0x0 - }; - - soc8555@e0000000 { - #address-cells = <1>; - #size-cells = <1>; - device_type = "soc"; - compatible = "simple-bus"; - ranges = <0x0 0xe0000000 0x100000>; - bus-frequency = <0>; - - ecm-law@0 { - compatible = "fsl,ecm-law"; - reg = <0x0 0x1000>; - fsl,num-laws = <8>; - }; - - ecm@1000 { - compatible = "fsl,mpc8555-ecm", "fsl,ecm"; - reg = <0x1000 0x1000>; - interrupts = <17 2>; - interrupt-parent = <&mpic>; - }; - - memory-controller@2000 { - compatible = "fsl,mpc8555-memory-controller"; - reg = <0x2000 0x1000>; - interrupt-parent = <&mpic>; - interrupts = <18 2>; - }; - - L2: l2-cache-controller@20000 { - compatible = "fsl,mpc8555-l2-cache-controller"; - reg = <0x20000 0x1000>; - cache-line-size = <32>; // 32 bytes - cache-size = <0x40000>; // L2, 256K - interrupt-parent = <&mpic>; - interrupts = <16 2>; - }; - - i2c@3000 { - #address-cells = <1>; - #size-cells = <0>; - cell-index = <0>; - compatible = "fsl-i2c"; - reg = <0x3000 0x100>; - interrupts = <43 2>; - interrupt-parent = <&mpic>; - dfsrr; - }; - - dma@21300 { - #address-cells = <1>; - #size-cells = <1>; - compatible = "fsl,mpc8555-dma", "fsl,eloplus-dma"; - reg = <0x21300 0x4>; - ranges = <0x0 0x21100 0x200>; - cell-index = <0>; - dma-channel@0 { - compatible = "fsl,mpc8555-dma-channel", - "fsl,eloplus-dma-channel"; - reg = <0x0 0x80>; - cell-index = <0>; - interrupt-parent = <&mpic>; - interrupts = <20 2>; - }; - dma-channel@80 { - compatible = "fsl,mpc8555-dma-channel", - "fsl,eloplus-dma-channel"; - reg = <0x80 0x80>; - cell-index = <1>; - interrupt-parent = <&mpic>; - interrupts = <21 2>; - }; - dma-channel@100 { - compatible = "fsl,mpc8555-dma-channel", - "fsl,eloplus-dma-channel"; - reg = <0x100 0x80>; - cell-index = <2>; - interrupt-parent = <&mpic>; - interrupts = <22 2>; - }; - dma-channel@180 { - compatible = "fsl,mpc8555-dma-channel", - "fsl,eloplus-dma-channel"; - reg = <0x180 0x80>; - cell-index = <3>; - interrupt-parent = <&mpic>; - interrupts = <23 2>; - }; - }; - - enet0: ethernet@24000 { - #address-cells = <1>; - #size-cells = <1>; - cell-index = <0>; - device_type = "network"; - model = "TSEC"; - compatible = "gianfar"; - reg = <0x24000 0x1000>; - ranges = <0x0 0x24000 0x1000>; - local-mac-address = [ 00 00 00 00 00 00 ]; - interrupts = <29 2 30 2 34 2>; - interrupt-parent = <&mpic>; - tbi-handle = <&tbi0>; - phy-handle = <&phy0>; - - mdio@520 { - #address-cells = <1>; - #size-cells = <0>; - compatible = "fsl,gianfar-mdio"; - reg = <0x520 0x20>; - - phy0: ethernet-phy@0 { - interrupt-parent = <&mpic>; - interrupts = <5 1>; - reg = <0x0>; - }; - phy1: ethernet-phy@1 { - interrupt-parent = <&mpic>; - interrupts = <5 1>; - reg = <0x1>; - }; - tbi0: tbi-phy@11 { - reg = <0x11>; - device_type = "tbi-phy"; - }; - }; - }; - - enet1: ethernet@25000 { - #address-cells = <1>; - #size-cells = <1>; - cell-index = <1>; - device_type = "network"; - model = "TSEC"; - compatible = "gianfar"; - reg = <0x25000 0x1000>; - ranges = <0x0 0x25000 0x1000>; - local-mac-address = [ 00 00 00 00 00 00 ]; - interrupts = <35 2 36 2 40 2>; - interrupt-parent = <&mpic>; - tbi-handle = <&tbi1>; - phy-handle = <&phy1>; - - mdio@520 { - #address-cells = <1>; - #size-cells = <0>; - compatible = "fsl,gianfar-tbi"; - reg = <0x520 0x20>; - - tbi1: tbi-phy@11 { - reg = <0x11>; - device_type = "tbi-phy"; - }; - }; - }; - - serial0: serial@4500 { - cell-index = <0>; - device_type = "serial"; - compatible = "fsl,ns16550", "ns16550"; - reg = <0x4500 0x100>; // reg base, size - clock-frequency = <0>; // should we fill in in uboot? - interrupts = <42 2>; - interrupt-parent = <&mpic>; - }; - - serial1: serial@4600 { - cell-index = <1>; - device_type = "serial"; - compatible = "fsl,ns16550", "ns16550"; - reg = <0x4600 0x100>; // reg base, size - clock-frequency = <0>; // should we fill in in uboot? - interrupts = <42 2>; - interrupt-parent = <&mpic>; - }; - - crypto@30000 { - compatible = "fsl,sec2.0"; - reg = <0x30000 0x10000>; - interrupts = <45 2>; - interrupt-parent = <&mpic>; - fsl,num-channels = <4>; - fsl,channel-fifo-len = <24>; - fsl,exec-units-mask = <0x7e>; - fsl,descriptor-types-mask = <0x01010ebf>; - }; - - mpic: pic@40000 { - interrupt-controller; - #address-cells = <0>; - #interrupt-cells = <2>; - reg = <0x40000 0x40000>; - compatible = "chrp,open-pic"; - device_type = "open-pic"; - }; - - cpm@919c0 { - #address-cells = <1>; - #size-cells = <1>; - compatible = "fsl,mpc8555-cpm", "fsl,cpm2"; - reg = <0x919c0 0x30>; - ranges; - - muram@80000 { - #address-cells = <1>; - #size-cells = <1>; - ranges = <0x0 0x80000 0x10000>; - - data@0 { - compatible = "fsl,cpm-muram-data"; - reg = <0x0 0x2000 0x9000 0x1000>; - }; - }; - - brg@919f0 { - compatible = "fsl,mpc8555-brg", - "fsl,cpm2-brg", - "fsl,cpm-brg"; - reg = <0x919f0 0x10 0x915f0 0x10>; - }; - - cpmpic: pic@90c00 { - interrupt-controller; - #address-cells = <0>; - #interrupt-cells = <2>; - interrupts = <46 2>; - interrupt-parent = <&mpic>; - reg = <0x90c00 0x80>; - compatible = "fsl,mpc8555-cpm-pic", "fsl,cpm2-pic"; - }; - }; - }; - - pci0: pci@e0008000 { - interrupt-map-mask = <0x1f800 0x0 0x0 0x7>; - interrupt-map = < - - /* IDSEL 0x10 */ - 0x8000 0x0 0x0 0x1 &mpic 0x0 0x1 - 0x8000 0x0 0x0 0x2 &mpic 0x1 0x1 - 0x8000 0x0 0x0 0x3 &mpic 0x2 0x1 - 0x8000 0x0 0x0 0x4 &mpic 0x3 0x1 - - /* IDSEL 0x11 */ - 0x8800 0x0 0x0 0x1 &mpic 0x0 0x1 - 0x8800 0x0 0x0 0x2 &mpic 0x1 0x1 - 0x8800 0x0 0x0 0x3 &mpic 0x2 0x1 - 0x8800 0x0 0x0 0x4 &mpic 0x3 0x1 - - /* IDSEL 0x12 (Slot 1) */ - 0x9000 0x0 0x0 0x1 &mpic 0x0 0x1 - 0x9000 0x0 0x0 0x2 &mpic 0x1 0x1 - 0x9000 0x0 0x0 0x3 &mpic 0x2 0x1 - 0x9000 0x0 0x0 0x4 &mpic 0x3 0x1 - - /* IDSEL 0x13 (Slot 2) */ - 0x9800 0x0 0x0 0x1 &mpic 0x1 0x1 - 0x9800 0x0 0x0 0x2 &mpic 0x2 0x1 - 0x9800 0x0 0x0 0x3 &mpic 0x3 0x1 - 0x9800 0x0 0x0 0x4 &mpic 0x0 0x1 - - /* IDSEL 0x14 (Slot 3) */ - 0xa000 0x0 0x0 0x1 &mpic 0x2 0x1 - 0xa000 0x0 0x0 0x2 &mpic 0x3 0x1 - 0xa000 0x0 0x0 0x3 &mpic 0x0 0x1 - 0xa000 0x0 0x0 0x4 &mpic 0x1 0x1 - - /* IDSEL 0x15 (Slot 4) */ - 0xa800 0x0 0x0 0x1 &mpic 0x3 0x1 - 0xa800 0x0 0x0 0x2 &mpic 0x0 0x1 - 0xa800 0x0 0x0 0x3 &mpic 0x1 0x1 - 0xa800 0x0 0x0 0x4 &mpic 0x2 0x1 - - /* Bus 1 (Tundra Bridge) */ - /* IDSEL 0x12 (ISA bridge) */ - 0x19000 0x0 0x0 0x1 &mpic 0x0 0x1 - 0x19000 0x0 0x0 0x2 &mpic 0x1 0x1 - 0x19000 0x0 0x0 0x3 &mpic 0x2 0x1 - 0x19000 0x0 0x0 0x4 &mpic 0x3 0x1>; - interrupt-parent = <&mpic>; - interrupts = <24 2>; - bus-range = <0 0>; - ranges = <0x2000000 0x0 0x80000000 0x80000000 0x0 0x20000000 - 0x1000000 0x0 0x0 0xe2000000 0x0 0x100000>; - clock-frequency = <66666666>; - #interrupt-cells = <1>; - #size-cells = <2>; - #address-cells = <3>; - reg = <0xe0008000 0x1000>; - compatible = "fsl,mpc8540-pci"; - device_type = "pci"; - - i8259@19000 { - interrupt-controller; - device_type = "interrupt-controller"; - reg = <0x19000 0x0 0x0 0x0 0x1>; - #address-cells = <0>; - #interrupt-cells = <2>; - compatible = "chrp,iic"; - interrupts = <1>; - interrupt-parent = <&pci0>; - }; - }; - - pci1: pci@e0009000 { - interrupt-map-mask = <0xf800 0x0 0x0 0x7>; - interrupt-map = < - - /* IDSEL 0x15 */ - 0xa800 0x0 0x0 0x1 &mpic 0xb 0x1 - 0xa800 0x0 0x0 0x2 &mpic 0xb 0x1 - 0xa800 0x0 0x0 0x3 &mpic 0xb 0x1 - 0xa800 0x0 0x0 0x4 &mpic 0xb 0x1>; - interrupt-parent = <&mpic>; - interrupts = <25 2>; - bus-range = <0 0>; - ranges = <0x2000000 0x0 0xa0000000 0xa0000000 0x0 0x20000000 - 0x1000000 0x0 0x0 0xe3000000 0x0 0x100000>; - clock-frequency = <66666666>; - #interrupt-cells = <1>; - #size-cells = <2>; - #address-cells = <3>; - reg = <0xe0009000 0x1000>; - compatible = "fsl,mpc8540-pci"; - device_type = "pci"; - }; -}; diff --git a/arch/powerpc/boot/dts/fsl/mpc8560ads.dts b/arch/powerpc/boot/dts/fsl/mpc8560ads.dts deleted file mode 100644 index c2f9aea78b29ff3b8e513ab60498292a2d1927bc..0000000000000000000000000000000000000000 --- a/arch/powerpc/boot/dts/fsl/mpc8560ads.dts +++ /dev/null @@ -1,388 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * MPC8560 ADS Device Tree Source - * - * Copyright 2006, 2008 Freescale Semiconductor Inc. - */ - -/dts-v1/; - -/include/ "e500v1_power_isa.dtsi" - -/ { - model = "MPC8560ADS"; - compatible = "MPC8560ADS", "MPC85xxADS"; - #address-cells = <1>; - #size-cells = <1>; - - aliases { - ethernet0 = &enet0; - ethernet1 = &enet1; - ethernet2 = &enet2; - ethernet3 = &enet3; - serial0 = &serial0; - serial1 = &serial1; - pci0 = &pci0; - }; - - cpus { - #address-cells = <1>; - #size-cells = <0>; - - PowerPC,8560@0 { - device_type = "cpu"; - reg = <0x0>; - d-cache-line-size = <32>; // 32 bytes - i-cache-line-size = <32>; // 32 bytes - d-cache-size = <0x8000>; // L1, 32K - i-cache-size = <0x8000>; // L1, 32K - timebase-frequency = <82500000>; - bus-frequency = <330000000>; - clock-frequency = <825000000>; - }; - }; - - memory { - device_type = "memory"; - reg = <0x0 0x10000000>; - }; - - soc8560@e0000000 { - #address-cells = <1>; - #size-cells = <1>; - device_type = "soc"; - compatible = "simple-bus"; - ranges = <0x0 0xe0000000 0x100000>; - bus-frequency = <330000000>; - - ecm-law@0 { - compatible = "fsl,ecm-law"; - reg = <0x0 0x1000>; - fsl,num-laws = <8>; - }; - - ecm@1000 { - compatible = "fsl,mpc8560-ecm", "fsl,ecm"; - reg = <0x1000 0x1000>; - interrupts = <17 2>; - interrupt-parent = <&mpic>; - }; - - memory-controller@2000 { - compatible = "fsl,mpc8540-memory-controller"; - reg = <0x2000 0x1000>; - interrupt-parent = <&mpic>; - interrupts = <18 2>; - }; - - L2: l2-cache-controller@20000 { - compatible = "fsl,mpc8540-l2-cache-controller"; - reg = <0x20000 0x1000>; - cache-line-size = <32>; // 32 bytes - cache-size = <0x40000>; // L2, 256K - interrupt-parent = <&mpic>; - interrupts = <16 2>; - }; - - dma@21300 { - #address-cells = <1>; - #size-cells = <1>; - compatible = "fsl,mpc8560-dma", "fsl,eloplus-dma"; - reg = <0x21300 0x4>; - ranges = <0x0 0x21100 0x200>; - cell-index = <0>; - dma-channel@0 { - compatible = "fsl,mpc8560-dma-channel", - "fsl,eloplus-dma-channel"; - reg = <0x0 0x80>; - cell-index = <0>; - interrupt-parent = <&mpic>; - interrupts = <20 2>; - }; - dma-channel@80 { - compatible = "fsl,mpc8560-dma-channel", - "fsl,eloplus-dma-channel"; - reg = <0x80 0x80>; - cell-index = <1>; - interrupt-parent = <&mpic>; - interrupts = <21 2>; - }; - dma-channel@100 { - compatible = "fsl,mpc8560-dma-channel", - "fsl,eloplus-dma-channel"; - reg = <0x100 0x80>; - cell-index = <2>; - interrupt-parent = <&mpic>; - interrupts = <22 2>; - }; - dma-channel@180 { - compatible = "fsl,mpc8560-dma-channel", - "fsl,eloplus-dma-channel"; - reg = <0x180 0x80>; - cell-index = <3>; - interrupt-parent = <&mpic>; - interrupts = <23 2>; - }; - }; - - enet0: ethernet@24000 { - #address-cells = <1>; - #size-cells = <1>; - cell-index = <0>; - device_type = "network"; - model = "TSEC"; - compatible = "gianfar"; - reg = <0x24000 0x1000>; - ranges = <0x0 0x24000 0x1000>; - local-mac-address = [ 00 00 00 00 00 00 ]; - interrupts = <29 2 30 2 34 2>; - interrupt-parent = <&mpic>; - tbi-handle = <&tbi0>; - phy-handle = <&phy0>; - - mdio@520 { - #address-cells = <1>; - #size-cells = <0>; - compatible = "fsl,gianfar-mdio"; - reg = <0x520 0x20>; - - phy0: ethernet-phy@0 { - interrupt-parent = <&mpic>; - interrupts = <5 1>; - reg = <0x0>; - }; - phy1: ethernet-phy@1 { - interrupt-parent = <&mpic>; - interrupts = <5 1>; - reg = <0x1>; - }; - phy2: ethernet-phy@2 { - interrupt-parent = <&mpic>; - interrupts = <7 1>; - reg = <0x2>; - }; - phy3: ethernet-phy@3 { - interrupt-parent = <&mpic>; - interrupts = <7 1>; - reg = <0x3>; - }; - tbi0: tbi-phy@11 { - reg = <0x11>; - device_type = "tbi-phy"; - }; - }; - }; - - enet1: ethernet@25000 { - #address-cells = <1>; - #size-cells = <1>; - cell-index = <1>; - device_type = "network"; - model = "TSEC"; - compatible = "gianfar"; - reg = <0x25000 0x1000>; - ranges = <0x0 0x25000 0x1000>; - local-mac-address = [ 00 00 00 00 00 00 ]; - interrupts = <35 2 36 2 40 2>; - interrupt-parent = <&mpic>; - tbi-handle = <&tbi1>; - phy-handle = <&phy1>; - - mdio@520 { - #address-cells = <1>; - #size-cells = <0>; - compatible = "fsl,gianfar-tbi"; - reg = <0x520 0x20>; - - tbi1: tbi-phy@11 { - reg = <0x11>; - device_type = "tbi-phy"; - }; - }; - }; - - mpic: pic@40000 { - interrupt-controller; - #address-cells = <0>; - #interrupt-cells = <2>; - reg = <0x40000 0x40000>; - compatible = "chrp,open-pic"; - device_type = "open-pic"; - }; - - cpm@919c0 { - #address-cells = <1>; - #size-cells = <1>; - compatible = "fsl,mpc8560-cpm", "fsl,cpm2"; - reg = <0x919c0 0x30>; - ranges; - - muram@80000 { - #address-cells = <1>; - #size-cells = <1>; - ranges = <0x0 0x80000 0x10000>; - - data@0 { - compatible = "fsl,cpm-muram-data"; - reg = <0x0 0x4000 0x9000 0x2000>; - }; - }; - - brg@919f0 { - compatible = "fsl,mpc8560-brg", - "fsl,cpm2-brg", - "fsl,cpm-brg"; - reg = <0x919f0 0x10 0x915f0 0x10>; - clock-frequency = <165000000>; - }; - - cpmpic: pic@90c00 { - interrupt-controller; - #address-cells = <0>; - #interrupt-cells = <2>; - interrupts = <46 2>; - interrupt-parent = <&mpic>; - reg = <0x90c00 0x80>; - compatible = "fsl,mpc8560-cpm-pic", "fsl,cpm2-pic"; - }; - - serial0: serial@91a00 { - device_type = "serial"; - compatible = "fsl,mpc8560-scc-uart", - "fsl,cpm2-scc-uart"; - reg = <0x91a00 0x20 0x88000 0x100>; - fsl,cpm-brg = <1>; - fsl,cpm-command = <0x800000>; - current-speed = <115200>; - interrupts = <40 8>; - interrupt-parent = <&cpmpic>; - }; - - serial1: serial@91a20 { - device_type = "serial"; - compatible = "fsl,mpc8560-scc-uart", - "fsl,cpm2-scc-uart"; - reg = <0x91a20 0x20 0x88100 0x100>; - fsl,cpm-brg = <2>; - fsl,cpm-command = <0x4a00000>; - current-speed = <115200>; - interrupts = <41 8>; - interrupt-parent = <&cpmpic>; - }; - - enet2: ethernet@91320 { - device_type = "network"; - compatible = "fsl,mpc8560-fcc-enet", - "fsl,cpm2-fcc-enet"; - reg = <0x91320 0x20 0x88500 0x100 0x913b0 0x1>; - local-mac-address = [ 00 00 00 00 00 00 ]; - fsl,cpm-command = <0x16200300>; - interrupts = <33 8>; - interrupt-parent = <&cpmpic>; - phy-handle = <&phy2>; - }; - - enet3: ethernet@91340 { - device_type = "network"; - compatible = "fsl,mpc8560-fcc-enet", - "fsl,cpm2-fcc-enet"; - reg = <0x91340 0x20 0x88600 0x100 0x913d0 0x1>; - local-mac-address = [ 00 00 00 00 00 00 ]; - fsl,cpm-command = <0x1a400300>; - interrupts = <34 8>; - interrupt-parent = <&cpmpic>; - phy-handle = <&phy3>; - }; - }; - }; - - pci0: pci@e0008000 { - #interrupt-cells = <1>; - #size-cells = <2>; - #address-cells = <3>; - compatible = "fsl,mpc8540-pcix", "fsl,mpc8540-pci"; - device_type = "pci"; - reg = <0xe0008000 0x1000>; - clock-frequency = <66666666>; - interrupt-map-mask = <0xf800 0x0 0x0 0x7>; - interrupt-map = < - - /* IDSEL 0x2 */ - 0x1000 0x0 0x0 0x1 &mpic 0x1 0x1 - 0x1000 0x0 0x0 0x2 &mpic 0x2 0x1 - 0x1000 0x0 0x0 0x3 &mpic 0x3 0x1 - 0x1000 0x0 0x0 0x4 &mpic 0x4 0x1 - - /* IDSEL 0x3 */ - 0x1800 0x0 0x0 0x1 &mpic 0x4 0x1 - 0x1800 0x0 0x0 0x2 &mpic 0x1 0x1 - 0x1800 0x0 0x0 0x3 &mpic 0x2 0x1 - 0x1800 0x0 0x0 0x4 &mpic 0x3 0x1 - - /* IDSEL 0x4 */ - 0x2000 0x0 0x0 0x1 &mpic 0x3 0x1 - 0x2000 0x0 0x0 0x2 &mpic 0x4 0x1 - 0x2000 0x0 0x0 0x3 &mpic 0x1 0x1 - 0x2000 0x0 0x0 0x4 &mpic 0x2 0x1 - - /* IDSEL 0x5 */ - 0x2800 0x0 0x0 0x1 &mpic 0x2 0x1 - 0x2800 0x0 0x0 0x2 &mpic 0x3 0x1 - 0x2800 0x0 0x0 0x3 &mpic 0x4 0x1 - 0x2800 0x0 0x0 0x4 &mpic 0x1 0x1 - - /* IDSEL 12 */ - 0x6000 0x0 0x0 0x1 &mpic 0x1 0x1 - 0x6000 0x0 0x0 0x2 &mpic 0x2 0x1 - 0x6000 0x0 0x0 0x3 &mpic 0x3 0x1 - 0x6000 0x0 0x0 0x4 &mpic 0x4 0x1 - - /* IDSEL 13 */ - 0x6800 0x0 0x0 0x1 &mpic 0x4 0x1 - 0x6800 0x0 0x0 0x2 &mpic 0x1 0x1 - 0x6800 0x0 0x0 0x3 &mpic 0x2 0x1 - 0x6800 0x0 0x0 0x4 &mpic 0x3 0x1 - - /* IDSEL 14*/ - 0x7000 0x0 0x0 0x1 &mpic 0x3 0x1 - 0x7000 0x0 0x0 0x2 &mpic 0x4 0x1 - 0x7000 0x0 0x0 0x3 &mpic 0x1 0x1 - 0x7000 0x0 0x0 0x4 &mpic 0x2 0x1 - - /* IDSEL 15 */ - 0x7800 0x0 0x0 0x1 &mpic 0x2 0x1 - 0x7800 0x0 0x0 0x2 &mpic 0x3 0x1 - 0x7800 0x0 0x0 0x3 &mpic 0x4 0x1 - 0x7800 0x0 0x0 0x4 &mpic 0x1 0x1 - - /* IDSEL 18 */ - 0x9000 0x0 0x0 0x1 &mpic 0x1 0x1 - 0x9000 0x0 0x0 0x2 &mpic 0x2 0x1 - 0x9000 0x0 0x0 0x3 &mpic 0x3 0x1 - 0x9000 0x0 0x0 0x4 &mpic 0x4 0x1 - - /* IDSEL 19 */ - 0x9800 0x0 0x0 0x1 &mpic 0x4 0x1 - 0x9800 0x0 0x0 0x2 &mpic 0x1 0x1 - 0x9800 0x0 0x0 0x3 &mpic 0x2 0x1 - 0x9800 0x0 0x0 0x4 &mpic 0x3 0x1 - - /* IDSEL 20 */ - 0xa000 0x0 0x0 0x1 &mpic 0x3 0x1 - 0xa000 0x0 0x0 0x2 &mpic 0x4 0x1 - 0xa000 0x0 0x0 0x3 &mpic 0x1 0x1 - 0xa000 0x0 0x0 0x4 &mpic 0x2 0x1 - - /* IDSEL 21 */ - 0xa800 0x0 0x0 0x1 &mpic 0x2 0x1 - 0xa800 0x0 0x0 0x2 &mpic 0x3 0x1 - 0xa800 0x0 0x0 0x3 &mpic 0x4 0x1 - 0xa800 0x0 0x0 0x4 &mpic 0x1 0x1>; - - interrupt-parent = <&mpic>; - interrupts = <24 2>; - bus-range = <0 0>; - ranges = <0x2000000 0x0 0x80000000 0x80000000 0x0 0x20000000 - 0x1000000 0x0 0x0 0xe2000000 0x0 0x1000000>; - }; -}; diff --git a/arch/powerpc/boot/dts/turris1x.dts b/arch/powerpc/boot/dts/turris1x.dts index 6612160c19d59087650d3bf1684d97a601756edf..dff1ea074d9d995279a9ef73d35d4e74a031831b 100644 --- a/arch/powerpc/boot/dts/turris1x.dts +++ b/arch/powerpc/boot/dts/turris1x.dts @@ -476,12 +476,12 @@ * channel 1 (but only USB 2.0 subset) to USB 2.0 pins on mPCIe * slot 1 (CN5), channels 2 and 3 to connector P600. * - * P2020 PCIe Root Port uses 1MB of PCIe MEM and xHCI controller + * P2020 PCIe Root Port does not use PCIe MEM and xHCI controller * uses 64kB + 8kB of PCIe MEM. No PCIe IO is used or required. - * So allocate 2MB of PCIe MEM for this PCIe bus. + * So allocate 128kB of PCIe MEM for this PCIe bus. */ reg = <0 0xffe08000 0 0x1000>; - ranges = <0x02000000 0x0 0xc0000000 0 0xc0000000 0x0 0x00200000>, /* MEM */ + ranges = <0x02000000 0x0 0xc0000000 0 0xc0000000 0x0 0x00020000>, /* MEM */ <0x01000000 0x0 0x00000000 0 0xffc20000 0x0 0x00010000>; /* IO */ pcie@0 { diff --git a/arch/powerpc/configs/40x/klondike_defconfig b/arch/powerpc/configs/40x/klondike_defconfig index 6a735ee7571592ec05c3a17068d28645c298fb57..acafbb8f680890552d8d65bd69884e85b0fe8068 100644 --- a/arch/powerpc/configs/40x/klondike_defconfig +++ b/arch/powerpc/configs/40x/klondike_defconfig @@ -5,7 +5,6 @@ CONFIG_SYSFS_DEPRECATED=y CONFIG_SYSFS_DEPRECATED_V2=y CONFIG_BLK_DEV_INITRD=y CONFIG_EMBEDDED=y -CONFIG_SLAB=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y CONFIG_APM8018X=y diff --git a/arch/powerpc/configs/52xx/pcm030_defconfig b/arch/powerpc/configs/52xx/pcm030_defconfig index 789622ffd84413238dd82605cd26a20825699d3d..88fbe0d42e11b538c8ba715efc3160976f096733 100644 --- a/arch/powerpc/configs/52xx/pcm030_defconfig +++ b/arch/powerpc/configs/52xx/pcm030_defconfig @@ -10,7 +10,6 @@ CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=14 CONFIG_EXPERT=y # CONFIG_VM_EVENT_COUNTERS is not set -CONFIG_SLAB=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y # CONFIG_BLK_DEV_BSG is not set diff --git a/arch/powerpc/configs/83xx/kmeter1_defconfig b/arch/powerpc/configs/83xx/kmeter1_defconfig index 24bf1bde1bb46dc0cf90d8fb273ca4a2f8922742..487e5e1bbf4c49a0f69b2ef82135e029711c08a0 100644 --- a/arch/powerpc/configs/83xx/kmeter1_defconfig +++ b/arch/powerpc/configs/83xx/kmeter1_defconfig @@ -5,7 +5,6 @@ CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y CONFIG_LOG_BUF_SHIFT=14 CONFIG_EXPERT=y -CONFIG_SLAB=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y # CONFIG_BLK_DEV_BSG is not set diff --git a/arch/powerpc/configs/83xx/mpc837x_rdb_defconfig b/arch/powerpc/configs/83xx/mpc837x_rdb_defconfig index 4e3373381ab6e4cd708b5aed41efa46bcd17d6d4..58fae5131fa7fc6f9d74485f7cb50826adb33f27 100644 --- a/arch/powerpc/configs/83xx/mpc837x_rdb_defconfig +++ b/arch/powerpc/configs/83xx/mpc837x_rdb_defconfig @@ -2,7 +2,6 @@ CONFIG_SYSVIPC=y CONFIG_LOG_BUF_SHIFT=14 CONFIG_BLK_DEV_INITRD=y CONFIG_EXPERT=y -CONFIG_SLAB=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y # CONFIG_BLK_DEV_BSG is not set diff --git a/arch/powerpc/configs/85xx/ge_imp3a_defconfig b/arch/powerpc/configs/85xx/ge_imp3a_defconfig index 6cb7e90d52c1ba750fa71eecdad383c5f2044348..da6fc203e2dc6e43a3ef60185f42fc1b072ed040 100644 --- a/arch/powerpc/configs/85xx/ge_imp3a_defconfig +++ b/arch/powerpc/configs/85xx/ge_imp3a_defconfig @@ -17,7 +17,6 @@ CONFIG_SYSFS_DEPRECATED_V2=y CONFIG_RELAY=y CONFIG_BLK_DEV_INITRD=y CONFIG_PERF_EVENTS=y -CONFIG_SLAB=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y # CONFIG_BLK_DEV_BSG is not set diff --git a/arch/powerpc/configs/85xx/mpc8540_ads_defconfig b/arch/powerpc/configs/85xx/mpc8540_ads_defconfig deleted file mode 100644 index 618e03e0706dd5ad2a4a031b399554df1c991a6a..0000000000000000000000000000000000000000 --- a/arch/powerpc/configs/85xx/mpc8540_ads_defconfig +++ /dev/null @@ -1,47 +0,0 @@ -CONFIG_PPC_85xx=y -CONFIG_SYSVIPC=y -CONFIG_NO_HZ=y -CONFIG_HIGH_RES_TIMERS=y -CONFIG_LOG_BUF_SHIFT=14 -CONFIG_BLK_DEV_INITRD=y -CONFIG_EXPERT=y -# CONFIG_BLK_DEV_BSG is not set -CONFIG_PARTITION_ADVANCED=y -# CONFIG_MSDOS_PARTITION is not set -CONFIG_MPC8540_ADS=y -CONFIG_GEN_RTC=y -CONFIG_BINFMT_MISC=y -CONFIG_MATH_EMULATION=y -# CONFIG_SECCOMP is not set -CONFIG_NET=y -CONFIG_PACKET=y -CONFIG_UNIX=y -CONFIG_XFRM_USER=y -CONFIG_INET=y -CONFIG_IP_MULTICAST=y -CONFIG_IP_PNP=y -CONFIG_IP_PNP_DHCP=y -CONFIG_IP_PNP_BOOTP=y -CONFIG_SYN_COOKIES=y -# CONFIG_IPV6 is not set -# CONFIG_FW_LOADER is not set -CONFIG_BLK_DEV_LOOP=y -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_SIZE=32768 -CONFIG_NETDEVICES=y -CONFIG_GIANFAR=y -# CONFIG_INPUT_KEYBOARD is not set -# CONFIG_INPUT_MOUSE is not set -# CONFIG_SERIO is not set -# CONFIG_VT is not set -CONFIG_SERIAL_8250=y -CONFIG_SERIAL_8250_CONSOLE=y -# CONFIG_HW_RANDOM is not set -CONFIG_EXT2_FS=y -CONFIG_EXT4_FS=y -CONFIG_PROC_KCORE=y -CONFIG_TMPFS=y -CONFIG_NFS_FS=y -CONFIG_ROOT_NFS=y -CONFIG_DETECT_HUNG_TASK=y -CONFIG_DEBUG_MUTEXES=y diff --git a/arch/powerpc/configs/85xx/mpc8560_ads_defconfig b/arch/powerpc/configs/85xx/mpc8560_ads_defconfig deleted file mode 100644 index 9bc6283f2fb223a624f02f145d0f866555399e65..0000000000000000000000000000000000000000 --- a/arch/powerpc/configs/85xx/mpc8560_ads_defconfig +++ /dev/null @@ -1,50 +0,0 @@ -CONFIG_PPC_85xx=y -CONFIG_SYSVIPC=y -CONFIG_LOG_BUF_SHIFT=14 -CONFIG_BLK_DEV_INITRD=y -CONFIG_EXPERT=y -# CONFIG_BLK_DEV_BSG is not set -CONFIG_PARTITION_ADVANCED=y -# CONFIG_MSDOS_PARTITION is not set -CONFIG_MPC8560_ADS=y -CONFIG_GEN_RTC=y -CONFIG_BINFMT_MISC=y -CONFIG_MATH_EMULATION=y -# CONFIG_SECCOMP is not set -CONFIG_PCI=y -CONFIG_PCI_DEBUG=y -CONFIG_NET=y -CONFIG_PACKET=y -CONFIG_UNIX=y -CONFIG_INET=y -CONFIG_IP_MULTICAST=y -CONFIG_IP_PNP=y -CONFIG_IP_PNP_DHCP=y -CONFIG_IP_PNP_BOOTP=y -CONFIG_SYN_COOKIES=y -# CONFIG_IPV6 is not set -# CONFIG_FW_LOADER is not set -CONFIG_BLK_DEV_LOOP=y -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_SIZE=32768 -CONFIG_NETDEVICES=y -CONFIG_FS_ENET=y -# CONFIG_FS_ENET_HAS_SCC is not set -CONFIG_GIANFAR=y -CONFIG_E1000=y -CONFIG_DAVICOM_PHY=y -CONFIG_MARVELL_PHY=y -# CONFIG_INPUT_KEYBOARD is not set -# CONFIG_INPUT_MOUSE is not set -# CONFIG_SERIO is not set -# CONFIG_VT is not set -CONFIG_SERIAL_CPM=y -CONFIG_SERIAL_CPM_CONSOLE=y -CONFIG_EXT2_FS=y -CONFIG_EXT4_FS=y -CONFIG_PROC_KCORE=y -CONFIG_TMPFS=y -CONFIG_NFS_FS=y -CONFIG_ROOT_NFS=y -CONFIG_DETECT_HUNG_TASK=y -CONFIG_DEBUG_MUTEXES=y diff --git a/arch/powerpc/configs/85xx/mpc85xx_cds_defconfig b/arch/powerpc/configs/85xx/mpc85xx_cds_defconfig deleted file mode 100644 index cea72e85ed2614b08d608055b1333e3d4357e6ae..0000000000000000000000000000000000000000 --- a/arch/powerpc/configs/85xx/mpc85xx_cds_defconfig +++ /dev/null @@ -1,52 +0,0 @@ -CONFIG_PPC_85xx=y -CONFIG_SYSVIPC=y -CONFIG_NO_HZ=y -CONFIG_HIGH_RES_TIMERS=y -CONFIG_LOG_BUF_SHIFT=14 -CONFIG_BLK_DEV_INITRD=y -CONFIG_EXPERT=y -# CONFIG_BLK_DEV_BSG is not set -CONFIG_PARTITION_ADVANCED=y -# CONFIG_MSDOS_PARTITION is not set -CONFIG_MPC85xx_CDS=y -CONFIG_GEN_RTC=y -CONFIG_BINFMT_MISC=y -CONFIG_MATH_EMULATION=y -# CONFIG_SECCOMP is not set -CONFIG_PCI=y -CONFIG_NET=y -CONFIG_PACKET=y -CONFIG_UNIX=y -CONFIG_XFRM_USER=y -CONFIG_INET=y -CONFIG_IP_MULTICAST=y -CONFIG_IP_PNP=y -CONFIG_IP_PNP_DHCP=y -CONFIG_IP_PNP_BOOTP=y -CONFIG_SYN_COOKIES=y -# CONFIG_IPV6 is not set -# CONFIG_FW_LOADER is not set -CONFIG_BLK_DEV_LOOP=y -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_SIZE=32768 -CONFIG_ATA=y -CONFIG_ATA_GENERIC=y -CONFIG_PATA_VIA=y -CONFIG_NETDEVICES=y -CONFIG_GIANFAR=y -CONFIG_E1000=y -# CONFIG_INPUT_KEYBOARD is not set -# CONFIG_INPUT_MOUSE is not set -# CONFIG_SERIO is not set -# CONFIG_VT is not set -CONFIG_SERIAL_8250=y -CONFIG_SERIAL_8250_CONSOLE=y -# CONFIG_HW_RANDOM is not set -CONFIG_EXT2_FS=y -CONFIG_EXT4_FS=y -CONFIG_PROC_KCORE=y -CONFIG_TMPFS=y -CONFIG_NFS_FS=y -CONFIG_ROOT_NFS=y -CONFIG_DETECT_HUNG_TASK=y -CONFIG_DEBUG_MUTEXES=y diff --git a/arch/powerpc/configs/ep8248e_defconfig b/arch/powerpc/configs/ep8248e_defconfig index 8df6d3a293e3c51cbc25dddef58d0dd6b3d4a676..b9dfa3a0713b4d04d45f9ab9d4e0a6174fcb8422 100644 --- a/arch/powerpc/configs/ep8248e_defconfig +++ b/arch/powerpc/configs/ep8248e_defconfig @@ -4,7 +4,6 @@ CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=14 CONFIG_EXPERT=y CONFIG_KALLSYMS_ALL=y -CONFIG_SLAB=y CONFIG_PARTITION_ADVANCED=y # CONFIG_PPC_CHRP is not set # CONFIG_PPC_PMAC is not set diff --git a/arch/powerpc/configs/gamecube_defconfig b/arch/powerpc/configs/gamecube_defconfig index 91a1b99f4e8fd76705050e52cd97d421448c141d..d77eeb525366a3cde254e52b3897c3c7cf23dc3b 100644 --- a/arch/powerpc/configs/gamecube_defconfig +++ b/arch/powerpc/configs/gamecube_defconfig @@ -8,7 +8,6 @@ CONFIG_EXPERT=y # CONFIG_ELF_CORE is not set CONFIG_PERF_EVENTS=y # CONFIG_VM_EVENT_COUNTERS is not set -CONFIG_SLAB=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y # CONFIG_BLK_DEV_BSG is not set diff --git a/arch/powerpc/configs/mgcoge_defconfig b/arch/powerpc/configs/mgcoge_defconfig index 498d35db78331715630f0fdf395c1623fcc41005..ce220ceeb91c8f22a7af3d892ca60fb715a8d06a 100644 --- a/arch/powerpc/configs/mgcoge_defconfig +++ b/arch/powerpc/configs/mgcoge_defconfig @@ -10,7 +10,6 @@ CONFIG_BLK_DEV_INITRD=y CONFIG_KALLSYMS_ALL=y # CONFIG_PCSPKR_PLATFORM is not set CONFIG_EMBEDDED=y -CONFIG_SLAB=y CONFIG_PARTITION_ADVANCED=y # CONFIG_PPC_PMAC is not set CONFIG_PPC_82xx=y diff --git a/arch/powerpc/configs/mpc512x_defconfig b/arch/powerpc/configs/mpc512x_defconfig index 10fe061c5e6d13b1f6cce7c5515c2ac878c1e654..d24457bc57916a31a0cdc4576fd56c07a04a99f6 100644 --- a/arch/powerpc/configs/mpc512x_defconfig +++ b/arch/powerpc/configs/mpc512x_defconfig @@ -4,7 +4,6 @@ CONFIG_NO_HZ=y CONFIG_LOG_BUF_SHIFT=16 CONFIG_BLK_DEV_INITRD=y # CONFIG_COMPAT_BRK is not set -CONFIG_SLAB=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y # CONFIG_BLK_DEV_BSG is not set diff --git a/arch/powerpc/configs/mpc83xx_defconfig b/arch/powerpc/configs/mpc83xx_defconfig index 8779f03bced1e93090f1719f054abbb31b09d4a8..83c4710017e949c358f3ba8b73f5c1873cfd10f8 100644 --- a/arch/powerpc/configs/mpc83xx_defconfig +++ b/arch/powerpc/configs/mpc83xx_defconfig @@ -2,7 +2,6 @@ CONFIG_SYSVIPC=y CONFIG_LOG_BUF_SHIFT=14 CONFIG_BLK_DEV_INITRD=y CONFIG_EXPERT=y -CONFIG_SLAB=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y # CONFIG_BLK_DEV_BSG is not set diff --git a/arch/powerpc/configs/mpc85xx_base.config b/arch/powerpc/configs/mpc85xx_base.config index 85907b7769084d110d4c156a9e64858fefd7bfc0..a1e4d72ed39de519084be323e3ef36c30cf5f917 100644 --- a/arch/powerpc/configs/mpc85xx_base.config +++ b/arch/powerpc/configs/mpc85xx_base.config @@ -1,8 +1,5 @@ CONFIG_MATH_EMULATION=y CONFIG_MPC8536_DS=y -CONFIG_MPC8540_ADS=y -CONFIG_MPC8560_ADS=y -CONFIG_MPC85xx_CDS=y CONFIG_MPC85xx_DS=y CONFIG_MPC85xx_MDS=y CONFIG_MPC85xx_RDB=y diff --git a/arch/powerpc/configs/ps3_defconfig b/arch/powerpc/configs/ps3_defconfig index 52a8c5450ecba0039dbf3e0119710c072c0eee08..ea3ee0719bb258bef751a5ed7ef54f75b915c8c6 100644 --- a/arch/powerpc/configs/ps3_defconfig +++ b/arch/powerpc/configs/ps3_defconfig @@ -33,7 +33,6 @@ CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set CONFIG_BINFMT_MISC=y -CONFIG_SLAB=y # CONFIG_COMPAT_BRK is not set # CONFIG_SPARSEMEM_VMEMMAP is not set # CONFIG_COMPACTION is not set diff --git a/arch/powerpc/configs/wii_defconfig b/arch/powerpc/configs/wii_defconfig index 0ab78c51455d3b4aff920751e694292c131087f0..5017a697b67bc3e453c54143b120caecc3d2fa1e 100644 --- a/arch/powerpc/configs/wii_defconfig +++ b/arch/powerpc/configs/wii_defconfig @@ -9,7 +9,6 @@ CONFIG_EXPERT=y # CONFIG_ELF_CORE is not set CONFIG_PERF_EVENTS=y # CONFIG_VM_EVENT_COUNTERS is not set -CONFIG_SLAB=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y # CONFIG_PPC_CHRP is not set diff --git a/arch/powerpc/include/asm/atomic.h b/arch/powerpc/include/asm/atomic.h index 47228b17747811160b7c5dcd3cf5e98a31cf8aba..5bf6a4d49268c702a67c42f15c4a750d12fa565b 100644 --- a/arch/powerpc/include/asm/atomic.h +++ b/arch/powerpc/include/asm/atomic.h @@ -126,18 +126,6 @@ ATOMIC_OPS(xor, xor, "", K) #undef ATOMIC_OP_RETURN_RELAXED #undef ATOMIC_OP -#define arch_atomic_cmpxchg(v, o, n) \ - (arch_cmpxchg(&((v)->counter), (o), (n))) -#define arch_atomic_cmpxchg_relaxed(v, o, n) \ - arch_cmpxchg_relaxed(&((v)->counter), (o), (n)) -#define arch_atomic_cmpxchg_acquire(v, o, n) \ - arch_cmpxchg_acquire(&((v)->counter), (o), (n)) - -#define arch_atomic_xchg(v, new) \ - (arch_xchg(&((v)->counter), new)) -#define arch_atomic_xchg_relaxed(v, new) \ - arch_xchg_relaxed(&((v)->counter), (new)) - /** * atomic_fetch_add_unless - add unless the number is a given value * @v: pointer of type atomic_t @@ -396,18 +384,6 @@ static __inline__ s64 arch_atomic64_dec_if_positive(atomic64_t *v) } #define arch_atomic64_dec_if_positive arch_atomic64_dec_if_positive -#define arch_atomic64_cmpxchg(v, o, n) \ - (arch_cmpxchg(&((v)->counter), (o), (n))) -#define arch_atomic64_cmpxchg_relaxed(v, o, n) \ - arch_cmpxchg_relaxed(&((v)->counter), (o), (n)) -#define arch_atomic64_cmpxchg_acquire(v, o, n) \ - arch_cmpxchg_acquire(&((v)->counter), (o), (n)) - -#define arch_atomic64_xchg(v, new) \ - (arch_xchg(&((v)->counter), new)) -#define arch_atomic64_xchg_relaxed(v, new) \ - arch_xchg_relaxed(&((v)->counter), (new)) - /** * atomic64_fetch_add_unless - add unless the number is a given value * @v: pointer of type atomic64_t diff --git a/arch/powerpc/include/asm/book3s/64/hash-4k.h b/arch/powerpc/include/asm/book3s/64/hash-4k.h index b6ac4f86c87b44b619681a2c7909c4a3fa7f0f0b..6472b08fa1b0cd6de6a962ced58234844e5ad28e 100644 --- a/arch/powerpc/include/asm/book3s/64/hash-4k.h +++ b/arch/powerpc/include/asm/book3s/64/hash-4k.h @@ -136,12 +136,6 @@ static inline int hash__pmd_trans_huge(pmd_t pmd) return 0; } -static inline int hash__pmd_same(pmd_t pmd_a, pmd_t pmd_b) -{ - BUG(); - return 0; -} - static inline pmd_t hash__pmd_mkhuge(pmd_t pmd) { BUG(); diff --git a/arch/powerpc/include/asm/book3s/64/hash-64k.h b/arch/powerpc/include/asm/book3s/64/hash-64k.h index 338e62fbea0bb1dc30f984d4168c853689315e03..0bf6fd0bf42ae290b4c9982aadc388cfc4580dbc 100644 --- a/arch/powerpc/include/asm/book3s/64/hash-64k.h +++ b/arch/powerpc/include/asm/book3s/64/hash-64k.h @@ -263,11 +263,6 @@ static inline int hash__pmd_trans_huge(pmd_t pmd) (_PAGE_PTE | H_PAGE_THP_HUGE)); } -static inline int hash__pmd_same(pmd_t pmd_a, pmd_t pmd_b) -{ - return (((pmd_raw(pmd_a) ^ pmd_raw(pmd_b)) & ~cpu_to_be64(_PAGE_HPTEFLAGS)) == 0); -} - static inline pmd_t hash__pmd_mkhuge(pmd_t pmd) { return __pmd(pmd_val(pmd) | (_PAGE_PTE | H_PAGE_THP_HUGE)); diff --git a/arch/powerpc/include/asm/book3s/64/hash.h b/arch/powerpc/include/asm/book3s/64/hash.h index 17e7a778c856c3bd6b33bd500db88f80f6d4b7b0..d4a19e6547acf6edbd22ac1bbc0e5fc545346c05 100644 --- a/arch/powerpc/include/asm/book3s/64/hash.h +++ b/arch/powerpc/include/asm/book3s/64/hash.h @@ -132,6 +132,11 @@ static inline int get_region_id(unsigned long ea) return region_id; } +static inline int hash__pmd_same(pmd_t pmd_a, pmd_t pmd_b) +{ + return (((pmd_raw(pmd_a) ^ pmd_raw(pmd_b)) & ~cpu_to_be64(_PAGE_HPTEFLAGS)) == 0); +} + #define hash__pmd_bad(pmd) (pmd_val(pmd) & H_PMD_BAD_BITS) #define hash__pud_bad(pud) (pud_val(pud) & H_PUD_BAD_BITS) static inline int hash__p4d_bad(p4d_t p4d) diff --git a/arch/powerpc/include/asm/book3s/64/kexec.h b/arch/powerpc/include/asm/book3s/64/kexec.h index d4b9d476ecba272eafbd9e94edcdb4e24ede18d0..df37a76c1e9f3286f6468fc4dc44ed3fa1f17e17 100644 --- a/arch/powerpc/include/asm/book3s/64/kexec.h +++ b/arch/powerpc/include/asm/book3s/64/kexec.h @@ -21,6 +21,11 @@ static inline void reset_sprs(void) plpar_set_ciabr(0); } + if (cpu_has_feature(CPU_FTR_ARCH_31)) { + mtspr(SPRN_DEXCR, 0); + mtspr(SPRN_HASHKEYR, 0); + } + /* Do we need isync()? We are going via a kexec reset */ isync(); } diff --git a/arch/powerpc/include/asm/book3s/64/kup.h b/arch/powerpc/include/asm/book3s/64/kup.h index 54cf46808157c1a544899d0f4c5a0b9428f1fd54..84c09e546115a7da6c3a4521d16c4ca2003c057a 100644 --- a/arch/powerpc/include/asm/book3s/64/kup.h +++ b/arch/powerpc/include/asm/book3s/64/kup.h @@ -194,6 +194,7 @@ #else /* !__ASSEMBLY__ */ #include +#include DECLARE_STATIC_KEY_FALSE(uaccess_flush_key); diff --git a/arch/powerpc/include/asm/bugs.h b/arch/powerpc/include/asm/bugs.h deleted file mode 100644 index 01b8f6ca4dbbcd98cebc2928783896efd508fe72..0000000000000000000000000000000000000000 --- a/arch/powerpc/include/asm/bugs.h +++ /dev/null @@ -1,15 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -#ifndef _ASM_POWERPC_BUGS_H -#define _ASM_POWERPC_BUGS_H - -/* - */ - -/* - * This file is included by 'init/main.c' to check for - * architecture-dependent bugs. - */ - -static inline void check_bugs(void) { } - -#endif /* _ASM_POWERPC_BUGS_H */ diff --git a/arch/powerpc/include/asm/cache.h b/arch/powerpc/include/asm/cache.h index ae0a68a838e8ad0390002ebce392f28c1ff121ff..69232231d270808aa69c37219cd5c2ab3161c98d 100644 --- a/arch/powerpc/include/asm/cache.h +++ b/arch/powerpc/include/asm/cache.h @@ -33,6 +33,10 @@ #define IFETCH_ALIGN_BYTES (1 << IFETCH_ALIGN_SHIFT) +#ifdef CONFIG_NOT_COHERENT_CACHE +#define ARCH_DMA_MINALIGN L1_CACHE_BYTES +#endif + #if !defined(__ASSEMBLY__) #ifdef CONFIG_PPC64 diff --git a/arch/powerpc/include/asm/cputable.h b/arch/powerpc/include/asm/cputable.h index 757dbded11dcfa3c9de381cb10ee49821091f5ba..443a9d482b1524f6b9ee815284e5a76d41b95b96 100644 --- a/arch/powerpc/include/asm/cputable.h +++ b/arch/powerpc/include/asm/cputable.h @@ -192,6 +192,7 @@ static inline void cpu_feature_keys_init(void) { } #define CPU_FTR_P9_RADIX_PREFETCH_BUG LONG_ASM_CONST(0x0002000000000000) #define CPU_FTR_ARCH_31 LONG_ASM_CONST(0x0004000000000000) #define CPU_FTR_DAWR1 LONG_ASM_CONST(0x0008000000000000) +#define CPU_FTR_DEXCR_NPHIE LONG_ASM_CONST(0x0010000000000000) #ifndef __ASSEMBLY__ @@ -451,7 +452,8 @@ static inline void cpu_feature_keys_init(void) { } CPU_FTR_CFAR | CPU_FTR_HVMODE | CPU_FTR_VMX_COPY | \ CPU_FTR_DBELL | CPU_FTR_HAS_PPR | CPU_FTR_ARCH_207S | \ CPU_FTR_ARCH_300 | CPU_FTR_ARCH_31 | \ - CPU_FTR_DAWR | CPU_FTR_DAWR1) + CPU_FTR_DAWR | CPU_FTR_DAWR1 | \ + CPU_FTR_DEXCR_NPHIE) #define CPU_FTRS_CELL (CPU_FTR_LWSYNC | \ CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \ CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT | \ diff --git a/arch/powerpc/include/asm/elf.h b/arch/powerpc/include/asm/elf.h index 79f1c480b5eb2fe6e3266c46fe8c232226693ddd..a26ca097d032d6c955c20de681d3a0a5983d900f 100644 --- a/arch/powerpc/include/asm/elf.h +++ b/arch/powerpc/include/asm/elf.h @@ -12,8 +12,14 @@ /* * This is used to ensure we don't load something for the wrong architecture. + * 64le only supports ELFv2 64-bit binaries (64be supports v1 and v2). */ +#if defined(CONFIG_PPC64) && defined(CONFIG_CPU_LITTLE_ENDIAN) +#define elf_check_arch(x) (((x)->e_machine == ELF_ARCH) && \ + (((x)->e_flags & 0x3) == 0x2)) +#else #define elf_check_arch(x) ((x)->e_machine == ELF_ARCH) +#endif #define compat_elf_check_arch(x) ((x)->e_machine == EM_PPC) #define CORE_DUMP_USE_REGSET diff --git a/arch/powerpc/include/asm/irq.h b/arch/powerpc/include/asm/irq.h index deadd2149426a44b3f1feacdce9643e401de138f..f257cacb49a9c2fc9fc577abf4049a93da076ed7 100644 --- a/arch/powerpc/include/asm/irq.h +++ b/arch/powerpc/include/asm/irq.h @@ -50,9 +50,14 @@ extern void *hardirq_ctx[NR_CPUS]; extern void *softirq_ctx[NR_CPUS]; void __do_IRQ(struct pt_regs *regs); -extern void __init init_IRQ(void); int irq_choose_cpu(const struct cpumask *mask); +#if defined(CONFIG_PPC_BOOK3S_64) && defined(CONFIG_NMI_IPI) +extern void arch_trigger_cpumask_backtrace(const cpumask_t *mask, + bool exclude_self); +#define arch_trigger_cpumask_backtrace arch_trigger_cpumask_backtrace +#endif + #endif /* _ASM_IRQ_H */ #endif /* __KERNEL__ */ diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h index 79a9c0bb8bba9ca51ad5ec2e7f7c71c151a93056..d16d80ad2ae42f37749a62a64eb2c6aeab693f44 100644 --- a/arch/powerpc/include/asm/kvm_ppc.h +++ b/arch/powerpc/include/asm/kvm_ppc.h @@ -548,12 +548,12 @@ static inline void kvmppc_set_host_ipi(int cpu) * pairs with the barrier in kvmppc_clear_host_ipi() */ smp_mb(); - paca_ptrs[cpu]->kvm_hstate.host_ipi = 1; + WRITE_ONCE(paca_ptrs[cpu]->kvm_hstate.host_ipi, 1); } static inline void kvmppc_clear_host_ipi(int cpu) { - paca_ptrs[cpu]->kvm_hstate.host_ipi = 0; + WRITE_ONCE(paca_ptrs[cpu]->kvm_hstate.host_ipi, 0); /* * order clearing of host_ipi flag vs. processing of IPI messages * diff --git a/arch/powerpc/include/asm/mpc52xx.h b/arch/powerpc/include/asm/mpc52xx.h index 5ea16a71c2f0501fcbc780eff43c70de7e025acb..01ae6c351e5028731979e715c7777583805fc3ae 100644 --- a/arch/powerpc/include/asm/mpc52xx.h +++ b/arch/powerpc/include/asm/mpc52xx.h @@ -285,47 +285,6 @@ extern int mpc52xx_gpt_start_timer(struct mpc52xx_gpt_priv *gpt, u64 period, extern u64 mpc52xx_gpt_timer_period(struct mpc52xx_gpt_priv *gpt); extern int mpc52xx_gpt_stop_timer(struct mpc52xx_gpt_priv *gpt); -/* mpc52xx_lpbfifo.c */ -#define MPC52XX_LPBFIFO_FLAG_READ (0) -#define MPC52XX_LPBFIFO_FLAG_WRITE (1<<0) -#define MPC52XX_LPBFIFO_FLAG_NO_INCREMENT (1<<1) -#define MPC52XX_LPBFIFO_FLAG_NO_DMA (1<<2) -#define MPC52XX_LPBFIFO_FLAG_POLL_DMA (1<<3) - -struct mpc52xx_lpbfifo_request { - struct list_head list; - - /* localplus bus address */ - unsigned int cs; - size_t offset; - - /* Memory address */ - void *data; - phys_addr_t data_phys; - - /* Details of transfer */ - size_t size; - size_t pos; /* current position of transfer */ - int flags; - int defer_xfer_start; - - /* What to do when finished */ - void (*callback)(struct mpc52xx_lpbfifo_request *); - - void *priv; /* Driver private data */ - - /* statistics */ - int irq_count; - int irq_ticks; - u8 last_byte; - int buffer_not_done_cnt; -}; - -extern int mpc52xx_lpbfifo_submit(struct mpc52xx_lpbfifo_request *req); -extern void mpc52xx_lpbfifo_abort(struct mpc52xx_lpbfifo_request *req); -extern void mpc52xx_lpbfifo_poll(void); -extern int mpc52xx_lpbfifo_start_xfer(struct mpc52xx_lpbfifo_request *req); - /* mpc52xx_pic.c */ extern void mpc52xx_init_irq(void); extern unsigned int mpc52xx_get_irq(void); diff --git a/arch/powerpc/include/asm/nmi.h b/arch/powerpc/include/asm/nmi.h index c3c7adef74de0605a795d278121712dbf51f47c3..49a75340c3e07f37d4e1c344f63a191476f164aa 100644 --- a/arch/powerpc/include/asm/nmi.h +++ b/arch/powerpc/include/asm/nmi.h @@ -3,18 +3,10 @@ #define _ASM_NMI_H #ifdef CONFIG_PPC_WATCHDOG -extern void arch_touch_nmi_watchdog(void); long soft_nmi_interrupt(struct pt_regs *regs); -void watchdog_nmi_set_timeout_pct(u64 pct); +void watchdog_hardlockup_set_timeout_pct(u64 pct); #else -static inline void arch_touch_nmi_watchdog(void) {} -static inline void watchdog_nmi_set_timeout_pct(u64 pct) {} -#endif - -#ifdef CONFIG_NMI_IPI -extern void arch_trigger_cpumask_backtrace(const cpumask_t *mask, - bool exclude_self); -#define arch_trigger_cpumask_backtrace arch_trigger_cpumask_backtrace +static inline void watchdog_hardlockup_set_timeout_pct(u64 pct) {} #endif extern void hv_nmi_check_nonrecoverable(struct pt_regs *regs); diff --git a/arch/powerpc/include/asm/opal.h b/arch/powerpc/include/asm/opal.h index 726125a534de80817fdd0e99742477ae704b0e69..a9b31cc258fcb31330177b66236912bac574e38c 100644 --- a/arch/powerpc/include/asm/opal.h +++ b/arch/powerpc/include/asm/opal.h @@ -112,9 +112,6 @@ int64_t opal_pci_set_pe(uint64_t phb_id, uint64_t pe_number, uint64_t bus_dev_fu uint8_t pe_action); int64_t opal_pci_set_peltv(uint64_t phb_id, uint32_t parent_pe, uint32_t child_pe, uint8_t state); -int64_t opal_pci_set_mve(uint64_t phb_id, uint32_t mve_number, uint32_t pe_number); -int64_t opal_pci_set_mve_enable(uint64_t phb_id, uint32_t mve_number, - uint32_t state); int64_t opal_pci_get_xive_reissue(uint64_t phb_id, uint32_t xive_number, uint8_t *p_bit, uint8_t *q_bit); int64_t opal_pci_set_xive_reissue(uint64_t phb_id, uint32_t xive_number, diff --git a/arch/powerpc/include/asm/paca.h b/arch/powerpc/include/asm/paca.h index da0377f465973786ae9d955a857af9b0d482ec7b..cb325938766a5db0297fe8dfaa9da3b654f6962f 100644 --- a/arch/powerpc/include/asm/paca.h +++ b/arch/powerpc/include/asm/paca.h @@ -191,6 +191,7 @@ struct paca_struct { #ifdef CONFIG_PPC_POWERNV /* PowerNV idle fields */ /* PNV_CORE_IDLE_* bits, all siblings work on thread 0 paca */ + unsigned long idle_lock; /* A value of 1 means acquired */ unsigned long idle_state; union { /* P7/P8 specific fields */ diff --git a/arch/powerpc/include/asm/page_32.h b/arch/powerpc/include/asm/page_32.h index 56f21760632749dae8f94b74289d02f138501036..b9ac9e3a771cbbad12a9ed27ece0238a9b77b524 100644 --- a/arch/powerpc/include/asm/page_32.h +++ b/arch/powerpc/include/asm/page_32.h @@ -12,10 +12,6 @@ #define VM_DATA_DEFAULT_FLAGS VM_DATA_DEFAULT_FLAGS32 -#ifdef CONFIG_NOT_COHERENT_CACHE -#define ARCH_DMA_MINALIGN L1_CACHE_BYTES -#endif - #if defined(CONFIG_PPC_256K_PAGES) || \ (defined(CONFIG_PPC_8xx) && defined(CONFIG_PPC_16K_PAGES)) #define PTE_SHIFT (PAGE_SHIFT - PTE_T_LOG2 - 2) /* 1/4 of a page */ diff --git a/arch/powerpc/include/asm/pgtable.h b/arch/powerpc/include/asm/pgtable.h index 9972626ddaf68e3c5d8d2dbd36d8fa8ff7dfd6cd..6a88bfdaa69b6f586152d653294c7fa26ca65bc8 100644 --- a/arch/powerpc/include/asm/pgtable.h +++ b/arch/powerpc/include/asm/pgtable.h @@ -165,9 +165,6 @@ static inline bool is_ioremap_addr(const void *x) return addr >= IOREMAP_BASE && addr < IOREMAP_END; } - -struct seq_file; -void arch_report_meminfo(struct seq_file *m); #endif /* CONFIG_PPC64 */ #endif /* __ASSEMBLY__ */ diff --git a/arch/powerpc/include/asm/ppc-opcode.h b/arch/powerpc/include/asm/ppc-opcode.h index ca5a0da7df4e533318eae617f36b40d71735ed65..ef6972aa33b92ace1658405427397304576c2107 100644 --- a/arch/powerpc/include/asm/ppc-opcode.h +++ b/arch/powerpc/include/asm/ppc-opcode.h @@ -222,6 +222,7 @@ #define OP_31_XOP_STFSX 663 #define OP_31_XOP_STFSUX 695 #define OP_31_XOP_STFDX 727 +#define OP_31_XOP_HASHCHK 754 #define OP_31_XOP_STFDUX 759 #define OP_31_XOP_LHBRX 790 #define OP_31_XOP_LFIWAX 855 diff --git a/arch/powerpc/include/asm/ppc_asm.h b/arch/powerpc/include/asm/ppc_asm.h index 5f05a984b10330afd7c44cb4d994df985213bd97..e7792aa135105ab00f7a563c0520b093845eb330 100644 --- a/arch/powerpc/include/asm/ppc_asm.h +++ b/arch/powerpc/include/asm/ppc_asm.h @@ -406,6 +406,15 @@ GLUE(.,name): /* offsets for stack frame layout */ #define LRSAVE 16 +/* + * GCC stack frames follow a different pattern on 32 vs 64. This can be used + * to make asm frames be consistent with C. + */ +#define PPC_CREATE_STACK_FRAME(size) \ + mflr r0; \ + std r0,16(r1); \ + stdu r1,-(size)(r1) + #else /* 32-bit */ #define LOAD_REG_IMMEDIATE(reg, expr) __LOAD_REG_IMMEDIATE_32 reg, expr @@ -422,6 +431,11 @@ GLUE(.,name): /* offsets for stack frame layout */ #define LRSAVE 4 +#define PPC_CREATE_STACK_FRAME(size) \ + stwu r1,-(size)(r1); \ + mflr r0; \ + stw r0,(size+4)(r1) + #endif /* various errata or part fixups */ diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h index e96c9b8c2a60bdac9fb2a833c48bf241a21fa4c7..8a6754ffdc7ea1b77eef1e2d7775b420fda4e624 100644 --- a/arch/powerpc/include/asm/processor.h +++ b/arch/powerpc/include/asm/processor.h @@ -264,6 +264,7 @@ struct thread_struct { unsigned long mmcr3; unsigned long sier2; unsigned long sier3; + unsigned long hashkeyr; #endif }; diff --git a/arch/powerpc/include/asm/ptrace.h b/arch/powerpc/include/asm/ptrace.h index 0eb90a0133466690b6286b53589a4e480af15494..9db8b16567e22b486a7d7b10f965708d0ee4f1e4 100644 --- a/arch/powerpc/include/asm/ptrace.h +++ b/arch/powerpc/include/asm/ptrace.h @@ -180,8 +180,8 @@ void do_syscall_trace_leave(struct pt_regs *regs); static inline void set_return_regs_changed(void) { #ifdef CONFIG_PPC_BOOK3S_64 - local_paca->hsrr_valid = 0; - local_paca->srr_valid = 0; + WRITE_ONCE(local_paca->hsrr_valid, 0); + WRITE_ONCE(local_paca->srr_valid, 0); #endif } diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h index 6372e5f55ef02bffabfc3a31f35c074ac9961dc0..bb0121222ee3c4ef4939c64e977cc80a8a77cb3d 100644 --- a/arch/powerpc/include/asm/reg.h +++ b/arch/powerpc/include/asm/reg.h @@ -382,7 +382,17 @@ #define SPRN_HIOR 0x137 /* 970 Hypervisor interrupt offset */ #define SPRN_RMOR 0x138 /* Real mode offset register */ #define SPRN_HRMOR 0x139 /* Real mode offset register */ +#define SPRN_HDEXCR_RO 0x1C7 /* Hypervisor DEXCR (non-privileged, readonly) */ +#define SPRN_HASHKEYR 0x1D4 /* Non-privileged hashst/hashchk key register */ +#define SPRN_HDEXCR 0x1D7 /* Hypervisor dynamic execution control register */ +#define SPRN_DEXCR_RO 0x32C /* DEXCR (non-privileged, readonly) */ #define SPRN_ASDR 0x330 /* Access segment descriptor register */ +#define SPRN_DEXCR 0x33C /* Dynamic execution control register */ +#define DEXCR_PR_SBHE 0x80000000UL /* 0: Speculative Branch Hint Enable */ +#define DEXCR_PR_IBRTPD 0x10000000UL /* 3: Indirect Branch Recurrent Target Prediction Disable */ +#define DEXCR_PR_SRAPD 0x08000000UL /* 4: Subroutine Return Address Prediction Disable */ +#define DEXCR_PR_NPHIE 0x04000000UL /* 5: Non-Privileged Hash Instruction Enable */ +#define DEXCR_INIT DEXCR_PR_NPHIE /* Fixed DEXCR value to initialise all CPUs with */ #define SPRN_IC 0x350 /* Virtual Instruction Count */ #define SPRN_VTB 0x351 /* Virtual Time Base */ #define SPRN_LDBAR 0x352 /* LD Base Address Register */ diff --git a/arch/powerpc/include/asm/simple_spinlock.h b/arch/powerpc/include/asm/simple_spinlock.h index 9dcc7e9993b9006c9ead372479133aa288b668f7..4dd12dcb9ef8c91b398fb59b4019b11a6777d22c 100644 --- a/arch/powerpc/include/asm/simple_spinlock.h +++ b/arch/powerpc/include/asm/simple_spinlock.h @@ -15,6 +15,7 @@ * (the type definitions are in asm/simple_spinlock_types.h) */ #include +#include #include #include #include @@ -126,6 +127,7 @@ static inline void arch_spin_lock(arch_spinlock_t *lock) static inline void arch_spin_unlock(arch_spinlock_t *lock) { + kcsan_mb(); __asm__ __volatile__("# arch_spin_unlock\n\t" PPC_RELEASE_BARRIER: : :"memory"); lock->slock = 0; diff --git a/arch/powerpc/include/asm/thread_info.h b/arch/powerpc/include/asm/thread_info.h index bf5dde1a411471fcc95d4503dfb41d3881aad9fe..bc5d39a835fe44542dd95e10dd7bc05ef9c33d4a 100644 --- a/arch/powerpc/include/asm/thread_info.h +++ b/arch/powerpc/include/asm/thread_info.h @@ -183,9 +183,13 @@ static inline bool test_thread_local_flags(unsigned int flags) #define clear_tsk_compat_task(tsk) do { } while (0) #endif -#if defined(CONFIG_PPC64) +#ifdef CONFIG_PPC64 +#ifdef CONFIG_CPU_BIG_ENDIAN #define is_elf2_task() (test_thread_flag(TIF_ELF2ABI)) #else +#define is_elf2_task() (1) +#endif +#else #define is_elf2_task() (0) #endif diff --git a/arch/powerpc/include/uapi/asm/elf.h b/arch/powerpc/include/uapi/asm/elf.h index dbc4a5b8d02d0682ff4aa4d232166f0a6e870740..a5377f494fa316f62821a27ce1c32fede4c0507d 100644 --- a/arch/powerpc/include/uapi/asm/elf.h +++ b/arch/powerpc/include/uapi/asm/elf.h @@ -98,6 +98,8 @@ #define ELF_NEBB 3 /* includes ebbrr, ebbhr, bescr */ #define ELF_NPMU 5 /* includes siar, sdar, sier, mmcr2, mmcr0 */ #define ELF_NPKEY 3 /* includes amr, iamr, uamor */ +#define ELF_NDEXCR 2 /* includes dexcr, hdexcr */ +#define ELF_NHASHKEYR 1 /* includes hashkeyr */ typedef unsigned long elf_greg_t64; typedef elf_greg_t64 elf_gregset_t64[ELF_NGREG]; diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile index 9bf2be123093314b46af843ccc85f716ab8c557b..2919433be35574eb26e687b637c19e2529e88055 100644 --- a/arch/powerpc/kernel/Makefile +++ b/arch/powerpc/kernel/Makefile @@ -68,7 +68,7 @@ CFLAGS_REMOVE_syscall.o = -fstack-protector -fstack-protector-strong CFLAGS_syscall.o += -fno-stack-protector #endif -obj-y := cputable.o syscalls.o \ +obj-y := cputable.o syscalls.o switch.o \ irq.o align.o signal_$(BITS).o pmc.o vdso.o \ process.o systbl.o idle.o \ signal.o sysfs.o cacheinfo.o time.o \ @@ -165,9 +165,6 @@ endif obj64-$(CONFIG_PPC_TRANSACTIONAL_MEM) += tm.o -obj-$(CONFIG_PPC64) += $(obj64-y) -obj-$(CONFIG_PPC32) += $(obj32-y) - ifneq ($(CONFIG_XMON)$(CONFIG_KEXEC_CORE)(CONFIG_PPC_BOOK3S),) obj-y += ppc_save_regs.o endif @@ -209,10 +206,13 @@ CFLAGS_paca.o += -fno-stack-protector obj-$(CONFIG_PPC_FPU) += fpu.o obj-$(CONFIG_ALTIVEC) += vector.o -obj-$(CONFIG_PPC64) += entry_64.o -obj-$(CONFIG_PPC_OF_BOOT_TRAMPOLINE) += prom_init.o -extra-$(CONFIG_PPC_OF_BOOT_TRAMPOLINE) += prom_init_check +obj-$(CONFIG_PPC_OF_BOOT_TRAMPOLINE) += prom_init.o +obj64-$(CONFIG_PPC_OF_BOOT_TRAMPOLINE) += prom_entry_64.o +extra-$(CONFIG_PPC_OF_BOOT_TRAMPOLINE) += prom_init_check + +obj-$(CONFIG_PPC64) += $(obj64-y) +obj-$(CONFIG_PPC32) += $(obj32-y) quiet_cmd_prom_init_check = PROMCHK $@ cmd_prom_init_check = $(CONFIG_SHELL) $< "$(NM)" $(obj)/prom_init.o; touch $@ diff --git a/arch/powerpc/kernel/cpu_setup_power.c b/arch/powerpc/kernel/cpu_setup_power.c index 097c033668f0faee68f3a9d3410137142a778e53..98bd4e6c1770523c4062ff436fb8f90c620ad739 100644 --- a/arch/powerpc/kernel/cpu_setup_power.c +++ b/arch/powerpc/kernel/cpu_setup_power.c @@ -126,6 +126,12 @@ static void init_PMU_ISA31(void) mtspr(SPRN_MMCR0, MMCR0_FC | MMCR0_PMCCEXT); } +static void init_DEXCR(void) +{ + mtspr(SPRN_DEXCR, DEXCR_INIT); + mtspr(SPRN_HASHKEYR, 0); +} + /* * Note that we can be called twice of pseudo-PVRs. * The parameter offset is not used. @@ -241,6 +247,7 @@ void __setup_cpu_power10(unsigned long offset, struct cpu_spec *t) init_FSCR_power10(); init_PMU(); init_PMU_ISA31(); + init_DEXCR(); if (!init_hvmode_206(t)) return; @@ -263,6 +270,7 @@ void __restore_cpu_power10(void) init_FSCR_power10(); init_PMU(); init_PMU_ISA31(); + init_DEXCR(); msr = mfmsr(); if (!(msr & MSR_HV)) diff --git a/arch/powerpc/kernel/eeh_pe.c b/arch/powerpc/kernel/eeh_pe.c index d2873d17d2b1504384fdb74da53bd66bd5e12f76..e0ce812796241aae6e310676a2422d6c13cfb7a8 100644 --- a/arch/powerpc/kernel/eeh_pe.c +++ b/arch/powerpc/kernel/eeh_pe.c @@ -671,9 +671,8 @@ static void eeh_bridge_check_link(struct eeh_dev *edev) eeh_ops->write_config(edev, cap + PCI_EXP_LNKCTL, 2, val); /* Check link */ - eeh_ops->read_config(edev, cap + PCI_EXP_LNKCAP, 4, &val); - if (!(val & PCI_EXP_LNKCAP_DLLLARC)) { - eeh_edev_dbg(edev, "No link reporting capability (0x%08x) \n", val); + if (!edev->pdev->link_active_reporting) { + eeh_edev_dbg(edev, "No link reporting capability\n"); msleep(1000); return; } diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S index 47f0dd9a45adc28c0ce249b05e5b7783fe2cca7d..fe27d41f9a3de50c4f874686b6725ea53189a19e 100644 --- a/arch/powerpc/kernel/entry_32.S +++ b/arch/powerpc/kernel/entry_32.S @@ -211,64 +211,6 @@ start_kernel_thread: 100: trap EMIT_BUG_ENTRY 100b,__FILE__,__LINE__,0 - -/* - * This routine switches between two different tasks. The process - * state of one is saved on its kernel stack. Then the state - * of the other is restored from its kernel stack. The memory - * management hardware is updated to the second process's state. - * Finally, we can return to the second process. - * On entry, r3 points to the THREAD for the current task, r4 - * points to the THREAD for the new task. - * - * This routine is always called with interrupts disabled. - * - * Note: there are two ways to get to the "going out" portion - * of this code; either by coming in via the entry (_switch) - * or via "fork" which must set up an environment equivalent - * to the "_switch" path. If you change this , you'll have to - * change the fork code also. - * - * The code which creates the new task context is in 'copy_thread' - * in arch/ppc/kernel/process.c - */ -_GLOBAL(_switch) - stwu r1,-SWITCH_FRAME_SIZE(r1) - mflr r0 - stw r0,SWITCH_FRAME_SIZE+4(r1) - /* r3-r12 are caller saved -- Cort */ - SAVE_NVGPRS(r1) - stw r0,_NIP(r1) /* Return to switch caller */ - mfcr r10 - stw r10,_CCR(r1) - stw r1,KSP(r3) /* Set old stack pointer */ - -#ifdef CONFIG_SMP - /* We need a sync somewhere here to make sure that if the - * previous task gets rescheduled on another CPU, it sees all - * stores it has performed on this one. - */ - sync -#endif /* CONFIG_SMP */ - - tophys(r0,r4) - mtspr SPRN_SPRG_THREAD,r0 /* Update current THREAD phys addr */ - lwz r1,KSP(r4) /* Load new stack pointer */ - - /* save the old current 'last' for return value */ - mr r3,r2 - addi r2,r4,-THREAD /* Update current */ - - lwz r0,_CCR(r1) - mtcrf 0xFF,r0 - /* r3-r12 are destroyed -- Cort */ - REST_NVGPRS(r1) - - lwz r4,_NIP(r1) /* Return to _switch caller in new task */ - mtlr r4 - addi r1,r1,SWITCH_FRAME_SIZE - blr - .globl fast_exception_return fast_exception_return: #if !(defined(CONFIG_4xx) || defined(CONFIG_BOOKE)) diff --git a/arch/powerpc/kernel/exceptions-64e.S b/arch/powerpc/kernel/exceptions-64e.S index 3f86091e68b3bd4231ec069412c7b5edecb8e60b..7ab4c8c0f1abcb1aaf0412b9bf9fe78cd24ea489 100644 --- a/arch/powerpc/kernel/exceptions-64e.S +++ b/arch/powerpc/kernel/exceptions-64e.S @@ -5,6 +5,7 @@ * Copyright (C) 2007 Ben. Herrenschmidt (benh@kernel.crashing.org), IBM Corp. */ +#include #include #include #include @@ -66,7 +67,7 @@ #define SPECIAL_EXC_LOAD(reg, name) \ ld reg, (SPECIAL_EXC_##name * 8 + SPECIAL_EXC_FRAME_OFFS)(r1) -special_reg_save: +SYM_CODE_START_LOCAL(special_reg_save) /* * We only need (or have stack space) to save this stuff if * we interrupted the kernel. @@ -131,8 +132,9 @@ END_FTR_SECTION_IFSET(CPU_FTR_EMB_HV) SPECIAL_EXC_STORE(r10,CSRR1) blr +SYM_CODE_END(special_reg_save) -ret_from_level_except: +SYM_CODE_START_LOCAL(ret_from_level_except) ld r3,_MSR(r1) andi. r3,r3,MSR_PR beq 1f @@ -206,6 +208,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_EMB_HV) mtxer r11 blr +SYM_CODE_END(ret_from_level_except) .macro ret_from_level srr0 srr1 paca_ex scratch bl ret_from_level_except @@ -232,13 +235,15 @@ END_FTR_SECTION_IFSET(CPU_FTR_EMB_HV) mfspr r13,\scratch .endm -ret_from_crit_except: +SYM_CODE_START_LOCAL(ret_from_crit_except) ret_from_level SPRN_CSRR0 SPRN_CSRR1 PACA_EXCRIT SPRN_SPRG_CRIT_SCRATCH rfci +SYM_CODE_END(ret_from_crit_except) -ret_from_mc_except: +SYM_CODE_START_LOCAL(ret_from_mc_except) ret_from_level SPRN_MCSRR0 SPRN_MCSRR1 PACA_EXMC SPRN_SPRG_MC_SCRATCH rfmci +SYM_CODE_END(ret_from_mc_except) /* Exception prolog code for all exceptions */ #define EXCEPTION_PROLOG(n, intnum, type, addition) \ @@ -978,20 +983,22 @@ masked_interrupt_book3e_0x2c0: * r14 and r15 containing the fault address and error code, with the * original values stashed away in the PACA */ -storage_fault_common: +SYM_CODE_START_LOCAL(storage_fault_common) addi r3,r1,STACK_INT_FRAME_REGS bl do_page_fault b interrupt_return +SYM_CODE_END(storage_fault_common) /* * Alignment exception doesn't fit entirely in the 0x100 bytes so it * continues here. */ -alignment_more: +SYM_CODE_START_LOCAL(alignment_more) addi r3,r1,STACK_INT_FRAME_REGS bl alignment_exception REST_NVGPRS(r1) b interrupt_return +SYM_CODE_END(alignment_more) /* * Trampolines used when spotting a bad kernel stack pointer in @@ -1030,8 +1037,7 @@ BAD_STACK_TRAMPOLINE(0xe00) BAD_STACK_TRAMPOLINE(0xf00) BAD_STACK_TRAMPOLINE(0xf20) - .globl bad_stack_book3e -bad_stack_book3e: +_GLOBAL(bad_stack_book3e) /* XXX: Needs to make SPRN_SPRG_GEN depend on exception type */ mfspr r10,SPRN_SRR0; /* read SRR0 before touching stack */ ld r1,PACAEMERGSP(r13) @@ -1285,8 +1291,7 @@ have_hes: * ever takes any parameters, the SCOM code must also be updated to * provide them. */ - .globl a2_tlbinit_code_start -a2_tlbinit_code_start: +_GLOBAL(a2_tlbinit_code_start) ori r11,r3,MAS0_WQ_ALLWAYS oris r11,r11,MAS0_ESEL(3)@h /* Use way 3: workaround A2 erratum 376 */ @@ -1479,8 +1484,7 @@ _GLOBAL(book3e_secondary_thread_init) mflr r28 b 3b - .globl init_core_book3e -init_core_book3e: +_GLOBAL(init_core_book3e) /* Establish the interrupt vector base */ tovirt(r2,r2) LOAD_REG_ADDR(r3, interrupt_base_book3e) @@ -1488,7 +1492,7 @@ init_core_book3e: sync blr -init_thread_book3e: +SYM_CODE_START_LOCAL(init_thread_book3e) lis r3,(SPRN_EPCR_ICM | SPRN_EPCR_GICM)@h mtspr SPRN_EPCR,r3 @@ -1502,6 +1506,7 @@ init_thread_book3e: mtspr SPRN_TSR,r3 blr +SYM_CODE_END(init_thread_book3e) _GLOBAL(__setup_base_ivors) SET_IVOR(0, 0x020) /* Critical Input */ diff --git a/arch/powerpc/kernel/interrupt.c b/arch/powerpc/kernel/interrupt.c index e34c72285b4e90cc4748af618e88cd3638761030..c4f6d3c69ba9d3a76c5115394c33618a68199d4b 100644 --- a/arch/powerpc/kernel/interrupt.c +++ b/arch/powerpc/kernel/interrupt.c @@ -125,7 +125,7 @@ static notrace void check_return_regs_valid(struct pt_regs *regs) case 0x1600: case 0x1800: validp = &local_paca->hsrr_valid; - if (!*validp) + if (!READ_ONCE(*validp)) return; srr0 = mfspr(SPRN_HSRR0); @@ -135,7 +135,7 @@ static notrace void check_return_regs_valid(struct pt_regs *regs) break; default: validp = &local_paca->srr_valid; - if (!*validp) + if (!READ_ONCE(*validp)) return; srr0 = mfspr(SPRN_SRR0); @@ -161,19 +161,17 @@ static notrace void check_return_regs_valid(struct pt_regs *regs) * such things will get caught most of the time, statistically * enough to be able to get a warning out. */ - barrier(); - - if (!*validp) + if (!READ_ONCE(*validp)) return; - if (!warned) { - warned = true; + if (!data_race(warned)) { + data_race(warned = true); printk("%sSRR0 was: %lx should be: %lx\n", h, srr0, regs->nip); printk("%sSRR1 was: %lx should be: %lx\n", h, srr1, regs->msr); show_regs(regs); } - *validp = 0; /* fixup */ + WRITE_ONCE(*validp, 0); /* fixup */ #endif } @@ -368,7 +366,6 @@ void preempt_schedule_irq(void); notrace unsigned long interrupt_exit_kernel_prepare(struct pt_regs *regs) { - unsigned long flags; unsigned long ret = 0; unsigned long kuap; bool stack_store = read_thread_flags() & _TIF_EMULATE_STACK_STORE; @@ -392,7 +389,7 @@ notrace unsigned long interrupt_exit_kernel_prepare(struct pt_regs *regs) kuap = kuap_get_and_assert_locked(); - local_irq_save(flags); + local_irq_disable(); if (!arch_irq_disabled_regs(regs)) { /* Returning to a kernel context with local irqs enabled. */ diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c index 67f0b01e6ff575d54d95532f04e70e735b3640ee..c52449ae6936ad488c497bd00877202d7189b3e7 100644 --- a/arch/powerpc/kernel/iommu.c +++ b/arch/powerpc/kernel/iommu.c @@ -1090,6 +1090,7 @@ void iommu_tce_kill(struct iommu_table *tbl, } EXPORT_SYMBOL_GPL(iommu_tce_kill); +#if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV) static int iommu_take_ownership(struct iommu_table *tbl) { unsigned long flags, i, sz = (tbl->it_size + 7) >> 3; @@ -1140,6 +1141,7 @@ static void iommu_release_ownership(struct iommu_table *tbl) spin_unlock(&tbl->pools[i].lock); spin_unlock_irqrestore(&tbl->large_pool.lock, flags); } +#endif int iommu_add_device(struct iommu_table_group *table_group, struct device *dev) { @@ -1171,6 +1173,7 @@ int iommu_add_device(struct iommu_table_group *table_group, struct device *dev) } EXPORT_SYMBOL_GPL(iommu_add_device); +#if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV) /* * A simple iommu_table_group_ops which only allows reusing the existing * iommu_table. This handles VFIO for POWER7 or the nested KVM. @@ -1398,5 +1401,6 @@ static int __init spapr_tce_setup_phb_iommus_initcall(void) return 0; } postcore_initcall_sync(spapr_tce_setup_phb_iommus_initcall); +#endif #endif /* CONFIG_IOMMU_API */ diff --git a/arch/powerpc/kernel/legacy_serial.c b/arch/powerpc/kernel/legacy_serial.c index c9ad12461d44bbcfd0bed1cf84804344bb952230..6ee65741dbd52d0b19f0cab485840ce41ca57149 100644 --- a/arch/powerpc/kernel/legacy_serial.c +++ b/arch/powerpc/kernel/legacy_serial.c @@ -508,12 +508,16 @@ static void __init fixup_port_irq(int index, port->irq = virq; -#ifdef CONFIG_SERIAL_8250_FSL - if (of_device_is_compatible(np, "fsl,ns16550")) { - port->handle_irq = fsl8250_handle_irq; - port->has_sysrq = IS_ENABLED(CONFIG_SERIAL_8250_CONSOLE); + if (IS_ENABLED(CONFIG_SERIAL_8250) && + of_device_is_compatible(np, "fsl,ns16550")) { + if (IS_REACHABLE(CONFIG_SERIAL_8250_FSL)) { + port->handle_irq = fsl8250_handle_irq; + port->has_sysrq = IS_ENABLED(CONFIG_SERIAL_8250_CONSOLE); + } else { + pr_warn_once("Not activating Freescale specific workaround for device %pOFP\n", + np); + } } -#endif } static void __init fixup_port_pio(int index, diff --git a/arch/powerpc/kernel/ppc_save_regs.S b/arch/powerpc/kernel/ppc_save_regs.S index 49813f98246813aedb229e46c87d8d4243ac2c52..a9b9c32d0c1ff32fcf517566942c9d90a0550827 100644 --- a/arch/powerpc/kernel/ppc_save_regs.S +++ b/arch/powerpc/kernel/ppc_save_regs.S @@ -31,10 +31,10 @@ _GLOBAL(ppc_save_regs) lbz r0,PACAIRQSOFTMASK(r13) PPC_STL r0,SOFTE(r3) #endif - /* go up one stack frame for SP */ - PPC_LL r4,0(r1) - PPC_STL r4,GPR1(r3) + /* store current SP */ + PPC_STL r1,GPR1(r3) /* get caller's LR */ + PPC_LL r4,0(r1) PPC_LL r0,LRSAVE(r4) PPC_STL r0,_LINK(r3) mflr r0 diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index 1fefafb2b29be53f21577b3d76c63cb1a2ccfa8b..b68898ac07e1999d4ae74467c1cdbcfcc419a31d 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -1182,6 +1182,9 @@ static inline void save_sprs(struct thread_struct *t) */ t->tar = mfspr(SPRN_TAR); } + + if (cpu_has_feature(CPU_FTR_DEXCR_NPHIE)) + t->hashkeyr = mfspr(SPRN_HASHKEYR); #endif } @@ -1260,6 +1263,10 @@ static inline void restore_sprs(struct thread_struct *old_thread, if (cpu_has_feature(CPU_FTR_P9_TIDR) && old_thread->tidr != new_thread->tidr) mtspr(SPRN_TIDR, new_thread->tidr); + + if (cpu_has_feature(CPU_FTR_DEXCR_NPHIE) && + old_thread->hashkeyr != new_thread->hashkeyr) + mtspr(SPRN_HASHKEYR, new_thread->hashkeyr); #endif } @@ -1867,6 +1874,10 @@ int copy_thread(struct task_struct *p, const struct kernel_clone_args *args) } p->thread.tidr = 0; +#endif +#ifdef CONFIG_PPC_BOOK3S_64 + if (cpu_has_feature(CPU_FTR_DEXCR_NPHIE)) + p->thread.hashkeyr = current->thread.hashkeyr; #endif return 0; } @@ -1984,6 +1995,12 @@ void start_thread(struct pt_regs *regs, unsigned long start, unsigned long sp) current->thread.tm_tfiar = 0; current->thread.load_tm = 0; #endif /* CONFIG_PPC_TRANSACTIONAL_MEM */ +#ifdef CONFIG_PPC_BOOK3S_64 + if (cpu_has_feature(CPU_FTR_DEXCR_NPHIE)) { + current->thread.hashkeyr = get_random_long(); + mtspr(SPRN_HASHKEYR, current->thread.hashkeyr); + } +#endif /* CONFIG_PPC_BOOK3S_64 */ } EXPORT_SYMBOL(start_thread); diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index 9d9ee4e9e1a1bd79599f20d09a31e0f69046cdc5..0b5878c3125b1cd67ff3f44cedf83d514478c262 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -182,6 +182,7 @@ static struct ibm_feature ibm_pa_features[] __initdata = { .cpu_user_ftrs2 = PPC_FEATURE2_HTM_COMP | PPC_FEATURE2_HTM_NOSC_COMP }, { .pabyte = 64, .pabit = 0, .cpu_features = CPU_FTR_DAWR1 }, + { .pabyte = 68, .pabit = 5, .cpu_features = CPU_FTR_DEXCR_NPHIE }, }; /* diff --git a/arch/powerpc/kernel/prom_entry_64.S b/arch/powerpc/kernel/prom_entry_64.S new file mode 100644 index 0000000000000000000000000000000000000000..f1b8793d28c64931cee476abcddaee08e55152ad --- /dev/null +++ b/arch/powerpc/kernel/prom_entry_64.S @@ -0,0 +1,87 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * PowerPC version + * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) + * Rewritten by Cort Dougan (cort@cs.nmt.edu) for PReP + * Copyright (C) 1996 Cort Dougan + * Adapted for Power Macintosh by Paul Mackerras. + * Low-level exception handlers and MMU support + * rewritten by Paul Mackerras. + * Copyright (C) 1996 Paul Mackerras. + * MPC8xx modifications Copyright (C) 1997 Dan Malek (dmalek@jlc.net). + * + * This file contains the 64-bit prom entry code. + */ +#include +#ifdef CONFIG_PPC_BOOK3S +#include +#else +#include +#endif +#include + +.section ".text","ax",@progbits + +_GLOBAL(enter_prom) + mflr r0 + std r0,16(r1) + stdu r1,-SWITCH_FRAME_SIZE(r1) /* Save SP and create stack space */ + + /* Because PROM is running in 32b mode, it clobbers the high order half + * of all registers that it saves. We therefore save those registers + * PROM might touch to the stack. (r0, r3-r13 are caller saved) + */ + SAVE_GPR(2, r1) + SAVE_GPR(13, r1) + SAVE_NVGPRS(r1) + mfcr r10 + mfmsr r11 + std r10,_CCR(r1) + std r11,_MSR(r1) + + /* Put PROM address in SRR0 */ + mtsrr0 r4 + + /* Setup our trampoline return addr in LR */ + bcl 20,31,$+4 +0: mflr r4 + addi r4,r4,(1f - 0b) + mtlr r4 + + /* Prepare a 32-bit mode big endian MSR + */ +#ifdef CONFIG_PPC_BOOK3E_64 + rlwinm r11,r11,0,1,31 + mtsrr1 r11 + rfi +#else /* CONFIG_PPC_BOOK3E_64 */ + LOAD_REG_IMMEDIATE(r12, MSR_SF | MSR_LE) + andc r11,r11,r12 + mtsrr1 r11 + RFI_TO_KERNEL +#endif /* CONFIG_PPC_BOOK3E_64 */ + +1: /* Return from OF */ + FIXUP_ENDIAN + + /* Just make sure that r1 top 32 bits didn't get + * corrupt by OF + */ + rldicl r1,r1,0,32 + + /* Restore the MSR (back to 64 bits) */ + ld r0,_MSR(r1) + MTMSRD(r0) + isync + + /* Restore other registers */ + REST_GPR(2, r1) + REST_GPR(13, r1) + REST_NVGPRS(r1) + ld r4,_CCR(r1) + mtcr r4 + + addi r1,r1,SWITCH_FRAME_SIZE + ld r0,16(r1) + mtlr r0 + blr diff --git a/arch/powerpc/kernel/ptrace/ptrace-decl.h b/arch/powerpc/kernel/ptrace/ptrace-decl.h index eafe5f0f62898cc07f0e761111b2039ed5692133..4171a5727197ba62619f837783761382fcd0b168 100644 --- a/arch/powerpc/kernel/ptrace/ptrace-decl.h +++ b/arch/powerpc/kernel/ptrace/ptrace-decl.h @@ -1,5 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-or-later */ +#include + /* * Set of msr bits that gdb can change on behalf of a process. */ @@ -55,6 +57,10 @@ enum powerpc_regset { REGSET_TAR, /* TAR register */ REGSET_EBB, /* EBB registers */ REGSET_PMR, /* Performance Monitor Registers */ + REGSET_DEXCR, /* DEXCR registers */ +#ifdef CONFIG_CHECKPOINT_RESTORE + REGSET_HASHKEYR, /* HASHKEYR register */ +#endif #endif #ifdef CONFIG_PPC_MEM_KEYS REGSET_PKEY, /* AMR register */ diff --git a/arch/powerpc/kernel/ptrace/ptrace-view.c b/arch/powerpc/kernel/ptrace/ptrace-view.c index 5fff0d04b23f7a7161de470e504378807a887568..3910cd7bb2d9b1a7997a730b9a20ddfacadad561 100644 --- a/arch/powerpc/kernel/ptrace/ptrace-view.c +++ b/arch/powerpc/kernel/ptrace/ptrace-view.c @@ -454,7 +454,65 @@ static int pmu_set(struct task_struct *target, const struct user_regset *regset, 5 * sizeof(unsigned long)); return ret; } -#endif + +static int dexcr_active(struct task_struct *target, const struct user_regset *regset) +{ + if (!cpu_has_feature(CPU_FTR_ARCH_31)) + return -ENODEV; + + return regset->n; +} + +static int dexcr_get(struct task_struct *target, const struct user_regset *regset, + struct membuf to) +{ + if (!cpu_has_feature(CPU_FTR_ARCH_31)) + return -ENODEV; + + /* + * The DEXCR is currently static across all CPUs, so we don't + * store the target's value anywhere, but the static value + * will also be correct. + */ + membuf_store(&to, (u64)lower_32_bits(DEXCR_INIT)); + + /* + * Technically the HDEXCR is per-cpu, but a hypervisor can't reasonably + * change it between CPUs of the same guest. + */ + return membuf_store(&to, (u64)lower_32_bits(mfspr(SPRN_HDEXCR_RO))); +} + +#ifdef CONFIG_CHECKPOINT_RESTORE +static int hashkeyr_active(struct task_struct *target, const struct user_regset *regset) +{ + if (!cpu_has_feature(CPU_FTR_ARCH_31)) + return -ENODEV; + + return regset->n; +} + +static int hashkeyr_get(struct task_struct *target, const struct user_regset *regset, + struct membuf to) +{ + if (!cpu_has_feature(CPU_FTR_ARCH_31)) + return -ENODEV; + + return membuf_store(&to, target->thread.hashkeyr); +} + +static int hashkeyr_set(struct task_struct *target, const struct user_regset *regset, + unsigned int pos, unsigned int count, const void *kbuf, + const void __user *ubuf) +{ + if (!cpu_has_feature(CPU_FTR_ARCH_31)) + return -ENODEV; + + return user_regset_copyin(&pos, &count, &kbuf, &ubuf, &target->thread.hashkeyr, + 0, sizeof(unsigned long)); +} +#endif /* CONFIG_CHECKPOINT_RESTORE */ +#endif /* CONFIG_PPC_BOOK3S_64 */ #ifdef CONFIG_PPC_MEM_KEYS static int pkey_active(struct task_struct *target, const struct user_regset *regset) @@ -615,6 +673,18 @@ static const struct user_regset native_regsets[] = { .size = sizeof(u64), .align = sizeof(u64), .active = pmu_active, .regset_get = pmu_get, .set = pmu_set }, + [REGSET_DEXCR] = { + .core_note_type = NT_PPC_DEXCR, .n = ELF_NDEXCR, + .size = sizeof(u64), .align = sizeof(u64), + .active = dexcr_active, .regset_get = dexcr_get + }, +#ifdef CONFIG_CHECKPOINT_RESTORE + [REGSET_HASHKEYR] = { + .core_note_type = NT_PPC_HASHKEYR, .n = ELF_NHASHKEYR, + .size = sizeof(u64), .align = sizeof(u64), + .active = hashkeyr_active, .regset_get = hashkeyr_get, .set = hashkeyr_set + }, +#endif #endif #ifdef CONFIG_PPC_MEM_KEYS [REGSET_PKEY] = { diff --git a/arch/powerpc/kernel/security.c b/arch/powerpc/kernel/security.c index 206475e3e0b480116719b69b0ddd0873f18dd529..4856e1a5161cccab5d7d5685dc1c9fc69516d119 100644 --- a/arch/powerpc/kernel/security.c +++ b/arch/powerpc/kernel/security.c @@ -364,26 +364,27 @@ ssize_t cpu_show_spec_store_bypass(struct device *dev, struct device_attribute * static int ssb_prctl_get(struct task_struct *task) { + /* + * The STF_BARRIER feature is on by default, so if it's off that means + * firmware has explicitly said the CPU is not vulnerable via either + * the hypercall or device tree. + */ + if (!security_ftr_enabled(SEC_FTR_STF_BARRIER)) + return PR_SPEC_NOT_AFFECTED; + + /* + * If the system's CPU has no known barrier (see setup_stf_barrier()) + * then assume that the CPU is not vulnerable. + */ if (stf_enabled_flush_types == STF_BARRIER_NONE) - /* - * We don't have an explicit signal from firmware that we're - * vulnerable or not, we only have certain CPU revisions that - * are known to be vulnerable. - * - * We assume that if we're on another CPU, where the barrier is - * NONE, then we are not vulnerable. - */ return PR_SPEC_NOT_AFFECTED; - else - /* - * If we do have a barrier type then we are vulnerable. The - * barrier is not a global or per-process mitigation, so the - * only value we can report here is PR_SPEC_ENABLE, which - * appears as "vulnerable" in /proc. - */ - return PR_SPEC_ENABLE; - - return -EINVAL; + + /* + * Otherwise the CPU is vulnerable. The barrier is not a global or + * per-process mitigation, so the only value that can be reported here + * is PR_SPEC_ENABLE, which appears as "vulnerable" in /proc. + */ + return PR_SPEC_ENABLE; } int arch_prctl_spec_ctrl_get(struct task_struct *task, unsigned long which) diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c index c114c7f25645c0b41f810e0f95705eb906c61fbc..7a718ed32b277f289116dcaa73a24e1354bf4f55 100644 --- a/arch/powerpc/kernel/signal_32.c +++ b/arch/powerpc/kernel/signal_32.c @@ -264,8 +264,9 @@ static void prepare_save_user_regs(int ctx_has_vsx_region) #endif } -static int __unsafe_save_user_regs(struct pt_regs *regs, struct mcontext __user *frame, - struct mcontext __user *tm_frame, int ctx_has_vsx_region) +static __always_inline int +__unsafe_save_user_regs(struct pt_regs *regs, struct mcontext __user *frame, + struct mcontext __user *tm_frame, int ctx_has_vsx_region) { unsigned long msr = regs->msr; @@ -364,8 +365,9 @@ static void prepare_save_tm_user_regs(void) current->thread.ckvrsave = mfspr(SPRN_VRSAVE); } -static int save_tm_user_regs_unsafe(struct pt_regs *regs, struct mcontext __user *frame, - struct mcontext __user *tm_frame, unsigned long msr) +static __always_inline int +save_tm_user_regs_unsafe(struct pt_regs *regs, struct mcontext __user *frame, + struct mcontext __user *tm_frame, unsigned long msr) { /* Save both sets of general registers */ unsafe_save_general_regs(¤t->thread.ckpt_regs, frame, failed); @@ -444,8 +446,9 @@ static int save_tm_user_regs_unsafe(struct pt_regs *regs, struct mcontext __user #else static void prepare_save_tm_user_regs(void) { } -static int save_tm_user_regs_unsafe(struct pt_regs *regs, struct mcontext __user *frame, - struct mcontext __user *tm_frame, unsigned long msr) +static __always_inline int +save_tm_user_regs_unsafe(struct pt_regs *regs, struct mcontext __user *frame, + struct mcontext __user *tm_frame, unsigned long msr) { return 0; } diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c index 265801a3e94cfe883966bc7a52b3634c9f25ccc0..fbbb695bae3d25753e8c11d1c77af64761fa8699 100644 --- a/arch/powerpc/kernel/smp.c +++ b/arch/powerpc/kernel/smp.c @@ -291,7 +291,7 @@ void smp_muxed_ipi_set_message(int cpu, int msg) * Order previous accesses before accesses in the IPI handler. */ smp_mb(); - message[msg] = 1; + WRITE_ONCE(message[msg], 1); } void smp_muxed_ipi_message_pass(int cpu, int msg) @@ -350,7 +350,7 @@ irqreturn_t smp_ipi_demux_relaxed(void) if (all & IPI_MESSAGE(PPC_MSG_NMI_IPI)) nmi_ipi_action(0, NULL); #endif - } while (info->messages); + } while (READ_ONCE(info->messages)); return IRQ_HANDLED; } @@ -417,9 +417,9 @@ noinstr static void nmi_ipi_lock_start(unsigned long *flags) { raw_local_irq_save(*flags); hard_irq_disable(); - while (arch_atomic_cmpxchg(&__nmi_ipi_lock, 0, 1) == 1) { + while (raw_atomic_cmpxchg(&__nmi_ipi_lock, 0, 1) == 1) { raw_local_irq_restore(*flags); - spin_until_cond(arch_atomic_read(&__nmi_ipi_lock) == 0); + spin_until_cond(raw_atomic_read(&__nmi_ipi_lock) == 0); raw_local_irq_save(*flags); hard_irq_disable(); } @@ -427,15 +427,15 @@ noinstr static void nmi_ipi_lock_start(unsigned long *flags) noinstr static void nmi_ipi_lock(void) { - while (arch_atomic_cmpxchg(&__nmi_ipi_lock, 0, 1) == 1) - spin_until_cond(arch_atomic_read(&__nmi_ipi_lock) == 0); + while (raw_atomic_cmpxchg(&__nmi_ipi_lock, 0, 1) == 1) + spin_until_cond(raw_atomic_read(&__nmi_ipi_lock) == 0); } noinstr static void nmi_ipi_unlock(void) { smp_mb(); - WARN_ON(arch_atomic_read(&__nmi_ipi_lock) != 1); - arch_atomic_set(&__nmi_ipi_lock, 0); + WARN_ON(raw_atomic_read(&__nmi_ipi_lock) != 1); + raw_atomic_set(&__nmi_ipi_lock, 0); } noinstr static void nmi_ipi_unlock_end(unsigned long *flags) @@ -1605,6 +1605,7 @@ static void add_cpu_to_masks(int cpu) } /* Activate a secondary processor. */ +__no_stack_protector void start_secondary(void *unused) { unsigned int cpu = raw_smp_processor_id(); diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/switch.S similarity index 59% rename from arch/powerpc/kernel/entry_64.S rename to arch/powerpc/kernel/switch.S index 1bf1121e17f1c12853f7afabd7281eb9212d6a1c..608c0ce7cec67f7a7375470e7f4a009dd7463c42 100644 --- a/arch/powerpc/kernel/entry_64.S +++ b/arch/powerpc/kernel/switch.S @@ -1,56 +1,21 @@ /* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * PowerPC version - * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) - * Rewritten by Cort Dougan (cort@cs.nmt.edu) for PReP - * Copyright (C) 1996 Cort Dougan - * Adapted for Power Macintosh by Paul Mackerras. - * Low-level exception handlers and MMU support - * rewritten by Paul Mackerras. - * Copyright (C) 1996 Paul Mackerras. - * MPC8xx modifications Copyright (C) 1997 Dan Malek (dmalek@jlc.net). - * - * This file contains the system call entry code, context switch - * code, and exception/interrupt return code for PowerPC. - */ - #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 -#ifdef CONFIG_PPC_BOOK3S -#include -#else -#include -#endif -#include #include +#include -/* - * System calls. - */ - .section ".text" +.section ".text","ax",@progbits #ifdef CONFIG_PPC_BOOK3S_64 +/* + * Cancel all explict user streams as they will have no use after context + * switch and will stop the HW from creating streams itself + */ +#define STOP_STREAMS \ + DCBT_BOOK3S_STOP_ALL_STREAM_IDS(r6) #define FLUSH_COUNT_CACHE \ 1: nop; \ @@ -105,87 +70,13 @@ flush_branch_caches: .endr blr -#else -#define FLUSH_COUNT_CACHE -#endif /* CONFIG_PPC_BOOK3S_64 */ +#ifdef CONFIG_PPC_64S_HASH_MMU +.balign 32 /* - * This routine switches between two different tasks. The process - * state of one is saved on its kernel stack. Then the state - * of the other is restored from its kernel stack. The memory - * management hardware is updated to the second process's state. - * Finally, we can return to the second process, via interrupt_return. - * On entry, r3 points to the THREAD for the current task, r4 - * points to the THREAD for the new task. - * - * Note: there are two ways to get to the "going out" portion - * of this code; either by coming in via the entry (_switch) - * or via "fork" which must set up an environment equivalent - * to the "_switch" path. If you change this you'll have to change - * the fork code also. - * - * The code which creates the new task context is in 'copy_thread' - * in arch/powerpc/kernel/process.c + * New stack pointer in r8, old stack pointer in r1, must not clobber r3 */ - .align 7 -_GLOBAL(_switch) - mflr r0 - std r0,16(r1) - stdu r1,-SWITCH_FRAME_SIZE(r1) - /* r3-r13 are caller saved -- Cort */ - SAVE_NVGPRS(r1) - std r0,_NIP(r1) /* Return to switch caller */ - mfcr r23 - std r23,_CCR(r1) - std r1,KSP(r3) /* Set old stack pointer */ - - kuap_check_amr r9, r10 - - FLUSH_COUNT_CACHE /* Clobbers r9, ctr */ - - /* - * On SMP kernels, care must be taken because a task may be - * scheduled off CPUx and on to CPUy. Memory ordering must be - * considered. - * - * Cacheable stores on CPUx will be visible when the task is - * scheduled on CPUy by virtue of the core scheduler barriers - * (see "Notes on Program-Order guarantees on SMP systems." in - * kernel/sched/core.c). - * - * Uncacheable stores in the case of involuntary preemption must - * be taken care of. The smp_mb__after_spinlock() in __schedule() - * is implemented as hwsync on powerpc, which orders MMIO too. So - * long as there is an hwsync in the context switch path, it will - * be executed on the source CPU after the task has performed - * all MMIO ops on that CPU, and on the destination CPU before the - * task performs any MMIO ops there. - */ - - /* - * The kernel context switch path must contain a spin_lock, - * which contains larx/stcx, which will clear any reservation - * of the task being switched. - */ -#ifdef CONFIG_PPC_BOOK3S -/* Cancel all explict user streams as they will have no use after context - * switch and will stop the HW from creating streams itself - */ - DCBT_BOOK3S_STOP_ALL_STREAM_IDS(r6) -#endif - - addi r6,r4,-THREAD /* Convert THREAD to 'current' */ - std r6,PACACURRENT(r13) /* Set new 'current' */ -#if defined(CONFIG_STACKPROTECTOR) - ld r6, TASK_CANARY(r6) - std r6, PACA_CANARY(r13) -#endif - - ld r8,KSP(r4) /* new stack pointer */ -#ifdef CONFIG_PPC_64S_HASH_MMU -BEGIN_MMU_FTR_SECTION - b 2f -END_MMU_FTR_SECTION_IFSET(MMU_FTR_TYPE_RADIX) +pin_stack_slb: BEGIN_FTR_SECTION clrrdi r6,r8,28 /* get its ESID */ clrrdi r9,r1,28 /* get current sp ESID */ @@ -233,15 +124,57 @@ BEGIN_FTR_SECTION END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_207S) slbmte r7,r0 isync -2: +2: blr + .size pin_stack_slb,.-pin_stack_slb #endif /* CONFIG_PPC_64S_HASH_MMU */ - clrrdi r7, r8, THREAD_SHIFT /* base of new stack */ - /* Note: this uses SWITCH_FRAME_SIZE rather than INT_FRAME_SIZE - because we don't need to leave the 288-byte ABI gap at the - top of the kernel stack. */ +#else +#define STOP_STREAMS +#define FLUSH_COUNT_CACHE +#endif /* CONFIG_PPC_BOOK3S_64 */ + +/* + * do_switch_32/64 have the same calling convention as _switch, i.e., r3,r4 + * are prev and next thread_struct *, and returns prev task_struct * in r3. + + * This switches the stack, current, and does other task switch housekeeping. + */ +.macro do_switch_32 + tophys(r0,r4) + mtspr SPRN_SPRG_THREAD,r0 /* Update current THREAD phys addr */ + lwz r1,KSP(r4) /* Load new stack pointer */ + + /* save the old current 'last' for return value */ + mr r3,r2 + addi r2,r4,-THREAD /* Update current */ +.endm + +.macro do_switch_64 + ld r8,KSP(r4) /* Load new stack pointer */ + + kuap_check_amr r9, r10 + + FLUSH_COUNT_CACHE /* Clobbers r9, ctr */ + + STOP_STREAMS /* Clobbers r6 */ + + addi r3,r3,-THREAD /* old thread -> task_struct for return value */ + addi r6,r4,-THREAD /* new thread -> task_struct */ + std r6,PACACURRENT(r13) /* Set new task_struct to 'current' */ +#if defined(CONFIG_STACKPROTECTOR) + ld r6, TASK_CANARY(r6) + std r6, PACA_CANARY(r13) +#endif + /* Set new PACAKSAVE */ + clrrdi r7,r8,THREAD_SHIFT /* base of new stack */ addi r7,r7,THREAD_SIZE-SWITCH_FRAME_SIZE + std r7,PACAKSAVE(r13) +#ifdef CONFIG_PPC_64S_HASH_MMU +BEGIN_MMU_FTR_SECTION + bl pin_stack_slb +END_MMU_FTR_SECTION_IFCLR(MMU_FTR_TYPE_RADIX) +#endif /* * PMU interrupts in radix may come in here. They will use r1, not * PACAKSAVE, so this stack switch will not cause a problem. They @@ -251,81 +184,75 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_207S) * active on the new CPU, will order those stores. */ mr r1,r8 /* start using new stack pointer */ - std r7,PACAKSAVE(r13) +.endm + +/* + * This routine switches between two different tasks. The process + * state of one is saved on its kernel stack. Then the state + * of the other is restored from its kernel stack. The memory + * management hardware is updated to the second process's state. + * Finally, we can return to the second process. + * On entry, r3 points to the THREAD for the current task, r4 + * points to the THREAD for the new task. + * + * This routine is always called with interrupts disabled. + * + * Note: there are two ways to get to the "going out" portion + * of this code; either by coming in via the entry (_switch) + * or via "fork" which must set up an environment equivalent + * to the "_switch" path. If you change this , you'll have to + * change the fork code also. + * + * The code which creates the new task context is in 'copy_thread' + * in arch/ppc/kernel/process.c + * + * Note: this uses SWITCH_FRAME_SIZE rather than USER_INT_FRAME_SIZE + * because we don't need to leave the redzone ABI gap at the top of + * the kernel stack. + */ +_GLOBAL(_switch) + PPC_CREATE_STACK_FRAME(SWITCH_FRAME_SIZE) + PPC_STL r1,KSP(r3) /* Set old stack pointer */ + SAVE_NVGPRS(r1) /* volatiles are caller-saved -- Cort */ + PPC_STL r0,_NIP(r1) /* Return to switch caller */ + mfcr r0 + stw r0,_CCR(r1) - ld r6,_CCR(r1) - mtcrf 0xFF,r6 + /* + * On SMP kernels, care must be taken because a task may be + * scheduled off CPUx and on to CPUy. Memory ordering must be + * considered. + * + * Cacheable stores on CPUx will be visible when the task is + * scheduled on CPUy by virtue of the core scheduler barriers + * (see "Notes on Program-Order guarantees on SMP systems." in + * kernel/sched/core.c). + * + * Uncacheable stores in the case of involuntary preemption must + * be taken care of. The smp_mb__after_spinlock() in __schedule() + * is implemented as hwsync on powerpc, which orders MMIO too. So + * long as there is an hwsync in the context switch path, it will + * be executed on the source CPU after the task has performed + * all MMIO ops on that CPU, and on the destination CPU before the + * task performs any MMIO ops there. + */ + + /* + * The kernel context switch path must contain a spin_lock, + * which contains larx/stcx, which will clear any reservation + * of the task being switched. + */ - /* r3-r13 are destroyed -- Cort */ - REST_NVGPRS(r1) +#ifdef CONFIG_PPC32 + do_switch_32 +#else + do_switch_64 +#endif - /* convert old thread to its task_struct for return value */ - addi r3,r3,-THREAD - ld r7,_NIP(r1) /* Return to _switch caller in new task */ - mtlr r7 + lwz r0,_CCR(r1) + mtcrf 0xFF,r0 + REST_NVGPRS(r1) /* volatiles are destroyed -- Cort */ + PPC_LL r0,_NIP(r1) /* Return to _switch caller in new task */ + mtlr r0 addi r1,r1,SWITCH_FRAME_SIZE blr - -_GLOBAL(enter_prom) - mflr r0 - std r0,16(r1) - stdu r1,-SWITCH_FRAME_SIZE(r1) /* Save SP and create stack space */ - - /* Because PROM is running in 32b mode, it clobbers the high order half - * of all registers that it saves. We therefore save those registers - * PROM might touch to the stack. (r0, r3-r13 are caller saved) - */ - SAVE_GPR(2, r1) - SAVE_GPR(13, r1) - SAVE_NVGPRS(r1) - mfcr r10 - mfmsr r11 - std r10,_CCR(r1) - std r11,_MSR(r1) - - /* Put PROM address in SRR0 */ - mtsrr0 r4 - - /* Setup our trampoline return addr in LR */ - bcl 20,31,$+4 -0: mflr r4 - addi r4,r4,(1f - 0b) - mtlr r4 - - /* Prepare a 32-bit mode big endian MSR - */ -#ifdef CONFIG_PPC_BOOK3E_64 - rlwinm r11,r11,0,1,31 - mtsrr1 r11 - rfi -#else /* CONFIG_PPC_BOOK3E_64 */ - LOAD_REG_IMMEDIATE(r12, MSR_SF | MSR_LE) - andc r11,r11,r12 - mtsrr1 r11 - RFI_TO_KERNEL -#endif /* CONFIG_PPC_BOOK3E_64 */ - -1: /* Return from OF */ - FIXUP_ENDIAN - - /* Just make sure that r1 top 32 bits didn't get - * corrupt by OF - */ - rldicl r1,r1,0,32 - - /* Restore the MSR (back to 64 bits) */ - ld r0,_MSR(r1) - MTMSRD(r0) - isync - - /* Restore other registers */ - REST_GPR(2, r1) - REST_GPR(13, r1) - REST_NVGPRS(r1) - ld r4,_CCR(r1) - mtcr r4 - - addi r1,r1,SWITCH_FRAME_SIZE - ld r0,16(r1) - mtlr r0 - blr diff --git a/arch/powerpc/kernel/syscalls/syscall.tbl b/arch/powerpc/kernel/syscalls/syscall.tbl index a0be127475b1f7614d79f3c85e950c5805e54cd8..8c0b08b7a80ec4b75fbc059054cf745ac89ad3dc 100644 --- a/arch/powerpc/kernel/syscalls/syscall.tbl +++ b/arch/powerpc/kernel/syscalls/syscall.tbl @@ -537,3 +537,4 @@ 448 common process_mrelease sys_process_mrelease 449 common futex_waitv sys_futex_waitv 450 nospu set_mempolicy_home_node sys_set_mempolicy_home_node +451 common cachestat sys_cachestat diff --git a/arch/powerpc/kernel/tau_6xx.c b/arch/powerpc/kernel/tau_6xx.c index 828d0f4106d23ffa4f20f9561773851856bb9c6c..cba6dd15de3bcc1b728a62be653c1d25bb56011f 100644 --- a/arch/powerpc/kernel/tau_6xx.c +++ b/arch/powerpc/kernel/tau_6xx.c @@ -200,7 +200,7 @@ static int __init TAU_init(void) tau_int_enable = IS_ENABLED(CONFIG_TAU_INT) && !strcmp(cur_cpu_spec->platform, "ppc750"); - tau_workq = alloc_workqueue("tau", WQ_UNBOUND, 1); + tau_workq = alloc_ordered_workqueue("tau", 0); if (!tau_workq) return -ENOMEM; diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index 9bdd79aa51cfc12422476e00b4994534b7192a54..e59ec6d32d37530950b5e883451902990bbc07f0 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c @@ -1516,6 +1516,22 @@ static void do_program_check(struct pt_regs *regs) return; } } + + if (cpu_has_feature(CPU_FTR_DEXCR_NPHIE) && user_mode(regs)) { + ppc_inst_t insn; + + if (get_user_instr(insn, (void __user *)regs->nip)) { + _exception(SIGSEGV, regs, SEGV_MAPERR, regs->nip); + return; + } + + if (ppc_inst_primary_opcode(insn) == 31 && + get_xop(ppc_inst_val(insn)) == OP_31_XOP_HASHCHK) { + _exception(SIGILL, regs, ILL_ILLOPN, regs->nip); + return; + } + } + _exception(SIGTRAP, regs, TRAP_BRKPT, regs->nip); return; } diff --git a/arch/powerpc/kernel/vdso/Makefile b/arch/powerpc/kernel/vdso/Makefile index 4c3f34485f08f8ba0f933fdb5d42f0c494512252..0c7d82c270c37a4c1ad3ff9dd5c0eb4794b7ccdd 100644 --- a/arch/powerpc/kernel/vdso/Makefile +++ b/arch/powerpc/kernel/vdso/Makefile @@ -54,8 +54,10 @@ KASAN_SANITIZE := n KCSAN_SANITIZE := n ccflags-y := -fno-common -fno-builtin -ldflags-y := -Wl,--hash-style=both -nostdlib -shared -z noexecstack +ldflags-y := -Wl,--hash-style=both -nostdlib -shared -z noexecstack $(CLANG_FLAGS) ldflags-$(CONFIG_LD_IS_LLD) += $(call cc-option,--ld-path=$(LD),-fuse-ld=lld) +ldflags-$(CONFIG_LD_ORPHAN_WARN) += -Wl,--orphan-handling=$(CONFIG_LD_ORPHAN_WARN_LEVEL) + # Filter flags that clang will warn are unused for linking ldflags-y += $(filter-out $(CC_AUTO_VAR_INIT_ZERO_ENABLER) $(CC_FLAGS_FTRACE) -Wa$(comma)%, $(KBUILD_CFLAGS)) diff --git a/arch/powerpc/kernel/vdso/vdso32.lds.S b/arch/powerpc/kernel/vdso/vdso32.lds.S index bc0be274a9ac24d8ae87a4f5dddb63aefa4fa443..426e1ccc6971a3832dd0afe18bc7c8aec295b22f 100644 --- a/arch/powerpc/kernel/vdso/vdso32.lds.S +++ b/arch/powerpc/kernel/vdso/vdso32.lds.S @@ -83,9 +83,11 @@ SECTIONS /DISCARD/ : { *(.note.GNU-stack) + *(*.EMB.apuinfo) + *(.branch_lt) *(.data .data.* .gnu.linkonce.d.* .sdata*) *(.bss .sbss .dynbss .dynsbss) - *(.got1) + *(.got1 .glink .iplt .rela*) } } diff --git a/arch/powerpc/kernel/vdso/vdso64.lds.S b/arch/powerpc/kernel/vdso/vdso64.lds.S index 744ae5363e6c8581c1ae839729154e68f8989745..bda6c8cdd459c0004a386c23e4f5149517752778 100644 --- a/arch/powerpc/kernel/vdso/vdso64.lds.S +++ b/arch/powerpc/kernel/vdso/vdso64.lds.S @@ -32,7 +32,7 @@ SECTIONS . = ALIGN(16); .text : { *(.text .stub .text.* .gnu.linkonce.t.* __ftr_alt_*) - *(.sfpr .glink) + *(.sfpr) } :text PROVIDE(__etext = .); PROVIDE(_etext = .); @@ -81,10 +81,12 @@ SECTIONS /DISCARD/ : { *(.note.GNU-stack) + *(*.EMB.apuinfo) *(.branch_lt) *(.data .data.* .gnu.linkonce.d.* .sdata*) *(.bss .sbss .dynbss .dynsbss) *(.opd) + *(.glink .iplt .plt .rela*) } } diff --git a/arch/powerpc/kernel/watchdog.c b/arch/powerpc/kernel/watchdog.c index dbcc4a793f0b9cea7df30edb4f5cbb32f5bfaa21..edb2dd1f53ebc8370a921636e1243f12ee1983b9 100644 --- a/arch/powerpc/kernel/watchdog.c +++ b/arch/powerpc/kernel/watchdog.c @@ -438,7 +438,7 @@ static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer) { int cpu = smp_processor_id(); - if (!(watchdog_enabled & NMI_WATCHDOG_ENABLED)) + if (!(watchdog_enabled & WATCHDOG_HARDLOCKUP_ENABLED)) return HRTIMER_NORESTART; if (!cpumask_test_cpu(cpu, &watchdog_cpumask)) @@ -479,7 +479,7 @@ static void start_watchdog(void *arg) return; } - if (!(watchdog_enabled & NMI_WATCHDOG_ENABLED)) + if (!(watchdog_enabled & WATCHDOG_HARDLOCKUP_ENABLED)) return; if (!cpumask_test_cpu(cpu, &watchdog_cpumask)) @@ -546,7 +546,7 @@ static void watchdog_calc_timeouts(void) wd_timer_period_ms = watchdog_thresh * 1000 * 2 / 5; } -void watchdog_nmi_stop(void) +void watchdog_hardlockup_stop(void) { int cpu; @@ -554,7 +554,7 @@ void watchdog_nmi_stop(void) stop_watchdog_on_cpu(cpu); } -void watchdog_nmi_start(void) +void watchdog_hardlockup_start(void) { int cpu; @@ -566,7 +566,7 @@ void watchdog_nmi_start(void) /* * Invoked from core watchdog init. */ -int __init watchdog_nmi_probe(void) +int __init watchdog_hardlockup_probe(void) { int err; @@ -582,7 +582,7 @@ int __init watchdog_nmi_probe(void) } #ifdef CONFIG_PPC_PSERIES -void watchdog_nmi_set_timeout_pct(u64 pct) +void watchdog_hardlockup_set_timeout_pct(u64 pct) { pr_info("Set the NMI watchdog timeout factor to %llu%%\n", pct); WRITE_ONCE(wd_timeout_pct, pct); diff --git a/arch/powerpc/kvm/book3s_64_mmu_radix.c b/arch/powerpc/kvm/book3s_64_mmu_radix.c index 461307b89c3a0a892fdbcdc5e7a11719a5f940f5..572707858d65d410bd07944eac10ceaca83abae7 100644 --- a/arch/powerpc/kvm/book3s_64_mmu_radix.c +++ b/arch/powerpc/kvm/book3s_64_mmu_radix.c @@ -509,7 +509,7 @@ static void kvmppc_unmap_free_pmd(struct kvm *kvm, pmd_t *pmd, bool full, } else { pte_t *pte; - pte = pte_offset_map(p, 0); + pte = pte_offset_kernel(p, 0); kvmppc_unmap_free_pte(kvm, pte, full, lpid); pmd_clear(p); } diff --git a/arch/powerpc/kvm/book3s_hv_builtin.c b/arch/powerpc/kvm/book3s_hv_builtin.c index da85f046377a4bbb1534ec884cf42cc13b99d466..0f5b021fa5590b59ac13227dcb952bd8e830d6ab 100644 --- a/arch/powerpc/kvm/book3s_hv_builtin.c +++ b/arch/powerpc/kvm/book3s_hv_builtin.c @@ -406,7 +406,7 @@ static long kvmppc_read_one_intr(bool *again) return 1; /* see if a host IPI is pending */ - host_ipi = local_paca->kvm_hstate.host_ipi; + host_ipi = READ_ONCE(local_paca->kvm_hstate.host_ipi); if (host_ipi) return 1; @@ -466,7 +466,7 @@ static long kvmppc_read_one_intr(bool *again) * meantime. If it's clear, we bounce the interrupt to the * guest */ - host_ipi = local_paca->kvm_hstate.host_ipi; + host_ipi = READ_ONCE(local_paca->kvm_hstate.host_ipi); if (unlikely(host_ipi != 0)) { /* We raced with the host, * we need to resend that IPI, bummer diff --git a/arch/powerpc/lib/Makefile b/arch/powerpc/lib/Makefile index c4db459d304a0825fdd5ab4ad0d6e4479fba2ffc..9aa8286c96871776cbc3bbbec7534ed0c331bfd2 100644 --- a/arch/powerpc/lib/Makefile +++ b/arch/powerpc/lib/Makefile @@ -44,7 +44,7 @@ obj-$(CONFIG_FUNCTION_ERROR_INJECTION) += error-inject.o # 64-bit linker creates .sfpr on demand for final link (vmlinux), # so it is only needed for modules, and only for older linkers which # do not support --save-restore-funcs -ifeq ($(call ld-ifversion, -lt, 22500, y),y) +ifndef CONFIG_LD_IS_BFD extra-$(CONFIG_PPC64) += crtsavres.o endif diff --git a/arch/powerpc/lib/qspinlock.c b/arch/powerpc/lib/qspinlock.c index e4bd145255d0010df9e87737e4c3a12f0d8282fb..253620979d0cd849a53d5853d2e995fa4fb6fc69 100644 --- a/arch/powerpc/lib/qspinlock.c +++ b/arch/powerpc/lib/qspinlock.c @@ -161,6 +161,8 @@ static __always_inline u32 publish_tail_cpu(struct qspinlock *lock, u32 tail) { u32 prev, tmp; + kcsan_release(); + asm volatile( "\t" PPC_RELEASE_BARRIER " \n" "1: lwarx %0,0,%2 # publish_tail_cpu \n" @@ -435,7 +437,7 @@ static __always_inline bool yield_to_prev(struct qspinlock *lock, struct qnode * smp_rmb(); /* See __yield_to_locked_owner comment */ - if (!node->locked) { + if (!READ_ONCE(node->locked)) { yield_to_preempted(prev_cpu, yield_count); spin_begin(); return preempted; @@ -570,6 +572,11 @@ static __always_inline void queued_spin_lock_mcs_queue(struct qspinlock *lock, b tail = encode_tail_cpu(node->cpu); + /* + * Assign all attributes of a node before it can be published. + * Issues an lwsync, serving as a release barrier, as well as a + * compiler barrier. + */ old = publish_tail_cpu(lock, tail); /* @@ -584,7 +591,7 @@ static __always_inline void queued_spin_lock_mcs_queue(struct qspinlock *lock, b /* Wait for mcs node lock to be released */ spin_begin(); - while (!node->locked) { + while (!READ_ONCE(node->locked)) { spec_barrier(); if (yield_to_prev(lock, node, old, paravirt)) diff --git a/arch/powerpc/mm/book3s32/hash_low.S b/arch/powerpc/mm/book3s32/hash_low.S index 6925ce9985571e2fb9d138fe5a2e86ea48f26f07..a5a21d444e729db5f8a09f7437d710d25579f84b 100644 --- a/arch/powerpc/mm/book3s32/hash_low.S +++ b/arch/powerpc/mm/book3s32/hash_low.S @@ -199,12 +199,12 @@ _GLOBAL(add_hash_page) lis r6, (mmu_hash_lock - PAGE_OFFSET)@ha addi r6, r6, (mmu_hash_lock - PAGE_OFFSET)@l 10: lwarx r0,0,r6 /* take the mmu_hash_lock */ - cmpi 0,r0,0 + cmpwi 0,r0,0 bne- 11f stwcx. r8,0,r6 beq+ 12f 11: lwz r0,0(r6) - cmpi 0,r0,0 + cmpwi 0,r0,0 beq 10b b 11b 12: isync @@ -512,12 +512,12 @@ _GLOBAL(flush_hash_pages) lwz r8, TASK_CPU(r8) oris r8,r8,9 10: lwarx r0,0,r9 - cmpi 0,r0,0 + cmpwi 0,r0,0 bne- 11f stwcx. r8,0,r9 beq+ 12f 11: lwz r0,0(r9) - cmpi 0,r0,0 + cmpwi 0,r0,0 beq 10b b 11b 12: isync diff --git a/arch/powerpc/mm/book3s64/hash_native.c b/arch/powerpc/mm/book3s64/hash_native.c index 9342e79870dfd408bb8220ed1865c8f9e1959f9e..430d1d935a7cb5c6355aeac0c0037b00cec84a17 100644 --- a/arch/powerpc/mm/book3s64/hash_native.c +++ b/arch/powerpc/mm/book3s64/hash_native.c @@ -328,10 +328,12 @@ static long native_hpte_insert(unsigned long hpte_group, unsigned long vpn, static long native_hpte_remove(unsigned long hpte_group) { + unsigned long hpte_v, flags; struct hash_pte *hptep; int i; int slot_offset; - unsigned long hpte_v; + + local_irq_save(flags); DBG_LOW(" remove(group=%lx)\n", hpte_group); @@ -356,13 +358,16 @@ static long native_hpte_remove(unsigned long hpte_group) slot_offset &= 0x7; } - if (i == HPTES_PER_GROUP) - return -1; + if (i == HPTES_PER_GROUP) { + i = -1; + goto out; + } /* Invalidate the hpte. NOTE: this also unlocks it */ release_hpte_lock(); hptep->v = 0; - +out: + local_irq_restore(flags); return i; } diff --git a/arch/powerpc/mm/book3s64/hash_tlb.c b/arch/powerpc/mm/book3s64/hash_tlb.c index a64ea0a7ef96d2acf9f6e738a52a30523ab95cb4..21fcad97ae80dd46fe28b6f195150d82f52979d8 100644 --- a/arch/powerpc/mm/book3s64/hash_tlb.c +++ b/arch/powerpc/mm/book3s64/hash_tlb.c @@ -239,12 +239,16 @@ void flush_hash_table_pmd_range(struct mm_struct *mm, pmd_t *pmd, unsigned long local_irq_save(flags); arch_enter_lazy_mmu_mode(); start_pte = pte_offset_map(pmd, addr); + if (!start_pte) + goto out; for (pte = start_pte; pte < start_pte + PTRS_PER_PTE; pte++) { unsigned long pteval = pte_val(*pte); if (pteval & H_PAGE_HASHPTE) hpte_need_flush(mm, addr, pte, pteval, 0); addr += PAGE_SIZE; } + pte_unmap(start_pte); +out: arch_leave_lazy_mmu_mode(); local_irq_restore(flags); } diff --git a/arch/powerpc/mm/book3s64/iommu_api.c b/arch/powerpc/mm/book3s64/iommu_api.c index 81d7185e2ae89c1a14825b1edbd2fa27e9c44f19..d19fb1f3007d2df32394a87138b545802d78819d 100644 --- a/arch/powerpc/mm/book3s64/iommu_api.c +++ b/arch/powerpc/mm/book3s64/iommu_api.c @@ -105,7 +105,7 @@ static long mm_iommu_do_alloc(struct mm_struct *mm, unsigned long ua, ret = pin_user_pages(ua + (entry << PAGE_SHIFT), n, FOLL_WRITE | FOLL_LONGTERM, - mem->hpages + entry, NULL); + mem->hpages + entry); if (ret == n) { pinned += n; continue; diff --git a/arch/powerpc/mm/book3s64/radix_pgtable.c b/arch/powerpc/mm/book3s64/radix_pgtable.c index 2297aa764ecdbcedbaf7958df234f5d5c4408470..e7ea492ac510a8c447368a6fc192bfcacde14f37 100644 --- a/arch/powerpc/mm/book3s64/radix_pgtable.c +++ b/arch/powerpc/mm/book3s64/radix_pgtable.c @@ -745,9 +745,9 @@ static void free_pud_table(pud_t *pud_start, p4d_t *p4d) } static void remove_pte_table(pte_t *pte_start, unsigned long addr, - unsigned long end) + unsigned long end, bool direct) { - unsigned long next; + unsigned long next, pages = 0; pte_t *pte; pte = pte_start + pte_index(addr); @@ -769,13 +769,16 @@ static void remove_pte_table(pte_t *pte_start, unsigned long addr, } pte_clear(&init_mm, addr, pte); + pages++; } + if (direct) + update_page_count(mmu_virtual_psize, -pages); } static void __meminit remove_pmd_table(pmd_t *pmd_start, unsigned long addr, - unsigned long end) + unsigned long end, bool direct) { - unsigned long next; + unsigned long next, pages = 0; pte_t *pte_base; pmd_t *pmd; @@ -793,19 +796,22 @@ static void __meminit remove_pmd_table(pmd_t *pmd_start, unsigned long addr, continue; } pte_clear(&init_mm, addr, (pte_t *)pmd); + pages++; continue; } pte_base = (pte_t *)pmd_page_vaddr(*pmd); - remove_pte_table(pte_base, addr, next); + remove_pte_table(pte_base, addr, next, direct); free_pte_table(pte_base, pmd); } + if (direct) + update_page_count(MMU_PAGE_2M, -pages); } static void __meminit remove_pud_table(pud_t *pud_start, unsigned long addr, - unsigned long end) + unsigned long end, bool direct) { - unsigned long next; + unsigned long next, pages = 0; pmd_t *pmd_base; pud_t *pud; @@ -823,16 +829,20 @@ static void __meminit remove_pud_table(pud_t *pud_start, unsigned long addr, continue; } pte_clear(&init_mm, addr, (pte_t *)pud); + pages++; continue; } pmd_base = pud_pgtable(*pud); - remove_pmd_table(pmd_base, addr, next); + remove_pmd_table(pmd_base, addr, next, direct); free_pmd_table(pmd_base, pud); } + if (direct) + update_page_count(MMU_PAGE_1G, -pages); } -static void __meminit remove_pagetable(unsigned long start, unsigned long end) +static void __meminit remove_pagetable(unsigned long start, unsigned long end, + bool direct) { unsigned long addr, next; pud_t *pud_base; @@ -861,7 +871,7 @@ static void __meminit remove_pagetable(unsigned long start, unsigned long end) } pud_base = p4d_pgtable(*p4d); - remove_pud_table(pud_base, addr, next); + remove_pud_table(pud_base, addr, next, direct); free_pud_table(pud_base, p4d); } @@ -884,7 +894,7 @@ int __meminit radix__create_section_mapping(unsigned long start, int __meminit radix__remove_section_mapping(unsigned long start, unsigned long end) { - remove_pagetable(start, end); + remove_pagetable(start, end, true); return 0; } #endif /* CONFIG_MEMORY_HOTPLUG */ @@ -902,7 +912,6 @@ int __meminit radix__vmemmap_create_mapping(unsigned long start, unsigned long phys) { /* Create a PTE encoding */ - unsigned long flags = _PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_KERNEL_RW; int nid = early_pfn_to_nid(phys >> PAGE_SHIFT); int ret; @@ -911,7 +920,7 @@ int __meminit radix__vmemmap_create_mapping(unsigned long start, return -1; } - ret = __map_kernel_page_nid(start, phys, __pgprot(flags), page_size, nid); + ret = __map_kernel_page_nid(start, phys, PAGE_KERNEL, page_size, nid); BUG_ON(ret); return 0; @@ -920,7 +929,7 @@ int __meminit radix__vmemmap_create_mapping(unsigned long start, #ifdef CONFIG_MEMORY_HOTPLUG void __meminit radix__vmemmap_remove_mapping(unsigned long start, unsigned long page_size) { - remove_pagetable(start, start + page_size); + remove_pagetable(start, start + page_size, false); } #endif #endif @@ -952,7 +961,7 @@ unsigned long radix__pmd_hugepage_update(struct mm_struct *mm, unsigned long add assert_spin_locked(pmd_lockptr(mm, pmdp)); #endif - old = radix__pte_update(mm, addr, (pte_t *)pmdp, clr, set, 1); + old = radix__pte_update(mm, addr, pmdp_ptep(pmdp), clr, set, 1); trace_hugepage_update(addr, old, clr, set); return old; diff --git a/arch/powerpc/mm/book3s64/radix_tlb.c b/arch/powerpc/mm/book3s64/radix_tlb.c index ce804b7bf84e42c131634e7639c93096f4acfe9d..0bd4866d98241d68546ec7669fc265b93866badb 100644 --- a/arch/powerpc/mm/book3s64/radix_tlb.c +++ b/arch/powerpc/mm/book3s64/radix_tlb.c @@ -795,12 +795,20 @@ void exit_lazy_flush_tlb(struct mm_struct *mm, bool always_flush) goto out; if (current->active_mm == mm) { + unsigned long flags; + WARN_ON_ONCE(current->mm != NULL); - /* Is a kernel thread and is using mm as the lazy tlb */ + /* + * It is a kernel thread and is using mm as the lazy tlb, so + * switch it to init_mm. This is not always called from IPI + * (e.g., flush_type_needed), so must disable irqs. + */ + local_irq_save(flags); mmgrab_lazy_tlb(&init_mm); current->active_mm = &init_mm; switch_mm_irqs_off(mm, &init_mm, current); mmdrop_lazy_tlb(mm); + local_irq_restore(flags); } /* diff --git a/arch/powerpc/mm/book3s64/subpage_prot.c b/arch/powerpc/mm/book3s64/subpage_prot.c index b75a9fb99599a146ed61607c374eca0842f913a1..0dc85556dec55f0e8eb87b3b69016024a1ef68f7 100644 --- a/arch/powerpc/mm/book3s64/subpage_prot.c +++ b/arch/powerpc/mm/book3s64/subpage_prot.c @@ -71,6 +71,8 @@ static void hpte_flush_range(struct mm_struct *mm, unsigned long addr, if (pmd_none(*pmd)) return; pte = pte_offset_map_lock(mm, pmd, addr, &ptl); + if (!pte) + return; arch_enter_lazy_mmu_mode(); for (; npages > 0; --npages) { pte_update(mm, addr, pte, 0, 0, 0); diff --git a/arch/powerpc/mm/copro_fault.c b/arch/powerpc/mm/copro_fault.c index 7c507fb48182bd461da33036b67cdcef946f93fb..f49fd873df8da239e3c24934bfae3ca646ca875a 100644 --- a/arch/powerpc/mm/copro_fault.c +++ b/arch/powerpc/mm/copro_fault.c @@ -33,19 +33,11 @@ int copro_handle_mm_fault(struct mm_struct *mm, unsigned long ea, if (mm->pgd == NULL) return -EFAULT; - mmap_read_lock(mm); - ret = -EFAULT; - vma = find_vma(mm, ea); + vma = lock_mm_and_find_vma(mm, ea, NULL); if (!vma) - goto out_unlock; - - if (ea < vma->vm_start) { - if (!(vma->vm_flags & VM_GROWSDOWN)) - goto out_unlock; - if (expand_stack(vma, ea)) - goto out_unlock; - } + return -EFAULT; + ret = -EFAULT; is_write = dsisr & DSISR_ISSTORE; if (is_write) { if (!(vma->vm_flags & VM_WRITE)) diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c index 531177a4ee0881b412c2b8ded4b62d9902107f1e..5bfdf6ecfa9650f9f102a9872bce3b0d5d031da2 100644 --- a/arch/powerpc/mm/fault.c +++ b/arch/powerpc/mm/fault.c @@ -84,11 +84,6 @@ static int __bad_area(struct pt_regs *regs, unsigned long address, int si_code) return __bad_area_nosemaphore(regs, address, si_code); } -static noinline int bad_area(struct pt_regs *regs, unsigned long address) -{ - return __bad_area(regs, address, SEGV_MAPERR); -} - static noinline int bad_access_pkey(struct pt_regs *regs, unsigned long address, struct vm_area_struct *vma) { @@ -515,40 +510,12 @@ static int ___do_page_fault(struct pt_regs *regs, unsigned long address, * we will deadlock attempting to validate the fault against the * address space. Luckily the kernel only validly references user * space from well defined areas of code, which are listed in the - * exceptions table. - * - * As the vast majority of faults will be valid we will only perform - * the source reference check when there is a possibility of a deadlock. - * Attempt to lock the address space, if we cannot we then validate the - * source. If this is invalid we can skip the address space check, - * thus avoiding the deadlock. + * exceptions table. lock_mm_and_find_vma() handles that logic. */ - if (unlikely(!mmap_read_trylock(mm))) { - if (!is_user && !search_exception_tables(regs->nip)) - return bad_area_nosemaphore(regs, address); - retry: - mmap_read_lock(mm); - } else { - /* - * The above down_read_trylock() might have succeeded in - * which case we'll have missed the might_sleep() from - * down_read(): - */ - might_sleep(); - } - - vma = find_vma(mm, address); + vma = lock_mm_and_find_vma(mm, address, regs); if (unlikely(!vma)) - return bad_area(regs, address); - - if (unlikely(vma->vm_start > address)) { - if (unlikely(!(vma->vm_flags & VM_GROWSDOWN))) - return bad_area(regs, address); - - if (unlikely(expand_stack(vma, address))) - return bad_area(regs, address); - } + return bad_area_nosemaphore(regs, address); if (unlikely(access_pkey_error(is_write, is_exec, (error_code & DSISR_KEYFAULT), vma))) diff --git a/arch/powerpc/mm/hugetlbpage.c b/arch/powerpc/mm/hugetlbpage.c index b900933507da17e73403c0f1d4e5884e1d31944d..f7c683b672c1849a49a6f817236256219d8439a2 100644 --- a/arch/powerpc/mm/hugetlbpage.c +++ b/arch/powerpc/mm/hugetlbpage.c @@ -183,7 +183,7 @@ pte_t *huge_pte_alloc(struct mm_struct *mm, struct vm_area_struct *vma, return NULL; if (IS_ENABLED(CONFIG_PPC_8xx) && pshift < PMD_SHIFT) - return pte_alloc_map(mm, (pmd_t *)hpdp, addr); + return pte_alloc_huge(mm, (pmd_t *)hpdp, addr); BUG_ON(!hugepd_none(*hpdp) && !hugepd_ok(*hpdp)); diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c index 05b0d584e50b82a1ded312baa1ba9a84d50de8ca..fe1b83020e0df0c700eae0a816d5257c1059cc76 100644 --- a/arch/powerpc/mm/init_64.c +++ b/arch/powerpc/mm/init_64.c @@ -189,7 +189,7 @@ static bool altmap_cross_boundary(struct vmem_altmap *altmap, unsigned long star unsigned long nr_pfn = page_size / sizeof(struct page); unsigned long start_pfn = page_to_pfn((struct page *)start); - if ((start_pfn + nr_pfn) > altmap->end_pfn) + if ((start_pfn + nr_pfn - 1) > altmap->end_pfn) return true; if (start_pfn < altmap->base_pfn) diff --git a/arch/powerpc/platforms/44x/ppc476.c b/arch/powerpc/platforms/44x/ppc476.c index fbc6edad481f8dddcaca849973adb2879596e190..164cbcd4588e4c3b8b7e34f6a482675e59fe4c79 100644 --- a/arch/powerpc/platforms/44x/ppc476.c +++ b/arch/powerpc/platforms/44x/ppc476.c @@ -103,7 +103,7 @@ static struct i2c_driver avr_driver = { .driver = { .name = "akebono-avr", }, - .probe_new = avr_probe, + .probe = avr_probe, .id_table = avr_id, }; diff --git a/arch/powerpc/platforms/512x/mpc512x_lpbfifo.c b/arch/powerpc/platforms/512x/mpc512x_lpbfifo.c index 04bf6ecf7d55d68a2233de27662132d992350412..1bfb29574caa7f7fb19f133b1f6c3de3b2f15cab 100644 --- a/arch/powerpc/platforms/512x/mpc512x_lpbfifo.c +++ b/arch/powerpc/platforms/512x/mpc512x_lpbfifo.c @@ -373,50 +373,32 @@ static int get_cs_ranges(struct device *dev) { int ret = -ENODEV; struct device_node *lb_node; - const u32 *addr_cells_p; - const u32 *size_cells_p; - int proplen; - size_t i; + size_t i = 0; + struct of_range_parser parser; + struct of_range range; lb_node = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-localbus"); if (!lb_node) return ret; - /* - * The node defined as compatible with 'fsl,mpc5121-localbus' - * should have two address cells and one size cell. - * Every item of its ranges property should consist of: - * - the first address cell which is the chipselect number; - * - the second address cell which is the offset in the chipselect, - * must be zero. - * - CPU address of the beginning of an access window; - * - the only size cell which is the size of an access window. - */ - addr_cells_p = of_get_property(lb_node, "#address-cells", NULL); - size_cells_p = of_get_property(lb_node, "#size-cells", NULL); - if (addr_cells_p == NULL || *addr_cells_p != 2 || - size_cells_p == NULL || *size_cells_p != 1) { - goto end; - } - - proplen = of_property_count_u32_elems(lb_node, "ranges"); - if (proplen <= 0 || proplen % 4 != 0) - goto end; + of_range_parser_init(&parser, lb_node); + lpbfifo.cs_n = of_range_count(&parser); - lpbfifo.cs_n = proplen / 4; lpbfifo.cs_ranges = devm_kcalloc(dev, lpbfifo.cs_n, sizeof(struct cs_range), GFP_KERNEL); if (!lpbfifo.cs_ranges) goto end; - if (of_property_read_u32_array(lb_node, "ranges", - (u32 *)lpbfifo.cs_ranges, proplen) != 0) { - goto end; - } - - for (i = 0; i < lpbfifo.cs_n; i++) { - if (lpbfifo.cs_ranges[i].base != 0) + for_each_of_range(&parser, &range) { + u32 base = lower_32_bits(range.bus_addr); + if (base) goto end; + + lpbfifo.cs_ranges[i].csnum = upper_32_bits(range.bus_addr); + lpbfifo.cs_ranges[i].base = base; + lpbfifo.cs_ranges[i].addr = range.cpu_addr; + lpbfifo.cs_ranges[i].size = range.size; + i++; } ret = 0; diff --git a/arch/powerpc/platforms/52xx/Kconfig b/arch/powerpc/platforms/52xx/Kconfig index b72ed2950ca8edc6536ae0ebb35cdb5585ad6e7c..384e4bef2c284f82dc0a465e8133e3b553733d37 100644 --- a/arch/powerpc/platforms/52xx/Kconfig +++ b/arch/powerpc/platforms/52xx/Kconfig @@ -54,8 +54,3 @@ config PPC_MPC5200_BUGFIX for MPC5200B based boards. It is safe to say 'Y' here - -config PPC_MPC5200_LPBFIFO - tristate "MPC5200 LocalPlus bus FIFO driver" - depends on PPC_MPC52xx && PPC_BESTCOMM - select PPC_BESTCOMM_GEN_BD diff --git a/arch/powerpc/platforms/52xx/Makefile b/arch/powerpc/platforms/52xx/Makefile index f40d48eab7792da0a4f9cbfbf0ff4699e29a829e..1b1f72d83342b90b1e7d632edca42709502127e8 100644 --- a/arch/powerpc/platforms/52xx/Makefile +++ b/arch/powerpc/platforms/52xx/Makefile @@ -14,5 +14,3 @@ obj-$(CONFIG_PM) += mpc52xx_sleep.o mpc52xx_pm.o ifdef CONFIG_PPC_LITE5200 obj-$(CONFIG_PM) += lite5200_sleep.o lite5200_pm.o endif - -obj-$(CONFIG_PPC_MPC5200_LPBFIFO) += mpc52xx_lpbfifo.o diff --git a/arch/powerpc/platforms/52xx/lite5200_pm.c b/arch/powerpc/platforms/52xx/lite5200_pm.c index ee29b63fca160d8c87cd2b13f2780ace7e2efba8..4900f5f48ccef414d21f9402cfbf7b1c55abf9bf 100644 --- a/arch/powerpc/platforms/52xx/lite5200_pm.c +++ b/arch/powerpc/platforms/52xx/lite5200_pm.c @@ -47,7 +47,7 @@ static int lite5200_pm_begin(suspend_state_t state) static int lite5200_pm_prepare(void) { struct device_node *np; - const struct of_device_id immr_ids[] = { + static const struct of_device_id immr_ids[] = { { .compatible = "fsl,mpc5200-immr", }, { .compatible = "fsl,mpc5200b-immr", }, { .type = "soc", .compatible = "mpc5200", }, /* lite5200 */ diff --git a/arch/powerpc/platforms/52xx/mpc52xx_lpbfifo.c b/arch/powerpc/platforms/52xx/mpc52xx_lpbfifo.c deleted file mode 100644 index 6d1dd6e874786538e6c2d8b847f35037040deb52..0000000000000000000000000000000000000000 --- a/arch/powerpc/platforms/52xx/mpc52xx_lpbfifo.c +++ /dev/null @@ -1,594 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * LocalPlus Bus FIFO driver for the Freescale MPC52xx. - * - * Copyright (C) 2009 Secret Lab Technologies Ltd. - * - * Todo: - * - Add support for multiple requests to be queued. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -MODULE_AUTHOR("Grant Likely "); -MODULE_DESCRIPTION("MPC5200 LocalPlus FIFO device driver"); -MODULE_LICENSE("GPL"); - -#define LPBFIFO_REG_PACKET_SIZE (0x00) -#define LPBFIFO_REG_START_ADDRESS (0x04) -#define LPBFIFO_REG_CONTROL (0x08) -#define LPBFIFO_REG_ENABLE (0x0C) -#define LPBFIFO_REG_BYTES_DONE_STATUS (0x14) -#define LPBFIFO_REG_FIFO_DATA (0x40) -#define LPBFIFO_REG_FIFO_STATUS (0x44) -#define LPBFIFO_REG_FIFO_CONTROL (0x48) -#define LPBFIFO_REG_FIFO_ALARM (0x4C) - -struct mpc52xx_lpbfifo { - struct device *dev; - phys_addr_t regs_phys; - void __iomem *regs; - int irq; - spinlock_t lock; - - struct bcom_task *bcom_tx_task; - struct bcom_task *bcom_rx_task; - struct bcom_task *bcom_cur_task; - - /* Current state data */ - struct mpc52xx_lpbfifo_request *req; - int dma_irqs_enabled; -}; - -/* The MPC5200 has only one fifo, so only need one instance structure */ -static struct mpc52xx_lpbfifo lpbfifo; - -/** - * mpc52xx_lpbfifo_kick - Trigger the next block of data to be transferred - * - * @req: Pointer to request structure - */ -static void mpc52xx_lpbfifo_kick(struct mpc52xx_lpbfifo_request *req) -{ - size_t transfer_size = req->size - req->pos; - struct bcom_bd *bd; - void __iomem *reg; - u32 *data; - int i; - int bit_fields; - int dma = !(req->flags & MPC52XX_LPBFIFO_FLAG_NO_DMA); - int write = req->flags & MPC52XX_LPBFIFO_FLAG_WRITE; - int poll_dma = req->flags & MPC52XX_LPBFIFO_FLAG_POLL_DMA; - - /* Set and clear the reset bits; is good practice in User Manual */ - out_be32(lpbfifo.regs + LPBFIFO_REG_ENABLE, 0x01010000); - - /* set master enable bit */ - out_be32(lpbfifo.regs + LPBFIFO_REG_ENABLE, 0x00000001); - if (!dma) { - /* While the FIFO can be setup for transfer sizes as large as - * 16M-1, the FIFO itself is only 512 bytes deep and it does - * not generate interrupts for FIFO full events (only transfer - * complete will raise an IRQ). Therefore when not using - * Bestcomm to drive the FIFO it needs to either be polled, or - * transfers need to constrained to the size of the fifo. - * - * This driver restricts the size of the transfer - */ - if (transfer_size > 512) - transfer_size = 512; - - /* Load the FIFO with data */ - if (write) { - reg = lpbfifo.regs + LPBFIFO_REG_FIFO_DATA; - data = req->data + req->pos; - for (i = 0; i < transfer_size; i += 4) - out_be32(reg, *data++); - } - - /* Unmask both error and completion irqs */ - out_be32(lpbfifo.regs + LPBFIFO_REG_ENABLE, 0x00000301); - } else { - /* Choose the correct direction - * - * Configure the watermarks so DMA will always complete correctly. - * It may be worth experimenting with the ALARM value to see if - * there is a performance impact. However, if it is wrong there - * is a risk of DMA not transferring the last chunk of data - */ - if (write) { - out_be32(lpbfifo.regs + LPBFIFO_REG_FIFO_ALARM, 0x1e4); - out_8(lpbfifo.regs + LPBFIFO_REG_FIFO_CONTROL, 7); - lpbfifo.bcom_cur_task = lpbfifo.bcom_tx_task; - } else { - out_be32(lpbfifo.regs + LPBFIFO_REG_FIFO_ALARM, 0x1ff); - out_8(lpbfifo.regs + LPBFIFO_REG_FIFO_CONTROL, 0); - lpbfifo.bcom_cur_task = lpbfifo.bcom_rx_task; - - if (poll_dma) { - if (lpbfifo.dma_irqs_enabled) { - disable_irq(bcom_get_task_irq(lpbfifo.bcom_rx_task)); - lpbfifo.dma_irqs_enabled = 0; - } - } else { - if (!lpbfifo.dma_irqs_enabled) { - enable_irq(bcom_get_task_irq(lpbfifo.bcom_rx_task)); - lpbfifo.dma_irqs_enabled = 1; - } - } - } - - bd = bcom_prepare_next_buffer(lpbfifo.bcom_cur_task); - bd->status = transfer_size; - if (!write) { - /* - * In the DMA read case, the DMA doesn't complete, - * possibly due to incorrect watermarks in the ALARM - * and CONTROL regs. For now instead of trying to - * determine the right watermarks that will make this - * work, just increase the number of bytes the FIFO is - * expecting. - * - * When submitting another operation, the FIFO will get - * reset, so the condition of the FIFO waiting for a - * non-existent 4 bytes will get cleared. - */ - transfer_size += 4; /* BLECH! */ - } - bd->data[0] = req->data_phys + req->pos; - bcom_submit_next_buffer(lpbfifo.bcom_cur_task, NULL); - - /* error irq & master enabled bit */ - bit_fields = 0x00000201; - - /* Unmask irqs */ - if (write && (!poll_dma)) - bit_fields |= 0x00000100; /* completion irq too */ - out_be32(lpbfifo.regs + LPBFIFO_REG_ENABLE, bit_fields); - } - - /* Set transfer size, width, chip select and READ mode */ - out_be32(lpbfifo.regs + LPBFIFO_REG_START_ADDRESS, - req->offset + req->pos); - out_be32(lpbfifo.regs + LPBFIFO_REG_PACKET_SIZE, transfer_size); - - bit_fields = req->cs << 24 | 0x000008; - if (!write) - bit_fields |= 0x010000; /* read mode */ - out_be32(lpbfifo.regs + LPBFIFO_REG_CONTROL, bit_fields); - - /* Kick it off */ - if (!lpbfifo.req->defer_xfer_start) - out_8(lpbfifo.regs + LPBFIFO_REG_PACKET_SIZE, 0x01); - if (dma) - bcom_enable(lpbfifo.bcom_cur_task); -} - -/** - * mpc52xx_lpbfifo_irq - IRQ handler for LPB FIFO - * @irq: IRQ number to be handled - * @dev_id: device ID cookie - * - * On transmit, the dma completion irq triggers before the fifo completion - * triggers. Handle the dma completion here instead of the LPB FIFO Bestcomm - * task completion irq because everything is not really done until the LPB FIFO - * completion irq triggers. - * - * In other words: - * For DMA, on receive, the "Fat Lady" is the bestcom completion irq. on - * transmit, the fifo completion irq is the "Fat Lady". The opera (or in this - * case the DMA/FIFO operation) is not finished until the "Fat Lady" sings. - * - * Reasons for entering this routine: - * 1) PIO mode rx and tx completion irq - * 2) DMA interrupt mode tx completion irq - * 3) DMA polled mode tx - * - * Exit conditions: - * 1) Transfer aborted - * 2) FIFO complete without DMA; more data to do - * 3) FIFO complete without DMA; all data transferred - * 4) FIFO complete using DMA - * - * Condition 1 can occur regardless of whether or not DMA is used. - * It requires executing the callback to report the error and exiting - * immediately. - * - * Condition 2 requires programming the FIFO with the next block of data - * - * Condition 3 requires executing the callback to report completion - * - * Condition 4 means the same as 3, except that we also retrieve the bcom - * buffer so DMA doesn't get clogged up. - * - * To make things trickier, the spinlock must be dropped before - * executing the callback, otherwise we could end up with a deadlock - * or nested spinlock condition. The out path is non-trivial, so - * extra fiddling is done to make sure all paths lead to the same - * outbound code. - * - * Return: irqreturn code (%IRQ_HANDLED) - */ -static irqreturn_t mpc52xx_lpbfifo_irq(int irq, void *dev_id) -{ - struct mpc52xx_lpbfifo_request *req; - u32 status = in_8(lpbfifo.regs + LPBFIFO_REG_BYTES_DONE_STATUS); - void __iomem *reg; - u32 *data; - int count, i; - int do_callback = 0; - u32 ts; - unsigned long flags; - int dma, write, poll_dma; - - spin_lock_irqsave(&lpbfifo.lock, flags); - ts = mftb(); - - req = lpbfifo.req; - if (!req) { - spin_unlock_irqrestore(&lpbfifo.lock, flags); - pr_err("bogus LPBFIFO IRQ\n"); - return IRQ_HANDLED; - } - - dma = !(req->flags & MPC52XX_LPBFIFO_FLAG_NO_DMA); - write = req->flags & MPC52XX_LPBFIFO_FLAG_WRITE; - poll_dma = req->flags & MPC52XX_LPBFIFO_FLAG_POLL_DMA; - - if (dma && !write) { - spin_unlock_irqrestore(&lpbfifo.lock, flags); - pr_err("bogus LPBFIFO IRQ (dma and not writing)\n"); - return IRQ_HANDLED; - } - - if ((status & 0x01) == 0) { - goto out; - } - - /* check abort bit */ - if (status & 0x10) { - out_be32(lpbfifo.regs + LPBFIFO_REG_ENABLE, 0x01010000); - do_callback = 1; - goto out; - } - - /* Read result from hardware */ - count = in_be32(lpbfifo.regs + LPBFIFO_REG_BYTES_DONE_STATUS); - count &= 0x00ffffff; - - if (!dma && !write) { - /* copy the data out of the FIFO */ - reg = lpbfifo.regs + LPBFIFO_REG_FIFO_DATA; - data = req->data + req->pos; - for (i = 0; i < count; i += 4) - *data++ = in_be32(reg); - } - - /* Update transfer position and count */ - req->pos += count; - - /* Decide what to do next */ - if (req->size - req->pos) - mpc52xx_lpbfifo_kick(req); /* more work to do */ - else - do_callback = 1; - - out: - /* Clear the IRQ */ - out_8(lpbfifo.regs + LPBFIFO_REG_BYTES_DONE_STATUS, 0x01); - - if (dma && (status & 0x11)) { - /* - * Count the DMA as complete only when the FIFO completion - * status or abort bits are set. - * - * (status & 0x01) should always be the case except sometimes - * when using polled DMA. - * - * (status & 0x10) {transfer aborted}: This case needs more - * testing. - */ - bcom_retrieve_buffer(lpbfifo.bcom_cur_task, &status, NULL); - } - req->last_byte = ((u8 *)req->data)[req->size - 1]; - - /* When the do_callback flag is set; it means the transfer is finished - * so set the FIFO as idle */ - if (do_callback) - lpbfifo.req = NULL; - - if (irq != 0) /* don't increment on polled case */ - req->irq_count++; - - req->irq_ticks += mftb() - ts; - spin_unlock_irqrestore(&lpbfifo.lock, flags); - - /* Spinlock is released; it is now safe to call the callback */ - if (do_callback && req->callback) - req->callback(req); - - return IRQ_HANDLED; -} - -/** - * mpc52xx_lpbfifo_bcom_irq - IRQ handler for LPB FIFO Bestcomm task - * @irq: IRQ number to be handled - * @dev_id: device ID cookie - * - * Only used when receiving data. - * - * Return: irqreturn code (%IRQ_HANDLED) - */ -static irqreturn_t mpc52xx_lpbfifo_bcom_irq(int irq, void *dev_id) -{ - struct mpc52xx_lpbfifo_request *req; - unsigned long flags; - u32 status; - u32 ts; - - spin_lock_irqsave(&lpbfifo.lock, flags); - ts = mftb(); - - req = lpbfifo.req; - if (!req || (req->flags & MPC52XX_LPBFIFO_FLAG_NO_DMA)) { - spin_unlock_irqrestore(&lpbfifo.lock, flags); - return IRQ_HANDLED; - } - - if (irq != 0) /* don't increment on polled case */ - req->irq_count++; - - if (!bcom_buffer_done(lpbfifo.bcom_cur_task)) { - spin_unlock_irqrestore(&lpbfifo.lock, flags); - - req->buffer_not_done_cnt++; - if ((req->buffer_not_done_cnt % 1000) == 0) - pr_err("transfer stalled\n"); - - return IRQ_HANDLED; - } - - bcom_retrieve_buffer(lpbfifo.bcom_cur_task, &status, NULL); - - req->last_byte = ((u8 *)req->data)[req->size - 1]; - - req->pos = status & 0x00ffffff; - - /* Mark the FIFO as idle */ - lpbfifo.req = NULL; - - /* Release the lock before calling out to the callback. */ - req->irq_ticks += mftb() - ts; - spin_unlock_irqrestore(&lpbfifo.lock, flags); - - if (req->callback) - req->callback(req); - - return IRQ_HANDLED; -} - -/** - * mpc52xx_lpbfifo_poll - Poll for DMA completion - */ -void mpc52xx_lpbfifo_poll(void) -{ - struct mpc52xx_lpbfifo_request *req = lpbfifo.req; - int dma = !(req->flags & MPC52XX_LPBFIFO_FLAG_NO_DMA); - int write = req->flags & MPC52XX_LPBFIFO_FLAG_WRITE; - - /* - * For more information, see comments on the "Fat Lady" - */ - if (dma && write) - mpc52xx_lpbfifo_irq(0, NULL); - else - mpc52xx_lpbfifo_bcom_irq(0, NULL); -} -EXPORT_SYMBOL(mpc52xx_lpbfifo_poll); - -/** - * mpc52xx_lpbfifo_submit - Submit an LPB FIFO transfer request. - * @req: Pointer to request structure - * - * Return: %0 on success, -errno code on error - */ -int mpc52xx_lpbfifo_submit(struct mpc52xx_lpbfifo_request *req) -{ - unsigned long flags; - - if (!lpbfifo.regs) - return -ENODEV; - - spin_lock_irqsave(&lpbfifo.lock, flags); - - /* If the req pointer is already set, then a transfer is in progress */ - if (lpbfifo.req) { - spin_unlock_irqrestore(&lpbfifo.lock, flags); - return -EBUSY; - } - - /* Setup the transfer */ - lpbfifo.req = req; - req->irq_count = 0; - req->irq_ticks = 0; - req->buffer_not_done_cnt = 0; - req->pos = 0; - - mpc52xx_lpbfifo_kick(req); - spin_unlock_irqrestore(&lpbfifo.lock, flags); - return 0; -} -EXPORT_SYMBOL(mpc52xx_lpbfifo_submit); - -int mpc52xx_lpbfifo_start_xfer(struct mpc52xx_lpbfifo_request *req) -{ - unsigned long flags; - - if (!lpbfifo.regs) - return -ENODEV; - - spin_lock_irqsave(&lpbfifo.lock, flags); - - /* - * If the req pointer is already set and a transfer was - * started on submit, then this transfer is in progress - */ - if (lpbfifo.req && !lpbfifo.req->defer_xfer_start) { - spin_unlock_irqrestore(&lpbfifo.lock, flags); - return -EBUSY; - } - - /* - * If the req was previously submitted but not - * started, start it now - */ - if (lpbfifo.req && lpbfifo.req == req && - lpbfifo.req->defer_xfer_start) { - out_8(lpbfifo.regs + LPBFIFO_REG_PACKET_SIZE, 0x01); - } - - spin_unlock_irqrestore(&lpbfifo.lock, flags); - return 0; -} -EXPORT_SYMBOL(mpc52xx_lpbfifo_start_xfer); - -void mpc52xx_lpbfifo_abort(struct mpc52xx_lpbfifo_request *req) -{ - unsigned long flags; - - spin_lock_irqsave(&lpbfifo.lock, flags); - if (lpbfifo.req == req) { - /* Put it into reset and clear the state */ - bcom_gen_bd_rx_reset(lpbfifo.bcom_rx_task); - bcom_gen_bd_tx_reset(lpbfifo.bcom_tx_task); - out_be32(lpbfifo.regs + LPBFIFO_REG_ENABLE, 0x01010000); - lpbfifo.req = NULL; - } - spin_unlock_irqrestore(&lpbfifo.lock, flags); -} -EXPORT_SYMBOL(mpc52xx_lpbfifo_abort); - -static int mpc52xx_lpbfifo_probe(struct platform_device *op) -{ - struct resource res; - int rc = -ENOMEM; - - if (lpbfifo.dev != NULL) - return -ENOSPC; - - lpbfifo.irq = irq_of_parse_and_map(op->dev.of_node, 0); - if (!lpbfifo.irq) - return -ENODEV; - - if (of_address_to_resource(op->dev.of_node, 0, &res)) - return -ENODEV; - lpbfifo.regs_phys = res.start; - lpbfifo.regs = of_iomap(op->dev.of_node, 0); - if (!lpbfifo.regs) - return -ENOMEM; - - spin_lock_init(&lpbfifo.lock); - - /* Put FIFO into reset */ - out_be32(lpbfifo.regs + LPBFIFO_REG_ENABLE, 0x01010000); - - /* Register the interrupt handler */ - rc = request_irq(lpbfifo.irq, mpc52xx_lpbfifo_irq, 0, - "mpc52xx-lpbfifo", &lpbfifo); - if (rc) - goto err_irq; - - /* Request the Bestcomm receive (fifo --> memory) task and IRQ */ - lpbfifo.bcom_rx_task = - bcom_gen_bd_rx_init(2, res.start + LPBFIFO_REG_FIFO_DATA, - BCOM_INITIATOR_SCLPC, BCOM_IPR_SCLPC, - 16*1024*1024); - if (!lpbfifo.bcom_rx_task) - goto err_bcom_rx; - - rc = request_irq(bcom_get_task_irq(lpbfifo.bcom_rx_task), - mpc52xx_lpbfifo_bcom_irq, 0, - "mpc52xx-lpbfifo-rx", &lpbfifo); - if (rc) - goto err_bcom_rx_irq; - - lpbfifo.dma_irqs_enabled = 1; - - /* Request the Bestcomm transmit (memory --> fifo) task and IRQ */ - lpbfifo.bcom_tx_task = - bcom_gen_bd_tx_init(2, res.start + LPBFIFO_REG_FIFO_DATA, - BCOM_INITIATOR_SCLPC, BCOM_IPR_SCLPC); - if (!lpbfifo.bcom_tx_task) - goto err_bcom_tx; - - lpbfifo.dev = &op->dev; - return 0; - - err_bcom_tx: - free_irq(bcom_get_task_irq(lpbfifo.bcom_rx_task), &lpbfifo); - err_bcom_rx_irq: - bcom_gen_bd_rx_release(lpbfifo.bcom_rx_task); - err_bcom_rx: - free_irq(lpbfifo.irq, &lpbfifo); - err_irq: - iounmap(lpbfifo.regs); - lpbfifo.regs = NULL; - - dev_err(&op->dev, "mpc52xx_lpbfifo_probe() failed\n"); - return -ENODEV; -} - - -static int mpc52xx_lpbfifo_remove(struct platform_device *op) -{ - if (lpbfifo.dev != &op->dev) - return 0; - - /* Put FIFO in reset */ - out_be32(lpbfifo.regs + LPBFIFO_REG_ENABLE, 0x01010000); - - /* Release the bestcomm transmit task */ - free_irq(bcom_get_task_irq(lpbfifo.bcom_tx_task), &lpbfifo); - bcom_gen_bd_tx_release(lpbfifo.bcom_tx_task); - - /* Release the bestcomm receive task */ - free_irq(bcom_get_task_irq(lpbfifo.bcom_rx_task), &lpbfifo); - bcom_gen_bd_rx_release(lpbfifo.bcom_rx_task); - - free_irq(lpbfifo.irq, &lpbfifo); - iounmap(lpbfifo.regs); - lpbfifo.regs = NULL; - lpbfifo.dev = NULL; - - return 0; -} - -static const struct of_device_id mpc52xx_lpbfifo_match[] = { - { .compatible = "fsl,mpc5200-lpbfifo", }, - {}, -}; -MODULE_DEVICE_TABLE(of, mpc52xx_lpbfifo_match); - -static struct platform_driver mpc52xx_lpbfifo_driver = { - .driver = { - .name = "mpc52xx-lpbfifo", - .of_match_table = mpc52xx_lpbfifo_match, - }, - .probe = mpc52xx_lpbfifo_probe, - .remove = mpc52xx_lpbfifo_remove, -}; -module_platform_driver(mpc52xx_lpbfifo_driver); diff --git a/arch/powerpc/platforms/52xx/mpc52xx_pm.c b/arch/powerpc/platforms/52xx/mpc52xx_pm.c index 549b3629e39a6a1b3c1aac378b00094a41d084a2..f0c31ae15da53283dcc13ba7c225be9f8d2140dd 100644 --- a/arch/powerpc/platforms/52xx/mpc52xx_pm.c +++ b/arch/powerpc/platforms/52xx/mpc52xx_pm.c @@ -60,7 +60,7 @@ int mpc52xx_set_wakeup_gpio(u8 pin, u8 level) int mpc52xx_pm_prepare(void) { struct device_node *np; - const struct of_device_id immr_ids[] = { + static const struct of_device_id immr_ids[] = { { .compatible = "fsl,mpc5200-immr", }, { .compatible = "fsl,mpc5200b-immr", }, { .type = "soc", .compatible = "mpc5200", }, /* lite5200 */ diff --git a/arch/powerpc/platforms/83xx/mcu_mpc8349emitx.c b/arch/powerpc/platforms/83xx/mcu_mpc8349emitx.c index 77ed61306a73a9ba80de101f7a6f302da110b001..4d8fa9ed1a6781b69f9e9e4c6d1e5509e3eb2d43 100644 --- a/arch/powerpc/platforms/83xx/mcu_mpc8349emitx.c +++ b/arch/powerpc/platforms/83xx/mcu_mpc8349emitx.c @@ -211,7 +211,7 @@ static struct i2c_driver mcu_driver = { .name = "mcu-mpc8349emitx", .of_match_table = mcu_of_match_table, }, - .probe_new = mcu_probe, + .probe = mcu_probe, .remove = mcu_remove, .id_table = mcu_ids, }; diff --git a/arch/powerpc/platforms/85xx/Makefile b/arch/powerpc/platforms/85xx/Makefile index e3d977624e3380e370090471bd8e36e5cf2ea352..43c34f26f108bcb102d03190c87c324eaac7f215 100644 --- a/arch/powerpc/platforms/85xx/Makefile +++ b/arch/powerpc/platforms/85xx/Makefile @@ -12,9 +12,6 @@ obj-y += common.o obj-$(CONFIG_BSC9131_RDB) += bsc913x_rdb.o obj-$(CONFIG_BSC9132_QDS) += bsc913x_qds.o obj-$(CONFIG_C293_PCIE) += c293pcie.o -obj-$(CONFIG_MPC8540_ADS) += mpc85xx_ads.o -obj-$(CONFIG_MPC8560_ADS) += mpc85xx_ads.o -obj-$(CONFIG_MPC85xx_CDS) += mpc85xx_cds.o obj-$(CONFIG_MPC8536_DS) += mpc8536_ds.o obj8259-$(CONFIG_PPC_I8259) += mpc85xx_8259.o obj-$(CONFIG_MPC85xx_DS) += mpc85xx_ds.o $(obj8259-y) diff --git a/arch/powerpc/platforms/85xx/mpc85xx_ads.c b/arch/powerpc/platforms/85xx/mpc85xx_ads.c deleted file mode 100644 index 7c67438e76f84fa54bb0af05c6628c7934ed8c03..0000000000000000000000000000000000000000 --- a/arch/powerpc/platforms/85xx/mpc85xx_ads.c +++ /dev/null @@ -1,162 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * MPC85xx setup and early boot code plus other random bits. - * - * Maintained by Kumar Gala (see MAINTAINERS for contact information) - * - * Copyright 2005 Freescale Semiconductor Inc. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include - -#ifdef CONFIG_CPM2 -#include -#include -#endif - -#include "mpc85xx.h" - -static void __init mpc85xx_ads_pic_init(void) -{ - struct mpic *mpic = mpic_alloc(NULL, 0, MPIC_BIG_ENDIAN, - 0, 256, " OpenPIC "); - BUG_ON(mpic == NULL); - mpic_init(mpic); - - mpc85xx_cpm2_pic_init(); -} - -/* - * Setup the architecture - */ -#ifdef CONFIG_CPM2 -struct cpm_pin { - int port, pin, flags; -}; - -static const struct cpm_pin mpc8560_ads_pins[] = { - /* SCC1 */ - {3, 29, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, - {3, 30, CPM_PIN_OUTPUT | CPM_PIN_SECONDARY}, - {3, 31, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, - - /* SCC2 */ - {2, 12, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, - {2, 13, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, - {3, 26, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, - {3, 27, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, - {3, 28, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, - - /* FCC2 */ - {1, 18, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, - {1, 19, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, - {1, 20, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, - {1, 21, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, - {1, 22, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, - {1, 23, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, - {1, 24, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, - {1, 25, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, - {1, 26, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, - {1, 27, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, - {1, 28, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, - {1, 29, CPM_PIN_OUTPUT | CPM_PIN_SECONDARY}, - {1, 30, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, - {1, 31, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, - {2, 18, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, /* CLK14 */ - {2, 19, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, /* CLK13 */ - - /* FCC3 */ - {1, 4, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, - {1, 5, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, - {1, 6, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, - {1, 8, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, - {1, 9, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, - {1, 10, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, - {1, 11, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, - {1, 12, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, - {1, 13, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, - {1, 14, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, - {1, 15, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, - {1, 16, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, - {1, 17, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, - {2, 16, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, /* CLK16 */ - {2, 17, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, /* CLK15 */ - {2, 27, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, -}; - -static void __init init_ioports(void) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(mpc8560_ads_pins); i++) { - const struct cpm_pin *pin = &mpc8560_ads_pins[i]; - cpm2_set_pin(pin->port, pin->pin, pin->flags); - } - - cpm2_clk_setup(CPM_CLK_SCC1, CPM_BRG1, CPM_CLK_RX); - cpm2_clk_setup(CPM_CLK_SCC1, CPM_BRG1, CPM_CLK_TX); - cpm2_clk_setup(CPM_CLK_SCC2, CPM_BRG2, CPM_CLK_RX); - cpm2_clk_setup(CPM_CLK_SCC2, CPM_BRG2, CPM_CLK_TX); - cpm2_clk_setup(CPM_CLK_FCC2, CPM_CLK13, CPM_CLK_RX); - cpm2_clk_setup(CPM_CLK_FCC2, CPM_CLK14, CPM_CLK_TX); - cpm2_clk_setup(CPM_CLK_FCC3, CPM_CLK15, CPM_CLK_RX); - cpm2_clk_setup(CPM_CLK_FCC3, CPM_CLK16, CPM_CLK_TX); -} -#endif - -static void __init mpc85xx_ads_setup_arch(void) -{ - if (ppc_md.progress) - ppc_md.progress("mpc85xx_ads_setup_arch()", 0); - -#ifdef CONFIG_CPM2 - cpm2_reset(); - init_ioports(); -#endif - - fsl_pci_assign_primary(); -} - -static void mpc85xx_ads_show_cpuinfo(struct seq_file *m) -{ - uint pvid, svid, phid1; - - pvid = mfspr(SPRN_PVR); - svid = mfspr(SPRN_SVR); - - seq_printf(m, "Vendor\t\t: Freescale Semiconductor\n"); - seq_printf(m, "PVR\t\t: 0x%x\n", pvid); - seq_printf(m, "SVR\t\t: 0x%x\n", svid); - - /* Display cpu Pll setting */ - phid1 = mfspr(SPRN_HID1); - seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f)); -} - -machine_arch_initcall(mpc85xx_ads, mpc85xx_common_publish_devices); - -define_machine(mpc85xx_ads) { - .name = "MPC85xx ADS", - .compatible = "MPC85xxADS", - .setup_arch = mpc85xx_ads_setup_arch, - .init_IRQ = mpc85xx_ads_pic_init, - .show_cpuinfo = mpc85xx_ads_show_cpuinfo, - .get_irq = mpic_get_irq, - .progress = udbg_progress, -}; diff --git a/arch/powerpc/platforms/85xx/mpc85xx_cds.c b/arch/powerpc/platforms/85xx/mpc85xx_cds.c deleted file mode 100644 index 0e6964c7fdd6400510338836720c502f6bed5456..0000000000000000000000000000000000000000 --- a/arch/powerpc/platforms/85xx/mpc85xx_cds.c +++ /dev/null @@ -1,387 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * MPC85xx setup and early boot code plus other random bits. - * - * Maintained by Kumar Gala (see MAINTAINERS for contact information) - * - * Copyright 2005, 2011-2012 Freescale Semiconductor Inc. - */ - -#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 -#include - -#include -#include - -#include "mpc85xx.h" - -/* - * The CDS board contains an FPGA/CPLD called "Cadmus", which collects - * various logic and performs system control functions. - * Here is the FPGA/CPLD register map. - */ -struct cadmus_reg { - u8 cm_ver; /* Board version */ - u8 cm_csr; /* General control/status */ - u8 cm_rst; /* Reset control */ - u8 cm_hsclk; /* High speed clock */ - u8 cm_hsxclk; /* High speed clock extended */ - u8 cm_led; /* LED data */ - u8 cm_pci; /* PCI control/status */ - u8 cm_dma; /* DMA control */ - u8 res[248]; /* Total 256 bytes */ -}; - -static struct cadmus_reg *cadmus; - -#ifdef CONFIG_PCI - -#define ARCADIA_HOST_BRIDGE_IDSEL 17 -#define ARCADIA_2ND_BRIDGE_IDSEL 3 - -static int mpc85xx_exclude_device(struct pci_controller *hose, - u_char bus, u_char devfn) -{ - /* We explicitly do not go past the Tundra 320 Bridge */ - if ((bus == 1) && (PCI_SLOT(devfn) == ARCADIA_2ND_BRIDGE_IDSEL)) - return PCIBIOS_DEVICE_NOT_FOUND; - if ((bus == 0) && (PCI_SLOT(devfn) == ARCADIA_2ND_BRIDGE_IDSEL)) - return PCIBIOS_DEVICE_NOT_FOUND; - else - return PCIBIOS_SUCCESSFUL; -} - -static int mpc85xx_cds_restart(struct notifier_block *this, - unsigned long mode, void *cmd) -{ - struct pci_dev *dev; - u_char tmp; - - if ((dev = pci_get_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686, - NULL))) { - - /* Use the VIA Super Southbridge to force a PCI reset */ - pci_read_config_byte(dev, 0x47, &tmp); - pci_write_config_byte(dev, 0x47, tmp | 1); - - /* Flush the outbound PCI write queues */ - pci_read_config_byte(dev, 0x47, &tmp); - - /* - * At this point, the hardware reset should have triggered. - * However, if it doesn't work for some mysterious reason, - * just fall through to the default reset below. - */ - - pci_dev_put(dev); - } - - /* - * If we can't find the VIA chip (maybe the P2P bridge is - * disabled) or the VIA chip reset didn't work, just return - * and let default reset sequence happen. - */ - return NOTIFY_DONE; -} - -static int mpc85xx_cds_restart_register(void) -{ - static struct notifier_block restart_handler; - - restart_handler.notifier_call = mpc85xx_cds_restart; - restart_handler.priority = 192; - - return register_restart_handler(&restart_handler); -} -machine_arch_initcall(mpc85xx_cds, mpc85xx_cds_restart_register); - - -static void __init mpc85xx_cds_pci_irq_fixup(struct pci_dev *dev) -{ - u_char c; - if (dev->vendor == PCI_VENDOR_ID_VIA) { - switch (dev->device) { - case PCI_DEVICE_ID_VIA_82C586_1: - /* - * U-Boot does not set the enable bits - * for the IDE device. Force them on here. - */ - pci_read_config_byte(dev, 0x40, &c); - c |= 0x03; /* IDE: Chip Enable Bits */ - pci_write_config_byte(dev, 0x40, c); - - /* - * Since only primary interface works, force the - * IDE function to standard primary IDE interrupt - * w/ 8259 offset - */ - dev->irq = 14; - pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); - break; - /* - * Force legacy USB interrupt routing - */ - case PCI_DEVICE_ID_VIA_82C586_2: - /* There are two USB controllers. - * Identify them by function number - */ - if (PCI_FUNC(dev->devfn) == 3) - dev->irq = 11; - else - dev->irq = 10; - pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); - break; - default: - break; - } - } -} - -static void skip_fake_bridge(struct pci_dev *dev) -{ - /* Make it an error to skip the fake bridge - * in pci_setup_device() in probe.c */ - dev->hdr_type = 0x7f; -} -DECLARE_PCI_FIXUP_EARLY(0x1957, 0x3fff, skip_fake_bridge); -DECLARE_PCI_FIXUP_EARLY(0x3fff, 0x1957, skip_fake_bridge); -DECLARE_PCI_FIXUP_EARLY(0xff3f, 0x5719, skip_fake_bridge); - -#define PCI_DEVICE_ID_IDT_TSI310 0x01a7 - -/* - * Fix Tsi310 PCI-X bridge resource. - * Force the bridge to open a window from 0x0000-0x1fff in PCI I/O space. - * This allows legacy I/O(i8259, etc) on the VIA southbridge to be accessed. - */ -void mpc85xx_cds_fixup_bus(struct pci_bus *bus) -{ - struct pci_dev *dev = bus->self; - struct resource *res = bus->resource[0]; - - if (dev != NULL && - dev->vendor == PCI_VENDOR_ID_IBM && - dev->device == PCI_DEVICE_ID_IDT_TSI310) { - if (res) { - res->start = 0; - res->end = 0x1fff; - res->flags = IORESOURCE_IO; - pr_info("mpc85xx_cds: PCI bridge resource fixup applied\n"); - pr_info("mpc85xx_cds: %pR\n", res); - } - } - - fsl_pcibios_fixup_bus(bus); -} - -#ifdef CONFIG_PPC_I8259 -static void mpc85xx_8259_cascade_handler(struct irq_desc *desc) -{ - unsigned int cascade_irq = i8259_irq(); - - if (cascade_irq) - /* handle an interrupt from the 8259 */ - generic_handle_irq(cascade_irq); - - /* check for any interrupts from the shared IRQ line */ - handle_fasteoi_irq(desc); -} - -static irqreturn_t mpc85xx_8259_cascade_action(int irq, void *dev_id) -{ - return IRQ_HANDLED; -} -#endif /* PPC_I8259 */ -#endif /* CONFIG_PCI */ - -static void __init mpc85xx_cds_pic_init(void) -{ - struct mpic *mpic; - mpic = mpic_alloc(NULL, 0, MPIC_BIG_ENDIAN, - 0, 256, " OpenPIC "); - BUG_ON(mpic == NULL); - mpic_init(mpic); -} - -#if defined(CONFIG_PPC_I8259) && defined(CONFIG_PCI) -static int mpc85xx_cds_8259_attach(void) -{ - int ret; - struct device_node *np = NULL; - struct device_node *cascade_node = NULL; - int cascade_irq; - - /* Initialize the i8259 controller */ - for_each_node_by_type(np, "interrupt-controller") - if (of_device_is_compatible(np, "chrp,iic")) { - cascade_node = np; - break; - } - - if (cascade_node == NULL) { - printk(KERN_DEBUG "Could not find i8259 PIC\n"); - return -ENODEV; - } - - cascade_irq = irq_of_parse_and_map(cascade_node, 0); - if (!cascade_irq) { - printk(KERN_ERR "Failed to map cascade interrupt\n"); - return -ENXIO; - } - - i8259_init(cascade_node, 0); - of_node_put(cascade_node); - - /* - * Hook the interrupt to make sure desc->action is never NULL. - * This is required to ensure that the interrupt does not get - * disabled when the last user of the shared IRQ line frees their - * interrupt. - */ - ret = request_irq(cascade_irq, mpc85xx_8259_cascade_action, - IRQF_SHARED | IRQF_NO_THREAD, "8259 cascade", - cascade_node); - if (ret) { - printk(KERN_ERR "Failed to setup cascade interrupt\n"); - return ret; - } - - /* Success. Connect our low-level cascade handler. */ - irq_set_handler(cascade_irq, mpc85xx_8259_cascade_handler); - - return 0; -} -machine_device_initcall(mpc85xx_cds, mpc85xx_cds_8259_attach); - -#endif /* CONFIG_PPC_I8259 */ - -static void __init mpc85xx_cds_pci_assign_primary(void) -{ -#ifdef CONFIG_PCI - struct device_node *np; - - if (fsl_pci_primary) - return; - - /* - * MPC85xx_CDS has ISA bridge but unfortunately there is no - * isa node in device tree. We now looking for i8259 node as - * a workaround for such a broken device tree. This routine - * is for complying to all device trees. - */ - np = of_find_node_by_name(NULL, "i8259"); - while ((fsl_pci_primary = of_get_parent(np))) { - of_node_put(np); - np = fsl_pci_primary; - - if ((of_device_is_compatible(np, "fsl,mpc8540-pci") || - of_device_is_compatible(np, "fsl,mpc8548-pcie")) && - of_device_is_available(np)) - return; - } -#endif -} - -/* - * Setup the architecture - */ -static void __init mpc85xx_cds_setup_arch(void) -{ - struct device_node *np; - int cds_pci_slot; - - if (ppc_md.progress) - ppc_md.progress("mpc85xx_cds_setup_arch()", 0); - - np = of_find_compatible_node(NULL, NULL, "fsl,mpc8548cds-fpga"); - if (!np) { - pr_err("Could not find FPGA node.\n"); - return; - } - - cadmus = of_iomap(np, 0); - of_node_put(np); - if (!cadmus) { - pr_err("Fail to map FPGA area.\n"); - return; - } - - if (ppc_md.progress) { - char buf[40]; - cds_pci_slot = ((in_8(&cadmus->cm_csr) >> 6) & 0x3) + 1; - snprintf(buf, 40, "CDS Version = 0x%x in slot %d\n", - in_8(&cadmus->cm_ver), cds_pci_slot); - ppc_md.progress(buf, 0); - } - -#ifdef CONFIG_PCI - ppc_md.pci_irq_fixup = mpc85xx_cds_pci_irq_fixup; - ppc_md.pci_exclude_device = mpc85xx_exclude_device; -#endif - - mpc85xx_cds_pci_assign_primary(); - fsl_pci_assign_primary(); -} - -static void mpc85xx_cds_show_cpuinfo(struct seq_file *m) -{ - uint pvid, svid, phid1; - - pvid = mfspr(SPRN_PVR); - svid = mfspr(SPRN_SVR); - - seq_printf(m, "Vendor\t\t: Freescale Semiconductor\n"); - seq_printf(m, "Machine\t\t: MPC85xx CDS (0x%x)\n", - in_8(&cadmus->cm_ver)); - seq_printf(m, "PVR\t\t: 0x%x\n", pvid); - seq_printf(m, "SVR\t\t: 0x%x\n", svid); - - /* Display cpu Pll setting */ - phid1 = mfspr(SPRN_HID1); - seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f)); -} - -machine_arch_initcall(mpc85xx_cds, mpc85xx_common_publish_devices); - -define_machine(mpc85xx_cds) { - .name = "MPC85xx CDS", - .compatible = "MPC85xxCDS", - .setup_arch = mpc85xx_cds_setup_arch, - .init_IRQ = mpc85xx_cds_pic_init, - .show_cpuinfo = mpc85xx_cds_show_cpuinfo, - .get_irq = mpic_get_irq, -#ifdef CONFIG_PCI - .pcibios_fixup_bus = mpc85xx_cds_fixup_bus, - .pcibios_fixup_phb = fsl_pcibios_fixup_phb, -#endif - .progress = udbg_progress, -}; diff --git a/arch/powerpc/platforms/86xx/Kconfig b/arch/powerpc/platforms/86xx/Kconfig index 8bfafc9d2bf7b56d97d77040c0264f20a32c3581..67467cd6f34cd52924f7ad395b1f480c5e0c14cd 100644 --- a/arch/powerpc/platforms/86xx/Kconfig +++ b/arch/powerpc/platforms/86xx/Kconfig @@ -1,5 +1,4 @@ # SPDX-License-Identifier: GPL-2.0 -config PPC_86xx menuconfig PPC_86xx bool "86xx-based boards" depends on PPC_BOOK3S_32 diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c index 7bd0b563e163a8c4ebc293972fb780e2db5eec3a..dea6f0f2589742166a30570b27271634bea427d4 100644 --- a/arch/powerpc/platforms/cell/spu_base.c +++ b/arch/powerpc/platforms/cell/spu_base.c @@ -326,12 +326,6 @@ spu_irq_class_1(int irq, void *data) if (stat & CLASS1_STORAGE_FAULT_INTR) __spu_trap_data_map(spu, dar, dsisr); - if (stat & CLASS1_LS_COMPARE_SUSPEND_ON_GET_INTR) - ; - - if (stat & CLASS1_LS_COMPARE_SUSPEND_ON_PUT_INTR) - ; - spu->class_1_dsisr = 0; spu->class_1_dar = 0; diff --git a/arch/powerpc/platforms/embedded6xx/Kconfig b/arch/powerpc/platforms/embedded6xx/Kconfig index a57424d6ef2016dd0d7518edd50f595785af4f1d..c6adff216fe633f43a3b1c1d24af23f2fa976d99 100644 --- a/arch/powerpc/platforms/embedded6xx/Kconfig +++ b/arch/powerpc/platforms/embedded6xx/Kconfig @@ -10,7 +10,7 @@ config LINKSTATION select FSL_SOC select PPC_UDBG_16550 if SERIAL_8250 select DEFAULT_UIMAGE - select MPC10X_BRIDGE + imply MPC10X_BRIDGE if PCI help Select LINKSTATION if configuring for one of PPC- (MPC8241) based NAS systems from Buffalo Technology. So far only @@ -24,7 +24,7 @@ config STORCENTER select MPIC select FSL_SOC select PPC_UDBG_16550 if SERIAL_8250 - select MPC10X_BRIDGE + imply MPC10X_BRIDGE if PCI help Select STORCENTER if configuring for the iomega StorCenter with an 8241 CPU in it. diff --git a/arch/powerpc/platforms/powermac/feature.c b/arch/powerpc/platforms/powermac/feature.c index a195d5faa4e572a57b7b2857f0f45a3cca319f3d..ed58928469b5ba6bfb507ba84d657cdf9cadc2f8 100644 --- a/arch/powerpc/platforms/powermac/feature.c +++ b/arch/powerpc/platforms/powermac/feature.c @@ -1053,11 +1053,11 @@ core99_reset_cpu(struct device_node *node, long param, long value) return -ENODEV; for_each_of_cpu_node(np) { - const u32 *num = of_get_property(np, "reg", NULL); const u32 *rst = of_get_property(np, "soft-reset", NULL); - if (num == NULL || rst == NULL) + if (!rst) continue; - if (param == *num) { + if (param == of_get_cpu_hwid(np, 0)) { + of_node_put(np); reset_io = *rst; break; } @@ -1499,11 +1499,11 @@ static long g5_reset_cpu(struct device_node *node, long param, long value) return -ENODEV; for_each_of_cpu_node(np) { - const u32 *num = of_get_property(np, "reg", NULL); const u32 *rst = of_get_property(np, "soft-reset", NULL); - if (num == NULL || rst == NULL) + if (!rst) continue; - if (param == *num) { + if (param == of_get_cpu_hwid(np, 0)) { + of_node_put(np); reset_io = *rst; break; } diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c index 193cc9c394221b09b399a57e45a6622365992b25..0c41f4b005bcf329965f62f4e77ec3b50f60b7d1 100644 --- a/arch/powerpc/platforms/powermac/setup.c +++ b/arch/powerpc/platforms/powermac/setup.c @@ -76,7 +76,8 @@ int pmac_newworld; static int current_root_goodness = -1; -#define DEFAULT_ROOT_DEVICE Root_SDA1 /* sda1 - slightly silly choice */ +/* sda1 - slightly silly choice */ +#define DEFAULT_ROOT_DEVICE MKDEV(SCSI_DISK0_MAJOR, 1) sys_ctrler_t sys_ctrler = SYS_CTRLER_UNKNOWN; EXPORT_SYMBOL(sys_ctrler); diff --git a/arch/powerpc/platforms/powernv/idle.c b/arch/powerpc/platforms/powernv/idle.c index 6dfe8d611164fd588e7ca98dab6e7af1c57a9675..ad41dffe4d9291a5cf3d0cea8b973d0cdc1167b3 100644 --- a/arch/powerpc/platforms/powernv/idle.c +++ b/arch/powerpc/platforms/powernv/idle.c @@ -246,9 +246,9 @@ static inline void atomic_lock_thread_idle(void) { int cpu = raw_smp_processor_id(); int first = cpu_first_thread_sibling(cpu); - unsigned long *state = &paca_ptrs[first]->idle_state; + unsigned long *lock = &paca_ptrs[first]->idle_lock; - while (unlikely(test_and_set_bit_lock(NR_PNV_CORE_IDLE_LOCK_BIT, state))) + while (unlikely(test_and_set_bit_lock(NR_PNV_CORE_IDLE_LOCK_BIT, lock))) barrier(); } @@ -258,29 +258,31 @@ static inline void atomic_unlock_and_stop_thread_idle(void) int first = cpu_first_thread_sibling(cpu); unsigned long thread = 1UL << cpu_thread_in_core(cpu); unsigned long *state = &paca_ptrs[first]->idle_state; + unsigned long *lock = &paca_ptrs[first]->idle_lock; u64 s = READ_ONCE(*state); u64 new, tmp; - BUG_ON(!(s & PNV_CORE_IDLE_LOCK_BIT)); + BUG_ON(!(READ_ONCE(*lock) & PNV_CORE_IDLE_LOCK_BIT)); BUG_ON(s & thread); again: - new = (s | thread) & ~PNV_CORE_IDLE_LOCK_BIT; + new = s | thread; tmp = cmpxchg(state, s, new); if (unlikely(tmp != s)) { s = tmp; goto again; } + clear_bit_unlock(NR_PNV_CORE_IDLE_LOCK_BIT, lock); } static inline void atomic_unlock_thread_idle(void) { int cpu = raw_smp_processor_id(); int first = cpu_first_thread_sibling(cpu); - unsigned long *state = &paca_ptrs[first]->idle_state; + unsigned long *lock = &paca_ptrs[first]->idle_lock; - BUG_ON(!test_bit(NR_PNV_CORE_IDLE_LOCK_BIT, state)); - clear_bit_unlock(NR_PNV_CORE_IDLE_LOCK_BIT, state); + BUG_ON(!test_bit(NR_PNV_CORE_IDLE_LOCK_BIT, lock)); + clear_bit_unlock(NR_PNV_CORE_IDLE_LOCK_BIT, lock); } /* P7 and P8 */ diff --git a/arch/powerpc/platforms/powernv/opal-call.c b/arch/powerpc/platforms/powernv/opal-call.c index f812c74c61e5fc4eda6ba380f2f628ec86c84f1f..021b0ec29e2400dee7697af78d69b0166f712a35 100644 --- a/arch/powerpc/platforms/powernv/opal-call.c +++ b/arch/powerpc/platforms/powernv/opal-call.c @@ -167,8 +167,6 @@ OPAL_CALL(opal_pci_map_pe_mmio_window, OPAL_PCI_MAP_PE_MMIO_WINDOW); OPAL_CALL(opal_pci_set_phb_table_memory, OPAL_PCI_SET_PHB_TABLE_MEMORY); OPAL_CALL(opal_pci_set_pe, OPAL_PCI_SET_PE); OPAL_CALL(opal_pci_set_peltv, OPAL_PCI_SET_PELTV); -OPAL_CALL(opal_pci_set_mve, OPAL_PCI_SET_MVE); -OPAL_CALL(opal_pci_set_mve_enable, OPAL_PCI_SET_MVE_ENABLE); OPAL_CALL(opal_pci_get_xive_reissue, OPAL_PCI_GET_XIVE_REISSUE); OPAL_CALL(opal_pci_set_xive_reissue, OPAL_PCI_SET_XIVE_REISSUE); OPAL_CALL(opal_pci_set_xive_pe, OPAL_PCI_SET_XIVE_PE); diff --git a/arch/powerpc/platforms/powernv/opal-irqchip.c b/arch/powerpc/platforms/powernv/opal-irqchip.c index d55652b5f6fa40f098217019e4d306b8ec222b4c..f9a7001dacb7a1eacb9e8da60eba587e3ea0d44d 100644 --- a/arch/powerpc/platforms/powernv/opal-irqchip.c +++ b/arch/powerpc/platforms/powernv/opal-irqchip.c @@ -59,7 +59,7 @@ void opal_handle_events(void) cond_resched(); } - last_outstanding_events = 0; + WRITE_ONCE(last_outstanding_events, 0); if (opal_poll_events(&events) != OPAL_SUCCESS) return; e = be64_to_cpu(events) & opal_event_irqchip.mask; @@ -69,7 +69,7 @@ void opal_handle_events(void) bool opal_have_pending_events(void) { - if (last_outstanding_events & opal_event_irqchip.mask) + if (READ_ONCE(last_outstanding_events) & opal_event_irqchip.mask) return true; return false; } @@ -124,7 +124,7 @@ static irqreturn_t opal_interrupt(int irq, void *data) __be64 events; opal_handle_interrupt(virq_to_hw(irq), &events); - last_outstanding_events = be64_to_cpu(events); + WRITE_ONCE(last_outstanding_events, be64_to_cpu(events)); if (opal_have_pending_events()) opal_wake_poller(); diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c index a02e9cdb5b5d6f50218491dd775e4a32d5dc62de..cb637827bc585e26b47b11d3754a893e55c2d34a 100644 --- a/arch/powerpc/platforms/powernv/pci-ioda.c +++ b/arch/powerpc/platforms/powernv/pci-ioda.c @@ -45,11 +45,8 @@ #include "pci.h" #include "../../../../drivers/pci/pci.h" -#define PNV_IODA1_M64_NUM 16 /* Number of M64 BARs */ -#define PNV_IODA1_M64_SEGS 8 /* Segments per M64 BAR */ -#define PNV_IODA1_DMA32_SEGSIZE 0x10000000 - -static const char * const pnv_phb_names[] = { "IODA1", "IODA2", "NPU_OCAPI" }; +/* This array is indexed with enum pnv_phb_type */ +static const char * const pnv_phb_names[] = { "IODA2", "NPU_OCAPI" }; static void pnv_pci_ioda2_set_bypass(struct pnv_ioda_pe *pe, bool enable); static void pnv_pci_configure_bus(struct pci_bus *bus); @@ -280,86 +277,6 @@ static void pnv_ioda_reserve_dev_m64_pe(struct pci_dev *pdev, } } -static int pnv_ioda1_init_m64(struct pnv_phb *phb) -{ - struct resource *r; - int index; - - /* - * There are 16 M64 BARs, each of which has 8 segments. So - * there are as many M64 segments as the maximum number of - * PEs, which is 128. - */ - for (index = 0; index < PNV_IODA1_M64_NUM; index++) { - unsigned long base, segsz = phb->ioda.m64_segsize; - int64_t rc; - - base = phb->ioda.m64_base + - index * PNV_IODA1_M64_SEGS * segsz; - rc = opal_pci_set_phb_mem_window(phb->opal_id, - OPAL_M64_WINDOW_TYPE, index, base, 0, - PNV_IODA1_M64_SEGS * segsz); - if (rc != OPAL_SUCCESS) { - pr_warn(" Error %lld setting M64 PHB#%x-BAR#%d\n", - rc, phb->hose->global_number, index); - goto fail; - } - - rc = opal_pci_phb_mmio_enable(phb->opal_id, - OPAL_M64_WINDOW_TYPE, index, - OPAL_ENABLE_M64_SPLIT); - if (rc != OPAL_SUCCESS) { - pr_warn(" Error %lld enabling M64 PHB#%x-BAR#%d\n", - rc, phb->hose->global_number, index); - goto fail; - } - } - - for (index = 0; index < phb->ioda.total_pe_num; index++) { - int64_t rc; - - /* - * P7IOC supports M64DT, which helps mapping M64 segment - * to one particular PE#. However, PHB3 has fixed mapping - * between M64 segment and PE#. In order to have same logic - * for P7IOC and PHB3, we enforce fixed mapping between M64 - * segment and PE# on P7IOC. - */ - rc = opal_pci_map_pe_mmio_window(phb->opal_id, - index, OPAL_M64_WINDOW_TYPE, - index / PNV_IODA1_M64_SEGS, - index % PNV_IODA1_M64_SEGS); - if (rc != OPAL_SUCCESS) { - pr_warn("%s: Error %lld mapping M64 for PHB#%x-PE#%x\n", - __func__, rc, phb->hose->global_number, - index); - goto fail; - } - } - - /* - * Exclude the segments for reserved and root bus PE, which - * are first or last two PEs. - */ - r = &phb->hose->mem_resources[1]; - if (phb->ioda.reserved_pe_idx == 0) - r->start += (2 * phb->ioda.m64_segsize); - else if (phb->ioda.reserved_pe_idx == (phb->ioda.total_pe_num - 1)) - r->end -= (2 * phb->ioda.m64_segsize); - else - WARN(1, "Wrong reserved PE#%x on PHB#%x\n", - phb->ioda.reserved_pe_idx, phb->hose->global_number); - - return 0; - -fail: - for ( ; index >= 0; index--) - opal_pci_phb_mmio_enable(phb->opal_id, - OPAL_M64_WINDOW_TYPE, index, OPAL_DISABLE_M64); - - return -EIO; -} - static void pnv_ioda_reserve_m64_pe(struct pci_bus *bus, unsigned long *pe_bitmap, bool all) @@ -443,7 +360,7 @@ static void __init pnv_ioda_parse_m64_window(struct pnv_phb *phb) const __be32 *r; u64 pci_addr; - if (phb->type != PNV_PHB_IODA1 && phb->type != PNV_PHB_IODA2) { + if (phb->type != PNV_PHB_IODA2) { pr_info(" Not support M64 window\n"); return; } @@ -518,10 +435,7 @@ static void __init pnv_ioda_parse_m64_window(struct pnv_phb *phb) * Setup init functions for M64 based on IODA version, IODA3 uses * the IODA2 code. */ - if (phb->type == PNV_PHB_IODA1) - phb->init_m64 = pnv_ioda1_init_m64; - else - phb->init_m64 = pnv_ioda2_init_m64; + phb->init_m64 = pnv_ioda2_init_m64; } static void pnv_ioda_freeze_pe(struct pnv_phb *phb, int pe_no) @@ -952,29 +866,8 @@ int pnv_ioda_configure_pe(struct pnv_phb *phb, struct pnv_ioda_pe *pe) for (rid = pe->rid; rid < rid_end; rid++) phb->ioda.pe_rmap[rid] = pe->pe_number; - /* Setup one MVTs on IODA1 */ - if (phb->type != PNV_PHB_IODA1) { - pe->mve_number = 0; - goto out; - } - - pe->mve_number = pe->pe_number; - rc = opal_pci_set_mve(phb->opal_id, pe->mve_number, pe->pe_number); - if (rc != OPAL_SUCCESS) { - pe_err(pe, "OPAL error %ld setting up MVE %x\n", - rc, pe->mve_number); - pe->mve_number = -1; - } else { - rc = opal_pci_set_mve_enable(phb->opal_id, - pe->mve_number, OPAL_ENABLE_MVE); - if (rc) { - pe_err(pe, "OPAL error %ld enabling MVE %x\n", - rc, pe->mve_number); - pe->mve_number = -1; - } - } + pe->mve_number = 0; -out: return 0; } @@ -1097,9 +990,6 @@ static struct pnv_ioda_pe *pnv_ioda_setup_bus_PE(struct pci_bus *bus, bool all) return pe; } -static void pnv_pci_ioda1_setup_dma_pe(struct pnv_phb *phb, - struct pnv_ioda_pe *pe); - static void pnv_pci_ioda_dma_dev_setup(struct pci_dev *pdev) { struct pnv_phb *phb = pci_bus_to_pnvhb(pdev->bus); @@ -1134,9 +1024,6 @@ static void pnv_pci_ioda_dma_dev_setup(struct pci_dev *pdev) */ if (!pe->dma_setup_done && !pci_is_bridge(pdev)) { switch (phb->type) { - case PNV_PHB_IODA1: - pnv_pci_ioda1_setup_dma_pe(phb, pe); - break; case PNV_PHB_IODA2: pnv_pci_ioda2_setup_dma_pe(phb, pe); break; @@ -1273,53 +1160,6 @@ static inline __be64 __iomem *pnv_ioda_get_inval_reg(struct pnv_phb *phb) return phb->regs + 0x210; } -static void pnv_pci_p7ioc_tce_invalidate(struct iommu_table *tbl, - unsigned long index, unsigned long npages) -{ - struct iommu_table_group_link *tgl = list_first_entry_or_null( - &tbl->it_group_list, struct iommu_table_group_link, - next); - struct pnv_ioda_pe *pe = container_of(tgl->table_group, - struct pnv_ioda_pe, table_group); - __be64 __iomem *invalidate = pnv_ioda_get_inval_reg(pe->phb); - unsigned long start, end, inc; - - start = __pa(((__be64 *)tbl->it_base) + index - tbl->it_offset); - end = __pa(((__be64 *)tbl->it_base) + index - tbl->it_offset + - npages - 1); - - /* p7ioc-style invalidation, 2 TCEs per write */ - start |= (1ull << 63); - end |= (1ull << 63); - inc = 16; - end |= inc - 1; /* round up end to be different than start */ - - mb(); /* Ensure above stores are visible */ - while (start <= end) { - __raw_writeq_be(start, invalidate); - start += inc; - } - - /* - * The iommu layer will do another mb() for us on build() - * and we don't care on free() - */ -} - -static int pnv_ioda1_tce_build(struct iommu_table *tbl, long index, - long npages, unsigned long uaddr, - enum dma_data_direction direction, - unsigned long attrs) -{ - int ret = pnv_tce_build(tbl, index, npages, uaddr, direction, - attrs); - - if (!ret) - pnv_pci_p7ioc_tce_invalidate(tbl, index, npages); - - return ret; -} - #ifdef CONFIG_IOMMU_API /* Common for IODA1 and IODA2 */ static int pnv_ioda_tce_xchg_no_kill(struct iommu_table *tbl, long index, @@ -1329,25 +1169,6 @@ static int pnv_ioda_tce_xchg_no_kill(struct iommu_table *tbl, long index, } #endif -static void pnv_ioda1_tce_free(struct iommu_table *tbl, long index, - long npages) -{ - pnv_tce_free(tbl, index, npages); - - pnv_pci_p7ioc_tce_invalidate(tbl, index, npages); -} - -static struct iommu_table_ops pnv_ioda1_iommu_ops = { - .set = pnv_ioda1_tce_build, -#ifdef CONFIG_IOMMU_API - .xchg_no_kill = pnv_ioda_tce_xchg_no_kill, - .tce_kill = pnv_pci_p7ioc_tce_invalidate, - .useraddrptr = pnv_tce_useraddrptr, -#endif - .clear = pnv_ioda1_tce_free, - .get = pnv_tce_get, -}; - #define PHB3_TCE_KILL_INVAL_ALL PPC_BIT(0) #define PHB3_TCE_KILL_INVAL_PE PPC_BIT(1) #define PHB3_TCE_KILL_INVAL_ONE PPC_BIT(2) @@ -1453,182 +1274,6 @@ static struct iommu_table_ops pnv_ioda2_iommu_ops = { .free = pnv_pci_ioda2_table_free_pages, }; -static int pnv_pci_ioda_dev_dma_weight(struct pci_dev *dev, void *data) -{ - unsigned int *weight = (unsigned int *)data; - - /* This is quite simplistic. The "base" weight of a device - * is 10. 0 means no DMA is to be accounted for it. - */ - if (dev->hdr_type != PCI_HEADER_TYPE_NORMAL) - return 0; - - if (dev->class == PCI_CLASS_SERIAL_USB_UHCI || - dev->class == PCI_CLASS_SERIAL_USB_OHCI || - dev->class == PCI_CLASS_SERIAL_USB_EHCI) - *weight += 3; - else if ((dev->class >> 8) == PCI_CLASS_STORAGE_RAID) - *weight += 15; - else - *weight += 10; - - return 0; -} - -static unsigned int pnv_pci_ioda_pe_dma_weight(struct pnv_ioda_pe *pe) -{ - unsigned int weight = 0; - - /* SRIOV VF has same DMA32 weight as its PF */ -#ifdef CONFIG_PCI_IOV - if ((pe->flags & PNV_IODA_PE_VF) && pe->parent_dev) { - pnv_pci_ioda_dev_dma_weight(pe->parent_dev, &weight); - return weight; - } -#endif - - if ((pe->flags & PNV_IODA_PE_DEV) && pe->pdev) { - pnv_pci_ioda_dev_dma_weight(pe->pdev, &weight); - } else if ((pe->flags & PNV_IODA_PE_BUS) && pe->pbus) { - struct pci_dev *pdev; - - list_for_each_entry(pdev, &pe->pbus->devices, bus_list) - pnv_pci_ioda_dev_dma_weight(pdev, &weight); - } else if ((pe->flags & PNV_IODA_PE_BUS_ALL) && pe->pbus) { - pci_walk_bus(pe->pbus, pnv_pci_ioda_dev_dma_weight, &weight); - } - - return weight; -} - -static void pnv_pci_ioda1_setup_dma_pe(struct pnv_phb *phb, - struct pnv_ioda_pe *pe) -{ - - struct page *tce_mem = NULL; - struct iommu_table *tbl; - unsigned int weight, total_weight = 0; - unsigned int tce32_segsz, base, segs, avail, i; - int64_t rc; - void *addr; - - /* XXX FIXME: Handle 64-bit only DMA devices */ - /* XXX FIXME: Provide 64-bit DMA facilities & non-4K TCE tables etc.. */ - /* XXX FIXME: Allocate multi-level tables on PHB3 */ - weight = pnv_pci_ioda_pe_dma_weight(pe); - if (!weight) - return; - - pci_walk_bus(phb->hose->bus, pnv_pci_ioda_dev_dma_weight, - &total_weight); - segs = (weight * phb->ioda.dma32_count) / total_weight; - if (!segs) - segs = 1; - - /* - * Allocate contiguous DMA32 segments. We begin with the expected - * number of segments. With one more attempt, the number of DMA32 - * segments to be allocated is decreased by one until one segment - * is allocated successfully. - */ - do { - for (base = 0; base <= phb->ioda.dma32_count - segs; base++) { - for (avail = 0, i = base; i < base + segs; i++) { - if (phb->ioda.dma32_segmap[i] == - IODA_INVALID_PE) - avail++; - } - - if (avail == segs) - goto found; - } - } while (--segs); - - if (!segs) { - pe_warn(pe, "No available DMA32 segments\n"); - return; - } - -found: - tbl = pnv_pci_table_alloc(phb->hose->node); - if (WARN_ON(!tbl)) - return; - -#ifdef CONFIG_IOMMU_API - pe->table_group.ops = &spapr_tce_table_group_ops; - pe->table_group.pgsizes = SZ_4K; -#endif - iommu_register_group(&pe->table_group, phb->hose->global_number, - pe->pe_number); - pnv_pci_link_table_and_group(phb->hose->node, 0, tbl, &pe->table_group); - - /* Grab a 32-bit TCE table */ - pe_info(pe, "DMA weight %d (%d), assigned (%d) %d DMA32 segments\n", - weight, total_weight, base, segs); - pe_info(pe, " Setting up 32-bit TCE table at %08x..%08x\n", - base * PNV_IODA1_DMA32_SEGSIZE, - (base + segs) * PNV_IODA1_DMA32_SEGSIZE - 1); - - /* XXX Currently, we allocate one big contiguous table for the - * TCEs. We only really need one chunk per 256M of TCE space - * (ie per segment) but that's an optimization for later, it - * requires some added smarts with our get/put_tce implementation - * - * Each TCE page is 4KB in size and each TCE entry occupies 8 - * bytes - */ - tce32_segsz = PNV_IODA1_DMA32_SEGSIZE >> (IOMMU_PAGE_SHIFT_4K - 3); - tce_mem = alloc_pages_node(phb->hose->node, GFP_KERNEL, - get_order(tce32_segsz * segs)); - if (!tce_mem) { - pe_err(pe, " Failed to allocate a 32-bit TCE memory\n"); - goto fail; - } - addr = page_address(tce_mem); - memset(addr, 0, tce32_segsz * segs); - - /* Configure HW */ - for (i = 0; i < segs; i++) { - rc = opal_pci_map_pe_dma_window(phb->opal_id, - pe->pe_number, - base + i, 1, - __pa(addr) + tce32_segsz * i, - tce32_segsz, IOMMU_PAGE_SIZE_4K); - if (rc) { - pe_err(pe, " Failed to configure 32-bit TCE table, err %lld\n", - rc); - goto fail; - } - } - - /* Setup DMA32 segment mapping */ - for (i = base; i < base + segs; i++) - phb->ioda.dma32_segmap[i] = pe->pe_number; - - /* Setup linux iommu table */ - pnv_pci_setup_iommu_table(tbl, addr, tce32_segsz * segs, - base * PNV_IODA1_DMA32_SEGSIZE, - IOMMU_PAGE_SHIFT_4K); - - tbl->it_ops = &pnv_ioda1_iommu_ops; - pe->table_group.tce32_start = tbl->it_offset << tbl->it_page_shift; - pe->table_group.tce32_size = tbl->it_size << tbl->it_page_shift; - tbl->it_index = (phb->hose->global_number << 16) | pe->pe_number; - if (!iommu_init_table(tbl, phb->hose->node, 0, 0)) - panic("Failed to initialize iommu table"); - - pe->dma_setup_done = true; - return; - fail: - /* XXX Failure: Try to fallback to 64-bit only ? */ - if (tce_mem) - __free_pages(tce_mem, get_order(tce32_segsz * segs)); - if (tbl) { - pnv_pci_unlink_table_and_group(tbl, &pe->table_group); - iommu_tce_table_put(tbl); - } -} - static long pnv_pci_ioda2_set_window(struct iommu_table_group *table_group, int num, struct iommu_table *tbl) { @@ -2707,57 +2352,6 @@ static bool pnv_ocapi_enable_device_hook(struct pci_dev *dev) return true; } -static long pnv_pci_ioda1_unset_window(struct iommu_table_group *table_group, - int num) -{ - struct pnv_ioda_pe *pe = container_of(table_group, - struct pnv_ioda_pe, table_group); - struct pnv_phb *phb = pe->phb; - unsigned int idx; - long rc; - - pe_info(pe, "Removing DMA window #%d\n", num); - for (idx = 0; idx < phb->ioda.dma32_count; idx++) { - if (phb->ioda.dma32_segmap[idx] != pe->pe_number) - continue; - - rc = opal_pci_map_pe_dma_window(phb->opal_id, pe->pe_number, - idx, 0, 0ul, 0ul, 0ul); - if (rc != OPAL_SUCCESS) { - pe_warn(pe, "Failure %ld unmapping DMA32 segment#%d\n", - rc, idx); - return rc; - } - - phb->ioda.dma32_segmap[idx] = IODA_INVALID_PE; - } - - pnv_pci_unlink_table_and_group(table_group->tables[num], table_group); - return OPAL_SUCCESS; -} - -static void pnv_pci_ioda1_release_pe_dma(struct pnv_ioda_pe *pe) -{ - struct iommu_table *tbl = pe->table_group.tables[0]; - int64_t rc; - - if (!pe->dma_setup_done) - return; - - rc = pnv_pci_ioda1_unset_window(&pe->table_group, 0); - if (rc != OPAL_SUCCESS) - return; - - pnv_pci_p7ioc_tce_invalidate(tbl, tbl->it_offset, tbl->it_size); - if (pe->table_group.group) { - iommu_group_put(pe->table_group.group); - WARN_ON(pe->table_group.group); - } - - free_pages(tbl->it_base, get_order(tbl->it_size << 3)); - iommu_tce_table_put(tbl); -} - void pnv_pci_ioda2_release_pe_dma(struct pnv_ioda_pe *pe) { struct iommu_table *tbl = pe->table_group.tables[0]; @@ -2806,13 +2400,7 @@ static void pnv_ioda_release_pe_seg(struct pnv_ioda_pe *pe) { struct pnv_phb *phb = pe->phb; - if (phb->type == PNV_PHB_IODA1) { - pnv_ioda_free_pe_seg(pe, OPAL_IO_WINDOW_TYPE, - phb->ioda.io_segmap); - pnv_ioda_free_pe_seg(pe, OPAL_M32_WINDOW_TYPE, - phb->ioda.m32_segmap); - /* M64 is pre-configured by pnv_ioda1_init_m64() */ - } else if (phb->type == PNV_PHB_IODA2) { + if (phb->type == PNV_PHB_IODA2) { pnv_ioda_free_pe_seg(pe, OPAL_M32_WINDOW_TYPE, phb->ioda.m32_segmap); } @@ -2830,9 +2418,6 @@ static void pnv_ioda_release_pe(struct pnv_ioda_pe *pe) mutex_unlock(&phb->ioda.pe_list_mutex); switch (phb->type) { - case PNV_PHB_IODA1: - pnv_pci_ioda1_release_pe_dma(pe); - break; case PNV_PHB_IODA2: pnv_pci_ioda2_release_pe_dma(pe); break; @@ -2981,7 +2566,6 @@ static void __init pnv_pci_init_ioda_phb(struct device_node *np, struct pci_controller *hose; struct pnv_phb *phb; unsigned long size, m64map_off, m32map_off, pemap_off; - unsigned long iomap_off = 0, dma32map_off = 0; struct pnv_ioda_pe *root_pe; struct resource r; const __be64 *prop64; @@ -3092,10 +2676,6 @@ static void __init pnv_pci_init_ioda_phb(struct device_node *np, phb->ioda.io_segsize = phb->ioda.io_size / phb->ioda.total_pe_num; phb->ioda.io_pci_base = 0; /* XXX calculate this ? */ - /* Calculate how many 32-bit TCE segments we have */ - phb->ioda.dma32_count = phb->ioda.m32_pci_base / - PNV_IODA1_DMA32_SEGSIZE; - /* Allocate aux data & arrays. We don't have IO ports on PHB3 */ size = ALIGN(max_t(unsigned, phb->ioda.total_pe_num, 8) / 8, sizeof(unsigned long)); @@ -3103,13 +2683,6 @@ static void __init pnv_pci_init_ioda_phb(struct device_node *np, size += phb->ioda.total_pe_num * sizeof(phb->ioda.m64_segmap[0]); m32map_off = size; size += phb->ioda.total_pe_num * sizeof(phb->ioda.m32_segmap[0]); - if (phb->type == PNV_PHB_IODA1) { - iomap_off = size; - size += phb->ioda.total_pe_num * sizeof(phb->ioda.io_segmap[0]); - dma32map_off = size; - size += phb->ioda.dma32_count * - sizeof(phb->ioda.dma32_segmap[0]); - } pemap_off = size; size += phb->ioda.total_pe_num * sizeof(struct pnv_ioda_pe); aux = kzalloc(size, GFP_KERNEL); @@ -3123,15 +2696,6 @@ static void __init pnv_pci_init_ioda_phb(struct device_node *np, phb->ioda.m64_segmap[segno] = IODA_INVALID_PE; phb->ioda.m32_segmap[segno] = IODA_INVALID_PE; } - if (phb->type == PNV_PHB_IODA1) { - phb->ioda.io_segmap = aux + iomap_off; - for (segno = 0; segno < phb->ioda.total_pe_num; segno++) - phb->ioda.io_segmap[segno] = IODA_INVALID_PE; - - phb->ioda.dma32_segmap = aux + dma32map_off; - for (segno = 0; segno < phb->ioda.dma32_count; segno++) - phb->ioda.dma32_segmap[segno] = IODA_INVALID_PE; - } phb->ioda.pe_array = aux + pemap_off; /* @@ -3155,10 +2719,6 @@ static void __init pnv_pci_init_ioda_phb(struct device_node *np, INIT_LIST_HEAD(&phb->ioda.pe_list); mutex_init(&phb->ioda.pe_list_mutex); - /* Calculate how many 32-bit TCE segments we have */ - phb->ioda.dma32_count = phb->ioda.m32_pci_base / - PNV_IODA1_DMA32_SEGSIZE; - #if 0 /* We should really do that ... */ rc = opal_pci_set_phb_mem_window(opal->phb_id, window_type, @@ -3265,27 +2825,3 @@ static void pnv_npu2_opencapi_cfg_size_fixup(struct pci_dev *dev) dev->cfg_size = PCI_CFG_SPACE_EXP_SIZE; } DECLARE_PCI_FIXUP_EARLY(PCI_ANY_ID, PCI_ANY_ID, pnv_npu2_opencapi_cfg_size_fixup); - -void __init pnv_pci_init_ioda_hub(struct device_node *np) -{ - struct device_node *phbn; - const __be64 *prop64; - u64 hub_id; - - pr_info("Probing IODA IO-Hub %pOF\n", np); - - prop64 = of_get_property(np, "ibm,opal-hubid", NULL); - if (!prop64) { - pr_err(" Missing \"ibm,opal-hubid\" property !\n"); - return; - } - hub_id = be64_to_cpup(prop64); - pr_devel(" HUB-ID : 0x%016llx\n", hub_id); - - /* Count child PHBs */ - for_each_child_of_node(np, phbn) { - /* Look for IODA1 PHBs */ - if (of_device_is_compatible(phbn, "ibm,ioda-phb")) - pnv_pci_init_ioda_phb(phbn, hub_id, PNV_PHB_IODA1); - } -} diff --git a/arch/powerpc/platforms/powernv/pci-sriov.c b/arch/powerpc/platforms/powernv/pci-sriov.c index 7195133b26bb9eeafca1bc4efb2c0f1df125cfaf..59882da3e74253fcf0fb34d5976065081f1faa41 100644 --- a/arch/powerpc/platforms/powernv/pci-sriov.c +++ b/arch/powerpc/platforms/powernv/pci-sriov.c @@ -594,12 +594,12 @@ static void pnv_pci_sriov_disable(struct pci_dev *pdev) struct pnv_iov_data *iov; iov = pnv_iov_get(pdev); - num_vfs = iov->num_vfs; - base_pe = iov->vf_pe_arr[0].pe_number; - if (WARN_ON(!iov)) return; + num_vfs = iov->num_vfs; + base_pe = iov->vf_pe_arr[0].pe_number; + /* Release VF PEs */ pnv_ioda_release_vf_PE(pdev); diff --git a/arch/powerpc/platforms/powernv/pci.c b/arch/powerpc/platforms/powernv/pci.c index 7725492097b627ff70b6026f0c9267bf94feb9be..35f566aa04243d1cfd56ce151e3f7d2d16720767 100644 --- a/arch/powerpc/platforms/powernv/pci.c +++ b/arch/powerpc/platforms/powernv/pci.c @@ -845,11 +845,6 @@ void __init pnv_pci_init(void) pcie_ports_disabled = true; #endif - /* Look for IODA IO-Hubs. */ - for_each_compatible_node(np, NULL, "ibm,ioda-hub") { - pnv_pci_init_ioda_hub(np); - } - /* Look for ioda2 built-in PHB3's */ for_each_compatible_node(np, NULL, "ibm,ioda2-phb") pnv_pci_init_ioda2_phb(np); diff --git a/arch/powerpc/platforms/powernv/pci.h b/arch/powerpc/platforms/powernv/pci.h index f12643958b8d88ca1f8e77bf126fd9366c8a9b10..957f2b47a3c0c21e8c83e3c7062be003d0e2d0b2 100644 --- a/arch/powerpc/platforms/powernv/pci.h +++ b/arch/powerpc/platforms/powernv/pci.h @@ -10,7 +10,6 @@ struct pci_dn; enum pnv_phb_type { - PNV_PHB_IODA1, PNV_PHB_IODA2, PNV_PHB_NPU_OCAPI, }; @@ -163,10 +162,6 @@ struct pnv_phb { unsigned int *m32_segmap; unsigned int *io_segmap; - /* DMA32 segment maps - IODA1 only */ - unsigned int dma32_count; - unsigned int *dma32_segmap; - /* IRQ chip */ int irq_chip_init; struct irq_chip irq_chip; diff --git a/arch/powerpc/platforms/powernv/vas-window.c b/arch/powerpc/platforms/powernv/vas-window.c index 0072682531d8064e638958e120d17a3dcea725c5..b664838008c12a48c33359fb5e23259b7d26e57b 100644 --- a/arch/powerpc/platforms/powernv/vas-window.c +++ b/arch/powerpc/platforms/powernv/vas-window.c @@ -1310,8 +1310,8 @@ int vas_win_close(struct vas_window *vwin) /* if send window, drop reference to matching receive window */ if (window->tx_win) { if (window->user_win) { - put_vas_user_win_ref(&vwin->task_ref); mm_context_remove_vas_window(vwin->task_ref.mm); + put_vas_user_win_ref(&vwin->task_ref); } put_rx_win(window->rxwin); } diff --git a/arch/powerpc/platforms/pseries/dlpar.c b/arch/powerpc/platforms/pseries/dlpar.c index 719c97a155edfab9f5eae927c446bd0f7dad38cf..47f8eabd1bee311b84f53b66d61e2215fb0b4a83 100644 --- a/arch/powerpc/platforms/pseries/dlpar.c +++ b/arch/powerpc/platforms/pseries/dlpar.c @@ -564,8 +564,7 @@ int __init dlpar_workqueue_init(void) if (pseries_hp_wq) return 0; - pseries_hp_wq = alloc_workqueue("pseries hotplug workqueue", - WQ_UNBOUND, 1); + pseries_hp_wq = alloc_ordered_workqueue("pseries hotplug workqueue", 0); return pseries_hp_wq ? 0 : -ENOMEM; } diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c index d59e8a98a200826c75a1602129312b8014f5f26d..d593a7227dc919a66752831beab9b62711665bb0 100644 --- a/arch/powerpc/platforms/pseries/iommu.c +++ b/arch/powerpc/platforms/pseries/iommu.c @@ -372,6 +372,7 @@ struct dynamic_dma_window_prop { struct dma_win { struct device_node *device; const struct dynamic_dma_window_prop *prop; + bool direct; struct list_head list; }; @@ -948,6 +949,7 @@ static struct dma_win *ddw_list_new_entry(struct device_node *pdn, window->device = pdn; window->prop = dma64; + window->direct = false; return window; } @@ -1418,6 +1420,8 @@ static bool enable_ddw(struct pci_dev *dev, struct device_node *pdn) goto out_del_prop; if (direct_mapping) { + window->direct = true; + /* DDW maps the whole partition, so enable direct DMA mapping */ ret = walk_system_ram_range(0, memblock_end_of_DRAM() >> PAGE_SHIFT, win64->value, tce_setrange_multi_pSeriesLP_walk); @@ -1434,6 +1438,8 @@ static bool enable_ddw(struct pci_dev *dev, struct device_node *pdn) int i; unsigned long start = 0, end = 0; + window->direct = false; + for (i = 0; i < ARRAY_SIZE(pci->phb->mem_resources); i++) { const unsigned long mask = IORESOURCE_MEM_64 | IORESOURCE_MEM; @@ -1596,8 +1602,10 @@ static int iommu_mem_notifier(struct notifier_block *nb, unsigned long action, case MEM_GOING_ONLINE: spin_lock(&dma_win_list_lock); list_for_each_entry(window, &dma_win_list, list) { - ret |= tce_setrange_multi_pSeriesLP(arg->start_pfn, - arg->nr_pages, window->prop); + if (window->direct) { + ret |= tce_setrange_multi_pSeriesLP(arg->start_pfn, + arg->nr_pages, window->prop); + } /* XXX log error */ } spin_unlock(&dma_win_list_lock); @@ -1606,8 +1614,10 @@ static int iommu_mem_notifier(struct notifier_block *nb, unsigned long action, case MEM_OFFLINE: spin_lock(&dma_win_list_lock); list_for_each_entry(window, &dma_win_list, list) { - ret |= tce_clearrange_multi_pSeriesLP(arg->start_pfn, - arg->nr_pages, window->prop); + if (window->direct) { + ret |= tce_clearrange_multi_pSeriesLP(arg->start_pfn, + arg->nr_pages, window->prop); + } /* XXX log error */ } spin_unlock(&dma_win_list_lock); diff --git a/arch/powerpc/platforms/pseries/mobility.c b/arch/powerpc/platforms/pseries/mobility.c index 6f30113b5468eb2b7296cc7cff480dd426733f3b..0161226d8fec9465e9699da363ef5ab1a59e4a80 100644 --- a/arch/powerpc/platforms/pseries/mobility.c +++ b/arch/powerpc/platforms/pseries/mobility.c @@ -24,6 +24,7 @@ #include #include +#include #include #include "pseries.h" #include "vas.h" /* vas_migration_handler() */ @@ -750,7 +751,7 @@ static int pseries_migrate_partition(u64 handle) goto out; if (factor) - watchdog_nmi_set_timeout_pct(factor); + watchdog_hardlockup_set_timeout_pct(factor); ret = pseries_suspend(handle); if (ret == 0) { @@ -766,7 +767,7 @@ static int pseries_migrate_partition(u64 handle) pseries_cancel_migration(handle, ret); if (factor) - watchdog_nmi_set_timeout_pct(0); + watchdog_hardlockup_set_timeout_pct(0); out: vas_migration_handler(VAS_RESUME); diff --git a/arch/powerpc/platforms/pseries/vas.c b/arch/powerpc/platforms/pseries/vas.c index 513180467562b60e78956813027b90894b05ffe6..9a44a98ba3420652b47fed461f4ee19bd4699558 100644 --- a/arch/powerpc/platforms/pseries/vas.c +++ b/arch/powerpc/platforms/pseries/vas.c @@ -507,8 +507,8 @@ static int vas_deallocate_window(struct vas_window *vwin) vascaps[win->win_type].nr_open_windows--; mutex_unlock(&vas_pseries_mutex); - put_vas_user_win_ref(&vwin->task_ref); mm_context_remove_vas_window(vwin->task_ref.mm); + put_vas_user_win_ref(&vwin->task_ref); kfree(win); return 0; diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c index b7232c46b24481a8f6b35ef266fb2e074a21abdb..6daf620b63a4d52b12567971ae0bcdf35cb5cad3 100644 --- a/arch/powerpc/sysdev/fsl_pci.c +++ b/arch/powerpc/sysdev/fsl_pci.c @@ -1353,6 +1353,7 @@ static struct platform_driver fsl_pci_driver = { .of_match_table = pci_ids, }, .probe = fsl_pci_probe, + .driver_managed_dma = true, }; static int __init fsl_pci_init(void) diff --git a/arch/powerpc/sysdev/fsl_rio.c b/arch/powerpc/sysdev/fsl_rio.c index f8e492ee54ccb07a855775f1241da1e939287269..0331962bc6d2dc85edf4a2842aabb8057683927c 100644 --- a/arch/powerpc/sysdev/fsl_rio.c +++ b/arch/powerpc/sysdev/fsl_rio.c @@ -448,13 +448,11 @@ int fsl_rio_setup(struct platform_device *dev) struct rio_mport *port; struct rio_priv *priv; int rc = 0; - const u32 *dt_range, *cell, *port_index; + const u32 *port_index; u32 active_ports = 0; struct device_node *np, *rmu_node; - int rlen; u32 ccsr; - u64 range_start, range_size; - int paw, aw, sw; + u64 range_start; u32 i; static int tmp; struct device_node *rmu_np[MAX_MSG_UNIT_NUM] = {NULL}; @@ -528,15 +526,12 @@ int fsl_rio_setup(struct platform_device *dev) dbell->bellirq = irq_of_parse_and_map(np, 1); dev_info(&dev->dev, "bellirq: %d\n", dbell->bellirq); - aw = of_n_addr_cells(np); - dt_range = of_get_property(np, "reg", &rlen); - if (!dt_range) { + if (of_property_read_reg(np, 0, &range_start, NULL)) { pr_err("%pOF: unable to find 'reg' property\n", np); rc = -ENOMEM; goto err_pw; } - range_start = of_read_number(dt_range, aw); dbell->dbell_regs = (struct rio_dbell_regs *)(rmu_regs_win + (u32)range_start); @@ -556,19 +551,18 @@ int fsl_rio_setup(struct platform_device *dev) pw->dev = &dev->dev; pw->pwirq = irq_of_parse_and_map(np, 0); dev_info(&dev->dev, "pwirq: %d\n", pw->pwirq); - aw = of_n_addr_cells(np); - dt_range = of_get_property(np, "reg", &rlen); - if (!dt_range) { + if (of_property_read_reg(np, 0, &range_start, NULL)) { pr_err("%pOF: unable to find 'reg' property\n", np); rc = -ENOMEM; goto err; } - range_start = of_read_number(dt_range, aw); pw->pw_regs = (struct rio_pw_regs *)(rmu_regs_win + (u32)range_start); /*set up ports node*/ for_each_child_of_node(dev->dev.of_node, np) { + struct resource res; + port_index = of_get_property(np, "cell-index", NULL); if (!port_index) { dev_err(&dev->dev, "Can't get %pOF property 'cell-index'\n", @@ -576,32 +570,14 @@ int fsl_rio_setup(struct platform_device *dev) continue; } - dt_range = of_get_property(np, "ranges", &rlen); - if (!dt_range) { + if (of_range_to_resource(np, 0, &res)) { dev_err(&dev->dev, "Can't get %pOF property 'ranges'\n", np); continue; } - /* Get node address wide */ - cell = of_get_property(np, "#address-cells", NULL); - if (cell) - aw = *cell; - else - aw = of_n_addr_cells(np); - /* Get node size wide */ - cell = of_get_property(np, "#size-cells", NULL); - if (cell) - sw = *cell; - else - sw = of_n_size_cells(np); - /* Get parent address wide wide */ - paw = of_n_addr_cells(np); - range_start = of_read_number(dt_range + aw, paw); - range_size = of_read_number(dt_range + aw + paw, sw); - - dev_info(&dev->dev, "%pOF: LAW start 0x%016llx, size 0x%016llx.\n", - np, range_start, range_size); + dev_info(&dev->dev, "%pOF: LAW %pR\n", + np, &res); port = kzalloc(sizeof(struct rio_mport), GFP_KERNEL); if (!port) @@ -624,9 +600,7 @@ int fsl_rio_setup(struct platform_device *dev) } INIT_LIST_HEAD(&port->dbells); - port->iores.start = range_start; - port->iores.end = port->iores.start + range_size - 1; - port->iores.flags = IORESOURCE_MEM; + port->iores = res; /* struct copy */ port->iores.name = "rio_io_win"; if (request_resource(&iomem_resource, &port->iores) < 0) { diff --git a/arch/powerpc/sysdev/fsl_rmu.c b/arch/powerpc/sysdev/fsl_rmu.c index 7a5e2e2b9d060e4a1f98bba06624d2d4e20fc110..c1f724973589721564abf13b8b2061ba49d0a580 100644 --- a/arch/powerpc/sysdev/fsl_rmu.c +++ b/arch/powerpc/sysdev/fsl_rmu.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -1067,9 +1068,6 @@ int fsl_rio_setup_rmu(struct rio_mport *mport, struct device_node *node) struct rio_priv *priv; struct fsl_rmu *rmu; u64 msg_start; - const u32 *msg_addr; - int mlen; - int aw; if (!mport || !mport->priv) return -EINVAL; @@ -1086,16 +1084,12 @@ int fsl_rio_setup_rmu(struct rio_mport *mport, struct device_node *node) if (!rmu) return -ENOMEM; - aw = of_n_addr_cells(node); - msg_addr = of_get_property(node, "reg", &mlen); - if (!msg_addr) { + if (of_property_read_reg(node, 0, &msg_start, NULL)) { pr_err("%pOF: unable to find 'reg' property of message-unit\n", node); kfree(rmu); return -ENOMEM; } - msg_start = of_read_number(msg_addr, aw); - rmu->msg_regs = (struct rio_msg_regs *) (rmu_regs_win + (u32)msg_start); diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c index 6ebbbca41065f2a9a9e770c4cc35b87a22cf559e..68709743450e3fad5ea77b1e1cccdbff7859cd8a 100644 --- a/arch/powerpc/sysdev/fsl_soc.c +++ b/arch/powerpc/sysdev/fsl_soc.c @@ -51,18 +51,10 @@ phys_addr_t get_immrbase(void) soc = of_find_node_by_type(NULL, "soc"); if (soc) { - int size; - u32 naddr; - const __be32 *prop = of_get_property(soc, "#address-cells", &size); - - if (prop && size == 4) - naddr = be32_to_cpup(prop); - else - naddr = 2; - - prop = of_get_property(soc, "ranges", &size); - if (prop) - immrbase = of_translate_address(soc, prop + naddr); + struct resource res; + + if (!of_range_to_resource(soc, 0, &res)) + immrbase = res.start; of_node_put(soc); } diff --git a/arch/powerpc/tools/gcc-check-mprofile-kernel.sh b/arch/powerpc/tools/gcc-check-mprofile-kernel.sh index 137f3376ac2bb05a3debbcdbe913594dbd7f54a8..a31a56016c094fb644d5c36c20be0c9f081cbc9d 100755 --- a/arch/powerpc/tools/gcc-check-mprofile-kernel.sh +++ b/arch/powerpc/tools/gcc-check-mprofile-kernel.sh @@ -7,20 +7,21 @@ set -o pipefail # To debug, uncomment the following line # set -x -# -mprofile-kernel is only supported on 64le, so this should not be invoked -# for other targets. Therefore we can pass in -m64 and -mlittle-endian -# explicitly, to take care of toolchains defaulting to other targets. +# -mprofile-kernel is only supported on 64-bit, so this should not be invoked +# for 32-bit. We pass in -m64 explicitly, and -mbig-endian and -mlittle-endian +# are passed in from Kconfig, which takes care of toolchains defaulting to +# other targets. # Test whether the compile option -mprofile-kernel exists and generates # profiling code (ie. a call to _mcount()). echo "int func() { return 0; }" | \ - $* -m64 -mlittle-endian -S -x c -O2 -p -mprofile-kernel - -o - \ + $* -m64 -S -x c -O2 -p -mprofile-kernel - -o - \ 2> /dev/null | grep -q "_mcount" # Test whether the notrace attribute correctly suppresses calls to _mcount(). echo -e "#include \nnotrace int func() { return 0; }" | \ - $* -m64 -mlittle-endian -S -x c -O2 -p -mprofile-kernel - -o - \ + $* -m64 -S -x c -O2 -p -mprofile-kernel - -o - \ 2> /dev/null | grep -q "_mcount" && \ exit 1 diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c index 70c4c59a1a8f47f103ba180935974b6e71f6db31..fae747cc57d2dd8af03768cae8df506f75286639 100644 --- a/arch/powerpc/xmon/xmon.c +++ b/arch/powerpc/xmon/xmon.c @@ -3376,12 +3376,15 @@ static void show_pte(unsigned long addr) printf("pmdp @ 0x%px = 0x%016lx\n", pmdp, pmd_val(*pmdp)); ptep = pte_offset_map(pmdp, addr); - if (pte_none(*ptep)) { + if (!ptep || pte_none(*ptep)) { + if (ptep) + pte_unmap(ptep); printf("no valid PTE\n"); return; } format_pte(ptep, pte_val(*ptep)); + pte_unmap(ptep); sync(); __delay(200); diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig index 5966ad97c30c3d8f157dad32f4da9a5ab07790a7..4c07b9189c867b715f96ec3beaf1c14a810bb2ae 100644 --- a/arch/riscv/Kconfig +++ b/arch/riscv/Kconfig @@ -12,6 +12,8 @@ config 32BIT config RISCV def_bool y + select ACPI_GENERIC_GSI if ACPI + select ACPI_REDUCED_HARDWARE_ONLY if ACPI select ARCH_DMA_DEFAULT_COHERENT select ARCH_ENABLE_HUGEPAGE_MIGRATION if HUGETLB_PAGE && MIGRATION select ARCH_ENABLE_SPLIT_PMD_PTLOCK if PGTABLE_LEVELS > 2 @@ -43,6 +45,7 @@ config RISCV select ARCH_SUPPORTS_DEBUG_PAGEALLOC if MMU select ARCH_SUPPORTS_HUGETLBFS if MMU select ARCH_SUPPORTS_PAGE_TABLE_CHECK if MMU + select ARCH_SUPPORTS_PER_VMA_LOCK if MMU select ARCH_USE_MEMTEST select ARCH_USE_QUEUED_RWLOCKS select ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT if MMU @@ -97,11 +100,18 @@ config RISCV select HAVE_ARCH_THREAD_STRUCT_WHITELIST select HAVE_ARCH_TRACEHOOK select HAVE_ARCH_TRANSPARENT_HUGEPAGE if 64BIT && MMU + select HAVE_ARCH_USERFAULTFD_MINOR if 64BIT && USERFAULTFD select HAVE_ARCH_VMAP_STACK if MMU && 64BIT select HAVE_ASM_MODVERSIONS select HAVE_CONTEXT_TRACKING_USER select HAVE_DEBUG_KMEMLEAK select HAVE_DMA_CONTIGUOUS if MMU + select HAVE_DYNAMIC_FTRACE if !XIP_KERNEL && MMU && (CLANG_SUPPORTS_DYNAMIC_FTRACE || GCC_SUPPORTS_DYNAMIC_FTRACE) + select HAVE_DYNAMIC_FTRACE_WITH_REGS if HAVE_DYNAMIC_FTRACE + select HAVE_FTRACE_MCOUNT_RECORD if !XIP_KERNEL + select HAVE_FUNCTION_GRAPH_TRACER + select HAVE_FUNCTION_GRAPH_RETVAL if HAVE_FUNCTION_GRAPH_TRACER + select HAVE_FUNCTION_TRACER if !XIP_KERNEL && !PREEMPTION select HAVE_EBPF_JIT if MMU select HAVE_FUNCTION_ARG_ACCESS_API select HAVE_FUNCTION_ERROR_INJECTION @@ -111,7 +121,8 @@ config RISCV select HAVE_KPROBES if !XIP_KERNEL select HAVE_KPROBES_ON_FTRACE if !XIP_KERNEL select HAVE_KRETPROBES if !XIP_KERNEL - select HAVE_RETHOOK if !XIP_KERNEL + # https://github.com/ClangBuiltLinux/linux/issues/1881 + select HAVE_LD_DEAD_CODE_DATA_ELIMINATION if !LD_IS_LLD select HAVE_MOVE_PMD select HAVE_MOVE_PUD select HAVE_PCI @@ -120,12 +131,15 @@ config RISCV select HAVE_PERF_USER_STACK_DUMP select HAVE_POSIX_CPU_TIMERS_TASK_WORK select HAVE_REGS_AND_STACK_ACCESS_API + select HAVE_RETHOOK if !XIP_KERNEL select HAVE_RSEQ select HAVE_STACKPROTECTOR select HAVE_SYSCALL_TRACEPOINTS + select HOTPLUG_CORE_SYNC_DEAD if HOTPLUG_CPU select IRQ_DOMAIN select IRQ_FORCED_THREADING select KASAN_VMALLOC if KASAN + select LOCK_MM_AND_FIND_VMA select MODULES_USE_ELF_RELA if MODULES select MODULE_SECTIONS if MODULES select OF @@ -143,11 +157,6 @@ config RISCV select TRACE_IRQFLAGS_SUPPORT select UACCESS_MEMCPY if !MMU select ZONE_DMA32 if 64BIT - select HAVE_DYNAMIC_FTRACE if !XIP_KERNEL && MMU && (CLANG_SUPPORTS_DYNAMIC_FTRACE || GCC_SUPPORTS_DYNAMIC_FTRACE) - select HAVE_DYNAMIC_FTRACE_WITH_REGS if HAVE_DYNAMIC_FTRACE - select HAVE_FTRACE_MCOUNT_RECORD if !XIP_KERNEL - select HAVE_FUNCTION_GRAPH_TRACER - select HAVE_FUNCTION_TRACER if !XIP_KERNEL && !PREEMPTION config CLANG_SUPPORTS_DYNAMIC_FTRACE def_bool CC_IS_CLANG @@ -263,6 +272,12 @@ config RISCV_DMA_NONCOHERENT config AS_HAS_INSN def_bool $(as-instr,.insn r 51$(comma) 0$(comma) 0$(comma) t0$(comma) t0$(comma) zero) +config AS_HAS_OPTION_ARCH + # https://reviews.llvm.org/D123515 + def_bool y + depends on $(as-instr, .option arch$(comma) +m) + depends on !$(as-instr, .option arch$(comma) -i) + source "arch/riscv/Kconfig.socs" source "arch/riscv/Kconfig.errata" @@ -461,13 +476,44 @@ config RISCV_ISA_SVPBMT If you don't know what to do here, say Y. +config TOOLCHAIN_HAS_V + bool + default y + depends on !64BIT || $(cc-option,-mabi=lp64 -march=rv64iv) + depends on !32BIT || $(cc-option,-mabi=ilp32 -march=rv32iv) + depends on LLD_VERSION >= 140000 || LD_VERSION >= 23800 + depends on AS_HAS_OPTION_ARCH + +config RISCV_ISA_V + bool "VECTOR extension support" + depends on TOOLCHAIN_HAS_V + depends on FPU + select DYNAMIC_SIGFRAME + default y + help + Say N here if you want to disable all vector related procedure + in the kernel. + + If you don't know what to do here, say Y. + +config RISCV_ISA_V_DEFAULT_ENABLE + bool "Enable userspace Vector by default" + depends on RISCV_ISA_V + default y + help + Say Y here if you want to enable Vector in userspace by default. + Otherwise, userspace has to make explicit prctl() call to enable + Vector, or enable it via the sysctl interface. + + If you don't know what to do here, say Y. + config TOOLCHAIN_HAS_ZBB bool default y depends on !64BIT || $(cc-option,-mabi=lp64 -march=rv64ima_zbb) depends on !32BIT || $(cc-option,-mabi=ilp32 -march=rv32ima_zbb) depends on LLD_VERSION >= 150000 || LD_VERSION >= 23900 - depends on AS_IS_GNU + depends on AS_HAS_OPTION_ARCH config RISCV_ISA_ZBB bool "Zbb extension support for bit manipulation instructions" @@ -552,6 +598,25 @@ config FPU If you don't know what to do here, say Y. +config IRQ_STACKS + bool "Independent irq & softirq stacks" if EXPERT + default y + select HAVE_IRQ_EXIT_ON_IRQ_STACK + select HAVE_SOFTIRQ_ON_OWN_STACK + help + Add independent irq & softirq stacks for percpu to prevent kernel stack + overflows. We may save some memory footprint by disabling IRQ_STACKS. + +config THREAD_SIZE_ORDER + int "Kernel stack size (in power-of-two numbers of page size)" if VMAP_STACK && EXPERT + range 0 4 + default 1 if 32BIT && !KASAN + default 3 if 64BIT && KASAN + default 2 + help + Specify the Pages of thread stack size (from 4KB to 64KB), which also + affects irq stack size, which is equal to thread stack size. + endmenu # "Platform type" menu "Kernel features" @@ -708,6 +773,7 @@ config EFI depends on OF && !XIP_KERNEL depends on MMU default y + select ARCH_SUPPORTS_ACPI if 64BIT select EFI_GENERIC_STUB select EFI_PARAMS_FROM_FDT select EFI_RUNTIME_WRAPPERS @@ -809,6 +875,9 @@ config ARCH_HIBERNATION_POSSIBLE config ARCH_HIBERNATION_HEADER def_bool HIBERNATION +config ARCH_SUSPEND_POSSIBLE + def_bool y + endmenu # "Power management options" menu "CPU Power Management" @@ -820,3 +889,5 @@ source "drivers/cpufreq/Kconfig" endmenu # "CPU Power Management" source "arch/riscv/kvm/Kconfig" + +source "drivers/acpi/Kconfig" diff --git a/arch/riscv/Kconfig.socs b/arch/riscv/Kconfig.socs index 1cf69f958f1042dd22b8e1cd49939ab35435dd26..6833d01e2e707bbc85e9acd7f1b1538d32cc06e7 100644 --- a/arch/riscv/Kconfig.socs +++ b/arch/riscv/Kconfig.socs @@ -41,6 +41,13 @@ config ARCH_SUNXI This enables support for Allwinner sun20i platform hardware, including boards based on the D1 and D1s SoCs. +config ARCH_THEAD + bool "T-HEAD RISC-V SoCs" + depends on MMU && !XIP_KERNEL + select ERRATA_THEAD + help + This enables support for the RISC-V based T-HEAD SoCs. + config ARCH_VIRT def_bool SOC_VIRT diff --git a/arch/riscv/Makefile b/arch/riscv/Makefile index 0fb256bf8270916c320b9a291b6e5bcb47ed349f..6ec6d52a4180442ab44dd9d91b30d9ee71debcca 100644 --- a/arch/riscv/Makefile +++ b/arch/riscv/Makefile @@ -60,6 +60,7 @@ riscv-march-$(CONFIG_ARCH_RV32I) := rv32ima riscv-march-$(CONFIG_ARCH_RV64I) := rv64ima riscv-march-$(CONFIG_FPU) := $(riscv-march-y)fd riscv-march-$(CONFIG_RISCV_ISA_C) := $(riscv-march-y)c +riscv-march-$(CONFIG_RISCV_ISA_V) := $(riscv-march-y)v ifdef CONFIG_TOOLCHAIN_NEEDS_OLD_ISA_SPEC KBUILD_CFLAGS += -Wa,-misa-spec=2.2 @@ -71,7 +72,10 @@ endif # Check if the toolchain supports Zihintpause extension riscv-march-$(CONFIG_TOOLCHAIN_HAS_ZIHINTPAUSE) := $(riscv-march-y)_zihintpause -KBUILD_CFLAGS += -march=$(subst fd,,$(riscv-march-y)) +# Remove F,D,V from isa string for all. Keep extensions between "fd" and "v" by +# matching non-v and non-multi-letter extensions out with the filter ([^v_]*) +KBUILD_CFLAGS += -march=$(shell echo $(riscv-march-y) | sed -E 's/(rv32ima|rv64ima)fd([^v_]*)v?/\1\2/') + KBUILD_AFLAGS += -march=$(riscv-march-y) KBUILD_CFLAGS += -mno-save-restore diff --git a/arch/riscv/boot/dts/Makefile b/arch/riscv/boot/dts/Makefile index f0d9f89054f821cded0b2e5a58641059807e9a37..f60a280abb1573ee8b775ab5e55b917885aaaf08 100644 --- a/arch/riscv/boot/dts/Makefile +++ b/arch/riscv/boot/dts/Makefile @@ -1,9 +1,10 @@ # SPDX-License-Identifier: GPL-2.0 subdir-y += allwinner -subdir-y += sifive -subdir-y += starfive subdir-y += canaan subdir-y += microchip subdir-y += renesas +subdir-y += sifive +subdir-y += starfive +subdir-y += thead obj-$(CONFIG_BUILTIN_DTB) := $(addsuffix /, $(subdir-y)) diff --git a/arch/riscv/boot/dts/allwinner/sunxi-d1s-t113.dtsi b/arch/riscv/boot/dts/allwinner/sunxi-d1s-t113.dtsi index 922e8e0e2c0999b689cb35b9db1d5f7677ab1818..1bb1e5cae6021cfb065adfc5b043ebc1a8c259d8 100644 --- a/arch/riscv/boot/dts/allwinner/sunxi-d1s-t113.dtsi +++ b/arch/riscv/boot/dts/allwinner/sunxi-d1s-t113.dtsi @@ -108,6 +108,12 @@ function = "emac"; }; + /omit-if-no-ref/ + spi0_pins: spi0-pins { + pins = "PC2", "PC3", "PC4", "PC5"; + function = "spi0"; + }; + /omit-if-no-ref/ uart1_pg6_pins: uart1-pg6-pins { pins = "PG6", "PG7"; @@ -447,6 +453,37 @@ #size-cells = <0>; }; + spi0: spi@4025000 { + compatible = "allwinner,sun20i-d1-spi", + "allwinner,sun50i-r329-spi"; + reg = <0x04025000 0x1000>; + interrupts = ; + clocks = <&ccu CLK_BUS_SPI0>, <&ccu CLK_SPI0>; + clock-names = "ahb", "mod"; + dmas = <&dma 22>, <&dma 22>; + dma-names = "rx", "tx"; + resets = <&ccu RST_BUS_SPI0>; + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; + }; + + spi1: spi@4026000 { + compatible = "allwinner,sun20i-d1-spi-dbi", + "allwinner,sun50i-r329-spi-dbi", + "allwinner,sun50i-r329-spi"; + reg = <0x04026000 0x1000>; + interrupts = ; + clocks = <&ccu CLK_BUS_SPI1>, <&ccu CLK_SPI1>; + clock-names = "ahb", "mod"; + dmas = <&dma 23>, <&dma 23>; + dma-names = "rx", "tx"; + resets = <&ccu RST_BUS_SPI1>; + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; + }; + usb_otg: usb@4100000 { compatible = "allwinner,sun20i-d1-musb", "allwinner,sun8i-a33-musb"; diff --git a/arch/riscv/boot/dts/starfive/jh7100.dtsi b/arch/riscv/boot/dts/starfive/jh7100.dtsi index 000447482acaa504020b9994c7e2701c8e09eb8d..4218621ea3b92c90a6b8b81bc4015649cc7eda3e 100644 --- a/arch/riscv/boot/dts/starfive/jh7100.dtsi +++ b/arch/riscv/boot/dts/starfive/jh7100.dtsi @@ -238,5 +238,15 @@ #size-cells = <0>; status = "disabled"; }; + + watchdog@12480000 { + compatible = "starfive,jh7100-wdt"; + reg = <0x0 0x12480000 0x0 0x10000>; + clocks = <&clkgen JH7100_CLK_WDTIMER_APB>, + <&clkgen JH7100_CLK_WDT_CORE>; + clock-names = "apb", "core"; + resets = <&rstgen JH7100_RSTN_WDTIMER_APB>, + <&rstgen JH7100_RSTN_WDT>; + }; }; }; diff --git a/arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2.dtsi b/arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2.dtsi index 2a6d81609284cb57c1132851a891cc6ce3812c70..fa0061eb33a75fbcf089c4349b836a63edb64b4e 100644 --- a/arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2.dtsi +++ b/arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2.dtsi @@ -114,6 +114,23 @@ pinctrl-names = "default"; pinctrl-0 = <&i2c5_pins>; status = "okay"; + + axp15060: pmic@36 { + compatible = "x-powers,axp15060"; + reg = <0x36>; + interrupts = <0>; + interrupt-controller; + #interrupt-cells = <1>; + + regulators { + vdd_cpu: dcdc2 { + regulator-always-on; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <1540000>; + regulator-name = "vdd-cpu"; + }; + }; + }; }; &i2c6 { @@ -213,3 +230,19 @@ pinctrl-0 = <&uart0_pins>; status = "okay"; }; + +&U74_1 { + cpu-supply = <&vdd_cpu>; +}; + +&U74_2 { + cpu-supply = <&vdd_cpu>; +}; + +&U74_3 { + cpu-supply = <&vdd_cpu>; +}; + +&U74_4 { + cpu-supply = <&vdd_cpu>; +}; diff --git a/arch/riscv/boot/dts/starfive/jh7110.dtsi b/arch/riscv/boot/dts/starfive/jh7110.dtsi index 4c5fdb905da8040174e2f223017af0829039b23c..ec2e70011a73673669babb53323b9ee5240355c0 100644 --- a/arch/riscv/boot/dts/starfive/jh7110.dtsi +++ b/arch/riscv/boot/dts/starfive/jh7110.dtsi @@ -53,6 +53,9 @@ next-level-cache = <&ccache>; riscv,isa = "rv64imafdc_zba_zbb"; tlb-split; + operating-points-v2 = <&cpu_opp>; + clocks = <&syscrg JH7110_SYSCLK_CPU_CORE>; + clock-names = "cpu"; cpu1_intc: interrupt-controller { compatible = "riscv,cpu-intc"; @@ -79,6 +82,9 @@ next-level-cache = <&ccache>; riscv,isa = "rv64imafdc_zba_zbb"; tlb-split; + operating-points-v2 = <&cpu_opp>; + clocks = <&syscrg JH7110_SYSCLK_CPU_CORE>; + clock-names = "cpu"; cpu2_intc: interrupt-controller { compatible = "riscv,cpu-intc"; @@ -105,6 +111,9 @@ next-level-cache = <&ccache>; riscv,isa = "rv64imafdc_zba_zbb"; tlb-split; + operating-points-v2 = <&cpu_opp>; + clocks = <&syscrg JH7110_SYSCLK_CPU_CORE>; + clock-names = "cpu"; cpu3_intc: interrupt-controller { compatible = "riscv,cpu-intc"; @@ -131,6 +140,9 @@ next-level-cache = <&ccache>; riscv,isa = "rv64imafdc_zba_zbb"; tlb-split; + operating-points-v2 = <&cpu_opp>; + clocks = <&syscrg JH7110_SYSCLK_CPU_CORE>; + clock-names = "cpu"; cpu4_intc: interrupt-controller { compatible = "riscv,cpu-intc"; @@ -164,6 +176,27 @@ }; }; + cpu_opp: opp-table-0 { + compatible = "operating-points-v2"; + opp-shared; + opp-375000000 { + opp-hz = /bits/ 64 <375000000>; + opp-microvolt = <800000>; + }; + opp-500000000 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <800000>; + }; + opp-750000000 { + opp-hz = /bits/ 64 <750000000>; + opp-microvolt = <800000>; + }; + opp-1500000000 { + opp-hz = /bits/ 64 <1500000000>; + opp-microvolt = <1040000>; + }; + }; + gmac0_rgmii_rxin: gmac0-rgmii-rxin-clock { compatible = "fixed-clock"; clock-output-names = "gmac0_rgmii_rxin"; @@ -469,6 +502,16 @@ #gpio-cells = <2>; }; + watchdog@13070000 { + compatible = "starfive,jh7110-wdt"; + reg = <0x0 0x13070000 0x0 0x10000>; + clocks = <&syscrg JH7110_SYSCLK_WDT_APB>, + <&syscrg JH7110_SYSCLK_WDT_CORE>; + clock-names = "apb", "core"; + resets = <&syscrg JH7110_SYSRST_WDT_APB>, + <&syscrg JH7110_SYSRST_WDT_CORE>; + }; + aoncrg: clock-controller@17000000 { compatible = "starfive,jh7110-aoncrg"; reg = <0x0 0x17000000 0x0 0x10000>; @@ -496,5 +539,12 @@ gpio-controller; #gpio-cells = <2>; }; + + pwrc: power-controller@17030000 { + compatible = "starfive,jh7110-pmu"; + reg = <0x0 0x17030000 0x0 0x10000>; + interrupts = <111>; + #power-domain-cells = <1>; + }; }; }; diff --git a/arch/riscv/boot/dts/thead/Makefile b/arch/riscv/boot/dts/thead/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..e311fc9a59390a419b828b879cc8477c2de5d8d2 --- /dev/null +++ b/arch/riscv/boot/dts/thead/Makefile @@ -0,0 +1,2 @@ +# SPDX-License-Identifier: GPL-2.0 +dtb-$(CONFIG_ARCH_THEAD) += th1520-lichee-pi-4a.dtb diff --git a/arch/riscv/boot/dts/thead/th1520-lichee-module-4a.dtsi b/arch/riscv/boot/dts/thead/th1520-lichee-module-4a.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..4b0249ac710f4f0f66677f236b7e6cd445f06f5d --- /dev/null +++ b/arch/riscv/boot/dts/thead/th1520-lichee-module-4a.dtsi @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2023 Jisheng Zhang + */ + +/dts-v1/; + +#include "th1520.dtsi" + +/ { + model = "Sipeed Lichee Module 4A"; + compatible = "sipeed,lichee-module-4a", "thead,th1520"; + + memory@0 { + device_type = "memory"; + reg = <0x0 0x00000000 0x2 0x00000000>; + }; +}; + +&osc { + clock-frequency = <24000000>; +}; + +&osc_32k { + clock-frequency = <32768>; +}; + +&apb_clk { + clock-frequency = <62500000>; +}; + +&uart_sclk { + clock-frequency = <100000000>; +}; + +&dmac0 { + status = "okay"; +}; diff --git a/arch/riscv/boot/dts/thead/th1520-lichee-pi-4a.dts b/arch/riscv/boot/dts/thead/th1520-lichee-pi-4a.dts new file mode 100644 index 0000000000000000000000000000000000000000..a1248b2ee3a3e474ed7ff06f6ee355e6790b6457 --- /dev/null +++ b/arch/riscv/boot/dts/thead/th1520-lichee-pi-4a.dts @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2023 Jisheng Zhang + */ + +#include "th1520-lichee-module-4a.dtsi" + +/ { + model = "Sipeed Lichee Pi 4A"; + compatible = "sipeed,lichee-pi-4a", "sipeed,lichee-module-4a", "thead,th1520"; + + aliases { + gpio0 = &gpio0; + gpio1 = &gpio1; + gpio2 = &gpio2; + gpio3 = &gpio3; + serial0 = &uart0; + serial1 = &uart1; + serial2 = &uart2; + serial3 = &uart3; + serial4 = &uart4; + serial5 = &uart5; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; +}; + +&uart0 { + status = "okay"; +}; diff --git a/arch/riscv/boot/dts/thead/th1520.dtsi b/arch/riscv/boot/dts/thead/th1520.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..56a73134b49e67cba255f486c0767958e098bcf7 --- /dev/null +++ b/arch/riscv/boot/dts/thead/th1520.dtsi @@ -0,0 +1,422 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2021 Alibaba Group Holding Limited. + * Copyright (C) 2023 Jisheng Zhang + */ + +#include + +/ { + compatible = "thead,th1520"; + #address-cells = <2>; + #size-cells = <2>; + + cpus: cpus { + #address-cells = <1>; + #size-cells = <0>; + timebase-frequency = <3000000>; + + c910_0: cpu@0 { + compatible = "thead,c910", "riscv"; + device_type = "cpu"; + riscv,isa = "rv64imafdc"; + reg = <0>; + i-cache-block-size = <64>; + i-cache-size = <65536>; + i-cache-sets = <512>; + d-cache-block-size = <64>; + d-cache-size = <65536>; + d-cache-sets = <512>; + next-level-cache = <&l2_cache>; + mmu-type = "riscv,sv39"; + + cpu0_intc: interrupt-controller { + compatible = "riscv,cpu-intc"; + interrupt-controller; + #interrupt-cells = <1>; + }; + }; + + c910_1: cpu@1 { + compatible = "thead,c910", "riscv"; + device_type = "cpu"; + riscv,isa = "rv64imafdc"; + reg = <1>; + i-cache-block-size = <64>; + i-cache-size = <65536>; + i-cache-sets = <512>; + d-cache-block-size = <64>; + d-cache-size = <65536>; + d-cache-sets = <512>; + next-level-cache = <&l2_cache>; + mmu-type = "riscv,sv39"; + + cpu1_intc: interrupt-controller { + compatible = "riscv,cpu-intc"; + interrupt-controller; + #interrupt-cells = <1>; + }; + }; + + c910_2: cpu@2 { + compatible = "thead,c910", "riscv"; + device_type = "cpu"; + riscv,isa = "rv64imafdc"; + reg = <2>; + i-cache-block-size = <64>; + i-cache-size = <65536>; + i-cache-sets = <512>; + d-cache-block-size = <64>; + d-cache-size = <65536>; + d-cache-sets = <512>; + next-level-cache = <&l2_cache>; + mmu-type = "riscv,sv39"; + + cpu2_intc: interrupt-controller { + compatible = "riscv,cpu-intc"; + interrupt-controller; + #interrupt-cells = <1>; + }; + }; + + c910_3: cpu@3 { + compatible = "thead,c910", "riscv"; + device_type = "cpu"; + riscv,isa = "rv64imafdc"; + reg = <3>; + i-cache-block-size = <64>; + i-cache-size = <65536>; + i-cache-sets = <512>; + d-cache-block-size = <64>; + d-cache-size = <65536>; + d-cache-sets = <512>; + next-level-cache = <&l2_cache>; + mmu-type = "riscv,sv39"; + + cpu3_intc: interrupt-controller { + compatible = "riscv,cpu-intc"; + interrupt-controller; + #interrupt-cells = <1>; + }; + }; + + l2_cache: l2-cache { + compatible = "cache"; + cache-block-size = <64>; + cache-level = <2>; + cache-size = <1048576>; + cache-sets = <1024>; + cache-unified; + }; + }; + + osc: oscillator { + compatible = "fixed-clock"; + clock-output-names = "osc_24m"; + #clock-cells = <0>; + }; + + osc_32k: 32k-oscillator { + compatible = "fixed-clock"; + clock-output-names = "osc_32k"; + #clock-cells = <0>; + }; + + apb_clk: apb-clk-clock { + compatible = "fixed-clock"; + clock-output-names = "apb_clk"; + #clock-cells = <0>; + }; + + uart_sclk: uart-sclk-clock { + compatible = "fixed-clock"; + clock-output-names = "uart_sclk"; + #clock-cells = <0>; + }; + + soc { + compatible = "simple-bus"; + interrupt-parent = <&plic>; + #address-cells = <2>; + #size-cells = <2>; + ranges; + + plic: interrupt-controller@ffd8000000 { + compatible = "thead,th1520-plic", "thead,c900-plic"; + reg = <0xff 0xd8000000 0x0 0x01000000>; + interrupts-extended = <&cpu0_intc 11>, <&cpu0_intc 9>, + <&cpu1_intc 11>, <&cpu1_intc 9>, + <&cpu2_intc 11>, <&cpu2_intc 9>, + <&cpu3_intc 11>, <&cpu3_intc 9>; + interrupt-controller; + #address-cells = <0>; + #interrupt-cells = <2>; + riscv,ndev = <240>; + }; + + clint: timer@ffdc000000 { + compatible = "thead,th1520-clint", "thead,c900-clint"; + reg = <0xff 0xdc000000 0x0 0x00010000>; + interrupts-extended = <&cpu0_intc 3>, <&cpu0_intc 7>, + <&cpu1_intc 3>, <&cpu1_intc 7>, + <&cpu2_intc 3>, <&cpu2_intc 7>, + <&cpu3_intc 3>, <&cpu3_intc 7>; + }; + + uart0: serial@ffe7014000 { + compatible = "snps,dw-apb-uart"; + reg = <0xff 0xe7014000 0x0 0x100>; + interrupts = <36 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&uart_sclk>; + reg-shift = <2>; + reg-io-width = <4>; + status = "disabled"; + }; + + uart1: serial@ffe7f00000 { + compatible = "snps,dw-apb-uart"; + reg = <0xff 0xe7f00000 0x0 0x100>; + interrupts = <37 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&uart_sclk>; + reg-shift = <2>; + reg-io-width = <4>; + status = "disabled"; + }; + + uart3: serial@ffe7f04000 { + compatible = "snps,dw-apb-uart"; + reg = <0xff 0xe7f04000 0x0 0x100>; + interrupts = <39 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&uart_sclk>; + reg-shift = <2>; + reg-io-width = <4>; + status = "disabled"; + }; + + gpio2: gpio@ffe7f34000 { + compatible = "snps,dw-apb-gpio"; + reg = <0xff 0xe7f34000 0x0 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + + portc: gpio-controller@0 { + compatible = "snps,dw-apb-gpio-port"; + gpio-controller; + #gpio-cells = <2>; + ngpios = <32>; + reg = <0>; + interrupt-controller; + #interrupt-cells = <2>; + interrupts = <58 IRQ_TYPE_LEVEL_HIGH>; + }; + }; + + gpio3: gpio@ffe7f38000 { + compatible = "snps,dw-apb-gpio"; + reg = <0xff 0xe7f38000 0x0 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + + portd: gpio-controller@0 { + compatible = "snps,dw-apb-gpio-port"; + gpio-controller; + #gpio-cells = <2>; + ngpios = <32>; + reg = <0>; + interrupt-controller; + #interrupt-cells = <2>; + interrupts = <59 IRQ_TYPE_LEVEL_HIGH>; + }; + }; + + gpio0: gpio@ffec005000 { + compatible = "snps,dw-apb-gpio"; + reg = <0xff 0xec005000 0x0 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + + porta: gpio-controller@0 { + compatible = "snps,dw-apb-gpio-port"; + gpio-controller; + #gpio-cells = <2>; + ngpios = <32>; + reg = <0>; + interrupt-controller; + #interrupt-cells = <2>; + interrupts = <56 IRQ_TYPE_LEVEL_HIGH>; + }; + }; + + gpio1: gpio@ffec006000 { + compatible = "snps,dw-apb-gpio"; + reg = <0xff 0xec006000 0x0 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + + portb: gpio-controller@0 { + compatible = "snps,dw-apb-gpio-port"; + gpio-controller; + #gpio-cells = <2>; + ngpios = <32>; + reg = <0>; + interrupt-controller; + #interrupt-cells = <2>; + interrupts = <57 IRQ_TYPE_LEVEL_HIGH>; + }; + }; + + uart2: serial@ffec010000 { + compatible = "snps,dw-apb-uart"; + reg = <0xff 0xec010000 0x0 0x4000>; + interrupts = <38 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&uart_sclk>; + reg-shift = <2>; + reg-io-width = <4>; + status = "disabled"; + }; + + dmac0: dma-controller@ffefc00000 { + compatible = "snps,axi-dma-1.01a"; + reg = <0xff 0xefc00000 0x0 0x1000>; + interrupts = <27 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&apb_clk>, <&apb_clk>; + clock-names = "core-clk", "cfgr-clk"; + #dma-cells = <1>; + dma-channels = <4>; + snps,block-size = <65536 65536 65536 65536>; + snps,priority = <0 1 2 3>; + snps,dma-masters = <1>; + snps,data-width = <4>; + snps,axi-max-burst-len = <16>; + status = "disabled"; + }; + + timer0: timer@ffefc32000 { + compatible = "snps,dw-apb-timer"; + reg = <0xff 0xefc32000 0x0 0x14>; + clocks = <&apb_clk>; + clock-names = "timer"; + interrupts = <16 IRQ_TYPE_LEVEL_HIGH>; + status = "disabled"; + }; + + timer1: timer@ffefc32014 { + compatible = "snps,dw-apb-timer"; + reg = <0xff 0xefc32014 0x0 0x14>; + clocks = <&apb_clk>; + clock-names = "timer"; + interrupts = <17 IRQ_TYPE_LEVEL_HIGH>; + status = "disabled"; + }; + + timer2: timer@ffefc32028 { + compatible = "snps,dw-apb-timer"; + reg = <0xff 0xefc32028 0x0 0x14>; + clocks = <&apb_clk>; + clock-names = "timer"; + interrupts = <18 IRQ_TYPE_LEVEL_HIGH>; + status = "disabled"; + }; + + timer3: timer@ffefc3203c { + compatible = "snps,dw-apb-timer"; + reg = <0xff 0xefc3203c 0x0 0x14>; + clocks = <&apb_clk>; + clock-names = "timer"; + interrupts = <19 IRQ_TYPE_LEVEL_HIGH>; + status = "disabled"; + }; + + uart4: serial@fff7f08000 { + compatible = "snps,dw-apb-uart"; + reg = <0xff 0xf7f08000 0x0 0x4000>; + interrupts = <40 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&uart_sclk>; + reg-shift = <2>; + reg-io-width = <4>; + status = "disabled"; + }; + + uart5: serial@fff7f0c000 { + compatible = "snps,dw-apb-uart"; + reg = <0xff 0xf7f0c000 0x0 0x4000>; + interrupts = <41 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&uart_sclk>; + reg-shift = <2>; + reg-io-width = <4>; + status = "disabled"; + }; + + timer4: timer@ffffc33000 { + compatible = "snps,dw-apb-timer"; + reg = <0xff 0xffc33000 0x0 0x14>; + clocks = <&apb_clk>; + clock-names = "timer"; + interrupts = <20 IRQ_TYPE_LEVEL_HIGH>; + status = "disabled"; + }; + + timer5: timer@ffffc33014 { + compatible = "snps,dw-apb-timer"; + reg = <0xff 0xffc33014 0x0 0x14>; + clocks = <&apb_clk>; + clock-names = "timer"; + interrupts = <21 IRQ_TYPE_LEVEL_HIGH>; + status = "disabled"; + }; + + timer6: timer@ffffc33028 { + compatible = "snps,dw-apb-timer"; + reg = <0xff 0xffc33028 0x0 0x14>; + clocks = <&apb_clk>; + clock-names = "timer"; + interrupts = <22 IRQ_TYPE_LEVEL_HIGH>; + status = "disabled"; + }; + + timer7: timer@ffffc3303c { + compatible = "snps,dw-apb-timer"; + reg = <0xff 0xffc3303c 0x0 0x14>; + clocks = <&apb_clk>; + clock-names = "timer"; + interrupts = <23 IRQ_TYPE_LEVEL_HIGH>; + status = "disabled"; + }; + + ao_gpio0: gpio@fffff41000 { + compatible = "snps,dw-apb-gpio"; + reg = <0xff 0xfff41000 0x0 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + + porte: gpio-controller@0 { + compatible = "snps,dw-apb-gpio-port"; + gpio-controller; + #gpio-cells = <2>; + ngpios = <32>; + reg = <0>; + interrupt-controller; + #interrupt-cells = <2>; + interrupts = <76 IRQ_TYPE_LEVEL_HIGH>; + }; + }; + + ao_gpio1: gpio@fffff52000 { + compatible = "snps,dw-apb-gpio"; + reg = <0xff 0xfff52000 0x0 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + + portf: gpio-controller@0 { + compatible = "snps,dw-apb-gpio-port"; + gpio-controller; + #gpio-cells = <2>; + ngpios = <32>; + reg = <0>; + interrupt-controller; + #interrupt-cells = <2>; + interrupts = <55 IRQ_TYPE_LEVEL_HIGH>; + }; + }; + }; +}; diff --git a/arch/riscv/configs/defconfig b/arch/riscv/configs/defconfig index d98d6e90b2b820544549bf667aa53f48d874b376..0a0107460a5c0644963ef7d68f5ddbcd459b1eab 100644 --- a/arch/riscv/configs/defconfig +++ b/arch/riscv/configs/defconfig @@ -27,6 +27,7 @@ CONFIG_EXPERT=y CONFIG_PROFILING=y CONFIG_SOC_MICROCHIP_POLARFIRE=y CONFIG_ARCH_RENESAS=y +CONFIG_ARCH_THEAD=y CONFIG_SOC_SIFIVE=y CONFIG_SOC_STARFIVE=y CONFIG_ARCH_SUNXI=y @@ -37,6 +38,7 @@ CONFIG_PM=y CONFIG_CPU_IDLE=y CONFIG_VIRTUALIZATION=y CONFIG_KVM=m +CONFIG_ACPI=y CONFIG_JUMP_LABEL=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y diff --git a/arch/riscv/errata/thead/errata.c b/arch/riscv/errata/thead/errata.c index c259dc925ec1e796d7300bdddfe5bde704bffd7d..be84b14f01180a1db6b80846d5ce8be6a16a6b8c 100644 --- a/arch/riscv/errata/thead/errata.c +++ b/arch/riscv/errata/thead/errata.c @@ -45,8 +45,11 @@ static bool errata_probe_cmo(unsigned int stage, if (stage == RISCV_ALTERNATIVES_EARLY_BOOT) return false; - riscv_cbom_block_size = L1_CACHE_BYTES; - riscv_noncoherent_supported(); + if (stage == RISCV_ALTERNATIVES_BOOT) { + riscv_cbom_block_size = L1_CACHE_BYTES; + riscv_noncoherent_supported(); + } + return true; } diff --git a/arch/riscv/include/asm/acenv.h b/arch/riscv/include/asm/acenv.h new file mode 100644 index 0000000000000000000000000000000000000000..43ae2e32c779a96fd0fa66c51831929aa70cfd23 --- /dev/null +++ b/arch/riscv/include/asm/acenv.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * RISC-V specific ACPICA environments and implementation + */ + +#ifndef _ASM_ACENV_H +#define _ASM_ACENV_H + +/* This header is required unconditionally by the ACPI core */ + +#endif /* _ASM_ACENV_H */ diff --git a/arch/riscv/include/asm/acpi.h b/arch/riscv/include/asm/acpi.h new file mode 100644 index 0000000000000000000000000000000000000000..f71ce21ff684ff5f7d4c12d9bdefa671f1aa05d8 --- /dev/null +++ b/arch/riscv/include/asm/acpi.h @@ -0,0 +1,84 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (C) 2013-2014, Linaro Ltd. + * Author: Al Stone + * Author: Graeme Gregory + * Author: Hanjun Guo + * + * Copyright (C) 2021-2023, Ventana Micro Systems Inc. + * Author: Sunil V L + */ + +#ifndef _ASM_ACPI_H +#define _ASM_ACPI_H + +/* Basic configuration for ACPI */ +#ifdef CONFIG_ACPI + +typedef u64 phys_cpuid_t; +#define PHYS_CPUID_INVALID INVALID_HARTID + +/* ACPI table mapping after acpi_permanent_mmap is set */ +void *acpi_os_ioremap(acpi_physical_address phys, acpi_size size); +#define acpi_os_ioremap acpi_os_ioremap + +#define acpi_strict 1 /* No out-of-spec workarounds on RISC-V */ +extern int acpi_disabled; +extern int acpi_noirq; +extern int acpi_pci_disabled; + +static inline void disable_acpi(void) +{ + acpi_disabled = 1; + acpi_pci_disabled = 1; + acpi_noirq = 1; +} + +static inline void enable_acpi(void) +{ + acpi_disabled = 0; + acpi_pci_disabled = 0; + acpi_noirq = 0; +} + +/* + * The ACPI processor driver for ACPI core code needs this macro + * to find out whether this cpu was already mapped (mapping from CPU hardware + * ID to CPU logical ID) or not. + */ +#define cpu_physical_id(cpu) cpuid_to_hartid_map(cpu) + +/* + * Since MADT must provide at least one RINTC structure, the + * CPU will be always available in MADT on RISC-V. + */ +static inline bool acpi_has_cpu_in_madt(void) +{ + return true; +} + +static inline void arch_fix_phys_package_id(int num, u32 slot) { } + +void acpi_init_rintc_map(void); +struct acpi_madt_rintc *acpi_cpu_get_madt_rintc(int cpu); +u32 get_acpi_id_for_cpu(int cpu); +int acpi_get_riscv_isa(struct acpi_table_header *table, + unsigned int cpu, const char **isa); + +static inline int acpi_numa_get_nid(unsigned int cpu) { return NUMA_NO_NODE; } +#else +static inline void acpi_init_rintc_map(void) { } +static inline struct acpi_madt_rintc *acpi_cpu_get_madt_rintc(int cpu) +{ + return NULL; +} + +static inline int acpi_get_riscv_isa(struct acpi_table_header *table, + unsigned int cpu, const char **isa) +{ + return -EINVAL; +} + +#endif /* CONFIG_ACPI */ + +#endif /*_ASM_ACPI_H*/ diff --git a/arch/riscv/include/asm/asm-extable.h b/arch/riscv/include/asm/asm-extable.h index 14be0673f5b55c45ac2a2d48d46aa03975a738ad..00a96e7a966445175a687d481efa29f6862b3675 100644 --- a/arch/riscv/include/asm/asm-extable.h +++ b/arch/riscv/include/asm/asm-extable.h @@ -7,6 +7,8 @@ #define EX_TYPE_BPF 2 #define EX_TYPE_UACCESS_ERR_ZERO 3 +#ifdef CONFIG_MMU + #ifdef __ASSEMBLY__ #define __ASM_EXTABLE_RAW(insn, fixup, type, data) \ @@ -62,4 +64,8 @@ #endif /* __ASSEMBLY__ */ +#else /* CONFIG_MMU */ + #define _ASM_EXTABLE_UACCESS_ERR(insn, fixup, err) +#endif /* CONFIG_MMU */ + #endif /* __ASM_ASM_EXTABLE_H */ diff --git a/arch/riscv/include/asm/atomic.h b/arch/riscv/include/asm/atomic.h index bba472928b53932880f845625deff21683045fa8..f5dfef6c2153f189288d3a4f3fa7a1d5d1b5021b 100644 --- a/arch/riscv/include/asm/atomic.h +++ b/arch/riscv/include/asm/atomic.h @@ -238,78 +238,6 @@ static __always_inline s64 arch_atomic64_fetch_add_unless(atomic64_t *v, s64 a, #define arch_atomic64_fetch_add_unless arch_atomic64_fetch_add_unless #endif -/* - * atomic_{cmp,}xchg is required to have exactly the same ordering semantics as - * {cmp,}xchg and the operations that return, so they need a full barrier. - */ -#define ATOMIC_OP(c_t, prefix, size) \ -static __always_inline \ -c_t arch_atomic##prefix##_xchg_relaxed(atomic##prefix##_t *v, c_t n) \ -{ \ - return __xchg_relaxed(&(v->counter), n, size); \ -} \ -static __always_inline \ -c_t arch_atomic##prefix##_xchg_acquire(atomic##prefix##_t *v, c_t n) \ -{ \ - return __xchg_acquire(&(v->counter), n, size); \ -} \ -static __always_inline \ -c_t arch_atomic##prefix##_xchg_release(atomic##prefix##_t *v, c_t n) \ -{ \ - return __xchg_release(&(v->counter), n, size); \ -} \ -static __always_inline \ -c_t arch_atomic##prefix##_xchg(atomic##prefix##_t *v, c_t n) \ -{ \ - return __arch_xchg(&(v->counter), n, size); \ -} \ -static __always_inline \ -c_t arch_atomic##prefix##_cmpxchg_relaxed(atomic##prefix##_t *v, \ - c_t o, c_t n) \ -{ \ - return __cmpxchg_relaxed(&(v->counter), o, n, size); \ -} \ -static __always_inline \ -c_t arch_atomic##prefix##_cmpxchg_acquire(atomic##prefix##_t *v, \ - c_t o, c_t n) \ -{ \ - return __cmpxchg_acquire(&(v->counter), o, n, size); \ -} \ -static __always_inline \ -c_t arch_atomic##prefix##_cmpxchg_release(atomic##prefix##_t *v, \ - c_t o, c_t n) \ -{ \ - return __cmpxchg_release(&(v->counter), o, n, size); \ -} \ -static __always_inline \ -c_t arch_atomic##prefix##_cmpxchg(atomic##prefix##_t *v, c_t o, c_t n) \ -{ \ - return __cmpxchg(&(v->counter), o, n, size); \ -} - -#ifdef CONFIG_GENERIC_ATOMIC64 -#define ATOMIC_OPS() \ - ATOMIC_OP(int, , 4) -#else -#define ATOMIC_OPS() \ - ATOMIC_OP(int, , 4) \ - ATOMIC_OP(s64, 64, 8) -#endif - -ATOMIC_OPS() - -#define arch_atomic_xchg_relaxed arch_atomic_xchg_relaxed -#define arch_atomic_xchg_acquire arch_atomic_xchg_acquire -#define arch_atomic_xchg_release arch_atomic_xchg_release -#define arch_atomic_xchg arch_atomic_xchg -#define arch_atomic_cmpxchg_relaxed arch_atomic_cmpxchg_relaxed -#define arch_atomic_cmpxchg_acquire arch_atomic_cmpxchg_acquire -#define arch_atomic_cmpxchg_release arch_atomic_cmpxchg_release -#define arch_atomic_cmpxchg arch_atomic_cmpxchg - -#undef ATOMIC_OPS -#undef ATOMIC_OP - static __always_inline bool arch_atomic_inc_unless_negative(atomic_t *v) { int prev, rc; diff --git a/arch/riscv/include/asm/cpu.h b/arch/riscv/include/asm/cpu.h new file mode 100644 index 0000000000000000000000000000000000000000..28d45a6678ceb056d7d8612f0080fadd74031278 --- /dev/null +++ b/arch/riscv/include/asm/cpu.h @@ -0,0 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef _ASM_CPU_H +#define _ASM_CPU_H + +/* This header is required unconditionally by the ACPI core */ + +#endif /* _ASM_CPU_H */ diff --git a/arch/riscv/include/asm/cpufeature.h b/arch/riscv/include/asm/cpufeature.h index 808d5403f2ac1c31accf3c8f083664956e84748f..23fed53b88157842308fd8e67640b981dacde40b 100644 --- a/arch/riscv/include/asm/cpufeature.h +++ b/arch/riscv/include/asm/cpufeature.h @@ -6,6 +6,9 @@ #ifndef _ASM_CPUFEATURE_H #define _ASM_CPUFEATURE_H +#include +#include + /* * These are probed via a device_initcall(), via either the SBI or directly * from the corresponding CSRs. @@ -16,8 +19,15 @@ struct riscv_cpuinfo { unsigned long mimpid; }; +struct riscv_isainfo { + DECLARE_BITMAP(isa, RISCV_ISA_EXT_MAX); +}; + DECLARE_PER_CPU(struct riscv_cpuinfo, riscv_cpuinfo); DECLARE_PER_CPU(long, misaligned_access_speed); +/* Per-cpu ISA extensions. */ +extern struct riscv_isainfo hart_isa[NR_CPUS]; + #endif diff --git a/arch/riscv/include/asm/csr.h b/arch/riscv/include/asm/csr.h index b6acb7ed115f7ab0a7be2490ee4045cd02fd065f..7bac43a3176ed1d45aad779e2e625e0dfa17ecd5 100644 --- a/arch/riscv/include/asm/csr.h +++ b/arch/riscv/include/asm/csr.h @@ -24,16 +24,24 @@ #define SR_FS_CLEAN _AC(0x00004000, UL) #define SR_FS_DIRTY _AC(0x00006000, UL) +#define SR_VS _AC(0x00000600, UL) /* Vector Status */ +#define SR_VS_OFF _AC(0x00000000, UL) +#define SR_VS_INITIAL _AC(0x00000200, UL) +#define SR_VS_CLEAN _AC(0x00000400, UL) +#define SR_VS_DIRTY _AC(0x00000600, UL) + #define SR_XS _AC(0x00018000, UL) /* Extension Status */ #define SR_XS_OFF _AC(0x00000000, UL) #define SR_XS_INITIAL _AC(0x00008000, UL) #define SR_XS_CLEAN _AC(0x00010000, UL) #define SR_XS_DIRTY _AC(0x00018000, UL) +#define SR_FS_VS (SR_FS | SR_VS) /* Vector and Floating-Point Unit */ + #ifndef CONFIG_64BIT -#define SR_SD _AC(0x80000000, UL) /* FS/XS dirty */ +#define SR_SD _AC(0x80000000, UL) /* FS/VS/XS dirty */ #else -#define SR_SD _AC(0x8000000000000000, UL) /* FS/XS dirty */ +#define SR_SD _AC(0x8000000000000000, UL) /* FS/VS/XS dirty */ #endif #ifdef CONFIG_64BIT @@ -82,7 +90,9 @@ #define EXC_INST_ACCESS 1 #define EXC_INST_ILLEGAL 2 #define EXC_BREAKPOINT 3 +#define EXC_LOAD_MISALIGNED 4 #define EXC_LOAD_ACCESS 5 +#define EXC_STORE_MISALIGNED 6 #define EXC_STORE_ACCESS 7 #define EXC_SYSCALL 8 #define EXC_HYPERVISOR_SYSCALL 9 @@ -375,6 +385,12 @@ #define CSR_MVIPH 0x319 #define CSR_MIPH 0x354 +#define CSR_VSTART 0x8 +#define CSR_VCSR 0xf +#define CSR_VL 0xc20 +#define CSR_VTYPE 0xc21 +#define CSR_VLENB 0xc22 + #ifdef CONFIG_RISCV_M_MODE # define CSR_STATUS CSR_MSTATUS # define CSR_IE CSR_MIE diff --git a/arch/riscv/include/asm/elf.h b/arch/riscv/include/asm/elf.h index 30e7d24559602ec4eb4bcf9e2885b41bc92b0e46..c24280774caf7da63674a21b767a64086b9fb2dc 100644 --- a/arch/riscv/include/asm/elf.h +++ b/arch/riscv/include/asm/elf.h @@ -66,7 +66,7 @@ extern bool compat_elf_check_arch(Elf32_Ehdr *hdr); * via a bitmap that coorespends to each single-letter ISA extension. This is * essentially defunct, but will remain for compatibility with userspace. */ -#define ELF_HWCAP (elf_hwcap & ((1UL << RISCV_ISA_EXT_BASE) - 1)) +#define ELF_HWCAP riscv_get_elf_hwcap() extern unsigned long elf_hwcap; /* @@ -105,6 +105,15 @@ do { \ get_cache_size(3, CACHE_TYPE_UNIFIED)); \ NEW_AUX_ENT(AT_L3_CACHEGEOMETRY, \ get_cache_geometry(3, CACHE_TYPE_UNIFIED)); \ + /* \ + * Should always be nonzero unless there's a kernel bug. \ + * If we haven't determined a sensible value to give to \ + * userspace, omit the entry: \ + */ \ + if (likely(signal_minsigstksz)) \ + NEW_AUX_ENT(AT_MINSIGSTKSZ, signal_minsigstksz); \ + else \ + NEW_AUX_ENT(AT_IGNORE, 0); \ } while (0) #define ARCH_HAS_SETUP_ADDITIONAL_PAGES struct linux_binprm; diff --git a/arch/riscv/include/asm/extable.h b/arch/riscv/include/asm/extable.h index 512012d193dca68c42afbe703ca37e5410e7277e..3eb5c1f7bf34611336323a9600cc665bde410b3b 100644 --- a/arch/riscv/include/asm/extable.h +++ b/arch/riscv/include/asm/extable.h @@ -32,7 +32,11 @@ do { \ (b)->data = (tmp).data; \ } while (0) +#ifdef CONFIG_MMU bool fixup_exception(struct pt_regs *regs); +#else +static inline bool fixup_exception(struct pt_regs *regs) { return false; } +#endif #if defined(CONFIG_BPF_JIT) && defined(CONFIG_ARCH_RV64I) bool ex_handler_bpf(const struct exception_table_entry *ex, struct pt_regs *regs); diff --git a/arch/riscv/include/asm/ftrace.h b/arch/riscv/include/asm/ftrace.h index d47d87c2d7e3d0f1393688527f3c72d589fdb907..740a979171e565173036191f95c424662c84deec 100644 --- a/arch/riscv/include/asm/ftrace.h +++ b/arch/riscv/include/asm/ftrace.h @@ -111,4 +111,25 @@ int ftrace_init_nop(struct module *mod, struct dyn_ftrace *rec); #endif /* CONFIG_DYNAMIC_FTRACE */ +#ifndef __ASSEMBLY__ +#ifdef CONFIG_FUNCTION_GRAPH_TRACER +struct fgraph_ret_regs { + unsigned long a1; + unsigned long a0; + unsigned long s0; + unsigned long ra; +}; + +static inline unsigned long fgraph_ret_regs_return_value(struct fgraph_ret_regs *ret_regs) +{ + return ret_regs->a0; +} + +static inline unsigned long fgraph_ret_regs_frame_pointer(struct fgraph_ret_regs *ret_regs) +{ + return ret_regs->s0; +} +#endif /* ifdef CONFIG_FUNCTION_GRAPH_TRACER */ +#endif + #endif /* _ASM_RISCV_FTRACE_H */ diff --git a/arch/riscv/include/asm/hwcap.h b/arch/riscv/include/asm/hwcap.h index e0c40a4c63d51d4591c77eeda2e0dda070187d16..f041bfa7f6a0d8c6f5c7c5761b4336f44ad98a6b 100644 --- a/arch/riscv/include/asm/hwcap.h +++ b/arch/riscv/include/asm/hwcap.h @@ -22,6 +22,7 @@ #define RISCV_ISA_EXT_m ('m' - 'a') #define RISCV_ISA_EXT_s ('s' - 'a') #define RISCV_ISA_EXT_u ('u' - 'a') +#define RISCV_ISA_EXT_v ('v' - 'a') /* * These macros represent the logical IDs of each multi-letter RISC-V ISA @@ -46,6 +47,12 @@ #define RISCV_ISA_EXT_ZICBOZ 34 #define RISCV_ISA_EXT_SMAIA 35 #define RISCV_ISA_EXT_SSAIA 36 +#define RISCV_ISA_EXT_ZBA 37 +#define RISCV_ISA_EXT_ZBS 38 +#define RISCV_ISA_EXT_ZICNTR 39 +#define RISCV_ISA_EXT_ZICSR 40 +#define RISCV_ISA_EXT_ZIFENCEI 41 +#define RISCV_ISA_EXT_ZIHPM 42 #define RISCV_ISA_EXT_MAX 64 #define RISCV_ISA_EXT_NAME_LEN_MAX 32 @@ -60,6 +67,8 @@ #include +unsigned long riscv_get_elf_hwcap(void); + struct riscv_isa_ext_data { /* Name of the extension displayed to userspace via /proc/cpuinfo */ char uprop[RISCV_ISA_EXT_NAME_LEN_MAX]; diff --git a/arch/riscv/include/asm/insn.h b/arch/riscv/include/asm/insn.h index 8d5c84f2d5ef7877c9fb3fed07bd24ba91b7bf28..4e1505cef8aa40fd543c4c2f00bc357a6cb5c4be 100644 --- a/arch/riscv/include/asm/insn.h +++ b/arch/riscv/include/asm/insn.h @@ -137,6 +137,26 @@ #define RVG_OPCODE_JALR 0x67 #define RVG_OPCODE_JAL 0x6f #define RVG_OPCODE_SYSTEM 0x73 +#define RVG_SYSTEM_CSR_OFF 20 +#define RVG_SYSTEM_CSR_MASK GENMASK(12, 0) + +/* parts of opcode for RVF, RVD and RVQ */ +#define RVFDQ_FL_FS_WIDTH_OFF 12 +#define RVFDQ_FL_FS_WIDTH_MASK GENMASK(3, 0) +#define RVFDQ_FL_FS_WIDTH_W 2 +#define RVFDQ_FL_FS_WIDTH_D 3 +#define RVFDQ_LS_FS_WIDTH_Q 4 +#define RVFDQ_OPCODE_FL 0x07 +#define RVFDQ_OPCODE_FS 0x27 + +/* parts of opcode for RVV */ +#define RVV_OPCODE_VECTOR 0x57 +#define RVV_VL_VS_WIDTH_8 0 +#define RVV_VL_VS_WIDTH_16 5 +#define RVV_VL_VS_WIDTH_32 6 +#define RVV_VL_VS_WIDTH_64 7 +#define RVV_OPCODE_VL RVFDQ_OPCODE_FL +#define RVV_OPCODE_VS RVFDQ_OPCODE_FS /* parts of opcode for RVC*/ #define RVC_OPCODE_C0 0x0 @@ -304,6 +324,15 @@ static __always_inline bool riscv_insn_is_branch(u32 code) (RVC_X(x_, RVC_B_IMM_7_6_OPOFF, RVC_B_IMM_7_6_MASK) << RVC_B_IMM_7_6_OFF) | \ (RVC_IMM_SIGN(x_) << RVC_B_IMM_SIGN_OFF); }) +#define RVG_EXTRACT_SYSTEM_CSR(x) \ + ({typeof(x) x_ = (x); RV_X(x_, RVG_SYSTEM_CSR_OFF, RVG_SYSTEM_CSR_MASK); }) + +#define RVFDQ_EXTRACT_FL_FS_WIDTH(x) \ + ({typeof(x) x_ = (x); RV_X(x_, RVFDQ_FL_FS_WIDTH_OFF, \ + RVFDQ_FL_FS_WIDTH_MASK); }) + +#define RVV_EXRACT_VL_VS_WIDTH(x) RVFDQ_EXTRACT_FL_FS_WIDTH(x) + /* * Get the immediate from a J-type instruction. * diff --git a/arch/riscv/include/asm/irq.h b/arch/riscv/include/asm/irq.h index 43b9ebfbd94364f229f139ef0a0ed5c63c89dfc4..8e10a94430a2c2bc6228ac7141f16ba832b474c0 100644 --- a/arch/riscv/include/asm/irq.h +++ b/arch/riscv/include/asm/irq.h @@ -16,6 +16,4 @@ void riscv_set_intc_hwnode_fn(struct fwnode_handle *(*fn)(void)); struct fwnode_handle *riscv_get_intc_hwnode(void); -extern void __init init_IRQ(void); - #endif /* _ASM_RISCV_IRQ_H */ diff --git a/arch/riscv/include/asm/irq_stack.h b/arch/riscv/include/asm/irq_stack.h new file mode 100644 index 0000000000000000000000000000000000000000..e4042d297580080c0c3dfffed0dd711f5f371ca1 --- /dev/null +++ b/arch/riscv/include/asm/irq_stack.h @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef _ASM_RISCV_IRQ_STACK_H +#define _ASM_RISCV_IRQ_STACK_H + +#include +#include +#include +#include +#include +#include + +DECLARE_PER_CPU(ulong *, irq_stack_ptr); + +#ifdef CONFIG_VMAP_STACK +/* + * To ensure that VMAP'd stack overflow detection works correctly, all VMAP'd + * stacks need to have the same alignment. + */ +static inline unsigned long *arch_alloc_vmap_stack(size_t stack_size, int node) +{ + void *p; + + p = __vmalloc_node(stack_size, THREAD_ALIGN, THREADINFO_GFP, node, + __builtin_return_address(0)); + return kasan_reset_tag(p); +} +#endif /* CONFIG_VMAP_STACK */ + +#endif /* _ASM_RISCV_IRQ_STACK_H */ diff --git a/arch/riscv/include/asm/kvm_aia.h b/arch/riscv/include/asm/kvm_aia.h index 1de0717112e5e7716a142c5d8c692fff968e9f94..1f37b600ca47925ee45d67e5b4822ff358843119 100644 --- a/arch/riscv/include/asm/kvm_aia.h +++ b/arch/riscv/include/asm/kvm_aia.h @@ -20,6 +20,33 @@ struct kvm_aia { /* In-kernel irqchip initialized */ bool initialized; + + /* Virtualization mode (Emulation, HW Accelerated, or Auto) */ + u32 mode; + + /* Number of MSIs */ + u32 nr_ids; + + /* Number of wired IRQs */ + u32 nr_sources; + + /* Number of group bits in IMSIC address */ + u32 nr_group_bits; + + /* Position of group bits in IMSIC address */ + u32 nr_group_shift; + + /* Number of hart bits in IMSIC address */ + u32 nr_hart_bits; + + /* Number of guest bits in IMSIC address */ + u32 nr_guest_bits; + + /* Guest physical address of APLIC */ + gpa_t aplic_addr; + + /* Internal state of APLIC */ + void *aplic_state; }; struct kvm_vcpu_aia_csr { @@ -38,25 +65,53 @@ struct kvm_vcpu_aia { /* CPU AIA CSR context upon Guest VCPU reset */ struct kvm_vcpu_aia_csr guest_reset_csr; + + /* Guest physical address of IMSIC for this VCPU */ + gpa_t imsic_addr; + + /* HART index of IMSIC extacted from guest physical address */ + u32 hart_index; + + /* Internal state of IMSIC for this VCPU */ + void *imsic_state; }; +#define KVM_RISCV_AIA_UNDEF_ADDR (-1) + #define kvm_riscv_aia_initialized(k) ((k)->arch.aia.initialized) #define irqchip_in_kernel(k) ((k)->arch.aia.in_kernel) +extern unsigned int kvm_riscv_aia_nr_hgei; +extern unsigned int kvm_riscv_aia_max_ids; DECLARE_STATIC_KEY_FALSE(kvm_riscv_aia_available); #define kvm_riscv_aia_available() \ static_branch_unlikely(&kvm_riscv_aia_available) +extern struct kvm_device_ops kvm_riscv_aia_device_ops; + +void kvm_riscv_vcpu_aia_imsic_release(struct kvm_vcpu *vcpu); +int kvm_riscv_vcpu_aia_imsic_update(struct kvm_vcpu *vcpu); + #define KVM_RISCV_AIA_IMSIC_TOPEI (ISELECT_MASK + 1) -static inline int kvm_riscv_vcpu_aia_imsic_rmw(struct kvm_vcpu *vcpu, - unsigned long isel, - unsigned long *val, - unsigned long new_val, - unsigned long wr_mask) -{ - return 0; -} +int kvm_riscv_vcpu_aia_imsic_rmw(struct kvm_vcpu *vcpu, unsigned long isel, + unsigned long *val, unsigned long new_val, + unsigned long wr_mask); +int kvm_riscv_aia_imsic_rw_attr(struct kvm *kvm, unsigned long type, + bool write, unsigned long *val); +int kvm_riscv_aia_imsic_has_attr(struct kvm *kvm, unsigned long type); +void kvm_riscv_vcpu_aia_imsic_reset(struct kvm_vcpu *vcpu); +int kvm_riscv_vcpu_aia_imsic_inject(struct kvm_vcpu *vcpu, + u32 guest_index, u32 offset, u32 iid); +int kvm_riscv_vcpu_aia_imsic_init(struct kvm_vcpu *vcpu); +void kvm_riscv_vcpu_aia_imsic_cleanup(struct kvm_vcpu *vcpu); + +int kvm_riscv_aia_aplic_set_attr(struct kvm *kvm, unsigned long type, u32 v); +int kvm_riscv_aia_aplic_get_attr(struct kvm *kvm, unsigned long type, u32 *v); +int kvm_riscv_aia_aplic_has_attr(struct kvm *kvm, unsigned long type); +int kvm_riscv_aia_aplic_inject(struct kvm *kvm, u32 source, bool level); +int kvm_riscv_aia_aplic_init(struct kvm *kvm); +void kvm_riscv_aia_aplic_cleanup(struct kvm *kvm); #ifdef CONFIG_32BIT void kvm_riscv_vcpu_aia_flush_interrupts(struct kvm_vcpu *vcpu); @@ -93,31 +148,23 @@ int kvm_riscv_vcpu_aia_rmw_ireg(struct kvm_vcpu *vcpu, unsigned int csr_num, { .base = CSR_SIREG, .count = 1, .func = kvm_riscv_vcpu_aia_rmw_ireg }, \ { .base = CSR_STOPEI, .count = 1, .func = kvm_riscv_vcpu_aia_rmw_topei }, -static inline int kvm_riscv_vcpu_aia_update(struct kvm_vcpu *vcpu) -{ - return 1; -} - -static inline void kvm_riscv_vcpu_aia_reset(struct kvm_vcpu *vcpu) -{ -} - -static inline int kvm_riscv_vcpu_aia_init(struct kvm_vcpu *vcpu) -{ - return 0; -} +int kvm_riscv_vcpu_aia_update(struct kvm_vcpu *vcpu); +void kvm_riscv_vcpu_aia_reset(struct kvm_vcpu *vcpu); +int kvm_riscv_vcpu_aia_init(struct kvm_vcpu *vcpu); +void kvm_riscv_vcpu_aia_deinit(struct kvm_vcpu *vcpu); -static inline void kvm_riscv_vcpu_aia_deinit(struct kvm_vcpu *vcpu) -{ -} +int kvm_riscv_aia_inject_msi_by_id(struct kvm *kvm, u32 hart_index, + u32 guest_index, u32 iid); +int kvm_riscv_aia_inject_msi(struct kvm *kvm, struct kvm_msi *msi); +int kvm_riscv_aia_inject_irq(struct kvm *kvm, unsigned int irq, bool level); -static inline void kvm_riscv_aia_init_vm(struct kvm *kvm) -{ -} +void kvm_riscv_aia_init_vm(struct kvm *kvm); +void kvm_riscv_aia_destroy_vm(struct kvm *kvm); -static inline void kvm_riscv_aia_destroy_vm(struct kvm *kvm) -{ -} +int kvm_riscv_aia_alloc_hgei(int cpu, struct kvm_vcpu *owner, + void __iomem **hgei_va, phys_addr_t *hgei_pa); +void kvm_riscv_aia_free_hgei(int cpu, int hgei); +void kvm_riscv_aia_wakeon_hgei(struct kvm_vcpu *owner, bool enable); void kvm_riscv_aia_enable(void); void kvm_riscv_aia_disable(void); diff --git a/arch/riscv/include/asm/kvm_aia_aplic.h b/arch/riscv/include/asm/kvm_aia_aplic.h new file mode 100644 index 0000000000000000000000000000000000000000..6dd1a4809ec181bff5373fd7d651090729ea7a41 --- /dev/null +++ b/arch/riscv/include/asm/kvm_aia_aplic.h @@ -0,0 +1,58 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (C) 2021 Western Digital Corporation or its affiliates. + * Copyright (C) 2022 Ventana Micro Systems Inc. + */ +#ifndef __KVM_RISCV_AIA_IMSIC_H +#define __KVM_RISCV_AIA_IMSIC_H + +#include + +#define APLIC_MAX_IDC BIT(14) +#define APLIC_MAX_SOURCE 1024 + +#define APLIC_DOMAINCFG 0x0000 +#define APLIC_DOMAINCFG_RDONLY 0x80000000 +#define APLIC_DOMAINCFG_IE BIT(8) +#define APLIC_DOMAINCFG_DM BIT(2) +#define APLIC_DOMAINCFG_BE BIT(0) + +#define APLIC_SOURCECFG_BASE 0x0004 +#define APLIC_SOURCECFG_D BIT(10) +#define APLIC_SOURCECFG_CHILDIDX_MASK 0x000003ff +#define APLIC_SOURCECFG_SM_MASK 0x00000007 +#define APLIC_SOURCECFG_SM_INACTIVE 0x0 +#define APLIC_SOURCECFG_SM_DETACH 0x1 +#define APLIC_SOURCECFG_SM_EDGE_RISE 0x4 +#define APLIC_SOURCECFG_SM_EDGE_FALL 0x5 +#define APLIC_SOURCECFG_SM_LEVEL_HIGH 0x6 +#define APLIC_SOURCECFG_SM_LEVEL_LOW 0x7 + +#define APLIC_IRQBITS_PER_REG 32 + +#define APLIC_SETIP_BASE 0x1c00 +#define APLIC_SETIPNUM 0x1cdc + +#define APLIC_CLRIP_BASE 0x1d00 +#define APLIC_CLRIPNUM 0x1ddc + +#define APLIC_SETIE_BASE 0x1e00 +#define APLIC_SETIENUM 0x1edc + +#define APLIC_CLRIE_BASE 0x1f00 +#define APLIC_CLRIENUM 0x1fdc + +#define APLIC_SETIPNUM_LE 0x2000 +#define APLIC_SETIPNUM_BE 0x2004 + +#define APLIC_GENMSI 0x3000 + +#define APLIC_TARGET_BASE 0x3004 +#define APLIC_TARGET_HART_IDX_SHIFT 18 +#define APLIC_TARGET_HART_IDX_MASK 0x3fff +#define APLIC_TARGET_GUEST_IDX_SHIFT 12 +#define APLIC_TARGET_GUEST_IDX_MASK 0x3f +#define APLIC_TARGET_IPRIO_MASK 0xff +#define APLIC_TARGET_EIID_MASK 0x7ff + +#endif diff --git a/arch/riscv/include/asm/kvm_aia_imsic.h b/arch/riscv/include/asm/kvm_aia_imsic.h new file mode 100644 index 0000000000000000000000000000000000000000..da5881d2bde09f928351f7fe9b964dc7b220739a --- /dev/null +++ b/arch/riscv/include/asm/kvm_aia_imsic.h @@ -0,0 +1,38 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (C) 2021 Western Digital Corporation or its affiliates. + * Copyright (C) 2022 Ventana Micro Systems Inc. + */ +#ifndef __KVM_RISCV_AIA_IMSIC_H +#define __KVM_RISCV_AIA_IMSIC_H + +#include +#include + +#define IMSIC_MMIO_PAGE_SHIFT 12 +#define IMSIC_MMIO_PAGE_SZ (1UL << IMSIC_MMIO_PAGE_SHIFT) +#define IMSIC_MMIO_PAGE_LE 0x00 +#define IMSIC_MMIO_PAGE_BE 0x04 + +#define IMSIC_MIN_ID 63 +#define IMSIC_MAX_ID 2048 + +#define IMSIC_EIDELIVERY 0x70 + +#define IMSIC_EITHRESHOLD 0x72 + +#define IMSIC_EIP0 0x80 +#define IMSIC_EIP63 0xbf +#define IMSIC_EIPx_BITS 32 + +#define IMSIC_EIE0 0xc0 +#define IMSIC_EIE63 0xff +#define IMSIC_EIEx_BITS 32 + +#define IMSIC_FIRST IMSIC_EIDELIVERY +#define IMSIC_LAST IMSIC_EIE63 + +#define IMSIC_MMIO_SETIPNUM_LE 0x00 +#define IMSIC_MMIO_SETIPNUM_BE 0x04 + +#endif diff --git a/arch/riscv/include/asm/kvm_host.h b/arch/riscv/include/asm/kvm_host.h index ee0acccb1d3bab18ad5c611718c069dfb4ff58a3..2d8ee53b66c7b1377bead9b5b02226fcb0e533eb 100644 --- a/arch/riscv/include/asm/kvm_host.h +++ b/arch/riscv/include/asm/kvm_host.h @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -27,6 +28,8 @@ #define KVM_VCPU_MAX_FEATURES 0 +#define KVM_IRQCHIP_NUM_PINS 1024 + #define KVM_REQ_SLEEP \ KVM_ARCH_REQ_FLAGS(0, KVM_REQUEST_WAIT | KVM_REQUEST_NO_WAKEUP) #define KVM_REQ_VCPU_RESET KVM_ARCH_REQ(1) @@ -145,6 +148,7 @@ struct kvm_cpu_context { unsigned long sstatus; unsigned long hstatus; union __riscv_fp_state fp; + struct __riscv_v_ext_state vector; }; struct kvm_vcpu_csr { @@ -318,6 +322,8 @@ int kvm_riscv_gstage_vmid_init(struct kvm *kvm); bool kvm_riscv_gstage_vmid_ver_changed(struct kvm_vmid *vmid); void kvm_riscv_gstage_vmid_update(struct kvm_vcpu *vcpu); +int kvm_riscv_setup_default_irq_routing(struct kvm *kvm, u32 lines); + void __kvm_riscv_unpriv_trap(void); unsigned long kvm_riscv_vcpu_unpriv_read(struct kvm_vcpu *vcpu, diff --git a/arch/riscv/include/asm/kvm_vcpu_sbi.h b/arch/riscv/include/asm/kvm_vcpu_sbi.h index 4278125a38a52750e04f5030ac173df1cb00922b..cdcf0ff07be7b54d947d1a6afc53798066afd6a2 100644 --- a/arch/riscv/include/asm/kvm_vcpu_sbi.h +++ b/arch/riscv/include/asm/kvm_vcpu_sbi.h @@ -14,9 +14,15 @@ #define KVM_SBI_VERSION_MAJOR 1 #define KVM_SBI_VERSION_MINOR 0 +enum kvm_riscv_sbi_ext_status { + KVM_RISCV_SBI_EXT_UNINITIALIZED, + KVM_RISCV_SBI_EXT_AVAILABLE, + KVM_RISCV_SBI_EXT_UNAVAILABLE, +}; + struct kvm_vcpu_sbi_context { int return_handled; - bool extension_disabled[KVM_RISCV_SBI_EXT_MAX]; + enum kvm_riscv_sbi_ext_status ext_status[KVM_RISCV_SBI_EXT_MAX]; }; struct kvm_vcpu_sbi_return { @@ -66,4 +72,7 @@ extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_hsm; extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_experimental; extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_vendor; +#ifdef CONFIG_RISCV_PMU_SBI +extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_pmu; +#endif #endif /* __RISCV_KVM_VCPU_SBI_H__ */ diff --git a/arch/riscv/include/asm/kvm_vcpu_vector.h b/arch/riscv/include/asm/kvm_vcpu_vector.h new file mode 100644 index 0000000000000000000000000000000000000000..ff994fdd6d0d1cc7c01079847dcd8242cb1790a5 --- /dev/null +++ b/arch/riscv/include/asm/kvm_vcpu_vector.h @@ -0,0 +1,82 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (C) 2022 SiFive + * + * Authors: + * Vincent Chen + * Greentime Hu + */ + +#ifndef __KVM_VCPU_RISCV_VECTOR_H +#define __KVM_VCPU_RISCV_VECTOR_H + +#include + +#ifdef CONFIG_RISCV_ISA_V +#include +#include + +static __always_inline void __kvm_riscv_vector_save(struct kvm_cpu_context *context) +{ + __riscv_v_vstate_save(&context->vector, context->vector.datap); +} + +static __always_inline void __kvm_riscv_vector_restore(struct kvm_cpu_context *context) +{ + __riscv_v_vstate_restore(&context->vector, context->vector.datap); +} + +void kvm_riscv_vcpu_vector_reset(struct kvm_vcpu *vcpu); +void kvm_riscv_vcpu_guest_vector_save(struct kvm_cpu_context *cntx, + unsigned long *isa); +void kvm_riscv_vcpu_guest_vector_restore(struct kvm_cpu_context *cntx, + unsigned long *isa); +void kvm_riscv_vcpu_host_vector_save(struct kvm_cpu_context *cntx); +void kvm_riscv_vcpu_host_vector_restore(struct kvm_cpu_context *cntx); +int kvm_riscv_vcpu_alloc_vector_context(struct kvm_vcpu *vcpu, + struct kvm_cpu_context *cntx); +void kvm_riscv_vcpu_free_vector_context(struct kvm_vcpu *vcpu); +#else + +struct kvm_cpu_context; + +static inline void kvm_riscv_vcpu_vector_reset(struct kvm_vcpu *vcpu) +{ +} + +static inline void kvm_riscv_vcpu_guest_vector_save(struct kvm_cpu_context *cntx, + unsigned long *isa) +{ +} + +static inline void kvm_riscv_vcpu_guest_vector_restore(struct kvm_cpu_context *cntx, + unsigned long *isa) +{ +} + +static inline void kvm_riscv_vcpu_host_vector_save(struct kvm_cpu_context *cntx) +{ +} + +static inline void kvm_riscv_vcpu_host_vector_restore(struct kvm_cpu_context *cntx) +{ +} + +static inline int kvm_riscv_vcpu_alloc_vector_context(struct kvm_vcpu *vcpu, + struct kvm_cpu_context *cntx) +{ + return 0; +} + +static inline void kvm_riscv_vcpu_free_vector_context(struct kvm_vcpu *vcpu) +{ +} +#endif + +int kvm_riscv_vcpu_get_reg_vector(struct kvm_vcpu *vcpu, + const struct kvm_one_reg *reg, + unsigned long rtype); +int kvm_riscv_vcpu_set_reg_vector(struct kvm_vcpu *vcpu, + const struct kvm_one_reg *reg, + unsigned long rtype); +#endif diff --git a/arch/riscv/include/asm/processor.h b/arch/riscv/include/asm/processor.h index 94a0590c69710b54e2e1f7258bd6692858ce5f90..c950a8d9edef8cb562b4d783360c3cbdf1cb5bf6 100644 --- a/arch/riscv/include/asm/processor.h +++ b/arch/riscv/include/asm/processor.h @@ -7,6 +7,7 @@ #define _ASM_RISCV_PROCESSOR_H #include +#include #include @@ -39,6 +40,8 @@ struct thread_struct { unsigned long s[12]; /* s[0]: frame pointer */ struct __riscv_d_ext_state fstate; unsigned long bad_cause; + unsigned long vstate_ctrl; + struct __riscv_v_ext_state vstate; }; /* Whitelist the fstate from the task_struct for hardened usercopy */ @@ -75,11 +78,22 @@ static inline void wait_for_interrupt(void) struct device_node; int riscv_of_processor_hartid(struct device_node *node, unsigned long *hartid); +int riscv_early_of_processor_hartid(struct device_node *node, unsigned long *hartid); int riscv_of_parent_hartid(struct device_node *node, unsigned long *hartid); extern void riscv_fill_hwcap(void); extern int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src); +extern unsigned long signal_minsigstksz __ro_after_init; + +#ifdef CONFIG_RISCV_ISA_V +/* Userspace interface for PR_RISCV_V_{SET,GET}_VS prctl()s: */ +#define RISCV_V_SET_CONTROL(arg) riscv_v_vstate_ctrl_set_current(arg) +#define RISCV_V_GET_CONTROL() riscv_v_vstate_ctrl_get_current() +extern long riscv_v_vstate_ctrl_set_current(unsigned long arg); +extern long riscv_v_vstate_ctrl_get_current(void); +#endif /* CONFIG_RISCV_ISA_V */ + #endif /* __ASSEMBLY__ */ #endif /* _ASM_RISCV_PROCESSOR_H */ diff --git a/arch/riscv/include/asm/smp.h b/arch/riscv/include/asm/smp.h index c4b77017ec5869fd507d7e366b44e22ef376abe8..0d555847cde64aa1a78bb439292af9de23378b05 100644 --- a/arch/riscv/include/asm/smp.h +++ b/arch/riscv/include/asm/smp.h @@ -70,7 +70,7 @@ asmlinkage void smp_callin(void); #if defined CONFIG_HOTPLUG_CPU int __cpu_disable(void); -void __cpu_die(unsigned int cpu); +static inline void __cpu_die(unsigned int cpu) { } #endif /* CONFIG_HOTPLUG_CPU */ #else diff --git a/arch/riscv/include/asm/switch_to.h b/arch/riscv/include/asm/switch_to.h index 60f8ca01d36e4514f29ee23594f92cb29ce079c6..a727be723c5610f9ce2bc42de6f4dd2987c7536c 100644 --- a/arch/riscv/include/asm/switch_to.h +++ b/arch/riscv/include/asm/switch_to.h @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -46,7 +47,7 @@ static inline void fstate_restore(struct task_struct *task, } } -static inline void __switch_to_aux(struct task_struct *prev, +static inline void __switch_to_fpu(struct task_struct *prev, struct task_struct *next) { struct pt_regs *regs; @@ -66,7 +67,7 @@ static __always_inline bool has_fpu(void) static __always_inline bool has_fpu(void) { return false; } #define fstate_save(task, regs) do { } while (0) #define fstate_restore(task, regs) do { } while (0) -#define __switch_to_aux(__prev, __next) do { } while (0) +#define __switch_to_fpu(__prev, __next) do { } while (0) #endif extern struct task_struct *__switch_to(struct task_struct *, @@ -77,7 +78,9 @@ do { \ struct task_struct *__prev = (prev); \ struct task_struct *__next = (next); \ if (has_fpu()) \ - __switch_to_aux(__prev, __next); \ + __switch_to_fpu(__prev, __next); \ + if (has_vector()) \ + __switch_to_vector(__prev, __next); \ ((last) = __switch_to(__prev, __next)); \ } while (0) diff --git a/arch/riscv/include/asm/thread_info.h b/arch/riscv/include/asm/thread_info.h index e0d202134b44f050cdd7abef3db5e29eade4d5c0..1833beb00489c317c43a263afc926099a271cfed 100644 --- a/arch/riscv/include/asm/thread_info.h +++ b/arch/riscv/include/asm/thread_info.h @@ -11,18 +11,8 @@ #include #include -#ifdef CONFIG_KASAN -#define KASAN_STACK_ORDER 1 -#else -#define KASAN_STACK_ORDER 0 -#endif - /* thread information allocation */ -#ifdef CONFIG_64BIT -#define THREAD_SIZE_ORDER (2 + KASAN_STACK_ORDER) -#else -#define THREAD_SIZE_ORDER (1 + KASAN_STACK_ORDER) -#endif +#define THREAD_SIZE_ORDER CONFIG_THREAD_SIZE_ORDER #define THREAD_SIZE (PAGE_SIZE << THREAD_SIZE_ORDER) /* @@ -40,6 +30,8 @@ #define OVERFLOW_STACK_SIZE SZ_4K #define SHADOW_OVERFLOW_STACK_SIZE (1024) +#define IRQ_STACK_SIZE THREAD_SIZE + #ifndef __ASSEMBLY__ extern long shadow_stack[SHADOW_OVERFLOW_STACK_SIZE / sizeof(long)]; @@ -81,6 +73,9 @@ struct thread_info { .preempt_count = INIT_PREEMPT_COUNT, \ } +void arch_release_task_struct(struct task_struct *tsk); +int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src); + #endif /* !__ASSEMBLY__ */ /* diff --git a/arch/riscv/include/asm/timex.h b/arch/riscv/include/asm/timex.h index d6a7428f6248d4251f6ec9121cc373d101e994a5..a06697846e69521caceac2ae4d4e040d227d2ae7 100644 --- a/arch/riscv/include/asm/timex.h +++ b/arch/riscv/include/asm/timex.h @@ -88,6 +88,4 @@ static inline int read_current_timer(unsigned long *timer_val) return 0; } -extern void time_init(void); - #endif /* _ASM_RISCV_TIMEX_H */ diff --git a/arch/riscv/include/asm/vector.h b/arch/riscv/include/asm/vector.h new file mode 100644 index 0000000000000000000000000000000000000000..3d78930cab51381ef7c7fd853049957e285801c7 --- /dev/null +++ b/arch/riscv/include/asm/vector.h @@ -0,0 +1,218 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2020 SiFive + */ + +#ifndef __ASM_RISCV_VECTOR_H +#define __ASM_RISCV_VECTOR_H + +#include +#include + +#ifdef CONFIG_RISCV_ISA_V + +#include +#include +#include +#include +#include +#include +#include + +extern unsigned long riscv_v_vsize; +int riscv_v_setup_vsize(void); +bool riscv_v_first_use_handler(struct pt_regs *regs); + +static __always_inline bool has_vector(void) +{ + return riscv_has_extension_unlikely(RISCV_ISA_EXT_v); +} + +static inline void __riscv_v_vstate_clean(struct pt_regs *regs) +{ + regs->status = (regs->status & ~SR_VS) | SR_VS_CLEAN; +} + +static inline void __riscv_v_vstate_dirty(struct pt_regs *regs) +{ + regs->status = (regs->status & ~SR_VS) | SR_VS_DIRTY; +} + +static inline void riscv_v_vstate_off(struct pt_regs *regs) +{ + regs->status = (regs->status & ~SR_VS) | SR_VS_OFF; +} + +static inline void riscv_v_vstate_on(struct pt_regs *regs) +{ + regs->status = (regs->status & ~SR_VS) | SR_VS_INITIAL; +} + +static inline bool riscv_v_vstate_query(struct pt_regs *regs) +{ + return (regs->status & SR_VS) != 0; +} + +static __always_inline void riscv_v_enable(void) +{ + csr_set(CSR_SSTATUS, SR_VS); +} + +static __always_inline void riscv_v_disable(void) +{ + csr_clear(CSR_SSTATUS, SR_VS); +} + +static __always_inline void __vstate_csr_save(struct __riscv_v_ext_state *dest) +{ + asm volatile ( + "csrr %0, " __stringify(CSR_VSTART) "\n\t" + "csrr %1, " __stringify(CSR_VTYPE) "\n\t" + "csrr %2, " __stringify(CSR_VL) "\n\t" + "csrr %3, " __stringify(CSR_VCSR) "\n\t" + : "=r" (dest->vstart), "=r" (dest->vtype), "=r" (dest->vl), + "=r" (dest->vcsr) : :); +} + +static __always_inline void __vstate_csr_restore(struct __riscv_v_ext_state *src) +{ + asm volatile ( + ".option push\n\t" + ".option arch, +v\n\t" + "vsetvl x0, %2, %1\n\t" + ".option pop\n\t" + "csrw " __stringify(CSR_VSTART) ", %0\n\t" + "csrw " __stringify(CSR_VCSR) ", %3\n\t" + : : "r" (src->vstart), "r" (src->vtype), "r" (src->vl), + "r" (src->vcsr) :); +} + +static inline void __riscv_v_vstate_save(struct __riscv_v_ext_state *save_to, + void *datap) +{ + unsigned long vl; + + riscv_v_enable(); + __vstate_csr_save(save_to); + asm volatile ( + ".option push\n\t" + ".option arch, +v\n\t" + "vsetvli %0, x0, e8, m8, ta, ma\n\t" + "vse8.v v0, (%1)\n\t" + "add %1, %1, %0\n\t" + "vse8.v v8, (%1)\n\t" + "add %1, %1, %0\n\t" + "vse8.v v16, (%1)\n\t" + "add %1, %1, %0\n\t" + "vse8.v v24, (%1)\n\t" + ".option pop\n\t" + : "=&r" (vl) : "r" (datap) : "memory"); + riscv_v_disable(); +} + +static inline void __riscv_v_vstate_restore(struct __riscv_v_ext_state *restore_from, + void *datap) +{ + unsigned long vl; + + riscv_v_enable(); + asm volatile ( + ".option push\n\t" + ".option arch, +v\n\t" + "vsetvli %0, x0, e8, m8, ta, ma\n\t" + "vle8.v v0, (%1)\n\t" + "add %1, %1, %0\n\t" + "vle8.v v8, (%1)\n\t" + "add %1, %1, %0\n\t" + "vle8.v v16, (%1)\n\t" + "add %1, %1, %0\n\t" + "vle8.v v24, (%1)\n\t" + ".option pop\n\t" + : "=&r" (vl) : "r" (datap) : "memory"); + __vstate_csr_restore(restore_from); + riscv_v_disable(); +} + +static inline void __riscv_v_vstate_discard(void) +{ + unsigned long vl, vtype_inval = 1UL << (BITS_PER_LONG - 1); + + riscv_v_enable(); + asm volatile ( + ".option push\n\t" + ".option arch, +v\n\t" + "vsetvli %0, x0, e8, m8, ta, ma\n\t" + "vmv.v.i v0, -1\n\t" + "vmv.v.i v8, -1\n\t" + "vmv.v.i v16, -1\n\t" + "vmv.v.i v24, -1\n\t" + "vsetvl %0, x0, %1\n\t" + ".option pop\n\t" + : "=&r" (vl) : "r" (vtype_inval) : "memory"); + riscv_v_disable(); +} + +static inline void riscv_v_vstate_discard(struct pt_regs *regs) +{ + if ((regs->status & SR_VS) == SR_VS_OFF) + return; + + __riscv_v_vstate_discard(); + __riscv_v_vstate_dirty(regs); +} + +static inline void riscv_v_vstate_save(struct task_struct *task, + struct pt_regs *regs) +{ + if ((regs->status & SR_VS) == SR_VS_DIRTY) { + struct __riscv_v_ext_state *vstate = &task->thread.vstate; + + __riscv_v_vstate_save(vstate, vstate->datap); + __riscv_v_vstate_clean(regs); + } +} + +static inline void riscv_v_vstate_restore(struct task_struct *task, + struct pt_regs *regs) +{ + if ((regs->status & SR_VS) != SR_VS_OFF) { + struct __riscv_v_ext_state *vstate = &task->thread.vstate; + + __riscv_v_vstate_restore(vstate, vstate->datap); + __riscv_v_vstate_clean(regs); + } +} + +static inline void __switch_to_vector(struct task_struct *prev, + struct task_struct *next) +{ + struct pt_regs *regs; + + regs = task_pt_regs(prev); + riscv_v_vstate_save(prev, regs); + riscv_v_vstate_restore(next, task_pt_regs(next)); +} + +void riscv_v_vstate_ctrl_init(struct task_struct *tsk); +bool riscv_v_vstate_ctrl_user_allowed(void); + +#else /* ! CONFIG_RISCV_ISA_V */ + +struct pt_regs; + +static inline int riscv_v_setup_vsize(void) { return -EOPNOTSUPP; } +static __always_inline bool has_vector(void) { return false; } +static inline bool riscv_v_first_use_handler(struct pt_regs *regs) { return false; } +static inline bool riscv_v_vstate_query(struct pt_regs *regs) { return false; } +static inline bool riscv_v_vstate_ctrl_user_allowed(void) { return false; } +#define riscv_v_vsize (0) +#define riscv_v_vstate_discard(regs) do {} while (0) +#define riscv_v_vstate_save(task, regs) do {} while (0) +#define riscv_v_vstate_restore(task, regs) do {} while (0) +#define __switch_to_vector(__prev, __next) do {} while (0) +#define riscv_v_vstate_off(regs) do {} while (0) +#define riscv_v_vstate_on(regs) do {} while (0) + +#endif /* CONFIG_RISCV_ISA_V */ + +#endif /* ! __ASM_RISCV_VECTOR_H */ diff --git a/arch/riscv/include/uapi/asm/auxvec.h b/arch/riscv/include/uapi/asm/auxvec.h index fb187a33ce5897e7b671d7253324d5eadb00c5f3..10aaa83db89ef74a6441f5782698dc82d7e0ee5c 100644 --- a/arch/riscv/include/uapi/asm/auxvec.h +++ b/arch/riscv/include/uapi/asm/auxvec.h @@ -35,5 +35,6 @@ /* entries in ARCH_DLINFO */ #define AT_VECTOR_SIZE_ARCH 9 +#define AT_MINSIGSTKSZ 51 #endif /* _UAPI_ASM_RISCV_AUXVEC_H */ diff --git a/arch/riscv/include/uapi/asm/bitsperlong.h b/arch/riscv/include/uapi/asm/bitsperlong.h deleted file mode 100644 index 7d0b32e3b7017696866b4a0c12d94bd8e0d3b44d..0000000000000000000000000000000000000000 --- a/arch/riscv/include/uapi/asm/bitsperlong.h +++ /dev/null @@ -1,14 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */ -/* - * Copyright (C) 2012 ARM Ltd. - * Copyright (C) 2015 Regents of the University of California - */ - -#ifndef _UAPI_ASM_RISCV_BITSPERLONG_H -#define _UAPI_ASM_RISCV_BITSPERLONG_H - -#define __BITS_PER_LONG (__SIZEOF_POINTER__ * 8) - -#include - -#endif /* _UAPI_ASM_RISCV_BITSPERLONG_H */ diff --git a/arch/riscv/include/uapi/asm/hwcap.h b/arch/riscv/include/uapi/asm/hwcap.h index 46dc3f5ee99f9681639fa4d0e38802ecd9eb208c..c52bb7bbbabe93176963be20cf8bb39d9239901e 100644 --- a/arch/riscv/include/uapi/asm/hwcap.h +++ b/arch/riscv/include/uapi/asm/hwcap.h @@ -21,5 +21,6 @@ #define COMPAT_HWCAP_ISA_F (1 << ('F' - 'A')) #define COMPAT_HWCAP_ISA_D (1 << ('D' - 'A')) #define COMPAT_HWCAP_ISA_C (1 << ('C' - 'A')) +#define COMPAT_HWCAP_ISA_V (1 << ('V' - 'A')) #endif /* _UAPI_ASM_RISCV_HWCAP_H */ diff --git a/arch/riscv/include/uapi/asm/hwprobe.h b/arch/riscv/include/uapi/asm/hwprobe.h index 8d745a4ad8a2c3e60ba09c0a93497711bd56f6e8..006bfb48343dd423d5ddd04fb38a73043318e2e1 100644 --- a/arch/riscv/include/uapi/asm/hwprobe.h +++ b/arch/riscv/include/uapi/asm/hwprobe.h @@ -25,6 +25,10 @@ struct riscv_hwprobe { #define RISCV_HWPROBE_KEY_IMA_EXT_0 4 #define RISCV_HWPROBE_IMA_FD (1 << 0) #define RISCV_HWPROBE_IMA_C (1 << 1) +#define RISCV_HWPROBE_IMA_V (1 << 2) +#define RISCV_HWPROBE_EXT_ZBA (1 << 3) +#define RISCV_HWPROBE_EXT_ZBB (1 << 4) +#define RISCV_HWPROBE_EXT_ZBS (1 << 5) #define RISCV_HWPROBE_KEY_CPUPERF_0 5 #define RISCV_HWPROBE_MISALIGNED_UNKNOWN (0 << 0) #define RISCV_HWPROBE_MISALIGNED_EMULATED (1 << 0) diff --git a/arch/riscv/include/uapi/asm/kvm.h b/arch/riscv/include/uapi/asm/kvm.h index f92790c9481a33f384ba461dc0dcfd1f83b10b90..930fdc4101cdab8eddbd31e2ff33fb27f17bc998 100644 --- a/arch/riscv/include/uapi/asm/kvm.h +++ b/arch/riscv/include/uapi/asm/kvm.h @@ -15,6 +15,7 @@ #include #include +#define __KVM_HAVE_IRQ_LINE #define __KVM_HAVE_READONLY_MEM #define KVM_COALESCED_MMIO_PAGE_OFFSET 1 @@ -121,6 +122,8 @@ enum KVM_RISCV_ISA_EXT_ID { KVM_RISCV_ISA_EXT_ZICBOZ, KVM_RISCV_ISA_EXT_ZBB, KVM_RISCV_ISA_EXT_SSAIA, + KVM_RISCV_ISA_EXT_V, + KVM_RISCV_ISA_EXT_SVNAPOT, KVM_RISCV_ISA_EXT_MAX, }; @@ -203,6 +206,84 @@ enum KVM_RISCV_SBI_EXT_ID { #define KVM_REG_RISCV_SBI_MULTI_REG_LAST \ KVM_REG_RISCV_SBI_MULTI_REG(KVM_RISCV_SBI_EXT_MAX - 1) +/* V extension registers are mapped as type 9 */ +#define KVM_REG_RISCV_VECTOR (0x09 << KVM_REG_RISCV_TYPE_SHIFT) +#define KVM_REG_RISCV_VECTOR_CSR_REG(name) \ + (offsetof(struct __riscv_v_ext_state, name) / sizeof(unsigned long)) +#define KVM_REG_RISCV_VECTOR_REG(n) \ + ((n) + sizeof(struct __riscv_v_ext_state) / sizeof(unsigned long)) + +/* Device Control API: RISC-V AIA */ +#define KVM_DEV_RISCV_APLIC_ALIGN 0x1000 +#define KVM_DEV_RISCV_APLIC_SIZE 0x4000 +#define KVM_DEV_RISCV_APLIC_MAX_HARTS 0x4000 +#define KVM_DEV_RISCV_IMSIC_ALIGN 0x1000 +#define KVM_DEV_RISCV_IMSIC_SIZE 0x1000 + +#define KVM_DEV_RISCV_AIA_GRP_CONFIG 0 +#define KVM_DEV_RISCV_AIA_CONFIG_MODE 0 +#define KVM_DEV_RISCV_AIA_CONFIG_IDS 1 +#define KVM_DEV_RISCV_AIA_CONFIG_SRCS 2 +#define KVM_DEV_RISCV_AIA_CONFIG_GROUP_BITS 3 +#define KVM_DEV_RISCV_AIA_CONFIG_GROUP_SHIFT 4 +#define KVM_DEV_RISCV_AIA_CONFIG_HART_BITS 5 +#define KVM_DEV_RISCV_AIA_CONFIG_GUEST_BITS 6 + +/* + * Modes of RISC-V AIA device: + * 1) EMUL (aka Emulation): Trap-n-emulate IMSIC + * 2) HWACCEL (aka HW Acceleration): Virtualize IMSIC using IMSIC guest files + * 3) AUTO (aka Automatic): Virtualize IMSIC using IMSIC guest files whenever + * available otherwise fallback to trap-n-emulation + */ +#define KVM_DEV_RISCV_AIA_MODE_EMUL 0 +#define KVM_DEV_RISCV_AIA_MODE_HWACCEL 1 +#define KVM_DEV_RISCV_AIA_MODE_AUTO 2 + +#define KVM_DEV_RISCV_AIA_IDS_MIN 63 +#define KVM_DEV_RISCV_AIA_IDS_MAX 2048 +#define KVM_DEV_RISCV_AIA_SRCS_MAX 1024 +#define KVM_DEV_RISCV_AIA_GROUP_BITS_MAX 8 +#define KVM_DEV_RISCV_AIA_GROUP_SHIFT_MIN 24 +#define KVM_DEV_RISCV_AIA_GROUP_SHIFT_MAX 56 +#define KVM_DEV_RISCV_AIA_HART_BITS_MAX 16 +#define KVM_DEV_RISCV_AIA_GUEST_BITS_MAX 8 + +#define KVM_DEV_RISCV_AIA_GRP_ADDR 1 +#define KVM_DEV_RISCV_AIA_ADDR_APLIC 0 +#define KVM_DEV_RISCV_AIA_ADDR_IMSIC(__vcpu) (1 + (__vcpu)) +#define KVM_DEV_RISCV_AIA_ADDR_MAX \ + (1 + KVM_DEV_RISCV_APLIC_MAX_HARTS) + +#define KVM_DEV_RISCV_AIA_GRP_CTRL 2 +#define KVM_DEV_RISCV_AIA_CTRL_INIT 0 + +/* + * The device attribute type contains the memory mapped offset of the + * APLIC register (range 0x0000-0x3FFF) and it must be 4-byte aligned. + */ +#define KVM_DEV_RISCV_AIA_GRP_APLIC 3 + +/* + * The lower 12-bits of the device attribute type contains the iselect + * value of the IMSIC register (range 0x70-0xFF) whereas the higher order + * bits contains the VCPU id. + */ +#define KVM_DEV_RISCV_AIA_GRP_IMSIC 4 +#define KVM_DEV_RISCV_AIA_IMSIC_ISEL_BITS 12 +#define KVM_DEV_RISCV_AIA_IMSIC_ISEL_MASK \ + ((1U << KVM_DEV_RISCV_AIA_IMSIC_ISEL_BITS) - 1) +#define KVM_DEV_RISCV_AIA_IMSIC_MKATTR(__vcpu, __isel) \ + (((__vcpu) << KVM_DEV_RISCV_AIA_IMSIC_ISEL_BITS) | \ + ((__isel) & KVM_DEV_RISCV_AIA_IMSIC_ISEL_MASK)) +#define KVM_DEV_RISCV_AIA_IMSIC_GET_ISEL(__attr) \ + ((__attr) & KVM_DEV_RISCV_AIA_IMSIC_ISEL_MASK) +#define KVM_DEV_RISCV_AIA_IMSIC_GET_VCPU(__attr) \ + ((__attr) >> KVM_DEV_RISCV_AIA_IMSIC_ISEL_BITS) + +/* One single KVM irqchip, ie. the AIA */ +#define KVM_NR_IRQCHIPS 1 + #endif #endif /* __LINUX_KVM_RISCV_H */ diff --git a/arch/riscv/include/uapi/asm/ptrace.h b/arch/riscv/include/uapi/asm/ptrace.h index 882547f6bd5c91d34c376ae81fe38f5634e8380a..e17c550986a696bdc19651afaa42d2e91b55c659 100644 --- a/arch/riscv/include/uapi/asm/ptrace.h +++ b/arch/riscv/include/uapi/asm/ptrace.h @@ -71,12 +71,51 @@ struct __riscv_q_ext_state { __u32 reserved[3]; }; +struct __riscv_ctx_hdr { + __u32 magic; + __u32 size; +}; + +struct __riscv_extra_ext_header { + __u32 __padding[129] __attribute__((aligned(16))); + /* + * Reserved for expansion of sigcontext structure. Currently zeroed + * upon signal, and must be zero upon sigreturn. + */ + __u32 reserved; + struct __riscv_ctx_hdr hdr; +}; + union __riscv_fp_state { struct __riscv_f_ext_state f; struct __riscv_d_ext_state d; struct __riscv_q_ext_state q; }; +struct __riscv_v_ext_state { + unsigned long vstart; + unsigned long vl; + unsigned long vtype; + unsigned long vcsr; + void *datap; + /* + * In signal handler, datap will be set a correct user stack offset + * and vector registers will be copied to the address of datap + * pointer. + * + * In ptrace syscall, datap will be set to zero and the vector + * registers will be copied to the address right after this + * structure. + */ +}; + +/* + * According to spec: The number of bits in a single vector register, + * VLEN >= ELEN, which must be a power of 2, and must be no greater than + * 2^16 = 65536bits = 8192bytes + */ +#define RISCV_MAX_VLENB (8192) + #endif /* __ASSEMBLY__ */ #endif /* _UAPI_ASM_RISCV_PTRACE_H */ diff --git a/arch/riscv/include/uapi/asm/sigcontext.h b/arch/riscv/include/uapi/asm/sigcontext.h index 84f2dfcfdbce2ee92ba6250822bb2397cbce2768..8c8712aa95513ba2c78fdeacad02c0a8e508e87c 100644 --- a/arch/riscv/include/uapi/asm/sigcontext.h +++ b/arch/riscv/include/uapi/asm/sigcontext.h @@ -8,6 +8,19 @@ #include +/* The Magic number for signal context frame header. */ +#define RISCV_V_MAGIC 0x53465457 +#define END_MAGIC 0x0 + +/* The size of END signal context header. */ +#define END_HDR_SIZE 0x0 + +#ifndef __ASSEMBLY__ + +struct __sc_riscv_v_state { + struct __riscv_v_ext_state v_state; +} __attribute__((aligned(16))); + /* * Signal context structure * @@ -16,7 +29,12 @@ */ struct sigcontext { struct user_regs_struct sc_regs; - union __riscv_fp_state sc_fpregs; + union { + union __riscv_fp_state sc_fpregs; + struct __riscv_extra_ext_header sc_extdesc; + }; }; +#endif /*!__ASSEMBLY__*/ + #endif /* _UAPI_ASM_RISCV_SIGCONTEXT_H */ diff --git a/arch/riscv/kernel/Makefile b/arch/riscv/kernel/Makefile index 153864e4f3996dc3405a28fc024e0d76f0232028..506cc4a9a45a555eb3032b23caed8def62c9aa71 100644 --- a/arch/riscv/kernel/Makefile +++ b/arch/riscv/kernel/Makefile @@ -60,6 +60,7 @@ obj-$(CONFIG_MMU) += vdso.o vdso/ obj-$(CONFIG_RISCV_M_MODE) += traps_misaligned.o obj-$(CONFIG_FPU) += fpu.o +obj-$(CONFIG_RISCV_ISA_V) += vector.o obj-$(CONFIG_SMP) += smpboot.o obj-$(CONFIG_SMP) += smp.o obj-$(CONFIG_SMP) += cpu_ops.o @@ -96,3 +97,4 @@ obj-$(CONFIG_COMPAT) += compat_signal.o obj-$(CONFIG_COMPAT) += compat_vdso/ obj-$(CONFIG_64BIT) += pi/ +obj-$(CONFIG_ACPI) += acpi.o diff --git a/arch/riscv/kernel/acpi.c b/arch/riscv/kernel/acpi.c new file mode 100644 index 0000000000000000000000000000000000000000..5ee03ebab80e5af633ac086e79436688ad6cd9d5 --- /dev/null +++ b/arch/riscv/kernel/acpi.c @@ -0,0 +1,251 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * RISC-V Specific Low-Level ACPI Boot Support + * + * Copyright (C) 2013-2014, Linaro Ltd. + * Author: Al Stone + * Author: Graeme Gregory + * Author: Hanjun Guo + * Author: Tomasz Nowicki + * Author: Naresh Bhat + * + * Copyright (C) 2021-2023, Ventana Micro Systems Inc. + * Author: Sunil V L + */ + +#include +#include +#include +#include + +int acpi_noirq = 1; /* skip ACPI IRQ initialization */ +int acpi_disabled = 1; +EXPORT_SYMBOL(acpi_disabled); + +int acpi_pci_disabled = 1; /* skip ACPI PCI scan and IRQ initialization */ +EXPORT_SYMBOL(acpi_pci_disabled); + +static bool param_acpi_off __initdata; +static bool param_acpi_on __initdata; +static bool param_acpi_force __initdata; + +static struct acpi_madt_rintc cpu_madt_rintc[NR_CPUS]; + +static int __init parse_acpi(char *arg) +{ + if (!arg) + return -EINVAL; + + /* "acpi=off" disables both ACPI table parsing and interpreter */ + if (strcmp(arg, "off") == 0) + param_acpi_off = true; + else if (strcmp(arg, "on") == 0) /* prefer ACPI over DT */ + param_acpi_on = true; + else if (strcmp(arg, "force") == 0) /* force ACPI to be enabled */ + param_acpi_force = true; + else + return -EINVAL; /* Core will print when we return error */ + + return 0; +} +early_param("acpi", parse_acpi); + +/* + * acpi_fadt_sanity_check() - Check FADT presence and carry out sanity + * checks on it + * + * Return 0 on success, <0 on failure + */ +static int __init acpi_fadt_sanity_check(void) +{ + struct acpi_table_header *table; + struct acpi_table_fadt *fadt; + acpi_status status; + int ret = 0; + + /* + * FADT is required on riscv; retrieve it to check its presence + * and carry out revision and ACPI HW reduced compliancy tests + */ + status = acpi_get_table(ACPI_SIG_FADT, 0, &table); + if (ACPI_FAILURE(status)) { + const char *msg = acpi_format_exception(status); + + pr_err("Failed to get FADT table, %s\n", msg); + return -ENODEV; + } + + fadt = (struct acpi_table_fadt *)table; + + /* + * The revision in the table header is the FADT's Major revision. The + * FADT also has a minor revision, which is stored in the FADT itself. + * + * TODO: Currently, we check for 6.5 as the minimum version to check + * for HW_REDUCED flag. However, once RISC-V updates are released in + * the ACPI spec, we need to update this check for exact minor revision + */ + if (table->revision < 6 || (table->revision == 6 && fadt->minor_revision < 5)) + pr_err(FW_BUG "Unsupported FADT revision %d.%d, should be 6.5+\n", + table->revision, fadt->minor_revision); + + if (!(fadt->flags & ACPI_FADT_HW_REDUCED)) { + pr_err("FADT not ACPI hardware reduced compliant\n"); + ret = -EINVAL; + } + + /* + * acpi_get_table() creates FADT table mapping that + * should be released after parsing and before resuming boot + */ + acpi_put_table(table); + return ret; +} + +/* + * acpi_boot_table_init() called from setup_arch(), always. + * 1. find RSDP and get its address, and then find XSDT + * 2. extract all tables and checksums them all + * 3. check ACPI FADT HW reduced flag + * + * We can parse ACPI boot-time tables such as MADT after + * this function is called. + * + * On return ACPI is enabled if either: + * + * - ACPI tables are initialized and sanity checks passed + * - acpi=force was passed in the command line and ACPI was not disabled + * explicitly through acpi=off command line parameter + * + * ACPI is disabled on function return otherwise + */ +void __init acpi_boot_table_init(void) +{ + /* + * Enable ACPI instead of device tree unless + * - ACPI has been disabled explicitly (acpi=off), or + * - firmware has not populated ACPI ptr in EFI system table + * and ACPI has not been [force] enabled (acpi=on|force) + */ + if (param_acpi_off || + (!param_acpi_on && !param_acpi_force && + efi.acpi20 == EFI_INVALID_TABLE_ADDR)) + return; + + /* + * ACPI is disabled at this point. Enable it in order to parse + * the ACPI tables and carry out sanity checks + */ + enable_acpi(); + + /* + * If ACPI tables are initialized and FADT sanity checks passed, + * leave ACPI enabled and carry on booting; otherwise disable ACPI + * on initialization error. + * If acpi=force was passed on the command line it forces ACPI + * to be enabled even if its initialization failed. + */ + if (acpi_table_init() || acpi_fadt_sanity_check()) { + pr_err("Failed to init ACPI tables\n"); + if (!param_acpi_force) + disable_acpi(); + } +} + +static int acpi_parse_madt_rintc(union acpi_subtable_headers *header, const unsigned long end) +{ + struct acpi_madt_rintc *rintc = (struct acpi_madt_rintc *)header; + int cpuid; + + if (!(rintc->flags & ACPI_MADT_ENABLED)) + return 0; + + cpuid = riscv_hartid_to_cpuid(rintc->hart_id); + /* + * When CONFIG_SMP is disabled, mapping won't be created for + * all cpus. + * CPUs more than num_possible_cpus, will be ignored. + */ + if (cpuid >= 0 && cpuid < num_possible_cpus()) + cpu_madt_rintc[cpuid] = *rintc; + + return 0; +} + +/* + * Instead of parsing (and freeing) the ACPI table, cache + * the RINTC structures since they are frequently used + * like in cpuinfo. + */ +void __init acpi_init_rintc_map(void) +{ + if (acpi_table_parse_madt(ACPI_MADT_TYPE_RINTC, acpi_parse_madt_rintc, 0) <= 0) { + pr_err("No valid RINTC entries exist\n"); + BUG(); + } +} + +struct acpi_madt_rintc *acpi_cpu_get_madt_rintc(int cpu) +{ + return &cpu_madt_rintc[cpu]; +} + +u32 get_acpi_id_for_cpu(int cpu) +{ + return acpi_cpu_get_madt_rintc(cpu)->uid; +} + +/* + * __acpi_map_table() will be called before paging_init(), so early_ioremap() + * or early_memremap() should be called here to for ACPI table mapping. + */ +void __init __iomem *__acpi_map_table(unsigned long phys, unsigned long size) +{ + if (!size) + return NULL; + + return early_ioremap(phys, size); +} + +void __init __acpi_unmap_table(void __iomem *map, unsigned long size) +{ + if (!map || !size) + return; + + early_iounmap(map, size); +} + +void *acpi_os_ioremap(acpi_physical_address phys, acpi_size size) +{ + return memremap(phys, size, MEMREMAP_WB); +} + +#ifdef CONFIG_PCI + +/* + * These interfaces are defined just to enable building ACPI core. + * TODO: Update it with actual implementation when external interrupt + * controller support is added in RISC-V ACPI. + */ +int raw_pci_read(unsigned int domain, unsigned int bus, unsigned int devfn, + int reg, int len, u32 *val) +{ + return PCIBIOS_DEVICE_NOT_FOUND; +} + +int raw_pci_write(unsigned int domain, unsigned int bus, unsigned int devfn, + int reg, int len, u32 val) +{ + return PCIBIOS_DEVICE_NOT_FOUND; +} + +int acpi_pci_bus_find_domain_nr(struct pci_bus *bus) +{ + return -1; +} + +struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root) +{ + return NULL; +} +#endif /* CONFIG_PCI */ diff --git a/arch/riscv/kernel/cpu-hotplug.c b/arch/riscv/kernel/cpu-hotplug.c index a941adc7cbf24311022b35079f2d491f70f6965b..457a18efcb114880511f9eb342ccb2fb7e377382 100644 --- a/arch/riscv/kernel/cpu-hotplug.c +++ b/arch/riscv/kernel/cpu-hotplug.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -49,17 +50,15 @@ int __cpu_disable(void) return ret; } +#ifdef CONFIG_HOTPLUG_CPU /* - * Called on the thread which is asking for a CPU to be shutdown. + * Called on the thread which is asking for a CPU to be shutdown, if the + * CPU reported dead to the hotplug core. */ -void __cpu_die(unsigned int cpu) +void arch_cpuhp_cleanup_dead_cpu(unsigned int cpu) { int ret = 0; - if (!cpu_wait_death(cpu, 5)) { - pr_err("CPU %u: didn't die\n", cpu); - return; - } pr_notice("CPU%u: off\n", cpu); /* Verify from the firmware if the cpu is really stopped*/ @@ -76,9 +75,10 @@ void __noreturn arch_cpu_idle_dead(void) { idle_task_exit(); - (void)cpu_report_death(); + cpuhp_ap_report_dead(); cpu_ops[smp_processor_id()]->cpu_stop(); /* It should never reach here */ BUG(); } +#endif diff --git a/arch/riscv/kernel/cpu.c b/arch/riscv/kernel/cpu.c index c96aa56cf1c7b2a8856c8eda3da77e4a24b447e0..a2fc952318e9f903dc2232c89106e82c3edfcc07 100644 --- a/arch/riscv/kernel/cpu.c +++ b/arch/riscv/kernel/cpu.c @@ -3,10 +3,13 @@ * Copyright (C) 2012 Regents of the University of California */ +#include #include +#include #include #include #include +#include #include #include #include @@ -19,6 +22,26 @@ * isn't an enabled and valid RISC-V hart node. */ int riscv_of_processor_hartid(struct device_node *node, unsigned long *hart) +{ + int cpu; + + *hart = (unsigned long)of_get_cpu_hwid(node, 0); + if (*hart == ~0UL) { + pr_warn("Found CPU without hart ID\n"); + return -ENODEV; + } + + cpu = riscv_hartid_to_cpuid(*hart); + if (cpu < 0) + return cpu; + + if (!cpu_possible(cpu)) + return -ENODEV; + + return 0; +} + +int riscv_early_of_processor_hartid(struct device_node *node, unsigned long *hart) { const char *isa; @@ -27,7 +50,7 @@ int riscv_of_processor_hartid(struct device_node *node, unsigned long *hart) return -ENODEV; } - *hart = (unsigned long) of_get_cpu_hwid(node, 0); + *hart = (unsigned long)of_get_cpu_hwid(node, 0); if (*hart == ~0UL) { pr_warn("Found CPU without hart ID\n"); return -ENODEV; @@ -42,10 +65,12 @@ int riscv_of_processor_hartid(struct device_node *node, unsigned long *hart) pr_warn("CPU with hartid=%lu has no \"riscv,isa\" property\n", *hart); return -ENODEV; } - if (isa[0] != 'r' || isa[1] != 'v') { - pr_warn("CPU with hartid=%lu has an invalid ISA of \"%s\"\n", *hart, isa); + + if (IS_ENABLED(CONFIG_32BIT) && strncasecmp(isa, "rv32ima", 7)) + return -ENODEV; + + if (IS_ENABLED(CONFIG_64BIT) && strncasecmp(isa, "rv64ima", 7)) return -ENODEV; - } return 0; } @@ -183,8 +208,14 @@ arch_initcall(riscv_cpuinfo_init); static struct riscv_isa_ext_data isa_ext_arr[] = { __RISCV_ISA_EXT_DATA(zicbom, RISCV_ISA_EXT_ZICBOM), __RISCV_ISA_EXT_DATA(zicboz, RISCV_ISA_EXT_ZICBOZ), + __RISCV_ISA_EXT_DATA(zicntr, RISCV_ISA_EXT_ZICNTR), + __RISCV_ISA_EXT_DATA(zicsr, RISCV_ISA_EXT_ZICSR), + __RISCV_ISA_EXT_DATA(zifencei, RISCV_ISA_EXT_ZIFENCEI), __RISCV_ISA_EXT_DATA(zihintpause, RISCV_ISA_EXT_ZIHINTPAUSE), + __RISCV_ISA_EXT_DATA(zihpm, RISCV_ISA_EXT_ZIHPM), + __RISCV_ISA_EXT_DATA(zba, RISCV_ISA_EXT_ZBA), __RISCV_ISA_EXT_DATA(zbb, RISCV_ISA_EXT_ZBB), + __RISCV_ISA_EXT_DATA(zbs, RISCV_ISA_EXT_ZBS), __RISCV_ISA_EXT_DATA(smaia, RISCV_ISA_EXT_SMAIA), __RISCV_ISA_EXT_DATA(ssaia, RISCV_ISA_EXT_SSAIA), __RISCV_ISA_EXT_DATA(sscofpmf, RISCV_ISA_EXT_SSCOFPMF), @@ -283,23 +314,35 @@ static void c_stop(struct seq_file *m, void *v) static int c_show(struct seq_file *m, void *v) { unsigned long cpu_id = (unsigned long)v - 1; - struct device_node *node = of_get_cpu_node(cpu_id, NULL); struct riscv_cpuinfo *ci = per_cpu_ptr(&riscv_cpuinfo, cpu_id); + struct device_node *node; const char *compat, *isa; seq_printf(m, "processor\t: %lu\n", cpu_id); seq_printf(m, "hart\t\t: %lu\n", cpuid_to_hartid_map(cpu_id)); - if (!of_property_read_string(node, "riscv,isa", &isa)) - print_isa(m, isa); - print_mmu(m); - if (!of_property_read_string(node, "compatible", &compat) - && strcmp(compat, "riscv")) - seq_printf(m, "uarch\t\t: %s\n", compat); + + if (acpi_disabled) { + node = of_get_cpu_node(cpu_id, NULL); + if (!of_property_read_string(node, "riscv,isa", &isa)) + print_isa(m, isa); + + print_mmu(m); + if (!of_property_read_string(node, "compatible", &compat) && + strcmp(compat, "riscv")) + seq_printf(m, "uarch\t\t: %s\n", compat); + + of_node_put(node); + } else { + if (!acpi_get_riscv_isa(NULL, cpu_id, &isa)) + print_isa(m, isa); + + print_mmu(m); + } + seq_printf(m, "mvendorid\t: 0x%lx\n", ci->mvendorid); seq_printf(m, "marchid\t\t: 0x%lx\n", ci->marchid); seq_printf(m, "mimpid\t\t: 0x%lx\n", ci->mimpid); seq_puts(m, "\n"); - of_node_put(node); return 0; } diff --git a/arch/riscv/kernel/cpufeature.c b/arch/riscv/kernel/cpufeature.c index b1d6b7e4b82902fc8515e659a0533a39997f94f2..a8f66c015229727e9fd3bbcb93340943b24cff93 100644 --- a/arch/riscv/kernel/cpufeature.c +++ b/arch/riscv/kernel/cpufeature.c @@ -6,18 +6,22 @@ * Copyright (C) 2017 SiFive */ +#include #include #include #include #include #include #include +#include +#include #include #include #include #include #include #include +#include #define NUM_ALPHA_EXTS ('z' - 'a' + 1) @@ -26,6 +30,9 @@ unsigned long elf_hwcap __read_mostly; /* Host ISA bitmap */ static DECLARE_BITMAP(riscv_isa, RISCV_ISA_EXT_MAX) __read_mostly; +/* Per-cpu ISA extensions. */ +struct riscv_isainfo hart_isa[NR_CPUS]; + /* Performance information */ DEFINE_PER_CPU(long, misaligned_access_speed); @@ -71,10 +78,10 @@ static bool riscv_isa_extension_check(int id) switch (id) { case RISCV_ISA_EXT_ZICBOM: if (!riscv_cbom_block_size) { - pr_err("Zicbom detected in ISA string, but no cbom-block-size found\n"); + pr_err("Zicbom detected in ISA string, disabling as no cbom-block-size found\n"); return false; } else if (!is_power_of_2(riscv_cbom_block_size)) { - pr_err("cbom-block-size present, but is not a power-of-2\n"); + pr_err("Zicbom disabled as cbom-block-size present, but is not a power-of-2\n"); return false; } return true; @@ -99,7 +106,9 @@ void __init riscv_fill_hwcap(void) char print_str[NUM_ALPHA_EXTS + 1]; int i, j, rc; unsigned long isa2hwcap[26] = {0}; - unsigned long hartid; + struct acpi_table_header *rhct; + acpi_status status; + unsigned int cpu; isa2hwcap['i' - 'a'] = COMPAT_HWCAP_ISA_I; isa2hwcap['m' - 'a'] = COMPAT_HWCAP_ISA_M; @@ -107,45 +116,59 @@ void __init riscv_fill_hwcap(void) isa2hwcap['f' - 'a'] = COMPAT_HWCAP_ISA_F; isa2hwcap['d' - 'a'] = COMPAT_HWCAP_ISA_D; isa2hwcap['c' - 'a'] = COMPAT_HWCAP_ISA_C; + isa2hwcap['v' - 'a'] = COMPAT_HWCAP_ISA_V; elf_hwcap = 0; bitmap_zero(riscv_isa, RISCV_ISA_EXT_MAX); - for_each_of_cpu_node(node) { + if (!acpi_disabled) { + status = acpi_get_table(ACPI_SIG_RHCT, 0, &rhct); + if (ACPI_FAILURE(status)) + return; + } + + for_each_possible_cpu(cpu) { + struct riscv_isainfo *isainfo = &hart_isa[cpu]; unsigned long this_hwcap = 0; - DECLARE_BITMAP(this_isa, RISCV_ISA_EXT_MAX); - const char *temp; - rc = riscv_of_processor_hartid(node, &hartid); - if (rc < 0) - continue; + if (acpi_disabled) { + node = of_cpu_device_node_get(cpu); + if (!node) { + pr_warn("Unable to find cpu node\n"); + continue; + } - if (of_property_read_string(node, "riscv,isa", &isa)) { - pr_warn("Unable to find \"riscv,isa\" devicetree entry\n"); - continue; + rc = of_property_read_string(node, "riscv,isa", &isa); + of_node_put(node); + if (rc) { + pr_warn("Unable to find \"riscv,isa\" devicetree entry\n"); + continue; + } + } else { + rc = acpi_get_riscv_isa(rhct, cpu, &isa); + if (rc < 0) { + pr_warn("Unable to get ISA for the hart - %d\n", cpu); + continue; + } } - temp = isa; -#if IS_ENABLED(CONFIG_32BIT) - if (!strncmp(isa, "rv32", 4)) - isa += 4; -#elif IS_ENABLED(CONFIG_64BIT) - if (!strncmp(isa, "rv64", 4)) - isa += 4; -#endif - /* The riscv,isa DT property must start with rv64 or rv32 */ - if (temp == isa) - continue; - bitmap_zero(this_isa, RISCV_ISA_EXT_MAX); - for (; *isa; ++isa) { + /* + * For all possible cpus, we have already validated in + * the boot process that they at least contain "rv" and + * whichever of "32"/"64" this kernel supports, and so this + * section can be skipped. + */ + isa += 4; + + while (*isa) { const char *ext = isa++; const char *ext_end = isa; bool ext_long = false, ext_err = false; switch (*ext) { case 's': - /** + /* * Workaround for invalid single-letter 's' & 'u'(QEMU). * No need to set the bit in riscv_isa as 's' & 'u' are * not valid ISA extensions. It works until multi-letter @@ -157,75 +180,123 @@ void __init riscv_fill_hwcap(void) break; } fallthrough; + case 'S': case 'x': + case 'X': case 'z': + case 'Z': + /* + * Before attempting to parse the extension itself, we find its end. + * As multi-letter extensions must be split from other multi-letter + * extensions with an "_", the end of a multi-letter extension will + * either be the null character or the "_" at the start of the next + * multi-letter extension. + * + * Next, as the extensions version is currently ignored, we + * eliminate that portion. This is done by parsing backwards from + * the end of the extension, removing any numbers. This may be a + * major or minor number however, so the process is repeated if a + * minor number was found. + * + * ext_end is intended to represent the first character *after* the + * name portion of an extension, but will be decremented to the last + * character itself while eliminating the extensions version number. + * A simple re-increment solves this problem. + */ ext_long = true; - /* Multi-letter extension must be delimited */ for (; *isa && *isa != '_'; ++isa) - if (unlikely(!islower(*isa) - && !isdigit(*isa))) + if (unlikely(!isalnum(*isa))) ext_err = true; - /* Parse backwards */ + ext_end = isa; if (unlikely(ext_err)) break; + if (!isdigit(ext_end[-1])) break; - /* Skip the minor version */ + while (isdigit(*--ext_end)) ; - if (ext_end[0] != 'p' - || !isdigit(ext_end[-1])) { - /* Advance it to offset the pre-decrement */ + + if (tolower(ext_end[0]) != 'p' || !isdigit(ext_end[-1])) { ++ext_end; break; } - /* Skip the major version */ + while (isdigit(*--ext_end)) ; + ++ext_end; break; default: - if (unlikely(!islower(*ext))) { + /* + * Things are a little easier for single-letter extensions, as they + * are parsed forwards. + * + * After checking that our starting position is valid, we need to + * ensure that, when isa was incremented at the start of the loop, + * that it arrived at the start of the next extension. + * + * If we are already on a non-digit, there is nothing to do. Either + * we have a multi-letter extension's _, or the start of an + * extension. + * + * Otherwise we have found the current extension's major version + * number. Parse past it, and a subsequent p/minor version number + * if present. The `p` extension must not appear immediately after + * a number, so there is no fear of missing it. + * + */ + if (unlikely(!isalpha(*ext))) { ext_err = true; break; } - /* Find next extension */ + if (!isdigit(*isa)) break; - /* Skip the minor version */ + while (isdigit(*++isa)) ; - if (*isa != 'p') + + if (tolower(*isa) != 'p') break; + if (!isdigit(*++isa)) { --isa; break; } - /* Skip the major version */ + while (isdigit(*++isa)) ; + break; } - if (*isa != '_') - --isa; -#define SET_ISA_EXT_MAP(name, bit) \ - do { \ - if ((ext_end - ext == sizeof(name) - 1) && \ - !memcmp(ext, name, sizeof(name) - 1) && \ - riscv_isa_extension_check(bit)) \ - set_bit(bit, this_isa); \ - } while (false) \ + /* + * The parser expects that at the start of an iteration isa points to the + * first character of the next extension. As we stop parsing an extension + * on meeting a non-alphanumeric character, an extra increment is needed + * where the succeeding extension is a multi-letter prefixed with an "_". + */ + if (*isa == '_') + ++isa; + +#define SET_ISA_EXT_MAP(name, bit) \ + do { \ + if ((ext_end - ext == sizeof(name) - 1) && \ + !strncasecmp(ext, name, sizeof(name) - 1) && \ + riscv_isa_extension_check(bit)) \ + set_bit(bit, isainfo->isa); \ + } while (false) \ if (unlikely(ext_err)) continue; if (!ext_long) { - int nr = *ext - 'a'; + int nr = tolower(*ext) - 'a'; if (riscv_isa_extension_check(nr)) { this_hwcap |= isa2hwcap[nr]; - set_bit(nr, this_isa); + set_bit(nr, isainfo->isa); } } else { /* sorted alphabetically */ @@ -236,7 +307,9 @@ void __init riscv_fill_hwcap(void) SET_ISA_EXT_MAP("svinval", RISCV_ISA_EXT_SVINVAL); SET_ISA_EXT_MAP("svnapot", RISCV_ISA_EXT_SVNAPOT); SET_ISA_EXT_MAP("svpbmt", RISCV_ISA_EXT_SVPBMT); + SET_ISA_EXT_MAP("zba", RISCV_ISA_EXT_ZBA); SET_ISA_EXT_MAP("zbb", RISCV_ISA_EXT_ZBB); + SET_ISA_EXT_MAP("zbs", RISCV_ISA_EXT_ZBS); SET_ISA_EXT_MAP("zicbom", RISCV_ISA_EXT_ZICBOM); SET_ISA_EXT_MAP("zicboz", RISCV_ISA_EXT_ZICBOZ); SET_ISA_EXT_MAP("zihintpause", RISCV_ISA_EXT_ZIHINTPAUSE); @@ -244,6 +317,18 @@ void __init riscv_fill_hwcap(void) #undef SET_ISA_EXT_MAP } + /* + * These ones were as they were part of the base ISA when the + * port & dt-bindings were upstreamed, and so can be set + * unconditionally where `i` is in riscv,isa on DT systems. + */ + if (acpi_disabled) { + set_bit(RISCV_ISA_EXT_ZICSR, isainfo->isa); + set_bit(RISCV_ISA_EXT_ZIFENCEI, isainfo->isa); + set_bit(RISCV_ISA_EXT_ZICNTR, isainfo->isa); + set_bit(RISCV_ISA_EXT_ZIHPM, isainfo->isa); + } + /* * All "okay" hart should have same isa. Set HWCAP based on * common capabilities of every "okay" hart, in case they don't @@ -255,11 +340,14 @@ void __init riscv_fill_hwcap(void) elf_hwcap = this_hwcap; if (bitmap_empty(riscv_isa, RISCV_ISA_EXT_MAX)) - bitmap_copy(riscv_isa, this_isa, RISCV_ISA_EXT_MAX); + bitmap_copy(riscv_isa, isainfo->isa, RISCV_ISA_EXT_MAX); else - bitmap_and(riscv_isa, riscv_isa, this_isa, RISCV_ISA_EXT_MAX); + bitmap_and(riscv_isa, riscv_isa, isainfo->isa, RISCV_ISA_EXT_MAX); } + if (!acpi_disabled && rhct) + acpi_put_table((struct acpi_table_header *)rhct); + /* We don't support systems with F but without D, so mask those out * here. */ if ((elf_hwcap & COMPAT_HWCAP_ISA_F) && !(elf_hwcap & COMPAT_HWCAP_ISA_D)) { @@ -267,6 +355,17 @@ void __init riscv_fill_hwcap(void) elf_hwcap &= ~COMPAT_HWCAP_ISA_F; } + if (elf_hwcap & COMPAT_HWCAP_ISA_V) { + riscv_v_setup_vsize(); + /* + * ISA string in device tree might have 'v' flag, but + * CONFIG_RISCV_ISA_V is disabled in kernel. + * Clear V flag in elf_hwcap if CONFIG_RISCV_ISA_V is disabled. + */ + if (!IS_ENABLED(CONFIG_RISCV_ISA_V)) + elf_hwcap &= ~COMPAT_HWCAP_ISA_V; + } + memset(print_str, 0, sizeof(print_str)); for (i = 0, j = 0; i < NUM_ALPHA_EXTS; i++) if (riscv_isa[0] & BIT_MASK(i)) @@ -280,6 +379,18 @@ void __init riscv_fill_hwcap(void) pr_info("riscv: ELF capabilities %s\n", print_str); } +unsigned long riscv_get_elf_hwcap(void) +{ + unsigned long hwcap; + + hwcap = (elf_hwcap & ((1UL << RISCV_ISA_EXT_BASE) - 1)); + + if (!riscv_v_vstate_ctrl_user_allowed()) + hwcap &= ~COMPAT_HWCAP_ISA_V; + + return hwcap; +} + #ifdef CONFIG_RISCV_ALTERNATIVE /* * Alternative patch sites consider 48 bits when determining when to patch diff --git a/arch/riscv/kernel/entry.S b/arch/riscv/kernel/entry.S index 3fbb100bc9e4a362efa74503d3182aefc5b38dad..143a2bb3e69760b00aebae5be78d08475f98792a 100644 --- a/arch/riscv/kernel/entry.S +++ b/arch/riscv/kernel/entry.S @@ -48,10 +48,10 @@ _save_context: * Disable user-mode memory access as it should only be set in the * actual user copy routines. * - * Disable the FPU to detect illegal usage of floating point in kernel - * space. + * Disable the FPU/Vector to detect illegal usage of floating point + * or vector in kernel space. */ - li t0, SR_SUM | SR_FS + li t0, SR_SUM | SR_FS_VS REG_L s0, TASK_TI_USER_SP(tp) csrrc s1, CSR_STATUS, t0 @@ -348,6 +348,6 @@ SYM_CODE_END(excp_vect_table) #ifndef CONFIG_MMU SYM_CODE_START(__user_rt_sigreturn) li a7, __NR_rt_sigreturn - scall + ecall SYM_CODE_END(__user_rt_sigreturn) #endif diff --git a/arch/riscv/kernel/head.S b/arch/riscv/kernel/head.S index 4bf6c449d78b6a0719bfb3c7e9bbed927b71deb2..11c3b94c4534f907571462f8201e1ae239321269 100644 --- a/arch/riscv/kernel/head.S +++ b/arch/riscv/kernel/head.S @@ -140,10 +140,10 @@ secondary_start_sbi: .option pop /* - * Disable FPU to detect illegal usage of - * floating point in kernel space + * Disable FPU & VECTOR to detect illegal usage of + * floating point or vector in kernel space */ - li t0, SR_FS + li t0, SR_FS_VS csrc CSR_STATUS, t0 /* Set trap vector to spin forever to help debug */ @@ -234,10 +234,10 @@ pmp_done: .option pop /* - * Disable FPU to detect illegal usage of - * floating point in kernel space + * Disable FPU & VECTOR to detect illegal usage of + * floating point or vector in kernel space */ - li t0, SR_FS + li t0, SR_FS_VS csrc CSR_STATUS, t0 #ifdef CONFIG_RISCV_BOOT_SPINWAIT @@ -301,6 +301,7 @@ clear_bss_done: la tp, init_task la sp, init_thread_union + THREAD_SIZE XIP_FIXUP_OFFSET sp + addi sp, sp, -PT_SIZE_ON_STACK #ifdef CONFIG_BUILTIN_DTB la a0, __dtb_start XIP_FIXUP_OFFSET a0 @@ -318,6 +319,7 @@ clear_bss_done: /* Restore C environment */ la tp, init_task la sp, init_thread_union + THREAD_SIZE + addi sp, sp, -PT_SIZE_ON_STACK #ifdef CONFIG_KASAN call kasan_early_init @@ -392,7 +394,7 @@ ENTRY(reset_regs) #ifdef CONFIG_FPU csrr t0, CSR_MISA andi t0, t0, (COMPAT_HWCAP_ISA_F | COMPAT_HWCAP_ISA_D) - beqz t0, .Lreset_regs_done + beqz t0, .Lreset_regs_done_fpu li t1, SR_FS csrs CSR_STATUS, t1 @@ -430,8 +432,31 @@ ENTRY(reset_regs) fmv.s.x f31, zero csrw fcsr, 0 /* note that the caller must clear SR_FS */ +.Lreset_regs_done_fpu: #endif /* CONFIG_FPU */ -.Lreset_regs_done: + +#ifdef CONFIG_RISCV_ISA_V + csrr t0, CSR_MISA + li t1, COMPAT_HWCAP_ISA_V + and t0, t0, t1 + beqz t0, .Lreset_regs_done_vector + + /* + * Clear vector registers and reset vcsr + * VLMAX has a defined value, VLEN is a constant, + * and this form of vsetvli is defined to set vl to VLMAX. + */ + li t1, SR_VS + csrs CSR_STATUS, t1 + csrs CSR_VCSR, x0 + vsetvli t1, x0, e8, m8, ta, ma + vmv.v.i v0, 0 + vmv.v.i v8, 0 + vmv.v.i v16, 0 + vmv.v.i v24, 0 + /* note that the caller must clear SR_VS */ +.Lreset_regs_done_vector: +#endif /* CONFIG_RISCV_ISA_V */ ret END(reset_regs) #endif /* CONFIG_RISCV_M_MODE */ diff --git a/arch/riscv/kernel/hibernate-asm.S b/arch/riscv/kernel/hibernate-asm.S index effaf5ca5da0e44fc94142031dbade082d396187..d698dd7df637ba8ad9263e2312f896c268a58b2d 100644 --- a/arch/riscv/kernel/hibernate-asm.S +++ b/arch/riscv/kernel/hibernate-asm.S @@ -28,7 +28,6 @@ ENTRY(__hibernate_cpu_resume) REG_L a0, hibernate_cpu_context - suspend_restore_csrs suspend_restore_regs /* Return zero value. */ @@ -50,7 +49,7 @@ ENTRY(hibernate_restore_image) REG_L s4, restore_pblist REG_L a1, relocated_restore_code - jalr a1 + jr a1 END(hibernate_restore_image) /* @@ -73,5 +72,5 @@ ENTRY(hibernate_core_restore_code) REG_L s4, HIBERN_PBE_NEXT(s4) bnez s4, .Lcopy - jalr s2 + jr s2 END(hibernate_core_restore_code) diff --git a/arch/riscv/kernel/hibernate.c b/arch/riscv/kernel/hibernate.c index 264b2dcdd67e31cd872b158ada55c6a2d90997fe..671b686c0158767432d7146e99a751e803e2c029 100644 --- a/arch/riscv/kernel/hibernate.c +++ b/arch/riscv/kernel/hibernate.c @@ -80,7 +80,6 @@ int pfn_is_nosave(unsigned long pfn) void notrace save_processor_state(void) { - WARN_ON(num_online_cpus() != 1); } void notrace restore_processor_state(void) diff --git a/arch/riscv/kernel/irq.c b/arch/riscv/kernel/irq.c index eb9a68a539e66292fa655e9a7ce1348e561a2ab8..d0577cc6a0813f8b05661e25e701902492f75ec5 100644 --- a/arch/riscv/kernel/irq.c +++ b/arch/riscv/kernel/irq.c @@ -11,6 +11,9 @@ #include #include #include +#include +#include +#include static struct fwnode_handle *(*__get_intc_node)(void); @@ -28,6 +31,70 @@ struct fwnode_handle *riscv_get_intc_hwnode(void) } EXPORT_SYMBOL_GPL(riscv_get_intc_hwnode); +#ifdef CONFIG_IRQ_STACKS +#include + +DEFINE_PER_CPU(ulong *, irq_stack_ptr); + +#ifdef CONFIG_VMAP_STACK +static void init_irq_stacks(void) +{ + int cpu; + ulong *p; + + for_each_possible_cpu(cpu) { + p = arch_alloc_vmap_stack(IRQ_STACK_SIZE, cpu_to_node(cpu)); + per_cpu(irq_stack_ptr, cpu) = p; + } +} +#else +/* irq stack only needs to be 16 byte aligned - not IRQ_STACK_SIZE aligned. */ +DEFINE_PER_CPU_ALIGNED(ulong [IRQ_STACK_SIZE/sizeof(ulong)], irq_stack); + +static void init_irq_stacks(void) +{ + int cpu; + + for_each_possible_cpu(cpu) + per_cpu(irq_stack_ptr, cpu) = per_cpu(irq_stack, cpu); +} +#endif /* CONFIG_VMAP_STACK */ + +#ifdef CONFIG_HAVE_SOFTIRQ_ON_OWN_STACK +void do_softirq_own_stack(void) +{ +#ifdef CONFIG_IRQ_STACKS + if (on_thread_stack()) { + ulong *sp = per_cpu(irq_stack_ptr, smp_processor_id()) + + IRQ_STACK_SIZE/sizeof(ulong); + __asm__ __volatile( + "addi sp, sp, -"RISCV_SZPTR "\n" + REG_S" ra, (sp) \n" + "addi sp, sp, -"RISCV_SZPTR "\n" + REG_S" s0, (sp) \n" + "addi s0, sp, 2*"RISCV_SZPTR "\n" + "move sp, %[sp] \n" + "call __do_softirq \n" + "addi sp, s0, -2*"RISCV_SZPTR"\n" + REG_L" s0, (sp) \n" + "addi sp, sp, "RISCV_SZPTR "\n" + REG_L" ra, (sp) \n" + "addi sp, sp, "RISCV_SZPTR "\n" + : + : [sp] "r" (sp) + : "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", + "t0", "t1", "t2", "t3", "t4", "t5", "t6", + "memory"); + } else +#endif + __do_softirq(); +} +#endif /* CONFIG_HAVE_SOFTIRQ_ON_OWN_STACK */ + +#else +static void init_irq_stacks(void) {} +#endif /* CONFIG_IRQ_STACKS */ + int arch_show_interrupts(struct seq_file *p, int prec) { show_ipi_stats(p, prec); @@ -36,6 +103,7 @@ int arch_show_interrupts(struct seq_file *p, int prec) void __init init_IRQ(void) { + init_irq_stacks(); irqchip_init(); if (!handle_arch_irq) panic("No interrupt controller found."); diff --git a/arch/riscv/kernel/mcount.S b/arch/riscv/kernel/mcount.S index 30102aadc4d73ce463dce7b88bc7e73c124a109c..8a6e5a9e842a68bf056ed30738defd9b48f10921 100644 --- a/arch/riscv/kernel/mcount.S +++ b/arch/riscv/kernel/mcount.S @@ -65,13 +65,8 @@ ENTRY(return_to_handler) * So alternatively we check the *old* frame pointer position, that is, the * value stored in -16(s0) on entry, and the s0 on return. */ -#ifdef HAVE_FUNCTION_GRAPH_FP_TEST - mv t6, s0 -#endif SAVE_RET_ABI_STATE -#ifdef HAVE_FUNCTION_GRAPH_FP_TEST - mv a0, t6 -#endif + mv a0, sp call ftrace_return_to_handler mv a2, a0 RESTORE_RET_ABI_STATE diff --git a/arch/riscv/kernel/probes/uprobes.c b/arch/riscv/kernel/probes/uprobes.c index c976a21cd4bd5b20cd5030995335c601202dad01..194f166b2cc40e77b3bcef5dabe6ca9c01d86bd9 100644 --- a/arch/riscv/kernel/probes/uprobes.c +++ b/arch/riscv/kernel/probes/uprobes.c @@ -67,6 +67,7 @@ int arch_uprobe_post_xol(struct arch_uprobe *auprobe, struct pt_regs *regs) struct uprobe_task *utask = current->utask; WARN_ON_ONCE(current->thread.bad_cause != UPROBE_TRAP_NR); + current->thread.bad_cause = utask->autask.saved_cause; instruction_pointer_set(regs, utask->vaddr + auprobe->insn_size); @@ -102,6 +103,7 @@ void arch_uprobe_abort_xol(struct arch_uprobe *auprobe, struct pt_regs *regs) { struct uprobe_task *utask = current->utask; + current->thread.bad_cause = utask->autask.saved_cause; /* * Task has received a fatal signal, so reset back to probbed * address. diff --git a/arch/riscv/kernel/process.c b/arch/riscv/kernel/process.c index e2a06006673024f095b1355d95171c03bcceb9e4..e32d737e039fd477c33861da55705b86dbe5f53f 100644 --- a/arch/riscv/kernel/process.c +++ b/arch/riscv/kernel/process.c @@ -24,6 +24,7 @@ #include #include #include +#include register unsigned long gp_in_global __asm__("gp"); @@ -146,12 +147,29 @@ void flush_thread(void) fstate_off(current, task_pt_regs(current)); memset(¤t->thread.fstate, 0, sizeof(current->thread.fstate)); #endif +#ifdef CONFIG_RISCV_ISA_V + /* Reset vector state */ + riscv_v_vstate_ctrl_init(current); + riscv_v_vstate_off(task_pt_regs(current)); + kfree(current->thread.vstate.datap); + memset(¤t->thread.vstate, 0, sizeof(struct __riscv_v_ext_state)); +#endif +} + +void arch_release_task_struct(struct task_struct *tsk) +{ + /* Free the vector context of datap. */ + if (has_vector()) + kfree(tsk->thread.vstate.datap); } int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) { fstate_save(src, task_pt_regs(src)); *dst = *src; + /* clear entire V context, including datap for a new task */ + memset(&dst->thread.vstate, 0, sizeof(struct __riscv_v_ext_state)); + return 0; } @@ -176,6 +194,8 @@ int copy_thread(struct task_struct *p, const struct kernel_clone_args *args) p->thread.s[1] = (unsigned long)args->fn_arg; } else { *childregs = *(current_pt_regs()); + /* Turn off status.VS */ + riscv_v_vstate_off(childregs); if (usp) /* User fork */ childregs->sp = usp; if (clone_flags & CLONE_SETTLS) diff --git a/arch/riscv/kernel/ptrace.c b/arch/riscv/kernel/ptrace.c index 23c48b14a0e77804a3ab6afad776a924325109ab..1d572cf3140f0bf2a731ed7b88aebe0018830a2f 100644 --- a/arch/riscv/kernel/ptrace.c +++ b/arch/riscv/kernel/ptrace.c @@ -7,6 +7,7 @@ * Copied from arch/tile/kernel/ptrace.c */ +#include #include #include #include @@ -24,6 +25,9 @@ enum riscv_regset { #ifdef CONFIG_FPU REGSET_F, #endif +#ifdef CONFIG_RISCV_ISA_V + REGSET_V, +#endif }; static int riscv_gpr_get(struct task_struct *target, @@ -80,6 +84,61 @@ static int riscv_fpr_set(struct task_struct *target, } #endif +#ifdef CONFIG_RISCV_ISA_V +static int riscv_vr_get(struct task_struct *target, + const struct user_regset *regset, + struct membuf to) +{ + struct __riscv_v_ext_state *vstate = &target->thread.vstate; + + if (!riscv_v_vstate_query(task_pt_regs(target))) + return -EINVAL; + + /* + * Ensure the vector registers have been saved to the memory before + * copying them to membuf. + */ + if (target == current) + riscv_v_vstate_save(current, task_pt_regs(current)); + + /* Copy vector header from vstate. */ + membuf_write(&to, vstate, offsetof(struct __riscv_v_ext_state, datap)); + membuf_zero(&to, sizeof(vstate->datap)); + + /* Copy all the vector registers from vstate. */ + return membuf_write(&to, vstate->datap, riscv_v_vsize); +} + +static int riscv_vr_set(struct task_struct *target, + const struct user_regset *regset, + unsigned int pos, unsigned int count, + const void *kbuf, const void __user *ubuf) +{ + int ret, size; + struct __riscv_v_ext_state *vstate = &target->thread.vstate; + + if (!riscv_v_vstate_query(task_pt_regs(target))) + return -EINVAL; + + /* Copy rest of the vstate except datap */ + ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, vstate, 0, + offsetof(struct __riscv_v_ext_state, datap)); + if (unlikely(ret)) + return ret; + + /* Skip copy datap. */ + size = sizeof(vstate->datap); + count -= size; + ubuf += size; + + /* Copy all the vector registers. */ + pos = 0; + ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, vstate->datap, + 0, riscv_v_vsize); + return ret; +} +#endif + static const struct user_regset riscv_user_regset[] = { [REGSET_X] = { .core_note_type = NT_PRSTATUS, @@ -99,6 +158,17 @@ static const struct user_regset riscv_user_regset[] = { .set = riscv_fpr_set, }, #endif +#ifdef CONFIG_RISCV_ISA_V + [REGSET_V] = { + .core_note_type = NT_RISCV_VECTOR, + .align = 16, + .n = ((32 * RISCV_MAX_VLENB) + + sizeof(struct __riscv_v_ext_state)) / sizeof(__u32), + .size = sizeof(__u32), + .regset_get = riscv_vr_get, + .set = riscv_vr_set, + }, +#endif }; static const struct user_regset_view riscv_user_native_view = { diff --git a/arch/riscv/kernel/setup.c b/arch/riscv/kernel/setup.c index 36b0260575039b1a937246f96e149104b60a6794..971fe776e2f8b675b2ef2e8978919d798746cfa3 100644 --- a/arch/riscv/kernel/setup.c +++ b/arch/riscv/kernel/setup.c @@ -8,6 +8,7 @@ * Nick Kossifidis */ +#include #include #include #include @@ -21,6 +22,7 @@ #include #include +#include #include #include #include @@ -262,6 +264,8 @@ static void __init parse_dtb(void) #endif } +extern void __init init_rt_signal_env(void); + void __init setup_arch(char **cmdline_p) { parse_dtb(); @@ -270,11 +274,16 @@ void __init setup_arch(char **cmdline_p) *cmdline_p = boot_command_line; early_ioremap_setup(); + sbi_init(); jump_label_init(); parse_early_param(); efi_init(); paging_init(); + + /* Parse the ACPI tables for possible boot-time configuration */ + acpi_boot_table_init(); + #if IS_ENABLED(CONFIG_BUILTIN_DTB) unflatten_and_copy_device_tree(); #else @@ -283,7 +292,6 @@ void __init setup_arch(char **cmdline_p) misc_mem_init(); init_resources(); - sbi_init(); #ifdef CONFIG_KASAN kasan_init(); @@ -293,8 +301,12 @@ void __init setup_arch(char **cmdline_p) setup_smp(); #endif + if (!acpi_disabled) + acpi_init_rintc_map(); + riscv_init_cbo_blocksizes(); riscv_fill_hwcap(); + init_rt_signal_env(); apply_boot_alternatives(); if (IS_ENABLED(CONFIG_RISCV_ISA_ZICBOM) && riscv_isa_extension_available(NULL, ZICBOM)) diff --git a/arch/riscv/kernel/signal.c b/arch/riscv/kernel/signal.c index 9aff9d720590d05aec4efcd957a0c270b2e978bc..180d951d362418ee00ab1361fa15eb407446c1f7 100644 --- a/arch/riscv/kernel/signal.c +++ b/arch/riscv/kernel/signal.c @@ -19,10 +19,14 @@ #include #include #include +#include #include #include +unsigned long signal_minsigstksz __ro_after_init; + extern u32 __user_rt_sigreturn[2]; +static size_t riscv_v_sc_size __ro_after_init; #define DEBUG_SIG 0 @@ -40,26 +44,13 @@ static long restore_fp_state(struct pt_regs *regs, { long err; struct __riscv_d_ext_state __user *state = &sc_fpregs->d; - size_t i; err = __copy_from_user(¤t->thread.fstate, state, sizeof(*state)); if (unlikely(err)) return err; fstate_restore(current, regs); - - /* We support no other extension state at this time. */ - for (i = 0; i < ARRAY_SIZE(sc_fpregs->q.reserved); i++) { - u32 value; - - err = __get_user(value, &sc_fpregs->q.reserved[i]); - if (unlikely(err)) - break; - if (value != 0) - return -EINVAL; - } - - return err; + return 0; } static long save_fp_state(struct pt_regs *regs, @@ -67,52 +58,186 @@ static long save_fp_state(struct pt_regs *regs, { long err; struct __riscv_d_ext_state __user *state = &sc_fpregs->d; - size_t i; fstate_save(current, regs); err = __copy_to_user(state, ¤t->thread.fstate, sizeof(*state)); + return err; +} +#else +#define save_fp_state(task, regs) (0) +#define restore_fp_state(task, regs) (0) +#endif + +#ifdef CONFIG_RISCV_ISA_V + +static long save_v_state(struct pt_regs *regs, void __user **sc_vec) +{ + struct __riscv_ctx_hdr __user *hdr; + struct __sc_riscv_v_state __user *state; + void __user *datap; + long err; + + hdr = *sc_vec; + /* Place state to the user's signal context space after the hdr */ + state = (struct __sc_riscv_v_state __user *)(hdr + 1); + /* Point datap right after the end of __sc_riscv_v_state */ + datap = state + 1; + + /* datap is designed to be 16 byte aligned for better performance */ + WARN_ON(unlikely(!IS_ALIGNED((unsigned long)datap, 16))); + + riscv_v_vstate_save(current, regs); + /* Copy everything of vstate but datap. */ + err = __copy_to_user(&state->v_state, ¤t->thread.vstate, + offsetof(struct __riscv_v_ext_state, datap)); + /* Copy the pointer datap itself. */ + err |= __put_user(datap, &state->v_state.datap); + /* Copy the whole vector content to user space datap. */ + err |= __copy_to_user(datap, current->thread.vstate.datap, riscv_v_vsize); + /* Copy magic to the user space after saving all vector conetext */ + err |= __put_user(RISCV_V_MAGIC, &hdr->magic); + err |= __put_user(riscv_v_sc_size, &hdr->size); if (unlikely(err)) return err; - /* We support no other extension state at this time. */ - for (i = 0; i < ARRAY_SIZE(sc_fpregs->q.reserved); i++) { - err = __put_user(0, &sc_fpregs->q.reserved[i]); - if (unlikely(err)) - break; - } + /* Only progress the sv_vec if everything has done successfully */ + *sc_vec += riscv_v_sc_size; + return 0; +} + +/* + * Restore Vector extension context from the user's signal frame. This function + * assumes a valid extension header. So magic and size checking must be done by + * the caller. + */ +static long __restore_v_state(struct pt_regs *regs, void __user *sc_vec) +{ + long err; + struct __sc_riscv_v_state __user *state = sc_vec; + void __user *datap; + + /* Copy everything of __sc_riscv_v_state except datap. */ + err = __copy_from_user(¤t->thread.vstate, &state->v_state, + offsetof(struct __riscv_v_ext_state, datap)); + if (unlikely(err)) + return err; + + /* Copy the pointer datap itself. */ + err = __get_user(datap, &state->v_state.datap); + if (unlikely(err)) + return err; + /* + * Copy the whole vector content from user space datap. Use + * copy_from_user to prevent information leak. + */ + err = copy_from_user(current->thread.vstate.datap, datap, riscv_v_vsize); + if (unlikely(err)) + return err; + + riscv_v_vstate_restore(current, regs); return err; } #else -#define save_fp_state(task, regs) (0) -#define restore_fp_state(task, regs) (0) +#define save_v_state(task, regs) (0) +#define __restore_v_state(task, regs) (0) #endif static long restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc) { + void __user *sc_ext_ptr = &sc->sc_extdesc.hdr; + __u32 rsvd; long err; /* sc_regs is structured the same as the start of pt_regs */ err = __copy_from_user(regs, &sc->sc_regs, sizeof(sc->sc_regs)); + if (unlikely(err)) + return err; + /* Restore the floating-point state. */ - if (has_fpu()) - err |= restore_fp_state(regs, &sc->sc_fpregs); + if (has_fpu()) { + err = restore_fp_state(regs, &sc->sc_fpregs); + if (unlikely(err)) + return err; + } + + /* Check the reserved word before extensions parsing */ + err = __get_user(rsvd, &sc->sc_extdesc.reserved); + if (unlikely(err)) + return err; + if (unlikely(rsvd)) + return -EINVAL; + + while (!err) { + __u32 magic, size; + struct __riscv_ctx_hdr __user *head = sc_ext_ptr; + + err |= __get_user(magic, &head->magic); + err |= __get_user(size, &head->size); + if (unlikely(err)) + return err; + + sc_ext_ptr += sizeof(*head); + switch (magic) { + case END_MAGIC: + if (size != END_HDR_SIZE) + return -EINVAL; + + return 0; + case RISCV_V_MAGIC: + if (!has_vector() || !riscv_v_vstate_query(regs) || + size != riscv_v_sc_size) + return -EINVAL; + + err = __restore_v_state(regs, sc_ext_ptr); + break; + default: + return -EINVAL; + } + sc_ext_ptr = (void __user *)head + size; + } return err; } +static size_t get_rt_frame_size(bool cal_all) +{ + struct rt_sigframe __user *frame; + size_t frame_size; + size_t total_context_size = 0; + + frame_size = sizeof(*frame); + + if (has_vector()) { + if (cal_all || riscv_v_vstate_query(task_pt_regs(current))) + total_context_size += riscv_v_sc_size; + } + /* + * Preserved a __riscv_ctx_hdr for END signal context header if an + * extension uses __riscv_extra_ext_header + */ + if (total_context_size) + total_context_size += sizeof(struct __riscv_ctx_hdr); + + frame_size += total_context_size; + + frame_size = round_up(frame_size, 16); + return frame_size; +} + SYSCALL_DEFINE0(rt_sigreturn) { struct pt_regs *regs = current_pt_regs(); struct rt_sigframe __user *frame; struct task_struct *task; sigset_t set; + size_t frame_size = get_rt_frame_size(false); /* Always make any pending restarted system calls return -EINTR */ current->restart_block.fn = do_no_restart_syscall; frame = (struct rt_sigframe __user *)regs->sp; - if (!access_ok(frame, sizeof(*frame))) + if (!access_ok(frame, frame_size)) goto badframe; if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) @@ -146,12 +271,23 @@ static long setup_sigcontext(struct rt_sigframe __user *frame, struct pt_regs *regs) { struct sigcontext __user *sc = &frame->uc.uc_mcontext; + struct __riscv_ctx_hdr __user *sc_ext_ptr = &sc->sc_extdesc.hdr; long err; + /* sc_regs is structured the same as the start of pt_regs */ err = __copy_to_user(&sc->sc_regs, regs, sizeof(sc->sc_regs)); /* Save the floating-point state. */ if (has_fpu()) err |= save_fp_state(regs, &sc->sc_fpregs); + /* Save the vector state. */ + if (has_vector() && riscv_v_vstate_query(regs)) + err |= save_v_state(regs, (void __user **)&sc_ext_ptr); + /* Write zero to fp-reserved space and check it on restore_sigcontext */ + err |= __put_user(0, &sc->sc_extdesc.reserved); + /* And put END __riscv_ctx_hdr at the end. */ + err |= __put_user(END_MAGIC, &sc_ext_ptr->magic); + err |= __put_user(END_HDR_SIZE, &sc_ext_ptr->size); + return err; } @@ -175,6 +311,13 @@ static inline void __user *get_sigframe(struct ksignal *ksig, /* Align the stack frame. */ sp &= ~0xfUL; + /* + * Fail if the size of the altstack is not large enough for the + * sigframe construction. + */ + if (current->sas_ss_size && sp < current->sas_ss_sp) + return (void __user __force *)-1UL; + return (void __user *)sp; } @@ -184,9 +327,10 @@ static int setup_rt_frame(struct ksignal *ksig, sigset_t *set, struct rt_sigframe __user *frame; long err = 0; unsigned long __maybe_unused addr; + size_t frame_size = get_rt_frame_size(false); - frame = get_sigframe(ksig, regs, sizeof(*frame)); - if (!access_ok(frame, sizeof(*frame))) + frame = get_sigframe(ksig, regs, frame_size); + if (!access_ok(frame, frame_size)) return -EFAULT; err |= copy_siginfo_to_user(&frame->info, &ksig->info); @@ -319,3 +463,23 @@ void arch_do_signal_or_restart(struct pt_regs *regs) */ restore_saved_sigmask(); } + +void init_rt_signal_env(void); +void __init init_rt_signal_env(void) +{ + riscv_v_sc_size = sizeof(struct __riscv_ctx_hdr) + + sizeof(struct __sc_riscv_v_state) + riscv_v_vsize; + /* + * Determine the stack space required for guaranteed signal delivery. + * The signal_minsigstksz will be populated into the AT_MINSIGSTKSZ entry + * in the auxiliary array at process startup. + */ + signal_minsigstksz = get_rt_frame_size(true); +} + +#ifdef CONFIG_DYNAMIC_SIGFRAME +bool sigaltstack_size_valid(size_t ss_size) +{ + return ss_size > get_rt_frame_size(false); +} +#endif /* CONFIG_DYNAMIC_SIGFRAME */ diff --git a/arch/riscv/kernel/smp.c b/arch/riscv/kernel/smp.c index 23e533766a49c706b2525043a89ba5f8717537e0..85bbce0f758cbcc6f3204a14a8600c13f1d2f476 100644 --- a/arch/riscv/kernel/smp.c +++ b/arch/riscv/kernel/smp.c @@ -58,7 +58,6 @@ int riscv_hartid_to_cpuid(unsigned long hartid) if (cpuid_to_hartid_map(i) == hartid) return i; - pr_err("Couldn't find cpu id for hartid [%lu]\n", hartid); return -ENOENT; } diff --git a/arch/riscv/kernel/smpboot.c b/arch/riscv/kernel/smpboot.c index 445a4efee267d315e51b2b733881ff04c9250f99..f4d6acb38dd0dfd81653425f9717f976703ca232 100644 --- a/arch/riscv/kernel/smpboot.c +++ b/arch/riscv/kernel/smpboot.c @@ -8,6 +8,7 @@ * Copyright (C) 2017 SiFive */ +#include #include #include #include @@ -31,6 +32,8 @@ #include #include #include +#include +#include #include "head.h" @@ -70,7 +73,73 @@ void __init smp_prepare_cpus(unsigned int max_cpus) } } -void __init setup_smp(void) +#ifdef CONFIG_ACPI +static unsigned int cpu_count = 1; + +static int __init acpi_parse_rintc(union acpi_subtable_headers *header, const unsigned long end) +{ + unsigned long hart; + static bool found_boot_cpu; + struct acpi_madt_rintc *processor = (struct acpi_madt_rintc *)header; + + /* + * Each RINTC structure in MADT will have a flag. If ACPI_MADT_ENABLED + * bit in the flag is not enabled, it means OS should not try to enable + * the cpu to which RINTC belongs. + */ + if (!(processor->flags & ACPI_MADT_ENABLED)) + return 0; + + if (BAD_MADT_ENTRY(processor, end)) + return -EINVAL; + + acpi_table_print_madt_entry(&header->common); + + hart = processor->hart_id; + if (hart == INVALID_HARTID) { + pr_warn("Invalid hartid\n"); + return 0; + } + + if (hart == cpuid_to_hartid_map(0)) { + BUG_ON(found_boot_cpu); + found_boot_cpu = true; + early_map_cpu_to_node(0, acpi_numa_get_nid(cpu_count)); + return 0; + } + + if (cpu_count >= NR_CPUS) { + pr_warn("NR_CPUS is too small for the number of ACPI tables.\n"); + return 0; + } + + cpuid_to_hartid_map(cpu_count) = hart; + early_map_cpu_to_node(cpu_count, acpi_numa_get_nid(cpu_count)); + cpu_count++; + + return 0; +} + +static void __init acpi_parse_and_init_cpus(void) +{ + int cpuid; + + cpu_set_ops(0); + + acpi_table_parse_madt(ACPI_MADT_TYPE_RINTC, acpi_parse_rintc, 0); + + for (cpuid = 1; cpuid < nr_cpu_ids; cpuid++) { + if (cpuid_to_hartid_map(cpuid) != INVALID_HARTID) { + cpu_set_ops(cpuid); + set_cpu_possible(cpuid, true); + } + } +} +#else +#define acpi_parse_and_init_cpus(...) do { } while (0) +#endif + +static void __init of_parse_and_init_cpus(void) { struct device_node *dn; unsigned long hart; @@ -81,7 +150,7 @@ void __init setup_smp(void) cpu_set_ops(0); for_each_of_cpu_node(dn) { - rc = riscv_of_processor_hartid(dn, &hart); + rc = riscv_early_of_processor_hartid(dn, &hart); if (rc < 0) continue; @@ -116,6 +185,14 @@ void __init setup_smp(void) } } +void __init setup_smp(void) +{ + if (acpi_disabled) + of_parse_and_init_cpus(); + else + acpi_parse_and_init_cpus(); +} + static int start_secondary_cpu(int cpu, struct task_struct *tidle) { if (cpu_ops[cpu]->cpu_start) @@ -161,14 +238,20 @@ asmlinkage __visible void smp_callin(void) mmgrab(mm); current->active_mm = mm; - riscv_ipi_enable(); - store_cpu_topology(curr_cpuid); notify_cpu_starting(curr_cpuid); + + riscv_ipi_enable(); + numa_add_cpu(curr_cpuid); set_cpu_online(curr_cpuid, 1); probe_vendor_features(curr_cpuid); + if (has_vector()) { + if (riscv_v_setup_vsize()) + elf_hwcap &= ~COMPAT_HWCAP_ISA_V; + } + /* * Remote TLB flushes are ignored while the CPU is offline, so emit * a local TLB flush right now just in case. diff --git a/arch/riscv/kernel/sys_riscv.c b/arch/riscv/kernel/sys_riscv.c index 5db29683ebee7a8cb8c115f221178c947cbbc230..26ef5526bfb4cc45e57096b536b75e5bb3116600 100644 --- a/arch/riscv/kernel/sys_riscv.c +++ b/arch/riscv/kernel/sys_riscv.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -121,6 +122,49 @@ static void hwprobe_arch_id(struct riscv_hwprobe *pair, pair->value = id; } +static void hwprobe_isa_ext0(struct riscv_hwprobe *pair, + const struct cpumask *cpus) +{ + int cpu; + u64 missing = 0; + + pair->value = 0; + if (has_fpu()) + pair->value |= RISCV_HWPROBE_IMA_FD; + + if (riscv_isa_extension_available(NULL, c)) + pair->value |= RISCV_HWPROBE_IMA_C; + + if (has_vector()) + pair->value |= RISCV_HWPROBE_IMA_V; + + /* + * Loop through and record extensions that 1) anyone has, and 2) anyone + * doesn't have. + */ + for_each_cpu(cpu, cpus) { + struct riscv_isainfo *isainfo = &hart_isa[cpu]; + + if (riscv_isa_extension_available(isainfo->isa, ZBA)) + pair->value |= RISCV_HWPROBE_EXT_ZBA; + else + missing |= RISCV_HWPROBE_EXT_ZBA; + + if (riscv_isa_extension_available(isainfo->isa, ZBB)) + pair->value |= RISCV_HWPROBE_EXT_ZBB; + else + missing |= RISCV_HWPROBE_EXT_ZBB; + + if (riscv_isa_extension_available(isainfo->isa, ZBS)) + pair->value |= RISCV_HWPROBE_EXT_ZBS; + else + missing |= RISCV_HWPROBE_EXT_ZBS; + } + + /* Now turn off reporting features if any CPU is missing it. */ + pair->value &= ~missing; +} + static u64 hwprobe_misaligned(const struct cpumask *cpus) { int cpu; @@ -164,13 +208,7 @@ static void hwprobe_one_pair(struct riscv_hwprobe *pair, break; case RISCV_HWPROBE_KEY_IMA_EXT_0: - pair->value = 0; - if (has_fpu()) - pair->value |= RISCV_HWPROBE_IMA_FD; - - if (riscv_isa_extension_available(NULL, c)) - pair->value |= RISCV_HWPROBE_IMA_C; - + hwprobe_isa_ext0(pair, cpus); break; case RISCV_HWPROBE_KEY_CPUPERF_0: diff --git a/arch/riscv/kernel/time.c b/arch/riscv/kernel/time.c index babaf3b48ba83172431edd3aef68f9e74dfe82ed..23641e82a9df2a244727d9e5b674f8c546299ea2 100644 --- a/arch/riscv/kernel/time.c +++ b/arch/riscv/kernel/time.c @@ -4,6 +4,7 @@ * Copyright (C) 2017 SiFive */ +#include #include #include #include @@ -18,17 +19,29 @@ EXPORT_SYMBOL_GPL(riscv_timebase); void __init time_init(void) { struct device_node *cpu; + struct acpi_table_rhct *rhct; + acpi_status status; u32 prop; - cpu = of_find_node_by_path("/cpus"); - if (!cpu || of_property_read_u32(cpu, "timebase-frequency", &prop)) - panic(KERN_WARNING "RISC-V system with no 'timebase-frequency' in DTS\n"); - of_node_put(cpu); - riscv_timebase = prop; + if (acpi_disabled) { + cpu = of_find_node_by_path("/cpus"); + if (!cpu || of_property_read_u32(cpu, "timebase-frequency", &prop)) + panic("RISC-V system with no 'timebase-frequency' in DTS\n"); + + of_node_put(cpu); + riscv_timebase = prop; + of_clk_init(NULL); + } else { + status = acpi_get_table(ACPI_SIG_RHCT, 0, (struct acpi_table_header **)&rhct); + if (ACPI_FAILURE(status)) + panic("RISC-V ACPI system with no RHCT table\n"); + + riscv_timebase = rhct->time_base_freq; + acpi_put_table((struct acpi_table_header *)rhct); + } lpj_fine = riscv_timebase / HZ; - of_clk_init(NULL); timer_probe(); tick_setup_hrtimer_broadcast(); diff --git a/arch/riscv/kernel/traps.c b/arch/riscv/kernel/traps.c index 8c258b78c925c21e1814d5704428d30085a1e70a..f910dfccbf5d2aaf5b838cdbfd809f8e937bdfd5 100644 --- a/arch/riscv/kernel/traps.c +++ b/arch/riscv/kernel/traps.c @@ -26,6 +26,8 @@ #include #include #include +#include +#include int show_unhandled_signals = 1; @@ -145,8 +147,35 @@ DO_ERROR_INFO(do_trap_insn_misaligned, SIGBUS, BUS_ADRALN, "instruction address misaligned"); DO_ERROR_INFO(do_trap_insn_fault, SIGSEGV, SEGV_ACCERR, "instruction access fault"); -DO_ERROR_INFO(do_trap_insn_illegal, - SIGILL, ILL_ILLOPC, "illegal instruction"); + +asmlinkage __visible __trap_section void do_trap_insn_illegal(struct pt_regs *regs) +{ + bool handled; + + if (user_mode(regs)) { + irqentry_enter_from_user_mode(regs); + + local_irq_enable(); + + handled = riscv_v_first_use_handler(regs); + + local_irq_disable(); + + if (!handled) + do_trap_error(regs, SIGILL, ILL_ILLOPC, regs->epc, + "Oops - illegal instruction"); + + irqentry_exit_to_user_mode(regs); + } else { + irqentry_state_t state = irqentry_nmi_enter(regs); + + do_trap_error(regs, SIGILL, ILL_ILLOPC, regs->epc, + "Oops - illegal instruction"); + + irqentry_nmi_exit(regs, state); + } +} + DO_ERROR_INFO(do_trap_load_fault, SIGSEGV, SEGV_ACCERR, "load access fault"); #ifndef CONFIG_RISCV_M_MODE @@ -273,6 +302,8 @@ asmlinkage __visible __trap_section void do_trap_ecall_u(struct pt_regs *regs) regs->epc += 4; regs->orig_a0 = regs->a0; + riscv_v_vstate_discard(regs); + syscall = syscall_enter_from_user_mode(regs, syscall); if (syscall < NR_syscalls) @@ -305,16 +336,46 @@ asmlinkage __visible noinstr void do_page_fault(struct pt_regs *regs) } #endif -asmlinkage __visible noinstr void do_irq(struct pt_regs *regs) +static void noinstr handle_riscv_irq(struct pt_regs *regs) { struct pt_regs *old_regs; - irqentry_state_t state = irqentry_enter(regs); irq_enter_rcu(); old_regs = set_irq_regs(regs); handle_arch_irq(regs); set_irq_regs(old_regs); irq_exit_rcu(); +} + +asmlinkage void noinstr do_irq(struct pt_regs *regs) +{ + irqentry_state_t state = irqentry_enter(regs); +#ifdef CONFIG_IRQ_STACKS + if (on_thread_stack()) { + ulong *sp = per_cpu(irq_stack_ptr, smp_processor_id()) + + IRQ_STACK_SIZE/sizeof(ulong); + __asm__ __volatile( + "addi sp, sp, -"RISCV_SZPTR "\n" + REG_S" ra, (sp) \n" + "addi sp, sp, -"RISCV_SZPTR "\n" + REG_S" s0, (sp) \n" + "addi s0, sp, 2*"RISCV_SZPTR "\n" + "move sp, %[sp] \n" + "move a0, %[regs] \n" + "call handle_riscv_irq \n" + "addi sp, s0, -2*"RISCV_SZPTR"\n" + REG_L" s0, (sp) \n" + "addi sp, sp, "RISCV_SZPTR "\n" + REG_L" ra, (sp) \n" + "addi sp, sp, "RISCV_SZPTR "\n" + : + : [sp] "r" (sp), [regs] "r" (regs) + : "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", + "t0", "t1", "t2", "t3", "t4", "t5", "t6", + "memory"); + } else +#endif + handle_riscv_irq(regs); irqentry_exit(regs, state); } diff --git a/arch/riscv/kernel/vdso.c b/arch/riscv/kernel/vdso.c index 9a68e7eaae4d47e573c7c96289ddbf325164721d..2cf76218a5bd02c8f148318f78abd648dab276bf 100644 --- a/arch/riscv/kernel/vdso.c +++ b/arch/riscv/kernel/vdso.c @@ -15,6 +15,7 @@ #include #include #include +#include enum vvar_pages { VVAR_DATA_PAGE_OFFSET, diff --git a/arch/riscv/kernel/vdso/rt_sigreturn.S b/arch/riscv/kernel/vdso/rt_sigreturn.S index 0573705eac76bc7b5f2698e027b826454a7e84fa..10438c7c626acc8034fa22d6765422fbc7b67f0b 100644 --- a/arch/riscv/kernel/vdso/rt_sigreturn.S +++ b/arch/riscv/kernel/vdso/rt_sigreturn.S @@ -11,6 +11,6 @@ ENTRY(__vdso_rt_sigreturn) .cfi_startproc .cfi_signal_frame li a7, __NR_rt_sigreturn - scall + ecall .cfi_endproc ENDPROC(__vdso_rt_sigreturn) diff --git a/arch/riscv/kernel/vector.c b/arch/riscv/kernel/vector.c new file mode 100644 index 0000000000000000000000000000000000000000..8d92fb6c522cc27ca3015550bcfa3afddb6c4909 --- /dev/null +++ b/arch/riscv/kernel/vector.c @@ -0,0 +1,277 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2023 SiFive + * Author: Andy Chiu + */ +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +static bool riscv_v_implicit_uacc = IS_ENABLED(CONFIG_RISCV_ISA_V_DEFAULT_ENABLE); + +unsigned long riscv_v_vsize __read_mostly; +EXPORT_SYMBOL_GPL(riscv_v_vsize); + +int riscv_v_setup_vsize(void) +{ + unsigned long this_vsize; + + /* There are 32 vector registers with vlenb length. */ + riscv_v_enable(); + this_vsize = csr_read(CSR_VLENB) * 32; + riscv_v_disable(); + + if (!riscv_v_vsize) { + riscv_v_vsize = this_vsize; + return 0; + } + + if (riscv_v_vsize != this_vsize) { + WARN(1, "RISCV_ISA_V only supports one vlenb on SMP systems"); + return -EOPNOTSUPP; + } + + return 0; +} + +static bool insn_is_vector(u32 insn_buf) +{ + u32 opcode = insn_buf & __INSN_OPCODE_MASK; + u32 width, csr; + + /* + * All V-related instructions, including CSR operations are 4-Byte. So, + * do not handle if the instruction length is not 4-Byte. + */ + if (unlikely(GET_INSN_LENGTH(insn_buf) != 4)) + return false; + + switch (opcode) { + case RVV_OPCODE_VECTOR: + return true; + case RVV_OPCODE_VL: + case RVV_OPCODE_VS: + width = RVV_EXRACT_VL_VS_WIDTH(insn_buf); + if (width == RVV_VL_VS_WIDTH_8 || width == RVV_VL_VS_WIDTH_16 || + width == RVV_VL_VS_WIDTH_32 || width == RVV_VL_VS_WIDTH_64) + return true; + + break; + case RVG_OPCODE_SYSTEM: + csr = RVG_EXTRACT_SYSTEM_CSR(insn_buf); + if ((csr >= CSR_VSTART && csr <= CSR_VCSR) || + (csr >= CSR_VL && csr <= CSR_VLENB)) + return true; + } + + return false; +} + +static int riscv_v_thread_zalloc(void) +{ + void *datap; + + datap = kzalloc(riscv_v_vsize, GFP_KERNEL); + if (!datap) + return -ENOMEM; + + current->thread.vstate.datap = datap; + memset(¤t->thread.vstate, 0, offsetof(struct __riscv_v_ext_state, + datap)); + return 0; +} + +#define VSTATE_CTRL_GET_CUR(x) ((x) & PR_RISCV_V_VSTATE_CTRL_CUR_MASK) +#define VSTATE_CTRL_GET_NEXT(x) (((x) & PR_RISCV_V_VSTATE_CTRL_NEXT_MASK) >> 2) +#define VSTATE_CTRL_MAKE_NEXT(x) (((x) << 2) & PR_RISCV_V_VSTATE_CTRL_NEXT_MASK) +#define VSTATE_CTRL_GET_INHERIT(x) (!!((x) & PR_RISCV_V_VSTATE_CTRL_INHERIT)) +static inline int riscv_v_ctrl_get_cur(struct task_struct *tsk) +{ + return VSTATE_CTRL_GET_CUR(tsk->thread.vstate_ctrl); +} + +static inline int riscv_v_ctrl_get_next(struct task_struct *tsk) +{ + return VSTATE_CTRL_GET_NEXT(tsk->thread.vstate_ctrl); +} + +static inline bool riscv_v_ctrl_test_inherit(struct task_struct *tsk) +{ + return VSTATE_CTRL_GET_INHERIT(tsk->thread.vstate_ctrl); +} + +static inline void riscv_v_ctrl_set(struct task_struct *tsk, int cur, int nxt, + bool inherit) +{ + unsigned long ctrl; + + ctrl = cur & PR_RISCV_V_VSTATE_CTRL_CUR_MASK; + ctrl |= VSTATE_CTRL_MAKE_NEXT(nxt); + if (inherit) + ctrl |= PR_RISCV_V_VSTATE_CTRL_INHERIT; + tsk->thread.vstate_ctrl = ctrl; +} + +bool riscv_v_vstate_ctrl_user_allowed(void) +{ + return riscv_v_ctrl_get_cur(current) == PR_RISCV_V_VSTATE_CTRL_ON; +} +EXPORT_SYMBOL_GPL(riscv_v_vstate_ctrl_user_allowed); + +bool riscv_v_first_use_handler(struct pt_regs *regs) +{ + u32 __user *epc = (u32 __user *)regs->epc; + u32 insn = (u32)regs->badaddr; + + /* Do not handle if V is not supported, or disabled */ + if (!(ELF_HWCAP & COMPAT_HWCAP_ISA_V)) + return false; + + /* If V has been enabled then it is not the first-use trap */ + if (riscv_v_vstate_query(regs)) + return false; + + /* Get the instruction */ + if (!insn) { + if (__get_user(insn, epc)) + return false; + } + + /* Filter out non-V instructions */ + if (!insn_is_vector(insn)) + return false; + + /* Sanity check. datap should be null by the time of the first-use trap */ + WARN_ON(current->thread.vstate.datap); + + /* + * Now we sure that this is a V instruction. And it executes in the + * context where VS has been off. So, try to allocate the user's V + * context and resume execution. + */ + if (riscv_v_thread_zalloc()) { + force_sig(SIGBUS); + return true; + } + riscv_v_vstate_on(regs); + riscv_v_vstate_restore(current, regs); + return true; +} + +void riscv_v_vstate_ctrl_init(struct task_struct *tsk) +{ + bool inherit; + int cur, next; + + if (!has_vector()) + return; + + next = riscv_v_ctrl_get_next(tsk); + if (!next) { + if (READ_ONCE(riscv_v_implicit_uacc)) + cur = PR_RISCV_V_VSTATE_CTRL_ON; + else + cur = PR_RISCV_V_VSTATE_CTRL_OFF; + } else { + cur = next; + } + /* Clear next mask if inherit-bit is not set */ + inherit = riscv_v_ctrl_test_inherit(tsk); + if (!inherit) + next = PR_RISCV_V_VSTATE_CTRL_DEFAULT; + + riscv_v_ctrl_set(tsk, cur, next, inherit); +} + +long riscv_v_vstate_ctrl_get_current(void) +{ + if (!has_vector()) + return -EINVAL; + + return current->thread.vstate_ctrl & PR_RISCV_V_VSTATE_CTRL_MASK; +} + +long riscv_v_vstate_ctrl_set_current(unsigned long arg) +{ + bool inherit; + int cur, next; + + if (!has_vector()) + return -EINVAL; + + if (arg & ~PR_RISCV_V_VSTATE_CTRL_MASK) + return -EINVAL; + + cur = VSTATE_CTRL_GET_CUR(arg); + switch (cur) { + case PR_RISCV_V_VSTATE_CTRL_OFF: + /* Do not allow user to turn off V if current is not off */ + if (riscv_v_ctrl_get_cur(current) != PR_RISCV_V_VSTATE_CTRL_OFF) + return -EPERM; + + break; + case PR_RISCV_V_VSTATE_CTRL_ON: + break; + case PR_RISCV_V_VSTATE_CTRL_DEFAULT: + cur = riscv_v_ctrl_get_cur(current); + break; + default: + return -EINVAL; + } + + next = VSTATE_CTRL_GET_NEXT(arg); + inherit = VSTATE_CTRL_GET_INHERIT(arg); + switch (next) { + case PR_RISCV_V_VSTATE_CTRL_DEFAULT: + case PR_RISCV_V_VSTATE_CTRL_OFF: + case PR_RISCV_V_VSTATE_CTRL_ON: + riscv_v_ctrl_set(current, cur, next, inherit); + return 0; + } + + return -EINVAL; +} + +#ifdef CONFIG_SYSCTL + +static struct ctl_table riscv_v_default_vstate_table[] = { + { + .procname = "riscv_v_default_allow", + .data = &riscv_v_implicit_uacc, + .maxlen = sizeof(riscv_v_implicit_uacc), + .mode = 0644, + .proc_handler = proc_dobool, + }, + { } +}; + +static int __init riscv_v_sysctl_init(void) +{ + if (has_vector()) + if (!register_sysctl("abi", riscv_v_default_vstate_table)) + return -EINVAL; + return 0; +} + +#else /* ! CONFIG_SYSCTL */ +static int __init riscv_v_sysctl_init(void) { return 0; } +#endif /* ! CONFIG_SYSCTL */ + +static int riscv_v_init(void) +{ + return riscv_v_sysctl_init(); +} +core_initcall(riscv_v_init); diff --git a/arch/riscv/kernel/vmlinux-xip.lds.S b/arch/riscv/kernel/vmlinux-xip.lds.S index eab9edc3b63147ec0d1205d0fde92989c5669cd5..50767647fbc649de81d7722528e9bcd116d88657 100644 --- a/arch/riscv/kernel/vmlinux-xip.lds.S +++ b/arch/riscv/kernel/vmlinux-xip.lds.S @@ -98,12 +98,6 @@ SECTIONS __soc_builtin_dtb_table_end = .; } - . = ALIGN(8); - .alternative : { - __alt_start = .; - *(.alternative) - __alt_end = .; - } __init_end = .; . = ALIGN(16); diff --git a/arch/riscv/kernel/vmlinux.lds.S b/arch/riscv/kernel/vmlinux.lds.S index e5f9f4677bbfdabd2f5af995f281267414422aad..492dd4b8f3d69a0bcdb6e133d47d6444e2e72804 100644 --- a/arch/riscv/kernel/vmlinux.lds.S +++ b/arch/riscv/kernel/vmlinux.lds.S @@ -85,11 +85,11 @@ SECTIONS INIT_DATA_SECTION(16) .init.pi : { - *(.init.pi*) + KEEP(*(.init.pi*)) } .init.bss : { - *(.init.bss) /* from the EFI stub */ + KEEP(*(.init.bss*)) /* from the EFI stub */ } .exit.data : { @@ -112,7 +112,7 @@ SECTIONS . = ALIGN(8); .alternative : { __alt_start = .; - *(.alternative) + KEEP(*(.alternative)) __alt_end = .; } __init_end = .; diff --git a/arch/riscv/kvm/Kconfig b/arch/riscv/kvm/Kconfig index 28891e583259c0e7d8fb9d9947235c5ac3151cfc..dfc237d7875b53bb2f3e7e716c1b85af8b335458 100644 --- a/arch/riscv/kvm/Kconfig +++ b/arch/riscv/kvm/Kconfig @@ -21,6 +21,10 @@ config KVM tristate "Kernel-based Virtual Machine (KVM) support (EXPERIMENTAL)" depends on RISCV_SBI && MMU select HAVE_KVM_EVENTFD + select HAVE_KVM_IRQCHIP + select HAVE_KVM_IRQFD + select HAVE_KVM_IRQ_ROUTING + select HAVE_KVM_MSI select HAVE_KVM_VCPU_ASYNC_IOCTL select KVM_GENERIC_DIRTYLOG_READ_PROTECT select KVM_GENERIC_HARDWARE_ENABLING diff --git a/arch/riscv/kvm/Makefile b/arch/riscv/kvm/Makefile index 8031b8912a0d0bb8bc3a640f0d8ec43fcd39cdf5..fee0671e2dc12d65e3faeb48f21d0493f06f556c 100644 --- a/arch/riscv/kvm/Makefile +++ b/arch/riscv/kvm/Makefile @@ -17,6 +17,7 @@ kvm-y += mmu.o kvm-y += vcpu.o kvm-y += vcpu_exit.o kvm-y += vcpu_fp.o +kvm-y += vcpu_vector.o kvm-y += vcpu_insn.o kvm-y += vcpu_switch.o kvm-y += vcpu_sbi.o @@ -27,3 +28,6 @@ kvm-y += vcpu_sbi_hsm.o kvm-y += vcpu_timer.o kvm-$(CONFIG_RISCV_PMU_SBI) += vcpu_pmu.o vcpu_sbi_pmu.o kvm-y += aia.o +kvm-y += aia_device.o +kvm-y += aia_aplic.o +kvm-y += aia_imsic.o diff --git a/arch/riscv/kvm/aia.c b/arch/riscv/kvm/aia.c index 4f1286fc7f17da1ee2caa4f1c4ae8d86e1de0764..585a3b42c52c69cc34662d9740e4378fcc475147 100644 --- a/arch/riscv/kvm/aia.c +++ b/arch/riscv/kvm/aia.c @@ -8,11 +8,49 @@ */ #include +#include +#include +#include #include +#include +#include #include +#include +struct aia_hgei_control { + raw_spinlock_t lock; + unsigned long free_bitmap; + struct kvm_vcpu *owners[BITS_PER_LONG]; +}; +static DEFINE_PER_CPU(struct aia_hgei_control, aia_hgei); +static int hgei_parent_irq; + +unsigned int kvm_riscv_aia_nr_hgei; +unsigned int kvm_riscv_aia_max_ids; DEFINE_STATIC_KEY_FALSE(kvm_riscv_aia_available); +static int aia_find_hgei(struct kvm_vcpu *owner) +{ + int i, hgei; + unsigned long flags; + struct aia_hgei_control *hgctrl = get_cpu_ptr(&aia_hgei); + + raw_spin_lock_irqsave(&hgctrl->lock, flags); + + hgei = -1; + for (i = 1; i <= kvm_riscv_aia_nr_hgei; i++) { + if (hgctrl->owners[i] == owner) { + hgei = i; + break; + } + } + + raw_spin_unlock_irqrestore(&hgctrl->lock, flags); + + put_cpu_ptr(&aia_hgei); + return hgei; +} + static void aia_set_hvictl(bool ext_irq_pending) { unsigned long hvictl; @@ -56,6 +94,7 @@ void kvm_riscv_vcpu_aia_sync_interrupts(struct kvm_vcpu *vcpu) bool kvm_riscv_vcpu_aia_has_interrupts(struct kvm_vcpu *vcpu, u64 mask) { + int hgei; unsigned long seip; if (!kvm_riscv_aia_available()) @@ -74,6 +113,10 @@ bool kvm_riscv_vcpu_aia_has_interrupts(struct kvm_vcpu *vcpu, u64 mask) if (!kvm_riscv_aia_initialized(vcpu->kvm) || !seip) return false; + hgei = aia_find_hgei(vcpu); + if (hgei > 0) + return !!(csr_read(CSR_HGEIP) & BIT(hgei)); + return false; } @@ -323,8 +366,6 @@ static int aia_rmw_iprio(struct kvm_vcpu *vcpu, unsigned int isel, return KVM_INSN_CONTINUE_NEXT_SEPC; } -#define IMSIC_FIRST 0x70 -#define IMSIC_LAST 0xff int kvm_riscv_vcpu_aia_rmw_ireg(struct kvm_vcpu *vcpu, unsigned int csr_num, unsigned long *val, unsigned long new_val, unsigned long wr_mask) @@ -348,6 +389,143 @@ int kvm_riscv_vcpu_aia_rmw_ireg(struct kvm_vcpu *vcpu, unsigned int csr_num, return KVM_INSN_EXIT_TO_USER_SPACE; } +int kvm_riscv_aia_alloc_hgei(int cpu, struct kvm_vcpu *owner, + void __iomem **hgei_va, phys_addr_t *hgei_pa) +{ + int ret = -ENOENT; + unsigned long flags; + struct aia_hgei_control *hgctrl = per_cpu_ptr(&aia_hgei, cpu); + + if (!kvm_riscv_aia_available() || !hgctrl) + return -ENODEV; + + raw_spin_lock_irqsave(&hgctrl->lock, flags); + + if (hgctrl->free_bitmap) { + ret = __ffs(hgctrl->free_bitmap); + hgctrl->free_bitmap &= ~BIT(ret); + hgctrl->owners[ret] = owner; + } + + raw_spin_unlock_irqrestore(&hgctrl->lock, flags); + + /* TODO: To be updated later by AIA IMSIC HW guest file support */ + if (hgei_va) + *hgei_va = NULL; + if (hgei_pa) + *hgei_pa = 0; + + return ret; +} + +void kvm_riscv_aia_free_hgei(int cpu, int hgei) +{ + unsigned long flags; + struct aia_hgei_control *hgctrl = per_cpu_ptr(&aia_hgei, cpu); + + if (!kvm_riscv_aia_available() || !hgctrl) + return; + + raw_spin_lock_irqsave(&hgctrl->lock, flags); + + if (hgei > 0 && hgei <= kvm_riscv_aia_nr_hgei) { + if (!(hgctrl->free_bitmap & BIT(hgei))) { + hgctrl->free_bitmap |= BIT(hgei); + hgctrl->owners[hgei] = NULL; + } + } + + raw_spin_unlock_irqrestore(&hgctrl->lock, flags); +} + +void kvm_riscv_aia_wakeon_hgei(struct kvm_vcpu *owner, bool enable) +{ + int hgei; + + if (!kvm_riscv_aia_available()) + return; + + hgei = aia_find_hgei(owner); + if (hgei > 0) { + if (enable) + csr_set(CSR_HGEIE, BIT(hgei)); + else + csr_clear(CSR_HGEIE, BIT(hgei)); + } +} + +static irqreturn_t hgei_interrupt(int irq, void *dev_id) +{ + int i; + unsigned long hgei_mask, flags; + struct aia_hgei_control *hgctrl = get_cpu_ptr(&aia_hgei); + + hgei_mask = csr_read(CSR_HGEIP) & csr_read(CSR_HGEIE); + csr_clear(CSR_HGEIE, hgei_mask); + + raw_spin_lock_irqsave(&hgctrl->lock, flags); + + for_each_set_bit(i, &hgei_mask, BITS_PER_LONG) { + if (hgctrl->owners[i]) + kvm_vcpu_kick(hgctrl->owners[i]); + } + + raw_spin_unlock_irqrestore(&hgctrl->lock, flags); + + put_cpu_ptr(&aia_hgei); + return IRQ_HANDLED; +} + +static int aia_hgei_init(void) +{ + int cpu, rc; + struct irq_domain *domain; + struct aia_hgei_control *hgctrl; + + /* Initialize per-CPU guest external interrupt line management */ + for_each_possible_cpu(cpu) { + hgctrl = per_cpu_ptr(&aia_hgei, cpu); + raw_spin_lock_init(&hgctrl->lock); + if (kvm_riscv_aia_nr_hgei) { + hgctrl->free_bitmap = + BIT(kvm_riscv_aia_nr_hgei + 1) - 1; + hgctrl->free_bitmap &= ~BIT(0); + } else + hgctrl->free_bitmap = 0; + } + + /* Find INTC irq domain */ + domain = irq_find_matching_fwnode(riscv_get_intc_hwnode(), + DOMAIN_BUS_ANY); + if (!domain) { + kvm_err("unable to find INTC domain\n"); + return -ENOENT; + } + + /* Map per-CPU SGEI interrupt from INTC domain */ + hgei_parent_irq = irq_create_mapping(domain, IRQ_S_GEXT); + if (!hgei_parent_irq) { + kvm_err("unable to map SGEI IRQ\n"); + return -ENOMEM; + } + + /* Request per-CPU SGEI interrupt */ + rc = request_percpu_irq(hgei_parent_irq, hgei_interrupt, + "riscv-kvm", &aia_hgei); + if (rc) { + kvm_err("failed to request SGEI IRQ\n"); + return rc; + } + + return 0; +} + +static void aia_hgei_exit(void) +{ + /* Free per-CPU SGEI interrupt */ + free_percpu_irq(hgei_parent_irq, &aia_hgei); +} + void kvm_riscv_aia_enable(void) { if (!kvm_riscv_aia_available()) @@ -362,21 +540,105 @@ void kvm_riscv_aia_enable(void) csr_write(CSR_HVIPRIO1H, 0x0); csr_write(CSR_HVIPRIO2H, 0x0); #endif + + /* Enable per-CPU SGEI interrupt */ + enable_percpu_irq(hgei_parent_irq, + irq_get_trigger_type(hgei_parent_irq)); + csr_set(CSR_HIE, BIT(IRQ_S_GEXT)); } void kvm_riscv_aia_disable(void) { + int i; + unsigned long flags; + struct kvm_vcpu *vcpu; + struct aia_hgei_control *hgctrl; + if (!kvm_riscv_aia_available()) return; + hgctrl = get_cpu_ptr(&aia_hgei); + + /* Disable per-CPU SGEI interrupt */ + csr_clear(CSR_HIE, BIT(IRQ_S_GEXT)); + disable_percpu_irq(hgei_parent_irq); aia_set_hvictl(false); + + raw_spin_lock_irqsave(&hgctrl->lock, flags); + + for (i = 0; i <= kvm_riscv_aia_nr_hgei; i++) { + vcpu = hgctrl->owners[i]; + if (!vcpu) + continue; + + /* + * We release hgctrl->lock before notifying IMSIC + * so that we don't have lock ordering issues. + */ + raw_spin_unlock_irqrestore(&hgctrl->lock, flags); + + /* Notify IMSIC */ + kvm_riscv_vcpu_aia_imsic_release(vcpu); + + /* + * Wakeup VCPU if it was blocked so that it can + * run on other HARTs + */ + if (csr_read(CSR_HGEIE) & BIT(i)) { + csr_clear(CSR_HGEIE, BIT(i)); + kvm_vcpu_kick(vcpu); + } + + raw_spin_lock_irqsave(&hgctrl->lock, flags); + } + + raw_spin_unlock_irqrestore(&hgctrl->lock, flags); + + put_cpu_ptr(&aia_hgei); } int kvm_riscv_aia_init(void) { + int rc; + if (!riscv_isa_extension_available(NULL, SxAIA)) return -ENODEV; + /* Figure-out number of bits in HGEIE */ + csr_write(CSR_HGEIE, -1UL); + kvm_riscv_aia_nr_hgei = fls_long(csr_read(CSR_HGEIE)); + csr_write(CSR_HGEIE, 0); + if (kvm_riscv_aia_nr_hgei) + kvm_riscv_aia_nr_hgei--; + + /* + * Number of usable HGEI lines should be minimum of per-HART + * IMSIC guest files and number of bits in HGEIE + * + * TODO: To be updated later by AIA IMSIC HW guest file support + */ + kvm_riscv_aia_nr_hgei = 0; + + /* + * Find number of guest MSI IDs + * + * TODO: To be updated later by AIA IMSIC HW guest file support + */ + kvm_riscv_aia_max_ids = IMSIC_MAX_ID; + + /* Initialize guest external interrupt line management */ + rc = aia_hgei_init(); + if (rc) + return rc; + + /* Register device operations */ + rc = kvm_register_device_ops(&kvm_riscv_aia_device_ops, + KVM_DEV_TYPE_RISCV_AIA); + if (rc) { + aia_hgei_exit(); + return rc; + } + /* Enable KVM AIA support */ static_branch_enable(&kvm_riscv_aia_available); @@ -385,4 +647,12 @@ int kvm_riscv_aia_init(void) void kvm_riscv_aia_exit(void) { + if (!kvm_riscv_aia_available()) + return; + + /* Unregister device operations */ + kvm_unregister_device_ops(KVM_DEV_TYPE_RISCV_AIA); + + /* Cleanup the HGEI state */ + aia_hgei_exit(); } diff --git a/arch/riscv/kvm/aia_aplic.c b/arch/riscv/kvm/aia_aplic.c new file mode 100644 index 0000000000000000000000000000000000000000..39e72aa016a4cc2d96a4994a342762762f2189c2 --- /dev/null +++ b/arch/riscv/kvm/aia_aplic.c @@ -0,0 +1,619 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2021 Western Digital Corporation or its affiliates. + * Copyright (C) 2022 Ventana Micro Systems Inc. + * + * Authors: + * Anup Patel + */ + +#include +#include +#include +#include +#include +#include + +struct aplic_irq { + raw_spinlock_t lock; + u32 sourcecfg; + u32 state; +#define APLIC_IRQ_STATE_PENDING BIT(0) +#define APLIC_IRQ_STATE_ENABLED BIT(1) +#define APLIC_IRQ_STATE_ENPEND (APLIC_IRQ_STATE_PENDING | \ + APLIC_IRQ_STATE_ENABLED) +#define APLIC_IRQ_STATE_INPUT BIT(8) + u32 target; +}; + +struct aplic { + struct kvm_io_device iodev; + + u32 domaincfg; + u32 genmsi; + + u32 nr_irqs; + u32 nr_words; + struct aplic_irq *irqs; +}; + +static u32 aplic_read_sourcecfg(struct aplic *aplic, u32 irq) +{ + u32 ret; + unsigned long flags; + struct aplic_irq *irqd; + + if (!irq || aplic->nr_irqs <= irq) + return 0; + irqd = &aplic->irqs[irq]; + + raw_spin_lock_irqsave(&irqd->lock, flags); + ret = irqd->sourcecfg; + raw_spin_unlock_irqrestore(&irqd->lock, flags); + + return ret; +} + +static void aplic_write_sourcecfg(struct aplic *aplic, u32 irq, u32 val) +{ + unsigned long flags; + struct aplic_irq *irqd; + + if (!irq || aplic->nr_irqs <= irq) + return; + irqd = &aplic->irqs[irq]; + + if (val & APLIC_SOURCECFG_D) + val = 0; + else + val &= APLIC_SOURCECFG_SM_MASK; + + raw_spin_lock_irqsave(&irqd->lock, flags); + irqd->sourcecfg = val; + raw_spin_unlock_irqrestore(&irqd->lock, flags); +} + +static u32 aplic_read_target(struct aplic *aplic, u32 irq) +{ + u32 ret; + unsigned long flags; + struct aplic_irq *irqd; + + if (!irq || aplic->nr_irqs <= irq) + return 0; + irqd = &aplic->irqs[irq]; + + raw_spin_lock_irqsave(&irqd->lock, flags); + ret = irqd->target; + raw_spin_unlock_irqrestore(&irqd->lock, flags); + + return ret; +} + +static void aplic_write_target(struct aplic *aplic, u32 irq, u32 val) +{ + unsigned long flags; + struct aplic_irq *irqd; + + if (!irq || aplic->nr_irqs <= irq) + return; + irqd = &aplic->irqs[irq]; + + val &= APLIC_TARGET_EIID_MASK | + (APLIC_TARGET_HART_IDX_MASK << APLIC_TARGET_HART_IDX_SHIFT) | + (APLIC_TARGET_GUEST_IDX_MASK << APLIC_TARGET_GUEST_IDX_SHIFT); + + raw_spin_lock_irqsave(&irqd->lock, flags); + irqd->target = val; + raw_spin_unlock_irqrestore(&irqd->lock, flags); +} + +static bool aplic_read_pending(struct aplic *aplic, u32 irq) +{ + bool ret; + unsigned long flags; + struct aplic_irq *irqd; + + if (!irq || aplic->nr_irqs <= irq) + return false; + irqd = &aplic->irqs[irq]; + + raw_spin_lock_irqsave(&irqd->lock, flags); + ret = (irqd->state & APLIC_IRQ_STATE_PENDING) ? true : false; + raw_spin_unlock_irqrestore(&irqd->lock, flags); + + return ret; +} + +static void aplic_write_pending(struct aplic *aplic, u32 irq, bool pending) +{ + unsigned long flags, sm; + struct aplic_irq *irqd; + + if (!irq || aplic->nr_irqs <= irq) + return; + irqd = &aplic->irqs[irq]; + + raw_spin_lock_irqsave(&irqd->lock, flags); + + sm = irqd->sourcecfg & APLIC_SOURCECFG_SM_MASK; + if (!pending && + ((sm == APLIC_SOURCECFG_SM_LEVEL_HIGH) || + (sm == APLIC_SOURCECFG_SM_LEVEL_LOW))) + goto skip_write_pending; + + if (pending) + irqd->state |= APLIC_IRQ_STATE_PENDING; + else + irqd->state &= ~APLIC_IRQ_STATE_PENDING; + +skip_write_pending: + raw_spin_unlock_irqrestore(&irqd->lock, flags); +} + +static bool aplic_read_enabled(struct aplic *aplic, u32 irq) +{ + bool ret; + unsigned long flags; + struct aplic_irq *irqd; + + if (!irq || aplic->nr_irqs <= irq) + return false; + irqd = &aplic->irqs[irq]; + + raw_spin_lock_irqsave(&irqd->lock, flags); + ret = (irqd->state & APLIC_IRQ_STATE_ENABLED) ? true : false; + raw_spin_unlock_irqrestore(&irqd->lock, flags); + + return ret; +} + +static void aplic_write_enabled(struct aplic *aplic, u32 irq, bool enabled) +{ + unsigned long flags; + struct aplic_irq *irqd; + + if (!irq || aplic->nr_irqs <= irq) + return; + irqd = &aplic->irqs[irq]; + + raw_spin_lock_irqsave(&irqd->lock, flags); + if (enabled) + irqd->state |= APLIC_IRQ_STATE_ENABLED; + else + irqd->state &= ~APLIC_IRQ_STATE_ENABLED; + raw_spin_unlock_irqrestore(&irqd->lock, flags); +} + +static bool aplic_read_input(struct aplic *aplic, u32 irq) +{ + bool ret; + unsigned long flags; + struct aplic_irq *irqd; + + if (!irq || aplic->nr_irqs <= irq) + return false; + irqd = &aplic->irqs[irq]; + + raw_spin_lock_irqsave(&irqd->lock, flags); + ret = (irqd->state & APLIC_IRQ_STATE_INPUT) ? true : false; + raw_spin_unlock_irqrestore(&irqd->lock, flags); + + return ret; +} + +static void aplic_inject_msi(struct kvm *kvm, u32 irq, u32 target) +{ + u32 hart_idx, guest_idx, eiid; + + hart_idx = target >> APLIC_TARGET_HART_IDX_SHIFT; + hart_idx &= APLIC_TARGET_HART_IDX_MASK; + guest_idx = target >> APLIC_TARGET_GUEST_IDX_SHIFT; + guest_idx &= APLIC_TARGET_GUEST_IDX_MASK; + eiid = target & APLIC_TARGET_EIID_MASK; + kvm_riscv_aia_inject_msi_by_id(kvm, hart_idx, guest_idx, eiid); +} + +static void aplic_update_irq_range(struct kvm *kvm, u32 first, u32 last) +{ + bool inject; + u32 irq, target; + unsigned long flags; + struct aplic_irq *irqd; + struct aplic *aplic = kvm->arch.aia.aplic_state; + + if (!(aplic->domaincfg & APLIC_DOMAINCFG_IE)) + return; + + for (irq = first; irq <= last; irq++) { + if (!irq || aplic->nr_irqs <= irq) + continue; + irqd = &aplic->irqs[irq]; + + raw_spin_lock_irqsave(&irqd->lock, flags); + + inject = false; + target = irqd->target; + if ((irqd->state & APLIC_IRQ_STATE_ENPEND) == + APLIC_IRQ_STATE_ENPEND) { + irqd->state &= ~APLIC_IRQ_STATE_PENDING; + inject = true; + } + + raw_spin_unlock_irqrestore(&irqd->lock, flags); + + if (inject) + aplic_inject_msi(kvm, irq, target); + } +} + +int kvm_riscv_aia_aplic_inject(struct kvm *kvm, u32 source, bool level) +{ + u32 target; + bool inject = false, ie; + unsigned long flags; + struct aplic_irq *irqd; + struct aplic *aplic = kvm->arch.aia.aplic_state; + + if (!aplic || !source || (aplic->nr_irqs <= source)) + return -ENODEV; + irqd = &aplic->irqs[source]; + ie = (aplic->domaincfg & APLIC_DOMAINCFG_IE) ? true : false; + + raw_spin_lock_irqsave(&irqd->lock, flags); + + if (irqd->sourcecfg & APLIC_SOURCECFG_D) + goto skip_unlock; + + switch (irqd->sourcecfg & APLIC_SOURCECFG_SM_MASK) { + case APLIC_SOURCECFG_SM_EDGE_RISE: + if (level && !(irqd->state & APLIC_IRQ_STATE_INPUT) && + !(irqd->state & APLIC_IRQ_STATE_PENDING)) + irqd->state |= APLIC_IRQ_STATE_PENDING; + break; + case APLIC_SOURCECFG_SM_EDGE_FALL: + if (!level && (irqd->state & APLIC_IRQ_STATE_INPUT) && + !(irqd->state & APLIC_IRQ_STATE_PENDING)) + irqd->state |= APLIC_IRQ_STATE_PENDING; + break; + case APLIC_SOURCECFG_SM_LEVEL_HIGH: + if (level && !(irqd->state & APLIC_IRQ_STATE_PENDING)) + irqd->state |= APLIC_IRQ_STATE_PENDING; + break; + case APLIC_SOURCECFG_SM_LEVEL_LOW: + if (!level && !(irqd->state & APLIC_IRQ_STATE_PENDING)) + irqd->state |= APLIC_IRQ_STATE_PENDING; + break; + } + + if (level) + irqd->state |= APLIC_IRQ_STATE_INPUT; + else + irqd->state &= ~APLIC_IRQ_STATE_INPUT; + + target = irqd->target; + if (ie && ((irqd->state & APLIC_IRQ_STATE_ENPEND) == + APLIC_IRQ_STATE_ENPEND)) { + irqd->state &= ~APLIC_IRQ_STATE_PENDING; + inject = true; + } + +skip_unlock: + raw_spin_unlock_irqrestore(&irqd->lock, flags); + + if (inject) + aplic_inject_msi(kvm, source, target); + + return 0; +} + +static u32 aplic_read_input_word(struct aplic *aplic, u32 word) +{ + u32 i, ret = 0; + + for (i = 0; i < 32; i++) + ret |= aplic_read_input(aplic, word * 32 + i) ? BIT(i) : 0; + + return ret; +} + +static u32 aplic_read_pending_word(struct aplic *aplic, u32 word) +{ + u32 i, ret = 0; + + for (i = 0; i < 32; i++) + ret |= aplic_read_pending(aplic, word * 32 + i) ? BIT(i) : 0; + + return ret; +} + +static void aplic_write_pending_word(struct aplic *aplic, u32 word, + u32 val, bool pending) +{ + u32 i; + + for (i = 0; i < 32; i++) { + if (val & BIT(i)) + aplic_write_pending(aplic, word * 32 + i, pending); + } +} + +static u32 aplic_read_enabled_word(struct aplic *aplic, u32 word) +{ + u32 i, ret = 0; + + for (i = 0; i < 32; i++) + ret |= aplic_read_enabled(aplic, word * 32 + i) ? BIT(i) : 0; + + return ret; +} + +static void aplic_write_enabled_word(struct aplic *aplic, u32 word, + u32 val, bool enabled) +{ + u32 i; + + for (i = 0; i < 32; i++) { + if (val & BIT(i)) + aplic_write_enabled(aplic, word * 32 + i, enabled); + } +} + +static int aplic_mmio_read_offset(struct kvm *kvm, gpa_t off, u32 *val32) +{ + u32 i; + struct aplic *aplic = kvm->arch.aia.aplic_state; + + if ((off & 0x3) != 0) + return -EOPNOTSUPP; + + if (off == APLIC_DOMAINCFG) { + *val32 = APLIC_DOMAINCFG_RDONLY | + aplic->domaincfg | APLIC_DOMAINCFG_DM; + } else if ((off >= APLIC_SOURCECFG_BASE) && + (off < (APLIC_SOURCECFG_BASE + (aplic->nr_irqs - 1) * 4))) { + i = ((off - APLIC_SOURCECFG_BASE) >> 2) + 1; + *val32 = aplic_read_sourcecfg(aplic, i); + } else if ((off >= APLIC_SETIP_BASE) && + (off < (APLIC_SETIP_BASE + aplic->nr_words * 4))) { + i = (off - APLIC_SETIP_BASE) >> 2; + *val32 = aplic_read_pending_word(aplic, i); + } else if (off == APLIC_SETIPNUM) { + *val32 = 0; + } else if ((off >= APLIC_CLRIP_BASE) && + (off < (APLIC_CLRIP_BASE + aplic->nr_words * 4))) { + i = (off - APLIC_CLRIP_BASE) >> 2; + *val32 = aplic_read_input_word(aplic, i); + } else if (off == APLIC_CLRIPNUM) { + *val32 = 0; + } else if ((off >= APLIC_SETIE_BASE) && + (off < (APLIC_SETIE_BASE + aplic->nr_words * 4))) { + i = (off - APLIC_SETIE_BASE) >> 2; + *val32 = aplic_read_enabled_word(aplic, i); + } else if (off == APLIC_SETIENUM) { + *val32 = 0; + } else if ((off >= APLIC_CLRIE_BASE) && + (off < (APLIC_CLRIE_BASE + aplic->nr_words * 4))) { + *val32 = 0; + } else if (off == APLIC_CLRIENUM) { + *val32 = 0; + } else if (off == APLIC_SETIPNUM_LE) { + *val32 = 0; + } else if (off == APLIC_SETIPNUM_BE) { + *val32 = 0; + } else if (off == APLIC_GENMSI) { + *val32 = aplic->genmsi; + } else if ((off >= APLIC_TARGET_BASE) && + (off < (APLIC_TARGET_BASE + (aplic->nr_irqs - 1) * 4))) { + i = ((off - APLIC_TARGET_BASE) >> 2) + 1; + *val32 = aplic_read_target(aplic, i); + } else + return -ENODEV; + + return 0; +} + +static int aplic_mmio_read(struct kvm_vcpu *vcpu, struct kvm_io_device *dev, + gpa_t addr, int len, void *val) +{ + if (len != 4) + return -EOPNOTSUPP; + + return aplic_mmio_read_offset(vcpu->kvm, + addr - vcpu->kvm->arch.aia.aplic_addr, + val); +} + +static int aplic_mmio_write_offset(struct kvm *kvm, gpa_t off, u32 val32) +{ + u32 i; + struct aplic *aplic = kvm->arch.aia.aplic_state; + + if ((off & 0x3) != 0) + return -EOPNOTSUPP; + + if (off == APLIC_DOMAINCFG) { + /* Only IE bit writeable */ + aplic->domaincfg = val32 & APLIC_DOMAINCFG_IE; + } else if ((off >= APLIC_SOURCECFG_BASE) && + (off < (APLIC_SOURCECFG_BASE + (aplic->nr_irqs - 1) * 4))) { + i = ((off - APLIC_SOURCECFG_BASE) >> 2) + 1; + aplic_write_sourcecfg(aplic, i, val32); + } else if ((off >= APLIC_SETIP_BASE) && + (off < (APLIC_SETIP_BASE + aplic->nr_words * 4))) { + i = (off - APLIC_SETIP_BASE) >> 2; + aplic_write_pending_word(aplic, i, val32, true); + } else if (off == APLIC_SETIPNUM) { + aplic_write_pending(aplic, val32, true); + } else if ((off >= APLIC_CLRIP_BASE) && + (off < (APLIC_CLRIP_BASE + aplic->nr_words * 4))) { + i = (off - APLIC_CLRIP_BASE) >> 2; + aplic_write_pending_word(aplic, i, val32, false); + } else if (off == APLIC_CLRIPNUM) { + aplic_write_pending(aplic, val32, false); + } else if ((off >= APLIC_SETIE_BASE) && + (off < (APLIC_SETIE_BASE + aplic->nr_words * 4))) { + i = (off - APLIC_SETIE_BASE) >> 2; + aplic_write_enabled_word(aplic, i, val32, true); + } else if (off == APLIC_SETIENUM) { + aplic_write_enabled(aplic, val32, true); + } else if ((off >= APLIC_CLRIE_BASE) && + (off < (APLIC_CLRIE_BASE + aplic->nr_words * 4))) { + i = (off - APLIC_CLRIE_BASE) >> 2; + aplic_write_enabled_word(aplic, i, val32, false); + } else if (off == APLIC_CLRIENUM) { + aplic_write_enabled(aplic, val32, false); + } else if (off == APLIC_SETIPNUM_LE) { + aplic_write_pending(aplic, val32, true); + } else if (off == APLIC_SETIPNUM_BE) { + aplic_write_pending(aplic, __swab32(val32), true); + } else if (off == APLIC_GENMSI) { + aplic->genmsi = val32 & ~(APLIC_TARGET_GUEST_IDX_MASK << + APLIC_TARGET_GUEST_IDX_SHIFT); + kvm_riscv_aia_inject_msi_by_id(kvm, + val32 >> APLIC_TARGET_HART_IDX_SHIFT, 0, + val32 & APLIC_TARGET_EIID_MASK); + } else if ((off >= APLIC_TARGET_BASE) && + (off < (APLIC_TARGET_BASE + (aplic->nr_irqs - 1) * 4))) { + i = ((off - APLIC_TARGET_BASE) >> 2) + 1; + aplic_write_target(aplic, i, val32); + } else + return -ENODEV; + + aplic_update_irq_range(kvm, 1, aplic->nr_irqs - 1); + + return 0; +} + +static int aplic_mmio_write(struct kvm_vcpu *vcpu, struct kvm_io_device *dev, + gpa_t addr, int len, const void *val) +{ + if (len != 4) + return -EOPNOTSUPP; + + return aplic_mmio_write_offset(vcpu->kvm, + addr - vcpu->kvm->arch.aia.aplic_addr, + *((const u32 *)val)); +} + +static struct kvm_io_device_ops aplic_iodoev_ops = { + .read = aplic_mmio_read, + .write = aplic_mmio_write, +}; + +int kvm_riscv_aia_aplic_set_attr(struct kvm *kvm, unsigned long type, u32 v) +{ + int rc; + + if (!kvm->arch.aia.aplic_state) + return -ENODEV; + + rc = aplic_mmio_write_offset(kvm, type, v); + if (rc) + return rc; + + return 0; +} + +int kvm_riscv_aia_aplic_get_attr(struct kvm *kvm, unsigned long type, u32 *v) +{ + int rc; + + if (!kvm->arch.aia.aplic_state) + return -ENODEV; + + rc = aplic_mmio_read_offset(kvm, type, v); + if (rc) + return rc; + + return 0; +} + +int kvm_riscv_aia_aplic_has_attr(struct kvm *kvm, unsigned long type) +{ + int rc; + u32 val; + + if (!kvm->arch.aia.aplic_state) + return -ENODEV; + + rc = aplic_mmio_read_offset(kvm, type, &val); + if (rc) + return rc; + + return 0; +} + +int kvm_riscv_aia_aplic_init(struct kvm *kvm) +{ + int i, ret = 0; + struct aplic *aplic; + + /* Do nothing if we have zero sources */ + if (!kvm->arch.aia.nr_sources) + return 0; + + /* Allocate APLIC global state */ + aplic = kzalloc(sizeof(*aplic), GFP_KERNEL); + if (!aplic) + return -ENOMEM; + kvm->arch.aia.aplic_state = aplic; + + /* Setup APLIC IRQs */ + aplic->nr_irqs = kvm->arch.aia.nr_sources + 1; + aplic->nr_words = DIV_ROUND_UP(aplic->nr_irqs, 32); + aplic->irqs = kcalloc(aplic->nr_irqs, + sizeof(*aplic->irqs), GFP_KERNEL); + if (!aplic->irqs) { + ret = -ENOMEM; + goto fail_free_aplic; + } + for (i = 0; i < aplic->nr_irqs; i++) + raw_spin_lock_init(&aplic->irqs[i].lock); + + /* Setup IO device */ + kvm_iodevice_init(&aplic->iodev, &aplic_iodoev_ops); + mutex_lock(&kvm->slots_lock); + ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS, + kvm->arch.aia.aplic_addr, + KVM_DEV_RISCV_APLIC_SIZE, + &aplic->iodev); + mutex_unlock(&kvm->slots_lock); + if (ret) + goto fail_free_aplic_irqs; + + /* Setup default IRQ routing */ + ret = kvm_riscv_setup_default_irq_routing(kvm, aplic->nr_irqs); + if (ret) + goto fail_unreg_iodev; + + return 0; + +fail_unreg_iodev: + mutex_lock(&kvm->slots_lock); + kvm_io_bus_unregister_dev(kvm, KVM_MMIO_BUS, &aplic->iodev); + mutex_unlock(&kvm->slots_lock); +fail_free_aplic_irqs: + kfree(aplic->irqs); +fail_free_aplic: + kvm->arch.aia.aplic_state = NULL; + kfree(aplic); + return ret; +} + +void kvm_riscv_aia_aplic_cleanup(struct kvm *kvm) +{ + struct aplic *aplic = kvm->arch.aia.aplic_state; + + if (!aplic) + return; + + mutex_lock(&kvm->slots_lock); + kvm_io_bus_unregister_dev(kvm, KVM_MMIO_BUS, &aplic->iodev); + mutex_unlock(&kvm->slots_lock); + + kfree(aplic->irqs); + + kvm->arch.aia.aplic_state = NULL; + kfree(aplic); +} diff --git a/arch/riscv/kvm/aia_device.c b/arch/riscv/kvm/aia_device.c new file mode 100644 index 0000000000000000000000000000000000000000..0eb689351b7d04128ba93122209f71b830b33efe --- /dev/null +++ b/arch/riscv/kvm/aia_device.c @@ -0,0 +1,673 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2021 Western Digital Corporation or its affiliates. + * Copyright (C) 2022 Ventana Micro Systems Inc. + * + * Authors: + * Anup Patel + */ + +#include +#include +#include +#include + +static void unlock_vcpus(struct kvm *kvm, int vcpu_lock_idx) +{ + struct kvm_vcpu *tmp_vcpu; + + for (; vcpu_lock_idx >= 0; vcpu_lock_idx--) { + tmp_vcpu = kvm_get_vcpu(kvm, vcpu_lock_idx); + mutex_unlock(&tmp_vcpu->mutex); + } +} + +static void unlock_all_vcpus(struct kvm *kvm) +{ + unlock_vcpus(kvm, atomic_read(&kvm->online_vcpus) - 1); +} + +static bool lock_all_vcpus(struct kvm *kvm) +{ + struct kvm_vcpu *tmp_vcpu; + unsigned long c; + + kvm_for_each_vcpu(c, tmp_vcpu, kvm) { + if (!mutex_trylock(&tmp_vcpu->mutex)) { + unlock_vcpus(kvm, c - 1); + return false; + } + } + + return true; +} + +static int aia_create(struct kvm_device *dev, u32 type) +{ + int ret; + unsigned long i; + struct kvm *kvm = dev->kvm; + struct kvm_vcpu *vcpu; + + if (irqchip_in_kernel(kvm)) + return -EEXIST; + + ret = -EBUSY; + if (!lock_all_vcpus(kvm)) + return ret; + + kvm_for_each_vcpu(i, vcpu, kvm) { + if (vcpu->arch.ran_atleast_once) + goto out_unlock; + } + ret = 0; + + kvm->arch.aia.in_kernel = true; + +out_unlock: + unlock_all_vcpus(kvm); + return ret; +} + +static void aia_destroy(struct kvm_device *dev) +{ + kfree(dev); +} + +static int aia_config(struct kvm *kvm, unsigned long type, + u32 *nr, bool write) +{ + struct kvm_aia *aia = &kvm->arch.aia; + + /* Writes can only be done before irqchip is initialized */ + if (write && kvm_riscv_aia_initialized(kvm)) + return -EBUSY; + + switch (type) { + case KVM_DEV_RISCV_AIA_CONFIG_MODE: + if (write) { + switch (*nr) { + case KVM_DEV_RISCV_AIA_MODE_EMUL: + break; + case KVM_DEV_RISCV_AIA_MODE_HWACCEL: + case KVM_DEV_RISCV_AIA_MODE_AUTO: + /* + * HW Acceleration and Auto modes only + * supported on host with non-zero guest + * external interrupts (i.e. non-zero + * VS-level IMSIC pages). + */ + if (!kvm_riscv_aia_nr_hgei) + return -EINVAL; + break; + default: + return -EINVAL; + } + aia->mode = *nr; + } else + *nr = aia->mode; + break; + case KVM_DEV_RISCV_AIA_CONFIG_IDS: + if (write) { + if ((*nr < KVM_DEV_RISCV_AIA_IDS_MIN) || + (*nr >= KVM_DEV_RISCV_AIA_IDS_MAX) || + ((*nr & KVM_DEV_RISCV_AIA_IDS_MIN) != + KVM_DEV_RISCV_AIA_IDS_MIN) || + (kvm_riscv_aia_max_ids <= *nr)) + return -EINVAL; + aia->nr_ids = *nr; + } else + *nr = aia->nr_ids; + break; + case KVM_DEV_RISCV_AIA_CONFIG_SRCS: + if (write) { + if ((*nr >= KVM_DEV_RISCV_AIA_SRCS_MAX) || + (*nr >= kvm_riscv_aia_max_ids)) + return -EINVAL; + aia->nr_sources = *nr; + } else + *nr = aia->nr_sources; + break; + case KVM_DEV_RISCV_AIA_CONFIG_GROUP_BITS: + if (write) { + if (*nr >= KVM_DEV_RISCV_AIA_GROUP_BITS_MAX) + return -EINVAL; + aia->nr_group_bits = *nr; + } else + *nr = aia->nr_group_bits; + break; + case KVM_DEV_RISCV_AIA_CONFIG_GROUP_SHIFT: + if (write) { + if ((*nr < KVM_DEV_RISCV_AIA_GROUP_SHIFT_MIN) || + (*nr >= KVM_DEV_RISCV_AIA_GROUP_SHIFT_MAX)) + return -EINVAL; + aia->nr_group_shift = *nr; + } else + *nr = aia->nr_group_shift; + break; + case KVM_DEV_RISCV_AIA_CONFIG_HART_BITS: + if (write) { + if (*nr >= KVM_DEV_RISCV_AIA_HART_BITS_MAX) + return -EINVAL; + aia->nr_hart_bits = *nr; + } else + *nr = aia->nr_hart_bits; + break; + case KVM_DEV_RISCV_AIA_CONFIG_GUEST_BITS: + if (write) { + if (*nr >= KVM_DEV_RISCV_AIA_GUEST_BITS_MAX) + return -EINVAL; + aia->nr_guest_bits = *nr; + } else + *nr = aia->nr_guest_bits; + break; + default: + return -ENXIO; + } + + return 0; +} + +static int aia_aplic_addr(struct kvm *kvm, u64 *addr, bool write) +{ + struct kvm_aia *aia = &kvm->arch.aia; + + if (write) { + /* Writes can only be done before irqchip is initialized */ + if (kvm_riscv_aia_initialized(kvm)) + return -EBUSY; + + if (*addr & (KVM_DEV_RISCV_APLIC_ALIGN - 1)) + return -EINVAL; + + aia->aplic_addr = *addr; + } else + *addr = aia->aplic_addr; + + return 0; +} + +static int aia_imsic_addr(struct kvm *kvm, u64 *addr, + unsigned long vcpu_idx, bool write) +{ + struct kvm_vcpu *vcpu; + struct kvm_vcpu_aia *vcpu_aia; + + vcpu = kvm_get_vcpu(kvm, vcpu_idx); + if (!vcpu) + return -EINVAL; + vcpu_aia = &vcpu->arch.aia_context; + + if (write) { + /* Writes can only be done before irqchip is initialized */ + if (kvm_riscv_aia_initialized(kvm)) + return -EBUSY; + + if (*addr & (KVM_DEV_RISCV_IMSIC_ALIGN - 1)) + return -EINVAL; + } + + mutex_lock(&vcpu->mutex); + if (write) + vcpu_aia->imsic_addr = *addr; + else + *addr = vcpu_aia->imsic_addr; + mutex_unlock(&vcpu->mutex); + + return 0; +} + +static gpa_t aia_imsic_ppn(struct kvm_aia *aia, gpa_t addr) +{ + u32 h, l; + gpa_t mask = 0; + + h = aia->nr_hart_bits + aia->nr_guest_bits + + IMSIC_MMIO_PAGE_SHIFT - 1; + mask = GENMASK_ULL(h, 0); + + if (aia->nr_group_bits) { + h = aia->nr_group_bits + aia->nr_group_shift - 1; + l = aia->nr_group_shift; + mask |= GENMASK_ULL(h, l); + } + + return (addr & ~mask) >> IMSIC_MMIO_PAGE_SHIFT; +} + +static u32 aia_imsic_hart_index(struct kvm_aia *aia, gpa_t addr) +{ + u32 hart, group = 0; + + hart = (addr >> (aia->nr_guest_bits + IMSIC_MMIO_PAGE_SHIFT)) & + GENMASK_ULL(aia->nr_hart_bits - 1, 0); + if (aia->nr_group_bits) + group = (addr >> aia->nr_group_shift) & + GENMASK_ULL(aia->nr_group_bits - 1, 0); + + return (group << aia->nr_hart_bits) | hart; +} + +static int aia_init(struct kvm *kvm) +{ + int ret, i; + unsigned long idx; + struct kvm_vcpu *vcpu; + struct kvm_vcpu_aia *vaia; + struct kvm_aia *aia = &kvm->arch.aia; + gpa_t base_ppn = KVM_RISCV_AIA_UNDEF_ADDR; + + /* Irqchip can be initialized only once */ + if (kvm_riscv_aia_initialized(kvm)) + return -EBUSY; + + /* We might be in the middle of creating a VCPU? */ + if (kvm->created_vcpus != atomic_read(&kvm->online_vcpus)) + return -EBUSY; + + /* Number of sources should be less than or equals number of IDs */ + if (aia->nr_ids < aia->nr_sources) + return -EINVAL; + + /* APLIC base is required for non-zero number of sources */ + if (aia->nr_sources && aia->aplic_addr == KVM_RISCV_AIA_UNDEF_ADDR) + return -EINVAL; + + /* Initialize APLIC */ + ret = kvm_riscv_aia_aplic_init(kvm); + if (ret) + return ret; + + /* Iterate over each VCPU */ + kvm_for_each_vcpu(idx, vcpu, kvm) { + vaia = &vcpu->arch.aia_context; + + /* IMSIC base is required */ + if (vaia->imsic_addr == KVM_RISCV_AIA_UNDEF_ADDR) { + ret = -EINVAL; + goto fail_cleanup_imsics; + } + + /* All IMSICs should have matching base PPN */ + if (base_ppn == KVM_RISCV_AIA_UNDEF_ADDR) + base_ppn = aia_imsic_ppn(aia, vaia->imsic_addr); + if (base_ppn != aia_imsic_ppn(aia, vaia->imsic_addr)) { + ret = -EINVAL; + goto fail_cleanup_imsics; + } + + /* Update HART index of the IMSIC based on IMSIC base */ + vaia->hart_index = aia_imsic_hart_index(aia, + vaia->imsic_addr); + + /* Initialize IMSIC for this VCPU */ + ret = kvm_riscv_vcpu_aia_imsic_init(vcpu); + if (ret) + goto fail_cleanup_imsics; + } + + /* Set the initialized flag */ + kvm->arch.aia.initialized = true; + + return 0; + +fail_cleanup_imsics: + for (i = idx - 1; i >= 0; i--) { + vcpu = kvm_get_vcpu(kvm, i); + if (!vcpu) + continue; + kvm_riscv_vcpu_aia_imsic_cleanup(vcpu); + } + kvm_riscv_aia_aplic_cleanup(kvm); + return ret; +} + +static int aia_set_attr(struct kvm_device *dev, struct kvm_device_attr *attr) +{ + u32 nr; + u64 addr; + int nr_vcpus, r = -ENXIO; + unsigned long v, type = (unsigned long)attr->attr; + void __user *uaddr = (void __user *)(long)attr->addr; + + switch (attr->group) { + case KVM_DEV_RISCV_AIA_GRP_CONFIG: + if (copy_from_user(&nr, uaddr, sizeof(nr))) + return -EFAULT; + + mutex_lock(&dev->kvm->lock); + r = aia_config(dev->kvm, type, &nr, true); + mutex_unlock(&dev->kvm->lock); + + break; + + case KVM_DEV_RISCV_AIA_GRP_ADDR: + if (copy_from_user(&addr, uaddr, sizeof(addr))) + return -EFAULT; + + nr_vcpus = atomic_read(&dev->kvm->online_vcpus); + mutex_lock(&dev->kvm->lock); + if (type == KVM_DEV_RISCV_AIA_ADDR_APLIC) + r = aia_aplic_addr(dev->kvm, &addr, true); + else if (type < KVM_DEV_RISCV_AIA_ADDR_IMSIC(nr_vcpus)) + r = aia_imsic_addr(dev->kvm, &addr, + type - KVM_DEV_RISCV_AIA_ADDR_IMSIC(0), true); + mutex_unlock(&dev->kvm->lock); + + break; + + case KVM_DEV_RISCV_AIA_GRP_CTRL: + switch (type) { + case KVM_DEV_RISCV_AIA_CTRL_INIT: + mutex_lock(&dev->kvm->lock); + r = aia_init(dev->kvm); + mutex_unlock(&dev->kvm->lock); + break; + } + + break; + case KVM_DEV_RISCV_AIA_GRP_APLIC: + if (copy_from_user(&nr, uaddr, sizeof(nr))) + return -EFAULT; + + mutex_lock(&dev->kvm->lock); + r = kvm_riscv_aia_aplic_set_attr(dev->kvm, type, nr); + mutex_unlock(&dev->kvm->lock); + + break; + case KVM_DEV_RISCV_AIA_GRP_IMSIC: + if (copy_from_user(&v, uaddr, sizeof(v))) + return -EFAULT; + + mutex_lock(&dev->kvm->lock); + r = kvm_riscv_aia_imsic_rw_attr(dev->kvm, type, true, &v); + mutex_unlock(&dev->kvm->lock); + + break; + } + + return r; +} + +static int aia_get_attr(struct kvm_device *dev, struct kvm_device_attr *attr) +{ + u32 nr; + u64 addr; + int nr_vcpus, r = -ENXIO; + void __user *uaddr = (void __user *)(long)attr->addr; + unsigned long v, type = (unsigned long)attr->attr; + + switch (attr->group) { + case KVM_DEV_RISCV_AIA_GRP_CONFIG: + if (copy_from_user(&nr, uaddr, sizeof(nr))) + return -EFAULT; + + mutex_lock(&dev->kvm->lock); + r = aia_config(dev->kvm, type, &nr, false); + mutex_unlock(&dev->kvm->lock); + if (r) + return r; + + if (copy_to_user(uaddr, &nr, sizeof(nr))) + return -EFAULT; + + break; + case KVM_DEV_RISCV_AIA_GRP_ADDR: + if (copy_from_user(&addr, uaddr, sizeof(addr))) + return -EFAULT; + + nr_vcpus = atomic_read(&dev->kvm->online_vcpus); + mutex_lock(&dev->kvm->lock); + if (type == KVM_DEV_RISCV_AIA_ADDR_APLIC) + r = aia_aplic_addr(dev->kvm, &addr, false); + else if (type < KVM_DEV_RISCV_AIA_ADDR_IMSIC(nr_vcpus)) + r = aia_imsic_addr(dev->kvm, &addr, + type - KVM_DEV_RISCV_AIA_ADDR_IMSIC(0), false); + mutex_unlock(&dev->kvm->lock); + if (r) + return r; + + if (copy_to_user(uaddr, &addr, sizeof(addr))) + return -EFAULT; + + break; + case KVM_DEV_RISCV_AIA_GRP_APLIC: + if (copy_from_user(&nr, uaddr, sizeof(nr))) + return -EFAULT; + + mutex_lock(&dev->kvm->lock); + r = kvm_riscv_aia_aplic_get_attr(dev->kvm, type, &nr); + mutex_unlock(&dev->kvm->lock); + if (r) + return r; + + if (copy_to_user(uaddr, &nr, sizeof(nr))) + return -EFAULT; + + break; + case KVM_DEV_RISCV_AIA_GRP_IMSIC: + if (copy_from_user(&v, uaddr, sizeof(v))) + return -EFAULT; + + mutex_lock(&dev->kvm->lock); + r = kvm_riscv_aia_imsic_rw_attr(dev->kvm, type, false, &v); + mutex_unlock(&dev->kvm->lock); + if (r) + return r; + + if (copy_to_user(uaddr, &v, sizeof(v))) + return -EFAULT; + + break; + } + + return r; +} + +static int aia_has_attr(struct kvm_device *dev, struct kvm_device_attr *attr) +{ + int nr_vcpus; + + switch (attr->group) { + case KVM_DEV_RISCV_AIA_GRP_CONFIG: + switch (attr->attr) { + case KVM_DEV_RISCV_AIA_CONFIG_MODE: + case KVM_DEV_RISCV_AIA_CONFIG_IDS: + case KVM_DEV_RISCV_AIA_CONFIG_SRCS: + case KVM_DEV_RISCV_AIA_CONFIG_GROUP_BITS: + case KVM_DEV_RISCV_AIA_CONFIG_GROUP_SHIFT: + case KVM_DEV_RISCV_AIA_CONFIG_HART_BITS: + case KVM_DEV_RISCV_AIA_CONFIG_GUEST_BITS: + return 0; + } + break; + case KVM_DEV_RISCV_AIA_GRP_ADDR: + nr_vcpus = atomic_read(&dev->kvm->online_vcpus); + if (attr->attr == KVM_DEV_RISCV_AIA_ADDR_APLIC) + return 0; + else if (attr->attr < KVM_DEV_RISCV_AIA_ADDR_IMSIC(nr_vcpus)) + return 0; + break; + case KVM_DEV_RISCV_AIA_GRP_CTRL: + switch (attr->attr) { + case KVM_DEV_RISCV_AIA_CTRL_INIT: + return 0; + } + break; + case KVM_DEV_RISCV_AIA_GRP_APLIC: + return kvm_riscv_aia_aplic_has_attr(dev->kvm, attr->attr); + case KVM_DEV_RISCV_AIA_GRP_IMSIC: + return kvm_riscv_aia_imsic_has_attr(dev->kvm, attr->attr); + } + + return -ENXIO; +} + +struct kvm_device_ops kvm_riscv_aia_device_ops = { + .name = "kvm-riscv-aia", + .create = aia_create, + .destroy = aia_destroy, + .set_attr = aia_set_attr, + .get_attr = aia_get_attr, + .has_attr = aia_has_attr, +}; + +int kvm_riscv_vcpu_aia_update(struct kvm_vcpu *vcpu) +{ + /* Proceed only if AIA was initialized successfully */ + if (!kvm_riscv_aia_initialized(vcpu->kvm)) + return 1; + + /* Update the IMSIC HW state before entering guest mode */ + return kvm_riscv_vcpu_aia_imsic_update(vcpu); +} + +void kvm_riscv_vcpu_aia_reset(struct kvm_vcpu *vcpu) +{ + struct kvm_vcpu_aia_csr *csr = &vcpu->arch.aia_context.guest_csr; + struct kvm_vcpu_aia_csr *reset_csr = + &vcpu->arch.aia_context.guest_reset_csr; + + if (!kvm_riscv_aia_available()) + return; + memcpy(csr, reset_csr, sizeof(*csr)); + + /* Proceed only if AIA was initialized successfully */ + if (!kvm_riscv_aia_initialized(vcpu->kvm)) + return; + + /* Reset the IMSIC context */ + kvm_riscv_vcpu_aia_imsic_reset(vcpu); +} + +int kvm_riscv_vcpu_aia_init(struct kvm_vcpu *vcpu) +{ + struct kvm_vcpu_aia *vaia = &vcpu->arch.aia_context; + + if (!kvm_riscv_aia_available()) + return 0; + + /* + * We don't do any memory allocations over here because these + * will be done after AIA device is initialized by the user-space. + * + * Refer, aia_init() implementation for more details. + */ + + /* Initialize default values in AIA vcpu context */ + vaia->imsic_addr = KVM_RISCV_AIA_UNDEF_ADDR; + vaia->hart_index = vcpu->vcpu_idx; + + return 0; +} + +void kvm_riscv_vcpu_aia_deinit(struct kvm_vcpu *vcpu) +{ + /* Proceed only if AIA was initialized successfully */ + if (!kvm_riscv_aia_initialized(vcpu->kvm)) + return; + + /* Cleanup IMSIC context */ + kvm_riscv_vcpu_aia_imsic_cleanup(vcpu); +} + +int kvm_riscv_aia_inject_msi_by_id(struct kvm *kvm, u32 hart_index, + u32 guest_index, u32 iid) +{ + unsigned long idx; + struct kvm_vcpu *vcpu; + + /* Proceed only if AIA was initialized successfully */ + if (!kvm_riscv_aia_initialized(kvm)) + return -EBUSY; + + /* Inject MSI to matching VCPU */ + kvm_for_each_vcpu(idx, vcpu, kvm) { + if (vcpu->arch.aia_context.hart_index == hart_index) + return kvm_riscv_vcpu_aia_imsic_inject(vcpu, + guest_index, + 0, iid); + } + + return 0; +} + +int kvm_riscv_aia_inject_msi(struct kvm *kvm, struct kvm_msi *msi) +{ + gpa_t tppn, ippn; + unsigned long idx; + struct kvm_vcpu *vcpu; + u32 g, toff, iid = msi->data; + struct kvm_aia *aia = &kvm->arch.aia; + gpa_t target = (((gpa_t)msi->address_hi) << 32) | msi->address_lo; + + /* Proceed only if AIA was initialized successfully */ + if (!kvm_riscv_aia_initialized(kvm)) + return -EBUSY; + + /* Convert target address to target PPN */ + tppn = target >> IMSIC_MMIO_PAGE_SHIFT; + + /* Extract and clear Guest ID from target PPN */ + g = tppn & (BIT(aia->nr_guest_bits) - 1); + tppn &= ~((gpa_t)(BIT(aia->nr_guest_bits) - 1)); + + /* Inject MSI to matching VCPU */ + kvm_for_each_vcpu(idx, vcpu, kvm) { + ippn = vcpu->arch.aia_context.imsic_addr >> + IMSIC_MMIO_PAGE_SHIFT; + if (ippn == tppn) { + toff = target & (IMSIC_MMIO_PAGE_SZ - 1); + return kvm_riscv_vcpu_aia_imsic_inject(vcpu, g, + toff, iid); + } + } + + return 0; +} + +int kvm_riscv_aia_inject_irq(struct kvm *kvm, unsigned int irq, bool level) +{ + /* Proceed only if AIA was initialized successfully */ + if (!kvm_riscv_aia_initialized(kvm)) + return -EBUSY; + + /* Inject interrupt level change in APLIC */ + return kvm_riscv_aia_aplic_inject(kvm, irq, level); +} + +void kvm_riscv_aia_init_vm(struct kvm *kvm) +{ + struct kvm_aia *aia = &kvm->arch.aia; + + if (!kvm_riscv_aia_available()) + return; + + /* + * We don't do any memory allocations over here because these + * will be done after AIA device is initialized by the user-space. + * + * Refer, aia_init() implementation for more details. + */ + + /* Initialize default values in AIA global context */ + aia->mode = (kvm_riscv_aia_nr_hgei) ? + KVM_DEV_RISCV_AIA_MODE_AUTO : KVM_DEV_RISCV_AIA_MODE_EMUL; + aia->nr_ids = kvm_riscv_aia_max_ids - 1; + aia->nr_sources = 0; + aia->nr_group_bits = 0; + aia->nr_group_shift = KVM_DEV_RISCV_AIA_GROUP_SHIFT_MIN; + aia->nr_hart_bits = 0; + aia->nr_guest_bits = 0; + aia->aplic_addr = KVM_RISCV_AIA_UNDEF_ADDR; +} + +void kvm_riscv_aia_destroy_vm(struct kvm *kvm) +{ + /* Proceed only if AIA was initialized successfully */ + if (!kvm_riscv_aia_initialized(kvm)) + return; + + /* Cleanup APLIC context */ + kvm_riscv_aia_aplic_cleanup(kvm); +} diff --git a/arch/riscv/kvm/aia_imsic.c b/arch/riscv/kvm/aia_imsic.c new file mode 100644 index 0000000000000000000000000000000000000000..6cf23b8adb7129c2aa2043034b64f3b50768a66a --- /dev/null +++ b/arch/riscv/kvm/aia_imsic.c @@ -0,0 +1,1084 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2021 Western Digital Corporation or its affiliates. + * Copyright (C) 2022 Ventana Micro Systems Inc. + * + * Authors: + * Anup Patel + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define IMSIC_MAX_EIX (IMSIC_MAX_ID / BITS_PER_TYPE(u64)) + +struct imsic_mrif_eix { + unsigned long eip[BITS_PER_TYPE(u64) / BITS_PER_LONG]; + unsigned long eie[BITS_PER_TYPE(u64) / BITS_PER_LONG]; +}; + +struct imsic_mrif { + struct imsic_mrif_eix eix[IMSIC_MAX_EIX]; + unsigned long eithreshold; + unsigned long eidelivery; +}; + +struct imsic { + struct kvm_io_device iodev; + + u32 nr_msis; + u32 nr_eix; + u32 nr_hw_eix; + + /* + * At any point in time, the register state is in + * one of the following places: + * + * 1) Hardware: IMSIC VS-file (vsfile_cpu >= 0) + * 2) Software: IMSIC SW-file (vsfile_cpu < 0) + */ + + /* IMSIC VS-file */ + rwlock_t vsfile_lock; + int vsfile_cpu; + int vsfile_hgei; + void __iomem *vsfile_va; + phys_addr_t vsfile_pa; + + /* IMSIC SW-file */ + struct imsic_mrif *swfile; + phys_addr_t swfile_pa; +}; + +#define imsic_vs_csr_read(__c) \ +({ \ + unsigned long __r; \ + csr_write(CSR_VSISELECT, __c); \ + __r = csr_read(CSR_VSIREG); \ + __r; \ +}) + +#define imsic_read_switchcase(__ireg) \ + case __ireg: \ + return imsic_vs_csr_read(__ireg); +#define imsic_read_switchcase_2(__ireg) \ + imsic_read_switchcase(__ireg + 0) \ + imsic_read_switchcase(__ireg + 1) +#define imsic_read_switchcase_4(__ireg) \ + imsic_read_switchcase_2(__ireg + 0) \ + imsic_read_switchcase_2(__ireg + 2) +#define imsic_read_switchcase_8(__ireg) \ + imsic_read_switchcase_4(__ireg + 0) \ + imsic_read_switchcase_4(__ireg + 4) +#define imsic_read_switchcase_16(__ireg) \ + imsic_read_switchcase_8(__ireg + 0) \ + imsic_read_switchcase_8(__ireg + 8) +#define imsic_read_switchcase_32(__ireg) \ + imsic_read_switchcase_16(__ireg + 0) \ + imsic_read_switchcase_16(__ireg + 16) +#define imsic_read_switchcase_64(__ireg) \ + imsic_read_switchcase_32(__ireg + 0) \ + imsic_read_switchcase_32(__ireg + 32) + +static unsigned long imsic_eix_read(int ireg) +{ + switch (ireg) { + imsic_read_switchcase_64(IMSIC_EIP0) + imsic_read_switchcase_64(IMSIC_EIE0) + } + + return 0; +} + +#define imsic_vs_csr_swap(__c, __v) \ +({ \ + unsigned long __r; \ + csr_write(CSR_VSISELECT, __c); \ + __r = csr_swap(CSR_VSIREG, __v); \ + __r; \ +}) + +#define imsic_swap_switchcase(__ireg, __v) \ + case __ireg: \ + return imsic_vs_csr_swap(__ireg, __v); +#define imsic_swap_switchcase_2(__ireg, __v) \ + imsic_swap_switchcase(__ireg + 0, __v) \ + imsic_swap_switchcase(__ireg + 1, __v) +#define imsic_swap_switchcase_4(__ireg, __v) \ + imsic_swap_switchcase_2(__ireg + 0, __v) \ + imsic_swap_switchcase_2(__ireg + 2, __v) +#define imsic_swap_switchcase_8(__ireg, __v) \ + imsic_swap_switchcase_4(__ireg + 0, __v) \ + imsic_swap_switchcase_4(__ireg + 4, __v) +#define imsic_swap_switchcase_16(__ireg, __v) \ + imsic_swap_switchcase_8(__ireg + 0, __v) \ + imsic_swap_switchcase_8(__ireg + 8, __v) +#define imsic_swap_switchcase_32(__ireg, __v) \ + imsic_swap_switchcase_16(__ireg + 0, __v) \ + imsic_swap_switchcase_16(__ireg + 16, __v) +#define imsic_swap_switchcase_64(__ireg, __v) \ + imsic_swap_switchcase_32(__ireg + 0, __v) \ + imsic_swap_switchcase_32(__ireg + 32, __v) + +static unsigned long imsic_eix_swap(int ireg, unsigned long val) +{ + switch (ireg) { + imsic_swap_switchcase_64(IMSIC_EIP0, val) + imsic_swap_switchcase_64(IMSIC_EIE0, val) + } + + return 0; +} + +#define imsic_vs_csr_write(__c, __v) \ +do { \ + csr_write(CSR_VSISELECT, __c); \ + csr_write(CSR_VSIREG, __v); \ +} while (0) + +#define imsic_write_switchcase(__ireg, __v) \ + case __ireg: \ + imsic_vs_csr_write(__ireg, __v); \ + break; +#define imsic_write_switchcase_2(__ireg, __v) \ + imsic_write_switchcase(__ireg + 0, __v) \ + imsic_write_switchcase(__ireg + 1, __v) +#define imsic_write_switchcase_4(__ireg, __v) \ + imsic_write_switchcase_2(__ireg + 0, __v) \ + imsic_write_switchcase_2(__ireg + 2, __v) +#define imsic_write_switchcase_8(__ireg, __v) \ + imsic_write_switchcase_4(__ireg + 0, __v) \ + imsic_write_switchcase_4(__ireg + 4, __v) +#define imsic_write_switchcase_16(__ireg, __v) \ + imsic_write_switchcase_8(__ireg + 0, __v) \ + imsic_write_switchcase_8(__ireg + 8, __v) +#define imsic_write_switchcase_32(__ireg, __v) \ + imsic_write_switchcase_16(__ireg + 0, __v) \ + imsic_write_switchcase_16(__ireg + 16, __v) +#define imsic_write_switchcase_64(__ireg, __v) \ + imsic_write_switchcase_32(__ireg + 0, __v) \ + imsic_write_switchcase_32(__ireg + 32, __v) + +static void imsic_eix_write(int ireg, unsigned long val) +{ + switch (ireg) { + imsic_write_switchcase_64(IMSIC_EIP0, val) + imsic_write_switchcase_64(IMSIC_EIE0, val) + } +} + +#define imsic_vs_csr_set(__c, __v) \ +do { \ + csr_write(CSR_VSISELECT, __c); \ + csr_set(CSR_VSIREG, __v); \ +} while (0) + +#define imsic_set_switchcase(__ireg, __v) \ + case __ireg: \ + imsic_vs_csr_set(__ireg, __v); \ + break; +#define imsic_set_switchcase_2(__ireg, __v) \ + imsic_set_switchcase(__ireg + 0, __v) \ + imsic_set_switchcase(__ireg + 1, __v) +#define imsic_set_switchcase_4(__ireg, __v) \ + imsic_set_switchcase_2(__ireg + 0, __v) \ + imsic_set_switchcase_2(__ireg + 2, __v) +#define imsic_set_switchcase_8(__ireg, __v) \ + imsic_set_switchcase_4(__ireg + 0, __v) \ + imsic_set_switchcase_4(__ireg + 4, __v) +#define imsic_set_switchcase_16(__ireg, __v) \ + imsic_set_switchcase_8(__ireg + 0, __v) \ + imsic_set_switchcase_8(__ireg + 8, __v) +#define imsic_set_switchcase_32(__ireg, __v) \ + imsic_set_switchcase_16(__ireg + 0, __v) \ + imsic_set_switchcase_16(__ireg + 16, __v) +#define imsic_set_switchcase_64(__ireg, __v) \ + imsic_set_switchcase_32(__ireg + 0, __v) \ + imsic_set_switchcase_32(__ireg + 32, __v) + +static void imsic_eix_set(int ireg, unsigned long val) +{ + switch (ireg) { + imsic_set_switchcase_64(IMSIC_EIP0, val) + imsic_set_switchcase_64(IMSIC_EIE0, val) + } +} + +static unsigned long imsic_mrif_atomic_rmw(struct imsic_mrif *mrif, + unsigned long *ptr, + unsigned long new_val, + unsigned long wr_mask) +{ + unsigned long old_val = 0, tmp = 0; + + __asm__ __volatile__ ( + "0: lr.w.aq %1, %0\n" + " and %2, %1, %3\n" + " or %2, %2, %4\n" + " sc.w.rl %2, %2, %0\n" + " bnez %2, 0b" + : "+A" (*ptr), "+r" (old_val), "+r" (tmp) + : "r" (~wr_mask), "r" (new_val & wr_mask) + : "memory"); + + return old_val; +} + +static unsigned long imsic_mrif_atomic_or(struct imsic_mrif *mrif, + unsigned long *ptr, + unsigned long val) +{ + return atomic_long_fetch_or(val, (atomic_long_t *)ptr); +} + +#define imsic_mrif_atomic_write(__mrif, __ptr, __new_val) \ + imsic_mrif_atomic_rmw(__mrif, __ptr, __new_val, -1UL) +#define imsic_mrif_atomic_read(__mrif, __ptr) \ + imsic_mrif_atomic_or(__mrif, __ptr, 0) + +static u32 imsic_mrif_topei(struct imsic_mrif *mrif, u32 nr_eix, u32 nr_msis) +{ + struct imsic_mrif_eix *eix; + u32 i, imin, imax, ei, max_msi; + unsigned long eipend[BITS_PER_TYPE(u64) / BITS_PER_LONG]; + unsigned long eithreshold = imsic_mrif_atomic_read(mrif, + &mrif->eithreshold); + + max_msi = (eithreshold && (eithreshold <= nr_msis)) ? + eithreshold : nr_msis; + for (ei = 0; ei < nr_eix; ei++) { + eix = &mrif->eix[ei]; + eipend[0] = imsic_mrif_atomic_read(mrif, &eix->eie[0]) & + imsic_mrif_atomic_read(mrif, &eix->eip[0]); +#ifdef CONFIG_32BIT + eipend[1] = imsic_mrif_atomic_read(mrif, &eix->eie[1]) & + imsic_mrif_atomic_read(mrif, &eix->eip[1]); + if (!eipend[0] && !eipend[1]) +#else + if (!eipend[0]) +#endif + continue; + + imin = ei * BITS_PER_TYPE(u64); + imax = ((imin + BITS_PER_TYPE(u64)) < max_msi) ? + imin + BITS_PER_TYPE(u64) : max_msi; + for (i = (!imin) ? 1 : imin; i < imax; i++) { + if (test_bit(i - imin, eipend)) + return (i << TOPEI_ID_SHIFT) | i; + } + } + + return 0; +} + +static int imsic_mrif_isel_check(u32 nr_eix, unsigned long isel) +{ + u32 num = 0; + + switch (isel) { + case IMSIC_EIDELIVERY: + case IMSIC_EITHRESHOLD: + break; + case IMSIC_EIP0 ... IMSIC_EIP63: + num = isel - IMSIC_EIP0; + break; + case IMSIC_EIE0 ... IMSIC_EIE63: + num = isel - IMSIC_EIE0; + break; + default: + return -ENOENT; + } +#ifndef CONFIG_32BIT + if (num & 0x1) + return -EINVAL; +#endif + if ((num / 2) >= nr_eix) + return -EINVAL; + + return 0; +} + +static int imsic_mrif_rmw(struct imsic_mrif *mrif, u32 nr_eix, + unsigned long isel, unsigned long *val, + unsigned long new_val, unsigned long wr_mask) +{ + bool pend; + struct imsic_mrif_eix *eix; + unsigned long *ei, num, old_val = 0; + + switch (isel) { + case IMSIC_EIDELIVERY: + old_val = imsic_mrif_atomic_rmw(mrif, &mrif->eidelivery, + new_val, wr_mask & 0x1); + break; + case IMSIC_EITHRESHOLD: + old_val = imsic_mrif_atomic_rmw(mrif, &mrif->eithreshold, + new_val, wr_mask & (IMSIC_MAX_ID - 1)); + break; + case IMSIC_EIP0 ... IMSIC_EIP63: + case IMSIC_EIE0 ... IMSIC_EIE63: + if (isel >= IMSIC_EIP0 && isel <= IMSIC_EIP63) { + pend = true; + num = isel - IMSIC_EIP0; + } else { + pend = false; + num = isel - IMSIC_EIE0; + } + + if ((num / 2) >= nr_eix) + return -EINVAL; + eix = &mrif->eix[num / 2]; + +#ifndef CONFIG_32BIT + if (num & 0x1) + return -EINVAL; + ei = (pend) ? &eix->eip[0] : &eix->eie[0]; +#else + ei = (pend) ? &eix->eip[num & 0x1] : &eix->eie[num & 0x1]; +#endif + + /* Bit0 of EIP0 or EIE0 is read-only */ + if (!num) + wr_mask &= ~BIT(0); + + old_val = imsic_mrif_atomic_rmw(mrif, ei, new_val, wr_mask); + break; + default: + return -ENOENT; + } + + if (val) + *val = old_val; + + return 0; +} + +struct imsic_vsfile_read_data { + int hgei; + u32 nr_eix; + bool clear; + struct imsic_mrif *mrif; +}; + +static void imsic_vsfile_local_read(void *data) +{ + u32 i; + struct imsic_mrif_eix *eix; + struct imsic_vsfile_read_data *idata = data; + struct imsic_mrif *mrif = idata->mrif; + unsigned long new_hstatus, old_hstatus, old_vsiselect; + + old_vsiselect = csr_read(CSR_VSISELECT); + old_hstatus = csr_read(CSR_HSTATUS); + new_hstatus = old_hstatus & ~HSTATUS_VGEIN; + new_hstatus |= ((unsigned long)idata->hgei) << HSTATUS_VGEIN_SHIFT; + csr_write(CSR_HSTATUS, new_hstatus); + + /* + * We don't use imsic_mrif_atomic_xyz() functions to store + * values in MRIF because imsic_vsfile_read() is always called + * with pointer to temporary MRIF on stack. + */ + + if (idata->clear) { + mrif->eidelivery = imsic_vs_csr_swap(IMSIC_EIDELIVERY, 0); + mrif->eithreshold = imsic_vs_csr_swap(IMSIC_EITHRESHOLD, 0); + for (i = 0; i < idata->nr_eix; i++) { + eix = &mrif->eix[i]; + eix->eip[0] = imsic_eix_swap(IMSIC_EIP0 + i * 2, 0); + eix->eie[0] = imsic_eix_swap(IMSIC_EIE0 + i * 2, 0); +#ifdef CONFIG_32BIT + eix->eip[1] = imsic_eix_swap(IMSIC_EIP0 + i * 2 + 1, 0); + eix->eie[1] = imsic_eix_swap(IMSIC_EIE0 + i * 2 + 1, 0); +#endif + } + } else { + mrif->eidelivery = imsic_vs_csr_read(IMSIC_EIDELIVERY); + mrif->eithreshold = imsic_vs_csr_read(IMSIC_EITHRESHOLD); + for (i = 0; i < idata->nr_eix; i++) { + eix = &mrif->eix[i]; + eix->eip[0] = imsic_eix_read(IMSIC_EIP0 + i * 2); + eix->eie[0] = imsic_eix_read(IMSIC_EIE0 + i * 2); +#ifdef CONFIG_32BIT + eix->eip[1] = imsic_eix_read(IMSIC_EIP0 + i * 2 + 1); + eix->eie[1] = imsic_eix_read(IMSIC_EIE0 + i * 2 + 1); +#endif + } + } + + csr_write(CSR_HSTATUS, old_hstatus); + csr_write(CSR_VSISELECT, old_vsiselect); +} + +static void imsic_vsfile_read(int vsfile_hgei, int vsfile_cpu, u32 nr_eix, + bool clear, struct imsic_mrif *mrif) +{ + struct imsic_vsfile_read_data idata; + + /* We can only read clear if we have a IMSIC VS-file */ + if (vsfile_cpu < 0 || vsfile_hgei <= 0) + return; + + /* We can only read clear on local CPU */ + idata.hgei = vsfile_hgei; + idata.nr_eix = nr_eix; + idata.clear = clear; + idata.mrif = mrif; + on_each_cpu_mask(cpumask_of(vsfile_cpu), + imsic_vsfile_local_read, &idata, 1); +} + +struct imsic_vsfile_rw_data { + int hgei; + int isel; + bool write; + unsigned long val; +}; + +static void imsic_vsfile_local_rw(void *data) +{ + struct imsic_vsfile_rw_data *idata = data; + unsigned long new_hstatus, old_hstatus, old_vsiselect; + + old_vsiselect = csr_read(CSR_VSISELECT); + old_hstatus = csr_read(CSR_HSTATUS); + new_hstatus = old_hstatus & ~HSTATUS_VGEIN; + new_hstatus |= ((unsigned long)idata->hgei) << HSTATUS_VGEIN_SHIFT; + csr_write(CSR_HSTATUS, new_hstatus); + + switch (idata->isel) { + case IMSIC_EIDELIVERY: + if (idata->write) + imsic_vs_csr_write(IMSIC_EIDELIVERY, idata->val); + else + idata->val = imsic_vs_csr_read(IMSIC_EIDELIVERY); + break; + case IMSIC_EITHRESHOLD: + if (idata->write) + imsic_vs_csr_write(IMSIC_EITHRESHOLD, idata->val); + else + idata->val = imsic_vs_csr_read(IMSIC_EITHRESHOLD); + break; + case IMSIC_EIP0 ... IMSIC_EIP63: + case IMSIC_EIE0 ... IMSIC_EIE63: +#ifndef CONFIG_32BIT + if (idata->isel & 0x1) + break; +#endif + if (idata->write) + imsic_eix_write(idata->isel, idata->val); + else + idata->val = imsic_eix_read(idata->isel); + break; + default: + break; + } + + csr_write(CSR_HSTATUS, old_hstatus); + csr_write(CSR_VSISELECT, old_vsiselect); +} + +static int imsic_vsfile_rw(int vsfile_hgei, int vsfile_cpu, u32 nr_eix, + unsigned long isel, bool write, + unsigned long *val) +{ + int rc; + struct imsic_vsfile_rw_data rdata; + + /* We can only access register if we have a IMSIC VS-file */ + if (vsfile_cpu < 0 || vsfile_hgei <= 0) + return -EINVAL; + + /* Check IMSIC register iselect */ + rc = imsic_mrif_isel_check(nr_eix, isel); + if (rc) + return rc; + + /* We can only access register on local CPU */ + rdata.hgei = vsfile_hgei; + rdata.isel = isel; + rdata.write = write; + rdata.val = (write) ? *val : 0; + on_each_cpu_mask(cpumask_of(vsfile_cpu), + imsic_vsfile_local_rw, &rdata, 1); + + if (!write) + *val = rdata.val; + + return 0; +} + +static void imsic_vsfile_local_clear(int vsfile_hgei, u32 nr_eix) +{ + u32 i; + unsigned long new_hstatus, old_hstatus, old_vsiselect; + + /* We can only zero-out if we have a IMSIC VS-file */ + if (vsfile_hgei <= 0) + return; + + old_vsiselect = csr_read(CSR_VSISELECT); + old_hstatus = csr_read(CSR_HSTATUS); + new_hstatus = old_hstatus & ~HSTATUS_VGEIN; + new_hstatus |= ((unsigned long)vsfile_hgei) << HSTATUS_VGEIN_SHIFT; + csr_write(CSR_HSTATUS, new_hstatus); + + imsic_vs_csr_write(IMSIC_EIDELIVERY, 0); + imsic_vs_csr_write(IMSIC_EITHRESHOLD, 0); + for (i = 0; i < nr_eix; i++) { + imsic_eix_write(IMSIC_EIP0 + i * 2, 0); + imsic_eix_write(IMSIC_EIE0 + i * 2, 0); +#ifdef CONFIG_32BIT + imsic_eix_write(IMSIC_EIP0 + i * 2 + 1, 0); + imsic_eix_write(IMSIC_EIE0 + i * 2 + 1, 0); +#endif + } + + csr_write(CSR_HSTATUS, old_hstatus); + csr_write(CSR_VSISELECT, old_vsiselect); +} + +static void imsic_vsfile_local_update(int vsfile_hgei, u32 nr_eix, + struct imsic_mrif *mrif) +{ + u32 i; + struct imsic_mrif_eix *eix; + unsigned long new_hstatus, old_hstatus, old_vsiselect; + + /* We can only update if we have a HW IMSIC context */ + if (vsfile_hgei <= 0) + return; + + /* + * We don't use imsic_mrif_atomic_xyz() functions to read values + * from MRIF in this function because it is always called with + * pointer to temporary MRIF on stack. + */ + + old_vsiselect = csr_read(CSR_VSISELECT); + old_hstatus = csr_read(CSR_HSTATUS); + new_hstatus = old_hstatus & ~HSTATUS_VGEIN; + new_hstatus |= ((unsigned long)vsfile_hgei) << HSTATUS_VGEIN_SHIFT; + csr_write(CSR_HSTATUS, new_hstatus); + + for (i = 0; i < nr_eix; i++) { + eix = &mrif->eix[i]; + imsic_eix_set(IMSIC_EIP0 + i * 2, eix->eip[0]); + imsic_eix_set(IMSIC_EIE0 + i * 2, eix->eie[0]); +#ifdef CONFIG_32BIT + imsic_eix_set(IMSIC_EIP0 + i * 2 + 1, eix->eip[1]); + imsic_eix_set(IMSIC_EIE0 + i * 2 + 1, eix->eie[1]); +#endif + } + imsic_vs_csr_write(IMSIC_EITHRESHOLD, mrif->eithreshold); + imsic_vs_csr_write(IMSIC_EIDELIVERY, mrif->eidelivery); + + csr_write(CSR_HSTATUS, old_hstatus); + csr_write(CSR_VSISELECT, old_vsiselect); +} + +static void imsic_vsfile_cleanup(struct imsic *imsic) +{ + int old_vsfile_hgei, old_vsfile_cpu; + unsigned long flags; + + /* + * We don't use imsic_mrif_atomic_xyz() functions to clear the + * SW-file in this function because it is always called when the + * VCPU is being destroyed. + */ + + write_lock_irqsave(&imsic->vsfile_lock, flags); + old_vsfile_hgei = imsic->vsfile_hgei; + old_vsfile_cpu = imsic->vsfile_cpu; + imsic->vsfile_cpu = imsic->vsfile_hgei = -1; + imsic->vsfile_va = NULL; + imsic->vsfile_pa = 0; + write_unlock_irqrestore(&imsic->vsfile_lock, flags); + + memset(imsic->swfile, 0, sizeof(*imsic->swfile)); + + if (old_vsfile_cpu >= 0) + kvm_riscv_aia_free_hgei(old_vsfile_cpu, old_vsfile_hgei); +} + +static void imsic_swfile_extirq_update(struct kvm_vcpu *vcpu) +{ + struct imsic *imsic = vcpu->arch.aia_context.imsic_state; + struct imsic_mrif *mrif = imsic->swfile; + + if (imsic_mrif_atomic_read(mrif, &mrif->eidelivery) && + imsic_mrif_topei(mrif, imsic->nr_eix, imsic->nr_msis)) + kvm_riscv_vcpu_set_interrupt(vcpu, IRQ_VS_EXT); + else + kvm_riscv_vcpu_unset_interrupt(vcpu, IRQ_VS_EXT); +} + +static void imsic_swfile_read(struct kvm_vcpu *vcpu, bool clear, + struct imsic_mrif *mrif) +{ + struct imsic *imsic = vcpu->arch.aia_context.imsic_state; + + /* + * We don't use imsic_mrif_atomic_xyz() functions to read and + * write SW-file and MRIF in this function because it is always + * called when VCPU is not using SW-file and the MRIF points to + * a temporary MRIF on stack. + */ + + memcpy(mrif, imsic->swfile, sizeof(*mrif)); + if (clear) { + memset(imsic->swfile, 0, sizeof(*imsic->swfile)); + kvm_riscv_vcpu_unset_interrupt(vcpu, IRQ_VS_EXT); + } +} + +static void imsic_swfile_update(struct kvm_vcpu *vcpu, + struct imsic_mrif *mrif) +{ + u32 i; + struct imsic_mrif_eix *seix, *eix; + struct imsic *imsic = vcpu->arch.aia_context.imsic_state; + struct imsic_mrif *smrif = imsic->swfile; + + imsic_mrif_atomic_write(smrif, &smrif->eidelivery, mrif->eidelivery); + imsic_mrif_atomic_write(smrif, &smrif->eithreshold, mrif->eithreshold); + for (i = 0; i < imsic->nr_eix; i++) { + seix = &smrif->eix[i]; + eix = &mrif->eix[i]; + imsic_mrif_atomic_or(smrif, &seix->eip[0], eix->eip[0]); + imsic_mrif_atomic_or(smrif, &seix->eie[0], eix->eie[0]); +#ifdef CONFIG_32BIT + imsic_mrif_atomic_or(smrif, &seix->eip[1], eix->eip[1]); + imsic_mrif_atomic_or(smrif, &seix->eie[1], eix->eie[1]); +#endif + } + + imsic_swfile_extirq_update(vcpu); +} + +void kvm_riscv_vcpu_aia_imsic_release(struct kvm_vcpu *vcpu) +{ + unsigned long flags; + struct imsic_mrif tmrif; + int old_vsfile_hgei, old_vsfile_cpu; + struct imsic *imsic = vcpu->arch.aia_context.imsic_state; + + /* Read and clear IMSIC VS-file details */ + write_lock_irqsave(&imsic->vsfile_lock, flags); + old_vsfile_hgei = imsic->vsfile_hgei; + old_vsfile_cpu = imsic->vsfile_cpu; + imsic->vsfile_cpu = imsic->vsfile_hgei = -1; + imsic->vsfile_va = NULL; + imsic->vsfile_pa = 0; + write_unlock_irqrestore(&imsic->vsfile_lock, flags); + + /* Do nothing, if no IMSIC VS-file to release */ + if (old_vsfile_cpu < 0) + return; + + /* + * At this point, all interrupt producers are still using + * the old IMSIC VS-file so we first re-direct all interrupt + * producers. + */ + + /* Purge the G-stage mapping */ + kvm_riscv_gstage_iounmap(vcpu->kvm, + vcpu->arch.aia_context.imsic_addr, + IMSIC_MMIO_PAGE_SZ); + + /* TODO: Purge the IOMMU mapping ??? */ + + /* + * At this point, all interrupt producers have been re-directed + * to somewhere else so we move register state from the old IMSIC + * VS-file to the IMSIC SW-file. + */ + + /* Read and clear register state from old IMSIC VS-file */ + memset(&tmrif, 0, sizeof(tmrif)); + imsic_vsfile_read(old_vsfile_hgei, old_vsfile_cpu, imsic->nr_hw_eix, + true, &tmrif); + + /* Update register state in IMSIC SW-file */ + imsic_swfile_update(vcpu, &tmrif); + + /* Free-up old IMSIC VS-file */ + kvm_riscv_aia_free_hgei(old_vsfile_cpu, old_vsfile_hgei); +} + +int kvm_riscv_vcpu_aia_imsic_update(struct kvm_vcpu *vcpu) +{ + unsigned long flags; + phys_addr_t new_vsfile_pa; + struct imsic_mrif tmrif; + void __iomem *new_vsfile_va; + struct kvm *kvm = vcpu->kvm; + struct kvm_run *run = vcpu->run; + struct kvm_vcpu_aia *vaia = &vcpu->arch.aia_context; + struct imsic *imsic = vaia->imsic_state; + int ret = 0, new_vsfile_hgei = -1, old_vsfile_hgei, old_vsfile_cpu; + + /* Do nothing for emulation mode */ + if (kvm->arch.aia.mode == KVM_DEV_RISCV_AIA_MODE_EMUL) + return 1; + + /* Read old IMSIC VS-file details */ + read_lock_irqsave(&imsic->vsfile_lock, flags); + old_vsfile_hgei = imsic->vsfile_hgei; + old_vsfile_cpu = imsic->vsfile_cpu; + read_unlock_irqrestore(&imsic->vsfile_lock, flags); + + /* Do nothing if we are continuing on same CPU */ + if (old_vsfile_cpu == vcpu->cpu) + return 1; + + /* Allocate new IMSIC VS-file */ + ret = kvm_riscv_aia_alloc_hgei(vcpu->cpu, vcpu, + &new_vsfile_va, &new_vsfile_pa); + if (ret <= 0) { + /* For HW acceleration mode, we can't continue */ + if (kvm->arch.aia.mode == KVM_DEV_RISCV_AIA_MODE_HWACCEL) { + run->fail_entry.hardware_entry_failure_reason = + CSR_HSTATUS; + run->fail_entry.cpu = vcpu->cpu; + run->exit_reason = KVM_EXIT_FAIL_ENTRY; + return 0; + } + + /* Release old IMSIC VS-file */ + if (old_vsfile_cpu >= 0) + kvm_riscv_vcpu_aia_imsic_release(vcpu); + + /* For automatic mode, we continue */ + goto done; + } + new_vsfile_hgei = ret; + + /* + * At this point, all interrupt producers are still using + * to the old IMSIC VS-file so we first move all interrupt + * producers to the new IMSIC VS-file. + */ + + /* Zero-out new IMSIC VS-file */ + imsic_vsfile_local_clear(new_vsfile_hgei, imsic->nr_hw_eix); + + /* Update G-stage mapping for the new IMSIC VS-file */ + ret = kvm_riscv_gstage_ioremap(kvm, vcpu->arch.aia_context.imsic_addr, + new_vsfile_pa, IMSIC_MMIO_PAGE_SZ, + true, true); + if (ret) + goto fail_free_vsfile_hgei; + + /* TODO: Update the IOMMU mapping ??? */ + + /* Update new IMSIC VS-file details in IMSIC context */ + write_lock_irqsave(&imsic->vsfile_lock, flags); + imsic->vsfile_hgei = new_vsfile_hgei; + imsic->vsfile_cpu = vcpu->cpu; + imsic->vsfile_va = new_vsfile_va; + imsic->vsfile_pa = new_vsfile_pa; + write_unlock_irqrestore(&imsic->vsfile_lock, flags); + + /* + * At this point, all interrupt producers have been moved + * to the new IMSIC VS-file so we move register state from + * the old IMSIC VS/SW-file to the new IMSIC VS-file. + */ + + memset(&tmrif, 0, sizeof(tmrif)); + if (old_vsfile_cpu >= 0) { + /* Read and clear register state from old IMSIC VS-file */ + imsic_vsfile_read(old_vsfile_hgei, old_vsfile_cpu, + imsic->nr_hw_eix, true, &tmrif); + + /* Free-up old IMSIC VS-file */ + kvm_riscv_aia_free_hgei(old_vsfile_cpu, old_vsfile_hgei); + } else { + /* Read and clear register state from IMSIC SW-file */ + imsic_swfile_read(vcpu, true, &tmrif); + } + + /* Restore register state in the new IMSIC VS-file */ + imsic_vsfile_local_update(new_vsfile_hgei, imsic->nr_hw_eix, &tmrif); + +done: + /* Set VCPU HSTATUS.VGEIN to new IMSIC VS-file */ + vcpu->arch.guest_context.hstatus &= ~HSTATUS_VGEIN; + if (new_vsfile_hgei > 0) + vcpu->arch.guest_context.hstatus |= + ((unsigned long)new_vsfile_hgei) << HSTATUS_VGEIN_SHIFT; + + /* Continue run-loop */ + return 1; + +fail_free_vsfile_hgei: + kvm_riscv_aia_free_hgei(vcpu->cpu, new_vsfile_hgei); + return ret; +} + +int kvm_riscv_vcpu_aia_imsic_rmw(struct kvm_vcpu *vcpu, unsigned long isel, + unsigned long *val, unsigned long new_val, + unsigned long wr_mask) +{ + u32 topei; + struct imsic_mrif_eix *eix; + int r, rc = KVM_INSN_CONTINUE_NEXT_SEPC; + struct imsic *imsic = vcpu->arch.aia_context.imsic_state; + + if (isel == KVM_RISCV_AIA_IMSIC_TOPEI) { + /* Read pending and enabled interrupt with highest priority */ + topei = imsic_mrif_topei(imsic->swfile, imsic->nr_eix, + imsic->nr_msis); + if (val) + *val = topei; + + /* Writes ignore value and clear top pending interrupt */ + if (topei && wr_mask) { + topei >>= TOPEI_ID_SHIFT; + if (topei) { + eix = &imsic->swfile->eix[topei / + BITS_PER_TYPE(u64)]; + clear_bit(topei & (BITS_PER_TYPE(u64) - 1), + eix->eip); + } + } + } else { + r = imsic_mrif_rmw(imsic->swfile, imsic->nr_eix, isel, + val, new_val, wr_mask); + /* Forward unknown IMSIC register to user-space */ + if (r) + rc = (r == -ENOENT) ? 0 : KVM_INSN_ILLEGAL_TRAP; + } + + if (wr_mask) + imsic_swfile_extirq_update(vcpu); + + return rc; +} + +int kvm_riscv_aia_imsic_rw_attr(struct kvm *kvm, unsigned long type, + bool write, unsigned long *val) +{ + u32 isel, vcpu_id; + unsigned long flags; + struct imsic *imsic; + struct kvm_vcpu *vcpu; + int rc, vsfile_hgei, vsfile_cpu; + + if (!kvm_riscv_aia_initialized(kvm)) + return -ENODEV; + + vcpu_id = KVM_DEV_RISCV_AIA_IMSIC_GET_VCPU(type); + vcpu = kvm_get_vcpu_by_id(kvm, vcpu_id); + if (!vcpu) + return -ENODEV; + + isel = KVM_DEV_RISCV_AIA_IMSIC_GET_ISEL(type); + imsic = vcpu->arch.aia_context.imsic_state; + + read_lock_irqsave(&imsic->vsfile_lock, flags); + + rc = 0; + vsfile_hgei = imsic->vsfile_hgei; + vsfile_cpu = imsic->vsfile_cpu; + if (vsfile_cpu < 0) { + if (write) { + rc = imsic_mrif_rmw(imsic->swfile, imsic->nr_eix, + isel, NULL, *val, -1UL); + imsic_swfile_extirq_update(vcpu); + } else + rc = imsic_mrif_rmw(imsic->swfile, imsic->nr_eix, + isel, val, 0, 0); + } + + read_unlock_irqrestore(&imsic->vsfile_lock, flags); + + if (!rc && vsfile_cpu >= 0) + rc = imsic_vsfile_rw(vsfile_hgei, vsfile_cpu, imsic->nr_eix, + isel, write, val); + + return rc; +} + +int kvm_riscv_aia_imsic_has_attr(struct kvm *kvm, unsigned long type) +{ + u32 isel, vcpu_id; + struct imsic *imsic; + struct kvm_vcpu *vcpu; + + if (!kvm_riscv_aia_initialized(kvm)) + return -ENODEV; + + vcpu_id = KVM_DEV_RISCV_AIA_IMSIC_GET_VCPU(type); + vcpu = kvm_get_vcpu_by_id(kvm, vcpu_id); + if (!vcpu) + return -ENODEV; + + isel = KVM_DEV_RISCV_AIA_IMSIC_GET_ISEL(type); + imsic = vcpu->arch.aia_context.imsic_state; + return imsic_mrif_isel_check(imsic->nr_eix, isel); +} + +void kvm_riscv_vcpu_aia_imsic_reset(struct kvm_vcpu *vcpu) +{ + struct imsic *imsic = vcpu->arch.aia_context.imsic_state; + + if (!imsic) + return; + + kvm_riscv_vcpu_aia_imsic_release(vcpu); + + memset(imsic->swfile, 0, sizeof(*imsic->swfile)); +} + +int kvm_riscv_vcpu_aia_imsic_inject(struct kvm_vcpu *vcpu, + u32 guest_index, u32 offset, u32 iid) +{ + unsigned long flags; + struct imsic_mrif_eix *eix; + struct imsic *imsic = vcpu->arch.aia_context.imsic_state; + + /* We only emulate one IMSIC MMIO page for each Guest VCPU */ + if (!imsic || !iid || guest_index || + (offset != IMSIC_MMIO_SETIPNUM_LE && + offset != IMSIC_MMIO_SETIPNUM_BE)) + return -ENODEV; + + iid = (offset == IMSIC_MMIO_SETIPNUM_BE) ? __swab32(iid) : iid; + if (imsic->nr_msis <= iid) + return -EINVAL; + + read_lock_irqsave(&imsic->vsfile_lock, flags); + + if (imsic->vsfile_cpu >= 0) { + writel(iid, imsic->vsfile_va + IMSIC_MMIO_SETIPNUM_LE); + kvm_vcpu_kick(vcpu); + } else { + eix = &imsic->swfile->eix[iid / BITS_PER_TYPE(u64)]; + set_bit(iid & (BITS_PER_TYPE(u64) - 1), eix->eip); + imsic_swfile_extirq_update(vcpu); + } + + read_unlock_irqrestore(&imsic->vsfile_lock, flags); + + return 0; +} + +static int imsic_mmio_read(struct kvm_vcpu *vcpu, struct kvm_io_device *dev, + gpa_t addr, int len, void *val) +{ + if (len != 4 || (addr & 0x3) != 0) + return -EOPNOTSUPP; + + *((u32 *)val) = 0; + + return 0; +} + +static int imsic_mmio_write(struct kvm_vcpu *vcpu, struct kvm_io_device *dev, + gpa_t addr, int len, const void *val) +{ + struct kvm_msi msi = { 0 }; + + if (len != 4 || (addr & 0x3) != 0) + return -EOPNOTSUPP; + + msi.address_hi = addr >> 32; + msi.address_lo = (u32)addr; + msi.data = *((const u32 *)val); + kvm_riscv_aia_inject_msi(vcpu->kvm, &msi); + + return 0; +}; + +static struct kvm_io_device_ops imsic_iodoev_ops = { + .read = imsic_mmio_read, + .write = imsic_mmio_write, +}; + +int kvm_riscv_vcpu_aia_imsic_init(struct kvm_vcpu *vcpu) +{ + int ret = 0; + struct imsic *imsic; + struct page *swfile_page; + struct kvm *kvm = vcpu->kvm; + + /* Fail if we have zero IDs */ + if (!kvm->arch.aia.nr_ids) + return -EINVAL; + + /* Allocate IMSIC context */ + imsic = kzalloc(sizeof(*imsic), GFP_KERNEL); + if (!imsic) + return -ENOMEM; + vcpu->arch.aia_context.imsic_state = imsic; + + /* Setup IMSIC context */ + imsic->nr_msis = kvm->arch.aia.nr_ids + 1; + rwlock_init(&imsic->vsfile_lock); + imsic->nr_eix = BITS_TO_U64(imsic->nr_msis); + imsic->nr_hw_eix = BITS_TO_U64(kvm_riscv_aia_max_ids); + imsic->vsfile_hgei = imsic->vsfile_cpu = -1; + + /* Setup IMSIC SW-file */ + swfile_page = alloc_pages(GFP_KERNEL | __GFP_ZERO, + get_order(sizeof(*imsic->swfile))); + if (!swfile_page) { + ret = -ENOMEM; + goto fail_free_imsic; + } + imsic->swfile = page_to_virt(swfile_page); + imsic->swfile_pa = page_to_phys(swfile_page); + + /* Setup IO device */ + kvm_iodevice_init(&imsic->iodev, &imsic_iodoev_ops); + mutex_lock(&kvm->slots_lock); + ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS, + vcpu->arch.aia_context.imsic_addr, + KVM_DEV_RISCV_IMSIC_SIZE, + &imsic->iodev); + mutex_unlock(&kvm->slots_lock); + if (ret) + goto fail_free_swfile; + + return 0; + +fail_free_swfile: + free_pages((unsigned long)imsic->swfile, + get_order(sizeof(*imsic->swfile))); +fail_free_imsic: + vcpu->arch.aia_context.imsic_state = NULL; + kfree(imsic); + return ret; +} + +void kvm_riscv_vcpu_aia_imsic_cleanup(struct kvm_vcpu *vcpu) +{ + struct kvm *kvm = vcpu->kvm; + struct imsic *imsic = vcpu->arch.aia_context.imsic_state; + + if (!imsic) + return; + + imsic_vsfile_cleanup(imsic); + + mutex_lock(&kvm->slots_lock); + kvm_io_bus_unregister_dev(kvm, KVM_MMIO_BUS, &imsic->iodev); + mutex_unlock(&kvm->slots_lock); + + free_pages((unsigned long)imsic->swfile, + get_order(sizeof(*imsic->swfile))); + + vcpu->arch.aia_context.imsic_state = NULL; + kfree(imsic); +} diff --git a/arch/riscv/kvm/main.c b/arch/riscv/kvm/main.c index a7112d5836376215adf12e7975b8bbd68b3be890..48ae0d4b3932457f642760b01c831bf84f5fb3bc 100644 --- a/arch/riscv/kvm/main.c +++ b/arch/riscv/kvm/main.c @@ -116,7 +116,8 @@ static int __init riscv_kvm_init(void) kvm_info("VMID %ld bits available\n", kvm_riscv_gstage_vmid_bits()); if (kvm_riscv_aia_available()) - kvm_info("AIA available\n"); + kvm_info("AIA available with %d guest external interrupts\n", + kvm_riscv_aia_nr_hgei); rc = kvm_init(sizeof(struct kvm_vcpu), 0, THIS_MODULE); if (rc) { diff --git a/arch/riscv/kvm/tlb.c b/arch/riscv/kvm/tlb.c index 0e54796006959460b8836053edd20e91c9516d01..44bc324aeeb08d824804fd1138e4ab2b0d5e2d8e 100644 --- a/arch/riscv/kvm/tlb.c +++ b/arch/riscv/kvm/tlb.c @@ -296,7 +296,7 @@ static void make_xfence_request(struct kvm *kvm, unsigned int actual_req = req; DECLARE_BITMAP(vcpu_mask, KVM_MAX_VCPUS); - bitmap_clear(vcpu_mask, 0, KVM_MAX_VCPUS); + bitmap_zero(vcpu_mask, KVM_MAX_VCPUS); kvm_for_each_vcpu(i, vcpu, kvm) { if (hbase != -1UL) { if (vcpu->vcpu_id < hbase) diff --git a/arch/riscv/kvm/vcpu.c b/arch/riscv/kvm/vcpu.c index 8bd9f2a8a0b9131b54ef9605de1a6a01aae11621..d12ef99901fc50334df504c04d9492304f513411 100644 --- a/arch/riscv/kvm/vcpu.c +++ b/arch/riscv/kvm/vcpu.c @@ -22,6 +22,8 @@ #include #include #include +#include +#include const struct _kvm_stats_desc kvm_vcpu_stats_desc[] = { KVM_GENERIC_VCPU_STATS(), @@ -57,10 +59,12 @@ static const unsigned long kvm_isa_ext_arr[] = { [KVM_RISCV_ISA_EXT_H] = RISCV_ISA_EXT_h, [KVM_RISCV_ISA_EXT_I] = RISCV_ISA_EXT_i, [KVM_RISCV_ISA_EXT_M] = RISCV_ISA_EXT_m, + [KVM_RISCV_ISA_EXT_V] = RISCV_ISA_EXT_v, KVM_ISA_EXT_ARR(SSAIA), KVM_ISA_EXT_ARR(SSTC), KVM_ISA_EXT_ARR(SVINVAL), + KVM_ISA_EXT_ARR(SVNAPOT), KVM_ISA_EXT_ARR(SVPBMT), KVM_ISA_EXT_ARR(ZBB), KVM_ISA_EXT_ARR(ZIHINTPAUSE), @@ -85,6 +89,8 @@ static bool kvm_riscv_vcpu_isa_enable_allowed(unsigned long ext) switch (ext) { case KVM_RISCV_ISA_EXT_H: return false; + case KVM_RISCV_ISA_EXT_V: + return riscv_v_vstate_ctrl_user_allowed(); default: break; } @@ -102,6 +108,7 @@ static bool kvm_riscv_vcpu_isa_disable_allowed(unsigned long ext) case KVM_RISCV_ISA_EXT_SSAIA: case KVM_RISCV_ISA_EXT_SSTC: case KVM_RISCV_ISA_EXT_SVINVAL: + case KVM_RISCV_ISA_EXT_SVNAPOT: case KVM_RISCV_ISA_EXT_ZIHINTPAUSE: case KVM_RISCV_ISA_EXT_ZBB: return false; @@ -138,6 +145,8 @@ static void kvm_riscv_reset_vcpu(struct kvm_vcpu *vcpu) kvm_riscv_vcpu_fp_reset(vcpu); + kvm_riscv_vcpu_vector_reset(vcpu); + kvm_riscv_vcpu_timer_reset(vcpu); kvm_riscv_vcpu_aia_reset(vcpu); @@ -198,6 +207,9 @@ int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu) cntx->hstatus |= HSTATUS_SPVP; cntx->hstatus |= HSTATUS_SPV; + if (kvm_riscv_vcpu_alloc_vector_context(vcpu, cntx)) + return -ENOMEM; + /* By default, make CY, TM, and IR counters accessible in VU mode */ reset_csr->scounteren = 0x7; @@ -241,6 +253,9 @@ void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu) /* Free unused pages pre-allocated for G-stage page table mappings */ kvm_mmu_free_memory_cache(&vcpu->arch.mmu_page_cache); + + /* Free vector context space for host and guest kernel */ + kvm_riscv_vcpu_free_vector_context(vcpu); } int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu) @@ -250,10 +265,12 @@ int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu) void kvm_arch_vcpu_blocking(struct kvm_vcpu *vcpu) { + kvm_riscv_aia_wakeon_hgei(vcpu, true); } void kvm_arch_vcpu_unblocking(struct kvm_vcpu *vcpu) { + kvm_riscv_aia_wakeon_hgei(vcpu, false); } int kvm_arch_vcpu_runnable(struct kvm_vcpu *vcpu) @@ -679,6 +696,9 @@ static int kvm_riscv_vcpu_set_reg(struct kvm_vcpu *vcpu, return kvm_riscv_vcpu_set_reg_isa_ext(vcpu, reg); case KVM_REG_RISCV_SBI_EXT: return kvm_riscv_vcpu_set_reg_sbi_ext(vcpu, reg); + case KVM_REG_RISCV_VECTOR: + return kvm_riscv_vcpu_set_reg_vector(vcpu, reg, + KVM_REG_RISCV_VECTOR); default: break; } @@ -708,6 +728,9 @@ static int kvm_riscv_vcpu_get_reg(struct kvm_vcpu *vcpu, return kvm_riscv_vcpu_get_reg_isa_ext(vcpu, reg); case KVM_REG_RISCV_SBI_EXT: return kvm_riscv_vcpu_get_reg_sbi_ext(vcpu, reg); + case KVM_REG_RISCV_VECTOR: + return kvm_riscv_vcpu_get_reg_vector(vcpu, reg, + KVM_REG_RISCV_VECTOR); default: break; } @@ -1002,6 +1025,9 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu) kvm_riscv_vcpu_host_fp_save(&vcpu->arch.host_context); kvm_riscv_vcpu_guest_fp_restore(&vcpu->arch.guest_context, vcpu->arch.isa); + kvm_riscv_vcpu_host_vector_save(&vcpu->arch.host_context); + kvm_riscv_vcpu_guest_vector_restore(&vcpu->arch.guest_context, + vcpu->arch.isa); kvm_riscv_vcpu_aia_load(vcpu, cpu); @@ -1021,6 +1047,9 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu) kvm_riscv_vcpu_host_fp_restore(&vcpu->arch.host_context); kvm_riscv_vcpu_timer_save(vcpu); + kvm_riscv_vcpu_guest_vector_save(&vcpu->arch.guest_context, + vcpu->arch.isa); + kvm_riscv_vcpu_host_vector_restore(&vcpu->arch.host_context); csr->vsstatus = csr_read(CSR_VSSTATUS); csr->vsie = csr_read(CSR_VSIE); diff --git a/arch/riscv/kvm/vcpu_exit.c b/arch/riscv/kvm/vcpu_exit.c index 4ea101a73d8b66ae6da9ab680b7ec90464771417..2415722c01b8e9194a8a2c87d86d70e97a9ae6f4 100644 --- a/arch/riscv/kvm/vcpu_exit.c +++ b/arch/riscv/kvm/vcpu_exit.c @@ -183,6 +183,8 @@ int kvm_riscv_vcpu_exit(struct kvm_vcpu *vcpu, struct kvm_run *run, run->exit_reason = KVM_EXIT_UNKNOWN; switch (trap->scause) { case EXC_INST_ILLEGAL: + case EXC_LOAD_MISALIGNED: + case EXC_STORE_MISALIGNED: if (vcpu->arch.guest_context.hstatus & HSTATUS_SPV) { kvm_riscv_vcpu_trap_redirect(vcpu, trap); ret = 1; diff --git a/arch/riscv/kvm/vcpu_sbi.c b/arch/riscv/kvm/vcpu_sbi.c index e52fde504433fda9ab197f6558c008794318c912..7b46e04fb6675cbe9fea91955ee5b74060462614 100644 --- a/arch/riscv/kvm/vcpu_sbi.c +++ b/arch/riscv/kvm/vcpu_sbi.c @@ -20,9 +20,7 @@ static const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_v01 = { }; #endif -#ifdef CONFIG_RISCV_PMU_SBI -extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_pmu; -#else +#ifndef CONFIG_RISCV_PMU_SBI static const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_pmu = { .extid_start = -1UL, .extid_end = -1UL, @@ -31,49 +29,49 @@ static const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_pmu = { #endif struct kvm_riscv_sbi_extension_entry { - enum KVM_RISCV_SBI_EXT_ID dis_idx; + enum KVM_RISCV_SBI_EXT_ID ext_idx; const struct kvm_vcpu_sbi_extension *ext_ptr; }; static const struct kvm_riscv_sbi_extension_entry sbi_ext[] = { { - .dis_idx = KVM_RISCV_SBI_EXT_V01, + .ext_idx = KVM_RISCV_SBI_EXT_V01, .ext_ptr = &vcpu_sbi_ext_v01, }, { - .dis_idx = KVM_RISCV_SBI_EXT_MAX, /* Can't be disabled */ + .ext_idx = KVM_RISCV_SBI_EXT_MAX, /* Can't be disabled */ .ext_ptr = &vcpu_sbi_ext_base, }, { - .dis_idx = KVM_RISCV_SBI_EXT_TIME, + .ext_idx = KVM_RISCV_SBI_EXT_TIME, .ext_ptr = &vcpu_sbi_ext_time, }, { - .dis_idx = KVM_RISCV_SBI_EXT_IPI, + .ext_idx = KVM_RISCV_SBI_EXT_IPI, .ext_ptr = &vcpu_sbi_ext_ipi, }, { - .dis_idx = KVM_RISCV_SBI_EXT_RFENCE, + .ext_idx = KVM_RISCV_SBI_EXT_RFENCE, .ext_ptr = &vcpu_sbi_ext_rfence, }, { - .dis_idx = KVM_RISCV_SBI_EXT_SRST, + .ext_idx = KVM_RISCV_SBI_EXT_SRST, .ext_ptr = &vcpu_sbi_ext_srst, }, { - .dis_idx = KVM_RISCV_SBI_EXT_HSM, + .ext_idx = KVM_RISCV_SBI_EXT_HSM, .ext_ptr = &vcpu_sbi_ext_hsm, }, { - .dis_idx = KVM_RISCV_SBI_EXT_PMU, + .ext_idx = KVM_RISCV_SBI_EXT_PMU, .ext_ptr = &vcpu_sbi_ext_pmu, }, { - .dis_idx = KVM_RISCV_SBI_EXT_EXPERIMENTAL, + .ext_idx = KVM_RISCV_SBI_EXT_EXPERIMENTAL, .ext_ptr = &vcpu_sbi_ext_experimental, }, { - .dis_idx = KVM_RISCV_SBI_EXT_VENDOR, + .ext_idx = KVM_RISCV_SBI_EXT_VENDOR, .ext_ptr = &vcpu_sbi_ext_vendor, }, }; @@ -147,7 +145,7 @@ static int riscv_vcpu_set_sbi_ext_single(struct kvm_vcpu *vcpu, return -EINVAL; for (i = 0; i < ARRAY_SIZE(sbi_ext); i++) { - if (sbi_ext[i].dis_idx == reg_num) { + if (sbi_ext[i].ext_idx == reg_num) { sext = &sbi_ext[i]; break; } @@ -155,7 +153,15 @@ static int riscv_vcpu_set_sbi_ext_single(struct kvm_vcpu *vcpu, if (!sext) return -ENOENT; - scontext->extension_disabled[sext->dis_idx] = !reg_val; + /* + * We can't set the extension status to available here, since it may + * have a probe() function which needs to confirm availability first, + * but it may be too early to call that here. We can set the status to + * unavailable, though. + */ + if (!reg_val) + scontext->ext_status[sext->ext_idx] = + KVM_RISCV_SBI_EXT_UNAVAILABLE; return 0; } @@ -172,7 +178,7 @@ static int riscv_vcpu_get_sbi_ext_single(struct kvm_vcpu *vcpu, return -EINVAL; for (i = 0; i < ARRAY_SIZE(sbi_ext); i++) { - if (sbi_ext[i].dis_idx == reg_num) { + if (sbi_ext[i].ext_idx == reg_num) { sext = &sbi_ext[i]; break; } @@ -180,7 +186,15 @@ static int riscv_vcpu_get_sbi_ext_single(struct kvm_vcpu *vcpu, if (!sext) return -ENOENT; - *reg_val = !scontext->extension_disabled[sext->dis_idx]; + /* + * If the extension status is still uninitialized, then we should probe + * to determine if it's available, but it may be too early to do that + * here. The best we can do is report that the extension has not been + * disabled, i.e. we return 1 when the extension is available and also + * when it only may be available. + */ + *reg_val = scontext->ext_status[sext->ext_idx] != + KVM_RISCV_SBI_EXT_UNAVAILABLE; return 0; } @@ -307,18 +321,32 @@ int kvm_riscv_vcpu_get_reg_sbi_ext(struct kvm_vcpu *vcpu, const struct kvm_vcpu_sbi_extension *kvm_vcpu_sbi_find_ext( struct kvm_vcpu *vcpu, unsigned long extid) { - int i; - const struct kvm_riscv_sbi_extension_entry *sext; struct kvm_vcpu_sbi_context *scontext = &vcpu->arch.sbi_context; + const struct kvm_riscv_sbi_extension_entry *entry; + const struct kvm_vcpu_sbi_extension *ext; + int i; for (i = 0; i < ARRAY_SIZE(sbi_ext); i++) { - sext = &sbi_ext[i]; - if (sext->ext_ptr->extid_start <= extid && - sext->ext_ptr->extid_end >= extid) { - if (sext->dis_idx < KVM_RISCV_SBI_EXT_MAX && - scontext->extension_disabled[sext->dis_idx]) + entry = &sbi_ext[i]; + ext = entry->ext_ptr; + + if (ext->extid_start <= extid && ext->extid_end >= extid) { + if (entry->ext_idx >= KVM_RISCV_SBI_EXT_MAX || + scontext->ext_status[entry->ext_idx] == + KVM_RISCV_SBI_EXT_AVAILABLE) + return ext; + if (scontext->ext_status[entry->ext_idx] == + KVM_RISCV_SBI_EXT_UNAVAILABLE) return NULL; - return sbi_ext[i].ext_ptr; + if (ext->probe && !ext->probe(vcpu)) { + scontext->ext_status[entry->ext_idx] = + KVM_RISCV_SBI_EXT_UNAVAILABLE; + return NULL; + } + + scontext->ext_status[entry->ext_idx] = + KVM_RISCV_SBI_EXT_AVAILABLE; + return ext; } } diff --git a/arch/riscv/kvm/vcpu_vector.c b/arch/riscv/kvm/vcpu_vector.c new file mode 100644 index 0000000000000000000000000000000000000000..edd2eecbddc2ed14666e330590272dccd52ab54a --- /dev/null +++ b/arch/riscv/kvm/vcpu_vector.c @@ -0,0 +1,186 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2022 SiFive + * + * Authors: + * Vincent Chen + * Greentime Hu + */ + +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_RISCV_ISA_V +void kvm_riscv_vcpu_vector_reset(struct kvm_vcpu *vcpu) +{ + unsigned long *isa = vcpu->arch.isa; + struct kvm_cpu_context *cntx = &vcpu->arch.guest_context; + + cntx->sstatus &= ~SR_VS; + if (riscv_isa_extension_available(isa, v)) { + cntx->sstatus |= SR_VS_INITIAL; + WARN_ON(!cntx->vector.datap); + memset(cntx->vector.datap, 0, riscv_v_vsize); + } else { + cntx->sstatus |= SR_VS_OFF; + } +} + +static void kvm_riscv_vcpu_vector_clean(struct kvm_cpu_context *cntx) +{ + cntx->sstatus &= ~SR_VS; + cntx->sstatus |= SR_VS_CLEAN; +} + +void kvm_riscv_vcpu_guest_vector_save(struct kvm_cpu_context *cntx, + unsigned long *isa) +{ + if ((cntx->sstatus & SR_VS) == SR_VS_DIRTY) { + if (riscv_isa_extension_available(isa, v)) + __kvm_riscv_vector_save(cntx); + kvm_riscv_vcpu_vector_clean(cntx); + } +} + +void kvm_riscv_vcpu_guest_vector_restore(struct kvm_cpu_context *cntx, + unsigned long *isa) +{ + if ((cntx->sstatus & SR_VS) != SR_VS_OFF) { + if (riscv_isa_extension_available(isa, v)) + __kvm_riscv_vector_restore(cntx); + kvm_riscv_vcpu_vector_clean(cntx); + } +} + +void kvm_riscv_vcpu_host_vector_save(struct kvm_cpu_context *cntx) +{ + /* No need to check host sstatus as it can be modified outside */ + if (riscv_isa_extension_available(NULL, v)) + __kvm_riscv_vector_save(cntx); +} + +void kvm_riscv_vcpu_host_vector_restore(struct kvm_cpu_context *cntx) +{ + if (riscv_isa_extension_available(NULL, v)) + __kvm_riscv_vector_restore(cntx); +} + +int kvm_riscv_vcpu_alloc_vector_context(struct kvm_vcpu *vcpu, + struct kvm_cpu_context *cntx) +{ + cntx->vector.datap = kmalloc(riscv_v_vsize, GFP_KERNEL); + if (!cntx->vector.datap) + return -ENOMEM; + + vcpu->arch.host_context.vector.datap = kzalloc(riscv_v_vsize, GFP_KERNEL); + if (!vcpu->arch.host_context.vector.datap) + return -ENOMEM; + + return 0; +} + +void kvm_riscv_vcpu_free_vector_context(struct kvm_vcpu *vcpu) +{ + kfree(vcpu->arch.guest_reset_context.vector.datap); + kfree(vcpu->arch.host_context.vector.datap); +} +#endif + +static void *kvm_riscv_vcpu_vreg_addr(struct kvm_vcpu *vcpu, + unsigned long reg_num, + size_t reg_size) +{ + struct kvm_cpu_context *cntx = &vcpu->arch.guest_context; + void *reg_val; + size_t vlenb = riscv_v_vsize / 32; + + if (reg_num < KVM_REG_RISCV_VECTOR_REG(0)) { + if (reg_size != sizeof(unsigned long)) + return NULL; + switch (reg_num) { + case KVM_REG_RISCV_VECTOR_CSR_REG(vstart): + reg_val = &cntx->vector.vstart; + break; + case KVM_REG_RISCV_VECTOR_CSR_REG(vl): + reg_val = &cntx->vector.vl; + break; + case KVM_REG_RISCV_VECTOR_CSR_REG(vtype): + reg_val = &cntx->vector.vtype; + break; + case KVM_REG_RISCV_VECTOR_CSR_REG(vcsr): + reg_val = &cntx->vector.vcsr; + break; + case KVM_REG_RISCV_VECTOR_CSR_REG(datap): + default: + return NULL; + } + } else if (reg_num <= KVM_REG_RISCV_VECTOR_REG(31)) { + if (reg_size != vlenb) + return NULL; + reg_val = cntx->vector.datap + + (reg_num - KVM_REG_RISCV_VECTOR_REG(0)) * vlenb; + } else { + return NULL; + } + + return reg_val; +} + +int kvm_riscv_vcpu_get_reg_vector(struct kvm_vcpu *vcpu, + const struct kvm_one_reg *reg, + unsigned long rtype) +{ + unsigned long *isa = vcpu->arch.isa; + unsigned long __user *uaddr = + (unsigned long __user *)(unsigned long)reg->addr; + unsigned long reg_num = reg->id & ~(KVM_REG_ARCH_MASK | + KVM_REG_SIZE_MASK | + rtype); + void *reg_val = NULL; + size_t reg_size = KVM_REG_SIZE(reg->id); + + if (rtype == KVM_REG_RISCV_VECTOR && + riscv_isa_extension_available(isa, v)) { + reg_val = kvm_riscv_vcpu_vreg_addr(vcpu, reg_num, reg_size); + } + + if (!reg_val) + return -EINVAL; + + if (copy_to_user(uaddr, reg_val, reg_size)) + return -EFAULT; + + return 0; +} + +int kvm_riscv_vcpu_set_reg_vector(struct kvm_vcpu *vcpu, + const struct kvm_one_reg *reg, + unsigned long rtype) +{ + unsigned long *isa = vcpu->arch.isa; + unsigned long __user *uaddr = + (unsigned long __user *)(unsigned long)reg->addr; + unsigned long reg_num = reg->id & ~(KVM_REG_ARCH_MASK | + KVM_REG_SIZE_MASK | + rtype); + void *reg_val = NULL; + size_t reg_size = KVM_REG_SIZE(reg->id); + + if (rtype == KVM_REG_RISCV_VECTOR && + riscv_isa_extension_available(isa, v)) { + reg_val = kvm_riscv_vcpu_vreg_addr(vcpu, reg_num, reg_size); + } + + if (!reg_val) + return -EINVAL; + + if (copy_from_user(reg_val, uaddr, reg_size)) + return -EFAULT; + + return 0; +} diff --git a/arch/riscv/kvm/vm.c b/arch/riscv/kvm/vm.c index 6ef15f78e80ffc5081dce3715f5cf13a0dca93ea..7e2b50c692c1bb583fbfb8fc187d2107f1615f78 100644 --- a/arch/riscv/kvm/vm.c +++ b/arch/riscv/kvm/vm.c @@ -55,11 +55,129 @@ void kvm_arch_destroy_vm(struct kvm *kvm) kvm_riscv_aia_destroy_vm(kvm); } +int kvm_vm_ioctl_irq_line(struct kvm *kvm, struct kvm_irq_level *irql, + bool line_status) +{ + if (!irqchip_in_kernel(kvm)) + return -ENXIO; + + return kvm_riscv_aia_inject_irq(kvm, irql->irq, irql->level); +} + +int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e, + struct kvm *kvm, int irq_source_id, + int level, bool line_status) +{ + struct kvm_msi msi; + + if (!level) + return -1; + + msi.address_lo = e->msi.address_lo; + msi.address_hi = e->msi.address_hi; + msi.data = e->msi.data; + msi.flags = e->msi.flags; + msi.devid = e->msi.devid; + + return kvm_riscv_aia_inject_msi(kvm, &msi); +} + +static int kvm_riscv_set_irq(struct kvm_kernel_irq_routing_entry *e, + struct kvm *kvm, int irq_source_id, + int level, bool line_status) +{ + return kvm_riscv_aia_inject_irq(kvm, e->irqchip.pin, level); +} + +int kvm_riscv_setup_default_irq_routing(struct kvm *kvm, u32 lines) +{ + struct kvm_irq_routing_entry *ents; + int i, rc; + + ents = kcalloc(lines, sizeof(*ents), GFP_KERNEL); + if (!ents) + return -ENOMEM; + + for (i = 0; i < lines; i++) { + ents[i].gsi = i; + ents[i].type = KVM_IRQ_ROUTING_IRQCHIP; + ents[i].u.irqchip.irqchip = 0; + ents[i].u.irqchip.pin = i; + } + rc = kvm_set_irq_routing(kvm, ents, lines, 0); + kfree(ents); + + return rc; +} + +bool kvm_arch_can_set_irq_routing(struct kvm *kvm) +{ + return irqchip_in_kernel(kvm); +} + +int kvm_set_routing_entry(struct kvm *kvm, + struct kvm_kernel_irq_routing_entry *e, + const struct kvm_irq_routing_entry *ue) +{ + int r = -EINVAL; + + switch (ue->type) { + case KVM_IRQ_ROUTING_IRQCHIP: + e->set = kvm_riscv_set_irq; + e->irqchip.irqchip = ue->u.irqchip.irqchip; + e->irqchip.pin = ue->u.irqchip.pin; + if ((e->irqchip.pin >= KVM_IRQCHIP_NUM_PINS) || + (e->irqchip.irqchip >= KVM_NR_IRQCHIPS)) + goto out; + break; + case KVM_IRQ_ROUTING_MSI: + e->set = kvm_set_msi; + e->msi.address_lo = ue->u.msi.address_lo; + e->msi.address_hi = ue->u.msi.address_hi; + e->msi.data = ue->u.msi.data; + e->msi.flags = ue->flags; + e->msi.devid = ue->u.msi.devid; + break; + default: + goto out; + } + r = 0; +out: + return r; +} + +int kvm_arch_set_irq_inatomic(struct kvm_kernel_irq_routing_entry *e, + struct kvm *kvm, int irq_source_id, int level, + bool line_status) +{ + if (!level) + return -EWOULDBLOCK; + + switch (e->type) { + case KVM_IRQ_ROUTING_MSI: + return kvm_set_msi(e, kvm, irq_source_id, level, line_status); + + case KVM_IRQ_ROUTING_IRQCHIP: + return kvm_riscv_set_irq(e, kvm, irq_source_id, + level, line_status); + } + + return -EWOULDBLOCK; +} + +bool kvm_arch_irqchip_in_kernel(struct kvm *kvm) +{ + return irqchip_in_kernel(kvm); +} + int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) { int r; switch (ext) { + case KVM_CAP_IRQCHIP: + r = kvm_riscv_aia_available(); + break; case KVM_CAP_IOEVENTFD: case KVM_CAP_DEVICE_CTRL: case KVM_CAP_USER_MEMORY: diff --git a/arch/riscv/mm/Makefile b/arch/riscv/mm/Makefile index b85e9e82f082194379a75a8a0acbb0ef025dbc4f..9c454f90fd3da21200d180da8a463d45a15da178 100644 --- a/arch/riscv/mm/Makefile +++ b/arch/riscv/mm/Makefile @@ -13,8 +13,7 @@ endif KCOV_INSTRUMENT_init.o := n obj-y += init.o -obj-y += extable.o -obj-$(CONFIG_MMU) += fault.o pageattr.o +obj-$(CONFIG_MMU) += extable.o fault.o pageattr.o obj-y += cacheflush.o obj-y += context.o obj-y += pgtable.o diff --git a/arch/riscv/mm/cacheflush.c b/arch/riscv/mm/cacheflush.c index fca532ddf3ec25b5cadc1914160bd264803212ab..fbc59b3f69f24e54d3efce50e51227ebefa21e88 100644 --- a/arch/riscv/mm/cacheflush.c +++ b/arch/riscv/mm/cacheflush.c @@ -104,9 +104,9 @@ EXPORT_SYMBOL_GPL(riscv_cbom_block_size); unsigned int riscv_cboz_block_size; EXPORT_SYMBOL_GPL(riscv_cboz_block_size); -static void cbo_get_block_size(struct device_node *node, - const char *name, u32 *block_size, - unsigned long *first_hartid) +static void __init cbo_get_block_size(struct device_node *node, + const char *name, u32 *block_size, + unsigned long *first_hartid) { unsigned long hartid; u32 val; @@ -126,7 +126,7 @@ static void cbo_get_block_size(struct device_node *node, } } -void riscv_init_cbo_blocksizes(void) +void __init riscv_init_cbo_blocksizes(void) { unsigned long cbom_hartid, cboz_hartid; u32 cbom_block_size = 0, cboz_block_size = 0; diff --git a/arch/riscv/mm/dma-noncoherent.c b/arch/riscv/mm/dma-noncoherent.c index d919efab6ebad6d88fab7545cde0a11de0adb3ad..d51a75864e53108a0e49704b73a9a83c5a57aa1d 100644 --- a/arch/riscv/mm/dma-noncoherent.c +++ b/arch/riscv/mm/dma-noncoherent.c @@ -10,7 +10,7 @@ #include #include -static bool noncoherent_supported; +static bool noncoherent_supported __ro_after_init; void arch_sync_dma_for_device(phys_addr_t paddr, size_t size, enum dma_data_direction dir) diff --git a/arch/riscv/mm/fault.c b/arch/riscv/mm/fault.c index 8685f85a7474ef096037e306b904b725f68a1ac2..6ea2cce4cc17e17a8e30a639a3d6e7b82c8d5b81 100644 --- a/arch/riscv/mm/fault.c +++ b/arch/riscv/mm/fault.c @@ -84,13 +84,13 @@ static inline void mm_fault_error(struct pt_regs *regs, unsigned long addr, vm_f BUG(); } -static inline void bad_area(struct pt_regs *regs, struct mm_struct *mm, int code, unsigned long addr) +static inline void +bad_area_nosemaphore(struct pt_regs *regs, int code, unsigned long addr) { /* * Something tried to access memory that isn't in our memory map. * Fix it, but check if it's kernel or user first. */ - mmap_read_unlock(mm); /* User mode accesses just cause a SIGSEGV */ if (user_mode(regs)) { do_trap(regs, SIGSEGV, code, addr); @@ -100,6 +100,15 @@ static inline void bad_area(struct pt_regs *regs, struct mm_struct *mm, int code no_context(regs, addr); } +static inline void +bad_area(struct pt_regs *regs, struct mm_struct *mm, int code, + unsigned long addr) +{ + mmap_read_unlock(mm); + + bad_area_nosemaphore(regs, code, addr); +} + static inline void vmalloc_fault(struct pt_regs *regs, int code, unsigned long addr) { pgd_t *pgd, *pgd_k; @@ -238,24 +247,12 @@ void handle_page_fault(struct pt_regs *regs) * only copy the information from the master page table, * nothing more. */ - if (unlikely((addr >= VMALLOC_START) && (addr < VMALLOC_END))) { + if ((!IS_ENABLED(CONFIG_MMU) || !IS_ENABLED(CONFIG_64BIT)) && + unlikely(addr >= VMALLOC_START && addr < VMALLOC_END)) { vmalloc_fault(regs, code, addr); return; } -#ifdef CONFIG_64BIT - /* - * Modules in 64bit kernels lie in their own virtual region which is not - * in the vmalloc region, but dealing with page faults in this region - * or the vmalloc region amounts to doing the same thing: checking that - * the mapping exists in init_mm.pgd and updating user page table, so - * just use vmalloc_fault. - */ - if (unlikely(addr >= MODULES_VADDR && addr < MODULES_END)) { - vmalloc_fault(regs, code, addr); - return; - } -#endif /* Enable interrupts if they were enabled in the parent context. */ if (!regs_irqs_disabled(regs)) local_irq_enable(); @@ -286,24 +283,41 @@ void handle_page_fault(struct pt_regs *regs) flags |= FAULT_FLAG_WRITE; else if (cause == EXC_INST_PAGE_FAULT) flags |= FAULT_FLAG_INSTRUCTION; -retry: - mmap_read_lock(mm); - vma = find_vma(mm, addr); - if (unlikely(!vma)) { - tsk->thread.bad_cause = cause; - bad_area(regs, mm, code, addr); - return; +#ifdef CONFIG_PER_VMA_LOCK + if (!(flags & FAULT_FLAG_USER)) + goto lock_mmap; + + vma = lock_vma_under_rcu(mm, addr); + if (!vma) + goto lock_mmap; + + if (unlikely(access_error(cause, vma))) { + vma_end_read(vma); + goto lock_mmap; } - if (likely(vma->vm_start <= addr)) - goto good_area; - if (unlikely(!(vma->vm_flags & VM_GROWSDOWN))) { - tsk->thread.bad_cause = cause; - bad_area(regs, mm, code, addr); + + fault = handle_mm_fault(vma, addr, flags | FAULT_FLAG_VMA_LOCK, regs); + vma_end_read(vma); + + if (!(fault & VM_FAULT_RETRY)) { + count_vm_vma_lock_event(VMA_LOCK_SUCCESS); + goto done; + } + count_vm_vma_lock_event(VMA_LOCK_RETRY); + + if (fault_signal_pending(fault, regs)) { + if (!user_mode(regs)) + no_context(regs, addr); return; } - if (unlikely(expand_stack(vma, addr))) { +lock_mmap: +#endif /* CONFIG_PER_VMA_LOCK */ + +retry: + vma = lock_mm_and_find_vma(mm, addr, regs); + if (unlikely(!vma)) { tsk->thread.bad_cause = cause; - bad_area(regs, mm, code, addr); + bad_area_nosemaphore(regs, code, addr); return; } @@ -311,7 +325,6 @@ void handle_page_fault(struct pt_regs *regs) * Ok, we have a good vm_area for this memory access, so * we can handle it. */ -good_area: code = SEGV_ACCERR; if (unlikely(access_error(cause, vma))) { @@ -355,6 +368,9 @@ void handle_page_fault(struct pt_regs *regs) mmap_read_unlock(mm); +#ifdef CONFIG_PER_VMA_LOCK +done: +#endif if (unlikely(fault & VM_FAULT_ERROR)) { tsk->thread.bad_cause = cause; mm_fault_error(regs, addr, fault); diff --git a/arch/riscv/mm/hugetlbpage.c b/arch/riscv/mm/hugetlbpage.c index e0ef56dc57b90a31a9ef95072f4360019ac84ba1..96225a8533ad8002e39518f87c6bab9d0e8ffb5a 100644 --- a/arch/riscv/mm/hugetlbpage.c +++ b/arch/riscv/mm/hugetlbpage.c @@ -67,13 +67,17 @@ pte_t *huge_pte_alloc(struct mm_struct *mm, for_each_napot_order(order) { if (napot_cont_size(order) == sz) { - pte = pte_alloc_map(mm, pmd, addr & napot_cont_mask(order)); + pte = pte_alloc_huge(mm, pmd, addr & napot_cont_mask(order)); break; } } out: - WARN_ON_ONCE(pte && pte_present(*pte) && !pte_huge(*pte)); + if (pte) { + pte_t pteval = ptep_get_lockless(pte); + + WARN_ON_ONCE(pte_present(pteval) && !pte_huge(pteval)); + } return pte; } @@ -114,7 +118,7 @@ pte_t *huge_pte_offset(struct mm_struct *mm, for_each_napot_order(order) { if (napot_cont_size(order) == sz) { - pte = pte_offset_kernel(pmd, addr & napot_cont_mask(order)); + pte = pte_offset_huge(pmd, addr & napot_cont_mask(order)); break; } } diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c index 4fa420faa780899b4802fc12eba567d03cd458e5..9ce504737d18582b0a91152a885d5f0686fd6423 100644 --- a/arch/riscv/mm/init.c +++ b/arch/riscv/mm/init.c @@ -267,7 +267,6 @@ static void __init setup_bootmem(void) dma_contiguous_reserve(dma32_phys_limit); if (IS_ENABLED(CONFIG_64BIT)) hugetlb_cma_reserve(PUD_SHIFT - PAGE_SHIFT); - memblock_allow_resize(); } #ifdef CONFIG_MMU @@ -357,7 +356,7 @@ static phys_addr_t __init alloc_pte_late(uintptr_t va) unsigned long vaddr; vaddr = __get_free_page(GFP_KERNEL); - BUG_ON(!vaddr || !pgtable_pte_page_ctor(virt_to_page(vaddr))); + BUG_ON(!vaddr || !pgtable_pte_page_ctor(virt_to_page((void *)vaddr))); return __pa(vaddr); } @@ -440,7 +439,7 @@ static phys_addr_t __init alloc_pmd_late(uintptr_t va) unsigned long vaddr; vaddr = __get_free_page(GFP_KERNEL); - BUG_ON(!vaddr || !pgtable_pmd_page_ctor(virt_to_page(vaddr))); + BUG_ON(!vaddr || !pgtable_pmd_page_ctor(virt_to_page((void *)vaddr))); return __pa(vaddr); } @@ -1347,7 +1346,7 @@ static void __init reserve_crashkernel(void) */ crash_base = memblock_phys_alloc_range(crash_size, PMD_SIZE, search_start, - min(search_end, (unsigned long) SZ_4G)); + min(search_end, (unsigned long)(SZ_4G - 1))); if (crash_base == 0) { /* Try again without restricting region to 32bit addressible memory */ crash_base = memblock_phys_alloc_range(crash_size, PMD_SIZE, @@ -1370,6 +1369,9 @@ void __init paging_init(void) { setup_bootmem(); setup_vm_final(); + + /* Depend on that Linear Mapping is ready */ + memblock_allow_resize(); } void __init misc_mem_init(void) @@ -1389,3 +1391,61 @@ int __meminit vmemmap_populate(unsigned long start, unsigned long end, int node, return vmemmap_populate_basepages(start, end, node, NULL); } #endif + +#if defined(CONFIG_MMU) && defined(CONFIG_64BIT) +/* + * Pre-allocates page-table pages for a specific area in the kernel + * page-table. Only the level which needs to be synchronized between + * all page-tables is allocated because the synchronization can be + * expensive. + */ +static void __init preallocate_pgd_pages_range(unsigned long start, unsigned long end, + const char *area) +{ + unsigned long addr; + const char *lvl; + + for (addr = start; addr < end && addr >= start; addr = ALIGN(addr + 1, PGDIR_SIZE)) { + pgd_t *pgd = pgd_offset_k(addr); + p4d_t *p4d; + pud_t *pud; + pmd_t *pmd; + + lvl = "p4d"; + p4d = p4d_alloc(&init_mm, pgd, addr); + if (!p4d) + goto failed; + + if (pgtable_l5_enabled) + continue; + + lvl = "pud"; + pud = pud_alloc(&init_mm, p4d, addr); + if (!pud) + goto failed; + + if (pgtable_l4_enabled) + continue; + + lvl = "pmd"; + pmd = pmd_alloc(&init_mm, pud, addr); + if (!pmd) + goto failed; + } + return; + +failed: + /* + * The pages have to be there now or they will be missing in + * process page-tables later. + */ + panic("Failed to pre-allocate %s pages for %s area\n", lvl, area); +} + +void __init pgtable_cache_init(void) +{ + preallocate_pgd_pages_range(VMALLOC_START, VMALLOC_END, "vmalloc"); + if (IS_ENABLED(CONFIG_MODULES)) + preallocate_pgd_pages_range(MODULES_VADDR, MODULES_END, "bpf/modules"); +} +#endif diff --git a/arch/riscv/net/bpf_jit.h b/arch/riscv/net/bpf_jit.h index bf9802a63061df851a8d1858a63c1e0ac7672e6c..2717f549042870cb020d90cbbd941cde490eb667 100644 --- a/arch/riscv/net/bpf_jit.h +++ b/arch/riscv/net/bpf_jit.h @@ -69,7 +69,7 @@ struct rv_jit_context { struct bpf_prog *prog; u16 *insns; /* RV insns */ int ninsns; - int body_len; + int prologue_len; int epilogue_offset; int *offset; /* BPF to RV */ int nexentries; @@ -216,8 +216,8 @@ static inline int rv_offset(int insn, int off, struct rv_jit_context *ctx) int from, to; off++; /* BPF branch is from PC+1, RV is from PC */ - from = (insn > 0) ? ctx->offset[insn - 1] : 0; - to = (insn + off > 0) ? ctx->offset[insn + off - 1] : 0; + from = (insn > 0) ? ctx->offset[insn - 1] : ctx->prologue_len; + to = (insn + off > 0) ? ctx->offset[insn + off - 1] : ctx->prologue_len; return ninsns_rvoff(to - from); } diff --git a/arch/riscv/net/bpf_jit_core.c b/arch/riscv/net/bpf_jit_core.c index 737baf8715da7eb9aa72ebdc5e63f9cd4cae1570..7a26a3e1c73cfe8c75c0090c546f83d185572e2c 100644 --- a/arch/riscv/net/bpf_jit_core.c +++ b/arch/riscv/net/bpf_jit_core.c @@ -44,7 +44,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog) unsigned int prog_size = 0, extable_size = 0; bool tmp_blinded = false, extra_pass = false; struct bpf_prog *tmp, *orig_prog = prog; - int pass = 0, prev_ninsns = 0, prologue_len, i; + int pass = 0, prev_ninsns = 0, i; struct rv_jit_data *jit_data; struct rv_jit_context *ctx; @@ -83,6 +83,12 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog) prog = orig_prog; goto out_offset; } + + if (build_body(ctx, extra_pass, NULL)) { + prog = orig_prog; + goto out_offset; + } + for (i = 0; i < prog->len; i++) { prev_ninsns += 32; ctx->offset[i] = prev_ninsns; @@ -91,12 +97,15 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog) for (i = 0; i < NR_JIT_ITERATIONS; i++) { pass++; ctx->ninsns = 0; + + bpf_jit_build_prologue(ctx); + ctx->prologue_len = ctx->ninsns; + if (build_body(ctx, extra_pass, ctx->offset)) { prog = orig_prog; goto out_offset; } - ctx->body_len = ctx->ninsns; - bpf_jit_build_prologue(ctx); + ctx->epilogue_offset = ctx->ninsns; bpf_jit_build_epilogue(ctx); @@ -162,10 +171,8 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog) if (!prog->is_func || extra_pass) { bpf_jit_binary_lock_ro(jit_data->header); - prologue_len = ctx->epilogue_offset - ctx->body_len; for (i = 0; i < prog->len; i++) - ctx->offset[i] = ninsns_rvoff(prologue_len + - ctx->offset[i]); + ctx->offset[i] = ninsns_rvoff(ctx->offset[i]); bpf_prog_fill_jited_linfo(prog, ctx->offset); out_offset: kfree(ctx->offset); diff --git a/arch/riscv/purgatory/Makefile b/arch/riscv/purgatory/Makefile index bd2e27f82532681ff124a01b28c25dd346347afe..dc20e166983e3be9257b8d9a2b4d71423a8eff92 100644 --- a/arch/riscv/purgatory/Makefile +++ b/arch/riscv/purgatory/Makefile @@ -31,7 +31,7 @@ $(obj)/strncmp.o: $(srctree)/arch/riscv/lib/strncmp.S FORCE $(obj)/sha256.o: $(srctree)/lib/crypto/sha256.c FORCE $(call if_changed_rule,cc_o_c) -CFLAGS_sha256.o := -D__DISABLE_EXPORTS +CFLAGS_sha256.o := -D__DISABLE_EXPORTS -D__NO_FORTIFY CFLAGS_string.o := -D__DISABLE_EXPORTS CFLAGS_ctype.o := -D__DISABLE_EXPORTS diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index 6dab9c1be508b9138ef7dde50db6db2ef9ff5a3a..5b39918b7042b071601becf673e2b9f05b81ec7c 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig @@ -117,6 +117,7 @@ config S390 select ARCH_SUPPORTS_ATOMIC_RMW select ARCH_SUPPORTS_DEBUG_PAGEALLOC select ARCH_SUPPORTS_HUGETLBFS + select ARCH_SUPPORTS_INT128 if CC_HAS_INT128 && CC_IS_CLANG select ARCH_SUPPORTS_NUMA_BALANCING select ARCH_SUPPORTS_PER_VMA_LOCK select ARCH_USE_BUILTIN_BSWAP diff --git a/arch/s390/Makefile b/arch/s390/Makefile index ed646c583e4fe694e1678d9e54356d370c67d7f8..5ed242897b0d221ddaca2fe84323552831c845fa 100644 --- a/arch/s390/Makefile +++ b/arch/s390/Makefile @@ -27,6 +27,7 @@ KBUILD_CFLAGS_DECOMPRESSOR += -fno-delete-null-pointer-checks -msoft-float -mbac KBUILD_CFLAGS_DECOMPRESSOR += -fno-asynchronous-unwind-tables KBUILD_CFLAGS_DECOMPRESSOR += -ffreestanding KBUILD_CFLAGS_DECOMPRESSOR += -fno-stack-protector +KBUILD_CFLAGS_DECOMPRESSOR += -fPIE KBUILD_CFLAGS_DECOMPRESSOR += $(call cc-disable-warning, address-of-packed-member) KBUILD_CFLAGS_DECOMPRESSOR += $(if $(CONFIG_DEBUG_INFO),-g) KBUILD_CFLAGS_DECOMPRESSOR += $(if $(CONFIG_DEBUG_INFO_DWARF4), $(call cc-option, -gdwarf-4,)) diff --git a/arch/s390/appldata/appldata_base.c b/arch/s390/appldata/appldata_base.c index b07b0610950ee99efeae6957f4de5b35cd52d5ff..bbefe5e86bdfd3d7c534a7d44f815d44a1586279 100644 --- a/arch/s390/appldata/appldata_base.c +++ b/arch/s390/appldata/appldata_base.c @@ -26,10 +26,10 @@ #include #include #include +#include +#include #include #include -#include -#include #include #include "appldata.h" diff --git a/arch/s390/appldata/appldata_mem.c b/arch/s390/appldata/appldata_mem.c index 21c3147bd92ad34e9f63489011b18c6baa3619c2..fc608f9b79abe6df12ca3a6a68e4ce1b82b16400 100644 --- a/arch/s390/appldata/appldata_mem.c +++ b/arch/s390/appldata/appldata_mem.c @@ -15,7 +15,7 @@ #include #include #include -#include +#include #include "appldata.h" diff --git a/arch/s390/boot/head.S b/arch/s390/boot/head.S index 3f79b9efb8034901a0a697187f5cd6f40a3e48d7..637c29c3f6e33a6835fb1b51627a35622a5fee19 100644 --- a/arch/s390/boot/head.S +++ b/arch/s390/boot/head.S @@ -67,7 +67,7 @@ ipl_start: jz .Lagain1 # skip dataset header larl %r13,.L_eof clc 0(3,%r4),0(%r13) # if it is EOFx - jz .Lagain1 # skip dateset trailer + jz .Lagain1 # skip data set trailer lgr %r5,%r2 la %r6,COMMAND_LINE-PARMAREA(%r12) lgr %r7,%r2 @@ -185,19 +185,19 @@ ipl_start: larl %r13,.Lcrash lpsw 0(%r13) - .align 8 + .balign 8 .Lwaitpsw: .quad 0x0202000180000000,.Lioint .Lnewpswmask: .quad 0x0000000180000000 - .align 8 + .balign 8 .Lorb: .long 0x00000000,0x0080ff00,.Lccws .Lirb: .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 - .align 8 + .balign 8 .Lcr6: .quad 0x00000000ff000000 - .align 8 + .balign 8 .Lcrash:.long 0x000a0000,0x00000000 - .align 8 + .balign 8 .Lccws: .rept 19 .long 0x02600050,0x00000000 .endr @@ -207,7 +207,7 @@ ipl_start: .byte 0xc8,0xd6,0xd3,0xc4 # "change rdr all keep nohold" .L_eof: .long 0xc5d6c600 /* C'EOF' */ .L_hdr: .long 0xc8c4d900 /* C'HDR' */ - .align 8 + .balign 8 .Lcpuid:.fill 8,1,0 # @@ -265,7 +265,7 @@ SYM_CODE_START_LOCAL(startup_normal) brasl %r14,startup_kernel SYM_CODE_END(startup_normal) - .align 8 + .balign 8 6: .long 0x7fffffff,0xffffffff .Lext_new_psw: .quad 0x0002000180000000,0x1b0 # disabled wait diff --git a/arch/s390/boot/head_kdump.S b/arch/s390/boot/head_kdump.S index f015469e7db9ab3eb05f77bc7904da971f94a5b1..f7107c76258c311fa92b986b5d280b8fabcaadc5 100644 --- a/arch/s390/boot/head_kdump.S +++ b/arch/s390/boot/head_kdump.S @@ -82,12 +82,12 @@ SYM_CODE_START_LOCAL(startup_kdump) # # Startup of kdump (relocated new kernel) # -.align 2 + .balign 2 startup_kdump_relocated: basr %r13,0 0: lpswe .Lrestart_psw-0b(%r13) # Start new kernel... SYM_CODE_END(startup_kdump) -.align 8 + .balign 8 .Lrestart_psw: .quad 0x0000000080000000,0x0000000000000000 + startup #else @@ -95,7 +95,7 @@ SYM_CODE_START_LOCAL(startup_kdump) larl %r13,startup_kdump_crash lpswe 0(%r13) SYM_CODE_END(startup_kdump) -.align 8 + .balign 8 startup_kdump_crash: .quad 0x0002000080000000,0x0000000000000000 + startup_kdump_crash #endif /* CONFIG_CRASH_DUMP */ diff --git a/arch/s390/boot/uv.c b/arch/s390/boot/uv.c index 0a077c0a20563035867cf1fb45f2cf211cbce9ce..1e66d2cbb0965a145730d08bf70e79d48ba1e1a9 100644 --- a/arch/s390/boot/uv.c +++ b/arch/s390/boot/uv.c @@ -47,6 +47,10 @@ void uv_query_info(void) uv_info.conf_dump_finalize_len = uvcb.conf_dump_finalize_len; uv_info.supp_att_req_hdr_ver = uvcb.supp_att_req_hdr_ver; uv_info.supp_att_pflags = uvcb.supp_att_pflags; + uv_info.supp_add_secret_req_ver = uvcb.supp_add_secret_req_ver; + uv_info.supp_add_secret_pcf = uvcb.supp_add_secret_pcf; + uv_info.supp_secret_types = uvcb.supp_secret_types; + uv_info.max_secrets = uvcb.max_secrets; } #ifdef CONFIG_PROTECTED_VIRTUALIZATION_GUEST diff --git a/arch/s390/boot/vmem.c b/arch/s390/boot/vmem.c index acb1f8b53105bdb557c99776c76e842fbc74e13f..c67f59db7a51240a4fdca8064bebe051b64a736e 100644 --- a/arch/s390/boot/vmem.c +++ b/arch/s390/boot/vmem.c @@ -45,6 +45,13 @@ static void pgtable_populate(unsigned long addr, unsigned long end, enum populat static pte_t pte_z; +static inline void kasan_populate(unsigned long start, unsigned long end, enum populate_mode mode) +{ + start = PAGE_ALIGN_DOWN(__sha(start)); + end = PAGE_ALIGN(__sha(end)); + pgtable_populate(start, end, mode); +} + static void kasan_populate_shadow(void) { pmd_t pmd_z = __pmd(__pa(kasan_early_shadow_pte) | _SEGMENT_ENTRY); @@ -95,17 +102,17 @@ static void kasan_populate_shadow(void) */ for_each_physmem_usable_range(i, &start, &end) - pgtable_populate(__sha(start), __sha(end), POPULATE_KASAN_MAP_SHADOW); + kasan_populate(start, end, POPULATE_KASAN_MAP_SHADOW); if (IS_ENABLED(CONFIG_KASAN_VMALLOC)) { untracked_end = VMALLOC_START; /* shallowly populate kasan shadow for vmalloc and modules */ - pgtable_populate(__sha(VMALLOC_START), __sha(MODULES_END), POPULATE_KASAN_SHALLOW); + kasan_populate(VMALLOC_START, MODULES_END, POPULATE_KASAN_SHALLOW); } else { untracked_end = MODULES_VADDR; } /* populate kasan shadow for untracked memory */ - pgtable_populate(__sha(ident_map_size), __sha(untracked_end), POPULATE_KASAN_ZERO_SHADOW); - pgtable_populate(__sha(MODULES_END), __sha(_REGION1_SIZE), POPULATE_KASAN_ZERO_SHADOW); + kasan_populate(ident_map_size, untracked_end, POPULATE_KASAN_ZERO_SHADOW); + kasan_populate(MODULES_END, _REGION1_SIZE, POPULATE_KASAN_ZERO_SHADOW); } static bool kasan_pgd_populate_zero_shadow(pgd_t *pgd, unsigned long addr, diff --git a/arch/s390/configs/debug_defconfig b/arch/s390/configs/debug_defconfig index be3bf03bf361850d9a0abd5cdb6644878ebec6a4..aa95cf6dfabbf39a78558e416de6853ec05e2d28 100644 --- a/arch/s390/configs/debug_defconfig +++ b/arch/s390/configs/debug_defconfig @@ -116,6 +116,7 @@ CONFIG_UNIX=y CONFIG_UNIX_DIAG=m CONFIG_XFRM_USER=m CONFIG_NET_KEY=m +CONFIG_NET_TC_SKB_EXT=y CONFIG_SMC=m CONFIG_SMC_DIAG=m CONFIG_INET=y diff --git a/arch/s390/configs/defconfig b/arch/s390/configs/defconfig index 769c7eed8b6ac67f01ac781b6eac7721c21ce3b8..f041945f91489266acc52b9c6ddf2bdb2d955e2f 100644 --- a/arch/s390/configs/defconfig +++ b/arch/s390/configs/defconfig @@ -107,6 +107,7 @@ CONFIG_UNIX=y CONFIG_UNIX_DIAG=m CONFIG_XFRM_USER=m CONFIG_NET_KEY=m +CONFIG_NET_TC_SKB_EXT=y CONFIG_SMC=m CONFIG_SMC_DIAG=m CONFIG_INET=y diff --git a/arch/s390/crypto/crc32be-vx.S b/arch/s390/crypto/crc32be-vx.S index 6ea17628ea103aee5ca4aa3211fc15bd18c50604..34ee4792689188847bf9868e829239391306f9ae 100644 --- a/arch/s390/crypto/crc32be-vx.S +++ b/arch/s390/crypto/crc32be-vx.S @@ -48,7 +48,7 @@ * * Note that the constant definitions below are extended in order to compute * intermediate results with a single VECTOR GALOIS FIELD MULTIPLY instruction. - * The righmost doubleword can be 0 to prevent contribution to the result or + * The rightmost doubleword can be 0 to prevent contribution to the result or * can be multiplied by 1 to perform an XOR without the need for a separate * VECTOR EXCLUSIVE OR instruction. * diff --git a/arch/s390/crypto/paes_s390.c b/arch/s390/crypto/paes_s390.c index 29dc827e0fe81fa2dbb6f6ac7cdced91809691b9..d29a9d908797f40d84fb9f2552b588fcf78f96c6 100644 --- a/arch/s390/crypto/paes_s390.c +++ b/arch/s390/crypto/paes_s390.c @@ -5,7 +5,7 @@ * s390 implementation of the AES Cipher Algorithm with protected keys. * * s390 Version: - * Copyright IBM Corp. 2017,2020 + * Copyright IBM Corp. 2017, 2023 * Author(s): Martin Schwidefsky * Harald Freudenberger */ @@ -132,7 +132,8 @@ static inline int __paes_keyblob2pkey(struct key_blob *kb, if (i > 0 && ret == -EAGAIN && in_task()) if (msleep_interruptible(1000)) return -EINTR; - ret = pkey_keyblob2pkey(kb->key, kb->keylen, pk); + ret = pkey_keyblob2pkey(kb->key, kb->keylen, + pk->protkey, &pk->len, &pk->type); if (ret == 0) break; } @@ -145,6 +146,7 @@ static inline int __paes_convert_key(struct s390_paes_ctx *ctx) int ret; struct pkey_protkey pkey; + pkey.len = sizeof(pkey.protkey); ret = __paes_keyblob2pkey(&ctx->kb, &pkey); if (ret) return ret; @@ -414,6 +416,9 @@ static inline int __xts_paes_convert_key(struct s390_pxts_ctx *ctx) { struct pkey_protkey pkey0, pkey1; + pkey0.len = sizeof(pkey0.protkey); + pkey1.len = sizeof(pkey1.protkey); + if (__paes_keyblob2pkey(&ctx->kb[0], &pkey0) || __paes_keyblob2pkey(&ctx->kb[1], &pkey1)) return -EINVAL; diff --git a/arch/s390/include/asm/ap.h b/arch/s390/include/asm/ap.h index d5d967166bacec1ace78ab491828387784cc3c11..40c2b82f083a3e2b752bfc6a0f1909eb3856b942 100644 --- a/arch/s390/include/asm/ap.h +++ b/arch/s390/include/asm/ap.h @@ -333,7 +333,7 @@ union ap_qact_ap_info { }; /** - * ap_qact(): Query AP combatibility type. + * ap_qact(): Query AP compatibility type. * @qid: The AP queue number * @apinfo: On input the info about the AP queue. On output the * alternate AP queue info provided by the qact function diff --git a/arch/s390/include/asm/appldata.h b/arch/s390/include/asm/appldata.h index c5bd9f4437e59d0754cbc72a6784a693312df6cf..f2240392c70807635ef5d9c5e630855f954af6ce 100644 --- a/arch/s390/include/asm/appldata.h +++ b/arch/s390/include/asm/appldata.h @@ -8,8 +8,8 @@ #ifndef _ASM_S390_APPLDATA_H #define _ASM_S390_APPLDATA_H +#include #include -#include #define APPLDATA_START_INTERVAL_REC 0x80 #define APPLDATA_STOP_REC 0x81 diff --git a/arch/s390/include/asm/asm-extable.h b/arch/s390/include/asm/asm-extable.h index 55a02a153dfc681e7c699a17ce7152a1cbe26ca5..e6532477f126d785bd683e682e2f8a56ef460b36 100644 --- a/arch/s390/include/asm/asm-extable.h +++ b/arch/s390/include/asm/asm-extable.h @@ -25,7 +25,7 @@ #define __EX_TABLE(_section, _fault, _target, _type) \ stringify_in_c(.section _section,"a";) \ - stringify_in_c(.align 4;) \ + stringify_in_c(.balign 4;) \ stringify_in_c(.long (_fault) - .;) \ stringify_in_c(.long (_target) - .;) \ stringify_in_c(.short (_type);) \ @@ -34,7 +34,7 @@ #define __EX_TABLE_UA(_section, _fault, _target, _type, _regerr, _regaddr, _len)\ stringify_in_c(.section _section,"a";) \ - stringify_in_c(.align 4;) \ + stringify_in_c(.balign 4;) \ stringify_in_c(.long (_fault) - .;) \ stringify_in_c(.long (_target) - .;) \ stringify_in_c(.short (_type);) \ diff --git a/arch/s390/include/asm/asm-prototypes.h b/arch/s390/include/asm/asm-prototypes.h index c37eb921bfbf39288d04aa7e9b3db30c1877fc44..a873e873e1ee4bdf11c1ff813afcc5129fd09fd7 100644 --- a/arch/s390/include/asm/asm-prototypes.h +++ b/arch/s390/include/asm/asm-prototypes.h @@ -6,4 +6,8 @@ #include #include +__int128_t __ashlti3(__int128_t a, int b); +__int128_t __ashrti3(__int128_t a, int b); +__int128_t __lshrti3(__int128_t a, int b); + #endif /* _ASM_S390_PROTOTYPES_H */ diff --git a/arch/s390/include/asm/cmpxchg.h b/arch/s390/include/asm/cmpxchg.h index 06e0e42f4eec9ce0526b39fe13c65fa3a05154b2..aae0315374def29d1ade4238fbe9d0edd6361c76 100644 --- a/arch/s390/include/asm/cmpxchg.h +++ b/arch/s390/include/asm/cmpxchg.h @@ -190,38 +190,18 @@ static __always_inline unsigned long __cmpxchg(unsigned long address, #define arch_cmpxchg_local arch_cmpxchg #define arch_cmpxchg64_local arch_cmpxchg -#define system_has_cmpxchg_double() 1 +#define system_has_cmpxchg128() 1 -static __always_inline int __cmpxchg_double(unsigned long p1, unsigned long p2, - unsigned long o1, unsigned long o2, - unsigned long n1, unsigned long n2) +static __always_inline u128 arch_cmpxchg128(volatile u128 *ptr, u128 old, u128 new) { - union register_pair old = { .even = o1, .odd = o2, }; - union register_pair new = { .even = n1, .odd = n2, }; - int cc; - asm volatile( " cdsg %[old],%[new],%[ptr]\n" - " ipm %[cc]\n" - " srl %[cc],28\n" - : [cc] "=&d" (cc), [old] "+&d" (old.pair) - : [new] "d" (new.pair), - [ptr] "QS" (*(unsigned long *)p1), "Q" (*(unsigned long *)p2) + : [old] "+d" (old), [ptr] "+QS" (*ptr) + : [new] "d" (new) : "memory", "cc"); - return !cc; + return old; } -#define arch_cmpxchg_double(p1, p2, o1, o2, n1, n2) \ -({ \ - typeof(p1) __p1 = (p1); \ - typeof(p2) __p2 = (p2); \ - \ - BUILD_BUG_ON(sizeof(*(p1)) != sizeof(long)); \ - BUILD_BUG_ON(sizeof(*(p2)) != sizeof(long)); \ - VM_BUG_ON((unsigned long)((__p1) + 1) != (unsigned long)(__p2));\ - __cmpxchg_double((unsigned long)__p1, (unsigned long)__p2, \ - (unsigned long)(o1), (unsigned long)(o2), \ - (unsigned long)(n1), (unsigned long)(n2)); \ -}) +#define arch_cmpxchg128 arch_cmpxchg128 #endif /* __ASM_CMPXCHG_H */ diff --git a/arch/s390/include/asm/cpacf.h b/arch/s390/include/asm/cpacf.h index 646b12981f2080ce410a65f510a368e657990105..b378e2b57ad875cd9a13f823aa5ac9559cd67e95 100644 --- a/arch/s390/include/asm/cpacf.h +++ b/arch/s390/include/asm/cpacf.h @@ -2,7 +2,7 @@ /* * CP Assist for Cryptographic Functions (CPACF) * - * Copyright IBM Corp. 2003, 2017 + * Copyright IBM Corp. 2003, 2023 * Author(s): Thomas Spatzier * Jan Glauber * Harald Freudenberger (freude@de.ibm.com) @@ -132,6 +132,11 @@ #define CPACF_PCKMO_ENC_AES_128_KEY 0x12 #define CPACF_PCKMO_ENC_AES_192_KEY 0x13 #define CPACF_PCKMO_ENC_AES_256_KEY 0x14 +#define CPACF_PCKMO_ENC_ECC_P256_KEY 0x20 +#define CPACF_PCKMO_ENC_ECC_P384_KEY 0x21 +#define CPACF_PCKMO_ENC_ECC_P521_KEY 0x22 +#define CPACF_PCKMO_ENC_ECC_ED25519_KEY 0x28 +#define CPACF_PCKMO_ENC_ECC_ED448_KEY 0x29 /* * Function codes for the PRNO (PERFORM RANDOM NUMBER OPERATION) diff --git a/arch/s390/include/asm/cpu_mf.h b/arch/s390/include/asm/cpu_mf.h index 7e417d7de5689e0b35b59e38362c32d2107c4bf3..a0de5b9b02eaafb433ea39c9871ff97c7cd18ece 100644 --- a/arch/s390/include/asm/cpu_mf.h +++ b/arch/s390/include/asm/cpu_mf.h @@ -140,7 +140,7 @@ union hws_trailer_header { unsigned int dsdes:16; /* 48-63: size of diagnostic SDE */ unsigned long long overflow; /* 64 - Overflow Count */ }; - __uint128_t val; + u128 val; }; struct hws_trailer_entry { diff --git a/arch/s390/include/asm/dma.h b/arch/s390/include/asm/dma.h index dec1c4ce628c8906719720336e8fbb18935c5965..c260adb259979eed4edf671f805e2a5c87f88752 100644 --- a/arch/s390/include/asm/dma.h +++ b/arch/s390/include/asm/dma.h @@ -2,7 +2,7 @@ #ifndef _ASM_S390_DMA_H #define _ASM_S390_DMA_H -#include +#include /* * MAX_DMA_ADDRESS is ambiguous because on s390 its completely unrelated diff --git a/arch/s390/include/asm/lowcore.h b/arch/s390/include/asm/lowcore.h index 8aa1f6530a3e42c71e8d5fc03fb1d8e83e75fa2b..69ccc464a4301af29387fce4e585330a95513459 100644 --- a/arch/s390/include/asm/lowcore.h +++ b/arch/s390/include/asm/lowcore.h @@ -118,8 +118,8 @@ struct lowcore { __u64 avg_steal_timer; /* 0x0300 */ __u64 last_update_timer; /* 0x0308 */ __u64 last_update_clock; /* 0x0310 */ - __u64 int_clock; /* 0x0318*/ - __u64 mcck_clock; /* 0x0320 */ + __u64 int_clock; /* 0x0318 */ + __u8 pad_0x0320[0x0328-0x0320]; /* 0x0320 */ __u64 clock_comparator; /* 0x0328 */ __u64 boot_clock[2]; /* 0x0330 */ diff --git a/arch/s390/include/asm/os_info.h b/arch/s390/include/asm/os_info.h index 0d1c74a7a65044f86b7dcff62a7aab17a5064b48..a4d2e103f1161b93d4d183918de5d19697d60f94 100644 --- a/arch/s390/include/asm/os_info.h +++ b/arch/s390/include/asm/os_info.h @@ -16,6 +16,9 @@ #define OS_INFO_VMCOREINFO 0 #define OS_INFO_REIPL_BLOCK 1 +#define OS_INFO_FLAGS_ENTRY 2 + +#define OS_INFO_FLAG_REIPL_CLEAR (1UL << 0) struct os_info_entry { u64 addr; @@ -30,8 +33,8 @@ struct os_info { u16 version_minor; u64 crashkernel_addr; u64 crashkernel_size; - struct os_info_entry entry[2]; - u8 reserved[4024]; + struct os_info_entry entry[3]; + u8 reserved[4004]; } __packed; void os_info_init(void); diff --git a/arch/s390/include/asm/page.h b/arch/s390/include/asm/page.h index 8a2a3b5d1e293e89082a21b070ef8e51746a72e7..a9c138fcd2ad36faebc7836be05e9970f44bd1a6 100644 --- a/arch/s390/include/asm/page.h +++ b/arch/s390/include/asm/page.h @@ -19,7 +19,7 @@ #define PAGE_SHIFT _PAGE_SHIFT #define PAGE_SIZE _PAGE_SIZE #define PAGE_MASK _PAGE_MASK -#define PAGE_DEFAULT_ACC 0 +#define PAGE_DEFAULT_ACC _AC(0, UL) /* storage-protection override */ #define PAGE_SPO_ACC 9 #define PAGE_DEFAULT_KEY (PAGE_DEFAULT_ACC << 4) @@ -179,8 +179,6 @@ int arch_make_page_accessible(struct page *page); #define HAVE_ARCH_MAKE_PAGE_ACCESSIBLE #endif -#endif /* !__ASSEMBLY__ */ - #define __PAGE_OFFSET 0x0UL #define PAGE_OFFSET 0x0UL @@ -204,6 +202,8 @@ int arch_make_page_accessible(struct page *page); #define VM_DATA_DEFAULT_FLAGS VM_DATA_FLAGS_NON_EXEC +#endif /* !__ASSEMBLY__ */ + #include #include diff --git a/arch/s390/include/asm/percpu.h b/arch/s390/include/asm/percpu.h index 081837b391e353a4467b194719671e4bd435e3a9..264095dd84bc7f50cfea2091be09b8ec64b0cf26 100644 --- a/arch/s390/include/asm/percpu.h +++ b/arch/s390/include/asm/percpu.h @@ -148,6 +148,22 @@ #define this_cpu_cmpxchg_4(pcp, oval, nval) arch_this_cpu_cmpxchg(pcp, oval, nval) #define this_cpu_cmpxchg_8(pcp, oval, nval) arch_this_cpu_cmpxchg(pcp, oval, nval) +#define this_cpu_cmpxchg64(pcp, o, n) this_cpu_cmpxchg_8(pcp, o, n) + +#define this_cpu_cmpxchg128(pcp, oval, nval) \ +({ \ + typedef typeof(pcp) pcp_op_T__; \ + u128 old__, new__, ret__; \ + pcp_op_T__ *ptr__; \ + old__ = oval; \ + new__ = nval; \ + preempt_disable_notrace(); \ + ptr__ = raw_cpu_ptr(&(pcp)); \ + ret__ = cmpxchg128((void *)ptr__, old__, new__); \ + preempt_enable_notrace(); \ + ret__; \ +}) + #define arch_this_cpu_xchg(pcp, nval) \ ({ \ typeof(pcp) *ptr__; \ @@ -164,24 +180,6 @@ #define this_cpu_xchg_4(pcp, nval) arch_this_cpu_xchg(pcp, nval) #define this_cpu_xchg_8(pcp, nval) arch_this_cpu_xchg(pcp, nval) -#define arch_this_cpu_cmpxchg_double(pcp1, pcp2, o1, o2, n1, n2) \ -({ \ - typeof(pcp1) *p1__; \ - typeof(pcp2) *p2__; \ - int ret__; \ - \ - preempt_disable_notrace(); \ - p1__ = raw_cpu_ptr(&(pcp1)); \ - p2__ = raw_cpu_ptr(&(pcp2)); \ - ret__ = __cmpxchg_double((unsigned long)p1__, (unsigned long)p2__, \ - (unsigned long)(o1), (unsigned long)(o2), \ - (unsigned long)(n1), (unsigned long)(n2)); \ - preempt_enable_notrace(); \ - ret__; \ -}) - -#define this_cpu_cmpxchg_double_8 arch_this_cpu_cmpxchg_double - #include #endif /* __ARCH_S390_PERCPU__ */ diff --git a/arch/s390/include/asm/pgtable.h b/arch/s390/include/asm/pgtable.h index 6822a11c2c8ad35627b23fc3910bdaf266c9bada..c55f3c3365af8eea424648cc9ba319a33ffdf367 100644 --- a/arch/s390/include/asm/pgtable.h +++ b/arch/s390/include/asm/pgtable.h @@ -42,9 +42,6 @@ static inline void update_page_count(int level, long count) atomic_long_add(count, &direct_pages_count[level]); } -struct seq_file; -void arch_report_meminfo(struct seq_file *m); - /* * The S390 doesn't have any external MMU info: the kernel page * tables contain all the necessary information. diff --git a/arch/s390/include/asm/physmem_info.h b/arch/s390/include/asm/physmem_info.h index 8e9c582592b3f18db90864e09d74c0357224772e..9e41a74fce9ac64fdf9de24f4e421f69e506d280 100644 --- a/arch/s390/include/asm/physmem_info.h +++ b/arch/s390/include/asm/physmem_info.h @@ -3,6 +3,7 @@ #define _ASM_S390_MEM_DETECT_H #include +#include enum physmem_info_source { MEM_DETECT_NONE = 0, @@ -133,7 +134,7 @@ static inline const char *get_rr_type_name(enum reserved_range_type t) #define for_each_physmem_reserved_type_range(t, range, p_start, p_end) \ for (range = &physmem_info.reserved[t], *p_start = range->start, *p_end = range->end; \ - range && range->end; range = range->chain, \ + range && range->end; range = range->chain ? __va(range->chain) : NULL, \ *p_start = range ? range->start : 0, *p_end = range ? range->end : 0) static inline struct reserved_range *__physmem_reserved_next(enum reserved_range_type *t, @@ -145,7 +146,7 @@ static inline struct reserved_range *__physmem_reserved_next(enum reserved_range return range; } if (range->chain) - return range->chain; + return __va(range->chain); while (++*t < RR_MAX) { range = &physmem_info.reserved[*t]; if (range->end) diff --git a/arch/s390/include/asm/pkey.h b/arch/s390/include/asm/pkey.h index dd3d20c332ace4492240722f62c7b6c3b9e5a705..47d80a7451a6692c224e924e30eebe661d7bbf3f 100644 --- a/arch/s390/include/asm/pkey.h +++ b/arch/s390/include/asm/pkey.h @@ -2,7 +2,7 @@ /* * Kernelspace interface to the pkey device driver * - * Copyright IBM Corp. 2016,2019 + * Copyright IBM Corp. 2016, 2023 * * Author: Harald Freudenberger * @@ -23,6 +23,6 @@ * @return 0 on success, negative errno value on failure */ int pkey_keyblob2pkey(const u8 *key, u32 keylen, - struct pkey_protkey *protkey); + u8 *protkey, u32 *protkeylen, u32 *protkeytype); #endif /* _KAPI_PKEY_H */ diff --git a/arch/s390/include/asm/ptrace.h b/arch/s390/include/asm/ptrace.h index bfb8c3cb8aeea6a7b79e26846b3e616fe95ec287..d28bf8fb279959409397b60e82086e0fa56e34d2 100644 --- a/arch/s390/include/asm/ptrace.h +++ b/arch/s390/include/asm/ptrace.h @@ -23,7 +23,31 @@ #define _PIF_GUEST_FAULT BIT(PIF_GUEST_FAULT) #define _PIF_FTRACE_FULL_REGS BIT(PIF_FTRACE_FULL_REGS) -#ifndef __ASSEMBLY__ +#define PSW32_MASK_PER _AC(0x40000000, UL) +#define PSW32_MASK_DAT _AC(0x04000000, UL) +#define PSW32_MASK_IO _AC(0x02000000, UL) +#define PSW32_MASK_EXT _AC(0x01000000, UL) +#define PSW32_MASK_KEY _AC(0x00F00000, UL) +#define PSW32_MASK_BASE _AC(0x00080000, UL) /* Always one */ +#define PSW32_MASK_MCHECK _AC(0x00040000, UL) +#define PSW32_MASK_WAIT _AC(0x00020000, UL) +#define PSW32_MASK_PSTATE _AC(0x00010000, UL) +#define PSW32_MASK_ASC _AC(0x0000C000, UL) +#define PSW32_MASK_CC _AC(0x00003000, UL) +#define PSW32_MASK_PM _AC(0x00000f00, UL) +#define PSW32_MASK_RI _AC(0x00000080, UL) + +#define PSW32_ADDR_AMODE _AC(0x80000000, UL) +#define PSW32_ADDR_INSN _AC(0x7FFFFFFF, UL) + +#define PSW32_DEFAULT_KEY ((PAGE_DEFAULT_ACC) << 20) + +#define PSW32_ASC_PRIMARY _AC(0x00000000, UL) +#define PSW32_ASC_ACCREG _AC(0x00004000, UL) +#define PSW32_ASC_SECONDARY _AC(0x00008000, UL) +#define PSW32_ASC_HOME _AC(0x0000C000, UL) + +#define PSW_DEFAULT_KEY ((PAGE_DEFAULT_ACC) << 52) #define PSW_KERNEL_BITS (PSW_DEFAULT_KEY | PSW_MASK_BASE | PSW_ASC_HOME | \ PSW_MASK_EA | PSW_MASK_BA | PSW_MASK_DAT) @@ -31,6 +55,8 @@ PSW_DEFAULT_KEY | PSW_MASK_BASE | PSW_MASK_MCHECK | \ PSW_MASK_PSTATE | PSW_ASC_PRIMARY) +#ifndef __ASSEMBLY__ + struct psw_bits { unsigned long : 1; unsigned long per : 1; /* PER-Mask */ @@ -71,30 +97,6 @@ enum { &(*(struct psw_bits *)(&(__psw))); \ })) -#define PSW32_MASK_PER 0x40000000UL -#define PSW32_MASK_DAT 0x04000000UL -#define PSW32_MASK_IO 0x02000000UL -#define PSW32_MASK_EXT 0x01000000UL -#define PSW32_MASK_KEY 0x00F00000UL -#define PSW32_MASK_BASE 0x00080000UL /* Always one */ -#define PSW32_MASK_MCHECK 0x00040000UL -#define PSW32_MASK_WAIT 0x00020000UL -#define PSW32_MASK_PSTATE 0x00010000UL -#define PSW32_MASK_ASC 0x0000C000UL -#define PSW32_MASK_CC 0x00003000UL -#define PSW32_MASK_PM 0x00000f00UL -#define PSW32_MASK_RI 0x00000080UL - -#define PSW32_ADDR_AMODE 0x80000000UL -#define PSW32_ADDR_INSN 0x7FFFFFFFUL - -#define PSW32_DEFAULT_KEY (((u32)PAGE_DEFAULT_ACC) << 20) - -#define PSW32_ASC_PRIMARY 0x00000000UL -#define PSW32_ASC_ACCREG 0x00004000UL -#define PSW32_ASC_SECONDARY 0x00008000UL -#define PSW32_ASC_HOME 0x0000C000UL - typedef struct { unsigned int mask; unsigned int addr; diff --git a/arch/s390/include/asm/thread_info.h b/arch/s390/include/asm/thread_info.h index c7c97921ed8d2e7928c5c13b23a07998f45f7dc6..a674c7d25da5a1790367ea238d7b4c5b11327639 100644 --- a/arch/s390/include/asm/thread_info.h +++ b/arch/s390/include/asm/thread_info.h @@ -52,9 +52,6 @@ struct thread_info { struct task_struct; -void arch_release_task_struct(struct task_struct *tsk); -int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src); - void arch_setup_new_exec(void); #define arch_setup_new_exec arch_setup_new_exec diff --git a/arch/s390/include/asm/timex.h b/arch/s390/include/asm/timex.h index ce878e85b6e4e9a2c7c2f6f32a9dcd6bbc4087bb..4d646659a5f582564290d23f15a3e1b748e00617 100644 --- a/arch/s390/include/asm/timex.h +++ b/arch/s390/include/asm/timex.h @@ -63,7 +63,7 @@ static inline int store_tod_clock_ext_cc(union tod_clock *clk) return cc; } -static inline void store_tod_clock_ext(union tod_clock *tod) +static __always_inline void store_tod_clock_ext(union tod_clock *tod) { asm volatile("stcke %0" : "=Q" (*tod) : : "cc"); } @@ -177,7 +177,7 @@ static inline void local_tick_enable(unsigned long comp) typedef unsigned long cycles_t; -static inline unsigned long get_tod_clock(void) +static __always_inline unsigned long get_tod_clock(void) { union tod_clock clk; @@ -204,6 +204,11 @@ void init_cpu_timer(void); extern union tod_clock tod_clock_base; +static __always_inline unsigned long __get_tod_clock_monotonic(void) +{ + return get_tod_clock() - tod_clock_base.tod; +} + /** * get_clock_monotonic - returns current time in clock rate units * @@ -216,7 +221,7 @@ static inline unsigned long get_tod_clock_monotonic(void) unsigned long tod; preempt_disable_notrace(); - tod = get_tod_clock() - tod_clock_base.tod; + tod = __get_tod_clock_monotonic(); preempt_enable_notrace(); return tod; } @@ -240,7 +245,7 @@ static inline unsigned long get_tod_clock_monotonic(void) * -> ns = (th * 125) + ((tl * 125) >> 9); * */ -static inline unsigned long tod_to_ns(unsigned long todval) +static __always_inline unsigned long tod_to_ns(unsigned long todval) { return ((todval >> 9) * 125) + (((todval & 0x1ff) * 125) >> 9); } diff --git a/arch/s390/include/asm/uv.h b/arch/s390/include/asm/uv.h index 28a9ad57b6f16ca30cf2be582eb047425bc7827b..d6bb2f4f78d1f495e45098707136091689d6a326 100644 --- a/arch/s390/include/asm/uv.h +++ b/arch/s390/include/asm/uv.h @@ -58,6 +58,9 @@ #define UVC_CMD_SET_SHARED_ACCESS 0x1000 #define UVC_CMD_REMOVE_SHARED_ACCESS 0x1001 #define UVC_CMD_RETR_ATTEST 0x1020 +#define UVC_CMD_ADD_SECRET 0x1031 +#define UVC_CMD_LIST_SECRETS 0x1033 +#define UVC_CMD_LOCK_SECRETS 0x1034 /* Bits in installed uv calls */ enum uv_cmds_inst { @@ -88,6 +91,9 @@ enum uv_cmds_inst { BIT_UVC_CMD_DUMP_CPU = 26, BIT_UVC_CMD_DUMP_COMPLETE = 27, BIT_UVC_CMD_RETR_ATTEST = 28, + BIT_UVC_CMD_ADD_SECRET = 29, + BIT_UVC_CMD_LIST_SECRETS = 30, + BIT_UVC_CMD_LOCK_SECRETS = 31, }; enum uv_feat_ind { @@ -117,7 +123,7 @@ struct uv_cb_qui { u32 reserved70[3]; /* 0x0070 */ u32 max_num_sec_conf; /* 0x007c */ u64 max_guest_stor_addr; /* 0x0080 */ - u8 reserved88[158 - 136]; /* 0x0088 */ + u8 reserved88[0x9e - 0x88]; /* 0x0088 */ u16 max_guest_cpu_id; /* 0x009e */ u64 uv_feature_indications; /* 0x00a0 */ u64 reserveda8; /* 0x00a8 */ @@ -129,7 +135,12 @@ struct uv_cb_qui { u64 reservedd8; /* 0x00d8 */ u64 supp_att_req_hdr_ver; /* 0x00e0 */ u64 supp_att_pflags; /* 0x00e8 */ - u8 reservedf0[256 - 240]; /* 0x00f0 */ + u64 reservedf0; /* 0x00f0 */ + u64 supp_add_secret_req_ver; /* 0x00f8 */ + u64 supp_add_secret_pcf; /* 0x0100 */ + u64 supp_secret_types; /* 0x0180 */ + u16 max_secrets; /* 0x0110 */ + u8 reserved112[0x120 - 0x112]; /* 0x0112 */ } __packed __aligned(8); /* Initialize Ultravisor */ @@ -292,6 +303,19 @@ struct uv_cb_dump_complete { u64 reserved30[5]; } __packed __aligned(8); +/* + * A common UV call struct for pv guests that contains a single address + * Examples: + * Add Secret + * List Secrets + */ +struct uv_cb_guest_addr { + struct uv_cb_header header; + u64 reserved08[3]; + u64 addr; + u64 reserved28[4]; +} __packed __aligned(8); + static inline int __uv_call(unsigned long r1, unsigned long r2) { int cc; @@ -365,6 +389,10 @@ struct uv_info { unsigned long conf_dump_finalize_len; unsigned long supp_att_req_hdr_ver; unsigned long supp_att_pflags; + unsigned long supp_add_secret_req_ver; + unsigned long supp_add_secret_pcf; + unsigned long supp_secret_types; + unsigned short max_secrets; }; extern struct uv_info uv_info; diff --git a/arch/s390/include/uapi/asm/cmb.h b/arch/s390/include/uapi/asm/cmb.h index ecbe9494140396345f33aeddaee56b1bf3a7a13d..115434ab98fb611243fac92386e4cd3b08aa8383 100644 --- a/arch/s390/include/uapi/asm/cmb.h +++ b/arch/s390/include/uapi/asm/cmb.h @@ -31,7 +31,7 @@ struct cmbdata { __u64 size; __u64 elapsed_time; - /* basic and exended format: */ + /* basic and extended format: */ __u64 ssch_rsch_count; __u64 sample_count; __u64 device_connect_time; diff --git a/arch/s390/include/uapi/asm/dasd.h b/arch/s390/include/uapi/asm/dasd.h index 9c49c3d67cd56d79589126d5f5f1d15d514a999b..b11d988004584527e4e54e9ed77bae0a4c52b120 100644 --- a/arch/s390/include/uapi/asm/dasd.h +++ b/arch/s390/include/uapi/asm/dasd.h @@ -24,7 +24,7 @@ /* * struct dasd_information2_t * represents any data about the device, which is visible to userspace. - * including foramt and featueres. + * including format and featueres. */ typedef struct dasd_information2_t { unsigned int devno; /* S/390 devno */ diff --git a/arch/s390/include/uapi/asm/pkey.h b/arch/s390/include/uapi/asm/pkey.h index 924b876f992c15e0efc4b8cf7094183987cc8bc3..5faf0a1d2c1670d854f0f440ea0554b3908d14c2 100644 --- a/arch/s390/include/uapi/asm/pkey.h +++ b/arch/s390/include/uapi/asm/pkey.h @@ -2,7 +2,7 @@ /* * Userspace interface to the pkey device driver * - * Copyright IBM Corp. 2017, 2019 + * Copyright IBM Corp. 2017, 2023 * * Author: Harald Freudenberger * @@ -32,10 +32,15 @@ #define MINKEYBLOBSIZE SECKEYBLOBSIZE /* defines for the type field within the pkey_protkey struct */ -#define PKEY_KEYTYPE_AES_128 1 -#define PKEY_KEYTYPE_AES_192 2 -#define PKEY_KEYTYPE_AES_256 3 -#define PKEY_KEYTYPE_ECC 4 +#define PKEY_KEYTYPE_AES_128 1 +#define PKEY_KEYTYPE_AES_192 2 +#define PKEY_KEYTYPE_AES_256 3 +#define PKEY_KEYTYPE_ECC 4 +#define PKEY_KEYTYPE_ECC_P256 5 +#define PKEY_KEYTYPE_ECC_P384 6 +#define PKEY_KEYTYPE_ECC_P521 7 +#define PKEY_KEYTYPE_ECC_ED25519 8 +#define PKEY_KEYTYPE_ECC_ED448 9 /* the newer ioctls use a pkey_key_type enum for type information */ enum pkey_key_type { @@ -348,7 +353,7 @@ struct pkey_kblob2pkey2 { * Is able to find out which type of secure key is given (CCA AES secure * key, CCA AES cipher key, CCA ECC private key, EP11 AES key, EP11 ECC private * key) and tries to find all matching crypto cards based on the MKVP and maybe - * other criterias (like CCA AES cipher keys need a CEX5C or higher, EP11 keys + * other criteria (like CCA AES cipher keys need a CEX5C or higher, EP11 keys * with BLOB_PKEY_EXTRACTABLE need a CEX7 and EP11 api version 4). The list of * APQNs is further filtered by the key's mkvp which needs to match to either * the current mkvp (CCA and EP11) or the alternate mkvp (old mkvp, CCA adapters @@ -365,7 +370,7 @@ struct pkey_kblob2pkey2 { * is empty (apqn_entries is 0) the apqn_entries field is updated to the number * of apqn targets found and the ioctl returns with 0. If apqn_entries is > 0 * but the number of apqn targets does not fit into the list, the apqn_targets - * field is updatedd with the number of reqired entries but there are no apqn + * field is updated with the number of required entries but there are no apqn * values stored in the list and the ioctl returns with ENOSPC. If no matching * APQN is found, the ioctl returns with 0 but the apqn_entries value is 0. */ @@ -403,7 +408,7 @@ struct pkey_apqns4key { * is empty (apqn_entries is 0) the apqn_entries field is updated to the number * of apqn targets found and the ioctl returns with 0. If apqn_entries is > 0 * but the number of apqn targets does not fit into the list, the apqn_targets - * field is updatedd with the number of reqired entries but there are no apqn + * field is updated with the number of required entries but there are no apqn * values stored in the list and the ioctl returns with ENOSPC. If no matching * APQN is found, the ioctl returns with 0 but the apqn_entries value is 0. */ diff --git a/arch/s390/include/uapi/asm/ptrace.h b/arch/s390/include/uapi/asm/ptrace.h index ad64d673b5e6bb6372bf4e9ec0694c47d469c90b..f0fe3bcc78a87357b205782b40f21554e053f789 100644 --- a/arch/s390/include/uapi/asm/ptrace.h +++ b/arch/s390/include/uapi/asm/ptrace.h @@ -166,6 +166,64 @@ #endif /* __s390x__ */ +#ifndef __s390x__ + +#define PSW_MASK_PER _AC(0x40000000, UL) +#define PSW_MASK_DAT _AC(0x04000000, UL) +#define PSW_MASK_IO _AC(0x02000000, UL) +#define PSW_MASK_EXT _AC(0x01000000, UL) +#define PSW_MASK_KEY _AC(0x00F00000, UL) +#define PSW_MASK_BASE _AC(0x00080000, UL) /* always one */ +#define PSW_MASK_MCHECK _AC(0x00040000, UL) +#define PSW_MASK_WAIT _AC(0x00020000, UL) +#define PSW_MASK_PSTATE _AC(0x00010000, UL) +#define PSW_MASK_ASC _AC(0x0000C000, UL) +#define PSW_MASK_CC _AC(0x00003000, UL) +#define PSW_MASK_PM _AC(0x00000F00, UL) +#define PSW_MASK_RI _AC(0x00000000, UL) +#define PSW_MASK_EA _AC(0x00000000, UL) +#define PSW_MASK_BA _AC(0x00000000, UL) + +#define PSW_MASK_USER _AC(0x0000FF00, UL) + +#define PSW_ADDR_AMODE _AC(0x80000000, UL) +#define PSW_ADDR_INSN _AC(0x7FFFFFFF, UL) + +#define PSW_ASC_PRIMARY _AC(0x00000000, UL) +#define PSW_ASC_ACCREG _AC(0x00004000, UL) +#define PSW_ASC_SECONDARY _AC(0x00008000, UL) +#define PSW_ASC_HOME _AC(0x0000C000, UL) + +#else /* __s390x__ */ + +#define PSW_MASK_PER _AC(0x4000000000000000, UL) +#define PSW_MASK_DAT _AC(0x0400000000000000, UL) +#define PSW_MASK_IO _AC(0x0200000000000000, UL) +#define PSW_MASK_EXT _AC(0x0100000000000000, UL) +#define PSW_MASK_BASE _AC(0x0000000000000000, UL) +#define PSW_MASK_KEY _AC(0x00F0000000000000, UL) +#define PSW_MASK_MCHECK _AC(0x0004000000000000, UL) +#define PSW_MASK_WAIT _AC(0x0002000000000000, UL) +#define PSW_MASK_PSTATE _AC(0x0001000000000000, UL) +#define PSW_MASK_ASC _AC(0x0000C00000000000, UL) +#define PSW_MASK_CC _AC(0x0000300000000000, UL) +#define PSW_MASK_PM _AC(0x00000F0000000000, UL) +#define PSW_MASK_RI _AC(0x0000008000000000, UL) +#define PSW_MASK_EA _AC(0x0000000100000000, UL) +#define PSW_MASK_BA _AC(0x0000000080000000, UL) + +#define PSW_MASK_USER _AC(0x0000FF0180000000, UL) + +#define PSW_ADDR_AMODE _AC(0x0000000000000000, UL) +#define PSW_ADDR_INSN _AC(0xFFFFFFFFFFFFFFFF, UL) + +#define PSW_ASC_PRIMARY _AC(0x0000000000000000, UL) +#define PSW_ASC_ACCREG _AC(0x0000400000000000, UL) +#define PSW_ASC_SECONDARY _AC(0x0000800000000000, UL) +#define PSW_ASC_HOME _AC(0x0000C00000000000, UL) + +#endif /* __s390x__ */ + #define NUM_GPRS 16 #define NUM_FPRS 16 #define NUM_CRS 16 @@ -214,69 +272,6 @@ typedef struct { unsigned long addr; } __attribute__ ((aligned(8))) psw_t; -#ifndef __s390x__ - -#define PSW_MASK_PER 0x40000000UL -#define PSW_MASK_DAT 0x04000000UL -#define PSW_MASK_IO 0x02000000UL -#define PSW_MASK_EXT 0x01000000UL -#define PSW_MASK_KEY 0x00F00000UL -#define PSW_MASK_BASE 0x00080000UL /* always one */ -#define PSW_MASK_MCHECK 0x00040000UL -#define PSW_MASK_WAIT 0x00020000UL -#define PSW_MASK_PSTATE 0x00010000UL -#define PSW_MASK_ASC 0x0000C000UL -#define PSW_MASK_CC 0x00003000UL -#define PSW_MASK_PM 0x00000F00UL -#define PSW_MASK_RI 0x00000000UL -#define PSW_MASK_EA 0x00000000UL -#define PSW_MASK_BA 0x00000000UL - -#define PSW_MASK_USER 0x0000FF00UL - -#define PSW_ADDR_AMODE 0x80000000UL -#define PSW_ADDR_INSN 0x7FFFFFFFUL - -#define PSW_DEFAULT_KEY (((unsigned long) PAGE_DEFAULT_ACC) << 20) - -#define PSW_ASC_PRIMARY 0x00000000UL -#define PSW_ASC_ACCREG 0x00004000UL -#define PSW_ASC_SECONDARY 0x00008000UL -#define PSW_ASC_HOME 0x0000C000UL - -#else /* __s390x__ */ - -#define PSW_MASK_PER 0x4000000000000000UL -#define PSW_MASK_DAT 0x0400000000000000UL -#define PSW_MASK_IO 0x0200000000000000UL -#define PSW_MASK_EXT 0x0100000000000000UL -#define PSW_MASK_BASE 0x0000000000000000UL -#define PSW_MASK_KEY 0x00F0000000000000UL -#define PSW_MASK_MCHECK 0x0004000000000000UL -#define PSW_MASK_WAIT 0x0002000000000000UL -#define PSW_MASK_PSTATE 0x0001000000000000UL -#define PSW_MASK_ASC 0x0000C00000000000UL -#define PSW_MASK_CC 0x0000300000000000UL -#define PSW_MASK_PM 0x00000F0000000000UL -#define PSW_MASK_RI 0x0000008000000000UL -#define PSW_MASK_EA 0x0000000100000000UL -#define PSW_MASK_BA 0x0000000080000000UL - -#define PSW_MASK_USER 0x0000FF0180000000UL - -#define PSW_ADDR_AMODE 0x0000000000000000UL -#define PSW_ADDR_INSN 0xFFFFFFFFFFFFFFFFUL - -#define PSW_DEFAULT_KEY (((unsigned long) PAGE_DEFAULT_ACC) << 52) - -#define PSW_ASC_PRIMARY 0x0000000000000000UL -#define PSW_ASC_ACCREG 0x0000400000000000UL -#define PSW_ASC_SECONDARY 0x0000800000000000UL -#define PSW_ASC_HOME 0x0000C00000000000UL - -#endif /* __s390x__ */ - - /* * The s390_regs structure is used to define the elf_gregset_t. */ diff --git a/arch/s390/include/uapi/asm/uvdevice.h b/arch/s390/include/uapi/asm/uvdevice.h index 10a5ac918e02d96f2e1f99f64cc17adec1b10a59..b9c2f14a6af31ae30f5b96228c85f24dc8fb675e 100644 --- a/arch/s390/include/uapi/asm/uvdevice.h +++ b/arch/s390/include/uapi/asm/uvdevice.h @@ -32,6 +32,33 @@ struct uvio_attest { __u16 reserved136; /* 0x0136 */ }; +/** + * uvio_uvdev_info - Information of supported functions + * @supp_uvio_cmds - supported IOCTLs by this device + * @supp_uv_cmds - supported UVCs corresponding to the IOCTL + * + * UVIO request to get information about supported request types by this + * uvdevice and the Ultravisor. Everything is output. Bits are in LSB0 + * ordering. If the bit is set in both, @supp_uvio_cmds and @supp_uv_cmds, the + * uvdevice and the Ultravisor support that call. + * + * Note that bit 0 (UVIO_IOCTL_UVDEV_INFO_NR) is always zero for `supp_uv_cmds` + * as there is no corresponding UV-call. + */ +struct uvio_uvdev_info { + /* + * If bit `n` is set, this device supports the IOCTL with nr `n`. + */ + __u64 supp_uvio_cmds; + /* + * If bit `n` is set, the Ultravisor(UV) supports the UV-call + * corresponding to the IOCTL with nr `n` in the calling contextx (host + * or guest). The value is only valid if the corresponding bit in + * @supp_uvio_cmds is set as well. + */ + __u64 supp_uv_cmds; +}; + /* * The following max values define an upper length for the IOCTL in/out buffers. * However, they do not represent the maximum the Ultravisor allows which is @@ -42,10 +69,34 @@ struct uvio_attest { #define UVIO_ATT_ARCB_MAX_LEN 0x100000 #define UVIO_ATT_MEASUREMENT_MAX_LEN 0x8000 #define UVIO_ATT_ADDITIONAL_MAX_LEN 0x8000 +#define UVIO_ADD_SECRET_MAX_LEN 0x100000 +#define UVIO_LIST_SECRETS_LEN 0x1000 #define UVIO_DEVICE_NAME "uv" #define UVIO_TYPE_UVC 'u' -#define UVIO_IOCTL_ATT _IOWR(UVIO_TYPE_UVC, 0x01, struct uvio_ioctl_cb) +enum UVIO_IOCTL_NR { + UVIO_IOCTL_UVDEV_INFO_NR = 0x00, + UVIO_IOCTL_ATT_NR, + UVIO_IOCTL_ADD_SECRET_NR, + UVIO_IOCTL_LIST_SECRETS_NR, + UVIO_IOCTL_LOCK_SECRETS_NR, + /* must be the last entry */ + UVIO_IOCTL_NUM_IOCTLS +}; + +#define UVIO_IOCTL(nr) _IOWR(UVIO_TYPE_UVC, nr, struct uvio_ioctl_cb) +#define UVIO_IOCTL_UVDEV_INFO UVIO_IOCTL(UVIO_IOCTL_UVDEV_INFO_NR) +#define UVIO_IOCTL_ATT UVIO_IOCTL(UVIO_IOCTL_ATT_NR) +#define UVIO_IOCTL_ADD_SECRET UVIO_IOCTL(UVIO_IOCTL_ADD_SECRET_NR) +#define UVIO_IOCTL_LIST_SECRETS UVIO_IOCTL(UVIO_IOCTL_LIST_SECRETS_NR) +#define UVIO_IOCTL_LOCK_SECRETS UVIO_IOCTL(UVIO_IOCTL_LOCK_SECRETS_NR) + +#define UVIO_SUPP_CALL(nr) (1ULL << (nr)) +#define UVIO_SUPP_UDEV_INFO UVIO_SUPP_CALL(UVIO_IOCTL_UDEV_INFO_NR) +#define UVIO_SUPP_ATT UVIO_SUPP_CALL(UVIO_IOCTL_ATT_NR) +#define UVIO_SUPP_ADD_SECRET UVIO_SUPP_CALL(UVIO_IOCTL_ADD_SECRET_NR) +#define UVIO_SUPP_LIST_SECRETS UVIO_SUPP_CALL(UVIO_IOCTL_LIST_SECRETS_NR) +#define UVIO_SUPP_LOCK_SECRETS UVIO_SUPP_CALL(UVIO_IOCTL_LOCK_SECRETS_NR) #endif /* __S390_ASM_UVDEVICE_H */ diff --git a/arch/s390/kernel/asm-offsets.c b/arch/s390/kernel/asm-offsets.c index 3f8e760298c2201c3bf207433d2e25ecdcca2dd8..81cf7208804137b2b81b2a3fc8e82884c00fd683 100644 --- a/arch/s390/kernel/asm-offsets.c +++ b/arch/s390/kernel/asm-offsets.c @@ -122,7 +122,6 @@ int main(void) OFFSET(__LC_LAST_UPDATE_TIMER, lowcore, last_update_timer); OFFSET(__LC_LAST_UPDATE_CLOCK, lowcore, last_update_clock); OFFSET(__LC_INT_CLOCK, lowcore, int_clock); - OFFSET(__LC_MCCK_CLOCK, lowcore, mcck_clock); OFFSET(__LC_BOOT_CLOCK, lowcore, boot_clock); OFFSET(__LC_CURRENT, lowcore, current_task); OFFSET(__LC_KERNEL_STACK, lowcore, kernel_stack); diff --git a/arch/s390/kernel/cpcmd.c b/arch/s390/kernel/cpcmd.c index 72e106cfd8c7fa3f4dc9cf5cdcd07c32ca0f9b6e..b210a29d3ee96189533bde9a1e1402fce5a548af 100644 --- a/arch/s390/kernel/cpcmd.c +++ b/arch/s390/kernel/cpcmd.c @@ -16,10 +16,10 @@ #include #include #include +#include #include #include #include -#include static DEFINE_SPINLOCK(cpcmd_lock); static char cpcmd_buf[241]; diff --git a/arch/s390/kernel/crash_dump.c b/arch/s390/kernel/crash_dump.c index 8a617be28bb48d2473bc7fae7f8f2c6b7931e5ed..7af69948b290a79d695f3c145e97b84d606c0820 100644 --- a/arch/s390/kernel/crash_dump.c +++ b/arch/s390/kernel/crash_dump.c @@ -568,9 +568,9 @@ static size_t get_elfcorehdr_size(int mem_chunk_cnt) int elfcorehdr_alloc(unsigned long long *addr, unsigned long long *size) { Elf64_Phdr *phdr_notes, *phdr_loads; + size_t alloc_size; int mem_chunk_cnt; void *ptr, *hdr; - u32 alloc_size; u64 hdr_off; /* If we are not in kdump or zfcp/nvme dump mode return */ diff --git a/arch/s390/kernel/dis.c b/arch/s390/kernel/dis.c index 90bbb4ea1d086d9ded929bfbf8733c931ed7d4a1..89dc826a8d2ef1e3ed823baa5b427a453332cfc5 100644 --- a/arch/s390/kernel/dis.c +++ b/arch/s390/kernel/dis.c @@ -24,8 +24,8 @@ #include #include #include +#include #include -#include #include #include #include @@ -516,7 +516,7 @@ void show_code(struct pt_regs *regs) if (copy_from_regs(regs, code + end, (void *)addr, 2)) break; } - /* Code snapshot useable ? */ + /* Code snapshot usable ? */ if ((regs->psw.addr & 1) || start >= end) { printk("%s Code: Bad PSW.\n", mode); return; diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S index e5b6c1369e8e1edb3d456428c0959ba0d8de3ee4..a660f4b6d6542a8ab1d005894efedcf4c68a84b1 100644 --- a/arch/s390/kernel/entry.S +++ b/arch/s390/kernel/entry.S @@ -136,7 +136,7 @@ _LPP_OFFSET = __LC_LPP clgfrl %r14,.Lrange_size\@ jhe \outside_label .section .rodata, "a" - .align 4 + .balign 4 .Lrange_size\@: .long \end - \start .previous @@ -488,7 +488,6 @@ SYM_FUNC_END(psw_idle) * Machine check handler routines */ SYM_CODE_START(mcck_int_handler) - stckf __LC_MCCK_CLOCK BPOFF la %r1,4095 # validate r1 spt __LC_CPU_TIMER_SAVE_AREA-4095(%r1) # validate cpu timer @@ -598,8 +597,9 @@ SYM_CODE_START(restart_int_handler) TSTMSK __LC_RESTART_FLAGS,RESTART_FLAG_CTLREGS,4 jz 0f lctlg %c0,%c15,__LC_CREGS_SAVE_AREA -0: larl %r15,stosm_tmp - stosm 0(%r15),0x04 # turn dat on, keep irqs off +0: larl %r15,daton_psw + lpswe 0(%r15) # turn dat on, keep irqs off +.Ldaton: lg %r15,__LC_RESTART_STACK xc STACK_FRAME_OVERHEAD(__PT_SIZE,%r15),STACK_FRAME_OVERHEAD(%r15) stmg %r0,%r14,STACK_FRAME_OVERHEAD+__PT_R0(%r15) @@ -646,7 +646,11 @@ SYM_CODE_END(stack_overflow) .balign 4 SYM_DATA_LOCAL(stop_lock, .long 0) SYM_DATA_LOCAL(this_cpu, .short 0) -SYM_DATA_LOCAL(stosm_tmp, .byte 0) + .balign 8 +SYM_DATA_START_LOCAL(daton_psw) + .quad PSW_KERNEL_BITS + .quad .Ldaton +SYM_DATA_END(daton_psw) .section .rodata, "a" #define SYSCALL(esame,emu) .quad __s390x_ ## esame diff --git a/arch/s390/kernel/entry.h b/arch/s390/kernel/entry.h index 34674e38826b68ea61a6b3b0e9fb18904acce298..9f41853f36b934bc8dd0675cd2bbe57e17377b2b 100644 --- a/arch/s390/kernel/entry.h +++ b/arch/s390/kernel/entry.h @@ -34,14 +34,12 @@ void kernel_stack_overflow(struct pt_regs * regs); void handle_signal32(struct ksignal *ksig, sigset_t *oldset, struct pt_regs *regs); -void __init init_IRQ(void); void do_io_irq(struct pt_regs *regs); void do_ext_irq(struct pt_regs *regs); void do_restart(void *arg); void __init startup_init(void); void die(struct pt_regs *regs, const char *str); int setup_profiling_timer(unsigned int multiplier); -void __init time_init(void); unsigned long prepare_ftrace_return(unsigned long parent, unsigned long sp, unsigned long ip); struct s390_mmap_arg_struct; diff --git a/arch/s390/kernel/head64.S b/arch/s390/kernel/head64.S index df77ba102096499179a561dc66d18c642ac8677b..45413b04efc525a8eed9aeb9d16476a8c20a5463 100644 --- a/arch/s390/kernel/head64.S +++ b/arch/s390/kernel/head64.S @@ -36,5 +36,5 @@ SYM_CODE_START(startup_continue) lpswe dw_psw-.(%r13) # load disabled wait psw SYM_CODE_END(startup_continue) - .align 16 + .balign 16 SYM_DATA_LOCAL(dw_psw, .quad 0x0002000180000000,0x0000000000000000) diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c index f44f70de966115c64aa6286afb9bfe06f2543dc6..85a00d97a3143957ec58df4a6193b6ac7b3a6422 100644 --- a/arch/s390/kernel/ipl.c +++ b/arch/s390/kernel/ipl.c @@ -176,6 +176,8 @@ static bool reipl_fcp_clear; static bool reipl_ccw_clear; static bool reipl_eckd_clear; +static unsigned long os_info_flags; + static inline int __diag308(unsigned long subcode, unsigned long addr) { union register_pair r1; @@ -1938,6 +1940,20 @@ static void dump_reipl_run(struct shutdown_trigger *trigger) struct lowcore *abs_lc; unsigned int csum; + /* + * Set REIPL_CLEAR flag in os_info flags entry indicating + * 'clear' sysfs attribute has been set on the panicked system + * for specified reipl type. + * Always set for IPL_TYPE_NSS and IPL_TYPE_UNKNOWN. + */ + if ((reipl_type == IPL_TYPE_CCW && reipl_ccw_clear) || + (reipl_type == IPL_TYPE_ECKD && reipl_eckd_clear) || + (reipl_type == IPL_TYPE_FCP && reipl_fcp_clear) || + (reipl_type == IPL_TYPE_NVME && reipl_nvme_clear) || + reipl_type == IPL_TYPE_NSS || + reipl_type == IPL_TYPE_UNKNOWN) + os_info_flags |= OS_INFO_FLAG_REIPL_CLEAR; + os_info_entry_add(OS_INFO_FLAGS_ENTRY, &os_info_flags, sizeof(os_info_flags)); csum = (__force unsigned int) csum_partial(reipl_block_actual, reipl_block_actual->hdr.len, 0); abs_lc = get_abs_lowcore(); diff --git a/arch/s390/kernel/kprobes_insn_page.S b/arch/s390/kernel/kprobes_insn_page.S index b6335296dcd8e6fad9c9676a056588f57cca2ac9..0fe4d725e98bbdb63d2e61182958d1982a24c562 100644 --- a/arch/s390/kernel/kprobes_insn_page.S +++ b/arch/s390/kernel/kprobes_insn_page.S @@ -13,7 +13,7 @@ * would be in the data section instead. */ .section .kprobes.text, "ax" - .align 4096 + .balign 4096 SYM_CODE_START(kprobes_insn_page) .rept 2048 .word 0x07fe diff --git a/arch/s390/kernel/module.c b/arch/s390/kernel/module.c index f1b35dcdf3eb520cbdefad6d57c333f9598aceae..42215f9404af4e9f9b5f18ed062631b816eabe92 100644 --- a/arch/s390/kernel/module.c +++ b/arch/s390/kernel/module.c @@ -352,7 +352,8 @@ static int apply_rela(Elf_Rela *rela, Elf_Addr base, Elf_Sym *symtab, rc = apply_rela_bits(loc, val, 0, 64, 0, write); else if (r_type == R_390_GOTENT || r_type == R_390_GOTPLTENT) { - val += (Elf_Addr) me->mem[MOD_TEXT].base - loc; + val += (Elf_Addr)me->mem[MOD_TEXT].base + + me->arch.got_offset - loc; rc = apply_rela_bits(loc, val, 1, 32, 1, write); } break; diff --git a/arch/s390/kernel/nospec-branch.c b/arch/s390/kernel/nospec-branch.c index 717bbcc056e583e7b567cbe75d9dffb034e4dcd4..d1b16d83e49ade48ada34328b70c926748041812 100644 --- a/arch/s390/kernel/nospec-branch.c +++ b/arch/s390/kernel/nospec-branch.c @@ -14,7 +14,7 @@ static int __init nobp_setup_early(char *str) return rc; if (enabled && test_facility(82)) { /* - * The user explicitely requested nobp=1, enable it and + * The user explicitly requested nobp=1, enable it and * disable the expoline support. */ __set_facility(82, alt_stfle_fac_list); diff --git a/arch/s390/kernel/perf_cpum_cf.c b/arch/s390/kernel/perf_cpum_cf.c index cf1b6e8a708de67dcc7bac3c02d4a64e05069fd1..850c11ea631a6b0a51048bc4a6c1c4ebf79ada8b 100644 --- a/arch/s390/kernel/perf_cpum_cf.c +++ b/arch/s390/kernel/perf_cpum_cf.c @@ -76,6 +76,7 @@ static inline int ctr_stcctm(enum cpumf_ctr_set set, u64 range, u64 *dest) } struct cpu_cf_events { + refcount_t refcnt; /* Reference count */ atomic_t ctr_set[CPUMF_CTR_SET_MAX]; u64 state; /* For perf_event_open SVC */ u64 dev_state; /* For /dev/hwctr */ @@ -88,9 +89,6 @@ struct cpu_cf_events { unsigned int sets; /* # Counter set saved in memory */ }; -/* Per-CPU event structure for the counter facility */ -static DEFINE_PER_CPU(struct cpu_cf_events, cpu_cf_events); - static unsigned int cfdiag_cpu_speed; /* CPU speed for CF_DIAG trailer */ static debug_info_t *cf_dbg; @@ -103,6 +101,221 @@ static debug_info_t *cf_dbg; */ static struct cpumf_ctr_info cpumf_ctr_info; +struct cpu_cf_ptr { + struct cpu_cf_events *cpucf; +}; + +static struct cpu_cf_root { /* Anchor to per CPU data */ + refcount_t refcnt; /* Overall active events */ + struct cpu_cf_ptr __percpu *cfptr; +} cpu_cf_root; + +/* + * Serialize event initialization and event removal. Both are called from + * user space in task context with perf_event_open() and close() + * system calls. + * + * This mutex serializes functions cpum_cf_alloc_cpu() called at event + * initialization via cpumf_pmu_event_init() and function cpum_cf_free_cpu() + * called at event removal via call back function hw_perf_event_destroy() + * when the event is deleted. They are serialized to enforce correct + * bookkeeping of pointer and reference counts anchored by + * struct cpu_cf_root and the access to cpu_cf_root::refcnt and the + * per CPU pointers stored in cpu_cf_root::cfptr. + */ +static DEFINE_MUTEX(pmc_reserve_mutex); + +/* + * Get pointer to per-cpu structure. + * + * Function get_cpu_cfhw() is called from + * - cfset_copy_all(): This function is protected by cpus_read_lock(), so + * CPU hot plug remove can not happen. Event removal requires a close() + * first. + * + * Function this_cpu_cfhw() is called from perf common code functions: + * - pmu_{en|dis}able(), pmu_{add|del}()and pmu_{start|stop}(): + * All functions execute with interrupts disabled on that particular CPU. + * - cfset_ioctl_{on|off}, cfset_cpu_read(): see comment cfset_copy_all(). + * + * Therefore it is safe to access the CPU specific pointer to the event. + */ +static struct cpu_cf_events *get_cpu_cfhw(int cpu) +{ + struct cpu_cf_ptr __percpu *p = cpu_cf_root.cfptr; + + if (p) { + struct cpu_cf_ptr *q = per_cpu_ptr(p, cpu); + + return q->cpucf; + } + return NULL; +} + +static struct cpu_cf_events *this_cpu_cfhw(void) +{ + return get_cpu_cfhw(smp_processor_id()); +} + +/* Disable counter sets on dedicated CPU */ +static void cpum_cf_reset_cpu(void *flags) +{ + lcctl(0); +} + +/* Free per CPU data when the last event is removed. */ +static void cpum_cf_free_root(void) +{ + if (!refcount_dec_and_test(&cpu_cf_root.refcnt)) + return; + free_percpu(cpu_cf_root.cfptr); + cpu_cf_root.cfptr = NULL; + irq_subclass_unregister(IRQ_SUBCLASS_MEASUREMENT_ALERT); + on_each_cpu(cpum_cf_reset_cpu, NULL, 1); + debug_sprintf_event(cf_dbg, 4, "%s root.refcnt %u cfptr %d\n", + __func__, refcount_read(&cpu_cf_root.refcnt), + !cpu_cf_root.cfptr); +} + +/* + * On initialization of first event also allocate per CPU data dynamically. + * Start with an array of pointers, the array size is the maximum number of + * CPUs possible, which might be larger than the number of CPUs currently + * online. + */ +static int cpum_cf_alloc_root(void) +{ + int rc = 0; + + if (refcount_inc_not_zero(&cpu_cf_root.refcnt)) + return rc; + + /* The memory is already zeroed. */ + cpu_cf_root.cfptr = alloc_percpu(struct cpu_cf_ptr); + if (cpu_cf_root.cfptr) { + refcount_set(&cpu_cf_root.refcnt, 1); + on_each_cpu(cpum_cf_reset_cpu, NULL, 1); + irq_subclass_register(IRQ_SUBCLASS_MEASUREMENT_ALERT); + } else { + rc = -ENOMEM; + } + + return rc; +} + +/* Free CPU counter data structure for a PMU */ +static void cpum_cf_free_cpu(int cpu) +{ + struct cpu_cf_events *cpuhw; + struct cpu_cf_ptr *p; + + mutex_lock(&pmc_reserve_mutex); + /* + * When invoked via CPU hotplug handler, there might be no events + * installed or that particular CPU might not have an + * event installed. This anchor pointer can be NULL! + */ + if (!cpu_cf_root.cfptr) + goto out; + p = per_cpu_ptr(cpu_cf_root.cfptr, cpu); + cpuhw = p->cpucf; + /* + * Might be zero when called from CPU hotplug handler and no event + * installed on that CPU, but on different CPUs. + */ + if (!cpuhw) + goto out; + + if (refcount_dec_and_test(&cpuhw->refcnt)) { + kfree(cpuhw); + p->cpucf = NULL; + } + cpum_cf_free_root(); +out: + mutex_unlock(&pmc_reserve_mutex); +} + +/* Allocate CPU counter data structure for a PMU. Called under mutex lock. */ +static int cpum_cf_alloc_cpu(int cpu) +{ + struct cpu_cf_events *cpuhw; + struct cpu_cf_ptr *p; + int rc; + + mutex_lock(&pmc_reserve_mutex); + rc = cpum_cf_alloc_root(); + if (rc) + goto unlock; + p = per_cpu_ptr(cpu_cf_root.cfptr, cpu); + cpuhw = p->cpucf; + + if (!cpuhw) { + cpuhw = kzalloc(sizeof(*cpuhw), GFP_KERNEL); + if (cpuhw) { + p->cpucf = cpuhw; + refcount_set(&cpuhw->refcnt, 1); + } else { + rc = -ENOMEM; + } + } else { + refcount_inc(&cpuhw->refcnt); + } + if (rc) { + /* + * Error in allocation of event, decrement anchor. Since + * cpu_cf_event in not created, its destroy() function is not + * invoked. Adjust the reference counter for the anchor. + */ + cpum_cf_free_root(); + } +unlock: + mutex_unlock(&pmc_reserve_mutex); + return rc; +} + +/* + * Create/delete per CPU data structures for /dev/hwctr interface and events + * created by perf_event_open(). + * If cpu is -1, track task on all available CPUs. This requires + * allocation of hardware data structures for all CPUs. This setup handles + * perf_event_open() with task context and /dev/hwctr interface. + * If cpu is non-zero install event on this CPU only. This setup handles + * perf_event_open() with CPU context. + */ +static int cpum_cf_alloc(int cpu) +{ + cpumask_var_t mask; + int rc; + + if (cpu == -1) { + if (!zalloc_cpumask_var(&mask, GFP_KERNEL)) + return -ENOMEM; + for_each_online_cpu(cpu) { + rc = cpum_cf_alloc_cpu(cpu); + if (rc) { + for_each_cpu(cpu, mask) + cpum_cf_free_cpu(cpu); + break; + } + cpumask_set_cpu(cpu, mask); + } + free_cpumask_var(mask); + } else { + rc = cpum_cf_alloc_cpu(cpu); + } + return rc; +} + +static void cpum_cf_free(int cpu) +{ + if (cpu == -1) { + for_each_online_cpu(cpu) + cpum_cf_free_cpu(cpu); + } else { + cpum_cf_free_cpu(cpu); + } +} + #define CF_DIAG_CTRSET_DEF 0xfeef /* Counter set header mark */ /* interval in seconds */ @@ -451,10 +664,10 @@ static int validate_ctr_version(const u64 config, enum cpumf_ctr_set set) */ static void cpumf_pmu_enable(struct pmu *pmu) { - struct cpu_cf_events *cpuhw = this_cpu_ptr(&cpu_cf_events); + struct cpu_cf_events *cpuhw = this_cpu_cfhw(); int err; - if (cpuhw->flags & PMU_F_ENABLED) + if (!cpuhw || (cpuhw->flags & PMU_F_ENABLED)) return; err = lcctl(cpuhw->state | cpuhw->dev_state); @@ -471,11 +684,11 @@ static void cpumf_pmu_enable(struct pmu *pmu) */ static void cpumf_pmu_disable(struct pmu *pmu) { - struct cpu_cf_events *cpuhw = this_cpu_ptr(&cpu_cf_events); - int err; + struct cpu_cf_events *cpuhw = this_cpu_cfhw(); u64 inactive; + int err; - if (!(cpuhw->flags & PMU_F_ENABLED)) + if (!cpuhw || !(cpuhw->flags & PMU_F_ENABLED)) return; inactive = cpuhw->state & ~((1 << CPUMF_LCCTL_ENABLE_SHIFT) - 1); @@ -487,58 +700,10 @@ static void cpumf_pmu_disable(struct pmu *pmu) cpuhw->flags &= ~PMU_F_ENABLED; } -#define PMC_INIT 0UL -#define PMC_RELEASE 1UL - -static void cpum_cf_setup_cpu(void *flags) -{ - struct cpu_cf_events *cpuhw = this_cpu_ptr(&cpu_cf_events); - - switch ((unsigned long)flags) { - case PMC_INIT: - cpuhw->flags |= PMU_F_RESERVED; - break; - - case PMC_RELEASE: - cpuhw->flags &= ~PMU_F_RESERVED; - break; - } - - /* Disable CPU counter sets */ - lcctl(0); - debug_sprintf_event(cf_dbg, 5, "%s flags %#x flags %#x state %#llx\n", - __func__, *(int *)flags, cpuhw->flags, - cpuhw->state); -} - -/* Initialize the CPU-measurement counter facility */ -static int __kernel_cpumcf_begin(void) -{ - on_each_cpu(cpum_cf_setup_cpu, (void *)PMC_INIT, 1); - irq_subclass_register(IRQ_SUBCLASS_MEASUREMENT_ALERT); - - return 0; -} - -/* Release the CPU-measurement counter facility */ -static void __kernel_cpumcf_end(void) -{ - on_each_cpu(cpum_cf_setup_cpu, (void *)PMC_RELEASE, 1); - irq_subclass_unregister(IRQ_SUBCLASS_MEASUREMENT_ALERT); -} - -/* Number of perf events counting hardware events */ -static atomic_t num_events = ATOMIC_INIT(0); -/* Used to avoid races in calling reserve/release_cpumf_hardware */ -static DEFINE_MUTEX(pmc_reserve_mutex); - /* Release the PMU if event is the last perf event */ static void hw_perf_event_destroy(struct perf_event *event) { - mutex_lock(&pmc_reserve_mutex); - if (atomic_dec_return(&num_events) == 0) - __kernel_cpumcf_end(); - mutex_unlock(&pmc_reserve_mutex); + cpum_cf_free(event->cpu); } /* CPUMF <-> perf event mappings for kernel+userspace (basic set) */ @@ -562,14 +727,6 @@ static const int cpumf_generic_events_user[] = { [PERF_COUNT_HW_BUS_CYCLES] = -1, }; -static void cpumf_hw_inuse(void) -{ - mutex_lock(&pmc_reserve_mutex); - if (atomic_inc_return(&num_events) == 1) - __kernel_cpumcf_begin(); - mutex_unlock(&pmc_reserve_mutex); -} - static int is_userspace_event(u64 ev) { return cpumf_generic_events_user[PERF_COUNT_HW_CPU_CYCLES] == ev || @@ -653,7 +810,8 @@ static int __hw_perf_event_init(struct perf_event *event, unsigned int type) } /* Initialize for using the CPU-measurement counter facility */ - cpumf_hw_inuse(); + if (cpum_cf_alloc(event->cpu)) + return -ENOMEM; event->destroy = hw_perf_event_destroy; /* @@ -756,7 +914,7 @@ static void cpumf_pmu_read(struct perf_event *event) static void cpumf_pmu_start(struct perf_event *event, int flags) { - struct cpu_cf_events *cpuhw = this_cpu_ptr(&cpu_cf_events); + struct cpu_cf_events *cpuhw = this_cpu_cfhw(); struct hw_perf_event *hwc = &event->hw; int i; @@ -817,10 +975,6 @@ static int cfdiag_push_sample(struct perf_event *event, } overflow = perf_event_overflow(event, &data, ®s); - debug_sprintf_event(cf_dbg, 3, - "%s event %#llx sample_type %#llx raw %d ov %d\n", - __func__, event->hw.config, - event->attr.sample_type, raw.size, overflow); if (overflow) event->pmu->stop(event, 0); @@ -830,7 +984,7 @@ static int cfdiag_push_sample(struct perf_event *event, static void cpumf_pmu_stop(struct perf_event *event, int flags) { - struct cpu_cf_events *cpuhw = this_cpu_ptr(&cpu_cf_events); + struct cpu_cf_events *cpuhw = this_cpu_cfhw(); struct hw_perf_event *hwc = &event->hw; int i; @@ -857,8 +1011,7 @@ static void cpumf_pmu_stop(struct perf_event *event, int flags) false); if (cfdiag_diffctr(cpuhw, event->hw.config_base)) cfdiag_push_sample(event, cpuhw); - } else if (cpuhw->flags & PMU_F_RESERVED) { - /* Only update when PMU not hotplugged off */ + } else { hw_perf_event_update(event); } hwc->state |= PERF_HES_UPTODATE; @@ -867,7 +1020,7 @@ static void cpumf_pmu_stop(struct perf_event *event, int flags) static int cpumf_pmu_add(struct perf_event *event, int flags) { - struct cpu_cf_events *cpuhw = this_cpu_ptr(&cpu_cf_events); + struct cpu_cf_events *cpuhw = this_cpu_cfhw(); ctr_set_enable(&cpuhw->state, event->hw.config_base); event->hw.state = PERF_HES_UPTODATE | PERF_HES_STOPPED; @@ -880,7 +1033,7 @@ static int cpumf_pmu_add(struct perf_event *event, int flags) static void cpumf_pmu_del(struct perf_event *event, int flags) { - struct cpu_cf_events *cpuhw = this_cpu_ptr(&cpu_cf_events); + struct cpu_cf_events *cpuhw = this_cpu_cfhw(); int i; cpumf_pmu_stop(event, PERF_EF_UPDATE); @@ -912,29 +1065,76 @@ static struct pmu cpumf_pmu = { .read = cpumf_pmu_read, }; -static int cpum_cf_setup(unsigned int cpu, unsigned long flags) -{ - local_irq_disable(); - cpum_cf_setup_cpu((void *)flags); - local_irq_enable(); - return 0; -} +static struct cfset_session { /* CPUs and counter set bit mask */ + struct list_head head; /* Head of list of active processes */ +} cfset_session = { + .head = LIST_HEAD_INIT(cfset_session.head) +}; + +static refcount_t cfset_opencnt = REFCOUNT_INIT(0); /* Access count */ +/* + * Synchronize access to device /dev/hwc. This mutex protects against + * concurrent access to functions cfset_open() and cfset_release(). + * Same for CPU hotplug add and remove events triggering + * cpum_cf_online_cpu() and cpum_cf_offline_cpu(). + * It also serializes concurrent device ioctl access from multiple + * processes accessing /dev/hwc. + * + * The mutex protects concurrent access to the /dev/hwctr session management + * struct cfset_session and reference counting variable cfset_opencnt. + */ +static DEFINE_MUTEX(cfset_ctrset_mutex); +/* + * CPU hotplug handles only /dev/hwctr device. + * For perf_event_open() the CPU hotplug handling is done on kernel common + * code: + * - CPU add: Nothing is done since a file descriptor can not be created + * and returned to the user. + * - CPU delete: Handled by common code via pmu_disable(), pmu_stop() and + * pmu_delete(). The event itself is removed when the file descriptor is + * closed. + */ static int cfset_online_cpu(unsigned int cpu); + static int cpum_cf_online_cpu(unsigned int cpu) { - debug_sprintf_event(cf_dbg, 4, "%s cpu %d in_irq %ld\n", __func__, - cpu, in_interrupt()); - cpum_cf_setup(cpu, PMC_INIT); - return cfset_online_cpu(cpu); + int rc = 0; + + /* + * Ignore notification for perf_event_open(). + * Handle only /dev/hwctr device sessions. + */ + mutex_lock(&cfset_ctrset_mutex); + if (refcount_read(&cfset_opencnt)) { + rc = cpum_cf_alloc_cpu(cpu); + if (!rc) + cfset_online_cpu(cpu); + } + mutex_unlock(&cfset_ctrset_mutex); + return rc; } static int cfset_offline_cpu(unsigned int cpu); + static int cpum_cf_offline_cpu(unsigned int cpu) { - debug_sprintf_event(cf_dbg, 4, "%s cpu %d\n", __func__, cpu); - cfset_offline_cpu(cpu); - return cpum_cf_setup(cpu, PMC_RELEASE); + /* + * During task exit processing of grouped perf events triggered by CPU + * hotplug processing, pmu_disable() is called as part of perf context + * removal process. Therefore do not trigger event removal now for + * perf_event_open() created events. Perf common code triggers event + * destruction when the event file descriptor is closed. + * + * Handle only /dev/hwctr device sessions. + */ + mutex_lock(&cfset_ctrset_mutex); + if (refcount_read(&cfset_opencnt)) { + cfset_offline_cpu(cpu); + cpum_cf_free_cpu(cpu); + } + mutex_unlock(&cfset_ctrset_mutex); + return 0; } /* Return true if store counter set multiple instruction is available */ @@ -953,13 +1153,13 @@ static void cpumf_measurement_alert(struct ext_code ext_code, return; inc_irq_stat(IRQEXT_CMC); - cpuhw = this_cpu_ptr(&cpu_cf_events); /* * Measurement alerts are shared and might happen when the PMU * is not reserved. Ignore these alerts in this case. */ - if (!(cpuhw->flags & PMU_F_RESERVED)) + cpuhw = this_cpu_cfhw(); + if (!cpuhw) return; /* counter authorization change alert */ @@ -1039,19 +1239,11 @@ static int __init cpumf_pmu_init(void) * counter set via normal file operations. */ -static atomic_t cfset_opencnt = ATOMIC_INIT(0); /* Access count */ -static DEFINE_MUTEX(cfset_ctrset_mutex);/* Synchronize access to hardware */ struct cfset_call_on_cpu_parm { /* Parm struct for smp_call_on_cpu */ unsigned int sets; /* Counter set bit mask */ atomic_t cpus_ack; /* # CPUs successfully executed func */ }; -static struct cfset_session { /* CPUs and counter set bit mask */ - struct list_head head; /* Head of list of active processes */ -} cfset_session = { - .head = LIST_HEAD_INIT(cfset_session.head) -}; - struct cfset_request { /* CPUs and counter set bit mask */ unsigned long ctrset; /* Bit mask of counter set to read */ cpumask_t mask; /* CPU mask to read from */ @@ -1113,11 +1305,11 @@ static void cfset_session_add(struct cfset_request *p) /* Stop all counter sets via ioctl interface */ static void cfset_ioctl_off(void *parm) { - struct cpu_cf_events *cpuhw = this_cpu_ptr(&cpu_cf_events); + struct cpu_cf_events *cpuhw = this_cpu_cfhw(); struct cfset_call_on_cpu_parm *p = parm; int rc; - /* Check if any counter set used by /dev/hwc */ + /* Check if any counter set used by /dev/hwctr */ for (rc = CPUMF_CTR_SET_BASIC; rc < CPUMF_CTR_SET_MAX; ++rc) if ((p->sets & cpumf_ctr_ctl[rc])) { if (!atomic_dec_return(&cpuhw->ctr_set[rc])) { @@ -1134,14 +1326,12 @@ static void cfset_ioctl_off(void *parm) cpuhw->state, S390_HWCTR_DEVICE, rc); if (!cpuhw->dev_state) cpuhw->flags &= ~PMU_F_IN_USE; - debug_sprintf_event(cf_dbg, 4, "%s rc %d state %#llx dev_state %#llx\n", - __func__, rc, cpuhw->state, cpuhw->dev_state); } /* Start counter sets on particular CPU */ static void cfset_ioctl_on(void *parm) { - struct cpu_cf_events *cpuhw = this_cpu_ptr(&cpu_cf_events); + struct cpu_cf_events *cpuhw = this_cpu_cfhw(); struct cfset_call_on_cpu_parm *p = parm; int rc; @@ -1157,17 +1347,13 @@ static void cfset_ioctl_on(void *parm) else pr_err("Counter set start %#llx of /dev/%s failed rc=%i\n", cpuhw->dev_state | cpuhw->state, S390_HWCTR_DEVICE, rc); - debug_sprintf_event(cf_dbg, 4, "%s rc %d state %#llx dev_state %#llx\n", - __func__, rc, cpuhw->state, cpuhw->dev_state); } static void cfset_release_cpu(void *p) { - struct cpu_cf_events *cpuhw = this_cpu_ptr(&cpu_cf_events); + struct cpu_cf_events *cpuhw = this_cpu_cfhw(); int rc; - debug_sprintf_event(cf_dbg, 4, "%s state %#llx dev_state %#llx\n", - __func__, cpuhw->state, cpuhw->dev_state); cpuhw->dev_state = 0; rc = lcctl(cpuhw->state); /* Keep perf_event_open counter sets */ if (rc) @@ -1203,27 +1389,41 @@ static int cfset_release(struct inode *inode, struct file *file) kfree(file->private_data); file->private_data = NULL; } - if (!atomic_dec_return(&cfset_opencnt)) + if (refcount_dec_and_test(&cfset_opencnt)) { /* Last close */ on_each_cpu(cfset_release_cpu, NULL, 1); + cpum_cf_free(-1); + } mutex_unlock(&cfset_ctrset_mutex); - - hw_perf_event_destroy(NULL); return 0; } +/* + * Open via /dev/hwctr device. Allocate all per CPU resources on the first + * open of the device. The last close releases all per CPU resources. + * Parallel perf_event_open system calls also use per CPU resources. + * These invocations are handled via reference counting on the per CPU data + * structures. + */ static int cfset_open(struct inode *inode, struct file *file) { - if (!capable(CAP_SYS_ADMIN)) + int rc = 0; + + if (!perfmon_capable()) return -EPERM; + file->private_data = NULL; + mutex_lock(&cfset_ctrset_mutex); - if (atomic_inc_return(&cfset_opencnt) == 1) - cfset_session_init(); + if (!refcount_inc_not_zero(&cfset_opencnt)) { /* First open */ + rc = cpum_cf_alloc(-1); + if (!rc) { + cfset_session_init(); + refcount_set(&cfset_opencnt, 1); + } + } mutex_unlock(&cfset_ctrset_mutex); - cpumf_hw_inuse(); - file->private_data = NULL; /* nonseekable_open() never fails */ - return nonseekable_open(inode, file); + return rc ?: nonseekable_open(inode, file); } static int cfset_all_start(struct cfset_request *req) @@ -1242,7 +1442,6 @@ static int cfset_all_start(struct cfset_request *req) if (atomic_read(&p.cpus_ack) != cpumask_weight(mask)) { on_each_cpu_mask(mask, cfset_ioctl_off, &p, 1); rc = -EIO; - debug_sprintf_event(cf_dbg, 4, "%s CPUs missing", __func__); } free_cpumask_var(mask); return rc; @@ -1280,7 +1479,7 @@ static int cfset_all_copy(unsigned long arg, cpumask_t *mask) ctrset_read = (struct s390_ctrset_read __user *)arg; uptr = ctrset_read->data; for_each_cpu(cpu, mask) { - struct cpu_cf_events *cpuhw = per_cpu_ptr(&cpu_cf_events, cpu); + struct cpu_cf_events *cpuhw = get_cpu_cfhw(cpu); struct s390_ctrset_cpudata __user *ctrset_cpudata; ctrset_cpudata = uptr; @@ -1299,8 +1498,6 @@ static int cfset_all_copy(unsigned long arg, cpumask_t *mask) if (put_user(cpus, &ctrset_read->no_cpus)) rc = -EFAULT; out: - debug_sprintf_event(cf_dbg, 4, "%s rc %d copied %ld\n", __func__, rc, - uptr - (void __user *)ctrset_read->data); return rc; } @@ -1324,7 +1521,7 @@ static size_t cfset_cpuset_read(struct s390_ctrset_setdata *p, int ctrset, /* Read all counter sets. */ static void cfset_cpu_read(void *parm) { - struct cpu_cf_events *cpuhw = this_cpu_ptr(&cpu_cf_events); + struct cpu_cf_events *cpuhw = this_cpu_cfhw(); struct cfset_call_on_cpu_parm *p = parm; int set, set_size; size_t space; @@ -1349,8 +1546,6 @@ static void cfset_cpu_read(void *parm) cpuhw->sets += 1; } } - debug_sprintf_event(cf_dbg, 4, "%s sets %d used %zd\n", __func__, - cpuhw->sets, cpuhw->used); } static int cfset_all_read(unsigned long arg, struct cfset_request *req) @@ -1444,8 +1639,6 @@ static long cfset_ioctl_start(unsigned long arg, struct file *file) if (!ret) { cfset_session_add(preq); file->private_data = preq; - debug_sprintf_event(cf_dbg, 4, "%s set %#lx need %ld ret %d\n", - __func__, preq->ctrset, need, ret); } else { kfree(preq); } @@ -1502,6 +1695,7 @@ static struct miscdevice cfset_dev = { .name = S390_HWCTR_DEVICE, .minor = MISC_DYNAMIC_MINOR, .fops = &cfset_fops, + .mode = 0666, }; /* Hotplug add of a CPU. Scan through all active processes and add @@ -1512,7 +1706,6 @@ static int cfset_online_cpu(unsigned int cpu) struct cfset_call_on_cpu_parm p; struct cfset_request *rp; - mutex_lock(&cfset_ctrset_mutex); if (!list_empty(&cfset_session.head)) { list_for_each_entry(rp, &cfset_session.head, node) { p.sets = rp->ctrset; @@ -1520,19 +1713,18 @@ static int cfset_online_cpu(unsigned int cpu) cpumask_set_cpu(cpu, &rp->mask); } } - mutex_unlock(&cfset_ctrset_mutex); return 0; } /* Hotplug remove of a CPU. Scan through all active processes and clear * that CPU from the list of CPUs supplied with ioctl(..., START, ...). + * Adjust reference counts. */ static int cfset_offline_cpu(unsigned int cpu) { struct cfset_call_on_cpu_parm p; struct cfset_request *rp; - mutex_lock(&cfset_ctrset_mutex); if (!list_empty(&cfset_session.head)) { list_for_each_entry(rp, &cfset_session.head, node) { p.sets = rp->ctrset; @@ -1540,14 +1732,11 @@ static int cfset_offline_cpu(unsigned int cpu) cpumask_clear_cpu(cpu, &rp->mask); } } - mutex_unlock(&cfset_ctrset_mutex); return 0; } static void cfdiag_read(struct perf_event *event) { - debug_sprintf_event(cf_dbg, 3, "%s event %#llx count %ld\n", __func__, - event->attr.config, local64_read(&event->count)); } static int get_authctrsets(void) @@ -1592,8 +1781,6 @@ static int cfdiag_event_init2(struct perf_event *event) if (!event->hw.config_base) err = -EINVAL; - debug_sprintf_event(cf_dbg, 5, "%s err %d config_base %#lx\n", - __func__, err, event->hw.config_base); return err; } @@ -1618,7 +1805,8 @@ static int cfdiag_event_init(struct perf_event *event) } /* Initialize for using the CPU-measurement counter facility */ - cpumf_hw_inuse(); + if (cpum_cf_alloc(event->cpu)) + return -ENOMEM; event->destroy = hw_perf_event_destroy; err = cfdiag_event_init2(event); diff --git a/arch/s390/kernel/perf_cpum_sf.c b/arch/s390/kernel/perf_cpum_sf.c index 7ef72f5ff52e609b31c543f47dd2077c6cecd101..06efad5b4f931b5c0ada1baad1a474945d3b05da 100644 --- a/arch/s390/kernel/perf_cpum_sf.c +++ b/arch/s390/kernel/perf_cpum_sf.c @@ -22,7 +22,7 @@ #include #include #include -#include +#include /* Minimum number of sample-data-block-tables: * At least one table is required for the sampling buffer structure. @@ -43,7 +43,7 @@ #define CPUM_SF_SDBT_TL_OFFSET (CPUM_SF_SDB_PER_TABLE * 8) static inline int require_table_link(const void *sdbt) { - return ((unsigned long) sdbt & ~PAGE_MASK) == CPUM_SF_SDBT_TL_OFFSET; + return ((unsigned long)sdbt & ~PAGE_MASK) == CPUM_SF_SDBT_TL_OFFSET; } /* Minimum and maximum sampling buffer sizes: @@ -192,7 +192,7 @@ static void free_sampling_buffer(struct sf_buffer *sfb) if (is_link_entry(curr)) { curr = get_next_sdbt(curr); if (sdbt) - free_page((unsigned long) sdbt); + free_page((unsigned long)sdbt); /* If the origin is reached, sampling buffer is freed */ if (curr == sfb->sdbt) @@ -278,7 +278,7 @@ static int realloc_sampling_buffer(struct sf_buffer *sfb, for (i = 0; i < num_sdb; i++) { /* Allocate a new SDB-table if it is full. */ if (require_table_link(tail)) { - new = (unsigned long *) get_zeroed_page(gfp_flags); + new = (unsigned long *)get_zeroed_page(gfp_flags); if (!new) { rc = -ENOMEM; break; @@ -304,7 +304,7 @@ static int realloc_sampling_buffer(struct sf_buffer *sfb, */ if (tail_prev) { sfb->num_sdbt--; - free_page((unsigned long) new); + free_page((unsigned long)new); tail = tail_prev; } break; @@ -343,7 +343,7 @@ static int alloc_sampling_buffer(struct sf_buffer *sfb, unsigned long num_sdb) return -EINVAL; /* Allocate the sample-data-block-table origin */ - sfb->sdbt = (unsigned long *) get_zeroed_page(GFP_KERNEL); + sfb->sdbt = (unsigned long *)get_zeroed_page(GFP_KERNEL); if (!sfb->sdbt) return -ENOMEM; sfb->num_sdb = 0; @@ -594,11 +594,10 @@ static DEFINE_MUTEX(pmc_reserve_mutex); #define PMC_FAILURE 2 static void setup_pmc_cpu(void *flags) { - int err; struct cpu_hw_sf *cpusf = this_cpu_ptr(&cpu_hw_sf); + int err = 0; - err = 0; - switch (*((int *) flags)) { + switch (*((int *)flags)) { case PMC_INIT: memset(cpusf, 0, sizeof(*cpusf)); err = qsi(&cpusf->qsi); @@ -606,22 +605,18 @@ static void setup_pmc_cpu(void *flags) break; cpusf->flags |= PMU_F_RESERVED; err = sf_disable(); - if (err) - pr_err("Switching off the sampling facility failed " - "with rc %i\n", err); break; case PMC_RELEASE: cpusf->flags &= ~PMU_F_RESERVED; err = sf_disable(); - if (err) { - pr_err("Switching off the sampling facility failed " - "with rc %i\n", err); - } else + if (!err) deallocate_buffers(cpusf); break; } - if (err) - *((int *) flags) |= PMC_FAILURE; + if (err) { + *((int *)flags) |= PMC_FAILURE; + pr_err("Switching off the sampling facility failed with rc %i\n", err); + } } static void release_pmc_hardware(void) @@ -963,10 +958,6 @@ static int cpumsf_pmu_event_init(struct perf_event *event) return -ENOENT; } - /* Check online status of the CPU to which the event is pinned */ - if (event->cpu >= 0 && !cpu_online(event->cpu)) - return -ENODEV; - /* Force reset of idle/hv excludes regardless of what the * user requested. */ @@ -1026,8 +1017,7 @@ static void cpumsf_pmu_enable(struct pmu *pmu) err = lsctl(&cpuhw->lsctl); if (err) { cpuhw->flags &= ~PMU_F_ENABLED; - pr_err("Loading sampling controls failed: op %i err %i\n", - 1, err); + pr_err("Loading sampling controls failed: op 1 err %i\n", err); return; } @@ -1061,8 +1051,7 @@ static void cpumsf_pmu_disable(struct pmu *pmu) err = lsctl(&inactive); if (err) { - pr_err("Loading sampling controls failed: op %i err %i\n", - 2, err); + pr_err("Loading sampling controls failed: op 2 err %i\n", err); return; } @@ -1221,7 +1210,7 @@ static void hw_collect_samples(struct perf_event *event, unsigned long *sdbt, te = trailer_entry_ptr((unsigned long)sdbt); sample = (struct hws_basic_entry *)sdbt; - while ((unsigned long *) sample < (unsigned long *) te) { + while ((unsigned long *)sample < (unsigned long *)te) { /* Check for an empty sample */ if (!sample->def || sample->LS) break; @@ -1271,16 +1260,6 @@ static void hw_collect_samples(struct perf_event *event, unsigned long *sdbt, } } -static inline __uint128_t __cdsg(__uint128_t *ptr, __uint128_t old, __uint128_t new) -{ - asm volatile( - " cdsg %[old],%[new],%[ptr]\n" - : [old] "+d" (old), [ptr] "+QS" (*ptr) - : [new] "d" (new) - : "memory", "cc"); - return old; -} - /* hw_perf_event_update() - Process sampling buffer * @event: The perf event * @flush_all: Flag to also flush partially filled sample-data-blocks @@ -1308,7 +1287,7 @@ static void hw_perf_event_update(struct perf_event *event, int flush_all) if (SAMPL_DIAG_MODE(&event->hw)) return; - sdbt = (unsigned long *) TEAR_REG(hwc); + sdbt = (unsigned long *)TEAR_REG(hwc); done = event_overflow = sampl_overflow = num_sdb = 0; while (!done) { /* Get the trailer entry of the sample-data-block */ @@ -1352,7 +1331,7 @@ static void hw_perf_event_update(struct perf_event *event, int flush_all) new.f = 0; new.a = 1; new.overflow = 0; - prev.val = __cdsg(&te->header.val, old.val, new.val); + prev.val = cmpxchg128(&te->header.val, old.val, new.val); } while (prev.val != old.val); /* Advance to next sample-data-block */ @@ -1562,7 +1541,7 @@ static bool aux_set_alert(struct aux_buffer *aux, unsigned long alert_index, } new.a = 1; new.overflow = 0; - prev.val = __cdsg(&te->header.val, old.val, new.val); + prev.val = cmpxchg128(&te->header.val, old.val, new.val); } while (prev.val != old.val); return true; } @@ -1636,7 +1615,7 @@ static bool aux_reset_buffer(struct aux_buffer *aux, unsigned long range, new.a = 1; else new.a = 0; - prev.val = __cdsg(&te->header.val, old.val, new.val); + prev.val = cmpxchg128(&te->header.val, old.val, new.val); } while (prev.val != old.val); *overflow += orig_overflow; } @@ -1680,9 +1659,6 @@ static void hw_collect_aux(struct cpu_hw_sf *cpuhw) pr_err("The AUX buffer with %lu pages for the " "diagnostic-sampling mode is full\n", num_sdb); - debug_sprintf_event(sfdbg, 1, - "%s: AUX buffer used up\n", - __func__); break; } if (WARN_ON_ONCE(!aux)) @@ -1814,7 +1790,7 @@ static void *aux_buffer_setup(struct perf_event *event, void **pages, /* Allocate the first SDBT */ sfb->num_sdbt = 0; - sfb->sdbt = (unsigned long *) get_zeroed_page(GFP_KERNEL); + sfb->sdbt = (unsigned long *)get_zeroed_page(GFP_KERNEL); if (!sfb->sdbt) goto no_sdbt; aux->sdbt_index[sfb->num_sdbt++] = (unsigned long)sfb->sdbt; @@ -1826,7 +1802,7 @@ static void *aux_buffer_setup(struct perf_event *event, void **pages, */ for (i = 0; i < nr_pages; i++, tail++) { if (require_table_link(tail)) { - new = (unsigned long *) get_zeroed_page(GFP_KERNEL); + new = (unsigned long *)get_zeroed_page(GFP_KERNEL); if (!new) goto no_sdbt; aux->sdbt_index[sfb->num_sdbt++] = (unsigned long)new; @@ -1875,7 +1851,7 @@ static void cpumsf_pmu_read(struct perf_event *event) /* Nothing to do ... updates are interrupt-driven */ } -/* Check if the new sampling period/freqeuncy is appropriate. +/* Check if the new sampling period/frequency is appropriate. * * Return non-zero on error and zero on passed checks. */ @@ -1983,8 +1959,8 @@ static int cpumsf_pmu_add(struct perf_event *event, int flags) cpuhw->lsctl.interval = SAMPL_RATE(&event->hw); if (!SAMPL_DIAG_MODE(&event->hw)) { cpuhw->lsctl.tear = virt_to_phys(cpuhw->sfb.sdbt); - cpuhw->lsctl.dear = *(unsigned long *) cpuhw->sfb.sdbt; - TEAR_REG(&event->hw) = (unsigned long) cpuhw->sfb.sdbt; + cpuhw->lsctl.dear = *(unsigned long *)cpuhw->sfb.sdbt; + TEAR_REG(&event->hw) = (unsigned long)cpuhw->sfb.sdbt; } /* Ensure sampling functions are in the disabled state. If disabled, diff --git a/arch/s390/kernel/perf_pai_crypto.c b/arch/s390/kernel/perf_pai_crypto.c index a7b339c4fd7c9ed6046f0c7a06913846df223e5d..fe7d1774ded18439270efeb3eecd200cbcc8893c 100644 --- a/arch/s390/kernel/perf_pai_crypto.c +++ b/arch/s390/kernel/perf_pai_crypto.c @@ -36,7 +36,7 @@ struct paicrypt_map { unsigned long *page; /* Page for CPU to store counters */ struct pai_userdata *save; /* Page to store no-zero counters */ unsigned int active_events; /* # of PAI crypto users */ - unsigned int refcnt; /* Reference count mapped buffers */ + refcount_t refcnt; /* Reference count mapped buffers */ enum paievt_mode mode; /* Type of event */ struct perf_event *event; /* Perf event for sampling */ }; @@ -57,10 +57,11 @@ static void paicrypt_event_destroy(struct perf_event *event) static_branch_dec(&pai_key); mutex_lock(&pai_reserve_mutex); debug_sprintf_event(cfm_dbg, 5, "%s event %#llx cpu %d users %d" - " mode %d refcnt %d\n", __func__, + " mode %d refcnt %u\n", __func__, event->attr.config, event->cpu, - cpump->active_events, cpump->mode, cpump->refcnt); - if (!--cpump->refcnt) { + cpump->active_events, cpump->mode, + refcount_read(&cpump->refcnt)); + if (refcount_dec_and_test(&cpump->refcnt)) { debug_sprintf_event(cfm_dbg, 4, "%s page %#lx save %p\n", __func__, (unsigned long)cpump->page, cpump->save); @@ -149,8 +150,10 @@ static int paicrypt_busy(struct perf_event_attr *a, struct paicrypt_map *cpump) /* Allocate memory for counter page and counter extraction. * Only the first counting event has to allocate a page. */ - if (cpump->page) + if (cpump->page) { + refcount_inc(&cpump->refcnt); goto unlock; + } rc = -ENOMEM; cpump->page = (unsigned long *)get_zeroed_page(GFP_KERNEL); @@ -164,18 +167,18 @@ static int paicrypt_busy(struct perf_event_attr *a, struct paicrypt_map *cpump) goto unlock; } rc = 0; + refcount_set(&cpump->refcnt, 1); unlock: /* If rc is non-zero, do not set mode and reference count */ if (!rc) { - cpump->refcnt++; cpump->mode = a->sample_period ? PAI_MODE_SAMPLING : PAI_MODE_COUNTING; } debug_sprintf_event(cfm_dbg, 5, "%s sample_period %#llx users %d" - " mode %d refcnt %d page %#lx save %p rc %d\n", + " mode %d refcnt %u page %#lx save %p rc %d\n", __func__, a->sample_period, cpump->active_events, - cpump->mode, cpump->refcnt, + cpump->mode, refcount_read(&cpump->refcnt), (unsigned long)cpump->page, cpump->save, rc); mutex_unlock(&pai_reserve_mutex); return rc; diff --git a/arch/s390/kernel/perf_pai_ext.c b/arch/s390/kernel/perf_pai_ext.c index fcea307d7529ade041973a7535effafc14c72796..c57c1a203256fba029be8e0a17344cbce5cc0957 100644 --- a/arch/s390/kernel/perf_pai_ext.c +++ b/arch/s390/kernel/perf_pai_ext.c @@ -50,7 +50,7 @@ struct paiext_map { struct pai_userdata *save; /* Area to store non-zero counters */ enum paievt_mode mode; /* Type of event */ unsigned int active_events; /* # of PAI Extension users */ - unsigned int refcnt; + refcount_t refcnt; struct perf_event *event; /* Perf event for sampling */ struct paiext_cb *paiext_cb; /* PAI extension control block area */ }; @@ -60,14 +60,14 @@ struct paiext_mapptr { }; static struct paiext_root { /* Anchor to per CPU data */ - int refcnt; /* Overall active events */ + refcount_t refcnt; /* Overall active events */ struct paiext_mapptr __percpu *mapptr; } paiext_root; /* Free per CPU data when the last event is removed. */ static void paiext_root_free(void) { - if (!--paiext_root.refcnt) { + if (refcount_dec_and_test(&paiext_root.refcnt)) { free_percpu(paiext_root.mapptr); paiext_root.mapptr = NULL; } @@ -80,17 +80,18 @@ static void paiext_root_free(void) */ static int paiext_root_alloc(void) { - if (++paiext_root.refcnt == 1) { + if (!refcount_inc_not_zero(&paiext_root.refcnt)) { /* The memory is already zeroed. */ paiext_root.mapptr = alloc_percpu(struct paiext_mapptr); if (!paiext_root.mapptr) { - /* Returing without refcnt adjustment is ok. The + /* Returning without refcnt adjustment is ok. The * error code is handled by paiext_alloc() which * decrements refcnt when an event can not be * created. */ return -ENOMEM; } + refcount_set(&paiext_root.refcnt, 1); } return 0; } @@ -122,7 +123,7 @@ static void paiext_event_destroy(struct perf_event *event) mutex_lock(&paiext_reserve_mutex); cpump->event = NULL; - if (!--cpump->refcnt) /* Last reference gone */ + if (refcount_dec_and_test(&cpump->refcnt)) /* Last reference gone */ paiext_free(mp); paiext_root_free(); mutex_unlock(&paiext_reserve_mutex); @@ -163,7 +164,7 @@ static int paiext_alloc(struct perf_event_attr *a, struct perf_event *event) rc = -ENOMEM; cpump = kzalloc(sizeof(*cpump), GFP_KERNEL); if (!cpump) - goto unlock; + goto undo; /* Allocate memory for counter area and counter extraction. * These are @@ -183,27 +184,28 @@ static int paiext_alloc(struct perf_event_attr *a, struct perf_event *event) GFP_KERNEL); if (!cpump->save || !cpump->area || !cpump->paiext_cb) { paiext_free(mp); - goto unlock; + goto undo; } + refcount_set(&cpump->refcnt, 1); cpump->mode = a->sample_period ? PAI_MODE_SAMPLING : PAI_MODE_COUNTING; } else { - /* Multiple invocation, check whats active. + /* Multiple invocation, check what is active. * Supported are multiple counter events or only one sampling * event concurrently at any one time. */ if (cpump->mode == PAI_MODE_SAMPLING || (cpump->mode == PAI_MODE_COUNTING && a->sample_period)) { rc = -EBUSY; - goto unlock; + goto undo; } + refcount_inc(&cpump->refcnt); } rc = 0; cpump->event = event; - ++cpump->refcnt; -unlock: +undo: if (rc) { /* Error in allocation of event, decrement anchor. Since * the event in not created, its destroy() function is never @@ -211,6 +213,7 @@ static int paiext_alloc(struct perf_event_attr *a, struct perf_event *event) */ paiext_root_free(); } +unlock: mutex_unlock(&paiext_reserve_mutex); /* If rc is non-zero, no increment of counter/sampler was done. */ return rc; diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c index 87ca3a727604ed26d89b5670ef6501388af17d94..2580004177248b2dd3bf549149416eaf60d8b8d3 100644 --- a/arch/s390/kernel/process.c +++ b/arch/s390/kernel/process.c @@ -30,8 +30,8 @@ #include #include #include +#include #include -#include #include #include #include diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index fe10da1a271e867966c2635e0ae1c4f5280a8f8f..00d76448319d25d02ac6aa1192ae9562cd9ed200 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c @@ -529,7 +529,7 @@ static void __init setup_resources(void) res->start = start; /* * In memblock, end points to the first byte after the - * range while in resourses, end points to the last byte in + * range while in resources, end points to the last byte in * the range. */ res->end = end - 1; diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index 726de4f4df0189240bea16888daeb65744f35bed..f9a2b755f510527c84e4d1c3a0ebe2d35bb4f01a 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c @@ -113,7 +113,7 @@ early_param("smt", early_smt); /* * The smp_cpu_state_mutex must be held when changing the state or polarization - * member of a pcpu data structure within the pcpu_devices arreay. + * member of a pcpu data structure within the pcpu_devices array. */ DEFINE_MUTEX(smp_cpu_state_mutex); diff --git a/arch/s390/kernel/syscalls/syscall.tbl b/arch/s390/kernel/syscalls/syscall.tbl index b68f47541169f9afdc0b440ee9ead767d76471fc..a6935af2235cab6cbc993a2efdb3e6fb18abcaeb 100644 --- a/arch/s390/kernel/syscalls/syscall.tbl +++ b/arch/s390/kernel/syscalls/syscall.tbl @@ -453,3 +453,4 @@ 448 common process_mrelease sys_process_mrelease sys_process_mrelease 449 common futex_waitv sys_futex_waitv sys_futex_waitv 450 common set_mempolicy_home_node sys_set_mempolicy_home_node sys_set_mempolicy_home_node +451 common cachestat sys_cachestat sys_cachestat diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c index 6b7b6d5e3632a27b53ebd768b273ada03f24be44..d34d3548c046c2ad2bcf8b61feda7b9b90e4bff6 100644 --- a/arch/s390/kernel/time.c +++ b/arch/s390/kernel/time.c @@ -102,6 +102,11 @@ void __init time_early_init(void) ((long) qui.old_leap * 4096000000L); } +unsigned long long noinstr sched_clock_noinstr(void) +{ + return tod_to_ns(__get_tod_clock_monotonic()); +} + /* * Scheduler clock - returns current time in nanosec units. */ @@ -697,7 +702,7 @@ static void stp_work_fn(struct work_struct *work) if (!check_sync_clock()) /* - * There is a usable clock but the synchonization failed. + * There is a usable clock but the synchronization failed. * Retry after a second. */ mod_timer(&stp_timer, jiffies + msecs_to_jiffies(MSEC_PER_SEC)); diff --git a/arch/s390/kernel/uv.c b/arch/s390/kernel/uv.c index cb2ee06df286cdcd7d93e0a0df400fc538fa5a24..66f0eb1c872bfefd81c9ff4de4261c1bf3c6afbe 100644 --- a/arch/s390/kernel/uv.c +++ b/arch/s390/kernel/uv.c @@ -23,12 +23,20 @@ int __bootdata_preserved(prot_virt_guest); #endif +/* + * uv_info contains both host and guest information but it's currently only + * expected to be used within modules if it's the KVM module or for + * any PV guest module. + * + * The kernel itself will write these values once in uv_query_info() + * and then make some of them readable via a sysfs interface. + */ struct uv_info __bootdata_preserved(uv_info); +EXPORT_SYMBOL(uv_info); #if IS_ENABLED(CONFIG_KVM) int __bootdata_preserved(prot_virt_host); EXPORT_SYMBOL(prot_virt_host); -EXPORT_SYMBOL(uv_info); static int __init uv_init(phys_addr_t stor_base, unsigned long stor_len) { @@ -294,6 +302,8 @@ int gmap_make_secure(struct gmap *gmap, unsigned long gaddr, void *uvcb) rc = -ENXIO; ptep = get_locked_pte(gmap->mm, uaddr, &ptelock); + if (!ptep) + goto out; if (pte_present(*ptep) && !(pte_val(*ptep) & _PAGE_INVALID) && pte_write(*ptep)) { page = pte_page(*ptep); rc = -EAGAIN; @@ -460,13 +470,13 @@ EXPORT_SYMBOL_GPL(arch_make_page_accessible); #if defined(CONFIG_PROTECTED_VIRTUALIZATION_GUEST) || IS_ENABLED(CONFIG_KVM) static ssize_t uv_query_facilities(struct kobject *kobj, - struct kobj_attribute *attr, char *page) + struct kobj_attribute *attr, char *buf) { - return scnprintf(page, PAGE_SIZE, "%lx\n%lx\n%lx\n%lx\n", - uv_info.inst_calls_list[0], - uv_info.inst_calls_list[1], - uv_info.inst_calls_list[2], - uv_info.inst_calls_list[3]); + return sysfs_emit(buf, "%lx\n%lx\n%lx\n%lx\n", + uv_info.inst_calls_list[0], + uv_info.inst_calls_list[1], + uv_info.inst_calls_list[2], + uv_info.inst_calls_list[3]); } static struct kobj_attribute uv_query_facilities_attr = @@ -491,30 +501,27 @@ static struct kobj_attribute uv_query_supp_se_hdr_pcf_attr = __ATTR(supp_se_hdr_pcf, 0444, uv_query_supp_se_hdr_pcf, NULL); static ssize_t uv_query_dump_cpu_len(struct kobject *kobj, - struct kobj_attribute *attr, char *page) + struct kobj_attribute *attr, char *buf) { - return scnprintf(page, PAGE_SIZE, "%lx\n", - uv_info.guest_cpu_stor_len); + return sysfs_emit(buf, "%lx\n", uv_info.guest_cpu_stor_len); } static struct kobj_attribute uv_query_dump_cpu_len_attr = __ATTR(uv_query_dump_cpu_len, 0444, uv_query_dump_cpu_len, NULL); static ssize_t uv_query_dump_storage_state_len(struct kobject *kobj, - struct kobj_attribute *attr, char *page) + struct kobj_attribute *attr, char *buf) { - return scnprintf(page, PAGE_SIZE, "%lx\n", - uv_info.conf_dump_storage_state_len); + return sysfs_emit(buf, "%lx\n", uv_info.conf_dump_storage_state_len); } static struct kobj_attribute uv_query_dump_storage_state_len_attr = __ATTR(dump_storage_state_len, 0444, uv_query_dump_storage_state_len, NULL); static ssize_t uv_query_dump_finalize_len(struct kobject *kobj, - struct kobj_attribute *attr, char *page) + struct kobj_attribute *attr, char *buf) { - return scnprintf(page, PAGE_SIZE, "%lx\n", - uv_info.conf_dump_finalize_len); + return sysfs_emit(buf, "%lx\n", uv_info.conf_dump_finalize_len); } static struct kobj_attribute uv_query_dump_finalize_len_attr = @@ -530,53 +537,86 @@ static struct kobj_attribute uv_query_feature_indications_attr = __ATTR(feature_indications, 0444, uv_query_feature_indications, NULL); static ssize_t uv_query_max_guest_cpus(struct kobject *kobj, - struct kobj_attribute *attr, char *page) + struct kobj_attribute *attr, char *buf) { - return scnprintf(page, PAGE_SIZE, "%d\n", - uv_info.max_guest_cpu_id + 1); + return sysfs_emit(buf, "%d\n", uv_info.max_guest_cpu_id + 1); } static struct kobj_attribute uv_query_max_guest_cpus_attr = __ATTR(max_cpus, 0444, uv_query_max_guest_cpus, NULL); static ssize_t uv_query_max_guest_vms(struct kobject *kobj, - struct kobj_attribute *attr, char *page) + struct kobj_attribute *attr, char *buf) { - return scnprintf(page, PAGE_SIZE, "%d\n", - uv_info.max_num_sec_conf); + return sysfs_emit(buf, "%d\n", uv_info.max_num_sec_conf); } static struct kobj_attribute uv_query_max_guest_vms_attr = __ATTR(max_guests, 0444, uv_query_max_guest_vms, NULL); static ssize_t uv_query_max_guest_addr(struct kobject *kobj, - struct kobj_attribute *attr, char *page) + struct kobj_attribute *attr, char *buf) { - return scnprintf(page, PAGE_SIZE, "%lx\n", - uv_info.max_sec_stor_addr); + return sysfs_emit(buf, "%lx\n", uv_info.max_sec_stor_addr); } static struct kobj_attribute uv_query_max_guest_addr_attr = __ATTR(max_address, 0444, uv_query_max_guest_addr, NULL); static ssize_t uv_query_supp_att_req_hdr_ver(struct kobject *kobj, - struct kobj_attribute *attr, char *page) + struct kobj_attribute *attr, char *buf) { - return scnprintf(page, PAGE_SIZE, "%lx\n", uv_info.supp_att_req_hdr_ver); + return sysfs_emit(buf, "%lx\n", uv_info.supp_att_req_hdr_ver); } static struct kobj_attribute uv_query_supp_att_req_hdr_ver_attr = __ATTR(supp_att_req_hdr_ver, 0444, uv_query_supp_att_req_hdr_ver, NULL); static ssize_t uv_query_supp_att_pflags(struct kobject *kobj, - struct kobj_attribute *attr, char *page) + struct kobj_attribute *attr, char *buf) { - return scnprintf(page, PAGE_SIZE, "%lx\n", uv_info.supp_att_pflags); + return sysfs_emit(buf, "%lx\n", uv_info.supp_att_pflags); } static struct kobj_attribute uv_query_supp_att_pflags_attr = __ATTR(supp_att_pflags, 0444, uv_query_supp_att_pflags, NULL); +static ssize_t uv_query_supp_add_secret_req_ver(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + return sysfs_emit(buf, "%lx\n", uv_info.supp_add_secret_req_ver); +} + +static struct kobj_attribute uv_query_supp_add_secret_req_ver_attr = + __ATTR(supp_add_secret_req_ver, 0444, uv_query_supp_add_secret_req_ver, NULL); + +static ssize_t uv_query_supp_add_secret_pcf(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + return sysfs_emit(buf, "%lx\n", uv_info.supp_add_secret_pcf); +} + +static struct kobj_attribute uv_query_supp_add_secret_pcf_attr = + __ATTR(supp_add_secret_pcf, 0444, uv_query_supp_add_secret_pcf, NULL); + +static ssize_t uv_query_supp_secret_types(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + return sysfs_emit(buf, "%lx\n", uv_info.supp_secret_types); +} + +static struct kobj_attribute uv_query_supp_secret_types_attr = + __ATTR(supp_secret_types, 0444, uv_query_supp_secret_types, NULL); + +static ssize_t uv_query_max_secrets(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + return sysfs_emit(buf, "%d\n", uv_info.max_secrets); +} + +static struct kobj_attribute uv_query_max_secrets_attr = + __ATTR(max_secrets, 0444, uv_query_max_secrets, NULL); + static struct attribute *uv_query_attrs[] = { &uv_query_facilities_attr.attr, &uv_query_feature_indications_attr.attr, @@ -590,6 +630,10 @@ static struct attribute *uv_query_attrs[] = { &uv_query_dump_cpu_len_attr.attr, &uv_query_supp_att_req_hdr_ver_attr.attr, &uv_query_supp_att_pflags_attr.attr, + &uv_query_supp_add_secret_req_ver_attr.attr, + &uv_query_supp_add_secret_pcf_attr.attr, + &uv_query_supp_secret_types_attr.attr, + &uv_query_max_secrets_attr.attr, NULL, }; @@ -598,18 +642,18 @@ static struct attribute_group uv_query_attr_group = { }; static ssize_t uv_is_prot_virt_guest(struct kobject *kobj, - struct kobj_attribute *attr, char *page) + struct kobj_attribute *attr, char *buf) { int val = 0; #ifdef CONFIG_PROTECTED_VIRTUALIZATION_GUEST val = prot_virt_guest; #endif - return scnprintf(page, PAGE_SIZE, "%d\n", val); + return sysfs_emit(buf, "%d\n", val); } static ssize_t uv_is_prot_virt_host(struct kobject *kobj, - struct kobj_attribute *attr, char *page) + struct kobj_attribute *attr, char *buf) { int val = 0; @@ -617,7 +661,7 @@ static ssize_t uv_is_prot_virt_host(struct kobject *kobj, val = prot_virt_host; #endif - return scnprintf(page, PAGE_SIZE, "%d\n", val); + return sysfs_emit(buf, "%d\n", val); } static struct kobj_attribute uv_prot_virt_guest = diff --git a/arch/s390/kernel/vdso32/Makefile b/arch/s390/kernel/vdso32/Makefile index bafd3147eb4efbdc96308a78e9d54cdfe25b82a6..23e868b79a6c99a8e119f829a923dbc6f81cbffa 100644 --- a/arch/s390/kernel/vdso32/Makefile +++ b/arch/s390/kernel/vdso32/Makefile @@ -19,6 +19,7 @@ KBUILD_AFLAGS_32 := $(filter-out -m64,$(KBUILD_AFLAGS)) KBUILD_AFLAGS_32 += -m31 -s KBUILD_CFLAGS_32 := $(filter-out -m64,$(KBUILD_CFLAGS)) +KBUILD_CFLAGS_32 := $(filter-out -mno-pic-data-is-text-relative,$(KBUILD_CFLAGS_32)) KBUILD_CFLAGS_32 += -m31 -fPIC -shared -fno-common -fno-builtin LDFLAGS_vdso32.so.dbg += -fPIC -shared -soname=linux-vdso32.so.1 \ @@ -40,8 +41,11 @@ KCSAN_SANITIZE := n # Force dependency (incbin is bad) $(obj)/vdso32_wrapper.o : $(obj)/vdso32.so +quiet_cmd_vdso_and_check = VDSO $@ + cmd_vdso_and_check = $(cmd_ld); $(cmd_vdso_check) + $(obj)/vdso32.so.dbg: $(src)/vdso32.lds $(obj-vdso32) FORCE - $(call if_changed,ld) + $(call if_changed,vdso_and_check) # strip rule for the .so file $(obj)/%.so: OBJCOPYFLAGS := -S diff --git a/arch/s390/kernel/vdso64/Makefile b/arch/s390/kernel/vdso64/Makefile index a766d286e15ff6482c29dc2735894088f2aa52c5..fc1c6ff8178f59489a8957f8ff6c6538b9d54919 100644 --- a/arch/s390/kernel/vdso64/Makefile +++ b/arch/s390/kernel/vdso64/Makefile @@ -24,6 +24,7 @@ KBUILD_AFLAGS_64 := $(filter-out -m64,$(KBUILD_AFLAGS)) KBUILD_AFLAGS_64 += -m64 KBUILD_CFLAGS_64 := $(filter-out -m64,$(KBUILD_CFLAGS)) +KBUILD_CFLAGS_64 := $(filter-out -mno-pic-data-is-text-relative,$(KBUILD_CFLAGS_64)) KBUILD_CFLAGS_64 += -m64 -fPIC -fno-common -fno-builtin ldflags-y := -fPIC -shared -soname=linux-vdso64.so.1 \ --hash-style=both --build-id=sha1 -T @@ -44,9 +45,12 @@ KCSAN_SANITIZE := n # Force dependency (incbin is bad) $(obj)/vdso64_wrapper.o : $(obj)/vdso64.so +quiet_cmd_vdso_and_check = VDSO $@ + cmd_vdso_and_check = $(cmd_ld); $(cmd_vdso_check) + # link rule for the .so file, .lds has to be first $(obj)/vdso64.so.dbg: $(src)/vdso64.lds $(obj-vdso64) $(obj-cvdso64) FORCE - $(call if_changed,ld) + $(call if_changed,vdso_and_check) # strip rule for the .so file $(obj)/%.so: OBJCOPYFLAGS := -S diff --git a/arch/s390/kvm/diag.c b/arch/s390/kvm/diag.c index 807fa9da1e721d59b637189309f7c1681d1b8b24..3c65b8258ae67ad4b28589494e663034e69dffdd 100644 --- a/arch/s390/kvm/diag.c +++ b/arch/s390/kvm/diag.c @@ -166,6 +166,7 @@ static int diag9c_forwarding_overrun(void) static int __diag_time_slice_end_directed(struct kvm_vcpu *vcpu) { struct kvm_vcpu *tcpu; + int tcpu_cpu; int tid; tid = vcpu->run->s.regs.gprs[(vcpu->arch.sie_block->ipa & 0xf0) >> 4]; @@ -181,14 +182,15 @@ static int __diag_time_slice_end_directed(struct kvm_vcpu *vcpu) goto no_yield; /* target guest VCPU already running */ - if (READ_ONCE(tcpu->cpu) >= 0) { + tcpu_cpu = READ_ONCE(tcpu->cpu); + if (tcpu_cpu >= 0) { if (!diag9c_forwarding_hz || diag9c_forwarding_overrun()) goto no_yield; /* target host CPU already running */ - if (!vcpu_is_preempted(tcpu->cpu)) + if (!vcpu_is_preempted(tcpu_cpu)) goto no_yield; - smp_yield_cpu(tcpu->cpu); + smp_yield_cpu(tcpu_cpu); VCPU_EVENT(vcpu, 5, "diag time slice end directed to %d: yield forwarded", tid); diff --git a/arch/s390/kvm/gaccess.c b/arch/s390/kvm/gaccess.c index 3eb85f254881c3673214fa5e826ab96bc7c979c3..6d6bc19b37dcbd25610df55a4e0b06a152187a96 100644 --- a/arch/s390/kvm/gaccess.c +++ b/arch/s390/kvm/gaccess.c @@ -478,7 +478,7 @@ struct trans_exc_code_bits { }; enum { - FSI_UNKNOWN = 0, /* Unknown wether fetch or store */ + FSI_UNKNOWN = 0, /* Unknown whether fetch or store */ FSI_STORE = 1, /* Exception was due to store operation */ FSI_FETCH = 2 /* Exception was due to fetch operation */ }; @@ -625,7 +625,7 @@ static int deref_table(struct kvm *kvm, unsigned long gpa, unsigned long *val) * Returns: - zero on success; @gpa contains the resulting absolute address * - a negative value if guest access failed due to e.g. broken * guest mapping - * - a positve value if an access exception happened. In this case + * - a positive value if an access exception happened. In this case * the returned value is the program interruption code as defined * by the architecture */ diff --git a/arch/s390/kvm/intercept.c b/arch/s390/kvm/intercept.c index 2cda8d9d7c6ef1f4d3762dcd2d6735ccb8e18100..954d39adf85cd3034f9d28d5e87d4e36f3f228b7 100644 --- a/arch/s390/kvm/intercept.c +++ b/arch/s390/kvm/intercept.c @@ -630,7 +630,7 @@ int kvm_handle_sie_intercept(struct kvm_vcpu *vcpu) return -EOPNOTSUPP; } - /* process PER, also if the instrution is processed in user space */ + /* process PER, also if the instruction is processed in user space */ if (vcpu->arch.sie_block->icptstatus & 0x02 && (!rc || rc == -EOPNOTSUPP)) per_rc = kvm_s390_handle_per_ifetch_icpt(vcpu); diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c index da6dac36e959f2e4720995bf02d14b3c5995b65e..9bd0a873f3b15f984bb06e0ceebcc6b7343665fc 100644 --- a/arch/s390/kvm/interrupt.c +++ b/arch/s390/kvm/interrupt.c @@ -2777,7 +2777,7 @@ static struct page *get_map_page(struct kvm *kvm, u64 uaddr) mmap_read_lock(kvm->mm); get_user_pages_remote(kvm->mm, uaddr, 1, FOLL_WRITE, - &page, NULL, NULL); + &page, NULL); mmap_read_unlock(kvm->mm); return page; } diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c index 17b81659cdb20c991565f46d422abc2d6eddb4d5..d1e768bcfe1d380fc6653c6376c0ad4f366c0a9a 100644 --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c @@ -2156,6 +2156,10 @@ static unsigned long kvm_s390_next_dirty_cmma(struct kvm_memslots *slots, ms = container_of(mnode, struct kvm_memory_slot, gfn_node[slots->node_idx]); ofs = 0; } + + if (cur_gfn < ms->base_gfn) + ofs = 0; + ofs = find_next_bit(kvm_second_dirty_bitmap(ms), ms->npages, ofs); while (ofs >= ms->npages && (mnode = rb_next(mnode))) { ms = container_of(mnode, struct kvm_memory_slot, gfn_node[slots->node_idx]); @@ -4157,7 +4161,7 @@ static void kvm_arch_vcpu_ioctl_initial_reset(struct kvm_vcpu *vcpu) vcpu->run->s.regs.fpc = 0; /* * Do not reset these registers in the protected case, as some of - * them are overlayed and they are not accessible in this case + * them are overlaid and they are not accessible in this case * anyway. */ if (!kvm_s390_pv_cpu_is_protected(vcpu)) { diff --git a/arch/s390/kvm/pci.c b/arch/s390/kvm/pci.c index 7dab00f1e83359a98d3c325039d1c4bb30c5c894..ffa7739c7a284d8b8f76634c7feb9bbb4bc392a6 100644 --- a/arch/s390/kvm/pci.c +++ b/arch/s390/kvm/pci.c @@ -427,7 +427,7 @@ static void kvm_s390_pci_dev_release(struct zpci_dev *zdev) /* - * Register device with the specified KVM. If interpetation facilities are + * Register device with the specified KVM. If interpretation facilities are * available, enable them and let userspace indicate whether or not they will * be used (specify SHM bit to disable). */ diff --git a/arch/s390/kvm/priv.c b/arch/s390/kvm/priv.c index 9f8a192bd750f9b4150779aabbaed2000c962cab..dc4cfa8795c08c9e1ff647817384794139ba5517 100644 --- a/arch/s390/kvm/priv.c +++ b/arch/s390/kvm/priv.c @@ -13,7 +13,7 @@ #include #include #include - +#include #include #include #include @@ -22,7 +22,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/s390/kvm/pv.c b/arch/s390/kvm/pv.c index 3ce5f4351156a2995951cbac7db02ed62eabd8c4..2f34c7c3c5abf8b0562ade069985d09087df0f29 100644 --- a/arch/s390/kvm/pv.c +++ b/arch/s390/kvm/pv.c @@ -273,7 +273,7 @@ static int kvm_s390_pv_deinit_vm_fast(struct kvm *kvm, u16 *rc, u16 *rrc) uvcb.header.rc, uvcb.header.rrc); WARN_ONCE(cc, "protvirt destroy vm fast failed handle %llx rc %x rrc %x", kvm_s390_pv_get_handle(kvm), uvcb.header.rc, uvcb.header.rrc); - /* Inteded memory leak on "impossible" error */ + /* Intended memory leak on "impossible" error */ if (!cc) kvm_s390_pv_dealloc_vm(kvm); return cc ? -EIO : 0; diff --git a/arch/s390/kvm/sigp.c b/arch/s390/kvm/sigp.c index cb747bf6c7982ec460073e44175d620659bb5c80..d9696b5300647c87332bb212cab2840071913e37 100644 --- a/arch/s390/kvm/sigp.c +++ b/arch/s390/kvm/sigp.c @@ -469,7 +469,7 @@ int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu) * * This interception will occur at the source cpu when a source cpu sends an * external call to a target cpu and the target cpu has the WAIT bit set in - * its cpuflags. Interception will occurr after the interrupt indicator bits at + * its cpuflags. Interception will occur after the interrupt indicator bits at * the target cpu have been set. All error cases will lead to instruction * interception, therefore nothing is to be checked or prepared. */ diff --git a/arch/s390/kvm/vsie.c b/arch/s390/kvm/vsie.c index 8d6b765abf29bffd3a9c5ef57f44b10645e0f3a4..61499293c2ac3b955a7de66a366f955d144ae3b5 100644 --- a/arch/s390/kvm/vsie.c +++ b/arch/s390/kvm/vsie.c @@ -177,7 +177,8 @@ static int setup_apcb00(struct kvm_vcpu *vcpu, unsigned long *apcb_s, sizeof(struct kvm_s390_apcb0))) return -EFAULT; - bitmap_and(apcb_s, apcb_s, apcb_h, sizeof(struct kvm_s390_apcb0)); + bitmap_and(apcb_s, apcb_s, apcb_h, + BITS_PER_BYTE * sizeof(struct kvm_s390_apcb0)); return 0; } @@ -203,7 +204,8 @@ static int setup_apcb11(struct kvm_vcpu *vcpu, unsigned long *apcb_s, sizeof(struct kvm_s390_apcb1))) return -EFAULT; - bitmap_and(apcb_s, apcb_s, apcb_h, sizeof(struct kvm_s390_apcb1)); + bitmap_and(apcb_s, apcb_s, apcb_h, + BITS_PER_BYTE * sizeof(struct kvm_s390_apcb1)); return 0; } @@ -502,7 +504,7 @@ static int shadow_scb(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page) scb_s->mso = new_mso; scb_s->prefix = new_prefix; - /* We have to definetly flush the tlb if this scb never ran */ + /* We have to definitely flush the tlb if this scb never ran */ if (scb_s->ihcpu != 0xffffU) scb_s->ihcpu = scb_o->ihcpu; @@ -899,7 +901,7 @@ static int inject_fault(struct kvm_vcpu *vcpu, __u16 code, __u64 vaddr, (vaddr & 0xfffffffffffff000UL) | /* 52-53: store / fetch */ (((unsigned int) !write_flag) + 1) << 10, - /* 62-63: asce id (alway primary == 0) */ + /* 62-63: asce id (always primary == 0) */ .exc_access_id = 0, /* always primary */ .op_access_id = 0, /* not MVPG */ }; diff --git a/arch/s390/lib/Makefile b/arch/s390/lib/Makefile index 580d2e3265cb2ce04523064b2c14c76b78ae42db..7c50eca85ca40b02432c82b5e41b391e5eafd5c0 100644 --- a/arch/s390/lib/Makefile +++ b/arch/s390/lib/Makefile @@ -3,7 +3,7 @@ # Makefile for s390-specific library files.. # -lib-y += delay.o string.o uaccess.o find.o spinlock.o +lib-y += delay.o string.o uaccess.o find.o spinlock.o tishift.o obj-y += mem.o xor.o lib-$(CONFIG_KPROBES) += probes.o lib-$(CONFIG_UPROBES) += probes.o diff --git a/arch/s390/lib/spinlock.c b/arch/s390/lib/spinlock.c index 04d4c6cf898ef3b61ef889a06196dc91a5c6f1b8..81c53440b3e66d3d34f0b1b805970ba82a332fe1 100644 --- a/arch/s390/lib/spinlock.c +++ b/arch/s390/lib/spinlock.c @@ -13,8 +13,8 @@ #include #include #include +#include #include -#include int spin_retry = -1; diff --git a/arch/s390/lib/tishift.S b/arch/s390/lib/tishift.S new file mode 100644 index 0000000000000000000000000000000000000000..de33cf02cfd2f9b45ee0f9f70f2d1eeaac345233 --- /dev/null +++ b/arch/s390/lib/tishift.S @@ -0,0 +1,63 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#include +#include +#include + + .section .noinstr.text, "ax" + + GEN_BR_THUNK %r14 + +SYM_FUNC_START(__ashlti3) + lmg %r0,%r1,0(%r3) + cije %r4,0,1f + lhi %r3,64 + sr %r3,%r4 + jnh 0f + srlg %r3,%r1,0(%r3) + sllg %r0,%r0,0(%r4) + sllg %r1,%r1,0(%r4) + ogr %r0,%r3 + j 1f +0: sllg %r0,%r1,-64(%r4) + lghi %r1,0 +1: stmg %r0,%r1,0(%r2) + BR_EX %r14 +SYM_FUNC_END(__ashlti3) +EXPORT_SYMBOL(__ashlti3) + +SYM_FUNC_START(__ashrti3) + lmg %r0,%r1,0(%r3) + cije %r4,0,1f + lhi %r3,64 + sr %r3,%r4 + jnh 0f + sllg %r3,%r0,0(%r3) + srlg %r1,%r1,0(%r4) + srag %r0,%r0,0(%r4) + ogr %r1,%r3 + j 1f +0: srag %r1,%r0,-64(%r4) + srag %r0,%r0,63 +1: stmg %r0,%r1,0(%r2) + BR_EX %r14 +SYM_FUNC_END(__ashrti3) +EXPORT_SYMBOL(__ashrti3) + +SYM_FUNC_START(__lshrti3) + lmg %r0,%r1,0(%r3) + cije %r4,0,1f + lhi %r3,64 + sr %r3,%r4 + jnh 0f + sllg %r3,%r0,0(%r3) + srlg %r1,%r1,0(%r4) + srlg %r0,%r0,0(%r4) + ogr %r1,%r3 + j 1f +0: srlg %r1,%r0,-64(%r4) + lghi %r0,0 +1: stmg %r0,%r1,0(%r2) + BR_EX %r14 +SYM_FUNC_END(__lshrti3) +EXPORT_SYMBOL(__lshrti3) diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c index b65144c392b01a1f6a0468e2d08e66d15a0cecd6..dbe8394234e2b10050b913485b51a3b438f66506 100644 --- a/arch/s390/mm/fault.c +++ b/arch/s390/mm/fault.c @@ -457,8 +457,9 @@ static inline vm_fault_t do_exception(struct pt_regs *regs, int access) if (unlikely(vma->vm_start > address)) { if (!(vma->vm_flags & VM_GROWSDOWN)) goto out_up; - if (expand_stack(vma, address)) - goto out_up; + vma = expand_stack(mm, address); + if (!vma) + goto out; } /* diff --git a/arch/s390/mm/gmap.c b/arch/s390/mm/gmap.c index dc90d1eb0d554f920712929783826cd32843091b..989ebd0912b489ba4667c0c8d4452a5e71c13d3a 100644 --- a/arch/s390/mm/gmap.c +++ b/arch/s390/mm/gmap.c @@ -895,12 +895,12 @@ static int gmap_pte_op_fixup(struct gmap *gmap, unsigned long gaddr, /** * gmap_pte_op_end - release the page table lock - * @ptl: pointer to the spinlock pointer + * @ptep: pointer to the locked pte + * @ptl: pointer to the page table spinlock */ -static void gmap_pte_op_end(spinlock_t *ptl) +static void gmap_pte_op_end(pte_t *ptep, spinlock_t *ptl) { - if (ptl) - spin_unlock(ptl); + pte_unmap_unlock(ptep, ptl); } /** @@ -1011,7 +1011,7 @@ static int gmap_protect_pte(struct gmap *gmap, unsigned long gaddr, { int rc; pte_t *ptep; - spinlock_t *ptl = NULL; + spinlock_t *ptl; unsigned long pbits = 0; if (pmd_val(*pmdp) & _SEGMENT_ENTRY_INVALID) @@ -1025,7 +1025,7 @@ static int gmap_protect_pte(struct gmap *gmap, unsigned long gaddr, pbits |= (bits & GMAP_NOTIFY_SHADOW) ? PGSTE_VSIE_BIT : 0; /* Protect and unlock. */ rc = ptep_force_prot(gmap->mm, gaddr, ptep, prot, pbits); - gmap_pte_op_end(ptl); + gmap_pte_op_end(ptep, ptl); return rc; } @@ -1154,7 +1154,7 @@ int gmap_read_table(struct gmap *gmap, unsigned long gaddr, unsigned long *val) /* Do *NOT* clear the _PAGE_INVALID bit! */ rc = 0; } - gmap_pte_op_end(ptl); + gmap_pte_op_end(ptep, ptl); } if (!rc) break; @@ -1248,7 +1248,7 @@ static int gmap_protect_rmap(struct gmap *sg, unsigned long raddr, if (!rc) gmap_insert_rmap(sg, vmaddr, rmap); spin_unlock(&sg->guest_table_lock); - gmap_pte_op_end(ptl); + gmap_pte_op_end(ptep, ptl); } radix_tree_preload_end(); if (rc) { @@ -1740,7 +1740,7 @@ EXPORT_SYMBOL_GPL(gmap_shadow); * The r2t parameter specifies the address of the source table. The * four pages of the source table are made read-only in the parent gmap * address space. A write to the source table area @r2t will automatically - * remove the shadow r2 table and all of its decendents. + * remove the shadow r2 table and all of its descendants. * * Returns 0 if successfully shadowed or already shadowed, -EAGAIN if the * shadow table structure is incomplete, -ENOMEM if out of memory and @@ -2156,7 +2156,7 @@ int gmap_shadow_page(struct gmap *sg, unsigned long saddr, pte_t pte) tptep = (pte_t *) gmap_table_walk(sg, saddr, 0); if (!tptep) { spin_unlock(&sg->guest_table_lock); - gmap_pte_op_end(ptl); + gmap_pte_op_end(sptep, ptl); radix_tree_preload_end(); break; } @@ -2167,7 +2167,7 @@ int gmap_shadow_page(struct gmap *sg, unsigned long saddr, pte_t pte) rmap = NULL; rc = 0; } - gmap_pte_op_end(ptl); + gmap_pte_op_end(sptep, ptl); spin_unlock(&sg->guest_table_lock); } radix_tree_preload_end(); @@ -2495,7 +2495,7 @@ void gmap_sync_dirty_log_pmd(struct gmap *gmap, unsigned long bitmap[4], continue; if (ptep_test_and_clear_uc(gmap->mm, vmaddr, ptep)) set_bit(i, bitmap); - spin_unlock(ptl); + pte_unmap_unlock(ptep, ptl); } } gmap_pmd_op_end(gmap, pmdp); @@ -2537,7 +2537,12 @@ static inline void thp_split_mm(struct mm_struct *mm) * Remove all empty zero pages from the mapping for lazy refaulting * - This must be called after mm->context.has_pgste is set, to avoid * future creation of zero pages - * - This must be called after THP was enabled + * - This must be called after THP was disabled. + * + * mm contracts with s390, that even if mm were to remove a page table, + * racing with the loop below and so causing pte_offset_map_lock() to fail, + * it will never insert a page table containing empty zero pages once + * mm_forbids_zeropage(mm) i.e. mm->context.has_pgste is set. */ static int __zap_zero_pages(pmd_t *pmd, unsigned long start, unsigned long end, struct mm_walk *walk) @@ -2549,6 +2554,8 @@ static int __zap_zero_pages(pmd_t *pmd, unsigned long start, spinlock_t *ptl; ptep = pte_offset_map_lock(walk->mm, pmd, addr, &ptl); + if (!ptep) + break; if (is_zero_pfn(pte_pfn(*ptep))) ptep_xchg_direct(walk->mm, addr, ptep, __pte(_PAGE_INVALID)); pte_unmap_unlock(ptep, ptl); diff --git a/arch/s390/mm/maccess.c b/arch/s390/mm/maccess.c index d02a61620cfab771dde0acdb4243e188529bf056..cbe1df1e9c185dae64c869f24fe17e0279249ca2 100644 --- a/arch/s390/mm/maccess.c +++ b/arch/s390/mm/maccess.c @@ -13,9 +13,9 @@ #include #include #include +#include #include #include -#include #include #include #include diff --git a/arch/s390/mm/pageattr.c b/arch/s390/mm/pageattr.c index 5ba3bd8a7b12495bac66a22b93a8056619285f71..ca5a418c58a8c87e9671c1869b0abec7b5b26c19 100644 --- a/arch/s390/mm/pageattr.c +++ b/arch/s390/mm/pageattr.c @@ -4,6 +4,7 @@ * Author(s): Jan Glauber */ #include +#include #include #include #include diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c index 6effb24de6d9feef2dee59958d3a748776103810..3bd2ab2a9a3449a411145a938d65a0b1f9a5ad62 100644 --- a/arch/s390/mm/pgtable.c +++ b/arch/s390/mm/pgtable.c @@ -829,7 +829,7 @@ int set_guest_storage_key(struct mm_struct *mm, unsigned long addr, default: return -EFAULT; } - +again: ptl = pmd_lock(mm, pmdp); if (!pmd_present(*pmdp)) { spin_unlock(ptl); @@ -850,6 +850,8 @@ int set_guest_storage_key(struct mm_struct *mm, unsigned long addr, spin_unlock(ptl); ptep = pte_offset_map_lock(mm, pmdp, addr, &ptl); + if (!ptep) + goto again; new = old = pgste_get_lock(ptep); pgste_val(new) &= ~(PGSTE_GR_BIT | PGSTE_GC_BIT | PGSTE_ACC_BITS | PGSTE_FP_BIT); @@ -938,7 +940,7 @@ int reset_guest_reference_bit(struct mm_struct *mm, unsigned long addr) default: return -EFAULT; } - +again: ptl = pmd_lock(mm, pmdp); if (!pmd_present(*pmdp)) { spin_unlock(ptl); @@ -955,6 +957,8 @@ int reset_guest_reference_bit(struct mm_struct *mm, unsigned long addr) spin_unlock(ptl); ptep = pte_offset_map_lock(mm, pmdp, addr, &ptl); + if (!ptep) + goto again; new = old = pgste_get_lock(ptep); /* Reset guest reference bit only */ pgste_val(new) &= ~PGSTE_GR_BIT; @@ -1000,7 +1004,7 @@ int get_guest_storage_key(struct mm_struct *mm, unsigned long addr, default: return -EFAULT; } - +again: ptl = pmd_lock(mm, pmdp); if (!pmd_present(*pmdp)) { spin_unlock(ptl); @@ -1017,6 +1021,8 @@ int get_guest_storage_key(struct mm_struct *mm, unsigned long addr, spin_unlock(ptl); ptep = pte_offset_map_lock(mm, pmdp, addr, &ptl); + if (!ptep) + goto again; pgste = pgste_get_lock(ptep); *key = (pgste_val(pgste) & (PGSTE_ACC_BITS | PGSTE_FP_BIT)) >> 56; paddr = pte_val(*ptep) & PAGE_MASK; diff --git a/arch/s390/mm/vmem.c b/arch/s390/mm/vmem.c index 5b22c6e24528aa2d7a359d9a29182088738975c1..b26649233d124984018633396fc7df6ea4adda74 100644 --- a/arch/s390/mm/vmem.c +++ b/arch/s390/mm/vmem.c @@ -481,6 +481,7 @@ static int remove_pagetable(unsigned long start, unsigned long end, bool direct) */ static int vmem_add_range(unsigned long start, unsigned long size) { + start = (unsigned long)__va(start); return add_pagetable(start, start + size, true); } @@ -489,6 +490,7 @@ static int vmem_add_range(unsigned long start, unsigned long size) */ static void vmem_remove_range(unsigned long start, unsigned long size) { + start = (unsigned long)__va(start); remove_pagetable(start, start + size, true); } @@ -556,7 +558,7 @@ int vmem_add_mapping(unsigned long start, unsigned long size) * to any physical address. If missing, allocate segment- and region- * table entries along. Meeting a large segment- or region-table entry * while traversing is an error, since the function is expected to be - * called against virtual regions reserverd for 4KB mappings only. + * called against virtual regions reserved for 4KB mappings only. */ pte_t *vmem_get_alloc_pte(unsigned long addr, bool alloc) { @@ -667,7 +669,15 @@ static void __init memblock_region_swap(void *a, void *b, int size) #ifdef CONFIG_KASAN #define __sha(x) ((unsigned long)kasan_mem_to_shadow((void *)x)) + +static inline int set_memory_kasan(unsigned long start, unsigned long end) +{ + start = PAGE_ALIGN_DOWN(__sha(start)); + end = PAGE_ALIGN(__sha(end)); + return set_memory_rwnx(start, (end - start) >> PAGE_SHIFT); +} #endif + /* * map whole physical memory to virtual memory (identity mapping) * we reserve enough space in the vmalloc area for vmemmap to hotplug @@ -737,10 +747,8 @@ void __init vmem_map_init(void) } #ifdef CONFIG_KASAN - for_each_mem_range(i, &base, &end) { - set_memory_rwnx(__sha(base), - (__sha(end) - __sha(base)) >> PAGE_SHIFT); - } + for_each_mem_range(i, &base, &end) + set_memory_kasan(base, end); #endif set_memory_rox((unsigned long)_stext, (unsigned long)(_etext - _stext) >> PAGE_SHIFT); diff --git a/arch/s390/net/bpf_jit_comp.c b/arch/s390/net/bpf_jit_comp.c index f95d7e401b96ca13e27df188a03710d6b83c4ecc..5e9371fbf3d5f3c39f6e98126c0ba8c1d28eb777 100644 --- a/arch/s390/net/bpf_jit_comp.c +++ b/arch/s390/net/bpf_jit_comp.c @@ -523,12 +523,12 @@ extern const char bpf_plt_end[]; #define BPF_PLT_SIZE 32 asm( ".pushsection .rodata\n" - " .align 8\n" + " .balign 8\n" "bpf_plt:\n" " lgrl %r0,bpf_plt_ret\n" " lgrl %r1,bpf_plt_target\n" " br %r1\n" - " .align 8\n" + " .balign 8\n" "bpf_plt_ret: .quad 0\n" "bpf_plt_target: .quad 0\n" "bpf_plt_end:\n" diff --git a/arch/s390/pci/pci_irq.c b/arch/s390/pci/pci_irq.c index 4ab0cf8299992c00b3fa335ee6de6b794a1c8be2..ff8f24854c6462f34b29e3d523b6a6bce8f68100 100644 --- a/arch/s390/pci/pci_irq.c +++ b/arch/s390/pci/pci_irq.c @@ -163,7 +163,7 @@ static void zpci_handle_cpu_local_irq(bool rescan) if (!rescan || irqs_on++) /* End of second scan with interrupts on. */ break; - /* First scan complete, reenable interrupts. */ + /* First scan complete, re-enable interrupts. */ if (zpci_set_irq_ctrl(SIC_IRQ_MODE_D_SINGLE, PCI_ISC, &iib)) break; bit = 0; @@ -202,7 +202,7 @@ static void zpci_handle_fallback_irq(void) if (irqs_on++) /* End of second scan with interrupts on. */ break; - /* First scan complete, reenable interrupts. */ + /* First scan complete, re-enable interrupts. */ if (zpci_set_irq_ctrl(SIC_IRQ_MODE_SINGLE, PCI_ISC, &iib)) break; cpu = 0; @@ -247,7 +247,7 @@ static void zpci_floating_irq_handler(struct airq_struct *airq, if (irqs_on++) /* End of second scan with interrupts on. */ break; - /* First scan complete, reenable interrupts. */ + /* First scan complete, re-enable interrupts. */ if (zpci_set_irq_ctrl(SIC_IRQ_MODE_SINGLE, PCI_ISC, &iib)) break; si = 0; diff --git a/arch/s390/purgatory/Makefile b/arch/s390/purgatory/Makefile index cc8cf5abea158c63449fb130bd3f369a10884e5d..4e930f56687899f2cc18e38b07adc7fbd98e0d25 100644 --- a/arch/s390/purgatory/Makefile +++ b/arch/s390/purgatory/Makefile @@ -10,7 +10,7 @@ PURGATORY_OBJS = $(addprefix $(obj)/,$(purgatory-y)) $(obj)/sha256.o: $(srctree)/lib/crypto/sha256.c FORCE $(call if_changed_rule,cc_o_c) -CFLAGS_sha256.o := -D__DISABLE_EXPORTS +CFLAGS_sha256.o := -D__DISABLE_EXPORTS -D__NO_FORTIFY $(obj)/mem.o: $(srctree)/arch/s390/lib/mem.S FORCE $(call if_changed_rule,as_o_S) diff --git a/arch/s390/purgatory/head.S b/arch/s390/purgatory/head.S index e5bd1a50352833eef9dff6d347fc156e9152b223..0f93f2e72eba0897c932c56a124f2a1b2505faa6 100644 --- a/arch/s390/purgatory/head.S +++ b/arch/s390/purgatory/head.S @@ -100,7 +100,7 @@ SYM_CODE_START(purgatory_start) * checksum verification only (%r2 = 0 -> verification only). * * Check now and preserve over C function call by storing in - * %r10 whith + * %r10 with * 1 -> checksum verification only * 0 -> load new kernel */ diff --git a/arch/sh/Kbuild b/arch/sh/Kbuild index be171880977e5d250117b4c9810de7aa0ca7fbf6..056efec72c2a0b1157d6d536924bdedf416c3f4b 100644 --- a/arch/sh/Kbuild +++ b/arch/sh/Kbuild @@ -3,5 +3,7 @@ obj-y += kernel/ mm/ boards/ obj-$(CONFIG_SH_FPU_EMU) += math-emu/ obj-$(CONFIG_USE_BUILTIN_DTB) += boot/dts/ +obj-$(CONFIG_HD6446X_SERIES) += cchips/hd6446x/ + # for cleaning subdir- += boot diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index 9652d367fc37771863e57369c94ab9489f080f87..2b3ce4fd39563d5284a415c8e1b32011471d9afa 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig @@ -6,6 +6,7 @@ config SUPERH select ARCH_ENABLE_MEMORY_HOTREMOVE if SPARSEMEM && MMU select ARCH_HAVE_NMI_SAFE_CMPXCHG if (GUSA_RB || CPU_SH4A) select ARCH_HAS_BINFMT_FLAT if !MMU + select ARCH_HAS_CPU_FINALIZE_INIT select ARCH_HAS_CURRENT_STACK_POINTER select ARCH_HAS_GIGANTIC_PAGE select ARCH_HAS_GCOV_PROFILE_ALL @@ -59,6 +60,7 @@ config SUPERH select HAVE_STACKPROTECTOR select HAVE_SYSCALL_TRACEPOINTS select IRQ_FORCED_THREADING + select LOCK_MM_AND_FIND_VMA select MODULES_USE_ELF_RELA select NEED_SG_DMA_LENGTH select NO_DMA if !MMU && !DMA_COHERENT diff --git a/arch/sh/Makefile b/arch/sh/Makefile index 5c8776482530c35a653f888fd05da38da5ab197a..cab2f9c011a8db8f15a3ce253bf185268fa06078 100644 --- a/arch/sh/Makefile +++ b/arch/sh/Makefile @@ -116,34 +116,15 @@ export ld-bfd # Mach groups machdir-$(CONFIG_SOLUTION_ENGINE) += mach-se -machdir-$(CONFIG_SH_HP6XX) += mach-hp6xx machdir-$(CONFIG_SH_DREAMCAST) += mach-dreamcast machdir-$(CONFIG_SH_SH03) += mach-sh03 -machdir-$(CONFIG_SH_RTS7751R2D) += mach-r2d -machdir-$(CONFIG_SH_HIGHLANDER) += mach-highlander machdir-$(CONFIG_SH_MIGOR) += mach-migor -machdir-$(CONFIG_SH_AP325RXA) += mach-ap325rxa machdir-$(CONFIG_SH_KFR2R09) += mach-kfr2r09 machdir-$(CONFIG_SH_ECOVEC) += mach-ecovec24 -machdir-$(CONFIG_SH_SDK7780) += mach-sdk7780 machdir-$(CONFIG_SH_SDK7786) += mach-sdk7786 machdir-$(CONFIG_SH_X3PROTO) += mach-x3proto -machdir-$(CONFIG_SH_SH7763RDP) += mach-sh7763rdp -machdir-$(CONFIG_SH_SH4202_MICRODEV) += mach-microdev machdir-$(CONFIG_SH_LANDISK) += mach-landisk -machdir-$(CONFIG_SH_LBOX_RE2) += mach-lboxre2 -machdir-$(CONFIG_SH_RSK) += mach-rsk - -ifneq ($(machdir-y),) -core-y += $(addprefix arch/sh/boards/, \ - $(filter-out ., $(patsubst %,%/,$(machdir-y)))) -endif - -# Common machine type headers. Not part of the arch/sh/boards/ hierarchy. -machdir-y += mach-common - -# Companion chips -core-$(CONFIG_HD6446X_SERIES) += arch/sh/cchips/hd6446x/ +machdir-y += mach-common # # CPU header paths @@ -164,11 +145,8 @@ cpuincdir-y += cpu-common # Must be last drivers-y += arch/sh/drivers/ -cflags-y += $(foreach d, $(cpuincdir-y), -I $(srctree)/arch/sh/include/$(d)) \ - $(foreach d, $(machdir-y), -I $(srctree)/arch/sh/include/$(d)) - +KBUILD_CPPFLAGS += $(addprefix -I $(srctree)/arch/sh/include/, $(cpuincdir-y) $(machdir-y)) KBUILD_CFLAGS += -pipe $(cflags-y) -KBUILD_CPPFLAGS += $(cflags-y) KBUILD_AFLAGS += $(cflags-y) ifeq ($(CONFIG_MCOUNT),y) diff --git a/arch/sh/boards/Makefile b/arch/sh/boards/Makefile index 4002a22a7c409be069d66507694243de9277f631..b57219436ace3ebb816396821dee10214d45fa9f 100644 --- a/arch/sh/boards/Makefile +++ b/arch/sh/boards/Makefile @@ -18,3 +18,22 @@ obj-$(CONFIG_SH_APSH4A3A) += board-apsh4a3a.o obj-$(CONFIG_SH_APSH4AD0A) += board-apsh4ad0a.o obj-$(CONFIG_SH_DEVICE_TREE) += of-generic.o + +obj-$(CONFIG_SOLUTION_ENGINE) += mach-se/ +obj-$(CONFIG_SH_HP6XX) += mach-hp6xx/ +obj-$(CONFIG_SH_DREAMCAST) += mach-dreamcast/ +obj-$(CONFIG_SH_SH03) += mach-sh03/ +obj-$(CONFIG_SH_RTS7751R2D) += mach-r2d/ +obj-$(CONFIG_SH_HIGHLANDER) += mach-highlander/ +obj-$(CONFIG_SH_MIGOR) += mach-migor/ +obj-$(CONFIG_SH_AP325RXA) += mach-ap325rxa/ +obj-$(CONFIG_SH_KFR2R09) += mach-kfr2r09/ +obj-$(CONFIG_SH_ECOVEC) += mach-ecovec24/ +obj-$(CONFIG_SH_SDK7780) += mach-sdk7780/ +obj-$(CONFIG_SH_SDK7786) += mach-sdk7786/ +obj-$(CONFIG_SH_X3PROTO) += mach-x3proto/ +obj-$(CONFIG_SH_SH7763RDP) += mach-sh7763rdp/ +obj-$(CONFIG_SH_SH4202_MICRODEV)+= mach-microdev/ +obj-$(CONFIG_SH_LANDISK) += mach-landisk/ +obj-$(CONFIG_SH_LBOX_RE2) += mach-lboxre2/ +obj-$(CONFIG_SH_RSK) += mach-rsk/ diff --git a/arch/sh/boards/mach-dreamcast/irq.c b/arch/sh/boards/mach-dreamcast/irq.c index cc06e4cdb4cdf9b7cab0597183b06061a5901ec9..0eec82fb85e7c6b4cb262fc79ed7fa24d3e4f70b 100644 --- a/arch/sh/boards/mach-dreamcast/irq.c +++ b/arch/sh/boards/mach-dreamcast/irq.c @@ -108,13 +108,13 @@ int systemasic_irq_demux(int irq) __u32 j, bit; switch (irq) { - case 13: + case 13 + 16: level = 0; break; - case 11: + case 11 + 16: level = 1; break; - case 9: + case 9 + 16: level = 2; break; default: diff --git a/arch/sh/boards/mach-highlander/setup.c b/arch/sh/boards/mach-highlander/setup.c index 533393d779c2b97f987c7df2444847278e14b549..01565660a6695014a75dd5d36365935677ea995f 100644 --- a/arch/sh/boards/mach-highlander/setup.c +++ b/arch/sh/boards/mach-highlander/setup.c @@ -389,10 +389,10 @@ static unsigned char irl2irq[HL_NR_IRL]; static int highlander_irq_demux(int irq) { - if (irq >= HL_NR_IRL || irq < 0 || !irl2irq[irq]) + if (irq >= HL_NR_IRL + 16 || irq < 16 || !irl2irq[irq - 16]) return irq; - return irl2irq[irq]; + return irl2irq[irq - 16]; } static void __init highlander_init_irq(void) diff --git a/arch/sh/boards/mach-r2d/irq.c b/arch/sh/boards/mach-r2d/irq.c index e34f81e9ae813b8dbb650a742e328869dc6d91de..d0a54a9adbce20fa447f620df1d65cdcbea35e08 100644 --- a/arch/sh/boards/mach-r2d/irq.c +++ b/arch/sh/boards/mach-r2d/irq.c @@ -117,10 +117,10 @@ static unsigned char irl2irq[R2D_NR_IRL]; int rts7751r2d_irq_demux(int irq) { - if (irq >= R2D_NR_IRL || irq < 0 || !irl2irq[irq]) + if (irq >= R2D_NR_IRL + 16 || irq < 16 || !irl2irq[irq - 16]) return irq; - return irl2irq[irq]; + return irl2irq[irq - 16]; } /* diff --git a/arch/sh/cchips/Kconfig b/arch/sh/cchips/Kconfig index efde2edb5627809e232cbf1528b9d152f4659103..9659a0bc58dec40b9952cd8b8cd15dbb3dee7c32 100644 --- a/arch/sh/cchips/Kconfig +++ b/arch/sh/cchips/Kconfig @@ -29,9 +29,9 @@ endchoice config HD64461_IRQ int "HD64461 IRQ" depends on HD64461 - default "36" + default "52" help - The default setting of the HD64461 IRQ is 36. + The default setting of the HD64461 IRQ is 52. Do not change this unless you know what you are doing. diff --git a/arch/sh/configs/ap325rxa_defconfig b/arch/sh/configs/ap325rxa_defconfig index 4d83576b89c66510161bd2243cee93f0653f39de..4464a2ad42ed0fb43c2a22813833a7bdedd71649 100644 --- a/arch/sh/configs/ap325rxa_defconfig +++ b/arch/sh/configs/ap325rxa_defconfig @@ -3,7 +3,6 @@ CONFIG_SYSVIPC=y CONFIG_BSD_PROCESS_ACCT=y CONFIG_LOG_BUF_SHIFT=14 # CONFIG_KALLSYMS is not set -CONFIG_SLAB=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y # CONFIG_BLK_DEV_BSG is not set diff --git a/arch/sh/configs/apsh4a3a_defconfig b/arch/sh/configs/apsh4a3a_defconfig index 99931a13a74da9d7e7bb7066a163e4a28c6ea637..cc909f3478776958b2afae4bf91ab770e7de1c93 100644 --- a/arch/sh/configs/apsh4a3a_defconfig +++ b/arch/sh/configs/apsh4a3a_defconfig @@ -6,7 +6,6 @@ CONFIG_LOG_BUF_SHIFT=14 CONFIG_SYSFS_DEPRECATED=y CONFIG_SYSFS_DEPRECATED_V2=y CONFIG_BLK_DEV_INITRD=y -CONFIG_SLAB=y CONFIG_PROFILING=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y diff --git a/arch/sh/configs/apsh4ad0a_defconfig b/arch/sh/configs/apsh4ad0a_defconfig index d9fb124bf015a21089ee28976c035609fc0eac9d..64558bf60e106a398f3f8a058197a0d97328948f 100644 --- a/arch/sh/configs/apsh4ad0a_defconfig +++ b/arch/sh/configs/apsh4ad0a_defconfig @@ -15,7 +15,6 @@ CONFIG_NAMESPACES=y CONFIG_BLK_DEV_INITRD=y CONFIG_KALLSYMS_ALL=y # CONFIG_COMPAT_BRK is not set -CONFIG_SLAB=y CONFIG_PROFILING=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y diff --git a/arch/sh/configs/dreamcast_defconfig b/arch/sh/configs/dreamcast_defconfig index 6a82c7b8ff32b88cdfbe3d003fd53625b0c8a4a5..0c9f2030bb7c9a4feb02252ba36130389442c62d 100644 --- a/arch/sh/configs/dreamcast_defconfig +++ b/arch/sh/configs/dreamcast_defconfig @@ -1,7 +1,6 @@ CONFIG_SYSVIPC=y CONFIG_BSD_PROCESS_ACCT=y CONFIG_LOG_BUF_SHIFT=14 -CONFIG_SLAB=y CONFIG_PROFILING=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y diff --git a/arch/sh/configs/ecovec24-romimage_defconfig b/arch/sh/configs/ecovec24-romimage_defconfig index 5c60e71d839e05f5ed38db250a40cbfe68f7ea10..13fec4338416ad411e8fc22f76c5be7ec608020d 100644 --- a/arch/sh/configs/ecovec24-romimage_defconfig +++ b/arch/sh/configs/ecovec24-romimage_defconfig @@ -6,7 +6,6 @@ CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=14 CONFIG_BLK_DEV_INITRD=y # CONFIG_KALLSYMS is not set -CONFIG_SLAB=y # CONFIG_BLK_DEV_BSG is not set CONFIG_CPU_SUBTYPE_SH7724=y CONFIG_MEMORY_SIZE=0x10000000 diff --git a/arch/sh/configs/ecovec24_defconfig b/arch/sh/configs/ecovec24_defconfig index 4d655e8d4d74e5d99f59192b3d05190d92b74eb9..ee1b36682155dd0e23d86b01f429c1119a538454 100644 --- a/arch/sh/configs/ecovec24_defconfig +++ b/arch/sh/configs/ecovec24_defconfig @@ -3,7 +3,6 @@ CONFIG_SYSVIPC=y CONFIG_BSD_PROCESS_ACCT=y CONFIG_LOG_BUF_SHIFT=14 # CONFIG_KALLSYMS is not set -CONFIG_SLAB=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y # CONFIG_BLK_DEV_BSG is not set diff --git a/arch/sh/configs/espt_defconfig b/arch/sh/configs/espt_defconfig index 2804cb760a76152b6d15c60336d3e079ed1c55de..623012d9af9d178ed609a912bfd64bb1eae6cf16 100644 --- a/arch/sh/configs/espt_defconfig +++ b/arch/sh/configs/espt_defconfig @@ -5,7 +5,6 @@ CONFIG_LOG_BUF_SHIFT=14 CONFIG_NAMESPACES=y CONFIG_UTS_NS=y CONFIG_IPC_NS=y -CONFIG_SLAB=y CONFIG_PROFILING=y CONFIG_MODULES=y # CONFIG_BLK_DEV_BSG is not set diff --git a/arch/sh/configs/hp6xx_defconfig b/arch/sh/configs/hp6xx_defconfig index 70e6605d7f7ef77b7c86b22d3331845be971aa9d..0c45f2a0f9bd93ef1e7ddb2af7645a33ec1a17b3 100644 --- a/arch/sh/configs/hp6xx_defconfig +++ b/arch/sh/configs/hp6xx_defconfig @@ -3,7 +3,6 @@ CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=14 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set -CONFIG_SLAB=y # CONFIG_BLK_DEV_BSG is not set CONFIG_CPU_SUBTYPE_SH7709=y CONFIG_MEMORY_START=0x0d000000 diff --git a/arch/sh/configs/kfr2r09-romimage_defconfig b/arch/sh/configs/kfr2r09-romimage_defconfig index 04436b4fbd7695f0f84fd3bb1588b220fce3b80c..42bf34181a3e095857d25435b9f77c9450ac5bb0 100644 --- a/arch/sh/configs/kfr2r09-romimage_defconfig +++ b/arch/sh/configs/kfr2r09-romimage_defconfig @@ -6,7 +6,6 @@ CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=14 CONFIG_BLK_DEV_INITRD=y # CONFIG_KALLSYMS is not set -CONFIG_SLAB=y # CONFIG_BLOCK is not set CONFIG_CPU_SUBTYPE_SH7724=y CONFIG_MEMORY_SIZE=0x08000000 diff --git a/arch/sh/configs/kfr2r09_defconfig b/arch/sh/configs/kfr2r09_defconfig index 833404490cfeea4dd18d67d1ef40e10a46bdc78e..d80e83e7ec38fe0a489b7830b702f2b02eb2508c 100644 --- a/arch/sh/configs/kfr2r09_defconfig +++ b/arch/sh/configs/kfr2r09_defconfig @@ -6,7 +6,6 @@ CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=14 CONFIG_BLK_DEV_INITRD=y # CONFIG_KALLSYMS is not set -CONFIG_SLAB=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y # CONFIG_BLK_DEV_BSG is not set diff --git a/arch/sh/configs/landisk_defconfig b/arch/sh/configs/landisk_defconfig index 7037320b654ad65b83d0df1d71c24dfc8e73ba59..54108209091874cbd12f048cc25150a51f4f3bef 100644 --- a/arch/sh/configs/landisk_defconfig +++ b/arch/sh/configs/landisk_defconfig @@ -1,7 +1,6 @@ CONFIG_SYSVIPC=y CONFIG_LOG_BUF_SHIFT=14 CONFIG_KALLSYMS_EXTRA_PASS=y -CONFIG_SLAB=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y CONFIG_MODULE_FORCE_UNLOAD=y diff --git a/arch/sh/configs/lboxre2_defconfig b/arch/sh/configs/lboxre2_defconfig index 05e4ac6fed5f9c78b951ef67c5e3527d824d645e..6a234761bfd7778e86d8bce7f9a30192d49b2f57 100644 --- a/arch/sh/configs/lboxre2_defconfig +++ b/arch/sh/configs/lboxre2_defconfig @@ -1,7 +1,6 @@ CONFIG_SYSVIPC=y CONFIG_LOG_BUF_SHIFT=14 CONFIG_KALLSYMS_EXTRA_PASS=y -CONFIG_SLAB=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y CONFIG_MODULE_FORCE_UNLOAD=y diff --git a/arch/sh/configs/magicpanelr2_defconfig b/arch/sh/configs/magicpanelr2_defconfig index ef1d98e35c91f7dc93f0b25a9d3bf62517cb3d47..52937f9cc2ab310bff2c191813cb4fe5ee7bca39 100644 --- a/arch/sh/configs/magicpanelr2_defconfig +++ b/arch/sh/configs/magicpanelr2_defconfig @@ -8,7 +8,6 @@ CONFIG_RELAY=y CONFIG_BLK_DEV_INITRD=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set CONFIG_KALLSYMS_ALL=y -CONFIG_SLAB=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y CONFIG_MODVERSIONS=y diff --git a/arch/sh/configs/microdev_defconfig b/arch/sh/configs/microdev_defconfig index e9825196dd66affa5f6ff86f8e789a9bf9dff687..39a83d832cac6aa17f7a2c8b7b6eb0edbe43a216 100644 --- a/arch/sh/configs/microdev_defconfig +++ b/arch/sh/configs/microdev_defconfig @@ -2,7 +2,6 @@ CONFIG_BSD_PROCESS_ACCT=y CONFIG_LOG_BUF_SHIFT=14 CONFIG_BLK_DEV_INITRD=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set -CONFIG_SLAB=y # CONFIG_BLK_DEV_BSG is not set CONFIG_CPU_SUBTYPE_SH4_202=y CONFIG_FLATMEM_MANUAL=y diff --git a/arch/sh/configs/migor_defconfig b/arch/sh/configs/migor_defconfig index 4859cd30cfc4c666e3d446c76055a426c5333de4..2d1e65cad2398a919c5c95911bfcf51e7904ca19 100644 --- a/arch/sh/configs/migor_defconfig +++ b/arch/sh/configs/migor_defconfig @@ -4,7 +4,6 @@ CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=14 CONFIG_BLK_DEV_INITRD=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set -CONFIG_SLAB=y CONFIG_PROFILING=y CONFIG_MODULES=y # CONFIG_BLK_DEV_BSG is not set diff --git a/arch/sh/configs/polaris_defconfig b/arch/sh/configs/polaris_defconfig index f42e4867ddc1a7e5f9b92cfcf2ea4121ff5d1f46..4f0396c2ac79068ab03a1b50d64c5dc9723daae0 100644 --- a/arch/sh/configs/polaris_defconfig +++ b/arch/sh/configs/polaris_defconfig @@ -7,7 +7,6 @@ CONFIG_BSD_PROCESS_ACCT_V3=y CONFIG_AUDIT=y CONFIG_LOG_BUF_SHIFT=14 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set -CONFIG_SLAB=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y CONFIG_MODVERSIONS=y diff --git a/arch/sh/configs/r7780mp_defconfig b/arch/sh/configs/r7780mp_defconfig index e527cd60a1910531dcbde65ca62e255dd53a778f..6bd6c0ae85d7c998fc6cdceca74f36c9b56f7b01 100644 --- a/arch/sh/configs/r7780mp_defconfig +++ b/arch/sh/configs/r7780mp_defconfig @@ -5,7 +5,6 @@ CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=14 # CONFIG_FUTEX is not set # CONFIG_EPOLL is not set -CONFIG_SLAB=y CONFIG_PROFILING=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y diff --git a/arch/sh/configs/r7785rp_defconfig b/arch/sh/configs/r7785rp_defconfig index a3f952a83d970f810d242678291e9bb647f9f115..cde668569cc1dd3418082eba4c49ba7691a17fb9 100644 --- a/arch/sh/configs/r7785rp_defconfig +++ b/arch/sh/configs/r7785rp_defconfig @@ -7,7 +7,6 @@ CONFIG_RCU_TRACE=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=14 -CONFIG_SLAB=y CONFIG_PROFILING=y CONFIG_KPROBES=y CONFIG_MODULES=y diff --git a/arch/sh/configs/rsk7264_defconfig b/arch/sh/configs/rsk7264_defconfig index f7b9c528c6df87489a70e65b6916084d7f953e96..de9e350cdf288adb67cdb662b09c9f4bd9e0d085 100644 --- a/arch/sh/configs/rsk7264_defconfig +++ b/arch/sh/configs/rsk7264_defconfig @@ -12,7 +12,6 @@ CONFIG_KALLSYMS_ALL=y CONFIG_EMBEDDED=y CONFIG_PERF_COUNTERS=y # CONFIG_VM_EVENT_COUNTERS is not set -CONFIG_SLAB=y CONFIG_MMAP_ALLOW_UNINITIALIZED=y CONFIG_PROFILING=y # CONFIG_BLK_DEV_BSG is not set diff --git a/arch/sh/configs/rsk7269_defconfig b/arch/sh/configs/rsk7269_defconfig index 4bff14fb185dbb4e20b0e97129fa0720409b478a..7ca6a5c25a9ff0d5740a6629384d70c2f6bca3cd 100644 --- a/arch/sh/configs/rsk7269_defconfig +++ b/arch/sh/configs/rsk7269_defconfig @@ -2,7 +2,6 @@ CONFIG_LOG_BUF_SHIFT=14 CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_EMBEDDED=y # CONFIG_VM_EVENT_COUNTERS is not set -CONFIG_SLAB=y # CONFIG_BLK_DEV_BSG is not set CONFIG_SWAP_IO_SPACE=y CONFIG_CPU_SUBTYPE_SH7269=y diff --git a/arch/sh/configs/rts7751r2d1_defconfig b/arch/sh/configs/rts7751r2d1_defconfig index 96263a4912b726f7f880b8fc5a43c8cdf09091a0..c863a11c75920706e2d81204c028fd799d6db321 100644 --- a/arch/sh/configs/rts7751r2d1_defconfig +++ b/arch/sh/configs/rts7751r2d1_defconfig @@ -1,7 +1,6 @@ CONFIG_SYSVIPC=y CONFIG_LOG_BUF_SHIFT=14 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set -CONFIG_SLAB=y CONFIG_PROFILING=y CONFIG_MODULES=y # CONFIG_BLK_DEV_BSG is not set diff --git a/arch/sh/configs/rts7751r2dplus_defconfig b/arch/sh/configs/rts7751r2dplus_defconfig index 92e586e6c97432aedf230ba4cbb41012dff3ea75..7e4f710d46c7373b81e809efb4c28504659daea0 100644 --- a/arch/sh/configs/rts7751r2dplus_defconfig +++ b/arch/sh/configs/rts7751r2dplus_defconfig @@ -1,7 +1,6 @@ CONFIG_SYSVIPC=y CONFIG_LOG_BUF_SHIFT=14 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set -CONFIG_SLAB=y CONFIG_PROFILING=y CONFIG_MODULES=y # CONFIG_BLK_DEV_BSG is not set diff --git a/arch/sh/configs/sdk7786_defconfig b/arch/sh/configs/sdk7786_defconfig index 97b7356639ed82fbca6a8677a46ab3b8589d8ad4..a080c5d05a7b7b726f9adeed0a99e0244c7dfa94 100644 --- a/arch/sh/configs/sdk7786_defconfig +++ b/arch/sh/configs/sdk7786_defconfig @@ -31,7 +31,6 @@ CONFIG_RD_BZIP2=y CONFIG_RD_LZMA=y CONFIG_RD_LZO=y # CONFIG_COMPAT_BRK is not set -CONFIG_SLAB=y CONFIG_PROFILING=y CONFIG_KPROBES=y CONFIG_MODULES=y diff --git a/arch/sh/configs/se7343_defconfig b/arch/sh/configs/se7343_defconfig index 5d6c19338ebf2992f4c3405e42731a8a0d9153db..75db12fb9ad177261651a420a8e5f0214e89ed4e 100644 --- a/arch/sh/configs/se7343_defconfig +++ b/arch/sh/configs/se7343_defconfig @@ -5,7 +5,6 @@ CONFIG_LOG_BUF_SHIFT=14 # CONFIG_FUTEX is not set # CONFIG_EPOLL is not set # CONFIG_SHMEM is not set -CONFIG_SLAB=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y CONFIG_MODULE_FORCE_UNLOAD=y diff --git a/arch/sh/configs/se7619_defconfig b/arch/sh/configs/se7619_defconfig index 71a672c307168ecfb64346d514251f16dcd3259f..14d0f5ead502f443f451985848d80838d97e736f 100644 --- a/arch/sh/configs/se7619_defconfig +++ b/arch/sh/configs/se7619_defconfig @@ -8,7 +8,6 @@ CONFIG_LOG_BUF_SHIFT=14 # CONFIG_FUTEX is not set # CONFIG_EPOLL is not set # CONFIG_VM_EVENT_COUNTERS is not set -CONFIG_SLAB=y # CONFIG_BLK_DEV_BSG is not set CONFIG_MEMORY_START=0x0c000000 CONFIG_FLATMEM_MANUAL=y diff --git a/arch/sh/configs/se7705_defconfig b/arch/sh/configs/se7705_defconfig index ed00a6eeadf55e31f258bd3f6d0faf09743bf3b9..16a0f72f082260a9cbca14d648987fa7f2ad36ac 100644 --- a/arch/sh/configs/se7705_defconfig +++ b/arch/sh/configs/se7705_defconfig @@ -4,7 +4,6 @@ CONFIG_BLK_DEV_INITRD=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set # CONFIG_KALLSYMS is not set # CONFIG_HOTPLUG is not set -CONFIG_SLAB=y CONFIG_MODULES=y # CONFIG_BLK_DEV_BSG is not set CONFIG_CPU_SUBTYPE_SH7705=y diff --git a/arch/sh/configs/se7712_defconfig b/arch/sh/configs/se7712_defconfig index 36356223d51c837d24bf3a857b7a2e705c672100..dc854293da43569538073043ff3b31b4fa826c3a 100644 --- a/arch/sh/configs/se7712_defconfig +++ b/arch/sh/configs/se7712_defconfig @@ -9,7 +9,6 @@ CONFIG_KALLSYMS_ALL=y # CONFIG_BUG is not set # CONFIG_BASE_FULL is not set # CONFIG_SHMEM is not set -CONFIG_SLAB=y CONFIG_MODULES=y # CONFIG_BLK_DEV_BSG is not set CONFIG_CPU_SUBTYPE_SH7712=y diff --git a/arch/sh/configs/se7721_defconfig b/arch/sh/configs/se7721_defconfig index 46c5a263a239255b1fc11e5d92aaa3794293c1ab..c891945b8a900e0c34f9bbd48658dc339611600b 100644 --- a/arch/sh/configs/se7721_defconfig +++ b/arch/sh/configs/se7721_defconfig @@ -9,7 +9,6 @@ CONFIG_KALLSYMS_ALL=y # CONFIG_BUG is not set # CONFIG_BASE_FULL is not set # CONFIG_SHMEM is not set -CONFIG_SLAB=y CONFIG_MODULES=y # CONFIG_BLK_DEV_BSG is not set CONFIG_CPU_SUBTYPE_SH7721=y diff --git a/arch/sh/configs/se7724_defconfig b/arch/sh/configs/se7724_defconfig index d817df7cc4a72aee63609b4b3c5e4ff481a32337..96521271758c9db42642ebd3822d71fc7e2359b7 100644 --- a/arch/sh/configs/se7724_defconfig +++ b/arch/sh/configs/se7724_defconfig @@ -3,7 +3,6 @@ CONFIG_SYSVIPC=y CONFIG_BSD_PROCESS_ACCT=y CONFIG_LOG_BUF_SHIFT=14 # CONFIG_KALLSYMS is not set -CONFIG_SLAB=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y # CONFIG_BLK_DEV_BSG is not set diff --git a/arch/sh/configs/se7750_defconfig b/arch/sh/configs/se7750_defconfig index 4defc7628a498a32703113f27684954d4d6a965e..5fa6239ae4eae4200b5b532abdc12a11df5ce03c 100644 --- a/arch/sh/configs/se7750_defconfig +++ b/arch/sh/configs/se7750_defconfig @@ -6,7 +6,6 @@ CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=14 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set # CONFIG_HOTPLUG is not set -CONFIG_SLAB=y CONFIG_MODULES=y # CONFIG_BLK_DEV_BSG is not set CONFIG_CPU_SUBTYPE_SH7750=y diff --git a/arch/sh/configs/se7751_defconfig b/arch/sh/configs/se7751_defconfig index 4a024065bb7501affe151890ca07afcbace49deb..8b5fe4ec16bc28e78df4c914dbb2e8b2e4d40c99 100644 --- a/arch/sh/configs/se7751_defconfig +++ b/arch/sh/configs/se7751_defconfig @@ -4,7 +4,6 @@ CONFIG_LOG_BUF_SHIFT=14 CONFIG_BLK_DEV_INITRD=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set # CONFIG_HOTPLUG is not set -CONFIG_SLAB=y CONFIG_MODULES=y # CONFIG_BLK_DEV_BSG is not set CONFIG_CPU_SUBTYPE_SH7751=y diff --git a/arch/sh/configs/se7780_defconfig b/arch/sh/configs/se7780_defconfig index dcd85b858ac8ca4fd501d1aebe1095a56179f0ff..21303304eda28b33f9be897ec6c6c1acf0f9ab73 100644 --- a/arch/sh/configs/se7780_defconfig +++ b/arch/sh/configs/se7780_defconfig @@ -6,7 +6,6 @@ CONFIG_LOG_BUF_SHIFT=14 # CONFIG_KALLSYMS is not set # CONFIG_HOTPLUG is not set # CONFIG_EPOLL is not set -CONFIG_SLAB=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y CONFIG_CPU_SUBTYPE_SH7780=y diff --git a/arch/sh/configs/secureedge5410_defconfig b/arch/sh/configs/secureedge5410_defconfig index 8422599cfb04dc1144dffa5869fd6c6e7789228e..120176afe3f6f5a747a7bcd39598656bd0cbc0a4 100644 --- a/arch/sh/configs/secureedge5410_defconfig +++ b/arch/sh/configs/secureedge5410_defconfig @@ -2,7 +2,6 @@ CONFIG_LOG_BUF_SHIFT=14 CONFIG_BLK_DEV_INITRD=y # CONFIG_HOTPLUG is not set -CONFIG_SLAB=y # CONFIG_BLK_DEV_BSG is not set CONFIG_CPU_SUBTYPE_SH7751R=y CONFIG_MEMORY_SIZE=0x01000000 diff --git a/arch/sh/configs/sh03_defconfig b/arch/sh/configs/sh03_defconfig index 9fcf68b22dba9afa3cca335622b3c8591c1532cb..f661ef816f09cc69e29fd7cef28e740e6bd48e96 100644 --- a/arch/sh/configs/sh03_defconfig +++ b/arch/sh/configs/sh03_defconfig @@ -3,7 +3,6 @@ CONFIG_POSIX_MQUEUE=y CONFIG_BSD_PROCESS_ACCT=y CONFIG_LOG_BUF_SHIFT=14 CONFIG_BLK_DEV_INITRD=y -CONFIG_SLAB=y CONFIG_PROFILING=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y diff --git a/arch/sh/configs/sh2007_defconfig b/arch/sh/configs/sh2007_defconfig index 259c69e3fa22796c9651d982255057bff3ffea6a..977ae405a75e75657a255ebdeb87221631082d79 100644 --- a/arch/sh/configs/sh2007_defconfig +++ b/arch/sh/configs/sh2007_defconfig @@ -8,7 +8,6 @@ CONFIG_IKCONFIG=y CONFIG_LOG_BUF_SHIFT=14 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set CONFIG_KALLSYMS_ALL=y -CONFIG_SLAB=y # CONFIG_BLK_DEV_BSG is not set CONFIG_CPU_SUBTYPE_SH7780=y CONFIG_MEMORY_SIZE=0x08000000 diff --git a/arch/sh/configs/sh7710voipgw_defconfig b/arch/sh/configs/sh7710voipgw_defconfig index 0d814770b07fe97bc7fcb0bb30491ba8a1e829fb..7f742729df697dc0f162ef2c3f17e08c1a083218 100644 --- a/arch/sh/configs/sh7710voipgw_defconfig +++ b/arch/sh/configs/sh7710voipgw_defconfig @@ -5,7 +5,6 @@ CONFIG_LOG_BUF_SHIFT=14 # CONFIG_FUTEX is not set # CONFIG_EPOLL is not set # CONFIG_SHMEM is not set -CONFIG_SLAB=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y CONFIG_MODULE_FORCE_UNLOAD=y diff --git a/arch/sh/configs/sh7757lcr_defconfig b/arch/sh/configs/sh7757lcr_defconfig index 2579dc4bc0c8f6f963dfedd625bc4bf3224a0c94..48a0f9beb116e1dc0a5417605d6ed2bf4eaea9ee 100644 --- a/arch/sh/configs/sh7757lcr_defconfig +++ b/arch/sh/configs/sh7757lcr_defconfig @@ -9,7 +9,6 @@ CONFIG_TASK_IO_ACCOUNTING=y CONFIG_LOG_BUF_SHIFT=14 CONFIG_BLK_DEV_INITRD=y CONFIG_KALLSYMS_ALL=y -CONFIG_SLAB=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y # CONFIG_BLK_DEV_BSG is not set diff --git a/arch/sh/configs/sh7763rdp_defconfig b/arch/sh/configs/sh7763rdp_defconfig index 8a6a446f9eb88a6f2e08d3aab4c6f5fa44c18847..ae726745d9a015a550a9fcc9b783bec53ef04747 100644 --- a/arch/sh/configs/sh7763rdp_defconfig +++ b/arch/sh/configs/sh7763rdp_defconfig @@ -5,7 +5,6 @@ CONFIG_LOG_BUF_SHIFT=14 CONFIG_NAMESPACES=y CONFIG_UTS_NS=y CONFIG_IPC_NS=y -CONFIG_SLAB=y CONFIG_PROFILING=y CONFIG_MODULES=y # CONFIG_BLK_DEV_BSG is not set diff --git a/arch/sh/configs/sh7785lcr_32bit_defconfig b/arch/sh/configs/sh7785lcr_32bit_defconfig index 781ff13227fc99dfb47410f7addabce9b85e43bc..59262f42abe6f80d669d9e8a6ac9b5785cdb625f 100644 --- a/arch/sh/configs/sh7785lcr_32bit_defconfig +++ b/arch/sh/configs/sh7785lcr_32bit_defconfig @@ -6,7 +6,6 @@ CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=16 CONFIG_PERF_EVENTS=y # CONFIG_COMPAT_BRK is not set -CONFIG_SLAB=y CONFIG_PROFILING=y CONFIG_GCOV_KERNEL=y CONFIG_MODULES=y diff --git a/arch/sh/configs/sh7785lcr_defconfig b/arch/sh/configs/sh7785lcr_defconfig index 1b88929083f786fd40e6f13afdcababea761074f..94381f8268fffc7b79e42b9ba6bd08aa6131883f 100644 --- a/arch/sh/configs/sh7785lcr_defconfig +++ b/arch/sh/configs/sh7785lcr_defconfig @@ -3,7 +3,6 @@ CONFIG_BSD_PROCESS_ACCT=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=14 -CONFIG_SLAB=y CONFIG_PROFILING=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y diff --git a/arch/sh/configs/titan_defconfig b/arch/sh/configs/titan_defconfig index 73a0d68b0de6ce6bd8092f68d8edc6da73382f25..871092753591a045da2f29bd1f7f535bba817747 100644 --- a/arch/sh/configs/titan_defconfig +++ b/arch/sh/configs/titan_defconfig @@ -6,7 +6,6 @@ CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=16 CONFIG_BLK_DEV_INITRD=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set -CONFIG_SLAB=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y CONFIG_MODULE_FORCE_UNLOAD=y diff --git a/arch/sh/configs/urquell_defconfig b/arch/sh/configs/urquell_defconfig index 8fc687c98fd195e8dd6c3845789772dd88020b5f..445bb451a5ec8076c694fc3234908977621d07ff 100644 --- a/arch/sh/configs/urquell_defconfig +++ b/arch/sh/configs/urquell_defconfig @@ -17,7 +17,6 @@ CONFIG_CGROUP_MEMCG=y CONFIG_CGROUP_SCHED=y CONFIG_RT_GROUP_SCHED=y CONFIG_BLK_DEV_INITRD=y -CONFIG_SLAB=y CONFIG_PROFILING=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y diff --git a/arch/sh/drivers/dma/Kconfig b/arch/sh/drivers/dma/Kconfig index 7d54f284ce10fb10f3c5d30b34775f9a3288a84f..08d937a6d249a60353a5a1414ea493d4d6858cc9 100644 --- a/arch/sh/drivers/dma/Kconfig +++ b/arch/sh/drivers/dma/Kconfig @@ -28,17 +28,19 @@ config SH_DMA_API config NR_ONCHIP_DMA_CHANNELS int depends on SH_DMA - default "4" if CPU_SUBTYPE_SH7750 || CPU_SUBTYPE_SH7751 || \ - CPU_SUBTYPE_SH7750S || CPU_SUBTYPE_SH7091 + default "4" if CPU_SUBTYPE_SH7709 || CPU_SUBTYPE_SH7750 || \ + CPU_SUBTYPE_SH7750S || CPU_SUBTYPE_SH7751 || \ + CPU_SUBTYPE_SH7091 default "8" if CPU_SUBTYPE_SH7750R || CPU_SUBTYPE_SH7751R || \ CPU_SUBTYPE_SH7760 - default "12" if CPU_SUBTYPE_SH7723 || CPU_SUBTYPE_SH7780 || \ - CPU_SUBTYPE_SH7785 || CPU_SUBTYPE_SH7724 + default "12" if CPU_SUBTYPE_SH7723 || CPU_SUBTYPE_SH7724 || \ + CPU_SUBTYPE_SH7780 || CPU_SUBTYPE_SH7785 default "6" help This allows you to specify the number of channels that the on-chip - DMAC supports. This will be 4 for SH7750/SH7751/Sh7750S/SH7091 and 8 for the - SH7750R/SH7751R/SH7760, 12 for the SH7723/SH7780/SH7785/SH7724, default is 6. + DMAC supports. This will be 4 for SH7709/SH7750/SH7750S/SH7751/SH7091, + 8 for SH7750R/SH7751R/SH7760, and 12 for SH7723/SH7724/SH7780/SH7785. + Default is 6. config SH_DMABRG bool "SH7760 DMABRG support" diff --git a/arch/sh/drivers/dma/dma-api.c b/arch/sh/drivers/dma/dma-api.c index ab9170494dcc29e0a8b64ed991cd8010d3c3e694..89cd4a3b4ccafbe27e1d766ccfefc59e5f6bed84 100644 --- a/arch/sh/drivers/dma/dma-api.c +++ b/arch/sh/drivers/dma/dma-api.c @@ -198,7 +198,7 @@ int request_dma(unsigned int chan, const char *dev_id) if (atomic_xchg(&channel->busy, 1)) return -EBUSY; - strlcpy(channel->dev_id, dev_id, sizeof(channel->dev_id)); + strscpy(channel->dev_id, dev_id, sizeof(channel->dev_id)); if (info->ops->request) { result = info->ops->request(channel); diff --git a/arch/sh/drivers/dma/dma-sh.c b/arch/sh/drivers/dma/dma-sh.c index 96c626c2cd0a496487eb3c6f660497cd0a5d3281..306fba1564e5e6fd37fa1016a6b6bd998baa2dec 100644 --- a/arch/sh/drivers/dma/dma-sh.c +++ b/arch/sh/drivers/dma/dma-sh.c @@ -18,6 +18,18 @@ #include #include +/* + * Some of the SoCs feature two DMAC modules. In such a case, the channels are + * distributed equally among them. + */ +#ifdef SH_DMAC_BASE1 +#define SH_DMAC_NR_MD_CH (CONFIG_NR_ONCHIP_DMA_CHANNELS / 2) +#else +#define SH_DMAC_NR_MD_CH CONFIG_NR_ONCHIP_DMA_CHANNELS +#endif + +#define SH_DMAC_CH_SZ 0x10 + /* * Define the default configuration for dual address memory-memory transfer. * The 0x400 value represents auto-request, external->external. @@ -29,7 +41,7 @@ static unsigned long dma_find_base(unsigned int chan) unsigned long base = SH_DMAC_BASE0; #ifdef SH_DMAC_BASE1 - if (chan >= 6) + if (chan >= SH_DMAC_NR_MD_CH) base = SH_DMAC_BASE1; #endif @@ -40,13 +52,13 @@ static unsigned long dma_base_addr(unsigned int chan) { unsigned long base = dma_find_base(chan); - /* Normalize offset calculation */ - if (chan >= 9) - chan -= 6; - if (chan >= 4) - base += 0x10; + chan = (chan % SH_DMAC_NR_MD_CH) * SH_DMAC_CH_SZ; + + /* DMAOR is placed inside the channel register space. Step over it. */ + if (chan >= DMAOR) + base += SH_DMAC_CH_SZ; - return base + (chan * 0x10); + return base + chan; } #ifdef CONFIG_SH_DMA_IRQ_MULTI @@ -250,12 +262,11 @@ static int sh_dmac_get_dma_residue(struct dma_channel *chan) #define NR_DMAOR 1 #endif -/* - * DMAOR bases are broken out amongst channel groups. DMAOR0 manages - * channels 0 - 5, DMAOR1 6 - 11 (optional). - */ -#define dmaor_read_reg(n) __raw_readw(dma_find_base((n)*6)) -#define dmaor_write_reg(n, data) __raw_writew(data, dma_find_base(n)*6) +#define dmaor_read_reg(n) __raw_readw(dma_find_base((n) * \ + SH_DMAC_NR_MD_CH) + DMAOR) +#define dmaor_write_reg(n, data) __raw_writew(data, \ + dma_find_base((n) * \ + SH_DMAC_NR_MD_CH) + DMAOR) static inline int dmaor_reset(int no) { diff --git a/arch/sh/include/asm/atomic-grb.h b/arch/sh/include/asm/atomic-grb.h index 059791fd394fc40d234a6555022e607a15b674d1..cf1c10f15528bfa36e19a804cc9b96ce3edd31aa 100644 --- a/arch/sh/include/asm/atomic-grb.h +++ b/arch/sh/include/asm/atomic-grb.h @@ -71,6 +71,11 @@ static inline int arch_atomic_fetch_##op(int i, atomic_t *v) \ ATOMIC_OPS(add) ATOMIC_OPS(sub) +#define arch_atomic_add_return arch_atomic_add_return +#define arch_atomic_sub_return arch_atomic_sub_return +#define arch_atomic_fetch_add arch_atomic_fetch_add +#define arch_atomic_fetch_sub arch_atomic_fetch_sub + #undef ATOMIC_OPS #define ATOMIC_OPS(op) ATOMIC_OP(op) ATOMIC_FETCH_OP(op) @@ -78,6 +83,10 @@ ATOMIC_OPS(and) ATOMIC_OPS(or) ATOMIC_OPS(xor) +#define arch_atomic_fetch_and arch_atomic_fetch_and +#define arch_atomic_fetch_or arch_atomic_fetch_or +#define arch_atomic_fetch_xor arch_atomic_fetch_xor + #undef ATOMIC_OPS #undef ATOMIC_FETCH_OP #undef ATOMIC_OP_RETURN diff --git a/arch/sh/include/asm/atomic-irq.h b/arch/sh/include/asm/atomic-irq.h index 7665de9d00d0d1977bb53a4bcec9c6d2819eb744..b4090cc354935ab3dd6eef7ca341b50235955637 100644 --- a/arch/sh/include/asm/atomic-irq.h +++ b/arch/sh/include/asm/atomic-irq.h @@ -55,6 +55,11 @@ static inline int arch_atomic_fetch_##op(int i, atomic_t *v) \ ATOMIC_OPS(add, +=) ATOMIC_OPS(sub, -=) +#define arch_atomic_add_return arch_atomic_add_return +#define arch_atomic_sub_return arch_atomic_sub_return +#define arch_atomic_fetch_add arch_atomic_fetch_add +#define arch_atomic_fetch_sub arch_atomic_fetch_sub + #undef ATOMIC_OPS #define ATOMIC_OPS(op, c_op) \ ATOMIC_OP(op, c_op) \ @@ -64,6 +69,10 @@ ATOMIC_OPS(and, &=) ATOMIC_OPS(or, |=) ATOMIC_OPS(xor, ^=) +#define arch_atomic_fetch_and arch_atomic_fetch_and +#define arch_atomic_fetch_or arch_atomic_fetch_or +#define arch_atomic_fetch_xor arch_atomic_fetch_xor + #undef ATOMIC_OPS #undef ATOMIC_FETCH_OP #undef ATOMIC_OP_RETURN diff --git a/arch/sh/include/asm/atomic-llsc.h b/arch/sh/include/asm/atomic-llsc.h index b63dcfbfa14ef534ef0e9da833ff092b68f45a45..9ef1fb1dd12ee7b9365568432f2a96293d848fdb 100644 --- a/arch/sh/include/asm/atomic-llsc.h +++ b/arch/sh/include/asm/atomic-llsc.h @@ -73,6 +73,11 @@ static inline int arch_atomic_fetch_##op(int i, atomic_t *v) \ ATOMIC_OPS(add) ATOMIC_OPS(sub) +#define arch_atomic_add_return arch_atomic_add_return +#define arch_atomic_sub_return arch_atomic_sub_return +#define arch_atomic_fetch_add arch_atomic_fetch_add +#define arch_atomic_fetch_sub arch_atomic_fetch_sub + #undef ATOMIC_OPS #define ATOMIC_OPS(op) ATOMIC_OP(op) ATOMIC_FETCH_OP(op) @@ -80,6 +85,10 @@ ATOMIC_OPS(and) ATOMIC_OPS(or) ATOMIC_OPS(xor) +#define arch_atomic_fetch_and arch_atomic_fetch_and +#define arch_atomic_fetch_or arch_atomic_fetch_or +#define arch_atomic_fetch_xor arch_atomic_fetch_xor + #undef ATOMIC_OPS #undef ATOMIC_FETCH_OP #undef ATOMIC_OP_RETURN diff --git a/arch/sh/include/asm/atomic.h b/arch/sh/include/asm/atomic.h index 528bfeda78f56933160785f051671456b961108c..7a18cb2a1c1ac642d3f0bf714458cb055f119dd1 100644 --- a/arch/sh/include/asm/atomic.h +++ b/arch/sh/include/asm/atomic.h @@ -30,9 +30,6 @@ #include #endif -#define arch_atomic_xchg(v, new) (arch_xchg(&((v)->counter), new)) -#define arch_atomic_cmpxchg(v, o, n) (arch_cmpxchg(&((v)->counter), (o), (n))) - #endif /* CONFIG_CPU_J2 */ #endif /* __ASM_SH_ATOMIC_H */ diff --git a/arch/sh/include/asm/bugs.h b/arch/sh/include/asm/bugs.h deleted file mode 100644 index fe52abb69cea319374554322ddfd57376f900a97..0000000000000000000000000000000000000000 --- a/arch/sh/include/asm/bugs.h +++ /dev/null @@ -1,74 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef __ASM_SH_BUGS_H -#define __ASM_SH_BUGS_H - -/* - * This is included by init/main.c to check for architecture-dependent bugs. - * - * Needs: - * void check_bugs(void); - */ - -/* - * I don't know of any Super-H bugs yet. - */ - -#include - -extern void select_idle_routine(void); - -static void __init check_bugs(void) -{ - extern unsigned long loops_per_jiffy; - char *p = &init_utsname()->machine[2]; /* "sh" */ - - select_idle_routine(); - - current_cpu_data.loops_per_jiffy = loops_per_jiffy; - - switch (current_cpu_data.family) { - case CPU_FAMILY_SH2: - *p++ = '2'; - break; - case CPU_FAMILY_SH2A: - *p++ = '2'; - *p++ = 'a'; - break; - case CPU_FAMILY_SH3: - *p++ = '3'; - break; - case CPU_FAMILY_SH4: - *p++ = '4'; - break; - case CPU_FAMILY_SH4A: - *p++ = '4'; - *p++ = 'a'; - break; - case CPU_FAMILY_SH4AL_DSP: - *p++ = '4'; - *p++ = 'a'; - *p++ = 'l'; - *p++ = '-'; - *p++ = 'd'; - *p++ = 's'; - *p++ = 'p'; - break; - case CPU_FAMILY_UNKNOWN: - /* - * Specifically use CPU_FAMILY_UNKNOWN rather than - * default:, so we're able to have the compiler whine - * about unhandled enumerations. - */ - break; - } - - printk("CPU: %s\n", get_cpu_subtype(¤t_cpu_data)); - -#ifndef __LITTLE_ENDIAN__ - /* 'eb' means 'Endian Big' */ - *p++ = 'e'; - *p++ = 'b'; -#endif - *p = '\0'; -} -#endif /* __ASM_SH_BUGS_H */ diff --git a/arch/sh/include/asm/cache.h b/arch/sh/include/asm/cache.h index 32dfa6b82ec663b992fe960e15e8133ac9ddd933..b38dbc9755811c221d6a435b8e6e5a89935da85f 100644 --- a/arch/sh/include/asm/cache.h +++ b/arch/sh/include/asm/cache.h @@ -14,6 +14,12 @@ #define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT) +/* + * Some drivers need to perform DMA into kmalloc'ed buffers + * and so we have to increase the kmalloc minalign for this. + */ +#define ARCH_DMA_MINALIGN L1_CACHE_BYTES + #define __read_mostly __section(".data..read_mostly") #ifndef __ASSEMBLY__ diff --git a/arch/sh/include/asm/hd64461.h b/arch/sh/include/asm/hd64461.h index afb24cb034b114c91bb633f280b52880b988d3dd..d2c485fa333b5180a7b76a291e8e70a83bfa2231 100644 --- a/arch/sh/include/asm/hd64461.h +++ b/arch/sh/include/asm/hd64461.h @@ -229,7 +229,7 @@ #define HD64461_NIMR HD64461_IO_OFFSET(0x5002) #define HD64461_IRQBASE OFFCHIP_IRQ_BASE -#define OFFCHIP_IRQ_BASE 64 +#define OFFCHIP_IRQ_BASE (64 + 16) #define HD64461_IRQ_NUM 16 #define HD64461_IRQ_UART (HD64461_IRQBASE+5) diff --git a/arch/sh/include/asm/io.h b/arch/sh/include/asm/io.h index fba90e670ed41d4821a45edeac6649936d85419e..d8f3537ef57f9ed90bb5c6b90989e6c6d6e7e061 100644 --- a/arch/sh/include/asm/io.h +++ b/arch/sh/include/asm/io.h @@ -286,6 +286,7 @@ static inline void iounmap(volatile void __iomem *addr) { } * access */ #define xlate_dev_mem_ptr(p) __va(p) +#define unxlate_dev_mem_ptr(p, v) do { } while (0) #define ARCH_HAS_VALID_PHYS_ADDR_RANGE int valid_phys_addr_range(phys_addr_t addr, size_t size); diff --git a/arch/sh/include/asm/irq.h b/arch/sh/include/asm/irq.h index 1c4923502fd4c1b69bb115de8121d3731a2ce641..0f384b1f45cafa50703ab0586ee205cacd197c8c 100644 --- a/arch/sh/include/asm/irq.h +++ b/arch/sh/include/asm/irq.h @@ -22,7 +22,6 @@ extern unsigned short *irq_mask_register; /* * PINT IRQs */ -void init_IRQ_pint(void); void make_imask_irq(unsigned int irq); static inline int generic_irq_demux(int irq) diff --git a/arch/sh/include/asm/page.h b/arch/sh/include/asm/page.h index 09ac6c7faee0fffbcd133fbed6521a64abbd3c75..62f4b9edcb985a3a1ce1b8c572a5763bccd312c3 100644 --- a/arch/sh/include/asm/page.h +++ b/arch/sh/include/asm/page.h @@ -174,10 +174,4 @@ typedef struct page *pgtable_t; #include #include -/* - * Some drivers need to perform DMA into kmalloc'ed buffers - * and so we have to increase the kmalloc minalign for this. - */ -#define ARCH_DMA_MINALIGN L1_CACHE_BYTES - #endif /* __ASM_SH_PAGE_H */ diff --git a/arch/sh/include/asm/processor.h b/arch/sh/include/asm/processor.h index 85a6c1c3c16e70019a8ff55982ffc4bec7dbc9af..73fba7c922f929646a88c439bd827101738b6b94 100644 --- a/arch/sh/include/asm/processor.h +++ b/arch/sh/include/asm/processor.h @@ -166,6 +166,8 @@ extern unsigned int instruction_size(unsigned int insn); #define instruction_size(insn) (2) #endif +void select_idle_routine(void); + #endif /* __ASSEMBLY__ */ #include diff --git a/arch/sh/include/asm/rtc.h b/arch/sh/include/asm/rtc.h index 69dbae2949b0dd679d8fe7a47050c4962b7aaf24..7fe7002d1d509a267711447dcd39221d8b9ab988 100644 --- a/arch/sh/include/asm/rtc.h +++ b/arch/sh/include/asm/rtc.h @@ -2,8 +2,6 @@ #ifndef _ASM_RTC_H #define _ASM_RTC_H -void time_init(void); - #define RTC_CAP_4_DIGIT_YEAR (1 << 0) struct sh_rtc_platform_info { diff --git a/arch/sh/include/asm/thread_info.h b/arch/sh/include/asm/thread_info.h index 1400fbb8b423b966f6795422ab1196b3e62d8589..9f19a682d315fcf7e8fd096f15e2e24706961eac 100644 --- a/arch/sh/include/asm/thread_info.h +++ b/arch/sh/include/asm/thread_info.h @@ -84,9 +84,6 @@ static inline struct thread_info *current_thread_info(void) #define THREAD_SIZE_ORDER (THREAD_SHIFT - PAGE_SHIFT) -extern void arch_task_cache_init(void); -extern int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src); -extern void arch_release_task_struct(struct task_struct *tsk); extern void init_thread_xstate(void); #endif /* __ASSEMBLY__ */ diff --git a/arch/sh/include/cpu-sh4/cpu/dma.h b/arch/sh/include/cpu-sh4/cpu/dma.h index 38187d06b2343363ffaafd5b5d0fd0cbb24265e0..e97fb2c791778cb2aa446f25120f2d24eed801f2 100644 --- a/arch/sh/include/cpu-sh4/cpu/dma.h +++ b/arch/sh/include/cpu-sh4/cpu/dma.h @@ -13,6 +13,5 @@ #define DMAE0_IRQ evt2irq(0x6c0) #define SH_DMAC_BASE0 0xffa00000 -#define SH_DMAC_BASE1 0xffa00070 #endif /* __ASM_CPU_SH4_DMA_H */ diff --git a/arch/sh/include/mach-common/mach/highlander.h b/arch/sh/include/mach-common/mach/highlander.h index fb44c299d0337e3f454470829aa2874dbcb76e72..b12c79558422534936006cd7e187ffda31c932fa 100644 --- a/arch/sh/include/mach-common/mach/highlander.h +++ b/arch/sh/include/mach-common/mach/highlander.h @@ -176,7 +176,7 @@ #define IVDR_CK_ON 4 /* iVDR Clock ON */ #endif -#define HL_FPGA_IRQ_BASE 200 +#define HL_FPGA_IRQ_BASE (200 + 16) #define HL_NR_IRL 15 #define IRQ_AX88796 (HL_FPGA_IRQ_BASE + 0) diff --git a/arch/sh/include/mach-common/mach/r2d.h b/arch/sh/include/mach-common/mach/r2d.h index 0d7e483c7d3f5348b9cbf979ae91e248ddf427a4..69bc1907c5637071cc5baae5a6adead1ab12a9f7 100644 --- a/arch/sh/include/mach-common/mach/r2d.h +++ b/arch/sh/include/mach-common/mach/r2d.h @@ -47,7 +47,7 @@ #define IRLCNTR1 (PA_BCR + 0) /* Interrupt Control Register1 */ -#define R2D_FPGA_IRQ_BASE 100 +#define R2D_FPGA_IRQ_BASE (100 + 16) #define IRQ_VOYAGER (R2D_FPGA_IRQ_BASE + 0) #define IRQ_EXT (R2D_FPGA_IRQ_BASE + 1) diff --git a/arch/sh/include/mach-dreamcast/mach/sysasic.h b/arch/sh/include/mach-dreamcast/mach/sysasic.h index ed69ce7f20301241831117de187dbd40d37641f1..3b27be9a527ea071dbf05186fa993d181e5f9e15 100644 --- a/arch/sh/include/mach-dreamcast/mach/sysasic.h +++ b/arch/sh/include/mach-dreamcast/mach/sysasic.h @@ -22,7 +22,7 @@ takes. */ -#define HW_EVENT_IRQ_BASE 48 +#define HW_EVENT_IRQ_BASE (48 + 16) /* IRQ 13 */ #define HW_EVENT_VSYNC (HW_EVENT_IRQ_BASE + 5) /* VSync */ diff --git a/arch/sh/include/mach-se/mach/se7724.h b/arch/sh/include/mach-se/mach/se7724.h index 1fe28820dfa95373c42b46ac29e9dfc277c0be44..ea6c46633b3375ffcaf3e4acf9ce11c3a6c79c42 100644 --- a/arch/sh/include/mach-se/mach/se7724.h +++ b/arch/sh/include/mach-se/mach/se7724.h @@ -37,7 +37,7 @@ #define IRQ2_IRQ evt2irq(0x640) /* Bits in IRQ012 registers */ -#define SE7724_FPGA_IRQ_BASE 220 +#define SE7724_FPGA_IRQ_BASE (220 + 16) /* IRQ0 */ #define IRQ0_BASE SE7724_FPGA_IRQ_BASE diff --git a/arch/sh/kernel/cpu/sh2/probe.c b/arch/sh/kernel/cpu/sh2/probe.c index d342ea08843f6a6262ce0b6838451ce97b6ce520..70a07f4f2142f4e02921f3e95db5cd0c18505586 100644 --- a/arch/sh/kernel/cpu/sh2/probe.c +++ b/arch/sh/kernel/cpu/sh2/probe.c @@ -21,7 +21,7 @@ static int __init scan_cache(unsigned long node, const char *uname, if (!of_flat_dt_is_compatible(node, "jcore,cache")) return 0; - j2_ccr_base = (u32 __iomem *)of_flat_dt_translate_address(node); + j2_ccr_base = ioremap(of_flat_dt_translate_address(node), 4); return 1; } diff --git a/arch/sh/kernel/cpu/sh3/entry.S b/arch/sh/kernel/cpu/sh3/entry.S index e48b3dd996f58d6dfd9452640e16d5c5e29f8563..b1f5b3c58a018c55417fc656ae0618a9cb1f224c 100644 --- a/arch/sh/kernel/cpu/sh3/entry.S +++ b/arch/sh/kernel/cpu/sh3/entry.S @@ -470,9 +470,9 @@ ENTRY(handle_interrupt) mov r4, r0 ! save vector->jmp table offset for later shlr2 r4 ! vector to IRQ# conversion - add #-0x10, r4 - cmp/pz r4 ! is it a valid IRQ? + mov #0x10, r5 + cmp/hs r5, r4 ! is it a valid IRQ? bt 10f /* diff --git a/arch/sh/kernel/idle.c b/arch/sh/kernel/idle.c index d662503b0665da219acd3816fc8145a1d3f0a969..045d93f151fd79360046606c232d0310de17bc5d 100644 --- a/arch/sh/kernel/idle.c +++ b/arch/sh/kernel/idle.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c index af977ec4ca5e5b51ae7be1870b5a0f5fdce2a628..b3da2757faaf31a8b0287410b8f88b9b20398c4e 100644 --- a/arch/sh/kernel/setup.c +++ b/arch/sh/kernel/setup.c @@ -43,6 +43,7 @@ #include #include #include +#include #include #include @@ -304,9 +305,9 @@ void __init setup_arch(char **cmdline_p) bss_resource.end = virt_to_phys(__bss_stop)-1; #ifdef CONFIG_CMDLINE_OVERWRITE - strlcpy(command_line, CONFIG_CMDLINE, sizeof(command_line)); + strscpy(command_line, CONFIG_CMDLINE, sizeof(command_line)); #else - strlcpy(command_line, COMMAND_LINE, sizeof(command_line)); + strscpy(command_line, COMMAND_LINE, sizeof(command_line)); #ifdef CONFIG_CMDLINE_EXTEND strlcat(command_line, " ", sizeof(command_line)); strlcat(command_line, CONFIG_CMDLINE, sizeof(command_line)); @@ -354,3 +355,57 @@ int test_mode_pin(int pin) { return sh_mv.mv_mode_pins() & pin; } + +void __init arch_cpu_finalize_init(void) +{ + char *p = &init_utsname()->machine[2]; /* "sh" */ + + select_idle_routine(); + + current_cpu_data.loops_per_jiffy = loops_per_jiffy; + + switch (current_cpu_data.family) { + case CPU_FAMILY_SH2: + *p++ = '2'; + break; + case CPU_FAMILY_SH2A: + *p++ = '2'; + *p++ = 'a'; + break; + case CPU_FAMILY_SH3: + *p++ = '3'; + break; + case CPU_FAMILY_SH4: + *p++ = '4'; + break; + case CPU_FAMILY_SH4A: + *p++ = '4'; + *p++ = 'a'; + break; + case CPU_FAMILY_SH4AL_DSP: + *p++ = '4'; + *p++ = 'a'; + *p++ = 'l'; + *p++ = '-'; + *p++ = 'd'; + *p++ = 's'; + *p++ = 'p'; + break; + case CPU_FAMILY_UNKNOWN: + /* + * Specifically use CPU_FAMILY_UNKNOWN rather than + * default:, so we're able to have the compiler whine + * about unhandled enumerations. + */ + break; + } + + pr_info("CPU: %s\n", get_cpu_subtype(¤t_cpu_data)); + +#ifndef __LITTLE_ENDIAN__ + /* 'eb' means 'Endian Big' */ + *p++ = 'e'; + *p++ = 'b'; +#endif + *p = '\0'; +} diff --git a/arch/sh/kernel/syscalls/syscall.tbl b/arch/sh/kernel/syscalls/syscall.tbl index 2de85c977f54f92c0b39b8e7bd47ffde52693ff4..97377e8c50251e30dab1442c6901e9f10e1fb00f 100644 --- a/arch/sh/kernel/syscalls/syscall.tbl +++ b/arch/sh/kernel/syscalls/syscall.tbl @@ -453,3 +453,4 @@ 448 common process_mrelease sys_process_mrelease 449 common futex_waitv sys_futex_waitv 450 common set_mempolicy_home_node sys_set_mempolicy_home_node +451 common cachestat sys_cachestat diff --git a/arch/sh/mm/fault.c b/arch/sh/mm/fault.c index acd2f5e50bfcd08ccb71fc71a8f33a1c9cb84c06..06e6b49529245a58bce87aef5caaeb0e5051357d 100644 --- a/arch/sh/mm/fault.c +++ b/arch/sh/mm/fault.c @@ -439,21 +439,9 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs, } retry: - mmap_read_lock(mm); - - vma = find_vma(mm, address); + vma = lock_mm_and_find_vma(mm, address, regs); if (unlikely(!vma)) { - bad_area(regs, error_code, address); - return; - } - if (likely(vma->vm_start <= address)) - goto good_area; - if (unlikely(!(vma->vm_flags & VM_GROWSDOWN))) { - bad_area(regs, error_code, address); - return; - } - if (unlikely(expand_stack(vma, address))) { - bad_area(regs, error_code, address); + bad_area_nosemaphore(regs, error_code, address); return; } @@ -461,7 +449,6 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs, * Ok, we have a good vm_area for this memory access, so * we can handle it.. */ -good_area: if (unlikely(access_error(error_code, vma))) { bad_area_access_error(regs, error_code, address); return; diff --git a/arch/sh/mm/hugetlbpage.c b/arch/sh/mm/hugetlbpage.c index 999ab5916e6927a916129475875eb885786cedf4..6cb0ad73dbb9e38fbde09534cab964c166f5e1f4 100644 --- a/arch/sh/mm/hugetlbpage.c +++ b/arch/sh/mm/hugetlbpage.c @@ -38,7 +38,7 @@ pte_t *huge_pte_alloc(struct mm_struct *mm, struct vm_area_struct *vma, if (pud) { pmd = pmd_alloc(mm, pud, addr); if (pmd) - pte = pte_alloc_map(mm, pmd, addr); + pte = pte_alloc_huge(mm, pmd, addr); } } } @@ -63,7 +63,7 @@ pte_t *huge_pte_offset(struct mm_struct *mm, if (pud) { pmd = pmd_offset(pud, addr); if (pmd) - pte = pte_offset_map(pmd, addr); + pte = pte_offset_huge(pmd, addr); } } } diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig index 8535e19062f65fa99cbe380e4ea4f02422d28954..49849790e66dc301ca1f5622e0f67170df105022 100644 --- a/arch/sparc/Kconfig +++ b/arch/sparc/Kconfig @@ -33,7 +33,7 @@ config SPARC select ARCH_WANT_IPC_PARSE_VERSION select GENERIC_PCI_IOMAP select HAS_IOPORT - select HAVE_NMI_WATCHDOG if SPARC64 + select HAVE_HARDLOCKUP_DETECTOR_SPARC64 if SPARC64 select HAVE_CBPF_JIT if SPARC32 select HAVE_EBPF_JIT if SPARC64 select HAVE_DEBUG_BUGVERBOSE @@ -52,11 +52,13 @@ config SPARC config SPARC32 def_bool !64BIT select ARCH_32BIT_OFF_T + select ARCH_HAS_CPU_FINALIZE_INIT if !SMP select ARCH_HAS_SYNC_DMA_FOR_CPU select CLZ_TAB select DMA_DIRECT_REMAP select GENERIC_ATOMIC64 select HAVE_UID16 + select LOCK_MM_AND_FIND_VMA select OLD_SIGACTION select ZONE_DMA diff --git a/arch/sparc/Kconfig.debug b/arch/sparc/Kconfig.debug index 6b2bec1888b3ec8a621870f46e55accc54729b95..37e003665de652ba7583157dd5092cb567663d41 100644 --- a/arch/sparc/Kconfig.debug +++ b/arch/sparc/Kconfig.debug @@ -14,3 +14,17 @@ config FRAME_POINTER bool depends on MCOUNT default y + +config HAVE_HARDLOCKUP_DETECTOR_SPARC64 + bool + depends on HAVE_NMI + select HARDLOCKUP_DETECTOR_SPARC64 + help + Sparc64 hardlockup detector is the last one developed before adding + the common infrastructure for handling hardlockup detectors. It is + always built. It does _not_ use the common command line parameters + and sysctl interface, except for /proc/sys/kernel/nmi_watchdog. + +config HARDLOCKUP_DETECTOR_SPARC64 + bool + depends on HAVE_HARDLOCKUP_DETECTOR_SPARC64 diff --git a/arch/sparc/configs/sparc32_defconfig b/arch/sparc/configs/sparc32_defconfig index 7b3efe5edc1a045c6e9672ca70b67a90fe605b26..7c489e7f19b7373116307143ff34cd78198bce59 100644 --- a/arch/sparc/configs/sparc32_defconfig +++ b/arch/sparc/configs/sparc32_defconfig @@ -4,7 +4,6 @@ CONFIG_LOG_BUF_SHIFT=14 CONFIG_SYSFS_DEPRECATED_V2=y CONFIG_BLK_DEV_INITRD=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set -CONFIG_SLAB=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y # CONFIG_BLK_DEV_BSG is not set diff --git a/arch/sparc/configs/sparc64_defconfig b/arch/sparc/configs/sparc64_defconfig index 18099099583ed9aa2fde66d29835eab9ab73831d..0bb0d4da522775eb8304ffe152652110ab2e70c5 100644 --- a/arch/sparc/configs/sparc64_defconfig +++ b/arch/sparc/configs/sparc64_defconfig @@ -6,7 +6,6 @@ CONFIG_LOG_BUF_SHIFT=18 CONFIG_BLK_DEV_INITRD=y CONFIG_PERF_EVENTS=y # CONFIG_COMPAT_BRK is not set -CONFIG_SLAB=y CONFIG_PROFILING=y CONFIG_KPROBES=y CONFIG_MODULES=y diff --git a/arch/sparc/include/asm/atomic_32.h b/arch/sparc/include/asm/atomic_32.h index d775daa83d1291c5607b52b44a3fdd9051685fa6..60ce2fe57fcd7d5a4be82e5a795c368695235332 100644 --- a/arch/sparc/include/asm/atomic_32.h +++ b/arch/sparc/include/asm/atomic_32.h @@ -19,17 +19,31 @@ #include int arch_atomic_add_return(int, atomic_t *); +#define arch_atomic_add_return arch_atomic_add_return + int arch_atomic_fetch_add(int, atomic_t *); +#define arch_atomic_fetch_add arch_atomic_fetch_add + int arch_atomic_fetch_and(int, atomic_t *); +#define arch_atomic_fetch_and arch_atomic_fetch_and + int arch_atomic_fetch_or(int, atomic_t *); +#define arch_atomic_fetch_or arch_atomic_fetch_or + int arch_atomic_fetch_xor(int, atomic_t *); +#define arch_atomic_fetch_xor arch_atomic_fetch_xor + int arch_atomic_cmpxchg(atomic_t *, int, int); +#define arch_atomic_cmpxchg arch_atomic_cmpxchg + int arch_atomic_xchg(atomic_t *, int); -int arch_atomic_fetch_add_unless(atomic_t *, int, int); -void arch_atomic_set(atomic_t *, int); +#define arch_atomic_xchg arch_atomic_xchg +int arch_atomic_fetch_add_unless(atomic_t *, int, int); #define arch_atomic_fetch_add_unless arch_atomic_fetch_add_unless +void arch_atomic_set(atomic_t *, int); + #define arch_atomic_set_release(v, i) arch_atomic_set((v), (i)) #define arch_atomic_read(v) READ_ONCE((v)->counter) diff --git a/arch/sparc/include/asm/atomic_64.h b/arch/sparc/include/asm/atomic_64.h index 077891686715a1f076c5d3db957e7912d9099fb8..a5e9c37605a7008f3a38c6aaad2558c30c588118 100644 --- a/arch/sparc/include/asm/atomic_64.h +++ b/arch/sparc/include/asm/atomic_64.h @@ -37,6 +37,16 @@ s64 arch_atomic64_fetch_##op(s64, atomic64_t *); ATOMIC_OPS(add) ATOMIC_OPS(sub) +#define arch_atomic_add_return arch_atomic_add_return +#define arch_atomic_sub_return arch_atomic_sub_return +#define arch_atomic_fetch_add arch_atomic_fetch_add +#define arch_atomic_fetch_sub arch_atomic_fetch_sub + +#define arch_atomic64_add_return arch_atomic64_add_return +#define arch_atomic64_sub_return arch_atomic64_sub_return +#define arch_atomic64_fetch_add arch_atomic64_fetch_add +#define arch_atomic64_fetch_sub arch_atomic64_fetch_sub + #undef ATOMIC_OPS #define ATOMIC_OPS(op) ATOMIC_OP(op) ATOMIC_FETCH_OP(op) @@ -44,22 +54,19 @@ ATOMIC_OPS(and) ATOMIC_OPS(or) ATOMIC_OPS(xor) +#define arch_atomic_fetch_and arch_atomic_fetch_and +#define arch_atomic_fetch_or arch_atomic_fetch_or +#define arch_atomic_fetch_xor arch_atomic_fetch_xor + +#define arch_atomic64_fetch_and arch_atomic64_fetch_and +#define arch_atomic64_fetch_or arch_atomic64_fetch_or +#define arch_atomic64_fetch_xor arch_atomic64_fetch_xor + #undef ATOMIC_OPS #undef ATOMIC_FETCH_OP #undef ATOMIC_OP_RETURN #undef ATOMIC_OP -#define arch_atomic_cmpxchg(v, o, n) (arch_cmpxchg(&((v)->counter), (o), (n))) - -static inline int arch_atomic_xchg(atomic_t *v, int new) -{ - return arch_xchg(&v->counter, new); -} - -#define arch_atomic64_cmpxchg(v, o, n) \ - ((__typeof__((v)->counter))arch_cmpxchg(&((v)->counter), (o), (n))) -#define arch_atomic64_xchg(v, new) (arch_xchg(&((v)->counter), new)) - s64 arch_atomic64_dec_if_positive(atomic64_t *v); #define arch_atomic64_dec_if_positive arch_atomic64_dec_if_positive diff --git a/arch/sparc/include/asm/bugs.h b/arch/sparc/include/asm/bugs.h deleted file mode 100644 index 02fa369b9c21f440c9a792055cd76ddc1eaa53df..0000000000000000000000000000000000000000 --- a/arch/sparc/include/asm/bugs.h +++ /dev/null @@ -1,18 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* include/asm/bugs.h: Sparc probes for various bugs. - * - * Copyright (C) 1996, 2007 David S. Miller (davem@davemloft.net) - */ - -#ifdef CONFIG_SPARC32 -#include -#endif - -extern unsigned long loops_per_jiffy; - -static void __init check_bugs(void) -{ -#if defined(CONFIG_SPARC32) && !defined(CONFIG_SMP) - cpu_data(0).udelay_val = loops_per_jiffy; -#endif -} diff --git a/arch/sparc/include/asm/cmpxchg_32.h b/arch/sparc/include/asm/cmpxchg_32.h index 7a1339533d1d7ec214cff5ec9c51f60803c1aac0..d0af82c240b7318fcde01a6fe613d6a611fe4540 100644 --- a/arch/sparc/include/asm/cmpxchg_32.h +++ b/arch/sparc/include/asm/cmpxchg_32.h @@ -15,7 +15,7 @@ unsigned long __xchg_u32(volatile u32 *m, u32 new); void __xchg_called_with_bad_pointer(void); -static inline unsigned long __arch_xchg(unsigned long x, __volatile__ void * ptr, int size) +static __always_inline unsigned long __arch_xchg(unsigned long x, __volatile__ void * ptr, int size) { switch (size) { case 4: diff --git a/arch/sparc/include/asm/cmpxchg_64.h b/arch/sparc/include/asm/cmpxchg_64.h index 66cd61dde9ec1f0284a17037ec178fa5157a5411..3de25262c411803106a6f445e1a246ff6aee6c89 100644 --- a/arch/sparc/include/asm/cmpxchg_64.h +++ b/arch/sparc/include/asm/cmpxchg_64.h @@ -87,7 +87,7 @@ xchg16(__volatile__ unsigned short *m, unsigned short val) return (load32 & mask) >> bit_shift; } -static inline unsigned long +static __always_inline unsigned long __arch_xchg(unsigned long x, __volatile__ void * ptr, int size) { switch (size) { diff --git a/arch/sparc/include/asm/irq_32.h b/arch/sparc/include/asm/irq_32.h index 43ec2609b8115418d33db0858272585513f7fc6d..6ee48321cbc2658c5485f7903e35cee71f4be482 100644 --- a/arch/sparc/include/asm/irq_32.h +++ b/arch/sparc/include/asm/irq_32.h @@ -17,7 +17,6 @@ #define irq_canonicalize(irq) (irq) -void __init init_IRQ(void); void __init sun4d_init_sbi_irq(void); #define NO_IRQ 0xffffffff diff --git a/arch/sparc/include/asm/irq_64.h b/arch/sparc/include/asm/irq_64.h index 154df2cf19f42d8fdf1ea2bc49a56a31fdf09398..b436029f1ced2c15a58cd22e1c6d271977b7cfad 100644 --- a/arch/sparc/include/asm/irq_64.h +++ b/arch/sparc/include/asm/irq_64.h @@ -61,7 +61,6 @@ void sun4u_destroy_msi(unsigned int irq); unsigned int irq_alloc(unsigned int dev_handle, unsigned int dev_ino); void irq_free(unsigned int irq); -void __init init_IRQ(void); void fixup_irqs(void); static inline void set_softint(unsigned long bits) diff --git a/arch/sparc/include/asm/nmi.h b/arch/sparc/include/asm/nmi.h index 90ee7863d9fe69082e47b3b292fac0660e854cd3..920dc23f443f2cc1e6bf03fdfaa47afba2d53777 100644 --- a/arch/sparc/include/asm/nmi.h +++ b/arch/sparc/include/asm/nmi.h @@ -8,7 +8,6 @@ void nmi_adjust_hz(unsigned int new_hz); extern atomic_t nmi_active; -void arch_touch_nmi_watchdog(void); void start_nmi_watchdog(void *unused); void stop_nmi_watchdog(void *unused); diff --git a/arch/sparc/include/asm/timer_64.h b/arch/sparc/include/asm/timer_64.h index dcfad4613e1875cc74e90d0420d313bf5d79ae59..ffff52c8b76003b292c64eac907262b0f0f41008 100644 --- a/arch/sparc/include/asm/timer_64.h +++ b/arch/sparc/include/asm/timer_64.h @@ -34,7 +34,6 @@ extern struct sparc64_tick_ops *tick_ops; unsigned long sparc64_get_clock_tick(unsigned int cpu); void setup_sparc64_timer(void); -void __init time_init(void); #define TICK_PRIV_BIT BIT(63) #define TICKCMP_IRQ_BIT BIT(63) diff --git a/arch/sparc/include/uapi/asm/socket.h b/arch/sparc/include/uapi/asm/socket.h index 2fda57a3ea86e6e953d2644b9c5d218a2764ff54..682da3714686c9b2d659062b05d86722a47e11ed 100644 --- a/arch/sparc/include/uapi/asm/socket.h +++ b/arch/sparc/include/uapi/asm/socket.h @@ -130,6 +130,9 @@ #define SO_RCVMARK 0x0054 +#define SO_PASSPIDFD 0x0055 +#define SO_PEERPIDFD 0x0056 + #if !defined(__KERNEL__) diff --git a/arch/sparc/kernel/ioport.c b/arch/sparc/kernel/ioport.c index 4e4f3d3263e46ba409127cf6fe51b8e2bb1d8b6b..a8cbe403301f3e357cc9e751051d8c0c0aaba940 100644 --- a/arch/sparc/kernel/ioport.c +++ b/arch/sparc/kernel/ioport.c @@ -191,7 +191,7 @@ static void __iomem *_sparc_alloc_io(unsigned int busno, unsigned long phys, tack += sizeof (struct resource); } - strlcpy(tack, name, XNMLN+1); + strscpy(tack, name, XNMLN+1); res->name = tack; va = _sparc_ioremap(res, busno, phys, size); diff --git a/arch/sparc/kernel/kernel.h b/arch/sparc/kernel/kernel.h index 9cd09a3ef35f5cd49d76bc3aebacc22eda8d5779..15da3c0597a564af026ccc93db42f8a80339c74d 100644 --- a/arch/sparc/kernel/kernel.h +++ b/arch/sparc/kernel/kernel.h @@ -91,7 +91,6 @@ extern int static_irq_count; extern spinlock_t irq_action_lock; void unexpected_irq(int irq, void *dev_id, struct pt_regs * regs); -void init_IRQ(void); /* sun4m_irq.c */ void sun4m_init_IRQ(void); diff --git a/arch/sparc/kernel/nmi.c b/arch/sparc/kernel/nmi.c index 060fff95a305c1135432f94a37216f68c76d6725..17cdfdbf1f3b78928e4bc8cea63a1d0ed2898df9 100644 --- a/arch/sparc/kernel/nmi.c +++ b/arch/sparc/kernel/nmi.c @@ -65,6 +65,11 @@ void arch_touch_nmi_watchdog(void) } EXPORT_SYMBOL(arch_touch_nmi_watchdog); +int __init watchdog_hardlockup_probe(void) +{ + return 0; +} + static void die_nmi(const char *str, struct pt_regs *regs, int do_panic) { int this_cpu = smp_processor_id(); @@ -282,11 +287,11 @@ __setup("nmi_watchdog=", setup_nmi_watchdog); * sparc specific NMI watchdog enable function. * Enables watchdog if it is not enabled already. */ -int watchdog_nmi_enable(unsigned int cpu) +void watchdog_hardlockup_enable(unsigned int cpu) { if (atomic_read(&nmi_active) == -1) { pr_warn("NMI watchdog cannot be enabled or disabled\n"); - return -1; + return; } /* @@ -295,17 +300,15 @@ int watchdog_nmi_enable(unsigned int cpu) * process first. */ if (!nmi_init_done) - return 0; + return; smp_call_function_single(cpu, start_nmi_watchdog, NULL, 1); - - return 0; } /* * sparc specific NMI watchdog disable function. * Disables watchdog if it is not disabled already. */ -void watchdog_nmi_disable(unsigned int cpu) +void watchdog_hardlockup_disable(unsigned int cpu) { if (atomic_read(&nmi_active) == -1) pr_warn_once("NMI watchdog cannot be enabled or disabled\n"); diff --git a/arch/sparc/kernel/setup_32.c b/arch/sparc/kernel/setup_32.c index c8e0dd99f3700e73851878ca44102f1c7d24fe8f..1adf5c1c16b856d20a1ed4a1f46b154e5a03b775 100644 --- a/arch/sparc/kernel/setup_32.c +++ b/arch/sparc/kernel/setup_32.c @@ -302,7 +302,7 @@ void __init setup_arch(char **cmdline_p) /* Initialize PROM console and command line. */ *cmdline_p = prom_getbootargs(); - strlcpy(boot_command_line, *cmdline_p, COMMAND_LINE_SIZE); + strscpy(boot_command_line, *cmdline_p, COMMAND_LINE_SIZE); parse_early_param(); boot_flags_init(*cmdline_p); @@ -412,3 +412,10 @@ static int __init topology_init(void) } subsys_initcall(topology_init); + +#if defined(CONFIG_SPARC32) && !defined(CONFIG_SMP) +void __init arch_cpu_finalize_init(void) +{ + cpu_data(0).udelay_val = loops_per_jiffy; +} +#endif diff --git a/arch/sparc/kernel/setup_64.c b/arch/sparc/kernel/setup_64.c index 48abee4eee29d8589d9452029f109e102f63f91a..6546ca9d4d3f1f629a632f9c8c000ee6802b99eb 100644 --- a/arch/sparc/kernel/setup_64.c +++ b/arch/sparc/kernel/setup_64.c @@ -636,7 +636,7 @@ void __init setup_arch(char **cmdline_p) { /* Initialize PROM console and command line. */ *cmdline_p = prom_getbootargs(); - strlcpy(boot_command_line, *cmdline_p, COMMAND_LINE_SIZE); + strscpy(boot_command_line, *cmdline_p, COMMAND_LINE_SIZE); parse_early_param(); boot_flags_init(*cmdline_p); diff --git a/arch/sparc/kernel/signal32.c b/arch/sparc/kernel/signal32.c index dad38960d1a8ac92aba0546d8f323945407048a7..ca450c7bc53fd832577b056f7d193ca1fe47557a 100644 --- a/arch/sparc/kernel/signal32.c +++ b/arch/sparc/kernel/signal32.c @@ -328,6 +328,8 @@ static void flush_signal_insns(unsigned long address) goto out_irqs_on; ptep = pte_offset_map(pmdp, address); + if (!ptep) + goto out_irqs_on; pte = *ptep; if (!pte_present(pte)) goto out_unmap; diff --git a/arch/sparc/kernel/syscalls/syscall.tbl b/arch/sparc/kernel/syscalls/syscall.tbl index 4398cc6fb68dd84955d3c3c7e8e10437ba2d5312..faa835f3c54a5f132965e1c63a1072d2d357c539 100644 --- a/arch/sparc/kernel/syscalls/syscall.tbl +++ b/arch/sparc/kernel/syscalls/syscall.tbl @@ -496,3 +496,4 @@ 448 common process_mrelease sys_process_mrelease 449 common futex_waitv sys_futex_waitv 450 common set_mempolicy_home_node sys_set_mempolicy_home_node +451 common cachestat sys_cachestat diff --git a/arch/sparc/mm/fault_32.c b/arch/sparc/mm/fault_32.c index 179295b14664a55d889844790f0048c8b29ef553..86a831ebd8c8e30e51058bc09d8c02d2ef2cf71b 100644 --- a/arch/sparc/mm/fault_32.c +++ b/arch/sparc/mm/fault_32.c @@ -143,28 +143,19 @@ asmlinkage void do_sparc_fault(struct pt_regs *regs, int text_fault, int write, if (pagefault_disabled() || !mm) goto no_context; + if (!from_user && address >= PAGE_OFFSET) + goto no_context; + perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address); retry: - mmap_read_lock(mm); - - if (!from_user && address >= PAGE_OFFSET) - goto bad_area; - - vma = find_vma(mm, address); + vma = lock_mm_and_find_vma(mm, address, regs); if (!vma) - goto bad_area; - if (vma->vm_start <= address) - goto good_area; - if (!(vma->vm_flags & VM_GROWSDOWN)) - goto bad_area; - if (expand_stack(vma, address)) - goto bad_area; + goto bad_area_nosemaphore; /* * Ok, we have a good vm_area for this memory access, so * we can handle it.. */ -good_area: code = SEGV_ACCERR; if (write) { if (!(vma->vm_flags & VM_WRITE)) @@ -321,17 +312,9 @@ static void force_user_fault(unsigned long address, int write) code = SEGV_MAPERR; - mmap_read_lock(mm); - vma = find_vma(mm, address); + vma = lock_mm_and_find_vma(mm, address, NULL); if (!vma) - goto bad_area; - if (vma->vm_start <= address) - goto good_area; - if (!(vma->vm_flags & VM_GROWSDOWN)) - goto bad_area; - if (expand_stack(vma, address)) - goto bad_area; -good_area: + goto bad_area_nosemaphore; code = SEGV_ACCERR; if (write) { if (!(vma->vm_flags & VM_WRITE)) @@ -350,6 +333,7 @@ static void force_user_fault(unsigned long address, int write) return; bad_area: mmap_read_unlock(mm); +bad_area_nosemaphore: __do_fault_siginfo(code, SIGSEGV, tsk->thread.kregs, address); return; diff --git a/arch/sparc/mm/fault_64.c b/arch/sparc/mm/fault_64.c index d91305de694c54dce9bfcaa8ababf0620465818f..e326caf708c609204d1d40af5b5cc073496780e5 100644 --- a/arch/sparc/mm/fault_64.c +++ b/arch/sparc/mm/fault_64.c @@ -99,6 +99,7 @@ static unsigned int get_user_insn(unsigned long tpc) local_irq_disable(); pmdp = pmd_offset(pudp, tpc); +again: if (pmd_none(*pmdp) || unlikely(pmd_bad(*pmdp))) goto out_irq_enable; @@ -115,6 +116,8 @@ static unsigned int get_user_insn(unsigned long tpc) #endif { ptep = pte_offset_map(pmdp, tpc); + if (!ptep) + goto again; pte = *ptep; if (pte_present(pte)) { pa = (pte_pfn(pte) << PAGE_SHIFT); @@ -383,8 +386,9 @@ asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs) goto bad_area; } } - if (expand_stack(vma, address)) - goto bad_area; + vma = expand_stack(mm, address); + if (!vma) + goto bad_area_nosemaphore; /* * Ok, we have a good vm_area for this memory access, so * we can handle it.. @@ -487,8 +491,9 @@ asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs) * Fix it, but check if it's kernel or user first.. */ bad_area: - insn = get_fault_insn(regs, insn); mmap_read_unlock(mm); +bad_area_nosemaphore: + insn = get_fault_insn(regs, insn); handle_kernel_fault: do_kernel_fault(regs, si_code, fault_code, insn, address); diff --git a/arch/sparc/mm/hugetlbpage.c b/arch/sparc/mm/hugetlbpage.c index d8e0e3c7038d06d381dd783a5c43905c5d5bc68a..d7018823206c13647fa5ddde4103fa9ff18f5cd7 100644 --- a/arch/sparc/mm/hugetlbpage.c +++ b/arch/sparc/mm/hugetlbpage.c @@ -298,7 +298,7 @@ pte_t *huge_pte_alloc(struct mm_struct *mm, struct vm_area_struct *vma, return NULL; if (sz >= PMD_SIZE) return (pte_t *)pmd; - return pte_alloc_map(mm, pmd, addr); + return pte_alloc_huge(mm, pmd, addr); } pte_t *huge_pte_offset(struct mm_struct *mm, @@ -325,7 +325,7 @@ pte_t *huge_pte_offset(struct mm_struct *mm, return NULL; if (is_hugetlb_pmd(*pmd)) return (pte_t *)pmd; - return pte_offset_map(pmd, addr); + return pte_offset_huge(pmd, addr); } void set_huge_pte_at(struct mm_struct *mm, unsigned long addr, diff --git a/arch/sparc/mm/io-unit.c b/arch/sparc/mm/io-unit.c index bf3e6d2fe5d949549b8ab103482a58c0b84d7619..133dd42570d69c6c926c49536ca539a9a2bd0bdc 100644 --- a/arch/sparc/mm/io-unit.c +++ b/arch/sparc/mm/io-unit.c @@ -244,7 +244,7 @@ static void *iounit_alloc(struct device *dev, size_t len, long i; pmdp = pmd_off_k(addr); - ptep = pte_offset_map(pmdp, addr); + ptep = pte_offset_kernel(pmdp, addr); set_pte(ptep, mk_pte(virt_to_page(page), dvma_prot)); diff --git a/arch/sparc/mm/iommu.c b/arch/sparc/mm/iommu.c index 9e3f6933ca13f4e3282d128a0581b3519b086802..3a6caef683488421b9e03ad8fde8f0e8270c5bd7 100644 --- a/arch/sparc/mm/iommu.c +++ b/arch/sparc/mm/iommu.c @@ -358,7 +358,7 @@ static void *sbus_iommu_alloc(struct device *dev, size_t len, __flush_page_to_ram(page); pmdp = pmd_off_k(addr); - ptep = pte_offset_map(pmdp, addr); + ptep = pte_offset_kernel(pmdp, addr); set_pte(ptep, mk_pte(virt_to_page(page), dvma_prot)); } diff --git a/arch/sparc/mm/tlb.c b/arch/sparc/mm/tlb.c index 9a725547578e87a3c89f5cff592376dd1f2f5c76..7ecf8556947abc28661ee649b636c13272375d2e 100644 --- a/arch/sparc/mm/tlb.c +++ b/arch/sparc/mm/tlb.c @@ -149,6 +149,8 @@ static void tlb_batch_pmd_scan(struct mm_struct *mm, unsigned long vaddr, pte_t *pte; pte = pte_offset_map(&pmd, vaddr); + if (!pte) + return; end = vaddr + HPAGE_SIZE; while (vaddr < end) { if (pte_val(*pte) & _PAGE_VALID) { diff --git a/arch/sparc/prom/bootstr_32.c b/arch/sparc/prom/bootstr_32.c index e3b731ff00f07b3cc937cf5baf5bc40fe0d213f8..1c7cd258b0dc02ad533e79563701186a08093294 100644 --- a/arch/sparc/prom/bootstr_32.c +++ b/arch/sparc/prom/bootstr_32.c @@ -52,7 +52,7 @@ prom_getbootargs(void) * V3 PROM cannot supply as with more than 128 bytes * of an argument. But a smart bootstrap loader can. */ - strlcpy(barg_buf, *romvec->pv_v2bootargs.bootargs, sizeof(barg_buf)); + strscpy(barg_buf, *romvec->pv_v2bootargs.bootargs, sizeof(barg_buf)); break; default: break; diff --git a/arch/sparc/video/fbdev.c b/arch/sparc/video/fbdev.c index 25837f128132de151ce5dce80a8338de52a772ff..bff66dd1909a4411549f7f381eef4960375b7dbf 100644 --- a/arch/sparc/video/fbdev.c +++ b/arch/sparc/video/fbdev.c @@ -21,3 +21,6 @@ int fb_is_primary_device(struct fb_info *info) return 0; } EXPORT_SYMBOL(fb_is_primary_device); + +MODULE_DESCRIPTION("Sparc fbdev helpers"); +MODULE_LICENSE("GPL"); diff --git a/arch/um/Kconfig b/arch/um/Kconfig index 541a9b18e3435ca49e932f5767a5906b2ab9ea58..b5e179360534631deb98b62891b927186b5086fe 100644 --- a/arch/um/Kconfig +++ b/arch/um/Kconfig @@ -5,7 +5,7 @@ menu "UML-specific options" config UML bool default y - select ARCH_EPHEMERAL_INODES + select ARCH_HAS_CPU_FINALIZE_INIT select ARCH_HAS_FORTIFY_SOURCE select ARCH_HAS_GCOV_PROFILE_ALL select ARCH_HAS_KCOV diff --git a/arch/um/Makefile b/arch/um/Makefile index 8186d4761bda6b7b0d8ec32e58b1093cfe4a51bb..da4d5256af2f00aff819d5a007d5f69844c3c403 100644 --- a/arch/um/Makefile +++ b/arch/um/Makefile @@ -149,7 +149,7 @@ export CFLAGS_vmlinux := $(LINK-y) $(LINK_WRAPS) $(LD_FLAGS_CMDLINE) $(CC_FLAGS_ # When cleaning we don't include .config, so we don't include # TT or skas makefiles and don't clean skas_ptregs.h. CLEAN_FILES += linux x.i gmon.out -MRPROPER_FILES += arch/$(SUBARCH)/include/generated +MRPROPER_FILES += $(HOST_DIR)/include/generated archclean: @find . \( -name '*.bb' -o -name '*.bbg' -o -name '*.da' \ diff --git a/arch/um/configs/i386_defconfig b/arch/um/configs/i386_defconfig index c0162286d68b7e6f70317af06c501bf8e3a2b454..05ae535ba0dca81391e9e097baa10c7ebe046650 100644 --- a/arch/um/configs/i386_defconfig +++ b/arch/um/configs/i386_defconfig @@ -22,7 +22,6 @@ CONFIG_BLK_CGROUP=y # CONFIG_PID_NS is not set CONFIG_SYSFS_DEPRECATED=y CONFIG_CC_OPTIMIZE_FOR_SIZE=y -CONFIG_SLAB=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y # CONFIG_BLK_DEV_BSG is not set diff --git a/arch/um/configs/x86_64_defconfig b/arch/um/configs/x86_64_defconfig index bec6e5d956873089736bcfc1ef0523103d46c678..1c757238be7feafab1569432c710b73a0db8e5ff 100644 --- a/arch/um/configs/x86_64_defconfig +++ b/arch/um/configs/x86_64_defconfig @@ -20,7 +20,6 @@ CONFIG_BLK_CGROUP=y # CONFIG_PID_NS is not set CONFIG_SYSFS_DEPRECATED=y CONFIG_CC_OPTIMIZE_FOR_SIZE=y -CONFIG_SLAB=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y # CONFIG_BLK_DEV_BSG is not set diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c index f4c1e6e97ad520ef0e5cdabd622ec473862c7b72..50206feac577d539e638cd18a012195f5bc91bac 100644 --- a/arch/um/drivers/ubd_kern.c +++ b/arch/um/drivers/ubd_kern.c @@ -108,9 +108,9 @@ static inline void ubd_set_bit(__u64 bit, unsigned char *data) static DEFINE_MUTEX(ubd_lock); static DEFINE_MUTEX(ubd_mutex); /* replaces BKL, might not be needed */ -static int ubd_open(struct block_device *bdev, fmode_t mode); -static void ubd_release(struct gendisk *disk, fmode_t mode); -static int ubd_ioctl(struct block_device *bdev, fmode_t mode, +static int ubd_open(struct gendisk *disk, blk_mode_t mode); +static void ubd_release(struct gendisk *disk); +static int ubd_ioctl(struct block_device *bdev, blk_mode_t mode, unsigned int cmd, unsigned long arg); static int ubd_getgeo(struct block_device *bdev, struct hd_geometry *geo); @@ -1154,9 +1154,8 @@ static int __init ubd_driver_init(void){ device_initcall(ubd_driver_init); -static int ubd_open(struct block_device *bdev, fmode_t mode) +static int ubd_open(struct gendisk *disk, blk_mode_t mode) { - struct gendisk *disk = bdev->bd_disk; struct ubd *ubd_dev = disk->private_data; int err = 0; @@ -1171,19 +1170,12 @@ static int ubd_open(struct block_device *bdev, fmode_t mode) } ubd_dev->count++; set_disk_ro(disk, !ubd_dev->openflags.w); - - /* This should no more be needed. And it didn't work anyway to exclude - * read-write remounting of filesystems.*/ - /*if((mode & FMODE_WRITE) && !ubd_dev->openflags.w){ - if(--ubd_dev->count == 0) ubd_close_dev(ubd_dev); - err = -EROFS; - }*/ out: mutex_unlock(&ubd_mutex); return err; } -static void ubd_release(struct gendisk *disk, fmode_t mode) +static void ubd_release(struct gendisk *disk) { struct ubd *ubd_dev = disk->private_data; @@ -1397,7 +1389,7 @@ static int ubd_getgeo(struct block_device *bdev, struct hd_geometry *geo) return 0; } -static int ubd_ioctl(struct block_device *bdev, fmode_t mode, +static int ubd_ioctl(struct block_device *bdev, blk_mode_t mode, unsigned int cmd, unsigned long arg) { struct ubd *ubd_dev = bdev->bd_disk->private_data; diff --git a/arch/um/include/asm/bugs.h b/arch/um/include/asm/bugs.h deleted file mode 100644 index 4473942a083973d85d590174900fd69250799e27..0000000000000000000000000000000000000000 --- a/arch/um/include/asm/bugs.h +++ /dev/null @@ -1,7 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef __UM_BUGS_H -#define __UM_BUGS_H - -void check_bugs(void); - -#endif diff --git a/arch/um/include/shared/user.h b/arch/um/include/shared/user.h index bda66e5a9d4e3fc8187cb5b3356475a5bec0c556..0347a190429cd4bbc69f9afdadf4dd349fd85084 100644 --- a/arch/um/include/shared/user.h +++ b/arch/um/include/shared/user.h @@ -52,6 +52,7 @@ static inline int printk(const char *fmt, ...) extern int in_aton(char *str); extern size_t strlcpy(char *, const char *, size_t); extern size_t strlcat(char *, const char *, size_t); +extern size_t strscpy(char *, const char *, size_t); /* Copied from linux/compiler-gcc.h since we can't include it directly */ #define barrier() __asm__ __volatile__("": : :"memory") diff --git a/arch/um/kernel/trap.c b/arch/um/kernel/trap.c index d3ce21c4ca32a8391de6b5372960ff461be1fe87..6d8ae86ae978fdeef10c52d7d9a8d5cb11a43038 100644 --- a/arch/um/kernel/trap.c +++ b/arch/um/kernel/trap.c @@ -47,14 +47,15 @@ int handle_page_fault(unsigned long address, unsigned long ip, vma = find_vma(mm, address); if (!vma) goto out; - else if (vma->vm_start <= address) + if (vma->vm_start <= address) goto good_area; - else if (!(vma->vm_flags & VM_GROWSDOWN)) + if (!(vma->vm_flags & VM_GROWSDOWN)) goto out; - else if (is_user && !ARCH_IS_STACKGROW(address)) - goto out; - else if (expand_stack(vma, address)) + if (is_user && !ARCH_IS_STACKGROW(address)) goto out; + vma = expand_stack(mm, address); + if (!vma) + goto out_nosemaphore; good_area: *code_out = SEGV_ACCERR; diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c index 0a23a98d4ca0a74fc5825f68df9a2cea1510fe00..b1bfed0c85288fbb0ec583d571c9b3c6202b62c5 100644 --- a/arch/um/kernel/um_arch.c +++ b/arch/um/kernel/um_arch.c @@ -3,6 +3,7 @@ * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) */ +#include #include #include #include @@ -430,13 +431,13 @@ void __init setup_arch(char **cmdline_p) } } -void __init check_bugs(void) +void __init arch_cpu_finalize_init(void) { arch_check_bugs(); os_check_bugs(); } -void apply_ibt_endbr(s32 *start, s32 *end) +void apply_seal_endbr(s32 *start, s32 *end) { } diff --git a/arch/um/os-Linux/drivers/tuntap_user.c b/arch/um/os-Linux/drivers/tuntap_user.c index 53eb3d508645d72c5b9b5eae9c02d5156a66dd4c..2284e9c1cbbbf702d986e0f8337e77f07f475bb7 100644 --- a/arch/um/os-Linux/drivers/tuntap_user.c +++ b/arch/um/os-Linux/drivers/tuntap_user.c @@ -146,7 +146,7 @@ static int tuntap_open(void *data) } memset(&ifr, 0, sizeof(ifr)); ifr.ifr_flags = IFF_TAP | IFF_NO_PI; - strlcpy(ifr.ifr_name, pri->dev_name, sizeof(ifr.ifr_name)); + strscpy(ifr.ifr_name, pri->dev_name, sizeof(ifr.ifr_name)); if (ioctl(pri->fd, TUNSETIFF, &ifr) < 0) { err = -errno; printk(UM_KERN_ERR "TUNSETIFF failed, errno = %d\n", diff --git a/arch/um/os-Linux/user_syms.c b/arch/um/os-Linux/user_syms.c index 9b62a9d352b3ae99bd9ce17e30efded195095dff..a310ae27b479ae80e0ca29e112e8cd4fa7e3edfb 100644 --- a/arch/um/os-Linux/user_syms.c +++ b/arch/um/os-Linux/user_syms.c @@ -37,13 +37,6 @@ EXPORT_SYMBOL(vsyscall_ehdr); EXPORT_SYMBOL(vsyscall_end); #endif -/* Export symbols used by GCC for the stack protector. */ -extern void __stack_smash_handler(void *) __attribute__((weak)); -EXPORT_SYMBOL(__stack_smash_handler); - -extern long __guard __attribute__((weak)); -EXPORT_SYMBOL(__guard); - #ifdef _FORTIFY_SOURCE extern int __sprintf_chk(char *str, int flag, size_t len, const char *format); EXPORT_SYMBOL(__sprintf_chk); diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 53bab123a8ee40a2484ae63b29cac4e8f545ee32..7422db4097701c96710ce67054a9f0c7edc6ec1b 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -71,6 +71,7 @@ config X86 select ARCH_HAS_ACPI_TABLE_UPGRADE if ACPI select ARCH_HAS_CACHE_LINE_SIZE select ARCH_HAS_CPU_CACHE_INVALIDATE_MEMREGION + select ARCH_HAS_CPU_FINALIZE_INIT select ARCH_HAS_CURRENT_STACK_POINTER select ARCH_HAS_DEBUG_VIRTUAL select ARCH_HAS_DEBUG_VM_PGTABLE if !X86_PAE @@ -216,6 +217,7 @@ config X86 select HAVE_FAST_GUP select HAVE_FENTRY if X86_64 || DYNAMIC_FTRACE select HAVE_FTRACE_MCOUNT_RECORD + select HAVE_FUNCTION_GRAPH_RETVAL if HAVE_FUNCTION_GRAPH_TRACER select HAVE_FUNCTION_GRAPH_TRACER if X86_32 || (X86_64 && DYNAMIC_FTRACE) select HAVE_FUNCTION_TRACER select HAVE_GCC_PLUGINS @@ -274,8 +276,11 @@ config X86 select HAVE_UNSTABLE_SCHED_CLOCK select HAVE_USER_RETURN_NOTIFIER select HAVE_GENERIC_VDSO + select HOTPLUG_PARALLEL if SMP && X86_64 select HOTPLUG_SMT if SMP + select HOTPLUG_SPLIT_STARTUP if SMP && X86_32 select IRQ_FORCED_THREADING + select LOCK_MM_AND_FIND_VMA select NEED_PER_CPU_EMBED_FIRST_CHUNK select NEED_PER_CPU_PAGE_FIRST_CHUNK select NEED_SG_DMA_LENGTH @@ -291,7 +296,6 @@ config X86 select TRACE_IRQFLAGS_NMI_SUPPORT select USER_STACKTRACE_SUPPORT select HAVE_ARCH_KCSAN if X86_64 - select X86_FEATURE_NAMES if PROC_FS select PROC_PID_ARCH_STATUS if PROC_FS select HAVE_ARCH_NODE_DEV_GROUP if X86_SGX select FUNCTION_ALIGNMENT_16B if X86_64 || X86_ALIGNMENT_16 @@ -441,17 +445,6 @@ config SMP If you don't know what to do here, say N. -config X86_FEATURE_NAMES - bool "Processor feature human-readable names" if EMBEDDED - default y - help - This option compiles in a table of x86 feature bits and corresponding - names. This is required to support /proc/cpuinfo and a few kernel - messages. You can disable this to save space, at the expense of - making those few kernel messages show numeric feature bits instead. - - If in doubt, say Y. - config X86_X2APIC bool "Support x2apic" depends on X86_LOCAL_APIC && X86_64 && (IRQ_REMAP || HYPERVISOR_GUEST) @@ -884,9 +877,11 @@ config INTEL_TDX_GUEST bool "Intel TDX (Trust Domain Extensions) - Guest Support" depends on X86_64 && CPU_SUP_INTEL depends on X86_X2APIC + depends on EFI_STUB select ARCH_HAS_CC_PLATFORM select X86_MEM_ENCRYPT select X86_MCE + select UNACCEPTED_MEMORY help Support running as a guest under Intel TDX. Without this support, the guest kernel can not boot or run under TDX. @@ -1541,11 +1536,13 @@ config X86_MEM_ENCRYPT config AMD_MEM_ENCRYPT bool "AMD Secure Memory Encryption (SME) support" depends on X86_64 && CPU_SUP_AMD + depends on EFI_STUB select DMA_COHERENT_POOL select ARCH_USE_MEMREMAP_PROT select INSTRUCTION_DECODER select ARCH_HAS_CC_PLATFORM select X86_MEM_ENCRYPT + select UNACCEPTED_MEMORY help Say yes to enable support for the encryption of system memory. This requires an AMD processor that supports Secure Memory @@ -2305,49 +2302,6 @@ config HOTPLUG_CPU def_bool y depends on SMP -config BOOTPARAM_HOTPLUG_CPU0 - bool "Set default setting of cpu0_hotpluggable" - depends on HOTPLUG_CPU - help - Set whether default state of cpu0_hotpluggable is on or off. - - Say Y here to enable CPU0 hotplug by default. If this switch - is turned on, there is no need to give cpu0_hotplug kernel - parameter and the CPU0 hotplug feature is enabled by default. - - Please note: there are two known CPU0 dependencies if you want - to enable the CPU0 hotplug feature either by this switch or by - cpu0_hotplug kernel parameter. - - First, resume from hibernate or suspend always starts from CPU0. - So hibernate and suspend are prevented if CPU0 is offline. - - Second dependency is PIC interrupts always go to CPU0. CPU0 can not - offline if any interrupt can not migrate out of CPU0. There may - be other CPU0 dependencies. - - Please make sure the dependencies are under your control before - you enable this feature. - - Say N if you don't want to enable CPU0 hotplug feature by default. - You still can enable the CPU0 hotplug feature at boot by kernel - parameter cpu0_hotplug. - -config DEBUG_HOTPLUG_CPU0 - def_bool n - prompt "Debug CPU0 hotplug" - depends on HOTPLUG_CPU - help - Enabling this option offlines CPU0 (if CPU0 can be offlined) as - soon as possible and boots up userspace with CPU0 offlined. User - can online CPU0 back after boot time. - - To debug CPU0 hotplug, you need to enable CPU0 offline/online - feature by either turning on CONFIG_BOOTPARAM_HOTPLUG_CPU0 during - compilation or giving cpu0_hotplug kernel parameter at boot. - - If unsure, say N. - config COMPAT_VDSO def_bool n prompt "Disable the 32-bit vDSO (needed for glibc 2.3.3)" diff --git a/arch/x86/Kconfig.cpu b/arch/x86/Kconfig.cpu index 542377cd419d788e470e2a90d306ee3212cf9024..00468adf180f1d9192eec9924d6108159bd209d8 100644 --- a/arch/x86/Kconfig.cpu +++ b/arch/x86/Kconfig.cpu @@ -389,7 +389,7 @@ config IA32_FEAT_CTL config X86_VMX_FEATURE_NAMES def_bool y - depends on IA32_FEAT_CTL && X86_FEATURE_NAMES + depends on IA32_FEAT_CTL menuconfig PROCESSOR_SELECT bool "Supported processor vendors" if EXPERT diff --git a/arch/x86/Makefile b/arch/x86/Makefile index 89a02e69be5f39017d772ef5ab85bdf029734e8e..95315d3474a292cc3418ea4a9f43dedcdbd5dc14 100644 --- a/arch/x86/Makefile +++ b/arch/x86/Makefile @@ -305,6 +305,18 @@ ifeq ($(RETPOLINE_CFLAGS),) endif endif +ifdef CONFIG_UNWINDER_ORC +orc_hash_h := arch/$(SRCARCH)/include/generated/asm/orc_hash.h +orc_hash_sh := $(srctree)/scripts/orc_hash.sh +targets += $(orc_hash_h) +quiet_cmd_orc_hash = GEN $@ + cmd_orc_hash = mkdir -p $(dir $@); \ + $(CONFIG_SHELL) $(orc_hash_sh) < $< > $@ +$(orc_hash_h): $(srctree)/arch/x86/include/asm/orc_types.h $(orc_hash_sh) FORCE + $(call if_changed,orc_hash) +archprepare: $(orc_hash_h) +endif + archclean: $(Q)rm -rf $(objtree)/arch/i386 $(Q)rm -rf $(objtree)/arch/x86_64 diff --git a/arch/x86/Makefile.postlink b/arch/x86/Makefile.postlink new file mode 100644 index 0000000000000000000000000000000000000000..936093d291605ebcae5284bfacf1db8b6d5c9b1c --- /dev/null +++ b/arch/x86/Makefile.postlink @@ -0,0 +1,47 @@ +# SPDX-License-Identifier: GPL-2.0 +# =========================================================================== +# Post-link x86 pass +# =========================================================================== +# +# 1. Separate relocations from vmlinux into vmlinux.relocs. +# 2. Strip relocations from vmlinux. + +PHONY := __archpost +__archpost: + +-include include/config/auto.conf +include $(srctree)/scripts/Kbuild.include + +CMD_RELOCS = arch/x86/tools/relocs +OUT_RELOCS = arch/x86/boot/compressed +quiet_cmd_relocs = RELOCS $(OUT_RELOCS)/$@.relocs + cmd_relocs = \ + mkdir -p $(OUT_RELOCS); \ + $(CMD_RELOCS) $@ > $(OUT_RELOCS)/$@.relocs; \ + $(CMD_RELOCS) --abs-relocs $@ + +quiet_cmd_strip_relocs = RSTRIP $@ + cmd_strip_relocs = \ + $(OBJCOPY) --remove-section='.rel.*' --remove-section='.rel__*' \ + --remove-section='.rela.*' --remove-section='.rela__*' $@ + +# `@true` prevents complaint when there is nothing to be done + +vmlinux: FORCE + @true +ifeq ($(CONFIG_X86_NEED_RELOCS),y) + $(call cmd,relocs) + $(call cmd,strip_relocs) +endif + +%.ko: FORCE + @true + +clean: + @rm -f $(OUT_RELOCS)/vmlinux.relocs + +PHONY += FORCE clean + +FORCE: + +.PHONY: $(PHONY) diff --git a/arch/x86/boot/Makefile b/arch/x86/boot/Makefile index 9e38ffaadb5d972e640520e4985718b23b0a76ba..f33e45ed143765f99c80c55b18f0c500d08208d4 100644 --- a/arch/x86/boot/Makefile +++ b/arch/x86/boot/Makefile @@ -55,14 +55,12 @@ HOST_EXTRACFLAGS += -I$(srctree)/tools/include \ -include include/generated/autoconf.h \ -D__EXPORTED_HEADERS__ -ifdef CONFIG_X86_FEATURE_NAMES $(obj)/cpu.o: $(obj)/cpustr.h quiet_cmd_cpustr = CPUSTR $@ cmd_cpustr = $(obj)/mkcpustr > $@ $(obj)/cpustr.h: $(obj)/mkcpustr FORCE $(call if_changed,cpustr) -endif targets += cpustr.h # --------------------------------------------------------------------------- diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile index 6b6cfe607bdbdfaa3ab42a7a1850b10fe3e31e91..40d2ff503079e594e17f133a58fbfa8a914ec666 100644 --- a/arch/x86/boot/compressed/Makefile +++ b/arch/x86/boot/compressed/Makefile @@ -106,7 +106,8 @@ ifdef CONFIG_X86_64 endif vmlinux-objs-$(CONFIG_ACPI) += $(obj)/acpi.o -vmlinux-objs-$(CONFIG_INTEL_TDX_GUEST) += $(obj)/tdx.o $(obj)/tdcall.o +vmlinux-objs-$(CONFIG_INTEL_TDX_GUEST) += $(obj)/tdx.o $(obj)/tdcall.o $(obj)/tdx-shared.o +vmlinux-objs-$(CONFIG_UNACCEPTED_MEMORY) += $(obj)/mem.o vmlinux-objs-$(CONFIG_EFI) += $(obj)/efi.o vmlinux-objs-$(CONFIG_EFI_MIXED) += $(obj)/efi_mixed.o @@ -121,11 +122,9 @@ $(obj)/vmlinux.bin: vmlinux FORCE targets += $(patsubst $(obj)/%,%,$(vmlinux-objs-y)) vmlinux.bin.all vmlinux.relocs -CMD_RELOCS = arch/x86/tools/relocs -quiet_cmd_relocs = RELOCS $@ - cmd_relocs = $(CMD_RELOCS) $< > $@;$(CMD_RELOCS) --abs-relocs $< -$(obj)/vmlinux.relocs: vmlinux FORCE - $(call if_changed,relocs) +# vmlinux.relocs is created by the vmlinux postlink step. +$(obj)/vmlinux.relocs: vmlinux + @true vmlinux.bin.all-y := $(obj)/vmlinux.bin vmlinux.bin.all-$(CONFIG_X86_NEED_RELOCS) += $(obj)/vmlinux.relocs diff --git a/arch/x86/boot/compressed/efi.h b/arch/x86/boot/compressed/efi.h index 7db2f41b54cd8dba8acf4765e0ccb999b1bc03e7..866c0af8b5b9e2a6ae8b7de0a28e3c77f47f933d 100644 --- a/arch/x86/boot/compressed/efi.h +++ b/arch/x86/boot/compressed/efi.h @@ -16,6 +16,7 @@ typedef guid_t efi_guid_t __aligned(__alignof__(u32)); #define ACPI_TABLE_GUID EFI_GUID(0xeb9d2d30, 0x2d88, 0x11d3, 0x9a, 0x16, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d) #define ACPI_20_TABLE_GUID EFI_GUID(0x8868e871, 0xe4f1, 0x11d3, 0xbc, 0x22, 0x00, 0x80, 0xc7, 0x3c, 0x88, 0x81) #define EFI_CC_BLOB_GUID EFI_GUID(0x067b1f5f, 0xcf26, 0x44c5, 0x85, 0x54, 0x93, 0xd7, 0x77, 0x91, 0x2d, 0x42) +#define LINUX_EFI_UNACCEPTED_MEM_TABLE_GUID EFI_GUID(0xd5d1de3c, 0x105c, 0x44f9, 0x9e, 0xa9, 0xbc, 0xef, 0x98, 0x12, 0x00, 0x31) #define EFI32_LOADER_SIGNATURE "EL32" #define EFI64_LOADER_SIGNATURE "EL64" @@ -32,6 +33,7 @@ typedef struct { } efi_table_hdr_t; #define EFI_CONVENTIONAL_MEMORY 7 +#define EFI_UNACCEPTED_MEMORY 15 #define EFI_MEMORY_MORE_RELIABLE \ ((u64)0x0000000000010000ULL) /* higher reliability */ @@ -104,6 +106,14 @@ struct efi_setup_data { u64 reserved[8]; }; +struct efi_unaccepted_memory { + u32 version; + u32 unit_size; + u64 phys_base; + u64 size; + unsigned long bitmap[]; +}; + static inline int efi_guidcmp (efi_guid_t left, efi_guid_t right) { return memcmp(&left, &right, sizeof (efi_guid_t)); diff --git a/arch/x86/boot/compressed/error.c b/arch/x86/boot/compressed/error.c index c881878e56d313f004787c81269e230b05d9bc3a..5313c5cb2b802beed4b062071efaa4c212e4abeb 100644 --- a/arch/x86/boot/compressed/error.c +++ b/arch/x86/boot/compressed/error.c @@ -22,3 +22,22 @@ void error(char *m) while (1) asm("hlt"); } + +/* EFI libstub provides vsnprintf() */ +#ifdef CONFIG_EFI_STUB +void panic(const char *fmt, ...) +{ + static char buf[1024]; + va_list args; + int len; + + va_start(args, fmt); + len = vsnprintf(buf, sizeof(buf), fmt, args); + va_end(args); + + if (len && buf[len - 1] == '\n') + buf[len - 1] = '\0'; + + error(buf); +} +#endif diff --git a/arch/x86/boot/compressed/error.h b/arch/x86/boot/compressed/error.h index 1de5821184f180fd25dc023ae97db311925f6d52..86fe33b937154cab11923ceccfb1bf73cc715d95 100644 --- a/arch/x86/boot/compressed/error.h +++ b/arch/x86/boot/compressed/error.h @@ -6,5 +6,6 @@ void warn(char *m); void error(char *m) __noreturn; +void panic(const char *fmt, ...) __noreturn __cold; #endif /* BOOT_COMPRESSED_ERROR_H */ diff --git a/arch/x86/boot/compressed/kaslr.c b/arch/x86/boot/compressed/kaslr.c index 454757fbdfe5adb5b3b12438bc29a909eb3a548a..9193acf0e9cdec5d42bf89743ac16c280af51b41 100644 --- a/arch/x86/boot/compressed/kaslr.c +++ b/arch/x86/boot/compressed/kaslr.c @@ -672,6 +672,33 @@ static bool process_mem_region(struct mem_vector *region, } #ifdef CONFIG_EFI + +/* + * Only EFI_CONVENTIONAL_MEMORY and EFI_UNACCEPTED_MEMORY (if supported) are + * guaranteed to be free. + * + * Pick free memory more conservatively than the EFI spec allows: according to + * the spec, EFI_BOOT_SERVICES_{CODE|DATA} are also free memory and thus + * available to place the kernel image into, but in practice there's firmware + * where using that memory leads to crashes. Buggy vendor EFI code registers + * for an event that triggers on SetVirtualAddressMap(). The handler assumes + * that EFI_BOOT_SERVICES_DATA memory has not been touched by loader yet, which + * is probably true for Windows. + * + * Preserve EFI_BOOT_SERVICES_* regions until after SetVirtualAddressMap(). + */ +static inline bool memory_type_is_free(efi_memory_desc_t *md) +{ + if (md->type == EFI_CONVENTIONAL_MEMORY) + return true; + + if (IS_ENABLED(CONFIG_UNACCEPTED_MEMORY) && + md->type == EFI_UNACCEPTED_MEMORY) + return true; + + return false; +} + /* * Returns true if we processed the EFI memmap, which we prefer over the E820 * table if it is available. @@ -716,18 +743,7 @@ process_efi_entries(unsigned long minimum, unsigned long image_size) for (i = 0; i < nr_desc; i++) { md = efi_early_memdesc_ptr(pmap, e->efi_memdesc_size, i); - /* - * Here we are more conservative in picking free memory than - * the EFI spec allows: - * - * According to the spec, EFI_BOOT_SERVICES_{CODE|DATA} are also - * free memory and thus available to place the kernel image into, - * but in practice there's firmware where using that memory leads - * to crashes. - * - * Only EFI_CONVENTIONAL_MEMORY is guaranteed to be free. - */ - if (md->type != EFI_CONVENTIONAL_MEMORY) + if (!memory_type_is_free(md)) continue; if (efi_soft_reserve_enabled() && diff --git a/arch/x86/boot/compressed/mem.c b/arch/x86/boot/compressed/mem.c new file mode 100644 index 0000000000000000000000000000000000000000..3c1609245f2add2baaade4820dcfdd3be3285dc2 --- /dev/null +++ b/arch/x86/boot/compressed/mem.c @@ -0,0 +1,86 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include "error.h" +#include "misc.h" +#include "tdx.h" +#include "sev.h" +#include + +/* + * accept_memory() and process_unaccepted_memory() called from EFI stub which + * runs before decompresser and its early_tdx_detect(). + * + * Enumerate TDX directly from the early users. + */ +static bool early_is_tdx_guest(void) +{ + static bool once; + static bool is_tdx; + + if (!IS_ENABLED(CONFIG_INTEL_TDX_GUEST)) + return false; + + if (!once) { + u32 eax, sig[3]; + + cpuid_count(TDX_CPUID_LEAF_ID, 0, &eax, + &sig[0], &sig[2], &sig[1]); + is_tdx = !memcmp(TDX_IDENT, sig, sizeof(sig)); + once = true; + } + + return is_tdx; +} + +void arch_accept_memory(phys_addr_t start, phys_addr_t end) +{ + /* Platform-specific memory-acceptance call goes here */ + if (early_is_tdx_guest()) { + if (!tdx_accept_memory(start, end)) + panic("TDX: Failed to accept memory\n"); + } else if (sev_snp_enabled()) { + snp_accept_memory(start, end); + } else { + error("Cannot accept memory: unknown platform\n"); + } +} + +bool init_unaccepted_memory(void) +{ + guid_t guid = LINUX_EFI_UNACCEPTED_MEM_TABLE_GUID; + struct efi_unaccepted_memory *table; + unsigned long cfg_table_pa; + unsigned int cfg_table_len; + enum efi_type et; + int ret; + + et = efi_get_type(boot_params); + if (et == EFI_TYPE_NONE) + return false; + + ret = efi_get_conf_table(boot_params, &cfg_table_pa, &cfg_table_len); + if (ret) { + warn("EFI config table not found."); + return false; + } + + table = (void *)efi_find_vendor_table(boot_params, cfg_table_pa, + cfg_table_len, guid); + if (!table) + return false; + + if (table->version != 1) + error("Unknown version of unaccepted memory table\n"); + + /* + * In many cases unaccepted_table is already set by EFI stub, but it + * has to be initialized again to cover cases when the table is not + * allocated by EFI stub or EFI stub copied the kernel image with + * efi_relocate_kernel() before the variable is set. + * + * It must be initialized before the first usage of accept_memory(). + */ + unaccepted_table = table; + + return true; +} diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c index 014ff222bf4b35c2031e71938b913e368b64495f..94b7abcf624b3b55fd8ebbd898524d2a9afd298e 100644 --- a/arch/x86/boot/compressed/misc.c +++ b/arch/x86/boot/compressed/misc.c @@ -455,6 +455,12 @@ asmlinkage __visible void *extract_kernel(void *rmode, memptr heap, #endif debug_putstr("\nDecompressing Linux... "); + + if (init_unaccepted_memory()) { + debug_putstr("Accepting memory... "); + accept_memory(__pa(output), __pa(output) + needed_size); + } + __decompress(input_data, input_len, NULL, NULL, output, output_len, NULL, error); entry_offset = parse_elf(output); diff --git a/arch/x86/boot/compressed/misc.h b/arch/x86/boot/compressed/misc.h index 2f155a0e3041bb1561c73fe37d410724b84e1bde..964fe903a1cdccdce962ae7b3a51b15c639de0a4 100644 --- a/arch/x86/boot/compressed/misc.h +++ b/arch/x86/boot/compressed/misc.h @@ -247,4 +247,14 @@ static inline unsigned long efi_find_vendor_table(struct boot_params *bp, } #endif /* CONFIG_EFI */ +#ifdef CONFIG_UNACCEPTED_MEMORY +bool init_unaccepted_memory(void); +#else +static inline bool init_unaccepted_memory(void) { return false; } +#endif + +/* Defined in EFI stub */ +extern struct efi_unaccepted_memory *unaccepted_table; +void accept_memory(phys_addr_t start, phys_addr_t end); + #endif /* BOOT_COMPRESSED_MISC_H */ diff --git a/arch/x86/boot/compressed/sev.c b/arch/x86/boot/compressed/sev.c index 014b89c890887b9a881f698f8a4b83b7f75823e4..09dc8c187b3cc75236f0772311f3b9f13950a3f2 100644 --- a/arch/x86/boot/compressed/sev.c +++ b/arch/x86/boot/compressed/sev.c @@ -115,7 +115,7 @@ static enum es_result vc_read_mem(struct es_em_ctxt *ctxt, /* Include code for early handlers */ #include "../../kernel/sev-shared.c" -static inline bool sev_snp_enabled(void) +bool sev_snp_enabled(void) { return sev_status & MSR_AMD64_SEV_SNP_ENABLED; } @@ -181,6 +181,58 @@ static bool early_setup_ghcb(void) return true; } +static phys_addr_t __snp_accept_memory(struct snp_psc_desc *desc, + phys_addr_t pa, phys_addr_t pa_end) +{ + struct psc_hdr *hdr; + struct psc_entry *e; + unsigned int i; + + hdr = &desc->hdr; + memset(hdr, 0, sizeof(*hdr)); + + e = desc->entries; + + i = 0; + while (pa < pa_end && i < VMGEXIT_PSC_MAX_ENTRY) { + hdr->end_entry = i; + + e->gfn = pa >> PAGE_SHIFT; + e->operation = SNP_PAGE_STATE_PRIVATE; + if (IS_ALIGNED(pa, PMD_SIZE) && (pa_end - pa) >= PMD_SIZE) { + e->pagesize = RMP_PG_SIZE_2M; + pa += PMD_SIZE; + } else { + e->pagesize = RMP_PG_SIZE_4K; + pa += PAGE_SIZE; + } + + e++; + i++; + } + + if (vmgexit_psc(boot_ghcb, desc)) + sev_es_terminate(SEV_TERM_SET_LINUX, GHCB_TERM_PSC); + + pvalidate_pages(desc); + + return pa; +} + +void snp_accept_memory(phys_addr_t start, phys_addr_t end) +{ + struct snp_psc_desc desc = {}; + unsigned int i; + phys_addr_t pa; + + if (!boot_ghcb && !early_setup_ghcb()) + sev_es_terminate(SEV_TERM_SET_LINUX, GHCB_TERM_PSC); + + pa = start; + while (pa < end) + pa = __snp_accept_memory(&desc, pa, end); +} + void sev_es_shutdown_ghcb(void) { if (!boot_ghcb) diff --git a/arch/x86/boot/compressed/sev.h b/arch/x86/boot/compressed/sev.h new file mode 100644 index 0000000000000000000000000000000000000000..fc725a981b093b56b27207e40b911404de06374e --- /dev/null +++ b/arch/x86/boot/compressed/sev.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * AMD SEV header for early boot related functions. + * + * Author: Tom Lendacky + */ + +#ifndef BOOT_COMPRESSED_SEV_H +#define BOOT_COMPRESSED_SEV_H + +#ifdef CONFIG_AMD_MEM_ENCRYPT + +bool sev_snp_enabled(void); +void snp_accept_memory(phys_addr_t start, phys_addr_t end); + +#else + +static inline bool sev_snp_enabled(void) { return false; } +static inline void snp_accept_memory(phys_addr_t start, phys_addr_t end) { } + +#endif + +#endif diff --git a/arch/x86/boot/compressed/tdx-shared.c b/arch/x86/boot/compressed/tdx-shared.c new file mode 100644 index 0000000000000000000000000000000000000000..5ac43762fe13c17e0c23bdd936f8dc3494e97ee5 --- /dev/null +++ b/arch/x86/boot/compressed/tdx-shared.c @@ -0,0 +1,2 @@ +#include "error.h" +#include "../../coco/tdx/tdx-shared.c" diff --git a/arch/x86/boot/compressed/tdx.c b/arch/x86/boot/compressed/tdx.c index 2d81d3cc72a1fa1e5633fd121f40e9d45536c90b..8841b945a1e262994e07245066bf0be0c2dbdb34 100644 --- a/arch/x86/boot/compressed/tdx.c +++ b/arch/x86/boot/compressed/tdx.c @@ -20,7 +20,7 @@ static inline unsigned int tdx_io_in(int size, u16 port) { struct tdx_hypercall_args args = { .r10 = TDX_HYPERCALL_STANDARD, - .r11 = EXIT_REASON_IO_INSTRUCTION, + .r11 = hcall_func(EXIT_REASON_IO_INSTRUCTION), .r12 = size, .r13 = 0, .r14 = port, @@ -36,7 +36,7 @@ static inline void tdx_io_out(int size, u16 port, u32 value) { struct tdx_hypercall_args args = { .r10 = TDX_HYPERCALL_STANDARD, - .r11 = EXIT_REASON_IO_INSTRUCTION, + .r11 = hcall_func(EXIT_REASON_IO_INSTRUCTION), .r12 = size, .r13 = 1, .r14 = port, diff --git a/arch/x86/boot/cpu.c b/arch/x86/boot/cpu.c index 0bbf4f3707d221360b7f0398ac2e427e52d7677e..feb6dbd7ca86004db8837a236f2b069f18345495 100644 --- a/arch/x86/boot/cpu.c +++ b/arch/x86/boot/cpu.c @@ -14,9 +14,7 @@ */ #include "boot.h" -#ifdef CONFIG_X86_FEATURE_NAMES #include "cpustr.h" -#endif static char *cpu_name(int level) { @@ -35,7 +33,6 @@ static char *cpu_name(int level) static void show_cap_strs(u32 *err_flags) { int i, j; -#ifdef CONFIG_X86_FEATURE_NAMES const unsigned char *msg_strs = (const unsigned char *)x86_cap_strs; for (i = 0; i < NCAPINTS; i++) { u32 e = err_flags[i]; @@ -58,16 +55,6 @@ static void show_cap_strs(u32 *err_flags) e >>= 1; } } -#else - for (i = 0; i < NCAPINTS; i++) { - u32 e = err_flags[i]; - for (j = 0; j < 32; j++) { - if (e & 1) - printf("%d:%d ", i, j); - e >>= 1; - } - } -#endif } int validate_cpu(void) diff --git a/arch/x86/coco/core.c b/arch/x86/coco/core.c index 73f83233d25df8481b322456039b49b0f108699f..eeec9986570ed05a5a0d686898139e26fcf0f228 100644 --- a/arch/x86/coco/core.c +++ b/arch/x86/coco/core.c @@ -13,10 +13,10 @@ #include #include -enum cc_vendor cc_vendor __ro_after_init; +enum cc_vendor cc_vendor __ro_after_init = CC_VENDOR_NONE; static u64 cc_mask __ro_after_init; -static bool intel_cc_platform_has(enum cc_attr attr) +static bool noinstr intel_cc_platform_has(enum cc_attr attr) { switch (attr) { case CC_ATTR_GUEST_UNROLL_STRING_IO: @@ -34,7 +34,7 @@ static bool intel_cc_platform_has(enum cc_attr attr) * the other levels of SME/SEV functionality, including C-bit * based SEV-SNP, are not enabled. */ -static __maybe_unused bool amd_cc_platform_vtom(enum cc_attr attr) +static __maybe_unused __always_inline bool amd_cc_platform_vtom(enum cc_attr attr) { switch (attr) { case CC_ATTR_GUEST_MEM_ENCRYPT: @@ -58,7 +58,7 @@ static __maybe_unused bool amd_cc_platform_vtom(enum cc_attr attr) * the trampoline area must be encrypted. */ -static bool amd_cc_platform_has(enum cc_attr attr) +static bool noinstr amd_cc_platform_has(enum cc_attr attr) { #ifdef CONFIG_AMD_MEM_ENCRYPT @@ -97,7 +97,7 @@ static bool amd_cc_platform_has(enum cc_attr attr) #endif } -bool cc_platform_has(enum cc_attr attr) +bool noinstr cc_platform_has(enum cc_attr attr) { switch (cc_vendor) { case CC_VENDOR_AMD: diff --git a/arch/x86/coco/tdx/Makefile b/arch/x86/coco/tdx/Makefile index 46c55998557daf385f32d63733b530ea189e88be..2c7dcbf1458b054e06578e7b80fef018f898d309 100644 --- a/arch/x86/coco/tdx/Makefile +++ b/arch/x86/coco/tdx/Makefile @@ -1,3 +1,3 @@ # SPDX-License-Identifier: GPL-2.0 -obj-y += tdx.o tdcall.o +obj-y += tdx.o tdx-shared.o tdcall.o diff --git a/arch/x86/coco/tdx/tdx-shared.c b/arch/x86/coco/tdx/tdx-shared.c new file mode 100644 index 0000000000000000000000000000000000000000..ef20ddc37b58aa2f505e0ef36d0fd8c1b28e0947 --- /dev/null +++ b/arch/x86/coco/tdx/tdx-shared.c @@ -0,0 +1,71 @@ +#include +#include + +static unsigned long try_accept_one(phys_addr_t start, unsigned long len, + enum pg_level pg_level) +{ + unsigned long accept_size = page_level_size(pg_level); + u64 tdcall_rcx; + u8 page_size; + + if (!IS_ALIGNED(start, accept_size)) + return 0; + + if (len < accept_size) + return 0; + + /* + * Pass the page physical address to the TDX module to accept the + * pending, private page. + * + * Bits 2:0 of RCX encode page size: 0 - 4K, 1 - 2M, 2 - 1G. + */ + switch (pg_level) { + case PG_LEVEL_4K: + page_size = 0; + break; + case PG_LEVEL_2M: + page_size = 1; + break; + case PG_LEVEL_1G: + page_size = 2; + break; + default: + return 0; + } + + tdcall_rcx = start | page_size; + if (__tdx_module_call(TDX_ACCEPT_PAGE, tdcall_rcx, 0, 0, 0, NULL)) + return 0; + + return accept_size; +} + +bool tdx_accept_memory(phys_addr_t start, phys_addr_t end) +{ + /* + * For shared->private conversion, accept the page using + * TDX_ACCEPT_PAGE TDX module call. + */ + while (start < end) { + unsigned long len = end - start; + unsigned long accept_size; + + /* + * Try larger accepts first. It gives chance to VMM to keep + * 1G/2M Secure EPT entries where possible and speeds up + * process by cutting number of hypercalls (if successful). + */ + + accept_size = try_accept_one(start, len, PG_LEVEL_1G); + if (!accept_size) + accept_size = try_accept_one(start, len, PG_LEVEL_2M); + if (!accept_size) + accept_size = try_accept_one(start, len, PG_LEVEL_4K); + if (!accept_size) + return false; + start += accept_size; + } + + return true; +} diff --git a/arch/x86/coco/tdx/tdx.c b/arch/x86/coco/tdx/tdx.c index e146b599260f81a2525c3eeb6823a532457a0272..1d6b863c42b001c8c28c8bc36bc94b318c9df0d7 100644 --- a/arch/x86/coco/tdx/tdx.c +++ b/arch/x86/coco/tdx/tdx.c @@ -14,20 +14,6 @@ #include #include -/* TDX module Call Leaf IDs */ -#define TDX_GET_INFO 1 -#define TDX_GET_VEINFO 3 -#define TDX_GET_REPORT 4 -#define TDX_ACCEPT_PAGE 6 -#define TDX_WR 8 - -/* TDCS fields. To be used by TDG.VM.WR and TDG.VM.RD module calls */ -#define TDCS_NOTIFY_ENABLES 0x9100000000000010 - -/* TDX hypercall Leaf IDs */ -#define TDVMCALL_MAP_GPA 0x10001 -#define TDVMCALL_REPORT_FATAL_ERROR 0x10003 - /* MMIO direction */ #define EPT_READ 0 #define EPT_WRITE 1 @@ -51,24 +37,6 @@ #define TDREPORT_SUBTYPE_0 0 -/* - * Wrapper for standard use of __tdx_hypercall with no output aside from - * return code. - */ -static inline u64 _tdx_hypercall(u64 fn, u64 r12, u64 r13, u64 r14, u64 r15) -{ - struct tdx_hypercall_args args = { - .r10 = TDX_HYPERCALL_STANDARD, - .r11 = fn, - .r12 = r12, - .r13 = r13, - .r14 = r14, - .r15 = r15, - }; - - return __tdx_hypercall(&args); -} - /* Called from __tdx_hypercall() for unrecoverable failure */ noinstr void __tdx_hypercall_failed(void) { @@ -76,17 +44,6 @@ noinstr void __tdx_hypercall_failed(void) panic("TDVMCALL failed. TDX module bug?"); } -/* - * The TDG.VP.VMCALL-Instruction-execution sub-functions are defined - * independently from but are currently matched 1:1 with VMX EXIT_REASONs. - * Reusing the KVM EXIT_REASON macros makes it easier to connect the host and - * guest sides of these calls. - */ -static __always_inline u64 hcall_func(u64 exit_reason) -{ - return exit_reason; -} - #ifdef CONFIG_KVM_GUEST long tdx_kvm_hypercall(unsigned int nr, unsigned long p1, unsigned long p2, unsigned long p3, unsigned long p4) @@ -745,47 +702,6 @@ static bool tdx_cache_flush_required(void) return true; } -static bool try_accept_one(phys_addr_t *start, unsigned long len, - enum pg_level pg_level) -{ - unsigned long accept_size = page_level_size(pg_level); - u64 tdcall_rcx; - u8 page_size; - - if (!IS_ALIGNED(*start, accept_size)) - return false; - - if (len < accept_size) - return false; - - /* - * Pass the page physical address to the TDX module to accept the - * pending, private page. - * - * Bits 2:0 of RCX encode page size: 0 - 4K, 1 - 2M, 2 - 1G. - */ - switch (pg_level) { - case PG_LEVEL_4K: - page_size = 0; - break; - case PG_LEVEL_2M: - page_size = 1; - break; - case PG_LEVEL_1G: - page_size = 2; - break; - default: - return false; - } - - tdcall_rcx = *start | page_size; - if (__tdx_module_call(TDX_ACCEPT_PAGE, tdcall_rcx, 0, 0, 0, NULL)) - return false; - - *start += accept_size; - return true; -} - /* * Inform the VMM of the guest's intent for this physical page: shared with * the VMM or private to the guest. The VMM is expected to change its mapping @@ -810,33 +726,34 @@ static bool tdx_enc_status_changed(unsigned long vaddr, int numpages, bool enc) if (_tdx_hypercall(TDVMCALL_MAP_GPA, start, end - start, 0, 0)) return false; - /* private->shared conversion requires only MapGPA call */ - if (!enc) - return true; + /* shared->private conversion requires memory to be accepted before use */ + if (enc) + return tdx_accept_memory(start, end); + + return true; +} +static bool tdx_enc_status_change_prepare(unsigned long vaddr, int numpages, + bool enc) +{ /* - * For shared->private conversion, accept the page using - * TDX_ACCEPT_PAGE TDX module call. + * Only handle shared->private conversion here. + * See the comment in tdx_early_init(). */ - while (start < end) { - unsigned long len = end - start; - - /* - * Try larger accepts first. It gives chance to VMM to keep - * 1G/2M SEPT entries where possible and speeds up process by - * cutting number of hypercalls (if successful). - */ - - if (try_accept_one(&start, len, PG_LEVEL_1G)) - continue; - - if (try_accept_one(&start, len, PG_LEVEL_2M)) - continue; - - if (!try_accept_one(&start, len, PG_LEVEL_4K)) - return false; - } + if (enc) + return tdx_enc_status_changed(vaddr, numpages, enc); + return true; +} +static bool tdx_enc_status_change_finish(unsigned long vaddr, int numpages, + bool enc) +{ + /* + * Only handle private->shared conversion here. + * See the comment in tdx_early_init(). + */ + if (!enc) + return tdx_enc_status_changed(vaddr, numpages, enc); return true; } @@ -852,7 +769,7 @@ void __init tdx_early_init(void) setup_force_cpu_cap(X86_FEATURE_TDX_GUEST); - cc_set_vendor(CC_VENDOR_INTEL); + cc_vendor = CC_VENDOR_INTEL; tdx_parse_tdinfo(&cc_mask); cc_set_mask(cc_mask); @@ -867,9 +784,41 @@ void __init tdx_early_init(void) */ physical_mask &= cc_mask - 1; - x86_platform.guest.enc_cache_flush_required = tdx_cache_flush_required; - x86_platform.guest.enc_tlb_flush_required = tdx_tlb_flush_required; - x86_platform.guest.enc_status_change_finish = tdx_enc_status_changed; + /* + * The kernel mapping should match the TDX metadata for the page. + * load_unaligned_zeropad() can touch memory *adjacent* to that which is + * owned by the caller and can catch even _momentary_ mismatches. Bad + * things happen on mismatch: + * + * - Private mapping => Shared Page == Guest shutdown + * - Shared mapping => Private Page == Recoverable #VE + * + * guest.enc_status_change_prepare() converts the page from + * shared=>private before the mapping becomes private. + * + * guest.enc_status_change_finish() converts the page from + * private=>shared after the mapping becomes private. + * + * In both cases there is a temporary shared mapping to a private page, + * which can result in a #VE. But, there is never a private mapping to + * a shared page. + */ + x86_platform.guest.enc_status_change_prepare = tdx_enc_status_change_prepare; + x86_platform.guest.enc_status_change_finish = tdx_enc_status_change_finish; + + x86_platform.guest.enc_cache_flush_required = tdx_cache_flush_required; + x86_platform.guest.enc_tlb_flush_required = tdx_tlb_flush_required; + + /* + * TDX intercepts the RDMSR to read the X2APIC ID in the parallel + * bringup low level code. That raises #VE which cannot be handled + * there. + * + * Intel-TDX has a secure RDMSR hypercall, but that needs to be + * implemented seperately in the low level startup ASM code. + * Until that is in place, disable parallel bringup for TDX. + */ + x86_cpuinit.parallel_bringup = false; pr_info("Guest detected\n"); } diff --git a/arch/x86/entry/entry_32.S b/arch/x86/entry/entry_32.S index 91397f58ac3008556fc0cfbb2437eee45da706ff..6e6af42e044a20cf0aec1115406c546ebcb3bbab 100644 --- a/arch/x86/entry/entry_32.S +++ b/arch/x86/entry/entry_32.S @@ -719,26 +719,6 @@ SYM_CODE_START(__switch_to_asm) SYM_CODE_END(__switch_to_asm) .popsection -/* - * The unwinder expects the last frame on the stack to always be at the same - * offset from the end of the page, which allows it to validate the stack. - * Calling schedule_tail() directly would break that convention because its an - * asmlinkage function so its argument has to be pushed on the stack. This - * wrapper creates a proper "end of stack" frame header before the call. - */ -.pushsection .text, "ax" -SYM_FUNC_START(schedule_tail_wrapper) - FRAME_BEGIN - - pushl %eax - call schedule_tail - popl %eax - - FRAME_END - RET -SYM_FUNC_END(schedule_tail_wrapper) -.popsection - /* * A newly forked process directly context switches into this address. * @@ -747,29 +727,22 @@ SYM_FUNC_END(schedule_tail_wrapper) * edi: kernel thread arg */ .pushsection .text, "ax" -SYM_CODE_START(ret_from_fork) - call schedule_tail_wrapper +SYM_CODE_START(ret_from_fork_asm) + movl %esp, %edx /* regs */ - testl %ebx, %ebx - jnz 1f /* kernel threads are uncommon */ + /* return address for the stack unwinder */ + pushl $.Lsyscall_32_done -2: - /* When we fork, we trace the syscall return in the child, too. */ - movl %esp, %eax - call syscall_exit_to_user_mode - jmp .Lsyscall_32_done + FRAME_BEGIN + /* prev already in EAX */ + movl %ebx, %ecx /* fn */ + pushl %edi /* fn_arg */ + call ret_from_fork + addl $4, %esp + FRAME_END - /* kernel thread */ -1: movl %edi, %eax - CALL_NOSPEC ebx - /* - * A kernel thread is allowed to return here after successfully - * calling kernel_execve(). Exit to userspace to complete the execve() - * syscall. - */ - movl $0, PT_EAX(%esp) - jmp 2b -SYM_CODE_END(ret_from_fork) + RET +SYM_CODE_END(ret_from_fork_asm) .popsection SYM_ENTRY(__begin_SYSENTER_singlestep_region, SYM_L_GLOBAL, SYM_A_NONE) diff --git a/arch/x86/entry/entry_64.S b/arch/x86/entry/entry_64.S index f31e286c297737d77d44a98b9526384ddbae273b..91f6818884fa3b39b61a7de2fb51ffa3e8c38136 100644 --- a/arch/x86/entry/entry_64.S +++ b/arch/x86/entry/entry_64.S @@ -284,36 +284,19 @@ SYM_FUNC_END(__switch_to_asm) * r12: kernel thread arg */ .pushsection .text, "ax" - __FUNC_ALIGN -SYM_CODE_START_NOALIGN(ret_from_fork) - UNWIND_HINT_END_OF_STACK +SYM_CODE_START(ret_from_fork_asm) + UNWIND_HINT_REGS ANNOTATE_NOENDBR // copy_thread CALL_DEPTH_ACCOUNT - movq %rax, %rdi - call schedule_tail /* rdi: 'prev' task parameter */ - testq %rbx, %rbx /* from kernel_thread? */ - jnz 1f /* kernel threads are uncommon */ + movq %rax, %rdi /* prev */ + movq %rsp, %rsi /* regs */ + movq %rbx, %rdx /* fn */ + movq %r12, %rcx /* fn_arg */ + call ret_from_fork -2: - UNWIND_HINT_REGS - movq %rsp, %rdi - call syscall_exit_to_user_mode /* returns with IRQs disabled */ jmp swapgs_restore_regs_and_return_to_usermode - -1: - /* kernel thread */ - UNWIND_HINT_END_OF_STACK - movq %r12, %rdi - CALL_NOSPEC rbx - /* - * A kernel thread is allowed to return here after successfully - * calling kernel_execve(). Exit to userspace to complete the execve() - * syscall. - */ - movq $0, RAX(%rsp) - jmp 2b -SYM_CODE_END(ret_from_fork) +SYM_CODE_END(ret_from_fork_asm) .popsection .macro DEBUG_ENTRY_ASSERT_IRQS_OFF diff --git a/arch/x86/entry/syscalls/syscall_32.tbl b/arch/x86/entry/syscalls/syscall_32.tbl index 320480a8db4f834dfee790b9a41e5516a88674f6..bc0a3c941b35c850354fa456ed8aba161dba5d87 100644 --- a/arch/x86/entry/syscalls/syscall_32.tbl +++ b/arch/x86/entry/syscalls/syscall_32.tbl @@ -455,3 +455,4 @@ 448 i386 process_mrelease sys_process_mrelease 449 i386 futex_waitv sys_futex_waitv 450 i386 set_mempolicy_home_node sys_set_mempolicy_home_node +451 i386 cachestat sys_cachestat diff --git a/arch/x86/entry/syscalls/syscall_64.tbl b/arch/x86/entry/syscalls/syscall_64.tbl index c84d12608cd2de9e45f6cc166169cf70ecbf7518..227538b0ce801eeba96e10d8214e7847b77cee88 100644 --- a/arch/x86/entry/syscalls/syscall_64.tbl +++ b/arch/x86/entry/syscalls/syscall_64.tbl @@ -372,6 +372,7 @@ 448 common process_mrelease sys_process_mrelease 449 common futex_waitv sys_futex_waitv 450 common set_mempolicy_home_node sys_set_mempolicy_home_node +451 common cachestat sys_cachestat # # Due to a historical design error, certain syscalls are numbered differently diff --git a/arch/x86/entry/thunk_64.S b/arch/x86/entry/thunk_64.S index 5e37f41e5f14d483283c8dc81f30463ff228be4b..27b5da2111ac9eb6d7681a79706f7e0c64a7f38b 100644 --- a/arch/x86/entry/thunk_64.S +++ b/arch/x86/entry/thunk_64.S @@ -26,17 +26,7 @@ SYM_FUNC_START(\name) pushq %r11 call \func - jmp __thunk_restore -SYM_FUNC_END(\name) - _ASM_NOKPROBE(\name) - .endm - - THUNK preempt_schedule_thunk, preempt_schedule - THUNK preempt_schedule_notrace_thunk, preempt_schedule_notrace - EXPORT_SYMBOL(preempt_schedule_thunk) - EXPORT_SYMBOL(preempt_schedule_notrace_thunk) -SYM_CODE_START_LOCAL(__thunk_restore) popq %r11 popq %r10 popq %r9 @@ -48,5 +38,11 @@ SYM_CODE_START_LOCAL(__thunk_restore) popq %rdi popq %rbp RET - _ASM_NOKPROBE(__thunk_restore) -SYM_CODE_END(__thunk_restore) +SYM_FUNC_END(\name) + _ASM_NOKPROBE(\name) + .endm + +THUNK preempt_schedule_thunk, preempt_schedule +THUNK preempt_schedule_notrace_thunk, preempt_schedule_notrace +EXPORT_SYMBOL(preempt_schedule_thunk) +EXPORT_SYMBOL(preempt_schedule_notrace_thunk) diff --git a/arch/x86/entry/vdso/vgetcpu.c b/arch/x86/entry/vdso/vgetcpu.c index 0a9007c2405680350523fb0b267cfda28f78cd31..e4640306b2e3c95d74d73037ab6b09294b8e1d6c 100644 --- a/arch/x86/entry/vdso/vgetcpu.c +++ b/arch/x86/entry/vdso/vgetcpu.c @@ -8,6 +8,7 @@ #include #include #include +#include notrace long __vdso_getcpu(unsigned *cpu, unsigned *node, struct getcpu_cache *unused) diff --git a/arch/x86/events/amd/core.c b/arch/x86/events/amd/core.c index bccea57dee81ecd12caac3ecc7a2cbe654d9fe90..abadd5f234254ce053c08d49381eb3ec9410958e 100644 --- a/arch/x86/events/amd/core.c +++ b/arch/x86/events/amd/core.c @@ -374,7 +374,7 @@ static int amd_pmu_hw_config(struct perf_event *event) /* pass precise event sampling to ibs: */ if (event->attr.precise_ip && get_ibs_caps()) - return -ENOENT; + return forward_event_to_ibs(event); if (has_branch_stack(event) && !x86_pmu.lbr_nr) return -EOPNOTSUPP; diff --git a/arch/x86/events/amd/ibs.c b/arch/x86/events/amd/ibs.c index 64582954b5f675597503ee747182f6cea162f48b..371014802191670e2697925e7e90e64e8cdb2530 100644 --- a/arch/x86/events/amd/ibs.c +++ b/arch/x86/events/amd/ibs.c @@ -190,7 +190,7 @@ static struct perf_ibs *get_ibs_pmu(int type) } /* - * Use IBS for precise event sampling: + * core pmu config -> IBS config * * perf record -a -e cpu-cycles:p ... # use ibs op counting cycle count * perf record -a -e r076:p ... # same as -e cpu-cycles:p @@ -199,25 +199,9 @@ static struct perf_ibs *get_ibs_pmu(int type) * IbsOpCntCtl (bit 19) of IBS Execution Control Register (IbsOpCtl, * MSRC001_1033) is used to select either cycle or micro-ops counting * mode. - * - * The rip of IBS samples has skid 0. Thus, IBS supports precise - * levels 1 and 2 and the PERF_EFLAGS_EXACT is set. In rare cases the - * rip is invalid when IBS was not able to record the rip correctly. - * We clear PERF_EFLAGS_EXACT and take the rip from pt_regs then. - * */ -static int perf_ibs_precise_event(struct perf_event *event, u64 *config) +static int core_pmu_ibs_config(struct perf_event *event, u64 *config) { - switch (event->attr.precise_ip) { - case 0: - return -ENOENT; - case 1: - case 2: - break; - default: - return -EOPNOTSUPP; - } - switch (event->attr.type) { case PERF_TYPE_HARDWARE: switch (event->attr.config) { @@ -243,22 +227,37 @@ static int perf_ibs_precise_event(struct perf_event *event, u64 *config) return -EOPNOTSUPP; } +/* + * The rip of IBS samples has skid 0. Thus, IBS supports precise + * levels 1 and 2 and the PERF_EFLAGS_EXACT is set. In rare cases the + * rip is invalid when IBS was not able to record the rip correctly. + * We clear PERF_EFLAGS_EXACT and take the rip from pt_regs then. + */ +int forward_event_to_ibs(struct perf_event *event) +{ + u64 config = 0; + + if (!event->attr.precise_ip || event->attr.precise_ip > 2) + return -EOPNOTSUPP; + + if (!core_pmu_ibs_config(event, &config)) { + event->attr.type = perf_ibs_op.pmu.type; + event->attr.config = config; + } + return -ENOENT; +} + static int perf_ibs_init(struct perf_event *event) { struct hw_perf_event *hwc = &event->hw; struct perf_ibs *perf_ibs; u64 max_cnt, config; - int ret; perf_ibs = get_ibs_pmu(event->attr.type); - if (perf_ibs) { - config = event->attr.config; - } else { - perf_ibs = &perf_ibs_op; - ret = perf_ibs_precise_event(event, &config); - if (ret) - return ret; - } + if (!perf_ibs) + return -ENOENT; + + config = event->attr.config; if (event->pmu != &perf_ibs->pmu) return -ENOENT; diff --git a/arch/x86/events/intel/core.c b/arch/x86/events/intel/core.c index 89b9c1cebb613a89865909cfe7e322f93f5abe10..2a284ba951b76ac513f71dd89a2456a19125d965 100644 --- a/arch/x86/events/intel/core.c +++ b/arch/x86/events/intel/core.c @@ -349,6 +349,16 @@ static struct event_constraint intel_spr_event_constraints[] = { EVENT_CONSTRAINT_END }; +static struct extra_reg intel_gnr_extra_regs[] __read_mostly = { + INTEL_UEVENT_EXTRA_REG(0x012a, MSR_OFFCORE_RSP_0, 0x3fffffffffull, RSP_0), + INTEL_UEVENT_EXTRA_REG(0x012b, MSR_OFFCORE_RSP_1, 0x3fffffffffull, RSP_1), + INTEL_UEVENT_PEBS_LDLAT_EXTRA_REG(0x01cd), + INTEL_UEVENT_EXTRA_REG(0x02c6, MSR_PEBS_FRONTEND, 0x9, FE), + INTEL_UEVENT_EXTRA_REG(0x03c6, MSR_PEBS_FRONTEND, 0x7fff1f, FE), + INTEL_UEVENT_EXTRA_REG(0x40ad, MSR_PEBS_FRONTEND, 0x7, FE), + INTEL_UEVENT_EXTRA_REG(0x04c2, MSR_PEBS_FRONTEND, 0x8, FE), + EVENT_EXTRA_END +}; EVENT_ATTR_STR(mem-loads, mem_ld_nhm, "event=0x0b,umask=0x10,ldlat=3"); EVENT_ATTR_STR(mem-loads, mem_ld_snb, "event=0xcd,umask=0x1,ldlat=3"); @@ -2451,7 +2461,7 @@ static void intel_pmu_disable_fixed(struct perf_event *event) intel_clear_masks(event, idx); - mask = 0xfULL << ((idx - INTEL_PMC_IDX_FIXED) * 4); + mask = intel_fixed_bits_by_idx(idx - INTEL_PMC_IDX_FIXED, INTEL_FIXED_BITS_MASK); cpuc->fixed_ctrl_val &= ~mask; } @@ -2750,25 +2760,25 @@ static void intel_pmu_enable_fixed(struct perf_event *event) * if requested: */ if (!event->attr.precise_ip) - bits |= 0x8; + bits |= INTEL_FIXED_0_ENABLE_PMI; if (hwc->config & ARCH_PERFMON_EVENTSEL_USR) - bits |= 0x2; + bits |= INTEL_FIXED_0_USER; if (hwc->config & ARCH_PERFMON_EVENTSEL_OS) - bits |= 0x1; + bits |= INTEL_FIXED_0_KERNEL; /* * ANY bit is supported in v3 and up */ if (x86_pmu.version > 2 && hwc->config & ARCH_PERFMON_EVENTSEL_ANY) - bits |= 0x4; + bits |= INTEL_FIXED_0_ANYTHREAD; idx -= INTEL_PMC_IDX_FIXED; - bits <<= (idx * 4); - mask = 0xfULL << (idx * 4); + bits = intel_fixed_bits_by_idx(idx, bits); + mask = intel_fixed_bits_by_idx(idx, INTEL_FIXED_BITS_MASK); if (x86_pmu.intel_cap.pebs_baseline && event->attr.precise_ip) { - bits |= ICL_FIXED_0_ADAPTIVE << (idx * 4); - mask |= ICL_FIXED_0_ADAPTIVE << (idx * 4); + bits |= intel_fixed_bits_by_idx(idx, ICL_FIXED_0_ADAPTIVE); + mask |= intel_fixed_bits_by_idx(idx, ICL_FIXED_0_ADAPTIVE); } cpuc->fixed_ctrl_val &= ~mask; @@ -3983,6 +3993,13 @@ static int intel_pmu_hw_config(struct perf_event *event) struct perf_event *leader = event->group_leader; struct perf_event *sibling = NULL; + /* + * When this memload event is also the first event (no group + * exists yet), then there is no aux event before it. + */ + if (leader == event) + return -ENODATA; + if (!is_mem_loads_aux_event(leader)) { for_each_sibling_event(sibling, leader) { if (is_mem_loads_aux_event(sibling)) @@ -6496,6 +6513,7 @@ __init int intel_pmu_init(void) case INTEL_FAM6_SAPPHIRERAPIDS_X: case INTEL_FAM6_EMERALDRAPIDS_X: x86_pmu.flags |= PMU_FL_MEM_LOADS_AUX; + x86_pmu.extra_regs = intel_spr_extra_regs; fallthrough; case INTEL_FAM6_GRANITERAPIDS_X: case INTEL_FAM6_GRANITERAPIDS_D: @@ -6506,7 +6524,8 @@ __init int intel_pmu_init(void) x86_pmu.event_constraints = intel_spr_event_constraints; x86_pmu.pebs_constraints = intel_spr_pebs_event_constraints; - x86_pmu.extra_regs = intel_spr_extra_regs; + if (!x86_pmu.extra_regs) + x86_pmu.extra_regs = intel_gnr_extra_regs; x86_pmu.limit_period = spr_limit_period; x86_pmu.pebs_ept = 1; x86_pmu.pebs_aliases = NULL; @@ -6650,6 +6669,7 @@ __init int intel_pmu_init(void) pmu->pebs_constraints = intel_grt_pebs_event_constraints; pmu->extra_regs = intel_grt_extra_regs; if (is_mtl(boot_cpu_data.x86_model)) { + x86_pmu.hybrid_pmu[X86_HYBRID_PMU_CORE_IDX].extra_regs = intel_gnr_extra_regs; x86_pmu.pebs_latency_data = mtl_latency_data_small; extra_attr = boot_cpu_has(X86_FEATURE_RTM) ? mtl_hybrid_extra_attr_rtm : mtl_hybrid_extra_attr; diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c index a5f9474f08e123fa6c703e29ecfe2049763fd2cc..6c04b52f139b5e54ec7e3363cdd3eba3cc3a16b8 100644 --- a/arch/x86/hyperv/hv_init.c +++ b/arch/x86/hyperv/hv_init.c @@ -416,7 +416,7 @@ void __init hyperv_init(void) goto free_vp_assist_page; } - cpuhp = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "x86/hyperv_init:online", + cpuhp = cpuhp_setup_state(CPUHP_AP_HYPERV_ONLINE, "x86/hyperv_init:online", hv_cpu_init, hv_cpu_die); if (cpuhp < 0) goto free_ghcb_page; diff --git a/arch/x86/hyperv/hv_vtl.c b/arch/x86/hyperv/hv_vtl.c index 1ba5d3b99b1630bc373fe2f44cd9ffdae926b873..85d38b9f35861b65eafe3b4323bfae2f99e5fab3 100644 --- a/arch/x86/hyperv/hv_vtl.c +++ b/arch/x86/hyperv/hv_vtl.c @@ -20,6 +20,8 @@ void __init hv_vtl_init_platform(void) { pr_info("Linux runs in Hyper-V Virtual Trust Level\n"); + x86_platform.realmode_reserve = x86_init_noop; + x86_platform.realmode_init = x86_init_noop; x86_init.irqs.pre_vector_init = x86_init_noop; x86_init.timers.timer_init = x86_init_noop; diff --git a/arch/x86/hyperv/ivm.c b/arch/x86/hyperv/ivm.c index cc92388b7a999f9fde40d8691e3141eb3da984a6..14f46ad2ca644dc92ec1501d2e5d26d1e2a9697f 100644 --- a/arch/x86/hyperv/ivm.c +++ b/arch/x86/hyperv/ivm.c @@ -17,6 +17,7 @@ #include #include #include +#include #ifdef CONFIG_AMD_MEM_ENCRYPT @@ -364,7 +365,7 @@ void __init hv_vtom_init(void) * Set it here to indicate a vTOM VM. */ sev_status = MSR_AMD64_SNP_VTOM; - cc_set_vendor(CC_VENDOR_AMD); + cc_vendor = CC_VENDOR_AMD; cc_set_mask(ms_hyperv.shared_gpa_boundary); physical_mask &= ms_hyperv.shared_gpa_boundary - 1; @@ -372,6 +373,9 @@ void __init hv_vtom_init(void) x86_platform.guest.enc_cache_flush_required = hv_vtom_cache_flush_required; x86_platform.guest.enc_tlb_flush_required = hv_vtom_tlb_flush_required; x86_platform.guest.enc_status_change_finish = hv_vtom_set_host_visibility; + + /* Set WB as the default cache mode. */ + mtrr_overwrite_state(NULL, 0, MTRR_TYPE_WRBACK); } #endif /* CONFIG_AMD_MEM_ENCRYPT */ diff --git a/arch/x86/include/asm/Kbuild b/arch/x86/include/asm/Kbuild index 1e51650b79d7c87a9497ab79d9906ebae1ff83d1..4f1ce5fc4e194fc03ae6e36c03253f5f95ac1f95 100644 --- a/arch/x86/include/asm/Kbuild +++ b/arch/x86/include/asm/Kbuild @@ -1,6 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 +generated-y += orc_hash.h generated-y += syscalls_32.h generated-y += syscalls_64.h generated-y += syscalls_x32.h diff --git a/arch/x86/include/asm/alternative.h b/arch/x86/include/asm/alternative.h index d7da28fada87a35445c2c9740dda83c589a23de0..9c4da699e11aff225eac586a3bbc0598b1201a5d 100644 --- a/arch/x86/include/asm/alternative.h +++ b/arch/x86/include/asm/alternative.h @@ -96,7 +96,7 @@ extern void alternative_instructions(void); extern void apply_alternatives(struct alt_instr *start, struct alt_instr *end); extern void apply_retpolines(s32 *start, s32 *end); extern void apply_returns(s32 *start, s32 *end); -extern void apply_ibt_endbr(s32 *start, s32 *end); +extern void apply_seal_endbr(s32 *start, s32 *end); extern void apply_fineibt(s32 *start_retpoline, s32 *end_retpoine, s32 *start_cfi, s32 *end_cfi); @@ -113,7 +113,6 @@ extern void callthunks_patch_builtin_calls(void); extern void callthunks_patch_module_calls(struct callthunk_sites *sites, struct module *mod); extern void *callthunks_translate_call_dest(void *dest); -extern bool is_callthunk(void *addr); extern int x86_call_depth_emit_accounting(u8 **pprog, void *func); #else static __always_inline void callthunks_patch_builtin_calls(void) {} @@ -124,10 +123,6 @@ static __always_inline void *callthunks_translate_call_dest(void *dest) { return dest; } -static __always_inline bool is_callthunk(void *addr) -{ - return false; -} static __always_inline int x86_call_depth_emit_accounting(u8 **pprog, void *func) { diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h index 3216da7074bad80515872a72a69e75ff7add4d66..98c32aa5963a2dde146966948a402e29b6895cfb 100644 --- a/arch/x86/include/asm/apic.h +++ b/arch/x86/include/asm/apic.h @@ -55,6 +55,8 @@ extern int local_apic_timer_c2_ok; extern int disable_apic; extern unsigned int lapic_timer_period; +extern int cpuid_to_apicid[]; + extern enum apic_intr_mode_id apic_intr_mode; enum apic_intr_mode_id { APIC_PIC, @@ -377,7 +379,6 @@ extern struct apic *__apicdrivers[], *__apicdrivers_end[]; * APIC functionality to boot other CPUs - only used on SMP: */ #ifdef CONFIG_SMP -extern int wakeup_secondary_cpu_via_nmi(int apicid, unsigned long start_eip); extern int lapic_can_unplug_cpu(void); #endif @@ -507,10 +508,8 @@ extern int default_check_phys_apicid_present(int phys_apicid); #endif /* CONFIG_X86_LOCAL_APIC */ #ifdef CONFIG_SMP -bool apic_id_is_primary_thread(unsigned int id); void apic_smt_update(void); #else -static inline bool apic_id_is_primary_thread(unsigned int id) { return false; } static inline void apic_smt_update(void) { } #endif diff --git a/arch/x86/include/asm/apicdef.h b/arch/x86/include/asm/apicdef.h index 68d213e83fcc20e9b94655b7d13e8d9d7fd767a6..4b125e5b31873ab60e67a6dc5f2aa582f5a49323 100644 --- a/arch/x86/include/asm/apicdef.h +++ b/arch/x86/include/asm/apicdef.h @@ -2,6 +2,8 @@ #ifndef _ASM_X86_APICDEF_H #define _ASM_X86_APICDEF_H +#include + /* * Constants for various Intel APICs. (local APIC, IOAPIC, etc.) * @@ -138,9 +140,10 @@ #define APIC_EILVT_MASKED (1 << 16) #define APIC_BASE (fix_to_virt(FIX_APIC_BASE)) -#define APIC_BASE_MSR 0x800 -#define XAPIC_ENABLE (1UL << 11) -#define X2APIC_ENABLE (1UL << 10) +#define APIC_BASE_MSR 0x800 +#define APIC_X2APIC_ID_MSR 0x802 +#define XAPIC_ENABLE BIT(11) +#define X2APIC_ENABLE BIT(10) #ifdef CONFIG_X86_32 # define MAX_IO_APICS 64 @@ -162,6 +165,7 @@ #define APIC_CPUID(apicid) ((apicid) & XAPIC_DEST_CPUS_MASK) #define NUM_APIC_CLUSTERS ((BAD_APICID + 1) >> XAPIC_DEST_CPUS_SHIFT) +#ifndef __ASSEMBLY__ /* * the local APIC register structure, memory mapped. Not terribly well * tested, but we might eventually use this one in the future - the @@ -435,4 +439,5 @@ enum apic_delivery_modes { APIC_DELIVERY_MODE_EXTINT = 7, }; +#endif /* !__ASSEMBLY__ */ #endif /* _ASM_X86_APICDEF_H */ diff --git a/arch/x86/include/asm/atomic.h b/arch/x86/include/asm/atomic.h index 5e754e89576719ae16f9b85fddedba830b1643b0..55a55ec0435020e99302aa1218aaaca1cf4c745c 100644 --- a/arch/x86/include/asm/atomic.h +++ b/arch/x86/include/asm/atomic.h @@ -14,12 +14,6 @@ * resource counting etc.. */ -/** - * arch_atomic_read - read atomic variable - * @v: pointer of type atomic_t - * - * Atomically reads the value of @v. - */ static __always_inline int arch_atomic_read(const atomic_t *v) { /* @@ -29,25 +23,11 @@ static __always_inline int arch_atomic_read(const atomic_t *v) return __READ_ONCE((v)->counter); } -/** - * arch_atomic_set - set atomic variable - * @v: pointer of type atomic_t - * @i: required value - * - * Atomically sets the value of @v to @i. - */ static __always_inline void arch_atomic_set(atomic_t *v, int i) { __WRITE_ONCE(v->counter, i); } -/** - * arch_atomic_add - add integer to atomic variable - * @i: integer value to add - * @v: pointer of type atomic_t - * - * Atomically adds @i to @v. - */ static __always_inline void arch_atomic_add(int i, atomic_t *v) { asm volatile(LOCK_PREFIX "addl %1,%0" @@ -55,13 +35,6 @@ static __always_inline void arch_atomic_add(int i, atomic_t *v) : "ir" (i) : "memory"); } -/** - * arch_atomic_sub - subtract integer from atomic variable - * @i: integer value to subtract - * @v: pointer of type atomic_t - * - * Atomically subtracts @i from @v. - */ static __always_inline void arch_atomic_sub(int i, atomic_t *v) { asm volatile(LOCK_PREFIX "subl %1,%0" @@ -69,27 +42,12 @@ static __always_inline void arch_atomic_sub(int i, atomic_t *v) : "ir" (i) : "memory"); } -/** - * arch_atomic_sub_and_test - subtract value from variable and test result - * @i: integer value to subtract - * @v: pointer of type atomic_t - * - * Atomically subtracts @i from @v and returns - * true if the result is zero, or false for all - * other cases. - */ static __always_inline bool arch_atomic_sub_and_test(int i, atomic_t *v) { return GEN_BINARY_RMWcc(LOCK_PREFIX "subl", v->counter, e, "er", i); } #define arch_atomic_sub_and_test arch_atomic_sub_and_test -/** - * arch_atomic_inc - increment atomic variable - * @v: pointer of type atomic_t - * - * Atomically increments @v by 1. - */ static __always_inline void arch_atomic_inc(atomic_t *v) { asm volatile(LOCK_PREFIX "incl %0" @@ -97,12 +55,6 @@ static __always_inline void arch_atomic_inc(atomic_t *v) } #define arch_atomic_inc arch_atomic_inc -/** - * arch_atomic_dec - decrement atomic variable - * @v: pointer of type atomic_t - * - * Atomically decrements @v by 1. - */ static __always_inline void arch_atomic_dec(atomic_t *v) { asm volatile(LOCK_PREFIX "decl %0" @@ -110,69 +62,30 @@ static __always_inline void arch_atomic_dec(atomic_t *v) } #define arch_atomic_dec arch_atomic_dec -/** - * arch_atomic_dec_and_test - decrement and test - * @v: pointer of type atomic_t - * - * Atomically decrements @v by 1 and - * returns true if the result is 0, or false for all other - * cases. - */ static __always_inline bool arch_atomic_dec_and_test(atomic_t *v) { return GEN_UNARY_RMWcc(LOCK_PREFIX "decl", v->counter, e); } #define arch_atomic_dec_and_test arch_atomic_dec_and_test -/** - * arch_atomic_inc_and_test - increment and test - * @v: pointer of type atomic_t - * - * Atomically increments @v by 1 - * and returns true if the result is zero, or false for all - * other cases. - */ static __always_inline bool arch_atomic_inc_and_test(atomic_t *v) { return GEN_UNARY_RMWcc(LOCK_PREFIX "incl", v->counter, e); } #define arch_atomic_inc_and_test arch_atomic_inc_and_test -/** - * arch_atomic_add_negative - add and test if negative - * @i: integer value to add - * @v: pointer of type atomic_t - * - * Atomically adds @i to @v and returns true - * if the result is negative, or false when - * result is greater than or equal to zero. - */ static __always_inline bool arch_atomic_add_negative(int i, atomic_t *v) { return GEN_BINARY_RMWcc(LOCK_PREFIX "addl", v->counter, s, "er", i); } #define arch_atomic_add_negative arch_atomic_add_negative -/** - * arch_atomic_add_return - add integer and return - * @i: integer value to add - * @v: pointer of type atomic_t - * - * Atomically adds @i to @v and returns @i + @v - */ static __always_inline int arch_atomic_add_return(int i, atomic_t *v) { return i + xadd(&v->counter, i); } #define arch_atomic_add_return arch_atomic_add_return -/** - * arch_atomic_sub_return - subtract integer and return - * @v: pointer of type atomic_t - * @i: integer value to subtract - * - * Atomically subtracts @i from @v and returns @v - @i - */ static __always_inline int arch_atomic_sub_return(int i, atomic_t *v) { return arch_atomic_add_return(-i, v); diff --git a/arch/x86/include/asm/atomic64_32.h b/arch/x86/include/asm/atomic64_32.h index 808b4eece251ebc80a4068961a9de01a0fac0a3c..3486d91b8595f1dffa03d718dc671dc8000c8770 100644 --- a/arch/x86/include/asm/atomic64_32.h +++ b/arch/x86/include/asm/atomic64_32.h @@ -61,30 +61,12 @@ ATOMIC64_DECL(add_unless); #undef __ATOMIC64_DECL #undef ATOMIC64_EXPORT -/** - * arch_atomic64_cmpxchg - cmpxchg atomic64 variable - * @v: pointer to type atomic64_t - * @o: expected value - * @n: new value - * - * Atomically sets @v to @n if it was equal to @o and returns - * the old value. - */ - static __always_inline s64 arch_atomic64_cmpxchg(atomic64_t *v, s64 o, s64 n) { return arch_cmpxchg64(&v->counter, o, n); } #define arch_atomic64_cmpxchg arch_atomic64_cmpxchg -/** - * arch_atomic64_xchg - xchg atomic64 variable - * @v: pointer to type atomic64_t - * @n: value to assign - * - * Atomically xchgs the value of @v to @n and returns - * the old value. - */ static __always_inline s64 arch_atomic64_xchg(atomic64_t *v, s64 n) { s64 o; @@ -97,13 +79,6 @@ static __always_inline s64 arch_atomic64_xchg(atomic64_t *v, s64 n) } #define arch_atomic64_xchg arch_atomic64_xchg -/** - * arch_atomic64_set - set atomic64 variable - * @v: pointer to type atomic64_t - * @i: value to assign - * - * Atomically sets the value of @v to @n. - */ static __always_inline void arch_atomic64_set(atomic64_t *v, s64 i) { unsigned high = (unsigned)(i >> 32); @@ -113,12 +88,6 @@ static __always_inline void arch_atomic64_set(atomic64_t *v, s64 i) : "eax", "edx", "memory"); } -/** - * arch_atomic64_read - read atomic64 variable - * @v: pointer to type atomic64_t - * - * Atomically reads the value of @v and returns it. - */ static __always_inline s64 arch_atomic64_read(const atomic64_t *v) { s64 r; @@ -126,13 +95,6 @@ static __always_inline s64 arch_atomic64_read(const atomic64_t *v) return r; } -/** - * arch_atomic64_add_return - add and return - * @i: integer value to add - * @v: pointer to type atomic64_t - * - * Atomically adds @i to @v and returns @i + *@v - */ static __always_inline s64 arch_atomic64_add_return(s64 i, atomic64_t *v) { alternative_atomic64(add_return, @@ -142,9 +104,6 @@ static __always_inline s64 arch_atomic64_add_return(s64 i, atomic64_t *v) } #define arch_atomic64_add_return arch_atomic64_add_return -/* - * Other variants with different arithmetic operators: - */ static __always_inline s64 arch_atomic64_sub_return(s64 i, atomic64_t *v) { alternative_atomic64(sub_return, @@ -172,13 +131,6 @@ static __always_inline s64 arch_atomic64_dec_return(atomic64_t *v) } #define arch_atomic64_dec_return arch_atomic64_dec_return -/** - * arch_atomic64_add - add integer to atomic64 variable - * @i: integer value to add - * @v: pointer to type atomic64_t - * - * Atomically adds @i to @v. - */ static __always_inline s64 arch_atomic64_add(s64 i, atomic64_t *v) { __alternative_atomic64(add, add_return, @@ -187,13 +139,6 @@ static __always_inline s64 arch_atomic64_add(s64 i, atomic64_t *v) return i; } -/** - * arch_atomic64_sub - subtract the atomic64 variable - * @i: integer value to subtract - * @v: pointer to type atomic64_t - * - * Atomically subtracts @i from @v. - */ static __always_inline s64 arch_atomic64_sub(s64 i, atomic64_t *v) { __alternative_atomic64(sub, sub_return, @@ -202,12 +147,6 @@ static __always_inline s64 arch_atomic64_sub(s64 i, atomic64_t *v) return i; } -/** - * arch_atomic64_inc - increment atomic64 variable - * @v: pointer to type atomic64_t - * - * Atomically increments @v by 1. - */ static __always_inline void arch_atomic64_inc(atomic64_t *v) { __alternative_atomic64(inc, inc_return, /* no output */, @@ -215,12 +154,6 @@ static __always_inline void arch_atomic64_inc(atomic64_t *v) } #define arch_atomic64_inc arch_atomic64_inc -/** - * arch_atomic64_dec - decrement atomic64 variable - * @v: pointer to type atomic64_t - * - * Atomically decrements @v by 1. - */ static __always_inline void arch_atomic64_dec(atomic64_t *v) { __alternative_atomic64(dec, dec_return, /* no output */, @@ -228,15 +161,6 @@ static __always_inline void arch_atomic64_dec(atomic64_t *v) } #define arch_atomic64_dec arch_atomic64_dec -/** - * arch_atomic64_add_unless - add unless the number is a given value - * @v: pointer of type atomic64_t - * @a: the amount to add to v... - * @u: ...unless v is equal to u. - * - * Atomically adds @a to @v, so long as it was not @u. - * Returns non-zero if the add was done, zero otherwise. - */ static __always_inline int arch_atomic64_add_unless(atomic64_t *v, s64 a, s64 u) { unsigned low = (unsigned)u; diff --git a/arch/x86/include/asm/atomic64_64.h b/arch/x86/include/asm/atomic64_64.h index c496595bf6012a0bd3eddf2369f8880fe7d27914..3165c0feedf7421a4c241513b7dc10673899a527 100644 --- a/arch/x86/include/asm/atomic64_64.h +++ b/arch/x86/include/asm/atomic64_64.h @@ -10,37 +10,16 @@ #define ATOMIC64_INIT(i) { (i) } -/** - * arch_atomic64_read - read atomic64 variable - * @v: pointer of type atomic64_t - * - * Atomically reads the value of @v. - * Doesn't imply a read memory barrier. - */ static __always_inline s64 arch_atomic64_read(const atomic64_t *v) { return __READ_ONCE((v)->counter); } -/** - * arch_atomic64_set - set atomic64 variable - * @v: pointer to type atomic64_t - * @i: required value - * - * Atomically sets the value of @v to @i. - */ static __always_inline void arch_atomic64_set(atomic64_t *v, s64 i) { __WRITE_ONCE(v->counter, i); } -/** - * arch_atomic64_add - add integer to atomic64 variable - * @i: integer value to add - * @v: pointer to type atomic64_t - * - * Atomically adds @i to @v. - */ static __always_inline void arch_atomic64_add(s64 i, atomic64_t *v) { asm volatile(LOCK_PREFIX "addq %1,%0" @@ -48,13 +27,6 @@ static __always_inline void arch_atomic64_add(s64 i, atomic64_t *v) : "er" (i), "m" (v->counter) : "memory"); } -/** - * arch_atomic64_sub - subtract the atomic64 variable - * @i: integer value to subtract - * @v: pointer to type atomic64_t - * - * Atomically subtracts @i from @v. - */ static __always_inline void arch_atomic64_sub(s64 i, atomic64_t *v) { asm volatile(LOCK_PREFIX "subq %1,%0" @@ -62,27 +34,12 @@ static __always_inline void arch_atomic64_sub(s64 i, atomic64_t *v) : "er" (i), "m" (v->counter) : "memory"); } -/** - * arch_atomic64_sub_and_test - subtract value from variable and test result - * @i: integer value to subtract - * @v: pointer to type atomic64_t - * - * Atomically subtracts @i from @v and returns - * true if the result is zero, or false for all - * other cases. - */ static __always_inline bool arch_atomic64_sub_and_test(s64 i, atomic64_t *v) { return GEN_BINARY_RMWcc(LOCK_PREFIX "subq", v->counter, e, "er", i); } #define arch_atomic64_sub_and_test arch_atomic64_sub_and_test -/** - * arch_atomic64_inc - increment atomic64 variable - * @v: pointer to type atomic64_t - * - * Atomically increments @v by 1. - */ static __always_inline void arch_atomic64_inc(atomic64_t *v) { asm volatile(LOCK_PREFIX "incq %0" @@ -91,12 +48,6 @@ static __always_inline void arch_atomic64_inc(atomic64_t *v) } #define arch_atomic64_inc arch_atomic64_inc -/** - * arch_atomic64_dec - decrement atomic64 variable - * @v: pointer to type atomic64_t - * - * Atomically decrements @v by 1. - */ static __always_inline void arch_atomic64_dec(atomic64_t *v) { asm volatile(LOCK_PREFIX "decq %0" @@ -105,56 +56,24 @@ static __always_inline void arch_atomic64_dec(atomic64_t *v) } #define arch_atomic64_dec arch_atomic64_dec -/** - * arch_atomic64_dec_and_test - decrement and test - * @v: pointer to type atomic64_t - * - * Atomically decrements @v by 1 and - * returns true if the result is 0, or false for all other - * cases. - */ static __always_inline bool arch_atomic64_dec_and_test(atomic64_t *v) { return GEN_UNARY_RMWcc(LOCK_PREFIX "decq", v->counter, e); } #define arch_atomic64_dec_and_test arch_atomic64_dec_and_test -/** - * arch_atomic64_inc_and_test - increment and test - * @v: pointer to type atomic64_t - * - * Atomically increments @v by 1 - * and returns true if the result is zero, or false for all - * other cases. - */ static __always_inline bool arch_atomic64_inc_and_test(atomic64_t *v) { return GEN_UNARY_RMWcc(LOCK_PREFIX "incq", v->counter, e); } #define arch_atomic64_inc_and_test arch_atomic64_inc_and_test -/** - * arch_atomic64_add_negative - add and test if negative - * @i: integer value to add - * @v: pointer to type atomic64_t - * - * Atomically adds @i to @v and returns true - * if the result is negative, or false when - * result is greater than or equal to zero. - */ static __always_inline bool arch_atomic64_add_negative(s64 i, atomic64_t *v) { return GEN_BINARY_RMWcc(LOCK_PREFIX "addq", v->counter, s, "er", i); } #define arch_atomic64_add_negative arch_atomic64_add_negative -/** - * arch_atomic64_add_return - add and return - * @i: integer value to add - * @v: pointer to type atomic64_t - * - * Atomically adds @i to @v and returns @i + @v - */ static __always_inline s64 arch_atomic64_add_return(s64 i, atomic64_t *v) { return i + xadd(&v->counter, i); diff --git a/arch/x86/include/asm/bugs.h b/arch/x86/include/asm/bugs.h index 92ae283899409df20a0865b1734d1864feccb5a6..f25ca2d709d404f2a49ec3935a7a5a1658f81470 100644 --- a/arch/x86/include/asm/bugs.h +++ b/arch/x86/include/asm/bugs.h @@ -4,8 +4,6 @@ #include -extern void check_bugs(void); - #if defined(CONFIG_CPU_SUP_INTEL) && defined(CONFIG_X86_32) int ppro_with_ram_bug(void); #else diff --git a/arch/x86/include/asm/cmpxchg.h b/arch/x86/include/asm/cmpxchg.h index 540573f515b7bb6cb766fa5218e3af27bcaed83e..d53636506134754c064648cd7a1ff7cac4e9b1df 100644 --- a/arch/x86/include/asm/cmpxchg.h +++ b/arch/x86/include/asm/cmpxchg.h @@ -239,29 +239,4 @@ extern void __add_wrong_size(void) #define __xadd(ptr, inc, lock) __xchg_op((ptr), (inc), xadd, lock) #define xadd(ptr, inc) __xadd((ptr), (inc), LOCK_PREFIX) -#define __cmpxchg_double(pfx, p1, p2, o1, o2, n1, n2) \ -({ \ - bool __ret; \ - __typeof__(*(p1)) __old1 = (o1), __new1 = (n1); \ - __typeof__(*(p2)) __old2 = (o2), __new2 = (n2); \ - BUILD_BUG_ON(sizeof(*(p1)) != sizeof(long)); \ - BUILD_BUG_ON(sizeof(*(p2)) != sizeof(long)); \ - VM_BUG_ON((unsigned long)(p1) % (2 * sizeof(long))); \ - VM_BUG_ON((unsigned long)((p1) + 1) != (unsigned long)(p2)); \ - asm volatile(pfx "cmpxchg%c5b %1" \ - CC_SET(e) \ - : CC_OUT(e) (__ret), \ - "+m" (*(p1)), "+m" (*(p2)), \ - "+a" (__old1), "+d" (__old2) \ - : "i" (2 * sizeof(long)), \ - "b" (__new1), "c" (__new2)); \ - __ret; \ -}) - -#define arch_cmpxchg_double(p1, p2, o1, o2, n1, n2) \ - __cmpxchg_double(LOCK_PREFIX, p1, p2, o1, o2, n1, n2) - -#define arch_cmpxchg_double_local(p1, p2, o1, o2, n1, n2) \ - __cmpxchg_double(, p1, p2, o1, o2, n1, n2) - #endif /* ASM_X86_CMPXCHG_H */ diff --git a/arch/x86/include/asm/cmpxchg_32.h b/arch/x86/include/asm/cmpxchg_32.h index 6ba80ce9438dde9f93a741f290fda08ac8c596a6..b5731c51f0f4cda144527a376ada43835e0d4cb3 100644 --- a/arch/x86/include/asm/cmpxchg_32.h +++ b/arch/x86/include/asm/cmpxchg_32.h @@ -103,6 +103,6 @@ static inline bool __try_cmpxchg64(volatile u64 *ptr, u64 *pold, u64 new) #endif -#define system_has_cmpxchg_double() boot_cpu_has(X86_FEATURE_CX8) +#define system_has_cmpxchg64() boot_cpu_has(X86_FEATURE_CX8) #endif /* _ASM_X86_CMPXCHG_32_H */ diff --git a/arch/x86/include/asm/cmpxchg_64.h b/arch/x86/include/asm/cmpxchg_64.h index 0d3beb27b7fe4fbc43c25f204f5ce76c592409a1..44b08b53ab32fc358cb314ea1c89ac3ded8d815b 100644 --- a/arch/x86/include/asm/cmpxchg_64.h +++ b/arch/x86/include/asm/cmpxchg_64.h @@ -20,6 +20,71 @@ arch_try_cmpxchg((ptr), (po), (n)); \ }) -#define system_has_cmpxchg_double() boot_cpu_has(X86_FEATURE_CX16) +union __u128_halves { + u128 full; + struct { + u64 low, high; + }; +}; + +#define __arch_cmpxchg128(_ptr, _old, _new, _lock) \ +({ \ + union __u128_halves o = { .full = (_old), }, \ + n = { .full = (_new), }; \ + \ + asm volatile(_lock "cmpxchg16b %[ptr]" \ + : [ptr] "+m" (*(_ptr)), \ + "+a" (o.low), "+d" (o.high) \ + : "b" (n.low), "c" (n.high) \ + : "memory"); \ + \ + o.full; \ +}) + +static __always_inline u128 arch_cmpxchg128(volatile u128 *ptr, u128 old, u128 new) +{ + return __arch_cmpxchg128(ptr, old, new, LOCK_PREFIX); +} +#define arch_cmpxchg128 arch_cmpxchg128 + +static __always_inline u128 arch_cmpxchg128_local(volatile u128 *ptr, u128 old, u128 new) +{ + return __arch_cmpxchg128(ptr, old, new,); +} +#define arch_cmpxchg128_local arch_cmpxchg128_local + +#define __arch_try_cmpxchg128(_ptr, _oldp, _new, _lock) \ +({ \ + union __u128_halves o = { .full = *(_oldp), }, \ + n = { .full = (_new), }; \ + bool ret; \ + \ + asm volatile(_lock "cmpxchg16b %[ptr]" \ + CC_SET(e) \ + : CC_OUT(e) (ret), \ + [ptr] "+m" (*ptr), \ + "+a" (o.low), "+d" (o.high) \ + : "b" (n.low), "c" (n.high) \ + : "memory"); \ + \ + if (unlikely(!ret)) \ + *(_oldp) = o.full; \ + \ + likely(ret); \ +}) + +static __always_inline bool arch_try_cmpxchg128(volatile u128 *ptr, u128 *oldp, u128 new) +{ + return __arch_try_cmpxchg128(ptr, oldp, new, LOCK_PREFIX); +} +#define arch_try_cmpxchg128 arch_try_cmpxchg128 + +static __always_inline bool arch_try_cmpxchg128_local(volatile u128 *ptr, u128 *oldp, u128 new) +{ + return __arch_try_cmpxchg128(ptr, oldp, new,); +} +#define arch_try_cmpxchg128_local arch_try_cmpxchg128_local + +#define system_has_cmpxchg128() boot_cpu_has(X86_FEATURE_CX16) #endif /* _ASM_X86_CMPXCHG_64_H */ diff --git a/arch/x86/include/asm/coco.h b/arch/x86/include/asm/coco.h index eb08796002f3c59c352172da5a44d4ef386988ea..6ae2d16a7613b714cb58283dafa600db5829ba6f 100644 --- a/arch/x86/include/asm/coco.h +++ b/arch/x86/include/asm/coco.h @@ -10,30 +10,13 @@ enum cc_vendor { CC_VENDOR_INTEL, }; -#ifdef CONFIG_ARCH_HAS_CC_PLATFORM extern enum cc_vendor cc_vendor; -static inline enum cc_vendor cc_get_vendor(void) -{ - return cc_vendor; -} - -static inline void cc_set_vendor(enum cc_vendor vendor) -{ - cc_vendor = vendor; -} - +#ifdef CONFIG_ARCH_HAS_CC_PLATFORM void cc_set_mask(u64 mask); u64 cc_mkenc(u64 val); u64 cc_mkdec(u64 val); #else -static inline enum cc_vendor cc_get_vendor(void) -{ - return CC_VENDOR_NONE; -} - -static inline void cc_set_vendor(enum cc_vendor vendor) { } - static inline u64 cc_mkenc(u64 val) { return val; diff --git a/arch/x86/include/asm/cpu.h b/arch/x86/include/asm/cpu.h index 78796b98a5449c858af91c94484e15ca1127b6c6..3a233ebff7129c2cf8363527722cef099d5e8550 100644 --- a/arch/x86/include/asm/cpu.h +++ b/arch/x86/include/asm/cpu.h @@ -30,10 +30,7 @@ struct x86_cpu { #ifdef CONFIG_HOTPLUG_CPU extern int arch_register_cpu(int num); extern void arch_unregister_cpu(int); -extern void start_cpu0(void); -#ifdef CONFIG_DEBUG_HOTPLUG_CPU0 -extern int _debug_hotplug_cpu(int cpu, int action); -#endif +extern void soft_restart_cpu(void); #endif extern void ap_init_aperfmperf(void); @@ -98,4 +95,6 @@ extern u64 x86_read_arch_cap_msr(void); int intel_find_matching_signature(void *mc, unsigned int csig, int cpf); int intel_microcode_sanity_check(void *mc, bool print_err, int hdr_type); +extern struct cpumask cpus_stop_mask; + #endif /* _ASM_X86_CPU_H */ diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h index ce0c8f7d32186f32893bfdf4555246c856febc61..a26bebbdff87ed20c45bdb98dcc4a8873f5c30f5 100644 --- a/arch/x86/include/asm/cpufeature.h +++ b/arch/x86/include/asm/cpufeature.h @@ -38,15 +38,10 @@ enum cpuid_leafs #define X86_CAP_FMT_NUM "%d:%d" #define x86_cap_flag_num(flag) ((flag) >> 5), ((flag) & 31) -#ifdef CONFIG_X86_FEATURE_NAMES extern const char * const x86_cap_flags[NCAPINTS*32]; extern const char * const x86_power_flags[32]; #define X86_CAP_FMT "%s" #define x86_cap_flag(flag) x86_cap_flags[flag] -#else -#define X86_CAP_FMT X86_CAP_FMT_NUM -#define x86_cap_flag x86_cap_flag_num -#endif /* * In order to save room, we index into this array by doing diff --git a/arch/x86/include/asm/cpumask.h b/arch/x86/include/asm/cpumask.h index c5aed9e9226c669fe03b67431ef01984a4d98002..4acfd57de8f1ce307fdaa8a09180845ec39347d1 100644 --- a/arch/x86/include/asm/cpumask.h +++ b/arch/x86/include/asm/cpumask.h @@ -4,11 +4,6 @@ #ifndef __ASSEMBLY__ #include -extern cpumask_var_t cpu_callin_mask; -extern cpumask_var_t cpu_callout_mask; -extern cpumask_var_t cpu_initialized_mask; -extern cpumask_var_t cpu_sibling_setup_mask; - extern void setup_cpu_local_masks(void); /* diff --git a/arch/x86/include/asm/doublefault.h b/arch/x86/include/asm/doublefault.h index 54a6e4a2e132d1b9527a90793ba60ece450be07c..de0e88b32207e7781723c5c9f18e9d375baf72dc 100644 --- a/arch/x86/include/asm/doublefault.h +++ b/arch/x86/include/asm/doublefault.h @@ -2,6 +2,8 @@ #ifndef _ASM_X86_DOUBLEFAULT_H #define _ASM_X86_DOUBLEFAULT_H +#include + #ifdef CONFIG_X86_32 extern void doublefault_init_cpu_tss(void); #else @@ -10,4 +12,6 @@ static inline void doublefault_init_cpu_tss(void) } #endif +asmlinkage void __noreturn doublefault_shim(void); + #endif /* _ASM_X86_DOUBLEFAULT_H */ diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h index 419280d263d2e3f24d6549cc50abb3ccd21e219c..8b4be7cecdb8eb733e44e5571e025e2629a98eed 100644 --- a/arch/x86/include/asm/efi.h +++ b/arch/x86/include/asm/efi.h @@ -31,6 +31,8 @@ extern unsigned long efi_mixed_mode_stack_pa; #define ARCH_EFI_IRQ_FLAGS_MASK X86_EFLAGS_IF +#define EFI_UNACCEPTED_UNIT_SIZE PMD_SIZE + /* * The EFI services are called through variadic functions in many cases. These * functions are implemented in assembler and support only a fixed number of diff --git a/arch/x86/include/asm/fpu/api.h b/arch/x86/include/asm/fpu/api.h index 503a577814b2e5a7b47c1f5069a76c3e568ff6b7..b475d9a582b88973a15ef0af0e125f97a88ffffe 100644 --- a/arch/x86/include/asm/fpu/api.h +++ b/arch/x86/include/asm/fpu/api.h @@ -109,7 +109,7 @@ extern void fpu_reset_from_exception_fixup(void); /* Boot, hotplug and resume */ extern void fpu__init_cpu(void); -extern void fpu__init_system(struct cpuinfo_x86 *c); +extern void fpu__init_system(void); extern void fpu__init_check_bugs(void); extern void fpu__resume_cpu(void); diff --git a/arch/x86/include/asm/ftrace.h b/arch/x86/include/asm/ftrace.h index 5061ac98ffa160c064eebff3eb21a421b08d37cc..897cf02c20b1baf7e3bebdc5c1b052e413f85d8a 100644 --- a/arch/x86/include/asm/ftrace.h +++ b/arch/x86/include/asm/ftrace.h @@ -106,6 +106,9 @@ struct dyn_arch_ftrace { #ifndef __ASSEMBLY__ +void prepare_ftrace_return(unsigned long ip, unsigned long *parent, + unsigned long frame_pointer); + #if defined(CONFIG_FUNCTION_TRACER) && defined(CONFIG_DYNAMIC_FTRACE) extern void set_ftrace_ops_ro(void); #else @@ -147,4 +150,24 @@ static inline bool arch_trace_is_compat_syscall(struct pt_regs *regs) #endif /* !COMPILE_OFFSETS */ #endif /* !__ASSEMBLY__ */ +#ifndef __ASSEMBLY__ +#ifdef CONFIG_FUNCTION_GRAPH_TRACER +struct fgraph_ret_regs { + unsigned long ax; + unsigned long dx; + unsigned long bp; +}; + +static inline unsigned long fgraph_ret_regs_return_value(struct fgraph_ret_regs *ret_regs) +{ + return ret_regs->ax; +} + +static inline unsigned long fgraph_ret_regs_frame_pointer(struct fgraph_ret_regs *ret_regs) +{ + return ret_regs->bp; +} +#endif /* ifdef CONFIG_FUNCTION_GRAPH_TRACER */ +#endif + #endif /* _ASM_X86_FTRACE_H */ diff --git a/arch/x86/include/asm/ibt.h b/arch/x86/include/asm/ibt.h index baae6b4fea23ae84ceb0550bd0ccdcaeb33bb305..1e59581d500ca9f82dc073e1587da11fe944873d 100644 --- a/arch/x86/include/asm/ibt.h +++ b/arch/x86/include/asm/ibt.h @@ -34,7 +34,7 @@ /* * Create a dummy function pointer reference to prevent objtool from marking * the function as needing to be "sealed" (i.e. ENDBR converted to NOP by - * apply_ibt_endbr()). + * apply_seal_endbr()). */ #define IBT_NOSEAL(fname) \ ".pushsection .discard.ibt_endbr_noseal\n\t" \ diff --git a/arch/x86/include/asm/irq.h b/arch/x86/include/asm/irq.h index 768aa234cbb4a6c2fb3c6362156825e11ee046d1..29e083b92813c345fece77a30b5f98bdbb2403f4 100644 --- a/arch/x86/include/asm/irq.h +++ b/arch/x86/include/asm/irq.h @@ -40,8 +40,6 @@ extern void __handle_irq(struct irq_desc *desc, struct pt_regs *regs); extern void init_ISA_irqs(void); -extern void __init init_IRQ(void); - #ifdef CONFIG_X86_LOCAL_APIC void arch_trigger_cpumask_backtrace(const struct cpumask *mask, bool exclude_self); diff --git a/arch/x86/include/asm/kvm-x86-pmu-ops.h b/arch/x86/include/asm/kvm-x86-pmu-ops.h index c17e3e96fc1d4c9bccbf612fb32ad3b869f03fcf..6c98f4bb4228ba5a05acb55f30fa965020c206c4 100644 --- a/arch/x86/include/asm/kvm-x86-pmu-ops.h +++ b/arch/x86/include/asm/kvm-x86-pmu-ops.h @@ -13,7 +13,6 @@ BUILD_BUG_ON(1) * at the call sites. */ KVM_X86_PMU_OP(hw_event_available) -KVM_X86_PMU_OP(pmc_is_enabled) KVM_X86_PMU_OP(pmc_idx_to_pmc) KVM_X86_PMU_OP(rdpmc_ecx_to_pmc) KVM_X86_PMU_OP(msr_idx_to_pmc) diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index fb9d1f2d6136c9952844840dc18c7f77af7a9b17..28bd38303d70461ad51b79d85b9f7b79b5984605 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -523,7 +523,7 @@ struct kvm_pmu { u64 global_status; u64 counter_bitmask[2]; u64 global_ctrl_mask; - u64 global_ovf_ctrl_mask; + u64 global_status_mask; u64 reserved_bits; u64 raw_event_mask; struct kvm_pmc gp_counters[KVM_INTEL_PMC_MAX_GENERIC]; diff --git a/arch/x86/include/asm/mce.h b/arch/x86/include/asm/mce.h index 9646ed6e8c0b95318ab65e19dd261ec3c34ba55e..180b1cbfcc4e11e90f25f4dd378ba8d0e14e8f5e 100644 --- a/arch/x86/include/asm/mce.h +++ b/arch/x86/include/asm/mce.h @@ -350,4 +350,7 @@ static inline void mce_amd_feature_init(struct cpuinfo_x86 *c) { } #endif static inline void mce_hygon_feature_init(struct cpuinfo_x86 *c) { return mce_amd_feature_init(c); } + +unsigned long copy_mc_fragile_handle_tail(char *to, char *from, unsigned len); + #endif /* _ASM_X86_MCE_H */ diff --git a/arch/x86/include/asm/mem_encrypt.h b/arch/x86/include/asm/mem_encrypt.h index b7126701574c1b10f1e24f11f9952bc7b9217bc9..7f97a8a97e24a81ad56fc4421b30c38a5ba2c821 100644 --- a/arch/x86/include/asm/mem_encrypt.h +++ b/arch/x86/include/asm/mem_encrypt.h @@ -17,6 +17,12 @@ #include +#ifdef CONFIG_X86_MEM_ENCRYPT +void __init mem_encrypt_init(void); +#else +static inline void mem_encrypt_init(void) { } +#endif + #ifdef CONFIG_AMD_MEM_ENCRYPT extern u64 sme_me_mask; @@ -87,9 +93,6 @@ static inline void mem_encrypt_free_decrypted_mem(void) { } #endif /* CONFIG_AMD_MEM_ENCRYPT */ -/* Architecture __weak replacement functions */ -void __init mem_encrypt_init(void); - void add_encrypt_protection_map(void); /* diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h index 49bb4f2bd300e0a50b9cef20d4e1c2b28d49b2cc..88d9ef98e087aff9bfe835457c079a3a0cdc0253 100644 --- a/arch/x86/include/asm/mshyperv.h +++ b/arch/x86/include/asm/mshyperv.h @@ -257,6 +257,11 @@ void hv_set_register(unsigned int reg, u64 value); u64 hv_get_non_nested_register(unsigned int reg); void hv_set_non_nested_register(unsigned int reg, u64 value); +static __always_inline u64 hv_raw_get_register(unsigned int reg) +{ + return __rdmsr(reg); +} + #else /* CONFIG_HYPERV */ static inline void hyperv_init(void) {} static inline void hyperv_setup_mmu_ops(void) {} diff --git a/arch/x86/include/asm/mtrr.h b/arch/x86/include/asm/mtrr.h index f0eeaf6e5f5f79f318814efd8c72ef20f6f9ce40..090d658a85a6c03a69e360798ab6bc6c5c799a90 100644 --- a/arch/x86/include/asm/mtrr.h +++ b/arch/x86/include/asm/mtrr.h @@ -23,14 +23,43 @@ #ifndef _ASM_X86_MTRR_H #define _ASM_X86_MTRR_H +#include #include +/* Defines for hardware MTRR registers. */ +#define MTRR_CAP_VCNT GENMASK(7, 0) +#define MTRR_CAP_FIX BIT_MASK(8) +#define MTRR_CAP_WC BIT_MASK(10) + +#define MTRR_DEF_TYPE_TYPE GENMASK(7, 0) +#define MTRR_DEF_TYPE_FE BIT_MASK(10) +#define MTRR_DEF_TYPE_E BIT_MASK(11) + +#define MTRR_DEF_TYPE_ENABLE (MTRR_DEF_TYPE_FE | MTRR_DEF_TYPE_E) +#define MTRR_DEF_TYPE_DISABLE ~(MTRR_DEF_TYPE_TYPE | MTRR_DEF_TYPE_ENABLE) + +#define MTRR_PHYSBASE_TYPE GENMASK(7, 0) +#define MTRR_PHYSBASE_RSVD GENMASK(11, 8) + +#define MTRR_PHYSMASK_RSVD GENMASK(10, 0) +#define MTRR_PHYSMASK_V BIT_MASK(11) + +struct mtrr_state_type { + struct mtrr_var_range var_ranges[MTRR_MAX_VAR_RANGES]; + mtrr_type fixed_ranges[MTRR_NUM_FIXED_RANGES]; + unsigned char enabled; + bool have_fixed; + mtrr_type def_type; +}; + /* * The following functions are for use by other drivers that cannot use * arch_phys_wc_add and arch_phys_wc_del. */ # ifdef CONFIG_MTRR void mtrr_bp_init(void); +void mtrr_overwrite_state(struct mtrr_var_range *var, unsigned int num_var, + mtrr_type def_type); extern u8 mtrr_type_lookup(u64 addr, u64 end, u8 *uniform); extern void mtrr_save_fixed_ranges(void *); extern void mtrr_save_state(void); @@ -40,7 +69,6 @@ extern int mtrr_add_page(unsigned long base, unsigned long size, unsigned int type, bool increment); extern int mtrr_del(int reg, unsigned long base, unsigned long size); extern int mtrr_del_page(int reg, unsigned long base, unsigned long size); -extern void mtrr_centaur_report_mcr(int mcr, u32 lo, u32 hi); extern void mtrr_bp_restore(void); extern int mtrr_trim_uncached_memory(unsigned long end_pfn); extern int amd_special_default_mtrr(void); @@ -48,12 +76,21 @@ void mtrr_disable(void); void mtrr_enable(void); void mtrr_generic_set_state(void); # else +static inline void mtrr_overwrite_state(struct mtrr_var_range *var, + unsigned int num_var, + mtrr_type def_type) +{ +} + static inline u8 mtrr_type_lookup(u64 addr, u64 end, u8 *uniform) { /* - * Return no-MTRRs: + * Return the default MTRR type, without any known other types in + * that range. */ - return MTRR_TYPE_INVALID; + *uniform = 1; + + return MTRR_TYPE_UNCACHABLE; } #define mtrr_save_fixed_ranges(arg) do {} while (0) #define mtrr_save_state() do {} while (0) @@ -79,9 +116,6 @@ static inline int mtrr_trim_uncached_memory(unsigned long end_pfn) { return 0; } -static inline void mtrr_centaur_report_mcr(int mcr, u32 lo, u32 hi) -{ -} #define mtrr_bp_init() do {} while (0) #define mtrr_bp_restore() do {} while (0) #define mtrr_disable() do {} while (0) @@ -121,7 +155,8 @@ struct mtrr_gentry32 { #endif /* CONFIG_COMPAT */ /* Bit fields for enabled in struct mtrr_state_type */ -#define MTRR_STATE_MTRR_FIXED_ENABLED 0x01 -#define MTRR_STATE_MTRR_ENABLED 0x02 +#define MTRR_STATE_SHIFT 10 +#define MTRR_STATE_MTRR_FIXED_ENABLED (MTRR_DEF_TYPE_FE >> MTRR_STATE_SHIFT) +#define MTRR_STATE_MTRR_ENABLED (MTRR_DEF_TYPE_E >> MTRR_STATE_SHIFT) #endif /* _ASM_X86_MTRR_H */ diff --git a/arch/x86/include/asm/nops.h b/arch/x86/include/asm/nops.h index c5573eaa5bb987332c638c461cd0bc96e71c5db2..1c1b7550fa5508a2131b63602132fd444037835a 100644 --- a/arch/x86/include/asm/nops.h +++ b/arch/x86/include/asm/nops.h @@ -34,6 +34,8 @@ #define BYTES_NOP7 0x8d,0xb4,0x26,0x00,0x00,0x00,0x00 #define BYTES_NOP8 0x3e,BYTES_NOP7 +#define ASM_NOP_MAX 8 + #else /* @@ -47,6 +49,9 @@ * 6: osp nopl 0x00(%eax,%eax,1) * 7: nopl 0x00000000(%eax) * 8: nopl 0x00000000(%eax,%eax,1) + * 9: cs nopl 0x00000000(%eax,%eax,1) + * 10: osp cs nopl 0x00000000(%eax,%eax,1) + * 11: osp osp cs nopl 0x00000000(%eax,%eax,1) */ #define BYTES_NOP1 0x90 #define BYTES_NOP2 0x66,BYTES_NOP1 @@ -56,6 +61,15 @@ #define BYTES_NOP6 0x66,BYTES_NOP5 #define BYTES_NOP7 0x0f,0x1f,0x80,0x00,0x00,0x00,0x00 #define BYTES_NOP8 0x0f,0x1f,0x84,0x00,0x00,0x00,0x00,0x00 +#define BYTES_NOP9 0x2e,BYTES_NOP8 +#define BYTES_NOP10 0x66,BYTES_NOP9 +#define BYTES_NOP11 0x66,BYTES_NOP10 + +#define ASM_NOP9 _ASM_BYTES(BYTES_NOP9) +#define ASM_NOP10 _ASM_BYTES(BYTES_NOP10) +#define ASM_NOP11 _ASM_BYTES(BYTES_NOP11) + +#define ASM_NOP_MAX 11 #endif /* CONFIG_64BIT */ @@ -68,8 +82,6 @@ #define ASM_NOP7 _ASM_BYTES(BYTES_NOP7) #define ASM_NOP8 _ASM_BYTES(BYTES_NOP8) -#define ASM_NOP_MAX 8 - #ifndef __ASSEMBLY__ extern const unsigned char * const x86_nops[]; #endif diff --git a/arch/x86/include/asm/nospec-branch.h b/arch/x86/include/asm/nospec-branch.h index edb2b0cb8efe5d47ef84bddbba62d58ebbe72a3a..1a65cf4acb2b93313581497ff27d29ac6cd61365 100644 --- a/arch/x86/include/asm/nospec-branch.h +++ b/arch/x86/include/asm/nospec-branch.h @@ -84,12 +84,12 @@ movq $-1, PER_CPU_VAR(pcpu_hot + X86_call_depth); #define RESET_CALL_DEPTH \ - mov $0x80, %rax; \ - shl $56, %rax; \ + xor %eax, %eax; \ + bts $63, %rax; \ movq %rax, PER_CPU_VAR(pcpu_hot + X86_call_depth); #define RESET_CALL_DEPTH_FROM_CALL \ - mov $0xfc, %rax; \ + movb $0xfc, %al; \ shl $56, %rax; \ movq %rax, PER_CPU_VAR(pcpu_hot + X86_call_depth); \ CALL_THUNKS_DEBUG_INC_CALLS @@ -234,6 +234,10 @@ * JMP_NOSPEC and CALL_NOSPEC macros can be used instead of a simple * indirect jmp/call which may be susceptible to the Spectre variant 2 * attack. + * + * NOTE: these do not take kCFI into account and are thus not comparable to C + * indirect calls, take care when using. The target of these should be an ENDBR + * instruction irrespective of kCFI. */ .macro JMP_NOSPEC reg:req #ifdef CONFIG_RETPOLINE diff --git a/arch/x86/include/asm/orc_header.h b/arch/x86/include/asm/orc_header.h new file mode 100644 index 0000000000000000000000000000000000000000..07bacf3e160eaceecbcb5a49ae70c5bce804847a --- /dev/null +++ b/arch/x86/include/asm/orc_header.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* Copyright (c) Meta Platforms, Inc. and affiliates. */ + +#ifndef _ORC_HEADER_H +#define _ORC_HEADER_H + +#include +#include +#include + +/* + * The header is currently a 20-byte hash of the ORC entry definition; see + * scripts/orc_hash.sh. + */ +#define ORC_HEADER \ + __used __section(".orc_header") __aligned(4) \ + static const u8 orc_header[] = { ORC_HASH } + +#endif /* _ORC_HEADER_H */ diff --git a/arch/x86/include/asm/percpu.h b/arch/x86/include/asm/percpu.h index 13c0d63ed55e428226ecd004dd078ed9d412eb55..34734d73046397058357e113df1b26a8ce75f24b 100644 --- a/arch/x86/include/asm/percpu.h +++ b/arch/x86/include/asm/percpu.h @@ -210,6 +210,67 @@ do { \ (typeof(_var))(unsigned long) pco_old__; \ }) +#if defined(CONFIG_X86_32) && !defined(CONFIG_UML) +#define percpu_cmpxchg64_op(size, qual, _var, _oval, _nval) \ +({ \ + union { \ + u64 var; \ + struct { \ + u32 low, high; \ + }; \ + } old__, new__; \ + \ + old__.var = _oval; \ + new__.var = _nval; \ + \ + asm qual (ALTERNATIVE("leal %P[var], %%esi; call this_cpu_cmpxchg8b_emu", \ + "cmpxchg8b " __percpu_arg([var]), X86_FEATURE_CX8) \ + : [var] "+m" (_var), \ + "+a" (old__.low), \ + "+d" (old__.high) \ + : "b" (new__.low), \ + "c" (new__.high) \ + : "memory", "esi"); \ + \ + old__.var; \ +}) + +#define raw_cpu_cmpxchg64(pcp, oval, nval) percpu_cmpxchg64_op(8, , pcp, oval, nval) +#define this_cpu_cmpxchg64(pcp, oval, nval) percpu_cmpxchg64_op(8, volatile, pcp, oval, nval) +#endif + +#ifdef CONFIG_X86_64 +#define raw_cpu_cmpxchg64(pcp, oval, nval) percpu_cmpxchg_op(8, , pcp, oval, nval); +#define this_cpu_cmpxchg64(pcp, oval, nval) percpu_cmpxchg_op(8, volatile, pcp, oval, nval); + +#define percpu_cmpxchg128_op(size, qual, _var, _oval, _nval) \ +({ \ + union { \ + u128 var; \ + struct { \ + u64 low, high; \ + }; \ + } old__, new__; \ + \ + old__.var = _oval; \ + new__.var = _nval; \ + \ + asm qual (ALTERNATIVE("leaq %P[var], %%rsi; call this_cpu_cmpxchg16b_emu", \ + "cmpxchg16b " __percpu_arg([var]), X86_FEATURE_CX16) \ + : [var] "+m" (_var), \ + "+a" (old__.low), \ + "+d" (old__.high) \ + : "b" (new__.low), \ + "c" (new__.high) \ + : "memory", "rsi"); \ + \ + old__.var; \ +}) + +#define raw_cpu_cmpxchg128(pcp, oval, nval) percpu_cmpxchg128_op(16, , pcp, oval, nval) +#define this_cpu_cmpxchg128(pcp, oval, nval) percpu_cmpxchg128_op(16, volatile, pcp, oval, nval) +#endif + /* * this_cpu_read() makes gcc load the percpu variable every time it is * accessed while this_cpu_read_stable() allows the value to be cached. @@ -290,23 +351,6 @@ do { \ #define this_cpu_cmpxchg_2(pcp, oval, nval) percpu_cmpxchg_op(2, volatile, pcp, oval, nval) #define this_cpu_cmpxchg_4(pcp, oval, nval) percpu_cmpxchg_op(4, volatile, pcp, oval, nval) -#ifdef CONFIG_X86_CMPXCHG64 -#define percpu_cmpxchg8b_double(pcp1, pcp2, o1, o2, n1, n2) \ -({ \ - bool __ret; \ - typeof(pcp1) __o1 = (o1), __n1 = (n1); \ - typeof(pcp2) __o2 = (o2), __n2 = (n2); \ - asm volatile("cmpxchg8b "__percpu_arg(1) \ - CC_SET(z) \ - : CC_OUT(z) (__ret), "+m" (pcp1), "+m" (pcp2), "+a" (__o1), "+d" (__o2) \ - : "b" (__n1), "c" (__n2)); \ - __ret; \ -}) - -#define raw_cpu_cmpxchg_double_4 percpu_cmpxchg8b_double -#define this_cpu_cmpxchg_double_4 percpu_cmpxchg8b_double -#endif /* CONFIG_X86_CMPXCHG64 */ - /* * Per cpu atomic 64 bit operations are only available under 64 bit. * 32 bit must fall back to generic operations. @@ -329,30 +373,6 @@ do { \ #define this_cpu_add_return_8(pcp, val) percpu_add_return_op(8, volatile, pcp, val) #define this_cpu_xchg_8(pcp, nval) percpu_xchg_op(8, volatile, pcp, nval) #define this_cpu_cmpxchg_8(pcp, oval, nval) percpu_cmpxchg_op(8, volatile, pcp, oval, nval) - -/* - * Pretty complex macro to generate cmpxchg16 instruction. The instruction - * is not supported on early AMD64 processors so we must be able to emulate - * it in software. The address used in the cmpxchg16 instruction must be - * aligned to a 16 byte boundary. - */ -#define percpu_cmpxchg16b_double(pcp1, pcp2, o1, o2, n1, n2) \ -({ \ - bool __ret; \ - typeof(pcp1) __o1 = (o1), __n1 = (n1); \ - typeof(pcp2) __o2 = (o2), __n2 = (n2); \ - alternative_io("leaq %P1,%%rsi\n\tcall this_cpu_cmpxchg16b_emu\n\t", \ - "cmpxchg16b " __percpu_arg(1) "\n\tsetz %0\n\t", \ - X86_FEATURE_CX16, \ - ASM_OUTPUT2("=a" (__ret), "+m" (pcp1), \ - "+m" (pcp2), "+d" (__o2)), \ - "b" (__n1), "c" (__n2), "a" (__o1) : "rsi"); \ - __ret; \ -}) - -#define raw_cpu_cmpxchg_double_8 percpu_cmpxchg16b_double -#define this_cpu_cmpxchg_double_8 percpu_cmpxchg16b_double - #endif static __always_inline bool x86_this_cpu_constant_test_bit(unsigned int nr, diff --git a/arch/x86/include/asm/perf_event.h b/arch/x86/include/asm/perf_event.h index abf09882f58b67c20a622a98ced522961b818931..85a9fd5a3ec33176ff3e2dd96aae915136f47864 100644 --- a/arch/x86/include/asm/perf_event.h +++ b/arch/x86/include/asm/perf_event.h @@ -32,11 +32,21 @@ #define ARCH_PERFMON_EVENTSEL_INV (1ULL << 23) #define ARCH_PERFMON_EVENTSEL_CMASK 0xFF000000ULL +#define INTEL_FIXED_BITS_MASK 0xFULL +#define INTEL_FIXED_BITS_STRIDE 4 +#define INTEL_FIXED_0_KERNEL (1ULL << 0) +#define INTEL_FIXED_0_USER (1ULL << 1) +#define INTEL_FIXED_0_ANYTHREAD (1ULL << 2) +#define INTEL_FIXED_0_ENABLE_PMI (1ULL << 3) + #define HSW_IN_TX (1ULL << 32) #define HSW_IN_TX_CHECKPOINTED (1ULL << 33) #define ICL_EVENTSEL_ADAPTIVE (1ULL << 34) #define ICL_FIXED_0_ADAPTIVE (1ULL << 32) +#define intel_fixed_bits_by_idx(_idx, _bits) \ + ((_bits) << ((_idx) * INTEL_FIXED_BITS_STRIDE)) + #define AMD64_EVENTSEL_INT_CORE_ENABLE (1ULL << 36) #define AMD64_EVENTSEL_GUESTONLY (1ULL << 40) #define AMD64_EVENTSEL_HOSTONLY (1ULL << 41) @@ -478,8 +488,10 @@ struct pebs_xmm { #ifdef CONFIG_X86_LOCAL_APIC extern u32 get_ibs_caps(void); +extern int forward_event_to_ibs(struct perf_event *event); #else static inline u32 get_ibs_caps(void) { return 0; } +static inline int forward_event_to_ibs(struct perf_event *event) { return -ENOENT; } #endif #ifdef CONFIG_PERF_EVENTS diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h index 15ae4d6ba4768d19f6cf330839c9926b85941bcc..5700bb3379877efe1818c4fdc35c5e20a4a3f7fb 100644 --- a/arch/x86/include/asm/pgtable.h +++ b/arch/x86/include/asm/pgtable.h @@ -27,6 +27,7 @@ extern pgd_t early_top_pgt[PTRS_PER_PGD]; bool __init __early_make_pgtable(unsigned long address, pmdval_t pmd); +struct seq_file; void ptdump_walk_pgd_level(struct seq_file *m, struct mm_struct *mm); void ptdump_walk_pgd_level_debugfs(struct seq_file *m, struct mm_struct *mm, bool user); diff --git a/arch/x86/include/asm/pgtable_64.h b/arch/x86/include/asm/pgtable_64.h index 7929327abe009112b59ed62436d28af4929e1424..a629b1b9f65a61cad916d6d9f8ef3853b5deadf8 100644 --- a/arch/x86/include/asm/pgtable_64.h +++ b/arch/x86/include/asm/pgtable_64.h @@ -237,8 +237,8 @@ static inline void native_pgd_clear(pgd_t *pgd) #define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val((pte)) }) #define __pmd_to_swp_entry(pmd) ((swp_entry_t) { pmd_val((pmd)) }) -#define __swp_entry_to_pte(x) ((pte_t) { .pte = (x).val }) -#define __swp_entry_to_pmd(x) ((pmd_t) { .pmd = (x).val }) +#define __swp_entry_to_pte(x) (__pte((x).val)) +#define __swp_entry_to_pmd(x) (__pmd((x).val)) extern void cleanup_highmap(void); diff --git a/arch/x86/include/asm/pgtable_types.h b/arch/x86/include/asm/pgtable_types.h index 447d4bee25c48c7650b3adbed4606f54b9188743..ba3e2554799abcae10067eb802a960b2adf5135a 100644 --- a/arch/x86/include/asm/pgtable_types.h +++ b/arch/x86/include/asm/pgtable_types.h @@ -513,9 +513,6 @@ extern void native_pagetable_init(void); #define native_pagetable_init paging_init #endif -struct seq_file; -extern void arch_report_meminfo(struct seq_file *m); - enum pg_level { PG_LEVEL_NONE, PG_LEVEL_4K, diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index a1e4fa58b357464a631f4028879ce28baf9a177b..d46300e94f853ae12659b9cf887b0a96444905b6 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h @@ -551,7 +551,6 @@ extern void switch_gdt_and_percpu_base(int); extern void load_direct_gdt(int); extern void load_fixmap_gdt(int); extern void cpu_init(void); -extern void cpu_init_secondary(void); extern void cpu_init_exception_handling(void); extern void cr4_init(void); diff --git a/arch/x86/include/asm/realmode.h b/arch/x86/include/asm/realmode.h index f6a1737c77be2dc128147978e7f9f85945aed7a6..87e5482acd0dca56c4169a8c5321057447bbf6a5 100644 --- a/arch/x86/include/asm/realmode.h +++ b/arch/x86/include/asm/realmode.h @@ -52,6 +52,7 @@ struct trampoline_header { u64 efer; u32 cr4; u32 flags; + u32 lock; #endif }; @@ -64,6 +65,8 @@ extern unsigned long initial_stack; extern unsigned long initial_vc_handler; #endif +extern u32 *trampoline_lock; + extern unsigned char real_mode_blob[]; extern unsigned char real_mode_relocs[]; diff --git a/arch/x86/include/asm/sev-common.h b/arch/x86/include/asm/sev-common.h index 0759af9b1acfcf4544ecc9d20b461ee35a8e8228..b463fcbd4b9070b005a7b187f0b62c2046163a18 100644 --- a/arch/x86/include/asm/sev-common.h +++ b/arch/x86/include/asm/sev-common.h @@ -106,8 +106,13 @@ enum psc_op { #define GHCB_HV_FT_SNP BIT_ULL(0) #define GHCB_HV_FT_SNP_AP_CREATION BIT_ULL(1) -/* SNP Page State Change NAE event */ -#define VMGEXIT_PSC_MAX_ENTRY 253 +/* + * SNP Page State Change NAE event + * The VMGEXIT_PSC_MAX_ENTRY determines the size of the PSC structure, which + * is a local stack variable in set_pages_state(). Do not increase this value + * without evaluating the impact to stack usage. + */ +#define VMGEXIT_PSC_MAX_ENTRY 64 struct psc_hdr { u16 cur_entry; diff --git a/arch/x86/include/asm/sev.h b/arch/x86/include/asm/sev.h index 13dc2a9d23c1eb258ce4e2b78e74859902dd9f4b..66c806784c5256bd372aa029a364bcdf24e98e84 100644 --- a/arch/x86/include/asm/sev.h +++ b/arch/x86/include/asm/sev.h @@ -14,6 +14,7 @@ #include #include #include +#include #define GHCB_PROTOCOL_MIN 1ULL #define GHCB_PROTOCOL_MAX 2ULL @@ -80,11 +81,15 @@ extern void vc_no_ghcb(void); extern void vc_boot_ghcb(void); extern bool handle_vc_boot_ghcb(struct pt_regs *regs); +/* PVALIDATE return codes */ +#define PVALIDATE_FAIL_SIZEMISMATCH 6 + /* Software defined (when rFlags.CF = 1) */ #define PVALIDATE_FAIL_NOUPDATE 255 /* RMP page size */ #define RMP_PG_SIZE_4K 0 +#define RMP_PG_SIZE_2M 1 #define RMPADJUST_VMSA_PAGE_BIT BIT(16) @@ -136,24 +141,26 @@ struct snp_secrets_page_layout { } __packed; #ifdef CONFIG_AMD_MEM_ENCRYPT -extern struct static_key_false sev_es_enable_key; extern void __sev_es_ist_enter(struct pt_regs *regs); extern void __sev_es_ist_exit(void); static __always_inline void sev_es_ist_enter(struct pt_regs *regs) { - if (static_branch_unlikely(&sev_es_enable_key)) + if (cc_vendor == CC_VENDOR_AMD && + cc_platform_has(CC_ATTR_GUEST_STATE_ENCRYPT)) __sev_es_ist_enter(regs); } static __always_inline void sev_es_ist_exit(void) { - if (static_branch_unlikely(&sev_es_enable_key)) + if (cc_vendor == CC_VENDOR_AMD && + cc_platform_has(CC_ATTR_GUEST_STATE_ENCRYPT)) __sev_es_ist_exit(); } extern int sev_es_setup_ap_jump_table(struct real_mode_header *rmh); extern void __sev_es_nmi_complete(void); static __always_inline void sev_es_nmi_complete(void) { - if (static_branch_unlikely(&sev_es_enable_key)) + if (cc_vendor == CC_VENDOR_AMD && + cc_platform_has(CC_ATTR_GUEST_STATE_ENCRYPT)) __sev_es_nmi_complete(); } extern int __init sev_es_efi_map_ghcbs(pgd_t *pgd); @@ -192,16 +199,17 @@ struct snp_guest_request_ioctl; void setup_ghcb(void); void __init early_snp_set_memory_private(unsigned long vaddr, unsigned long paddr, - unsigned int npages); + unsigned long npages); void __init early_snp_set_memory_shared(unsigned long vaddr, unsigned long paddr, - unsigned int npages); + unsigned long npages); void __init snp_prep_memory(unsigned long paddr, unsigned int sz, enum psc_op op); -void snp_set_memory_shared(unsigned long vaddr, unsigned int npages); -void snp_set_memory_private(unsigned long vaddr, unsigned int npages); +void snp_set_memory_shared(unsigned long vaddr, unsigned long npages); +void snp_set_memory_private(unsigned long vaddr, unsigned long npages); void snp_set_wakeup_secondary_cpu(void); bool snp_init(struct boot_params *bp); void __init __noreturn snp_abort(void); int snp_issue_guest_request(u64 exit_code, struct snp_req_data *input, struct snp_guest_request_ioctl *rio); +void snp_accept_memory(phys_addr_t start, phys_addr_t end); #else static inline void sev_es_ist_enter(struct pt_regs *regs) { } static inline void sev_es_ist_exit(void) { } @@ -212,12 +220,12 @@ static inline int pvalidate(unsigned long vaddr, bool rmp_psize, bool validate) static inline int rmpadjust(unsigned long vaddr, bool rmp_psize, unsigned long attrs) { return 0; } static inline void setup_ghcb(void) { } static inline void __init -early_snp_set_memory_private(unsigned long vaddr, unsigned long paddr, unsigned int npages) { } +early_snp_set_memory_private(unsigned long vaddr, unsigned long paddr, unsigned long npages) { } static inline void __init -early_snp_set_memory_shared(unsigned long vaddr, unsigned long paddr, unsigned int npages) { } +early_snp_set_memory_shared(unsigned long vaddr, unsigned long paddr, unsigned long npages) { } static inline void __init snp_prep_memory(unsigned long paddr, unsigned int sz, enum psc_op op) { } -static inline void snp_set_memory_shared(unsigned long vaddr, unsigned int npages) { } -static inline void snp_set_memory_private(unsigned long vaddr, unsigned int npages) { } +static inline void snp_set_memory_shared(unsigned long vaddr, unsigned long npages) { } +static inline void snp_set_memory_private(unsigned long vaddr, unsigned long npages) { } static inline void snp_set_wakeup_secondary_cpu(void) { } static inline bool snp_init(struct boot_params *bp) { return false; } static inline void snp_abort(void) { } @@ -225,6 +233,8 @@ static inline int snp_issue_guest_request(u64 exit_code, struct snp_req_data *in { return -ENOTTY; } + +static inline void snp_accept_memory(phys_addr_t start, phys_addr_t end) { } #endif #endif diff --git a/arch/x86/include/asm/shared/tdx.h b/arch/x86/include/asm/shared/tdx.h index 2631e01f6e0fb274f78a260a51cec358118c43d6..7513b3bb69b7e4248ca5a58ec33608beeb221b9e 100644 --- a/arch/x86/include/asm/shared/tdx.h +++ b/arch/x86/include/asm/shared/tdx.h @@ -10,6 +10,20 @@ #define TDX_CPUID_LEAF_ID 0x21 #define TDX_IDENT "IntelTDX " +/* TDX module Call Leaf IDs */ +#define TDX_GET_INFO 1 +#define TDX_GET_VEINFO 3 +#define TDX_GET_REPORT 4 +#define TDX_ACCEPT_PAGE 6 +#define TDX_WR 8 + +/* TDCS fields. To be used by TDG.VM.WR and TDG.VM.RD module calls */ +#define TDCS_NOTIFY_ENABLES 0x9100000000000010 + +/* TDX hypercall Leaf IDs */ +#define TDVMCALL_MAP_GPA 0x10001 +#define TDVMCALL_REPORT_FATAL_ERROR 0x10003 + #ifndef __ASSEMBLY__ /* @@ -37,8 +51,58 @@ struct tdx_hypercall_args { u64 __tdx_hypercall(struct tdx_hypercall_args *args); u64 __tdx_hypercall_ret(struct tdx_hypercall_args *args); +/* + * Wrapper for standard use of __tdx_hypercall with no output aside from + * return code. + */ +static inline u64 _tdx_hypercall(u64 fn, u64 r12, u64 r13, u64 r14, u64 r15) +{ + struct tdx_hypercall_args args = { + .r10 = TDX_HYPERCALL_STANDARD, + .r11 = fn, + .r12 = r12, + .r13 = r13, + .r14 = r14, + .r15 = r15, + }; + + return __tdx_hypercall(&args); +} + + /* Called from __tdx_hypercall() for unrecoverable failure */ void __tdx_hypercall_failed(void); +/* + * Used in __tdx_module_call() to gather the output registers' values of the + * TDCALL instruction when requesting services from the TDX module. This is a + * software only structure and not part of the TDX module/VMM ABI + */ +struct tdx_module_output { + u64 rcx; + u64 rdx; + u64 r8; + u64 r9; + u64 r10; + u64 r11; +}; + +/* Used to communicate with the TDX module */ +u64 __tdx_module_call(u64 fn, u64 rcx, u64 rdx, u64 r8, u64 r9, + struct tdx_module_output *out); + +bool tdx_accept_memory(phys_addr_t start, phys_addr_t end); + +/* + * The TDG.VP.VMCALL-Instruction-execution sub-functions are defined + * independently from but are currently matched 1:1 with VMX EXIT_REASONs. + * Reusing the KVM EXIT_REASON macros makes it easier to connect the host and + * guest sides of these calls. + */ +static __always_inline u64 hcall_func(u64 exit_reason) +{ + return exit_reason; +} + #endif /* !__ASSEMBLY__ */ #endif /* _ASM_X86_SHARED_TDX_H */ diff --git a/arch/x86/include/asm/sigframe.h b/arch/x86/include/asm/sigframe.h index 5b1ed650b12489f328c38645cebd66f446603532..84eab27248754233da3d75f9b27cecd8f0fb89ff 100644 --- a/arch/x86/include/asm/sigframe.h +++ b/arch/x86/include/asm/sigframe.h @@ -85,6 +85,4 @@ struct rt_sigframe_x32 { #endif /* CONFIG_X86_64 */ -void __init init_sigframe_size(void); - #endif /* _ASM_X86_SIGFRAME_H */ diff --git a/arch/x86/include/asm/smp.h b/arch/x86/include/asm/smp.h index 4e91054c84be9e6f54c41e1f5f7c3e7c87d4eefa..600cf25dbfc64b0f43a2257cabb50b5c0ce43883 100644 --- a/arch/x86/include/asm/smp.h +++ b/arch/x86/include/asm/smp.h @@ -38,7 +38,9 @@ struct smp_ops { void (*crash_stop_other_cpus)(void); void (*smp_send_reschedule)(int cpu); - int (*cpu_up)(unsigned cpu, struct task_struct *tidle); + void (*cleanup_dead_cpu)(unsigned cpu); + void (*poll_sync_state)(void); + int (*kick_ap_alive)(unsigned cpu, struct task_struct *tidle); int (*cpu_disable)(void); void (*cpu_die)(unsigned int cpu); void (*play_dead)(void); @@ -78,11 +80,6 @@ static inline void smp_cpus_done(unsigned int max_cpus) smp_ops.smp_cpus_done(max_cpus); } -static inline int __cpu_up(unsigned int cpu, struct task_struct *tidle) -{ - return smp_ops.cpu_up(cpu, tidle); -} - static inline int __cpu_disable(void) { return smp_ops.cpu_disable(); @@ -90,7 +87,8 @@ static inline int __cpu_disable(void) static inline void __cpu_die(unsigned int cpu) { - smp_ops.cpu_die(cpu); + if (smp_ops.cpu_die) + smp_ops.cpu_die(cpu); } static inline void __noreturn play_dead(void) @@ -121,22 +119,23 @@ void native_smp_prepare_cpus(unsigned int max_cpus); void calculate_max_logical_packages(void); void native_smp_cpus_done(unsigned int max_cpus); int common_cpu_up(unsigned int cpunum, struct task_struct *tidle); -int native_cpu_up(unsigned int cpunum, struct task_struct *tidle); +int native_kick_ap(unsigned int cpu, struct task_struct *tidle); int native_cpu_disable(void); -int common_cpu_die(unsigned int cpu); -void native_cpu_die(unsigned int cpu); void __noreturn hlt_play_dead(void); void native_play_dead(void); void play_dead_common(void); void wbinvd_on_cpu(int cpu); int wbinvd_on_all_cpus(void); -void cond_wakeup_cpu0(void); + +void smp_kick_mwait_play_dead(void); void native_smp_send_reschedule(int cpu); void native_send_call_func_ipi(const struct cpumask *mask); void native_send_call_func_single_ipi(int cpu); void x86_idle_thread_init(unsigned int cpu, struct task_struct *idle); +bool smp_park_other_cpus_in_init(void); + void smp_store_boot_cpu_info(void); void smp_store_cpu_info(int id); @@ -201,7 +200,14 @@ extern void nmi_selftest(void); #endif extern unsigned int smpboot_control; +extern unsigned long apic_mmio_base; #endif /* !__ASSEMBLY__ */ +/* Control bits for startup_64 */ +#define STARTUP_READ_APICID 0x80000000 + +/* Top 8 bits are reserved for control */ +#define STARTUP_PARALLEL_MASK 0xFF000000 + #endif /* _ASM_X86_SMP_H */ diff --git a/arch/x86/include/asm/switch_to.h b/arch/x86/include/asm/switch_to.h index 5c91305d09d26d5a8d3c6407e7b6fe23b85a28c7..f42dbf17f52b0ee12ec74f34d1fb551743be0e6c 100644 --- a/arch/x86/include/asm/switch_to.h +++ b/arch/x86/include/asm/switch_to.h @@ -12,7 +12,9 @@ struct task_struct *__switch_to_asm(struct task_struct *prev, __visible struct task_struct *__switch_to(struct task_struct *prev, struct task_struct *next); -asmlinkage void ret_from_fork(void); +asmlinkage void ret_from_fork_asm(void); +__visible void ret_from_fork(struct task_struct *prev, struct pt_regs *regs, + int (*fn)(void *), void *fn_arg); /* * This is the structure pointed to by thread.sp for an inactive task. The diff --git a/arch/x86/include/asm/syscall.h b/arch/x86/include/asm/syscall.h index 5b85987a5e97c3d350636b2a3d72ed86f6e589e3..4fb36fba4b5a1f3034345eb640111a8f1f1573c7 100644 --- a/arch/x86/include/asm/syscall.h +++ b/arch/x86/include/asm/syscall.h @@ -127,9 +127,11 @@ static inline int syscall_get_arch(struct task_struct *task) } void do_syscall_64(struct pt_regs *regs, int nr); -void do_int80_syscall_32(struct pt_regs *regs); -long do_fast_syscall_32(struct pt_regs *regs); #endif /* CONFIG_X86_32 */ +void do_int80_syscall_32(struct pt_regs *regs); +long do_fast_syscall_32(struct pt_regs *regs); +long do_SYSENTER_32(struct pt_regs *regs); + #endif /* _ASM_X86_SYSCALL_H */ diff --git a/arch/x86/include/asm/tdx.h b/arch/x86/include/asm/tdx.h index 28d889c9aa163088cfe2d7e769c951a7fad31a19..603e6d1e9d4aac6e0e145f8832ce2a52483a6910 100644 --- a/arch/x86/include/asm/tdx.h +++ b/arch/x86/include/asm/tdx.h @@ -5,6 +5,8 @@ #include #include + +#include #include #include @@ -20,21 +22,6 @@ #ifndef __ASSEMBLY__ -/* - * Used to gather the output registers values of the TDCALL and SEAMCALL - * instructions when requesting services from the TDX module. - * - * This is a software only structure and not part of the TDX module/VMM ABI. - */ -struct tdx_module_output { - u64 rcx; - u64 rdx; - u64 r8; - u64 r9; - u64 r10; - u64 r11; -}; - /* * Used by the #VE exception handler to gather the #VE exception * info from the TDX module. This is a software only structure @@ -55,10 +42,6 @@ struct ve_info { void __init tdx_early_init(void); -/* Used to communicate with the TDX module */ -u64 __tdx_module_call(u64 fn, u64 rcx, u64 rdx, u64 r8, u64 r9, - struct tdx_module_output *out); - void tdx_get_ve_info(struct ve_info *ve); bool tdx_handle_virt_exception(struct pt_regs *regs, struct ve_info *ve); diff --git a/arch/x86/include/asm/thread_info.h b/arch/x86/include/asm/thread_info.h index f1cccba52eb976ed01e1ab21f979e7cf4b62408e..d63b02940747fad97cabfdb399b488d577d36529 100644 --- a/arch/x86/include/asm/thread_info.h +++ b/arch/x86/include/asm/thread_info.h @@ -232,9 +232,6 @@ static inline int arch_within_stack_frames(const void * const stack, current_thread_info()->status & TS_COMPAT) #endif -extern void arch_task_cache_init(void); -extern int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src); -extern void arch_release_task_struct(struct task_struct *tsk); extern void arch_setup_new_exec(void); #define arch_setup_new_exec arch_setup_new_exec #endif /* !__ASSEMBLY__ */ diff --git a/arch/x86/include/asm/time.h b/arch/x86/include/asm/time.h index a53961c64a5671e0bb248fe417c245033e9cba61..f360104ed172ffce0f9256ff3f7073eb08552c59 100644 --- a/arch/x86/include/asm/time.h +++ b/arch/x86/include/asm/time.h @@ -6,7 +6,6 @@ #include extern void hpet_time_init(void); -extern void time_init(void); extern bool pit_timer_init(void); extern bool tsc_clocksource_watchdog_disabled(void); diff --git a/arch/x86/include/asm/tlbflush.h b/arch/x86/include/asm/tlbflush.h index 75bfaa421030328b72542ed803e45dd401fbf210..80450e1d5385aac538817425dbd5132b45172f66 100644 --- a/arch/x86/include/asm/tlbflush.h +++ b/arch/x86/include/asm/tlbflush.h @@ -14,6 +14,8 @@ #include #include +DECLARE_PER_CPU(u64, tlbstate_untag_mask); + void __flush_tlb_all(void); #define TLB_FLUSH_ALL -1UL @@ -54,15 +56,6 @@ static inline void cr4_clear_bits(unsigned long mask) local_irq_restore(flags); } -#ifdef CONFIG_ADDRESS_MASKING -DECLARE_PER_CPU(u64, tlbstate_untag_mask); - -static inline u64 current_untag_mask(void) -{ - return this_cpu_read(tlbstate_untag_mask); -} -#endif - #ifndef MODULE /* * 6 because 6 should be plenty and struct tlb_state will fit in two cache diff --git a/arch/x86/include/asm/topology.h b/arch/x86/include/asm/topology.h index 458c891a82736549469c2c09b38848f18634412a..caf41c4869a0e470fc63a880d355460cbae02a2e 100644 --- a/arch/x86/include/asm/topology.h +++ b/arch/x86/include/asm/topology.h @@ -31,9 +31,9 @@ * CONFIG_NUMA. */ #include +#include #ifdef CONFIG_NUMA -#include #include #include @@ -139,23 +139,31 @@ static inline int topology_max_smt_threads(void) int topology_update_package_map(unsigned int apicid, unsigned int cpu); int topology_update_die_map(unsigned int dieid, unsigned int cpu); int topology_phys_to_logical_pkg(unsigned int pkg); -int topology_phys_to_logical_die(unsigned int die, unsigned int cpu); -bool topology_is_primary_thread(unsigned int cpu); bool topology_smt_supported(void); -#else + +extern struct cpumask __cpu_primary_thread_mask; +#define cpu_primary_thread_mask ((const struct cpumask *)&__cpu_primary_thread_mask) + +/** + * topology_is_primary_thread - Check whether CPU is the primary SMT thread + * @cpu: CPU to check + */ +static inline bool topology_is_primary_thread(unsigned int cpu) +{ + return cpumask_test_cpu(cpu, cpu_primary_thread_mask); +} +#else /* CONFIG_SMP */ #define topology_max_packages() (1) static inline int topology_update_package_map(unsigned int apicid, unsigned int cpu) { return 0; } static inline int topology_update_die_map(unsigned int dieid, unsigned int cpu) { return 0; } static inline int topology_phys_to_logical_pkg(unsigned int pkg) { return 0; } -static inline int topology_phys_to_logical_die(unsigned int die, - unsigned int cpu) { return 0; } static inline int topology_max_die_per_package(void) { return 1; } static inline int topology_max_smt_threads(void) { return 1; } static inline bool topology_is_primary_thread(unsigned int cpu) { return true; } static inline bool topology_smt_supported(void) { return false; } -#endif +#endif /* !CONFIG_SMP */ static inline void arch_fix_phys_package_id(int num, u32 slot) { diff --git a/arch/x86/include/asm/tsc.h b/arch/x86/include/asm/tsc.h index fbdc3d951494358faccee071be1ceb545257dcdb..594fce0ca744398f0086f43582f66fe870b12fa9 100644 --- a/arch/x86/include/asm/tsc.h +++ b/arch/x86/include/asm/tsc.h @@ -32,7 +32,6 @@ extern struct system_counterval_t convert_art_ns_to_tsc(u64 art_ns); extern void tsc_early_init(void); extern void tsc_init(void); -extern unsigned long calibrate_delay_is_known(void); extern void mark_tsc_unstable(char *reason); extern int unsynchronized_tsc(void); extern int check_tsc_unstable(void); @@ -55,12 +54,10 @@ extern bool tsc_async_resets; #ifdef CONFIG_X86_TSC extern bool tsc_store_and_check_tsc_adjust(bool bootcpu); extern void tsc_verify_tsc_adjust(bool resume); -extern void check_tsc_sync_source(int cpu); extern void check_tsc_sync_target(void); #else static inline bool tsc_store_and_check_tsc_adjust(bool bootcpu) { return false; } static inline void tsc_verify_tsc_adjust(bool resume) { } -static inline void check_tsc_sync_source(int cpu) { } static inline void check_tsc_sync_target(void) { } #endif diff --git a/arch/x86/include/asm/unaccepted_memory.h b/arch/x86/include/asm/unaccepted_memory.h new file mode 100644 index 0000000000000000000000000000000000000000..f5937e9866ac119afaa6826af33d9c2399271d0a --- /dev/null +++ b/arch/x86/include/asm/unaccepted_memory.h @@ -0,0 +1,27 @@ +#ifndef _ASM_X86_UNACCEPTED_MEMORY_H +#define _ASM_X86_UNACCEPTED_MEMORY_H + +#include +#include +#include + +static inline void arch_accept_memory(phys_addr_t start, phys_addr_t end) +{ + /* Platform-specific memory-acceptance call goes here */ + if (cpu_feature_enabled(X86_FEATURE_TDX_GUEST)) { + if (!tdx_accept_memory(start, end)) + panic("TDX: Failed to accept memory\n"); + } else if (cc_platform_has(CC_ATTR_GUEST_SEV_SNP)) { + snp_accept_memory(start, end); + } else { + panic("Cannot accept memory: unknown platform\n"); + } +} + +static inline struct efi_unaccepted_memory *efi_get_unaccepted_table(void) +{ + if (efi.unaccepted == EFI_INVALID_TABLE_ADDR) + return NULL; + return __va(efi.unaccepted); +} +#endif diff --git a/arch/x86/include/asm/unwind_hints.h b/arch/x86/include/asm/unwind_hints.h index 01cb9692b160a0ae0e935f3117e618433035a93f..85cc57cb65392e197ef8e6cc79d812890004c386 100644 --- a/arch/x86/include/asm/unwind_hints.h +++ b/arch/x86/include/asm/unwind_hints.h @@ -76,9 +76,18 @@ #else +#define UNWIND_HINT_UNDEFINED \ + UNWIND_HINT(UNWIND_HINT_TYPE_UNDEFINED, 0, 0, 0) + #define UNWIND_HINT_FUNC \ UNWIND_HINT(UNWIND_HINT_TYPE_FUNC, ORC_REG_SP, 8, 0) +#define UNWIND_HINT_SAVE \ + UNWIND_HINT(UNWIND_HINT_TYPE_SAVE, 0, 0, 0) + +#define UNWIND_HINT_RESTORE \ + UNWIND_HINT(UNWIND_HINT_TYPE_RESTORE, 0, 0, 0) + #endif /* __ASSEMBLY__ */ #endif /* _ASM_X86_UNWIND_HINTS_H */ diff --git a/arch/x86/include/asm/uv/uv_hub.h b/arch/x86/include/asm/uv/uv_hub.h index d3e3197917be89f9bb7d9d488bf5a9772ccb9090..5fa76c2ced51fa92db95fc79c383ad27a75fb4fe 100644 --- a/arch/x86/include/asm/uv/uv_hub.h +++ b/arch/x86/include/asm/uv/uv_hub.h @@ -177,6 +177,7 @@ struct uv_hub_info_s { unsigned short nr_possible_cpus; unsigned short nr_online_cpus; short memory_nid; + unsigned short *node_to_socket; }; /* CPU specific info with a pointer to the hub common info struct */ @@ -519,25 +520,30 @@ static inline int uv_socket_to_node(int socket) return _uv_socket_to_node(socket, uv_hub_info->socket_to_node); } +static inline int uv_pnode_to_socket(int pnode) +{ + unsigned short *p2s = uv_hub_info->pnode_to_socket; + + return p2s ? p2s[pnode - uv_hub_info->min_pnode] : pnode; +} + /* pnode, offset --> socket virtual */ static inline void *uv_pnode_offset_to_vaddr(int pnode, unsigned long offset) { unsigned int m_val = uv_hub_info->m_val; unsigned long base; - unsigned short sockid, node, *p2s; + unsigned short sockid; if (m_val) return __va(((unsigned long)pnode << m_val) | offset); - p2s = uv_hub_info->pnode_to_socket; - sockid = p2s ? p2s[pnode - uv_hub_info->min_pnode] : pnode; - node = uv_socket_to_node(sockid); + sockid = uv_pnode_to_socket(pnode); /* limit address of previous socket is our base, except node 0 is 0 */ - if (!node) + if (sockid == 0) return __va((unsigned long)offset); - base = (unsigned long)(uv_hub_info->gr_table[node - 1].limit); + base = (unsigned long)(uv_hub_info->gr_table[sockid - 1].limit); return __va(base << UV_GAM_RANGE_SHFT | offset); } @@ -644,7 +650,7 @@ static inline int uv_cpu_blade_processor_id(int cpu) /* Blade number to Node number (UV2..UV4 is 1:1) */ static inline int uv_blade_to_node(int blade) { - return blade; + return uv_socket_to_node(blade); } /* Blade number of current cpu. Numnbered 0 .. <#blades -1> */ @@ -656,23 +662,27 @@ static inline int uv_numa_blade_id(void) /* * Convert linux node number to the UV blade number. * .. Currently for UV2 thru UV4 the node and the blade are identical. - * .. If this changes then you MUST check references to this function! + * .. UV5 needs conversion when sub-numa clustering is enabled. */ static inline int uv_node_to_blade_id(int nid) { - return nid; + unsigned short *n2s = uv_hub_info->node_to_socket; + + return n2s ? n2s[nid] : nid; } /* Convert a CPU number to the UV blade number */ static inline int uv_cpu_to_blade_id(int cpu) { - return uv_node_to_blade_id(cpu_to_node(cpu)); + return uv_cpu_hub_info(cpu)->numa_blade_id; } /* Convert a blade id to the PNODE of the blade */ static inline int uv_blade_to_pnode(int bid) { - return uv_hub_info_list(uv_blade_to_node(bid))->pnode; + unsigned short *s2p = uv_hub_info->socket_to_pnode; + + return s2p ? s2p[bid] : bid; } /* Nid of memory node on blade. -1 if no blade-local memory */ diff --git a/arch/x86/include/asm/uv/uv_mmrs.h b/arch/x86/include/asm/uv/uv_mmrs.h index 57fa67373262965470b2463d6a686f85da68be32..bb45812889ddb8206169ccf641dd6d072da8df65 100644 --- a/arch/x86/include/asm/uv/uv_mmrs.h +++ b/arch/x86/include/asm/uv/uv_mmrs.h @@ -4199,6 +4199,13 @@ union uvh_rh_gam_mmioh_overlay_config1_u { #define UV3H_RH_GAM_MMIOH_REDIRECT_CONFIG0_NASID_SHFT 0 #define UV3H_RH_GAM_MMIOH_REDIRECT_CONFIG0_NASID_MASK 0x0000000000007fffUL +/* UVH common defines */ +#define UVH_RH_GAM_MMIOH_REDIRECT_CONFIG0_NASID_MASK ( \ + is_uv(UV4A) ? UV4AH_RH_GAM_MMIOH_REDIRECT_CONFIG0_NASID_MASK : \ + is_uv(UV4) ? UV4H_RH_GAM_MMIOH_REDIRECT_CONFIG0_NASID_MASK : \ + is_uv(UV3) ? UV3H_RH_GAM_MMIOH_REDIRECT_CONFIG0_NASID_MASK : \ + 0) + union uvh_rh_gam_mmioh_redirect_config0_u { unsigned long v; @@ -4247,8 +4254,8 @@ union uvh_rh_gam_mmioh_redirect_config0_u { 0) /* UV4A unique defines */ -#define UV4AH_RH_GAM_MMIOH_REDIRECT_CONFIG0_NASID_SHFT 0 -#define UV4AH_RH_GAM_MMIOH_REDIRECT_CONFIG0_NASID_MASK 0x0000000000000fffUL +#define UV4AH_RH_GAM_MMIOH_REDIRECT_CONFIG1_NASID_SHFT 0 +#define UV4AH_RH_GAM_MMIOH_REDIRECT_CONFIG1_NASID_MASK 0x0000000000000fffUL /* UV4 unique defines */ #define UV4H_RH_GAM_MMIOH_REDIRECT_CONFIG1_NASID_SHFT 0 @@ -4258,6 +4265,13 @@ union uvh_rh_gam_mmioh_redirect_config0_u { #define UV3H_RH_GAM_MMIOH_REDIRECT_CONFIG1_NASID_SHFT 0 #define UV3H_RH_GAM_MMIOH_REDIRECT_CONFIG1_NASID_MASK 0x0000000000007fffUL +/* UVH common defines */ +#define UVH_RH_GAM_MMIOH_REDIRECT_CONFIG1_NASID_MASK ( \ + is_uv(UV4A) ? UV4AH_RH_GAM_MMIOH_REDIRECT_CONFIG1_NASID_MASK : \ + is_uv(UV4) ? UV4H_RH_GAM_MMIOH_REDIRECT_CONFIG1_NASID_MASK : \ + is_uv(UV3) ? UV3H_RH_GAM_MMIOH_REDIRECT_CONFIG1_NASID_MASK : \ + 0) + union uvh_rh_gam_mmioh_redirect_config1_u { unsigned long v; diff --git a/arch/x86/include/asm/vdso/gettimeofday.h b/arch/x86/include/asm/vdso/gettimeofday.h index 4cf6794f9d688d78de5751767f0d264919a681dd..c81858d903dc0fadcfdb0b63e07e4ceeae0981e7 100644 --- a/arch/x86/include/asm/vdso/gettimeofday.h +++ b/arch/x86/include/asm/vdso/gettimeofday.h @@ -231,14 +231,19 @@ static u64 vread_pvclock(void) ret = __pvclock_read_cycles(pvti, rdtsc_ordered()); } while (pvclock_read_retry(pvti, version)); - return ret; + return ret & S64_MAX; } #endif #ifdef CONFIG_HYPERV_TIMER static u64 vread_hvclock(void) { - return hv_read_tsc_page(&hvclock_page); + u64 tsc, time; + + if (hv_read_tsc_page_tsc(&hvclock_page, &tsc, &time)) + return time & S64_MAX; + + return U64_MAX; } #endif @@ -246,7 +251,7 @@ static inline u64 __arch_get_hw_counter(s32 clock_mode, const struct vdso_data *vd) { if (likely(clock_mode == VDSO_CLOCKMODE_TSC)) - return (u64)rdtsc_ordered(); + return (u64)rdtsc_ordered() & S64_MAX; /* * For any memory-mapped vclock type, we need to make sure that gcc * doesn't cleverly hoist a load before the mode check. Otherwise we @@ -284,6 +289,9 @@ static inline bool arch_vdso_clocksource_ok(const struct vdso_data *vd) * which can be invalidated asynchronously and indicate invalidation by * returning U64_MAX, which can be effectively tested by checking for a * negative value after casting it to s64. + * + * This effectively forces a S64_MAX mask on the calculations, unlike the + * U64_MAX mask normally used by x86 clocksources. */ static inline bool arch_vdso_cycles_ok(u64 cycles) { @@ -303,18 +311,29 @@ static inline bool arch_vdso_cycles_ok(u64 cycles) * @last. If not then use @last, which is the base time of the current * conversion period. * - * This variant also removes the masking of the subtraction because the - * clocksource mask of all VDSO capable clocksources on x86 is U64_MAX - * which would result in a pointless operation. The compiler cannot - * optimize it away as the mask comes from the vdso data and is not compile - * time constant. + * This variant also uses a custom mask because while the clocksource mask of + * all the VDSO capable clocksources on x86 is U64_MAX, the above code uses + * U64_MASK as an exception value, additionally arch_vdso_cycles_ok() above + * declares everything with the MSB/Sign-bit set as invalid. Therefore the + * effective mask is S64_MAX. */ static __always_inline u64 vdso_calc_delta(u64 cycles, u64 last, u64 mask, u32 mult) { - if (cycles > last) - return (cycles - last) * mult; - return 0; + /* + * Due to the MSB/Sign-bit being used as invald marker (see + * arch_vdso_cycles_valid() above), the effective mask is S64_MAX. + */ + u64 delta = (cycles - last) & S64_MAX; + + /* + * Due to the above mentioned TSC wobbles, filter out negative motion. + * Per the above masking, the effective sign bit is now bit 62. + */ + if (unlikely(delta & (1ULL << 62))) + return 0; + + return delta * mult; } #define vdso_calc_delta vdso_calc_delta diff --git a/arch/x86/include/asm/x86_init.h b/arch/x86/include/asm/x86_init.h index 88085f369ff6fbec1a06de400655be3d2540664e..5240d88db52a70d4211d7a8d2c7758f22e9432f8 100644 --- a/arch/x86/include/asm/x86_init.h +++ b/arch/x86/include/asm/x86_init.h @@ -150,7 +150,7 @@ struct x86_init_acpi { * @enc_cache_flush_required Returns true if a cache flush is needed before changing page encryption status */ struct x86_guest { - void (*enc_status_change_prepare)(unsigned long vaddr, int npages, bool enc); + bool (*enc_status_change_prepare)(unsigned long vaddr, int npages, bool enc); bool (*enc_status_change_finish)(unsigned long vaddr, int npages, bool enc); bool (*enc_tlb_flush_required)(bool enc); bool (*enc_cache_flush_required)(void); @@ -177,11 +177,14 @@ struct x86_init_ops { * struct x86_cpuinit_ops - platform specific cpu hotplug setups * @setup_percpu_clockev: set up the per cpu clock event device * @early_percpu_clock_init: early init of the per cpu clock event device + * @fixup_cpu_id: fixup function for cpuinfo_x86::phys_proc_id + * @parallel_bringup: Parallel bringup control */ struct x86_cpuinit_ops { void (*setup_percpu_clockev)(void); void (*early_percpu_clock_init)(void); void (*fixup_cpu_id)(struct cpuinfo_x86 *c, int node); + bool parallel_bringup; }; struct timespec64; diff --git a/arch/x86/include/uapi/asm/mtrr.h b/arch/x86/include/uapi/asm/mtrr.h index 376563f2bac1f5d93ab53b32c32ae0ea4b55e652..3a8a8eb8ac3a353d1748002b0c6c9a2b52b52ebb 100644 --- a/arch/x86/include/uapi/asm/mtrr.h +++ b/arch/x86/include/uapi/asm/mtrr.h @@ -81,14 +81,6 @@ typedef __u8 mtrr_type; #define MTRR_NUM_FIXED_RANGES 88 #define MTRR_MAX_VAR_RANGES 256 -struct mtrr_state_type { - struct mtrr_var_range var_ranges[MTRR_MAX_VAR_RANGES]; - mtrr_type fixed_ranges[MTRR_NUM_FIXED_RANGES]; - unsigned char enabled; - unsigned char have_fixed; - mtrr_type def_type; -}; - #define MTRRphysBase_MSR(reg) (0x200 + 2 * (reg)) #define MTRRphysMask_MSR(reg) (0x200 + 2 * (reg) + 1) @@ -115,9 +107,9 @@ struct mtrr_state_type { #define MTRR_NUM_TYPES 7 /* - * Invalid MTRR memory type. mtrr_type_lookup() returns this value when - * MTRRs are disabled. Note, this value is allocated from the reserved - * values (0x7-0xff) of the MTRR memory types. + * Invalid MTRR memory type. No longer used outside of MTRR code. + * Note, this value is allocated from the reserved values (0x7-0xff) of + * the MTRR memory types. */ #define MTRR_TYPE_INVALID 0xff diff --git a/arch/x86/kernel/acpi/sleep.c b/arch/x86/kernel/acpi/sleep.c index 1328c221af30e8dba1ef7c89a679de3c64132a08..6dfecb27b84611e9b1fa3bde3e60426812d657e6 100644 --- a/arch/x86/kernel/acpi/sleep.c +++ b/arch/x86/kernel/acpi/sleep.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include "../../realmode/rm/wakeup.h" @@ -127,7 +128,13 @@ int x86_acpi_suspend_lowlevel(void) * value is in the actual %rsp register. */ current->thread.sp = (unsigned long)temp_stack + sizeof(temp_stack); - smpboot_control = smp_processor_id(); + /* + * Ensure the CPU knows which one it is when it comes back, if + * it isn't in parallel mode and expected to work that out for + * itself. + */ + if (!(smpboot_control & STARTUP_PARALLEL_MASK)) + smpboot_control = smp_processor_id(); #endif initial_code = (unsigned long)wakeup_long64; saved_magic = 0x123456789abcdef0L; diff --git a/arch/x86/kernel/acpi/sleep.h b/arch/x86/kernel/acpi/sleep.h index 171a40c74db68e52b04613b000529d213a59837c..054c15a2f860ebf25317b384d2d05172e2f7c371 100644 --- a/arch/x86/kernel/acpi/sleep.h +++ b/arch/x86/kernel/acpi/sleep.h @@ -12,7 +12,6 @@ extern int wakeup_pmode_return; extern u8 wake_sleep_flags; -extern unsigned long acpi_copy_wakeup_routine(unsigned long); extern void wakeup_long64(void); extern void do_suspend_lowlevel(void); diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c index f615e0cb6d932cf6399ccff4c8056a6a42fd5180..2dcf3a06af0908b6dc67594daff54d7555b9fc83 100644 --- a/arch/x86/kernel/alternative.c +++ b/arch/x86/kernel/alternative.c @@ -37,11 +37,23 @@ EXPORT_SYMBOL_GPL(alternatives_patched); #define MAX_PATCH_LEN (255-1) -static int __initdata_or_module debug_alternative; +#define DA_ALL (~0) +#define DA_ALT 0x01 +#define DA_RET 0x02 +#define DA_RETPOLINE 0x04 +#define DA_ENDBR 0x08 +#define DA_SMP 0x10 + +static unsigned int __initdata_or_module debug_alternative; static int __init debug_alt(char *str) { - debug_alternative = 1; + if (str && *str == '=') + str++; + + if (!str || kstrtouint(str, 0, &debug_alternative)) + debug_alternative = DA_ALL; + return 1; } __setup("debug-alternative", debug_alt); @@ -55,15 +67,15 @@ static int __init setup_noreplace_smp(char *str) } __setup("noreplace-smp", setup_noreplace_smp); -#define DPRINTK(fmt, args...) \ +#define DPRINTK(type, fmt, args...) \ do { \ - if (debug_alternative) \ + if (debug_alternative & DA_##type) \ printk(KERN_DEBUG pr_fmt(fmt) "\n", ##args); \ } while (0) -#define DUMP_BYTES(buf, len, fmt, args...) \ +#define DUMP_BYTES(type, buf, len, fmt, args...) \ do { \ - if (unlikely(debug_alternative)) { \ + if (unlikely(debug_alternative & DA_##type)) { \ int j; \ \ if (!(len)) \ @@ -86,6 +98,11 @@ static const unsigned char x86nops[] = BYTES_NOP6, BYTES_NOP7, BYTES_NOP8, +#ifdef CONFIG_64BIT + BYTES_NOP9, + BYTES_NOP10, + BYTES_NOP11, +#endif }; const unsigned char * const x86_nops[ASM_NOP_MAX+1] = @@ -99,19 +116,44 @@ const unsigned char * const x86_nops[ASM_NOP_MAX+1] = x86nops + 1 + 2 + 3 + 4 + 5, x86nops + 1 + 2 + 3 + 4 + 5 + 6, x86nops + 1 + 2 + 3 + 4 + 5 + 6 + 7, +#ifdef CONFIG_64BIT + x86nops + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8, + x86nops + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9, + x86nops + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10, +#endif }; -/* Use this to add nops to a buffer, then text_poke the whole buffer. */ -static void __init_or_module add_nops(void *insns, unsigned int len) +/* + * Fill the buffer with a single effective instruction of size @len. + * + * In order not to issue an ORC stack depth tracking CFI entry (Call Frame Info) + * for every single-byte NOP, try to generate the maximally available NOP of + * size <= ASM_NOP_MAX such that only a single CFI entry is generated (vs one for + * each single-byte NOPs). If @len to fill out is > ASM_NOP_MAX, pad with INT3 and + * *jump* over instead of executing long and daft NOPs. + */ +static void __init_or_module add_nop(u8 *instr, unsigned int len) { - while (len > 0) { - unsigned int noplen = len; - if (noplen > ASM_NOP_MAX) - noplen = ASM_NOP_MAX; - memcpy(insns, x86_nops[noplen], noplen); - insns += noplen; - len -= noplen; + u8 *target = instr + len; + + if (!len) + return; + + if (len <= ASM_NOP_MAX) { + memcpy(instr, x86_nops[len], len); + return; + } + + if (len < 128) { + __text_gen_insn(instr, JMP8_INSN_OPCODE, instr, target, JMP8_INSN_SIZE); + instr += JMP8_INSN_SIZE; + } else { + __text_gen_insn(instr, JMP32_INSN_OPCODE, instr, target, JMP32_INSN_SIZE); + instr += JMP32_INSN_SIZE; } + + for (;instr < target; instr++) + *instr = INT3_INSN_OPCODE; } extern s32 __retpoline_sites[], __retpoline_sites_end[]; @@ -123,133 +165,223 @@ extern s32 __smp_locks[], __smp_locks_end[]; void text_poke_early(void *addr, const void *opcode, size_t len); /* - * Are we looking at a near JMP with a 1 or 4-byte displacement. + * Matches NOP and NOPL, not any of the other possible NOPs. */ -static inline bool is_jmp(const u8 opcode) +static bool insn_is_nop(struct insn *insn) { - return opcode == 0xeb || opcode == 0xe9; + /* Anything NOP, but no REP NOP */ + if (insn->opcode.bytes[0] == 0x90 && + (!insn->prefixes.nbytes || insn->prefixes.bytes[0] != 0xF3)) + return true; + + /* NOPL */ + if (insn->opcode.bytes[0] == 0x0F && insn->opcode.bytes[1] == 0x1F) + return true; + + /* TODO: more nops */ + + return false; } -static void __init_or_module -recompute_jump(struct alt_instr *a, u8 *orig_insn, u8 *repl_insn, u8 *insn_buff) +/* + * Find the offset of the first non-NOP instruction starting at @offset + * but no further than @len. + */ +static int skip_nops(u8 *instr, int offset, int len) { - u8 *next_rip, *tgt_rip; - s32 n_dspl, o_dspl; - int repl_len; + struct insn insn; - if (a->replacementlen != 5) - return; + for (; offset < len; offset += insn.length) { + if (insn_decode_kernel(&insn, &instr[offset])) + break; - o_dspl = *(s32 *)(insn_buff + 1); + if (!insn_is_nop(&insn)) + break; + } - /* next_rip of the replacement JMP */ - next_rip = repl_insn + a->replacementlen; - /* target rip of the replacement JMP */ - tgt_rip = next_rip + o_dspl; - n_dspl = tgt_rip - orig_insn; + return offset; +} - DPRINTK("target RIP: %px, new_displ: 0x%x", tgt_rip, n_dspl); +/* + * Optimize a sequence of NOPs, possibly preceded by an unconditional jump + * to the end of the NOP sequence into a single NOP. + */ +static bool __init_or_module +__optimize_nops(u8 *instr, size_t len, struct insn *insn, int *next, int *prev, int *target) +{ + int i = *next - insn->length; - if (tgt_rip - orig_insn >= 0) { - if (n_dspl - 2 <= 127) - goto two_byte_jmp; - else - goto five_byte_jmp; - /* negative offset */ - } else { - if (((n_dspl - 2) & 0xff) == (n_dspl - 2)) - goto two_byte_jmp; - else - goto five_byte_jmp; + switch (insn->opcode.bytes[0]) { + case JMP8_INSN_OPCODE: + case JMP32_INSN_OPCODE: + *prev = i; + *target = *next + insn->immediate.value; + return false; } -two_byte_jmp: - n_dspl -= 2; + if (insn_is_nop(insn)) { + int nop = i; - insn_buff[0] = 0xeb; - insn_buff[1] = (s8)n_dspl; - add_nops(insn_buff + 2, 3); + *next = skip_nops(instr, *next, len); + if (*target && *next == *target) + nop = *prev; - repl_len = 2; - goto done; + add_nop(instr + nop, *next - nop); + DUMP_BYTES(ALT, instr, len, "%px: [%d:%d) optimized NOPs: ", instr, nop, *next); + return true; + } -five_byte_jmp: - n_dspl -= 5; + *target = 0; + return false; +} - insn_buff[0] = 0xe9; - *(s32 *)&insn_buff[1] = n_dspl; +/* + * "noinline" to cause control flow change and thus invalidate I$ and + * cause refetch after modification. + */ +static void __init_or_module noinline optimize_nops(u8 *instr, size_t len) +{ + int prev, target = 0; - repl_len = 5; + for (int next, i = 0; i < len; i = next) { + struct insn insn; -done: + if (insn_decode_kernel(&insn, &instr[i])) + return; + + next = i + insn.length; - DPRINTK("final displ: 0x%08x, JMP 0x%lx", - n_dspl, (unsigned long)orig_insn + n_dspl + repl_len); + __optimize_nops(instr, len, &insn, &next, &prev, &target); + } } /* - * optimize_nops_range() - Optimize a sequence of single byte NOPs (0x90) + * In this context, "source" is where the instructions are placed in the + * section .altinstr_replacement, for example during kernel build by the + * toolchain. + * "Destination" is where the instructions are being patched in by this + * machinery. + * + * The source offset is: + * + * src_imm = target - src_next_ip (1) * - * @instr: instruction byte stream - * @instrlen: length of the above - * @off: offset within @instr where the first NOP has been detected + * and the target offset is: * - * Return: number of NOPs found (and replaced). + * dst_imm = target - dst_next_ip (2) + * + * so rework (1) as an expression for target like: + * + * target = src_imm + src_next_ip (1a) + * + * and substitute in (2) to get: + * + * dst_imm = (src_imm + src_next_ip) - dst_next_ip (3) + * + * Now, since the instruction stream is 'identical' at src and dst (it + * is being copied after all) it can be stated that: + * + * src_next_ip = src + ip_offset + * dst_next_ip = dst + ip_offset (4) + * + * Substitute (4) in (3) and observe ip_offset being cancelled out to + * obtain: + * + * dst_imm = src_imm + (src + ip_offset) - (dst + ip_offset) + * = src_imm + src - dst + ip_offset - ip_offset + * = src_imm + src - dst (5) + * + * IOW, only the relative displacement of the code block matters. */ -static __always_inline int optimize_nops_range(u8 *instr, u8 instrlen, int off) -{ - unsigned long flags; - int i = off, nnops; - while (i < instrlen) { - if (instr[i] != 0x90) - break; +#define apply_reloc_n(n_, p_, d_) \ + do { \ + s32 v = *(s##n_ *)(p_); \ + v += (d_); \ + BUG_ON((v >> 31) != (v >> (n_-1))); \ + *(s##n_ *)(p_) = (s##n_)v; \ + } while (0) - i++; + +static __always_inline +void apply_reloc(int n, void *ptr, uintptr_t diff) +{ + switch (n) { + case 1: apply_reloc_n(8, ptr, diff); break; + case 2: apply_reloc_n(16, ptr, diff); break; + case 4: apply_reloc_n(32, ptr, diff); break; + default: BUG(); } +} - nnops = i - off; +static __always_inline +bool need_reloc(unsigned long offset, u8 *src, size_t src_len) +{ + u8 *target = src + offset; + /* + * If the target is inside the patched block, it's relative to the + * block itself and does not need relocation. + */ + return (target < src || target > src + src_len); +} - if (nnops <= 1) - return nnops; +static void __init_or_module noinline +apply_relocation(u8 *buf, size_t len, u8 *dest, u8 *src, size_t src_len) +{ + int prev, target = 0; - local_irq_save(flags); - add_nops(instr + off, nnops); - local_irq_restore(flags); + for (int next, i = 0; i < len; i = next) { + struct insn insn; - DUMP_BYTES(instr, instrlen, "%px: [%d:%d) optimized NOPs: ", instr, off, i); + if (WARN_ON_ONCE(insn_decode_kernel(&insn, &buf[i]))) + return; - return nnops; -} + next = i + insn.length; -/* - * "noinline" to cause control flow change and thus invalidate I$ and - * cause refetch after modification. - */ -static void __init_or_module noinline optimize_nops(u8 *instr, size_t len) -{ - struct insn insn; - int i = 0; + if (__optimize_nops(buf, len, &insn, &next, &prev, &target)) + continue; - /* - * Jump over the non-NOP insns and optimize single-byte NOPs into bigger - * ones. - */ - for (;;) { - if (insn_decode_kernel(&insn, &instr[i])) - return; + switch (insn.opcode.bytes[0]) { + case 0x0f: + if (insn.opcode.bytes[1] < 0x80 || + insn.opcode.bytes[1] > 0x8f) + break; - /* - * See if this and any potentially following NOPs can be - * optimized. - */ - if (insn.length == 1 && insn.opcode.bytes[0] == 0x90) - i += optimize_nops_range(instr, len, i); - else - i += insn.length; + fallthrough; /* Jcc.d32 */ + case 0x70 ... 0x7f: /* Jcc.d8 */ + case JMP8_INSN_OPCODE: + case JMP32_INSN_OPCODE: + case CALL_INSN_OPCODE: + if (need_reloc(next + insn.immediate.value, src, src_len)) { + apply_reloc(insn.immediate.nbytes, + buf + i + insn_offset_immediate(&insn), + src - dest); + } - if (i >= len) - return; + /* + * Where possible, convert JMP.d32 into JMP.d8. + */ + if (insn.opcode.bytes[0] == JMP32_INSN_OPCODE) { + s32 imm = insn.immediate.value; + imm += src - dest; + imm += JMP32_INSN_SIZE - JMP8_INSN_SIZE; + if ((imm >> 31) == (imm >> 7)) { + buf[i+0] = JMP8_INSN_OPCODE; + buf[i+1] = (s8)imm; + + memset(&buf[i+2], INT3_INSN_OPCODE, insn.length - 2); + } + } + break; + } + + if (insn_rip_relative(&insn)) { + if (need_reloc(next + insn.displacement.value, src, src_len)) { + apply_reloc(insn.displacement.nbytes, + buf + i + insn_offset_displacement(&insn), + src - dest); + } + } } } @@ -270,7 +402,7 @@ void __init_or_module noinline apply_alternatives(struct alt_instr *start, u8 *instr, *replacement; u8 insn_buff[MAX_PATCH_LEN]; - DPRINTK("alt table %px, -> %px", start, end); + DPRINTK(ALT, "alt table %px, -> %px", start, end); /* * The scan order should be from start to end. A later scanned * alternative code can overwrite previously scanned alternative code. @@ -294,47 +426,31 @@ void __init_or_module noinline apply_alternatives(struct alt_instr *start, * - feature not present but ALT_FLAG_NOT is set to mean, * patch if feature is *NOT* present. */ - if (!boot_cpu_has(a->cpuid) == !(a->flags & ALT_FLAG_NOT)) - goto next; + if (!boot_cpu_has(a->cpuid) == !(a->flags & ALT_FLAG_NOT)) { + optimize_nops(instr, a->instrlen); + continue; + } - DPRINTK("feat: %s%d*32+%d, old: (%pS (%px) len: %d), repl: (%px, len: %d)", + DPRINTK(ALT, "feat: %s%d*32+%d, old: (%pS (%px) len: %d), repl: (%px, len: %d)", (a->flags & ALT_FLAG_NOT) ? "!" : "", a->cpuid >> 5, a->cpuid & 0x1f, instr, instr, a->instrlen, replacement, a->replacementlen); - DUMP_BYTES(instr, a->instrlen, "%px: old_insn: ", instr); - DUMP_BYTES(replacement, a->replacementlen, "%px: rpl_insn: ", replacement); - memcpy(insn_buff, replacement, a->replacementlen); insn_buff_sz = a->replacementlen; - /* - * 0xe8 is a relative jump; fix the offset. - * - * Instruction length is checked before the opcode to avoid - * accessing uninitialized bytes for zero-length replacements. - */ - if (a->replacementlen == 5 && *insn_buff == 0xe8) { - *(s32 *)(insn_buff + 1) += replacement - instr; - DPRINTK("Fix CALL offset: 0x%x, CALL 0x%lx", - *(s32 *)(insn_buff + 1), - (unsigned long)instr + *(s32 *)(insn_buff + 1) + 5); - } - - if (a->replacementlen && is_jmp(replacement[0])) - recompute_jump(a, instr, replacement, insn_buff); - for (; insn_buff_sz < a->instrlen; insn_buff_sz++) insn_buff[insn_buff_sz] = 0x90; - DUMP_BYTES(insn_buff, insn_buff_sz, "%px: final_insn: ", instr); + apply_relocation(insn_buff, a->instrlen, instr, replacement, a->replacementlen); - text_poke_early(instr, insn_buff, insn_buff_sz); + DUMP_BYTES(ALT, instr, a->instrlen, "%px: old_insn: ", instr); + DUMP_BYTES(ALT, replacement, a->replacementlen, "%px: rpl_insn: ", replacement); + DUMP_BYTES(ALT, insn_buff, insn_buff_sz, "%px: final_insn: ", instr); -next: - optimize_nops(instr, a->instrlen); + text_poke_early(instr, insn_buff, insn_buff_sz); } } @@ -555,15 +671,15 @@ void __init_or_module noinline apply_retpolines(s32 *start, s32 *end) continue; } - DPRINTK("retpoline at: %pS (%px) len: %d to: %pS", + DPRINTK(RETPOLINE, "retpoline at: %pS (%px) len: %d to: %pS", addr, addr, insn.length, addr + insn.length + insn.immediate.value); len = patch_retpoline(addr, &insn, bytes); if (len == insn.length) { optimize_nops(bytes, len); - DUMP_BYTES(((u8*)addr), len, "%px: orig: ", addr); - DUMP_BYTES(((u8*)bytes), len, "%px: repl: ", addr); + DUMP_BYTES(RETPOLINE, ((u8*)addr), len, "%px: orig: ", addr); + DUMP_BYTES(RETPOLINE, ((u8*)bytes), len, "%px: repl: ", addr); text_poke_early(addr, bytes, len); } } @@ -590,13 +706,12 @@ static int patch_return(void *addr, struct insn *insn, u8 *bytes) { int i = 0; + /* Patch the custom return thunks... */ if (cpu_feature_enabled(X86_FEATURE_RETHUNK)) { - if (x86_return_thunk == __x86_return_thunk) - return -1; - i = JMP32_INSN_SIZE; __text_gen_insn(bytes, JMP32_INSN_OPCODE, addr, x86_return_thunk, i); } else { + /* ... or patch them out if not needed. */ bytes[i++] = RET_INSN_OPCODE; } @@ -609,6 +724,14 @@ void __init_or_module noinline apply_returns(s32 *start, s32 *end) { s32 *s; + /* + * Do not patch out the default return thunks if those needed are the + * ones generated by the compiler. + */ + if (cpu_feature_enabled(X86_FEATURE_RETHUNK) && + (x86_return_thunk == __x86_return_thunk)) + return; + for (s = start; s < end; s++) { void *dest = NULL, *addr = (void *)s + *s; struct insn insn; @@ -630,14 +753,14 @@ void __init_or_module noinline apply_returns(s32 *start, s32 *end) addr, dest, 5, addr)) continue; - DPRINTK("return thunk at: %pS (%px) len: %d to: %pS", + DPRINTK(RET, "return thunk at: %pS (%px) len: %d to: %pS", addr, addr, insn.length, addr + insn.length + insn.immediate.value); len = patch_return(addr, &insn, bytes); if (len == insn.length) { - DUMP_BYTES(((u8*)addr), len, "%px: orig: ", addr); - DUMP_BYTES(((u8*)bytes), len, "%px: repl: ", addr); + DUMP_BYTES(RET, ((u8*)addr), len, "%px: orig: ", addr); + DUMP_BYTES(RET, ((u8*)bytes), len, "%px: repl: ", addr); text_poke_early(addr, bytes, len); } } @@ -655,7 +778,9 @@ void __init_or_module noinline apply_returns(s32 *start, s32 *end) { } #ifdef CONFIG_X86_KERNEL_IBT -static void poison_endbr(void *addr, bool warn) +static void poison_cfi(void *addr); + +static void __init_or_module poison_endbr(void *addr, bool warn) { u32 endbr, poison = gen_endbr_poison(); @@ -667,20 +792,23 @@ static void poison_endbr(void *addr, bool warn) return; } - DPRINTK("ENDBR at: %pS (%px)", addr, addr); + DPRINTK(ENDBR, "ENDBR at: %pS (%px)", addr, addr); /* * When we have IBT, the lack of ENDBR will trigger #CP */ - DUMP_BYTES(((u8*)addr), 4, "%px: orig: ", addr); - DUMP_BYTES(((u8*)&poison), 4, "%px: repl: ", addr); + DUMP_BYTES(ENDBR, ((u8*)addr), 4, "%px: orig: ", addr); + DUMP_BYTES(ENDBR, ((u8*)&poison), 4, "%px: repl: ", addr); text_poke_early(addr, &poison, 4); } /* * Generated by: objtool --ibt + * + * Seal the functions for indirect calls by clobbering the ENDBR instructions + * and the kCFI hash value. */ -void __init_or_module noinline apply_ibt_endbr(s32 *start, s32 *end) +void __init_or_module noinline apply_seal_endbr(s32 *start, s32 *end) { s32 *s; @@ -689,13 +817,13 @@ void __init_or_module noinline apply_ibt_endbr(s32 *start, s32 *end) poison_endbr(addr, true); if (IS_ENABLED(CONFIG_FINEIBT)) - poison_endbr(addr - 16, false); + poison_cfi(addr - 16); } } #else -void __init_or_module apply_ibt_endbr(s32 *start, s32 *end) { } +void __init_or_module apply_seal_endbr(s32 *start, s32 *end) { } #endif /* CONFIG_X86_KERNEL_IBT */ @@ -940,6 +1068,17 @@ static int cfi_rewrite_preamble(s32 *start, s32 *end) return 0; } +static void cfi_rewrite_endbr(s32 *start, s32 *end) +{ + s32 *s; + + for (s = start; s < end; s++) { + void *addr = (void *)s + *s; + + poison_endbr(addr+16, false); + } +} + /* .retpoline_sites */ static int cfi_rand_callers(s32 *start, s32 *end) { @@ -1034,14 +1173,19 @@ static void __apply_fineibt(s32 *start_retpoline, s32 *end_retpoline, return; case CFI_FINEIBT: + /* place the FineIBT preamble at func()-16 */ ret = cfi_rewrite_preamble(start_cfi, end_cfi); if (ret) goto err; + /* rewrite the callers to target func()-16 */ ret = cfi_rewrite_callers(start_retpoline, end_retpoline); if (ret) goto err; + /* now that nobody targets func()+0, remove ENDBR there */ + cfi_rewrite_endbr(start_cfi, end_cfi); + if (builtin) pr_info("Using FineIBT CFI\n"); return; @@ -1054,6 +1198,41 @@ static void __apply_fineibt(s32 *start_retpoline, s32 *end_retpoline, pr_err("Something went horribly wrong trying to rewrite the CFI implementation.\n"); } +static inline void poison_hash(void *addr) +{ + *(u32 *)addr = 0; +} + +static void poison_cfi(void *addr) +{ + switch (cfi_mode) { + case CFI_FINEIBT: + /* + * __cfi_\func: + * osp nopl (%rax) + * subl $0, %r10d + * jz 1f + * ud2 + * 1: nop + */ + poison_endbr(addr, false); + poison_hash(addr + fineibt_preamble_hash); + break; + + case CFI_KCFI: + /* + * __cfi_\func: + * movl $0, %eax + * .skip 11, 0x90 + */ + poison_hash(addr + 1); + break; + + default: + break; + } +} + #else static void __apply_fineibt(s32 *start_retpoline, s32 *end_retpoline, @@ -1061,6 +1240,10 @@ static void __apply_fineibt(s32 *start_retpoline, s32 *end_retpoline, { } +#ifdef CONFIG_X86_KERNEL_IBT +static void poison_cfi(void *addr) { } +#endif + #endif void apply_fineibt(s32 *start_retpoline, s32 *end_retpoline, @@ -1148,7 +1331,7 @@ void __init_or_module alternatives_smp_module_add(struct module *mod, smp->locks_end = locks_end; smp->text = text; smp->text_end = text_end; - DPRINTK("locks %p -> %p, text %p -> %p, name %s\n", + DPRINTK(SMP, "locks %p -> %p, text %p -> %p, name %s\n", smp->locks, smp->locks_end, smp->text, smp->text_end, smp->name); @@ -1225,6 +1408,20 @@ int alternatives_text_reserved(void *start, void *end) #endif /* CONFIG_SMP */ #ifdef CONFIG_PARAVIRT + +/* Use this to add nops to a buffer, then text_poke the whole buffer. */ +static void __init_or_module add_nops(void *insns, unsigned int len) +{ + while (len > 0) { + unsigned int noplen = len; + if (noplen > ASM_NOP_MAX) + noplen = ASM_NOP_MAX; + memcpy(insns, x86_nops[noplen], noplen); + insns += noplen; + len -= noplen; + } +} + void __init_or_module apply_paravirt(struct paravirt_patch_site *start, struct paravirt_patch_site *end) { @@ -1332,6 +1529,35 @@ static noinline void __init int3_selftest(void) unregister_die_notifier(&int3_exception_nb); } +static __initdata int __alt_reloc_selftest_addr; + +__visible noinline void __init __alt_reloc_selftest(void *arg) +{ + WARN_ON(arg != &__alt_reloc_selftest_addr); +} + +static noinline void __init alt_reloc_selftest(void) +{ + /* + * Tests apply_relocation(). + * + * This has a relative immediate (CALL) in a place other than the first + * instruction and additionally on x86_64 we get a RIP-relative LEA: + * + * lea 0x0(%rip),%rdi # 5d0: R_X86_64_PC32 .init.data+0x5566c + * call +0 # 5d5: R_X86_64_PLT32 __alt_reloc_selftest-0x4 + * + * Getting this wrong will either crash and burn or tickle the WARN + * above. + */ + asm_inline volatile ( + ALTERNATIVE("", "lea %[mem], %%" _ASM_ARG1 "; call __alt_reloc_selftest;", X86_FEATURE_ALWAYS) + : /* output */ + : [mem] "m" (__alt_reloc_selftest_addr) + : _ASM_ARG1 + ); +} + void __init alternative_instructions(void) { int3_selftest(); @@ -1399,7 +1625,10 @@ void __init alternative_instructions(void) */ callthunks_patch_builtin_calls(); - apply_ibt_endbr(__ibt_endbr_seal, __ibt_endbr_seal_end); + /* + * Seal all functions that do not have their address taken. + */ + apply_seal_endbr(__ibt_endbr_seal, __ibt_endbr_seal_end); #ifdef CONFIG_SMP /* Patch to UP if other cpus not imminent. */ @@ -1419,6 +1648,8 @@ void __init alternative_instructions(void) restart_nmi(); alternatives_patched = 1; + + alt_reloc_selftest(); } /** @@ -1799,7 +2030,7 @@ struct bp_patching_desc *try_get_desc(void) { struct bp_patching_desc *desc = &bp_desc; - if (!arch_atomic_inc_not_zero(&desc->refs)) + if (!raw_atomic_inc_not_zero(&desc->refs)) return NULL; return desc; @@ -1810,7 +2041,7 @@ static __always_inline void put_desc(void) struct bp_patching_desc *desc = &bp_desc; smp_mb__before_atomic(); - arch_atomic_dec(&desc->refs); + raw_atomic_dec(&desc->refs); } static __always_inline void *text_poke_addr(struct text_poke_loc *tp) @@ -1953,6 +2184,16 @@ static void text_poke_bp_batch(struct text_poke_loc *tp, unsigned int nr_entries */ atomic_set_release(&bp_desc.refs, 1); + /* + * Function tracing can enable thousands of places that need to be + * updated. This can take quite some time, and with full kernel debugging + * enabled, this could cause the softlockup watchdog to trigger. + * This function gets called every 256 entries added to be patched. + * Call cond_resched() here to make sure that other tasks can get scheduled + * while processing all the functions being patched. + */ + cond_resched(); + /* * Corresponding read barrier in int3 notifier for making sure the * nr_entries and handler are correctly ordered wrt. patching. diff --git a/arch/x86/kernel/amd_nb.c b/arch/x86/kernel/amd_nb.c index 7e331e8f36929de7a4550a7b90127252f9768f86..035a3db5330b08a4df25bf3217d652d7be516fe4 100644 --- a/arch/x86/kernel/amd_nb.c +++ b/arch/x86/kernel/amd_nb.c @@ -15,28 +15,31 @@ #include #include -#define PCI_DEVICE_ID_AMD_17H_ROOT 0x1450 -#define PCI_DEVICE_ID_AMD_17H_M10H_ROOT 0x15d0 -#define PCI_DEVICE_ID_AMD_17H_M30H_ROOT 0x1480 -#define PCI_DEVICE_ID_AMD_17H_M60H_ROOT 0x1630 -#define PCI_DEVICE_ID_AMD_17H_MA0H_ROOT 0x14b5 -#define PCI_DEVICE_ID_AMD_19H_M10H_ROOT 0x14a4 -#define PCI_DEVICE_ID_AMD_19H_M60H_ROOT 0x14d8 -#define PCI_DEVICE_ID_AMD_19H_M70H_ROOT 0x14e8 -#define PCI_DEVICE_ID_AMD_17H_DF_F4 0x1464 -#define PCI_DEVICE_ID_AMD_17H_M10H_DF_F4 0x15ec -#define PCI_DEVICE_ID_AMD_17H_M30H_DF_F4 0x1494 -#define PCI_DEVICE_ID_AMD_17H_M60H_DF_F4 0x144c -#define PCI_DEVICE_ID_AMD_17H_M70H_DF_F4 0x1444 -#define PCI_DEVICE_ID_AMD_17H_MA0H_DF_F4 0x1728 -#define PCI_DEVICE_ID_AMD_19H_DF_F4 0x1654 -#define PCI_DEVICE_ID_AMD_19H_M10H_DF_F4 0x14b1 -#define PCI_DEVICE_ID_AMD_19H_M40H_ROOT 0x14b5 -#define PCI_DEVICE_ID_AMD_19H_M40H_DF_F4 0x167d -#define PCI_DEVICE_ID_AMD_19H_M50H_DF_F4 0x166e -#define PCI_DEVICE_ID_AMD_19H_M60H_DF_F4 0x14e4 -#define PCI_DEVICE_ID_AMD_19H_M70H_DF_F4 0x14f4 -#define PCI_DEVICE_ID_AMD_19H_M78H_DF_F4 0x12fc +#define PCI_DEVICE_ID_AMD_17H_ROOT 0x1450 +#define PCI_DEVICE_ID_AMD_17H_M10H_ROOT 0x15d0 +#define PCI_DEVICE_ID_AMD_17H_M30H_ROOT 0x1480 +#define PCI_DEVICE_ID_AMD_17H_M60H_ROOT 0x1630 +#define PCI_DEVICE_ID_AMD_17H_MA0H_ROOT 0x14b5 +#define PCI_DEVICE_ID_AMD_19H_M10H_ROOT 0x14a4 +#define PCI_DEVICE_ID_AMD_19H_M40H_ROOT 0x14b5 +#define PCI_DEVICE_ID_AMD_19H_M60H_ROOT 0x14d8 +#define PCI_DEVICE_ID_AMD_19H_M70H_ROOT 0x14e8 +#define PCI_DEVICE_ID_AMD_MI200_ROOT 0x14bb + +#define PCI_DEVICE_ID_AMD_17H_DF_F4 0x1464 +#define PCI_DEVICE_ID_AMD_17H_M10H_DF_F4 0x15ec +#define PCI_DEVICE_ID_AMD_17H_M30H_DF_F4 0x1494 +#define PCI_DEVICE_ID_AMD_17H_M60H_DF_F4 0x144c +#define PCI_DEVICE_ID_AMD_17H_M70H_DF_F4 0x1444 +#define PCI_DEVICE_ID_AMD_17H_MA0H_DF_F4 0x1728 +#define PCI_DEVICE_ID_AMD_19H_DF_F4 0x1654 +#define PCI_DEVICE_ID_AMD_19H_M10H_DF_F4 0x14b1 +#define PCI_DEVICE_ID_AMD_19H_M40H_DF_F4 0x167d +#define PCI_DEVICE_ID_AMD_19H_M50H_DF_F4 0x166e +#define PCI_DEVICE_ID_AMD_19H_M60H_DF_F4 0x14e4 +#define PCI_DEVICE_ID_AMD_19H_M70H_DF_F4 0x14f4 +#define PCI_DEVICE_ID_AMD_19H_M78H_DF_F4 0x12fc +#define PCI_DEVICE_ID_AMD_MI200_DF_F4 0x14d4 /* Protect the PCI config register pairs used for SMN. */ static DEFINE_MUTEX(smn_mutex); @@ -53,6 +56,7 @@ static const struct pci_device_id amd_root_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_19H_M40H_ROOT) }, { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_19H_M60H_ROOT) }, { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_19H_M70H_ROOT) }, + { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_MI200_ROOT) }, {} }; @@ -81,6 +85,7 @@ static const struct pci_device_id amd_nb_misc_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_19H_M60H_DF_F3) }, { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_19H_M70H_DF_F3) }, { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_19H_M78H_DF_F3) }, + { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_MI200_DF_F3) }, {} }; @@ -101,6 +106,7 @@ static const struct pci_device_id amd_nb_link_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_19H_M40H_DF_F4) }, { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_19H_M50H_DF_F4) }, { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CNB17H_F4) }, + { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_MI200_DF_F4) }, {} }; diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index 77055711005187c10c9b973f0df4ca27ac5b772d..af49e24b46a43a20c2f17b170845debfe708be62 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -101,6 +101,9 @@ static int apic_extnmi __ro_after_init = APIC_EXTNMI_BSP; */ static bool virt_ext_dest_id __ro_after_init; +/* For parallel bootup. */ +unsigned long apic_mmio_base __ro_after_init; + /* * Map cpu index to physical APIC ID */ @@ -2163,6 +2166,7 @@ void __init register_lapic_address(unsigned long address) if (!x2apic_mode) { set_fixmap_nocache(FIX_APIC_BASE, address); + apic_mmio_base = APIC_BASE; apic_printk(APIC_VERBOSE, "mapped APIC to %16lx (%16lx)\n", APIC_BASE, address); } @@ -2376,7 +2380,7 @@ static int nr_logical_cpuids = 1; /* * Used to store mapping between logical CPU IDs and APIC IDs. */ -static int cpuid_to_apicid[] = { +int cpuid_to_apicid[] = { [0 ... NR_CPUS - 1] = -1, }; @@ -2386,20 +2390,31 @@ bool arch_match_cpu_phys_id(int cpu, u64 phys_id) } #ifdef CONFIG_SMP -/** - * apic_id_is_primary_thread - Check whether APIC ID belongs to a primary thread - * @apicid: APIC ID to check +static void cpu_mark_primary_thread(unsigned int cpu, unsigned int apicid) +{ + /* Isolate the SMT bit(s) in the APICID and check for 0 */ + u32 mask = (1U << (fls(smp_num_siblings) - 1)) - 1; + + if (smp_num_siblings == 1 || !(apicid & mask)) + cpumask_set_cpu(cpu, &__cpu_primary_thread_mask); +} + +/* + * Due to the utter mess of CPUID evaluation smp_num_siblings is not valid + * during early boot. Initialize the primary thread mask before SMP + * bringup. */ -bool apic_id_is_primary_thread(unsigned int apicid) +static int __init smp_init_primary_thread_mask(void) { - u32 mask; + unsigned int cpu; - if (smp_num_siblings == 1) - return true; - /* Isolate the SMT bit(s) in the APICID and check for 0 */ - mask = (1U << (fls(smp_num_siblings) - 1)) - 1; - return !(apicid & mask); + for (cpu = 0; cpu < nr_logical_cpuids; cpu++) + cpu_mark_primary_thread(cpu, cpuid_to_apicid[cpu]); + return 0; } +early_initcall(smp_init_primary_thread_mask); +#else +static inline void cpu_mark_primary_thread(unsigned int cpu, unsigned int apicid) { } #endif /* @@ -2544,6 +2559,9 @@ int generic_processor_info(int apicid, int version) set_cpu_present(cpu, true); num_processors++; + if (system_state != SYSTEM_BOOTING) + cpu_mark_primary_thread(cpu, apicid); + return cpu; } diff --git a/arch/x86/kernel/apic/x2apic_phys.c b/arch/x86/kernel/apic/x2apic_phys.c index 6bde05a86b4edde5b0ea91b4f088424a97c4a216..896bc41cb2ba7fe6ab89377297e37c4954e39895 100644 --- a/arch/x86/kernel/apic/x2apic_phys.c +++ b/arch/x86/kernel/apic/x2apic_phys.c @@ -97,7 +97,10 @@ static void init_x2apic_ldr(void) static int x2apic_phys_probe(void) { - if (x2apic_mode && (x2apic_phys || x2apic_fadt_phys())) + if (!x2apic_mode) + return 0; + + if (x2apic_phys || x2apic_fadt_phys()) return 1; return apic == &apic_x2apic_phys; diff --git a/arch/x86/kernel/apic/x2apic_uv_x.c b/arch/x86/kernel/apic/x2apic_uv_x.c index 48285522796454b4b368e8ff1c0287e4bef7d574..d9384d5b4b8e93093323ed299a46923a7a913b2f 100644 --- a/arch/x86/kernel/apic/x2apic_uv_x.c +++ b/arch/x86/kernel/apic/x2apic_uv_x.c @@ -546,7 +546,6 @@ unsigned long sn_rtc_cycles_per_second; EXPORT_SYMBOL(sn_rtc_cycles_per_second); /* The following values are used for the per node hub info struct */ -static __initdata unsigned short *_node_to_pnode; static __initdata unsigned short _min_socket, _max_socket; static __initdata unsigned short _min_pnode, _max_pnode, _gr_table_len; static __initdata struct uv_gam_range_entry *uv_gre_table; @@ -554,6 +553,7 @@ static __initdata struct uv_gam_parameters *uv_gp_table; static __initdata unsigned short *_socket_to_node; static __initdata unsigned short *_socket_to_pnode; static __initdata unsigned short *_pnode_to_socket; +static __initdata unsigned short *_node_to_socket; static __initdata struct uv_gam_range_s *_gr_table; @@ -617,7 +617,8 @@ static __init void build_uv_gr_table(void) bytes = _gr_table_len * sizeof(struct uv_gam_range_s); grt = kzalloc(bytes, GFP_KERNEL); - BUG_ON(!grt); + if (WARN_ON_ONCE(!grt)) + return; _gr_table = grt; for (; gre->type != UV_GAM_RANGE_TYPE_UNUSED; gre++) { @@ -1022,7 +1023,7 @@ static void __init calc_mmioh_map(enum mmioh_arch index, switch (index) { case UVY_MMIOH0: mmr = UVH_RH10_GAM_MMIOH_REDIRECT_CONFIG0; - nasid_mask = UVH_RH10_GAM_MMIOH_OVERLAY_CONFIG0_BASE_MASK; + nasid_mask = UVYH_RH10_GAM_MMIOH_REDIRECT_CONFIG0_NASID_MASK; n = UVH_RH10_GAM_MMIOH_REDIRECT_CONFIG0_DEPTH; min_nasid = min_pnode; max_nasid = max_pnode; @@ -1030,7 +1031,7 @@ static void __init calc_mmioh_map(enum mmioh_arch index, break; case UVY_MMIOH1: mmr = UVH_RH10_GAM_MMIOH_REDIRECT_CONFIG1; - nasid_mask = UVH_RH10_GAM_MMIOH_OVERLAY_CONFIG1_BASE_MASK; + nasid_mask = UVYH_RH10_GAM_MMIOH_REDIRECT_CONFIG1_NASID_MASK; n = UVH_RH10_GAM_MMIOH_REDIRECT_CONFIG1_DEPTH; min_nasid = min_pnode; max_nasid = max_pnode; @@ -1038,7 +1039,7 @@ static void __init calc_mmioh_map(enum mmioh_arch index, break; case UVX_MMIOH0: mmr = UVH_RH_GAM_MMIOH_REDIRECT_CONFIG0; - nasid_mask = UVH_RH_GAM_MMIOH_OVERLAY_CONFIG0_BASE_MASK; + nasid_mask = UVH_RH_GAM_MMIOH_REDIRECT_CONFIG0_NASID_MASK; n = UVH_RH_GAM_MMIOH_REDIRECT_CONFIG0_DEPTH; min_nasid = min_pnode * 2; max_nasid = max_pnode * 2; @@ -1046,7 +1047,7 @@ static void __init calc_mmioh_map(enum mmioh_arch index, break; case UVX_MMIOH1: mmr = UVH_RH_GAM_MMIOH_REDIRECT_CONFIG1; - nasid_mask = UVH_RH_GAM_MMIOH_OVERLAY_CONFIG1_BASE_MASK; + nasid_mask = UVH_RH_GAM_MMIOH_REDIRECT_CONFIG1_NASID_MASK; n = UVH_RH_GAM_MMIOH_REDIRECT_CONFIG1_DEPTH; min_nasid = min_pnode * 2; max_nasid = max_pnode * 2; @@ -1072,8 +1073,9 @@ static void __init calc_mmioh_map(enum mmioh_arch index, /* Invalid NASID check */ if (nasid < min_nasid || max_nasid < nasid) { - pr_err("UV:%s:Invalid NASID:%x (range:%x..%x)\n", - __func__, index, min_nasid, max_nasid); + /* Not an error: unused table entries get "poison" values */ + pr_debug("UV:%s:Invalid NASID(%x):%x (range:%x..%x)\n", + __func__, index, nasid, min_nasid, max_nasid); nasid = -1; } @@ -1292,6 +1294,7 @@ static void __init uv_init_hub_info(struct uv_hub_info_s *hi) hi->nasid_shift = uv_cpuid.nasid_shift; hi->min_pnode = _min_pnode; hi->min_socket = _min_socket; + hi->node_to_socket = _node_to_socket; hi->pnode_to_socket = _pnode_to_socket; hi->socket_to_node = _socket_to_node; hi->socket_to_pnode = _socket_to_pnode; @@ -1348,7 +1351,7 @@ static void __init decode_gam_rng_tbl(unsigned long ptr) struct uv_gam_range_entry *gre = (struct uv_gam_range_entry *)ptr; unsigned long lgre = 0, gend = 0; int index = 0; - int sock_min = 999999, pnode_min = 99999; + int sock_min = INT_MAX, pnode_min = INT_MAX; int sock_max = -1, pnode_max = -1; uv_gre_table = gre; @@ -1459,11 +1462,37 @@ static int __init decode_uv_systab(void) return 0; } +/* + * Given a bitmask 'bits' representing presnt blades, numbered + * starting at 'base', masking off unused high bits of blade number + * with 'mask', update the minimum and maximum blade numbers that we + * have found. (Masking with 'mask' necessary because of BIOS + * treatment of system partitioning when creating this table we are + * interpreting.) + */ +static inline void blade_update_min_max(unsigned long bits, int base, int mask, int *min, int *max) +{ + int first, last; + + if (!bits) + return; + first = (base + __ffs(bits)) & mask; + last = (base + __fls(bits)) & mask; + + if (*min > first) + *min = first; + if (*max < last) + *max = last; +} + /* Set up physical blade translations from UVH_NODE_PRESENT_TABLE */ static __init void boot_init_possible_blades(struct uv_hub_info_s *hub_info) { unsigned long np; int i, uv_pb = 0; + int sock_min = INT_MAX, sock_max = -1, s_mask; + + s_mask = (1 << uv_cpuid.n_skt) - 1; if (UVH_NODE_PRESENT_TABLE) { pr_info("UV: NODE_PRESENT_DEPTH = %d\n", @@ -1471,35 +1500,82 @@ static __init void boot_init_possible_blades(struct uv_hub_info_s *hub_info) for (i = 0; i < UVH_NODE_PRESENT_TABLE_DEPTH; i++) { np = uv_read_local_mmr(UVH_NODE_PRESENT_TABLE + i * 8); pr_info("UV: NODE_PRESENT(%d) = 0x%016lx\n", i, np); - uv_pb += hweight64(np); + blade_update_min_max(np, i * 64, s_mask, &sock_min, &sock_max); } } if (UVH_NODE_PRESENT_0) { np = uv_read_local_mmr(UVH_NODE_PRESENT_0); pr_info("UV: NODE_PRESENT_0 = 0x%016lx\n", np); - uv_pb += hweight64(np); + blade_update_min_max(np, 0, s_mask, &sock_min, &sock_max); } if (UVH_NODE_PRESENT_1) { np = uv_read_local_mmr(UVH_NODE_PRESENT_1); pr_info("UV: NODE_PRESENT_1 = 0x%016lx\n", np); - uv_pb += hweight64(np); + blade_update_min_max(np, 64, s_mask, &sock_min, &sock_max); + } + + /* Only update if we actually found some bits indicating blades present */ + if (sock_max >= sock_min) { + _min_socket = sock_min; + _max_socket = sock_max; + uv_pb = sock_max - sock_min + 1; } if (uv_possible_blades != uv_pb) uv_possible_blades = uv_pb; - pr_info("UV: number nodes/possible blades %d\n", uv_pb); + pr_info("UV: number nodes/possible blades %d (%d - %d)\n", + uv_pb, sock_min, sock_max); +} + +static int __init alloc_conv_table(int num_elem, unsigned short **table) +{ + int i; + size_t bytes; + + bytes = num_elem * sizeof(*table[0]); + *table = kmalloc(bytes, GFP_KERNEL); + if (WARN_ON_ONCE(!*table)) + return -ENOMEM; + for (i = 0; i < num_elem; i++) + ((unsigned short *)*table)[i] = SOCK_EMPTY; + return 0; } +/* Remove conversion table if it's 1:1 */ +#define FREE_1_TO_1_TABLE(tbl, min, max, max2) free_1_to_1_table(&tbl, #tbl, min, max, max2) + +static void __init free_1_to_1_table(unsigned short **tp, char *tname, int min, int max, int max2) +{ + int i; + unsigned short *table = *tp; + + if (table == NULL) + return; + if (max != max2) + return; + for (i = 0; i < max; i++) { + if (i != table[i]) + return; + } + kfree(table); + *tp = NULL; + pr_info("UV: %s is 1:1, conversion table removed\n", tname); +} + +/* + * Build Socket Tables + * If the number of nodes is >1 per socket, socket to node table will + * contain lowest node number on that socket. + */ static void __init build_socket_tables(void) { struct uv_gam_range_entry *gre = uv_gre_table; - int num, nump; + int nums, numn, nump; int cpu, i, lnid; int minsock = _min_socket; int maxsock = _max_socket; int minpnode = _min_pnode; int maxpnode = _max_pnode; - size_t bytes; if (!gre) { if (is_uv2_hub() || is_uv3_hub()) { @@ -1507,39 +1583,36 @@ static void __init build_socket_tables(void) return; } pr_err("UV: Error: UVsystab address translations not available!\n"); - BUG(); + WARN_ON_ONCE(!gre); + return; } - /* Build socket id -> node id, pnode */ - num = maxsock - minsock + 1; - bytes = num * sizeof(_socket_to_node[0]); - _socket_to_node = kmalloc(bytes, GFP_KERNEL); - _socket_to_pnode = kmalloc(bytes, GFP_KERNEL); - + numn = num_possible_nodes(); nump = maxpnode - minpnode + 1; - bytes = nump * sizeof(_pnode_to_socket[0]); - _pnode_to_socket = kmalloc(bytes, GFP_KERNEL); - BUG_ON(!_socket_to_node || !_socket_to_pnode || !_pnode_to_socket); - - for (i = 0; i < num; i++) - _socket_to_node[i] = _socket_to_pnode[i] = SOCK_EMPTY; - - for (i = 0; i < nump; i++) - _pnode_to_socket[i] = SOCK_EMPTY; + nums = maxsock - minsock + 1; + + /* Allocate and clear tables */ + if ((alloc_conv_table(nump, &_pnode_to_socket) < 0) + || (alloc_conv_table(nums, &_socket_to_pnode) < 0) + || (alloc_conv_table(numn, &_node_to_socket) < 0) + || (alloc_conv_table(nums, &_socket_to_node) < 0)) { + kfree(_pnode_to_socket); + kfree(_socket_to_pnode); + kfree(_node_to_socket); + return; + } /* Fill in pnode/node/addr conversion list values: */ - pr_info("UV: GAM Building socket/pnode conversion tables\n"); for (; gre->type != UV_GAM_RANGE_TYPE_UNUSED; gre++) { if (gre->type == UV_GAM_RANGE_TYPE_HOLE) continue; i = gre->sockid - minsock; - /* Duplicate: */ - if (_socket_to_pnode[i] != SOCK_EMPTY) - continue; - _socket_to_pnode[i] = gre->pnode; + if (_socket_to_pnode[i] == SOCK_EMPTY) + _socket_to_pnode[i] = gre->pnode; i = gre->pnode - minpnode; - _pnode_to_socket[i] = gre->sockid; + if (_pnode_to_socket[i] == SOCK_EMPTY) + _pnode_to_socket[i] = gre->sockid; pr_info("UV: sid:%02x type:%d nasid:%04x pn:%02x pn2s:%2x\n", gre->sockid, gre->type, gre->nasid, @@ -1549,66 +1622,39 @@ static void __init build_socket_tables(void) /* Set socket -> node values: */ lnid = NUMA_NO_NODE; - for_each_present_cpu(cpu) { + for_each_possible_cpu(cpu) { int nid = cpu_to_node(cpu); int apicid, sockid; if (lnid == nid) continue; lnid = nid; + apicid = per_cpu(x86_cpu_to_apicid, cpu); sockid = apicid >> uv_cpuid.socketid_shift; - _socket_to_node[sockid - minsock] = nid; - pr_info("UV: sid:%02x: apicid:%04x node:%2d\n", - sockid, apicid, nid); - } - /* Set up physical blade to pnode translation from GAM Range Table: */ - bytes = num_possible_nodes() * sizeof(_node_to_pnode[0]); - _node_to_pnode = kmalloc(bytes, GFP_KERNEL); - BUG_ON(!_node_to_pnode); + if (_socket_to_node[sockid - minsock] == SOCK_EMPTY) + _socket_to_node[sockid - minsock] = nid; - for (lnid = 0; lnid < num_possible_nodes(); lnid++) { - unsigned short sockid; + if (_node_to_socket[nid] == SOCK_EMPTY) + _node_to_socket[nid] = sockid; - for (sockid = minsock; sockid <= maxsock; sockid++) { - if (lnid == _socket_to_node[sockid - minsock]) { - _node_to_pnode[lnid] = _socket_to_pnode[sockid - minsock]; - break; - } - } - if (sockid > maxsock) { - pr_err("UV: socket for node %d not found!\n", lnid); - BUG(); - } + pr_info("UV: sid:%02x: apicid:%04x socket:%02d node:%03x s2n:%03x\n", + sockid, + apicid, + _node_to_socket[nid], + nid, + _socket_to_node[sockid - minsock]); } /* - * If socket id == pnode or socket id == node for all nodes, + * If e.g. socket id == pnode for all pnodes, * system runs faster by removing corresponding conversion table. */ - pr_info("UV: Checking socket->node/pnode for identity maps\n"); - if (minsock == 0) { - for (i = 0; i < num; i++) - if (_socket_to_node[i] == SOCK_EMPTY || i != _socket_to_node[i]) - break; - if (i >= num) { - kfree(_socket_to_node); - _socket_to_node = NULL; - pr_info("UV: 1:1 socket_to_node table removed\n"); - } - } - if (minsock == minpnode) { - for (i = 0; i < num; i++) - if (_socket_to_pnode[i] != SOCK_EMPTY && - _socket_to_pnode[i] != i + minpnode) - break; - if (i >= num) { - kfree(_socket_to_pnode); - _socket_to_pnode = NULL; - pr_info("UV: 1:1 socket_to_pnode table removed\n"); - } - } + FREE_1_TO_1_TABLE(_socket_to_node, _min_socket, nums, numn); + FREE_1_TO_1_TABLE(_node_to_socket, _min_socket, nums, numn); + FREE_1_TO_1_TABLE(_socket_to_pnode, _min_pnode, nums, nump); + FREE_1_TO_1_TABLE(_pnode_to_socket, _min_pnode, nums, nump); } /* Check which reboot to use */ @@ -1692,12 +1738,13 @@ static __init int uv_system_init_hubless(void) static void __init uv_system_init_hub(void) { struct uv_hub_info_s hub_info = {0}; - int bytes, cpu, nodeid; - unsigned short min_pnode = 9999, max_pnode = 0; + int bytes, cpu, nodeid, bid; + unsigned short min_pnode = USHRT_MAX, max_pnode = 0; char *hub = is_uv5_hub() ? "UV500" : is_uv4_hub() ? "UV400" : is_uv3_hub() ? "UV300" : is_uv2_hub() ? "UV2000/3000" : NULL; + struct uv_hub_info_s **uv_hub_info_list_blade; if (!hub) { pr_err("UV: Unknown/unsupported UV hub\n"); @@ -1720,9 +1767,12 @@ static void __init uv_system_init_hub(void) build_uv_gr_table(); set_block_size(); uv_init_hub_info(&hub_info); - uv_possible_blades = num_possible_nodes(); - if (!_node_to_pnode) + /* If UV2 or UV3 may need to get # blades from HW */ + if (is_uv(UV2|UV3) && !uv_gre_table) boot_init_possible_blades(&hub_info); + else + /* min/max sockets set in decode_gam_rng_tbl */ + uv_possible_blades = (_max_socket - _min_socket) + 1; /* uv_num_possible_blades() is really the hub count: */ pr_info("UV: Found %d hubs, %d nodes, %d CPUs\n", uv_num_possible_blades(), num_possible_nodes(), num_possible_cpus()); @@ -1731,79 +1781,98 @@ static void __init uv_system_init_hub(void) hub_info.coherency_domain_number = sn_coherency_id; uv_rtc_init(); + /* + * __uv_hub_info_list[] is indexed by node, but there is only + * one hub_info structure per blade. First, allocate one + * structure per blade. Further down we create a per-node + * table (__uv_hub_info_list[]) pointing to hub_info + * structures for the correct blade. + */ + bytes = sizeof(void *) * uv_num_possible_blades(); - __uv_hub_info_list = kzalloc(bytes, GFP_KERNEL); - BUG_ON(!__uv_hub_info_list); + uv_hub_info_list_blade = kzalloc(bytes, GFP_KERNEL); + if (WARN_ON_ONCE(!uv_hub_info_list_blade)) + return; bytes = sizeof(struct uv_hub_info_s); - for_each_node(nodeid) { + for_each_possible_blade(bid) { struct uv_hub_info_s *new_hub; - if (__uv_hub_info_list[nodeid]) { - pr_err("UV: Node %d UV HUB already initialized!?\n", nodeid); - BUG(); + /* Allocate & fill new per hub info list */ + new_hub = (bid == 0) ? &uv_hub_info_node0 + : kzalloc_node(bytes, GFP_KERNEL, uv_blade_to_node(bid)); + if (WARN_ON_ONCE(!new_hub)) { + /* do not kfree() bid 0, which is statically allocated */ + while (--bid > 0) + kfree(uv_hub_info_list_blade[bid]); + kfree(uv_hub_info_list_blade); + return; } - /* Allocate new per hub info list */ - new_hub = (nodeid == 0) ? &uv_hub_info_node0 : kzalloc_node(bytes, GFP_KERNEL, nodeid); - BUG_ON(!new_hub); - __uv_hub_info_list[nodeid] = new_hub; - new_hub = uv_hub_info_list(nodeid); - BUG_ON(!new_hub); + uv_hub_info_list_blade[bid] = new_hub; *new_hub = hub_info; /* Use information from GAM table if available: */ - if (_node_to_pnode) - new_hub->pnode = _node_to_pnode[nodeid]; + if (uv_gre_table) + new_hub->pnode = uv_blade_to_pnode(bid); else /* Or fill in during CPU loop: */ new_hub->pnode = 0xffff; - new_hub->numa_blade_id = uv_node_to_blade_id(nodeid); + new_hub->numa_blade_id = bid; new_hub->memory_nid = NUMA_NO_NODE; new_hub->nr_possible_cpus = 0; new_hub->nr_online_cpus = 0; } + /* + * Now populate __uv_hub_info_list[] for each node with the + * pointer to the struct for the blade it resides on. + */ + + bytes = sizeof(void *) * num_possible_nodes(); + __uv_hub_info_list = kzalloc(bytes, GFP_KERNEL); + if (WARN_ON_ONCE(!__uv_hub_info_list)) { + for_each_possible_blade(bid) + /* bid 0 is statically allocated */ + if (bid != 0) + kfree(uv_hub_info_list_blade[bid]); + kfree(uv_hub_info_list_blade); + return; + } + + for_each_node(nodeid) + __uv_hub_info_list[nodeid] = uv_hub_info_list_blade[uv_node_to_blade_id(nodeid)]; + /* Initialize per CPU info: */ for_each_possible_cpu(cpu) { - int apicid = per_cpu(x86_cpu_to_apicid, cpu); - int numa_node_id; + int apicid = early_per_cpu(x86_cpu_to_apicid, cpu); + unsigned short bid; unsigned short pnode; - nodeid = cpu_to_node(cpu); - numa_node_id = numa_cpu_node(cpu); pnode = uv_apicid_to_pnode(apicid); + bid = uv_pnode_to_socket(pnode) - _min_socket; - uv_cpu_info_per(cpu)->p_uv_hub_info = uv_hub_info_list(nodeid); + uv_cpu_info_per(cpu)->p_uv_hub_info = uv_hub_info_list_blade[bid]; uv_cpu_info_per(cpu)->blade_cpu_id = uv_cpu_hub_info(cpu)->nr_possible_cpus++; if (uv_cpu_hub_info(cpu)->memory_nid == NUMA_NO_NODE) uv_cpu_hub_info(cpu)->memory_nid = cpu_to_node(cpu); - /* Init memoryless node: */ - if (nodeid != numa_node_id && - uv_hub_info_list(numa_node_id)->pnode == 0xffff) - uv_hub_info_list(numa_node_id)->pnode = pnode; - else if (uv_cpu_hub_info(cpu)->pnode == 0xffff) + if (uv_cpu_hub_info(cpu)->pnode == 0xffff) uv_cpu_hub_info(cpu)->pnode = pnode; } - for_each_node(nodeid) { - unsigned short pnode = uv_hub_info_list(nodeid)->pnode; + for_each_possible_blade(bid) { + unsigned short pnode = uv_hub_info_list_blade[bid]->pnode; - /* Add pnode info for pre-GAM list nodes without CPUs: */ - if (pnode == 0xffff) { - unsigned long paddr; + if (pnode == 0xffff) + continue; - paddr = node_start_pfn(nodeid) << PAGE_SHIFT; - pnode = uv_gpa_to_pnode(uv_soc_phys_ram_to_gpa(paddr)); - uv_hub_info_list(nodeid)->pnode = pnode; - } min_pnode = min(pnode, min_pnode); max_pnode = max(pnode, max_pnode); - pr_info("UV: UVHUB node:%2d pn:%02x nrcpus:%d\n", - nodeid, - uv_hub_info_list(nodeid)->pnode, - uv_hub_info_list(nodeid)->nr_possible_cpus); + pr_info("UV: HUB:%2d pn:%02x nrcpus:%d\n", + bid, + uv_hub_info_list_blade[bid]->pnode, + uv_hub_info_list_blade[bid]->nr_possible_cpus); } pr_info("UV: min_pnode:%02x max_pnode:%02x\n", min_pnode, max_pnode); @@ -1811,6 +1880,9 @@ static void __init uv_system_init_hub(void) map_mmr_high(max_pnode); map_mmioh_high(min_pnode, max_pnode); + kfree(uv_hub_info_list_blade); + uv_hub_info_list_blade = NULL; + uv_nmi_setup(); uv_cpu_init(); uv_setup_proc_files(0); diff --git a/arch/x86/kernel/callthunks.c b/arch/x86/kernel/callthunks.c index 22ab139664271a5860ac0ebe62b2f8a762a701d9..c06bfc086565dff236c72c0ab9758c3239c63bcc 100644 --- a/arch/x86/kernel/callthunks.c +++ b/arch/x86/kernel/callthunks.c @@ -133,8 +133,8 @@ static bool skip_addr(void *dest) /* Accounts directly */ if (dest == ret_from_fork) return true; -#ifdef CONFIG_HOTPLUG_CPU - if (dest == start_cpu0) +#if defined(CONFIG_HOTPLUG_CPU) && defined(CONFIG_AMD_MEM_ENCRYPT) + if (dest == soft_restart_cpu) return true; #endif #ifdef CONFIG_FUNCTION_TRACER @@ -293,7 +293,8 @@ void *callthunks_translate_call_dest(void *dest) return target ? : dest; } -bool is_callthunk(void *addr) +#ifdef CONFIG_BPF_JIT +static bool is_callthunk(void *addr) { unsigned int tmpl_size = SKL_TMPL_SIZE; void *tmpl = skl_call_thunk_template; @@ -306,7 +307,6 @@ bool is_callthunk(void *addr) return !bcmp((void *)(dest - tmpl_size), tmpl, tmpl_size); } -#ifdef CONFIG_BPF_JIT int x86_call_depth_emit_accounting(u8 **pprog, void *func) { unsigned int tmpl_size = SKL_TMPL_SIZE; diff --git a/arch/x86/kernel/cpu/Makefile b/arch/x86/kernel/cpu/Makefile index d7e3ceaf75c16637cf10db37afcae0b28ecf49b3..4350f6bfc0641ea7a6877cd9a224055a456753bd 100644 --- a/arch/x86/kernel/cpu/Makefile +++ b/arch/x86/kernel/cpu/Makefile @@ -27,7 +27,7 @@ obj-y += cpuid-deps.o obj-y += umwait.o obj-$(CONFIG_PROC_FS) += proc.o -obj-$(CONFIG_X86_FEATURE_NAMES) += capflags.o powerflags.o +obj-y += capflags.o powerflags.o obj-$(CONFIG_IA32_FEAT_CTL) += feat_ctl.o ifdef CONFIG_CPU_SUP_INTEL @@ -54,7 +54,6 @@ obj-$(CONFIG_X86_LOCAL_APIC) += perfctr-watchdog.o obj-$(CONFIG_HYPERVISOR_GUEST) += vmware.o hypervisor.o mshyperv.o obj-$(CONFIG_ACRN_GUEST) += acrn.o -ifdef CONFIG_X86_FEATURE_NAMES quiet_cmd_mkcapflags = MKCAP $@ cmd_mkcapflags = $(CONFIG_SHELL) $(srctree)/$(src)/mkcapflags.sh $@ $^ @@ -63,5 +62,4 @@ vmxfeature = $(src)/../../include/asm/vmxfeatures.h $(obj)/capflags.c: $(cpufeature) $(vmxfeature) $(src)/mkcapflags.sh FORCE $(call if_changed,mkcapflags) -endif targets += capflags.c diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c index 182af64387d061294d4883b3b7b752c60aa616fc..9e2a91830f728b0048f35de1162b231f28997255 100644 --- a/arch/x86/kernel/cpu/bugs.c +++ b/arch/x86/kernel/cpu/bugs.c @@ -9,7 +9,6 @@ * - Andrew D. Balsa (code cleanup). */ #include -#include #include #include #include @@ -27,8 +26,6 @@ #include #include #include -#include -#include #include #include #include @@ -125,21 +122,8 @@ DEFINE_STATIC_KEY_FALSE(switch_mm_cond_l1d_flush); DEFINE_STATIC_KEY_FALSE(mmio_stale_data_clear); EXPORT_SYMBOL_GPL(mmio_stale_data_clear); -void __init check_bugs(void) +void __init cpu_select_mitigations(void) { - identify_boot_cpu(); - - /* - * identify_boot_cpu() initialized SMT support information, let the - * core code know. - */ - cpu_smt_check_topology(); - - if (!IS_ENABLED(CONFIG_SMP)) { - pr_info("CPU: "); - print_cpu_info(&boot_cpu_data); - } - /* * Read the SPEC_CTRL MSR to account for reserved bits which may * have unknown values. AMD64_LS_CFG MSR is cached in the early AMD @@ -176,39 +160,6 @@ void __init check_bugs(void) md_clear_select_mitigation(); srbds_select_mitigation(); l1d_flush_select_mitigation(); - - arch_smt_update(); - -#ifdef CONFIG_X86_32 - /* - * Check whether we are able to run this kernel safely on SMP. - * - * - i386 is no longer supported. - * - In order to run on anything without a TSC, we need to be - * compiled for a i486. - */ - if (boot_cpu_data.x86 < 4) - panic("Kernel requires i486+ for 'invlpg' and other features"); - - init_utsname()->machine[1] = - '0' + (boot_cpu_data.x86 > 6 ? 6 : boot_cpu_data.x86); - alternative_instructions(); - - fpu__init_check_bugs(); -#else /* CONFIG_X86_64 */ - alternative_instructions(); - - /* - * Make sure the first 2MB area is not mapped by huge pages - * There are typically fixed size MTRRs in there and overlapping - * MTRRs into large pages causes slow downs. - * - * Right now we don't do that with gbpages because there seems - * very little benefit for that case. - */ - if (!direct_gbpages) - set_memory_4k((unsigned long)__va(0), 1); -#endif } /* diff --git a/arch/x86/kernel/cpu/cacheinfo.c b/arch/x86/kernel/cpu/cacheinfo.c index 4063e8991211793d9bea489a82dc65995f4fddaf..8f86eacf69f7c965a92996ddf669c02b2d62b751 100644 --- a/arch/x86/kernel/cpu/cacheinfo.c +++ b/arch/x86/kernel/cpu/cacheinfo.c @@ -39,6 +39,8 @@ DEFINE_PER_CPU_READ_MOSTLY(cpumask_var_t, cpu_llc_shared_map); /* Shared L2 cache maps */ DEFINE_PER_CPU_READ_MOSTLY(cpumask_var_t, cpu_l2c_shared_map); +static cpumask_var_t cpu_cacheinfo_mask; + /* Kernel controls MTRR and/or PAT MSRs. */ unsigned int memory_caching_control __ro_after_init; @@ -1172,8 +1174,10 @@ void cache_bp_restore(void) cache_cpu_init(); } -static int cache_ap_init(unsigned int cpu) +static int cache_ap_online(unsigned int cpu) { + cpumask_set_cpu(cpu, cpu_cacheinfo_mask); + if (!memory_caching_control || get_cache_aps_delayed_init()) return 0; @@ -1191,11 +1195,17 @@ static int cache_ap_init(unsigned int cpu) * lock to prevent MTRR entry changes */ stop_machine_from_inactive_cpu(cache_rendezvous_handler, NULL, - cpu_callout_mask); + cpu_cacheinfo_mask); return 0; } +static int cache_ap_offline(unsigned int cpu) +{ + cpumask_clear_cpu(cpu, cpu_cacheinfo_mask); + return 0; +} + /* * Delayed cache initialization for all AP's */ @@ -1210,9 +1220,12 @@ void cache_aps_init(void) static int __init cache_ap_register(void) { + zalloc_cpumask_var(&cpu_cacheinfo_mask, GFP_KERNEL); + cpumask_set_cpu(smp_processor_id(), cpu_cacheinfo_mask); + cpuhp_setup_state_nocalls(CPUHP_AP_CACHECTRL_STARTING, "x86/cachectrl:starting", - cache_ap_init, NULL); + cache_ap_online, cache_ap_offline); return 0; } -core_initcall(cache_ap_register); +early_initcall(cache_ap_register); diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 80710a68ef7daedcc565faead87445a0554f1839..52683fddafaf42130cef1cce0b3d7632ba87d9bf 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -18,12 +18,16 @@ #include #include #include +#include #include +#include #include #include #include #include +#include +#include #include #include #include @@ -59,7 +63,7 @@ #include #include #include -#include +#include #include #include @@ -67,14 +71,6 @@ u32 elf_hwcap2 __read_mostly; -/* all of these masks are initialized in setup_cpu_local_masks() */ -cpumask_var_t cpu_initialized_mask; -cpumask_var_t cpu_callout_mask; -cpumask_var_t cpu_callin_mask; - -/* representing cpus for which sibling maps can be computed */ -cpumask_var_t cpu_sibling_setup_mask; - /* Number of siblings per CPU package */ int smp_num_siblings = 1; EXPORT_SYMBOL(smp_num_siblings); @@ -169,15 +165,6 @@ static void ppin_init(struct cpuinfo_x86 *c) clear_cpu_cap(c, info->feature); } -/* correctly size the local cpu masks */ -void __init setup_cpu_local_masks(void) -{ - alloc_bootmem_cpumask_var(&cpu_initialized_mask); - alloc_bootmem_cpumask_var(&cpu_callin_mask); - alloc_bootmem_cpumask_var(&cpu_callout_mask); - alloc_bootmem_cpumask_var(&cpu_sibling_setup_mask); -} - static void default_init(struct cpuinfo_x86 *c) { #ifdef CONFIG_X86_64 @@ -1502,12 +1489,10 @@ static void __init cpu_parse_early_param(void) if (!kstrtouint(opt, 10, &bit)) { if (bit < NCAPINTS * 32) { -#ifdef CONFIG_X86_FEATURE_NAMES /* empty-string, i.e., ""-defined feature flags */ if (!x86_cap_flags[bit]) pr_cont(" " X86_CAP_FMT_NUM, x86_cap_flag_num(bit)); else -#endif pr_cont(" " X86_CAP_FMT, x86_cap_flag(bit)); setup_clear_cpu_cap(bit); @@ -1520,7 +1505,6 @@ static void __init cpu_parse_early_param(void) continue; } -#ifdef CONFIG_X86_FEATURE_NAMES for (bit = 0; bit < 32 * NCAPINTS; bit++) { if (!x86_cap_flag(bit)) continue; @@ -1537,7 +1521,6 @@ static void __init cpu_parse_early_param(void) if (!found) pr_cont(" (unknown: %s)", opt); -#endif } pr_cont("\n"); @@ -1600,10 +1583,6 @@ static void __init early_identify_cpu(struct cpuinfo_x86 *c) sld_setup(c); - fpu__init_system(c); - - init_sigframe_size(); - #ifdef CONFIG_X86_32 /* * Regardless of whether PCID is enumerated, the SDM says @@ -2123,19 +2102,6 @@ static void dbg_restore_debug_regs(void) #define dbg_restore_debug_regs() #endif /* ! CONFIG_KGDB */ -static void wait_for_master_cpu(int cpu) -{ -#ifdef CONFIG_SMP - /* - * wait for ACK from master CPU before continuing - * with AP initialization - */ - WARN_ON(cpumask_test_and_set_cpu(cpu, cpu_initialized_mask)); - while (!cpumask_test_cpu(cpu, cpu_callout_mask)) - cpu_relax(); -#endif -} - static inline void setup_getcpu(int cpu) { unsigned long cpudata = vdso_encode_cpunode(cpu, early_cpu_to_node(cpu)); @@ -2158,11 +2124,7 @@ static inline void setup_getcpu(int cpu) } #ifdef CONFIG_X86_64 -static inline void ucode_cpu_init(int cpu) -{ - if (cpu) - load_ucode_ap(); -} +static inline void ucode_cpu_init(int cpu) { } static inline void tss_setup_ist(struct tss_struct *tss) { @@ -2239,8 +2201,6 @@ void cpu_init(void) struct task_struct *cur = current; int cpu = raw_smp_processor_id(); - wait_for_master_cpu(cpu); - ucode_cpu_init(cpu); #ifdef CONFIG_NUMA @@ -2285,26 +2245,12 @@ void cpu_init(void) doublefault_init_cpu_tss(); - fpu__init_cpu(); - if (is_uv_system()) uv_cpu_init(); load_fixmap_gdt(cpu); } -#ifdef CONFIG_SMP -void cpu_init_secondary(void) -{ - /* - * Relies on the BP having set-up the IDT tables, which are loaded - * on this CPU in cpu_init_exception_handling(). - */ - cpu_init_exception_handling(); - cpu_init(); -} -#endif - #ifdef CONFIG_MICROCODE_LATE_LOADING /** * store_cpu_caps() - Store a snapshot of CPU capabilities @@ -2362,3 +2308,69 @@ void arch_smt_update(void) /* Check whether IPI broadcasting can be enabled */ apic_smt_update(); } + +void __init arch_cpu_finalize_init(void) +{ + identify_boot_cpu(); + + /* + * identify_boot_cpu() initialized SMT support information, let the + * core code know. + */ + cpu_smt_check_topology(); + + if (!IS_ENABLED(CONFIG_SMP)) { + pr_info("CPU: "); + print_cpu_info(&boot_cpu_data); + } + + cpu_select_mitigations(); + + arch_smt_update(); + + if (IS_ENABLED(CONFIG_X86_32)) { + /* + * Check whether this is a real i386 which is not longer + * supported and fixup the utsname. + */ + if (boot_cpu_data.x86 < 4) + panic("Kernel requires i486+ for 'invlpg' and other features"); + + init_utsname()->machine[1] = + '0' + (boot_cpu_data.x86 > 6 ? 6 : boot_cpu_data.x86); + } + + /* + * Must be before alternatives because it might set or clear + * feature bits. + */ + fpu__init_system(); + fpu__init_cpu(); + + alternative_instructions(); + + if (IS_ENABLED(CONFIG_X86_64)) { + /* + * Make sure the first 2MB area is not mapped by huge pages + * There are typically fixed size MTRRs in there and overlapping + * MTRRs into large pages causes slow downs. + * + * Right now we don't do that with gbpages because there seems + * very little benefit for that case. + */ + if (!direct_gbpages) + set_memory_4k((unsigned long)__va(0), 1); + } else { + fpu__init_check_bugs(); + } + + /* + * This needs to be called before any devices perform DMA + * operations that might use the SWIOTLB bounce buffers. It will + * mark the bounce buffers as decrypted so that their usage will + * not cause "plain-text" data to be decrypted when accessed. It + * must be called after late_time_init() so that Hyper-V x86/x64 + * hypercalls work when the SWIOTLB bounce buffers are decrypted. + */ + mem_encrypt_init(); +} diff --git a/arch/x86/kernel/cpu/cpu.h b/arch/x86/kernel/cpu/cpu.h index f97b0fe13da805badcb180c4e27a1add8d6ccf1b..1c44630d47891c5fe0ac5313a221fbd7721ab1e3 100644 --- a/arch/x86/kernel/cpu/cpu.h +++ b/arch/x86/kernel/cpu/cpu.h @@ -79,6 +79,7 @@ extern void detect_ht(struct cpuinfo_x86 *c); extern void check_null_seg_clears_base(struct cpuinfo_x86 *c); unsigned int aperfmperf_get_khz(int cpu); +void cpu_select_mitigations(void); extern void x86_spec_ctrl_setup_ap(void); extern void update_srbds_msr(void); diff --git a/arch/x86/kernel/cpu/mce/amd.c b/arch/x86/kernel/cpu/mce/amd.c index 0b971f97409642636b7a4cff8e2f15885e8df9c1..5e74610b39e74f0b37b8e0dd8e78c32f55d8f07c 100644 --- a/arch/x86/kernel/cpu/mce/amd.c +++ b/arch/x86/kernel/cpu/mce/amd.c @@ -715,11 +715,13 @@ void mce_amd_feature_init(struct cpuinfo_x86 *c) bool amd_mce_is_memory_error(struct mce *m) { + enum smca_bank_types bank_type; /* ErrCodeExt[20:16] */ u8 xec = (m->status >> 16) & 0x1f; + bank_type = smca_get_bank_type(m->extcpu, m->bank); if (mce_flags.smca) - return smca_get_bank_type(m->extcpu, m->bank) == SMCA_UMC && xec == 0x0; + return (bank_type == SMCA_UMC || bank_type == SMCA_UMC_V2) && xec == 0x0; return m->bank == 4 && xec == 0x8; } @@ -1050,7 +1052,7 @@ static const char *get_name(unsigned int cpu, unsigned int bank, struct threshol if (bank_type >= N_SMCA_BANK_TYPES) return NULL; - if (b && bank_type == SMCA_UMC) { + if (b && (bank_type == SMCA_UMC || bank_type == SMCA_UMC_V2)) { if (b->block < ARRAY_SIZE(smca_umc_block_names)) return smca_umc_block_names[b->block]; return NULL; diff --git a/arch/x86/kernel/cpu/mce/core.c b/arch/x86/kernel/cpu/mce/core.c index 2eec60f50057a7204ea9e36e208d2637614de06d..89e2aab5d34d8513208ec45313df25502c8713ad 100644 --- a/arch/x86/kernel/cpu/mce/core.c +++ b/arch/x86/kernel/cpu/mce/core.c @@ -1022,12 +1022,12 @@ static noinstr int mce_start(int *no_way_out) if (!timeout) return ret; - arch_atomic_add(*no_way_out, &global_nwo); + raw_atomic_add(*no_way_out, &global_nwo); /* * Rely on the implied barrier below, such that global_nwo * is updated before mce_callin. */ - order = arch_atomic_inc_return(&mce_callin); + order = raw_atomic_inc_return(&mce_callin); arch_cpumask_clear_cpu(smp_processor_id(), &mce_missing_cpus); /* Enable instrumentation around calls to external facilities */ @@ -1036,10 +1036,10 @@ static noinstr int mce_start(int *no_way_out) /* * Wait for everyone. */ - while (arch_atomic_read(&mce_callin) != num_online_cpus()) { + while (raw_atomic_read(&mce_callin) != num_online_cpus()) { if (mce_timed_out(&timeout, "Timeout: Not all CPUs entered broadcast exception handler")) { - arch_atomic_set(&global_nwo, 0); + raw_atomic_set(&global_nwo, 0); goto out; } ndelay(SPINUNIT); @@ -1054,7 +1054,7 @@ static noinstr int mce_start(int *no_way_out) /* * Monarch: Starts executing now, the others wait. */ - arch_atomic_set(&mce_executing, 1); + raw_atomic_set(&mce_executing, 1); } else { /* * Subject: Now start the scanning loop one by one in @@ -1062,10 +1062,10 @@ static noinstr int mce_start(int *no_way_out) * This way when there are any shared banks it will be * only seen by one CPU before cleared, avoiding duplicates. */ - while (arch_atomic_read(&mce_executing) < order) { + while (raw_atomic_read(&mce_executing) < order) { if (mce_timed_out(&timeout, "Timeout: Subject CPUs unable to finish machine check processing")) { - arch_atomic_set(&global_nwo, 0); + raw_atomic_set(&global_nwo, 0); goto out; } ndelay(SPINUNIT); @@ -1075,7 +1075,7 @@ static noinstr int mce_start(int *no_way_out) /* * Cache the global no_way_out state. */ - *no_way_out = arch_atomic_read(&global_nwo); + *no_way_out = raw_atomic_read(&global_nwo); ret = order; @@ -1533,7 +1533,7 @@ noinstr void do_machine_check(struct pt_regs *regs) /* If this triggers there is no way to recover. Die hard. */ BUG_ON(!on_thread_stack() || !user_mode(regs)); - if (kill_current_task) + if (!mce_usable_address(&m)) queue_task_work(&m, msg, kill_me_now); else queue_task_work(&m, msg, kill_me_maybe); diff --git a/arch/x86/kernel/cpu/microcode/amd.c b/arch/x86/kernel/cpu/microcode/amd.c index f5fdeb1e3606ec3ce989624d513a459f3fd3d04a..87208e46f7ed1289ffd77f738801abc0bc415efb 100644 --- a/arch/x86/kernel/cpu/microcode/amd.c +++ b/arch/x86/kernel/cpu/microcode/amd.c @@ -78,8 +78,6 @@ static u16 find_equiv_id(struct equiv_cpu_table *et, u32 sig) if (sig == e->installed_cpu) return e->equiv_cpu; - - e++; } return 0; } @@ -596,11 +594,6 @@ void reload_ucode_amd(unsigned int cpu) } } } -static u16 __find_equiv_id(unsigned int cpu) -{ - struct ucode_cpu_info *uci = ucode_cpu_info + cpu; - return find_equiv_id(&equiv_table, uci->cpu_sig.sig); -} /* * a small, trivial cache of per-family ucode patches @@ -651,9 +644,11 @@ static void free_cache(void) static struct ucode_patch *find_patch(unsigned int cpu) { + struct ucode_cpu_info *uci = ucode_cpu_info + cpu; u16 equiv_id; - equiv_id = __find_equiv_id(cpu); + + equiv_id = find_equiv_id(&equiv_table, uci->cpu_sig.sig); if (!equiv_id) return NULL; @@ -705,7 +700,7 @@ static enum ucode_state apply_microcode_amd(int cpu) rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy); /* need to apply patch? */ - if (rev >= mc_amd->hdr.patch_id) { + if (rev > mc_amd->hdr.patch_id) { ret = UCODE_OK; goto out; } diff --git a/arch/x86/kernel/cpu/mtrr/Makefile b/arch/x86/kernel/cpu/mtrr/Makefile index cc4f9f1cb94cb1c97c8ca62fa5636c1e92a56187..aee4bc5ad49604decd43a4a5944585c162b0fd11 100644 --- a/arch/x86/kernel/cpu/mtrr/Makefile +++ b/arch/x86/kernel/cpu/mtrr/Makefile @@ -1,4 +1,4 @@ # SPDX-License-Identifier: GPL-2.0-only obj-y := mtrr.o if.o generic.o cleanup.o -obj-$(CONFIG_X86_32) += amd.o cyrix.o centaur.o +obj-$(CONFIG_X86_32) += amd.o cyrix.o centaur.o legacy.o diff --git a/arch/x86/kernel/cpu/mtrr/amd.c b/arch/x86/kernel/cpu/mtrr/amd.c index eff6ac62c0ff41586a7d36e30b09dfdf6d56ead1..ef3e8e42b7820ea5c7746f25b4bcec70f57e5f9d 100644 --- a/arch/x86/kernel/cpu/mtrr/amd.c +++ b/arch/x86/kernel/cpu/mtrr/amd.c @@ -110,7 +110,7 @@ amd_validate_add_page(unsigned long base, unsigned long size, unsigned int type) } const struct mtrr_ops amd_mtrr_ops = { - .vendor = X86_VENDOR_AMD, + .var_regs = 2, .set = amd_set_mtrr, .get = amd_get_mtrr, .get_free_region = generic_get_free_region, diff --git a/arch/x86/kernel/cpu/mtrr/centaur.c b/arch/x86/kernel/cpu/mtrr/centaur.c index b8a74eddde83b0eda80f0ce090f75422dcb88f02..6f6c3ae9294372fa62e95fee39b751dbc3371d7f 100644 --- a/arch/x86/kernel/cpu/mtrr/centaur.c +++ b/arch/x86/kernel/cpu/mtrr/centaur.c @@ -45,15 +45,6 @@ centaur_get_free_region(unsigned long base, unsigned long size, int replace_reg) return -ENOSPC; } -/* - * Report boot time MCR setups - */ -void mtrr_centaur_report_mcr(int mcr, u32 lo, u32 hi) -{ - centaur_mcr[mcr].low = lo; - centaur_mcr[mcr].high = hi; -} - static void centaur_get_mcr(unsigned int reg, unsigned long *base, unsigned long *size, mtrr_type * type) @@ -112,7 +103,7 @@ centaur_validate_add_page(unsigned long base, unsigned long size, unsigned int t } const struct mtrr_ops centaur_mtrr_ops = { - .vendor = X86_VENDOR_CENTAUR, + .var_regs = 8, .set = centaur_set_mcr, .get = centaur_get_mcr, .get_free_region = centaur_get_free_region, diff --git a/arch/x86/kernel/cpu/mtrr/cleanup.c b/arch/x86/kernel/cpu/mtrr/cleanup.c index b5f43049fa5f762a1c005ee66e2801c0d4be5286..18cf79d6e2c5a9d02509eced1272c3fb0dea099b 100644 --- a/arch/x86/kernel/cpu/mtrr/cleanup.c +++ b/arch/x86/kernel/cpu/mtrr/cleanup.c @@ -55,9 +55,6 @@ static int __initdata nr_range; static struct var_mtrr_range_state __initdata range_state[RANGE_NUM]; -static int __initdata debug_print; -#define Dprintk(x...) do { if (debug_print) pr_debug(x); } while (0) - #define BIOS_BUG_MSG \ "WARNING: BIOS bug: VAR MTRR %d contains strange UC entry under 1M, check with your system vendor!\n" @@ -79,12 +76,11 @@ x86_get_mtrr_mem_range(struct range *range, int nr_range, nr_range = add_range_with_merge(range, RANGE_NUM, nr_range, base, base + size); } - if (debug_print) { - pr_debug("After WB checking\n"); - for (i = 0; i < nr_range; i++) - pr_debug("MTRR MAP PFN: %016llx - %016llx\n", - range[i].start, range[i].end); - } + + Dprintk("After WB checking\n"); + for (i = 0; i < nr_range; i++) + Dprintk("MTRR MAP PFN: %016llx - %016llx\n", + range[i].start, range[i].end); /* Take out UC ranges: */ for (i = 0; i < num_var_ranges; i++) { @@ -112,24 +108,22 @@ x86_get_mtrr_mem_range(struct range *range, int nr_range, subtract_range(range, RANGE_NUM, extra_remove_base, extra_remove_base + extra_remove_size); - if (debug_print) { - pr_debug("After UC checking\n"); - for (i = 0; i < RANGE_NUM; i++) { - if (!range[i].end) - continue; - pr_debug("MTRR MAP PFN: %016llx - %016llx\n", - range[i].start, range[i].end); - } + Dprintk("After UC checking\n"); + for (i = 0; i < RANGE_NUM; i++) { + if (!range[i].end) + continue; + + Dprintk("MTRR MAP PFN: %016llx - %016llx\n", + range[i].start, range[i].end); } /* sort the ranges */ nr_range = clean_sort_range(range, RANGE_NUM); - if (debug_print) { - pr_debug("After sorting\n"); - for (i = 0; i < nr_range; i++) - pr_debug("MTRR MAP PFN: %016llx - %016llx\n", - range[i].start, range[i].end); - } + + Dprintk("After sorting\n"); + for (i = 0; i < nr_range; i++) + Dprintk("MTRR MAP PFN: %016llx - %016llx\n", + range[i].start, range[i].end); return nr_range; } @@ -164,16 +158,9 @@ static int __init enable_mtrr_cleanup_setup(char *str) } early_param("enable_mtrr_cleanup", enable_mtrr_cleanup_setup); -static int __init mtrr_cleanup_debug_setup(char *str) -{ - debug_print = 1; - return 0; -} -early_param("mtrr_cleanup_debug", mtrr_cleanup_debug_setup); - static void __init set_var_mtrr(unsigned int reg, unsigned long basek, unsigned long sizek, - unsigned char type, unsigned int address_bits) + unsigned char type) { u32 base_lo, base_hi, mask_lo, mask_hi; u64 base, mask; @@ -183,7 +170,7 @@ set_var_mtrr(unsigned int reg, unsigned long basek, unsigned long sizek, return; } - mask = (1ULL << address_bits) - 1; + mask = (1ULL << boot_cpu_data.x86_phys_bits) - 1; mask &= ~((((u64)sizek) << 10) - 1); base = ((u64)basek) << 10; @@ -209,7 +196,7 @@ save_var_mtrr(unsigned int reg, unsigned long basek, unsigned long sizek, range_state[reg].type = type; } -static void __init set_var_mtrr_all(unsigned int address_bits) +static void __init set_var_mtrr_all(void) { unsigned long basek, sizek; unsigned char type; @@ -220,7 +207,7 @@ static void __init set_var_mtrr_all(unsigned int address_bits) sizek = range_state[reg].size_pfn << (PAGE_SHIFT - 10); type = range_state[reg].type; - set_var_mtrr(reg, basek, sizek, type, address_bits); + set_var_mtrr(reg, basek, sizek, type); } } @@ -267,7 +254,7 @@ range_to_mtrr(unsigned int reg, unsigned long range_startk, align = max_align; sizek = 1UL << align; - if (debug_print) { + if (mtrr_debug) { char start_factor = 'K', size_factor = 'K'; unsigned long start_base, size_base; @@ -542,7 +529,7 @@ static void __init print_out_mtrr_range_state(void) start_base = to_size_factor(start_base, &start_factor); type = range_state[i].type; - pr_debug("reg %d, base: %ld%cB, range: %ld%cB, type %s\n", + Dprintk("reg %d, base: %ld%cB, range: %ld%cB, type %s\n", i, start_base, start_factor, size_base, size_factor, (type == MTRR_TYPE_UNCACHABLE) ? "UC" : @@ -680,7 +667,7 @@ static int __init mtrr_search_optimal_index(void) return index_good; } -int __init mtrr_cleanup(unsigned address_bits) +int __init mtrr_cleanup(void) { unsigned long x_remove_base, x_remove_size; unsigned long base, size, def, dummy; @@ -689,7 +676,10 @@ int __init mtrr_cleanup(unsigned address_bits) int index_good; int i; - if (!is_cpu(INTEL) || enable_mtrr_cleanup < 1) + if (!mtrr_enabled()) + return 0; + + if (!cpu_feature_enabled(X86_FEATURE_MTRR) || enable_mtrr_cleanup < 1) return 0; rdmsr(MSR_MTRRdefType, def, dummy); @@ -711,7 +701,7 @@ int __init mtrr_cleanup(unsigned address_bits) return 0; /* Print original var MTRRs at first, for debugging: */ - pr_debug("original variable MTRRs\n"); + Dprintk("original variable MTRRs\n"); print_out_mtrr_range_state(); memset(range, 0, sizeof(range)); @@ -742,8 +732,8 @@ int __init mtrr_cleanup(unsigned address_bits) mtrr_print_out_one_result(i); if (!result[i].bad) { - set_var_mtrr_all(address_bits); - pr_debug("New variable MTRRs\n"); + set_var_mtrr_all(); + Dprintk("New variable MTRRs\n"); print_out_mtrr_range_state(); return 1; } @@ -763,7 +753,7 @@ int __init mtrr_cleanup(unsigned address_bits) mtrr_calc_range_state(chunk_size, gran_size, x_remove_base, x_remove_size, i); - if (debug_print) { + if (mtrr_debug) { mtrr_print_out_one_result(i); pr_info("\n"); } @@ -786,8 +776,8 @@ int __init mtrr_cleanup(unsigned address_bits) gran_size = result[i].gran_sizek; gran_size <<= 10; x86_setup_var_mtrrs(range, nr_range, chunk_size, gran_size); - set_var_mtrr_all(address_bits); - pr_debug("New variable MTRRs\n"); + set_var_mtrr_all(); + Dprintk("New variable MTRRs\n"); print_out_mtrr_range_state(); return 1; } else { @@ -802,7 +792,7 @@ int __init mtrr_cleanup(unsigned address_bits) return 0; } #else -int __init mtrr_cleanup(unsigned address_bits) +int __init mtrr_cleanup(void) { return 0; } @@ -882,15 +872,18 @@ int __init mtrr_trim_uncached_memory(unsigned long end_pfn) /* extra one for all 0 */ int num[MTRR_NUM_TYPES + 1]; + if (!mtrr_enabled()) + return 0; + /* * Make sure we only trim uncachable memory on machines that * support the Intel MTRR architecture: */ - if (!is_cpu(INTEL) || disable_mtrr_trim) + if (!cpu_feature_enabled(X86_FEATURE_MTRR) || disable_mtrr_trim) return 0; rdmsr(MSR_MTRRdefType, def, dummy); - def &= 0xff; + def &= MTRR_DEF_TYPE_TYPE; if (def != MTRR_TYPE_UNCACHABLE) return 0; diff --git a/arch/x86/kernel/cpu/mtrr/cyrix.c b/arch/x86/kernel/cpu/mtrr/cyrix.c index 173b9e01e6231da0831cfed0580fcbf2957e57b8..238dad57d4d6bc9f34184bbc16f950dd87a8f03e 100644 --- a/arch/x86/kernel/cpu/mtrr/cyrix.c +++ b/arch/x86/kernel/cpu/mtrr/cyrix.c @@ -235,7 +235,7 @@ static void cyrix_set_arr(unsigned int reg, unsigned long base, } const struct mtrr_ops cyrix_mtrr_ops = { - .vendor = X86_VENDOR_CYRIX, + .var_regs = 8, .set = cyrix_set_arr, .get = cyrix_get_arr, .get_free_region = cyrix_get_free_region, diff --git a/arch/x86/kernel/cpu/mtrr/generic.c b/arch/x86/kernel/cpu/mtrr/generic.c index ee09d359e08f032090ce67ecba3106c1dec52663..2d6aa5d2e3d77ec49fd725e180fffe1df3c5987d 100644 --- a/arch/x86/kernel/cpu/mtrr/generic.c +++ b/arch/x86/kernel/cpu/mtrr/generic.c @@ -8,10 +8,12 @@ #include #include #include - +#include #include #include #include +#include +#include #include #include #include @@ -31,6 +33,55 @@ static struct fixed_range_block fixed_range_blocks[] = { {} }; +struct cache_map { + u64 start; + u64 end; + u64 flags; + u64 type:8; + u64 fixed:1; +}; + +bool mtrr_debug; + +static int __init mtrr_param_setup(char *str) +{ + int rc = 0; + + if (!str) + return -EINVAL; + if (!strcmp(str, "debug")) + mtrr_debug = true; + else + rc = -EINVAL; + + return rc; +} +early_param("mtrr", mtrr_param_setup); + +/* + * CACHE_MAP_MAX is the maximum number of memory ranges in cache_map, where + * no 2 adjacent ranges have the same cache mode (those would be merged). + * The number is based on the worst case: + * - no two adjacent fixed MTRRs share the same cache mode + * - one variable MTRR is spanning a huge area with mode WB + * - 255 variable MTRRs with mode UC all overlap with the WB MTRR, creating 2 + * additional ranges each (result like "ababababa...aba" with a = WB, b = UC), + * accounting for MTRR_MAX_VAR_RANGES * 2 - 1 range entries + * - a TOP_MEM2 area (even with overlapping an UC MTRR can't add 2 range entries + * to the possible maximum, as it always starts at 4GB, thus it can't be in + * the middle of that MTRR, unless that MTRR starts at 0, which would remove + * the initial "a" from the "abababa" pattern above) + * The map won't contain ranges with no matching MTRR (those fall back to the + * default cache mode). + */ +#define CACHE_MAP_MAX (MTRR_NUM_FIXED_RANGES + MTRR_MAX_VAR_RANGES * 2) + +static struct cache_map init_cache_map[CACHE_MAP_MAX] __initdata; +static struct cache_map *cache_map __refdata = init_cache_map; +static unsigned int cache_map_size = CACHE_MAP_MAX; +static unsigned int cache_map_n; +static unsigned int cache_map_fixed; + static unsigned long smp_changes_mask; static int mtrr_state_set; u64 mtrr_tom2; @@ -38,6 +89,9 @@ u64 mtrr_tom2; struct mtrr_state_type mtrr_state; EXPORT_SYMBOL_GPL(mtrr_state); +/* Reserved bits in the high portion of the MTRRphysBaseN MSR. */ +u32 phys_hi_rsvd; + /* * BIOS is expected to clear MtrrFixDramModEn bit, see for example * "BIOS and Kernel Developer's Guide for the AMD Athlon 64 and AMD @@ -69,175 +123,370 @@ static u64 get_mtrr_size(u64 mask) { u64 size; - mask >>= PAGE_SHIFT; - mask |= size_or_mask; + mask |= (u64)phys_hi_rsvd << 32; size = -mask; - size <<= PAGE_SHIFT; + return size; } +static u8 get_var_mtrr_state(unsigned int reg, u64 *start, u64 *size) +{ + struct mtrr_var_range *mtrr = mtrr_state.var_ranges + reg; + + if (!(mtrr->mask_lo & MTRR_PHYSMASK_V)) + return MTRR_TYPE_INVALID; + + *start = (((u64)mtrr->base_hi) << 32) + (mtrr->base_lo & PAGE_MASK); + *size = get_mtrr_size((((u64)mtrr->mask_hi) << 32) + + (mtrr->mask_lo & PAGE_MASK)); + + return mtrr->base_lo & MTRR_PHYSBASE_TYPE; +} + +static u8 get_effective_type(u8 type1, u8 type2) +{ + if (type1 == MTRR_TYPE_UNCACHABLE || type2 == MTRR_TYPE_UNCACHABLE) + return MTRR_TYPE_UNCACHABLE; + + if ((type1 == MTRR_TYPE_WRBACK && type2 == MTRR_TYPE_WRTHROUGH) || + (type1 == MTRR_TYPE_WRTHROUGH && type2 == MTRR_TYPE_WRBACK)) + return MTRR_TYPE_WRTHROUGH; + + if (type1 != type2) + return MTRR_TYPE_UNCACHABLE; + + return type1; +} + +static void rm_map_entry_at(int idx) +{ + cache_map_n--; + if (cache_map_n > idx) { + memmove(cache_map + idx, cache_map + idx + 1, + sizeof(*cache_map) * (cache_map_n - idx)); + } +} + /* - * Check and return the effective type for MTRR-MTRR type overlap. - * Returns 1 if the effective type is UNCACHEABLE, else returns 0 + * Add an entry into cache_map at a specific index. Merges adjacent entries if + * appropriate. Return the number of merges for correcting the scan index + * (this is needed as merging will reduce the number of entries, which will + * result in skipping entries in future iterations if the scan index isn't + * corrected). + * Note that the corrected index can never go below -1 (resulting in being 0 in + * the next scan iteration), as "2" is returned only if the current index is + * larger than zero. */ -static int check_type_overlap(u8 *prev, u8 *curr) +static int add_map_entry_at(u64 start, u64 end, u8 type, int idx) { - if (*prev == MTRR_TYPE_UNCACHABLE || *curr == MTRR_TYPE_UNCACHABLE) { - *prev = MTRR_TYPE_UNCACHABLE; - *curr = MTRR_TYPE_UNCACHABLE; - return 1; + bool merge_prev = false, merge_next = false; + + if (start >= end) + return 0; + + if (idx > 0) { + struct cache_map *prev = cache_map + idx - 1; + + if (!prev->fixed && start == prev->end && type == prev->type) + merge_prev = true; } - if ((*prev == MTRR_TYPE_WRBACK && *curr == MTRR_TYPE_WRTHROUGH) || - (*prev == MTRR_TYPE_WRTHROUGH && *curr == MTRR_TYPE_WRBACK)) { - *prev = MTRR_TYPE_WRTHROUGH; - *curr = MTRR_TYPE_WRTHROUGH; + if (idx < cache_map_n) { + struct cache_map *next = cache_map + idx; + + if (!next->fixed && end == next->start && type == next->type) + merge_next = true; } - if (*prev != *curr) { - *prev = MTRR_TYPE_UNCACHABLE; - *curr = MTRR_TYPE_UNCACHABLE; + if (merge_prev && merge_next) { + cache_map[idx - 1].end = cache_map[idx].end; + rm_map_entry_at(idx); + return 2; + } + if (merge_prev) { + cache_map[idx - 1].end = end; return 1; } + if (merge_next) { + cache_map[idx].start = start; + return 1; + } + + /* Sanity check: the array should NEVER be too small! */ + if (cache_map_n == cache_map_size) { + WARN(1, "MTRR cache mode memory map exhausted!\n"); + cache_map_n = cache_map_fixed; + return 0; + } + + if (cache_map_n > idx) { + memmove(cache_map + idx + 1, cache_map + idx, + sizeof(*cache_map) * (cache_map_n - idx)); + } + + cache_map[idx].start = start; + cache_map[idx].end = end; + cache_map[idx].type = type; + cache_map[idx].fixed = 0; + cache_map_n++; return 0; } -/** - * mtrr_type_lookup_fixed - look up memory type in MTRR fixed entries - * - * Return the MTRR fixed memory type of 'start'. - * - * MTRR fixed entries are divided into the following ways: - * 0x00000 - 0x7FFFF : This range is divided into eight 64KB sub-ranges - * 0x80000 - 0xBFFFF : This range is divided into sixteen 16KB sub-ranges - * 0xC0000 - 0xFFFFF : This range is divided into sixty-four 4KB sub-ranges - * - * Return Values: - * MTRR_TYPE_(type) - Matched memory type - * MTRR_TYPE_INVALID - Unmatched +/* Clear a part of an entry. Return 1 if start of entry is still valid. */ +static int clr_map_range_at(u64 start, u64 end, int idx) +{ + int ret = start != cache_map[idx].start; + u64 tmp; + + if (start == cache_map[idx].start && end == cache_map[idx].end) { + rm_map_entry_at(idx); + } else if (start == cache_map[idx].start) { + cache_map[idx].start = end; + } else if (end == cache_map[idx].end) { + cache_map[idx].end = start; + } else { + tmp = cache_map[idx].end; + cache_map[idx].end = start; + add_map_entry_at(end, tmp, cache_map[idx].type, idx + 1); + } + + return ret; +} + +/* + * Add MTRR to the map. The current map is scanned and each part of the MTRR + * either overlapping with an existing entry or with a hole in the map is + * handled separately. */ -static u8 mtrr_type_lookup_fixed(u64 start, u64 end) +static void add_map_entry(u64 start, u64 end, u8 type) { - int idx; + u8 new_type, old_type; + u64 tmp; + int i; - if (start >= 0x100000) - return MTRR_TYPE_INVALID; + for (i = 0; i < cache_map_n && start < end; i++) { + if (start >= cache_map[i].end) + continue; + + if (start < cache_map[i].start) { + /* Region start has no overlap. */ + tmp = min(end, cache_map[i].start); + i -= add_map_entry_at(start, tmp, type, i); + start = tmp; + continue; + } - /* 0x0 - 0x7FFFF */ - if (start < 0x80000) { - idx = 0; - idx += (start >> 16); - return mtrr_state.fixed_ranges[idx]; - /* 0x80000 - 0xBFFFF */ - } else if (start < 0xC0000) { - idx = 1 * 8; - idx += ((start - 0x80000) >> 14); - return mtrr_state.fixed_ranges[idx]; + new_type = get_effective_type(type, cache_map[i].type); + old_type = cache_map[i].type; + + if (cache_map[i].fixed || new_type == old_type) { + /* Cut off start of new entry. */ + start = cache_map[i].end; + continue; + } + + /* Handle only overlapping part of region. */ + tmp = min(end, cache_map[i].end); + i += clr_map_range_at(start, tmp, i); + i -= add_map_entry_at(start, tmp, new_type, i); + start = tmp; } - /* 0xC0000 - 0xFFFFF */ - idx = 3 * 8; - idx += ((start - 0xC0000) >> 12); - return mtrr_state.fixed_ranges[idx]; + /* Add rest of region after last map entry (rest might be empty). */ + add_map_entry_at(start, end, type, i); } -/** - * mtrr_type_lookup_variable - look up memory type in MTRR variable entries - * - * Return Value: - * MTRR_TYPE_(type) - Matched memory type or default memory type (unmatched) - * - * Output Arguments: - * repeat - Set to 1 when [start:end] spanned across MTRR range and type - * returned corresponds only to [start:*partial_end]. Caller has - * to lookup again for [*partial_end:end]. - * - * uniform - Set to 1 when an MTRR covers the region uniformly, i.e. the - * region is fully covered by a single MTRR entry or the default - * type. +/* Add variable MTRRs to cache map. */ +static void map_add_var(void) +{ + u64 start, size; + unsigned int i; + u8 type; + + /* + * Add AMD TOP_MEM2 area. Can't be added in mtrr_build_map(), as it + * needs to be added again when rebuilding the map due to potentially + * having moved as a result of variable MTRRs for memory below 4GB. + */ + if (mtrr_tom2) { + add_map_entry(BIT_ULL(32), mtrr_tom2, MTRR_TYPE_WRBACK); + cache_map[cache_map_n - 1].fixed = 1; + } + + for (i = 0; i < num_var_ranges; i++) { + type = get_var_mtrr_state(i, &start, &size); + if (type != MTRR_TYPE_INVALID) + add_map_entry(start, start + size, type); + } +} + +/* + * Rebuild map by replacing variable entries. Needs to be called when MTRR + * registers are being changed after boot, as such changes could include + * removals of registers, which are complicated to handle without rebuild of + * the map. */ -static u8 mtrr_type_lookup_variable(u64 start, u64 end, u64 *partial_end, - int *repeat, u8 *uniform) +void generic_rebuild_map(void) { - int i; - u64 base, mask; - u8 prev_match, curr_match; + if (mtrr_if != &generic_mtrr_ops) + return; - *repeat = 0; - *uniform = 1; + cache_map_n = cache_map_fixed; - prev_match = MTRR_TYPE_INVALID; - for (i = 0; i < num_var_ranges; ++i) { - unsigned short start_state, end_state, inclusive; + map_add_var(); +} - if (!(mtrr_state.var_ranges[i].mask_lo & (1 << 11))) - continue; +static unsigned int __init get_cache_map_size(void) +{ + return cache_map_fixed + 2 * num_var_ranges + (mtrr_tom2 != 0); +} - base = (((u64)mtrr_state.var_ranges[i].base_hi) << 32) + - (mtrr_state.var_ranges[i].base_lo & PAGE_MASK); - mask = (((u64)mtrr_state.var_ranges[i].mask_hi) << 32) + - (mtrr_state.var_ranges[i].mask_lo & PAGE_MASK); - - start_state = ((start & mask) == (base & mask)); - end_state = ((end & mask) == (base & mask)); - inclusive = ((start < base) && (end > base)); - - if ((start_state != end_state) || inclusive) { - /* - * We have start:end spanning across an MTRR. - * We split the region into either - * - * - start_state:1 - * (start:mtrr_end)(mtrr_end:end) - * - end_state:1 - * (start:mtrr_start)(mtrr_start:end) - * - inclusive:1 - * (start:mtrr_start)(mtrr_start:mtrr_end)(mtrr_end:end) - * - * depending on kind of overlap. - * - * Return the type of the first region and a pointer - * to the start of next region so that caller will be - * advised to lookup again after having adjusted start - * and end. - * - * Note: This way we handle overlaps with multiple - * entries and the default type properly. - */ - if (start_state) - *partial_end = base + get_mtrr_size(mask); - else - *partial_end = base; - - if (unlikely(*partial_end <= start)) { - WARN_ON(1); - *partial_end = start + PAGE_SIZE; - } +/* Build the cache_map containing the cache modes per memory range. */ +void __init mtrr_build_map(void) +{ + u64 start, end, size; + unsigned int i; + u8 type; - end = *partial_end - 1; /* end is inclusive */ - *repeat = 1; - *uniform = 0; + /* Add fixed MTRRs, optimize for adjacent entries with same type. */ + if (mtrr_state.enabled & MTRR_STATE_MTRR_FIXED_ENABLED) { + /* + * Start with 64k size fixed entries, preset 1st one (hence the + * loop below is starting with index 1). + */ + start = 0; + end = size = 0x10000; + type = mtrr_state.fixed_ranges[0]; + + for (i = 1; i < MTRR_NUM_FIXED_RANGES; i++) { + /* 8 64k entries, then 16 16k ones, rest 4k. */ + if (i == 8 || i == 24) + size >>= 2; + + if (mtrr_state.fixed_ranges[i] != type) { + add_map_entry(start, end, type); + start = end; + type = mtrr_state.fixed_ranges[i]; + } + end += size; } + add_map_entry(start, end, type); + } - if ((start & mask) != (base & mask)) - continue; + /* Mark fixed, they take precedence. */ + for (i = 0; i < cache_map_n; i++) + cache_map[i].fixed = 1; + cache_map_fixed = cache_map_n; - curr_match = mtrr_state.var_ranges[i].base_lo & 0xff; - if (prev_match == MTRR_TYPE_INVALID) { - prev_match = curr_match; - continue; + map_add_var(); + + pr_info("MTRR map: %u entries (%u fixed + %u variable; max %u), built from %u variable MTRRs\n", + cache_map_n, cache_map_fixed, cache_map_n - cache_map_fixed, + get_cache_map_size(), num_var_ranges + (mtrr_tom2 != 0)); + + if (mtrr_debug) { + for (i = 0; i < cache_map_n; i++) { + pr_info("%3u: %016llx-%016llx %s\n", i, + cache_map[i].start, cache_map[i].end - 1, + mtrr_attrib_to_str(cache_map[i].type)); } + } +} - *uniform = 0; - if (check_type_overlap(&prev_match, &curr_match)) - return curr_match; +/* Copy the cache_map from __initdata memory to dynamically allocated one. */ +void __init mtrr_copy_map(void) +{ + unsigned int new_size = get_cache_map_size(); + + if (!mtrr_state.enabled || !new_size) { + cache_map = NULL; + return; + } + + mutex_lock(&mtrr_mutex); + + cache_map = kcalloc(new_size, sizeof(*cache_map), GFP_KERNEL); + if (cache_map) { + memmove(cache_map, init_cache_map, + cache_map_n * sizeof(*cache_map)); + cache_map_size = new_size; + } else { + mtrr_state.enabled = 0; + pr_err("MTRRs disabled due to allocation failure for lookup map.\n"); + } + + mutex_unlock(&mtrr_mutex); +} + +/** + * mtrr_overwrite_state - set static MTRR state + * + * Used to set MTRR state via different means (e.g. with data obtained from + * a hypervisor). + * Is allowed only for special cases when running virtualized. Must be called + * from the x86_init.hyper.init_platform() hook. It can be called only once. + * The MTRR state can't be changed afterwards. To ensure that, X86_FEATURE_MTRR + * is cleared. + */ +void mtrr_overwrite_state(struct mtrr_var_range *var, unsigned int num_var, + mtrr_type def_type) +{ + unsigned int i; + + /* Only allowed to be called once before mtrr_bp_init(). */ + if (WARN_ON_ONCE(mtrr_state_set)) + return; + + /* Only allowed when running virtualized. */ + if (!cpu_feature_enabled(X86_FEATURE_HYPERVISOR)) + return; + + /* + * Only allowed for special virtualization cases: + * - when running as Hyper-V, SEV-SNP guest using vTOM + * - when running as Xen PV guest + * - when running as SEV-SNP or TDX guest to avoid unnecessary + * VMM communication/Virtualization exceptions (#VC, #VE) + */ + if (!cc_platform_has(CC_ATTR_GUEST_SEV_SNP) && + !hv_is_isolation_supported() && + !cpu_feature_enabled(X86_FEATURE_XENPV) && + !cpu_feature_enabled(X86_FEATURE_TDX_GUEST)) + return; + + /* Disable MTRR in order to disable MTRR modifications. */ + setup_clear_cpu_cap(X86_FEATURE_MTRR); + + if (var) { + if (num_var > MTRR_MAX_VAR_RANGES) { + pr_warn("Trying to overwrite MTRR state with %u variable entries\n", + num_var); + num_var = MTRR_MAX_VAR_RANGES; + } + for (i = 0; i < num_var; i++) + mtrr_state.var_ranges[i] = var[i]; + num_var_ranges = num_var; } - if (prev_match != MTRR_TYPE_INVALID) - return prev_match; + mtrr_state.def_type = def_type; + mtrr_state.enabled |= MTRR_STATE_MTRR_ENABLED; - return mtrr_state.def_type; + mtrr_state_set = 1; +} + +static u8 type_merge(u8 type, u8 new_type, u8 *uniform) +{ + u8 effective_type; + + if (type == MTRR_TYPE_INVALID) + return new_type; + + effective_type = get_effective_type(type, new_type); + if (type != effective_type) + *uniform = 0; + + return effective_type; } /** @@ -248,66 +497,49 @@ static u8 mtrr_type_lookup_variable(u64 start, u64 end, u64 *partial_end, * MTRR_TYPE_INVALID - MTRR is disabled * * Output Argument: - * uniform - Set to 1 when an MTRR covers the region uniformly, i.e. the - * region is fully covered by a single MTRR entry or the default - * type. + * uniform - Set to 1 when the returned MTRR type is valid for the whole + * region, set to 0 else. */ u8 mtrr_type_lookup(u64 start, u64 end, u8 *uniform) { - u8 type, prev_type, is_uniform = 1, dummy; - int repeat; - u64 partial_end; + u8 type = MTRR_TYPE_INVALID; + unsigned int i; - /* Make end inclusive instead of exclusive */ - end--; + if (!mtrr_state_set) { + /* Uniformity is unknown. */ + *uniform = 0; + return MTRR_TYPE_UNCACHABLE; + } - if (!mtrr_state_set) - return MTRR_TYPE_INVALID; + *uniform = 1; if (!(mtrr_state.enabled & MTRR_STATE_MTRR_ENABLED)) - return MTRR_TYPE_INVALID; + return MTRR_TYPE_UNCACHABLE; - /* - * Look up the fixed ranges first, which take priority over - * the variable ranges. - */ - if ((start < 0x100000) && - (mtrr_state.have_fixed) && - (mtrr_state.enabled & MTRR_STATE_MTRR_FIXED_ENABLED)) { - is_uniform = 0; - type = mtrr_type_lookup_fixed(start, end); - goto out; - } + for (i = 0; i < cache_map_n && start < end; i++) { + /* Region after current map entry? -> continue with next one. */ + if (start >= cache_map[i].end) + continue; - /* - * Look up the variable ranges. Look of multiple ranges matching - * this address and pick type as per MTRR precedence. - */ - type = mtrr_type_lookup_variable(start, end, &partial_end, - &repeat, &is_uniform); + /* Start of region not covered by current map entry? */ + if (start < cache_map[i].start) { + /* At least some part of region has default type. */ + type = type_merge(type, mtrr_state.def_type, uniform); + /* End of region not covered, too? -> lookup done. */ + if (end <= cache_map[i].start) + return type; + } - /* - * Common path is with repeat = 0. - * However, we can have cases where [start:end] spans across some - * MTRR ranges and/or the default type. Do repeated lookups for - * that case here. - */ - while (repeat) { - prev_type = type; - start = partial_end; - is_uniform = 0; - type = mtrr_type_lookup_variable(start, end, &partial_end, - &repeat, &dummy); + /* At least part of region covered by map entry. */ + type = type_merge(type, cache_map[i].type, uniform); - if (check_type_overlap(&prev_type, &type)) - goto out; + start = cache_map[i].end; } - if (mtrr_tom2 && (start >= (1ULL<<32)) && (end < mtrr_tom2)) - type = MTRR_TYPE_WRBACK; + /* End of region past last entry in map? -> use default type. */ + if (start < end) + type = type_merge(type, mtrr_state.def_type, uniform); -out: - *uniform = is_uniform; return type; } @@ -363,8 +595,8 @@ static void __init print_fixed_last(void) if (!last_fixed_end) return; - pr_debug(" %05X-%05X %s\n", last_fixed_start, - last_fixed_end - 1, mtrr_attrib_to_str(last_fixed_type)); + pr_info(" %05X-%05X %s\n", last_fixed_start, + last_fixed_end - 1, mtrr_attrib_to_str(last_fixed_type)); last_fixed_end = 0; } @@ -402,10 +634,10 @@ static void __init print_mtrr_state(void) unsigned int i; int high_width; - pr_debug("MTRR default type: %s\n", - mtrr_attrib_to_str(mtrr_state.def_type)); + pr_info("MTRR default type: %s\n", + mtrr_attrib_to_str(mtrr_state.def_type)); if (mtrr_state.have_fixed) { - pr_debug("MTRR fixed ranges %sabled:\n", + pr_info("MTRR fixed ranges %sabled:\n", ((mtrr_state.enabled & MTRR_STATE_MTRR_ENABLED) && (mtrr_state.enabled & MTRR_STATE_MTRR_FIXED_ENABLED)) ? "en" : "dis"); @@ -420,26 +652,27 @@ static void __init print_mtrr_state(void) /* tail */ print_fixed_last(); } - pr_debug("MTRR variable ranges %sabled:\n", - mtrr_state.enabled & MTRR_STATE_MTRR_ENABLED ? "en" : "dis"); - high_width = (__ffs64(size_or_mask) - (32 - PAGE_SHIFT) + 3) / 4; + pr_info("MTRR variable ranges %sabled:\n", + mtrr_state.enabled & MTRR_STATE_MTRR_ENABLED ? "en" : "dis"); + high_width = (boot_cpu_data.x86_phys_bits - (32 - PAGE_SHIFT) + 3) / 4; for (i = 0; i < num_var_ranges; ++i) { - if (mtrr_state.var_ranges[i].mask_lo & (1 << 11)) - pr_debug(" %u base %0*X%05X000 mask %0*X%05X000 %s\n", - i, - high_width, - mtrr_state.var_ranges[i].base_hi, - mtrr_state.var_ranges[i].base_lo >> 12, - high_width, - mtrr_state.var_ranges[i].mask_hi, - mtrr_state.var_ranges[i].mask_lo >> 12, - mtrr_attrib_to_str(mtrr_state.var_ranges[i].base_lo & 0xff)); + if (mtrr_state.var_ranges[i].mask_lo & MTRR_PHYSMASK_V) + pr_info(" %u base %0*X%05X000 mask %0*X%05X000 %s\n", + i, + high_width, + mtrr_state.var_ranges[i].base_hi, + mtrr_state.var_ranges[i].base_lo >> 12, + high_width, + mtrr_state.var_ranges[i].mask_hi, + mtrr_state.var_ranges[i].mask_lo >> 12, + mtrr_attrib_to_str(mtrr_state.var_ranges[i].base_lo & + MTRR_PHYSBASE_TYPE)); else - pr_debug(" %u disabled\n", i); + pr_info(" %u disabled\n", i); } if (mtrr_tom2) - pr_debug("TOM2: %016llx aka %lldM\n", mtrr_tom2, mtrr_tom2>>20); + pr_info("TOM2: %016llx aka %lldM\n", mtrr_tom2, mtrr_tom2>>20); } /* Grab all of the MTRR state for this CPU into *state */ @@ -452,7 +685,7 @@ bool __init get_mtrr_state(void) vrs = mtrr_state.var_ranges; rdmsr(MSR_MTRRcap, lo, dummy); - mtrr_state.have_fixed = (lo >> 8) & 1; + mtrr_state.have_fixed = lo & MTRR_CAP_FIX; for (i = 0; i < num_var_ranges; i++) get_mtrr_var_range(i, &vrs[i]); @@ -460,8 +693,8 @@ bool __init get_mtrr_state(void) get_fixed_ranges(mtrr_state.fixed_ranges); rdmsr(MSR_MTRRdefType, lo, dummy); - mtrr_state.def_type = (lo & 0xff); - mtrr_state.enabled = (lo & 0xc00) >> 10; + mtrr_state.def_type = lo & MTRR_DEF_TYPE_TYPE; + mtrr_state.enabled = (lo & MTRR_DEF_TYPE_ENABLE) >> MTRR_STATE_SHIFT; if (amd_special_default_mtrr()) { unsigned low, high; @@ -474,7 +707,8 @@ bool __init get_mtrr_state(void) mtrr_tom2 &= 0xffffff800000ULL; } - print_mtrr_state(); + if (mtrr_debug) + print_mtrr_state(); mtrr_state_set = 1; @@ -574,7 +808,7 @@ static void generic_get_mtrr(unsigned int reg, unsigned long *base, rdmsr(MTRRphysMask_MSR(reg), mask_lo, mask_hi); - if ((mask_lo & 0x800) == 0) { + if (!(mask_lo & MTRR_PHYSMASK_V)) { /* Invalid (i.e. free) range */ *base = 0; *size = 0; @@ -585,8 +819,8 @@ static void generic_get_mtrr(unsigned int reg, unsigned long *base, rdmsr(MTRRphysBase_MSR(reg), base_lo, base_hi); /* Work out the shifted address mask: */ - tmp = (u64)mask_hi << (32 - PAGE_SHIFT) | mask_lo >> PAGE_SHIFT; - mask = size_or_mask | tmp; + tmp = (u64)mask_hi << 32 | (mask_lo & PAGE_MASK); + mask = (u64)phys_hi_rsvd << 32 | tmp; /* Expand tmp with high bits to all 1s: */ hi = fls64(tmp); @@ -604,9 +838,9 @@ static void generic_get_mtrr(unsigned int reg, unsigned long *base, * This works correctly if size is a power of two, i.e. a * contiguous range: */ - *size = -mask; + *size = -mask >> PAGE_SHIFT; *base = (u64)base_hi << (32 - PAGE_SHIFT) | base_lo >> PAGE_SHIFT; - *type = base_lo & 0xff; + *type = base_lo & MTRR_PHYSBASE_TYPE; out_put_cpu: put_cpu(); @@ -644,9 +878,8 @@ static bool set_mtrr_var_ranges(unsigned int index, struct mtrr_var_range *vr) bool changed = false; rdmsr(MTRRphysBase_MSR(index), lo, hi); - if ((vr->base_lo & 0xfffff0ffUL) != (lo & 0xfffff0ffUL) - || (vr->base_hi & (size_and_mask >> (32 - PAGE_SHIFT))) != - (hi & (size_and_mask >> (32 - PAGE_SHIFT)))) { + if ((vr->base_lo & ~MTRR_PHYSBASE_RSVD) != (lo & ~MTRR_PHYSBASE_RSVD) + || (vr->base_hi & ~phys_hi_rsvd) != (hi & ~phys_hi_rsvd)) { mtrr_wrmsr(MTRRphysBase_MSR(index), vr->base_lo, vr->base_hi); changed = true; @@ -654,9 +887,8 @@ static bool set_mtrr_var_ranges(unsigned int index, struct mtrr_var_range *vr) rdmsr(MTRRphysMask_MSR(index), lo, hi); - if ((vr->mask_lo & 0xfffff800UL) != (lo & 0xfffff800UL) - || (vr->mask_hi & (size_and_mask >> (32 - PAGE_SHIFT))) != - (hi & (size_and_mask >> (32 - PAGE_SHIFT)))) { + if ((vr->mask_lo & ~MTRR_PHYSMASK_RSVD) != (lo & ~MTRR_PHYSMASK_RSVD) + || (vr->mask_hi & ~phys_hi_rsvd) != (hi & ~phys_hi_rsvd)) { mtrr_wrmsr(MTRRphysMask_MSR(index), vr->mask_lo, vr->mask_hi); changed = true; } @@ -691,11 +923,12 @@ static unsigned long set_mtrr_state(void) * Set_mtrr_restore restores the old value of MTRRdefType, * so to set it we fiddle with the saved value: */ - if ((deftype_lo & 0xff) != mtrr_state.def_type - || ((deftype_lo & 0xc00) >> 10) != mtrr_state.enabled) { + if ((deftype_lo & MTRR_DEF_TYPE_TYPE) != mtrr_state.def_type || + ((deftype_lo & MTRR_DEF_TYPE_ENABLE) >> MTRR_STATE_SHIFT) != mtrr_state.enabled) { - deftype_lo = (deftype_lo & ~0xcff) | mtrr_state.def_type | - (mtrr_state.enabled << 10); + deftype_lo = (deftype_lo & MTRR_DEF_TYPE_DISABLE) | + mtrr_state.def_type | + (mtrr_state.enabled << MTRR_STATE_SHIFT); change_mask |= MTRR_CHANGE_MASK_DEFTYPE; } @@ -708,7 +941,7 @@ void mtrr_disable(void) rdmsr(MSR_MTRRdefType, deftype_lo, deftype_hi); /* Disable MTRRs, and set the default type to uncached */ - mtrr_wrmsr(MSR_MTRRdefType, deftype_lo & ~0xcff, deftype_hi); + mtrr_wrmsr(MSR_MTRRdefType, deftype_lo & MTRR_DEF_TYPE_DISABLE, deftype_hi); } void mtrr_enable(void) @@ -762,9 +995,9 @@ static void generic_set_mtrr(unsigned int reg, unsigned long base, memset(vr, 0, sizeof(struct mtrr_var_range)); } else { vr->base_lo = base << PAGE_SHIFT | type; - vr->base_hi = (base & size_and_mask) >> (32 - PAGE_SHIFT); - vr->mask_lo = -size << PAGE_SHIFT | 0x800; - vr->mask_hi = (-size & size_and_mask) >> (32 - PAGE_SHIFT); + vr->base_hi = (base >> (32 - PAGE_SHIFT)) & ~phys_hi_rsvd; + vr->mask_lo = -size << PAGE_SHIFT | MTRR_PHYSMASK_V; + vr->mask_hi = (-size >> (32 - PAGE_SHIFT)) & ~phys_hi_rsvd; mtrr_wrmsr(MTRRphysBase_MSR(reg), vr->base_lo, vr->base_hi); mtrr_wrmsr(MTRRphysMask_MSR(reg), vr->mask_lo, vr->mask_hi); @@ -783,7 +1016,7 @@ int generic_validate_add_page(unsigned long base, unsigned long size, * For Intel PPro stepping <= 7 * must be 4 MiB aligned and not touch 0x70000000 -> 0x7003FFFF */ - if (is_cpu(INTEL) && boot_cpu_data.x86 == 6 && + if (mtrr_if == &generic_mtrr_ops && boot_cpu_data.x86 == 6 && boot_cpu_data.x86_model == 1 && boot_cpu_data.x86_stepping <= 7) { if (base & ((1 << (22 - PAGE_SHIFT)) - 1)) { @@ -817,7 +1050,7 @@ static int generic_have_wrcomb(void) { unsigned long config, dummy; rdmsr(MSR_MTRRcap, config, dummy); - return config & (1 << 10); + return config & MTRR_CAP_WC; } int positive_have_wrcomb(void) diff --git a/arch/x86/kernel/cpu/mtrr/legacy.c b/arch/x86/kernel/cpu/mtrr/legacy.c new file mode 100644 index 0000000000000000000000000000000000000000..d25882fcf181dbc8e7a62f379bc5a76397db5ea1 --- /dev/null +++ b/arch/x86/kernel/cpu/mtrr/legacy.c @@ -0,0 +1,90 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include +#include +#include +#include +#include +#include +#include "mtrr.h" + +void mtrr_set_if(void) +{ + switch (boot_cpu_data.x86_vendor) { + case X86_VENDOR_AMD: + /* Pre-Athlon (K6) AMD CPU MTRRs */ + if (cpu_feature_enabled(X86_FEATURE_K6_MTRR)) + mtrr_if = &amd_mtrr_ops; + break; + case X86_VENDOR_CENTAUR: + if (cpu_feature_enabled(X86_FEATURE_CENTAUR_MCR)) + mtrr_if = ¢aur_mtrr_ops; + break; + case X86_VENDOR_CYRIX: + if (cpu_feature_enabled(X86_FEATURE_CYRIX_ARR)) + mtrr_if = &cyrix_mtrr_ops; + break; + default: + break; + } +} + +/* + * The suspend/resume methods are only for CPUs without MTRR. CPUs using generic + * MTRR driver don't require this. + */ +struct mtrr_value { + mtrr_type ltype; + unsigned long lbase; + unsigned long lsize; +}; + +static struct mtrr_value *mtrr_value; + +static int mtrr_save(void) +{ + int i; + + if (!mtrr_value) + return -ENOMEM; + + for (i = 0; i < num_var_ranges; i++) { + mtrr_if->get(i, &mtrr_value[i].lbase, + &mtrr_value[i].lsize, + &mtrr_value[i].ltype); + } + return 0; +} + +static void mtrr_restore(void) +{ + int i; + + for (i = 0; i < num_var_ranges; i++) { + if (mtrr_value[i].lsize) { + mtrr_if->set(i, mtrr_value[i].lbase, + mtrr_value[i].lsize, + mtrr_value[i].ltype); + } + } +} + +static struct syscore_ops mtrr_syscore_ops = { + .suspend = mtrr_save, + .resume = mtrr_restore, +}; + +void mtrr_register_syscore(void) +{ + mtrr_value = kcalloc(num_var_ranges, sizeof(*mtrr_value), GFP_KERNEL); + + /* + * The CPU has no MTRR and seems to not support SMP. They have + * specific drivers, we use a tricky method to support + * suspend/resume for them. + * + * TBD: is there any system with such CPU which supports + * suspend/resume? If no, we should remove the code. + */ + register_syscore_ops(&mtrr_syscore_ops); +} diff --git a/arch/x86/kernel/cpu/mtrr/mtrr.c b/arch/x86/kernel/cpu/mtrr/mtrr.c index 783f3210d5827ecf68e5a9b97eb0a869539a9de6..767bf1c71aadda1a63e9d8c43244b219294ac778 100644 --- a/arch/x86/kernel/cpu/mtrr/mtrr.c +++ b/arch/x86/kernel/cpu/mtrr/mtrr.c @@ -59,15 +59,9 @@ #define MTRR_TO_PHYS_WC_OFFSET 1000 u32 num_var_ranges; -static bool mtrr_enabled(void) -{ - return !!mtrr_if; -} unsigned int mtrr_usage_table[MTRR_MAX_VAR_RANGES]; -static DEFINE_MUTEX(mtrr_mutex); - -u64 size_or_mask, size_and_mask; +DEFINE_MUTEX(mtrr_mutex); const struct mtrr_ops *mtrr_if; @@ -105,21 +99,6 @@ static int have_wrcomb(void) return mtrr_if->have_wrcomb ? mtrr_if->have_wrcomb() : 0; } -/* This function returns the number of variable MTRRs */ -static void __init set_num_var_ranges(bool use_generic) -{ - unsigned long config = 0, dummy; - - if (use_generic) - rdmsr(MSR_MTRRcap, config, dummy); - else if (is_cpu(AMD) || is_cpu(HYGON)) - config = 2; - else if (is_cpu(CYRIX) || is_cpu(CENTAUR)) - config = 8; - - num_var_ranges = config & 0xff; -} - static void __init init_table(void) { int i, max; @@ -194,20 +173,8 @@ static inline int types_compatible(mtrr_type type1, mtrr_type type2) * Note that the mechanism is the same for UP systems, too; all the SMP stuff * becomes nops. */ -static void -set_mtrr(unsigned int reg, unsigned long base, unsigned long size, mtrr_type type) -{ - struct set_mtrr_data data = { .smp_reg = reg, - .smp_base = base, - .smp_size = size, - .smp_type = type - }; - - stop_machine(mtrr_rendezvous_handler, &data, cpu_online_mask); -} - -static void set_mtrr_cpuslocked(unsigned int reg, unsigned long base, - unsigned long size, mtrr_type type) +static void set_mtrr(unsigned int reg, unsigned long base, unsigned long size, + mtrr_type type) { struct set_mtrr_data data = { .smp_reg = reg, .smp_base = base, @@ -216,6 +183,8 @@ static void set_mtrr_cpuslocked(unsigned int reg, unsigned long base, }; stop_machine_cpuslocked(mtrr_rendezvous_handler, &data, cpu_online_mask); + + generic_rebuild_map(); } /** @@ -337,7 +306,7 @@ int mtrr_add_page(unsigned long base, unsigned long size, /* Search for an empty MTRR */ i = mtrr_if->get_free_region(base, size, replace); if (i >= 0) { - set_mtrr_cpuslocked(i, base, size, type); + set_mtrr(i, base, size, type); if (likely(replace < 0)) { mtrr_usage_table[i] = 1; } else { @@ -345,7 +314,7 @@ int mtrr_add_page(unsigned long base, unsigned long size, if (increment) mtrr_usage_table[i]++; if (unlikely(replace != i)) { - set_mtrr_cpuslocked(replace, 0, 0, 0); + set_mtrr(replace, 0, 0, 0); mtrr_usage_table[replace] = 0; } } @@ -363,7 +332,7 @@ static int mtrr_check(unsigned long base, unsigned long size) { if ((base & (PAGE_SIZE - 1)) || (size & (PAGE_SIZE - 1))) { pr_warn("size and base must be multiples of 4 kiB\n"); - pr_debug("size: 0x%lx base: 0x%lx\n", size, base); + Dprintk("size: 0x%lx base: 0x%lx\n", size, base); dump_stack(); return -1; } @@ -454,8 +423,7 @@ int mtrr_del_page(int reg, unsigned long base, unsigned long size) } } if (reg < 0) { - pr_debug("no MTRR for %lx000,%lx000 found\n", - base, size); + Dprintk("no MTRR for %lx000,%lx000 found\n", base, size); goto out; } } @@ -473,7 +441,7 @@ int mtrr_del_page(int reg, unsigned long base, unsigned long size) goto out; } if (--mtrr_usage_table[reg] < 1) - set_mtrr_cpuslocked(reg, 0, 0, 0); + set_mtrr(reg, 0, 0, 0); error = reg; out: mutex_unlock(&mtrr_mutex); @@ -574,136 +542,54 @@ int arch_phys_wc_index(int handle) } EXPORT_SYMBOL_GPL(arch_phys_wc_index); -/* The suspend/resume methods are only for CPU without MTRR. CPU using generic - * MTRR driver doesn't require this - */ -struct mtrr_value { - mtrr_type ltype; - unsigned long lbase; - unsigned long lsize; -}; - -static struct mtrr_value mtrr_value[MTRR_MAX_VAR_RANGES]; - -static int mtrr_save(void) -{ - int i; - - for (i = 0; i < num_var_ranges; i++) { - mtrr_if->get(i, &mtrr_value[i].lbase, - &mtrr_value[i].lsize, - &mtrr_value[i].ltype); - } - return 0; -} - -static void mtrr_restore(void) -{ - int i; - - for (i = 0; i < num_var_ranges; i++) { - if (mtrr_value[i].lsize) { - set_mtrr(i, mtrr_value[i].lbase, - mtrr_value[i].lsize, - mtrr_value[i].ltype); - } - } -} - - - -static struct syscore_ops mtrr_syscore_ops = { - .suspend = mtrr_save, - .resume = mtrr_restore, -}; - int __initdata changed_by_mtrr_cleanup; -#define SIZE_OR_MASK_BITS(n) (~((1ULL << ((n) - PAGE_SHIFT)) - 1)) /** - * mtrr_bp_init - initialize mtrrs on the boot CPU + * mtrr_bp_init - initialize MTRRs on the boot CPU * * This needs to be called early; before any of the other CPUs are * initialized (i.e. before smp_init()). - * */ void __init mtrr_bp_init(void) { + bool generic_mtrrs = cpu_feature_enabled(X86_FEATURE_MTRR); const char *why = "(not available)"; - u32 phys_addr; - - phys_addr = 32; + unsigned long config, dummy; - if (boot_cpu_has(X86_FEATURE_MTRR)) { - mtrr_if = &generic_mtrr_ops; - size_or_mask = SIZE_OR_MASK_BITS(36); - size_and_mask = 0x00f00000; - phys_addr = 36; + phys_hi_rsvd = GENMASK(31, boot_cpu_data.x86_phys_bits - 32); + if (!generic_mtrrs && mtrr_state.enabled) { /* - * This is an AMD specific MSR, but we assume(hope?) that - * Intel will implement it too when they extend the address - * bus of the Xeon. + * Software overwrite of MTRR state, only for generic case. + * Note that X86_FEATURE_MTRR has been reset in this case. */ - if (cpuid_eax(0x80000000) >= 0x80000008) { - phys_addr = cpuid_eax(0x80000008) & 0xff; - /* CPUID workaround for Intel 0F33/0F34 CPU */ - if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL && - boot_cpu_data.x86 == 0xF && - boot_cpu_data.x86_model == 0x3 && - (boot_cpu_data.x86_stepping == 0x3 || - boot_cpu_data.x86_stepping == 0x4)) - phys_addr = 36; - - size_or_mask = SIZE_OR_MASK_BITS(phys_addr); - size_and_mask = ~size_or_mask & 0xfffff00000ULL; - } else if (boot_cpu_data.x86_vendor == X86_VENDOR_CENTAUR && - boot_cpu_data.x86 == 6) { - /* - * VIA C* family have Intel style MTRRs, - * but don't support PAE - */ - size_or_mask = SIZE_OR_MASK_BITS(32); - size_and_mask = 0; - phys_addr = 32; - } - } else { - switch (boot_cpu_data.x86_vendor) { - case X86_VENDOR_AMD: - if (cpu_feature_enabled(X86_FEATURE_K6_MTRR)) { - /* Pre-Athlon (K6) AMD CPU MTRRs */ - mtrr_if = &amd_mtrr_ops; - size_or_mask = SIZE_OR_MASK_BITS(32); - size_and_mask = 0; - } - break; - case X86_VENDOR_CENTAUR: - if (cpu_feature_enabled(X86_FEATURE_CENTAUR_MCR)) { - mtrr_if = ¢aur_mtrr_ops; - size_or_mask = SIZE_OR_MASK_BITS(32); - size_and_mask = 0; - } - break; - case X86_VENDOR_CYRIX: - if (cpu_feature_enabled(X86_FEATURE_CYRIX_ARR)) { - mtrr_if = &cyrix_mtrr_ops; - size_or_mask = SIZE_OR_MASK_BITS(32); - size_and_mask = 0; - } - break; - default: - break; - } + init_table(); + mtrr_build_map(); + pr_info("MTRRs set to read-only\n"); + + return; } + if (generic_mtrrs) + mtrr_if = &generic_mtrr_ops; + else + mtrr_set_if(); + if (mtrr_enabled()) { - set_num_var_ranges(mtrr_if == &generic_mtrr_ops); + /* Get the number of variable MTRR ranges. */ + if (mtrr_if == &generic_mtrr_ops) + rdmsr(MSR_MTRRcap, config, dummy); + else + config = mtrr_if->var_regs; + num_var_ranges = config & MTRR_CAP_VCNT; + init_table(); if (mtrr_if == &generic_mtrr_ops) { /* BIOS may override */ if (get_mtrr_state()) { memory_caching_control |= CACHE_MTRR; - changed_by_mtrr_cleanup = mtrr_cleanup(phys_addr); + changed_by_mtrr_cleanup = mtrr_cleanup(); + mtrr_build_map(); } else { mtrr_if = NULL; why = "by BIOS"; @@ -730,8 +616,14 @@ void mtrr_save_state(void) smp_call_function_single(first_cpu, mtrr_save_fixed_ranges, NULL, 1); } -static int __init mtrr_init_finialize(void) +static int __init mtrr_init_finalize(void) { + /* + * Map might exist if mtrr_overwrite_state() has been called or if + * mtrr_enabled() returns true. + */ + mtrr_copy_map(); + if (!mtrr_enabled()) return 0; @@ -741,16 +633,8 @@ static int __init mtrr_init_finialize(void) return 0; } - /* - * The CPU has no MTRR and seems to not support SMP. They have - * specific drivers, we use a tricky method to support - * suspend/resume for them. - * - * TBD: is there any system with such CPU which supports - * suspend/resume? If no, we should remove the code. - */ - register_syscore_ops(&mtrr_syscore_ops); + mtrr_register_syscore(); return 0; } -subsys_initcall(mtrr_init_finialize); +subsys_initcall(mtrr_init_finalize); diff --git a/arch/x86/kernel/cpu/mtrr/mtrr.h b/arch/x86/kernel/cpu/mtrr/mtrr.h index 02eb5871492d08cdd7189f23f4e4076e3cb4b2a7..5655f253d929a84f0c211af7485db00a305a88d7 100644 --- a/arch/x86/kernel/cpu/mtrr/mtrr.h +++ b/arch/x86/kernel/cpu/mtrr/mtrr.h @@ -10,10 +10,13 @@ #define MTRR_CHANGE_MASK_VARIABLE 0x02 #define MTRR_CHANGE_MASK_DEFTYPE 0x04 +extern bool mtrr_debug; +#define Dprintk(x...) do { if (mtrr_debug) pr_info(x); } while (0) + extern unsigned int mtrr_usage_table[MTRR_MAX_VAR_RANGES]; struct mtrr_ops { - u32 vendor; + u32 var_regs; void (*set)(unsigned int reg, unsigned long base, unsigned long size, mtrr_type type); void (*get)(unsigned int reg, unsigned long *base, @@ -51,18 +54,26 @@ void fill_mtrr_var_range(unsigned int index, u32 base_lo, u32 base_hi, u32 mask_lo, u32 mask_hi); bool get_mtrr_state(void); -extern u64 size_or_mask, size_and_mask; extern const struct mtrr_ops *mtrr_if; - -#define is_cpu(vnd) (mtrr_if && mtrr_if->vendor == X86_VENDOR_##vnd) +extern struct mutex mtrr_mutex; extern unsigned int num_var_ranges; extern u64 mtrr_tom2; extern struct mtrr_state_type mtrr_state; +extern u32 phys_hi_rsvd; void mtrr_state_warn(void); const char *mtrr_attrib_to_str(int x); void mtrr_wrmsr(unsigned, unsigned, unsigned); +#ifdef CONFIG_X86_32 +void mtrr_set_if(void); +void mtrr_register_syscore(void); +#else +static inline void mtrr_set_if(void) { } +static inline void mtrr_register_syscore(void) { } +#endif +void mtrr_build_map(void); +void mtrr_copy_map(void); /* CPU specific mtrr_ops vectors. */ extern const struct mtrr_ops amd_mtrr_ops; @@ -70,4 +81,14 @@ extern const struct mtrr_ops cyrix_mtrr_ops; extern const struct mtrr_ops centaur_mtrr_ops; extern int changed_by_mtrr_cleanup; -extern int mtrr_cleanup(unsigned address_bits); +extern int mtrr_cleanup(void); + +/* + * Must be used by code which uses mtrr_if to call platform-specific + * MTRR manipulation functions. + */ +static inline bool mtrr_enabled(void) +{ + return !!mtrr_if; +} +void generic_rebuild_map(void); diff --git a/arch/x86/kernel/cpu/resctrl/rdtgroup.c b/arch/x86/kernel/cpu/resctrl/rdtgroup.c index 6ad33f355861feab9a1f013ff82e026e9638044b..725344048f85da42a826514c66c8abe79f4035ba 100644 --- a/arch/x86/kernel/cpu/resctrl/rdtgroup.c +++ b/arch/x86/kernel/cpu/resctrl/rdtgroup.c @@ -726,11 +726,15 @@ static ssize_t rdtgroup_tasks_write(struct kernfs_open_file *of, static void show_rdt_tasks(struct rdtgroup *r, struct seq_file *s) { struct task_struct *p, *t; + pid_t pid; rcu_read_lock(); for_each_process_thread(p, t) { - if (is_closid_match(t, r) || is_rmid_match(t, r)) - seq_printf(s, "%d\n", t->pid); + if (is_closid_match(t, r) || is_rmid_match(t, r)) { + pid = task_pid_vnr(t); + if (pid) + seq_printf(s, "%d\n", pid); + } } rcu_read_unlock(); } @@ -2301,6 +2305,26 @@ static struct rdtgroup *kernfs_to_rdtgroup(struct kernfs_node *kn) } } +static void rdtgroup_kn_get(struct rdtgroup *rdtgrp, struct kernfs_node *kn) +{ + atomic_inc(&rdtgrp->waitcount); + kernfs_break_active_protection(kn); +} + +static void rdtgroup_kn_put(struct rdtgroup *rdtgrp, struct kernfs_node *kn) +{ + if (atomic_dec_and_test(&rdtgrp->waitcount) && + (rdtgrp->flags & RDT_DELETED)) { + if (rdtgrp->mode == RDT_MODE_PSEUDO_LOCKSETUP || + rdtgrp->mode == RDT_MODE_PSEUDO_LOCKED) + rdtgroup_pseudo_lock_remove(rdtgrp); + kernfs_unbreak_active_protection(kn); + rdtgroup_remove(rdtgrp); + } else { + kernfs_unbreak_active_protection(kn); + } +} + struct rdtgroup *rdtgroup_kn_lock_live(struct kernfs_node *kn) { struct rdtgroup *rdtgrp = kernfs_to_rdtgroup(kn); @@ -2308,8 +2332,7 @@ struct rdtgroup *rdtgroup_kn_lock_live(struct kernfs_node *kn) if (!rdtgrp) return NULL; - atomic_inc(&rdtgrp->waitcount); - kernfs_break_active_protection(kn); + rdtgroup_kn_get(rdtgrp, kn); mutex_lock(&rdtgroup_mutex); @@ -2328,17 +2351,7 @@ void rdtgroup_kn_unlock(struct kernfs_node *kn) return; mutex_unlock(&rdtgroup_mutex); - - if (atomic_dec_and_test(&rdtgrp->waitcount) && - (rdtgrp->flags & RDT_DELETED)) { - if (rdtgrp->mode == RDT_MODE_PSEUDO_LOCKSETUP || - rdtgrp->mode == RDT_MODE_PSEUDO_LOCKED) - rdtgroup_pseudo_lock_remove(rdtgrp); - kernfs_unbreak_active_protection(kn); - rdtgroup_remove(rdtgrp); - } else { - kernfs_unbreak_active_protection(kn); - } + rdtgroup_kn_put(rdtgrp, kn); } static int mkdir_mondata_all(struct kernfs_node *parent_kn, @@ -3505,6 +3518,133 @@ static int rdtgroup_rmdir(struct kernfs_node *kn) return ret; } +/** + * mongrp_reparent() - replace parent CTRL_MON group of a MON group + * @rdtgrp: the MON group whose parent should be replaced + * @new_prdtgrp: replacement parent CTRL_MON group for @rdtgrp + * @cpus: cpumask provided by the caller for use during this call + * + * Replaces the parent CTRL_MON group for a MON group, resulting in all member + * tasks' CLOSID immediately changing to that of the new parent group. + * Monitoring data for the group is unaffected by this operation. + */ +static void mongrp_reparent(struct rdtgroup *rdtgrp, + struct rdtgroup *new_prdtgrp, + cpumask_var_t cpus) +{ + struct rdtgroup *prdtgrp = rdtgrp->mon.parent; + + WARN_ON(rdtgrp->type != RDTMON_GROUP); + WARN_ON(new_prdtgrp->type != RDTCTRL_GROUP); + + /* Nothing to do when simply renaming a MON group. */ + if (prdtgrp == new_prdtgrp) + return; + + WARN_ON(list_empty(&prdtgrp->mon.crdtgrp_list)); + list_move_tail(&rdtgrp->mon.crdtgrp_list, + &new_prdtgrp->mon.crdtgrp_list); + + rdtgrp->mon.parent = new_prdtgrp; + rdtgrp->closid = new_prdtgrp->closid; + + /* Propagate updated closid to all tasks in this group. */ + rdt_move_group_tasks(rdtgrp, rdtgrp, cpus); + + update_closid_rmid(cpus, NULL); +} + +static int rdtgroup_rename(struct kernfs_node *kn, + struct kernfs_node *new_parent, const char *new_name) +{ + struct rdtgroup *new_prdtgrp; + struct rdtgroup *rdtgrp; + cpumask_var_t tmpmask; + int ret; + + rdtgrp = kernfs_to_rdtgroup(kn); + new_prdtgrp = kernfs_to_rdtgroup(new_parent); + if (!rdtgrp || !new_prdtgrp) + return -ENOENT; + + /* Release both kernfs active_refs before obtaining rdtgroup mutex. */ + rdtgroup_kn_get(rdtgrp, kn); + rdtgroup_kn_get(new_prdtgrp, new_parent); + + mutex_lock(&rdtgroup_mutex); + + rdt_last_cmd_clear(); + + /* + * Don't allow kernfs_to_rdtgroup() to return a parent rdtgroup if + * either kernfs_node is a file. + */ + if (kernfs_type(kn) != KERNFS_DIR || + kernfs_type(new_parent) != KERNFS_DIR) { + rdt_last_cmd_puts("Source and destination must be directories"); + ret = -EPERM; + goto out; + } + + if ((rdtgrp->flags & RDT_DELETED) || (new_prdtgrp->flags & RDT_DELETED)) { + ret = -ENOENT; + goto out; + } + + if (rdtgrp->type != RDTMON_GROUP || !kn->parent || + !is_mon_groups(kn->parent, kn->name)) { + rdt_last_cmd_puts("Source must be a MON group\n"); + ret = -EPERM; + goto out; + } + + if (!is_mon_groups(new_parent, new_name)) { + rdt_last_cmd_puts("Destination must be a mon_groups subdirectory\n"); + ret = -EPERM; + goto out; + } + + /* + * If the MON group is monitoring CPUs, the CPUs must be assigned to the + * current parent CTRL_MON group and therefore cannot be assigned to + * the new parent, making the move illegal. + */ + if (!cpumask_empty(&rdtgrp->cpu_mask) && + rdtgrp->mon.parent != new_prdtgrp) { + rdt_last_cmd_puts("Cannot move a MON group that monitors CPUs\n"); + ret = -EPERM; + goto out; + } + + /* + * Allocate the cpumask for use in mongrp_reparent() to avoid the + * possibility of failing to allocate it after kernfs_rename() has + * succeeded. + */ + if (!zalloc_cpumask_var(&tmpmask, GFP_KERNEL)) { + ret = -ENOMEM; + goto out; + } + + /* + * Perform all input validation and allocations needed to ensure + * mongrp_reparent() will succeed before calling kernfs_rename(), + * otherwise it would be necessary to revert this call if + * mongrp_reparent() failed. + */ + ret = kernfs_rename(kn, new_parent, new_name); + if (!ret) + mongrp_reparent(rdtgrp, new_prdtgrp, tmpmask); + + free_cpumask_var(tmpmask); + +out: + mutex_unlock(&rdtgroup_mutex); + rdtgroup_kn_put(rdtgrp, kn); + rdtgroup_kn_put(new_prdtgrp, new_parent); + return ret; +} + static int rdtgroup_show_options(struct seq_file *seq, struct kernfs_root *kf) { if (resctrl_arch_get_cdp_enabled(RDT_RESOURCE_L3)) @@ -3522,6 +3662,7 @@ static int rdtgroup_show_options(struct seq_file *seq, struct kernfs_root *kf) static struct kernfs_syscall_ops rdtgroup_kf_syscall_ops = { .mkdir = rdtgroup_mkdir, .rmdir = rdtgroup_rmdir, + .rename = rdtgroup_rename, .show_options = rdtgroup_show_options, }; diff --git a/arch/x86/kernel/cpu/sgx/encl.c b/arch/x86/kernel/cpu/sgx/encl.c index 2a0e90fe2abce14f049fb3c3eb083e306f4bd94c..91fa70e5100413655b4b99629ad72b2843a4836b 100644 --- a/arch/x86/kernel/cpu/sgx/encl.c +++ b/arch/x86/kernel/cpu/sgx/encl.c @@ -755,6 +755,7 @@ static void sgx_mmu_notifier_release(struct mmu_notifier *mn, { struct sgx_encl_mm *encl_mm = container_of(mn, struct sgx_encl_mm, mmu_notifier); struct sgx_encl_mm *tmp = NULL; + bool found = false; /* * The enclave itself can remove encl_mm. Note, objects can't be moved @@ -764,12 +765,13 @@ static void sgx_mmu_notifier_release(struct mmu_notifier *mn, list_for_each_entry(tmp, &encl_mm->encl->mm_list, list) { if (tmp == encl_mm) { list_del_rcu(&encl_mm->list); + found = true; break; } } spin_unlock(&encl_mm->encl->mm_lock); - if (tmp == encl_mm) { + if (found) { synchronize_srcu(&encl_mm->encl->srcu); mmu_notifier_put(mn); } diff --git a/arch/x86/kernel/cpu/sgx/ioctl.c b/arch/x86/kernel/cpu/sgx/ioctl.c index 21ca0a831b70aef8a70e5c5c707b5c4aad288995..5d390df2144066ef11c439a5d0fb24959c9b3961 100644 --- a/arch/x86/kernel/cpu/sgx/ioctl.c +++ b/arch/x86/kernel/cpu/sgx/ioctl.c @@ -214,7 +214,7 @@ static int __sgx_encl_add_page(struct sgx_encl *encl, if (!(vma->vm_flags & VM_MAYEXEC)) return -EACCES; - ret = get_user_pages(src, 1, 0, &src_page, NULL); + ret = get_user_pages(src, 1, 0, &src_page); if (ret < 1) return -EFAULT; diff --git a/arch/x86/kernel/doublefault_32.c b/arch/x86/kernel/doublefault_32.c index 3b58d8703094f54b078063ff92a0cff405052aab..6eaf9a6bc02fff3a52ca5b2403dc851721cd286c 100644 --- a/arch/x86/kernel/doublefault_32.c +++ b/arch/x86/kernel/doublefault_32.c @@ -9,6 +9,7 @@ #include #include #include +#include #define ptr_ok(x) ((x) > PAGE_OFFSET && (x) < PAGE_OFFSET + MAXMEM) diff --git a/arch/x86/kernel/fpu/init.c b/arch/x86/kernel/fpu/init.c index 851eb13edc014764c2798cf2516038de64fc5f74..998a08f17e3317abde0d01961ebfe5d571681e62 100644 --- a/arch/x86/kernel/fpu/init.c +++ b/arch/x86/kernel/fpu/init.c @@ -53,7 +53,7 @@ void fpu__init_cpu(void) fpu__init_cpu_xstate(); } -static bool fpu__probe_without_cpuid(void) +static bool __init fpu__probe_without_cpuid(void) { unsigned long cr0; u16 fsw, fcw; @@ -71,7 +71,7 @@ static bool fpu__probe_without_cpuid(void) return fsw == 0 && (fcw & 0x103f) == 0x003f; } -static void fpu__init_system_early_generic(struct cpuinfo_x86 *c) +static void __init fpu__init_system_early_generic(void) { if (!boot_cpu_has(X86_FEATURE_CPUID) && !test_bit(X86_FEATURE_FPU, (unsigned long *)cpu_caps_cleared)) { @@ -211,10 +211,10 @@ static void __init fpu__init_system_xstate_size_legacy(void) * Called on the boot CPU once per system bootup, to set up the initial * FPU state that is later cloned into all processes: */ -void __init fpu__init_system(struct cpuinfo_x86 *c) +void __init fpu__init_system(void) { fpstate_reset(¤t->thread.fpu); - fpu__init_system_early_generic(c); + fpu__init_system_early_generic(); /* * The FPU has to be operational for some of the diff --git a/arch/x86/kernel/ftrace.c b/arch/x86/kernel/ftrace.c index 5e7ead52cfdb7ae0e092f1425bf2bcae3a8ba610..12df54ff0e817188d384affee8d98a515d6db471 100644 --- a/arch/x86/kernel/ftrace.c +++ b/arch/x86/kernel/ftrace.c @@ -282,7 +282,6 @@ static inline void tramp_free(void *tramp) { } /* Defined as markers to the end of the ftrace default trampolines */ extern void ftrace_regs_caller_end(void); -extern void ftrace_regs_caller_ret(void); extern void ftrace_caller_end(void); extern void ftrace_caller_op_ptr(void); extern void ftrace_regs_caller_op_ptr(void); @@ -525,9 +524,6 @@ static void *addr_from_call(void *ptr) return ptr + CALL_INSN_SIZE + call.disp; } -void prepare_ftrace_return(unsigned long ip, unsigned long *parent, - unsigned long frame_pointer); - /* * If the ops->trampoline was not allocated, then it probably * has a static trampoline func, or is the ftrace caller itself. diff --git a/arch/x86/kernel/ftrace_32.S b/arch/x86/kernel/ftrace_32.S index 0d9a14528176400f2f6458ac33951c2c2c5394c8..24c1175a47e292ddad72fe1e617ded6174790feb 100644 --- a/arch/x86/kernel/ftrace_32.S +++ b/arch/x86/kernel/ftrace_32.S @@ -187,12 +187,14 @@ SYM_CODE_END(ftrace_graph_caller) .globl return_to_handler return_to_handler: - pushl %eax + pushl $0 pushl %edx - movl $0, %eax + pushl %eax + movl %esp, %eax call ftrace_return_to_handler movl %eax, %ecx - popl %edx popl %eax + popl %edx + addl $4, %esp # skip ebp JMP_NOSPEC ecx #endif diff --git a/arch/x86/kernel/ftrace_64.S b/arch/x86/kernel/ftrace_64.S index b8c720b5dab2c7c770a5c2452b7c2431cfdc96fb..945cfa5f723991cad22449cb1835fa0283455e39 100644 --- a/arch/x86/kernel/ftrace_64.S +++ b/arch/x86/kernel/ftrace_64.S @@ -348,12 +348,13 @@ STACK_FRAME_NON_STANDARD_FP(__fentry__) SYM_CODE_START(return_to_handler) UNWIND_HINT_UNDEFINED ANNOTATE_NOENDBR - subq $16, %rsp + subq $24, %rsp /* Save the return values */ movq %rax, (%rsp) movq %rdx, 8(%rsp) - movq %rbp, %rdi + movq %rbp, 16(%rsp) + movq %rsp, %rdi call ftrace_return_to_handler @@ -361,7 +362,7 @@ SYM_CODE_START(return_to_handler) movq 8(%rsp), %rdx movq (%rsp), %rax - addq $16, %rsp + addq $24, %rsp /* * Jump back to the old return address. This cannot be JMP_NOSPEC rdi * since IBT would demand that contain ENDBR, which simply isn't so for diff --git a/arch/x86/kernel/head32.c b/arch/x86/kernel/head32.c index 10c27b4261eb0b969e6360c9acffe4358ff4adb0..246a609f889b20986fe9b66d2449a81db125aec1 100644 --- a/arch/x86/kernel/head32.c +++ b/arch/x86/kernel/head32.c @@ -69,6 +69,7 @@ asmlinkage __visible void __init __noreturn i386_start_kernel(void) * to the first kernel PMD. Note the upper half of each PMD or PTE are * always zero at this stage. */ +void __init mk_early_pgtbl_32(void); void __init mk_early_pgtbl_32(void) { #ifdef __pa diff --git a/arch/x86/kernel/head_32.S b/arch/x86/kernel/head_32.S index 67c8ed99144b7a55c4e1665992da2a69c3bec445..c9318993f9594562f8518d60d7182d9e1f483f1e 100644 --- a/arch/x86/kernel/head_32.S +++ b/arch/x86/kernel/head_32.S @@ -138,20 +138,6 @@ SYM_CODE_START(startup_32) jmp .Ldefault_entry SYM_CODE_END(startup_32) -#ifdef CONFIG_HOTPLUG_CPU -/* - * Boot CPU0 entry point. It's called from play_dead(). Everything has been set - * up already except stack. We just set up stack here. Then call - * start_secondary(). - */ -SYM_FUNC_START(start_cpu0) - movl initial_stack, %ecx - movl %ecx, %esp - call *(initial_code) -1: jmp 1b -SYM_FUNC_END(start_cpu0) -#endif - /* * Non-boot CPU entry point; entered from trampoline.S * We can't lgdt here, because lgdt itself uses a data segment, but diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S index 113c13376e5125c05212dc1808ff44c9bf9df43c..c5b9289837dcbad26af59a63d47829e211ad3c73 100644 --- a/arch/x86/kernel/head_64.S +++ b/arch/x86/kernel/head_64.S @@ -24,7 +24,9 @@ #include "../entry/calling.h" #include #include +#include #include +#include /* * We are not able to switch in one step to the final KERNEL ADDRESS SPACE @@ -234,8 +236,67 @@ SYM_INNER_LABEL(secondary_startup_64_no_verify, SYM_L_GLOBAL) ANNOTATE_NOENDBR // above #ifdef CONFIG_SMP + /* + * For parallel boot, the APIC ID is read from the APIC, and then + * used to look up the CPU number. For booting a single CPU, the + * CPU number is encoded in smpboot_control. + * + * Bit 31 STARTUP_READ_APICID (Read APICID from APIC) + * Bit 0-23 CPU# if STARTUP_xx flags are not set + */ movl smpboot_control(%rip), %ecx + testl $STARTUP_READ_APICID, %ecx + jnz .Lread_apicid + /* + * No control bit set, single CPU bringup. CPU number is provided + * in bit 0-23. This is also the boot CPU case (CPU number 0). + */ + andl $(~STARTUP_PARALLEL_MASK), %ecx + jmp .Lsetup_cpu +.Lread_apicid: + /* Check whether X2APIC mode is already enabled */ + mov $MSR_IA32_APICBASE, %ecx + rdmsr + testl $X2APIC_ENABLE, %eax + jnz .Lread_apicid_msr + + /* Read the APIC ID from the fix-mapped MMIO space. */ + movq apic_mmio_base(%rip), %rcx + addq $APIC_ID, %rcx + movl (%rcx), %eax + shr $24, %eax + jmp .Llookup_AP + +.Lread_apicid_msr: + mov $APIC_X2APIC_ID_MSR, %ecx + rdmsr + +.Llookup_AP: + /* EAX contains the APIC ID of the current CPU */ + xorq %rcx, %rcx + leaq cpuid_to_apicid(%rip), %rbx + +.Lfind_cpunr: + cmpl (%rbx,%rcx,4), %eax + jz .Lsetup_cpu + inc %ecx +#ifdef CONFIG_FORCE_NR_CPUS + cmpl $NR_CPUS, %ecx +#else + cmpl nr_cpu_ids(%rip), %ecx +#endif + jb .Lfind_cpunr + + /* APIC ID not found in the table. Drop the trampoline lock and bail. */ + movq trampoline_lock(%rip), %rax + movl $0, (%rax) + +1: cli + hlt + jmp 1b + +.Lsetup_cpu: /* Get the per cpu offset for the given CPU# which is in ECX */ movq __per_cpu_offset(,%rcx,8), %rdx #else @@ -251,6 +312,16 @@ SYM_INNER_LABEL(secondary_startup_64_no_verify, SYM_L_GLOBAL) movq pcpu_hot + X86_current_task(%rdx), %rax movq TASK_threadsp(%rax), %rsp + /* + * Now that this CPU is running on its own stack, drop the realmode + * protection. For the boot CPU the pointer is NULL! + */ + movq trampoline_lock(%rip), %rax + testq %rax, %rax + jz .Lsetup_gdt + movl $0, (%rax) + +.Lsetup_gdt: /* * We must switch to a new descriptor in kernel space for the GDT * because soon the kernel won't have access anymore to the userspace @@ -375,13 +446,13 @@ SYM_CODE_END(secondary_startup_64) #include "verify_cpu.S" #include "sev_verify_cbit.S" -#ifdef CONFIG_HOTPLUG_CPU +#if defined(CONFIG_HOTPLUG_CPU) && defined(CONFIG_AMD_MEM_ENCRYPT) /* - * Boot CPU0 entry point. It's called from play_dead(). Everything has been set - * up already except stack. We just set up stack here. Then call - * start_secondary() via .Ljump_to_C_code. + * Entry point for soft restart of a CPU. Invoked from xxx_play_dead() for + * restarting the boot CPU or for restarting SEV guest CPUs after CPU hot + * unplug. Everything is set up already except the stack. */ -SYM_CODE_START(start_cpu0) +SYM_CODE_START(soft_restart_cpu) ANNOTATE_NOENDBR UNWIND_HINT_END_OF_STACK @@ -390,7 +461,7 @@ SYM_CODE_START(start_cpu0) movq TASK_threadsp(%rcx), %rsp jmp .Ljump_to_C_code -SYM_CODE_END(start_cpu0) +SYM_CODE_END(soft_restart_cpu) #endif #ifdef CONFIG_AMD_MEM_ENCRYPT @@ -433,6 +504,8 @@ SYM_DATA(initial_code, .quad x86_64_start_kernel) #ifdef CONFIG_AMD_MEM_ENCRYPT SYM_DATA(initial_vc_handler, .quad handle_vc_boot_ghcb) #endif + +SYM_DATA(trampoline_lock, .quad 0); __FINITDATA __INIT diff --git a/arch/x86/kernel/irq.c b/arch/x86/kernel/irq.c index 766ffe3ba313711fef22b21bee349d2db360fb46..9f668d2f3d11996d4d378b1d8be130bf2e11aef2 100644 --- a/arch/x86/kernel/irq.c +++ b/arch/x86/kernel/irq.c @@ -211,6 +211,13 @@ u64 arch_irq_stat_cpu(unsigned int cpu) #ifdef CONFIG_X86_MCE_THRESHOLD sum += irq_stats(cpu)->irq_threshold_count; #endif +#ifdef CONFIG_X86_HV_CALLBACK_VECTOR + sum += irq_stats(cpu)->irq_hv_callback_count; +#endif +#if IS_ENABLED(CONFIG_HYPERV) + sum += irq_stats(cpu)->irq_hv_reenlightenment_count; + sum += irq_stats(cpu)->hyperv_stimer0_count; +#endif #ifdef CONFIG_X86_MCE sum += per_cpu(mce_exception_count, cpu); sum += per_cpu(mce_poll_count, cpu); diff --git a/arch/x86/kernel/itmt.c b/arch/x86/kernel/itmt.c index 670eb08b972aac3213171a87a4fa98be8fac5c85..ee4fe8cdb857676f3fb69cd14a17aed3c735f8f1 100644 --- a/arch/x86/kernel/itmt.c +++ b/arch/x86/kernel/itmt.c @@ -165,32 +165,19 @@ int arch_asym_cpu_priority(int cpu) /** * sched_set_itmt_core_prio() - Set CPU priority based on ITMT - * @prio: Priority of cpu core - * @core_cpu: The cpu number associated with the core + * @prio: Priority of @cpu + * @cpu: The CPU number * * The pstate driver will find out the max boost frequency * and call this function to set a priority proportional - * to the max boost frequency. CPU with higher boost + * to the max boost frequency. CPUs with higher boost * frequency will receive higher priority. * * No need to rebuild sched domain after updating * the CPU priorities. The sched domains have no * dependency on CPU priorities. */ -void sched_set_itmt_core_prio(int prio, int core_cpu) +void sched_set_itmt_core_prio(int prio, int cpu) { - int cpu, i = 1; - - for_each_cpu(cpu, topology_sibling_cpumask(core_cpu)) { - int smt_prio; - - /* - * Ensure that the siblings are moved to the end - * of the priority chain and only used when - * all other high priority cpus are out of capacity. - */ - smt_prio = prio * smp_num_siblings / (i * i); - per_cpu(sched_core_priority, cpu) = smt_prio; - i++; - } + per_cpu(sched_core_priority, cpu) = prio; } diff --git a/arch/x86/kernel/kvmclock.c b/arch/x86/kernel/kvmclock.c index 0f35d44c56feb6d8cc50b54c8d8470b3b8b56caf..fb8f52149be9adfe127b9550ef738642fbc54caf 100644 --- a/arch/x86/kernel/kvmclock.c +++ b/arch/x86/kernel/kvmclock.c @@ -71,7 +71,7 @@ static int kvm_set_wallclock(const struct timespec64 *now) return -ENODEV; } -static noinstr u64 kvm_clock_read(void) +static u64 kvm_clock_read(void) { u64 ret; @@ -88,7 +88,7 @@ static u64 kvm_clock_get_cycles(struct clocksource *cs) static noinstr u64 kvm_sched_clock_read(void) { - return kvm_clock_read() - kvm_sched_clock_offset; + return pvclock_clocksource_read_nowd(this_cpu_pvti()) - kvm_sched_clock_offset; } static inline void kvm_sched_clock_init(bool stable) diff --git a/arch/x86/kernel/ldt.c b/arch/x86/kernel/ldt.c index 525876e7b9f4a87de0b38806fbad235fbdde7964..adc67f98819aa4a27c07270cf6cf4616a3f079ac 100644 --- a/arch/x86/kernel/ldt.c +++ b/arch/x86/kernel/ldt.c @@ -367,8 +367,10 @@ static void unmap_ldt_struct(struct mm_struct *mm, struct ldt_struct *ldt) va = (unsigned long)ldt_slot_va(ldt->slot) + offset; ptep = get_locked_pte(mm, va, &ptl); - pte_clear(mm, va, ptep); - pte_unmap_unlock(ptep, ptl); + if (!WARN_ON_ONCE(!ptep)) { + pte_clear(mm, va, ptep); + pte_unmap_unlock(ptep, ptl); + } } va = (unsigned long)ldt_slot_va(ldt->slot); diff --git a/arch/x86/kernel/module.c b/arch/x86/kernel/module.c index b05f62ee2344ba6eaf1bc8eab29ebcba3256e0e6..5f71a0cf4399a577e1235f6040a70fb26ee56346 100644 --- a/arch/x86/kernel/module.c +++ b/arch/x86/kernel/module.c @@ -358,7 +358,7 @@ int module_finalize(const Elf_Ehdr *hdr, } if (ibt_endbr) { void *iseg = (void *)ibt_endbr->sh_addr; - apply_ibt_endbr(iseg, iseg + ibt_endbr->sh_size); + apply_seal_endbr(iseg, iseg + ibt_endbr->sh_size); } if (locks) { void *lseg = (void *)locks->sh_addr; diff --git a/arch/x86/kernel/nmi.c b/arch/x86/kernel/nmi.c index 776f4b1e395b5dd30e12af5447031ac9186c58c2..a0c551846b35f17627f2bccdff20ea8b1969c685 100644 --- a/arch/x86/kernel/nmi.c +++ b/arch/x86/kernel/nmi.c @@ -496,7 +496,7 @@ DEFINE_IDTENTRY_RAW(exc_nmi) */ sev_es_nmi_complete(); if (IS_ENABLED(CONFIG_NMI_CHECK_CPU)) - arch_atomic_long_inc(&nsp->idt_calls); + raw_atomic_long_inc(&nsp->idt_calls); if (IS_ENABLED(CONFIG_SMP) && arch_cpu_is_offline(smp_processor_id())) return; diff --git a/arch/x86/kernel/platform-quirks.c b/arch/x86/kernel/platform-quirks.c index b348a672f71d5ecd381822deab84585d35d1afc8..b525fe6d66571232d8029493348de8dbfb320dbe 100644 --- a/arch/x86/kernel/platform-quirks.c +++ b/arch/x86/kernel/platform-quirks.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 #include #include +#include #include #include diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c index dac41a0072ea1ffea2c9bb4411f1fb2dc4f98ed6..72015dba72ab4c09fc750e8a66a40adfbf043b4e 100644 --- a/arch/x86/kernel/process.c +++ b/arch/x86/kernel/process.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -134,6 +135,25 @@ static int set_new_tls(struct task_struct *p, unsigned long tls) return do_set_thread_area_64(p, ARCH_SET_FS, tls); } +__visible void ret_from_fork(struct task_struct *prev, struct pt_regs *regs, + int (*fn)(void *), void *fn_arg) +{ + schedule_tail(prev); + + /* Is this a kernel thread? */ + if (unlikely(fn)) { + fn(fn_arg); + /* + * A kernel thread is allowed to return here after successfully + * calling kernel_execve(). Exit to userspace to complete the + * execve() syscall. + */ + regs->ax = 0; + } + + syscall_exit_to_user_mode(regs); +} + int copy_thread(struct task_struct *p, const struct kernel_clone_args *args) { unsigned long clone_flags = args->flags; @@ -149,7 +169,7 @@ int copy_thread(struct task_struct *p, const struct kernel_clone_args *args) frame = &fork_frame->frame; frame->bp = encode_frame_pointer(childregs); - frame->ret_addr = (unsigned long) ret_from_fork; + frame->ret_addr = (unsigned long) ret_from_fork_asm; p->thread.sp = (unsigned long) fork_frame; p->thread.io_bitmap = NULL; p->thread.iopl_warn = 0; @@ -759,15 +779,26 @@ bool xen_set_default_idle(void) } #endif +struct cpumask cpus_stop_mask; + void __noreturn stop_this_cpu(void *dummy) { + struct cpuinfo_x86 *c = this_cpu_ptr(&cpu_info); + unsigned int cpu = smp_processor_id(); + local_irq_disable(); + /* - * Remove this CPU: + * Remove this CPU from the online mask and disable it + * unconditionally. This might be redundant in case that the reboot + * vector was handled late and stop_other_cpus() sent an NMI. + * + * According to SDM and APM NMIs can be accepted even after soft + * disabling the local APIC. */ - set_cpu_online(smp_processor_id(), false); + set_cpu_online(cpu, false); disable_local_APIC(); - mcheck_cpu_clear(this_cpu_ptr(&cpu_info)); + mcheck_cpu_clear(c); /* * Use wbinvd on processors that support SME. This provides support @@ -781,8 +812,17 @@ void __noreturn stop_this_cpu(void *dummy) * Test the CPUID bit directly because the machine might've cleared * X86_FEATURE_SME due to cmdline options. */ - if (cpuid_eax(0x8000001f) & BIT(0)) + if (c->extended_cpuid_level >= 0x8000001f && (cpuid_eax(0x8000001f) & BIT(0))) native_wbinvd(); + + /* + * This brings a cache line back and dirties it, but + * native_stop_other_cpus() will overwrite cpus_stop_mask after it + * observed that all CPUs reported stop. This write will invalidate + * the related cache line on this CPU. + */ + cpumask_clear_cpu(cpu, &cpus_stop_mask); + for (;;) { /* * Use native_halt() so that memory contents don't change diff --git a/arch/x86/kernel/pvclock.c b/arch/x86/kernel/pvclock.c index 56acf53a782ad8e1b4193b5bdf33063a91ba0bcf..b3f81379c2fc06fd127728ea6ca6db65d5a7b34a 100644 --- a/arch/x86/kernel/pvclock.c +++ b/arch/x86/kernel/pvclock.c @@ -101,11 +101,11 @@ u64 __pvclock_clocksource_read(struct pvclock_vcpu_time_info *src, bool dowd) * updating at the same time, and one of them could be slightly behind, * making the assumption that last_value always go forward fail to hold. */ - last = arch_atomic64_read(&last_value); + last = raw_atomic64_read(&last_value); do { if (ret <= last) return last; - } while (!arch_atomic64_try_cmpxchg(&last_value, &last, ret)); + } while (!raw_atomic64_try_cmpxchg(&last_value, &last, ret)); return ret; } diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 16babff771bdf2d38288c8e9339cf044060b3abf..fd975a4a52006687a152ec6f84caa2a59cab595c 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -796,7 +796,6 @@ static void __init early_reserve_memory(void) memblock_x86_reserve_range_setup_data(); - reserve_ibft_region(); reserve_bios_regions(); trim_snb_memory(); } @@ -1032,11 +1031,14 @@ void __init setup_arch(char **cmdline_p) if (efi_enabled(EFI_BOOT)) efi_init(); + reserve_ibft_region(); dmi_setup(); /* * VMware detection requires dmi to be available, so this * needs to be done after dmi_setup(), for the boot CPU. + * For some guest types (Xen PV, SEV-SNP, TDX) it is required to be + * called before cache_bp_init() for setting up MTRR state. */ init_hypervisor_platform(); diff --git a/arch/x86/kernel/sev-shared.c b/arch/x86/kernel/sev-shared.c index 3a5b0c9c4fccc2b3cb861f4774eaa80ff6f1418d..2eabccde94fb31b77b738e4b32d614fd35b5b5c8 100644 --- a/arch/x86/kernel/sev-shared.c +++ b/arch/x86/kernel/sev-shared.c @@ -12,6 +12,9 @@ #ifndef __BOOT_COMPRESSED #define error(v) pr_err(v) #define has_cpuflag(f) boot_cpu_has(f) +#else +#undef WARN +#define WARN(condition, format...) (!!(condition)) #endif /* I/O parameters for CPUID-related helpers */ @@ -991,3 +994,103 @@ static void __init setup_cpuid_table(const struct cc_blob_sev_info *cc_info) cpuid_ext_range_max = fn->eax; } } + +static void pvalidate_pages(struct snp_psc_desc *desc) +{ + struct psc_entry *e; + unsigned long vaddr; + unsigned int size; + unsigned int i; + bool validate; + int rc; + + for (i = 0; i <= desc->hdr.end_entry; i++) { + e = &desc->entries[i]; + + vaddr = (unsigned long)pfn_to_kaddr(e->gfn); + size = e->pagesize ? RMP_PG_SIZE_2M : RMP_PG_SIZE_4K; + validate = e->operation == SNP_PAGE_STATE_PRIVATE; + + rc = pvalidate(vaddr, size, validate); + if (rc == PVALIDATE_FAIL_SIZEMISMATCH && size == RMP_PG_SIZE_2M) { + unsigned long vaddr_end = vaddr + PMD_SIZE; + + for (; vaddr < vaddr_end; vaddr += PAGE_SIZE) { + rc = pvalidate(vaddr, RMP_PG_SIZE_4K, validate); + if (rc) + break; + } + } + + if (rc) { + WARN(1, "Failed to validate address 0x%lx ret %d", vaddr, rc); + sev_es_terminate(SEV_TERM_SET_LINUX, GHCB_TERM_PVALIDATE); + } + } +} + +static int vmgexit_psc(struct ghcb *ghcb, struct snp_psc_desc *desc) +{ + int cur_entry, end_entry, ret = 0; + struct snp_psc_desc *data; + struct es_em_ctxt ctxt; + + vc_ghcb_invalidate(ghcb); + + /* Copy the input desc into GHCB shared buffer */ + data = (struct snp_psc_desc *)ghcb->shared_buffer; + memcpy(ghcb->shared_buffer, desc, min_t(int, GHCB_SHARED_BUF_SIZE, sizeof(*desc))); + + /* + * As per the GHCB specification, the hypervisor can resume the guest + * before processing all the entries. Check whether all the entries + * are processed. If not, then keep retrying. Note, the hypervisor + * will update the data memory directly to indicate the status, so + * reference the data->hdr everywhere. + * + * The strategy here is to wait for the hypervisor to change the page + * state in the RMP table before guest accesses the memory pages. If the + * page state change was not successful, then later memory access will + * result in a crash. + */ + cur_entry = data->hdr.cur_entry; + end_entry = data->hdr.end_entry; + + while (data->hdr.cur_entry <= data->hdr.end_entry) { + ghcb_set_sw_scratch(ghcb, (u64)__pa(data)); + + /* This will advance the shared buffer data points to. */ + ret = sev_es_ghcb_hv_call(ghcb, &ctxt, SVM_VMGEXIT_PSC, 0, 0); + + /* + * Page State Change VMGEXIT can pass error code through + * exit_info_2. + */ + if (WARN(ret || ghcb->save.sw_exit_info_2, + "SNP: PSC failed ret=%d exit_info_2=%llx\n", + ret, ghcb->save.sw_exit_info_2)) { + ret = 1; + goto out; + } + + /* Verify that reserved bit is not set */ + if (WARN(data->hdr.reserved, "Reserved bit is set in the PSC header\n")) { + ret = 1; + goto out; + } + + /* + * Sanity check that entry processing is not going backwards. + * This will happen only if hypervisor is tricking us. + */ + if (WARN(data->hdr.end_entry > end_entry || cur_entry > data->hdr.cur_entry, +"SNP: PSC processing going backward, end_entry %d (got %d) cur_entry %d (got %d)\n", + end_entry, data->hdr.end_entry, cur_entry, data->hdr.cur_entry)) { + ret = 1; + goto out; + } + } + +out: + return ret; +} diff --git a/arch/x86/kernel/sev.c b/arch/x86/kernel/sev.c index b031244d6d2df4cfb5e508c28eaf8d15d580b69a..1ee7bed453ded5df0d50469b6f75fbd7ca1ed189 100644 --- a/arch/x86/kernel/sev.c +++ b/arch/x86/kernel/sev.c @@ -113,13 +113,23 @@ struct ghcb_state { }; static DEFINE_PER_CPU(struct sev_es_runtime_data*, runtime_data); -DEFINE_STATIC_KEY_FALSE(sev_es_enable_key); - static DEFINE_PER_CPU(struct sev_es_save_area *, sev_vmsa); struct sev_config { __u64 debug : 1, - __reserved : 63; + + /* + * A flag used by __set_pages_state() that indicates when the + * per-CPU GHCB has been created and registered and thus can be + * used by the BSP instead of the early boot GHCB. + * + * For APs, the per-CPU GHCB is created before they are started + * and registered upon startup, so this flag can be used globally + * for the BSP and APs. + */ + ghcbs_initialized : 1, + + __reserved : 62; }; static struct sev_config sev_cfg __read_mostly; @@ -645,32 +655,26 @@ static u64 __init get_jump_table_addr(void) return ret; } -static void pvalidate_pages(unsigned long vaddr, unsigned int npages, bool validate) -{ - unsigned long vaddr_end; - int rc; - - vaddr = vaddr & PAGE_MASK; - vaddr_end = vaddr + (npages << PAGE_SHIFT); - - while (vaddr < vaddr_end) { - rc = pvalidate(vaddr, RMP_PG_SIZE_4K, validate); - if (WARN(rc, "Failed to validate address 0x%lx ret %d", vaddr, rc)) - sev_es_terminate(SEV_TERM_SET_LINUX, GHCB_TERM_PVALIDATE); - - vaddr = vaddr + PAGE_SIZE; - } -} - -static void __init early_set_pages_state(unsigned long paddr, unsigned int npages, enum psc_op op) +static void early_set_pages_state(unsigned long vaddr, unsigned long paddr, + unsigned long npages, enum psc_op op) { unsigned long paddr_end; u64 val; + int ret; + + vaddr = vaddr & PAGE_MASK; paddr = paddr & PAGE_MASK; paddr_end = paddr + (npages << PAGE_SHIFT); while (paddr < paddr_end) { + if (op == SNP_PAGE_STATE_SHARED) { + /* Page validation must be rescinded before changing to shared */ + ret = pvalidate(vaddr, RMP_PG_SIZE_4K, false); + if (WARN(ret, "Failed to validate address 0x%lx ret %d", paddr, ret)) + goto e_term; + } + /* * Use the MSR protocol because this function can be called before * the GHCB is established. @@ -691,7 +695,15 @@ static void __init early_set_pages_state(unsigned long paddr, unsigned int npage paddr, GHCB_MSR_PSC_RESP_VAL(val))) goto e_term; - paddr = paddr + PAGE_SIZE; + if (op == SNP_PAGE_STATE_PRIVATE) { + /* Page validation must be performed after changing to private */ + ret = pvalidate(vaddr, RMP_PG_SIZE_4K, true); + if (WARN(ret, "Failed to validate address 0x%lx ret %d", paddr, ret)) + goto e_term; + } + + vaddr += PAGE_SIZE; + paddr += PAGE_SIZE; } return; @@ -701,7 +713,7 @@ static void __init early_set_pages_state(unsigned long paddr, unsigned int npage } void __init early_snp_set_memory_private(unsigned long vaddr, unsigned long paddr, - unsigned int npages) + unsigned long npages) { /* * This can be invoked in early boot while running identity mapped, so @@ -716,14 +728,11 @@ void __init early_snp_set_memory_private(unsigned long vaddr, unsigned long padd * Ask the hypervisor to mark the memory pages as private in the RMP * table. */ - early_set_pages_state(paddr, npages, SNP_PAGE_STATE_PRIVATE); - - /* Validate the memory pages after they've been added in the RMP table. */ - pvalidate_pages(vaddr, npages, true); + early_set_pages_state(vaddr, paddr, npages, SNP_PAGE_STATE_PRIVATE); } void __init early_snp_set_memory_shared(unsigned long vaddr, unsigned long paddr, - unsigned int npages) + unsigned long npages) { /* * This can be invoked in early boot while running identity mapped, so @@ -734,11 +743,8 @@ void __init early_snp_set_memory_shared(unsigned long vaddr, unsigned long paddr if (!(sev_status & MSR_AMD64_SEV_SNP_ENABLED)) return; - /* Invalidate the memory pages before they are marked shared in the RMP table. */ - pvalidate_pages(vaddr, npages, false); - /* Ask hypervisor to mark the memory pages shared in the RMP table. */ - early_set_pages_state(paddr, npages, SNP_PAGE_STATE_SHARED); + early_set_pages_state(vaddr, paddr, npages, SNP_PAGE_STATE_SHARED); } void __init snp_prep_memory(unsigned long paddr, unsigned int sz, enum psc_op op) @@ -756,96 +762,16 @@ void __init snp_prep_memory(unsigned long paddr, unsigned int sz, enum psc_op op WARN(1, "invalid memory op %d\n", op); } -static int vmgexit_psc(struct snp_psc_desc *desc) +static unsigned long __set_pages_state(struct snp_psc_desc *data, unsigned long vaddr, + unsigned long vaddr_end, int op) { - int cur_entry, end_entry, ret = 0; - struct snp_psc_desc *data; struct ghcb_state state; - struct es_em_ctxt ctxt; - unsigned long flags; - struct ghcb *ghcb; - - /* - * __sev_get_ghcb() needs to run with IRQs disabled because it is using - * a per-CPU GHCB. - */ - local_irq_save(flags); - - ghcb = __sev_get_ghcb(&state); - if (!ghcb) { - ret = 1; - goto out_unlock; - } - - /* Copy the input desc into GHCB shared buffer */ - data = (struct snp_psc_desc *)ghcb->shared_buffer; - memcpy(ghcb->shared_buffer, desc, min_t(int, GHCB_SHARED_BUF_SIZE, sizeof(*desc))); - - /* - * As per the GHCB specification, the hypervisor can resume the guest - * before processing all the entries. Check whether all the entries - * are processed. If not, then keep retrying. Note, the hypervisor - * will update the data memory directly to indicate the status, so - * reference the data->hdr everywhere. - * - * The strategy here is to wait for the hypervisor to change the page - * state in the RMP table before guest accesses the memory pages. If the - * page state change was not successful, then later memory access will - * result in a crash. - */ - cur_entry = data->hdr.cur_entry; - end_entry = data->hdr.end_entry; - - while (data->hdr.cur_entry <= data->hdr.end_entry) { - ghcb_set_sw_scratch(ghcb, (u64)__pa(data)); - - /* This will advance the shared buffer data points to. */ - ret = sev_es_ghcb_hv_call(ghcb, &ctxt, SVM_VMGEXIT_PSC, 0, 0); - - /* - * Page State Change VMGEXIT can pass error code through - * exit_info_2. - */ - if (WARN(ret || ghcb->save.sw_exit_info_2, - "SNP: PSC failed ret=%d exit_info_2=%llx\n", - ret, ghcb->save.sw_exit_info_2)) { - ret = 1; - goto out; - } - - /* Verify that reserved bit is not set */ - if (WARN(data->hdr.reserved, "Reserved bit is set in the PSC header\n")) { - ret = 1; - goto out; - } - - /* - * Sanity check that entry processing is not going backwards. - * This will happen only if hypervisor is tricking us. - */ - if (WARN(data->hdr.end_entry > end_entry || cur_entry > data->hdr.cur_entry, -"SNP: PSC processing going backward, end_entry %d (got %d) cur_entry %d (got %d)\n", - end_entry, data->hdr.end_entry, cur_entry, data->hdr.cur_entry)) { - ret = 1; - goto out; - } - } - -out: - __sev_put_ghcb(&state); - -out_unlock: - local_irq_restore(flags); - - return ret; -} - -static void __set_pages_state(struct snp_psc_desc *data, unsigned long vaddr, - unsigned long vaddr_end, int op) -{ + bool use_large_entry; struct psc_hdr *hdr; struct psc_entry *e; + unsigned long flags; unsigned long pfn; + struct ghcb *ghcb; int i; hdr = &data->hdr; @@ -854,74 +780,104 @@ static void __set_pages_state(struct snp_psc_desc *data, unsigned long vaddr, memset(data, 0, sizeof(*data)); i = 0; - while (vaddr < vaddr_end) { - if (is_vmalloc_addr((void *)vaddr)) + while (vaddr < vaddr_end && i < ARRAY_SIZE(data->entries)) { + hdr->end_entry = i; + + if (is_vmalloc_addr((void *)vaddr)) { pfn = vmalloc_to_pfn((void *)vaddr); - else + use_large_entry = false; + } else { pfn = __pa(vaddr) >> PAGE_SHIFT; + use_large_entry = true; + } e->gfn = pfn; e->operation = op; - hdr->end_entry = i; - /* - * Current SNP implementation doesn't keep track of the RMP page - * size so use 4K for simplicity. - */ - e->pagesize = RMP_PG_SIZE_4K; + if (use_large_entry && IS_ALIGNED(vaddr, PMD_SIZE) && + (vaddr_end - vaddr) >= PMD_SIZE) { + e->pagesize = RMP_PG_SIZE_2M; + vaddr += PMD_SIZE; + } else { + e->pagesize = RMP_PG_SIZE_4K; + vaddr += PAGE_SIZE; + } - vaddr = vaddr + PAGE_SIZE; e++; i++; } - if (vmgexit_psc(data)) + /* Page validation must be rescinded before changing to shared */ + if (op == SNP_PAGE_STATE_SHARED) + pvalidate_pages(data); + + local_irq_save(flags); + + if (sev_cfg.ghcbs_initialized) + ghcb = __sev_get_ghcb(&state); + else + ghcb = boot_ghcb; + + /* Invoke the hypervisor to perform the page state changes */ + if (!ghcb || vmgexit_psc(ghcb, data)) sev_es_terminate(SEV_TERM_SET_LINUX, GHCB_TERM_PSC); + + if (sev_cfg.ghcbs_initialized) + __sev_put_ghcb(&state); + + local_irq_restore(flags); + + /* Page validation must be performed after changing to private */ + if (op == SNP_PAGE_STATE_PRIVATE) + pvalidate_pages(data); + + return vaddr; } -static void set_pages_state(unsigned long vaddr, unsigned int npages, int op) +static void set_pages_state(unsigned long vaddr, unsigned long npages, int op) { - unsigned long vaddr_end, next_vaddr; - struct snp_psc_desc *desc; + struct snp_psc_desc desc; + unsigned long vaddr_end; - desc = kmalloc(sizeof(*desc), GFP_KERNEL_ACCOUNT); - if (!desc) - panic("SNP: failed to allocate memory for PSC descriptor\n"); + /* Use the MSR protocol when a GHCB is not available. */ + if (!boot_ghcb) + return early_set_pages_state(vaddr, __pa(vaddr), npages, op); vaddr = vaddr & PAGE_MASK; vaddr_end = vaddr + (npages << PAGE_SHIFT); - while (vaddr < vaddr_end) { - /* Calculate the last vaddr that fits in one struct snp_psc_desc. */ - next_vaddr = min_t(unsigned long, vaddr_end, - (VMGEXIT_PSC_MAX_ENTRY * PAGE_SIZE) + vaddr); - - __set_pages_state(desc, vaddr, next_vaddr, op); - - vaddr = next_vaddr; - } - - kfree(desc); + while (vaddr < vaddr_end) + vaddr = __set_pages_state(&desc, vaddr, vaddr_end, op); } -void snp_set_memory_shared(unsigned long vaddr, unsigned int npages) +void snp_set_memory_shared(unsigned long vaddr, unsigned long npages) { if (!cc_platform_has(CC_ATTR_GUEST_SEV_SNP)) return; - pvalidate_pages(vaddr, npages, false); - set_pages_state(vaddr, npages, SNP_PAGE_STATE_SHARED); } -void snp_set_memory_private(unsigned long vaddr, unsigned int npages) +void snp_set_memory_private(unsigned long vaddr, unsigned long npages) { if (!cc_platform_has(CC_ATTR_GUEST_SEV_SNP)) return; set_pages_state(vaddr, npages, SNP_PAGE_STATE_PRIVATE); +} + +void snp_accept_memory(phys_addr_t start, phys_addr_t end) +{ + unsigned long vaddr; + unsigned int npages; + + if (!cc_platform_has(CC_ATTR_GUEST_SEV_SNP)) + return; + + vaddr = (unsigned long)__va(start); + npages = (end - start) >> PAGE_SHIFT; - pvalidate_pages(vaddr, npages, true); + set_pages_state(vaddr, npages, SNP_PAGE_STATE_PRIVATE); } static int snp_set_vmsa(void *va, bool vmsa) @@ -1267,6 +1223,8 @@ void setup_ghcb(void) if (cc_platform_has(CC_ATTR_GUEST_SEV_SNP)) snp_register_per_cpu_ghcb(); + sev_cfg.ghcbs_initialized = true; + return; } @@ -1328,7 +1286,7 @@ static void sev_es_play_dead(void) * If we get here, the VCPU was woken up again. Jump to CPU * startup code to get it back online. */ - start_cpu0(); + soft_restart_cpu(); } #else /* CONFIG_HOTPLUG_CPU */ #define sev_es_play_dead native_play_dead @@ -1395,9 +1353,6 @@ void __init sev_es_init_vc_handling(void) sev_es_terminate(SEV_TERM_SET_GEN, GHCB_SNP_UNSUPPORTED); } - /* Enable SEV-ES special handling */ - static_branch_enable(&sev_es_enable_key); - /* Initialize per-cpu GHCB pages */ for_each_possible_cpu(cpu) { alloc_runtime_data(cpu); diff --git a/arch/x86/kernel/signal.c b/arch/x86/kernel/signal.c index 004cb30b74198faf3456b8db84c2a717ba8914dc..cfeec3ee877ebb9c4779a3ce9fe77ab172f685d4 100644 --- a/arch/x86/kernel/signal.c +++ b/arch/x86/kernel/signal.c @@ -182,7 +182,7 @@ get_sigframe(struct ksignal *ksig, struct pt_regs *regs, size_t frame_size, static unsigned long __ro_after_init max_frame_size; static unsigned int __ro_after_init fpu_default_state_size; -void __init init_sigframe_size(void) +static int __init init_sigframe_size(void) { fpu_default_state_size = fpu__get_fpstate_size(); @@ -194,7 +194,9 @@ void __init init_sigframe_size(void) max_frame_size = round_up(max_frame_size, FRAME_ALIGNMENT); pr_info("max sigframe size: %lu\n", max_frame_size); + return 0; } +early_initcall(init_sigframe_size); unsigned long get_sigframe_size(void) { diff --git a/arch/x86/kernel/smp.c b/arch/x86/kernel/smp.c index 375b33ecafa27ac425486e9cddf79e77ddc20f34..7eb18ca7bd45beea76839871edce64a5fba69b2b 100644 --- a/arch/x86/kernel/smp.c +++ b/arch/x86/kernel/smp.c @@ -21,12 +21,14 @@ #include #include #include +#include #include #include #include #include #include +#include #include #include #include @@ -129,7 +131,7 @@ static int smp_stop_nmi_callback(unsigned int val, struct pt_regs *regs) } /* - * this function calls the 'stop' function on all other CPUs in the system. + * Disable virtualization, APIC etc. and park the CPU in a HLT loop */ DEFINE_IDTENTRY_SYSVEC(sysvec_reboot) { @@ -146,61 +148,96 @@ static int register_stop_handler(void) static void native_stop_other_cpus(int wait) { - unsigned long flags; - unsigned long timeout; + unsigned int cpu = smp_processor_id(); + unsigned long flags, timeout; if (reboot_force) return; - /* - * Use an own vector here because smp_call_function - * does lots of things not suitable in a panic situation. - */ + /* Only proceed if this is the first CPU to reach this code */ + if (atomic_cmpxchg(&stopping_cpu, -1, cpu) != -1) + return; + + /* For kexec, ensure that offline CPUs are out of MWAIT and in HLT */ + if (kexec_in_progress) + smp_kick_mwait_play_dead(); /* - * We start by using the REBOOT_VECTOR irq. - * The irq is treated as a sync point to allow critical - * regions of code on other cpus to release their spin locks - * and re-enable irqs. Jumping straight to an NMI might - * accidentally cause deadlocks with further shutdown/panic - * code. By syncing, we give the cpus up to one second to - * finish their work before we force them off with the NMI. + * 1) Send an IPI on the reboot vector to all other CPUs. + * + * The other CPUs should react on it after leaving critical + * sections and re-enabling interrupts. They might still hold + * locks, but there is nothing which can be done about that. + * + * 2) Wait for all other CPUs to report that they reached the + * HLT loop in stop_this_cpu() + * + * 3) If the system uses INIT/STARTUP for CPU bringup, then + * send all present CPUs an INIT vector, which brings them + * completely out of the way. + * + * 4) If #3 is not possible and #2 timed out send an NMI to the + * CPUs which did not yet report + * + * 5) Wait for all other CPUs to report that they reached the + * HLT loop in stop_this_cpu() + * + * #4 can obviously race against a CPU reaching the HLT loop late. + * That CPU will have reported already and the "have all CPUs + * reached HLT" condition will be true despite the fact that the + * other CPU is still handling the NMI. Again, there is no + * protection against that as "disabled" APICs still respond to + * NMIs. */ - if (num_online_cpus() > 1) { - /* did someone beat us here? */ - if (atomic_cmpxchg(&stopping_cpu, -1, safe_smp_processor_id()) != -1) - return; - - /* sync above data before sending IRQ */ - wmb(); + cpumask_copy(&cpus_stop_mask, cpu_online_mask); + cpumask_clear_cpu(cpu, &cpus_stop_mask); + if (!cpumask_empty(&cpus_stop_mask)) { apic_send_IPI_allbutself(REBOOT_VECTOR); /* * Don't wait longer than a second for IPI completion. The * wait request is not checked here because that would - * prevent an NMI shutdown attempt in case that not all + * prevent an NMI/INIT shutdown in case that not all * CPUs reach shutdown state. */ timeout = USEC_PER_SEC; - while (num_online_cpus() > 1 && timeout--) + while (!cpumask_empty(&cpus_stop_mask) && timeout--) udelay(1); } - /* if the REBOOT_VECTOR didn't work, try with the NMI */ - if (num_online_cpus() > 1) { + /* + * Park all other CPUs in INIT including "offline" CPUs, if + * possible. That's a safe place where they can't resume execution + * of HLT and then execute the HLT loop from overwritten text or + * page tables. + * + * The only downside is a broadcast MCE, but up to the point where + * the kexec() kernel brought all APs online again an MCE will just + * make HLT resume and handle the MCE. The machine crashes and burns + * due to overwritten text, page tables and data. So there is a + * choice between fire and frying pan. The result is pretty much + * the same. Chose frying pan until x86 provides a sane mechanism + * to park a CPU. + */ + if (smp_park_other_cpus_in_init()) + goto done; + + /* + * If park with INIT was not possible and the REBOOT_VECTOR didn't + * take all secondary CPUs offline, try with the NMI. + */ + if (!cpumask_empty(&cpus_stop_mask)) { /* * If NMI IPI is enabled, try to register the stop handler * and send the IPI. In any case try to wait for the other * CPUs to stop. */ if (!smp_no_nmi_ipi && !register_stop_handler()) { - /* Sync above data before sending IRQ */ - wmb(); - pr_emerg("Shutting down cpus with NMI\n"); - apic_send_IPI_allbutself(NMI_VECTOR); + for_each_cpu(cpu, &cpus_stop_mask) + apic->send_IPI(cpu, NMI_VECTOR); } /* * Don't wait longer than 10 ms if the caller didn't @@ -208,14 +245,21 @@ static void native_stop_other_cpus(int wait) * one or more CPUs do not reach shutdown state. */ timeout = USEC_PER_MSEC * 10; - while (num_online_cpus() > 1 && (wait || timeout--)) + while (!cpumask_empty(&cpus_stop_mask) && (wait || timeout--)) udelay(1); } +done: local_irq_save(flags); disable_local_APIC(); mcheck_cpu_clear(this_cpu_ptr(&cpu_info)); local_irq_restore(flags); + + /* + * Ensure that the cpus_stop_mask cache lines are invalidated on + * the other CPUs. See comment vs. SME in stop_this_cpu(). + */ + cpumask_clear(&cpus_stop_mask); } /* @@ -268,8 +312,7 @@ struct smp_ops smp_ops = { #endif .smp_send_reschedule = native_smp_send_reschedule, - .cpu_up = native_cpu_up, - .cpu_die = native_cpu_die, + .kick_ap_alive = native_kick_ap, .cpu_disable = native_cpu_disable, .play_dead = native_play_dead, diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 352f0ce1ece42911271023391f1848df5a7b657c..e1aa2cd7734ba40825f83ecfe01e25fd41b8e5a4 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -53,10 +53,13 @@ #include #include #include +#include #include #include #include #include +#include +#include #include #include @@ -74,7 +77,7 @@ #include #include #include -#include +#include #include #include #include @@ -101,6 +104,26 @@ EXPORT_PER_CPU_SYMBOL(cpu_die_map); DEFINE_PER_CPU_READ_MOSTLY(struct cpuinfo_x86, cpu_info); EXPORT_PER_CPU_SYMBOL(cpu_info); +/* CPUs which are the primary SMT threads */ +struct cpumask __cpu_primary_thread_mask __read_mostly; + +/* Representing CPUs for which sibling maps can be computed */ +static cpumask_var_t cpu_sibling_setup_mask; + +struct mwait_cpu_dead { + unsigned int control; + unsigned int status; +}; + +#define CPUDEAD_MWAIT_WAIT 0xDEADBEEF +#define CPUDEAD_MWAIT_KEXEC_HLT 0x4A17DEAD + +/* + * Cache line aligned data for mwait_play_dead(). Separate on purpose so + * that it's unlikely to be touched by other CPUs. + */ +static DEFINE_PER_CPU_ALIGNED(struct mwait_cpu_dead, mwait_cpu_dead); + /* Logical package management. We might want to allocate that dynamically */ unsigned int __max_logical_packages __read_mostly; EXPORT_SYMBOL(__max_logical_packages); @@ -121,7 +144,6 @@ int arch_update_cpu_topology(void) return retval; } - static unsigned int smpboot_warm_reset_vector_count; static inline void smpboot_setup_warm_reset_vector(unsigned long start_eip) @@ -154,66 +176,63 @@ static inline void smpboot_restore_warm_reset_vector(void) } -/* - * Report back to the Boot Processor during boot time or to the caller processor - * during CPU online. - */ -static void smp_callin(void) +/* Run the next set of setup steps for the upcoming CPU */ +static void ap_starting(void) { - int cpuid; + int cpuid = smp_processor_id(); - /* - * If waken up by an INIT in an 82489DX configuration - * cpu_callout_mask guarantees we don't get here before - * an INIT_deassert IPI reaches our local APIC, so it is - * now safe to touch our local APIC. - */ - cpuid = smp_processor_id(); + /* Mop up eventual mwait_play_dead() wreckage */ + this_cpu_write(mwait_cpu_dead.status, 0); + this_cpu_write(mwait_cpu_dead.control, 0); /* - * the boot CPU has finished the init stage and is spinning - * on callin_map until we finish. We are free to set up this - * CPU, first the APIC. (this is probably redundant on most - * boards) + * If woken up by an INIT in an 82489DX configuration the alive + * synchronization guarantees that the CPU does not reach this + * point before an INIT_deassert IPI reaches the local APIC, so it + * is now safe to touch the local APIC. + * + * Set up this CPU, first the APIC, which is probably redundant on + * most boards. */ apic_ap_setup(); - /* - * Save our processor parameters. Note: this information - * is needed for clock calibration. - */ + /* Save the processor parameters. */ smp_store_cpu_info(cpuid); /* * The topology information must be up to date before - * calibrate_delay() and notify_cpu_starting(). + * notify_cpu_starting(). */ - set_cpu_sibling_map(raw_smp_processor_id()); + set_cpu_sibling_map(cpuid); ap_init_aperfmperf(); - /* - * Get our bogomips. - * Update loops_per_jiffy in cpu_data. Previous call to - * smp_store_cpu_info() stored a value that is close but not as - * accurate as the value just calculated. - */ - calibrate_delay(); - cpu_data(cpuid).loops_per_jiffy = loops_per_jiffy; pr_debug("Stack at about %p\n", &cpuid); wmb(); + /* + * This runs the AP through all the cpuhp states to its target + * state CPUHP_ONLINE. + */ notify_cpu_starting(cpuid); +} +static void ap_calibrate_delay(void) +{ /* - * Allow the master to continue. + * Calibrate the delay loop and update loops_per_jiffy in cpu_data. + * smp_store_cpu_info() stored a value that is close but not as + * accurate as the value just calculated. + * + * As this is invoked after the TSC synchronization check, + * calibrate_delay_is_known() will skip the calibration routine + * when TSC is synchronized across sockets. */ - cpumask_set_cpu(cpuid, cpu_callin_mask); + calibrate_delay(); + cpu_data(smp_processor_id()).loops_per_jiffy = loops_per_jiffy; } -static int cpu0_logical_apicid; -static int enable_start_cpu0; /* * Activate a secondary processor. */ @@ -226,24 +245,63 @@ static void notrace start_secondary(void *unused) */ cr4_init(); -#ifdef CONFIG_X86_32 - /* switch away from the initial page table */ - load_cr3(swapper_pg_dir); - __flush_tlb_all(); -#endif - cpu_init_secondary(); + /* + * 32-bit specific. 64-bit reaches this code with the correct page + * table established. Yet another historical divergence. + */ + if (IS_ENABLED(CONFIG_X86_32)) { + /* switch away from the initial page table */ + load_cr3(swapper_pg_dir); + __flush_tlb_all(); + } + + cpu_init_exception_handling(); + + /* + * 32-bit systems load the microcode from the ASM startup code for + * historical reasons. + * + * On 64-bit systems load it before reaching the AP alive + * synchronization point below so it is not part of the full per + * CPU serialized bringup part when "parallel" bringup is enabled. + * + * That's even safe when hyperthreading is enabled in the CPU as + * the core code starts the primary threads first and leaves the + * secondary threads waiting for SIPI. Loading microcode on + * physical cores concurrently is a safe operation. + * + * This covers both the Intel specific issue that concurrent + * microcode loading on SMT siblings must be prohibited and the + * vendor independent issue`that microcode loading which changes + * CPUID, MSRs etc. must be strictly serialized to maintain + * software state correctness. + */ + if (IS_ENABLED(CONFIG_X86_64)) + load_ucode_ap(); + + /* + * Synchronization point with the hotplug core. Sets this CPUs + * synchronization state to ALIVE and spin-waits for the control CPU to + * release this CPU for further bringup. + */ + cpuhp_ap_sync_alive(); + + cpu_init(); + fpu__init_cpu(); rcu_cpu_starting(raw_smp_processor_id()); x86_cpuinit.early_percpu_clock_init(); - smp_callin(); - enable_start_cpu0 = 0; + ap_starting(); + + /* Check TSC synchronization with the control CPU. */ + check_tsc_sync_target(); - /* otherwise gcc will move up smp_processor_id before the cpu_init */ - barrier(); /* - * Check TSC synchronization with the boot CPU: + * Calibrate the delay loop after the TSC synchronization check. + * This allows to skip the calibration when TSC is synchronized + * across sockets. */ - check_tsc_sync_target(); + ap_calibrate_delay(); speculative_store_bypass_ht_init(); @@ -257,7 +315,6 @@ static void notrace start_secondary(void *unused) set_cpu_online(smp_processor_id(), true); lapic_online(); unlock_vector_lock(); - cpu_set_state_online(smp_processor_id()); x86_platform.nmi_init(); /* enable local interrupts */ @@ -269,15 +326,6 @@ static void notrace start_secondary(void *unused) cpu_startup_entry(CPUHP_AP_ONLINE_IDLE); } -/** - * topology_is_primary_thread - Check whether CPU is the primary SMT thread - * @cpu: CPU to check - */ -bool topology_is_primary_thread(unsigned int cpu) -{ - return apic_id_is_primary_thread(per_cpu(x86_cpu_to_apicid, cpu)); -} - /** * topology_smt_supported - Check whether SMT is supported by the CPUs */ @@ -288,6 +336,7 @@ bool topology_smt_supported(void) /** * topology_phys_to_logical_pkg - Map a physical package id to a logical + * @phys_pkg: The physical package id to map * * Returns logical package id or -1 if not found */ @@ -304,15 +353,17 @@ int topology_phys_to_logical_pkg(unsigned int phys_pkg) return -1; } EXPORT_SYMBOL(topology_phys_to_logical_pkg); + /** * topology_phys_to_logical_die - Map a physical die id to logical + * @die_id: The physical die id to map + * @cur_cpu: The CPU for which the mapping is done * * Returns logical die id or -1 if not found */ -int topology_phys_to_logical_die(unsigned int die_id, unsigned int cur_cpu) +static int topology_phys_to_logical_die(unsigned int die_id, unsigned int cur_cpu) { - int cpu; - int proc_id = cpu_data(cur_cpu).phys_proc_id; + int cpu, proc_id = cpu_data(cur_cpu).phys_proc_id; for_each_possible_cpu(cpu) { struct cpuinfo_x86 *c = &cpu_data(cpu); @@ -323,7 +374,6 @@ int topology_phys_to_logical_die(unsigned int die_id, unsigned int cur_cpu) } return -1; } -EXPORT_SYMBOL(topology_phys_to_logical_die); /** * topology_update_package_map - Update the physical to logical package map @@ -398,7 +448,7 @@ void smp_store_cpu_info(int id) c->cpu_index = id; /* * During boot time, CPU0 has this setup already. Save the info when - * bringing up AP or offlined CPU0. + * bringing up an AP. */ identify_secondary_cpu(c); c->initialized = true; @@ -552,7 +602,7 @@ static int x86_core_flags(void) #ifdef CONFIG_SCHED_SMT static int x86_smt_flags(void) { - return cpu_smt_flags() | x86_sched_itmt_flags(); + return cpu_smt_flags(); } #endif #ifdef CONFIG_SCHED_CLUSTER @@ -563,50 +613,57 @@ static int x86_cluster_flags(void) #endif #endif -static struct sched_domain_topology_level x86_numa_in_package_topology[] = { -#ifdef CONFIG_SCHED_SMT - { cpu_smt_mask, x86_smt_flags, SD_INIT_NAME(SMT) }, -#endif -#ifdef CONFIG_SCHED_CLUSTER - { cpu_clustergroup_mask, x86_cluster_flags, SD_INIT_NAME(CLS) }, -#endif -#ifdef CONFIG_SCHED_MC - { cpu_coregroup_mask, x86_core_flags, SD_INIT_NAME(MC) }, -#endif - { NULL, }, -}; +/* + * Set if a package/die has multiple NUMA nodes inside. + * AMD Magny-Cours, Intel Cluster-on-Die, and Intel + * Sub-NUMA Clustering have this. + */ +static bool x86_has_numa_in_package; -static struct sched_domain_topology_level x86_hybrid_topology[] = { -#ifdef CONFIG_SCHED_SMT - { cpu_smt_mask, x86_smt_flags, SD_INIT_NAME(SMT) }, -#endif -#ifdef CONFIG_SCHED_MC - { cpu_coregroup_mask, x86_core_flags, SD_INIT_NAME(MC) }, -#endif - { cpu_cpu_mask, SD_INIT_NAME(DIE) }, - { NULL, }, -}; +static struct sched_domain_topology_level x86_topology[6]; + +static void __init build_sched_topology(void) +{ + int i = 0; -static struct sched_domain_topology_level x86_topology[] = { #ifdef CONFIG_SCHED_SMT - { cpu_smt_mask, x86_smt_flags, SD_INIT_NAME(SMT) }, + x86_topology[i++] = (struct sched_domain_topology_level){ + cpu_smt_mask, x86_smt_flags, SD_INIT_NAME(SMT) + }; #endif #ifdef CONFIG_SCHED_CLUSTER - { cpu_clustergroup_mask, x86_cluster_flags, SD_INIT_NAME(CLS) }, + /* + * For now, skip the cluster domain on Hybrid. + */ + if (!cpu_feature_enabled(X86_FEATURE_HYBRID_CPU)) { + x86_topology[i++] = (struct sched_domain_topology_level){ + cpu_clustergroup_mask, x86_cluster_flags, SD_INIT_NAME(CLS) + }; + } #endif #ifdef CONFIG_SCHED_MC - { cpu_coregroup_mask, x86_core_flags, SD_INIT_NAME(MC) }, + x86_topology[i++] = (struct sched_domain_topology_level){ + cpu_coregroup_mask, x86_core_flags, SD_INIT_NAME(MC) + }; #endif - { cpu_cpu_mask, SD_INIT_NAME(DIE) }, - { NULL, }, -}; + /* + * When there is NUMA topology inside the package skip the DIE domain + * since the NUMA domains will auto-magically create the right spanning + * domains based on the SLIT. + */ + if (!x86_has_numa_in_package) { + x86_topology[i++] = (struct sched_domain_topology_level){ + cpu_cpu_mask, SD_INIT_NAME(DIE) + }; + } -/* - * Set if a package/die has multiple NUMA nodes inside. - * AMD Magny-Cours, Intel Cluster-on-Die, and Intel - * Sub-NUMA Clustering have this. - */ -static bool x86_has_numa_in_package; + /* + * There must be one trailing NULL entry left. + */ + BUG_ON(i >= ARRAY_SIZE(x86_topology)-1); + + set_sched_topology(x86_topology); +} void set_cpu_sibling_map(int cpu) { @@ -706,9 +763,9 @@ static void impress_friends(void) * Allow the user to impress friends. */ pr_debug("Before bogomips\n"); - for_each_possible_cpu(cpu) - if (cpumask_test_cpu(cpu, cpu_callout_mask)) - bogosum += cpu_data(cpu).loops_per_jiffy; + for_each_online_cpu(cpu) + bogosum += cpu_data(cpu).loops_per_jiffy; + pr_info("Total of %d processors activated (%lu.%02lu BogoMIPS)\n", num_online_cpus(), bogosum/(500000/HZ), @@ -795,86 +852,42 @@ static void __init smp_quirk_init_udelay(void) } /* - * Poke the other CPU in the eye via NMI to wake it up. Remember that the normal - * INIT, INIT, STARTUP sequence will reset the chip hard for us, and this - * won't ... remember to clear down the APIC, etc later. + * Wake up AP by INIT, INIT, STARTUP sequence. */ -int -wakeup_secondary_cpu_via_nmi(int apicid, unsigned long start_eip) +static void send_init_sequence(int phys_apicid) { - u32 dm = apic->dest_mode_logical ? APIC_DEST_LOGICAL : APIC_DEST_PHYSICAL; - unsigned long send_status, accept_status = 0; - int maxlvt; - - /* Target chip */ - /* Boot on the stack */ - /* Kick the second */ - apic_icr_write(APIC_DM_NMI | dm, apicid); + int maxlvt = lapic_get_maxlvt(); - pr_debug("Waiting for send to finish...\n"); - send_status = safe_apic_wait_icr_idle(); - - /* - * Give the other CPU some time to accept the IPI. - */ - udelay(200); + /* Be paranoid about clearing APIC errors. */ if (APIC_INTEGRATED(boot_cpu_apic_version)) { - maxlvt = lapic_get_maxlvt(); - if (maxlvt > 3) /* Due to the Pentium erratum 3AP. */ + /* Due to the Pentium erratum 3AP. */ + if (maxlvt > 3) apic_write(APIC_ESR, 0); - accept_status = (apic_read(APIC_ESR) & 0xEF); + apic_read(APIC_ESR); } - pr_debug("NMI sent\n"); - if (send_status) - pr_err("APIC never delivered???\n"); - if (accept_status) - pr_err("APIC delivery error (%lx)\n", accept_status); + /* Assert INIT on the target CPU */ + apic_icr_write(APIC_INT_LEVELTRIG | APIC_INT_ASSERT | APIC_DM_INIT, phys_apicid); + safe_apic_wait_icr_idle(); - return (send_status | accept_status); + udelay(init_udelay); + + /* Deassert INIT on the target CPU */ + apic_icr_write(APIC_INT_LEVELTRIG | APIC_DM_INIT, phys_apicid); + safe_apic_wait_icr_idle(); } -static int -wakeup_secondary_cpu_via_init(int phys_apicid, unsigned long start_eip) +/* + * Wake up AP by INIT, INIT, STARTUP sequence. + */ +static int wakeup_secondary_cpu_via_init(int phys_apicid, unsigned long start_eip) { unsigned long send_status = 0, accept_status = 0; - int maxlvt, num_starts, j; + int num_starts, j, maxlvt; + preempt_disable(); maxlvt = lapic_get_maxlvt(); - - /* - * Be paranoid about clearing APIC errors. - */ - if (APIC_INTEGRATED(boot_cpu_apic_version)) { - if (maxlvt > 3) /* Due to the Pentium erratum 3AP. */ - apic_write(APIC_ESR, 0); - apic_read(APIC_ESR); - } - - pr_debug("Asserting INIT\n"); - - /* - * Turn INIT on target chip - */ - /* - * Send IPI - */ - apic_icr_write(APIC_INT_LEVELTRIG | APIC_INT_ASSERT | APIC_DM_INIT, - phys_apicid); - - pr_debug("Waiting for send to finish...\n"); - send_status = safe_apic_wait_icr_idle(); - - udelay(init_udelay); - - pr_debug("Deasserting INIT\n"); - - /* Target chip */ - /* Send IPI */ - apic_icr_write(APIC_INT_LEVELTRIG | APIC_DM_INIT, phys_apicid); - - pr_debug("Waiting for send to finish...\n"); - send_status = safe_apic_wait_icr_idle(); + send_init_sequence(phys_apicid); mb(); @@ -945,15 +958,16 @@ wakeup_secondary_cpu_via_init(int phys_apicid, unsigned long start_eip) if (accept_status) pr_err("APIC delivery error (%lx)\n", accept_status); + preempt_enable(); return (send_status | accept_status); } /* reduce the number of lines printed when booting a large cpu count system */ static void announce_cpu(int cpu, int apicid) { + static int width, node_width, first = 1; static int current_node = NUMA_NO_NODE; int node = early_cpu_to_node(cpu); - static int width, node_width; if (!width) width = num_digits(num_possible_cpus()) + 1; /* + '#' sign */ @@ -961,10 +975,10 @@ static void announce_cpu(int cpu, int apicid) if (!node_width) node_width = num_digits(num_possible_nodes()) + 1; /* + '#' */ - if (cpu == 1) - printk(KERN_INFO "x86: Booting SMP configuration:\n"); - if (system_state < SYSTEM_RUNNING) { + if (first) + pr_info("x86: Booting SMP configuration:\n"); + if (node != current_node) { if (current_node > (-1)) pr_cont("\n"); @@ -975,77 +989,16 @@ static void announce_cpu(int cpu, int apicid) } /* Add padding for the BSP */ - if (cpu == 1) + if (first) pr_cont("%*s", width + 1, " "); + first = 0; pr_cont("%*s#%d", width - num_digits(cpu), " ", cpu); - } else pr_info("Booting Node %d Processor %d APIC 0x%x\n", node, cpu, apicid); } -static int wakeup_cpu0_nmi(unsigned int cmd, struct pt_regs *regs) -{ - int cpu; - - cpu = smp_processor_id(); - if (cpu == 0 && !cpu_online(cpu) && enable_start_cpu0) - return NMI_HANDLED; - - return NMI_DONE; -} - -/* - * Wake up AP by INIT, INIT, STARTUP sequence. - * - * Instead of waiting for STARTUP after INITs, BSP will execute the BIOS - * boot-strap code which is not a desired behavior for waking up BSP. To - * void the boot-strap code, wake up CPU0 by NMI instead. - * - * This works to wake up soft offlined CPU0 only. If CPU0 is hard offlined - * (i.e. physically hot removed and then hot added), NMI won't wake it up. - * We'll change this code in the future to wake up hard offlined CPU0 if - * real platform and request are available. - */ -static int -wakeup_cpu_via_init_nmi(int cpu, unsigned long start_ip, int apicid, - int *cpu0_nmi_registered) -{ - int id; - int boot_error; - - preempt_disable(); - - /* - * Wake up AP by INIT, INIT, STARTUP sequence. - */ - if (cpu) { - boot_error = wakeup_secondary_cpu_via_init(apicid, start_ip); - goto out; - } - - /* - * Wake up BSP by nmi. - * - * Register a NMI handler to help wake up CPU0. - */ - boot_error = register_nmi_handler(NMI_LOCAL, - wakeup_cpu0_nmi, 0, "wake_cpu0"); - - if (!boot_error) { - enable_start_cpu0 = 1; - *cpu0_nmi_registered = 1; - id = apic->dest_mode_logical ? cpu0_logical_apicid : apicid; - boot_error = wakeup_secondary_cpu_via_nmi(id, start_ip); - } - -out: - preempt_enable(); - - return boot_error; -} - int common_cpu_up(unsigned int cpu, struct task_struct *idle) { int ret; @@ -1071,17 +1024,13 @@ int common_cpu_up(unsigned int cpu, struct task_struct *idle) /* * NOTE - on most systems this is a PHYSICAL apic ID, but on multiquad * (ie clustered apic addressing mode), this is a LOGICAL apic ID. - * Returns zero if CPU booted OK, else error code from + * Returns zero if startup was successfully sent, else error code from * ->wakeup_secondary_cpu. */ -static int do_boot_cpu(int apicid, int cpu, struct task_struct *idle, - int *cpu0_nmi_registered) +static int do_boot_cpu(int apicid, int cpu, struct task_struct *idle) { - /* start_ip had better be page-aligned! */ unsigned long start_ip = real_mode_header->trampoline_start; - - unsigned long boot_error = 0; - unsigned long timeout; + int ret; #ifdef CONFIG_X86_64 /* If 64-bit wakeup method exists, use the 64-bit mode trampoline IP */ @@ -1094,7 +1043,7 @@ static int do_boot_cpu(int apicid, int cpu, struct task_struct *idle, if (IS_ENABLED(CONFIG_X86_32)) { early_gdt_descr.address = (unsigned long)get_cpu_gdt_rw(cpu); initial_stack = idle->thread.sp; - } else { + } else if (!(smpboot_control & STARTUP_PARALLEL_MASK)) { smpboot_control = cpu; } @@ -1108,7 +1057,6 @@ static int do_boot_cpu(int apicid, int cpu, struct task_struct *idle, * This grunge runs the startup process for * the targeted processor. */ - if (x86_platform.legacy.warm_reset) { pr_debug("Setting warm reset code and vector.\n"); @@ -1123,13 +1071,6 @@ static int do_boot_cpu(int apicid, int cpu, struct task_struct *idle, } } - /* - * AP might wait on cpu_callout_mask in cpu_init() with - * cpu_initialized_mask set if previous attempt to online - * it timed-out. Clear cpu_initialized_mask so that after - * INIT/SIPI it could start with a clean state. - */ - cpumask_clear_cpu(cpu, cpu_initialized_mask); smp_mb(); /* @@ -1137,66 +1078,25 @@ static int do_boot_cpu(int apicid, int cpu, struct task_struct *idle, * - Use a method from the APIC driver if one defined, with wakeup * straight to 64-bit mode preferred over wakeup to RM. * Otherwise, - * - Use an INIT boot APIC message for APs or NMI for BSP. + * - Use an INIT boot APIC message */ if (apic->wakeup_secondary_cpu_64) - boot_error = apic->wakeup_secondary_cpu_64(apicid, start_ip); + ret = apic->wakeup_secondary_cpu_64(apicid, start_ip); else if (apic->wakeup_secondary_cpu) - boot_error = apic->wakeup_secondary_cpu(apicid, start_ip); + ret = apic->wakeup_secondary_cpu(apicid, start_ip); else - boot_error = wakeup_cpu_via_init_nmi(cpu, start_ip, apicid, - cpu0_nmi_registered); + ret = wakeup_secondary_cpu_via_init(apicid, start_ip); - if (!boot_error) { - /* - * Wait 10s total for first sign of life from AP - */ - boot_error = -1; - timeout = jiffies + 10*HZ; - while (time_before(jiffies, timeout)) { - if (cpumask_test_cpu(cpu, cpu_initialized_mask)) { - /* - * Tell AP to proceed with initialization - */ - cpumask_set_cpu(cpu, cpu_callout_mask); - boot_error = 0; - break; - } - schedule(); - } - } - - if (!boot_error) { - /* - * Wait till AP completes initial initialization - */ - while (!cpumask_test_cpu(cpu, cpu_callin_mask)) { - /* - * Allow other tasks to run while we wait for the - * AP to come online. This also gives a chance - * for the MTRR work(triggered by the AP coming online) - * to be completed in the stop machine context. - */ - schedule(); - } - } - - if (x86_platform.legacy.warm_reset) { - /* - * Cleanup possible dangling ends... - */ - smpboot_restore_warm_reset_vector(); - } - - return boot_error; + /* If the wakeup mechanism failed, cleanup the warm reset vector */ + if (ret) + arch_cpuhp_cleanup_kick_cpu(cpu); + return ret; } -int native_cpu_up(unsigned int cpu, struct task_struct *tidle) +int native_kick_ap(unsigned int cpu, struct task_struct *tidle) { int apicid = apic->cpu_present_to_apicid(cpu); - int cpu0_nmi_registered = 0; - unsigned long flags; - int err, ret = 0; + int err; lockdep_assert_irqs_enabled(); @@ -1209,25 +1109,12 @@ int native_cpu_up(unsigned int cpu, struct task_struct *tidle) return -EINVAL; } - /* - * Already booted CPU? - */ - if (cpumask_test_cpu(cpu, cpu_callin_mask)) { - pr_debug("do_boot_cpu %d Already started\n", cpu); - return -ENOSYS; - } - /* * Save current MTRR state in case it was changed since early boot * (e.g. by the ACPI SMI) to initialize new CPUs with MTRRs in sync: */ mtrr_save_state(); - /* x86 CPUs take themselves offline, so delayed offline is OK. */ - err = cpu_check_up_prepare(cpu); - if (err && err != -EBUSY) - return err; - /* the FPU context is blank, nobody can own it */ per_cpu(fpu_fpregs_owner_ctx, cpu) = NULL; @@ -1235,41 +1122,44 @@ int native_cpu_up(unsigned int cpu, struct task_struct *tidle) if (err) return err; - err = do_boot_cpu(apicid, cpu, tidle, &cpu0_nmi_registered); - if (err) { + err = do_boot_cpu(apicid, cpu, tidle); + if (err) pr_err("do_boot_cpu failed(%d) to wakeup CPU#%u\n", err, cpu); - ret = -EIO; - goto unreg_nmi; - } - /* - * Check TSC synchronization with the AP (keep irqs disabled - * while doing so): - */ - local_irq_save(flags); - check_tsc_sync_source(cpu); - local_irq_restore(flags); + return err; +} - while (!cpu_online(cpu)) { - cpu_relax(); - touch_nmi_watchdog(); - } +int arch_cpuhp_kick_ap_alive(unsigned int cpu, struct task_struct *tidle) +{ + return smp_ops.kick_ap_alive(cpu, tidle); +} -unreg_nmi: - /* - * Clean up the nmi handler. Do this after the callin and callout sync - * to avoid impact of possible long unregister time. - */ - if (cpu0_nmi_registered) - unregister_nmi_handler(NMI_LOCAL, "wake_cpu0"); +void arch_cpuhp_cleanup_kick_cpu(unsigned int cpu) +{ + /* Cleanup possible dangling ends... */ + if (smp_ops.kick_ap_alive == native_kick_ap && x86_platform.legacy.warm_reset) + smpboot_restore_warm_reset_vector(); +} - return ret; +void arch_cpuhp_cleanup_dead_cpu(unsigned int cpu) +{ + if (smp_ops.cleanup_dead_cpu) + smp_ops.cleanup_dead_cpu(cpu); + + if (system_state == SYSTEM_RUNNING) + pr_info("CPU %u is now offline\n", cpu); +} + +void arch_cpuhp_sync_state_poll(void) +{ + if (smp_ops.poll_sync_state) + smp_ops.poll_sync_state(); } /** - * arch_disable_smp_support() - disables SMP support for x86 at runtime + * arch_disable_smp_support() - Disables SMP support for x86 at boottime */ -void arch_disable_smp_support(void) +void __init arch_disable_smp_support(void) { disable_ioapic_support(); } @@ -1361,14 +1251,6 @@ static void __init smp_cpu_index_default(void) } } -static void __init smp_get_logical_apicid(void) -{ - if (x2apic_mode) - cpu0_logical_apicid = apic_read(APIC_LDR); - else - cpu0_logical_apicid = GET_APIC_LOGICAL_ID(apic_read(APIC_LDR)); -} - void __init smp_prepare_cpus_common(void) { unsigned int i; @@ -1379,7 +1261,6 @@ void __init smp_prepare_cpus_common(void) * Setup boot CPU information */ smp_store_boot_cpu_info(); /* Final full version of the data */ - cpumask_copy(cpu_callin_mask, cpumask_of(0)); mb(); for_each_possible_cpu(i) { @@ -1390,18 +1271,24 @@ void __init smp_prepare_cpus_common(void) zalloc_cpumask_var(&per_cpu(cpu_l2c_shared_map, i), GFP_KERNEL); } - /* - * Set 'default' x86 topology, this matches default_topology() in that - * it has NUMA nodes as a topology level. See also - * native_smp_cpus_done(). - * - * Must be done before set_cpus_sibling_map() is ran. - */ - set_sched_topology(x86_topology); - set_cpu_sibling_map(0); } +#ifdef CONFIG_X86_64 +/* Establish whether parallel bringup can be supported. */ +bool __init arch_cpuhp_init_parallel_bringup(void) +{ + if (!x86_cpuinit.parallel_bringup) { + pr_info("Parallel CPU startup disabled by the platform\n"); + return false; + } + + smpboot_control = STARTUP_READ_APICID; + pr_debug("Parallel CPU startup enabled: 0x%08x\n", smpboot_control); + return true; +} +#endif + /* * Prepare for SMP bootup. * @max_cpus: configured maximum number of CPUs, It is a legacy parameter @@ -1431,8 +1318,6 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus) /* Setup local timer */ x86_init.timers.setup_percpu_clockev(); - smp_get_logical_apicid(); - pr_info("CPU0: "); print_cpu_info(&cpu_data(0)); @@ -1455,6 +1340,33 @@ void arch_thaw_secondary_cpus_end(void) cache_aps_init(); } +bool smp_park_other_cpus_in_init(void) +{ + unsigned int cpu, this_cpu = smp_processor_id(); + unsigned int apicid; + + if (apic->wakeup_secondary_cpu_64 || apic->wakeup_secondary_cpu) + return false; + + /* + * If this is a crash stop which does not execute on the boot CPU, + * then this cannot use the INIT mechanism because INIT to the boot + * CPU will reset the machine. + */ + if (this_cpu) + return false; + + for_each_present_cpu(cpu) { + if (cpu == this_cpu) + continue; + apicid = apic->cpu_present_to_apicid(cpu); + if (apicid == BAD_APICID) + continue; + send_init_sequence(apicid); + } + return true; +} + /* * Early setup to make printk work. */ @@ -1466,9 +1378,6 @@ void __init native_smp_prepare_boot_cpu(void) if (!IS_ENABLED(CONFIG_SMP)) switch_gdt_and_percpu_base(me); - /* already set me in cpu_online_mask in boot_cpu_init() */ - cpumask_set_cpu(me, cpu_callout_mask); - cpu_set_state_online(me); native_pv_lock_init(); } @@ -1490,13 +1399,7 @@ void __init native_smp_cpus_done(unsigned int max_cpus) pr_debug("Boot done\n"); calculate_max_logical_packages(); - - /* XXX for now assume numa-in-package and hybrid don't overlap */ - if (x86_has_numa_in_package) - set_sched_topology(x86_numa_in_package_topology); - if (cpu_feature_enabled(X86_FEATURE_HYBRID_CPU)) - set_sched_topology(x86_hybrid_topology); - + build_sched_topology(); nmi_selftest(); impress_friends(); cache_aps_init(); @@ -1592,6 +1495,12 @@ __init void prefill_possible_map(void) set_cpu_possible(i, true); } +/* correctly size the local cpu masks */ +void __init setup_cpu_local_masks(void) +{ + alloc_bootmem_cpumask_var(&cpu_sibling_setup_mask); +} + #ifdef CONFIG_HOTPLUG_CPU /* Recompute SMT state for all CPUs on offline */ @@ -1650,10 +1559,6 @@ static void remove_siblinginfo(int cpu) static void remove_cpu_from_maps(int cpu) { set_cpu_online(cpu, false); - cpumask_clear_cpu(cpu, cpu_callout_mask); - cpumask_clear_cpu(cpu, cpu_callin_mask); - /* was set by cpu_init() */ - cpumask_clear_cpu(cpu, cpu_initialized_mask); numa_remove_cpu(cpu); } @@ -1704,64 +1609,27 @@ int native_cpu_disable(void) return 0; } -int common_cpu_die(unsigned int cpu) -{ - int ret = 0; - - /* We don't do anything here: idle task is faking death itself. */ - - /* They ack this in play_dead() by setting CPU_DEAD */ - if (cpu_wait_death(cpu, 5)) { - if (system_state == SYSTEM_RUNNING) - pr_info("CPU %u is now offline\n", cpu); - } else { - pr_err("CPU %u didn't die...\n", cpu); - ret = -1; - } - - return ret; -} - -void native_cpu_die(unsigned int cpu) -{ - common_cpu_die(cpu); -} - void play_dead_common(void) { idle_task_exit(); - /* Ack it */ - (void)cpu_report_death(); - + cpuhp_ap_report_dead(); /* * With physical CPU hotplug, we should halt the cpu */ local_irq_disable(); } -/** - * cond_wakeup_cpu0 - Wake up CPU0 if needed. - * - * If NMI wants to wake up CPU0, start CPU0. - */ -void cond_wakeup_cpu0(void) -{ - if (smp_processor_id() == 0 && enable_start_cpu0) - start_cpu0(); -} -EXPORT_SYMBOL_GPL(cond_wakeup_cpu0); - /* * We need to flush the caches before going to sleep, lest we have * dirty data in our caches when we come back up. */ static inline void mwait_play_dead(void) { + struct mwait_cpu_dead *md = this_cpu_ptr(&mwait_cpu_dead); unsigned int eax, ebx, ecx, edx; unsigned int highest_cstate = 0; unsigned int highest_subcstate = 0; - void *mwait_ptr; int i; if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD || @@ -1796,12 +1664,9 @@ static inline void mwait_play_dead(void) (highest_subcstate - 1); } - /* - * This should be a memory location in a cache line which is - * unlikely to be touched by other processors. The actual - * content is immaterial as it is not actually modified in any way. - */ - mwait_ptr = ¤t_thread_info()->flags; + /* Set up state for the kexec() hack below */ + md->status = CPUDEAD_MWAIT_WAIT; + md->control = CPUDEAD_MWAIT_WAIT; wbinvd(); @@ -1814,13 +1679,58 @@ static inline void mwait_play_dead(void) * case where we return around the loop. */ mb(); - clflush(mwait_ptr); + clflush(md); mb(); - __monitor(mwait_ptr, 0, 0); + __monitor(md, 0, 0); mb(); __mwait(eax, 0); - cond_wakeup_cpu0(); + if (READ_ONCE(md->control) == CPUDEAD_MWAIT_KEXEC_HLT) { + /* + * Kexec is about to happen. Don't go back into mwait() as + * the kexec kernel might overwrite text and data including + * page tables and stack. So mwait() would resume when the + * monitor cache line is written to and then the CPU goes + * south due to overwritten text, page tables and stack. + * + * Note: This does _NOT_ protect against a stray MCE, NMI, + * SMI. They will resume execution at the instruction + * following the HLT instruction and run into the problem + * which this is trying to prevent. + */ + WRITE_ONCE(md->status, CPUDEAD_MWAIT_KEXEC_HLT); + while(1) + native_halt(); + } + } +} + +/* + * Kick all "offline" CPUs out of mwait on kexec(). See comment in + * mwait_play_dead(). + */ +void smp_kick_mwait_play_dead(void) +{ + u32 newstate = CPUDEAD_MWAIT_KEXEC_HLT; + struct mwait_cpu_dead *md; + unsigned int cpu, i; + + for_each_cpu_andnot(cpu, cpu_present_mask, cpu_online_mask) { + md = per_cpu_ptr(&mwait_cpu_dead, cpu); + + /* Does it sit in mwait_play_dead() ? */ + if (READ_ONCE(md->status) != CPUDEAD_MWAIT_WAIT) + continue; + + /* Wait up to 5ms */ + for (i = 0; READ_ONCE(md->status) != newstate && i < 1000; i++) { + /* Bring it out of mwait */ + WRITE_ONCE(md->control, newstate); + udelay(5); + } + + if (READ_ONCE(md->status) != newstate) + pr_err_once("CPU%u is stuck in mwait_play_dead()\n", cpu); } } @@ -1829,11 +1739,8 @@ void __noreturn hlt_play_dead(void) if (__this_cpu_read(cpu_info.x86) >= 4) wbinvd(); - while (1) { + while (1) native_halt(); - - cond_wakeup_cpu0(); - } } void native_play_dead(void) @@ -1852,12 +1759,6 @@ int native_cpu_disable(void) return -ENOSYS; } -void native_cpu_die(unsigned int cpu) -{ - /* We said "no" in __cpu_disable */ - BUG(); -} - void native_play_dead(void) { BUG(); diff --git a/arch/x86/kernel/topology.c b/arch/x86/kernel/topology.c index 1b83377274b8ca1292bc563f9c99c41dcd102333..ca004e2e44699ee922998e4c51d891bd391feacb 100644 --- a/arch/x86/kernel/topology.c +++ b/arch/x86/kernel/topology.c @@ -38,102 +38,12 @@ static DEFINE_PER_CPU(struct x86_cpu, cpu_devices); #ifdef CONFIG_HOTPLUG_CPU - -#ifdef CONFIG_BOOTPARAM_HOTPLUG_CPU0 -static int cpu0_hotpluggable = 1; -#else -static int cpu0_hotpluggable; -static int __init enable_cpu0_hotplug(char *str) -{ - cpu0_hotpluggable = 1; - return 1; -} - -__setup("cpu0_hotplug", enable_cpu0_hotplug); -#endif - -#ifdef CONFIG_DEBUG_HOTPLUG_CPU0 -/* - * This function offlines a CPU as early as possible and allows userspace to - * boot up without the CPU. The CPU can be onlined back by user after boot. - * - * This is only called for debugging CPU offline/online feature. - */ -int _debug_hotplug_cpu(int cpu, int action) +int arch_register_cpu(int cpu) { - int ret; - - if (!cpu_is_hotpluggable(cpu)) - return -EINVAL; + struct x86_cpu *xc = per_cpu_ptr(&cpu_devices, cpu); - switch (action) { - case 0: - ret = remove_cpu(cpu); - if (!ret) - pr_info("DEBUG_HOTPLUG_CPU0: CPU %u is now offline\n", cpu); - else - pr_debug("Can't offline CPU%d.\n", cpu); - break; - case 1: - ret = add_cpu(cpu); - if (ret) - pr_debug("Can't online CPU%d.\n", cpu); - - break; - default: - ret = -EINVAL; - } - - return ret; -} - -static int __init debug_hotplug_cpu(void) -{ - _debug_hotplug_cpu(0, 0); - return 0; -} - -late_initcall_sync(debug_hotplug_cpu); -#endif /* CONFIG_DEBUG_HOTPLUG_CPU0 */ - -int arch_register_cpu(int num) -{ - struct cpuinfo_x86 *c = &cpu_data(num); - - /* - * Currently CPU0 is only hotpluggable on Intel platforms. Other - * vendors can add hotplug support later. - * Xen PV guests don't support CPU0 hotplug at all. - */ - if (c->x86_vendor != X86_VENDOR_INTEL || - cpu_feature_enabled(X86_FEATURE_XENPV)) - cpu0_hotpluggable = 0; - - /* - * Two known BSP/CPU0 dependencies: Resume from suspend/hibernate - * depends on BSP. PIC interrupts depend on BSP. - * - * If the BSP dependencies are under control, one can tell kernel to - * enable BSP hotplug. This basically adds a control file and - * one can attempt to offline BSP. - */ - if (num == 0 && cpu0_hotpluggable) { - unsigned int irq; - /* - * We won't take down the boot processor on i386 if some - * interrupts only are able to be serviced by the BSP in PIC. - */ - for_each_active_irq(irq) { - if (!IO_APIC_IRQ(irq) && irq_has_action(irq)) { - cpu0_hotpluggable = 0; - break; - } - } - } - if (num || cpu0_hotpluggable) - per_cpu(cpu_devices, num).cpu.hotpluggable = 1; - - return register_cpu(&per_cpu(cpu_devices, num).cpu, num); + xc->cpu.hotpluggable = cpu > 0; + return register_cpu(&xc->cpu, cpu); } EXPORT_SYMBOL(arch_register_cpu); diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c index 3446988521466a5dfdeccbb54510680725095869..3425c6a943e44917c08ebf877f4782d8c4ec0d21 100644 --- a/arch/x86/kernel/tsc.c +++ b/arch/x86/kernel/tsc.c @@ -69,12 +69,10 @@ static int __init tsc_early_khz_setup(char *buf) } early_param("tsc_early_khz", tsc_early_khz_setup); -__always_inline void cyc2ns_read_begin(struct cyc2ns_data *data) +__always_inline void __cyc2ns_read(struct cyc2ns_data *data) { int seq, idx; - preempt_disable_notrace(); - do { seq = this_cpu_read(cyc2ns.seq.seqcount.sequence); idx = seq & 1; @@ -86,6 +84,12 @@ __always_inline void cyc2ns_read_begin(struct cyc2ns_data *data) } while (unlikely(seq != this_cpu_read(cyc2ns.seq.seqcount.sequence))); } +__always_inline void cyc2ns_read_begin(struct cyc2ns_data *data) +{ + preempt_disable_notrace(); + __cyc2ns_read(data); +} + __always_inline void cyc2ns_read_end(void) { preempt_enable_notrace(); @@ -115,18 +119,25 @@ __always_inline void cyc2ns_read_end(void) * -johnstul@us.ibm.com "math is hard, lets go shopping!" */ -static __always_inline unsigned long long cycles_2_ns(unsigned long long cyc) +static __always_inline unsigned long long __cycles_2_ns(unsigned long long cyc) { struct cyc2ns_data data; unsigned long long ns; - cyc2ns_read_begin(&data); + __cyc2ns_read(&data); ns = data.cyc2ns_offset; ns += mul_u64_u32_shr(cyc, data.cyc2ns_mul, data.cyc2ns_shift); - cyc2ns_read_end(); + return ns; +} +static __always_inline unsigned long long cycles_2_ns(unsigned long long cyc) +{ + unsigned long long ns; + preempt_disable_notrace(); + ns = __cycles_2_ns(cyc); + preempt_enable_notrace(); return ns; } @@ -223,7 +234,7 @@ noinstr u64 native_sched_clock(void) u64 tsc_now = rdtsc(); /* return the value in ns */ - return cycles_2_ns(tsc_now); + return __cycles_2_ns(tsc_now); } /* @@ -250,7 +261,7 @@ u64 native_sched_clock_from_tsc(u64 tsc) /* We need to define a real function for sched_clock, to override the weak default version */ #ifdef CONFIG_PARAVIRT -noinstr u64 sched_clock(void) +noinstr u64 sched_clock_noinstr(void) { return paravirt_sched_clock(); } @@ -260,11 +271,20 @@ bool using_native_sched_clock(void) return static_call_query(pv_sched_clock) == native_sched_clock; } #else -u64 sched_clock(void) __attribute__((alias("native_sched_clock"))); +u64 sched_clock_noinstr(void) __attribute__((alias("native_sched_clock"))); bool using_native_sched_clock(void) { return true; } #endif +notrace u64 sched_clock(void) +{ + u64 now; + preempt_disable_notrace(); + now = sched_clock_noinstr(); + preempt_enable_notrace(); + return now; +} + int check_tsc_unstable(void) { return tsc_unstable; @@ -1598,10 +1618,7 @@ void __init tsc_init(void) #ifdef CONFIG_SMP /* - * If we have a constant TSC and are using the TSC for the delay loop, - * we can skip clock calibration if another cpu in the same socket has already - * been calibrated. This assumes that CONSTANT_TSC applies to all - * cpus in the socket - this should be a safe assumption. + * Check whether existing calibration data can be reused. */ unsigned long calibrate_delay_is_known(void) { @@ -1609,6 +1626,21 @@ unsigned long calibrate_delay_is_known(void) int constant_tsc = cpu_has(&cpu_data(cpu), X86_FEATURE_CONSTANT_TSC); const struct cpumask *mask = topology_core_cpumask(cpu); + /* + * If TSC has constant frequency and TSC is synchronized across + * sockets then reuse CPU0 calibration. + */ + if (constant_tsc && !tsc_unstable) + return cpu_data(0).loops_per_jiffy; + + /* + * If TSC has constant frequency and TSC is not synchronized across + * sockets and this is not the first CPU in the socket, then reuse + * the calibration value of an already online CPU on that socket. + * + * This assumes that CONSTANT_TSC is consistent for all CPUs in a + * socket. + */ if (!constant_tsc || !mask) return 0; diff --git a/arch/x86/kernel/tsc_sync.c b/arch/x86/kernel/tsc_sync.c index 9452dc9664b51fddcfaeb6274935c91885814fda..bbc440c93e0881e52c601af434d0c79d90a06fc5 100644 --- a/arch/x86/kernel/tsc_sync.c +++ b/arch/x86/kernel/tsc_sync.c @@ -245,7 +245,6 @@ bool tsc_store_and_check_tsc_adjust(bool bootcpu) */ static atomic_t start_count; static atomic_t stop_count; -static atomic_t skip_test; static atomic_t test_runs; /* @@ -344,20 +343,13 @@ static inline unsigned int loop_timeout(int cpu) } /* - * Source CPU calls into this - it waits for the freshly booted - * target CPU to arrive and then starts the measurement: + * The freshly booted CPU initiates this via an async SMP function call. */ -void check_tsc_sync_source(int cpu) +static void check_tsc_sync_source(void *__cpu) { + unsigned int cpu = (unsigned long)__cpu; int cpus = 2; - /* - * No need to check if we already know that the TSC is not - * synchronized or if we have no TSC. - */ - if (unsynchronized_tsc()) - return; - /* * Set the maximum number of test runs to * 1 if the CPU does not provide the TSC_ADJUST MSR @@ -368,16 +360,9 @@ void check_tsc_sync_source(int cpu) else atomic_set(&test_runs, 3); retry: - /* - * Wait for the target to start or to skip the test: - */ - while (atomic_read(&start_count) != cpus - 1) { - if (atomic_read(&skip_test) > 0) { - atomic_set(&skip_test, 0); - return; - } + /* Wait for the target to start. */ + while (atomic_read(&start_count) != cpus - 1) cpu_relax(); - } /* * Trigger the target to continue into the measurement too: @@ -397,14 +382,14 @@ void check_tsc_sync_source(int cpu) if (!nr_warps) { atomic_set(&test_runs, 0); - pr_debug("TSC synchronization [CPU#%d -> CPU#%d]: passed\n", + pr_debug("TSC synchronization [CPU#%d -> CPU#%u]: passed\n", smp_processor_id(), cpu); } else if (atomic_dec_and_test(&test_runs) || random_warps) { /* Force it to 0 if random warps brought us here */ atomic_set(&test_runs, 0); - pr_warn("TSC synchronization [CPU#%d -> CPU#%d]:\n", + pr_warn("TSC synchronization [CPU#%d -> CPU#%u]:\n", smp_processor_id(), cpu); pr_warn("Measured %Ld cycles TSC warp between CPUs, " "turning off TSC clock.\n", max_warp); @@ -457,11 +442,12 @@ void check_tsc_sync_target(void) * SoCs the TSC is frequency synchronized, but still the TSC ADJUST * register might have been wreckaged by the BIOS.. */ - if (tsc_store_and_check_tsc_adjust(false) || tsc_clocksource_reliable) { - atomic_inc(&skip_test); + if (tsc_store_and_check_tsc_adjust(false) || tsc_clocksource_reliable) return; - } + /* Kick the control CPU into the TSC synchronization function */ + smp_call_function_single(cpumask_first(cpu_online_mask), check_tsc_sync_source, + (unsigned long *)(unsigned long)cpu, 0); retry: /* * Register this CPU's participation and wait for the diff --git a/arch/x86/kernel/unwind_orc.c b/arch/x86/kernel/unwind_orc.c index 3ac50b7298d15a82114663effa26cf8c13d99a8a..7e574cf3bf8a29dd31317aea9c829700dcd451fd 100644 --- a/arch/x86/kernel/unwind_orc.c +++ b/arch/x86/kernel/unwind_orc.c @@ -7,14 +7,23 @@ #include #include #include +#include + +ORC_HEADER; #define orc_warn(fmt, ...) \ printk_deferred_once(KERN_WARNING "WARNING: " fmt, ##__VA_ARGS__) #define orc_warn_current(args...) \ ({ \ - if (state->task == current && !state->error) \ + static bool dumped_before; \ + if (state->task == current && !state->error) { \ orc_warn(args); \ + if (unwind_debug && !dumped_before) { \ + dumped_before = true; \ + unwind_dump(state); \ + } \ + } \ }) extern int __start_orc_unwind_ip[]; @@ -23,8 +32,49 @@ extern struct orc_entry __start_orc_unwind[]; extern struct orc_entry __stop_orc_unwind[]; static bool orc_init __ro_after_init; +static bool unwind_debug __ro_after_init; static unsigned int lookup_num_blocks __ro_after_init; +static int __init unwind_debug_cmdline(char *str) +{ + unwind_debug = true; + + return 0; +} +early_param("unwind_debug", unwind_debug_cmdline); + +static void unwind_dump(struct unwind_state *state) +{ + static bool dumped_before; + unsigned long word, *sp; + struct stack_info stack_info = {0}; + unsigned long visit_mask = 0; + + if (dumped_before) + return; + + dumped_before = true; + + printk_deferred("unwind stack type:%d next_sp:%p mask:0x%lx graph_idx:%d\n", + state->stack_info.type, state->stack_info.next_sp, + state->stack_mask, state->graph_idx); + + for (sp = __builtin_frame_address(0); sp; + sp = PTR_ALIGN(stack_info.next_sp, sizeof(long))) { + if (get_stack_info(sp, state->task, &stack_info, &visit_mask)) + break; + + for (; sp < stack_info.end; sp++) { + + word = READ_ONCE_NOCHECK(*sp); + + printk_deferred("%0*lx: %0*lx (%pB)\n", BITS_PER_LONG/4, + (unsigned long)sp, BITS_PER_LONG/4, + word, (void *)word); + } + } +} + static inline unsigned long orc_ip(const int *ip) { return (unsigned long)ip + *ip; @@ -136,21 +186,6 @@ static struct orc_entry null_orc_entry = { .type = ORC_TYPE_CALL }; -#ifdef CONFIG_CALL_THUNKS -static struct orc_entry *orc_callthunk_find(unsigned long ip) -{ - if (!is_callthunk((void *)ip)) - return NULL; - - return &null_orc_entry; -} -#else -static struct orc_entry *orc_callthunk_find(unsigned long ip) -{ - return NULL; -} -#endif - /* Fake frame pointer entry -- used as a fallback for generated code */ static struct orc_entry orc_fp_entry = { .type = ORC_TYPE_CALL, @@ -203,11 +238,7 @@ static struct orc_entry *orc_find(unsigned long ip) if (orc) return orc; - orc = orc_ftrace_find(ip); - if (orc) - return orc; - - return orc_callthunk_find(ip); + return orc_ftrace_find(ip); } #ifdef CONFIG_MODULES @@ -219,7 +250,6 @@ static struct orc_entry *cur_orc_table = __start_orc_unwind; static void orc_sort_swap(void *_a, void *_b, int size) { struct orc_entry *orc_a, *orc_b; - struct orc_entry orc_tmp; int *a = _a, *b = _b, tmp; int delta = _b - _a; @@ -231,9 +261,7 @@ static void orc_sort_swap(void *_a, void *_b, int size) /* Swap the corresponding .orc_unwind entries: */ orc_a = cur_orc_table + (a - cur_orc_ip_table); orc_b = cur_orc_table + (b - cur_orc_ip_table); - orc_tmp = *orc_a; - *orc_a = *orc_b; - *orc_b = orc_tmp; + swap(*orc_a, *orc_b); } static int orc_sort_cmp(const void *_a, const void *_b) diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S index 25f155205770c7d6286e345a70c77a3159599621..03c885d3640fbe6b626a6fe14cabdf31c9e01dcb 100644 --- a/arch/x86/kernel/vmlinux.lds.S +++ b/arch/x86/kernel/vmlinux.lds.S @@ -508,4 +508,8 @@ INIT_PER_CPU(irq_stack_backing_store); "fixed_percpu_data is not at start of per-cpu area"); #endif +#ifdef CONFIG_RETHUNK +. = ASSERT((__x86_return_thunk & 0x3f) == 0, "__x86_return_thunk not cacheline-aligned"); +#endif + #endif /* CONFIG_X86_64 */ diff --git a/arch/x86/kernel/x86_init.c b/arch/x86/kernel/x86_init.c index d82f4fa2f1bfe87487872903018a274156783df7..a37ebd3b47736dfe55f5e7518df50e4135cdcfab 100644 --- a/arch/x86/kernel/x86_init.c +++ b/arch/x86/kernel/x86_init.c @@ -126,12 +126,13 @@ struct x86_init_ops x86_init __initdata = { struct x86_cpuinit_ops x86_cpuinit = { .early_percpu_clock_init = x86_init_noop, .setup_percpu_clockev = setup_secondary_APIC_clock, + .parallel_bringup = true, }; static void default_nmi_init(void) { }; -static void enc_status_change_prepare_noop(unsigned long vaddr, int npages, bool enc) { } -static bool enc_status_change_finish_noop(unsigned long vaddr, int npages, bool enc) { return false; } +static bool enc_status_change_prepare_noop(unsigned long vaddr, int npages, bool enc) { return true; } +static bool enc_status_change_finish_noop(unsigned long vaddr, int npages, bool enc) { return true; } static bool enc_tlb_flush_required_noop(bool enc) { return false; } static bool enc_cache_flush_required_noop(void) { return false; } static bool is_private_mmio_noop(u64 addr) {return false; } diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c index 0c9660a07b233ff404147fa6acda76668241f7ee..7f4d13383cf2582e14a573d445e0501ec8ba9169 100644 --- a/arch/x86/kvm/cpuid.c +++ b/arch/x86/kvm/cpuid.c @@ -501,20 +501,15 @@ int kvm_vcpu_ioctl_get_cpuid2(struct kvm_vcpu *vcpu, struct kvm_cpuid2 *cpuid, struct kvm_cpuid_entry2 __user *entries) { - int r; - - r = -E2BIG; if (cpuid->nent < vcpu->arch.cpuid_nent) - goto out; - r = -EFAULT; + return -E2BIG; + if (copy_to_user(entries, vcpu->arch.cpuid_entries, vcpu->arch.cpuid_nent * sizeof(struct kvm_cpuid_entry2))) - goto out; - return 0; + return -EFAULT; -out: cpuid->nent = vcpu->arch.cpuid_nent; - return r; + return 0; } /* Mask kvm_cpu_caps for @leaf with the raw CPUID capabilities of this CPU. */ @@ -734,6 +729,10 @@ void kvm_set_cpu_caps(void) F(NULL_SEL_CLR_BASE) | F(AUTOIBRS) | 0 /* PrefetchCtlMsr */ ); + kvm_cpu_cap_init_kvm_defined(CPUID_8000_0022_EAX, + F(PERFMON_V2) + ); + /* * Synthesize "LFENCE is serializing" into the AMD-defined entry in * KVM's supported CPUID if the feature is reported as supported by the @@ -948,7 +947,7 @@ static inline int __do_cpuid_func(struct kvm_cpuid_array *array, u32 function) union cpuid10_eax eax; union cpuid10_edx edx; - if (!static_cpu_has(X86_FEATURE_ARCH_PERFMON)) { + if (!enable_pmu || !static_cpu_has(X86_FEATURE_ARCH_PERFMON)) { entry->eax = entry->ebx = entry->ecx = entry->edx = 0; break; } @@ -1128,7 +1127,7 @@ static inline int __do_cpuid_func(struct kvm_cpuid_array *array, u32 function) entry->edx = 0; break; case 0x80000000: - entry->eax = min(entry->eax, 0x80000021); + entry->eax = min(entry->eax, 0x80000022); /* * Serializing LFENCE is reported in a multitude of ways, and * NullSegClearsBase is not reported in CPUID on Zen2; help @@ -1233,6 +1232,28 @@ static inline int __do_cpuid_func(struct kvm_cpuid_array *array, u32 function) entry->ebx = entry->ecx = entry->edx = 0; cpuid_entry_override(entry, CPUID_8000_0021_EAX); break; + /* AMD Extended Performance Monitoring and Debug */ + case 0x80000022: { + union cpuid_0x80000022_ebx ebx; + + entry->ecx = entry->edx = 0; + if (!enable_pmu || !kvm_cpu_cap_has(X86_FEATURE_PERFMON_V2)) { + entry->eax = entry->ebx; + break; + } + + cpuid_entry_override(entry, CPUID_8000_0022_EAX); + + if (kvm_cpu_cap_has(X86_FEATURE_PERFMON_V2)) + ebx.split.num_core_pmc = kvm_pmu_cap.num_counters_gp; + else if (kvm_cpu_cap_has(X86_FEATURE_PERFCTR_CORE)) + ebx.split.num_core_pmc = AMD64_NUM_COUNTERS_CORE; + else + ebx.split.num_core_pmc = AMD64_NUM_COUNTERS; + + entry->ebx = ebx.full; + break; + } /*Add support for Centaur's CPUID instruction*/ case 0xC0000000: /*Just support up to 0xC0000004 now*/ diff --git a/arch/x86/kvm/i8259.c b/arch/x86/kvm/i8259.c index 4756bcb5724f863fab17474b7d7acbd145077d24..8dec646e764b60d6c52a3b435eeadbb1355b065b 100644 --- a/arch/x86/kvm/i8259.c +++ b/arch/x86/kvm/i8259.c @@ -411,7 +411,10 @@ static u32 pic_poll_read(struct kvm_kpic_state *s, u32 addr1) pic_clear_isr(s, ret); if (addr1 >> 7 || ret != 2) pic_update_irq(s->pics_state); + /* Bit 7 is 1, means there's an interrupt */ + ret |= 0x80; } else { + /* Bit 7 is 0, means there's no interrupt */ ret = 0x07; pic_update_irq(s->pics_state); } diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c index 3c300a196bdf945ea7354cc370b4cd0aad515c61..113ca9661ab21d75ef7ff9757deca759baf9d22f 100644 --- a/arch/x86/kvm/lapic.c +++ b/arch/x86/kvm/lapic.c @@ -51,11 +51,6 @@ #define mod_64(x, y) ((x) % (y)) #endif -#define PRId64 "d" -#define PRIx64 "llx" -#define PRIu64 "u" -#define PRIo64 "o" - /* 14 is the version for Xeon and Pentium 8.4.8*/ #define APIC_VERSION 0x14UL #define LAPIC_MMIO_LENGTH (1 << 12) diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c index 6eaa3d6994aebea7ecc344626adce9d0d062a31b..ec169f5c7dce21d5f730638ba86ebc99f3050146 100644 --- a/arch/x86/kvm/mmu/mmu.c +++ b/arch/x86/kvm/mmu/mmu.c @@ -58,6 +58,8 @@ extern bool itlb_multihit_kvm_mitigation; +static bool nx_hugepage_mitigation_hard_disabled; + int __read_mostly nx_huge_pages = -1; static uint __read_mostly nx_huge_pages_recovery_period_ms; #ifdef CONFIG_PREEMPT_RT @@ -67,12 +69,13 @@ static uint __read_mostly nx_huge_pages_recovery_ratio = 0; static uint __read_mostly nx_huge_pages_recovery_ratio = 60; #endif +static int get_nx_huge_pages(char *buffer, const struct kernel_param *kp); static int set_nx_huge_pages(const char *val, const struct kernel_param *kp); static int set_nx_huge_pages_recovery_param(const char *val, const struct kernel_param *kp); static const struct kernel_param_ops nx_huge_pages_ops = { .set = set_nx_huge_pages, - .get = param_get_bool, + .get = get_nx_huge_pages, }; static const struct kernel_param_ops nx_huge_pages_recovery_param_ops = { @@ -1600,6 +1603,10 @@ bool kvm_unmap_gfn_range(struct kvm *kvm, struct kvm_gfn_range *range) if (tdp_mmu_enabled) flush = kvm_tdp_mmu_unmap_gfn_range(kvm, range, flush); + if (kvm_x86_ops.set_apic_access_page_addr && + range->slot->id == APIC_ACCESS_PAGE_PRIVATE_MEMSLOT) + kvm_make_all_cpus_request(kvm, KVM_REQ_APIC_PAGE_RELOAD); + return flush; } @@ -5797,6 +5804,14 @@ static void __kvm_mmu_invalidate_addr(struct kvm_vcpu *vcpu, struct kvm_mmu *mmu vcpu_clear_mmio_info(vcpu, addr); + /* + * Walking and synchronizing SPTEs both assume they are operating in + * the context of the current MMU, and would need to be reworked if + * this is ever used to sync the guest_mmu, e.g. to emulate INVEPT. + */ + if (WARN_ON_ONCE(mmu != vcpu->arch.mmu)) + return; + if (!VALID_PAGE(root_hpa)) return; @@ -6844,6 +6859,14 @@ static void mmu_destroy_caches(void) kmem_cache_destroy(mmu_page_header_cache); } +static int get_nx_huge_pages(char *buffer, const struct kernel_param *kp) +{ + if (nx_hugepage_mitigation_hard_disabled) + return sprintf(buffer, "never\n"); + + return param_get_bool(buffer, kp); +} + static bool get_nx_auto_mode(void) { /* Return true when CPU has the bug, and mitigations are ON */ @@ -6860,15 +6883,29 @@ static int set_nx_huge_pages(const char *val, const struct kernel_param *kp) bool old_val = nx_huge_pages; bool new_val; + if (nx_hugepage_mitigation_hard_disabled) + return -EPERM; + /* In "auto" mode deploy workaround only if CPU has the bug. */ - if (sysfs_streq(val, "off")) + if (sysfs_streq(val, "off")) { new_val = 0; - else if (sysfs_streq(val, "force")) + } else if (sysfs_streq(val, "force")) { new_val = 1; - else if (sysfs_streq(val, "auto")) + } else if (sysfs_streq(val, "auto")) { new_val = get_nx_auto_mode(); - else if (kstrtobool(val, &new_val) < 0) + } else if (sysfs_streq(val, "never")) { + new_val = 0; + + mutex_lock(&kvm_lock); + if (!list_empty(&vm_list)) { + mutex_unlock(&kvm_lock); + return -EBUSY; + } + nx_hugepage_mitigation_hard_disabled = true; + mutex_unlock(&kvm_lock); + } else if (kstrtobool(val, &new_val) < 0) { return -EINVAL; + } __set_nx_huge_pages(new_val); @@ -7006,6 +7043,9 @@ static int set_nx_huge_pages_recovery_param(const char *val, const struct kernel uint old_period, new_period; int err; + if (nx_hugepage_mitigation_hard_disabled) + return -EPERM; + was_recovery_enabled = calc_nx_huge_pages_recovery_period(&old_period); err = param_set_uint(val, kp); @@ -7164,6 +7204,9 @@ int kvm_mmu_post_init_vm(struct kvm *kvm) { int err; + if (nx_hugepage_mitigation_hard_disabled) + return 0; + err = kvm_vm_create_worker_thread(kvm, kvm_nx_huge_page_recovery_worker, 0, "kvm-nx-lpage-recovery", &kvm->arch.nx_huge_page_recovery_thread); diff --git a/arch/x86/kvm/mmu/tdp_mmu.c b/arch/x86/kvm/mmu/tdp_mmu.c index 08340219c35a40291abc29856a0f396834e0e742..512163d52194b9945ec19e03b90ae590810107ab 100644 --- a/arch/x86/kvm/mmu/tdp_mmu.c +++ b/arch/x86/kvm/mmu/tdp_mmu.c @@ -592,7 +592,10 @@ static inline int tdp_mmu_set_spte_atomic(struct kvm *kvm, /* * Note, fast_pf_fix_direct_spte() can also modify TDP MMU SPTEs and - * does not hold the mmu_lock. + * does not hold the mmu_lock. On failure, i.e. if a different logical + * CPU modified the SPTE, try_cmpxchg64() updates iter->old_spte with + * the current value, so the caller operates on fresh data, e.g. if it + * retries tdp_mmu_set_spte_atomic() */ if (!try_cmpxchg64(sptep, &iter->old_spte, new_spte)) return -EBUSY; diff --git a/arch/x86/kvm/mtrr.c b/arch/x86/kvm/mtrr.c index 9fac1ec0346335974fa1fadf0e11f58b3c2bf323..3eb6e7f47e9634c144b448b435fc147eb48cb4ed 100644 --- a/arch/x86/kvm/mtrr.c +++ b/arch/x86/kvm/mtrr.c @@ -25,10 +25,24 @@ #define IA32_MTRR_DEF_TYPE_FE (1ULL << 10) #define IA32_MTRR_DEF_TYPE_TYPE_MASK (0xff) +static bool is_mtrr_base_msr(unsigned int msr) +{ + /* MTRR base MSRs use even numbers, masks use odd numbers. */ + return !(msr & 0x1); +} + +static struct kvm_mtrr_range *var_mtrr_msr_to_range(struct kvm_vcpu *vcpu, + unsigned int msr) +{ + int index = (msr - MTRRphysBase_MSR(0)) / 2; + + return &vcpu->arch.mtrr_state.var_ranges[index]; +} + static bool msr_mtrr_valid(unsigned msr) { switch (msr) { - case 0x200 ... 0x200 + 2 * KVM_NR_VAR_MTRR - 1: + case MTRRphysBase_MSR(0) ... MTRRphysMask_MSR(KVM_NR_VAR_MTRR - 1): case MSR_MTRRfix64K_00000: case MSR_MTRRfix16K_80000: case MSR_MTRRfix16K_A0000: @@ -41,7 +55,6 @@ static bool msr_mtrr_valid(unsigned msr) case MSR_MTRRfix4K_F0000: case MSR_MTRRfix4K_F8000: case MSR_MTRRdefType: - case MSR_IA32_CR_PAT: return true; } return false; @@ -52,7 +65,7 @@ static bool valid_mtrr_type(unsigned t) return t < 8 && (1 << t) & 0x73; /* 0, 1, 4, 5, 6 */ } -bool kvm_mtrr_valid(struct kvm_vcpu *vcpu, u32 msr, u64 data) +static bool kvm_mtrr_valid(struct kvm_vcpu *vcpu, u32 msr, u64 data) { int i; u64 mask; @@ -60,9 +73,7 @@ bool kvm_mtrr_valid(struct kvm_vcpu *vcpu, u32 msr, u64 data) if (!msr_mtrr_valid(msr)) return false; - if (msr == MSR_IA32_CR_PAT) { - return kvm_pat_valid(data); - } else if (msr == MSR_MTRRdefType) { + if (msr == MSR_MTRRdefType) { if (data & ~0xcff) return false; return valid_mtrr_type(data & 0xff); @@ -74,7 +85,8 @@ bool kvm_mtrr_valid(struct kvm_vcpu *vcpu, u32 msr, u64 data) } /* variable MTRRs */ - WARN_ON(!(msr >= 0x200 && msr < 0x200 + 2 * KVM_NR_VAR_MTRR)); + WARN_ON(!(msr >= MTRRphysBase_MSR(0) && + msr <= MTRRphysMask_MSR(KVM_NR_VAR_MTRR - 1))); mask = kvm_vcpu_reserved_gpa_bits_raw(vcpu); if ((msr & 1) == 0) { @@ -88,7 +100,6 @@ bool kvm_mtrr_valid(struct kvm_vcpu *vcpu, u32 msr, u64 data) return (data & mask) == 0; } -EXPORT_SYMBOL_GPL(kvm_mtrr_valid); static bool mtrr_is_enabled(struct kvm_mtrr *mtrr_state) { @@ -308,10 +319,8 @@ static void update_mtrr(struct kvm_vcpu *vcpu, u32 msr) { struct kvm_mtrr *mtrr_state = &vcpu->arch.mtrr_state; gfn_t start, end; - int index; - if (msr == MSR_IA32_CR_PAT || !tdp_enabled || - !kvm_arch_has_noncoherent_dma(vcpu->kvm)) + if (!tdp_enabled || !kvm_arch_has_noncoherent_dma(vcpu->kvm)) return; if (!mtrr_is_enabled(mtrr_state) && msr != MSR_MTRRdefType) @@ -326,8 +335,7 @@ static void update_mtrr(struct kvm_vcpu *vcpu, u32 msr) end = ~0ULL; } else { /* variable range MTRRs. */ - index = (msr - 0x200) / 2; - var_mtrr_range(&mtrr_state->var_ranges[index], &start, &end); + var_mtrr_range(var_mtrr_msr_to_range(vcpu, msr), &start, &end); } kvm_zap_gfn_range(vcpu->kvm, gpa_to_gfn(start), gpa_to_gfn(end)); @@ -342,21 +350,18 @@ static void set_var_mtrr_msr(struct kvm_vcpu *vcpu, u32 msr, u64 data) { struct kvm_mtrr *mtrr_state = &vcpu->arch.mtrr_state; struct kvm_mtrr_range *tmp, *cur; - int index, is_mtrr_mask; - index = (msr - 0x200) / 2; - is_mtrr_mask = msr - 0x200 - 2 * index; - cur = &mtrr_state->var_ranges[index]; + cur = var_mtrr_msr_to_range(vcpu, msr); /* remove the entry if it's in the list. */ if (var_mtrr_range_is_valid(cur)) - list_del(&mtrr_state->var_ranges[index].node); + list_del(&cur->node); /* * Set all illegal GPA bits in the mask, since those bits must * implicitly be 0. The bits are then cleared when reading them. */ - if (!is_mtrr_mask) + if (is_mtrr_base_msr(msr)) cur->base = data; else cur->mask = data | kvm_vcpu_reserved_gpa_bits_raw(vcpu); @@ -382,8 +387,6 @@ int kvm_mtrr_set_msr(struct kvm_vcpu *vcpu, u32 msr, u64 data) *(u64 *)&vcpu->arch.mtrr_state.fixed_ranges[index] = data; else if (msr == MSR_MTRRdefType) vcpu->arch.mtrr_state.deftype = data; - else if (msr == MSR_IA32_CR_PAT) - vcpu->arch.pat = data; else set_var_mtrr_msr(vcpu, msr, data); @@ -411,21 +414,16 @@ int kvm_mtrr_get_msr(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata) return 1; index = fixed_msr_to_range_index(msr); - if (index >= 0) + if (index >= 0) { *pdata = *(u64 *)&vcpu->arch.mtrr_state.fixed_ranges[index]; - else if (msr == MSR_MTRRdefType) + } else if (msr == MSR_MTRRdefType) { *pdata = vcpu->arch.mtrr_state.deftype; - else if (msr == MSR_IA32_CR_PAT) - *pdata = vcpu->arch.pat; - else { /* Variable MTRRs */ - int is_mtrr_mask; - - index = (msr - 0x200) / 2; - is_mtrr_mask = msr - 0x200 - 2 * index; - if (!is_mtrr_mask) - *pdata = vcpu->arch.mtrr_state.var_ranges[index].base; + } else { + /* Variable MTRRs */ + if (is_mtrr_base_msr(msr)) + *pdata = var_mtrr_msr_to_range(vcpu, msr)->base; else - *pdata = vcpu->arch.mtrr_state.var_ranges[index].mask; + *pdata = var_mtrr_msr_to_range(vcpu, msr)->mask; *pdata &= ~kvm_vcpu_reserved_gpa_bits_raw(vcpu); } diff --git a/arch/x86/kvm/pmu.c b/arch/x86/kvm/pmu.c index 1690d41c183085eb9433f69264ae9fd2066778c3..bf653df86112071badbc3fea07bb2e5cad4f3ce2 100644 --- a/arch/x86/kvm/pmu.c +++ b/arch/x86/kvm/pmu.c @@ -93,11 +93,6 @@ void kvm_pmu_ops_update(const struct kvm_pmu_ops *pmu_ops) #undef __KVM_X86_PMU_OP } -static inline bool pmc_is_globally_enabled(struct kvm_pmc *pmc) -{ - return static_call(kvm_x86_pmu_pmc_is_enabled)(pmc); -} - static void kvm_pmi_trigger_fn(struct irq_work *irq_work) { struct kvm_pmu *pmu = container_of(irq_work, struct kvm_pmu, irq_work); @@ -562,6 +557,14 @@ void kvm_pmu_deliver_pmi(struct kvm_vcpu *vcpu) bool kvm_pmu_is_valid_msr(struct kvm_vcpu *vcpu, u32 msr) { + switch (msr) { + case MSR_CORE_PERF_GLOBAL_STATUS: + case MSR_CORE_PERF_GLOBAL_CTRL: + case MSR_CORE_PERF_GLOBAL_OVF_CTRL: + return kvm_pmu_has_perf_global_ctrl(vcpu_to_pmu(vcpu)); + default: + break; + } return static_call(kvm_x86_pmu_msr_idx_to_pmc)(vcpu, msr) || static_call(kvm_x86_pmu_is_valid_msr)(vcpu, msr); } @@ -577,13 +580,86 @@ static void kvm_pmu_mark_pmc_in_use(struct kvm_vcpu *vcpu, u32 msr) int kvm_pmu_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info) { - return static_call(kvm_x86_pmu_get_msr)(vcpu, msr_info); + struct kvm_pmu *pmu = vcpu_to_pmu(vcpu); + u32 msr = msr_info->index; + + switch (msr) { + case MSR_CORE_PERF_GLOBAL_STATUS: + case MSR_AMD64_PERF_CNTR_GLOBAL_STATUS: + msr_info->data = pmu->global_status; + break; + case MSR_AMD64_PERF_CNTR_GLOBAL_CTL: + case MSR_CORE_PERF_GLOBAL_CTRL: + msr_info->data = pmu->global_ctrl; + break; + case MSR_AMD64_PERF_CNTR_GLOBAL_STATUS_CLR: + case MSR_CORE_PERF_GLOBAL_OVF_CTRL: + msr_info->data = 0; + break; + default: + return static_call(kvm_x86_pmu_get_msr)(vcpu, msr_info); + } + + return 0; } int kvm_pmu_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info) { - kvm_pmu_mark_pmc_in_use(vcpu, msr_info->index); - return static_call(kvm_x86_pmu_set_msr)(vcpu, msr_info); + struct kvm_pmu *pmu = vcpu_to_pmu(vcpu); + u32 msr = msr_info->index; + u64 data = msr_info->data; + u64 diff; + + /* + * Note, AMD ignores writes to reserved bits and read-only PMU MSRs, + * whereas Intel generates #GP on attempts to write reserved/RO MSRs. + */ + switch (msr) { + case MSR_CORE_PERF_GLOBAL_STATUS: + if (!msr_info->host_initiated) + return 1; /* RO MSR */ + fallthrough; + case MSR_AMD64_PERF_CNTR_GLOBAL_STATUS: + /* Per PPR, Read-only MSR. Writes are ignored. */ + if (!msr_info->host_initiated) + break; + + if (data & pmu->global_status_mask) + return 1; + + pmu->global_status = data; + break; + case MSR_AMD64_PERF_CNTR_GLOBAL_CTL: + data &= ~pmu->global_ctrl_mask; + fallthrough; + case MSR_CORE_PERF_GLOBAL_CTRL: + if (!kvm_valid_perf_global_ctrl(pmu, data)) + return 1; + + if (pmu->global_ctrl != data) { + diff = pmu->global_ctrl ^ data; + pmu->global_ctrl = data; + reprogram_counters(pmu, diff); + } + break; + case MSR_CORE_PERF_GLOBAL_OVF_CTRL: + /* + * GLOBAL_OVF_CTRL, a.k.a. GLOBAL STATUS_RESET, clears bits in + * GLOBAL_STATUS, and so the set of reserved bits is the same. + */ + if (data & pmu->global_status_mask) + return 1; + fallthrough; + case MSR_AMD64_PERF_CNTR_GLOBAL_STATUS_CLR: + if (!msr_info->host_initiated) + pmu->global_status &= ~data; + break; + default: + kvm_pmu_mark_pmc_in_use(vcpu, msr_info->index); + return static_call(kvm_x86_pmu_set_msr)(vcpu, msr_info); + } + + return 0; } /* refresh PMU settings. This function generally is called when underlying diff --git a/arch/x86/kvm/pmu.h b/arch/x86/kvm/pmu.h index 5c7bbf03b599acce82d6d62db12329aada14bde7..7d9ba301c090624c7d69bdf616f3806175eb3ead 100644 --- a/arch/x86/kvm/pmu.h +++ b/arch/x86/kvm/pmu.h @@ -20,7 +20,6 @@ struct kvm_pmu_ops { bool (*hw_event_available)(struct kvm_pmc *pmc); - bool (*pmc_is_enabled)(struct kvm_pmc *pmc); struct kvm_pmc *(*pmc_idx_to_pmc)(struct kvm_pmu *pmu, int pmc_idx); struct kvm_pmc *(*rdpmc_ecx_to_pmc)(struct kvm_vcpu *vcpu, unsigned int idx, u64 *mask); @@ -37,10 +36,25 @@ struct kvm_pmu_ops { const u64 EVENTSEL_EVENT; const int MAX_NR_GP_COUNTERS; + const int MIN_NR_GP_COUNTERS; }; void kvm_pmu_ops_update(const struct kvm_pmu_ops *pmu_ops); +static inline bool kvm_pmu_has_perf_global_ctrl(struct kvm_pmu *pmu) +{ + /* + * Architecturally, Intel's SDM states that IA32_PERF_GLOBAL_CTRL is + * supported if "CPUID.0AH: EAX[7:0] > 0", i.e. if the PMU version is + * greater than zero. However, KVM only exposes and emulates the MSR + * to/for the guest if the guest PMU supports at least "Architectural + * Performance Monitoring Version 2". + * + * AMD's version of PERF_GLOBAL_CTRL conveniently shows up with v2. + */ + return pmu->version > 1; +} + static inline u64 pmc_bitmask(struct kvm_pmc *pmc) { struct kvm_pmu *pmu = pmc_to_pmu(pmc); @@ -161,6 +175,7 @@ extern struct x86_pmu_capability kvm_pmu_cap; static inline void kvm_init_pmu_capability(const struct kvm_pmu_ops *pmu_ops) { bool is_intel = boot_cpu_data.x86_vendor == X86_VENDOR_INTEL; + int min_nr_gp_ctrs = pmu_ops->MIN_NR_GP_COUNTERS; /* * Hybrid PMUs don't play nice with virtualization without careful @@ -175,11 +190,15 @@ static inline void kvm_init_pmu_capability(const struct kvm_pmu_ops *pmu_ops) perf_get_x86_pmu_capability(&kvm_pmu_cap); /* - * For Intel, only support guest architectural pmu - * on a host with architectural pmu. + * WARN if perf did NOT disable hardware PMU if the number of + * architecturally required GP counters aren't present, i.e. if + * there are a non-zero number of counters, but fewer than what + * is architecturally required. */ - if ((is_intel && !kvm_pmu_cap.version) || - !kvm_pmu_cap.num_counters_gp) + if (!kvm_pmu_cap.num_counters_gp || + WARN_ON_ONCE(kvm_pmu_cap.num_counters_gp < min_nr_gp_ctrs)) + enable_pmu = false; + else if (is_intel && !kvm_pmu_cap.version) enable_pmu = false; } @@ -201,6 +220,33 @@ static inline void kvm_pmu_request_counter_reprogram(struct kvm_pmc *pmc) kvm_make_request(KVM_REQ_PMU, pmc->vcpu); } +static inline void reprogram_counters(struct kvm_pmu *pmu, u64 diff) +{ + int bit; + + if (!diff) + return; + + for_each_set_bit(bit, (unsigned long *)&diff, X86_PMC_IDX_MAX) + set_bit(bit, pmu->reprogram_pmi); + kvm_make_request(KVM_REQ_PMU, pmu_to_vcpu(pmu)); +} + +/* + * Check if a PMC is enabled by comparing it against global_ctrl bits. + * + * If the vPMU doesn't have global_ctrl MSR, all vPMCs are enabled. + */ +static inline bool pmc_is_globally_enabled(struct kvm_pmc *pmc) +{ + struct kvm_pmu *pmu = pmc_to_pmu(pmc); + + if (!kvm_pmu_has_perf_global_ctrl(pmu)) + return true; + + return test_bit(pmc->idx, (unsigned long *)&pmu->global_ctrl); +} + void kvm_pmu_deliver_pmi(struct kvm_vcpu *vcpu); void kvm_pmu_handle_event(struct kvm_vcpu *vcpu); int kvm_pmu_rdpmc(struct kvm_vcpu *vcpu, unsigned pmc, u64 *data); diff --git a/arch/x86/kvm/reverse_cpuid.h b/arch/x86/kvm/reverse_cpuid.h index a5717282bb9ced6945c047913ca273ca4c9ca482..56cbdb24400ae13a99356dcbf1dd81ed54dda95e 100644 --- a/arch/x86/kvm/reverse_cpuid.h +++ b/arch/x86/kvm/reverse_cpuid.h @@ -15,6 +15,7 @@ enum kvm_only_cpuid_leafs { CPUID_12_EAX = NCAPINTS, CPUID_7_1_EDX, CPUID_8000_0007_EDX, + CPUID_8000_0022_EAX, NR_KVM_CPU_CAPS, NKVMCAPINTS = NR_KVM_CPU_CAPS - NCAPINTS, @@ -47,6 +48,9 @@ enum kvm_only_cpuid_leafs { /* CPUID level 0x80000007 (EDX). */ #define KVM_X86_FEATURE_CONSTANT_TSC KVM_X86_FEATURE(CPUID_8000_0007_EDX, 8) +/* CPUID level 0x80000022 (EAX) */ +#define KVM_X86_FEATURE_PERFMON_V2 KVM_X86_FEATURE(CPUID_8000_0022_EAX, 0) + struct cpuid_reg { u32 function; u32 index; @@ -74,6 +78,7 @@ static const struct cpuid_reg reverse_cpuid[] = { [CPUID_7_1_EDX] = { 7, 1, CPUID_EDX}, [CPUID_8000_0007_EDX] = {0x80000007, 0, CPUID_EDX}, [CPUID_8000_0021_EAX] = {0x80000021, 0, CPUID_EAX}, + [CPUID_8000_0022_EAX] = {0x80000022, 0, CPUID_EAX}, }; /* @@ -108,6 +113,8 @@ static __always_inline u32 __feature_translate(int x86_feature) return KVM_X86_FEATURE_SGX_EDECCSSA; else if (x86_feature == X86_FEATURE_CONSTANT_TSC) return KVM_X86_FEATURE_CONSTANT_TSC; + else if (x86_feature == X86_FEATURE_PERFMON_V2) + return KVM_X86_FEATURE_PERFMON_V2; return x86_feature; } diff --git a/arch/x86/kvm/svm/pmu.c b/arch/x86/kvm/svm/pmu.c index 5fa939e411d8c49cf8dd22189649524b4e7ece2c..cef5a3d0abd09664fe58174689aa633221be948d 100644 --- a/arch/x86/kvm/svm/pmu.c +++ b/arch/x86/kvm/svm/pmu.c @@ -78,14 +78,6 @@ static bool amd_hw_event_available(struct kvm_pmc *pmc) return true; } -/* check if a PMC is enabled by comparing it against global_ctrl bits. Because - * AMD CPU doesn't have global_ctrl MSR, all PMCs are enabled (return TRUE). - */ -static bool amd_pmc_is_enabled(struct kvm_pmc *pmc) -{ - return true; -} - static bool amd_is_valid_rdpmc_ecx(struct kvm_vcpu *vcpu, unsigned int idx) { struct kvm_pmu *pmu = vcpu_to_pmu(vcpu); @@ -102,12 +94,6 @@ static struct kvm_pmc *amd_rdpmc_ecx_to_pmc(struct kvm_vcpu *vcpu, return amd_pmc_idx_to_pmc(vcpu_to_pmu(vcpu), idx & ~(3u << 30)); } -static bool amd_is_valid_msr(struct kvm_vcpu *vcpu, u32 msr) -{ - /* All MSRs refer to exactly one PMC, so msr_idx_to_pmc is enough. */ - return false; -} - static struct kvm_pmc *amd_msr_idx_to_pmc(struct kvm_vcpu *vcpu, u32 msr) { struct kvm_pmu *pmu = vcpu_to_pmu(vcpu); @@ -119,6 +105,29 @@ static struct kvm_pmc *amd_msr_idx_to_pmc(struct kvm_vcpu *vcpu, u32 msr) return pmc; } +static bool amd_is_valid_msr(struct kvm_vcpu *vcpu, u32 msr) +{ + struct kvm_pmu *pmu = vcpu_to_pmu(vcpu); + + switch (msr) { + case MSR_K7_EVNTSEL0 ... MSR_K7_PERFCTR3: + return pmu->version > 0; + case MSR_F15H_PERF_CTL0 ... MSR_F15H_PERF_CTR5: + return guest_cpuid_has(vcpu, X86_FEATURE_PERFCTR_CORE); + case MSR_AMD64_PERF_CNTR_GLOBAL_STATUS: + case MSR_AMD64_PERF_CNTR_GLOBAL_CTL: + case MSR_AMD64_PERF_CNTR_GLOBAL_STATUS_CLR: + return pmu->version > 1; + default: + if (msr > MSR_F15H_PERF_CTR5 && + msr < MSR_F15H_PERF_CTL0 + 2 * pmu->nr_arch_gp_counters) + return pmu->version > 1; + break; + } + + return amd_msr_idx_to_pmc(vcpu, msr); +} + static int amd_pmu_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info) { struct kvm_pmu *pmu = vcpu_to_pmu(vcpu); @@ -172,20 +181,39 @@ static int amd_pmu_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info) static void amd_pmu_refresh(struct kvm_vcpu *vcpu) { struct kvm_pmu *pmu = vcpu_to_pmu(vcpu); + union cpuid_0x80000022_ebx ebx; - if (guest_cpuid_has(vcpu, X86_FEATURE_PERFCTR_CORE)) + pmu->version = 1; + if (guest_cpuid_has(vcpu, X86_FEATURE_PERFMON_V2)) { + pmu->version = 2; + /* + * Note, PERFMON_V2 is also in 0x80000022.0x0, i.e. the guest + * CPUID entry is guaranteed to be non-NULL. + */ + BUILD_BUG_ON(x86_feature_cpuid(X86_FEATURE_PERFMON_V2).function != 0x80000022 || + x86_feature_cpuid(X86_FEATURE_PERFMON_V2).index); + ebx.full = kvm_find_cpuid_entry_index(vcpu, 0x80000022, 0)->ebx; + pmu->nr_arch_gp_counters = ebx.split.num_core_pmc; + } else if (guest_cpuid_has(vcpu, X86_FEATURE_PERFCTR_CORE)) { pmu->nr_arch_gp_counters = AMD64_NUM_COUNTERS_CORE; - else + } else { pmu->nr_arch_gp_counters = AMD64_NUM_COUNTERS; + } + + pmu->nr_arch_gp_counters = min_t(unsigned int, pmu->nr_arch_gp_counters, + kvm_pmu_cap.num_counters_gp); + + if (pmu->version > 1) { + pmu->global_ctrl_mask = ~((1ull << pmu->nr_arch_gp_counters) - 1); + pmu->global_status_mask = pmu->global_ctrl_mask; + } pmu->counter_bitmask[KVM_PMC_GP] = ((u64)1 << 48) - 1; pmu->reserved_bits = 0xfffffff000280000ull; pmu->raw_event_mask = AMD64_RAW_EVENT_MASK; - pmu->version = 1; /* not applicable to AMD; but clean them to prevent any fall out */ pmu->counter_bitmask[KVM_PMC_FIXED] = 0; pmu->nr_arch_fixed_counters = 0; - pmu->global_status = 0; bitmap_set(pmu->all_valid_pmc_idx, 0, pmu->nr_arch_gp_counters); } @@ -216,11 +244,12 @@ static void amd_pmu_reset(struct kvm_vcpu *vcpu) pmc_stop_counter(pmc); pmc->counter = pmc->prev_counter = pmc->eventsel = 0; } + + pmu->global_ctrl = pmu->global_status = 0; } struct kvm_pmu_ops amd_pmu_ops __initdata = { .hw_event_available = amd_hw_event_available, - .pmc_is_enabled = amd_pmc_is_enabled, .pmc_idx_to_pmc = amd_pmc_idx_to_pmc, .rdpmc_ecx_to_pmc = amd_rdpmc_ecx_to_pmc, .msr_idx_to_pmc = amd_msr_idx_to_pmc, @@ -233,4 +262,5 @@ struct kvm_pmu_ops amd_pmu_ops __initdata = { .reset = amd_pmu_reset, .EVENTSEL_EVENT = AMD64_EVENTSEL_EVENT, .MAX_NR_GP_COUNTERS = KVM_AMD_PMC_MAX_GENERIC, + .MIN_NR_GP_COUNTERS = AMD64_NUM_COUNTERS, }; diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c index 69ae5e1b31207f1d6ac115fe7b594ace375930c2..07756b7348ae8edec8c5f0e0f41070eb2998a7e8 100644 --- a/arch/x86/kvm/svm/sev.c +++ b/arch/x86/kvm/svm/sev.c @@ -2216,10 +2216,7 @@ void __init sev_hardware_setup(void) } sev_asid_count = max_sev_asid - min_sev_asid + 1; - if (misc_cg_set_capacity(MISC_CG_RES_SEV, sev_asid_count)) - goto out; - - pr_info("SEV supported: %u ASIDs\n", sev_asid_count); + WARN_ON_ONCE(misc_cg_set_capacity(MISC_CG_RES_SEV, sev_asid_count)); sev_supported = true; /* SEV-ES support requested? */ @@ -2244,13 +2241,19 @@ void __init sev_hardware_setup(void) goto out; sev_es_asid_count = min_sev_asid - 1; - if (misc_cg_set_capacity(MISC_CG_RES_SEV_ES, sev_es_asid_count)) - goto out; - - pr_info("SEV-ES supported: %u ASIDs\n", sev_es_asid_count); + WARN_ON_ONCE(misc_cg_set_capacity(MISC_CG_RES_SEV_ES, sev_es_asid_count)); sev_es_supported = true; out: + if (boot_cpu_has(X86_FEATURE_SEV)) + pr_info("SEV %s (ASIDs %u - %u)\n", + sev_supported ? "enabled" : "disabled", + min_sev_asid, max_sev_asid); + if (boot_cpu_has(X86_FEATURE_SEV_ES)) + pr_info("SEV-ES %s (ASIDs %u - %u)\n", + sev_es_supported ? "enabled" : "disabled", + min_sev_asid > 1 ? 1 : 0, min_sev_asid - 1); + sev_enabled = sev_supported; sev_es_enabled = sev_es_supported; #endif diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c index 54089f990c8f83292eecede362b19269c8756900..d381ad4245542c2d30805433fe2a381f2f5cddf0 100644 --- a/arch/x86/kvm/svm/svm.c +++ b/arch/x86/kvm/svm/svm.c @@ -244,15 +244,6 @@ static u8 rsm_ins_bytes[] = "\x0f\xaa"; static unsigned long iopm_base; -struct kvm_ldttss_desc { - u16 limit0; - u16 base0; - unsigned base1:8, type:5, dpl:2, p:1; - unsigned limit1:4, zero0:3, g:1, base2:8; - u32 base3; - u32 zero1; -} __attribute__((packed)); - DEFINE_PER_CPU(struct svm_cpu_data, svm_data); /* @@ -588,7 +579,6 @@ static int svm_hardware_enable(void) struct svm_cpu_data *sd; uint64_t efer; - struct desc_struct *gdt; int me = raw_smp_processor_id(); rdmsrl(MSR_EFER, efer); @@ -601,9 +591,6 @@ static int svm_hardware_enable(void) sd->next_asid = sd->max_asid + 1; sd->min_asid = max_sev_asid + 1; - gdt = get_current_gdt_rw(); - sd->tss_desc = (struct kvm_ldttss_desc *)(gdt + GDT_ENTRY_TSS); - wrmsrl(MSR_EFER, efer | EFER_SVME); wrmsrl(MSR_VM_HSAVE_PA, sd->save_area_pa); @@ -752,7 +739,7 @@ static bool msr_write_intercepted(struct kvm_vcpu *vcpu, u32 msr) BUG_ON(offset == MSR_INVALID); - return !!test_bit(bit_write, &tmp); + return test_bit(bit_write, &tmp); } static void set_msr_interception_bitmap(struct kvm_vcpu *vcpu, u32 *msrpm, @@ -2939,9 +2926,10 @@ static int svm_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr) break; case MSR_IA32_CR_PAT: - if (!kvm_mtrr_valid(vcpu, MSR_IA32_CR_PAT, data)) - return 1; - vcpu->arch.pat = data; + ret = kvm_set_msr_common(vcpu, msr); + if (ret) + break; + svm->vmcb01.ptr->save.g_pat = data; if (is_guest_mode(vcpu)) nested_vmcb02_compute_g_pat(svm); @@ -3418,8 +3406,6 @@ static int svm_handle_exit(struct kvm_vcpu *vcpu, fastpath_t exit_fastpath) struct kvm_run *kvm_run = vcpu->run; u32 exit_code = svm->vmcb->control.exit_code; - trace_kvm_exit(vcpu, KVM_ISA_SVM); - /* SEV-ES guests must use the CR write traps to track CR registers. */ if (!sev_es_guest(vcpu->kvm)) { if (!svm_is_intercept(svm, INTERCEPT_CR0_WRITE)) @@ -3457,14 +3443,6 @@ static int svm_handle_exit(struct kvm_vcpu *vcpu, fastpath_t exit_fastpath) return svm_invoke_exit_handler(vcpu, exit_code); } -static void reload_tss(struct kvm_vcpu *vcpu) -{ - struct svm_cpu_data *sd = per_cpu_ptr(&svm_data, vcpu->cpu); - - sd->tss_desc->type = 9; /* available 32/64-bit TSS */ - load_TR_desc(); -} - static void pre_svm_run(struct kvm_vcpu *vcpu) { struct svm_cpu_data *sd = per_cpu_ptr(&svm_data, vcpu->cpu); @@ -4099,9 +4077,6 @@ static __no_kcsan fastpath_t svm_vcpu_run(struct kvm_vcpu *vcpu) svm_vcpu_enter_exit(vcpu, spec_ctrl_intercepted); - if (!sev_es_guest(vcpu->kvm)) - reload_tss(vcpu); - if (!static_cpu_has(X86_FEATURE_V_SPEC_CTRL)) x86_spec_ctrl_restore_host(svm->virt_spec_ctrl); @@ -4156,6 +4131,8 @@ static __no_kcsan fastpath_t svm_vcpu_run(struct kvm_vcpu *vcpu) SVM_EXIT_EXCP_BASE + MC_VECTOR)) svm_handle_mce(vcpu); + trace_kvm_exit(vcpu, KVM_ISA_SVM); + svm_complete_interrupts(vcpu); if (is_guest_mode(vcpu)) @@ -5025,9 +5002,22 @@ static __init void svm_set_cpu_caps(void) boot_cpu_has(X86_FEATURE_AMD_SSBD)) kvm_cpu_cap_set(X86_FEATURE_VIRT_SSBD); - /* AMD PMU PERFCTR_CORE CPUID */ - if (enable_pmu && boot_cpu_has(X86_FEATURE_PERFCTR_CORE)) - kvm_cpu_cap_set(X86_FEATURE_PERFCTR_CORE); + if (enable_pmu) { + /* + * Enumerate support for PERFCTR_CORE if and only if KVM has + * access to enough counters to virtualize "core" support, + * otherwise limit vPMU support to the legacy number of counters. + */ + if (kvm_pmu_cap.num_counters_gp < AMD64_NUM_COUNTERS_CORE) + kvm_pmu_cap.num_counters_gp = min(AMD64_NUM_COUNTERS, + kvm_pmu_cap.num_counters_gp); + else + kvm_cpu_cap_check_and_set(X86_FEATURE_PERFCTR_CORE); + + if (kvm_pmu_cap.version != 2 || + !kvm_cpu_cap_has(X86_FEATURE_PERFCTR_CORE)) + kvm_cpu_cap_clear(X86_FEATURE_PERFMON_V2); + } /* CPUID 0x8000001F (SME/SEV features) */ sev_set_cpu_caps(); diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h index f44751dd8d5d9921ade844887b694d6ede0140af..18af7e712a5ae73d93cff78255eeb3fc2d0c5bb1 100644 --- a/arch/x86/kvm/svm/svm.h +++ b/arch/x86/kvm/svm/svm.h @@ -303,7 +303,6 @@ struct svm_cpu_data { u32 max_asid; u32 next_asid; u32 min_asid; - struct kvm_ldttss_desc *tss_desc; struct page *save_area; unsigned long save_area_pa; diff --git a/arch/x86/kvm/vmx/capabilities.h b/arch/x86/kvm/vmx/capabilities.h index 45162c1bcd8f5cff68d026140cd4c03efe224955..d0abee35d7ba48fd134d4c52c262e1e9471eb4ae 100644 --- a/arch/x86/kvm/vmx/capabilities.h +++ b/arch/x86/kvm/vmx/capabilities.h @@ -152,8 +152,8 @@ static inline bool cpu_has_vmx_ept(void) static inline bool vmx_umip_emulated(void) { - return vmcs_config.cpu_based_2nd_exec_ctrl & - SECONDARY_EXEC_DESC; + return !boot_cpu_has(X86_FEATURE_UMIP) && + (vmcs_config.cpu_based_2nd_exec_ctrl & SECONDARY_EXEC_DESC); } static inline bool cpu_has_vmx_rdtscp(void) diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c index e35cf0bd0df9cd421c5de275d19624eaf37670b8..516391cc0d64fb9689d17fea0d04903c13abe66a 100644 --- a/arch/x86/kvm/vmx/nested.c +++ b/arch/x86/kvm/vmx/nested.c @@ -2328,8 +2328,7 @@ static void prepare_vmcs02_early(struct vcpu_vmx *vmx, struct loaded_vmcs *vmcs0 * Preset *DT exiting when emulating UMIP, so that vmx_set_cr4() * will not have to rewrite the controls just for this bit. */ - if (!boot_cpu_has(X86_FEATURE_UMIP) && vmx_umip_emulated() && - (vmcs12->guest_cr4 & X86_CR4_UMIP)) + if (vmx_umip_emulated() && (vmcs12->guest_cr4 & X86_CR4_UMIP)) exec_control |= SECONDARY_EXEC_DESC; if (exec_control & SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY) @@ -2649,7 +2648,7 @@ static int prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12, } if ((vmcs12->vm_entry_controls & VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL) && - intel_pmu_has_perf_global_ctrl(vcpu_to_pmu(vcpu)) && + kvm_pmu_has_perf_global_ctrl(vcpu_to_pmu(vcpu)) && WARN_ON_ONCE(kvm_set_msr(vcpu, MSR_CORE_PERF_GLOBAL_CTRL, vmcs12->guest_ia32_perf_global_ctrl))) { *entry_failure_code = ENTRY_FAIL_DEFAULT; @@ -4524,7 +4523,7 @@ static void load_vmcs12_host_state(struct kvm_vcpu *vcpu, vcpu->arch.pat = vmcs12->host_ia32_pat; } if ((vmcs12->vm_exit_controls & VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL) && - intel_pmu_has_perf_global_ctrl(vcpu_to_pmu(vcpu))) + kvm_pmu_has_perf_global_ctrl(vcpu_to_pmu(vcpu))) WARN_ON_ONCE(kvm_set_msr(vcpu, MSR_CORE_PERF_GLOBAL_CTRL, vmcs12->host_ia32_perf_global_ctrl)); diff --git a/arch/x86/kvm/vmx/pmu_intel.c b/arch/x86/kvm/vmx/pmu_intel.c index 741efe2c497bafe05559eb681b7d3756d483adf6..80c769c58a876530674e823434bcbf627d19d3c6 100644 --- a/arch/x86/kvm/vmx/pmu_intel.c +++ b/arch/x86/kvm/vmx/pmu_intel.c @@ -73,18 +73,6 @@ static struct kvm_pmc *intel_pmc_idx_to_pmc(struct kvm_pmu *pmu, int pmc_idx) } } -static void reprogram_counters(struct kvm_pmu *pmu, u64 diff) -{ - int bit; - - if (!diff) - return; - - for_each_set_bit(bit, (unsigned long *)&diff, X86_PMC_IDX_MAX) - set_bit(bit, pmu->reprogram_pmi); - kvm_make_request(KVM_REQ_PMU, pmu_to_vcpu(pmu)); -} - static bool intel_hw_event_available(struct kvm_pmc *pmc) { struct kvm_pmu *pmu = pmc_to_pmu(pmc); @@ -107,17 +95,6 @@ static bool intel_hw_event_available(struct kvm_pmc *pmc) return true; } -/* check if a PMC is enabled by comparing it with globl_ctrl bits. */ -static bool intel_pmc_is_enabled(struct kvm_pmc *pmc) -{ - struct kvm_pmu *pmu = pmc_to_pmu(pmc); - - if (!intel_pmu_has_perf_global_ctrl(pmu)) - return true; - - return test_bit(pmc->idx, (unsigned long *)&pmu->global_ctrl); -} - static bool intel_is_valid_rdpmc_ecx(struct kvm_vcpu *vcpu, unsigned int idx) { struct kvm_pmu *pmu = vcpu_to_pmu(vcpu); @@ -198,11 +175,7 @@ static bool intel_is_valid_msr(struct kvm_vcpu *vcpu, u32 msr) switch (msr) { case MSR_CORE_PERF_FIXED_CTR_CTRL: - case MSR_CORE_PERF_GLOBAL_STATUS: - case MSR_CORE_PERF_GLOBAL_CTRL: - case MSR_CORE_PERF_GLOBAL_OVF_CTRL: - return intel_pmu_has_perf_global_ctrl(pmu); - break; + return kvm_pmu_has_perf_global_ctrl(pmu); case MSR_IA32_PEBS_ENABLE: ret = vcpu_get_perf_capabilities(vcpu) & PERF_CAP_PEBS_FORMAT; break; @@ -352,15 +325,6 @@ static int intel_pmu_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info) case MSR_CORE_PERF_FIXED_CTR_CTRL: msr_info->data = pmu->fixed_ctr_ctrl; break; - case MSR_CORE_PERF_GLOBAL_STATUS: - msr_info->data = pmu->global_status; - break; - case MSR_CORE_PERF_GLOBAL_CTRL: - msr_info->data = pmu->global_ctrl; - break; - case MSR_CORE_PERF_GLOBAL_OVF_CTRL: - msr_info->data = 0; - break; case MSR_IA32_PEBS_ENABLE: msr_info->data = pmu->pebs_enable; break; @@ -410,29 +374,6 @@ static int intel_pmu_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info) if (pmu->fixed_ctr_ctrl != data) reprogram_fixed_counters(pmu, data); break; - case MSR_CORE_PERF_GLOBAL_STATUS: - if (!msr_info->host_initiated) - return 1; /* RO MSR */ - - pmu->global_status = data; - break; - case MSR_CORE_PERF_GLOBAL_CTRL: - if (!kvm_valid_perf_global_ctrl(pmu, data)) - return 1; - - if (pmu->global_ctrl != data) { - diff = pmu->global_ctrl ^ data; - pmu->global_ctrl = data; - reprogram_counters(pmu, diff); - } - break; - case MSR_CORE_PERF_GLOBAL_OVF_CTRL: - if (data & pmu->global_ovf_ctrl_mask) - return 1; - - if (!msr_info->host_initiated) - pmu->global_status &= ~data; - break; case MSR_IA32_PEBS_ENABLE: if (data & pmu->pebs_enable_mask) return 1; @@ -444,8 +385,6 @@ static int intel_pmu_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info) } break; case MSR_IA32_DS_AREA: - if (msr_info->host_initiated && data && !guest_cpuid_has(vcpu, X86_FEATURE_DS)) - return 1; if (is_noncanonical_address(data, vcpu)) return 1; @@ -531,7 +470,7 @@ static void intel_pmu_refresh(struct kvm_vcpu *vcpu) pmu->reserved_bits = 0xffffffff00200000ull; pmu->raw_event_mask = X86_RAW_EVENT_MASK; pmu->global_ctrl_mask = ~0ull; - pmu->global_ovf_ctrl_mask = ~0ull; + pmu->global_status_mask = ~0ull; pmu->fixed_ctr_ctrl_mask = ~0ull; pmu->pebs_enable_mask = ~0ull; pmu->pebs_data_cfg_mask = ~0ull; @@ -585,11 +524,17 @@ static void intel_pmu_refresh(struct kvm_vcpu *vcpu) counter_mask = ~(((1ull << pmu->nr_arch_gp_counters) - 1) | (((1ull << pmu->nr_arch_fixed_counters) - 1) << INTEL_PMC_IDX_FIXED)); pmu->global_ctrl_mask = counter_mask; - pmu->global_ovf_ctrl_mask = pmu->global_ctrl_mask + + /* + * GLOBAL_STATUS and GLOBAL_OVF_CONTROL (a.k.a. GLOBAL_STATUS_RESET) + * share reserved bit definitions. The kernel just happens to use + * OVF_CTRL for the names. + */ + pmu->global_status_mask = pmu->global_ctrl_mask & ~(MSR_CORE_PERF_GLOBAL_OVF_CTRL_OVF_BUF | MSR_CORE_PERF_GLOBAL_OVF_CTRL_COND_CHGD); if (vmx_pt_mode_is_host_guest()) - pmu->global_ovf_ctrl_mask &= + pmu->global_status_mask &= ~MSR_CORE_PERF_GLOBAL_OVF_CTRL_TRACE_TOPA_PMI; entry = kvm_find_cpuid_entry_index(vcpu, 7, 0); @@ -801,7 +746,7 @@ void intel_pmu_cross_mapped_check(struct kvm_pmu *pmu) pmc = intel_pmc_idx_to_pmc(pmu, bit); if (!pmc || !pmc_speculative_in_use(pmc) || - !intel_pmc_is_enabled(pmc) || !pmc->perf_event) + !pmc_is_globally_enabled(pmc) || !pmc->perf_event) continue; /* @@ -816,7 +761,6 @@ void intel_pmu_cross_mapped_check(struct kvm_pmu *pmu) struct kvm_pmu_ops intel_pmu_ops __initdata = { .hw_event_available = intel_hw_event_available, - .pmc_is_enabled = intel_pmc_is_enabled, .pmc_idx_to_pmc = intel_pmc_idx_to_pmc, .rdpmc_ecx_to_pmc = intel_rdpmc_ecx_to_pmc, .msr_idx_to_pmc = intel_msr_idx_to_pmc, @@ -831,4 +775,5 @@ struct kvm_pmu_ops intel_pmu_ops __initdata = { .cleanup = intel_pmu_cleanup, .EVENTSEL_EVENT = ARCH_PERFMON_EVENTSEL_EVENT, .MAX_NR_GP_COUNTERS = KVM_INTEL_PMC_MAX_GENERIC, + .MIN_NR_GP_COUNTERS = 1, }; diff --git a/arch/x86/kvm/vmx/sgx.c b/arch/x86/kvm/vmx/sgx.c index 2261b684a7d4475ab78107114aa5cb8dd5b2179e..3e822e58249753c5ff267b5ce4f69e2ede9a00c9 100644 --- a/arch/x86/kvm/vmx/sgx.c +++ b/arch/x86/kvm/vmx/sgx.c @@ -357,11 +357,12 @@ static int handle_encls_einit(struct kvm_vcpu *vcpu) static inline bool encls_leaf_enabled_in_guest(struct kvm_vcpu *vcpu, u32 leaf) { - if (!enable_sgx || !guest_cpuid_has(vcpu, X86_FEATURE_SGX)) - return false; - + /* + * ENCLS generates a #UD if SGX1 isn't supported, i.e. this point will + * be reached if and only if the SGX1 leafs are enabled. + */ if (leaf >= ECREATE && leaf <= ETRACK) - return guest_cpuid_has(vcpu, X86_FEATURE_SGX1); + return true; if (leaf >= EAUG && leaf <= EMODT) return guest_cpuid_has(vcpu, X86_FEATURE_SGX2); @@ -380,9 +381,11 @@ int handle_encls(struct kvm_vcpu *vcpu) { u32 leaf = (u32)kvm_rax_read(vcpu); - if (!encls_leaf_enabled_in_guest(vcpu, leaf)) { + if (!enable_sgx || !guest_cpuid_has(vcpu, X86_FEATURE_SGX) || + !guest_cpuid_has(vcpu, X86_FEATURE_SGX1)) { kvm_queue_exception(vcpu, UD_VECTOR); - } else if (!sgx_enabled_in_guest_bios(vcpu)) { + } else if (!encls_leaf_enabled_in_guest(vcpu, leaf) || + !sgx_enabled_in_guest_bios(vcpu) || !is_paging(vcpu)) { kvm_inject_gp(vcpu, 0); } else { if (leaf == ECREATE) diff --git a/arch/x86/kvm/vmx/vmenter.S b/arch/x86/kvm/vmx/vmenter.S index 631fd7da2bc36fc7b86c1d04500d168f5cc9b8de..07e927d4d099c95dce218147ba6a9bb2905918ac 100644 --- a/arch/x86/kvm/vmx/vmenter.S +++ b/arch/x86/kvm/vmx/vmenter.S @@ -187,7 +187,7 @@ SYM_FUNC_START(__vmx_vcpu_run) _ASM_EXTABLE(.Lvmresume, .Lfixup) _ASM_EXTABLE(.Lvmlaunch, .Lfixup) -SYM_INNER_LABEL(vmx_vmexit, SYM_L_GLOBAL) +SYM_INNER_LABEL_ALIGN(vmx_vmexit, SYM_L_GLOBAL) /* Restore unwind state from before the VMRESUME/VMLAUNCH. */ UNWIND_HINT_RESTORE diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index 44fb619803b8952f14853aefb6055f988fb8a7fa..0ecf4be2c6af0e11de6b2ea993c29c3b1b00d7c0 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -2287,19 +2287,16 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info) return 1; goto find_uret_msr; case MSR_IA32_CR_PAT: - if (!kvm_pat_valid(data)) - return 1; + ret = kvm_set_msr_common(vcpu, msr_info); + if (ret) + break; if (is_guest_mode(vcpu) && get_vmcs12(vcpu)->vm_exit_controls & VM_EXIT_SAVE_IA32_PAT) get_vmcs12(vcpu)->guest_ia32_pat = data; - if (vmcs_config.vmentry_ctrl & VM_ENTRY_LOAD_IA32_PAT) { + if (vmcs_config.vmentry_ctrl & VM_ENTRY_LOAD_IA32_PAT) vmcs_write64(GUEST_IA32_PAT, data); - vcpu->arch.pat = data; - break; - } - ret = kvm_set_msr_common(vcpu, msr_info); break; case MSR_IA32_MCG_EXT_CTL: if ((!msr_info->host_initiated && @@ -3387,15 +3384,15 @@ static bool vmx_is_valid_cr4(struct kvm_vcpu *vcpu, unsigned long cr4) void vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4) { - unsigned long old_cr4 = vcpu->arch.cr4; + unsigned long old_cr4 = kvm_read_cr4(vcpu); struct vcpu_vmx *vmx = to_vmx(vcpu); + unsigned long hw_cr4; + /* * Pass through host's Machine Check Enable value to hw_cr4, which * is in force while we are in guest mode. Do not let guests control * this bit, even if host CR4.MCE == 0. */ - unsigned long hw_cr4; - hw_cr4 = (cr4_read_shadow() & X86_CR4_MCE) | (cr4 & ~X86_CR4_MCE); if (is_unrestricted_guest(vcpu)) hw_cr4 |= KVM_VM_CR4_ALWAYS_ON_UNRESTRICTED_GUEST; @@ -3404,7 +3401,7 @@ void vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4) else hw_cr4 |= KVM_PMODE_VM_CR4_ALWAYS_ON; - if (!boot_cpu_has(X86_FEATURE_UMIP) && vmx_umip_emulated()) { + if (vmx_umip_emulated()) { if (cr4 & X86_CR4_UMIP) { secondary_exec_controls_setbit(vmx, SECONDARY_EXEC_DESC); hw_cr4 &= ~X86_CR4_UMIP; @@ -5402,7 +5399,13 @@ static int handle_set_cr4(struct kvm_vcpu *vcpu, unsigned long val) static int handle_desc(struct kvm_vcpu *vcpu) { - WARN_ON(!(vcpu->arch.cr4 & X86_CR4_UMIP)); + /* + * UMIP emulation relies on intercepting writes to CR4.UMIP, i.e. this + * and other code needs to be updated if UMIP can be guest owned. + */ + BUILD_BUG_ON(KVM_POSSIBLE_CR4_GUEST_BITS & X86_CR4_UMIP); + + WARN_ON_ONCE(!kvm_is_cr4_bit_set(vcpu, X86_CR4_UMIP)); return kvm_emulate_instruction(vcpu, 0); } @@ -6708,7 +6711,12 @@ void vmx_set_virtual_apic_mode(struct kvm_vcpu *vcpu) static void vmx_set_apic_access_page_addr(struct kvm_vcpu *vcpu) { - struct page *page; + const gfn_t gfn = APIC_DEFAULT_PHYS_BASE >> PAGE_SHIFT; + struct kvm *kvm = vcpu->kvm; + struct kvm_memslots *slots = kvm_memslots(kvm); + struct kvm_memory_slot *slot; + unsigned long mmu_seq; + kvm_pfn_t pfn; /* Defer reload until vmcs01 is the current VMCS. */ if (is_guest_mode(vcpu)) { @@ -6720,18 +6728,53 @@ static void vmx_set_apic_access_page_addr(struct kvm_vcpu *vcpu) SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES)) return; - page = gfn_to_page(vcpu->kvm, APIC_DEFAULT_PHYS_BASE >> PAGE_SHIFT); - if (is_error_page(page)) + /* + * Grab the memslot so that the hva lookup for the mmu_notifier retry + * is guaranteed to use the same memslot as the pfn lookup, i.e. rely + * on the pfn lookup's validation of the memslot to ensure a valid hva + * is used for the retry check. + */ + slot = id_to_memslot(slots, APIC_ACCESS_PAGE_PRIVATE_MEMSLOT); + if (!slot || slot->flags & KVM_MEMSLOT_INVALID) return; - vmcs_write64(APIC_ACCESS_ADDR, page_to_phys(page)); + /* + * Ensure that the mmu_notifier sequence count is read before KVM + * retrieves the pfn from the primary MMU. Note, the memslot is + * protected by SRCU, not the mmu_notifier. Pairs with the smp_wmb() + * in kvm_mmu_invalidate_end(). + */ + mmu_seq = kvm->mmu_invalidate_seq; + smp_rmb(); + + /* + * No need to retry if the memslot does not exist or is invalid. KVM + * controls the APIC-access page memslot, and only deletes the memslot + * if APICv is permanently inhibited, i.e. the memslot won't reappear. + */ + pfn = gfn_to_pfn_memslot(slot, gfn); + if (is_error_noslot_pfn(pfn)) + return; + + read_lock(&vcpu->kvm->mmu_lock); + if (mmu_invalidate_retry_hva(kvm, mmu_seq, + gfn_to_hva_memslot(slot, gfn))) { + kvm_make_request(KVM_REQ_APIC_PAGE_RELOAD, vcpu); + read_unlock(&vcpu->kvm->mmu_lock); + goto out; + } + + vmcs_write64(APIC_ACCESS_ADDR, pfn_to_hpa(pfn)); + read_unlock(&vcpu->kvm->mmu_lock); + vmx_flush_tlb_current(vcpu); +out: /* * Do not pin apic access page in memory, the MMU notifier * will call us again if it is migrated or swapped out. */ - put_page(page); + kvm_release_pfn_clean(pfn); } static void vmx_hwapic_isr_update(int max_isr) diff --git a/arch/x86/kvm/vmx/vmx.h b/arch/x86/kvm/vmx/vmx.h index 9e66531861cf92f532ac555a8bc70970e2358f5a..32384ba3849949c2b04f195b7a37c47c7fcc7b43 100644 --- a/arch/x86/kvm/vmx/vmx.h +++ b/arch/x86/kvm/vmx/vmx.h @@ -93,18 +93,6 @@ union vmx_exit_reason { u32 full; }; -static inline bool intel_pmu_has_perf_global_ctrl(struct kvm_pmu *pmu) -{ - /* - * Architecturally, Intel's SDM states that IA32_PERF_GLOBAL_CTRL is - * supported if "CPUID.0AH: EAX[7:0] > 0", i.e. if the PMU version is - * greater than zero. However, KVM only exposes and emulates the MSR - * to/for the guest if the guest PMU supports at least "Architectural - * Performance Monitoring Version 2". - */ - return pmu->version > 1; -} - struct lbr_desc { /* Basic info about guest LBR records. */ struct x86_pmu_lbr records; diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 04b57a336b34e5fc5224c47e5e8f23f794e98729..a6b9bea62fb8ac4498cccc7686196f6b63a8c1e9 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -1017,13 +1017,11 @@ void kvm_load_guest_xsave_state(struct kvm_vcpu *vcpu) wrmsrl(MSR_IA32_XSS, vcpu->arch.ia32_xss); } -#ifdef CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS - if (static_cpu_has(X86_FEATURE_PKU) && + if (cpu_feature_enabled(X86_FEATURE_PKU) && vcpu->arch.pkru != vcpu->arch.host_pkru && ((vcpu->arch.xcr0 & XFEATURE_MASK_PKRU) || kvm_is_cr4_bit_set(vcpu, X86_CR4_PKE))) write_pkru(vcpu->arch.pkru); -#endif /* CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS */ } EXPORT_SYMBOL_GPL(kvm_load_guest_xsave_state); @@ -1032,15 +1030,13 @@ void kvm_load_host_xsave_state(struct kvm_vcpu *vcpu) if (vcpu->arch.guest_state_protected) return; -#ifdef CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS - if (static_cpu_has(X86_FEATURE_PKU) && + if (cpu_feature_enabled(X86_FEATURE_PKU) && ((vcpu->arch.xcr0 & XFEATURE_MASK_PKRU) || kvm_is_cr4_bit_set(vcpu, X86_CR4_PKE))) { vcpu->arch.pkru = rdpkru(); if (vcpu->arch.pkru != vcpu->arch.host_pkru) write_pkru(vcpu->arch.host_pkru); } -#endif /* CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS */ if (kvm_is_cr4_bit_set(vcpu, X86_CR4_OSXSAVE)) { @@ -1427,15 +1423,14 @@ int kvm_emulate_rdpmc(struct kvm_vcpu *vcpu) EXPORT_SYMBOL_GPL(kvm_emulate_rdpmc); /* - * List of msr numbers which we expose to userspace through KVM_GET_MSRS - * and KVM_SET_MSRS, and KVM_GET_MSR_INDEX_LIST. - * - * The three MSR lists(msrs_to_save, emulated_msrs, msr_based_features) - * extract the supported MSRs from the related const lists. - * msrs_to_save is selected from the msrs_to_save_all to reflect the - * capabilities of the host cpu. This capabilities test skips MSRs that are - * kvm-specific. Those are put in emulated_msrs_all; filtering of emulated_msrs - * may depend on host virtualization features rather than host cpu features. + * The three MSR lists(msrs_to_save, emulated_msrs, msr_based_features) track + * the set of MSRs that KVM exposes to userspace through KVM_GET_MSRS, + * KVM_SET_MSRS, and KVM_GET_MSR_INDEX_LIST. msrs_to_save holds MSRs that + * require host support, i.e. should be probed via RDMSR. emulated_msrs holds + * MSRs that KVM emulates without strictly requiring host support. + * msr_based_features holds MSRs that enumerate features, i.e. are effectively + * CPUID leafs. Note, msr_based_features isn't mutually exclusive with + * msrs_to_save and emulated_msrs. */ static const u32 msrs_to_save_base[] = { @@ -1483,6 +1478,10 @@ static const u32 msrs_to_save_pmu[] = { MSR_F15H_PERF_CTL3, MSR_F15H_PERF_CTL4, MSR_F15H_PERF_CTL5, MSR_F15H_PERF_CTR0, MSR_F15H_PERF_CTR1, MSR_F15H_PERF_CTR2, MSR_F15H_PERF_CTR3, MSR_F15H_PERF_CTR4, MSR_F15H_PERF_CTR5, + + MSR_AMD64_PERF_CNTR_GLOBAL_CTL, + MSR_AMD64_PERF_CNTR_GLOBAL_STATUS, + MSR_AMD64_PERF_CNTR_GLOBAL_STATUS_CLR, }; static u32 msrs_to_save[ARRAY_SIZE(msrs_to_save_base) + @@ -1531,11 +1530,11 @@ static const u32 emulated_msrs_all[] = { MSR_IA32_UCODE_REV, /* - * The following list leaves out MSRs whose values are determined - * by arch/x86/kvm/vmx/nested.c based on CPUID or other MSRs. - * We always support the "true" VMX control MSRs, even if the host - * processor does not, so I am putting these registers here rather - * than in msrs_to_save_all. + * KVM always supports the "true" VMX control MSRs, even if the host + * does not. The VMX MSRs as a whole are considered "emulated" as KVM + * doesn't strictly require them to exist in the host (ignoring that + * KVM would refuse to load in the first place if the core set of MSRs + * aren't supported). */ MSR_IA32_VMX_BASIC, MSR_IA32_VMX_TRUE_PINBASED_CTLS, @@ -1631,7 +1630,7 @@ static u64 kvm_get_arch_capabilities(void) * If we're doing cache flushes (either "always" or "cond") * we will do one whenever the guest does a vmlaunch/vmresume. * If an outer hypervisor is doing the cache flush for us - * (VMENTER_L1D_FLUSH_NESTED_VM), we can safely pass that + * (ARCH_CAP_SKIP_VMENTRY_L1DFLUSH), we can safely pass that * capability to the guest too, and if EPT is disabled we're not * vulnerable. Overall, only VMENTER_L1D_FLUSH_NEVER will * require a nested hypervisor to do a flush of its own. @@ -1809,7 +1808,7 @@ bool kvm_msr_allowed(struct kvm_vcpu *vcpu, u32 index, u32 type) unsigned long *bitmap = ranges[i].bitmap; if ((index >= start) && (index < end) && (flags & type)) { - allowed = !!test_bit(index - start, bitmap); + allowed = test_bit(index - start, bitmap); break; } } @@ -2799,14 +2798,13 @@ static u64 read_tsc(void) static inline u64 vgettsc(struct pvclock_clock *clock, u64 *tsc_timestamp, int *mode) { - long v; u64 tsc_pg_val; + long v; switch (clock->vclock_mode) { case VDSO_CLOCKMODE_HVCLOCK: - tsc_pg_val = hv_read_tsc_page_tsc(hv_get_tsc_page(), - tsc_timestamp); - if (tsc_pg_val != U64_MAX) { + if (hv_read_tsc_page_tsc(hv_get_tsc_page(), + tsc_timestamp, &tsc_pg_val)) { /* TSC page valid */ *mode = VDSO_CLOCKMODE_HVCLOCK; v = (tsc_pg_val - clock->cycle_last) & @@ -3702,8 +3700,14 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info) return 1; } break; - case 0x200 ... MSR_IA32_MC0_CTL2 - 1: - case MSR_IA32_MCx_CTL2(KVM_MAX_MCE_BANKS) ... 0x2ff: + case MSR_IA32_CR_PAT: + if (!kvm_pat_valid(data)) + return 1; + + vcpu->arch.pat = data; + break; + case MTRRphysBase_MSR(0) ... MSR_MTRRfix4K_F8000: + case MSR_MTRRdefType: return kvm_mtrr_set_msr(vcpu, msr, data); case MSR_IA32_APICBASE: return kvm_set_apic_base(vcpu, msr_info); @@ -4110,9 +4114,12 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info) msr_info->data = kvm_scale_tsc(rdtsc(), ratio) + offset; break; } + case MSR_IA32_CR_PAT: + msr_info->data = vcpu->arch.pat; + break; case MSR_MTRRcap: - case 0x200 ... MSR_IA32_MC0_CTL2 - 1: - case MSR_IA32_MCx_CTL2(KVM_MAX_MCE_BANKS) ... 0x2ff: + case MTRRphysBase_MSR(0) ... MSR_MTRRfix4K_F8000: + case MSR_MTRRdefType: return kvm_mtrr_get_msr(vcpu, msr_info->index, &msr_info->data); case 0xcd: /* fsb frequency */ msr_info->data = 3; @@ -7150,6 +7157,12 @@ static void kvm_probe_msr_to_save(u32 msr_index) kvm_pmu_cap.num_counters_fixed) return; break; + case MSR_AMD64_PERF_CNTR_GLOBAL_CTL: + case MSR_AMD64_PERF_CNTR_GLOBAL_STATUS: + case MSR_AMD64_PERF_CNTR_GLOBAL_STATUS_CLR: + if (!kvm_cpu_cap_has(X86_FEATURE_PERFMON_V2)) + return; + break; case MSR_IA32_XFD: case MSR_IA32_XFD_ERR: if (!kvm_cpu_cap_has(X86_FEATURE_XFD)) @@ -10435,20 +10448,6 @@ static void vcpu_load_eoi_exitmap(struct kvm_vcpu *vcpu) vcpu, (u64 *)vcpu->arch.ioapic_handled_vectors); } -void kvm_arch_mmu_notifier_invalidate_range(struct kvm *kvm, - unsigned long start, unsigned long end) -{ - unsigned long apic_address; - - /* - * The physical address of apic access page is stored in the VMCS. - * Update it when it becomes invalid. - */ - apic_address = gfn_to_hva(kvm, APIC_DEFAULT_PHYS_BASE >> PAGE_SHIFT); - if (start <= apic_address && apic_address < end) - kvm_make_all_cpus_request(kvm, KVM_REQ_APIC_PAGE_RELOAD); -} - void kvm_arch_guest_memory_reclaimed(struct kvm *kvm) { static_call_cond(kvm_x86_guest_memory_reclaimed)(kvm); @@ -13162,7 +13161,7 @@ EXPORT_SYMBOL_GPL(kvm_arch_end_assignment); bool noinstr kvm_arch_has_assigned_device(struct kvm *kvm) { - return arch_atomic_read(&kvm->arch.assigned_device_count); + return raw_atomic_read(&kvm->arch.assigned_device_count); } EXPORT_SYMBOL_GPL(kvm_arch_has_assigned_device); diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h index c544602d07a359fba5774dbd192335c50044072c..82e3dafc5453facc8eeaba39a3bde8fd90081ab3 100644 --- a/arch/x86/kvm/x86.h +++ b/arch/x86/kvm/x86.h @@ -309,7 +309,6 @@ void kvm_deliver_exception_payload(struct kvm_vcpu *vcpu, void kvm_vcpu_mtrr_init(struct kvm_vcpu *vcpu); u8 kvm_mtrr_get_guest_memory_type(struct kvm_vcpu *vcpu, gfn_t gfn); -bool kvm_mtrr_valid(struct kvm_vcpu *vcpu, u32 msr, u64 data); int kvm_mtrr_set_msr(struct kvm_vcpu *vcpu, u32 msr, u64 data); int kvm_mtrr_get_msr(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata); bool kvm_mtrr_check_gfn_range_consistency(struct kvm_vcpu *vcpu, gfn_t gfn, diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile index 01932af64193c14a3da15d86b92ca2ee332929ad..ea3a28e7b613ccbda58490702c6609057412e4c0 100644 --- a/arch/x86/lib/Makefile +++ b/arch/x86/lib/Makefile @@ -61,8 +61,9 @@ ifeq ($(CONFIG_X86_32),y) lib-y += strstr_32.o lib-y += string_32.o lib-y += memmove_32.o + lib-y += cmpxchg8b_emu.o ifneq ($(CONFIG_X86_CMPXCHG64),y) - lib-y += cmpxchg8b_emu.o atomic64_386_32.o + lib-y += atomic64_386_32.o endif else obj-y += iomap_copy_64.o diff --git a/arch/x86/lib/cmpxchg16b_emu.S b/arch/x86/lib/cmpxchg16b_emu.S index 33c70c0160ea04066c479f97fe30f34737bbc0ff..6962df3157938d9936895d67d5b18806844fb761 100644 --- a/arch/x86/lib/cmpxchg16b_emu.S +++ b/arch/x86/lib/cmpxchg16b_emu.S @@ -1,47 +1,54 @@ /* SPDX-License-Identifier: GPL-2.0-only */ #include #include +#include .text /* + * Emulate 'cmpxchg16b %gs:(%rsi)' + * * Inputs: * %rsi : memory location to compare * %rax : low 64 bits of old value * %rdx : high 64 bits of old value * %rbx : low 64 bits of new value * %rcx : high 64 bits of new value - * %al : Operation successful + * + * Notably this is not LOCK prefixed and is not safe against NMIs */ SYM_FUNC_START(this_cpu_cmpxchg16b_emu) -# -# Emulate 'cmpxchg16b %gs:(%rsi)' except we return the result in %al not -# via the ZF. Caller will access %al to get result. -# -# Note that this is only useful for a cpuops operation. Meaning that we -# do *not* have a fully atomic operation but just an operation that is -# *atomic* on a single cpu (as provided by the this_cpu_xx class of -# macros). -# pushfq cli - cmpq PER_CPU_VAR((%rsi)), %rax - jne .Lnot_same - cmpq PER_CPU_VAR(8(%rsi)), %rdx - jne .Lnot_same + /* if (*ptr == old) */ + cmpq PER_CPU_VAR(0(%rsi)), %rax + jne .Lnot_same + cmpq PER_CPU_VAR(8(%rsi)), %rdx + jne .Lnot_same - movq %rbx, PER_CPU_VAR((%rsi)) - movq %rcx, PER_CPU_VAR(8(%rsi)) + /* *ptr = new */ + movq %rbx, PER_CPU_VAR(0(%rsi)) + movq %rcx, PER_CPU_VAR(8(%rsi)) + + /* set ZF in EFLAGS to indicate success */ + orl $X86_EFLAGS_ZF, (%rsp) popfq - mov $1, %al RET .Lnot_same: + /* *ptr != old */ + + /* old = *ptr */ + movq PER_CPU_VAR(0(%rsi)), %rax + movq PER_CPU_VAR(8(%rsi)), %rdx + + /* clear ZF in EFLAGS to indicate failure */ + andl $(~X86_EFLAGS_ZF), (%rsp) + popfq - xor %al,%al RET SYM_FUNC_END(this_cpu_cmpxchg16b_emu) diff --git a/arch/x86/lib/cmpxchg8b_emu.S b/arch/x86/lib/cmpxchg8b_emu.S index 6a912d58fecc3f65ca6044a636b838161e1b74a6..49805257b1255b2b6d3be0172dc6be920fa7168e 100644 --- a/arch/x86/lib/cmpxchg8b_emu.S +++ b/arch/x86/lib/cmpxchg8b_emu.S @@ -2,10 +2,16 @@ #include #include +#include +#include .text +#ifndef CONFIG_X86_CMPXCHG64 + /* + * Emulate 'cmpxchg8b (%esi)' on UP + * * Inputs: * %esi : memory location to compare * %eax : low 32 bits of old value @@ -15,32 +21,65 @@ */ SYM_FUNC_START(cmpxchg8b_emu) -# -# Emulate 'cmpxchg8b (%esi)' on UP except we don't -# set the whole ZF thing (caller will just compare -# eax:edx with the expected value) -# pushfl cli - cmpl (%esi), %eax - jne .Lnot_same - cmpl 4(%esi), %edx - jne .Lhalf_same + cmpl 0(%esi), %eax + jne .Lnot_same + cmpl 4(%esi), %edx + jne .Lnot_same + + movl %ebx, 0(%esi) + movl %ecx, 4(%esi) - movl %ebx, (%esi) - movl %ecx, 4(%esi) + orl $X86_EFLAGS_ZF, (%esp) popfl RET .Lnot_same: - movl (%esi), %eax -.Lhalf_same: - movl 4(%esi), %edx + movl 0(%esi), %eax + movl 4(%esi), %edx + + andl $(~X86_EFLAGS_ZF), (%esp) popfl RET SYM_FUNC_END(cmpxchg8b_emu) EXPORT_SYMBOL(cmpxchg8b_emu) + +#endif + +#ifndef CONFIG_UML + +SYM_FUNC_START(this_cpu_cmpxchg8b_emu) + + pushfl + cli + + cmpl PER_CPU_VAR(0(%esi)), %eax + jne .Lnot_same2 + cmpl PER_CPU_VAR(4(%esi)), %edx + jne .Lnot_same2 + + movl %ebx, PER_CPU_VAR(0(%esi)) + movl %ecx, PER_CPU_VAR(4(%esi)) + + orl $X86_EFLAGS_ZF, (%esp) + + popfl + RET + +.Lnot_same2: + movl PER_CPU_VAR(0(%esi)), %eax + movl PER_CPU_VAR(4(%esi)), %edx + + andl $(~X86_EFLAGS_ZF), (%esp) + + popfl + RET + +SYM_FUNC_END(this_cpu_cmpxchg8b_emu) + +#endif diff --git a/arch/x86/lib/csum-partial_64.c b/arch/x86/lib/csum-partial_64.c index 50734a23034c438487e060cde8304c2a5ad05af7..cea25ca8b8cf69885a2de752c3bc1fb067cded26 100644 --- a/arch/x86/lib/csum-partial_64.c +++ b/arch/x86/lib/csum-partial_64.c @@ -5,22 +5,34 @@ * This file contains network checksum routines that are better done * in an architecture-specific manner due to speed. */ - + #include #include #include #include -static inline unsigned short from32to16(unsigned a) +static inline unsigned short from32to16(unsigned a) { - unsigned short b = a >> 16; + unsigned short b = a >> 16; asm("addw %w2,%w0\n\t" - "adcw $0,%w0\n" + "adcw $0,%w0\n" : "=r" (b) : "0" (b), "r" (a)); return b; } +static inline __wsum csum_tail(u64 temp64, int odd) +{ + unsigned int result; + + result = add32_with_carry(temp64 >> 32, temp64 & 0xffffffff); + if (unlikely(odd)) { + result = from32to16(result); + result = ((result >> 8) & 0xff) | ((result & 0xff) << 8); + } + return (__force __wsum)result; +} + /* * Do a checksum on an arbitrary memory area. * Returns a 32bit checksum. @@ -35,7 +47,7 @@ static inline unsigned short from32to16(unsigned a) __wsum csum_partial(const void *buff, int len, __wsum sum) { u64 temp64 = (__force u64)sum; - unsigned odd, result; + unsigned odd; odd = 1 & (unsigned long) buff; if (unlikely(odd)) { @@ -47,21 +59,52 @@ __wsum csum_partial(const void *buff, int len, __wsum sum) buff++; } - while (unlikely(len >= 64)) { + /* + * len == 40 is the hot case due to IPv6 headers, but annotating it likely() + * has noticeable negative affect on codegen for all other cases with + * minimal performance benefit here. + */ + if (len == 40) { asm("addq 0*8(%[src]),%[res]\n\t" "adcq 1*8(%[src]),%[res]\n\t" "adcq 2*8(%[src]),%[res]\n\t" "adcq 3*8(%[src]),%[res]\n\t" "adcq 4*8(%[src]),%[res]\n\t" - "adcq 5*8(%[src]),%[res]\n\t" - "adcq 6*8(%[src]),%[res]\n\t" - "adcq 7*8(%[src]),%[res]\n\t" "adcq $0,%[res]" - : [res] "+r" (temp64) - : [src] "r" (buff) - : "memory"); - buff += 64; - len -= 64; + : [res] "+r"(temp64) + : [src] "r"(buff), "m"(*(const char(*)[40])buff)); + return csum_tail(temp64, odd); + } + if (unlikely(len >= 64)) { + /* + * Extra accumulators for better ILP in the loop. + */ + u64 tmp_accum, tmp_carries; + + asm("xorl %k[tmp_accum],%k[tmp_accum]\n\t" + "xorl %k[tmp_carries],%k[tmp_carries]\n\t" + "subl $64, %[len]\n\t" + "1:\n\t" + "addq 0*8(%[src]),%[res]\n\t" + "adcq 1*8(%[src]),%[res]\n\t" + "adcq 2*8(%[src]),%[res]\n\t" + "adcq 3*8(%[src]),%[res]\n\t" + "adcl $0,%k[tmp_carries]\n\t" + "addq 4*8(%[src]),%[tmp_accum]\n\t" + "adcq 5*8(%[src]),%[tmp_accum]\n\t" + "adcq 6*8(%[src]),%[tmp_accum]\n\t" + "adcq 7*8(%[src]),%[tmp_accum]\n\t" + "adcl $0,%k[tmp_carries]\n\t" + "addq $64, %[src]\n\t" + "subl $64, %[len]\n\t" + "jge 1b\n\t" + "addq %[tmp_accum],%[res]\n\t" + "adcq %[tmp_carries],%[res]\n\t" + "adcq $0,%[res]" + : [tmp_accum] "=&r"(tmp_accum), + [tmp_carries] "=&r"(tmp_carries), [res] "+r"(temp64), + [len] "+r"(len), [src] "+r"(buff) + : "m"(*(const char *)buff)); } if (len & 32) { @@ -70,45 +113,37 @@ __wsum csum_partial(const void *buff, int len, __wsum sum) "adcq 2*8(%[src]),%[res]\n\t" "adcq 3*8(%[src]),%[res]\n\t" "adcq $0,%[res]" - : [res] "+r" (temp64) - : [src] "r" (buff) - : "memory"); + : [res] "+r"(temp64) + : [src] "r"(buff), "m"(*(const char(*)[32])buff)); buff += 32; } if (len & 16) { asm("addq 0*8(%[src]),%[res]\n\t" "adcq 1*8(%[src]),%[res]\n\t" "adcq $0,%[res]" - : [res] "+r" (temp64) - : [src] "r" (buff) - : "memory"); + : [res] "+r"(temp64) + : [src] "r"(buff), "m"(*(const char(*)[16])buff)); buff += 16; } if (len & 8) { asm("addq 0*8(%[src]),%[res]\n\t" "adcq $0,%[res]" - : [res] "+r" (temp64) - : [src] "r" (buff) - : "memory"); + : [res] "+r"(temp64) + : [src] "r"(buff), "m"(*(const char(*)[8])buff)); buff += 8; } if (len & 7) { - unsigned int shift = (8 - (len & 7)) * 8; + unsigned int shift = (-len << 3) & 63; unsigned long trail; trail = (load_unaligned_zeropad(buff) << shift) >> shift; asm("addq %[trail],%[res]\n\t" "adcq $0,%[res]" - : [res] "+r" (temp64) - : [trail] "r" (trail)); + : [res] "+r"(temp64) + : [trail] "r"(trail)); } - result = add32_with_carry(temp64 >> 32, temp64 & 0xffffffff); - if (unlikely(odd)) { - result = from32to16(result); - result = ((result >> 8) & 0xff) | ((result & 0xff) << 8); - } - return (__force __wsum)result; + return csum_tail(temp64, odd); } EXPORT_SYMBOL(csum_partial); @@ -118,6 +153,6 @@ EXPORT_SYMBOL(csum_partial); */ __sum16 ip_compute_csum(const void *buff, int len) { - return csum_fold(csum_partial(buff,len,0)); + return csum_fold(csum_partial(buff, len, 0)); } EXPORT_SYMBOL(ip_compute_csum); diff --git a/arch/x86/lib/getuser.S b/arch/x86/lib/getuser.S index b64a2bd1a1efae5b94311f00b2db51d08813f03d..9c63713477bbb7b5df157a1047b0625546a7a09e 100644 --- a/arch/x86/lib/getuser.S +++ b/arch/x86/lib/getuser.S @@ -143,43 +143,43 @@ SYM_FUNC_END(__get_user_nocheck_8) EXPORT_SYMBOL(__get_user_nocheck_8) -SYM_CODE_START_LOCAL(.Lbad_get_user_clac) +SYM_CODE_START_LOCAL(__get_user_handle_exception) ASM_CLAC .Lbad_get_user: xor %edx,%edx mov $(-EFAULT),%_ASM_AX RET -SYM_CODE_END(.Lbad_get_user_clac) +SYM_CODE_END(__get_user_handle_exception) #ifdef CONFIG_X86_32 -SYM_CODE_START_LOCAL(.Lbad_get_user_8_clac) +SYM_CODE_START_LOCAL(__get_user_8_handle_exception) ASM_CLAC bad_get_user_8: xor %edx,%edx xor %ecx,%ecx mov $(-EFAULT),%_ASM_AX RET -SYM_CODE_END(.Lbad_get_user_8_clac) +SYM_CODE_END(__get_user_8_handle_exception) #endif /* get_user */ - _ASM_EXTABLE(1b, .Lbad_get_user_clac) - _ASM_EXTABLE(2b, .Lbad_get_user_clac) - _ASM_EXTABLE(3b, .Lbad_get_user_clac) + _ASM_EXTABLE(1b, __get_user_handle_exception) + _ASM_EXTABLE(2b, __get_user_handle_exception) + _ASM_EXTABLE(3b, __get_user_handle_exception) #ifdef CONFIG_X86_64 - _ASM_EXTABLE(4b, .Lbad_get_user_clac) + _ASM_EXTABLE(4b, __get_user_handle_exception) #else - _ASM_EXTABLE(4b, .Lbad_get_user_8_clac) - _ASM_EXTABLE(5b, .Lbad_get_user_8_clac) + _ASM_EXTABLE(4b, __get_user_8_handle_exception) + _ASM_EXTABLE(5b, __get_user_8_handle_exception) #endif /* __get_user */ - _ASM_EXTABLE(6b, .Lbad_get_user_clac) - _ASM_EXTABLE(7b, .Lbad_get_user_clac) - _ASM_EXTABLE(8b, .Lbad_get_user_clac) + _ASM_EXTABLE(6b, __get_user_handle_exception) + _ASM_EXTABLE(7b, __get_user_handle_exception) + _ASM_EXTABLE(8b, __get_user_handle_exception) #ifdef CONFIG_X86_64 - _ASM_EXTABLE(9b, .Lbad_get_user_clac) + _ASM_EXTABLE(9b, __get_user_handle_exception) #else - _ASM_EXTABLE(9b, .Lbad_get_user_8_clac) - _ASM_EXTABLE(10b, .Lbad_get_user_8_clac) + _ASM_EXTABLE(9b, __get_user_8_handle_exception) + _ASM_EXTABLE(10b, __get_user_8_handle_exception) #endif diff --git a/arch/x86/lib/memmove_64.S b/arch/x86/lib/memmove_64.S index 02661861e5dd9665966dbd3a830ed6a7d4054dba..0559b206fb1109c459d4a74b50dd6226f69a8153 100644 --- a/arch/x86/lib/memmove_64.S +++ b/arch/x86/lib/memmove_64.S @@ -38,10 +38,12 @@ SYM_FUNC_START(__memmove) cmp %rdi, %r8 jg 2f - /* FSRM implies ERMS => no length checks, do the copy directly */ +#define CHECK_LEN cmp $0x20, %rdx; jb 1f +#define MEMMOVE_BYTES movq %rdx, %rcx; rep movsb; RET .Lmemmove_begin_forward: - ALTERNATIVE "cmp $0x20, %rdx; jb 1f", "", X86_FEATURE_FSRM - ALTERNATIVE "", "jmp .Lmemmove_erms", X86_FEATURE_ERMS + ALTERNATIVE_2 __stringify(CHECK_LEN), \ + __stringify(CHECK_LEN; MEMMOVE_BYTES), X86_FEATURE_ERMS, \ + __stringify(MEMMOVE_BYTES), X86_FEATURE_FSRM /* * movsq instruction have many startup latency @@ -207,11 +209,6 @@ SYM_FUNC_START(__memmove) movb %r11b, (%rdi) 13: RET - -.Lmemmove_erms: - movq %rdx, %rcx - rep movsb - RET SYM_FUNC_END(__memmove) EXPORT_SYMBOL(__memmove) diff --git a/arch/x86/lib/msr.c b/arch/x86/lib/msr.c index b09cd2ad426ccde84865b1d974f3dd35d5109c54..47fd9bd6b91d8c2e69434a112b369e0d243c38d1 100644 --- a/arch/x86/lib/msr.c +++ b/arch/x86/lib/msr.c @@ -27,14 +27,14 @@ void msrs_free(struct msr *msrs) EXPORT_SYMBOL(msrs_free); /** - * Read an MSR with error handling - * + * msr_read - Read an MSR with error handling * @msr: MSR to read * @m: value to read into * * It returns read data only on success, otherwise it doesn't change the output * argument @m. * + * Return: %0 for success, otherwise an error code */ static int msr_read(u32 msr, struct msr *m) { @@ -49,10 +49,12 @@ static int msr_read(u32 msr, struct msr *m) } /** - * Write an MSR with error handling + * msr_write - Write an MSR with error handling * * @msr: MSR to write * @m: value to write + * + * Return: %0 for success, otherwise an error code */ static int msr_write(u32 msr, struct msr *m) { @@ -88,12 +90,14 @@ static inline int __flip_bit(u32 msr, u8 bit, bool set) } /** - * Set @bit in a MSR @msr. + * msr_set_bit - Set @bit in a MSR @msr. + * @msr: MSR to write + * @bit: bit number to set * - * Retval: - * < 0: An error was encountered. - * = 0: Bit was already set. - * > 0: Hardware accepted the MSR write. + * Return: + * * < 0: An error was encountered. + * * = 0: Bit was already set. + * * > 0: Hardware accepted the MSR write. */ int msr_set_bit(u32 msr, u8 bit) { @@ -101,12 +105,14 @@ int msr_set_bit(u32 msr, u8 bit) } /** - * Clear @bit in a MSR @msr. + * msr_clear_bit - Clear @bit in a MSR @msr. + * @msr: MSR to write + * @bit: bit number to clear * - * Retval: - * < 0: An error was encountered. - * = 0: Bit was already cleared. - * > 0: Hardware accepted the MSR write. + * Return: + * * < 0: An error was encountered. + * * = 0: Bit was already cleared. + * * > 0: Hardware accepted the MSR write. */ int msr_clear_bit(u32 msr, u8 bit) { diff --git a/arch/x86/lib/putuser.S b/arch/x86/lib/putuser.S index 3062d09a776d5018039904aa60238ce71918e018..1451e0c4ae22af2ac0721596755be825d51e32fd 100644 --- a/arch/x86/lib/putuser.S +++ b/arch/x86/lib/putuser.S @@ -131,22 +131,22 @@ SYM_FUNC_START(__put_user_nocheck_8) SYM_FUNC_END(__put_user_nocheck_8) EXPORT_SYMBOL(__put_user_nocheck_8) -SYM_CODE_START_LOCAL(.Lbad_put_user_clac) +SYM_CODE_START_LOCAL(__put_user_handle_exception) ASM_CLAC .Lbad_put_user: movl $-EFAULT,%ecx RET -SYM_CODE_END(.Lbad_put_user_clac) +SYM_CODE_END(__put_user_handle_exception) - _ASM_EXTABLE(1b, .Lbad_put_user_clac) - _ASM_EXTABLE(2b, .Lbad_put_user_clac) - _ASM_EXTABLE(3b, .Lbad_put_user_clac) - _ASM_EXTABLE(4b, .Lbad_put_user_clac) - _ASM_EXTABLE(5b, .Lbad_put_user_clac) - _ASM_EXTABLE(6b, .Lbad_put_user_clac) - _ASM_EXTABLE(7b, .Lbad_put_user_clac) - _ASM_EXTABLE(9b, .Lbad_put_user_clac) + _ASM_EXTABLE(1b, __put_user_handle_exception) + _ASM_EXTABLE(2b, __put_user_handle_exception) + _ASM_EXTABLE(3b, __put_user_handle_exception) + _ASM_EXTABLE(4b, __put_user_handle_exception) + _ASM_EXTABLE(5b, __put_user_handle_exception) + _ASM_EXTABLE(6b, __put_user_handle_exception) + _ASM_EXTABLE(7b, __put_user_handle_exception) + _ASM_EXTABLE(9b, __put_user_handle_exception) #ifdef CONFIG_X86_32 - _ASM_EXTABLE(8b, .Lbad_put_user_clac) - _ASM_EXTABLE(10b, .Lbad_put_user_clac) + _ASM_EXTABLE(8b, __put_user_handle_exception) + _ASM_EXTABLE(10b, __put_user_handle_exception) #endif diff --git a/arch/x86/lib/retpoline.S b/arch/x86/lib/retpoline.S index b3b1e376dce86a15ea56a8445867d9ccb5db5c87..3fd066d42ec056e26154db0823789d1e4b81a73a 100644 --- a/arch/x86/lib/retpoline.S +++ b/arch/x86/lib/retpoline.S @@ -143,7 +143,7 @@ SYM_CODE_END(__x86_indirect_jump_thunk_array) * from re-poisioning the BTB prediction. */ .align 64 - .skip 63, 0xcc + .skip 64 - (__x86_return_thunk - zen_untrain_ret), 0xcc SYM_START(zen_untrain_ret, SYM_L_GLOBAL, SYM_A_NONE) ANNOTATE_NOENDBR /* diff --git a/arch/x86/lib/usercopy_64.c b/arch/x86/lib/usercopy_64.c index 003d90138e20c610f22fc53b0687c44d5e8c8b39..e9251b89a9e9398cc7acd9eccd301f27dcf96a07 100644 --- a/arch/x86/lib/usercopy_64.c +++ b/arch/x86/lib/usercopy_64.c @@ -9,6 +9,7 @@ #include #include #include +#include /* * Zero Userspace diff --git a/arch/x86/math-emu/fpu_entry.c b/arch/x86/math-emu/fpu_entry.c index 7fe56c594aa627e5de65199ba85bbae6d4d340ea..91c52ead1226576f973459ffe9ec6a0d484ce5f1 100644 --- a/arch/x86/math-emu/fpu_entry.c +++ b/arch/x86/math-emu/fpu_entry.c @@ -32,6 +32,7 @@ #include #include #include +#include #include "fpu_system.h" #include "fpu_emu.h" diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c index e4399983c50c05aa1e2906ce9df15874304f9b31..e8711b2cafaf70cc8ef5cb1ce72c7fa12e3c070c 100644 --- a/arch/x86/mm/fault.c +++ b/arch/x86/mm/fault.c @@ -880,12 +880,6 @@ __bad_area(struct pt_regs *regs, unsigned long error_code, __bad_area_nosemaphore(regs, error_code, address, pkey, si_code); } -static noinline void -bad_area(struct pt_regs *regs, unsigned long error_code, unsigned long address) -{ - __bad_area(regs, error_code, address, 0, SEGV_MAPERR); -} - static inline bool bad_area_access_from_pkeys(unsigned long error_code, struct vm_area_struct *vma) { @@ -1366,51 +1360,10 @@ void do_user_addr_fault(struct pt_regs *regs, lock_mmap: #endif /* CONFIG_PER_VMA_LOCK */ - /* - * Kernel-mode access to the user address space should only occur - * on well-defined single instructions listed in the exception - * tables. But, an erroneous kernel fault occurring outside one of - * those areas which also holds mmap_lock might deadlock attempting - * to validate the fault against the address space. - * - * Only do the expensive exception table search when we might be at - * risk of a deadlock. This happens if we - * 1. Failed to acquire mmap_lock, and - * 2. The access did not originate in userspace. - */ - if (unlikely(!mmap_read_trylock(mm))) { - if (!user_mode(regs) && !search_exception_tables(regs->ip)) { - /* - * Fault from code in kernel from - * which we do not expect faults. - */ - bad_area_nosemaphore(regs, error_code, address); - return; - } retry: - mmap_read_lock(mm); - } else { - /* - * The above down_read_trylock() might have succeeded in - * which case we'll have missed the might_sleep() from - * down_read(): - */ - might_sleep(); - } - - vma = find_vma(mm, address); + vma = lock_mm_and_find_vma(mm, address, regs); if (unlikely(!vma)) { - bad_area(regs, error_code, address); - return; - } - if (likely(vma->vm_start <= address)) - goto good_area; - if (unlikely(!(vma->vm_flags & VM_GROWSDOWN))) { - bad_area(regs, error_code, address); - return; - } - if (unlikely(expand_stack(vma, address))) { - bad_area(regs, error_code, address); + bad_area_nosemaphore(regs, error_code, address); return; } @@ -1418,7 +1371,6 @@ void do_user_addr_fault(struct pt_regs *regs, * Ok, we have a good vm_area for this memory access, so * we can handle it.. */ -good_area: if (unlikely(access_error(error_code, vma))) { bad_area_access_error(regs, error_code, address, vma); return; diff --git a/arch/x86/mm/highmem_32.c b/arch/x86/mm/highmem_32.c index 2c54b76d8f849483cf98e6ef0293babfb814ca7e..d9efa35711ee9f561dd8a097741d8e0a41eaf1e7 100644 --- a/arch/x86/mm/highmem_32.c +++ b/arch/x86/mm/highmem_32.c @@ -3,6 +3,7 @@ #include #include /* for totalram_pages */ #include +#include void __init set_highmem_pages_init(void) { diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c index d4e2648a1dfb25376ba1dafa05201585d7c94e17..b63403d7179df4b466d3c7b1b5ff36b654cc5fd1 100644 --- a/arch/x86/mm/init_32.c +++ b/arch/x86/mm/init_32.c @@ -45,7 +45,6 @@ #include #include #include -#include #include #include #include @@ -74,7 +73,6 @@ static pmd_t * __init one_md_table_init(pgd_t *pgd) #ifdef CONFIG_X86_PAE if (!(pgd_val(*pgd) & _PAGE_PRESENT)) { pmd_table = (pmd_t *)alloc_low_page(); - paravirt_alloc_pmd(&init_mm, __pa(pmd_table) >> PAGE_SHIFT); set_pgd(pgd, __pgd(__pa(pmd_table) | _PAGE_PRESENT)); p4d = p4d_offset(pgd, 0); pud = pud_offset(p4d, 0); @@ -99,7 +97,6 @@ static pte_t * __init one_page_table_init(pmd_t *pmd) if (!(pmd_val(*pmd) & _PAGE_PRESENT)) { pte_t *page_table = (pte_t *)alloc_low_page(); - paravirt_alloc_pte(&init_mm, __pa(page_table) >> PAGE_SHIFT); set_pmd(pmd, __pmd(__pa(page_table) | _PAGE_TABLE)); BUG_ON(page_table != pte_offset_kernel(pmd, 0)); } @@ -181,12 +178,10 @@ static pte_t *__init page_table_kmap_check(pte_t *pte, pmd_t *pmd, set_pte(newpte + i, pte[i]); *adr = (void *)(((unsigned long)(*adr)) + PAGE_SIZE); - paravirt_alloc_pte(&init_mm, __pa(newpte) >> PAGE_SHIFT); set_pmd(pmd, __pmd(__pa(newpte)|_PAGE_TABLE)); BUG_ON(newpte != pte_offset_kernel(pmd, 0)); __flush_tlb_all(); - paravirt_release_pte(__pa(pte) >> PAGE_SHIFT); pte = newpte; } BUG_ON(vaddr < fix_to_virt(FIX_KMAP_BEGIN - 1) @@ -482,7 +477,6 @@ void __init native_pagetable_init(void) pfn, pmd, __pa(pmd), pte, __pa(pte)); pte_clear(NULL, va, pte); } - paravirt_alloc_pmd(&init_mm, __pa(base) >> PAGE_SHIFT); paging_init(); } @@ -491,15 +485,8 @@ void __init native_pagetable_init(void) * point, we've been running on some set of pagetables constructed by * the boot process. * - * If we're booting on native hardware, this will be a pagetable - * constructed in arch/x86/kernel/head_32.S. The root of the - * pagetable will be swapper_pg_dir. - * - * If we're booting paravirtualized under a hypervisor, then there are - * more options: we may already be running PAE, and the pagetable may - * or may not be based in swapper_pg_dir. In any case, - * paravirt_pagetable_init() will set up swapper_pg_dir - * appropriately for the rest of the initialization to work. + * This will be a pagetable constructed in arch/x86/kernel/head_32.S. + * The root of the pagetable will be swapper_pg_dir. * * In general, pagetable_init() assumes that the pagetable may already * be partially populated, and so it avoids stomping on any existing diff --git a/arch/x86/mm/kaslr.c b/arch/x86/mm/kaslr.c index 557f0fe25dff47641f03a86e5166a03f19627901..37db264866b6489ef99325d2fe1604d6cd3c9885 100644 --- a/arch/x86/mm/kaslr.c +++ b/arch/x86/mm/kaslr.c @@ -172,10 +172,10 @@ void __meminit init_trampoline_kaslr(void) set_p4d(p4d_tramp, __p4d(_KERNPG_TABLE | __pa(pud_page_tramp))); - set_pgd(&trampoline_pgd_entry, - __pgd(_KERNPG_TABLE | __pa(p4d_page_tramp))); + trampoline_pgd_entry = + __pgd(_KERNPG_TABLE | __pa(p4d_page_tramp)); } else { - set_pgd(&trampoline_pgd_entry, - __pgd(_KERNPG_TABLE | __pa(pud_page_tramp))); + trampoline_pgd_entry = + __pgd(_KERNPG_TABLE | __pa(pud_page_tramp)); } } diff --git a/arch/x86/mm/mem_encrypt_amd.c b/arch/x86/mm/mem_encrypt_amd.c index e0b51c09109f66ea6d04300e5c9afc3e98a7ff95..54bbd5163e8d396f79e762e738a8cf5e8a913311 100644 --- a/arch/x86/mm/mem_encrypt_amd.c +++ b/arch/x86/mm/mem_encrypt_amd.c @@ -319,7 +319,7 @@ static void enc_dec_hypercall(unsigned long vaddr, int npages, bool enc) #endif } -static void amd_enc_status_change_prepare(unsigned long vaddr, int npages, bool enc) +static bool amd_enc_status_change_prepare(unsigned long vaddr, int npages, bool enc) { /* * To maintain the security guarantees of SEV-SNP guests, make sure @@ -327,6 +327,8 @@ static void amd_enc_status_change_prepare(unsigned long vaddr, int npages, bool */ if (cc_platform_has(CC_ATTR_GUEST_SEV_SNP) && !enc) snp_set_memory_shared(vaddr, npages); + + return true; } /* Return true unconditionally: return value doesn't matter for the SEV side */ @@ -501,6 +503,21 @@ void __init sme_early_init(void) x86_platform.guest.enc_status_change_finish = amd_enc_status_change_finish; x86_platform.guest.enc_tlb_flush_required = amd_enc_tlb_flush_required; x86_platform.guest.enc_cache_flush_required = amd_enc_cache_flush_required; + + /* + * AMD-SEV-ES intercepts the RDMSR to read the X2APIC ID in the + * parallel bringup low level code. That raises #VC which cannot be + * handled there. + * It does not provide a RDMSR GHCB protocol so the early startup + * code cannot directly communicate with the secure firmware. The + * alternative solution to retrieve the APIC ID via CPUID(0xb), + * which is covered by the GHCB protocol, is not viable either + * because there is no enforcement of the CPUID(0xb) provided + * "initial" APIC ID to be the same as the real APIC ID. + * Disable parallel bootup. + */ + if (sev_status & MSR_AMD64_SEV_ES_ENABLED) + x86_cpuinit.parallel_bringup = false; } void __init mem_encrypt_free_decrypted_mem(void) diff --git a/arch/x86/mm/mem_encrypt_identity.c b/arch/x86/mm/mem_encrypt_identity.c index c6efcf559d8821261cb1724bf45275101a351238..d73aeb16417fcfbb99607c3bc2241962e3590948 100644 --- a/arch/x86/mm/mem_encrypt_identity.c +++ b/arch/x86/mm/mem_encrypt_identity.c @@ -188,7 +188,7 @@ static void __init sme_populate_pgd(struct sme_populate_pgd_data *ppd) if (pmd_large(*pmd)) return; - pte = pte_offset_map(pmd, ppd->vaddr); + pte = pte_offset_kernel(pmd, ppd->vaddr); if (pte_none(*pte)) set_pte(pte, __pte(ppd->paddr | ppd->pte_flags)); } @@ -612,7 +612,7 @@ void __init sme_enable(struct boot_params *bp) out: if (sme_me_mask) { physical_mask &= ~sme_me_mask; - cc_set_vendor(CC_VENDOR_AMD); + cc_vendor = CC_VENDOR_AMD; cc_set_mask(sme_me_mask); } } diff --git a/arch/x86/mm/pat/set_memory.c b/arch/x86/mm/pat/set_memory.c index 7159cf7876130abde0acadd3c34e0a1b86eb41e1..df4182b6449f607177ad7aeaa83135ca335d6564 100644 --- a/arch/x86/mm/pat/set_memory.c +++ b/arch/x86/mm/pat/set_memory.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -231,7 +232,7 @@ within_inclusive(unsigned long addr, unsigned long start, unsigned long end) * points to #2, but almost all physical-to-virtual translations point to #1. * * This is so that we can have both a directmap of all physical memory *and* - * take full advantage of the the limited (s32) immediate addressing range (2G) + * take full advantage of the limited (s32) immediate addressing range (2G) * of x86_64. * * See Documentation/arch/x86/x86_64/mm.rst for more detail. @@ -2151,7 +2152,8 @@ static int __set_memory_enc_pgtable(unsigned long addr, int numpages, bool enc) cpa_flush(&cpa, x86_platform.guest.enc_cache_flush_required()); /* Notify hypervisor that we are about to set/clr encryption attribute. */ - x86_platform.guest.enc_status_change_prepare(addr, numpages, enc); + if (!x86_platform.guest.enc_status_change_prepare(addr, numpages, enc)) + return -EIO; ret = __change_page_attr_set_clr(&cpa, 1); diff --git a/arch/x86/mm/pgtable.c b/arch/x86/mm/pgtable.c index e4f499eb0f295beda06263181a0247e0d76eaac7..15a8009a4480a98abcd25aca53ab8a45da42bef9 100644 --- a/arch/x86/mm/pgtable.c +++ b/arch/x86/mm/pgtable.c @@ -702,14 +702,8 @@ void p4d_clear_huge(p4d_t *p4d) * pud_set_huge - setup kernel PUD mapping * * MTRRs can override PAT memory types with 4KiB granularity. Therefore, this - * function sets up a huge page only if any of the following conditions are met: - * - * - MTRRs are disabled, or - * - * - MTRRs are enabled and the range is completely covered by a single MTRR, or - * - * - MTRRs are enabled and the corresponding MTRR memory type is WB, which - * has no effect on the requested PAT memory type. + * function sets up a huge page only if the complete range has the same MTRR + * caching mode. * * Callers should try to decrease page size (1GB -> 2MB -> 4K) if the bigger * page mapping attempt fails. @@ -718,11 +712,10 @@ void p4d_clear_huge(p4d_t *p4d) */ int pud_set_huge(pud_t *pud, phys_addr_t addr, pgprot_t prot) { - u8 mtrr, uniform; + u8 uniform; - mtrr = mtrr_type_lookup(addr, addr + PUD_SIZE, &uniform); - if ((mtrr != MTRR_TYPE_INVALID) && (!uniform) && - (mtrr != MTRR_TYPE_WRBACK)) + mtrr_type_lookup(addr, addr + PUD_SIZE, &uniform); + if (!uniform) return 0; /* Bail out if we are we on a populated non-leaf entry: */ @@ -745,11 +738,10 @@ int pud_set_huge(pud_t *pud, phys_addr_t addr, pgprot_t prot) */ int pmd_set_huge(pmd_t *pmd, phys_addr_t addr, pgprot_t prot) { - u8 mtrr, uniform; + u8 uniform; - mtrr = mtrr_type_lookup(addr, addr + PMD_SIZE, &uniform); - if ((mtrr != MTRR_TYPE_INVALID) && (!uniform) && - (mtrr != MTRR_TYPE_WRBACK)) { + mtrr_type_lookup(addr, addr + PMD_SIZE, &uniform); + if (!uniform) { pr_warn_once("%s: Cannot satisfy [mem %#010llx-%#010llx] with a huge-page mapping due to MTRR override.\n", __func__, addr, addr + PMD_SIZE); return 0; diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c index 1056bbf55b172c4e1ad1992be7b53b34ceef9156..438adb695daab16cb60cc9239ce8107796a836d7 100644 --- a/arch/x86/net/bpf_jit_comp.c +++ b/arch/x86/net/bpf_jit_comp.c @@ -2570,7 +2570,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog) } if (bpf_jit_enable > 1) - bpf_jit_dump(prog->len, proglen, pass + 1, image); + bpf_jit_dump(prog->len, proglen, pass + 1, rw_image); if (image) { if (!prog->is_func || extra_pass) { diff --git a/arch/x86/pci/ce4100.c b/arch/x86/pci/ce4100.c index 584c25b588b40ba3ce17ef0137a4add1b3b9f165..87313701f069ea5a8fc19a3de16c513259bc7575 100644 --- a/arch/x86/pci/ce4100.c +++ b/arch/x86/pci/ce4100.c @@ -83,7 +83,7 @@ static void ehci_reg_read(struct sim_dev_reg *reg, u32 *value) *value |= 0x100; } -void sata_revid_init(struct sim_dev_reg *reg) +static void sata_revid_init(struct sim_dev_reg *reg) { reg->sim_reg.value = 0x01060100; reg->sim_reg.mask = 0; @@ -172,7 +172,7 @@ static inline void extract_bytes(u32 *value, int reg, int len) *value &= mask; } -int bridge_read(unsigned int devfn, int reg, int len, u32 *value) +static int bridge_read(unsigned int devfn, int reg, int len, u32 *value) { u32 av_bridge_base, av_bridge_limit; int retval = 0; diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index f3f2d87cce1b9631d35105884a2c2767e918d790..e9f99c56f3ce625d0b568124091ff3281dd03b87 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c @@ -96,6 +96,9 @@ static const unsigned long * const efi_tables[] = { #ifdef CONFIG_EFI_COCO_SECRET &efi.coco_secret, #endif +#ifdef CONFIG_UNACCEPTED_MEMORY + &efi.unaccepted, +#endif }; u64 efi_setup; /* efi setup_data physical address */ diff --git a/arch/x86/platform/efi/efi_64.c b/arch/x86/platform/efi/efi_64.c index 232acf418cfbe625b5a5a427bf06ad26a05396ac..77f7ac3668cb4ac0c97d01a7dce648e01be15fbb 100644 --- a/arch/x86/platform/efi/efi_64.c +++ b/arch/x86/platform/efi/efi_64.c @@ -853,9 +853,9 @@ efi_set_virtual_address_map(unsigned long memory_map_size, /* Disable interrupts around EFI calls: */ local_irq_save(flags); - status = efi_call(efi.runtime->set_virtual_address_map, - memory_map_size, descriptor_size, - descriptor_version, virtual_map); + status = arch_efi_call_virt(efi.runtime, set_virtual_address_map, + memory_map_size, descriptor_size, + descriptor_version, virtual_map); local_irq_restore(flags); efi_fpu_end(); diff --git a/arch/x86/platform/efi/quirks.c b/arch/x86/platform/efi/quirks.c index b0b848d6933afbcf118415ea6689488e28675054..f0cc00032751d063955e10ee556b08ca4b3806a9 100644 --- a/arch/x86/platform/efi/quirks.c +++ b/arch/x86/platform/efi/quirks.c @@ -114,6 +114,14 @@ void efi_delete_dummy_variable(void) EFI_VARIABLE_RUNTIME_ACCESS, 0, NULL); } +u64 efivar_reserved_space(void) +{ + if (efi_no_storage_paranoia) + return 0; + return EFI_MIN_RESERVE; +} +EXPORT_SYMBOL_GPL(efivar_reserved_space); + /* * In the nonblocking case we do not attempt to perform garbage * collection if we do not have enough free space. Rather, we do the diff --git a/arch/x86/platform/efi/runtime-map.c b/arch/x86/platform/efi/runtime-map.c index bbee682ef8cd1b19a8749cb8da73e441aad957be..a6f02cef3ca2b8a97210193db5f63001a9215bf6 100644 --- a/arch/x86/platform/efi/runtime-map.c +++ b/arch/x86/platform/efi/runtime-map.c @@ -93,7 +93,7 @@ static void map_release(struct kobject *kobj) kfree(entry); } -static struct kobj_type __refdata map_ktype = { +static const struct kobj_type __refconst map_ktype = { .sysfs_ops = &map_attr_ops, .default_groups = def_groups, .release = map_release, diff --git a/arch/x86/platform/olpc/olpc_dt.c b/arch/x86/platform/olpc/olpc_dt.c index 75e3319e8bee5b22986473c5690cc4da8bc56e9c..74ebd6882690b820edcfbe532dd05bf26c7ea16d 100644 --- a/arch/x86/platform/olpc/olpc_dt.c +++ b/arch/x86/platform/olpc/olpc_dt.c @@ -234,7 +234,7 @@ static int __init olpc_dt_compatible_match(phandle node, const char *compat) return 0; } -void __init olpc_dt_fixup(void) +static void __init olpc_dt_fixup(void) { phandle node; u32 board_rev; diff --git a/arch/x86/power/cpu.c b/arch/x86/power/cpu.c index 7a4d5e91141528e9b87fc3a3719aa2a82f537615..63230ff8cf4f0612054a768e8073de5261ba1895 100644 --- a/arch/x86/power/cpu.c +++ b/arch/x86/power/cpu.c @@ -351,43 +351,6 @@ static int bsp_pm_callback(struct notifier_block *nb, unsigned long action, case PM_HIBERNATION_PREPARE: ret = bsp_check(); break; -#ifdef CONFIG_DEBUG_HOTPLUG_CPU0 - case PM_RESTORE_PREPARE: - /* - * When system resumes from hibernation, online CPU0 because - * 1. it's required for resume and - * 2. the CPU was online before hibernation - */ - if (!cpu_online(0)) - _debug_hotplug_cpu(0, 1); - break; - case PM_POST_RESTORE: - /* - * When a resume really happens, this code won't be called. - * - * This code is called only when user space hibernation software - * prepares for snapshot device during boot time. So we just - * call _debug_hotplug_cpu() to restore to CPU0's state prior to - * preparing the snapshot device. - * - * This works for normal boot case in our CPU0 hotplug debug - * mode, i.e. CPU0 is offline and user mode hibernation - * software initializes during boot time. - * - * If CPU0 is online and user application accesses snapshot - * device after boot time, this will offline CPU0 and user may - * see different CPU0 state before and after accessing - * the snapshot device. But hopefully this is not a case when - * user debugging CPU0 hotplug. Even if users hit this case, - * they can easily online CPU0 back. - * - * To simplify this debug code, we only consider normal boot - * case. Otherwise we need to remember CPU0's state and restore - * to that state and resolve racy conditions etc. - */ - _debug_hotplug_cpu(0, 0); - break; -#endif default: break; } diff --git a/arch/x86/purgatory/Makefile b/arch/x86/purgatory/Makefile index 42abd6af119846977f7e8eea870bef761876a480..c2a29be35c01bb306efbd01daabb618636f6d880 100644 --- a/arch/x86/purgatory/Makefile +++ b/arch/x86/purgatory/Makefile @@ -12,7 +12,7 @@ $(obj)/string.o: $(srctree)/arch/x86/boot/compressed/string.c FORCE $(obj)/sha256.o: $(srctree)/lib/crypto/sha256.c FORCE $(call if_changed_rule,cc_o_c) -CFLAGS_sha256.o := -D__DISABLE_EXPORTS +CFLAGS_sha256.o := -D__DISABLE_EXPORTS -D__NO_FORTIFY # When profile-guided optimization is enabled, llvm emits two different # overlapping text sections, which is not supported by kexec. Remove profile diff --git a/arch/x86/realmode/init.c b/arch/x86/realmode/init.c index af565816d2ba6aed5df706910d9e43e773b53fcb..788e5559549f39ab72573fb582d5964ce3490ed0 100644 --- a/arch/x86/realmode/init.c +++ b/arch/x86/realmode/init.c @@ -154,6 +154,9 @@ static void __init setup_real_mode(void) trampoline_header->flags = 0; + trampoline_lock = &trampoline_header->lock; + *trampoline_lock = 0; + trampoline_pgd = (u64 *) __va(real_mode_header->trampoline_pgd); /* Map the real mode stub as virtual == physical */ diff --git a/arch/x86/realmode/rm/trampoline_64.S b/arch/x86/realmode/rm/trampoline_64.S index e38d61d6562e4611c9150b935b018bee46717fe5..c9f76fae902e4b2f4cd4268bda51a82e018c1d65 100644 --- a/arch/x86/realmode/rm/trampoline_64.S +++ b/arch/x86/realmode/rm/trampoline_64.S @@ -37,6 +37,24 @@ .text .code16 +.macro LOCK_AND_LOAD_REALMODE_ESP lock_pa=0 + /* + * Make sure only one CPU fiddles with the realmode stack + */ +.Llock_rm\@: + .if \lock_pa + lock btsl $0, pa_tr_lock + .else + lock btsl $0, tr_lock + .endif + jnc 2f + pause + jmp .Llock_rm\@ +2: + # Setup stack + movl $rm_stack_end, %esp +.endm + .balign PAGE_SIZE SYM_CODE_START(trampoline_start) cli # We should be safe anyway @@ -49,8 +67,7 @@ SYM_CODE_START(trampoline_start) mov %ax, %es mov %ax, %ss - # Setup stack - movl $rm_stack_end, %esp + LOCK_AND_LOAD_REALMODE_ESP call verify_cpu # Verify the cpu supports long mode testl %eax, %eax # Check for return code @@ -93,8 +110,7 @@ SYM_CODE_START(sev_es_trampoline_start) mov %ax, %es mov %ax, %ss - # Setup stack - movl $rm_stack_end, %esp + LOCK_AND_LOAD_REALMODE_ESP jmp .Lswitch_to_protected SYM_CODE_END(sev_es_trampoline_start) @@ -177,7 +193,7 @@ SYM_CODE_START(pa_trampoline_compat) * In compatibility mode. Prep ESP and DX for startup_32, then disable * paging and complete the switch to legacy 32-bit mode. */ - movl $rm_stack_end, %esp + LOCK_AND_LOAD_REALMODE_ESP lock_pa=1 movw $__KERNEL_DS, %dx movl $(CR0_STATE & ~X86_CR0_PG), %eax @@ -241,6 +257,7 @@ SYM_DATA_START(trampoline_header) SYM_DATA(tr_efer, .space 8) SYM_DATA(tr_cr4, .space 4) SYM_DATA(tr_flags, .space 4) + SYM_DATA(tr_lock, .space 4) SYM_DATA_END(trampoline_header) #include "trampoline_common.S" diff --git a/arch/x86/video/fbdev.c b/arch/x86/video/fbdev.c index f41a17ebac48d7371db31fb00174c35825a0c605..49a0452402e97f6d0c325e4cf0429d59603e138f 100644 --- a/arch/x86/video/fbdev.c +++ b/arch/x86/video/fbdev.c @@ -11,6 +11,7 @@ #include #include #include +#include void fb_pgprotect(struct file *file, struct vm_area_struct *vma, unsigned long off) { diff --git a/arch/x86/xen/efi.c b/arch/x86/xen/efi.c index 7d7ffb9c826a3a5efc8c4e1fcdcccbc1260b754b..863d0d6b3edc47e06346c378356b412ba2358707 100644 --- a/arch/x86/xen/efi.c +++ b/arch/x86/xen/efi.c @@ -16,6 +16,8 @@ #include #include +#include "xen-ops.h" + static efi_char16_t vendor[100] __initdata; static efi_system_table_t efi_systab_xen __initdata = { diff --git a/arch/x86/xen/enlighten_hvm.c b/arch/x86/xen/enlighten_hvm.c index c1cd28e915a3a9a853d8e572cf516e10affdd8db..a6820ca940bf072930a604e2cdaee12c74ef9895 100644 --- a/arch/x86/xen/enlighten_hvm.c +++ b/arch/x86/xen/enlighten_hvm.c @@ -161,13 +161,12 @@ static int xen_cpu_up_prepare_hvm(unsigned int cpu) int rc = 0; /* - * This can happen if CPU was offlined earlier and - * offlining timed out in common_cpu_die(). + * If a CPU was offlined earlier and offlining timed out then the + * lock mechanism is still initialized. Uninit it unconditionally + * as it's safe to call even if already uninited. Interrupts and + * timer have already been handled in xen_cpu_dead_hvm(). */ - if (cpu_report_state(cpu) == CPU_DEAD_FROZEN) { - xen_smp_intr_free(cpu); - xen_uninit_lock_cpu(cpu); - } + xen_uninit_lock_cpu(cpu); if (cpu_acpi_id(cpu) != U32_MAX) per_cpu(xen_vcpu_id, cpu) = cpu_acpi_id(cpu); diff --git a/arch/x86/xen/enlighten_pv.c b/arch/x86/xen/enlighten_pv.c index 093b78c8bbec0724e59947211b55e3eaae76cc8c..93b658248d013c5a64c441fbcd5110945501211e 100644 --- a/arch/x86/xen/enlighten_pv.c +++ b/arch/x86/xen/enlighten_pv.c @@ -68,6 +68,7 @@ #include #include #include +#include #include #include #include @@ -119,6 +120,54 @@ static int __init parse_xen_msr_safe(char *str) } early_param("xen_msr_safe", parse_xen_msr_safe); +/* Get MTRR settings from Xen and put them into mtrr_state. */ +static void __init xen_set_mtrr_data(void) +{ +#ifdef CONFIG_MTRR + struct xen_platform_op op = { + .cmd = XENPF_read_memtype, + .interface_version = XENPF_INTERFACE_VERSION, + }; + unsigned int reg; + unsigned long mask; + uint32_t eax, width; + static struct mtrr_var_range var[MTRR_MAX_VAR_RANGES] __initdata; + + /* Get physical address width (only 64-bit cpus supported). */ + width = 36; + eax = cpuid_eax(0x80000000); + if ((eax >> 16) == 0x8000 && eax >= 0x80000008) { + eax = cpuid_eax(0x80000008); + width = eax & 0xff; + } + + for (reg = 0; reg < MTRR_MAX_VAR_RANGES; reg++) { + op.u.read_memtype.reg = reg; + if (HYPERVISOR_platform_op(&op)) + break; + + /* + * Only called in dom0, which has all RAM PFNs mapped at + * RAM MFNs, and all PCI space etc. is identity mapped. + * This means we can treat MFN == PFN regarding MTRR settings. + */ + var[reg].base_lo = op.u.read_memtype.type; + var[reg].base_lo |= op.u.read_memtype.mfn << PAGE_SHIFT; + var[reg].base_hi = op.u.read_memtype.mfn >> (32 - PAGE_SHIFT); + mask = ~((op.u.read_memtype.nr_mfns << PAGE_SHIFT) - 1); + mask &= (1UL << width) - 1; + if (mask) + mask |= MTRR_PHYSMASK_V; + var[reg].mask_lo = mask; + var[reg].mask_hi = mask >> 32; + } + + /* Only overwrite MTRR state if any MTRR could be got from Xen. */ + if (reg) + mtrr_overwrite_state(var, reg, MTRR_TYPE_UNCACHABLE); +#endif +} + static void __init xen_pv_init_platform(void) { /* PV guests can't operate virtio devices without grants. */ @@ -135,6 +184,11 @@ static void __init xen_pv_init_platform(void) /* pvclock is in shared info area */ xen_init_time_ops(); + + if (xen_initial_domain()) + xen_set_mtrr_data(); + else + mtrr_overwrite_state(NULL, 0, MTRR_TYPE_WRBACK); } static void __init xen_pv_guest_late_init(void) diff --git a/arch/x86/xen/mmu_pv.c b/arch/x86/xen/mmu_pv.c index b3b8d289b9abfcac97604501adf9efccb04e0644..e0a975165de7869c7ee00aca011c6104f1465334 100644 --- a/arch/x86/xen/mmu_pv.c +++ b/arch/x86/xen/mmu_pv.c @@ -86,6 +86,22 @@ #include "mmu.h" #include "debugfs.h" +/* + * Prototypes for functions called via PV_CALLEE_SAVE_REGS_THUNK() in order + * to avoid warnings with "-Wmissing-prototypes". + */ +pteval_t xen_pte_val(pte_t pte); +pgdval_t xen_pgd_val(pgd_t pgd); +pmdval_t xen_pmd_val(pmd_t pmd); +pudval_t xen_pud_val(pud_t pud); +p4dval_t xen_p4d_val(p4d_t p4d); +pte_t xen_make_pte(pteval_t pte); +pgd_t xen_make_pgd(pgdval_t pgd); +pmd_t xen_make_pmd(pmdval_t pmd); +pud_t xen_make_pud(pudval_t pud); +p4d_t xen_make_p4d(p4dval_t p4d); +pte_t xen_make_pte_init(pteval_t pte); + #ifdef CONFIG_X86_VSYSCALL_EMULATION /* l3 pud for userspace vsyscall mapping */ static pud_t level3_user_vsyscall[PTRS_PER_PUD] __page_aligned_bss; diff --git a/arch/x86/xen/setup.c b/arch/x86/xen/setup.c index c2be3efb2ba0fae74200fef92a905e105ce7de4c..8b5cf7bb1f47f802eb2da44fb76771b73d9049c3 100644 --- a/arch/x86/xen/setup.c +++ b/arch/x86/xen/setup.c @@ -6,6 +6,7 @@ */ #include +#include #include #include #include @@ -764,17 +765,26 @@ char * __init xen_memory_setup(void) BUG_ON(memmap.nr_entries == 0); xen_e820_table.nr_entries = memmap.nr_entries; - /* - * Xen won't allow a 1:1 mapping to be created to UNUSABLE - * regions, so if we're using the machine memory map leave the - * region as RAM as it is in the pseudo-physical map. - * - * UNUSABLE regions in domUs are not handled and will need - * a patch in the future. - */ - if (xen_initial_domain()) + if (xen_initial_domain()) { + /* + * Xen won't allow a 1:1 mapping to be created to UNUSABLE + * regions, so if we're using the machine memory map leave the + * region as RAM as it is in the pseudo-physical map. + * + * UNUSABLE regions in domUs are not handled and will need + * a patch in the future. + */ xen_ignore_unusable(); +#ifdef CONFIG_ISCSI_IBFT_FIND + /* Reserve 0.5 MiB to 1 MiB region so iBFT can be found */ + xen_e820_table.entries[xen_e820_table.nr_entries].addr = IBFT_START; + xen_e820_table.entries[xen_e820_table.nr_entries].size = IBFT_END - IBFT_START; + xen_e820_table.entries[xen_e820_table.nr_entries].type = E820_TYPE_RESERVED; + xen_e820_table.nr_entries++; +#endif + } + /* Make sure the Xen-supplied memory map is well-ordered. */ e820__update_table(&xen_e820_table); diff --git a/arch/x86/xen/smp.h b/arch/x86/xen/smp.h index 22fb982ff97134c5f7edbf09eebb7f583ff3342e..c20cbb14c82bad72f5703297d49ac8aa775e4425 100644 --- a/arch/x86/xen/smp.h +++ b/arch/x86/xen/smp.h @@ -2,6 +2,10 @@ #ifndef _XEN_SMP_H #ifdef CONFIG_SMP + +void asm_cpu_bringup_and_idle(void); +asmlinkage void cpu_bringup_and_idle(void); + extern void xen_send_IPI_mask(const struct cpumask *mask, int vector); extern void xen_send_IPI_mask_allbutself(const struct cpumask *mask, diff --git a/arch/x86/xen/smp_hvm.c b/arch/x86/xen/smp_hvm.c index b70afdff419ca3cc9591e7d5e180b765271ed34a..ac95d1981cc0bae3211eb43fb66023dfbb6d460d 100644 --- a/arch/x86/xen/smp_hvm.c +++ b/arch/x86/xen/smp_hvm.c @@ -55,18 +55,16 @@ static void __init xen_hvm_smp_prepare_cpus(unsigned int max_cpus) } #ifdef CONFIG_HOTPLUG_CPU -static void xen_hvm_cpu_die(unsigned int cpu) +static void xen_hvm_cleanup_dead_cpu(unsigned int cpu) { - if (common_cpu_die(cpu) == 0) { - if (xen_have_vector_callback) { - xen_smp_intr_free(cpu); - xen_uninit_lock_cpu(cpu); - xen_teardown_timer(cpu); - } + if (xen_have_vector_callback) { + xen_smp_intr_free(cpu); + xen_uninit_lock_cpu(cpu); + xen_teardown_timer(cpu); } } #else -static void xen_hvm_cpu_die(unsigned int cpu) +static void xen_hvm_cleanup_dead_cpu(unsigned int cpu) { BUG(); } @@ -77,7 +75,7 @@ void __init xen_hvm_smp_init(void) smp_ops.smp_prepare_boot_cpu = xen_hvm_smp_prepare_boot_cpu; smp_ops.smp_prepare_cpus = xen_hvm_smp_prepare_cpus; smp_ops.smp_cpus_done = xen_smp_cpus_done; - smp_ops.cpu_die = xen_hvm_cpu_die; + smp_ops.cleanup_dead_cpu = xen_hvm_cleanup_dead_cpu; if (!xen_have_vector_callback) { #ifdef CONFIG_PARAVIRT_SPINLOCKS diff --git a/arch/x86/xen/smp_pv.c b/arch/x86/xen/smp_pv.c index a9cf8c8fa074cd58b18c6edcf591d99fcebe13e1..cef78b8c89f4456acc8d1f5f261320c41a319a2f 100644 --- a/arch/x86/xen/smp_pv.c +++ b/arch/x86/xen/smp_pv.c @@ -55,14 +55,15 @@ static DEFINE_PER_CPU(struct xen_common_irq, xen_irq_work) = { .irq = -1 }; static DEFINE_PER_CPU(struct xen_common_irq, xen_pmu_irq) = { .irq = -1 }; static irqreturn_t xen_irq_work_interrupt(int irq, void *dev_id); -void asm_cpu_bringup_and_idle(void); static void cpu_bringup(void) { int cpu; cr4_init(); + cpuhp_ap_sync_alive(); cpu_init(); + fpu__init_cpu(); touch_softlockup_watchdog(); /* PVH runs in ring 0 and allows us to do native syscalls. Yay! */ @@ -83,7 +84,7 @@ static void cpu_bringup(void) set_cpu_online(cpu, true); - cpu_set_state_online(cpu); /* Implies full memory barrier. */ + smp_mb(); /* We can take interrupts now: we're officially "up". */ local_irq_enable(); @@ -254,15 +255,12 @@ cpu_initialize_context(unsigned int cpu, struct task_struct *idle) struct desc_struct *gdt; unsigned long gdt_mfn; - /* used to tell cpu_init() that it can proceed with initialization */ - cpumask_set_cpu(cpu, cpu_callout_mask); if (cpumask_test_and_set_cpu(cpu, xen_cpu_initialized_map)) return 0; ctxt = kzalloc(sizeof(*ctxt), GFP_KERNEL); if (ctxt == NULL) { cpumask_clear_cpu(cpu, xen_cpu_initialized_map); - cpumask_clear_cpu(cpu, cpu_callout_mask); return -ENOMEM; } @@ -316,7 +314,7 @@ cpu_initialize_context(unsigned int cpu, struct task_struct *idle) return 0; } -static int xen_pv_cpu_up(unsigned int cpu, struct task_struct *idle) +static int xen_pv_kick_ap(unsigned int cpu, struct task_struct *idle) { int rc; @@ -326,14 +324,6 @@ static int xen_pv_cpu_up(unsigned int cpu, struct task_struct *idle) xen_setup_runstate_info(cpu); - /* - * PV VCPUs are always successfully taken down (see 'while' loop - * in xen_cpu_die()), so -EBUSY is an error. - */ - rc = cpu_check_up_prepare(cpu); - if (rc) - return rc; - /* make sure interrupts start blocked */ per_cpu(xen_vcpu, cpu)->evtchn_upcall_mask = 1; @@ -343,15 +333,20 @@ static int xen_pv_cpu_up(unsigned int cpu, struct task_struct *idle) xen_pmu_init(cpu); - rc = HYPERVISOR_vcpu_op(VCPUOP_up, xen_vcpu_nr(cpu), NULL); - BUG_ON(rc); - - while (cpu_report_state(cpu) != CPU_ONLINE) - HYPERVISOR_sched_op(SCHEDOP_yield, NULL); + /* + * Why is this a BUG? If the hypercall fails then everything can be + * rolled back, no? + */ + BUG_ON(HYPERVISOR_vcpu_op(VCPUOP_up, xen_vcpu_nr(cpu), NULL)); return 0; } +static void xen_pv_poll_sync_state(void) +{ + HYPERVISOR_sched_op(SCHEDOP_yield, NULL); +} + #ifdef CONFIG_HOTPLUG_CPU static int xen_pv_cpu_disable(void) { @@ -367,18 +362,18 @@ static int xen_pv_cpu_disable(void) static void xen_pv_cpu_die(unsigned int cpu) { - while (HYPERVISOR_vcpu_op(VCPUOP_is_up, - xen_vcpu_nr(cpu), NULL)) { + while (HYPERVISOR_vcpu_op(VCPUOP_is_up, xen_vcpu_nr(cpu), NULL)) { __set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(HZ/10); } +} - if (common_cpu_die(cpu) == 0) { - xen_smp_intr_free(cpu); - xen_uninit_lock_cpu(cpu); - xen_teardown_timer(cpu); - xen_pmu_finish(cpu); - } +static void xen_pv_cleanup_dead_cpu(unsigned int cpu) +{ + xen_smp_intr_free(cpu); + xen_uninit_lock_cpu(cpu); + xen_teardown_timer(cpu); + xen_pmu_finish(cpu); } static void __noreturn xen_pv_play_dead(void) /* used only with HOTPLUG_CPU */ @@ -400,6 +395,11 @@ static void xen_pv_cpu_die(unsigned int cpu) BUG(); } +static void xen_pv_cleanup_dead_cpu(unsigned int cpu) +{ + BUG(); +} + static void __noreturn xen_pv_play_dead(void) { BUG(); @@ -438,8 +438,10 @@ static const struct smp_ops xen_smp_ops __initconst = { .smp_prepare_cpus = xen_pv_smp_prepare_cpus, .smp_cpus_done = xen_smp_cpus_done, - .cpu_up = xen_pv_cpu_up, + .kick_ap_alive = xen_pv_kick_ap, .cpu_die = xen_pv_cpu_die, + .cleanup_dead_cpu = xen_pv_cleanup_dead_cpu, + .poll_sync_state = xen_pv_poll_sync_state, .cpu_disable = xen_pv_cpu_disable, .play_dead = xen_pv_play_dead, diff --git a/arch/x86/xen/time.c b/arch/x86/xen/time.c index b74ac2562cfbafddf4be10d53983515febbc7276..52fa5609b7f64d13e40583b02fe70f44b92aeab1 100644 --- a/arch/x86/xen/time.c +++ b/arch/x86/xen/time.c @@ -66,11 +66,10 @@ static noinstr u64 xen_sched_clock(void) struct pvclock_vcpu_time_info *src; u64 ret; - preempt_disable_notrace(); src = &__this_cpu_read(xen_vcpu)->time; ret = pvclock_clocksource_read_nowd(src); ret -= xen_sched_clock_offset; - preempt_enable_notrace(); + return ret; } diff --git a/arch/x86/xen/xen-head.S b/arch/x86/xen/xen-head.S index 643d02900fbb0561492c23bd0a588ff5ce9806b0..a0ea285878dbe168ce5bf8cea61d5c642c4d0b72 100644 --- a/arch/x86/xen/xen-head.S +++ b/arch/x86/xen/xen-head.S @@ -90,30 +90,35 @@ SYM_CODE_END(xen_cpu_bringup_again) ELFNOTE(Xen, XEN_ELFNOTE_GUEST_OS, .asciz "linux") ELFNOTE(Xen, XEN_ELFNOTE_GUEST_VERSION, .asciz "2.6") ELFNOTE(Xen, XEN_ELFNOTE_XEN_VERSION, .asciz "xen-3.0") -#ifdef CONFIG_X86_32 - ELFNOTE(Xen, XEN_ELFNOTE_VIRT_BASE, _ASM_PTR __PAGE_OFFSET) -#else +#ifdef CONFIG_XEN_PV ELFNOTE(Xen, XEN_ELFNOTE_VIRT_BASE, _ASM_PTR __START_KERNEL_map) /* Map the p2m table to a 512GB-aligned user address. */ ELFNOTE(Xen, XEN_ELFNOTE_INIT_P2M, .quad (PUD_SIZE * PTRS_PER_PUD)) -#endif -#ifdef CONFIG_XEN_PV ELFNOTE(Xen, XEN_ELFNOTE_ENTRY, _ASM_PTR startup_xen) -#endif - ELFNOTE(Xen, XEN_ELFNOTE_HYPERCALL_PAGE, _ASM_PTR hypercall_page) - ELFNOTE(Xen, XEN_ELFNOTE_FEATURES, - .ascii "!writable_page_tables|pae_pgdir_above_4gb") - ELFNOTE(Xen, XEN_ELFNOTE_SUPPORTED_FEATURES, - .long (1 << XENFEAT_writable_page_tables) | \ - (1 << XENFEAT_dom0) | \ - (1 << XENFEAT_linux_rsdp_unrestricted)) + ELFNOTE(Xen, XEN_ELFNOTE_FEATURES, .ascii "!writable_page_tables") ELFNOTE(Xen, XEN_ELFNOTE_PAE_MODE, .asciz "yes") - ELFNOTE(Xen, XEN_ELFNOTE_LOADER, .asciz "generic") ELFNOTE(Xen, XEN_ELFNOTE_L1_MFN_VALID, .quad _PAGE_PRESENT; .quad _PAGE_PRESENT) - ELFNOTE(Xen, XEN_ELFNOTE_SUSPEND_CANCEL, .long 1) ELFNOTE(Xen, XEN_ELFNOTE_MOD_START_PFN, .long 1) - ELFNOTE(Xen, XEN_ELFNOTE_HV_START_LOW, _ASM_PTR __HYPERVISOR_VIRT_START) ELFNOTE(Xen, XEN_ELFNOTE_PADDR_OFFSET, _ASM_PTR 0) +# define FEATURES_PV (1 << XENFEAT_writable_page_tables) +#else +# define FEATURES_PV 0 +#endif +#ifdef CONFIG_XEN_PVH +# define FEATURES_PVH (1 << XENFEAT_linux_rsdp_unrestricted) +#else +# define FEATURES_PVH 0 +#endif +#ifdef CONFIG_XEN_DOM0 +# define FEATURES_DOM0 (1 << XENFEAT_dom0) +#else +# define FEATURES_DOM0 0 +#endif + ELFNOTE(Xen, XEN_ELFNOTE_HYPERCALL_PAGE, _ASM_PTR hypercall_page) + ELFNOTE(Xen, XEN_ELFNOTE_SUPPORTED_FEATURES, + .long FEATURES_PV | FEATURES_PVH | FEATURES_DOM0) + ELFNOTE(Xen, XEN_ELFNOTE_LOADER, .asciz "generic") + ELFNOTE(Xen, XEN_ELFNOTE_SUSPEND_CANCEL, .long 1) #endif /*CONFIG_XEN */ diff --git a/arch/x86/xen/xen-ops.h b/arch/x86/xen/xen-ops.h index a10903785a33863c358de6d73ede4dd38a82be80..408a2aa66c6922e0df72732358e6e1e96bb105bc 100644 --- a/arch/x86/xen/xen-ops.h +++ b/arch/x86/xen/xen-ops.h @@ -72,8 +72,6 @@ void xen_restore_time_memory_area(void); void xen_init_time_ops(void); void xen_hvm_init_time_ops(void); -irqreturn_t xen_debug_interrupt(int irq, void *dev_id); - bool xen_vcpu_stolen(int vcpu); void xen_vcpu_setup(int cpu); @@ -148,9 +146,12 @@ int xen_cpuhp_setup(int (*cpu_up_prepare_cb)(unsigned int), void xen_pin_vcpu(int cpu); void xen_emergency_restart(void); +void xen_force_evtchn_callback(void); + #ifdef CONFIG_XEN_PV void xen_pv_pre_suspend(void); void xen_pv_post_suspend(int suspend_cancelled); +void xen_start_kernel(struct start_info *si); #else static inline void xen_pv_pre_suspend(void) {} static inline void xen_pv_post_suspend(int suspend_cancelled) {} diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig index 3c6e5471f025b91c51119af68b0bb4389329f061..2a51a466779fe416406afcea2186e186204f6d32 100644 --- a/arch/xtensa/Kconfig +++ b/arch/xtensa/Kconfig @@ -16,7 +16,6 @@ config XTENSA select ARCH_USE_MEMTEST select ARCH_USE_QUEUED_RWLOCKS select ARCH_USE_QUEUED_SPINLOCKS - select ARCH_WANT_FRAME_POINTERS select ARCH_WANT_IPC_PARSE_VERSION select BUILDTIME_TABLE_SORT select CLONE_BACKWARDS @@ -35,6 +34,7 @@ config XTENSA select HAVE_ARCH_KCSAN select HAVE_ARCH_SECCOMP_FILTER select HAVE_ARCH_TRACEHOOK + select HAVE_ASM_MODVERSIONS select HAVE_CONTEXT_TRACKING_USER select HAVE_DEBUG_KMEMLEAK select HAVE_DMA_CONTIGUOUS @@ -49,6 +49,7 @@ config XTENSA select HAVE_SYSCALL_TRACEPOINTS select HAVE_VIRT_CPU_ACCOUNTING_GEN select IRQ_DOMAIN + select LOCK_MM_AND_FIND_VMA select MODULES_USE_ELF_RELA select PERF_USE_VMALLOC select TRACE_IRQFLAGS_SUPPORT @@ -203,6 +204,18 @@ config XTENSA_UNALIGNED_USER Say Y here to enable unaligned memory access in user space. +config XTENSA_LOAD_STORE + bool "Load/store exception handler for memory only readable with l32" + help + The Xtensa architecture only allows reading memory attached to its + instruction bus with l32r and l32i instructions, all other + instructions raise an exception with the LoadStoreErrorCause code. + This makes it hard to use some configurations, e.g. store string + literals in FLASH memory attached to the instruction bus. + + Say Y here to enable exception handler that allows transparent + byte and 2-byte access to memory attached to instruction bus. + config HAVE_SMP bool "System Supports SMP (MX)" depends on XTENSA_VARIANT_CUSTOM diff --git a/arch/xtensa/Kconfig.debug b/arch/xtensa/Kconfig.debug index 83cc8d12fa0e1e1373a1f51f5fb0138d8ed1c846..e84172a7763c9d11736d55d66a19a2140159915c 100644 --- a/arch/xtensa/Kconfig.debug +++ b/arch/xtensa/Kconfig.debug @@ -38,3 +38,11 @@ config PRINT_STACK_DEPTH help This option allows you to set the stack depth that the kernel prints in stack traces. + +config PRINT_USER_CODE_ON_UNHANDLED_EXCEPTION + bool "Dump user code around unhandled exception address" + help + Enable this option to display user code around PC of the unhandled + exception (starting at address aligned on 16 byte boundary). + This may simplify finding faulting code in the absence of other + debug facilities. diff --git a/arch/xtensa/boot/boot-redboot/Makefile b/arch/xtensa/boot/boot-redboot/Makefile index 1d1d46215b1cfde328ff10348c47e3ff9ee190e0..c0eef3f6f32dcdb2bd84708229b052d0c7e64b17 100644 --- a/arch/xtensa/boot/boot-redboot/Makefile +++ b/arch/xtensa/boot/boot-redboot/Makefile @@ -6,16 +6,12 @@ OBJCOPY_ARGS := -O $(if $(CONFIG_CPU_BIG_ENDIAN),elf32-xtensa-be,elf32-xtensa-le) -LD_ARGS = -T $(srctree)/$(obj)/boot.ld - boot-y := bootstrap.o targets += $(boot-y) OBJS := $(addprefix $(obj)/,$(boot-y)) LIBS := arch/xtensa/boot/lib/lib.a arch/xtensa/lib/lib.a -LIBGCC := $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name) - $(obj)/zImage.o: $(obj)/../vmlinux.bin.gz $(OBJS) $(Q)$(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \ --add-section image=$< \ @@ -23,7 +19,10 @@ $(obj)/zImage.o: $(obj)/../vmlinux.bin.gz $(OBJS) $(OBJS) $@ $(obj)/zImage.elf: $(obj)/zImage.o $(LIBS) - $(Q)$(LD) $(LD_ARGS) -o $@ $^ -L/xtensa-elf/lib $(LIBGCC) + $(Q)$(LD) $(KBUILD_LDFLAGS) \ + -T $(srctree)/$(obj)/boot.ld \ + --build-id=none \ + -o $@ $^ $(obj)/../zImage.redboot: $(obj)/zImage.elf $(Q)$(OBJCOPY) -S -O binary $< $@ diff --git a/arch/xtensa/include/asm/asm-prototypes.h b/arch/xtensa/include/asm/asm-prototypes.h new file mode 100644 index 0000000000000000000000000000000000000000..b0da61812b853775d67e487874e2dfe3d8067ee2 --- /dev/null +++ b/arch/xtensa/include/asm/asm-prototypes.h @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __ASM_PROTOTYPES_H +#define __ASM_PROTOTYPES_H + +#include +#include +#include +#include +#include +#include + +#include + +/* + * gcc internal math functions + */ +long long __ashrdi3(long long, int); +long long __ashldi3(long long, int); +long long __bswapdi2(long long); +int __bswapsi2(int); +long long __lshrdi3(long long, int); +int __divsi3(int, int); +int __modsi3(int, int); +int __mulsi3(int, int); +unsigned int __udivsi3(unsigned int, unsigned int); +unsigned int __umodsi3(unsigned int, unsigned int); +unsigned long long __umulsidi3(unsigned int, unsigned int); + +#endif /* __ASM_PROTOTYPES_H */ diff --git a/arch/xtensa/include/asm/asmmacro.h b/arch/xtensa/include/asm/asmmacro.h index e3474ca411ff29959f180c0104039a847c0db0cc..01bf7d9dbb1910a291316cd713b0014045793933 100644 --- a/arch/xtensa/include/asm/asmmacro.h +++ b/arch/xtensa/include/asm/asmmacro.h @@ -11,6 +11,7 @@ #ifndef _XTENSA_ASMMACRO_H #define _XTENSA_ASMMACRO_H +#include #include /* diff --git a/arch/xtensa/include/asm/atomic.h b/arch/xtensa/include/asm/atomic.h index 52da614f953ce007b90173413baf7da9d91c281a..7308b7f777d79dc13cf58a7590c5ee901d804128 100644 --- a/arch/xtensa/include/asm/atomic.h +++ b/arch/xtensa/include/asm/atomic.h @@ -245,6 +245,11 @@ static inline int arch_atomic_fetch_##op(int i, atomic_t * v) \ ATOMIC_OPS(add) ATOMIC_OPS(sub) +#define arch_atomic_add_return arch_atomic_add_return +#define arch_atomic_sub_return arch_atomic_sub_return +#define arch_atomic_fetch_add arch_atomic_fetch_add +#define arch_atomic_fetch_sub arch_atomic_fetch_sub + #undef ATOMIC_OPS #define ATOMIC_OPS(op) ATOMIC_OP(op) ATOMIC_FETCH_OP(op) @@ -252,12 +257,13 @@ ATOMIC_OPS(and) ATOMIC_OPS(or) ATOMIC_OPS(xor) +#define arch_atomic_fetch_and arch_atomic_fetch_and +#define arch_atomic_fetch_or arch_atomic_fetch_or +#define arch_atomic_fetch_xor arch_atomic_fetch_xor + #undef ATOMIC_OPS #undef ATOMIC_FETCH_OP #undef ATOMIC_OP_RETURN #undef ATOMIC_OP -#define arch_atomic_cmpxchg(v, o, n) ((int)arch_cmpxchg(&((v)->counter), (o), (n))) -#define arch_atomic_xchg(v, new) (arch_xchg(&((v)->counter), new)) - #endif /* _XTENSA_ATOMIC_H */ diff --git a/arch/xtensa/include/asm/bugs.h b/arch/xtensa/include/asm/bugs.h deleted file mode 100644 index 69b29d19824946e051dab0e55a1b49513f601a74..0000000000000000000000000000000000000000 --- a/arch/xtensa/include/asm/bugs.h +++ /dev/null @@ -1,18 +0,0 @@ -/* - * include/asm-xtensa/bugs.h - * - * This is included by init/main.c to check for architecture-dependent bugs. - * - * Xtensa processors don't have any bugs. :) - * - * This file is subject to the terms and conditions of the GNU General - * Public License. See the file "COPYING" in the main directory of - * this archive for more details. - */ - -#ifndef _XTENSA_BUGS_H -#define _XTENSA_BUGS_H - -static void check_bugs(void) { } - -#endif /* _XTENSA_BUGS_H */ diff --git a/arch/xtensa/include/asm/core.h b/arch/xtensa/include/asm/core.h index f856d2bcb9f3618d9b8025b438590f5bed687f76..0e1bb6f019d6b09293f6e16e7abb6297436bb0c9 100644 --- a/arch/xtensa/include/asm/core.h +++ b/arch/xtensa/include/asm/core.h @@ -26,6 +26,14 @@ #define XCHAL_SPANNING_WAY 0 #endif +#ifndef XCHAL_HAVE_TRAX +#define XCHAL_HAVE_TRAX 0 +#endif + +#ifndef XCHAL_NUM_PERF_COUNTERS +#define XCHAL_NUM_PERF_COUNTERS 0 +#endif + #if XCHAL_HAVE_WINDOWED #if defined(CONFIG_USER_ABI_DEFAULT) || defined(CONFIG_USER_ABI_CALL0_PROBE) /* Whether windowed ABI is supported in userspace. */ diff --git a/arch/xtensa/include/asm/ftrace.h b/arch/xtensa/include/asm/ftrace.h index 6c6d9a9f185f8803ca534543a526422b03234ebc..0ea4f84cd5581fabd4e5abc93e6c7e177ee8c879 100644 --- a/arch/xtensa/include/asm/ftrace.h +++ b/arch/xtensa/include/asm/ftrace.h @@ -13,17 +13,8 @@ #include #ifndef __ASSEMBLY__ -#define ftrace_return_address0 ({ unsigned long a0, a1; \ - __asm__ __volatile__ ( \ - "mov %0, a0\n" \ - "mov %1, a1\n" \ - : "=r"(a0), "=r"(a1)); \ - MAKE_PC_FROM_RA(a0, a1); }) - -#ifdef CONFIG_FRAME_POINTER extern unsigned long return_address(unsigned level); #define ftrace_return_address(n) return_address(n) -#endif #endif /* __ASSEMBLY__ */ #ifdef CONFIG_FUNCTION_TRACER diff --git a/arch/xtensa/include/asm/platform.h b/arch/xtensa/include/asm/platform.h index 354ca942de405b4a62730a788e4d05fe70937955..94f13fabf7cd7c3f2c17fb3491b92de6702c7fec 100644 --- a/arch/xtensa/include/asm/platform.h +++ b/arch/xtensa/include/asm/platform.h @@ -27,31 +27,11 @@ extern void platform_init(bp_tag_t*); */ extern void platform_setup (char **); -/* - * platform_restart is called to restart the system. - */ -extern void platform_restart (void); - -/* - * platform_halt is called to stop the system and halt. - */ -extern void platform_halt (void); - -/* - * platform_power_off is called to stop the system and power it off. - */ -extern void platform_power_off (void); - /* * platform_idle is called from the idle function. */ extern void platform_idle (void); -/* - * platform_heartbeat is called every HZ - */ -extern void platform_heartbeat (void); - /* * platform_calibrate_ccount calibrates cpu clock freq (CONFIG_XTENSA_CALIBRATE) */ diff --git a/arch/xtensa/include/asm/string.h b/arch/xtensa/include/asm/string.h index 89b51a0c752f4bea189afd349a73a6eb10e86de8..ffce43513fa298f462e9d4aede1b0c3a8731f454 100644 --- a/arch/xtensa/include/asm/string.h +++ b/arch/xtensa/include/asm/string.h @@ -118,9 +118,6 @@ extern void *__memcpy(void *__to, __const__ void *__from, size_t __n); extern void *memmove(void *__dest, __const__ void *__src, size_t __n); extern void *__memmove(void *__dest, __const__ void *__src, size_t __n); -/* Don't build bcopy at all ... */ -#define __HAVE_ARCH_BCOPY - #if defined(CONFIG_KASAN) && !defined(__SANITIZE_ADDRESS__) /* diff --git a/arch/xtensa/include/asm/traps.h b/arch/xtensa/include/asm/traps.h index 6f74ccc0c7eadc6a184132f643ea8f380ae29742..212c3b9ff407871d9d3047993a880d234e60c3d5 100644 --- a/arch/xtensa/include/asm/traps.h +++ b/arch/xtensa/include/asm/traps.h @@ -47,6 +47,7 @@ __init trap_set_handler(int cause, xtensa_exception_handler *handler); asmlinkage void fast_illegal_instruction_user(void); asmlinkage void fast_syscall_user(void); asmlinkage void fast_alloca(void); +asmlinkage void fast_load_store(void); asmlinkage void fast_unaligned(void); asmlinkage void fast_second_level_miss(void); asmlinkage void fast_store_prohibited(void); @@ -64,8 +65,14 @@ void do_unhandled(struct pt_regs *regs); static inline void __init early_trap_init(void) { static struct exc_table init_exc_table __initdata = { +#ifdef CONFIG_XTENSA_LOAD_STORE + .fast_kernel_handler[EXCCAUSE_LOAD_STORE_ERROR] = + fast_load_store, +#endif +#ifdef CONFIG_MMU .fast_kernel_handler[EXCCAUSE_DTLB_MISS] = fast_second_level_miss, +#endif }; xtensa_set_sr(&init_exc_table, excsave1); } diff --git a/arch/xtensa/kernel/align.S b/arch/xtensa/kernel/align.S index d062c732ef1864c9eab5730a86682c62a9bb1b3a..ee97edce2300fab94d0cbffe16fc5dd73d527dec 100644 --- a/arch/xtensa/kernel/align.S +++ b/arch/xtensa/kernel/align.S @@ -1,7 +1,7 @@ /* * arch/xtensa/kernel/align.S * - * Handle unalignment exceptions in kernel space. + * Handle unalignment and load/store exceptions. * * This file is subject to the terms and conditions of the GNU General * Public License. See the file "COPYING" in the main directory of @@ -22,13 +22,21 @@ #include #include -#if XCHAL_UNALIGNED_LOAD_EXCEPTION || XCHAL_UNALIGNED_STORE_EXCEPTION +#if XCHAL_UNALIGNED_LOAD_EXCEPTION || defined CONFIG_XTENSA_LOAD_STORE +#define LOAD_EXCEPTION_HANDLER +#endif -/* First-level exception handler for unaligned exceptions. - * - * Note: This handler works only for kernel exceptions. Unaligned user - * access should get a seg fault. - */ +#if XCHAL_UNALIGNED_STORE_EXCEPTION || defined CONFIG_XTENSA_LOAD_STORE +#define STORE_EXCEPTION_HANDLER +#endif + +#if defined LOAD_EXCEPTION_HANDLER || defined STORE_EXCEPTION_HANDLER +#define ANY_EXCEPTION_HANDLER +#endif + +#if XCHAL_HAVE_WINDOWED && defined CONFIG_MMU +#define UNALIGNED_USER_EXCEPTION +#endif /* Big and little endian 16-bit values are located in * different halves of a register. HWORD_START helps to @@ -58,10 +66,6 @@ * BE shift left / mask 0 0 X X */ -#if XCHAL_HAVE_WINDOWED -#define UNALIGNED_USER_EXCEPTION -#endif - #if XCHAL_HAVE_BE #define HWORD_START 16 @@ -103,7 +107,7 @@ * * 23 0 * ----------------------------- - * res 0000 0010 + * L8UI xxxx xxxx 0000 ssss tttt 0010 * L16UI xxxx xxxx 0001 ssss tttt 0010 * L32I xxxx xxxx 0010 ssss tttt 0010 * XXX 0011 ssss tttt 0010 @@ -128,9 +132,11 @@ #define OP0_L32I_N 0x8 /* load immediate narrow */ #define OP0_S32I_N 0x9 /* store immediate narrow */ +#define OP0_LSAI 0x2 /* load/store */ #define OP1_SI_MASK 0x4 /* OP1 bit set for stores */ #define OP1_SI_BIT 2 /* OP1 bit number for stores */ +#define OP1_L8UI 0x0 #define OP1_L32I 0x2 #define OP1_L16UI 0x1 #define OP1_L16SI 0x9 @@ -155,60 +161,72 @@ */ .literal_position -ENTRY(fast_unaligned) +#ifdef CONFIG_XTENSA_LOAD_STORE +ENTRY(fast_load_store) - /* Note: We don't expect the address to be aligned on a word - * boundary. After all, the processor generated that exception - * and it would be a hardware fault. - */ + call0 .Lsave_and_load_instruction - /* Save some working register */ + /* Analyze the instruction (load or store?). */ - s32i a4, a2, PT_AREG4 - s32i a5, a2, PT_AREG5 - s32i a6, a2, PT_AREG6 - s32i a7, a2, PT_AREG7 - s32i a8, a2, PT_AREG8 + extui a0, a4, INSN_OP0, 4 # get insn.op0 nibble - rsr a0, depc - s32i a0, a2, PT_AREG2 - s32i a3, a2, PT_AREG3 +#if XCHAL_HAVE_DENSITY + _beqi a0, OP0_L32I_N, 1f # L32I.N, jump +#endif + bnei a0, OP0_LSAI, .Linvalid_instruction + /* 'store indicator bit' set, jump */ + bbsi.l a4, OP1_SI_BIT + INSN_OP1, .Linvalid_instruction - rsr a3, excsave1 - movi a4, fast_unaligned_fixup - s32i a4, a3, EXC_TABLE_FIXUP +1: + movi a3, ~3 + and a3, a3, a8 # align memory address - /* Keep value of SAR in a0 */ + __ssa8 a8 - rsr a0, sar - rsr a8, excvaddr # load unaligned memory address +#ifdef CONFIG_MMU + /* l32e can't be used here even when it's available. */ + /* TODO access_ok(a3) could be used here */ + j .Linvalid_instruction +#endif + l32i a5, a3, 0 + l32i a6, a3, 4 + __src_b a3, a5, a6 # a3 has the data word - /* Now, identify one of the following load/store instructions. - * - * The only possible danger of a double exception on the - * following l32i instructions is kernel code in vmalloc - * memory. The processor was just executing at the EPC_1 - * address, and indeed, already fetched the instruction. That - * guarantees a TLB mapping, which hasn't been replaced by - * this unaligned exception handler that uses only static TLB - * mappings. However, high-level interrupt handlers might - * modify TLB entries, so for the generic case, we register a - * TABLE_FIXUP handler here, too. - */ +#if XCHAL_HAVE_DENSITY + addi a7, a7, 2 # increment PC (assume 16-bit insn) + _beqi a0, OP0_L32I_N, .Lload_w# l32i.n: jump + addi a7, a7, 1 +#else + addi a7, a7, 3 +#endif - /* a3...a6 saved on stack, a2 = SP */ + extui a5, a4, INSN_OP1, 4 + _beqi a5, OP1_L32I, .Lload_w + bnei a5, OP1_L8UI, .Lload16 + extui a3, a3, 0, 8 + j .Lload_w - /* Extract the instruction that caused the unaligned access. */ +ENDPROC(fast_load_store) +#endif - rsr a7, epc1 # load exception address - movi a3, ~3 - and a3, a3, a7 # mask lower bits +/* + * Entry condition: + * + * a0: trashed, original value saved on stack (PT_AREG0) + * a1: a1 + * a2: new stack pointer, original in DEPC + * a3: a3 + * depc: a2, original value saved on stack (PT_DEPC) + * excsave_1: dispatch table + * + * PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC + * < VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception + */ - l32i a4, a3, 0 # load 2 words - l32i a5, a3, 4 +#ifdef ANY_EXCEPTION_HANDLER +ENTRY(fast_unaligned) - __ssa8 a7 - __src_b a4, a4, a5 # a4 has the instruction + call0 .Lsave_and_load_instruction /* Analyze the instruction (load or store?). */ @@ -222,12 +240,16 @@ ENTRY(fast_unaligned) /* 'store indicator bit' not set, jump */ _bbci.l a4, OP1_SI_BIT + INSN_OP1, .Lload +#ifdef STORE_EXCEPTION_HANDLER + /* Store: Jump to table entry to get the value in the source register.*/ .Lstore:movi a5, .Lstore_table # table extui a6, a4, INSN_T, 4 # get source register addx8 a5, a6, a5 jx a5 # jump into table +#endif +#ifdef LOAD_EXCEPTION_HANDLER /* Load: Load memory address. */ @@ -249,7 +271,7 @@ ENTRY(fast_unaligned) addi a7, a7, 2 # increment PC (assume 16-bit insn) extui a5, a4, INSN_OP0, 4 - _beqi a5, OP0_L32I_N, 1f # l32i.n: jump + _beqi a5, OP0_L32I_N, .Lload_w# l32i.n: jump addi a7, a7, 1 #else @@ -257,21 +279,26 @@ ENTRY(fast_unaligned) #endif extui a5, a4, INSN_OP1, 4 - _beqi a5, OP1_L32I, 1f # l32i: jump - + _beqi a5, OP1_L32I, .Lload_w # l32i: jump +#endif +#ifdef LOAD_EXCEPTION_HANDLER +.Lload16: extui a3, a3, 0, 16 # extract lower 16 bits - _beqi a5, OP1_L16UI, 1f + _beqi a5, OP1_L16UI, .Lload_w addi a5, a5, -OP1_L16SI - _bnez a5, .Linvalid_instruction_load + _bnez a5, .Linvalid_instruction /* sign extend value */ - +#if XCHAL_HAVE_SEXT + sext a3, a3, 15 +#else slli a3, a3, 16 srai a3, a3, 16 +#endif /* Set target register. */ -1: +.Lload_w: extui a4, a4, INSN_T, 4 # extract target register movi a5, .Lload_table addx8 a4, a4, a5 @@ -295,30 +322,31 @@ ENTRY(fast_unaligned) mov a13, a3 ; _j .Lexit; .align 8 mov a14, a3 ; _j .Lexit; .align 8 mov a15, a3 ; _j .Lexit; .align 8 - +#endif +#ifdef STORE_EXCEPTION_HANDLER .Lstore_table: - l32i a3, a2, PT_AREG0; _j 1f; .align 8 - mov a3, a1; _j 1f; .align 8 # fishy?? - l32i a3, a2, PT_AREG2; _j 1f; .align 8 - l32i a3, a2, PT_AREG3; _j 1f; .align 8 - l32i a3, a2, PT_AREG4; _j 1f; .align 8 - l32i a3, a2, PT_AREG5; _j 1f; .align 8 - l32i a3, a2, PT_AREG6; _j 1f; .align 8 - l32i a3, a2, PT_AREG7; _j 1f; .align 8 - l32i a3, a2, PT_AREG8; _j 1f; .align 8 - mov a3, a9 ; _j 1f; .align 8 - mov a3, a10 ; _j 1f; .align 8 - mov a3, a11 ; _j 1f; .align 8 - mov a3, a12 ; _j 1f; .align 8 - mov a3, a13 ; _j 1f; .align 8 - mov a3, a14 ; _j 1f; .align 8 - mov a3, a15 ; _j 1f; .align 8 + l32i a3, a2, PT_AREG0; _j .Lstore_w; .align 8 + mov a3, a1; _j .Lstore_w; .align 8 # fishy?? + l32i a3, a2, PT_AREG2; _j .Lstore_w; .align 8 + l32i a3, a2, PT_AREG3; _j .Lstore_w; .align 8 + l32i a3, a2, PT_AREG4; _j .Lstore_w; .align 8 + l32i a3, a2, PT_AREG5; _j .Lstore_w; .align 8 + l32i a3, a2, PT_AREG6; _j .Lstore_w; .align 8 + l32i a3, a2, PT_AREG7; _j .Lstore_w; .align 8 + l32i a3, a2, PT_AREG8; _j .Lstore_w; .align 8 + mov a3, a9 ; _j .Lstore_w; .align 8 + mov a3, a10 ; _j .Lstore_w; .align 8 + mov a3, a11 ; _j .Lstore_w; .align 8 + mov a3, a12 ; _j .Lstore_w; .align 8 + mov a3, a13 ; _j .Lstore_w; .align 8 + mov a3, a14 ; _j .Lstore_w; .align 8 + mov a3, a15 ; _j .Lstore_w; .align 8 +#endif /* We cannot handle this exception. */ .extern _kernel_exception -.Linvalid_instruction_load: -.Linvalid_instruction_store: +.Linvalid_instruction: movi a4, 0 rsr a3, excsave1 @@ -326,6 +354,7 @@ ENTRY(fast_unaligned) /* Restore a4...a8 and SAR, set SP, and jump to default exception. */ + l32i a0, a2, PT_SAR l32i a8, a2, PT_AREG8 l32i a7, a2, PT_AREG7 l32i a6, a2, PT_AREG6 @@ -343,8 +372,10 @@ ENTRY(fast_unaligned) 2: movi a0, _user_exception jx a0 -1: # a7: instruction pointer, a4: instruction, a3: value +#ifdef STORE_EXCEPTION_HANDLER + # a7: instruction pointer, a4: instruction, a3: value +.Lstore_w: movi a6, 0 # mask: ffffffff:00000000 #if XCHAL_HAVE_DENSITY @@ -361,7 +392,7 @@ ENTRY(fast_unaligned) extui a5, a4, INSN_OP1, 4 # extract OP1 _beqi a5, OP1_S32I, 1f # jump if 32 bit store - _bnei a5, OP1_S16I, .Linvalid_instruction_store + _bnei a5, OP1_S16I, .Linvalid_instruction movi a5, -1 __extl a3, a3 # get 16-bit value @@ -406,6 +437,7 @@ ENTRY(fast_unaligned) #else s32i a6, a4, 4 #endif +#endif .Lexit: #if XCHAL_HAVE_LOOPS @@ -434,6 +466,7 @@ ENTRY(fast_unaligned) /* Restore working register */ + l32i a0, a2, PT_SAR l32i a8, a2, PT_AREG8 l32i a7, a2, PT_AREG7 l32i a6, a2, PT_AREG6 @@ -448,6 +481,59 @@ ENTRY(fast_unaligned) l32i a2, a2, PT_AREG2 rfe + .align 4 +.Lsave_and_load_instruction: + + /* Save some working register */ + + s32i a3, a2, PT_AREG3 + s32i a4, a2, PT_AREG4 + s32i a5, a2, PT_AREG5 + s32i a6, a2, PT_AREG6 + s32i a7, a2, PT_AREG7 + s32i a8, a2, PT_AREG8 + + rsr a4, depc + s32i a4, a2, PT_AREG2 + + rsr a5, sar + s32i a5, a2, PT_SAR + + rsr a3, excsave1 + movi a4, fast_unaligned_fixup + s32i a4, a3, EXC_TABLE_FIXUP + + rsr a8, excvaddr # load unaligned memory address + + /* Now, identify one of the following load/store instructions. + * + * The only possible danger of a double exception on the + * following l32i instructions is kernel code in vmalloc + * memory. The processor was just executing at the EPC_1 + * address, and indeed, already fetched the instruction. That + * guarantees a TLB mapping, which hasn't been replaced by + * this unaligned exception handler that uses only static TLB + * mappings. However, high-level interrupt handlers might + * modify TLB entries, so for the generic case, we register a + * TABLE_FIXUP handler here, too. + */ + + /* a3...a6 saved on stack, a2 = SP */ + + /* Extract the instruction that caused the unaligned access. */ + + rsr a7, epc1 # load exception address + movi a3, ~3 + and a3, a3, a7 # mask lower bits + + l32i a4, a3, 0 # load 2 words + l32i a5, a3, 4 + + __ssa8 a7 + __src_b a4, a4, a5 # a4 has the instruction + + ret + ENDPROC(fast_unaligned) ENTRY(fast_unaligned_fixup) @@ -459,10 +545,11 @@ ENTRY(fast_unaligned_fixup) l32i a7, a2, PT_AREG7 l32i a6, a2, PT_AREG6 l32i a5, a2, PT_AREG5 - l32i a4, a2, PT_AREG4 + l32i a4, a2, PT_SAR l32i a0, a2, PT_AREG2 - xsr a0, depc # restore depc and a0 - wsr a0, sar + wsr a4, sar + wsr a0, depc # restore depc and a0 + l32i a4, a2, PT_AREG4 rsr a0, exccause s32i a0, a2, PT_DEPC # mark as a regular exception @@ -483,5 +570,4 @@ ENTRY(fast_unaligned_fixup) jx a0 ENDPROC(fast_unaligned_fixup) - -#endif /* XCHAL_UNALIGNED_LOAD_EXCEPTION || XCHAL_UNALIGNED_STORE_EXCEPTION */ +#endif diff --git a/arch/xtensa/kernel/mcount.S b/arch/xtensa/kernel/mcount.S index 51daaf4e0b82a5e34a02978b6e05fbe90257d5ca..309b3298258f699b2f8663d4e70c472aaa3889c9 100644 --- a/arch/xtensa/kernel/mcount.S +++ b/arch/xtensa/kernel/mcount.S @@ -78,6 +78,7 @@ ENTRY(_mcount) #error Unsupported Xtensa ABI #endif ENDPROC(_mcount) +EXPORT_SYMBOL(_mcount) ENTRY(ftrace_stub) abi_entry_default diff --git a/arch/xtensa/kernel/platform.c b/arch/xtensa/kernel/platform.c index ac1e0e566995037a653f15d9c35ef417ff1c1a40..926b8bf0f14c975146ad37b8e436cb4107ce4b8d 100644 --- a/arch/xtensa/kernel/platform.c +++ b/arch/xtensa/kernel/platform.c @@ -17,27 +17,28 @@ #include #include -#define _F(r,f,a,b) \ - r __platform_##f a b; \ - r platform_##f a __attribute__((weak, alias("__platform_"#f))) - /* * Default functions that are used if no platform specific function is defined. - * (Please, refer to include/asm-xtensa/platform.h for more information) + * (Please, refer to arch/xtensa/include/asm/platform.h for more information) */ -_F(void, init, (bp_tag_t *first), { }); -_F(void, setup, (char** cmd), { }); -_F(void, restart, (void), { while(1); }); -_F(void, halt, (void), { while(1); }); -_F(void, power_off, (void), { while(1); }); -_F(void, idle, (void), { __asm__ __volatile__ ("waiti 0" ::: "memory"); }); -_F(void, heartbeat, (void), { }); +void __weak __init platform_init(bp_tag_t *first) +{ +} + +void __weak __init platform_setup(char **cmd) +{ +} + +void __weak platform_idle(void) +{ + __asm__ __volatile__ ("waiti 0" ::: "memory"); +} #ifdef CONFIG_XTENSA_CALIBRATE_CCOUNT -_F(void, calibrate_ccount, (void), +void __weak platform_calibrate_ccount(void) { pr_err("ERROR: Cannot calibrate cpu frequency! Assuming 10MHz.\n"); ccount_freq = 10 * 1000000UL; -}); +} #endif diff --git a/arch/xtensa/kernel/setup.c b/arch/xtensa/kernel/setup.c index 9191738f99413ab3943be889e79f1bc75a1be732..aba3ff4e60d85740a64a116884391ffda8906bbc 100644 --- a/arch/xtensa/kernel/setup.c +++ b/arch/xtensa/kernel/setup.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -46,6 +47,7 @@ #include #include #include +#include #if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE) struct screen_info screen_info = { @@ -241,6 +243,12 @@ void __init early_init_devtree(void *params) void __init init_arch(bp_tag_t *bp_start) { + /* Initialize basic exception handling if configuration may need it */ + + if (IS_ENABLED(CONFIG_KASAN) || + IS_ENABLED(CONFIG_XTENSA_LOAD_STORE)) + early_trap_init(); + /* Initialize MMU. */ init_mmu(); @@ -522,19 +530,30 @@ void cpu_reset(void) void machine_restart(char * cmd) { - platform_restart(); + local_irq_disable(); + smp_send_stop(); + do_kernel_restart(cmd); + pr_err("Reboot failed -- System halted\n"); + while (1) + cpu_relax(); } void machine_halt(void) { - platform_halt(); - while (1); + local_irq_disable(); + smp_send_stop(); + do_kernel_power_off(); + while (1) + cpu_relax(); } void machine_power_off(void) { - platform_power_off(); - while (1); + local_irq_disable(); + smp_send_stop(); + do_kernel_power_off(); + while (1) + cpu_relax(); } #ifdef CONFIG_PROC_FS @@ -574,6 +593,12 @@ c_show(struct seq_file *f, void *slot) # if XCHAL_HAVE_OCD "ocd " # endif +#if XCHAL_HAVE_TRAX + "trax " +#endif +#if XCHAL_NUM_PERF_COUNTERS + "perf " +#endif #endif #if XCHAL_HAVE_DENSITY "density " @@ -623,11 +648,13 @@ c_show(struct seq_file *f, void *slot) seq_printf(f,"physical aregs\t: %d\n" "misc regs\t: %d\n" "ibreak\t\t: %d\n" - "dbreak\t\t: %d\n", + "dbreak\t\t: %d\n" + "perf counters\t: %d\n", XCHAL_NUM_AREGS, XCHAL_NUM_MISC_REGS, XCHAL_NUM_IBREAK, - XCHAL_NUM_DBREAK); + XCHAL_NUM_DBREAK, + XCHAL_NUM_PERF_COUNTERS); /* Interrupt. */ diff --git a/arch/xtensa/kernel/stacktrace.c b/arch/xtensa/kernel/stacktrace.c index 7f7755cd28f077773c46be1e6b95d631f6f32cbf..f643ea5e36dab50fd21fad55706118785247837a 100644 --- a/arch/xtensa/kernel/stacktrace.c +++ b/arch/xtensa/kernel/stacktrace.c @@ -237,8 +237,6 @@ EXPORT_SYMBOL_GPL(save_stack_trace); #endif -#ifdef CONFIG_FRAME_POINTER - struct return_addr_data { unsigned long addr; unsigned skip; @@ -271,5 +269,3 @@ unsigned long return_address(unsigned level) return r.addr; } EXPORT_SYMBOL(return_address); - -#endif diff --git a/arch/xtensa/kernel/syscalls/syscall.tbl b/arch/xtensa/kernel/syscalls/syscall.tbl index 52c94ab5c2058c81d8104cead4a9a7defa680276..2b69c3c035b6aedcfff30c0b9fcac5ed08094588 100644 --- a/arch/xtensa/kernel/syscalls/syscall.tbl +++ b/arch/xtensa/kernel/syscalls/syscall.tbl @@ -421,3 +421,4 @@ 448 common process_mrelease sys_process_mrelease 449 common futex_waitv sys_futex_waitv 450 common set_mempolicy_home_node sys_set_mempolicy_home_node +451 common cachestat sys_cachestat diff --git a/arch/xtensa/kernel/time.c b/arch/xtensa/kernel/time.c index 16b8a6273772cb2507a38d33e5ad0dc1e352c9ed..1c3dfea843ece552956089f997b485833ac771b2 100644 --- a/arch/xtensa/kernel/time.c +++ b/arch/xtensa/kernel/time.c @@ -121,10 +121,6 @@ static irqreturn_t timer_interrupt(int irq, void *dev_id) set_linux_timer(get_linux_timer()); evt->event_handler(evt); - - /* Allow platform to do something useful (Wdog). */ - platform_heartbeat(); - return IRQ_HANDLED; } diff --git a/arch/xtensa/kernel/traps.c b/arch/xtensa/kernel/traps.c index f0a7d1c2641e0c67f9a652f9c0626a85f7c43184..427c125a137aae95b8635d860c609c60fa500883 100644 --- a/arch/xtensa/kernel/traps.c +++ b/arch/xtensa/kernel/traps.c @@ -54,9 +54,10 @@ static void do_interrupt(struct pt_regs *regs); #if XTENSA_FAKE_NMI static void do_nmi(struct pt_regs *regs); #endif -#if XCHAL_UNALIGNED_LOAD_EXCEPTION || XCHAL_UNALIGNED_STORE_EXCEPTION -static void do_unaligned_user(struct pt_regs *regs); +#ifdef CONFIG_XTENSA_LOAD_STORE +static void do_load_store(struct pt_regs *regs); #endif +static void do_unaligned_user(struct pt_regs *regs); static void do_multihit(struct pt_regs *regs); #if XTENSA_HAVE_COPROCESSORS static void do_coprocessor(struct pt_regs *regs); @@ -91,20 +92,24 @@ static dispatch_init_table_t __initdata dispatch_init_table[] = { { EXCCAUSE_SYSTEM_CALL, USER, fast_syscall_user }, { EXCCAUSE_SYSTEM_CALL, 0, system_call }, /* EXCCAUSE_INSTRUCTION_FETCH unhandled */ -/* EXCCAUSE_LOAD_STORE_ERROR unhandled*/ +#ifdef CONFIG_XTENSA_LOAD_STORE +{ EXCCAUSE_LOAD_STORE_ERROR, USER|KRNL, fast_load_store }, +{ EXCCAUSE_LOAD_STORE_ERROR, 0, do_load_store }, +#endif { EXCCAUSE_LEVEL1_INTERRUPT, 0, do_interrupt }, #ifdef SUPPORT_WINDOWED { EXCCAUSE_ALLOCA, USER|KRNL, fast_alloca }, #endif { EXCCAUSE_INTEGER_DIVIDE_BY_ZERO, 0, do_div0 }, /* EXCCAUSE_PRIVILEGED unhandled */ -#if XCHAL_UNALIGNED_LOAD_EXCEPTION || XCHAL_UNALIGNED_STORE_EXCEPTION +#if XCHAL_UNALIGNED_LOAD_EXCEPTION || XCHAL_UNALIGNED_STORE_EXCEPTION || \ + IS_ENABLED(CONFIG_XTENSA_LOAD_STORE) #ifdef CONFIG_XTENSA_UNALIGNED_USER { EXCCAUSE_UNALIGNED, USER, fast_unaligned }, #endif -{ EXCCAUSE_UNALIGNED, 0, do_unaligned_user }, { EXCCAUSE_UNALIGNED, KRNL, fast_unaligned }, #endif +{ EXCCAUSE_UNALIGNED, 0, do_unaligned_user }, #ifdef CONFIG_MMU { EXCCAUSE_ITLB_MISS, 0, do_page_fault }, { EXCCAUSE_ITLB_MISS, USER|KRNL, fast_second_level_miss}, @@ -171,6 +176,23 @@ __die_if_kernel(const char *str, struct pt_regs *regs, long err) die(str, regs, err); } +#ifdef CONFIG_PRINT_USER_CODE_ON_UNHANDLED_EXCEPTION +static inline void dump_user_code(struct pt_regs *regs) +{ + char buf[32]; + + if (copy_from_user(buf, (void __user *)(regs->pc & -16), sizeof(buf)) == 0) { + print_hex_dump(KERN_INFO, " ", DUMP_PREFIX_NONE, + 32, 1, buf, sizeof(buf), false); + + } +} +#else +static inline void dump_user_code(struct pt_regs *regs) +{ +} +#endif + /* * Unhandled Exceptions. Kill user task or panic if in kernel space. */ @@ -186,6 +208,7 @@ void do_unhandled(struct pt_regs *regs) "\tEXCCAUSE is %ld\n", current->comm, task_pid_nr(current), regs->pc, regs->exccause); + dump_user_code(regs); force_sig(SIGILL); } @@ -349,6 +372,19 @@ static void do_div0(struct pt_regs *regs) force_sig_fault(SIGFPE, FPE_INTDIV, (void __user *)regs->pc); } +#ifdef CONFIG_XTENSA_LOAD_STORE +static void do_load_store(struct pt_regs *regs) +{ + __die_if_kernel("Unhandled load/store exception in kernel", + regs, SIGKILL); + + pr_info_ratelimited("Load/store error to %08lx in '%s' (pid = %d, pc = %#010lx)\n", + regs->excvaddr, current->comm, + task_pid_nr(current), regs->pc); + force_sig_fault(SIGBUS, BUS_ADRERR, (void *)regs->excvaddr); +} +#endif + /* * Handle unaligned memory accesses from user space. Kill task. * @@ -356,7 +392,6 @@ static void do_div0(struct pt_regs *regs) * accesses causes from user space. */ -#if XCHAL_UNALIGNED_LOAD_EXCEPTION || XCHAL_UNALIGNED_STORE_EXCEPTION static void do_unaligned_user(struct pt_regs *regs) { __die_if_kernel("Unhandled unaligned exception in kernel", @@ -368,7 +403,6 @@ static void do_unaligned_user(struct pt_regs *regs) task_pid_nr(current), regs->pc); force_sig_fault(SIGBUS, BUS_ADRALN, (void *) regs->excvaddr); } -#endif #if XTENSA_HAVE_COPROCESSORS static void do_coprocessor(struct pt_regs *regs) @@ -534,31 +568,58 @@ static void show_trace(struct task_struct *task, unsigned long *sp, } #define STACK_DUMP_ENTRY_SIZE 4 -#define STACK_DUMP_LINE_SIZE 32 +#define STACK_DUMP_LINE_SIZE 16 static size_t kstack_depth_to_print = CONFIG_PRINT_STACK_DEPTH; -void show_stack(struct task_struct *task, unsigned long *sp, const char *loglvl) +struct stack_fragment { - size_t len, off = 0; - - if (!sp) - sp = stack_pointer(task); + size_t len; + size_t off; + u8 *sp; + const char *loglvl; +}; - len = min((-(size_t)sp) & (THREAD_SIZE - STACK_DUMP_ENTRY_SIZE), - kstack_depth_to_print * STACK_DUMP_ENTRY_SIZE); +static int show_stack_fragment_cb(struct stackframe *frame, void *data) +{ + struct stack_fragment *sf = data; - printk("%sStack:\n", loglvl); - while (off < len) { + while (sf->off < sf->len) { u8 line[STACK_DUMP_LINE_SIZE]; - size_t line_len = len - off > STACK_DUMP_LINE_SIZE ? - STACK_DUMP_LINE_SIZE : len - off; + size_t line_len = sf->len - sf->off > STACK_DUMP_LINE_SIZE ? + STACK_DUMP_LINE_SIZE : sf->len - sf->off; + bool arrow = sf->off == 0; + + if (frame && frame->sp == (unsigned long)(sf->sp + sf->off)) + arrow = true; - __memcpy(line, (u8 *)sp + off, line_len); - print_hex_dump(loglvl, " ", DUMP_PREFIX_NONE, + __memcpy(line, sf->sp + sf->off, line_len); + print_hex_dump(sf->loglvl, arrow ? "> " : " ", DUMP_PREFIX_NONE, STACK_DUMP_LINE_SIZE, STACK_DUMP_ENTRY_SIZE, line, line_len, false); - off += STACK_DUMP_LINE_SIZE; + sf->off += STACK_DUMP_LINE_SIZE; + if (arrow) + return 0; } + return 1; +} + +void show_stack(struct task_struct *task, unsigned long *sp, const char *loglvl) +{ + struct stack_fragment sf; + + if (!sp) + sp = stack_pointer(task); + + sf.len = min((-(size_t)sp) & (THREAD_SIZE - STACK_DUMP_ENTRY_SIZE), + kstack_depth_to_print * STACK_DUMP_ENTRY_SIZE); + sf.off = 0; + sf.sp = (u8 *)sp; + sf.loglvl = loglvl; + + printk("%sStack:\n", loglvl); + walk_stackframe(sp, show_stack_fragment_cb, &sf); + while (sf.off < sf.len) + show_stack_fragment_cb(NULL, &sf); show_trace(task, sp, loglvl); } diff --git a/arch/xtensa/kernel/xtensa_ksyms.c b/arch/xtensa/kernel/xtensa_ksyms.c index 17a7ef86fd0dd0c67c4ef0d25576ac1ce106620f..62d81e76e18e238ec1772de97b783f07033228e6 100644 --- a/arch/xtensa/kernel/xtensa_ksyms.c +++ b/arch/xtensa/kernel/xtensa_ksyms.c @@ -13,71 +13,10 @@ */ #include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#ifdef CONFIG_BLK_DEV_FD -#include -#endif -#ifdef CONFIG_NET -#include -#endif /* CONFIG_NET */ - - -/* - * String functions - */ -EXPORT_SYMBOL(memset); -EXPORT_SYMBOL(memcpy); -EXPORT_SYMBOL(memmove); -EXPORT_SYMBOL(__memset); -EXPORT_SYMBOL(__memcpy); -EXPORT_SYMBOL(__memmove); -#ifdef CONFIG_ARCH_HAS_STRNCPY_FROM_USER -EXPORT_SYMBOL(__strncpy_user); -#endif -EXPORT_SYMBOL(clear_page); -EXPORT_SYMBOL(copy_page); +#include EXPORT_SYMBOL(empty_zero_page); -/* - * gcc internal math functions - */ -extern long long __ashrdi3(long long, int); -extern long long __ashldi3(long long, int); -extern long long __bswapdi2(long long); -extern int __bswapsi2(int); -extern long long __lshrdi3(long long, int); -extern int __divsi3(int, int); -extern int __modsi3(int, int); -extern int __mulsi3(int, int); -extern unsigned int __udivsi3(unsigned int, unsigned int); -extern unsigned int __umodsi3(unsigned int, unsigned int); -extern unsigned long long __umulsidi3(unsigned int, unsigned int); - -EXPORT_SYMBOL(__ashldi3); -EXPORT_SYMBOL(__ashrdi3); -EXPORT_SYMBOL(__bswapdi2); -EXPORT_SYMBOL(__bswapsi2); -EXPORT_SYMBOL(__lshrdi3); -EXPORT_SYMBOL(__divsi3); -EXPORT_SYMBOL(__modsi3); -EXPORT_SYMBOL(__mulsi3); -EXPORT_SYMBOL(__udivsi3); -EXPORT_SYMBOL(__umodsi3); -EXPORT_SYMBOL(__umulsidi3); - unsigned int __sync_fetch_and_and_4(volatile void *p, unsigned int v) { BUG(); @@ -89,35 +28,3 @@ unsigned int __sync_fetch_and_or_4(volatile void *p, unsigned int v) BUG(); } EXPORT_SYMBOL(__sync_fetch_and_or_4); - -/* - * Networking support - */ -EXPORT_SYMBOL(csum_partial); -EXPORT_SYMBOL(csum_partial_copy_generic); - -/* - * Architecture-specific symbols - */ -EXPORT_SYMBOL(__xtensa_copy_user); -EXPORT_SYMBOL(__invalidate_icache_range); - -/* - * Kernel hacking ... - */ - -#if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE) -// FIXME EXPORT_SYMBOL(screen_info); -#endif - -extern long common_exception_return; -EXPORT_SYMBOL(common_exception_return); - -#ifdef CONFIG_FUNCTION_TRACER -EXPORT_SYMBOL(_mcount); -#endif - -EXPORT_SYMBOL(__invalidate_dcache_range); -#if XCHAL_DCACHE_IS_WRITEBACK -EXPORT_SYMBOL(__flush_dcache_range); -#endif diff --git a/arch/xtensa/lib/Makefile b/arch/xtensa/lib/Makefile index c9c2614188f74c788a566a1c58b24f3b68721163..ec0d8d233c7468b5c499d9f14c68d8ba0ad01695 100644 --- a/arch/xtensa/lib/Makefile +++ b/arch/xtensa/lib/Makefile @@ -6,7 +6,6 @@ lib-y += memcopy.o memset.o checksum.o \ ashldi3.o ashrdi3.o bswapdi2.o bswapsi2.o lshrdi3.o \ divsi3.o udivsi3.o modsi3.o umodsi3.o mulsi3.o umulsidi3.o \ - usercopy.o strncpy_user.o strnlen_user.o + usercopy.o strnlen_user.o +lib-$(CONFIG_ARCH_HAS_STRNCPY_FROM_USER) += strncpy_user.o lib-$(CONFIG_PCI) += pci-auto.o -lib-$(CONFIG_KCSAN) += kcsan-stubs.o -KCSAN_SANITIZE_kcsan-stubs.o := n diff --git a/arch/xtensa/lib/ashldi3.S b/arch/xtensa/lib/ashldi3.S index 67fb0da9e432c3940f645b6f92027869dbadd15b..cd6b731215d3e0b2eb32ca58ae1fddef4b28ef21 100644 --- a/arch/xtensa/lib/ashldi3.S +++ b/arch/xtensa/lib/ashldi3.S @@ -26,3 +26,4 @@ ENTRY(__ashldi3) abi_ret_default ENDPROC(__ashldi3) +EXPORT_SYMBOL(__ashldi3) diff --git a/arch/xtensa/lib/ashrdi3.S b/arch/xtensa/lib/ashrdi3.S index cbf052c512cc8ff38a23942b09a391f7e9ce5015..07bc6e7580203788d42b79b2973557707adda951 100644 --- a/arch/xtensa/lib/ashrdi3.S +++ b/arch/xtensa/lib/ashrdi3.S @@ -26,3 +26,4 @@ ENTRY(__ashrdi3) abi_ret_default ENDPROC(__ashrdi3) +EXPORT_SYMBOL(__ashrdi3) diff --git a/arch/xtensa/lib/bswapdi2.S b/arch/xtensa/lib/bswapdi2.S index d8e52e05eba664fe80a41a6ee20468eab878b1a2..5d94a93528877b9a9cc8d729a07e67e5607c8eab 100644 --- a/arch/xtensa/lib/bswapdi2.S +++ b/arch/xtensa/lib/bswapdi2.S @@ -19,3 +19,4 @@ ENTRY(__bswapdi2) abi_ret_default ENDPROC(__bswapdi2) +EXPORT_SYMBOL(__bswapdi2) diff --git a/arch/xtensa/lib/bswapsi2.S b/arch/xtensa/lib/bswapsi2.S index 9c1de1344f79ad7c71a6dcfcb73a0dd72c302328..fbfb8613d410523e590bf9d3add415378e536fb6 100644 --- a/arch/xtensa/lib/bswapsi2.S +++ b/arch/xtensa/lib/bswapsi2.S @@ -14,3 +14,4 @@ ENTRY(__bswapsi2) abi_ret_default ENDPROC(__bswapsi2) +EXPORT_SYMBOL(__bswapsi2) diff --git a/arch/xtensa/lib/checksum.S b/arch/xtensa/lib/checksum.S index cf1bed1a5bd65807f7f59e1c1ae7fa165e76c3b0..ffee6f94c8f82e6194dac0d1effe994ebd6b75e1 100644 --- a/arch/xtensa/lib/checksum.S +++ b/arch/xtensa/lib/checksum.S @@ -169,6 +169,7 @@ ENTRY(csum_partial) j 5b /* branch to handle the remaining byte */ ENDPROC(csum_partial) +EXPORT_SYMBOL(csum_partial) /* * Copy from ds while checksumming, otherwise like csum_partial @@ -346,6 +347,7 @@ EX(10f) s8i a8, a3, 1 j 4b /* process the possible trailing odd byte */ ENDPROC(csum_partial_copy_generic) +EXPORT_SYMBOL(csum_partial_copy_generic) # Exception handler: diff --git a/arch/xtensa/lib/divsi3.S b/arch/xtensa/lib/divsi3.S index b044b4744a8b4f7981b030dfc8b10516294155a8..edb3c4ad971b2cedf9c98647763a70acb891e525 100644 --- a/arch/xtensa/lib/divsi3.S +++ b/arch/xtensa/lib/divsi3.S @@ -72,3 +72,4 @@ ENTRY(__divsi3) abi_ret_default ENDPROC(__divsi3) +EXPORT_SYMBOL(__divsi3) diff --git a/arch/xtensa/lib/kcsan-stubs.c b/arch/xtensa/lib/kcsan-stubs.c deleted file mode 100644 index 2b08faa62b869e5925d445f40102126623dc1992..0000000000000000000000000000000000000000 --- a/arch/xtensa/lib/kcsan-stubs.c +++ /dev/null @@ -1,54 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 - -#include -#include - -void __atomic_store_8(volatile void *p, u64 v, int i) -{ - BUG(); -} - -u64 __atomic_load_8(const volatile void *p, int i) -{ - BUG(); -} - -u64 __atomic_exchange_8(volatile void *p, u64 v, int i) -{ - BUG(); -} - -bool __atomic_compare_exchange_8(volatile void *p1, void *p2, u64 v, bool b, int i1, int i2) -{ - BUG(); -} - -u64 __atomic_fetch_add_8(volatile void *p, u64 v, int i) -{ - BUG(); -} - -u64 __atomic_fetch_sub_8(volatile void *p, u64 v, int i) -{ - BUG(); -} - -u64 __atomic_fetch_and_8(volatile void *p, u64 v, int i) -{ - BUG(); -} - -u64 __atomic_fetch_or_8(volatile void *p, u64 v, int i) -{ - BUG(); -} - -u64 __atomic_fetch_xor_8(volatile void *p, u64 v, int i) -{ - BUG(); -} - -u64 __atomic_fetch_nand_8(volatile void *p, u64 v, int i) -{ - BUG(); -} diff --git a/arch/xtensa/lib/lshrdi3.S b/arch/xtensa/lib/lshrdi3.S index 129ef8d1725b3b8d49091a38661aa54ed8ade042..e432e1a4070281c2020b60c28480e6120e48a2aa 100644 --- a/arch/xtensa/lib/lshrdi3.S +++ b/arch/xtensa/lib/lshrdi3.S @@ -26,3 +26,4 @@ ENTRY(__lshrdi3) abi_ret_default ENDPROC(__lshrdi3) +EXPORT_SYMBOL(__lshrdi3) diff --git a/arch/xtensa/lib/memcopy.S b/arch/xtensa/lib/memcopy.S index b20d206bcb719878bad55842a5f8aa932fe10f8d..f60760396ceedfbddb82de55431489b1870062d8 100644 --- a/arch/xtensa/lib/memcopy.S +++ b/arch/xtensa/lib/memcopy.S @@ -273,21 +273,8 @@ WEAK(memcpy) abi_ret_default ENDPROC(__memcpy) - -/* - * void bcopy(const void *src, void *dest, size_t n); - */ - -ENTRY(bcopy) - - abi_entry_default - # a2=src, a3=dst, a4=len - mov a5, a3 - mov a3, a2 - mov a2, a5 - j .Lmovecommon # go to common code for memmove+bcopy - -ENDPROC(bcopy) +EXPORT_SYMBOL(__memcpy) +EXPORT_SYMBOL(memcpy) /* * void *memmove(void *dst, const void *src, size_t len); @@ -551,3 +538,5 @@ WEAK(memmove) abi_ret_default ENDPROC(__memmove) +EXPORT_SYMBOL(__memmove) +EXPORT_SYMBOL(memmove) diff --git a/arch/xtensa/lib/memset.S b/arch/xtensa/lib/memset.S index 59b1524fd601d175090ebe6f4bb3eb419b228e7d..262c3f39f945f4befcd8d524e47b1eabd0bac62c 100644 --- a/arch/xtensa/lib/memset.S +++ b/arch/xtensa/lib/memset.S @@ -142,6 +142,8 @@ EX(10f) s8i a3, a5, 0 abi_ret_default ENDPROC(__memset) +EXPORT_SYMBOL(__memset) +EXPORT_SYMBOL(memset) .section .fixup, "ax" .align 4 diff --git a/arch/xtensa/lib/modsi3.S b/arch/xtensa/lib/modsi3.S index d00e77181e201bdf0562ecf61fb18a4a8d80f1de..c5f4295c6868241f878929d80ff6de930b1b6313 100644 --- a/arch/xtensa/lib/modsi3.S +++ b/arch/xtensa/lib/modsi3.S @@ -60,6 +60,7 @@ ENTRY(__modsi3) abi_ret_default ENDPROC(__modsi3) +EXPORT_SYMBOL(__modsi3) #if !XCHAL_HAVE_NSA .section .rodata diff --git a/arch/xtensa/lib/mulsi3.S b/arch/xtensa/lib/mulsi3.S index 91a9d7c62f9645c200d92a119525d7d135ce57b0..c6b4fd46bfa9269d0b945b5c0f50bf94d3fa9d38 100644 --- a/arch/xtensa/lib/mulsi3.S +++ b/arch/xtensa/lib/mulsi3.S @@ -131,3 +131,4 @@ ENTRY(__mulsi3) abi_ret_default ENDPROC(__mulsi3) +EXPORT_SYMBOL(__mulsi3) diff --git a/arch/xtensa/lib/strncpy_user.S b/arch/xtensa/lib/strncpy_user.S index 0731912227d37eb12a2616ff845c27c0a47cca9b..9841d1694cdff4c3320022f4c80eb504d321d844 100644 --- a/arch/xtensa/lib/strncpy_user.S +++ b/arch/xtensa/lib/strncpy_user.S @@ -201,6 +201,7 @@ EX(10f) s8i a9, a11, 0 abi_ret_default ENDPROC(__strncpy_user) +EXPORT_SYMBOL(__strncpy_user) .section .fixup, "ax" .align 4 diff --git a/arch/xtensa/lib/strnlen_user.S b/arch/xtensa/lib/strnlen_user.S index 3d391dca3efb729efcb7bc358dee19eaeb417cd0..cdcf574741648b8bbc016d1b0f3599fc837a2099 100644 --- a/arch/xtensa/lib/strnlen_user.S +++ b/arch/xtensa/lib/strnlen_user.S @@ -133,6 +133,7 @@ EX(10f) l32i a9, a4, 0 # get word with first two bytes of string abi_ret_default ENDPROC(__strnlen_user) +EXPORT_SYMBOL(__strnlen_user) .section .fixup, "ax" .align 4 diff --git a/arch/xtensa/lib/udivsi3.S b/arch/xtensa/lib/udivsi3.S index d2477e0786cf08bacf0426f4dfb2dba0de6b7b54..59ea2dfc3f720ab0db7e762b0fa3611ed465f072 100644 --- a/arch/xtensa/lib/udivsi3.S +++ b/arch/xtensa/lib/udivsi3.S @@ -66,3 +66,4 @@ ENTRY(__udivsi3) abi_ret_default ENDPROC(__udivsi3) +EXPORT_SYMBOL(__udivsi3) diff --git a/arch/xtensa/lib/umodsi3.S b/arch/xtensa/lib/umodsi3.S index 5f031bfa0354726f344cd6804145f448fa4b130b..d39a7e56a9716ee5cc3ec7d62448bbb74562956f 100644 --- a/arch/xtensa/lib/umodsi3.S +++ b/arch/xtensa/lib/umodsi3.S @@ -55,3 +55,4 @@ ENTRY(__umodsi3) abi_ret_default ENDPROC(__umodsi3) +EXPORT_SYMBOL(__umodsi3) diff --git a/arch/xtensa/lib/umulsidi3.S b/arch/xtensa/lib/umulsidi3.S index 13608164794274250c02b703edfc7ceb49ef5e97..8c7a94a0c5d07937eeea538c5882e0854b79d3ca 100644 --- a/arch/xtensa/lib/umulsidi3.S +++ b/arch/xtensa/lib/umulsidi3.S @@ -228,3 +228,4 @@ ENTRY(__umulsidi3) #endif /* XCHAL_NO_MUL */ ENDPROC(__umulsidi3) +EXPORT_SYMBOL(__umulsidi3) diff --git a/arch/xtensa/lib/usercopy.S b/arch/xtensa/lib/usercopy.S index 16128c094c621ed8cdc9c6f8854a9aac611c966e..2c665c0b408eb80f2c7c6a09c03ae95267990ef1 100644 --- a/arch/xtensa/lib/usercopy.S +++ b/arch/xtensa/lib/usercopy.S @@ -283,6 +283,7 @@ EX(10f) s8i a6, a5, 0 abi_ret(STACK_SIZE) ENDPROC(__xtensa_copy_user) +EXPORT_SYMBOL(__xtensa_copy_user) .section .fixup, "ax" .align 4 diff --git a/arch/xtensa/mm/fault.c b/arch/xtensa/mm/fault.c index faf7cf35a0ee3d244f60332ad967da9e6d500142..d1eb8d6c5b826702b87e289b5737310cb9695995 100644 --- a/arch/xtensa/mm/fault.c +++ b/arch/xtensa/mm/fault.c @@ -130,23 +130,14 @@ void do_page_fault(struct pt_regs *regs) perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address); retry: - mmap_read_lock(mm); - vma = find_vma(mm, address); - + vma = lock_mm_and_find_vma(mm, address, regs); if (!vma) - goto bad_area; - if (vma->vm_start <= address) - goto good_area; - if (!(vma->vm_flags & VM_GROWSDOWN)) - goto bad_area; - if (expand_stack(vma, address)) - goto bad_area; + goto bad_area_nosemaphore; /* Ok, we have a good vm_area for this memory access, so * we can handle it.. */ -good_area: code = SEGV_ACCERR; if (is_write) { @@ -205,6 +196,7 @@ void do_page_fault(struct pt_regs *regs) */ bad_area: mmap_read_unlock(mm); +bad_area_nosemaphore: if (user_mode(regs)) { force_sig_fault(SIGSEGV, code, (void *) address); return; diff --git a/arch/xtensa/mm/kasan_init.c b/arch/xtensa/mm/kasan_init.c index 1fef24db2ff6430046b352f932393a27be6665e4..f00d122aa806b9f945899963c3ac04d686ff035a 100644 --- a/arch/xtensa/mm/kasan_init.c +++ b/arch/xtensa/mm/kasan_init.c @@ -14,7 +14,6 @@ #include #include #include -#include void __init kasan_early_init(void) { @@ -31,7 +30,6 @@ void __init kasan_early_init(void) BUG_ON(!pmd_none(*pmd)); set_pmd(pmd, __pmd((unsigned long)kasan_early_shadow_pte)); } - early_trap_init(); } static void __init populate(void *start, void *end) diff --git a/arch/xtensa/mm/misc.S b/arch/xtensa/mm/misc.S index 0527bf6e32111b31d72094136a62f101802f2b5b..ec36f73c47652786fb4dc70adf3dd0ff9d550ffc 100644 --- a/arch/xtensa/mm/misc.S +++ b/arch/xtensa/mm/misc.S @@ -47,6 +47,7 @@ ENTRY(clear_page) abi_ret_default ENDPROC(clear_page) +EXPORT_SYMBOL(clear_page) /* * copy_page and copy_user_page are the same for non-cache-aliased configs. @@ -89,6 +90,7 @@ ENTRY(copy_page) abi_ret_default ENDPROC(copy_page) +EXPORT_SYMBOL(copy_page) #ifdef CONFIG_MMU /* @@ -367,6 +369,7 @@ ENTRY(__invalidate_icache_range) abi_ret_default ENDPROC(__invalidate_icache_range) +EXPORT_SYMBOL(__invalidate_icache_range) /* * void __flush_invalidate_dcache_range(ulong start, ulong size) @@ -397,6 +400,7 @@ ENTRY(__flush_dcache_range) abi_ret_default ENDPROC(__flush_dcache_range) +EXPORT_SYMBOL(__flush_dcache_range) /* * void _invalidate_dcache_range(ulong start, ulong size) @@ -411,6 +415,7 @@ ENTRY(__invalidate_dcache_range) abi_ret_default ENDPROC(__invalidate_dcache_range) +EXPORT_SYMBOL(__invalidate_dcache_range) /* * void _invalidate_icache_all(void) diff --git a/arch/xtensa/mm/tlb.c b/arch/xtensa/mm/tlb.c index 27a477dae2322d91aa20a5aba7b7562e03d3f91b..0a11fc5f185b7f17380f648a0d2d2672915de4bb 100644 --- a/arch/xtensa/mm/tlb.c +++ b/arch/xtensa/mm/tlb.c @@ -179,6 +179,7 @@ static unsigned get_pte_for_vaddr(unsigned vaddr) pud_t *pud; pmd_t *pmd; pte_t *pte; + unsigned int pteval; if (!mm) mm = task->active_mm; @@ -197,7 +198,9 @@ static unsigned get_pte_for_vaddr(unsigned vaddr) pte = pte_offset_map(pmd, vaddr); if (!pte) return 0; - return pte_val(*pte); + pteval = pte_val(*pte); + pte_unmap(pte); + return pteval; } enum { diff --git a/arch/xtensa/platforms/iss/network.c b/arch/xtensa/platforms/iss/network.c index 9ac46ab3a296cb599ab193b60ba0dae62c4c1cd7..85c82cd42188aff4181210953ccded5729e136cf 100644 --- a/arch/xtensa/platforms/iss/network.c +++ b/arch/xtensa/platforms/iss/network.c @@ -237,7 +237,7 @@ static int tuntap_probe(struct iss_net_private *lp, int index, char *init) init += sizeof(TRANSPORT_TUNTAP_NAME) - 1; if (*init == ',') { - rem = split_if_spec(init + 1, &mac_str, &dev_name); + rem = split_if_spec(init + 1, &mac_str, &dev_name, NULL); if (rem != NULL) { pr_err("%s: extra garbage on specification : '%s'\n", dev->name, rem); @@ -540,6 +540,7 @@ static void iss_net_configure(int index, char *init) rtnl_unlock(); pr_err("%s: error registering net device!\n", dev->name); platform_device_unregister(&lp->pdev); + /* dev is freed by the iss_net_pdev_release callback */ return; } rtnl_unlock(); diff --git a/arch/xtensa/platforms/iss/setup.c b/arch/xtensa/platforms/iss/setup.c index d3433e1bb94e0cca317338048a3032db9039b5da..0f1fe132691e26195d5834cb061be3d0fb9257e7 100644 --- a/arch/xtensa/platforms/iss/setup.c +++ b/arch/xtensa/platforms/iss/setup.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -24,26 +25,27 @@ #include -void platform_halt(void) -{ - pr_info(" ** Called platform_halt() **\n"); - simc_exit(0); -} - -void platform_power_off(void) +static int iss_power_off(struct sys_off_data *unused) { pr_info(" ** Called platform_power_off() **\n"); simc_exit(0); + return NOTIFY_DONE; } -void platform_restart(void) +static int iss_restart(struct notifier_block *this, + unsigned long event, void *ptr) { /* Flush and reset the mmu, simulate a processor reset, and * jump to the reset vector. */ cpu_reset(); - /* control never gets here */ + + return NOTIFY_DONE; } +static struct notifier_block iss_restart_block = { + .notifier_call = iss_restart, +}; + static int iss_panic_event(struct notifier_block *this, unsigned long event, void *ptr) { @@ -82,4 +84,8 @@ void __init platform_setup(char **p_cmdline) } atomic_notifier_chain_register(&panic_notifier_list, &iss_panic_block); + register_restart_handler(&iss_restart_block); + register_sys_off_handler(SYS_OFF_MODE_POWER_OFF, + SYS_OFF_PRIO_PLATFORM, + iss_power_off, NULL); } diff --git a/arch/xtensa/platforms/iss/simdisk.c b/arch/xtensa/platforms/iss/simdisk.c index f50caaa1c2496e86fdc85a0f74d55813aec13ad2..178cf96ca10acb4cd70f8cd052e58503a9ee1494 100644 --- a/arch/xtensa/platforms/iss/simdisk.c +++ b/arch/xtensa/platforms/iss/simdisk.c @@ -120,9 +120,9 @@ static void simdisk_submit_bio(struct bio *bio) bio_endio(bio); } -static int simdisk_open(struct block_device *bdev, fmode_t mode) +static int simdisk_open(struct gendisk *disk, blk_mode_t mode) { - struct simdisk *dev = bdev->bd_disk->private_data; + struct simdisk *dev = disk->private_data; spin_lock(&dev->lock); ++dev->users; @@ -130,7 +130,7 @@ static int simdisk_open(struct block_device *bdev, fmode_t mode) return 0; } -static void simdisk_release(struct gendisk *disk, fmode_t mode) +static void simdisk_release(struct gendisk *disk) { struct simdisk *dev = disk->private_data; spin_lock(&dev->lock); diff --git a/arch/xtensa/platforms/xt2000/setup.c b/arch/xtensa/platforms/xt2000/setup.c index 0dc22c3716148713596d8c2595256dc7642719f4..258e01a51fd88e60a4b610d317d7e6db1dfa0996 100644 --- a/arch/xtensa/platforms/xt2000/setup.c +++ b/arch/xtensa/platforms/xt2000/setup.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -41,51 +42,46 @@ static void led_print (int f, char *s) break; } -void platform_halt(void) -{ - led_print (0, " HALT "); - local_irq_disable(); - while (1); -} - -void platform_power_off(void) +static int xt2000_power_off(struct sys_off_data *unused) { led_print (0, "POWEROFF"); local_irq_disable(); while (1); + return NOTIFY_DONE; } -void platform_restart(void) +static int xt2000_restart(struct notifier_block *this, + unsigned long event, void *ptr) { /* Flush and reset the mmu, simulate a processor reset, and * jump to the reset vector. */ cpu_reset(); - /* control never gets here */ + + return NOTIFY_DONE; } +static struct notifier_block xt2000_restart_block = { + .notifier_call = xt2000_restart, +}; + void __init platform_setup(char** cmdline) { led_print (0, "LINUX "); } -/* early initialization */ +/* Heartbeat. Let the LED blink. */ -void __init platform_init(bp_tag_t *first) -{ -} +static void xt2000_heartbeat(struct timer_list *unused); -/* Heartbeat. Let the LED blink. */ +static DEFINE_TIMER(heartbeat_timer, xt2000_heartbeat); -void platform_heartbeat(void) +static void xt2000_heartbeat(struct timer_list *unused) { - static int i, t; + static int i; - if (--t < 0) - { - t = 59; - led_print(7, i ? ".": " "); - i ^= 1; - } + led_print(7, i ? "." : " "); + i ^= 1; + mod_timer(&heartbeat_timer, jiffies + HZ / 2); } //#define RS_TABLE_SIZE 2 @@ -143,7 +139,11 @@ static int __init xt2000_setup_devinit(void) { platform_device_register(&xt2000_serial8250_device); platform_device_register(&xt2000_sonic_device); - + mod_timer(&heartbeat_timer, jiffies + HZ / 2); + register_restart_handler(&xt2000_restart_block); + register_sys_off_handler(SYS_OFF_MODE_POWER_OFF, + SYS_OFF_PRIO_DEFAULT, + xt2000_power_off, NULL); return 0; } diff --git a/arch/xtensa/platforms/xtfpga/setup.c b/arch/xtensa/platforms/xtfpga/setup.c index c79c1d09ea8631d84496ca5b0e8f6de90b233ac3..a2432f0817101005d6cf995ce1cc5217d403bb57 100644 --- a/arch/xtensa/platforms/xtfpga/setup.c +++ b/arch/xtensa/platforms/xtfpga/setup.c @@ -33,23 +33,17 @@ #include #include -void platform_halt(void) -{ - lcd_disp_at_pos(" HALT ", 0); - local_irq_disable(); - while (1) - cpu_relax(); -} - -void platform_power_off(void) +static int xtfpga_power_off(struct sys_off_data *unused) { lcd_disp_at_pos("POWEROFF", 0); local_irq_disable(); while (1) cpu_relax(); + return NOTIFY_DONE; } -void platform_restart(void) +static int xtfpga_restart(struct notifier_block *this, + unsigned long event, void *ptr) { /* Try software reset first. */ WRITE_ONCE(*(u32 *)XTFPGA_SWRST_VADDR, 0xdead); @@ -58,9 +52,14 @@ void platform_restart(void) * simulate a processor reset, and jump to the reset vector. */ cpu_reset(); - /* control never gets here */ + + return NOTIFY_DONE; } +static struct notifier_block xtfpga_restart_block = { + .notifier_call = xtfpga_restart, +}; + #ifdef CONFIG_XTENSA_CALIBRATE_CCOUNT void __init platform_calibrate_ccount(void) @@ -70,6 +69,14 @@ void __init platform_calibrate_ccount(void) #endif +static void __init xtfpga_register_handlers(void) +{ + register_restart_handler(&xtfpga_restart_block); + register_sys_off_handler(SYS_OFF_MODE_POWER_OFF, + SYS_OFF_PRIO_DEFAULT, + xtfpga_power_off, NULL); +} + #ifdef CONFIG_USE_OF static void __init xtfpga_clk_setup(struct device_node *np) @@ -134,6 +141,9 @@ static int __init machine_setup(void) if ((eth = of_find_compatible_node(eth, NULL, "opencores,ethoc"))) update_local_mac(eth); of_node_put(eth); + + xtfpga_register_handlers(); + return 0; } arch_initcall(machine_setup); @@ -281,6 +291,8 @@ static int __init xtavnet_init(void) pr_info("XTFPGA: Ethernet MAC %pM\n", ethoc_pdata.hwaddr); ethoc_pdata.eth_clkfreq = *(long *)XTFPGA_CLKFRQ_VADDR; + xtfpga_register_handlers(); + return 0; } diff --git a/block/Makefile b/block/Makefile index b31b05390749a1ce71cf96ef7a35a20019a5ae4a..46ada9dc8bbfe2ef6ab63e728635c30bdd25c725 100644 --- a/block/Makefile +++ b/block/Makefile @@ -9,7 +9,7 @@ obj-y := bdev.o fops.o bio.o elevator.o blk-core.o blk-sysfs.o \ blk-lib.o blk-mq.o blk-mq-tag.o blk-stat.o \ blk-mq-sysfs.o blk-mq-cpumap.o blk-mq-sched.o ioctl.o \ genhd.o ioprio.o badblocks.o partitions/ blk-rq-qos.o \ - disk-events.o blk-ia-ranges.o + disk-events.o blk-ia-ranges.o early-lookup.o obj-$(CONFIG_BOUNCE) += bounce.o obj-$(CONFIG_BLK_DEV_BSG_COMMON) += bsg.o diff --git a/block/bdev.c b/block/bdev.c index 21c63bfef3237aaa5b37f353167562f30eb51074..979e28a46b988eade74777fb09d8954820dbfd21 100644 --- a/block/bdev.c +++ b/block/bdev.c @@ -93,7 +93,7 @@ EXPORT_SYMBOL(invalidate_bdev); * Drop all buffers & page cache for given bdev range. This function bails * with error if bdev has other exclusive owner (such as filesystem). */ -int truncate_bdev_range(struct block_device *bdev, fmode_t mode, +int truncate_bdev_range(struct block_device *bdev, blk_mode_t mode, loff_t lstart, loff_t lend) { /* @@ -101,14 +101,14 @@ int truncate_bdev_range(struct block_device *bdev, fmode_t mode, * while we discard the buffer cache to avoid discarding buffers * under live filesystem. */ - if (!(mode & FMODE_EXCL)) { - int err = bd_prepare_to_claim(bdev, truncate_bdev_range); + if (!(mode & BLK_OPEN_EXCL)) { + int err = bd_prepare_to_claim(bdev, truncate_bdev_range, NULL); if (err) goto invalidate; } truncate_inode_pages_range(bdev->bd_inode->i_mapping, lstart, lend); - if (!(mode & FMODE_EXCL)) + if (!(mode & BLK_OPEN_EXCL)) bd_abort_claiming(bdev, truncate_bdev_range); return 0; @@ -308,7 +308,7 @@ EXPORT_SYMBOL(thaw_bdev); * pseudo-fs */ -static __cacheline_aligned_in_smp DEFINE_SPINLOCK(bdev_lock); +static __cacheline_aligned_in_smp DEFINE_MUTEX(bdev_lock); static struct kmem_cache * bdev_cachep __read_mostly; static struct inode *bdev_alloc_inode(struct super_block *sb) @@ -415,6 +415,7 @@ struct block_device *bdev_alloc(struct gendisk *disk, u8 partno) bdev = I_BDEV(inode); mutex_init(&bdev->bd_fsfreeze_mutex); spin_lock_init(&bdev->bd_size_lock); + mutex_init(&bdev->bd_holder_lock); bdev->bd_partno = partno; bdev->bd_inode = inode; bdev->bd_queue = disk->queue; @@ -463,39 +464,48 @@ long nr_blockdev_pages(void) /** * bd_may_claim - test whether a block device can be claimed * @bdev: block device of interest - * @whole: whole block device containing @bdev, may equal @bdev * @holder: holder trying to claim @bdev + * @hops: holder ops * * Test whether @bdev can be claimed by @holder. * - * CONTEXT: - * spin_lock(&bdev_lock). - * * RETURNS: * %true if @bdev can be claimed, %false otherwise. */ -static bool bd_may_claim(struct block_device *bdev, struct block_device *whole, - void *holder) +static bool bd_may_claim(struct block_device *bdev, void *holder, + const struct blk_holder_ops *hops) { - if (bdev->bd_holder == holder) - return true; /* already a holder */ - else if (bdev->bd_holder != NULL) - return false; /* held by someone else */ - else if (whole == bdev) - return true; /* is a whole device which isn't held */ - - else if (whole->bd_holder == bd_may_claim) - return true; /* is a partition of a device that is being partitioned */ - else if (whole->bd_holder != NULL) - return false; /* is a partition of a held device */ - else - return true; /* is a partition of an un-held device */ + struct block_device *whole = bdev_whole(bdev); + + lockdep_assert_held(&bdev_lock); + + if (bdev->bd_holder) { + /* + * The same holder can always re-claim. + */ + if (bdev->bd_holder == holder) { + if (WARN_ON_ONCE(bdev->bd_holder_ops != hops)) + return false; + return true; + } + return false; + } + + /* + * If the whole devices holder is set to bd_may_claim, a partition on + * the device is claimed, but not the whole device. + */ + if (whole != bdev && + whole->bd_holder && whole->bd_holder != bd_may_claim) + return false; + return true; } /** * bd_prepare_to_claim - claim a block device * @bdev: block device of interest * @holder: holder trying to claim @bdev + * @hops: holder ops. * * Claim @bdev. This function fails if @bdev is already claimed by another * holder and waits if another claiming is in progress. return, the caller @@ -504,17 +514,18 @@ static bool bd_may_claim(struct block_device *bdev, struct block_device *whole, * RETURNS: * 0 if @bdev can be claimed, -EBUSY otherwise. */ -int bd_prepare_to_claim(struct block_device *bdev, void *holder) +int bd_prepare_to_claim(struct block_device *bdev, void *holder, + const struct blk_holder_ops *hops) { struct block_device *whole = bdev_whole(bdev); if (WARN_ON_ONCE(!holder)) return -EINVAL; retry: - spin_lock(&bdev_lock); + mutex_lock(&bdev_lock); /* if someone else claimed, fail */ - if (!bd_may_claim(bdev, whole, holder)) { - spin_unlock(&bdev_lock); + if (!bd_may_claim(bdev, holder, hops)) { + mutex_unlock(&bdev_lock); return -EBUSY; } @@ -524,7 +535,7 @@ int bd_prepare_to_claim(struct block_device *bdev, void *holder) DEFINE_WAIT(wait); prepare_to_wait(wq, &wait, TASK_UNINTERRUPTIBLE); - spin_unlock(&bdev_lock); + mutex_unlock(&bdev_lock); schedule(); finish_wait(wq, &wait); goto retry; @@ -532,7 +543,7 @@ int bd_prepare_to_claim(struct block_device *bdev, void *holder) /* yay, all mine */ whole->bd_claiming = holder; - spin_unlock(&bdev_lock); + mutex_unlock(&bdev_lock); return 0; } EXPORT_SYMBOL_GPL(bd_prepare_to_claim); /* only for the loop driver */ @@ -550,16 +561,18 @@ static void bd_clear_claiming(struct block_device *whole, void *holder) * bd_finish_claiming - finish claiming of a block device * @bdev: block device of interest * @holder: holder that has claimed @bdev + * @hops: block device holder operations * * Finish exclusive open of a block device. Mark the device as exlusively * open by the holder and wake up all waiters for exclusive open to finish. */ -static void bd_finish_claiming(struct block_device *bdev, void *holder) +static void bd_finish_claiming(struct block_device *bdev, void *holder, + const struct blk_holder_ops *hops) { struct block_device *whole = bdev_whole(bdev); - spin_lock(&bdev_lock); - BUG_ON(!bd_may_claim(bdev, whole, holder)); + mutex_lock(&bdev_lock); + BUG_ON(!bd_may_claim(bdev, holder, hops)); /* * Note that for a whole device bd_holders will be incremented twice, * and bd_holder will be set to bd_may_claim before being set to holder @@ -567,9 +580,12 @@ static void bd_finish_claiming(struct block_device *bdev, void *holder) whole->bd_holders++; whole->bd_holder = bd_may_claim; bdev->bd_holders++; + mutex_lock(&bdev->bd_holder_lock); bdev->bd_holder = holder; + bdev->bd_holder_ops = hops; + mutex_unlock(&bdev->bd_holder_lock); bd_clear_claiming(whole, holder); - spin_unlock(&bdev_lock); + mutex_unlock(&bdev_lock); } /** @@ -583,12 +599,47 @@ static void bd_finish_claiming(struct block_device *bdev, void *holder) */ void bd_abort_claiming(struct block_device *bdev, void *holder) { - spin_lock(&bdev_lock); + mutex_lock(&bdev_lock); bd_clear_claiming(bdev_whole(bdev), holder); - spin_unlock(&bdev_lock); + mutex_unlock(&bdev_lock); } EXPORT_SYMBOL(bd_abort_claiming); +static void bd_end_claim(struct block_device *bdev, void *holder) +{ + struct block_device *whole = bdev_whole(bdev); + bool unblock = false; + + /* + * Release a claim on the device. The holder fields are protected with + * bdev_lock. open_mutex is used to synchronize disk_holder unlinking. + */ + mutex_lock(&bdev_lock); + WARN_ON_ONCE(bdev->bd_holder != holder); + WARN_ON_ONCE(--bdev->bd_holders < 0); + WARN_ON_ONCE(--whole->bd_holders < 0); + if (!bdev->bd_holders) { + mutex_lock(&bdev->bd_holder_lock); + bdev->bd_holder = NULL; + bdev->bd_holder_ops = NULL; + mutex_unlock(&bdev->bd_holder_lock); + if (bdev->bd_write_holder) + unblock = true; + } + if (!whole->bd_holders) + whole->bd_holder = NULL; + mutex_unlock(&bdev_lock); + + /* + * If this was the last claim, remove holder link and unblock evpoll if + * it was a write holder. + */ + if (unblock) { + disk_unblock_events(bdev->bd_disk); + bdev->bd_write_holder = false; + } +} + static void blkdev_flush_mapping(struct block_device *bdev) { WARN_ON_ONCE(bdev->bd_holders); @@ -597,13 +648,13 @@ static void blkdev_flush_mapping(struct block_device *bdev) bdev_write_inode(bdev); } -static int blkdev_get_whole(struct block_device *bdev, fmode_t mode) +static int blkdev_get_whole(struct block_device *bdev, blk_mode_t mode) { struct gendisk *disk = bdev->bd_disk; int ret; if (disk->fops->open) { - ret = disk->fops->open(bdev, mode); + ret = disk->fops->open(disk, mode); if (ret) { /* avoid ghost partitions on a removed medium */ if (ret == -ENOMEDIUM && @@ -621,22 +672,19 @@ static int blkdev_get_whole(struct block_device *bdev, fmode_t mode) return 0; } -static void blkdev_put_whole(struct block_device *bdev, fmode_t mode) +static void blkdev_put_whole(struct block_device *bdev) { if (atomic_dec_and_test(&bdev->bd_openers)) blkdev_flush_mapping(bdev); if (bdev->bd_disk->fops->release) - bdev->bd_disk->fops->release(bdev->bd_disk, mode); + bdev->bd_disk->fops->release(bdev->bd_disk); } -static int blkdev_get_part(struct block_device *part, fmode_t mode) +static int blkdev_get_part(struct block_device *part, blk_mode_t mode) { struct gendisk *disk = part->bd_disk; int ret; - if (atomic_read(&part->bd_openers)) - goto done; - ret = blkdev_get_whole(bdev_whole(part), mode); if (ret) return ret; @@ -645,26 +693,27 @@ static int blkdev_get_part(struct block_device *part, fmode_t mode) if (!bdev_nr_sectors(part)) goto out_blkdev_put; - disk->open_partitions++; - set_init_blocksize(part); -done: + if (!atomic_read(&part->bd_openers)) { + disk->open_partitions++; + set_init_blocksize(part); + } atomic_inc(&part->bd_openers); return 0; out_blkdev_put: - blkdev_put_whole(bdev_whole(part), mode); + blkdev_put_whole(bdev_whole(part)); return ret; } -static void blkdev_put_part(struct block_device *part, fmode_t mode) +static void blkdev_put_part(struct block_device *part) { struct block_device *whole = bdev_whole(part); - if (!atomic_dec_and_test(&part->bd_openers)) - return; - blkdev_flush_mapping(part); - whole->bd_disk->open_partitions--; - blkdev_put_whole(whole, mode); + if (atomic_dec_and_test(&part->bd_openers)) { + blkdev_flush_mapping(part); + whole->bd_disk->open_partitions--; + } + blkdev_put_whole(whole); } struct block_device *blkdev_get_no_open(dev_t dev) @@ -695,17 +744,17 @@ void blkdev_put_no_open(struct block_device *bdev) { put_device(&bdev->bd_device); } - + /** * blkdev_get_by_dev - open a block device by device number * @dev: device number of block device to open - * @mode: FMODE_* mask + * @mode: open mode (BLK_OPEN_*) * @holder: exclusive holder identifier + * @hops: holder operations * - * Open the block device described by device number @dev. If @mode includes - * %FMODE_EXCL, the block device is opened with exclusive access. Specifying - * %FMODE_EXCL with a %NULL @holder is invalid. Exclusive opens may nest for - * the same @holder. + * Open the block device described by device number @dev. If @holder is not + * %NULL, the block device is opened with exclusive access. Exclusive opens may + * nest for the same @holder. * * Use this interface ONLY if you really do not have anything better - i.e. when * you are behind a truly sucky interface and all you are given is a device @@ -717,7 +766,8 @@ void blkdev_put_no_open(struct block_device *bdev) * RETURNS: * Reference to the block_device on success, ERR_PTR(-errno) on failure. */ -struct block_device *blkdev_get_by_dev(dev_t dev, fmode_t mode, void *holder) +struct block_device *blkdev_get_by_dev(dev_t dev, blk_mode_t mode, void *holder, + const struct blk_holder_ops *hops) { bool unblock_events = true; struct block_device *bdev; @@ -726,8 +776,8 @@ struct block_device *blkdev_get_by_dev(dev_t dev, fmode_t mode, void *holder) ret = devcgroup_check_permission(DEVCG_DEV_BLOCK, MAJOR(dev), MINOR(dev), - ((mode & FMODE_READ) ? DEVCG_ACC_READ : 0) | - ((mode & FMODE_WRITE) ? DEVCG_ACC_WRITE : 0)); + ((mode & BLK_OPEN_READ) ? DEVCG_ACC_READ : 0) | + ((mode & BLK_OPEN_WRITE) ? DEVCG_ACC_WRITE : 0)); if (ret) return ERR_PTR(ret); @@ -736,10 +786,16 @@ struct block_device *blkdev_get_by_dev(dev_t dev, fmode_t mode, void *holder) return ERR_PTR(-ENXIO); disk = bdev->bd_disk; - if (mode & FMODE_EXCL) { - ret = bd_prepare_to_claim(bdev, holder); + if (holder) { + mode |= BLK_OPEN_EXCL; + ret = bd_prepare_to_claim(bdev, holder, hops); if (ret) goto put_blkdev; + } else { + if (WARN_ON_ONCE(mode & BLK_OPEN_EXCL)) { + ret = -EIO; + goto put_blkdev; + } } disk_block_events(disk); @@ -756,8 +812,8 @@ struct block_device *blkdev_get_by_dev(dev_t dev, fmode_t mode, void *holder) ret = blkdev_get_whole(bdev, mode); if (ret) goto put_module; - if (mode & FMODE_EXCL) { - bd_finish_claiming(bdev, holder); + if (holder) { + bd_finish_claiming(bdev, holder, hops); /* * Block event polling for write claims if requested. Any write @@ -766,7 +822,7 @@ struct block_device *blkdev_get_by_dev(dev_t dev, fmode_t mode, void *holder) * writeable reference is too fragile given the way @mode is * used in blkdev_get/put(). */ - if ((mode & FMODE_WRITE) && !bdev->bd_write_holder && + if ((mode & BLK_OPEN_WRITE) && !bdev->bd_write_holder && (disk->event_flags & DISK_EVENT_FLAG_BLOCK_ON_EXCL_WRITE)) { bdev->bd_write_holder = true; unblock_events = false; @@ -780,7 +836,7 @@ struct block_device *blkdev_get_by_dev(dev_t dev, fmode_t mode, void *holder) put_module: module_put(disk->fops->owner); abort_claiming: - if (mode & FMODE_EXCL) + if (holder) bd_abort_claiming(bdev, holder); mutex_unlock(&disk->open_mutex); disk_unblock_events(disk); @@ -793,13 +849,13 @@ EXPORT_SYMBOL(blkdev_get_by_dev); /** * blkdev_get_by_path - open a block device by name * @path: path to the block device to open - * @mode: FMODE_* mask + * @mode: open mode (BLK_OPEN_*) * @holder: exclusive holder identifier + * @hops: holder operations * - * Open the block device described by the device file at @path. If @mode - * includes %FMODE_EXCL, the block device is opened with exclusive access. - * Specifying %FMODE_EXCL with a %NULL @holder is invalid. Exclusive opens may - * nest for the same @holder. + * Open the block device described by the device file at @path. If @holder is + * not %NULL, the block device is opened with exclusive access. Exclusive opens + * may nest for the same @holder. * * CONTEXT: * Might sleep. @@ -807,8 +863,8 @@ EXPORT_SYMBOL(blkdev_get_by_dev); * RETURNS: * Reference to the block_device on success, ERR_PTR(-errno) on failure. */ -struct block_device *blkdev_get_by_path(const char *path, fmode_t mode, - void *holder) +struct block_device *blkdev_get_by_path(const char *path, blk_mode_t mode, + void *holder, const struct blk_holder_ops *hops) { struct block_device *bdev; dev_t dev; @@ -818,9 +874,9 @@ struct block_device *blkdev_get_by_path(const char *path, fmode_t mode, if (error) return ERR_PTR(error); - bdev = blkdev_get_by_dev(dev, mode, holder); - if (!IS_ERR(bdev) && (mode & FMODE_WRITE) && bdev_read_only(bdev)) { - blkdev_put(bdev, mode); + bdev = blkdev_get_by_dev(dev, mode, holder, hops); + if (!IS_ERR(bdev) && (mode & BLK_OPEN_WRITE) && bdev_read_only(bdev)) { + blkdev_put(bdev, holder); return ERR_PTR(-EACCES); } @@ -828,7 +884,7 @@ struct block_device *blkdev_get_by_path(const char *path, fmode_t mode, } EXPORT_SYMBOL(blkdev_get_by_path); -void blkdev_put(struct block_device *bdev, fmode_t mode) +void blkdev_put(struct block_device *bdev, void *holder) { struct gendisk *disk = bdev->bd_disk; @@ -843,36 +899,8 @@ void blkdev_put(struct block_device *bdev, fmode_t mode) sync_blockdev(bdev); mutex_lock(&disk->open_mutex); - if (mode & FMODE_EXCL) { - struct block_device *whole = bdev_whole(bdev); - bool bdev_free; - - /* - * Release a claim on the device. The holder fields - * are protected with bdev_lock. open_mutex is to - * synchronize disk_holder unlinking. - */ - spin_lock(&bdev_lock); - - WARN_ON_ONCE(--bdev->bd_holders < 0); - WARN_ON_ONCE(--whole->bd_holders < 0); - - if ((bdev_free = !bdev->bd_holders)) - bdev->bd_holder = NULL; - if (!whole->bd_holders) - whole->bd_holder = NULL; - - spin_unlock(&bdev_lock); - - /* - * If this was the last claim, remove holder link and - * unblock evpoll if it was a write holder. - */ - if (bdev_free && bdev->bd_write_holder) { - disk_unblock_events(disk); - bdev->bd_write_holder = false; - } - } + if (holder) + bd_end_claim(bdev, holder); /* * Trigger event checking and tell drivers to flush MEDIA_CHANGE @@ -882,9 +910,9 @@ void blkdev_put(struct block_device *bdev, fmode_t mode) disk_flush_events(disk, DISK_EVENT_MEDIA_CHANGE); if (bdev_is_partition(bdev)) - blkdev_put_part(bdev, mode); + blkdev_put_part(bdev); else - blkdev_put_whole(bdev, mode); + blkdev_put_whole(bdev); mutex_unlock(&disk->open_mutex); module_put(disk->fops->owner); diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c index 3164e31779657eeb93870010281f71c622d66a6b..3cce6de464a7b7c1b506158d044b537510a3e6f8 100644 --- a/block/bfq-iosched.c +++ b/block/bfq-iosched.c @@ -5403,6 +5403,10 @@ void bfq_put_queue(struct bfq_queue *bfqq) if (bfqq->bfqd->last_completed_rq_bfqq == bfqq) bfqq->bfqd->last_completed_rq_bfqq = NULL; + WARN_ON_ONCE(!list_empty(&bfqq->fifo)); + WARN_ON_ONCE(!RB_EMPTY_ROOT(&bfqq->sort_list)); + WARN_ON_ONCE(bfqq->dispatched); + kmem_cache_free(bfq_pool, bfqq); bfqg_and_blkg_put(bfqg); } @@ -5524,16 +5528,16 @@ bfq_set_next_ioprio_data(struct bfq_queue *bfqq, struct bfq_io_cq *bic) bfqq->new_ioprio_class = task_nice_ioclass(tsk); break; case IOPRIO_CLASS_RT: - bfqq->new_ioprio = IOPRIO_PRIO_DATA(bic->ioprio); + bfqq->new_ioprio = IOPRIO_PRIO_LEVEL(bic->ioprio); bfqq->new_ioprio_class = IOPRIO_CLASS_RT; break; case IOPRIO_CLASS_BE: - bfqq->new_ioprio = IOPRIO_PRIO_DATA(bic->ioprio); + bfqq->new_ioprio = IOPRIO_PRIO_LEVEL(bic->ioprio); bfqq->new_ioprio_class = IOPRIO_CLASS_BE; break; case IOPRIO_CLASS_IDLE: bfqq->new_ioprio_class = IOPRIO_CLASS_IDLE; - bfqq->new_ioprio = 7; + bfqq->new_ioprio = IOPRIO_NR_LEVELS - 1; break; } @@ -5830,7 +5834,7 @@ static struct bfq_queue *bfq_get_queue(struct bfq_data *bfqd, struct bfq_io_cq *bic, bool respawn) { - const int ioprio = IOPRIO_PRIO_DATA(bic->ioprio); + const int ioprio = IOPRIO_PRIO_LEVEL(bic->ioprio); const int ioprio_class = IOPRIO_PRIO_CLASS(bic->ioprio); struct bfq_queue **async_bfqq = NULL; struct bfq_queue *bfqq; @@ -7135,6 +7139,7 @@ static void bfq_exit_queue(struct elevator_queue *e) { struct bfq_data *bfqd = e->elevator_data; struct bfq_queue *bfqq, *n; + unsigned int actuator; hrtimer_cancel(&bfqd->idle_slice_timer); @@ -7143,6 +7148,10 @@ static void bfq_exit_queue(struct elevator_queue *e) bfq_deactivate_bfqq(bfqd, bfqq, false, false); spin_unlock_irq(&bfqd->lock); + for (actuator = 0; actuator < bfqd->num_actuators; actuator++) + WARN_ON_ONCE(bfqd->rq_in_driver[actuator]); + WARN_ON_ONCE(bfqd->tot_rq_in_driver); + hrtimer_cancel(&bfqd->idle_slice_timer); /* release oom-queue reference to root group */ diff --git a/block/bio.c b/block/bio.c index 043944fd46ebbcac3c30fe722c52f03f71dfd5ab..8672179213b93902dde50a1d125f9563f80a4dcd 100644 --- a/block/bio.c +++ b/block/bio.c @@ -1138,6 +1138,14 @@ int bio_add_page(struct bio *bio, struct page *page, } EXPORT_SYMBOL(bio_add_page); +void bio_add_folio_nofail(struct bio *bio, struct folio *folio, size_t len, + size_t off) +{ + WARN_ON_ONCE(len > UINT_MAX); + WARN_ON_ONCE(off > UINT_MAX); + __bio_add_page(bio, &folio->page, len, off); +} + /** * bio_add_folio - Attempt to add part of a folio to a bio. * @bio: BIO to add to. @@ -1169,7 +1177,7 @@ void __bio_release_pages(struct bio *bio, bool mark_dirty) bio_for_each_segment_all(bvec, bio, iter_all) { if (mark_dirty && !PageCompound(bvec->bv_page)) set_page_dirty_lock(bvec->bv_page); - put_page(bvec->bv_page); + bio_release_page(bio, bvec->bv_page); } } EXPORT_SYMBOL_GPL(__bio_release_pages); @@ -1191,7 +1199,6 @@ void bio_iov_bvec_set(struct bio *bio, struct iov_iter *iter) bio->bi_io_vec = (struct bio_vec *)iter->bvec; bio->bi_iter.bi_bvec_done = iter->iov_offset; bio->bi_iter.bi_size = size; - bio_set_flag(bio, BIO_NO_PAGE_REF); bio_set_flag(bio, BIO_CLONED); } @@ -1206,7 +1213,7 @@ static int bio_iov_add_page(struct bio *bio, struct page *page, } if (same_page) - put_page(page); + bio_release_page(bio, page); return 0; } @@ -1220,7 +1227,7 @@ static int bio_iov_add_zone_append_page(struct bio *bio, struct page *page, queue_max_zone_append_sectors(q), &same_page) != len) return -EINVAL; if (same_page) - put_page(page); + bio_release_page(bio, page); return 0; } @@ -1231,10 +1238,10 @@ static int bio_iov_add_zone_append_page(struct bio *bio, struct page *page, * @bio: bio to add pages to * @iter: iov iterator describing the region to be mapped * - * Pins pages from *iter and appends them to @bio's bvec array. The - * pages will have to be released using put_page() when done. - * For multi-segment *iter, this function only adds pages from the - * next non-empty segment of the iov iterator. + * Extracts pages from *iter and appends them to @bio's bvec array. The pages + * will have to be cleaned up in the way indicated by the BIO_PAGE_PINNED flag. + * For a multi-segment *iter, this function only adds pages from the next + * non-empty segment of the iov iterator. */ static int __bio_iov_iter_get_pages(struct bio *bio, struct iov_iter *iter) { @@ -1266,9 +1273,9 @@ static int __bio_iov_iter_get_pages(struct bio *bio, struct iov_iter *iter) * result to ensure the bio's total size is correct. The remainder of * the iov data will be picked up in the next bio iteration. */ - size = iov_iter_get_pages(iter, pages, - UINT_MAX - bio->bi_iter.bi_size, - nr_pages, &offset, extraction_flags); + size = iov_iter_extract_pages(iter, &pages, + UINT_MAX - bio->bi_iter.bi_size, + nr_pages, extraction_flags, &offset); if (unlikely(size <= 0)) return size ? size : -EFAULT; @@ -1301,7 +1308,7 @@ static int __bio_iov_iter_get_pages(struct bio *bio, struct iov_iter *iter) iov_iter_revert(iter, left); out: while (i < nr_pages) - put_page(pages[i++]); + bio_release_page(bio, pages[i++]); return ret; } @@ -1336,6 +1343,8 @@ int bio_iov_iter_get_pages(struct bio *bio, struct iov_iter *iter) return 0; } + if (iov_iter_extract_will_pin(iter)) + bio_set_flag(bio, BIO_PAGE_PINNED); do { ret = __bio_iov_iter_get_pages(bio, iter); } while (!ret && iov_iter_count(iter) && !bio_full(bio, 0)); @@ -1489,8 +1498,8 @@ void bio_set_pages_dirty(struct bio *bio) * the BIO and re-dirty the pages in process context. * * It is expected that bio_check_pages_dirty() will wholly own the BIO from - * here on. It will run one put_page() against each page and will run one - * bio_put() against the BIO. + * here on. It will unpin each page and will run one bio_put() against the + * BIO. */ static void bio_dirty_fn(struct work_struct *work); diff --git a/block/blk-cgroup-fc-appid.c b/block/blk-cgroup-fc-appid.c index 842e5e1c0f3cb97dafe6810dfbc527a30edb78ff..3ec21333f393b79a6650ff0f214f217fe666bed5 100644 --- a/block/blk-cgroup-fc-appid.c +++ b/block/blk-cgroup-fc-appid.c @@ -34,7 +34,7 @@ int blkcg_set_fc_appid(char *app_id, u64 cgrp_id, size_t app_id_len) * the vmid from the fabric. * Adding the overhead of a lock is not necessary. */ - strlcpy(blkcg->fc_app_id, app_id, app_id_len); + strscpy(blkcg->fc_app_id, app_id, app_id_len); css_put(css); out_cgrp_put: cgroup_put(cgrp); diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c index f0b5c9c41cdee1c40cab795beca2e5e932ef0d00..fc49be622e05b159e3a3a5fb5f717383cd325c93 100644 --- a/block/blk-cgroup.c +++ b/block/blk-cgroup.c @@ -624,8 +624,13 @@ static int blkcg_reset_stats(struct cgroup_subsys_state *css, struct blkg_iostat_set *bis = per_cpu_ptr(blkg->iostat_cpu, cpu); memset(bis, 0, sizeof(*bis)); + + /* Re-initialize the cleared blkg_iostat_set */ + u64_stats_init(&bis->sync); + bis->blkg = blkg; } memset(&blkg->iostat, 0, sizeof(blkg->iostat)); + u64_stats_init(&blkg->iostat.sync); for (i = 0; i < BLKCG_MAX_POLS; i++) { struct blkcg_policy *pol = blkcg_policy[i]; @@ -762,6 +767,13 @@ int blkg_conf_open_bdev(struct blkg_conf_ctx *ctx) return -ENODEV; } + mutex_lock(&bdev->bd_queue->rq_qos_mutex); + if (!disk_live(bdev->bd_disk)) { + blkdev_put_no_open(bdev); + mutex_unlock(&bdev->bd_queue->rq_qos_mutex); + return -ENODEV; + } + ctx->body = input; ctx->bdev = bdev; return 0; @@ -906,6 +918,7 @@ EXPORT_SYMBOL_GPL(blkg_conf_prep); */ void blkg_conf_exit(struct blkg_conf_ctx *ctx) __releases(&ctx->bdev->bd_queue->queue_lock) + __releases(&ctx->bdev->bd_queue->rq_qos_mutex) { if (ctx->blkg) { spin_unlock_irq(&bdev_get_queue(ctx->bdev)->queue_lock); @@ -913,6 +926,7 @@ void blkg_conf_exit(struct blkg_conf_ctx *ctx) } if (ctx->bdev) { + mutex_unlock(&ctx->bdev->bd_queue->rq_qos_mutex); blkdev_put_no_open(ctx->bdev); ctx->body = NULL; ctx->bdev = NULL; @@ -970,6 +984,7 @@ static void __blkcg_rstat_flush(struct blkcg *blkcg, int cpu) struct llist_head *lhead = per_cpu_ptr(blkcg->lhead, cpu); struct llist_node *lnode; struct blkg_iostat_set *bisc, *next_bisc; + unsigned long flags; rcu_read_lock(); @@ -983,7 +998,7 @@ static void __blkcg_rstat_flush(struct blkcg *blkcg, int cpu) * When flushing from cgroup, cgroup_rstat_lock is always held, so * this lock won't cause contention most of time. */ - raw_spin_lock(&blkg_stat_lock); + raw_spin_lock_irqsave(&blkg_stat_lock, flags); /* * Iterate only the iostat_cpu's queued in the lockless list. @@ -1009,7 +1024,7 @@ static void __blkcg_rstat_flush(struct blkcg *blkcg, int cpu) blkcg_iostat_update(parent, &blkg->iostat.cur, &blkg->iostat.last); } - raw_spin_unlock(&blkg_stat_lock); + raw_spin_unlock_irqrestore(&blkg_stat_lock, flags); out: rcu_read_unlock(); } @@ -2071,6 +2086,9 @@ void blk_cgroup_bio_start(struct bio *bio) struct blkg_iostat_set *bis; unsigned long flags; + if (!cgroup_subsys_on_dfl(io_cgrp_subsys)) + return; + /* Root-level stats are sourced from system-wide IO stats */ if (!cgroup_parent(blkcg->css.cgroup)) return; @@ -2101,8 +2119,7 @@ void blk_cgroup_bio_start(struct bio *bio) } u64_stats_update_end_irqrestore(&bis->sync, flags); - if (cgroup_subsys_on_dfl(io_cgrp_subsys)) - cgroup_rstat_updated(blkcg->css.cgroup, cpu); + cgroup_rstat_updated(blkcg->css.cgroup, cpu); put_cpu(); } diff --git a/block/blk-core.c b/block/blk-core.c index 1da77e7d62894651d3e307dbd1be1930983baad8..99d8b9812b18f49a393f2ad714f91dfac91efb61 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -155,7 +155,7 @@ static const struct { [BLK_STS_NOSPC] = { -ENOSPC, "critical space allocation" }, [BLK_STS_TRANSPORT] = { -ENOLINK, "recoverable transport" }, [BLK_STS_TARGET] = { -EREMOTEIO, "critical target" }, - [BLK_STS_NEXUS] = { -EBADE, "critical nexus" }, + [BLK_STS_RESV_CONFLICT] = { -EBADE, "reservation conflict" }, [BLK_STS_MEDIUM] = { -ENODATA, "critical medium" }, [BLK_STS_PROTECTION] = { -EILSEQ, "protection" }, [BLK_STS_RESOURCE] = { -ENOMEM, "kernel resource" }, @@ -170,6 +170,9 @@ static const struct { [BLK_STS_ZONE_OPEN_RESOURCE] = { -ETOOMANYREFS, "open zones exceeded" }, [BLK_STS_ZONE_ACTIVE_RESOURCE] = { -EOVERFLOW, "active zones exceeded" }, + /* Command duration limit device-side timeout */ + [BLK_STS_DURATION_LIMIT] = { -ETIME, "duration limit exceeded" }, + /* everything else not covered above: */ [BLK_STS_IOERR] = { -EIO, "I/O" }, }; @@ -420,6 +423,7 @@ struct request_queue *blk_alloc_queue(int node_id) mutex_init(&q->debugfs_mutex); mutex_init(&q->sysfs_lock); mutex_init(&q->sysfs_dir_lock); + mutex_init(&q->rq_qos_mutex); spin_lock_init(&q->queue_lock); init_waitqueue_head(&q->mq_freeze_wq); diff --git a/block/blk-crypto-profile.c b/block/blk-crypto-profile.c index 2a67d3fb63e5ced175d1da86e2e3d78e130c41b4..7fabc883e39f1cef7e7d250ae7df635a4ccc2ae9 100644 --- a/block/blk-crypto-profile.c +++ b/block/blk-crypto-profile.c @@ -79,7 +79,14 @@ int blk_crypto_profile_init(struct blk_crypto_profile *profile, unsigned int slot_hashtable_size; memset(profile, 0, sizeof(*profile)); - init_rwsem(&profile->lock); + + /* + * profile->lock of an underlying device can nest inside profile->lock + * of a device-mapper device, so use a dynamic lock class to avoid + * false-positive lockdep reports. + */ + lockdep_register_key(&profile->lockdep_key); + __init_rwsem(&profile->lock, "&profile->lock", &profile->lockdep_key); if (num_slots == 0) return 0; @@ -89,7 +96,7 @@ int blk_crypto_profile_init(struct blk_crypto_profile *profile, profile->slots = kvcalloc(num_slots, sizeof(profile->slots[0]), GFP_KERNEL); if (!profile->slots) - return -ENOMEM; + goto err_destroy; profile->num_slots = num_slots; @@ -435,6 +442,7 @@ void blk_crypto_profile_destroy(struct blk_crypto_profile *profile) { if (!profile) return; + lockdep_unregister_key(&profile->lockdep_key); kvfree(profile->slot_hashtable); kvfree_sensitive(profile->slots, sizeof(profile->slots[0]) * profile->num_slots); diff --git a/block/blk-flush.c b/block/blk-flush.c index 04698ed9bcd4a9926761cf0cd5ad28517bea29c8..8220517c2d67dad4e09457b7dd1303e4015a6844 100644 --- a/block/blk-flush.c +++ b/block/blk-flush.c @@ -188,7 +188,9 @@ static void blk_flush_complete_seq(struct request *rq, case REQ_FSEQ_DATA: list_move_tail(&rq->flush.list, &fq->flush_data_in_flight); - blk_mq_add_to_requeue_list(rq, BLK_MQ_INSERT_AT_HEAD); + spin_lock(&q->requeue_lock); + list_add(&rq->queuelist, &q->requeue_list); + spin_unlock(&q->requeue_lock); blk_mq_kick_requeue_list(q); break; @@ -346,7 +348,10 @@ static void blk_kick_flush(struct request_queue *q, struct blk_flush_queue *fq, smp_wmb(); req_ref_set(flush_rq, 1); - blk_mq_add_to_requeue_list(flush_rq, 0); + spin_lock(&q->requeue_lock); + list_add_tail(&flush_rq->queuelist, &q->flush_list); + spin_unlock(&q->requeue_lock); + blk_mq_kick_requeue_list(q); } @@ -376,22 +381,29 @@ static enum rq_end_io_ret mq_flush_data_end_io(struct request *rq, return RQ_END_IO_NONE; } -/** - * blk_insert_flush - insert a new PREFLUSH/FUA request - * @rq: request to insert - * - * To be called from __elv_add_request() for %ELEVATOR_INSERT_FLUSH insertions. - * or __blk_mq_run_hw_queue() to dispatch request. - * @rq is being submitted. Analyze what needs to be done and put it on the - * right queue. +static void blk_rq_init_flush(struct request *rq) +{ + rq->flush.seq = 0; + INIT_LIST_HEAD(&rq->flush.list); + rq->rq_flags |= RQF_FLUSH_SEQ; + rq->flush.saved_end_io = rq->end_io; /* Usually NULL */ + rq->end_io = mq_flush_data_end_io; +} + +/* + * Insert a PREFLUSH/FUA request into the flush state machine. + * Returns true if the request has been consumed by the flush state machine, + * or false if the caller should continue to process it. */ -void blk_insert_flush(struct request *rq) +bool blk_insert_flush(struct request *rq) { struct request_queue *q = rq->q; unsigned long fflags = q->queue_flags; /* may change, cache */ unsigned int policy = blk_flush_policy(fflags, rq); struct blk_flush_queue *fq = blk_get_flush_queue(q, rq->mq_ctx); - struct blk_mq_hw_ctx *hctx = rq->mq_hctx; + + /* FLUSH/FUA request must never be merged */ + WARN_ON_ONCE(rq->bio != rq->biotail); /* * @policy now records what operations need to be done. Adjust @@ -408,45 +420,45 @@ void blk_insert_flush(struct request *rq) */ rq->cmd_flags |= REQ_SYNC; - /* - * An empty flush handed down from a stacking driver may - * translate into nothing if the underlying device does not - * advertise a write-back cache. In this case, simply - * complete the request. - */ - if (!policy) { + switch (policy) { + case 0: + /* + * An empty flush handed down from a stacking driver may + * translate into nothing if the underlying device does not + * advertise a write-back cache. In this case, simply + * complete the request. + */ blk_mq_end_request(rq, 0); - return; - } - - BUG_ON(rq->bio != rq->biotail); /*assumes zero or single bio rq */ - - /* - * If there's data but flush is not necessary, the request can be - * processed directly without going through flush machinery. Queue - * for normal execution. - */ - if ((policy & REQ_FSEQ_DATA) && - !(policy & (REQ_FSEQ_PREFLUSH | REQ_FSEQ_POSTFLUSH))) { - blk_mq_request_bypass_insert(rq, 0); - blk_mq_run_hw_queue(hctx, false); - return; + return true; + case REQ_FSEQ_DATA: + /* + * If there's data, but no flush is necessary, the request can + * be processed directly without going through flush machinery. + * Queue for normal execution. + */ + return false; + case REQ_FSEQ_DATA | REQ_FSEQ_POSTFLUSH: + /* + * Initialize the flush fields and completion handler to trigger + * the post flush, and then just pass the command on. + */ + blk_rq_init_flush(rq); + rq->flush.seq |= REQ_FSEQ_POSTFLUSH; + spin_lock_irq(&fq->mq_flush_lock); + list_move_tail(&rq->flush.list, &fq->flush_data_in_flight); + spin_unlock_irq(&fq->mq_flush_lock); + return false; + default: + /* + * Mark the request as part of a flush sequence and submit it + * for further processing to the flush state machine. + */ + blk_rq_init_flush(rq); + spin_lock_irq(&fq->mq_flush_lock); + blk_flush_complete_seq(rq, fq, REQ_FSEQ_ACTIONS & ~policy, 0); + spin_unlock_irq(&fq->mq_flush_lock); + return true; } - - /* - * @rq should go through flush machinery. Mark it part of flush - * sequence and submit for further processing. - */ - memset(&rq->flush, 0, sizeof(rq->flush)); - INIT_LIST_HEAD(&rq->flush.list); - rq->rq_flags |= RQF_FLUSH_SEQ; - rq->flush.saved_end_io = rq->end_io; /* Usually NULL */ - - rq->end_io = mq_flush_data_end_io; - - spin_lock_irq(&fq->mq_flush_lock); - blk_flush_complete_seq(rq, fq, REQ_FSEQ_ACTIONS & ~policy, 0); - spin_unlock_irq(&fq->mq_flush_lock); } /** diff --git a/block/blk-ioc.c b/block/blk-ioc.c index 63fc02042408274a8dd100d5214a44d293e6e130..25dd4db11121bf5490fb0be64dc9681a6983af29 100644 --- a/block/blk-ioc.c +++ b/block/blk-ioc.c @@ -77,6 +77,10 @@ static void ioc_destroy_icq(struct io_cq *icq) struct elevator_type *et = q->elevator->type; lockdep_assert_held(&ioc->lock); + lockdep_assert_held(&q->queue_lock); + + if (icq->flags & ICQ_DESTROYED) + return; radix_tree_delete(&ioc->icq_tree, icq->q->id); hlist_del_init(&icq->ioc_node); @@ -128,12 +132,7 @@ static void ioc_release_fn(struct work_struct *work) spin_lock(&q->queue_lock); spin_lock(&ioc->lock); - /* - * The icq may have been destroyed when the ioc lock - * was released. - */ - if (!(icq->flags & ICQ_DESTROYED)) - ioc_destroy_icq(icq); + ioc_destroy_icq(icq); spin_unlock(&q->queue_lock); rcu_read_unlock(); @@ -171,23 +170,20 @@ static bool ioc_delay_free(struct io_context *ioc) */ void ioc_clear_queue(struct request_queue *q) { - LIST_HEAD(icq_list); - spin_lock_irq(&q->queue_lock); - list_splice_init(&q->icq_list, &icq_list); - spin_unlock_irq(&q->queue_lock); - - rcu_read_lock(); - while (!list_empty(&icq_list)) { + while (!list_empty(&q->icq_list)) { struct io_cq *icq = - list_entry(icq_list.next, struct io_cq, q_node); - - spin_lock_irq(&icq->ioc->lock); - if (!(icq->flags & ICQ_DESTROYED)) - ioc_destroy_icq(icq); - spin_unlock_irq(&icq->ioc->lock); + list_first_entry(&q->icq_list, struct io_cq, q_node); + + /* + * Other context won't hold ioc lock to wait for queue_lock, see + * details in ioc_release_fn(). + */ + spin_lock(&icq->ioc->lock); + ioc_destroy_icq(icq); + spin_unlock(&icq->ioc->lock); } - rcu_read_unlock(); + spin_unlock_irq(&q->queue_lock); } #else /* CONFIG_BLK_ICQ */ static inline void ioc_exit_icqs(struct io_context *ioc) diff --git a/block/blk-iocost.c b/block/blk-iocost.c index 285ced3467abb10f2a926bc86588f14fefe87c07..9dfcf540f4001048a6299fc0dd0232acc79bbba8 100644 --- a/block/blk-iocost.c +++ b/block/blk-iocost.c @@ -2455,6 +2455,7 @@ static u64 adjust_inuse_and_calc_cost(struct ioc_gq *iocg, u64 vtime, u32 hwi, adj_step; s64 margin; u64 cost, new_inuse; + unsigned long flags; current_hweight(iocg, NULL, &hwi); old_hwi = hwi; @@ -2473,11 +2474,11 @@ static u64 adjust_inuse_and_calc_cost(struct ioc_gq *iocg, u64 vtime, iocg->inuse == iocg->active) return cost; - spin_lock_irq(&ioc->lock); + spin_lock_irqsave(&ioc->lock, flags); /* we own inuse only when @iocg is in the normal active state */ if (iocg->abs_vdebt || list_empty(&iocg->active_list)) { - spin_unlock_irq(&ioc->lock); + spin_unlock_irqrestore(&ioc->lock, flags); return cost; } @@ -2498,7 +2499,7 @@ static u64 adjust_inuse_and_calc_cost(struct ioc_gq *iocg, u64 vtime, } while (time_after64(vtime + cost, now->vnow) && iocg->inuse != iocg->active); - spin_unlock_irq(&ioc->lock); + spin_unlock_irqrestore(&ioc->lock, flags); TRACE_IOCG_PATH(inuse_adjust, iocg, now, old_inuse, iocg->inuse, old_hwi, hwi); @@ -3300,11 +3301,9 @@ static ssize_t ioc_qos_write(struct kernfs_open_file *of, char *input, blk_stat_enable_accounting(disk->queue); blk_queue_flag_set(QUEUE_FLAG_RQ_ALLOC_TIME, disk->queue); ioc->enabled = true; - wbt_disable_default(disk); } else { blk_queue_flag_clear(QUEUE_FLAG_RQ_ALLOC_TIME, disk->queue); ioc->enabled = false; - wbt_enable_default(disk); } if (user) { @@ -3317,6 +3316,11 @@ static ssize_t ioc_qos_write(struct kernfs_open_file *of, char *input, ioc_refresh_params(ioc, true); spin_unlock_irq(&ioc->lock); + if (enable) + wbt_disable_default(disk); + else + wbt_enable_default(disk); + blk_mq_unquiesce_queue(disk->queue); blk_mq_unfreeze_queue(disk->queue); diff --git a/block/blk-ioprio.c b/block/blk-ioprio.c index 055529b9b92bab5de70e689d76f536345d4067c3..4051fada01f1e87086b95d34a67743efbfd342f0 100644 --- a/block/blk-ioprio.c +++ b/block/blk-ioprio.c @@ -23,25 +23,28 @@ /** * enum prio_policy - I/O priority class policy. * @POLICY_NO_CHANGE: (default) do not modify the I/O priority class. - * @POLICY_NONE_TO_RT: modify IOPRIO_CLASS_NONE into IOPRIO_CLASS_RT. + * @POLICY_PROMOTE_TO_RT: modify no-IOPRIO_CLASS_RT to IOPRIO_CLASS_RT. * @POLICY_RESTRICT_TO_BE: modify IOPRIO_CLASS_NONE and IOPRIO_CLASS_RT into * IOPRIO_CLASS_BE. * @POLICY_ALL_TO_IDLE: change the I/O priority class into IOPRIO_CLASS_IDLE. + * @POLICY_NONE_TO_RT: an alias for POLICY_PROMOTE_TO_RT. * * See also . */ enum prio_policy { POLICY_NO_CHANGE = 0, - POLICY_NONE_TO_RT = 1, + POLICY_PROMOTE_TO_RT = 1, POLICY_RESTRICT_TO_BE = 2, POLICY_ALL_TO_IDLE = 3, + POLICY_NONE_TO_RT = 4, }; static const char *policy_name[] = { [POLICY_NO_CHANGE] = "no-change", - [POLICY_NONE_TO_RT] = "none-to-rt", + [POLICY_PROMOTE_TO_RT] = "promote-to-rt", [POLICY_RESTRICT_TO_BE] = "restrict-to-be", [POLICY_ALL_TO_IDLE] = "idle", + [POLICY_NONE_TO_RT] = "none-to-rt", }; static struct blkcg_policy ioprio_policy; @@ -189,6 +192,20 @@ void blkcg_set_ioprio(struct bio *bio) if (!blkcg || blkcg->prio_policy == POLICY_NO_CHANGE) return; + if (blkcg->prio_policy == POLICY_PROMOTE_TO_RT || + blkcg->prio_policy == POLICY_NONE_TO_RT) { + /* + * For RT threads, the default priority level is 4 because + * task_nice is 0. By promoting non-RT io-priority to RT-class + * and default level 4, those requests that are already + * RT-class but need a higher io-priority can use ioprio_set() + * to achieve this. + */ + if (IOPRIO_PRIO_CLASS(bio->bi_ioprio) != IOPRIO_CLASS_RT) + bio->bi_ioprio = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_RT, 4); + return; + } + /* * Except for IOPRIO_CLASS_NONE, higher I/O priority numbers * correspond to a lower priority. Hence, the max_t() below selects diff --git a/block/blk-map.c b/block/blk-map.c index 46eed2e627c363a4ab6a3797b538380be6a45ef6..44d74a30ddac042ec29c2b6880724c3156fd49d8 100644 --- a/block/blk-map.c +++ b/block/blk-map.c @@ -281,21 +281,21 @@ static int bio_map_user_iov(struct request *rq, struct iov_iter *iter, if (blk_queue_pci_p2pdma(rq->q)) extraction_flags |= ITER_ALLOW_P2PDMA; + if (iov_iter_extract_will_pin(iter)) + bio_set_flag(bio, BIO_PAGE_PINNED); while (iov_iter_count(iter)) { - struct page **pages, *stack_pages[UIO_FASTIOV]; + struct page *stack_pages[UIO_FASTIOV]; + struct page **pages = stack_pages; ssize_t bytes; size_t offs; int npages; - if (nr_vecs <= ARRAY_SIZE(stack_pages)) { - pages = stack_pages; - bytes = iov_iter_get_pages(iter, pages, LONG_MAX, - nr_vecs, &offs, extraction_flags); - } else { - bytes = iov_iter_get_pages_alloc(iter, &pages, - LONG_MAX, &offs, extraction_flags); - } + if (nr_vecs > ARRAY_SIZE(stack_pages)) + pages = NULL; + + bytes = iov_iter_extract_pages(iter, &pages, LONG_MAX, + nr_vecs, extraction_flags, &offs); if (unlikely(bytes <= 0)) { ret = bytes ? bytes : -EFAULT; goto out_unmap; @@ -317,7 +317,7 @@ static int bio_map_user_iov(struct request *rq, struct iov_iter *iter, if (!bio_add_hw_page(rq->q, bio, page, n, offs, max_sectors, &same_page)) { if (same_page) - put_page(page); + bio_release_page(bio, page); break; } @@ -329,7 +329,7 @@ static int bio_map_user_iov(struct request *rq, struct iov_iter *iter, * release the pages we didn't map into the bio, if any */ while (j < npages) - put_page(pages[j++]); + bio_release_page(bio, pages[j++]); if (pages != stack_pages) kvfree(pages); /* couldn't stuff something into bio? */ diff --git a/block/blk-mq-debugfs.c b/block/blk-mq-debugfs.c index d23a8554ec4aeb15dac8375b0973b7ebd06af5c7..c3b5930106b288bec70850a90f88f2fdc1ed5a38 100644 --- a/block/blk-mq-debugfs.c +++ b/block/blk-mq-debugfs.c @@ -88,6 +88,7 @@ static const char *const blk_queue_flag_name[] = { QUEUE_FLAG_NAME(IO_STAT), QUEUE_FLAG_NAME(NOXMERGES), QUEUE_FLAG_NAME(ADD_RANDOM), + QUEUE_FLAG_NAME(SYNCHRONOUS), QUEUE_FLAG_NAME(SAME_FORCE), QUEUE_FLAG_NAME(INIT_DONE), QUEUE_FLAG_NAME(STABLE_WRITES), @@ -103,6 +104,8 @@ static const char *const blk_queue_flag_name[] = { QUEUE_FLAG_NAME(RQ_ALLOC_TIME), QUEUE_FLAG_NAME(HCTX_ACTIVE), QUEUE_FLAG_NAME(NOWAIT), + QUEUE_FLAG_NAME(SQ_SCHED), + QUEUE_FLAG_NAME(SKIP_TAGSET_QUIESCE), }; #undef QUEUE_FLAG_NAME @@ -241,14 +244,14 @@ static const char *const cmd_flag_name[] = { #define RQF_NAME(name) [ilog2((__force u32)RQF_##name)] = #name static const char *const rqf_name[] = { RQF_NAME(STARTED), - RQF_NAME(SOFTBARRIER), RQF_NAME(FLUSH_SEQ), RQF_NAME(MIXED_MERGE), RQF_NAME(MQ_INFLIGHT), RQF_NAME(DONTPREP), + RQF_NAME(SCHED_TAGS), + RQF_NAME(USE_SCHED), RQF_NAME(FAILED), RQF_NAME(QUIET), - RQF_NAME(ELVPRIV), RQF_NAME(IO_STAT), RQF_NAME(PM), RQF_NAME(HASHED), @@ -256,7 +259,6 @@ static const char *const rqf_name[] = { RQF_NAME(SPECIAL_PAYLOAD), RQF_NAME(ZONE_WRITE_LOCKED), RQF_NAME(TIMED_OUT), - RQF_NAME(ELV), RQF_NAME(RESV), }; #undef RQF_NAME @@ -399,7 +401,7 @@ static void blk_mq_debugfs_tags_show(struct seq_file *m, seq_printf(m, "nr_tags=%u\n", tags->nr_tags); seq_printf(m, "nr_reserved_tags=%u\n", tags->nr_reserved_tags); seq_printf(m, "active_queues=%d\n", - atomic_read(&tags->active_queues)); + READ_ONCE(tags->active_queues)); seq_puts(m, "\nbitmap_tags:\n"); sbitmap_queue_show(&tags->bitmap_tags, m); diff --git a/block/blk-mq-sched.h b/block/blk-mq-sched.h index 7c3cbad17f3052065ef5f5285451c2fdf3b60336..1326526bb7338ce28989101b896d5d2d58864f5f 100644 --- a/block/blk-mq-sched.h +++ b/block/blk-mq-sched.h @@ -37,7 +37,7 @@ static inline bool blk_mq_sched_allow_merge(struct request_queue *q, struct request *rq, struct bio *bio) { - if (rq->rq_flags & RQF_ELV) { + if (rq->rq_flags & RQF_USE_SCHED) { struct elevator_queue *e = q->elevator; if (e->type->ops.allow_merge) @@ -48,7 +48,7 @@ blk_mq_sched_allow_merge(struct request_queue *q, struct request *rq, static inline void blk_mq_sched_completed_request(struct request *rq, u64 now) { - if (rq->rq_flags & RQF_ELV) { + if (rq->rq_flags & RQF_USE_SCHED) { struct elevator_queue *e = rq->q->elevator; if (e->type->ops.completed_request) @@ -58,11 +58,11 @@ static inline void blk_mq_sched_completed_request(struct request *rq, u64 now) static inline void blk_mq_sched_requeue_request(struct request *rq) { - if (rq->rq_flags & RQF_ELV) { + if (rq->rq_flags & RQF_USE_SCHED) { struct request_queue *q = rq->q; struct elevator_queue *e = q->elevator; - if ((rq->rq_flags & RQF_ELVPRIV) && e->type->ops.requeue_request) + if (e->type->ops.requeue_request) e->type->ops.requeue_request(rq); } } diff --git a/block/blk-mq-tag.c b/block/blk-mq-tag.c index dfd81cab57888b33a39b7b8b8e7d8d1c3bae0506..cc57e2dd9a0bb3cf0f6443a29800f6a76120bc5e 100644 --- a/block/blk-mq-tag.c +++ b/block/blk-mq-tag.c @@ -38,6 +38,7 @@ static void blk_mq_update_wake_batch(struct blk_mq_tags *tags, void __blk_mq_tag_busy(struct blk_mq_hw_ctx *hctx) { unsigned int users; + struct blk_mq_tags *tags = hctx->tags; /* * calling test_bit() prior to test_and_set_bit() is intentional, @@ -55,9 +56,11 @@ void __blk_mq_tag_busy(struct blk_mq_hw_ctx *hctx) return; } - users = atomic_inc_return(&hctx->tags->active_queues); - - blk_mq_update_wake_batch(hctx->tags, users); + spin_lock_irq(&tags->lock); + users = tags->active_queues + 1; + WRITE_ONCE(tags->active_queues, users); + blk_mq_update_wake_batch(tags, users); + spin_unlock_irq(&tags->lock); } /* @@ -90,9 +93,11 @@ void __blk_mq_tag_idle(struct blk_mq_hw_ctx *hctx) return; } - users = atomic_dec_return(&tags->active_queues); - + spin_lock_irq(&tags->lock); + users = tags->active_queues - 1; + WRITE_ONCE(tags->active_queues, users); blk_mq_update_wake_batch(tags, users); + spin_unlock_irq(&tags->lock); blk_mq_tag_wakeup_all(tags, false); } diff --git a/block/blk-mq.c b/block/blk-mq.c index 850bfb844ed2f75b7c37774fe541a08cd59294c5..d50b1d62a3d923fc050c53802d87fb08cd9aab49 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c @@ -45,19 +45,12 @@ static DEFINE_PER_CPU(struct llist_head, blk_cpu_done); static void blk_mq_insert_request(struct request *rq, blk_insert_t flags); +static void blk_mq_request_bypass_insert(struct request *rq, + blk_insert_t flags); static void blk_mq_try_issue_list_directly(struct blk_mq_hw_ctx *hctx, struct list_head *list); - -static inline struct blk_mq_hw_ctx *blk_qc_to_hctx(struct request_queue *q, - blk_qc_t qc) -{ - return xa_load(&q->hctx_table, qc); -} - -static inline blk_qc_t blk_rq_to_qc(struct request *rq) -{ - return rq->mq_hctx->queue_num; -} +static int blk_hctx_poll(struct request_queue *q, struct blk_mq_hw_ctx *hctx, + struct io_comp_batch *iob, unsigned int flags); /* * Check if any of the ctx, dispatch list or elevator @@ -335,8 +328,24 @@ void blk_rq_init(struct request_queue *q, struct request *rq) } EXPORT_SYMBOL(blk_rq_init); +/* Set start and alloc time when the allocated request is actually used */ +static inline void blk_mq_rq_time_init(struct request *rq, u64 alloc_time_ns) +{ + if (blk_mq_need_time_stamp(rq)) + rq->start_time_ns = ktime_get_ns(); + else + rq->start_time_ns = 0; + +#ifdef CONFIG_BLK_RQ_ALLOC_TIME + if (blk_queue_rq_alloc_time(rq->q)) + rq->alloc_time_ns = alloc_time_ns ?: rq->start_time_ns; + else + rq->alloc_time_ns = 0; +#endif +} + static struct request *blk_mq_rq_ctx_init(struct blk_mq_alloc_data *data, - struct blk_mq_tags *tags, unsigned int tag, u64 alloc_time_ns) + struct blk_mq_tags *tags, unsigned int tag) { struct blk_mq_ctx *ctx = data->ctx; struct blk_mq_hw_ctx *hctx = data->hctx; @@ -354,23 +363,16 @@ static struct request *blk_mq_rq_ctx_init(struct blk_mq_alloc_data *data, data->rq_flags |= RQF_IO_STAT; rq->rq_flags = data->rq_flags; - if (!(data->rq_flags & RQF_ELV)) { - rq->tag = tag; - rq->internal_tag = BLK_MQ_NO_TAG; - } else { + if (data->rq_flags & RQF_SCHED_TAGS) { rq->tag = BLK_MQ_NO_TAG; rq->internal_tag = tag; + } else { + rq->tag = tag; + rq->internal_tag = BLK_MQ_NO_TAG; } rq->timeout = 0; - if (blk_mq_need_time_stamp(rq)) - rq->start_time_ns = ktime_get_ns(); - else - rq->start_time_ns = 0; rq->part = NULL; -#ifdef CONFIG_BLK_RQ_ALLOC_TIME - rq->alloc_time_ns = alloc_time_ns; -#endif rq->io_start_time_ns = 0; rq->stats_sectors = 0; rq->nr_phys_segments = 0; @@ -386,25 +388,21 @@ static struct request *blk_mq_rq_ctx_init(struct blk_mq_alloc_data *data, WRITE_ONCE(rq->deadline, 0); req_ref_set(rq, 1); - if (rq->rq_flags & RQF_ELV) { + if (rq->rq_flags & RQF_USE_SCHED) { struct elevator_queue *e = data->q->elevator; INIT_HLIST_NODE(&rq->hash); RB_CLEAR_NODE(&rq->rb_node); - if (!op_is_flush(data->cmd_flags) && - e->type->ops.prepare_request) { + if (e->type->ops.prepare_request) e->type->ops.prepare_request(rq); - rq->rq_flags |= RQF_ELVPRIV; - } } return rq; } static inline struct request * -__blk_mq_alloc_requests_batch(struct blk_mq_alloc_data *data, - u64 alloc_time_ns) +__blk_mq_alloc_requests_batch(struct blk_mq_alloc_data *data) { unsigned int tag, tag_offset; struct blk_mq_tags *tags; @@ -423,7 +421,7 @@ __blk_mq_alloc_requests_batch(struct blk_mq_alloc_data *data, tag = tag_offset + i; prefetch(tags->static_rqs[tag]); tag_mask &= ~(1UL << i); - rq = blk_mq_rq_ctx_init(data, tags, tag, alloc_time_ns); + rq = blk_mq_rq_ctx_init(data, tags, tag); rq_list_add(data->cached_rq, rq); nr++; } @@ -449,26 +447,32 @@ static struct request *__blk_mq_alloc_requests(struct blk_mq_alloc_data *data) data->flags |= BLK_MQ_REQ_NOWAIT; if (q->elevator) { - struct elevator_queue *e = q->elevator; - - data->rq_flags |= RQF_ELV; + /* + * All requests use scheduler tags when an I/O scheduler is + * enabled for the queue. + */ + data->rq_flags |= RQF_SCHED_TAGS; /* * Flush/passthrough requests are special and go directly to the - * dispatch list. Don't include reserved tags in the - * limiting, as it isn't useful. + * dispatch list. */ - if (!op_is_flush(data->cmd_flags) && - !blk_op_is_passthrough(data->cmd_flags) && - e->type->ops.limit_depth && - !(data->flags & BLK_MQ_REQ_RESERVED)) - e->type->ops.limit_depth(data->cmd_flags, data); + if ((data->cmd_flags & REQ_OP_MASK) != REQ_OP_FLUSH && + !blk_op_is_passthrough(data->cmd_flags)) { + struct elevator_mq_ops *ops = &q->elevator->type->ops; + + WARN_ON_ONCE(data->flags & BLK_MQ_REQ_RESERVED); + + data->rq_flags |= RQF_USE_SCHED; + if (ops->limit_depth) + ops->limit_depth(data->cmd_flags, data); + } } retry: data->ctx = blk_mq_get_ctx(q); data->hctx = blk_mq_map_queue(q, data->cmd_flags, data->ctx); - if (!(data->rq_flags & RQF_ELV)) + if (!(data->rq_flags & RQF_SCHED_TAGS)) blk_mq_tag_busy(data->hctx); if (data->flags & BLK_MQ_REQ_RESERVED) @@ -478,9 +482,11 @@ static struct request *__blk_mq_alloc_requests(struct blk_mq_alloc_data *data) * Try batched alloc if we want more than 1 tag. */ if (data->nr_tags > 1) { - rq = __blk_mq_alloc_requests_batch(data, alloc_time_ns); - if (rq) + rq = __blk_mq_alloc_requests_batch(data); + if (rq) { + blk_mq_rq_time_init(rq, alloc_time_ns); return rq; + } data->nr_tags = 1; } @@ -503,8 +509,9 @@ static struct request *__blk_mq_alloc_requests(struct blk_mq_alloc_data *data) goto retry; } - return blk_mq_rq_ctx_init(data, blk_mq_tags_from_data(data), tag, - alloc_time_ns); + rq = blk_mq_rq_ctx_init(data, blk_mq_tags_from_data(data), tag); + blk_mq_rq_time_init(rq, alloc_time_ns); + return rq; } static struct request *blk_mq_rq_cache_fill(struct request_queue *q, @@ -559,6 +566,7 @@ static struct request *blk_mq_alloc_cached_request(struct request_queue *q, return NULL; plug->cached_rq = rq_list_next(rq); + blk_mq_rq_time_init(rq, 0); } rq->cmd_flags = opf; @@ -648,10 +656,10 @@ struct request *blk_mq_alloc_request_hctx(struct request_queue *q, goto out_queue_exit; data.ctx = __blk_mq_get_ctx(q, cpu); - if (!q->elevator) - blk_mq_tag_busy(data.hctx); + if (q->elevator) + data.rq_flags |= RQF_SCHED_TAGS; else - data.rq_flags |= RQF_ELV; + blk_mq_tag_busy(data.hctx); if (flags & BLK_MQ_REQ_RESERVED) data.rq_flags |= RQF_RESV; @@ -660,8 +668,8 @@ struct request *blk_mq_alloc_request_hctx(struct request_queue *q, tag = blk_mq_get_tag(&data); if (tag == BLK_MQ_NO_TAG) goto out_queue_exit; - rq = blk_mq_rq_ctx_init(&data, blk_mq_tags_from_data(&data), tag, - alloc_time_ns); + rq = blk_mq_rq_ctx_init(&data, blk_mq_tags_from_data(&data), tag); + blk_mq_rq_time_init(rq, alloc_time_ns); rq->__data_len = 0; rq->__sector = (sector_t) -1; rq->bio = rq->biotail = NULL; @@ -699,7 +707,7 @@ void blk_mq_free_request(struct request *rq) { struct request_queue *q = rq->q; - if ((rq->rq_flags & RQF_ELVPRIV) && + if ((rq->rq_flags & RQF_USE_SCHED) && q->elevator->type->ops.finish_request) q->elevator->type->ops.finish_request(rq); @@ -957,6 +965,8 @@ EXPORT_SYMBOL_GPL(blk_update_request); static inline void blk_account_io_done(struct request *req, u64 now) { + trace_block_io_done(req); + /* * Account IO completion. flush_rq isn't accounted as a * normal IO on queueing nor completion. Accounting the @@ -976,6 +986,8 @@ static inline void blk_account_io_done(struct request *req, u64 now) static inline void blk_account_io_start(struct request *req) { + trace_block_io_start(req); + if (blk_do_io_stat(req)) { /* * All non-passthrough requests are created from a bio with one @@ -1176,8 +1188,9 @@ bool blk_mq_complete_request_remote(struct request *rq) * or a polled request, always complete locally, * it's pointless to redirect the completion. */ - if (rq->mq_hctx->nr_ctx == 1 || - rq->cmd_flags & REQ_POLLED) + if ((rq->mq_hctx->nr_ctx == 1 && + rq->mq_ctx->cpu == raw_smp_processor_id()) || + rq->cmd_flags & REQ_POLLED) return false; if (blk_mq_complete_need_ipi(rq)) { @@ -1238,7 +1251,7 @@ void blk_mq_start_request(struct request *rq) q->integrity.profile->prepare_fn(rq); #endif if (rq->bio && rq->bio->bi_opf & REQ_POLLED) - WRITE_ONCE(rq->bio->bi_cookie, blk_rq_to_qc(rq)); + WRITE_ONCE(rq->bio->bi_cookie, rq->mq_hctx->queue_num); } EXPORT_SYMBOL(blk_mq_start_request); @@ -1270,7 +1283,11 @@ static void blk_add_rq_to_plug(struct blk_plug *plug, struct request *rq) if (!plug->multiple_queues && last && last->q != rq->q) plug->multiple_queues = true; - if (!plug->has_elevator && (rq->rq_flags & RQF_ELV)) + /* + * Any request allocated from sched tags can't be issued to + * ->queue_rqs() directly + */ + if (!plug->has_elevator && (rq->rq_flags & RQF_SCHED_TAGS)) plug->has_elevator = true; rq->rq_next = NULL; rq_list_add(&plug->mq_list, rq); @@ -1340,7 +1357,7 @@ EXPORT_SYMBOL_GPL(blk_rq_is_poll); static void blk_rq_poll_completion(struct request *rq, struct completion *wait) { do { - blk_mq_poll(rq->q, blk_rq_to_qc(rq), NULL, 0); + blk_hctx_poll(rq->q, rq->mq_hctx, NULL, 0); cond_resched(); } while (!completion_done(wait)); } @@ -1411,13 +1428,16 @@ static void __blk_mq_requeue_request(struct request *rq) void blk_mq_requeue_request(struct request *rq, bool kick_requeue_list) { struct request_queue *q = rq->q; + unsigned long flags; __blk_mq_requeue_request(rq); /* this request will be re-inserted to io scheduler queue */ blk_mq_sched_requeue_request(rq); - blk_mq_add_to_requeue_list(rq, BLK_MQ_INSERT_AT_HEAD); + spin_lock_irqsave(&q->requeue_lock, flags); + list_add_tail(&rq->queuelist, &q->requeue_list); + spin_unlock_irqrestore(&q->requeue_lock, flags); if (kick_requeue_list) blk_mq_kick_requeue_list(q); @@ -1429,13 +1449,16 @@ static void blk_mq_requeue_work(struct work_struct *work) struct request_queue *q = container_of(work, struct request_queue, requeue_work.work); LIST_HEAD(rq_list); - struct request *rq, *next; + LIST_HEAD(flush_list); + struct request *rq; spin_lock_irq(&q->requeue_lock); list_splice_init(&q->requeue_list, &rq_list); + list_splice_init(&q->flush_list, &flush_list); spin_unlock_irq(&q->requeue_lock); - list_for_each_entry_safe(rq, next, &rq_list, queuelist) { + while (!list_empty(&rq_list)) { + rq = list_entry(rq_list.next, struct request, queuelist); /* * If RQF_DONTPREP ist set, the request has been started by the * driver already and might have driver-specific data allocated @@ -1443,18 +1466,16 @@ static void blk_mq_requeue_work(struct work_struct *work) * block layer merges for the request. */ if (rq->rq_flags & RQF_DONTPREP) { - rq->rq_flags &= ~RQF_SOFTBARRIER; list_del_init(&rq->queuelist); blk_mq_request_bypass_insert(rq, 0); - } else if (rq->rq_flags & RQF_SOFTBARRIER) { - rq->rq_flags &= ~RQF_SOFTBARRIER; + } else { list_del_init(&rq->queuelist); blk_mq_insert_request(rq, BLK_MQ_INSERT_AT_HEAD); } } - while (!list_empty(&rq_list)) { - rq = list_entry(rq_list.next, struct request, queuelist); + while (!list_empty(&flush_list)) { + rq = list_entry(flush_list.next, struct request, queuelist); list_del_init(&rq->queuelist); blk_mq_insert_request(rq, 0); } @@ -1462,27 +1483,6 @@ static void blk_mq_requeue_work(struct work_struct *work) blk_mq_run_hw_queues(q, false); } -void blk_mq_add_to_requeue_list(struct request *rq, blk_insert_t insert_flags) -{ - struct request_queue *q = rq->q; - unsigned long flags; - - /* - * We abuse this flag that is otherwise used by the I/O scheduler to - * request head insertion from the workqueue. - */ - BUG_ON(rq->rq_flags & RQF_SOFTBARRIER); - - spin_lock_irqsave(&q->requeue_lock, flags); - if (insert_flags & BLK_MQ_INSERT_AT_HEAD) { - rq->rq_flags |= RQF_SOFTBARRIER; - list_add(&rq->queuelist, &q->requeue_list); - } else { - list_add_tail(&rq->queuelist, &q->requeue_list); - } - spin_unlock_irqrestore(&q->requeue_lock, flags); -} - void blk_mq_kick_requeue_list(struct request_queue *q) { kblockd_mod_delayed_work_on(WORK_CPU_UNBOUND, &q->requeue_work, 0); @@ -2427,7 +2427,7 @@ static void blk_mq_run_work_fn(struct work_struct *work) * Should only be used carefully, when the caller knows we want to * bypass a potential IO scheduler on the target device. */ -void blk_mq_request_bypass_insert(struct request *rq, blk_insert_t flags) +static void blk_mq_request_bypass_insert(struct request *rq, blk_insert_t flags) { struct blk_mq_hw_ctx *hctx = rq->mq_hctx; @@ -2492,7 +2492,7 @@ static void blk_mq_insert_request(struct request *rq, blk_insert_t flags) * dispatch it given we prioritize requests in hctx->dispatch. */ blk_mq_request_bypass_insert(rq, flags); - } else if (rq->rq_flags & RQF_FLUSH_SEQ) { + } else if (req_op(rq) == REQ_OP_FLUSH) { /* * Firstly normal IO request is inserted to scheduler queue or * sw queue, meantime we add flush request to dispatch queue( @@ -2622,7 +2622,7 @@ static void blk_mq_try_issue_directly(struct blk_mq_hw_ctx *hctx, return; } - if ((rq->rq_flags & RQF_ELV) || !blk_mq_get_budget_and_tag(rq)) { + if ((rq->rq_flags & RQF_USE_SCHED) || !blk_mq_get_budget_and_tag(rq)) { blk_mq_insert_request(rq, 0); blk_mq_run_hw_queue(hctx, false); return; @@ -2711,6 +2711,7 @@ static void blk_mq_dispatch_plug_list(struct blk_plug *plug, bool from_sched) struct request *requeue_list = NULL; struct request **requeue_lastp = &requeue_list; unsigned int depth = 0; + bool is_passthrough = false; LIST_HEAD(list); do { @@ -2719,7 +2720,9 @@ static void blk_mq_dispatch_plug_list(struct blk_plug *plug, bool from_sched) if (!this_hctx) { this_hctx = rq->mq_hctx; this_ctx = rq->mq_ctx; - } else if (this_hctx != rq->mq_hctx || this_ctx != rq->mq_ctx) { + is_passthrough = blk_rq_is_passthrough(rq); + } else if (this_hctx != rq->mq_hctx || this_ctx != rq->mq_ctx || + is_passthrough != blk_rq_is_passthrough(rq)) { rq_list_add_tail(&requeue_lastp, rq); continue; } @@ -2731,7 +2734,13 @@ static void blk_mq_dispatch_plug_list(struct blk_plug *plug, bool from_sched) trace_block_unplug(this_hctx->queue, depth, !from_sched); percpu_ref_get(&this_hctx->queue->q_usage_counter); - if (this_hctx->queue->elevator) { + /* passthrough requests should never be issued to the I/O scheduler */ + if (is_passthrough) { + spin_lock(&this_hctx->lock); + list_splice_tail_init(&list, &this_hctx->dispatch); + spin_unlock(&this_hctx->lock); + blk_mq_run_hw_queue(this_hctx, from_sched); + } else if (this_hctx->queue->elevator) { this_hctx->queue->elevator->type->ops.insert_requests(this_hctx, &list, 0); blk_mq_run_hw_queue(this_hctx, from_sched); @@ -2899,6 +2908,7 @@ static inline struct request *blk_mq_get_cached_request(struct request_queue *q, plug->cached_rq = rq_list_next(rq); rq_qos_throttle(q, *bio); + blk_mq_rq_time_init(rq, 0); rq->cmd_flags = (*bio)->bi_opf; INIT_LIST_HEAD(&rq->queuelist); return rq; @@ -2970,10 +2980,8 @@ void blk_mq_submit_bio(struct bio *bio) return; } - if (op_is_flush(bio->bi_opf)) { - blk_insert_flush(rq); + if (op_is_flush(bio->bi_opf) && blk_insert_flush(rq)) return; - } if (plug) { blk_add_rq_to_plug(plug, rq); @@ -2981,7 +2989,7 @@ void blk_mq_submit_bio(struct bio *bio) } hctx = rq->mq_hctx; - if ((rq->rq_flags & RQF_ELV) || + if ((rq->rq_flags & RQF_USE_SCHED) || (hctx->dispatch_busy && (q->nr_hw_queues == 1 || !is_sync))) { blk_mq_insert_request(rq, 0); blk_mq_run_hw_queue(hctx, true); @@ -4232,6 +4240,7 @@ int blk_mq_init_allocated_queue(struct blk_mq_tag_set *set, blk_mq_update_poll_flag(q); INIT_DELAYED_WORK(&q->requeue_work, blk_mq_requeue_work); + INIT_LIST_HEAD(&q->flush_list); INIT_LIST_HEAD(&q->requeue_list); spin_lock_init(&q->requeue_lock); @@ -4608,9 +4617,6 @@ static bool blk_mq_elv_switch_none(struct list_head *head, { struct blk_mq_qe_pair *qe; - if (!q->elevator) - return true; - qe = kmalloc(sizeof(*qe), GFP_NOIO | __GFP_NOWARN | __GFP_NORETRY); if (!qe) return false; @@ -4618,6 +4624,12 @@ static bool blk_mq_elv_switch_none(struct list_head *head, /* q->elevator needs protection from ->sysfs_lock */ mutex_lock(&q->sysfs_lock); + /* the check has to be done with holding sysfs_lock */ + if (!q->elevator) { + kfree(qe); + goto unlock; + } + INIT_LIST_HEAD(&qe->node); qe->q = q; qe->type = q->elevator->type; @@ -4625,6 +4637,7 @@ static bool blk_mq_elv_switch_none(struct list_head *head, __elevator_get(qe->type); list_add(&qe->node, head); elevator_disable(q); +unlock: mutex_unlock(&q->sysfs_lock); return true; @@ -4740,10 +4753,9 @@ void blk_mq_update_nr_hw_queues(struct blk_mq_tag_set *set, int nr_hw_queues) } EXPORT_SYMBOL_GPL(blk_mq_update_nr_hw_queues); -int blk_mq_poll(struct request_queue *q, blk_qc_t cookie, struct io_comp_batch *iob, - unsigned int flags) +static int blk_hctx_poll(struct request_queue *q, struct blk_mq_hw_ctx *hctx, + struct io_comp_batch *iob, unsigned int flags) { - struct blk_mq_hw_ctx *hctx = blk_qc_to_hctx(q, cookie); long state = get_current_state(); int ret; @@ -4768,6 +4780,32 @@ int blk_mq_poll(struct request_queue *q, blk_qc_t cookie, struct io_comp_batch * return 0; } +int blk_mq_poll(struct request_queue *q, blk_qc_t cookie, + struct io_comp_batch *iob, unsigned int flags) +{ + struct blk_mq_hw_ctx *hctx = xa_load(&q->hctx_table, cookie); + + return blk_hctx_poll(q, hctx, iob, flags); +} + +int blk_rq_poll(struct request *rq, struct io_comp_batch *iob, + unsigned int poll_flags) +{ + struct request_queue *q = rq->q; + int ret; + + if (!blk_rq_is_poll(rq)) + return 0; + if (!percpu_ref_tryget(&q->q_usage_counter)) + return 0; + + ret = blk_hctx_poll(q, rq->mq_hctx, iob, poll_flags); + blk_queue_exit(q); + + return ret; +} +EXPORT_SYMBOL_GPL(blk_rq_poll); + unsigned int blk_mq_rq_cpu(struct request *rq) { return rq->mq_ctx->cpu; diff --git a/block/blk-mq.h b/block/blk-mq.h index e876584d3516340920ab57ba98783de6f431c1cd..1743857e0b01d9c94406d74aa923433d86852dd5 100644 --- a/block/blk-mq.h +++ b/block/blk-mq.h @@ -47,7 +47,6 @@ int blk_mq_update_nr_requests(struct request_queue *q, unsigned int nr); void blk_mq_wake_waiters(struct request_queue *q); bool blk_mq_dispatch_rq_list(struct blk_mq_hw_ctx *hctx, struct list_head *, unsigned int); -void blk_mq_add_to_requeue_list(struct request *rq, blk_insert_t insert_flags); void blk_mq_flush_busy_ctxs(struct blk_mq_hw_ctx *hctx, struct list_head *list); struct request *blk_mq_dequeue_from_ctx(struct blk_mq_hw_ctx *hctx, struct blk_mq_ctx *start); @@ -64,10 +63,6 @@ struct blk_mq_tags *blk_mq_alloc_map_and_rqs(struct blk_mq_tag_set *set, void blk_mq_free_map_and_rqs(struct blk_mq_tag_set *set, struct blk_mq_tags *tags, unsigned int hctx_idx); -/* - * Internal helpers for request insertion into sw queues - */ -void blk_mq_request_bypass_insert(struct request *rq, blk_insert_t flags); /* * CPU -> queue mappings @@ -226,9 +221,9 @@ static inline bool blk_mq_is_shared_tags(unsigned int flags) static inline struct blk_mq_tags *blk_mq_tags_from_data(struct blk_mq_alloc_data *data) { - if (!(data->rq_flags & RQF_ELV)) - return data->hctx->tags; - return data->hctx->sched_tags; + if (data->rq_flags & RQF_SCHED_TAGS) + return data->hctx->sched_tags; + return data->hctx->tags; } static inline bool blk_mq_hctx_stopped(struct blk_mq_hw_ctx *hctx) @@ -417,8 +412,7 @@ static inline bool hctx_may_queue(struct blk_mq_hw_ctx *hctx, return true; } - users = atomic_read(&hctx->tags->active_queues); - + users = READ_ONCE(hctx->tags->active_queues); if (!users) return true; diff --git a/block/blk-rq-qos.c b/block/blk-rq-qos.c index d8cc820a365e3a51331e359345daabcaf499ef79..167be74df4eeca66c175a1e77f2a274cc6602ba8 100644 --- a/block/blk-rq-qos.c +++ b/block/blk-rq-qos.c @@ -288,11 +288,13 @@ void rq_qos_wait(struct rq_wait *rqw, void *private_data, void rq_qos_exit(struct request_queue *q) { + mutex_lock(&q->rq_qos_mutex); while (q->rq_qos) { struct rq_qos *rqos = q->rq_qos; q->rq_qos = rqos->next; rqos->ops->exit(rqos); } + mutex_unlock(&q->rq_qos_mutex); } int rq_qos_add(struct rq_qos *rqos, struct gendisk *disk, enum rq_qos_id id, @@ -300,6 +302,8 @@ int rq_qos_add(struct rq_qos *rqos, struct gendisk *disk, enum rq_qos_id id, { struct request_queue *q = disk->queue; + lockdep_assert_held(&q->rq_qos_mutex); + rqos->disk = disk; rqos->id = id; rqos->ops = ops; @@ -307,18 +311,13 @@ int rq_qos_add(struct rq_qos *rqos, struct gendisk *disk, enum rq_qos_id id, /* * No IO can be in-flight when adding rqos, so freeze queue, which * is fine since we only support rq_qos for blk-mq queue. - * - * Reuse ->queue_lock for protecting against other concurrent - * rq_qos adding/deleting */ blk_mq_freeze_queue(q); - spin_lock_irq(&q->queue_lock); if (rq_qos_id(q, rqos->id)) goto ebusy; rqos->next = q->rq_qos; q->rq_qos = rqos; - spin_unlock_irq(&q->queue_lock); blk_mq_unfreeze_queue(q); @@ -330,7 +329,6 @@ int rq_qos_add(struct rq_qos *rqos, struct gendisk *disk, enum rq_qos_id id, return 0; ebusy: - spin_unlock_irq(&q->queue_lock); blk_mq_unfreeze_queue(q); return -EBUSY; } @@ -340,21 +338,15 @@ void rq_qos_del(struct rq_qos *rqos) struct request_queue *q = rqos->disk->queue; struct rq_qos **cur; - /* - * See comment in rq_qos_add() about freezing queue & using - * ->queue_lock. - */ - blk_mq_freeze_queue(q); + lockdep_assert_held(&q->rq_qos_mutex); - spin_lock_irq(&q->queue_lock); + blk_mq_freeze_queue(q); for (cur = &q->rq_qos; *cur; cur = &(*cur)->next) { if (*cur == rqos) { *cur = rqos->next; break; } } - spin_unlock_irq(&q->queue_lock); - blk_mq_unfreeze_queue(q); mutex_lock(&q->debugfs_mutex); diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c index a642085838531fc9e980179c51d4c6cedb57875d..afc797fb0dfc4883b6335c69e4cb6949dcc46ceb 100644 --- a/block/blk-sysfs.c +++ b/block/blk-sysfs.c @@ -47,19 +47,6 @@ queue_var_store(unsigned long *var, const char *page, size_t count) return count; } -static ssize_t queue_var_store64(s64 *var, const char *page) -{ - int err; - s64 v; - - err = kstrtos64(page, 10, &v); - if (err < 0) - return err; - - *var = v; - return 0; -} - static ssize_t queue_requests_show(struct request_queue *q, char *page) { return queue_var_show(q->nr_requests, page); @@ -451,61 +438,6 @@ static ssize_t queue_io_timeout_store(struct request_queue *q, const char *page, return count; } -static ssize_t queue_wb_lat_show(struct request_queue *q, char *page) -{ - if (!wbt_rq_qos(q)) - return -EINVAL; - - if (wbt_disabled(q)) - return sprintf(page, "0\n"); - - return sprintf(page, "%llu\n", div_u64(wbt_get_min_lat(q), 1000)); -} - -static ssize_t queue_wb_lat_store(struct request_queue *q, const char *page, - size_t count) -{ - struct rq_qos *rqos; - ssize_t ret; - s64 val; - - ret = queue_var_store64(&val, page); - if (ret < 0) - return ret; - if (val < -1) - return -EINVAL; - - rqos = wbt_rq_qos(q); - if (!rqos) { - ret = wbt_init(q->disk); - if (ret) - return ret; - } - - if (val == -1) - val = wbt_default_latency_nsec(q); - else if (val >= 0) - val *= 1000ULL; - - if (wbt_get_min_lat(q) == val) - return count; - - /* - * Ensure that the queue is idled, in case the latency update - * ends up either enabling or disabling wbt completely. We can't - * have IO inflight if that happens. - */ - blk_mq_freeze_queue(q); - blk_mq_quiesce_queue(q); - - wbt_set_min_lat(q, val); - - blk_mq_unquiesce_queue(q); - blk_mq_unfreeze_queue(q); - - return count; -} - static ssize_t queue_wc_show(struct request_queue *q, char *page) { if (test_bit(QUEUE_FLAG_WC, &q->queue_flags)) @@ -598,7 +530,6 @@ QUEUE_RW_ENTRY(queue_wc, "write_cache"); QUEUE_RO_ENTRY(queue_fua, "fua"); QUEUE_RO_ENTRY(queue_dax, "dax"); QUEUE_RW_ENTRY(queue_io_timeout, "io_timeout"); -QUEUE_RW_ENTRY(queue_wb_lat, "wbt_lat_usec"); QUEUE_RO_ENTRY(queue_virt_boundary_mask, "virt_boundary_mask"); QUEUE_RO_ENTRY(queue_dma_alignment, "dma_alignment"); @@ -617,8 +548,79 @@ QUEUE_RW_ENTRY(queue_iostats, "iostats"); QUEUE_RW_ENTRY(queue_random, "add_random"); QUEUE_RW_ENTRY(queue_stable_writes, "stable_writes"); +#ifdef CONFIG_BLK_WBT +static ssize_t queue_var_store64(s64 *var, const char *page) +{ + int err; + s64 v; + + err = kstrtos64(page, 10, &v); + if (err < 0) + return err; + + *var = v; + return 0; +} + +static ssize_t queue_wb_lat_show(struct request_queue *q, char *page) +{ + if (!wbt_rq_qos(q)) + return -EINVAL; + + if (wbt_disabled(q)) + return sprintf(page, "0\n"); + + return sprintf(page, "%llu\n", div_u64(wbt_get_min_lat(q), 1000)); +} + +static ssize_t queue_wb_lat_store(struct request_queue *q, const char *page, + size_t count) +{ + struct rq_qos *rqos; + ssize_t ret; + s64 val; + + ret = queue_var_store64(&val, page); + if (ret < 0) + return ret; + if (val < -1) + return -EINVAL; + + rqos = wbt_rq_qos(q); + if (!rqos) { + ret = wbt_init(q->disk); + if (ret) + return ret; + } + + if (val == -1) + val = wbt_default_latency_nsec(q); + else if (val >= 0) + val *= 1000ULL; + + if (wbt_get_min_lat(q) == val) + return count; + + /* + * Ensure that the queue is idled, in case the latency update + * ends up either enabling or disabling wbt completely. We can't + * have IO inflight if that happens. + */ + blk_mq_freeze_queue(q); + blk_mq_quiesce_queue(q); + + wbt_set_min_lat(q, val); + + blk_mq_unquiesce_queue(q); + blk_mq_unfreeze_queue(q); + + return count; +} + +QUEUE_RW_ENTRY(queue_wb_lat, "wbt_lat_usec"); +#endif + static struct attribute *queue_attrs[] = { - &queue_requests_entry.attr, &queue_ra_entry.attr, &queue_max_hw_sectors_entry.attr, &queue_max_sectors_entry.attr, @@ -626,7 +628,6 @@ static struct attribute *queue_attrs[] = { &queue_max_discard_segments_entry.attr, &queue_max_integrity_segments_entry.attr, &queue_max_segment_size_entry.attr, - &elv_iosched_entry.attr, &queue_hw_sector_size_entry.attr, &queue_logical_block_size_entry.attr, &queue_physical_block_size_entry.attr, @@ -647,7 +648,6 @@ static struct attribute *queue_attrs[] = { &queue_max_open_zones_entry.attr, &queue_max_active_zones_entry.attr, &queue_nomerges_entry.attr, - &queue_rq_affinity_entry.attr, &queue_iostats_entry.attr, &queue_stable_writes_entry.attr, &queue_random_entry.attr, @@ -655,9 +655,7 @@ static struct attribute *queue_attrs[] = { &queue_wc_entry.attr, &queue_fua_entry.attr, &queue_dax_entry.attr, - &queue_wb_lat_entry.attr, &queue_poll_delay_entry.attr, - &queue_io_timeout_entry.attr, #ifdef CONFIG_BLK_DEV_THROTTLING_LOW &blk_throtl_sample_time_entry.attr, #endif @@ -666,16 +664,23 @@ static struct attribute *queue_attrs[] = { NULL, }; +static struct attribute *blk_mq_queue_attrs[] = { + &queue_requests_entry.attr, + &elv_iosched_entry.attr, + &queue_rq_affinity_entry.attr, + &queue_io_timeout_entry.attr, +#ifdef CONFIG_BLK_WBT + &queue_wb_lat_entry.attr, +#endif + NULL, +}; + static umode_t queue_attr_visible(struct kobject *kobj, struct attribute *attr, int n) { struct gendisk *disk = container_of(kobj, struct gendisk, queue_kobj); struct request_queue *q = disk->queue; - if (attr == &queue_io_timeout_entry.attr && - (!q->mq_ops || !q->mq_ops->timeout)) - return 0; - if ((attr == &queue_max_open_zones_entry.attr || attr == &queue_max_active_zones_entry.attr) && !blk_queue_is_zoned(q)) @@ -684,11 +689,30 @@ static umode_t queue_attr_visible(struct kobject *kobj, struct attribute *attr, return attr->mode; } +static umode_t blk_mq_queue_attr_visible(struct kobject *kobj, + struct attribute *attr, int n) +{ + struct gendisk *disk = container_of(kobj, struct gendisk, queue_kobj); + struct request_queue *q = disk->queue; + + if (!queue_is_mq(q)) + return 0; + + if (attr == &queue_io_timeout_entry.attr && !q->mq_ops->timeout) + return 0; + + return attr->mode; +} + static struct attribute_group queue_attr_group = { .attrs = queue_attrs, .is_visible = queue_attr_visible, }; +static struct attribute_group blk_mq_queue_attr_group = { + .attrs = blk_mq_queue_attrs, + .is_visible = blk_mq_queue_attr_visible, +}; #define to_queue(atr) container_of((atr), struct queue_sysfs_entry, attr) @@ -733,6 +757,7 @@ static const struct sysfs_ops queue_sysfs_ops = { static const struct attribute_group *blk_queue_attr_groups[] = { &queue_attr_group, + &blk_mq_queue_attr_group, NULL }; diff --git a/block/blk-throttle.c b/block/blk-throttle.c index 9d010d867fbf4ee32d3c4aedb1962afab73304c2..7397ff199d6695e40f4e181f91982d4ec8870252 100644 --- a/block/blk-throttle.c +++ b/block/blk-throttle.c @@ -2178,12 +2178,6 @@ bool __blk_throtl_bio(struct bio *bio) rcu_read_lock(); - if (!cgroup_subsys_on_dfl(io_cgrp_subsys)) { - blkg_rwstat_add(&tg->stat_bytes, bio->bi_opf, - bio->bi_iter.bi_size); - blkg_rwstat_add(&tg->stat_ios, bio->bi_opf, 1); - } - spin_lock_irq(&q->queue_lock); throtl_update_latency_buckets(td); diff --git a/block/blk-throttle.h b/block/blk-throttle.h index ef4b7a4de987dddfd0dc368cd36893b899d8c3f2..d1ccbfe9f797882c05256a5780fa151093174c44 100644 --- a/block/blk-throttle.h +++ b/block/blk-throttle.h @@ -185,6 +185,15 @@ static inline bool blk_should_throtl(struct bio *bio) struct throtl_grp *tg = blkg_to_tg(bio->bi_blkg); int rw = bio_data_dir(bio); + if (!cgroup_subsys_on_dfl(io_cgrp_subsys)) { + if (!bio_flagged(bio, BIO_CGROUP_ACCT)) { + bio_set_flag(bio, BIO_CGROUP_ACCT); + blkg_rwstat_add(&tg->stat_bytes, bio->bi_opf, + bio->bi_iter.bi_size); + } + blkg_rwstat_add(&tg->stat_ios, bio->bi_opf, 1); + } + /* iops limit is always counted */ if (tg->has_rules_iops[rw]) return true; diff --git a/block/blk-wbt.c b/block/blk-wbt.c index 9ec2a2f1eda3882b8d174b90c2e5f14ae5d07679..0bb613139becbb5d783f1d2b84112f2e4b626477 100644 --- a/block/blk-wbt.c +++ b/block/blk-wbt.c @@ -146,7 +146,7 @@ enum { static inline bool rwb_enabled(struct rq_wb *rwb) { return rwb && rwb->enable_state != WBT_STATE_OFF_DEFAULT && - rwb->wb_normal != 0; + rwb->enable_state != WBT_STATE_OFF_MANUAL; } static void wb_timestamp(struct rq_wb *rwb, unsigned long *var) @@ -200,15 +200,6 @@ static void wbt_rqw_done(struct rq_wb *rwb, struct rq_wait *rqw, inflight = atomic_dec_return(&rqw->inflight); - /* - * wbt got disabled with IO in flight. Wake up any potential - * waiters, we don't have to do more than that. - */ - if (unlikely(!rwb_enabled(rwb))) { - rwb_wake_all(rwb); - return; - } - /* * For discards, our limit is always the background. For writes, if * the device does write back caching, drop further down before we @@ -503,8 +494,7 @@ bool wbt_disabled(struct request_queue *q) { struct rq_qos *rqos = wbt_rq_qos(q); - return !rqos || RQWB(rqos)->enable_state == WBT_STATE_OFF_DEFAULT || - RQWB(rqos)->enable_state == WBT_STATE_OFF_MANUAL; + return !rqos || !rwb_enabled(RQWB(rqos)); } u64 wbt_get_min_lat(struct request_queue *q) @@ -545,13 +535,6 @@ static inline unsigned int get_limit(struct rq_wb *rwb, blk_opf_t opf) { unsigned int limit; - /* - * If we got disabled, just return UINT_MAX. This ensures that - * we'll properly inc a new IO, and dec+wakeup at the end. - */ - if (!rwb_enabled(rwb)) - return UINT_MAX; - if ((opf & REQ_OP_MASK) == REQ_OP_DISCARD) return rwb->wb_background; @@ -944,7 +927,9 @@ int wbt_init(struct gendisk *disk) /* * Assign rwb and add the stats callback. */ + mutex_lock(&q->rq_qos_mutex); ret = rq_qos_add(&rwb->rqos, disk, RQ_QOS_WBT, &wbt_rqos_ops); + mutex_unlock(&q->rq_qos_mutex); if (ret) goto err_free; diff --git a/block/blk-wbt.h b/block/blk-wbt.h index ba6cca5849a65518993ae0d3ae1f24538800e0ef..8a029e138f7ace62e8f99222150ccbe6595a99ec 100644 --- a/block/blk-wbt.h +++ b/block/blk-wbt.h @@ -18,10 +18,6 @@ u64 wbt_default_latency_nsec(struct request_queue *); #else -static inline int wbt_init(struct gendisk *disk) -{ - return -EINVAL; -} static inline void wbt_disable_default(struct gendisk *disk) { } @@ -31,21 +27,6 @@ static inline void wbt_enable_default(struct gendisk *disk) static inline void wbt_set_write_cache(struct request_queue *q, bool wc) { } -static inline u64 wbt_get_min_lat(struct request_queue *q) -{ - return 0; -} -static inline void wbt_set_min_lat(struct request_queue *q, u64 val) -{ -} -static inline u64 wbt_default_latency_nsec(struct request_queue *q) -{ - return 0; -} -static inline bool wbt_disabled(struct request_queue *q) -{ - return true; -} #endif /* CONFIG_BLK_WBT */ diff --git a/block/blk-zoned.c b/block/blk-zoned.c index fce9082384d65dfcdcdf49d2d4fe40ec49dc217e..619ee41a51cc8c81b0333f4f95a70e3b3ed7c442 100644 --- a/block/blk-zoned.c +++ b/block/blk-zoned.c @@ -57,16 +57,10 @@ EXPORT_SYMBOL_GPL(blk_zone_cond_str); */ bool blk_req_needs_zone_write_lock(struct request *rq) { - if (blk_rq_is_passthrough(rq)) - return false; - if (!rq->q->disk->seq_zones_wlock) return false; - if (bdev_op_is_zoned_write(rq->q->disk->part0, req_op(rq))) - return blk_rq_zone_is_seq(rq); - - return false; + return blk_rq_is_seq_zoned_write(rq); } EXPORT_SYMBOL_GPL(blk_req_needs_zone_write_lock); @@ -329,8 +323,8 @@ static int blkdev_copy_zone_to_user(struct blk_zone *zone, unsigned int idx, * BLKREPORTZONE ioctl processing. * Called from blkdev_ioctl. */ -int blkdev_report_zones_ioctl(struct block_device *bdev, fmode_t mode, - unsigned int cmd, unsigned long arg) +int blkdev_report_zones_ioctl(struct block_device *bdev, unsigned int cmd, + unsigned long arg) { void __user *argp = (void __user *)arg; struct zone_report_args args; @@ -362,8 +356,8 @@ int blkdev_report_zones_ioctl(struct block_device *bdev, fmode_t mode, return 0; } -static int blkdev_truncate_zone_range(struct block_device *bdev, fmode_t mode, - const struct blk_zone_range *zrange) +static int blkdev_truncate_zone_range(struct block_device *bdev, + blk_mode_t mode, const struct blk_zone_range *zrange) { loff_t start, end; @@ -382,7 +376,7 @@ static int blkdev_truncate_zone_range(struct block_device *bdev, fmode_t mode, * BLKRESETZONE, BLKOPENZONE, BLKCLOSEZONE and BLKFINISHZONE ioctl processing. * Called from blkdev_ioctl. */ -int blkdev_zone_mgmt_ioctl(struct block_device *bdev, fmode_t mode, +int blkdev_zone_mgmt_ioctl(struct block_device *bdev, blk_mode_t mode, unsigned int cmd, unsigned long arg) { void __user *argp = (void __user *)arg; @@ -396,7 +390,7 @@ int blkdev_zone_mgmt_ioctl(struct block_device *bdev, fmode_t mode, if (!bdev_is_zoned(bdev)) return -ENOTTY; - if (!(mode & FMODE_WRITE)) + if (!(mode & BLK_OPEN_WRITE)) return -EBADF; if (copy_from_user(&zrange, argp, sizeof(struct blk_zone_range))) @@ -448,7 +442,6 @@ struct blk_revalidate_zone_args { unsigned long *conv_zones_bitmap; unsigned long *seq_zones_wlock; unsigned int nr_zones; - sector_t zone_sectors; sector_t sector; }; @@ -462,38 +455,34 @@ static int blk_revalidate_zone_cb(struct blk_zone *zone, unsigned int idx, struct gendisk *disk = args->disk; struct request_queue *q = disk->queue; sector_t capacity = get_capacity(disk); + sector_t zone_sectors = q->limits.chunk_sectors; + + /* Check for bad zones and holes in the zone report */ + if (zone->start != args->sector) { + pr_warn("%s: Zone gap at sectors %llu..%llu\n", + disk->disk_name, args->sector, zone->start); + return -ENODEV; + } + + if (zone->start >= capacity || !zone->len) { + pr_warn("%s: Invalid zone start %llu, length %llu\n", + disk->disk_name, zone->start, zone->len); + return -ENODEV; + } /* * All zones must have the same size, with the exception on an eventual * smaller last zone. */ - if (zone->start == 0) { - if (zone->len == 0 || !is_power_of_2(zone->len)) { - pr_warn("%s: Invalid zoned device with non power of two zone size (%llu)\n", - disk->disk_name, zone->len); - return -ENODEV; - } - - args->zone_sectors = zone->len; - args->nr_zones = (capacity + zone->len - 1) >> ilog2(zone->len); - } else if (zone->start + args->zone_sectors < capacity) { - if (zone->len != args->zone_sectors) { + if (zone->start + zone->len < capacity) { + if (zone->len != zone_sectors) { pr_warn("%s: Invalid zoned device with non constant zone size\n", disk->disk_name); return -ENODEV; } - } else { - if (zone->len > args->zone_sectors) { - pr_warn("%s: Invalid zoned device with larger last zone size\n", - disk->disk_name); - return -ENODEV; - } - } - - /* Check for holes in the zone report */ - if (zone->start != args->sector) { - pr_warn("%s: Zone gap at sectors %llu..%llu\n", - disk->disk_name, args->sector, zone->start); + } else if (zone->len > zone_sectors) { + pr_warn("%s: Invalid zoned device with larger last zone size\n", + disk->disk_name); return -ENODEV; } @@ -532,11 +521,13 @@ static int blk_revalidate_zone_cb(struct blk_zone *zone, unsigned int idx, * @disk: Target disk * @update_driver_data: Callback to update driver data on the frozen disk * - * Helper function for low-level device drivers to (re) allocate and initialize - * a disk request queue zone bitmaps. This functions should normally be called - * within the disk ->revalidate method for blk-mq based drivers. For BIO based - * drivers only q->nr_zones needs to be updated so that the sysfs exposed value - * is correct. + * Helper function for low-level device drivers to check and (re) allocate and + * initialize a disk request queue zone bitmaps. This functions should normally + * be called within the disk ->revalidate method for blk-mq based drivers. + * Before calling this function, the device driver must already have set the + * device zone size (chunk_sector limit) and the max zone append limit. + * For BIO based drivers, this function cannot be used. BIO based device drivers + * only need to set disk->nr_zones so that the sysfs exposed value is correct. * If the @update_driver_data callback function is not NULL, the callback is * executed with the device request queue frozen after all zones have been * checked. @@ -545,9 +536,9 @@ int blk_revalidate_disk_zones(struct gendisk *disk, void (*update_driver_data)(struct gendisk *disk)) { struct request_queue *q = disk->queue; - struct blk_revalidate_zone_args args = { - .disk = disk, - }; + sector_t zone_sectors = q->limits.chunk_sectors; + sector_t capacity = get_capacity(disk); + struct blk_revalidate_zone_args args = { }; unsigned int noio_flag; int ret; @@ -556,13 +547,31 @@ int blk_revalidate_disk_zones(struct gendisk *disk, if (WARN_ON_ONCE(!queue_is_mq(q))) return -EIO; - if (!get_capacity(disk)) - return -EIO; + if (!capacity) + return -ENODEV; + + /* + * Checks that the device driver indicated a valid zone size and that + * the max zone append limit is set. + */ + if (!zone_sectors || !is_power_of_2(zone_sectors)) { + pr_warn("%s: Invalid non power of two zone size (%llu)\n", + disk->disk_name, zone_sectors); + return -ENODEV; + } + + if (!q->limits.max_zone_append_sectors) { + pr_warn("%s: Invalid 0 maximum zone append limit\n", + disk->disk_name); + return -ENODEV; + } /* * Ensure that all memory allocations in this context are done as if * GFP_NOIO was specified. */ + args.disk = disk; + args.nr_zones = (capacity + zone_sectors - 1) >> ilog2(zone_sectors); noio_flag = memalloc_noio_save(); ret = disk->fops->report_zones(disk, 0, UINT_MAX, blk_revalidate_zone_cb, &args); @@ -576,7 +585,7 @@ int blk_revalidate_disk_zones(struct gendisk *disk, * If zones where reported, make sure that the entire disk capacity * has been checked. */ - if (ret > 0 && args.sector != get_capacity(disk)) { + if (ret > 0 && args.sector != capacity) { pr_warn("%s: Missing zones from sector %llu\n", disk->disk_name, args.sector); ret = -ENODEV; @@ -589,7 +598,6 @@ int blk_revalidate_disk_zones(struct gendisk *disk, */ blk_mq_freeze_queue(q); if (ret > 0) { - blk_queue_chunk_sectors(q, args.zone_sectors); disk->nr_zones = args.nr_zones; swap(disk->seq_zones_wlock, args.seq_zones_wlock); swap(disk->conv_zones_bitmap, args.conv_zones_bitmap); diff --git a/block/blk.h b/block/blk.h index 45547bcf111938db1fcd7744f8a90641b56c54ad..608c5dcc516b55c992b62f0334bb5fa1abe07c62 100644 --- a/block/blk.h +++ b/block/blk.h @@ -269,7 +269,7 @@ bool blk_bio_list_merge(struct request_queue *q, struct list_head *list, */ #define ELV_ON_HASH(rq) ((rq)->rq_flags & RQF_HASHED) -void blk_insert_flush(struct request *rq); +bool blk_insert_flush(struct request *rq); int elevator_switch(struct request_queue *q, struct elevator_type *new_e); void elevator_disable(struct request_queue *q); @@ -394,10 +394,27 @@ static inline struct bio *blk_queue_bounce(struct bio *bio, #ifdef CONFIG_BLK_DEV_ZONED void disk_free_zone_bitmaps(struct gendisk *disk); void disk_clear_zone_settings(struct gendisk *disk); -#else +int blkdev_report_zones_ioctl(struct block_device *bdev, unsigned int cmd, + unsigned long arg); +int blkdev_zone_mgmt_ioctl(struct block_device *bdev, blk_mode_t mode, + unsigned int cmd, unsigned long arg); +#else /* CONFIG_BLK_DEV_ZONED */ static inline void disk_free_zone_bitmaps(struct gendisk *disk) {} static inline void disk_clear_zone_settings(struct gendisk *disk) {} -#endif +static inline int blkdev_report_zones_ioctl(struct block_device *bdev, + unsigned int cmd, unsigned long arg) +{ + return -ENOTTY; +} +static inline int blkdev_zone_mgmt_ioctl(struct block_device *bdev, + blk_mode_t mode, unsigned int cmd, unsigned long arg) +{ + return -ENOTTY; +} +#endif /* CONFIG_BLK_DEV_ZONED */ + +struct block_device *bdev_alloc(struct gendisk *disk, u8 partno); +void bdev_add(struct block_device *bdev, dev_t dev); int blk_alloc_ext_minor(void); void blk_free_ext_minor(unsigned int minor); @@ -409,7 +426,7 @@ int bdev_add_partition(struct gendisk *disk, int partno, sector_t start, int bdev_del_partition(struct gendisk *disk, int partno); int bdev_resize_partition(struct gendisk *disk, int partno, sector_t start, sector_t length); -void blk_drop_partitions(struct gendisk *disk); +void drop_partition(struct block_device *part); void bdev_set_nr_sectors(struct block_device *bdev, sector_t sectors); @@ -420,9 +437,19 @@ int bio_add_hw_page(struct request_queue *q, struct bio *bio, struct page *page, unsigned int len, unsigned int offset, unsigned int max_sectors, bool *same_page); +/* + * Clean up a page appropriately, where the page may be pinned, may have a + * ref taken on it or neither. + */ +static inline void bio_release_page(struct bio *bio, struct page *page) +{ + if (bio_flagged(bio, BIO_PAGE_PINNED)) + unpin_user_page(page); +} + struct request_queue *blk_alloc_queue(int node_id); -int disk_scan_partitions(struct gendisk *disk, fmode_t mode); +int disk_scan_partitions(struct gendisk *disk, blk_mode_t mode); int disk_alloc_events(struct gendisk *disk); void disk_add_events(struct gendisk *disk); @@ -437,6 +464,9 @@ extern struct device_attribute dev_attr_events_poll_msecs; extern struct attribute_group blk_trace_attr_group; +blk_mode_t file_to_blk_mode(struct file *file); +int truncate_bdev_range(struct block_device *bdev, blk_mode_t mode, + loff_t lstart, loff_t lend); long blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg); long compat_blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg); diff --git a/block/bsg-lib.c b/block/bsg-lib.c index 435c32373cd68ff98a2b0923efcb2dde92148fef..b3acdbdb6e7ea8f62c8d9f76d7ae83a4a35bf0e2 100644 --- a/block/bsg-lib.c +++ b/block/bsg-lib.c @@ -26,7 +26,7 @@ struct bsg_set { }; static int bsg_transport_sg_io_fn(struct request_queue *q, struct sg_io_v4 *hdr, - fmode_t mode, unsigned int timeout) + bool open_for_write, unsigned int timeout) { struct bsg_job *job; struct request *rq; diff --git a/block/bsg.c b/block/bsg.c index 7eca43f33d7ff8f6e2ef8f56908feea5c280768a..72157a59b7881f4e4b975f70db879eef22597e17 100644 --- a/block/bsg.c +++ b/block/bsg.c @@ -36,10 +36,10 @@ static inline struct bsg_device *to_bsg_device(struct inode *inode) } #define BSG_DEFAULT_CMDS 64 -#define BSG_MAX_DEVS 32768 +#define BSG_MAX_DEVS (1 << MINORBITS) static DEFINE_IDA(bsg_minor_ida); -static struct class *bsg_class; +static const struct class bsg_class; static int bsg_major; static unsigned int bsg_timeout(struct bsg_device *bd, struct sg_io_v4 *hdr) @@ -54,7 +54,8 @@ static unsigned int bsg_timeout(struct bsg_device *bd, struct sg_io_v4 *hdr) return max_t(unsigned int, timeout, BLK_MIN_SG_TIMEOUT); } -static int bsg_sg_io(struct bsg_device *bd, fmode_t mode, void __user *uarg) +static int bsg_sg_io(struct bsg_device *bd, bool open_for_write, + void __user *uarg) { struct sg_io_v4 hdr; int ret; @@ -63,7 +64,8 @@ static int bsg_sg_io(struct bsg_device *bd, fmode_t mode, void __user *uarg) return -EFAULT; if (hdr.guard != 'Q') return -EINVAL; - ret = bd->sg_io_fn(bd->queue, &hdr, mode, bsg_timeout(bd, &hdr)); + ret = bd->sg_io_fn(bd->queue, &hdr, open_for_write, + bsg_timeout(bd, &hdr)); if (!ret && copy_to_user(uarg, &hdr, sizeof(hdr))) return -EFAULT; return ret; @@ -146,7 +148,7 @@ static long bsg_ioctl(struct file *file, unsigned int cmd, unsigned long arg) case SG_EMULATED_HOST: return put_user(1, intp); case SG_IO: - return bsg_sg_io(bd, file->f_mode, uarg); + return bsg_sg_io(bd, file->f_mode & FMODE_WRITE, uarg); case SCSI_IOCTL_SEND_COMMAND: pr_warn_ratelimited("%s: calling unsupported SCSI_IOCTL_SEND_COMMAND\n", current->comm); @@ -206,7 +208,7 @@ struct bsg_device *bsg_register_queue(struct request_queue *q, return ERR_PTR(ret); } bd->device.devt = MKDEV(bsg_major, ret); - bd->device.class = bsg_class; + bd->device.class = &bsg_class; bd->device.parent = parent; bd->device.release = bsg_device_release; dev_set_name(&bd->device, "%s", name); @@ -240,15 +242,19 @@ static char *bsg_devnode(const struct device *dev, umode_t *mode) return kasprintf(GFP_KERNEL, "bsg/%s", dev_name(dev)); } +static const struct class bsg_class = { + .name = "bsg", + .devnode = bsg_devnode, +}; + static int __init bsg_init(void) { dev_t devid; int ret; - bsg_class = class_create("bsg"); - if (IS_ERR(bsg_class)) - return PTR_ERR(bsg_class); - bsg_class->devnode = bsg_devnode; + ret = class_register(&bsg_class); + if (ret) + return ret; ret = alloc_chrdev_region(&devid, 0, BSG_MAX_DEVS, "bsg"); if (ret) @@ -260,7 +266,7 @@ static int __init bsg_init(void) return 0; destroy_bsg_class: - class_destroy(bsg_class); + class_unregister(&bsg_class); return ret; } diff --git a/block/disk-events.c b/block/disk-events.c index aee25a7e1ab7de8cc82b3c3774e83489d3a86ff9..0cfac464e6d120e6cde84e0914e34d687996c8f3 100644 --- a/block/disk-events.c +++ b/block/disk-events.c @@ -263,31 +263,31 @@ static unsigned int disk_clear_events(struct gendisk *disk, unsigned int mask) } /** - * bdev_check_media_change - check if a removable media has been changed - * @bdev: block device to check + * disk_check_media_change - check if a removable media has been changed + * @disk: gendisk to check * * Check whether a removable media has been changed, and attempt to free all * dentries and inodes and invalidates all block device page cache entries in * that case. * - * Returns %true if the block device changed, or %false if not. + * Returns %true if the media has changed, or %false if not. */ -bool bdev_check_media_change(struct block_device *bdev) +bool disk_check_media_change(struct gendisk *disk) { unsigned int events; - events = disk_clear_events(bdev->bd_disk, DISK_EVENT_MEDIA_CHANGE | + events = disk_clear_events(disk, DISK_EVENT_MEDIA_CHANGE | DISK_EVENT_EJECT_REQUEST); if (!(events & DISK_EVENT_MEDIA_CHANGE)) return false; - if (__invalidate_device(bdev, true)) + if (__invalidate_device(disk->part0, true)) pr_warn("VFS: busy inodes on changed media %s\n", - bdev->bd_disk->disk_name); - set_bit(GD_NEED_PART_SCAN, &bdev->bd_disk->state); + disk->disk_name); + set_bit(GD_NEED_PART_SCAN, &disk->state); return true; } -EXPORT_SYMBOL(bdev_check_media_change); +EXPORT_SYMBOL(disk_check_media_change); /** * disk_force_media_change - force a media change event @@ -307,6 +307,7 @@ bool disk_force_media_change(struct gendisk *disk, unsigned int events) if (!(events & DISK_EVENT_MEDIA_CHANGE)) return false; + inc_diskseq(disk); if (__invalidate_device(disk->part0, true)) pr_warn("VFS: busy inodes on changed media %s\n", disk->disk_name); diff --git a/block/early-lookup.c b/block/early-lookup.c new file mode 100644 index 0000000000000000000000000000000000000000..3effbd0d35e9fa0eb1f24b1131f3eca2ad4b6656 --- /dev/null +++ b/block/early-lookup.c @@ -0,0 +1,316 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Code for looking up block devices in the early boot code before mounting the + * root file system. + */ +#include +#include + +struct uuidcmp { + const char *uuid; + int len; +}; + +/** + * match_dev_by_uuid - callback for finding a partition using its uuid + * @dev: device passed in by the caller + * @data: opaque pointer to the desired struct uuidcmp to match + * + * Returns 1 if the device matches, and 0 otherwise. + */ +static int __init match_dev_by_uuid(struct device *dev, const void *data) +{ + struct block_device *bdev = dev_to_bdev(dev); + const struct uuidcmp *cmp = data; + + if (!bdev->bd_meta_info || + strncasecmp(cmp->uuid, bdev->bd_meta_info->uuid, cmp->len)) + return 0; + return 1; +} + +/** + * devt_from_partuuid - looks up the dev_t of a partition by its UUID + * @uuid_str: char array containing ascii UUID + * @devt: dev_t result + * + * The function will return the first partition which contains a matching + * UUID value in its partition_meta_info struct. This does not search + * by filesystem UUIDs. + * + * If @uuid_str is followed by a "/PARTNROFF=%d", then the number will be + * extracted and used as an offset from the partition identified by the UUID. + * + * Returns 0 on success or a negative error code on failure. + */ +static int __init devt_from_partuuid(const char *uuid_str, dev_t *devt) +{ + struct uuidcmp cmp; + struct device *dev = NULL; + int offset = 0; + char *slash; + + cmp.uuid = uuid_str; + + slash = strchr(uuid_str, '/'); + /* Check for optional partition number offset attributes. */ + if (slash) { + char c = 0; + + /* Explicitly fail on poor PARTUUID syntax. */ + if (sscanf(slash + 1, "PARTNROFF=%d%c", &offset, &c) != 1) + goto out_invalid; + cmp.len = slash - uuid_str; + } else { + cmp.len = strlen(uuid_str); + } + + if (!cmp.len) + goto out_invalid; + + dev = class_find_device(&block_class, NULL, &cmp, &match_dev_by_uuid); + if (!dev) + return -ENODEV; + + if (offset) { + /* + * Attempt to find the requested partition by adding an offset + * to the partition number found by UUID. + */ + *devt = part_devt(dev_to_disk(dev), + dev_to_bdev(dev)->bd_partno + offset); + } else { + *devt = dev->devt; + } + + put_device(dev); + return 0; + +out_invalid: + pr_err("VFS: PARTUUID= is invalid.\n" + "Expected PARTUUID=[/PARTNROFF=%%d]\n"); + return -EINVAL; +} + +/** + * match_dev_by_label - callback for finding a partition using its label + * @dev: device passed in by the caller + * @data: opaque pointer to the label to match + * + * Returns 1 if the device matches, and 0 otherwise. + */ +static int __init match_dev_by_label(struct device *dev, const void *data) +{ + struct block_device *bdev = dev_to_bdev(dev); + const char *label = data; + + if (!bdev->bd_meta_info || strcmp(label, bdev->bd_meta_info->volname)) + return 0; + return 1; +} + +static int __init devt_from_partlabel(const char *label, dev_t *devt) +{ + struct device *dev; + + dev = class_find_device(&block_class, NULL, label, &match_dev_by_label); + if (!dev) + return -ENODEV; + *devt = dev->devt; + put_device(dev); + return 0; +} + +static dev_t __init blk_lookup_devt(const char *name, int partno) +{ + dev_t devt = MKDEV(0, 0); + struct class_dev_iter iter; + struct device *dev; + + class_dev_iter_init(&iter, &block_class, NULL, &disk_type); + while ((dev = class_dev_iter_next(&iter))) { + struct gendisk *disk = dev_to_disk(dev); + + if (strcmp(dev_name(dev), name)) + continue; + + if (partno < disk->minors) { + /* We need to return the right devno, even + * if the partition doesn't exist yet. + */ + devt = MKDEV(MAJOR(dev->devt), + MINOR(dev->devt) + partno); + } else { + devt = part_devt(disk, partno); + if (devt) + break; + } + } + class_dev_iter_exit(&iter); + return devt; +} + +static int __init devt_from_devname(const char *name, dev_t *devt) +{ + int part; + char s[32]; + char *p; + + if (strlen(name) > 31) + return -EINVAL; + strcpy(s, name); + for (p = s; *p; p++) { + if (*p == '/') + *p = '!'; + } + + *devt = blk_lookup_devt(s, 0); + if (*devt) + return 0; + + /* + * Try non-existent, but valid partition, which may only exist after + * opening the device, like partitioned md devices. + */ + while (p > s && isdigit(p[-1])) + p--; + if (p == s || !*p || *p == '0') + return -ENODEV; + + /* try disk name without */ + part = simple_strtoul(p, NULL, 10); + *p = '\0'; + *devt = blk_lookup_devt(s, part); + if (*devt) + return 0; + + /* try disk name without p */ + if (p < s + 2 || !isdigit(p[-2]) || p[-1] != 'p') + return -ENODEV; + p[-1] = '\0'; + *devt = blk_lookup_devt(s, part); + if (*devt) + return 0; + return -ENODEV; +} + +static int __init devt_from_devnum(const char *name, dev_t *devt) +{ + unsigned maj, min, offset; + char *p, dummy; + + if (sscanf(name, "%u:%u%c", &maj, &min, &dummy) == 2 || + sscanf(name, "%u:%u:%u:%c", &maj, &min, &offset, &dummy) == 3) { + *devt = MKDEV(maj, min); + if (maj != MAJOR(*devt) || min != MINOR(*devt)) + return -EINVAL; + } else { + *devt = new_decode_dev(simple_strtoul(name, &p, 16)); + if (*p) + return -EINVAL; + } + + return 0; +} + +/* + * Convert a name into device number. We accept the following variants: + * + * 1) device number in hexadecimal represents itself + * no leading 0x, for example b302. + * 3) /dev/ represents the device number of disk + * 4) /dev/ represents the device number + * of partition - device number of disk plus the partition number + * 5) /dev/p - same as the above, that form is + * used when disk name of partitioned disk ends on a digit. + * 6) PARTUUID=00112233-4455-6677-8899-AABBCCDDEEFF representing the + * unique id of a partition if the partition table provides it. + * The UUID may be either an EFI/GPT UUID, or refer to an MSDOS + * partition using the format SSSSSSSS-PP, where SSSSSSSS is a zero- + * filled hex representation of the 32-bit "NT disk signature", and PP + * is a zero-filled hex representation of the 1-based partition number. + * 7) PARTUUID=/PARTNROFF= to select a partition in relation to + * a partition with a known unique id. + * 8) : major and minor number of the device separated by + * a colon. + * 9) PARTLABEL= with name being the GPT partition label. + * MSDOS partitions do not support labels! + * + * If name doesn't have fall into the categories above, we return (0,0). + * block_class is used to check if something is a disk name. If the disk + * name contains slashes, the device name has them replaced with + * bangs. + */ +int __init early_lookup_bdev(const char *name, dev_t *devt) +{ + if (strncmp(name, "PARTUUID=", 9) == 0) + return devt_from_partuuid(name + 9, devt); + if (strncmp(name, "PARTLABEL=", 10) == 0) + return devt_from_partlabel(name + 10, devt); + if (strncmp(name, "/dev/", 5) == 0) + return devt_from_devname(name + 5, devt); + return devt_from_devnum(name, devt); +} + +static char __init *bdevt_str(dev_t devt, char *buf) +{ + if (MAJOR(devt) <= 0xff && MINOR(devt) <= 0xff) { + char tbuf[BDEVT_SIZE]; + snprintf(tbuf, BDEVT_SIZE, "%02x%02x", MAJOR(devt), MINOR(devt)); + snprintf(buf, BDEVT_SIZE, "%-9s", tbuf); + } else + snprintf(buf, BDEVT_SIZE, "%03x:%05x", MAJOR(devt), MINOR(devt)); + + return buf; +} + +/* + * print a full list of all partitions - intended for places where the root + * filesystem can't be mounted and thus to give the victim some idea of what + * went wrong + */ +void __init printk_all_partitions(void) +{ + struct class_dev_iter iter; + struct device *dev; + + class_dev_iter_init(&iter, &block_class, NULL, &disk_type); + while ((dev = class_dev_iter_next(&iter))) { + struct gendisk *disk = dev_to_disk(dev); + struct block_device *part; + char devt_buf[BDEVT_SIZE]; + unsigned long idx; + + /* + * Don't show empty devices or things that have been + * suppressed + */ + if (get_capacity(disk) == 0 || (disk->flags & GENHD_FL_HIDDEN)) + continue; + + /* + * Note, unlike /proc/partitions, I am showing the numbers in + * hex - the same format as the root= option takes. + */ + rcu_read_lock(); + xa_for_each(&disk->part_tbl, idx, part) { + if (!bdev_nr_sectors(part)) + continue; + printk("%s%s %10llu %pg %s", + bdev_is_partition(part) ? " " : "", + bdevt_str(part->bd_dev, devt_buf), + bdev_nr_sectors(part) >> 1, part, + part->bd_meta_info ? + part->bd_meta_info->uuid : ""); + if (bdev_is_partition(part)) + printk("\n"); + else if (dev->parent && dev->parent->driver) + printk(" driver: %s\n", + dev->parent->driver->name); + else + printk(" (driver?)\n"); + } + rcu_read_unlock(); + } + class_dev_iter_exit(&iter); +} diff --git a/block/elevator.c b/block/elevator.c index 24909069f872889506ce2b77313c5f8fd46b1c66..8400e303fbcbd6d4e0e4371aa990e021bedb24a6 100644 --- a/block/elevator.c +++ b/block/elevator.c @@ -751,7 +751,7 @@ ssize_t elv_iosched_store(struct request_queue *q, const char *buf, if (!elv_support_iosched(q)) return count; - strlcpy(elevator_name, buf, sizeof(elevator_name)); + strscpy(elevator_name, buf, sizeof(elevator_name)); ret = elevator_change(q, strstrip(elevator_name)); if (!ret) return count; diff --git a/block/fops.c b/block/fops.c index 58d0aebc7313a838d4d895fd73f7c383290d75da..a286bf3325c5d84bf8d0e388f560f584ec57283c 100644 --- a/block/fops.c +++ b/block/fops.c @@ -54,7 +54,7 @@ static bool blkdev_dio_unaligned(struct block_device *bdev, loff_t pos, static ssize_t __blkdev_direct_IO_simple(struct kiocb *iocb, struct iov_iter *iter, unsigned int nr_pages) { - struct block_device *bdev = iocb->ki_filp->private_data; + struct block_device *bdev = I_BDEV(iocb->ki_filp->f_mapping->host); struct bio_vec inline_vecs[DIO_INLINE_BIO_VECS], *vecs; loff_t pos = iocb->ki_pos; bool should_dirty = false; @@ -170,7 +170,7 @@ static void blkdev_bio_end_io(struct bio *bio) static ssize_t __blkdev_direct_IO(struct kiocb *iocb, struct iov_iter *iter, unsigned int nr_pages) { - struct block_device *bdev = iocb->ki_filp->private_data; + struct block_device *bdev = I_BDEV(iocb->ki_filp->f_mapping->host); struct blk_plug plug; struct blkdev_dio *dio; struct bio *bio; @@ -310,7 +310,7 @@ static ssize_t __blkdev_direct_IO_async(struct kiocb *iocb, struct iov_iter *iter, unsigned int nr_pages) { - struct block_device *bdev = iocb->ki_filp->private_data; + struct block_device *bdev = I_BDEV(iocb->ki_filp->f_mapping->host); bool is_read = iov_iter_rw(iter) == READ; blk_opf_t opf = is_read ? REQ_OP_READ : dio_bio_write_op(iocb); struct blkdev_dio *dio; @@ -451,7 +451,7 @@ static loff_t blkdev_llseek(struct file *file, loff_t offset, int whence) static int blkdev_fsync(struct file *filp, loff_t start, loff_t end, int datasync) { - struct block_device *bdev = filp->private_data; + struct block_device *bdev = I_BDEV(filp->f_mapping->host); int error; error = file_write_and_wait_range(filp, start, end); @@ -470,6 +470,30 @@ static int blkdev_fsync(struct file *filp, loff_t start, loff_t end, return error; } +blk_mode_t file_to_blk_mode(struct file *file) +{ + blk_mode_t mode = 0; + + if (file->f_mode & FMODE_READ) + mode |= BLK_OPEN_READ; + if (file->f_mode & FMODE_WRITE) + mode |= BLK_OPEN_WRITE; + if (file->private_data) + mode |= BLK_OPEN_EXCL; + if (file->f_flags & O_NDELAY) + mode |= BLK_OPEN_NDELAY; + + /* + * If all bits in O_ACCMODE set (aka O_RDWR | O_WRONLY), the floppy + * driver has historically allowed ioctls as if the file was opened for + * writing, but does not allow and actual reads or writes. + */ + if ((file->f_flags & O_ACCMODE) == (O_RDWR | O_WRONLY)) + mode |= BLK_OPEN_WRITE_IOCTL; + + return mode; +} + static int blkdev_open(struct inode *inode, struct file *filp) { struct block_device *bdev; @@ -481,30 +505,31 @@ static int blkdev_open(struct inode *inode, struct file *filp) * during an unstable branch. */ filp->f_flags |= O_LARGEFILE; - filp->f_mode |= FMODE_NOWAIT | FMODE_BUF_RASYNC; + filp->f_mode |= FMODE_BUF_RASYNC; - if (filp->f_flags & O_NDELAY) - filp->f_mode |= FMODE_NDELAY; + /* + * Use the file private data to store the holder for exclusive openes. + * file_to_blk_mode relies on it being present to set BLK_OPEN_EXCL. + */ if (filp->f_flags & O_EXCL) - filp->f_mode |= FMODE_EXCL; - if ((filp->f_flags & O_ACCMODE) == 3) - filp->f_mode |= FMODE_WRITE_IOCTL; + filp->private_data = filp; - bdev = blkdev_get_by_dev(inode->i_rdev, filp->f_mode, filp); + bdev = blkdev_get_by_dev(inode->i_rdev, file_to_blk_mode(filp), + filp->private_data, NULL); if (IS_ERR(bdev)) return PTR_ERR(bdev); - filp->private_data = bdev; + if (bdev_nowait(bdev)) + filp->f_mode |= FMODE_NOWAIT; + filp->f_mapping = bdev->bd_inode->i_mapping; filp->f_wb_err = filemap_sample_wb_err(filp->f_mapping); return 0; } -static int blkdev_close(struct inode *inode, struct file *filp) +static int blkdev_release(struct inode *inode, struct file *filp) { - struct block_device *bdev = filp->private_data; - - blkdev_put(bdev, filp->f_mode); + blkdev_put(I_BDEV(filp->f_mapping->host), filp->private_data); return 0; } @@ -517,10 +542,9 @@ static int blkdev_close(struct inode *inode, struct file *filp) */ static ssize_t blkdev_write_iter(struct kiocb *iocb, struct iov_iter *from) { - struct block_device *bdev = iocb->ki_filp->private_data; + struct block_device *bdev = I_BDEV(iocb->ki_filp->f_mapping->host); struct inode *bd_inode = bdev->bd_inode; loff_t size = bdev_nr_bytes(bdev); - struct blk_plug plug; size_t shorted = 0; ssize_t ret; @@ -545,18 +569,16 @@ static ssize_t blkdev_write_iter(struct kiocb *iocb, struct iov_iter *from) iov_iter_truncate(from, size); } - blk_start_plug(&plug); ret = __generic_file_write_iter(iocb, from); if (ret > 0) ret = generic_write_sync(iocb, ret); iov_iter_reexpand(from, iov_iter_count(from) + shorted); - blk_finish_plug(&plug); return ret; } static ssize_t blkdev_read_iter(struct kiocb *iocb, struct iov_iter *to) { - struct block_device *bdev = iocb->ki_filp->private_data; + struct block_device *bdev = I_BDEV(iocb->ki_filp->f_mapping->host); loff_t size = bdev_nr_bytes(bdev); loff_t pos = iocb->ki_pos; size_t shorted = 0; @@ -576,21 +598,9 @@ static ssize_t blkdev_read_iter(struct kiocb *iocb, struct iov_iter *to) goto reexpand; /* skip atime */ if (iocb->ki_flags & IOCB_DIRECT) { - struct address_space *mapping = iocb->ki_filp->f_mapping; - - if (iocb->ki_flags & IOCB_NOWAIT) { - if (filemap_range_needs_writeback(mapping, pos, - pos + count - 1)) { - ret = -EAGAIN; - goto reexpand; - } - } else { - ret = filemap_write_and_wait_range(mapping, pos, - pos + count - 1); - if (ret < 0) - goto reexpand; - } - + ret = kiocb_write_and_wait(iocb, count); + if (ret < 0) + goto reexpand; file_accessed(iocb->ki_filp); ret = blkdev_direct_IO(iocb, to); @@ -649,7 +659,7 @@ static long blkdev_fallocate(struct file *file, int mode, loff_t start, filemap_invalidate_lock(inode->i_mapping); /* Invalidate the page cache, including dirty pages. */ - error = truncate_bdev_range(bdev, file->f_mode, start, end); + error = truncate_bdev_range(bdev, file_to_blk_mode(file), start, end); if (error) goto fail; @@ -690,7 +700,7 @@ static int blkdev_mmap(struct file *file, struct vm_area_struct *vma) const struct file_operations def_blk_fops = { .open = blkdev_open, - .release = blkdev_close, + .release = blkdev_release, .llseek = blkdev_llseek, .read_iter = blkdev_read_iter, .write_iter = blkdev_write_iter, @@ -701,7 +711,7 @@ const struct file_operations def_blk_fops = { #ifdef CONFIG_COMPAT .compat_ioctl = compat_blkdev_ioctl, #endif - .splice_read = generic_file_splice_read, + .splice_read = filemap_splice_read, .splice_write = iter_file_splice_write, .fallocate = blkdev_fallocate, }; diff --git a/block/genhd.c b/block/genhd.c index 1cb489b927d50ab06a84a4bfd6913ca8ba7318d4..3d287b32d50dfdb455c89b32ed8664b17e120898 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -25,8 +25,9 @@ #include #include #include -#include "blk-throttle.h" +#include +#include "blk-throttle.h" #include "blk.h" #include "blk-mq-sched.h" #include "blk-rq-qos.h" @@ -253,7 +254,7 @@ int __register_blkdev(unsigned int major, const char *name, #ifdef CONFIG_BLOCK_LEGACY_AUTOLOAD p->probe = probe; #endif - strlcpy(p->name, name, sizeof(p->name)); + strscpy(p->name, name, sizeof(p->name)); p->next = NULL; index = major_to_index(major); @@ -318,18 +319,6 @@ void blk_free_ext_minor(unsigned int minor) ida_free(&ext_devt_ida, minor); } -static char *bdevt_str(dev_t devt, char *buf) -{ - if (MAJOR(devt) <= 0xff && MINOR(devt) <= 0xff) { - char tbuf[BDEVT_SIZE]; - snprintf(tbuf, BDEVT_SIZE, "%02x%02x", MAJOR(devt), MINOR(devt)); - snprintf(buf, BDEVT_SIZE, "%-9s", tbuf); - } else - snprintf(buf, BDEVT_SIZE, "%03x:%05x", MAJOR(devt), MINOR(devt)); - - return buf; -} - void disk_uevent(struct gendisk *disk, enum kobject_action action) { struct block_device *part; @@ -351,7 +340,7 @@ void disk_uevent(struct gendisk *disk, enum kobject_action action) } EXPORT_SYMBOL_GPL(disk_uevent); -int disk_scan_partitions(struct gendisk *disk, fmode_t mode) +int disk_scan_partitions(struct gendisk *disk, blk_mode_t mode) { struct block_device *bdev; int ret = 0; @@ -369,18 +358,20 @@ int disk_scan_partitions(struct gendisk *disk, fmode_t mode) * synchronize with other exclusive openers and other partition * scanners. */ - if (!(mode & FMODE_EXCL)) { - ret = bd_prepare_to_claim(disk->part0, disk_scan_partitions); + if (!(mode & BLK_OPEN_EXCL)) { + ret = bd_prepare_to_claim(disk->part0, disk_scan_partitions, + NULL); if (ret) return ret; } set_bit(GD_NEED_PART_SCAN, &disk->state); - bdev = blkdev_get_by_dev(disk_devt(disk), mode & ~FMODE_EXCL, NULL); + bdev = blkdev_get_by_dev(disk_devt(disk), mode & ~BLK_OPEN_EXCL, NULL, + NULL); if (IS_ERR(bdev)) ret = PTR_ERR(bdev); else - blkdev_put(bdev, mode & ~FMODE_EXCL); + blkdev_put(bdev, NULL); /* * If blkdev_get_by_dev() failed early, GD_NEED_PART_SCAN is still set, @@ -388,7 +379,7 @@ int disk_scan_partitions(struct gendisk *disk, fmode_t mode) * creat partition for underlying disk. */ clear_bit(GD_NEED_PART_SCAN, &disk->state); - if (!(mode & FMODE_EXCL)) + if (!(mode & BLK_OPEN_EXCL)) bd_abort_claiming(disk->part0, disk_scan_partitions); return ret; } @@ -516,7 +507,7 @@ int __must_check device_add_disk(struct device *parent, struct gendisk *disk, bdev_add(disk->part0, ddev->devt); if (get_capacity(disk)) - disk_scan_partitions(disk, FMODE_READ); + disk_scan_partitions(disk, BLK_OPEN_READ); /* * Announce the disk and partitions after all partitions are @@ -563,6 +554,28 @@ int __must_check device_add_disk(struct device *parent, struct gendisk *disk, } EXPORT_SYMBOL(device_add_disk); +static void blk_report_disk_dead(struct gendisk *disk) +{ + struct block_device *bdev; + unsigned long idx; + + rcu_read_lock(); + xa_for_each(&disk->part_tbl, idx, bdev) { + if (!kobject_get_unless_zero(&bdev->bd_device.kobj)) + continue; + rcu_read_unlock(); + + mutex_lock(&bdev->bd_holder_lock); + if (bdev->bd_holder_ops && bdev->bd_holder_ops->mark_dead) + bdev->bd_holder_ops->mark_dead(bdev); + mutex_unlock(&bdev->bd_holder_lock); + + put_device(&bdev->bd_device); + rcu_read_lock(); + } + rcu_read_unlock(); +} + /** * blk_mark_disk_dead - mark a disk as dead * @disk: disk to mark as dead @@ -572,13 +585,26 @@ EXPORT_SYMBOL(device_add_disk); */ void blk_mark_disk_dead(struct gendisk *disk) { - set_bit(GD_DEAD, &disk->state); - blk_queue_start_drain(disk->queue); + /* + * Fail any new I/O. + */ + if (test_and_set_bit(GD_DEAD, &disk->state)) + return; + + if (test_bit(GD_OWNS_QUEUE, &disk->state)) + blk_queue_flag_set(QUEUE_FLAG_DYING, disk->queue); /* * Stop buffered writers from dirtying pages that can't be written out. */ - set_capacity_and_notify(disk, 0); + set_capacity(disk, 0); + + /* + * Prevent new I/O from crossing bio_queue_enter(). + */ + blk_queue_start_drain(disk->queue); + + blk_report_disk_dead(disk); } EXPORT_SYMBOL_GPL(blk_mark_disk_dead); @@ -604,6 +630,8 @@ EXPORT_SYMBOL_GPL(blk_mark_disk_dead); void del_gendisk(struct gendisk *disk) { struct request_queue *q = disk->queue; + struct block_device *part; + unsigned long idx; might_sleep(); @@ -612,26 +640,27 @@ void del_gendisk(struct gendisk *disk) disk_del_events(disk); + /* + * Prevent new openers by unlinked the bdev inode, and write out + * dirty data before marking the disk dead and stopping all I/O. + */ mutex_lock(&disk->open_mutex); - remove_inode_hash(disk->part0->bd_inode); - blk_drop_partitions(disk); + xa_for_each(&disk->part_tbl, idx, part) { + remove_inode_hash(part->bd_inode); + fsync_bdev(part); + __invalidate_device(part, true); + } mutex_unlock(&disk->open_mutex); - fsync_bdev(disk->part0); - __invalidate_device(disk->part0, true); + blk_mark_disk_dead(disk); /* - * Fail any new I/O. + * Drop all partitions now that the disk is marked dead. */ - set_bit(GD_DEAD, &disk->state); - if (test_bit(GD_OWNS_QUEUE, &disk->state)) - blk_queue_flag_set(QUEUE_FLAG_DYING, q); - set_capacity(disk, 0); - - /* - * Prevent new I/O from crossing bio_queue_enter(). - */ - blk_queue_start_drain(q); + mutex_lock(&disk->open_mutex); + xa_for_each_start(&disk->part_tbl, idx, part, 1) + drop_partition(part); + mutex_unlock(&disk->open_mutex); if (!(disk->flags & GENHD_FL_HIDDEN)) { sysfs_remove_link(&disk_to_dev(disk)->kobj, "bdi"); @@ -755,57 +784,6 @@ void blk_request_module(dev_t devt) } #endif /* CONFIG_BLOCK_LEGACY_AUTOLOAD */ -/* - * print a full list of all partitions - intended for places where the root - * filesystem can't be mounted and thus to give the victim some idea of what - * went wrong - */ -void __init printk_all_partitions(void) -{ - struct class_dev_iter iter; - struct device *dev; - - class_dev_iter_init(&iter, &block_class, NULL, &disk_type); - while ((dev = class_dev_iter_next(&iter))) { - struct gendisk *disk = dev_to_disk(dev); - struct block_device *part; - char devt_buf[BDEVT_SIZE]; - unsigned long idx; - - /* - * Don't show empty devices or things that have been - * suppressed - */ - if (get_capacity(disk) == 0 || (disk->flags & GENHD_FL_HIDDEN)) - continue; - - /* - * Note, unlike /proc/partitions, I am showing the numbers in - * hex - the same format as the root= option takes. - */ - rcu_read_lock(); - xa_for_each(&disk->part_tbl, idx, part) { - if (!bdev_nr_sectors(part)) - continue; - printk("%s%s %10llu %pg %s", - bdev_is_partition(part) ? " " : "", - bdevt_str(part->bd_dev, devt_buf), - bdev_nr_sectors(part) >> 1, part, - part->bd_meta_info ? - part->bd_meta_info->uuid : ""); - if (bdev_is_partition(part)) - printk("\n"); - else if (dev->parent && dev->parent->driver) - printk(" driver: %s\n", - dev->parent->driver->name); - else - printk(" (driver?)\n"); - } - rcu_read_unlock(); - } - class_dev_iter_exit(&iter); -} - #ifdef CONFIG_PROC_FS /* iterator */ static void *disk_seqf_start(struct seq_file *seqf, loff_t *pos) @@ -1171,6 +1149,8 @@ static void disk_release(struct device *dev) might_sleep(); WARN_ON_ONCE(disk_live(disk)); + blk_trace_remove(disk->queue); + /* * To undo the all initialization from blk_mq_init_allocated_queue in * case of a probe failure where add_disk is never called we have to @@ -1339,35 +1319,6 @@ dev_t part_devt(struct gendisk *disk, u8 partno) return devt; } -dev_t blk_lookup_devt(const char *name, int partno) -{ - dev_t devt = MKDEV(0, 0); - struct class_dev_iter iter; - struct device *dev; - - class_dev_iter_init(&iter, &block_class, NULL, &disk_type); - while ((dev = class_dev_iter_next(&iter))) { - struct gendisk *disk = dev_to_disk(dev); - - if (strcmp(dev_name(dev), name)) - continue; - - if (partno < disk->minors) { - /* We need to return the right devno, even - * if the partition doesn't exist yet. - */ - devt = MKDEV(MAJOR(dev->devt), - MINOR(dev->devt) + partno); - } else { - devt = part_devt(disk, partno); - if (devt) - break; - } - } - class_dev_iter_exit(&iter); - return devt; -} - struct gendisk *__alloc_disk_node(struct request_queue *q, int node_id, struct lock_class_key *lkclass) { diff --git a/block/ioctl.c b/block/ioctl.c index 9c5f637ff153f8b0010a6812ab8565fdacfbc5fe..3be11941fb2ddce37bd4a1db0cd1c4b3a9101fbf 100644 --- a/block/ioctl.c +++ b/block/ioctl.c @@ -82,7 +82,7 @@ static int compat_blkpg_ioctl(struct block_device *bdev, } #endif -static int blk_ioctl_discard(struct block_device *bdev, fmode_t mode, +static int blk_ioctl_discard(struct block_device *bdev, blk_mode_t mode, unsigned long arg) { uint64_t range[2]; @@ -90,7 +90,7 @@ static int blk_ioctl_discard(struct block_device *bdev, fmode_t mode, struct inode *inode = bdev->bd_inode; int err; - if (!(mode & FMODE_WRITE)) + if (!(mode & BLK_OPEN_WRITE)) return -EBADF; if (!bdev_max_discard_sectors(bdev)) @@ -120,14 +120,14 @@ static int blk_ioctl_discard(struct block_device *bdev, fmode_t mode, return err; } -static int blk_ioctl_secure_erase(struct block_device *bdev, fmode_t mode, +static int blk_ioctl_secure_erase(struct block_device *bdev, blk_mode_t mode, void __user *argp) { uint64_t start, len; uint64_t range[2]; int err; - if (!(mode & FMODE_WRITE)) + if (!(mode & BLK_OPEN_WRITE)) return -EBADF; if (!bdev_max_secure_erase_sectors(bdev)) return -EOPNOTSUPP; @@ -151,7 +151,7 @@ static int blk_ioctl_secure_erase(struct block_device *bdev, fmode_t mode, } -static int blk_ioctl_zeroout(struct block_device *bdev, fmode_t mode, +static int blk_ioctl_zeroout(struct block_device *bdev, blk_mode_t mode, unsigned long arg) { uint64_t range[2]; @@ -159,7 +159,7 @@ static int blk_ioctl_zeroout(struct block_device *bdev, fmode_t mode, struct inode *inode = bdev->bd_inode; int err; - if (!(mode & FMODE_WRITE)) + if (!(mode & BLK_OPEN_WRITE)) return -EBADF; if (copy_from_user(range, (void __user *)arg, sizeof(range))) @@ -240,7 +240,7 @@ static int compat_put_ulong(compat_ulong_t __user *argp, compat_ulong_t val) * drivers that implement only commands that are completely compatible * between 32-bit and 64-bit user space */ -int blkdev_compat_ptr_ioctl(struct block_device *bdev, fmode_t mode, +int blkdev_compat_ptr_ioctl(struct block_device *bdev, blk_mode_t mode, unsigned cmd, unsigned long arg) { struct gendisk *disk = bdev->bd_disk; @@ -254,13 +254,28 @@ int blkdev_compat_ptr_ioctl(struct block_device *bdev, fmode_t mode, EXPORT_SYMBOL(blkdev_compat_ptr_ioctl); #endif -static int blkdev_pr_register(struct block_device *bdev, +static bool blkdev_pr_allowed(struct block_device *bdev, blk_mode_t mode) +{ + /* no sense to make reservations for partitions */ + if (bdev_is_partition(bdev)) + return false; + + if (capable(CAP_SYS_ADMIN)) + return true; + /* + * Only allow unprivileged reservations if the file descriptor is open + * for writing. + */ + return mode & BLK_OPEN_WRITE; +} + +static int blkdev_pr_register(struct block_device *bdev, blk_mode_t mode, struct pr_registration __user *arg) { const struct pr_ops *ops = bdev->bd_disk->fops->pr_ops; struct pr_registration reg; - if (!capable(CAP_SYS_ADMIN)) + if (!blkdev_pr_allowed(bdev, mode)) return -EPERM; if (!ops || !ops->pr_register) return -EOPNOTSUPP; @@ -272,13 +287,13 @@ static int blkdev_pr_register(struct block_device *bdev, return ops->pr_register(bdev, reg.old_key, reg.new_key, reg.flags); } -static int blkdev_pr_reserve(struct block_device *bdev, +static int blkdev_pr_reserve(struct block_device *bdev, blk_mode_t mode, struct pr_reservation __user *arg) { const struct pr_ops *ops = bdev->bd_disk->fops->pr_ops; struct pr_reservation rsv; - if (!capable(CAP_SYS_ADMIN)) + if (!blkdev_pr_allowed(bdev, mode)) return -EPERM; if (!ops || !ops->pr_reserve) return -EOPNOTSUPP; @@ -290,13 +305,13 @@ static int blkdev_pr_reserve(struct block_device *bdev, return ops->pr_reserve(bdev, rsv.key, rsv.type, rsv.flags); } -static int blkdev_pr_release(struct block_device *bdev, +static int blkdev_pr_release(struct block_device *bdev, blk_mode_t mode, struct pr_reservation __user *arg) { const struct pr_ops *ops = bdev->bd_disk->fops->pr_ops; struct pr_reservation rsv; - if (!capable(CAP_SYS_ADMIN)) + if (!blkdev_pr_allowed(bdev, mode)) return -EPERM; if (!ops || !ops->pr_release) return -EOPNOTSUPP; @@ -308,13 +323,13 @@ static int blkdev_pr_release(struct block_device *bdev, return ops->pr_release(bdev, rsv.key, rsv.type); } -static int blkdev_pr_preempt(struct block_device *bdev, +static int blkdev_pr_preempt(struct block_device *bdev, blk_mode_t mode, struct pr_preempt __user *arg, bool abort) { const struct pr_ops *ops = bdev->bd_disk->fops->pr_ops; struct pr_preempt p; - if (!capable(CAP_SYS_ADMIN)) + if (!blkdev_pr_allowed(bdev, mode)) return -EPERM; if (!ops || !ops->pr_preempt) return -EOPNOTSUPP; @@ -326,13 +341,13 @@ static int blkdev_pr_preempt(struct block_device *bdev, return ops->pr_preempt(bdev, p.old_key, p.new_key, p.type, abort); } -static int blkdev_pr_clear(struct block_device *bdev, +static int blkdev_pr_clear(struct block_device *bdev, blk_mode_t mode, struct pr_clear __user *arg) { const struct pr_ops *ops = bdev->bd_disk->fops->pr_ops; struct pr_clear c; - if (!capable(CAP_SYS_ADMIN)) + if (!blkdev_pr_allowed(bdev, mode)) return -EPERM; if (!ops || !ops->pr_clear) return -EOPNOTSUPP; @@ -344,8 +359,8 @@ static int blkdev_pr_clear(struct block_device *bdev, return ops->pr_clear(bdev, c.key); } -static int blkdev_flushbuf(struct block_device *bdev, fmode_t mode, - unsigned cmd, unsigned long arg) +static int blkdev_flushbuf(struct block_device *bdev, unsigned cmd, + unsigned long arg) { if (!capable(CAP_SYS_ADMIN)) return -EACCES; @@ -354,8 +369,8 @@ static int blkdev_flushbuf(struct block_device *bdev, fmode_t mode, return 0; } -static int blkdev_roset(struct block_device *bdev, fmode_t mode, - unsigned cmd, unsigned long arg) +static int blkdev_roset(struct block_device *bdev, unsigned cmd, + unsigned long arg) { int ret, n; @@ -439,7 +454,7 @@ static int compat_hdio_getgeo(struct block_device *bdev, #endif /* set the logical block size */ -static int blkdev_bszset(struct block_device *bdev, fmode_t mode, +static int blkdev_bszset(struct block_device *bdev, blk_mode_t mode, int __user *argp) { int ret, n; @@ -451,13 +466,13 @@ static int blkdev_bszset(struct block_device *bdev, fmode_t mode, if (get_user(n, argp)) return -EFAULT; - if (mode & FMODE_EXCL) + if (mode & BLK_OPEN_EXCL) return set_blocksize(bdev, n); - if (IS_ERR(blkdev_get_by_dev(bdev->bd_dev, mode | FMODE_EXCL, &bdev))) + if (IS_ERR(blkdev_get_by_dev(bdev->bd_dev, mode, &bdev, NULL))) return -EBUSY; ret = set_blocksize(bdev, n); - blkdev_put(bdev, mode | FMODE_EXCL); + blkdev_put(bdev, &bdev); return ret; } @@ -467,7 +482,7 @@ static int blkdev_bszset(struct block_device *bdev, fmode_t mode, * user space. Note the separate arg/argp parameters that are needed * to deal with the compat_ptr() conversion. */ -static int blkdev_common_ioctl(struct block_device *bdev, fmode_t mode, +static int blkdev_common_ioctl(struct block_device *bdev, blk_mode_t mode, unsigned int cmd, unsigned long arg, void __user *argp) { @@ -475,9 +490,9 @@ static int blkdev_common_ioctl(struct block_device *bdev, fmode_t mode, switch (cmd) { case BLKFLSBUF: - return blkdev_flushbuf(bdev, mode, cmd, arg); + return blkdev_flushbuf(bdev, cmd, arg); case BLKROSET: - return blkdev_roset(bdev, mode, cmd, arg); + return blkdev_roset(bdev, cmd, arg); case BLKDISCARD: return blk_ioctl_discard(bdev, mode, arg); case BLKSECDISCARD: @@ -487,7 +502,7 @@ static int blkdev_common_ioctl(struct block_device *bdev, fmode_t mode, case BLKGETDISKSEQ: return put_u64(argp, bdev->bd_disk->diskseq); case BLKREPORTZONE: - return blkdev_report_zones_ioctl(bdev, mode, cmd, arg); + return blkdev_report_zones_ioctl(bdev, cmd, arg); case BLKRESETZONE: case BLKOPENZONE: case BLKCLOSEZONE: @@ -534,17 +549,17 @@ static int blkdev_common_ioctl(struct block_device *bdev, fmode_t mode, case BLKTRACETEARDOWN: return blk_trace_ioctl(bdev, cmd, argp); case IOC_PR_REGISTER: - return blkdev_pr_register(bdev, argp); + return blkdev_pr_register(bdev, mode, argp); case IOC_PR_RESERVE: - return blkdev_pr_reserve(bdev, argp); + return blkdev_pr_reserve(bdev, mode, argp); case IOC_PR_RELEASE: - return blkdev_pr_release(bdev, argp); + return blkdev_pr_release(bdev, mode, argp); case IOC_PR_PREEMPT: - return blkdev_pr_preempt(bdev, argp, false); + return blkdev_pr_preempt(bdev, mode, argp, false); case IOC_PR_PREEMPT_ABORT: - return blkdev_pr_preempt(bdev, argp, true); + return blkdev_pr_preempt(bdev, mode, argp, true); case IOC_PR_CLEAR: - return blkdev_pr_clear(bdev, argp); + return blkdev_pr_clear(bdev, mode, argp); default: return -ENOIOCTLCMD; } @@ -560,18 +575,9 @@ long blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg) { struct block_device *bdev = I_BDEV(file->f_mapping->host); void __user *argp = (void __user *)arg; - fmode_t mode = file->f_mode; + blk_mode_t mode = file_to_blk_mode(file); int ret; - /* - * O_NDELAY can be altered using fcntl(.., F_SETFL, ..), so we have - * to updated it before every ioctl. - */ - if (file->f_flags & O_NDELAY) - mode |= FMODE_NDELAY; - else - mode &= ~FMODE_NDELAY; - switch (cmd) { /* These need separate implementations for the data structure */ case HDIO_GETGEO: @@ -630,16 +636,7 @@ long compat_blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg) void __user *argp = compat_ptr(arg); struct block_device *bdev = I_BDEV(file->f_mapping->host); struct gendisk *disk = bdev->bd_disk; - fmode_t mode = file->f_mode; - - /* - * O_NDELAY can be altered using fcntl(.., F_SETFL, ..), so we have - * to updated it before every ioctl. - */ - if (file->f_flags & O_NDELAY) - mode |= FMODE_NDELAY; - else - mode &= ~FMODE_NDELAY; + blk_mode_t mode = file_to_blk_mode(file); switch (cmd) { /* These need separate implementations for the data structure */ diff --git a/block/ioprio.c b/block/ioprio.c index 32a456b458049f45baf30be663cdfe63bcde2a55..b5a942519a797ceab4729231dd7c673e50ab0613 100644 --- a/block/ioprio.c +++ b/block/ioprio.c @@ -33,7 +33,7 @@ int ioprio_check_cap(int ioprio) { int class = IOPRIO_PRIO_CLASS(ioprio); - int data = IOPRIO_PRIO_DATA(ioprio); + int level = IOPRIO_PRIO_LEVEL(ioprio); switch (class) { case IOPRIO_CLASS_RT: @@ -49,15 +49,16 @@ int ioprio_check_cap(int ioprio) fallthrough; /* rt has prio field too */ case IOPRIO_CLASS_BE: - if (data >= IOPRIO_NR_LEVELS || data < 0) + if (level >= IOPRIO_NR_LEVELS) return -EINVAL; break; case IOPRIO_CLASS_IDLE: break; case IOPRIO_CLASS_NONE: - if (data) + if (level) return -EINVAL; break; + case IOPRIO_CLASS_INVALID: default: return -EINVAL; } diff --git a/block/mq-deadline.c b/block/mq-deadline.c index 5839a027e0f051736f30cd0c459a975a608d1e06..02a916ba62ee750d4ad29127604b7d4a0cb474d7 100644 --- a/block/mq-deadline.c +++ b/block/mq-deadline.c @@ -74,8 +74,8 @@ struct dd_per_prio { struct list_head dispatch; struct rb_root sort_list[DD_DIR_COUNT]; struct list_head fifo_list[DD_DIR_COUNT]; - /* Next request in FIFO order. Read, write or both are NULL. */ - struct request *next_rq[DD_DIR_COUNT]; + /* Position of the most recently dispatched request. */ + sector_t latest_pos[DD_DIR_COUNT]; struct io_stats_per_prio stats; }; @@ -156,6 +156,40 @@ deadline_latter_request(struct request *rq) return NULL; } +/* + * Return the first request for which blk_rq_pos() >= @pos. For zoned devices, + * return the first request after the start of the zone containing @pos. + */ +static inline struct request *deadline_from_pos(struct dd_per_prio *per_prio, + enum dd_data_dir data_dir, sector_t pos) +{ + struct rb_node *node = per_prio->sort_list[data_dir].rb_node; + struct request *rq, *res = NULL; + + if (!node) + return NULL; + + rq = rb_entry_rq(node); + /* + * A zoned write may have been requeued with a starting position that + * is below that of the most recently dispatched request. Hence, for + * zoned writes, start searching from the start of a zone. + */ + if (blk_rq_is_seq_zoned_write(rq)) + pos = round_down(pos, rq->q->limits.chunk_sectors); + + while (node) { + rq = rb_entry_rq(node); + if (blk_rq_pos(rq) >= pos) { + res = rq; + node = node->rb_left; + } else { + node = node->rb_right; + } + } + return res; +} + static void deadline_add_rq_rb(struct dd_per_prio *per_prio, struct request *rq) { @@ -167,11 +201,6 @@ deadline_add_rq_rb(struct dd_per_prio *per_prio, struct request *rq) static inline void deadline_del_rq_rb(struct dd_per_prio *per_prio, struct request *rq) { - const enum dd_data_dir data_dir = rq_data_dir(rq); - - if (per_prio->next_rq[data_dir] == rq) - per_prio->next_rq[data_dir] = deadline_latter_request(rq); - elv_rb_del(deadline_rb_root(per_prio, rq), rq); } @@ -251,10 +280,6 @@ static void deadline_move_request(struct deadline_data *dd, struct dd_per_prio *per_prio, struct request *rq) { - const enum dd_data_dir data_dir = rq_data_dir(rq); - - per_prio->next_rq[data_dir] = deadline_latter_request(rq); - /* * take it off the sort and fifo list */ @@ -272,21 +297,15 @@ static u32 dd_queued(struct deadline_data *dd, enum dd_prio prio) } /* - * deadline_check_fifo returns 0 if there are no expired requests on the fifo, - * 1 otherwise. Requires !list_empty(&dd->fifo_list[data_dir]) + * deadline_check_fifo returns true if and only if there are expired requests + * in the FIFO list. Requires !list_empty(&dd->fifo_list[data_dir]). */ -static inline int deadline_check_fifo(struct dd_per_prio *per_prio, - enum dd_data_dir data_dir) +static inline bool deadline_check_fifo(struct dd_per_prio *per_prio, + enum dd_data_dir data_dir) { struct request *rq = rq_entry_fifo(per_prio->fifo_list[data_dir].next); - /* - * rq is expired! - */ - if (time_after_eq(jiffies, (unsigned long)rq->fifo_time)) - return 1; - - return 0; + return time_is_before_eq_jiffies((unsigned long)rq->fifo_time); } /* @@ -310,14 +329,11 @@ static struct request *deadline_skip_seq_writes(struct deadline_data *dd, struct request *rq) { sector_t pos = blk_rq_pos(rq); - sector_t skipped_sectors = 0; - while (rq) { - if (blk_rq_pos(rq) != pos + skipped_sectors) - break; - skipped_sectors += blk_rq_sectors(rq); + do { + pos += blk_rq_sectors(rq); rq = deadline_latter_request(rq); - } + } while (rq && blk_rq_pos(rq) == pos); return rq; } @@ -330,7 +346,7 @@ static struct request * deadline_fifo_request(struct deadline_data *dd, struct dd_per_prio *per_prio, enum dd_data_dir data_dir) { - struct request *rq; + struct request *rq, *rb_rq, *next; unsigned long flags; if (list_empty(&per_prio->fifo_list[data_dir])) @@ -348,7 +364,12 @@ deadline_fifo_request(struct deadline_data *dd, struct dd_per_prio *per_prio, * zones and these zones are unlocked. */ spin_lock_irqsave(&dd->zone_lock, flags); - list_for_each_entry(rq, &per_prio->fifo_list[DD_WRITE], queuelist) { + list_for_each_entry_safe(rq, next, &per_prio->fifo_list[DD_WRITE], + queuelist) { + /* Check whether a prior request exists for the same zone. */ + rb_rq = deadline_from_pos(per_prio, data_dir, blk_rq_pos(rq)); + if (rb_rq && blk_rq_pos(rb_rq) < blk_rq_pos(rq)) + rq = rb_rq; if (blk_req_can_dispatch_to_zone(rq) && (blk_queue_nonrot(rq->q) || !deadline_is_seq_write(dd, rq))) @@ -372,7 +393,8 @@ deadline_next_request(struct deadline_data *dd, struct dd_per_prio *per_prio, struct request *rq; unsigned long flags; - rq = per_prio->next_rq[data_dir]; + rq = deadline_from_pos(per_prio, data_dir, + per_prio->latest_pos[data_dir]); if (!rq) return NULL; @@ -435,6 +457,7 @@ static struct request *__dd_dispatch_request(struct deadline_data *dd, if (started_after(dd, rq, latest_start)) return NULL; list_del_init(&rq->queuelist); + data_dir = rq_data_dir(rq); goto done; } @@ -442,9 +465,11 @@ static struct request *__dd_dispatch_request(struct deadline_data *dd, * batches are currently reads XOR writes */ rq = deadline_next_request(dd, per_prio, dd->last_dir); - if (rq && dd->batching < dd->fifo_batch) - /* we have a next request are still entitled to batch */ + if (rq && dd->batching < dd->fifo_batch) { + /* we have a next request and are still entitled to batch */ + data_dir = rq_data_dir(rq); goto dispatch_request; + } /* * at this point we are not running a batch. select the appropriate @@ -522,6 +547,7 @@ static struct request *__dd_dispatch_request(struct deadline_data *dd, done: ioprio_class = dd_rq_ioclass(rq); prio = ioprio_class_to_prio[ioprio_class]; + dd->per_prio[prio].latest_pos[data_dir] = blk_rq_pos(rq); dd->per_prio[prio].stats.dispatched++; /* * If the request needs its target zone locked, do it. @@ -766,7 +792,7 @@ static bool dd_bio_merge(struct request_queue *q, struct bio *bio, * add rq to rbtree and fifo */ static void dd_insert_request(struct blk_mq_hw_ctx *hctx, struct request *rq, - blk_insert_t flags) + blk_insert_t flags, struct list_head *free) { struct request_queue *q = hctx->queue; struct deadline_data *dd = q->elevator->elevator_data; @@ -775,7 +801,6 @@ static void dd_insert_request(struct blk_mq_hw_ctx *hctx, struct request *rq, u8 ioprio_class = IOPRIO_PRIO_CLASS(ioprio); struct dd_per_prio *per_prio; enum dd_prio prio; - LIST_HEAD(free); lockdep_assert_held(&dd->lock); @@ -792,10 +817,8 @@ static void dd_insert_request(struct blk_mq_hw_ctx *hctx, struct request *rq, rq->elv.priv[0] = (void *)(uintptr_t)1; } - if (blk_mq_sched_try_insert_merge(q, rq, &free)) { - blk_mq_free_requests(&free); + if (blk_mq_sched_try_insert_merge(q, rq, free)) return; - } trace_block_rq_insert(rq); @@ -803,6 +826,8 @@ static void dd_insert_request(struct blk_mq_hw_ctx *hctx, struct request *rq, list_add(&rq->queuelist, &per_prio->dispatch); rq->fifo_time = jiffies; } else { + struct list_head *insert_before; + deadline_add_rq_rb(per_prio, rq); if (rq_mergeable(rq)) { @@ -815,7 +840,20 @@ static void dd_insert_request(struct blk_mq_hw_ctx *hctx, struct request *rq, * set expire time and add to fifo list */ rq->fifo_time = jiffies + dd->fifo_expire[data_dir]; - list_add_tail(&rq->queuelist, &per_prio->fifo_list[data_dir]); + insert_before = &per_prio->fifo_list[data_dir]; +#ifdef CONFIG_BLK_DEV_ZONED + /* + * Insert zoned writes such that requests are sorted by + * position per zone. + */ + if (blk_rq_is_seq_zoned_write(rq)) { + struct request *rq2 = deadline_latter_request(rq); + + if (rq2 && blk_rq_zone_no(rq2) == blk_rq_zone_no(rq)) + insert_before = &rq2->queuelist; + } +#endif + list_add_tail(&rq->queuelist, insert_before); } } @@ -828,6 +866,7 @@ static void dd_insert_requests(struct blk_mq_hw_ctx *hctx, { struct request_queue *q = hctx->queue; struct deadline_data *dd = q->elevator->elevator_data; + LIST_HEAD(free); spin_lock(&dd->lock); while (!list_empty(list)) { @@ -835,9 +874,11 @@ static void dd_insert_requests(struct blk_mq_hw_ctx *hctx, rq = list_first_entry(list, struct request, queuelist); list_del_init(&rq->queuelist); - dd_insert_request(hctx, rq, flags); + dd_insert_request(hctx, rq, flags, &free); } spin_unlock(&dd->lock); + + blk_mq_free_requests(&free); } /* Callback from inside blk_mq_rq_ctx_init(). */ @@ -1035,8 +1076,10 @@ static int deadline_##name##_next_rq_show(void *data, \ struct request_queue *q = data; \ struct deadline_data *dd = q->elevator->elevator_data; \ struct dd_per_prio *per_prio = &dd->per_prio[prio]; \ - struct request *rq = per_prio->next_rq[data_dir]; \ + struct request *rq; \ \ + rq = deadline_from_pos(per_prio, data_dir, \ + per_prio->latest_pos[data_dir]); \ if (rq) \ __blk_mq_debugfs_rq_show(m, rq); \ return 0; \ diff --git a/block/partitions/amiga.c b/block/partitions/amiga.c index 5c8624e26a54c12823237581cc1b01a6ed740e95..506921095412958132a4f946d63e3bff52bc15dd 100644 --- a/block/partitions/amiga.c +++ b/block/partitions/amiga.c @@ -11,10 +11,18 @@ #define pr_fmt(fmt) fmt #include +#include +#include #include #include "check.h" +/* magic offsets in partition DosEnvVec */ +#define NR_HD 3 +#define NR_SECT 5 +#define LO_CYL 9 +#define HI_CYL 10 + static __inline__ u32 checksum_block(__be32 *m, int size) { @@ -31,8 +39,12 @@ int amiga_partition(struct parsed_partitions *state) unsigned char *data; struct RigidDiskBlock *rdb; struct PartitionBlock *pb; - int start_sect, nr_sects, blk, part, res = 0; - int blksize = 1; /* Multiplier for disk block size */ + u64 start_sect, nr_sects; + sector_t blk, end_sect; + u32 cylblk; /* rdb_CylBlocks = nr_heads*sect_per_track */ + u32 nr_hd, nr_sect, lo_cyl, hi_cyl; + int part, res = 0; + unsigned int blksize = 1; /* Multiplier for disk block size */ int slot = 1; for (blk = 0; ; blk++, put_dev_sector(sect)) { @@ -40,7 +52,7 @@ int amiga_partition(struct parsed_partitions *state) goto rdb_done; data = read_part_sector(state, blk, §); if (!data) { - pr_err("Dev %s: unable to read RDB block %d\n", + pr_err("Dev %s: unable to read RDB block %llu\n", state->disk->disk_name, blk); res = -1; goto rdb_done; @@ -57,12 +69,12 @@ int amiga_partition(struct parsed_partitions *state) *(__be32 *)(data+0xdc) = 0; if (checksum_block((__be32 *)data, be32_to_cpu(rdb->rdb_SummedLongs) & 0x7F)==0) { - pr_err("Trashed word at 0xd0 in block %d ignored in checksum calculation\n", + pr_err("Trashed word at 0xd0 in block %llu ignored in checksum calculation\n", blk); break; } - pr_err("Dev %s: RDB in block %d has bad checksum\n", + pr_err("Dev %s: RDB in block %llu has bad checksum\n", state->disk->disk_name, blk); } @@ -78,11 +90,16 @@ int amiga_partition(struct parsed_partitions *state) } blk = be32_to_cpu(rdb->rdb_PartitionList); put_dev_sector(sect); - for (part = 1; blk>0 && part<=16; part++, put_dev_sector(sect)) { - blk *= blksize; /* Read in terms partition table understands */ + for (part = 1; (s32) blk>0 && part<=16; part++, put_dev_sector(sect)) { + /* Read in terms partition table understands */ + if (check_mul_overflow(blk, (sector_t) blksize, &blk)) { + pr_err("Dev %s: overflow calculating partition block %llu! Skipping partitions %u and beyond\n", + state->disk->disk_name, blk, part); + break; + } data = read_part_sector(state, blk, §); if (!data) { - pr_err("Dev %s: unable to read partition block %d\n", + pr_err("Dev %s: unable to read partition block %llu\n", state->disk->disk_name, blk); res = -1; goto rdb_done; @@ -94,19 +111,70 @@ int amiga_partition(struct parsed_partitions *state) if (checksum_block((__be32 *)pb, be32_to_cpu(pb->pb_SummedLongs) & 0x7F) != 0 ) continue; - /* Tell Kernel about it */ + /* RDB gives us more than enough rope to hang ourselves with, + * many times over (2^128 bytes if all fields max out). + * Some careful checks are in order, so check for potential + * overflows. + * We are multiplying four 32 bit numbers to one sector_t! + */ + + nr_hd = be32_to_cpu(pb->pb_Environment[NR_HD]); + nr_sect = be32_to_cpu(pb->pb_Environment[NR_SECT]); + + /* CylBlocks is total number of blocks per cylinder */ + if (check_mul_overflow(nr_hd, nr_sect, &cylblk)) { + pr_err("Dev %s: heads*sects %u overflows u32, skipping partition!\n", + state->disk->disk_name, cylblk); + continue; + } + + /* check for consistency with RDB defined CylBlocks */ + if (cylblk > be32_to_cpu(rdb->rdb_CylBlocks)) { + pr_warn("Dev %s: cylblk %u > rdb_CylBlocks %u!\n", + state->disk->disk_name, cylblk, + be32_to_cpu(rdb->rdb_CylBlocks)); + } + + /* RDB allows for variable logical block size - + * normalize to 512 byte blocks and check result. + */ + + if (check_mul_overflow(cylblk, blksize, &cylblk)) { + pr_err("Dev %s: partition %u bytes per cyl. overflows u32, skipping partition!\n", + state->disk->disk_name, part); + continue; + } + + /* Calculate partition start and end. Limit of 32 bit on cylblk + * guarantees no overflow occurs if LBD support is enabled. + */ + + lo_cyl = be32_to_cpu(pb->pb_Environment[LO_CYL]); + start_sect = ((u64) lo_cyl * cylblk); + + hi_cyl = be32_to_cpu(pb->pb_Environment[HI_CYL]); + nr_sects = (((u64) hi_cyl - lo_cyl + 1) * cylblk); - nr_sects = (be32_to_cpu(pb->pb_Environment[10]) + 1 - - be32_to_cpu(pb->pb_Environment[9])) * - be32_to_cpu(pb->pb_Environment[3]) * - be32_to_cpu(pb->pb_Environment[5]) * - blksize; if (!nr_sects) continue; - start_sect = be32_to_cpu(pb->pb_Environment[9]) * - be32_to_cpu(pb->pb_Environment[3]) * - be32_to_cpu(pb->pb_Environment[5]) * - blksize; + + /* Warn user if partition end overflows u32 (AmigaDOS limit) */ + + if ((start_sect + nr_sects) > UINT_MAX) { + pr_warn("Dev %s: partition %u (%llu-%llu) needs 64 bit device support!\n", + state->disk->disk_name, part, + start_sect, start_sect + nr_sects); + } + + if (check_add_overflow(start_sect, nr_sects, &end_sect)) { + pr_err("Dev %s: partition %u (%llu-%llu) needs LBD device support, skipping partition!\n", + state->disk->disk_name, part, + start_sect, end_sect); + continue; + } + + /* Tell Kernel about it */ + put_partition(state,slot++,start_sect,nr_sects); { /* Be even more informative to aid mounting */ diff --git a/block/partitions/core.c b/block/partitions/core.c index 49e0496ff23c1ebce6bcc822fd75257e0b06b485..13a7341299a9134de2c17d00020d3475d397f2cf 100644 --- a/block/partitions/core.c +++ b/block/partitions/core.c @@ -12,7 +12,7 @@ #include #include "check.h" -static int (*check_part[])(struct parsed_partitions *) = { +static int (*const check_part[])(struct parsed_partitions *) = { /* * Probe partition formats with tables at disk address 0 * that also have an ADFS boot block at 0xdc0. @@ -228,7 +228,7 @@ static struct attribute *part_attrs[] = { NULL }; -static struct attribute_group part_attr_group = { +static const struct attribute_group part_attr_group = { .attrs = part_attrs, }; @@ -256,31 +256,36 @@ static int part_uevent(const struct device *dev, struct kobj_uevent_env *env) return 0; } -struct device_type part_type = { +const struct device_type part_type = { .name = "partition", .groups = part_attr_groups, .release = part_release, .uevent = part_uevent, }; -static void delete_partition(struct block_device *part) +void drop_partition(struct block_device *part) { lockdep_assert_held(&part->bd_disk->open_mutex); - fsync_bdev(part); - __invalidate_device(part, true); - xa_erase(&part->bd_disk->part_tbl, part->bd_partno); kobject_put(part->bd_holder_dir); + device_del(&part->bd_device); + put_device(&part->bd_device); +} +static void delete_partition(struct block_device *part) +{ /* * Remove the block device from the inode hash, so that it cannot be * looked up any more even when openers still hold references. */ remove_inode_hash(part->bd_inode); - put_device(&part->bd_device); + fsync_bdev(part); + __invalidate_device(part, true); + + drop_partition(part); } static ssize_t whole_disk_show(struct device *dev, @@ -288,7 +293,7 @@ static ssize_t whole_disk_show(struct device *dev, { return 0; } -static DEVICE_ATTR(whole_disk, 0444, whole_disk_show, NULL); +static const DEVICE_ATTR(whole_disk, 0444, whole_disk_show, NULL); /* * Must be called either with open_mutex held, before a disk can be opened or @@ -436,10 +441,21 @@ static bool partition_overlaps(struct gendisk *disk, sector_t start, int bdev_add_partition(struct gendisk *disk, int partno, sector_t start, sector_t length) { + sector_t capacity = get_capacity(disk), end; struct block_device *part; int ret; mutex_lock(&disk->open_mutex); + if (check_add_overflow(start, length, &end)) { + ret = -EINVAL; + goto out; + } + + if (start >= capacity || end > capacity) { + ret = -EINVAL; + goto out; + } + if (!disk_live(disk)) { ret = -ENXIO; goto out; @@ -519,17 +535,6 @@ static bool disk_unlock_native_capacity(struct gendisk *disk) return true; } -void blk_drop_partitions(struct gendisk *disk) -{ - struct block_device *part; - unsigned long idx; - - lockdep_assert_held(&disk->open_mutex); - - xa_for_each_start(&disk->part_tbl, idx, part, 1) - delete_partition(part); -} - static bool blk_add_partition(struct gendisk *disk, struct parsed_partitions *state, int p) { @@ -646,6 +651,8 @@ static int blk_add_partitions(struct gendisk *disk) int bdev_disk_changed(struct gendisk *disk, bool invalidate) { + struct block_device *part; + unsigned long idx; int ret = 0; lockdep_assert_held(&disk->open_mutex); @@ -658,8 +665,9 @@ int bdev_disk_changed(struct gendisk *disk, bool invalidate) return -EBUSY; sync_blockdev(disk->part0); invalidate_bdev(disk->part0); - blk_drop_partitions(disk); + xa_for_each_start(&disk->part_tbl, idx, part, 1) + delete_partition(part); clear_bit(GD_NEED_PART_SCAN, &disk->state); /* diff --git a/crypto/Kconfig b/crypto/Kconfig index a0e080d5f6ae34c6c567a8254b42dadc4d6c4893..650b1b3620d8183ca5b0f5937af39b154078bd19 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -71,8 +71,15 @@ config CRYPTO_AEAD config CRYPTO_AEAD2 tristate select CRYPTO_ALGAPI2 - select CRYPTO_NULL2 - select CRYPTO_RNG2 + +config CRYPTO_SIG + tristate + select CRYPTO_SIG2 + select CRYPTO_ALGAPI + +config CRYPTO_SIG2 + tristate + select CRYPTO_ALGAPI2 config CRYPTO_SKCIPHER tristate @@ -82,7 +89,6 @@ config CRYPTO_SKCIPHER config CRYPTO_SKCIPHER2 tristate select CRYPTO_ALGAPI2 - select CRYPTO_RNG2 config CRYPTO_HASH tristate @@ -143,12 +149,14 @@ config CRYPTO_MANAGER config CRYPTO_MANAGER2 def_tristate CRYPTO_MANAGER || (CRYPTO_MANAGER!=n && CRYPTO_ALGAPI=y) + select CRYPTO_ACOMP2 select CRYPTO_AEAD2 - select CRYPTO_HASH2 - select CRYPTO_SKCIPHER2 select CRYPTO_AKCIPHER2 + select CRYPTO_SIG2 + select CRYPTO_HASH2 select CRYPTO_KPP2 - select CRYPTO_ACOMP2 + select CRYPTO_RNG2 + select CRYPTO_SKCIPHER2 config CRYPTO_USER tristate "Userspace cryptographic algorithm configuration" @@ -833,13 +841,16 @@ config CRYPTO_GCM This is required for IPSec ESP (XFRM_ESP). -config CRYPTO_SEQIV - tristate "Sequence Number IV Generator" +config CRYPTO_GENIV + tristate select CRYPTO_AEAD - select CRYPTO_SKCIPHER select CRYPTO_NULL - select CRYPTO_RNG_DEFAULT select CRYPTO_MANAGER + select CRYPTO_RNG_DEFAULT + +config CRYPTO_SEQIV + tristate "Sequence Number IV Generator" + select CRYPTO_GENIV help Sequence Number IV generator @@ -850,10 +861,7 @@ config CRYPTO_SEQIV config CRYPTO_ECHAINIV tristate "Encrypted Chain IV Generator" - select CRYPTO_AEAD - select CRYPTO_NULL - select CRYPTO_RNG_DEFAULT - select CRYPTO_MANAGER + select CRYPTO_GENIV help Encrypted Chain IV generator @@ -1277,6 +1285,7 @@ endif # if CRYPTO_DRBG_MENU config CRYPTO_JITTERENTROPY tristate "CPU Jitter Non-Deterministic RNG (Random Number Generator)" select CRYPTO_RNG + select CRYPTO_SHA3 help CPU Jitter RNG (Random Number Generator) from the Jitterentropy library @@ -1287,6 +1296,26 @@ config CRYPTO_JITTERENTROPY See https://www.chronox.de/jent.html +config CRYPTO_JITTERENTROPY_TESTINTERFACE + bool "CPU Jitter RNG Test Interface" + depends on CRYPTO_JITTERENTROPY + help + The test interface allows a privileged process to capture + the raw unconditioned high resolution time stamp noise that + is collected by the Jitter RNG for statistical analysis. As + this data is used at the same time to generate random bits, + the Jitter RNG operates in an insecure mode as long as the + recording is enabled. This interface therefore is only + intended for testing purposes and is not suitable for + production systems. + + The raw noise data can be obtained using the jent_raw_hires + debugfs file. Using the option + jitterentropy_testing.boot_raw_hires_test=1 the raw noise of + the first 1000 entropy events since boot can be sampled. + + If unsure, select N. + config CRYPTO_KDF800108_CTR tristate select CRYPTO_HMAC @@ -1372,6 +1401,9 @@ config CRYPTO_STATS help Enable the gathering of crypto stats. + Enabling this option reduces the performance of the crypto API. It + should only be enabled when there is actually a use case for it. + This collects data sizes, numbers of requests, and numbers of errors processed by: - AEAD ciphers (encrypt, decrypt) diff --git a/crypto/Makefile b/crypto/Makefile index d0126c915834b2f09b3ed42ab712a69b26b47258..953a7e105e58c837d927d21a0358581e94f86857 100644 --- a/crypto/Makefile +++ b/crypto/Makefile @@ -14,7 +14,7 @@ crypto_algapi-y := algapi.o scatterwalk.o $(crypto_algapi-y) obj-$(CONFIG_CRYPTO_ALGAPI2) += crypto_algapi.o obj-$(CONFIG_CRYPTO_AEAD2) += aead.o -obj-$(CONFIG_CRYPTO_AEAD2) += geniv.o +obj-$(CONFIG_CRYPTO_GENIV) += geniv.o obj-$(CONFIG_CRYPTO_SKCIPHER2) += skcipher.o obj-$(CONFIG_CRYPTO_SEQIV) += seqiv.o @@ -25,6 +25,7 @@ crypto_hash-y += shash.o obj-$(CONFIG_CRYPTO_HASH2) += crypto_hash.o obj-$(CONFIG_CRYPTO_AKCIPHER2) += akcipher.o +obj-$(CONFIG_CRYPTO_SIG2) += sig.o obj-$(CONFIG_CRYPTO_KPP2) += kpp.o dh_generic-y := dh.o @@ -171,6 +172,7 @@ CFLAGS_jitterentropy.o = -O0 KASAN_SANITIZE_jitterentropy.o = n UBSAN_SANITIZE_jitterentropy.o = n jitterentropy_rng-y := jitterentropy.o jitterentropy-kcapi.o +obj-$(CONFIG_CRYPTO_JITTERENTROPY_TESTINTERFACE) += jitterentropy-testing.o obj-$(CONFIG_CRYPTO_TEST) += tcrypt.o obj-$(CONFIG_CRYPTO_GHASH) += ghash-generic.o obj-$(CONFIG_CRYPTO_POLYVAL) += polyval-generic.o diff --git a/crypto/aegis-neon.h b/crypto/aegis-neon.h new file mode 100644 index 0000000000000000000000000000000000000000..61e5614b45dedb3a812310b34c4f34f77cdedfc3 --- /dev/null +++ b/crypto/aegis-neon.h @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +#ifndef _AEGIS_NEON_H +#define _AEGIS_NEON_H + +void crypto_aegis128_init_neon(void *state, const void *key, const void *iv); +void crypto_aegis128_update_neon(void *state, const void *msg); +void crypto_aegis128_encrypt_chunk_neon(void *state, void *dst, const void *src, + unsigned int size); +void crypto_aegis128_decrypt_chunk_neon(void *state, void *dst, const void *src, + unsigned int size); +int crypto_aegis128_final_neon(void *state, void *tag_xor, + unsigned int assoclen, + unsigned int cryptlen, + unsigned int authsize); + +#endif diff --git a/crypto/aegis128-neon-inner.c b/crypto/aegis128-neon-inner.c index 7de485907d816483e82dd191d62d6edd6fb1ac3d..b6a52a386b220836d6268ade86672726a812d766 100644 --- a/crypto/aegis128-neon-inner.c +++ b/crypto/aegis128-neon-inner.c @@ -16,6 +16,7 @@ #define AEGIS_BLOCK_SIZE 16 #include +#include "aegis-neon.h" extern int aegis128_have_aes_insn; diff --git a/crypto/aegis128-neon.c b/crypto/aegis128-neon.c index a7856915ec85b4172eceff31442f024d7d00809f..9ee50549e8231eef27731c3011b733be240539df 100644 --- a/crypto/aegis128-neon.c +++ b/crypto/aegis128-neon.c @@ -7,17 +7,7 @@ #include #include "aegis.h" - -void crypto_aegis128_init_neon(void *state, const void *key, const void *iv); -void crypto_aegis128_update_neon(void *state, const void *msg); -void crypto_aegis128_encrypt_chunk_neon(void *state, void *dst, const void *src, - unsigned int size); -void crypto_aegis128_decrypt_chunk_neon(void *state, void *dst, const void *src, - unsigned int size); -int crypto_aegis128_final_neon(void *state, void *tag_xor, - unsigned int assoclen, - unsigned int cryptlen, - unsigned int authsize); +#include "aegis-neon.h" int aegis128_have_aes_insn __ro_after_init; diff --git a/crypto/af_alg.c b/crypto/af_alg.c index 5f7252a5b7b44af2915913ef9ac35fddb369b3d5..06b15b9f661ca0f97b8d1b569becbbeec857eb43 100644 --- a/crypto/af_alg.c +++ b/crypto/af_alg.c @@ -482,7 +482,6 @@ static const struct proto_ops alg_proto_ops = { .listen = sock_no_listen, .shutdown = sock_no_shutdown, .mmap = sock_no_mmap, - .sendpage = sock_no_sendpage, .sendmsg = sock_no_sendmsg, .recvmsg = sock_no_recvmsg, @@ -531,50 +530,25 @@ static const struct net_proto_family alg_family = { .owner = THIS_MODULE, }; -int af_alg_make_sg(struct af_alg_sgl *sgl, struct iov_iter *iter, int len) -{ - size_t off; - ssize_t n; - int npages, i; - - n = iov_iter_get_pages2(iter, sgl->pages, len, ALG_MAX_PAGES, &off); - if (n < 0) - return n; - - npages = DIV_ROUND_UP(off + n, PAGE_SIZE); - if (WARN_ON(npages == 0)) - return -EINVAL; - /* Add one extra for linking */ - sg_init_table(sgl->sg, npages + 1); - - for (i = 0, len = n; i < npages; i++) { - int plen = min_t(int, len, PAGE_SIZE - off); - - sg_set_page(sgl->sg + i, sgl->pages[i], plen, off); - - off = 0; - len -= plen; - } - sg_mark_end(sgl->sg + npages - 1); - sgl->npages = npages; - - return n; -} -EXPORT_SYMBOL_GPL(af_alg_make_sg); - static void af_alg_link_sg(struct af_alg_sgl *sgl_prev, struct af_alg_sgl *sgl_new) { - sg_unmark_end(sgl_prev->sg + sgl_prev->npages - 1); - sg_chain(sgl_prev->sg, sgl_prev->npages + 1, sgl_new->sg); + sg_unmark_end(sgl_prev->sgt.sgl + sgl_prev->sgt.nents - 1); + sg_chain(sgl_prev->sgt.sgl, sgl_prev->sgt.nents + 1, sgl_new->sgt.sgl); } void af_alg_free_sg(struct af_alg_sgl *sgl) { int i; - for (i = 0; i < sgl->npages; i++) - put_page(sgl->pages[i]); + if (sgl->sgt.sgl) { + if (sgl->need_unpin) + for (i = 0; i < sgl->sgt.nents; i++) + unpin_user_page(sg_page(&sgl->sgt.sgl[i])); + if (sgl->sgt.sgl != sgl->sgl) + kvfree(sgl->sgt.sgl); + sgl->sgt.sgl = NULL; + } } EXPORT_SYMBOL_GPL(af_alg_free_sg); @@ -1015,10 +989,10 @@ int af_alg_sendmsg(struct socket *sock, struct msghdr *msg, size_t size, while (size) { struct scatterlist *sg; size_t len = size; - size_t plen; + ssize_t plen; /* use the existing memory in an allocated page */ - if (ctx->merge) { + if (ctx->merge && !(msg->msg_flags & MSG_SPLICE_PAGES)) { sgl = list_entry(ctx->tsgl_list.prev, struct af_alg_tsgl, list); sg = sgl->sg + sgl->cur - 1; @@ -1060,116 +1034,77 @@ int af_alg_sendmsg(struct socket *sock, struct msghdr *msg, size_t size, if (sgl->cur) sg_unmark_end(sg + sgl->cur - 1); - do { - struct page *pg; - unsigned int i = sgl->cur; - - plen = min_t(size_t, len, PAGE_SIZE); - - pg = alloc_page(GFP_KERNEL); - if (!pg) { - err = -ENOMEM; - goto unlock; - } - - sg_assign_page(sg + i, pg); - - err = memcpy_from_msg(page_address(sg_page(sg + i)), - msg, plen); - if (err) { - __free_page(sg_page(sg + i)); - sg_assign_page(sg + i, NULL); + if (msg->msg_flags & MSG_SPLICE_PAGES) { + struct sg_table sgtable = { + .sgl = sg, + .nents = sgl->cur, + .orig_nents = sgl->cur, + }; + + plen = extract_iter_to_sg(&msg->msg_iter, len, &sgtable, + MAX_SGL_ENTS - sgl->cur, 0); + if (plen < 0) { + err = plen; goto unlock; } - sg[i].length = plen; + for (; sgl->cur < sgtable.nents; sgl->cur++) + get_page(sg_page(&sg[sgl->cur])); len -= plen; ctx->used += plen; copied += plen; size -= plen; - sgl->cur++; - } while (len && sgl->cur < MAX_SGL_ENTS); - - if (!size) - sg_mark_end(sg + sgl->cur - 1); - - ctx->merge = plen & (PAGE_SIZE - 1); - } - - err = 0; - - ctx->more = msg->msg_flags & MSG_MORE; + ctx->merge = 0; + } else { + do { + struct page *pg; + unsigned int i = sgl->cur; -unlock: - af_alg_data_wakeup(sk); - release_sock(sk); + plen = min_t(size_t, len, PAGE_SIZE); - return copied ?: err; -} -EXPORT_SYMBOL_GPL(af_alg_sendmsg); + pg = alloc_page(GFP_KERNEL); + if (!pg) { + err = -ENOMEM; + goto unlock; + } -/** - * af_alg_sendpage - sendpage system call handler - * @sock: socket of connection to user space to write to - * @page: data to send - * @offset: offset into page to begin sending - * @size: length of data - * @flags: message send/receive flags - * - * This is a generic implementation of sendpage to fill ctx->tsgl_list. - */ -ssize_t af_alg_sendpage(struct socket *sock, struct page *page, - int offset, size_t size, int flags) -{ - struct sock *sk = sock->sk; - struct alg_sock *ask = alg_sk(sk); - struct af_alg_ctx *ctx = ask->private; - struct af_alg_tsgl *sgl; - int err = -EINVAL; + sg_assign_page(sg + i, pg); - if (flags & MSG_SENDPAGE_NOTLAST) - flags |= MSG_MORE; + err = memcpy_from_msg( + page_address(sg_page(sg + i)), + msg, plen); + if (err) { + __free_page(sg_page(sg + i)); + sg_assign_page(sg + i, NULL); + goto unlock; + } - lock_sock(sk); - if (!ctx->more && ctx->used) - goto unlock; + sg[i].length = plen; + len -= plen; + ctx->used += plen; + copied += plen; + size -= plen; + sgl->cur++; + } while (len && sgl->cur < MAX_SGL_ENTS); - if (!size) - goto done; + ctx->merge = plen & (PAGE_SIZE - 1); + } - if (!af_alg_writable(sk)) { - err = af_alg_wait_for_wmem(sk, flags); - if (err) - goto unlock; + if (!size) + sg_mark_end(sg + sgl->cur - 1); } - err = af_alg_alloc_tsgl(sk); - if (err) - goto unlock; - - ctx->merge = 0; - sgl = list_entry(ctx->tsgl_list.prev, struct af_alg_tsgl, list); - - if (sgl->cur) - sg_unmark_end(sgl->sg + sgl->cur - 1); - - sg_mark_end(sgl->sg + sgl->cur); - - get_page(page); - sg_set_page(sgl->sg + sgl->cur, page, size, offset); - sgl->cur++; - ctx->used += size; + err = 0; -done: - ctx->more = flags & MSG_MORE; + ctx->more = msg->msg_flags & MSG_MORE; unlock: af_alg_data_wakeup(sk); release_sock(sk); - return err ?: size; + return copied ?: err; } -EXPORT_SYMBOL_GPL(af_alg_sendpage); +EXPORT_SYMBOL_GPL(af_alg_sendmsg); /** * af_alg_free_resources - release resources required for crypto request @@ -1288,8 +1223,8 @@ int af_alg_get_rsgl(struct sock *sk, struct msghdr *msg, int flags, while (maxsize > len && msg_data_left(msg)) { struct af_alg_rsgl *rsgl; + ssize_t err; size_t seglen; - int err; /* limit the amount of readable buffers */ if (!af_alg_readable(sk)) @@ -1306,16 +1241,23 @@ int af_alg_get_rsgl(struct sock *sk, struct msghdr *msg, int flags, return -ENOMEM; } - rsgl->sgl.npages = 0; + rsgl->sgl.sgt.sgl = rsgl->sgl.sgl; + rsgl->sgl.sgt.nents = 0; + rsgl->sgl.sgt.orig_nents = 0; list_add_tail(&rsgl->list, &areq->rsgl_list); - /* make one iovec available as scatterlist */ - err = af_alg_make_sg(&rsgl->sgl, &msg->msg_iter, seglen); + sg_init_table(rsgl->sgl.sgt.sgl, ALG_MAX_PAGES); + err = extract_iter_to_sg(&msg->msg_iter, seglen, &rsgl->sgl.sgt, + ALG_MAX_PAGES, 0); if (err < 0) { rsgl->sg_num_bytes = 0; return err; } + sg_mark_end(rsgl->sgl.sgt.sgl + rsgl->sgl.sgt.nents - 1); + rsgl->sgl.need_unpin = + iov_iter_extract_will_pin(&msg->msg_iter); + /* chain the new scatterlist with previous one */ if (areq->last_rsgl) af_alg_link_sg(&areq->last_rsgl->sgl, &rsgl->sgl); diff --git a/crypto/ahash.c b/crypto/ahash.c index 32465104044651af4cbd3b918eaeff84ab8663e3..709ef09407991374e633c3d015ffca9c3bdaa72a 100644 --- a/crypto/ahash.c +++ b/crypto/ahash.c @@ -31,12 +31,6 @@ struct ahash_request_priv { void *ubuf[] CRYPTO_MINALIGN_ATTR; }; -static inline struct ahash_alg *crypto_ahash_alg(struct crypto_ahash *hash) -{ - return container_of(crypto_hash_alg_common(hash), struct ahash_alg, - halg); -} - static int hash_walk_next(struct crypto_hash_walk *walk) { unsigned int alignmask = walk->alignmask; @@ -432,6 +426,8 @@ static int crypto_ahash_init_tfm(struct crypto_tfm *tfm) hash->setkey = ahash_nosetkey; + crypto_ahash_set_statesize(hash, alg->halg.statesize); + if (tfm->__crt_alg->cra_type != &crypto_ahash_type) return crypto_init_shash_ops_async(tfm); @@ -573,6 +569,7 @@ struct crypto_ahash *crypto_clone_ahash(struct crypto_ahash *hash) nhash->import = hash->import; nhash->setkey = hash->setkey; nhash->reqsize = hash->reqsize; + nhash->statesize = hash->statesize; if (tfm->__crt_alg->cra_type != &crypto_ahash_type) return crypto_clone_shash_ops_async(nhash, hash); diff --git a/crypto/akcipher.c b/crypto/akcipher.c index 7960ceb528c3664fb74968f57da9ba754281f324..52813f0b19e4e915bf7c53e178e97833caee72f0 100644 --- a/crypto/akcipher.c +++ b/crypto/akcipher.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -17,6 +18,8 @@ #include "internal.h" +#define CRYPTO_ALG_TYPE_AHASH_MASK 0x0000000e + static int __maybe_unused crypto_akcipher_report( struct sk_buff *skb, struct crypto_alg *alg) { @@ -105,7 +108,7 @@ static const struct crypto_type crypto_akcipher_type = { .report_stat = crypto_akcipher_report_stat, #endif .maskclear = ~CRYPTO_ALG_TYPE_MASK, - .maskset = CRYPTO_ALG_TYPE_MASK, + .maskset = CRYPTO_ALG_TYPE_AHASH_MASK, .type = CRYPTO_ALG_TYPE_AKCIPHER, .tfmsize = offsetof(struct crypto_akcipher, base), }; @@ -186,5 +189,124 @@ int akcipher_register_instance(struct crypto_template *tmpl, } EXPORT_SYMBOL_GPL(akcipher_register_instance); +int crypto_akcipher_sync_prep(struct crypto_akcipher_sync_data *data) +{ + unsigned int reqsize = crypto_akcipher_reqsize(data->tfm); + struct akcipher_request *req; + struct scatterlist *sg; + unsigned int mlen; + unsigned int len; + u8 *buf; + + if (data->dst) + mlen = max(data->slen, data->dlen); + else + mlen = data->slen + data->dlen; + + len = sizeof(*req) + reqsize + mlen; + if (len < mlen) + return -EOVERFLOW; + + req = kzalloc(len, GFP_KERNEL); + if (!req) + return -ENOMEM; + + data->req = req; + akcipher_request_set_tfm(req, data->tfm); + + buf = (u8 *)(req + 1) + reqsize; + data->buf = buf; + memcpy(buf, data->src, data->slen); + + sg = &data->sg; + sg_init_one(sg, buf, mlen); + akcipher_request_set_crypt(req, sg, data->dst ? sg : NULL, + data->slen, data->dlen); + + crypto_init_wait(&data->cwait); + akcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_SLEEP, + crypto_req_done, &data->cwait); + + return 0; +} +EXPORT_SYMBOL_GPL(crypto_akcipher_sync_prep); + +int crypto_akcipher_sync_post(struct crypto_akcipher_sync_data *data, int err) +{ + err = crypto_wait_req(err, &data->cwait); + if (data->dst) + memcpy(data->dst, data->buf, data->dlen); + data->dlen = data->req->dst_len; + kfree_sensitive(data->req); + return err; +} +EXPORT_SYMBOL_GPL(crypto_akcipher_sync_post); + +int crypto_akcipher_sync_encrypt(struct crypto_akcipher *tfm, + const void *src, unsigned int slen, + void *dst, unsigned int dlen) +{ + struct crypto_akcipher_sync_data data = { + .tfm = tfm, + .src = src, + .dst = dst, + .slen = slen, + .dlen = dlen, + }; + + return crypto_akcipher_sync_prep(&data) ?: + crypto_akcipher_sync_post(&data, + crypto_akcipher_encrypt(data.req)); +} +EXPORT_SYMBOL_GPL(crypto_akcipher_sync_encrypt); + +int crypto_akcipher_sync_decrypt(struct crypto_akcipher *tfm, + const void *src, unsigned int slen, + void *dst, unsigned int dlen) +{ + struct crypto_akcipher_sync_data data = { + .tfm = tfm, + .src = src, + .dst = dst, + .slen = slen, + .dlen = dlen, + }; + + return crypto_akcipher_sync_prep(&data) ?: + crypto_akcipher_sync_post(&data, + crypto_akcipher_decrypt(data.req)) ?: + data.dlen; +} +EXPORT_SYMBOL_GPL(crypto_akcipher_sync_decrypt); + +static void crypto_exit_akcipher_ops_sig(struct crypto_tfm *tfm) +{ + struct crypto_akcipher **ctx = crypto_tfm_ctx(tfm); + + crypto_free_akcipher(*ctx); +} + +int crypto_init_akcipher_ops_sig(struct crypto_tfm *tfm) +{ + struct crypto_akcipher **ctx = crypto_tfm_ctx(tfm); + struct crypto_alg *calg = tfm->__crt_alg; + struct crypto_akcipher *akcipher; + + if (!crypto_mod_get(calg)) + return -EAGAIN; + + akcipher = crypto_create_tfm(calg, &crypto_akcipher_type); + if (IS_ERR(akcipher)) { + crypto_mod_put(calg); + return PTR_ERR(akcipher); + } + + *ctx = akcipher; + tfm->exit = crypto_exit_akcipher_ops_sig; + + return 0; +} +EXPORT_SYMBOL_GPL(crypto_init_akcipher_ops_sig); + MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Generic public key cipher type"); diff --git a/crypto/algif_aead.c b/crypto/algif_aead.c index 42493b4d8ce462a10719a3a24095326efd54dc68..7d58cbbce4af28bbaec153ca31feabe0345df516 100644 --- a/crypto/algif_aead.c +++ b/crypto/algif_aead.c @@ -9,10 +9,10 @@ * The following concept of the memory management is used: * * The kernel maintains two SGLs, the TX SGL and the RX SGL. The TX SGL is - * filled by user space with the data submitted via sendpage/sendmsg. Filling - * up the TX SGL does not cause a crypto operation -- the data will only be - * tracked by the kernel. Upon receipt of one recvmsg call, the caller must - * provide a buffer which is tracked with the RX SGL. + * filled by user space with the data submitted via sendmsg (maybe with + * MSG_SPLICE_PAGES). Filling up the TX SGL does not cause a crypto operation + * -- the data will only be tracked by the kernel. Upon receipt of one recvmsg + * call, the caller must provide a buffer which is tracked with the RX SGL. * * During the processing of the recvmsg operation, the cipher request is * allocated and prepared. As part of the recvmsg operation, the processed @@ -113,19 +113,19 @@ static int _aead_recvmsg(struct socket *sock, struct msghdr *msg, } /* - * Data length provided by caller via sendmsg/sendpage that has not - * yet been processed. + * Data length provided by caller via sendmsg that has not yet been + * processed. */ used = ctx->used; /* - * Make sure sufficient data is present -- note, the same check is - * also present in sendmsg/sendpage. The checks in sendpage/sendmsg - * shall provide an information to the data sender that something is - * wrong, but they are irrelevant to maintain the kernel integrity. - * We need this check here too in case user space decides to not honor - * the error message in sendmsg/sendpage and still call recvmsg. This - * check here protects the kernel integrity. + * Make sure sufficient data is present -- note, the same check is also + * present in sendmsg. The checks in sendmsg shall provide an + * information to the data sender that something is wrong, but they are + * irrelevant to maintain the kernel integrity. We need this check + * here too in case user space decides to not honor the error message + * in sendmsg and still call recvmsg. This check here protects the + * kernel integrity. */ if (!aead_sufficient_data(sk)) return -EINVAL; @@ -210,7 +210,7 @@ static int _aead_recvmsg(struct socket *sock, struct msghdr *msg, */ /* Use the RX SGL as source (and destination) for crypto op. */ - rsgl_src = areq->first_rsgl.sgl.sg; + rsgl_src = areq->first_rsgl.sgl.sgt.sgl; if (ctx->enc) { /* @@ -224,7 +224,8 @@ static int _aead_recvmsg(struct socket *sock, struct msghdr *msg, * RX SGL: AAD || PT || Tag */ err = crypto_aead_copy_sgl(null_tfm, tsgl_src, - areq->first_rsgl.sgl.sg, processed); + areq->first_rsgl.sgl.sgt.sgl, + processed); if (err) goto free; af_alg_pull_tsgl(sk, processed, NULL, 0); @@ -242,7 +243,8 @@ static int _aead_recvmsg(struct socket *sock, struct msghdr *msg, /* Copy AAD || CT to RX SGL buffer for in-place operation. */ err = crypto_aead_copy_sgl(null_tfm, tsgl_src, - areq->first_rsgl.sgl.sg, outlen); + areq->first_rsgl.sgl.sgt.sgl, + outlen); if (err) goto free; @@ -267,10 +269,10 @@ static int _aead_recvmsg(struct socket *sock, struct msghdr *msg, if (usedpages) { /* RX SGL present */ struct af_alg_sgl *sgl_prev = &areq->last_rsgl->sgl; + struct scatterlist *sg = sgl_prev->sgt.sgl; - sg_unmark_end(sgl_prev->sg + sgl_prev->npages - 1); - sg_chain(sgl_prev->sg, sgl_prev->npages + 1, - areq->tsgl); + sg_unmark_end(sg + sgl_prev->sgt.nents - 1); + sg_chain(sg, sgl_prev->sgt.nents + 1, areq->tsgl); } else /* no RX SGL present (e.g. authentication only) */ rsgl_src = areq->tsgl; @@ -278,7 +280,7 @@ static int _aead_recvmsg(struct socket *sock, struct msghdr *msg, /* Initialize the crypto operation */ aead_request_set_crypt(&areq->cra_u.aead_req, rsgl_src, - areq->first_rsgl.sgl.sg, used, ctx->iv); + areq->first_rsgl.sgl.sgt.sgl, used, ctx->iv); aead_request_set_ad(&areq->cra_u.aead_req, ctx->aead_assoclen); aead_request_set_tfm(&areq->cra_u.aead_req, tfm); @@ -368,7 +370,6 @@ static struct proto_ops algif_aead_ops = { .release = af_alg_release, .sendmsg = aead_sendmsg, - .sendpage = af_alg_sendpage, .recvmsg = aead_recvmsg, .poll = af_alg_poll, }; @@ -420,18 +421,6 @@ static int aead_sendmsg_nokey(struct socket *sock, struct msghdr *msg, return aead_sendmsg(sock, msg, size); } -static ssize_t aead_sendpage_nokey(struct socket *sock, struct page *page, - int offset, size_t size, int flags) -{ - int err; - - err = aead_check_key(sock); - if (err) - return err; - - return af_alg_sendpage(sock, page, offset, size, flags); -} - static int aead_recvmsg_nokey(struct socket *sock, struct msghdr *msg, size_t ignored, int flags) { @@ -459,7 +448,6 @@ static struct proto_ops algif_aead_ops_nokey = { .release = af_alg_release, .sendmsg = aead_sendmsg_nokey, - .sendpage = aead_sendpage_nokey, .recvmsg = aead_recvmsg_nokey, .poll = af_alg_poll, }; diff --git a/crypto/algif_hash.c b/crypto/algif_hash.c index 63af72e19fa8c948b2f40570aaaf32eee1b41600..82c44d4899b9676d4d43c2f2af7fd9f95758b894 100644 --- a/crypto/algif_hash.c +++ b/crypto/algif_hash.c @@ -63,122 +63,116 @@ static void hash_free_result(struct sock *sk, struct hash_ctx *ctx) static int hash_sendmsg(struct socket *sock, struct msghdr *msg, size_t ignored) { - int limit = ALG_MAX_PAGES * PAGE_SIZE; struct sock *sk = sock->sk; struct alg_sock *ask = alg_sk(sk); struct hash_ctx *ctx = ask->private; - long copied = 0; + ssize_t copied = 0; + size_t len, max_pages, npages; + bool continuing, need_init = false; int err; - if (limit > sk->sk_sndbuf) - limit = sk->sk_sndbuf; + max_pages = min_t(size_t, ALG_MAX_PAGES, + DIV_ROUND_UP(sk->sk_sndbuf, PAGE_SIZE)); lock_sock(sk); - if (!ctx->more) { - if ((msg->msg_flags & MSG_MORE)) - hash_free_result(sk, ctx); + continuing = ctx->more; - err = crypto_wait_req(crypto_ahash_init(&ctx->req), &ctx->wait); - if (err) - goto unlock; - } - - ctx->more = false; - - while (msg_data_left(msg)) { - int len = msg_data_left(msg); - - if (len > limit) - len = limit; - - len = af_alg_make_sg(&ctx->sgl, &msg->msg_iter, len); - if (len < 0) { - err = copied ? 0 : len; - goto unlock; - } - - ahash_request_set_crypt(&ctx->req, ctx->sgl.sg, NULL, len); - - err = crypto_wait_req(crypto_ahash_update(&ctx->req), - &ctx->wait); - af_alg_free_sg(&ctx->sgl); - if (err) { - iov_iter_revert(&msg->msg_iter, len); - goto unlock; + if (!continuing) { + /* Discard a previous request that wasn't marked MSG_MORE. */ + hash_free_result(sk, ctx); + if (!msg_data_left(msg)) + goto done; /* Zero-length; don't start new req */ + need_init = true; + } else if (!msg_data_left(msg)) { + /* + * No data - finalise the prev req if MSG_MORE so any error + * comes out here. + */ + if (!(msg->msg_flags & MSG_MORE)) { + err = hash_alloc_result(sk, ctx); + if (err) + goto unlock_free; + ahash_request_set_crypt(&ctx->req, NULL, + ctx->result, 0); + err = crypto_wait_req(crypto_ahash_final(&ctx->req), + &ctx->wait); + if (err) + goto unlock_free; } - - copied += len; + goto done_more; } - err = 0; - - ctx->more = msg->msg_flags & MSG_MORE; - if (!ctx->more) { - err = hash_alloc_result(sk, ctx); - if (err) - goto unlock; - - ahash_request_set_crypt(&ctx->req, NULL, ctx->result, 0); - err = crypto_wait_req(crypto_ahash_final(&ctx->req), - &ctx->wait); - } - -unlock: - release_sock(sk); + while (msg_data_left(msg)) { + ctx->sgl.sgt.sgl = ctx->sgl.sgl; + ctx->sgl.sgt.nents = 0; + ctx->sgl.sgt.orig_nents = 0; - return err ?: copied; -} + err = -EIO; + npages = iov_iter_npages(&msg->msg_iter, max_pages); + if (npages == 0) + goto unlock_free; -static ssize_t hash_sendpage(struct socket *sock, struct page *page, - int offset, size_t size, int flags) -{ - struct sock *sk = sock->sk; - struct alg_sock *ask = alg_sk(sk); - struct hash_ctx *ctx = ask->private; - int err; + sg_init_table(ctx->sgl.sgl, npages); - if (flags & MSG_SENDPAGE_NOTLAST) - flags |= MSG_MORE; + ctx->sgl.need_unpin = iov_iter_extract_will_pin(&msg->msg_iter); - lock_sock(sk); - sg_init_table(ctx->sgl.sg, 1); - sg_set_page(ctx->sgl.sg, page, size, offset); + err = extract_iter_to_sg(&msg->msg_iter, LONG_MAX, + &ctx->sgl.sgt, npages, 0); + if (err < 0) + goto unlock_free; + len = err; + sg_mark_end(ctx->sgl.sgt.sgl + ctx->sgl.sgt.nents - 1); - if (!(flags & MSG_MORE)) { - err = hash_alloc_result(sk, ctx); - if (err) - goto unlock; - } else if (!ctx->more) - hash_free_result(sk, ctx); + if (!msg_data_left(msg)) { + err = hash_alloc_result(sk, ctx); + if (err) + goto unlock_free; + } - ahash_request_set_crypt(&ctx->req, ctx->sgl.sg, ctx->result, size); + ahash_request_set_crypt(&ctx->req, ctx->sgl.sgt.sgl, + ctx->result, len); - if (!(flags & MSG_MORE)) { - if (ctx->more) - err = crypto_ahash_finup(&ctx->req); - else + if (!msg_data_left(msg) && !continuing && + !(msg->msg_flags & MSG_MORE)) { err = crypto_ahash_digest(&ctx->req); - } else { - if (!ctx->more) { - err = crypto_ahash_init(&ctx->req); - err = crypto_wait_req(err, &ctx->wait); - if (err) - goto unlock; + } else { + if (need_init) { + err = crypto_wait_req( + crypto_ahash_init(&ctx->req), + &ctx->wait); + if (err) + goto unlock_free; + need_init = false; + } + + if (msg_data_left(msg) || (msg->msg_flags & MSG_MORE)) + err = crypto_ahash_update(&ctx->req); + else + err = crypto_ahash_finup(&ctx->req); + continuing = true; } - err = crypto_ahash_update(&ctx->req); - } - - err = crypto_wait_req(err, &ctx->wait); - if (err) - goto unlock; + err = crypto_wait_req(err, &ctx->wait); + if (err) + goto unlock_free; - ctx->more = flags & MSG_MORE; + copied += len; + af_alg_free_sg(&ctx->sgl); + } +done_more: + ctx->more = msg->msg_flags & MSG_MORE; +done: + err = 0; unlock: release_sock(sk); + return copied ?: err; - return err ?: size; +unlock_free: + af_alg_free_sg(&ctx->sgl); + hash_free_result(sk, ctx); + ctx->more = false; + goto unlock; } static int hash_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, @@ -296,7 +290,6 @@ static struct proto_ops algif_hash_ops = { .release = af_alg_release, .sendmsg = hash_sendmsg, - .sendpage = hash_sendpage, .recvmsg = hash_recvmsg, .accept = hash_accept, }; @@ -348,18 +341,6 @@ static int hash_sendmsg_nokey(struct socket *sock, struct msghdr *msg, return hash_sendmsg(sock, msg, size); } -static ssize_t hash_sendpage_nokey(struct socket *sock, struct page *page, - int offset, size_t size, int flags) -{ - int err; - - err = hash_check_key(sock); - if (err) - return err; - - return hash_sendpage(sock, page, offset, size, flags); -} - static int hash_recvmsg_nokey(struct socket *sock, struct msghdr *msg, size_t ignored, int flags) { @@ -398,7 +379,6 @@ static struct proto_ops algif_hash_ops_nokey = { .release = af_alg_release, .sendmsg = hash_sendmsg_nokey, - .sendpage = hash_sendpage_nokey, .recvmsg = hash_recvmsg_nokey, .accept = hash_accept_nokey, }; diff --git a/crypto/algif_rng.c b/crypto/algif_rng.c index 407408c437308f9d27eb0031da0fb16a4c8bf2a6..10c41adac3b1f3574494ad71ce65f6e4db383997 100644 --- a/crypto/algif_rng.c +++ b/crypto/algif_rng.c @@ -174,7 +174,6 @@ static struct proto_ops algif_rng_ops = { .bind = sock_no_bind, .accept = sock_no_accept, .sendmsg = sock_no_sendmsg, - .sendpage = sock_no_sendpage, .release = af_alg_release, .recvmsg = rng_recvmsg, @@ -192,7 +191,6 @@ static struct proto_ops __maybe_unused algif_rng_test_ops = { .mmap = sock_no_mmap, .bind = sock_no_bind, .accept = sock_no_accept, - .sendpage = sock_no_sendpage, .release = af_alg_release, .recvmsg = rng_test_recvmsg, diff --git a/crypto/algif_skcipher.c b/crypto/algif_skcipher.c index ee8890ee8f33294d9fa3d277255c5c05e4936f90..9ada9b741af8dc99e62c165a1d469123ebe8183d 100644 --- a/crypto/algif_skcipher.c +++ b/crypto/algif_skcipher.c @@ -9,10 +9,10 @@ * The following concept of the memory management is used: * * The kernel maintains two SGLs, the TX SGL and the RX SGL. The TX SGL is - * filled by user space with the data submitted via sendpage/sendmsg. Filling - * up the TX SGL does not cause a crypto operation -- the data will only be - * tracked by the kernel. Upon receipt of one recvmsg call, the caller must - * provide a buffer which is tracked with the RX SGL. + * filled by user space with the data submitted via sendmsg. Filling up the TX + * SGL does not cause a crypto operation -- the data will only be tracked by + * the kernel. Upon receipt of one recvmsg call, the caller must provide a + * buffer which is tracked with the RX SGL. * * During the processing of the recvmsg operation, the cipher request is * allocated and prepared. As part of the recvmsg operation, the processed @@ -105,7 +105,7 @@ static int _skcipher_recvmsg(struct socket *sock, struct msghdr *msg, /* Initialize the crypto operation */ skcipher_request_set_tfm(&areq->cra_u.skcipher_req, tfm); skcipher_request_set_crypt(&areq->cra_u.skcipher_req, areq->tsgl, - areq->first_rsgl.sgl.sg, len, ctx->iv); + areq->first_rsgl.sgl.sgt.sgl, len, ctx->iv); if (msg->msg_iocb && !is_sync_kiocb(msg->msg_iocb)) { /* AIO operation */ @@ -194,7 +194,6 @@ static struct proto_ops algif_skcipher_ops = { .release = af_alg_release, .sendmsg = skcipher_sendmsg, - .sendpage = af_alg_sendpage, .recvmsg = skcipher_recvmsg, .poll = af_alg_poll, }; @@ -246,18 +245,6 @@ static int skcipher_sendmsg_nokey(struct socket *sock, struct msghdr *msg, return skcipher_sendmsg(sock, msg, size); } -static ssize_t skcipher_sendpage_nokey(struct socket *sock, struct page *page, - int offset, size_t size, int flags) -{ - int err; - - err = skcipher_check_key(sock); - if (err) - return err; - - return af_alg_sendpage(sock, page, offset, size, flags); -} - static int skcipher_recvmsg_nokey(struct socket *sock, struct msghdr *msg, size_t ignored, int flags) { @@ -285,7 +272,6 @@ static struct proto_ops algif_skcipher_ops_nokey = { .release = af_alg_release, .sendmsg = skcipher_sendmsg_nokey, - .sendpage = skcipher_sendpage_nokey, .recvmsg = skcipher_recvmsg_nokey, .poll = af_alg_poll, }; diff --git a/crypto/api.c b/crypto/api.c index d375e8cd770d17db043c61c6601aaa9cf8e1d73d..b9cc0c906efe0706fadb8ba9629ac09e652dd99c 100644 --- a/crypto/api.c +++ b/crypto/api.c @@ -345,15 +345,6 @@ struct crypto_alg *crypto_alg_mod_lookup(const char *name, u32 type, u32 mask) } EXPORT_SYMBOL_GPL(crypto_alg_mod_lookup); -static int crypto_init_ops(struct crypto_tfm *tfm, u32 type, u32 mask) -{ - const struct crypto_type *type_obj = tfm->__crt_alg->cra_type; - - if (type_obj) - return type_obj->init(tfm, type, mask); - return 0; -} - static void crypto_exit_ops(struct crypto_tfm *tfm) { const struct crypto_type *type = tfm->__crt_alg->cra_type; @@ -395,25 +386,21 @@ void crypto_shoot_alg(struct crypto_alg *alg) } EXPORT_SYMBOL_GPL(crypto_shoot_alg); -struct crypto_tfm *__crypto_alloc_tfm(struct crypto_alg *alg, u32 type, - u32 mask) +struct crypto_tfm *__crypto_alloc_tfmgfp(struct crypto_alg *alg, u32 type, + u32 mask, gfp_t gfp) { struct crypto_tfm *tfm = NULL; unsigned int tfm_size; int err = -ENOMEM; tfm_size = sizeof(*tfm) + crypto_ctxsize(alg, type, mask); - tfm = kzalloc(tfm_size, GFP_KERNEL); + tfm = kzalloc(tfm_size, gfp); if (tfm == NULL) goto out_err; tfm->__crt_alg = alg; refcount_set(&tfm->refcnt, 1); - err = crypto_init_ops(tfm, type, mask); - if (err) - goto out_free_tfm; - if (!tfm->exit && alg->cra_init && (err = alg->cra_init(tfm))) goto cra_init_failed; @@ -421,7 +408,6 @@ struct crypto_tfm *__crypto_alloc_tfm(struct crypto_alg *alg, u32 type, cra_init_failed: crypto_exit_ops(tfm); -out_free_tfm: if (err == -EAGAIN) crypto_shoot_alg(alg); kfree(tfm); @@ -430,6 +416,13 @@ struct crypto_tfm *__crypto_alloc_tfm(struct crypto_alg *alg, u32 type, out: return tfm; } +EXPORT_SYMBOL_GPL(__crypto_alloc_tfmgfp); + +struct crypto_tfm *__crypto_alloc_tfm(struct crypto_alg *alg, u32 type, + u32 mask) +{ + return __crypto_alloc_tfmgfp(alg, type, mask, GFP_KERNEL); +} EXPORT_SYMBOL_GPL(__crypto_alloc_tfm); /* diff --git a/crypto/asymmetric_keys/public_key.c b/crypto/asymmetric_keys/public_key.c index 50c933f86b218cca0ffe07756272dadbcf9854a2..773e159dbbcb83963716338198b26def04bc959d 100644 --- a/crypto/asymmetric_keys/public_key.c +++ b/crypto/asymmetric_keys/public_key.c @@ -8,18 +8,17 @@ */ #define pr_fmt(fmt) "PKEY: "fmt -#include -#include +#include +#include +#include +#include +#include +#include #include -#include +#include #include -#include -#include -#include -#include -#include -#include -#include +#include +#include MODULE_DESCRIPTION("In-software asymmetric public-key subtype"); MODULE_AUTHOR("Red Hat, Inc."); @@ -67,10 +66,13 @@ static void public_key_destroy(void *payload0, void *payload3) static int software_key_determine_akcipher(const struct public_key *pkey, const char *encoding, const char *hash_algo, - char alg_name[CRYPTO_MAX_ALG_NAME]) + char alg_name[CRYPTO_MAX_ALG_NAME], bool *sig, + enum kernel_pkey_operation op) { int n; + *sig = true; + if (!encoding) return -EINVAL; @@ -79,14 +81,18 @@ software_key_determine_akcipher(const struct public_key *pkey, * RSA signatures usually use EMSA-PKCS1-1_5 [RFC3447 sec 8.2]. */ if (strcmp(encoding, "pkcs1") == 0) { - if (!hash_algo) + if (!hash_algo) { + *sig = false; n = snprintf(alg_name, CRYPTO_MAX_ALG_NAME, "pkcs1pad(%s)", pkey->pkey_algo); - else + } else { + *sig = op == kernel_pkey_sign || + op == kernel_pkey_verify; n = snprintf(alg_name, CRYPTO_MAX_ALG_NAME, "pkcs1pad(%s,%s)", pkey->pkey_algo, hash_algo); + } return n >= CRYPTO_MAX_ALG_NAME ? -EINVAL : 0; } if (strcmp(encoding, "raw") != 0) @@ -97,6 +103,7 @@ software_key_determine_akcipher(const struct public_key *pkey, */ if (hash_algo) return -EINVAL; + *sig = false; } else if (strncmp(pkey->pkey_algo, "ecdsa", 5) == 0) { if (strcmp(encoding, "x962") != 0) return -EINVAL; @@ -154,37 +161,74 @@ static int software_key_query(const struct kernel_pkey_params *params, struct crypto_akcipher *tfm; struct public_key *pkey = params->key->payload.data[asym_crypto]; char alg_name[CRYPTO_MAX_ALG_NAME]; + struct crypto_sig *sig; u8 *key, *ptr; int ret, len; + bool issig; ret = software_key_determine_akcipher(pkey, params->encoding, - params->hash_algo, alg_name); + params->hash_algo, alg_name, + &issig, kernel_pkey_sign); if (ret < 0) return ret; - tfm = crypto_alloc_akcipher(alg_name, 0, 0); - if (IS_ERR(tfm)) - return PTR_ERR(tfm); - - ret = -ENOMEM; key = kmalloc(pkey->keylen + sizeof(u32) * 2 + pkey->paramlen, GFP_KERNEL); if (!key) - goto error_free_tfm; + return -ENOMEM; + memcpy(key, pkey->key, pkey->keylen); ptr = key + pkey->keylen; ptr = pkey_pack_u32(ptr, pkey->algo); ptr = pkey_pack_u32(ptr, pkey->paramlen); memcpy(ptr, pkey->params, pkey->paramlen); - if (pkey->key_is_private) - ret = crypto_akcipher_set_priv_key(tfm, key, pkey->keylen); - else - ret = crypto_akcipher_set_pub_key(tfm, key, pkey->keylen); - if (ret < 0) - goto error_free_key; + if (issig) { + sig = crypto_alloc_sig(alg_name, 0, 0); + if (IS_ERR(sig)) { + ret = PTR_ERR(sig); + goto error_free_key; + } + + if (pkey->key_is_private) + ret = crypto_sig_set_privkey(sig, key, pkey->keylen); + else + ret = crypto_sig_set_pubkey(sig, key, pkey->keylen); + if (ret < 0) + goto error_free_tfm; + + len = crypto_sig_maxsize(sig); + + info->supported_ops = KEYCTL_SUPPORTS_VERIFY; + if (pkey->key_is_private) + info->supported_ops |= KEYCTL_SUPPORTS_SIGN; + + if (strcmp(params->encoding, "pkcs1") == 0) { + info->supported_ops |= KEYCTL_SUPPORTS_ENCRYPT; + if (pkey->key_is_private) + info->supported_ops |= KEYCTL_SUPPORTS_DECRYPT; + } + } else { + tfm = crypto_alloc_akcipher(alg_name, 0, 0); + if (IS_ERR(tfm)) { + ret = PTR_ERR(tfm); + goto error_free_key; + } + + if (pkey->key_is_private) + ret = crypto_akcipher_set_priv_key(tfm, key, pkey->keylen); + else + ret = crypto_akcipher_set_pub_key(tfm, key, pkey->keylen); + if (ret < 0) + goto error_free_tfm; + + len = crypto_akcipher_maxsize(tfm); + + info->supported_ops = KEYCTL_SUPPORTS_ENCRYPT; + if (pkey->key_is_private) + info->supported_ops |= KEYCTL_SUPPORTS_DECRYPT; + } - len = crypto_akcipher_maxsize(tfm); info->key_size = len * 8; if (strncmp(pkey->pkey_algo, "ecdsa", 5) == 0) { @@ -210,17 +254,16 @@ static int software_key_query(const struct kernel_pkey_params *params, info->max_enc_size = len; info->max_dec_size = len; - info->supported_ops = (KEYCTL_SUPPORTS_ENCRYPT | - KEYCTL_SUPPORTS_VERIFY); - if (pkey->key_is_private) - info->supported_ops |= (KEYCTL_SUPPORTS_DECRYPT | - KEYCTL_SUPPORTS_SIGN); + ret = 0; +error_free_tfm: + if (issig) + crypto_free_sig(sig); + else + crypto_free_akcipher(tfm); error_free_key: kfree(key); -error_free_tfm: - crypto_free_akcipher(tfm); pr_devel("<==%s() = %d\n", __func__, ret); return ret; } @@ -232,34 +275,26 @@ static int software_key_eds_op(struct kernel_pkey_params *params, const void *in, void *out) { const struct public_key *pkey = params->key->payload.data[asym_crypto]; - struct akcipher_request *req; - struct crypto_akcipher *tfm; - struct crypto_wait cwait; - struct scatterlist in_sg, out_sg; char alg_name[CRYPTO_MAX_ALG_NAME]; + struct crypto_akcipher *tfm; + struct crypto_sig *sig; char *key, *ptr; + bool issig; + int ksz; int ret; pr_devel("==>%s()\n", __func__); ret = software_key_determine_akcipher(pkey, params->encoding, - params->hash_algo, alg_name); + params->hash_algo, alg_name, + &issig, params->op); if (ret < 0) return ret; - tfm = crypto_alloc_akcipher(alg_name, 0, 0); - if (IS_ERR(tfm)) - return PTR_ERR(tfm); - - ret = -ENOMEM; - req = akcipher_request_alloc(tfm, GFP_KERNEL); - if (!req) - goto error_free_tfm; - key = kmalloc(pkey->keylen + sizeof(u32) * 2 + pkey->paramlen, GFP_KERNEL); if (!key) - goto error_free_req; + return -ENOMEM; memcpy(key, pkey->key, pkey->keylen); ptr = key + pkey->keylen; @@ -267,123 +302,88 @@ static int software_key_eds_op(struct kernel_pkey_params *params, ptr = pkey_pack_u32(ptr, pkey->paramlen); memcpy(ptr, pkey->params, pkey->paramlen); - if (pkey->key_is_private) - ret = crypto_akcipher_set_priv_key(tfm, key, pkey->keylen); - else - ret = crypto_akcipher_set_pub_key(tfm, key, pkey->keylen); - if (ret) - goto error_free_key; + if (issig) { + sig = crypto_alloc_sig(alg_name, 0, 0); + if (IS_ERR(sig)) { + ret = PTR_ERR(sig); + goto error_free_key; + } + + if (pkey->key_is_private) + ret = crypto_sig_set_privkey(sig, key, pkey->keylen); + else + ret = crypto_sig_set_pubkey(sig, key, pkey->keylen); + if (ret) + goto error_free_tfm; - sg_init_one(&in_sg, in, params->in_len); - sg_init_one(&out_sg, out, params->out_len); - akcipher_request_set_crypt(req, &in_sg, &out_sg, params->in_len, - params->out_len); - crypto_init_wait(&cwait); - akcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG | - CRYPTO_TFM_REQ_MAY_SLEEP, - crypto_req_done, &cwait); + ksz = crypto_sig_maxsize(sig); + } else { + tfm = crypto_alloc_akcipher(alg_name, 0, 0); + if (IS_ERR(tfm)) { + ret = PTR_ERR(tfm); + goto error_free_key; + } + + if (pkey->key_is_private) + ret = crypto_akcipher_set_priv_key(tfm, key, pkey->keylen); + else + ret = crypto_akcipher_set_pub_key(tfm, key, pkey->keylen); + if (ret) + goto error_free_tfm; + + ksz = crypto_akcipher_maxsize(tfm); + } + + ret = -EINVAL; /* Perform the encryption calculation. */ switch (params->op) { case kernel_pkey_encrypt: - ret = crypto_akcipher_encrypt(req); + if (issig) + break; + ret = crypto_akcipher_sync_encrypt(tfm, in, params->in_len, + out, params->out_len); break; case kernel_pkey_decrypt: - ret = crypto_akcipher_decrypt(req); + if (issig) + break; + ret = crypto_akcipher_sync_decrypt(tfm, in, params->in_len, + out, params->out_len); break; case kernel_pkey_sign: - ret = crypto_akcipher_sign(req); + if (!issig) + break; + ret = crypto_sig_sign(sig, in, params->in_len, + out, params->out_len); break; default: BUG(); } - ret = crypto_wait_req(ret, &cwait); if (ret == 0) - ret = req->dst_len; + ret = ksz; +error_free_tfm: + if (issig) + crypto_free_sig(sig); + else + crypto_free_akcipher(tfm); error_free_key: kfree(key); -error_free_req: - akcipher_request_free(req); -error_free_tfm: - crypto_free_akcipher(tfm); pr_devel("<==%s() = %d\n", __func__, ret); return ret; } -#if IS_REACHABLE(CONFIG_CRYPTO_SM2) -static int cert_sig_digest_update(const struct public_key_signature *sig, - struct crypto_akcipher *tfm_pkey) -{ - struct crypto_shash *tfm; - struct shash_desc *desc; - size_t desc_size; - unsigned char dgst[SM3_DIGEST_SIZE]; - int ret; - - BUG_ON(!sig->data); - - /* SM2 signatures always use the SM3 hash algorithm */ - if (!sig->hash_algo || strcmp(sig->hash_algo, "sm3") != 0) - return -EINVAL; - - ret = sm2_compute_z_digest(tfm_pkey, SM2_DEFAULT_USERID, - SM2_DEFAULT_USERID_LEN, dgst); - if (ret) - return ret; - - tfm = crypto_alloc_shash(sig->hash_algo, 0, 0); - if (IS_ERR(tfm)) - return PTR_ERR(tfm); - - desc_size = crypto_shash_descsize(tfm) + sizeof(*desc); - desc = kzalloc(desc_size, GFP_KERNEL); - if (!desc) { - ret = -ENOMEM; - goto error_free_tfm; - } - - desc->tfm = tfm; - - ret = crypto_shash_init(desc); - if (ret < 0) - goto error_free_desc; - - ret = crypto_shash_update(desc, dgst, SM3_DIGEST_SIZE); - if (ret < 0) - goto error_free_desc; - - ret = crypto_shash_finup(desc, sig->data, sig->data_size, sig->digest); - -error_free_desc: - kfree(desc); -error_free_tfm: - crypto_free_shash(tfm); - return ret; -} -#else -static inline int cert_sig_digest_update( - const struct public_key_signature *sig, - struct crypto_akcipher *tfm_pkey) -{ - return -ENOTSUPP; -} -#endif /* ! IS_REACHABLE(CONFIG_CRYPTO_SM2) */ - /* * Verify a signature using a public key. */ int public_key_verify_signature(const struct public_key *pkey, const struct public_key_signature *sig) { - struct crypto_wait cwait; - struct crypto_akcipher *tfm; - struct akcipher_request *req; - struct scatterlist src_sg; char alg_name[CRYPTO_MAX_ALG_NAME]; - char *buf, *ptr; - size_t buf_len; + struct crypto_sig *tfm; + char *key, *ptr; + bool issig; int ret; pr_devel("==>%s()\n", __func__); @@ -408,63 +408,42 @@ int public_key_verify_signature(const struct public_key *pkey, } ret = software_key_determine_akcipher(pkey, sig->encoding, - sig->hash_algo, alg_name); + sig->hash_algo, alg_name, + &issig, kernel_pkey_verify); if (ret < 0) return ret; - tfm = crypto_alloc_akcipher(alg_name, 0, 0); + tfm = crypto_alloc_sig(alg_name, 0, 0); if (IS_ERR(tfm)) return PTR_ERR(tfm); - ret = -ENOMEM; - req = akcipher_request_alloc(tfm, GFP_KERNEL); - if (!req) + key = kmalloc(pkey->keylen + sizeof(u32) * 2 + pkey->paramlen, + GFP_KERNEL); + if (!key) { + ret = -ENOMEM; goto error_free_tfm; + } - buf_len = max_t(size_t, pkey->keylen + sizeof(u32) * 2 + pkey->paramlen, - sig->s_size + sig->digest_size); - - buf = kmalloc(buf_len, GFP_KERNEL); - if (!buf) - goto error_free_req; - - memcpy(buf, pkey->key, pkey->keylen); - ptr = buf + pkey->keylen; + memcpy(key, pkey->key, pkey->keylen); + ptr = key + pkey->keylen; ptr = pkey_pack_u32(ptr, pkey->algo); ptr = pkey_pack_u32(ptr, pkey->paramlen); memcpy(ptr, pkey->params, pkey->paramlen); if (pkey->key_is_private) - ret = crypto_akcipher_set_priv_key(tfm, buf, pkey->keylen); + ret = crypto_sig_set_privkey(tfm, key, pkey->keylen); else - ret = crypto_akcipher_set_pub_key(tfm, buf, pkey->keylen); + ret = crypto_sig_set_pubkey(tfm, key, pkey->keylen); if (ret) - goto error_free_buf; + goto error_free_key; - if (strcmp(pkey->pkey_algo, "sm2") == 0 && sig->data_size) { - ret = cert_sig_digest_update(sig, tfm); - if (ret) - goto error_free_buf; - } + ret = crypto_sig_verify(tfm, sig->s, sig->s_size, + sig->digest, sig->digest_size); - memcpy(buf, sig->s, sig->s_size); - memcpy(buf + sig->s_size, sig->digest, sig->digest_size); - - sg_init_one(&src_sg, buf, sig->s_size + sig->digest_size); - akcipher_request_set_crypt(req, &src_sg, NULL, sig->s_size, - sig->digest_size); - crypto_init_wait(&cwait); - akcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG | - CRYPTO_TFM_REQ_MAY_SLEEP, - crypto_req_done, &cwait); - ret = crypto_wait_req(crypto_akcipher_verify(req), &cwait); - -error_free_buf: - kfree(buf); -error_free_req: - akcipher_request_free(req); +error_free_key: + kfree(key); error_free_tfm: - crypto_free_akcipher(tfm); + crypto_free_sig(tfm); pr_devel("<==%s() = %d\n", __func__, ret); if (WARN_ON_ONCE(ret > 0)) ret = -EINVAL; diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c index 0b4943a4592b7f9e2b4c69a2f249cc4ae5dfe103..6fdfc82e23a8afac7061f9947e194f5638a3096f 100644 --- a/crypto/asymmetric_keys/x509_public_key.c +++ b/crypto/asymmetric_keys/x509_public_key.c @@ -6,13 +6,15 @@ */ #define pr_fmt(fmt) "X.509: "fmt +#include +#include +#include +#include +#include #include #include #include -#include -#include -#include -#include +#include #include "asymmetric_keys.h" #include "x509_parser.h" @@ -30,9 +32,6 @@ int x509_get_sig_params(struct x509_certificate *cert) pr_devel("==>%s()\n", __func__); - sig->data = cert->tbs; - sig->data_size = cert->tbs_size; - sig->s = kmemdup(cert->raw_sig, cert->raw_sig_size, GFP_KERNEL); if (!sig->s) return -ENOMEM; @@ -65,7 +64,21 @@ int x509_get_sig_params(struct x509_certificate *cert) desc->tfm = tfm; - ret = crypto_shash_digest(desc, cert->tbs, cert->tbs_size, sig->digest); + if (strcmp(cert->pub->pkey_algo, "sm2") == 0) { + ret = strcmp(sig->hash_algo, "sm3") != 0 ? -EINVAL : + crypto_shash_init(desc) ?: + sm2_compute_z_digest(desc, cert->pub->key, + cert->pub->keylen, sig->digest) ?: + crypto_shash_init(desc) ?: + crypto_shash_update(desc, sig->digest, + sig->digest_size) ?: + crypto_shash_finup(desc, cert->tbs, cert->tbs_size, + sig->digest); + } else { + ret = crypto_shash_digest(desc, cert->tbs, cert->tbs_size, + sig->digest); + } + if (ret < 0) goto error_2; diff --git a/crypto/cipher.c b/crypto/cipher.c index b47141ed4a9f3da03237847d4cec4f08a50e3840..47c77a3e59783320f22ea7bf4b771b0102f5b73e 100644 --- a/crypto/cipher.c +++ b/crypto/cipher.c @@ -90,3 +90,31 @@ void crypto_cipher_decrypt_one(struct crypto_cipher *tfm, cipher_crypt_one(tfm, dst, src, false); } EXPORT_SYMBOL_NS_GPL(crypto_cipher_decrypt_one, CRYPTO_INTERNAL); + +struct crypto_cipher *crypto_clone_cipher(struct crypto_cipher *cipher) +{ + struct crypto_tfm *tfm = crypto_cipher_tfm(cipher); + struct crypto_alg *alg = tfm->__crt_alg; + struct crypto_cipher *ncipher; + struct crypto_tfm *ntfm; + + if (alg->cra_init) + return ERR_PTR(-ENOSYS); + + if (unlikely(!crypto_mod_get(alg))) + return ERR_PTR(-ESTALE); + + ntfm = __crypto_alloc_tfmgfp(alg, CRYPTO_ALG_TYPE_CIPHER, + CRYPTO_ALG_TYPE_MASK, GFP_ATOMIC); + if (IS_ERR(ntfm)) { + crypto_mod_put(alg); + return ERR_CAST(ntfm); + } + + ntfm->crt_flags = tfm->crt_flags; + + ncipher = __crypto_cipher_cast(ntfm); + + return ncipher; +} +EXPORT_SYMBOL_GPL(crypto_clone_cipher); diff --git a/crypto/cmac.c b/crypto/cmac.c index f4a5d3bfb37624e553b47030d1cee9de4a71e811..fce6b0f58e88e70e513387a9eb1d466b7dac72c1 100644 --- a/crypto/cmac.c +++ b/crypto/cmac.c @@ -198,13 +198,14 @@ static int crypto_cmac_digest_final(struct shash_desc *pdesc, u8 *out) return 0; } -static int cmac_init_tfm(struct crypto_tfm *tfm) +static int cmac_init_tfm(struct crypto_shash *tfm) { + struct shash_instance *inst = shash_alg_instance(tfm); + struct cmac_tfm_ctx *ctx = crypto_shash_ctx(tfm); + struct crypto_cipher_spawn *spawn; struct crypto_cipher *cipher; - struct crypto_instance *inst = (void *)tfm->__crt_alg; - struct crypto_cipher_spawn *spawn = crypto_instance_ctx(inst); - struct cmac_tfm_ctx *ctx = crypto_tfm_ctx(tfm); + spawn = shash_instance_ctx(inst); cipher = crypto_spawn_cipher(spawn); if (IS_ERR(cipher)) return PTR_ERR(cipher); @@ -212,11 +213,26 @@ static int cmac_init_tfm(struct crypto_tfm *tfm) ctx->child = cipher; return 0; -}; +} + +static int cmac_clone_tfm(struct crypto_shash *tfm, struct crypto_shash *otfm) +{ + struct cmac_tfm_ctx *octx = crypto_shash_ctx(otfm); + struct cmac_tfm_ctx *ctx = crypto_shash_ctx(tfm); + struct crypto_cipher *cipher; + + cipher = crypto_clone_cipher(octx->child); + if (IS_ERR(cipher)) + return PTR_ERR(cipher); + + ctx->child = cipher; -static void cmac_exit_tfm(struct crypto_tfm *tfm) + return 0; +} + +static void cmac_exit_tfm(struct crypto_shash *tfm) { - struct cmac_tfm_ctx *ctx = crypto_tfm_ctx(tfm); + struct cmac_tfm_ctx *ctx = crypto_shash_ctx(tfm); crypto_free_cipher(ctx->child); } @@ -274,13 +290,13 @@ static int cmac_create(struct crypto_template *tmpl, struct rtattr **tb) ~(crypto_tfm_ctx_alignment() - 1)) + alg->cra_blocksize * 2; - inst->alg.base.cra_init = cmac_init_tfm; - inst->alg.base.cra_exit = cmac_exit_tfm; - inst->alg.init = crypto_cmac_digest_init; inst->alg.update = crypto_cmac_digest_update; inst->alg.final = crypto_cmac_digest_final; inst->alg.setkey = crypto_cmac_digest_setkey; + inst->alg.init_tfm = cmac_init_tfm; + inst->alg.clone_tfm = cmac_clone_tfm; + inst->alg.exit_tfm = cmac_exit_tfm; inst->free = shash_free_singlespawn_instance; diff --git a/crypto/hmac.c b/crypto/hmac.c index 09a7872b406003aa7c6ab14e3b1e7564c934b7f8..ea93f4c55f251bd96aca41046b62eaca611739a5 100644 --- a/crypto/hmac.c +++ b/crypto/hmac.c @@ -177,6 +177,7 @@ static int hmac_clone_tfm(struct crypto_shash *dst, struct crypto_shash *src) static void hmac_exit_tfm(struct crypto_shash *parent) { struct hmac_ctx *ctx = hmac_ctx(parent); + crypto_free_shash(ctx->hash); } diff --git a/crypto/internal.h b/crypto/internal.h index 8dd746b1130b6ef588665bee1ceeb9566efd4c5f..63e59240d5fbf4fb17d7ce1bd87009a0519c8643 100644 --- a/crypto/internal.h +++ b/crypto/internal.h @@ -18,9 +18,12 @@ #include #include #include +#include #include #include +struct akcipher_request; +struct crypto_akcipher; struct crypto_instance; struct crypto_template; @@ -32,6 +35,19 @@ struct crypto_larval { bool test_started; }; +struct crypto_akcipher_sync_data { + struct crypto_akcipher *tfm; + const void *src; + void *dst; + unsigned int slen; + unsigned int dlen; + + struct akcipher_request *req; + struct crypto_wait cwait; + struct scatterlist sg; + u8 *buf; +}; + enum { CRYPTOA_UNSPEC, CRYPTOA_ALG, @@ -102,6 +118,8 @@ void crypto_remove_spawns(struct crypto_alg *alg, struct list_head *list, struct crypto_alg *nalg); void crypto_remove_final(struct list_head *list); void crypto_shoot_alg(struct crypto_alg *alg); +struct crypto_tfm *__crypto_alloc_tfmgfp(struct crypto_alg *alg, u32 type, + u32 mask, gfp_t gfp); struct crypto_tfm *__crypto_alloc_tfm(struct crypto_alg *alg, u32 type, u32 mask); void *crypto_create_tfm_node(struct crypto_alg *alg, @@ -109,6 +127,10 @@ void *crypto_create_tfm_node(struct crypto_alg *alg, void *crypto_clone_tfm(const struct crypto_type *frontend, struct crypto_tfm *otfm); +int crypto_akcipher_sync_prep(struct crypto_akcipher_sync_data *data); +int crypto_akcipher_sync_post(struct crypto_akcipher_sync_data *data, int err); +int crypto_init_akcipher_ops_sig(struct crypto_tfm *tfm); + static inline void *crypto_create_tfm(struct crypto_alg *alg, const struct crypto_type *frontend) { diff --git a/crypto/jitterentropy-kcapi.c b/crypto/jitterentropy-kcapi.c index b9edfaa51b2732caf8d429f726a3c4820f1935d7..7d1463a1562acbe7493b51c71e07d040eeb2301b 100644 --- a/crypto/jitterentropy-kcapi.c +++ b/crypto/jitterentropy-kcapi.c @@ -2,7 +2,7 @@ * Non-physical true random number generator based on timing jitter -- * Linux Kernel Crypto API specific code * - * Copyright Stephan Mueller , 2015 + * Copyright Stephan Mueller , 2015 - 2023 * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -37,6 +37,8 @@ * DAMAGE. */ +#include +#include #include #include #include @@ -46,6 +48,8 @@ #include "jitterentropy.h" +#define JENT_CONDITIONING_HASH "sha3-256-generic" + /*************************************************************************** * Helper function ***************************************************************************/ @@ -60,11 +64,6 @@ void jent_zfree(void *ptr) kfree_sensitive(ptr); } -void jent_memcpy(void *dest, const void *src, unsigned int n) -{ - memcpy(dest, src, n); -} - /* * Obtain a high-resolution time stamp value. The time stamp is used to measure * the execution time of a given code path and its variations. Hence, the time @@ -89,6 +88,92 @@ void jent_get_nstime(__u64 *out) tmp = ktime_get_ns(); *out = tmp; + jent_raw_hires_entropy_store(tmp); +} + +int jent_hash_time(void *hash_state, __u64 time, u8 *addtl, + unsigned int addtl_len, __u64 hash_loop_cnt, + unsigned int stuck) +{ + struct shash_desc *hash_state_desc = (struct shash_desc *)hash_state; + SHASH_DESC_ON_STACK(desc, hash_state_desc->tfm); + u8 intermediary[SHA3_256_DIGEST_SIZE]; + __u64 j = 0; + int ret; + + desc->tfm = hash_state_desc->tfm; + + if (sizeof(intermediary) != crypto_shash_digestsize(desc->tfm)) { + pr_warn_ratelimited("Unexpected digest size\n"); + return -EINVAL; + } + + /* + * This loop fills a buffer which is injected into the entropy pool. + * The main reason for this loop is to execute something over which we + * can perform a timing measurement. The injection of the resulting + * data into the pool is performed to ensure the result is used and + * the compiler cannot optimize the loop away in case the result is not + * used at all. Yet that data is considered "additional information" + * considering the terminology from SP800-90A without any entropy. + * + * Note, it does not matter which or how much data you inject, we are + * interested in one Keccack1600 compression operation performed with + * the crypto_shash_final. + */ + for (j = 0; j < hash_loop_cnt; j++) { + ret = crypto_shash_init(desc) ?: + crypto_shash_update(desc, intermediary, + sizeof(intermediary)) ?: + crypto_shash_finup(desc, addtl, addtl_len, intermediary); + if (ret) + goto err; + } + + /* + * Inject the data from the previous loop into the pool. This data is + * not considered to contain any entropy, but it stirs the pool a bit. + */ + ret = crypto_shash_update(desc, intermediary, sizeof(intermediary)); + if (ret) + goto err; + + /* + * Insert the time stamp into the hash context representing the pool. + * + * If the time stamp is stuck, do not finally insert the value into the + * entropy pool. Although this operation should not do any harm even + * when the time stamp has no entropy, SP800-90B requires that any + * conditioning operation to have an identical amount of input data + * according to section 3.1.5. + */ + if (!stuck) { + ret = crypto_shash_update(hash_state_desc, (u8 *)&time, + sizeof(__u64)); + } + +err: + shash_desc_zero(desc); + memzero_explicit(intermediary, sizeof(intermediary)); + + return ret; +} + +int jent_read_random_block(void *hash_state, char *dst, unsigned int dst_len) +{ + struct shash_desc *hash_state_desc = (struct shash_desc *)hash_state; + u8 jent_block[SHA3_256_DIGEST_SIZE]; + /* Obtain data from entropy pool and re-initialize it */ + int ret = crypto_shash_final(hash_state_desc, jent_block) ?: + crypto_shash_init(hash_state_desc) ?: + crypto_shash_update(hash_state_desc, jent_block, + sizeof(jent_block)); + + if (!ret && dst_len) + memcpy(dst, jent_block, dst_len); + + memzero_explicit(jent_block, sizeof(jent_block)); + return ret; } /*************************************************************************** @@ -98,32 +183,82 @@ void jent_get_nstime(__u64 *out) struct jitterentropy { spinlock_t jent_lock; struct rand_data *entropy_collector; + struct crypto_shash *tfm; + struct shash_desc *sdesc; }; -static int jent_kcapi_init(struct crypto_tfm *tfm) +static void jent_kcapi_cleanup(struct crypto_tfm *tfm) { struct jitterentropy *rng = crypto_tfm_ctx(tfm); - int ret = 0; - rng->entropy_collector = jent_entropy_collector_alloc(1, 0); - if (!rng->entropy_collector) - ret = -ENOMEM; + spin_lock(&rng->jent_lock); - spin_lock_init(&rng->jent_lock); - return ret; -} + if (rng->sdesc) { + shash_desc_zero(rng->sdesc); + kfree(rng->sdesc); + } + rng->sdesc = NULL; -static void jent_kcapi_cleanup(struct crypto_tfm *tfm) -{ - struct jitterentropy *rng = crypto_tfm_ctx(tfm); + if (rng->tfm) + crypto_free_shash(rng->tfm); + rng->tfm = NULL; - spin_lock(&rng->jent_lock); if (rng->entropy_collector) jent_entropy_collector_free(rng->entropy_collector); rng->entropy_collector = NULL; spin_unlock(&rng->jent_lock); } +static int jent_kcapi_init(struct crypto_tfm *tfm) +{ + struct jitterentropy *rng = crypto_tfm_ctx(tfm); + struct crypto_shash *hash; + struct shash_desc *sdesc; + int size, ret = 0; + + spin_lock_init(&rng->jent_lock); + + /* + * Use SHA3-256 as conditioner. We allocate only the generic + * implementation as we are not interested in high-performance. The + * execution time of the SHA3 operation is measured and adds to the + * Jitter RNG's unpredictable behavior. If we have a slower hash + * implementation, the execution timing variations are larger. When + * using a fast implementation, we would need to call it more often + * as its variations are lower. + */ + hash = crypto_alloc_shash(JENT_CONDITIONING_HASH, 0, 0); + if (IS_ERR(hash)) { + pr_err("Cannot allocate conditioning digest\n"); + return PTR_ERR(hash); + } + rng->tfm = hash; + + size = sizeof(struct shash_desc) + crypto_shash_descsize(hash); + sdesc = kmalloc(size, GFP_KERNEL); + if (!sdesc) { + ret = -ENOMEM; + goto err; + } + + sdesc->tfm = hash; + crypto_shash_init(sdesc); + rng->sdesc = sdesc; + + rng->entropy_collector = jent_entropy_collector_alloc(1, 0, sdesc); + if (!rng->entropy_collector) { + ret = -ENOMEM; + goto err; + } + + spin_lock_init(&rng->jent_lock); + return 0; + +err: + jent_kcapi_cleanup(tfm); + return ret; +} + static int jent_kcapi_random(struct crypto_rng *tfm, const u8 *src, unsigned int slen, u8 *rdata, unsigned int dlen) @@ -180,20 +315,34 @@ static struct rng_alg jent_alg = { .cra_module = THIS_MODULE, .cra_init = jent_kcapi_init, .cra_exit = jent_kcapi_cleanup, - } }; static int __init jent_mod_init(void) { + SHASH_DESC_ON_STACK(desc, tfm); + struct crypto_shash *tfm; int ret = 0; - ret = jent_entropy_init(); + jent_testing_init(); + + tfm = crypto_alloc_shash(JENT_CONDITIONING_HASH, 0, 0); + if (IS_ERR(tfm)) { + jent_testing_exit(); + return PTR_ERR(tfm); + } + + desc->tfm = tfm; + crypto_shash_init(desc); + ret = jent_entropy_init(desc); + shash_desc_zero(desc); + crypto_free_shash(tfm); if (ret) { /* Handle permanent health test error */ if (fips_enabled) panic("jitterentropy: Initialization failed with host not compliant with requirements: %d\n", ret); + jent_testing_exit(); pr_info("jitterentropy: Initialization failed with host not compliant with requirements: %d\n", ret); return -EFAULT; } @@ -202,6 +351,7 @@ static int __init jent_mod_init(void) static void __exit jent_mod_exit(void) { + jent_testing_exit(); crypto_unregister_rng(&jent_alg); } diff --git a/crypto/jitterentropy-testing.c b/crypto/jitterentropy-testing.c new file mode 100644 index 0000000000000000000000000000000000000000..5cb6a77b8e3b2ad0ed3a3ad373b04f700675145f --- /dev/null +++ b/crypto/jitterentropy-testing.c @@ -0,0 +1,294 @@ +/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */ +/* + * Test interface for Jitter RNG. + * + * Copyright (C) 2023, Stephan Mueller + */ + +#include +#include +#include + +#include "jitterentropy.h" + +#define JENT_TEST_RINGBUFFER_SIZE (1<<10) +#define JENT_TEST_RINGBUFFER_MASK (JENT_TEST_RINGBUFFER_SIZE - 1) + +struct jent_testing { + u32 jent_testing_rb[JENT_TEST_RINGBUFFER_SIZE]; + u32 rb_reader; + atomic_t rb_writer; + atomic_t jent_testing_enabled; + spinlock_t lock; + wait_queue_head_t read_wait; +}; + +static struct dentry *jent_raw_debugfs_root = NULL; + +/*************************** Generic Data Handling ****************************/ + +/* + * boot variable: + * 0 ==> No boot test, gathering of runtime data allowed + * 1 ==> Boot test enabled and ready for collecting data, gathering runtime + * data is disabled + * 2 ==> Boot test completed and disabled, gathering of runtime data is + * disabled + */ + +static void jent_testing_reset(struct jent_testing *data) +{ + unsigned long flags; + + spin_lock_irqsave(&data->lock, flags); + data->rb_reader = 0; + atomic_set(&data->rb_writer, 0); + spin_unlock_irqrestore(&data->lock, flags); +} + +static void jent_testing_data_init(struct jent_testing *data, u32 boot) +{ + /* + * The boot time testing implies we have a running test. If the + * caller wants to clear it, he has to unset the boot_test flag + * at runtime via sysfs to enable regular runtime testing + */ + if (boot) + return; + + jent_testing_reset(data); + atomic_set(&data->jent_testing_enabled, 1); + pr_warn("Enabling data collection\n"); +} + +static void jent_testing_fini(struct jent_testing *data, u32 boot) +{ + /* If we have boot data, we do not reset yet to allow data to be read */ + if (boot) + return; + + atomic_set(&data->jent_testing_enabled, 0); + jent_testing_reset(data); + pr_warn("Disabling data collection\n"); +} + +static bool jent_testing_store(struct jent_testing *data, u32 value, + u32 *boot) +{ + unsigned long flags; + + if (!atomic_read(&data->jent_testing_enabled) && (*boot != 1)) + return false; + + spin_lock_irqsave(&data->lock, flags); + + /* + * Disable entropy testing for boot time testing after ring buffer + * is filled. + */ + if (*boot) { + if (((u32)atomic_read(&data->rb_writer)) > + JENT_TEST_RINGBUFFER_SIZE) { + *boot = 2; + pr_warn_once("One time data collection test disabled\n"); + spin_unlock_irqrestore(&data->lock, flags); + return false; + } + + if (atomic_read(&data->rb_writer) == 1) + pr_warn("One time data collection test enabled\n"); + } + + data->jent_testing_rb[((u32)atomic_read(&data->rb_writer)) & + JENT_TEST_RINGBUFFER_MASK] = value; + atomic_inc(&data->rb_writer); + + spin_unlock_irqrestore(&data->lock, flags); + + if (wq_has_sleeper(&data->read_wait)) + wake_up_interruptible(&data->read_wait); + + return true; +} + +static bool jent_testing_have_data(struct jent_testing *data) +{ + return ((((u32)atomic_read(&data->rb_writer)) & + JENT_TEST_RINGBUFFER_MASK) != + (data->rb_reader & JENT_TEST_RINGBUFFER_MASK)); +} + +static int jent_testing_reader(struct jent_testing *data, u32 *boot, + u8 *outbuf, u32 outbuflen) +{ + unsigned long flags; + int collected_data = 0; + + jent_testing_data_init(data, *boot); + + while (outbuflen) { + u32 writer = (u32)atomic_read(&data->rb_writer); + + spin_lock_irqsave(&data->lock, flags); + + /* We have no data or reached the writer. */ + if (!writer || (writer == data->rb_reader)) { + + spin_unlock_irqrestore(&data->lock, flags); + + /* + * Now we gathered all boot data, enable regular data + * collection. + */ + if (*boot) { + *boot = 0; + goto out; + } + + wait_event_interruptible(data->read_wait, + jent_testing_have_data(data)); + if (signal_pending(current)) { + collected_data = -ERESTARTSYS; + goto out; + } + + continue; + } + + /* We copy out word-wise */ + if (outbuflen < sizeof(u32)) { + spin_unlock_irqrestore(&data->lock, flags); + goto out; + } + + memcpy(outbuf, &data->jent_testing_rb[data->rb_reader], + sizeof(u32)); + data->rb_reader++; + + spin_unlock_irqrestore(&data->lock, flags); + + outbuf += sizeof(u32); + outbuflen -= sizeof(u32); + collected_data += sizeof(u32); + } + +out: + jent_testing_fini(data, *boot); + return collected_data; +} + +static int jent_testing_extract_user(struct file *file, char __user *buf, + size_t nbytes, loff_t *ppos, + int (*reader)(u8 *outbuf, u32 outbuflen)) +{ + u8 *tmp, *tmp_aligned; + int ret = 0, large_request = (nbytes > 256); + + if (!nbytes) + return 0; + + /* + * The intention of this interface is for collecting at least + * 1000 samples due to the SP800-90B requirements. So, we make no + * effort in avoiding allocating more memory that actually needed + * by the user. Hence, we allocate sufficient memory to always hold + * that amount of data. + */ + tmp = kmalloc(JENT_TEST_RINGBUFFER_SIZE + sizeof(u32), GFP_KERNEL); + if (!tmp) + return -ENOMEM; + + tmp_aligned = PTR_ALIGN(tmp, sizeof(u32)); + + while (nbytes) { + int i; + + if (large_request && need_resched()) { + if (signal_pending(current)) { + if (ret == 0) + ret = -ERESTARTSYS; + break; + } + schedule(); + } + + i = min_t(int, nbytes, JENT_TEST_RINGBUFFER_SIZE); + i = reader(tmp_aligned, i); + if (i <= 0) { + if (i < 0) + ret = i; + break; + } + if (copy_to_user(buf, tmp_aligned, i)) { + ret = -EFAULT; + break; + } + + nbytes -= i; + buf += i; + ret += i; + } + + kfree_sensitive(tmp); + + if (ret > 0) + *ppos += ret; + + return ret; +} + +/************** Raw High-Resolution Timer Entropy Data Handling **************/ + +static u32 boot_raw_hires_test = 0; +module_param(boot_raw_hires_test, uint, 0644); +MODULE_PARM_DESC(boot_raw_hires_test, + "Enable gathering boot time high resolution timer entropy of the first Jitter RNG entropy events"); + +static struct jent_testing jent_raw_hires = { + .rb_reader = 0, + .rb_writer = ATOMIC_INIT(0), + .lock = __SPIN_LOCK_UNLOCKED(jent_raw_hires.lock), + .read_wait = __WAIT_QUEUE_HEAD_INITIALIZER(jent_raw_hires.read_wait) +}; + +int jent_raw_hires_entropy_store(__u32 value) +{ + return jent_testing_store(&jent_raw_hires, value, &boot_raw_hires_test); +} +EXPORT_SYMBOL(jent_raw_hires_entropy_store); + +static int jent_raw_hires_entropy_reader(u8 *outbuf, u32 outbuflen) +{ + return jent_testing_reader(&jent_raw_hires, &boot_raw_hires_test, + outbuf, outbuflen); +} + +static ssize_t jent_raw_hires_read(struct file *file, char __user *to, + size_t count, loff_t *ppos) +{ + return jent_testing_extract_user(file, to, count, ppos, + jent_raw_hires_entropy_reader); +} + +static const struct file_operations jent_raw_hires_fops = { + .owner = THIS_MODULE, + .read = jent_raw_hires_read, +}; + +/******************************* Initialization *******************************/ + +void jent_testing_init(void) +{ + jent_raw_debugfs_root = debugfs_create_dir(KBUILD_MODNAME, NULL); + + debugfs_create_file_unsafe("jent_raw_hires", 0400, + jent_raw_debugfs_root, NULL, + &jent_raw_hires_fops); +} +EXPORT_SYMBOL(jent_testing_init); + +void jent_testing_exit(void) +{ + debugfs_remove_recursive(jent_raw_debugfs_root); +} +EXPORT_SYMBOL(jent_testing_exit); diff --git a/crypto/jitterentropy.c b/crypto/jitterentropy.c index 22f48bf4c6f5716d0d2bea11fdc9180fa55c1f8d..c7d7f2caa7793b131d203c9fc3907d17d800c887 100644 --- a/crypto/jitterentropy.c +++ b/crypto/jitterentropy.c @@ -2,7 +2,7 @@ * Non-physical true random number generator based on timing jitter -- * Jitter RNG standalone code. * - * Copyright Stephan Mueller , 2015 - 2020 + * Copyright Stephan Mueller , 2015 - 2023 * * Design * ====== @@ -47,7 +47,7 @@ /* * This Jitterentropy RNG is based on the jitterentropy library - * version 2.2.0 provided at https://www.chronox.de/jent.html + * version 3.4.0 provided at https://www.chronox.de/jent.html */ #ifdef __OPTIMIZE__ @@ -57,21 +57,22 @@ typedef unsigned long long __u64; typedef long long __s64; typedef unsigned int __u32; +typedef unsigned char u8; #define NULL ((void *) 0) /* The entropy pool */ struct rand_data { + /* SHA3-256 is used as conditioner */ +#define DATA_SIZE_BITS 256 /* all data values that are vital to maintain the security * of the RNG are marked as SENSITIVE. A user must not * access that information while the RNG executes its loops to * calculate the next random value. */ - __u64 data; /* SENSITIVE Actual random number */ - __u64 old_data; /* SENSITIVE Previous random number */ - __u64 prev_time; /* SENSITIVE Previous time stamp */ -#define DATA_SIZE_BITS ((sizeof(__u64)) * 8) - __u64 last_delta; /* SENSITIVE stuck test */ - __s64 last_delta2; /* SENSITIVE stuck test */ - unsigned int osr; /* Oversample rate */ + void *hash_state; /* SENSITIVE hash state entropy pool */ + __u64 prev_time; /* SENSITIVE Previous time stamp */ + __u64 last_delta; /* SENSITIVE stuck test */ + __s64 last_delta2; /* SENSITIVE stuck test */ + unsigned int osr; /* Oversample rate */ #define JENT_MEMORY_BLOCKS 64 #define JENT_MEMORY_BLOCKSIZE 32 #define JENT_MEMORY_ACCESSLOOPS 128 @@ -117,7 +118,6 @@ struct rand_data { * zero). */ #define JENT_ESTUCK 8 /* Too many stuck results during init. */ #define JENT_EHEALTH 9 /* Health test failed during initialization */ -#define JENT_ERCT 10 /* RCT failed during initialization */ /* * The output n bits can receive more than n bits of min entropy, of course, @@ -302,15 +302,13 @@ static int jent_permanent_health_failure(struct rand_data *ec) * an entropy collection. * * Input: - * @ec entropy collector struct -- may be NULL * @bits is the number of low bits of the timer to consider * @min is the number of bits we shift the timer value to the right at * the end to make sure we have a guaranteed minimum value * * @return Newly calculated loop counter */ -static __u64 jent_loop_shuffle(struct rand_data *ec, - unsigned int bits, unsigned int min) +static __u64 jent_loop_shuffle(unsigned int bits, unsigned int min) { __u64 time = 0; __u64 shuffle = 0; @@ -318,12 +316,7 @@ static __u64 jent_loop_shuffle(struct rand_data *ec, unsigned int mask = (1<data; + /* * We fold the time value as much as possible to ensure that as many * bits of the time stamp are included as possible. @@ -345,81 +338,32 @@ static __u64 jent_loop_shuffle(struct rand_data *ec, * execution time jitter * * This function injects the individual bits of the time value into the - * entropy pool using an LFSR. + * entropy pool using a hash. * - * The code is deliberately inefficient with respect to the bit shifting - * and shall stay that way. This function is the root cause why the code - * shall be compiled without optimization. This function not only acts as - * folding operation, but this function's execution is used to measure - * the CPU execution time jitter. Any change to the loop in this function - * implies that careful retesting must be done. - * - * @ec [in] entropy collector struct - * @time [in] time stamp to be injected - * @loop_cnt [in] if a value not equal to 0 is set, use the given value as - * number of loops to perform the folding - * @stuck [in] Is the time stamp identified as stuck? + * ec [in] entropy collector + * time [in] time stamp to be injected + * stuck [in] Is the time stamp identified as stuck? * * Output: - * updated ec->data - * - * @return Number of loops the folding operation is performed + * updated hash context in the entropy collector or error code */ -static void jent_lfsr_time(struct rand_data *ec, __u64 time, __u64 loop_cnt, - int stuck) +static int jent_condition_data(struct rand_data *ec, __u64 time, int stuck) { - unsigned int i; - __u64 j = 0; - __u64 new = 0; -#define MAX_FOLD_LOOP_BIT 4 -#define MIN_FOLD_LOOP_BIT 0 - __u64 fold_loop_cnt = - jent_loop_shuffle(ec, MAX_FOLD_LOOP_BIT, MIN_FOLD_LOOP_BIT); - - /* - * testing purposes -- allow test app to set the counter, not - * needed during runtime - */ - if (loop_cnt) - fold_loop_cnt = loop_cnt; - for (j = 0; j < fold_loop_cnt; j++) { - new = ec->data; - for (i = 1; (DATA_SIZE_BITS) >= i; i++) { - __u64 tmp = time << (DATA_SIZE_BITS - i); - - tmp = tmp >> (DATA_SIZE_BITS - 1); - - /* - * Fibonacci LSFR with polynomial of - * x^64 + x^61 + x^56 + x^31 + x^28 + x^23 + 1 which is - * primitive according to - * http://poincare.matf.bg.ac.rs/~ezivkovm/publications/primpol1.pdf - * (the shift values are the polynomial values minus one - * due to counting bits from 0 to 63). As the current - * position is always the LSB, the polynomial only needs - * to shift data in from the left without wrap. - */ - tmp ^= ((new >> 63) & 1); - tmp ^= ((new >> 60) & 1); - tmp ^= ((new >> 55) & 1); - tmp ^= ((new >> 30) & 1); - tmp ^= ((new >> 27) & 1); - tmp ^= ((new >> 22) & 1); - new <<= 1; - new ^= tmp; - } - } - - /* - * If the time stamp is stuck, do not finally insert the value into - * the entropy pool. Although this operation should not do any harm - * even when the time stamp has no entropy, SP800-90B requires that - * any conditioning operation (SP800-90B considers the LFSR to be a - * conditioning operation) to have an identical amount of input - * data according to section 3.1.5. - */ - if (!stuck) - ec->data = new; +#define SHA3_HASH_LOOP (1<<3) + struct { + int rct_count; + unsigned int apt_observations; + unsigned int apt_count; + unsigned int apt_base; + } addtl = { + ec->rct_count, + ec->apt_observations, + ec->apt_count, + ec->apt_base + }; + + return jent_hash_time(ec->hash_state, time, (u8 *)&addtl, sizeof(addtl), + SHA3_HASH_LOOP, stuck); } /* @@ -453,7 +397,7 @@ static void jent_memaccess(struct rand_data *ec, __u64 loop_cnt) #define MAX_ACC_LOOP_BIT 7 #define MIN_ACC_LOOP_BIT 0 __u64 acc_loop_cnt = - jent_loop_shuffle(ec, MAX_ACC_LOOP_BIT, MIN_ACC_LOOP_BIT); + jent_loop_shuffle(MAX_ACC_LOOP_BIT, MIN_ACC_LOOP_BIT); if (NULL == ec || NULL == ec->mem) return; @@ -521,14 +465,15 @@ static int jent_measure_jitter(struct rand_data *ec) stuck = jent_stuck(ec, current_delta); /* Now call the next noise sources which also injects the data */ - jent_lfsr_time(ec, current_delta, 0, stuck); + if (jent_condition_data(ec, current_delta, stuck)) + stuck = 1; return stuck; } /* * Generator of one 64 bit random number - * Function fills rand_data->data + * Function fills rand_data->hash_state * * @ec [in] Reference to entropy collector */ @@ -575,7 +520,7 @@ static void jent_gen_entropy(struct rand_data *ec) * @return 0 when request is fulfilled or an error * * The following error codes can occur: - * -1 entropy_collector is NULL + * -1 entropy_collector is NULL or the generation failed * -2 Intermittent health failure * -3 Permanent health failure */ @@ -605,7 +550,7 @@ int jent_read_entropy(struct rand_data *ec, unsigned char *data, * Perform startup health tests and return permanent * error if it fails. */ - if (jent_entropy_init()) + if (jent_entropy_init(ec->hash_state)) return -3; return -2; @@ -615,7 +560,8 @@ int jent_read_entropy(struct rand_data *ec, unsigned char *data, tocopy = (DATA_SIZE_BITS / 8); else tocopy = len; - jent_memcpy(p, &ec->data, tocopy); + if (jent_read_random_block(ec->hash_state, p, tocopy)) + return -1; len -= tocopy; p += tocopy; @@ -629,7 +575,8 @@ int jent_read_entropy(struct rand_data *ec, unsigned char *data, ***************************************************************************/ struct rand_data *jent_entropy_collector_alloc(unsigned int osr, - unsigned int flags) + unsigned int flags, + void *hash_state) { struct rand_data *entropy_collector; @@ -656,6 +603,8 @@ struct rand_data *jent_entropy_collector_alloc(unsigned int osr, osr = 1; /* minimum sampling rate is 1 */ entropy_collector->osr = osr; + entropy_collector->hash_state = hash_state; + /* fill the data pad with non-zero values */ jent_gen_entropy(entropy_collector); @@ -669,7 +618,7 @@ void jent_entropy_collector_free(struct rand_data *entropy_collector) jent_zfree(entropy_collector); } -int jent_entropy_init(void) +int jent_entropy_init(void *hash_state) { int i; __u64 delta_sum = 0; @@ -682,6 +631,7 @@ int jent_entropy_init(void) /* Required for RCT */ ec.osr = 1; + ec.hash_state = hash_state; /* We could perform statistical tests here, but the problem is * that we only have a few loop counts to do testing. These @@ -719,7 +669,7 @@ int jent_entropy_init(void) /* Invoke core entropy collection logic */ jent_get_nstime(&time); ec.prev_time = time; - jent_lfsr_time(&ec, time, 0, 0); + jent_condition_data(&ec, time, 0); jent_get_nstime(&time2); /* test whether timer works */ @@ -762,14 +712,12 @@ int jent_entropy_init(void) if ((nonstuck % JENT_APT_WINDOW_SIZE) == 0) { jent_apt_reset(&ec, delta & JENT_APT_WORD_MASK); - if (jent_health_failure(&ec)) - return JENT_EHEALTH; } } - /* Validate RCT */ - if (jent_rct_failure(&ec)) - return JENT_ERCT; + /* Validate health test result */ + if (jent_health_failure(&ec)) + return JENT_EHEALTH; /* test whether we have an increasing timer */ if (!(time2 > time)) diff --git a/crypto/jitterentropy.h b/crypto/jitterentropy.h index 5cc583f6bc6b84c207137e076470e664374658b4..4c92176ea2b1ddf76644ccdc07b10ae4ef2f1012 100644 --- a/crypto/jitterentropy.h +++ b/crypto/jitterentropy.h @@ -2,14 +2,28 @@ extern void *jent_zalloc(unsigned int len); extern void jent_zfree(void *ptr); -extern void jent_memcpy(void *dest, const void *src, unsigned int n); extern void jent_get_nstime(__u64 *out); +extern int jent_hash_time(void *hash_state, __u64 time, u8 *addtl, + unsigned int addtl_len, __u64 hash_loop_cnt, + unsigned int stuck); +int jent_read_random_block(void *hash_state, char *dst, unsigned int dst_len); struct rand_data; -extern int jent_entropy_init(void); +extern int jent_entropy_init(void *hash_state); extern int jent_read_entropy(struct rand_data *ec, unsigned char *data, unsigned int len); extern struct rand_data *jent_entropy_collector_alloc(unsigned int osr, - unsigned int flags); + unsigned int flags, + void *hash_state); extern void jent_entropy_collector_free(struct rand_data *entropy_collector); + +#ifdef CONFIG_CRYPTO_JITTERENTROPY_TESTINTERFACE +int jent_raw_hires_entropy_store(__u32 value); +void jent_testing_init(void); +void jent_testing_exit(void); +#else /* CONFIG_CRYPTO_JITTERENTROPY_TESTINTERFACE */ +static inline int jent_raw_hires_entropy_store(__u32 value) { return 0; } +static inline void jent_testing_init(void) { } +static inline void jent_testing_exit(void) { } +#endif /* CONFIG_CRYPTO_JITTERENTROPY_TESTINTERFACE */ diff --git a/crypto/rsa.c b/crypto/rsa.c index c50f2d2a4d0649fd01566b5438d91c7e324805dc..c79613cdce6e443aacdc4477315e4765a9210990 100644 --- a/crypto/rsa.c +++ b/crypto/rsa.c @@ -205,6 +205,32 @@ static int rsa_check_key_length(unsigned int len) return -EINVAL; } +static int rsa_check_exponent_fips(MPI e) +{ + MPI e_max = NULL; + + /* check if odd */ + if (!mpi_test_bit(e, 0)) { + return -EINVAL; + } + + /* check if 2^16 < e < 2^256. */ + if (mpi_cmp_ui(e, 65536) <= 0) { + return -EINVAL; + } + + e_max = mpi_alloc(0); + mpi_set_bit(e_max, 256); + + if (mpi_cmp(e, e_max) >= 0) { + mpi_free(e_max); + return -EINVAL; + } + + mpi_free(e_max); + return 0; +} + static int rsa_set_pub_key(struct crypto_akcipher *tfm, const void *key, unsigned int keylen) { @@ -232,6 +258,11 @@ static int rsa_set_pub_key(struct crypto_akcipher *tfm, const void *key, return -EINVAL; } + if (fips_enabled && rsa_check_exponent_fips(mpi_key->e)) { + rsa_free_mpi_key(mpi_key); + return -EINVAL; + } + return 0; err: @@ -290,6 +321,11 @@ static int rsa_set_priv_key(struct crypto_akcipher *tfm, const void *key, return -EINVAL; } + if (fips_enabled && rsa_check_exponent_fips(mpi_key->e)) { + rsa_free_mpi_key(mpi_key); + return -EINVAL; + } + return 0; err: diff --git a/crypto/shash.c b/crypto/shash.c index 717b42df3495ed55a87e744da3153e898a380cf2..1fadb6b59bdcc1afdd61b280813249327b4025d5 100644 --- a/crypto/shash.c +++ b/crypto/shash.c @@ -597,7 +597,7 @@ struct crypto_shash *crypto_clone_shash(struct crypto_shash *hash) return hash; } - if (!alg->clone_tfm) + if (!alg->clone_tfm && (alg->init_tfm || alg->base.cra_init)) return ERR_PTR(-ENOSYS); nhash = crypto_clone_tfm(&crypto_shash_type, tfm); @@ -606,10 +606,12 @@ struct crypto_shash *crypto_clone_shash(struct crypto_shash *hash) nhash->descsize = hash->descsize; - err = alg->clone_tfm(nhash, hash); - if (err) { - crypto_free_shash(nhash); - return ERR_PTR(err); + if (alg->clone_tfm) { + err = alg->clone_tfm(nhash, hash); + if (err) { + crypto_free_shash(nhash); + return ERR_PTR(err); + } } return nhash; diff --git a/crypto/sig.c b/crypto/sig.c new file mode 100644 index 0000000000000000000000000000000000000000..b48c18ec65cd4ec5c63e39db7f7d75f4b681babf --- /dev/null +++ b/crypto/sig.c @@ -0,0 +1,157 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Public Key Signature Algorithm + * + * Copyright (c) 2023 Herbert Xu + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "internal.h" + +#define CRYPTO_ALG_TYPE_SIG_MASK 0x0000000e + +static const struct crypto_type crypto_sig_type; + +static inline struct crypto_sig *__crypto_sig_tfm(struct crypto_tfm *tfm) +{ + return container_of(tfm, struct crypto_sig, base); +} + +static int crypto_sig_init_tfm(struct crypto_tfm *tfm) +{ + if (tfm->__crt_alg->cra_type != &crypto_sig_type) + return crypto_init_akcipher_ops_sig(tfm); + + return 0; +} + +static void __maybe_unused crypto_sig_show(struct seq_file *m, + struct crypto_alg *alg) +{ + seq_puts(m, "type : sig\n"); +} + +static int __maybe_unused crypto_sig_report(struct sk_buff *skb, + struct crypto_alg *alg) +{ + struct crypto_report_akcipher rsig = {}; + + strscpy(rsig.type, "sig", sizeof(rsig.type)); + + return nla_put(skb, CRYPTOCFGA_REPORT_AKCIPHER, sizeof(rsig), &rsig); +} + +static int __maybe_unused crypto_sig_report_stat(struct sk_buff *skb, + struct crypto_alg *alg) +{ + struct crypto_stat_akcipher rsig = {}; + + strscpy(rsig.type, "sig", sizeof(rsig.type)); + + return nla_put(skb, CRYPTOCFGA_STAT_AKCIPHER, sizeof(rsig), &rsig); +} + +static const struct crypto_type crypto_sig_type = { + .extsize = crypto_alg_extsize, + .init_tfm = crypto_sig_init_tfm, +#ifdef CONFIG_PROC_FS + .show = crypto_sig_show, +#endif +#if IS_ENABLED(CONFIG_CRYPTO_USER) + .report = crypto_sig_report, +#endif +#ifdef CONFIG_CRYPTO_STATS + .report_stat = crypto_sig_report_stat, +#endif + .maskclear = ~CRYPTO_ALG_TYPE_MASK, + .maskset = CRYPTO_ALG_TYPE_SIG_MASK, + .type = CRYPTO_ALG_TYPE_SIG, + .tfmsize = offsetof(struct crypto_sig, base), +}; + +struct crypto_sig *crypto_alloc_sig(const char *alg_name, u32 type, u32 mask) +{ + return crypto_alloc_tfm(alg_name, &crypto_sig_type, type, mask); +} +EXPORT_SYMBOL_GPL(crypto_alloc_sig); + +int crypto_sig_maxsize(struct crypto_sig *tfm) +{ + struct crypto_akcipher **ctx = crypto_sig_ctx(tfm); + + return crypto_akcipher_maxsize(*ctx); +} +EXPORT_SYMBOL_GPL(crypto_sig_maxsize); + +int crypto_sig_sign(struct crypto_sig *tfm, + const void *src, unsigned int slen, + void *dst, unsigned int dlen) +{ + struct crypto_akcipher **ctx = crypto_sig_ctx(tfm); + struct crypto_akcipher_sync_data data = { + .tfm = *ctx, + .src = src, + .dst = dst, + .slen = slen, + .dlen = dlen, + }; + + return crypto_akcipher_sync_prep(&data) ?: + crypto_akcipher_sync_post(&data, + crypto_akcipher_sign(data.req)); +} +EXPORT_SYMBOL_GPL(crypto_sig_sign); + +int crypto_sig_verify(struct crypto_sig *tfm, + const void *src, unsigned int slen, + const void *digest, unsigned int dlen) +{ + struct crypto_akcipher **ctx = crypto_sig_ctx(tfm); + struct crypto_akcipher_sync_data data = { + .tfm = *ctx, + .src = src, + .slen = slen, + .dlen = dlen, + }; + int err; + + err = crypto_akcipher_sync_prep(&data); + if (err) + return err; + + memcpy(data.buf + slen, digest, dlen); + + return crypto_akcipher_sync_post(&data, + crypto_akcipher_verify(data.req)); +} +EXPORT_SYMBOL_GPL(crypto_sig_verify); + +int crypto_sig_set_pubkey(struct crypto_sig *tfm, + const void *key, unsigned int keylen) +{ + struct crypto_akcipher **ctx = crypto_sig_ctx(tfm); + + return crypto_akcipher_set_pub_key(*ctx, key, keylen); +} +EXPORT_SYMBOL_GPL(crypto_sig_set_pubkey); + +int crypto_sig_set_privkey(struct crypto_sig *tfm, + const void *key, unsigned int keylen) +{ + struct crypto_akcipher **ctx = crypto_sig_ctx(tfm); + + return crypto_akcipher_set_priv_key(*ctx, key, keylen); +} +EXPORT_SYMBOL_GPL(crypto_sig_set_privkey); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Public Key Signature Algorithms"); diff --git a/crypto/sm2.c b/crypto/sm2.c index ed9307dac3d1eeb283a57a7f10b141d8159a5a34..285b3cb7c0bc781b4c8be08b1c2c32a931ad0c3c 100644 --- a/crypto/sm2.c +++ b/crypto/sm2.c @@ -13,11 +13,14 @@ #include #include #include -#include #include #include #include "sm2signature.asn1.h" +/* The default user id as specified in GM/T 0009-2012 */ +#define SM2_DEFAULT_USERID "1234567812345678" +#define SM2_DEFAULT_USERID_LEN 16 + #define MPI_NBYTES(m) ((mpi_get_nbits(m) + 7) / 8) struct ecc_domain_parms { @@ -60,6 +63,9 @@ static const struct ecc_domain_parms sm2_ecp = { .h = 1 }; +static int __sm2_set_pub_key(struct mpi_ec_ctx *ec, + const void *key, unsigned int keylen); + static int sm2_ec_ctx_init(struct mpi_ec_ctx *ec) { const struct ecc_domain_parms *ecp = &sm2_ecp; @@ -213,12 +219,13 @@ int sm2_get_signature_s(void *context, size_t hdrlen, unsigned char tag, return 0; } -static int sm2_z_digest_update(struct sm3_state *sctx, - MPI m, unsigned int pbytes) +static int sm2_z_digest_update(struct shash_desc *desc, + MPI m, unsigned int pbytes) { static const unsigned char zero[32]; unsigned char *in; unsigned int inlen; + int err; in = mpi_get_buffer(m, &inlen, NULL); if (!in) @@ -226,21 +233,22 @@ static int sm2_z_digest_update(struct sm3_state *sctx, if (inlen < pbytes) { /* padding with zero */ - sm3_update(sctx, zero, pbytes - inlen); - sm3_update(sctx, in, inlen); + err = crypto_shash_update(desc, zero, pbytes - inlen) ?: + crypto_shash_update(desc, in, inlen); } else if (inlen > pbytes) { /* skip the starting zero */ - sm3_update(sctx, in + inlen - pbytes, pbytes); + err = crypto_shash_update(desc, in + inlen - pbytes, pbytes); } else { - sm3_update(sctx, in, inlen); + err = crypto_shash_update(desc, in, inlen); } kfree(in); - return 0; + return err; } -static int sm2_z_digest_update_point(struct sm3_state *sctx, - MPI_POINT point, struct mpi_ec_ctx *ec, unsigned int pbytes) +static int sm2_z_digest_update_point(struct shash_desc *desc, + MPI_POINT point, struct mpi_ec_ctx *ec, + unsigned int pbytes) { MPI x, y; int ret = -EINVAL; @@ -248,50 +256,68 @@ static int sm2_z_digest_update_point(struct sm3_state *sctx, x = mpi_new(0); y = mpi_new(0); - if (!mpi_ec_get_affine(x, y, point, ec) && - !sm2_z_digest_update(sctx, x, pbytes) && - !sm2_z_digest_update(sctx, y, pbytes)) - ret = 0; + ret = mpi_ec_get_affine(x, y, point, ec) ? -EINVAL : + sm2_z_digest_update(desc, x, pbytes) ?: + sm2_z_digest_update(desc, y, pbytes); mpi_free(x); mpi_free(y); return ret; } -int sm2_compute_z_digest(struct crypto_akcipher *tfm, - const unsigned char *id, size_t id_len, - unsigned char dgst[SM3_DIGEST_SIZE]) +int sm2_compute_z_digest(struct shash_desc *desc, + const void *key, unsigned int keylen, void *dgst) { - struct mpi_ec_ctx *ec = akcipher_tfm_ctx(tfm); - uint16_t bits_len; - unsigned char entl[2]; - struct sm3_state sctx; + struct mpi_ec_ctx *ec; + unsigned int bits_len; unsigned int pbytes; + u8 entl[2]; + int err; - if (id_len > (USHRT_MAX / 8) || !ec->Q) - return -EINVAL; + ec = kmalloc(sizeof(*ec), GFP_KERNEL); + if (!ec) + return -ENOMEM; + + err = __sm2_set_pub_key(ec, key, keylen); + if (err) + goto out_free_ec; - bits_len = (uint16_t)(id_len * 8); + bits_len = SM2_DEFAULT_USERID_LEN * 8; entl[0] = bits_len >> 8; entl[1] = bits_len & 0xff; pbytes = MPI_NBYTES(ec->p); /* ZA = H256(ENTLA | IDA | a | b | xG | yG | xA | yA) */ - sm3_init(&sctx); - sm3_update(&sctx, entl, 2); - sm3_update(&sctx, id, id_len); - - if (sm2_z_digest_update(&sctx, ec->a, pbytes) || - sm2_z_digest_update(&sctx, ec->b, pbytes) || - sm2_z_digest_update_point(&sctx, ec->G, ec, pbytes) || - sm2_z_digest_update_point(&sctx, ec->Q, ec, pbytes)) - return -EINVAL; + err = crypto_shash_init(desc); + if (err) + goto out_deinit_ec; - sm3_final(&sctx, dgst); - return 0; + err = crypto_shash_update(desc, entl, 2); + if (err) + goto out_deinit_ec; + + err = crypto_shash_update(desc, SM2_DEFAULT_USERID, + SM2_DEFAULT_USERID_LEN); + if (err) + goto out_deinit_ec; + + err = sm2_z_digest_update(desc, ec->a, pbytes) ?: + sm2_z_digest_update(desc, ec->b, pbytes) ?: + sm2_z_digest_update_point(desc, ec->G, ec, pbytes) ?: + sm2_z_digest_update_point(desc, ec->Q, ec, pbytes); + if (err) + goto out_deinit_ec; + + err = crypto_shash_final(desc, dgst); + +out_deinit_ec: + sm2_ec_ctx_deinit(ec); +out_free_ec: + kfree(ec); + return err; } -EXPORT_SYMBOL(sm2_compute_z_digest); +EXPORT_SYMBOL_GPL(sm2_compute_z_digest); static int _sm2_verify(struct mpi_ec_ctx *ec, MPI hash, MPI sig_r, MPI sig_s) { @@ -391,6 +417,14 @@ static int sm2_set_pub_key(struct crypto_akcipher *tfm, const void *key, unsigned int keylen) { struct mpi_ec_ctx *ec = akcipher_tfm_ctx(tfm); + + return __sm2_set_pub_key(ec, key, keylen); + +} + +static int __sm2_set_pub_key(struct mpi_ec_ctx *ec, + const void *key, unsigned int keylen) +{ MPI a; int rc; diff --git a/drivers/accel/ivpu/ivpu_drv.h b/drivers/accel/ivpu/ivpu_drv.h index 315180dd72ce52695df5bd6881ecc4935c67688a..8fe8cda2e39d1aa2da41c5cb9ff69e12f4ab0426 100644 --- a/drivers/accel/ivpu/ivpu_drv.h +++ b/drivers/accel/ivpu/ivpu_drv.h @@ -75,6 +75,7 @@ struct ivpu_wa_table { bool punit_disabled; bool clear_runtime_mem; bool d3hot_after_power_off; + bool interrupt_clear_with_0; }; struct ivpu_hw_info; diff --git a/drivers/accel/ivpu/ivpu_hw_mtl.c b/drivers/accel/ivpu/ivpu_hw_mtl.c index 3ff60fbbc8d9dba372e1bd866e59bfd08ce2098f..f1211e74017def72ff489b7ac85909a3302f0445 100644 --- a/drivers/accel/ivpu/ivpu_hw_mtl.c +++ b/drivers/accel/ivpu/ivpu_hw_mtl.c @@ -101,6 +101,9 @@ static void ivpu_hw_wa_init(struct ivpu_device *vdev) vdev->wa.punit_disabled = ivpu_is_fpga(vdev); vdev->wa.clear_runtime_mem = false; vdev->wa.d3hot_after_power_off = true; + + if (ivpu_device_id(vdev) == PCI_DEVICE_ID_MTL && ivpu_revision(vdev) < 4) + vdev->wa.interrupt_clear_with_0 = true; } static void ivpu_hw_timeouts_init(struct ivpu_device *vdev) @@ -874,7 +877,7 @@ static void ivpu_hw_mtl_irq_disable(struct ivpu_device *vdev) REGB_WR32(MTL_BUTTRESS_GLOBAL_INT_MASK, 0x1); REGB_WR32(MTL_BUTTRESS_LOCAL_INT_MASK, BUTTRESS_IRQ_DISABLE_MASK); REGV_WR64(MTL_VPU_HOST_SS_ICB_ENABLE_0, 0x0ull); - REGB_WR32(MTL_VPU_HOST_SS_FW_SOC_IRQ_EN, 0x0); + REGV_WR32(MTL_VPU_HOST_SS_FW_SOC_IRQ_EN, 0x0); } static void ivpu_hw_mtl_irq_wdt_nce_handler(struct ivpu_device *vdev) @@ -962,12 +965,15 @@ static u32 ivpu_hw_mtl_irqb_handler(struct ivpu_device *vdev, int irq) schedule_recovery = true; } - /* - * Clear local interrupt status by writing 0 to all bits. - * This must be done after interrupts are cleared at the source. - * Writing 1 triggers an interrupt, so we can't perform read update write. - */ - REGB_WR32(MTL_BUTTRESS_INTERRUPT_STAT, 0x0); + /* This must be done after interrupts are cleared at the source. */ + if (IVPU_WA(interrupt_clear_with_0)) + /* + * Writing 1 triggers an interrupt, so we can't perform read update write. + * Clear local interrupt status by writing 0 to all bits. + */ + REGB_WR32(MTL_BUTTRESS_INTERRUPT_STAT, 0x0); + else + REGB_WR32(MTL_BUTTRESS_INTERRUPT_STAT, status); /* Re-enable global interrupt */ REGB_WR32(MTL_BUTTRESS_GLOBAL_INT_MASK, 0x0); diff --git a/drivers/accel/qaic/qaic_data.c b/drivers/accel/qaic/qaic_data.c index e42c1f9ffff85eb72650b2bc75590d924d4f3d02..e9a1cb779b3056aedb3cb561926d5472aab56d11 100644 --- a/drivers/accel/qaic/qaic_data.c +++ b/drivers/accel/qaic/qaic_data.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -616,8 +617,7 @@ static void qaic_free_object(struct drm_gem_object *obj) if (obj->import_attach) { /* DMABUF/PRIME Path */ - dma_buf_detach(obj->import_attach->dmabuf, obj->import_attach); - dma_buf_put(obj->import_attach->dmabuf); + drm_prime_gem_destroy(obj, NULL); } else { /* Private buffer allocation path */ qaic_free_sgt(bo->sgt); diff --git a/drivers/accessibility/speakup/Kconfig b/drivers/accessibility/speakup/Kconfig index 07ecbbde0384123d22509a37c01a117273507546..e84fb617acc44b1f56352e6cf8d351b3b25c0451 100644 --- a/drivers/accessibility/speakup/Kconfig +++ b/drivers/accessibility/speakup/Kconfig @@ -46,6 +46,7 @@ if SPEAKUP config SPEAKUP_SERIALIO def_bool y depends on ISA || COMPILE_TEST + depends on HAS_IOPORT config SPEAKUP_SYNTH_ACNTSA tristate "Accent SA synthesizer support" diff --git a/drivers/accessibility/speakup/main.c b/drivers/accessibility/speakup/main.c index 56c073103cbb9958e79ddf54e3b6bda0345bd812..1fbc9b921c4fccbff6bb64981ce678efd1841890 100644 --- a/drivers/accessibility/speakup/main.c +++ b/drivers/accessibility/speakup/main.c @@ -1287,7 +1287,7 @@ static struct var_t spk_vars[NB_ID] = { [PUNC_LEVEL_ID] = { PUNC_LEVEL, .u.n = {NULL, 1, 0, 4, 0, 0, NULL} }, [READING_PUNC_ID] = { READING_PUNC, .u.n = {NULL, 1, 0, 4, 0, 0, NULL} }, [CURSOR_TIME_ID] = { CURSOR_TIME, .u.n = {NULL, 120, 50, 600, 0, 0, NULL} }, - [SAY_CONTROL_ID] { SAY_CONTROL, TOGGLE_0}, + [SAY_CONTROL_ID] = { SAY_CONTROL, TOGGLE_0}, [SAY_WORD_CTL_ID] = {SAY_WORD_CTL, TOGGLE_0}, [NO_INTERRUPT_ID] = { NO_INTERRUPT, TOGGLE_0}, [KEY_ECHO_ID] = { KEY_ECHO, .u.n = {NULL, 1, 0, 2, 0, 0, NULL} }, diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index ccbeab9500ecb003c93046cfe4039d868252b750..00dd309b668281826a6d5328c8dde36c6f5dbd02 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -542,10 +542,10 @@ config ACPI_PFRUT if ARM64 source "drivers/acpi/arm64/Kconfig" +endif config ACPI_PPTT bool -endif config ACPI_PCC bool "ACPI PCC Address Space" diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index feb36c0b9446052158655648aea3a62f5f3d97eb..3fc5a0d54f6efcf5425ac4b6b5a86b68570dd766 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -131,3 +131,5 @@ obj-y += dptf/ obj-$(CONFIG_ARM64) += arm64/ obj-$(CONFIG_ACPI_VIOT) += viot.o + +obj-$(CONFIG_RISCV) += riscv/ diff --git a/drivers/acpi/acpi_ffh.c b/drivers/acpi/acpi_ffh.c index 19aff808bbb853bfa9b82e0a1c45ea7659ec10e0..8d5126963dc790ef96b5d0e40efce706d0312a13 100644 --- a/drivers/acpi/acpi_ffh.c +++ b/drivers/acpi/acpi_ffh.c @@ -9,8 +9,6 @@ #include #include -#include - static struct acpi_ffh_info ffh_ctx; int __weak acpi_ffh_address_space_arch_setup(void *handler_ctxt, diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/acpi_lpss.c index 77186f084d3ae36566e55b6594d2c97dd712e68a..539e700de4d289013bdc3fdefe8a5b22e7a5d157 100644 --- a/drivers/acpi/acpi_lpss.c +++ b/drivers/acpi/acpi_lpss.c @@ -201,11 +201,19 @@ static void byt_i2c_setup(struct lpss_private_data *pdata) writel(0, pdata->mmio_base + LPSS_I2C_ENABLE); } -/* BSW PWM used for backlight control by the i915 driver */ +/* + * BSW PWM1 is used for backlight control by the i915 driver + * BSW PWM2 is used for backlight control for fixed (etched into the glass) + * touch controls on some models. These touch-controls have specialized + * drivers which know they need the "pwm_soc_lpss_2" con-id. + */ static struct pwm_lookup bsw_pwm_lookup[] = { PWM_LOOKUP_WITH_MODULE("80862288:00", 0, "0000:00:02.0", "pwm_soc_backlight", 0, PWM_POLARITY_NORMAL, "pwm-lpss-platform"), + PWM_LOOKUP_WITH_MODULE("80862289:00", 0, NULL, + "pwm_soc_lpss_2", 0, PWM_POLARITY_NORMAL, + "pwm-lpss-platform"), }; static void bsw_pwm_setup(struct lpss_private_data *pdata) diff --git a/drivers/acpi/acpi_pad.c b/drivers/acpi/acpi_pad.c index 02f1a1b1143c543c5e4175fbe1947e7956a45fc4..7a453c5ff303a9e285fe8b136c00c332c6b274f5 100644 --- a/drivers/acpi/acpi_pad.c +++ b/drivers/acpi/acpi_pad.c @@ -66,6 +66,7 @@ static void power_saving_mwait_init(void) case X86_VENDOR_AMD: case X86_VENDOR_INTEL: case X86_VENDOR_ZHAOXIN: + case X86_VENDOR_CENTAUR: /* * AMD Fam10h TSC will tick in all * C/P/S0/S1 states when this bit is set. diff --git a/drivers/acpi/acpi_platform.c b/drivers/acpi/acpi_platform.c index fe00a5783f53f48798c6784126b0d95f9909e50a..48d15dd785f6eb9fccc13054969f3b7c05cfc694 100644 --- a/drivers/acpi/acpi_platform.c +++ b/drivers/acpi/acpi_platform.c @@ -9,6 +9,7 @@ */ #include +#include #include #include #include @@ -19,13 +20,16 @@ #include "internal.h" +/* Exclude devices that have no _CRS resources provided */ +#define ACPI_ALLOW_WO_RESOURCES BIT(0) + static const struct acpi_device_id forbidden_id_list[] = { {"ACPI0009", 0}, /* IOxAPIC */ {"ACPI000A", 0}, /* IOAPIC */ {"PNP0000", 0}, /* PIC */ {"PNP0100", 0}, /* Timer */ {"PNP0200", 0}, /* AT DMA Controller */ - {"SMB0001", 0}, /* ACPI SMBUS virtual device */ + {ACPI_SMBUS_MS_HID, ACPI_ALLOW_WO_RESOURCES}, /* ACPI SMBUS virtual device */ { } }; @@ -83,6 +87,15 @@ static void acpi_platform_fill_resource(struct acpi_device *adev, dest->parent = pci_find_resource(to_pci_dev(parent), dest); } +static unsigned int acpi_platform_resource_count(struct acpi_resource *ares, void *data) +{ + bool *has_resources = data; + + *has_resources = true; + + return AE_CTRL_TERMINATE; +} + /** * acpi_create_platform_device - Create platform device for ACPI device node * @adev: ACPI device node to create a platform device for. @@ -100,6 +113,7 @@ struct platform_device *acpi_create_platform_device(struct acpi_device *adev, struct acpi_device *parent = acpi_dev_parent(adev); struct platform_device *pdev = NULL; struct platform_device_info pdevinfo; + const struct acpi_device_id *match; struct resource_entry *rentry; struct list_head resource_list; struct resource *resources = NULL; @@ -109,8 +123,19 @@ struct platform_device *acpi_create_platform_device(struct acpi_device *adev, if (adev->physical_node_count) return NULL; - if (!acpi_match_device_ids(adev, forbidden_id_list)) - return ERR_PTR(-EINVAL); + match = acpi_match_acpi_device(forbidden_id_list, adev); + if (match) { + if (match->driver_data & ACPI_ALLOW_WO_RESOURCES) { + bool has_resources = false; + + acpi_walk_resources(adev->handle, METHOD_NAME__CRS, + acpi_platform_resource_count, &has_resources); + if (has_resources) + return ERR_PTR(-EINVAL); + } else { + return ERR_PTR(-EINVAL); + } + } INIT_LIST_HEAD(&resource_list); count = acpi_dev_get_resources(adev, &resource_list, NULL, NULL); diff --git a/drivers/acpi/acpica/achware.h b/drivers/acpi/acpica/achware.h index ebf8fd373cf7ea0e37cbd7f159acbb7ab7ac37e9..79bbfe00d241f94b73d7c777a6e80f66b65c6075 100644 --- a/drivers/acpi/acpica/achware.h +++ b/drivers/acpi/acpica/achware.h @@ -101,8 +101,6 @@ acpi_status acpi_hw_get_gpe_status(struct acpi_gpe_event_info *gpe_event_info, acpi_event_status *event_status); -acpi_status acpi_hw_disable_all_gpes(void); - acpi_status acpi_hw_enable_all_runtime_gpes(void); acpi_status acpi_hw_enable_all_wakeup_gpes(void); diff --git a/drivers/acpi/apei/bert.c b/drivers/acpi/apei/bert.c index 7514e38d5640eed18483897f9ddfd867061d9fa9..5427e49e646b2686b269155156d85f43819fb8e0 100644 --- a/drivers/acpi/apei/bert.c +++ b/drivers/acpi/apei/bert.c @@ -34,7 +34,7 @@ #define ACPI_BERT_PRINT_MAX_RECORDS 5 #define ACPI_BERT_PRINT_MAX_LEN 1024 -static int bert_disable; +static int bert_disable __initdata; /* * Print "all" the error records in the BERT table, but avoid huge spam to diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c index 34ad071a64e96710184a3de25e23a215a2e12c09..ef59d6ea16da0ff693d692dee9e0b197dc213825 100644 --- a/drivers/acpi/apei/ghes.c +++ b/drivers/acpi/apei/ghes.c @@ -152,7 +152,6 @@ struct ghes_vendor_record_entry { }; static struct gen_pool *ghes_estatus_pool; -static unsigned long ghes_estatus_pool_size_request; static struct ghes_estatus_cache __rcu *ghes_estatus_caches[GHES_ESTATUS_CACHES_SIZE]; static atomic_t ghes_estatus_cache_alloced; @@ -191,7 +190,6 @@ int ghes_estatus_pool_init(unsigned int num_ghes) len = GHES_ESTATUS_CACHE_AVG_SIZE * GHES_ESTATUS_CACHE_ALLOCED_MAX; len += (num_ghes * GHES_ESOURCE_PREALLOC_MAX_SIZE); - ghes_estatus_pool_size_request = PAGE_ALIGN(len); addr = (unsigned long)vmalloc(PAGE_ALIGN(len)); if (!addr) goto err_pool_alloc; @@ -1544,6 +1542,8 @@ struct list_head *ghes_get_devices(void) pr_warn_once("Force-loading ghes_edac on an unsupported platform. You're on your own!\n"); } + } else if (list_empty(&ghes_devs)) { + return NULL; } return &ghes_devs; diff --git a/drivers/acpi/arm64/Makefile b/drivers/acpi/arm64/Makefile index e21a9e84e3945487a1149d691929b85ede411f06..f81fe24894b26eb229b20770dbf77a956d0e61ec 100644 --- a/drivers/acpi/arm64/Makefile +++ b/drivers/acpi/arm64/Makefile @@ -3,4 +3,4 @@ obj-$(CONFIG_ACPI_AGDI) += agdi.o obj-$(CONFIG_ACPI_IORT) += iort.o obj-$(CONFIG_ACPI_GTDT) += gtdt.o obj-$(CONFIG_ACPI_APMT) += apmt.o -obj-y += dma.o +obj-y += dma.o init.o diff --git a/drivers/acpi/arm64/agdi.c b/drivers/acpi/arm64/agdi.c index f605302395c3ed1dad322f30367a58e03643e865..8b3c7d42b41bc56a88303c61d2fa38fefef9e3af 100644 --- a/drivers/acpi/arm64/agdi.c +++ b/drivers/acpi/arm64/agdi.c @@ -9,11 +9,11 @@ #define pr_fmt(fmt) "ACPI: AGDI: " fmt #include -#include #include #include #include #include +#include "init.h" struct agdi_data { int sdei_event; diff --git a/drivers/acpi/arm64/apmt.c b/drivers/acpi/arm64/apmt.c index 8cab69fa5d59acbd43a6ca3d9808e1b06fac550a..bb010f6164e528acd802f65afd80d65a57f5844f 100644 --- a/drivers/acpi/arm64/apmt.c +++ b/drivers/acpi/arm64/apmt.c @@ -10,10 +10,10 @@ #define pr_fmt(fmt) "ACPI: APMT: " fmt #include -#include #include #include #include +#include "init.h" #define DEV_NAME "arm-cs-arch-pmu" @@ -35,11 +35,13 @@ static int __init apmt_init_resources(struct resource *res, num_res++; - res[num_res].start = node->base_address1; - res[num_res].end = node->base_address1 + SZ_4K - 1; - res[num_res].flags = IORESOURCE_MEM; + if (node->flags & ACPI_APMT_FLAGS_DUAL_PAGE) { + res[num_res].start = node->base_address1; + res[num_res].end = node->base_address1 + SZ_4K - 1; + res[num_res].flags = IORESOURCE_MEM; - num_res++; + num_res++; + } if (node->ovflw_irq != 0) { trigger = (node->ovflw_irq_flags & ACPI_APMT_OVFLW_IRQ_FLAGS_MODE); diff --git a/drivers/acpi/arm64/init.c b/drivers/acpi/arm64/init.c new file mode 100644 index 0000000000000000000000000000000000000000..d3ce53dda12204d835255d0e138b7ab1a1249d8d --- /dev/null +++ b/drivers/acpi/arm64/init.c @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: GPL-2.0-only +#include +#include "init.h" + +void __init acpi_arm_init(void) +{ + if (IS_ENABLED(CONFIG_ACPI_AGDI)) + acpi_agdi_init(); + if (IS_ENABLED(CONFIG_ACPI_APMT)) + acpi_apmt_init(); + if (IS_ENABLED(CONFIG_ACPI_IORT)) + acpi_iort_init(); +} diff --git a/drivers/acpi/arm64/init.h b/drivers/acpi/arm64/init.h new file mode 100644 index 0000000000000000000000000000000000000000..a1715a2a34e924cf75891f2a1f428b6a49a10ace --- /dev/null +++ b/drivers/acpi/arm64/init.h @@ -0,0 +1,6 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +#include + +void __init acpi_agdi_init(void); +void __init acpi_apmt_init(void); +void __init acpi_iort_init(void); diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c index 38fb84974f352cc8e8d734bb10dd676668327425..3631230a61c8f52bc77334d5344b5b235eb405a2 100644 --- a/drivers/acpi/arm64/iort.c +++ b/drivers/acpi/arm64/iort.c @@ -19,6 +19,7 @@ #include #include #include +#include "init.h" #define IORT_TYPE_MASK(type) (1 << (type)) #define IORT_MSI_TYPE (1 << ACPI_IORT_NODE_ITS_GROUP) diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index d161ff707de4a6ca4193c96afc53c1b2c7944950..2fc2b43a4ed3877e8a41a6f62d21b55340317723 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -26,9 +26,6 @@ #include #include #endif -#include -#include -#include #include #include #include @@ -530,65 +527,30 @@ static void acpi_notify_device(acpi_handle handle, u32 event, void *data) acpi_drv->ops.notify(device, event); } -static void acpi_notify_device_fixed(void *data) -{ - struct acpi_device *device = data; - - /* Fixed hardware devices have no handles */ - acpi_notify_device(NULL, ACPI_FIXED_HARDWARE_EVENT, device); -} - -static u32 acpi_device_fixed_event(void *data) -{ - acpi_os_execute(OSL_NOTIFY_HANDLER, acpi_notify_device_fixed, data); - return ACPI_INTERRUPT_HANDLED; -} - static int acpi_device_install_notify_handler(struct acpi_device *device, struct acpi_driver *acpi_drv) { - acpi_status status; - - if (device->device_type == ACPI_BUS_TYPE_POWER_BUTTON) { - status = - acpi_install_fixed_event_handler(ACPI_EVENT_POWER_BUTTON, - acpi_device_fixed_event, - device); - } else if (device->device_type == ACPI_BUS_TYPE_SLEEP_BUTTON) { - status = - acpi_install_fixed_event_handler(ACPI_EVENT_SLEEP_BUTTON, - acpi_device_fixed_event, - device); - } else { - u32 type = acpi_drv->flags & ACPI_DRIVER_ALL_NOTIFY_EVENTS ? + u32 type = acpi_drv->flags & ACPI_DRIVER_ALL_NOTIFY_EVENTS ? ACPI_ALL_NOTIFY : ACPI_DEVICE_NOTIFY; + acpi_status status; - status = acpi_install_notify_handler(device->handle, type, - acpi_notify_device, - device); - } - + status = acpi_install_notify_handler(device->handle, type, + acpi_notify_device, device); if (ACPI_FAILURE(status)) return -EINVAL; + return 0; } static void acpi_device_remove_notify_handler(struct acpi_device *device, struct acpi_driver *acpi_drv) { - if (device->device_type == ACPI_BUS_TYPE_POWER_BUTTON) { - acpi_remove_fixed_event_handler(ACPI_EVENT_POWER_BUTTON, - acpi_device_fixed_event); - } else if (device->device_type == ACPI_BUS_TYPE_SLEEP_BUTTON) { - acpi_remove_fixed_event_handler(ACPI_EVENT_SLEEP_BUTTON, - acpi_device_fixed_event); - } else { - u32 type = acpi_drv->flags & ACPI_DRIVER_ALL_NOTIFY_EVENTS ? + u32 type = acpi_drv->flags & ACPI_DRIVER_ALL_NOTIFY_EVENTS ? ACPI_ALL_NOTIFY : ACPI_DEVICE_NOTIFY; - acpi_remove_notify_handler(device->handle, type, - acpi_notify_device); - } + acpi_remove_notify_handler(device->handle, type, + acpi_notify_device); + acpi_os_wait_events_complete(); } @@ -720,7 +682,7 @@ bool acpi_device_is_first_physical_node(struct acpi_device *adev, * resources available from it but they will be matched normally using functions * provided by their bus types (and analogously for their modalias). */ -struct acpi_device *acpi_companion_match(const struct device *dev) +const struct acpi_device *acpi_companion_match(const struct device *dev) { struct acpi_device *adev; @@ -744,7 +706,7 @@ struct acpi_device *acpi_companion_match(const struct device *dev) * identifiers and a _DSD object with the "compatible" property, use that * property to match against the given list of identifiers. */ -static bool acpi_of_match_device(struct acpi_device *adev, +static bool acpi_of_match_device(const struct acpi_device *adev, const struct of_device_id *of_match_table, const struct of_device_id **of_id) { @@ -846,7 +808,7 @@ static bool __acpi_match_device_cls(const struct acpi_device_id *id, return true; } -static bool __acpi_match_device(struct acpi_device *device, +static bool __acpi_match_device(const struct acpi_device *device, const struct acpi_device_id *acpi_ids, const struct of_device_id *of_ids, const struct acpi_device_id **acpi_id, @@ -888,6 +850,26 @@ static bool __acpi_match_device(struct acpi_device *device, return true; } +/** + * acpi_match_acpi_device - Match an ACPI device against a given list of ACPI IDs + * @ids: Array of struct acpi_device_id objects to match against. + * @adev: The ACPI device pointer to match. + * + * Match the ACPI device @adev against a given list of ACPI IDs @ids. + * + * Return: + * a pointer to the first matching ACPI ID on success or %NULL on failure. + */ +const struct acpi_device_id *acpi_match_acpi_device(const struct acpi_device_id *ids, + const struct acpi_device *adev) +{ + const struct acpi_device_id *id = NULL; + + __acpi_match_device(adev, ids, NULL, &id, NULL); + return id; +} +EXPORT_SYMBOL_GPL(acpi_match_acpi_device); + /** * acpi_match_device - Match a struct device against a given list of ACPI IDs * @ids: Array of struct acpi_device_id object to match against. @@ -902,10 +884,7 @@ static bool __acpi_match_device(struct acpi_device *device, const struct acpi_device_id *acpi_match_device(const struct acpi_device_id *ids, const struct device *dev) { - const struct acpi_device_id *id = NULL; - - __acpi_match_device(acpi_companion_match(dev), ids, NULL, &id, NULL); - return id; + return acpi_match_acpi_device(ids, acpi_companion_match(dev)); } EXPORT_SYMBOL_GPL(acpi_match_device); @@ -1408,7 +1387,7 @@ static int __init acpi_init(void) acpi_init_ffh(); pci_mmcfg_late_init(); - acpi_iort_init(); + acpi_arm_init(); acpi_viot_early_init(); acpi_hest_init(); acpi_ghes_init(); @@ -1420,8 +1399,6 @@ static int __init acpi_init(void) acpi_debugger_init(); acpi_setup_sb_notify_handler(); acpi_viot_init(); - acpi_agdi_init(); - acpi_apmt_init(); return 0; } diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c index 475e1eddfa3b4ae162bb88157a29619ca58a2290..1e76a64cce0a911ceca550086fe2b1256ac98a02 100644 --- a/drivers/acpi/button.c +++ b/drivers/acpi/button.c @@ -77,6 +77,15 @@ static const struct dmi_system_id dmi_lid_quirks[] = { }, .driver_data = (void *)(long)ACPI_BUTTON_LID_INIT_DISABLED, }, + { + /* Nextbook Ares 8A tablet, _LID device always reports lid closed */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Insyde"), + DMI_MATCH(DMI_PRODUCT_NAME, "CherryTrail"), + DMI_MATCH(DMI_BIOS_VERSION, "M882"), + }, + .driver_data = (void *)(long)ACPI_BUTTON_LID_INIT_DISABLED, + }, { /* * Lenovo Yoga 9 14ITL5, initial notification of the LID device @@ -126,7 +135,6 @@ static const struct dmi_system_id dmi_lid_quirks[] = { static int acpi_button_add(struct acpi_device *device); static void acpi_button_remove(struct acpi_device *device); -static void acpi_button_notify(struct acpi_device *device, u32 event); #ifdef CONFIG_PM_SLEEP static int acpi_button_suspend(struct device *dev); @@ -144,7 +152,6 @@ static struct acpi_driver acpi_button_driver = { .ops = { .add = acpi_button_add, .remove = acpi_button_remove, - .notify = acpi_button_notify, }, .drv.pm = &acpi_button_pm, }; @@ -400,45 +407,65 @@ static void acpi_lid_initialize_state(struct acpi_device *device) button->lid_state_initialized = true; } -static void acpi_button_notify(struct acpi_device *device, u32 event) +static void acpi_lid_notify(acpi_handle handle, u32 event, void *data) { - struct acpi_button *button = acpi_driver_data(device); + struct acpi_device *device = data; + struct acpi_button *button; + + if (event != ACPI_BUTTON_NOTIFY_STATUS) { + acpi_handle_debug(device->handle, "Unsupported event [0x%x]\n", + event); + return; + } + + button = acpi_driver_data(device); + if (!button->lid_state_initialized) + return; + + acpi_lid_update_state(device, true); +} + +static void acpi_button_notify(acpi_handle handle, u32 event, void *data) +{ + struct acpi_device *device = data; + struct acpi_button *button; struct input_dev *input; + int keycode; - switch (event) { - case ACPI_FIXED_HARDWARE_EVENT: - event = ACPI_BUTTON_NOTIFY_STATUS; - fallthrough; - case ACPI_BUTTON_NOTIFY_STATUS: - input = button->input; - if (button->type == ACPI_BUTTON_TYPE_LID) { - if (button->lid_state_initialized) - acpi_lid_update_state(device, true); - } else { - int keycode; - - acpi_pm_wakeup_event(&device->dev); - if (button->suspended) - break; - - keycode = test_bit(KEY_SLEEP, input->keybit) ? - KEY_SLEEP : KEY_POWER; - input_report_key(input, keycode, 1); - input_sync(input); - input_report_key(input, keycode, 0); - input_sync(input); - - acpi_bus_generate_netlink_event( - device->pnp.device_class, - dev_name(&device->dev), - event, ++button->pushed); - } - break; - default: + if (event != ACPI_BUTTON_NOTIFY_STATUS) { acpi_handle_debug(device->handle, "Unsupported event [0x%x]\n", event); - break; + return; } + + acpi_pm_wakeup_event(&device->dev); + + button = acpi_driver_data(device); + if (button->suspended) + return; + + input = button->input; + keycode = test_bit(KEY_SLEEP, input->keybit) ? KEY_SLEEP : KEY_POWER; + + input_report_key(input, keycode, 1); + input_sync(input); + input_report_key(input, keycode, 0); + input_sync(input); + + acpi_bus_generate_netlink_event(device->pnp.device_class, + dev_name(&device->dev), + event, ++button->pushed); +} + +static void acpi_button_notify_run(void *data) +{ + acpi_button_notify(NULL, ACPI_BUTTON_NOTIFY_STATUS, data); +} + +static u32 acpi_button_event(void *data) +{ + acpi_os_execute(OSL_NOTIFY_HANDLER, acpi_button_notify_run, data); + return ACPI_INTERRUPT_HANDLED; } #ifdef CONFIG_PM_SLEEP @@ -480,11 +507,13 @@ static int acpi_lid_input_open(struct input_dev *input) static int acpi_button_add(struct acpi_device *device) { + acpi_notify_handler handler; struct acpi_button *button; struct input_dev *input; const char *hid = acpi_device_hid(device); + acpi_status status; char *name, *class; - int error; + int error = 0; if (!strcmp(hid, ACPI_BUTTON_HID_LID) && lid_init_state == ACPI_BUTTON_LID_INIT_DISABLED) @@ -508,17 +537,20 @@ static int acpi_button_add(struct acpi_device *device) if (!strcmp(hid, ACPI_BUTTON_HID_POWER) || !strcmp(hid, ACPI_BUTTON_HID_POWERF)) { button->type = ACPI_BUTTON_TYPE_POWER; + handler = acpi_button_notify; strcpy(name, ACPI_BUTTON_DEVICE_NAME_POWER); sprintf(class, "%s/%s", ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_POWER); } else if (!strcmp(hid, ACPI_BUTTON_HID_SLEEP) || !strcmp(hid, ACPI_BUTTON_HID_SLEEPF)) { button->type = ACPI_BUTTON_TYPE_SLEEP; + handler = acpi_button_notify; strcpy(name, ACPI_BUTTON_DEVICE_NAME_SLEEP); sprintf(class, "%s/%s", ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_SLEEP); } else if (!strcmp(hid, ACPI_BUTTON_HID_LID)) { button->type = ACPI_BUTTON_TYPE_LID; + handler = acpi_lid_notify; strcpy(name, ACPI_BUTTON_DEVICE_NAME_LID); sprintf(class, "%s/%s", ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_LID); @@ -526,12 +558,15 @@ static int acpi_button_add(struct acpi_device *device) } else { pr_info("Unsupported hid [%s]\n", hid); error = -ENODEV; - goto err_free_input; } - error = acpi_button_add_fs(device); - if (error) - goto err_free_input; + if (!error) + error = acpi_button_add_fs(device); + + if (error) { + input_free_device(input); + goto err_free_button; + } snprintf(button->phys, sizeof(button->phys), "%s/button/input0", hid); @@ -559,6 +594,29 @@ static int acpi_button_add(struct acpi_device *device) error = input_register_device(input); if (error) goto err_remove_fs; + + switch (device->device_type) { + case ACPI_BUS_TYPE_POWER_BUTTON: + status = acpi_install_fixed_event_handler(ACPI_EVENT_POWER_BUTTON, + acpi_button_event, + device); + break; + case ACPI_BUS_TYPE_SLEEP_BUTTON: + status = acpi_install_fixed_event_handler(ACPI_EVENT_SLEEP_BUTTON, + acpi_button_event, + device); + break; + default: + status = acpi_install_notify_handler(device->handle, + ACPI_DEVICE_NOTIFY, handler, + device); + break; + } + if (ACPI_FAILURE(status)) { + error = -ENODEV; + goto err_input_unregister; + } + if (button->type == ACPI_BUTTON_TYPE_LID) { /* * This assumes there's only one lid device, or if there are @@ -571,11 +629,11 @@ static int acpi_button_add(struct acpi_device *device) pr_info("%s [%s]\n", name, acpi_device_bid(device)); return 0; - err_remove_fs: +err_input_unregister: + input_unregister_device(input); +err_remove_fs: acpi_button_remove_fs(device); - err_free_input: - input_free_device(input); - err_free_button: +err_free_button: kfree(button); return error; } @@ -584,6 +642,24 @@ static void acpi_button_remove(struct acpi_device *device) { struct acpi_button *button = acpi_driver_data(device); + switch (device->device_type) { + case ACPI_BUS_TYPE_POWER_BUTTON: + acpi_remove_fixed_event_handler(ACPI_EVENT_POWER_BUTTON, + acpi_button_event); + break; + case ACPI_BUS_TYPE_SLEEP_BUTTON: + acpi_remove_fixed_event_handler(ACPI_EVENT_SLEEP_BUTTON, + acpi_button_event); + break; + default: + acpi_remove_notify_handler(device->handle, ACPI_DEVICE_NOTIFY, + button->type == ACPI_BUTTON_TYPE_LID ? + acpi_lid_notify : + acpi_button_notify); + break; + } + acpi_os_wait_events_complete(); + acpi_button_remove_fs(device); input_unregister_device(button->input); kfree(button); diff --git a/drivers/acpi/device_sysfs.c b/drivers/acpi/device_sysfs.c index 0fbfbaa8d8e3d223f793a2d974430a43189c7830..b9bbf0746199215b77b0a769fdefd92ab350eb53 100644 --- a/drivers/acpi/device_sysfs.c +++ b/drivers/acpi/device_sysfs.c @@ -283,7 +283,7 @@ int acpi_device_uevent_modalias(const struct device *dev, struct kobj_uevent_env } EXPORT_SYMBOL_GPL(acpi_device_uevent_modalias); -static int __acpi_device_modalias(struct acpi_device *adev, char *buf, int size) +static int __acpi_device_modalias(const struct acpi_device *adev, char *buf, int size) { int len, count; diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 928899ab950262383282a81aba62f5604494484c..660834a49c1f9ead66252f74685c2bbf8b90b2f4 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -662,21 +662,6 @@ static void advance_transaction(struct acpi_ec *ec, bool interrupt) ec_dbg_stm("%s (%d)", interrupt ? "IRQ" : "TASK", smp_processor_id()); - /* - * Clear GPE_STS upfront to allow subsequent hardware GPE_STS 0->1 - * changes to always trigger a GPE interrupt. - * - * GPE STS is a W1C register, which means: - * - * 1. Software can clear it without worrying about clearing the other - * GPEs' STS bits when the hardware sets them in parallel. - * - * 2. As long as software can ensure only clearing it when it is set, - * hardware won't set it in parallel. - */ - if (ec->gpe >= 0 && acpi_ec_gpe_status_set(ec)) - acpi_clear_gpe(NULL, ec->gpe); - status = acpi_ec_read_status(ec); /* @@ -1282,12 +1267,34 @@ static void acpi_ec_event_handler(struct work_struct *work) spin_unlock_irq(&ec->lock); } +static void clear_gpe_and_advance_transaction(struct acpi_ec *ec, bool interrupt) +{ + /* + * Clear GPE_STS upfront to allow subsequent hardware GPE_STS 0->1 + * changes to always trigger a GPE interrupt. + * + * GPE STS is a W1C register, which means: + * + * 1. Software can clear it without worrying about clearing the other + * GPEs' STS bits when the hardware sets them in parallel. + * + * 2. As long as software can ensure only clearing it when it is set, + * hardware won't set it in parallel. + */ + if (ec->gpe >= 0 && acpi_ec_gpe_status_set(ec)) + acpi_clear_gpe(NULL, ec->gpe); + + advance_transaction(ec, true); +} + static void acpi_ec_handle_interrupt(struct acpi_ec *ec) { unsigned long flags; spin_lock_irqsave(&ec->lock, flags); - advance_transaction(ec, true); + + clear_gpe_and_advance_transaction(ec, true); + spin_unlock_irqrestore(&ec->lock, flags); } @@ -2082,7 +2089,7 @@ bool acpi_ec_dispatch_gpe(void) if (acpi_ec_gpe_status_set(first_ec)) { pm_pr_dbg("ACPI EC GPE status set\n"); - advance_transaction(first_ec, false); + clear_gpe_and_advance_transaction(first_ec, false); work_in_progress = acpi_ec_work_in_progress(first_ec); } diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index 06ad497067acf8709f18ab8fe8c21addbbff7edf..f4148dc50b9c233940c1054ab54a42a8d0727e5a 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -11,6 +11,8 @@ #include +extern struct acpi_device *acpi_root; + int early_acpi_osi_init(void); int acpi_osi_init(void); acpi_status acpi_os_initialize1(void); @@ -119,7 +121,7 @@ int acpi_bus_register_early_device(int type); /* -------------------------------------------------------------------------- Device Matching and Notification -------------------------------------------------------------------------- */ -struct acpi_device *acpi_companion_match(const struct device *dev); +const struct acpi_device *acpi_companion_match(const struct device *dev); int __acpi_device_uevent_modalias(const struct acpi_device *adev, struct kobj_uevent_env *env); diff --git a/drivers/acpi/nfit/nfit.h b/drivers/acpi/nfit/nfit.h index 6023ad61831aa3a1d7f1d9c12c65dad20775bc70..573bc0de29908f2b70b64f5deb0cb7687147f90d 100644 --- a/drivers/acpi/nfit/nfit.h +++ b/drivers/acpi/nfit/nfit.h @@ -347,4 +347,6 @@ int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm, void acpi_nfit_desc_init(struct acpi_nfit_desc *acpi_desc, struct device *dev); bool intel_fwa_supported(struct nvdimm_bus *nvdimm_bus); extern struct device_attribute dev_attr_firmware_activate_noidle; +void nfit_intel_shutdown_status(struct nfit_mem *nfit_mem); + #endif /* __NFIT_H__ */ diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 3269a888fb7a97a3566be8eaa76ad17eb0843805..f725813d0cce6a4c5e0418334a9d4bd812dc8ef8 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -276,7 +276,7 @@ acpi_map_lookup_virt(void __iomem *virt, acpi_size size) return NULL; } -#if defined(CONFIG_IA64) || defined(CONFIG_ARM64) +#if defined(CONFIG_IA64) || defined(CONFIG_ARM64) || defined(CONFIG_RISCV) /* ioremap will take care of cache attributes */ #define should_use_kmap(pfn) 0 #else diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index 2ac48cda5b2014ad8494a170d3175f3586a76db4..d6606a9f2da664a4cf1b87183133d6f0591db7ee 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c @@ -106,6 +106,32 @@ static int map_gicc_mpidr(struct acpi_subtable_header *entry, return -EINVAL; } +/* + * Retrieve the RISC-V hartid for the processor + */ +static int map_rintc_hartid(struct acpi_subtable_header *entry, + int device_declaration, u32 acpi_id, + phys_cpuid_t *hartid) +{ + struct acpi_madt_rintc *rintc = + container_of(entry, struct acpi_madt_rintc, header); + + if (!(rintc->flags & ACPI_MADT_ENABLED)) + return -ENODEV; + + /* device_declaration means Device object in DSDT, in the + * RISC-V, logical processors are required to + * have a Processor Device object in the DSDT, so we should + * check device_declaration here + */ + if (device_declaration && rintc->uid == acpi_id) { + *hartid = rintc->hart_id; + return 0; + } + + return -EINVAL; +} + static phys_cpuid_t map_madt_entry(struct acpi_table_madt *madt, int type, u32 acpi_id) { @@ -136,6 +162,9 @@ static phys_cpuid_t map_madt_entry(struct acpi_table_madt *madt, } else if (header->type == ACPI_MADT_TYPE_GENERIC_INTERRUPT) { if (!map_gicc_mpidr(header, type, acpi_id, &phys_id)) break; + } else if (header->type == ACPI_MADT_TYPE_RINTC) { + if (!map_rintc_hartid(header, type, acpi_id, &phys_id)) + break; } entry += header->length; } diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 9718d07cc2a2b2fefc5cbeb4e501a9e31911f4f8..dc615ef6550a12b58592de70fddbd4a9f8f6304d 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -597,10 +597,6 @@ static int acpi_idle_play_dead(struct cpuidle_device *dev, int index) io_idle(cx->address); } else return -ENODEV; - -#if defined(CONFIG_X86) && defined(CONFIG_HOTPLUG_CPU) - cond_wakeup_cpu0(); -#endif } /* Never reached */ diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c index 0800a9d77558069edc16243098183b16f5f78e39..1dd8d5aebf678900e7d6abd6d8d03e1d18f4b1f7 100644 --- a/drivers/acpi/resource.c +++ b/drivers/acpi/resource.c @@ -470,52 +470,6 @@ static const struct dmi_system_id asus_laptop[] = { { } }; -static const struct dmi_system_id lenovo_laptop[] = { - { - .ident = "LENOVO IdeaPad Flex 5 14ALC7", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_NAME, "82R9"), - }, - }, - { - .ident = "LENOVO IdeaPad Flex 5 16ALC7", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_NAME, "82RA"), - }, - }, - { } -}; - -static const struct dmi_system_id tongfang_gm_rg[] = { - { - .ident = "TongFang GMxRGxx/XMG CORE 15 (M22)/TUXEDO Stellaris 15 Gen4 AMD", - .matches = { - DMI_MATCH(DMI_BOARD_NAME, "GMxRGxx"), - }, - }, - { } -}; - -static const struct dmi_system_id maingear_laptop[] = { - { - .ident = "MAINGEAR Vector Pro 2 15", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Micro Electronics Inc"), - DMI_MATCH(DMI_PRODUCT_NAME, "MG-VCP2-15A3070T"), - } - }, - { - .ident = "MAINGEAR Vector Pro 2 17", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Micro Electronics Inc"), - DMI_MATCH(DMI_PRODUCT_NAME, "MG-VCP2-17A3070T"), - }, - }, - { } -}; - static const struct dmi_system_id lg_laptop[] = { { .ident = "LG Electronics 17U70P", @@ -539,10 +493,6 @@ struct irq_override_cmp { static const struct irq_override_cmp override_table[] = { { medion_laptop, 1, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW, 0, false }, { asus_laptop, 1, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW, 0, false }, - { lenovo_laptop, 6, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW, 0, true }, - { lenovo_laptop, 10, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW, 0, true }, - { tongfang_gm_rg, 1, ACPI_EDGE_SENSITIVE, ACPI_ACTIVE_LOW, 1, true }, - { maingear_laptop, 1, ACPI_EDGE_SENSITIVE, ACPI_ACTIVE_LOW, 1, true }, { lg_laptop, 1, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW, 0, false }, }; @@ -562,16 +512,6 @@ static bool acpi_dev_irq_override(u32 gsi, u8 triggering, u8 polarity, return entry->override; } -#ifdef CONFIG_X86 - /* - * IRQ override isn't needed on modern AMD Zen systems and - * this override breaks active low IRQs on AMD Ryzen 6000 and - * newer systems. Skip it. - */ - if (boot_cpu_has(X86_FEATURE_ZEN)) - return false; -#endif - return true; } diff --git a/drivers/acpi/riscv/Makefile b/drivers/acpi/riscv/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..8b3b126e0b940bd1492c759c6f267acd6d0f1dc6 --- /dev/null +++ b/drivers/acpi/riscv/Makefile @@ -0,0 +1,2 @@ +# SPDX-License-Identifier: GPL-2.0-only +obj-y += rhct.o diff --git a/drivers/acpi/riscv/rhct.c b/drivers/acpi/riscv/rhct.c new file mode 100644 index 0000000000000000000000000000000000000000..b280b3e9c7d94d8c04c442056cb990ee75f49731 --- /dev/null +++ b/drivers/acpi/riscv/rhct.c @@ -0,0 +1,83 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2022-2023, Ventana Micro Systems Inc + * Author: Sunil V L + * + */ + +#define pr_fmt(fmt) "ACPI: RHCT: " fmt + +#include + +static struct acpi_table_header *acpi_get_rhct(void) +{ + static struct acpi_table_header *rhct; + acpi_status status; + + /* + * RHCT will be used at runtime on every CPU, so we + * don't need to call acpi_put_table() to release the table mapping. + */ + if (!rhct) { + status = acpi_get_table(ACPI_SIG_RHCT, 0, &rhct); + if (ACPI_FAILURE(status)) { + pr_warn_once("No RHCT table found\n"); + return NULL; + } + } + + return rhct; +} + +/* + * During early boot, the caller should call acpi_get_table() and pass its pointer to + * these functions(and free up later). At run time, since this table can be used + * multiple times, NULL may be passed in order to use the cached table. + */ +int acpi_get_riscv_isa(struct acpi_table_header *table, unsigned int cpu, const char **isa) +{ + struct acpi_rhct_node_header *node, *ref_node, *end; + u32 size_hdr = sizeof(struct acpi_rhct_node_header); + u32 size_hartinfo = sizeof(struct acpi_rhct_hart_info); + struct acpi_rhct_hart_info *hart_info; + struct acpi_rhct_isa_string *isa_node; + struct acpi_table_rhct *rhct; + u32 *hart_info_node_offset; + u32 acpi_cpu_id = get_acpi_id_for_cpu(cpu); + + BUG_ON(acpi_disabled); + + if (!table) { + rhct = (struct acpi_table_rhct *)acpi_get_rhct(); + if (!rhct) + return -ENOENT; + } else { + rhct = (struct acpi_table_rhct *)table; + } + + end = ACPI_ADD_PTR(struct acpi_rhct_node_header, rhct, rhct->header.length); + + for (node = ACPI_ADD_PTR(struct acpi_rhct_node_header, rhct, rhct->node_offset); + node < end; + node = ACPI_ADD_PTR(struct acpi_rhct_node_header, node, node->length)) { + if (node->type == ACPI_RHCT_NODE_TYPE_HART_INFO) { + hart_info = ACPI_ADD_PTR(struct acpi_rhct_hart_info, node, size_hdr); + hart_info_node_offset = ACPI_ADD_PTR(u32, hart_info, size_hartinfo); + if (acpi_cpu_id != hart_info->uid) + continue; + + for (int i = 0; i < hart_info->num_offsets; i++) { + ref_node = ACPI_ADD_PTR(struct acpi_rhct_node_header, + rhct, hart_info_node_offset[i]); + if (ref_node->type == ACPI_RHCT_NODE_TYPE_ISA_STRING) { + isa_node = ACPI_ADD_PTR(struct acpi_rhct_isa_string, + ref_node, size_hdr); + *isa = isa_node->isa; + return 0; + } + } + } + } + + return -1; +} diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 0c6f06abe3f47f2b77879b0fd051ffb5a043be58..5b145f1aaa1b8bcd2b4e22a55ec5a91a04d1a738 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -23,8 +23,7 @@ #include #include "internal.h" - -extern struct acpi_device *acpi_root; +#include "sleep.h" #define ACPI_BUS_CLASS "system_bus" #define ACPI_BUS_HID "LNXSYBUS" @@ -930,26 +929,29 @@ static int acpi_bus_extract_wakeup_device_power_package(struct acpi_device *dev) return err; } +/* Do not use a button for S5 wakeup */ +#define ACPI_AVOID_WAKE_FROM_S5 BIT(0) + static bool acpi_wakeup_gpe_init(struct acpi_device *device) { static const struct acpi_device_id button_device_ids[] = { - {"PNP0C0C", 0}, /* Power button */ - {"PNP0C0D", 0}, /* Lid */ - {"PNP0C0E", 0}, /* Sleep button */ + {"PNP0C0C", 0}, /* Power button */ + {"PNP0C0D", ACPI_AVOID_WAKE_FROM_S5}, /* Lid */ + {"PNP0C0E", ACPI_AVOID_WAKE_FROM_S5}, /* Sleep button */ {"", 0}, }; struct acpi_device_wakeup *wakeup = &device->wakeup; + const struct acpi_device_id *match; acpi_status status; wakeup->flags.notifier_present = 0; /* Power button, Lid switch always enable wakeup */ - if (!acpi_match_device_ids(device, button_device_ids)) { - if (!acpi_match_device_ids(device, &button_device_ids[1])) { - /* Do not use Lid/sleep button for S5 wakeup */ - if (wakeup->sleep_state == ACPI_STATE_S5) - wakeup->sleep_state = ACPI_STATE_S4; - } + match = acpi_match_acpi_device(button_device_ids, device); + if (match) { + if ((match->driver_data & ACPI_AVOID_WAKE_FROM_S5) && + wakeup->sleep_state == ACPI_STATE_S5) + wakeup->sleep_state = ACPI_STATE_S4; acpi_mark_gpe_for_wake(wakeup->gpe_device, wakeup->gpe_number); device_set_wakeup_capable(&device->dev, true); return true; @@ -2029,8 +2031,6 @@ static u32 acpi_scan_check_dep(acpi_handle handle, bool check_dep) return count; } -static bool acpi_bus_scan_second_pass; - static acpi_status acpi_bus_check_add(acpi_handle handle, bool check_dep, struct acpi_device **adev_p) { @@ -2050,10 +2050,8 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, bool check_dep, return AE_OK; /* Bail out if there are dependencies. */ - if (acpi_scan_check_dep(handle, check_dep) > 0) { - acpi_bus_scan_second_pass = true; + if (acpi_scan_check_dep(handle, check_dep) > 0) return AE_CTRL_DEPTH; - } fallthrough; case ACPI_TYPE_ANY: /* for ACPI_ROOT_OBJECT */ @@ -2301,6 +2299,12 @@ static bool acpi_scan_clear_dep_queue(struct acpi_device *adev) return true; } +static void acpi_scan_delete_dep_data(struct acpi_dep_data *dep) +{ + list_del(&dep->node); + kfree(dep); +} + static int acpi_scan_clear_dep(struct acpi_dep_data *dep, void *data) { struct acpi_device *adev = acpi_get_acpi_dev(dep->consumer); @@ -2311,8 +2315,10 @@ static int acpi_scan_clear_dep(struct acpi_dep_data *dep, void *data) acpi_dev_put(adev); } - list_del(&dep->node); - kfree(dep); + if (dep->free_when_met) + acpi_scan_delete_dep_data(dep); + else + dep->met = true; return 0; } @@ -2406,6 +2412,55 @@ struct acpi_device *acpi_dev_get_next_consumer_dev(struct acpi_device *supplier, } EXPORT_SYMBOL_GPL(acpi_dev_get_next_consumer_dev); +static void acpi_scan_postponed_branch(acpi_handle handle) +{ + struct acpi_device *adev = NULL; + + if (ACPI_FAILURE(acpi_bus_check_add(handle, false, &adev))) + return; + + acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, + acpi_bus_check_add_2, NULL, NULL, (void **)&adev); + acpi_bus_attach(adev, NULL); +} + +static void acpi_scan_postponed(void) +{ + struct acpi_dep_data *dep, *tmp; + + mutex_lock(&acpi_dep_list_lock); + + list_for_each_entry_safe(dep, tmp, &acpi_dep_list, node) { + acpi_handle handle = dep->consumer; + + /* + * In case there are multiple acpi_dep_list entries with the + * same consumer, skip the current entry if the consumer device + * object corresponding to it is present already. + */ + if (!acpi_fetch_acpi_dev(handle)) { + /* + * Even though the lock is released here, tmp is + * guaranteed to be valid, because none of the list + * entries following dep is marked as "free when met" + * and so they cannot be deleted. + */ + mutex_unlock(&acpi_dep_list_lock); + + acpi_scan_postponed_branch(handle); + + mutex_lock(&acpi_dep_list_lock); + } + + if (dep->met) + acpi_scan_delete_dep_data(dep); + else + dep->free_when_met = true; + } + + mutex_unlock(&acpi_dep_list_lock); +} + /** * acpi_bus_scan - Add ACPI device node objects in a given namespace scope. * @handle: Root of the namespace scope to scan. @@ -2424,8 +2479,6 @@ int acpi_bus_scan(acpi_handle handle) { struct acpi_device *device = NULL; - acpi_bus_scan_second_pass = false; - /* Pass 1: Avoid enumerating devices with missing dependencies. */ if (ACPI_SUCCESS(acpi_bus_check_add(handle, true, &device))) @@ -2438,19 +2491,9 @@ int acpi_bus_scan(acpi_handle handle) acpi_bus_attach(device, (void *)true); - if (!acpi_bus_scan_second_pass) - return 0; - /* Pass 2: Enumerate all of the remaining devices. */ - device = NULL; - - if (ACPI_SUCCESS(acpi_bus_check_add(handle, false, &device))) - acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, - acpi_bus_check_add_2, NULL, NULL, - (void **)&device); - - acpi_bus_attach(device, NULL); + acpi_scan_postponed(); return 0; } diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 72470b9f16c4577fa8fe6ec5037c5e7ce0e85f75..808484d11209761d93e10a6e4937a3e4a75d34b2 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -636,11 +636,19 @@ static int acpi_suspend_enter(suspend_state_t pm_state) } /* - * Disable and clear GPE status before interrupt is enabled. Some GPEs - * (like wakeup GPE) haven't handler, this can avoid such GPE misfire. - * acpi_leave_sleep_state will reenable specific GPEs later + * Disable all GPE and clear their status bits before interrupts are + * enabled. Some GPEs (like wakeup GPEs) have no handlers and this can + * prevent them from producing spurious interrups. + * + * acpi_leave_sleep_state() will reenable specific GPEs later. + * + * Because this code runs on one CPU with disabled interrupts (all of + * the other CPUs are offline at this time), it need not acquire any + * sleeping locks which may trigger an implicit preemption point even + * if there is no contention, so avoid doing that by using a low-level + * library routine here. */ - acpi_disable_all_gpes(); + acpi_hw_disable_all_gpes(); /* Allow EC transactions to happen. */ acpi_ec_unblock_transactions(); @@ -840,7 +848,7 @@ void __weak acpi_s2idle_setup(void) s2idle_set_ops(&acpi_s2idle_ops); } -static void acpi_sleep_suspend_setup(void) +static void __init acpi_sleep_suspend_setup(void) { bool suspend_ops_needed = false; int i; diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c index 7b4680da57d7c866f09aedeeb8b6f33d92e62edd..8ab0a82b4da41d2aad9f975db596e6d0a9375e20 100644 --- a/drivers/acpi/tables.c +++ b/drivers/acpi/tables.c @@ -220,6 +220,16 @@ void acpi_table_print_madt_entry(struct acpi_subtable_header *header) } break; + case ACPI_MADT_TYPE_RINTC: + { + struct acpi_madt_rintc *p = (struct acpi_madt_rintc *)header; + + pr_debug("RISC-V INTC (acpi_uid[0x%04x] hart_id[0x%llx] %s)\n", + p->uid, p->hart_id, + (p->flags & ACPI_MADT_ENABLED) ? "enabled" : "disabled"); + } + break; + default: pr_warn("Found unsupported MADT entry (type = 0x%x)\n", header->type); diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index 4720a3649a61bcc8e61cca40f0444a52ba95567b..f9f6ebb08fdb76f58cf1f663d04e2d00b4e8a8ee 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -40,12 +40,35 @@ #define ACPI_THERMAL_NOTIFY_HOT 0xF1 #define ACPI_THERMAL_MODE_ACTIVE 0x00 -#define ACPI_THERMAL_MAX_ACTIVE 10 -#define ACPI_THERMAL_MAX_LIMIT_STR_LEN 65 +#define ACPI_THERMAL_MAX_ACTIVE 10 +#define ACPI_THERMAL_MAX_LIMIT_STR_LEN 65 -MODULE_AUTHOR("Paul Diefenbaugh"); -MODULE_DESCRIPTION("ACPI Thermal Zone Driver"); -MODULE_LICENSE("GPL"); +#define ACPI_TRIPS_CRITICAL BIT(0) +#define ACPI_TRIPS_HOT BIT(1) +#define ACPI_TRIPS_PASSIVE BIT(2) +#define ACPI_TRIPS_ACTIVE BIT(3) +#define ACPI_TRIPS_DEVICES BIT(4) + +#define ACPI_TRIPS_THRESHOLDS (ACPI_TRIPS_PASSIVE | ACPI_TRIPS_ACTIVE) + +#define ACPI_TRIPS_INIT (ACPI_TRIPS_CRITICAL | ACPI_TRIPS_HOT | \ + ACPI_TRIPS_PASSIVE | ACPI_TRIPS_ACTIVE | \ + ACPI_TRIPS_DEVICES) + +/* + * This exception is thrown out in two cases: + * 1.An invalid trip point becomes invalid or a valid trip point becomes invalid + * when re-evaluating the AML code. + * 2.TODO: Devices listed in _PSL, _ALx, _TZD may change. + * We need to re-bind the cooling devices of a thermal zone when this occurs. + */ +#define ACPI_THERMAL_TRIPS_EXCEPTION(flags, tz, str) \ +do { \ + if (flags != ACPI_TRIPS_INIT) \ + acpi_handle_info(tz->device->handle, \ + "ACPI thermal trip point %s changed\n" \ + "Please report to linux-acpi@vger.kernel.org\n", str); \ +} while (0) static int act; module_param(act, int, 0644); @@ -73,75 +96,30 @@ MODULE_PARM_DESC(psv, "Disable or override all passive trip points."); static struct workqueue_struct *acpi_thermal_pm_queue; -static int acpi_thermal_add(struct acpi_device *device); -static void acpi_thermal_remove(struct acpi_device *device); -static void acpi_thermal_notify(struct acpi_device *device, u32 event); - -static const struct acpi_device_id thermal_device_ids[] = { - {ACPI_THERMAL_HID, 0}, - {"", 0}, -}; -MODULE_DEVICE_TABLE(acpi, thermal_device_ids); - -#ifdef CONFIG_PM_SLEEP -static int acpi_thermal_suspend(struct device *dev); -static int acpi_thermal_resume(struct device *dev); -#else -#define acpi_thermal_suspend NULL -#define acpi_thermal_resume NULL -#endif -static SIMPLE_DEV_PM_OPS(acpi_thermal_pm, acpi_thermal_suspend, acpi_thermal_resume); - -static struct acpi_driver acpi_thermal_driver = { - .name = "thermal", - .class = ACPI_THERMAL_CLASS, - .ids = thermal_device_ids, - .ops = { - .add = acpi_thermal_add, - .remove = acpi_thermal_remove, - .notify = acpi_thermal_notify, - }, - .drv.pm = &acpi_thermal_pm, -}; - -struct acpi_thermal_state { - u8 critical:1; - u8 hot:1; - u8 passive:1; - u8 active:1; - u8 reserved:4; - int active_index; -}; - -struct acpi_thermal_state_flags { - u8 valid:1; - u8 enabled:1; - u8 reserved:6; -}; - struct acpi_thermal_critical { - struct acpi_thermal_state_flags flags; unsigned long temperature; + bool valid; }; struct acpi_thermal_hot { - struct acpi_thermal_state_flags flags; unsigned long temperature; + bool valid; }; struct acpi_thermal_passive { - struct acpi_thermal_state_flags flags; + struct acpi_handle_list devices; unsigned long temperature; unsigned long tc1; unsigned long tc2; unsigned long tsp; - struct acpi_handle_list devices; + bool valid; }; struct acpi_thermal_active { - struct acpi_thermal_state_flags flags; - unsigned long temperature; struct acpi_handle_list devices; + unsigned long temperature; + bool valid; + bool enabled; }; struct acpi_thermal_trips { @@ -151,12 +129,6 @@ struct acpi_thermal_trips { struct acpi_thermal_active active[ACPI_THERMAL_MAX_ACTIVE]; }; -struct acpi_thermal_flags { - u8 cooling_mode:1; /* _SCP */ - u8 devices:1; /* _TZD */ - u8 reserved:6; -}; - struct acpi_thermal { struct acpi_device *device; acpi_bus_id name; @@ -164,8 +136,6 @@ struct acpi_thermal { unsigned long last_temperature; unsigned long polling_frequency; volatile u8 zombie; - struct acpi_thermal_flags flags; - struct acpi_thermal_state state; struct acpi_thermal_trips trips; struct acpi_handle_list devices; struct thermal_zone_device *thermal_zone; @@ -220,52 +190,12 @@ static int acpi_thermal_get_polling_frequency(struct acpi_thermal *tz) return 0; } -static int acpi_thermal_set_cooling_mode(struct acpi_thermal *tz, int mode) -{ - if (!tz) - return -EINVAL; - - if (ACPI_FAILURE(acpi_execute_simple_method(tz->device->handle, - "_SCP", mode))) - return -ENODEV; - - return 0; -} - -#define ACPI_TRIPS_CRITICAL 0x01 -#define ACPI_TRIPS_HOT 0x02 -#define ACPI_TRIPS_PASSIVE 0x04 -#define ACPI_TRIPS_ACTIVE 0x08 -#define ACPI_TRIPS_DEVICES 0x10 - -#define ACPI_TRIPS_REFRESH_THRESHOLDS (ACPI_TRIPS_PASSIVE | ACPI_TRIPS_ACTIVE) -#define ACPI_TRIPS_REFRESH_DEVICES ACPI_TRIPS_DEVICES - -#define ACPI_TRIPS_INIT (ACPI_TRIPS_CRITICAL | ACPI_TRIPS_HOT | \ - ACPI_TRIPS_PASSIVE | ACPI_TRIPS_ACTIVE | \ - ACPI_TRIPS_DEVICES) - -/* - * This exception is thrown out in two cases: - * 1.An invalid trip point becomes invalid or a valid trip point becomes invalid - * when re-evaluating the AML code. - * 2.TODO: Devices listed in _PSL, _ALx, _TZD may change. - * We need to re-bind the cooling devices of a thermal zone when this occurs. - */ -#define ACPI_THERMAL_TRIPS_EXCEPTION(flags, tz, str) \ -do { \ - if (flags != ACPI_TRIPS_INIT) \ - acpi_handle_info(tz->device->handle, \ - "ACPI thermal trip point %s changed\n" \ - "Please report to linux-acpi@vger.kernel.org\n", str); \ -} while (0) - static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag) { acpi_status status; unsigned long long tmp; struct acpi_handle_list devices; - int valid = 0; + bool valid = false; int i; /* Critical Shutdown */ @@ -279,21 +209,21 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag) * ... so lets discard those as invalid. */ if (ACPI_FAILURE(status)) { - tz->trips.critical.flags.valid = 0; + tz->trips.critical.valid = false; acpi_handle_debug(tz->device->handle, "No critical threshold\n"); } else if (tmp <= 2732) { pr_info(FW_BUG "Invalid critical threshold (%llu)\n", tmp); - tz->trips.critical.flags.valid = 0; + tz->trips.critical.valid = false; } else { - tz->trips.critical.flags.valid = 1; + tz->trips.critical.valid = true; acpi_handle_debug(tz->device->handle, "Found critical threshold [%lu]\n", tz->trips.critical.temperature); } - if (tz->trips.critical.flags.valid) { + if (tz->trips.critical.valid) { if (crt == -1) { - tz->trips.critical.flags.valid = 0; + tz->trips.critical.valid = false; } else if (crt > 0) { unsigned long crt_k = celsius_to_deci_kelvin(crt); @@ -312,12 +242,12 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag) if (flag & ACPI_TRIPS_HOT) { status = acpi_evaluate_integer(tz->device->handle, "_HOT", NULL, &tmp); if (ACPI_FAILURE(status)) { - tz->trips.hot.flags.valid = 0; + tz->trips.hot.valid = false; acpi_handle_debug(tz->device->handle, "No hot threshold\n"); } else { tz->trips.hot.temperature = tmp; - tz->trips.hot.flags.valid = 1; + tz->trips.hot.valid = true; acpi_handle_debug(tz->device->handle, "Found hot threshold [%lu]\n", tz->trips.hot.temperature); @@ -325,9 +255,9 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag) } /* Passive (optional) */ - if (((flag & ACPI_TRIPS_PASSIVE) && tz->trips.passive.flags.valid) || + if (((flag & ACPI_TRIPS_PASSIVE) && tz->trips.passive.valid) || flag == ACPI_TRIPS_INIT) { - valid = tz->trips.passive.flags.valid; + valid = tz->trips.passive.valid; if (psv == -1) { status = AE_SUPPORT; } else if (psv > 0) { @@ -339,44 +269,44 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag) } if (ACPI_FAILURE(status)) { - tz->trips.passive.flags.valid = 0; + tz->trips.passive.valid = false; } else { tz->trips.passive.temperature = tmp; - tz->trips.passive.flags.valid = 1; + tz->trips.passive.valid = true; if (flag == ACPI_TRIPS_INIT) { status = acpi_evaluate_integer(tz->device->handle, "_TC1", NULL, &tmp); if (ACPI_FAILURE(status)) - tz->trips.passive.flags.valid = 0; + tz->trips.passive.valid = false; else tz->trips.passive.tc1 = tmp; status = acpi_evaluate_integer(tz->device->handle, "_TC2", NULL, &tmp); if (ACPI_FAILURE(status)) - tz->trips.passive.flags.valid = 0; + tz->trips.passive.valid = false; else tz->trips.passive.tc2 = tmp; status = acpi_evaluate_integer(tz->device->handle, "_TSP", NULL, &tmp); if (ACPI_FAILURE(status)) - tz->trips.passive.flags.valid = 0; + tz->trips.passive.valid = false; else tz->trips.passive.tsp = tmp; } } } - if ((flag & ACPI_TRIPS_DEVICES) && tz->trips.passive.flags.valid) { + if ((flag & ACPI_TRIPS_DEVICES) && tz->trips.passive.valid) { memset(&devices, 0, sizeof(struct acpi_handle_list)); status = acpi_evaluate_reference(tz->device->handle, "_PSL", NULL, &devices); if (ACPI_FAILURE(status)) { acpi_handle_info(tz->device->handle, "Invalid passive threshold\n"); - tz->trips.passive.flags.valid = 0; + tz->trips.passive.valid = false; } else { - tz->trips.passive.flags.valid = 1; + tz->trips.passive.valid = true; } if (memcmp(&tz->trips.passive.devices, &devices, @@ -387,24 +317,24 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag) } } if ((flag & ACPI_TRIPS_PASSIVE) || (flag & ACPI_TRIPS_DEVICES)) { - if (valid != tz->trips.passive.flags.valid) + if (valid != tz->trips.passive.valid) ACPI_THERMAL_TRIPS_EXCEPTION(flag, tz, "state"); } /* Active (optional) */ for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) { char name[5] = { '_', 'A', 'C', ('0' + i), '\0' }; - valid = tz->trips.active[i].flags.valid; + valid = tz->trips.active[i].valid; if (act == -1) break; /* disable all active trip points */ if (flag == ACPI_TRIPS_INIT || ((flag & ACPI_TRIPS_ACTIVE) && - tz->trips.active[i].flags.valid)) { + tz->trips.active[i].valid)) { status = acpi_evaluate_integer(tz->device->handle, name, NULL, &tmp); if (ACPI_FAILURE(status)) { - tz->trips.active[i].flags.valid = 0; + tz->trips.active[i].valid = false; if (i == 0) break; @@ -426,21 +356,21 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag) break; } else { tz->trips.active[i].temperature = tmp; - tz->trips.active[i].flags.valid = 1; + tz->trips.active[i].valid = true; } } name[2] = 'L'; - if ((flag & ACPI_TRIPS_DEVICES) && tz->trips.active[i].flags.valid) { + if ((flag & ACPI_TRIPS_DEVICES) && tz->trips.active[i].valid) { memset(&devices, 0, sizeof(struct acpi_handle_list)); status = acpi_evaluate_reference(tz->device->handle, name, NULL, &devices); if (ACPI_FAILURE(status)) { acpi_handle_info(tz->device->handle, "Invalid active%d threshold\n", i); - tz->trips.active[i].flags.valid = 0; + tz->trips.active[i].valid = false; } else { - tz->trips.active[i].flags.valid = 1; + tz->trips.active[i].valid = true; } if (memcmp(&tz->trips.active[i].devices, &devices, @@ -451,10 +381,10 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag) } } if ((flag & ACPI_TRIPS_ACTIVE) || (flag & ACPI_TRIPS_DEVICES)) - if (valid != tz->trips.active[i].flags.valid) + if (valid != tz->trips.active[i].valid) ACPI_THERMAL_TRIPS_EXCEPTION(flag, tz, "state"); - if (!tz->trips.active[i].flags.valid) + if (!tz->trips.active[i].valid) break; } @@ -474,17 +404,18 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag) static int acpi_thermal_get_trip_points(struct acpi_thermal *tz) { - int i, valid, ret = acpi_thermal_trips_update(tz, ACPI_TRIPS_INIT); + int i, ret = acpi_thermal_trips_update(tz, ACPI_TRIPS_INIT); + bool valid; if (ret) return ret; - valid = tz->trips.critical.flags.valid | - tz->trips.hot.flags.valid | - tz->trips.passive.flags.valid; + valid = tz->trips.critical.valid | + tz->trips.hot.valid | + tz->trips.passive.valid; for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) - valid |= tz->trips.active[i].flags.valid; + valid = valid || tz->trips.active[i].valid; if (!valid) { pr_warn(FW_BUG "No valid trip found\n"); @@ -521,7 +452,7 @@ static int thermal_get_trip_type(struct thermal_zone_device *thermal, if (!tz || trip < 0) return -EINVAL; - if (tz->trips.critical.flags.valid) { + if (tz->trips.critical.valid) { if (!trip) { *type = THERMAL_TRIP_CRITICAL; return 0; @@ -529,7 +460,7 @@ static int thermal_get_trip_type(struct thermal_zone_device *thermal, trip--; } - if (tz->trips.hot.flags.valid) { + if (tz->trips.hot.valid) { if (!trip) { *type = THERMAL_TRIP_HOT; return 0; @@ -537,7 +468,7 @@ static int thermal_get_trip_type(struct thermal_zone_device *thermal, trip--; } - if (tz->trips.passive.flags.valid) { + if (tz->trips.passive.valid) { if (!trip) { *type = THERMAL_TRIP_PASSIVE; return 0; @@ -545,7 +476,7 @@ static int thermal_get_trip_type(struct thermal_zone_device *thermal, trip--; } - for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE && tz->trips.active[i].flags.valid; i++) { + for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE && tz->trips.active[i].valid; i++) { if (!trip) { *type = THERMAL_TRIP_ACTIVE; return 0; @@ -565,7 +496,7 @@ static int thermal_get_trip_temp(struct thermal_zone_device *thermal, if (!tz || trip < 0) return -EINVAL; - if (tz->trips.critical.flags.valid) { + if (tz->trips.critical.valid) { if (!trip) { *temp = deci_kelvin_to_millicelsius_with_offset( tz->trips.critical.temperature, @@ -575,7 +506,7 @@ static int thermal_get_trip_temp(struct thermal_zone_device *thermal, trip--; } - if (tz->trips.hot.flags.valid) { + if (tz->trips.hot.valid) { if (!trip) { *temp = deci_kelvin_to_millicelsius_with_offset( tz->trips.hot.temperature, @@ -585,7 +516,7 @@ static int thermal_get_trip_temp(struct thermal_zone_device *thermal, trip--; } - if (tz->trips.passive.flags.valid) { + if (tz->trips.passive.valid) { if (!trip) { *temp = deci_kelvin_to_millicelsius_with_offset( tz->trips.passive.temperature, @@ -596,7 +527,7 @@ static int thermal_get_trip_temp(struct thermal_zone_device *thermal, } for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE && - tz->trips.active[i].flags.valid; i++) { + tz->trips.active[i].valid; i++) { if (!trip) { *temp = deci_kelvin_to_millicelsius_with_offset( tz->trips.active[i].temperature, @@ -614,7 +545,7 @@ static int thermal_get_crit_temp(struct thermal_zone_device *thermal, { struct acpi_thermal *tz = thermal_zone_device_priv(thermal); - if (tz->trips.critical.flags.valid) { + if (tz->trips.critical.valid) { *temperature = deci_kelvin_to_millicelsius_with_offset( tz->trips.critical.temperature, tz->kelvin_offset); @@ -700,13 +631,13 @@ static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal, int trip = -1; int result = 0; - if (tz->trips.critical.flags.valid) + if (tz->trips.critical.valid) trip++; - if (tz->trips.hot.flags.valid) + if (tz->trips.hot.valid) trip++; - if (tz->trips.passive.flags.valid) { + if (tz->trips.passive.valid) { trip++; for (i = 0; i < tz->trips.passive.devices.count; i++) { handle = tz->trips.passive.devices.handles[i]; @@ -731,7 +662,7 @@ static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal, } for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) { - if (!tz->trips.active[i].flags.valid) + if (!tz->trips.active[i].valid) break; trip++; @@ -819,19 +750,19 @@ static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz) acpi_status status; int i; - if (tz->trips.critical.flags.valid) + if (tz->trips.critical.valid) trips++; - if (tz->trips.hot.flags.valid) + if (tz->trips.hot.valid) trips++; - if (tz->trips.passive.flags.valid) + if (tz->trips.passive.valid) trips++; - for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE && tz->trips.active[i].flags.valid; + for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE && tz->trips.active[i].valid; i++, trips++); - if (tz->trips.passive.flags.valid) + if (tz->trips.passive.valid) tz->thermal_zone = thermal_zone_device_register("acpitz", trips, 0, tz, &acpi_thermal_zone_ops, NULL, tz->trips.passive.tsp * 100, @@ -906,13 +837,13 @@ static void acpi_thermal_notify(struct acpi_device *device, u32 event) acpi_queue_thermal_check(tz); break; case ACPI_THERMAL_NOTIFY_THRESHOLDS: - acpi_thermal_trips_update(tz, ACPI_TRIPS_REFRESH_THRESHOLDS); + acpi_thermal_trips_update(tz, ACPI_TRIPS_THRESHOLDS); acpi_queue_thermal_check(tz); acpi_bus_generate_netlink_event(device->pnp.device_class, dev_name(&device->dev), event, 0); break; case ACPI_THERMAL_NOTIFY_DEVICES: - acpi_thermal_trips_update(tz, ACPI_TRIPS_REFRESH_DEVICES); + acpi_thermal_trips_update(tz, ACPI_TRIPS_DEVICES); acpi_queue_thermal_check(tz); acpi_bus_generate_netlink_event(device->pnp.device_class, dev_name(&device->dev), event, 0); @@ -976,9 +907,8 @@ static int acpi_thermal_get_info(struct acpi_thermal *tz) return result; /* Set the cooling mode [_SCP] to active cooling (default) */ - result = acpi_thermal_set_cooling_mode(tz, ACPI_THERMAL_MODE_ACTIVE); - if (!result) - tz->flags.cooling_mode = 1; + acpi_execute_simple_method(tz->device->handle, "_SCP", + ACPI_THERMAL_MODE_ACTIVE); /* Get default polling frequency [_TZP] (optional) */ if (tzp) @@ -1001,7 +931,7 @@ static int acpi_thermal_get_info(struct acpi_thermal *tz) */ static void acpi_thermal_guess_offset(struct acpi_thermal *tz) { - if (tz->trips.critical.flags.valid && + if (tz->trips.critical.valid && (tz->trips.critical.temperature % 5) == 1) tz->kelvin_offset = 273100; else @@ -1110,27 +1040,48 @@ static int acpi_thermal_resume(struct device *dev) return -EINVAL; for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) { - if (!tz->trips.active[i].flags.valid) + if (!tz->trips.active[i].valid) break; - tz->trips.active[i].flags.enabled = 1; + tz->trips.active[i].enabled = true; for (j = 0; j < tz->trips.active[i].devices.count; j++) { result = acpi_bus_update_power( tz->trips.active[i].devices.handles[j], &power_state); if (result || (power_state != ACPI_STATE_D0)) { - tz->trips.active[i].flags.enabled = 0; + tz->trips.active[i].enabled = false; break; } } - tz->state.active |= tz->trips.active[i].flags.enabled; } acpi_queue_thermal_check(tz); return AE_OK; } +#else +#define acpi_thermal_suspend NULL +#define acpi_thermal_resume NULL #endif +static SIMPLE_DEV_PM_OPS(acpi_thermal_pm, acpi_thermal_suspend, acpi_thermal_resume); + +static const struct acpi_device_id thermal_device_ids[] = { + {ACPI_THERMAL_HID, 0}, + {"", 0}, +}; +MODULE_DEVICE_TABLE(acpi, thermal_device_ids); + +static struct acpi_driver acpi_thermal_driver = { + .name = "thermal", + .class = ACPI_THERMAL_CLASS, + .ids = thermal_device_ids, + .ops = { + .add = acpi_thermal_add, + .remove = acpi_thermal_remove, + .notify = acpi_thermal_notify, + }, + .drv.pm = &acpi_thermal_pm, +}; static int thermal_act(const struct dmi_system_id *d) { if (act == 0) { @@ -1236,3 +1187,7 @@ static void __exit acpi_thermal_exit(void) module_init(acpi_thermal_init); module_exit(acpi_thermal_exit); + +MODULE_AUTHOR("Paul Diefenbaugh"); +MODULE_DESCRIPTION("ACPI Thermal Zone Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/acpi/tiny-power-button.c b/drivers/acpi/tiny-power-button.c index 598f548b21f360496bbb46467a3fbcd0b9e15aa1..6353be6fec698f07a72e3ac1a98099ad93d70923 100644 --- a/drivers/acpi/tiny-power-button.c +++ b/drivers/acpi/tiny-power-button.c @@ -19,18 +19,52 @@ static const struct acpi_device_id tiny_power_button_device_ids[] = { }; MODULE_DEVICE_TABLE(acpi, tiny_power_button_device_ids); -static int acpi_noop_add(struct acpi_device *device) +static void acpi_tiny_power_button_notify(acpi_handle handle, u32 event, void *data) { - return 0; + kill_cad_pid(power_signal, 1); } -static void acpi_noop_remove(struct acpi_device *device) +static void acpi_tiny_power_button_notify_run(void *not_used) { + acpi_tiny_power_button_notify(NULL, ACPI_FIXED_HARDWARE_EVENT, NULL); } -static void acpi_tiny_power_button_notify(struct acpi_device *device, u32 event) +static u32 acpi_tiny_power_button_event(void *not_used) { - kill_cad_pid(power_signal, 1); + acpi_os_execute(OSL_NOTIFY_HANDLER, acpi_tiny_power_button_notify_run, NULL); + return ACPI_INTERRUPT_HANDLED; +} + +static int acpi_tiny_power_button_add(struct acpi_device *device) +{ + acpi_status status; + + if (device->device_type == ACPI_BUS_TYPE_POWER_BUTTON) { + status = acpi_install_fixed_event_handler(ACPI_EVENT_POWER_BUTTON, + acpi_tiny_power_button_event, + NULL); + } else { + status = acpi_install_notify_handler(device->handle, + ACPI_DEVICE_NOTIFY, + acpi_tiny_power_button_notify, + NULL); + } + if (ACPI_FAILURE(status)) + return -ENODEV; + + return 0; +} + +static void acpi_tiny_power_button_remove(struct acpi_device *device) +{ + if (device->device_type == ACPI_BUS_TYPE_POWER_BUTTON) { + acpi_remove_fixed_event_handler(ACPI_EVENT_POWER_BUTTON, + acpi_tiny_power_button_event); + } else { + acpi_remove_notify_handler(device->handle, ACPI_DEVICE_NOTIFY, + acpi_tiny_power_button_notify); + } + acpi_os_wait_events_complete(); } static struct acpi_driver acpi_tiny_power_button_driver = { @@ -38,9 +72,8 @@ static struct acpi_driver acpi_tiny_power_button_driver = { .class = "tiny-power-button", .ids = tiny_power_button_device_ids, .ops = { - .add = acpi_noop_add, - .remove = acpi_noop_remove, - .notify = acpi_tiny_power_button_notify, + .add = acpi_tiny_power_button_add, + .remove = acpi_tiny_power_button_remove, }, }; diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c index bcc25d457581dbe3490fe699e22abef4bfdeef5d..18cc08c858cf20fa4b27b02175265aba1dd92aef 100644 --- a/drivers/acpi/video_detect.c +++ b/drivers/acpi/video_detect.c @@ -470,6 +470,22 @@ static const struct dmi_system_id video_detect_dmi_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "82BK"), }, }, + { + .callback = video_detect_force_native, + /* Lenovo ThinkPad X131e (3371 AMD version) */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "3371"), + }, + }, + { + .callback = video_detect_force_native, + /* Apple iMac11,3 */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "iMac11,3"), + }, + }, { /* https://bugzilla.redhat.com/show_bug.cgi?id=1217249 */ .callback = video_detect_force_native, @@ -512,6 +528,14 @@ static const struct dmi_system_id video_detect_dmi_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "Precision 7510"), }, }, + { + .callback = video_detect_force_native, + /* Dell Studio 1569 */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "Studio 1569"), + }, + }, { .callback = video_detect_force_native, /* Acer Aspire 3830TG */ @@ -828,6 +852,27 @@ enum acpi_backlight_type __acpi_video_get_backlight_type(bool native, bool *auto if (native_available) return acpi_backlight_native; + /* + * The vendor specific BIOS interfaces are only necessary for + * laptops from before ~2008. + * + * For laptops from ~2008 till ~2023 this point is never reached + * because on those (video_caps & ACPI_VIDEO_BACKLIGHT) above is true. + * + * Laptops from after ~2023 no longer support ACPI_VIDEO_BACKLIGHT, + * if this point is reached on those, this likely means that + * the GPU kms driver which sets native_available has not loaded yet. + * + * Returning acpi_backlight_vendor in this case is known to sometimes + * cause a non working vendor specific /sys/class/backlight device to + * get registered. + * + * Return acpi_backlight_none on laptops with ACPI tables written + * for Windows 8 (laptops from after ~2012) to avoid this problem. + */ + if (acpi_osi_is_win8()) + return acpi_backlight_none; + /* No ACPI video/native (old hw), use vendor specific fw methods. */ return acpi_backlight_vendor; } diff --git a/drivers/acpi/x86/s2idle.c b/drivers/acpi/x86/s2idle.c index e499c60c45791f8d8e02705502e2c1e8981ebd36..ce62e61a9605eb15dbfe711308b091733829843b 100644 --- a/drivers/acpi/x86/s2idle.c +++ b/drivers/acpi/x86/s2idle.c @@ -59,6 +59,7 @@ static int lps0_dsm_func_mask; static guid_t lps0_dsm_guid_microsoft; static int lps0_dsm_func_mask_microsoft; +static int lps0_dsm_state; /* Device constraint entry structure */ struct lpi_device_info { @@ -320,6 +321,44 @@ static void lpi_check_constraints(void) } } +static bool acpi_s2idle_vendor_amd(void) +{ + return boot_cpu_data.x86_vendor == X86_VENDOR_AMD; +} + +static const char *acpi_sleep_dsm_state_to_str(unsigned int state) +{ + if (lps0_dsm_func_mask_microsoft || !acpi_s2idle_vendor_amd()) { + switch (state) { + case ACPI_LPS0_SCREEN_OFF: + return "screen off"; + case ACPI_LPS0_SCREEN_ON: + return "screen on"; + case ACPI_LPS0_ENTRY: + return "lps0 entry"; + case ACPI_LPS0_EXIT: + return "lps0 exit"; + case ACPI_LPS0_MS_ENTRY: + return "lps0 ms entry"; + case ACPI_LPS0_MS_EXIT: + return "lps0 ms exit"; + } + } else { + switch (state) { + case ACPI_LPS0_SCREEN_ON_AMD: + return "screen on"; + case ACPI_LPS0_SCREEN_OFF_AMD: + return "screen off"; + case ACPI_LPS0_ENTRY_AMD: + return "lps0 entry"; + case ACPI_LPS0_EXIT_AMD: + return "lps0 exit"; + } + } + + return "unknown"; +} + static void acpi_sleep_run_lps0_dsm(unsigned int func, unsigned int func_mask, guid_t dsm_guid) { union acpi_object *out_obj; @@ -331,14 +370,15 @@ static void acpi_sleep_run_lps0_dsm(unsigned int func, unsigned int func_mask, g rev_id, func, NULL); ACPI_FREE(out_obj); - acpi_handle_debug(lps0_device_handle, "_DSM function %u evaluation %s\n", - func, out_obj ? "successful" : "failed"); + lps0_dsm_state = func; + if (pm_debug_messages_on) { + acpi_handle_info(lps0_device_handle, + "%s transitioned to state %s\n", + out_obj ? "Successfully" : "Failed to", + acpi_sleep_dsm_state_to_str(lps0_dsm_state)); + } } -static bool acpi_s2idle_vendor_amd(void) -{ - return boot_cpu_data.x86_vendor == X86_VENDOR_AMD; -} static int validate_dsm(acpi_handle handle, const char *uuid, int rev, guid_t *dsm_guid) { @@ -485,11 +525,11 @@ int acpi_s2idle_prepare_late(void) ACPI_LPS0_ENTRY, lps0_dsm_func_mask, lps0_dsm_guid); if (lps0_dsm_func_mask_microsoft > 0) { - acpi_sleep_run_lps0_dsm(ACPI_LPS0_ENTRY, - lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft); /* modern standby entry */ acpi_sleep_run_lps0_dsm(ACPI_LPS0_MS_ENTRY, lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft); + acpi_sleep_run_lps0_dsm(ACPI_LPS0_ENTRY, + lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft); } list_for_each_entry(handler, &lps0_s2idle_devops_head, list_node) { @@ -524,11 +564,6 @@ void acpi_s2idle_restore_early(void) if (handler->restore) handler->restore(); - /* Modern standby exit */ - if (lps0_dsm_func_mask_microsoft > 0) - acpi_sleep_run_lps0_dsm(ACPI_LPS0_MS_EXIT, - lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft); - /* LPS0 exit */ if (lps0_dsm_func_mask > 0) acpi_sleep_run_lps0_dsm(acpi_s2idle_vendor_amd() ? @@ -539,6 +574,11 @@ void acpi_s2idle_restore_early(void) acpi_sleep_run_lps0_dsm(ACPI_LPS0_EXIT, lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft); + /* Modern standby exit */ + if (lps0_dsm_func_mask_microsoft > 0) + acpi_sleep_run_lps0_dsm(ACPI_LPS0_MS_EXIT, + lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft); + /* Screen on */ if (lps0_dsm_func_mask_microsoft > 0) acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_ON, diff --git a/drivers/acpi/x86/utils.c b/drivers/acpi/x86/utils.c index 9c2d6f35f88a07f6b2df5fa3e307006717c6ec5e..c2b925f8cd4e41b06afa7f77529384a0e271e443 100644 --- a/drivers/acpi/x86/utils.c +++ b/drivers/acpi/x86/utils.c @@ -259,10 +259,11 @@ bool force_storage_d3(void) * drivers/platform/x86/x86-android-tablets.c kernel module. */ #define ACPI_QUIRK_SKIP_I2C_CLIENTS BIT(0) -#define ACPI_QUIRK_UART1_TTY_UART2_SKIP BIT(1) -#define ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY BIT(2) -#define ACPI_QUIRK_USE_ACPI_AC_AND_BATTERY BIT(3) -#define ACPI_QUIRK_SKIP_GPIO_EVENT_HANDLERS BIT(4) +#define ACPI_QUIRK_UART1_SKIP BIT(1) +#define ACPI_QUIRK_UART1_TTY_UART2_SKIP BIT(2) +#define ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY BIT(3) +#define ACPI_QUIRK_USE_ACPI_AC_AND_BATTERY BIT(4) +#define ACPI_QUIRK_SKIP_GPIO_EVENT_HANDLERS BIT(5) static const struct dmi_system_id acpi_quirk_skip_dmi_ids[] = { /* @@ -319,6 +320,7 @@ static const struct dmi_system_id acpi_quirk_skip_dmi_ids[] = { DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "YETI-11"), }, .driver_data = (void *)(ACPI_QUIRK_SKIP_I2C_CLIENTS | + ACPI_QUIRK_UART1_SKIP | ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY | ACPI_QUIRK_SKIP_GPIO_EVENT_HANDLERS), }, @@ -365,7 +367,7 @@ static const struct dmi_system_id acpi_quirk_skip_dmi_ids[] = { ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY), }, { - /* Nextbook Ares 8 */ + /* Nextbook Ares 8 (BYT version)*/ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Insyde"), DMI_MATCH(DMI_PRODUCT_NAME, "M890BAP"), @@ -374,6 +376,16 @@ static const struct dmi_system_id acpi_quirk_skip_dmi_ids[] = { ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY | ACPI_QUIRK_SKIP_GPIO_EVENT_HANDLERS), }, + { + /* Nextbook Ares 8A (CHT version)*/ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Insyde"), + DMI_MATCH(DMI_PRODUCT_NAME, "CherryTrail"), + DMI_MATCH(DMI_BIOS_VERSION, "M882"), + }, + .driver_data = (void *)(ACPI_QUIRK_SKIP_I2C_CLIENTS | + ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY), + }, { /* Whitelabel (sold as various brands) TM800A550L */ .matches = { @@ -392,6 +404,7 @@ static const struct dmi_system_id acpi_quirk_skip_dmi_ids[] = { #if IS_ENABLED(CONFIG_X86_ANDROID_TABLETS) static const struct acpi_device_id i2c_acpi_known_good_ids[] = { { "10EC5640", 0 }, /* RealTek ALC5640 audio codec */ + { "10EC5651", 0 }, /* RealTek ALC5651 audio codec */ { "INT33F4", 0 }, /* X-Powers AXP288 PMIC */ { "INT33FD", 0 }, /* Intel Crystal Cove PMIC */ { "INT34D3", 0 }, /* Intel Whiskey Cove PMIC */ @@ -438,6 +451,9 @@ int acpi_quirk_skip_serdev_enumeration(struct device *controller_parent, bool *s if (dmi_id) quirks = (unsigned long)dmi_id->driver_data; + if ((quirks & ACPI_QUIRK_UART1_SKIP) && uid == 1) + *skip = true; + if (quirks & ACPI_QUIRK_UART1_TTY_UART2_SKIP) { if (uid == 1) return -ENODEV; /* Create tty cdev instead of serdev */ diff --git a/drivers/android/binder.c b/drivers/android/binder.c index 8fb7672021ee2d2fc06570c29dbcb2b6f09bc993..486c8271cab7ae71cf2be952935bc034e6ae3b20 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -66,6 +66,7 @@ #include #include #include +#include #include @@ -2918,6 +2919,7 @@ static void binder_transaction(struct binder_proc *proc, binder_size_t last_fixup_min_off = 0; struct binder_context *context = proc->context; int t_debug_id = atomic_inc_return(&binder_last_id); + ktime_t t_start_time = ktime_get(); char *secctx = NULL; u32 secctx_sz = 0; struct list_head sgc_head; @@ -3159,6 +3161,7 @@ static void binder_transaction(struct binder_proc *proc, binder_stats_created(BINDER_STAT_TRANSACTION_COMPLETE); t->debug_id = t_debug_id; + t->start_time = t_start_time; if (reply) binder_debug(BINDER_DEBUG_TRANSACTION, @@ -3183,6 +3186,8 @@ static void binder_transaction(struct binder_proc *proc, t->from = thread; else t->from = NULL; + t->from_pid = proc->pid; + t->from_tid = thread->pid; t->sender_euid = task_euid(proc->tsk); t->to_proc = target_proc; t->to_thread = target_thread; @@ -5944,17 +5949,19 @@ static void print_binder_transaction_ilocked(struct seq_file *m, { struct binder_proc *to_proc; struct binder_buffer *buffer = t->buffer; + ktime_t current_time = ktime_get(); spin_lock(&t->lock); to_proc = t->to_proc; seq_printf(m, - "%s %d: %pK from %d:%d to %d:%d code %x flags %x pri %ld r%d", + "%s %d: %pK from %d:%d to %d:%d code %x flags %x pri %ld r%d elapsed %lldms", prefix, t->debug_id, t, - t->from ? t->from->proc->pid : 0, - t->from ? t->from->pid : 0, + t->from_pid, + t->from_tid, to_proc ? to_proc->pid : 0, t->to_thread ? t->to_thread->pid : 0, - t->code, t->flags, t->priority, t->need_reply); + t->code, t->flags, t->priority, t->need_reply, + ktime_ms_delta(current_time, t->start_time)); spin_unlock(&t->lock); if (proc != to_proc) { diff --git a/drivers/android/binder_internal.h b/drivers/android/binder_internal.h index 28ef5b3704b1a9b02d559b7f427bd403886ce8d1..7270d4d22207021007af32638b79b0e48bdd313c 100644 --- a/drivers/android/binder_internal.h +++ b/drivers/android/binder_internal.h @@ -515,6 +515,8 @@ struct binder_transaction { int debug_id; struct binder_work work; struct binder_thread *from; + pid_t from_pid; + pid_t from_tid; struct binder_transaction *from_parent; struct binder_proc *to_proc; struct binder_thread *to_thread; @@ -528,6 +530,7 @@ struct binder_transaction { long priority; long saved_priority; kuid_t sender_euid; + ktime_t start_time; struct list_head fd_fixups; binder_uintptr_t security_ctx; /** diff --git a/drivers/ata/ahci_brcm.c b/drivers/ata/ahci_brcm.c index 4e3dc2b6d67f8199aa1ce1c0cb712e7ba396dfd4..70c3a33eee6f24058694851e4f83b80d3a68dcdd 100644 --- a/drivers/ata/ahci_brcm.c +++ b/drivers/ata/ahci_brcm.c @@ -544,7 +544,7 @@ static int brcm_ahci_probe(struct platform_device *pdev) return ret; } -static int brcm_ahci_remove(struct platform_device *pdev) +static void brcm_ahci_remove(struct platform_device *pdev) { struct ata_host *host = dev_get_drvdata(&pdev->dev); struct ahci_host_priv *hpriv = host->private_data; @@ -552,7 +552,7 @@ static int brcm_ahci_remove(struct platform_device *pdev) brcm_sata_phys_disable(priv); - return ata_platform_remove_one(pdev); + ata_platform_remove_one(pdev); } static void brcm_ahci_shutdown(struct platform_device *pdev) @@ -573,7 +573,7 @@ static SIMPLE_DEV_PM_OPS(ahci_brcm_pm_ops, brcm_ahci_suspend, brcm_ahci_resume); static struct platform_driver brcm_ahci_driver = { .probe = brcm_ahci_probe, - .remove = brcm_ahci_remove, + .remove_new = brcm_ahci_remove, .shutdown = brcm_ahci_shutdown, .driver = { .name = DRV_NAME, diff --git a/drivers/ata/ahci_ceva.c b/drivers/ata/ahci_ceva.c index bc027468decb9a3950fc16b00be1863c5c94cc51..c2b6be083af434d2ea2a539bae101b9b7259f9cf 100644 --- a/drivers/ata/ahci_ceva.c +++ b/drivers/ata/ahci_ceva.c @@ -369,7 +369,7 @@ MODULE_DEVICE_TABLE(of, ceva_ahci_of_match); static struct platform_driver ceva_ahci_driver = { .probe = ceva_ahci_probe, - .remove = ata_platform_remove_one, + .remove_new = ata_platform_remove_one, .driver = { .name = DRV_NAME, .of_match_table = ceva_ahci_of_match, diff --git a/drivers/ata/ahci_da850.c b/drivers/ata/ahci_da850.c index ca0924dc5bd26ba424b26bd040bf83720c96b56f..55a6627d5450e7b6625cfa29e50138489b2c6f05 100644 --- a/drivers/ata/ahci_da850.c +++ b/drivers/ata/ahci_da850.c @@ -238,7 +238,7 @@ MODULE_DEVICE_TABLE(of, ahci_da850_of_match); static struct platform_driver ahci_da850_driver = { .probe = ahci_da850_probe, - .remove = ata_platform_remove_one, + .remove_new = ata_platform_remove_one, .driver = { .name = DRV_NAME, .of_match_table = ahci_da850_of_match, diff --git a/drivers/ata/ahci_dm816.c b/drivers/ata/ahci_dm816.c index b08547b877a1f77ba220e925de321ed034147d7b..4cb70064fb9944e06ca108208d597cc27a6a7e4d 100644 --- a/drivers/ata/ahci_dm816.c +++ b/drivers/ata/ahci_dm816.c @@ -182,7 +182,7 @@ MODULE_DEVICE_TABLE(of, ahci_dm816_of_match); static struct platform_driver ahci_dm816_driver = { .probe = ahci_dm816_probe, - .remove = ata_platform_remove_one, + .remove_new = ata_platform_remove_one, .driver = { .name = AHCI_DM816_DRV_NAME, .of_match_table = ahci_dm816_of_match, diff --git a/drivers/ata/ahci_dwc.c b/drivers/ata/ahci_dwc.c index 4bfbb09cdc029410aea49337cb5e72ad0792cfac..9604a2f6ed489e4ad5d9bde8ede8032446daf262 100644 --- a/drivers/ata/ahci_dwc.c +++ b/drivers/ata/ahci_dwc.c @@ -478,7 +478,7 @@ MODULE_DEVICE_TABLE(of, ahci_dwc_of_match); static struct platform_driver ahci_dwc_driver = { .probe = ahci_dwc_probe, - .remove = ata_platform_remove_one, + .remove_new = ata_platform_remove_one, .shutdown = ahci_platform_shutdown, .driver = { .name = DRV_NAME, diff --git a/drivers/ata/ahci_imx.c b/drivers/ata/ahci_imx.c index 3a8c248e7c0e88113f52044ae7889b895a8241d0..9fa005965f3b2fc7994025c3cb6f82692675c058 100644 --- a/drivers/ata/ahci_imx.c +++ b/drivers/ata/ahci_imx.c @@ -1223,7 +1223,7 @@ static SIMPLE_DEV_PM_OPS(ahci_imx_pm_ops, imx_ahci_suspend, imx_ahci_resume); static struct platform_driver imx_ahci_driver = { .probe = imx_ahci_probe, - .remove = ata_platform_remove_one, + .remove_new = ata_platform_remove_one, .driver = { .name = DRV_NAME, .of_match_table = imx_ahci_of_match, diff --git a/drivers/ata/ahci_mtk.c b/drivers/ata/ahci_mtk.c index 0bf83a297091297f2dfb87bf2c97a400395679c1..5083fb6c49277324a7e38fd44f158067c64747df 100644 --- a/drivers/ata/ahci_mtk.c +++ b/drivers/ata/ahci_mtk.c @@ -173,7 +173,7 @@ MODULE_DEVICE_TABLE(of, ahci_of_match); static struct platform_driver mtk_ahci_driver = { .probe = mtk_ahci_probe, - .remove = ata_platform_remove_one, + .remove_new = ata_platform_remove_one, .driver = { .name = DRV_NAME, .of_match_table = ahci_of_match, diff --git a/drivers/ata/ahci_mvebu.c b/drivers/ata/ahci_mvebu.c index 596cf017f42791d38dd440d3860abf1ac47db389..76450151858236df0b3c3465e28d2109ec6691fb 100644 --- a/drivers/ata/ahci_mvebu.c +++ b/drivers/ata/ahci_mvebu.c @@ -245,7 +245,7 @@ MODULE_DEVICE_TABLE(of, ahci_mvebu_of_match); static struct platform_driver ahci_mvebu_driver = { .probe = ahci_mvebu_probe, - .remove = ata_platform_remove_one, + .remove_new = ata_platform_remove_one, .suspend = ahci_mvebu_suspend, .resume = ahci_mvebu_resume, .driver = { diff --git a/drivers/ata/ahci_octeon.c b/drivers/ata/ahci_octeon.c index 5021ab3ede4904ae6aa564d60d66cb1c981f393b..e89807fa928e4bd1d158554c02e947263a67389f 100644 --- a/drivers/ata/ahci_octeon.c +++ b/drivers/ata/ahci_octeon.c @@ -16,7 +16,6 @@ #include #include -#include #define CVMX_SATA_UCTL_SHIM_CFG 0xE8 diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c index 299ee686ac49a616d029f33503cc6840e00887bf..81fc63f6b00816171e4626afa2f22584c4c11365 100644 --- a/drivers/ata/ahci_platform.c +++ b/drivers/ata/ahci_platform.c @@ -9,14 +9,14 @@ */ #include +#include #include #include #include -#include #include +#include #include #include -#include #include #include "ahci.h" @@ -56,10 +56,10 @@ static int ahci_probe(struct platform_device *pdev) if (rc) return rc; - if (of_device_is_compatible(dev->of_node, "hisilicon,hisi-ahci")) + if (device_is_compatible(dev, "hisilicon,hisi-ahci")) hpriv->flags |= AHCI_HFLAG_NO_FBS | AHCI_HFLAG_NO_NCQ; - port = acpi_device_get_match_data(dev); + port = device_get_match_data(dev); if (!port) port = &ahci_port_info; @@ -96,7 +96,7 @@ MODULE_DEVICE_TABLE(acpi, ahci_acpi_match); static struct platform_driver ahci_driver = { .probe = ahci_probe, - .remove = ata_platform_remove_one, + .remove_new = ata_platform_remove_one, .shutdown = ahci_platform_shutdown, .driver = { .name = DRV_NAME, diff --git a/drivers/ata/ahci_qoriq.c b/drivers/ata/ahci_qoriq.c index 0ba764d283c86a5fff3766b7262aad7ebdf4e3c4..3d01b118c9a1a2f8f1770525b8560f007deefc20 100644 --- a/drivers/ata/ahci_qoriq.c +++ b/drivers/ata/ahci_qoriq.c @@ -359,7 +359,7 @@ static SIMPLE_DEV_PM_OPS(ahci_qoriq_pm_ops, ahci_platform_suspend, static struct platform_driver ahci_qoriq_driver = { .probe = ahci_qoriq_probe, - .remove = ata_platform_remove_one, + .remove_new = ata_platform_remove_one, .driver = { .name = DRV_NAME, .of_match_table = ahci_qoriq_of_match, diff --git a/drivers/ata/ahci_seattle.c b/drivers/ata/ahci_seattle.c index 9eda7bbd215138e0ef00efa5f9415da237191dc8..2c32d58c6ae7543bafb327c99254ceb461b61004 100644 --- a/drivers/ata/ahci_seattle.c +++ b/drivers/ata/ahci_seattle.c @@ -187,7 +187,7 @@ MODULE_DEVICE_TABLE(acpi, ahci_acpi_match); static struct platform_driver ahci_seattle_driver = { .probe = ahci_seattle_probe, - .remove = ata_platform_remove_one, + .remove_new = ata_platform_remove_one, .driver = { .name = DRV_NAME, .acpi_match_table = ahci_acpi_match, diff --git a/drivers/ata/ahci_st.c b/drivers/ata/ahci_st.c index f2c1edb3698615e1f4ec2b92cc86c4e5eb6c5743..d4a626f87963ba123a4f07a366c28681db4714fa 100644 --- a/drivers/ata/ahci_st.c +++ b/drivers/ata/ahci_st.c @@ -239,7 +239,7 @@ static struct platform_driver st_ahci_driver = { .of_match_table = st_ahci_match, }, .probe = st_ahci_probe, - .remove = ata_platform_remove_one, + .remove_new = ata_platform_remove_one, }; module_platform_driver(st_ahci_driver); diff --git a/drivers/ata/ahci_sunxi.c b/drivers/ata/ahci_sunxi.c index 076c12b4ba08bd9a15bfc9c6b443dd09bfc48177..04531fa95e404c41ac5313f77231d603b01e7b50 100644 --- a/drivers/ata/ahci_sunxi.c +++ b/drivers/ata/ahci_sunxi.c @@ -292,7 +292,7 @@ MODULE_DEVICE_TABLE(of, ahci_sunxi_of_match); static struct platform_driver ahci_sunxi_driver = { .probe = ahci_sunxi_probe, - .remove = ata_platform_remove_one, + .remove_new = ata_platform_remove_one, .driver = { .name = DRV_NAME, .of_match_table = ahci_sunxi_of_match, diff --git a/drivers/ata/ahci_tegra.c b/drivers/ata/ahci_tegra.c index 8e5e2b359f2d2049dbd8e34ec5170c15b8cf12a5..21c20793e517780ec69c1e65d6df06a9b7315fd0 100644 --- a/drivers/ata/ahci_tegra.c +++ b/drivers/ata/ahci_tegra.c @@ -609,7 +609,7 @@ static int tegra_ahci_probe(struct platform_device *pdev) static struct platform_driver tegra_ahci_driver = { .probe = tegra_ahci_probe, - .remove = ata_platform_remove_one, + .remove_new = ata_platform_remove_one, .driver = { .name = DRV_NAME, .of_match_table = tegra_ahci_of_match, diff --git a/drivers/ata/ahci_xgene.c b/drivers/ata/ahci_xgene.c index 83f5ff54ef5b9c1537fff064a2f9f50468204d54..eb773f2e28fcbbc6eeccbc9b0eff6197e2ef6a87 100644 --- a/drivers/ata/ahci_xgene.c +++ b/drivers/ata/ahci_xgene.c @@ -868,7 +868,7 @@ static int xgene_ahci_probe(struct platform_device *pdev) static struct platform_driver xgene_ahci_driver = { .probe = xgene_ahci_probe, - .remove = ata_platform_remove_one, + .remove_new = ata_platform_remove_one, .driver = { .name = DRV_NAME, .of_match_table = xgene_ahci_of_match, diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c index 9c2cb6cbea762284b78ac1250d64fc85cd2da948..06aec35f88f2c61cf01b0b08d994585a73a4aa87 100644 --- a/drivers/ata/libahci.c +++ b/drivers/ata/libahci.c @@ -975,44 +975,43 @@ int ahci_reset_controller(struct ata_host *host) void __iomem *mmio = hpriv->mmio; u32 tmp; - /* we must be in AHCI mode, before using anything - * AHCI-specific, such as HOST_RESET. + /* + * We must be in AHCI mode, before using anything AHCI-specific, such + * as HOST_RESET. */ ahci_enable_ahci(mmio); - /* global controller reset */ - if (!ahci_skip_host_reset) { - tmp = readl(mmio + HOST_CTL); - if ((tmp & HOST_RESET) == 0) { - writel(tmp | HOST_RESET, mmio + HOST_CTL); - readl(mmio + HOST_CTL); /* flush */ - } + /* Global controller reset */ + if (ahci_skip_host_reset) { + dev_info(host->dev, "Skipping global host reset\n"); + return 0; + } - /* - * to perform host reset, OS should set HOST_RESET - * and poll until this bit is read to be "0". - * reset must complete within 1 second, or - * the hardware should be considered fried. - */ - tmp = ata_wait_register(NULL, mmio + HOST_CTL, HOST_RESET, - HOST_RESET, 10, 1000); + tmp = readl(mmio + HOST_CTL); + if (!(tmp & HOST_RESET)) { + writel(tmp | HOST_RESET, mmio + HOST_CTL); + readl(mmio + HOST_CTL); /* flush */ + } - if (tmp & HOST_RESET) { - dev_err(host->dev, "controller reset failed (0x%x)\n", - tmp); - return -EIO; - } + /* + * To perform host reset, OS should set HOST_RESET and poll until this + * bit is read to be "0". Reset must complete within 1 second, or the + * hardware should be considered fried. + */ + tmp = ata_wait_register(NULL, mmio + HOST_CTL, HOST_RESET, + HOST_RESET, 10, 1000); + if (tmp & HOST_RESET) { + dev_err(host->dev, "Controller reset failed (0x%x)\n", + tmp); + return -EIO; + } - /* turn on AHCI mode */ - ahci_enable_ahci(mmio); + /* Turn on AHCI mode */ + ahci_enable_ahci(mmio); - /* Some registers might be cleared on reset. Restore - * initial values. - */ - if (!(hpriv->flags & AHCI_HFLAG_NO_WRITE_TO_RO)) - ahci_restore_initial_config(host); - } else - dev_info(host->dev, "skipping global host reset\n"); + /* Some registers might be cleared on reset. Restore initial values. */ + if (!(hpriv->flags & AHCI_HFLAG_NO_WRITE_TO_RO)) + ahci_restore_initial_config(host); return 0; } diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index b4f246f0cac7f05a6942d41526af51d6f65eb766..d37ab6087f2f0d515cf109ba3c828558fb231388 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -665,12 +665,33 @@ u64 ata_tf_read_block(const struct ata_taskfile *tf, struct ata_device *dev) return block; } +/* + * Set a taskfile command duration limit index. + */ +static inline void ata_set_tf_cdl(struct ata_queued_cmd *qc, int cdl) +{ + struct ata_taskfile *tf = &qc->tf; + + if (tf->protocol == ATA_PROT_NCQ) + tf->auxiliary |= cdl; + else + tf->feature |= cdl; + + /* + * Mark this command as having a CDL and request the result + * task file so that we can inspect the sense data available + * bit on completion. + */ + qc->flags |= ATA_QCFLAG_HAS_CDL | ATA_QCFLAG_RESULT_TF; +} + /** * ata_build_rw_tf - Build ATA taskfile for given read/write request * @qc: Metadata associated with the taskfile to build * @block: Block address * @n_block: Number of blocks * @tf_flags: RW/FUA etc... + * @cdl: Command duration limit index * @class: IO priority class * * LOCKING: @@ -685,7 +706,7 @@ u64 ata_tf_read_block(const struct ata_taskfile *tf, struct ata_device *dev) * -EINVAL if the request is invalid. */ int ata_build_rw_tf(struct ata_queued_cmd *qc, u64 block, u32 n_block, - unsigned int tf_flags, int class) + unsigned int tf_flags, int cdl, int class) { struct ata_taskfile *tf = &qc->tf; struct ata_device *dev = qc->dev; @@ -724,11 +745,20 @@ int ata_build_rw_tf(struct ata_queued_cmd *qc, u64 block, u32 n_block, if (dev->flags & ATA_DFLAG_NCQ_PRIO_ENABLED && class == IOPRIO_CLASS_RT) tf->hob_nsect |= ATA_PRIO_HIGH << ATA_SHIFT_PRIO; + + if ((dev->flags & ATA_DFLAG_CDL_ENABLED) && cdl) + ata_set_tf_cdl(qc, cdl); + } else if (dev->flags & ATA_DFLAG_LBA) { tf->flags |= ATA_TFLAG_LBA; - /* We need LBA48 for FUA writes */ - if (!(tf->flags & ATA_TFLAG_FUA) && lba_28_ok(block, n_block)) { + if ((dev->flags & ATA_DFLAG_CDL_ENABLED) && cdl) + ata_set_tf_cdl(qc, cdl); + + /* Both FUA writes and a CDL index require 48-bit commands */ + if (!(tf->flags & ATA_TFLAG_FUA) && + !(qc->flags & ATA_QCFLAG_HAS_CDL) && + lba_28_ok(block, n_block)) { /* use LBA28 */ tf->device |= (block >> 24) & 0xf; } else if (lba_48_ok(block, n_block)) { @@ -2367,6 +2397,139 @@ static void ata_dev_config_trusted(struct ata_device *dev) dev->flags |= ATA_DFLAG_TRUSTED; } +static void ata_dev_config_cdl(struct ata_device *dev) +{ + struct ata_port *ap = dev->link->ap; + unsigned int err_mask; + bool cdl_enabled; + u64 val; + + if (ata_id_major_version(dev->id) < 12) + goto not_supported; + + if (!ata_log_supported(dev, ATA_LOG_IDENTIFY_DEVICE) || + !ata_identify_page_supported(dev, ATA_LOG_SUPPORTED_CAPABILITIES) || + !ata_identify_page_supported(dev, ATA_LOG_CURRENT_SETTINGS)) + goto not_supported; + + err_mask = ata_read_log_page(dev, ATA_LOG_IDENTIFY_DEVICE, + ATA_LOG_SUPPORTED_CAPABILITIES, + ap->sector_buf, 1); + if (err_mask) + goto not_supported; + + /* Check Command Duration Limit Supported bits */ + val = get_unaligned_le64(&ap->sector_buf[168]); + if (!(val & BIT_ULL(63)) || !(val & BIT_ULL(0))) + goto not_supported; + + /* Warn the user if command duration guideline is not supported */ + if (!(val & BIT_ULL(1))) + ata_dev_warn(dev, + "Command duration guideline is not supported\n"); + + /* + * We must have support for the sense data for successful NCQ commands + * log indicated by the successful NCQ command sense data supported bit. + */ + val = get_unaligned_le64(&ap->sector_buf[8]); + if (!(val & BIT_ULL(63)) || !(val & BIT_ULL(47))) { + ata_dev_warn(dev, + "CDL supported but Successful NCQ Command Sense Data is not supported\n"); + goto not_supported; + } + + /* Without NCQ autosense, the successful NCQ commands log is useless. */ + if (!ata_id_has_ncq_autosense(dev->id)) { + ata_dev_warn(dev, + "CDL supported but NCQ autosense is not supported\n"); + goto not_supported; + } + + /* + * If CDL is marked as enabled, make sure the feature is enabled too. + * Conversely, if CDL is disabled, make sure the feature is turned off. + */ + err_mask = ata_read_log_page(dev, ATA_LOG_IDENTIFY_DEVICE, + ATA_LOG_CURRENT_SETTINGS, + ap->sector_buf, 1); + if (err_mask) + goto not_supported; + + val = get_unaligned_le64(&ap->sector_buf[8]); + cdl_enabled = val & BIT_ULL(63) && val & BIT_ULL(21); + if (dev->flags & ATA_DFLAG_CDL_ENABLED) { + if (!cdl_enabled) { + /* Enable CDL on the device */ + err_mask = ata_dev_set_feature(dev, SETFEATURES_CDL, 1); + if (err_mask) { + ata_dev_err(dev, + "Enable CDL feature failed\n"); + goto not_supported; + } + } + } else { + if (cdl_enabled) { + /* Disable CDL on the device */ + err_mask = ata_dev_set_feature(dev, SETFEATURES_CDL, 0); + if (err_mask) { + ata_dev_err(dev, + "Disable CDL feature failed\n"); + goto not_supported; + } + } + } + + /* + * While CDL itself has to be enabled using sysfs, CDL requires that + * sense data for successful NCQ commands is enabled to work properly. + * Just like ata_dev_config_sense_reporting(), enable it unconditionally + * if supported. + */ + if (!(val & BIT_ULL(63)) || !(val & BIT_ULL(18))) { + err_mask = ata_dev_set_feature(dev, + SETFEATURE_SENSE_DATA_SUCC_NCQ, 0x1); + if (err_mask) { + ata_dev_warn(dev, + "failed to enable Sense Data for successful NCQ commands, Emask 0x%x\n", + err_mask); + goto not_supported; + } + } + + /* + * Allocate a buffer to handle reading the sense data for successful + * NCQ Commands log page for commands using a CDL with one of the limit + * policy set to 0xD (successful completion with sense data available + * bit set). + */ + if (!ap->ncq_sense_buf) { + ap->ncq_sense_buf = kmalloc(ATA_LOG_SENSE_NCQ_SIZE, GFP_KERNEL); + if (!ap->ncq_sense_buf) + goto not_supported; + } + + /* + * Command duration limits is supported: cache the CDL log page 18h + * (command duration descriptors). + */ + err_mask = ata_read_log_page(dev, ATA_LOG_CDL, 0, ap->sector_buf, 1); + if (err_mask) { + ata_dev_warn(dev, "Read Command Duration Limits log failed\n"); + goto not_supported; + } + + memcpy(dev->cdl, ap->sector_buf, ATA_LOG_CDL_SIZE); + dev->flags |= ATA_DFLAG_CDL; + + return; + +not_supported: + dev->flags &= ~(ATA_DFLAG_CDL | ATA_DFLAG_CDL_ENABLED); + kfree(ap->ncq_sense_buf); + ap->ncq_sense_buf = NULL; +} + static int ata_dev_config_lba(struct ata_device *dev) { const u16 *id = dev->id; @@ -2534,13 +2697,14 @@ static void ata_dev_print_features(struct ata_device *dev) return; ata_dev_info(dev, - "Features:%s%s%s%s%s%s%s\n", + "Features:%s%s%s%s%s%s%s%s\n", dev->flags & ATA_DFLAG_FUA ? " FUA" : "", dev->flags & ATA_DFLAG_TRUSTED ? " Trust" : "", dev->flags & ATA_DFLAG_DA ? " Dev-Attention" : "", dev->flags & ATA_DFLAG_DEVSLP ? " Dev-Sleep" : "", dev->flags & ATA_DFLAG_NCQ_SEND_RECV ? " NCQ-sndrcv" : "", dev->flags & ATA_DFLAG_NCQ_PRIO ? " NCQ-prio" : "", + dev->flags & ATA_DFLAG_CDL ? " CDL" : "", dev->cpr_log ? " CPR" : ""); } @@ -2702,6 +2866,7 @@ int ata_dev_configure(struct ata_device *dev) ata_dev_config_zac(dev); ata_dev_config_trusted(dev); ata_dev_config_cpr(dev); + ata_dev_config_cdl(dev); dev->cdb_len = 32; if (print_info) @@ -3802,11 +3967,7 @@ int ata_dev_revalidate(struct ata_device *dev, unsigned int new_class, return -ENODEV; /* fail early if !ATA && !ATAPI to avoid issuing [P]IDENTIFY to PMP */ - if (ata_class_enabled(new_class) && - new_class != ATA_DEV_ATA && - new_class != ATA_DEV_ATAPI && - new_class != ATA_DEV_ZAC && - new_class != ATA_DEV_SEMB) { + if (ata_class_enabled(new_class) && new_class == ATA_DEV_PMP) { ata_dev_info(dev, "class mismatch %u != %u\n", dev->class, new_class); rc = -ENODEV; @@ -4766,6 +4927,36 @@ void ata_qc_complete(struct ata_queued_cmd *qc) fill_result_tf(qc); trace_ata_qc_complete_done(qc); + + /* + * For CDL commands that completed without an error, check if + * we have sense data (ATA_SENSE is set). If we do, then the + * command may have been aborted by the device due to a limit + * timeout using the policy 0xD. For these commands, invoke EH + * to get the command sense data. + */ + if (qc->result_tf.status & ATA_SENSE && + ((ata_is_ncq(qc->tf.protocol) && + dev->flags & ATA_DFLAG_CDL_ENABLED) || + (!(ata_is_ncq(qc->tf.protocol) && + ata_id_sense_reporting_enabled(dev->id))))) { + /* + * Tell SCSI EH to not overwrite scmd->result even if + * this command is finished with result SAM_STAT_GOOD. + */ + qc->scsicmd->flags |= SCMD_FORCE_EH_SUCCESS; + qc->flags |= ATA_QCFLAG_EH_SUCCESS_CMD; + ehi->dev_action[dev->devno] |= ATA_EH_GET_SUCCESS_SENSE; + + /* + * set pending so that ata_qc_schedule_eh() does not + * trigger fast drain, and freeze the port. + */ + ap->pflags |= ATA_PFLAG_EH_PENDING; + ata_qc_schedule_eh(qc); + return; + } + /* Some commands need post-processing after successful * completion. */ @@ -5398,6 +5589,7 @@ static void ata_host_release(struct kref *kref) kfree(ap->pmp_link); kfree(ap->slave_link); + kfree(ap->ncq_sense_buf); kfree(ap); host->ports[i] = NULL; } @@ -6142,13 +6334,11 @@ EXPORT_SYMBOL_GPL(ata_pci_device_resume); * LOCKING: * Inherited from platform layer (may sleep). */ -int ata_platform_remove_one(struct platform_device *pdev) +void ata_platform_remove_one(struct platform_device *pdev) { struct ata_host *host = platform_get_drvdata(pdev); ata_host_detach(host); - - return 0; } EXPORT_SYMBOL_GPL(ata_platform_remove_one); diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 6f8d141915939441dafd1a9852e2172da128cadf..35e03679b0bfe77e26587865e0830477759b0994 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -1401,8 +1401,11 @@ unsigned int atapi_eh_tur(struct ata_device *dev, u8 *r_sense_key) * * LOCKING: * Kernel thread context (may sleep). + * + * RETURNS: + * true if sense data could be fetched, false otherwise. */ -static void ata_eh_request_sense(struct ata_queued_cmd *qc) +static bool ata_eh_request_sense(struct ata_queued_cmd *qc) { struct scsi_cmnd *cmd = qc->scsicmd; struct ata_device *dev = qc->dev; @@ -1411,15 +1414,12 @@ static void ata_eh_request_sense(struct ata_queued_cmd *qc) if (ata_port_is_frozen(qc->ap)) { ata_dev_warn(dev, "sense data available but port frozen\n"); - return; + return false; } - if (!cmd || qc->flags & ATA_QCFLAG_SENSE_VALID) - return; - if (!ata_id_sense_reporting_enabled(dev->id)) { ata_dev_warn(qc->dev, "sense data reporting disabled\n"); - return; + return false; } ata_tf_init(dev, &tf); @@ -1432,13 +1432,19 @@ static void ata_eh_request_sense(struct ata_queued_cmd *qc) /* Ignore err_mask; ATA_ERR might be set */ if (tf.status & ATA_SENSE) { if (ata_scsi_sense_is_valid(tf.lbah, tf.lbam, tf.lbal)) { - ata_scsi_set_sense(dev, cmd, tf.lbah, tf.lbam, tf.lbal); + /* Set sense without also setting scsicmd->result */ + scsi_build_sense_buffer(dev->flags & ATA_DFLAG_D_SENSE, + cmd->sense_buffer, tf.lbah, + tf.lbam, tf.lbal); qc->flags |= ATA_QCFLAG_SENSE_VALID; + return true; } } else { ata_dev_warn(dev, "request sense failed stat %02x emask %x\n", tf.status, err_mask); } + + return false; } /** @@ -1588,8 +1594,9 @@ static unsigned int ata_eh_analyze_tf(struct ata_queued_cmd *qc) * was not included in the NCQ command error log * (i.e. NCQ autosense is not supported by the device). */ - if (!(qc->flags & ATA_QCFLAG_SENSE_VALID) && (stat & ATA_SENSE)) - ata_eh_request_sense(qc); + if (!(qc->flags & ATA_QCFLAG_SENSE_VALID) && + (stat & ATA_SENSE) && ata_eh_request_sense(qc)) + set_status_byte(qc->scsicmd, SAM_STAT_CHECK_CONDITION); if (err & ATA_ICRC) qc->err_mask |= AC_ERR_ATA_BUS; if (err & (ATA_UNC | ATA_AMNF)) @@ -1817,9 +1824,7 @@ static unsigned int ata_eh_speed_down(struct ata_device *dev, verdict = ata_eh_speed_down_verdict(dev); /* turn off NCQ? */ - if ((verdict & ATA_EH_SPDN_NCQ_OFF) && - (dev->flags & (ATA_DFLAG_PIO | ATA_DFLAG_NCQ | - ATA_DFLAG_NCQ_OFF)) == ATA_DFLAG_NCQ) { + if ((verdict & ATA_EH_SPDN_NCQ_OFF) && ata_ncq_enabled(dev)) { dev->flags |= ATA_DFLAG_NCQ_OFF; ata_dev_warn(dev, "NCQ disabled due to excessive errors\n"); goto done; @@ -1910,6 +1915,99 @@ static inline bool ata_eh_quiet(struct ata_queued_cmd *qc) return qc->flags & ATA_QCFLAG_QUIET; } +static int ata_eh_read_sense_success_non_ncq(struct ata_link *link) +{ + struct ata_port *ap = link->ap; + struct ata_queued_cmd *qc; + + qc = __ata_qc_from_tag(ap, link->active_tag); + if (!qc) + return -EIO; + + if (!(qc->flags & ATA_QCFLAG_EH) || + !(qc->flags & ATA_QCFLAG_EH_SUCCESS_CMD) || + qc->err_mask) + return -EIO; + + if (!ata_eh_request_sense(qc)) + return -EIO; + + /* + * If we have sense data, call scsi_check_sense() in order to set the + * correct SCSI ML byte (if any). No point in checking the return value, + * since the command has already completed successfully. + */ + scsi_check_sense(qc->scsicmd); + + return 0; +} + +static void ata_eh_get_success_sense(struct ata_link *link) +{ + struct ata_eh_context *ehc = &link->eh_context; + struct ata_device *dev = link->device; + struct ata_port *ap = link->ap; + struct ata_queued_cmd *qc; + int tag, ret = 0; + + if (!(ehc->i.dev_action[dev->devno] & ATA_EH_GET_SUCCESS_SENSE)) + return; + + /* if frozen, we can't do much */ + if (ata_port_is_frozen(ap)) { + ata_dev_warn(dev, + "successful sense data available but port frozen\n"); + goto out; + } + + /* + * If the link has sactive set, then we have outstanding NCQ commands + * and have to read the Successful NCQ Commands log to get the sense + * data. Otherwise, we are dealing with a non-NCQ command and use + * request sense ext command to retrieve the sense data. + */ + if (link->sactive) + ret = ata_eh_read_sense_success_ncq_log(link); + else + ret = ata_eh_read_sense_success_non_ncq(link); + if (ret) + goto out; + + ata_eh_done(link, dev, ATA_EH_GET_SUCCESS_SENSE); + return; + +out: + /* + * If we failed to get sense data for a successful command that ought to + * have sense data, we cannot simply return BLK_STS_OK to user space. + * This is because we can't know if the sense data that we couldn't get + * was actually "DATA CURRENTLY UNAVAILABLE". Reporting such a command + * as success to user space would result in a silent data corruption. + * Thus, add a bogus ABORTED_COMMAND sense data to such commands, such + * that SCSI will report these commands as BLK_STS_IOERR to user space. + */ + ata_qc_for_each_raw(ap, qc, tag) { + if (!(qc->flags & ATA_QCFLAG_EH) || + !(qc->flags & ATA_QCFLAG_EH_SUCCESS_CMD) || + qc->err_mask || + ata_dev_phys_link(qc->dev) != link) + continue; + + /* We managed to get sense for this success command, skip. */ + if (qc->flags & ATA_QCFLAG_SENSE_VALID) + continue; + + /* This success command did not have any sense data, skip. */ + if (!(qc->result_tf.status & ATA_SENSE)) + continue; + + /* This success command had sense data, but we failed to get. */ + ata_scsi_set_sense(dev, qc->scsicmd, ABORTED_COMMAND, 0, 0); + qc->flags |= ATA_QCFLAG_SENSE_VALID; + } + ata_eh_done(link, dev, ATA_EH_GET_SUCCESS_SENSE); +} + /** * ata_eh_link_autopsy - analyze error and determine recovery action * @link: host link to perform autopsy on @@ -1950,6 +2048,14 @@ static void ata_eh_link_autopsy(struct ata_link *link) /* analyze NCQ failure */ ata_eh_analyze_ncq_error(link); + /* + * Check if this was a successful command that simply needs sense data. + * Since the sense data is not part of the completion, we need to fetch + * it using an additional command. Since this can't be done from irq + * context, the sense data for successful commands are fetched by EH. + */ + ata_eh_get_success_sense(link); + /* any real error trumps AC_ERR_OTHER */ if (ehc->i.err_mask & ~AC_ERR_OTHER) ehc->i.err_mask &= ~AC_ERR_OTHER; @@ -1959,6 +2065,7 @@ static void ata_eh_link_autopsy(struct ata_link *link) ata_qc_for_each_raw(ap, qc, tag) { if (!(qc->flags & ATA_QCFLAG_EH) || qc->flags & ATA_QCFLAG_RETRY || + qc->flags & ATA_QCFLAG_EH_SUCCESS_CMD || ata_dev_phys_link(qc->dev) != link) continue; @@ -3813,16 +3920,30 @@ void ata_eh_finish(struct ata_port *ap) * generate sense data in this function, * considering both err_mask and tf. */ - if (qc->flags & ATA_QCFLAG_RETRY) + if (qc->flags & ATA_QCFLAG_RETRY) { + /* + * Since qc->err_mask is set, ata_eh_qc_retry() + * will not increment scmd->allowed, so upper + * layer will only retry the command if it has + * not already been retried too many times. + */ ata_eh_qc_retry(qc); - else + } else { ata_eh_qc_complete(qc); + } } else { - if (qc->flags & ATA_QCFLAG_SENSE_VALID) { + if (qc->flags & ATA_QCFLAG_SENSE_VALID || + qc->flags & ATA_QCFLAG_EH_SUCCESS_CMD) { ata_eh_qc_complete(qc); } else { /* feed zero TF to sense generation */ memset(&qc->result_tf, 0, sizeof(qc->result_tf)); + /* + * Since qc->err_mask is not set, + * ata_eh_qc_retry() will increment + * scmd->allowed, so upper layer is guaranteed + * to retry the command. + */ ata_eh_qc_retry(qc); } } diff --git a/drivers/ata/libata-sata.c b/drivers/ata/libata-sata.c index f3e7396e319198490cdd09d93cd591127f0baed8..85e279a12f62c495f257e8ef25129c7b3e953ad5 100644 --- a/drivers/ata/libata-sata.c +++ b/drivers/ata/libata-sata.c @@ -11,7 +11,9 @@ #include #include #include +#include #include +#include #include "libata.h" #include "libata-transport.h" @@ -907,10 +909,17 @@ static ssize_t ata_ncq_prio_enable_store(struct device *device, goto unlock; } - if (input) + if (input) { + if (dev->flags & ATA_DFLAG_CDL_ENABLED) { + ata_dev_err(dev, + "CDL must be disabled to enable NCQ priority\n"); + rc = -EINVAL; + goto unlock; + } dev->flags |= ATA_DFLAG_NCQ_PRIO_ENABLED; - else + } else { dev->flags &= ~ATA_DFLAG_NCQ_PRIO_ENABLED; + } unlock: spin_unlock_irq(ap->lock); @@ -1023,7 +1032,6 @@ EXPORT_SYMBOL_GPL(dev_attr_sw_activity); /** * ata_change_queue_depth - Set a device maximum queue depth * @ap: ATA port of the target device - * @dev: target ATA device * @sdev: SCSI device to configure queue depth for * @queue_depth: new queue depth * @@ -1031,33 +1039,47 @@ EXPORT_SYMBOL_GPL(dev_attr_sw_activity); * and libata. * */ -int ata_change_queue_depth(struct ata_port *ap, struct ata_device *dev, - struct scsi_device *sdev, int queue_depth) +int ata_change_queue_depth(struct ata_port *ap, struct scsi_device *sdev, + int queue_depth) { + struct ata_device *dev; unsigned long flags; + int max_queue_depth; - if (!dev || !ata_dev_enabled(dev)) - return sdev->queue_depth; + spin_lock_irqsave(ap->lock, flags); - if (queue_depth < 1 || queue_depth == sdev->queue_depth) + dev = ata_scsi_find_dev(ap, sdev); + if (!dev || queue_depth < 1 || queue_depth == sdev->queue_depth) { + spin_unlock_irqrestore(ap->lock, flags); return sdev->queue_depth; + } - /* NCQ enabled? */ - spin_lock_irqsave(ap->lock, flags); - dev->flags &= ~ATA_DFLAG_NCQ_OFF; - if (queue_depth == 1 || !ata_ncq_enabled(dev)) { + /* + * Make sure that the queue depth requested does not exceed the device + * capabilities. + */ + max_queue_depth = min(ATA_MAX_QUEUE, sdev->host->can_queue); + max_queue_depth = min(max_queue_depth, ata_id_queue_depth(dev->id)); + if (queue_depth > max_queue_depth) { + spin_unlock_irqrestore(ap->lock, flags); + return -EINVAL; + } + + /* + * If NCQ is not supported by the device or if the target queue depth + * is 1 (to disable drive side command queueing), turn off NCQ. + */ + if (queue_depth == 1 || !ata_ncq_supported(dev)) { dev->flags |= ATA_DFLAG_NCQ_OFF; queue_depth = 1; + } else { + dev->flags &= ~ATA_DFLAG_NCQ_OFF; } - spin_unlock_irqrestore(ap->lock, flags); - /* limit and apply queue depth */ - queue_depth = min(queue_depth, sdev->host->can_queue); - queue_depth = min(queue_depth, ata_id_queue_depth(dev->id)); - queue_depth = min(queue_depth, ATA_MAX_QUEUE); + spin_unlock_irqrestore(ap->lock, flags); - if (sdev->queue_depth == queue_depth) - return -EINVAL; + if (queue_depth == sdev->queue_depth) + return sdev->queue_depth; return scsi_change_queue_depth(sdev, queue_depth); } @@ -1082,8 +1104,7 @@ int ata_scsi_change_queue_depth(struct scsi_device *sdev, int queue_depth) { struct ata_port *ap = ata_shost_to_port(sdev->host); - return ata_change_queue_depth(ap, ata_scsi_find_dev(ap, sdev), - sdev, queue_depth); + return ata_change_queue_depth(ap, sdev, queue_depth); } EXPORT_SYMBOL_GPL(ata_scsi_change_queue_depth); @@ -1401,6 +1422,95 @@ static int ata_eh_read_log_10h(struct ata_device *dev, return 0; } +/** + * ata_eh_read_sense_success_ncq_log - Read the sense data for successful + * NCQ commands log + * @link: ATA link to get sense data for + * + * Read the sense data for successful NCQ commands log page to obtain + * sense data for all NCQ commands that completed successfully with + * the sense data available bit set. + * + * LOCKING: + * Kernel thread context (may sleep). + * + * RETURNS: + * 0 on success, -errno otherwise. + */ +int ata_eh_read_sense_success_ncq_log(struct ata_link *link) +{ + struct ata_device *dev = link->device; + struct ata_port *ap = dev->link->ap; + u8 *buf = ap->ncq_sense_buf; + struct ata_queued_cmd *qc; + unsigned int err_mask, tag; + u8 *sense, sk = 0, asc = 0, ascq = 0; + u64 sense_valid, val; + int ret = 0; + + err_mask = ata_read_log_page(dev, ATA_LOG_SENSE_NCQ, 0, buf, 2); + if (err_mask) { + ata_dev_err(dev, + "Failed to read Sense Data for Successful NCQ Commands log\n"); + return -EIO; + } + + /* Check the log header */ + val = get_unaligned_le64(&buf[0]); + if ((val & 0xffff) != 1 || ((val >> 16) & 0xff) != 0x0f) { + ata_dev_err(dev, + "Invalid Sense Data for Successful NCQ Commands log\n"); + return -EIO; + } + + sense_valid = (u64)buf[8] | ((u64)buf[9] << 8) | + ((u64)buf[10] << 16) | ((u64)buf[11] << 24); + + ata_qc_for_each_raw(ap, qc, tag) { + if (!(qc->flags & ATA_QCFLAG_EH) || + !(qc->flags & ATA_QCFLAG_EH_SUCCESS_CMD) || + qc->err_mask || + ata_dev_phys_link(qc->dev) != link) + continue; + + /* + * If the command does not have any sense data, clear ATA_SENSE. + * Keep ATA_QCFLAG_EH_SUCCESS_CMD so that command is finished. + */ + if (!(sense_valid & (1ULL << tag))) { + qc->result_tf.status &= ~ATA_SENSE; + continue; + } + + sense = &buf[32 + 24 * tag]; + sk = sense[0]; + asc = sense[1]; + ascq = sense[2]; + + if (!ata_scsi_sense_is_valid(sk, asc, ascq)) { + ret = -EIO; + continue; + } + + /* Set sense without also setting scsicmd->result */ + scsi_build_sense_buffer(dev->flags & ATA_DFLAG_D_SENSE, + qc->scsicmd->sense_buffer, sk, + asc, ascq); + qc->flags |= ATA_QCFLAG_SENSE_VALID; + + /* + * If we have sense data, call scsi_check_sense() in order to + * set the correct SCSI ML byte (if any). No point in checking + * the return value, since the command has already completed + * successfully. + */ + scsi_check_sense(qc->scsicmd); + } + + return ret; +} +EXPORT_SYMBOL_GPL(ata_eh_read_sense_success_ncq_log); + /** * ata_eh_analyze_ncq_error - analyze NCQ error * @link: ATA link to analyze NCQ error for @@ -1481,6 +1591,7 @@ void ata_eh_analyze_ncq_error(struct ata_link *link) ata_qc_for_each_raw(ap, qc, tag) { if (!(qc->flags & ATA_QCFLAG_EH) || + qc->flags & ATA_QCFLAG_EH_SUCCESS_CMD || ata_dev_phys_link(qc->dev) != link) continue; diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 551077cea4e4e023e20e913e37ee7b939488083a..370d18aca71e87653339e53002a7326812693665 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -37,7 +37,7 @@ #include "libata.h" #include "libata-transport.h" -#define ATA_SCSI_RBUF_SIZE 576 +#define ATA_SCSI_RBUF_SIZE 2048 static DEFINE_SPINLOCK(ata_scsi_rbuf_lock); static u8 ata_scsi_rbuf[ATA_SCSI_RBUF_SIZE]; @@ -47,15 +47,19 @@ typedef unsigned int (*ata_xlat_func_t)(struct ata_queued_cmd *qc); static struct ata_device *__ata_scsi_find_dev(struct ata_port *ap, const struct scsi_device *scsidev); -#define RW_RECOVERY_MPAGE 0x1 -#define RW_RECOVERY_MPAGE_LEN 12 -#define CACHE_MPAGE 0x8 -#define CACHE_MPAGE_LEN 20 -#define CONTROL_MPAGE 0xa -#define CONTROL_MPAGE_LEN 12 -#define ALL_MPAGES 0x3f -#define ALL_SUB_MPAGES 0xff - +#define RW_RECOVERY_MPAGE 0x1 +#define RW_RECOVERY_MPAGE_LEN 12 +#define CACHE_MPAGE 0x8 +#define CACHE_MPAGE_LEN 20 +#define CONTROL_MPAGE 0xa +#define CONTROL_MPAGE_LEN 12 +#define ALL_MPAGES 0x3f +#define ALL_SUB_MPAGES 0xff +#define CDL_T2A_SUB_MPAGE 0x07 +#define CDL_T2B_SUB_MPAGE 0x08 +#define CDL_T2_SUB_MPAGE_LEN 232 +#define ATA_FEATURE_SUB_MPAGE 0xf2 +#define ATA_FEATURE_SUB_MPAGE_LEN 16 static const u8 def_rw_recovery_mpage[RW_RECOVERY_MPAGE_LEN] = { RW_RECOVERY_MPAGE, @@ -209,9 +213,6 @@ void ata_scsi_set_sense(struct ata_device *dev, struct scsi_cmnd *cmd, { bool d_sense = (dev->flags & ATA_DFLAG_D_SENSE); - if (!cmd) - return; - scsi_build_sense(cmd, d_sense, sk, asc, ascq); } @@ -221,9 +222,6 @@ void ata_scsi_set_sense_information(struct ata_device *dev, { u64 information; - if (!cmd) - return; - information = ata_tf_read_block(tf, dev); if (information == U64_MAX) return; @@ -1122,7 +1120,7 @@ int ata_scsi_dev_config(struct scsi_device *sdev, struct ata_device *dev) if (dev->flags & ATA_DFLAG_AN) set_bit(SDEV_EVT_MEDIA_CHANGE, sdev->supported_events); - if (dev->flags & ATA_DFLAG_NCQ) + if (ata_ncq_supported(dev)) depth = min(sdev->host->can_queue, ata_id_queue_depth(dev->id)); depth = min(ATA_MAX_QUEUE, depth); scsi_change_queue_depth(sdev, depth); @@ -1382,6 +1380,18 @@ static inline void scsi_16_lba_len(const u8 *cdb, u64 *plba, u32 *plen) *plen = get_unaligned_be32(&cdb[10]); } +/** + * scsi_dld - Get duration limit descriptor index + * @cdb: SCSI command to translate + * + * Returns the dld bits indicating the index of a command duration limit + * descriptor. + */ +static inline int scsi_dld(const u8 *cdb) +{ + return ((cdb[1] & 0x01) << 2) | ((cdb[14] >> 6) & 0x03); +} + /** * ata_scsi_verify_xlat - Translate SCSI VERIFY command into an ATA one * @qc: Storage for translated ATA taskfile @@ -1550,6 +1560,7 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc) struct request *rq = scsi_cmd_to_rq(scmd); int class = IOPRIO_PRIO_CLASS(req_get_ioprio(rq)); unsigned int tf_flags = 0; + int dld = 0; u64 block; u32 n_block; int rc; @@ -1600,6 +1611,7 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc) goto invalid_fld; } scsi_16_lba_len(cdb, &block, &n_block); + dld = scsi_dld(cdb); if (cdb[1] & (1 << 3)) tf_flags |= ATA_TFLAG_FUA; if (!ata_check_nblocks(scmd, n_block)) @@ -1624,7 +1636,7 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc) qc->flags |= ATA_QCFLAG_IO; qc->nbytes = n_block * scmd->device->sector_size; - rc = ata_build_rw_tf(qc, block, n_block, tf_flags, class); + rc = ata_build_rw_tf(qc, block, n_block, tf_flags, dld, class); if (likely(rc == 0)) return 0; @@ -2203,10 +2215,123 @@ static unsigned int ata_msense_caching(u16 *id, u8 *buf, bool changeable) return sizeof(def_cache_mpage); } +/* + * Simulate MODE SENSE control mode page, sub-page 0. + */ +static unsigned int ata_msense_control_spg0(struct ata_device *dev, u8 *buf, + bool changeable) +{ + modecpy(buf, def_control_mpage, + sizeof(def_control_mpage), changeable); + if (changeable) { + /* ata_mselect_control() */ + buf[2] |= (1 << 2); + } else { + bool d_sense = (dev->flags & ATA_DFLAG_D_SENSE); + + /* descriptor format sense data */ + buf[2] |= (d_sense << 2); + } + + return sizeof(def_control_mpage); +} + +/* + * Translate an ATA duration limit in microseconds to a SCSI duration limit + * using the t2cdlunits 0xa (10ms). Since the SCSI duration limits are 2-bytes + * only, take care of overflows. + */ +static inline u16 ata_xlat_cdl_limit(u8 *buf) +{ + u32 limit = get_unaligned_le32(buf); + + return min_t(u32, limit / 10000, 65535); +} + +/* + * Simulate MODE SENSE control mode page, sub-pages 07h and 08h + * (command duration limits T2A and T2B mode pages). + */ +static unsigned int ata_msense_control_spgt2(struct ata_device *dev, u8 *buf, + u8 spg) +{ + u8 *b, *cdl = dev->cdl, *desc; + u32 policy; + int i; + + /* + * Fill the subpage. The first four bytes of the T2A/T2B mode pages + * are a header. The PAGE LENGTH field is the size of the page + * excluding the header. + */ + buf[0] = CONTROL_MPAGE; + buf[1] = spg; + put_unaligned_be16(CDL_T2_SUB_MPAGE_LEN - 4, &buf[2]); + if (spg == CDL_T2A_SUB_MPAGE) { + /* + * Read descriptors map to the T2A page: + * set perf_vs_duration_guidleine. + */ + buf[7] = (cdl[0] & 0x03) << 4; + desc = cdl + 64; + } else { + /* Write descriptors map to the T2B page */ + desc = cdl + 288; + } + + /* Fill the T2 page descriptors */ + b = &buf[8]; + policy = get_unaligned_le32(&cdl[0]); + for (i = 0; i < 7; i++, b += 32, desc += 32) { + /* t2cdlunits: fixed to 10ms */ + b[0] = 0x0a; + + /* Max inactive time and its policy */ + put_unaligned_be16(ata_xlat_cdl_limit(&desc[8]), &b[2]); + b[6] = ((policy >> 8) & 0x0f) << 4; + + /* Max active time and its policy */ + put_unaligned_be16(ata_xlat_cdl_limit(&desc[4]), &b[4]); + b[6] |= (policy >> 4) & 0x0f; + + /* Command duration guideline and its policy */ + put_unaligned_be16(ata_xlat_cdl_limit(&desc[16]), &b[10]); + b[14] = policy & 0x0f; + } + + return CDL_T2_SUB_MPAGE_LEN; +} + +/* + * Simulate MODE SENSE control mode page, sub-page f2h + * (ATA feature control mode page). + */ +static unsigned int ata_msense_control_ata_feature(struct ata_device *dev, + u8 *buf) +{ + /* PS=0, SPF=1 */ + buf[0] = CONTROL_MPAGE | (1 << 6); + buf[1] = ATA_FEATURE_SUB_MPAGE; + + /* + * The first four bytes of ATA Feature Control mode page are a header. + * The PAGE LENGTH field is the size of the page excluding the header. + */ + put_unaligned_be16(ATA_FEATURE_SUB_MPAGE_LEN - 4, &buf[2]); + + if (dev->flags & ATA_DFLAG_CDL) + buf[4] = 0x02; /* Support T2A and T2B pages */ + else + buf[4] = 0; + + return ATA_FEATURE_SUB_MPAGE_LEN; +} + /** * ata_msense_control - Simulate MODE SENSE control mode page * @dev: ATA device of interest * @buf: output buffer + * @spg: sub-page code * @changeable: whether changeable parameters are requested * * Generate a generic MODE SENSE control mode page. @@ -2215,17 +2340,27 @@ static unsigned int ata_msense_caching(u16 *id, u8 *buf, bool changeable) * None. */ static unsigned int ata_msense_control(struct ata_device *dev, u8 *buf, - bool changeable) + u8 spg, bool changeable) { - modecpy(buf, def_control_mpage, sizeof(def_control_mpage), changeable); - if (changeable) { - buf[2] |= (1 << 2); /* ata_mselect_control() */ - } else { - bool d_sense = (dev->flags & ATA_DFLAG_D_SENSE); - - buf[2] |= (d_sense << 2); /* descriptor format sense data */ + unsigned int n; + + switch (spg) { + case 0: + return ata_msense_control_spg0(dev, buf, changeable); + case CDL_T2A_SUB_MPAGE: + case CDL_T2B_SUB_MPAGE: + return ata_msense_control_spgt2(dev, buf, spg); + case ATA_FEATURE_SUB_MPAGE: + return ata_msense_control_ata_feature(dev, buf); + case ALL_SUB_MPAGES: + n = ata_msense_control_spg0(dev, buf, changeable); + n += ata_msense_control_spgt2(dev, buf + n, CDL_T2A_SUB_MPAGE); + n += ata_msense_control_spgt2(dev, buf + n, CDL_T2A_SUB_MPAGE); + n += ata_msense_control_ata_feature(dev, buf + n); + return n; + default: + return 0; } - return sizeof(def_control_mpage); } /** @@ -2298,13 +2433,25 @@ static unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf) pg = scsicmd[2] & 0x3f; spg = scsicmd[3]; + /* - * No mode subpages supported (yet) but asking for _all_ - * subpages may be valid + * Supported subpages: all subpages and sub-pages 07h, 08h and f2h of + * the control page. */ - if (spg && (spg != ALL_SUB_MPAGES)) { - fp = 3; - goto invalid_fld; + if (spg) { + switch (spg) { + case ALL_SUB_MPAGES: + break; + case CDL_T2A_SUB_MPAGE: + case CDL_T2B_SUB_MPAGE: + case ATA_FEATURE_SUB_MPAGE: + if (dev->flags & ATA_DFLAG_CDL && pg == CONTROL_MPAGE) + break; + fallthrough; + default: + fp = 3; + goto invalid_fld; + } } switch(pg) { @@ -2317,13 +2464,13 @@ static unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf) break; case CONTROL_MPAGE: - p += ata_msense_control(args->dev, p, page_control == 1); + p += ata_msense_control(args->dev, p, spg, page_control == 1); break; case ALL_MPAGES: p += ata_msense_rw_recovery(p, page_control == 1); p += ata_msense_caching(args->id, p, page_control == 1); - p += ata_msense_control(args->dev, p, page_control == 1); + p += ata_msense_control(args->dev, p, spg, page_control == 1); break; default: /* invalid page code */ @@ -2342,10 +2489,7 @@ static unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf) memcpy(rbuf + 4, sat_blk_desc, sizeof(sat_blk_desc)); } } else { - unsigned int output_len = p - rbuf - 2; - - rbuf[0] = output_len >> 8; - rbuf[1] = output_len; + put_unaligned_be16(p - rbuf - 2, &rbuf[0]); rbuf[3] |= dpofua; if (ebd) { rbuf[7] = sizeof(sat_blk_desc); @@ -3260,7 +3404,7 @@ static unsigned int ata_scsiop_maint_in(struct ata_scsi_args *args, u8 *rbuf) { struct ata_device *dev = args->dev; u8 *cdb = args->cmd->cmnd; - u8 supported = 0; + u8 supported = 0, cdlp = 0, rwcdlp = 0; unsigned int err = 0; if (cdb[2] != 1 && cdb[2] != 3) { @@ -3287,10 +3431,8 @@ static unsigned int ata_scsiop_maint_in(struct ata_scsi_args *args, u8 *rbuf) case MAINTENANCE_IN: case READ_6: case READ_10: - case READ_16: case WRITE_6: case WRITE_10: - case WRITE_16: case ATA_12: case ATA_16: case VERIFY: @@ -3300,6 +3442,28 @@ static unsigned int ata_scsiop_maint_in(struct ata_scsi_args *args, u8 *rbuf) case START_STOP: supported = 3; break; + case READ_16: + supported = 3; + if (dev->flags & ATA_DFLAG_CDL) { + /* + * CDL read descriptors map to the T2A page, that is, + * rwcdlp = 0x01 and cdlp = 0x01 + */ + rwcdlp = 0x01; + cdlp = 0x01 << 3; + } + break; + case WRITE_16: + supported = 3; + if (dev->flags & ATA_DFLAG_CDL) { + /* + * CDL write descriptors map to the T2B page, that is, + * rwcdlp = 0x01 and cdlp = 0x02 + */ + rwcdlp = 0x01; + cdlp = 0x02 << 3; + } + break; case ZBC_IN: case ZBC_OUT: if (ata_id_zoned_cap(dev->id) || @@ -3315,7 +3479,9 @@ static unsigned int ata_scsiop_maint_in(struct ata_scsi_args *args, u8 *rbuf) break; } out: - rbuf[1] = supported; /* supported */ + /* One command format */ + rbuf[0] = rwcdlp; + rbuf[1] = cdlp | supported; return err; } @@ -3605,20 +3771,11 @@ static int ata_mselect_caching(struct ata_queued_cmd *qc, return 0; } -/** - * ata_mselect_control - Simulate MODE SELECT for control page - * @qc: Storage for translated ATA taskfile - * @buf: input buffer - * @len: number of valid bytes in the input buffer - * @fp: out parameter for the failed field on error - * - * Prepare a taskfile to modify caching information for the device. - * - * LOCKING: - * None. +/* + * Simulate MODE SELECT control mode page, sub-page 0. */ -static int ata_mselect_control(struct ata_queued_cmd *qc, - const u8 *buf, int len, u16 *fp) +static int ata_mselect_control_spg0(struct ata_queued_cmd *qc, + const u8 *buf, int len, u16 *fp) { struct ata_device *dev = qc->dev; u8 mpage[CONTROL_MPAGE_LEN]; @@ -3640,7 +3797,7 @@ static int ata_mselect_control(struct ata_queued_cmd *qc, /* * Check that read-only bits are not modified. */ - ata_msense_control(dev, mpage, false); + ata_msense_control_spg0(dev, mpage, false); for (i = 0; i < CONTROL_MPAGE_LEN - 2; i++) { if (i == 0) continue; @@ -3656,6 +3813,84 @@ static int ata_mselect_control(struct ata_queued_cmd *qc, return 0; } +/* + * Translate MODE SELECT control mode page, sub-pages f2h (ATA feature mode + * page) into a SET FEATURES command. + */ +static unsigned int ata_mselect_control_ata_feature(struct ata_queued_cmd *qc, + const u8 *buf, int len, + u16 *fp) +{ + struct ata_device *dev = qc->dev; + struct ata_taskfile *tf = &qc->tf; + u8 cdl_action; + + /* + * The first four bytes of ATA Feature Control mode page are a header, + * so offsets in mpage are off by 4 compared to buf. Same for len. + */ + if (len != ATA_FEATURE_SUB_MPAGE_LEN - 4) { + *fp = min(len, ATA_FEATURE_SUB_MPAGE_LEN - 4); + return -EINVAL; + } + + /* Check cdl_ctrl */ + switch (buf[0] & 0x03) { + case 0: + /* Disable CDL */ + cdl_action = 0; + dev->flags &= ~ATA_DFLAG_CDL_ENABLED; + break; + case 0x02: + /* Enable CDL T2A/T2B: NCQ priority must be disabled */ + if (dev->flags & ATA_DFLAG_NCQ_PRIO_ENABLED) { + ata_dev_err(dev, + "NCQ priority must be disabled to enable CDL\n"); + return -EINVAL; + } + cdl_action = 1; + dev->flags |= ATA_DFLAG_CDL_ENABLED; + break; + default: + *fp = 0; + return -EINVAL; + } + + tf->flags |= ATA_TFLAG_DEVICE | ATA_TFLAG_ISADDR; + tf->protocol = ATA_PROT_NODATA; + tf->command = ATA_CMD_SET_FEATURES; + tf->feature = SETFEATURES_CDL; + tf->nsect = cdl_action; + + return 1; +} + +/** + * ata_mselect_control - Simulate MODE SELECT for control page + * @qc: Storage for translated ATA taskfile + * @spg: target sub-page of the control page + * @buf: input buffer + * @len: number of valid bytes in the input buffer + * @fp: out parameter for the failed field on error + * + * Prepare a taskfile to modify caching information for the device. + * + * LOCKING: + * None. + */ +static int ata_mselect_control(struct ata_queued_cmd *qc, u8 spg, + const u8 *buf, int len, u16 *fp) +{ + switch (spg) { + case 0: + return ata_mselect_control_spg0(qc, buf, len, fp); + case ATA_FEATURE_SUB_MPAGE: + return ata_mselect_control_ata_feature(qc, buf, len, fp); + default: + return -EINVAL; + } +} + /** * ata_scsi_mode_select_xlat - Simulate MODE SELECT 6, 10 commands * @qc: Storage for translated ATA taskfile @@ -3673,7 +3908,7 @@ static unsigned int ata_scsi_mode_select_xlat(struct ata_queued_cmd *qc) const u8 *cdb = scmd->cmnd; u8 pg, spg; unsigned six_byte, pg_len, hdr_len, bd_len; - int len; + int len, ret; u16 fp = (u16)-1; u8 bp = 0xff; u8 buffer[64]; @@ -3758,13 +3993,29 @@ static unsigned int ata_scsi_mode_select_xlat(struct ata_queued_cmd *qc) } /* - * No mode subpages supported (yet) but asking for _all_ - * subpages may be valid + * Supported subpages: all subpages and ATA feature sub-page f2h of + * the control page. */ - if (spg && (spg != ALL_SUB_MPAGES)) { - fp = (p[0] & 0x40) ? 1 : 0; - fp += hdr_len + bd_len; - goto invalid_param; + if (spg) { + switch (spg) { + case ALL_SUB_MPAGES: + /* All subpages is not supported for the control page */ + if (pg == CONTROL_MPAGE) { + fp = (p[0] & 0x40) ? 1 : 0; + fp += hdr_len + bd_len; + goto invalid_param; + } + break; + case ATA_FEATURE_SUB_MPAGE: + if (qc->dev->flags & ATA_DFLAG_CDL && + pg == CONTROL_MPAGE) + break; + fallthrough; + default: + fp = (p[0] & 0x40) ? 1 : 0; + fp += hdr_len + bd_len; + goto invalid_param; + } } if (pg_len > len) goto invalid_param_len; @@ -3777,14 +4028,16 @@ static unsigned int ata_scsi_mode_select_xlat(struct ata_queued_cmd *qc) } break; case CONTROL_MPAGE: - if (ata_mselect_control(qc, p, pg_len, &fp) < 0) { + ret = ata_mselect_control(qc, spg, p, pg_len, &fp); + if (ret < 0) { fp += hdr_len + bd_len; goto invalid_param; - } else { - goto skip; /* No ATA command to send */ } + if (!ret) + goto skip; /* No ATA command to send */ break; - default: /* invalid page code */ + default: + /* Invalid page code */ fp = bd_len + hdr_len; goto invalid_param; } diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h index 926d0d33cd29ffe4c71b886e87e723c11de90a24..cf993885d2b259b1fc992065b89bed9f37e87b69 100644 --- a/drivers/ata/libata.h +++ b/drivers/ata/libata.h @@ -45,7 +45,7 @@ static inline void ata_force_cbl(struct ata_port *ap) { } extern u64 ata_tf_to_lba(const struct ata_taskfile *tf); extern u64 ata_tf_to_lba48(const struct ata_taskfile *tf); extern int ata_build_rw_tf(struct ata_queued_cmd *qc, u64 block, u32 n_block, - unsigned int tf_flags, int class); + unsigned int tf_flags, int dld, int class); extern u64 ata_tf_read_block(const struct ata_taskfile *tf, struct ata_device *dev); extern unsigned ata_exec_internal(struct ata_device *dev, diff --git a/drivers/ata/pata_ixp4xx_cf.c b/drivers/ata/pata_ixp4xx_cf.c index 99a2ce7234953f5b6139b3e18779a38d9f1c1035..b1daa4d3fcd97818bb6b26180008d515cef9ea00 100644 --- a/drivers/ata/pata_ixp4xx_cf.c +++ b/drivers/ata/pata_ixp4xx_cf.c @@ -303,7 +303,7 @@ static struct platform_driver ixp4xx_pata_platform_driver = { .of_match_table = ixp4xx_pata_of_match, }, .probe = ixp4xx_pata_probe, - .remove = ata_platform_remove_one, + .remove_new = ata_platform_remove_one, }; module_platform_driver(ixp4xx_pata_platform_driver); diff --git a/drivers/ata/pata_octeon_cf.c b/drivers/ata/pata_octeon_cf.c index b1ce9f1761af545ff2e39213b69d67603a5d0e39..ff538b8589287171d4a45ae9c6be5c3e30ad338f 100644 --- a/drivers/ata/pata_octeon_cf.c +++ b/drivers/ata/pata_octeon_cf.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -804,9 +805,7 @@ static int octeon_cf_probe(struct platform_device *pdev) struct resource *res_cs0, *res_cs1; bool is_16bit; - const __be32 *cs_num; - struct property *reg_prop; - int n_addr, n_size, reg_len; + u64 reg; struct device_node *node; void __iomem *cs0; void __iomem *cs1 = NULL; @@ -834,15 +833,10 @@ static int octeon_cf_probe(struct platform_device *pdev) else is_16bit = false; - n_addr = of_n_addr_cells(node); - n_size = of_n_size_cells(node); - - reg_prop = of_find_property(node, "reg", ®_len); - if (!reg_prop || reg_len < sizeof(__be32)) - return -EINVAL; - - cs_num = reg_prop->value; - cf_port->cs0 = be32_to_cpup(cs_num); + rv = of_property_read_reg(node, 0, ®, NULL); + if (rv < 0) + return rv; + cf_port->cs0 = upper_32_bits(reg); if (cf_port->is_true_ide) { struct device_node *dma_node; @@ -884,13 +878,12 @@ static int octeon_cf_probe(struct platform_device *pdev) cs1 = devm_ioremap(&pdev->dev, res_cs1->start, resource_size(res_cs1)); if (!cs1) - return rv; - - if (reg_len < (n_addr + n_size + 1) * sizeof(__be32)) return -EINVAL; - cs_num += n_addr + n_size; - cf_port->cs1 = be32_to_cpup(cs_num); + rv = of_property_read_reg(node, 1, ®, NULL); + if (rv < 0) + return rv; + cf_port->cs1 = upper_32_bits(reg); } res_cs0 = platform_get_resource(pdev, IORESOURCE_MEM, 0); diff --git a/drivers/ata/pata_of_platform.c b/drivers/ata/pata_of_platform.c index 178b28eff170a97f3c1190f432b8e54a465ecafb..4956f0f5b93fad69b500b4da91d5d0be78a33366 100644 --- a/drivers/ata/pata_of_platform.c +++ b/drivers/ata/pata_of_platform.c @@ -89,7 +89,7 @@ static struct platform_driver pata_of_platform_driver = { .of_match_table = pata_of_platform_match, }, .probe = pata_of_platform_probe, - .remove = ata_platform_remove_one, + .remove_new = ata_platform_remove_one, }; module_platform_driver(pata_of_platform_driver); diff --git a/drivers/ata/pata_parport/aten.c b/drivers/ata/pata_parport/aten.c index 1bd248c42f8b7ee246774f6e1a0104ba7335d86f..8328a49a95efca2c84e8cb9e71aa54755f24df41 100644 --- a/drivers/ata/pata_parport/aten.c +++ b/drivers/ata/pata_parport/aten.c @@ -1,13 +1,12 @@ -/* - aten.c (c) 1997-8 Grant R. Guenther - Under the terms of the GNU General Public License. - - aten.c is a low-level protocol driver for the ATEN EH-100 - parallel port adapter. The EH-100 supports 4-bit and 8-bit - modes only. There is also an EH-132 which supports EPP mode - transfers. The EH-132 is not yet supported. - -*/ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * (c) 1997-8 Grant R. Guenther + * + * aten.c is a low-level protocol driver for the ATEN EH-100 + * parallel port adapter. The EH-100 supports 4-bit and 8-bit + * modes only. There is also an EH-132 which supports EPP mode + * transfers. The EH-132 is not yet supported. + */ #include #include @@ -20,36 +19,36 @@ #define j44(a,b) ((((a>>4)&0x0f)|(b&0xf0))^0x88) -/* cont = 0 - access the IDE register file - cont = 1 - access the IDE command set -*/ - +/* + * cont = 0 - access the IDE register file + * cont = 1 - access the IDE command set + */ static int cont_map[2] = { 0x08, 0x20 }; static void aten_write_regr(struct pi_adapter *pi, int cont, int regr, int val) - -{ int r; - - r = regr + cont_map[cont] + 0x80; +{ + int r = regr + cont_map[cont] + 0x80; w0(r); w2(0xe); w2(6); w0(val); w2(7); w2(6); w2(0xc); } static int aten_read_regr(struct pi_adapter *pi, int cont, int regr) +{ + int a, b, r; -{ int a, b, r; - - r = regr + cont_map[cont] + 0x40; + r = regr + cont_map[cont] + 0x40; switch (pi->mode) { - case 0: w0(r); w2(0xe); w2(6); + case 0: + w0(r); w2(0xe); w2(6); w2(7); w2(6); w2(0); a = r1(); w0(0x10); b = r1(); w2(0xc); return j44(a,b); - case 1: r |= 0x10; - w0(r); w2(0xe); w2(6); w0(0xff); + case 1: + r |= 0x10; + w0(r); w2(0xe); w2(6); w0(0xff); w2(0x27); w2(0x26); w2(0x20); a = r0(); w2(0x26); w2(0xc); @@ -59,27 +58,30 @@ static int aten_read_regr(struct pi_adapter *pi, int cont, int regr) } static void aten_read_block(struct pi_adapter *pi, char *buf, int count) - -{ int k, a, b, c, d; +{ + int k, a, b, c, d; switch (pi->mode) { - case 0: w0(0x48); w2(0xe); w2(6); - for (k=0;ksaved_r0 = r0(); - pi->saved_r2 = r2(); - w2(0xc); +{ + pi->saved_r0 = r0(); + pi->saved_r2 = r2(); + w2(0xc); } static void aten_disconnect(struct pi_adapter *pi) - -{ w0(pi->saved_r0); - w2(pi->saved_r2); -} +{ + w0(pi->saved_r0); + w2(pi->saved_r2); +} static void aten_log_adapter(struct pi_adapter *pi) +{ + char *mode_string[2] = { "4-bit", "8-bit" }; -{ char *mode_string[2] = {"4-bit","8-bit"}; - - dev_info(&pi->dev, "ATEN EH-100 at 0x%x, mode %d (%s), delay %d\n", - pi->port, pi->mode, mode_string[pi->mode], pi->delay); + dev_info(&pi->dev, + "ATEN EH-100 at 0x%x, mode %d (%s), delay %d\n", + pi->port, pi->mode, mode_string[pi->mode], pi->delay); } static struct pi_protocol aten = { diff --git a/drivers/ata/pata_parport/bpck.c b/drivers/ata/pata_parport/bpck.c index 1c5035a09554afb774ce601315d0e2a692e2f170..9f4309f9b57f660fcaa2198ca90bc45ecac8844d 100644 --- a/drivers/ata/pata_parport/bpck.c +++ b/drivers/ata/pata_parport/bpck.c @@ -1,11 +1,10 @@ -/* - bpck.c (c) 1996-8 Grant R. Guenther - Under the terms of the GNU General Public License. - - bpck.c is a low-level protocol driver for the MicroSolutions - "backpack" parallel port IDE adapter. - -*/ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * (c) 1996-1998 Grant R. Guenther + * + * bpck.c is a low-level protocol driver for the MicroSolutions + * "backpack" parallel port IDE adapter. + */ #include #include @@ -29,59 +28,57 @@ #define j44(l,h) (((l>>3)&0x7)|((l>>4)&0x8)|((h<<1)&0x70)|(h&0x80)) -/* cont = 0 - access the IDE register file - cont = 1 - access the IDE command set - cont = 2 - use internal bpck register addressing -*/ - +/* + * cont = 0 - access the IDE register file + * cont = 1 - access the IDE command set + * cont = 2 - use internal bpck register addressing + */ static int cont_map[3] = { 0x40, 0x48, 0 }; static int bpck_read_regr(struct pi_adapter *pi, int cont, int regr) - -{ int r, l, h; +{ + int r, l, h; r = regr + cont_map[cont]; switch (pi->mode) { - - case 0: w0(r & 0xf); w0(r); t2(2); t2(4); + case 0: + w0(r & 0xf); w0(r); t2(2); t2(4); l = r1(); - t2(4); - h = r1(); - return j44(l,h); - - case 1: w0(r & 0xf); w0(r); t2(2); - e2(); t2(0x20); + t2(4); + h = r1(); + return j44(l, h); + case 1: + w0(r & 0xf); w0(r); t2(2); + e2(); t2(0x20); t2(4); h = r0(); - t2(1); t2(0x20); - return h; - + t2(1); t2(0x20); + return h; case 2: case 3: - case 4: w0(r); w2(9); w2(0); w2(0x20); + case 4: + w0(r); w2(9); w2(0); w2(0x20); h = r4(); w2(0); return h; } return -1; -} +} static void bpck_write_regr(struct pi_adapter *pi, int cont, int regr, int val) - -{ int r; +{ + int r; r = regr + cont_map[cont]; switch (pi->mode) { - case 0: case 1: w0(r); t2(2); w0(val); o2(); t2(4); t2(1); break; - case 2: case 3: case 4: w0(r); w2(9); w2(0); @@ -97,210 +94,249 @@ static void bpck_write_regr(struct pi_adapter *pi, int cont, int regr, int val) #define RR(r) (bpck_read_regr(pi,2,r)) static void bpck_write_block(struct pi_adapter *pi, char *buf, int count) - -{ int i; +{ + int i; switch (pi->mode) { - case 0: WR(4,0x40); + case 0: + WR(4, 0x40); + w0(0x40); t2(2); t2(1); + for (i = 0; i < count; i++) { + w0(buf[i]); + t2(4); + } + WR(4, 0); + break; + + case 1: + WR(4, 0x50); w0(0x40); t2(2); t2(1); - for (i=0;imode) { - case 0: WR(4,0x40); + case 0: + WR(4, 0x40); w0(0x40); t2(2); - for (i=0;iunit; s = 0; - w2(4); w2(0xe); r2(); t2(2); + w2(4); w2(0xe); r2(); t2(2); o1 = r1()&0xf8; o0 = r0(); w0(255-id); w2(4); w0(id); t2(8); t2(8); t2(8); t2(2); t = r1()&0xf8; f7 = ((id % 8) == 7); - if ((f7) || (t != o1)) { t2(2); s = r1()&0xf8; } + if ((f7) || (t != o1)) { + t2(2); + s = r1() & 0xf8; + } if ((t == o1) && ((!f7) || (s == o1))) { w2(0x4c); w0(o0); - return 0; + return 0; } t2(8); w0(0); t2(2); w2(0x4c); w0(o0); return 1; } - -static void bpck_connect(struct pi_adapter *pi) -{ pi->saved_r0 = r0(); +static void bpck_connect(struct pi_adapter *pi) +{ + pi->saved_r0 = r0(); w0(0xff-pi->unit); w2(4); w0(pi->unit); - t2(8); t2(8); t2(8); + t2(8); t2(8); t2(8); t2(2); t2(2); - - switch (pi->mode) { - case 0: t2(8); WR(4,0); + switch (pi->mode) { + case 0: + t2(8); WR(4, 0); break; - - case 1: t2(8); WR(4,0x10); + case 1: + t2(8); WR(4, 0x10); break; - case 2: - case 3: - case 4: w2(0); WR(4,8); + case 3: + case 4: + w2(0); WR(4, 8); break; - } WR(5,8); -/* if (pi->devtype == PI_PCD) { possibly wrong, purpose unknown */ - WR(0x46,0x10); /* fiddle with ESS logic ??? */ - WR(0x4c,0x38); - WR(0x4d,0x88); - WR(0x46,0xa0); - WR(0x41,0); - WR(0x4e,8); -/* }*/ + /* + * Possibly wrong, purpose unknown (fiddle with ESS logic ???) + * if (pi->devtype == PI_PCD) { + */ + WR(0x46, 0x10); + WR(0x4c, 0x38); + WR(0x4d, 0x88); + WR(0x46, 0xa0); + WR(0x41, 0); + WR(0x4e, 8); + /* } */ } static void bpck_disconnect(struct pi_adapter *pi) - -{ w0(0); - if (pi->mode >= 2) { w2(9); w2(0); } else t2(2); +{ + w0(0); + if (pi->mode >= 2) { + w2(9); w2(0); + } else { + t2(2); + } w2(0x4c); w0(pi->saved_r0); -} +} static void bpck_force_spp(struct pi_adapter *pi) +{ + /* This fakes the EPP protocol to turn off EPP ... */ + pi->saved_r0 = r0(); + w0(0xff-pi->unit); w2(4); w0(pi->unit); + t2(8); t2(8); t2(8); + t2(2); t2(2); -/* This fakes the EPP protocol to turn off EPP ... */ - -{ pi->saved_r0 = r0(); - w0(0xff-pi->unit); w2(4); w0(pi->unit); - t2(8); t2(8); t2(8); - t2(2); t2(2); - - w2(0); - w0(4); w2(9); w2(0); - w0(0); w2(1); w2(3); w2(0); - w0(0); w2(9); w2(0); - w2(0x4c); w0(pi->saved_r0); + w2(0); + w0(4); w2(9); w2(0); + w0(0); w2(1); w2(3); w2(0); + w0(0); w2(9); w2(0); + w2(0x4c); w0(pi->saved_r0); } #define TEST_LEN 16 static int bpck_test_proto(struct pi_adapter *pi) - -{ int i, e, l, h, om; +{ + int i, e, l, h, om; char buf[TEST_LEN]; bpck_force_spp(pi); switch (pi->mode) { - case 0: bpck_connect(pi); - WR(0x13,0x7f); + case 0: + bpck_connect(pi); + WR(0x13, 0x7f); w0(0x13); t2(2); - for(i=0;imode; + case 4: + om = pi->mode; pi->mode = 0; bpck_connect(pi); - WR(7,3); - WR(4,8); + WR(7, 3); + WR(4, 8); bpck_disconnect(pi); pi->mode = om; @@ -308,34 +344,44 @@ static int bpck_test_proto(struct pi_adapter *pi) w0(0x13); w2(9); w2(1); w0(0); w2(3); w2(0); w2(0xe0); switch (pi->mode) { - case 2: for (i=0;idev, "bpck: 0x%x unit %d mode %d: ", pi->port, pi->unit, pi->mode); - print_hex_dump_debug("bpck: ", DUMP_PREFIX_NONE, TEST_LEN, 1, buf, TEST_LEN, false); + print_hex_dump_debug("bpck: ", DUMP_PREFIX_NONE, TEST_LEN, 1, buf, + TEST_LEN, false); e = 0; - for (i=0;imode = 0; pi->delay = 6; bpck_connect(pi); - - WR(4,0); - for (i=0;i<64;i++) { - WR(6,8); - WR(6,0xc); - p = 0x100; - for (k=0;k<9;k++) { - f = (((i + 0x180) & p) != 0) * 2; - WR(6,f+0xc); - WR(6,f+0xd); - WR(6,f+0xc); - p = (p >> 1); - } - for (j=0;j<2;j++) { - v = 0; - for (k=0;k<8;k++) { - WR(6,0xc); - WR(6,0xd); - WR(6,0xc); - f = RR(0); - v = 2*v + (f == 0x84); + + WR(4, 0); + for (i = 0; i < 64; i++) { + WR(6, 8); + WR(6, 0xc); + p = 0x100; + for (k = 0; k < 9; k++) { + f = (((i + 0x180) & p) != 0) * 2; + WR(6, f + 0xc); + WR(6, f + 0xd); + WR(6, f + 0xc); + p = (p >> 1); + } + for (j = 0; j < 2; j++) { + v = 0; + for (k = 0; k < 8; k++) { + WR(6, 0xc); + WR(6, 0xd); + WR(6, 0xc); + f = RR(0); + v = 2 * v + (f == 0x84); + } + buf[2 * i + 1 - j] = v; } - buf[2*i+1-j] = v; - } } - WR(6,8); - WR(6,0); - WR(5,8); + WR(6, 8); + WR(6, 0); + WR(5, 8); bpck_disconnect(pi); if (om >= 2) { - bpck_connect(pi); - WR(7,3); - WR(4,8); - bpck_disconnect(pi); + bpck_connect(pi); + WR(7, 3); + WR(4, 8); + bpck_disconnect(pi); } pi->mode = om; pi->delay = od; } -static int bpck_test_port(struct pi_adapter *pi) /* check for 8-bit port */ - -{ int i, r, m; +static int bpck_test_port(struct pi_adapter *pi) +{ + int i, r, m; + /* Check for 8-bit port */ w2(0x2c); i = r0(); w0(255-i); r = r0(); w0(i); m = -1; - if (r == i) m = 2; - if (r == (255-i)) m = 0; + if (r == i) + m = 2; + if (r == (255-i)) + m = 0; + + w2(0xc); + i = r0(); + w0(255-i); + r = r0(); + w0(i); + if (r != (255-i)) + m = -1; + + if (m == 0) { + w2(6); + w2(0xc); + r = r0(); + w0(0xaa); + w0(r); + w0(0xaa); + } + if (m == 2) { + w2(0x26); + w2(0xc); + } - w2(0xc); i = r0(); w0(255-i); r = r0(); w0(i); - if (r != (255-i)) m = -1; - - if (m == 0) { w2(6); w2(0xc); r = r0(); w0(0xaa); w0(r); w0(0xaa); } - if (m == 2) { w2(0x26); w2(0xc); } + if (m == -1) + return 0; - if (m == -1) return 0; return 5; } static void bpck_log_adapter(struct pi_adapter *pi) - -{ char *mode_string[5] = { "4-bit","8-bit","EPP-8", - "EPP-16","EPP-32" }; +{ + char *mode_str[5] = { "4-bit", "8-bit", "EPP-8", "EPP-16", "EPP-32" }; char scratch[128]; bpck_read_eeprom(pi,scratch); print_hex_dump_bytes("bpck EEPROM: ", DUMP_PREFIX_NONE, scratch, 128); - dev_info(&pi->dev, "backpack %8.8s unit %d at 0x%x, mode %d (%s), delay %d\n", + dev_info(&pi->dev, + "backpack %8.8s unit %d at 0x%x, mode %d (%s), delay %d\n", &scratch[110], pi->unit, pi->port, pi->mode, - mode_string[pi->mode], pi->delay); + mode_str[pi->mode], pi->delay); } static struct pi_protocol bpck = { diff --git a/drivers/ata/pata_parport/bpck6.c b/drivers/ata/pata_parport/bpck6.c index 76febd07a9bb43a08ae53c1114b1f109fc1b44cf..c6dbd14120d122d05ad0b0f12277c1003673d57c 100644 --- a/drivers/ata/pata_parport/bpck6.c +++ b/drivers/ata/pata_parport/bpck6.c @@ -1,15 +1,13 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* - backpack.c (c) 2001 Micro Solutions Inc. - Released under the terms of the GNU General Public license - - backpack.c is a low-level protocol driver for the Micro Solutions - "BACKPACK" parallel port IDE adapter - (Works on Series 6 drives) - - Written by: Ken Hahn (linux-dev@micro-solutions.com) - Clive Turvey (linux-dev@micro-solutions.com) - -*/ + * (c) 2001 Micro Solutions Inc. + * + * backpack.c is a low-level protocol driver for the Micro Solutions + * "BACKPACK" parallel port IDE adapter (works on Series 6 drives). + * + * Written by: Ken Hahn (linux-dev@micro-solutions.com) + * Clive Turvey (linux-dev@micro-solutions.com) + */ #include #include @@ -326,11 +324,14 @@ static int bpck6_open(struct pi_adapter *pi) if (j != k) goto fail; - if (i & 4) // EPP + if (i & 4) { + /* EPP */ parport_frob_control(pi->pardev->port, PARPORT_CONTROL_SELECT | PARPORT_CONTROL_INIT, 0); - else // PPC/ECP + } else { + /* PPC/ECP */ parport_frob_control(pi->pardev->port, PARPORT_CONTROL_SELECT, 0); + } pi->private = 0; @@ -347,17 +348,20 @@ static int bpck6_open(struct pi_adapter *pi) parport_write_control(pi->pardev->port, pi->saved_r2); parport_write_data(pi->pardev->port, pi->saved_r0); - return 0; // FAIL + return 0; } static void bpck6_deselect(struct pi_adapter *pi) { - if (mode_map[pi->mode] & 4) // EPP + if (mode_map[pi->mode] & 4) { + /* EPP */ parport_frob_control(pi->pardev->port, PARPORT_CONTROL_INIT, - PARPORT_CONTROL_INIT); - else // PPC/ECP + PARPORT_CONTROL_INIT); + } else { + /* PPC/ECP */ parport_frob_control(pi->pardev->port, PARPORT_CONTROL_SELECT, - PARPORT_CONTROL_SELECT); + PARPORT_CONTROL_SELECT); + } parport_write_data(pi->pardev->port, pi->saved_r0); parport_write_control(pi->pardev->port, @@ -386,7 +390,8 @@ static void bpck6_disconnect(struct pi_adapter *pi) bpck6_deselect(pi); } -static int bpck6_test_port(struct pi_adapter *pi) /* check for 8-bit port */ +/* check for 8-bit port */ +static int bpck6_test_port(struct pi_adapter *pi) { dev_dbg(&pi->dev, "PARPORT indicates modes=%x for lp=0x%lx\n", pi->pardev->port->modes, pi->pardev->port->base); @@ -413,28 +418,26 @@ static int bpck6_probe_unit(struct pi_adapter *pi) dev_dbg(&pi->dev, "ppc_open returned %2x\n", out); - if(out) - { + if (out) { bpck6_deselect(pi); dev_dbg(&pi->dev, "leaving probe\n"); pi->mode = saved_mode; - return(1); + return 1; } - else - { - dev_dbg(&pi->dev, "Failed open\n"); - pi->mode = saved_mode; - return(0); - } + + dev_dbg(&pi->dev, "Failed open\n"); + pi->mode = saved_mode; + + return 0; } static void bpck6_log_adapter(struct pi_adapter *pi) { - char *mode_string[5]= - {"4-bit","8-bit","EPP-8","EPP-16","EPP-32"}; + char *mode_string[5] = { "4-bit", "8-bit", "EPP-8", "EPP-16", "EPP-32" }; - dev_info(&pi->dev, "Micro Solutions BACKPACK Drive unit %d at 0x%x, mode:%d (%s), delay %d\n", - pi->unit, pi->port, pi->mode, mode_string[pi->mode], pi->delay); + dev_info(&pi->dev, + "Micro Solutions BACKPACK Drive unit %d at 0x%x, mode:%d (%s), delay %d\n", + pi->unit, pi->port, pi->mode, mode_string[pi->mode], pi->delay); } static struct pi_protocol bpck6 = { diff --git a/drivers/ata/pata_parport/comm.c b/drivers/ata/pata_parport/comm.c index 4c2f9ad60ad8a676d7610b3bbe1a5d8f1acaa2dd..cc5485bd0a5b6dfdd326603a98f29a1a1c08d98b 100644 --- a/drivers/ata/pata_parport/comm.c +++ b/drivers/ata/pata_parport/comm.c @@ -1,12 +1,11 @@ -/* - comm.c (c) 1997-8 Grant R. Guenther - Under the terms of the GNU General Public License. - - comm.c is a low-level protocol driver for some older models - of the DataStor "Commuter" parallel to IDE adapter. Some of - the parallel port devices marketed by Arista currently - use this adapter. -*/ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * (c) 1997-1998 Grant R. Guenther + * + * comm.c is a low-level protocol driver for some older models of the DataStor + * "Commuter" parallel to IDE adapter. Some of the parallel port devices + * marketed by Arista currently use this adapter. + */ #include #include @@ -17,165 +16,172 @@ #include #include "pata_parport.h" -/* mode codes: 0 nybble reads, 8-bit writes - 1 8-bit reads and writes - 2 8-bit EPP mode -*/ +/* + * mode codes: 0 nybble reads, 8-bit writes + * 1 8-bit reads and writes + * 2 8-bit EPP mode + */ -#define j44(a,b) (((a>>3)&0x0f)|((b<<1)&0xf0)) +#define j44(a, b) (((a >> 3) & 0x0f) | ((b << 1) & 0xf0)) #define P1 w2(5);w2(0xd);w2(0xd);w2(5);w2(4); #define P2 w2(5);w2(7);w2(7);w2(5);w2(4); -/* cont = 0 - access the IDE register file - cont = 1 - access the IDE command set -*/ - +/* + * cont = 0 - access the IDE register file + * cont = 1 - access the IDE command set + */ static int cont_map[2] = { 0x08, 0x10 }; static int comm_read_regr(struct pi_adapter *pi, int cont, int regr) - -{ int l, h, r; +{ + int l, h, r; r = regr + cont_map[cont]; - switch (pi->mode) { + switch (pi->mode) { + case 0: + w0(r); P1; w0(0); + w2(6); l = r1(); w0(0x80); h = r1(); w2(4); + return j44(l, h); - case 0: w0(r); P1; w0(0); - w2(6); l = r1(); w0(0x80); h = r1(); w2(4); - return j44(l,h); - - case 1: w0(r+0x20); P1; - w0(0); w2(0x26); h = r0(); w2(4); - return h; + case 1: + w0(r+0x20); P1; + w0(0); w2(0x26); h = r0(); w2(4); + return h; case 2: case 3: - case 4: w3(r+0x20); (void)r1(); - w2(0x24); h = r4(); w2(4); - return h; + case 4: + w3(r+0x20); (void)r1(); + w2(0x24); h = r4(); w2(4); + return h; + } - } - return -1; -} + return -1; +} static void comm_write_regr(struct pi_adapter *pi, int cont, int regr, int val) +{ + int r = regr + cont_map[cont]; -{ int r; - - r = regr + cont_map[cont]; - - switch (pi->mode) { - - case 0: - case 1: w0(r); P1; w0(val); P2; + switch (pi->mode) { + case 0: + case 1: + w0(r); P1; w0(val); P2; break; - case 2: case 3: - case 4: w3(r); (void)r1(); w4(val); - break; - } + case 4: + w3(r); (void)r1(); w4(val); + break; + } } static void comm_connect(struct pi_adapter *pi) - -{ pi->saved_r0 = r0(); - pi->saved_r2 = r2(); - w2(4); w0(0xff); w2(6); - w2(4); w0(0xaa); w2(6); - w2(4); w0(0x00); w2(6); - w2(4); w0(0x87); w2(6); - w2(4); w0(0xe0); w2(0xc); w2(0xc); w2(4); +{ + pi->saved_r0 = r0(); + pi->saved_r2 = r2(); + w2(4); w0(0xff); w2(6); + w2(4); w0(0xaa); w2(6); + w2(4); w0(0x00); w2(6); + w2(4); w0(0x87); w2(6); + w2(4); w0(0xe0); w2(0xc); w2(0xc); w2(4); } static void comm_disconnect(struct pi_adapter *pi) -{ w2(0); w2(0); w2(0); w2(4); +{ + w2(0); w2(0); w2(0); w2(4); w0(pi->saved_r0); - w2(pi->saved_r2); -} + w2(pi->saved_r2); +} static void comm_read_block(struct pi_adapter *pi, char *buf, int count) - -{ int i, l, h; - - switch (pi->mode) { - - case 0: w0(0x48); P1; - for(i=0;imode) { + case 0: + w0(0x48); P1; + for (i = 0; i < count; i++) { + w0(0); w2(6); l = r1(); + w0(0x80); h = r1(); w2(4); + buf[i] = j44(l, h); + } + break; + case 1: + w0(0x68); P1; w0(0); + for (i = 0; i < count; i++) { + w2(0x26); + buf[i] = r0(); + w2(0x24); + } w2(4); break; - - case 2: w3(0x68); (void)r1(); w2(0x24); - for (i=0;imode) { - - case 0: - case 1: w0(0x68); P1; - for (k=0;kmode) { + case 0: + case 1: + w0(0x68); P1; + for (k = 0; k < count; k++) { + w2(5); + w0(buf[k ^ 1]); + w2(7); + } + w2(5); w2(4); + break; + case 2: + w3(0x48); (void)r1(); + for (k = 0; k < count; k++) + w4(buf[k ^ 1]); + break; + case 3: + w3(0x48); (void)r1(); for (k = 0; k < count / 2; k++) w4w(swab16(((u16 *)buf)[k])); - break; - - case 4: w3(0x48); (void)r1(); + break; + case 4: + w3(0x48); (void)r1(); for (k = 0; k < count / 4; k++) w4l(swab16(((u16 *)buf)[2 * k]) | swab16(((u16 *)buf)[2 * k + 1]) << 16); - break; - - + break; } } static void comm_log_adapter(struct pi_adapter *pi) -{ char *mode_string[5] = {"4-bit","8-bit","EPP-8","EPP-16","EPP-32"}; +{ char *mode_string[5] = { "4-bit", "8-bit", "EPP-8", "EPP-16", "EPP-32" }; - dev_info(&pi->dev, "DataStor Commuter at 0x%x, mode %d (%s), delay %d\n", - pi->port, pi->mode, mode_string[pi->mode], pi->delay); + dev_info(&pi->dev, + "DataStor Commuter at 0x%x, mode %d (%s), delay %d\n", + pi->port, pi->mode, mode_string[pi->mode], pi->delay); } static struct pi_protocol comm = { diff --git a/drivers/ata/pata_parport/dstr.c b/drivers/ata/pata_parport/dstr.c index 2524684be206dc4c47ef67e7421b9c005925ed79..368d7c7962a9057f2998e618bd4abc99c87b4021 100644 --- a/drivers/ata/pata_parport/dstr.c +++ b/drivers/ata/pata_parport/dstr.c @@ -1,11 +1,10 @@ -/* - dstr.c (c) 1997-8 Grant R. Guenther - Under the terms of the GNU General Public License. - - dstr.c is a low-level protocol driver for the - DataStor EP2000 parallel to IDE adapter chip. - -*/ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * (c) 1997-1998 Grant R. Guenther + * + * dstr.c is a low-level protocol driver for the DataStor EP2000 parallel + * to IDE adapter chip. + */ #include #include @@ -16,178 +15,202 @@ #include #include "pata_parport.h" -/* mode codes: 0 nybble reads, 8-bit writes - 1 8-bit reads and writes - 2 8-bit EPP mode - 3 EPP-16 - 4 EPP-32 -*/ +/* + * mode codes: 0 nybble reads, 8-bit writes + * 1 8-bit reads and writes + * 2 8-bit EPP mode + * 3 EPP-16 + * 4 EPP-32 + */ -#define j44(a,b) (((a>>3)&0x07)|((~a>>4)&0x08)|((b<<1)&0x70)|((~b)&0x80)) +#define j44(a, b) (((a >> 3) & 0x07) | ((~a >> 4) & 0x08) | \ + ((b << 1) & 0x70) | ((~b) & 0x80)) #define P1 w2(5);w2(0xd);w2(5);w2(4); #define P2 w2(5);w2(7);w2(5);w2(4); #define P3 w2(6);w2(4);w2(6);w2(4); -/* cont = 0 - access the IDE register file - cont = 1 - access the IDE command set -*/ - +/* + * cont = 0 - access the IDE register file + * cont = 1 - access the IDE command set + */ static int cont_map[2] = { 0x20, 0x40 }; static int dstr_read_regr(struct pi_adapter *pi, int cont, int regr) +{ + int a, b, r; -{ int a, b, r; - - r = regr + cont_map[cont]; + r = regr + cont_map[cont]; w0(0x81); P1; - if (pi->mode) { w0(0x11); } else { w0(1); } + if (pi->mode) + w0(0x11); + else + w0(1); P2; w0(r); P1; - switch (pi->mode) { - - case 0: w2(6); a = r1(); w2(4); w2(6); b = r1(); w2(4); - return j44(a,b); - - case 1: w0(0); w2(0x26); a = r0(); w2(4); - return a; - + switch (pi->mode) { + case 0: + w2(6); a = r1(); w2(4); w2(6); b = r1(); w2(4); + return j44(a, b); + case 1: + w0(0); w2(0x26); a = r0(); w2(4); + return a; case 2: case 3: - case 4: w2(0x24); a = r4(); w2(4); - return a; + case 4: + w2(0x24); a = r4(); w2(4); + return a; + } - } - return -1; -} + return -1; +} static void dstr_write_regr(struct pi_adapter *pi, int cont, int regr, int val) +{ + int r = regr + cont_map[cont]; -{ int r; - - r = regr + cont_map[cont]; - - w0(0x81); P1; - if (pi->mode >= 2) { w0(0x11); } else { w0(1); } + w0(0x81); P1; + if (pi->mode >= 2) + w0(0x11); + else + w0(1); P2; w0(r); P1; - - switch (pi->mode) { - case 0: - case 1: w0(val); w2(5); w2(7); w2(5); w2(4); + switch (pi->mode) { + case 0: + case 1: + w0(val); w2(5); w2(7); w2(5); w2(4); break; - case 2: case 3: - case 4: w4(val); - break; - } + case 4: + w4(val); + break; + } } -#define CCP(x) w0(0xff);w2(0xc);w2(4);\ - w0(0xaa);w0(0x55);w0(0);w0(0xff);w0(0x87);w0(0x78);\ - w0(x);w2(5);w2(4); +#define CCP(x) \ + do { \ + w0(0xff); w2(0xc); w2(4); \ + w0(0xaa); w0(0x55); w0(0); w0(0xff); \ + w0(0x87); w0(0x78); \ + w0(x); w2(5); w2(4); \ + } while (0) static void dstr_connect(struct pi_adapter *pi) - -{ pi->saved_r0 = r0(); - pi->saved_r2 = r2(); - w2(4); CCP(0xe0); w0(0xff); +{ + pi->saved_r0 = r0(); + pi->saved_r2 = r2(); + w2(4); CCP(0xe0); w0(0xff); } static void dstr_disconnect(struct pi_adapter *pi) - -{ CCP(0x30); - w0(pi->saved_r0); - w2(pi->saved_r2); -} +{ + CCP(0x30); + w0(pi->saved_r0); + w2(pi->saved_r2); +} static void dstr_read_block(struct pi_adapter *pi, char *buf, int count) - -{ int k, a, b; +{ + int k, a, b; w0(0x81); P1; - if (pi->mode) { w0(0x19); } else { w0(9); } + if (pi->mode) + w0(0x19); + else + w0(9); P2; w0(0x82); P1; P3; w0(0x20); P1; - switch (pi->mode) { - - case 0: for (k=0;kmode) { + case 0: + for (k = 0; k < count; k++) { + w2(6); a = r1(); w2(4); + w2(6); b = r1(); w2(4); + buf[k] = j44(a, b); + } + break; + case 1: + w0(0); + for (k = 0; k < count; k++) { + w2(0x26); + buf[k] = r0(); + w2(0x24); + } + w2(4); + break; + case 2: + w2(0x24); + for (k = 0; k < count; k++) + buf[k] = r4(); + w2(4); + break; + case 3: + w2(0x24); + for (k = 0; k < count / 2; k++) + ((u16 *)buf)[k] = r4w(); + w2(4); + break; + case 4: + w2(0x24); + for (k = 0; k < count / 4; k++) + ((u32 *)buf)[k] = r4l(); + w2(4); + break; + } } static void dstr_write_block(struct pi_adapter *pi, char *buf, int count) +{ + int k; -{ int k; - - w0(0x81); P1; - if (pi->mode) { w0(0x19); } else { w0(9); } - P2; w0(0x82); P1; P3; w0(0x20); P1; - - switch (pi->mode) { - - case 0: - case 1: for (k=0;kmode) + w0(0x19); + else + w0(9); + P2; w0(0x82); P1; P3; w0(0x20); P1; - case 2: w2(0xc5); - for (k=0;kmode) { + case 0: + case 1: + for (k = 0; k < count; k++) { + w2(5); + w0(buf[k]); + w2(7); + } + w2(5); w2(4); + break; + case 2: + w2(0xc5); + for (k = 0; k < count; k++) + w4(buf[k]); w2(0xc4); - break; - - case 3: w2(0xc5); - for (k=0;kdev, "DataStor EP2000 at 0x%x, mode %d (%s), delay %d\n", - pi->port, pi->mode, mode_string[pi->mode], pi->delay); + dev_info(&pi->dev, + "DataStor EP2000 at 0x%x, mode %d (%s), delay %d\n", + pi->port, pi->mode, mode_string[pi->mode], pi->delay); } static struct pi_protocol dstr = { diff --git a/drivers/ata/pata_parport/epat.c b/drivers/ata/pata_parport/epat.c index b146999368ae8222fbde273e035affc15753de18..016bd96bce899fbe233244c26f328d0cc2290b15 100644 --- a/drivers/ata/pata_parport/epat.c +++ b/drivers/ata/pata_parport/epat.c @@ -1,13 +1,12 @@ -/* - epat.c (c) 1997-8 Grant R. Guenther - Under the terms of the GNU General Public License. - - This is the low level protocol driver for the EPAT parallel - to IDE adapter from Shuttle Technologies. This adapter is - used in many popular parallel port disk products such as the - SyQuest EZ drives, the Avatar Shark and the Imation SuperDisk. - -*/ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * (c) 1997-1998 Grant R. Guenther + * + * This is the low level protocol driver for the EPAT parallel + * to IDE adapter from Shuttle Technologies. This adapter is + * used in many popular parallel port disk products such as the + * SyQuest EZ drives, the Avatar Shark and the Imation SuperDisk. + */ #include #include @@ -18,276 +17,313 @@ #include #include "pata_parport.h" -#define j44(a,b) (((a>>4)&0x0f)+(b&0xf0)) -#define j53(a,b) (((a>>3)&0x1f)+((b<<4)&0xe0)) +#define j44(a, b) (((a >> 4) & 0x0f) + (b & 0xf0)) +#define j53(a, b) (((a >> 3) & 0x1f) + ((b << 4) & 0xe0)) static int epatc8; module_param(epatc8, int, 0); -MODULE_PARM_DESC(epatc8, "support for the Shuttle EP1284 chip, " - "used in any recent Imation SuperDisk (LS-120) drive."); - -/* cont = 0 IDE register file - cont = 1 IDE control registers - cont = 2 internal EPAT registers -*/ - +MODULE_PARM_DESC(epatc8, + "support for the Shuttle EP1284 chip, " + "used in any recent Imation SuperDisk (LS-120) drive."); + +/* + * cont = 0 IDE register file + * cont = 1 IDE control registers + * cont = 2 internal EPAT registers + */ static int cont_map[3] = { 0x18, 0x10, 0 }; static void epat_write_regr(struct pi_adapter *pi, int cont, int regr, int val) - -{ int r; - - r = regr + cont_map[cont]; +{ + int r = regr + cont_map[cont]; switch (pi->mode) { - case 0: case 1: - case 2: w0(0x60+r); w2(1); w0(val); w2(4); + case 2: + w0(0x60+r); w2(1); w0(val); w2(4); break; - case 3: case 4: - case 5: w3(0x40+r); w4(val); + case 5: + w3(0x40+r); w4(val); break; - } } static int epat_read_regr(struct pi_adapter *pi, int cont, int regr) - -{ int a, b, r; +{ + int a, b, r; r = regr + cont_map[cont]; switch (pi->mode) { - case 0: w0(r); w2(1); w2(3); + case 0: + w0(r); w2(1); w2(3); a = r1(); w2(4); b = r1(); - return j44(a,b); - - case 1: w0(0x40+r); w2(1); w2(4); + return j44(a, b); + case 1: + w0(0x40+r); w2(1); w2(4); a = r1(); b = r2(); w0(0xff); - return j53(a,b); - - case 2: w0(0x20+r); w2(1); w2(0x25); + return j53(a, b); + case 2: + w0(0x20+r); w2(1); w2(0x25); a = r0(); w2(4); return a; - case 3: case 4: - case 5: w3(r); w2(0x24); a = r4(); w2(4); + case 5: + w3(r); w2(0x24); a = r4(); w2(4); return a; - } + return -1; /* never gets here */ } static void epat_read_block(struct pi_adapter *pi, char *buf, int count) - -{ int k, ph, a, b; +{ + int k, ph, a, b; switch (pi->mode) { - case 0: w0(7); w2(1); w2(3); w0(0xff); + case 0: + w0(7); w2(1); w2(3); w0(0xff); ph = 0; - for(k=0;kmode) { - case 0: case 1: - case 2: w0(0x67); w2(1); w2(5); + case 2: + w0(0x67); w2(1); w2(5); ph = 0; - for(k=0;ksaved_r0 = r0(); - pi->saved_r2 = r2(); +{ + pi->saved_r0 = r0(); + pi->saved_r2 = r2(); /* Initialize the chip */ CPP(0); if (epatc8) { - CPP(0x40);CPP(0xe0); - w0(0);w2(1);w2(4); - WR(0x8,0x12);WR(0xc,0x14);WR(0x12,0x10); - WR(0xe,0xf);WR(0xf,4); + CPP(0x40); CPP(0xe0); + w0(0); w2(1); w2(4); + WR(0x8, 0x12); + WR(0xc, 0x14); + WR(0x12, 0x10); + WR(0xe, 0xf); + WR(0xf, 4); /* WR(0xe,0xa);WR(0xf,4); */ - WR(0xe,0xd);WR(0xf,0); + WR(0xe, 0xd); + WR(0xf, 0); /* CPP(0x30); */ } /* Connect to the chip */ CPP(0xe0); - w0(0);w2(1);w2(4); /* Idle into SPP */ + w0(0); w2(1); w2(4); /* Idle into SPP */ if (pi->mode >= 3) { - w0(0);w2(1);w2(4);w2(0xc); - /* Request EPP */ - w0(0x40);w2(6);w2(7);w2(4);w2(0xc);w2(4); + w0(0); w2(1); w2(4); w2(0xc); + /* Request EPP */ + w0(0x40); w2(6); w2(7); w2(4); w2(0xc); w2(4); } if (!epatc8) { - WR(8,0x10); WR(0xc,0x14); WR(0xa,0x38); WR(0x12,0x10); + WR(8, 0x10); + WR(0xc, 0x14); + WR(0xa, 0x38); + WR(0x12, 0x10); } } static void epat_disconnect(struct pi_adapter *pi) -{ CPP(0x30); +{ + CPP(0x30); w0(pi->saved_r0); w2(pi->saved_r2); } static int epat_test_proto(struct pi_adapter *pi) - -{ int k, j, f, cc; - int e[2] = {0,0}; +{ + int k, j, f, cc; + int e[2] = { 0, 0 }; char scratch[512]; - epat_connect(pi); + epat_connect(pi); cc = RR(0xd); epat_disconnect(pi); epat_connect(pi); for (j=0;j<2;j++) { - WRi(6,0xa0+j*0x10); - for (k=0;k<256;k++) { - WRi(2,k^0xaa); - WRi(3,k^0x55); - if (RRi(2) != (k^0xaa)) e[j]++; - } - } - epat_disconnect(pi); - - f = 0; - epat_connect(pi); - WR(0x13,1); WR(0x13,0); WR(0xa,0x11); - epat_read_block(pi,scratch,512); - - for (k=0;k<256;k++) { - if ((scratch[2*k] & 0xff) != k) f++; - if ((scratch[2*k+1] & 0xff) != (0xff-k)) f++; - } - epat_disconnect(pi); + WRi(6, 0xa0 + j * 0x10); + for (k = 0; k < 256; k++) { + WRi(2, k ^ 0xaa); + WRi(3, k ^ 0x55); + if (RRi(2) != (k ^ 0xaa)) + e[j]++; + } + } + epat_disconnect(pi); - dev_dbg(&pi->dev, "epat: port 0x%x, mode %d, ccr %x, test=(%d,%d,%d)\n", - pi->port, pi->mode, cc, e[0], e[1], f); - - return (e[0] && e[1]) || f; + f = 0; + epat_connect(pi); + WR(0x13, 1); WR(0x13, 0); WR(0xa, 0x11); + epat_read_block(pi, scratch, 512); + + for (k = 0; k < 256; k++) { + if ((scratch[2 * k] & 0xff) != k) + f++; + if ((scratch[2 * k + 1] & 0xff) != 0xff - k) + f++; + } + epat_disconnect(pi); + + dev_dbg(&pi->dev, + "epat: port 0x%x, mode %d, ccr %x, test=(%d,%d,%d)\n", + pi->port, pi->mode, cc, e[0], e[1], f); + + return (e[0] && e[1]) || f; } static void epat_log_adapter(struct pi_adapter *pi) - -{ int ver; - char *mode_string[6] = - {"4-bit","5/3","8-bit","EPP-8","EPP-16","EPP-32"}; +{ + int ver; + char *mode_string[6] = + { "4-bit", "5/3", "8-bit", "EPP-8", "EPP-16", "EPP-32" }; epat_connect(pi); - WR(0xa,0x38); /* read the version code */ - ver = RR(0xb); - epat_disconnect(pi); + WR(0xa, 0x38); /* read the version code */ + ver = RR(0xb); + epat_disconnect(pi); - dev_info(&pi->dev, "Shuttle EPAT chip %x at 0x%x, mode %d (%s), delay %d\n", + dev_info(&pi->dev, + "Shuttle EPAT chip %x at 0x%x, mode %d (%s), delay %d\n", ver, pi->port, pi->mode, mode_string[pi->mode], pi->delay); } diff --git a/drivers/ata/pata_parport/epia.c b/drivers/ata/pata_parport/epia.c index f6db2f79fe999b19c13b2e9551be8a31ff2870e6..920e9f40d4019f896c7aa374ed580e1af2ca72c5 100644 --- a/drivers/ata/pata_parport/epia.c +++ b/drivers/ata/pata_parport/epia.c @@ -1,14 +1,13 @@ -/* - epia.c (c) 1997-8 Grant R. Guenther - Under the terms of the GNU General Public License. - - epia.c is a low-level protocol driver for Shuttle Technologies - EPIA parallel to IDE adapter chip. This device is now obsolete - and has been replaced with the EPAT chip, which is supported - by epat.c, however, some devices based on EPIA are still - available. - -*/ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * (c) 1997-1998 Grant R. Guenther + * + * epia.c is a low-level protocol driver for Shuttle Technologies + * EPIA parallel to IDE adapter chip. This device is now obsolete + * and has been replaced with the EPAT chip, which is supported + * by epat.c, however, some devices based on EPIA are still + * available. + */ #include #include @@ -19,255 +18,274 @@ #include #include "pata_parport.h" -/* mode codes: 0 nybble reads on port 1, 8-bit writes - 1 5/3 reads on ports 1 & 2, 8-bit writes - 2 8-bit reads and writes - 3 8-bit EPP mode - 4 16-bit EPP - 5 32-bit EPP -*/ - -#define j44(a,b) (((a>>4)&0x0f)+(b&0xf0)) -#define j53(a,b) (((a>>3)&0x1f)+((b<<4)&0xe0)) - -/* cont = 0 IDE register file - cont = 1 IDE control registers -*/ - +/* + * mode codes: 0 nybble reads on port 1, 8-bit writes + * 1 5/3 reads on ports 1 & 2, 8-bit writes + * 2 8-bit reads and writes + * 3 8-bit EPP mode + * 4 16-bit EPP + * 5 32-bit EPP + */ + +#define j44(a, b) (((a >> 4) & 0x0f) + (b & 0xf0)) +#define j53(a, b) (((a >> 3) & 0x1f) + ((b << 4) & 0xe0)) + +/* + * cont = 0 IDE register file + * cont = 1 IDE control registers + */ static int cont_map[2] = { 0, 0x80 }; static int epia_read_regr(struct pi_adapter *pi, int cont, int regr) - -{ int a, b, r; +{ + int a, b, r; regr += cont_map[cont]; - switch (pi->mode) { - - case 0: r = regr^0x39; - w0(r); w2(1); w2(3); w0(r); - a = r1(); w2(1); b = r1(); w2(4); - return j44(a,b); - - case 1: r = regr^0x31; - w0(r); w2(1); w0(r&0x37); - w2(3); w2(5); w0(r|0xf0); - a = r1(); b = r2(); w2(4); - return j53(a,b); - - case 2: r = regr^0x29; - w0(r); w2(1); w2(0X21); w2(0x23); - a = r0(); w2(4); - return a; - + switch (pi->mode) { + case 0: + r = regr ^ 0x39; + w0(r); w2(1); w2(3); w0(r); + a = r1(); w2(1); b = r1(); w2(4); + return j44(a, b); + case 1: + r = regr ^ 0x31; + w0(r); w2(1); w0(r & 0x37); + w2(3); w2(5); w0(r | 0xf0); + a = r1(); b = r2(); w2(4); + return j53(a, b); + case 2: + r = regr^0x29; + w0(r); w2(1); w2(0X21); w2(0x23); + a = r0(); w2(4); + return a; case 3: case 4: - case 5: w3(regr); w2(0x24); a = r4(); w2(4); - return a; + case 5: + w3(regr); w2(0x24); a = r4(); w2(4); + return a; + } - } - return -1; -} + return -1; +} static void epia_write_regr(struct pi_adapter *pi, int cont, int regr, int val) - -{ int r; +{ + int r; regr += cont_map[cont]; - switch (pi->mode) { - - case 0: - case 1: - case 2: r = regr^0x19; - w0(r); w2(1); w0(val); w2(3); w2(4); - break; - + switch (pi->mode) { + case 0: + case 1: + case 2: + r = regr ^ 0x19; + w0(r); w2(1); w0(val); w2(3); w2(4); + break; case 3: case 4: - case 5: r = regr^0x40; - w3(r); w4(val); w2(4); - break; - } + case 5: + r = regr ^ 0x40; + w3(r); w4(val); w2(4); + break; + } } -#define WR(r,v) epia_write_regr(pi,0,r,v) -#define RR(r) (epia_read_regr(pi,0,r)) - -/* The use of register 0x84 is entirely unclear - it seems to control - some EPP counters ... currently we know about 3 different block - sizes: the standard 512 byte reads and writes, 12 byte writes and - 2048 byte reads (the last two being used in the CDrom drivers. -*/ +#define WR(r, v) epia_write_regr(pi, 0, r, v) +#define RR(r) epia_read_regr(pi, 0, r) +/* + * The use of register 0x84 is entirely unclear - it seems to control + * some EPP counters ... currently we know about 3 different block + * sizes: the standard 512 byte reads and writes, 12 byte writes and + * 2048 byte reads (the last two being used in the CDrom drivers. + */ static void epia_connect(struct pi_adapter *pi) - -{ pi->saved_r0 = r0(); - pi->saved_r2 = r2(); - - w2(4); w0(0xa0); w0(0x50); w0(0xc0); w0(0x30); w0(0xa0); w0(0); - w2(1); w2(4); - if (pi->mode >= 3) { - w0(0xa); w2(1); w2(4); w0(0x82); w2(4); w2(0xc); w2(4); - w2(0x24); w2(0x26); w2(4); - } - WR(0x86,8); +{ + pi->saved_r0 = r0(); + pi->saved_r2 = r2(); + + w2(4); w0(0xa0); w0(0x50); w0(0xc0); w0(0x30); w0(0xa0); w0(0); + w2(1); w2(4); + if (pi->mode >= 3) { + w0(0xa); w2(1); w2(4); w0(0x82); w2(4); w2(0xc); w2(4); + w2(0x24); w2(0x26); w2(4); + } + WR(0x86, 8); } static void epia_disconnect(struct pi_adapter *pi) - -{ /* WR(0x84,0x10); */ - w0(pi->saved_r0); - w2(1); w2(4); - w0(pi->saved_r0); - w2(pi->saved_r2); -} +{ + /* WR(0x84,0x10); */ + w0(pi->saved_r0); + w2(1); w2(4); + w0(pi->saved_r0); + w2(pi->saved_r2); +} static void epia_read_block(struct pi_adapter *pi, char *buf, int count) -{ int k, ph, a, b; - - switch (pi->mode) { - - case 0: w0(0x81); w2(1); w2(3); w0(0xc1); - ph = 1; - for (k=0;k 512) WR(0x84,3); +{ + int k, ph, a, b; + + switch (pi->mode) { + case 0: + w0(0x81); w2(1); w2(3); w0(0xc1); + ph = 1; + for (k = 0; k < count; k++) { + w2(2+ph); a = r1(); + w2(4+ph); b = r1(); + buf[k] = j44(a, b); + ph = 1 - ph; + } + w0(0); w2(4); + break; + case 1: + w0(0x91); w2(1); w0(0x10); w2(3); + w0(0x51); w2(5); w0(0xd1); + ph = 1; + for (k = 0; k < count; k++) { + w2(4 + ph); + a = r1(); b = r2(); + buf[k] = j53(a, b); + ph = 1 - ph; + } + w0(0); w2(4); + break; + case 2: + w0(0x89); w2(1); w2(0x23); w2(0x21); + ph = 1; + for (k = 0; k < count; k++) { + w2(0x24 + ph); + buf[k] = r0(); + ph = 1 - ph; + } + w2(6); w2(4); + break; + case 3: + if (count > 512) + WR(0x84, 3); w3(0); w2(0x24); - for (k=0;k 512) WR(0x84,3); + for (k = 0; k < count; k++) + buf[k] = r4(); + w2(4); WR(0x84, 0); + break; + case 4: + if (count > 512) + WR(0x84, 3); w3(0); w2(0x24); - for (k=0;k 512) WR(0x84,3); + for (k = 0; k < count / 2; k++) + ((u16 *)buf)[k] = r4w(); + w2(4); WR(0x84, 0); + break; + case 5: + if (count > 512) + WR(0x84, 3); w3(0); w2(0x24); - for (k=0;kmode) { - - case 0: - case 1: - case 2: w0(0xa1); w2(1); w2(3); w2(1); w2(5); - ph = 0; last = 0x8000; - for (k=0;kmode) { + case 0: + case 1: + case 2: + w0(0xa1); w2(1); w2(3); w2(1); w2(5); + ph = 0; last = 0x8000; + for (k = 0; k < count; k++) { + d = buf[k]; + if (d != last) { + last = d; + w0(d); + } + w2(4 + ph); + ph = 1 - ph; + } + w2(7); w2(4); + break; + case 3: + if (count < 512) + WR(0x84, 1); w3(0x40); - for (k=0;kdev, "epia: port 0x%x, mode %d, test=(%d,%d,%d)\n", - pi->port, pi->mode, e[0], e[1], f); - - return (e[0] && e[1]) || f; + pi->port, pi->mode, e[0], e[1], f); + return (e[0] && e[1]) || f; } static void epia_log_adapter(struct pi_adapter *pi) +{ + char *mode[6] = { "4-bit", "5/3", "8-bit", "EPP-8", "EPP-16", "EPP-32"}; -{ char *mode_string[6] = {"4-bit","5/3","8-bit", - "EPP-8","EPP-16","EPP-32"}; - - dev_info(&pi->dev, "Shuttle EPIA at 0x%x, mode %d (%s), delay %d\n", - pi->port, pi->mode, mode_string[pi->mode], pi->delay); + dev_info(&pi->dev, + "Shuttle EPIA at 0x%x, mode %d (%s), delay %d\n", + pi->port, pi->mode, mode[pi->mode], pi->delay); } static struct pi_protocol epia = { diff --git a/drivers/ata/pata_parport/fit2.c b/drivers/ata/pata_parport/fit2.c index fd3b2ce426a5fdb8cb873d12193f9834a3fad50d..6524f3033b1efa205329bbc2207dec42385207e5 100644 --- a/drivers/ata/pata_parport/fit2.c +++ b/drivers/ata/pata_parport/fit2.c @@ -1,17 +1,16 @@ -/* - fit2.c (c) 1998 Grant R. Guenther - Under the terms of the GNU General Public License. - - fit2.c is a low-level protocol driver for the older version - of the Fidelity International Technology parallel port adapter. - This adapter is used in their TransDisk 2000 and older TransDisk - 3000 portable hard-drives. As far as I can tell, this device - supports 4-bit mode _only_. - - Newer models of the FIT products use an enhanced protocol. - The "fit3" protocol module should support current drives. - -*/ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * (c) 1998 Grant R. Guenther + * + * fit2.c is a low-level protocol driver for the older version + * of the Fidelity International Technology parallel port adapter. + * This adapter is used in their TransDisk 2000 and older TransDisk + * 3000 portable hard-drives. As far as I can tell, this device + * supports 4-bit mode _only_. + * + * Newer models of the FIT products use an enhanced protocol. + * The "fit3" protocol module should support current drives. + */ #include #include @@ -22,99 +21,97 @@ #include #include "pata_parport.h" -#define j44(a,b) (((a>>4)&0x0f)|(b&0xf0)) - -/* cont = 0 - access the IDE register file - cont = 1 - access the IDE command set +#define j44(a, b) (((a >> 4) & 0x0f) | (b & 0xf0)) -NB: The FIT adapter does not appear to use the control registers. -So, we map ALT_STATUS to STATUS and NO-OP writes to the device -control register - this means that IDE reset will not work on these -devices. - -*/ +/* + * cont = 0 - access the IDE register file + * cont = 1 - access the IDE command set + * + * NB: The FIT adapter does not appear to use the control registers. + * So, we map ALT_STATUS to STATUS and NO-OP writes to the device + * control register - this means that IDE reset will not work on these + * devices. + */ static void fit2_write_regr(struct pi_adapter *pi, int cont, int regr, int val) - -{ if (cont == 1) return; +{ + if (cont == 1) + return; w2(0xc); w0(regr); w2(4); w0(val); w2(5); w0(0); w2(4); } static int fit2_read_regr(struct pi_adapter *pi, int cont, int regr) - -{ int a, b, r; +{ + int a, b, r; if (cont) { - if (regr != 6) return 0xff; - r = 7; - } else r = regr + 0x10; + if (regr != 6) + return 0xff; + r = 7; + } else { + r = regr + 0x10; + } - w2(0xc); w0(r); w2(4); w2(5); - w0(0); a = r1(); - w0(1); b = r1(); + w2(0xc); w0(r); w2(4); w2(5); + w0(0); a = r1(); + w0(1); b = r1(); w2(4); - return j44(a,b); - + return j44(a, b); } static void fit2_read_block(struct pi_adapter *pi, char *buf, int count) - -{ int k, a, b, c, d; +{ + int k, a, b, c, d; w2(0xc); w0(0x10); - for (k=0;ksaved_r0 = r0(); - pi->saved_r2 = r2(); - w2(0xcc); +{ + pi->saved_r0 = r0(); + pi->saved_r2 = r2(); + w2(0xcc); } static void fit2_disconnect(struct pi_adapter *pi) - -{ w0(pi->saved_r0); - w2(pi->saved_r2); -} +{ + w0(pi->saved_r0); + w2(pi->saved_r2); +} static void fit2_log_adapter(struct pi_adapter *pi) - { dev_info(&pi->dev, "FIT 2000 adapter at 0x%x, delay %d\n", - pi->port, pi->delay); + pi->port, pi->delay); } diff --git a/drivers/ata/pata_parport/fit3.c b/drivers/ata/pata_parport/fit3.c index 75df656ac472e57824968a39d3b9d86ef4f7cb43..c172a38ae67d464f9bc35efc274e7ab1711a51cf 100644 --- a/drivers/ata/pata_parport/fit3.c +++ b/drivers/ata/pata_parport/fit3.c @@ -1,21 +1,20 @@ -/* - fit3.c (c) 1998 Grant R. Guenther - Under the terms of the GNU General Public License. - - fit3.c is a low-level protocol driver for newer models - of the Fidelity International Technology parallel port adapter. - This adapter is used in their TransDisk 3000 portable - hard-drives, as well as CD-ROM, PD-CD and other devices. - - The TD-2000 and certain older devices use a different protocol. - Try the fit2 protocol module with them. - - NB: The FIT adapters do not appear to support the control - registers. So, we map ALT_STATUS to STATUS and NO-OP writes - to the device control register - this means that IDE reset - will not work on these devices. - -*/ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * (c) 1998 Grant R. Guenther + * + * fit3.c is a low-level protocol driver for newer models + * of the Fidelity International Technology parallel port adapter. + * This adapter is used in their TransDisk 3000 portable + * hard-drives, as well as CD-ROM, PD-CD and other devices. + * + * The TD-2000 and certain older devices use a different protocol. + * Try the fit2 protocol module with them. + * + * NB: The FIT adapters do not appear to support the control + * registers. So, we map ALT_STATUS to STATUS and NO-OP writes + * to the device control register - this means that IDE reset + * will not work on these devices. + */ #include #include @@ -26,152 +25,155 @@ #include #include "pata_parport.h" -#define j44(a,b) (((a>>3)&0x0f)|((b<<1)&0xf0)) - -#define w7(byte) {out_p(7,byte);} -#define r7() (in_p(7) & 0xff) +#define j44(a, b) (((a >> 3) & 0x0f) | ((b << 1) & 0xf0)) -/* cont = 0 - access the IDE register file - cont = 1 - access the IDE command set +#define w7(byte) out_p(7, byte) +#define r7() (in_p(7) & 0xff) -*/ +/* + * cont = 0 - access the IDE register file + * cont = 1 - access the IDE command set + */ static void fit3_write_regr(struct pi_adapter *pi, int cont, int regr, int val) - -{ if (cont == 1) return; +{ + if (cont == 1) + return; switch (pi->mode) { - case 0: - case 1: w2(0xc); w0(regr); w2(0x8); w2(0xc); - w0(val); w2(0xd); + case 1: + w2(0xc); w0(regr); w2(0x8); w2(0xc); + w0(val); w2(0xd); w0(0); w2(0xc); break; - - case 2: w2(0xc); w0(regr); w2(0x8); w2(0xc); + case 2: + w2(0xc); w0(regr); w2(0x8); w2(0xc); w4(val); w4(0); w2(0xc); break; - } } static int fit3_read_regr(struct pi_adapter *pi, int cont, int regr) - -{ int a, b; +{ + int a, b; if (cont) { - if (regr != 6) return 0xff; - regr = 7; - } + if (regr != 6) + return 0xff; + regr = 7; + } switch (pi->mode) { - - case 0: w2(0xc); w0(regr + 0x10); w2(0x8); w2(0xc); + case 0: + w2(0xc); w0(regr + 0x10); w2(0x8); w2(0xc); w2(0xd); a = r1(); - w2(0xf); b = r1(); + w2(0xf); b = r1(); w2(0xc); - return j44(a,b); - - case 1: w2(0xc); w0(regr + 0x90); w2(0x8); w2(0xc); - w2(0xec); w2(0xee); w2(0xef); a = r0(); + return j44(a, b); + case 1: + w2(0xc); w0(regr + 0x90); w2(0x8); w2(0xc); + w2(0xec); w2(0xee); w2(0xef); a = r0(); w2(0xc); return a; - - case 2: w2(0xc); w0(regr + 0x90); w2(0x8); w2(0xc); - w2(0xec); - a = r4(); b = r4(); + case 2: + w2(0xc); w0(regr + 0x90); w2(0x8); w2(0xc); + w2(0xec); + a = r4(); b = r4(); w2(0xc); return a; - } - return -1; + return -1; } static void fit3_read_block(struct pi_adapter *pi, char *buf, int count) - -{ int k, a, b, c, d; +{ + int k, a, b, c, d; switch (pi->mode) { - - case 0: w2(0xc); w0(0x10); w2(0x8); w2(0xc); - for (k=0;kmode) { - + switch (pi->mode) { case 0: - case 1: w2(0xc); w0(0); w2(0x8); w2(0xc); - for (k=0;ksaved_r0 = r0(); - pi->saved_r2 = r2(); +{ + pi->saved_r0 = r0(); + pi->saved_r2 = r2(); w2(0xc); w0(0); w2(0xa); - if (pi->mode == 2) { - w2(0xc); w0(0x9); w2(0x8); w2(0xc); - } + if (pi->mode == 2) { + w2(0xc); w0(0x9); + w2(0x8); w2(0xc); + } } static void fit3_disconnect(struct pi_adapter *pi) - -{ w2(0xc); w0(0xa); w2(0x8); w2(0xc); +{ + w2(0xc); w0(0xa); w2(0x8); w2(0xc); w0(pi->saved_r0); - w2(pi->saved_r2); -} + w2(pi->saved_r2); +} static void fit3_log_adapter(struct pi_adapter *pi) +{ + char *mode_string[3] = { "4-bit", "8-bit", "EPP"}; -{ char *mode_string[3] = {"4-bit","8-bit","EPP"}; - - dev_info(&pi->dev, "FIT 3000 adapter at 0x%x, mode %d (%s), delay %d\n", - pi->port, pi->mode, mode_string[pi->mode], pi->delay); + dev_info(&pi->dev, + "FIT 3000 adapter at 0x%x, mode %d (%s), delay %d\n", + pi->port, pi->mode, mode_string[pi->mode], pi->delay); } static struct pi_protocol fit3 = { diff --git a/drivers/ata/pata_parport/friq.c b/drivers/ata/pata_parport/friq.c index 1647264cd9a8dddff5ccf1d0e46c4fc3897a83b4..dc428f54fe0c33341ccb955ea7de8bfd0c24a7ba 100644 --- a/drivers/ata/pata_parport/friq.c +++ b/drivers/ata/pata_parport/friq.c @@ -1,24 +1,23 @@ -/* - friq.c (c) 1998 Grant R. Guenther - Under the terms of the GNU General Public License - - friq.c is a low-level protocol driver for the Freecom "IQ" - parallel port IDE adapter. Early versions of this adapter - use the 'frpw' protocol. - - Freecom uses this adapter in a battery powered external - CD-ROM drive. It is also used in LS-120 drives by - Maxell and Panasonic, and other devices. - - The battery powered drive requires software support to - control the power to the drive. This module enables the - drive power when the high level driver (pcd) is loaded - and disables it when the module is unloaded. Note, if - the friq module is built in to the kernel, the power - will never be switched off, so other means should be - used to conserve battery power. - -*/ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * (c) 1998 Grant R. Guenther + * + * friq.c is a low-level protocol driver for the Freecom "IQ" + * parallel port IDE adapter. Early versions of this adapter + * use the 'frpw' protocol. + * + * Freecom uses this adapter in a battery powered external + * CD-ROM drive. It is also used in LS-120 drives by + * Maxell and Panasonic, and other devices. + * + * The battery powered drive requires software support to + * control the power to the drive. This module enables the + * drive power when the high level driver (pcd) is loaded + * and disables it when the module is unloaded. Note, if + * the friq module is built in to the kernel, the power + * will never be switched off, so other means should be + * used to conserve battery power. + */ #include #include @@ -29,197 +28,206 @@ #include #include "pata_parport.h" -#define CMD(x) w2(4);w0(0xff);w0(0xff);w0(0x73);w0(0x73);\ - w0(0xc9);w0(0xc9);w0(0x26);w0(0x26);w0(x);w0(x); +#define CMD(x) \ + do { \ + w2(4); w0(0xff); w0(0xff); w0(0x73); w0(0x73); \ + w0(0xc9); w0(0xc9); w0(0x26); \ + w0(0x26); w0(x); w0(x); \ + } while (0) -#define j44(l,h) (((l>>4)&0x0f)|(h&0xf0)) +#define j44(l, h) (((l >> 4) & 0x0f) | (h & 0xf0)) -/* cont = 0 - access the IDE register file - cont = 1 - access the IDE command set -*/ - -static int cont_map[2] = { 0x08, 0x10 }; +/* + * cont = 0 - access the IDE register file + * cont = 1 - access the IDE command set + */ +static int cont_map[2] = { 0x08, 0x10 }; static int friq_read_regr(struct pi_adapter *pi, int cont, int regr) - -{ int h,l,r; +{ + int h, l, r; r = regr + cont_map[cont]; CMD(r); w2(6); l = r1(); w2(4); h = r1(); - w2(4); - - return j44(l,h); + w2(4); + return j44(l, h); } static void friq_write_regr(struct pi_adapter *pi, int cont, int regr, int val) - -{ int r; - - r = regr + cont_map[cont]; +{ + int r = regr + cont_map[cont]; CMD(r); w0(val); - w2(5);w2(7);w2(5);w2(4); + w2(5); w2(7); w2(5); w2(4); } static void friq_read_block_int(struct pi_adapter *pi, char *buf, int count, int regr) +{ + int h, l, k, ph; -{ int h, l, k, ph; - - switch(pi->mode) { - - case 0: CMD(regr); - for (k=0;kmode) { + case 0: + CMD(regr); + for (k = 0; k < count; k++) { + w2(6); l = r1(); + w2(4); h = r1(); + buf[k] = j44(l, h); + } + w2(4); + break; + case 1: + ph = 2; + CMD(regr + 0xc0); + w0(0xff); + for (k = 0; k < count; k++) { + w2(0xa4 + ph); + buf[k] = r0(); + ph = 2 - ph; + } + w2(0xac); w2(0xa4); w2(4); + break; + case 2: + CMD(regr + 0x80); + for (k = 0; k < count - 2; k++) + buf[k] = r4(); w2(0xac); w2(0xa4); - buf[count-2] = r4(); - buf[count-1] = r4(); + buf[count - 2] = r4(); + buf[count - 1] = r4(); w2(4); break; - - case 3: CMD(regr+0x80); - for (k=0;k<(count/2)-1;k++) ((u16 *)buf)[k] = r4w(); - w2(0xac); w2(0xa4); - buf[count-2] = r4(); - buf[count-1] = r4(); - w2(4); - break; - - case 4: CMD(regr+0x80); - for (k=0;k<(count/4)-1;k++) ((u32 *)buf)[k] = r4l(); - buf[count-4] = r4(); - buf[count-3] = r4(); - w2(0xac); w2(0xa4); - buf[count-2] = r4(); - buf[count-1] = r4(); - w2(4); - break; - - } + case 3: + CMD(regr + 0x80); + for (k = 0; k < count / 2 - 1; k++) + ((u16 *)buf)[k] = r4w(); + w2(0xac); w2(0xa4); + buf[count - 2] = r4(); + buf[count - 1] = r4(); + w2(4); + break; + case 4: + CMD(regr + 0x80); + for (k = 0; k < count / 4 - 1; k++) + ((u32 *)buf)[k] = r4l(); + buf[count - 4] = r4(); + buf[count - 3] = r4(); + w2(0xac); w2(0xa4); + buf[count - 2] = r4(); + buf[count - 1] = r4(); + w2(4); + break; + } } static void friq_read_block(struct pi_adapter *pi, char *buf, int count) - -{ friq_read_block_int(pi,buf,count,0x08); +{ + friq_read_block_int(pi, buf, count, 0x08); } static void friq_write_block(struct pi_adapter *pi, char *buf, int count) - -{ int k; - - switch(pi->mode) { +{ + int k; + switch (pi->mode) { case 0: - case 1: CMD(8); w2(5); - for (k=0;ksaved_r0 = r0(); - pi->saved_r2 = r2(); +{ + pi->saved_r0 = r0(); + pi->saved_r2 = r2(); w2(4); } static void friq_disconnect(struct pi_adapter *pi) - -{ CMD(0x20); +{ + CMD(0x20); w0(pi->saved_r0); - w2(pi->saved_r2); -} + w2(pi->saved_r2); +} static int friq_test_proto(struct pi_adapter *pi) - -{ int j, k, r; - int e[2] = {0,0}; +{ + int j, k, r; + int e[2] = { 0, 0 }; char scratch[512]; - pi->saved_r0 = r0(); + pi->saved_r0 = r0(); w0(0xff); udelay(20); CMD(0x3d); /* turn the power on */ udelay(500); w0(pi->saved_r0); friq_connect(pi); - for (j=0;j<2;j++) { - friq_write_regr(pi,0,6,0xa0+j*0x10); - for (k=0;k<256;k++) { - friq_write_regr(pi,0,2,k^0xaa); - friq_write_regr(pi,0,3,k^0x55); - if (friq_read_regr(pi,0,2) != (k^0xaa)) e[j]++; - } - } + for (j = 0; j < 2; j++) { + friq_write_regr(pi, 0, 6, 0xa0 + j * 0x10); + for (k = 0; k < 256; k++) { + friq_write_regr(pi, 0, 2, k ^ 0xaa); + friq_write_regr(pi, 0, 3, k ^ 0x55); + if (friq_read_regr(pi, 0, 2) != (k ^ 0xaa)) + e[j]++; + } + } friq_disconnect(pi); friq_connect(pi); - friq_read_block_int(pi,scratch,512,0x10); - r = 0; - for (k=0;k<128;k++) if (scratch[k] != k) r++; + friq_read_block_int(pi, scratch, 512, 0x10); + r = 0; + for (k = 0; k < 128; k++) { + if (scratch[k] != k) + r++; + } friq_disconnect(pi); - dev_dbg(&pi->dev, "friq: port 0x%x, mode %d, test=(%d,%d,%d)\n", - pi->port, pi->mode, e[0], e[1], r); + dev_dbg(&pi->dev, + "friq: port 0x%x, mode %d, test=(%d,%d,%d)\n", + pi->port, pi->mode, e[0], e[1], r); - return (r || (e[0] && e[1])); + return r || (e[0] && e[1]); } - static void friq_log_adapter(struct pi_adapter *pi) +{ + char *mode_string[6] = { "4-bit", "8-bit", "EPP-8", "EPP-16", "EPP-32"}; -{ char *mode_string[6] = {"4-bit","8-bit", - "EPP-8","EPP-16","EPP-32"}; - - dev_info(&pi->dev, "Freecom IQ ASIC-2 adapter at 0x%x, mode %d (%s), delay %d\n", - pi->port, pi->mode, mode_string[pi->mode], pi->delay); + dev_info(&pi->dev, + "Freecom IQ ASIC-2 adapter at 0x%x, mode %d (%s), delay %d\n", + pi->port, pi->mode, mode_string[pi->mode], pi->delay); pi->private = 1; friq_connect(pi); CMD(0x9e); /* disable sleep timer */ friq_disconnect(pi); - } static void friq_release_proto(struct pi_adapter *pi) diff --git a/drivers/ata/pata_parport/frpw.c b/drivers/ata/pata_parport/frpw.c index 3ec0abf16fa6f5eb1120c3bc8376a510506e892e..28d9bb2c6baff7057254799c6366007f1839e962 100644 --- a/drivers/ata/pata_parport/frpw.c +++ b/drivers/ata/pata_parport/frpw.c @@ -1,17 +1,15 @@ -/* - frpw.c (c) 1996-8 Grant R. Guenther - Under the terms of the GNU General Public License - - frpw.c is a low-level protocol driver for the Freecom "Power" - parallel port IDE adapter. - - Some applications of this adapter may require a "printer" reset - prior to loading the driver. This can be done by loading and - unloading the "lp" driver, or it can be done by this driver - if you define FRPW_HARD_RESET. The latter is not recommended - as it may upset devices on other ports. - -*/ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * (c) 1996-1998 Grant R. Guenther + * + * frpw.c is a low-level protocol driver for the Freecom "Power" parallel port + * IDE adapter. + * + * Some applications of this adapter may require a "printer" reset prior to + * loading the driver. This can be done by loading and unloading the "lp" + * driver, or it can be done by this driver if you define FRPW_HARD_RESET. + * The latter is not recommended as it may upset devices on other ports. + */ #include #include @@ -25,15 +23,15 @@ #define cec4 w2(0xc);w2(0xe);w2(0xe);w2(0xc);w2(4);w2(4);w2(4); #define j44(l,h) (((l>>4)&0x0f)|(h&0xf0)) -/* cont = 0 - access the IDE register file - cont = 1 - access the IDE command set -*/ - +/* + * cont = 0 - access the IDE register file + * cont = 1 - access the IDE command set + */ static int cont_map[2] = { 0x08, 0x10 }; static int frpw_read_regr(struct pi_adapter *pi, int cont, int regr) - -{ int h,l,r; +{ + int h, l, r; r = regr + cont_map[cont]; @@ -41,145 +39,156 @@ static int frpw_read_regr(struct pi_adapter *pi, int cont, int regr) w0(r); cec4; w2(6); l = r1(); w2(4); h = r1(); - w2(4); - - return j44(l,h); + w2(4); + return j44(l, h); } static void frpw_write_regr(struct pi_adapter *pi, int cont, int regr, int val) +{ + int r = regr + cont_map[cont]; -{ int r; - - r = regr + cont_map[cont]; - - w2(4); w0(r); cec4; + w2(4); w0(r); cec4; w0(val); - w2(5);w2(7);w2(5);w2(4); + w2(5); w2(7); w2(5); w2(4); } -static void frpw_read_block_int(struct pi_adapter *pi, char *buf, int count, int regr) - -{ int h, l, k, ph; - - switch(pi->mode) { - - case 0: w2(4); w0(regr); cec4; - for (k=0;kmode) { + case 0: + w2(4); w0(regr); cec4; + for (k = 0; k < count; k++) { + w2(6); l = r1(); + w2(4); h = r1(); + buf[k] = j44(l, h); + } + w2(4); + break; + + case 1: + ph = 2; + w2(4); w0(regr + 0xc0); cec4; + w0(0xff); + for (k = 0; k < count; k++) { + w2(0xa4 + ph); + buf[k] = r0(); + ph = 2 - ph; + } + w2(0xac); w2(0xa4); w2(4); + break; + + case 2: + w2(4); w0(regr + 0x80); cec4; + for (k = 0; k < count; k++) + buf[k] = r4(); w2(0xac); w2(0xa4); - buf[count-2] = r4(); - buf[count-1] = r4(); w2(4); break; - case 4: w2(4); w0(regr + 0x80); cec4; - for (k=0;k<(count/2)-1;k++) ((u16 *)buf)[k] = r4w(); - w2(0xac); w2(0xa4); - buf[count-2] = r4(); - buf[count-1] = r4(); - w2(4); - break; - - case 5: w2(4); w0(regr + 0x80); cec4; - for (k=0;k<(count/4)-1;k++) ((u32 *)buf)[k] = r4l(); - buf[count-4] = r4(); - buf[count-3] = r4(); - w2(0xac); w2(0xa4); - buf[count-2] = r4(); - buf[count-1] = r4(); - w2(4); - break; + case 3: + w2(4); w0(regr + 0x80); cec4; + for (k = 0; k < count - 2; k++) + buf[k] = r4(); + w2(0xac); w2(0xa4); + buf[count - 2] = r4(); + buf[count - 1] = r4(); + w2(4); + break; + + case 4: + w2(4); w0(regr + 0x80); cec4; + for (k = 0; k < count / 2 - 1; k++) + ((u16 *)buf)[k] = r4w(); + w2(0xac); w2(0xa4); + buf[count - 2] = r4(); + buf[count - 1] = r4(); + w2(4); + break; + case 5: + w2(4); w0(regr + 0x80); cec4; + for (k = 0; k < count / 4 - 1; k++) + ((u32 *)buf)[k] = r4l(); + buf[count - 4] = r4(); + buf[count - 3] = r4(); + w2(0xac); w2(0xa4); + buf[count - 2] = r4(); + buf[count - 1] = r4(); + w2(4); + break; } } static void frpw_read_block(struct pi_adapter *pi, char *buf, int count) - -{ frpw_read_block_int(pi,buf,count,0x08); +{ + frpw_read_block_int(pi, buf, count, 0x08); } static void frpw_write_block(struct pi_adapter *pi, char *buf, int count) - -{ int k; - - switch(pi->mode) { +{ + int k; + switch (pi->mode) { case 0: case 1: - case 2: w2(4); w0(8); cec4; w2(5); - for (k=0;ksaved_r0 = r0(); - pi->saved_r2 = r2(); +{ + pi->saved_r0 = r0(); + pi->saved_r2 = r2(); w2(4); } static void frpw_disconnect(struct pi_adapter *pi) - -{ w2(4); w0(0x20); cec4; +{ + w2(4); w0(0x20); cec4; w0(pi->saved_r0); - w2(pi->saved_r2); -} - -/* Stub logic to see if PNP string is available - used to distinguish - between the Xilinx and ASIC implementations of the Freecom adapter. -*/ + w2(pi->saved_r2); +} +/* + * Stub logic to see if PNP string is available - used to distinguish + * between the Xilinx and ASIC implementations of the Freecom adapter. + * returns chip_type: 0 = Xilinx, 1 = ASIC + */ static int frpw_test_pnp(struct pi_adapter *pi) - -/* returns chip_type: 0 = Xilinx, 1 = ASIC */ - -{ int olddelay, a, b; +{ + int olddelay, a, b; #ifdef FRPW_HARD_RESET w0(0); w2(8); udelay(50); w2(0xc); /* parallel bus reset */ @@ -191,7 +200,7 @@ static int frpw_test_pnp(struct pi_adapter *pi) pi->saved_r0 = r0(); pi->saved_r2 = r2(); - + w2(4); w0(4); w2(6); w2(7); a = r1() & 0xff; w2(4); b = r1() & 0xff; w2(0xc); w2(0xe); w2(4); @@ -200,65 +209,70 @@ static int frpw_test_pnp(struct pi_adapter *pi) w0(pi->saved_r0); w2(pi->saved_r2); - return ((~a&0x40) && (b&0x40)); -} - -/* We use the pi->private to remember the result of the PNP test. - To make this work, private = port*2 + chip. Yes, I know it's - a hack :-( -*/ + return ((~a & 0x40) && (b & 0x40)); +} +/* + * We use the pi->private to remember the result of the PNP test. + * To make this work, private = port*2 + chip. Yes, I know it's a hack :-( + */ static int frpw_test_proto(struct pi_adapter *pi) - -{ int j, k, r; - int e[2] = {0,0}; +{ + int j, k, r; + int e[2] = { 0, 0 }; char scratch[512]; - if ((pi->private>>1) != pi->port) - pi->private = frpw_test_pnp(pi) + 2*pi->port; + if ((pi->private >> 1) != pi->port) + pi->private = frpw_test_pnp(pi) + 2*pi->port; - if (((pi->private%2) == 0) && (pi->mode > 2)) { - dev_dbg(&pi->dev, "frpw: Xilinx does not support mode %d\n", pi->mode); - return 1; + if (((pi->private & 0x1) == 0) && (pi->mode > 2)) { + dev_dbg(&pi->dev, + "frpw: Xilinx does not support mode %d\n", pi->mode); + return 1; } - if (((pi->private%2) == 1) && (pi->mode == 2)) { + if (((pi->private & 0x1) == 1) && (pi->mode == 2)) { dev_dbg(&pi->dev, "frpw: ASIC does not support mode 2\n"); - return 1; + return 1; } frpw_connect(pi); - for (j=0;j<2;j++) { - frpw_write_regr(pi,0,6,0xa0+j*0x10); - for (k=0;k<256;k++) { - frpw_write_regr(pi,0,2,k^0xaa); - frpw_write_regr(pi,0,3,k^0x55); - if (frpw_read_regr(pi,0,2) != (k^0xaa)) e[j]++; - } - } + for (j = 0; j < 2; j++) { + frpw_write_regr(pi, 0, 6, 0xa0 + j * 0x10); + for (k = 0; k < 256; k++) { + frpw_write_regr(pi, 0, 2, k ^ 0xaa); + frpw_write_regr(pi, 0, 3, k ^ 0x55); + if (frpw_read_regr(pi, 0, 2) != (k ^ 0xaa)) + e[j]++; + } + } frpw_disconnect(pi); frpw_connect(pi); - frpw_read_block_int(pi,scratch,512,0x10); - r = 0; - for (k=0;k<128;k++) if (scratch[k] != k) r++; + frpw_read_block_int(pi, scratch, 512, 0x10); + r = 0; + for (k = 0; k < 128; k++) { + if (scratch[k] != k) + r++; + } frpw_disconnect(pi); - dev_dbg(&pi->dev, "frpw: port 0x%x, chip %ld, mode %d, test=(%d,%d,%d)\n", - pi->port, (pi->private%2), pi->mode, e[0], e[1], r); + dev_dbg(&pi->dev, + "frpw: port 0x%x, chip %ld, mode %d, test=(%d,%d,%d)\n", + pi->port, (pi->private%2), pi->mode, e[0], e[1], r); - return (r || (e[0] && e[1])); + return r || (e[0] && e[1]); } - static void frpw_log_adapter(struct pi_adapter *pi) -{ char *mode_string[6] = {"4-bit","8-bit","EPP", - "EPP-8","EPP-16","EPP-32"}; +{ + char *mode[6] = { "4-bit", "8-bit", "EPP", "EPP-8", "EPP-16", "EPP-32"}; - dev_info(&pi->dev, "Freecom (%s) adapter at 0x%x, mode %d (%s), delay %d\n", - ((pi->private % 2) == 0) ? "Xilinx" : "ASIC", - pi->port, pi->mode, mode_string[pi->mode], pi->delay); + dev_info(&pi->dev, + "Freecom (%s) adapter at 0x%x, mode %d (%s), delay %d\n", + ((pi->private & 0x1) == 0) ? "Xilinx" : "ASIC", + pi->port, pi->mode, mode[pi->mode], pi->delay); } static struct pi_protocol frpw = { diff --git a/drivers/ata/pata_parport/kbic.c b/drivers/ata/pata_parport/kbic.c index 8213e62f8f00774efe338253ba368356c96f719e..6023e071516d4caa6a87c2a2570beefe2dae897a 100644 --- a/drivers/ata/pata_parport/kbic.c +++ b/drivers/ata/pata_parport/kbic.c @@ -1,16 +1,15 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* - kbic.c (c) 1997-8 Grant R. Guenther - Under the terms of the GNU General Public License. - - This is a low-level driver for the KBIC-951A and KBIC-971A - parallel to IDE adapter chips from KingByte Information Systems. - - The chips are almost identical, however, the wakeup code - required for the 971A interferes with the correct operation of - the 951A, so this driver registers itself twice, once for - each chip. - -*/ + * (c) 1997-1998 Grant R. Guenther + * + * This is a low-level driver for the KBIC-951A and KBIC-971A + * parallel to IDE adapter chips from KingByte Information Systems. + * + * The chips are almost identical, however, the wakeup code + * required for the 971A interferes with the correct operation of + * the 951A, so this driver registers itself twice, once for + * each chip. + */ #include #include @@ -21,212 +20,223 @@ #include #include "pata_parport.h" -#define r12w() (delay_p,inw(pi->port+1)&0xffff) +#define r12w() (delay_p, inw(pi->port + 1) & 0xffff) -#define j44(a,b) ((((a>>4)&0x0f)|(b&0xf0))^0x88) -#define j53(w) (((w>>3)&0x1f)|((w>>4)&0xe0)) +#define j44(a, b) ((((a >> 4) & 0x0f) | (b & 0xf0)) ^ 0x88) +#define j53(w) (((w >> 3) & 0x1f) | ((w >> 4) & 0xe0)) -/* cont = 0 - access the IDE register file - cont = 1 - access the IDE command set -*/ - -static int cont_map[2] = { 0x80, 0x40 }; +/* + * cont = 0 - access the IDE register file + * cont = 1 - access the IDE command set + */ +static int cont_map[2] = { 0x80, 0x40 }; static int kbic_read_regr(struct pi_adapter *pi, int cont, int regr) +{ + int a, b, s; -{ int a, b, s; - - s = cont_map[cont]; + s = cont_map[cont]; switch (pi->mode) { - - case 0: w0(regr|0x18|s); w2(4); w2(6); w2(4); w2(1); w0(8); - a = r1(); w0(0x28); b = r1(); w2(4); - return j44(a,b); - - case 1: w0(regr|0x38|s); w2(4); w2(6); w2(4); w2(5); w0(8); + case 0: + w0(regr | 0x18 | s); w2(4); w2(6); w2(4); w2(1); w0(8); + a = r1(); w0(0x28); b = r1(); w2(4); + return j44(a, b); + case 1: + w0(regr|0x38 | s); w2(4); w2(6); w2(4); w2(5); w0(8); a = r12w(); w2(4); return j53(a); - - case 2: w0(regr|0x08|s); w2(4); w2(6); w2(4); w2(0xa5); w2(0xa1); + case 2: + w0(regr | 0x08 | s); w2(4); w2(6); w2(4); w2(0xa5); w2(0xa1); a = r0(); w2(4); - return a; - + return a; case 3: case 4: - case 5: w0(0x20|s); w2(4); w2(6); w2(4); w3(regr); + case 5: + w0(0x20 | s); w2(4); w2(6); w2(4); w3(regr); a = r4(); b = r4(); w2(4); w2(0); w2(4); return a; - } + return -1; -} +} static void kbic_write_regr(struct pi_adapter *pi, int cont, int regr, int val) +{ + int s = cont_map[cont]; -{ int s; - - s = cont_map[cont]; - - switch (pi->mode) { - - case 0: - case 1: - case 2: w0(regr|0x10|s); w2(4); w2(6); w2(4); + switch (pi->mode) { + case 0: + case 1: + case 2: + w0(regr | 0x10 | s); w2(4); w2(6); w2(4); w0(val); w2(5); w2(4); break; - case 3: case 4: - case 5: w0(0x20|s); w2(4); w2(6); w2(4); w3(regr); + case 5: + w0(0x20 | s); w2(4); w2(6); w2(4); w3(regr); w4(val); w4(val); w2(4); w2(0); w2(4); - break; - + break; } } static void k951_connect(struct pi_adapter *pi) - -{ pi->saved_r0 = r0(); - pi->saved_r2 = r2(); - w2(4); +{ + pi->saved_r0 = r0(); + pi->saved_r2 = r2(); + w2(4); } static void k951_disconnect(struct pi_adapter *pi) - -{ w0(pi->saved_r0); - w2(pi->saved_r2); +{ + w0(pi->saved_r0); + w2(pi->saved_r2); } -#define CCP(x) w2(0xc4);w0(0xaa);w0(0x55);w0(0);w0(0xff);w0(0x87);\ - w0(0x78);w0(x);w2(0xc5);w2(0xc4);w0(0xff); +#define CCP(x) \ + do { \ + w2(0xc4); w0(0xaa); w0(0x55); \ + w0(0); w0(0xff); w0(0x87); \ + w0(0x78); w0(x); w2(0xc5); \ + w2(0xc4); w0(0xff); \ + } while (0) static void k971_connect(struct pi_adapter *pi) - -{ pi->saved_r0 = r0(); - pi->saved_r2 = r2(); +{ + pi->saved_r0 = r0(); + pi->saved_r2 = r2(); CCP(0x20); - w2(4); + w2(4); } static void k971_disconnect(struct pi_adapter *pi) - -{ CCP(0x30); +{ + CCP(0x30); w0(pi->saved_r0); - w2(pi->saved_r2); + w2(pi->saved_r2); } -/* counts must be congruent to 0 MOD 4, but all known applications - have this property. -*/ - +/* + * count must be congruent to 0 MOD 4, but all known applications + *have this property. + */ static void kbic_read_block(struct pi_adapter *pi, char *buf, int count) +{ + int k, a, b; -{ int k, a, b; - - switch (pi->mode) { - - case 0: w0(0x98); w2(4); w2(6); w2(4); - for (k=0;kmode) { + case 0: + w0(0x98); w2(4); w2(6); w2(4); + for (k = 0; k < count / 2; k++) { + w2(1); w0(8); + a = r1(); + w0(0x28); + b = r1(); + buf[2 * k] = j44(a, b); + w2(5); + b = r1(); + w0(8); + a = r1(); + buf[2 * k + 1] = j44(a, b); w2(4); - } - break; - - case 1: w0(0xb8); w2(4); w2(6); w2(4); - for (k=0;kmode) { - - case 0: - case 1: - case 2: w0(0x90); w2(4); w2(6); w2(4); - for(k=0;kmode) { + case 0: + case 1: + case 2: + w0(0x90); w2(4); w2(6); w2(4); + for (k = 0; k < count / 2; k++) { + w0(buf[2 * k + 1]); + w2(0); w2(4); + w0(buf[2 * k]); + w2(5); w2(4); } break; - - case 3: w0(0xa0); w2(4); w2(6); w2(4); w3(0); - for(k=0;kdev, "KingByte %s at 0x%x, mode %d (%s), delay %d\n", - chip, pi->port, pi->mode, mode_string[pi->mode], pi->delay); + chip, pi->port, pi->mode, mode[pi->mode], pi->delay); } static void k951_log_adapter(struct pi_adapter *pi) diff --git a/drivers/ata/pata_parport/ktti.c b/drivers/ata/pata_parport/ktti.c index 4890b1f1234872c10b04987cf16de2758f8784f7..bca6c20ef617cac331939434fea2cc697be39c4f 100644 --- a/drivers/ata/pata_parport/ktti.c +++ b/drivers/ata/pata_parport/ktti.c @@ -1,12 +1,11 @@ -/* - ktti.c (c) 1998 Grant R. Guenther - Under the terms of the GNU General Public License. - - ktti.c is a low-level protocol driver for the KT Technology - parallel port adapter. This adapter is used in the "PHd" - portable hard-drives. As far as I can tell, this device - supports 4-bit mode _only_. - +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * (c) 1998 Grant R. Guenther + * + * ktti.c is a low-level protocol driver for the KT Technology + * parallel port adapter. This adapter is used in the "PHd" + * portable hard-drives. As far as I can tell, this device + * supports 4-bit mode _only_. */ #include @@ -18,80 +17,76 @@ #include #include "pata_parport.h" -#define j44(a,b) (((a>>4)&0x0f)|(b&0xf0)) +#define j44(a, b) (((a >> 4) & 0x0f) | (b & 0xf0)) -/* cont = 0 - access the IDE register file - cont = 1 - access the IDE command set -*/ - -static int cont_map[2] = { 0x10, 0x08 }; +/* + * cont = 0 - access the IDE register file + * cont = 1 - access the IDE command set + */ +static int cont_map[2] = { 0x10, 0x08 }; static void ktti_write_regr(struct pi_adapter *pi, int cont, int regr, int val) +{ + int r = regr + cont_map[cont]; -{ int r; - - r = regr + cont_map[cont]; - - w0(r); w2(0xb); w2(0xa); w2(3); w2(6); + w0(r); w2(0xb); w2(0xa); w2(3); w2(6); w0(val); w2(3); w0(0); w2(6); w2(0xb); } static int ktti_read_regr(struct pi_adapter *pi, int cont, int regr) - -{ int a, b, r; +{ + int a, b, r; r = regr + cont_map[cont]; - w0(r); w2(0xb); w2(0xa); w2(9); w2(0xc); w2(9); + w0(r); w2(0xb); w2(0xa); w2(9); w2(0xc); w2(9); a = r1(); w2(0xc); b = r1(); w2(9); w2(0xc); w2(9); - return j44(a,b); - + return j44(a, b); } static void ktti_read_block(struct pi_adapter *pi, char *buf, int count) +{ + int k, a, b; -{ int k, a, b; - - for (k=0;ksaved_r0 = r0(); - pi->saved_r2 = r2(); - w2(0xb); w2(0xa); w0(0); w2(3); w2(6); +{ + pi->saved_r0 = r0(); + pi->saved_r2 = r2(); + w2(0xb); w2(0xa); w0(0); w2(3); w2(6); } static void ktti_disconnect(struct pi_adapter *pi) - -{ w2(0xb); w2(0xa); w0(0xa0); w2(3); w2(4); +{ + w2(0xb); w2(0xa); w0(0xa0); w2(3); w2(4); w0(pi->saved_r0); - w2(pi->saved_r2); -} + w2(pi->saved_r2); +} static void ktti_log_adapter(struct pi_adapter *pi) - { dev_info(&pi->dev, "KT adapter at 0x%x, delay %d\n", - pi->port, pi->delay); + pi->port, pi->delay); } static struct pi_protocol ktti = { diff --git a/drivers/ata/pata_parport/on20.c b/drivers/ata/pata_parport/on20.c index 276ace12d490805fd16b33a1b0203116987ef532..34e69da2bec87291b3609b2e3b7133b498deac23 100644 --- a/drivers/ata/pata_parport/on20.c +++ b/drivers/ata/pata_parport/on20.c @@ -1,10 +1,10 @@ -/* - on20.c (c) 1996-8 Grant R. Guenther - Under the terms of the GNU General Public License. - - on20.c is a low-level protocol driver for the - Onspec 90c20 parallel to IDE adapter. -*/ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * (c) 1996-1998 Grant R. Guenther + * + * on20.c is a low-level protocol driver for the + * Onspec 90c20 parallel to IDE adapter. + */ #include #include @@ -15,99 +15,114 @@ #include #include "pata_parport.h" -#define op(f) w2(4);w0(f);w2(5);w2(0xd);w2(5);w2(0xd);w2(5);w2(4); -#define vl(v) w2(4);w0(v);w2(5);w2(7);w2(5);w2(4); - -#define j44(a,b) (((a>>4)&0x0f)|(b&0xf0)) - -/* cont = 0 - access the IDE register file - cont = 1 - access the IDE command set -*/ - -static int on20_read_regr(struct pi_adapter *pi, int cont, int regr) - -{ int h,l, r ; +#define op(f) \ + do { \ + w2(4); w0(f); w2(5); w2(0xd); \ + w2(5); w2(0xd); w2(5); w2(4); \ + } while (0) - r = (regr<<2) + 1 + cont; +#define vl(v) \ + do { \ + w2(4); w0(v); w2(5); \ + w2(7); w2(5); w2(4); \ + } while (0) - op(1); vl(r); op(0); +#define j44(a, b) (((a >> 4) & 0x0f) | (b & 0xf0)) - switch (pi->mode) { - - case 0: w2(4); w2(6); l = r1(); - w2(4); w2(6); h = r1(); - w2(4); w2(6); w2(4); w2(6); w2(4); - return j44(l,h); - - case 1: w2(4); w2(0x26); r = r0(); - w2(4); w2(0x26); w2(4); - return r; +/* + * cont = 0 - access the IDE register file + * cont = 1 - access the IDE command set + */ +static int on20_read_regr(struct pi_adapter *pi, int cont, int regr) +{ + int h, l, r; + + r = (regr << 2) + 1 + cont; + + op(1); vl(r); op(0); + + switch (pi->mode) { + case 0: + w2(4); w2(6); l = r1(); + w2(4); w2(6); h = r1(); + w2(4); w2(6); w2(4); w2(6); w2(4); + return j44(l, h); + case 1: + w2(4); w2(0x26); r = r0(); + w2(4); w2(0x26); w2(4); + return r; } + return -1; -} +} static void on20_write_regr(struct pi_adapter *pi, int cont, int regr, int val) +{ + int r = (regr << 2) + 1 + cont; -{ int r; - - r = (regr<<2) + 1 + cont; - - op(1); vl(r); - op(0); vl(val); + op(1); vl(r); + op(0); vl(val); op(0); vl(val); } static void on20_connect(struct pi_adapter *pi) - -{ pi->saved_r0 = r0(); - pi->saved_r2 = r2(); - - w2(4);w0(0);w2(0xc);w2(4);w2(6);w2(4);w2(6);w2(4); - if (pi->mode) { op(2); vl(8); op(2); vl(9); } - else { op(2); vl(0); op(2); vl(8); } +{ + pi->saved_r0 = r0(); + pi->saved_r2 = r2(); + + w2(4); w0(0); w2(0xc); w2(4); w2(6); w2(4); w2(6); w2(4); + if (pi->mode) { + op(2); vl(8); op(2); vl(9); + } else { + op(2); vl(0); op(2); vl(8); + } } static void on20_disconnect(struct pi_adapter *pi) - -{ w2(4);w0(7);w2(4);w2(0xc);w2(4); - w0(pi->saved_r0); - w2(pi->saved_r2); -} +{ + w2(4); w0(7); w2(4); w2(0xc); w2(4); + w0(pi->saved_r0); + w2(pi->saved_r2); +} static void on20_read_block(struct pi_adapter *pi, char *buf, int count) - -{ int k, l, h; +{ + int k, l, h; op(1); vl(1); op(0); - for (k=0;kmode) { - w2(4); w2(0x26); buf[k] = r0(); - } else { - w2(6); l = r1(); w2(4); - w2(6); h = r1(); w2(4); - buf[k] = j44(l,h); - } + for (k = 0; k < count; k++) { + if (pi->mode) { + w2(4); w2(0x26); buf[k] = r0(); + } else { + w2(6); l = r1(); w2(4); + w2(6); h = r1(); w2(4); + buf[k] = j44(l, h); + } + } w2(4); } static void on20_write_block(struct pi_adapter *pi, char *buf, int count) - -{ int k; +{ + int k; op(1); vl(1); op(0); - for (k=0;kdev, "OnSpec 90c20 at 0x%x, mode %d (%s), delay %d\n", - pi->port, pi->mode, mode_string[pi->mode], pi->delay); + dev_info(&pi->dev, + "OnSpec 90c20 at 0x%x, mode %d (%s), delay %d\n", + pi->port, pi->mode, mode_string[pi->mode], pi->delay); } static struct pi_protocol on20 = { diff --git a/drivers/ata/pata_parport/on26.c b/drivers/ata/pata_parport/on26.c index dc47a54b121ff7fe66afc6a073ef300dfdb6b997..5da317b394c18ec256d7a2fa6a6765be567c33d7 100644 --- a/drivers/ata/pata_parport/on26.c +++ b/drivers/ata/pata_parport/on26.c @@ -1,11 +1,10 @@ -/* - on26.c (c) 1997-8 Grant R. Guenther - Under the terms of the GNU General Public License. - - on26.c is a low-level protocol driver for the - OnSpec 90c26 parallel to IDE adapter chip. - -*/ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * (c) 1997-1998 Grant R. Guenther + * + * on26.c is a low-level protocol driver for the + * OnSpec 90c26 parallel to IDE adapter chip. + */ #include #include @@ -16,260 +15,281 @@ #include #include "pata_parport.h" -/* mode codes: 0 nybble reads, 8-bit writes - 1 8-bit reads and writes - 2 8-bit EPP mode - 3 EPP-16 - 4 EPP-32 -*/ +/* + * mode codes: 0 nybble reads, 8-bit writes + * 1 8-bit reads and writes + * 2 8-bit EPP mode + * 3 EPP-16 + * 4 EPP-32 + */ -#define j44(a,b) (((a>>4)&0x0f)|(b&0xf0)) +#define j44(a, b) (((a >> 4) & 0x0f) | (b & 0xf0)) -#define P1 w2(5);w2(0xd);w2(5);w2(0xd);w2(5);w2(4); -#define P2 w2(5);w2(7);w2(5);w2(4); +#define P1 \ + do { \ + w2(5); w2(0xd); w2(5); w2(0xd); w2(5); w2(4); \ + } while (0) -/* cont = 0 - access the IDE register file - cont = 1 - access the IDE command set -*/ - -static int on26_read_regr(struct pi_adapter *pi, int cont, int regr) +#define P2 \ + do { \ + w2(5); w2(7); w2(5); w2(4); \ + } while (0) -{ int a, b, r; +/* + * cont = 0 - access the IDE register file + * cont = 1 - access the IDE command set + */ - r = (regr<<2) + 1 + cont; +static int on26_read_regr(struct pi_adapter *pi, int cont, int regr) +{ + int a, b, r; - switch (pi->mode) { + r = (regr << 2) + 1 + cont; - case 0: w0(1); P1; w0(r); P2; w0(0); P1; + switch (pi->mode) { + case 0: + w0(1); P1; w0(r); P2; w0(0); P1; w2(6); a = r1(); w2(4); w2(6); b = r1(); w2(4); w2(6); w2(4); w2(6); w2(4); - return j44(a,b); - - case 1: w0(1); P1; w0(r); P2; w0(0); P1; + return j44(a, b); + case 1: + w0(1); P1; w0(r); P2; w0(0); P1; w2(0x26); a = r0(); w2(4); w2(0x26); w2(4); - return a; - + return a; case 2: case 3: - case 4: w3(1); w3(1); w2(5); w4(r); w2(4); + case 4: + w3(1); w3(1); w2(5); w4(r); w2(4); w3(0); w3(0); w2(0x24); a = r4(); w2(4); w2(0x24); (void)r4(); w2(4); - return a; + return a; + } - } - return -1; -} + return -1; +} static void on26_write_regr(struct pi_adapter *pi, int cont, int regr, int val) +{ + int r = (regr << 2) + 1 + cont; -{ int r; - - r = (regr<<2) + 1 + cont; - - switch (pi->mode) { - - case 0: - case 1: w0(1); P1; w0(r); P2; w0(0); P1; + switch (pi->mode) { + case 0: + case 1: + w0(1); P1; w0(r); P2; w0(0); P1; w0(val); P2; w0(val); P2; break; - case 2: case 3: - case 4: w3(1); w3(1); w2(5); w4(r); w2(4); - w3(0); w3(0); + case 4: + w3(1); w3(1); w2(5); w4(r); w2(4); + w3(0); w3(0); w2(5); w4(val); w2(4); w2(5); w4(val); w2(4); - break; - } + break; + } } -#define CCP(x) w0(0xfe);w0(0xaa);w0(0x55);w0(0);w0(0xff);\ - w0(0x87);w0(0x78);w0(x);w2(4);w2(5);w2(4);w0(0xff); +#define CCP(x) \ + do { \ + w0(0xfe); w0(0xaa); w0(0x55); w0(0); \ + w0(0xff); w0(0x87); w0(0x78); w0(x); \ + w2(4); w2(5); w2(4); w0(0xff); \ + } while (0) static void on26_connect(struct pi_adapter *pi) - -{ int x; +{ + int x; pi->saved_r0 = r0(); - pi->saved_r2 = r2(); + pi->saved_r2 = r2(); - CCP(0x20); - x = 8; if (pi->mode) x = 9; + CCP(0x20); + if (pi->mode) + x = 9; + else + x = 8; w0(2); P1; w0(8); P2; w0(2); P1; w0(x); P2; } static void on26_disconnect(struct pi_adapter *pi) - -{ if (pi->mode >= 2) { w3(4); w3(4); w3(4); w3(4); } - else { w0(4); P1; w0(4); P1; } +{ + if (pi->mode >= 2) { + w3(4); w3(4); w3(4); w3(4); + } else { + w0(4); P1; w0(4); P1; + } CCP(0x30); - w0(pi->saved_r0); - w2(pi->saved_r2); -} + w0(pi->saved_r0); + w2(pi->saved_r2); +} #define RESET_WAIT 200 -static int on26_test_port(struct pi_adapter *pi) /* hard reset */ +/* hard reset */ +static int on26_test_port(struct pi_adapter *pi) +{ + int i, m, d, x = 0, y = 0; -{ int i, m, d, x=0, y=0; - - pi->saved_r0 = r0(); - pi->saved_r2 = r2(); - - d = pi->delay; - m = pi->mode; - pi->delay = 5; - pi->mode = 0; - - w2(0xc); - - CCP(0x30); CCP(0); - - w0(0xfe);w0(0xaa);w0(0x55);w0(0);w0(0xff); - i = ((r1() & 0xf0) << 4); w0(0x87); - i |= (r1() & 0xf0); w0(0x78); - w0(0x20);w2(4);w2(5); - i |= ((r1() & 0xf0) >> 4); - w2(4);w0(0xff); - - if (i == 0xb5f) { - - w0(2); P1; w0(0); P2; - w0(3); P1; w0(0); P2; - w0(2); P1; w0(8); P2; udelay(100); - w0(2); P1; w0(0xa); P2; udelay(100); - w0(2); P1; w0(8); P2; udelay(1000); - - on26_write_regr(pi,0,6,0xa0); - - for (i=0;idev, "on26: Device reset failed (%x,%x)\n", x, y); - - w0(4); P1; w0(4); P1; - } + pi->saved_r0 = r0(); + pi->saved_r2 = r2(); + + d = pi->delay; + m = pi->mode; + pi->delay = 5; + pi->mode = 0; + + w2(0xc); + + CCP(0x30); CCP(0); + + w0(0xfe); w0(0xaa); w0(0x55); w0(0); w0(0xff); + i = ((r1() & 0xf0) << 4); w0(0x87); + i |= (r1() & 0xf0); w0(0x78); + w0(0x20); w2(4); w2(5); + i |= ((r1() & 0xf0) >> 4); + w2(4); w0(0xff); + + if (i == 0xb5f) { + w0(2); P1; w0(0); P2; + w0(3); P1; w0(0); P2; + w0(2); P1; w0(8); P2; udelay(100); + w0(2); P1; w0(0xa); P2; udelay(100); + w0(2); P1; w0(8); P2; udelay(1000); + + on26_write_regr(pi, 0, 6, 0xa0); + + for (i = 0; i < RESET_WAIT; i++) { + on26_write_regr(pi, 0, 6, 0xa0); + x = on26_read_regr(pi, 0, 7); + on26_write_regr(pi, 0, 6, 0xb0); + y = on26_read_regr(pi, 0, 7); + if (!((x & 0x80) || (y & 0x80))) + break; + mdelay(100); + } + + if (i == RESET_WAIT) + dev_err(&pi->dev, + "on26: Device reset failed (%x,%x)\n", x, y); + + w0(4); P1; w0(4); P1; + } - CCP(0x30); + CCP(0x30); - pi->delay = d; - pi->mode = m; - w0(pi->saved_r0); - w2(pi->saved_r2); + pi->delay = d; + pi->mode = m; + w0(pi->saved_r0); + w2(pi->saved_r2); - return 5; + return 5; } - static void on26_read_block(struct pi_adapter *pi, char *buf, int count) +{ + int k, a, b; -{ int k, a, b; - - switch (pi->mode) { - - case 0: w0(1); P1; w0(1); P2; w0(2); P1; w0(0x18); P2; w0(0); P1; + switch (pi->mode) { + case 0: + w0(1); P1; w0(1); P2; w0(2); P1; w0(0x18); P2; w0(0); P1; udelay(10); - for (k=0;kmode) { - - case 0: - case 1: w0(1); P1; w0(1); P2; - w0(2); P1; w0(0x18+pi->mode); P2; w0(0); P1; +{ + int k; + + switch (pi->mode) { + case 0: + case 1: + w0(1); P1; w0(1); P2; + w0(2); P1; w0(0x18 + pi->mode); P2; w0(0); P1; udelay(10); - for (k=0;kmode); P2; - break; - - case 2: w3(1); w3(1); w2(5); w4(1); w2(4); + for (k = 0; k < count / 2; k++) { + w2(5); w0(buf[2 * k]); + w2(7); w0(buf[2 * k + 1]); + } + w2(5); w2(4); + w0(2); P1; w0(8 + pi->mode); P2; + break; + case 2: + w3(1); w3(1); w2(5); w4(1); w2(4); w3(0); w3(0); w2(0xc5); udelay(10); - for (k=0;kdev, "OnSpec 90c26 at 0x%x, mode %d (%s), delay %d\n", - pi->port, pi->mode, mode_string[pi->mode], pi->delay); + dev_info(&pi->dev, + "OnSpec 90c26 at 0x%x, mode %d (%s), delay %d\n", + pi->port, pi->mode, mode_string[pi->mode], pi->delay); } static struct pi_protocol on26 = { diff --git a/drivers/ata/pata_platform.c b/drivers/ata/pata_platform.c index 87479bc893b252622d5f5b4a0761a09a3adb6d93..232c3dad7ee88acbfaa8a0ef4afb8ef399c85e8c 100644 --- a/drivers/ata/pata_platform.c +++ b/drivers/ata/pata_platform.c @@ -223,7 +223,7 @@ static int pata_platform_probe(struct platform_device *pdev) static struct platform_driver pata_platform_driver = { .probe = pata_platform_probe, - .remove = ata_platform_remove_one, + .remove_new = ata_platform_remove_one, .driver = { .name = DRV_NAME, }, diff --git a/drivers/ata/sata_highbank.c b/drivers/ata/sata_highbank.c index 8237ece4a46fee455ce4e42e988e7768952155f3..d6b324d03e5974b7fde0bdaf9b027df3083d5868 100644 --- a/drivers/ata/sata_highbank.c +++ b/drivers/ata/sata_highbank.c @@ -614,7 +614,7 @@ static SIMPLE_DEV_PM_OPS(ahci_highbank_pm_ops, ahci_highbank_suspend, ahci_highbank_resume); static struct platform_driver ahci_highbank_driver = { - .remove = ata_platform_remove_one, + .remove_new = ata_platform_remove_one, .driver = { .name = "highbank-ahci", .of_match_table = ahci_of_match, diff --git a/drivers/ata/sata_svw.c b/drivers/ata/sata_svw.c index c47c3fb434d53fb5882f226bec0113a223099491..598a872f6a08c696f1cd7a61e2870ab0b407be39 100644 --- a/drivers/ata/sata_svw.c +++ b/drivers/ata/sata_svw.c @@ -32,6 +32,7 @@ #include #include #include +#include #define DRV_NAME "sata_svw" #define DRV_VERSION "2.3" @@ -319,10 +320,11 @@ static int k2_sata_show_info(struct seq_file *m, struct Scsi_Host *shost) /* Match it to a port node */ index = (ap == ap->host->ports[0]) ? 0 : 1; for (np = np->child; np != NULL; np = np->sibling) { - const u32 *reg = of_get_property(np, "reg", NULL); - if (!reg) + u64 reg; + + if (of_property_read_reg(np, 0, ®, NULL)) continue; - if (index == *reg) { + if (index == reg) { seq_printf(m, "devspec: %pOF\n", np); break; } diff --git a/drivers/auxdisplay/ht16k33.c b/drivers/auxdisplay/ht16k33.c index edaf92b7ea770a7e08c7b2279b010750fdc628f1..0c5cd5193fbfbc54130798df4d6488c9bf059658 100644 --- a/drivers/auxdisplay/ht16k33.c +++ b/drivers/auxdisplay/ht16k33.c @@ -820,7 +820,7 @@ static const struct of_device_id ht16k33_of_match[] = { MODULE_DEVICE_TABLE(of, ht16k33_of_match); static struct i2c_driver ht16k33_driver = { - .probe_new = ht16k33_probe, + .probe = ht16k33_probe, .remove = ht16k33_remove, .driver = { .name = DRIVER_NAME, diff --git a/drivers/auxdisplay/lcd2s.c b/drivers/auxdisplay/lcd2s.c index 135831a165149c1582e38aada4463e086121bf71..6422be0dfe20e65add8516ba14ac1ec5a0139675 100644 --- a/drivers/auxdisplay/lcd2s.c +++ b/drivers/auxdisplay/lcd2s.c @@ -365,7 +365,7 @@ static struct i2c_driver lcd2s_i2c_driver = { .name = "lcd2s", .of_match_table = lcd2s_of_table, }, - .probe_new = lcd2s_i2c_probe, + .probe = lcd2s_i2c_probe, .remove = lcd2s_i2c_remove, .id_table = lcd2s_i2c_id, }; diff --git a/drivers/base/dd.c b/drivers/base/dd.c index 9c09ca5c4ab68e347e83f6547c8de122a12f5c62..878aa7646b37e49625f8d9990c343c4264eec833 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c @@ -751,14 +751,12 @@ static int really_probe_debug(struct device *dev, struct device_driver *drv) * * Should somehow figure out how to use a semaphore, not an atomic variable... */ -int driver_probe_done(void) +bool __init driver_probe_done(void) { int local_probe_count = atomic_read(&probe_count); pr_debug("%s: probe_count = %d\n", __func__, local_probe_count); - if (local_probe_count) - return -EBUSY; - return 0; + return !local_probe_count; } /** diff --git a/drivers/base/devres.c b/drivers/base/devres.c index 5c998cfac335dd405f39b8f17209738044087fa1..3df0025d12aa488dd772b1f87638f70a1aba6086 100644 --- a/drivers/base/devres.c +++ b/drivers/base/devres.c @@ -29,10 +29,10 @@ struct devres { * Some archs want to perform DMA into kmalloc caches * and need a guaranteed alignment larger than * the alignment of a 64-bit integer. - * Thus we use ARCH_KMALLOC_MINALIGN here and get exactly the same - * buffer alignment as if it was allocated by plain kmalloc(). + * Thus we use ARCH_DMA_MINALIGN for data[] which will force the same + * alignment for struct devres when allocated by kmalloc(). */ - u8 __aligned(ARCH_KMALLOC_MINALIGN) data[]; + u8 __aligned(ARCH_DMA_MINALIGN) data[]; }; struct devres_group { diff --git a/drivers/base/isa.c b/drivers/base/isa.c index 55e3ee2da98f81fbf2d1b7a232727821328523a8..675ad3139224623bae18d17c7729b4e4b9c2d14e 100644 --- a/drivers/base/isa.c +++ b/drivers/base/isa.c @@ -149,11 +149,8 @@ int isa_register_driver(struct isa_driver *isa_driver, unsigned int ndev) break; } - if (isa_dev->dev.platform_data) { - isa_dev->next = isa_driver->devices; - isa_driver->devices = &isa_dev->dev; - } else - device_unregister(&isa_dev->dev); + isa_dev->next = isa_driver->devices; + isa_driver->devices = &isa_dev->dev; } if (!error && !isa_driver->devices) diff --git a/drivers/base/node.c b/drivers/base/node.c index b46db17124f346aff070bf839b606046720b9854..9de524e563074e729bbed4bc1215a11ba3923c3e 100644 --- a/drivers/base/node.c +++ b/drivers/base/node.c @@ -162,15 +162,15 @@ static struct node_access_nodes *node_init_node_access(struct node *node, } #ifdef CONFIG_HMEM_REPORTING -#define ACCESS_ATTR(name) \ -static ssize_t name##_show(struct device *dev, \ +#define ACCESS_ATTR(property) \ +static ssize_t property##_show(struct device *dev, \ struct device_attribute *attr, \ char *buf) \ { \ return sysfs_emit(buf, "%u\n", \ - to_access_nodes(dev)->hmem_attrs.name); \ + to_access_nodes(dev)->hmem_attrs.property); \ } \ -static DEVICE_ATTR_RO(name) +static DEVICE_ATTR_RO(property) ACCESS_ATTR(read_bandwidth); ACCESS_ATTR(read_latency); @@ -448,6 +448,9 @@ static ssize_t node_read_meminfo(struct device *dev, "Node %d ShmemPmdMapped: %8lu kB\n" "Node %d FileHugePages: %8lu kB\n" "Node %d FilePmdMapped: %8lu kB\n" +#endif +#ifdef CONFIG_UNACCEPTED_MEMORY + "Node %d Unaccepted: %8lu kB\n" #endif , nid, K(node_page_state(pgdat, NR_FILE_DIRTY)), @@ -477,6 +480,10 @@ static ssize_t node_read_meminfo(struct device *dev, nid, K(node_page_state(pgdat, NR_SHMEM_PMDMAPPED)), nid, K(node_page_state(pgdat, NR_FILE_THPS)), nid, K(node_page_state(pgdat, NR_FILE_PMDMAPPED)) +#endif +#ifdef CONFIG_UNACCEPTED_MEMORY + , + nid, K(sum_zone_node_page_state(nid, NR_UNACCEPTED)) #endif ); len += hugetlb_report_node_meminfo(buf, len, nid); diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index 32084e38b73d01f58ae1a5a9f5beb759e1328a88..5cb2023581d4db5a97bc940cb5fb6b9986be93df 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -1632,9 +1632,6 @@ static int genpd_add_device(struct generic_pm_domain *genpd, struct device *dev, dev_dbg(dev, "%s()\n", __func__); - if (IS_ERR_OR_NULL(genpd) || IS_ERR_OR_NULL(dev)) - return -EINVAL; - gpd_data = genpd_alloc_dev_data(dev, gd); if (IS_ERR(gpd_data)) return PTR_ERR(gpd_data); @@ -1676,6 +1673,9 @@ int pm_genpd_add_device(struct generic_pm_domain *genpd, struct device *dev) { int ret; + if (!genpd || !dev) + return -EINVAL; + mutex_lock(&gpd_list_lock); ret = genpd_add_device(genpd, dev, dev); mutex_unlock(&gpd_list_lock); @@ -2523,6 +2523,9 @@ int of_genpd_add_device(struct of_phandle_args *genpdspec, struct device *dev) struct generic_pm_domain *genpd; int ret; + if (!dev) + return -EINVAL; + mutex_lock(&gpd_list_lock); genpd = genpd_get_from_provider(genpdspec); @@ -2939,10 +2942,10 @@ static int genpd_parse_state(struct genpd_power_state *genpd_state, err = of_property_read_u32(state_node, "min-residency-us", &residency); if (!err) - genpd_state->residency_ns = 1000 * residency; + genpd_state->residency_ns = 1000LL * residency; - genpd_state->power_on_latency_ns = 1000 * exit_latency; - genpd_state->power_off_latency_ns = 1000 * entry_latency; + genpd_state->power_on_latency_ns = 1000LL * exit_latency; + genpd_state->power_off_latency_ns = 1000LL * entry_latency; genpd_state->fwnode = &state_node->fwnode; return 0; diff --git a/drivers/base/power/wakeup.c b/drivers/base/power/wakeup.c index 7cc0c0cf8eaa529eb2eecd484f8a2a9fbedf4fb3..a917219feea62d256a80166879bc01098eee54a3 100644 --- a/drivers/base/power/wakeup.c +++ b/drivers/base/power/wakeup.c @@ -19,11 +19,6 @@ #include "power.h" -#ifndef CONFIG_SUSPEND -suspend_state_t pm_suspend_target_state; -#define pm_suspend_target_state (PM_SUSPEND_ON) -#endif - #define list_for_each_entry_rcu_locked(pos, head, member) \ list_for_each_entry_rcu(pos, head, member, \ srcu_read_lock_held(&wakeup_srcu)) diff --git a/drivers/base/property.c b/drivers/base/property.c index f6117ec9805c4b7aae86dac1216088fc9f83c7ab..8c40abed785247b6262aac141d6f02f876a66835 100644 --- a/drivers/base/property.c +++ b/drivers/base/property.c @@ -987,12 +987,18 @@ EXPORT_SYMBOL(fwnode_iomap); * @fwnode: Pointer to the firmware node * @index: Zero-based index of the IRQ * - * Return: Linux IRQ number on success. Other values are determined - * according to acpi_irq_get() or of_irq_get() operation. + * Return: Linux IRQ number on success. Negative errno on failure. */ int fwnode_irq_get(const struct fwnode_handle *fwnode, unsigned int index) { - return fwnode_call_int_op(fwnode, irq_get, index); + int ret; + + ret = fwnode_call_int_op(fwnode, irq_get, index); + /* We treat mapping errors as invalid case */ + if (ret == 0) + return -EINVAL; + + return ret; } EXPORT_SYMBOL(fwnode_irq_get); diff --git a/drivers/base/regmap/Makefile b/drivers/base/regmap/Makefile index f6c6cb0172000100e93cbe941648ba2e7a694c66..5fdd0845b45e5a2d649af6f66d692637beafad5a 100644 --- a/drivers/base/regmap/Makefile +++ b/drivers/base/regmap/Makefile @@ -8,7 +8,7 @@ obj-$(CONFIG_DEBUG_FS) += regmap-debugfs.o obj-$(CONFIG_REGMAP_KUNIT) += regmap-kunit.o obj-$(CONFIG_REGMAP_AC97) += regmap-ac97.o obj-$(CONFIG_REGMAP_I2C) += regmap-i2c.o -obj-$(CONFIG_REGMAP_RAM) += regmap-ram.o +obj-$(CONFIG_REGMAP_RAM) += regmap-ram.o regmap-raw-ram.o obj-$(CONFIG_REGMAP_SLIMBUS) += regmap-slimbus.o obj-$(CONFIG_REGMAP_SPI) += regmap-spi.o obj-$(CONFIG_REGMAP_SPMI) += regmap-spmi.o diff --git a/drivers/base/regmap/internal.h b/drivers/base/regmap/internal.h index 9bd0dfd1e2596fc3cff0dd1ace31c8e293fb89f7..9a9ea514c2d8176ded59056c7565ff195e6a64d1 100644 --- a/drivers/base/regmap/internal.h +++ b/drivers/base/regmap/internal.h @@ -125,6 +125,9 @@ struct regmap { int reg_stride; int reg_stride_order; + /* If set, will always write field to HW. */ + bool force_write_field; + /* regcache specific members */ const struct regcache_ops *cache_ops; enum regcache_type cache_type; @@ -257,6 +260,8 @@ int regcache_sync_block(struct regmap *map, void *block, unsigned long *cache_present, unsigned int block_base, unsigned int start, unsigned int end); +bool regcache_reg_needs_sync(struct regmap *map, unsigned int reg, + unsigned int val); static inline const void *regcache_get_val_addr(struct regmap *map, const void *base, @@ -267,7 +272,7 @@ static inline const void *regcache_get_val_addr(struct regmap *map, unsigned int regcache_get_val(struct regmap *map, const void *base, unsigned int idx); -bool regcache_set_val(struct regmap *map, void *base, unsigned int idx, +void regcache_set_val(struct regmap *map, void *base, unsigned int idx, unsigned int val); int regcache_lookup_reg(struct regmap *map, unsigned int reg); int regcache_sync_val(struct regmap *map, unsigned int reg, unsigned int val); @@ -312,6 +317,7 @@ struct regmap_ram_data { unsigned int *vals; /* Allocatd by caller */ bool *read; bool *written; + enum regmap_endian reg_endian; }; /* @@ -326,5 +332,12 @@ struct regmap *__regmap_init_ram(const struct regmap_config *config, #define regmap_init_ram(config, data) \ __regmap_lockdep_wrapper(__regmap_init_ram, #config, config, data) +struct regmap *__regmap_init_raw_ram(const struct regmap_config *config, + struct regmap_ram_data *data, + struct lock_class_key *lock_key, + const char *lock_name); + +#define regmap_init_raw_ram(config, data) \ + __regmap_lockdep_wrapper(__regmap_init_raw_ram, #config, config, data) #endif diff --git a/drivers/base/regmap/regcache-maple.c b/drivers/base/regmap/regcache-maple.c index c2e3a0f6c2183bd2c3cc59561d162317dfea8d50..283c2e02a2985aa274bc25dab1f321d6c45638ee 100644 --- a/drivers/base/regmap/regcache-maple.c +++ b/drivers/base/regmap/regcache-maple.c @@ -186,6 +186,55 @@ static int regcache_maple_drop(struct regmap *map, unsigned int min, return ret; } +static int regcache_maple_sync_block(struct regmap *map, unsigned long *entry, + struct ma_state *mas, + unsigned int min, unsigned int max) +{ + void *buf; + unsigned long r; + size_t val_bytes = map->format.val_bytes; + int ret = 0; + + mas_pause(mas); + rcu_read_unlock(); + + /* + * Use a raw write if writing more than one register to a + * device that supports raw writes to reduce transaction + * overheads. + */ + if (max - min > 1 && regmap_can_raw_write(map)) { + buf = kmalloc(val_bytes * (max - min), map->alloc_flags); + if (!buf) { + ret = -ENOMEM; + goto out; + } + + /* Render the data for a raw write */ + for (r = min; r < max; r++) { + regcache_set_val(map, buf, r - min, + entry[r - mas->index]); + } + + ret = _regmap_raw_write(map, min, buf, (max - min) * val_bytes, + false); + + kfree(buf); + } else { + for (r = min; r < max; r++) { + ret = _regmap_write(map, r, + entry[r - mas->index]); + if (ret != 0) + goto out; + } + } + +out: + rcu_read_lock(); + + return ret; +} + static int regcache_maple_sync(struct regmap *map, unsigned int min, unsigned int max) { @@ -194,8 +243,9 @@ static int regcache_maple_sync(struct regmap *map, unsigned int min, MA_STATE(mas, mt, min, max); unsigned long lmin = min; unsigned long lmax = max; - unsigned int r; + unsigned int r, v, sync_start; int ret; + bool sync_needed = false; map->cache_bypass = true; @@ -203,18 +253,38 @@ static int regcache_maple_sync(struct regmap *map, unsigned int min, mas_for_each(&mas, entry, max) { for (r = max(mas.index, lmin); r <= min(mas.last, lmax); r++) { - mas_pause(&mas); - rcu_read_unlock(); - ret = regcache_sync_val(map, r, entry[r - mas.index]); + v = entry[r - mas.index]; + + if (regcache_reg_needs_sync(map, r, v)) { + if (!sync_needed) { + sync_start = r; + sync_needed = true; + } + continue; + } + + if (!sync_needed) + continue; + + ret = regcache_maple_sync_block(map, entry, &mas, + sync_start, r); + if (ret != 0) + goto out; + sync_needed = false; + } + + if (sync_needed) { + ret = regcache_maple_sync_block(map, entry, &mas, + sync_start, r); if (ret != 0) goto out; - rcu_read_lock(); + sync_needed = false; } } +out: rcu_read_unlock(); -out: map->cache_bypass = false; return ret; @@ -242,11 +312,41 @@ static int regcache_maple_exit(struct regmap *map) return 0; } +static int regcache_maple_insert_block(struct regmap *map, int first, + int last) +{ + struct maple_tree *mt = map->cache; + MA_STATE(mas, mt, first, last); + unsigned long *entry; + int i, ret; + + entry = kcalloc(last - first + 1, sizeof(unsigned long), GFP_KERNEL); + if (!entry) + return -ENOMEM; + + for (i = 0; i < last - first + 1; i++) + entry[i] = map->reg_defaults[first + i].def; + + mas_lock(&mas); + + mas_set_range(&mas, map->reg_defaults[first].reg, + map->reg_defaults[last].reg); + ret = mas_store_gfp(&mas, entry, GFP_KERNEL); + + mas_unlock(&mas); + + if (ret) + kfree(entry); + + return ret; +} + static int regcache_maple_init(struct regmap *map) { struct maple_tree *mt; int i; int ret; + int range_start; mt = kmalloc(sizeof(*mt), GFP_KERNEL); if (!mt) @@ -255,14 +355,30 @@ static int regcache_maple_init(struct regmap *map) mt_init(mt); - for (i = 0; i < map->num_reg_defaults; i++) { - ret = regcache_maple_write(map, - map->reg_defaults[i].reg, - map->reg_defaults[i].def); - if (ret) - goto err; + if (!map->num_reg_defaults) + return 0; + + range_start = 0; + + /* Scan for ranges of contiguous registers */ + for (i = 1; i < map->num_reg_defaults; i++) { + if (map->reg_defaults[i].reg != + map->reg_defaults[i - 1].reg + 1) { + ret = regcache_maple_insert_block(map, range_start, + i - 1); + if (ret != 0) + goto err; + + range_start = i; + } } + /* Add the last block */ + ret = regcache_maple_insert_block(map, range_start, + map->num_reg_defaults - 1); + if (ret != 0) + goto err; + return 0; err: diff --git a/drivers/base/regmap/regcache.c b/drivers/base/regmap/regcache.c index 97c681fcf9f6ee4cd4e5bb0c709fabb9faf07b50..28bc3ae9458acb94ff07e8e20adf12b79c29a01b 100644 --- a/drivers/base/regmap/regcache.c +++ b/drivers/base/regmap/regcache.c @@ -279,8 +279,8 @@ int regcache_write(struct regmap *map, return 0; } -static bool regcache_reg_needs_sync(struct regmap *map, unsigned int reg, - unsigned int val) +bool regcache_reg_needs_sync(struct regmap *map, unsigned int reg, + unsigned int val) { int ret; @@ -561,17 +561,14 @@ void regcache_cache_bypass(struct regmap *map, bool enable) } EXPORT_SYMBOL_GPL(regcache_cache_bypass); -bool regcache_set_val(struct regmap *map, void *base, unsigned int idx, +void regcache_set_val(struct regmap *map, void *base, unsigned int idx, unsigned int val) { - if (regcache_get_val(map, base, idx) == val) - return true; - /* Use device native format if possible */ if (map->format.format_val) { map->format.format_val(base + (map->cache_word_size * idx), val, 0); - return false; + return; } switch (map->cache_word_size) { @@ -604,7 +601,6 @@ bool regcache_set_val(struct regmap *map, void *base, unsigned int idx, default: BUG(); } - return false; } unsigned int regcache_get_val(struct regmap *map, const void *base, diff --git a/drivers/base/regmap/regmap-debugfs.c b/drivers/base/regmap/regmap-debugfs.c index c491fabe3617a94e5be45aecd090d1720028556e..f36027591e1a8db986c54a2f04f1a645d5f77b76 100644 --- a/drivers/base/regmap/regmap-debugfs.c +++ b/drivers/base/regmap/regmap-debugfs.c @@ -636,6 +636,17 @@ void regmap_debugfs_init(struct regmap *map) ®map_cache_bypass_fops); } + /* + * This could interfere with driver operation. Therefore, don't provide + * any real compile time configuration option for this feature. One will + * have to modify the source code directly in order to use it. + */ +#undef REGMAP_ALLOW_FORCE_WRITE_FIELD_DEBUGFS +#ifdef REGMAP_ALLOW_FORCE_WRITE_FIELD_DEBUGFS + debugfs_create_bool("force_write_field", 0600, map->debugfs, + &map->force_write_field); +#endif + next = rb_first(&map->range_tree); while (next) { range_node = rb_entry(next, struct regmap_range_node, node); diff --git a/drivers/base/regmap/regmap-irq.c b/drivers/base/regmap/regmap-irq.c index b99bb2369fffb7252aa134001428432152c6f747..45fd13ef13fc645ef7b31233308e6b35f6ef1222 100644 --- a/drivers/base/regmap/regmap-irq.c +++ b/drivers/base/regmap/regmap-irq.c @@ -30,9 +30,6 @@ struct regmap_irq_chip_data { int irq; int wake_count; - unsigned int mask_base; - unsigned int unmask_base; - void *status_reg_buf; unsigned int *main_status_buf; unsigned int *status_buf; @@ -41,7 +38,6 @@ struct regmap_irq_chip_data { unsigned int *wake_buf; unsigned int *type_buf; unsigned int *type_buf_def; - unsigned int **virt_buf; unsigned int **config_buf; unsigned int irq_reg_stride; @@ -114,25 +110,22 @@ static void regmap_irq_sync_unlock(struct irq_data *data) * suppress pointless writes. */ for (i = 0; i < d->chip->num_regs; i++) { - if (d->mask_base) { - if (d->chip->handle_mask_sync) - d->chip->handle_mask_sync(d->map, i, - d->mask_buf_def[i], - d->mask_buf[i], - d->chip->irq_drv_data); - else { - reg = d->get_irq_reg(d, d->mask_base, i); - ret = regmap_update_bits(d->map, reg, - d->mask_buf_def[i], - d->mask_buf[i]); - if (ret) - dev_err(d->map->dev, "Failed to sync masks in %x\n", - reg); - } + if (d->chip->handle_mask_sync) + d->chip->handle_mask_sync(i, d->mask_buf_def[i], + d->mask_buf[i], + d->chip->irq_drv_data); + + if (d->chip->mask_base && !d->chip->handle_mask_sync) { + reg = d->get_irq_reg(d, d->chip->mask_base, i); + ret = regmap_update_bits(d->map, reg, + d->mask_buf_def[i], + d->mask_buf[i]); + if (ret) + dev_err(d->map->dev, "Failed to sync masks in %x\n", reg); } - if (d->unmask_base) { - reg = d->get_irq_reg(d, d->unmask_base, i); + if (d->chip->unmask_base && !d->chip->handle_mask_sync) { + reg = d->get_irq_reg(d, d->chip->unmask_base, i); ret = regmap_update_bits(d->map, reg, d->mask_buf_def[i], ~d->mask_buf[i]); if (ret) @@ -183,34 +176,6 @@ static void regmap_irq_sync_unlock(struct irq_data *data) } } - /* Don't update the type bits if we're using mask bits for irq type. */ - if (!d->chip->type_in_mask) { - for (i = 0; i < d->chip->num_type_reg; i++) { - if (!d->type_buf_def[i]) - continue; - reg = d->get_irq_reg(d, d->chip->type_base, i); - ret = regmap_update_bits(d->map, reg, - d->type_buf_def[i], d->type_buf[i]); - if (ret != 0) - dev_err(d->map->dev, "Failed to sync type in %x\n", - reg); - } - } - - if (d->chip->num_virt_regs) { - for (i = 0; i < d->chip->num_virt_regs; i++) { - for (j = 0; j < d->chip->num_regs; j++) { - reg = d->get_irq_reg(d, d->chip->virt_reg_base[i], - j); - ret = regmap_write(map, reg, d->virt_buf[i][j]); - if (ret != 0) - dev_err(d->map->dev, - "Failed to write virt 0x%x: %d\n", - reg, ret); - } - } - } - for (i = 0; i < d->chip->num_config_bases; i++) { for (j = 0; j < d->chip->num_config_regs; j++) { reg = d->get_irq_reg(d, d->chip->config_base[i], j); @@ -289,41 +254,9 @@ static int regmap_irq_set_type(struct irq_data *data, unsigned int type) reg = t->type_reg_offset / map->reg_stride; - if (t->type_reg_mask) - d->type_buf[reg] &= ~t->type_reg_mask; - else - d->type_buf[reg] &= ~(t->type_falling_val | - t->type_rising_val | - t->type_level_low_val | - t->type_level_high_val); - switch (type) { - case IRQ_TYPE_EDGE_FALLING: - d->type_buf[reg] |= t->type_falling_val; - break; - - case IRQ_TYPE_EDGE_RISING: - d->type_buf[reg] |= t->type_rising_val; - break; - - case IRQ_TYPE_EDGE_BOTH: - d->type_buf[reg] |= (t->type_falling_val | - t->type_rising_val); - break; - - case IRQ_TYPE_LEVEL_HIGH: - d->type_buf[reg] |= t->type_level_high_val; - break; - - case IRQ_TYPE_LEVEL_LOW: - d->type_buf[reg] |= t->type_level_low_val; - break; - default: - return -EINVAL; - } - - if (d->chip->set_type_virt) { - ret = d->chip->set_type_virt(d->virt_buf, type, data->hwirq, - reg); + if (d->chip->type_in_mask) { + ret = regmap_irq_set_type_config_simple(&d->type_buf, type, + irq_data, reg, d->chip->irq_drv_data); if (ret) return ret; } @@ -390,15 +323,8 @@ static inline int read_sub_irq_data(struct regmap_irq_chip_data *data, unsigned int offset = subreg->offset[i]; unsigned int index = offset / map->reg_stride; - if (chip->not_fixed_stride) - ret = regmap_read(map, - chip->status_base + offset, - &data->status_buf[b]); - else - ret = regmap_read(map, - chip->status_base + offset, - &data->status_buf[index]); - + ret = regmap_read(map, chip->status_base + offset, + &data->status_buf[index]); if (ret) break; } @@ -453,17 +379,7 @@ static irqreturn_t regmap_irq_thread(int irq, void *d) * sake of simplicity. and add bulk reads only if needed */ for (i = 0; i < chip->num_main_regs; i++) { - /* - * For not_fixed_stride, don't use ->get_irq_reg(). - * It would produce an incorrect result. - */ - if (data->chip->not_fixed_stride) - reg = chip->main_status + - i * map->reg_stride * data->irq_reg_stride; - else - reg = data->get_irq_reg(data, - chip->main_status, i); - + reg = data->get_irq_reg(data, chip->main_status, i); ret = regmap_read(map, reg, &data->main_status_buf[i]); if (ret) { dev_err(map->dev, @@ -586,12 +502,12 @@ static irqreturn_t regmap_irq_thread(int irq, void *d) } exit: - if (chip->runtime_pm) - pm_runtime_put(map->dev); - if (chip->handle_post_irq) chip->handle_post_irq(chip->irq_drv_data); + if (chip->runtime_pm) + pm_runtime_put(map->dev); + if (handled) return IRQ_HANDLED; else @@ -629,20 +545,8 @@ static const struct irq_domain_ops regmap_domain_ops = { unsigned int regmap_irq_get_irq_reg_linear(struct regmap_irq_chip_data *data, unsigned int base, int index) { - const struct regmap_irq_chip *chip = data->chip; struct regmap *map = data->map; - /* - * FIXME: This is for backward compatibility and should be removed - * when not_fixed_stride is dropped (it's only used by qcom-pm8008). - */ - if (chip->not_fixed_stride && chip->sub_reg_offsets) { - struct regmap_irq_sub_irq_map *subreg; - - subreg = &chip->sub_reg_offsets[0]; - return base + subreg->offset[0]; - } - return base + index * map->reg_stride * data->irq_reg_stride; } EXPORT_SYMBOL_GPL(regmap_irq_get_irq_reg_linear); @@ -730,8 +634,6 @@ int regmap_add_irq_chip_fwnode(struct fwnode_handle *fwnode, struct regmap_irq_chip_data *d; int i; int ret = -ENOMEM; - int num_type_reg; - int num_regs; u32 reg; if (chip->num_regs <= 0) @@ -740,6 +642,9 @@ int regmap_add_irq_chip_fwnode(struct fwnode_handle *fwnode, if (chip->clear_on_unmask && (chip->ack_base || chip->use_ack)) return -EINVAL; + if (chip->mask_base && chip->unmask_base && !chip->mask_unmask_non_inverted) + return -EINVAL; + for (i = 0; i < chip->num_irqs; i++) { if (chip->irqs[i].reg_offset % map->reg_stride) return -EINVAL; @@ -748,20 +653,6 @@ int regmap_add_irq_chip_fwnode(struct fwnode_handle *fwnode, return -EINVAL; } - if (chip->not_fixed_stride) { - dev_warn(map->dev, "not_fixed_stride is deprecated; use ->get_irq_reg() instead"); - - for (i = 0; i < chip->num_regs; i++) - if (chip->sub_reg_offsets[i].num_regs != 1) - return -EINVAL; - } - - if (chip->num_type_reg) - dev_warn(map->dev, "type registers are deprecated; use config registers instead"); - - if (chip->num_virt_regs || chip->virt_reg_base || chip->set_type_virt) - dev_warn(map->dev, "virtual registers are deprecated; use config registers instead"); - if (irq_base) { irq_base = irq_alloc_descs(irq_base, 0, chip->num_irqs, 0); if (irq_base < 0) { @@ -806,43 +697,17 @@ int regmap_add_irq_chip_fwnode(struct fwnode_handle *fwnode, goto err_alloc; } - /* - * Use num_config_regs if defined, otherwise fall back to num_type_reg - * to maintain backward compatibility. - */ - num_type_reg = chip->num_config_regs ? chip->num_config_regs - : chip->num_type_reg; - num_regs = chip->type_in_mask ? chip->num_regs : num_type_reg; - if (num_regs) { - d->type_buf_def = kcalloc(num_regs, + if (chip->type_in_mask) { + d->type_buf_def = kcalloc(chip->num_regs, sizeof(*d->type_buf_def), GFP_KERNEL); if (!d->type_buf_def) goto err_alloc; - d->type_buf = kcalloc(num_regs, sizeof(*d->type_buf), - GFP_KERNEL); + d->type_buf = kcalloc(chip->num_regs, sizeof(*d->type_buf), GFP_KERNEL); if (!d->type_buf) goto err_alloc; } - if (chip->num_virt_regs) { - /* - * Create virt_buf[chip->num_extra_config_regs][chip->num_regs] - */ - d->virt_buf = kcalloc(chip->num_virt_regs, sizeof(*d->virt_buf), - GFP_KERNEL); - if (!d->virt_buf) - goto err_alloc; - - for (i = 0; i < chip->num_virt_regs; i++) { - d->virt_buf[i] = kcalloc(chip->num_regs, - sizeof(**d->virt_buf), - GFP_KERNEL); - if (!d->virt_buf[i]) - goto err_alloc; - } - } - if (chip->num_config_bases && chip->num_config_regs) { /* * Create config_buf[num_config_bases][num_config_regs] @@ -852,7 +717,7 @@ int regmap_add_irq_chip_fwnode(struct fwnode_handle *fwnode, if (!d->config_buf) goto err_alloc; - for (i = 0; i < chip->num_config_regs; i++) { + for (i = 0; i < chip->num_config_bases; i++) { d->config_buf[i] = kcalloc(chip->num_config_regs, sizeof(**d->config_buf), GFP_KERNEL); @@ -868,28 +733,6 @@ int regmap_add_irq_chip_fwnode(struct fwnode_handle *fwnode, d->chip = chip; d->irq_base = irq_base; - if (chip->mask_base && chip->unmask_base && - !chip->mask_unmask_non_inverted) { - /* - * Chips that specify both mask_base and unmask_base used to - * get inverted mask behavior by default, with no way to ask - * for the normal, non-inverted behavior. This "inverted by - * default" behavior is deprecated, but we have to support it - * until existing drivers have been fixed. - * - * Existing drivers should be updated by swapping mask_base - * and unmask_base and setting mask_unmask_non_inverted=true. - * New drivers should always set the flag. - */ - dev_warn(map->dev, "mask_base and unmask_base are inverted, please fix it"); - - d->mask_base = chip->unmask_base; - d->unmask_base = chip->mask_base; - } else { - d->mask_base = chip->mask_base; - d->unmask_base = chip->unmask_base; - } - if (chip->irq_reg_stride) d->irq_reg_stride = chip->irq_reg_stride; else @@ -918,29 +761,28 @@ int regmap_add_irq_chip_fwnode(struct fwnode_handle *fwnode, for (i = 0; i < chip->num_regs; i++) { d->mask_buf[i] = d->mask_buf_def[i]; - if (d->mask_base) { - if (chip->handle_mask_sync) { - ret = chip->handle_mask_sync(d->map, i, - d->mask_buf_def[i], - d->mask_buf[i], - chip->irq_drv_data); - if (ret) - goto err_alloc; - } else { - reg = d->get_irq_reg(d, d->mask_base, i); - ret = regmap_update_bits(d->map, reg, - d->mask_buf_def[i], - d->mask_buf[i]); - if (ret) { - dev_err(map->dev, "Failed to set masks in 0x%x: %d\n", - reg, ret); - goto err_alloc; - } + if (chip->handle_mask_sync) { + ret = chip->handle_mask_sync(i, d->mask_buf_def[i], + d->mask_buf[i], + chip->irq_drv_data); + if (ret) + goto err_alloc; + } + + if (chip->mask_base && !chip->handle_mask_sync) { + reg = d->get_irq_reg(d, chip->mask_base, i); + ret = regmap_update_bits(d->map, reg, + d->mask_buf_def[i], + d->mask_buf[i]); + if (ret) { + dev_err(map->dev, "Failed to set masks in 0x%x: %d\n", + reg, ret); + goto err_alloc; } } - if (d->unmask_base) { - reg = d->get_irq_reg(d, d->unmask_base, i); + if (chip->unmask_base && !chip->handle_mask_sync) { + reg = d->get_irq_reg(d, chip->unmask_base, i); ret = regmap_update_bits(d->map, reg, d->mask_buf_def[i], ~d->mask_buf[i]); if (ret) { @@ -1014,20 +856,6 @@ int regmap_add_irq_chip_fwnode(struct fwnode_handle *fwnode, } } - if (chip->num_type_reg && !chip->type_in_mask) { - for (i = 0; i < chip->num_type_reg; ++i) { - reg = d->get_irq_reg(d, d->chip->type_base, i); - - ret = regmap_read(map, reg, &d->type_buf_def[i]); - - if (ret) { - dev_err(map->dev, "Failed to get type defaults at 0x%x: %d\n", - reg, ret); - goto err_alloc; - } - } - } - if (irq_base) d->domain = irq_domain_create_legacy(fwnode, chip->num_irqs, irq_base, 0, @@ -1064,11 +892,6 @@ int regmap_add_irq_chip_fwnode(struct fwnode_handle *fwnode, kfree(d->mask_buf); kfree(d->status_buf); kfree(d->status_reg_buf); - if (d->virt_buf) { - for (i = 0; i < chip->num_virt_regs; i++) - kfree(d->virt_buf[i]); - kfree(d->virt_buf); - } if (d->config_buf) { for (i = 0; i < chip->num_config_bases; i++) kfree(d->config_buf[i]); diff --git a/drivers/base/regmap/regmap-kunit.c b/drivers/base/regmap/regmap-kunit.c index f76d4168813498ec900f2638083ca7f2576eb6a5..24257aa9004dbc3a1c629f94093b649c86dbe8b5 100644 --- a/drivers/base/regmap/regmap-kunit.c +++ b/drivers/base/regmap/regmap-kunit.c @@ -92,6 +92,11 @@ static struct regmap *gen_regmap(struct regmap_config *config, return ret; } +static bool reg_5_false(struct device *context, unsigned int reg) +{ + return reg != 5; +} + static void basic_read_write(struct kunit *test) { struct regcache_types *t = (struct regcache_types *)test->param_value; @@ -191,6 +196,81 @@ static void bulk_read(struct kunit *test) regmap_exit(map); } +static void write_readonly(struct kunit *test) +{ + struct regcache_types *t = (struct regcache_types *)test->param_value; + struct regmap *map; + struct regmap_config config; + struct regmap_ram_data *data; + unsigned int val; + int i; + + config = test_regmap_config; + config.cache_type = t->type; + config.num_reg_defaults = BLOCK_TEST_SIZE; + config.writeable_reg = reg_5_false; + + map = gen_regmap(&config, &data); + KUNIT_ASSERT_FALSE(test, IS_ERR(map)); + if (IS_ERR(map)) + return; + + get_random_bytes(&val, sizeof(val)); + + for (i = 0; i < BLOCK_TEST_SIZE; i++) + data->written[i] = false; + + /* Change the value of all registers, readonly should fail */ + for (i = 0; i < BLOCK_TEST_SIZE; i++) + KUNIT_EXPECT_EQ(test, i != 5, regmap_write(map, i, val) == 0); + + /* Did that match what we see on the device? */ + for (i = 0; i < BLOCK_TEST_SIZE; i++) + KUNIT_EXPECT_EQ(test, i != 5, data->written[i]); + + regmap_exit(map); +} + +static void read_writeonly(struct kunit *test) +{ + struct regcache_types *t = (struct regcache_types *)test->param_value; + struct regmap *map; + struct regmap_config config; + struct regmap_ram_data *data; + unsigned int val; + int i; + + config = test_regmap_config; + config.cache_type = t->type; + config.readable_reg = reg_5_false; + + map = gen_regmap(&config, &data); + KUNIT_ASSERT_FALSE(test, IS_ERR(map)); + if (IS_ERR(map)) + return; + + for (i = 0; i < BLOCK_TEST_SIZE; i++) + data->read[i] = false; + + /* + * Try to read all the registers, the writeonly one should + * fail if we aren't using the flat cache. + */ + for (i = 0; i < BLOCK_TEST_SIZE; i++) { + if (t->type != REGCACHE_FLAT) { + KUNIT_EXPECT_EQ(test, i != 5, + regmap_read(map, i, &val) == 0); + } else { + KUNIT_EXPECT_EQ(test, 0, regmap_read(map, i, &val)); + } + } + + /* Did we trigger a hardware access? */ + KUNIT_EXPECT_FALSE(test, data->read[5]); + + regmap_exit(map); +} + static void reg_defaults(struct kunit *test) { struct regcache_types *t = (struct regcache_types *)test->param_value; @@ -609,6 +689,47 @@ static void cache_sync_defaults(struct kunit *test) regmap_exit(map); } +static void cache_sync_readonly(struct kunit *test) +{ + struct regcache_types *t = (struct regcache_types *)test->param_value; + struct regmap *map; + struct regmap_config config; + struct regmap_ram_data *data; + unsigned int val; + int i; + + config = test_regmap_config; + config.cache_type = t->type; + config.writeable_reg = reg_5_false; + + map = gen_regmap(&config, &data); + KUNIT_ASSERT_FALSE(test, IS_ERR(map)); + if (IS_ERR(map)) + return; + + /* Read all registers to fill the cache */ + for (i = 0; i < BLOCK_TEST_SIZE; i++) + KUNIT_EXPECT_EQ(test, 0, regmap_read(map, i, &val)); + + /* Change the value of all registers, readonly should fail */ + get_random_bytes(&val, sizeof(val)); + regcache_cache_only(map, true); + for (i = 0; i < BLOCK_TEST_SIZE; i++) + KUNIT_EXPECT_EQ(test, i != 5, regmap_write(map, i, val) == 0); + regcache_cache_only(map, false); + + /* Resync */ + for (i = 0; i < BLOCK_TEST_SIZE; i++) + data->written[i] = false; + KUNIT_EXPECT_EQ(test, 0, regcache_sync(map)); + + /* Did that match what we see on the device? */ + for (i = 0; i < BLOCK_TEST_SIZE; i++) + KUNIT_EXPECT_EQ(test, i != 5, data->written[i]); + + regmap_exit(map); +} + static void cache_sync_patch(struct kunit *test) { struct regcache_types *t = (struct regcache_types *)test->param_value; @@ -712,10 +833,333 @@ static void cache_drop(struct kunit *test) regmap_exit(map); } +struct raw_test_types { + const char *name; + + enum regcache_type cache_type; + enum regmap_endian val_endian; +}; + +static void raw_to_desc(const struct raw_test_types *t, char *desc) +{ + strcpy(desc, t->name); +} + +static const struct raw_test_types raw_types_list[] = { + { "none-little", REGCACHE_NONE, REGMAP_ENDIAN_LITTLE }, + { "none-big", REGCACHE_NONE, REGMAP_ENDIAN_BIG }, + { "flat-little", REGCACHE_FLAT, REGMAP_ENDIAN_LITTLE }, + { "flat-big", REGCACHE_FLAT, REGMAP_ENDIAN_BIG }, + { "rbtree-little", REGCACHE_RBTREE, REGMAP_ENDIAN_LITTLE }, + { "rbtree-big", REGCACHE_RBTREE, REGMAP_ENDIAN_BIG }, + { "maple-little", REGCACHE_MAPLE, REGMAP_ENDIAN_LITTLE }, + { "maple-big", REGCACHE_MAPLE, REGMAP_ENDIAN_BIG }, +}; + +KUNIT_ARRAY_PARAM(raw_test_types, raw_types_list, raw_to_desc); + +static const struct raw_test_types raw_cache_types_list[] = { + { "flat-little", REGCACHE_FLAT, REGMAP_ENDIAN_LITTLE }, + { "flat-big", REGCACHE_FLAT, REGMAP_ENDIAN_BIG }, + { "rbtree-little", REGCACHE_RBTREE, REGMAP_ENDIAN_LITTLE }, + { "rbtree-big", REGCACHE_RBTREE, REGMAP_ENDIAN_BIG }, + { "maple-little", REGCACHE_MAPLE, REGMAP_ENDIAN_LITTLE }, + { "maple-big", REGCACHE_MAPLE, REGMAP_ENDIAN_BIG }, +}; + +KUNIT_ARRAY_PARAM(raw_test_cache_types, raw_cache_types_list, raw_to_desc); + +static const struct regmap_config raw_regmap_config = { + .max_register = BLOCK_TEST_SIZE, + + .reg_format_endian = REGMAP_ENDIAN_LITTLE, + .reg_bits = 16, + .val_bits = 16, +}; + +static struct regmap *gen_raw_regmap(struct regmap_config *config, + struct raw_test_types *test_type, + struct regmap_ram_data **data) +{ + u16 *buf; + struct regmap *ret; + size_t size = (config->max_register + 1) * config->reg_bits / 8; + int i; + struct reg_default *defaults; + + config->cache_type = test_type->cache_type; + config->val_format_endian = test_type->val_endian; + + buf = kmalloc(size, GFP_KERNEL); + if (!buf) + return ERR_PTR(-ENOMEM); + + get_random_bytes(buf, size); + + *data = kzalloc(sizeof(**data), GFP_KERNEL); + if (!(*data)) + return ERR_PTR(-ENOMEM); + (*data)->vals = (void *)buf; + + config->num_reg_defaults = config->max_register + 1; + defaults = kcalloc(config->num_reg_defaults, + sizeof(struct reg_default), + GFP_KERNEL); + if (!defaults) + return ERR_PTR(-ENOMEM); + config->reg_defaults = defaults; + + for (i = 0; i < config->num_reg_defaults; i++) { + defaults[i].reg = i; + switch (test_type->val_endian) { + case REGMAP_ENDIAN_LITTLE: + defaults[i].def = le16_to_cpu(buf[i]); + break; + case REGMAP_ENDIAN_BIG: + defaults[i].def = be16_to_cpu(buf[i]); + break; + default: + return ERR_PTR(-EINVAL); + } + } + + /* + * We use the defaults in the tests but they don't make sense + * to the core if there's no cache. + */ + if (config->cache_type == REGCACHE_NONE) + config->num_reg_defaults = 0; + + ret = regmap_init_raw_ram(config, *data); + if (IS_ERR(ret)) { + kfree(buf); + kfree(*data); + } + + return ret; +} + +static void raw_read_defaults_single(struct kunit *test) +{ + struct raw_test_types *t = (struct raw_test_types *)test->param_value; + struct regmap *map; + struct regmap_config config; + struct regmap_ram_data *data; + unsigned int rval; + int i; + + config = raw_regmap_config; + + map = gen_raw_regmap(&config, t, &data); + KUNIT_ASSERT_FALSE(test, IS_ERR(map)); + if (IS_ERR(map)) + return; + + /* Check that we can read the defaults via the API */ + for (i = 0; i < config.max_register + 1; i++) { + KUNIT_EXPECT_EQ(test, 0, regmap_read(map, i, &rval)); + KUNIT_EXPECT_EQ(test, config.reg_defaults[i].def, rval); + } + + regmap_exit(map); +} + +static void raw_read_defaults(struct kunit *test) +{ + struct raw_test_types *t = (struct raw_test_types *)test->param_value; + struct regmap *map; + struct regmap_config config; + struct regmap_ram_data *data; + u16 *rval; + u16 def; + size_t val_len; + int i; + + config = raw_regmap_config; + + map = gen_raw_regmap(&config, t, &data); + KUNIT_ASSERT_FALSE(test, IS_ERR(map)); + if (IS_ERR(map)) + return; + + val_len = sizeof(*rval) * (config.max_register + 1); + rval = kmalloc(val_len, GFP_KERNEL); + KUNIT_ASSERT_TRUE(test, rval != NULL); + if (!rval) + return; + + /* Check that we can read the defaults via the API */ + KUNIT_EXPECT_EQ(test, 0, regmap_raw_read(map, 0, rval, val_len)); + for (i = 0; i < config.max_register + 1; i++) { + def = config.reg_defaults[i].def; + if (config.val_format_endian == REGMAP_ENDIAN_BIG) { + KUNIT_EXPECT_EQ(test, def, be16_to_cpu(rval[i])); + } else { + KUNIT_EXPECT_EQ(test, def, le16_to_cpu(rval[i])); + } + } + + kfree(rval); + regmap_exit(map); +} + +static void raw_write_read_single(struct kunit *test) +{ + struct raw_test_types *t = (struct raw_test_types *)test->param_value; + struct regmap *map; + struct regmap_config config; + struct regmap_ram_data *data; + u16 val; + unsigned int rval; + + config = raw_regmap_config; + + map = gen_raw_regmap(&config, t, &data); + KUNIT_ASSERT_FALSE(test, IS_ERR(map)); + if (IS_ERR(map)) + return; + + get_random_bytes(&val, sizeof(val)); + + /* If we write a value to a register we can read it back */ + KUNIT_EXPECT_EQ(test, 0, regmap_write(map, 0, val)); + KUNIT_EXPECT_EQ(test, 0, regmap_read(map, 0, &rval)); + KUNIT_EXPECT_EQ(test, val, rval); + + regmap_exit(map); +} + +static void raw_write(struct kunit *test) +{ + struct raw_test_types *t = (struct raw_test_types *)test->param_value; + struct regmap *map; + struct regmap_config config; + struct regmap_ram_data *data; + u16 *hw_buf; + u16 val[2]; + unsigned int rval; + int i; + + config = raw_regmap_config; + + map = gen_raw_regmap(&config, t, &data); + KUNIT_ASSERT_FALSE(test, IS_ERR(map)); + if (IS_ERR(map)) + return; + + hw_buf = (u16 *)data->vals; + + get_random_bytes(&val, sizeof(val)); + + /* Do a raw write */ + KUNIT_EXPECT_EQ(test, 0, regmap_raw_write(map, 2, val, sizeof(val))); + + /* We should read back the new values, and defaults for the rest */ + for (i = 0; i < config.max_register + 1; i++) { + KUNIT_EXPECT_EQ(test, 0, regmap_read(map, i, &rval)); + + switch (i) { + case 2: + case 3: + if (config.val_format_endian == REGMAP_ENDIAN_BIG) { + KUNIT_EXPECT_EQ(test, rval, + be16_to_cpu(val[i % 2])); + } else { + KUNIT_EXPECT_EQ(test, rval, + le16_to_cpu(val[i % 2])); + } + break; + default: + KUNIT_EXPECT_EQ(test, config.reg_defaults[i].def, rval); + break; + } + } + + /* The values should appear in the "hardware" */ + KUNIT_EXPECT_MEMEQ(test, &hw_buf[2], val, sizeof(val)); + + regmap_exit(map); +} + +static void raw_sync(struct kunit *test) +{ + struct raw_test_types *t = (struct raw_test_types *)test->param_value; + struct regmap *map; + struct regmap_config config; + struct regmap_ram_data *data; + u16 val[2]; + u16 *hw_buf; + unsigned int rval; + int i; + + config = raw_regmap_config; + + map = gen_raw_regmap(&config, t, &data); + KUNIT_ASSERT_FALSE(test, IS_ERR(map)); + if (IS_ERR(map)) + return; + + hw_buf = (u16 *)data->vals; + + get_random_bytes(&val, sizeof(val)); + + /* Do a regular write and a raw write in cache only mode */ + regcache_cache_only(map, true); + KUNIT_EXPECT_EQ(test, 0, regmap_raw_write(map, 2, val, sizeof(val))); + if (config.val_format_endian == REGMAP_ENDIAN_BIG) + KUNIT_EXPECT_EQ(test, 0, regmap_write(map, 6, + be16_to_cpu(val[0]))); + else + KUNIT_EXPECT_EQ(test, 0, regmap_write(map, 6, + le16_to_cpu(val[0]))); + + /* We should read back the new values, and defaults for the rest */ + for (i = 0; i < config.max_register + 1; i++) { + KUNIT_EXPECT_EQ(test, 0, regmap_read(map, i, &rval)); + + switch (i) { + case 2: + case 3: + case 6: + if (config.val_format_endian == REGMAP_ENDIAN_BIG) { + KUNIT_EXPECT_EQ(test, rval, + be16_to_cpu(val[i % 2])); + } else { + KUNIT_EXPECT_EQ(test, rval, + le16_to_cpu(val[i % 2])); + } + break; + default: + KUNIT_EXPECT_EQ(test, config.reg_defaults[i].def, rval); + break; + } + } + + /* The values should not appear in the "hardware" */ + KUNIT_EXPECT_MEMNEQ(test, &hw_buf[2], val, sizeof(val)); + KUNIT_EXPECT_MEMNEQ(test, &hw_buf[6], val, sizeof(u16)); + + for (i = 0; i < config.max_register + 1; i++) + data->written[i] = false; + + /* Do the sync */ + regcache_cache_only(map, false); + regcache_mark_dirty(map); + KUNIT_EXPECT_EQ(test, 0, regcache_sync(map)); + + /* The values should now appear in the "hardware" */ + KUNIT_EXPECT_MEMEQ(test, &hw_buf[2], val, sizeof(val)); + KUNIT_EXPECT_MEMEQ(test, &hw_buf[6], val, sizeof(u16)); + + regmap_exit(map); +} + static struct kunit_case regmap_test_cases[] = { KUNIT_CASE_PARAM(basic_read_write, regcache_types_gen_params), KUNIT_CASE_PARAM(bulk_write, regcache_types_gen_params), KUNIT_CASE_PARAM(bulk_read, regcache_types_gen_params), + KUNIT_CASE_PARAM(write_readonly, regcache_types_gen_params), + KUNIT_CASE_PARAM(read_writeonly, regcache_types_gen_params), KUNIT_CASE_PARAM(reg_defaults, regcache_types_gen_params), KUNIT_CASE_PARAM(reg_defaults_read_dev, regcache_types_gen_params), KUNIT_CASE_PARAM(register_patch, regcache_types_gen_params), @@ -725,8 +1169,15 @@ static struct kunit_case regmap_test_cases[] = { KUNIT_CASE_PARAM(cache_bypass, real_cache_types_gen_params), KUNIT_CASE_PARAM(cache_sync, real_cache_types_gen_params), KUNIT_CASE_PARAM(cache_sync_defaults, real_cache_types_gen_params), + KUNIT_CASE_PARAM(cache_sync_readonly, real_cache_types_gen_params), KUNIT_CASE_PARAM(cache_sync_patch, real_cache_types_gen_params), KUNIT_CASE_PARAM(cache_drop, sparse_cache_types_gen_params), + + KUNIT_CASE_PARAM(raw_read_defaults_single, raw_test_types_gen_params), + KUNIT_CASE_PARAM(raw_read_defaults, raw_test_types_gen_params), + KUNIT_CASE_PARAM(raw_write_read_single, raw_test_types_gen_params), + KUNIT_CASE_PARAM(raw_write, raw_test_types_gen_params), + KUNIT_CASE_PARAM(raw_sync, raw_test_cache_types_gen_params), {} }; diff --git a/drivers/base/regmap/regmap-mmio.c b/drivers/base/regmap/regmap-mmio.c index 3ccdd86a97e77609fa747499b45228de3c804cd1..8132b5c101c42e06958635564f465c6642833235 100644 --- a/drivers/base/regmap/regmap-mmio.c +++ b/drivers/base/regmap/regmap-mmio.c @@ -448,7 +448,7 @@ static struct regmap_mmio_context *regmap_mmio_gen_context(struct device *dev, if (min_stride < 0) return ERR_PTR(min_stride); - if (config->reg_stride < min_stride) + if (config->reg_stride && config->reg_stride < min_stride) return ERR_PTR(-EINVAL); if (config->use_relaxed_mmio && config->io_port) diff --git a/drivers/base/regmap/regmap-raw-ram.c b/drivers/base/regmap/regmap-raw-ram.c new file mode 100644 index 0000000000000000000000000000000000000000..c9b800885f3ba4f2cd19db5a4f1b121023ac203e --- /dev/null +++ b/drivers/base/regmap/regmap-raw-ram.c @@ -0,0 +1,133 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Register map access API - Memory region with raw access +// +// This is intended for testing only +// +// Copyright (c) 2023, Arm Ltd + +#include +#include +#include +#include +#include +#include +#include + +#include "internal.h" + +static unsigned int decode_reg(enum regmap_endian endian, const void *reg) +{ + const u16 *r = reg; + + if (endian == REGMAP_ENDIAN_BIG) + return be16_to_cpu(*r); + else + return le16_to_cpu(*r); +} + +static int regmap_raw_ram_gather_write(void *context, + const void *reg, size_t reg_len, + const void *val, size_t val_len) +{ + struct regmap_ram_data *data = context; + unsigned int r; + u16 *our_buf = (u16 *)data->vals; + int i; + + if (reg_len != 2) + return -EINVAL; + if (val_len % 2) + return -EINVAL; + + r = decode_reg(data->reg_endian, reg); + memcpy(&our_buf[r], val, val_len); + + for (i = 0; i < val_len / 2; i++) + data->written[r + i] = true; + + return 0; +} + +static int regmap_raw_ram_write(void *context, const void *data, size_t count) +{ + return regmap_raw_ram_gather_write(context, data, 2, + data + 2, count - 2); +} + +static int regmap_raw_ram_read(void *context, + const void *reg, size_t reg_len, + void *val, size_t val_len) +{ + struct regmap_ram_data *data = context; + unsigned int r; + u16 *our_buf = (u16 *)data->vals; + int i; + + if (reg_len != 2) + return -EINVAL; + if (val_len % 2) + return -EINVAL; + + r = decode_reg(data->reg_endian, reg); + memcpy(val, &our_buf[r], val_len); + + for (i = 0; i < val_len / 2; i++) + data->read[r + i] = true; + + return 0; +} + +static void regmap_raw_ram_free_context(void *context) +{ + struct regmap_ram_data *data = context; + + kfree(data->vals); + kfree(data->read); + kfree(data->written); + kfree(data); +} + +static const struct regmap_bus regmap_raw_ram = { + .fast_io = true, + .write = regmap_raw_ram_write, + .gather_write = regmap_raw_ram_gather_write, + .read = regmap_raw_ram_read, + .free_context = regmap_raw_ram_free_context, +}; + +struct regmap *__regmap_init_raw_ram(const struct regmap_config *config, + struct regmap_ram_data *data, + struct lock_class_key *lock_key, + const char *lock_name) +{ + struct regmap *map; + + if (config->reg_bits != 16) + return ERR_PTR(-EINVAL); + + if (!config->max_register) { + pr_crit("No max_register specified for RAM regmap\n"); + return ERR_PTR(-EINVAL); + } + + data->read = kcalloc(sizeof(bool), config->max_register + 1, + GFP_KERNEL); + if (!data->read) + return ERR_PTR(-ENOMEM); + + data->written = kcalloc(sizeof(bool), config->max_register + 1, + GFP_KERNEL); + if (!data->written) + return ERR_PTR(-ENOMEM); + + data->reg_endian = config->reg_format_endian; + + map = __regmap_init(NULL, ®map_raw_ram, data, config, + lock_key, lock_name); + + return map; +} +EXPORT_SYMBOL_GPL(__regmap_init_raw_ram); + +MODULE_LICENSE("GPL v2"); diff --git a/drivers/base/regmap/regmap-spi-avmm.c b/drivers/base/regmap/regmap-spi-avmm.c index 4c2b94b3e30be588cac339d30a21b3b01ea879ff..6af692844c19681832b8580095d93301cd29d990 100644 --- a/drivers/base/regmap/regmap-spi-avmm.c +++ b/drivers/base/regmap/regmap-spi-avmm.c @@ -660,7 +660,7 @@ static const struct regmap_bus regmap_spi_avmm_bus = { .reg_format_endian_default = REGMAP_ENDIAN_NATIVE, .val_format_endian_default = REGMAP_ENDIAN_NATIVE, .max_raw_read = SPI_AVMM_VAL_SIZE * MAX_READ_CNT, - .max_raw_write = SPI_AVMM_VAL_SIZE * MAX_WRITE_CNT, + .max_raw_write = SPI_AVMM_REG_SIZE + SPI_AVMM_VAL_SIZE * MAX_WRITE_CNT, .free_context = spi_avmm_bridge_ctx_free, }; diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c index fa2d3fba6ac9d1d9df6f3a8ef63506c16f1e0cb0..89a7f1c459c1ad0319c0cb757266c3330d4f1b50 100644 --- a/drivers/base/regmap/regmap.c +++ b/drivers/base/regmap/regmap.c @@ -2983,6 +2983,11 @@ int regmap_raw_read(struct regmap *map, unsigned int reg, void *val, size_t chunk_count, chunk_bytes; size_t chunk_regs = val_count; + if (!map->cache_bypass && map->cache_only) { + ret = -EBUSY; + goto out; + } + if (!map->read) { ret = -ENOTSUPP; goto out; @@ -3078,18 +3083,19 @@ int regmap_noinc_read(struct regmap *map, unsigned int reg, goto out_unlock; } + /* + * We have not defined the FIFO semantics for cache, as the + * cache is just one value deep. Should we return the last + * written value? Just avoid this by always reading the FIFO + * even when using cache. Cache only will not work. + */ + if (!map->cache_bypass && map->cache_only) { + ret = -EBUSY; + goto out_unlock; + } + /* Use the accelerated operation if we can */ if (map->bus->reg_noinc_read) { - /* - * We have not defined the FIFO semantics for cache, as the - * cache is just one value deep. Should we return the last - * written value? Just avoid this by always reading the FIFO - * even when using cache. Cache only will not work. - */ - if (map->cache_only) { - ret = -EBUSY; - goto out_unlock; - } ret = regmap_noinc_readwrite(map, reg, val, val_len, false); goto out_unlock; } @@ -3273,7 +3279,7 @@ static int _regmap_update_bits(struct regmap *map, unsigned int reg, tmp = orig & ~mask; tmp |= val & mask; - if (force_write || (tmp != orig)) { + if (force_write || (tmp != orig) || map->force_write_field) { ret = _regmap_write(map, reg, tmp); if (ret == 0 && change) *change = true; diff --git a/drivers/block/amiflop.c b/drivers/block/amiflop.c index 4c8b2ba579ee6d8916f8c0299f45f3c64ff7fb10..e460c9799d9f352fe850aa330ca5d3651646512a 100644 --- a/drivers/block/amiflop.c +++ b/drivers/block/amiflop.c @@ -1532,7 +1532,7 @@ static int fd_getgeo(struct block_device *bdev, struct hd_geometry *geo) return 0; } -static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode, +static int fd_locked_ioctl(struct block_device *bdev, blk_mode_t mode, unsigned int cmd, unsigned long param) { struct amiga_floppy_struct *p = bdev->bd_disk->private_data; @@ -1607,7 +1607,7 @@ static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode, return 0; } -static int fd_ioctl(struct block_device *bdev, fmode_t mode, +static int fd_ioctl(struct block_device *bdev, blk_mode_t mode, unsigned int cmd, unsigned long param) { int ret; @@ -1654,10 +1654,10 @@ static void fd_probe(int dev) * /dev/PS0 etc), and disallows simultaneous access to the same * drive with different device numbers. */ -static int floppy_open(struct block_device *bdev, fmode_t mode) +static int floppy_open(struct gendisk *disk, blk_mode_t mode) { - int drive = MINOR(bdev->bd_dev) & 3; - int system = (MINOR(bdev->bd_dev) & 4) >> 2; + int drive = disk->first_minor & 3; + int system = (disk->first_minor & 4) >> 2; int old_dev; unsigned long flags; @@ -1673,10 +1673,9 @@ static int floppy_open(struct block_device *bdev, fmode_t mode) mutex_unlock(&amiflop_mutex); return -ENXIO; } - - if (mode & (FMODE_READ|FMODE_WRITE)) { - bdev_check_media_change(bdev); - if (mode & FMODE_WRITE) { + if (mode & (BLK_OPEN_READ | BLK_OPEN_WRITE)) { + disk_check_media_change(disk); + if (mode & BLK_OPEN_WRITE) { int wrprot; get_fdc(drive); @@ -1691,7 +1690,6 @@ static int floppy_open(struct block_device *bdev, fmode_t mode) } } } - local_irq_save(flags); fd_ref[drive]++; fd_device[drive] = system; @@ -1709,7 +1707,7 @@ static int floppy_open(struct block_device *bdev, fmode_t mode) return 0; } -static void floppy_release(struct gendisk *disk, fmode_t mode) +static void floppy_release(struct gendisk *disk) { struct amiga_floppy_struct *p = disk->private_data; int drive = p - unit; diff --git a/drivers/block/aoe/aoeblk.c b/drivers/block/aoe/aoeblk.c index 128722cf6c3cad69dede6a2b3f3748f0ed5e00b8..cf6883756155a316e897a59d3cd083d1d981524d 100644 --- a/drivers/block/aoe/aoeblk.c +++ b/drivers/block/aoe/aoeblk.c @@ -204,9 +204,9 @@ aoedisk_rm_debugfs(struct aoedev *d) } static int -aoeblk_open(struct block_device *bdev, fmode_t mode) +aoeblk_open(struct gendisk *disk, blk_mode_t mode) { - struct aoedev *d = bdev->bd_disk->private_data; + struct aoedev *d = disk->private_data; ulong flags; if (!virt_addr_valid(d)) { @@ -232,7 +232,7 @@ aoeblk_open(struct block_device *bdev, fmode_t mode) } static void -aoeblk_release(struct gendisk *disk, fmode_t mode) +aoeblk_release(struct gendisk *disk) { struct aoedev *d = disk->private_data; ulong flags; @@ -285,7 +285,7 @@ aoeblk_getgeo(struct block_device *bdev, struct hd_geometry *geo) } static int -aoeblk_ioctl(struct block_device *bdev, fmode_t mode, uint cmd, ulong arg) +aoeblk_ioctl(struct block_device *bdev, blk_mode_t mode, uint cmd, ulong arg) { struct aoedev *d; diff --git a/drivers/block/aoe/aoechr.c b/drivers/block/aoe/aoechr.c index 4c666f72203f1428f203dc90fab1b845e52ee760..a42c4bcc85ba3555dbb0bf06d046e27f6b65ed62 100644 --- a/drivers/block/aoe/aoechr.c +++ b/drivers/block/aoe/aoechr.c @@ -49,7 +49,7 @@ static int emsgs_head_idx, emsgs_tail_idx; static struct completion emsgs_comp; static spinlock_t emsgs_lock; static int nblocked_emsgs_readers; -static struct class *aoe_class; + static struct aoe_chardev chardevs[] = { { MINOR_ERR, "err" }, { MINOR_DISCOVER, "discover" }, @@ -58,6 +58,16 @@ static struct aoe_chardev chardevs[] = { { MINOR_FLUSH, "flush" }, }; +static char *aoe_devnode(const struct device *dev, umode_t *mode) +{ + return kasprintf(GFP_KERNEL, "etherd/%s", dev_name(dev)); +} + +static const struct class aoe_class = { + .name = "aoe", + .devnode = aoe_devnode, +}; + static int discover(void) { @@ -273,11 +283,6 @@ static const struct file_operations aoe_fops = { .llseek = noop_llseek, }; -static char *aoe_devnode(const struct device *dev, umode_t *mode) -{ - return kasprintf(GFP_KERNEL, "etherd/%s", dev_name(dev)); -} - int __init aoechr_init(void) { @@ -290,15 +295,14 @@ aoechr_init(void) } init_completion(&emsgs_comp); spin_lock_init(&emsgs_lock); - aoe_class = class_create("aoe"); - if (IS_ERR(aoe_class)) { + n = class_register(&aoe_class); + if (n) { unregister_chrdev(AOE_MAJOR, "aoechr"); - return PTR_ERR(aoe_class); + return n; } - aoe_class->devnode = aoe_devnode; for (i = 0; i < ARRAY_SIZE(chardevs); ++i) - device_create(aoe_class, NULL, + device_create(&aoe_class, NULL, MKDEV(AOE_MAJOR, chardevs[i].minor), NULL, chardevs[i].name); @@ -311,8 +315,8 @@ aoechr_exit(void) int i; for (i = 0; i < ARRAY_SIZE(chardevs); ++i) - device_destroy(aoe_class, MKDEV(AOE_MAJOR, chardevs[i].minor)); - class_destroy(aoe_class); + device_destroy(&aoe_class, MKDEV(AOE_MAJOR, chardevs[i].minor)); + class_unregister(&aoe_class); unregister_chrdev(AOE_MAJOR, "aoechr"); } diff --git a/drivers/block/ataflop.c b/drivers/block/ataflop.c index 9deb4df6bdb8b2cd58261a6bc899281fd539db7c..cd738cab725f39cb578661d58ba62a168eed084a 100644 --- a/drivers/block/ataflop.c +++ b/drivers/block/ataflop.c @@ -442,13 +442,13 @@ static void fd_times_out(struct timer_list *unused); static void finish_fdc( void ); static void finish_fdc_done( int dummy ); static void setup_req_params( int drive ); -static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode, unsigned int - cmd, unsigned long param); +static int fd_locked_ioctl(struct block_device *bdev, blk_mode_t mode, + unsigned int cmd, unsigned long param); static void fd_probe( int drive ); static int fd_test_drive_present( int drive ); static void config_types( void ); -static int floppy_open(struct block_device *bdev, fmode_t mode); -static void floppy_release(struct gendisk *disk, fmode_t mode); +static int floppy_open(struct gendisk *disk, blk_mode_t mode); +static void floppy_release(struct gendisk *disk); /************************* End of Prototypes **************************/ @@ -1581,7 +1581,7 @@ static blk_status_t ataflop_queue_rq(struct blk_mq_hw_ctx *hctx, return BLK_STS_OK; } -static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode, +static int fd_locked_ioctl(struct block_device *bdev, blk_mode_t mode, unsigned int cmd, unsigned long param) { struct gendisk *disk = bdev->bd_disk; @@ -1760,15 +1760,15 @@ static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode, /* invalidate the buffer track to force a reread */ BufferDrive = -1; set_bit(drive, &fake_change); - if (bdev_check_media_change(bdev)) - floppy_revalidate(bdev->bd_disk); + if (disk_check_media_change(disk)) + floppy_revalidate(disk); return 0; default: return -EINVAL; } } -static int fd_ioctl(struct block_device *bdev, fmode_t mode, +static int fd_ioctl(struct block_device *bdev, blk_mode_t mode, unsigned int cmd, unsigned long arg) { int ret; @@ -1915,32 +1915,31 @@ static void __init config_types( void ) * drive with different device numbers. */ -static int floppy_open(struct block_device *bdev, fmode_t mode) +static int floppy_open(struct gendisk *disk, blk_mode_t mode) { - struct atari_floppy_struct *p = bdev->bd_disk->private_data; - int type = MINOR(bdev->bd_dev) >> 2; + struct atari_floppy_struct *p = disk->private_data; + int type = disk->first_minor >> 2; DPRINT(("fd_open: type=%d\n",type)); if (p->ref && p->type != type) return -EBUSY; - if (p->ref == -1 || (p->ref && mode & FMODE_EXCL)) + if (p->ref == -1 || (p->ref && mode & BLK_OPEN_EXCL)) return -EBUSY; - - if (mode & FMODE_EXCL) + if (mode & BLK_OPEN_EXCL) p->ref = -1; else p->ref++; p->type = type; - if (mode & FMODE_NDELAY) + if (mode & BLK_OPEN_NDELAY) return 0; - if (mode & (FMODE_READ|FMODE_WRITE)) { - if (bdev_check_media_change(bdev)) - floppy_revalidate(bdev->bd_disk); - if (mode & FMODE_WRITE) { + if (mode & (BLK_OPEN_READ | BLK_OPEN_WRITE)) { + if (disk_check_media_change(disk)) + floppy_revalidate(disk); + if (mode & BLK_OPEN_WRITE) { if (p->wpstat) { if (p->ref < 0) p->ref = 0; @@ -1953,18 +1952,18 @@ static int floppy_open(struct block_device *bdev, fmode_t mode) return 0; } -static int floppy_unlocked_open(struct block_device *bdev, fmode_t mode) +static int floppy_unlocked_open(struct gendisk *disk, blk_mode_t mode) { int ret; mutex_lock(&ataflop_mutex); - ret = floppy_open(bdev, mode); + ret = floppy_open(disk, mode); mutex_unlock(&ataflop_mutex); return ret; } -static void floppy_release(struct gendisk *disk, fmode_t mode) +static void floppy_release(struct gendisk *disk) { struct atari_floppy_struct *p = disk->private_data; mutex_lock(&ataflop_mutex); diff --git a/drivers/block/brd.c b/drivers/block/brd.c index bcad9b926b0cd3a91ffab5089aaf6538669cc0f8..970bd6ff38c491a610f65026817f5c076aed8285 100644 --- a/drivers/block/brd.c +++ b/drivers/block/brd.c @@ -19,7 +19,7 @@ #include #include #include -#include +#include #include #include #include @@ -28,7 +28,7 @@ #include /* - * Each block ramdisk device has a radix_tree brd_pages of pages that stores + * Each block ramdisk device has a xarray brd_pages of pages that stores * the pages containing the block device's contents. A brd page's ->index is * its offset in PAGE_SIZE units. This is similar to, but in no way connected * with, the kernel's pagecache or buffer cache (which sit above our block @@ -40,11 +40,9 @@ struct brd_device { struct list_head brd_list; /* - * Backing store of pages and lock to protect it. This is the contents - * of the block device. + * Backing store of pages. This is the contents of the block device. */ - spinlock_t brd_lock; - struct radix_tree_root brd_pages; + struct xarray brd_pages; u64 brd_nr_pages; }; @@ -56,21 +54,8 @@ static struct page *brd_lookup_page(struct brd_device *brd, sector_t sector) pgoff_t idx; struct page *page; - /* - * The page lifetime is protected by the fact that we have opened the - * device node -- brd pages will never be deleted under us, so we - * don't need any further locking or refcounting. - * - * This is strictly true for the radix-tree nodes as well (ie. we - * don't actually need the rcu_read_lock()), however that is not a - * documented feature of the radix-tree API so it is better to be - * safe here (we don't have total exclusion from radix tree updates - * here, only deletes). - */ - rcu_read_lock(); idx = sector >> PAGE_SECTORS_SHIFT; /* sector to page index */ - page = radix_tree_lookup(&brd->brd_pages, idx); - rcu_read_unlock(); + page = xa_load(&brd->brd_pages, idx); BUG_ON(page && page->index != idx); @@ -83,7 +68,7 @@ static struct page *brd_lookup_page(struct brd_device *brd, sector_t sector) static int brd_insert_page(struct brd_device *brd, sector_t sector, gfp_t gfp) { pgoff_t idx; - struct page *page; + struct page *page, *cur; int ret = 0; page = brd_lookup_page(brd, sector); @@ -94,71 +79,42 @@ static int brd_insert_page(struct brd_device *brd, sector_t sector, gfp_t gfp) if (!page) return -ENOMEM; - if (radix_tree_maybe_preload(gfp)) { - __free_page(page); - return -ENOMEM; - } + xa_lock(&brd->brd_pages); - spin_lock(&brd->brd_lock); idx = sector >> PAGE_SECTORS_SHIFT; page->index = idx; - if (radix_tree_insert(&brd->brd_pages, idx, page)) { + + cur = __xa_cmpxchg(&brd->brd_pages, idx, NULL, page, gfp); + + if (unlikely(cur)) { __free_page(page); - page = radix_tree_lookup(&brd->brd_pages, idx); - if (!page) - ret = -ENOMEM; - else if (page->index != idx) + ret = xa_err(cur); + if (!ret && (cur->index != idx)) ret = -EIO; } else { brd->brd_nr_pages++; } - spin_unlock(&brd->brd_lock); - radix_tree_preload_end(); + xa_unlock(&brd->brd_pages); + return ret; } /* - * Free all backing store pages and radix tree. This must only be called when + * Free all backing store pages and xarray. This must only be called when * there are no other users of the device. */ -#define FREE_BATCH 16 static void brd_free_pages(struct brd_device *brd) { - unsigned long pos = 0; - struct page *pages[FREE_BATCH]; - int nr_pages; - - do { - int i; - - nr_pages = radix_tree_gang_lookup(&brd->brd_pages, - (void **)pages, pos, FREE_BATCH); - - for (i = 0; i < nr_pages; i++) { - void *ret; - - BUG_ON(pages[i]->index < pos); - pos = pages[i]->index; - ret = radix_tree_delete(&brd->brd_pages, pos); - BUG_ON(!ret || ret != pages[i]); - __free_page(pages[i]); - } - - pos++; + struct page *page; + pgoff_t idx; - /* - * It takes 3.4 seconds to remove 80GiB ramdisk. - * So, we need cond_resched to avoid stalling the CPU. - */ + xa_for_each(&brd->brd_pages, idx, page) { + __free_page(page); cond_resched(); + } - /* - * This assumes radix_tree_gang_lookup always returns as - * many pages as possible. If the radix-tree code changes, - * so will this have to. - */ - } while (nr_pages == FREE_BATCH); + xa_destroy(&brd->brd_pages); } /* @@ -372,8 +328,7 @@ static int brd_alloc(int i) brd->brd_number = i; list_add_tail(&brd->brd_list, &brd_devices); - spin_lock_init(&brd->brd_lock); - INIT_RADIX_TREE(&brd->brd_pages, GFP_ATOMIC); + xa_init(&brd->brd_pages); snprintf(buf, DISK_NAME_LEN, "ram%d", i); if (!IS_ERR_OR_NULL(brd_debugfs_dir)) diff --git a/drivers/block/drbd/drbd_bitmap.c b/drivers/block/drbd/drbd_bitmap.c index 6ac8c54b44c75a71edc97359f8110d0f3c0786e0..85ca000a05646926fddc4c9186dcf19aa214453e 100644 --- a/drivers/block/drbd/drbd_bitmap.c +++ b/drivers/block/drbd/drbd_bitmap.c @@ -1043,9 +1043,7 @@ static void bm_page_io_async(struct drbd_bm_aio_ctx *ctx, int page_nr) __must_ho bio = bio_alloc_bioset(device->ldev->md_bdev, 1, op, GFP_NOIO, &drbd_md_io_bio_set); bio->bi_iter.bi_sector = on_disk_sector; - /* bio_add_page of a single page to an empty bio will always succeed, - * according to api. Do we want to assert that? */ - bio_add_page(bio, page, len, 0); + __bio_add_page(bio, page, len, 0); bio->bi_private = ctx; bio->bi_end_io = drbd_bm_endio; diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index 83987e7a5ef275846d1fd2909853473de5f5a661..79ab532aabafbaf2089922c4b387e1dcc0a7c72a 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c @@ -37,7 +37,6 @@ #include #include #include -#define __KERNEL_SYSCALLS__ #include #include #include @@ -50,8 +49,8 @@ #include "drbd_debugfs.h" static DEFINE_MUTEX(drbd_main_mutex); -static int drbd_open(struct block_device *bdev, fmode_t mode); -static void drbd_release(struct gendisk *gd, fmode_t mode); +static int drbd_open(struct gendisk *disk, blk_mode_t mode); +static void drbd_release(struct gendisk *gd); static void md_sync_timer_fn(struct timer_list *t); static int w_bitmap_io(struct drbd_work *w, int unused); @@ -1540,6 +1539,8 @@ static int _drbd_send_page(struct drbd_peer_device *peer_device, struct page *pa int offset, size_t size, unsigned msg_flags) { struct socket *socket = peer_device->connection->data.socket; + struct msghdr msg = { .msg_flags = msg_flags, }; + struct bio_vec bvec; int len = size; int err = -EIO; @@ -1549,15 +1550,17 @@ static int _drbd_send_page(struct drbd_peer_device *peer_device, struct page *pa * put_page(); and would cause either a VM_BUG directly, or * __page_cache_release a page that would actually still be referenced * by someone, leading to some obscure delayed Oops somewhere else. */ - if (drbd_disable_sendpage || !sendpage_ok(page)) - return _drbd_no_send_page(peer_device, page, offset, size, msg_flags); + if (!drbd_disable_sendpage && sendpage_ok(page)) + msg.msg_flags |= MSG_NOSIGNAL | MSG_SPLICE_PAGES; - msg_flags |= MSG_NOSIGNAL; drbd_update_congested(peer_device->connection); do { int sent; - sent = socket->ops->sendpage(socket, page, offset, len, msg_flags); + bvec_set_page(&bvec, page, offset, len); + iov_iter_bvec(&msg.msg_iter, ITER_SOURCE, &bvec, 1, len); + + sent = sock_sendmsg(socket, &msg); if (sent <= 0) { if (sent == -EAGAIN) { if (we_should_drop_the_connection(peer_device->connection, socket)) @@ -1883,9 +1886,9 @@ int drbd_send_all(struct drbd_connection *connection, struct socket *sock, void return 0; } -static int drbd_open(struct block_device *bdev, fmode_t mode) +static int drbd_open(struct gendisk *disk, blk_mode_t mode) { - struct drbd_device *device = bdev->bd_disk->private_data; + struct drbd_device *device = disk->private_data; unsigned long flags; int rv = 0; @@ -1895,7 +1898,7 @@ static int drbd_open(struct block_device *bdev, fmode_t mode) * and no race with updating open_cnt */ if (device->state.role != R_PRIMARY) { - if (mode & FMODE_WRITE) + if (mode & BLK_OPEN_WRITE) rv = -EROFS; else if (!drbd_allow_oos) rv = -EMEDIUMTYPE; @@ -1909,9 +1912,10 @@ static int drbd_open(struct block_device *bdev, fmode_t mode) return rv; } -static void drbd_release(struct gendisk *gd, fmode_t mode) +static void drbd_release(struct gendisk *gd) { struct drbd_device *device = gd->private_data; + mutex_lock(&drbd_main_mutex); device->open_cnt--; mutex_unlock(&drbd_main_mutex); diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c index 1a5d3d72d91d272fa7942a1619e16f10394e6761..cddae6f4b00fea7bfb62cdde86bdb4195b8d7de9 100644 --- a/drivers/block/drbd/drbd_nl.c +++ b/drivers/block/drbd/drbd_nl.c @@ -1640,8 +1640,8 @@ static struct block_device *open_backing_dev(struct drbd_device *device, struct block_device *bdev; int err = 0; - bdev = blkdev_get_by_path(bdev_path, - FMODE_READ | FMODE_WRITE | FMODE_EXCL, claim_ptr); + bdev = blkdev_get_by_path(bdev_path, BLK_OPEN_READ | BLK_OPEN_WRITE, + claim_ptr, NULL); if (IS_ERR(bdev)) { drbd_err(device, "open(\"%s\") failed with %ld\n", bdev_path, PTR_ERR(bdev)); @@ -1653,7 +1653,7 @@ static struct block_device *open_backing_dev(struct drbd_device *device, err = bd_link_disk_holder(bdev, device->vdisk); if (err) { - blkdev_put(bdev, FMODE_READ | FMODE_WRITE | FMODE_EXCL); + blkdev_put(bdev, claim_ptr); drbd_err(device, "bd_link_disk_holder(\"%s\", ...) failed with %d\n", bdev_path, err); bdev = ERR_PTR(err); @@ -1695,13 +1695,13 @@ static int open_backing_devices(struct drbd_device *device, } static void close_backing_dev(struct drbd_device *device, struct block_device *bdev, - bool do_bd_unlink) + void *claim_ptr, bool do_bd_unlink) { if (!bdev) return; if (do_bd_unlink) bd_unlink_disk_holder(bdev, device->vdisk); - blkdev_put(bdev, FMODE_READ | FMODE_WRITE | FMODE_EXCL); + blkdev_put(bdev, claim_ptr); } void drbd_backing_dev_free(struct drbd_device *device, struct drbd_backing_dev *ldev) @@ -1709,8 +1709,11 @@ void drbd_backing_dev_free(struct drbd_device *device, struct drbd_backing_dev * if (ldev == NULL) return; - close_backing_dev(device, ldev->md_bdev, ldev->md_bdev != ldev->backing_bdev); - close_backing_dev(device, ldev->backing_bdev, true); + close_backing_dev(device, ldev->md_bdev, + ldev->md.meta_dev_idx < 0 ? + (void *)device : (void *)drbd_m_holder, + ldev->md_bdev != ldev->backing_bdev); + close_backing_dev(device, ldev->backing_bdev, device, true); kfree(ldev->disk_conf); kfree(ldev); @@ -2126,8 +2129,11 @@ int drbd_adm_attach(struct sk_buff *skb, struct genl_info *info) fail: conn_reconfig_done(connection); if (nbc) { - close_backing_dev(device, nbc->md_bdev, nbc->md_bdev != nbc->backing_bdev); - close_backing_dev(device, nbc->backing_bdev, true); + close_backing_dev(device, nbc->md_bdev, + nbc->disk_conf->meta_dev_idx < 0 ? + (void *)device : (void *)drbd_m_holder, + nbc->md_bdev != nbc->backing_bdev); + close_backing_dev(device, nbc->backing_bdev, device, true); kfree(nbc); } kfree(new_disk_conf); diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index 8c2bc47de4735e84d6afd5b66c67875f7584a52e..0c9f54197768d6db507cb8392c8b45ea5eef92d2 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c @@ -27,7 +27,6 @@ #include #include #include -#define __KERNEL_SYSCALLS__ #include #include #include diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index cec2c20f5e59d3b45b886cf4497e6af8fd4f416d..2db9b186b977ac61bd2e826e80b5ebee54906da9 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -402,7 +402,7 @@ static struct floppy_drive_struct drive_state[N_DRIVE]; static struct floppy_write_errors write_errors[N_DRIVE]; static struct timer_list motor_off_timer[N_DRIVE]; static struct blk_mq_tag_set tag_sets[N_DRIVE]; -static struct block_device *opened_bdev[N_DRIVE]; +static struct gendisk *opened_disk[N_DRIVE]; static DEFINE_MUTEX(open_lock); static struct floppy_raw_cmd *raw_cmd, default_raw_cmd; @@ -3210,13 +3210,13 @@ static int floppy_raw_cmd_ioctl(int type, int drive, int cmd, #endif -static int invalidate_drive(struct block_device *bdev) +static int invalidate_drive(struct gendisk *disk) { /* invalidate the buffer track to force a reread */ - set_bit((long)bdev->bd_disk->private_data, &fake_change); + set_bit((long)disk->private_data, &fake_change); process_fd_request(); - if (bdev_check_media_change(bdev)) - floppy_revalidate(bdev->bd_disk); + if (disk_check_media_change(disk)) + floppy_revalidate(disk); return 0; } @@ -3251,10 +3251,11 @@ static int set_geometry(unsigned int cmd, struct floppy_struct *g, floppy_type[type].size + 1; process_fd_request(); for (cnt = 0; cnt < N_DRIVE; cnt++) { - struct block_device *bdev = opened_bdev[cnt]; - if (!bdev || ITYPE(drive_state[cnt].fd_device) != type) + struct gendisk *disk = opened_disk[cnt]; + + if (!disk || ITYPE(drive_state[cnt].fd_device) != type) continue; - __invalidate_device(bdev, true); + __invalidate_device(disk->part0, true); } mutex_unlock(&open_lock); } else { @@ -3287,7 +3288,7 @@ static int set_geometry(unsigned int cmd, struct floppy_struct *g, drive_state[current_drive].maxtrack || ((user_params[drive].sect ^ oldStretch) & (FD_SWAPSIDES | FD_SECTBASEMASK))) - invalidate_drive(bdev); + invalidate_drive(bdev->bd_disk); else process_fd_request(); } @@ -3393,8 +3394,8 @@ static bool valid_floppy_drive_params(const short autodetect[FD_AUTODETECT_SIZE] return true; } -static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, - unsigned long param) +static int fd_locked_ioctl(struct block_device *bdev, blk_mode_t mode, + unsigned int cmd, unsigned long param) { int drive = (long)bdev->bd_disk->private_data; int type = ITYPE(drive_state[drive].fd_device); @@ -3427,7 +3428,8 @@ static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode, unsigned int return ret; /* permission checks */ - if (((cmd & 0x40) && !(mode & (FMODE_WRITE | FMODE_WRITE_IOCTL))) || + if (((cmd & 0x40) && + !(mode & (BLK_OPEN_WRITE | BLK_OPEN_WRITE_IOCTL))) || ((cmd & 0x80) && !capable(CAP_SYS_ADMIN))) return -EPERM; @@ -3464,7 +3466,7 @@ static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode, unsigned int current_type[drive] = NULL; floppy_sizes[drive] = MAX_DISK_SIZE << 1; drive_state[drive].keep_data = 0; - return invalidate_drive(bdev); + return invalidate_drive(bdev->bd_disk); case FDSETPRM: case FDDEFPRM: return set_geometry(cmd, &inparam.g, drive, type, bdev); @@ -3503,7 +3505,7 @@ static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode, unsigned int case FDFLUSH: if (lock_fdc(drive)) return -EINTR; - return invalidate_drive(bdev); + return invalidate_drive(bdev->bd_disk); case FDSETEMSGTRESH: drive_params[drive].max_errors.reporting = (unsigned short)(param & 0x0f); return 0; @@ -3565,7 +3567,7 @@ static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode, unsigned int return 0; } -static int fd_ioctl(struct block_device *bdev, fmode_t mode, +static int fd_ioctl(struct block_device *bdev, blk_mode_t mode, unsigned int cmd, unsigned long param) { int ret; @@ -3653,8 +3655,8 @@ struct compat_floppy_write_errors { #define FDGETFDCSTAT32 _IOR(2, 0x15, struct compat_floppy_fdc_state) #define FDWERRORGET32 _IOR(2, 0x17, struct compat_floppy_write_errors) -static int compat_set_geometry(struct block_device *bdev, fmode_t mode, unsigned int cmd, - struct compat_floppy_struct __user *arg) +static int compat_set_geometry(struct block_device *bdev, blk_mode_t mode, + unsigned int cmd, struct compat_floppy_struct __user *arg) { struct floppy_struct v; int drive, type; @@ -3663,7 +3665,7 @@ static int compat_set_geometry(struct block_device *bdev, fmode_t mode, unsigned BUILD_BUG_ON(offsetof(struct floppy_struct, name) != offsetof(struct compat_floppy_struct, name)); - if (!(mode & (FMODE_WRITE | FMODE_WRITE_IOCTL))) + if (!(mode & (BLK_OPEN_WRITE | BLK_OPEN_WRITE_IOCTL))) return -EPERM; memset(&v, 0, sizeof(struct floppy_struct)); @@ -3860,8 +3862,8 @@ static int compat_werrorget(int drive, return 0; } -static int fd_compat_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, - unsigned long param) +static int fd_compat_ioctl(struct block_device *bdev, blk_mode_t mode, + unsigned int cmd, unsigned long param) { int drive = (long)bdev->bd_disk->private_data; switch (cmd) { @@ -3962,7 +3964,7 @@ static void __init config_types(void) pr_cont("\n"); } -static void floppy_release(struct gendisk *disk, fmode_t mode) +static void floppy_release(struct gendisk *disk) { int drive = (long)disk->private_data; @@ -3973,7 +3975,7 @@ static void floppy_release(struct gendisk *disk, fmode_t mode) drive_state[drive].fd_ref = 0; } if (!drive_state[drive].fd_ref) - opened_bdev[drive] = NULL; + opened_disk[drive] = NULL; mutex_unlock(&open_lock); mutex_unlock(&floppy_mutex); } @@ -3983,9 +3985,9 @@ static void floppy_release(struct gendisk *disk, fmode_t mode) * /dev/PS0 etc), and disallows simultaneous access to the same * drive with different device numbers. */ -static int floppy_open(struct block_device *bdev, fmode_t mode) +static int floppy_open(struct gendisk *disk, blk_mode_t mode) { - int drive = (long)bdev->bd_disk->private_data; + int drive = (long)disk->private_data; int old_dev, new_dev; int try; int res = -EBUSY; @@ -3994,7 +3996,7 @@ static int floppy_open(struct block_device *bdev, fmode_t mode) mutex_lock(&floppy_mutex); mutex_lock(&open_lock); old_dev = drive_state[drive].fd_device; - if (opened_bdev[drive] && opened_bdev[drive] != bdev) + if (opened_disk[drive] && opened_disk[drive] != disk) goto out2; if (!drive_state[drive].fd_ref && (drive_params[drive].flags & FD_BROKEN_DCL)) { @@ -4004,7 +4006,7 @@ static int floppy_open(struct block_device *bdev, fmode_t mode) drive_state[drive].fd_ref++; - opened_bdev[drive] = bdev; + opened_disk[drive] = disk; res = -ENXIO; @@ -4038,7 +4040,7 @@ static int floppy_open(struct block_device *bdev, fmode_t mode) } } - new_dev = MINOR(bdev->bd_dev); + new_dev = disk->first_minor; drive_state[drive].fd_device = new_dev; set_capacity(disks[drive][ITYPE(new_dev)], floppy_sizes[new_dev]); if (old_dev != -1 && old_dev != new_dev) { @@ -4048,21 +4050,20 @@ static int floppy_open(struct block_device *bdev, fmode_t mode) if (fdc_state[FDC(drive)].rawcmd == 1) fdc_state[FDC(drive)].rawcmd = 2; - - if (!(mode & FMODE_NDELAY)) { - if (mode & (FMODE_READ|FMODE_WRITE)) { + if (!(mode & BLK_OPEN_NDELAY)) { + if (mode & (BLK_OPEN_READ | BLK_OPEN_WRITE)) { drive_state[drive].last_checked = 0; clear_bit(FD_OPEN_SHOULD_FAIL_BIT, &drive_state[drive].flags); - if (bdev_check_media_change(bdev)) - floppy_revalidate(bdev->bd_disk); + if (disk_check_media_change(disk)) + floppy_revalidate(disk); if (test_bit(FD_DISK_CHANGED_BIT, &drive_state[drive].flags)) goto out; if (test_bit(FD_OPEN_SHOULD_FAIL_BIT, &drive_state[drive].flags)) goto out; } res = -EROFS; - if ((mode & FMODE_WRITE) && + if ((mode & BLK_OPEN_WRITE) && !test_bit(FD_DISK_WRITABLE_BIT, &drive_state[drive].flags)) goto out; } @@ -4073,7 +4074,7 @@ static int floppy_open(struct block_device *bdev, fmode_t mode) drive_state[drive].fd_ref--; if (!drive_state[drive].fd_ref) - opened_bdev[drive] = NULL; + opened_disk[drive] = NULL; out2: mutex_unlock(&open_lock); mutex_unlock(&floppy_mutex); @@ -4147,7 +4148,7 @@ static int __floppy_read_block_0(struct block_device *bdev, int drive) cbdata.drive = drive; bio_init(&bio, bdev, &bio_vec, 1, REQ_OP_READ); - bio_add_page(&bio, page, block_size(bdev), 0); + __bio_add_page(&bio, page, block_size(bdev), 0); bio.bi_iter.bi_sector = 0; bio.bi_flags |= (1 << BIO_QUIET); @@ -4203,7 +4204,8 @@ static int floppy_revalidate(struct gendisk *disk) drive_state[drive].generation++; if (drive_no_geom(drive)) { /* auto-sensing */ - res = __floppy_read_block_0(opened_bdev[drive], drive); + res = __floppy_read_block_0(opened_disk[drive]->part0, + drive); } else { if (cf) poll_drive(false, FD_RAW_NEED_DISK); diff --git a/drivers/block/loop.c b/drivers/block/loop.c index bc31bb7072a2cb7294d32066f5d0aa14130349b4..37511d2b2caf7df1c2067019a1decaca4edba00a 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -990,7 +990,7 @@ loop_set_status_from_info(struct loop_device *lo, return 0; } -static int loop_configure(struct loop_device *lo, fmode_t mode, +static int loop_configure(struct loop_device *lo, blk_mode_t mode, struct block_device *bdev, const struct loop_config *config) { @@ -1014,8 +1014,8 @@ static int loop_configure(struct loop_device *lo, fmode_t mode, * If we don't hold exclusive handle for the device, upgrade to it * here to avoid changing device under exclusive owner. */ - if (!(mode & FMODE_EXCL)) { - error = bd_prepare_to_claim(bdev, loop_configure); + if (!(mode & BLK_OPEN_EXCL)) { + error = bd_prepare_to_claim(bdev, loop_configure, NULL); if (error) goto out_putf; } @@ -1050,7 +1050,7 @@ static int loop_configure(struct loop_device *lo, fmode_t mode, if (error) goto out_unlock; - if (!(file->f_mode & FMODE_WRITE) || !(mode & FMODE_WRITE) || + if (!(file->f_mode & FMODE_WRITE) || !(mode & BLK_OPEN_WRITE) || !file->f_op->write_iter) lo->lo_flags |= LO_FLAGS_READ_ONLY; @@ -1116,7 +1116,7 @@ static int loop_configure(struct loop_device *lo, fmode_t mode, if (partscan) loop_reread_partitions(lo); - if (!(mode & FMODE_EXCL)) + if (!(mode & BLK_OPEN_EXCL)) bd_abort_claiming(bdev, loop_configure); return 0; @@ -1124,7 +1124,7 @@ static int loop_configure(struct loop_device *lo, fmode_t mode, out_unlock: loop_global_unlock(lo, is_loop); out_bdev: - if (!(mode & FMODE_EXCL)) + if (!(mode & BLK_OPEN_EXCL)) bd_abort_claiming(bdev, loop_configure); out_putf: fput(file); @@ -1528,7 +1528,7 @@ static int lo_simple_ioctl(struct loop_device *lo, unsigned int cmd, return err; } -static int lo_ioctl(struct block_device *bdev, fmode_t mode, +static int lo_ioctl(struct block_device *bdev, blk_mode_t mode, unsigned int cmd, unsigned long arg) { struct loop_device *lo = bdev->bd_disk->private_data; @@ -1563,24 +1563,22 @@ static int lo_ioctl(struct block_device *bdev, fmode_t mode, return loop_clr_fd(lo); case LOOP_SET_STATUS: err = -EPERM; - if ((mode & FMODE_WRITE) || capable(CAP_SYS_ADMIN)) { + if ((mode & BLK_OPEN_WRITE) || capable(CAP_SYS_ADMIN)) err = loop_set_status_old(lo, argp); - } break; case LOOP_GET_STATUS: return loop_get_status_old(lo, argp); case LOOP_SET_STATUS64: err = -EPERM; - if ((mode & FMODE_WRITE) || capable(CAP_SYS_ADMIN)) { + if ((mode & BLK_OPEN_WRITE) || capable(CAP_SYS_ADMIN)) err = loop_set_status64(lo, argp); - } break; case LOOP_GET_STATUS64: return loop_get_status64(lo, argp); case LOOP_SET_CAPACITY: case LOOP_SET_DIRECT_IO: case LOOP_SET_BLOCK_SIZE: - if (!(mode & FMODE_WRITE) && !capable(CAP_SYS_ADMIN)) + if (!(mode & BLK_OPEN_WRITE) && !capable(CAP_SYS_ADMIN)) return -EPERM; fallthrough; default: @@ -1691,7 +1689,7 @@ loop_get_status_compat(struct loop_device *lo, return err; } -static int lo_compat_ioctl(struct block_device *bdev, fmode_t mode, +static int lo_compat_ioctl(struct block_device *bdev, blk_mode_t mode, unsigned int cmd, unsigned long arg) { struct loop_device *lo = bdev->bd_disk->private_data; @@ -1727,7 +1725,7 @@ static int lo_compat_ioctl(struct block_device *bdev, fmode_t mode, } #endif -static void lo_release(struct gendisk *disk, fmode_t mode) +static void lo_release(struct gendisk *disk) { struct loop_device *lo = disk->private_data; diff --git a/drivers/block/mtip32xx/mtip32xx.c b/drivers/block/mtip32xx/mtip32xx.c index 815d77ba63819e27da91160b06b27fee32f4b6af..b200950e8fb5f9b7c5efcb044dddf52087765e2e 100644 --- a/drivers/block/mtip32xx/mtip32xx.c +++ b/drivers/block/mtip32xx/mtip32xx.c @@ -3041,7 +3041,7 @@ static int rssd_disk_name_format(char *prefix, * structure pointer. */ static int mtip_block_ioctl(struct block_device *dev, - fmode_t mode, + blk_mode_t mode, unsigned cmd, unsigned long arg) { @@ -3079,7 +3079,7 @@ static int mtip_block_ioctl(struct block_device *dev, * structure pointer. */ static int mtip_block_compat_ioctl(struct block_device *dev, - fmode_t mode, + blk_mode_t mode, unsigned cmd, unsigned long arg) { diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index 65ecde3e2a5be810461a99cca98824dedbbbae1d..8576d696c7a22194ed25d0eb4fb2cfed381c6ce4 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -1502,7 +1502,7 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd, return -ENOTTY; } -static int nbd_ioctl(struct block_device *bdev, fmode_t mode, +static int nbd_ioctl(struct block_device *bdev, blk_mode_t mode, unsigned int cmd, unsigned long arg) { struct nbd_device *nbd = bdev->bd_disk->private_data; @@ -1553,13 +1553,13 @@ static struct nbd_config *nbd_alloc_config(void) return config; } -static int nbd_open(struct block_device *bdev, fmode_t mode) +static int nbd_open(struct gendisk *disk, blk_mode_t mode) { struct nbd_device *nbd; int ret = 0; mutex_lock(&nbd_index_mutex); - nbd = bdev->bd_disk->private_data; + nbd = disk->private_data; if (!nbd) { ret = -ENXIO; goto out; @@ -1587,17 +1587,17 @@ static int nbd_open(struct block_device *bdev, fmode_t mode) refcount_inc(&nbd->refs); mutex_unlock(&nbd->config_lock); if (max_part) - set_bit(GD_NEED_PART_SCAN, &bdev->bd_disk->state); + set_bit(GD_NEED_PART_SCAN, &disk->state); } else if (nbd_disconnected(nbd->config)) { if (max_part) - set_bit(GD_NEED_PART_SCAN, &bdev->bd_disk->state); + set_bit(GD_NEED_PART_SCAN, &disk->state); } out: mutex_unlock(&nbd_index_mutex); return ret; } -static void nbd_release(struct gendisk *disk, fmode_t mode) +static void nbd_release(struct gendisk *disk) { struct nbd_device *nbd = disk->private_data; @@ -1776,7 +1776,8 @@ static struct nbd_device *nbd_dev_add(int index, unsigned int refs) if (err == -ENOSPC) err = -EEXIST; } else { - err = idr_alloc(&nbd_index_idr, nbd, 0, 0, GFP_KERNEL); + err = idr_alloc(&nbd_index_idr, nbd, 0, + (MINORMASK >> part_shift) + 1, GFP_KERNEL); if (err >= 0) index = err; } diff --git a/drivers/block/null_blk/zoned.c b/drivers/block/null_blk/zoned.c index 635ce0648133dd28932ff5bab9447cecbf4af6ca..55c5b48bc276fe74b538d469f0db241632aee824 100644 --- a/drivers/block/null_blk/zoned.c +++ b/drivers/block/null_blk/zoned.c @@ -162,21 +162,15 @@ int null_register_zoned_dev(struct nullb *nullb) disk_set_zoned(nullb->disk, BLK_ZONED_HM); blk_queue_flag_set(QUEUE_FLAG_ZONE_RESETALL, q); blk_queue_required_elevator_features(q, ELEVATOR_F_ZBD_SEQ_WRITE); - - if (queue_is_mq(q)) { - int ret = blk_revalidate_disk_zones(nullb->disk, NULL); - - if (ret) - return ret; - } else { - blk_queue_chunk_sectors(q, dev->zone_size_sects); - nullb->disk->nr_zones = bdev_nr_zones(nullb->disk->part0); - } - + blk_queue_chunk_sectors(q, dev->zone_size_sects); + nullb->disk->nr_zones = bdev_nr_zones(nullb->disk->part0); blk_queue_max_zone_append_sectors(q, dev->zone_size_sects); disk_set_max_open_zones(nullb->disk, dev->zone_max_open); disk_set_max_active_zones(nullb->disk, dev->zone_max_active); + if (queue_is_mq(q)) + return blk_revalidate_disk_zones(nullb->disk, NULL); + return 0; } diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c index d5d7884cedd47793cfaecff23735db083ac5cff0..a1428538bda506213d750580ff9577cd4dff34fb 100644 --- a/drivers/block/pktcdvd.c +++ b/drivers/block/pktcdvd.c @@ -46,47 +46,34 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -#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 +#include + +#include #include #include -#include -#include -#include -#include -#include -#define DRIVER_NAME "pktcdvd" +#include -#define pkt_err(pd, fmt, ...) \ - pr_err("%s: " fmt, pd->name, ##__VA_ARGS__) -#define pkt_notice(pd, fmt, ...) \ - pr_notice("%s: " fmt, pd->name, ##__VA_ARGS__) -#define pkt_info(pd, fmt, ...) \ - pr_info("%s: " fmt, pd->name, ##__VA_ARGS__) - -#define pkt_dbg(level, pd, fmt, ...) \ -do { \ - if (level == 2 && PACKET_DEBUG >= 2) \ - pr_notice("%s: %s():" fmt, \ - pd->name, __func__, ##__VA_ARGS__); \ - else if (level == 1 && PACKET_DEBUG >= 1) \ - pr_notice("%s: " fmt, pd->name, ##__VA_ARGS__); \ -} while (0) +#define DRIVER_NAME "pktcdvd" #define MAX_SPEED 0xffff @@ -107,7 +94,6 @@ static struct dentry *pkt_debugfs_root = NULL; /* /sys/kernel/debug/pktcdvd */ /* forward declaration */ static int pkt_setup_dev(dev_t dev, dev_t* pkt_dev); static int pkt_remove_dev(dev_t pkt_dev); -static int pkt_seq_show(struct seq_file *m, void *p); static sector_t get_zone(sector_t sector, struct pktcdvd_device *pd) { @@ -253,15 +239,16 @@ static ssize_t congestion_off_store(struct device *dev, const char *buf, size_t len) { struct pktcdvd_device *pd = dev_get_drvdata(dev); - int val; + int val, ret; - if (sscanf(buf, "%d", &val) == 1) { - spin_lock(&pd->lock); - pd->write_congestion_off = val; - init_write_congestion_marks(&pd->write_congestion_off, - &pd->write_congestion_on); - spin_unlock(&pd->lock); - } + ret = kstrtoint(buf, 10, &val); + if (ret) + return ret; + + spin_lock(&pd->lock); + pd->write_congestion_off = val; + init_write_congestion_marks(&pd->write_congestion_off, &pd->write_congestion_on); + spin_unlock(&pd->lock); return len; } static DEVICE_ATTR_RW(congestion_off); @@ -283,15 +270,16 @@ static ssize_t congestion_on_store(struct device *dev, const char *buf, size_t len) { struct pktcdvd_device *pd = dev_get_drvdata(dev); - int val; + int val, ret; - if (sscanf(buf, "%d", &val) == 1) { - spin_lock(&pd->lock); - pd->write_congestion_on = val; - init_write_congestion_marks(&pd->write_congestion_off, - &pd->write_congestion_on); - spin_unlock(&pd->lock); - } + ret = kstrtoint(buf, 10, &val); + if (ret) + return ret; + + spin_lock(&pd->lock); + pd->write_congestion_on = val; + init_write_congestion_marks(&pd->write_congestion_off, &pd->write_congestion_on); + spin_unlock(&pd->lock); return len; } static DEVICE_ATTR_RW(congestion_on); @@ -319,7 +307,7 @@ static void pkt_sysfs_dev_new(struct pktcdvd_device *pd) if (class_is_registered(&class_pktcdvd)) { pd->dev = device_create_with_groups(&class_pktcdvd, NULL, MKDEV(0, 0), pd, pkt_groups, - "%s", pd->name); + "%s", pd->disk->disk_name); if (IS_ERR(pd->dev)) pd->dev = NULL; } @@ -349,8 +337,8 @@ static ssize_t device_map_show(const struct class *c, const struct class_attribu struct pktcdvd_device *pd = pkt_devs[idx]; if (!pd) continue; - n += sprintf(data+n, "%s %u:%u %u:%u\n", - pd->name, + n += sysfs_emit_at(data, n, "%s %u:%u %u:%u\n", + pd->disk->disk_name, MAJOR(pd->pkt_dev), MINOR(pd->pkt_dev), MAJOR(pd->bdev->bd_dev), MINOR(pd->bdev->bd_dev)); @@ -428,34 +416,92 @@ static void pkt_sysfs_cleanup(void) *******************************************************************/ -static int pkt_debugfs_seq_show(struct seq_file *m, void *p) +static void pkt_count_states(struct pktcdvd_device *pd, int *states) { - return pkt_seq_show(m, p); + struct packet_data *pkt; + int i; + + for (i = 0; i < PACKET_NUM_STATES; i++) + states[i] = 0; + + spin_lock(&pd->cdrw.active_list_lock); + list_for_each_entry(pkt, &pd->cdrw.pkt_active_list, list) { + states[pkt->state]++; + } + spin_unlock(&pd->cdrw.active_list_lock); } -static int pkt_debugfs_fops_open(struct inode *inode, struct file *file) +static int pkt_seq_show(struct seq_file *m, void *p) { - return single_open(file, pkt_debugfs_seq_show, inode->i_private); -} + struct pktcdvd_device *pd = m->private; + char *msg; + int states[PACKET_NUM_STATES]; -static const struct file_operations debug_fops = { - .open = pkt_debugfs_fops_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .owner = THIS_MODULE, -}; + seq_printf(m, "Writer %s mapped to %pg:\n", pd->disk->disk_name, pd->bdev); + + seq_printf(m, "\nSettings:\n"); + seq_printf(m, "\tpacket size:\t\t%dkB\n", pd->settings.size / 2); + + if (pd->settings.write_type == 0) + msg = "Packet"; + else + msg = "Unknown"; + seq_printf(m, "\twrite type:\t\t%s\n", msg); + + seq_printf(m, "\tpacket type:\t\t%s\n", pd->settings.fp ? "Fixed" : "Variable"); + seq_printf(m, "\tlink loss:\t\t%d\n", pd->settings.link_loss); + + seq_printf(m, "\ttrack mode:\t\t%d\n", pd->settings.track_mode); + + if (pd->settings.block_mode == PACKET_BLOCK_MODE1) + msg = "Mode 1"; + else if (pd->settings.block_mode == PACKET_BLOCK_MODE2) + msg = "Mode 2"; + else + msg = "Unknown"; + seq_printf(m, "\tblock mode:\t\t%s\n", msg); + + seq_printf(m, "\nStatistics:\n"); + seq_printf(m, "\tpackets started:\t%lu\n", pd->stats.pkt_started); + seq_printf(m, "\tpackets ended:\t\t%lu\n", pd->stats.pkt_ended); + seq_printf(m, "\twritten:\t\t%lukB\n", pd->stats.secs_w >> 1); + seq_printf(m, "\tread gather:\t\t%lukB\n", pd->stats.secs_rg >> 1); + seq_printf(m, "\tread:\t\t\t%lukB\n", pd->stats.secs_r >> 1); + + seq_printf(m, "\nMisc:\n"); + seq_printf(m, "\treference count:\t%d\n", pd->refcnt); + seq_printf(m, "\tflags:\t\t\t0x%lx\n", pd->flags); + seq_printf(m, "\tread speed:\t\t%ukB/s\n", pd->read_speed); + seq_printf(m, "\twrite speed:\t\t%ukB/s\n", pd->write_speed); + seq_printf(m, "\tstart offset:\t\t%lu\n", pd->offset); + seq_printf(m, "\tmode page offset:\t%u\n", pd->mode_offset); + + seq_printf(m, "\nQueue state:\n"); + seq_printf(m, "\tbios queued:\t\t%d\n", pd->bio_queue_size); + seq_printf(m, "\tbios pending:\t\t%d\n", atomic_read(&pd->cdrw.pending_bios)); + seq_printf(m, "\tcurrent sector:\t\t0x%llx\n", pd->current_sector); + + pkt_count_states(pd, states); + seq_printf(m, "\tstate:\t\t\ti:%d ow:%d rw:%d ww:%d rec:%d fin:%d\n", + states[0], states[1], states[2], states[3], states[4], states[5]); + + seq_printf(m, "\twrite congestion marks:\toff=%d on=%d\n", + pd->write_congestion_off, + pd->write_congestion_on); + return 0; +} +DEFINE_SHOW_ATTRIBUTE(pkt_seq); static void pkt_debugfs_dev_new(struct pktcdvd_device *pd) { if (!pkt_debugfs_root) return; - pd->dfs_d_root = debugfs_create_dir(pd->name, pkt_debugfs_root); + pd->dfs_d_root = debugfs_create_dir(pd->disk->disk_name, pkt_debugfs_root); if (!pd->dfs_d_root) return; - pd->dfs_f_info = debugfs_create_file("info", 0444, - pd->dfs_d_root, pd, &debug_fops); + pd->dfs_f_info = debugfs_create_file("info", 0444, pd->dfs_d_root, + pd, &pkt_seq_fops); } static void pkt_debugfs_dev_remove(struct pktcdvd_device *pd) @@ -484,9 +530,11 @@ static void pkt_debugfs_cleanup(void) static void pkt_bio_finished(struct pktcdvd_device *pd) { + struct device *ddev = disk_to_dev(pd->disk); + BUG_ON(atomic_read(&pd->cdrw.pending_bios) <= 0); if (atomic_dec_and_test(&pd->cdrw.pending_bios)) { - pkt_dbg(2, pd, "queue empty\n"); + dev_dbg(ddev, "queue empty\n"); atomic_set(&pd->iosched.attention, 1); wake_up(&pd->wqueue); } @@ -717,15 +765,16 @@ static const char *sense_key_string(__u8 index) static void pkt_dump_sense(struct pktcdvd_device *pd, struct packet_command *cgc) { + struct device *ddev = disk_to_dev(pd->disk); struct scsi_sense_hdr *sshdr = cgc->sshdr; if (sshdr) - pkt_err(pd, "%*ph - sense %02x.%02x.%02x (%s)\n", + dev_err(ddev, "%*ph - sense %02x.%02x.%02x (%s)\n", CDROM_PACKET_SIZE, cgc->cmd, sshdr->sense_key, sshdr->asc, sshdr->ascq, sense_key_string(sshdr->sense_key)); else - pkt_err(pd, "%*ph - no sense\n", CDROM_PACKET_SIZE, cgc->cmd); + dev_err(ddev, "%*ph - no sense\n", CDROM_PACKET_SIZE, cgc->cmd); } /* @@ -762,10 +811,8 @@ static noinline_for_stack int pkt_set_speed(struct pktcdvd_device *pd, init_cdrom_command(&cgc, NULL, 0, CGC_DATA_NONE); cgc.sshdr = &sshdr; cgc.cmd[0] = GPCMD_SET_SPEED; - cgc.cmd[2] = (read_speed >> 8) & 0xff; - cgc.cmd[3] = read_speed & 0xff; - cgc.cmd[4] = (write_speed >> 8) & 0xff; - cgc.cmd[5] = write_speed & 0xff; + put_unaligned_be16(read_speed, &cgc.cmd[2]); + put_unaligned_be16(write_speed, &cgc.cmd[4]); ret = pkt_generic_packet(pd, &cgc); if (ret) @@ -809,6 +856,7 @@ static void pkt_queue_bio(struct pktcdvd_device *pd, struct bio *bio) */ static void pkt_iosched_process_queue(struct pktcdvd_device *pd) { + struct device *ddev = disk_to_dev(pd->disk); if (atomic_read(&pd->iosched.attention) == 0) return; @@ -836,7 +884,7 @@ static void pkt_iosched_process_queue(struct pktcdvd_device *pd) need_write_seek = 0; if (need_write_seek && reads_queued) { if (atomic_read(&pd->cdrw.pending_bios) > 0) { - pkt_dbg(2, pd, "write, waiting\n"); + dev_dbg(ddev, "write, waiting\n"); break; } pkt_flush_cache(pd); @@ -845,7 +893,7 @@ static void pkt_iosched_process_queue(struct pktcdvd_device *pd) } else { if (!reads_queued && writes_queued) { if (atomic_read(&pd->cdrw.pending_bios) > 0) { - pkt_dbg(2, pd, "read, waiting\n"); + dev_dbg(ddev, "read, waiting\n"); break; } pd->iosched.writing = 1; @@ -892,25 +940,27 @@ static void pkt_iosched_process_queue(struct pktcdvd_device *pd) */ static int pkt_set_segment_merging(struct pktcdvd_device *pd, struct request_queue *q) { - if ((pd->settings.size << 9) / CD_FRAMESIZE - <= queue_max_segments(q)) { + struct device *ddev = disk_to_dev(pd->disk); + + if ((pd->settings.size << 9) / CD_FRAMESIZE <= queue_max_segments(q)) { /* * The cdrom device can handle one segment/frame */ clear_bit(PACKET_MERGE_SEGS, &pd->flags); return 0; - } else if ((pd->settings.size << 9) / PAGE_SIZE - <= queue_max_segments(q)) { + } + + if ((pd->settings.size << 9) / PAGE_SIZE <= queue_max_segments(q)) { /* * We can handle this case at the expense of some extra memory * copies during write operations */ set_bit(PACKET_MERGE_SEGS, &pd->flags); return 0; - } else { - pkt_err(pd, "cdrom max_phys_segments too small\n"); - return -EIO; } + + dev_err(ddev, "cdrom max_phys_segments too small\n"); + return -EIO; } static void pkt_end_io_read(struct bio *bio) @@ -919,9 +969,8 @@ static void pkt_end_io_read(struct bio *bio) struct pktcdvd_device *pd = pkt->pd; BUG_ON(!pd); - pkt_dbg(2, pd, "bio=%p sec0=%llx sec=%llx err=%d\n", - bio, (unsigned long long)pkt->sector, - (unsigned long long)bio->bi_iter.bi_sector, bio->bi_status); + dev_dbg(disk_to_dev(pd->disk), "bio=%p sec0=%llx sec=%llx err=%d\n", + bio, pkt->sector, bio->bi_iter.bi_sector, bio->bi_status); if (bio->bi_status) atomic_inc(&pkt->io_errors); @@ -939,7 +988,7 @@ static void pkt_end_io_packet_write(struct bio *bio) struct pktcdvd_device *pd = pkt->pd; BUG_ON(!pd); - pkt_dbg(2, pd, "id=%d, err=%d\n", pkt->id, bio->bi_status); + dev_dbg(disk_to_dev(pd->disk), "id=%d, err=%d\n", pkt->id, bio->bi_status); pd->stats.pkt_ended++; @@ -955,6 +1004,7 @@ static void pkt_end_io_packet_write(struct bio *bio) */ static void pkt_gather_data(struct pktcdvd_device *pd, struct packet_data *pkt) { + struct device *ddev = disk_to_dev(pd->disk); int frames_read = 0; struct bio *bio; int f; @@ -983,8 +1033,7 @@ static void pkt_gather_data(struct pktcdvd_device *pd, struct packet_data *pkt) spin_unlock(&pkt->lock); if (pkt->cache_valid) { - pkt_dbg(2, pd, "zone %llx cached\n", - (unsigned long long)pkt->sector); + dev_dbg(ddev, "zone %llx cached\n", pkt->sector); goto out_account; } @@ -1005,8 +1054,8 @@ static void pkt_gather_data(struct pktcdvd_device *pd, struct packet_data *pkt) p = (f * CD_FRAMESIZE) / PAGE_SIZE; offset = (f * CD_FRAMESIZE) % PAGE_SIZE; - pkt_dbg(2, pd, "Adding frame %d, page:%p offs:%d\n", - f, pkt->pages[p], offset); + dev_dbg(ddev, "Adding frame %d, page:%p offs:%d\n", f, + pkt->pages[p], offset); if (!bio_add_page(bio, pkt->pages[p], CD_FRAMESIZE, offset)) BUG(); @@ -1016,8 +1065,7 @@ static void pkt_gather_data(struct pktcdvd_device *pd, struct packet_data *pkt) } out_account: - pkt_dbg(2, pd, "need %d frames for zone %llx\n", - frames_read, (unsigned long long)pkt->sector); + dev_dbg(ddev, "need %d frames for zone %llx\n", frames_read, pkt->sector); pd->stats.pkt_started++; pd->stats.secs_rg += frames_read * (CD_FRAMESIZE >> 9); } @@ -1051,17 +1099,17 @@ static void pkt_put_packet_data(struct pktcdvd_device *pd, struct packet_data *p } } -static inline void pkt_set_state(struct packet_data *pkt, enum packet_data_state state) +static inline void pkt_set_state(struct device *ddev, struct packet_data *pkt, + enum packet_data_state state) { -#if PACKET_DEBUG > 1 static const char *state_name[] = { "IDLE", "WAITING", "READ_WAIT", "WRITE_WAIT", "RECOVERY", "FINISHED" }; enum packet_data_state old_state = pkt->state; - pkt_dbg(2, pd, "pkt %2d : s=%6llx %s -> %s\n", - pkt->id, (unsigned long long)pkt->sector, - state_name[old_state], state_name[state]); -#endif + + dev_dbg(ddev, "pkt %2d : s=%6llx %s -> %s\n", + pkt->id, pkt->sector, state_name[old_state], state_name[state]); + pkt->state = state; } @@ -1071,6 +1119,7 @@ static inline void pkt_set_state(struct packet_data *pkt, enum packet_data_state */ static int pkt_handle_queue(struct pktcdvd_device *pd) { + struct device *ddev = disk_to_dev(pd->disk); struct packet_data *pkt, *p; struct bio *bio = NULL; sector_t zone = 0; /* Suppress gcc warning */ @@ -1080,7 +1129,7 @@ static int pkt_handle_queue(struct pktcdvd_device *pd) atomic_set(&pd->scan_queue, 0); if (list_empty(&pd->cdrw.pkt_free_list)) { - pkt_dbg(2, pd, "no pkt\n"); + dev_dbg(ddev, "no pkt\n"); return 0; } @@ -1117,7 +1166,7 @@ static int pkt_handle_queue(struct pktcdvd_device *pd) } spin_unlock(&pd->lock); if (!bio) { - pkt_dbg(2, pd, "no bio\n"); + dev_dbg(ddev, "no bio\n"); return 0; } @@ -1133,12 +1182,13 @@ static int pkt_handle_queue(struct pktcdvd_device *pd) * to this packet. */ spin_lock(&pd->lock); - pkt_dbg(2, pd, "looking for zone %llx\n", (unsigned long long)zone); + dev_dbg(ddev, "looking for zone %llx\n", zone); while ((node = pkt_rbtree_find(pd, zone)) != NULL) { + sector_t tmp = get_zone(node->bio->bi_iter.bi_sector, pd); + bio = node->bio; - pkt_dbg(2, pd, "found zone=%llx\n", (unsigned long long) - get_zone(bio->bi_iter.bi_sector, pd)); - if (get_zone(bio->bi_iter.bi_sector, pd) != zone) + dev_dbg(ddev, "found zone=%llx\n", tmp); + if (tmp != zone) break; pkt_rbtree_erase(pd, node); spin_lock(&pkt->lock); @@ -1157,7 +1207,7 @@ static int pkt_handle_queue(struct pktcdvd_device *pd) spin_unlock(&pd->lock); pkt->sleep_time = max(PACKET_WAIT_TIME, 1); - pkt_set_state(pkt, PACKET_WAITING_STATE); + pkt_set_state(ddev, pkt, PACKET_WAITING_STATE); atomic_set(&pkt->run_sm, 1); spin_lock(&pd->cdrw.active_list_lock); @@ -1209,6 +1259,7 @@ static void bio_list_copy_data(struct bio *dst, struct bio *src) */ static void pkt_start_write(struct pktcdvd_device *pd, struct packet_data *pkt) { + struct device *ddev = disk_to_dev(pd->disk); int f; bio_init(pkt->w_bio, pd->bdev, pkt->w_bio->bi_inline_vecs, pkt->frames, @@ -1225,7 +1276,7 @@ static void pkt_start_write(struct pktcdvd_device *pd, struct packet_data *pkt) if (!bio_add_page(pkt->w_bio, page, CD_FRAMESIZE, offset)) BUG(); } - pkt_dbg(2, pd, "vcnt=%d\n", pkt->w_bio->bi_vcnt); + dev_dbg(ddev, "vcnt=%d\n", pkt->w_bio->bi_vcnt); /* * Fill-in bvec with data from orig_bios. @@ -1233,11 +1284,10 @@ static void pkt_start_write(struct pktcdvd_device *pd, struct packet_data *pkt) spin_lock(&pkt->lock); bio_list_copy_data(pkt->w_bio, pkt->orig_bios.head); - pkt_set_state(pkt, PACKET_WRITE_WAIT_STATE); + pkt_set_state(ddev, pkt, PACKET_WRITE_WAIT_STATE); spin_unlock(&pkt->lock); - pkt_dbg(2, pd, "Writing %d frames for zone %llx\n", - pkt->write_size, (unsigned long long)pkt->sector); + dev_dbg(ddev, "Writing %d frames for zone %llx\n", pkt->write_size, pkt->sector); if (test_bit(PACKET_MERGE_SEGS, &pd->flags) || (pkt->write_size < pkt->frames)) pkt->cache_valid = 1; @@ -1265,7 +1315,9 @@ static void pkt_finish_packet(struct packet_data *pkt, blk_status_t status) static void pkt_run_state_machine(struct pktcdvd_device *pd, struct packet_data *pkt) { - pkt_dbg(2, pd, "pkt %d\n", pkt->id); + struct device *ddev = disk_to_dev(pd->disk); + + dev_dbg(ddev, "pkt %d\n", pkt->id); for (;;) { switch (pkt->state) { @@ -1275,7 +1327,7 @@ static void pkt_run_state_machine(struct pktcdvd_device *pd, struct packet_data pkt->sleep_time = 0; pkt_gather_data(pd, pkt); - pkt_set_state(pkt, PACKET_READ_WAIT_STATE); + pkt_set_state(ddev, pkt, PACKET_READ_WAIT_STATE); break; case PACKET_READ_WAIT_STATE: @@ -1283,7 +1335,7 @@ static void pkt_run_state_machine(struct pktcdvd_device *pd, struct packet_data return; if (atomic_read(&pkt->io_errors) > 0) { - pkt_set_state(pkt, PACKET_RECOVERY_STATE); + pkt_set_state(ddev, pkt, PACKET_RECOVERY_STATE); } else { pkt_start_write(pd, pkt); } @@ -1294,15 +1346,15 @@ static void pkt_run_state_machine(struct pktcdvd_device *pd, struct packet_data return; if (!pkt->w_bio->bi_status) { - pkt_set_state(pkt, PACKET_FINISHED_STATE); + pkt_set_state(ddev, pkt, PACKET_FINISHED_STATE); } else { - pkt_set_state(pkt, PACKET_RECOVERY_STATE); + pkt_set_state(ddev, pkt, PACKET_RECOVERY_STATE); } break; case PACKET_RECOVERY_STATE: - pkt_dbg(2, pd, "No recovery possible\n"); - pkt_set_state(pkt, PACKET_FINISHED_STATE); + dev_dbg(ddev, "No recovery possible\n"); + pkt_set_state(ddev, pkt, PACKET_FINISHED_STATE); break; case PACKET_FINISHED_STATE: @@ -1318,6 +1370,7 @@ static void pkt_run_state_machine(struct pktcdvd_device *pd, struct packet_data static void pkt_handle_packets(struct pktcdvd_device *pd) { + struct device *ddev = disk_to_dev(pd->disk); struct packet_data *pkt, *next; /* @@ -1338,28 +1391,13 @@ static void pkt_handle_packets(struct pktcdvd_device *pd) if (pkt->state == PACKET_FINISHED_STATE) { list_del(&pkt->list); pkt_put_packet_data(pd, pkt); - pkt_set_state(pkt, PACKET_IDLE_STATE); + pkt_set_state(ddev, pkt, PACKET_IDLE_STATE); atomic_set(&pd->scan_queue, 1); } } spin_unlock(&pd->cdrw.active_list_lock); } -static void pkt_count_states(struct pktcdvd_device *pd, int *states) -{ - struct packet_data *pkt; - int i; - - for (i = 0; i < PACKET_NUM_STATES; i++) - states[i] = 0; - - spin_lock(&pd->cdrw.active_list_lock); - list_for_each_entry(pkt, &pd->cdrw.pkt_active_list, list) { - states[pkt->state]++; - } - spin_unlock(&pd->cdrw.active_list_lock); -} - /* * kcdrwd is woken up when writes have been queued for one of our * registered devices @@ -1367,7 +1405,9 @@ static void pkt_count_states(struct pktcdvd_device *pd, int *states) static int kcdrwd(void *foobar) { struct pktcdvd_device *pd = foobar; + struct device *ddev = disk_to_dev(pd->disk); struct packet_data *pkt; + int states[PACKET_NUM_STATES]; long min_sleep_time, residue; set_user_nice(current, MIN_NICE); @@ -1398,13 +1438,9 @@ static int kcdrwd(void *foobar) goto work_to_do; /* Otherwise, go to sleep */ - if (PACKET_DEBUG > 1) { - int states[PACKET_NUM_STATES]; - pkt_count_states(pd, states); - pkt_dbg(2, pd, "i:%d ow:%d rw:%d ww:%d rec:%d fin:%d\n", - states[0], states[1], states[2], - states[3], states[4], states[5]); - } + pkt_count_states(pd, states); + dev_dbg(ddev, "i:%d ow:%d rw:%d ww:%d rec:%d fin:%d\n", + states[0], states[1], states[2], states[3], states[4], states[5]); min_sleep_time = MAX_SCHEDULE_TIMEOUT; list_for_each_entry(pkt, &pd->cdrw.pkt_active_list, list) { @@ -1412,9 +1448,9 @@ static int kcdrwd(void *foobar) min_sleep_time = pkt->sleep_time; } - pkt_dbg(2, pd, "sleeping\n"); + dev_dbg(ddev, "sleeping\n"); residue = schedule_timeout(min_sleep_time); - pkt_dbg(2, pd, "wake up\n"); + dev_dbg(ddev, "wake up\n"); /* make swsusp happy with our thread */ try_to_freeze(); @@ -1462,7 +1498,7 @@ static int kcdrwd(void *foobar) static void pkt_print_settings(struct pktcdvd_device *pd) { - pkt_info(pd, "%s packets, %u blocks, Mode-%c disc\n", + dev_info(disk_to_dev(pd->disk), "%s packets, %u blocks, Mode-%c disc\n", pd->settings.fp ? "Fixed" : "Variable", pd->settings.size >> 2, pd->settings.block_mode == 8 ? '1' : '2'); @@ -1474,8 +1510,7 @@ static int pkt_mode_sense(struct pktcdvd_device *pd, struct packet_command *cgc, cgc->cmd[0] = GPCMD_MODE_SENSE_10; cgc->cmd[2] = page_code | (page_control << 6); - cgc->cmd[7] = cgc->buflen >> 8; - cgc->cmd[8] = cgc->buflen & 0xff; + put_unaligned_be16(cgc->buflen, &cgc->cmd[7]); cgc->data_direction = CGC_DATA_READ; return pkt_generic_packet(pd, cgc); } @@ -1486,8 +1521,7 @@ static int pkt_mode_select(struct pktcdvd_device *pd, struct packet_command *cgc memset(cgc->buffer, 0, 2); cgc->cmd[0] = GPCMD_MODE_SELECT_10; cgc->cmd[1] = 0x10; /* PF */ - cgc->cmd[7] = cgc->buflen >> 8; - cgc->cmd[8] = cgc->buflen & 0xff; + put_unaligned_be16(cgc->buflen, &cgc->cmd[7]); cgc->data_direction = CGC_DATA_WRITE; return pkt_generic_packet(pd, cgc); } @@ -1528,8 +1562,7 @@ static int pkt_get_track_info(struct pktcdvd_device *pd, __u16 track, __u8 type, init_cdrom_command(&cgc, ti, 8, CGC_DATA_READ); cgc.cmd[0] = GPCMD_READ_TRACK_RZONE_INFO; cgc.cmd[1] = type & 3; - cgc.cmd[4] = (track & 0xff00) >> 8; - cgc.cmd[5] = track & 0xff; + put_unaligned_be16(track, &cgc.cmd[4]); cgc.cmd[8] = 8; cgc.quiet = 1; @@ -1590,6 +1623,7 @@ static noinline_for_stack int pkt_get_last_written(struct pktcdvd_device *pd, */ static noinline_for_stack int pkt_set_write_settings(struct pktcdvd_device *pd) { + struct device *ddev = disk_to_dev(pd->disk); struct packet_command cgc; struct scsi_sense_hdr sshdr; write_param_page *wp; @@ -1609,8 +1643,8 @@ static noinline_for_stack int pkt_set_write_settings(struct pktcdvd_device *pd) return ret; } - size = 2 + ((buffer[0] << 8) | (buffer[1] & 0xff)); - pd->mode_offset = (buffer[6] << 8) | (buffer[7] & 0xff); + size = 2 + get_unaligned_be16(&buffer[0]); + pd->mode_offset = get_unaligned_be16(&buffer[6]); if (size > sizeof(buffer)) size = sizeof(buffer); @@ -1656,7 +1690,7 @@ static noinline_for_stack int pkt_set_write_settings(struct pktcdvd_device *pd) /* * paranoia */ - pkt_err(pd, "write mode wrong %d\n", wp->data_block_type); + dev_err(ddev, "write mode wrong %d\n", wp->data_block_type); return 1; } wp->packet_size = cpu_to_be32(pd->settings.size >> 2); @@ -1677,6 +1711,8 @@ static noinline_for_stack int pkt_set_write_settings(struct pktcdvd_device *pd) */ static int pkt_writable_track(struct pktcdvd_device *pd, track_information *ti) { + struct device *ddev = disk_to_dev(pd->disk); + switch (pd->mmc3_profile) { case 0x1a: /* DVD+RW */ case 0x12: /* DVD-RAM */ @@ -1701,7 +1737,7 @@ static int pkt_writable_track(struct pktcdvd_device *pd, track_information *ti) if (ti->rt == 1 && ti->blank == 0) return 1; - pkt_err(pd, "bad state %d-%d-%d\n", ti->rt, ti->blank, ti->packet); + dev_err(ddev, "bad state %d-%d-%d\n", ti->rt, ti->blank, ti->packet); return 0; } @@ -1710,6 +1746,8 @@ static int pkt_writable_track(struct pktcdvd_device *pd, track_information *ti) */ static int pkt_writable_disc(struct pktcdvd_device *pd, disc_information *di) { + struct device *ddev = disk_to_dev(pd->disk); + switch (pd->mmc3_profile) { case 0x0a: /* CD-RW */ case 0xffff: /* MMC3 not supported */ @@ -1719,8 +1757,7 @@ static int pkt_writable_disc(struct pktcdvd_device *pd, disc_information *di) case 0x12: /* DVD-RAM */ return 1; default: - pkt_dbg(2, pd, "Wrong disc profile (%x)\n", - pd->mmc3_profile); + dev_dbg(ddev, "Wrong disc profile (%x)\n", pd->mmc3_profile); return 0; } @@ -1729,22 +1766,22 @@ static int pkt_writable_disc(struct pktcdvd_device *pd, disc_information *di) * but i'm not sure, should we leave this to user apps? probably. */ if (di->disc_type == 0xff) { - pkt_notice(pd, "unknown disc - no track?\n"); + dev_notice(ddev, "unknown disc - no track?\n"); return 0; } if (di->disc_type != 0x20 && di->disc_type != 0) { - pkt_err(pd, "wrong disc type (%x)\n", di->disc_type); + dev_err(ddev, "wrong disc type (%x)\n", di->disc_type); return 0; } if (di->erasable == 0) { - pkt_notice(pd, "disc not erasable\n"); + dev_err(ddev, "disc not erasable\n"); return 0; } if (di->border_status == PACKET_SESSION_RESERVED) { - pkt_err(pd, "can't write to last track (reserved)\n"); + dev_err(ddev, "can't write to last track (reserved)\n"); return 0; } @@ -1753,6 +1790,7 @@ static int pkt_writable_disc(struct pktcdvd_device *pd, disc_information *di) static noinline_for_stack int pkt_probe_settings(struct pktcdvd_device *pd) { + struct device *ddev = disk_to_dev(pd->disk); struct packet_command cgc; unsigned char buf[12]; disc_information di; @@ -1763,14 +1801,14 @@ static noinline_for_stack int pkt_probe_settings(struct pktcdvd_device *pd) cgc.cmd[0] = GPCMD_GET_CONFIGURATION; cgc.cmd[8] = 8; ret = pkt_generic_packet(pd, &cgc); - pd->mmc3_profile = ret ? 0xffff : buf[6] << 8 | buf[7]; + pd->mmc3_profile = ret ? 0xffff : get_unaligned_be16(&buf[6]); memset(&di, 0, sizeof(disc_information)); memset(&ti, 0, sizeof(track_information)); ret = pkt_get_disc_info(pd, &di); if (ret) { - pkt_err(pd, "failed get_disc\n"); + dev_err(ddev, "failed get_disc\n"); return ret; } @@ -1782,12 +1820,12 @@ static noinline_for_stack int pkt_probe_settings(struct pktcdvd_device *pd) track = 1; /* (di.last_track_msb << 8) | di.last_track_lsb; */ ret = pkt_get_track_info(pd, track, 1, &ti); if (ret) { - pkt_err(pd, "failed get_track\n"); + dev_err(ddev, "failed get_track\n"); return ret; } if (!pkt_writable_track(pd, &ti)) { - pkt_err(pd, "can't write to this track\n"); + dev_err(ddev, "can't write to this track\n"); return -EROFS; } @@ -1797,11 +1835,11 @@ static noinline_for_stack int pkt_probe_settings(struct pktcdvd_device *pd) */ pd->settings.size = be32_to_cpu(ti.fixed_packet_size) << 2; if (pd->settings.size == 0) { - pkt_notice(pd, "detected zero packet size!\n"); + dev_notice(ddev, "detected zero packet size!\n"); return -ENXIO; } if (pd->settings.size > PACKET_MAX_SECTORS) { - pkt_err(pd, "packet size is too big\n"); + dev_err(ddev, "packet size is too big\n"); return -EROFS; } pd->settings.fp = ti.fp; @@ -1843,7 +1881,7 @@ static noinline_for_stack int pkt_probe_settings(struct pktcdvd_device *pd) pd->settings.block_mode = PACKET_BLOCK_MODE2; break; default: - pkt_err(pd, "unknown data mode\n"); + dev_err(ddev, "unknown data mode\n"); return -EROFS; } return 0; @@ -1854,6 +1892,7 @@ static noinline_for_stack int pkt_probe_settings(struct pktcdvd_device *pd) */ static noinline_for_stack int pkt_write_caching(struct pktcdvd_device *pd) { + struct device *ddev = disk_to_dev(pd->disk); struct packet_command cgc; struct scsi_sense_hdr sshdr; unsigned char buf[64]; @@ -1880,13 +1919,13 @@ static noinline_for_stack int pkt_write_caching(struct pktcdvd_device *pd) */ buf[pd->mode_offset + 10] |= (set << 2); - cgc.buflen = cgc.cmd[8] = 2 + ((buf[0] << 8) | (buf[1] & 0xff)); + cgc.buflen = cgc.cmd[8] = 2 + get_unaligned_be16(&buf[0]); ret = pkt_mode_select(pd, &cgc); if (ret) { - pkt_err(pd, "write caching control failed\n"); + dev_err(ddev, "write caching control failed\n"); pkt_dump_sense(pd, &cgc); } else if (!ret && set) - pkt_notice(pd, "enabled write caching\n"); + dev_notice(ddev, "enabled write caching\n"); return ret; } @@ -1935,12 +1974,12 @@ static noinline_for_stack int pkt_get_max_speed(struct pktcdvd_device *pd, * Speed Performance Descriptor Block", use the information * in the first block. (contains the highest speed) */ - int num_spdb = (cap_buf[30] << 8) + cap_buf[31]; + int num_spdb = get_unaligned_be16(&cap_buf[30]); if (num_spdb > 0) offset = 34; } - *write_speed = (cap_buf[offset] << 8) | cap_buf[offset + 1]; + *write_speed = get_unaligned_be16(&cap_buf[offset]); return 0; } @@ -1967,6 +2006,7 @@ static char us_clv_to_speed[16] = { static noinline_for_stack int pkt_media_speed(struct pktcdvd_device *pd, unsigned *speed) { + struct device *ddev = disk_to_dev(pd->disk); struct packet_command cgc; struct scsi_sense_hdr sshdr; unsigned char buf[64]; @@ -1984,7 +2024,7 @@ static noinline_for_stack int pkt_media_speed(struct pktcdvd_device *pd, pkt_dump_sense(pd, &cgc); return ret; } - size = ((unsigned int) buf[0]<<8) + buf[1] + 2; + size = 2 + get_unaligned_be16(&buf[0]); if (size > sizeof(buf)) size = sizeof(buf); @@ -2001,11 +2041,11 @@ static noinline_for_stack int pkt_media_speed(struct pktcdvd_device *pd, } if (!(buf[6] & 0x40)) { - pkt_notice(pd, "disc type is not CD-RW\n"); + dev_notice(ddev, "disc type is not CD-RW\n"); return 1; } if (!(buf[6] & 0x4)) { - pkt_notice(pd, "A1 values on media are not valid, maybe not CDRW?\n"); + dev_notice(ddev, "A1 values on media are not valid, maybe not CDRW?\n"); return 1; } @@ -2025,25 +2065,26 @@ static noinline_for_stack int pkt_media_speed(struct pktcdvd_device *pd, *speed = us_clv_to_speed[sp]; break; default: - pkt_notice(pd, "unknown disc sub-type %d\n", st); + dev_notice(ddev, "unknown disc sub-type %d\n", st); return 1; } if (*speed) { - pkt_info(pd, "maximum media speed: %d\n", *speed); + dev_info(ddev, "maximum media speed: %d\n", *speed); return 0; } else { - pkt_notice(pd, "unknown speed %d for sub-type %d\n", sp, st); + dev_notice(ddev, "unknown speed %d for sub-type %d\n", sp, st); return 1; } } static noinline_for_stack int pkt_perform_opc(struct pktcdvd_device *pd) { + struct device *ddev = disk_to_dev(pd->disk); struct packet_command cgc; struct scsi_sense_hdr sshdr; int ret; - pkt_dbg(2, pd, "Performing OPC\n"); + dev_dbg(ddev, "Performing OPC\n"); init_cdrom_command(&cgc, NULL, 0, CGC_DATA_NONE); cgc.sshdr = &sshdr; @@ -2058,18 +2099,19 @@ static noinline_for_stack int pkt_perform_opc(struct pktcdvd_device *pd) static int pkt_open_write(struct pktcdvd_device *pd) { + struct device *ddev = disk_to_dev(pd->disk); int ret; unsigned int write_speed, media_write_speed, read_speed; ret = pkt_probe_settings(pd); if (ret) { - pkt_dbg(2, pd, "failed probe\n"); + dev_dbg(ddev, "failed probe\n"); return ret; } ret = pkt_set_write_settings(pd); if (ret) { - pkt_dbg(1, pd, "failed saving write settings\n"); + dev_notice(ddev, "failed saving write settings\n"); return -EIO; } @@ -2082,30 +2124,29 @@ static int pkt_open_write(struct pktcdvd_device *pd) case 0x13: /* DVD-RW */ case 0x1a: /* DVD+RW */ case 0x12: /* DVD-RAM */ - pkt_dbg(1, pd, "write speed %ukB/s\n", write_speed); + dev_notice(ddev, "write speed %ukB/s\n", write_speed); break; default: ret = pkt_media_speed(pd, &media_write_speed); if (ret) media_write_speed = 16; write_speed = min(write_speed, media_write_speed * 177); - pkt_dbg(1, pd, "write speed %ux\n", write_speed / 176); + dev_notice(ddev, "write speed %ux\n", write_speed / 176); break; } read_speed = write_speed; ret = pkt_set_speed(pd, write_speed, read_speed); if (ret) { - pkt_dbg(1, pd, "couldn't set write speed\n"); + dev_notice(ddev, "couldn't set write speed\n"); return -EIO; } pd->write_speed = write_speed; pd->read_speed = read_speed; ret = pkt_perform_opc(pd); - if (ret) { - pkt_dbg(1, pd, "Optimum Power Calibration failed\n"); - } + if (ret) + dev_notice(ddev, "Optimum Power Calibration failed\n"); return 0; } @@ -2113,8 +2154,9 @@ static int pkt_open_write(struct pktcdvd_device *pd) /* * called at open time. */ -static int pkt_open_dev(struct pktcdvd_device *pd, fmode_t write) +static int pkt_open_dev(struct pktcdvd_device *pd, bool write) { + struct device *ddev = disk_to_dev(pd->disk); int ret; long lba; struct request_queue *q; @@ -2125,7 +2167,7 @@ static int pkt_open_dev(struct pktcdvd_device *pd, fmode_t write) * to read/write from/to it. It is already opened in O_NONBLOCK mode * so open should not fail. */ - bdev = blkdev_get_by_dev(pd->bdev->bd_dev, FMODE_READ | FMODE_EXCL, pd); + bdev = blkdev_get_by_dev(pd->bdev->bd_dev, BLK_OPEN_READ, pd, NULL); if (IS_ERR(bdev)) { ret = PTR_ERR(bdev); goto out; @@ -2133,7 +2175,7 @@ static int pkt_open_dev(struct pktcdvd_device *pd, fmode_t write) ret = pkt_get_last_written(pd, &lba); if (ret) { - pkt_err(pd, "pkt_get_last_written failed\n"); + dev_err(ddev, "pkt_get_last_written failed\n"); goto out_putdev; } @@ -2162,17 +2204,17 @@ static int pkt_open_dev(struct pktcdvd_device *pd, fmode_t write) if (write) { if (!pkt_grow_pktlist(pd, CONFIG_CDROM_PKTCDVD_BUFFERS)) { - pkt_err(pd, "not enough memory for buffers\n"); + dev_err(ddev, "not enough memory for buffers\n"); ret = -ENOMEM; goto out_putdev; } - pkt_info(pd, "%lukB available on disc\n", lba << 1); + dev_info(ddev, "%lukB available on disc\n", lba << 1); } return 0; out_putdev: - blkdev_put(bdev, FMODE_READ | FMODE_EXCL); + blkdev_put(bdev, pd); out: return ret; } @@ -2183,13 +2225,15 @@ static int pkt_open_dev(struct pktcdvd_device *pd, fmode_t write) */ static void pkt_release_dev(struct pktcdvd_device *pd, int flush) { + struct device *ddev = disk_to_dev(pd->disk); + if (flush && pkt_flush_cache(pd)) - pkt_dbg(1, pd, "not flushing cache\n"); + dev_notice(ddev, "not flushing cache\n"); pkt_lock_door(pd, 0); pkt_set_speed(pd, MAX_SPEED, MAX_SPEED); - blkdev_put(pd->bdev, FMODE_READ | FMODE_EXCL); + blkdev_put(pd->bdev, pd); pkt_shrink_pktlist(pd); } @@ -2203,14 +2247,14 @@ static struct pktcdvd_device *pkt_find_dev_from_minor(unsigned int dev_minor) return pkt_devs[dev_minor]; } -static int pkt_open(struct block_device *bdev, fmode_t mode) +static int pkt_open(struct gendisk *disk, blk_mode_t mode) { struct pktcdvd_device *pd = NULL; int ret; mutex_lock(&pktcdvd_mutex); mutex_lock(&ctl_mutex); - pd = pkt_find_dev_from_minor(MINOR(bdev->bd_dev)); + pd = pkt_find_dev_from_minor(disk->first_minor); if (!pd) { ret = -ENODEV; goto out; @@ -2219,22 +2263,21 @@ static int pkt_open(struct block_device *bdev, fmode_t mode) pd->refcnt++; if (pd->refcnt > 1) { - if ((mode & FMODE_WRITE) && + if ((mode & BLK_OPEN_WRITE) && !test_bit(PACKET_WRITABLE, &pd->flags)) { ret = -EBUSY; goto out_dec; } } else { - ret = pkt_open_dev(pd, mode & FMODE_WRITE); + ret = pkt_open_dev(pd, mode & BLK_OPEN_WRITE); if (ret) goto out_dec; /* * needed here as well, since ext2 (among others) may change * the blocksize at mount time */ - set_blocksize(bdev, CD_FRAMESIZE); + set_blocksize(disk->part0, CD_FRAMESIZE); } - mutex_unlock(&ctl_mutex); mutex_unlock(&pktcdvd_mutex); return 0; @@ -2247,7 +2290,7 @@ static int pkt_open(struct block_device *bdev, fmode_t mode) return ret; } -static void pkt_close(struct gendisk *disk, fmode_t mode) +static void pkt_release(struct gendisk *disk) { struct pktcdvd_device *pd = disk->private_data; @@ -2385,15 +2428,15 @@ static void pkt_make_request_write(struct request_queue *q, struct bio *bio) static void pkt_submit_bio(struct bio *bio) { struct pktcdvd_device *pd = bio->bi_bdev->bd_disk->queue->queuedata; + struct device *ddev = disk_to_dev(pd->disk); struct bio *split; bio = bio_split_to_limits(bio); if (!bio) return; - pkt_dbg(2, pd, "start = %6llx stop = %6llx\n", - (unsigned long long)bio->bi_iter.bi_sector, - (unsigned long long)bio_end_sector(bio)); + dev_dbg(ddev, "start = %6llx stop = %6llx\n", + bio->bi_iter.bi_sector, bio_end_sector(bio)); /* * Clone READ bios so we can have our own bi_end_io callback. @@ -2404,13 +2447,12 @@ static void pkt_submit_bio(struct bio *bio) } if (!test_bit(PACKET_WRITABLE, &pd->flags)) { - pkt_notice(pd, "WRITE for ro device (%llu)\n", - (unsigned long long)bio->bi_iter.bi_sector); + dev_notice(ddev, "WRITE for ro device (%llu)\n", bio->bi_iter.bi_sector); goto end_io; } if (!bio->bi_iter.bi_size || (bio->bi_iter.bi_size % CD_FRAMESIZE)) { - pkt_err(pd, "wrong bio size\n"); + dev_err(ddev, "wrong bio size\n"); goto end_io; } @@ -2446,74 +2488,15 @@ static void pkt_init_queue(struct pktcdvd_device *pd) q->queuedata = pd; } -static int pkt_seq_show(struct seq_file *m, void *p) -{ - struct pktcdvd_device *pd = m->private; - char *msg; - int states[PACKET_NUM_STATES]; - - seq_printf(m, "Writer %s mapped to %pg:\n", pd->name, pd->bdev); - - seq_printf(m, "\nSettings:\n"); - seq_printf(m, "\tpacket size:\t\t%dkB\n", pd->settings.size / 2); - - if (pd->settings.write_type == 0) - msg = "Packet"; - else - msg = "Unknown"; - seq_printf(m, "\twrite type:\t\t%s\n", msg); - - seq_printf(m, "\tpacket type:\t\t%s\n", pd->settings.fp ? "Fixed" : "Variable"); - seq_printf(m, "\tlink loss:\t\t%d\n", pd->settings.link_loss); - - seq_printf(m, "\ttrack mode:\t\t%d\n", pd->settings.track_mode); - - if (pd->settings.block_mode == PACKET_BLOCK_MODE1) - msg = "Mode 1"; - else if (pd->settings.block_mode == PACKET_BLOCK_MODE2) - msg = "Mode 2"; - else - msg = "Unknown"; - seq_printf(m, "\tblock mode:\t\t%s\n", msg); - - seq_printf(m, "\nStatistics:\n"); - seq_printf(m, "\tpackets started:\t%lu\n", pd->stats.pkt_started); - seq_printf(m, "\tpackets ended:\t\t%lu\n", pd->stats.pkt_ended); - seq_printf(m, "\twritten:\t\t%lukB\n", pd->stats.secs_w >> 1); - seq_printf(m, "\tread gather:\t\t%lukB\n", pd->stats.secs_rg >> 1); - seq_printf(m, "\tread:\t\t\t%lukB\n", pd->stats.secs_r >> 1); - - seq_printf(m, "\nMisc:\n"); - seq_printf(m, "\treference count:\t%d\n", pd->refcnt); - seq_printf(m, "\tflags:\t\t\t0x%lx\n", pd->flags); - seq_printf(m, "\tread speed:\t\t%ukB/s\n", pd->read_speed); - seq_printf(m, "\twrite speed:\t\t%ukB/s\n", pd->write_speed); - seq_printf(m, "\tstart offset:\t\t%lu\n", pd->offset); - seq_printf(m, "\tmode page offset:\t%u\n", pd->mode_offset); - - seq_printf(m, "\nQueue state:\n"); - seq_printf(m, "\tbios queued:\t\t%d\n", pd->bio_queue_size); - seq_printf(m, "\tbios pending:\t\t%d\n", atomic_read(&pd->cdrw.pending_bios)); - seq_printf(m, "\tcurrent sector:\t\t0x%llx\n", (unsigned long long)pd->current_sector); - - pkt_count_states(pd, states); - seq_printf(m, "\tstate:\t\t\ti:%d ow:%d rw:%d ww:%d rec:%d fin:%d\n", - states[0], states[1], states[2], states[3], states[4], states[5]); - - seq_printf(m, "\twrite congestion marks:\toff=%d on=%d\n", - pd->write_congestion_off, - pd->write_congestion_on); - return 0; -} - static int pkt_new_dev(struct pktcdvd_device *pd, dev_t dev) { + struct device *ddev = disk_to_dev(pd->disk); int i; struct block_device *bdev; struct scsi_device *sdev; if (pd->pkt_dev == dev) { - pkt_err(pd, "recursive setup not allowed\n"); + dev_err(ddev, "recursive setup not allowed\n"); return -EBUSY; } for (i = 0; i < MAX_WRITERS; i++) { @@ -2521,21 +2504,22 @@ static int pkt_new_dev(struct pktcdvd_device *pd, dev_t dev) if (!pd2) continue; if (pd2->bdev->bd_dev == dev) { - pkt_err(pd, "%pg already setup\n", pd2->bdev); + dev_err(ddev, "%pg already setup\n", pd2->bdev); return -EBUSY; } if (pd2->pkt_dev == dev) { - pkt_err(pd, "can't chain pktcdvd devices\n"); + dev_err(ddev, "can't chain pktcdvd devices\n"); return -EBUSY; } } - bdev = blkdev_get_by_dev(dev, FMODE_READ | FMODE_NDELAY, NULL); + bdev = blkdev_get_by_dev(dev, BLK_OPEN_READ | BLK_OPEN_NDELAY, NULL, + NULL); if (IS_ERR(bdev)) return PTR_ERR(bdev); sdev = scsi_device_from_queue(bdev->bd_disk->queue); if (!sdev) { - blkdev_put(bdev, FMODE_READ | FMODE_NDELAY); + blkdev_put(bdev, NULL); return -EINVAL; } put_device(&sdev->sdev_gendev); @@ -2549,30 +2533,31 @@ static int pkt_new_dev(struct pktcdvd_device *pd, dev_t dev) pkt_init_queue(pd); atomic_set(&pd->cdrw.pending_bios, 0); - pd->cdrw.thread = kthread_run(kcdrwd, pd, "%s", pd->name); + pd->cdrw.thread = kthread_run(kcdrwd, pd, "%s", pd->disk->disk_name); if (IS_ERR(pd->cdrw.thread)) { - pkt_err(pd, "can't start kernel thread\n"); + dev_err(ddev, "can't start kernel thread\n"); goto out_mem; } - proc_create_single_data(pd->name, 0, pkt_proc, pkt_seq_show, pd); - pkt_dbg(1, pd, "writer mapped to %pg\n", bdev); + proc_create_single_data(pd->disk->disk_name, 0, pkt_proc, pkt_seq_show, pd); + dev_notice(ddev, "writer mapped to %pg\n", bdev); return 0; out_mem: - blkdev_put(bdev, FMODE_READ | FMODE_NDELAY); + blkdev_put(bdev, NULL); /* This is safe: open() is still holding a reference. */ module_put(THIS_MODULE); return -ENOMEM; } -static int pkt_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long arg) +static int pkt_ioctl(struct block_device *bdev, blk_mode_t mode, + unsigned int cmd, unsigned long arg) { struct pktcdvd_device *pd = bdev->bd_disk->private_data; + struct device *ddev = disk_to_dev(pd->disk); int ret; - pkt_dbg(2, pd, "cmd %x, dev %d:%d\n", - cmd, MAJOR(bdev->bd_dev), MINOR(bdev->bd_dev)); + dev_dbg(ddev, "cmd %x, dev %d:%d\n", cmd, MAJOR(bdev->bd_dev), MINOR(bdev->bd_dev)); mutex_lock(&pktcdvd_mutex); switch (cmd) { @@ -2598,7 +2583,7 @@ static int pkt_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, ret = bdev->bd_disk->fops->ioctl(bdev, mode, cmd, arg); break; default: - pkt_dbg(2, pd, "Unknown ioctl (%x)\n", cmd); + dev_dbg(ddev, "Unknown ioctl (%x)\n", cmd); ret = -ENOTTY; } mutex_unlock(&pktcdvd_mutex); @@ -2631,7 +2616,7 @@ static const struct block_device_operations pktcdvd_ops = { .owner = THIS_MODULE, .submit_bio = pkt_submit_bio, .open = pkt_open, - .release = pkt_close, + .release = pkt_release, .ioctl = pkt_ioctl, .compat_ioctl = blkdev_compat_ptr_ioctl, .check_events = pkt_check_events, @@ -2676,7 +2661,6 @@ static int pkt_setup_dev(dev_t dev, dev_t* pkt_dev) spin_lock_init(&pd->iosched.lock); bio_list_init(&pd->iosched.read_queue); bio_list_init(&pd->iosched.write_queue); - sprintf(pd->name, DRIVER_NAME"%d", idx); init_waitqueue_head(&pd->wqueue); pd->bio_queue = RB_ROOT; @@ -2693,7 +2677,7 @@ static int pkt_setup_dev(dev_t dev, dev_t* pkt_dev) disk->minors = 1; disk->fops = &pktcdvd_ops; disk->flags = GENHD_FL_REMOVABLE | GENHD_FL_NO_PART; - strcpy(disk->disk_name, pd->name); + snprintf(disk->disk_name, sizeof(disk->disk_name), DRIVER_NAME"%d", idx); disk->private_data = pd; pd->pkt_dev = MKDEV(pktdev_major, idx); @@ -2735,6 +2719,7 @@ static int pkt_setup_dev(dev_t dev, dev_t* pkt_dev) static int pkt_remove_dev(dev_t pkt_dev) { struct pktcdvd_device *pd; + struct device *ddev; int idx; int ret = 0; @@ -2755,6 +2740,9 @@ static int pkt_remove_dev(dev_t pkt_dev) ret = -EBUSY; goto out; } + + ddev = disk_to_dev(pd->disk); + if (!IS_ERR(pd->cdrw.thread)) kthread_stop(pd->cdrw.thread); @@ -2763,10 +2751,10 @@ static int pkt_remove_dev(dev_t pkt_dev) pkt_debugfs_dev_remove(pd); pkt_sysfs_dev_remove(pd); - blkdev_put(pd->bdev, FMODE_READ | FMODE_NDELAY); + blkdev_put(pd->bdev, NULL); - remove_proc_entry(pd->name, pkt_proc); - pkt_dbg(1, pd, "writer unmapped\n"); + remove_proc_entry(pd->disk->disk_name, pkt_proc); + dev_notice(ddev, "writer unmapped\n"); del_gendisk(pd->disk); put_disk(pd->disk); diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index 632751ddb2870846926391f77986ca1e44a0a5bc..bd0e075a5d8928cda2beede3e567edf62011f6dd 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c @@ -660,9 +660,9 @@ static bool pending_result_dec(struct pending_result *pending, int *result) return true; } -static int rbd_open(struct block_device *bdev, fmode_t mode) +static int rbd_open(struct gendisk *disk, blk_mode_t mode) { - struct rbd_device *rbd_dev = bdev->bd_disk->private_data; + struct rbd_device *rbd_dev = disk->private_data; bool removing = false; spin_lock_irq(&rbd_dev->lock); @@ -679,7 +679,7 @@ static int rbd_open(struct block_device *bdev, fmode_t mode) return 0; } -static void rbd_release(struct gendisk *disk, fmode_t mode) +static void rbd_release(struct gendisk *disk) { struct rbd_device *rbd_dev = disk->private_data; unsigned long open_count_before; diff --git a/drivers/block/rnbd/Makefile b/drivers/block/rnbd/Makefile index 40b31630822ce5b22c504737d076ff74b08b6156..208e5f8654975a794ed4f688f5c409510a6d06fb 100644 --- a/drivers/block/rnbd/Makefile +++ b/drivers/block/rnbd/Makefile @@ -3,13 +3,11 @@ ccflags-y := -I$(srctree)/drivers/infiniband/ulp/rtrs rnbd-client-y := rnbd-clt.o \ - rnbd-clt-sysfs.o \ - rnbd-common.o + rnbd-clt-sysfs.o CFLAGS_rnbd-srv-trace.o = -I$(src) -rnbd-server-y := rnbd-common.o \ - rnbd-srv.o \ +rnbd-server-y := rnbd-srv.o \ rnbd-srv-sysfs.o \ rnbd-srv-trace.o diff --git a/drivers/block/rnbd/rnbd-clt-sysfs.c b/drivers/block/rnbd/rnbd-clt-sysfs.c index 8c6087949794ec3571de9016229ea0b371136639..c36d8b1ceeed74afc8311b218a7d516596c67814 100644 --- a/drivers/block/rnbd/rnbd-clt-sysfs.c +++ b/drivers/block/rnbd/rnbd-clt-sysfs.c @@ -24,7 +24,9 @@ #include "rnbd-clt.h" static struct device *rnbd_dev; -static struct class *rnbd_dev_class; +static const struct class rnbd_dev_class = { + .name = "rnbd_client", +}; static struct kobject *rnbd_devs_kobj; enum { @@ -278,7 +280,7 @@ static ssize_t access_mode_show(struct kobject *kobj, dev = container_of(kobj, struct rnbd_clt_dev, kobj); - return sysfs_emit(page, "%s\n", rnbd_access_mode_str(dev->access_mode)); + return sysfs_emit(page, "%s\n", rnbd_access_modes[dev->access_mode].str); } static struct kobj_attribute rnbd_clt_access_mode = @@ -596,7 +598,7 @@ static ssize_t rnbd_clt_map_device_store(struct kobject *kobj, pr_info("Mapping device %s on session %s, (access_mode: %s, nr_poll_queues: %d)\n", pathname, sessname, - rnbd_access_mode_str(access_mode), + rnbd_access_modes[access_mode].str, nr_poll_queues); dev = rnbd_clt_map_device(sessname, paths, path_cnt, port_nr, pathname, @@ -646,11 +648,11 @@ int rnbd_clt_create_sysfs_files(void) { int err; - rnbd_dev_class = class_create("rnbd-client"); - if (IS_ERR(rnbd_dev_class)) - return PTR_ERR(rnbd_dev_class); + err = class_register(&rnbd_dev_class); + if (err) + return err; - rnbd_dev = device_create_with_groups(rnbd_dev_class, NULL, + rnbd_dev = device_create_with_groups(&rnbd_dev_class, NULL, MKDEV(0, 0), NULL, default_attr_groups, "ctl"); if (IS_ERR(rnbd_dev)) { @@ -666,9 +668,9 @@ int rnbd_clt_create_sysfs_files(void) return 0; dev_destroy: - device_destroy(rnbd_dev_class, MKDEV(0, 0)); + device_destroy(&rnbd_dev_class, MKDEV(0, 0)); cls_destroy: - class_destroy(rnbd_dev_class); + class_unregister(&rnbd_dev_class); return err; } @@ -678,6 +680,6 @@ void rnbd_clt_destroy_sysfs_files(void) sysfs_remove_group(&rnbd_dev->kobj, &default_attr_group); kobject_del(rnbd_devs_kobj); kobject_put(rnbd_devs_kobj); - device_destroy(rnbd_dev_class, MKDEV(0, 0)); - class_destroy(rnbd_dev_class); + device_destroy(&rnbd_dev_class, MKDEV(0, 0)); + class_unregister(&rnbd_dev_class); } diff --git a/drivers/block/rnbd/rnbd-clt.c b/drivers/block/rnbd/rnbd-clt.c index 5eb8c7855970d1ab277798056b0fb3db2ba151be..b0550b68645d38ae7b901307eac348f48999ee84 100644 --- a/drivers/block/rnbd/rnbd-clt.c +++ b/drivers/block/rnbd/rnbd-clt.c @@ -921,11 +921,11 @@ rnbd_clt_session *find_or_create_sess(const char *sessname, bool *first) return sess; } -static int rnbd_client_open(struct block_device *block_device, fmode_t mode) +static int rnbd_client_open(struct gendisk *disk, blk_mode_t mode) { - struct rnbd_clt_dev *dev = block_device->bd_disk->private_data; + struct rnbd_clt_dev *dev = disk->private_data; - if (get_disk_ro(dev->gd) && (mode & FMODE_WRITE)) + if (get_disk_ro(dev->gd) && (mode & BLK_OPEN_WRITE)) return -EPERM; if (dev->dev_state == DEV_STATE_UNMAPPED || @@ -935,7 +935,7 @@ static int rnbd_client_open(struct block_device *block_device, fmode_t mode) return 0; } -static void rnbd_client_release(struct gendisk *gen, fmode_t mode) +static void rnbd_client_release(struct gendisk *gen) { struct rnbd_clt_dev *dev = gen->private_data; diff --git a/drivers/block/rnbd/rnbd-common.c b/drivers/block/rnbd/rnbd-common.c deleted file mode 100644 index 596c3f732403ef73b152916c12e1731d2b5764e9..0000000000000000000000000000000000000000 --- a/drivers/block/rnbd/rnbd-common.c +++ /dev/null @@ -1,23 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * RDMA Network Block Driver - * - * Copyright (c) 2014 - 2018 ProfitBricks GmbH. All rights reserved. - * Copyright (c) 2018 - 2019 1&1 IONOS Cloud GmbH. All rights reserved. - * Copyright (c) 2019 - 2020 1&1 IONOS SE. All rights reserved. - */ -#include "rnbd-proto.h" - -const char *rnbd_access_mode_str(enum rnbd_access_mode mode) -{ - switch (mode) { - case RNBD_ACCESS_RO: - return "ro"; - case RNBD_ACCESS_RW: - return "rw"; - case RNBD_ACCESS_MIGRATION: - return "migration"; - default: - return "unknown"; - } -} diff --git a/drivers/block/rnbd/rnbd-proto.h b/drivers/block/rnbd/rnbd-proto.h index da1d0542d7e2c243b823a0a50c6fd32359a52c3c..e32f8f2c868a7bd4b7f2241ddc7c0bc568efee5b 100644 --- a/drivers/block/rnbd/rnbd-proto.h +++ b/drivers/block/rnbd/rnbd-proto.h @@ -61,6 +61,15 @@ enum rnbd_access_mode { RNBD_ACCESS_MIGRATION, }; +static const __maybe_unused struct { + enum rnbd_access_mode mode; + const char *str; +} rnbd_access_modes[] = { + [RNBD_ACCESS_RO] = {RNBD_ACCESS_RO, "ro"}, + [RNBD_ACCESS_RW] = {RNBD_ACCESS_RW, "rw"}, + [RNBD_ACCESS_MIGRATION] = {RNBD_ACCESS_MIGRATION, "migration"}, +}; + /** * struct rnbd_msg_sess_info - initial session info from client to server * @hdr: message header @@ -185,7 +194,6 @@ struct rnbd_msg_io { enum rnbd_io_flags { /* Operations */ - RNBD_OP_READ = 0, RNBD_OP_WRITE = 1, RNBD_OP_FLUSH = 2, @@ -193,15 +201,9 @@ enum rnbd_io_flags { RNBD_OP_SECURE_ERASE = 4, RNBD_OP_WRITE_SAME = 5, - RNBD_OP_LAST, - /* Flags */ - RNBD_F_SYNC = 1<<(RNBD_OP_BITS + 0), RNBD_F_FUA = 1<<(RNBD_OP_BITS + 1), - - RNBD_F_ALL = (RNBD_F_SYNC | RNBD_F_FUA) - }; static inline u32 rnbd_op(u32 flags) @@ -214,21 +216,6 @@ static inline u32 rnbd_flags(u32 flags) return flags & ~RNBD_OP_MASK; } -static inline bool rnbd_flags_supported(u32 flags) -{ - u32 op; - - op = rnbd_op(flags); - flags = rnbd_flags(flags); - - if (op >= RNBD_OP_LAST) - return false; - if (flags & ~RNBD_F_ALL) - return false; - - return true; -} - static inline blk_opf_t rnbd_to_bio_flags(u32 rnbd_opf) { blk_opf_t bio_opf; diff --git a/drivers/block/rnbd/rnbd-srv-sysfs.c b/drivers/block/rnbd/rnbd-srv-sysfs.c index d5d9267e1fa5e48a7e494e7890e621810ee31ea2..cba6ba43c2c287f1127ecdc3a408c0c04544d8e4 100644 --- a/drivers/block/rnbd/rnbd-srv-sysfs.c +++ b/drivers/block/rnbd/rnbd-srv-sysfs.c @@ -9,7 +9,6 @@ #undef pr_fmt #define pr_fmt(fmt) KBUILD_MODNAME " L" __stringify(__LINE__) ": " fmt -#include #include #include #include @@ -20,7 +19,9 @@ #include "rnbd-srv.h" static struct device *rnbd_dev; -static struct class *rnbd_dev_class; +static const struct class rnbd_dev_class = { + .name = "rnbd-server", +}; static struct kobject *rnbd_devs_kobj; static void rnbd_srv_dev_release(struct kobject *kobj) @@ -88,8 +89,7 @@ static ssize_t read_only_show(struct kobject *kobj, struct kobj_attribute *attr, sess_dev = container_of(kobj, struct rnbd_srv_sess_dev, kobj); - return sysfs_emit(page, "%d\n", - !(sess_dev->open_flags & FMODE_WRITE)); + return sysfs_emit(page, "%d\n", sess_dev->readonly); } static struct kobj_attribute rnbd_srv_dev_session_ro_attr = @@ -104,7 +104,7 @@ static ssize_t access_mode_show(struct kobject *kobj, sess_dev = container_of(kobj, struct rnbd_srv_sess_dev, kobj); return sysfs_emit(page, "%s\n", - rnbd_access_mode_str(sess_dev->access_mode)); + rnbd_access_modes[sess_dev->access_mode].str); } static struct kobj_attribute rnbd_srv_dev_session_access_mode_attr = @@ -215,12 +215,12 @@ int rnbd_srv_create_sysfs_files(void) { int err; - rnbd_dev_class = class_create("rnbd-server"); - if (IS_ERR(rnbd_dev_class)) - return PTR_ERR(rnbd_dev_class); + err = class_register(&rnbd_dev_class); + if (err) + return err; - rnbd_dev = device_create(rnbd_dev_class, NULL, - MKDEV(0, 0), NULL, "ctl"); + rnbd_dev = device_create(&rnbd_dev_class, NULL, + MKDEV(0, 0), NULL, "ctl"); if (IS_ERR(rnbd_dev)) { err = PTR_ERR(rnbd_dev); goto cls_destroy; @@ -234,9 +234,9 @@ int rnbd_srv_create_sysfs_files(void) return 0; dev_destroy: - device_destroy(rnbd_dev_class, MKDEV(0, 0)); + device_destroy(&rnbd_dev_class, MKDEV(0, 0)); cls_destroy: - class_destroy(rnbd_dev_class); + class_unregister(&rnbd_dev_class); return err; } @@ -245,6 +245,6 @@ void rnbd_srv_destroy_sysfs_files(void) { kobject_del(rnbd_devs_kobj); kobject_put(rnbd_devs_kobj); - device_destroy(rnbd_dev_class, MKDEV(0, 0)); - class_destroy(rnbd_dev_class); + device_destroy(&rnbd_dev_class, MKDEV(0, 0)); + class_unregister(&rnbd_dev_class); } diff --git a/drivers/block/rnbd/rnbd-srv.c b/drivers/block/rnbd/rnbd-srv.c index 2cfed2e58d646f5df11fc4baa6125e1f0527d0e7..c186df0ec641c8cc388cff07942a30dc7a21a51c 100644 --- a/drivers/block/rnbd/rnbd-srv.c +++ b/drivers/block/rnbd/rnbd-srv.c @@ -96,7 +96,7 @@ rnbd_get_sess_dev(int dev_id, struct rnbd_srv_session *srv_sess) ret = kref_get_unless_zero(&sess_dev->kref); rcu_read_unlock(); - if (!sess_dev || !ret) + if (!ret) return ERR_PTR(-ENXIO); return sess_dev; @@ -180,7 +180,7 @@ static void destroy_device(struct kref *kref) WARN_ONCE(!list_empty(&dev->sess_dev_list), "Device %s is being destroyed but still in use!\n", - dev->id); + dev->name); spin_lock(&dev_lock); list_del(&dev->list); @@ -219,10 +219,10 @@ void rnbd_destroy_sess_dev(struct rnbd_srv_sess_dev *sess_dev, bool keep_id) rnbd_put_sess_dev(sess_dev); wait_for_completion(&dc); /* wait for inflights to drop to zero */ - blkdev_put(sess_dev->bdev, sess_dev->open_flags); + blkdev_put(sess_dev->bdev, NULL); mutex_lock(&sess_dev->dev->lock); list_del(&sess_dev->dev_list); - if (sess_dev->open_flags & FMODE_WRITE) + if (!sess_dev->readonly) sess_dev->dev->open_write_cnt--; mutex_unlock(&sess_dev->dev->lock); @@ -356,7 +356,7 @@ static int process_msg_open(struct rnbd_srv_session *srv_sess, const void *msg, size_t len, void *data, size_t datalen); -static int process_msg_sess_info(struct rnbd_srv_session *srv_sess, +static void process_msg_sess_info(struct rnbd_srv_session *srv_sess, const void *msg, size_t len, void *data, size_t datalen); @@ -384,8 +384,7 @@ static int rnbd_srv_rdma_ev(void *priv, struct rtrs_srv_op *id, ret = process_msg_open(srv_sess, usr, usrlen, data, datalen); break; case RNBD_MSG_SESS_INFO: - ret = process_msg_sess_info(srv_sess, usr, usrlen, data, - datalen); + process_msg_sess_info(srv_sess, usr, usrlen, data, datalen); break; default: pr_warn("Received unexpected message type %d from session %s\n", @@ -431,7 +430,7 @@ static struct rnbd_srv_dev *rnbd_srv_init_srv_dev(struct block_device *bdev) if (!dev) return ERR_PTR(-ENOMEM); - snprintf(dev->id, sizeof(dev->id), "%pg", bdev); + snprintf(dev->name, sizeof(dev->name), "%pg", bdev); kref_init(&dev->kref); INIT_LIST_HEAD(&dev->sess_dev_list); mutex_init(&dev->lock); @@ -446,7 +445,7 @@ rnbd_srv_find_or_add_srv_dev(struct rnbd_srv_dev *new_dev) spin_lock(&dev_lock); list_for_each_entry(dev, &dev_list, list) { - if (!strncmp(dev->id, new_dev->id, sizeof(dev->id))) { + if (!strncmp(dev->name, new_dev->name, sizeof(dev->name))) { if (!kref_get_unless_zero(&dev->kref)) /* * We lost the race, device is almost dead. @@ -467,39 +466,38 @@ static int rnbd_srv_check_update_open_perm(struct rnbd_srv_dev *srv_dev, struct rnbd_srv_session *srv_sess, enum rnbd_access_mode access_mode) { - int ret = -EPERM; + int ret = 0; mutex_lock(&srv_dev->lock); switch (access_mode) { case RNBD_ACCESS_RO: - ret = 0; break; case RNBD_ACCESS_RW: if (srv_dev->open_write_cnt == 0) { srv_dev->open_write_cnt++; - ret = 0; } else { pr_err("Mapping device '%s' for session %s with RW permissions failed. Device already opened as 'RW' by %d client(s), access mode %s.\n", - srv_dev->id, srv_sess->sessname, + srv_dev->name, srv_sess->sessname, srv_dev->open_write_cnt, - rnbd_access_mode_str(access_mode)); + rnbd_access_modes[access_mode].str); + ret = -EPERM; } break; case RNBD_ACCESS_MIGRATION: if (srv_dev->open_write_cnt < 2) { srv_dev->open_write_cnt++; - ret = 0; } else { pr_err("Mapping device '%s' for session %s with migration permissions failed. Device already opened as 'RW' by %d client(s), access mode %s.\n", - srv_dev->id, srv_sess->sessname, + srv_dev->name, srv_sess->sessname, srv_dev->open_write_cnt, - rnbd_access_mode_str(access_mode)); + rnbd_access_modes[access_mode].str); + ret = -EPERM; } break; default: pr_err("Received mapping request for device '%s' on session %s with invalid access mode: %d\n", - srv_dev->id, srv_sess->sessname, access_mode); + srv_dev->name, srv_sess->sessname, access_mode); ret = -EINVAL; } @@ -561,7 +559,7 @@ static void rnbd_srv_fill_msg_open_rsp(struct rnbd_msg_open_rsp *rsp, static struct rnbd_srv_sess_dev * rnbd_srv_create_set_sess_dev(struct rnbd_srv_session *srv_sess, const struct rnbd_msg_open *open_msg, - struct block_device *bdev, fmode_t open_flags, + struct block_device *bdev, bool readonly, struct rnbd_srv_dev *srv_dev) { struct rnbd_srv_sess_dev *sdev = rnbd_sess_dev_alloc(srv_sess); @@ -576,7 +574,7 @@ rnbd_srv_create_set_sess_dev(struct rnbd_srv_session *srv_sess, sdev->bdev = bdev; sdev->sess = srv_sess; sdev->dev = srv_dev; - sdev->open_flags = open_flags; + sdev->readonly = readonly; sdev->access_mode = open_msg->access_mode; return sdev; @@ -631,7 +629,7 @@ static char *rnbd_srv_get_full_path(struct rnbd_srv_session *srv_sess, return full_path; } -static int process_msg_sess_info(struct rnbd_srv_session *srv_sess, +static void process_msg_sess_info(struct rnbd_srv_session *srv_sess, const void *msg, size_t len, void *data, size_t datalen) { @@ -644,8 +642,6 @@ static int process_msg_sess_info(struct rnbd_srv_session *srv_sess, rsp->hdr.type = cpu_to_le16(RNBD_MSG_SESS_INFO_RSP); rsp->ver = srv_sess->ver; - - return 0; } /** @@ -681,15 +677,14 @@ static int process_msg_open(struct rnbd_srv_session *srv_sess, struct rnbd_srv_sess_dev *srv_sess_dev; const struct rnbd_msg_open *open_msg = msg; struct block_device *bdev; - fmode_t open_flags; + blk_mode_t open_flags = BLK_OPEN_READ; char *full_path; struct rnbd_msg_open_rsp *rsp = data; trace_process_msg_open(srv_sess, open_msg); - open_flags = FMODE_READ; if (open_msg->access_mode != RNBD_ACCESS_RO) - open_flags |= FMODE_WRITE; + open_flags |= BLK_OPEN_WRITE; mutex_lock(&srv_sess->lock); @@ -719,7 +714,7 @@ static int process_msg_open(struct rnbd_srv_session *srv_sess, goto reject; } - bdev = blkdev_get_by_path(full_path, open_flags, THIS_MODULE); + bdev = blkdev_get_by_path(full_path, open_flags, NULL, NULL); if (IS_ERR(bdev)) { ret = PTR_ERR(bdev); pr_err("Opening device '%s' on session %s failed, failed to open the block device, err: %d\n", @@ -736,9 +731,9 @@ static int process_msg_open(struct rnbd_srv_session *srv_sess, goto blkdev_put; } - srv_sess_dev = rnbd_srv_create_set_sess_dev(srv_sess, open_msg, - bdev, open_flags, - srv_dev); + srv_sess_dev = rnbd_srv_create_set_sess_dev(srv_sess, open_msg, bdev, + open_msg->access_mode == RNBD_ACCESS_RO, + srv_dev); if (IS_ERR(srv_sess_dev)) { pr_err("Opening device '%s' on session %s failed, creating sess_dev failed, err: %ld\n", full_path, srv_sess->sessname, PTR_ERR(srv_sess_dev)); @@ -774,7 +769,7 @@ static int process_msg_open(struct rnbd_srv_session *srv_sess, list_add(&srv_sess_dev->dev_list, &srv_dev->sess_dev_list); mutex_unlock(&srv_dev->lock); - rnbd_srv_info(srv_sess_dev, "Opened device '%s'\n", srv_dev->id); + rnbd_srv_info(srv_sess_dev, "Opened device '%s'\n", srv_dev->name); kfree(full_path); @@ -795,7 +790,7 @@ static int process_msg_open(struct rnbd_srv_session *srv_sess, } rnbd_put_srv_dev(srv_dev); blkdev_put: - blkdev_put(bdev, open_flags); + blkdev_put(bdev, NULL); free_path: kfree(full_path); reject: @@ -808,7 +803,7 @@ static struct rtrs_srv_ctx *rtrs_ctx; static struct rtrs_srv_ops rtrs_ops; static int __init rnbd_srv_init_module(void) { - int err; + int err = 0; BUILD_BUG_ON(sizeof(struct rnbd_msg_hdr) != 4); BUILD_BUG_ON(sizeof(struct rnbd_msg_sess_info) != 36); @@ -822,19 +817,17 @@ static int __init rnbd_srv_init_module(void) }; rtrs_ctx = rtrs_srv_open(&rtrs_ops, port_nr); if (IS_ERR(rtrs_ctx)) { - err = PTR_ERR(rtrs_ctx); pr_err("rtrs_srv_open(), err: %d\n", err); - return err; + return PTR_ERR(rtrs_ctx); } err = rnbd_srv_create_sysfs_files(); if (err) { pr_err("rnbd_srv_create_sysfs_files(), err: %d\n", err); rtrs_srv_close(rtrs_ctx); - return err; } - return 0; + return err; } static void __exit rnbd_srv_cleanup_module(void) diff --git a/drivers/block/rnbd/rnbd-srv.h b/drivers/block/rnbd/rnbd-srv.h index f5962fd31d62e469a9bd7ed786e2bd64fdcca9aa..1027656dedb0a3ef16a3a143be4c330120f45ff7 100644 --- a/drivers/block/rnbd/rnbd-srv.h +++ b/drivers/block/rnbd/rnbd-srv.h @@ -35,7 +35,7 @@ struct rnbd_srv_dev { struct kobject dev_kobj; struct kobject *dev_sessions_kobj; struct kref kref; - char id[NAME_MAX]; + char name[NAME_MAX]; /* List of rnbd_srv_sess_dev structs */ struct list_head sess_dev_list; struct mutex lock; @@ -52,7 +52,7 @@ struct rnbd_srv_sess_dev { struct kobject kobj; u32 device_id; bool keep_id; - fmode_t open_flags; + bool readonly; struct kref kref; struct completion *destroy_comp; char pathname[NAME_MAX]; diff --git a/drivers/block/sunvdc.c b/drivers/block/sunvdc.c index 9fa821fa76b07b47d673f7d57c591fc8e5ddd4a9..7bf4b48e2282e72247d3db519110d4de04b80f14 100644 --- a/drivers/block/sunvdc.c +++ b/drivers/block/sunvdc.c @@ -139,7 +139,7 @@ static int vdc_getgeo(struct block_device *bdev, struct hd_geometry *geo) * when vdisk_mtype is VD_MEDIA_TYPE_CD or VD_MEDIA_TYPE_DVD. * Needed to be able to install inside an ldom from an iso image. */ -static int vdc_ioctl(struct block_device *bdev, fmode_t mode, +static int vdc_ioctl(struct block_device *bdev, blk_mode_t mode, unsigned command, unsigned long argument) { struct vdc_port *port = bdev->bd_disk->private_data; diff --git a/drivers/block/swim.c b/drivers/block/swim.c index 42b4b682869096c351800388f969171619461847..f85b6af414b4318b394665bec1a679f174b31755 100644 --- a/drivers/block/swim.c +++ b/drivers/block/swim.c @@ -608,20 +608,18 @@ static void setup_medium(struct floppy_state *fs) } } -static int floppy_open(struct block_device *bdev, fmode_t mode) +static int floppy_open(struct gendisk *disk, blk_mode_t mode) { - struct floppy_state *fs = bdev->bd_disk->private_data; + struct floppy_state *fs = disk->private_data; struct swim __iomem *base = fs->swd->base; int err; - if (fs->ref_count == -1 || (fs->ref_count && mode & FMODE_EXCL)) + if (fs->ref_count == -1 || (fs->ref_count && mode & BLK_OPEN_EXCL)) return -EBUSY; - - if (mode & FMODE_EXCL) + if (mode & BLK_OPEN_EXCL) fs->ref_count = -1; else fs->ref_count++; - swim_write(base, setup, S_IBM_DRIVE | S_FCLK_DIV2); udelay(10); swim_drive(base, fs->location); @@ -636,13 +634,13 @@ static int floppy_open(struct block_device *bdev, fmode_t mode) set_capacity(fs->disk, fs->total_secs); - if (mode & FMODE_NDELAY) + if (mode & BLK_OPEN_NDELAY) return 0; - if (mode & (FMODE_READ|FMODE_WRITE)) { - if (bdev_check_media_change(bdev) && fs->disk_in) + if (mode & (BLK_OPEN_READ | BLK_OPEN_WRITE)) { + if (disk_check_media_change(disk) && fs->disk_in) fs->ejected = 0; - if ((mode & FMODE_WRITE) && fs->write_protected) { + if ((mode & BLK_OPEN_WRITE) && fs->write_protected) { err = -EROFS; goto out; } @@ -659,18 +657,18 @@ static int floppy_open(struct block_device *bdev, fmode_t mode) return err; } -static int floppy_unlocked_open(struct block_device *bdev, fmode_t mode) +static int floppy_unlocked_open(struct gendisk *disk, blk_mode_t mode) { int ret; mutex_lock(&swim_mutex); - ret = floppy_open(bdev, mode); + ret = floppy_open(disk, mode); mutex_unlock(&swim_mutex); return ret; } -static void floppy_release(struct gendisk *disk, fmode_t mode) +static void floppy_release(struct gendisk *disk) { struct floppy_state *fs = disk->private_data; struct swim __iomem *base = fs->swd->base; @@ -686,7 +684,7 @@ static void floppy_release(struct gendisk *disk, fmode_t mode) mutex_unlock(&swim_mutex); } -static int floppy_ioctl(struct block_device *bdev, fmode_t mode, +static int floppy_ioctl(struct block_device *bdev, blk_mode_t mode, unsigned int cmd, unsigned long param) { struct floppy_state *fs = bdev->bd_disk->private_data; diff --git a/drivers/block/swim3.c b/drivers/block/swim3.c index da811a7da03f3dff1fa3fc2fc37afc3d6aaf0f6d..dc43a63b3469468be6d30043898f92ba97be71f8 100644 --- a/drivers/block/swim3.c +++ b/drivers/block/swim3.c @@ -246,10 +246,9 @@ static int grab_drive(struct floppy_state *fs, enum swim_state state, int interruptible); static void release_drive(struct floppy_state *fs); static int fd_eject(struct floppy_state *fs); -static int floppy_ioctl(struct block_device *bdev, fmode_t mode, +static int floppy_ioctl(struct block_device *bdev, blk_mode_t mode, unsigned int cmd, unsigned long param); -static int floppy_open(struct block_device *bdev, fmode_t mode); -static void floppy_release(struct gendisk *disk, fmode_t mode); +static int floppy_open(struct gendisk *disk, blk_mode_t mode); static unsigned int floppy_check_events(struct gendisk *disk, unsigned int clearing); static int floppy_revalidate(struct gendisk *disk); @@ -883,7 +882,7 @@ static int fd_eject(struct floppy_state *fs) static struct floppy_struct floppy_type = { 2880,18,2,80,0,0x1B,0x00,0xCF,0x6C,NULL }; /* 7 1.44MB 3.5" */ -static int floppy_locked_ioctl(struct block_device *bdev, fmode_t mode, +static int floppy_locked_ioctl(struct block_device *bdev, blk_mode_t mode, unsigned int cmd, unsigned long param) { struct floppy_state *fs = bdev->bd_disk->private_data; @@ -911,7 +910,7 @@ static int floppy_locked_ioctl(struct block_device *bdev, fmode_t mode, return -ENOTTY; } -static int floppy_ioctl(struct block_device *bdev, fmode_t mode, +static int floppy_ioctl(struct block_device *bdev, blk_mode_t mode, unsigned int cmd, unsigned long param) { int ret; @@ -923,9 +922,9 @@ static int floppy_ioctl(struct block_device *bdev, fmode_t mode, return ret; } -static int floppy_open(struct block_device *bdev, fmode_t mode) +static int floppy_open(struct gendisk *disk, blk_mode_t mode) { - struct floppy_state *fs = bdev->bd_disk->private_data; + struct floppy_state *fs = disk->private_data; struct swim3 __iomem *sw = fs->swim3; int n, err = 0; @@ -958,18 +957,18 @@ static int floppy_open(struct block_device *bdev, fmode_t mode) swim3_action(fs, SETMFM); swim3_select(fs, RELAX); - } else if (fs->ref_count == -1 || mode & FMODE_EXCL) + } else if (fs->ref_count == -1 || mode & BLK_OPEN_EXCL) return -EBUSY; - if (err == 0 && (mode & FMODE_NDELAY) == 0 - && (mode & (FMODE_READ|FMODE_WRITE))) { - if (bdev_check_media_change(bdev)) - floppy_revalidate(bdev->bd_disk); + if (err == 0 && !(mode & BLK_OPEN_NDELAY) && + (mode & (BLK_OPEN_READ | BLK_OPEN_WRITE))) { + if (disk_check_media_change(disk)) + floppy_revalidate(disk); if (fs->ejected) err = -ENXIO; } - if (err == 0 && (mode & FMODE_WRITE)) { + if (err == 0 && (mode & BLK_OPEN_WRITE)) { if (fs->write_prot < 0) fs->write_prot = swim3_readbit(fs, WRITE_PROT); if (fs->write_prot) @@ -985,7 +984,7 @@ static int floppy_open(struct block_device *bdev, fmode_t mode) return err; } - if (mode & FMODE_EXCL) + if (mode & BLK_OPEN_EXCL) fs->ref_count = -1; else ++fs->ref_count; @@ -993,18 +992,18 @@ static int floppy_open(struct block_device *bdev, fmode_t mode) return 0; } -static int floppy_unlocked_open(struct block_device *bdev, fmode_t mode) +static int floppy_unlocked_open(struct gendisk *disk, blk_mode_t mode) { int ret; mutex_lock(&swim3_mutex); - ret = floppy_open(bdev, mode); + ret = floppy_open(disk, mode); mutex_unlock(&swim3_mutex); return ret; } -static void floppy_release(struct gendisk *disk, fmode_t mode) +static void floppy_release(struct gendisk *disk) { struct floppy_state *fs = disk->private_data; struct swim3 __iomem *sw = fs->swim3; diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c index 33d3298a0da16f1f70ecc87495f77746f2e6a4af..1c823750c95af139f92b7f8b9f5bdee309e5e02d 100644 --- a/drivers/block/ublk_drv.c +++ b/drivers/block/ublk_drv.c @@ -43,6 +43,7 @@ #include #include #include +#include #include #define UBLK_MINORS (1U << MINORBITS) @@ -54,7 +55,8 @@ | UBLK_F_USER_RECOVERY \ | UBLK_F_USER_RECOVERY_REISSUE \ | UBLK_F_UNPRIVILEGED_DEV \ - | UBLK_F_CMD_IOCTL_ENCODE) + | UBLK_F_CMD_IOCTL_ENCODE \ + | UBLK_F_USER_COPY) /* All UBLK_PARAM_TYPE_* should be included here */ #define UBLK_PARAM_TYPE_ALL (UBLK_PARAM_TYPE_BASIC | \ @@ -62,7 +64,8 @@ struct ublk_rq_data { struct llist_node node; - struct callback_head work; + + struct kref ref; }; struct ublk_uring_cmd_pdu { @@ -182,8 +185,13 @@ struct ublk_params_header { __u32 types; }; +static inline void __ublk_complete_rq(struct request *req); +static void ublk_complete_rq(struct kref *ref); + static dev_t ublk_chr_devt; -static struct class *ublk_chr_class; +static const struct class ublk_chr_class = { + .name = "ublk-char", +}; static DEFINE_IDR(ublk_index_idr); static DEFINE_SPINLOCK(ublk_idr_lock); @@ -202,6 +210,23 @@ static unsigned int ublks_added; /* protected by ublk_ctl_mutex */ static struct miscdevice ublk_misc; +static inline unsigned ublk_pos_to_hwq(loff_t pos) +{ + return ((pos - UBLKSRV_IO_BUF_OFFSET) >> UBLK_QID_OFF) & + UBLK_QID_BITS_MASK; +} + +static inline unsigned ublk_pos_to_buf_off(loff_t pos) +{ + return (pos - UBLKSRV_IO_BUF_OFFSET) & UBLK_IO_BUF_BITS_MASK; +} + +static inline unsigned ublk_pos_to_tag(loff_t pos) +{ + return ((pos - UBLKSRV_IO_BUF_OFFSET) >> UBLK_TAG_OFF) & + UBLK_TAG_BITS_MASK; +} + static void ublk_dev_param_basic_apply(struct ublk_device *ub) { struct request_queue *q = ub->ub_disk->queue; @@ -290,12 +315,52 @@ static int ublk_apply_params(struct ublk_device *ub) return 0; } -static inline bool ublk_can_use_task_work(const struct ublk_queue *ubq) +static inline bool ublk_support_user_copy(const struct ublk_queue *ubq) { - if (IS_BUILTIN(CONFIG_BLK_DEV_UBLK) && - !(ubq->flags & UBLK_F_URING_CMD_COMP_IN_TASK)) - return true; - return false; + return ubq->flags & UBLK_F_USER_COPY; +} + +static inline bool ublk_need_req_ref(const struct ublk_queue *ubq) +{ + /* + * read()/write() is involved in user copy, so request reference + * has to be grabbed + */ + return ublk_support_user_copy(ubq); +} + +static inline void ublk_init_req_ref(const struct ublk_queue *ubq, + struct request *req) +{ + if (ublk_need_req_ref(ubq)) { + struct ublk_rq_data *data = blk_mq_rq_to_pdu(req); + + kref_init(&data->ref); + } +} + +static inline bool ublk_get_req_ref(const struct ublk_queue *ubq, + struct request *req) +{ + if (ublk_need_req_ref(ubq)) { + struct ublk_rq_data *data = blk_mq_rq_to_pdu(req); + + return kref_get_unless_zero(&data->ref); + } + + return true; +} + +static inline void ublk_put_req_ref(const struct ublk_queue *ubq, + struct request *req) +{ + if (ublk_need_req_ref(ubq)) { + struct ublk_rq_data *data = blk_mq_rq_to_pdu(req); + + kref_put(&data->ref, ublk_complete_rq); + } else { + __ublk_complete_rq(req); + } } static inline bool ublk_need_get_data(const struct ublk_queue *ubq) @@ -384,9 +449,9 @@ static void ublk_store_owner_uid_gid(unsigned int *owner_uid, *owner_gid = from_kgid(&init_user_ns, gid); } -static int ublk_open(struct block_device *bdev, fmode_t mode) +static int ublk_open(struct gendisk *disk, blk_mode_t mode) { - struct ublk_device *ub = bdev->bd_disk->private_data; + struct ublk_device *ub = disk->private_data; if (capable(CAP_SYS_ADMIN)) return 0; @@ -421,49 +486,39 @@ static const struct block_device_operations ub_fops = { #define UBLK_MAX_PIN_PAGES 32 -struct ublk_map_data { - const struct request *rq; - unsigned long ubuf; - unsigned int len; -}; - struct ublk_io_iter { struct page *pages[UBLK_MAX_PIN_PAGES]; - unsigned pg_off; /* offset in the 1st page in pages */ - int nr_pages; /* how many page pointers in pages */ struct bio *bio; struct bvec_iter iter; }; -static inline unsigned ublk_copy_io_pages(struct ublk_io_iter *data, - unsigned max_bytes, bool to_vm) +/* return how many pages are copied */ +static void ublk_copy_io_pages(struct ublk_io_iter *data, + size_t total, size_t pg_off, int dir) { - const unsigned total = min_t(unsigned, max_bytes, - PAGE_SIZE - data->pg_off + - ((data->nr_pages - 1) << PAGE_SHIFT)); unsigned done = 0; unsigned pg_idx = 0; while (done < total) { struct bio_vec bv = bio_iter_iovec(data->bio, data->iter); - const unsigned int bytes = min3(bv.bv_len, total - done, - (unsigned)(PAGE_SIZE - data->pg_off)); + unsigned int bytes = min3(bv.bv_len, (unsigned)total - done, + (unsigned)(PAGE_SIZE - pg_off)); void *bv_buf = bvec_kmap_local(&bv); void *pg_buf = kmap_local_page(data->pages[pg_idx]); - if (to_vm) - memcpy(pg_buf + data->pg_off, bv_buf, bytes); + if (dir == ITER_DEST) + memcpy(pg_buf + pg_off, bv_buf, bytes); else - memcpy(bv_buf, pg_buf + data->pg_off, bytes); + memcpy(bv_buf, pg_buf + pg_off, bytes); kunmap_local(pg_buf); kunmap_local(bv_buf); /* advance page array */ - data->pg_off += bytes; - if (data->pg_off == PAGE_SIZE) { + pg_off += bytes; + if (pg_off == PAGE_SIZE) { pg_idx += 1; - data->pg_off = 0; + pg_off = 0; } done += bytes; @@ -477,41 +532,58 @@ static inline unsigned ublk_copy_io_pages(struct ublk_io_iter *data, data->iter = data->bio->bi_iter; } } +} - return done; +static bool ublk_advance_io_iter(const struct request *req, + struct ublk_io_iter *iter, unsigned int offset) +{ + struct bio *bio = req->bio; + + for_each_bio(bio) { + if (bio->bi_iter.bi_size > offset) { + iter->bio = bio; + iter->iter = bio->bi_iter; + bio_advance_iter(iter->bio, &iter->iter, offset); + return true; + } + offset -= bio->bi_iter.bi_size; + } + return false; } -static int ublk_copy_user_pages(struct ublk_map_data *data, bool to_vm) +/* + * Copy data between request pages and io_iter, and 'offset' + * is the start point of linear offset of request. + */ +static size_t ublk_copy_user_pages(const struct request *req, + unsigned offset, struct iov_iter *uiter, int dir) { - const unsigned int gup_flags = to_vm ? FOLL_WRITE : 0; - const unsigned long start_vm = data->ubuf; - unsigned int done = 0; - struct ublk_io_iter iter = { - .pg_off = start_vm & (PAGE_SIZE - 1), - .bio = data->rq->bio, - .iter = data->rq->bio->bi_iter, - }; - const unsigned int nr_pages = round_up(data->len + - (start_vm & (PAGE_SIZE - 1)), PAGE_SIZE) >> PAGE_SHIFT; - - while (done < nr_pages) { - const unsigned to_pin = min_t(unsigned, UBLK_MAX_PIN_PAGES, - nr_pages - done); - unsigned i, len; - - iter.nr_pages = get_user_pages_fast(start_vm + - (done << PAGE_SHIFT), to_pin, gup_flags, - iter.pages); - if (iter.nr_pages <= 0) - return done == 0 ? iter.nr_pages : done; - len = ublk_copy_io_pages(&iter, data->len, to_vm); - for (i = 0; i < iter.nr_pages; i++) { - if (to_vm) + struct ublk_io_iter iter; + size_t done = 0; + + if (!ublk_advance_io_iter(req, &iter, offset)) + return 0; + + while (iov_iter_count(uiter) && iter.bio) { + unsigned nr_pages; + ssize_t len; + size_t off; + int i; + + len = iov_iter_get_pages2(uiter, iter.pages, + iov_iter_count(uiter), + UBLK_MAX_PIN_PAGES, &off); + if (len <= 0) + return done; + + ublk_copy_io_pages(&iter, len, off, dir); + nr_pages = DIV_ROUND_UP(len + off, PAGE_SIZE); + for (i = 0; i < nr_pages; i++) { + if (dir == ITER_DEST) set_page_dirty(iter.pages[i]); put_page(iter.pages[i]); } - data->len -= len; - done += iter.nr_pages; + done += len; } return done; @@ -532,21 +604,23 @@ static int ublk_map_io(const struct ublk_queue *ubq, const struct request *req, { const unsigned int rq_bytes = blk_rq_bytes(req); + if (ublk_support_user_copy(ubq)) + return rq_bytes; + /* * no zero copy, we delay copy WRITE request data into ublksrv * context and the big benefit is that pinning pages in current * context is pretty fast, see ublk_pin_user_pages */ if (ublk_need_map_req(req)) { - struct ublk_map_data data = { - .rq = req, - .ubuf = io->addr, - .len = rq_bytes, - }; + struct iov_iter iter; + struct iovec iov; + const int dir = ITER_DEST; - ublk_copy_user_pages(&data, true); + import_single_range(dir, u64_to_user_ptr(io->addr), rq_bytes, + &iov, &iter); - return rq_bytes - data.len; + return ublk_copy_user_pages(req, 0, &iter, dir); } return rq_bytes; } @@ -557,18 +631,19 @@ static int ublk_unmap_io(const struct ublk_queue *ubq, { const unsigned int rq_bytes = blk_rq_bytes(req); + if (ublk_support_user_copy(ubq)) + return rq_bytes; + if (ublk_need_unmap_req(req)) { - struct ublk_map_data data = { - .rq = req, - .ubuf = io->addr, - .len = io->res, - }; + struct iov_iter iter; + struct iovec iov; + const int dir = ITER_SOURCE; WARN_ON_ONCE(io->res > rq_bytes); - ublk_copy_user_pages(&data, false); - - return io->res - data.len; + import_single_range(dir, u64_to_user_ptr(io->addr), io->res, + &iov, &iter); + return ublk_copy_user_pages(req, 0, &iter, dir); } return rq_bytes; } @@ -648,13 +723,19 @@ static inline bool ubq_daemon_is_dying(struct ublk_queue *ubq) } /* todo: handle partial completion */ -static void ublk_complete_rq(struct request *req) +static inline void __ublk_complete_rq(struct request *req) { struct ublk_queue *ubq = req->mq_hctx->driver_data; struct ublk_io *io = &ubq->ios[req->tag]; unsigned int unmapped_bytes; blk_status_t res = BLK_STS_OK; + /* called from ublk_abort_queue() code path */ + if (io->flags & UBLK_IO_FLAG_ABORTED) { + res = BLK_STS_IOERR; + goto exit; + } + /* failed read IO if nothing is read */ if (!io->res && req_op(req) == REQ_OP_READ) io->res = -EIO; @@ -694,6 +775,15 @@ static void ublk_complete_rq(struct request *req) blk_mq_end_request(req, res); } +static void ublk_complete_rq(struct kref *ref) +{ + struct ublk_rq_data *data = container_of(ref, struct ublk_rq_data, + ref); + struct request *req = blk_mq_rq_from_pdu(data); + + __ublk_complete_rq(req); +} + /* * Since __ublk_rq_task_work always fails requests immediately during * exiting, __ublk_fail_req() is only called from abort context during @@ -712,7 +802,7 @@ static void __ublk_fail_req(struct ublk_queue *ubq, struct ublk_io *io, if (ublk_queue_can_use_recovery_reissue(ubq)) blk_mq_requeue_request(req, false); else - blk_mq_end_request(req, BLK_STS_IOERR); + ublk_put_req_ref(ubq, req); } } @@ -821,6 +911,7 @@ static inline void __ublk_rq_task_work(struct request *req, mapped_bytes >> 9; } + ublk_init_req_ref(ubq, req); ubq_complete_io_cmd(io, UBLK_IO_RES_OK, issue_flags); } @@ -852,17 +943,6 @@ static void ublk_rq_task_work_cb(struct io_uring_cmd *cmd, unsigned issue_flags) ublk_forward_io_cmds(ubq, issue_flags); } -static void ublk_rq_task_work_fn(struct callback_head *work) -{ - struct ublk_rq_data *data = container_of(work, - struct ublk_rq_data, work); - struct request *req = blk_mq_rq_from_pdu(data); - struct ublk_queue *ubq = req->mq_hctx->driver_data; - unsigned issue_flags = IO_URING_F_UNLOCKED; - - ublk_forward_io_cmds(ubq, issue_flags); -} - static void ublk_queue_cmd(struct ublk_queue *ubq, struct request *rq) { struct ublk_rq_data *data = blk_mq_rq_to_pdu(rq); @@ -886,10 +966,6 @@ static void ublk_queue_cmd(struct ublk_queue *ubq, struct request *rq) */ if (unlikely(io->flags & UBLK_IO_FLAG_ABORTED)) { ublk_abort_io_cmds(ubq); - } else if (ublk_can_use_task_work(ubq)) { - if (task_work_add(ubq->ubq_daemon, &data->work, - TWA_SIGNAL_NO_IPI)) - ublk_abort_io_cmds(ubq); } else { struct io_uring_cmd *cmd = io->cmd; struct ublk_uring_cmd_pdu *pdu = ublk_get_uring_cmd_pdu(cmd); @@ -961,19 +1037,9 @@ static int ublk_init_hctx(struct blk_mq_hw_ctx *hctx, void *driver_data, return 0; } -static int ublk_init_rq(struct blk_mq_tag_set *set, struct request *req, - unsigned int hctx_idx, unsigned int numa_node) -{ - struct ublk_rq_data *data = blk_mq_rq_to_pdu(req); - - init_task_work(&data->work, ublk_rq_task_work_fn); - return 0; -} - static const struct blk_mq_ops ublk_mq_ops = { .queue_rq = ublk_queue_rq, .init_hctx = ublk_init_hctx, - .init_request = ublk_init_rq, .timeout = ublk_timeout, }; @@ -1050,7 +1116,7 @@ static void ublk_commit_completion(struct ublk_device *ub, req = blk_mq_tag_to_rq(ub->tag_set.tags[qid], tag); if (req && likely(!blk_should_fake_timeout(req->q))) - ublk_complete_rq(req); + ublk_put_req_ref(ubq, req); } /* @@ -1295,6 +1361,14 @@ static inline int ublk_check_cmd_op(u32 cmd_op) return 0; } +static inline void ublk_fill_io_cmd(struct ublk_io *io, + struct io_uring_cmd *cmd, unsigned long buf_addr) +{ + io->cmd = cmd; + io->flags |= UBLK_IO_FLAG_ACTIVE; + io->addr = buf_addr; +} + static int __ublk_ch_uring_cmd(struct io_uring_cmd *cmd, unsigned int issue_flags, const struct ublksrv_io_cmd *ub_cmd) @@ -1340,6 +1414,11 @@ static int __ublk_ch_uring_cmd(struct io_uring_cmd *cmd, ^ (_IOC_NR(cmd_op) == UBLK_IO_NEED_GET_DATA)) goto out; + if (ublk_support_user_copy(ubq) && ub_cmd->addr) { + ret = -EINVAL; + goto out; + } + ret = ublk_check_cmd_op(cmd_op); if (ret) goto out; @@ -1358,36 +1437,41 @@ static int __ublk_ch_uring_cmd(struct io_uring_cmd *cmd, */ if (io->flags & UBLK_IO_FLAG_OWNED_BY_SRV) goto out; - /* FETCH_RQ has to provide IO buffer if NEED GET DATA is not enabled */ - if (!ub_cmd->addr && !ublk_need_get_data(ubq)) - goto out; - io->cmd = cmd; - io->flags |= UBLK_IO_FLAG_ACTIVE; - io->addr = ub_cmd->addr; + if (!ublk_support_user_copy(ubq)) { + /* + * FETCH_RQ has to provide IO buffer if NEED GET + * DATA is not enabled + */ + if (!ub_cmd->addr && !ublk_need_get_data(ubq)) + goto out; + } + + ublk_fill_io_cmd(io, cmd, ub_cmd->addr); ublk_mark_io_ready(ub, ubq); break; case UBLK_IO_COMMIT_AND_FETCH_REQ: req = blk_mq_tag_to_rq(ub->tag_set.tags[ub_cmd->q_id], tag); - /* - * COMMIT_AND_FETCH_REQ has to provide IO buffer if NEED GET DATA is - * not enabled or it is Read IO. - */ - if (!ub_cmd->addr && (!ublk_need_get_data(ubq) || req_op(req) == REQ_OP_READ)) - goto out; + if (!(io->flags & UBLK_IO_FLAG_OWNED_BY_SRV)) goto out; - io->addr = ub_cmd->addr; - io->flags |= UBLK_IO_FLAG_ACTIVE; - io->cmd = cmd; + + if (!ublk_support_user_copy(ubq)) { + /* + * COMMIT_AND_FETCH_REQ has to provide IO buffer if + * NEED GET DATA is not enabled or it is Read IO. + */ + if (!ub_cmd->addr && (!ublk_need_get_data(ubq) || + req_op(req) == REQ_OP_READ)) + goto out; + } + ublk_fill_io_cmd(io, cmd, ub_cmd->addr); ublk_commit_completion(ub, ub_cmd); break; case UBLK_IO_NEED_GET_DATA: if (!(io->flags & UBLK_IO_FLAG_OWNED_BY_SRV)) goto out; - io->addr = ub_cmd->addr; - io->cmd = cmd; - io->flags |= UBLK_IO_FLAG_ACTIVE; + ublk_fill_io_cmd(io, cmd, ub_cmd->addr); ublk_handle_need_get_data(ub, ub_cmd->q_id, ub_cmd->tag); break; default: @@ -1402,6 +1486,36 @@ static int __ublk_ch_uring_cmd(struct io_uring_cmd *cmd, return -EIOCBQUEUED; } +static inline struct request *__ublk_check_and_get_req(struct ublk_device *ub, + struct ublk_queue *ubq, int tag, size_t offset) +{ + struct request *req; + + if (!ublk_need_req_ref(ubq)) + return NULL; + + req = blk_mq_tag_to_rq(ub->tag_set.tags[ubq->q_id], tag); + if (!req) + return NULL; + + if (!ublk_get_req_ref(ubq, req)) + return NULL; + + if (unlikely(!blk_mq_request_started(req) || req->tag != tag)) + goto fail_put; + + if (!ublk_rq_has_data(req)) + goto fail_put; + + if (offset > blk_rq_bytes(req)) + goto fail_put; + + return req; +fail_put: + ublk_put_req_ref(ubq, req); + return NULL; +} + static int ublk_ch_uring_cmd(struct io_uring_cmd *cmd, unsigned int issue_flags) { /* @@ -1419,11 +1533,112 @@ static int ublk_ch_uring_cmd(struct io_uring_cmd *cmd, unsigned int issue_flags) return __ublk_ch_uring_cmd(cmd, issue_flags, &ub_cmd); } +static inline bool ublk_check_ubuf_dir(const struct request *req, + int ubuf_dir) +{ + /* copy ubuf to request pages */ + if (req_op(req) == REQ_OP_READ && ubuf_dir == ITER_SOURCE) + return true; + + /* copy request pages to ubuf */ + if (req_op(req) == REQ_OP_WRITE && ubuf_dir == ITER_DEST) + return true; + + return false; +} + +static struct request *ublk_check_and_get_req(struct kiocb *iocb, + struct iov_iter *iter, size_t *off, int dir) +{ + struct ublk_device *ub = iocb->ki_filp->private_data; + struct ublk_queue *ubq; + struct request *req; + size_t buf_off; + u16 tag, q_id; + + if (!ub) + return ERR_PTR(-EACCES); + + if (!user_backed_iter(iter)) + return ERR_PTR(-EACCES); + + if (ub->dev_info.state == UBLK_S_DEV_DEAD) + return ERR_PTR(-EACCES); + + tag = ublk_pos_to_tag(iocb->ki_pos); + q_id = ublk_pos_to_hwq(iocb->ki_pos); + buf_off = ublk_pos_to_buf_off(iocb->ki_pos); + + if (q_id >= ub->dev_info.nr_hw_queues) + return ERR_PTR(-EINVAL); + + ubq = ublk_get_queue(ub, q_id); + if (!ubq) + return ERR_PTR(-EINVAL); + + if (tag >= ubq->q_depth) + return ERR_PTR(-EINVAL); + + req = __ublk_check_and_get_req(ub, ubq, tag, buf_off); + if (!req) + return ERR_PTR(-EINVAL); + + if (!req->mq_hctx || !req->mq_hctx->driver_data) + goto fail; + + if (!ublk_check_ubuf_dir(req, dir)) + goto fail; + + *off = buf_off; + return req; +fail: + ublk_put_req_ref(ubq, req); + return ERR_PTR(-EACCES); +} + +static ssize_t ublk_ch_read_iter(struct kiocb *iocb, struct iov_iter *to) +{ + struct ublk_queue *ubq; + struct request *req; + size_t buf_off; + size_t ret; + + req = ublk_check_and_get_req(iocb, to, &buf_off, ITER_DEST); + if (IS_ERR(req)) + return PTR_ERR(req); + + ret = ublk_copy_user_pages(req, buf_off, to, ITER_DEST); + ubq = req->mq_hctx->driver_data; + ublk_put_req_ref(ubq, req); + + return ret; +} + +static ssize_t ublk_ch_write_iter(struct kiocb *iocb, struct iov_iter *from) +{ + struct ublk_queue *ubq; + struct request *req; + size_t buf_off; + size_t ret; + + req = ublk_check_and_get_req(iocb, from, &buf_off, ITER_SOURCE); + if (IS_ERR(req)) + return PTR_ERR(req); + + ret = ublk_copy_user_pages(req, buf_off, from, ITER_SOURCE); + ubq = req->mq_hctx->driver_data; + ublk_put_req_ref(ubq, req); + + return ret; +} + static const struct file_operations ublk_ch_fops = { .owner = THIS_MODULE, .open = ublk_ch_open, .release = ublk_ch_release, .llseek = no_llseek, + .read_iter = ublk_ch_read_iter, + .write_iter = ublk_ch_write_iter, .uring_cmd = ublk_ch_uring_cmd, .mmap = ublk_ch_mmap, }; @@ -1547,7 +1762,7 @@ static int ublk_add_chdev(struct ublk_device *ub) dev->parent = ublk_misc.this_device; dev->devt = MKDEV(MAJOR(ublk_chr_devt), minor); - dev->class = ublk_chr_class; + dev->class = &ublk_chr_class; dev->release = ublk_cdev_rel; device_initialize(dev); @@ -1818,10 +2033,12 @@ static int ublk_ctrl_add_dev(struct io_uring_cmd *cmd) */ ub->dev_info.flags &= UBLK_F_ALL; - if (!IS_BUILTIN(CONFIG_BLK_DEV_UBLK)) - ub->dev_info.flags |= UBLK_F_URING_CMD_COMP_IN_TASK; + ub->dev_info.flags |= UBLK_F_CMD_IOCTL_ENCODE | + UBLK_F_URING_CMD_COMP_IN_TASK; - ub->dev_info.flags |= UBLK_F_CMD_IOCTL_ENCODE; + /* GET_DATA isn't needed any more with USER_COPY */ + if (ub->dev_info.flags & UBLK_F_USER_COPY) + ub->dev_info.flags &= ~UBLK_F_NEED_GET_DATA; /* We are not ready to support zero copy */ ub->dev_info.flags &= ~UBLK_F_SUPPORT_ZERO_COPY; @@ -2133,6 +2350,21 @@ static int ublk_ctrl_end_recovery(struct ublk_device *ub, return ret; } +static int ublk_ctrl_get_features(struct io_uring_cmd *cmd) +{ + const struct ublksrv_ctrl_cmd *header = io_uring_sqe_cmd(cmd->sqe); + void __user *argp = (void __user *)(unsigned long)header->addr; + u64 features = UBLK_F_ALL & ~UBLK_F_SUPPORT_ZERO_COPY; + + if (header->len != UBLK_FEATURES_LEN || !header->addr) + return -EINVAL; + + if (copy_to_user(argp, &features, UBLK_FEATURES_LEN)) + return -EFAULT; + + return 0; +} + /* * All control commands are sent via /dev/ublk-control, so we have to check * the destination device's permission @@ -2213,6 +2445,7 @@ static int ublk_ctrl_uring_cmd_permission(struct ublk_device *ub, case UBLK_CMD_GET_DEV_INFO2: case UBLK_CMD_GET_QUEUE_AFFINITY: case UBLK_CMD_GET_PARAMS: + case (_IOC_NR(UBLK_U_CMD_GET_FEATURES)): mask = MAY_READ; break; case UBLK_CMD_START_DEV: @@ -2262,6 +2495,11 @@ static int ublk_ctrl_uring_cmd(struct io_uring_cmd *cmd, if (ret) goto out; + if (cmd_op == UBLK_U_CMD_GET_FEATURES) { + ret = ublk_ctrl_get_features(cmd); + goto out; + } + if (_IOC_NR(cmd_op) != UBLK_CMD_ADD_DEV) { ret = -ENODEV; ub = ublk_get_device_from_id(header->dev_id); @@ -2337,6 +2575,9 @@ static int __init ublk_init(void) { int ret; + BUILD_BUG_ON((u64)UBLKSRV_IO_BUF_OFFSET + + UBLKSRV_IO_BUF_TOTAL_SIZE < UBLKSRV_IO_BUF_OFFSET); + init_waitqueue_head(&ublk_idr_wq); ret = misc_register(&ublk_misc); @@ -2347,11 +2588,10 @@ static int __init ublk_init(void) if (ret) goto unregister_mis; - ublk_chr_class = class_create("ublk-char"); - if (IS_ERR(ublk_chr_class)) { - ret = PTR_ERR(ublk_chr_class); + ret = class_register(&ublk_chr_class); + if (ret) goto free_chrdev_region; - } + return 0; free_chrdev_region: @@ -2369,7 +2609,7 @@ static void __exit ublk_exit(void) idr_for_each_entry(&ublk_index_idr, ub, id) ublk_remove(ub); - class_destroy(ublk_chr_class); + class_unregister(&ublk_chr_class); misc_deregister(&ublk_misc); idr_destroy(&ublk_index_idr); diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index 2b918e28acaacd973221e56344977053072f7f7d..1fe011676d070ed275490e0f265ca958f8b080bf 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c @@ -348,63 +348,33 @@ static inline void virtblk_request_done(struct request *req) blk_mq_end_request(req, status); } -static void virtblk_complete_batch(struct io_comp_batch *iob) -{ - struct request *req; - - rq_list_for_each(&iob->req_list, req) { - virtblk_unmap_data(req, blk_mq_rq_to_pdu(req)); - virtblk_cleanup_cmd(req); - } - blk_mq_end_request_batch(iob); -} - -static int virtblk_handle_req(struct virtio_blk_vq *vq, - struct io_comp_batch *iob) -{ - struct virtblk_req *vbr; - int req_done = 0; - unsigned int len; - - while ((vbr = virtqueue_get_buf(vq->vq, &len)) != NULL) { - struct request *req = blk_mq_rq_from_pdu(vbr); - - if (likely(!blk_should_fake_timeout(req->q)) && - !blk_mq_complete_request_remote(req) && - !blk_mq_add_to_batch(req, iob, virtblk_vbr_status(vbr), - virtblk_complete_batch)) - virtblk_request_done(req); - req_done++; - } - - return req_done; -} - static void virtblk_done(struct virtqueue *vq) { struct virtio_blk *vblk = vq->vdev->priv; - struct virtio_blk_vq *vblk_vq = &vblk->vqs[vq->index]; - int req_done = 0; + bool req_done = false; + int qid = vq->index; + struct virtblk_req *vbr; unsigned long flags; - DEFINE_IO_COMP_BATCH(iob); + unsigned int len; - spin_lock_irqsave(&vblk_vq->lock, flags); + spin_lock_irqsave(&vblk->vqs[qid].lock, flags); do { virtqueue_disable_cb(vq); - req_done += virtblk_handle_req(vblk_vq, &iob); + while ((vbr = virtqueue_get_buf(vblk->vqs[qid].vq, &len)) != NULL) { + struct request *req = blk_mq_rq_from_pdu(vbr); + if (likely(!blk_should_fake_timeout(req->q))) + blk_mq_complete_request(req); + req_done = true; + } if (unlikely(virtqueue_is_broken(vq))) break; } while (!virtqueue_enable_cb(vq)); - if (req_done) { - if (!rq_list_empty(iob.req_list)) - iob.complete(&iob); - - /* In case queue is stopped waiting for more buffers. */ + /* In case queue is stopped waiting for more buffers. */ + if (req_done) blk_mq_start_stopped_hw_queues(vblk->disk->queue, true); - } - spin_unlock_irqrestore(&vblk_vq->lock, flags); + spin_unlock_irqrestore(&vblk->vqs[qid].lock, flags); } static void virtio_commit_rqs(struct blk_mq_hw_ctx *hctx) @@ -781,7 +751,6 @@ static int virtblk_probe_zoned_device(struct virtio_device *vdev, { u32 v, wg; u8 model; - int ret; virtio_cread(vdev, struct virtio_blk_config, zoned.model, &model); @@ -836,6 +805,7 @@ static int virtblk_probe_zoned_device(struct virtio_device *vdev, vblk->zone_sectors); return -ENODEV; } + blk_queue_chunk_sectors(q, vblk->zone_sectors); dev_dbg(&vdev->dev, "zone sectors = %u\n", vblk->zone_sectors); if (virtio_has_feature(vdev, VIRTIO_BLK_F_DISCARD)) { @@ -844,26 +814,22 @@ static int virtblk_probe_zoned_device(struct virtio_device *vdev, blk_queue_max_discard_sectors(q, 0); } - ret = blk_revalidate_disk_zones(vblk->disk, NULL); - if (!ret) { - virtio_cread(vdev, struct virtio_blk_config, - zoned.max_append_sectors, &v); - if (!v) { - dev_warn(&vdev->dev, "zero max_append_sectors reported\n"); - return -ENODEV; - } - if ((v << SECTOR_SHIFT) < wg) { - dev_err(&vdev->dev, - "write granularity %u exceeds max_append_sectors %u limit\n", - wg, v); - return -ENODEV; - } - - blk_queue_max_zone_append_sectors(q, v); - dev_dbg(&vdev->dev, "max append sectors = %u\n", v); + virtio_cread(vdev, struct virtio_blk_config, + zoned.max_append_sectors, &v); + if (!v) { + dev_warn(&vdev->dev, "zero max_append_sectors reported\n"); + return -ENODEV; } + if ((v << SECTOR_SHIFT) < wg) { + dev_err(&vdev->dev, + "write granularity %u exceeds max_append_sectors %u limit\n", + wg, v); + return -ENODEV; + } + blk_queue_max_zone_append_sectors(q, v); + dev_dbg(&vdev->dev, "max append sectors = %u\n", v); - return ret; + return blk_revalidate_disk_zones(vblk->disk, NULL); } #else @@ -1283,15 +1249,37 @@ static void virtblk_map_queues(struct blk_mq_tag_set *set) } } +static void virtblk_complete_batch(struct io_comp_batch *iob) +{ + struct request *req; + + rq_list_for_each(&iob->req_list, req) { + virtblk_unmap_data(req, blk_mq_rq_to_pdu(req)); + virtblk_cleanup_cmd(req); + } + blk_mq_end_request_batch(iob); +} + static int virtblk_poll(struct blk_mq_hw_ctx *hctx, struct io_comp_batch *iob) { struct virtio_blk *vblk = hctx->queue->queuedata; struct virtio_blk_vq *vq = get_virtio_blk_vq(hctx); + struct virtblk_req *vbr; unsigned long flags; + unsigned int len; int found = 0; spin_lock_irqsave(&vq->lock, flags); - found = virtblk_handle_req(vq, iob); + + while ((vbr = virtqueue_get_buf(vq->vq, &len)) != NULL) { + struct request *req = blk_mq_rq_from_pdu(vbr); + + found++; + if (!blk_mq_complete_request_remote(req) && + !blk_mq_add_to_batch(req, iob, virtblk_vbr_status(vbr), + virtblk_complete_batch)) + virtblk_request_done(req); + } if (found) blk_mq_start_stopped_hw_queues(vblk->disk->queue, true); diff --git a/drivers/block/xen-blkback/xenbus.c b/drivers/block/xen-blkback/xenbus.c index 4807af1d58059394d7a992335dabaf2bc3901721..bb66178c432b0da183f85d1a119e18a74a1781fa 100644 --- a/drivers/block/xen-blkback/xenbus.c +++ b/drivers/block/xen-blkback/xenbus.c @@ -473,7 +473,7 @@ static void xenvbd_sysfs_delif(struct xenbus_device *dev) static void xen_vbd_free(struct xen_vbd *vbd) { if (vbd->bdev) - blkdev_put(vbd->bdev, vbd->readonly ? FMODE_READ : FMODE_WRITE); + blkdev_put(vbd->bdev, NULL); vbd->bdev = NULL; } @@ -492,7 +492,7 @@ static int xen_vbd_create(struct xen_blkif *blkif, blkif_vdev_t handle, vbd->pdevice = MKDEV(major, minor); bdev = blkdev_get_by_dev(vbd->pdevice, vbd->readonly ? - FMODE_READ : FMODE_WRITE, NULL); + BLK_OPEN_READ : BLK_OPEN_WRITE, NULL, NULL); if (IS_ERR(bdev)) { pr_warn("xen_vbd_create: device %08x could not be opened\n", diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c index c1890c8a9f6e7640d874237a988437ff4aa264d7..434fab306777439754a0f9feed417f848b2442a4 100644 --- a/drivers/block/xen-blkfront.c +++ b/drivers/block/xen-blkfront.c @@ -509,7 +509,7 @@ static int blkif_getgeo(struct block_device *bd, struct hd_geometry *hg) return 0; } -static int blkif_ioctl(struct block_device *bdev, fmode_t mode, +static int blkif_ioctl(struct block_device *bdev, blk_mode_t mode, unsigned command, unsigned long argument) { struct blkfront_info *info = bdev->bd_disk->private_data; diff --git a/drivers/block/z2ram.c b/drivers/block/z2ram.c index c1e85f356e4dfb518dcdc993dbfc73a3679824eb..11493167b0a848a255b5db442f97cb71e3f97e6a 100644 --- a/drivers/block/z2ram.c +++ b/drivers/block/z2ram.c @@ -140,16 +140,14 @@ static void get_chipram(void) return; } -static int z2_open(struct block_device *bdev, fmode_t mode) +static int z2_open(struct gendisk *disk, blk_mode_t mode) { - int device; + int device = disk->first_minor; int max_z2_map = (Z2RAM_SIZE / Z2RAM_CHUNKSIZE) * sizeof(z2ram_map[0]); int max_chip_map = (amiga_chip_size / Z2RAM_CHUNKSIZE) * sizeof(z2ram_map[0]); int rc = -ENOMEM; - device = MINOR(bdev->bd_dev); - mutex_lock(&z2ram_mutex); if (current_device != -1 && current_device != device) { rc = -EBUSY; @@ -290,7 +288,7 @@ static int z2_open(struct block_device *bdev, fmode_t mode) return rc; } -static void z2_release(struct gendisk *disk, fmode_t mode) +static void z2_release(struct gendisk *disk) { mutex_lock(&z2ram_mutex); if (current_device == -1) { diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c index f6d90f1ba5cf7b9d3d86cc87c88f2f239d76470b..5676e6dd5b1672a8a0ff2798afa0a6cb4f5f8a59 100644 --- a/drivers/block/zram/zram_drv.c +++ b/drivers/block/zram/zram_drv.c @@ -420,7 +420,7 @@ static void reset_bdev(struct zram *zram) return; bdev = zram->bdev; - blkdev_put(bdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL); + blkdev_put(bdev, zram); /* hope filp_close flush all of IO */ filp_close(zram->backing_dev, NULL); zram->backing_dev = NULL; @@ -507,8 +507,8 @@ static ssize_t backing_dev_store(struct device *dev, goto out; } - bdev = blkdev_get_by_dev(inode->i_rdev, - FMODE_READ | FMODE_WRITE | FMODE_EXCL, zram); + bdev = blkdev_get_by_dev(inode->i_rdev, BLK_OPEN_READ | BLK_OPEN_WRITE, + zram, NULL); if (IS_ERR(bdev)) { err = PTR_ERR(bdev); bdev = NULL; @@ -539,7 +539,7 @@ static ssize_t backing_dev_store(struct device *dev, kvfree(bitmap); if (bdev) - blkdev_put(bdev, FMODE_READ | FMODE_WRITE | FMODE_EXCL); + blkdev_put(bdev, zram); if (backing_dev) filp_close(backing_dev, NULL); @@ -700,7 +700,7 @@ static ssize_t writeback_store(struct device *dev, bio_init(&bio, zram->bdev, &bio_vec, 1, REQ_OP_WRITE | REQ_SYNC); bio.bi_iter.bi_sector = blk_idx * (PAGE_SIZE >> 9); - bio_add_page(&bio, page, PAGE_SIZE, 0); + __bio_add_page(&bio, page, PAGE_SIZE, 0); /* * XXX: A single page IO would be inefficient for write @@ -1753,7 +1753,7 @@ static ssize_t recompress_store(struct device *dev, } } - if (threshold >= PAGE_SIZE) + if (threshold >= huge_class_size) return -EINVAL; down_read(&zram->init_lock); @@ -2097,19 +2097,16 @@ static ssize_t reset_store(struct device *dev, return len; } -static int zram_open(struct block_device *bdev, fmode_t mode) +static int zram_open(struct gendisk *disk, blk_mode_t mode) { - int ret = 0; - struct zram *zram; + struct zram *zram = disk->private_data; - WARN_ON(!mutex_is_locked(&bdev->bd_disk->open_mutex)); + WARN_ON(!mutex_is_locked(&disk->open_mutex)); - zram = bdev->bd_disk->private_data; /* zram was claimed to reset so open request fails */ if (zram->claim) - ret = -EBUSY; - - return ret; + return -EBUSY; + return 0; } static const struct block_device_operations zram_devops = { diff --git a/drivers/bluetooth/btqca.c b/drivers/bluetooth/btqca.c index fd0941fe86081b403fa704683e7997baaaeb791e..e7e58a956d1544fb56e890a9df416d0d99b040f2 100644 --- a/drivers/bluetooth/btqca.c +++ b/drivers/bluetooth/btqca.c @@ -637,7 +637,7 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate, snprintf(config.fwname, sizeof(config.fwname), "qca/%s", firmware_name); else if (qca_is_wcn399x(soc_type)) { - if (ver.soc_id == QCA_WCN3991_SOC_ID) { + if (le32_to_cpu(ver.soc_id) == QCA_WCN3991_SOC_ID) { snprintf(config.fwname, sizeof(config.fwname), "qca/crnv%02xu.bin", rom_ver); } else { diff --git a/drivers/bluetooth/btrtl.c b/drivers/bluetooth/btrtl.c index 2915c82d719d886b953b0362e2e1b626f30ab64d..d978e7cea87313511539396398a0b4f68f254c80 100644 --- a/drivers/bluetooth/btrtl.c +++ b/drivers/bluetooth/btrtl.c @@ -1367,14 +1367,30 @@ MODULE_FIRMWARE("rtl_bt/rtl8723cs_vf_fw.bin"); MODULE_FIRMWARE("rtl_bt/rtl8723cs_vf_config.bin"); MODULE_FIRMWARE("rtl_bt/rtl8723cs_xx_fw.bin"); MODULE_FIRMWARE("rtl_bt/rtl8723cs_xx_config.bin"); +MODULE_FIRMWARE("rtl_bt/rtl8723d_fw.bin"); +MODULE_FIRMWARE("rtl_bt/rtl8723d_config.bin"); MODULE_FIRMWARE("rtl_bt/rtl8723ds_fw.bin"); MODULE_FIRMWARE("rtl_bt/rtl8723ds_config.bin"); MODULE_FIRMWARE("rtl_bt/rtl8761a_fw.bin"); MODULE_FIRMWARE("rtl_bt/rtl8761a_config.bin"); +MODULE_FIRMWARE("rtl_bt/rtl8761b_fw.bin"); +MODULE_FIRMWARE("rtl_bt/rtl8761b_config.bin"); +MODULE_FIRMWARE("rtl_bt/rtl8761bu_fw.bin"); +MODULE_FIRMWARE("rtl_bt/rtl8761bu_config.bin"); MODULE_FIRMWARE("rtl_bt/rtl8821a_fw.bin"); MODULE_FIRMWARE("rtl_bt/rtl8821a_config.bin"); +MODULE_FIRMWARE("rtl_bt/rtl8821c_fw.bin"); +MODULE_FIRMWARE("rtl_bt/rtl8821c_config.bin"); +MODULE_FIRMWARE("rtl_bt/rtl8821cs_fw.bin"); +MODULE_FIRMWARE("rtl_bt/rtl8821cs_config.bin"); MODULE_FIRMWARE("rtl_bt/rtl8822b_fw.bin"); MODULE_FIRMWARE("rtl_bt/rtl8822b_config.bin"); +MODULE_FIRMWARE("rtl_bt/rtl8822cs_fw.bin"); +MODULE_FIRMWARE("rtl_bt/rtl8822cs_config.bin"); +MODULE_FIRMWARE("rtl_bt/rtl8822cu_fw.bin"); +MODULE_FIRMWARE("rtl_bt/rtl8822cu_config.bin"); +MODULE_FIRMWARE("rtl_bt/rtl8851bu_fw.bin"); +MODULE_FIRMWARE("rtl_bt/rtl8851bu_config.bin"); MODULE_FIRMWARE("rtl_bt/rtl8852au_fw.bin"); MODULE_FIRMWARE("rtl_bt/rtl8852au_config.bin"); MODULE_FIRMWARE("rtl_bt/rtl8852bs_fw.bin"); @@ -1383,5 +1399,3 @@ MODULE_FIRMWARE("rtl_bt/rtl8852bu_fw.bin"); MODULE_FIRMWARE("rtl_bt/rtl8852bu_config.bin"); MODULE_FIRMWARE("rtl_bt/rtl8852cu_fw.bin"); MODULE_FIRMWARE("rtl_bt/rtl8852cu_config.bin"); -MODULE_FIRMWARE("rtl_bt/rtl8851bu_fw.bin"); -MODULE_FIRMWARE("rtl_bt/rtl8851bu_config.bin"); diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 2a8e2bb038f58640e9022147fc5c89a3e1fadd47..5ec4ad0a5c86fde1267766b02843238ae9536c44 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -613,6 +613,9 @@ static const struct usb_device_id blacklist_table[] = { { USB_DEVICE(0x0489, 0xe0d9), .driver_info = BTUSB_MEDIATEK | BTUSB_WIDEBAND_SPEECH | BTUSB_VALID_LE_STATES }, + { USB_DEVICE(0x0489, 0xe0f5), .driver_info = BTUSB_MEDIATEK | + BTUSB_WIDEBAND_SPEECH | + BTUSB_VALID_LE_STATES }, { USB_DEVICE(0x13d3, 0x3568), .driver_info = BTUSB_MEDIATEK | BTUSB_WIDEBAND_SPEECH | BTUSB_VALID_LE_STATES }, @@ -655,6 +658,8 @@ static const struct usb_device_id blacklist_table[] = { BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x0bda, 0x8771), .driver_info = BTUSB_REALTEK | BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x6655, 0x8771), .driver_info = BTUSB_REALTEK | + BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x7392, 0xc611), .driver_info = BTUSB_REALTEK | BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x2b89, 0x8761), .driver_info = BTUSB_REALTEK | diff --git a/drivers/bluetooth/hci_bcm.c b/drivers/bluetooth/hci_bcm.c index 83bf5d4330c40de83a172e7ed0110f85e468c6a8..874d23089b39b5448a636de2b475da46ff1f74b9 100644 --- a/drivers/bluetooth/hci_bcm.c +++ b/drivers/bluetooth/hci_bcm.c @@ -643,7 +643,8 @@ static int bcm_setup(struct hci_uart *hu) * Allow the bootloader to set a valid address through the * device tree. */ - set_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hu->hdev->quirks); + if (test_bit(HCI_QUIRK_INVALID_BDADDR, &hu->hdev->quirks)) + set_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hu->hdev->quirks); if (!bcm_request_irq(bcm)) err = bcm_setup_sleep(hu); diff --git a/drivers/bluetooth/virtio_bt.c b/drivers/bluetooth/virtio_bt.c index c570c45d148054fe31640015e674211f95387d6b..2ac70b560c46db16bef8b7ca86196c53c23b508e 100644 --- a/drivers/bluetooth/virtio_bt.c +++ b/drivers/bluetooth/virtio_bt.c @@ -79,6 +79,7 @@ static int virtbt_close_vdev(struct virtio_bluetooth *vbt) while ((skb = virtqueue_detach_unused_buf(vq))) kfree_skb(skb); + cond_resched(); } return 0; diff --git a/drivers/bus/fsl-mc/dprc-driver.c b/drivers/bus/fsl-mc/dprc-driver.c index 4c84be378bf27b3306be720d95527d38b8fd488c..4b68c84ef485055c9b300b4f7912a20f959b8ac1 100644 --- a/drivers/bus/fsl-mc/dprc-driver.c +++ b/drivers/bus/fsl-mc/dprc-driver.c @@ -45,6 +45,9 @@ static int __fsl_mc_device_remove_if_not_in_mc(struct device *dev, void *data) struct fsl_mc_child_objs *objs; struct fsl_mc_device *mc_dev; + if (!dev_is_fsl_mc(dev)) + return 0; + mc_dev = to_fsl_mc_device(dev); objs = data; @@ -64,6 +67,9 @@ static int __fsl_mc_device_remove_if_not_in_mc(struct device *dev, void *data) static int __fsl_mc_device_remove(struct device *dev, void *data) { + if (!dev_is_fsl_mc(dev)) + return 0; + fsl_mc_device_remove(to_fsl_mc_device(dev)); return 0; } @@ -835,15 +841,14 @@ EXPORT_SYMBOL_GPL(dprc_cleanup); * It tears down the interrupts that were configured for the DPRC device. * It destroys the interrupt pool associated with this MC bus. */ -static int dprc_remove(struct fsl_mc_device *mc_dev) +static void dprc_remove(struct fsl_mc_device *mc_dev) { struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_dev); - if (!is_fsl_mc_bus_dprc(mc_dev)) - return -EINVAL; - - if (!mc_bus->irq_resources) - return -EINVAL; + if (!mc_bus->irq_resources) { + dev_err(&mc_dev->dev, "No irq resources, so unbinding the device failed\n"); + return; + } if (dev_get_msi_domain(&mc_dev->dev)) dprc_teardown_irq(mc_dev); @@ -853,7 +858,6 @@ static int dprc_remove(struct fsl_mc_device *mc_dev) dprc_cleanup(mc_dev); dev_info(&mc_dev->dev, "DPRC device unbound from driver"); - return 0; } static const struct fsl_mc_device_id match_id_table[] = { diff --git a/drivers/bus/fsl-mc/fsl-mc-allocator.c b/drivers/bus/fsl-mc/fsl-mc-allocator.c index dced427ca8ba1cd11d0adc066a056e93f150b602..b5e8c021fa1fb4e62479c2486bd05ead1bf8b08c 100644 --- a/drivers/bus/fsl-mc/fsl-mc-allocator.c +++ b/drivers/bus/fsl-mc/fsl-mc-allocator.c @@ -103,26 +103,32 @@ static int __must_check fsl_mc_resource_pool_remove_device(struct fsl_mc_device struct fsl_mc_resource *resource; int error = -EINVAL; - if (!fsl_mc_is_allocatable(mc_dev)) - goto out; + mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent); + mc_bus = to_fsl_mc_bus(mc_bus_dev); resource = mc_dev->resource; - if (!resource || resource->data != mc_dev) + if (!resource || resource->data != mc_dev) { + dev_err(&mc_bus_dev->dev, "resource mismatch\n"); goto out; + } - mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent); - mc_bus = to_fsl_mc_bus(mc_bus_dev); res_pool = resource->parent_pool; - if (res_pool != &mc_bus->resource_pools[resource->type]) + if (res_pool != &mc_bus->resource_pools[resource->type]) { + dev_err(&mc_bus_dev->dev, "pool mismatch\n"); goto out; + } mutex_lock(&res_pool->mutex); - if (res_pool->max_count <= 0) + if (res_pool->max_count <= 0) { + dev_err(&mc_bus_dev->dev, "max_count underflow\n"); goto out_unlock; + } if (res_pool->free_count <= 0 || - res_pool->free_count > res_pool->max_count) + res_pool->free_count > res_pool->max_count) { + dev_err(&mc_bus_dev->dev, "free_count mismatch\n"); goto out_unlock; + } /* * If the device is currently allocated, its resource is not @@ -557,12 +563,9 @@ static void fsl_mc_cleanup_resource_pool(struct fsl_mc_device *mc_bus_dev, struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev); struct fsl_mc_resource_pool *res_pool = &mc_bus->resource_pools[pool_type]; - int free_count = 0; - list_for_each_entry_safe(resource, next, &res_pool->free_list, node) { - free_count++; + list_for_each_entry_safe(resource, next, &res_pool->free_list, node) devm_kfree(&mc_bus_dev->dev, resource); - } } void fsl_mc_cleanup_all_resource_pools(struct fsl_mc_device *mc_bus_dev) @@ -609,22 +612,18 @@ static int fsl_mc_allocator_probe(struct fsl_mc_device *mc_dev) * fsl_mc_allocator_remove - callback invoked when an allocatable device is * being removed from the system */ -static int fsl_mc_allocator_remove(struct fsl_mc_device *mc_dev) +static void fsl_mc_allocator_remove(struct fsl_mc_device *mc_dev) { int error; - if (!fsl_mc_is_allocatable(mc_dev)) - return -EINVAL; - if (mc_dev->resource) { error = fsl_mc_resource_pool_remove_device(mc_dev); if (error < 0) - return error; + return; } dev_dbg(&mc_dev->dev, "Allocatable fsl-mc device unbound from fsl_mc_allocator driver"); - return 0; } static const struct fsl_mc_device_id match_id_table[] = { diff --git a/drivers/bus/fsl-mc/fsl-mc-bus.c b/drivers/bus/fsl-mc/fsl-mc-bus.c index 653e2d4c116f0272a37433949153c7366305a54a..4352745a923ceaf7d25ed699c3cfc5f5df2b9344 100644 --- a/drivers/bus/fsl-mc/fsl-mc-bus.c +++ b/drivers/bus/fsl-mc/fsl-mc-bus.c @@ -454,13 +454,8 @@ static int fsl_mc_driver_remove(struct device *dev) { struct fsl_mc_driver *mc_drv = to_fsl_mc_driver(dev->driver); struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); - int error; - error = mc_drv->remove(mc_dev); - if (error < 0) { - dev_err(dev, "%s failed: %d\n", __func__, error); - return error; - } + mc_drv->remove(mc_dev); return 0; } diff --git a/drivers/bus/intel-ixp4xx-eb.c b/drivers/bus/intel-ixp4xx-eb.c index f5ba6bee6fd8b55887cc62c424e0125c548425fd..320cf307db054854af6f6f34c6eb03b47c2c6d34 100644 --- a/drivers/bus/intel-ixp4xx-eb.c +++ b/drivers/bus/intel-ixp4xx-eb.c @@ -33,7 +33,7 @@ #define IXP4XX_EXP_TIMING_STRIDE 0x04 #define IXP4XX_EXP_CS_EN BIT(31) #define IXP456_EXP_PAR_EN BIT(30) /* Only on IXP45x and IXP46x */ -#define IXP4XX_EXP_T1_MASK GENMASK(28, 27) +#define IXP4XX_EXP_T1_MASK GENMASK(29, 28) #define IXP4XX_EXP_T1_SHIFT 28 #define IXP4XX_EXP_T2_MASK GENMASK(27, 26) #define IXP4XX_EXP_T2_SHIFT 26 diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c index 6c49de37d5e90f98cf63b2875bbe3d3ed18c8b76..21fe9854703f9e1b9593e700ce3f4bc756e7fbdb 100644 --- a/drivers/bus/ti-sysc.c +++ b/drivers/bus/ti-sysc.c @@ -1791,7 +1791,7 @@ static u32 sysc_quirk_dispc(struct sysc *ddata, int dispc_offset, if (!ddata->module_va) return -EIO; - /* DISP_CONTROL */ + /* DISP_CONTROL, shut down lcd and digit on disable if enabled */ val = sysc_read(ddata, dispc_offset + 0x40); lcd_en = val & lcd_en_mask; digit_en = val & digit_en_mask; @@ -1803,7 +1803,7 @@ static u32 sysc_quirk_dispc(struct sysc *ddata, int dispc_offset, else irq_mask |= BIT(2) | BIT(3); /* EVSYNC bits */ } - if (disable & (lcd_en | digit_en)) + if (disable && (lcd_en || digit_en)) sysc_write(ddata, dispc_offset + 0x40, val & ~(lcd_en_mask | digit_en_mask)); diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c index 416f723a2dbb337508222aac17f29177029c60d1..cc283980598333c47161b8d5139135373940cd2e 100644 --- a/drivers/cdrom/cdrom.c +++ b/drivers/cdrom/cdrom.c @@ -264,6 +264,7 @@ #include #include #include +#include #include #include #include @@ -978,15 +979,6 @@ static void cdrom_dvd_rw_close_write(struct cdrom_device_info *cdi) cdi->media_written = 0; } -static int cdrom_close_write(struct cdrom_device_info *cdi) -{ -#if 0 - return cdrom_flush_cache(cdi); -#else - return 0; -#endif -} - /* badly broken, I know. Is due for a fixup anytime. */ static void cdrom_count_tracks(struct cdrom_device_info *cdi, tracktype *tracks) { @@ -1155,8 +1147,7 @@ int open_for_data(struct cdrom_device_info *cdi) * is in their own interest: device control becomes a lot easier * this way. */ -int cdrom_open(struct cdrom_device_info *cdi, struct block_device *bdev, - fmode_t mode) +int cdrom_open(struct cdrom_device_info *cdi, blk_mode_t mode) { int ret; @@ -1165,7 +1156,7 @@ int cdrom_open(struct cdrom_device_info *cdi, struct block_device *bdev, /* if this was a O_NONBLOCK open and we should honor the flags, * do a quick open without drive/disc integrity checks. */ cdi->use_count++; - if ((mode & FMODE_NDELAY) && (cdi->options & CDO_USE_FFLAGS)) { + if ((mode & BLK_OPEN_NDELAY) && (cdi->options & CDO_USE_FFLAGS)) { ret = cdi->ops->open(cdi, 1); } else { ret = open_for_data(cdi); @@ -1173,7 +1164,7 @@ int cdrom_open(struct cdrom_device_info *cdi, struct block_device *bdev, goto err; if (CDROM_CAN(CDC_GENERIC_PACKET)) cdrom_mmc3_profile(cdi); - if (mode & FMODE_WRITE) { + if (mode & BLK_OPEN_WRITE) { ret = -EROFS; if (cdrom_open_write(cdi)) goto err_release; @@ -1182,6 +1173,7 @@ int cdrom_open(struct cdrom_device_info *cdi, struct block_device *bdev, ret = 0; cdi->media_written = 0; } + cdi->opened_for_data = true; } if (ret) @@ -1259,10 +1251,9 @@ static int check_for_audio_disc(struct cdrom_device_info *cdi, return 0; } -void cdrom_release(struct cdrom_device_info *cdi, fmode_t mode) +void cdrom_release(struct cdrom_device_info *cdi) { const struct cdrom_device_ops *cdo = cdi->ops; - int opened_for_data; cd_dbg(CD_CLOSE, "entering cdrom_release\n"); @@ -1280,20 +1271,12 @@ void cdrom_release(struct cdrom_device_info *cdi, fmode_t mode) } } - opened_for_data = !(cdi->options & CDO_USE_FFLAGS) || - !(mode & FMODE_NDELAY); - - /* - * flush cache on last write release - */ - if (CDROM_CAN(CDC_RAM) && !cdi->use_count && cdi->for_data) - cdrom_close_write(cdi); - cdo->release(cdi); - if (cdi->use_count == 0) { /* last process that closes dev*/ - if (opened_for_data && - cdi->options & CDO_AUTO_EJECT && CDROM_CAN(CDC_OPEN_TRAY)) + + if (cdi->use_count == 0 && cdi->opened_for_data) { + if (cdi->options & CDO_AUTO_EJECT && CDROM_CAN(CDC_OPEN_TRAY)) cdo->tray_move(cdi, 1); + cdi->opened_for_data = false; } } EXPORT_SYMBOL(cdrom_release); @@ -2329,6 +2312,9 @@ static int cdrom_ioctl_media_changed(struct cdrom_device_info *cdi, if (arg >= cdi->capacity) return -EINVAL; + /* Prevent arg from speculatively bypassing the length check */ + barrier_nospec(); + info = kmalloc(sizeof(*info), GFP_KERNEL); if (!info) return -ENOMEM; @@ -3337,7 +3323,7 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, * ATAPI / SCSI specific code now mainly resides in mmc_ioctl(). */ int cdrom_ioctl(struct cdrom_device_info *cdi, struct block_device *bdev, - fmode_t mode, unsigned int cmd, unsigned long arg) + unsigned int cmd, unsigned long arg) { void __user *argp = (void __user *)arg; int ret; diff --git a/drivers/cdrom/gdrom.c b/drivers/cdrom/gdrom.c index ceded5772aac6d7d27b974c038615b7aafc8228f..d668b174ace92fbd7e6a8635034f01249afb67e2 100644 --- a/drivers/cdrom/gdrom.c +++ b/drivers/cdrom/gdrom.c @@ -474,22 +474,22 @@ static const struct cdrom_device_ops gdrom_ops = { CDC_RESET | CDC_DRIVE_STATUS | CDC_CD_R, }; -static int gdrom_bdops_open(struct block_device *bdev, fmode_t mode) +static int gdrom_bdops_open(struct gendisk *disk, blk_mode_t mode) { int ret; - bdev_check_media_change(bdev); + disk_check_media_change(disk); mutex_lock(&gdrom_mutex); - ret = cdrom_open(gd.cd_info, bdev, mode); + ret = cdrom_open(gd.cd_info, mode); mutex_unlock(&gdrom_mutex); return ret; } -static void gdrom_bdops_release(struct gendisk *disk, fmode_t mode) +static void gdrom_bdops_release(struct gendisk *disk) { mutex_lock(&gdrom_mutex); - cdrom_release(gd.cd_info, mode); + cdrom_release(gd.cd_info); mutex_unlock(&gdrom_mutex); } @@ -499,13 +499,13 @@ static unsigned int gdrom_bdops_check_events(struct gendisk *disk, return cdrom_check_events(gd.cd_info, clearing); } -static int gdrom_bdops_ioctl(struct block_device *bdev, fmode_t mode, +static int gdrom_bdops_ioctl(struct block_device *bdev, blk_mode_t mode, unsigned cmd, unsigned long arg) { int ret; mutex_lock(&gdrom_mutex); - ret = cdrom_ioctl(gd.cd_info, bdev, mode, cmd, arg); + ret = cdrom_ioctl(gd.cd_info, bdev, cmd, arg); mutex_unlock(&gdrom_mutex); return ret; diff --git a/drivers/cdx/cdx.c b/drivers/cdx/cdx.c index 38511fd363257a3137324d3a39ac61b37b822681..d2cad4c670a0734c883b4e326480b52edd8a4097 100644 --- a/drivers/cdx/cdx.c +++ b/drivers/cdx/cdx.c @@ -62,6 +62,8 @@ #include #include #include +#include +#include #include "cdx.h" /* Default DMA mask for devices on a CDX bus */ @@ -257,6 +259,7 @@ static void cdx_shutdown(struct device *dev) static int cdx_dma_configure(struct device *dev) { + struct cdx_driver *cdx_drv = to_cdx_driver(dev->driver); struct cdx_device *cdx_dev = to_cdx_device(dev); u32 input_id = cdx_dev->req_id; int ret; @@ -267,9 +270,23 @@ static int cdx_dma_configure(struct device *dev) return ret; } + if (!ret && !cdx_drv->driver_managed_dma) { + ret = iommu_device_use_default_domain(dev); + if (ret) + arch_teardown_dma_ops(dev); + } + return 0; } +static void cdx_dma_cleanup(struct device *dev) +{ + struct cdx_driver *cdx_drv = to_cdx_driver(dev->driver); + + if (!cdx_drv->driver_managed_dma) + iommu_device_unuse_default_domain(dev); +} + /* show configuration fields */ #define cdx_config_attr(field, format_string) \ static ssize_t \ @@ -405,6 +422,7 @@ struct bus_type cdx_bus_type = { .remove = cdx_remove, .shutdown = cdx_shutdown, .dma_configure = cdx_dma_configure, + .dma_cleanup = cdx_dma_cleanup, .bus_groups = cdx_bus_groups, .dev_groups = cdx_dev_groups, }; diff --git a/drivers/cdx/controller/Kconfig b/drivers/cdx/controller/Kconfig index c3e3b9ff8dfe120a90633e58c8f753b95a0a3bca..61bf17fbe43360cc0712a75025abb1d1371ac648 100644 --- a/drivers/cdx/controller/Kconfig +++ b/drivers/cdx/controller/Kconfig @@ -18,14 +18,4 @@ config CDX_CONTROLLER If unsure, say N. -config MCDI_LOGGING - bool "MCDI Logging for the CDX controller" - depends on CDX_CONTROLLER - help - Enable MCDI Logging for - the CDX Controller for debug - purpose. - - If unsure, say N. - endif diff --git a/drivers/cdx/controller/mcdi.c b/drivers/cdx/controller/mcdi.c index a211a2ca762e3c52863a756fd6eaeecddcae832e..1eedc5eeb315439ffa6ea5df206f3d9d01548b03 100644 --- a/drivers/cdx/controller/mcdi.c +++ b/drivers/cdx/controller/mcdi.c @@ -31,10 +31,6 @@ struct cdx_mcdi_copy_buffer { struct cdx_dword buffer[DIV_ROUND_UP(MCDI_CTL_SDU_LEN_MAX, 4)]; }; -#ifdef CONFIG_MCDI_LOGGING -#define LOG_LINE_MAX (1024 - 32) -#endif - static void cdx_mcdi_cancel_cmd(struct cdx_mcdi *cdx, struct cdx_mcdi_cmd *cmd); static void cdx_mcdi_wait_for_cleanup(struct cdx_mcdi *cdx); static int cdx_mcdi_rpc_async_internal(struct cdx_mcdi *cdx, @@ -119,14 +115,9 @@ int cdx_mcdi_init(struct cdx_mcdi *cdx) mcdi = cdx_mcdi_if(cdx); mcdi->cdx = cdx; -#ifdef CONFIG_MCDI_LOGGING - mcdi->logging_buffer = kmalloc(LOG_LINE_MAX, GFP_KERNEL); - if (!mcdi->logging_buffer) - goto fail2; -#endif mcdi->workqueue = alloc_ordered_workqueue("mcdi_wq", 0); if (!mcdi->workqueue) - goto fail3; + goto fail2; mutex_init(&mcdi->iface_lock); mcdi->mode = MCDI_MODE_EVENTS; INIT_LIST_HEAD(&mcdi->cmd_list); @@ -135,11 +126,7 @@ int cdx_mcdi_init(struct cdx_mcdi *cdx) mcdi->new_epoch = true; return 0; -fail3: -#ifdef CONFIG_MCDI_LOGGING - kfree(mcdi->logging_buffer); fail2: -#endif kfree(cdx->mcdi); cdx->mcdi = NULL; fail: @@ -156,10 +143,6 @@ void cdx_mcdi_finish(struct cdx_mcdi *cdx) cdx_mcdi_wait_for_cleanup(cdx); -#ifdef CONFIG_MCDI_LOGGING - kfree(mcdi->logging_buffer); -#endif - destroy_workqueue(mcdi->workqueue); kfree(cdx->mcdi); cdx->mcdi = NULL; @@ -246,15 +229,9 @@ static void cdx_mcdi_send_request(struct cdx_mcdi *cdx, size_t hdr_len; bool not_epoch; u32 xflags; -#ifdef CONFIG_MCDI_LOGGING - char *buf; -#endif if (!mcdi) return; -#ifdef CONFIG_MCDI_LOGGING - buf = mcdi->logging_buffer; /* page-sized */ -#endif mcdi->prev_seq = cmd->seq; mcdi->seq_held_by[cmd->seq] = cmd; @@ -281,39 +258,12 @@ static void cdx_mcdi_send_request(struct cdx_mcdi *cdx, MC_CMD_V2_EXTN_IN_MCDI_MESSAGE_TYPE_PLATFORM); hdr_len = 8; -#ifdef CONFIG_MCDI_LOGGING - if (!WARN_ON_ONCE(!buf)) { - const struct cdx_dword *frags[] = { hdr, inbuf }; - const size_t frag_len[] = { hdr_len, round_up(inlen, 4) }; - int bytes = 0; - int i, j; - - for (j = 0; j < ARRAY_SIZE(frags); j++) { - const struct cdx_dword *frag; - - frag = frags[j]; - for (i = 0; - i < frag_len[j] / 4; - i++) { - /* - * Do not exceed the internal printk limit. - * The string before that is just over 70 bytes. - */ - if ((bytes + 75) > LOG_LINE_MAX) { - pr_info("MCDI RPC REQ:%s \\\n", buf); - bytes = 0; - } - bytes += snprintf(buf + bytes, - LOG_LINE_MAX - bytes, " %08x", - le32_to_cpu(frag[i].cdx_u32)); - } - } - - pr_info("MCDI RPC REQ:%s\n", buf); - } -#endif hdr[0].cdx_u32 |= (__force __le32)(cdx_mcdi_payload_csum(hdr, hdr_len, inbuf, inlen) << MCDI_HEADER_XFLAGS_LBN); + + print_hex_dump_debug("MCDI REQ HEADER: ", DUMP_PREFIX_NONE, 32, 4, hdr, hdr_len, false); + print_hex_dump_debug("MCDI REQ PAYLOAD: ", DUMP_PREFIX_NONE, 32, 4, inbuf, inlen, false); + cdx->mcdi_ops->mcdi_request(cdx, hdr, hdr_len, inbuf, inlen); mcdi->new_epoch = false; @@ -700,28 +650,10 @@ static bool cdx_mcdi_complete_cmd(struct cdx_mcdi_iface *mcdi, resp_data_len = 0; } -#ifdef CONFIG_MCDI_LOGGING - if (!WARN_ON_ONCE(!mcdi->logging_buffer)) { - char *log = mcdi->logging_buffer; - int i, bytes = 0; - size_t rlen; - - WARN_ON_ONCE(resp_hdr_len % 4); - - rlen = resp_hdr_len / 4 + DIV_ROUND_UP(resp_data_len, 4); - - for (i = 0; i < rlen; i++) { - if ((bytes + 75) > LOG_LINE_MAX) { - pr_info("MCDI RPC RESP:%s \\\n", log); - bytes = 0; - } - bytes += snprintf(log + bytes, LOG_LINE_MAX - bytes, - " %08x", le32_to_cpu(outbuf[i].cdx_u32)); - } - - pr_info("MCDI RPC RESP:%s\n", log); - } -#endif + print_hex_dump_debug("MCDI RESP HEADER: ", DUMP_PREFIX_NONE, 32, 4, + outbuf, resp_hdr_len, false); + print_hex_dump_debug("MCDI RESP PAYLOAD: ", DUMP_PREFIX_NONE, 32, 4, + outbuf + (resp_hdr_len / 4), resp_data_len, false); if (error && resp_data_len == 0) { /* MC rebooted during command */ diff --git a/drivers/cdx/controller/mcdi.h b/drivers/cdx/controller/mcdi.h index 0bfbeab04e43235572a4e08078e585da0572d4f2..54a65e9760aeee30df21111f8298c2a7dbfa0e05 100644 --- a/drivers/cdx/controller/mcdi.h +++ b/drivers/cdx/controller/mcdi.h @@ -153,8 +153,6 @@ struct cdx_mcdi_cmd { * @mode: Poll for mcdi completion, or wait for an mcdi_event * @prev_seq: The last used sequence number * @new_epoch: Indicates start of day or start of MC reboot recovery - * @logging_buffer: Buffer that may be used to build MCDI tracing messages - * @logging_enabled: Whether to trace MCDI */ struct cdx_mcdi_iface { struct cdx_mcdi *cdx; @@ -170,10 +168,6 @@ struct cdx_mcdi_iface { enum cdx_mcdi_mode mode; u8 prev_seq; bool new_epoch; -#ifdef CONFIG_MCDI_LOGGING - bool logging_enabled; - char *logging_buffer; -#endif }; /** diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 801d6c83f896163426f073400937b2de4e290215..625af75833fc37047bbb93228dbf7131404a64a5 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -34,6 +34,7 @@ config TTY_PRINTK_LEVEL config PRINTER tristate "Parallel printer support" depends on PARPORT + depends on HAS_IOPORT || PARPORT_NOT_PC help If you intend to attach a printer to the parallel port of your Linux box (as opposed to using a serial printer; if the connector at the @@ -340,7 +341,7 @@ config NVRAM config DEVPORT bool "/dev/port character device" - depends on ISA || PCI + depends on HAS_IOPORT default y help Say Y here if you want to support the /dev/port device. The /dev/port diff --git a/drivers/char/bsr.c b/drivers/char/bsr.c index ff429ba02fa44f9592f2518f8fd7820c83b41730..12143854aeac26b4d885ad397a75dbe6e9ebbdd1 100644 --- a/drivers/char/bsr.c +++ b/drivers/char/bsr.c @@ -61,7 +61,6 @@ struct bsr_dev { static unsigned total_bsr_devs; static LIST_HEAD(bsr_devs); -static struct class *bsr_class; static int bsr_major; enum { @@ -108,6 +107,11 @@ static struct attribute *bsr_dev_attrs[] = { }; ATTRIBUTE_GROUPS(bsr_dev); +static const struct class bsr_class = { + .name = "bsr", + .dev_groups = bsr_dev_groups, +}; + static int bsr_mmap(struct file *filp, struct vm_area_struct *vma) { unsigned long size = vma->vm_end - vma->vm_start; @@ -244,7 +248,7 @@ static int bsr_add_node(struct device_node *bn) goto out_err; } - cur->bsr_device = device_create(bsr_class, NULL, cur->bsr_dev, + cur->bsr_device = device_create(&bsr_class, NULL, cur->bsr_dev, cur, "%s", cur->bsr_name); if (IS_ERR(cur->bsr_device)) { printk(KERN_ERR "device_create failed for %s\n", @@ -293,13 +297,9 @@ static int __init bsr_init(void) if (!np) goto out_err; - bsr_class = class_create("bsr"); - if (IS_ERR(bsr_class)) { - printk(KERN_ERR "class_create() failed for bsr_class\n"); - ret = PTR_ERR(bsr_class); + ret = class_register(&bsr_class); + if (ret) goto out_err_1; - } - bsr_class->dev_groups = bsr_dev_groups; ret = alloc_chrdev_region(&bsr_dev, 0, BSR_MAX_DEVS, "bsr"); bsr_major = MAJOR(bsr_dev); @@ -320,7 +320,7 @@ static int __init bsr_init(void) unregister_chrdev_region(bsr_dev, BSR_MAX_DEVS); out_err_2: - class_destroy(bsr_class); + class_unregister(&bsr_class); out_err_1: of_node_put(np); @@ -335,8 +335,7 @@ static void __exit bsr_exit(void) bsr_cleanup_devs(); - if (bsr_class) - class_destroy(bsr_class); + class_unregister(&bsr_class); if (bsr_major) unregister_chrdev_region(MKDEV(bsr_major, 0), BSR_MAX_DEVS); diff --git a/drivers/char/dsp56k.c b/drivers/char/dsp56k.c index b3eaf3e5ef2e291573a40fc61bf49c77716960a0..bda27e595da122696cdc7795099568ec81257472 100644 --- a/drivers/char/dsp56k.c +++ b/drivers/char/dsp56k.c @@ -101,7 +101,9 @@ static struct dsp56k_device { int tx_wsize, rx_wsize; } dsp56k; -static struct class *dsp56k_class; +static const struct class dsp56k_class = { + .name = "dsp56k", +}; static int dsp56k_reset(void) { @@ -493,7 +495,7 @@ static const char banner[] __initconst = KERN_INFO "DSP56k driver installed\n"; static int __init dsp56k_init_driver(void) { - int err = 0; + int err; if(!MACH_IS_ATARI || !ATARIHW_PRESENT(DSP56K)) { printk("DSP56k driver: Hardware not present\n"); @@ -504,12 +506,10 @@ static int __init dsp56k_init_driver(void) printk("DSP56k driver: Unable to register driver\n"); return -ENODEV; } - dsp56k_class = class_create("dsp56k"); - if (IS_ERR(dsp56k_class)) { - err = PTR_ERR(dsp56k_class); + err = class_register(&dsp56k_class); + if (err) goto out_chrdev; - } - device_create(dsp56k_class, NULL, MKDEV(DSP56K_MAJOR, 0), NULL, + device_create(&dsp56k_class, NULL, MKDEV(DSP56K_MAJOR, 0), NULL, "dsp56k"); printk(banner); @@ -524,8 +524,8 @@ module_init(dsp56k_init_driver); static void __exit dsp56k_cleanup_driver(void) { - device_destroy(dsp56k_class, MKDEV(DSP56K_MAJOR, 0)); - class_destroy(dsp56k_class); + device_destroy(&dsp56k_class, MKDEV(DSP56K_MAJOR, 0)); + class_unregister(&dsp56k_class); unregister_chrdev(DSP56K_MAJOR, "dsp56k"); } module_exit(dsp56k_cleanup_driver); diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig index 4fdf07ae3c54fac07d1b2eca7197d308575aca20..e0b3786ca51bcd02e6a895e7db029b8faf46d482 100644 --- a/drivers/char/hw_random/Kconfig +++ b/drivers/char/hw_random/Kconfig @@ -335,9 +335,20 @@ config HW_RANDOM_HISI If unsure, say Y. +config HW_RANDOM_HISTB + tristate "Hisilicon STB Random Number Generator support" + depends on ARCH_HISI || COMPILE_TEST + default ARCH_HISI + help + This driver provides kernel-side support for the Random Number + Generator hardware found on Hisilicon Hi37xx SoC. + + To compile this driver as a module, choose M here: the + module will be called histb-rng. + config HW_RANDOM_ST tristate "ST Microelectronics HW Random Number Generator support" - depends on HW_RANDOM && ARCH_STI + depends on HW_RANDOM && (ARCH_STI || COMPILE_TEST) help This driver provides kernel-side support for the Random Number Generator hardware found on STi series of SoCs. @@ -400,9 +411,9 @@ config HW_RANDOM_POLARFIRE_SOC config HW_RANDOM_MESON tristate "Amlogic Meson Random Number Generator support" - depends on HW_RANDOM depends on ARCH_MESON || COMPILE_TEST - default y + depends on HAS_IOMEM && OF + default HW_RANDOM if ARCH_MESON help This driver provides kernel-side support for the Random Number Generator hardware found on Amlogic Meson SoCs. @@ -427,9 +438,9 @@ config HW_RANDOM_CAVIUM config HW_RANDOM_MTK tristate "Mediatek Random Number Generator support" - depends on HW_RANDOM depends on ARCH_MEDIATEK || COMPILE_TEST - default y + depends on HAS_IOMEM && OF + default HW_RANDOM if ARCH_MEDIATEK help This driver provides kernel-side support for the Random Number Generator hardware found on Mediatek SoCs. @@ -456,7 +467,8 @@ config HW_RANDOM_S390 config HW_RANDOM_EXYNOS tristate "Samsung Exynos True Random Number Generator support" depends on ARCH_EXYNOS || COMPILE_TEST - default HW_RANDOM + depends on HAS_IOMEM + default HW_RANDOM if ARCH_EXYNOS help This driver provides support for the True Random Number Generator available in Exynos SoCs. @@ -483,7 +495,8 @@ config HW_RANDOM_OPTEE config HW_RANDOM_NPCM tristate "NPCM Random Number Generator support" depends on ARCH_NPCM || COMPILE_TEST - default HW_RANDOM + depends on HAS_IOMEM + default HW_RANDOM if ARCH_NPCM help This driver provides support for the Random Number Generator hardware available in Nuvoton NPCM SoCs. diff --git a/drivers/char/hw_random/Makefile b/drivers/char/hw_random/Makefile index 09bde4a0f971a797a7d8b006a788d7dad589d061..32549a1186dc57a26250d117a70820b328af62ac 100644 --- a/drivers/char/hw_random/Makefile +++ b/drivers/char/hw_random/Makefile @@ -29,6 +29,7 @@ obj-$(CONFIG_HW_RANDOM_NOMADIK) += nomadik-rng.o obj-$(CONFIG_HW_RANDOM_PSERIES) += pseries-rng.o obj-$(CONFIG_HW_RANDOM_POWERNV) += powernv-rng.o obj-$(CONFIG_HW_RANDOM_HISI) += hisi-rng.o +obj-$(CONFIG_HW_RANDOM_HISTB) += histb-rng.o obj-$(CONFIG_HW_RANDOM_BCM2835) += bcm2835-rng.o obj-$(CONFIG_HW_RANDOM_IPROC_RNG200) += iproc-rng200.o obj-$(CONFIG_HW_RANDOM_ST) += st-rng.o diff --git a/drivers/char/hw_random/cn10k-rng.c b/drivers/char/hw_random/cn10k-rng.c index c1193f85982c36cae1cd1bf57db09f9ceb99b9a6..0cd7e1a8e4995b8f3e45f87b8e183d305a14e33f 100644 --- a/drivers/char/hw_random/cn10k-rng.c +++ b/drivers/char/hw_random/cn10k-rng.c @@ -23,14 +23,49 @@ #define RNM_PF_RANDOM 0x400 #define RNM_TRNG_RESULT 0x408 +/* Extended TRNG Read and Status Registers */ +#define RNM_PF_TRNG_DAT 0x1000 +#define RNM_PF_TRNG_RES 0x1008 + struct cn10k_rng { void __iomem *reg_base; struct hwrng ops; struct pci_dev *pdev; + /* Octeon CN10K-A A0/A1, CNF10K-A A0/A1 and CNF10K-B A0/B0 + * does not support extended TRNG registers + */ + bool extended_trng_regs; }; #define PLAT_OCTEONTX_RESET_RNG_EBG_HEALTH_STATE 0xc2000b0f +#define PCI_SUBSYS_DEVID_CN10K_A_RNG 0xB900 +#define PCI_SUBSYS_DEVID_CNF10K_A_RNG 0xBA00 +#define PCI_SUBSYS_DEVID_CNF10K_B_RNG 0xBC00 + +static bool cn10k_is_extended_trng_regs_supported(struct pci_dev *pdev) +{ + /* CN10K-A A0/A1 */ + if ((pdev->subsystem_device == PCI_SUBSYS_DEVID_CN10K_A_RNG) && + (!pdev->revision || (pdev->revision & 0xff) == 0x50 || + (pdev->revision & 0xff) == 0x51)) + return false; + + /* CNF10K-A A0 */ + if ((pdev->subsystem_device == PCI_SUBSYS_DEVID_CNF10K_A_RNG) && + (!pdev->revision || (pdev->revision & 0xff) == 0x60 || + (pdev->revision & 0xff) == 0x61)) + return false; + + /* CNF10K-B A0/B0 */ + if ((pdev->subsystem_device == PCI_SUBSYS_DEVID_CNF10K_B_RNG) && + (!pdev->revision || (pdev->revision & 0xff) == 0x70 || + (pdev->revision & 0xff) == 0x74)) + return false; + + return true; +} + static unsigned long reset_rng_health_state(struct cn10k_rng *rng) { struct arm_smccc_res res; @@ -63,9 +98,23 @@ static int check_rng_health(struct cn10k_rng *rng) return 0; } -static void cn10k_read_trng(struct cn10k_rng *rng, u64 *value) +/* Returns true when valid data available otherwise return false */ +static bool cn10k_read_trng(struct cn10k_rng *rng, u64 *value) { + u16 retry_count = 0; u64 upper, lower; + u64 status; + + if (rng->extended_trng_regs) { + do { + *value = readq(rng->reg_base + RNM_PF_TRNG_DAT); + if (*value) + return true; + status = readq(rng->reg_base + RNM_PF_TRNG_RES); + if (!status && (retry_count++ > 0x1000)) + return false; + } while (!status); + } *value = readq(rng->reg_base + RNM_PF_RANDOM); @@ -82,6 +131,7 @@ static void cn10k_read_trng(struct cn10k_rng *rng, u64 *value) *value = (upper & 0xFFFFFFFF00000000) | (lower & 0xFFFFFFFF); } + return true; } static int cn10k_rng_read(struct hwrng *hwrng, void *data, @@ -100,7 +150,8 @@ static int cn10k_rng_read(struct hwrng *hwrng, void *data, size = max; while (size >= 8) { - cn10k_read_trng(rng, &value); + if (!cn10k_read_trng(rng, &value)) + goto out; *((u64 *)pos) = value; size -= 8; @@ -108,7 +159,8 @@ static int cn10k_rng_read(struct hwrng *hwrng, void *data, } if (size > 0) { - cn10k_read_trng(rng, &value); + if (!cn10k_read_trng(rng, &value)) + goto out; while (size > 0) { *pos = (u8)value; @@ -118,6 +170,7 @@ static int cn10k_rng_read(struct hwrng *hwrng, void *data, } } +out: return max - size; } @@ -144,9 +197,11 @@ static int cn10k_rng_probe(struct pci_dev *pdev, const struct pci_device_id *id) if (!rng->ops.name) return -ENOMEM; - rng->ops.read = cn10k_rng_read; + rng->ops.read = cn10k_rng_read; rng->ops.priv = (unsigned long)rng; + rng->extended_trng_regs = cn10k_is_extended_trng_regs_supported(pdev); + reset_rng_health_state(rng); err = devm_hwrng_register(&pdev->dev, &rng->ops); diff --git a/drivers/crypto/hisilicon/trng/trng-stb.c b/drivers/char/hw_random/histb-rng.c similarity index 53% rename from drivers/crypto/hisilicon/trng/trng-stb.c rename to drivers/char/hw_random/histb-rng.c index 29200a7d3d812ca514d315da0e2454f0d0ec9801..f652e1135e4b24b7807d2a00c300a0e8ceb15e1c 100644 --- a/drivers/crypto/hisilicon/trng/trng-stb.c +++ b/drivers/char/hw_random/histb-rng.c @@ -1,31 +1,27 @@ // SPDX-License-Identifier: GPL-2.0-or-later OR MIT /* - * Device driver for True RNG in HiSTB SoCs - * * Copyright (c) 2023 David Yang */ -#include -#include #include #include #include #include #include +#include #include -#include -#include +#include -#define HISTB_TRNG_CTRL 0x0 +#define RNG_CTRL 0x0 #define RNG_SOURCE GENMASK(1, 0) #define DROP_ENABLE BIT(5) #define POST_PROCESS_ENABLE BIT(7) #define POST_PROCESS_DEPTH GENMASK(15, 8) -#define HISTB_TRNG_NUMBER 0x4 -#define HISTB_TRNG_STAT 0x8 +#define RNG_NUMBER 0x4 +#define RNG_STAT 0x8 #define DATA_COUNT GENMASK(2, 0) /* max 4 */ -struct histb_trng_priv { +struct histb_rng_priv { struct hwrng rng; void __iomem *base; }; @@ -35,19 +31,19 @@ struct histb_trng_priv { * depth = 1 -> ~1ms * depth = 255 -> ~16ms */ -static int histb_trng_wait(void __iomem *base) +static int histb_rng_wait(void __iomem *base) { u32 val; - return readl_relaxed_poll_timeout(base + HISTB_TRNG_STAT, val, + return readl_relaxed_poll_timeout(base + RNG_STAT, val, val & DATA_COUNT, 1000, 30 * 1000); } -static void histb_trng_init(void __iomem *base, unsigned int depth) +static void histb_rng_init(void __iomem *base, unsigned int depth) { u32 val; - val = readl_relaxed(base + HISTB_TRNG_CTRL); + val = readl_relaxed(base + RNG_CTRL); val &= ~RNG_SOURCE; val |= 2; @@ -58,72 +54,72 @@ static void histb_trng_init(void __iomem *base, unsigned int depth) val |= POST_PROCESS_ENABLE; val |= DROP_ENABLE; - writel_relaxed(val, base + HISTB_TRNG_CTRL); + writel_relaxed(val, base + RNG_CTRL); } -static int histb_trng_read(struct hwrng *rng, void *data, size_t max, bool wait) +static int histb_rng_read(struct hwrng *rng, void *data, size_t max, bool wait) { - struct histb_trng_priv *priv = container_of(rng, typeof(*priv), rng); + struct histb_rng_priv *priv = container_of(rng, typeof(*priv), rng); void __iomem *base = priv->base; for (int i = 0; i < max; i += sizeof(u32)) { - if (!(readl_relaxed(base + HISTB_TRNG_STAT) & DATA_COUNT)) { + if (!(readl_relaxed(base + RNG_STAT) & DATA_COUNT)) { if (!wait) return i; - if (histb_trng_wait(base)) { + if (histb_rng_wait(base)) { pr_err("failed to generate random number, generated %d\n", i); return i ? i : -ETIMEDOUT; } } - *(u32 *) (data + i) = readl_relaxed(base + HISTB_TRNG_NUMBER); + *(u32 *) (data + i) = readl_relaxed(base + RNG_NUMBER); } return max; } -static unsigned int histb_trng_get_depth(void __iomem *base) +static unsigned int histb_rng_get_depth(void __iomem *base) { - return (readl_relaxed(base + HISTB_TRNG_CTRL) & POST_PROCESS_DEPTH) >> 8; + return (readl_relaxed(base + RNG_CTRL) & POST_PROCESS_DEPTH) >> 8; } static ssize_t depth_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct histb_trng_priv *priv = dev_get_drvdata(dev); + struct histb_rng_priv *priv = dev_get_drvdata(dev); void __iomem *base = priv->base; - return sprintf(buf, "%d\n", histb_trng_get_depth(base)); + return sprintf(buf, "%d\n", histb_rng_get_depth(base)); } static ssize_t depth_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct histb_trng_priv *priv = dev_get_drvdata(dev); + struct histb_rng_priv *priv = dev_get_drvdata(dev); void __iomem *base = priv->base; unsigned int depth; if (kstrtouint(buf, 0, &depth)) return -ERANGE; - histb_trng_init(base, depth); + histb_rng_init(base, depth); return count; } static DEVICE_ATTR_RW(depth); -static struct attribute *histb_trng_attrs[] = { +static struct attribute *histb_rng_attrs[] = { &dev_attr_depth.attr, NULL, }; -ATTRIBUTE_GROUPS(histb_trng); +ATTRIBUTE_GROUPS(histb_rng); -static int histb_trng_probe(struct platform_device *pdev) +static int histb_rng_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; - struct histb_trng_priv *priv; + struct histb_rng_priv *priv; void __iomem *base; int ret; @@ -133,17 +129,17 @@ static int histb_trng_probe(struct platform_device *pdev) base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(base)) - return -ENOMEM; + return PTR_ERR(base); - histb_trng_init(base, 144); - if (histb_trng_wait(base)) { + histb_rng_init(base, 144); + if (histb_rng_wait(base)) { dev_err(dev, "cannot bring up device\n"); return -ENODEV; } priv->base = base; priv->rng.name = pdev->name; - priv->rng.read = histb_trng_read; + priv->rng.read = histb_rng_read; ret = devm_hwrng_register(dev, &priv->rng); if (ret) { dev_err(dev, "failed to register hwrng: %d\n", ret); @@ -155,22 +151,23 @@ static int histb_trng_probe(struct platform_device *pdev) return 0; } -static const struct of_device_id histb_trng_of_match[] = { - { .compatible = "hisilicon,histb-trng", }, +static const struct of_device_id histb_rng_of_match[] = { + { .compatible = "hisilicon,histb-rng", }, { } }; +MODULE_DEVICE_TABLE(of, histb_rng_of_match); -static struct platform_driver histb_trng_driver = { - .probe = histb_trng_probe, +static struct platform_driver histb_rng_driver = { + .probe = histb_rng_probe, .driver = { - .name = "histb-trng", - .of_match_table = histb_trng_of_match, - .dev_groups = histb_trng_groups, + .name = "histb-rng", + .of_match_table = histb_rng_of_match, + .dev_groups = histb_rng_groups, }, }; -module_platform_driver(histb_trng_driver); +module_platform_driver(histb_rng_driver); -MODULE_DESCRIPTION("HiSTB True RNG"); +MODULE_DESCRIPTION("Hisilicon STB random number generator driver"); MODULE_LICENSE("Dual MIT/GPL"); MODULE_AUTHOR("David Yang "); diff --git a/drivers/char/hw_random/imx-rngc.c b/drivers/char/hw_random/imx-rngc.c index a1c24148ed31461bd256b5d7def3a57027e8a01e..bf07f17f78c8cc4c95aaadef294a73345e3d2136 100644 --- a/drivers/char/hw_random/imx-rngc.c +++ b/drivers/char/hw_random/imx-rngc.c @@ -17,6 +17,7 @@ #include #include #include +#include #define RNGC_VER_ID 0x0000 #define RNGC_COMMAND 0x0004 @@ -26,7 +27,7 @@ #define RNGC_FIFO 0x0014 /* the fields in the ver id register */ -#define RNGC_TYPE_SHIFT 28 +#define RNG_TYPE GENMASK(31, 28) #define RNGC_VER_MAJ_SHIFT 8 /* the rng_type field */ @@ -34,20 +35,19 @@ #define RNGC_TYPE_RNGC 0x2 -#define RNGC_CMD_CLR_ERR 0x00000020 -#define RNGC_CMD_CLR_INT 0x00000010 -#define RNGC_CMD_SEED 0x00000002 -#define RNGC_CMD_SELF_TEST 0x00000001 +#define RNGC_CMD_CLR_ERR BIT(5) +#define RNGC_CMD_CLR_INT BIT(4) +#define RNGC_CMD_SEED BIT(1) +#define RNGC_CMD_SELF_TEST BIT(0) -#define RNGC_CTRL_MASK_ERROR 0x00000040 -#define RNGC_CTRL_MASK_DONE 0x00000020 -#define RNGC_CTRL_AUTO_SEED 0x00000010 +#define RNGC_CTRL_MASK_ERROR BIT(6) +#define RNGC_CTRL_MASK_DONE BIT(5) +#define RNGC_CTRL_AUTO_SEED BIT(4) -#define RNGC_STATUS_ERROR 0x00010000 -#define RNGC_STATUS_FIFO_LEVEL_MASK 0x00000f00 -#define RNGC_STATUS_FIFO_LEVEL_SHIFT 8 -#define RNGC_STATUS_SEED_DONE 0x00000020 -#define RNGC_STATUS_ST_DONE 0x00000010 +#define RNGC_STATUS_ERROR BIT(16) +#define RNGC_STATUS_FIFO_LEVEL_MASK GENMASK(11, 8) +#define RNGC_STATUS_SEED_DONE BIT(5) +#define RNGC_STATUS_ST_DONE BIT(4) #define RNGC_ERROR_STATUS_STAT_ERR 0x00000008 @@ -110,7 +110,7 @@ static int imx_rngc_self_test(struct imx_rngc *rngc) cmd = readl(rngc->base + RNGC_COMMAND); writel(cmd | RNGC_CMD_SELF_TEST, rngc->base + RNGC_COMMAND); - ret = wait_for_completion_timeout(&rngc->rng_op_done, RNGC_TIMEOUT); + ret = wait_for_completion_timeout(&rngc->rng_op_done, msecs_to_jiffies(RNGC_TIMEOUT)); imx_rngc_irq_mask_clear(rngc); if (!ret) return -ETIMEDOUT; @@ -122,7 +122,6 @@ static int imx_rngc_read(struct hwrng *rng, void *data, size_t max, bool wait) { struct imx_rngc *rngc = container_of(rng, struct imx_rngc, rng); unsigned int status; - unsigned int level; int retval = 0; while (max >= sizeof(u32)) { @@ -132,11 +131,7 @@ static int imx_rngc_read(struct hwrng *rng, void *data, size_t max, bool wait) if (status & RNGC_STATUS_ERROR) break; - /* how many random numbers are in FIFO? [0-16] */ - level = (status & RNGC_STATUS_FIFO_LEVEL_MASK) >> - RNGC_STATUS_FIFO_LEVEL_SHIFT; - - if (level) { + if (status & RNGC_STATUS_FIFO_LEVEL_MASK) { /* retrieve a random number from FIFO */ *(u32 *)data = readl(rngc->base + RNGC_FIFO); @@ -187,9 +182,7 @@ static int imx_rngc_init(struct hwrng *rng) cmd = readl(rngc->base + RNGC_COMMAND); writel(cmd | RNGC_CMD_SEED, rngc->base + RNGC_COMMAND); - ret = wait_for_completion_timeout(&rngc->rng_op_done, - RNGC_TIMEOUT); - + ret = wait_for_completion_timeout(&rngc->rng_op_done, msecs_to_jiffies(RNGC_TIMEOUT)); if (!ret) { ret = -ETIMEDOUT; goto err; @@ -229,7 +222,7 @@ static void imx_rngc_cleanup(struct hwrng *rng) imx_rngc_irq_mask_clear(rngc); } -static int imx_rngc_probe(struct platform_device *pdev) +static int __init imx_rngc_probe(struct platform_device *pdev) { struct imx_rngc *rngc; int ret; @@ -256,7 +249,7 @@ static int imx_rngc_probe(struct platform_device *pdev) return irq; ver_id = readl(rngc->base + RNGC_VER_ID); - rng_type = ver_id >> RNGC_TYPE_SHIFT; + rng_type = FIELD_GET(RNG_TYPE, ver_id); /* * This driver supports only RNGC and RNGB. (There's a different * driver for RNGA.) @@ -305,7 +298,7 @@ static int imx_rngc_probe(struct platform_device *pdev) return 0; } -static int __maybe_unused imx_rngc_suspend(struct device *dev) +static int imx_rngc_suspend(struct device *dev) { struct imx_rngc *rngc = dev_get_drvdata(dev); @@ -314,7 +307,7 @@ static int __maybe_unused imx_rngc_suspend(struct device *dev) return 0; } -static int __maybe_unused imx_rngc_resume(struct device *dev) +static int imx_rngc_resume(struct device *dev) { struct imx_rngc *rngc = dev_get_drvdata(dev); @@ -323,10 +316,10 @@ static int __maybe_unused imx_rngc_resume(struct device *dev) return 0; } -static SIMPLE_DEV_PM_OPS(imx_rngc_pm_ops, imx_rngc_suspend, imx_rngc_resume); +static DEFINE_SIMPLE_DEV_PM_OPS(imx_rngc_pm_ops, imx_rngc_suspend, imx_rngc_resume); static const struct of_device_id imx_rngc_dt_ids[] = { - { .compatible = "fsl,imx25-rngb", .data = NULL, }, + { .compatible = "fsl,imx25-rngb" }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, imx_rngc_dt_ids); @@ -334,7 +327,7 @@ MODULE_DEVICE_TABLE(of, imx_rngc_dt_ids); static struct platform_driver imx_rngc_driver = { .driver = { .name = KBUILD_MODNAME, - .pm = &imx_rngc_pm_ops, + .pm = pm_sleep_ptr(&imx_rngc_pm_ops), .of_match_table = imx_rngc_dt_ids, }, }; diff --git a/drivers/char/hw_random/st-rng.c b/drivers/char/hw_random/st-rng.c index 15ba1e6fae4d27fd27bdbd603c42a0b1064e57b1..6e9dfac9fc9f4ccbea72a5766a93e3ac399cd613 100644 --- a/drivers/char/hw_random/st-rng.c +++ b/drivers/char/hw_random/st-rng.c @@ -42,7 +42,6 @@ struct st_rng_data { void __iomem *base; - struct clk *clk; struct hwrng ops; }; @@ -85,26 +84,18 @@ static int st_rng_probe(struct platform_device *pdev) if (IS_ERR(base)) return PTR_ERR(base); - clk = devm_clk_get(&pdev->dev, NULL); + clk = devm_clk_get_enabled(&pdev->dev, NULL); if (IS_ERR(clk)) return PTR_ERR(clk); - ret = clk_prepare_enable(clk); - if (ret) - return ret; - ddata->ops.priv = (unsigned long)ddata; ddata->ops.read = st_rng_read; ddata->ops.name = pdev->name; ddata->base = base; - ddata->clk = clk; - - dev_set_drvdata(&pdev->dev, ddata); ret = devm_hwrng_register(&pdev->dev, &ddata->ops); if (ret) { dev_err(&pdev->dev, "Failed to register HW RNG\n"); - clk_disable_unprepare(clk); return ret; } @@ -113,15 +104,6 @@ static int st_rng_probe(struct platform_device *pdev) return 0; } -static int st_rng_remove(struct platform_device *pdev) -{ - struct st_rng_data *ddata = dev_get_drvdata(&pdev->dev); - - clk_disable_unprepare(ddata->clk); - - return 0; -} - static const struct of_device_id st_rng_match[] __maybe_unused = { { .compatible = "st,rng" }, {}, @@ -134,7 +116,6 @@ static struct platform_driver st_rng_driver = { .of_match_table = of_match_ptr(st_rng_match), }, .probe = st_rng_probe, - .remove = st_rng_remove }; module_platform_driver(st_rng_driver); diff --git a/drivers/char/hw_random/virtio-rng.c b/drivers/char/hw_random/virtio-rng.c index f7690e0f92ede2f1ed29afc7de5943443c4b0988..e41a84e6b4b56a86a0921d6ee5e16665fcd7964b 100644 --- a/drivers/char/hw_random/virtio-rng.c +++ b/drivers/char/hw_random/virtio-rng.c @@ -4,6 +4,7 @@ * Copyright (C) 2007, 2008 Rusty Russell IBM Corporation */ +#include #include #include #include @@ -37,13 +38,13 @@ struct virtrng_info { static void random_recv_done(struct virtqueue *vq) { struct virtrng_info *vi = vq->vdev->priv; + unsigned int len; /* We can get spurious callbacks, e.g. shared IRQs + virtio_pci. */ - if (!virtqueue_get_buf(vi->vq, &vi->data_avail)) + if (!virtqueue_get_buf(vi->vq, &len)) return; - vi->data_idx = 0; - + smp_store_release(&vi->data_avail, len); complete(&vi->have_data); } @@ -52,7 +53,6 @@ static void request_entropy(struct virtrng_info *vi) struct scatterlist sg; reinit_completion(&vi->have_data); - vi->data_avail = 0; vi->data_idx = 0; sg_init_one(&sg, vi->data, sizeof(vi->data)); @@ -88,7 +88,7 @@ static int virtio_read(struct hwrng *rng, void *buf, size_t size, bool wait) read = 0; /* copy available data */ - if (vi->data_avail) { + if (smp_load_acquire(&vi->data_avail)) { chunk = copy_data(vi, buf, size); size -= chunk; read += chunk; diff --git a/drivers/char/lp.c b/drivers/char/lp.c index 70cfc5140c2cb8470e76d9e6356912920bfca5b9..2f171d14b9b50708ab342b074e009b4ded819f83 100644 --- a/drivers/char/lp.c +++ b/drivers/char/lp.c @@ -145,7 +145,9 @@ static struct lp_struct lp_table[LP_NO]; static int port_num[LP_NO]; static unsigned int lp_count = 0; -static struct class *lp_class; +static const struct class lp_class = { + .name = "printer", +}; #ifdef CONFIG_LP_CONSOLE static struct parport *console_registered; @@ -932,7 +934,7 @@ static int lp_register(int nr, struct parport *port) if (reset) lp_reset(nr); - device_create(lp_class, port->dev, MKDEV(LP_MAJOR, nr), NULL, + device_create(&lp_class, port->dev, MKDEV(LP_MAJOR, nr), NULL, "lp%d", nr); printk(KERN_INFO "lp%d: using %s (%s).\n", nr, port->name, @@ -1004,7 +1006,7 @@ static void lp_detach(struct parport *port) if (port_num[n] == port->number) { port_num[n] = -1; lp_count--; - device_destroy(lp_class, MKDEV(LP_MAJOR, n)); + device_destroy(&lp_class, MKDEV(LP_MAJOR, n)); parport_unregister_device(lp_table[n].dev); } } @@ -1049,11 +1051,9 @@ static int __init lp_init(void) return -EIO; } - lp_class = class_create("printer"); - if (IS_ERR(lp_class)) { - err = PTR_ERR(lp_class); + err = class_register(&lp_class); + if (err) goto out_reg; - } if (parport_register_driver(&lp_driver)) { printk(KERN_ERR "lp: unable to register with parport\n"); @@ -1072,7 +1072,7 @@ static int __init lp_init(void) return 0; out_class: - class_destroy(lp_class); + class_unregister(&lp_class); out_reg: unregister_chrdev(LP_MAJOR, "lp"); return err; @@ -1115,7 +1115,7 @@ static void lp_cleanup_module(void) #endif unregister_chrdev(LP_MAJOR, "lp"); - class_destroy(lp_class); + class_unregister(&lp_class); } __setup("lp=", lp_setup); diff --git a/drivers/char/mem.c b/drivers/char/mem.c index f494d31f2b9835b951f5f303194655308526430d..0fcc8615fb4f292e80d6d2f5142071ec5a8916c2 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c @@ -90,13 +90,6 @@ static inline int range_is_allowed(unsigned long pfn, unsigned long size) } #endif -#ifndef unxlate_dev_mem_ptr -#define unxlate_dev_mem_ptr unxlate_dev_mem_ptr -void __weak unxlate_dev_mem_ptr(phys_addr_t phys, void *addr) -{ -} -#endif - static inline bool should_stop_iteration(void) { if (need_resched()) @@ -753,20 +746,23 @@ static char *mem_devnode(const struct device *dev, umode_t *mode) return NULL; } -static struct class *mem_class; +static const struct class mem_class = { + .name = "mem", + .devnode = mem_devnode, +}; static int __init chr_dev_init(void) { + int retval; int minor; if (register_chrdev(MEM_MAJOR, "mem", &memory_fops)) printk("unable to get major %d for memory devs\n", MEM_MAJOR); - mem_class = class_create("mem"); - if (IS_ERR(mem_class)) - return PTR_ERR(mem_class); + retval = class_register(&mem_class); + if (retval) + return retval; - mem_class->devnode = mem_devnode; for (minor = 1; minor < ARRAY_SIZE(devlist); minor++) { if (!devlist[minor].name) continue; @@ -777,7 +773,7 @@ static int __init chr_dev_init(void) if ((minor == DEVPORT_MINOR) && !arch_has_dev_port()) continue; - device_create(mem_class, NULL, MKDEV(MEM_MAJOR, minor), + device_create(&mem_class, NULL, MKDEV(MEM_MAJOR, minor), NULL, devlist[minor].name); } diff --git a/drivers/char/misc.c b/drivers/char/misc.c index 1c44c29a666eb94956f1c2efab44b63082684027..541edc26ec89a14ef3735da111452c78d553b79e 100644 --- a/drivers/char/misc.c +++ b/drivers/char/misc.c @@ -168,7 +168,21 @@ static int misc_open(struct inode *inode, struct file *file) return err; } -static struct class *misc_class; +static char *misc_devnode(const struct device *dev, umode_t *mode) +{ + const struct miscdevice *c = dev_get_drvdata(dev); + + if (mode && c->mode) + *mode = c->mode; + if (c->nodename) + return kstrdup(c->nodename, GFP_KERNEL); + return NULL; +} + +static const struct class misc_class = { + .name = "misc", + .devnode = misc_devnode, +}; static const struct file_operations misc_fops = { .owner = THIS_MODULE, @@ -226,7 +240,7 @@ int misc_register(struct miscdevice *misc) dev = MKDEV(MISC_MAJOR, misc->minor); misc->this_device = - device_create_with_groups(misc_class, misc->parent, dev, + device_create_with_groups(&misc_class, misc->parent, dev, misc, misc->groups, "%s", misc->name); if (IS_ERR(misc->this_device)) { if (is_dynamic) { @@ -263,43 +277,30 @@ void misc_deregister(struct miscdevice *misc) mutex_lock(&misc_mtx); list_del(&misc->list); - device_destroy(misc_class, MKDEV(MISC_MAJOR, misc->minor)); + device_destroy(&misc_class, MKDEV(MISC_MAJOR, misc->minor)); misc_minor_free(misc->minor); mutex_unlock(&misc_mtx); } EXPORT_SYMBOL(misc_deregister); -static char *misc_devnode(const struct device *dev, umode_t *mode) -{ - const struct miscdevice *c = dev_get_drvdata(dev); - - if (mode && c->mode) - *mode = c->mode; - if (c->nodename) - return kstrdup(c->nodename, GFP_KERNEL); - return NULL; -} - static int __init misc_init(void) { int err; struct proc_dir_entry *ret; ret = proc_create_seq("misc", 0, NULL, &misc_seq_ops); - misc_class = class_create("misc"); - err = PTR_ERR(misc_class); - if (IS_ERR(misc_class)) + err = class_register(&misc_class); + if (err) goto fail_remove; err = -EIO; if (register_chrdev(MISC_MAJOR, "misc", &misc_fops)) goto fail_printk; - misc_class->devnode = misc_devnode; return 0; fail_printk: pr_err("unable to get major %d for misc devices\n", MISC_MAJOR); - class_destroy(misc_class); + class_unregister(&misc_class); fail_remove: if (ret) remove_proc_entry("misc", NULL); diff --git a/drivers/char/ppdev.c b/drivers/char/ppdev.c index 81ed58157b1579c147b640a82d7b3ba46ebb7c88..4c188e9e477cdfebec5fa237e0c30fe6e1289ef9 100644 --- a/drivers/char/ppdev.c +++ b/drivers/char/ppdev.c @@ -773,7 +773,9 @@ static __poll_t pp_poll(struct file *file, poll_table *wait) return mask; } -static struct class *ppdev_class; +static const struct class ppdev_class = { + .name = CHRDEV, +}; static const struct file_operations pp_fops = { .owner = THIS_MODULE, @@ -794,7 +796,7 @@ static void pp_attach(struct parport *port) if (devices[port->number]) return; - ret = device_create(ppdev_class, port->dev, + ret = device_create(&ppdev_class, port->dev, MKDEV(PP_MAJOR, port->number), NULL, "parport%d", port->number); if (IS_ERR(ret)) { @@ -810,7 +812,7 @@ static void pp_detach(struct parport *port) if (!devices[port->number]) return; - device_destroy(ppdev_class, MKDEV(PP_MAJOR, port->number)); + device_destroy(&ppdev_class, MKDEV(PP_MAJOR, port->number)); devices[port->number] = NULL; } @@ -841,11 +843,10 @@ static int __init ppdev_init(void) pr_warn(CHRDEV ": unable to get major %d\n", PP_MAJOR); return -EIO; } - ppdev_class = class_create(CHRDEV); - if (IS_ERR(ppdev_class)) { - err = PTR_ERR(ppdev_class); + err = class_register(&ppdev_class); + if (err) goto out_chrdev; - } + err = parport_register_driver(&pp_driver); if (err < 0) { pr_warn(CHRDEV ": unable to register with parport\n"); @@ -856,7 +857,7 @@ static int __init ppdev_init(void) goto out; out_class: - class_destroy(ppdev_class); + class_unregister(&ppdev_class); out_chrdev: unregister_chrdev(PP_MAJOR, CHRDEV); out: @@ -867,7 +868,7 @@ static void __exit ppdev_cleanup(void) { /* Clean up all parport stuff */ parport_unregister_driver(&pp_driver); - class_destroy(ppdev_class); + class_unregister(&ppdev_class); unregister_chrdev(PP_MAJOR, CHRDEV); } diff --git a/drivers/char/random.c b/drivers/char/random.c index 253f2ddb891308591db05ada2de72aa8703043da..3cb37760dfec231e4858e062100c3526be30f0be 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -1546,7 +1546,7 @@ const struct file_operations random_fops = { .compat_ioctl = compat_ptr_ioctl, .fasync = random_fasync, .llseek = noop_llseek, - .splice_read = generic_file_splice_read, + .splice_read = copy_splice_read, .splice_write = iter_file_splice_write, }; @@ -1557,7 +1557,7 @@ const struct file_operations urandom_fops = { .compat_ioctl = compat_ptr_ioctl, .fasync = random_fasync, .llseek = noop_llseek, - .splice_read = generic_file_splice_read, + .splice_read = copy_splice_read, .splice_write = iter_file_splice_write, }; diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index b65c809a4e978d41ba80bfab5b6fab1c5f9a2b7b..680d1ef2a21794b5b549e341c75828559a446571 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c @@ -40,9 +40,6 @@ * across multiple devices and multiple ports per device. */ struct ports_driver_data { - /* Used for registering chardevs */ - struct class *class; - /* Used for exporting per-port information to debugfs */ struct dentry *debugfs_dir; @@ -55,6 +52,10 @@ struct ports_driver_data { static struct ports_driver_data pdrvdata; +static const struct class port_class = { + .name = "virtio-ports", +}; + static DEFINE_SPINLOCK(pdrvdata_lock); static DECLARE_COMPLETION(early_console_added); @@ -1399,7 +1400,7 @@ static int add_port(struct ports_device *portdev, u32 id) "Error %d adding cdev for port %u\n", err, id); goto free_cdev; } - port->dev = device_create(pdrvdata.class, &port->portdev->vdev->dev, + port->dev = device_create(&port_class, &port->portdev->vdev->dev, devt, port, "vport%up%u", port->portdev->vdev->index, id); if (IS_ERR(port->dev)) { @@ -1465,7 +1466,7 @@ static int add_port(struct ports_device *portdev, u32 id) free_inbufs: free_device: - device_destroy(pdrvdata.class, port->dev->devt); + device_destroy(&port_class, port->dev->devt); free_cdev: cdev_del(port->cdev); free_port: @@ -1540,7 +1541,7 @@ static void unplug_port(struct port *port) port->portdev = NULL; sysfs_remove_group(&port->dev->kobj, &port_attribute_group); - device_destroy(pdrvdata.class, port->dev->devt); + device_destroy(&port_class, port->dev->devt); cdev_del(port->cdev); debugfs_remove(port->debugfs_file); @@ -1935,6 +1936,7 @@ static void remove_vqs(struct ports_device *portdev) flush_bufs(vq, true); while ((buf = virtqueue_detach_unused_buf(vq))) free_buf(buf, true); + cond_resched(); } portdev->vdev->config->del_vqs(portdev->vdev); kfree(portdev->in_vqs); @@ -2244,12 +2246,9 @@ static int __init virtio_console_init(void) { int err; - pdrvdata.class = class_create("virtio-ports"); - if (IS_ERR(pdrvdata.class)) { - err = PTR_ERR(pdrvdata.class); - pr_err("Error %d creating virtio-ports class\n", err); + err = class_register(&port_class); + if (err) return err; - } pdrvdata.debugfs_dir = debugfs_create_dir("virtio-ports", NULL); INIT_LIST_HEAD(&pdrvdata.consoles); @@ -2271,7 +2270,7 @@ static int __init virtio_console_init(void) unregister_virtio_driver(&virtio_console); free: debugfs_remove_recursive(pdrvdata.debugfs_dir); - class_destroy(pdrvdata.class); + class_unregister(&port_class); return err; } @@ -2282,7 +2281,7 @@ static void __exit virtio_console_fini(void) unregister_virtio_driver(&virtio_console); unregister_virtio_driver(&virtio_rproc_serial); - class_destroy(pdrvdata.class); + class_unregister(&port_class); debugfs_remove_recursive(pdrvdata.debugfs_dir); } module_init(virtio_console_init); diff --git a/drivers/char/xilinx_hwicap/xilinx_hwicap.c b/drivers/char/xilinx_hwicap/xilinx_hwicap.c index a46f637da9599afebb80c2bb5627671b21b08ea1..f60bb6151402f015b40b6affd879eb16a34c033d 100644 --- a/drivers/char/xilinx_hwicap/xilinx_hwicap.c +++ b/drivers/char/xilinx_hwicap/xilinx_hwicap.c @@ -113,7 +113,9 @@ static DEFINE_MUTEX(hwicap_mutex); static bool probed_devices[HWICAP_DEVICES]; static struct mutex icap_sem; -static struct class *icap_class; +static const struct class icap_class = { + .name = "xilinx_config", +}; #define UNIMPLEMENTED 0xFFFF @@ -687,7 +689,7 @@ static int hwicap_setup(struct device *dev, int id, goto failed3; } - device_create(icap_class, dev, devt, NULL, "%s%d", DRIVER_NAME, id); + device_create(&icap_class, dev, devt, NULL, "%s%d", DRIVER_NAME, id); return 0; /* success */ failed3: @@ -721,27 +723,6 @@ static struct hwicap_driver_config fifo_icap_config = { .reset = fifo_icap_reset, }; -static int hwicap_remove(struct device *dev) -{ - struct hwicap_drvdata *drvdata; - - drvdata = dev_get_drvdata(dev); - - if (!drvdata) - return 0; - - device_destroy(icap_class, drvdata->devt); - cdev_del(&drvdata->cdev); - iounmap(drvdata->base_address); - release_mem_region(drvdata->mem_start, drvdata->mem_size); - kfree(drvdata); - - mutex_lock(&icap_sem); - probed_devices[MINOR(dev->devt)-XHWICAP_MINOR] = 0; - mutex_unlock(&icap_sem); - return 0; /* success */ -} - #ifdef CONFIG_OF static int hwicap_of_probe(struct platform_device *op, const struct hwicap_driver_config *config) @@ -825,9 +806,22 @@ static int hwicap_drv_probe(struct platform_device *pdev) &buffer_icap_config, regs); } -static int hwicap_drv_remove(struct platform_device *pdev) +static void hwicap_drv_remove(struct platform_device *pdev) { - return hwicap_remove(&pdev->dev); + struct device *dev = &pdev->dev; + struct hwicap_drvdata *drvdata; + + drvdata = dev_get_drvdata(dev); + + device_destroy(&icap_class, drvdata->devt); + cdev_del(&drvdata->cdev); + iounmap(drvdata->base_address); + release_mem_region(drvdata->mem_start, drvdata->mem_size); + kfree(drvdata); + + mutex_lock(&icap_sem); + probed_devices[MINOR(dev->devt)-XHWICAP_MINOR] = 0; + mutex_unlock(&icap_sem); } #ifdef CONFIG_OF @@ -844,7 +838,7 @@ MODULE_DEVICE_TABLE(of, hwicap_of_match); static struct platform_driver hwicap_platform_driver = { .probe = hwicap_drv_probe, - .remove = hwicap_drv_remove, + .remove_new = hwicap_drv_remove, .driver = { .name = DRIVER_NAME, .of_match_table = hwicap_of_match, @@ -856,7 +850,9 @@ static int __init hwicap_module_init(void) dev_t devt; int retval; - icap_class = class_create("xilinx_config"); + retval = class_register(&icap_class); + if (retval) + return retval; mutex_init(&icap_sem); devt = MKDEV(XHWICAP_MAJOR, XHWICAP_MINOR); @@ -882,7 +878,7 @@ static void __exit hwicap_module_cleanup(void) { dev_t devt = MKDEV(XHWICAP_MAJOR, XHWICAP_MINOR); - class_destroy(icap_class); + class_unregister(&icap_class); platform_driver_unregister(&hwicap_platform_driver); diff --git a/drivers/char/xillybus/xillybus_class.c b/drivers/char/xillybus/xillybus_class.c index 89926fe9d8130b8f88ff01de55c03f6662c0b454..c92a628e389eefd1bb221b716f201d323d57bd52 100644 --- a/drivers/char/xillybus/xillybus_class.c +++ b/drivers/char/xillybus/xillybus_class.c @@ -23,7 +23,9 @@ MODULE_LICENSE("GPL v2"); static DEFINE_MUTEX(unit_mutex); static LIST_HEAD(unit_list); -static struct class *xillybus_class; +static const struct class xillybus_class = { + .name = "xillybus", +}; #define UNITNAMELEN 16 @@ -121,7 +123,7 @@ int xillybus_init_chrdev(struct device *dev, len -= namelen + 1; idt += namelen + 1; - device = device_create(xillybus_class, + device = device_create(&xillybus_class, NULL, MKDEV(unit->major, i + unit->lowest_minor), @@ -152,7 +154,7 @@ int xillybus_init_chrdev(struct device *dev, unroll_device_create: for (i--; i >= 0; i--) - device_destroy(xillybus_class, MKDEV(unit->major, + device_destroy(&xillybus_class, MKDEV(unit->major, i + unit->lowest_minor)); cdev_del(unit->cdev); @@ -193,7 +195,7 @@ void xillybus_cleanup_chrdev(void *private_data, for (minor = unit->lowest_minor; minor < (unit->lowest_minor + unit->num_nodes); minor++) - device_destroy(xillybus_class, MKDEV(unit->major, minor)); + device_destroy(&xillybus_class, MKDEV(unit->major, minor)); cdev_del(unit->cdev); @@ -242,19 +244,12 @@ EXPORT_SYMBOL(xillybus_find_inode); static int __init xillybus_class_init(void) { - xillybus_class = class_create("xillybus"); - - if (IS_ERR(xillybus_class)) { - pr_warn("Failed to register xillybus class\n"); - - return PTR_ERR(xillybus_class); - } - return 0; + return class_register(&xillybus_class); } static void __exit xillybus_class_exit(void) { - class_destroy(xillybus_class); + class_unregister(&xillybus_class); } module_init(xillybus_class_init); diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index 016814e15536a97d81be6702af644e31abfd8af7..93f38a8178bac24d664d1fc10bf4104f9b4b07a7 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -82,7 +82,7 @@ config COMMON_CLK_MAX9485 config COMMON_CLK_RK808 tristate "Clock driver for RK805/RK808/RK809/RK817/RK818" - depends on MFD_RK808 + depends on MFD_RK8XX help This driver supports RK805, RK809 and RK817, RK808 and RK818 crystal oscillator clock. These multi-function devices have two fixed-rate oscillators, clocked at 32KHz each. @@ -478,6 +478,7 @@ source "drivers/clk/meson/Kconfig" source "drivers/clk/mstar/Kconfig" source "drivers/clk/microchip/Kconfig" source "drivers/clk/mvebu/Kconfig" +source "drivers/clk/nuvoton/Kconfig" source "drivers/clk/pistachio/Kconfig" source "drivers/clk/qcom/Kconfig" source "drivers/clk/ralink/Kconfig" diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index 0aebef17edc66cfde2403112db0ee99f135bf5eb..7cb000549b612d6940732e1bc1dcbf775ae2d3a0 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -106,6 +106,7 @@ endif obj-y += mstar/ obj-y += mvebu/ obj-$(CONFIG_ARCH_MXS) += mxs/ +obj-$(CONFIG_ARCH_MA35) += nuvoton/ obj-$(CONFIG_COMMON_CLK_NXP) += nxp/ obj-$(CONFIG_COMMON_CLK_PISTACHIO) += pistachio/ obj-$(CONFIG_COMMON_CLK_PXA) += pxa/ diff --git a/drivers/clk/actions/owl-composite.c b/drivers/clk/actions/owl-composite.c index 101706e0c66ffdb2e2d0c2d1c36373d79ad385cf..48f177f6ce9cfacda80b4809b52a24f4fcd30871 100644 --- a/drivers/clk/actions/owl-composite.c +++ b/drivers/clk/actions/owl-composite.c @@ -53,13 +53,19 @@ static int owl_comp_is_enabled(struct clk_hw *hw) return owl_gate_clk_is_enabled(common, &comp->gate_hw); } -static long owl_comp_div_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *parent_rate) +static int owl_comp_div_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) { struct owl_composite *comp = hw_to_owl_comp(hw); + long rate; - return owl_divider_helper_round_rate(&comp->common, &comp->rate.div_hw, - rate, parent_rate); + rate = owl_divider_helper_round_rate(&comp->common, &comp->rate.div_hw, + req->rate, &req->best_parent_rate); + if (rate < 0) + return rate; + + req->rate = rate; + return 0; } static unsigned long owl_comp_div_recalc_rate(struct clk_hw *hw, @@ -80,14 +86,20 @@ static int owl_comp_div_set_rate(struct clk_hw *hw, unsigned long rate, rate, parent_rate); } -static long owl_comp_fact_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *parent_rate) +static int owl_comp_fact_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) { struct owl_composite *comp = hw_to_owl_comp(hw); + long rate; - return owl_factor_helper_round_rate(&comp->common, - &comp->rate.factor_hw, - rate, parent_rate); + rate = owl_factor_helper_round_rate(&comp->common, + &comp->rate.factor_hw, + req->rate, &req->best_parent_rate); + if (rate < 0) + return rate; + + req->rate = rate; + return 0; } static unsigned long owl_comp_fact_recalc_rate(struct clk_hw *hw, @@ -152,7 +164,7 @@ const struct clk_ops owl_comp_div_ops = { .is_enabled = owl_comp_is_enabled, /* div_ops */ - .round_rate = owl_comp_div_round_rate, + .determine_rate = owl_comp_div_determine_rate, .recalc_rate = owl_comp_div_recalc_rate, .set_rate = owl_comp_div_set_rate, }; @@ -169,7 +181,7 @@ const struct clk_ops owl_comp_fact_ops = { .is_enabled = owl_comp_is_enabled, /* fact_ops */ - .round_rate = owl_comp_fact_round_rate, + .determine_rate = owl_comp_fact_determine_rate, .recalc_rate = owl_comp_fact_recalc_rate, .set_rate = owl_comp_fact_set_rate, }; @@ -189,6 +201,7 @@ const struct clk_ops owl_comp_fix_fact_ops = { const struct clk_ops owl_comp_pass_ops = { /* mux_ops */ + .determine_rate = clk_hw_determine_rate_no_reparent, .get_parent = owl_comp_get_parent, .set_parent = owl_comp_set_parent, diff --git a/drivers/clk/at91/at91rm9200.c b/drivers/clk/at91/at91rm9200.c index 0b860126d589eee06376360e962b18328e043ba3..3f19e737ae4d2961e61255f56781b5b27e4566ff 100644 --- a/drivers/clk/at91/at91rm9200.c +++ b/drivers/clk/at91/at91rm9200.c @@ -108,12 +108,12 @@ static void __init at91rm9200_pmc_setup(struct device_node *np) bypass = of_property_read_bool(np, "atmel,osc-bypass"); - hw = at91_clk_register_main_osc(regmap, "main_osc", mainxtal_name, + hw = at91_clk_register_main_osc(regmap, "main_osc", mainxtal_name, NULL, bypass); if (IS_ERR(hw)) goto err_free; - hw = at91_clk_register_rm9200_main(regmap, "mainck", "main_osc"); + hw = at91_clk_register_rm9200_main(regmap, "mainck", "main_osc", NULL); if (IS_ERR(hw)) goto err_free; @@ -140,7 +140,7 @@ static void __init at91rm9200_pmc_setup(struct device_node *np) parent_names[2] = "pllack"; parent_names[3] = "pllbck"; hw = at91_clk_register_master_pres(regmap, "masterck_pres", 4, - parent_names, + parent_names, NULL, &at91rm9200_master_layout, &rm9200_mck_characteristics, &rm9200_mck_lock); @@ -148,7 +148,7 @@ static void __init at91rm9200_pmc_setup(struct device_node *np) goto err_free; hw = at91_clk_register_master_div(regmap, "masterck_div", - "masterck_pres", + "masterck_pres", NULL, &at91rm9200_master_layout, &rm9200_mck_characteristics, &rm9200_mck_lock, CLK_SET_RATE_GATE, 0); @@ -171,7 +171,7 @@ static void __init at91rm9200_pmc_setup(struct device_node *np) snprintf(name, sizeof(name), "prog%d", i); hw = at91_clk_register_programmable(regmap, name, - parent_names, 4, i, + parent_names, NULL, 4, i, &at91rm9200_programmable_layout, NULL); if (IS_ERR(hw)) @@ -182,7 +182,7 @@ static void __init at91rm9200_pmc_setup(struct device_node *np) for (i = 0; i < ARRAY_SIZE(at91rm9200_systemck); i++) { hw = at91_clk_register_system(regmap, at91rm9200_systemck[i].n, - at91rm9200_systemck[i].p, + at91rm9200_systemck[i].p, NULL, at91rm9200_systemck[i].id, 0); if (IS_ERR(hw)) goto err_free; @@ -193,7 +193,7 @@ static void __init at91rm9200_pmc_setup(struct device_node *np) for (i = 0; i < ARRAY_SIZE(at91rm9200_periphck); i++) { hw = at91_clk_register_peripheral(regmap, at91rm9200_periphck[i].n, - "masterck_div", + "masterck_div", NULL, at91rm9200_periphck[i].id); if (IS_ERR(hw)) goto err_free; diff --git a/drivers/clk/at91/at91sam9260.c b/drivers/clk/at91/at91sam9260.c index b521f470428ff205f627a6ca4c69cafddecdb019..0799a13060ea4551477246ef657cf381014cbaae 100644 --- a/drivers/clk/at91/at91sam9260.c +++ b/drivers/clk/at91/at91sam9260.c @@ -363,12 +363,12 @@ static void __init at91sam926x_pmc_setup(struct device_node *np, bypass = of_property_read_bool(np, "atmel,osc-bypass"); - hw = at91_clk_register_main_osc(regmap, "main_osc", mainxtal_name, + hw = at91_clk_register_main_osc(regmap, "main_osc", mainxtal_name, NULL, bypass); if (IS_ERR(hw)) goto err_free; - hw = at91_clk_register_rm9200_main(regmap, "mainck", "main_osc"); + hw = at91_clk_register_rm9200_main(regmap, "mainck", "main_osc", NULL); if (IS_ERR(hw)) goto err_free; @@ -416,7 +416,7 @@ static void __init at91sam926x_pmc_setup(struct device_node *np, parent_names[2] = "pllack"; parent_names[3] = "pllbck"; hw = at91_clk_register_master_pres(regmap, "masterck_pres", 4, - parent_names, + parent_names, NULL, &at91rm9200_master_layout, data->mck_characteristics, &at91sam9260_mck_lock); @@ -424,7 +424,7 @@ static void __init at91sam926x_pmc_setup(struct device_node *np, goto err_free; hw = at91_clk_register_master_div(regmap, "masterck_div", - "masterck_pres", + "masterck_pres", NULL, &at91rm9200_master_layout, data->mck_characteristics, &at91sam9260_mck_lock, @@ -448,7 +448,7 @@ static void __init at91sam926x_pmc_setup(struct device_node *np, snprintf(name, sizeof(name), "prog%d", i); hw = at91_clk_register_programmable(regmap, name, - parent_names, 4, i, + parent_names, NULL, 4, i, &at91rm9200_programmable_layout, NULL); if (IS_ERR(hw)) @@ -459,7 +459,7 @@ static void __init at91sam926x_pmc_setup(struct device_node *np, for (i = 0; i < data->num_sck; i++) { hw = at91_clk_register_system(regmap, data->sck[i].n, - data->sck[i].p, + data->sck[i].p, NULL, data->sck[i].id, 0); if (IS_ERR(hw)) goto err_free; @@ -470,7 +470,7 @@ static void __init at91sam926x_pmc_setup(struct device_node *np, for (i = 0; i < data->num_pck; i++) { hw = at91_clk_register_peripheral(regmap, data->pck[i].n, - "masterck_div", + "masterck_div", NULL, data->pck[i].id); if (IS_ERR(hw)) goto err_free; diff --git a/drivers/clk/at91/at91sam9g45.c b/drivers/clk/at91/at91sam9g45.c index 5099669ddcbd49c9e1ecf7328f0773f5e0c20cb4..f45a7b80f7d8be6ae34d4df2d98bc989f66176f5 100644 --- a/drivers/clk/at91/at91sam9g45.c +++ b/drivers/clk/at91/at91sam9g45.c @@ -123,12 +123,12 @@ static void __init at91sam9g45_pmc_setup(struct device_node *np) bypass = of_property_read_bool(np, "atmel,osc-bypass"); - hw = at91_clk_register_main_osc(regmap, "main_osc", mainxtal_name, + hw = at91_clk_register_main_osc(regmap, "main_osc", mainxtal_name, NULL, bypass); if (IS_ERR(hw)) goto err_free; - hw = at91_clk_register_rm9200_main(regmap, "mainck", "main_osc"); + hw = at91_clk_register_rm9200_main(regmap, "mainck", "main_osc", NULL); if (IS_ERR(hw)) goto err_free; @@ -145,7 +145,7 @@ static void __init at91sam9g45_pmc_setup(struct device_node *np) at91sam9g45_pmc->chws[PMC_PLLACK] = hw; - hw = at91_clk_register_utmi(regmap, NULL, "utmick", "mainck"); + hw = at91_clk_register_utmi(regmap, NULL, "utmick", "mainck", NULL); if (IS_ERR(hw)) goto err_free; @@ -156,7 +156,7 @@ static void __init at91sam9g45_pmc_setup(struct device_node *np) parent_names[2] = "plladivck"; parent_names[3] = "utmick"; hw = at91_clk_register_master_pres(regmap, "masterck_pres", 4, - parent_names, + parent_names, NULL, &at91rm9200_master_layout, &mck_characteristics, &at91sam9g45_mck_lock); @@ -164,7 +164,7 @@ static void __init at91sam9g45_pmc_setup(struct device_node *np) goto err_free; hw = at91_clk_register_master_div(regmap, "masterck_div", - "masterck_pres", + "masterck_pres", NULL, &at91rm9200_master_layout, &mck_characteristics, &at91sam9g45_mck_lock, @@ -191,7 +191,7 @@ static void __init at91sam9g45_pmc_setup(struct device_node *np) snprintf(name, sizeof(name), "prog%d", i); hw = at91_clk_register_programmable(regmap, name, - parent_names, 5, i, + parent_names, NULL, 5, i, &at91sam9g45_programmable_layout, NULL); if (IS_ERR(hw)) @@ -202,7 +202,7 @@ static void __init at91sam9g45_pmc_setup(struct device_node *np) for (i = 0; i < ARRAY_SIZE(at91sam9g45_systemck); i++) { hw = at91_clk_register_system(regmap, at91sam9g45_systemck[i].n, - at91sam9g45_systemck[i].p, + at91sam9g45_systemck[i].p, NULL, at91sam9g45_systemck[i].id, at91sam9g45_systemck[i].flags); if (IS_ERR(hw)) @@ -214,7 +214,7 @@ static void __init at91sam9g45_pmc_setup(struct device_node *np) for (i = 0; i < ARRAY_SIZE(at91sam9g45_periphck); i++) { hw = at91_clk_register_peripheral(regmap, at91sam9g45_periphck[i].n, - "masterck_div", + "masterck_div", NULL, at91sam9g45_periphck[i].id); if (IS_ERR(hw)) goto err_free; diff --git a/drivers/clk/at91/at91sam9n12.c b/drivers/clk/at91/at91sam9n12.c index 08a10e12d08dfc22c2a3acd7bb450014a63eb48c..751786184ae2b35a6c7fd441af3427e3c829d68a 100644 --- a/drivers/clk/at91/at91sam9n12.c +++ b/drivers/clk/at91/at91sam9n12.c @@ -147,14 +147,14 @@ static void __init at91sam9n12_pmc_setup(struct device_node *np) bypass = of_property_read_bool(np, "atmel,osc-bypass"); - hw = at91_clk_register_main_osc(regmap, "main_osc", mainxtal_name, + hw = at91_clk_register_main_osc(regmap, "main_osc", mainxtal_name, NULL, bypass); if (IS_ERR(hw)) goto err_free; parent_names[0] = "main_rc_osc"; parent_names[1] = "main_osc"; - hw = at91_clk_register_sam9x5_main(regmap, "mainck", parent_names, 2); + hw = at91_clk_register_sam9x5_main(regmap, "mainck", parent_names, NULL, 2); if (IS_ERR(hw)) goto err_free; @@ -183,7 +183,7 @@ static void __init at91sam9n12_pmc_setup(struct device_node *np) parent_names[2] = "plladivck"; parent_names[3] = "pllbck"; hw = at91_clk_register_master_pres(regmap, "masterck_pres", 4, - parent_names, + parent_names, NULL, &at91sam9x5_master_layout, &mck_characteristics, &at91sam9n12_mck_lock); @@ -191,7 +191,7 @@ static void __init at91sam9n12_pmc_setup(struct device_node *np) goto err_free; hw = at91_clk_register_master_div(regmap, "masterck_div", - "masterck_pres", + "masterck_pres", NULL, &at91sam9x5_master_layout, &mck_characteristics, &at91sam9n12_mck_lock, @@ -216,7 +216,7 @@ static void __init at91sam9n12_pmc_setup(struct device_node *np) snprintf(name, sizeof(name), "prog%d", i); hw = at91_clk_register_programmable(regmap, name, - parent_names, 5, i, + parent_names, NULL, 5, i, &at91sam9x5_programmable_layout, NULL); if (IS_ERR(hw)) @@ -227,7 +227,7 @@ static void __init at91sam9n12_pmc_setup(struct device_node *np) for (i = 0; i < ARRAY_SIZE(at91sam9n12_systemck); i++) { hw = at91_clk_register_system(regmap, at91sam9n12_systemck[i].n, - at91sam9n12_systemck[i].p, + at91sam9n12_systemck[i].p, NULL, at91sam9n12_systemck[i].id, at91sam9n12_systemck[i].flags); if (IS_ERR(hw)) @@ -240,7 +240,7 @@ static void __init at91sam9n12_pmc_setup(struct device_node *np) hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock, &at91sam9n12_pcr_layout, at91sam9n12_periphck[i].n, - "masterck_div", + "masterck_div", NULL, at91sam9n12_periphck[i].id, &range, INT_MIN, 0); if (IS_ERR(hw)) diff --git a/drivers/clk/at91/at91sam9rl.c b/drivers/clk/at91/at91sam9rl.c index 1a1b6b2bb0e35aa810a0835ae1a38d50193c0a30..969f809e7d65aab5eeba405bbb3f3b8353d3d469 100644 --- a/drivers/clk/at91/at91sam9rl.c +++ b/drivers/clk/at91/at91sam9rl.c @@ -95,7 +95,7 @@ static void __init at91sam9rl_pmc_setup(struct device_node *np) if (!at91sam9rl_pmc) return; - hw = at91_clk_register_rm9200_main(regmap, "mainck", mainxtal_name); + hw = at91_clk_register_rm9200_main(regmap, "mainck", mainxtal_name, NULL); if (IS_ERR(hw)) goto err_free; @@ -109,7 +109,7 @@ static void __init at91sam9rl_pmc_setup(struct device_node *np) at91sam9rl_pmc->chws[PMC_PLLACK] = hw; - hw = at91_clk_register_utmi(regmap, NULL, "utmick", "mainck"); + hw = at91_clk_register_utmi(regmap, NULL, "utmick", "mainck", NULL); if (IS_ERR(hw)) goto err_free; @@ -120,7 +120,7 @@ static void __init at91sam9rl_pmc_setup(struct device_node *np) parent_names[2] = "pllack"; parent_names[3] = "utmick"; hw = at91_clk_register_master_pres(regmap, "masterck_pres", 4, - parent_names, + parent_names, NULL, &at91rm9200_master_layout, &sam9rl_mck_characteristics, &sam9rl_mck_lock); @@ -128,7 +128,7 @@ static void __init at91sam9rl_pmc_setup(struct device_node *np) goto err_free; hw = at91_clk_register_master_div(regmap, "masterck_div", - "masterck_pres", + "masterck_pres", NULL, &at91rm9200_master_layout, &sam9rl_mck_characteristics, &sam9rl_mck_lock, CLK_SET_RATE_GATE, 0); @@ -148,7 +148,7 @@ static void __init at91sam9rl_pmc_setup(struct device_node *np) snprintf(name, sizeof(name), "prog%d", i); hw = at91_clk_register_programmable(regmap, name, - parent_names, 5, i, + parent_names, NULL, 5, i, &at91rm9200_programmable_layout, NULL); if (IS_ERR(hw)) @@ -159,7 +159,7 @@ static void __init at91sam9rl_pmc_setup(struct device_node *np) for (i = 0; i < ARRAY_SIZE(at91sam9rl_systemck); i++) { hw = at91_clk_register_system(regmap, at91sam9rl_systemck[i].n, - at91sam9rl_systemck[i].p, + at91sam9rl_systemck[i].p, NULL, at91sam9rl_systemck[i].id, 0); if (IS_ERR(hw)) goto err_free; @@ -170,7 +170,7 @@ static void __init at91sam9rl_pmc_setup(struct device_node *np) for (i = 0; i < ARRAY_SIZE(at91sam9rl_periphck); i++) { hw = at91_clk_register_peripheral(regmap, at91sam9rl_periphck[i].n, - "masterck_div", + "masterck_div", NULL, at91sam9rl_periphck[i].id); if (IS_ERR(hw)) goto err_free; diff --git a/drivers/clk/at91/at91sam9x5.c b/drivers/clk/at91/at91sam9x5.c index 13e589c9590704474b41e95a8d3a611e97e3aebc..3b801d12fac0d1c511b85abab8044d9dd974f0fb 100644 --- a/drivers/clk/at91/at91sam9x5.c +++ b/drivers/clk/at91/at91sam9x5.c @@ -169,14 +169,14 @@ static void __init at91sam9x5_pmc_setup(struct device_node *np, bypass = of_property_read_bool(np, "atmel,osc-bypass"); - hw = at91_clk_register_main_osc(regmap, "main_osc", mainxtal_name, + hw = at91_clk_register_main_osc(regmap, "main_osc", mainxtal_name, NULL, bypass); if (IS_ERR(hw)) goto err_free; parent_names[0] = "main_rc_osc"; parent_names[1] = "main_osc"; - hw = at91_clk_register_sam9x5_main(regmap, "mainck", parent_names, 2); + hw = at91_clk_register_sam9x5_main(regmap, "mainck", parent_names, NULL, 2); if (IS_ERR(hw)) goto err_free; @@ -193,7 +193,7 @@ static void __init at91sam9x5_pmc_setup(struct device_node *np, at91sam9x5_pmc->chws[PMC_PLLACK] = hw; - hw = at91_clk_register_utmi(regmap, NULL, "utmick", "mainck"); + hw = at91_clk_register_utmi(regmap, NULL, "utmick", "mainck", NULL); if (IS_ERR(hw)) goto err_free; @@ -204,14 +204,14 @@ static void __init at91sam9x5_pmc_setup(struct device_node *np, parent_names[2] = "plladivck"; parent_names[3] = "utmick"; hw = at91_clk_register_master_pres(regmap, "masterck_pres", 4, - parent_names, + parent_names, NULL, &at91sam9x5_master_layout, &mck_characteristics, &mck_lock); if (IS_ERR(hw)) goto err_free; hw = at91_clk_register_master_div(regmap, "masterck_div", - "masterck_pres", + "masterck_pres", NULL, &at91sam9x5_master_layout, &mck_characteristics, &mck_lock, CLK_SET_RATE_GATE, 0); @@ -241,7 +241,7 @@ static void __init at91sam9x5_pmc_setup(struct device_node *np, snprintf(name, sizeof(name), "prog%d", i); hw = at91_clk_register_programmable(regmap, name, - parent_names, 5, i, + parent_names, NULL, 5, i, &at91sam9x5_programmable_layout, NULL); if (IS_ERR(hw)) @@ -252,7 +252,7 @@ static void __init at91sam9x5_pmc_setup(struct device_node *np, for (i = 0; i < ARRAY_SIZE(at91sam9x5_systemck); i++) { hw = at91_clk_register_system(regmap, at91sam9x5_systemck[i].n, - at91sam9x5_systemck[i].p, + at91sam9x5_systemck[i].p, NULL, at91sam9x5_systemck[i].id, at91sam9x5_systemck[i].flags); if (IS_ERR(hw)) @@ -263,7 +263,7 @@ static void __init at91sam9x5_pmc_setup(struct device_node *np, if (has_lcdck) { hw = at91_clk_register_system(regmap, "lcdck", "masterck_div", - 3, 0); + NULL, 3, 0); if (IS_ERR(hw)) goto err_free; @@ -274,7 +274,7 @@ static void __init at91sam9x5_pmc_setup(struct device_node *np, hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock, &at91sam9x5_pcr_layout, at91sam9x5_periphck[i].n, - "masterck_div", + "masterck_div", NULL, at91sam9x5_periphck[i].id, &range, INT_MIN, 0); if (IS_ERR(hw)) @@ -287,7 +287,7 @@ static void __init at91sam9x5_pmc_setup(struct device_node *np, hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock, &at91sam9x5_pcr_layout, extra_pcks[i].n, - "masterck_div", + "masterck_div", NULL, extra_pcks[i].id, &range, INT_MIN, 0); if (IS_ERR(hw)) diff --git a/drivers/clk/at91/clk-generated.c b/drivers/clk/at91/clk-generated.c index 943ea67bf135fb486d96feae259b32ee45f7743e..4b4edeecc88971531d05c8338d005b7a66a9600e 100644 --- a/drivers/clk/at91/clk-generated.c +++ b/drivers/clk/at91/clk-generated.c @@ -319,22 +319,29 @@ struct clk_hw * __init at91_clk_register_generated(struct regmap *regmap, spinlock_t *lock, const struct clk_pcr_layout *layout, const char *name, const char **parent_names, + struct clk_hw **parent_hws, u32 *mux_table, u8 num_parents, u8 id, const struct clk_range *range, int chg_pid) { struct clk_generated *gck; - struct clk_init_data init; + struct clk_init_data init = {}; struct clk_hw *hw; int ret; + if (!(parent_names || parent_hws)) + return ERR_PTR(-ENOMEM); + gck = kzalloc(sizeof(*gck), GFP_KERNEL); if (!gck) return ERR_PTR(-ENOMEM); init.name = name; init.ops = &generated_ops; - init.parent_names = parent_names; + if (parent_hws) + init.parent_hws = (const struct clk_hw **)parent_hws; + else + init.parent_names = parent_names; init.num_parents = num_parents; init.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE; if (chg_pid >= 0) diff --git a/drivers/clk/at91/clk-main.c b/drivers/clk/at91/clk-main.c index 8601b27c1ae051d2c68786dd91eda594795e0416..9b462becc693e05e5ac6ec9b3d79fae46d7149cb 100644 --- a/drivers/clk/at91/clk-main.c +++ b/drivers/clk/at91/clk-main.c @@ -152,14 +152,15 @@ struct clk_hw * __init at91_clk_register_main_osc(struct regmap *regmap, const char *name, const char *parent_name, + struct clk_parent_data *parent_data, bool bypass) { struct clk_main_osc *osc; - struct clk_init_data init; + struct clk_init_data init = {}; struct clk_hw *hw; int ret; - if (!name || !parent_name) + if (!name || !(parent_name || parent_data)) return ERR_PTR(-EINVAL); osc = kzalloc(sizeof(*osc), GFP_KERNEL); @@ -168,7 +169,10 @@ at91_clk_register_main_osc(struct regmap *regmap, init.name = name; init.ops = &main_osc_ops; - init.parent_names = &parent_name; + if (parent_data) + init.parent_data = (const struct clk_parent_data *)parent_data; + else + init.parent_names = &parent_name; init.num_parents = 1; init.flags = CLK_IGNORE_UNUSED; @@ -397,17 +401,18 @@ static const struct clk_ops rm9200_main_ops = { struct clk_hw * __init at91_clk_register_rm9200_main(struct regmap *regmap, const char *name, - const char *parent_name) + const char *parent_name, + struct clk_hw *parent_hw) { struct clk_rm9200_main *clkmain; - struct clk_init_data init; + struct clk_init_data init = {}; struct clk_hw *hw; int ret; if (!name) return ERR_PTR(-EINVAL); - if (!parent_name) + if (!(parent_name || parent_hw)) return ERR_PTR(-EINVAL); clkmain = kzalloc(sizeof(*clkmain), GFP_KERNEL); @@ -416,7 +421,10 @@ at91_clk_register_rm9200_main(struct regmap *regmap, init.name = name; init.ops = &rm9200_main_ops; - init.parent_names = &parent_name; + if (parent_hw) + init.parent_hws = (const struct clk_hw **)&parent_hw; + else + init.parent_names = &parent_name; init.num_parents = 1; init.flags = 0; @@ -533,6 +541,7 @@ static const struct clk_ops sam9x5_main_ops = { .prepare = clk_sam9x5_main_prepare, .is_prepared = clk_sam9x5_main_is_prepared, .recalc_rate = clk_sam9x5_main_recalc_rate, + .determine_rate = clk_hw_determine_rate_no_reparent, .set_parent = clk_sam9x5_main_set_parent, .get_parent = clk_sam9x5_main_get_parent, .save_context = clk_sam9x5_main_save_context, @@ -543,10 +552,11 @@ struct clk_hw * __init at91_clk_register_sam9x5_main(struct regmap *regmap, const char *name, const char **parent_names, + struct clk_hw **parent_hws, int num_parents) { struct clk_sam9x5_main *clkmain; - struct clk_init_data init; + struct clk_init_data init = {}; unsigned int status; struct clk_hw *hw; int ret; @@ -554,7 +564,7 @@ at91_clk_register_sam9x5_main(struct regmap *regmap, if (!name) return ERR_PTR(-EINVAL); - if (!parent_names || !num_parents) + if (!(parent_hws || parent_names) || !num_parents) return ERR_PTR(-EINVAL); clkmain = kzalloc(sizeof(*clkmain), GFP_KERNEL); @@ -563,7 +573,10 @@ at91_clk_register_sam9x5_main(struct regmap *regmap, init.name = name; init.ops = &sam9x5_main_ops; - init.parent_names = parent_names; + if (parent_hws) + init.parent_hws = (const struct clk_hw **)parent_hws; + else + init.parent_names = parent_names; init.num_parents = num_parents; init.flags = CLK_SET_PARENT_GATE; diff --git a/drivers/clk/at91/clk-master.c b/drivers/clk/at91/clk-master.c index b7cd1924de52a924e3f58efaba6b0a2ab629374f..15c46489ba85015db157e34b83aa071d153068fa 100644 --- a/drivers/clk/at91/clk-master.c +++ b/drivers/clk/at91/clk-master.c @@ -473,18 +473,19 @@ static struct clk_hw * __init at91_clk_register_master_internal(struct regmap *regmap, const char *name, int num_parents, const char **parent_names, + struct clk_hw **parent_hws, const struct clk_master_layout *layout, const struct clk_master_characteristics *characteristics, const struct clk_ops *ops, spinlock_t *lock, u32 flags) { struct clk_master *master; - struct clk_init_data init; + struct clk_init_data init = {}; struct clk_hw *hw; unsigned int mckr; unsigned long irqflags; int ret; - if (!name || !num_parents || !parent_names || !lock) + if (!name || !num_parents || !(parent_names || parent_hws) || !lock) return ERR_PTR(-EINVAL); master = kzalloc(sizeof(*master), GFP_KERNEL); @@ -493,7 +494,10 @@ at91_clk_register_master_internal(struct regmap *regmap, init.name = name; init.ops = ops; - init.parent_names = parent_names; + if (parent_hws) + init.parent_hws = (const struct clk_hw **)parent_hws; + else + init.parent_names = parent_names; init.num_parents = num_parents; init.flags = flags; @@ -527,12 +531,13 @@ struct clk_hw * __init at91_clk_register_master_pres(struct regmap *regmap, const char *name, int num_parents, const char **parent_names, + struct clk_hw **parent_hws, const struct clk_master_layout *layout, const struct clk_master_characteristics *characteristics, spinlock_t *lock) { return at91_clk_register_master_internal(regmap, name, num_parents, - parent_names, layout, + parent_names, parent_hws, layout, characteristics, &master_pres_ops, lock, CLK_SET_RATE_GATE); @@ -541,7 +546,7 @@ at91_clk_register_master_pres(struct regmap *regmap, struct clk_hw * __init at91_clk_register_master_div(struct regmap *regmap, const char *name, const char *parent_name, - const struct clk_master_layout *layout, + struct clk_hw *parent_hw, const struct clk_master_layout *layout, const struct clk_master_characteristics *characteristics, spinlock_t *lock, u32 flags, u32 safe_div) { @@ -554,7 +559,8 @@ at91_clk_register_master_div(struct regmap *regmap, ops = &master_div_ops_chg; hw = at91_clk_register_master_internal(regmap, name, 1, - &parent_name, layout, + parent_name ? &parent_name : NULL, + parent_hw ? &parent_hw : NULL, layout, characteristics, ops, lock, flags); @@ -806,18 +812,19 @@ struct clk_hw * __init at91_clk_sama7g5_register_master(struct regmap *regmap, const char *name, int num_parents, const char **parent_names, + struct clk_hw **parent_hws, u32 *mux_table, spinlock_t *lock, u8 id, bool critical, int chg_pid) { struct clk_master *master; struct clk_hw *hw; - struct clk_init_data init; + struct clk_init_data init = {}; unsigned long flags; unsigned int val; int ret; - if (!name || !num_parents || !parent_names || !mux_table || + if (!name || !num_parents || !(parent_names || parent_hws) || !mux_table || !lock || id > MASTER_MAX_ID) return ERR_PTR(-EINVAL); @@ -827,7 +834,10 @@ at91_clk_sama7g5_register_master(struct regmap *regmap, init.name = name; init.ops = &sama7g5_master_ops; - init.parent_names = parent_names; + if (parent_hws) + init.parent_hws = (const struct clk_hw **)parent_hws; + else + init.parent_names = parent_names; init.num_parents = num_parents; init.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE; if (chg_pid >= 0) diff --git a/drivers/clk/at91/clk-peripheral.c b/drivers/clk/at91/clk-peripheral.c index 93ea685e27f679dd4067579236c0c8660ee34e68..c173a44c800aa8cc6970c266995f4a60b0a38554 100644 --- a/drivers/clk/at91/clk-peripheral.c +++ b/drivers/clk/at91/clk-peripheral.c @@ -97,14 +97,15 @@ static const struct clk_ops peripheral_ops = { struct clk_hw * __init at91_clk_register_peripheral(struct regmap *regmap, const char *name, - const char *parent_name, u32 id) + const char *parent_name, struct clk_hw *parent_hw, + u32 id) { struct clk_peripheral *periph; - struct clk_init_data init; + struct clk_init_data init = {}; struct clk_hw *hw; int ret; - if (!name || !parent_name || id > PERIPHERAL_ID_MAX) + if (!name || !(parent_name || parent_hw) || id > PERIPHERAL_ID_MAX) return ERR_PTR(-EINVAL); periph = kzalloc(sizeof(*periph), GFP_KERNEL); @@ -113,7 +114,10 @@ at91_clk_register_peripheral(struct regmap *regmap, const char *name, init.name = name; init.ops = &peripheral_ops; - init.parent_names = &parent_name; + if (parent_hw) + init.parent_hws = (const struct clk_hw **)&parent_hw; + else + init.parent_names = &parent_name; init.num_parents = 1; init.flags = 0; @@ -444,15 +448,16 @@ struct clk_hw * __init at91_clk_register_sam9x5_peripheral(struct regmap *regmap, spinlock_t *lock, const struct clk_pcr_layout *layout, const char *name, const char *parent_name, + struct clk_hw *parent_hw, u32 id, const struct clk_range *range, int chg_pid, unsigned long flags) { struct clk_sam9x5_peripheral *periph; - struct clk_init_data init; + struct clk_init_data init = {}; struct clk_hw *hw; int ret; - if (!name || !parent_name) + if (!name || !(parent_name || parent_hw)) return ERR_PTR(-EINVAL); periph = kzalloc(sizeof(*periph), GFP_KERNEL); @@ -460,7 +465,10 @@ at91_clk_register_sam9x5_peripheral(struct regmap *regmap, spinlock_t *lock, return ERR_PTR(-ENOMEM); init.name = name; - init.parent_names = &parent_name; + if (parent_hw) + init.parent_hws = (const struct clk_hw **)&parent_hw; + else + init.parent_names = &parent_name; init.num_parents = 1; init.flags = flags; if (chg_pid < 0) { diff --git a/drivers/clk/at91/clk-programmable.c b/drivers/clk/at91/clk-programmable.c index 6c4b259d31d397d915a077a14af6037cca5bd7f8..1195fb405503d1c8cf2e0b68cbd2ad96ee7fb8ea 100644 --- a/drivers/clk/at91/clk-programmable.c +++ b/drivers/clk/at91/clk-programmable.c @@ -215,16 +215,16 @@ static const struct clk_ops programmable_ops = { struct clk_hw * __init at91_clk_register_programmable(struct regmap *regmap, const char *name, const char **parent_names, - u8 num_parents, u8 id, + struct clk_hw **parent_hws, u8 num_parents, u8 id, const struct clk_programmable_layout *layout, u32 *mux_table) { struct clk_programmable *prog; struct clk_hw *hw; - struct clk_init_data init; + struct clk_init_data init = {}; int ret; - if (id > PROG_ID_MAX) + if (id > PROG_ID_MAX || !(parent_names || parent_hws)) return ERR_PTR(-EINVAL); prog = kzalloc(sizeof(*prog), GFP_KERNEL); @@ -233,7 +233,10 @@ at91_clk_register_programmable(struct regmap *regmap, init.name = name; init.ops = &programmable_ops; - init.parent_names = parent_names; + if (parent_hws) + init.parent_hws = (const struct clk_hw **)parent_hws; + else + init.parent_names = parent_names; init.num_parents = num_parents; init.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE; diff --git a/drivers/clk/at91/clk-sam9x60-pll.c b/drivers/clk/at91/clk-sam9x60-pll.c index 0882ed01d5c27fd1a693ff5a197584fc5009736e..ff65f7b916f077f1e2c87d7677beeb722a14f25c 100644 --- a/drivers/clk/at91/clk-sam9x60-pll.c +++ b/drivers/clk/at91/clk-sam9x60-pll.c @@ -616,7 +616,7 @@ sam9x60_clk_register_frac_pll(struct regmap *regmap, spinlock_t *lock, { struct sam9x60_frac *frac; struct clk_hw *hw; - struct clk_init_data init; + struct clk_init_data init = {}; unsigned long parent_rate, irqflags; unsigned int val; int ret; @@ -629,7 +629,10 @@ sam9x60_clk_register_frac_pll(struct regmap *regmap, spinlock_t *lock, return ERR_PTR(-ENOMEM); init.name = name; - init.parent_names = &parent_name; + if (parent_name) + init.parent_names = &parent_name; + else + init.parent_hws = (const struct clk_hw **)&parent_hw; init.num_parents = 1; if (flags & CLK_SET_RATE_GATE) init.ops = &sam9x60_frac_pll_ops; @@ -692,14 +695,15 @@ sam9x60_clk_register_frac_pll(struct regmap *regmap, spinlock_t *lock, struct clk_hw * __init sam9x60_clk_register_div_pll(struct regmap *regmap, spinlock_t *lock, - const char *name, const char *parent_name, u8 id, + const char *name, const char *parent_name, + struct clk_hw *parent_hw, u8 id, const struct clk_pll_characteristics *characteristics, const struct clk_pll_layout *layout, u32 flags, u32 safe_div) { struct sam9x60_div *div; struct clk_hw *hw; - struct clk_init_data init; + struct clk_init_data init = {}; unsigned long irqflags; unsigned int val; int ret; @@ -716,7 +720,10 @@ sam9x60_clk_register_div_pll(struct regmap *regmap, spinlock_t *lock, return ERR_PTR(-ENOMEM); init.name = name; - init.parent_names = &parent_name; + if (parent_hw) + init.parent_hws = (const struct clk_hw **)&parent_hw; + else + init.parent_names = &parent_name; init.num_parents = 1; if (flags & CLK_SET_RATE_GATE) init.ops = &sam9x60_div_pll_ops; diff --git a/drivers/clk/at91/clk-smd.c b/drivers/clk/at91/clk-smd.c index 160378438f1b4d4291b1f654134853f359299088..09c649c8598e2feb415a8e4106efc834f27e0689 100644 --- a/drivers/clk/at91/clk-smd.c +++ b/drivers/clk/at91/clk-smd.c @@ -36,26 +36,31 @@ static unsigned long at91sam9x5_clk_smd_recalc_rate(struct clk_hw *hw, return parent_rate / (smddiv + 1); } -static long at91sam9x5_clk_smd_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *parent_rate) +static int at91sam9x5_clk_smd_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) { unsigned long div; unsigned long bestrate; unsigned long tmp; - if (rate >= *parent_rate) - return *parent_rate; + if (req->rate >= req->best_parent_rate) { + req->rate = req->best_parent_rate; + return 0; + } - div = *parent_rate / rate; - if (div > SMD_MAX_DIV) - return *parent_rate / (SMD_MAX_DIV + 1); + div = req->best_parent_rate / req->rate; + if (div > SMD_MAX_DIV) { + req->rate = req->best_parent_rate / (SMD_MAX_DIV + 1); + return 0; + } - bestrate = *parent_rate / div; - tmp = *parent_rate / (div + 1); - if (bestrate - rate > rate - tmp) + bestrate = req->best_parent_rate / div; + tmp = req->best_parent_rate / (div + 1); + if (bestrate - req->rate > req->rate - tmp) bestrate = tmp; - return bestrate; + req->rate = bestrate; + return 0; } static int at91sam9x5_clk_smd_set_parent(struct clk_hw *hw, u8 index) @@ -98,7 +103,7 @@ static int at91sam9x5_clk_smd_set_rate(struct clk_hw *hw, unsigned long rate, static const struct clk_ops at91sam9x5_smd_ops = { .recalc_rate = at91sam9x5_clk_smd_recalc_rate, - .round_rate = at91sam9x5_clk_smd_round_rate, + .determine_rate = at91sam9x5_clk_smd_determine_rate, .get_parent = at91sam9x5_clk_smd_get_parent, .set_parent = at91sam9x5_clk_smd_set_parent, .set_rate = at91sam9x5_clk_smd_set_rate, diff --git a/drivers/clk/at91/clk-system.c b/drivers/clk/at91/clk-system.c index 10193650429eb6d908cc850b31ffcefb123f5718..90eed39d07856574798cc4a56874dd61404716b4 100644 --- a/drivers/clk/at91/clk-system.c +++ b/drivers/clk/at91/clk-system.c @@ -105,14 +105,15 @@ static const struct clk_ops system_ops = { struct clk_hw * __init at91_clk_register_system(struct regmap *regmap, const char *name, - const char *parent_name, u8 id, unsigned long flags) + const char *parent_name, struct clk_hw *parent_hw, u8 id, + unsigned long flags) { struct clk_system *sys; struct clk_hw *hw; - struct clk_init_data init; + struct clk_init_data init = {}; int ret; - if (!parent_name || id > SYSTEM_MAX_ID) + if (!(parent_name || parent_hw) || id > SYSTEM_MAX_ID) return ERR_PTR(-EINVAL); sys = kzalloc(sizeof(*sys), GFP_KERNEL); @@ -121,7 +122,10 @@ at91_clk_register_system(struct regmap *regmap, const char *name, init.name = name; init.ops = &system_ops; - init.parent_names = &parent_name; + if (parent_hw) + init.parent_hws = (const struct clk_hw **)&parent_hw; + else + init.parent_names = &parent_name; init.num_parents = 1; init.flags = CLK_SET_RATE_PARENT | flags; diff --git a/drivers/clk/at91/clk-utmi.c b/drivers/clk/at91/clk-utmi.c index a22c10d9a1b964e4fbeb883a3a5d02e85f250c16..40c84f5af5e8a6dda739f1d356b74e94c575fe78 100644 --- a/drivers/clk/at91/clk-utmi.c +++ b/drivers/clk/at91/clk-utmi.c @@ -144,21 +144,30 @@ static struct clk_hw * __init at91_clk_register_utmi_internal(struct regmap *regmap_pmc, struct regmap *regmap_sfr, const char *name, const char *parent_name, + struct clk_hw *parent_hw, const struct clk_ops *ops, unsigned long flags) { struct clk_utmi *utmi; struct clk_hw *hw; - struct clk_init_data init; + struct clk_init_data init = {}; int ret; + if (!(parent_name || parent_hw)) + return ERR_PTR(-EINVAL); + utmi = kzalloc(sizeof(*utmi), GFP_KERNEL); if (!utmi) return ERR_PTR(-ENOMEM); init.name = name; init.ops = ops; - init.parent_names = parent_name ? &parent_name : NULL; - init.num_parents = parent_name ? 1 : 0; + if (parent_hw) { + init.parent_hws = parent_hw ? (const struct clk_hw **)&parent_hw : NULL; + init.num_parents = parent_hw ? 1 : 0; + } else { + init.parent_names = parent_name ? &parent_name : NULL; + init.num_parents = parent_name ? 1 : 0; + } init.flags = flags; utmi->hw.init = &init; @@ -177,10 +186,11 @@ at91_clk_register_utmi_internal(struct regmap *regmap_pmc, struct clk_hw * __init at91_clk_register_utmi(struct regmap *regmap_pmc, struct regmap *regmap_sfr, - const char *name, const char *parent_name) + const char *name, const char *parent_name, + struct clk_hw *parent_hw) { return at91_clk_register_utmi_internal(regmap_pmc, regmap_sfr, name, - parent_name, &utmi_ops, CLK_SET_RATE_GATE); + parent_name, parent_hw, &utmi_ops, CLK_SET_RATE_GATE); } static int clk_utmi_sama7g5_prepare(struct clk_hw *hw) @@ -279,8 +289,8 @@ static const struct clk_ops sama7g5_utmi_ops = { struct clk_hw * __init at91_clk_sama7g5_register_utmi(struct regmap *regmap_pmc, const char *name, - const char *parent_name) + const char *parent_name, struct clk_hw *parent_hw) { return at91_clk_register_utmi_internal(regmap_pmc, NULL, name, - parent_name, &sama7g5_utmi_ops, 0); + parent_name, parent_hw, &sama7g5_utmi_ops, 0); } diff --git a/drivers/clk/at91/dt-compat.c b/drivers/clk/at91/dt-compat.c index 97f67e23ef80b363b9108e2f4fb4fdd4879b31fc..a32dc2111b900e3aa12efbbdfa79ab2308f0fe75 100644 --- a/drivers/clk/at91/dt-compat.c +++ b/drivers/clk/at91/dt-compat.c @@ -171,7 +171,7 @@ static void __init of_sama5d2_clk_generated_setup(struct device_node *np) hw = at91_clk_register_generated(regmap, &pmc_pcr_lock, &dt_pcr_layout, name, - parent_names, NULL, + parent_names, NULL, NULL, num_parents, id, &range, chg_pid); if (IS_ERR(hw)) @@ -269,7 +269,7 @@ static void __init of_at91rm9200_clk_main_osc_setup(struct device_node *np) if (IS_ERR(regmap)) return; - hw = at91_clk_register_main_osc(regmap, name, parent_name, bypass); + hw = at91_clk_register_main_osc(regmap, name, parent_name, NULL, bypass); if (IS_ERR(hw)) return; @@ -323,7 +323,7 @@ static void __init of_at91rm9200_clk_main_setup(struct device_node *np) if (IS_ERR(regmap)) return; - hw = at91_clk_register_rm9200_main(regmap, name, parent_name); + hw = at91_clk_register_rm9200_main(regmap, name, parent_name, NULL); if (IS_ERR(hw)) return; @@ -354,7 +354,7 @@ static void __init of_at91sam9x5_clk_main_setup(struct device_node *np) of_property_read_string(np, "clock-output-names", &name); - hw = at91_clk_register_sam9x5_main(regmap, name, parent_names, + hw = at91_clk_register_sam9x5_main(regmap, name, parent_names, NULL, num_parents); if (IS_ERR(hw)) return; @@ -420,12 +420,12 @@ of_at91_clk_master_setup(struct device_node *np, return; hw = at91_clk_register_master_pres(regmap, "masterck_pres", num_parents, - parent_names, layout, + parent_names, NULL, layout, characteristics, &mck_lock); if (IS_ERR(hw)) goto out_free_characteristics; - hw = at91_clk_register_master_div(regmap, name, "masterck_pres", + hw = at91_clk_register_master_div(regmap, name, "masterck_pres", NULL, layout, characteristics, &mck_lock, CLK_SET_RATE_GATE, 0); if (IS_ERR(hw)) @@ -490,7 +490,7 @@ of_at91_clk_periph_setup(struct device_node *np, u8 type) if (type == PERIPHERAL_AT91RM9200) { hw = at91_clk_register_peripheral(regmap, name, - parent_name, id); + parent_name, NULL, id); } else { struct clk_range range = CLK_RANGE(0, 0); unsigned long flags = 0; @@ -512,6 +512,7 @@ of_at91_clk_periph_setup(struct device_node *np, u8 type) &dt_pcr_layout, name, parent_name, + NULL, id, &range, INT_MIN, flags); @@ -769,7 +770,7 @@ of_at91_clk_prog_setup(struct device_node *np, name = progclknp->name; hw = at91_clk_register_programmable(regmap, name, - parent_names, num_parents, + parent_names, NULL, num_parents, id, layout, mux_table); if (IS_ERR(hw)) continue; @@ -907,8 +908,8 @@ static void __init of_at91rm9200_clk_sys_setup(struct device_node *np) if (!strcmp(sysclknp->name, "ddrck")) flags = CLK_IS_CRITICAL; - hw = at91_clk_register_system(regmap, name, parent_name, id, - flags); + hw = at91_clk_register_system(regmap, name, parent_name, NULL, + id, flags); if (IS_ERR(hw)) continue; @@ -1054,7 +1055,7 @@ static void __init of_at91sam9x5_clk_utmi_setup(struct device_node *np) regmap_sfr = NULL; } - hw = at91_clk_register_utmi(regmap_pmc, regmap_sfr, name, parent_name); + hw = at91_clk_register_utmi(regmap_pmc, regmap_sfr, name, parent_name, NULL); if (IS_ERR(hw)) return; diff --git a/drivers/clk/at91/pmc.h b/drivers/clk/at91/pmc.h index 1b3ca7dd9b57dcb859096ea8125a6c4d260495e0..0f52e80bcd49a1afe249459efcee8b17d92895c7 100644 --- a/drivers/clk/at91/pmc.h +++ b/drivers/clk/at91/pmc.h @@ -144,7 +144,8 @@ struct clk_hw * __init at91_clk_register_generated(struct regmap *regmap, spinlock_t *lock, const struct clk_pcr_layout *layout, const char *name, const char **parent_names, - u32 *mux_table, u8 num_parents, u8 id, + struct clk_hw **parent_hws, u32 *mux_table, + u8 num_parents, u8 id, const struct clk_range *range, int chg_pid); struct clk_hw * __init @@ -161,25 +162,29 @@ at91_clk_register_main_rc_osc(struct regmap *regmap, const char *name, u32 frequency, u32 accuracy); struct clk_hw * __init at91_clk_register_main_osc(struct regmap *regmap, const char *name, - const char *parent_name, bool bypass); + const char *parent_name, + struct clk_parent_data *parent_data, bool bypass); struct clk_hw * __init at91_clk_register_rm9200_main(struct regmap *regmap, const char *name, - const char *parent_name); + const char *parent_name, + struct clk_hw *parent_hw); struct clk_hw * __init at91_clk_register_sam9x5_main(struct regmap *regmap, const char *name, - const char **parent_names, int num_parents); + const char **parent_names, + struct clk_hw **parent_hws, int num_parents); struct clk_hw * __init at91_clk_register_master_pres(struct regmap *regmap, const char *name, int num_parents, const char **parent_names, + struct clk_hw **parent_hws, const struct clk_master_layout *layout, const struct clk_master_characteristics *characteristics, spinlock_t *lock); struct clk_hw * __init at91_clk_register_master_div(struct regmap *regmap, const char *name, - const char *parent_names, + const char *parent_names, struct clk_hw *parent_hw, const struct clk_master_layout *layout, const struct clk_master_characteristics *characteristics, spinlock_t *lock, u32 flags, u32 safe_div); @@ -187,17 +192,20 @@ at91_clk_register_master_div(struct regmap *regmap, const char *name, struct clk_hw * __init at91_clk_sama7g5_register_master(struct regmap *regmap, const char *name, int num_parents, - const char **parent_names, u32 *mux_table, + const char **parent_names, + struct clk_hw **parent_hws, u32 *mux_table, spinlock_t *lock, u8 id, bool critical, int chg_pid); struct clk_hw * __init at91_clk_register_peripheral(struct regmap *regmap, const char *name, - const char *parent_name, u32 id); + const char *parent_name, struct clk_hw *parent_hw, + u32 id); struct clk_hw * __init at91_clk_register_sam9x5_peripheral(struct regmap *regmap, spinlock_t *lock, const struct clk_pcr_layout *layout, const char *name, const char *parent_name, + struct clk_hw *parent_hw, u32 id, const struct clk_range *range, int chg_pid, unsigned long flags); @@ -212,7 +220,8 @@ at91_clk_register_plldiv(struct regmap *regmap, const char *name, struct clk_hw * __init sam9x60_clk_register_div_pll(struct regmap *regmap, spinlock_t *lock, - const char *name, const char *parent_name, u8 id, + const char *name, const char *parent_name, + struct clk_hw *parent_hw, u8 id, const struct clk_pll_characteristics *characteristics, const struct clk_pll_layout *layout, u32 flags, u32 safe_div); @@ -226,7 +235,8 @@ sam9x60_clk_register_frac_pll(struct regmap *regmap, spinlock_t *lock, struct clk_hw * __init at91_clk_register_programmable(struct regmap *regmap, const char *name, - const char **parent_names, u8 num_parents, u8 id, + const char **parent_names, struct clk_hw **parent_hws, + u8 num_parents, u8 id, const struct clk_programmable_layout *layout, u32 *mux_table); @@ -242,7 +252,8 @@ at91sam9x5_clk_register_smd(struct regmap *regmap, const char *name, struct clk_hw * __init at91_clk_register_system(struct regmap *regmap, const char *name, - const char *parent_name, u8 id, unsigned long flags); + const char *parent_name, struct clk_hw *parent_hw, + u8 id, unsigned long flags); struct clk_hw * __init at91sam9x5_clk_register_usb(struct regmap *regmap, const char *name, @@ -259,10 +270,11 @@ at91rm9200_clk_register_usb(struct regmap *regmap, const char *name, struct clk_hw * __init at91_clk_register_utmi(struct regmap *regmap_pmc, struct regmap *regmap_sfr, - const char *name, const char *parent_name); + const char *name, const char *parent_name, + struct clk_hw *parent_hw); struct clk_hw * __init at91_clk_sama7g5_register_utmi(struct regmap *regmap, const char *name, - const char *parent_name); + const char *parent_name, struct clk_hw *parent_hw); #endif /* __PMC_H_ */ diff --git a/drivers/clk/at91/sam9x60.c b/drivers/clk/at91/sam9x60.c index ac070db58195e196cf02950a19ad48797d27d8f8..e309cbf3cb9a4d611aa5bce8d2fb73428d515da6 100644 --- a/drivers/clk/at91/sam9x60.c +++ b/drivers/clk/at91/sam9x60.c @@ -219,14 +219,14 @@ static void __init sam9x60_pmc_setup(struct device_node *np) if (IS_ERR(hw)) goto err_free; - hw = at91_clk_register_main_osc(regmap, "main_osc", mainxtal_name, 0); + hw = at91_clk_register_main_osc(regmap, "main_osc", mainxtal_name, NULL, 0); if (IS_ERR(hw)) goto err_free; main_osc_hw = hw; parent_names[0] = "main_rc_osc"; parent_names[1] = "main_osc"; - hw = at91_clk_register_sam9x5_main(regmap, "mainck", parent_names, 2); + hw = at91_clk_register_sam9x5_main(regmap, "mainck", parent_names, NULL, 2); if (IS_ERR(hw)) goto err_free; @@ -246,7 +246,7 @@ static void __init sam9x60_pmc_setup(struct device_node *np) goto err_free; hw = sam9x60_clk_register_div_pll(regmap, &pmc_pll_lock, "pllack_divck", - "pllack_fracck", 0, &plla_characteristics, + "pllack_fracck", NULL, 0, &plla_characteristics, &pll_div_layout, /* * This feeds CPU. It should not @@ -266,7 +266,7 @@ static void __init sam9x60_pmc_setup(struct device_node *np) goto err_free; hw = sam9x60_clk_register_div_pll(regmap, &pmc_pll_lock, "upllck_divck", - "upllck_fracck", 1, &upll_characteristics, + "upllck_fracck", NULL, 1, &upll_characteristics, &pll_div_layout, CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE | @@ -280,13 +280,13 @@ static void __init sam9x60_pmc_setup(struct device_node *np) parent_names[1] = "mainck"; parent_names[2] = "pllack_divck"; hw = at91_clk_register_master_pres(regmap, "masterck_pres", 3, - parent_names, &sam9x60_master_layout, + parent_names, NULL, &sam9x60_master_layout, &mck_characteristics, &mck_lock); if (IS_ERR(hw)) goto err_free; hw = at91_clk_register_master_div(regmap, "masterck_div", - "masterck_pres", &sam9x60_master_layout, + "masterck_pres", NULL, &sam9x60_master_layout, &mck_characteristics, &mck_lock, CLK_SET_RATE_GATE, 0); if (IS_ERR(hw)) @@ -313,7 +313,7 @@ static void __init sam9x60_pmc_setup(struct device_node *np) snprintf(name, sizeof(name), "prog%d", i); hw = at91_clk_register_programmable(regmap, name, - parent_names, 6, i, + parent_names, NULL, 6, i, &sam9x60_programmable_layout, NULL); if (IS_ERR(hw)) @@ -324,7 +324,7 @@ static void __init sam9x60_pmc_setup(struct device_node *np) for (i = 0; i < ARRAY_SIZE(sam9x60_systemck); i++) { hw = at91_clk_register_system(regmap, sam9x60_systemck[i].n, - sam9x60_systemck[i].p, + sam9x60_systemck[i].p, NULL, sam9x60_systemck[i].id, sam9x60_systemck[i].flags); if (IS_ERR(hw)) @@ -337,7 +337,7 @@ static void __init sam9x60_pmc_setup(struct device_node *np) hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock, &sam9x60_pcr_layout, sam9x60_periphck[i].n, - "masterck_div", + "masterck_div", NULL, sam9x60_periphck[i].id, &range, INT_MIN, sam9x60_periphck[i].flags); @@ -351,7 +351,7 @@ static void __init sam9x60_pmc_setup(struct device_node *np) hw = at91_clk_register_generated(regmap, &pmc_pcr_lock, &sam9x60_pcr_layout, sam9x60_gck[i].n, - parent_names, NULL, 6, + parent_names, NULL, NULL, 6, sam9x60_gck[i].id, &sam9x60_gck[i].r, INT_MIN); if (IS_ERR(hw)) diff --git a/drivers/clk/at91/sama5d2.c b/drivers/clk/at91/sama5d2.c index c0e3e1a4bbf3d7dd50ea0659330259c9fe4a4136..c16594fce90c91c1ef46f614ac72aaa08e91db44 100644 --- a/drivers/clk/at91/sama5d2.c +++ b/drivers/clk/at91/sama5d2.c @@ -202,14 +202,14 @@ static void __init sama5d2_pmc_setup(struct device_node *np) bypass = of_property_read_bool(np, "atmel,osc-bypass"); - hw = at91_clk_register_main_osc(regmap, "main_osc", mainxtal_name, + hw = at91_clk_register_main_osc(regmap, "main_osc", mainxtal_name, NULL, bypass); if (IS_ERR(hw)) goto err_free; parent_names[0] = "main_rc_osc"; parent_names[1] = "main_osc"; - hw = at91_clk_register_sam9x5_main(regmap, "mainck", parent_names, 2); + hw = at91_clk_register_sam9x5_main(regmap, "mainck", parent_names, NULL, 2); if (IS_ERR(hw)) goto err_free; @@ -249,7 +249,7 @@ static void __init sama5d2_pmc_setup(struct device_node *np) if (IS_ERR(regmap_sfr)) regmap_sfr = NULL; - hw = at91_clk_register_utmi(regmap, regmap_sfr, "utmick", "mainck"); + hw = at91_clk_register_utmi(regmap, regmap_sfr, "utmick", "mainck", NULL); if (IS_ERR(hw)) goto err_free; @@ -260,14 +260,14 @@ static void __init sama5d2_pmc_setup(struct device_node *np) parent_names[2] = "plladivck"; parent_names[3] = "utmick"; hw = at91_clk_register_master_pres(regmap, "masterck_pres", 4, - parent_names, + parent_names, NULL, &at91sam9x5_master_layout, &mck_characteristics, &mck_lock); if (IS_ERR(hw)) goto err_free; hw = at91_clk_register_master_div(regmap, "masterck_div", - "masterck_pres", + "masterck_pres", NULL, &at91sam9x5_master_layout, &mck_characteristics, &mck_lock, CLK_SET_RATE_GATE, 0); @@ -300,7 +300,7 @@ static void __init sama5d2_pmc_setup(struct device_node *np) snprintf(name, sizeof(name), "prog%d", i); hw = at91_clk_register_programmable(regmap, name, - parent_names, 6, i, + parent_names, NULL, 6, i, &sama5d2_programmable_layout, NULL); if (IS_ERR(hw)) @@ -311,7 +311,7 @@ static void __init sama5d2_pmc_setup(struct device_node *np) for (i = 0; i < ARRAY_SIZE(sama5d2_systemck); i++) { hw = at91_clk_register_system(regmap, sama5d2_systemck[i].n, - sama5d2_systemck[i].p, + sama5d2_systemck[i].p, NULL, sama5d2_systemck[i].id, sama5d2_systemck[i].flags); if (IS_ERR(hw)) @@ -324,7 +324,7 @@ static void __init sama5d2_pmc_setup(struct device_node *np) hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock, &sama5d2_pcr_layout, sama5d2_periphck[i].n, - "masterck_div", + "masterck_div", NULL, sama5d2_periphck[i].id, &range, INT_MIN, sama5d2_periphck[i].flags); @@ -338,7 +338,7 @@ static void __init sama5d2_pmc_setup(struct device_node *np) hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock, &sama5d2_pcr_layout, sama5d2_periph32ck[i].n, - "h32mxck", + "h32mxck", NULL, sama5d2_periph32ck[i].id, &sama5d2_periph32ck[i].r, INT_MIN, 0); @@ -358,7 +358,7 @@ static void __init sama5d2_pmc_setup(struct device_node *np) hw = at91_clk_register_generated(regmap, &pmc_pcr_lock, &sama5d2_pcr_layout, sama5d2_gck[i].n, - parent_names, NULL, 6, + parent_names, NULL, NULL, 6, sama5d2_gck[i].id, &sama5d2_gck[i].r, sama5d2_gck[i].chg_pid); diff --git a/drivers/clk/at91/sama5d3.c b/drivers/clk/at91/sama5d3.c index ad6068b884de430c9145bb614f6a1a343ede4c3d..522ce6031446411b8dec4ac463db5ac152963e1c 100644 --- a/drivers/clk/at91/sama5d3.c +++ b/drivers/clk/at91/sama5d3.c @@ -150,14 +150,14 @@ static void __init sama5d3_pmc_setup(struct device_node *np) bypass = of_property_read_bool(np, "atmel,osc-bypass"); - hw = at91_clk_register_main_osc(regmap, "main_osc", mainxtal_name, + hw = at91_clk_register_main_osc(regmap, "main_osc", mainxtal_name, NULL, bypass); if (IS_ERR(hw)) goto err_free; parent_names[0] = "main_rc_osc"; parent_names[1] = "main_osc"; - hw = at91_clk_register_sam9x5_main(regmap, "mainck", parent_names, 2); + hw = at91_clk_register_sam9x5_main(regmap, "mainck", parent_names, NULL, 2); if (IS_ERR(hw)) goto err_free; @@ -172,7 +172,7 @@ static void __init sama5d3_pmc_setup(struct device_node *np) sama5d3_pmc->chws[PMC_PLLACK] = hw; - hw = at91_clk_register_utmi(regmap, NULL, "utmick", "mainck"); + hw = at91_clk_register_utmi(regmap, NULL, "utmick", "mainck", NULL); if (IS_ERR(hw)) goto err_free; @@ -183,14 +183,14 @@ static void __init sama5d3_pmc_setup(struct device_node *np) parent_names[2] = "plladivck"; parent_names[3] = "utmick"; hw = at91_clk_register_master_pres(regmap, "masterck_pres", 4, - parent_names, + parent_names, NULL, &at91sam9x5_master_layout, &mck_characteristics, &mck_lock); if (IS_ERR(hw)) goto err_free; hw = at91_clk_register_master_div(regmap, "masterck_div", - "masterck_pres", + "masterck_pres", NULL, &at91sam9x5_master_layout, &mck_characteristics, &mck_lock, CLK_SET_RATE_GATE, 0); @@ -220,7 +220,7 @@ static void __init sama5d3_pmc_setup(struct device_node *np) snprintf(name, sizeof(name), "prog%d", i); hw = at91_clk_register_programmable(regmap, name, - parent_names, 5, i, + parent_names, NULL, 5, i, &at91sam9x5_programmable_layout, NULL); if (IS_ERR(hw)) @@ -231,7 +231,7 @@ static void __init sama5d3_pmc_setup(struct device_node *np) for (i = 0; i < ARRAY_SIZE(sama5d3_systemck); i++) { hw = at91_clk_register_system(regmap, sama5d3_systemck[i].n, - sama5d3_systemck[i].p, + sama5d3_systemck[i].p, NULL, sama5d3_systemck[i].id, sama5d3_systemck[i].flags); if (IS_ERR(hw)) @@ -244,7 +244,7 @@ static void __init sama5d3_pmc_setup(struct device_node *np) hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock, &sama5d3_pcr_layout, sama5d3_periphck[i].n, - "masterck_div", + "masterck_div", NULL, sama5d3_periphck[i].id, &sama5d3_periphck[i].r, INT_MIN, diff --git a/drivers/clk/at91/sama5d4.c b/drivers/clk/at91/sama5d4.c index e876ec971a39c97fc9514098de2e40d8ae573053..160c0bddb6a3be7b12877d3d832a9aa9255c1bd5 100644 --- a/drivers/clk/at91/sama5d4.c +++ b/drivers/clk/at91/sama5d4.c @@ -165,14 +165,14 @@ static void __init sama5d4_pmc_setup(struct device_node *np) bypass = of_property_read_bool(np, "atmel,osc-bypass"); - hw = at91_clk_register_main_osc(regmap, "main_osc", mainxtal_name, + hw = at91_clk_register_main_osc(regmap, "main_osc", mainxtal_name, NULL, bypass); if (IS_ERR(hw)) goto err_free; parent_names[0] = "main_rc_osc"; parent_names[1] = "main_osc"; - hw = at91_clk_register_sam9x5_main(regmap, "mainck", parent_names, 2); + hw = at91_clk_register_sam9x5_main(regmap, "mainck", parent_names, NULL, 2); if (IS_ERR(hw)) goto err_free; @@ -187,7 +187,7 @@ static void __init sama5d4_pmc_setup(struct device_node *np) sama5d4_pmc->chws[PMC_PLLACK] = hw; - hw = at91_clk_register_utmi(regmap, NULL, "utmick", "mainck"); + hw = at91_clk_register_utmi(regmap, NULL, "utmick", "mainck", NULL); if (IS_ERR(hw)) goto err_free; @@ -198,14 +198,14 @@ static void __init sama5d4_pmc_setup(struct device_node *np) parent_names[2] = "plladivck"; parent_names[3] = "utmick"; hw = at91_clk_register_master_pres(regmap, "masterck_pres", 4, - parent_names, + parent_names, NULL, &at91sam9x5_master_layout, &mck_characteristics, &mck_lock); if (IS_ERR(hw)) goto err_free; hw = at91_clk_register_master_div(regmap, "masterck_div", - "masterck_pres", + "masterck_pres", NULL, &at91sam9x5_master_layout, &mck_characteristics, &mck_lock, CLK_SET_RATE_GATE, 0); @@ -243,7 +243,7 @@ static void __init sama5d4_pmc_setup(struct device_node *np) snprintf(name, sizeof(name), "prog%d", i); hw = at91_clk_register_programmable(regmap, name, - parent_names, 5, i, + parent_names, NULL, 5, i, &at91sam9x5_programmable_layout, NULL); if (IS_ERR(hw)) @@ -254,7 +254,7 @@ static void __init sama5d4_pmc_setup(struct device_node *np) for (i = 0; i < ARRAY_SIZE(sama5d4_systemck); i++) { hw = at91_clk_register_system(regmap, sama5d4_systemck[i].n, - sama5d4_systemck[i].p, + sama5d4_systemck[i].p, NULL, sama5d4_systemck[i].id, sama5d4_systemck[i].flags); if (IS_ERR(hw)) @@ -267,7 +267,7 @@ static void __init sama5d4_pmc_setup(struct device_node *np) hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock, &sama5d4_pcr_layout, sama5d4_periphck[i].n, - "masterck_div", + "masterck_div", NULL, sama5d4_periphck[i].id, &range, INT_MIN, sama5d4_periphck[i].flags); @@ -281,7 +281,7 @@ static void __init sama5d4_pmc_setup(struct device_node *np) hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock, &sama5d4_pcr_layout, sama5d4_periph32ck[i].n, - "h32mxck", + "h32mxck", NULL, sama5d4_periph32ck[i].id, &range, INT_MIN, 0); if (IS_ERR(hw)) diff --git a/drivers/clk/at91/sama7g5.c b/drivers/clk/at91/sama7g5.c index f135b662f1ffd92687c4f766781f932fe07b9230..91b5c6f14819642d2400fcfcc541a43de5f85c49 100644 --- a/drivers/clk/at91/sama7g5.c +++ b/drivers/clk/at91/sama7g5.c @@ -56,6 +56,18 @@ enum pll_ids { PLL_ID_MAX, }; +/* + * PLL component identifier + * @PLL_COMPID_FRAC: Fractional PLL component identifier + * @PLL_COMPID_DIV0: 1st PLL divider component identifier + * @PLL_COMPID_DIV1: 2nd PLL divider component identifier + */ +enum pll_component_id { + PLL_COMPID_FRAC, + PLL_COMPID_DIV0, + PLL_COMPID_DIV1, +}; + /* * PLL type identifiers * @PLL_TYPE_FRAC: fractional PLL identifier @@ -118,186 +130,234 @@ static const struct clk_pll_characteristics pll_characteristics = { .output = pll_outputs, }; +/* + * SAMA7G5 PLL possible parents + * @SAMA7G5_PLL_PARENT_MAINCK: MAINCK is PLL a parent + * @SAMA7G5_PLL_PARENT_MAIN_XTAL: MAIN XTAL is a PLL parent + * @SAMA7G5_PLL_PARENT_FRACCK: Frac PLL is a PLL parent (for PLL dividers) + */ +enum sama7g5_pll_parent { + SAMA7G5_PLL_PARENT_MAINCK, + SAMA7G5_PLL_PARENT_MAIN_XTAL, + SAMA7G5_PLL_PARENT_FRACCK, +}; + /* * PLL clocks description * @n: clock name - * @p: clock parent * @l: clock layout * @c: clock characteristics + * @hw: pointer to clk_hw * @t: clock type * @f: clock flags + * @p: clock parent * @eid: export index in sama7g5->chws[] array * @safe_div: intermediate divider need to be set on PRE_RATE_CHANGE * notification */ -static const struct { +static struct sama7g5_pll { const char *n; - const char *p; const struct clk_pll_layout *l; const struct clk_pll_characteristics *c; + struct clk_hw *hw; unsigned long f; + enum sama7g5_pll_parent p; u8 t; u8 eid; u8 safe_div; } sama7g5_plls[][PLL_ID_MAX] = { [PLL_ID_CPU] = { - { .n = "cpupll_fracck", - .p = "mainck", - .l = &pll_layout_frac, - .c = &cpu_pll_characteristics, - .t = PLL_TYPE_FRAC, - /* - * This feeds cpupll_divpmcck which feeds CPU. It should - * not be disabled. - */ - .f = CLK_IS_CRITICAL, }, - - { .n = "cpupll_divpmcck", - .p = "cpupll_fracck", - .l = &pll_layout_divpmc, - .c = &cpu_pll_characteristics, - .t = PLL_TYPE_DIV, - /* This feeds CPU. It should not be disabled. */ - .f = CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, - .eid = PMC_CPUPLL, - /* - * Safe div=15 should be safe even for switching b/w 1GHz and - * 90MHz (frac pll might go up to 1.2GHz). - */ - .safe_div = 15, }, + [PLL_COMPID_FRAC] = { + .n = "cpupll_fracck", + .p = SAMA7G5_PLL_PARENT_MAINCK, + .l = &pll_layout_frac, + .c = &cpu_pll_characteristics, + .t = PLL_TYPE_FRAC, + /* + * This feeds cpupll_divpmcck which feeds CPU. It should + * not be disabled. + */ + .f = CLK_IS_CRITICAL, + }, + + [PLL_COMPID_DIV0] = { + .n = "cpupll_divpmcck", + .p = SAMA7G5_PLL_PARENT_FRACCK, + .l = &pll_layout_divpmc, + .c = &cpu_pll_characteristics, + .t = PLL_TYPE_DIV, + /* This feeds CPU. It should not be disabled. */ + .f = CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, + .eid = PMC_CPUPLL, + /* + * Safe div=15 should be safe even for switching b/w 1GHz and + * 90MHz (frac pll might go up to 1.2GHz). + */ + .safe_div = 15, + }, }, [PLL_ID_SYS] = { - { .n = "syspll_fracck", - .p = "mainck", - .l = &pll_layout_frac, - .c = &pll_characteristics, - .t = PLL_TYPE_FRAC, - /* - * This feeds syspll_divpmcck which may feed critical parts - * of the systems like timers. Therefore it should not be - * disabled. - */ - .f = CLK_IS_CRITICAL | CLK_SET_RATE_GATE, }, - - { .n = "syspll_divpmcck", - .p = "syspll_fracck", - .l = &pll_layout_divpmc, - .c = &pll_characteristics, - .t = PLL_TYPE_DIV, - /* - * This may feed critical parts of the systems like timers. - * Therefore it should not be disabled. - */ - .f = CLK_IS_CRITICAL | CLK_SET_RATE_GATE, - .eid = PMC_SYSPLL, }, + [PLL_COMPID_FRAC] = { + .n = "syspll_fracck", + .p = SAMA7G5_PLL_PARENT_MAINCK, + .l = &pll_layout_frac, + .c = &pll_characteristics, + .t = PLL_TYPE_FRAC, + /* + * This feeds syspll_divpmcck which may feed critical parts + * of the systems like timers. Therefore it should not be + * disabled. + */ + .f = CLK_IS_CRITICAL | CLK_SET_RATE_GATE, + }, + + [PLL_COMPID_DIV0] = { + .n = "syspll_divpmcck", + .p = SAMA7G5_PLL_PARENT_FRACCK, + .l = &pll_layout_divpmc, + .c = &pll_characteristics, + .t = PLL_TYPE_DIV, + /* + * This may feed critical parts of the systems like timers. + * Therefore it should not be disabled. + */ + .f = CLK_IS_CRITICAL | CLK_SET_RATE_GATE, + .eid = PMC_SYSPLL, + }, }, [PLL_ID_DDR] = { - { .n = "ddrpll_fracck", - .p = "mainck", - .l = &pll_layout_frac, - .c = &pll_characteristics, - .t = PLL_TYPE_FRAC, - /* - * This feeds ddrpll_divpmcck which feeds DDR. It should not - * be disabled. - */ - .f = CLK_IS_CRITICAL | CLK_SET_RATE_GATE, }, - - { .n = "ddrpll_divpmcck", - .p = "ddrpll_fracck", - .l = &pll_layout_divpmc, - .c = &pll_characteristics, - .t = PLL_TYPE_DIV, - /* This feeds DDR. It should not be disabled. */ - .f = CLK_IS_CRITICAL | CLK_SET_RATE_GATE, }, + [PLL_COMPID_FRAC] = { + .n = "ddrpll_fracck", + .p = SAMA7G5_PLL_PARENT_MAINCK, + .l = &pll_layout_frac, + .c = &pll_characteristics, + .t = PLL_TYPE_FRAC, + /* + * This feeds ddrpll_divpmcck which feeds DDR. It should not + * be disabled. + */ + .f = CLK_IS_CRITICAL | CLK_SET_RATE_GATE, + }, + + [PLL_COMPID_DIV0] = { + .n = "ddrpll_divpmcck", + .p = SAMA7G5_PLL_PARENT_FRACCK, + .l = &pll_layout_divpmc, + .c = &pll_characteristics, + .t = PLL_TYPE_DIV, + /* This feeds DDR. It should not be disabled. */ + .f = CLK_IS_CRITICAL | CLK_SET_RATE_GATE, + }, }, [PLL_ID_IMG] = { - { .n = "imgpll_fracck", - .p = "mainck", - .l = &pll_layout_frac, - .c = &pll_characteristics, - .t = PLL_TYPE_FRAC, - .f = CLK_SET_RATE_GATE, }, - - { .n = "imgpll_divpmcck", - .p = "imgpll_fracck", - .l = &pll_layout_divpmc, - .c = &pll_characteristics, - .t = PLL_TYPE_DIV, - .f = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE | - CLK_SET_RATE_PARENT, }, + [PLL_COMPID_FRAC] = { + .n = "imgpll_fracck", + .p = SAMA7G5_PLL_PARENT_MAINCK, + .l = &pll_layout_frac, + .c = &pll_characteristics, + .t = PLL_TYPE_FRAC, + .f = CLK_SET_RATE_GATE, + }, + + [PLL_COMPID_DIV0] = { + .n = "imgpll_divpmcck", + .p = SAMA7G5_PLL_PARENT_FRACCK, + .l = &pll_layout_divpmc, + .c = &pll_characteristics, + .t = PLL_TYPE_DIV, + .f = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE | + CLK_SET_RATE_PARENT, + }, }, [PLL_ID_BAUD] = { - { .n = "baudpll_fracck", - .p = "mainck", - .l = &pll_layout_frac, - .c = &pll_characteristics, - .t = PLL_TYPE_FRAC, - .f = CLK_SET_RATE_GATE, }, - - { .n = "baudpll_divpmcck", - .p = "baudpll_fracck", - .l = &pll_layout_divpmc, - .c = &pll_characteristics, - .t = PLL_TYPE_DIV, - .f = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE | - CLK_SET_RATE_PARENT, }, + [PLL_COMPID_FRAC] = { + .n = "baudpll_fracck", + .p = SAMA7G5_PLL_PARENT_MAINCK, + .l = &pll_layout_frac, + .c = &pll_characteristics, + .t = PLL_TYPE_FRAC, + .f = CLK_SET_RATE_GATE, }, + + [PLL_COMPID_DIV0] = { + .n = "baudpll_divpmcck", + .p = SAMA7G5_PLL_PARENT_FRACCK, + .l = &pll_layout_divpmc, + .c = &pll_characteristics, + .t = PLL_TYPE_DIV, + .f = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE | + CLK_SET_RATE_PARENT, + }, }, [PLL_ID_AUDIO] = { - { .n = "audiopll_fracck", - .p = "main_xtal", - .l = &pll_layout_frac, - .c = &pll_characteristics, - .t = PLL_TYPE_FRAC, - .f = CLK_SET_RATE_GATE, }, - - { .n = "audiopll_divpmcck", - .p = "audiopll_fracck", - .l = &pll_layout_divpmc, - .c = &pll_characteristics, - .t = PLL_TYPE_DIV, - .f = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE | - CLK_SET_RATE_PARENT, - .eid = PMC_AUDIOPMCPLL, }, - - { .n = "audiopll_diviock", - .p = "audiopll_fracck", - .l = &pll_layout_divio, - .c = &pll_characteristics, - .t = PLL_TYPE_DIV, - .f = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE | - CLK_SET_RATE_PARENT, - .eid = PMC_AUDIOIOPLL, }, + [PLL_COMPID_FRAC] = { + .n = "audiopll_fracck", + .p = SAMA7G5_PLL_PARENT_MAIN_XTAL, + .l = &pll_layout_frac, + .c = &pll_characteristics, + .t = PLL_TYPE_FRAC, + .f = CLK_SET_RATE_GATE, + }, + + [PLL_COMPID_DIV0] = { + .n = "audiopll_divpmcck", + .p = SAMA7G5_PLL_PARENT_FRACCK, + .l = &pll_layout_divpmc, + .c = &pll_characteristics, + .t = PLL_TYPE_DIV, + .f = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE | + CLK_SET_RATE_PARENT, + .eid = PMC_AUDIOPMCPLL, + }, + + [PLL_COMPID_DIV1] = { + .n = "audiopll_diviock", + .p = SAMA7G5_PLL_PARENT_FRACCK, + .l = &pll_layout_divio, + .c = &pll_characteristics, + .t = PLL_TYPE_DIV, + .f = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE | + CLK_SET_RATE_PARENT, + .eid = PMC_AUDIOIOPLL, + }, }, [PLL_ID_ETH] = { - { .n = "ethpll_fracck", - .p = "main_xtal", - .l = &pll_layout_frac, - .c = &pll_characteristics, - .t = PLL_TYPE_FRAC, - .f = CLK_SET_RATE_GATE, }, - - { .n = "ethpll_divpmcck", - .p = "ethpll_fracck", - .l = &pll_layout_divpmc, - .c = &pll_characteristics, - .t = PLL_TYPE_DIV, - .f = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE | - CLK_SET_RATE_PARENT, }, + [PLL_COMPID_FRAC] = { + .n = "ethpll_fracck", + .p = SAMA7G5_PLL_PARENT_MAIN_XTAL, + .l = &pll_layout_frac, + .c = &pll_characteristics, + .t = PLL_TYPE_FRAC, + .f = CLK_SET_RATE_GATE, + }, + + [PLL_COMPID_DIV0] = { + .n = "ethpll_divpmcck", + .p = SAMA7G5_PLL_PARENT_FRACCK, + .l = &pll_layout_divpmc, + .c = &pll_characteristics, + .t = PLL_TYPE_DIV, + .f = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE | + CLK_SET_RATE_PARENT, + }, }, }; +/* Used to create an array entry identifying a PLL by its components. */ +#define PLL_IDS_TO_ARR_ENTRY(_id, _comp) { PLL_ID_##_id, PLL_COMPID_##_comp} + /* * Master clock (MCK[1..4]) description * @n: clock name - * @ep: extra parents names array - * @ep_chg_chg_id: index in parents array that specifies the changeable + * @ep: extra parents names array (entry formed by PLL components + * identifiers (see enum pll_component_id)) + * @hw: pointer to clk_hw + * @ep_chg_id: index in parents array that specifies the changeable * parent * @ep_count: extra parents count * @ep_mux_table: mux table for extra parents @@ -305,9 +365,13 @@ static const struct { * @eid: export index in sama7g5->chws[] array * @c: true if clock is critical and cannot be disabled */ -static const struct { +static struct { const char *n; - const char *ep[4]; + struct { + int pll_id; + int pll_compid; + } ep[4]; + struct clk_hw *hw; int ep_chg_id; u8 ep_count; u8 ep_mux_table[4]; @@ -315,9 +379,10 @@ static const struct { u8 eid; u8 c; } sama7g5_mckx[] = { + { .n = "mck0", }, /* Dummy entry for MCK0 to store hw in probe. */ { .n = "mck1", .id = 1, - .ep = { "syspll_divpmcck", }, + .ep = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), }, .ep_mux_table = { 5, }, .ep_count = 1, .ep_chg_id = INT_MIN, @@ -326,7 +391,7 @@ static const struct { { .n = "mck2", .id = 2, - .ep = { "ddrpll_divpmcck", }, + .ep = { PLL_IDS_TO_ARR_ENTRY(DDR, DIV0), }, .ep_mux_table = { 6, }, .ep_count = 1, .ep_chg_id = INT_MIN, @@ -334,14 +399,15 @@ static const struct { { .n = "mck3", .id = 3, - .ep = { "syspll_divpmcck", "ddrpll_divpmcck", "imgpll_divpmcck", }, + .ep = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(DDR, DIV0), + PLL_IDS_TO_ARR_ENTRY(IMG, DIV0), }, .ep_mux_table = { 5, 6, 7, }, .ep_count = 3, .ep_chg_id = 5, }, { .n = "mck4", .id = 4, - .ep = { "syspll_divpmcck", }, + .ep = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), }, .ep_mux_table = { 5, }, .ep_count = 1, .ep_chg_id = INT_MIN, @@ -351,120 +417,137 @@ static const struct { /* * System clock description * @n: clock name - * @p: clock parent name * @id: clock id */ static const struct { const char *n; - const char *p; u8 id; } sama7g5_systemck[] = { - { .n = "pck0", .p = "prog0", .id = 8, }, - { .n = "pck1", .p = "prog1", .id = 9, }, - { .n = "pck2", .p = "prog2", .id = 10, }, - { .n = "pck3", .p = "prog3", .id = 11, }, - { .n = "pck4", .p = "prog4", .id = 12, }, - { .n = "pck5", .p = "prog5", .id = 13, }, - { .n = "pck6", .p = "prog6", .id = 14, }, - { .n = "pck7", .p = "prog7", .id = 15, }, + { .n = "pck0", .id = 8, }, + { .n = "pck1", .id = 9, }, + { .n = "pck2", .id = 10, }, + { .n = "pck3", .id = 11, }, + { .n = "pck4", .id = 12, }, + { .n = "pck5", .id = 13, }, + { .n = "pck6", .id = 14, }, + { .n = "pck7", .id = 15, }, }; /* Mux table for programmable clocks. */ static u32 sama7g5_prog_mux_table[] = { 0, 1, 2, 5, 6, 7, 8, 9, 10, }; +/* + * Peripheral clock parent hw identifier (used to index in sama7g5_mckx[]) + * @PCK_PARENT_HW_MCK0: pck parent hw identifier is MCK0 + * @PCK_PARENT_HW_MCK1: pck parent hw identifier is MCK1 + * @PCK_PARENT_HW_MCK2: pck parent hw identifier is MCK2 + * @PCK_PARENT_HW_MCK3: pck parent hw identifier is MCK3 + * @PCK_PARENT_HW_MCK4: pck parent hw identifier is MCK4 + * @PCK_PARENT_HW_MAX: max identifier + */ +enum sama7g5_pck_parent_hw_id { + PCK_PARENT_HW_MCK0, + PCK_PARENT_HW_MCK1, + PCK_PARENT_HW_MCK2, + PCK_PARENT_HW_MCK3, + PCK_PARENT_HW_MCK4, + PCK_PARENT_HW_MAX, +}; + /* * Peripheral clock description * @n: clock name - * @p: clock parent name + * @p: clock parent hw id * @r: clock range values * @id: clock id * @chgp: index in parent array of the changeable parent */ -static const struct { +static struct { const char *n; - const char *p; + enum sama7g5_pck_parent_hw_id p; struct clk_range r; u8 chgp; u8 id; } sama7g5_periphck[] = { - { .n = "pioA_clk", .p = "mck0", .id = 11, }, - { .n = "securam_clk", .p = "mck0", .id = 18, }, - { .n = "sfr_clk", .p = "mck1", .id = 19, }, - { .n = "hsmc_clk", .p = "mck1", .id = 21, }, - { .n = "xdmac0_clk", .p = "mck1", .id = 22, }, - { .n = "xdmac1_clk", .p = "mck1", .id = 23, }, - { .n = "xdmac2_clk", .p = "mck1", .id = 24, }, - { .n = "acc_clk", .p = "mck1", .id = 25, }, - { .n = "aes_clk", .p = "mck1", .id = 27, }, - { .n = "tzaesbasc_clk", .p = "mck1", .id = 28, }, - { .n = "asrc_clk", .p = "mck1", .id = 30, .r = { .max = 200000000, }, }, - { .n = "cpkcc_clk", .p = "mck0", .id = 32, }, - { .n = "csi_clk", .p = "mck3", .id = 33, .r = { .max = 266000000, }, .chgp = 1, }, - { .n = "csi2dc_clk", .p = "mck3", .id = 34, .r = { .max = 266000000, }, .chgp = 1, }, - { .n = "eic_clk", .p = "mck1", .id = 37, }, - { .n = "flex0_clk", .p = "mck1", .id = 38, }, - { .n = "flex1_clk", .p = "mck1", .id = 39, }, - { .n = "flex2_clk", .p = "mck1", .id = 40, }, - { .n = "flex3_clk", .p = "mck1", .id = 41, }, - { .n = "flex4_clk", .p = "mck1", .id = 42, }, - { .n = "flex5_clk", .p = "mck1", .id = 43, }, - { .n = "flex6_clk", .p = "mck1", .id = 44, }, - { .n = "flex7_clk", .p = "mck1", .id = 45, }, - { .n = "flex8_clk", .p = "mck1", .id = 46, }, - { .n = "flex9_clk", .p = "mck1", .id = 47, }, - { .n = "flex10_clk", .p = "mck1", .id = 48, }, - { .n = "flex11_clk", .p = "mck1", .id = 49, }, - { .n = "gmac0_clk", .p = "mck1", .id = 51, }, - { .n = "gmac1_clk", .p = "mck1", .id = 52, }, - { .n = "icm_clk", .p = "mck1", .id = 55, }, - { .n = "isc_clk", .p = "mck3", .id = 56, .r = { .max = 266000000, }, .chgp = 1, }, - { .n = "i2smcc0_clk", .p = "mck1", .id = 57, .r = { .max = 200000000, }, }, - { .n = "i2smcc1_clk", .p = "mck1", .id = 58, .r = { .max = 200000000, }, }, - { .n = "matrix_clk", .p = "mck1", .id = 60, }, - { .n = "mcan0_clk", .p = "mck1", .id = 61, .r = { .max = 200000000, }, }, - { .n = "mcan1_clk", .p = "mck1", .id = 62, .r = { .max = 200000000, }, }, - { .n = "mcan2_clk", .p = "mck1", .id = 63, .r = { .max = 200000000, }, }, - { .n = "mcan3_clk", .p = "mck1", .id = 64, .r = { .max = 200000000, }, }, - { .n = "mcan4_clk", .p = "mck1", .id = 65, .r = { .max = 200000000, }, }, - { .n = "mcan5_clk", .p = "mck1", .id = 66, .r = { .max = 200000000, }, }, - { .n = "pdmc0_clk", .p = "mck1", .id = 68, .r = { .max = 200000000, }, }, - { .n = "pdmc1_clk", .p = "mck1", .id = 69, .r = { .max = 200000000, }, }, - { .n = "pit64b0_clk", .p = "mck1", .id = 70, }, - { .n = "pit64b1_clk", .p = "mck1", .id = 71, }, - { .n = "pit64b2_clk", .p = "mck1", .id = 72, }, - { .n = "pit64b3_clk", .p = "mck1", .id = 73, }, - { .n = "pit64b4_clk", .p = "mck1", .id = 74, }, - { .n = "pit64b5_clk", .p = "mck1", .id = 75, }, - { .n = "pwm_clk", .p = "mck1", .id = 77, }, - { .n = "qspi0_clk", .p = "mck1", .id = 78, }, - { .n = "qspi1_clk", .p = "mck1", .id = 79, }, - { .n = "sdmmc0_clk", .p = "mck1", .id = 80, }, - { .n = "sdmmc1_clk", .p = "mck1", .id = 81, }, - { .n = "sdmmc2_clk", .p = "mck1", .id = 82, }, - { .n = "sha_clk", .p = "mck1", .id = 83, }, - { .n = "spdifrx_clk", .p = "mck1", .id = 84, .r = { .max = 200000000, }, }, - { .n = "spdiftx_clk", .p = "mck1", .id = 85, .r = { .max = 200000000, }, }, - { .n = "ssc0_clk", .p = "mck1", .id = 86, .r = { .max = 200000000, }, }, - { .n = "ssc1_clk", .p = "mck1", .id = 87, .r = { .max = 200000000, }, }, - { .n = "tcb0_ch0_clk", .p = "mck1", .id = 88, .r = { .max = 200000000, }, }, - { .n = "tcb0_ch1_clk", .p = "mck1", .id = 89, .r = { .max = 200000000, }, }, - { .n = "tcb0_ch2_clk", .p = "mck1", .id = 90, .r = { .max = 200000000, }, }, - { .n = "tcb1_ch0_clk", .p = "mck1", .id = 91, .r = { .max = 200000000, }, }, - { .n = "tcb1_ch1_clk", .p = "mck1", .id = 92, .r = { .max = 200000000, }, }, - { .n = "tcb1_ch2_clk", .p = "mck1", .id = 93, .r = { .max = 200000000, }, }, - { .n = "tcpca_clk", .p = "mck1", .id = 94, }, - { .n = "tcpcb_clk", .p = "mck1", .id = 95, }, - { .n = "tdes_clk", .p = "mck1", .id = 96, }, - { .n = "trng_clk", .p = "mck1", .id = 97, }, - { .n = "udphsa_clk", .p = "mck1", .id = 104, }, - { .n = "udphsb_clk", .p = "mck1", .id = 105, }, - { .n = "uhphs_clk", .p = "mck1", .id = 106, }, + { .n = "pioA_clk", .p = PCK_PARENT_HW_MCK0, .id = 11, }, + { .n = "securam_clk", .p = PCK_PARENT_HW_MCK0, .id = 18, }, + { .n = "sfr_clk", .p = PCK_PARENT_HW_MCK1, .id = 19, }, + { .n = "hsmc_clk", .p = PCK_PARENT_HW_MCK1, .id = 21, }, + { .n = "xdmac0_clk", .p = PCK_PARENT_HW_MCK1, .id = 22, }, + { .n = "xdmac1_clk", .p = PCK_PARENT_HW_MCK1, .id = 23, }, + { .n = "xdmac2_clk", .p = PCK_PARENT_HW_MCK1, .id = 24, }, + { .n = "acc_clk", .p = PCK_PARENT_HW_MCK1, .id = 25, }, + { .n = "aes_clk", .p = PCK_PARENT_HW_MCK1, .id = 27, }, + { .n = "tzaesbasc_clk", .p = PCK_PARENT_HW_MCK1, .id = 28, }, + { .n = "asrc_clk", .p = PCK_PARENT_HW_MCK1, .id = 30, .r = { .max = 200000000, }, }, + { .n = "cpkcc_clk", .p = PCK_PARENT_HW_MCK0, .id = 32, }, + { .n = "csi_clk", .p = PCK_PARENT_HW_MCK3, .id = 33, .r = { .max = 266000000, }, .chgp = 1, }, + { .n = "csi2dc_clk", .p = PCK_PARENT_HW_MCK3, .id = 34, .r = { .max = 266000000, }, .chgp = 1, }, + { .n = "eic_clk", .p = PCK_PARENT_HW_MCK1, .id = 37, }, + { .n = "flex0_clk", .p = PCK_PARENT_HW_MCK1, .id = 38, }, + { .n = "flex1_clk", .p = PCK_PARENT_HW_MCK1, .id = 39, }, + { .n = "flex2_clk", .p = PCK_PARENT_HW_MCK1, .id = 40, }, + { .n = "flex3_clk", .p = PCK_PARENT_HW_MCK1, .id = 41, }, + { .n = "flex4_clk", .p = PCK_PARENT_HW_MCK1, .id = 42, }, + { .n = "flex5_clk", .p = PCK_PARENT_HW_MCK1, .id = 43, }, + { .n = "flex6_clk", .p = PCK_PARENT_HW_MCK1, .id = 44, }, + { .n = "flex7_clk", .p = PCK_PARENT_HW_MCK1, .id = 45, }, + { .n = "flex8_clk", .p = PCK_PARENT_HW_MCK1, .id = 46, }, + { .n = "flex9_clk", .p = PCK_PARENT_HW_MCK1, .id = 47, }, + { .n = "flex10_clk", .p = PCK_PARENT_HW_MCK1, .id = 48, }, + { .n = "flex11_clk", .p = PCK_PARENT_HW_MCK1, .id = 49, }, + { .n = "gmac0_clk", .p = PCK_PARENT_HW_MCK1, .id = 51, }, + { .n = "gmac1_clk", .p = PCK_PARENT_HW_MCK1, .id = 52, }, + { .n = "icm_clk", .p = PCK_PARENT_HW_MCK1, .id = 55, }, + { .n = "isc_clk", .p = PCK_PARENT_HW_MCK3, .id = 56, .r = { .max = 266000000, }, .chgp = 1, }, + { .n = "i2smcc0_clk", .p = PCK_PARENT_HW_MCK1, .id = 57, .r = { .max = 200000000, }, }, + { .n = "i2smcc1_clk", .p = PCK_PARENT_HW_MCK1, .id = 58, .r = { .max = 200000000, }, }, + { .n = "matrix_clk", .p = PCK_PARENT_HW_MCK1, .id = 60, }, + { .n = "mcan0_clk", .p = PCK_PARENT_HW_MCK1, .id = 61, .r = { .max = 200000000, }, }, + { .n = "mcan1_clk", .p = PCK_PARENT_HW_MCK1, .id = 62, .r = { .max = 200000000, }, }, + { .n = "mcan2_clk", .p = PCK_PARENT_HW_MCK1, .id = 63, .r = { .max = 200000000, }, }, + { .n = "mcan3_clk", .p = PCK_PARENT_HW_MCK1, .id = 64, .r = { .max = 200000000, }, }, + { .n = "mcan4_clk", .p = PCK_PARENT_HW_MCK1, .id = 65, .r = { .max = 200000000, }, }, + { .n = "mcan5_clk", .p = PCK_PARENT_HW_MCK1, .id = 66, .r = { .max = 200000000, }, }, + { .n = "pdmc0_clk", .p = PCK_PARENT_HW_MCK1, .id = 68, .r = { .max = 200000000, }, }, + { .n = "pdmc1_clk", .p = PCK_PARENT_HW_MCK1, .id = 69, .r = { .max = 200000000, }, }, + { .n = "pit64b0_clk", .p = PCK_PARENT_HW_MCK1, .id = 70, }, + { .n = "pit64b1_clk", .p = PCK_PARENT_HW_MCK1, .id = 71, }, + { .n = "pit64b2_clk", .p = PCK_PARENT_HW_MCK1, .id = 72, }, + { .n = "pit64b3_clk", .p = PCK_PARENT_HW_MCK1, .id = 73, }, + { .n = "pit64b4_clk", .p = PCK_PARENT_HW_MCK1, .id = 74, }, + { .n = "pit64b5_clk", .p = PCK_PARENT_HW_MCK1, .id = 75, }, + { .n = "pwm_clk", .p = PCK_PARENT_HW_MCK1, .id = 77, }, + { .n = "qspi0_clk", .p = PCK_PARENT_HW_MCK1, .id = 78, }, + { .n = "qspi1_clk", .p = PCK_PARENT_HW_MCK1, .id = 79, }, + { .n = "sdmmc0_clk", .p = PCK_PARENT_HW_MCK1, .id = 80, }, + { .n = "sdmmc1_clk", .p = PCK_PARENT_HW_MCK1, .id = 81, }, + { .n = "sdmmc2_clk", .p = PCK_PARENT_HW_MCK1, .id = 82, }, + { .n = "sha_clk", .p = PCK_PARENT_HW_MCK1, .id = 83, }, + { .n = "spdifrx_clk", .p = PCK_PARENT_HW_MCK1, .id = 84, .r = { .max = 200000000, }, }, + { .n = "spdiftx_clk", .p = PCK_PARENT_HW_MCK1, .id = 85, .r = { .max = 200000000, }, }, + { .n = "ssc0_clk", .p = PCK_PARENT_HW_MCK1, .id = 86, .r = { .max = 200000000, }, }, + { .n = "ssc1_clk", .p = PCK_PARENT_HW_MCK1, .id = 87, .r = { .max = 200000000, }, }, + { .n = "tcb0_ch0_clk", .p = PCK_PARENT_HW_MCK1, .id = 88, .r = { .max = 200000000, }, }, + { .n = "tcb0_ch1_clk", .p = PCK_PARENT_HW_MCK1, .id = 89, .r = { .max = 200000000, }, }, + { .n = "tcb0_ch2_clk", .p = PCK_PARENT_HW_MCK1, .id = 90, .r = { .max = 200000000, }, }, + { .n = "tcb1_ch0_clk", .p = PCK_PARENT_HW_MCK1, .id = 91, .r = { .max = 200000000, }, }, + { .n = "tcb1_ch1_clk", .p = PCK_PARENT_HW_MCK1, .id = 92, .r = { .max = 200000000, }, }, + { .n = "tcb1_ch2_clk", .p = PCK_PARENT_HW_MCK1, .id = 93, .r = { .max = 200000000, }, }, + { .n = "tcpca_clk", .p = PCK_PARENT_HW_MCK1, .id = 94, }, + { .n = "tcpcb_clk", .p = PCK_PARENT_HW_MCK1, .id = 95, }, + { .n = "tdes_clk", .p = PCK_PARENT_HW_MCK1, .id = 96, }, + { .n = "trng_clk", .p = PCK_PARENT_HW_MCK1, .id = 97, }, + { .n = "udphsa_clk", .p = PCK_PARENT_HW_MCK1, .id = 104, }, + { .n = "udphsb_clk", .p = PCK_PARENT_HW_MCK1, .id = 105, }, + { .n = "uhphs_clk", .p = PCK_PARENT_HW_MCK1, .id = 106, }, }; /* * Generic clock description * @n: clock name - * @pp: PLL parents + * @pp: PLL parents (entry formed by PLL components identifiers + * (see enum pll_component_id)) * @pp_mux_table: PLL parents mux table * @r: clock output range * @pp_chg_id: id in parent array of changeable PLL parent @@ -473,7 +556,10 @@ static const struct { */ static const struct { const char *n; - const char *pp[8]; + struct { + int pll_id; + int pll_compid; + } pp[8]; const char pp_mux_table[8]; struct clk_range r; int pp_chg_id; @@ -483,7 +569,8 @@ static const struct { { .n = "adc_gclk", .id = 26, .r = { .max = 100000000, }, - .pp = { "syspll_divpmcck", "imgpll_divpmcck", "audiopll_divpmcck", }, + .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(IMG, DIV0), + PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0), }, .pp_mux_table = { 5, 7, 9, }, .pp_count = 3, .pp_chg_id = INT_MIN, }, @@ -491,7 +578,7 @@ static const struct { { .n = "asrc_gclk", .id = 30, .r = { .max = 200000000 }, - .pp = { "audiopll_divpmcck", }, + .pp = { PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0), }, .pp_mux_table = { 9, }, .pp_count = 1, .pp_chg_id = 3, }, @@ -499,7 +586,7 @@ static const struct { { .n = "csi_gclk", .id = 33, .r = { .max = 27000000 }, - .pp = { "ddrpll_divpmcck", "imgpll_divpmcck", }, + .pp = { PLL_IDS_TO_ARR_ENTRY(DDR, DIV0), PLL_IDS_TO_ARR_ENTRY(IMG, DIV0), }, .pp_mux_table = { 6, 7, }, .pp_count = 2, .pp_chg_id = INT_MIN, }, @@ -507,7 +594,7 @@ static const struct { { .n = "flex0_gclk", .id = 38, .r = { .max = 200000000 }, - .pp = { "syspll_divpmcck", "baudpll_divpmcck", }, + .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), }, .pp_mux_table = { 5, 8, }, .pp_count = 2, .pp_chg_id = INT_MIN, }, @@ -515,7 +602,7 @@ static const struct { { .n = "flex1_gclk", .id = 39, .r = { .max = 200000000 }, - .pp = { "syspll_divpmcck", "baudpll_divpmcck", }, + .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), }, .pp_mux_table = { 5, 8, }, .pp_count = 2, .pp_chg_id = INT_MIN, }, @@ -523,7 +610,7 @@ static const struct { { .n = "flex2_gclk", .id = 40, .r = { .max = 200000000 }, - .pp = { "syspll_divpmcck", "baudpll_divpmcck", }, + .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), }, .pp_mux_table = { 5, 8, }, .pp_count = 2, .pp_chg_id = INT_MIN, }, @@ -531,7 +618,7 @@ static const struct { { .n = "flex3_gclk", .id = 41, .r = { .max = 200000000 }, - .pp = { "syspll_divpmcck", "baudpll_divpmcck", }, + .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), }, .pp_mux_table = { 5, 8, }, .pp_count = 2, .pp_chg_id = INT_MIN, }, @@ -539,7 +626,7 @@ static const struct { { .n = "flex4_gclk", .id = 42, .r = { .max = 200000000 }, - .pp = { "syspll_divpmcck", "baudpll_divpmcck", }, + .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), }, .pp_mux_table = { 5, 8, }, .pp_count = 2, .pp_chg_id = INT_MIN, }, @@ -547,7 +634,7 @@ static const struct { { .n = "flex5_gclk", .id = 43, .r = { .max = 200000000 }, - .pp = { "syspll_divpmcck", "baudpll_divpmcck", }, + .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), }, .pp_mux_table = { 5, 8, }, .pp_count = 2, .pp_chg_id = INT_MIN, }, @@ -555,7 +642,7 @@ static const struct { { .n = "flex6_gclk", .id = 44, .r = { .max = 200000000 }, - .pp = { "syspll_divpmcck", "baudpll_divpmcck", }, + .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), }, .pp_mux_table = { 5, 8, }, .pp_count = 2, .pp_chg_id = INT_MIN, }, @@ -563,7 +650,7 @@ static const struct { { .n = "flex7_gclk", .id = 45, .r = { .max = 200000000 }, - .pp = { "syspll_divpmcck", "baudpll_divpmcck", }, + .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), }, .pp_mux_table = { 5, 8, }, .pp_count = 2, .pp_chg_id = INT_MIN, }, @@ -571,7 +658,7 @@ static const struct { { .n = "flex8_gclk", .id = 46, .r = { .max = 200000000 }, - .pp = { "syspll_divpmcck", "baudpll_divpmcck", }, + .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), }, .pp_mux_table = { 5, 8, }, .pp_count = 2, .pp_chg_id = INT_MIN, }, @@ -579,7 +666,7 @@ static const struct { { .n = "flex9_gclk", .id = 47, .r = { .max = 200000000 }, - .pp = { "syspll_divpmcck", "baudpll_divpmcck", }, + .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), }, .pp_mux_table = { 5, 8, }, .pp_count = 2, .pp_chg_id = INT_MIN, }, @@ -587,7 +674,7 @@ static const struct { { .n = "flex10_gclk", .id = 48, .r = { .max = 200000000 }, - .pp = { "syspll_divpmcck", "baudpll_divpmcck", }, + .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), }, .pp_mux_table = { 5, 8, }, .pp_count = 2, .pp_chg_id = INT_MIN, }, @@ -595,7 +682,7 @@ static const struct { { .n = "flex11_gclk", .id = 49, .r = { .max = 200000000 }, - .pp = { "syspll_divpmcck", "baudpll_divpmcck", }, + .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), }, .pp_mux_table = { 5, 8, }, .pp_count = 2, .pp_chg_id = INT_MIN, }, @@ -603,7 +690,7 @@ static const struct { { .n = "gmac0_gclk", .id = 51, .r = { .max = 125000000 }, - .pp = { "ethpll_divpmcck", }, + .pp = { PLL_IDS_TO_ARR_ENTRY(ETH, DIV0), }, .pp_mux_table = { 10, }, .pp_count = 1, .pp_chg_id = 3, }, @@ -611,7 +698,7 @@ static const struct { { .n = "gmac1_gclk", .id = 52, .r = { .max = 50000000 }, - .pp = { "ethpll_divpmcck", }, + .pp = { PLL_IDS_TO_ARR_ENTRY(ETH, DIV0), }, .pp_mux_table = { 10, }, .pp_count = 1, .pp_chg_id = INT_MIN, }, @@ -619,7 +706,7 @@ static const struct { { .n = "gmac0_tsu_gclk", .id = 53, .r = { .max = 300000000 }, - .pp = { "audiopll_divpmcck", "ethpll_divpmcck", }, + .pp = { PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0), PLL_IDS_TO_ARR_ENTRY(ETH, DIV0), }, .pp_mux_table = { 9, 10, }, .pp_count = 2, .pp_chg_id = INT_MIN, }, @@ -627,7 +714,7 @@ static const struct { { .n = "gmac1_tsu_gclk", .id = 54, .r = { .max = 300000000 }, - .pp = { "audiopll_divpmcck", "ethpll_divpmcck", }, + .pp = { PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0), PLL_IDS_TO_ARR_ENTRY(ETH, DIV0), }, .pp_mux_table = { 9, 10, }, .pp_count = 2, .pp_chg_id = INT_MIN, }, @@ -635,7 +722,7 @@ static const struct { { .n = "i2smcc0_gclk", .id = 57, .r = { .max = 100000000 }, - .pp = { "syspll_divpmcck", "audiopll_divpmcck", }, + .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0), }, .pp_mux_table = { 5, 9, }, .pp_count = 2, .pp_chg_id = 4, }, @@ -643,7 +730,7 @@ static const struct { { .n = "i2smcc1_gclk", .id = 58, .r = { .max = 100000000 }, - .pp = { "syspll_divpmcck", "audiopll_divpmcck", }, + .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0), }, .pp_mux_table = { 5, 9, }, .pp_count = 2, .pp_chg_id = 4, }, @@ -651,7 +738,7 @@ static const struct { { .n = "mcan0_gclk", .id = 61, .r = { .max = 200000000 }, - .pp = { "syspll_divpmcck", "baudpll_divpmcck", }, + .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), }, .pp_mux_table = { 5, 8, }, .pp_count = 2, .pp_chg_id = INT_MIN, }, @@ -659,7 +746,7 @@ static const struct { { .n = "mcan1_gclk", .id = 62, .r = { .max = 200000000 }, - .pp = { "syspll_divpmcck", "baudpll_divpmcck", }, + .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), }, .pp_mux_table = { 5, 8, }, .pp_count = 2, .pp_chg_id = INT_MIN, }, @@ -667,7 +754,7 @@ static const struct { { .n = "mcan2_gclk", .id = 63, .r = { .max = 200000000 }, - .pp = { "syspll_divpmcck", "baudpll_divpmcck", }, + .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), }, .pp_mux_table = { 5, 8, }, .pp_count = 2, .pp_chg_id = INT_MIN, }, @@ -675,7 +762,7 @@ static const struct { { .n = "mcan3_gclk", .id = 64, .r = { .max = 200000000 }, - .pp = { "syspll_divpmcck", "baudpll_divpmcck", }, + .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), }, .pp_mux_table = { 5, 8, }, .pp_count = 2, .pp_chg_id = INT_MIN, }, @@ -683,7 +770,7 @@ static const struct { { .n = "mcan4_gclk", .id = 65, .r = { .max = 200000000 }, - .pp = { "syspll_divpmcck", "baudpll_divpmcck", }, + .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), }, .pp_mux_table = { 5, 8, }, .pp_count = 2, .pp_chg_id = INT_MIN, }, @@ -691,7 +778,7 @@ static const struct { { .n = "mcan5_gclk", .id = 66, .r = { .max = 200000000 }, - .pp = { "syspll_divpmcck", "baudpll_divpmcck", }, + .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), }, .pp_mux_table = { 5, 8, }, .pp_count = 2, .pp_chg_id = INT_MIN, }, @@ -699,7 +786,7 @@ static const struct { { .n = "pdmc0_gclk", .id = 68, .r = { .max = 50000000 }, - .pp = { "syspll_divpmcck", "audiopll_divpmcck", }, + .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0), }, .pp_mux_table = { 5, 9, }, .pp_count = 2, .pp_chg_id = INT_MIN, }, @@ -707,7 +794,7 @@ static const struct { { .n = "pdmc1_gclk", .id = 69, .r = { .max = 50000000, }, - .pp = { "syspll_divpmcck", "audiopll_divpmcck", }, + .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0), }, .pp_mux_table = { 5, 9, }, .pp_count = 2, .pp_chg_id = INT_MIN, }, @@ -715,8 +802,9 @@ static const struct { { .n = "pit64b0_gclk", .id = 70, .r = { .max = 200000000 }, - .pp = { "syspll_divpmcck", "imgpll_divpmcck", "baudpll_divpmcck", - "audiopll_divpmcck", "ethpll_divpmcck", }, + .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(IMG, DIV0), + PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0), + PLL_IDS_TO_ARR_ENTRY(ETH, DIV0), }, .pp_mux_table = { 5, 7, 8, 9, 10, }, .pp_count = 5, .pp_chg_id = INT_MIN, }, @@ -724,8 +812,9 @@ static const struct { { .n = "pit64b1_gclk", .id = 71, .r = { .max = 200000000 }, - .pp = { "syspll_divpmcck", "imgpll_divpmcck", "baudpll_divpmcck", - "audiopll_divpmcck", "ethpll_divpmcck", }, + .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(IMG, DIV0), + PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0), + PLL_IDS_TO_ARR_ENTRY(ETH, DIV0), }, .pp_mux_table = { 5, 7, 8, 9, 10, }, .pp_count = 5, .pp_chg_id = INT_MIN, }, @@ -733,8 +822,9 @@ static const struct { { .n = "pit64b2_gclk", .id = 72, .r = { .max = 200000000 }, - .pp = { "syspll_divpmcck", "imgpll_divpmcck", "baudpll_divpmcck", - "audiopll_divpmcck", "ethpll_divpmcck", }, + .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(IMG, DIV0), + PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0), + PLL_IDS_TO_ARR_ENTRY(ETH, DIV0), }, .pp_mux_table = { 5, 7, 8, 9, 10, }, .pp_count = 5, .pp_chg_id = INT_MIN, }, @@ -742,8 +832,9 @@ static const struct { { .n = "pit64b3_gclk", .id = 73, .r = { .max = 200000000 }, - .pp = { "syspll_divpmcck", "imgpll_divpmcck", "baudpll_divpmcck", - "audiopll_divpmcck", "ethpll_divpmcck", }, + .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(IMG, DIV0), + PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0), + PLL_IDS_TO_ARR_ENTRY(ETH, DIV0), }, .pp_mux_table = { 5, 7, 8, 9, 10, }, .pp_count = 5, .pp_chg_id = INT_MIN, }, @@ -751,8 +842,9 @@ static const struct { { .n = "pit64b4_gclk", .id = 74, .r = { .max = 200000000 }, - .pp = { "syspll_divpmcck", "imgpll_divpmcck", "baudpll_divpmcck", - "audiopll_divpmcck", "ethpll_divpmcck", }, + .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(IMG, DIV0), + PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0), + PLL_IDS_TO_ARR_ENTRY(ETH, DIV0), }, .pp_mux_table = { 5, 7, 8, 9, 10, }, .pp_count = 5, .pp_chg_id = INT_MIN, }, @@ -760,8 +852,9 @@ static const struct { { .n = "pit64b5_gclk", .id = 75, .r = { .max = 200000000 }, - .pp = { "syspll_divpmcck", "imgpll_divpmcck", "baudpll_divpmcck", - "audiopll_divpmcck", "ethpll_divpmcck", }, + .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(IMG, DIV0), + PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0), + PLL_IDS_TO_ARR_ENTRY(ETH, DIV0), }, .pp_mux_table = { 5, 7, 8, 9, 10, }, .pp_count = 5, .pp_chg_id = INT_MIN, }, @@ -769,7 +862,7 @@ static const struct { { .n = "qspi0_gclk", .id = 78, .r = { .max = 200000000 }, - .pp = { "syspll_divpmcck", "baudpll_divpmcck", }, + .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), }, .pp_mux_table = { 5, 8, }, .pp_count = 2, .pp_chg_id = INT_MIN, }, @@ -777,7 +870,7 @@ static const struct { { .n = "qspi1_gclk", .id = 79, .r = { .max = 200000000 }, - .pp = { "syspll_divpmcck", "baudpll_divpmcck", }, + .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), }, .pp_mux_table = { 5, 8, }, .pp_count = 2, .pp_chg_id = INT_MIN, }, @@ -785,7 +878,7 @@ static const struct { { .n = "sdmmc0_gclk", .id = 80, .r = { .max = 208000000 }, - .pp = { "syspll_divpmcck", "baudpll_divpmcck", }, + .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), }, .pp_mux_table = { 5, 8, }, .pp_count = 2, .pp_chg_id = 4, }, @@ -793,7 +886,7 @@ static const struct { { .n = "sdmmc1_gclk", .id = 81, .r = { .max = 208000000 }, - .pp = { "syspll_divpmcck", "baudpll_divpmcck", }, + .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), }, .pp_mux_table = { 5, 8, }, .pp_count = 2, .pp_chg_id = 4, }, @@ -801,7 +894,7 @@ static const struct { { .n = "sdmmc2_gclk", .id = 82, .r = { .max = 208000000 }, - .pp = { "syspll_divpmcck", "baudpll_divpmcck", }, + .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), }, .pp_mux_table = { 5, 8, }, .pp_count = 2, .pp_chg_id = 4, }, @@ -809,7 +902,7 @@ static const struct { { .n = "spdifrx_gclk", .id = 84, .r = { .max = 150000000 }, - .pp = { "syspll_divpmcck", "audiopll_divpmcck", }, + .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0), }, .pp_mux_table = { 5, 9, }, .pp_count = 2, .pp_chg_id = 4, }, @@ -817,7 +910,7 @@ static const struct { { .n = "spdiftx_gclk", .id = 85, .r = { .max = 25000000 }, - .pp = { "syspll_divpmcck", "audiopll_divpmcck", }, + .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0), }, .pp_mux_table = { 5, 9, }, .pp_count = 2, .pp_chg_id = 4, }, @@ -825,8 +918,9 @@ static const struct { { .n = "tcb0_ch0_gclk", .id = 88, .r = { .max = 200000000 }, - .pp = { "syspll_divpmcck", "imgpll_divpmcck", "baudpll_divpmcck", - "audiopll_divpmcck", "ethpll_divpmcck", }, + .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(IMG, DIV0), + PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0), + PLL_IDS_TO_ARR_ENTRY(ETH, DIV0), }, .pp_mux_table = { 5, 7, 8, 9, 10, }, .pp_count = 5, .pp_chg_id = INT_MIN, }, @@ -834,8 +928,9 @@ static const struct { { .n = "tcb1_ch0_gclk", .id = 91, .r = { .max = 200000000 }, - .pp = { "syspll_divpmcck", "imgpll_divpmcck", "baudpll_divpmcck", - "audiopll_divpmcck", "ethpll_divpmcck", }, + .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(IMG, DIV0), + PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0), + PLL_IDS_TO_ARR_ENTRY(ETH, DIV0), }, .pp_mux_table = { 5, 7, 8, 9, 10, }, .pp_count = 5, .pp_chg_id = INT_MIN, }, @@ -884,34 +979,25 @@ static const struct clk_pcr_layout sama7g5_pcr_layout = { static void __init sama7g5_pmc_setup(struct device_node *np) { - const char *td_slck_name, *md_slck_name, *mainxtal_name; + const char *main_xtal_name = "main_xtal"; struct pmc_data *sama7g5_pmc; - const char *parent_names[10]; void **alloc_mem = NULL; int alloc_mem_size = 0; struct regmap *regmap; - struct clk_hw *hw; + struct clk_hw *hw, *main_rc_hw, *main_osc_hw, *main_xtal_hw; + struct clk_hw *td_slck_hw, *md_slck_hw; + static struct clk_parent_data parent_data; + struct clk_hw *parent_hws[10]; bool bypass; int i, j; - i = of_property_match_string(np, "clock-names", "td_slck"); - if (i < 0) - return; - - td_slck_name = of_clk_get_parent_name(np, i); - - i = of_property_match_string(np, "clock-names", "md_slck"); - if (i < 0) - return; - - md_slck_name = of_clk_get_parent_name(np, i); + td_slck_hw = __clk_get_hw(of_clk_get_by_name(np, "td_slck")); + md_slck_hw = __clk_get_hw(of_clk_get_by_name(np, "md_slck")); + main_xtal_hw = __clk_get_hw(of_clk_get_by_name(np, main_xtal_name)); - i = of_property_match_string(np, "clock-names", "main_xtal"); - if (i < 0) + if (!td_slck_hw || !md_slck_hw || !main_xtal_hw) return; - mainxtal_name = of_clk_get_parent_name(np, i); - regmap = device_node_to_regmap(np); if (IS_ERR(regmap)) return; @@ -929,21 +1015,23 @@ static void __init sama7g5_pmc_setup(struct device_node *np) if (!alloc_mem) goto err_free; - hw = at91_clk_register_main_rc_osc(regmap, "main_rc_osc", 12000000, - 50000000); - if (IS_ERR(hw)) + main_rc_hw = at91_clk_register_main_rc_osc(regmap, "main_rc_osc", 12000000, + 50000000); + if (IS_ERR(main_rc_hw)) goto err_free; bypass = of_property_read_bool(np, "atmel,osc-bypass"); - hw = at91_clk_register_main_osc(regmap, "main_osc", mainxtal_name, - bypass); - if (IS_ERR(hw)) + parent_data.name = main_xtal_name; + parent_data.fw_name = main_xtal_name; + main_osc_hw = at91_clk_register_main_osc(regmap, "main_osc", NULL, + &parent_data, bypass); + if (IS_ERR(main_osc_hw)) goto err_free; - parent_names[0] = "main_rc_osc"; - parent_names[1] = "main_osc"; - hw = at91_clk_register_sam9x5_main(regmap, "mainck", parent_names, 2); + parent_hws[0] = main_rc_hw; + parent_hws[1] = main_osc_hw; + hw = at91_clk_register_sam9x5_main(regmap, "mainck", NULL, parent_hws, 2); if (IS_ERR(hw)) goto err_free; @@ -958,15 +1046,22 @@ static void __init sama7g5_pmc_setup(struct device_node *np) switch (sama7g5_plls[i][j].t) { case PLL_TYPE_FRAC: - if (!strcmp(sama7g5_plls[i][j].p, "mainck")) + switch (sama7g5_plls[i][j].p) { + case SAMA7G5_PLL_PARENT_MAINCK: parent_hw = sama7g5_pmc->chws[PMC_MAIN]; - else - parent_hw = __clk_get_hw(of_clk_get_by_name(np, - sama7g5_plls[i][j].p)); + break; + case SAMA7G5_PLL_PARENT_MAIN_XTAL: + parent_hw = main_xtal_hw; + break; + default: + /* Should not happen. */ + parent_hw = NULL; + break; + } hw = sam9x60_clk_register_frac_pll(regmap, &pmc_pll_lock, sama7g5_plls[i][j].n, - sama7g5_plls[i][j].p, parent_hw, i, + NULL, parent_hw, i, sama7g5_plls[i][j].c, sama7g5_plls[i][j].l, sama7g5_plls[i][j].f); @@ -975,7 +1070,7 @@ static void __init sama7g5_pmc_setup(struct device_node *np) case PLL_TYPE_DIV: hw = sam9x60_clk_register_div_pll(regmap, &pmc_pll_lock, sama7g5_plls[i][j].n, - sama7g5_plls[i][j].p, i, + NULL, sama7g5_plls[i][0].hw, i, sama7g5_plls[i][j].c, sama7g5_plls[i][j].l, sama7g5_plls[i][j].f, @@ -989,25 +1084,27 @@ static void __init sama7g5_pmc_setup(struct device_node *np) if (IS_ERR(hw)) goto err_free; + sama7g5_plls[i][j].hw = hw; if (sama7g5_plls[i][j].eid) sama7g5_pmc->chws[sama7g5_plls[i][j].eid] = hw; } } - parent_names[0] = "cpupll_divpmcck"; - hw = at91_clk_register_master_div(regmap, "mck0", "cpupll_divpmcck", + hw = at91_clk_register_master_div(regmap, "mck0", NULL, + sama7g5_plls[PLL_ID_CPU][1].hw, &mck0_layout, &mck0_characteristics, &pmc_mck0_lock, CLK_GET_RATE_NOCACHE, 5); if (IS_ERR(hw)) goto err_free; - sama7g5_pmc->chws[PMC_MCK] = hw; + sama7g5_mckx[PCK_PARENT_HW_MCK0].hw = sama7g5_pmc->chws[PMC_MCK] = hw; - parent_names[0] = md_slck_name; - parent_names[1] = td_slck_name; - parent_names[2] = "mainck"; - for (i = 0; i < ARRAY_SIZE(sama7g5_mckx); i++) { + parent_hws[0] = md_slck_hw; + parent_hws[1] = td_slck_hw; + parent_hws[2] = sama7g5_pmc->chws[PMC_MAIN]; + for (i = PCK_PARENT_HW_MCK1; i < ARRAY_SIZE(sama7g5_mckx); i++) { u8 num_parents = 3 + sama7g5_mckx[i].ep_count; + struct clk_hw *tmp_parent_hws[8]; u32 *mux_table; mux_table = kmalloc_array(num_parents, sizeof(*mux_table), @@ -1018,11 +1115,17 @@ static void __init sama7g5_pmc_setup(struct device_node *np) SAMA7G5_INIT_TABLE(mux_table, 3); SAMA7G5_FILL_TABLE(&mux_table[3], sama7g5_mckx[i].ep_mux_table, sama7g5_mckx[i].ep_count); - SAMA7G5_FILL_TABLE(&parent_names[3], sama7g5_mckx[i].ep, + for (j = 0; j < sama7g5_mckx[i].ep_count; j++) { + u8 pll_id = sama7g5_mckx[i].ep[j].pll_id; + u8 pll_compid = sama7g5_mckx[i].ep[j].pll_compid; + + tmp_parent_hws[j] = sama7g5_plls[pll_id][pll_compid].hw; + } + SAMA7G5_FILL_TABLE(&parent_hws[3], tmp_parent_hws, sama7g5_mckx[i].ep_count); hw = at91_clk_sama7g5_register_master(regmap, sama7g5_mckx[i].n, - num_parents, parent_names, mux_table, + num_parents, NULL, parent_hws, mux_table, &pmc_mckX_lock, sama7g5_mckx[i].id, sama7g5_mckx[i].c, sama7g5_mckx[i].ep_chg_id); @@ -1031,31 +1134,32 @@ static void __init sama7g5_pmc_setup(struct device_node *np) alloc_mem[alloc_mem_size++] = mux_table; + sama7g5_mckx[i].hw = hw; if (sama7g5_mckx[i].eid) sama7g5_pmc->chws[sama7g5_mckx[i].eid] = hw; } - hw = at91_clk_sama7g5_register_utmi(regmap, "utmick", "main_xtal"); + hw = at91_clk_sama7g5_register_utmi(regmap, "utmick", NULL, main_xtal_hw); if (IS_ERR(hw)) goto err_free; sama7g5_pmc->chws[PMC_UTMI] = hw; - parent_names[0] = md_slck_name; - parent_names[1] = td_slck_name; - parent_names[2] = "mainck"; - parent_names[3] = "syspll_divpmcck"; - parent_names[4] = "ddrpll_divpmcck"; - parent_names[5] = "imgpll_divpmcck"; - parent_names[6] = "baudpll_divpmcck"; - parent_names[7] = "audiopll_divpmcck"; - parent_names[8] = "ethpll_divpmcck"; + parent_hws[0] = md_slck_hw; + parent_hws[1] = td_slck_hw; + parent_hws[2] = sama7g5_pmc->chws[PMC_MAIN]; + parent_hws[3] = sama7g5_plls[PLL_ID_SYS][PLL_COMPID_DIV0].hw; + parent_hws[4] = sama7g5_plls[PLL_ID_DDR][PLL_COMPID_DIV0].hw; + parent_hws[5] = sama7g5_plls[PLL_ID_IMG][PLL_COMPID_DIV0].hw; + parent_hws[6] = sama7g5_plls[PLL_ID_BAUD][PLL_COMPID_DIV0].hw; + parent_hws[7] = sama7g5_plls[PLL_ID_AUDIO][PLL_COMPID_DIV0].hw; + parent_hws[8] = sama7g5_plls[PLL_ID_ETH][PLL_COMPID_DIV0].hw; for (i = 0; i < 8; i++) { char name[6]; snprintf(name, sizeof(name), "prog%d", i); - hw = at91_clk_register_programmable(regmap, name, parent_names, + hw = at91_clk_register_programmable(regmap, name, NULL, parent_hws, 9, i, &programmable_layout, sama7g5_prog_mux_table); @@ -1067,7 +1171,7 @@ static void __init sama7g5_pmc_setup(struct device_node *np) for (i = 0; i < ARRAY_SIZE(sama7g5_systemck); i++) { hw = at91_clk_register_system(regmap, sama7g5_systemck[i].n, - sama7g5_systemck[i].p, + NULL, sama7g5_pmc->pchws[i], sama7g5_systemck[i].id, 0); if (IS_ERR(hw)) goto err_free; @@ -1079,7 +1183,8 @@ static void __init sama7g5_pmc_setup(struct device_node *np) hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock, &sama7g5_pcr_layout, sama7g5_periphck[i].n, - sama7g5_periphck[i].p, + NULL, + sama7g5_mckx[sama7g5_periphck[i].p].hw, sama7g5_periphck[i].id, &sama7g5_periphck[i].r, sama7g5_periphck[i].chgp ? 0 : @@ -1090,11 +1195,12 @@ static void __init sama7g5_pmc_setup(struct device_node *np) sama7g5_pmc->phws[sama7g5_periphck[i].id] = hw; } - parent_names[0] = md_slck_name; - parent_names[1] = td_slck_name; - parent_names[2] = "mainck"; + parent_hws[0] = md_slck_hw; + parent_hws[1] = td_slck_hw; + parent_hws[2] = sama7g5_pmc->chws[PMC_MAIN]; for (i = 0; i < ARRAY_SIZE(sama7g5_gck); i++) { u8 num_parents = 3 + sama7g5_gck[i].pp_count; + struct clk_hw *tmp_parent_hws[8]; u32 *mux_table; mux_table = kmalloc_array(num_parents, sizeof(*mux_table), @@ -1105,13 +1211,19 @@ static void __init sama7g5_pmc_setup(struct device_node *np) SAMA7G5_INIT_TABLE(mux_table, 3); SAMA7G5_FILL_TABLE(&mux_table[3], sama7g5_gck[i].pp_mux_table, sama7g5_gck[i].pp_count); - SAMA7G5_FILL_TABLE(&parent_names[3], sama7g5_gck[i].pp, + for (j = 0; j < sama7g5_gck[i].pp_count; j++) { + u8 pll_id = sama7g5_gck[i].pp[j].pll_id; + u8 pll_compid = sama7g5_gck[i].pp[j].pll_compid; + + tmp_parent_hws[j] = sama7g5_plls[pll_id][pll_compid].hw; + } + SAMA7G5_FILL_TABLE(&parent_hws[3], tmp_parent_hws, sama7g5_gck[i].pp_count); hw = at91_clk_register_generated(regmap, &pmc_pcr_lock, &sama7g5_pcr_layout, - sama7g5_gck[i].n, - parent_names, mux_table, + sama7g5_gck[i].n, NULL, + parent_hws, mux_table, num_parents, sama7g5_gck[i].id, &sama7g5_gck[i].r, diff --git a/drivers/clk/at91/sckc.c b/drivers/clk/at91/sckc.c index fdc9b669f8a7af22f12e7c08cf98a02182533875..7741d8f3dbee9b8df3dbb155eef99e224a66c0a3 100644 --- a/drivers/clk/at91/sckc.c +++ b/drivers/clk/at91/sckc.c @@ -117,17 +117,17 @@ static const struct clk_ops slow_osc_ops = { static struct clk_hw * __init at91_clk_register_slow_osc(void __iomem *sckcr, const char *name, - const char *parent_name, + const struct clk_parent_data *parent_data, unsigned long startup, bool bypass, const struct clk_slow_bits *bits) { struct clk_slow_osc *osc; struct clk_hw *hw; - struct clk_init_data init; + struct clk_init_data init = {}; int ret; - if (!sckcr || !name || !parent_name) + if (!sckcr || !name || !parent_data) return ERR_PTR(-EINVAL); osc = kzalloc(sizeof(*osc), GFP_KERNEL); @@ -136,7 +136,7 @@ at91_clk_register_slow_osc(void __iomem *sckcr, init.name = name; init.ops = &slow_osc_ops; - init.parent_names = &parent_name; + init.parent_data = parent_data; init.num_parents = 1; init.flags = CLK_IGNORE_UNUSED; @@ -310,6 +310,7 @@ static u8 clk_sam9x5_slow_get_parent(struct clk_hw *hw) } static const struct clk_ops sam9x5_slow_ops = { + .determine_rate = clk_hw_determine_rate_no_reparent, .set_parent = clk_sam9x5_slow_set_parent, .get_parent = clk_sam9x5_slow_get_parent, }; @@ -317,16 +318,16 @@ static const struct clk_ops sam9x5_slow_ops = { static struct clk_hw * __init at91_clk_register_sam9x5_slow(void __iomem *sckcr, const char *name, - const char **parent_names, + const struct clk_hw **parent_hws, int num_parents, const struct clk_slow_bits *bits) { struct clk_sam9x5_slow *slowck; struct clk_hw *hw; - struct clk_init_data init; + struct clk_init_data init = {}; int ret; - if (!sckcr || !name || !parent_names || !num_parents) + if (!sckcr || !name || !parent_hws || !num_parents) return ERR_PTR(-EINVAL); slowck = kzalloc(sizeof(*slowck), GFP_KERNEL); @@ -335,7 +336,7 @@ at91_clk_register_sam9x5_slow(void __iomem *sckcr, init.name = name; init.ops = &sam9x5_slow_ops; - init.parent_names = parent_names; + init.parent_hws = parent_hws; init.num_parents = num_parents; init.flags = 0; @@ -366,18 +367,21 @@ static void __init at91sam9x5_sckc_register(struct device_node *np, unsigned int rc_osc_startup_us, const struct clk_slow_bits *bits) { - const char *parent_names[2] = { "slow_rc_osc", "slow_osc" }; void __iomem *regbase = of_iomap(np, 0); struct device_node *child = NULL; const char *xtal_name; struct clk_hw *slow_rc, *slow_osc, *slowck; + static struct clk_parent_data parent_data = { + .name = "slow_xtal", + }; + const struct clk_hw *parent_hws[2]; bool bypass; int ret; if (!regbase) return; - slow_rc = at91_clk_register_slow_rc_osc(regbase, parent_names[0], + slow_rc = at91_clk_register_slow_rc_osc(regbase, "slow_rc_osc", 32768, 50000000, rc_osc_startup_us, bits); if (IS_ERR(slow_rc)) @@ -401,12 +405,16 @@ static void __init at91sam9x5_sckc_register(struct device_node *np, if (!xtal_name) goto unregister_slow_rc; - slow_osc = at91_clk_register_slow_osc(regbase, parent_names[1], - xtal_name, 1200000, bypass, bits); + parent_data.fw_name = xtal_name; + + slow_osc = at91_clk_register_slow_osc(regbase, "slow_osc", + &parent_data, 1200000, bypass, bits); if (IS_ERR(slow_osc)) goto unregister_slow_rc; - slowck = at91_clk_register_sam9x5_slow(regbase, "slowck", parent_names, + parent_hws[0] = slow_rc; + parent_hws[1] = slow_osc; + slowck = at91_clk_register_sam9x5_slow(regbase, "slowck", parent_hws, 2, bits); if (IS_ERR(slowck)) goto unregister_slow_osc; @@ -464,14 +472,17 @@ static void __init of_sam9x60_sckc_setup(struct device_node *np) struct clk_hw_onecell_data *clk_data; struct clk_hw *slow_rc, *slow_osc; const char *xtal_name; - const char *parent_names[2] = { "slow_rc_osc", "slow_osc" }; + const struct clk_hw *parent_hws[2]; + static struct clk_parent_data parent_data = { + .name = "slow_xtal", + }; bool bypass; int ret; if (!regbase) return; - slow_rc = clk_hw_register_fixed_rate_with_accuracy(NULL, parent_names[0], + slow_rc = clk_hw_register_fixed_rate_with_accuracy(NULL, "slow_rc_osc", NULL, 0, 32768, 93750000); if (IS_ERR(slow_rc)) @@ -481,9 +492,10 @@ static void __init of_sam9x60_sckc_setup(struct device_node *np) if (!xtal_name) goto unregister_slow_rc; + parent_data.fw_name = xtal_name; bypass = of_property_read_bool(np, "atmel,osc-bypass"); - slow_osc = at91_clk_register_slow_osc(regbase, parent_names[1], - xtal_name, 5000000, bypass, + slow_osc = at91_clk_register_slow_osc(regbase, "slow_osc", + &parent_data, 5000000, bypass, &at91sam9x60_bits); if (IS_ERR(slow_osc)) goto unregister_slow_rc; @@ -494,14 +506,16 @@ static void __init of_sam9x60_sckc_setup(struct device_node *np) /* MD_SLCK and TD_SLCK. */ clk_data->num = 2; - clk_data->hws[0] = clk_hw_register_fixed_rate(NULL, "md_slck", - parent_names[0], - 0, 32768); + clk_data->hws[0] = clk_hw_register_fixed_rate_parent_hw(NULL, "md_slck", + slow_rc, + 0, 32768); if (IS_ERR(clk_data->hws[0])) goto clk_data_free; + parent_hws[0] = slow_rc; + parent_hws[1] = slow_osc; clk_data->hws[1] = at91_clk_register_sam9x5_slow(regbase, "td_slck", - parent_names, 2, + parent_hws, 2, &at91sam9x60_bits); if (IS_ERR(clk_data->hws[1])) goto unregister_md_slck; @@ -572,30 +586,36 @@ static void __init of_sama5d4_sckc_setup(struct device_node *np) void __iomem *regbase = of_iomap(np, 0); struct clk_hw *slow_rc, *slowck; struct clk_sama5d4_slow_osc *osc; - struct clk_init_data init; + struct clk_init_data init = {}; const char *xtal_name; - const char *parent_names[2] = { "slow_rc_osc", "slow_osc" }; + const struct clk_hw *parent_hws[2]; + static struct clk_parent_data parent_data = { + .name = "slow_xtal", + }; int ret; if (!regbase) return; slow_rc = clk_hw_register_fixed_rate_with_accuracy(NULL, - parent_names[0], + "slow_rc_osc", NULL, 0, 32768, 250000000); if (IS_ERR(slow_rc)) return; xtal_name = of_clk_get_parent_name(np, 0); + if (!xtal_name) + goto unregister_slow_rc; + parent_data.fw_name = xtal_name; osc = kzalloc(sizeof(*osc), GFP_KERNEL); if (!osc) goto unregister_slow_rc; - init.name = parent_names[1]; + init.name = "slow_osc"; init.ops = &sama5d4_slow_osc_ops; - init.parent_names = &xtal_name; + init.parent_data = &parent_data; init.num_parents = 1; init.flags = CLK_IGNORE_UNUSED; @@ -608,8 +628,10 @@ static void __init of_sama5d4_sckc_setup(struct device_node *np) if (ret) goto free_slow_osc_data; + parent_hws[0] = slow_rc; + parent_hws[1] = &osc->hw; slowck = at91_clk_register_sam9x5_slow(regbase, "slowck", - parent_names, 2, + parent_hws, 2, &at91sama5d4_bits); if (IS_ERR(slowck)) goto unregister_slow_osc; diff --git a/drivers/clk/bcm/clk-raspberrypi.c b/drivers/clk/bcm/clk-raspberrypi.c index eb399a4d141ba24b5656064b3799765666acad7c..829406dc44a20247afee4512a96960e93e76d812 100644 --- a/drivers/clk/bcm/clk-raspberrypi.c +++ b/drivers/clk/bcm/clk-raspberrypi.c @@ -356,9 +356,9 @@ static int raspberrypi_discover_clocks(struct raspberrypi_clk *rpi, while (clks->id) { struct raspberrypi_clk_variant *variant; - if (clks->id > RPI_FIRMWARE_NUM_CLK_ID) { + if (clks->id >= RPI_FIRMWARE_NUM_CLK_ID) { dev_err(rpi->dev, "Unknown clock id: %u (max: %u)\n", - clks->id, RPI_FIRMWARE_NUM_CLK_ID); + clks->id, RPI_FIRMWARE_NUM_CLK_ID - 1); return -EINVAL; } diff --git a/drivers/clk/berlin/berlin2-div.c b/drivers/clk/berlin/berlin2-div.c index eb14a5bc050723561cf4f771d0f8558135b078db..0a248bfe2193dbf49de089c00797257134681fe3 100644 --- a/drivers/clk/berlin/berlin2-div.c +++ b/drivers/clk/berlin/berlin2-div.c @@ -210,6 +210,7 @@ static unsigned long berlin2_div_recalc_rate(struct clk_hw *hw, } static const struct clk_ops berlin2_div_rate_ops = { + .determine_rate = clk_hw_determine_rate_no_reparent, .recalc_rate = berlin2_div_recalc_rate, }; diff --git a/drivers/clk/clk-axi-clkgen.c b/drivers/clk/clk-axi-clkgen.c index a04a3d38c76eac478cdede0173767512e07d7461..bf4d8ddc93aea1d4509a9ae50fa69fdb3f707a29 100644 --- a/drivers/clk/clk-axi-clkgen.c +++ b/drivers/clk/clk-axi-clkgen.c @@ -384,23 +384,25 @@ static int axi_clkgen_set_rate(struct clk_hw *clk_hw, return 0; } -static long axi_clkgen_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *parent_rate) +static int axi_clkgen_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) { struct axi_clkgen *axi_clkgen = clk_hw_to_axi_clkgen(hw); const struct axi_clkgen_limits *limits = &axi_clkgen->limits; unsigned int d, m, dout; unsigned long long tmp; - axi_clkgen_calc_params(limits, *parent_rate, rate, &d, &m, &dout); + axi_clkgen_calc_params(limits, req->best_parent_rate, req->rate, + &d, &m, &dout); if (d == 0 || dout == 0 || m == 0) return -EINVAL; - tmp = (unsigned long long)*parent_rate * m; + tmp = (unsigned long long)req->best_parent_rate * m; tmp = DIV_ROUND_CLOSEST_ULL(tmp, dout * d); - return min_t(unsigned long long, tmp, LONG_MAX); + req->rate = min_t(unsigned long long, tmp, LONG_MAX); + return 0; } static unsigned int axi_clkgen_get_div(struct axi_clkgen *axi_clkgen, @@ -495,7 +497,7 @@ static u8 axi_clkgen_get_parent(struct clk_hw *clk_hw) static const struct clk_ops axi_clkgen_ops = { .recalc_rate = axi_clkgen_recalc_rate, - .round_rate = axi_clkgen_round_rate, + .determine_rate = axi_clkgen_determine_rate, .set_rate = axi_clkgen_set_rate, .enable = axi_clkgen_enable, .disable = axi_clkgen_disable, diff --git a/drivers/clk/clk-cdce706.c b/drivers/clk/clk-cdce706.c index d8bee8180a6b37946f47aea6fdae986779b8a62c..dd3d42d9ad8670ef644544a29415db21f82a355d 100644 --- a/drivers/clk/clk-cdce706.c +++ b/drivers/clk/clk-cdce706.c @@ -155,6 +155,7 @@ static u8 cdce706_clkin_get_parent(struct clk_hw *hw) } static const struct clk_ops cdce706_clkin_ops = { + .determine_rate = clk_hw_determine_rate_no_reparent, .set_parent = cdce706_clkin_set_parent, .get_parent = cdce706_clkin_get_parent, }; @@ -287,18 +288,19 @@ static unsigned long cdce706_divider_recalc_rate(struct clk_hw *hw, return 0; } -static long cdce706_divider_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *parent_rate) +static int cdce706_divider_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) { struct cdce706_hw_data *hwd = to_hw_data(hw); struct cdce706_dev_data *cdce = hwd->dev_data; + unsigned long rate = req->rate; unsigned long mul, div; dev_dbg(&hwd->dev_data->client->dev, "%s, rate: %lu, parent_rate: %lu\n", - __func__, rate, *parent_rate); + __func__, rate, req->best_parent_rate); - rational_best_approximation(rate, *parent_rate, + rational_best_approximation(rate, req->best_parent_rate, 1, CDCE706_DIVIDER_DIVIDER_MAX, &mul, &div); if (!mul) @@ -343,8 +345,8 @@ static long cdce706_divider_round_rate(struct clk_hw *hw, unsigned long rate, dev_dbg(&hwd->dev_data->client->dev, "%s, altering parent rate: %lu -> %lu\n", - __func__, *parent_rate, rate * div); - *parent_rate = rate * div; + __func__, req->best_parent_rate, rate * div); + req->best_parent_rate = rate * div; } hwd->div = div; @@ -352,7 +354,8 @@ static long cdce706_divider_round_rate(struct clk_hw *hw, unsigned long rate, "%s, divider: %d, div: %lu\n", __func__, hwd->idx, div); - return *parent_rate / div; + req->rate = req->best_parent_rate / div; + return 0; } static int cdce706_divider_set_rate(struct clk_hw *hw, unsigned long rate, @@ -374,7 +377,7 @@ static const struct clk_ops cdce706_divider_ops = { .set_parent = cdce706_divider_set_parent, .get_parent = cdce706_divider_get_parent, .recalc_rate = cdce706_divider_recalc_rate, - .round_rate = cdce706_divider_round_rate, + .determine_rate = cdce706_divider_determine_rate, .set_rate = cdce706_divider_set_rate, }; @@ -420,11 +423,12 @@ static unsigned long cdce706_clkout_recalc_rate(struct clk_hw *hw, return parent_rate; } -static long cdce706_clkout_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *parent_rate) +static int cdce706_clkout_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) { - *parent_rate = rate; - return rate; + req->best_parent_rate = req->rate; + + return 0; } static int cdce706_clkout_set_rate(struct clk_hw *hw, unsigned long rate, @@ -439,7 +443,7 @@ static const struct clk_ops cdce706_clkout_ops = { .set_parent = cdce706_clkout_set_parent, .get_parent = cdce706_clkout_get_parent, .recalc_rate = cdce706_clkout_recalc_rate, - .round_rate = cdce706_clkout_round_rate, + .determine_rate = cdce706_clkout_determine_rate, .set_rate = cdce706_clkout_set_rate, }; @@ -684,7 +688,7 @@ static struct i2c_driver cdce706_i2c_driver = { .name = "cdce706", .of_match_table = of_match_ptr(cdce706_dt_match), }, - .probe_new = cdce706_probe, + .probe = cdce706_probe, .id_table = cdce706_id, }; module_i2c_driver(cdce706_i2c_driver); diff --git a/drivers/clk/clk-cdce925.c b/drivers/clk/clk-cdce925.c index 6350682f7e6d23d7035c6cc1a83f30d413678ebc..96ac90364847ebbae550d2dd2519c27d55ce187d 100644 --- a/drivers/clk/clk-cdce925.c +++ b/drivers/clk/clk-cdce925.c @@ -701,6 +701,10 @@ static int cdce925_probe(struct i2c_client *client) for (i = 0; i < data->chip_info->num_plls; ++i) { pll_clk_name[i] = kasprintf(GFP_KERNEL, "%pOFn.pll%d", client->dev.of_node, i); + if (!pll_clk_name[i]) { + err = -ENOMEM; + goto error; + } init.name = pll_clk_name[i]; data->pll[i].chip = data; data->pll[i].hw.init = &init; @@ -742,6 +746,10 @@ static int cdce925_probe(struct i2c_client *client) init.num_parents = 1; init.parent_names = &parent_name; /* Mux Y1 to input */ init.name = kasprintf(GFP_KERNEL, "%pOFn.Y1", client->dev.of_node); + if (!init.name) { + err = -ENOMEM; + goto error; + } data->clk[0].chip = data; data->clk[0].hw.init = &init; data->clk[0].index = 0; @@ -760,6 +768,10 @@ static int cdce925_probe(struct i2c_client *client) for (i = 1; i < data->chip_info->num_outputs; ++i) { init.name = kasprintf(GFP_KERNEL, "%pOFn.Y%d", client->dev.of_node, i+1); + if (!init.name) { + err = -ENOMEM; + goto error; + } data->clk[i].chip = data; data->clk[i].hw.init = &init; data->clk[i].index = i; @@ -824,7 +836,7 @@ static struct i2c_driver cdce925_driver = { .name = "cdce925", .of_match_table = of_match_ptr(clk_cdce925_of_match), }, - .probe_new = cdce925_probe, + .probe = cdce925_probe, .id_table = cdce925_id, }; module_i2c_driver(cdce925_driver); diff --git a/drivers/clk/clk-cs2000-cp.c b/drivers/clk/clk-cs2000-cp.c index 320d39922206ad470071ab9267b7025a3fb3e735..b82fee6a3d6f01b605e470976995a21a60710937 100644 --- a/drivers/clk/clk-cs2000-cp.c +++ b/drivers/clk/clk-cs2000-cp.c @@ -622,7 +622,7 @@ static struct i2c_driver cs2000_driver = { .pm = &cs2000_pm_ops, .of_match_table = cs2000_of_match, }, - .probe_new = cs2000_probe, + .probe = cs2000_probe, .remove = cs2000_remove, .id_table = cs2000_id, }; diff --git a/drivers/clk/clk-k210.c b/drivers/clk/clk-k210.c index 4eed667eddaf25b4e3bd974ade93a0243109bf6a..870adac5cdeeefaeb552d4f407e3142178480f62 100644 --- a/drivers/clk/clk-k210.c +++ b/drivers/clk/clk-k210.c @@ -537,6 +537,7 @@ static const struct clk_ops k210_pll2_ops = { .disable = k210_pll_disable, .is_enabled = k210_pll_is_enabled, .recalc_rate = k210_pll_get_rate, + .determine_rate = clk_hw_determine_rate_no_reparent, .set_parent = k210_pll2_set_parent, .get_parent = k210_pll2_get_parent, }; @@ -635,6 +636,7 @@ static unsigned long k210_aclk_get_rate(struct clk_hw *hw, } static const struct clk_ops k210_aclk_ops = { + .determine_rate = clk_hw_determine_rate_no_reparent, .set_parent = k210_aclk_set_parent, .get_parent = k210_aclk_get_parent, .recalc_rate = k210_aclk_get_rate, @@ -774,6 +776,7 @@ static unsigned long k210_clk_get_rate(struct clk_hw *hw, static const struct clk_ops k210_clk_mux_ops = { .enable = k210_clk_enable, .disable = k210_clk_disable, + .determine_rate = clk_hw_determine_rate_no_reparent, .set_parent = k210_clk_set_parent, .get_parent = k210_clk_get_parent, .recalc_rate = k210_clk_get_rate, diff --git a/drivers/clk/clk-lan966x.c b/drivers/clk/clk-lan966x.c index 460e7216bfa1ee19a32f448a3c4d0431dcfba30d..870fd7df50c1f0d5f4a28e6d68cfe02ae0031421 100644 --- a/drivers/clk/clk-lan966x.c +++ b/drivers/clk/clk-lan966x.c @@ -103,22 +103,6 @@ static int lan966x_gck_set_rate(struct clk_hw *hw, return 0; } -static long lan966x_gck_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *parent_rate) -{ - unsigned int div; - - if (rate == 0 || *parent_rate == 0) - return -EINVAL; - - if (rate >= *parent_rate) - return *parent_rate; - - div = DIV_ROUND_CLOSEST(*parent_rate, rate); - - return *parent_rate / div; -} - static unsigned long lan966x_gck_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { @@ -177,7 +161,6 @@ static const struct clk_ops lan966x_gck_ops = { .enable = lan966x_gck_enable, .disable = lan966x_gck_disable, .set_rate = lan966x_gck_set_rate, - .round_rate = lan966x_gck_round_rate, .recalc_rate = lan966x_gck_recalc_rate, .determine_rate = lan966x_gck_determine_rate, .set_parent = lan966x_gck_set_parent, diff --git a/drivers/clk/clk-lmk04832.c b/drivers/clk/clk-lmk04832.c index afdfee3b365f35f7d7766a879460a91b1a3c592d..e22ac93e0c2f0bfe1ac45f8e11a6c5d48087f9db 100644 --- a/drivers/clk/clk-lmk04832.c +++ b/drivers/clk/clk-lmk04832.c @@ -1279,6 +1279,7 @@ static const struct clk_ops lmk04832_clkout_ops = { .is_enabled = lmk04832_clkout_is_enabled, .prepare = lmk04832_clkout_prepare, .unprepare = lmk04832_clkout_unprepare, + .determine_rate = __clk_mux_determine_rate, .set_parent = lmk04832_clkout_set_parent, .get_parent = lmk04832_clkout_get_parent, }; diff --git a/drivers/clk/clk-lochnagar.c b/drivers/clk/clk-lochnagar.c index 80944bf482e9a85e0957b6ccca600677926d44f6..db468a62c8d71b1c9472918cce71a04afed7384a 100644 --- a/drivers/clk/clk-lochnagar.c +++ b/drivers/clk/clk-lochnagar.c @@ -209,6 +209,7 @@ static u8 lochnagar_clk_get_parent(struct clk_hw *hw) static const struct clk_ops lochnagar_clk_ops = { .prepare = lochnagar_clk_prepare, .unprepare = lochnagar_clk_unprepare, + .determine_rate = clk_hw_determine_rate_no_reparent, .set_parent = lochnagar_clk_set_parent, .get_parent = lochnagar_clk_get_parent, }; diff --git a/drivers/clk/clk-max9485.c b/drivers/clk/clk-max9485.c index 5f85b0a32872ae4887d0bffdc32e30fbb76f4659..be9020b6c789642e6d63065aa905088e01929147 100644 --- a/drivers/clk/clk-max9485.c +++ b/drivers/clk/clk-max9485.c @@ -376,7 +376,7 @@ static struct i2c_driver max9485_driver = { .pm = &max9485_pm_ops, .of_match_table = max9485_dt_ids, }, - .probe_new = max9485_i2c_probe, + .probe = max9485_i2c_probe, .id_table = max9485_i2c_ids, }; module_i2c_driver(max9485_driver); diff --git a/drivers/clk/clk-qoriq.c b/drivers/clk/clk-qoriq.c index 5eddb9f0d6bdb3993b3319e30baddfc12165eb15..e3386fd98c5e27c4aface40ec7a428de6ae1647c 100644 --- a/drivers/clk/clk-qoriq.c +++ b/drivers/clk/clk-qoriq.c @@ -878,6 +878,7 @@ static u8 mux_get_parent(struct clk_hw *hw) } static const struct clk_ops cmux_ops = { + .determine_rate = clk_hw_determine_rate_no_reparent, .get_parent = mux_get_parent, .set_parent = mux_set_parent, }; diff --git a/drivers/clk/clk-renesas-pcie.c b/drivers/clk/clk-renesas-pcie.c index 10d31c222a1cb428c3b4e3077adba7193e759c9f..7d7b2cb7531804dcd777bea0249fdae693891579 100644 --- a/drivers/clk/clk-renesas-pcie.c +++ b/drivers/clk/clk-renesas-pcie.c @@ -392,8 +392,8 @@ static const struct rs9_chip_info renesas_9fgv0441_info = { }; static const struct i2c_device_id rs9_id[] = { - { "9fgv0241", .driver_data = RENESAS_9FGV0241 }, - { "9fgv0441", .driver_data = RENESAS_9FGV0441 }, + { "9fgv0241", .driver_data = (kernel_ulong_t)&renesas_9fgv0241_info }, + { "9fgv0441", .driver_data = (kernel_ulong_t)&renesas_9fgv0441_info }, { } }; MODULE_DEVICE_TABLE(i2c, rs9_id); @@ -413,7 +413,7 @@ static struct i2c_driver rs9_driver = { .pm = &rs9_pm_ops, .of_match_table = clk_rs9_of_match, }, - .probe_new = rs9_probe, + .probe = rs9_probe, .id_table = rs9_id, }; module_i2c_driver(rs9_driver); diff --git a/drivers/clk/clk-rk808.c b/drivers/clk/clk-rk808.c index 32f833d732ed5655fdcd7419ea626cc2fa04654d..f7412b137e5ef4766254729621e9ce82eae29cb1 100644 --- a/drivers/clk/clk-rk808.c +++ b/drivers/clk/clk-rk808.c @@ -12,10 +12,9 @@ #include #include #include -#include struct rk808_clkout { - struct rk808 *rk808; + struct regmap *regmap; struct clk_hw clkout1_hw; struct clk_hw clkout2_hw; }; @@ -31,9 +30,8 @@ static int rk808_clkout2_enable(struct clk_hw *hw, bool enable) struct rk808_clkout *rk808_clkout = container_of(hw, struct rk808_clkout, clkout2_hw); - struct rk808 *rk808 = rk808_clkout->rk808; - return regmap_update_bits(rk808->regmap, RK808_CLK32OUT_REG, + return regmap_update_bits(rk808_clkout->regmap, RK808_CLK32OUT_REG, CLK32KOUT2_EN, enable ? CLK32KOUT2_EN : 0); } @@ -52,10 +50,9 @@ static int rk808_clkout2_is_prepared(struct clk_hw *hw) struct rk808_clkout *rk808_clkout = container_of(hw, struct rk808_clkout, clkout2_hw); - struct rk808 *rk808 = rk808_clkout->rk808; uint32_t val; - int ret = regmap_read(rk808->regmap, RK808_CLK32OUT_REG, &val); + int ret = regmap_read(rk808_clkout->regmap, RK808_CLK32OUT_REG, &val); if (ret < 0) return ret; @@ -93,9 +90,8 @@ static int rk817_clkout2_enable(struct clk_hw *hw, bool enable) struct rk808_clkout *rk808_clkout = container_of(hw, struct rk808_clkout, clkout2_hw); - struct rk808 *rk808 = rk808_clkout->rk808; - return regmap_update_bits(rk808->regmap, RK817_SYS_CFG(1), + return regmap_update_bits(rk808_clkout->regmap, RK817_SYS_CFG(1), RK817_CLK32KOUT2_EN, enable ? RK817_CLK32KOUT2_EN : 0); } @@ -115,10 +111,9 @@ static int rk817_clkout2_is_prepared(struct clk_hw *hw) struct rk808_clkout *rk808_clkout = container_of(hw, struct rk808_clkout, clkout2_hw); - struct rk808 *rk808 = rk808_clkout->rk808; unsigned int val; - int ret = regmap_read(rk808->regmap, RK817_SYS_CFG(1), &val); + int ret = regmap_read(rk808_clkout->regmap, RK817_SYS_CFG(1), &val); if (ret < 0) return 0; @@ -153,18 +148,21 @@ static const struct clk_ops *rkpmic_get_ops(long variant) static int rk808_clkout_probe(struct platform_device *pdev) { struct rk808 *rk808 = dev_get_drvdata(pdev->dev.parent); - struct i2c_client *client = rk808->i2c; - struct device_node *node = client->dev.of_node; + struct device *dev = &pdev->dev; struct clk_init_data init = {}; struct rk808_clkout *rk808_clkout; int ret; - rk808_clkout = devm_kzalloc(&client->dev, + dev->of_node = pdev->dev.parent->of_node; + + rk808_clkout = devm_kzalloc(dev, sizeof(*rk808_clkout), GFP_KERNEL); if (!rk808_clkout) return -ENOMEM; - rk808_clkout->rk808 = rk808; + rk808_clkout->regmap = dev_get_regmap(pdev->dev.parent, NULL); + if (!rk808_clkout->regmap) + return -ENODEV; init.parent_names = NULL; init.num_parents = 0; @@ -173,10 +171,10 @@ static int rk808_clkout_probe(struct platform_device *pdev) rk808_clkout->clkout1_hw.init = &init; /* optional override of the clockname */ - of_property_read_string_index(node, "clock-output-names", + of_property_read_string_index(dev->of_node, "clock-output-names", 0, &init.name); - ret = devm_clk_hw_register(&client->dev, &rk808_clkout->clkout1_hw); + ret = devm_clk_hw_register(dev, &rk808_clkout->clkout1_hw); if (ret) return ret; @@ -185,10 +183,10 @@ static int rk808_clkout_probe(struct platform_device *pdev) rk808_clkout->clkout2_hw.init = &init; /* optional override of the clockname */ - of_property_read_string_index(node, "clock-output-names", + of_property_read_string_index(dev->of_node, "clock-output-names", 1, &init.name); - ret = devm_clk_hw_register(&client->dev, &rk808_clkout->clkout2_hw); + ret = devm_clk_hw_register(dev, &rk808_clkout->clkout2_hw); if (ret) return ret; diff --git a/drivers/clk/clk-si514.c b/drivers/clk/clk-si514.c index cabdd8e8f4dbd2855418668c56c00a9d4e486d18..e8c18afac18412b46cf381765421e198427e5fe5 100644 --- a/drivers/clk/clk-si514.c +++ b/drivers/clk/clk-si514.c @@ -387,7 +387,7 @@ static struct i2c_driver si514_driver = { .name = "si514", .of_match_table = clk_si514_of_match, }, - .probe_new = si514_probe, + .probe = si514_probe, .id_table = si514_id, }; module_i2c_driver(si514_driver); diff --git a/drivers/clk/clk-si521xx.c b/drivers/clk/clk-si521xx.c index ac8d4c59cd3d873f0e532c572752e17e6641cc43..4eaf1b53f06bd78950f584d7a991e6253f671cc8 100644 --- a/drivers/clk/clk-si521xx.c +++ b/drivers/clk/clk-si521xx.c @@ -385,7 +385,7 @@ static struct i2c_driver si521xx_driver = { .pm = &si521xx_pm_ops, .of_match_table = clk_si521xx_of_match, }, - .probe_new = si521xx_probe, + .probe = si521xx_probe, .id_table = si521xx_id, }; module_i2c_driver(si521xx_driver); diff --git a/drivers/clk/clk-si5341.c b/drivers/clk/clk-si5341.c index 0e528d7ba656ee82a49ed352fdf4bde2086c9a3c..9599857842c72c77c69590bc0bae983fb55bdb61 100644 --- a/drivers/clk/clk-si5341.c +++ b/drivers/clk/clk-si5341.c @@ -551,6 +551,7 @@ static int si5341_clk_set_parent(struct clk_hw *hw, u8 index) } static const struct clk_ops si5341_clk_ops = { + .determine_rate = clk_hw_determine_rate_no_reparent, .set_parent = si5341_clk_set_parent, .get_parent = si5341_clk_get_parent, .recalc_rate = si5341_clk_recalc_rate, @@ -827,19 +828,20 @@ static unsigned long si5341_output_clk_recalc_rate(struct clk_hw *hw, return parent_rate / r_divider; } -static long si5341_output_clk_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *parent_rate) +static int si5341_output_clk_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) { + unsigned long rate = req->rate; unsigned long r; if (!rate) return 0; - r = *parent_rate >> 1; + r = req->best_parent_rate >> 1; /* If rate is an even divisor, no changes to parent required */ if (r && !(r % rate)) - return (long)rate; + return 0; if (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) { if (rate > 200000000) { @@ -849,14 +851,15 @@ static long si5341_output_clk_round_rate(struct clk_hw *hw, unsigned long rate, /* Take a parent frequency near 400 MHz */ r = (400000000u / rate) & ~1; } - *parent_rate = r * rate; + req->best_parent_rate = r * rate; } else { /* We cannot change our parent's rate, report what we can do */ r /= rate; - rate = *parent_rate / (r << 1); + rate = req->best_parent_rate / (r << 1); } - return rate; + req->rate = rate; + return 0; } static int si5341_output_clk_set_rate(struct clk_hw *hw, unsigned long rate, @@ -929,7 +932,7 @@ static const struct clk_ops si5341_output_clk_ops = { .prepare = si5341_output_clk_prepare, .unprepare = si5341_output_clk_unprepare, .recalc_rate = si5341_output_clk_recalc_rate, - .round_rate = si5341_output_clk_round_rate, + .determine_rate = si5341_output_clk_determine_rate, .set_rate = si5341_output_clk_set_rate, .set_parent = si5341_output_set_parent, .get_parent = si5341_output_get_parent, @@ -1553,7 +1556,7 @@ static int si5341_probe(struct i2c_client *client) struct clk_init_data init; struct clk *input; const char *root_clock_name; - const char *synth_clock_names[SI5341_NUM_SYNTH]; + const char *synth_clock_names[SI5341_NUM_SYNTH] = { NULL }; int err; unsigned int i; struct clk_si5341_output_config config[SI5341_MAX_NUM_OUTPUTS]; @@ -1697,6 +1700,10 @@ static int si5341_probe(struct i2c_client *client) for (i = 0; i < data->num_synth; ++i) { synth_clock_names[i] = devm_kasprintf(&client->dev, GFP_KERNEL, "%s.N%u", client->dev.of_node->name, i); + if (!synth_clock_names[i]) { + err = -ENOMEM; + goto free_clk_names; + } init.name = synth_clock_names[i]; data->synth[i].index = i; data->synth[i].data = data; @@ -1705,6 +1712,7 @@ static int si5341_probe(struct i2c_client *client) if (err) { dev_err(&client->dev, "synth N%u registration failed\n", i); + goto free_clk_names; } } @@ -1714,6 +1722,10 @@ static int si5341_probe(struct i2c_client *client) for (i = 0; i < data->num_outputs; ++i) { init.name = kasprintf(GFP_KERNEL, "%s.%d", client->dev.of_node->name, i); + if (!init.name) { + err = -ENOMEM; + goto free_clk_names; + } init.flags = config[i].synth_master ? CLK_SET_RATE_PARENT : 0; data->clk[i].index = i; data->clk[i].data = data; @@ -1735,7 +1747,7 @@ static int si5341_probe(struct i2c_client *client) if (err) { dev_err(&client->dev, "output %u registration failed\n", i); - goto cleanup; + goto free_clk_names; } if (config[i].always_on) clk_prepare(data->clk[i].hw.clk); @@ -1745,7 +1757,7 @@ static int si5341_probe(struct i2c_client *client) data); if (err) { dev_err(&client->dev, "unable to add clk provider\n"); - goto cleanup; + goto free_clk_names; } if (initialization_required) { @@ -1753,11 +1765,11 @@ static int si5341_probe(struct i2c_client *client) regcache_cache_only(data->regmap, false); err = regcache_sync(data->regmap); if (err < 0) - goto cleanup; + goto free_clk_names; err = si5341_finalize_defaults(data); if (err < 0) - goto cleanup; + goto free_clk_names; } /* wait for device to report input clock present and PLL lock */ @@ -1766,32 +1778,31 @@ static int si5341_probe(struct i2c_client *client) 10000, 250000); if (err) { dev_err(&client->dev, "Error waiting for input clock or PLL lock\n"); - goto cleanup; + goto free_clk_names; } /* clear sticky alarm bits from initialization */ err = regmap_write(data->regmap, SI5341_STATUS_STICKY, 0); if (err) { dev_err(&client->dev, "unable to clear sticky status\n"); - goto cleanup; + goto free_clk_names; } err = sysfs_create_files(&client->dev.kobj, si5341_attributes); - if (err) { + if (err) dev_err(&client->dev, "unable to create sysfs files\n"); - goto cleanup; - } +free_clk_names: /* Free the names, clk framework makes copies */ for (i = 0; i < data->num_synth; ++i) devm_kfree(&client->dev, (void *)synth_clock_names[i]); - return 0; - cleanup: - for (i = 0; i < SI5341_MAX_NUM_OUTPUTS; ++i) { - if (data->clk[i].vddo_reg) - regulator_disable(data->clk[i].vddo_reg); + if (err) { + for (i = 0; i < SI5341_MAX_NUM_OUTPUTS; ++i) { + if (data->clk[i].vddo_reg) + regulator_disable(data->clk[i].vddo_reg); + } } return err; } @@ -1834,7 +1845,7 @@ static struct i2c_driver si5341_driver = { .name = "si5341", .of_match_table = clk_si5341_of_match, }, - .probe_new = si5341_probe, + .probe = si5341_probe, .remove = si5341_remove, .id_table = si5341_id, }; diff --git a/drivers/clk/clk-si5351.c b/drivers/clk/clk-si5351.c index 4fcf7056717e9a98fc7f6fab40222a88429e7f94..31c3c8a71f127cc934437c69f8a6760b9d9eb0e2 100644 --- a/drivers/clk/clk-si5351.c +++ b/drivers/clk/clk-si5351.c @@ -442,11 +442,12 @@ static unsigned long si5351_pll_recalc_rate(struct clk_hw *hw, return (unsigned long)rate; } -static long si5351_pll_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *parent_rate) +static int si5351_pll_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) { struct si5351_hw_data *hwdata = container_of(hw, struct si5351_hw_data, hw); + unsigned long rate = req->rate; unsigned long rfrac, denom, a, b, c; unsigned long long lltmp; @@ -456,18 +457,18 @@ static long si5351_pll_round_rate(struct clk_hw *hw, unsigned long rate, rate = SI5351_PLL_VCO_MAX; /* determine integer part of feedback equation */ - a = rate / *parent_rate; + a = rate / req->best_parent_rate; if (a < SI5351_PLL_A_MIN) - rate = *parent_rate * SI5351_PLL_A_MIN; + rate = req->best_parent_rate * SI5351_PLL_A_MIN; if (a > SI5351_PLL_A_MAX) - rate = *parent_rate * SI5351_PLL_A_MAX; + rate = req->best_parent_rate * SI5351_PLL_A_MAX; /* find best approximation for b/c = fVCO mod fIN */ denom = 1000 * 1000; - lltmp = rate % (*parent_rate); + lltmp = rate % (req->best_parent_rate); lltmp *= denom; - do_div(lltmp, *parent_rate); + do_div(lltmp, req->best_parent_rate); rfrac = (unsigned long)lltmp; b = 0; @@ -484,19 +485,20 @@ static long si5351_pll_round_rate(struct clk_hw *hw, unsigned long rate, hwdata->params.p1 -= 512; /* recalculate rate by fIN * (a + b/c) */ - lltmp = *parent_rate; + lltmp = req->best_parent_rate; lltmp *= b; do_div(lltmp, c); rate = (unsigned long)lltmp; - rate += *parent_rate * a; + rate += req->best_parent_rate * a; dev_dbg(&hwdata->drvdata->client->dev, "%s - %s: a = %lu, b = %lu, c = %lu, parent_rate = %lu, rate = %lu\n", __func__, clk_hw_get_name(hw), a, b, c, - *parent_rate, rate); + req->best_parent_rate, rate); - return rate; + req->rate = rate; + return 0; } static int si5351_pll_set_rate(struct clk_hw *hw, unsigned long rate, @@ -533,7 +535,7 @@ static const struct clk_ops si5351_pll_ops = { .set_parent = si5351_pll_set_parent, .get_parent = si5351_pll_get_parent, .recalc_rate = si5351_pll_recalc_rate, - .round_rate = si5351_pll_round_rate, + .determine_rate = si5351_pll_determine_rate, .set_rate = si5351_pll_set_rate, }; @@ -640,11 +642,12 @@ static unsigned long si5351_msynth_recalc_rate(struct clk_hw *hw, return (unsigned long)rate; } -static long si5351_msynth_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *parent_rate) +static int si5351_msynth_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) { struct si5351_hw_data *hwdata = container_of(hw, struct si5351_hw_data, hw); + unsigned long rate = req->rate; unsigned long long lltmp; unsigned long a, b, c; int divby4; @@ -679,10 +682,10 @@ static long si5351_msynth_round_rate(struct clk_hw *hw, unsigned long rate, b = 0; c = 1; - *parent_rate = a * rate; + req->best_parent_rate = a * rate; } else if (hwdata->num >= 6) { /* determine the closest integer divider */ - a = DIV_ROUND_CLOSEST(*parent_rate, rate); + a = DIV_ROUND_CLOSEST(req->best_parent_rate, rate); if (a < SI5351_MULTISYNTH_A_MIN) a = SI5351_MULTISYNTH_A_MIN; if (a > SI5351_MULTISYNTH67_A_MAX) @@ -700,7 +703,7 @@ static long si5351_msynth_round_rate(struct clk_hw *hw, unsigned long rate, } /* determine integer part of divider equation */ - a = *parent_rate / rate; + a = req->best_parent_rate / rate; if (a < SI5351_MULTISYNTH_A_MIN) a = SI5351_MULTISYNTH_A_MIN; if (a > SI5351_MULTISYNTH_A_MAX) @@ -708,7 +711,7 @@ static long si5351_msynth_round_rate(struct clk_hw *hw, unsigned long rate, /* find best approximation for b/c = fVCO mod fOUT */ denom = 1000 * 1000; - lltmp = (*parent_rate) % rate; + lltmp = req->best_parent_rate % rate; lltmp *= denom; do_div(lltmp, rate); rfrac = (unsigned long)lltmp; @@ -722,7 +725,7 @@ static long si5351_msynth_round_rate(struct clk_hw *hw, unsigned long rate, } /* recalculate rate by fOUT = fIN / (a + b/c) */ - lltmp = *parent_rate; + lltmp = req->best_parent_rate; lltmp *= c; do_div(lltmp, a * c + b); rate = (unsigned long)lltmp; @@ -747,9 +750,11 @@ static long si5351_msynth_round_rate(struct clk_hw *hw, unsigned long rate, dev_dbg(&hwdata->drvdata->client->dev, "%s - %s: a = %lu, b = %lu, c = %lu, divby4 = %d, parent_rate = %lu, rate = %lu\n", __func__, clk_hw_get_name(hw), a, b, c, divby4, - *parent_rate, rate); + req->best_parent_rate, rate); - return rate; + req->rate = rate; + + return 0; } static int si5351_msynth_set_rate(struct clk_hw *hw, unsigned long rate, @@ -789,7 +794,7 @@ static const struct clk_ops si5351_msynth_ops = { .set_parent = si5351_msynth_set_parent, .get_parent = si5351_msynth_get_parent, .recalc_rate = si5351_msynth_recalc_rate, - .round_rate = si5351_msynth_round_rate, + .determine_rate = si5351_msynth_determine_rate, .set_rate = si5351_msynth_set_rate, }; @@ -1032,11 +1037,12 @@ static unsigned long si5351_clkout_recalc_rate(struct clk_hw *hw, return parent_rate >> rdiv; } -static long si5351_clkout_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *parent_rate) +static int si5351_clkout_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) { struct si5351_hw_data *hwdata = container_of(hw, struct si5351_hw_data, hw); + unsigned long rate = req->rate; unsigned char rdiv; /* clkout6/7 can only handle output freqencies < 150MHz */ @@ -1058,13 +1064,13 @@ static long si5351_clkout_round_rate(struct clk_hw *hw, unsigned long rate, rdiv += 1; rate *= 2; } - *parent_rate = rate; + req->best_parent_rate = rate; } else { unsigned long new_rate, new_err, err; /* round to closed rdiv */ rdiv = SI5351_OUTPUT_CLK_DIV_1; - new_rate = *parent_rate; + new_rate = req->best_parent_rate; err = abs(new_rate - rate); do { new_rate >>= 1; @@ -1075,14 +1081,15 @@ static long si5351_clkout_round_rate(struct clk_hw *hw, unsigned long rate, err = new_err; } while (1); } - rate = *parent_rate >> rdiv; + rate = req->best_parent_rate >> rdiv; dev_dbg(&hwdata->drvdata->client->dev, "%s - %s: rdiv = %u, parent_rate = %lu, rate = %lu\n", __func__, clk_hw_get_name(hw), (1 << rdiv), - *parent_rate, rate); + req->best_parent_rate, rate); - return rate; + req->rate = rate; + return 0; } static int si5351_clkout_set_rate(struct clk_hw *hw, unsigned long rate, @@ -1142,7 +1149,7 @@ static const struct clk_ops si5351_clkout_ops = { .set_parent = si5351_clkout_set_parent, .get_parent = si5351_clkout_get_parent, .recalc_rate = si5351_clkout_recalc_rate, - .round_rate = si5351_clkout_round_rate, + .determine_rate = si5351_clkout_determine_rate, .set_rate = si5351_clkout_set_rate, }; @@ -1656,7 +1663,7 @@ static struct i2c_driver si5351_driver = { .name = "si5351", .of_match_table = of_match_ptr(si5351_dt_ids), }, - .probe_new = si5351_i2c_probe, + .probe = si5351_i2c_probe, .id_table = si5351_i2c_ids, }; module_i2c_driver(si5351_driver); diff --git a/drivers/clk/clk-si544.c b/drivers/clk/clk-si544.c index 089786907641ebd8aa3256c261c9c6af1f199714..22925968aa35537c67c844e36588d7f180bb34d1 100644 --- a/drivers/clk/clk-si544.c +++ b/drivers/clk/clk-si544.c @@ -520,7 +520,7 @@ static struct i2c_driver si544_driver = { .name = "si544", .of_match_table = clk_si544_of_match, }, - .probe_new = si544_probe, + .probe = si544_probe, .id_table = si544_id, }; module_i2c_driver(si544_driver); diff --git a/drivers/clk/clk-si570.c b/drivers/clk/clk-si570.c index 0b834e9efb4bc2d1473451655c27870ddb782e61..de0212fb5f879a681a02dc3888cc3dda4a7b5adb 100644 --- a/drivers/clk/clk-si570.c +++ b/drivers/clk/clk-si570.c @@ -510,7 +510,7 @@ static struct i2c_driver si570_driver = { .name = "si570", .of_match_table = clk_si570_of_match, }, - .probe_new = si570_probe, + .probe = si570_probe, .id_table = si570_id, }; module_i2c_driver(si570_driver); diff --git a/drivers/clk/clk-stm32f4.c b/drivers/clk/clk-stm32f4.c index 473dfe632cc5771c3f089a2b7d3f19e856666b12..07c13ebe327d5d3ea8c460fe8ff7cad4856b63db 100644 --- a/drivers/clk/clk-stm32f4.c +++ b/drivers/clk/clk-stm32f4.c @@ -1045,6 +1045,7 @@ static int cclk_mux_set_parent(struct clk_hw *hw, u8 index) } static const struct clk_ops cclk_mux_ops = { + .determine_rate = clk_hw_determine_rate_no_reparent, .get_parent = cclk_mux_get_parent, .set_parent = cclk_mux_set_parent, }; diff --git a/drivers/clk/clk-versaclock5.c b/drivers/clk/clk-versaclock5.c index fa71a57875ce8c0ca67c95b56b2576c8d31ea055..8bc54176f325459d5977bcb985107936f7a73692 100644 --- a/drivers/clk/clk-versaclock5.c +++ b/drivers/clk/clk-versaclock5.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -281,6 +282,7 @@ static int vc5_mux_set_parent(struct clk_hw *hw, u8 index) } static const struct clk_ops vc5_mux_ops = { + .determine_rate = clk_hw_determine_rate_no_reparent, .set_parent = vc5_mux_set_parent, .get_parent = vc5_mux_get_parent, }; @@ -725,6 +727,7 @@ static int vc5_clk_out_set_parent(struct clk_hw *hw, u8 index) static const struct clk_ops vc5_clk_out_ops = { .prepare = vc5_clk_out_prepare, .unprepare = vc5_clk_out_unprepare, + .determine_rate = clk_hw_determine_rate_no_reparent, .set_parent = vc5_clk_out_set_parent, .get_parent = vc5_clk_out_get_parent, }; @@ -953,7 +956,7 @@ static int vc5_probe(struct i2c_client *client) i2c_set_clientdata(client, vc5); vc5->client = client; - vc5->chip_info = of_device_get_match_data(&client->dev); + vc5->chip_info = device_get_match_data(&client->dev); vc5->pin_xin = devm_clk_get(&client->dev, "xin"); if (PTR_ERR(vc5->pin_xin) == -EPROBE_DEFER) @@ -1028,6 +1031,11 @@ static int vc5_probe(struct i2c_client *client) } init.name = kasprintf(GFP_KERNEL, "%pOFn.mux", client->dev.of_node); + if (!init.name) { + ret = -ENOMEM; + goto err_clk; + } + init.ops = &vc5_mux_ops; init.flags = 0; init.parent_names = parent_names; @@ -1042,6 +1050,10 @@ static int vc5_probe(struct i2c_client *client) memset(&init, 0, sizeof(init)); init.name = kasprintf(GFP_KERNEL, "%pOFn.dbl", client->dev.of_node); + if (!init.name) { + ret = -ENOMEM; + goto err_clk; + } init.ops = &vc5_dbl_ops; init.flags = CLK_SET_RATE_PARENT; init.parent_names = parent_names; @@ -1057,6 +1069,10 @@ static int vc5_probe(struct i2c_client *client) /* Register PFD */ memset(&init, 0, sizeof(init)); init.name = kasprintf(GFP_KERNEL, "%pOFn.pfd", client->dev.of_node); + if (!init.name) { + ret = -ENOMEM; + goto err_clk; + } init.ops = &vc5_pfd_ops; init.flags = CLK_SET_RATE_PARENT; init.parent_names = parent_names; @@ -1074,6 +1090,10 @@ static int vc5_probe(struct i2c_client *client) /* Register PLL */ memset(&init, 0, sizeof(init)); init.name = kasprintf(GFP_KERNEL, "%pOFn.pll", client->dev.of_node); + if (!init.name) { + ret = -ENOMEM; + goto err_clk; + } init.ops = &vc5_pll_ops; init.flags = CLK_SET_RATE_PARENT; init.parent_names = parent_names; @@ -1093,6 +1113,10 @@ static int vc5_probe(struct i2c_client *client) memset(&init, 0, sizeof(init)); init.name = kasprintf(GFP_KERNEL, "%pOFn.fod%d", client->dev.of_node, idx); + if (!init.name) { + ret = -ENOMEM; + goto err_clk; + } init.ops = &vc5_fod_ops; init.flags = CLK_SET_RATE_PARENT; init.parent_names = parent_names; @@ -1111,6 +1135,10 @@ static int vc5_probe(struct i2c_client *client) memset(&init, 0, sizeof(init)); init.name = kasprintf(GFP_KERNEL, "%pOFn.out0_sel_i2cb", client->dev.of_node); + if (!init.name) { + ret = -ENOMEM; + goto err_clk; + } init.ops = &vc5_clk_out_ops; init.flags = CLK_SET_RATE_PARENT; init.parent_names = parent_names; @@ -1137,6 +1165,10 @@ static int vc5_probe(struct i2c_client *client) memset(&init, 0, sizeof(init)); init.name = kasprintf(GFP_KERNEL, "%pOFn.out%d", client->dev.of_node, idx + 1); + if (!init.name) { + ret = -ENOMEM; + goto err_clk; + } init.ops = &vc5_clk_out_ops; init.flags = CLK_SET_RATE_PARENT; init.parent_names = parent_names; @@ -1271,14 +1303,14 @@ static const struct vc5_chip_info idt_5p49v6975_info = { }; static const struct i2c_device_id vc5_id[] = { - { "5p49v5923", .driver_data = IDT_VC5_5P49V5923 }, - { "5p49v5925", .driver_data = IDT_VC5_5P49V5925 }, - { "5p49v5933", .driver_data = IDT_VC5_5P49V5933 }, - { "5p49v5935", .driver_data = IDT_VC5_5P49V5935 }, - { "5p49v60", .driver_data = IDT_VC6_5P49V60 }, - { "5p49v6901", .driver_data = IDT_VC6_5P49V6901 }, - { "5p49v6965", .driver_data = IDT_VC6_5P49V6965 }, - { "5p49v6975", .driver_data = IDT_VC6_5P49V6975 }, + { "5p49v5923", .driver_data = (kernel_ulong_t)&idt_5p49v5923_info }, + { "5p49v5925", .driver_data = (kernel_ulong_t)&idt_5p49v5925_info }, + { "5p49v5933", .driver_data = (kernel_ulong_t)&idt_5p49v5933_info }, + { "5p49v5935", .driver_data = (kernel_ulong_t)&idt_5p49v5935_info }, + { "5p49v60", .driver_data = (kernel_ulong_t)&idt_5p49v60_info }, + { "5p49v6901", .driver_data = (kernel_ulong_t)&idt_5p49v6901_info }, + { "5p49v6965", .driver_data = (kernel_ulong_t)&idt_5p49v6965_info }, + { "5p49v6975", .driver_data = (kernel_ulong_t)&idt_5p49v6975_info }, { } }; MODULE_DEVICE_TABLE(i2c, vc5_id); @@ -1304,7 +1336,7 @@ static struct i2c_driver vc5_driver = { .pm = &vc5_pm_ops, .of_match_table = clk_vc5_of_match, }, - .probe_new = vc5_probe, + .probe = vc5_probe, .remove = vc5_remove, .id_table = vc5_id, }; diff --git a/drivers/clk/clk-versaclock7.c b/drivers/clk/clk-versaclock7.c index 8e4f86e852aa0963421db2c5a4e028cb9975aefa..9babb7913c1c398d903d23e210fbaf469357d1d5 100644 --- a/drivers/clk/clk-versaclock7.c +++ b/drivers/clk/clk-versaclock7.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -1108,7 +1109,7 @@ static int vc7_probe(struct i2c_client *client) i2c_set_clientdata(client, vc7); vc7->client = client; - vc7->chip_info = of_device_get_match_data(&client->dev); + vc7->chip_info = device_get_match_data(&client->dev); vc7->pin_xin = devm_clk_get(&client->dev, "xin"); if (PTR_ERR(vc7->pin_xin) == -EPROBE_DEFER) { @@ -1282,7 +1283,7 @@ static const struct regmap_config vc7_regmap_config = { }; static const struct i2c_device_id vc7_i2c_id[] = { - { "rc21008a", VC7_RC21008A }, + { "rc21008a", .driver_data = (kernel_ulong_t)&vc7_rc21008a_info }, {} }; MODULE_DEVICE_TABLE(i2c, vc7_i2c_id); @@ -1298,7 +1299,7 @@ static struct i2c_driver vc7_i2c_driver = { .name = "vc7", .of_match_table = vc7_of_match, }, - .probe_new = vc7_probe, + .probe = vc7_probe, .remove = vc7_remove, .id_table = vc7_i2c_id, }; diff --git a/drivers/clk/clk-wm831x.c b/drivers/clk/clk-wm831x.c index ae6dd38ec0537c7234718d5bfb22eea40855d738..34e9d4d541e25c1adf766b48333f11c2d5b219fb 100644 --- a/drivers/clk/clk-wm831x.c +++ b/drivers/clk/clk-wm831x.c @@ -329,6 +329,7 @@ static const struct clk_ops wm831x_clkout_ops = { .is_prepared = wm831x_clkout_is_prepared, .prepare = wm831x_clkout_prepare, .unprepare = wm831x_clkout_unprepare, + .determine_rate = clk_hw_determine_rate_no_reparent, .get_parent = wm831x_clkout_get_parent, .set_parent = wm831x_clkout_set_parent, }; diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 27c30a533759ad390b3576f8aceebe5a3c3bbfc9..c249f9791ae864c607aaf9db0a4557fd2adfb7d1 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -594,45 +594,59 @@ clk_core_forward_rate_req(struct clk_core *core, req->max_rate = old_req->max_rate; } -int clk_mux_determine_rate_flags(struct clk_hw *hw, - struct clk_rate_request *req, - unsigned long flags) +static int +clk_core_determine_rate_no_reparent(struct clk_hw *hw, + struct clk_rate_request *req) { - struct clk_core *core = hw->core, *parent, *best_parent = NULL; - int i, num_parents, ret; - unsigned long best = 0; - - /* if NO_REPARENT flag set, pass through to current parent */ - if (core->flags & CLK_SET_RATE_NO_REPARENT) { - parent = core->parent; - if (core->flags & CLK_SET_RATE_PARENT) { - struct clk_rate_request parent_req; + struct clk_core *core = hw->core; + struct clk_core *parent = core->parent; + unsigned long best; + int ret; - if (!parent) { - req->rate = 0; - return 0; - } + if (core->flags & CLK_SET_RATE_PARENT) { + struct clk_rate_request parent_req; - clk_core_forward_rate_req(core, req, parent, &parent_req, req->rate); + if (!parent) { + req->rate = 0; + return 0; + } - trace_clk_rate_request_start(&parent_req); + clk_core_forward_rate_req(core, req, parent, &parent_req, + req->rate); - ret = clk_core_round_rate_nolock(parent, &parent_req); - if (ret) - return ret; + trace_clk_rate_request_start(&parent_req); - trace_clk_rate_request_done(&parent_req); + ret = clk_core_round_rate_nolock(parent, &parent_req); + if (ret) + return ret; - best = parent_req.rate; - } else if (parent) { - best = clk_core_get_rate_nolock(parent); - } else { - best = clk_core_get_rate_nolock(core); - } + trace_clk_rate_request_done(&parent_req); - goto out; + best = parent_req.rate; + } else if (parent) { + best = clk_core_get_rate_nolock(parent); + } else { + best = clk_core_get_rate_nolock(core); } + req->best_parent_rate = best; + req->rate = best; + + return 0; +} + +int clk_mux_determine_rate_flags(struct clk_hw *hw, + struct clk_rate_request *req, + unsigned long flags) +{ + struct clk_core *core = hw->core, *parent, *best_parent = NULL; + int i, num_parents, ret; + unsigned long best = 0; + + /* if NO_REPARENT flag set, pass through to current parent */ + if (core->flags & CLK_SET_RATE_NO_REPARENT) + return clk_core_determine_rate_no_reparent(hw, req); + /* find the parent that can provide the fastest rate <= rate */ num_parents = core->num_parents; for (i = 0; i < num_parents; i++) { @@ -670,9 +684,7 @@ int clk_mux_determine_rate_flags(struct clk_hw *hw, if (!best_parent) return -EINVAL; -out: - if (best_parent) - req->best_parent_hw = best_parent->hw; + req->best_parent_hw = best_parent->hw; req->best_parent_rate = best; req->rate = best; @@ -772,6 +784,25 @@ int __clk_mux_determine_rate_closest(struct clk_hw *hw, } EXPORT_SYMBOL_GPL(__clk_mux_determine_rate_closest); +/* + * clk_hw_determine_rate_no_reparent - clk_ops::determine_rate implementation for a clk that doesn't reparent + * @hw: mux type clk to determine rate on + * @req: rate request, also used to return preferred frequency + * + * Helper for finding best parent rate to provide a given frequency. + * This can be used directly as a determine_rate callback (e.g. for a + * mux), or from a more complex clock that may combine a mux with other + * operations. + * + * Returns: 0 on success, -EERROR value on error + */ +int clk_hw_determine_rate_no_reparent(struct clk_hw *hw, + struct clk_rate_request *req) +{ + return clk_core_determine_rate_no_reparent(hw, req); +} +EXPORT_SYMBOL_GPL(clk_hw_determine_rate_no_reparent); + /*** clk api ***/ static void clk_core_rate_unprotect(struct clk_core *core) @@ -1549,6 +1580,7 @@ void clk_hw_forward_rate_request(const struct clk_hw *hw, parent->core, req, parent_rate); } +EXPORT_SYMBOL_GPL(clk_hw_forward_rate_request); static bool clk_core_can_round(struct clk_core * const core) { @@ -3745,6 +3777,13 @@ static int __clk_core_init(struct clk_core *core) goto out; } + if (core->ops->set_parent && !core->ops->determine_rate) { + pr_err("%s: %s must implement .set_parent & .determine_rate\n", + __func__, core->name); + ret = -EINVAL; + goto out; + } + if (core->num_parents > 1 && !core->ops->get_parent) { pr_err("%s: %s must implement .get_parent as it has multi parents\n", __func__, core->name); @@ -4301,11 +4340,18 @@ static int clk_nodrv_set_parent(struct clk_hw *hw, u8 index) return -ENXIO; } +static int clk_nodrv_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) +{ + return -ENXIO; +} + static const struct clk_ops clk_nodrv_ops = { .enable = clk_nodrv_prepare_enable, .disable = clk_nodrv_disable_unprepare, .prepare = clk_nodrv_prepare_enable, .unprepare = clk_nodrv_disable_unprepare, + .determine_rate = clk_nodrv_determine_rate, .set_rate = clk_nodrv_set_rate, .set_parent = clk_nodrv_set_parent, }; @@ -4695,6 +4741,7 @@ int devm_clk_notifier_register(struct device *dev, struct clk *clk, if (!ret) { devres->clk = clk; devres->nb = nb; + devres_add(dev, devres); } else { devres_free(devres); } diff --git a/drivers/clk/clk_test.c b/drivers/clk/clk_test.c index f9a5c2964c65dc17e97c0b2ba3c89fc0db285182..a154ec9d01111aafc9e0b79a45717399c424e44e 100644 --- a/drivers/clk/clk_test.c +++ b/drivers/clk/clk_test.c @@ -104,6 +104,23 @@ static const struct clk_ops clk_dummy_minimize_rate_ops = { }; static const struct clk_ops clk_dummy_single_parent_ops = { + /* + * FIXME: Even though we should probably be able to use + * __clk_mux_determine_rate() here, if we use it and call + * clk_round_rate() or clk_set_rate() with a rate lower than + * what all the parents can provide, it will return -EINVAL. + * + * This is due to the fact that it has the undocumented + * behaviour to always pick up the closest rate higher than the + * requested rate. If we get something lower, it thus considers + * that it's not acceptable and will return an error. + * + * It's somewhat inconsistent and creates a weird threshold + * between rates above the parent rate which would be rounded to + * what the parent can provide, but rates below will simply + * return an error. + */ + .determine_rate = __clk_mux_determine_rate_closest, .set_parent = clk_dummy_single_set_parent, .get_parent = clk_dummy_single_get_parent, }; @@ -141,6 +158,12 @@ static const struct clk_ops clk_multiple_parents_mux_ops = { .determine_rate = __clk_mux_determine_rate_closest, }; +static const struct clk_ops clk_multiple_parents_no_reparent_mux_ops = { + .determine_rate = clk_hw_determine_rate_no_reparent, + .get_parent = clk_multiple_parents_mux_get_parent, + .set_parent = clk_multiple_parents_mux_set_parent, +}; + static int clk_test_init_with_ops(struct kunit *test, const struct clk_ops *ops) { struct clk_dummy_context *ctx; @@ -266,7 +289,8 @@ static void clk_test_round_set_get_rate(struct kunit *test) struct clk_dummy_context *ctx = test->priv; struct clk_hw *hw = &ctx->hw; struct clk *clk = clk_hw_get_clk(hw, NULL); - unsigned long rounded_rate, set_rate; + unsigned long set_rate; + long rounded_rate; rounded_rate = clk_round_rate(clk, DUMMY_CLOCK_RATE_1); KUNIT_ASSERT_GT(test, rounded_rate, 0); @@ -851,7 +875,7 @@ clk_test_orphan_transparent_multiple_parent_mux_set_range_round_rate(struct kuni struct clk_multiple_parent_ctx *ctx = test->priv; struct clk_hw *hw = &ctx->hw; struct clk *clk = clk_hw_get_clk(hw, NULL); - unsigned long rate; + long rate; int ret; ret = clk_set_rate_range(clk, DUMMY_CLOCK_RATE_1, DUMMY_CLOCK_RATE_2); @@ -1090,7 +1114,7 @@ clk_test_single_parent_mux_set_range_round_rate_parent_only(struct kunit *test) struct clk_hw *hw = &ctx->hw; struct clk *clk = clk_hw_get_clk(hw, NULL); struct clk *parent; - unsigned long rate; + long rate; int ret; parent = clk_get_parent(clk); @@ -1120,7 +1144,7 @@ clk_test_single_parent_mux_set_range_round_rate_child_smaller(struct kunit *test struct clk_hw *hw = &ctx->hw; struct clk *clk = clk_hw_get_clk(hw, NULL); struct clk *parent; - unsigned long rate; + long rate; int ret; parent = clk_get_parent(clk); @@ -1158,7 +1182,7 @@ clk_test_single_parent_mux_set_range_round_rate_parent_smaller(struct kunit *tes struct clk_hw *hw = &ctx->hw; struct clk *clk = clk_hw_get_clk(hw, NULL); struct clk *parent; - unsigned long rate; + long rate; int ret; parent = clk_get_parent(clk); @@ -2394,10 +2418,156 @@ static struct kunit_suite clk_mux_notifier_test_suite = { .test_cases = clk_mux_notifier_test_cases, }; +static int +clk_mux_no_reparent_test_init(struct kunit *test) +{ + struct clk_multiple_parent_ctx *ctx; + const char *parents[2] = { "parent-0", "parent-1"}; + int ret; + + ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL); + if (!ctx) + return -ENOMEM; + test->priv = ctx; + + ctx->parents_ctx[0].hw.init = CLK_HW_INIT_NO_PARENT("parent-0", + &clk_dummy_rate_ops, + 0); + ctx->parents_ctx[0].rate = DUMMY_CLOCK_RATE_1; + ret = clk_hw_register(NULL, &ctx->parents_ctx[0].hw); + if (ret) + return ret; + + ctx->parents_ctx[1].hw.init = CLK_HW_INIT_NO_PARENT("parent-1", + &clk_dummy_rate_ops, + 0); + ctx->parents_ctx[1].rate = DUMMY_CLOCK_RATE_2; + ret = clk_hw_register(NULL, &ctx->parents_ctx[1].hw); + if (ret) + return ret; + + ctx->current_parent = 0; + ctx->hw.init = CLK_HW_INIT_PARENTS("test-mux", parents, + &clk_multiple_parents_no_reparent_mux_ops, + 0); + ret = clk_hw_register(NULL, &ctx->hw); + if (ret) + return ret; + + return 0; +} + +static void +clk_mux_no_reparent_test_exit(struct kunit *test) +{ + struct clk_multiple_parent_ctx *ctx = test->priv; + + clk_hw_unregister(&ctx->hw); + clk_hw_unregister(&ctx->parents_ctx[0].hw); + clk_hw_unregister(&ctx->parents_ctx[1].hw); +} + +/* + * Test that if the we have a mux that cannot change parent and we call + * clk_round_rate() on it with a rate that should cause it to change + * parent, it won't. + */ +static void clk_mux_no_reparent_round_rate(struct kunit *test) +{ + struct clk_multiple_parent_ctx *ctx = test->priv; + struct clk_hw *hw = &ctx->hw; + struct clk *clk = clk_hw_get_clk(hw, NULL); + struct clk *other_parent, *parent; + unsigned long other_parent_rate; + unsigned long parent_rate; + long rounded_rate; + + parent = clk_get_parent(clk); + KUNIT_ASSERT_PTR_NE(test, parent, NULL); + + parent_rate = clk_get_rate(parent); + KUNIT_ASSERT_GT(test, parent_rate, 0); + + other_parent = clk_hw_get_clk(&ctx->parents_ctx[1].hw, NULL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, other_parent); + KUNIT_ASSERT_FALSE(test, clk_is_match(parent, other_parent)); + + other_parent_rate = clk_get_rate(other_parent); + KUNIT_ASSERT_GT(test, other_parent_rate, 0); + clk_put(other_parent); + + rounded_rate = clk_round_rate(clk, other_parent_rate); + KUNIT_ASSERT_GT(test, rounded_rate, 0); + KUNIT_EXPECT_EQ(test, rounded_rate, parent_rate); + + clk_put(clk); +} + +/* + * Test that if the we have a mux that cannot change parent and we call + * clk_set_rate() on it with a rate that should cause it to change + * parent, it won't. + */ +static void clk_mux_no_reparent_set_rate(struct kunit *test) +{ + struct clk_multiple_parent_ctx *ctx = test->priv; + struct clk_hw *hw = &ctx->hw; + struct clk *clk = clk_hw_get_clk(hw, NULL); + struct clk *other_parent, *parent; + unsigned long other_parent_rate; + unsigned long parent_rate; + unsigned long rate; + int ret; + + parent = clk_get_parent(clk); + KUNIT_ASSERT_PTR_NE(test, parent, NULL); + + parent_rate = clk_get_rate(parent); + KUNIT_ASSERT_GT(test, parent_rate, 0); + + other_parent = clk_hw_get_clk(&ctx->parents_ctx[1].hw, NULL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, other_parent); + KUNIT_ASSERT_FALSE(test, clk_is_match(parent, other_parent)); + + other_parent_rate = clk_get_rate(other_parent); + KUNIT_ASSERT_GT(test, other_parent_rate, 0); + clk_put(other_parent); + + ret = clk_set_rate(clk, other_parent_rate); + KUNIT_ASSERT_EQ(test, ret, 0); + + rate = clk_get_rate(clk); + KUNIT_ASSERT_GT(test, rate, 0); + KUNIT_EXPECT_EQ(test, rate, parent_rate); + + clk_put(clk); +} + +static struct kunit_case clk_mux_no_reparent_test_cases[] = { + KUNIT_CASE(clk_mux_no_reparent_round_rate), + KUNIT_CASE(clk_mux_no_reparent_set_rate), + {} +}; + +/* + * Test suite for a clock mux that isn't allowed to change parent, using + * the clk_hw_determine_rate_no_reparent() helper. + * + * These tests exercise that helper, and the proper selection of + * rates and parents. + */ +static struct kunit_suite clk_mux_no_reparent_test_suite = { + .name = "clk-mux-no-reparent", + .init = clk_mux_no_reparent_test_init, + .exit = clk_mux_no_reparent_test_exit, + .test_cases = clk_mux_no_reparent_test_cases, +}; + kunit_test_suites( &clk_leaf_mux_set_rate_parent_test_suite, &clk_test_suite, &clk_multiple_parents_mux_test_suite, + &clk_mux_no_reparent_test_suite, &clk_mux_notifier_test_suite, &clk_orphan_transparent_multiple_parent_mux_test_suite, &clk_orphan_transparent_single_parent_test_suite, diff --git a/drivers/clk/davinci/da8xx-cfgchip.c b/drivers/clk/davinci/da8xx-cfgchip.c index 4103d605e804fced5cd6bf325b6ce6674fa96a95..e5b2cdfe88ce18c5267304ef90ad6f4da6b320b3 100644 --- a/drivers/clk/davinci/da8xx-cfgchip.c +++ b/drivers/clk/davinci/da8xx-cfgchip.c @@ -229,6 +229,7 @@ static u8 da8xx_cfgchip_mux_clk_get_parent(struct clk_hw *hw) } static const struct clk_ops da8xx_cfgchip_mux_clk_ops = { + .determine_rate = clk_hw_determine_rate_no_reparent, .set_parent = da8xx_cfgchip_mux_clk_set_parent, .get_parent = da8xx_cfgchip_mux_clk_get_parent, }; @@ -461,10 +462,12 @@ static unsigned long da8xx_usb0_clk48_recalc_rate(struct clk_hw *hw, return 48000000; } -static long da8xx_usb0_clk48_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *parent_rate) +static int da8xx_usb0_clk48_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) { - return 48000000; + req->rate = 48000000; + + return 0; } static int da8xx_usb0_clk48_set_parent(struct clk_hw *hw, u8 index) @@ -493,7 +496,7 @@ static const struct clk_ops da8xx_usb0_clk48_ops = { .disable = da8xx_usb0_clk48_disable, .is_enabled = da8xx_usb0_clk48_is_enabled, .recalc_rate = da8xx_usb0_clk48_recalc_rate, - .round_rate = da8xx_usb0_clk48_round_rate, + .determine_rate = da8xx_usb0_clk48_determine_rate, .set_parent = da8xx_usb0_clk48_set_parent, .get_parent = da8xx_usb0_clk48_get_parent, }; @@ -564,6 +567,7 @@ static u8 da8xx_usb1_clk48_get_parent(struct clk_hw *hw) } static const struct clk_ops da8xx_usb1_clk48_ops = { + .determine_rate = clk_hw_determine_rate_no_reparent, .set_parent = da8xx_usb1_clk48_set_parent, .get_parent = da8xx_usb1_clk48_get_parent, }; diff --git a/drivers/clk/imx/clk-busy.c b/drivers/clk/imx/clk-busy.c index 6f17311647f3544de611bf0e382498aa34150f36..f163df952ccc65baf300b62048f4303b0050fd75 100644 --- a/drivers/clk/imx/clk-busy.c +++ b/drivers/clk/imx/clk-busy.c @@ -148,6 +148,7 @@ static int clk_busy_mux_set_parent(struct clk_hw *hw, u8 index) } static const struct clk_ops clk_busy_mux_ops = { + .determine_rate = clk_hw_determine_rate_no_reparent, .get_parent = clk_busy_mux_get_parent, .set_parent = clk_busy_mux_set_parent, }; diff --git a/drivers/clk/imx/clk-composite-8m.c b/drivers/clk/imx/clk-composite-8m.c index cbf0d7955a00ae1b5dbb11921054c94f82a11f5d..7a6e3ce97133b1d4790119d3615672fb2252bd5c 100644 --- a/drivers/clk/imx/clk-composite-8m.c +++ b/drivers/clk/imx/clk-composite-8m.c @@ -119,10 +119,41 @@ static int imx8m_clk_composite_divider_set_rate(struct clk_hw *hw, return ret; } +static int imx8m_divider_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) +{ + struct clk_divider *divider = to_clk_divider(hw); + int prediv_value; + int div_value; + + /* if read only, just return current value */ + if (divider->flags & CLK_DIVIDER_READ_ONLY) { + u32 val; + + val = readl(divider->reg); + prediv_value = val >> divider->shift; + prediv_value &= clk_div_mask(divider->width); + prediv_value++; + + div_value = val >> PCG_DIV_SHIFT; + div_value &= clk_div_mask(PCG_DIV_WIDTH); + div_value++; + + return divider_ro_determine_rate(hw, req, divider->table, + PCG_PREDIV_WIDTH + PCG_DIV_WIDTH, + divider->flags, prediv_value * div_value); + } + + return divider_determine_rate(hw, req, divider->table, + PCG_PREDIV_WIDTH + PCG_DIV_WIDTH, + divider->flags); +} + static const struct clk_ops imx8m_clk_composite_divider_ops = { .recalc_rate = imx8m_clk_composite_divider_recalc_rate, .round_rate = imx8m_clk_composite_divider_round_rate, .set_rate = imx8m_clk_composite_divider_set_rate, + .determine_rate = imx8m_divider_determine_rate, }; static u8 imx8m_clk_composite_mux_get_parent(struct clk_hw *hw) diff --git a/drivers/clk/imx/clk-fixup-mux.c b/drivers/clk/imx/clk-fixup-mux.c index c82401570c8432654c53591b3d567b644d93aff9..b48701864ef01205d0759478665928223af525b3 100644 --- a/drivers/clk/imx/clk-fixup-mux.c +++ b/drivers/clk/imx/clk-fixup-mux.c @@ -60,6 +60,7 @@ static int clk_fixup_mux_set_parent(struct clk_hw *hw, u8 index) } static const struct clk_ops clk_fixup_mux_ops = { + .determine_rate = clk_hw_determine_rate_no_reparent, .get_parent = clk_fixup_mux_get_parent, .set_parent = clk_fixup_mux_set_parent, }; diff --git a/drivers/clk/imx/clk-imx1.c b/drivers/clk/imx/clk-imx1.c index 22fc7491ba00878b365b984cc1d32183c2d33f11..f6ea7e5052d56256af4cad9fbba8f07c062197f9 100644 --- a/drivers/clk/imx/clk-imx1.c +++ b/drivers/clk/imx/clk-imx1.c @@ -10,7 +10,6 @@ #include #include #include -#include #include #include "clk.h" diff --git a/drivers/clk/imx/clk-imx27.c b/drivers/clk/imx/clk-imx27.c index 5d177125728df3a8c8694f1a34b089e4e1d78436..99618ded09397370adbc7d73e31891e2bbad25bd 100644 --- a/drivers/clk/imx/clk-imx27.c +++ b/drivers/clk/imx/clk-imx27.c @@ -8,7 +8,6 @@ #include #include #include -#include #include #include "clk.h" diff --git a/drivers/clk/imx/clk-imx31.c b/drivers/clk/imx/clk-imx31.c index c44e18c6f63f79e4aa2dcfd4c7dc6a9743d3558e..4c8d9ff0b2ad5654403550365c2b0f39bb21faf0 100644 --- a/drivers/clk/imx/clk-imx31.c +++ b/drivers/clk/imx/clk-imx31.c @@ -11,7 +11,6 @@ #include #include #include -#include #include #include "clk.h" diff --git a/drivers/clk/imx/clk-imx35.c b/drivers/clk/imx/clk-imx35.c index 7dcbaea3fea35d6839402967f27616b68c14ebc7..3b6fdb4e0be784ca039efab6dcdb06251c1deb8e 100644 --- a/drivers/clk/imx/clk-imx35.c +++ b/drivers/clk/imx/clk-imx35.c @@ -10,7 +10,6 @@ #include #include #include -#include #include #include "clk.h" diff --git a/drivers/clk/imx/clk-imx6sx.c b/drivers/clk/imx/clk-imx6sx.c index 7cf86707bc395309d12109aaf77c5b5fdb7e3cbd..3f1502933e59fe193cacadfbea5bcd2a95b4c8e8 100644 --- a/drivers/clk/imx/clk-imx6sx.c +++ b/drivers/clk/imx/clk-imx6sx.c @@ -302,10 +302,10 @@ static void __init imx6sx_clocks_init(struct device_node *ccm_node) hws[IMX6SX_CLK_CKO2_SEL] = imx_clk_hw_mux("cko2_sel", base + 0x60, 16, 5, cko2_sels, ARRAY_SIZE(cko2_sels)); hws[IMX6SX_CLK_CKO] = imx_clk_hw_mux("cko", base + 0x60, 8, 1, cko_sels, ARRAY_SIZE(cko_sels)); - hws[IMX6SX_CLK_LDB_DI1_DIV_SEL] = imx_clk_hw_mux_flags("ldb_di1_div_sel", base + 0x20, 11, 1, ldb_di1_div_sels, ARRAY_SIZE(ldb_di1_div_sels), CLK_SET_RATE_PARENT); - hws[IMX6SX_CLK_LDB_DI0_DIV_SEL] = imx_clk_hw_mux_flags("ldb_di0_div_sel", base + 0x20, 10, 1, ldb_di0_div_sels, ARRAY_SIZE(ldb_di0_div_sels), CLK_SET_RATE_PARENT); - hws[IMX6SX_CLK_LDB_DI1_SEL] = imx_clk_hw_mux_flags("ldb_di1_sel", base + 0x2c, 12, 3, ldb_di1_sels, ARRAY_SIZE(ldb_di1_sels), CLK_SET_RATE_PARENT); - hws[IMX6SX_CLK_LDB_DI0_SEL] = imx_clk_hw_mux_flags("ldb_di0_sel", base + 0x2c, 9, 3, ldb_di0_sels, ARRAY_SIZE(ldb_di0_sels), CLK_SET_RATE_PARENT); + hws[IMX6SX_CLK_LDB_DI1_DIV_SEL] = imx_clk_hw_mux("ldb_di1_div_sel", base + 0x20, 11, 1, ldb_di1_div_sels, ARRAY_SIZE(ldb_di1_div_sels)); + hws[IMX6SX_CLK_LDB_DI0_DIV_SEL] = imx_clk_hw_mux("ldb_di0_div_sel", base + 0x20, 10, 1, ldb_di0_div_sels, ARRAY_SIZE(ldb_di0_div_sels)); + hws[IMX6SX_CLK_LDB_DI1_SEL] = imx_clk_hw_mux("ldb_di1_sel", base + 0x2c, 12, 3, ldb_di1_sels, ARRAY_SIZE(ldb_di1_sels)); + hws[IMX6SX_CLK_LDB_DI0_SEL] = imx_clk_hw_mux("ldb_di0_sel", base + 0x2c, 9, 3, ldb_di0_sels, ARRAY_SIZE(ldb_di0_sels)); hws[IMX6SX_CLK_LCDIF1_PRE_SEL] = imx_clk_hw_mux_flags("lcdif1_pre_sel", base + 0x38, 15, 3, lcdif1_pre_sels, ARRAY_SIZE(lcdif1_pre_sels), CLK_SET_RATE_PARENT); hws[IMX6SX_CLK_LCDIF1_SEL] = imx_clk_hw_mux_flags("lcdif1_sel", base + 0x38, 9, 3, lcdif1_sels, ARRAY_SIZE(lcdif1_sels), CLK_SET_RATE_PARENT); diff --git a/drivers/clk/imx/clk-imx6ul.c b/drivers/clk/imx/clk-imx6ul.c index e3696a88b5a36af229370e8b7a996d60a987dcb4..f9394e94f69d733fce341d6447a3998b94497742 100644 --- a/drivers/clk/imx/clk-imx6ul.c +++ b/drivers/clk/imx/clk-imx6ul.c @@ -544,6 +544,8 @@ static void __init imx6ul_clocks_init(struct device_node *ccm_node) clk_set_parent(hws[IMX6UL_CLK_ENET1_REF_SEL]->clk, hws[IMX6UL_CLK_ENET_REF]->clk); clk_set_parent(hws[IMX6UL_CLK_ENET2_REF_SEL]->clk, hws[IMX6UL_CLK_ENET2_REF]->clk); + + imx_register_uart_clocks(); } CLK_OF_DECLARE(imx6ul, "fsl,imx6ul-ccm", imx6ul_clocks_init); diff --git a/drivers/clk/imx/clk-imx8mn.c b/drivers/clk/imx/clk-imx8mn.c index 4b23a4648600434bc8edaa04070caa4675090b4d..4bd1ed11353b38e500a27eb8932238579784430a 100644 --- a/drivers/clk/imx/clk-imx8mn.c +++ b/drivers/clk/imx/clk-imx8mn.c @@ -323,7 +323,7 @@ static int imx8mn_clocks_probe(struct platform_device *pdev) void __iomem *base; int ret; - clk_hw_data = kzalloc(struct_size(clk_hw_data, hws, + clk_hw_data = devm_kzalloc(dev, struct_size(clk_hw_data, hws, IMX8MN_CLK_END), GFP_KERNEL); if (WARN_ON(!clk_hw_data)) return -ENOMEM; @@ -340,10 +340,10 @@ static int imx8mn_clocks_probe(struct platform_device *pdev) hws[IMX8MN_CLK_EXT4] = imx_get_clk_hw_by_name(np, "clk_ext4"); np = of_find_compatible_node(NULL, NULL, "fsl,imx8mn-anatop"); - base = of_iomap(np, 0); + base = devm_of_iomap(dev, np, 0, NULL); of_node_put(np); - if (WARN_ON(!base)) { - ret = -ENOMEM; + if (WARN_ON(IS_ERR(base))) { + ret = PTR_ERR(base); goto unregister_hws; } diff --git a/drivers/clk/imx/clk-imx8mp.c b/drivers/clk/imx/clk-imx8mp.c index f26ae8de4cc6fb681fefa3d66f7f2e58ff5ccf72..1469249386dd87da72ccce1d69414b127eab0715 100644 --- a/drivers/clk/imx/clk-imx8mp.c +++ b/drivers/clk/imx/clk-imx8mp.c @@ -414,25 +414,22 @@ static int imx8mp_clocks_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct device_node *np; void __iomem *anatop_base, *ccm_base; + int err; np = of_find_compatible_node(NULL, NULL, "fsl,imx8mp-anatop"); - anatop_base = of_iomap(np, 0); + anatop_base = devm_of_iomap(dev, np, 0, NULL); of_node_put(np); - if (WARN_ON(!anatop_base)) - return -ENOMEM; + if (WARN_ON(IS_ERR(anatop_base))) + return PTR_ERR(anatop_base); np = dev->of_node; ccm_base = devm_platform_ioremap_resource(pdev, 0); - if (WARN_ON(IS_ERR(ccm_base))) { - iounmap(anatop_base); + if (WARN_ON(IS_ERR(ccm_base))) return PTR_ERR(ccm_base); - } - clk_hw_data = kzalloc(struct_size(clk_hw_data, hws, IMX8MP_CLK_END), GFP_KERNEL); - if (WARN_ON(!clk_hw_data)) { - iounmap(anatop_base); + clk_hw_data = devm_kzalloc(dev, struct_size(clk_hw_data, hws, IMX8MP_CLK_END), GFP_KERNEL); + if (WARN_ON(!clk_hw_data)) return -ENOMEM; - } clk_hw_data->num = IMX8MP_CLK_END; hws = clk_hw_data->hws; @@ -722,7 +719,12 @@ static int imx8mp_clocks_probe(struct platform_device *pdev) imx_check_clk_hws(hws, IMX8MP_CLK_END); - of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_hw_data); + err = of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_hw_data); + if (err < 0) { + dev_err(dev, "failed to register hws for i.MX8MP\n"); + imx_unregister_hw_clocks(hws, IMX8MP_CLK_END); + return err; + } imx_register_uart_clocks(); diff --git a/drivers/clk/imx/clk-imx93.c b/drivers/clk/imx/clk-imx93.c index 07b4a043e44952e550d4c869cc2834374d2985f1..b6c7c2725906c574a48fb43360806bdd3474d37c 100644 --- a/drivers/clk/imx/clk-imx93.c +++ b/drivers/clk/imx/clk-imx93.c @@ -264,7 +264,7 @@ static int imx93_clocks_probe(struct platform_device *pdev) void __iomem *base, *anatop_base; int i, ret; - clk_hw_data = kzalloc(struct_size(clk_hw_data, hws, + clk_hw_data = devm_kzalloc(dev, struct_size(clk_hw_data, hws, IMX93_CLK_END), GFP_KERNEL); if (!clk_hw_data) return -ENOMEM; @@ -288,10 +288,12 @@ static int imx93_clocks_probe(struct platform_device *pdev) "sys_pll_pfd2", 1, 2); np = of_find_compatible_node(NULL, NULL, "fsl,imx93-anatop"); - anatop_base = of_iomap(np, 0); + anatop_base = devm_of_iomap(dev, np, 0, NULL); of_node_put(np); - if (WARN_ON(!anatop_base)) - return -ENOMEM; + if (WARN_ON(IS_ERR(anatop_base))) { + ret = PTR_ERR(base); + goto unregister_hws; + } clks[IMX93_CLK_ARM_PLL] = imx_clk_fracn_gppll_integer("arm_pll", "osc_24m", anatop_base + 0x1000, @@ -304,8 +306,8 @@ static int imx93_clocks_probe(struct platform_device *pdev) np = dev->of_node; base = devm_platform_ioremap_resource(pdev, 0); if (WARN_ON(IS_ERR(base))) { - iounmap(anatop_base); - return PTR_ERR(base); + ret = PTR_ERR(base); + goto unregister_hws; } for (i = 0; i < ARRAY_SIZE(root_array); i++) { @@ -345,7 +347,6 @@ static int imx93_clocks_probe(struct platform_device *pdev) unregister_hws: imx_unregister_hw_clocks(clks, IMX93_CLK_END); - iounmap(anatop_base); return ret; } diff --git a/drivers/clk/imx/clk-imxrt1050.c b/drivers/clk/imx/clk-imxrt1050.c index fd5c51fc92c0e760c9161b5ebdbff6196fb76652..08d155feb035a8ee8cb44216df0ab97c49d75784 100644 --- a/drivers/clk/imx/clk-imxrt1050.c +++ b/drivers/clk/imx/clk-imxrt1050.c @@ -42,7 +42,7 @@ static int imxrt1050_clocks_probe(struct platform_device *pdev) struct device_node *anp; int ret; - clk_hw_data = kzalloc(struct_size(clk_hw_data, hws, + clk_hw_data = devm_kzalloc(dev, struct_size(clk_hw_data, hws, IMXRT1050_CLK_END), GFP_KERNEL); if (WARN_ON(!clk_hw_data)) return -ENOMEM; @@ -53,10 +53,12 @@ static int imxrt1050_clocks_probe(struct platform_device *pdev) hws[IMXRT1050_CLK_OSC] = imx_get_clk_hw_by_name(np, "osc"); anp = of_find_compatible_node(NULL, NULL, "fsl,imxrt-anatop"); - pll_base = of_iomap(anp, 0); + pll_base = devm_of_iomap(dev, anp, 0, NULL); of_node_put(anp); - if (WARN_ON(!pll_base)) - return -ENOMEM; + if (WARN_ON(IS_ERR(pll_base))) { + ret = PTR_ERR(pll_base); + goto unregister_hws; + } /* Anatop clocks */ hws[IMXRT1050_CLK_DUMMY] = imx_clk_hw_fixed("dummy", 0UL); @@ -104,8 +106,10 @@ static int imxrt1050_clocks_probe(struct platform_device *pdev) /* CCM clocks */ ccm_base = devm_platform_ioremap_resource(pdev, 0); - if (WARN_ON(IS_ERR(ccm_base))) - return PTR_ERR(ccm_base); + if (WARN_ON(IS_ERR(ccm_base))) { + ret = PTR_ERR(ccm_base); + goto unregister_hws; + } hws[IMXRT1050_CLK_ARM_PODF] = imx_clk_hw_divider("arm_podf", "pll1_arm", ccm_base + 0x10, 0, 3); hws[IMXRT1050_CLK_PRE_PERIPH_SEL] = imx_clk_hw_mux("pre_periph_sel", ccm_base + 0x18, 18, 2, @@ -149,8 +153,12 @@ static int imxrt1050_clocks_probe(struct platform_device *pdev) ret = of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_hw_data); if (ret < 0) { dev_err(dev, "Failed to register clks for i.MXRT1050.\n"); - imx_unregister_hw_clocks(hws, IMXRT1050_CLK_END); + goto unregister_hws; } + return 0; + +unregister_hws: + imx_unregister_hw_clocks(hws, IMXRT1050_CLK_END); return ret; } static const struct of_device_id imxrt1050_clk_of_match[] = { diff --git a/drivers/clk/imx/clk-scu.c b/drivers/clk/imx/clk-scu.c index 1e6870f3671f6b0b15a31a38d9d3e6d1ec54b298..85041e339515eb1b971c97590434380dbeaaf7e5 100644 --- a/drivers/clk/imx/clk-scu.c +++ b/drivers/clk/imx/clk-scu.c @@ -250,6 +250,23 @@ static unsigned long clk_scu_recalc_rate(struct clk_hw *hw, return le32_to_cpu(msg.data.resp.rate); } +/* + * clk_scu_determine_rate - Returns the closest rate for a SCU clock + * @hw: clock to round rate for + * @req: clock rate request + * + * Returns 0 on success, a negative error on failure + */ +static int clk_scu_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) +{ + /* + * Assume we support all the requested rate and let the SCU firmware + * to handle the left work + */ + return 0; +} + /* * clk_scu_round_rate - Round clock rate for a SCU clock * @hw: clock to round rate for @@ -425,7 +442,7 @@ static void clk_scu_unprepare(struct clk_hw *hw) static const struct clk_ops clk_scu_ops = { .recalc_rate = clk_scu_recalc_rate, - .round_rate = clk_scu_round_rate, + .determine_rate = clk_scu_determine_rate, .set_rate = clk_scu_set_rate, .get_parent = clk_scu_get_parent, .set_parent = clk_scu_set_parent, @@ -707,11 +724,11 @@ struct clk_hw *imx_clk_scu_alloc_dev(const char *name, void imx_clk_scu_unregister(void) { - struct imx_scu_clk_node *clk; + struct imx_scu_clk_node *clk, *n; int i; for (i = 0; i < IMX_SC_R_LAST; i++) { - list_for_each_entry(clk, &imx_scu_clks[i], node) { + list_for_each_entry_safe(clk, n, &imx_scu_clks[i], node) { clk_hw_unregister(clk->hw); kfree(clk); } @@ -785,6 +802,7 @@ static int clk_gpr_mux_scu_set_parent(struct clk_hw *hw, u8 index) } static const struct clk_ops clk_gpr_mux_scu_ops = { + .determine_rate = clk_hw_determine_rate_no_reparent, .get_parent = clk_gpr_mux_scu_get_parent, .set_parent = clk_gpr_mux_scu_set_parent, }; diff --git a/drivers/clk/imx/clk.c b/drivers/clk/imx/clk.c index 19cde59a20cb1d26978fdbaaa52c891261c6baa5..e35496af5ceba0120662191850cd7036750b6d77 100644 --- a/drivers/clk/imx/clk.c +++ b/drivers/clk/imx/clk.c @@ -20,14 +20,6 @@ EXPORT_SYMBOL_GPL(imx_ccm_lock); bool mcore_booted; EXPORT_SYMBOL_GPL(mcore_booted); -void imx_unregister_clocks(struct clk *clks[], unsigned int count) -{ - unsigned int i; - - for (i = 0; i < count; i++) - clk_unregister(clks[i]); -} - void imx_unregister_hw_clocks(struct clk_hw *hws[], unsigned int count) { unsigned int i; diff --git a/drivers/clk/imx/clk.h b/drivers/clk/imx/clk.h index 1031468701d7f01de0973105b6d4cb34c0e4f29f..af19d9f6aed0951a81120950dd9c31701c7a216c 100644 --- a/drivers/clk/imx/clk.h +++ b/drivers/clk/imx/clk.h @@ -19,7 +19,6 @@ static inline void imx_register_uart_clocks(void) } #endif void imx_mmdc_mask_handshake(void __iomem *ccm_base, unsigned int chn); -void imx_unregister_clocks(struct clk *clks[], unsigned int count); void imx_unregister_hw_clocks(struct clk_hw *hws[], unsigned int count); extern void imx_cscmr1_fixup(u32 *val); diff --git a/drivers/clk/ingenic/cgu.c b/drivers/clk/ingenic/cgu.c index 1f7ba30f5a1b00a02c143cb98b58a511ef98ecd2..0c9c8344ad1103b13337a26e14b0d5d5c340d705 100644 --- a/drivers/clk/ingenic/cgu.c +++ b/drivers/clk/ingenic/cgu.c @@ -491,22 +491,23 @@ ingenic_clk_calc_div(struct clk_hw *hw, return div; } -static long -ingenic_clk_round_rate(struct clk_hw *hw, unsigned long req_rate, - unsigned long *parent_rate) +static int ingenic_clk_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) { struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw); const struct ingenic_cgu_clk_info *clk_info = to_clk_info(ingenic_clk); unsigned int div = 1; if (clk_info->type & CGU_CLK_DIV) - div = ingenic_clk_calc_div(hw, clk_info, *parent_rate, req_rate); + div = ingenic_clk_calc_div(hw, clk_info, req->best_parent_rate, + req->rate); else if (clk_info->type & CGU_CLK_FIXDIV) div = clk_info->fixdiv.div; else if (clk_hw_can_set_rate_parent(hw)) - *parent_rate = req_rate; + req->best_parent_rate = req->rate; - return DIV_ROUND_UP(*parent_rate, div); + req->rate = DIV_ROUND_UP(req->best_parent_rate, div); + return 0; } static inline int ingenic_clk_check_stable(struct ingenic_cgu *cgu, @@ -626,7 +627,7 @@ static const struct clk_ops ingenic_clk_ops = { .set_parent = ingenic_clk_set_parent, .recalc_rate = ingenic_clk_recalc_rate, - .round_rate = ingenic_clk_round_rate, + .determine_rate = ingenic_clk_determine_rate, .set_rate = ingenic_clk_set_rate, .enable = ingenic_clk_enable, diff --git a/drivers/clk/ingenic/tcu.c b/drivers/clk/ingenic/tcu.c index d5544cbc5c48416d2bf8ff9aeb7c8896d4050296..7d04ef40b7cf9eeb0b790a734d3545236a369311 100644 --- a/drivers/clk/ingenic/tcu.c +++ b/drivers/clk/ingenic/tcu.c @@ -178,18 +178,21 @@ static u8 ingenic_tcu_get_prescale(unsigned long rate, unsigned long req_rate) return 5; /* /1024 divider */ } -static long ingenic_tcu_round_rate(struct clk_hw *hw, unsigned long req_rate, - unsigned long *parent_rate) +static int ingenic_tcu_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) { - unsigned long rate = *parent_rate; + unsigned long rate = req->best_parent_rate; u8 prescale; - if (req_rate > rate) - return rate; + if (req->rate > rate) { + req->rate = rate; + return 0; + } - prescale = ingenic_tcu_get_prescale(rate, req_rate); + prescale = ingenic_tcu_get_prescale(rate, req->rate); - return rate >> (prescale * 2); + req->rate = rate >> (prescale * 2); + return 0; } static int ingenic_tcu_set_rate(struct clk_hw *hw, unsigned long req_rate, @@ -219,7 +222,7 @@ static const struct clk_ops ingenic_tcu_clk_ops = { .set_parent = ingenic_tcu_set_parent, .recalc_rate = ingenic_tcu_recalc_rate, - .round_rate = ingenic_tcu_round_rate, + .determine_rate = ingenic_tcu_determine_rate, .set_rate = ingenic_tcu_set_rate, .enable = ingenic_tcu_enable, diff --git a/drivers/clk/keystone/sci-clk.c b/drivers/clk/keystone/sci-clk.c index 910ecd58c4ca2e7eae7496adf81faca55e97600a..6c1df4f11536dd0a6571625ec0028ce0ff77cbd0 100644 --- a/drivers/clk/keystone/sci-clk.c +++ b/drivers/clk/keystone/sci-clk.c @@ -294,6 +294,8 @@ static int _sci_clk_build(struct sci_clk_provider *provider, name = kasprintf(GFP_KERNEL, "clk:%d:%d", sci_clk->dev_id, sci_clk->clk_id); + if (!name) + return -ENOMEM; init.name = name; diff --git a/drivers/clk/keystone/syscon-clk.c b/drivers/clk/keystone/syscon-clk.c index 5d7cc83682da89f80e20f8a99010d841fecfb6a6..d33f74119488166318f5dcdf32d4b58b418b13d1 100644 --- a/drivers/clk/keystone/syscon-clk.c +++ b/drivers/clk/keystone/syscon-clk.c @@ -4,10 +4,12 @@ */ #include +#include #include #include #include #include +#include struct ti_syscon_gate_clk_priv { struct clk_hw hw; @@ -61,21 +63,31 @@ static const struct clk_ops ti_syscon_gate_clk_ops = { static struct clk_hw *ti_syscon_gate_clk_register(struct device *dev, struct regmap *regmap, + const char *parent_name, const struct ti_syscon_gate_clk_data *data) { struct ti_syscon_gate_clk_priv *priv; struct clk_init_data init; + char *name = NULL; int ret; priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); if (!priv) return ERR_PTR(-ENOMEM); - init.name = data->name; init.ops = &ti_syscon_gate_clk_ops; - init.parent_names = NULL; - init.num_parents = 0; - init.flags = 0; + if (parent_name) { + name = kasprintf(GFP_KERNEL, "%s:%s", data->name, parent_name); + init.name = name; + init.parent_names = &parent_name; + init.num_parents = 1; + init.flags = CLK_SET_RATE_PARENT; + } else { + init.name = data->name; + init.parent_names = NULL; + init.num_parents = 0; + init.flags = 0; + } priv->regmap = regmap; priv->reg = data->offset; @@ -83,6 +95,10 @@ static struct clk_hw priv->hw.init = &init; ret = devm_clk_hw_register(dev, &priv->hw); + + if (name) + kfree(init.name); + if (ret) return ERR_PTR(ret); @@ -94,22 +110,30 @@ static int ti_syscon_gate_clk_probe(struct platform_device *pdev) const struct ti_syscon_gate_clk_data *data, *p; struct clk_hw_onecell_data *hw_data; struct device *dev = &pdev->dev; + int num_clks, num_parents, i; + const char *parent_name; struct regmap *regmap; - int num_clks, i; data = device_get_match_data(dev); if (!data) return -EINVAL; - regmap = syscon_node_to_regmap(dev->of_node); + regmap = device_node_to_regmap(dev->of_node); if (IS_ERR(regmap)) return dev_err_probe(dev, PTR_ERR(regmap), - "failed to find parent regmap\n"); + "failed to get regmap\n"); num_clks = 0; for (p = data; p->name; p++) num_clks++; + num_parents = of_clk_get_parent_count(dev->of_node); + if (of_device_is_compatible(dev->of_node, "ti,am62-audio-refclk") && + num_parents == 0) { + return dev_err_probe(dev, -EINVAL, + "must specify a parent clock\n"); + } + hw_data = devm_kzalloc(dev, struct_size(hw_data, hws, num_clks), GFP_KERNEL); if (!hw_data) @@ -117,8 +141,10 @@ static int ti_syscon_gate_clk_probe(struct platform_device *pdev) hw_data->num = num_clks; + parent_name = of_clk_get_parent_name(dev->of_node, 0); for (i = 0; i < num_clks; i++) { hw_data->hws[i] = ti_syscon_gate_clk_register(dev, regmap, + parent_name, &data[i]); if (IS_ERR(hw_data->hws[i])) dev_warn(dev, "failed to register %s\n", @@ -166,6 +192,11 @@ static const struct ti_syscon_gate_clk_data am62_clk_data[] = { { /* Sentinel */ }, }; +static const struct ti_syscon_gate_clk_data am62_audio_clk_data[] = { + TI_SYSCON_CLK_GATE("audio_refclk", 0x0, 15), + { /* Sentinel */ }, +}; + static const struct of_device_id ti_syscon_gate_clk_ids[] = { { .compatible = "ti,am654-ehrpwm-tbclk", @@ -179,6 +210,10 @@ static const struct of_device_id ti_syscon_gate_clk_ids[] = { .compatible = "ti,am62-epwm-tbclk", .data = &am62_clk_data, }, + { + .compatible = "ti,am62-audio-refclk", + .data = &am62_audio_clk_data, + }, { } }; MODULE_DEVICE_TABLE(of, ti_syscon_gate_clk_ids); diff --git a/drivers/clk/mediatek/Kconfig b/drivers/clk/mediatek/Kconfig index 99e67c07e6385a3c76206241c7ac1ed8a9925223..48b42d11111cde9c075641f6e8522d84f0190525 100644 --- a/drivers/clk/mediatek/Kconfig +++ b/drivers/clk/mediatek/Kconfig @@ -781,72 +781,84 @@ config COMMON_CLK_MT8192 config COMMON_CLK_MT8192_AUDSYS tristate "Clock driver for MediaTek MT8192 audsys" depends on COMMON_CLK_MT8192 + default COMMON_CLK_MT8192 help This driver supports MediaTek MT8192 audsys clocks. config COMMON_CLK_MT8192_CAMSYS tristate "Clock driver for MediaTek MT8192 camsys" depends on COMMON_CLK_MT8192 + default COMMON_CLK_MT8192 help This driver supports MediaTek MT8192 camsys and camsys_raw clocks. config COMMON_CLK_MT8192_IMGSYS tristate "Clock driver for MediaTek MT8192 imgsys" depends on COMMON_CLK_MT8192 + default COMMON_CLK_MT8192 help This driver supports MediaTek MT8192 imgsys and imgsys2 clocks. config COMMON_CLK_MT8192_IMP_IIC_WRAP tristate "Clock driver for MediaTek MT8192 imp_iic_wrap" depends on COMMON_CLK_MT8192 + default COMMON_CLK_MT8192 help This driver supports MediaTek MT8192 imp_iic_wrap clocks. config COMMON_CLK_MT8192_IPESYS tristate "Clock driver for MediaTek MT8192 ipesys" depends on COMMON_CLK_MT8192 + default COMMON_CLK_MT8192 help This driver supports MediaTek MT8192 ipesys clocks. config COMMON_CLK_MT8192_MDPSYS tristate "Clock driver for MediaTek MT8192 mdpsys" depends on COMMON_CLK_MT8192 + default COMMON_CLK_MT8192 help This driver supports MediaTek MT8192 mdpsys clocks. config COMMON_CLK_MT8192_MFGCFG tristate "Clock driver for MediaTek MT8192 mfgcfg" depends on COMMON_CLK_MT8192 + default COMMON_CLK_MT8192 help This driver supports MediaTek MT8192 mfgcfg clocks. config COMMON_CLK_MT8192_MMSYS tristate "Clock driver for MediaTek MT8192 mmsys" depends on COMMON_CLK_MT8192 + default COMMON_CLK_MT8192 help This driver supports MediaTek MT8192 mmsys clocks. config COMMON_CLK_MT8192_MSDC tristate "Clock driver for MediaTek MT8192 msdc" depends on COMMON_CLK_MT8192 + default COMMON_CLK_MT8192 help This driver supports MediaTek MT8192 msdc and msdc_top clocks. config COMMON_CLK_MT8192_SCP_ADSP tristate "Clock driver for MediaTek MT8192 scp_adsp" depends on COMMON_CLK_MT8192 + default COMMON_CLK_MT8192 help This driver supports MediaTek MT8192 scp_adsp clocks. config COMMON_CLK_MT8192_VDECSYS tristate "Clock driver for MediaTek MT8192 vdecsys" depends on COMMON_CLK_MT8192 + default COMMON_CLK_MT8192 help This driver supports MediaTek MT8192 vdecsys and vdecsys_soc clocks. config COMMON_CLK_MT8192_VENCSYS tristate "Clock driver for MediaTek MT8192 vencsys" depends on COMMON_CLK_MT8192 + default COMMON_CLK_MT8192 help This driver supports MediaTek MT8192 vencsys clocks. diff --git a/drivers/clk/mediatek/clk-cpumux.c b/drivers/clk/mediatek/clk-cpumux.c index da05f06192c095dd32a8844f08d38a1b2b0c7a8d..a03826db4dcb70741982cfb9534ad85c3bfeb06d 100644 --- a/drivers/clk/mediatek/clk-cpumux.c +++ b/drivers/clk/mediatek/clk-cpumux.c @@ -53,6 +53,7 @@ static int clk_cpumux_set_parent(struct clk_hw *hw, u8 index) } static const struct clk_ops clk_cpumux_ops = { + .determine_rate = clk_hw_determine_rate_no_reparent, .get_parent = clk_cpumux_get_parent, .set_parent = clk_cpumux_set_parent, }; diff --git a/drivers/clk/mediatek/clk-mt2701-aud.c b/drivers/clk/mediatek/clk-mt2701-aud.c index 5cd343b98685830c2ae0c05e14fea92cb4747fbc..3ce7e71196fdc28e26a9782563c41f22046bf7b6 100644 --- a/drivers/clk/mediatek/clk-mt2701-aud.c +++ b/drivers/clk/mediatek/clk-mt2701-aud.c @@ -150,15 +150,15 @@ static int clk_mt2701_aud_probe(struct platform_device *pdev) return r; } -static int clk_mt2701_aud_remove(struct platform_device *pdev) +static void clk_mt2701_aud_remove(struct platform_device *pdev) { of_platform_depopulate(&pdev->dev); - return mtk_clk_simple_remove(pdev); + mtk_clk_simple_remove(pdev); } static struct platform_driver clk_mt2701_aud_drv = { .probe = clk_mt2701_aud_probe, - .remove = clk_mt2701_aud_remove, + .remove_new = clk_mt2701_aud_remove, .driver = { .name = "clk-mt2701-aud", .of_match_table = of_match_clk_mt2701_aud, diff --git a/drivers/clk/mediatek/clk-mt2701-bdp.c b/drivers/clk/mediatek/clk-mt2701-bdp.c index 4c5b70d48df944ac40670ad32bdf7966eae799da..b25703ec8dc08f2e1fc063c112778d4480eaf9b1 100644 --- a/drivers/clk/mediatek/clk-mt2701-bdp.c +++ b/drivers/clk/mediatek/clk-mt2701-bdp.c @@ -99,7 +99,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt2701_bdp); static struct platform_driver clk_mt2701_bdp_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt2701-bdp", .of_match_table = of_match_clk_mt2701_bdp, diff --git a/drivers/clk/mediatek/clk-mt2701-eth.c b/drivers/clk/mediatek/clk-mt2701-eth.c index 9a1fb0c93964776273dcf2bb6102181c89677779..056d1e8459da4da6e0de8029c6391cc99f6f6ead 100644 --- a/drivers/clk/mediatek/clk-mt2701-eth.c +++ b/drivers/clk/mediatek/clk-mt2701-eth.c @@ -53,7 +53,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt2701_eth); static struct platform_driver clk_mt2701_eth_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt2701-eth", .of_match_table = of_match_clk_mt2701_eth, diff --git a/drivers/clk/mediatek/clk-mt2701-g3d.c b/drivers/clk/mediatek/clk-mt2701-g3d.c index c0006861a3170da7363bac1b8272551bf2da72aa..e03ac76279bacc7a7b52cf63f1d474ef89c07634 100644 --- a/drivers/clk/mediatek/clk-mt2701-g3d.c +++ b/drivers/clk/mediatek/clk-mt2701-g3d.c @@ -52,7 +52,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt2701_g3d); static struct platform_driver clk_mt2701_g3d_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt2701-g3d", .of_match_table = of_match_clk_mt2701_g3d, diff --git a/drivers/clk/mediatek/clk-mt2701-hif.c b/drivers/clk/mediatek/clk-mt2701-hif.c index ff7c0b3228e46026b4c2cfe36359ee9a54c5a60c..cbd5ece3e9e97035bc5630ed30cb8d00ce9a8eb1 100644 --- a/drivers/clk/mediatek/clk-mt2701-hif.c +++ b/drivers/clk/mediatek/clk-mt2701-hif.c @@ -50,7 +50,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt2701_hif); static struct platform_driver clk_mt2701_hif_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt2701-hif", .of_match_table = of_match_clk_mt2701_hif, diff --git a/drivers/clk/mediatek/clk-mt2701-img.c b/drivers/clk/mediatek/clk-mt2701-img.c index baa1194eb01ea54eef1fde3f16dc9a6b4628c2d5..2768360b213efc39b77184921cd977348276b0b9 100644 --- a/drivers/clk/mediatek/clk-mt2701-img.c +++ b/drivers/clk/mediatek/clk-mt2701-img.c @@ -47,7 +47,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt2701_img); static struct platform_driver clk_mt2701_img_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt2701-img", .of_match_table = of_match_clk_mt2701_img, diff --git a/drivers/clk/mediatek/clk-mt2701-mm.c b/drivers/clk/mediatek/clk-mt2701-mm.c index c62c56fd2b7ec80da982c581f93802975e18de88..2b990b5a0422a41b4263b54e361f531542c740df 100644 --- a/drivers/clk/mediatek/clk-mt2701-mm.c +++ b/drivers/clk/mediatek/clk-mt2701-mm.c @@ -80,7 +80,7 @@ MODULE_DEVICE_TABLE(platform, clk_mt2701_mm_id_table); static struct platform_driver clk_mt2701_mm_drv = { .probe = mtk_clk_pdev_probe, - .remove = mtk_clk_pdev_remove, + .remove_new = mtk_clk_pdev_remove, .driver = { .name = "clk-mt2701-mm", }, diff --git a/drivers/clk/mediatek/clk-mt2701-vdec.c b/drivers/clk/mediatek/clk-mt2701-vdec.c index b7f97bc51c166737078b766314d493c83436bcd7..57711b953b7f90e4d3685784e6e8aba3cc3065d3 100644 --- a/drivers/clk/mediatek/clk-mt2701-vdec.c +++ b/drivers/clk/mediatek/clk-mt2701-vdec.c @@ -52,7 +52,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt2701_vdec); static struct platform_driver clk_mt2701_vdec_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt2701-vdec", .of_match_table = of_match_clk_mt2701_vdec, diff --git a/drivers/clk/mediatek/clk-mt2712-apmixedsys.c b/drivers/clk/mediatek/clk-mt2712-apmixedsys.c index 9d2fcda285fb09f47e5c10600cc77d716eed79c5..43272dc744c7ff382cbad8ad690d0d3930e4425c 100644 --- a/drivers/clk/mediatek/clk-mt2712-apmixedsys.c +++ b/drivers/clk/mediatek/clk-mt2712-apmixedsys.c @@ -138,7 +138,7 @@ static int clk_mt2712_apmixed_probe(struct platform_device *pdev) return r; } -static int clk_mt2712_apmixed_remove(struct platform_device *pdev) +static void clk_mt2712_apmixed_remove(struct platform_device *pdev) { struct device_node *node = pdev->dev.of_node; struct clk_hw_onecell_data *clk_data = platform_get_drvdata(pdev); @@ -146,8 +146,6 @@ static int clk_mt2712_apmixed_remove(struct platform_device *pdev) of_clk_del_provider(node); mtk_clk_unregister_plls(plls, ARRAY_SIZE(plls), clk_data); mtk_free_clk_data(clk_data); - - return 0; } static const struct of_device_id of_match_clk_mt2712_apmixed[] = { @@ -158,7 +156,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt2712_apmixed); static struct platform_driver clk_mt2712_apmixed_drv = { .probe = clk_mt2712_apmixed_probe, - .remove = clk_mt2712_apmixed_remove, + .remove_new = clk_mt2712_apmixed_remove, .driver = { .name = "clk-mt2712-apmixed", .of_match_table = of_match_clk_mt2712_apmixed, diff --git a/drivers/clk/mediatek/clk-mt2712-bdp.c b/drivers/clk/mediatek/clk-mt2712-bdp.c index f78e0181931612c8e96686526e541f0cfb14d600..1b54b1f3808d1c1c2eaabafc24dc0b476ddf8d85 100644 --- a/drivers/clk/mediatek/clk-mt2712-bdp.c +++ b/drivers/clk/mediatek/clk-mt2712-bdp.c @@ -69,7 +69,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt2712_bdp); static struct platform_driver clk_mt2712_bdp_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt2712-bdp", .of_match_table = of_match_clk_mt2712_bdp, diff --git a/drivers/clk/mediatek/clk-mt2712-img.c b/drivers/clk/mediatek/clk-mt2712-img.c index fbe7084886a0ffa34c20cdda6c2bbea84333ebe2..1fecc0f68f0e078e9901f46c79e98755c3dbaffd 100644 --- a/drivers/clk/mediatek/clk-mt2712-img.c +++ b/drivers/clk/mediatek/clk-mt2712-img.c @@ -47,7 +47,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt2712_img); static struct platform_driver clk_mt2712_img_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt2712-img", .of_match_table = of_match_clk_mt2712_img, diff --git a/drivers/clk/mediatek/clk-mt2712-jpgdec.c b/drivers/clk/mediatek/clk-mt2712-jpgdec.c index 7e8c2ebcdee03f3538106d0eab3f1862bf352167..019080d6d0f0e3da687dab82b1c68048e4d87625 100644 --- a/drivers/clk/mediatek/clk-mt2712-jpgdec.c +++ b/drivers/clk/mediatek/clk-mt2712-jpgdec.c @@ -43,7 +43,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt2712_jpgdec); static struct platform_driver clk_mt2712_jpgdec_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt2712-jpgdec", .of_match_table = of_match_clk_mt2712_jpgdec, diff --git a/drivers/clk/mediatek/clk-mt2712-mfg.c b/drivers/clk/mediatek/clk-mt2712-mfg.c index 932ea449d29964f1c54e428c2e251a835a3e5a35..39161516cf21877fa6f5fd7e7f03005bb08a8acc 100644 --- a/drivers/clk/mediatek/clk-mt2712-mfg.c +++ b/drivers/clk/mediatek/clk-mt2712-mfg.c @@ -42,7 +42,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt2712_mfg); static struct platform_driver clk_mt2712_mfg_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt2712-mfg", .of_match_table = of_match_clk_mt2712_mfg, diff --git a/drivers/clk/mediatek/clk-mt2712-mm.c b/drivers/clk/mediatek/clk-mt2712-mm.c index 204a3eae08dc5c26225a16bfad2c85472bf2322c..15cb61fe2d2f47f6bd0bcee2f5425d81aff34a97 100644 --- a/drivers/clk/mediatek/clk-mt2712-mm.c +++ b/drivers/clk/mediatek/clk-mt2712-mm.c @@ -121,7 +121,7 @@ MODULE_DEVICE_TABLE(platform, clk_mt2712_mm_id_table); static struct platform_driver clk_mt2712_mm_drv = { .probe = mtk_clk_pdev_probe, - .remove = mtk_clk_pdev_remove, + .remove_new = mtk_clk_pdev_remove, .driver = { .name = "clk-mt2712-mm", }, diff --git a/drivers/clk/mediatek/clk-mt2712-vdec.c b/drivers/clk/mediatek/clk-mt2712-vdec.c index 2fc1f82ebf5dbaded76fb82930acc307f213116a..e1dd38fc2b3cd7a6c3072e8851d435921208e9d4 100644 --- a/drivers/clk/mediatek/clk-mt2712-vdec.c +++ b/drivers/clk/mediatek/clk-mt2712-vdec.c @@ -55,7 +55,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt2712_vdec); static struct platform_driver clk_mt2712_vdec_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt2712-vdec", .of_match_table = of_match_clk_mt2712_vdec, diff --git a/drivers/clk/mediatek/clk-mt2712-venc.c b/drivers/clk/mediatek/clk-mt2712-venc.c index 6d053a00cf95a8f62807ca94ebd08da8bf7b0587..ef6608a5db3869a28441f4fb672e497b3bbdf8f9 100644 --- a/drivers/clk/mediatek/clk-mt2712-venc.c +++ b/drivers/clk/mediatek/clk-mt2712-venc.c @@ -44,7 +44,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt2712_venc); static struct platform_driver clk_mt2712_venc_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt2712-venc", .of_match_table = of_match_clk_mt2712_venc, diff --git a/drivers/clk/mediatek/clk-mt2712.c b/drivers/clk/mediatek/clk-mt2712.c index 74c529f6163d91d9477aaeca15a85c598e11206b..c4cc68c47af9aade33eb651fc0d1eeeb24962b7b 100644 --- a/drivers/clk/mediatek/clk-mt2712.c +++ b/drivers/clk/mediatek/clk-mt2712.c @@ -995,7 +995,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt2712); static struct platform_driver clk_mt2712_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt2712", .of_match_table = of_match_clk_mt2712, diff --git a/drivers/clk/mediatek/clk-mt6765-audio.c b/drivers/clk/mediatek/clk-mt6765-audio.c index 9e98d699732907a14ef6f7e5b07eaa6e8ba90b63..901bf793c272a4649db59355202582d842ee992b 100644 --- a/drivers/clk/mediatek/clk-mt6765-audio.c +++ b/drivers/clk/mediatek/clk-mt6765-audio.c @@ -69,7 +69,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt6765_audio); static struct platform_driver clk_mt6765_audio_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt6765-audio", .of_match_table = of_match_clk_mt6765_audio, diff --git a/drivers/clk/mediatek/clk-mt6765-cam.c b/drivers/clk/mediatek/clk-mt6765-cam.c index 6f6b29d8b29a7225b781e4ba1c8b9d68cfe0efed..19cedfa832bc15ac083733c989c6f6d773d5697b 100644 --- a/drivers/clk/mediatek/clk-mt6765-cam.c +++ b/drivers/clk/mediatek/clk-mt6765-cam.c @@ -50,7 +50,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt6765_cam); static struct platform_driver clk_mt6765_cam_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt6765-cam", .of_match_table = of_match_clk_mt6765_cam, diff --git a/drivers/clk/mediatek/clk-mt6765-img.c b/drivers/clk/mediatek/clk-mt6765-img.c index 984201077a20e6d046c0166b11e4cd05572fd1b9..16e20c61932ea72043672e12b38dfe40c271f237 100644 --- a/drivers/clk/mediatek/clk-mt6765-img.c +++ b/drivers/clk/mediatek/clk-mt6765-img.c @@ -46,7 +46,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt6765_img); static struct platform_driver clk_mt6765_img_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt6765-img", .of_match_table = of_match_clk_mt6765_img, diff --git a/drivers/clk/mediatek/clk-mt6765-mipi0a.c b/drivers/clk/mediatek/clk-mt6765-mipi0a.c index a47937f4efe5a91289a3d2427ed5cacbcf176dbf..cc5bb0c95f08860dc1e649d9f47661afdec0c667 100644 --- a/drivers/clk/mediatek/clk-mt6765-mipi0a.c +++ b/drivers/clk/mediatek/clk-mt6765-mipi0a.c @@ -43,7 +43,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt6765_mipi0a); static struct platform_driver clk_mt6765_mipi0a_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt6765-mipi0a", .of_match_table = of_match_clk_mt6765_mipi0a, diff --git a/drivers/clk/mediatek/clk-mt6765-mm.c b/drivers/clk/mediatek/clk-mt6765-mm.c index 2b8fc052558ee12bbf35ea49ec48a408c66d7410..fc5842e13b78f820ebf5bb9f440066f0a85625d2 100644 --- a/drivers/clk/mediatek/clk-mt6765-mm.c +++ b/drivers/clk/mediatek/clk-mt6765-mm.c @@ -72,7 +72,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt6765_mm); static struct platform_driver clk_mt6765_mm_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt6765-mm", .of_match_table = of_match_clk_mt6765_mm, diff --git a/drivers/clk/mediatek/clk-mt6765-vcodec.c b/drivers/clk/mediatek/clk-mt6765-vcodec.c index 36df9615b1be421c3192e21e2b412fefa42de53e..d6e036795b0aba14154460b2f2d78b229a414f00 100644 --- a/drivers/clk/mediatek/clk-mt6765-vcodec.c +++ b/drivers/clk/mediatek/clk-mt6765-vcodec.c @@ -45,7 +45,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt6765_vcodec); static struct platform_driver clk_mt6765_vcodec_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt6765-vcodec", .of_match_table = of_match_clk_mt6765_vcodec, diff --git a/drivers/clk/mediatek/clk-mt6765.c b/drivers/clk/mediatek/clk-mt6765.c index fa7948ef1e68b2f1cd1851ae712f8299644e09e1..0377e6dd3206a6c8e5feb60a2a6d826f94bb3f41 100644 --- a/drivers/clk/mediatek/clk-mt6765.c +++ b/drivers/clk/mediatek/clk-mt6765.c @@ -367,10 +367,12 @@ static const struct mtk_mux top_muxes[] = { /* CLK_CFG_0 */ MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_AXI_SEL, "axi_sel", axi_parents, CLK_CFG_0, CLK_CFG_0_SET, CLK_CFG_0_CLR, - 0, 2, 7, CLK_CFG_UPDATE, 0, CLK_IS_CRITICAL), + 0, 2, 7, CLK_CFG_UPDATE, 0, + CLK_IS_CRITICAL | CLK_SET_RATE_PARENT), MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_MEM_SEL, "mem_sel", mem_parents, CLK_CFG_0, CLK_CFG_0_SET, CLK_CFG_0_CLR, - 8, 2, 15, CLK_CFG_UPDATE, 1, CLK_IS_CRITICAL), + 8, 2, 15, CLK_CFG_UPDATE, 1, + CLK_IS_CRITICAL | CLK_SET_RATE_PARENT), MUX_GATE_CLR_SET_UPD(CLK_TOP_MM_SEL, "mm_sel", mm_parents, CLK_CFG_0, CLK_CFG_0_SET, CLK_CFG_0_CLR, 16, 3, 23, CLK_CFG_UPDATE, 2), @@ -404,15 +406,15 @@ static const struct mtk_mux top_muxes[] = { CLK_CFG_2_SET, CLK_CFG_2_CLR, 24, 2, 31, CLK_CFG_UPDATE, 11), /* CLK_CFG_3 */ - MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC50_0_HCLK_SEL, "msdc5hclk", + MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_MSDC50_0_HCLK_SEL, "msdc5hclk", msdc5hclk_parents, CLK_CFG_3, CLK_CFG_3_SET, - CLK_CFG_3_CLR, 0, 2, 7, CLK_CFG_UPDATE, 12), - MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC50_0_SEL, "msdc50_0_sel", + CLK_CFG_3_CLR, 0, 2, 7, CLK_CFG_UPDATE, 12, 0), + MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_MSDC50_0_SEL, "msdc50_0_sel", msdc50_0_parents, CLK_CFG_3, CLK_CFG_3_SET, - CLK_CFG_3_CLR, 8, 3, 15, CLK_CFG_UPDATE, 13), - MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC30_1_SEL, "msdc30_1_sel", + CLK_CFG_3_CLR, 8, 3, 15, CLK_CFG_UPDATE, 13, 0), + MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_MSDC30_1_SEL, "msdc30_1_sel", msdc30_1_parents, CLK_CFG_3, CLK_CFG_3_SET, - CLK_CFG_3_CLR, 16, 3, 23, CLK_CFG_UPDATE, 14), + CLK_CFG_3_CLR, 16, 3, 23, CLK_CFG_UPDATE, 14, 0), MUX_GATE_CLR_SET_UPD(CLK_TOP_AUDIO_SEL, "audio_sel", audio_parents, CLK_CFG_3, CLK_CFG_3_SET, CLK_CFG_3_CLR, 24, 2, 31, CLK_CFG_UPDATE, 15), @@ -459,7 +461,7 @@ static const struct mtk_mux top_muxes[] = { MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_PWRAP_ULPOSC_SEL, "ulposc_sel", ulposc_parents, CLK_CFG_7, CLK_CFG_7_SET, CLK_CFG_7_CLR, 0, 3, 7, CLK_CFG_UPDATE, 28, - CLK_IS_CRITICAL), + CLK_IS_CRITICAL | CLK_SET_RATE_PARENT), MUX_GATE_CLR_SET_UPD(CLK_TOP_CAMTM_SEL, "camtm_sel", camtm_parents, CLK_CFG_7, CLK_CFG_7_SET, CLK_CFG_7_CLR, 8, 2, 15, CLK_CFG_UPDATE, 29), diff --git a/drivers/clk/mediatek/clk-mt6779-aud.c b/drivers/clk/mediatek/clk-mt6779-aud.c index 6e3280d3a2e60a5f750368c2ccc191d9c0b5d850..a97e1117d30b9807d3736ca69566011989ce4c7f 100644 --- a/drivers/clk/mediatek/clk-mt6779-aud.c +++ b/drivers/clk/mediatek/clk-mt6779-aud.c @@ -106,7 +106,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt6779_aud); static struct platform_driver clk_mt6779_aud_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt6779-aud", .of_match_table = of_match_clk_mt6779_aud, diff --git a/drivers/clk/mediatek/clk-mt6779-cam.c b/drivers/clk/mediatek/clk-mt6779-cam.c index b4c4c7248672c099126f47eed6e1b77dea505233..7b1a40d891adbe13ea88c929966d92c87337f197 100644 --- a/drivers/clk/mediatek/clk-mt6779-cam.c +++ b/drivers/clk/mediatek/clk-mt6779-cam.c @@ -55,7 +55,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt6779_cam); static struct platform_driver clk_mt6779_cam_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt6779-cam", .of_match_table = of_match_clk_mt6779_cam, diff --git a/drivers/clk/mediatek/clk-mt6779-img.c b/drivers/clk/mediatek/clk-mt6779-img.c index b760a8af3462d82299b9b52f3e727ec63a797e5b..1c53209f60a9703632d6e0522ffce0d7307f4ef3 100644 --- a/drivers/clk/mediatek/clk-mt6779-img.c +++ b/drivers/clk/mediatek/clk-mt6779-img.c @@ -47,7 +47,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt6779_img); static struct platform_driver clk_mt6779_img_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt6779-img", .of_match_table = of_match_clk_mt6779_img, diff --git a/drivers/clk/mediatek/clk-mt6779-ipe.c b/drivers/clk/mediatek/clk-mt6779-ipe.c index 9285a792c59b21e491acd4e622742432d440b5d7..784bc08ace5e0c69132582cfb707eea64a5e4001 100644 --- a/drivers/clk/mediatek/clk-mt6779-ipe.c +++ b/drivers/clk/mediatek/clk-mt6779-ipe.c @@ -49,7 +49,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt6779_ipe); static struct platform_driver clk_mt6779_ipe_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt6779-ipe", .of_match_table = of_match_clk_mt6779_ipe, diff --git a/drivers/clk/mediatek/clk-mt6779-mfg.c b/drivers/clk/mediatek/clk-mt6779-mfg.c index d20f32d4f827108854944d643a2b3e0331c0affb..040e4c45fa5f0a753f1feef62d17a513512801be 100644 --- a/drivers/clk/mediatek/clk-mt6779-mfg.c +++ b/drivers/clk/mediatek/clk-mt6779-mfg.c @@ -44,7 +44,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt6779_mfg); static struct platform_driver clk_mt6779_mfg_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt6779-mfg", .of_match_table = of_match_clk_mt6779_mfg, diff --git a/drivers/clk/mediatek/clk-mt6779-mm.c b/drivers/clk/mediatek/clk-mt6779-mm.c index c2f700ae6c2c82be110339310ec94134610fcf2d..5e17e441f6797b8f6f9f5f554d40feedb437ad87 100644 --- a/drivers/clk/mediatek/clk-mt6779-mm.c +++ b/drivers/clk/mediatek/clk-mt6779-mm.c @@ -98,7 +98,7 @@ MODULE_DEVICE_TABLE(platform, clk_mt6779_mm_id_table); static struct platform_driver clk_mt6779_mm_drv = { .probe = mtk_clk_pdev_probe, - .remove = mtk_clk_pdev_remove, + .remove_new = mtk_clk_pdev_remove, .driver = { .name = "clk-mt6779-mm", }, diff --git a/drivers/clk/mediatek/clk-mt6779-vdec.c b/drivers/clk/mediatek/clk-mt6779-vdec.c index e062ed5aa45fde8e0e601a4135f25e8f7af9c1ea..a411c23512b7268ee20d408a93446cd13b99c8c1 100644 --- a/drivers/clk/mediatek/clk-mt6779-vdec.c +++ b/drivers/clk/mediatek/clk-mt6779-vdec.c @@ -56,7 +56,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt6779_vdec); static struct platform_driver clk_mt6779_vdec_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt6779-vdec", .of_match_table = of_match_clk_mt6779_vdec, diff --git a/drivers/clk/mediatek/clk-mt6779-venc.c b/drivers/clk/mediatek/clk-mt6779-venc.c index 0ae8ac28f8386c42da82373235f679e400f80225..f14512d284d6cc30da63a22990bb9a92cb0f0745 100644 --- a/drivers/clk/mediatek/clk-mt6779-venc.c +++ b/drivers/clk/mediatek/clk-mt6779-venc.c @@ -47,7 +47,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt6779_venc); static struct platform_driver clk_mt6779_venc_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt6779-venc", .of_match_table = of_match_clk_mt6779_venc, diff --git a/drivers/clk/mediatek/clk-mt6779.c b/drivers/clk/mediatek/clk-mt6779.c index 1f5ea1508f612a12a642dd238513a405a7d13656..f33fbaee14048a9c5df02495aeda83d36b3b9bae 100644 --- a/drivers/clk/mediatek/clk-mt6779.c +++ b/drivers/clk/mediatek/clk-mt6779.c @@ -640,7 +640,7 @@ static const struct mtk_mux top_muxes[] = { /* CLK_CFG_0 */ MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_AXI, "axi_sel", axi_parents, 0x20, 0x24, 0x28, 0, 2, 7, - 0x004, 0, CLK_IS_CRITICAL), + 0x004, 0, CLK_IS_CRITICAL | CLK_SET_RATE_PARENT), MUX_GATE_CLR_SET_UPD(CLK_TOP_MM, "mm_sel", mm_parents, 0x20, 0x24, 0x28, 8, 3, 15, 0x004, 1), MUX_GATE_CLR_SET_UPD(CLK_TOP_SCP, "scp_sel", scp_parents, @@ -687,16 +687,16 @@ static const struct mtk_mux top_muxes[] = { 0x70, 0x74, 0x78, 0, 1, 7, 0x004, 20), MUX_GATE_CLR_SET_UPD(CLK_TOP_SPI, "spi_sel", spi_parents, 0x70, 0x74, 0x78, 8, 2, 15, 0x004, 21), - MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC50_0_HCLK, "msdc50_hclk_sel", - msdc50_hclk_parents, 0x70, 0x74, 0x78, - 16, 2, 23, 0x004, 22), - MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC50_0, "msdc50_0_sel", - msdc50_0_parents, 0x70, 0x74, 0x78, - 24, 3, 31, 0x004, 23), + MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_MSDC50_0_HCLK, "msdc50_hclk_sel", + msdc50_hclk_parents, 0x70, 0x74, 0x78, + 16, 2, 23, 0x004, 22, 0), + MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_MSDC50_0, "msdc50_0_sel", + msdc50_0_parents, 0x70, 0x74, 0x78, + 24, 3, 31, 0x004, 23, 0), /* CLK_CFG_6 */ - MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC30_1, "msdc30_1_sel", - msdc30_1_parents, 0x80, 0x84, 0x88, - 0, 3, 7, 0x004, 24), + MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_MSDC30_1, "msdc30_1_sel", + msdc30_1_parents, 0x80, 0x84, 0x88, + 0, 3, 7, 0x004, 24, 0), MUX_GATE_CLR_SET_UPD(CLK_TOP_AUD, "audio_sel", audio_parents, 0x80, 0x84, 0x88, 8, 2, 15, 0x004, 25), MUX_GATE_CLR_SET_UPD(CLK_TOP_AUD_INTBUS, "aud_intbus_sel", @@ -710,7 +710,7 @@ static const struct mtk_mux top_muxes[] = { 0x90, 0x94, 0x98, 0, 2, 7, 0x004, 28), MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_SSPM, "sspm_sel", sspm_parents, 0x90, 0x94, 0x98, 8, 3, 15, - 0x004, 29, CLK_IS_CRITICAL), + 0x004, 29, CLK_IS_CRITICAL | CLK_SET_RATE_PARENT), MUX_GATE_CLR_SET_UPD(CLK_TOP_DPI0, "dpi0_sel", dpi0_parents, 0x90, 0x94, 0x98, 16, 3, 23, 0x004, 30), MUX_GATE_CLR_SET_UPD(CLK_TOP_SCAM, "scam_sel", scam_parents, @@ -727,7 +727,7 @@ static const struct mtk_mux top_muxes[] = { 16, 2, 23, 0x008, 3), MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_SPM, "spm_sel", spm_parents, 0xa0, 0xa4, 0xa8, 24, 2, 31, - 0x008, 4, CLK_IS_CRITICAL), + 0x008, 4, CLK_IS_CRITICAL | CLK_SET_RATE_PARENT), /* CLK_CFG_9 */ MUX_GATE_CLR_SET_UPD(CLK_TOP_I2C, "i2c_sel", i2c_parents, 0xb0, 0xb4, 0xb8, 0, 2, 7, 0x008, 5), @@ -1303,7 +1303,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt6779); static struct platform_driver clk_mt6779_infra_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt6779-infra", .of_match_table = of_match_clk_mt6779_infra, diff --git a/drivers/clk/mediatek/clk-mt6795-apmixedsys.c b/drivers/clk/mediatek/clk-mt6795-apmixedsys.c index 8b30109f253cf910b2f3db2d23e45d9b33b6efb5..8c65974ed9b870c758bcb463ee1db9da68da16f8 100644 --- a/drivers/clk/mediatek/clk-mt6795-apmixedsys.c +++ b/drivers/clk/mediatek/clk-mt6795-apmixedsys.c @@ -187,7 +187,7 @@ static int clk_mt6795_apmixed_probe(struct platform_device *pdev) return ret; } -static int clk_mt6795_apmixed_remove(struct platform_device *pdev) +static void clk_mt6795_apmixed_remove(struct platform_device *pdev) { struct device_node *node = pdev->dev.of_node; struct clk_hw_onecell_data *clk_data = platform_get_drvdata(pdev); @@ -197,13 +197,11 @@ static int clk_mt6795_apmixed_remove(struct platform_device *pdev) mtk_clk_unregister_pllfhs(plls, ARRAY_SIZE(plls), pllfhs, ARRAY_SIZE(pllfhs), clk_data); mtk_free_clk_data(clk_data); - - return 0; } static struct platform_driver clk_mt6795_apmixed_drv = { .probe = clk_mt6795_apmixed_probe, - .remove = clk_mt6795_apmixed_remove, + .remove_new = clk_mt6795_apmixed_remove, .driver = { .name = "clk-mt6795-apmixed", .of_match_table = of_match_clk_mt6795_apmixed, diff --git a/drivers/clk/mediatek/clk-mt6795-infracfg.c b/drivers/clk/mediatek/clk-mt6795-infracfg.c index 086ea1438564f35473b549ccba43cd5bc00debe8..06d7fdf3098b0c5eae7ddd0d65ca52756b83e029 100644 --- a/drivers/clk/mediatek/clk-mt6795-infracfg.c +++ b/drivers/clk/mediatek/clk-mt6795-infracfg.c @@ -127,7 +127,7 @@ static int clk_mt6795_infracfg_probe(struct platform_device *pdev) return ret; } -static int clk_mt6795_infracfg_remove(struct platform_device *pdev) +static void clk_mt6795_infracfg_remove(struct platform_device *pdev) { struct device_node *node = pdev->dev.of_node; struct clk_hw_onecell_data *clk_data = platform_get_drvdata(pdev); @@ -136,8 +136,6 @@ static int clk_mt6795_infracfg_remove(struct platform_device *pdev) mtk_clk_unregister_cpumuxes(cpu_muxes, ARRAY_SIZE(cpu_muxes), clk_data); mtk_clk_unregister_gates(infra_gates, ARRAY_SIZE(infra_gates), clk_data); mtk_free_clk_data(clk_data); - - return 0; } static struct platform_driver clk_mt6795_infracfg_drv = { @@ -146,7 +144,7 @@ static struct platform_driver clk_mt6795_infracfg_drv = { .of_match_table = of_match_clk_mt6795_infracfg, }, .probe = clk_mt6795_infracfg_probe, - .remove = clk_mt6795_infracfg_remove, + .remove_new = clk_mt6795_infracfg_remove, }; module_platform_driver(clk_mt6795_infracfg_drv); diff --git a/drivers/clk/mediatek/clk-mt6795-mfg.c b/drivers/clk/mediatek/clk-mt6795-mfg.c index 1d658bb19e822f739eeb73678d0a1c6f45149317..dff6a6ded837c79c25a44edbc95f24a36eb2394b 100644 --- a/drivers/clk/mediatek/clk-mt6795-mfg.c +++ b/drivers/clk/mediatek/clk-mt6795-mfg.c @@ -43,7 +43,7 @@ static struct platform_driver clk_mt6795_mfg_drv = { .of_match_table = of_match_clk_mt6795_mfg, }, .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, }; module_platform_driver(clk_mt6795_mfg_drv); diff --git a/drivers/clk/mediatek/clk-mt6795-mm.c b/drivers/clk/mediatek/clk-mt6795-mm.c index 8acc9cad2875b67de1cc0f8cad74c2aa03df461f..ced6e310d694c7a660f9417aaea4c80c8a7a6445 100644 --- a/drivers/clk/mediatek/clk-mt6795-mm.c +++ b/drivers/clk/mediatek/clk-mt6795-mm.c @@ -93,7 +93,7 @@ static struct platform_driver clk_mt6795_mm_drv = { }, .id_table = clk_mt6795_mm_id_table, .probe = mtk_clk_pdev_probe, - .remove = mtk_clk_pdev_remove, + .remove_new = mtk_clk_pdev_remove, }; module_platform_driver(clk_mt6795_mm_drv); diff --git a/drivers/clk/mediatek/clk-mt6795-pericfg.c b/drivers/clk/mediatek/clk-mt6795-pericfg.c index 62cc19eee2c787be69b8c7acbd0cc56b7d925aa5..3f6bea418a5ac1c133ee36f64eb0dd6fdfbc930d 100644 --- a/drivers/clk/mediatek/clk-mt6795-pericfg.c +++ b/drivers/clk/mediatek/clk-mt6795-pericfg.c @@ -136,7 +136,7 @@ static int clk_mt6795_pericfg_probe(struct platform_device *pdev) return ret; } -static int clk_mt6795_pericfg_remove(struct platform_device *pdev) +static void clk_mt6795_pericfg_remove(struct platform_device *pdev) { struct device_node *node = pdev->dev.of_node; struct clk_hw_onecell_data *clk_data = platform_get_drvdata(pdev); @@ -145,8 +145,6 @@ static int clk_mt6795_pericfg_remove(struct platform_device *pdev) mtk_clk_unregister_composites(peri_clks, ARRAY_SIZE(peri_clks), clk_data); mtk_clk_unregister_gates(peri_gates, ARRAY_SIZE(peri_gates), clk_data); mtk_free_clk_data(clk_data); - - return 0; } static struct platform_driver clk_mt6795_pericfg_drv = { @@ -155,7 +153,7 @@ static struct platform_driver clk_mt6795_pericfg_drv = { .of_match_table = of_match_clk_mt6795_pericfg, }, .probe = clk_mt6795_pericfg_probe, - .remove = clk_mt6795_pericfg_remove, + .remove_new = clk_mt6795_pericfg_remove, }; module_platform_driver(clk_mt6795_pericfg_drv); diff --git a/drivers/clk/mediatek/clk-mt6795-topckgen.c b/drivers/clk/mediatek/clk-mt6795-topckgen.c index 9c6d63a80b19b8ede1b6349fc1e1007a3dba2e5a..be595853a925869640e89958f4377ab0f3df068b 100644 --- a/drivers/clk/mediatek/clk-mt6795-topckgen.c +++ b/drivers/clk/mediatek/clk-mt6795-topckgen.c @@ -547,7 +547,7 @@ static struct platform_driver clk_mt6795_topckgen_drv = { .of_match_table = of_match_clk_mt6795_topckgen, }, .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, }; module_platform_driver(clk_mt6795_topckgen_drv); diff --git a/drivers/clk/mediatek/clk-mt6795-vdecsys.c b/drivers/clk/mediatek/clk-mt6795-vdecsys.c index f2968f859dca09a538640e36fa6bdda9b9f84a59..9e91d6f7f5bf400dfab5cdb764284f6e72b3514c 100644 --- a/drivers/clk/mediatek/clk-mt6795-vdecsys.c +++ b/drivers/clk/mediatek/clk-mt6795-vdecsys.c @@ -44,7 +44,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt6795_vdecsys); static struct platform_driver clk_mt6795_vdecsys_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt6795-vdecsys", .of_match_table = of_match_clk_mt6795_vdecsys, diff --git a/drivers/clk/mediatek/clk-mt6795-vencsys.c b/drivers/clk/mediatek/clk-mt6795-vencsys.c index 2f8d48da1a8599e1b9d790cb3cdb95c2e9f10758..bd81e80b744fb8ff7a7ecfc4e05e34b5d899ae9c 100644 --- a/drivers/clk/mediatek/clk-mt6795-vencsys.c +++ b/drivers/clk/mediatek/clk-mt6795-vencsys.c @@ -43,7 +43,7 @@ static struct platform_driver clk_mt6795_vencsys_drv = { .of_match_table = of_match_clk_mt6795_vencsys, }, .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, }; module_platform_driver(clk_mt6795_vencsys_drv); diff --git a/drivers/clk/mediatek/clk-mt6797-img.c b/drivers/clk/mediatek/clk-mt6797-img.c index 00fc0a03e646e3ca3b7d5bc88f299bdcb4724151..e1c1ee692a1d452513db203fe150ad7a5c6291b4 100644 --- a/drivers/clk/mediatek/clk-mt6797-img.c +++ b/drivers/clk/mediatek/clk-mt6797-img.c @@ -43,7 +43,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt6797_img); static struct platform_driver clk_mt6797_img_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt6797-img", .of_match_table = of_match_clk_mt6797_img, diff --git a/drivers/clk/mediatek/clk-mt6797-mm.c b/drivers/clk/mediatek/clk-mt6797-mm.c index caacfa40a5bc37c31f7414a26e7deee82398d61e..5b0a77530b62e0d258799e2135261b9be008ccec 100644 --- a/drivers/clk/mediatek/clk-mt6797-mm.c +++ b/drivers/clk/mediatek/clk-mt6797-mm.c @@ -93,7 +93,7 @@ MODULE_DEVICE_TABLE(platform, clk_mt6797_mm_id_table); static struct platform_driver clk_mt6797_mm_drv = { .probe = mtk_clk_pdev_probe, - .remove = mtk_clk_pdev_remove, + .remove_new = mtk_clk_pdev_remove, .driver = { .name = "clk-mt6797-mm", }, diff --git a/drivers/clk/mediatek/clk-mt6797-vdec.c b/drivers/clk/mediatek/clk-mt6797-vdec.c index 447fe6fa8e15a9b2e60d6f3b9c23ae4cc82e5ee3..0ed6710ab88e0f0f35b28f9a5f88e620fd41b29e 100644 --- a/drivers/clk/mediatek/clk-mt6797-vdec.c +++ b/drivers/clk/mediatek/clk-mt6797-vdec.c @@ -54,7 +54,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt6797_vdec); static struct platform_driver clk_mt6797_vdec_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt6797-vdec", .of_match_table = of_match_clk_mt6797_vdec, diff --git a/drivers/clk/mediatek/clk-mt6797-venc.c b/drivers/clk/mediatek/clk-mt6797-venc.c index 95b89ff8fd1975601336dc88e83469df2bdfe05a..93d1da7423fe77a3252d0b4d676d80a27304e769 100644 --- a/drivers/clk/mediatek/clk-mt6797-venc.c +++ b/drivers/clk/mediatek/clk-mt6797-venc.c @@ -45,7 +45,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt6797_venc); static struct platform_driver clk_mt6797_venc_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt6797-venc", .of_match_table = of_match_clk_mt6797_venc, diff --git a/drivers/clk/mediatek/clk-mt7622-apmixedsys.c b/drivers/clk/mediatek/clk-mt7622-apmixedsys.c index a36808d074d64716816ec58b79a37d0b0d746ade..9cffd278e9a43e6a0d7d5761f91adbc71f3ab479 100644 --- a/drivers/clk/mediatek/clk-mt7622-apmixedsys.c +++ b/drivers/clk/mediatek/clk-mt7622-apmixedsys.c @@ -119,7 +119,7 @@ static int clk_mt7622_apmixed_probe(struct platform_device *pdev) return ret; } -static int clk_mt7622_apmixed_remove(struct platform_device *pdev) +static void clk_mt7622_apmixed_remove(struct platform_device *pdev) { struct device_node *node = pdev->dev.of_node; struct clk_hw_onecell_data *clk_data = platform_get_drvdata(pdev); @@ -128,8 +128,6 @@ static int clk_mt7622_apmixed_remove(struct platform_device *pdev) mtk_clk_unregister_gates(apmixed_clks, ARRAY_SIZE(apmixed_clks), clk_data); mtk_clk_unregister_plls(plls, ARRAY_SIZE(plls), clk_data); mtk_free_clk_data(clk_data); - - return 0; } static const struct of_device_id of_match_clk_mt7622_apmixed[] = { @@ -140,7 +138,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt7622_apmixed); static struct platform_driver clk_mt7622_apmixed_drv = { .probe = clk_mt7622_apmixed_probe, - .remove = clk_mt7622_apmixed_remove, + .remove_new = clk_mt7622_apmixed_remove, .driver = { .name = "clk-mt7622-apmixed", .of_match_table = of_match_clk_mt7622_apmixed, diff --git a/drivers/clk/mediatek/clk-mt7622-aud.c b/drivers/clk/mediatek/clk-mt7622-aud.c index dd1799dd843590d45800e9d600d1a675e27b65eb..c3ce65ced902f595f1e10e6a9ebde8b597a8ce8a 100644 --- a/drivers/clk/mediatek/clk-mt7622-aud.c +++ b/drivers/clk/mediatek/clk-mt7622-aud.c @@ -135,10 +135,10 @@ static int clk_mt7622_aud_probe(struct platform_device *pdev) return r; } -static int clk_mt7622_aud_remove(struct platform_device *pdev) +static void clk_mt7622_aud_remove(struct platform_device *pdev) { of_platform_depopulate(&pdev->dev); - return mtk_clk_simple_remove(pdev); + mtk_clk_simple_remove(pdev); } static const struct of_device_id of_match_clk_mt7622_aud[] = { @@ -149,7 +149,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt7622_aud); static struct platform_driver clk_mt7622_aud_drv = { .probe = clk_mt7622_aud_probe, - .remove = clk_mt7622_aud_remove, + .remove_new = clk_mt7622_aud_remove, .driver = { .name = "clk-mt7622-aud", .of_match_table = of_match_clk_mt7622_aud, diff --git a/drivers/clk/mediatek/clk-mt7622-eth.c b/drivers/clk/mediatek/clk-mt7622-eth.c index f96b3673702959c76288e9b78791b5b211070575..df81e445026aeb35155813eca5913fae69ce1f70 100644 --- a/drivers/clk/mediatek/clk-mt7622-eth.c +++ b/drivers/clk/mediatek/clk-mt7622-eth.c @@ -81,7 +81,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt7622_eth); static struct platform_driver clk_mt7622_eth_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt7622-eth", .of_match_table = of_match_clk_mt7622_eth, diff --git a/drivers/clk/mediatek/clk-mt7622-hif.c b/drivers/clk/mediatek/clk-mt7622-hif.c index f440943f0d46729e97f8584d55ceae1b83478b25..9c738d730a7b11491e6055074eb6ea1392717162 100644 --- a/drivers/clk/mediatek/clk-mt7622-hif.c +++ b/drivers/clk/mediatek/clk-mt7622-hif.c @@ -93,7 +93,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt7622_hif); static struct platform_driver clk_mt7622_hif_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt7622-hif", .of_match_table = of_match_clk_mt7622_hif, diff --git a/drivers/clk/mediatek/clk-mt7622-infracfg.c b/drivers/clk/mediatek/clk-mt7622-infracfg.c index 9dc05526f2870c9f230d56e8e7a0f4998ec82371..6bc911cb29a67019a64a54b7af674999df96c9af 100644 --- a/drivers/clk/mediatek/clk-mt7622-infracfg.c +++ b/drivers/clk/mediatek/clk-mt7622-infracfg.c @@ -101,7 +101,7 @@ static int clk_mt7622_infracfg_probe(struct platform_device *pdev) return ret; } -static int clk_mt7622_infracfg_remove(struct platform_device *pdev) +static void clk_mt7622_infracfg_remove(struct platform_device *pdev) { struct device_node *node = pdev->dev.of_node; struct clk_hw_onecell_data *clk_data = platform_get_drvdata(pdev); @@ -110,8 +110,6 @@ static int clk_mt7622_infracfg_remove(struct platform_device *pdev) mtk_clk_unregister_cpumuxes(cpu_muxes, ARRAY_SIZE(cpu_muxes), clk_data); mtk_clk_unregister_gates(infra_clks, ARRAY_SIZE(infra_clks), clk_data); mtk_free_clk_data(clk_data); - - return 0; } static struct platform_driver clk_mt7622_infracfg_drv = { @@ -120,7 +118,7 @@ static struct platform_driver clk_mt7622_infracfg_drv = { .of_match_table = of_match_clk_mt7622_infracfg, }, .probe = clk_mt7622_infracfg_probe, - .remove = clk_mt7622_infracfg_remove, + .remove_new = clk_mt7622_infracfg_remove, }; module_platform_driver(clk_mt7622_infracfg_drv); diff --git a/drivers/clk/mediatek/clk-mt7622.c b/drivers/clk/mediatek/clk-mt7622.c index 274895264427af01c7825d6d8e251119884b2ff4..fa5fb5891a09945cc70af7eb3048955a5eb2edf8 100644 --- a/drivers/clk/mediatek/clk-mt7622.c +++ b/drivers/clk/mediatek/clk-mt7622.c @@ -526,7 +526,7 @@ static struct platform_driver clk_mt7622_drv = { .of_match_table = of_match_clk_mt7622, }, .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, }; module_platform_driver(clk_mt7622_drv) diff --git a/drivers/clk/mediatek/clk-mt7629-hif.c b/drivers/clk/mediatek/clk-mt7629-hif.c index c89036bee9a7284c4a51b825a862036c1b1ad7a0..ec3a71ebb76641fbbd72f1d95828b3b539a4d141 100644 --- a/drivers/clk/mediatek/clk-mt7629-hif.c +++ b/drivers/clk/mediatek/clk-mt7629-hif.c @@ -88,7 +88,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt7629_hif); static struct platform_driver clk_mt7629_hif_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt7629-hif", .of_match_table = of_match_clk_mt7629_hif, diff --git a/drivers/clk/mediatek/clk-mt7981-eth.c b/drivers/clk/mediatek/clk-mt7981-eth.c index b1f256b5ed4e7029ae7fabd3d40ef5ff7b22fae9..6bc509a54e14dd77b4bb6d74a25fd5b2c36cad09 100644 --- a/drivers/clk/mediatek/clk-mt7981-eth.c +++ b/drivers/clk/mediatek/clk-mt7981-eth.c @@ -109,7 +109,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt7981_eth); static struct platform_driver clk_mt7981_eth_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt7981-eth", .of_match_table = of_match_clk_mt7981_eth, diff --git a/drivers/clk/mediatek/clk-mt7981-infracfg.c b/drivers/clk/mediatek/clk-mt7981-infracfg.c index 293261ef71e62842bad475e856ff226b588f9cb9..7e9d3d309151a0adf1ee5e840ce032c8d997ce56 100644 --- a/drivers/clk/mediatek/clk-mt7981-infracfg.c +++ b/drivers/clk/mediatek/clk-mt7981-infracfg.c @@ -199,7 +199,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt7981_infracfg); static struct platform_driver clk_mt7981_infracfg_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt7981-infracfg", .of_match_table = of_match_clk_mt7981_infracfg, diff --git a/drivers/clk/mediatek/clk-mt7981-topckgen.c b/drivers/clk/mediatek/clk-mt7981-topckgen.c index 3aba1a9b9a36a60c574e9ebfefd072eadb5be36e..4740776e7aabd9055da03d89a0377c34e2381a5e 100644 --- a/drivers/clk/mediatek/clk-mt7981-topckgen.c +++ b/drivers/clk/mediatek/clk-mt7981-topckgen.c @@ -310,12 +310,12 @@ static const struct mtk_mux top_muxes[] = { pextp_tl_ck_parents, 0x010, 0x014, 0x018, 24, 2, 31, 0x1C0, 7), /* CLK_CFG_2 */ - MUX_GATE_CLR_SET_UPD(CLK_TOP_EMMC_208M_SEL, "emmc_208m_sel", - emmc_208m_parents, 0x020, 0x024, 0x028, 0, 3, 7, - 0x1C0, 8), - MUX_GATE_CLR_SET_UPD(CLK_TOP_EMMC_400M_SEL, "emmc_400m_sel", - emmc_400m_parents, 0x020, 0x024, 0x028, 8, 2, 15, - 0x1C0, 9), + MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_EMMC_208M_SEL, "emmc_208m_sel", + emmc_208m_parents, 0x020, 0x024, 0x028, 0, 3, 7, + 0x1C0, 8, 0), + MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_EMMC_400M_SEL, "emmc_400m_sel", + emmc_400m_parents, 0x020, 0x024, 0x028, 8, 2, 15, + 0x1C0, 9, 0), MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_F26M_SEL, "csw_f26m_sel", csw_f26m_parents, 0x020, 0x024, 0x028, 16, 1, 23, 0x1C0, 10, @@ -414,7 +414,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt7981_topckgen); static struct platform_driver clk_mt7981_topckgen_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt7981-topckgen", .of_match_table = of_match_clk_mt7981_topckgen, diff --git a/drivers/clk/mediatek/clk-mt7986-eth.c b/drivers/clk/mediatek/clk-mt7986-eth.c index 0681988960cc3ce4477de8f9054fd9fb7dba78e8..854e2c565041ef4c0101dd6bdffb03f789d4cf67 100644 --- a/drivers/clk/mediatek/clk-mt7986-eth.c +++ b/drivers/clk/mediatek/clk-mt7986-eth.c @@ -94,7 +94,7 @@ static struct platform_driver clk_mt7986_eth_drv = { .of_match_table = of_match_clk_mt7986_eth, }, .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, }; module_platform_driver(clk_mt7986_eth_drv); diff --git a/drivers/clk/mediatek/clk-mt7986-infracfg.c b/drivers/clk/mediatek/clk-mt7986-infracfg.c index b7efa70c2d6c271c4fb57819a8b20fa6dbe2925c..c576e9fb986c69198967cc1d3501bd605f19a419 100644 --- a/drivers/clk/mediatek/clk-mt7986-infracfg.c +++ b/drivers/clk/mediatek/clk-mt7986-infracfg.c @@ -179,7 +179,7 @@ static struct platform_driver clk_mt7986_infracfg_drv = { .of_match_table = of_match_clk_mt7986_infracfg, }, .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, }; module_platform_driver(clk_mt7986_infracfg_drv); diff --git a/drivers/clk/mediatek/clk-mt7986-topckgen.c b/drivers/clk/mediatek/clk-mt7986-topckgen.c index fbca3feded8f0f14bf246c1b05832a57f3d43690..af151b0168724d1aa768aed0e1a5cc6e867d819a 100644 --- a/drivers/clk/mediatek/clk-mt7986-topckgen.c +++ b/drivers/clk/mediatek/clk-mt7986-topckgen.c @@ -193,12 +193,12 @@ static const struct mtk_mux top_muxes[] = { pextp_tl_ck_parents, 0x010, 0x014, 0x018, 24, 2, 31, 0x1C0, 7), /* CLK_CFG_2 */ - MUX_GATE_CLR_SET_UPD(CLK_TOP_EMMC_250M_SEL, "emmc_250m_sel", - emmc_250m_parents, 0x020, 0x024, 0x028, 0, 1, 7, - 0x1C0, 8), - MUX_GATE_CLR_SET_UPD(CLK_TOP_EMMC_416M_SEL, "emmc_416m_sel", - emmc_416m_parents, 0x020, 0x024, 0x028, 8, 1, 15, - 0x1C0, 9), + MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_EMMC_250M_SEL, "emmc_250m_sel", + emmc_250m_parents, 0x020, 0x024, 0x028, 0, 1, 7, + 0x1C0, 8, 0), + MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_EMMC_416M_SEL, "emmc_416m_sel", + emmc_416m_parents, 0x020, 0x024, 0x028, 8, 1, 15, + 0x1C0, 9, 0), MUX_GATE_CLR_SET_UPD(CLK_TOP_F_26M_ADC_SEL, "f_26m_adc_sel", f_26m_adc_parents, 0x020, 0x024, 0x028, 16, 1, 23, 0x1C0, 10), @@ -308,7 +308,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt7986_topckgen); static struct platform_driver clk_mt7986_topckgen_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt7986-topckgen", .of_match_table = of_match_clk_mt7986_topckgen, diff --git a/drivers/clk/mediatek/clk-mt8135-apmixedsys.c b/drivers/clk/mediatek/clk-mt8135-apmixedsys.c index 744aae092281d102805339db1d69d09906d90ebb..d1239b4b3db74b4857cc3fe2fa981acb74b914d1 100644 --- a/drivers/clk/mediatek/clk-mt8135-apmixedsys.c +++ b/drivers/clk/mediatek/clk-mt8135-apmixedsys.c @@ -73,7 +73,7 @@ static int clk_mt8135_apmixed_probe(struct platform_device *pdev) return ret; } -static int clk_mt8135_apmixed_remove(struct platform_device *pdev) +static void clk_mt8135_apmixed_remove(struct platform_device *pdev) { struct device_node *node = pdev->dev.of_node; struct clk_hw_onecell_data *clk_data = platform_get_drvdata(pdev); @@ -81,8 +81,6 @@ static int clk_mt8135_apmixed_remove(struct platform_device *pdev) of_clk_del_provider(node); mtk_clk_unregister_plls(plls, ARRAY_SIZE(plls), clk_data); mtk_free_clk_data(clk_data); - - return 0; } static const struct of_device_id of_match_clk_mt8135_apmixed[] = { @@ -93,7 +91,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8135_apmixed); static struct platform_driver clk_mt8135_apmixed_drv = { .probe = clk_mt8135_apmixed_probe, - .remove = clk_mt8135_apmixed_remove, + .remove_new = clk_mt8135_apmixed_remove, .driver = { .name = "clk-mt8135-apmixed", .of_match_table = of_match_clk_mt8135_apmixed, diff --git a/drivers/clk/mediatek/clk-mt8135.c b/drivers/clk/mediatek/clk-mt8135.c index 084e48a554c26297aad978359f6aab205f9ca2af..019af88d7f9c320859a9cd7b501b05f9a13c42f2 100644 --- a/drivers/clk/mediatek/clk-mt8135.c +++ b/drivers/clk/mediatek/clk-mt8135.c @@ -558,7 +558,7 @@ static struct platform_driver clk_mt8135_drv = { .of_match_table = of_match_clk_mt8135, }, .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, }; module_platform_driver(clk_mt8135_drv); diff --git a/drivers/clk/mediatek/clk-mt8167-aud.c b/drivers/clk/mediatek/clk-mt8167-aud.c index 86125635c8a6415d6ba5891bf2121aae95211efd..b73058edf3d6150640b4a3563bf546ce0c388191 100644 --- a/drivers/clk/mediatek/clk-mt8167-aud.c +++ b/drivers/clk/mediatek/clk-mt8167-aud.c @@ -56,7 +56,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8167_audsys); static struct platform_driver clk_mt8167_audsys_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt8167-audsys", .of_match_table = of_match_clk_mt8167_audsys, diff --git a/drivers/clk/mediatek/clk-mt8167-img.c b/drivers/clk/mediatek/clk-mt8167-img.c index 315b7f64bad6d3f14482be088f8a8b52df7c490d..ba07d20f14b309a725f8fa48db4e6833bee6a149 100644 --- a/drivers/clk/mediatek/clk-mt8167-img.c +++ b/drivers/clk/mediatek/clk-mt8167-img.c @@ -48,7 +48,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8167_imgsys); static struct platform_driver clk_mt8167_imgsys_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt8167-imgsys", .of_match_table = of_match_clk_mt8167_imgsys, diff --git a/drivers/clk/mediatek/clk-mt8167-mfgcfg.c b/drivers/clk/mediatek/clk-mt8167-mfgcfg.c index 4851f5bf3a9017f634796c41e69647c1204d5037..5f7dbaf97e96aefc63ee12ff13517172c3df0e2b 100644 --- a/drivers/clk/mediatek/clk-mt8167-mfgcfg.c +++ b/drivers/clk/mediatek/clk-mt8167-mfgcfg.c @@ -46,7 +46,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8167_mfgcfg); static struct platform_driver clk_mt8167_mfgcfg_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt8167-mfgcfg", .of_match_table = of_match_clk_mt8167_mfgcfg, diff --git a/drivers/clk/mediatek/clk-mt8167-mm.c b/drivers/clk/mediatek/clk-mt8167-mm.c index 4e053c61315dab2f7a249245216c76d1c0fa7c8e..6472e76567a537d499fdd8a2b9e25d8c5a940cf5 100644 --- a/drivers/clk/mediatek/clk-mt8167-mm.c +++ b/drivers/clk/mediatek/clk-mt8167-mm.c @@ -87,7 +87,7 @@ MODULE_DEVICE_TABLE(platform, clk_mt8167_mm_id_table); static struct platform_driver clk_mt8167_mm_drv = { .probe = mtk_clk_pdev_probe, - .remove = mtk_clk_pdev_remove, + .remove_new = mtk_clk_pdev_remove, .driver = { .name = "clk-mt8167-mm", }, diff --git a/drivers/clk/mediatek/clk-mt8167-vdec.c b/drivers/clk/mediatek/clk-mt8167-vdec.c index 76900f393d31dda173b1c2813fcabe03fc5e15aa..2f662b3f16a9bcdb0ad8e6203b2c14b2d1880ad7 100644 --- a/drivers/clk/mediatek/clk-mt8167-vdec.c +++ b/drivers/clk/mediatek/clk-mt8167-vdec.c @@ -55,7 +55,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8167_vdec); static struct platform_driver clk_mt8167_vdec_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt8167-vdecsys", .of_match_table = of_match_clk_mt8167_vdec, diff --git a/drivers/clk/mediatek/clk-mt8167.c b/drivers/clk/mediatek/clk-mt8167.c index b9041f79cbbdf996d8d45eb8b7b80252402479ac..270221c6e6e8b055443456546976751658717448 100644 --- a/drivers/clk/mediatek/clk-mt8167.c +++ b/drivers/clk/mediatek/clk-mt8167.c @@ -887,7 +887,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8167); static struct platform_driver clk_mt8167_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt8167", .of_match_table = of_match_clk_mt8167, diff --git a/drivers/clk/mediatek/clk-mt8173-apmixedsys.c b/drivers/clk/mediatek/clk-mt8173-apmixedsys.c index 8c2aa8b0f39ead27eef7e3ed5641b750cb7ccf0f..1bbb21ab178698c683c8949375881b76f271c6d6 100644 --- a/drivers/clk/mediatek/clk-mt8173-apmixedsys.c +++ b/drivers/clk/mediatek/clk-mt8173-apmixedsys.c @@ -148,11 +148,13 @@ static int clk_mt8173_apmixed_probe(struct platform_device *pdev) base = of_iomap(node, 0); if (!base) - return PTR_ERR(base); + return -ENOMEM; clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR_CLK); - if (IS_ERR_OR_NULL(clk_data)) + if (IS_ERR_OR_NULL(clk_data)) { + iounmap(base); return -ENOMEM; + } fhctl_parse_dt(fhctl_node, pllfhs, ARRAY_SIZE(pllfhs)); r = mtk_clk_register_pllfhs(node, plls, ARRAY_SIZE(plls), @@ -186,10 +188,11 @@ static int clk_mt8173_apmixed_probe(struct platform_device *pdev) ARRAY_SIZE(pllfhs), clk_data); free_clk_data: mtk_free_clk_data(clk_data); + iounmap(base); return r; } -static int clk_mt8173_apmixed_remove(struct platform_device *pdev) +static void clk_mt8173_apmixed_remove(struct platform_device *pdev) { struct device_node *node = pdev->dev.of_node; struct clk_hw_onecell_data *clk_data = platform_get_drvdata(pdev); @@ -199,13 +202,11 @@ static int clk_mt8173_apmixed_remove(struct platform_device *pdev) mtk_clk_unregister_pllfhs(plls, ARRAY_SIZE(plls), pllfhs, ARRAY_SIZE(pllfhs), clk_data); mtk_free_clk_data(clk_data); - - return 0; } static struct platform_driver clk_mt8173_apmixed_drv = { .probe = clk_mt8173_apmixed_probe, - .remove = clk_mt8173_apmixed_remove, + .remove_new = clk_mt8173_apmixed_remove, .driver = { .name = "clk-mt8173-apmixed", .of_match_table = of_match_clk_mt8173_apmixed, diff --git a/drivers/clk/mediatek/clk-mt8173-img.c b/drivers/clk/mediatek/clk-mt8173-img.c index 6db2b9ab2bc9194d34c2cf7cc15c242a7463f9e8..1011b9ab3daddb9a951a5c5c307120b8e901524c 100644 --- a/drivers/clk/mediatek/clk-mt8173-img.c +++ b/drivers/clk/mediatek/clk-mt8173-img.c @@ -44,7 +44,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8173_imgsys); static struct platform_driver clk_mt8173_vdecsys_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt8173-imgsys", .of_match_table = of_match_clk_mt8173_imgsys, diff --git a/drivers/clk/mediatek/clk-mt8173-infracfg.c b/drivers/clk/mediatek/clk-mt8173-infracfg.c index 4ed5043076ec731e4b383f39bc204853c627c26f..2f2f074e231a7102190dd35b1d37ad98aded62ec 100644 --- a/drivers/clk/mediatek/clk-mt8173-infracfg.c +++ b/drivers/clk/mediatek/clk-mt8173-infracfg.c @@ -129,7 +129,7 @@ static int clk_mt8173_infracfg_probe(struct platform_device *pdev) return r; } -static int clk_mt8173_infracfg_remove(struct platform_device *pdev) +static void clk_mt8173_infracfg_remove(struct platform_device *pdev) { struct device_node *node = pdev->dev.of_node; struct clk_hw_onecell_data *clk_data = platform_get_drvdata(pdev); @@ -138,8 +138,6 @@ static int clk_mt8173_infracfg_remove(struct platform_device *pdev) mtk_clk_unregister_cpumuxes(cpu_muxes, ARRAY_SIZE(cpu_muxes), clk_data); mtk_clk_unregister_gates(infra_gates, ARRAY_SIZE(infra_gates), clk_data); mtk_free_clk_data(clk_data); - - return 0; } static struct platform_driver clk_mt8173_infracfg_drv = { @@ -148,7 +146,7 @@ static struct platform_driver clk_mt8173_infracfg_drv = { .of_match_table = of_match_clk_mt8173_infracfg, }, .probe = clk_mt8173_infracfg_probe, - .remove = clk_mt8173_infracfg_remove, + .remove_new = clk_mt8173_infracfg_remove, }; module_platform_driver(clk_mt8173_infracfg_drv); diff --git a/drivers/clk/mediatek/clk-mt8173-mm.c b/drivers/clk/mediatek/clk-mt8173-mm.c index 18e466dbf610645a8e2402539b9957297c6e6be7..ffed6c5bfde2d692bf2e949ea3c706693e06d902 100644 --- a/drivers/clk/mediatek/clk-mt8173-mm.c +++ b/drivers/clk/mediatek/clk-mt8173-mm.c @@ -106,7 +106,7 @@ static struct platform_driver clk_mt8173_mm_drv = { }, .id_table = clk_mt8173_mm_id_table, .probe = mtk_clk_pdev_probe, - .remove = mtk_clk_pdev_remove, + .remove_new = mtk_clk_pdev_remove, }; module_platform_driver(clk_mt8173_mm_drv); diff --git a/drivers/clk/mediatek/clk-mt8173-pericfg.c b/drivers/clk/mediatek/clk-mt8173-pericfg.c index bebda74d0f4391493bdb0774db4db873200159ae..783efed3f25421a9491329fcf3e8023d3ea3e4f4 100644 --- a/drivers/clk/mediatek/clk-mt8173-pericfg.c +++ b/drivers/clk/mediatek/clk-mt8173-pericfg.c @@ -115,7 +115,7 @@ static struct platform_driver clk_mt8173_pericfg_drv = { .of_match_table = of_match_clk_mt8173_pericfg, }, .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, }; module_platform_driver(clk_mt8173_pericfg_drv); diff --git a/drivers/clk/mediatek/clk-mt8173-topckgen.c b/drivers/clk/mediatek/clk-mt8173-topckgen.c index baa8fd6cb31266c88395898a9eea0b54e12d628b..6bb7ffd744872849f0f82ca565cd5acafcd76b18 100644 --- a/drivers/clk/mediatek/clk-mt8173-topckgen.c +++ b/drivers/clk/mediatek/clk-mt8173-topckgen.c @@ -547,17 +547,17 @@ static const struct mtk_composite top_muxes[] = { MUX_GATE(CLK_TOP_USB20_SEL, "usb20_sel", usb20_parents, 0x0060, 24, 2, 31), /* CLK_CFG_3 */ MUX_GATE(CLK_TOP_USB30_SEL, "usb30_sel", usb30_parents, 0x0070, 0, 2, 7), - MUX_GATE(CLK_TOP_MSDC50_0_H_SEL, "msdc50_0_h_sel", msdc50_0_h_parents, - 0x0070, 8, 3, 15), - MUX_GATE(CLK_TOP_MSDC50_0_SEL, "msdc50_0_sel", msdc50_0_parents, - 0x0070, 16, 4, 23), - MUX_GATE(CLK_TOP_MSDC30_1_SEL, "msdc30_1_sel", msdc30_1_parents, - 0x0070, 24, 3, 31), + MUX_GATE_FLAGS(CLK_TOP_MSDC50_0_H_SEL, "msdc50_0_h_sel", msdc50_0_h_parents, + 0x0070, 8, 3, 15, 0), + MUX_GATE_FLAGS(CLK_TOP_MSDC50_0_SEL, "msdc50_0_sel", msdc50_0_parents, + 0x0070, 16, 4, 23, 0), + MUX_GATE_FLAGS(CLK_TOP_MSDC30_1_SEL, "msdc30_1_sel", msdc30_1_parents, + 0x0070, 24, 3, 31, 0), /* CLK_CFG_4 */ - MUX_GATE(CLK_TOP_MSDC30_2_SEL, "msdc30_2_sel", msdc30_2_parents, - 0x0080, 0, 3, 7), - MUX_GATE(CLK_TOP_MSDC30_3_SEL, "msdc30_3_sel", msdc30_3_parents, - 0x0080, 8, 4, 15), + MUX_GATE_FLAGS(CLK_TOP_MSDC30_2_SEL, "msdc30_2_sel", msdc30_2_parents, + 0x0080, 0, 3, 7, 0), + MUX_GATE_FLAGS(CLK_TOP_MSDC30_3_SEL, "msdc30_3_sel", msdc30_3_parents, + 0x0080, 8, 4, 15, 0), MUX_GATE(CLK_TOP_AUDIO_SEL, "audio_sel", audio_parents, 0x0080, 16, 2, 23), MUX_GATE(CLK_TOP_AUD_INTBUS_SEL, "aud_intbus_sel", aud_intbus_parents, @@ -595,8 +595,8 @@ static const struct mtk_composite top_muxes[] = { MUX_GATE(CLK_TOP_DPILVDS_SEL, "dpilvds_sel", dpilvds_parents, 0x00c0, 24, 3, 31), /* CLK_CFG_13 */ - MUX_GATE(CLK_TOP_MSDC50_2_H_SEL, "msdc50_2_h_sel", msdc50_2_h_parents, - 0x00d0, 0, 3, 7), + MUX_GATE_FLAGS(CLK_TOP_MSDC50_2_H_SEL, "msdc50_2_h_sel", msdc50_2_h_parents, + 0x00d0, 0, 3, 7, 0), MUX_GATE(CLK_TOP_HDCP_SEL, "hdcp_sel", hdcp_parents, 0x00d0, 8, 2, 15), MUX_GATE(CLK_TOP_HDCP_24M_SEL, "hdcp_24m_sel", hdcp_24m_parents, 0x00d0, 16, 2, 23), @@ -646,7 +646,7 @@ static struct platform_driver clk_mt8173_topckgen_drv = { .of_match_table = of_match_clk_mt8173_topckgen, }, .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, }; module_platform_driver(clk_mt8173_topckgen_drv); diff --git a/drivers/clk/mediatek/clk-mt8173-vdecsys.c b/drivers/clk/mediatek/clk-mt8173-vdecsys.c index 625ca0b09cc225283b870264e7c6df68fd30a51d..011e3812156ff2186bcf08ed773ac05dbb420013 100644 --- a/drivers/clk/mediatek/clk-mt8173-vdecsys.c +++ b/drivers/clk/mediatek/clk-mt8173-vdecsys.c @@ -46,7 +46,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8173_vdecsys); static struct platform_driver clk_mt8173_vdecsys_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt8173-vdecsys", .of_match_table = of_match_clk_mt8173_vdecsys, diff --git a/drivers/clk/mediatek/clk-mt8173-vencsys.c b/drivers/clk/mediatek/clk-mt8173-vencsys.c index 87755dd1a337f9208578907239ef76e9fa8f75c6..1bf84ae6a0bcb6f3c26704f249e5d7686495a047 100644 --- a/drivers/clk/mediatek/clk-mt8173-vencsys.c +++ b/drivers/clk/mediatek/clk-mt8173-vencsys.c @@ -57,7 +57,7 @@ static struct platform_driver clk_mt8173_vencsys_drv = { .of_match_table = of_match_clk_mt8173_vencsys, }, .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, }; module_platform_driver(clk_mt8173_vencsys_drv); diff --git a/drivers/clk/mediatek/clk-mt8183-audio.c b/drivers/clk/mediatek/clk-mt8183-audio.c index 9938c6466e762a4b5dedb12be72a82c3ed852504..716b26825ef0e7235d151e4133d1c9173c9d04b0 100644 --- a/drivers/clk/mediatek/clk-mt8183-audio.c +++ b/drivers/clk/mediatek/clk-mt8183-audio.c @@ -87,10 +87,10 @@ static int clk_mt8183_audio_probe(struct platform_device *pdev) return r; } -static int clk_mt8183_audio_remove(struct platform_device *pdev) +static void clk_mt8183_audio_remove(struct platform_device *pdev) { of_platform_depopulate(&pdev->dev); - return mtk_clk_simple_remove(pdev); + mtk_clk_simple_remove(pdev); } static const struct of_device_id of_match_clk_mt8183_audio[] = { @@ -101,7 +101,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8183_audio); static struct platform_driver clk_mt8183_audio_drv = { .probe = clk_mt8183_audio_probe, - .remove = clk_mt8183_audio_remove, + .remove_new = clk_mt8183_audio_remove, .driver = { .name = "clk-mt8183-audio", .of_match_table = of_match_clk_mt8183_audio, diff --git a/drivers/clk/mediatek/clk-mt8183-cam.c b/drivers/clk/mediatek/clk-mt8183-cam.c index c0719624004fb633036bb5680e6b2a075928aed3..b0f8e4242a6311ffc3c7432f704c001ada64bd17 100644 --- a/drivers/clk/mediatek/clk-mt8183-cam.c +++ b/drivers/clk/mediatek/clk-mt8183-cam.c @@ -51,7 +51,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8183_cam); static struct platform_driver clk_mt8183_cam_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt8183-cam", .of_match_table = of_match_clk_mt8183_cam, diff --git a/drivers/clk/mediatek/clk-mt8183-img.c b/drivers/clk/mediatek/clk-mt8183-img.c index 55fc8061572424f14837941ba7f594f02c62c69a..6e177d2e8872c8c0e7dc1dd70c4b3dc1ad875f5e 100644 --- a/drivers/clk/mediatek/clk-mt8183-img.c +++ b/drivers/clk/mediatek/clk-mt8183-img.c @@ -51,7 +51,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8183_img); static struct platform_driver clk_mt8183_img_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt8183-img", .of_match_table = of_match_clk_mt8183_img, diff --git a/drivers/clk/mediatek/clk-mt8183-ipu0.c b/drivers/clk/mediatek/clk-mt8183-ipu0.c index 59255eab6fe250bdf3ccbf7fa7b36d2ba611fb7f..0b61c7af8aead06f17f08be5e98f84da5d7ffd5d 100644 --- a/drivers/clk/mediatek/clk-mt8183-ipu0.c +++ b/drivers/clk/mediatek/clk-mt8183-ipu0.c @@ -44,7 +44,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8183_ipu_core0); static struct platform_driver clk_mt8183_ipu_core0_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt8183-ipu_core0", .of_match_table = of_match_clk_mt8183_ipu_core0, diff --git a/drivers/clk/mediatek/clk-mt8183-ipu1.c b/drivers/clk/mediatek/clk-mt8183-ipu1.c index c4baa052c809948261983126f9cdc209020ef76b..544b1ca0e1c5a12c17430ba12c0d4fd9bc6c6834 100644 --- a/drivers/clk/mediatek/clk-mt8183-ipu1.c +++ b/drivers/clk/mediatek/clk-mt8183-ipu1.c @@ -44,7 +44,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8183_ipu_core1); static struct platform_driver clk_mt8183_ipu_core1_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt8183-ipu_core1", .of_match_table = of_match_clk_mt8183_ipu_core1, diff --git a/drivers/clk/mediatek/clk-mt8183-ipu_adl.c b/drivers/clk/mediatek/clk-mt8183-ipu_adl.c index 74866e9c50d74ac5f7d2fc7f2656ddedf20bc13c..7f53674f393c26d5cfcbc21a43a176eab386ae79 100644 --- a/drivers/clk/mediatek/clk-mt8183-ipu_adl.c +++ b/drivers/clk/mediatek/clk-mt8183-ipu_adl.c @@ -42,7 +42,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8183_ipu_adl); static struct platform_driver clk_mt8183_ipu_adl_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt8183-ipu_adl", .of_match_table = of_match_clk_mt8183_ipu_adl, diff --git a/drivers/clk/mediatek/clk-mt8183-ipu_conn.c b/drivers/clk/mediatek/clk-mt8183-ipu_conn.c index bd730310535785e23e59e416465d31b1c69e3594..fb03ad2d8f6a15f229088182d1e29694839ba89b 100644 --- a/drivers/clk/mediatek/clk-mt8183-ipu_conn.c +++ b/drivers/clk/mediatek/clk-mt8183-ipu_conn.c @@ -111,7 +111,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8183_ipu_conn); static struct platform_driver clk_mt8183_ipu_conn_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt8183-ipu_conn", .of_match_table = of_match_clk_mt8183_ipu_conn, diff --git a/drivers/clk/mediatek/clk-mt8183-mfgcfg.c b/drivers/clk/mediatek/clk-mt8183-mfgcfg.c index 816ecf1191ee8b3b60feeb1958aff04eacd95683..ba504e19d420314fbb5081a3b93d254c020fe280 100644 --- a/drivers/clk/mediatek/clk-mt8183-mfgcfg.c +++ b/drivers/clk/mediatek/clk-mt8183-mfgcfg.c @@ -43,7 +43,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8183_mfg); static struct platform_driver clk_mt8183_mfg_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt8183-mfg", .of_match_table = of_match_clk_mt8183_mfg, diff --git a/drivers/clk/mediatek/clk-mt8183-mm.c b/drivers/clk/mediatek/clk-mt8183-mm.c index 2f99828bff1b31c72fb1935b8cffcb0705454c92..8aaddcfee5683b9ccf9900a2281c4ca11fecb32b 100644 --- a/drivers/clk/mediatek/clk-mt8183-mm.c +++ b/drivers/clk/mediatek/clk-mt8183-mm.c @@ -95,7 +95,7 @@ MODULE_DEVICE_TABLE(platform, clk_mt8183_mm_id_table); static struct platform_driver clk_mt8183_mm_drv = { .probe = mtk_clk_pdev_probe, - .remove = mtk_clk_pdev_remove, + .remove_new = mtk_clk_pdev_remove, .driver = { .name = "clk-mt8183-mm", }, diff --git a/drivers/clk/mediatek/clk-mt8183-vdec.c b/drivers/clk/mediatek/clk-mt8183-vdec.c index 513b7956cbea095692aec57e1f02956bcafe0817..8c99ae89834f270a2a696822a06fa371c53d4252 100644 --- a/drivers/clk/mediatek/clk-mt8183-vdec.c +++ b/drivers/clk/mediatek/clk-mt8183-vdec.c @@ -55,7 +55,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8183_vdec); static struct platform_driver clk_mt8183_vdec_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt8183-vdec", .of_match_table = of_match_clk_mt8183_vdec, diff --git a/drivers/clk/mediatek/clk-mt8183-venc.c b/drivers/clk/mediatek/clk-mt8183-venc.c index 532f6e12a56161fefbc3d25339096ad73ae48930..a8e0220902aee47222ac5c7c799c4773273f84a2 100644 --- a/drivers/clk/mediatek/clk-mt8183-venc.c +++ b/drivers/clk/mediatek/clk-mt8183-venc.c @@ -47,7 +47,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8183_venc); static struct platform_driver clk_mt8183_venc_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt8183-venc", .of_match_table = of_match_clk_mt8183_venc, diff --git a/drivers/clk/mediatek/clk-mt8183.c b/drivers/clk/mediatek/clk-mt8183.c index 2336a1b69c0937ac8c0325a9aa977509ecb66271..1ba421b38ec55efa9294f8378eba3435717d9ad9 100644 --- a/drivers/clk/mediatek/clk-mt8183.c +++ b/drivers/clk/mediatek/clk-mt8183.c @@ -451,7 +451,8 @@ static const char * const aud_2_parents[] = { static const struct mtk_mux top_muxes[] = { /* CLK_CFG_0 */ MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_MUX_AXI, "axi_sel", - axi_parents, 0x40, 0x44, 0x48, 0, 2, 7, 0x004, 0, CLK_IS_CRITICAL), + axi_parents, 0x40, 0x44, 0x48, 0, 2, 7, 0x004, 0, + CLK_IS_CRITICAL | CLK_SET_RATE_PARENT), MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_MM, "mm_sel", mm_parents, 0x40, 0x44, 0x48, 8, 3, 15, 0x004, 1), MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_IMG, "img_sel", @@ -486,14 +487,14 @@ static const struct mtk_mux top_muxes[] = { MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_SPI, "spi_sel", spi_parents, 0x70, 0x74, 0x78, 24, 2, 31, 0x004, 15), /* CLK_CFG_4 */ - MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_MSDC50_0_HCLK, "msdc50_hclk_sel", - msdc50_hclk_parents, 0x80, 0x84, 0x88, 0, 2, 7, 0x004, 16), - MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_MSDC50_0, "msdc50_0_sel", - msdc50_0_parents, 0x80, 0x84, 0x88, 8, 3, 15, 0x004, 17), - MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_MSDC30_1, "msdc30_1_sel", - msdc30_1_parents, 0x80, 0x84, 0x88, 16, 3, 23, 0x004, 18), - MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_MSDC30_2, "msdc30_2_sel", - msdc30_2_parents, 0x80, 0x84, 0x88, 24, 3, 31, 0x004, 19), + MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_MUX_MSDC50_0_HCLK, "msdc50_hclk_sel", + msdc50_hclk_parents, 0x80, 0x84, 0x88, 0, 2, 7, 0x004, 16, 0), + MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_MUX_MSDC50_0, "msdc50_0_sel", + msdc50_0_parents, 0x80, 0x84, 0x88, 8, 3, 15, 0x004, 17, 0), + MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_MUX_MSDC30_1, "msdc30_1_sel", + msdc30_1_parents, 0x80, 0x84, 0x88, 16, 3, 23, 0x004, 18, 0), + MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_MUX_MSDC30_2, "msdc30_2_sel", + msdc30_2_parents, 0x80, 0x84, 0x88, 24, 3, 31, 0x004, 19, 0), /* CLK_CFG_5 */ MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_AUDIO, "audio_sel", audio_parents, 0x90, 0x94, 0x98, 0, 2, 7, 0x004, 20), @@ -518,7 +519,8 @@ static const struct mtk_mux top_muxes[] = { MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_SSUSB_TOP_XHCI, "ssusb_top_xhci_sel", ssusb_top_xhci_parents, 0xb0, 0xb4, 0xb8, 16, 2, 23, 0x004, 30), MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_MUX_SPM, "spm_sel", - spm_parents, 0xb0, 0xb4, 0xb8, 24, 1, 31, 0x008, 0, CLK_IS_CRITICAL), + spm_parents, 0xb0, 0xb4, 0xb8, 24, 1, 31, 0x008, 0, + CLK_IS_CRITICAL | CLK_SET_RATE_PARENT), /* CLK_CFG_8 */ MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_I2C, "i2c_sel", i2c_parents, 0xc0, 0xc4, 0xc8, 0, 2, 7, 0x008, 1), @@ -872,7 +874,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8183); static struct platform_driver clk_mt8183_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt8183", .of_match_table = of_match_clk_mt8183, diff --git a/drivers/clk/mediatek/clk-mt8186-apmixedsys.c b/drivers/clk/mediatek/clk-mt8186-apmixedsys.c index da7950d51c64e095f978b6583a010af939041ed8..fff64a8fd5573c8cef1e6e06293c722d22534071 100644 --- a/drivers/clk/mediatek/clk-mt8186-apmixedsys.c +++ b/drivers/clk/mediatek/clk-mt8186-apmixedsys.c @@ -172,7 +172,7 @@ static int clk_mt8186_apmixed_probe(struct platform_device *pdev) return r; } -static int clk_mt8186_apmixed_remove(struct platform_device *pdev) +static void clk_mt8186_apmixed_remove(struct platform_device *pdev) { struct device_node *node = pdev->dev.of_node; struct clk_hw_onecell_data *clk_data = platform_get_drvdata(pdev); @@ -181,13 +181,11 @@ static int clk_mt8186_apmixed_remove(struct platform_device *pdev) mtk_clk_unregister_pllfhs(plls, ARRAY_SIZE(plls), pllfhs, ARRAY_SIZE(pllfhs), clk_data); mtk_free_clk_data(clk_data); - - return 0; } static struct platform_driver clk_mt8186_apmixed_drv = { .probe = clk_mt8186_apmixed_probe, - .remove = clk_mt8186_apmixed_remove, + .remove_new = clk_mt8186_apmixed_remove, .driver = { .name = "clk-mt8186-apmixed", .of_match_table = of_match_clk_mt8186_apmixed, diff --git a/drivers/clk/mediatek/clk-mt8186-cam.c b/drivers/clk/mediatek/clk-mt8186-cam.c index 656d9e6f3ee2b7fe3a834c2bbb9aa7e8c3d31d69..effd2900d2e8e8518d100d3ed828a93330f22a40 100644 --- a/drivers/clk/mediatek/clk-mt8186-cam.c +++ b/drivers/clk/mediatek/clk-mt8186-cam.c @@ -82,7 +82,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8186_cam); static struct platform_driver clk_mt8186_cam_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt8186-cam", .of_match_table = of_match_clk_mt8186_cam, diff --git a/drivers/clk/mediatek/clk-mt8186-img.c b/drivers/clk/mediatek/clk-mt8186-img.c index 754b27f038176ae5f612138c5aff209019f5e18b..71b0571e6351491b49c387bb4fc2fcadd9552097 100644 --- a/drivers/clk/mediatek/clk-mt8186-img.c +++ b/drivers/clk/mediatek/clk-mt8186-img.c @@ -60,7 +60,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8186_img); static struct platform_driver clk_mt8186_img_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt8186-img", .of_match_table = of_match_clk_mt8186_img, diff --git a/drivers/clk/mediatek/clk-mt8186-imp_iic_wrap.c b/drivers/clk/mediatek/clk-mt8186-imp_iic_wrap.c index 7619c357b150d7fd40b3ac538e57da160a10ea31..640ccb5532741bcdda460a1904d81306040bf459 100644 --- a/drivers/clk/mediatek/clk-mt8186-imp_iic_wrap.c +++ b/drivers/clk/mediatek/clk-mt8186-imp_iic_wrap.c @@ -59,7 +59,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8186_imp_iic_wrap); static struct platform_driver clk_mt8186_imp_iic_wrap_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt8186-imp_iic_wrap", .of_match_table = of_match_clk_mt8186_imp_iic_wrap, diff --git a/drivers/clk/mediatek/clk-mt8186-infra_ao.c b/drivers/clk/mediatek/clk-mt8186-infra_ao.c index a907a5def5b8c3830c7568984d1f956f25e2a14e..837304cd0ed76eb2af08807296d688cf0922ccde 100644 --- a/drivers/clk/mediatek/clk-mt8186-infra_ao.c +++ b/drivers/clk/mediatek/clk-mt8186-infra_ao.c @@ -231,7 +231,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8186_infra_ao); static struct platform_driver clk_mt8186_infra_ao_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt8186-infra-ao", .of_match_table = of_match_clk_mt8186_infra_ao, diff --git a/drivers/clk/mediatek/clk-mt8186-ipe.c b/drivers/clk/mediatek/clk-mt8186-ipe.c index 50e340035aa70e599b573fc97a3071eabe842d91..60739e225cb6c90f1d2c869e893ed82845173510 100644 --- a/drivers/clk/mediatek/clk-mt8186-ipe.c +++ b/drivers/clk/mediatek/clk-mt8186-ipe.c @@ -47,7 +47,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8186_ipe); static struct platform_driver clk_mt8186_ipe_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt8186-ipe", .of_match_table = of_match_clk_mt8186_ipe, diff --git a/drivers/clk/mediatek/clk-mt8186-mcu.c b/drivers/clk/mediatek/clk-mt8186-mcu.c index d1640e4dc2adbdc0683800416b19f8ea3c58785a..eb54ccb77b74cb269ea29574dfffdc3690eceb47 100644 --- a/drivers/clk/mediatek/clk-mt8186-mcu.c +++ b/drivers/clk/mediatek/clk-mt8186-mcu.c @@ -60,7 +60,7 @@ static struct platform_driver clk_mt8186_mcu_drv = { .of_match_table = of_match_clk_mt8186_mcu, }, .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, }; module_platform_driver(clk_mt8186_mcu_drv); diff --git a/drivers/clk/mediatek/clk-mt8186-mdp.c b/drivers/clk/mediatek/clk-mt8186-mdp.c index e1d19007e3754f8309577818c5289badeefcac2a..9a335f2285cea612c2890a5c33bc8fa82ffed1f7 100644 --- a/drivers/clk/mediatek/clk-mt8186-mdp.c +++ b/drivers/clk/mediatek/clk-mt8186-mdp.c @@ -72,7 +72,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8186_mdp); static struct platform_driver clk_mt8186_mdp_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt8186-mdp", .of_match_table = of_match_clk_mt8186_mdp, diff --git a/drivers/clk/mediatek/clk-mt8186-mfg.c b/drivers/clk/mediatek/clk-mt8186-mfg.c index aeb098b54585e70ef391889ae0c78936f6abb1c9..7618dad9e0e0e0706d06ff4fde1233907643b677 100644 --- a/drivers/clk/mediatek/clk-mt8186-mfg.c +++ b/drivers/clk/mediatek/clk-mt8186-mfg.c @@ -41,7 +41,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8186_mfg); static struct platform_driver clk_mt8186_mfg_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt8186-mfg", .of_match_table = of_match_clk_mt8186_mfg, diff --git a/drivers/clk/mediatek/clk-mt8186-mm.c b/drivers/clk/mediatek/clk-mt8186-mm.c index fc3bb6d1f7148411957ed0600d08bc55a011ced0..44ed504a80695a60a73e35a914421287d11b0084 100644 --- a/drivers/clk/mediatek/clk-mt8186-mm.c +++ b/drivers/clk/mediatek/clk-mt8186-mm.c @@ -71,7 +71,7 @@ MODULE_DEVICE_TABLE(platform, clk_mt8186_mm_id_table); static struct platform_driver clk_mt8186_mm_drv = { .probe = mtk_clk_pdev_probe, - .remove = mtk_clk_pdev_remove, + .remove_new = mtk_clk_pdev_remove, .driver = { .name = "clk-mt8186-mm", }, diff --git a/drivers/clk/mediatek/clk-mt8186-topckgen.c b/drivers/clk/mediatek/clk-mt8186-topckgen.c index 1a0340a20bebecbbf698bf638c19e336d240b26a..8e385d6bfef23843fbf1387fb98bc0c86bb0951a 100644 --- a/drivers/clk/mediatek/clk-mt8186-topckgen.c +++ b/drivers/clk/mediatek/clk-mt8186-topckgen.c @@ -504,10 +504,10 @@ static const struct mtk_mux top_mtk_muxes[] = { */ MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_AXI, "top_axi", axi_parents, 0x0040, 0x0044, 0x0048, 0, 2, 7, 0x0004, 0, - CLK_IS_CRITICAL), + CLK_IS_CRITICAL | CLK_SET_RATE_PARENT), MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_SCP, "top_scp", scp_parents, 0x0040, 0x0044, 0x0048, 8, 3, 15, 0x0004, 1, - CLK_IS_CRITICAL), + CLK_IS_CRITICAL | CLK_SET_RATE_PARENT), MUX_GATE_CLR_SET_UPD(CLK_TOP_MFG, "top_mfg", mfg_parents, 0x0040, 0x0044, 0x0048, 16, 2, 23, 0x0004, 2), MUX_GATE_CLR_SET_UPD(CLK_TOP_CAMTG, "top_camtg", @@ -531,12 +531,12 @@ static const struct mtk_mux top_mtk_muxes[] = { MUX_GATE_CLR_SET_UPD(CLK_TOP_SPI, "top_spi", spi_parents, 0x0060, 0x0064, 0x0068, 24, 3, 31, 0x0004, 11), /* CLK_CFG_3 */ - MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC50_0_HCLK, "top_msdc5hclk", - msdc5hclk_parents, 0x0070, 0x0074, 0x0078, 0, 2, 7, 0x0004, 12), - MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC50_0, "top_msdc50_0", - msdc50_0_parents, 0x0070, 0x0074, 0x0078, 8, 3, 15, 0x0004, 13), - MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC30_1, "top_msdc30_1", - msdc30_1_parents, 0x0070, 0x0074, 0x0078, 16, 3, 23, 0x0004, 14), + MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_MSDC50_0_HCLK, "top_msdc5hclk", + msdc5hclk_parents, 0x0070, 0x0074, 0x0078, 0, 2, 7, 0x0004, 12, 0), + MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_MSDC50_0, "top_msdc50_0", + msdc50_0_parents, 0x0070, 0x0074, 0x0078, 8, 3, 15, 0x0004, 13, 0), + MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_MSDC30_1, "top_msdc30_1", + msdc30_1_parents, 0x0070, 0x0074, 0x0078, 16, 3, 23, 0x0004, 14, 0), MUX_GATE_CLR_SET_UPD(CLK_TOP_AUDIO, "top_audio", audio_parents, 0x0070, 0x0074, 0x0078, 24, 2, 31, 0x0004, 15), /* CLK_CFG_4 */ @@ -559,7 +559,7 @@ static const struct mtk_mux top_mtk_muxes[] = { disp_pwm_parents, 0x0090, 0x0094, 0x0098, 8, 3, 15, 0x0004, 21), MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_SSPM, "top_sspm", sspm_parents, 0x0090, 0x0094, 0x0098, 16, 3, 23, 0x0004, 22, - CLK_IS_CRITICAL), + CLK_IS_CRITICAL | CLK_SET_RATE_PARENT), MUX_GATE_CLR_SET_UPD(CLK_TOP_DXCC, "top_dxcc", dxcc_parents, 0x0090, 0x0094, 0x0098, 24, 2, 31, 0x0004, 23), /* @@ -570,10 +570,10 @@ static const struct mtk_mux top_mtk_muxes[] = { usb_parents, 0x00a0, 0x00a4, 0x00a8, 0, 2, 7, 0x0004, 24), MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_SRCK, "top_srck", srck_parents, 0x00a0, 0x00a4, 0x00a8, 8, 2, 15, 0x0004, 25, - CLK_IS_CRITICAL), + CLK_IS_CRITICAL | CLK_SET_RATE_PARENT), MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_SPM, "top_spm", spm_parents, 0x00a0, 0x00a4, 0x00a8, 16, 2, 23, 0x0004, 26, - CLK_IS_CRITICAL), + CLK_IS_CRITICAL | CLK_SET_RATE_PARENT), MUX_GATE_CLR_SET_UPD(CLK_TOP_I2C, "top_i2c", i2c_parents, 0x00a0, 0x00a4, 0x00a8, 24, 2, 31, 0x0004, 27), /* CLK_CFG_7 */ @@ -627,7 +627,7 @@ static const struct mtk_mux top_mtk_muxes[] = { */ MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_DVFSRC, "top_dvfsrc", dvfsrc_parents, 0x0100, 0x0104, 0x0108, 0, 1, 7, 0x0008, 17, - CLK_IS_CRITICAL), + CLK_IS_CRITICAL | CLK_SET_RATE_PARENT), MUX_GATE_CLR_SET_UPD(CLK_TOP_DSI_OCC, "top_dsi_occ", dsi_occ_parents, 0x0100, 0x0104, 0x0108, 8, 2, 15, 0x0008, 18), MUX_GATE_CLR_SET_UPD(CLK_TOP_SPMI_MST, "top_spmi_mst", @@ -725,7 +725,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8186_topck); static struct platform_driver clk_mt8186_topck_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt8186-topck", .of_match_table = of_match_clk_mt8186_topck, diff --git a/drivers/clk/mediatek/clk-mt8186-vdec.c b/drivers/clk/mediatek/clk-mt8186-vdec.c index 9bf3b86328703887c960b835075bd3cccf826502..0b814e8e107f90e5c18db8f1b7b5228ecaa11535 100644 --- a/drivers/clk/mediatek/clk-mt8186-vdec.c +++ b/drivers/clk/mediatek/clk-mt8186-vdec.c @@ -80,7 +80,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8186_vdec); static struct platform_driver clk_mt8186_vdec_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt8186-vdec", .of_match_table = of_match_clk_mt8186_vdec, diff --git a/drivers/clk/mediatek/clk-mt8186-venc.c b/drivers/clk/mediatek/clk-mt8186-venc.c index 0c1bc94e84cf77ae3f55bf104a75c208a740fac0..9493e51af3e2110333fbb5299ad0e50a38a602a1 100644 --- a/drivers/clk/mediatek/clk-mt8186-venc.c +++ b/drivers/clk/mediatek/clk-mt8186-venc.c @@ -43,7 +43,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8186_venc); static struct platform_driver clk_mt8186_venc_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt8186-venc", .of_match_table = of_match_clk_mt8186_venc, diff --git a/drivers/clk/mediatek/clk-mt8186-wpe.c b/drivers/clk/mediatek/clk-mt8186-wpe.c index c4727b1cb64d8db44c087430675a03403562b2fd..a0174eabef4a9cdd9acdad0aad89be03a1ff7984 100644 --- a/drivers/clk/mediatek/clk-mt8186-wpe.c +++ b/drivers/clk/mediatek/clk-mt8186-wpe.c @@ -43,7 +43,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8186_wpe); static struct platform_driver clk_mt8186_wpe_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt8186-wpe", .of_match_table = of_match_clk_mt8186_wpe, diff --git a/drivers/clk/mediatek/clk-mt8188-adsp_audio26m.c b/drivers/clk/mediatek/clk-mt8188-adsp_audio26m.c index 808f2ad3b7ee68133be55cd219e02a3f3921f698..1dc3d2bad42ded2a5191f3e7cde6b21353ad0ca6 100644 --- a/drivers/clk/mediatek/clk-mt8188-adsp_audio26m.c +++ b/drivers/clk/mediatek/clk-mt8188-adsp_audio26m.c @@ -40,7 +40,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8188_adsp_audio26m); static struct platform_driver clk_mt8188_adsp_audio26m_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt8188-adsp_audio26m", .of_match_table = of_match_clk_mt8188_adsp_audio26m, diff --git a/drivers/clk/mediatek/clk-mt8188-apmixedsys.c b/drivers/clk/mediatek/clk-mt8188-apmixedsys.c index 9d21da2d9aa76c4230782f9a0b98819b88594c70..3c1ace87796b22c7b03ca993bbfda646d12f66be 100644 --- a/drivers/clk/mediatek/clk-mt8188-apmixedsys.c +++ b/drivers/clk/mediatek/clk-mt8188-apmixedsys.c @@ -132,7 +132,7 @@ static int clk_mt8188_apmixed_probe(struct platform_device *pdev) return r; } -static int clk_mt8188_apmixed_remove(struct platform_device *pdev) +static void clk_mt8188_apmixed_remove(struct platform_device *pdev) { struct device_node *node = pdev->dev.of_node; struct clk_hw_onecell_data *clk_data = platform_get_drvdata(pdev); @@ -141,13 +141,11 @@ static int clk_mt8188_apmixed_remove(struct platform_device *pdev) mtk_clk_unregister_gates(apmixed_clks, ARRAY_SIZE(apmixed_clks), clk_data); mtk_clk_unregister_plls(plls, ARRAY_SIZE(plls), clk_data); mtk_free_clk_data(clk_data); - - return 0; } static struct platform_driver clk_mt8188_apmixed_drv = { .probe = clk_mt8188_apmixed_probe, - .remove = clk_mt8188_apmixed_remove, + .remove_new = clk_mt8188_apmixed_remove, .driver = { .name = "clk-mt8188-apmixed", .of_match_table = of_match_clk_mt8188_apmixed, diff --git a/drivers/clk/mediatek/clk-mt8188-cam.c b/drivers/clk/mediatek/clk-mt8188-cam.c index c5a3856bd2237eef75157be5554e6dc974af3daf..f78f564aa27e8c4352b6145df02c9b1c1db27eb6 100644 --- a/drivers/clk/mediatek/clk-mt8188-cam.c +++ b/drivers/clk/mediatek/clk-mt8188-cam.c @@ -109,7 +109,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8188_cam); static struct platform_driver clk_mt8188_cam_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt8188-cam", .of_match_table = of_match_clk_mt8188_cam, diff --git a/drivers/clk/mediatek/clk-mt8188-ccu.c b/drivers/clk/mediatek/clk-mt8188-ccu.c index ebc0d3aeee1118a738ed52610a48fe4197ad5fe4..428dcc4818c2f7c4d5c284691ffae51aae3a6c6f 100644 --- a/drivers/clk/mediatek/clk-mt8188-ccu.c +++ b/drivers/clk/mediatek/clk-mt8188-ccu.c @@ -39,7 +39,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8188_ccu); static struct platform_driver clk_mt8188_ccu_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt8188-ccu", .of_match_table = of_match_clk_mt8188_ccu, diff --git a/drivers/clk/mediatek/clk-mt8188-img.c b/drivers/clk/mediatek/clk-mt8188-img.c index b4622875e14cd13c0f88f0a2876249714fd450a4..76c64a8992a41a2d93b0fe78044c2d8ab1e42486 100644 --- a/drivers/clk/mediatek/clk-mt8188-img.c +++ b/drivers/clk/mediatek/clk-mt8188-img.c @@ -101,7 +101,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8188_imgsys_main); static struct platform_driver clk_mt8188_imgsys_main_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt8188-imgsys_main", .of_match_table = of_match_clk_mt8188_imgsys_main, diff --git a/drivers/clk/mediatek/clk-mt8188-imp_iic_wrap.c b/drivers/clk/mediatek/clk-mt8188-imp_iic_wrap.c index da41a3c59919c3b38b0a5cd66640870b9c91434c..66946784cdba7eefb7c883c9835eaa0193baab2d 100644 --- a/drivers/clk/mediatek/clk-mt8188-imp_iic_wrap.c +++ b/drivers/clk/mediatek/clk-mt8188-imp_iic_wrap.c @@ -71,7 +71,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8188_imp_iic_wrap); static struct platform_driver clk_mt8188_imp_iic_wrap_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt8188-imp_iic_wrap", .of_match_table = of_match_clk_mt8188_imp_iic_wrap, diff --git a/drivers/clk/mediatek/clk-mt8188-infra_ao.c b/drivers/clk/mediatek/clk-mt8188-infra_ao.c index 91c35db40b4e88521c6a654a6580deb46284ae83..f590178737cbb6b86b6fa78164dec90219fc6120 100644 --- a/drivers/clk/mediatek/clk-mt8188-infra_ao.c +++ b/drivers/clk/mediatek/clk-mt8188-infra_ao.c @@ -5,6 +5,7 @@ */ #include +#include #include #include @@ -176,9 +177,32 @@ static const struct mtk_gate infra_ao_clks[] = { "infra_ao_aes_msdcfde_0p", "top_aes_msdcfde", 18), }; +static u16 infra_ao_rst_ofs[] = { + INFRA_RST0_SET_OFFSET, + INFRA_RST1_SET_OFFSET, + INFRA_RST2_SET_OFFSET, + INFRA_RST3_SET_OFFSET, + INFRA_RST4_SET_OFFSET, +}; + +static u16 infra_ao_idx_map[] = { + [MT8188_INFRA_RST1_THERMAL_MCU_RST] = 1 * RST_NR_PER_BANK + 2, + [MT8188_INFRA_RST1_THERMAL_CTRL_RST] = 1 * RST_NR_PER_BANK + 4, + [MT8188_INFRA_RST3_PTP_CTRL_RST] = 3 * RST_NR_PER_BANK + 5, +}; + +static const struct mtk_clk_rst_desc infra_ao_rst_desc = { + .version = MTK_RST_SET_CLR, + .rst_bank_ofs = infra_ao_rst_ofs, + .rst_bank_nr = ARRAY_SIZE(infra_ao_rst_ofs), + .rst_idx_map = infra_ao_idx_map, + .rst_idx_map_nr = ARRAY_SIZE(infra_ao_idx_map), +}; + static const struct mtk_clk_desc infra_ao_desc = { .clks = infra_ao_clks, .num_clks = ARRAY_SIZE(infra_ao_clks), + .rst_desc = &infra_ao_rst_desc, }; static const struct of_device_id of_match_clk_mt8188_infra_ao[] = { @@ -189,7 +213,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8188_infra_ao); static struct platform_driver clk_mt8188_infra_ao_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt8188-infra_ao", .of_match_table = of_match_clk_mt8188_infra_ao, diff --git a/drivers/clk/mediatek/clk-mt8188-ipe.c b/drivers/clk/mediatek/clk-mt8188-ipe.c index c07afbd1429ef47cc2a4b274cc4cd19ff3223b83..54fe6b689b47ebb1a80b19f5d11427728937e4e4 100644 --- a/drivers/clk/mediatek/clk-mt8188-ipe.c +++ b/drivers/clk/mediatek/clk-mt8188-ipe.c @@ -41,7 +41,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8188_ipe); static struct platform_driver clk_mt8188_ipe_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt8188-ipe", .of_match_table = of_match_clk_mt8188_ipe, diff --git a/drivers/clk/mediatek/clk-mt8188-mfg.c b/drivers/clk/mediatek/clk-mt8188-mfg.c index e5a6eaf8467275b4f690ee4ca2f48569f17f8c48..1c8ef4c6820f942b3823260cee518ebe1cfa4e33 100644 --- a/drivers/clk/mediatek/clk-mt8188-mfg.c +++ b/drivers/clk/mediatek/clk-mt8188-mfg.c @@ -38,7 +38,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8188_mfgcfg); static struct platform_driver clk_mt8188_mfgcfg_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt8188-mfgcfg", .of_match_table = of_match_clk_mt8188_mfgcfg, diff --git a/drivers/clk/mediatek/clk-mt8188-peri_ao.c b/drivers/clk/mediatek/clk-mt8188-peri_ao.c index b00e1ae8bd260ad3b3f55c35bba92d87c94aeed3..a8214e42b8e594019fd88fce18f02e8d78069b04 100644 --- a/drivers/clk/mediatek/clk-mt8188-peri_ao.c +++ b/drivers/clk/mediatek/clk-mt8188-peri_ao.c @@ -49,7 +49,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8188_peri_ao); static struct platform_driver clk_mt8188_peri_ao_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt8188-peri_ao", .of_match_table = of_match_clk_mt8188_peri_ao, diff --git a/drivers/clk/mediatek/clk-mt8188-topckgen.c b/drivers/clk/mediatek/clk-mt8188-topckgen.c index c56ec42cb15f3061a76cc039aba80653e49c1a8e..d2eba2d6af8d85cc28b0e96679f8839d66cbc924 100644 --- a/drivers/clk/mediatek/clk-mt8188-topckgen.c +++ b/drivers/clk/mediatek/clk-mt8188-topckgen.c @@ -954,13 +954,17 @@ static const struct mtk_mux top_mtk_muxes[] = { * spm_sel and scp_sel are main clocks in always-on co-processor. */ MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_AXI, "top_axi", axi_parents, - 0x020, 0x024, 0x028, 0, 4, 7, 0x04, 0, CLK_IS_CRITICAL), + 0x020, 0x024, 0x028, 0, 4, 7, 0x04, 0, + CLK_IS_CRITICAL | CLK_SET_RATE_PARENT), MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_SPM, "top_spm", spm_parents, - 0x020, 0x024, 0x028, 8, 4, 15, 0x04, 1, CLK_IS_CRITICAL), + 0x020, 0x024, 0x028, 8, 4, 15, 0x04, 1, + CLK_IS_CRITICAL | CLK_SET_RATE_PARENT), MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_SCP, "top_scp", scp_parents, - 0x020, 0x024, 0x028, 16, 4, 23, 0x04, 2, CLK_IS_CRITICAL), + 0x020, 0x024, 0x028, 16, 4, 23, 0x04, 2, + CLK_IS_CRITICAL | CLK_SET_RATE_PARENT), MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_BUS_AXIMEM, "top_bus_aximem", bus_aximem_parents, - 0x020, 0x024, 0x028, 24, 4, 31, 0x04, 3, CLK_IS_CRITICAL), + 0x020, 0x024, 0x028, 24, 4, 31, 0x04, 3, + CLK_IS_CRITICAL | CLK_SET_RATE_PARENT), /* CLK_CFG_1 */ MUX_GATE_CLR_SET_UPD(CLK_TOP_VPP, "top_vpp", vpp_parents, 0x02C, 0x030, 0x034, 0, 4, 7, 0x04, 4), @@ -1011,15 +1015,15 @@ static const struct mtk_mux top_mtk_muxes[] = { uart_parents, 0x068, 0x06C, 0x070, 0, 4, 7, 0x04, 24), MUX_GATE_CLR_SET_UPD(CLK_TOP_SPI, "top_spi", spi_parents, 0x068, 0x06C, 0x070, 8, 4, 15, 0x04, 25), - MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC50_0_HCLK, "top_msdc5hclk", - msdc5hclk_parents, 0x068, 0x06C, 0x070, 16, 4, 23, 0x04, 26), - MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC50_0, "top_msdc50_0", - msdc50_0_parents, 0x068, 0x06C, 0x070, 24, 4, 31, 0x04, 27), + MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_MSDC50_0_HCLK, "top_msdc5hclk", + msdc5hclk_parents, 0x068, 0x06C, 0x070, 16, 4, 23, 0x04, 26, 0), + MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_MSDC50_0, "top_msdc50_0", + msdc50_0_parents, 0x068, 0x06C, 0x070, 24, 4, 31, 0x04, 27, 0), /* CLK_CFG_7 */ - MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC30_1, "top_msdc30_1", - msdc30_1_parents, 0x074, 0x078, 0x07C, 0, 4, 7, 0x04, 28), - MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC30_2, "top_msdc30_2", - msdc30_2_parents, 0x074, 0x078, 0x07C, 8, 4, 15, 0x04, 29), + MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_MSDC30_1, "top_msdc30_1", + msdc30_1_parents, 0x074, 0x078, 0x07C, 0, 4, 7, 0x04, 28, 0), + MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_MSDC30_2, "top_msdc30_2", + msdc30_2_parents, 0x074, 0x078, 0x07C, 8, 4, 15, 0x04, 29, 0), MUX_GATE_CLR_SET_UPD(CLK_TOP_INTDIR, "top_intdir", intdir_parents, 0x074, 0x078, 0x07C, 16, 4, 23, 0x04, 30), MUX_GATE_CLR_SET_UPD(CLK_TOP_AUD_INTBUS, "top_aud_intbus", @@ -1078,7 +1082,8 @@ static const struct mtk_mux top_mtk_muxes[] = { MUX_GATE_CLR_SET_UPD(CLK_TOP_PWM, "top_pwm", pwm_parents, 0x0BC, 0x0C0, 0x0C4, 8, 4, 15, 0x08, 21), MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_MCUPM, "top_mcupm", mcupm_parents, - 0x0BC, 0x0C0, 0x0C4, 16, 4, 23, 0x08, 22, CLK_IS_CRITICAL), + 0x0BC, 0x0C0, 0x0C4, 16, 4, 23, 0x08, 22, + CLK_IS_CRITICAL | CLK_SET_RATE_PARENT), MUX_GATE_CLR_SET_UPD(CLK_TOP_SPMI_P_MST, "top_spmi_p_mst", spmi_p_mst_parents, 0x0BC, 0x0C0, 0x0C4, 24, 4, 31, 0x08, 23), /* @@ -1088,7 +1093,8 @@ static const struct mtk_mux top_mtk_muxes[] = { MUX_GATE_CLR_SET_UPD(CLK_TOP_SPMI_M_MST, "top_spmi_m_mst", spmi_m_mst_parents, 0x0C8, 0x0CC, 0x0D0, 0, 4, 7, 0x08, 24), MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_DVFSRC, "top_dvfsrc", dvfsrc_parents, - 0x0C8, 0x0CC, 0x0D0, 8, 4, 15, 0x08, 25, CLK_IS_CRITICAL), + 0x0C8, 0x0CC, 0x0D0, 8, 4, 15, 0x08, 25, + CLK_IS_CRITICAL | CLK_SET_RATE_PARENT), MUX_GATE_CLR_SET_UPD(CLK_TOP_TL, "top_tl", tl_parents, 0x0C8, 0x0CC, 0x0D0, 16, 4, 23, 0x08, 26), MUX_GATE_CLR_SET_UPD(CLK_TOP_AES_MSDCFDE, "top_aes_msdcfde", @@ -1164,9 +1170,11 @@ static const struct mtk_mux top_mtk_muxes[] = { MUX_GATE_CLR_SET_UPD(CLK_TOP_SPINOR, "top_spinor", spinor_parents, 0x0128, 0x012C, 0x0130, 0, 4, 7, 0x0C, 24), MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_ULPOSC, "top_ulposc", ulposc_parents, - 0x0128, 0x012C, 0x0130, 8, 4, 15, 0x0C, 25, CLK_IS_CRITICAL), + 0x0128, 0x012C, 0x0130, 8, 4, 15, 0x0C, 25, + CLK_IS_CRITICAL | CLK_SET_RATE_PARENT), MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_SRCK, "top_srck", srck_parents, - 0x0128, 0x012C, 0x0130, 16, 4, 23, 0x0C, 26, CLK_IS_CRITICAL), + 0x0128, 0x012C, 0x0130, 16, 4, 23, 0x0C, 26, + CLK_IS_CRITICAL | CLK_SET_RATE_PARENT), }; static const struct mtk_composite top_adj_divs[] = { @@ -1322,7 +1330,7 @@ static int clk_mt8188_topck_probe(struct platform_device *pdev) return r; } -static int clk_mt8188_topck_remove(struct platform_device *pdev) +static void clk_mt8188_topck_remove(struct platform_device *pdev) { struct clk_hw_onecell_data *top_clk_data = platform_get_drvdata(pdev); struct device_node *node = pdev->dev.of_node; @@ -1334,13 +1342,11 @@ static int clk_mt8188_topck_remove(struct platform_device *pdev) mtk_clk_unregister_factors(top_divs, ARRAY_SIZE(top_divs), top_clk_data); mtk_clk_unregister_fixed_clks(top_fixed_clks, ARRAY_SIZE(top_fixed_clks), top_clk_data); mtk_free_clk_data(top_clk_data); - - return 0; } static struct platform_driver clk_mt8188_topck_drv = { .probe = clk_mt8188_topck_probe, - .remove = clk_mt8188_topck_remove, + .remove_new = clk_mt8188_topck_remove, .driver = { .name = "clk-mt8188-topck", .of_match_table = of_match_clk_mt8188_topck, diff --git a/drivers/clk/mediatek/clk-mt8188-vdec.c b/drivers/clk/mediatek/clk-mt8188-vdec.c index 8c3d76531753572dede88b643066e7fb876ee31c..db5855d133ac544284e4404c7307d0a05c6dc446 100644 --- a/drivers/clk/mediatek/clk-mt8188-vdec.c +++ b/drivers/clk/mediatek/clk-mt8188-vdec.c @@ -81,7 +81,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8188_vdec); static struct platform_driver clk_mt8188_vdec_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt8188-vdec", .of_match_table = of_match_clk_mt8188_vdec, diff --git a/drivers/clk/mediatek/clk-mt8188-vdo0.c b/drivers/clk/mediatek/clk-mt8188-vdo0.c index d2be44c2f3f5806cf4b0e8c9e90fe9ecd0f946e1..d252e198678c2f3749db239cecc206d614727904 100644 --- a/drivers/clk/mediatek/clk-mt8188-vdo0.c +++ b/drivers/clk/mediatek/clk-mt8188-vdo0.c @@ -97,7 +97,7 @@ MODULE_DEVICE_TABLE(platform, clk_mt8188_vdo0_id_table); static struct platform_driver clk_mt8188_vdo0_drv = { .probe = mtk_clk_pdev_probe, - .remove = mtk_clk_pdev_remove, + .remove_new = mtk_clk_pdev_remove, .driver = { .name = "clk-mt8188-vdo0", }, diff --git a/drivers/clk/mediatek/clk-mt8188-vdo1.c b/drivers/clk/mediatek/clk-mt8188-vdo1.c index 2ef8cae2e16ed8d87f8c6880340bbf3dc7a71b15..7b72d54086db3789ff5c0130fa3f84ff97d84445 100644 --- a/drivers/clk/mediatek/clk-mt8188-vdo1.c +++ b/drivers/clk/mediatek/clk-mt8188-vdo1.c @@ -144,7 +144,7 @@ MODULE_DEVICE_TABLE(platform, clk_mt8188_vdo1_id_table); static struct platform_driver clk_mt8188_vdo1_drv = { .probe = mtk_clk_pdev_probe, - .remove = mtk_clk_pdev_remove, + .remove_new = mtk_clk_pdev_remove, .driver = { .name = "clk-mt8188-vdo1", }, diff --git a/drivers/clk/mediatek/clk-mt8188-venc.c b/drivers/clk/mediatek/clk-mt8188-venc.c index 245367f33fa538c58ab4711bb7ad08b477e79910..5b1713908ed2c1ada986cb35d56e29f2e27362ff 100644 --- a/drivers/clk/mediatek/clk-mt8188-venc.c +++ b/drivers/clk/mediatek/clk-mt8188-venc.c @@ -45,7 +45,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8188_venc1); static struct platform_driver clk_mt8188_venc1_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt8188-venc1", .of_match_table = of_match_clk_mt8188_venc1, diff --git a/drivers/clk/mediatek/clk-mt8188-vpp0.c b/drivers/clk/mediatek/clk-mt8188-vpp0.c index 07bdedf6a21ac4a27372fb3470e654687e81a59c..e7b02b26fefbc0f49095c7425113d4385d8dad84 100644 --- a/drivers/clk/mediatek/clk-mt8188-vpp0.c +++ b/drivers/clk/mediatek/clk-mt8188-vpp0.c @@ -104,7 +104,7 @@ MODULE_DEVICE_TABLE(platform, clk_mt8188_vpp0_id_table); static struct platform_driver clk_mt8188_vpp0_drv = { .probe = mtk_clk_pdev_probe, - .remove = mtk_clk_pdev_remove, + .remove_new = mtk_clk_pdev_remove, .driver = { .name = "clk-mt8188-vpp0", }, diff --git a/drivers/clk/mediatek/clk-mt8188-vpp1.c b/drivers/clk/mediatek/clk-mt8188-vpp1.c index d4e66b2405733d9819d8f575753f4de5107d1dd9..e8f0f7eca097b5788b1db399e82a4e70b5762418 100644 --- a/drivers/clk/mediatek/clk-mt8188-vpp1.c +++ b/drivers/clk/mediatek/clk-mt8188-vpp1.c @@ -99,7 +99,7 @@ MODULE_DEVICE_TABLE(platform, clk_mt8188_vpp1_id_table); static struct platform_driver clk_mt8188_vpp1_drv = { .probe = mtk_clk_pdev_probe, - .remove = mtk_clk_pdev_remove, + .remove_new = mtk_clk_pdev_remove, .driver = { .name = "clk-mt8188-vpp1", }, diff --git a/drivers/clk/mediatek/clk-mt8188-wpe.c b/drivers/clk/mediatek/clk-mt8188-wpe.c index 393ac38a21724863d22ce2acd2c6e64faf387f74..f394ec049872724c3c7c7007796217a80a1c683e 100644 --- a/drivers/clk/mediatek/clk-mt8188-wpe.c +++ b/drivers/clk/mediatek/clk-mt8188-wpe.c @@ -94,7 +94,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8188_wpe); static struct platform_driver clk_mt8188_wpe_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt8188-wpe", .of_match_table = of_match_clk_mt8188_wpe, diff --git a/drivers/clk/mediatek/clk-mt8192-apmixedsys.c b/drivers/clk/mediatek/clk-mt8192-apmixedsys.c index eafd34297b9a979abd4a51e69f4b0d50d1c37e0a..3590932acc63a2551813a6316c2bb4ac788b5499 100644 --- a/drivers/clk/mediatek/clk-mt8192-apmixedsys.c +++ b/drivers/clk/mediatek/clk-mt8192-apmixedsys.c @@ -188,7 +188,7 @@ static int clk_mt8192_apmixed_probe(struct platform_device *pdev) return r; } -static int clk_mt8192_apmixed_remove(struct platform_device *pdev) +static void clk_mt8192_apmixed_remove(struct platform_device *pdev) { struct device_node *node = pdev->dev.of_node; struct clk_hw_onecell_data *clk_data = platform_get_drvdata(pdev); @@ -198,8 +198,6 @@ static int clk_mt8192_apmixed_remove(struct platform_device *pdev) mtk_clk_unregister_pllfhs(plls, ARRAY_SIZE(plls), pllfhs, ARRAY_SIZE(pllfhs), clk_data); mtk_free_clk_data(clk_data); - - return 0; } static struct platform_driver clk_mt8192_apmixed_drv = { @@ -208,7 +206,7 @@ static struct platform_driver clk_mt8192_apmixed_drv = { .of_match_table = of_match_clk_mt8192_apmixed, }, .probe = clk_mt8192_apmixed_probe, - .remove = clk_mt8192_apmixed_remove, + .remove_new = clk_mt8192_apmixed_remove, }; module_platform_driver(clk_mt8192_apmixed_drv); MODULE_DESCRIPTION("MediaTek MT8192 apmixed clocks driver"); diff --git a/drivers/clk/mediatek/clk-mt8192-aud.c b/drivers/clk/mediatek/clk-mt8192-aud.c index ee251492d4f13a05d4404b54a390958831c6a354..5bce67bf701d372f38ed1cca9d6bc0b2f046f331 100644 --- a/drivers/clk/mediatek/clk-mt8192-aud.c +++ b/drivers/clk/mediatek/clk-mt8192-aud.c @@ -97,10 +97,10 @@ static int clk_mt8192_aud_probe(struct platform_device *pdev) return r; } -static int clk_mt8192_aud_remove(struct platform_device *pdev) +static void clk_mt8192_aud_remove(struct platform_device *pdev) { of_platform_depopulate(&pdev->dev); - return mtk_clk_simple_remove(pdev); + mtk_clk_simple_remove(pdev); } static const struct of_device_id of_match_clk_mt8192_aud[] = { @@ -111,7 +111,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8192_aud); static struct platform_driver clk_mt8192_aud_drv = { .probe = clk_mt8192_aud_probe, - .remove = clk_mt8192_aud_remove, + .remove_new = clk_mt8192_aud_remove, .driver = { .name = "clk-mt8192-aud", .of_match_table = of_match_clk_mt8192_aud, diff --git a/drivers/clk/mediatek/clk-mt8192-cam.c b/drivers/clk/mediatek/clk-mt8192-cam.c index 7befd6ee8c799c1b1265edc8a0bde0e0e134a5b4..7b9327eba92417272e6e1d080856a66413228790 100644 --- a/drivers/clk/mediatek/clk-mt8192-cam.c +++ b/drivers/clk/mediatek/clk-mt8192-cam.c @@ -99,7 +99,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8192_cam); static struct platform_driver clk_mt8192_cam_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt8192-cam", .of_match_table = of_match_clk_mt8192_cam, diff --git a/drivers/clk/mediatek/clk-mt8192-img.c b/drivers/clk/mediatek/clk-mt8192-img.c index a7505150a9d014124cdb5a6f133501421426b98b..0208030c31a0d00b887808a8ffcae9b463c64625 100644 --- a/drivers/clk/mediatek/clk-mt8192-img.c +++ b/drivers/clk/mediatek/clk-mt8192-img.c @@ -62,7 +62,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8192_img); static struct platform_driver clk_mt8192_img_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt8192-img", .of_match_table = of_match_clk_mt8192_img, diff --git a/drivers/clk/mediatek/clk-mt8192-imp_iic_wrap.c b/drivers/clk/mediatek/clk-mt8192-imp_iic_wrap.c index cd5d00a7c54b32081978f31777884c75bd35e089..275581f8c7107b8625cd500e7b619856f804fd1e 100644 --- a/drivers/clk/mediatek/clk-mt8192-imp_iic_wrap.c +++ b/drivers/clk/mediatek/clk-mt8192-imp_iic_wrap.c @@ -111,7 +111,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8192_imp_iic_wrap); static struct platform_driver clk_mt8192_imp_iic_wrap_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt8192-imp_iic_wrap", .of_match_table = of_match_clk_mt8192_imp_iic_wrap, diff --git a/drivers/clk/mediatek/clk-mt8192-ipe.c b/drivers/clk/mediatek/clk-mt8192-ipe.c index dee671ae38e6d42d96fe4561d7d3d6cec7a3a39e..f3656c3b9573c61e0c54f2e0655f3eb5e67bd9af 100644 --- a/drivers/clk/mediatek/clk-mt8192-ipe.c +++ b/drivers/clk/mediatek/clk-mt8192-ipe.c @@ -49,7 +49,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8192_ipe); static struct platform_driver clk_mt8192_ipe_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt8192-ipe", .of_match_table = of_match_clk_mt8192_ipe, diff --git a/drivers/clk/mediatek/clk-mt8192-mdp.c b/drivers/clk/mediatek/clk-mt8192-mdp.c index f7b27264e378c5f8f48ea59e72b4220962f3ab64..5385ac95533a7632a65aea9873c99425b4e173fa 100644 --- a/drivers/clk/mediatek/clk-mt8192-mdp.c +++ b/drivers/clk/mediatek/clk-mt8192-mdp.c @@ -74,7 +74,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8192_mdp); static struct platform_driver clk_mt8192_mdp_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt8192-mdp", .of_match_table = of_match_clk_mt8192_mdp, diff --git a/drivers/clk/mediatek/clk-mt8192-mfg.c b/drivers/clk/mediatek/clk-mt8192-mfg.c index 85f76a2bbac4553ffe944f38effdb91a85fd2f1e..0ac7045cf5d186aaafb88273dd39174dc7ec253a 100644 --- a/drivers/clk/mediatek/clk-mt8192-mfg.c +++ b/drivers/clk/mediatek/clk-mt8192-mfg.c @@ -44,7 +44,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8192_mfg); static struct platform_driver clk_mt8192_mfg_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt8192-mfg", .of_match_table = of_match_clk_mt8192_mfg, diff --git a/drivers/clk/mediatek/clk-mt8192-mm.c b/drivers/clk/mediatek/clk-mt8192-mm.c index 47335d5177141c0186f64ee54a876f3816ff8e9f..b294184c518341ded681b9832c3377fd08bdb41c 100644 --- a/drivers/clk/mediatek/clk-mt8192-mm.c +++ b/drivers/clk/mediatek/clk-mt8192-mm.c @@ -93,7 +93,7 @@ MODULE_DEVICE_TABLE(platform, clk_mt8192_mm_id_table); static struct platform_driver clk_mt8192_mm_drv = { .probe = mtk_clk_pdev_probe, - .remove = mtk_clk_pdev_remove, + .remove_new = mtk_clk_pdev_remove, .driver = { .name = "clk-mt8192-mm", }, diff --git a/drivers/clk/mediatek/clk-mt8192-msdc.c b/drivers/clk/mediatek/clk-mt8192-msdc.c index 60d65f96d39a13674c8717b7a0729f8df4066f0a..9da647c5b8b31fe0173af69d57e5430d1750767c 100644 --- a/drivers/clk/mediatek/clk-mt8192-msdc.c +++ b/drivers/clk/mediatek/clk-mt8192-msdc.c @@ -56,7 +56,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8192_msdc); static struct platform_driver clk_mt8192_msdc_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt8192-msdc", .of_match_table = of_match_clk_mt8192_msdc, diff --git a/drivers/clk/mediatek/clk-mt8192-scp_adsp.c b/drivers/clk/mediatek/clk-mt8192-scp_adsp.c index 6aad57797c3908ab76913aedaea0191388545a22..44091147c8136b3e599d871a89286c1731f8ef5e 100644 --- a/drivers/clk/mediatek/clk-mt8192-scp_adsp.c +++ b/drivers/clk/mediatek/clk-mt8192-scp_adsp.c @@ -42,7 +42,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8192_scp_adsp); static struct platform_driver clk_mt8192_scp_adsp_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt8192-scp_adsp", .of_match_table = of_match_clk_mt8192_scp_adsp, diff --git a/drivers/clk/mediatek/clk-mt8192-vdec.c b/drivers/clk/mediatek/clk-mt8192-vdec.c index 473afd58495c29bcdee7e59b09a188b00fdea217..d82dee8317b2982aca60c3ae3f5a9d474eb0f4cb 100644 --- a/drivers/clk/mediatek/clk-mt8192-vdec.c +++ b/drivers/clk/mediatek/clk-mt8192-vdec.c @@ -86,7 +86,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8192_vdec); static struct platform_driver clk_mt8192_vdec_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt8192-vdec", .of_match_table = of_match_clk_mt8192_vdec, diff --git a/drivers/clk/mediatek/clk-mt8192-venc.c b/drivers/clk/mediatek/clk-mt8192-venc.c index 57b1b16e23108a2feb41f4f025f2bdd4c4a9ffca..b0ef242991e5e6ebd9902cb8b056feaad5ef80b9 100644 --- a/drivers/clk/mediatek/clk-mt8192-venc.c +++ b/drivers/clk/mediatek/clk-mt8192-venc.c @@ -45,7 +45,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8192_venc); static struct platform_driver clk_mt8192_venc_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt8192-venc", .of_match_table = of_match_clk_mt8192_venc, diff --git a/drivers/clk/mediatek/clk-mt8192.c b/drivers/clk/mediatek/clk-mt8192.c index aa11291463f7578afa7c04d28c5fcaffa695820a..462ec4465b5043c0c3b4824906b239d963d6f14a 100644 --- a/drivers/clk/mediatek/clk-mt8192.c +++ b/drivers/clk/mediatek/clk-mt8192.c @@ -549,15 +549,15 @@ static const struct mtk_mux top_mtk_muxes[] = { /* CLK_CFG_0 */ MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_AXI_SEL, "axi_sel", axi_parents, 0x010, 0x014, 0x018, 0, 3, 7, 0x004, 0, - CLK_IS_CRITICAL), + CLK_IS_CRITICAL | CLK_SET_RATE_PARENT), MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_SPM_SEL, "spm_sel", spm_parents, 0x010, 0x014, 0x018, 8, 2, 15, 0x004, 1, - CLK_IS_CRITICAL), + CLK_IS_CRITICAL | CLK_SET_RATE_PARENT), MUX_GATE_CLR_SET_UPD(CLK_TOP_SCP_SEL, "scp_sel", scp_parents, 0x010, 0x014, 0x018, 16, 3, 23, 0x004, 2), MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_BUS_AXIMEM_SEL, "bus_aximem_sel", bus_aximem_parents, 0x010, 0x014, 0x018, 24, 3, 31, 0x004, 3, - CLK_IS_CRITICAL), + CLK_IS_CRITICAL | CLK_SET_RATE_PARENT), /* CLK_CFG_1 */ MUX_GATE_CLR_SET_UPD(CLK_TOP_DISP_SEL, "disp_sel", disp_parents, 0x020, 0x024, 0x028, 0, 4, 7, 0x004, 4), @@ -601,15 +601,16 @@ static const struct mtk_mux top_mtk_muxes[] = { uart_parents, 0x070, 0x074, 0x078, 8, 1, 15, 0x004, 25), MUX_GATE_CLR_SET_UPD(CLK_TOP_SPI_SEL, "spi_sel", spi_parents, 0x070, 0x074, 0x078, 16, 2, 23, 0x004, 26), - MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC50_0_H_SEL, "msdc50_0_h_sel", - msdc50_0_h_parents, 0x070, 0x074, 0x078, 24, 2, 31, 0x004, 27), + MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_MSDC50_0_H_SEL, "msdc50_0_h_sel", + msdc50_0_h_parents, 0x070, 0x074, 0x078, 24, 2, + 31, 0x004, 27, 0), /* CLK_CFG_7 */ - MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC50_0_SEL, "msdc50_0_sel", - msdc50_0_parents, 0x080, 0x084, 0x088, 0, 3, 7, 0x004, 28), - MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC30_1_SEL, "msdc30_1_sel", - msdc30_parents, 0x080, 0x084, 0x088, 8, 3, 15, 0x004, 29), - MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC30_2_SEL, "msdc30_2_sel", - msdc30_parents, 0x080, 0x084, 0x088, 16, 3, 23, 0x004, 30), + MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_MSDC50_0_SEL, "msdc50_0_sel", + msdc50_0_parents, 0x080, 0x084, 0x088, 0, 3, 7, 0x004, 28, 0), + MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_MSDC30_1_SEL, "msdc30_1_sel", + msdc30_parents, 0x080, 0x084, 0x088, 8, 3, 15, 0x004, 29, 0), + MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_MSDC30_2_SEL, "msdc30_2_sel", + msdc30_parents, 0x080, 0x084, 0x088, 16, 3, 23, 0x004, 30, 0), MUX_GATE_CLR_SET_UPD(CLK_TOP_AUDIO_SEL, "audio_sel", audio_parents, 0x080, 0x084, 0x088, 24, 2, 31, 0x008, 0), /* CLK_CFG_8 */ @@ -1027,7 +1028,7 @@ static struct platform_driver clk_mt8192_drv = { .of_match_table = of_match_clk_mt8192, }, .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, }; module_platform_driver(clk_mt8192_drv); MODULE_LICENSE("GPL"); diff --git a/drivers/clk/mediatek/clk-mt8195-apmixedsys.c b/drivers/clk/mediatek/clk-mt8195-apmixedsys.c index 8b9b5d8202869b6af3ebb40eb4dc67fffcc2634b..502a9dc1fdb8fe7147d27d15d0a092598d80a3c8 100644 --- a/drivers/clk/mediatek/clk-mt8195-apmixedsys.c +++ b/drivers/clk/mediatek/clk-mt8195-apmixedsys.c @@ -209,7 +209,7 @@ static int clk_mt8195_apmixed_probe(struct platform_device *pdev) return r; } -static int clk_mt8195_apmixed_remove(struct platform_device *pdev) +static void clk_mt8195_apmixed_remove(struct platform_device *pdev) { struct device_node *node = pdev->dev.of_node; struct clk_hw_onecell_data *clk_data = platform_get_drvdata(pdev); @@ -219,13 +219,11 @@ static int clk_mt8195_apmixed_remove(struct platform_device *pdev) mtk_clk_unregister_pllfhs(plls, ARRAY_SIZE(plls), pllfhs, ARRAY_SIZE(pllfhs), clk_data); mtk_free_clk_data(clk_data); - - return 0; } static struct platform_driver clk_mt8195_apmixed_drv = { .probe = clk_mt8195_apmixed_probe, - .remove = clk_mt8195_apmixed_remove, + .remove_new = clk_mt8195_apmixed_remove, .driver = { .name = "clk-mt8195-apmixed", .of_match_table = of_match_clk_mt8195_apmixed, diff --git a/drivers/clk/mediatek/clk-mt8195-apusys_pll.c b/drivers/clk/mediatek/clk-mt8195-apusys_pll.c index de04c087c8c33d15e947d313eca82d7d0fcdbdba..79762bc85cd7f3451db18d15df901f1ccf5d1a3e 100644 --- a/drivers/clk/mediatek/clk-mt8195-apusys_pll.c +++ b/drivers/clk/mediatek/clk-mt8195-apusys_pll.c @@ -85,7 +85,7 @@ static int clk_mt8195_apusys_pll_probe(struct platform_device *pdev) return r; } -static int clk_mt8195_apusys_pll_remove(struct platform_device *pdev) +static void clk_mt8195_apusys_pll_remove(struct platform_device *pdev) { struct clk_hw_onecell_data *clk_data = platform_get_drvdata(pdev); struct device_node *node = pdev->dev.of_node; @@ -93,8 +93,6 @@ static int clk_mt8195_apusys_pll_remove(struct platform_device *pdev) of_clk_del_provider(node); mtk_clk_unregister_plls(apusys_plls, ARRAY_SIZE(apusys_plls), clk_data); mtk_free_clk_data(clk_data); - - return 0; } static const struct of_device_id of_match_clk_mt8195_apusys_pll[] = { @@ -105,7 +103,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8195_apusys_pll); static struct platform_driver clk_mt8195_apusys_pll_drv = { .probe = clk_mt8195_apusys_pll_probe, - .remove = clk_mt8195_apusys_pll_remove, + .remove_new = clk_mt8195_apusys_pll_remove, .driver = { .name = "clk-mt8195-apusys_pll", .of_match_table = of_match_clk_mt8195_apusys_pll, diff --git a/drivers/clk/mediatek/clk-mt8195-cam.c b/drivers/clk/mediatek/clk-mt8195-cam.c index 77e608be579aa138e5fab3db5ea682d56ad4f878..24cd6a2092b6411b6b9b4dae173b839da0b09fbb 100644 --- a/drivers/clk/mediatek/clk-mt8195-cam.c +++ b/drivers/clk/mediatek/clk-mt8195-cam.c @@ -135,7 +135,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8195_cam); static struct platform_driver clk_mt8195_cam_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt8195-cam", .of_match_table = of_match_clk_mt8195_cam, diff --git a/drivers/clk/mediatek/clk-mt8195-ccu.c b/drivers/clk/mediatek/clk-mt8195-ccu.c index bdc2e6f3e9ce3cb012a8fa9300da11d8e550fec2..24dab128507a369c8540cec36df3c6a538519da1 100644 --- a/drivers/clk/mediatek/clk-mt8195-ccu.c +++ b/drivers/clk/mediatek/clk-mt8195-ccu.c @@ -43,7 +43,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8195_ccu); static struct platform_driver clk_mt8195_ccu_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt8195-ccu", .of_match_table = of_match_clk_mt8195_ccu, diff --git a/drivers/clk/mediatek/clk-mt8195-img.c b/drivers/clk/mediatek/clk-mt8195-img.c index d853e0e63d87a8a32ff8404069ca05984ebc9c1b..c7dc3e9d133d1b563478701788e18bba9c3e27c5 100644 --- a/drivers/clk/mediatek/clk-mt8195-img.c +++ b/drivers/clk/mediatek/clk-mt8195-img.c @@ -89,7 +89,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8195_img); static struct platform_driver clk_mt8195_img_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt8195-img", .of_match_table = of_match_clk_mt8195_img, diff --git a/drivers/clk/mediatek/clk-mt8195-imp_iic_wrap.c b/drivers/clk/mediatek/clk-mt8195-imp_iic_wrap.c index 1d808876f5c54fb89e87d1c80bce6d13b0298104..94912d45509edb3fdb448da12b2f536703124654 100644 --- a/drivers/clk/mediatek/clk-mt8195-imp_iic_wrap.c +++ b/drivers/clk/mediatek/clk-mt8195-imp_iic_wrap.c @@ -59,7 +59,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8195_imp_iic_wrap); static struct platform_driver clk_mt8195_imp_iic_wrap_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt8195-imp_iic_wrap", .of_match_table = of_match_clk_mt8195_imp_iic_wrap, diff --git a/drivers/clk/mediatek/clk-mt8195-infra_ao.c b/drivers/clk/mediatek/clk-mt8195-infra_ao.c index f3ee4390707dd7c2fd07341d9099569e95211944..dfba6eb61ccfeed3239f7c032f4e9f5d8c26204b 100644 --- a/drivers/clk/mediatek/clk-mt8195-infra_ao.c +++ b/drivers/clk/mediatek/clk-mt8195-infra_ao.c @@ -233,7 +233,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8195_infra_ao); static struct platform_driver clk_mt8195_infra_ao_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt8195-infra_ao", .of_match_table = of_match_clk_mt8195_infra_ao, diff --git a/drivers/clk/mediatek/clk-mt8195-ipe.c b/drivers/clk/mediatek/clk-mt8195-ipe.c index 4c47f65212753b51b2240646ffd62c5c0332602c..21e76e5ad37609702786705117c88e894a143342 100644 --- a/drivers/clk/mediatek/clk-mt8195-ipe.c +++ b/drivers/clk/mediatek/clk-mt8195-ipe.c @@ -44,7 +44,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8195_ipe); static struct platform_driver clk_mt8195_ipe_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt8195-ipe", .of_match_table = of_match_clk_mt8195_ipe, diff --git a/drivers/clk/mediatek/clk-mt8195-mfg.c b/drivers/clk/mediatek/clk-mt8195-mfg.c index 038acf0b1167ab73529d8e1301aeb37169bec6ed..4951574abf2afbd4ddb11025019bf21782a7e89e 100644 --- a/drivers/clk/mediatek/clk-mt8195-mfg.c +++ b/drivers/clk/mediatek/clk-mt8195-mfg.c @@ -42,7 +42,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8195_mfg); static struct platform_driver clk_mt8195_mfg_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt8195-mfg", .of_match_table = of_match_clk_mt8195_mfg, diff --git a/drivers/clk/mediatek/clk-mt8195-peri_ao.c b/drivers/clk/mediatek/clk-mt8195-peri_ao.c index 0de162593c0153cbee2a23e4f5b63906b28838e4..39069aaf6bcd8e850efd6e91f3fa88194900b68a 100644 --- a/drivers/clk/mediatek/clk-mt8195-peri_ao.c +++ b/drivers/clk/mediatek/clk-mt8195-peri_ao.c @@ -55,7 +55,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8195_peri_ao); static struct platform_driver clk_mt8195_peri_ao_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt8195-peri_ao", .of_match_table = of_match_clk_mt8195_peri_ao, diff --git a/drivers/clk/mediatek/clk-mt8195-scp_adsp.c b/drivers/clk/mediatek/clk-mt8195-scp_adsp.c index d0d3e3b097803a698b1284c619f5fdec4021a094..2b94d75be29550237d1746b83ad275c7d1728dbd 100644 --- a/drivers/clk/mediatek/clk-mt8195-scp_adsp.c +++ b/drivers/clk/mediatek/clk-mt8195-scp_adsp.c @@ -40,7 +40,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8195_scp_adsp); static struct platform_driver clk_mt8195_scp_adsp_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt8195-scp_adsp", .of_match_table = of_match_clk_mt8195_scp_adsp, diff --git a/drivers/clk/mediatek/clk-mt8195-topckgen.c b/drivers/clk/mediatek/clk-mt8195-topckgen.c index 3c2174c3e742f390526a367921144d5ed9684e25..81daa24caddee2a8c5dd4ac7fc6941cb8d8ae45e 100644 --- a/drivers/clk/mediatek/clk-mt8195-topckgen.c +++ b/drivers/clk/mediatek/clk-mt8195-topckgen.c @@ -862,13 +862,17 @@ static const struct mtk_mux top_mtk_muxes[] = { * top_spm and top_scp are main clocks in always-on co-processor. */ MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_AXI, "top_axi", - axi_parents, 0x020, 0x024, 0x028, 0, 3, 7, 0x04, 0, CLK_IS_CRITICAL), + axi_parents, 0x020, 0x024, 0x028, 0, 3, 7, 0x04, 0, + CLK_IS_CRITICAL | CLK_SET_RATE_PARENT), MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_SPM, "top_spm", - spm_parents, 0x020, 0x024, 0x028, 8, 2, 15, 0x04, 1, CLK_IS_CRITICAL), + spm_parents, 0x020, 0x024, 0x028, 8, 2, 15, 0x04, 1, + CLK_IS_CRITICAL | CLK_SET_RATE_PARENT), MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_SCP, "top_scp", - scp_parents, 0x020, 0x024, 0x028, 16, 3, 23, 0x04, 2, CLK_IS_CRITICAL), + scp_parents, 0x020, 0x024, 0x028, 16, 3, 23, 0x04, 2, + CLK_IS_CRITICAL | CLK_SET_RATE_PARENT), MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_BUS_AXIMEM, "top_bus_aximem", - bus_aximem_parents, 0x020, 0x024, 0x028, 24, 3, 31, 0x04, 3, CLK_IS_CRITICAL), + bus_aximem_parents, 0x020, 0x024, 0x028, 24, 3, 31, 0x04, 3, + CLK_IS_CRITICAL | CLK_SET_RATE_PARENT), /* CLK_CFG_1 */ MUX_GATE_CLR_SET_UPD(CLK_TOP_VPP, "top_vpp", vpp_parents, 0x02C, 0x030, 0x034, 0, 4, 7, 0x04, 4), @@ -926,15 +930,15 @@ static const struct mtk_mux top_mtk_muxes[] = { /* CLK_CFG_7 */ MUX_GATE_CLR_SET_UPD(CLK_TOP_SPIS, "top_spis", spis_parents, 0x074, 0x078, 0x07C, 0, 3, 7, 0x04, 28), - MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC50_0_HCLK, "top_msdc50_0_hclk", - msdc50_0_h_parents, 0x074, 0x078, 0x07C, 8, 2, 15, 0x04, 29), - MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC50_0, "top_msdc50_0", - msdc50_0_parents, 0x074, 0x078, 0x07C, 16, 3, 23, 0x04, 30), - MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC30_1, "top_msdc30_1", - msdc30_parents, 0x074, 0x078, 0x07C, 24, 3, 31, 0x04, 31), + MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_MSDC50_0_HCLK, "top_msdc50_0_hclk", + msdc50_0_h_parents, 0x074, 0x078, 0x07C, 8, 2, 15, 0x04, 29, 0), + MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_MSDC50_0, "top_msdc50_0", + msdc50_0_parents, 0x074, 0x078, 0x07C, 16, 3, 23, 0x04, 30, 0), + MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_MSDC30_1, "top_msdc30_1", + msdc30_parents, 0x074, 0x078, 0x07C, 24, 3, 31, 0x04, 31, 0), /* CLK_CFG_8 */ - MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC30_2, "top_msdc30_2", - msdc30_parents, 0x080, 0x084, 0x088, 0, 3, 7, 0x08, 0), + MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_MSDC30_2, "top_msdc30_2", + msdc30_parents, 0x080, 0x084, 0x088, 0, 3, 7, 0x08, 0, 0), MUX_GATE_CLR_SET_UPD(CLK_TOP_INTDIR, "top_intdir", intdir_parents, 0x080, 0x084, 0x088, 8, 2, 15, 0x08, 1), MUX_GATE_CLR_SET_UPD(CLK_TOP_AUD_INTBUS, "top_aud_intbus", @@ -951,7 +955,8 @@ static const struct mtk_mux top_mtk_muxes[] = { MUX_GATE_CLR_SET_UPD(CLK_TOP_ATB, "top_atb", atb_parents, 0x08C, 0x090, 0x094, 8, 2, 15, 0x08, 5), MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_PWRMCU, "top_pwrmcu", - pwrmcu_parents, 0x08C, 0x090, 0x094, 16, 3, 23, 0x08, 6, CLK_IS_CRITICAL), + pwrmcu_parents, 0x08C, 0x090, 0x094, 16, 3, 23, 0x08, 6, + CLK_IS_CRITICAL | CLK_SET_RATE_PARENT), MUX_GATE_CLR_SET_UPD(CLK_TOP_DP, "top_dp", dp_parents, 0x08C, 0x090, 0x094, 24, 4, 31, 0x08, 7), /* CLK_CFG_10 */ @@ -1020,7 +1025,8 @@ static const struct mtk_mux top_mtk_muxes[] = { MUX_GATE_CLR_SET_UPD(CLK_TOP_PWM, "top_pwm", pwm_parents, 0x0E0, 0x0E4, 0x0E8, 16, 1, 23, 0x0C, 2), MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_MCUPM, "top_mcupm", - mcupm_parents, 0x0E0, 0x0E4, 0x0E8, 24, 2, 31, 0x0C, 3, CLK_IS_CRITICAL), + mcupm_parents, 0x0E0, 0x0E4, 0x0E8, 24, 2, 31, 0x0C, 3, + CLK_IS_CRITICAL | CLK_SET_RATE_PARENT), /* * CLK_CFG_17 * top_dvfsrc is for internal DVFS usage, should not be handled by Linux. @@ -1030,7 +1036,8 @@ static const struct mtk_mux top_mtk_muxes[] = { MUX_GATE_CLR_SET_UPD(CLK_TOP_SPMI_M_MST, "top_spmi_m_mst", spmi_parents, 0x0EC, 0x0F0, 0x0F4, 8, 4, 15, 0x0C, 5), MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_DVFSRC, "top_dvfsrc", - dvfsrc_parents, 0x0EC, 0x0F0, 0x0F4, 16, 2, 23, 0x0C, 6, CLK_IS_CRITICAL), + dvfsrc_parents, 0x0EC, 0x0F0, 0x0F4, 16, 2, 23, 0x0C, 6, + CLK_IS_CRITICAL | CLK_SET_RATE_PARENT), MUX_GATE_CLR_SET_UPD(CLK_TOP_TL, "top_tl", tl_parents, 0x0EC, 0x0F0, 0x0F4, 24, 2, 31, 0x0C, 7), /* CLK_CFG_18 */ @@ -1141,11 +1148,14 @@ static const struct mtk_mux top_mtk_muxes[] = { MUX_GATE_CLR_SET_UPD(CLK_TOP_DVIO_DGI_REF, "top_dvio_dgi_ref", dvio_dgi_ref_parents, 0x017C, 0x0180, 0x0184, 0, 3, 7, 0x010, 20), MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_ULPOSC, "top_ulposc", - ulposc_parents, 0x017C, 0x0180, 0x0184, 8, 2, 15, 0x010, 21, CLK_IS_CRITICAL), + ulposc_parents, 0x017C, 0x0180, 0x0184, 8, 2, 15, 0x010, 21, + CLK_IS_CRITICAL | CLK_SET_RATE_PARENT), MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_ULPOSC_CORE, "top_ulposc_core", - ulposc_core_parents, 0x017C, 0x0180, 0x0184, 16, 2, 23, 0x010, 22, CLK_IS_CRITICAL), + ulposc_core_parents, 0x017C, 0x0180, 0x0184, 16, 2, 23, 0x010, 22, + CLK_IS_CRITICAL | CLK_SET_RATE_PARENT), MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_SRCK, "top_srck", - srck_parents, 0x017C, 0x0180, 0x0184, 24, 1, 31, 0x010, 23, CLK_IS_CRITICAL), + srck_parents, 0x017C, 0x0180, 0x0184, 24, 1, 31, 0x010, 23, + CLK_IS_CRITICAL | CLK_SET_RATE_PARENT), /* * the clocks in CLK_CFG_30 ~ 37 are backup clock source, no need to handled * by Linux. @@ -1317,7 +1327,7 @@ static int clk_mt8195_topck_probe(struct platform_device *pdev) return r; } -static int clk_mt8195_topck_remove(struct platform_device *pdev) +static void clk_mt8195_topck_remove(struct platform_device *pdev) { struct clk_hw_onecell_data *top_clk_data = platform_get_drvdata(pdev); struct device_node *node = pdev->dev.of_node; @@ -1329,13 +1339,11 @@ static int clk_mt8195_topck_remove(struct platform_device *pdev) mtk_clk_unregister_factors(top_divs, ARRAY_SIZE(top_divs), top_clk_data); mtk_clk_unregister_fixed_clks(top_fixed_clks, ARRAY_SIZE(top_fixed_clks), top_clk_data); mtk_free_clk_data(top_clk_data); - - return 0; } static struct platform_driver clk_mt8195_topck_drv = { .probe = clk_mt8195_topck_probe, - .remove = clk_mt8195_topck_remove, + .remove_new = clk_mt8195_topck_remove, .driver = { .name = "clk-mt8195-topck", .of_match_table = of_match_clk_mt8195_topck, diff --git a/drivers/clk/mediatek/clk-mt8195-vdec.c b/drivers/clk/mediatek/clk-mt8195-vdec.c index 2bcbceb10326bb2a27f3128f0193ace2db3d4c86..d266a6d3b6032dfc8c13642d64daf322e587bfdc 100644 --- a/drivers/clk/mediatek/clk-mt8195-vdec.c +++ b/drivers/clk/mediatek/clk-mt8195-vdec.c @@ -97,7 +97,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8195_vdec); static struct platform_driver clk_mt8195_vdec_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt8195-vdec", .of_match_table = of_match_clk_mt8195_vdec, diff --git a/drivers/clk/mediatek/clk-mt8195-vdo0.c b/drivers/clk/mediatek/clk-mt8195-vdo0.c index 509780750e43c31dc5922bce5afa7fad2d491f47..34fc318c146c33426f5c23c7ca13e52a5953cb20 100644 --- a/drivers/clk/mediatek/clk-mt8195-vdo0.c +++ b/drivers/clk/mediatek/clk-mt8195-vdo0.c @@ -106,7 +106,7 @@ MODULE_DEVICE_TABLE(platform, clk_mt8195_vdo0_id_table); static struct platform_driver clk_mt8195_vdo0_drv = { .probe = mtk_clk_pdev_probe, - .remove = mtk_clk_pdev_remove, + .remove_new = mtk_clk_pdev_remove, .driver = { .name = "clk-mt8195-vdo0", }, diff --git a/drivers/clk/mediatek/clk-mt8195-vdo1.c b/drivers/clk/mediatek/clk-mt8195-vdo1.c index 0a5214a1ed256f4c5cb979cd96b6c263647378e2..e400631e1dbeac78943562cc6077c1fe83c0d004 100644 --- a/drivers/clk/mediatek/clk-mt8195-vdo1.c +++ b/drivers/clk/mediatek/clk-mt8195-vdo1.c @@ -133,7 +133,7 @@ MODULE_DEVICE_TABLE(platform, clk_mt8195_vdo1_id_table); static struct platform_driver clk_mt8195_vdo1_drv = { .probe = mtk_clk_pdev_probe, - .remove = mtk_clk_pdev_remove, + .remove_new = mtk_clk_pdev_remove, .driver = { .name = "clk-mt8195-vdo1", }, diff --git a/drivers/clk/mediatek/clk-mt8195-venc.c b/drivers/clk/mediatek/clk-mt8195-venc.c index 0991a69687650ef513ca7d3c720e06b4463cc61f..93093fadfd0d7d1ee313f68396456e1cedf0dea5 100644 --- a/drivers/clk/mediatek/clk-mt8195-venc.c +++ b/drivers/clk/mediatek/clk-mt8195-venc.c @@ -62,7 +62,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8195_venc); static struct platform_driver clk_mt8195_venc_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt8195-venc", .of_match_table = of_match_clk_mt8195_venc, diff --git a/drivers/clk/mediatek/clk-mt8195-vpp0.c b/drivers/clk/mediatek/clk-mt8195-vpp0.c index 1a98fb9a25e8a3274a87448ae09990aa2525175a..81725fcb3a7222f28399a567296449e6c3453b8c 100644 --- a/drivers/clk/mediatek/clk-mt8195-vpp0.c +++ b/drivers/clk/mediatek/clk-mt8195-vpp0.c @@ -99,7 +99,7 @@ MODULE_DEVICE_TABLE(platform, clk_mt8195_vpp0_id_table); static struct platform_driver clk_mt8195_vpp0_drv = { .probe = mtk_clk_pdev_probe, - .remove = mtk_clk_pdev_remove, + .remove_new = mtk_clk_pdev_remove, .driver = { .name = "clk-mt8195-vpp0", }, diff --git a/drivers/clk/mediatek/clk-mt8195-vpp1.c b/drivers/clk/mediatek/clk-mt8195-vpp1.c index c2d5b582f53a6d29b27ee9b99f88fa7cdfb0e505..867fde4e575b5e9a3a67db0ba58ed45cd3191541 100644 --- a/drivers/clk/mediatek/clk-mt8195-vpp1.c +++ b/drivers/clk/mediatek/clk-mt8195-vpp1.c @@ -97,7 +97,7 @@ MODULE_DEVICE_TABLE(platform, clk_mt8195_vpp1_id_table); static struct platform_driver clk_mt8195_vpp1_drv = { .probe = mtk_clk_pdev_probe, - .remove = mtk_clk_pdev_remove, + .remove_new = mtk_clk_pdev_remove, .driver = { .name = "clk-mt8195-vpp1", }, diff --git a/drivers/clk/mediatek/clk-mt8195-wpe.c b/drivers/clk/mediatek/clk-mt8195-wpe.c index 289896cb2f6ceb0d7c49ce0c3eb17bdf81a48c86..7324738179a4f1df8359db07749a41e4453dada7 100644 --- a/drivers/clk/mediatek/clk-mt8195-wpe.c +++ b/drivers/clk/mediatek/clk-mt8195-wpe.c @@ -136,7 +136,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8195_wpe); static struct platform_driver clk_mt8195_wpe_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt8195-wpe", .of_match_table = of_match_clk_mt8195_wpe, diff --git a/drivers/clk/mediatek/clk-mt8365-apu.c b/drivers/clk/mediatek/clk-mt8365-apu.c index 74f7fb22c87f3b9ef1798e6ef1abbb345533f7d3..4f10ce1531d2cd6eb8eb4b5f5274252cdf6cfde8 100644 --- a/drivers/clk/mediatek/clk-mt8365-apu.c +++ b/drivers/clk/mediatek/clk-mt8365-apu.c @@ -46,7 +46,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8365_apu); static struct platform_driver clk_mt8365_apu_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt8365-apu", .of_match_table = of_match_clk_mt8365_apu, diff --git a/drivers/clk/mediatek/clk-mt8365-cam.c b/drivers/clk/mediatek/clk-mt8365-cam.c index 61516e19acd11e9ba96ac21a82cc8266a0cf55fb..fe428a4f1d376cd232a413e9edc49a8d88c7cc17 100644 --- a/drivers/clk/mediatek/clk-mt8365-cam.c +++ b/drivers/clk/mediatek/clk-mt8365-cam.c @@ -48,7 +48,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8365_cam); static struct platform_driver clk_mt8365_cam_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt8365-cam", .of_match_table = of_match_clk_mt8365_cam, diff --git a/drivers/clk/mediatek/clk-mt8365-mfg.c b/drivers/clk/mediatek/clk-mt8365-mfg.c index 4c836c69db4fe2cd85b131292c26ff347f662232..4a590284f7e294426f5df2c542e2ea6964d344c7 100644 --- a/drivers/clk/mediatek/clk-mt8365-mfg.c +++ b/drivers/clk/mediatek/clk-mt8365-mfg.c @@ -54,7 +54,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8365_mfg); static struct platform_driver clk_mt8365_mfg_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt8365-mfg", .of_match_table = of_match_clk_mt8365_mfg, diff --git a/drivers/clk/mediatek/clk-mt8365-mm.c b/drivers/clk/mediatek/clk-mt8365-mm.c index 44427120846f01b06cb578f010e1ce512c4d95da..01a2ef8f594ef5aa6b7e0448ca9f5304c3ef7be5 100644 --- a/drivers/clk/mediatek/clk-mt8365-mm.c +++ b/drivers/clk/mediatek/clk-mt8365-mm.c @@ -85,7 +85,7 @@ MODULE_DEVICE_TABLE(platform, clk_mt8365_mm_id_table); static struct platform_driver clk_mt8365_mm_drv = { .probe = mtk_clk_pdev_probe, - .remove = mtk_clk_pdev_remove, + .remove_new = mtk_clk_pdev_remove, .driver = { .name = "clk-mt8365-mm", }, diff --git a/drivers/clk/mediatek/clk-mt8365-vdec.c b/drivers/clk/mediatek/clk-mt8365-vdec.c index b51571e9da00607909c4946085ab2ddca27ed15a..233924837c3bdf9e525ae892337feca1aebf0de4 100644 --- a/drivers/clk/mediatek/clk-mt8365-vdec.c +++ b/drivers/clk/mediatek/clk-mt8365-vdec.c @@ -54,7 +54,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8365_vdec); static struct platform_driver clk_mt8365_vdec_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt8365-vdec", .of_match_table = of_match_clk_mt8365_vdec, diff --git a/drivers/clk/mediatek/clk-mt8365-venc.c b/drivers/clk/mediatek/clk-mt8365-venc.c index 572344645c86645202a89c489e4f7620bee7e26d..cc063f18e56b8a5ffde0d6f44758b291e84f2f13 100644 --- a/drivers/clk/mediatek/clk-mt8365-venc.c +++ b/drivers/clk/mediatek/clk-mt8365-venc.c @@ -43,7 +43,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8365_venc); static struct platform_driver clk_mt8365_venc_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt8365-venc", .of_match_table = of_match_clk_mt8365_venc, diff --git a/drivers/clk/mediatek/clk-mt8365.c b/drivers/clk/mediatek/clk-mt8365.c index c87a6c4a79678c1e29c2bd8e67eb984313f484f0..1dca18f991347dc1c3677e219ffe0bb275097368 100644 --- a/drivers/clk/mediatek/clk-mt8365.c +++ b/drivers/clk/mediatek/clk-mt8365.c @@ -411,7 +411,7 @@ static const struct mtk_mux top_muxes[] = { /* CLK_CFG_0 */ MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_AXI_SEL, "axi_sel", axi_parents, 0x040, 0x044, 0x048, 0, 2, 7, CLK_CFG_UPDATE, - 0, CLK_IS_CRITICAL), + 0, CLK_IS_CRITICAL | CLK_SET_RATE_PARENT), MUX_GATE_CLR_SET_UPD(CLK_TOP_MEM_SEL, "mem_sel", mem_parents, 0x040, 0x044, 0x048, 8, 2, 15, CLK_CFG_UPDATE, 1), MUX_GATE_CLR_SET_UPD(CLK_TOP_MM_SEL, "mm_sel", mm_parents, 0x040, 0x044, @@ -432,22 +432,22 @@ static const struct mtk_mux top_muxes[] = { 0x064, 0x068, 0, 1, 7, CLK_CFG_UPDATE, 8), MUX_GATE_CLR_SET_UPD(CLK_TOP_SPI_SEL, "spi_sel", spi_parents, 0x060, 0x064, 0x068, 8, 2, 15, CLK_CFG_UPDATE, 9), - MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC50_0_HC_SEL, "msdc50_0_hc_sel", - msdc50_0_hc_parents, 0x060, 0x064, 0x068, 16, 2, - 23, CLK_CFG_UPDATE, 10), - MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC2_2_HC_SEL, "msdc2_2_hc_sel", - msdc50_0_hc_parents, 0x060, 0x064, 0x068, 24, 2, - 31, CLK_CFG_UPDATE, 11), + MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_MSDC50_0_HC_SEL, "msdc50_0_hc_sel", + msdc50_0_hc_parents, 0x060, 0x064, 0x068, 16, 2, + 23, CLK_CFG_UPDATE, 10, 0), + MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_MSDC2_2_HC_SEL, "msdc2_2_hc_sel", + msdc50_0_hc_parents, 0x060, 0x064, 0x068, 24, 2, + 31, CLK_CFG_UPDATE, 11, 0), /* CLK_CFG_3 */ - MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC50_0_SEL, "msdc50_0_sel", - msdc50_0_parents, 0x070, 0x074, 0x078, 0, 3, 7, - CLK_CFG_UPDATE, 12), - MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC50_2_SEL, "msdc50_2_sel", - msdc50_2_parents, 0x070, 0x074, 0x078, 8, 3, 15, - CLK_CFG_UPDATE, 13), - MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC30_1_SEL, "msdc30_1_sel", - msdc30_1_parents, 0x070, 0x074, 0x078, 16, 3, 23, - CLK_CFG_UPDATE, 14), + MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_MSDC50_0_SEL, "msdc50_0_sel", + msdc50_0_parents, 0x070, 0x074, 0x078, 0, 3, 7, + CLK_CFG_UPDATE, 12, 0), + MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_MSDC50_2_SEL, "msdc50_2_sel", + msdc50_2_parents, 0x070, 0x074, 0x078, 8, 3, 15, + CLK_CFG_UPDATE, 13, 0), + MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_MSDC30_1_SEL, "msdc30_1_sel", + msdc30_1_parents, 0x070, 0x074, 0x078, 16, 3, 23, + CLK_CFG_UPDATE, 14, 0), MUX_GATE_CLR_SET_UPD(CLK_TOP_AUDIO_SEL, "audio_sel", audio_parents, 0x070, 0x074, 0x078, 24, 2, 31, CLK_CFG_UPDATE, 15), @@ -476,7 +476,7 @@ static const struct mtk_mux top_muxes[] = { /* CLK_CFG_6 */ MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_DXCC_SEL, "dxcc_sel", dxcc_parents, 0x0a0, 0x0a4, 0x0a8, 0, 2, 7, CLK_CFG_UPDATE, - 24, CLK_IS_CRITICAL), + 24, CLK_IS_CRITICAL | CLK_SET_RATE_PARENT), MUX_GATE_CLR_SET_UPD(CLK_TOP_SSUSB_SYS_SEL, "ssusb_sys_sel", ssusb_sys_parents, 0x0a0, 0x0a4, 0x0a8, 8, 2, 15, CLK_CFG_UPDATE, 25), @@ -484,8 +484,8 @@ static const struct mtk_mux top_muxes[] = { ssusb_sys_parents, 0x0a0, 0x0a4, 0x0a8, 16, 2, 23, CLK_CFG_UPDATE, 26), MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_SPM_SEL, "spm_sel", spm_parents, - 0x0a0, 0x0a4, 0x0a8, 24, 1, 31, - CLK_CFG_UPDATE, 27, CLK_IS_CRITICAL), + 0x0a0, 0x0a4, 0x0a8, 24, 1, 31, CLK_CFG_UPDATE, + 27, CLK_IS_CRITICAL | CLK_SET_RATE_PARENT), /* CLK_CFG_7 */ MUX_GATE_CLR_SET_UPD(CLK_TOP_I2C_SEL, "i2c_sel", i2c_parents, 0x0b0, 0x0b4, 0x0b8, 0, 3, 7, CLK_CFG_UPDATE, 28), @@ -811,7 +811,7 @@ static struct platform_driver clk_mt8365_drv = { .of_match_table = of_match_clk_mt8365, }, .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, }; module_platform_driver(clk_mt8365_drv); MODULE_LICENSE("GPL"); diff --git a/drivers/clk/mediatek/clk-mt8516-aud.c b/drivers/clk/mediatek/clk-mt8516-aud.c index 48340fc7430db3d0309555f5247f24d22f9ef785..d1e848e78fd568ad35665a05a0b8c1e5df58d549 100644 --- a/drivers/clk/mediatek/clk-mt8516-aud.c +++ b/drivers/clk/mediatek/clk-mt8516-aud.c @@ -55,7 +55,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8516_aud); static struct platform_driver clk_mt8516_aud_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt8516-aud", .of_match_table = of_match_clk_mt8516_aud, diff --git a/drivers/clk/mediatek/clk-mt8516.c b/drivers/clk/mediatek/clk-mt8516.c index 21eb052b0a539c060401bc1990435d0ede8073cc..b8ae837c59dc8c74fc47cee950b1dcaf3e46a23a 100644 --- a/drivers/clk/mediatek/clk-mt8516.c +++ b/drivers/clk/mediatek/clk-mt8516.c @@ -669,7 +669,7 @@ MODULE_DEVICE_TABLE(of, of_match_clk_mt8516); static struct platform_driver clk_mt8516_drv = { .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, + .remove_new = mtk_clk_simple_remove, .driver = { .name = "clk-mt8516", .of_match_table = of_match_clk_mt8516, diff --git a/drivers/clk/mediatek/clk-mtk.c b/drivers/clk/mediatek/clk-mtk.c index fd2214c3242f2b2c372d088337fbdeef18220de8..2e55368dc4d82095b5baceb7b744a9ed4b1350b4 100644 --- a/drivers/clk/mediatek/clk-mtk.c +++ b/drivers/clk/mediatek/clk-mtk.c @@ -469,7 +469,7 @@ static int __mtk_clk_simple_probe(struct platform_device *pdev, const struct platform_device_id *id; const struct mtk_clk_desc *mcd; struct clk_hw_onecell_data *clk_data; - void __iomem *base; + void __iomem *base = NULL; int num_clks, r; mcd = device_get_match_data(&pdev->dev); @@ -483,8 +483,8 @@ static int __mtk_clk_simple_probe(struct platform_device *pdev, return -EINVAL; } - /* Composite clocks needs us to pass iomem pointer */ - if (mcd->composite_clks) { + /* Composite and divider clocks needs us to pass iomem pointer */ + if (mcd->composite_clks || mcd->divider_clks) { if (!mcd->shared_io) base = devm_platform_ioremap_resource(pdev, 0); else @@ -500,8 +500,10 @@ static int __mtk_clk_simple_probe(struct platform_device *pdev, num_clks += mcd->num_mux_clks + mcd->num_divider_clks; clk_data = mtk_alloc_clk_data(num_clks); - if (!clk_data) - return -ENOMEM; + if (!clk_data) { + r = -ENOMEM; + goto free_base; + } if (mcd->fixed_clks) { r = mtk_clk_register_fixed_clks(mcd->fixed_clks, @@ -599,12 +601,13 @@ static int __mtk_clk_simple_probe(struct platform_device *pdev, mcd->num_fixed_clks, clk_data); free_data: mtk_free_clk_data(clk_data); +free_base: if (mcd->shared_io && base) iounmap(base); return r; } -static int __mtk_clk_simple_remove(struct platform_device *pdev, +static void __mtk_clk_simple_remove(struct platform_device *pdev, struct device_node *node) { struct clk_hw_onecell_data *clk_data = platform_get_drvdata(pdev); @@ -629,8 +632,6 @@ static int __mtk_clk_simple_remove(struct platform_device *pdev, mtk_clk_unregister_fixed_clks(mcd->fixed_clks, mcd->num_fixed_clks, clk_data); mtk_free_clk_data(clk_data); - - return 0; } int mtk_clk_pdev_probe(struct platform_device *pdev) @@ -650,18 +651,18 @@ int mtk_clk_simple_probe(struct platform_device *pdev) } EXPORT_SYMBOL_GPL(mtk_clk_simple_probe); -int mtk_clk_pdev_remove(struct platform_device *pdev) +void mtk_clk_pdev_remove(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct device_node *node = dev->parent->of_node; - return __mtk_clk_simple_remove(pdev, node); + __mtk_clk_simple_remove(pdev, node); } EXPORT_SYMBOL_GPL(mtk_clk_pdev_remove); -int mtk_clk_simple_remove(struct platform_device *pdev) +void mtk_clk_simple_remove(struct platform_device *pdev) { - return __mtk_clk_simple_remove(pdev, pdev->dev.of_node); + __mtk_clk_simple_remove(pdev, pdev->dev.of_node); } EXPORT_SYMBOL_GPL(mtk_clk_simple_remove); diff --git a/drivers/clk/mediatek/clk-mtk.h b/drivers/clk/mediatek/clk-mtk.h index b7a751861fcee32b45dba3c5dedd6507ed0aeb13..22096501a60a7b801ec1951a95b128f007417279 100644 --- a/drivers/clk/mediatek/clk-mtk.h +++ b/drivers/clk/mediatek/clk-mtk.h @@ -240,8 +240,8 @@ struct mtk_clk_desc { }; int mtk_clk_pdev_probe(struct platform_device *pdev); -int mtk_clk_pdev_remove(struct platform_device *pdev); +void mtk_clk_pdev_remove(struct platform_device *pdev); int mtk_clk_simple_probe(struct platform_device *pdev); -int mtk_clk_simple_remove(struct platform_device *pdev); +void mtk_clk_simple_remove(struct platform_device *pdev); #endif /* __DRV_CLK_MTK_H */ diff --git a/drivers/clk/mediatek/clk-mux.c b/drivers/clk/mediatek/clk-mux.c index c8593554239d6e9da6612161a9479291f2e2b884..c93bc7f926e5d47956aecd516bff58f6ce726139 100644 --- a/drivers/clk/mediatek/clk-mux.c +++ b/drivers/clk/mediatek/clk-mux.c @@ -168,7 +168,7 @@ static struct clk_hw *mtk_clk_register_mux(struct device *dev, return ERR_PTR(-ENOMEM); init.name = mux->name; - init.flags = mux->flags | CLK_SET_RATE_PARENT; + init.flags = mux->flags; init.parent_names = mux->parent_names; init.num_parents = mux->num_parents; init.ops = mux->ops; diff --git a/drivers/clk/meson/Kconfig b/drivers/clk/meson/Kconfig index fc002c155bc3e0ddfa24ddf915578ccaef40cd33..8ce846fdbe43433877ad3471ec3ff1258a9f6f20 100644 --- a/drivers/clk/meson/Kconfig +++ b/drivers/clk/meson/Kconfig @@ -99,6 +99,26 @@ config COMMON_CLK_AXG_AUDIO Support for the audio clock controller on AmLogic A113D devices, aka axg, Say Y if you want audio subsystem to work. +config COMMON_CLK_A1_PLL + tristate "Amlogic A1 SoC PLL controller support" + depends on ARM64 + select COMMON_CLK_MESON_REGMAP + select COMMON_CLK_MESON_PLL + help + Support for the PLL clock controller on Amlogic A113L based + device, A1 SoC Family. Say Y if you want A1 PLL clock controller + to work. + +config COMMON_CLK_A1_PERIPHERALS + tristate "Amlogic A1 SoC Peripherals clock controller support" + depends on ARM64 + select COMMON_CLK_MESON_DUALDIV + select COMMON_CLK_MESON_REGMAP + help + Support for the Peripherals clock controller on Amlogic A113L based + device, A1 SoC Family. Say Y if you want A1 Peripherals clock + controller to work. + config COMMON_CLK_G12A tristate "G12 and SM1 SoC clock controllers support" depends on ARM64 diff --git a/drivers/clk/meson/Makefile b/drivers/clk/meson/Makefile index 6eca2a406ee378f0e842a8db6eecdd4f1b05878e..d5288662881d3fe89de5082da55fc95b32dd9ce0 100644 --- a/drivers/clk/meson/Makefile +++ b/drivers/clk/meson/Makefile @@ -16,6 +16,8 @@ obj-$(CONFIG_COMMON_CLK_MESON_VID_PLL_DIV) += vid-pll-div.o obj-$(CONFIG_COMMON_CLK_AXG) += axg.o axg-aoclk.o obj-$(CONFIG_COMMON_CLK_AXG_AUDIO) += axg-audio.o +obj-$(CONFIG_COMMON_CLK_A1_PLL) += a1-pll.o +obj-$(CONFIG_COMMON_CLK_A1_PERIPHERALS) += a1-peripherals.o obj-$(CONFIG_COMMON_CLK_GXBB) += gxbb.o gxbb-aoclk.o obj-$(CONFIG_COMMON_CLK_G12A) += g12a.o g12a-aoclk.o obj-$(CONFIG_COMMON_CLK_MESON8B) += meson8b.o meson8-ddr.o diff --git a/drivers/clk/meson/a1-peripherals.c b/drivers/clk/meson/a1-peripherals.c new file mode 100644 index 0000000000000000000000000000000000000000..75dfae210fe54c0037a80e79e93ce0969bb624ab --- /dev/null +++ b/drivers/clk/meson/a1-peripherals.c @@ -0,0 +1,2243 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2019 Amlogic, Inc. All rights reserved. + * Author: Jian Hu + * + * Copyright (c) 2023, SberDevices. All Rights Reserved. + * Author: Dmitry Rokosov + */ + +#include +#include +#include +#include "a1-peripherals.h" +#include "clk-dualdiv.h" +#include "clk-regmap.h" + +static struct clk_regmap xtal_in = { + .data = &(struct clk_regmap_gate_data){ + .offset = SYS_OSCIN_CTRL, + .bit_idx = 0, + }, + .hw.init = &(struct clk_init_data) { + .name = "xtal_in", + .ops = &clk_regmap_gate_ro_ops, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "xtal", + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap fixpll_in = { + .data = &(struct clk_regmap_gate_data){ + .offset = SYS_OSCIN_CTRL, + .bit_idx = 1, + }, + .hw.init = &(struct clk_init_data) { + .name = "fixpll_in", + .ops = &clk_regmap_gate_ro_ops, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "xtal", + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap usb_phy_in = { + .data = &(struct clk_regmap_gate_data){ + .offset = SYS_OSCIN_CTRL, + .bit_idx = 2, + }, + .hw.init = &(struct clk_init_data) { + .name = "usb_phy_in", + .ops = &clk_regmap_gate_ops, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "xtal", + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap usb_ctrl_in = { + .data = &(struct clk_regmap_gate_data){ + .offset = SYS_OSCIN_CTRL, + .bit_idx = 3, + }, + .hw.init = &(struct clk_init_data) { + .name = "usb_ctrl_in", + .ops = &clk_regmap_gate_ops, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "xtal", + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap hifipll_in = { + .data = &(struct clk_regmap_gate_data){ + .offset = SYS_OSCIN_CTRL, + .bit_idx = 4, + }, + .hw.init = &(struct clk_init_data) { + .name = "hifipll_in", + .ops = &clk_regmap_gate_ops, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "xtal", + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap syspll_in = { + .data = &(struct clk_regmap_gate_data){ + .offset = SYS_OSCIN_CTRL, + .bit_idx = 5, + }, + .hw.init = &(struct clk_init_data) { + .name = "syspll_in", + .ops = &clk_regmap_gate_ops, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "xtal", + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap dds_in = { + .data = &(struct clk_regmap_gate_data){ + .offset = SYS_OSCIN_CTRL, + .bit_idx = 6, + }, + .hw.init = &(struct clk_init_data) { + .name = "dds_in", + .ops = &clk_regmap_gate_ops, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "xtal", + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap rtc_32k_in = { + .data = &(struct clk_regmap_gate_data){ + .offset = RTC_BY_OSCIN_CTRL0, + .bit_idx = 31, + }, + .hw.init = &(struct clk_init_data) { + .name = "rtc_32k_in", + .ops = &clk_regmap_gate_ops, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "xtal", + }, + .num_parents = 1, + }, +}; + +static const struct meson_clk_dualdiv_param clk_32k_div_table[] = { + { + .dual = 1, + .n1 = 733, + .m1 = 8, + .n2 = 732, + .m2 = 11, + }, + {} +}; + +static struct clk_regmap rtc_32k_div = { + .data = &(struct meson_clk_dualdiv_data){ + .n1 = { + .reg_off = RTC_BY_OSCIN_CTRL0, + .shift = 0, + .width = 12, + }, + .n2 = { + .reg_off = RTC_BY_OSCIN_CTRL0, + .shift = 12, + .width = 12, + }, + .m1 = { + .reg_off = RTC_BY_OSCIN_CTRL1, + .shift = 0, + .width = 12, + }, + .m2 = { + .reg_off = RTC_BY_OSCIN_CTRL1, + .shift = 12, + .width = 12, + }, + .dual = { + .reg_off = RTC_BY_OSCIN_CTRL0, + .shift = 28, + .width = 1, + }, + .table = clk_32k_div_table, + }, + .hw.init = &(struct clk_init_data){ + .name = "rtc_32k_div", + .ops = &meson_clk_dualdiv_ops, + .parent_hws = (const struct clk_hw *[]) { + &rtc_32k_in.hw + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap rtc_32k_xtal = { + .data = &(struct clk_regmap_gate_data){ + .offset = RTC_BY_OSCIN_CTRL1, + .bit_idx = 24, + }, + .hw.init = &(struct clk_init_data) { + .name = "rtc_32k_xtal", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &rtc_32k_in.hw + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap rtc_32k_sel = { + .data = &(struct clk_regmap_mux_data) { + .offset = RTC_CTRL, + .mask = 0x3, + .shift = 0, + .flags = CLK_MUX_ROUND_CLOSEST, + }, + .hw.init = &(struct clk_init_data){ + .name = "rtc_32k_sel", + .ops = &clk_regmap_mux_ops, + .parent_hws = (const struct clk_hw *[]) { + &rtc_32k_xtal.hw, + &rtc_32k_div.hw, + }, + .num_parents = 2, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap rtc = { + .data = &(struct clk_regmap_gate_data){ + .offset = RTC_BY_OSCIN_CTRL0, + .bit_idx = 30, + }, + .hw.init = &(struct clk_init_data){ + .name = "rtc", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &rtc_32k_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static u32 mux_table_sys[] = { 0, 1, 2, 3, 7 }; +static const struct clk_parent_data sys_parents[] = { + { .fw_name = "xtal" }, + { .fw_name = "fclk_div2" }, + { .fw_name = "fclk_div3" }, + { .fw_name = "fclk_div5" }, + { .hw = &rtc.hw }, +}; + +static struct clk_regmap sys_b_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = SYS_CLK_CTRL0, + .mask = 0x7, + .shift = 26, + .table = mux_table_sys, + }, + .hw.init = &(struct clk_init_data){ + .name = "sys_b_sel", + .ops = &clk_regmap_mux_ro_ops, + .parent_data = sys_parents, + .num_parents = ARRAY_SIZE(sys_parents), + }, +}; + +static struct clk_regmap sys_b_div = { + .data = &(struct clk_regmap_div_data){ + .offset = SYS_CLK_CTRL0, + .shift = 16, + .width = 10, + }, + .hw.init = &(struct clk_init_data){ + .name = "sys_b_div", + .ops = &clk_regmap_divider_ro_ops, + .parent_hws = (const struct clk_hw *[]) { + &sys_b_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap sys_b = { + .data = &(struct clk_regmap_gate_data){ + .offset = SYS_CLK_CTRL0, + .bit_idx = 29, + }, + .hw.init = &(struct clk_init_data) { + .name = "sys_b", + .ops = &clk_regmap_gate_ro_ops, + .parent_hws = (const struct clk_hw *[]) { + &sys_b_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap sys_a_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = SYS_CLK_CTRL0, + .mask = 0x7, + .shift = 10, + .table = mux_table_sys, + }, + .hw.init = &(struct clk_init_data){ + .name = "sys_a_sel", + .ops = &clk_regmap_mux_ro_ops, + .parent_data = sys_parents, + .num_parents = ARRAY_SIZE(sys_parents), + }, +}; + +static struct clk_regmap sys_a_div = { + .data = &(struct clk_regmap_div_data){ + .offset = SYS_CLK_CTRL0, + .shift = 0, + .width = 10, + }, + .hw.init = &(struct clk_init_data){ + .name = "sys_a_div", + .ops = &clk_regmap_divider_ro_ops, + .parent_hws = (const struct clk_hw *[]) { + &sys_a_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap sys_a = { + .data = &(struct clk_regmap_gate_data){ + .offset = SYS_CLK_CTRL0, + .bit_idx = 13, + }, + .hw.init = &(struct clk_init_data) { + .name = "sys_a", + .ops = &clk_regmap_gate_ro_ops, + .parent_hws = (const struct clk_hw *[]) { + &sys_a_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap sys = { + .data = &(struct clk_regmap_mux_data){ + .offset = SYS_CLK_CTRL0, + .mask = 0x1, + .shift = 31, + }, + .hw.init = &(struct clk_init_data){ + .name = "sys", + .ops = &clk_regmap_mux_ro_ops, + .parent_hws = (const struct clk_hw *[]) { + &sys_a.hw, + &sys_b.hw, + }, + .num_parents = 2, + /* + * This clock is used by APB bus which is set in boot ROM code + * and is required by the platform to operate correctly. + * Until the following condition are met, we need this clock to + * be marked as critical: + * a) Mark the clock used by a firmware resource, if possible + * b) CCF has a clock hand-off mechanism to make the sure the + * clock stays on until the proper driver comes along + */ + .flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, + }, +}; + +static u32 mux_table_dsp_ab[] = { 0, 1, 2, 3, 4, 7 }; +static const struct clk_parent_data dsp_ab_parent_data[] = { + { .fw_name = "xtal", }, + { .fw_name = "fclk_div2", }, + { .fw_name = "fclk_div3", }, + { .fw_name = "fclk_div5", }, + { .fw_name = "hifi_pll", }, + { .hw = &rtc.hw }, +}; + +static struct clk_regmap dspa_a_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = DSPA_CLK_CTRL0, + .mask = 0x7, + .shift = 10, + .table = mux_table_dsp_ab, + }, + .hw.init = &(struct clk_init_data){ + .name = "dspa_a_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = dsp_ab_parent_data, + .num_parents = ARRAY_SIZE(dsp_ab_parent_data), + }, +}; + +static struct clk_regmap dspa_a_div = { + .data = &(struct clk_regmap_div_data){ + .offset = DSPA_CLK_CTRL0, + .shift = 0, + .width = 10, + }, + .hw.init = &(struct clk_init_data){ + .name = "dspa_a_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &dspa_a_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap dspa_a = { + .data = &(struct clk_regmap_gate_data){ + .offset = DSPA_CLK_CTRL0, + .bit_idx = 13, + }, + .hw.init = &(struct clk_init_data) { + .name = "dspa_a", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &dspa_a_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap dspa_b_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = DSPA_CLK_CTRL0, + .mask = 0x7, + .shift = 26, + .table = mux_table_dsp_ab, + }, + .hw.init = &(struct clk_init_data){ + .name = "dspa_b_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = dsp_ab_parent_data, + .num_parents = ARRAY_SIZE(dsp_ab_parent_data), + }, +}; + +static struct clk_regmap dspa_b_div = { + .data = &(struct clk_regmap_div_data){ + .offset = DSPA_CLK_CTRL0, + .shift = 16, + .width = 10, + }, + .hw.init = &(struct clk_init_data){ + .name = "dspa_b_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &dspa_b_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap dspa_b = { + .data = &(struct clk_regmap_gate_data){ + .offset = DSPA_CLK_CTRL0, + .bit_idx = 29, + }, + .hw.init = &(struct clk_init_data) { + .name = "dspa_b", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &dspa_b_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap dspa_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = DSPA_CLK_CTRL0, + .mask = 0x1, + .shift = 15, + }, + .hw.init = &(struct clk_init_data){ + .name = "dspa_sel", + .ops = &clk_regmap_mux_ops, + .parent_hws = (const struct clk_hw *[]) { + &dspa_a.hw, + &dspa_b.hw, + }, + .num_parents = 2, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap dspa_en = { + .data = &(struct clk_regmap_gate_data){ + .offset = DSPA_CLK_EN, + .bit_idx = 1, + }, + .hw.init = &(struct clk_init_data) { + .name = "dspa_en", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &dspa_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap dspa_en_nic = { + .data = &(struct clk_regmap_gate_data){ + .offset = DSPA_CLK_EN, + .bit_idx = 0, + }, + .hw.init = &(struct clk_init_data) { + .name = "dspa_en_nic", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &dspa_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap dspb_a_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = DSPB_CLK_CTRL0, + .mask = 0x7, + .shift = 10, + .table = mux_table_dsp_ab, + }, + .hw.init = &(struct clk_init_data){ + .name = "dspb_a_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = dsp_ab_parent_data, + .num_parents = ARRAY_SIZE(dsp_ab_parent_data), + }, +}; + +static struct clk_regmap dspb_a_div = { + .data = &(struct clk_regmap_div_data){ + .offset = DSPB_CLK_CTRL0, + .shift = 0, + .width = 10, + }, + .hw.init = &(struct clk_init_data){ + .name = "dspb_a_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &dspb_a_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap dspb_a = { + .data = &(struct clk_regmap_gate_data){ + .offset = DSPB_CLK_CTRL0, + .bit_idx = 13, + }, + .hw.init = &(struct clk_init_data) { + .name = "dspb_a", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &dspb_a_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap dspb_b_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = DSPB_CLK_CTRL0, + .mask = 0x7, + .shift = 26, + .table = mux_table_dsp_ab, + }, + .hw.init = &(struct clk_init_data){ + .name = "dspb_b_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = dsp_ab_parent_data, + .num_parents = ARRAY_SIZE(dsp_ab_parent_data), + }, +}; + +static struct clk_regmap dspb_b_div = { + .data = &(struct clk_regmap_div_data){ + .offset = DSPB_CLK_CTRL0, + .shift = 16, + .width = 10, + }, + .hw.init = &(struct clk_init_data){ + .name = "dspb_b_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &dspb_b_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap dspb_b = { + .data = &(struct clk_regmap_gate_data){ + .offset = DSPB_CLK_CTRL0, + .bit_idx = 29, + }, + .hw.init = &(struct clk_init_data) { + .name = "dspb_b", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &dspb_b_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap dspb_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = DSPB_CLK_CTRL0, + .mask = 0x1, + .shift = 15, + }, + .hw.init = &(struct clk_init_data){ + .name = "dspb_sel", + .ops = &clk_regmap_mux_ops, + .parent_hws = (const struct clk_hw *[]) { + &dspb_a.hw, + &dspb_b.hw, + }, + .num_parents = 2, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap dspb_en = { + .data = &(struct clk_regmap_gate_data){ + .offset = DSPB_CLK_EN, + .bit_idx = 1, + }, + .hw.init = &(struct clk_init_data) { + .name = "dspb_en", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &dspb_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap dspb_en_nic = { + .data = &(struct clk_regmap_gate_data){ + .offset = DSPB_CLK_EN, + .bit_idx = 0, + }, + .hw.init = &(struct clk_init_data) { + .name = "dspb_en_nic", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &dspb_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap clk_24m = { + .data = &(struct clk_regmap_gate_data){ + .offset = CLK12_24_CTRL, + .bit_idx = 11, + }, + .hw.init = &(struct clk_init_data) { + .name = "24m", + .ops = &clk_regmap_gate_ops, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "xtal", + }, + .num_parents = 1, + }, +}; + +static struct clk_fixed_factor clk_24m_div2 = { + .mult = 1, + .div = 2, + .hw.init = &(struct clk_init_data){ + .name = "24m_div2", + .ops = &clk_fixed_factor_ops, + .parent_hws = (const struct clk_hw *[]) { + &clk_24m.hw + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap clk_12m = { + .data = &(struct clk_regmap_gate_data){ + .offset = CLK12_24_CTRL, + .bit_idx = 10, + }, + .hw.init = &(struct clk_init_data) { + .name = "12m", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &clk_24m_div2.hw + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap fclk_div2_divn_pre = { + .data = &(struct clk_regmap_div_data){ + .offset = CLK12_24_CTRL, + .shift = 0, + .width = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "fclk_div2_divn_pre", + .ops = &clk_regmap_divider_ops, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "fclk_div2", + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap fclk_div2_divn = { + .data = &(struct clk_regmap_gate_data){ + .offset = CLK12_24_CTRL, + .bit_idx = 12, + }, + .hw.init = &(struct clk_init_data){ + .name = "fclk_div2_divn", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &fclk_div2_divn_pre.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +/* + * the index 2 is sys_pll_div16, it will be implemented in the CPU clock driver, + * the index 4 is the clock measurement source, it's not supported yet + */ +static u32 gen_table[] = { 0, 1, 3, 5, 6, 7, 8 }; +static const struct clk_parent_data gen_parent_data[] = { + { .fw_name = "xtal", }, + { .hw = &rtc.hw }, + { .fw_name = "hifi_pll", }, + { .fw_name = "fclk_div2", }, + { .fw_name = "fclk_div3", }, + { .fw_name = "fclk_div5", }, + { .fw_name = "fclk_div7", }, +}; + +static struct clk_regmap gen_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = GEN_CLK_CTRL, + .mask = 0xf, + .shift = 12, + .table = gen_table, + }, + .hw.init = &(struct clk_init_data){ + .name = "gen_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = gen_parent_data, + .num_parents = ARRAY_SIZE(gen_parent_data), + /* + * The GEN clock can be connected to an external pad, so it + * may be set up directly from the device tree. Additionally, + * the GEN clock can be inherited from a more accurate RTC + * clock, so in certain situations, it may be necessary + * to freeze its parent. + */ + .flags = CLK_SET_RATE_NO_REPARENT, + }, +}; + +static struct clk_regmap gen_div = { + .data = &(struct clk_regmap_div_data){ + .offset = GEN_CLK_CTRL, + .shift = 0, + .width = 11, + }, + .hw.init = &(struct clk_init_data){ + .name = "gen_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &gen_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap gen = { + .data = &(struct clk_regmap_gate_data){ + .offset = GEN_CLK_CTRL, + .bit_idx = 11, + }, + .hw.init = &(struct clk_init_data) { + .name = "gen", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &gen_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap saradc_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = SAR_ADC_CLK_CTRL, + .mask = 0x1, + .shift = 9, + }, + .hw.init = &(struct clk_init_data){ + .name = "saradc_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = (const struct clk_parent_data []) { + { .fw_name = "xtal", }, + { .hw = &sys.hw, }, + }, + .num_parents = 2, + }, +}; + +static struct clk_regmap saradc_div = { + .data = &(struct clk_regmap_div_data){ + .offset = SAR_ADC_CLK_CTRL, + .shift = 0, + .width = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "saradc_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &saradc_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap saradc = { + .data = &(struct clk_regmap_gate_data){ + .offset = SAR_ADC_CLK_CTRL, + .bit_idx = 8, + }, + .hw.init = &(struct clk_init_data) { + .name = "saradc", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &saradc_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static const struct clk_parent_data pwm_abcd_parents[] = { + { .fw_name = "xtal", }, + { .hw = &sys.hw }, + { .hw = &rtc.hw }, +}; + +static struct clk_regmap pwm_a_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = PWM_CLK_AB_CTRL, + .mask = 0x1, + .shift = 9, + }, + .hw.init = &(struct clk_init_data){ + .name = "pwm_a_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = pwm_abcd_parents, + .num_parents = ARRAY_SIZE(pwm_abcd_parents), + }, +}; + +static struct clk_regmap pwm_a_div = { + .data = &(struct clk_regmap_div_data){ + .offset = PWM_CLK_AB_CTRL, + .shift = 0, + .width = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "pwm_a_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &pwm_a_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap pwm_a = { + .data = &(struct clk_regmap_gate_data){ + .offset = PWM_CLK_AB_CTRL, + .bit_idx = 8, + }, + .hw.init = &(struct clk_init_data) { + .name = "pwm_a", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &pwm_a_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap pwm_b_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = PWM_CLK_AB_CTRL, + .mask = 0x1, + .shift = 25, + }, + .hw.init = &(struct clk_init_data){ + .name = "pwm_b_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = pwm_abcd_parents, + .num_parents = ARRAY_SIZE(pwm_abcd_parents), + }, +}; + +static struct clk_regmap pwm_b_div = { + .data = &(struct clk_regmap_div_data){ + .offset = PWM_CLK_AB_CTRL, + .shift = 16, + .width = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "pwm_b_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &pwm_b_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap pwm_b = { + .data = &(struct clk_regmap_gate_data){ + .offset = PWM_CLK_AB_CTRL, + .bit_idx = 24, + }, + .hw.init = &(struct clk_init_data) { + .name = "pwm_b", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &pwm_b_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap pwm_c_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = PWM_CLK_CD_CTRL, + .mask = 0x1, + .shift = 9, + }, + .hw.init = &(struct clk_init_data){ + .name = "pwm_c_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = pwm_abcd_parents, + .num_parents = ARRAY_SIZE(pwm_abcd_parents), + }, +}; + +static struct clk_regmap pwm_c_div = { + .data = &(struct clk_regmap_div_data){ + .offset = PWM_CLK_CD_CTRL, + .shift = 0, + .width = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "pwm_c_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &pwm_c_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap pwm_c = { + .data = &(struct clk_regmap_gate_data){ + .offset = PWM_CLK_CD_CTRL, + .bit_idx = 8, + }, + .hw.init = &(struct clk_init_data) { + .name = "pwm_c", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &pwm_c_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap pwm_d_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = PWM_CLK_CD_CTRL, + .mask = 0x1, + .shift = 25, + }, + .hw.init = &(struct clk_init_data){ + .name = "pwm_d_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = pwm_abcd_parents, + .num_parents = ARRAY_SIZE(pwm_abcd_parents), + }, +}; + +static struct clk_regmap pwm_d_div = { + .data = &(struct clk_regmap_div_data){ + .offset = PWM_CLK_CD_CTRL, + .shift = 16, + .width = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "pwm_d_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &pwm_d_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap pwm_d = { + .data = &(struct clk_regmap_gate_data){ + .offset = PWM_CLK_CD_CTRL, + .bit_idx = 24, + }, + .hw.init = &(struct clk_init_data) { + .name = "pwm_d", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &pwm_d_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static const struct clk_parent_data pwm_ef_parents[] = { + { .fw_name = "xtal", }, + { .hw = &sys.hw }, + { .fw_name = "fclk_div5", }, + { .hw = &rtc.hw }, +}; + +static struct clk_regmap pwm_e_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = PWM_CLK_EF_CTRL, + .mask = 0x3, + .shift = 9, + }, + .hw.init = &(struct clk_init_data){ + .name = "pwm_e_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = pwm_ef_parents, + .num_parents = ARRAY_SIZE(pwm_ef_parents), + }, +}; + +static struct clk_regmap pwm_e_div = { + .data = &(struct clk_regmap_div_data){ + .offset = PWM_CLK_EF_CTRL, + .shift = 0, + .width = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "pwm_e_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &pwm_e_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap pwm_e = { + .data = &(struct clk_regmap_gate_data){ + .offset = PWM_CLK_EF_CTRL, + .bit_idx = 8, + }, + .hw.init = &(struct clk_init_data) { + .name = "pwm_e", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &pwm_e_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap pwm_f_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = PWM_CLK_EF_CTRL, + .mask = 0x3, + .shift = 25, + }, + .hw.init = &(struct clk_init_data){ + .name = "pwm_f_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = pwm_ef_parents, + .num_parents = ARRAY_SIZE(pwm_ef_parents), + }, +}; + +static struct clk_regmap pwm_f_div = { + .data = &(struct clk_regmap_div_data){ + .offset = PWM_CLK_EF_CTRL, + .shift = 16, + .width = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "pwm_f_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &pwm_f_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap pwm_f = { + .data = &(struct clk_regmap_gate_data){ + .offset = PWM_CLK_EF_CTRL, + .bit_idx = 24, + }, + .hw.init = &(struct clk_init_data) { + .name = "pwm_f", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &pwm_f_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +/* + * spicc clk + * fdiv2 |\ |\ _____ + * ---------| |---DIV--| | | | spicc out + * ---------| | | |-----|GATE |--------- + * ..... |/ | / |_____| + * --------------------|/ + * 24M + */ +static const struct clk_parent_data spicc_spifc_parents[] = { + { .fw_name = "fclk_div2"}, + { .fw_name = "fclk_div3"}, + { .fw_name = "fclk_div5"}, + { .fw_name = "hifi_pll" }, +}; + +static struct clk_regmap spicc_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = SPICC_CLK_CTRL, + .mask = 0x3, + .shift = 9, + }, + .hw.init = &(struct clk_init_data){ + .name = "spicc_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = spicc_spifc_parents, + .num_parents = ARRAY_SIZE(spicc_spifc_parents), + }, +}; + +static struct clk_regmap spicc_div = { + .data = &(struct clk_regmap_div_data){ + .offset = SPICC_CLK_CTRL, + .shift = 0, + .width = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "spicc_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &spicc_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap spicc_sel2 = { + .data = &(struct clk_regmap_mux_data){ + .offset = SPICC_CLK_CTRL, + .mask = 0x1, + .shift = 15, + }, + .hw.init = &(struct clk_init_data){ + .name = "spicc_sel2", + .ops = &clk_regmap_mux_ops, + .parent_data = (const struct clk_parent_data []) { + { .hw = &spicc_div.hw }, + { .fw_name = "xtal", }, + }, + .num_parents = 2, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap spicc = { + .data = &(struct clk_regmap_gate_data){ + .offset = SPICC_CLK_CTRL, + .bit_idx = 8, + }, + .hw.init = &(struct clk_init_data) { + .name = "spicc", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &spicc_sel2.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap ts_div = { + .data = &(struct clk_regmap_div_data){ + .offset = TS_CLK_CTRL, + .shift = 0, + .width = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "ts_div", + .ops = &clk_regmap_divider_ops, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "xtal", + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap ts = { + .data = &(struct clk_regmap_gate_data){ + .offset = TS_CLK_CTRL, + .bit_idx = 8, + }, + .hw.init = &(struct clk_init_data) { + .name = "ts", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &ts_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap spifc_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = SPIFC_CLK_CTRL, + .mask = 0x3, + .shift = 9, + }, + .hw.init = &(struct clk_init_data){ + .name = "spifc_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = spicc_spifc_parents, + .num_parents = ARRAY_SIZE(spicc_spifc_parents), + }, +}; + +static struct clk_regmap spifc_div = { + .data = &(struct clk_regmap_div_data){ + .offset = SPIFC_CLK_CTRL, + .shift = 0, + .width = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "spifc_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &spifc_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap spifc_sel2 = { + .data = &(struct clk_regmap_mux_data){ + .offset = SPIFC_CLK_CTRL, + .mask = 0x1, + .shift = 15, + }, + .hw.init = &(struct clk_init_data){ + .name = "spifc_sel2", + .ops = &clk_regmap_mux_ops, + .parent_data = (const struct clk_parent_data []) { + { .hw = &spifc_div.hw }, + { .fw_name = "xtal", }, + }, + .num_parents = 2, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap spifc = { + .data = &(struct clk_regmap_gate_data){ + .offset = SPIFC_CLK_CTRL, + .bit_idx = 8, + }, + .hw.init = &(struct clk_init_data) { + .name = "spifc", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &spifc_sel2.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static const struct clk_parent_data usb_bus_parents[] = { + { .fw_name = "xtal", }, + { .hw = &sys.hw }, + { .fw_name = "fclk_div3", }, + { .fw_name = "fclk_div5", }, +}; + +static struct clk_regmap usb_bus_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = USB_BUSCLK_CTRL, + .mask = 0x3, + .shift = 9, + }, + .hw.init = &(struct clk_init_data){ + .name = "usb_bus_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = usb_bus_parents, + .num_parents = ARRAY_SIZE(usb_bus_parents), + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap usb_bus_div = { + .data = &(struct clk_regmap_div_data){ + .offset = USB_BUSCLK_CTRL, + .shift = 0, + .width = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "usb_bus_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &usb_bus_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap usb_bus = { + .data = &(struct clk_regmap_gate_data){ + .offset = USB_BUSCLK_CTRL, + .bit_idx = 8, + }, + .hw.init = &(struct clk_init_data) { + .name = "usb_bus", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &usb_bus_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static const struct clk_parent_data sd_emmc_psram_dmc_parents[] = { + { .fw_name = "fclk_div2", }, + { .fw_name = "fclk_div3", }, + { .fw_name = "fclk_div5", }, + { .fw_name = "hifi_pll", }, +}; + +static struct clk_regmap sd_emmc_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = SD_EMMC_CLK_CTRL, + .mask = 0x3, + .shift = 9, + }, + .hw.init = &(struct clk_init_data){ + .name = "sd_emmc_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = sd_emmc_psram_dmc_parents, + .num_parents = ARRAY_SIZE(sd_emmc_psram_dmc_parents), + }, +}; + +static struct clk_regmap sd_emmc_div = { + .data = &(struct clk_regmap_div_data){ + .offset = SD_EMMC_CLK_CTRL, + .shift = 0, + .width = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "sd_emmc_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &sd_emmc_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap sd_emmc_sel2 = { + .data = &(struct clk_regmap_mux_data){ + .offset = SD_EMMC_CLK_CTRL, + .mask = 0x1, + .shift = 15, + }, + .hw.init = &(struct clk_init_data){ + .name = "sd_emmc_sel2", + .ops = &clk_regmap_mux_ops, + .parent_data = (const struct clk_parent_data []) { + { .hw = &sd_emmc_div.hw }, + { .fw_name = "xtal", }, + }, + .num_parents = 2, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap sd_emmc = { + .data = &(struct clk_regmap_gate_data){ + .offset = SD_EMMC_CLK_CTRL, + .bit_idx = 8, + }, + .hw.init = &(struct clk_init_data) { + .name = "sd_emmc", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &sd_emmc_sel2.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap psram_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = PSRAM_CLK_CTRL, + .mask = 0x3, + .shift = 9, + }, + .hw.init = &(struct clk_init_data){ + .name = "psram_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = sd_emmc_psram_dmc_parents, + .num_parents = ARRAY_SIZE(sd_emmc_psram_dmc_parents), + }, +}; + +static struct clk_regmap psram_div = { + .data = &(struct clk_regmap_div_data){ + .offset = PSRAM_CLK_CTRL, + .shift = 0, + .width = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "psram_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &psram_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap psram_sel2 = { + .data = &(struct clk_regmap_mux_data){ + .offset = PSRAM_CLK_CTRL, + .mask = 0x1, + .shift = 15, + }, + .hw.init = &(struct clk_init_data){ + .name = "psram_sel2", + .ops = &clk_regmap_mux_ops, + .parent_data = (const struct clk_parent_data []) { + { .hw = &psram_div.hw }, + { .fw_name = "xtal", }, + }, + .num_parents = 2, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap psram = { + .data = &(struct clk_regmap_gate_data){ + .offset = PSRAM_CLK_CTRL, + .bit_idx = 8, + }, + .hw.init = &(struct clk_init_data) { + .name = "psram", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &psram_sel2.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap dmc_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = DMC_CLK_CTRL, + .mask = 0x3, + .shift = 9, + }, + .hw.init = &(struct clk_init_data){ + .name = "dmc_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = sd_emmc_psram_dmc_parents, + .num_parents = ARRAY_SIZE(sd_emmc_psram_dmc_parents), + }, +}; + +static struct clk_regmap dmc_div = { + .data = &(struct clk_regmap_div_data){ + .offset = DMC_CLK_CTRL, + .shift = 0, + .width = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "dmc_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &dmc_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap dmc_sel2 = { + .data = &(struct clk_regmap_mux_data){ + .offset = DMC_CLK_CTRL, + .mask = 0x1, + .shift = 15, + }, + .hw.init = &(struct clk_init_data){ + .name = "dmc_sel2", + .ops = &clk_regmap_mux_ops, + .parent_data = (const struct clk_parent_data []) { + { .hw = &dmc_div.hw }, + { .fw_name = "xtal", }, + }, + .num_parents = 2, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap dmc = { + .data = &(struct clk_regmap_gate_data){ + .offset = DMC_CLK_CTRL, + .bit_idx = 8, + }, + .hw.init = &(struct clk_init_data) { + .name = "dmc", + .ops = &clk_regmap_gate_ro_ops, + .parent_hws = (const struct clk_hw *[]) { + &dmc_sel2.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap ceca_32k_in = { + .data = &(struct clk_regmap_gate_data){ + .offset = CECA_CLK_CTRL0, + .bit_idx = 31, + }, + .hw.init = &(struct clk_init_data) { + .name = "ceca_32k_in", + .ops = &clk_regmap_gate_ops, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "xtal", + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap ceca_32k_div = { + .data = &(struct meson_clk_dualdiv_data){ + .n1 = { + .reg_off = CECA_CLK_CTRL0, + .shift = 0, + .width = 12, + }, + .n2 = { + .reg_off = CECA_CLK_CTRL0, + .shift = 12, + .width = 12, + }, + .m1 = { + .reg_off = CECA_CLK_CTRL1, + .shift = 0, + .width = 12, + }, + .m2 = { + .reg_off = CECA_CLK_CTRL1, + .shift = 12, + .width = 12, + }, + .dual = { + .reg_off = CECA_CLK_CTRL0, + .shift = 28, + .width = 1, + }, + .table = clk_32k_div_table, + }, + .hw.init = &(struct clk_init_data){ + .name = "ceca_32k_div", + .ops = &meson_clk_dualdiv_ops, + .parent_hws = (const struct clk_hw *[]) { + &ceca_32k_in.hw + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap ceca_32k_sel_pre = { + .data = &(struct clk_regmap_mux_data) { + .offset = CECA_CLK_CTRL1, + .mask = 0x1, + .shift = 24, + .flags = CLK_MUX_ROUND_CLOSEST, + }, + .hw.init = &(struct clk_init_data){ + .name = "ceca_32k_sel_pre", + .ops = &clk_regmap_mux_ops, + .parent_hws = (const struct clk_hw *[]) { + &ceca_32k_div.hw, + &ceca_32k_in.hw, + }, + .num_parents = 2, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap ceca_32k_sel = { + .data = &(struct clk_regmap_mux_data) { + .offset = CECA_CLK_CTRL1, + .mask = 0x1, + .shift = 31, + .flags = CLK_MUX_ROUND_CLOSEST, + }, + .hw.init = &(struct clk_init_data){ + .name = "ceca_32k_sel", + .ops = &clk_regmap_mux_ops, + .parent_hws = (const struct clk_hw *[]) { + &ceca_32k_sel_pre.hw, + &rtc.hw, + }, + .num_parents = 2, + }, +}; + +static struct clk_regmap ceca_32k_out = { + .data = &(struct clk_regmap_gate_data){ + .offset = CECA_CLK_CTRL0, + .bit_idx = 30, + }, + .hw.init = &(struct clk_init_data){ + .name = "ceca_32k_out", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &ceca_32k_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap cecb_32k_in = { + .data = &(struct clk_regmap_gate_data){ + .offset = CECB_CLK_CTRL0, + .bit_idx = 31, + }, + .hw.init = &(struct clk_init_data) { + .name = "cecb_32k_in", + .ops = &clk_regmap_gate_ops, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "xtal", + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap cecb_32k_div = { + .data = &(struct meson_clk_dualdiv_data){ + .n1 = { + .reg_off = CECB_CLK_CTRL0, + .shift = 0, + .width = 12, + }, + .n2 = { + .reg_off = CECB_CLK_CTRL0, + .shift = 12, + .width = 12, + }, + .m1 = { + .reg_off = CECB_CLK_CTRL1, + .shift = 0, + .width = 12, + }, + .m2 = { + .reg_off = CECB_CLK_CTRL1, + .shift = 12, + .width = 12, + }, + .dual = { + .reg_off = CECB_CLK_CTRL0, + .shift = 28, + .width = 1, + }, + .table = clk_32k_div_table, + }, + .hw.init = &(struct clk_init_data){ + .name = "cecb_32k_div", + .ops = &meson_clk_dualdiv_ops, + .parent_hws = (const struct clk_hw *[]) { + &cecb_32k_in.hw + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap cecb_32k_sel_pre = { + .data = &(struct clk_regmap_mux_data) { + .offset = CECB_CLK_CTRL1, + .mask = 0x1, + .shift = 24, + .flags = CLK_MUX_ROUND_CLOSEST, + }, + .hw.init = &(struct clk_init_data){ + .name = "cecb_32k_sel_pre", + .ops = &clk_regmap_mux_ops, + .parent_hws = (const struct clk_hw *[]) { + &cecb_32k_div.hw, + &cecb_32k_in.hw, + }, + .num_parents = 2, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap cecb_32k_sel = { + .data = &(struct clk_regmap_mux_data) { + .offset = CECB_CLK_CTRL1, + .mask = 0x1, + .shift = 31, + .flags = CLK_MUX_ROUND_CLOSEST, + }, + .hw.init = &(struct clk_init_data){ + .name = "cecb_32k_sel", + .ops = &clk_regmap_mux_ops, + .parent_hws = (const struct clk_hw *[]) { + &cecb_32k_sel_pre.hw, + &rtc.hw, + }, + .num_parents = 2, + }, +}; + +static struct clk_regmap cecb_32k_out = { + .data = &(struct clk_regmap_gate_data){ + .offset = CECB_CLK_CTRL0, + .bit_idx = 30, + }, + .hw.init = &(struct clk_init_data){ + .name = "cecb_32k_out", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &cecb_32k_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +#define MESON_GATE(_name, _reg, _bit) \ + MESON_PCLK(_name, _reg, _bit, &sys.hw) + +static MESON_GATE(clktree, SYS_CLK_EN0, 0); +static MESON_GATE(reset_ctrl, SYS_CLK_EN0, 1); +static MESON_GATE(analog_ctrl, SYS_CLK_EN0, 2); +static MESON_GATE(pwr_ctrl, SYS_CLK_EN0, 3); +static MESON_GATE(pad_ctrl, SYS_CLK_EN0, 4); +static MESON_GATE(sys_ctrl, SYS_CLK_EN0, 5); +static MESON_GATE(temp_sensor, SYS_CLK_EN0, 6); +static MESON_GATE(am2axi_dev, SYS_CLK_EN0, 7); +static MESON_GATE(spicc_b, SYS_CLK_EN0, 8); +static MESON_GATE(spicc_a, SYS_CLK_EN0, 9); +static MESON_GATE(msr, SYS_CLK_EN0, 10); +static MESON_GATE(audio, SYS_CLK_EN0, 11); +static MESON_GATE(jtag_ctrl, SYS_CLK_EN0, 12); +static MESON_GATE(saradc_en, SYS_CLK_EN0, 13); +static MESON_GATE(pwm_ef, SYS_CLK_EN0, 14); +static MESON_GATE(pwm_cd, SYS_CLK_EN0, 15); +static MESON_GATE(pwm_ab, SYS_CLK_EN0, 16); +static MESON_GATE(cec, SYS_CLK_EN0, 17); +static MESON_GATE(i2c_s, SYS_CLK_EN0, 18); +static MESON_GATE(ir_ctrl, SYS_CLK_EN0, 19); +static MESON_GATE(i2c_m_d, SYS_CLK_EN0, 20); +static MESON_GATE(i2c_m_c, SYS_CLK_EN0, 21); +static MESON_GATE(i2c_m_b, SYS_CLK_EN0, 22); +static MESON_GATE(i2c_m_a, SYS_CLK_EN0, 23); +static MESON_GATE(acodec, SYS_CLK_EN0, 24); +static MESON_GATE(otp, SYS_CLK_EN0, 25); +static MESON_GATE(sd_emmc_a, SYS_CLK_EN0, 26); +static MESON_GATE(usb_phy, SYS_CLK_EN0, 27); +static MESON_GATE(usb_ctrl, SYS_CLK_EN0, 28); +static MESON_GATE(sys_dspb, SYS_CLK_EN0, 29); +static MESON_GATE(sys_dspa, SYS_CLK_EN0, 30); +static MESON_GATE(dma, SYS_CLK_EN0, 31); +static MESON_GATE(irq_ctrl, SYS_CLK_EN1, 0); +static MESON_GATE(nic, SYS_CLK_EN1, 1); +static MESON_GATE(gic, SYS_CLK_EN1, 2); +static MESON_GATE(uart_c, SYS_CLK_EN1, 3); +static MESON_GATE(uart_b, SYS_CLK_EN1, 4); +static MESON_GATE(uart_a, SYS_CLK_EN1, 5); +static MESON_GATE(sys_psram, SYS_CLK_EN1, 6); +static MESON_GATE(rsa, SYS_CLK_EN1, 8); +static MESON_GATE(coresight, SYS_CLK_EN1, 9); +static MESON_GATE(am2axi_vad, AXI_CLK_EN, 0); +static MESON_GATE(audio_vad, AXI_CLK_EN, 1); +static MESON_GATE(axi_dmc, AXI_CLK_EN, 3); +static MESON_GATE(axi_psram, AXI_CLK_EN, 4); +static MESON_GATE(ramb, AXI_CLK_EN, 5); +static MESON_GATE(rama, AXI_CLK_EN, 6); +static MESON_GATE(axi_spifc, AXI_CLK_EN, 7); +static MESON_GATE(axi_nic, AXI_CLK_EN, 8); +static MESON_GATE(axi_dma, AXI_CLK_EN, 9); +static MESON_GATE(cpu_ctrl, AXI_CLK_EN, 10); +static MESON_GATE(rom, AXI_CLK_EN, 11); +static MESON_GATE(prod_i2c, AXI_CLK_EN, 12); + +/* Array of all clocks registered by this provider */ +static struct clk_hw_onecell_data a1_periphs_clks = { + .hws = { + [CLKID_XTAL_IN] = &xtal_in.hw, + [CLKID_FIXPLL_IN] = &fixpll_in.hw, + [CLKID_USB_PHY_IN] = &usb_phy_in.hw, + [CLKID_USB_CTRL_IN] = &usb_ctrl_in.hw, + [CLKID_HIFIPLL_IN] = &hifipll_in.hw, + [CLKID_SYSPLL_IN] = &syspll_in.hw, + [CLKID_DDS_IN] = &dds_in.hw, + [CLKID_SYS] = &sys.hw, + [CLKID_CLKTREE] = &clktree.hw, + [CLKID_RESET_CTRL] = &reset_ctrl.hw, + [CLKID_ANALOG_CTRL] = &analog_ctrl.hw, + [CLKID_PWR_CTRL] = &pwr_ctrl.hw, + [CLKID_PAD_CTRL] = &pad_ctrl.hw, + [CLKID_SYS_CTRL] = &sys_ctrl.hw, + [CLKID_TEMP_SENSOR] = &temp_sensor.hw, + [CLKID_AM2AXI_DIV] = &am2axi_dev.hw, + [CLKID_SPICC_B] = &spicc_b.hw, + [CLKID_SPICC_A] = &spicc_a.hw, + [CLKID_MSR] = &msr.hw, + [CLKID_AUDIO] = &audio.hw, + [CLKID_JTAG_CTRL] = &jtag_ctrl.hw, + [CLKID_SARADC_EN] = &saradc_en.hw, + [CLKID_PWM_EF] = &pwm_ef.hw, + [CLKID_PWM_CD] = &pwm_cd.hw, + [CLKID_PWM_AB] = &pwm_ab.hw, + [CLKID_CEC] = &cec.hw, + [CLKID_I2C_S] = &i2c_s.hw, + [CLKID_IR_CTRL] = &ir_ctrl.hw, + [CLKID_I2C_M_D] = &i2c_m_d.hw, + [CLKID_I2C_M_C] = &i2c_m_c.hw, + [CLKID_I2C_M_B] = &i2c_m_b.hw, + [CLKID_I2C_M_A] = &i2c_m_a.hw, + [CLKID_ACODEC] = &acodec.hw, + [CLKID_OTP] = &otp.hw, + [CLKID_SD_EMMC_A] = &sd_emmc_a.hw, + [CLKID_USB_PHY] = &usb_phy.hw, + [CLKID_USB_CTRL] = &usb_ctrl.hw, + [CLKID_SYS_DSPB] = &sys_dspb.hw, + [CLKID_SYS_DSPA] = &sys_dspa.hw, + [CLKID_DMA] = &dma.hw, + [CLKID_IRQ_CTRL] = &irq_ctrl.hw, + [CLKID_NIC] = &nic.hw, + [CLKID_GIC] = &gic.hw, + [CLKID_UART_C] = &uart_c.hw, + [CLKID_UART_B] = &uart_b.hw, + [CLKID_UART_A] = &uart_a.hw, + [CLKID_SYS_PSRAM] = &sys_psram.hw, + [CLKID_RSA] = &rsa.hw, + [CLKID_CORESIGHT] = &coresight.hw, + [CLKID_AM2AXI_VAD] = &am2axi_vad.hw, + [CLKID_AUDIO_VAD] = &audio_vad.hw, + [CLKID_AXI_DMC] = &axi_dmc.hw, + [CLKID_AXI_PSRAM] = &axi_psram.hw, + [CLKID_RAMB] = &ramb.hw, + [CLKID_RAMA] = &rama.hw, + [CLKID_AXI_SPIFC] = &axi_spifc.hw, + [CLKID_AXI_NIC] = &axi_nic.hw, + [CLKID_AXI_DMA] = &axi_dma.hw, + [CLKID_CPU_CTRL] = &cpu_ctrl.hw, + [CLKID_ROM] = &rom.hw, + [CLKID_PROC_I2C] = &prod_i2c.hw, + [CLKID_DSPA_SEL] = &dspa_sel.hw, + [CLKID_DSPB_SEL] = &dspb_sel.hw, + [CLKID_DSPA_EN] = &dspa_en.hw, + [CLKID_DSPA_EN_NIC] = &dspa_en_nic.hw, + [CLKID_DSPB_EN] = &dspb_en.hw, + [CLKID_DSPB_EN_NIC] = &dspb_en_nic.hw, + [CLKID_RTC] = &rtc.hw, + [CLKID_CECA_32K] = &ceca_32k_out.hw, + [CLKID_CECB_32K] = &cecb_32k_out.hw, + [CLKID_24M] = &clk_24m.hw, + [CLKID_12M] = &clk_12m.hw, + [CLKID_FCLK_DIV2_DIVN] = &fclk_div2_divn.hw, + [CLKID_GEN] = &gen.hw, + [CLKID_SARADC_SEL] = &saradc_sel.hw, + [CLKID_SARADC] = &saradc.hw, + [CLKID_PWM_A] = &pwm_a.hw, + [CLKID_PWM_B] = &pwm_b.hw, + [CLKID_PWM_C] = &pwm_c.hw, + [CLKID_PWM_D] = &pwm_d.hw, + [CLKID_PWM_E] = &pwm_e.hw, + [CLKID_PWM_F] = &pwm_f.hw, + [CLKID_SPICC] = &spicc.hw, + [CLKID_TS] = &ts.hw, + [CLKID_SPIFC] = &spifc.hw, + [CLKID_USB_BUS] = &usb_bus.hw, + [CLKID_SD_EMMC] = &sd_emmc.hw, + [CLKID_PSRAM] = &psram.hw, + [CLKID_DMC] = &dmc.hw, + [CLKID_SYS_A_SEL] = &sys_a_sel.hw, + [CLKID_SYS_A_DIV] = &sys_a_div.hw, + [CLKID_SYS_A] = &sys_a.hw, + [CLKID_SYS_B_SEL] = &sys_b_sel.hw, + [CLKID_SYS_B_DIV] = &sys_b_div.hw, + [CLKID_SYS_B] = &sys_b.hw, + [CLKID_DSPA_A_SEL] = &dspa_a_sel.hw, + [CLKID_DSPA_A_DIV] = &dspa_a_div.hw, + [CLKID_DSPA_A] = &dspa_a.hw, + [CLKID_DSPA_B_SEL] = &dspa_b_sel.hw, + [CLKID_DSPA_B_DIV] = &dspa_b_div.hw, + [CLKID_DSPA_B] = &dspa_b.hw, + [CLKID_DSPB_A_SEL] = &dspb_a_sel.hw, + [CLKID_DSPB_A_DIV] = &dspb_a_div.hw, + [CLKID_DSPB_A] = &dspb_a.hw, + [CLKID_DSPB_B_SEL] = &dspb_b_sel.hw, + [CLKID_DSPB_B_DIV] = &dspb_b_div.hw, + [CLKID_DSPB_B] = &dspb_b.hw, + [CLKID_RTC_32K_IN] = &rtc_32k_in.hw, + [CLKID_RTC_32K_DIV] = &rtc_32k_div.hw, + [CLKID_RTC_32K_XTAL] = &rtc_32k_xtal.hw, + [CLKID_RTC_32K_SEL] = &rtc_32k_sel.hw, + [CLKID_CECB_32K_IN] = &cecb_32k_in.hw, + [CLKID_CECB_32K_DIV] = &cecb_32k_div.hw, + [CLKID_CECB_32K_SEL_PRE] = &cecb_32k_sel_pre.hw, + [CLKID_CECB_32K_SEL] = &cecb_32k_sel.hw, + [CLKID_CECA_32K_IN] = &ceca_32k_in.hw, + [CLKID_CECA_32K_DIV] = &ceca_32k_div.hw, + [CLKID_CECA_32K_SEL_PRE] = &ceca_32k_sel_pre.hw, + [CLKID_CECA_32K_SEL] = &ceca_32k_sel.hw, + [CLKID_DIV2_PRE] = &fclk_div2_divn_pre.hw, + [CLKID_24M_DIV2] = &clk_24m_div2.hw, + [CLKID_GEN_SEL] = &gen_sel.hw, + [CLKID_GEN_DIV] = &gen_div.hw, + [CLKID_SARADC_DIV] = &saradc_div.hw, + [CLKID_PWM_A_SEL] = &pwm_a_sel.hw, + [CLKID_PWM_A_DIV] = &pwm_a_div.hw, + [CLKID_PWM_B_SEL] = &pwm_b_sel.hw, + [CLKID_PWM_B_DIV] = &pwm_b_div.hw, + [CLKID_PWM_C_SEL] = &pwm_c_sel.hw, + [CLKID_PWM_C_DIV] = &pwm_c_div.hw, + [CLKID_PWM_D_SEL] = &pwm_d_sel.hw, + [CLKID_PWM_D_DIV] = &pwm_d_div.hw, + [CLKID_PWM_E_SEL] = &pwm_e_sel.hw, + [CLKID_PWM_E_DIV] = &pwm_e_div.hw, + [CLKID_PWM_F_SEL] = &pwm_f_sel.hw, + [CLKID_PWM_F_DIV] = &pwm_f_div.hw, + [CLKID_SPICC_SEL] = &spicc_sel.hw, + [CLKID_SPICC_DIV] = &spicc_div.hw, + [CLKID_SPICC_SEL2] = &spicc_sel2.hw, + [CLKID_TS_DIV] = &ts_div.hw, + [CLKID_SPIFC_SEL] = &spifc_sel.hw, + [CLKID_SPIFC_DIV] = &spifc_div.hw, + [CLKID_SPIFC_SEL2] = &spifc_sel2.hw, + [CLKID_USB_BUS_SEL] = &usb_bus_sel.hw, + [CLKID_USB_BUS_DIV] = &usb_bus_div.hw, + [CLKID_SD_EMMC_SEL] = &sd_emmc_sel.hw, + [CLKID_SD_EMMC_DIV] = &sd_emmc_div.hw, + [CLKID_SD_EMMC_SEL2] = &sd_emmc_sel2.hw, + [CLKID_PSRAM_SEL] = &psram_sel.hw, + [CLKID_PSRAM_DIV] = &psram_div.hw, + [CLKID_PSRAM_SEL2] = &psram_sel2.hw, + [CLKID_DMC_SEL] = &dmc_sel.hw, + [CLKID_DMC_DIV] = &dmc_div.hw, + [CLKID_DMC_SEL2] = &dmc_sel2.hw, + [NR_CLKS] = NULL, + }, + .num = NR_CLKS, +}; + +/* Convenience table to populate regmap in .probe */ +static struct clk_regmap *const a1_periphs_regmaps[] = { + &xtal_in, + &fixpll_in, + &usb_phy_in, + &usb_ctrl_in, + &hifipll_in, + &syspll_in, + &dds_in, + &sys, + &clktree, + &reset_ctrl, + &analog_ctrl, + &pwr_ctrl, + &pad_ctrl, + &sys_ctrl, + &temp_sensor, + &am2axi_dev, + &spicc_b, + &spicc_a, + &msr, + &audio, + &jtag_ctrl, + &saradc_en, + &pwm_ef, + &pwm_cd, + &pwm_ab, + &cec, + &i2c_s, + &ir_ctrl, + &i2c_m_d, + &i2c_m_c, + &i2c_m_b, + &i2c_m_a, + &acodec, + &otp, + &sd_emmc_a, + &usb_phy, + &usb_ctrl, + &sys_dspb, + &sys_dspa, + &dma, + &irq_ctrl, + &nic, + &gic, + &uart_c, + &uart_b, + &uart_a, + &sys_psram, + &rsa, + &coresight, + &am2axi_vad, + &audio_vad, + &axi_dmc, + &axi_psram, + &ramb, + &rama, + &axi_spifc, + &axi_nic, + &axi_dma, + &cpu_ctrl, + &rom, + &prod_i2c, + &dspa_sel, + &dspb_sel, + &dspa_en, + &dspa_en_nic, + &dspb_en, + &dspb_en_nic, + &rtc, + &ceca_32k_out, + &cecb_32k_out, + &clk_24m, + &clk_12m, + &fclk_div2_divn, + &gen, + &saradc_sel, + &saradc, + &pwm_a, + &pwm_b, + &pwm_c, + &pwm_d, + &pwm_e, + &pwm_f, + &spicc, + &ts, + &spifc, + &usb_bus, + &sd_emmc, + &psram, + &dmc, + &sys_a_sel, + &sys_a_div, + &sys_a, + &sys_b_sel, + &sys_b_div, + &sys_b, + &dspa_a_sel, + &dspa_a_div, + &dspa_a, + &dspa_b_sel, + &dspa_b_div, + &dspa_b, + &dspb_a_sel, + &dspb_a_div, + &dspb_a, + &dspb_b_sel, + &dspb_b_div, + &dspb_b, + &rtc_32k_in, + &rtc_32k_div, + &rtc_32k_xtal, + &rtc_32k_sel, + &cecb_32k_in, + &cecb_32k_div, + &cecb_32k_sel_pre, + &cecb_32k_sel, + &ceca_32k_in, + &ceca_32k_div, + &ceca_32k_sel_pre, + &ceca_32k_sel, + &fclk_div2_divn_pre, + &gen_sel, + &gen_div, + &saradc_div, + &pwm_a_sel, + &pwm_a_div, + &pwm_b_sel, + &pwm_b_div, + &pwm_c_sel, + &pwm_c_div, + &pwm_d_sel, + &pwm_d_div, + &pwm_e_sel, + &pwm_e_div, + &pwm_f_sel, + &pwm_f_div, + &spicc_sel, + &spicc_div, + &spicc_sel2, + &ts_div, + &spifc_sel, + &spifc_div, + &spifc_sel2, + &usb_bus_sel, + &usb_bus_div, + &sd_emmc_sel, + &sd_emmc_div, + &sd_emmc_sel2, + &psram_sel, + &psram_div, + &psram_sel2, + &dmc_sel, + &dmc_div, + &dmc_sel2, +}; + +static struct regmap_config a1_periphs_regmap_cfg = { + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, +}; + +static int meson_a1_periphs_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + void __iomem *base; + struct regmap *map; + int clkid, i, err; + + base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(base)) + return dev_err_probe(dev, PTR_ERR(base), + "can't ioremap resource\n"); + + map = devm_regmap_init_mmio(dev, base, &a1_periphs_regmap_cfg); + if (IS_ERR(map)) + return dev_err_probe(dev, PTR_ERR(map), + "can't init regmap mmio region\n"); + + /* Populate regmap for the regmap backed clocks */ + for (i = 0; i < ARRAY_SIZE(a1_periphs_regmaps); i++) + a1_periphs_regmaps[i]->map = map; + + for (clkid = 0; clkid < a1_periphs_clks.num; clkid++) { + err = devm_clk_hw_register(dev, a1_periphs_clks.hws[clkid]); + if (err) + return dev_err_probe(dev, err, + "clock[%d] registration failed\n", + clkid); + } + + return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, + &a1_periphs_clks); +} + +static const struct of_device_id a1_periphs_clkc_match_table[] = { + { .compatible = "amlogic,a1-peripherals-clkc", }, + {} +}; +MODULE_DEVICE_TABLE(of, a1_periphs_clkc_match_table); + +static struct platform_driver a1_periphs_clkc_driver = { + .probe = meson_a1_periphs_probe, + .driver = { + .name = "a1-peripherals-clkc", + .of_match_table = a1_periphs_clkc_match_table, + }, +}; + +module_platform_driver(a1_periphs_clkc_driver); +MODULE_AUTHOR("Jian Hu "); +MODULE_AUTHOR("Dmitry Rokosov "); +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/meson/a1-peripherals.h b/drivers/clk/meson/a1-peripherals.h new file mode 100644 index 0000000000000000000000000000000000000000..526fc9ba5c9f634001b932ac77b2936830dd5929 --- /dev/null +++ b/drivers/clk/meson/a1-peripherals.h @@ -0,0 +1,113 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Amlogic A1 Peripherals Clock Controller internals + * + * Copyright (c) 2019 Amlogic, Inc. All rights reserved. + * Author: Jian Hu + * + * Copyright (c) 2023, SberDevices. All Rights Reserved. + * Author: Dmitry Rokosov + */ + +#ifndef __A1_PERIPHERALS_H +#define __A1_PERIPHERALS_H + +/* peripherals clock controller register offset */ +#define SYS_OSCIN_CTRL 0x0 +#define RTC_BY_OSCIN_CTRL0 0x4 +#define RTC_BY_OSCIN_CTRL1 0x8 +#define RTC_CTRL 0xc +#define SYS_CLK_CTRL0 0x10 +#define SYS_CLK_EN0 0x1c +#define SYS_CLK_EN1 0x20 +#define AXI_CLK_EN 0x24 +#define DSPA_CLK_EN 0x28 +#define DSPB_CLK_EN 0x2c +#define DSPA_CLK_CTRL0 0x30 +#define DSPB_CLK_CTRL0 0x34 +#define CLK12_24_CTRL 0x38 +#define GEN_CLK_CTRL 0x3c +#define SAR_ADC_CLK_CTRL 0xc0 +#define PWM_CLK_AB_CTRL 0xc4 +#define PWM_CLK_CD_CTRL 0xc8 +#define PWM_CLK_EF_CTRL 0xcc +#define SPICC_CLK_CTRL 0xd0 +#define TS_CLK_CTRL 0xd4 +#define SPIFC_CLK_CTRL 0xd8 +#define USB_BUSCLK_CTRL 0xdc +#define SD_EMMC_CLK_CTRL 0xe0 +#define CECA_CLK_CTRL0 0xe4 +#define CECA_CLK_CTRL1 0xe8 +#define CECB_CLK_CTRL0 0xec +#define CECB_CLK_CTRL1 0xf0 +#define PSRAM_CLK_CTRL 0xf4 +#define DMC_CLK_CTRL 0xf8 + +/* include the CLKIDs that have been made part of the DT binding */ +#include + +/* + * CLKID index values for internal clocks + * + * These indices are entirely contrived and do not map onto the hardware. + * It has now been decided to expose everything by default in the DT header: + * include/dt-bindings/clock/a1-peripherals-clkc.h. + * Only the clocks ids we don't want to expose, such as the internal muxes and + * dividers of composite clocks, will remain defined here. + */ +#define CLKID_XTAL_IN 0 +#define CLKID_DSPA_SEL 61 +#define CLKID_DSPB_SEL 62 +#define CLKID_SARADC_SEL 74 +#define CLKID_SYS_A_SEL 89 +#define CLKID_SYS_A_DIV 90 +#define CLKID_SYS_A 91 +#define CLKID_SYS_B_SEL 92 +#define CLKID_SYS_B_DIV 93 +#define CLKID_SYS_B 94 +#define CLKID_DSPA_A_DIV 96 +#define CLKID_DSPA_A 97 +#define CLKID_DSPA_B_DIV 99 +#define CLKID_DSPA_B 100 +#define CLKID_DSPB_A_DIV 102 +#define CLKID_DSPB_A 103 +#define CLKID_DSPB_B_DIV 105 +#define CLKID_DSPB_B 106 +#define CLKID_RTC_32K_IN 107 +#define CLKID_RTC_32K_DIV 108 +#define CLKID_RTC_32K_XTAL 109 +#define CLKID_RTC_32K_SEL 110 +#define CLKID_CECB_32K_IN 111 +#define CLKID_CECB_32K_DIV 112 +#define CLKID_CECA_32K_IN 115 +#define CLKID_CECA_32K_DIV 116 +#define CLKID_DIV2_PRE 119 +#define CLKID_24M_DIV2 120 +#define CLKID_GEN_DIV 122 +#define CLKID_SARADC_DIV 123 +#define CLKID_PWM_A_DIV 125 +#define CLKID_PWM_B_DIV 127 +#define CLKID_PWM_C_DIV 129 +#define CLKID_PWM_D_DIV 131 +#define CLKID_PWM_E_DIV 133 +#define CLKID_PWM_F_DIV 135 +#define CLKID_SPICC_SEL 136 +#define CLKID_SPICC_DIV 137 +#define CLKID_SPICC_SEL2 138 +#define CLKID_TS_DIV 139 +#define CLKID_SPIFC_SEL 140 +#define CLKID_SPIFC_DIV 141 +#define CLKID_SPIFC_SEL2 142 +#define CLKID_USB_BUS_SEL 143 +#define CLKID_USB_BUS_DIV 144 +#define CLKID_SD_EMMC_SEL 145 +#define CLKID_SD_EMMC_DIV 146 +#define CLKID_PSRAM_SEL 148 +#define CLKID_PSRAM_DIV 149 +#define CLKID_PSRAM_SEL2 150 +#define CLKID_DMC_SEL 151 +#define CLKID_DMC_DIV 152 +#define CLKID_DMC_SEL2 153 +#define NR_CLKS 154 + +#endif /* __A1_PERIPHERALS_H */ diff --git a/drivers/clk/meson/a1-pll.c b/drivers/clk/meson/a1-pll.c new file mode 100644 index 0000000000000000000000000000000000000000..bd2f1d1ec6e4f2fd5fc56a3dcd301356af8bc279 --- /dev/null +++ b/drivers/clk/meson/a1-pll.c @@ -0,0 +1,356 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2019 Amlogic, Inc. All rights reserved. + * Author: Jian Hu + * + * Copyright (c) 2023, SberDevices. All Rights Reserved. + * Author: Dmitry Rokosov + */ + +#include +#include +#include +#include "a1-pll.h" +#include "clk-regmap.h" + +static struct clk_regmap fixed_pll_dco = { + .data = &(struct meson_clk_pll_data){ + .en = { + .reg_off = ANACTRL_FIXPLL_CTRL0, + .shift = 28, + .width = 1, + }, + .m = { + .reg_off = ANACTRL_FIXPLL_CTRL0, + .shift = 0, + .width = 8, + }, + .n = { + .reg_off = ANACTRL_FIXPLL_CTRL0, + .shift = 10, + .width = 5, + }, + .frac = { + .reg_off = ANACTRL_FIXPLL_CTRL1, + .shift = 0, + .width = 19, + }, + .l = { + .reg_off = ANACTRL_FIXPLL_STS, + .shift = 31, + .width = 1, + }, + .rst = { + .reg_off = ANACTRL_FIXPLL_CTRL0, + .shift = 29, + .width = 1, + }, + }, + .hw.init = &(struct clk_init_data){ + .name = "fixed_pll_dco", + .ops = &meson_clk_pll_ro_ops, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "fixpll_in", + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap fixed_pll = { + .data = &(struct clk_regmap_gate_data){ + .offset = ANACTRL_FIXPLL_CTRL0, + .bit_idx = 20, + }, + .hw.init = &(struct clk_init_data) { + .name = "fixed_pll", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &fixed_pll_dco.hw + }, + .num_parents = 1, + }, +}; + +static const struct pll_mult_range hifi_pll_mult_range = { + .min = 32, + .max = 64, +}; + +static const struct reg_sequence hifi_init_regs[] = { + { .reg = ANACTRL_HIFIPLL_CTRL1, .def = 0x01800000 }, + { .reg = ANACTRL_HIFIPLL_CTRL2, .def = 0x00001100 }, + { .reg = ANACTRL_HIFIPLL_CTRL3, .def = 0x100a1100 }, + { .reg = ANACTRL_HIFIPLL_CTRL4, .def = 0x00302000 }, + { .reg = ANACTRL_HIFIPLL_CTRL0, .def = 0x01f18000 }, +}; + +static struct clk_regmap hifi_pll = { + .data = &(struct meson_clk_pll_data){ + .en = { + .reg_off = ANACTRL_HIFIPLL_CTRL0, + .shift = 28, + .width = 1, + }, + .m = { + .reg_off = ANACTRL_HIFIPLL_CTRL0, + .shift = 0, + .width = 8, + }, + .n = { + .reg_off = ANACTRL_HIFIPLL_CTRL0, + .shift = 10, + .width = 5, + }, + .frac = { + .reg_off = ANACTRL_HIFIPLL_CTRL1, + .shift = 0, + .width = 19, + }, + .l = { + .reg_off = ANACTRL_HIFIPLL_STS, + .shift = 31, + .width = 1, + }, + .current_en = { + .reg_off = ANACTRL_HIFIPLL_CTRL0, + .shift = 26, + .width = 1, + }, + .l_detect = { + .reg_off = ANACTRL_HIFIPLL_CTRL2, + .shift = 6, + .width = 1, + }, + .range = &hifi_pll_mult_range, + .init_regs = hifi_init_regs, + .init_count = ARRAY_SIZE(hifi_init_regs), + }, + .hw.init = &(struct clk_init_data){ + .name = "hifi_pll", + .ops = &meson_clk_pll_ops, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "hifipll_in", + }, + .num_parents = 1, + }, +}; + +static struct clk_fixed_factor fclk_div2_div = { + .mult = 1, + .div = 2, + .hw.init = &(struct clk_init_data){ + .name = "fclk_div2_div", + .ops = &clk_fixed_factor_ops, + .parent_hws = (const struct clk_hw *[]) { + &fixed_pll.hw + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap fclk_div2 = { + .data = &(struct clk_regmap_gate_data){ + .offset = ANACTRL_FIXPLL_CTRL0, + .bit_idx = 21, + }, + .hw.init = &(struct clk_init_data){ + .name = "fclk_div2", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &fclk_div2_div.hw + }, + .num_parents = 1, + /* + * This clock is used by DDR clock in BL2 firmware + * and is required by the platform to operate correctly. + * Until the following condition are met, we need this clock to + * be marked as critical: + * a) Mark the clock used by a firmware resource, if possible + * b) CCF has a clock hand-off mechanism to make the sure the + * clock stays on until the proper driver comes along + */ + .flags = CLK_IS_CRITICAL, + }, +}; + +static struct clk_fixed_factor fclk_div3_div = { + .mult = 1, + .div = 3, + .hw.init = &(struct clk_init_data){ + .name = "fclk_div3_div", + .ops = &clk_fixed_factor_ops, + .parent_hws = (const struct clk_hw *[]) { + &fixed_pll.hw + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap fclk_div3 = { + .data = &(struct clk_regmap_gate_data){ + .offset = ANACTRL_FIXPLL_CTRL0, + .bit_idx = 22, + }, + .hw.init = &(struct clk_init_data){ + .name = "fclk_div3", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &fclk_div3_div.hw + }, + .num_parents = 1, + /* + * This clock is used by APB bus which is set in boot ROM code + * and is required by the platform to operate correctly. + */ + .flags = CLK_IS_CRITICAL, + }, +}; + +static struct clk_fixed_factor fclk_div5_div = { + .mult = 1, + .div = 5, + .hw.init = &(struct clk_init_data){ + .name = "fclk_div5_div", + .ops = &clk_fixed_factor_ops, + .parent_hws = (const struct clk_hw *[]) { + &fixed_pll.hw + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap fclk_div5 = { + .data = &(struct clk_regmap_gate_data){ + .offset = ANACTRL_FIXPLL_CTRL0, + .bit_idx = 23, + }, + .hw.init = &(struct clk_init_data){ + .name = "fclk_div5", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &fclk_div5_div.hw + }, + .num_parents = 1, + /* + * This clock is used by AXI bus which setted in Romcode + * and is required by the platform to operate correctly. + */ + .flags = CLK_IS_CRITICAL, + }, +}; + +static struct clk_fixed_factor fclk_div7_div = { + .mult = 1, + .div = 7, + .hw.init = &(struct clk_init_data){ + .name = "fclk_div7_div", + .ops = &clk_fixed_factor_ops, + .parent_hws = (const struct clk_hw *[]) { + &fixed_pll.hw + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap fclk_div7 = { + .data = &(struct clk_regmap_gate_data){ + .offset = ANACTRL_FIXPLL_CTRL0, + .bit_idx = 24, + }, + .hw.init = &(struct clk_init_data){ + .name = "fclk_div7", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &fclk_div7_div.hw + }, + .num_parents = 1, + }, +}; + +/* Array of all clocks registered by this provider */ +static struct clk_hw_onecell_data a1_pll_clks = { + .hws = { + [CLKID_FIXED_PLL_DCO] = &fixed_pll_dco.hw, + [CLKID_FIXED_PLL] = &fixed_pll.hw, + [CLKID_FCLK_DIV2_DIV] = &fclk_div2_div.hw, + [CLKID_FCLK_DIV3_DIV] = &fclk_div3_div.hw, + [CLKID_FCLK_DIV5_DIV] = &fclk_div5_div.hw, + [CLKID_FCLK_DIV7_DIV] = &fclk_div7_div.hw, + [CLKID_FCLK_DIV2] = &fclk_div2.hw, + [CLKID_FCLK_DIV3] = &fclk_div3.hw, + [CLKID_FCLK_DIV5] = &fclk_div5.hw, + [CLKID_FCLK_DIV7] = &fclk_div7.hw, + [CLKID_HIFI_PLL] = &hifi_pll.hw, + [NR_PLL_CLKS] = NULL, + }, + .num = NR_PLL_CLKS, +}; + +static struct clk_regmap *const a1_pll_regmaps[] = { + &fixed_pll_dco, + &fixed_pll, + &fclk_div2, + &fclk_div3, + &fclk_div5, + &fclk_div7, + &hifi_pll, +}; + +static struct regmap_config a1_pll_regmap_cfg = { + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, +}; + +static int meson_a1_pll_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + void __iomem *base; + struct regmap *map; + int clkid, i, err; + + base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(base)) + return dev_err_probe(dev, PTR_ERR(base), + "can't ioremap resource\n"); + + map = devm_regmap_init_mmio(dev, base, &a1_pll_regmap_cfg); + if (IS_ERR(map)) + return dev_err_probe(dev, PTR_ERR(map), + "can't init regmap mmio region\n"); + + /* Populate regmap for the regmap backed clocks */ + for (i = 0; i < ARRAY_SIZE(a1_pll_regmaps); i++) + a1_pll_regmaps[i]->map = map; + + /* Register clocks */ + for (clkid = 0; clkid < a1_pll_clks.num; clkid++) { + err = devm_clk_hw_register(dev, a1_pll_clks.hws[clkid]); + if (err) + return dev_err_probe(dev, err, + "clock[%d] registration failed\n", + clkid); + } + + return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, + &a1_pll_clks); +} + +static const struct of_device_id a1_pll_clkc_match_table[] = { + { .compatible = "amlogic,a1-pll-clkc", }, + {} +}; +MODULE_DEVICE_TABLE(of, a1_pll_clkc_match_table); + +static struct platform_driver a1_pll_clkc_driver = { + .probe = meson_a1_pll_probe, + .driver = { + .name = "a1-pll-clkc", + .of_match_table = a1_pll_clkc_match_table, + }, +}; + +module_platform_driver(a1_pll_clkc_driver); +MODULE_AUTHOR("Jian Hu "); +MODULE_AUTHOR("Dmitry Rokosov "); +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/meson/a1-pll.h b/drivers/clk/meson/a1-pll.h new file mode 100644 index 0000000000000000000000000000000000000000..29726651b0569073f49c6d770a23ffd7a8be6cab --- /dev/null +++ b/drivers/clk/meson/a1-pll.h @@ -0,0 +1,47 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Amlogic A1 PLL Clock Controller internals + * + * Copyright (c) 2019 Amlogic, Inc. All rights reserved. + * Author: Jian Hu + * + * Copyright (c) 2023, SberDevices. All Rights Reserved. + * Author: Dmitry Rokosov + */ + +#ifndef __A1_PLL_H +#define __A1_PLL_H + +#include "clk-pll.h" + +/* PLL register offset */ +#define ANACTRL_FIXPLL_CTRL0 0x0 +#define ANACTRL_FIXPLL_CTRL1 0x4 +#define ANACTRL_FIXPLL_STS 0x14 +#define ANACTRL_HIFIPLL_CTRL0 0xc0 +#define ANACTRL_HIFIPLL_CTRL1 0xc4 +#define ANACTRL_HIFIPLL_CTRL2 0xc8 +#define ANACTRL_HIFIPLL_CTRL3 0xcc +#define ANACTRL_HIFIPLL_CTRL4 0xd0 +#define ANACTRL_HIFIPLL_STS 0xd4 + +/* include the CLKIDs that have been made part of the DT binding */ +#include + +/* + * CLKID index values for internal clocks + * + * These indices are entirely contrived and do not map onto the hardware. + * It has now been decided to expose everything by default in the DT header: + * include/dt-bindings/clock/a1-pll-clkc.h. Only the clocks ids we don't want + * to expose, such as the internal muxes and dividers of composite clocks, + * will remain defined here. + */ +#define CLKID_FIXED_PLL_DCO 0 +#define CLKID_FCLK_DIV2_DIV 2 +#define CLKID_FCLK_DIV3_DIV 3 +#define CLKID_FCLK_DIV5_DIV 4 +#define CLKID_FCLK_DIV7_DIV 5 +#define NR_PLL_CLKS 11 + +#endif /* __A1_PLL_H */ diff --git a/drivers/clk/meson/clk-pll.c b/drivers/clk/meson/clk-pll.c index afefeba6e458bc78ac3bbd432ad8c750db327405..8fef90bf962ff727138009fe65edbd703aefbc49 100644 --- a/drivers/clk/meson/clk-pll.c +++ b/drivers/clk/meson/clk-pll.c @@ -295,10 +295,14 @@ static int meson_clk_pll_init(struct clk_hw *hw) struct meson_clk_pll_data *pll = meson_clk_pll_data(clk); if (pll->init_count) { - meson_parm_write(clk->map, &pll->rst, 1); + if (MESON_PARM_APPLICABLE(&pll->rst)) + meson_parm_write(clk->map, &pll->rst, 1); + regmap_multi_reg_write(clk->map, pll->init_regs, pll->init_count); - meson_parm_write(clk->map, &pll->rst, 0); + + if (MESON_PARM_APPLICABLE(&pll->rst)) + meson_parm_write(clk->map, &pll->rst, 0); } return 0; @@ -309,8 +313,11 @@ static int meson_clk_pll_is_enabled(struct clk_hw *hw) struct clk_regmap *clk = to_clk_regmap(hw); struct meson_clk_pll_data *pll = meson_clk_pll_data(clk); - if (meson_parm_read(clk->map, &pll->rst) || - !meson_parm_read(clk->map, &pll->en) || + if (MESON_PARM_APPLICABLE(&pll->rst) && + meson_parm_read(clk->map, &pll->rst)) + return 0; + + if (!meson_parm_read(clk->map, &pll->en) || !meson_parm_read(clk->map, &pll->l)) return 0; @@ -341,13 +348,34 @@ static int meson_clk_pll_enable(struct clk_hw *hw) return 0; /* Make sure the pll is in reset */ - meson_parm_write(clk->map, &pll->rst, 1); + if (MESON_PARM_APPLICABLE(&pll->rst)) + meson_parm_write(clk->map, &pll->rst, 1); /* Enable the pll */ meson_parm_write(clk->map, &pll->en, 1); /* Take the pll out reset */ - meson_parm_write(clk->map, &pll->rst, 0); + if (MESON_PARM_APPLICABLE(&pll->rst)) + meson_parm_write(clk->map, &pll->rst, 0); + + /* + * Compared with the previous SoCs, self-adaption current module + * is newly added for A1, keep the new power-on sequence to enable the + * PLL. The sequence is: + * 1. enable the pll, delay for 10us + * 2. enable the pll self-adaption current module, delay for 40us + * 3. enable the lock detect module + */ + if (MESON_PARM_APPLICABLE(&pll->current_en)) { + usleep_range(10, 20); + meson_parm_write(clk->map, &pll->current_en, 1); + usleep_range(40, 50); + } + + if (MESON_PARM_APPLICABLE(&pll->l_detect)) { + meson_parm_write(clk->map, &pll->l_detect, 1); + meson_parm_write(clk->map, &pll->l_detect, 0); + } if (meson_clk_pll_wait_lock(hw)) return -EIO; @@ -361,10 +389,15 @@ static void meson_clk_pll_disable(struct clk_hw *hw) struct meson_clk_pll_data *pll = meson_clk_pll_data(clk); /* Put the pll is in reset */ - meson_parm_write(clk->map, &pll->rst, 1); + if (MESON_PARM_APPLICABLE(&pll->rst)) + meson_parm_write(clk->map, &pll->rst, 1); /* Disable the pll */ meson_parm_write(clk->map, &pll->en, 0); + + /* Disable PLL internal self-adaption current module */ + if (MESON_PARM_APPLICABLE(&pll->current_en)) + meson_parm_write(clk->map, &pll->current_en, 0); } static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate, diff --git a/drivers/clk/meson/clk-pll.h b/drivers/clk/meson/clk-pll.h index 367efd0f6410cf68906a9decf59fb153c935ea4b..a2228c0fdce5bd6b4b5a168177fdb2af070a4d0a 100644 --- a/drivers/clk/meson/clk-pll.h +++ b/drivers/clk/meson/clk-pll.h @@ -36,6 +36,8 @@ struct meson_clk_pll_data { struct parm frac; struct parm l; struct parm rst; + struct parm current_en; + struct parm l_detect; const struct reg_sequence *init_regs; unsigned int init_count; const struct pll_params_table *table; diff --git a/drivers/clk/microchip/Kconfig b/drivers/clk/microchip/Kconfig index e33e51978938331bc73829cf6bd5a0285f25013f..0724ce65898f3cc31efd35e99d39fd9979639af8 100644 --- a/drivers/clk/microchip/Kconfig +++ b/drivers/clk/microchip/Kconfig @@ -5,8 +5,8 @@ config COMMON_CLK_PIC32 config MCHP_CLK_MPFS bool "Clk driver for PolarFire SoC" - depends on SOC_MICROCHIP_POLARFIRE || COMPILE_TEST - default SOC_MICROCHIP_POLARFIRE + depends on ARCH_MICROCHIP_POLARFIRE || COMPILE_TEST + default ARCH_MICROCHIP_POLARFIRE select AUXILIARY_BUS help Supports Clock Configuration for PolarFire SoC diff --git a/drivers/clk/microchip/clk-pic32mzda.c b/drivers/clk/microchip/clk-pic32mzda.c index b72c76f9ecd1a28393bced8d8ac7acf67769014b..eabfc4931fe904bbfe0626b839f087aa8fff5c0e 100644 --- a/drivers/clk/microchip/clk-pic32mzda.c +++ b/drivers/clk/microchip/clk-pic32mzda.c @@ -184,7 +184,7 @@ static int pic32mzda_clk_probe(struct platform_device *pdev) clks[UPLLCLK] = clk_register_fixed_rate(&pdev->dev, "usbphy_clk", NULL, 0, 24000000); /* fixed rate (optional) clock */ - if (of_find_property(np, "microchip,pic32mzda-sosc", NULL)) { + if (of_property_read_bool(np, "microchip,pic32mzda-sosc")) { pr_info("pic32-clk: dt requests SOSC.\n"); clks[SOSCCLK] = pic32_sosc_clk_register(&sosc_clk, core); } diff --git a/drivers/clk/mvebu/ap-cpu-clk.c b/drivers/clk/mvebu/ap-cpu-clk.c index 71bdd7c3ff0341cd37f4d66c3f434bc225c15f1b..d8a7a4c90d54158b18b0e2fcb50678eb255b0f9b 100644 --- a/drivers/clk/mvebu/ap-cpu-clk.c +++ b/drivers/clk/mvebu/ap-cpu-clk.c @@ -253,12 +253,12 @@ static int ap_cpu_clock_probe(struct platform_device *pdev) */ nclusters = 1; for_each_of_cpu_node(dn) { - int cpu, err; + u64 cpu; - err = of_property_read_u32(dn, "reg", &cpu); - if (WARN_ON(err)) { + cpu = of_get_cpu_hwid(dn, 0); + if (WARN_ON(cpu == OF_BAD_ADDR)) { of_node_put(dn); - return err; + return -EINVAL; } /* If cpu2 or cpu3 is enabled */ @@ -288,12 +288,12 @@ static int ap_cpu_clock_probe(struct platform_device *pdev) struct clk_init_data init; const char *parent_name; struct clk *parent; - int cpu, err; + u64 cpu; - err = of_property_read_u32(dn, "reg", &cpu); - if (WARN_ON(err)) { + cpu = of_get_cpu_hwid(dn, 0); + if (WARN_ON(cpu == OF_BAD_ADDR)) { of_node_put(dn); - return err; + return -EINVAL; } cluster_index = cpu & APN806_CLUSTER_NUM_MASK; diff --git a/drivers/clk/mvebu/armada_ap_cp_helper.c b/drivers/clk/mvebu/armada_ap_cp_helper.c index 6a930f697ee59840e8b06392f23a06debff0086e..e7005de66327c3e85c6e9658e8ecfb2444df6647 100644 --- a/drivers/clk/mvebu/armada_ap_cp_helper.c +++ b/drivers/clk/mvebu/armada_ap_cp_helper.c @@ -16,15 +16,13 @@ char *ap_cp_unique_name(struct device *dev, struct device_node *np, const char *name) { - const __be32 *reg; - u64 addr; + struct resource res; /* Do not create a name if there is no clock */ if (!name) return NULL; - reg = of_get_property(np, "reg", NULL); - addr = of_translate_address(np, reg); + of_address_to_resource(np, 0, &res); return devm_kasprintf(dev, GFP_KERNEL, "%llx-%s", - (unsigned long long)addr, name); + (unsigned long long)res.start, name); } diff --git a/drivers/clk/mvebu/clk-cpu.c b/drivers/clk/mvebu/clk-cpu.c index c2af3395cf132e96b0d12727947c5e2fe861db48..db2b38c21304ecb8cc0bad0ff7de5a0a3c868516 100644 --- a/drivers/clk/mvebu/clk-cpu.c +++ b/drivers/clk/mvebu/clk-cpu.c @@ -168,8 +168,8 @@ static void __init of_cpu_clk_setup(struct device_node *node) struct cpu_clk *cpuclk; void __iomem *clock_complex_base = of_iomap(node, 0); void __iomem *pmu_dfs_base = of_iomap(node, 1); - int ncpus = 0; - struct device_node *dn; + int ncpus = num_possible_cpus(); + int cpu; if (clock_complex_base == NULL) { pr_err("%s: clock-complex base register not set\n", @@ -181,9 +181,6 @@ static void __init of_cpu_clk_setup(struct device_node *node) pr_warn("%s: pmu-dfs base register not set, dynamic frequency scaling not available\n", __func__); - for_each_of_cpu_node(dn) - ncpus++; - cpuclk = kcalloc(ncpus, sizeof(*cpuclk), GFP_KERNEL); if (WARN_ON(!cpuclk)) goto cpuclk_out; @@ -192,19 +189,14 @@ static void __init of_cpu_clk_setup(struct device_node *node) if (WARN_ON(!clks)) goto clks_out; - for_each_of_cpu_node(dn) { + for_each_possible_cpu(cpu) { struct clk_init_data init; struct clk *clk; char *clk_name = kzalloc(5, GFP_KERNEL); - int cpu, err; if (WARN_ON(!clk_name)) goto bail_out; - err = of_property_read_u32(dn, "reg", &cpu); - if (WARN_ON(err)) - goto bail_out; - sprintf(clk_name, "cpu%d", cpu); cpuclk[cpu].parent_name = of_clk_get_parent_name(node, 0); diff --git a/drivers/clk/nuvoton/Kconfig b/drivers/clk/nuvoton/Kconfig new file mode 100644 index 0000000000000000000000000000000000000000..fe4b7f62f467048b7c86890972d55faebd066947 --- /dev/null +++ b/drivers/clk/nuvoton/Kconfig @@ -0,0 +1,19 @@ +# SPDX-License-Identifier: GPL-2.0 +# common clock support for Nuvoton SoC family. + +config COMMON_CLK_NUVOTON + bool "Nuvoton clock controller common support" + depends on ARCH_MA35 || COMPILE_TEST + default y + help + Say y here to enable common clock controller for Nuvoton platforms. + +if COMMON_CLK_NUVOTON + +config CLK_MA35D1 + bool "Nuvoton MA35D1 clock controller support" + default y + help + Build the clock controller driver for MA35D1 SoC. + +endif diff --git a/drivers/clk/nuvoton/Makefile b/drivers/clk/nuvoton/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..c3c59dd9f2aaab61231f066a606e29bb8216924a --- /dev/null +++ b/drivers/clk/nuvoton/Makefile @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0-only +obj-$(CONFIG_CLK_MA35D1) += clk-ma35d1.o +obj-$(CONFIG_CLK_MA35D1) += clk-ma35d1-divider.o +obj-$(CONFIG_CLK_MA35D1) += clk-ma35d1-pll.o diff --git a/drivers/clk/nuvoton/clk-ma35d1-divider.c b/drivers/clk/nuvoton/clk-ma35d1-divider.c new file mode 100644 index 0000000000000000000000000000000000000000..bb8c23d2b895ff1975165443b4bd2541e9d6e272 --- /dev/null +++ b/drivers/clk/nuvoton/clk-ma35d1-divider.c @@ -0,0 +1,132 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2023 Nuvoton Technology Corp. + * Author: Chi-Fang Li + */ + +#include +#include +#include +#include + +#include "clk-ma35d1.h" + +struct ma35d1_adc_clk_div { + struct clk_hw hw; + void __iomem *reg; + u8 shift; + u8 width; + u32 mask; + const struct clk_div_table *table; + /* protects concurrent access to clock divider registers */ + spinlock_t *lock; +}; + +static inline struct ma35d1_adc_clk_div *to_ma35d1_adc_clk_div(struct clk_hw *_hw) +{ + return container_of(_hw, struct ma35d1_adc_clk_div, hw); +} + +static unsigned long ma35d1_clkdiv_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) +{ + unsigned int val; + struct ma35d1_adc_clk_div *dclk = to_ma35d1_adc_clk_div(hw); + + val = readl_relaxed(dclk->reg) >> dclk->shift; + val &= clk_div_mask(dclk->width); + val += 1; + return divider_recalc_rate(hw, parent_rate, val, dclk->table, + CLK_DIVIDER_ROUND_CLOSEST, dclk->width); +} + +static long ma35d1_clkdiv_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *prate) +{ + struct ma35d1_adc_clk_div *dclk = to_ma35d1_adc_clk_div(hw); + + return divider_round_rate(hw, rate, prate, dclk->table, + dclk->width, CLK_DIVIDER_ROUND_CLOSEST); +} + +static int ma35d1_clkdiv_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) +{ + int value; + unsigned long flags = 0; + u32 data; + struct ma35d1_adc_clk_div *dclk = to_ma35d1_adc_clk_div(hw); + + value = divider_get_val(rate, parent_rate, dclk->table, + dclk->width, CLK_DIVIDER_ROUND_CLOSEST); + + spin_lock_irqsave(dclk->lock, flags); + + data = readl_relaxed(dclk->reg); + data &= ~(clk_div_mask(dclk->width) << dclk->shift); + data |= (value - 1) << dclk->shift; + data |= dclk->mask; + writel_relaxed(data, dclk->reg); + + spin_unlock_irqrestore(dclk->lock, flags); + return 0; +} + +static const struct clk_ops ma35d1_adc_clkdiv_ops = { + .recalc_rate = ma35d1_clkdiv_recalc_rate, + .round_rate = ma35d1_clkdiv_round_rate, + .set_rate = ma35d1_clkdiv_set_rate, +}; + +struct clk_hw *ma35d1_reg_adc_clkdiv(struct device *dev, const char *name, + struct clk_hw *parent_hw, spinlock_t *lock, + unsigned long flags, void __iomem *reg, + u8 shift, u8 width, u32 mask_bit) +{ + struct ma35d1_adc_clk_div *div; + struct clk_init_data init; + struct clk_div_table *table; + struct clk_parent_data pdata = { .index = 0 }; + u32 max_div, min_div; + struct clk_hw *hw; + int ret; + int i; + + div = devm_kzalloc(dev, sizeof(*div), GFP_KERNEL); + if (!div) + return ERR_PTR(-ENOMEM); + + max_div = clk_div_mask(width) + 1; + min_div = 1; + + table = devm_kcalloc(dev, max_div + 1, sizeof(*table), GFP_KERNEL); + if (!table) + return ERR_PTR(-ENOMEM); + + for (i = 0; i < max_div; i++) { + table[i].val = min_div + i; + table[i].div = 2 * table[i].val; + } + table[max_div].val = 0; + table[max_div].div = 0; + + memset(&init, 0, sizeof(init)); + init.name = name; + init.ops = &ma35d1_adc_clkdiv_ops; + init.flags |= flags; + pdata.hw = parent_hw; + init.parent_data = &pdata; + init.num_parents = 1; + + div->reg = reg; + div->shift = shift; + div->width = width; + div->mask = mask_bit ? BIT(mask_bit) : 0; + div->lock = lock; + div->hw.init = &init; + div->table = table; + + hw = &div->hw; + ret = devm_clk_hw_register(dev, hw); + if (ret) + return ERR_PTR(ret); + return hw; +} +EXPORT_SYMBOL_GPL(ma35d1_reg_adc_clkdiv); diff --git a/drivers/clk/nuvoton/clk-ma35d1-pll.c b/drivers/clk/nuvoton/clk-ma35d1-pll.c new file mode 100644 index 0000000000000000000000000000000000000000..ff3fb8b87c24b0fc0823cbd2e3cf311137fa56db --- /dev/null +++ b/drivers/clk/nuvoton/clk-ma35d1-pll.c @@ -0,0 +1,360 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2023 Nuvoton Technology Corp. + * Author: Chi-Fang Li + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "clk-ma35d1.h" + +/* PLL frequency limits */ +#define PLL_FREF_MAX_FREQ (200 * HZ_PER_MHZ) +#define PLL_FREF_MIN_FREQ (1 * HZ_PER_MHZ) +#define PLL_FREF_M_MAX_FREQ (40 * HZ_PER_MHZ) +#define PLL_FREF_M_MIN_FREQ (10 * HZ_PER_MHZ) +#define PLL_FCLK_MAX_FREQ (2400 * HZ_PER_MHZ) +#define PLL_FCLK_MIN_FREQ (600 * HZ_PER_MHZ) +#define PLL_FCLKO_MAX_FREQ (2400 * HZ_PER_MHZ) +#define PLL_FCLKO_MIN_FREQ (85700 * HZ_PER_KHZ) +#define PLL_SS_RATE 0x77 +#define PLL_SLOPE 0x58CFA + +#define REG_PLL_CTL0_OFFSET 0x0 +#define REG_PLL_CTL1_OFFSET 0x4 +#define REG_PLL_CTL2_OFFSET 0x8 + +/* bit fields for REG_CLK_PLL0CTL0, which is SMIC PLL design */ +#define SPLL0_CTL0_FBDIV GENMASK(7, 0) +#define SPLL0_CTL0_INDIV GENMASK(11, 8) +#define SPLL0_CTL0_OUTDIV GENMASK(13, 12) +#define SPLL0_CTL0_PD BIT(16) +#define SPLL0_CTL0_BP BIT(17) + +/* bit fields for REG_CLK_PLLxCTL0 ~ REG_CLK_PLLxCTL2, where x = 2 ~ 5 */ +#define PLL_CTL0_FBDIV GENMASK(10, 0) +#define PLL_CTL0_INDIV GENMASK(17, 12) +#define PLL_CTL0_MODE GENMASK(19, 18) +#define PLL_CTL0_SSRATE GENMASK(30, 20) +#define PLL_CTL1_PD BIT(0) +#define PLL_CTL1_BP BIT(1) +#define PLL_CTL1_OUTDIV GENMASK(6, 4) +#define PLL_CTL1_FRAC GENMASK(31, 24) +#define PLL_CTL2_SLOPE GENMASK(23, 0) + +#define INDIV_MIN 1 +#define INDIV_MAX 63 +#define FBDIV_MIN 16 +#define FBDIV_MAX 2047 +#define FBDIV_FRAC_MIN 1600 +#define FBDIV_FRAC_MAX 204700 +#define OUTDIV_MIN 1 +#define OUTDIV_MAX 7 + +#define PLL_MODE_INT 0 +#define PLL_MODE_FRAC 1 +#define PLL_MODE_SS 2 + +struct ma35d1_clk_pll { + struct clk_hw hw; + u32 id; + u8 mode; + void __iomem *ctl0_base; + void __iomem *ctl1_base; + void __iomem *ctl2_base; +}; + +static inline struct ma35d1_clk_pll *to_ma35d1_clk_pll(struct clk_hw *_hw) +{ + return container_of(_hw, struct ma35d1_clk_pll, hw); +} + +static unsigned long ma35d1_calc_smic_pll_freq(u32 pll0_ctl0, + unsigned long parent_rate) +{ + u32 m, n, p, outdiv; + u64 pll_freq; + + if (pll0_ctl0 & SPLL0_CTL0_BP) + return parent_rate; + + n = FIELD_GET(SPLL0_CTL0_FBDIV, pll0_ctl0); + m = FIELD_GET(SPLL0_CTL0_INDIV, pll0_ctl0); + p = FIELD_GET(SPLL0_CTL0_OUTDIV, pll0_ctl0); + outdiv = 1 << p; + pll_freq = (u64)parent_rate * n; + div_u64(pll_freq, m * outdiv); + return pll_freq; +} + +static unsigned long ma35d1_calc_pll_freq(u8 mode, u32 *reg_ctl, unsigned long parent_rate) +{ + unsigned long pll_freq, x; + u32 m, n, p; + + if (reg_ctl[1] & PLL_CTL1_BP) + return parent_rate; + + n = FIELD_GET(PLL_CTL0_FBDIV, reg_ctl[0]); + m = FIELD_GET(PLL_CTL0_INDIV, reg_ctl[0]); + p = FIELD_GET(PLL_CTL1_OUTDIV, reg_ctl[1]); + + if (mode == PLL_MODE_INT) { + pll_freq = (u64)parent_rate * n; + div_u64(pll_freq, m * p); + } else { + x = FIELD_GET(PLL_CTL1_FRAC, reg_ctl[1]); + /* 2 decimal places floating to integer (ex. 1.23 to 123) */ + n = n * 100 + ((x * 100) / FIELD_MAX(PLL_CTL1_FRAC)); + pll_freq = div_u64(parent_rate * n, 100 * m * p); + } + return pll_freq; +} + +static int ma35d1_pll_find_closest(struct ma35d1_clk_pll *pll, unsigned long rate, + unsigned long parent_rate, u32 *reg_ctl, + unsigned long *freq) +{ + unsigned long min_diff = ULONG_MAX; + int fbdiv_min, fbdiv_max; + int p, m, n; + + *freq = 0; + if (rate < PLL_FCLKO_MIN_FREQ || rate > PLL_FCLKO_MAX_FREQ) + return -EINVAL; + + if (pll->mode == PLL_MODE_INT) { + fbdiv_min = FBDIV_MIN; + fbdiv_max = FBDIV_MAX; + } else { + fbdiv_min = FBDIV_FRAC_MIN; + fbdiv_max = FBDIV_FRAC_MAX; + } + + for (m = INDIV_MIN; m <= INDIV_MAX; m++) { + for (n = fbdiv_min; n <= fbdiv_max; n++) { + for (p = OUTDIV_MIN; p <= OUTDIV_MAX; p++) { + unsigned long tmp, fout, fclk, diff; + + tmp = div_u64(parent_rate, m); + if (tmp < PLL_FREF_M_MIN_FREQ || + tmp > PLL_FREF_M_MAX_FREQ) + continue; /* constrain */ + + fclk = div_u64(parent_rate * n, m); + /* for 2 decimal places */ + if (pll->mode != PLL_MODE_INT) + fclk = div_u64(fclk, 100); + + if (fclk < PLL_FCLK_MIN_FREQ || + fclk > PLL_FCLK_MAX_FREQ) + continue; /* constrain */ + + fout = div_u64(fclk, p); + if (fout < PLL_FCLKO_MIN_FREQ || + fout > PLL_FCLKO_MAX_FREQ) + continue; /* constrain */ + + diff = abs(rate - fout); + if (diff < min_diff) { + reg_ctl[0] = FIELD_PREP(PLL_CTL0_INDIV, m) | + FIELD_PREP(PLL_CTL0_FBDIV, n); + reg_ctl[1] = FIELD_PREP(PLL_CTL1_OUTDIV, p); + *freq = fout; + min_diff = diff; + if (min_diff == 0) + break; + } + } + } + } + if (*freq == 0) + return -EINVAL; /* cannot find even one valid setting */ + return 0; +} + +static int ma35d1_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct ma35d1_clk_pll *pll = to_ma35d1_clk_pll(hw); + u32 reg_ctl[3] = { 0 }; + unsigned long pll_freq; + int ret; + + if (parent_rate < PLL_FREF_MIN_FREQ || parent_rate > PLL_FREF_MAX_FREQ) + return -EINVAL; + + ret = ma35d1_pll_find_closest(pll, rate, parent_rate, reg_ctl, &pll_freq); + if (ret != 0) + return ret; + + switch (pll->mode) { + case PLL_MODE_INT: + reg_ctl[0] |= FIELD_PREP(PLL_CTL0_MODE, PLL_MODE_INT); + break; + case PLL_MODE_FRAC: + reg_ctl[0] |= FIELD_PREP(PLL_CTL0_MODE, PLL_MODE_FRAC); + break; + case PLL_MODE_SS: + reg_ctl[0] |= FIELD_PREP(PLL_CTL0_MODE, PLL_MODE_SS) | + FIELD_PREP(PLL_CTL0_SSRATE, PLL_SS_RATE); + reg_ctl[2] = FIELD_PREP(PLL_CTL2_SLOPE, PLL_SLOPE); + break; + } + reg_ctl[1] |= PLL_CTL1_PD; + + writel_relaxed(reg_ctl[0], pll->ctl0_base); + writel_relaxed(reg_ctl[1], pll->ctl1_base); + writel_relaxed(reg_ctl[2], pll->ctl2_base); + return 0; +} + +static unsigned long ma35d1_clk_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) +{ + struct ma35d1_clk_pll *pll = to_ma35d1_clk_pll(hw); + u32 reg_ctl[3]; + unsigned long pll_freq; + + if (parent_rate < PLL_FREF_MIN_FREQ || parent_rate > PLL_FREF_MAX_FREQ) + return 0; + + switch (pll->id) { + case CAPLL: + reg_ctl[0] = readl_relaxed(pll->ctl0_base); + pll_freq = ma35d1_calc_smic_pll_freq(reg_ctl[0], parent_rate); + return pll_freq; + case DDRPLL: + case APLL: + case EPLL: + case VPLL: + reg_ctl[0] = readl_relaxed(pll->ctl0_base); + reg_ctl[1] = readl_relaxed(pll->ctl1_base); + pll_freq = ma35d1_calc_pll_freq(pll->mode, reg_ctl, parent_rate); + return pll_freq; + } + return 0; +} + +static long ma35d1_clk_pll_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *parent_rate) +{ + struct ma35d1_clk_pll *pll = to_ma35d1_clk_pll(hw); + u32 reg_ctl[3] = { 0 }; + unsigned long pll_freq; + long ret; + + if (*parent_rate < PLL_FREF_MIN_FREQ || *parent_rate > PLL_FREF_MAX_FREQ) + return -EINVAL; + + ret = ma35d1_pll_find_closest(pll, rate, *parent_rate, reg_ctl, &pll_freq); + if (ret < 0) + return ret; + + switch (pll->id) { + case CAPLL: + reg_ctl[0] = readl_relaxed(pll->ctl0_base); + pll_freq = ma35d1_calc_smic_pll_freq(reg_ctl[0], *parent_rate); + return pll_freq; + case DDRPLL: + case APLL: + case EPLL: + case VPLL: + reg_ctl[0] = readl_relaxed(pll->ctl0_base); + reg_ctl[1] = readl_relaxed(pll->ctl1_base); + pll_freq = ma35d1_calc_pll_freq(pll->mode, reg_ctl, *parent_rate); + return pll_freq; + } + return 0; +} + +static int ma35d1_clk_pll_is_prepared(struct clk_hw *hw) +{ + struct ma35d1_clk_pll *pll = to_ma35d1_clk_pll(hw); + u32 val = readl_relaxed(pll->ctl1_base); + + return !(val & PLL_CTL1_PD); +} + +static int ma35d1_clk_pll_prepare(struct clk_hw *hw) +{ + struct ma35d1_clk_pll *pll = to_ma35d1_clk_pll(hw); + u32 val; + + val = readl_relaxed(pll->ctl1_base); + val &= ~PLL_CTL1_PD; + writel_relaxed(val, pll->ctl1_base); + return 0; +} + +static void ma35d1_clk_pll_unprepare(struct clk_hw *hw) +{ + struct ma35d1_clk_pll *pll = to_ma35d1_clk_pll(hw); + u32 val; + + val = readl_relaxed(pll->ctl1_base); + val |= PLL_CTL1_PD; + writel_relaxed(val, pll->ctl1_base); +} + +static const struct clk_ops ma35d1_clk_pll_ops = { + .is_prepared = ma35d1_clk_pll_is_prepared, + .prepare = ma35d1_clk_pll_prepare, + .unprepare = ma35d1_clk_pll_unprepare, + .set_rate = ma35d1_clk_pll_set_rate, + .recalc_rate = ma35d1_clk_pll_recalc_rate, + .round_rate = ma35d1_clk_pll_round_rate, +}; + +static const struct clk_ops ma35d1_clk_fixed_pll_ops = { + .recalc_rate = ma35d1_clk_pll_recalc_rate, + .round_rate = ma35d1_clk_pll_round_rate, +}; + +struct clk_hw *ma35d1_reg_clk_pll(struct device *dev, u32 id, u8 u8mode, const char *name, + struct clk_hw *parent_hw, void __iomem *base) +{ + struct clk_parent_data pdata = { .index = 0 }; + struct clk_init_data init = {}; + struct ma35d1_clk_pll *pll; + struct clk_hw *hw; + int ret; + + pll = devm_kzalloc(dev, sizeof(*pll), GFP_KERNEL); + if (!pll) + return ERR_PTR(-ENOMEM); + + pll->id = id; + pll->mode = u8mode; + pll->ctl0_base = base + REG_PLL_CTL0_OFFSET; + pll->ctl1_base = base + REG_PLL_CTL1_OFFSET; + pll->ctl2_base = base + REG_PLL_CTL2_OFFSET; + + init.name = name; + init.flags = 0; + pdata.hw = parent_hw; + init.parent_data = &pdata; + init.num_parents = 1; + + if (id == CAPLL || id == DDRPLL) + init.ops = &ma35d1_clk_fixed_pll_ops; + else + init.ops = &ma35d1_clk_pll_ops; + + pll->hw.init = &init; + hw = &pll->hw; + + ret = devm_clk_hw_register(dev, hw); + if (ret) + return ERR_PTR(ret); + return hw; +} +EXPORT_SYMBOL_GPL(ma35d1_reg_clk_pll); diff --git a/drivers/clk/nuvoton/clk-ma35d1.c b/drivers/clk/nuvoton/clk-ma35d1.c new file mode 100644 index 0000000000000000000000000000000000000000..f1fe7edd21b5ca6090d93862e492360bedf80610 --- /dev/null +++ b/drivers/clk/nuvoton/clk-ma35d1.c @@ -0,0 +1,1059 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2023 Nuvoton Technology Corp. + * Author: Chi-Fang Li + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "clk-ma35d1.h" + +static DEFINE_SPINLOCK(ma35d1_lock); + +#define PLL_MAX_NUM 5 + +/* Clock Control Registers Offset */ +#define REG_CLK_PWRCTL 0x00 +#define REG_CLK_SYSCLK0 0x04 +#define REG_CLK_SYSCLK1 0x08 +#define REG_CLK_APBCLK0 0x0c +#define REG_CLK_APBCLK1 0x10 +#define REG_CLK_APBCLK2 0x14 +#define REG_CLK_CLKSEL0 0x18 +#define REG_CLK_CLKSEL1 0x1c +#define REG_CLK_CLKSEL2 0x20 +#define REG_CLK_CLKSEL3 0x24 +#define REG_CLK_CLKSEL4 0x28 +#define REG_CLK_CLKDIV0 0x2c +#define REG_CLK_CLKDIV1 0x30 +#define REG_CLK_CLKDIV2 0x34 +#define REG_CLK_CLKDIV3 0x38 +#define REG_CLK_CLKDIV4 0x3c +#define REG_CLK_CLKOCTL 0x40 +#define REG_CLK_STATUS 0x50 +#define REG_CLK_PLL0CTL0 0x60 +#define REG_CLK_PLL2CTL0 0x80 +#define REG_CLK_PLL2CTL1 0x84 +#define REG_CLK_PLL2CTL2 0x88 +#define REG_CLK_PLL3CTL0 0x90 +#define REG_CLK_PLL3CTL1 0x94 +#define REG_CLK_PLL3CTL2 0x98 +#define REG_CLK_PLL4CTL0 0xa0 +#define REG_CLK_PLL4CTL1 0xa4 +#define REG_CLK_PLL4CTL2 0xa8 +#define REG_CLK_PLL5CTL0 0xb0 +#define REG_CLK_PLL5CTL1 0xb4 +#define REG_CLK_PLL5CTL2 0xb8 +#define REG_CLK_CLKDCTL 0xc0 +#define REG_CLK_CLKDSTS 0xc4 +#define REG_CLK_CDUPB 0xc8 +#define REG_CLK_CDLOWB 0xcc +#define REG_CLK_CKFLTRCTL 0xd0 +#define REG_CLK_TESTCLK 0xf0 +#define REG_CLK_PLLCTL 0x40 + +#define PLL_MODE_INT 0 +#define PLL_MODE_FRAC 1 +#define PLL_MODE_SS 2 + +static const struct clk_parent_data ca35clk_sel_clks[] = { + { .fw_name = "hxt", }, + { .fw_name = "capll", }, + { .fw_name = "ddrpll", }, +}; + +static const struct clk_parent_data sysclk0_sel_clks[] = { + { .fw_name = "epll_div2", }, + { .fw_name = "syspll", }, +}; + +static const struct clk_parent_data sysclk1_sel_clks[] = { + { .fw_name = "hxt", }, + { .fw_name = "syspll", }, +}; + +static const struct clk_parent_data axiclk_sel_clks[] = { + { .fw_name = "capll_div2", }, + { .fw_name = "capll_div4", }, +}; + +static const struct clk_parent_data ccap_sel_clks[] = { + { .fw_name = "hxt", }, + { .fw_name = "vpll", }, + { .fw_name = "apll", }, + { .fw_name = "syspll", }, +}; + +static const struct clk_parent_data sdh_sel_clks[] = { + { .fw_name = "syspll", }, + { .fw_name = "apll", }, +}; + +static const struct clk_parent_data dcu_sel_clks[] = { + { .fw_name = "epll_div2", }, + { .fw_name = "syspll", }, +}; + +static const struct clk_parent_data gfx_sel_clks[] = { + { .fw_name = "epll", }, + { .fw_name = "syspll", }, +}; + +static const struct clk_parent_data dbg_sel_clks[] = { + { .fw_name = "hirc", }, + { .fw_name = "syspll", }, +}; + +static const struct clk_parent_data timer0_sel_clks[] = { + { .fw_name = "hxt", }, + { .fw_name = "lxt", }, + { .fw_name = "pclk0", }, + { .index = -1, }, + { .index = -1, }, + { .fw_name = "lirc", }, + { .index = -1, }, + { .fw_name = "hirc", }, +}; + +static const struct clk_parent_data timer1_sel_clks[] = { + { .fw_name = "hxt", }, + { .fw_name = "lxt", }, + { .fw_name = "pclk0", }, + { .index = -1, }, + { .index = -1, }, + { .fw_name = "lirc", }, + { .index = -1, }, + { .fw_name = "hirc", }, +}; + +static const struct clk_parent_data timer2_sel_clks[] = { + { .fw_name = "hxt", }, + { .fw_name = "lxt", }, + { .fw_name = "pclk1", }, + { .index = -1, }, + { .index = -1, }, + { .fw_name = "lirc", }, + { .index = -1, }, + { .fw_name = "hirc", }, +}; + +static const struct clk_parent_data timer3_sel_clks[] = { + { .fw_name = "hxt", }, + { .fw_name = "lxt", }, + { .fw_name = "pclk1", }, + { .index = -1, }, + { .index = -1, }, + { .fw_name = "lirc", }, + { .index = -1, }, + { .fw_name = "hirc", }, +}; + +static const struct clk_parent_data timer4_sel_clks[] = { + { .fw_name = "hxt", }, + { .fw_name = "lxt", }, + { .fw_name = "pclk2", }, + { .index = -1, }, + { .index = -1, }, + { .fw_name = "lirc", }, + { .index = -1, }, + { .fw_name = "hirc", }, +}; + +static const struct clk_parent_data timer5_sel_clks[] = { + { .fw_name = "hxt", }, + { .fw_name = "lxt", }, + { .fw_name = "pclk2", }, + { .index = -1, }, + { .index = -1, }, + { .fw_name = "lirc", }, + { .index = -1, }, + { .fw_name = "hirc", }, +}; + +static const struct clk_parent_data timer6_sel_clks[] = { + { .fw_name = "hxt", }, + { .fw_name = "lxt", }, + { .fw_name = "pclk0", }, + { .index = -1, }, + { .index = -1, }, + { .fw_name = "lirc", }, + { .index = -1, }, + { .fw_name = "hirc", }, +}; + +static const struct clk_parent_data timer7_sel_clks[] = { + { .fw_name = "hxt", }, + { .fw_name = "lxt", }, + { .fw_name = "pclk0", }, + { .index = -1, }, + { .index = -1, }, + { .fw_name = "lirc", }, + { .index = -1, }, + { .fw_name = "hirc", }, +}; + +static const struct clk_parent_data timer8_sel_clks[] = { + { .fw_name = "hxt", }, + { .fw_name = "lxt", }, + { .fw_name = "pclk1", }, + { .index = -1, }, + { .index = -1, }, + { .fw_name = "lirc", }, + { .index = -1, }, + { .fw_name = "hirc", }, +}; + +static const struct clk_parent_data timer9_sel_clks[] = { + { .fw_name = "hxt", }, + { .fw_name = "lxt", }, + { .fw_name = "pclk1", }, + { .index = -1, }, + { .index = -1, }, + { .fw_name = "lirc", }, + { .index = -1, }, + { .fw_name = "hirc", }, +}; + +static const struct clk_parent_data timer10_sel_clks[] = { + { .fw_name = "hxt", }, + { .fw_name = "lxt", }, + { .fw_name = "pclk2", }, + { .index = -1, }, + { .index = -1, }, + { .fw_name = "lirc", }, + { .index = -1, }, + { .fw_name = "hirc", }, +}; + +static const struct clk_parent_data timer11_sel_clks[] = { + { .fw_name = "hxt", }, + { .fw_name = "lxt", }, + { .fw_name = "pclk2", }, + { .index = -1, }, + { .index = -1, }, + { .fw_name = "lirc", }, + { .index = -1, }, + { .fw_name = "hirc", }, +}; + +static const struct clk_parent_data uart_sel_clks[] = { + { .fw_name = "hxt", }, + { .fw_name = "sysclk1_div2", }, +}; + +static const struct clk_parent_data wdt0_sel_clks[] = { + { .index = -1, }, + { .fw_name = "lxt", }, + { .fw_name = "pclk3_div4096", }, + { .fw_name = "lirc", }, +}; + +static const struct clk_parent_data wdt1_sel_clks[] = { + { .index = -1, }, + { .fw_name = "lxt", }, + { .fw_name = "pclk3_div4096", }, + { .fw_name = "lirc", }, +}; + +static const struct clk_parent_data wdt2_sel_clks[] = { + { .index = -1, }, + { .fw_name = "lxt", }, + { .fw_name = "pclk4_div4096", }, + { .fw_name = "lirc", }, +}; + +static const struct clk_parent_data wwdt0_sel_clks[] = { + { .index = -1, }, + { .index = -1, }, + { .fw_name = "pclk3_div4096", }, + { .fw_name = "lirc", }, +}; + +static const struct clk_parent_data wwdt1_sel_clks[] = { + { .index = -1, }, + { .index = -1, }, + { .fw_name = "pclk3_div4096", }, + { .fw_name = "lirc", }, +}; + +static const struct clk_parent_data wwdt2_sel_clks[] = { + { .index = -1, }, + { .index = -1, }, + { .fw_name = "pclk4_div4096", }, + { .fw_name = "lirc", }, +}; + +static const struct clk_parent_data spi0_sel_clks[] = { + { .fw_name = "pclk1", }, + { .fw_name = "apll", }, +}; + +static const struct clk_parent_data spi1_sel_clks[] = { + { .fw_name = "pclk2", }, + { .fw_name = "apll", }, +}; + +static const struct clk_parent_data spi2_sel_clks[] = { + { .fw_name = "pclk1", }, + { .fw_name = "apll", }, +}; + +static const struct clk_parent_data spi3_sel_clks[] = { + { .fw_name = "pclk2", }, + { .fw_name = "apll", }, +}; + +static const struct clk_parent_data qspi0_sel_clks[] = { + { .fw_name = "pclk0", }, + { .fw_name = "apll", }, +}; + +static const struct clk_parent_data qspi1_sel_clks[] = { + { .fw_name = "pclk0", }, + { .fw_name = "apll", }, +}; + +static const struct clk_parent_data i2s0_sel_clks[] = { + { .fw_name = "apll", }, + { .fw_name = "sysclk1_div2", }, +}; + +static const struct clk_parent_data i2s1_sel_clks[] = { + { .fw_name = "apll", }, + { .fw_name = "sysclk1_div2", }, +}; + +static const struct clk_parent_data can_sel_clks[] = { + { .fw_name = "apll", }, + { .fw_name = "vpll", }, +}; + +static const struct clk_parent_data cko_sel_clks[] = { + { .fw_name = "hxt", }, + { .fw_name = "lxt", }, + { .fw_name = "hirc", }, + { .fw_name = "lirc", }, + { .fw_name = "capll_div4", }, + { .fw_name = "syspll", }, + { .fw_name = "ddrpll", }, + { .fw_name = "epll_div2", }, + { .fw_name = "apll", }, + { .fw_name = "vpll", }, +}; + +static const struct clk_parent_data smc_sel_clks[] = { + { .fw_name = "hxt", }, + { .fw_name = "pclk4", }, +}; + +static const struct clk_parent_data kpi_sel_clks[] = { + { .fw_name = "hxt", }, + { .fw_name = "lxt", }, +}; + +static const struct clk_div_table ip_div_table[] = { + {0, 2}, {1, 4}, {2, 6}, {3, 8}, {4, 10}, + {5, 12}, {6, 14}, {7, 16}, {0, 0}, +}; + +static const struct clk_div_table eadc_div_table[] = { + {0, 2}, {1, 4}, {2, 6}, {3, 8}, {4, 10}, + {5, 12}, {6, 14}, {7, 16}, {8, 18}, + {9, 20}, {10, 22}, {11, 24}, {12, 26}, + {13, 28}, {14, 30}, {15, 32}, {0, 0}, +}; + +static struct clk_hw *ma35d1_clk_fixed(const char *name, int rate) +{ + return clk_hw_register_fixed_rate(NULL, name, NULL, 0, rate); +} + +static struct clk_hw *ma35d1_clk_mux_parent(struct device *dev, const char *name, + void __iomem *reg, u8 shift, u8 width, + const struct clk_parent_data *pdata, + int num_pdata) +{ + return clk_hw_register_mux_parent_data(dev, name, pdata, num_pdata, + CLK_SET_RATE_NO_REPARENT, reg, shift, + width, 0, &ma35d1_lock); +} + +static struct clk_hw *ma35d1_clk_mux(struct device *dev, const char *name, + void __iomem *reg, u8 shift, u8 width, + const struct clk_parent_data *pdata, + int num_pdata) +{ + return clk_hw_register_mux_parent_data(dev, name, pdata, num_pdata, + CLK_SET_RATE_NO_REPARENT, reg, shift, + width, 0, &ma35d1_lock); +} + +static struct clk_hw *ma35d1_clk_divider(struct device *dev, const char *name, + const char *parent, void __iomem *reg, + u8 shift, u8 width) +{ + return devm_clk_hw_register_divider(dev, name, parent, CLK_SET_RATE_PARENT, + reg, shift, width, 0, &ma35d1_lock); +} + +static struct clk_hw *ma35d1_clk_divider_pow2(struct device *dev, const char *name, + const char *parent, void __iomem *reg, + u8 shift, u8 width) +{ + return devm_clk_hw_register_divider(dev, name, parent, + CLK_DIVIDER_POWER_OF_TWO, reg, shift, + width, 0, &ma35d1_lock); +} + +static struct clk_hw *ma35d1_clk_divider_table(struct device *dev, const char *name, + const char *parent, void __iomem *reg, + u8 shift, u8 width, + const struct clk_div_table *table) +{ + return devm_clk_hw_register_divider_table(dev, name, parent, 0, + reg, shift, width, 0, + table, &ma35d1_lock); +} + +static struct clk_hw *ma35d1_clk_fixed_factor(struct device *dev, const char *name, + const char *parent, unsigned int mult, + unsigned int div) +{ + return devm_clk_hw_register_fixed_factor(dev, name, parent, + CLK_SET_RATE_PARENT, mult, div); +} + +static struct clk_hw *ma35d1_clk_gate(struct device *dev, const char *name, const char *parent, + void __iomem *reg, u8 shift) +{ + return devm_clk_hw_register_gate(dev, name, parent, CLK_SET_RATE_PARENT, + reg, shift, 0, &ma35d1_lock); +} + +static int ma35d1_get_pll_setting(struct device_node *clk_node, u32 *pllmode) +{ + const char *of_str; + int i; + + for (i = 0; i < PLL_MAX_NUM; i++) { + if (of_property_read_string_index(clk_node, "nuvoton,pll-mode", i, &of_str)) + return -EINVAL; + if (!strcmp(of_str, "integer")) + pllmode[i] = PLL_MODE_INT; + else if (!strcmp(of_str, "fractional")) + pllmode[i] = PLL_MODE_FRAC; + else if (!strcmp(of_str, "spread-spectrum")) + pllmode[i] = PLL_MODE_SS; + else + return -EINVAL; + } + return 0; +} + +static int ma35d1_clocks_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *clk_node = pdev->dev.of_node; + struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + void __iomem *clk_base; + static struct clk_hw **hws; + static struct clk_hw_onecell_data *ma35d1_hw_data; + u32 pllmode[PLL_MAX_NUM]; + int ret; + + ma35d1_hw_data = devm_kzalloc(dev, + struct_size(ma35d1_hw_data, hws, CLK_MAX_IDX), + GFP_KERNEL); + if (!ma35d1_hw_data) + return -ENOMEM; + + ma35d1_hw_data->num = CLK_MAX_IDX; + hws = ma35d1_hw_data->hws; + + clk_base = devm_ioremap_resource(dev, res); + if (IS_ERR(clk_base)) + return PTR_ERR(clk_base); + + ret = ma35d1_get_pll_setting(clk_node, pllmode); + if (ret < 0) { + dev_err(dev, "Invalid PLL setting!\n"); + return -EINVAL; + } + + hws[HXT] = ma35d1_clk_fixed("hxt", 24000000); + hws[HXT_GATE] = ma35d1_clk_gate(dev, "hxt_gate", "hxt", + clk_base + REG_CLK_PWRCTL, 0); + hws[LXT] = ma35d1_clk_fixed("lxt", 32768); + hws[LXT_GATE] = ma35d1_clk_gate(dev, "lxt_gate", "lxt", + clk_base + REG_CLK_PWRCTL, 1); + hws[HIRC] = ma35d1_clk_fixed("hirc", 12000000); + hws[HIRC_GATE] = ma35d1_clk_gate(dev, "hirc_gate", "hirc", + clk_base + REG_CLK_PWRCTL, 2); + hws[LIRC] = ma35d1_clk_fixed("lirc", 32000); + hws[LIRC_GATE] = ma35d1_clk_gate(dev, "lirc_gate", "lirc", + clk_base + REG_CLK_PWRCTL, 3); + + hws[CAPLL] = ma35d1_reg_clk_pll(dev, CAPLL, pllmode[0], "capll", + hws[HXT], clk_base + REG_CLK_PLL0CTL0); + hws[SYSPLL] = ma35d1_clk_fixed("syspll", 180000000); + hws[DDRPLL] = ma35d1_reg_clk_pll(dev, DDRPLL, pllmode[1], "ddrpll", + hws[HXT], clk_base + REG_CLK_PLL2CTL0); + hws[APLL] = ma35d1_reg_clk_pll(dev, APLL, pllmode[2], "apll", + hws[HXT], clk_base + REG_CLK_PLL3CTL0); + hws[EPLL] = ma35d1_reg_clk_pll(dev, EPLL, pllmode[3], "epll", + hws[HXT], clk_base + REG_CLK_PLL4CTL0); + hws[VPLL] = ma35d1_reg_clk_pll(dev, VPLL, pllmode[4], "vpll", + hws[HXT], clk_base + REG_CLK_PLL5CTL0); + + hws[EPLL_DIV2] = ma35d1_clk_fixed_factor(dev, "epll_div2", "epll", 1, 2); + hws[EPLL_DIV4] = ma35d1_clk_fixed_factor(dev, "epll_div4", "epll", 1, 4); + hws[EPLL_DIV8] = ma35d1_clk_fixed_factor(dev, "epll_div8", "epll", 1, 8); + + hws[CA35CLK_MUX] = ma35d1_clk_mux_parent(dev, "ca35clk_mux", + clk_base + REG_CLK_CLKSEL0, 0, 2, + ca35clk_sel_clks, + ARRAY_SIZE(ca35clk_sel_clks)); + hws[AXICLK_DIV2] = ma35d1_clk_fixed_factor(dev, "capll_div2", "ca35clk_mux", 1, 2); + hws[AXICLK_DIV4] = ma35d1_clk_fixed_factor(dev, "capll_div4", "ca35clk_mux", 1, 4); + + hws[AXICLK_MUX] = ma35d1_clk_mux(dev, "axiclk_mux", clk_base + REG_CLK_CLKDIV0, + 26, 1, axiclk_sel_clks, + ARRAY_SIZE(axiclk_sel_clks)); + hws[SYSCLK0_MUX] = ma35d1_clk_mux(dev, "sysclk0_mux", clk_base + REG_CLK_CLKSEL0, + 2, 1, sysclk0_sel_clks, + ARRAY_SIZE(sysclk0_sel_clks)); + hws[SYSCLK1_MUX] = ma35d1_clk_mux(dev, "sysclk1_mux", clk_base + REG_CLK_CLKSEL0, + 4, 1, sysclk1_sel_clks, + ARRAY_SIZE(sysclk1_sel_clks)); + hws[SYSCLK1_DIV2] = ma35d1_clk_fixed_factor(dev, "sysclk1_div2", "sysclk1_mux", 1, 2); + + /* HCLK0~3 & PCLK0~4 */ + hws[HCLK0] = ma35d1_clk_fixed_factor(dev, "hclk0", "sysclk1_mux", 1, 1); + hws[HCLK1] = ma35d1_clk_fixed_factor(dev, "hclk1", "sysclk1_mux", 1, 1); + hws[HCLK2] = ma35d1_clk_fixed_factor(dev, "hclk2", "sysclk1_mux", 1, 1); + hws[PCLK0] = ma35d1_clk_fixed_factor(dev, "pclk0", "sysclk1_mux", 1, 1); + hws[PCLK1] = ma35d1_clk_fixed_factor(dev, "pclk1", "sysclk1_mux", 1, 1); + hws[PCLK2] = ma35d1_clk_fixed_factor(dev, "pclk2", "sysclk1_mux", 1, 1); + + hws[HCLK3] = ma35d1_clk_fixed_factor(dev, "hclk3", "sysclk1_mux", 1, 2); + hws[PCLK3] = ma35d1_clk_fixed_factor(dev, "pclk3", "sysclk1_mux", 1, 2); + hws[PCLK4] = ma35d1_clk_fixed_factor(dev, "pclk4", "sysclk1_mux", 1, 2); + + hws[USBPHY0] = ma35d1_clk_fixed("usbphy0", 480000000); + hws[USBPHY1] = ma35d1_clk_fixed("usbphy1", 480000000); + + /* DDR */ + hws[DDR0_GATE] = ma35d1_clk_gate(dev, "ddr0_gate", "ddrpll", + clk_base + REG_CLK_SYSCLK0, 4); + hws[DDR6_GATE] = ma35d1_clk_gate(dev, "ddr6_gate", "ddrpll", + clk_base + REG_CLK_SYSCLK0, 5); + + hws[CAN0_MUX] = ma35d1_clk_mux(dev, "can0_mux", clk_base + REG_CLK_CLKSEL4, + 16, 1, can_sel_clks, ARRAY_SIZE(can_sel_clks)); + hws[CAN0_DIV] = ma35d1_clk_divider_table(dev, "can0_div", "can0_mux", + clk_base + REG_CLK_CLKDIV0, + 0, 3, ip_div_table); + hws[CAN0_GATE] = ma35d1_clk_gate(dev, "can0_gate", "can0_div", + clk_base + REG_CLK_SYSCLK0, 8); + hws[CAN1_MUX] = ma35d1_clk_mux(dev, "can1_mux", clk_base + REG_CLK_CLKSEL4, + 17, 1, can_sel_clks, ARRAY_SIZE(can_sel_clks)); + hws[CAN1_DIV] = ma35d1_clk_divider_table(dev, "can1_div", "can1_mux", + clk_base + REG_CLK_CLKDIV0, + 4, 3, ip_div_table); + hws[CAN1_GATE] = ma35d1_clk_gate(dev, "can1_gate", "can1_div", + clk_base + REG_CLK_SYSCLK0, 9); + hws[CAN2_MUX] = ma35d1_clk_mux(dev, "can2_mux", clk_base + REG_CLK_CLKSEL4, + 18, 1, can_sel_clks, ARRAY_SIZE(can_sel_clks)); + hws[CAN2_DIV] = ma35d1_clk_divider_table(dev, "can2_div", "can2_mux", + clk_base + REG_CLK_CLKDIV0, + 8, 3, ip_div_table); + hws[CAN2_GATE] = ma35d1_clk_gate(dev, "can2_gate", "can2_div", + clk_base + REG_CLK_SYSCLK0, 10); + hws[CAN3_MUX] = ma35d1_clk_mux(dev, "can3_mux", clk_base + REG_CLK_CLKSEL4, + 19, 1, can_sel_clks, ARRAY_SIZE(can_sel_clks)); + hws[CAN3_DIV] = ma35d1_clk_divider_table(dev, "can3_div", "can3_mux", + clk_base + REG_CLK_CLKDIV0, + 12, 3, ip_div_table); + hws[CAN3_GATE] = ma35d1_clk_gate(dev, "can3_gate", "can3_div", + clk_base + REG_CLK_SYSCLK0, 11); + + hws[SDH0_MUX] = ma35d1_clk_mux(dev, "sdh0_mux", clk_base + REG_CLK_CLKSEL0, + 16, 2, sdh_sel_clks, ARRAY_SIZE(sdh_sel_clks)); + hws[SDH0_GATE] = ma35d1_clk_gate(dev, "sdh0_gate", "sdh0_mux", + clk_base + REG_CLK_SYSCLK0, 16); + hws[SDH1_MUX] = ma35d1_clk_mux(dev, "sdh1_mux", clk_base + REG_CLK_CLKSEL0, + 18, 2, sdh_sel_clks, ARRAY_SIZE(sdh_sel_clks)); + hws[SDH1_GATE] = ma35d1_clk_gate(dev, "sdh1_gate", "sdh1_mux", + clk_base + REG_CLK_SYSCLK0, 17); + + hws[NAND_GATE] = ma35d1_clk_gate(dev, "nand_gate", "hclk1", + clk_base + REG_CLK_SYSCLK0, 18); + + hws[USBD_GATE] = ma35d1_clk_gate(dev, "usbd_gate", "usbphy0", + clk_base + REG_CLK_SYSCLK0, 19); + hws[USBH_GATE] = ma35d1_clk_gate(dev, "usbh_gate", "usbphy0", + clk_base + REG_CLK_SYSCLK0, 20); + hws[HUSBH0_GATE] = ma35d1_clk_gate(dev, "husbh0_gate", "usbphy0", + clk_base + REG_CLK_SYSCLK0, 21); + hws[HUSBH1_GATE] = ma35d1_clk_gate(dev, "husbh1_gate", "usbphy0", + clk_base + REG_CLK_SYSCLK0, 22); + + hws[GFX_MUX] = ma35d1_clk_mux(dev, "gfx_mux", clk_base + REG_CLK_CLKSEL0, + 26, 1, gfx_sel_clks, ARRAY_SIZE(gfx_sel_clks)); + hws[GFX_GATE] = ma35d1_clk_gate(dev, "gfx_gate", "gfx_mux", + clk_base + REG_CLK_SYSCLK0, 24); + hws[VC8K_GATE] = ma35d1_clk_gate(dev, "vc8k_gate", "sysclk0_mux", + clk_base + REG_CLK_SYSCLK0, 25); + hws[DCU_MUX] = ma35d1_clk_mux(dev, "dcu_mux", clk_base + REG_CLK_CLKSEL0, + 24, 1, dcu_sel_clks, ARRAY_SIZE(dcu_sel_clks)); + hws[DCU_GATE] = ma35d1_clk_gate(dev, "dcu_gate", "dcu_mux", + clk_base + REG_CLK_SYSCLK0, 26); + hws[DCUP_DIV] = ma35d1_clk_divider_table(dev, "dcup_div", "vpll", + clk_base + REG_CLK_CLKDIV0, + 16, 3, ip_div_table); + + hws[EMAC0_GATE] = ma35d1_clk_gate(dev, "emac0_gate", "epll_div2", + clk_base + REG_CLK_SYSCLK0, 27); + hws[EMAC1_GATE] = ma35d1_clk_gate(dev, "emac1_gate", "epll_div2", + clk_base + REG_CLK_SYSCLK0, 28); + + hws[CCAP0_MUX] = ma35d1_clk_mux(dev, "ccap0_mux", clk_base + REG_CLK_CLKSEL0, + 12, 1, ccap_sel_clks, ARRAY_SIZE(ccap_sel_clks)); + hws[CCAP0_DIV] = ma35d1_clk_divider(dev, "ccap0_div", "ccap0_mux", + clk_base + REG_CLK_CLKDIV1, 8, 4); + hws[CCAP0_GATE] = ma35d1_clk_gate(dev, "ccap0_gate", "ccap0_div", + clk_base + REG_CLK_SYSCLK0, 29); + hws[CCAP1_MUX] = ma35d1_clk_mux(dev, "ccap1_mux", clk_base + REG_CLK_CLKSEL0, + 14, 1, ccap_sel_clks, ARRAY_SIZE(ccap_sel_clks)); + hws[CCAP1_DIV] = ma35d1_clk_divider(dev, "ccap1_div", "ccap1_mux", + clk_base + REG_CLK_CLKDIV1, + 12, 4); + hws[CCAP1_GATE] = ma35d1_clk_gate(dev, "ccap1_gate", "ccap1_div", + clk_base + REG_CLK_SYSCLK0, 30); + + hws[PDMA0_GATE] = ma35d1_clk_gate(dev, "pdma0_gate", "hclk0", + clk_base + REG_CLK_SYSCLK1, 0); + hws[PDMA1_GATE] = ma35d1_clk_gate(dev, "pdma1_gate", "hclk0", + clk_base + REG_CLK_SYSCLK1, 1); + hws[PDMA2_GATE] = ma35d1_clk_gate(dev, "pdma2_gate", "hclk0", + clk_base + REG_CLK_SYSCLK1, 2); + hws[PDMA3_GATE] = ma35d1_clk_gate(dev, "pdma3_gate", "hclk0", + clk_base + REG_CLK_SYSCLK1, 3); + + hws[WH0_GATE] = ma35d1_clk_gate(dev, "wh0_gate", "hclk0", + clk_base + REG_CLK_SYSCLK1, 4); + hws[WH1_GATE] = ma35d1_clk_gate(dev, "wh1_gate", "hclk0", + clk_base + REG_CLK_SYSCLK1, 5); + + hws[HWS_GATE] = ma35d1_clk_gate(dev, "hws_gate", "hclk0", + clk_base + REG_CLK_SYSCLK1, 6); + + hws[EBI_GATE] = ma35d1_clk_gate(dev, "ebi_gate", "hclk0", + clk_base + REG_CLK_SYSCLK1, 7); + + hws[SRAM0_GATE] = ma35d1_clk_gate(dev, "sram0_gate", "hclk0", + clk_base + REG_CLK_SYSCLK1, 8); + hws[SRAM1_GATE] = ma35d1_clk_gate(dev, "sram1_gate", "hclk0", + clk_base + REG_CLK_SYSCLK1, 9); + + hws[ROM_GATE] = ma35d1_clk_gate(dev, "rom_gate", "hclk0", + clk_base + REG_CLK_SYSCLK1, 10); + + hws[TRA_GATE] = ma35d1_clk_gate(dev, "tra_gate", "hclk0", + clk_base + REG_CLK_SYSCLK1, 11); + + hws[DBG_MUX] = ma35d1_clk_mux(dev, "dbg_mux", clk_base + REG_CLK_CLKSEL0, + 27, 1, dbg_sel_clks, ARRAY_SIZE(dbg_sel_clks)); + hws[DBG_GATE] = ma35d1_clk_gate(dev, "dbg_gate", "hclk0", + clk_base + REG_CLK_SYSCLK1, 12); + + hws[CKO_MUX] = ma35d1_clk_mux(dev, "cko_mux", clk_base + REG_CLK_CLKSEL4, + 24, 4, cko_sel_clks, ARRAY_SIZE(cko_sel_clks)); + hws[CKO_DIV] = ma35d1_clk_divider_pow2(dev, "cko_div", "cko_mux", + clk_base + REG_CLK_CLKOCTL, 0, 4); + hws[CKO_GATE] = ma35d1_clk_gate(dev, "cko_gate", "cko_div", + clk_base + REG_CLK_SYSCLK1, 13); + + hws[GTMR_GATE] = ma35d1_clk_gate(dev, "gtmr_gate", "hirc", + clk_base + REG_CLK_SYSCLK1, 14); + + hws[GPA_GATE] = ma35d1_clk_gate(dev, "gpa_gate", "hclk0", + clk_base + REG_CLK_SYSCLK1, 16); + hws[GPB_GATE] = ma35d1_clk_gate(dev, "gpb_gate", "hclk0", + clk_base + REG_CLK_SYSCLK1, 17); + hws[GPC_GATE] = ma35d1_clk_gate(dev, "gpc_gate", "hclk0", + clk_base + REG_CLK_SYSCLK1, 18); + hws[GPD_GATE] = ma35d1_clk_gate(dev, "gpd_gate", "hclk0", + clk_base + REG_CLK_SYSCLK1, 19); + hws[GPE_GATE] = ma35d1_clk_gate(dev, "gpe_gate", "hclk0", + clk_base + REG_CLK_SYSCLK1, 20); + hws[GPF_GATE] = ma35d1_clk_gate(dev, "gpf_gate", "hclk0", + clk_base + REG_CLK_SYSCLK1, 21); + hws[GPG_GATE] = ma35d1_clk_gate(dev, "gpg_gate", "hclk0", + clk_base + REG_CLK_SYSCLK1, 22); + hws[GPH_GATE] = ma35d1_clk_gate(dev, "gph_gate", "hclk0", + clk_base + REG_CLK_SYSCLK1, 23); + hws[GPI_GATE] = ma35d1_clk_gate(dev, "gpi_gate", "hclk0", + clk_base + REG_CLK_SYSCLK1, 24); + hws[GPJ_GATE] = ma35d1_clk_gate(dev, "gpj_gate", "hclk0", + clk_base + REG_CLK_SYSCLK1, 25); + hws[GPK_GATE] = ma35d1_clk_gate(dev, "gpk_gate", "hclk0", + clk_base + REG_CLK_SYSCLK1, 26); + hws[GPL_GATE] = ma35d1_clk_gate(dev, "gpl_gate", "hclk0", + clk_base + REG_CLK_SYSCLK1, 27); + hws[GPM_GATE] = ma35d1_clk_gate(dev, "gpm_gate", "hclk0", + clk_base + REG_CLK_SYSCLK1, 28); + hws[GPN_GATE] = ma35d1_clk_gate(dev, "gpn_gate", "hclk0", + clk_base + REG_CLK_SYSCLK1, 29); + + hws[TMR0_MUX] = ma35d1_clk_mux(dev, "tmr0_mux", clk_base + REG_CLK_CLKSEL1, + 0, 3, timer0_sel_clks, + ARRAY_SIZE(timer0_sel_clks)); + hws[TMR0_GATE] = ma35d1_clk_gate(dev, "tmr0_gate", "tmr0_mux", + clk_base + REG_CLK_APBCLK0, 0); + hws[TMR1_MUX] = ma35d1_clk_mux(dev, "tmr1_mux", clk_base + REG_CLK_CLKSEL1, + 4, 3, timer1_sel_clks, + ARRAY_SIZE(timer1_sel_clks)); + hws[TMR1_GATE] = ma35d1_clk_gate(dev, "tmr1_gate", "tmr1_mux", + clk_base + REG_CLK_APBCLK0, 1); + hws[TMR2_MUX] = ma35d1_clk_mux(dev, "tmr2_mux", clk_base + REG_CLK_CLKSEL1, + 8, 3, timer2_sel_clks, + ARRAY_SIZE(timer2_sel_clks)); + hws[TMR2_GATE] = ma35d1_clk_gate(dev, "tmr2_gate", "tmr2_mux", + clk_base + REG_CLK_APBCLK0, 2); + hws[TMR3_MUX] = ma35d1_clk_mux(dev, "tmr3_mux", clk_base + REG_CLK_CLKSEL1, + 12, 3, timer3_sel_clks, + ARRAY_SIZE(timer3_sel_clks)); + hws[TMR3_GATE] = ma35d1_clk_gate(dev, "tmr3_gate", "tmr3_mux", + clk_base + REG_CLK_APBCLK0, 3); + hws[TMR4_MUX] = ma35d1_clk_mux(dev, "tmr4_mux", clk_base + REG_CLK_CLKSEL1, + 16, 3, timer4_sel_clks, + ARRAY_SIZE(timer4_sel_clks)); + hws[TMR4_GATE] = ma35d1_clk_gate(dev, "tmr4_gate", "tmr4_mux", + clk_base + REG_CLK_APBCLK0, 4); + hws[TMR5_MUX] = ma35d1_clk_mux(dev, "tmr5_mux", clk_base + REG_CLK_CLKSEL1, + 20, 3, timer5_sel_clks, + ARRAY_SIZE(timer5_sel_clks)); + hws[TMR5_GATE] = ma35d1_clk_gate(dev, "tmr5_gate", "tmr5_mux", + clk_base + REG_CLK_APBCLK0, 5); + hws[TMR6_MUX] = ma35d1_clk_mux(dev, "tmr6_mux", clk_base + REG_CLK_CLKSEL1, + 24, 3, timer6_sel_clks, + ARRAY_SIZE(timer6_sel_clks)); + hws[TMR6_GATE] = ma35d1_clk_gate(dev, "tmr6_gate", "tmr6_mux", + clk_base + REG_CLK_APBCLK0, 6); + hws[TMR7_MUX] = ma35d1_clk_mux(dev, "tmr7_mux", clk_base + REG_CLK_CLKSEL1, + 28, 3, timer7_sel_clks, + ARRAY_SIZE(timer7_sel_clks)); + hws[TMR7_GATE] = ma35d1_clk_gate(dev, "tmr7_gate", "tmr7_mux", + clk_base + REG_CLK_APBCLK0, 7); + hws[TMR8_MUX] = ma35d1_clk_mux(dev, "tmr8_mux", clk_base + REG_CLK_CLKSEL2, + 0, 3, timer8_sel_clks, + ARRAY_SIZE(timer8_sel_clks)); + hws[TMR8_GATE] = ma35d1_clk_gate(dev, "tmr8_gate", "tmr8_mux", + clk_base + REG_CLK_APBCLK0, 8); + hws[TMR9_MUX] = ma35d1_clk_mux(dev, "tmr9_mux", clk_base + REG_CLK_CLKSEL2, + 4, 3, timer9_sel_clks, + ARRAY_SIZE(timer9_sel_clks)); + hws[TMR9_GATE] = ma35d1_clk_gate(dev, "tmr9_gate", "tmr9_mux", + clk_base + REG_CLK_APBCLK0, 9); + hws[TMR10_MUX] = ma35d1_clk_mux(dev, "tmr10_mux", clk_base + REG_CLK_CLKSEL2, + 8, 3, timer10_sel_clks, + ARRAY_SIZE(timer10_sel_clks)); + hws[TMR10_GATE] = ma35d1_clk_gate(dev, "tmr10_gate", "tmr10_mux", + clk_base + REG_CLK_APBCLK0, 10); + hws[TMR11_MUX] = ma35d1_clk_mux(dev, "tmr11_mux", clk_base + REG_CLK_CLKSEL2, + 12, 3, timer11_sel_clks, + ARRAY_SIZE(timer11_sel_clks)); + hws[TMR11_GATE] = ma35d1_clk_gate(dev, "tmr11_gate", "tmr11_mux", + clk_base + REG_CLK_APBCLK0, 11); + + hws[UART0_MUX] = ma35d1_clk_mux(dev, "uart0_mux", clk_base + REG_CLK_CLKSEL2, + 16, 2, uart_sel_clks, ARRAY_SIZE(uart_sel_clks)); + hws[UART0_DIV] = ma35d1_clk_divider(dev, "uart0_div", "uart0_mux", + clk_base + REG_CLK_CLKDIV1, + 16, 4); + hws[UART0_GATE] = ma35d1_clk_gate(dev, "uart0_gate", "uart0_div", + clk_base + REG_CLK_APBCLK0, 12); + hws[UART1_MUX] = ma35d1_clk_mux(dev, "uart1_mux", clk_base + REG_CLK_CLKSEL2, + 18, 2, uart_sel_clks, ARRAY_SIZE(uart_sel_clks)); + hws[UART1_DIV] = ma35d1_clk_divider(dev, "uart1_div", "uart1_mux", + clk_base + REG_CLK_CLKDIV1, + 20, 4); + hws[UART1_GATE] = ma35d1_clk_gate(dev, "uart1_gate", "uart1_div", + clk_base + REG_CLK_APBCLK0, 13); + hws[UART2_MUX] = ma35d1_clk_mux(dev, "uart2_mux", clk_base + REG_CLK_CLKSEL2, + 20, 2, uart_sel_clks, ARRAY_SIZE(uart_sel_clks)); + hws[UART2_DIV] = ma35d1_clk_divider(dev, "uart2_div", "uart2_mux", + clk_base + REG_CLK_CLKDIV1, + 24, 4); + hws[UART2_GATE] = ma35d1_clk_gate(dev, "uart2_gate", "uart2_div", + clk_base + REG_CLK_APBCLK0, 14); + hws[UART3_MUX] = ma35d1_clk_mux(dev, "uart3_mux", clk_base + REG_CLK_CLKSEL2, + 22, 2, uart_sel_clks, ARRAY_SIZE(uart_sel_clks)); + hws[UART3_DIV] = ma35d1_clk_divider(dev, "uart3_div", "uart3_mux", + clk_base + REG_CLK_CLKDIV1, + 28, 4); + hws[UART3_GATE] = ma35d1_clk_gate(dev, "uart3_gate", "uart3_div", + clk_base + REG_CLK_APBCLK0, 15); + hws[UART4_MUX] = ma35d1_clk_mux(dev, "uart4_mux", clk_base + REG_CLK_CLKSEL2, + 24, 2, uart_sel_clks, ARRAY_SIZE(uart_sel_clks)); + hws[UART4_DIV] = ma35d1_clk_divider(dev, "uart4_div", "uart4_mux", + clk_base + REG_CLK_CLKDIV2, + 0, 4); + hws[UART4_GATE] = ma35d1_clk_gate(dev, "uart4_gate", "uart4_div", + clk_base + REG_CLK_APBCLK0, 16); + hws[UART5_MUX] = ma35d1_clk_mux(dev, "uart5_mux", clk_base + REG_CLK_CLKSEL2, + 26, 2, uart_sel_clks, ARRAY_SIZE(uart_sel_clks)); + hws[UART5_DIV] = ma35d1_clk_divider(dev, "uart5_div", "uart5_mux", + clk_base + REG_CLK_CLKDIV2, + 4, 4); + hws[UART5_GATE] = ma35d1_clk_gate(dev, "uart5_gate", "uart5_div", + clk_base + REG_CLK_APBCLK0, 17); + hws[UART6_MUX] = ma35d1_clk_mux(dev, "uart6_mux", clk_base + REG_CLK_CLKSEL2, + 28, 2, uart_sel_clks, ARRAY_SIZE(uart_sel_clks)); + hws[UART6_DIV] = ma35d1_clk_divider(dev, "uart6_div", "uart6_mux", + clk_base + REG_CLK_CLKDIV2, + 8, 4); + hws[UART6_GATE] = ma35d1_clk_gate(dev, "uart6_gate", "uart6_div", + clk_base + REG_CLK_APBCLK0, 18); + hws[UART7_MUX] = ma35d1_clk_mux(dev, "uart7_mux", clk_base + REG_CLK_CLKSEL2, + 30, 2, uart_sel_clks, ARRAY_SIZE(uart_sel_clks)); + hws[UART7_DIV] = ma35d1_clk_divider(dev, "uart7_div", "uart7_mux", + clk_base + REG_CLK_CLKDIV2, + 12, 4); + hws[UART7_GATE] = ma35d1_clk_gate(dev, "uart7_gate", "uart7_div", + clk_base + REG_CLK_APBCLK0, 19); + hws[UART8_MUX] = ma35d1_clk_mux(dev, "uart8_mux", clk_base + REG_CLK_CLKSEL3, + 0, 2, uart_sel_clks, ARRAY_SIZE(uart_sel_clks)); + hws[UART8_DIV] = ma35d1_clk_divider(dev, "uart8_div", "uart8_mux", + clk_base + REG_CLK_CLKDIV2, + 16, 4); + hws[UART8_GATE] = ma35d1_clk_gate(dev, "uart8_gate", "uart8_div", + clk_base + REG_CLK_APBCLK0, 20); + hws[UART9_MUX] = ma35d1_clk_mux(dev, "uart9_mux", clk_base + REG_CLK_CLKSEL3, + 2, 2, uart_sel_clks, ARRAY_SIZE(uart_sel_clks)); + hws[UART9_DIV] = ma35d1_clk_divider(dev, "uart9_div", "uart9_mux", + clk_base + REG_CLK_CLKDIV2, + 20, 4); + hws[UART9_GATE] = ma35d1_clk_gate(dev, "uart9_gate", "uart9_div", + clk_base + REG_CLK_APBCLK0, 21); + hws[UART10_MUX] = ma35d1_clk_mux(dev, "uart10_mux", clk_base + REG_CLK_CLKSEL3, + 4, 2, uart_sel_clks, ARRAY_SIZE(uart_sel_clks)); + hws[UART10_DIV] = ma35d1_clk_divider(dev, "uart10_div", "uart10_mux", + clk_base + REG_CLK_CLKDIV2, + 24, 4); + hws[UART10_GATE] = ma35d1_clk_gate(dev, "uart10_gate", "uart10_div", + clk_base + REG_CLK_APBCLK0, 22); + hws[UART11_MUX] = ma35d1_clk_mux(dev, "uart11_mux", clk_base + REG_CLK_CLKSEL3, + 6, 2, uart_sel_clks, ARRAY_SIZE(uart_sel_clks)); + hws[UART11_DIV] = ma35d1_clk_divider(dev, "uart11_div", "uart11_mux", + clk_base + REG_CLK_CLKDIV2, + 28, 4); + hws[UART11_GATE] = ma35d1_clk_gate(dev, "uart11_gate", "uart11_div", + clk_base + REG_CLK_APBCLK0, 23); + hws[UART12_MUX] = ma35d1_clk_mux(dev, "uart12_mux", clk_base + REG_CLK_CLKSEL3, + 8, 2, uart_sel_clks, ARRAY_SIZE(uart_sel_clks)); + hws[UART12_DIV] = ma35d1_clk_divider(dev, "uart12_div", "uart12_mux", + clk_base + REG_CLK_CLKDIV3, + 0, 4); + hws[UART12_GATE] = ma35d1_clk_gate(dev, "uart12_gate", "uart12_div", + clk_base + REG_CLK_APBCLK0, 24); + hws[UART13_MUX] = ma35d1_clk_mux(dev, "uart13_mux", clk_base + REG_CLK_CLKSEL3, + 10, 2, uart_sel_clks, ARRAY_SIZE(uart_sel_clks)); + hws[UART13_DIV] = ma35d1_clk_divider(dev, "uart13_div", "uart13_mux", + clk_base + REG_CLK_CLKDIV3, + 4, 4); + hws[UART13_GATE] = ma35d1_clk_gate(dev, "uart13_gate", "uart13_div", + clk_base + REG_CLK_APBCLK0, 25); + hws[UART14_MUX] = ma35d1_clk_mux(dev, "uart14_mux", clk_base + REG_CLK_CLKSEL3, + 12, 2, uart_sel_clks, ARRAY_SIZE(uart_sel_clks)); + hws[UART14_DIV] = ma35d1_clk_divider(dev, "uart14_div", "uart14_mux", + clk_base + REG_CLK_CLKDIV3, + 8, 4); + hws[UART14_GATE] = ma35d1_clk_gate(dev, "uart14_gate", "uart14_div", + clk_base + REG_CLK_APBCLK0, 26); + hws[UART15_MUX] = ma35d1_clk_mux(dev, "uart15_mux", clk_base + REG_CLK_CLKSEL3, + 14, 2, uart_sel_clks, ARRAY_SIZE(uart_sel_clks)); + hws[UART15_DIV] = ma35d1_clk_divider(dev, "uart15_div", "uart15_mux", + clk_base + REG_CLK_CLKDIV3, + 12, 4); + hws[UART15_GATE] = ma35d1_clk_gate(dev, "uart15_gate", "uart15_div", + clk_base + REG_CLK_APBCLK0, 27); + hws[UART16_MUX] = ma35d1_clk_mux(dev, "uart16_mux", clk_base + REG_CLK_CLKSEL3, + 16, 2, uart_sel_clks, ARRAY_SIZE(uart_sel_clks)); + hws[UART16_DIV] = ma35d1_clk_divider(dev, "uart16_div", "uart16_mux", + clk_base + REG_CLK_CLKDIV3, + 16, 4); + hws[UART16_GATE] = ma35d1_clk_gate(dev, "uart16_gate", "uart16_div", + clk_base + REG_CLK_APBCLK0, 28); + + hws[RTC_GATE] = ma35d1_clk_gate(dev, "rtc_gate", "lxt", + clk_base + REG_CLK_APBCLK0, 29); + hws[DDR_GATE] = ma35d1_clk_gate(dev, "ddr_gate", "ddrpll", + clk_base + REG_CLK_APBCLK0, 30); + + hws[KPI_MUX] = ma35d1_clk_mux(dev, "kpi_mux", clk_base + REG_CLK_CLKSEL4, + 30, 1, kpi_sel_clks, ARRAY_SIZE(kpi_sel_clks)); + hws[KPI_DIV] = ma35d1_clk_divider(dev, "kpi_div", "kpi_mux", + clk_base + REG_CLK_CLKDIV4, + 24, 8); + hws[KPI_GATE] = ma35d1_clk_gate(dev, "kpi_gate", "kpi_div", + clk_base + REG_CLK_APBCLK0, 31); + + hws[I2C0_GATE] = ma35d1_clk_gate(dev, "i2c0_gate", "pclk0", + clk_base + REG_CLK_APBCLK1, 0); + hws[I2C1_GATE] = ma35d1_clk_gate(dev, "i2c1_gate", "pclk1", + clk_base + REG_CLK_APBCLK1, 1); + hws[I2C2_GATE] = ma35d1_clk_gate(dev, "i2c2_gate", "pclk2", + clk_base + REG_CLK_APBCLK1, 2); + hws[I2C3_GATE] = ma35d1_clk_gate(dev, "i2c3_gate", "pclk0", + clk_base + REG_CLK_APBCLK1, 3); + hws[I2C4_GATE] = ma35d1_clk_gate(dev, "i2c4_gate", "pclk1", + clk_base + REG_CLK_APBCLK1, 4); + hws[I2C5_GATE] = ma35d1_clk_gate(dev, "i2c5_gate", "pclk2", + clk_base + REG_CLK_APBCLK1, 5); + + hws[QSPI0_MUX] = ma35d1_clk_mux(dev, "qspi0_mux", clk_base + REG_CLK_CLKSEL4, + 8, 2, qspi0_sel_clks, ARRAY_SIZE(qspi0_sel_clks)); + hws[QSPI0_GATE] = ma35d1_clk_gate(dev, "qspi0_gate", "qspi0_mux", + clk_base + REG_CLK_APBCLK1, 6); + hws[QSPI1_MUX] = ma35d1_clk_mux(dev, "qspi1_mux", clk_base + REG_CLK_CLKSEL4, + 10, 2, qspi1_sel_clks, ARRAY_SIZE(qspi1_sel_clks)); + hws[QSPI1_GATE] = ma35d1_clk_gate(dev, "qspi1_gate", "qspi1_mux", + clk_base + REG_CLK_APBCLK1, 7); + + hws[SMC0_MUX] = ma35d1_clk_mux(dev, "smc0_mux", clk_base + REG_CLK_CLKSEL4, + 28, 1, smc_sel_clks, ARRAY_SIZE(smc_sel_clks)); + hws[SMC0_DIV] = ma35d1_clk_divider(dev, "smc0_div", "smc0_mux", + clk_base + REG_CLK_CLKDIV1, + 0, 4); + hws[SMC0_GATE] = ma35d1_clk_gate(dev, "smc0_gate", "smc0_div", + clk_base + REG_CLK_APBCLK1, 12); + hws[SMC1_MUX] = ma35d1_clk_mux(dev, "smc1_mux", clk_base + REG_CLK_CLKSEL4, + 29, 1, smc_sel_clks, ARRAY_SIZE(smc_sel_clks)); + hws[SMC1_DIV] = ma35d1_clk_divider(dev, "smc1_div", "smc1_mux", + clk_base + REG_CLK_CLKDIV1, + 4, 4); + hws[SMC1_GATE] = ma35d1_clk_gate(dev, "smc1_gate", "smc1_div", + clk_base + REG_CLK_APBCLK1, 13); + + hws[WDT0_MUX] = ma35d1_clk_mux(dev, "wdt0_mux", clk_base + REG_CLK_CLKSEL3, + 20, 2, wdt0_sel_clks, ARRAY_SIZE(wdt0_sel_clks)); + hws[WDT0_GATE] = ma35d1_clk_gate(dev, "wdt0_gate", "wdt0_mux", + clk_base + REG_CLK_APBCLK1, 16); + hws[WDT1_MUX] = ma35d1_clk_mux(dev, "wdt1_mux", clk_base + REG_CLK_CLKSEL3, + 24, 2, wdt1_sel_clks, ARRAY_SIZE(wdt1_sel_clks)); + hws[WDT1_GATE] = ma35d1_clk_gate(dev, "wdt1_gate", "wdt1_mux", + clk_base + REG_CLK_APBCLK1, 17); + hws[WDT2_MUX] = ma35d1_clk_mux(dev, "wdt2_mux", clk_base + REG_CLK_CLKSEL3, + 28, 2, wdt2_sel_clks, ARRAY_SIZE(wdt2_sel_clks)); + hws[WDT2_GATE] = ma35d1_clk_gate(dev, "wdt2_gate", "wdt2_mux", + clk_base + REG_CLK_APBCLK1, 18); + + hws[WWDT0_MUX] = ma35d1_clk_mux(dev, "wwdt0_mux", clk_base + REG_CLK_CLKSEL3, + 22, 2, wwdt0_sel_clks, ARRAY_SIZE(wwdt0_sel_clks)); + hws[WWDT1_MUX] = ma35d1_clk_mux(dev, "wwdt1_mux", clk_base + REG_CLK_CLKSEL3, + 26, 2, wwdt1_sel_clks, ARRAY_SIZE(wwdt1_sel_clks)); + hws[WWDT2_MUX] = ma35d1_clk_mux(dev, "wwdt2_mux", clk_base + REG_CLK_CLKSEL3, + 30, 2, wwdt2_sel_clks, ARRAY_SIZE(wwdt2_sel_clks)); + + hws[EPWM0_GATE] = ma35d1_clk_gate(dev, "epwm0_gate", "pclk1", + clk_base + REG_CLK_APBCLK1, 24); + hws[EPWM1_GATE] = ma35d1_clk_gate(dev, "epwm1_gate", "pclk2", + clk_base + REG_CLK_APBCLK1, 25); + hws[EPWM2_GATE] = ma35d1_clk_gate(dev, "epwm2_gate", "pclk1", + clk_base + REG_CLK_APBCLK1, 26); + + hws[I2S0_MUX] = ma35d1_clk_mux(dev, "i2s0_mux", clk_base + REG_CLK_CLKSEL4, + 12, 2, i2s0_sel_clks, ARRAY_SIZE(i2s0_sel_clks)); + hws[I2S0_GATE] = ma35d1_clk_gate(dev, "i2s0_gate", "i2s0_mux", + clk_base + REG_CLK_APBCLK2, 0); + hws[I2S1_MUX] = ma35d1_clk_mux(dev, "i2s1_mux", clk_base + REG_CLK_CLKSEL4, + 14, 2, i2s1_sel_clks, ARRAY_SIZE(i2s1_sel_clks)); + hws[I2S1_GATE] = ma35d1_clk_gate(dev, "i2s1_gate", "i2s1_mux", + clk_base + REG_CLK_APBCLK2, 1); + + hws[SSMCC_GATE] = ma35d1_clk_gate(dev, "ssmcc_gate", "pclk3", + clk_base + REG_CLK_APBCLK2, 2); + hws[SSPCC_GATE] = ma35d1_clk_gate(dev, "sspcc_gate", "pclk3", + clk_base + REG_CLK_APBCLK2, 3); + + hws[SPI0_MUX] = ma35d1_clk_mux(dev, "spi0_mux", clk_base + REG_CLK_CLKSEL4, + 0, 2, spi0_sel_clks, ARRAY_SIZE(spi0_sel_clks)); + hws[SPI0_GATE] = ma35d1_clk_gate(dev, "spi0_gate", "spi0_mux", + clk_base + REG_CLK_APBCLK2, 4); + hws[SPI1_MUX] = ma35d1_clk_mux(dev, "spi1_mux", clk_base + REG_CLK_CLKSEL4, + 2, 2, spi1_sel_clks, ARRAY_SIZE(spi1_sel_clks)); + hws[SPI1_GATE] = ma35d1_clk_gate(dev, "spi1_gate", "spi1_mux", + clk_base + REG_CLK_APBCLK2, 5); + hws[SPI2_MUX] = ma35d1_clk_mux(dev, "spi2_mux", clk_base + REG_CLK_CLKSEL4, + 4, 2, spi2_sel_clks, ARRAY_SIZE(spi2_sel_clks)); + hws[SPI2_GATE] = ma35d1_clk_gate(dev, "spi2_gate", "spi2_mux", + clk_base + REG_CLK_APBCLK2, 6); + hws[SPI3_MUX] = ma35d1_clk_mux(dev, "spi3_mux", clk_base + REG_CLK_CLKSEL4, + 6, 2, spi3_sel_clks, ARRAY_SIZE(spi3_sel_clks)); + hws[SPI3_GATE] = ma35d1_clk_gate(dev, "spi3_gate", "spi3_mux", + clk_base + REG_CLK_APBCLK2, 7); + + hws[ECAP0_GATE] = ma35d1_clk_gate(dev, "ecap0_gate", "pclk1", + clk_base + REG_CLK_APBCLK2, 8); + hws[ECAP1_GATE] = ma35d1_clk_gate(dev, "ecap1_gate", "pclk2", + clk_base + REG_CLK_APBCLK2, 9); + hws[ECAP2_GATE] = ma35d1_clk_gate(dev, "ecap2_gate", "pclk1", + clk_base + REG_CLK_APBCLK2, 10); + + hws[QEI0_GATE] = ma35d1_clk_gate(dev, "qei0_gate", "pclk1", + clk_base + REG_CLK_APBCLK2, 12); + hws[QEI1_GATE] = ma35d1_clk_gate(dev, "qei1_gate", "pclk2", + clk_base + REG_CLK_APBCLK2, 13); + hws[QEI2_GATE] = ma35d1_clk_gate(dev, "qei2_gate", "pclk1", + clk_base + REG_CLK_APBCLK2, 14); + + hws[ADC_DIV] = ma35d1_reg_adc_clkdiv(dev, "adc_div", hws[PCLK0], + &ma35d1_lock, 0, + clk_base + REG_CLK_CLKDIV4, + 4, 17, 0x1ffff); + hws[ADC_GATE] = ma35d1_clk_gate(dev, "adc_gate", "adc_div", + clk_base + REG_CLK_APBCLK2, 24); + + hws[EADC_DIV] = ma35d1_clk_divider_table(dev, "eadc_div", "pclk2", + clk_base + REG_CLK_CLKDIV4, + 0, 4, eadc_div_table); + hws[EADC_GATE] = ma35d1_clk_gate(dev, "eadc_gate", "eadc_div", + clk_base + REG_CLK_APBCLK2, 25); + + return devm_of_clk_add_hw_provider(dev, + of_clk_hw_onecell_get, + ma35d1_hw_data); +} + +static const struct of_device_id ma35d1_clk_of_match[] = { + { .compatible = "nuvoton,ma35d1-clk" }, + { } +}; +MODULE_DEVICE_TABLE(of, ma35d1_clk_of_match); + +static struct platform_driver ma35d1_clk_driver = { + .probe = ma35d1_clocks_probe, + .driver = { + .name = "ma35d1-clk", + .of_match_table = ma35d1_clk_of_match, + }, +}; + +static int __init ma35d1_clocks_init(void) +{ + return platform_driver_register(&ma35d1_clk_driver); +} + +postcore_initcall(ma35d1_clocks_init); + +MODULE_AUTHOR("Chi-Fang Li "); +MODULE_DESCRIPTION("NUVOTON MA35D1 Clock Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/nuvoton/clk-ma35d1.h b/drivers/clk/nuvoton/clk-ma35d1.h new file mode 100644 index 0000000000000000000000000000000000000000..3adee440f60a359e1382944f4bb7f99df49778e7 --- /dev/null +++ b/drivers/clk/nuvoton/clk-ma35d1.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (C) 2023 Nuvoton Technology Corp. + * Author: Chi-Fang Li + */ + +#ifndef __DRV_CLK_NUVOTON_MA35D1_H +#define __DRV_CLK_NUVOTON_MA35D1_H + +struct clk_hw *ma35d1_reg_clk_pll(struct device *dev, u32 id, u8 u8mode, const char *name, + struct clk_hw *parent_hw, void __iomem *base); + +struct clk_hw *ma35d1_reg_adc_clkdiv(struct device *dev, const char *name, + struct clk_hw *parent_hw, spinlock_t *lock, + unsigned long flags, void __iomem *reg, + u8 shift, u8 width, u32 mask_bit); + +#endif /* __DRV_CLK_NUVOTON_MA35D1_H */ diff --git a/drivers/clk/pxa/clk-pxa.c b/drivers/clk/pxa/clk-pxa.c index 374098ebbf2b6be139212c904d0ff5adb04cbd7e..ebee2afd05de2d1e1ae05e171cc9d22b906382f3 100644 --- a/drivers/clk/pxa/clk-pxa.c +++ b/drivers/clk/pxa/clk-pxa.c @@ -82,6 +82,7 @@ static u8 cken_get_parent(struct clk_hw *hw) } static const struct clk_ops cken_mux_ops = { + .determine_rate = clk_hw_determine_rate_no_reparent, .get_parent = cken_get_parent, .set_parent = dummy_clk_set_parent, }; diff --git a/drivers/clk/pxa/clk-pxa25x.c b/drivers/clk/pxa/clk-pxa25x.c index 93d5907b8530134625692047917652fe2c935495..0a4da519d704cca4291f6739cf21b9dc5f961569 100644 --- a/drivers/clk/pxa/clk-pxa25x.c +++ b/drivers/clk/pxa/clk-pxa25x.c @@ -11,10 +11,12 @@ */ #include #include +#include #include #include #include #include +#include #include #include "clk-pxa.h" diff --git a/drivers/clk/pxa/clk-pxa27x.c b/drivers/clk/pxa/clk-pxa27x.c index 116c6ac666e3c0b14c1f42a0c43143ceb84b56fb..2bea89874ec16bb924245bd67c648f5d32589b89 100644 --- a/drivers/clk/pxa/clk-pxa27x.c +++ b/drivers/clk/pxa/clk-pxa27x.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include "clk-pxa.h" @@ -99,7 +100,7 @@ unsigned int pxa27x_get_clk_frequency_khz(int info) return (unsigned int)clks[0] / KHz; } -bool pxa27x_is_ppll_disabled(void) +static bool pxa27x_is_ppll_disabled(void) { unsigned long ccsr = readl(clk_regs + CCSR); diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig index 12be3e2371b3062579454ec360c1e6d1a688938d..263e55d75e3f5c0ce67b3f207e4e57be965c104a 100644 --- a/drivers/clk/qcom/Kconfig +++ b/drivers/clk/qcom/Kconfig @@ -48,6 +48,7 @@ config QCOM_CLK_APCS_MSM8916 config QCOM_CLK_APCC_MSM8996 tristate "MSM8996 CPU Clock Controller" select QCOM_KRYO_L2_ACCESSORS + select INTERCONNECT_CLK if INTERCONNECT depends on ARM64 help Support for the CPU clock controller on msm8996 devices. @@ -57,6 +58,7 @@ config QCOM_CLK_APCC_MSM8996 config QCOM_CLK_APCS_SDX55 tristate "SDX55 and SDX65 APCS Clock Controller" depends on QCOM_APCS_IPC || COMPILE_TEST + depends on ARM || COMPILE_TEST help Support for the APCS Clock Controller on SDX55, SDX65 platforms. The APCS is managing the mux and divider which feeds the CPUs. @@ -100,6 +102,7 @@ config QCOM_CLK_RPMH config APQ_GCC_8084 tristate "APQ8084 Global Clock Controller" + depends on ARM || COMPILE_TEST select QCOM_GDSC help Support for the global clock controller on apq8084 devices. @@ -108,6 +111,7 @@ config APQ_GCC_8084 config APQ_MMCC_8084 tristate "APQ8084 Multimedia Clock Controller" + depends on ARM || COMPILE_TEST select APQ_GCC_8084 select QCOM_GDSC help @@ -159,6 +163,7 @@ config IPQ_GCC_6018 config IPQ_GCC_806X tristate "IPQ806x Global Clock Controller" + depends on ARM || COMPILE_TEST help Support for the global clock controller on ipq806x devices. Say Y if you want to use peripheral devices such as UART, SPI, @@ -166,6 +171,7 @@ config IPQ_GCC_806X config IPQ_LCC_806X tristate "IPQ806x LPASS Clock Controller" + depends on ARM || COMPILE_TEST select IPQ_GCC_806X help Support for the LPASS clock controller on ipq806x devices. @@ -191,6 +197,7 @@ config IPQ_GCC_9574 config MSM_GCC_8660 tristate "MSM8660 Global Clock Controller" + depends on ARM || COMPILE_TEST help Support for the global clock controller on msm8660 devices. Say Y if you want to use peripheral devices such as UART, SPI, @@ -198,6 +205,7 @@ config MSM_GCC_8660 config MSM_GCC_8909 tristate "MSM8909 Global Clock Controller" + depends on ARM || COMPILE_TEST select QCOM_GDSC help Support for the global clock controller on msm8909 devices. @@ -232,6 +240,7 @@ config MSM_GCC_8939 config MSM_GCC_8960 tristate "APQ8064/MSM8960 Global Clock Controller" + depends on ARM || COMPILE_TEST help Support for the global clock controller on apq8064/msm8960 devices. Say Y if you want to use peripheral devices such as UART, SPI, @@ -239,6 +248,7 @@ config MSM_GCC_8960 config MSM_LCC_8960 tristate "APQ8064/MSM8960 LPASS Clock Controller" + depends on ARM || COMPILE_TEST select MSM_GCC_8960 help Support for the LPASS clock controller on apq8064/msm8960 devices. @@ -247,6 +257,7 @@ config MSM_LCC_8960 config MDM_GCC_9607 tristate "MDM9607 Global Clock Controller" + depends on ARM || COMPILE_TEST help Support for the global clock controller on mdm9607 devices. Say Y if you want to use peripheral devices such as UART, SPI, @@ -254,6 +265,7 @@ config MDM_GCC_9607 config MDM_GCC_9615 tristate "MDM9615 Global Clock Controller" + depends on ARM || COMPILE_TEST help Support for the global clock controller on mdm9615 devices. Say Y if you want to use peripheral devices such as UART, SPI, @@ -261,6 +273,7 @@ config MDM_GCC_9615 config MDM_LCC_9615 tristate "MDM9615 LPASS Clock Controller" + depends on ARM || COMPILE_TEST select MDM_GCC_9615 help Support for the LPASS clock controller on mdm9615 devices. @@ -269,6 +282,7 @@ config MDM_LCC_9615 config MSM_MMCC_8960 tristate "MSM8960 Multimedia Clock Controller" + depends on ARM || COMPILE_TEST select MSM_GCC_8960 help Support for the multimedia clock controller on msm8960 devices. @@ -285,6 +299,7 @@ config MSM_GCC_8953 config MSM_GCC_8974 tristate "MSM8974 Global Clock Controller" + depends on ARM || COMPILE_TEST select QCOM_GDSC help Support for the global clock controller on msm8974 devices. @@ -293,6 +308,7 @@ config MSM_GCC_8974 config MSM_MMCC_8974 tristate "MSM8974 Multimedia Clock Controller" + depends on ARM || COMPILE_TEST select MSM_GCC_8974 select QCOM_GDSC help @@ -393,6 +409,7 @@ config QCS_GCC_404 config SC_CAMCC_7180 tristate "SC7180 Camera Clock Controller" + depends on ARM64 || COMPILE_TEST select SC_GCC_7180 help Support for the camera clock controller on Qualcomm Technologies, Inc @@ -402,6 +419,7 @@ config SC_CAMCC_7180 config SC_CAMCC_7280 tristate "SC7280 Camera Clock Controller" + depends on ARM64 || COMPILE_TEST select SC_GCC_7280 help Support for the camera clock controller on Qualcomm Technologies, Inc @@ -411,6 +429,7 @@ config SC_CAMCC_7280 config SC_DISPCC_7180 tristate "SC7180 Display Clock Controller" + depends on ARM64 || COMPILE_TEST select SC_GCC_7180 help Support for the display clock controller on Qualcomm Technologies, Inc @@ -420,6 +439,7 @@ config SC_DISPCC_7180 config SC_DISPCC_7280 tristate "SC7280 Display Clock Controller" + depends on ARM64 || COMPILE_TEST select SC_GCC_7280 help Support for the display clock controller on Qualcomm Technologies, Inc. @@ -429,6 +449,7 @@ config SC_DISPCC_7280 config SC_DISPCC_8280XP tristate "SC8280XP Display Clock Controller" + depends on ARM64 || COMPILE_TEST select SC_GCC_8280XP help Support for the two display clock controllers on Qualcomm @@ -458,6 +479,7 @@ config SC_GCC_7180 tristate "SC7180 Global Clock Controller" select QCOM_GDSC depends on COMMON_CLK_QCOM + depends on ARM64 || COMPILE_TEST help Support for the global clock controller on SC7180 devices. Say Y if you want to use peripheral devices such as UART, SPI, @@ -467,6 +489,7 @@ config SC_GCC_7280 tristate "SC7280 Global Clock Controller" select QCOM_GDSC depends on COMMON_CLK_QCOM + depends on ARM64 || COMPILE_TEST help Support for the global clock controller on SC7280 devices. Say Y if you want to use peripheral devices such as UART, SPI, @@ -476,6 +499,7 @@ config SC_GCC_8180X tristate "SC8180X Global Clock Controller" select QCOM_GDSC depends on COMMON_CLK_QCOM + depends on ARM64 || COMPILE_TEST help Support for the global clock controller on SC8180X devices. Say Y if you want to use peripheral devices such as UART, SPI, @@ -485,6 +509,7 @@ config SC_GCC_8280XP tristate "SC8280XP Global Clock Controller" select QCOM_GDSC depends on COMMON_CLK_QCOM + depends on ARM64 || COMPILE_TEST help Support for the global clock controller on SC8280XP devices. Say Y if you want to use peripheral devices such as UART, SPI, @@ -492,6 +517,7 @@ config SC_GCC_8280XP config SC_GPUCC_7180 tristate "SC7180 Graphics Clock Controller" + depends on ARM64 || COMPILE_TEST select SC_GCC_7180 help Support for the graphics clock controller on SC7180 devices. @@ -500,6 +526,7 @@ config SC_GPUCC_7180 config SC_GPUCC_7280 tristate "SC7280 Graphics Clock Controller" + depends on ARM64 || COMPILE_TEST select SC_GCC_7280 help Support for the graphics clock controller on SC7280 devices. @@ -508,6 +535,7 @@ config SC_GPUCC_7280 config SC_GPUCC_8280XP tristate "SC8280XP Graphics Clock Controller" + depends on ARM64 || COMPILE_TEST select SC_GCC_8280XP help Support for the graphics clock controller on SC8280XP devices. @@ -516,14 +544,25 @@ config SC_GPUCC_8280XP config SC_LPASSCC_7280 tristate "SC7280 Low Power Audio Subsystem (LPASS) Clock Controller" + depends on ARM64 || COMPILE_TEST select SC_GCC_7280 help Support for the LPASS clock controller on SC7280 devices. Say Y if you want to use the LPASS branch clocks of the LPASS clock controller to reset the LPASS subsystem. +config SC_LPASSCC_8280XP + tristate "SC8280 Low Power Audio Subsystem (LPASS) Clock Controller" + depends on ARM64 || COMPILE_TEST + select SC_GCC_8280XP + help + Support for the LPASS clock controller on SC8280XP devices. + Say Y if you want to use the LPASS branch clocks of the LPASS clock + controller to reset the LPASS subsystem. + config SC_LPASS_CORECC_7180 tristate "SC7180 LPASS Core Clock Controller" + depends on ARM64 || COMPILE_TEST select SC_GCC_7180 help Support for the LPASS(Low Power Audio Subsystem) core clock controller @@ -533,6 +572,7 @@ config SC_LPASS_CORECC_7180 config SC_LPASS_CORECC_7280 tristate "SC7280 LPASS Core & Audio Clock Controller" + depends on ARM64 || COMPILE_TEST select SC_GCC_7280 select QCOM_GDSC help @@ -543,6 +583,7 @@ config SC_LPASS_CORECC_7280 config SC_MSS_7180 tristate "SC7180 Modem Clock Controller" + depends on ARM64 || COMPILE_TEST select SC_GCC_7180 help Support for the Modem Subsystem clock controller on Qualcomm @@ -552,6 +593,7 @@ config SC_MSS_7180 config SC_VIDEOCC_7180 tristate "SC7180 Video Clock Controller" + depends on ARM64 || COMPILE_TEST select SC_GCC_7180 help Support for the video clock controller on SC7180 devices. @@ -560,6 +602,7 @@ config SC_VIDEOCC_7180 config SC_VIDEOCC_7280 tristate "SC7280 Video Clock Controller" + depends on ARM64 || COMPILE_TEST select SC_GCC_7280 help Support for the video clock controller on SC7280 devices. @@ -568,6 +611,7 @@ config SC_VIDEOCC_7280 config SDM_CAMCC_845 tristate "SDM845 Camera Clock Controller" + depends on ARM64 || COMPILE_TEST select SDM_GCC_845 help Support for the camera clock controller on SDM845 devices. @@ -575,6 +619,7 @@ config SDM_CAMCC_845 config SDM_GCC_660 tristate "SDM660 Global Clock Controller" + depends on ARM64 || COMPILE_TEST select QCOM_GDSC help Support for the global clock controller on SDM660 devices. @@ -583,6 +628,7 @@ config SDM_GCC_660 config SDM_MMCC_660 tristate "SDM660 Multimedia Clock Controller" + depends on ARM64 || COMPILE_TEST select SDM_GCC_660 select QCOM_GDSC help @@ -592,6 +638,7 @@ config SDM_MMCC_660 config SDM_GPUCC_660 tristate "SDM660 Graphics Clock Controller" + depends on ARM64 || COMPILE_TEST select SDM_GCC_660 select QCOM_GDSC help @@ -623,6 +670,7 @@ config QDU_GCC_1000 config SDM_GCC_845 tristate "SDM845/SDM670 Global Clock Controller" + depends on ARM64 || COMPILE_TEST select QCOM_GDSC help Support for the global clock controller on SDM845 and SDM670 devices. @@ -631,6 +679,7 @@ config SDM_GCC_845 config SDM_GPUCC_845 tristate "SDM845 Graphics Clock Controller" + depends on ARM64 || COMPILE_TEST select SDM_GCC_845 help Support for the graphics clock controller on SDM845 devices. @@ -639,6 +688,7 @@ config SDM_GPUCC_845 config SDM_VIDEOCC_845 tristate "SDM845 Video Clock Controller" + depends on ARM64 || COMPILE_TEST select SDM_GCC_845 select QCOM_GDSC help @@ -648,6 +698,7 @@ config SDM_VIDEOCC_845 config SDM_DISPCC_845 tristate "SDM845 Display Clock Controller" + depends on ARM64 || COMPILE_TEST select SDM_GCC_845 help Support for the display clock controller on Qualcomm Technologies, Inc @@ -657,6 +708,7 @@ config SDM_DISPCC_845 config SDM_LPASSCC_845 tristate "SDM845 Low Power Audio Subsystem (LPAAS) Clock Controller" + depends on ARM64 || COMPILE_TEST select SDM_GCC_845 help Support for the LPASS clock controller on SDM845 devices. @@ -665,6 +717,7 @@ config SDM_LPASSCC_845 config SDX_GCC_55 tristate "SDX55 Global Clock Controller" + depends on ARM || COMPILE_TEST select QCOM_GDSC help Support for the global clock controller on SDX55 devices. @@ -673,14 +726,24 @@ config SDX_GCC_55 config SDX_GCC_65 tristate "SDX65 Global Clock Controller" + depends on ARM || COMPILE_TEST select QCOM_GDSC help Support for the global clock controller on SDX65 devices. Say Y if you want to use peripheral devices such as UART, SPI, I2C, USB, SD/UFS, PCIe etc. +config SDX_GCC_75 + tristate "SDX75 Global Clock Controller" + select QCOM_GDSC + help + Support for the global clock controller on SDX75 devices. + Say Y if you want to use peripheral devices such as UART, + SPI, I2C, USB, SD/eMMC, PCIe etc. + config SM_CAMCC_6350 tristate "SM6350 Camera Clock Controller" + depends on ARM64 || COMPILE_TEST select SM_GCC_6350 help Support for the camera clock controller on SM6350 devices. @@ -688,6 +751,7 @@ config SM_CAMCC_6350 config SM_CAMCC_8250 tristate "SM8250 Camera Clock Controller" + depends on ARM64 || COMPILE_TEST select SM_GCC_8250 help Support for the camera clock controller on SM8250 devices. @@ -695,6 +759,7 @@ config SM_CAMCC_8250 config SM_CAMCC_8450 tristate "SM8450 Camera Clock Controller" + depends on ARM64 || COMPILE_TEST select SM_GCC_8450 help Support for the camera clock controller on SM8450 devices. @@ -702,6 +767,7 @@ config SM_CAMCC_8450 config SM_DISPCC_6115 tristate "SM6115 Display Clock Controller" + depends on ARM64 || COMPILE_TEST depends on SM_GCC_6115 help Support for the display clock controller on Qualcomm Technologies, Inc @@ -711,6 +777,7 @@ config SM_DISPCC_6115 config SM_DISPCC_6125 tristate "SM6125 Display Clock Controller" + depends on ARM64 || COMPILE_TEST depends on SM_GCC_6125 help Support for the display clock controller on Qualcomm Technologies, Inc @@ -720,6 +787,7 @@ config SM_DISPCC_6125 config SM_DISPCC_8250 tristate "SM8150/SM8250/SM8350 Display Clock Controller" + depends on ARM64 || COMPILE_TEST depends on SM_GCC_8150 || SM_GCC_8250 || SM_GCC_8350 help Support for the display clock controller on Qualcomm Technologies, Inc @@ -729,6 +797,7 @@ config SM_DISPCC_8250 config SM_DISPCC_6350 tristate "SM6350 Display Clock Controller" + depends on ARM64 || COMPILE_TEST depends on SM_GCC_6350 help Support for the display clock controller on Qualcomm Technologies, Inc @@ -738,6 +807,7 @@ config SM_DISPCC_6350 config SM_DISPCC_6375 tristate "SM6375 Display Clock Controller" + depends on ARM64 || COMPILE_TEST depends on SM_GCC_6375 help Support for the display clock controller on Qualcomm Technologies, Inc @@ -747,6 +817,7 @@ config SM_DISPCC_6375 config SM_DISPCC_8450 tristate "SM8450 Display Clock Controller" + depends on ARM64 || COMPILE_TEST depends on SM_GCC_8450 help Support for the display clock controller on Qualcomm Technologies, Inc @@ -756,6 +827,7 @@ config SM_DISPCC_8450 config SM_DISPCC_8550 tristate "SM8550 Display Clock Controller" + depends on ARM64 || COMPILE_TEST depends on SM_GCC_8550 help Support for the display clock controller on Qualcomm Technologies, Inc @@ -765,6 +837,7 @@ config SM_DISPCC_8550 config SM_GCC_6115 tristate "SM6115 and SM4250 Global Clock Controller" + depends on ARM64 || COMPILE_TEST select QCOM_GDSC help Support for the global clock controller on SM6115 and SM4250 devices. @@ -773,6 +846,7 @@ config SM_GCC_6115 config SM_GCC_6125 tristate "SM6125 Global Clock Controller" + depends on ARM64 || COMPILE_TEST help Support for the global clock controller on SM6125 devices. Say Y if you want to use peripheral devices such as UART, @@ -780,6 +854,7 @@ config SM_GCC_6125 config SM_GCC_6350 tristate "SM6350 Global Clock Controller" + depends on ARM64 || COMPILE_TEST select QCOM_GDSC help Support for the global clock controller on SM6350 devices. @@ -788,6 +863,7 @@ config SM_GCC_6350 config SM_GCC_6375 tristate "SM6375 Global Clock Controller" + depends on ARM64 || COMPILE_TEST select QCOM_GDSC help Support for the global clock controller on SM6375 devices. @@ -804,6 +880,7 @@ config SM_GCC_7150 config SM_GCC_8150 tristate "SM8150 Global Clock Controller" + depends on ARM64 || COMPILE_TEST help Support for the global clock controller on SM8150 devices. Say Y if you want to use peripheral devices such as UART, @@ -811,6 +888,7 @@ config SM_GCC_8150 config SM_GCC_8250 tristate "SM8250 Global Clock Controller" + depends on ARM64 || COMPILE_TEST select QCOM_GDSC help Support for the global clock controller on SM8250 devices. @@ -819,6 +897,7 @@ config SM_GCC_8250 config SM_GCC_8350 tristate "SM8350 Global Clock Controller" + depends on ARM64 || COMPILE_TEST select QCOM_GDSC help Support for the global clock controller on SM8350 devices. @@ -827,6 +906,7 @@ config SM_GCC_8350 config SM_GCC_8450 tristate "SM8450 Global Clock Controller" + depends on ARM64 || COMPILE_TEST select QCOM_GDSC help Support for the global clock controller on SM8450 devices. @@ -835,6 +915,7 @@ config SM_GCC_8450 config SM_GCC_8550 tristate "SM8550 Global Clock Controller" + depends on ARM64 || COMPILE_TEST select QCOM_GDSC help Support for the global clock controller on SM8550 devices. @@ -870,6 +951,7 @@ config SM_GPUCC_6375 config SM_GPUCC_6350 tristate "SM6350 Graphics Clock Controller" + depends on ARM64 || COMPILE_TEST select SM_GCC_6350 help Support for the graphics clock controller on SM6350 devices. @@ -878,6 +960,7 @@ config SM_GPUCC_6350 config SM_GPUCC_8150 tristate "SM8150 Graphics Clock Controller" + depends on ARM64 || COMPILE_TEST select SM_GCC_8150 help Support for the graphics clock controller on SM8150 devices. @@ -886,6 +969,7 @@ config SM_GPUCC_8150 config SM_GPUCC_8250 tristate "SM8250 Graphics Clock Controller" + depends on ARM64 || COMPILE_TEST select SM_GCC_8250 help Support for the graphics clock controller on SM8250 devices. @@ -894,14 +978,32 @@ config SM_GPUCC_8250 config SM_GPUCC_8350 tristate "SM8350 Graphics Clock Controller" + depends on ARM64 || COMPILE_TEST select SM_GCC_8350 help Support for the graphics clock controller on SM8350 devices. Say Y if you want to support graphics controller devices and functionality such as 3D graphics. +config SM_GPUCC_8450 + tristate "SM8450 Graphics Clock Controller" + select SM_GCC_8450 + help + Support for the graphics clock controller on SM8450 devices. + Say Y if you want to support graphics controller devices and + functionality such as 3D graphics. + +config SM_GPUCC_8550 + tristate "SM8550 Graphics Clock Controller" + select SM_GCC_8550 + help + Support for the graphics clock controller on SM8550 devices. + Say Y if you want to support graphics controller devices and + functionality such as 3D graphics. + config SM_TCSRCC_8550 tristate "SM8550 TCSR Clock Controller" + depends on ARM64 || COMPILE_TEST select QCOM_GDSC help Support for the TCSR clock controller on SM8550 devices. @@ -909,6 +1011,7 @@ config SM_TCSRCC_8550 config SM_VIDEOCC_8150 tristate "SM8150 Video Clock Controller" + depends on ARM64 || COMPILE_TEST select SM_GCC_8150 select QCOM_GDSC help @@ -918,6 +1021,7 @@ config SM_VIDEOCC_8150 config SM_VIDEOCC_8250 tristate "SM8250 Video Clock Controller" + depends on ARM64 || COMPILE_TEST select SM_GCC_8250 select QCOM_GDSC help @@ -925,6 +1029,25 @@ config SM_VIDEOCC_8250 Say Y if you want to support video devices and functionality such as video encode and decode. +config SM_VIDEOCC_8350 + tristate "SM8350 Video Clock Controller" + select SM_GCC_8350 + select QCOM_GDSC + help + Support for the video clock controller on SM8350 devices. + Say Y if you want to support video devices and functionality such as + video encode and decode. + +config SM_VIDEOCC_8550 + tristate "SM8550 Video Clock Controller" + select SM_GCC_8550 + select QCOM_GDSC + help + Support for the video clock controller on Qualcomm Technologies, Inc. + SM8550 devices. + Say Y if you want to support video devices and functionality such as + video encode/decode. + config SPMI_PMIC_CLKDIV tristate "SPMI PMIC clkdiv Support" depends on SPMI || COMPILE_TEST @@ -958,8 +1081,18 @@ config KRAITCC config CLK_GFM_LPASS_SM8250 tristate "SM8250 GFM LPASS Clocks" + depends on ARM64 || COMPILE_TEST help Support for the Glitch Free Mux (GFM) Low power audio subsystem (LPASS) clocks found on SM8250 SoCs. +config SM_VIDEOCC_8450 + tristate "SM8450 Video Clock Controller" + select SM_GCC_8450 + select QCOM_GDSC + help + Support for the video clock controller on Qualcomm Technologies, Inc. + SM8450 devices. + Say Y if you want to support video devices and functionality such as + video encode/decode. endif diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile index 9ff4c373ad95aca083b64540509a5027043a66f4..e6e294274c35098cdf8f9e8ef712608e0573984e 100644 --- a/drivers/clk/qcom/Makefile +++ b/drivers/clk/qcom/Makefile @@ -81,6 +81,7 @@ obj-$(CONFIG_SC_GPUCC_7180) += gpucc-sc7180.o obj-$(CONFIG_SC_GPUCC_7280) += gpucc-sc7280.o obj-$(CONFIG_SC_GPUCC_8280XP) += gpucc-sc8280xp.o obj-$(CONFIG_SC_LPASSCC_7280) += lpasscc-sc7280.o +obj-$(CONFIG_SC_LPASSCC_8280XP) += lpasscc-sc8280xp.o obj-$(CONFIG_SC_LPASS_CORECC_7180) += lpasscorecc-sc7180.o obj-$(CONFIG_SC_LPASS_CORECC_7280) += lpasscorecc-sc7280.o lpassaudiocc-sc7280.o obj-$(CONFIG_SC_MSS_7180) += mss-sc7180.o @@ -97,6 +98,7 @@ obj-$(CONFIG_SDM_LPASSCC_845) += lpasscc-sdm845.o obj-$(CONFIG_SDM_VIDEOCC_845) += videocc-sdm845.o obj-$(CONFIG_SDX_GCC_55) += gcc-sdx55.o obj-$(CONFIG_SDX_GCC_65) += gcc-sdx65.o +obj-$(CONFIG_SDX_GCC_75) += gcc-sdx75.o obj-$(CONFIG_SM_CAMCC_6350) += camcc-sm6350.o obj-$(CONFIG_SM_CAMCC_8250) += camcc-sm8250.o obj-$(CONFIG_SM_CAMCC_8450) += camcc-sm8450.o @@ -124,9 +126,14 @@ obj-$(CONFIG_SM_GPUCC_6375) += gpucc-sm6375.o obj-$(CONFIG_SM_GPUCC_8150) += gpucc-sm8150.o obj-$(CONFIG_SM_GPUCC_8250) += gpucc-sm8250.o obj-$(CONFIG_SM_GPUCC_8350) += gpucc-sm8350.o +obj-$(CONFIG_SM_GPUCC_8450) += gpucc-sm8450.o +obj-$(CONFIG_SM_GPUCC_8550) += gpucc-sm8550.o obj-$(CONFIG_SM_TCSRCC_8550) += tcsrcc-sm8550.o obj-$(CONFIG_SM_VIDEOCC_8150) += videocc-sm8150.o obj-$(CONFIG_SM_VIDEOCC_8250) += videocc-sm8250.o +obj-$(CONFIG_SM_VIDEOCC_8350) += videocc-sm8350.o +obj-$(CONFIG_SM_VIDEOCC_8450) += videocc-sm8450.o +obj-$(CONFIG_SM_VIDEOCC_8550) += videocc-sm8550.o obj-$(CONFIG_SPMI_PMIC_CLKDIV) += clk-spmi-pmic-div.o obj-$(CONFIG_KPSS_XCC) += kpss-xcc.o obj-$(CONFIG_QCOM_HFPLL) += hfpll.o diff --git a/drivers/clk/qcom/apss-ipq-pll.c b/drivers/clk/qcom/apss-ipq-pll.c index cf4f0d340cbf75384d80df54ffbebe1edd5c6630..ce28d882ee78588d617f568543127b0cfa93a49d 100644 --- a/drivers/clk/qcom/apss-ipq-pll.c +++ b/drivers/clk/qcom/apss-ipq-pll.c @@ -111,6 +111,18 @@ static const struct alpha_pll_config ipq8074_pll_config = { .test_ctl_hi_val = 0x4000, }; +static const struct alpha_pll_config ipq9574_pll_config = { + .l = 0x3b, + .config_ctl_val = 0x200d4828, + .config_ctl_hi_val = 0x6, + .early_output_mask = BIT(3), + .aux2_output_mask = BIT(2), + .aux_output_mask = BIT(1), + .main_output_mask = BIT(0), + .test_ctl_val = 0x0, + .test_ctl_hi_val = 0x4000, +}; + struct apss_pll_data { int pll_type; struct clk_alpha_pll *pll; @@ -135,6 +147,12 @@ static struct apss_pll_data ipq6018_pll_data = { .pll_config = &ipq6018_pll_config, }; +static struct apss_pll_data ipq9574_pll_data = { + .pll_type = CLK_ALPHA_PLL_TYPE_HUAYRA, + .pll = &ipq_pll_huayra, + .pll_config = &ipq9574_pll_config, +}; + static const struct regmap_config ipq_pll_regmap_config = { .reg_bits = 32, .reg_stride = 4, @@ -180,6 +198,7 @@ static const struct of_device_id apss_ipq_pll_match_table[] = { { .compatible = "qcom,ipq5332-a53pll", .data = &ipq5332_pll_data }, { .compatible = "qcom,ipq6018-a53pll", .data = &ipq6018_pll_data }, { .compatible = "qcom,ipq8074-a53pll", .data = &ipq8074_pll_data }, + { .compatible = "qcom,ipq9574-a73pll", .data = &ipq9574_pll_data }, { } }; MODULE_DEVICE_TABLE(of, apss_ipq_pll_match_table); diff --git a/drivers/clk/qcom/camcc-sc7180.c b/drivers/clk/qcom/camcc-sc7180.c index e2b4804695f37c227ac710f51c7e7cc0feaef42f..8a4ba7a19ed124ad51b8cc9a134fb6c0f00fcd88 100644 --- a/drivers/clk/qcom/camcc-sc7180.c +++ b/drivers/clk/qcom/camcc-sc7180.c @@ -1480,12 +1480,21 @@ static struct clk_branch cam_cc_sys_tmr_clk = { }, }; +static struct gdsc titan_top_gdsc = { + .gdscr = 0xb134, + .pd = { + .name = "titan_top_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, +}; + static struct gdsc bps_gdsc = { .gdscr = 0x6004, .pd = { .name = "bps_gdsc", }, .pwrsts = PWRSTS_OFF_ON, + .parent = &titan_top_gdsc.pd, .flags = HW_CTRL, }; @@ -1495,6 +1504,7 @@ static struct gdsc ife_0_gdsc = { .name = "ife_0_gdsc", }, .pwrsts = PWRSTS_OFF_ON, + .parent = &titan_top_gdsc.pd, }; static struct gdsc ife_1_gdsc = { @@ -1503,6 +1513,7 @@ static struct gdsc ife_1_gdsc = { .name = "ife_1_gdsc", }, .pwrsts = PWRSTS_OFF_ON, + .parent = &titan_top_gdsc.pd, }; static struct gdsc ipe_0_gdsc = { @@ -1512,15 +1523,9 @@ static struct gdsc ipe_0_gdsc = { }, .pwrsts = PWRSTS_OFF_ON, .flags = HW_CTRL, + .parent = &titan_top_gdsc.pd, }; -static struct gdsc titan_top_gdsc = { - .gdscr = 0xb134, - .pd = { - .name = "titan_top_gdsc", - }, - .pwrsts = PWRSTS_OFF_ON, -}; static struct clk_hw *cam_cc_sc7180_hws[] = { [CAM_CC_PLL2_OUT_EARLY] = &cam_cc_pll2_out_early.hw, diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c index b9f6535a7ba7caa5c526d2af69dec5bba5868b7b..e4ef645f65d1fd9ca1889d3b170100dae6b71814 100644 --- a/drivers/clk/qcom/clk-alpha-pll.c +++ b/drivers/clk/qcom/clk-alpha-pll.c @@ -55,6 +55,7 @@ #define PLL_TEST_CTL(p) ((p)->offset + (p)->regs[PLL_OFF_TEST_CTL]) #define PLL_TEST_CTL_U(p) ((p)->offset + (p)->regs[PLL_OFF_TEST_CTL_U]) #define PLL_TEST_CTL_U1(p) ((p)->offset + (p)->regs[PLL_OFF_TEST_CTL_U1]) +#define PLL_TEST_CTL_U2(p) ((p)->offset + (p)->regs[PLL_OFF_TEST_CTL_U2]) #define PLL_STATUS(p) ((p)->offset + (p)->regs[PLL_OFF_STATUS]) #define PLL_OPMODE(p) ((p)->offset + (p)->regs[PLL_OFF_OPMODE]) #define PLL_FRAC(p) ((p)->offset + (p)->regs[PLL_OFF_FRAC]) @@ -383,10 +384,21 @@ void clk_alpha_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap, regmap_update_bits(regmap, PLL_USER_CTL(pll), mask, val); - clk_alpha_pll_write_config(regmap, PLL_TEST_CTL(pll), - config->test_ctl_val); - clk_alpha_pll_write_config(regmap, PLL_TEST_CTL_U(pll), - config->test_ctl_hi_val); + if (config->test_ctl_mask) + regmap_update_bits(regmap, PLL_TEST_CTL(pll), + config->test_ctl_mask, + config->test_ctl_val); + else + clk_alpha_pll_write_config(regmap, PLL_TEST_CTL(pll), + config->test_ctl_val); + + if (config->test_ctl_hi_mask) + regmap_update_bits(regmap, PLL_TEST_CTL_U(pll), + config->test_ctl_hi_mask, + config->test_ctl_hi_val); + else + clk_alpha_pll_write_config(regmap, PLL_TEST_CTL_U(pll), + config->test_ctl_hi_val); if (pll->flags & SUPPORTS_FSM_MODE) qcom_pll_set_fsm_mode(regmap, PLL_MODE(pll), 6, 0); @@ -2096,6 +2108,7 @@ void clk_lucid_evo_pll_configure(struct clk_alpha_pll *pll, struct regmap *regma clk_alpha_pll_write_config(regmap, PLL_TEST_CTL(pll), config->test_ctl_val); clk_alpha_pll_write_config(regmap, PLL_TEST_CTL_U(pll), config->test_ctl_hi_val); clk_alpha_pll_write_config(regmap, PLL_TEST_CTL_U1(pll), config->test_ctl_hi1_val); + clk_alpha_pll_write_config(regmap, PLL_TEST_CTL_U2(pll), config->test_ctl_hi2_val); /* Disable PLL output */ regmap_update_bits(regmap, PLL_MODE(pll), PLL_OUTCTRL, 0); diff --git a/drivers/clk/qcom/clk-alpha-pll.h b/drivers/clk/qcom/clk-alpha-pll.h index d07b17186b901cb251c766c5b94aac42aa2195fc..e4bd863027ab63701b72e93f8943c6287dae7358 100644 --- a/drivers/clk/qcom/clk-alpha-pll.h +++ b/drivers/clk/qcom/clk-alpha-pll.h @@ -123,8 +123,11 @@ struct alpha_pll_config { u32 user_ctl_hi_val; u32 user_ctl_hi1_val; u32 test_ctl_val; + u32 test_ctl_mask; u32 test_ctl_hi_val; + u32 test_ctl_hi_mask; u32 test_ctl_hi1_val; + u32 test_ctl_hi2_val; u32 main_output_mask; u32 aux_output_mask; u32 aux2_output_mask; diff --git a/drivers/clk/qcom/clk-branch.c b/drivers/clk/qcom/clk-branch.c index ca896ebf7e1ba959e1cb12e1a40e99ff4508b687..fc4735f74f0f1506fe227bb42ad346c643d1a190 100644 --- a/drivers/clk/qcom/clk-branch.c +++ b/drivers/clk/qcom/clk-branch.c @@ -43,6 +43,7 @@ static bool clk_branch2_check_halt(const struct clk_branch *br, bool enabling) { u32 val; u32 mask; + bool invert = (br->halt_check == BRANCH_HALT_ENABLE); mask = CBCR_NOC_FSM_STATUS; mask |= CBCR_CLK_OFF; @@ -51,11 +52,10 @@ static bool clk_branch2_check_halt(const struct clk_branch *br, bool enabling) if (enabling) { val &= mask; - return (val & CBCR_CLK_OFF) == 0 || + return (val & CBCR_CLK_OFF) == (invert ? CBCR_CLK_OFF : 0) || FIELD_GET(CBCR_NOC_FSM_STATUS, val) == FSM_STATUS_ON; - } else { - return val & CBCR_CLK_OFF; } + return (val & CBCR_CLK_OFF) == (invert ? 0 : CBCR_CLK_OFF); } static int clk_branch_wait(const struct clk_branch *br, bool enabling, diff --git a/drivers/clk/qcom/clk-cbf-8996.c b/drivers/clk/qcom/clk-cbf-8996.c index cfd567636f4e0c7d23fdb275ceac6f2ef0250199..1e23b734abb3451f0687e67f953e753f857c89cc 100644 --- a/drivers/clk/qcom/clk-cbf-8996.c +++ b/drivers/clk/qcom/clk-cbf-8996.c @@ -5,11 +5,15 @@ #include #include #include +#include +#include #include #include #include #include +#include + #include "clk-alpha-pll.h" #include "clk-regmap.h" @@ -223,6 +227,49 @@ static const struct regmap_config cbf_msm8996_regmap_config = { .val_format_endian = REGMAP_ENDIAN_LITTLE, }; +#ifdef CONFIG_INTERCONNECT + +/* Random ID that doesn't clash with main qnoc and OSM */ +#define CBF_MASTER_NODE 2000 + +static int qcom_msm8996_cbf_icc_register(struct platform_device *pdev, struct clk_hw *cbf_hw) +{ + struct device *dev = &pdev->dev; + struct clk *clk = devm_clk_hw_get_clk(dev, cbf_hw, "cbf"); + const struct icc_clk_data data[] = { + { .clk = clk, .name = "cbf", }, + }; + struct icc_provider *provider; + + provider = icc_clk_register(dev, CBF_MASTER_NODE, ARRAY_SIZE(data), data); + if (IS_ERR(provider)) + return PTR_ERR(provider); + + platform_set_drvdata(pdev, provider); + + return 0; +} + +static int qcom_msm8996_cbf_icc_remove(struct platform_device *pdev) +{ + struct icc_provider *provider = platform_get_drvdata(pdev); + + icc_clk_unregister(provider); + + return 0; +} +#define qcom_msm8996_cbf_icc_sync_state icc_sync_state +#else +static int qcom_msm8996_cbf_icc_register(struct platform_device *pdev, struct clk_hw *cbf_hw) +{ + dev_warn(&pdev->dev, "CONFIG_INTERCONNECT is disabled, CBF clock is fixed\n"); + + return 0; +} +#define qcom_msm8996_cbf_icc_remove(pdev) (0) +#define qcom_msm8996_cbf_icc_sync_state NULL +#endif + static int qcom_msm8996_cbf_probe(struct platform_device *pdev) { void __iomem *base; @@ -281,7 +328,16 @@ static int qcom_msm8996_cbf_probe(struct platform_device *pdev) if (ret) return ret; - return devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, &cbf_mux.clkr.hw); + ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, &cbf_mux.clkr.hw); + if (ret) + return ret; + + return qcom_msm8996_cbf_icc_register(pdev, &cbf_mux.clkr.hw); +} + +static int qcom_msm8996_cbf_remove(struct platform_device *pdev) +{ + return qcom_msm8996_cbf_icc_remove(pdev); } static const struct of_device_id qcom_msm8996_cbf_match_table[] = { @@ -292,9 +348,11 @@ MODULE_DEVICE_TABLE(of, qcom_msm8996_cbf_match_table); static struct platform_driver qcom_msm8996_cbf_driver = { .probe = qcom_msm8996_cbf_probe, + .remove = qcom_msm8996_cbf_remove, .driver = { .name = "qcom-msm8996-cbf", .of_match_table = qcom_msm8996_cbf_match_table, + .sync_state = qcom_msm8996_cbf_icc_sync_state, }, }; diff --git a/drivers/clk/qcom/clk-rcg.h b/drivers/clk/qcom/clk-rcg.h index 01581f4d2c39c4a8e27df94d11e1ef379c291c07..e6d84c8c7989c8fe9e0fa5480be9f4fea3db5fd0 100644 --- a/drivers/clk/qcom/clk-rcg.h +++ b/drivers/clk/qcom/clk-rcg.h @@ -141,6 +141,7 @@ extern const struct clk_ops clk_dyn_rcg_ops; * @clkr: regmap clock handle * @cfg_off: defines the cfg register offset from the CMD_RCGR + CFG_REG * @parked_cfg: cached value of the CFG register for parked RCGs + * @hw_clk_ctrl: whether to enable hardware clock control */ struct clk_rcg2 { u32 cmd_rcgr; @@ -152,6 +153,7 @@ struct clk_rcg2 { struct clk_regmap clkr; u8 cfg_off; u32 parked_cfg; + bool hw_clk_ctrl; }; #define to_clk_rcg2(_hw) container_of(to_clk_regmap(_hw), struct clk_rcg2, clkr) diff --git a/drivers/clk/qcom/clk-rcg2.c b/drivers/clk/qcom/clk-rcg2.c index 76551534f10dfe0dc09a9917a3df974b80f2bd58..e22baf3a7112aadfc9715df18a9a24303aad57bc 100644 --- a/drivers/clk/qcom/clk-rcg2.c +++ b/drivers/clk/qcom/clk-rcg2.c @@ -325,6 +325,8 @@ static int __clk_rcg2_configure(struct clk_rcg2 *rcg, const struct freq_tbl *f, cfg |= rcg->parent_map[index].cfg << CFG_SRC_SEL_SHIFT; if (rcg->mnd_width && f->n && (f->m != f->n)) cfg |= CFG_MODE_DUAL_EDGE; + if (rcg->hw_clk_ctrl) + cfg |= CFG_HW_CLK_CTRL_MASK; *_cfg &= ~mask; *_cfg |= cfg; diff --git a/drivers/clk/qcom/clk-rpmh.c b/drivers/clk/qcom/clk-rpmh.c index 45ee370f330745ca86c8554a18c0a795c0a91461..86572570bc54cd0fd993ae415a616592c8fce5c3 100644 --- a/drivers/clk/qcom/clk-rpmh.c +++ b/drivers/clk/qcom/clk-rpmh.c @@ -700,6 +700,24 @@ static const struct clk_rpmh_desc clk_rpmh_qdu1000 = { .num_clks = ARRAY_SIZE(qdu1000_rpmh_clocks), }; +static struct clk_hw *sdx75_rpmh_clocks[] = { + [RPMH_CXO_CLK] = &clk_rpmh_bi_tcxo_div4.hw, + [RPMH_CXO_CLK_A] = &clk_rpmh_bi_tcxo_div4_ao.hw, + [RPMH_RF_CLK1] = &clk_rpmh_rf_clk1_a.hw, + [RPMH_RF_CLK1_A] = &clk_rpmh_rf_clk1_a_ao.hw, + [RPMH_RF_CLK2] = &clk_rpmh_rf_clk2_a.hw, + [RPMH_RF_CLK2_A] = &clk_rpmh_rf_clk2_a_ao.hw, + [RPMH_RF_CLK3] = &clk_rpmh_rf_clk3_a.hw, + [RPMH_RF_CLK3_A] = &clk_rpmh_rf_clk3_a_ao.hw, + [RPMH_QPIC_CLK] = &clk_rpmh_qpic_clk.hw, + [RPMH_IPA_CLK] = &clk_rpmh_ipa.hw, +}; + +static const struct clk_rpmh_desc clk_rpmh_sdx75 = { + .clks = sdx75_rpmh_clocks, + .num_clks = ARRAY_SIZE(sdx75_rpmh_clocks), +}; + static struct clk_hw *of_clk_rpmh_hw_get(struct of_phandle_args *clkspec, void *data) { @@ -792,6 +810,7 @@ static const struct of_device_id clk_rpmh_match_table[] = { { .compatible = "qcom,sdm670-rpmh-clk", .data = &clk_rpmh_sdm670}, { .compatible = "qcom,sdx55-rpmh-clk", .data = &clk_rpmh_sdx55}, { .compatible = "qcom,sdx65-rpmh-clk", .data = &clk_rpmh_sdx65}, + { .compatible = "qcom,sdx75-rpmh-clk", .data = &clk_rpmh_sdx75}, { .compatible = "qcom,sm6350-rpmh-clk", .data = &clk_rpmh_sm6350}, { .compatible = "qcom,sm8150-rpmh-clk", .data = &clk_rpmh_sm8150}, { .compatible = "qcom,sm8250-rpmh-clk", .data = &clk_rpmh_sm8250}, diff --git a/drivers/clk/qcom/clk-smd-rpm.c b/drivers/clk/qcom/clk-smd-rpm.c index 887b945a6fb7bb87fc47436d1ab23c66c3920b74..e4de74b687974b63876ed882e85294270d31e407 100644 --- a/drivers/clk/qcom/clk-smd-rpm.c +++ b/drivers/clk/qcom/clk-smd-rpm.c @@ -67,7 +67,7 @@ type, r_id, key) #define __DEFINE_CLK_SMD_RPM_BRANCH_PREFIX(_prefix, _name, _active,\ - type, r_id, r, key) \ + type, r_id, r, key, ao_flags) \ static struct clk_smd_rpm clk_smd_rpm_##_prefix##_active; \ static struct clk_smd_rpm clk_smd_rpm_##_prefix##_name = { \ .rpm_res_type = (type), \ @@ -102,12 +102,13 @@ .name = "xo_board", \ }, \ .num_parents = 1, \ + .flags = (ao_flags), \ }, \ } #define __DEFINE_CLK_SMD_RPM_BRANCH(_name, _active, type, r_id, r, key) \ __DEFINE_CLK_SMD_RPM_BRANCH_PREFIX(/* empty */, \ - _name, _active, type, r_id, r, key) + _name, _active, type, r_id, r, key, 0) #define DEFINE_CLK_SMD_RPM(_name, type, r_id) \ __DEFINE_CLK_SMD_RPM(_name##_clk, _name##_a_clk, \ @@ -126,12 +127,12 @@ #define DEFINE_CLK_SMD_RPM_BRANCH(_name, type, r_id, r) \ __DEFINE_CLK_SMD_RPM_BRANCH_PREFIX(branch_, \ _name##_clk, _name##_a_clk, \ - type, r_id, r, QCOM_RPM_SMD_KEY_ENABLE) + type, r_id, r, QCOM_RPM_SMD_KEY_ENABLE, 0) -#define DEFINE_CLK_SMD_RPM_BRANCH_A(_name, type, r_id, r) \ +#define DEFINE_CLK_SMD_RPM_BRANCH_A(_name, type, r_id, r, ao_flags) \ __DEFINE_CLK_SMD_RPM_BRANCH_PREFIX(branch_, \ _name, _name##_a, type, \ - r_id, r, QCOM_RPM_SMD_KEY_ENABLE) + r_id, r, QCOM_RPM_SMD_KEY_ENABLE, ao_flags) #define DEFINE_CLK_SMD_RPM_QDSS(_name, type, r_id) \ __DEFINE_CLK_SMD_RPM(_name##_clk, _name##_a_clk, \ @@ -146,7 +147,7 @@ __DEFINE_CLK_SMD_RPM_BRANCH_PREFIX(_prefix, \ _name, _name##_a, \ QCOM_SMD_RPM_CLK_BUF_A, r_id, r, \ - QCOM_RPM_KEY_SOFTWARE_ENABLE) + QCOM_RPM_KEY_SOFTWARE_ENABLE, 0) #define DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(_name, r_id, r) \ DEFINE_CLK_SMD_RPM_XO_BUFFER(_name, r_id, r); \ @@ -156,6 +157,8 @@ #define to_clk_smd_rpm(_hw) container_of(_hw, struct clk_smd_rpm, hw) +static struct qcom_smd_rpm *rpmcc_smd_rpm; + struct clk_smd_rpm { const int rpm_res_type; const int rpm_key; @@ -166,7 +169,6 @@ struct clk_smd_rpm { struct clk_smd_rpm *peer; struct clk_hw hw; unsigned long rate; - struct qcom_smd_rpm *rpm; }; struct clk_smd_rpm_req { @@ -178,6 +180,7 @@ struct clk_smd_rpm_req { struct rpm_smd_clk_desc { struct clk_smd_rpm **clks; size_t num_clks; + bool scaling_before_handover; }; static DEFINE_MUTEX(rpm_smd_clk_lock); @@ -191,12 +194,12 @@ static int clk_smd_rpm_handoff(struct clk_smd_rpm *r) .value = cpu_to_le32(r->branch ? 1 : INT_MAX), }; - ret = qcom_rpm_smd_write(r->rpm, QCOM_SMD_RPM_ACTIVE_STATE, + ret = qcom_rpm_smd_write(rpmcc_smd_rpm, QCOM_SMD_RPM_ACTIVE_STATE, r->rpm_res_type, r->rpm_clk_id, &req, sizeof(req)); if (ret) return ret; - ret = qcom_rpm_smd_write(r->rpm, QCOM_SMD_RPM_SLEEP_STATE, + ret = qcom_rpm_smd_write(rpmcc_smd_rpm, QCOM_SMD_RPM_SLEEP_STATE, r->rpm_res_type, r->rpm_clk_id, &req, sizeof(req)); if (ret) @@ -214,7 +217,7 @@ static int clk_smd_rpm_set_rate_active(struct clk_smd_rpm *r, .value = cpu_to_le32(DIV_ROUND_UP(rate, 1000)), /* to kHz */ }; - return qcom_rpm_smd_write(r->rpm, QCOM_SMD_RPM_ACTIVE_STATE, + return qcom_rpm_smd_write(rpmcc_smd_rpm, QCOM_SMD_RPM_ACTIVE_STATE, r->rpm_res_type, r->rpm_clk_id, &req, sizeof(req)); } @@ -228,7 +231,7 @@ static int clk_smd_rpm_set_rate_sleep(struct clk_smd_rpm *r, .value = cpu_to_le32(DIV_ROUND_UP(rate, 1000)), /* to kHz */ }; - return qcom_rpm_smd_write(r->rpm, QCOM_SMD_RPM_SLEEP_STATE, + return qcom_rpm_smd_write(rpmcc_smd_rpm, QCOM_SMD_RPM_SLEEP_STATE, r->rpm_res_type, r->rpm_clk_id, &req, sizeof(req)); } @@ -395,7 +398,7 @@ static unsigned long clk_smd_rpm_recalc_rate(struct clk_hw *hw, return r->rate; } -static int clk_smd_rpm_enable_scaling(struct qcom_smd_rpm *rpm) +static int clk_smd_rpm_enable_scaling(void) { int ret; struct clk_smd_rpm_req req = { @@ -404,7 +407,7 @@ static int clk_smd_rpm_enable_scaling(struct qcom_smd_rpm *rpm) .value = cpu_to_le32(1), }; - ret = qcom_rpm_smd_write(rpm, QCOM_SMD_RPM_SLEEP_STATE, + ret = qcom_rpm_smd_write(rpmcc_smd_rpm, QCOM_SMD_RPM_SLEEP_STATE, QCOM_SMD_RPM_MISC_CLK, QCOM_RPM_SCALING_ENABLE_ID, &req, sizeof(req)); if (ret) { @@ -412,7 +415,7 @@ static int clk_smd_rpm_enable_scaling(struct qcom_smd_rpm *rpm) return ret; } - ret = qcom_rpm_smd_write(rpm, QCOM_SMD_RPM_ACTIVE_STATE, + ret = qcom_rpm_smd_write(rpmcc_smd_rpm, QCOM_SMD_RPM_ACTIVE_STATE, QCOM_SMD_RPM_MISC_CLK, QCOM_RPM_SCALING_ENABLE_ID, &req, sizeof(req)); if (ret) { @@ -438,10 +441,11 @@ static const struct clk_ops clk_smd_rpm_branch_ops = { .recalc_rate = clk_smd_rpm_recalc_rate, }; -DEFINE_CLK_SMD_RPM_BRANCH_A(bi_tcxo, QCOM_SMD_RPM_MISC_CLK, 0, 19200000); +/* Disabling BI_TCXO_AO could gate the root clock source of the entire system. */ +DEFINE_CLK_SMD_RPM_BRANCH_A(bi_tcxo, QCOM_SMD_RPM_MISC_CLK, 0, 19200000, CLK_IS_CRITICAL); DEFINE_CLK_SMD_RPM_BRANCH(qdss, QCOM_SMD_RPM_MISC_CLK, 1, 19200000); DEFINE_CLK_SMD_RPM_QDSS(qdss, QCOM_SMD_RPM_MISC_CLK, 1); -DEFINE_CLK_SMD_RPM_BRANCH_A(bimc_freq_log, QCOM_SMD_RPM_MISC_CLK, 4, 1); +DEFINE_CLK_SMD_RPM_BRANCH_A(bimc_freq_log, QCOM_SMD_RPM_MISC_CLK, 4, 1, 0); DEFINE_CLK_SMD_RPM_BRANCH(mss_cfg_ahb, QCOM_SMD_RPM_MCFG_CLK, 0, 19200000); @@ -693,6 +697,7 @@ static struct clk_smd_rpm *msm8974_clks[] = { static const struct rpm_smd_clk_desc rpm_clk_msm8974 = { .clks = msm8974_clks, .num_clks = ARRAY_SIZE(msm8974_clks), + .scaling_before_handover = true, }; static struct clk_smd_rpm *msm8976_clks[] = { @@ -1301,12 +1306,11 @@ static int rpm_smd_clk_probe(struct platform_device *pdev) { int ret; size_t num_clks, i; - struct qcom_smd_rpm *rpm; struct clk_smd_rpm **rpm_smd_clks; const struct rpm_smd_clk_desc *desc; - rpm = dev_get_drvdata(pdev->dev.parent); - if (!rpm) { + rpmcc_smd_rpm = dev_get_drvdata(pdev->dev.parent); + if (!rpmcc_smd_rpm) { dev_err(&pdev->dev, "Unable to retrieve handle to RPM\n"); return -ENODEV; } @@ -1318,20 +1322,26 @@ static int rpm_smd_clk_probe(struct platform_device *pdev) rpm_smd_clks = desc->clks; num_clks = desc->num_clks; + if (desc->scaling_before_handover) { + ret = clk_smd_rpm_enable_scaling(); + if (ret) + goto err; + } + for (i = 0; i < num_clks; i++) { if (!rpm_smd_clks[i]) continue; - rpm_smd_clks[i]->rpm = rpm; - ret = clk_smd_rpm_handoff(rpm_smd_clks[i]); if (ret) goto err; } - ret = clk_smd_rpm_enable_scaling(rpm); - if (ret) - goto err; + if (!desc->scaling_before_handover) { + ret = clk_smd_rpm_enable_scaling(); + if (ret) + goto err; + } for (i = 0; i < num_clks; i++) { if (!rpm_smd_clks[i]) diff --git a/drivers/clk/qcom/dispcc-qcm2290.c b/drivers/clk/qcom/dispcc-qcm2290.c index e9cfe41c04426760bacd43cbc81cc472dee6e17c..44dd5cfcc150430fce3c302b4b13ed4904ff3eac 100644 --- a/drivers/clk/qcom/dispcc-qcm2290.c +++ b/drivers/clk/qcom/dispcc-qcm2290.c @@ -24,9 +24,11 @@ enum { P_BI_TCXO, + P_BI_TCXO_AO, P_DISP_CC_PLL0_OUT_MAIN, P_DSI0_PHY_PLL_OUT_BYTECLK, P_DSI0_PHY_PLL_OUT_DSICLK, + P_GPLL0_OUT_DIV, P_GPLL0_OUT_MAIN, P_SLEEP_CLK, }; @@ -82,8 +84,8 @@ static const struct clk_parent_data disp_cc_parent_data_1[] = { }; static const struct parent_map disp_cc_parent_map_2[] = { - { P_BI_TCXO, 0 }, - { P_GPLL0_OUT_MAIN, 4 }, + { P_BI_TCXO_AO, 0 }, + { P_GPLL0_OUT_DIV, 4 }, }; static const struct clk_parent_data disp_cc_parent_data_2[] = { @@ -151,9 +153,9 @@ static struct clk_regmap_div disp_cc_mdss_byte0_div_clk_src = { }; static const struct freq_tbl ftbl_disp_cc_mdss_ahb_clk_src[] = { - F(19200000, P_BI_TCXO, 1, 0, 0), - F(37500000, P_GPLL0_OUT_MAIN, 8, 0, 0), - F(75000000, P_GPLL0_OUT_MAIN, 4, 0, 0), + F(19200000, P_BI_TCXO_AO, 1, 0, 0), + F(37500000, P_GPLL0_OUT_DIV, 8, 0, 0), + F(75000000, P_GPLL0_OUT_DIV, 4, 0, 0), { } }; diff --git a/drivers/clk/qcom/gcc-ipq5332.c b/drivers/clk/qcom/gcc-ipq5332.c index bdb4a0a11d07b9d13ab96a590afafbe82a2a642e..a75ab88ed14c6bd1bd3c6f7127eda1412a843385 100644 --- a/drivers/clk/qcom/gcc-ipq5332.c +++ b/drivers/clk/qcom/gcc-ipq5332.c @@ -20,8 +20,8 @@ #include "reset.h" enum { - DT_SLEEP_CLK, DT_XO, + DT_SLEEP_CLK, DT_PCIE_2LANE_PHY_PIPE_CLK, DT_PCIE_2LANE_PHY_PIPE_CLK_X1, DT_USB_PCIE_WRAPPER_PIPE_CLK, @@ -366,7 +366,7 @@ static struct clk_rcg2 gcc_adss_pwm_clk_src = { }; static const struct freq_tbl ftbl_gcc_apss_axi_clk_src[] = { - F(480000000, P_GPLL4_OUT_MAIN, 2.5, 0, 0), + F(480000000, P_GPLL4_OUT_AUX, 2.5, 0, 0), F(533333333, P_GPLL0_OUT_MAIN, 1.5, 0, 0), { } }; @@ -963,7 +963,7 @@ static struct clk_rcg2 gcc_sdcc1_apps_clk_src = { .name = "gcc_sdcc1_apps_clk_src", .parent_data = gcc_parent_data_9, .num_parents = ARRAY_SIZE(gcc_parent_data_9), - .ops = &clk_rcg2_ops, + .ops = &clk_rcg2_floor_ops, }, }; diff --git a/drivers/clk/qcom/gcc-ipq6018.c b/drivers/clk/qcom/gcc-ipq6018.c index 3f9c2f61a5d93495f77659b6d42e68d2aa05ff27..86b43175b042271442eb21ca593bed2ae5391cec 100644 --- a/drivers/clk/qcom/gcc-ipq6018.c +++ b/drivers/clk/qcom/gcc-ipq6018.c @@ -26,8 +26,6 @@ #include "clk-regmap-mux.h" #include "reset.h" -#define F(f, s, h, m, n) { (f), (s), (2 * (h) - 1), (m), (n) } - enum { P_XO, P_BIAS_PLL, @@ -1654,7 +1652,7 @@ static struct clk_rcg2 sdcc1_apps_clk_src = { .name = "sdcc1_apps_clk_src", .parent_data = gcc_xo_gpll0_gpll2_gpll0_out_main_div2, .num_parents = 4, - .ops = &clk_rcg2_ops, + .ops = &clk_rcg2_floor_ops, }, }; @@ -4151,15 +4149,18 @@ static struct clk_branch gcc_dcc_clk = { static const struct alpha_pll_config ubi32_pll_config = { .l = 0x3e, - .alpha = 0x57, - .config_ctl_val = 0x240d6aa8, - .config_ctl_hi_val = 0x3c2, + .alpha = 0x6667, + .config_ctl_val = 0x240d4828, + .config_ctl_hi_val = 0x6, .main_output_mask = BIT(0), .aux_output_mask = BIT(1), .pre_div_val = 0x0, .pre_div_mask = BIT(12), .post_div_val = 0x0, .post_div_mask = GENMASK(9, 8), + .alpha_en_mask = BIT(24), + .test_ctl_val = 0x1C0000C0, + .test_ctl_hi_val = 0x4000, }; static const struct alpha_pll_config nss_crypto_pll_config = { @@ -4517,24 +4518,24 @@ static const struct qcom_reset_map gcc_ipq6018_resets[] = { [GCC_PCIE0_AHB_ARES] = { 0x75040, 5 }, [GCC_PCIE0_AXI_MASTER_STICKY_ARES] = { 0x75040, 6 }, [GCC_PCIE0_AXI_SLAVE_STICKY_ARES] = { 0x75040, 7 }, - [GCC_PPE_FULL_RESET] = { 0x68014, 0 }, - [GCC_UNIPHY0_SOFT_RESET] = { 0x56004, 0 }, + [GCC_PPE_FULL_RESET] = { .reg = 0x68014, .bitmask = 0xf0000 }, + [GCC_UNIPHY0_SOFT_RESET] = { .reg = 0x56004, .bitmask = 0x3ff2 }, [GCC_UNIPHY0_XPCS_RESET] = { 0x56004, 2 }, - [GCC_UNIPHY1_SOFT_RESET] = { 0x56104, 0 }, + [GCC_UNIPHY1_SOFT_RESET] = { .reg = 0x56104, .bitmask = 0x32 }, [GCC_UNIPHY1_XPCS_RESET] = { 0x56104, 2 }, - [GCC_EDMA_HW_RESET] = { 0x68014, 0 }, - [GCC_NSSPORT1_RESET] = { 0x68014, 0 }, - [GCC_NSSPORT2_RESET] = { 0x68014, 0 }, - [GCC_NSSPORT3_RESET] = { 0x68014, 0 }, - [GCC_NSSPORT4_RESET] = { 0x68014, 0 }, - [GCC_NSSPORT5_RESET] = { 0x68014, 0 }, - [GCC_UNIPHY0_PORT1_ARES] = { 0x56004, 0 }, - [GCC_UNIPHY0_PORT2_ARES] = { 0x56004, 0 }, - [GCC_UNIPHY0_PORT3_ARES] = { 0x56004, 0 }, - [GCC_UNIPHY0_PORT4_ARES] = { 0x56004, 0 }, - [GCC_UNIPHY0_PORT5_ARES] = { 0x56004, 0 }, - [GCC_UNIPHY0_PORT_4_5_RESET] = { 0x56004, 0 }, - [GCC_UNIPHY0_PORT_4_RESET] = { 0x56004, 0 }, + [GCC_EDMA_HW_RESET] = { .reg = 0x68014, .bitmask = 0x300000 }, + [GCC_NSSPORT1_RESET] = { .reg = 0x68014, .bitmask = 0x1000003 }, + [GCC_NSSPORT2_RESET] = { .reg = 0x68014, .bitmask = 0x200000c }, + [GCC_NSSPORT3_RESET] = { .reg = 0x68014, .bitmask = 0x4000030 }, + [GCC_NSSPORT4_RESET] = { .reg = 0x68014, .bitmask = 0x8000300 }, + [GCC_NSSPORT5_RESET] = { .reg = 0x68014, .bitmask = 0x10000c00 }, + [GCC_UNIPHY0_PORT1_ARES] = { .reg = 0x56004, .bitmask = 0x30 }, + [GCC_UNIPHY0_PORT2_ARES] = { .reg = 0x56004, .bitmask = 0xc0 }, + [GCC_UNIPHY0_PORT3_ARES] = { .reg = 0x56004, .bitmask = 0x300 }, + [GCC_UNIPHY0_PORT4_ARES] = { .reg = 0x56004, .bitmask = 0xc00 }, + [GCC_UNIPHY0_PORT5_ARES] = { .reg = 0x56004, .bitmask = 0x3000 }, + [GCC_UNIPHY0_PORT_4_5_RESET] = { .reg = 0x56004, .bitmask = 0x3c02 }, + [GCC_UNIPHY0_PORT_4_RESET] = { .reg = 0x56004, .bitmask = 0xc02 }, [GCC_LPASS_BCR] = {0x1F000, 0}, [GCC_UBI32_TBU_BCR] = {0x65000, 0}, [GCC_LPASS_TBU_BCR] = {0x6C000, 0}, diff --git a/drivers/clk/qcom/gcc-ipq9574.c b/drivers/clk/qcom/gcc-ipq9574.c index b2a2d618a5ec265bdd4f1c0c4cef5d9304e44d68..6914f962c89367ffcc099681893851210ccc2673 100644 --- a/drivers/clk/qcom/gcc-ipq9574.c +++ b/drivers/clk/qcom/gcc-ipq9574.c @@ -3,24 +3,24 @@ * Copyright (c) 2023 The Linux Foundation. All rights reserved. */ +#include #include -#include -#include #include #include -#include +#include #include -#include #include #include -#include "clk-rcg.h" -#include "clk-branch.h" #include "clk-alpha-pll.h" +#include "clk-branch.h" +#include "clk-rcg.h" +#include "clk-regmap.h" #include "clk-regmap-divider.h" #include "clk-regmap-mux.h" #include "clk-regmap-phy-mux.h" +#include "common.h" #include "reset.h" /* Need to match the order of clocks in DT binding */ @@ -69,7 +69,7 @@ static struct clk_alpha_pll gpll0_main = { .clkr = { .enable_reg = 0x0b000, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gpll0_main", .parent_data = gcc_xo_data, .num_parents = ARRAY_SIZE(gcc_xo_data), @@ -81,7 +81,7 @@ static struct clk_alpha_pll gpll0_main = { static struct clk_fixed_factor gpll0_out_main_div2 = { .mult = 1, .div = 2, - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gpll0_out_main_div2", .parent_hws = (const struct clk_hw *[]) { &gpll0_main.clkr.hw @@ -96,7 +96,7 @@ static struct clk_alpha_pll_postdiv gpll0 = { .offset = 0x20000, .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], .width = 4, - .clkr.hw.init = &(struct clk_init_data) { + .clkr.hw.init = &(const struct clk_init_data) { .name = "gpll0", .parent_hws = (const struct clk_hw *[]) { &gpll0_main.clkr.hw @@ -113,7 +113,7 @@ static struct clk_alpha_pll gpll4_main = { .clkr = { .enable_reg = 0x0b000, .enable_mask = BIT(2), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gpll4_main", .parent_data = gcc_xo_data, .num_parents = ARRAY_SIZE(gcc_xo_data), @@ -126,7 +126,7 @@ static struct clk_alpha_pll_postdiv gpll4 = { .offset = 0x22000, .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], .width = 4, - .clkr.hw.init = &(struct clk_init_data) { + .clkr.hw.init = &(const struct clk_init_data) { .name = "gpll4", .parent_hws = (const struct clk_hw *[]) { &gpll4_main.clkr.hw @@ -143,7 +143,7 @@ static struct clk_alpha_pll gpll2_main = { .clkr = { .enable_reg = 0x0b000, .enable_mask = BIT(1), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gpll2_main", .parent_data = gcc_xo_data, .num_parents = ARRAY_SIZE(gcc_xo_data), @@ -156,7 +156,7 @@ static struct clk_alpha_pll_postdiv gpll2 = { .offset = 0x21000, .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], .width = 4, - .clkr.hw.init = &(struct clk_init_data) { + .clkr.hw.init = &(const struct clk_init_data) { .name = "gpll2", .parent_hws = (const struct clk_hw *[]) { &gpll2_main.clkr.hw @@ -172,7 +172,7 @@ static struct clk_branch gcc_sleep_clk_src = { .clkr = { .enable_reg = 0x3400c, .enable_mask = BIT(1), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_sleep_clk_src", .parent_data = gcc_sleep_clk_data, .num_parents = ARRAY_SIZE(gcc_sleep_clk_data), @@ -420,7 +420,7 @@ static struct clk_rcg2 apss_ahb_clk_src = { .freq_tbl = ftbl_apss_ahb_clk_src, .hid_width = 5, .parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map, - .clkr.hw.init = &(struct clk_init_data) { + .clkr.hw.init = &(const struct clk_init_data) { .name = "apss_ahb_clk_src", .parent_data = gcc_xo_gpll0_gpll0_out_main_div2, .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_out_main_div2), @@ -438,7 +438,7 @@ static struct clk_rcg2 apss_axi_clk_src = { .freq_tbl = ftbl_apss_axi_clk_src, .hid_width = 5, .parent_map = gcc_xo_gpll0_gpll0_div2_gpll0_map, - .clkr.hw.init = &(struct clk_init_data) { + .clkr.hw.init = &(const struct clk_init_data) { .name = "apss_axi_clk_src", .parent_data = gcc_xo_gpll0_gpll0_div2_gpll0, .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_div2_gpll0), @@ -458,7 +458,7 @@ static struct clk_rcg2 blsp1_qup1_i2c_apps_clk_src = { .freq_tbl = ftbl_blsp1_qup_i2c_apps_clk_src, .hid_width = 5, .parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map, - .clkr.hw.init = &(struct clk_init_data) { + .clkr.hw.init = &(const struct clk_init_data) { .name = "blsp1_qup1_i2c_apps_clk_src", .parent_data = gcc_xo_gpll0_gpll0_out_main_div2, .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_out_main_div2), @@ -483,7 +483,7 @@ static struct clk_rcg2 blsp1_qup1_spi_apps_clk_src = { .mnd_width = 8, .hid_width = 5, .parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map, - .clkr.hw.init = &(struct clk_init_data) { + .clkr.hw.init = &(const struct clk_init_data) { .name = "blsp1_qup1_spi_apps_clk_src", .parent_data = gcc_xo_gpll0_gpll0_out_main_div2, .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_out_main_div2), @@ -496,7 +496,7 @@ static struct clk_rcg2 blsp1_qup2_i2c_apps_clk_src = { .freq_tbl = ftbl_blsp1_qup_i2c_apps_clk_src, .hid_width = 5, .parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map, - .clkr.hw.init = &(struct clk_init_data) { + .clkr.hw.init = &(const struct clk_init_data) { .name = "blsp1_qup2_i2c_apps_clk_src", .parent_data = gcc_xo_gpll0_gpll0_out_main_div2, .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_out_main_div2), @@ -510,7 +510,7 @@ static struct clk_rcg2 blsp1_qup2_spi_apps_clk_src = { .mnd_width = 8, .hid_width = 5, .parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map, - .clkr.hw.init = &(struct clk_init_data) { + .clkr.hw.init = &(const struct clk_init_data) { .name = "blsp1_qup2_spi_apps_clk_src", .parent_data = gcc_xo_gpll0_gpll0_out_main_div2, .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_out_main_div2), @@ -523,7 +523,7 @@ static struct clk_rcg2 blsp1_qup3_i2c_apps_clk_src = { .freq_tbl = ftbl_blsp1_qup_i2c_apps_clk_src, .hid_width = 5, .parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map, - .clkr.hw.init = &(struct clk_init_data) { + .clkr.hw.init = &(const struct clk_init_data) { .name = "blsp1_qup3_i2c_apps_clk_src", .parent_data = gcc_xo_gpll0_gpll0_out_main_div2, .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_out_main_div2), @@ -537,7 +537,7 @@ static struct clk_rcg2 blsp1_qup3_spi_apps_clk_src = { .mnd_width = 8, .hid_width = 5, .parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map, - .clkr.hw.init = &(struct clk_init_data) { + .clkr.hw.init = &(const struct clk_init_data) { .name = "blsp1_qup3_spi_apps_clk_src", .parent_data = gcc_xo_gpll0_gpll0_out_main_div2, .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_out_main_div2), @@ -550,7 +550,7 @@ static struct clk_rcg2 blsp1_qup4_i2c_apps_clk_src = { .freq_tbl = ftbl_blsp1_qup_i2c_apps_clk_src, .hid_width = 5, .parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map, - .clkr.hw.init = &(struct clk_init_data) { + .clkr.hw.init = &(const struct clk_init_data) { .name = "blsp1_qup4_i2c_apps_clk_src", .parent_data = gcc_xo_gpll0_gpll0_out_main_div2, .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_out_main_div2), @@ -564,7 +564,7 @@ static struct clk_rcg2 blsp1_qup4_spi_apps_clk_src = { .mnd_width = 8, .hid_width = 5, .parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map, - .clkr.hw.init = &(struct clk_init_data) { + .clkr.hw.init = &(const struct clk_init_data) { .name = "blsp1_qup4_spi_apps_clk_src", .parent_data = gcc_xo_gpll0_gpll0_out_main_div2, .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_out_main_div2), @@ -577,7 +577,7 @@ static struct clk_rcg2 blsp1_qup5_i2c_apps_clk_src = { .freq_tbl = ftbl_blsp1_qup_i2c_apps_clk_src, .hid_width = 5, .parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map, - .clkr.hw.init = &(struct clk_init_data) { + .clkr.hw.init = &(const struct clk_init_data) { .name = "blsp1_qup5_i2c_apps_clk_src", .parent_data = gcc_xo_gpll0_gpll0_out_main_div2, .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_out_main_div2), @@ -591,7 +591,7 @@ static struct clk_rcg2 blsp1_qup5_spi_apps_clk_src = { .mnd_width = 8, .hid_width = 5, .parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map, - .clkr.hw.init = &(struct clk_init_data) { + .clkr.hw.init = &(const struct clk_init_data) { .name = "blsp1_qup5_spi_apps_clk_src", .parent_data = gcc_xo_gpll0_gpll0_out_main_div2, .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_out_main_div2), @@ -604,7 +604,7 @@ static struct clk_rcg2 blsp1_qup6_i2c_apps_clk_src = { .freq_tbl = ftbl_blsp1_qup_i2c_apps_clk_src, .hid_width = 5, .parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map, - .clkr.hw.init = &(struct clk_init_data) { + .clkr.hw.init = &(const struct clk_init_data) { .name = "blsp1_qup6_i2c_apps_clk_src", .parent_data = gcc_xo_gpll0_gpll0_out_main_div2, .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_out_main_div2), @@ -618,7 +618,7 @@ static struct clk_rcg2 blsp1_qup6_spi_apps_clk_src = { .mnd_width = 8, .hid_width = 5, .parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map, - .clkr.hw.init = &(struct clk_init_data) { + .clkr.hw.init = &(const struct clk_init_data) { .name = "blsp1_qup6_spi_apps_clk_src", .parent_data = gcc_xo_gpll0_gpll0_out_main_div2, .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_out_main_div2), @@ -650,7 +650,7 @@ static struct clk_rcg2 blsp1_uart1_apps_clk_src = { .mnd_width = 16, .hid_width = 5, .parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map, - .clkr.hw.init = &(struct clk_init_data) { + .clkr.hw.init = &(const struct clk_init_data) { .name = "blsp1_uart1_apps_clk_src", .parent_data = gcc_xo_gpll0_gpll0_out_main_div2, .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_out_main_div2), @@ -664,7 +664,7 @@ static struct clk_rcg2 blsp1_uart2_apps_clk_src = { .mnd_width = 16, .hid_width = 5, .parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map, - .clkr.hw.init = &(struct clk_init_data) { + .clkr.hw.init = &(const struct clk_init_data) { .name = "blsp1_uart2_apps_clk_src", .parent_data = gcc_xo_gpll0_gpll0_out_main_div2, .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_out_main_div2), @@ -678,7 +678,7 @@ static struct clk_rcg2 blsp1_uart3_apps_clk_src = { .mnd_width = 16, .hid_width = 5, .parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map, - .clkr.hw.init = &(struct clk_init_data) { + .clkr.hw.init = &(const struct clk_init_data) { .name = "blsp1_uart3_apps_clk_src", .parent_data = gcc_xo_gpll0_gpll0_out_main_div2, .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_out_main_div2), @@ -692,7 +692,7 @@ static struct clk_rcg2 blsp1_uart4_apps_clk_src = { .mnd_width = 16, .hid_width = 5, .parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map, - .clkr.hw.init = &(struct clk_init_data) { + .clkr.hw.init = &(const struct clk_init_data) { .name = "blsp1_uart4_apps_clk_src", .parent_data = gcc_xo_gpll0_gpll0_out_main_div2, .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_out_main_div2), @@ -706,7 +706,7 @@ static struct clk_rcg2 blsp1_uart5_apps_clk_src = { .mnd_width = 16, .hid_width = 5, .parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map, - .clkr.hw.init = &(struct clk_init_data) { + .clkr.hw.init = &(const struct clk_init_data) { .name = "blsp1_uart5_apps_clk_src", .parent_data = gcc_xo_gpll0_gpll0_out_main_div2, .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_out_main_div2), @@ -720,7 +720,7 @@ static struct clk_rcg2 blsp1_uart6_apps_clk_src = { .mnd_width = 16, .hid_width = 5, .parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map, - .clkr.hw.init = &(struct clk_init_data) { + .clkr.hw.init = &(const struct clk_init_data) { .name = "blsp1_uart6_apps_clk_src", .parent_data = gcc_xo_gpll0_gpll0_out_main_div2, .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_out_main_div2), @@ -728,13 +728,48 @@ static struct clk_rcg2 blsp1_uart6_apps_clk_src = { }, }; +static const struct freq_tbl ftbl_gcc_crypto_clk_src[] = { + F(160000000, P_GPLL0, 5, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_crypto_clk_src = { + .cmd_rcgr = 0x16004, + .freq_tbl = ftbl_gcc_crypto_clk_src, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_crypto_clk_src", + .parent_data = gcc_xo_gpll0_gpll0_out_main_div2, + .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_out_main_div2), + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_branch gcc_crypto_clk = { + .halt_reg = 0x1600c, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x0b004, + .enable_mask = BIT(14), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_crypto_clk", + .parent_hws = (const struct clk_hw *[]) { + &gcc_crypto_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + static struct clk_branch gcc_apss_ahb_clk = { .halt_reg = 0x24018, .halt_check = BRANCH_HALT_VOTED, .clkr = { .enable_reg = 0x0b004, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_apss_ahb_clk", .parent_hws = (const struct clk_hw *[]) { &apss_ahb_clk_src.clkr.hw @@ -752,7 +787,7 @@ static struct clk_branch gcc_apss_axi_clk = { .clkr = { .enable_reg = 0x0b004, .enable_mask = BIT(1), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_apss_axi_clk", .parent_hws = (const struct clk_hw *[]) { &apss_axi_clk_src.clkr.hw @@ -769,7 +804,7 @@ static struct clk_branch gcc_blsp1_qup1_i2c_apps_clk = { .clkr = { .enable_reg = 0x2024, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_blsp1_qup1_i2c_apps_clk", .parent_hws = (const struct clk_hw *[]) { &blsp1_qup1_i2c_apps_clk_src.clkr.hw @@ -786,7 +821,7 @@ static struct clk_branch gcc_blsp1_qup1_spi_apps_clk = { .clkr = { .enable_reg = 0x02020, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_blsp1_qup1_spi_apps_clk", .parent_hws = (const struct clk_hw *[]) { &blsp1_qup1_spi_apps_clk_src.clkr.hw @@ -803,7 +838,7 @@ static struct clk_branch gcc_blsp1_qup2_i2c_apps_clk = { .clkr = { .enable_reg = 0x03024, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_blsp1_qup2_i2c_apps_clk", .parent_hws = (const struct clk_hw *[]) { &blsp1_qup2_i2c_apps_clk_src.clkr.hw @@ -820,7 +855,7 @@ static struct clk_branch gcc_blsp1_qup2_spi_apps_clk = { .clkr = { .enable_reg = 0x03020, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_blsp1_qup2_spi_apps_clk", .parent_hws = (const struct clk_hw *[]) { &blsp1_qup2_spi_apps_clk_src.clkr.hw @@ -837,7 +872,7 @@ static struct clk_branch gcc_blsp1_qup3_i2c_apps_clk = { .clkr = { .enable_reg = 0x04024, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_blsp1_qup3_i2c_apps_clk", .parent_hws = (const struct clk_hw *[]) { &blsp1_qup3_i2c_apps_clk_src.clkr.hw @@ -854,7 +889,7 @@ static struct clk_branch gcc_blsp1_qup3_spi_apps_clk = { .clkr = { .enable_reg = 0x04020, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_blsp1_qup3_spi_apps_clk", .parent_hws = (const struct clk_hw *[]) { &blsp1_qup3_spi_apps_clk_src.clkr.hw @@ -871,7 +906,7 @@ static struct clk_branch gcc_blsp1_qup4_i2c_apps_clk = { .clkr = { .enable_reg = 0x05024, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_blsp1_qup4_i2c_apps_clk", .parent_hws = (const struct clk_hw *[]) { &blsp1_qup4_i2c_apps_clk_src.clkr.hw @@ -888,7 +923,7 @@ static struct clk_branch gcc_blsp1_qup4_spi_apps_clk = { .clkr = { .enable_reg = 0x05020, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_blsp1_qup4_spi_apps_clk", .parent_hws = (const struct clk_hw *[]) { &blsp1_qup4_spi_apps_clk_src.clkr.hw @@ -905,7 +940,7 @@ static struct clk_branch gcc_blsp1_qup5_i2c_apps_clk = { .clkr = { .enable_reg = 0x06024, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_blsp1_qup5_i2c_apps_clk", .parent_hws = (const struct clk_hw *[]) { &blsp1_qup5_i2c_apps_clk_src.clkr.hw @@ -922,7 +957,7 @@ static struct clk_branch gcc_blsp1_qup5_spi_apps_clk = { .clkr = { .enable_reg = 0x06020, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_blsp1_qup5_spi_apps_clk", .parent_hws = (const struct clk_hw *[]) { &blsp1_qup5_spi_apps_clk_src.clkr.hw @@ -939,7 +974,7 @@ static struct clk_branch gcc_blsp1_qup6_i2c_apps_clk = { .clkr = { .enable_reg = 0x07024, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_blsp1_qup6_i2c_apps_clk", .parent_hws = (const struct clk_hw *[]) { &blsp1_qup6_i2c_apps_clk_src.clkr.hw @@ -956,7 +991,7 @@ static struct clk_branch gcc_blsp1_qup6_spi_apps_clk = { .clkr = { .enable_reg = 0x07020, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_blsp1_qup6_spi_apps_clk", .parent_hws = (const struct clk_hw *[]) { &blsp1_qup6_spi_apps_clk_src.clkr.hw @@ -973,7 +1008,7 @@ static struct clk_branch gcc_blsp1_uart1_apps_clk = { .clkr = { .enable_reg = 0x02040, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_blsp1_uart1_apps_clk", .parent_hws = (const struct clk_hw *[]) { &blsp1_uart1_apps_clk_src.clkr.hw @@ -990,7 +1025,7 @@ static struct clk_branch gcc_blsp1_uart2_apps_clk = { .clkr = { .enable_reg = 0x03040, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_blsp1_uart2_apps_clk", .parent_hws = (const struct clk_hw *[]) { &blsp1_uart2_apps_clk_src.clkr.hw @@ -1007,7 +1042,7 @@ static struct clk_branch gcc_blsp1_uart3_apps_clk = { .clkr = { .enable_reg = 0x04054, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_blsp1_uart3_apps_clk", .parent_hws = (const struct clk_hw *[]) { &blsp1_uart3_apps_clk_src.clkr.hw @@ -1024,7 +1059,7 @@ static struct clk_branch gcc_blsp1_uart4_apps_clk = { .clkr = { .enable_reg = 0x05040, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_blsp1_uart4_apps_clk", .parent_hws = (const struct clk_hw *[]) { &blsp1_uart4_apps_clk_src.clkr.hw @@ -1041,7 +1076,7 @@ static struct clk_branch gcc_blsp1_uart5_apps_clk = { .clkr = { .enable_reg = 0x06040, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_blsp1_uart5_apps_clk", .parent_hws = (const struct clk_hw *[]) { &blsp1_uart5_apps_clk_src.clkr.hw @@ -1058,7 +1093,7 @@ static struct clk_branch gcc_blsp1_uart6_apps_clk = { .clkr = { .enable_reg = 0x07040, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_blsp1_uart6_apps_clk", .parent_hws = (const struct clk_hw *[]) { &blsp1_uart6_apps_clk_src.clkr.hw @@ -1080,7 +1115,7 @@ static struct clk_rcg2 pcie0_axi_m_clk_src = { .freq_tbl = ftbl_pcie0_axi_m_clk_src, .hid_width = 5, .parent_map = gcc_xo_gpll0_gpll4_map, - .clkr.hw.init = &(struct clk_init_data) { + .clkr.hw.init = &(const struct clk_init_data) { .name = "pcie0_axi_m_clk_src", .parent_data = gcc_xo_gpll0_gpll4, .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll4), @@ -1093,7 +1128,7 @@ static struct clk_branch gcc_pcie0_axi_m_clk = { .clkr = { .enable_reg = 0x28038, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_pcie0_axi_m_clk", .parent_hws = (const struct clk_hw *[]) { &pcie0_axi_m_clk_src.clkr.hw @@ -1110,7 +1145,7 @@ static struct clk_branch gcc_anoc_pcie0_1lane_m_clk = { .clkr = { .enable_reg = 0x2e07c, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_anoc_pcie0_1lane_m_clk", .parent_hws = (const struct clk_hw *[]) { &pcie0_axi_m_clk_src.clkr.hw @@ -1127,7 +1162,7 @@ static struct clk_rcg2 pcie1_axi_m_clk_src = { .freq_tbl = ftbl_pcie0_axi_m_clk_src, .hid_width = 5, .parent_map = gcc_xo_gpll0_gpll4_map, - .clkr.hw.init = &(struct clk_init_data) { + .clkr.hw.init = &(const struct clk_init_data) { .name = "pcie1_axi_m_clk_src", .parent_data = gcc_xo_gpll0_gpll4, .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll4), @@ -1140,7 +1175,7 @@ static struct clk_branch gcc_pcie1_axi_m_clk = { .clkr = { .enable_reg = 0x29038, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_pcie1_axi_m_clk", .parent_hws = (const struct clk_hw *[]) { &pcie1_axi_m_clk_src.clkr.hw @@ -1157,7 +1192,7 @@ static struct clk_branch gcc_anoc_pcie1_1lane_m_clk = { .clkr = { .enable_reg = 0x2e08c, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_anoc_pcie1_1lane_m_clk", .parent_hws = (const struct clk_hw *[]) { &pcie1_axi_m_clk_src.clkr.hw @@ -1179,7 +1214,7 @@ static struct clk_rcg2 pcie2_axi_m_clk_src = { .freq_tbl = ftbl_pcie2_axi_m_clk_src, .hid_width = 5, .parent_map = gcc_xo_gpll0_gpll4_bias_pll_ubi_nc_clk_map, - .clkr.hw.init = &(struct clk_init_data) { + .clkr.hw.init = &(const struct clk_init_data) { .name = "pcie2_axi_m_clk_src", .parent_data = gcc_xo_gpll0_gpll4_bias_pll_ubi_nc_clk, .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll4_bias_pll_ubi_nc_clk), @@ -1192,7 +1227,7 @@ static struct clk_branch gcc_pcie2_axi_m_clk = { .clkr = { .enable_reg = 0x2a038, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_pcie2_axi_m_clk", .parent_hws = (const struct clk_hw *[]) { &pcie2_axi_m_clk_src.clkr.hw @@ -1209,7 +1244,7 @@ static struct clk_branch gcc_anoc_pcie2_2lane_m_clk = { .clkr = { .enable_reg = 0x2e080, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_anoc_pcie2_2lane_m_clk", .parent_hws = (const struct clk_hw *[]) { &pcie2_axi_m_clk_src.clkr.hw @@ -1226,7 +1261,7 @@ static struct clk_rcg2 pcie3_axi_m_clk_src = { .freq_tbl = ftbl_pcie2_axi_m_clk_src, .hid_width = 5, .parent_map = gcc_xo_gpll0_gpll4_bias_pll_ubi_nc_clk_map, - .clkr.hw.init = &(struct clk_init_data) { + .clkr.hw.init = &(const struct clk_init_data) { .name = "pcie3_axi_m_clk_src", .parent_data = gcc_xo_gpll0_gpll4_bias_pll_ubi_nc_clk, .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll4_bias_pll_ubi_nc_clk), @@ -1239,7 +1274,7 @@ static struct clk_branch gcc_pcie3_axi_m_clk = { .clkr = { .enable_reg = 0x2b038, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_pcie3_axi_m_clk", .parent_hws = (const struct clk_hw *[]) { &pcie3_axi_m_clk_src.clkr.hw @@ -1256,7 +1291,7 @@ static struct clk_branch gcc_anoc_pcie3_2lane_m_clk = { .clkr = { .enable_reg = 0x2e090, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_anoc_pcie3_2lane_m_clk", .parent_hws = (const struct clk_hw *[]) { &pcie3_axi_m_clk_src.clkr.hw @@ -1273,7 +1308,7 @@ static struct clk_rcg2 pcie0_axi_s_clk_src = { .freq_tbl = ftbl_pcie0_axi_m_clk_src, .hid_width = 5, .parent_map = gcc_xo_gpll0_gpll4_map, - .clkr.hw.init = &(struct clk_init_data) { + .clkr.hw.init = &(const struct clk_init_data) { .name = "pcie0_axi_s_clk_src", .parent_data = gcc_xo_gpll0_gpll4, .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll4), @@ -1286,7 +1321,7 @@ static struct clk_branch gcc_pcie0_axi_s_clk = { .clkr = { .enable_reg = 0x2803c, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_pcie0_axi_s_clk", .parent_hws = (const struct clk_hw *[]) { &pcie0_axi_s_clk_src.clkr.hw @@ -1303,7 +1338,7 @@ static struct clk_branch gcc_pcie0_axi_s_bridge_clk = { .clkr = { .enable_reg = 0x28040, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_pcie0_axi_s_bridge_clk", .parent_hws = (const struct clk_hw *[]) { &pcie0_axi_s_clk_src.clkr.hw @@ -1320,7 +1355,7 @@ static struct clk_branch gcc_snoc_pcie0_1lane_s_clk = { .clkr = { .enable_reg = 0x2e048, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_snoc_pcie0_1lane_s_clk", .parent_hws = (const struct clk_hw *[]) { &pcie0_axi_s_clk_src.clkr.hw @@ -1337,7 +1372,7 @@ static struct clk_rcg2 pcie1_axi_s_clk_src = { .freq_tbl = ftbl_pcie0_axi_m_clk_src, .hid_width = 5, .parent_map = gcc_xo_gpll0_gpll4_map, - .clkr.hw.init = &(struct clk_init_data) { + .clkr.hw.init = &(const struct clk_init_data) { .name = "pcie1_axi_s_clk_src", .parent_data = gcc_xo_gpll0_gpll4, .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll4), @@ -1350,7 +1385,7 @@ static struct clk_branch gcc_pcie1_axi_s_clk = { .clkr = { .enable_reg = 0x2903c, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_pcie1_axi_s_clk", .parent_hws = (const struct clk_hw *[]) { &pcie1_axi_s_clk_src.clkr.hw @@ -1367,7 +1402,7 @@ static struct clk_branch gcc_pcie1_axi_s_bridge_clk = { .clkr = { .enable_reg = 0x29040, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_pcie1_axi_s_bridge_clk", .parent_hws = (const struct clk_hw *[]) { &pcie1_axi_s_clk_src.clkr.hw @@ -1384,7 +1419,7 @@ static struct clk_branch gcc_snoc_pcie1_1lane_s_clk = { .clkr = { .enable_reg = 0x2e04c, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_snoc_pcie1_1lane_s_clk", .parent_hws = (const struct clk_hw *[]) { &pcie1_axi_s_clk_src.clkr.hw @@ -1401,7 +1436,7 @@ static struct clk_rcg2 pcie2_axi_s_clk_src = { .freq_tbl = ftbl_pcie0_axi_m_clk_src, .hid_width = 5, .parent_map = gcc_xo_gpll0_gpll4_map, - .clkr.hw.init = &(struct clk_init_data) { + .clkr.hw.init = &(const struct clk_init_data) { .name = "pcie2_axi_s_clk_src", .parent_data = gcc_xo_gpll0_gpll4, .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll4), @@ -1414,7 +1449,7 @@ static struct clk_branch gcc_pcie2_axi_s_clk = { .clkr = { .enable_reg = 0x2a03c, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_pcie2_axi_s_clk", .parent_hws = (const struct clk_hw *[]) { &pcie2_axi_s_clk_src.clkr.hw @@ -1431,7 +1466,7 @@ static struct clk_branch gcc_pcie2_axi_s_bridge_clk = { .clkr = { .enable_reg = 0x2a040, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_pcie2_axi_s_bridge_clk", .parent_hws = (const struct clk_hw *[]) { &pcie2_axi_s_clk_src.clkr.hw @@ -1448,7 +1483,7 @@ static struct clk_branch gcc_snoc_pcie2_2lane_s_clk = { .clkr = { .enable_reg = 0x2e050, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_snoc_pcie2_2lane_s_clk", .parent_hws = (const struct clk_hw *[]) { &pcie2_axi_s_clk_src.clkr.hw @@ -1465,7 +1500,7 @@ static struct clk_rcg2 pcie3_axi_s_clk_src = { .freq_tbl = ftbl_pcie0_axi_m_clk_src, .hid_width = 5, .parent_map = gcc_xo_gpll0_gpll4_map, - .clkr.hw.init = &(struct clk_init_data) { + .clkr.hw.init = &(const struct clk_init_data) { .name = "pcie3_axi_s_clk_src", .parent_data = gcc_xo_gpll0_gpll4, .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll4), @@ -1478,7 +1513,7 @@ static struct clk_branch gcc_pcie3_axi_s_clk = { .clkr = { .enable_reg = 0x2b03c, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_pcie3_axi_s_clk", .parent_hws = (const struct clk_hw *[]) { &pcie3_axi_s_clk_src.clkr.hw @@ -1495,7 +1530,7 @@ static struct clk_branch gcc_pcie3_axi_s_bridge_clk = { .clkr = { .enable_reg = 0x2b040, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_pcie3_axi_s_bridge_clk", .parent_hws = (const struct clk_hw *[]) { &pcie3_axi_s_clk_src.clkr.hw @@ -1512,7 +1547,7 @@ static struct clk_branch gcc_snoc_pcie3_2lane_s_clk = { .clkr = { .enable_reg = 0x2e054, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_snoc_pcie3_2lane_s_clk", .parent_hws = (const struct clk_hw *[]) { &pcie3_axi_s_clk_src.clkr.hw @@ -1527,7 +1562,7 @@ static struct clk_branch gcc_snoc_pcie3_2lane_s_clk = { static struct clk_regmap_phy_mux pcie0_pipe_clk_src = { .reg = 0x28064, .clkr = { - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "pcie0_pipe_clk_src", .parent_data = &(const struct clk_parent_data) { .index = DT_PCIE30_PHY0_PIPE_CLK, @@ -1541,7 +1576,7 @@ static struct clk_regmap_phy_mux pcie0_pipe_clk_src = { static struct clk_regmap_phy_mux pcie1_pipe_clk_src = { .reg = 0x29064, .clkr = { - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "pcie1_pipe_clk_src", .parent_data = &(const struct clk_parent_data) { .index = DT_PCIE30_PHY1_PIPE_CLK, @@ -1555,7 +1590,7 @@ static struct clk_regmap_phy_mux pcie1_pipe_clk_src = { static struct clk_regmap_phy_mux pcie2_pipe_clk_src = { .reg = 0x2a064, .clkr = { - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "pcie2_pipe_clk_src", .parent_data = &(const struct clk_parent_data) { .index = DT_PCIE30_PHY2_PIPE_CLK, @@ -1569,7 +1604,7 @@ static struct clk_regmap_phy_mux pcie2_pipe_clk_src = { static struct clk_regmap_phy_mux pcie3_pipe_clk_src = { .reg = 0x2b064, .clkr = { - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "pcie3_pipe_clk_src", .parent_data = &(const struct clk_parent_data) { .index = DT_PCIE30_PHY3_PIPE_CLK, @@ -1591,7 +1626,7 @@ static struct clk_rcg2 pcie0_rchng_clk_src = { .freq_tbl = ftbl_pcie_rchng_clk_src, .hid_width = 5, .parent_map = gcc_xo_gpll0_map, - .clkr.hw.init = &(struct clk_init_data) { + .clkr.hw.init = &(const struct clk_init_data) { .name = "pcie0_rchng_clk_src", .parent_data = gcc_xo_gpll0, .num_parents = ARRAY_SIZE(gcc_xo_gpll0), @@ -1604,7 +1639,7 @@ static struct clk_branch gcc_pcie0_rchng_clk = { .clkr = { .enable_reg = 0x28028, .enable_mask = BIT(1), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_pcie0_rchng_clk", .parent_hws = (const struct clk_hw *[]) { &pcie0_rchng_clk_src.clkr.hw @@ -1622,7 +1657,7 @@ static struct clk_rcg2 pcie1_rchng_clk_src = { .freq_tbl = ftbl_pcie_rchng_clk_src, .hid_width = 5, .parent_map = gcc_xo_gpll0_map, - .clkr.hw.init = &(struct clk_init_data) { + .clkr.hw.init = &(const struct clk_init_data) { .name = "pcie1_rchng_clk_src", .parent_data = gcc_xo_gpll0, .num_parents = ARRAY_SIZE(gcc_xo_gpll0), @@ -1635,7 +1670,7 @@ static struct clk_branch gcc_pcie1_rchng_clk = { .clkr = { .enable_reg = 0x29028, .enable_mask = BIT(1), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_pcie1_rchng_clk", .parent_hws = (const struct clk_hw *[]) { &pcie1_rchng_clk_src.clkr.hw @@ -1652,7 +1687,7 @@ static struct clk_rcg2 pcie2_rchng_clk_src = { .freq_tbl = ftbl_pcie_rchng_clk_src, .hid_width = 5, .parent_map = gcc_xo_gpll0_map, - .clkr.hw.init = &(struct clk_init_data) { + .clkr.hw.init = &(const struct clk_init_data) { .name = "pcie2_rchng_clk_src", .parent_data = gcc_xo_gpll0, .num_parents = ARRAY_SIZE(gcc_xo_gpll0), @@ -1665,7 +1700,7 @@ static struct clk_branch gcc_pcie2_rchng_clk = { .clkr = { .enable_reg = 0x2a028, .enable_mask = BIT(1), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_pcie2_rchng_clk", .parent_hws = (const struct clk_hw *[]) { &pcie2_rchng_clk_src.clkr.hw @@ -1682,7 +1717,7 @@ static struct clk_rcg2 pcie3_rchng_clk_src = { .freq_tbl = ftbl_pcie_rchng_clk_src, .hid_width = 5, .parent_map = gcc_xo_gpll0_map, - .clkr.hw.init = &(struct clk_init_data) { + .clkr.hw.init = &(const struct clk_init_data) { .name = "pcie3_rchng_clk_src", .parent_data = gcc_xo_gpll0, .num_parents = ARRAY_SIZE(gcc_xo_gpll0), @@ -1695,7 +1730,7 @@ static struct clk_branch gcc_pcie3_rchng_clk = { .clkr = { .enable_reg = 0x2b028, .enable_mask = BIT(1), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_pcie3_rchng_clk", .parent_hws = (const struct clk_hw *[]) { &pcie3_rchng_clk_src.clkr.hw @@ -1718,7 +1753,7 @@ static struct clk_rcg2 pcie_aux_clk_src = { .mnd_width = 16, .hid_width = 5, .parent_map = gcc_xo_gpll0_gpll0_aux_core_pi_sleep_clk_map, - .clkr.hw.init = &(struct clk_init_data) { + .clkr.hw.init = &(const struct clk_init_data) { .name = "pcie_aux_clk_src", .parent_data = gcc_xo_gpll0_gpll0_aux_core_pi_sleep_clk, .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_aux_core_pi_sleep_clk), @@ -1731,7 +1766,7 @@ static struct clk_branch gcc_pcie0_aux_clk = { .clkr = { .enable_reg = 0x28034, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_pcie0_aux_clk", .parent_hws = (const struct clk_hw *[]) { &pcie_aux_clk_src.clkr.hw @@ -1748,7 +1783,7 @@ static struct clk_branch gcc_pcie1_aux_clk = { .clkr = { .enable_reg = 0x29034, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_pcie1_aux_clk", .parent_hws = (const struct clk_hw *[]) { &pcie_aux_clk_src.clkr.hw @@ -1765,7 +1800,7 @@ static struct clk_branch gcc_pcie2_aux_clk = { .clkr = { .enable_reg = 0x2a034, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_pcie2_aux_clk", .parent_hws = (const struct clk_hw *[]) { &pcie_aux_clk_src.clkr.hw @@ -1782,7 +1817,7 @@ static struct clk_branch gcc_pcie3_aux_clk = { .clkr = { .enable_reg = 0x2b034, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_pcie3_aux_clk", .parent_hws = (const struct clk_hw *[]) { &pcie_aux_clk_src.clkr.hw @@ -1805,7 +1840,7 @@ static struct clk_rcg2 usb0_aux_clk_src = { .mnd_width = 16, .hid_width = 5, .parent_map = gcc_xo_gpll0_core_pi_sleep_clk_map, - .clkr.hw.init = &(struct clk_init_data) { + .clkr.hw.init = &(const struct clk_init_data) { .name = "usb0_aux_clk_src", .parent_data = gcc_xo_gpll0_core_pi_sleep_clk, .num_parents = ARRAY_SIZE(gcc_xo_gpll0_core_pi_sleep_clk), @@ -1818,7 +1853,7 @@ static struct clk_branch gcc_usb0_aux_clk = { .clkr = { .enable_reg = 0x2c048, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_usb0_aux_clk", .parent_hws = (const struct clk_hw *[]) { &usb0_aux_clk_src.clkr.hw @@ -1842,7 +1877,7 @@ static struct clk_rcg2 usb0_master_clk_src = { .mnd_width = 8, .hid_width = 5, .parent_map = gcc_xo_gpll0_out_main_div2_gpll0_map, - .clkr.hw.init = &(struct clk_init_data) { + .clkr.hw.init = &(const struct clk_init_data) { .name = "usb0_master_clk_src", .parent_data = gcc_xo_gpll0_out_main_div2_gpll0, .num_parents = ARRAY_SIZE(gcc_xo_gpll0_out_main_div2_gpll0), @@ -1855,7 +1890,7 @@ static struct clk_branch gcc_usb0_master_clk = { .clkr = { .enable_reg = 0x2c044, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_usb0_master_clk", .parent_hws = (const struct clk_hw *[]) { &usb0_master_clk_src.clkr.hw @@ -1872,7 +1907,7 @@ static struct clk_branch gcc_snoc_usb_clk = { .clkr = { .enable_reg = 0x2e058, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_snoc_usb_clk", .parent_hws = (const struct clk_hw *[]) { &usb0_master_clk_src.clkr.hw @@ -1889,7 +1924,7 @@ static struct clk_branch gcc_anoc_usb_axi_clk = { .clkr = { .enable_reg = 0x2e084, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_anoc_usb_axi_clk", .parent_hws = (const struct clk_hw *[]) { &usb0_master_clk_src.clkr.hw @@ -1913,7 +1948,7 @@ static struct clk_rcg2 usb0_mock_utmi_clk_src = { .mnd_width = 8, .hid_width = 5, .parent_map = gcc_xo_gpll4_gpll0_gpll0_out_main_div2_map, - .clkr.hw.init = &(struct clk_init_data) { + .clkr.hw.init = &(const struct clk_init_data) { .name = "usb0_mock_utmi_clk_src", .parent_data = gcc_xo_gpll4_gpll0_gpll0_out_main_div2, .num_parents = ARRAY_SIZE(gcc_xo_gpll4_gpll0_gpll0_out_main_div2), @@ -1925,7 +1960,7 @@ static struct clk_regmap_div usb0_mock_utmi_div_clk_src = { .reg = 0x2c040, .shift = 0, .width = 2, - .clkr.hw.init = &(struct clk_init_data) { + .clkr.hw.init = &(const struct clk_init_data) { .name = "usb0_mock_utmi_div_clk_src", .parent_data = &(const struct clk_parent_data) { .hw = &usb0_mock_utmi_clk_src.clkr.hw, @@ -1941,7 +1976,7 @@ static struct clk_branch gcc_usb0_mock_utmi_clk = { .clkr = { .enable_reg = 0x2c04c, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_usb0_mock_utmi_clk", .parent_hws = (const struct clk_hw *[]) { &usb0_mock_utmi_div_clk_src.clkr.hw @@ -1959,7 +1994,7 @@ static struct clk_regmap_mux usb0_pipe_clk_src = { .width = 2, .parent_map = gcc_usb3phy_0_cc_pipe_clk_xo_map, .clkr = { - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "usb0_pipe_clk_src", .parent_data = gcc_usb3phy_0_cc_pipe_clk_xo, .num_parents = ARRAY_SIZE(gcc_usb3phy_0_cc_pipe_clk_xo), @@ -1988,7 +2023,7 @@ static struct clk_rcg2 sdcc1_apps_clk_src = { .mnd_width = 8, .hid_width = 5, .parent_map = gcc_xo_gpll0_gpll2_gpll0_out_main_div2_map, - .clkr.hw.init = &(struct clk_init_data) { + .clkr.hw.init = &(const struct clk_init_data) { .name = "sdcc1_apps_clk_src", .parent_data = gcc_xo_gpll0_gpll2_gpll0_out_main_div2, .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll2_gpll0_out_main_div2), @@ -2001,7 +2036,7 @@ static struct clk_branch gcc_sdcc1_apps_clk = { .clkr = { .enable_reg = 0x3302c, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_sdcc1_apps_clk", .parent_hws = (const struct clk_hw *[]) { &sdcc1_apps_clk_src.clkr.hw @@ -2024,7 +2059,7 @@ static struct clk_rcg2 sdcc1_ice_core_clk_src = { .mnd_width = 8, .hid_width = 5, .parent_map = gcc_xo_gpll0_gpll4_gpll0_div2_map, - .clkr.hw.init = &(struct clk_init_data) { + .clkr.hw.init = &(const struct clk_init_data) { .name = "sdcc1_ice_core_clk_src", .parent_data = gcc_xo_gpll0_gpll4_gpll0_div2, .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll4_gpll0_div2), @@ -2037,7 +2072,7 @@ static struct clk_branch gcc_sdcc1_ice_core_clk = { .clkr = { .enable_reg = 0x33030, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_sdcc1_ice_core_clk", .parent_hws = (const struct clk_hw *[]) { &sdcc1_ice_core_clk_src.clkr.hw @@ -2062,7 +2097,7 @@ static struct clk_rcg2 pcnoc_bfdcd_clk_src = { .freq_tbl = ftbl_pcnoc_bfdcd_clk_src, .hid_width = 5, .parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map, - .clkr.hw.init = &(struct clk_init_data) { + .clkr.hw.init = &(const struct clk_init_data) { .name = "pcnoc_bfdcd_clk_src", .parent_data = gcc_xo_gpll0_gpll0_out_main_div2, .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_out_main_div2), @@ -2071,12 +2106,44 @@ static struct clk_rcg2 pcnoc_bfdcd_clk_src = { }, }; +static struct clk_branch gcc_crypto_axi_clk = { + .halt_reg = 0x16010, + .clkr = { + .enable_reg = 0x16010, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_crypto_axi_clk", + .parent_hws = (const struct clk_hw *[]) { + &pcnoc_bfdcd_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_crypto_ahb_clk = { + .halt_reg = 0x16014, + .clkr = { + .enable_reg = 0x16014, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_crypto_ahb_clk", + .parent_hws = (const struct clk_hw *[]) { + &pcnoc_bfdcd_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + static struct clk_branch gcc_nsscfg_clk = { .halt_reg = 0x1702c, .clkr = { .enable_reg = 0x1702c, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_nsscfg_clk", .parent_hws = (const struct clk_hw *[]) { &pcnoc_bfdcd_clk_src.clkr.hw @@ -2093,7 +2160,7 @@ static struct clk_branch gcc_nssnoc_nsscc_clk = { .clkr = { .enable_reg = 0x17030, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_nssnoc_nsscc_clk", .parent_hws = (const struct clk_hw *[]) { &pcnoc_bfdcd_clk_src.clkr.hw @@ -2110,7 +2177,7 @@ static struct clk_branch gcc_nsscc_clk = { .clkr = { .enable_reg = 0x17034, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_nsscc_clk", .parent_hws = (const struct clk_hw *[]) { &pcnoc_bfdcd_clk_src.clkr.hw @@ -2127,7 +2194,7 @@ static struct clk_branch gcc_nssnoc_pcnoc_1_clk = { .clkr = { .enable_reg = 0x17080, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_nssnoc_pcnoc_1_clk", .parent_hws = (const struct clk_hw *[]) { &pcnoc_bfdcd_clk_src.clkr.hw @@ -2144,7 +2211,7 @@ static struct clk_branch gcc_qdss_dap_ahb_clk = { .clkr = { .enable_reg = 0x2d064, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_qdss_dap_ahb_clk", .parent_hws = (const struct clk_hw *[]) { &pcnoc_bfdcd_clk_src.clkr.hw @@ -2161,7 +2228,7 @@ static struct clk_branch gcc_qdss_cfg_ahb_clk = { .clkr = { .enable_reg = 0x2d068, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_qdss_cfg_ahb_clk", .parent_hws = (const struct clk_hw *[]) { &pcnoc_bfdcd_clk_src.clkr.hw @@ -2178,7 +2245,7 @@ static struct clk_branch gcc_qpic_ahb_clk = { .clkr = { .enable_reg = 0x32010, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_qpic_ahb_clk", .parent_hws = (const struct clk_hw *[]) { &pcnoc_bfdcd_clk_src.clkr.hw @@ -2195,7 +2262,7 @@ static struct clk_branch gcc_qpic_clk = { .clkr = { .enable_reg = 0x32014, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_qpic_clk", .parent_hws = (const struct clk_hw *[]) { &pcnoc_bfdcd_clk_src.clkr.hw @@ -2213,7 +2280,7 @@ static struct clk_branch gcc_blsp1_ahb_clk = { .clkr = { .enable_reg = 0x0b004, .enable_mask = BIT(4), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_blsp1_ahb_clk", .parent_hws = (const struct clk_hw *[]) { &pcnoc_bfdcd_clk_src.clkr.hw @@ -2230,7 +2297,7 @@ static struct clk_branch gcc_mdio_ahb_clk = { .clkr = { .enable_reg = 0x17040, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_mdio_ahb_clk", .parent_hws = (const struct clk_hw *[]) { &pcnoc_bfdcd_clk_src.clkr.hw @@ -2248,7 +2315,7 @@ static struct clk_branch gcc_prng_ahb_clk = { .clkr = { .enable_reg = 0x0b004, .enable_mask = BIT(10), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_prng_ahb_clk", .parent_hws = (const struct clk_hw *[]) { &pcnoc_bfdcd_clk_src.clkr.hw @@ -2265,7 +2332,7 @@ static struct clk_branch gcc_uniphy0_ahb_clk = { .clkr = { .enable_reg = 0x1704c, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_uniphy0_ahb_clk", .parent_hws = (const struct clk_hw *[]) { &pcnoc_bfdcd_clk_src.clkr.hw @@ -2282,7 +2349,7 @@ static struct clk_branch gcc_uniphy1_ahb_clk = { .clkr = { .enable_reg = 0x1705c, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_uniphy1_ahb_clk", .parent_hws = (const struct clk_hw *[]) { &pcnoc_bfdcd_clk_src.clkr.hw @@ -2299,7 +2366,7 @@ static struct clk_branch gcc_uniphy2_ahb_clk = { .clkr = { .enable_reg = 0x1706c, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_uniphy2_ahb_clk", .parent_hws = (const struct clk_hw *[]) { &pcnoc_bfdcd_clk_src.clkr.hw @@ -2316,7 +2383,7 @@ static struct clk_branch gcc_cmn_12gpll_ahb_clk = { .clkr = { .enable_reg = 0x3a004, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_cmn_12gpll_ahb_clk", .parent_hws = (const struct clk_hw *[]) { &pcnoc_bfdcd_clk_src.clkr.hw @@ -2333,7 +2400,7 @@ static struct clk_branch gcc_cmn_12gpll_apu_clk = { .clkr = { .enable_reg = 0x3a00c, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_cmn_12gpll_apu_clk", .parent_hws = (const struct clk_hw *[]) { &pcnoc_bfdcd_clk_src.clkr.hw @@ -2350,7 +2417,7 @@ static struct clk_branch gcc_pcie0_ahb_clk = { .clkr = { .enable_reg = 0x28030, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_pcie0_ahb_clk", .parent_hws = (const struct clk_hw *[]) { &pcnoc_bfdcd_clk_src.clkr.hw @@ -2367,7 +2434,7 @@ static struct clk_branch gcc_pcie1_ahb_clk = { .clkr = { .enable_reg = 0x29030, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_pcie1_ahb_clk", .parent_hws = (const struct clk_hw *[]) { &pcnoc_bfdcd_clk_src.clkr.hw @@ -2384,7 +2451,7 @@ static struct clk_branch gcc_pcie2_ahb_clk = { .clkr = { .enable_reg = 0x2a030, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_pcie2_ahb_clk", .parent_hws = (const struct clk_hw *[]) { &pcnoc_bfdcd_clk_src.clkr.hw @@ -2401,7 +2468,7 @@ static struct clk_branch gcc_pcie3_ahb_clk = { .clkr = { .enable_reg = 0x2b030, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_pcie3_ahb_clk", .parent_hws = (const struct clk_hw *[]) { &pcnoc_bfdcd_clk_src.clkr.hw @@ -2418,7 +2485,7 @@ static struct clk_branch gcc_usb0_phy_cfg_ahb_clk = { .clkr = { .enable_reg = 0x2c05c, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_usb0_phy_cfg_ahb_clk", .parent_hws = (const struct clk_hw *[]) { &pcnoc_bfdcd_clk_src.clkr.hw @@ -2435,7 +2502,7 @@ static struct clk_branch gcc_sdcc1_ahb_clk = { .clkr = { .enable_reg = 0x33034, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_sdcc1_ahb_clk", .parent_hws = (const struct clk_hw *[]) { &pcnoc_bfdcd_clk_src.clkr.hw @@ -2460,7 +2527,7 @@ static struct clk_rcg2 system_noc_bfdcd_clk_src = { .freq_tbl = ftbl_system_noc_bfdcd_clk_src, .hid_width = 5, .parent_map = gcc_xo_gpll0_gpll4_map, - .clkr.hw.init = &(struct clk_init_data) { + .clkr.hw.init = &(const struct clk_init_data) { .name = "system_noc_bfdcd_clk_src", .parent_data = gcc_xo_gpll0_gpll4, .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll4), @@ -2475,7 +2542,7 @@ static struct clk_branch gcc_q6ss_boot_clk = { .clkr = { .enable_reg = 0x25080, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_q6ss_boot_clk", .parent_hws = (const struct clk_hw *[]) { &system_noc_bfdcd_clk_src.clkr.hw @@ -2492,7 +2559,7 @@ static struct clk_branch gcc_nssnoc_snoc_clk = { .clkr = { .enable_reg = 0x17028, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_nssnoc_snoc_clk", .parent_hws = (const struct clk_hw *[]) { &system_noc_bfdcd_clk_src.clkr.hw @@ -2509,7 +2576,7 @@ static struct clk_branch gcc_nssnoc_snoc_1_clk = { .clkr = { .enable_reg = 0x1707c, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_nssnoc_snoc_1_clk", .parent_hws = (const struct clk_hw *[]) { &system_noc_bfdcd_clk_src.clkr.hw @@ -2526,7 +2593,7 @@ static struct clk_branch gcc_qdss_etr_usb_clk = { .clkr = { .enable_reg = 0x2d060, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_qdss_etr_usb_clk", .parent_hws = (const struct clk_hw *[]) { &system_noc_bfdcd_clk_src.clkr.hw @@ -2549,7 +2616,7 @@ static struct clk_rcg2 wcss_ahb_clk_src = { .freq_tbl = ftbl_wcss_ahb_clk_src, .hid_width = 5, .parent_map = gcc_xo_gpll0_map, - .clkr.hw.init = &(struct clk_init_data) { + .clkr.hw.init = &(const struct clk_init_data) { .name = "wcss_ahb_clk_src", .parent_data = gcc_xo_gpll0, .num_parents = ARRAY_SIZE(gcc_xo_gpll0), @@ -2562,7 +2629,7 @@ static struct clk_branch gcc_q6_ahb_clk = { .clkr = { .enable_reg = 0x25014, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_q6_ahb_clk", .parent_hws = (const struct clk_hw *[]) { &wcss_ahb_clk_src.clkr.hw @@ -2579,7 +2646,7 @@ static struct clk_branch gcc_q6_ahb_s_clk = { .clkr = { .enable_reg = 0x25018, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_q6_ahb_s_clk", .parent_hws = (const struct clk_hw *[]) { &wcss_ahb_clk_src.clkr.hw @@ -2596,7 +2663,7 @@ static struct clk_branch gcc_wcss_ecahb_clk = { .clkr = { .enable_reg = 0x25058, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_wcss_ecahb_clk", .parent_hws = (const struct clk_hw *[]) { &wcss_ahb_clk_src.clkr.hw @@ -2613,7 +2680,7 @@ static struct clk_branch gcc_wcss_acmt_clk = { .clkr = { .enable_reg = 0x2505c, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_wcss_acmt_clk", .parent_hws = (const struct clk_hw *[]) { &wcss_ahb_clk_src.clkr.hw @@ -2630,7 +2697,7 @@ static struct clk_branch gcc_sys_noc_wcss_ahb_clk = { .clkr = { .enable_reg = 0x2e030, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_sys_noc_wcss_ahb_clk", .parent_hws = (const struct clk_hw *[]) { &wcss_ahb_clk_src.clkr.hw @@ -2654,7 +2721,7 @@ static struct clk_rcg2 wcss_axi_m_clk_src = { .freq_tbl = ftbl_wcss_axi_m_clk_src, .hid_width = 5, .parent_map = gcc_xo_gpll0_map, - .clkr.hw.init = &(struct clk_init_data) { + .clkr.hw.init = &(const struct clk_init_data) { .name = "wcss_axi_m_clk_src", .parent_data = gcc_xo_gpll0, .num_parents = ARRAY_SIZE(gcc_xo_gpll0), @@ -2667,7 +2734,7 @@ static struct clk_branch gcc_anoc_wcss_axi_m_clk = { .clkr = { .enable_reg = 0x2e0a8, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_anoc_wcss_axi_m_clk", .parent_hws = (const struct clk_hw *[]) { &wcss_axi_m_clk_src.clkr.hw @@ -2689,7 +2756,7 @@ static struct clk_rcg2 qdss_at_clk_src = { .freq_tbl = ftbl_qdss_at_clk_src, .hid_width = 5, .parent_map = gcc_xo_gpll4_gpll0_gpll0_div2_map, - .clkr.hw.init = &(struct clk_init_data) { + .clkr.hw.init = &(const struct clk_init_data) { .name = "qdss_at_clk_src", .parent_data = gcc_xo_gpll4_gpll0_gpll0_div2, .num_parents = ARRAY_SIZE(gcc_xo_gpll4_gpll0_gpll0_div2), @@ -2702,7 +2769,7 @@ static struct clk_branch gcc_q6ss_atbm_clk = { .clkr = { .enable_reg = 0x2501c, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_q6ss_atbm_clk", .parent_hws = (const struct clk_hw *[]) { &qdss_at_clk_src.clkr.hw @@ -2719,7 +2786,7 @@ static struct clk_branch gcc_wcss_dbg_ifc_atb_clk = { .clkr = { .enable_reg = 0x2503c, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_wcss_dbg_ifc_atb_clk", .parent_hws = (const struct clk_hw *[]) { &qdss_at_clk_src.clkr.hw @@ -2736,7 +2803,7 @@ static struct clk_branch gcc_nssnoc_atb_clk = { .clkr = { .enable_reg = 0x17014, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_nssnoc_atb_clk", .parent_hws = (const struct clk_hw *[]) { &qdss_at_clk_src.clkr.hw @@ -2753,7 +2820,7 @@ static struct clk_branch gcc_qdss_at_clk = { .clkr = { .enable_reg = 0x2d038, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_qdss_at_clk", .parent_hws = (const struct clk_hw *[]) { &qdss_at_clk_src.clkr.hw @@ -2770,7 +2837,7 @@ static struct clk_branch gcc_sys_noc_at_clk = { .clkr = { .enable_reg = 0x2e038, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_sys_noc_at_clk", .parent_hws = (const struct clk_hw *[]) { &qdss_at_clk_src.clkr.hw @@ -2787,7 +2854,7 @@ static struct clk_branch gcc_pcnoc_at_clk = { .clkr = { .enable_reg = 0x31024, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_pcnoc_at_clk", .parent_hws = (const struct clk_hw *[]) { &qdss_at_clk_src.clkr.hw @@ -2802,7 +2869,7 @@ static struct clk_branch gcc_pcnoc_at_clk = { static struct clk_fixed_factor gcc_eud_at_div_clk_src = { .mult = 1, .div = 6, - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_eud_at_div_clk_src", .parent_hws = (const struct clk_hw *[]) { &qdss_at_clk_src.clkr.hw @@ -2818,7 +2885,7 @@ static struct clk_branch gcc_usb0_eud_at_clk = { .clkr = { .enable_reg = 0x30004, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_usb0_eud_at_clk", .parent_hws = (const struct clk_hw *[]) { &gcc_eud_at_div_clk_src.hw @@ -2835,7 +2902,7 @@ static struct clk_branch gcc_qdss_eud_at_clk = { .clkr = { .enable_reg = 0x2d06c, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_qdss_eud_at_clk", .parent_hws = (const struct clk_hw *[]) { &gcc_eud_at_div_clk_src.hw @@ -2858,7 +2925,7 @@ static struct clk_rcg2 qdss_stm_clk_src = { .freq_tbl = ftbl_qdss_stm_clk_src, .hid_width = 5, .parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map, - .clkr.hw.init = &(struct clk_init_data) { + .clkr.hw.init = &(const struct clk_init_data) { .name = "qdss_stm_clk_src", .parent_data = gcc_xo_gpll0_gpll0_out_main_div2, .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_out_main_div2), @@ -2871,7 +2938,7 @@ static struct clk_branch gcc_qdss_stm_clk = { .clkr = { .enable_reg = 0x2d03c, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_qdss_stm_clk", .parent_hws = (const struct clk_hw *[]) { &qdss_stm_clk_src.clkr.hw @@ -2888,7 +2955,7 @@ static struct clk_branch gcc_sys_noc_qdss_stm_axi_clk = { .clkr = { .enable_reg = 0x2e034, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_sys_noc_qdss_stm_axi_clk", .parent_hws = (const struct clk_hw *[]) { &qdss_stm_clk_src.clkr.hw @@ -2910,7 +2977,7 @@ static struct clk_rcg2 qdss_traceclkin_clk_src = { .freq_tbl = ftbl_qdss_traceclkin_clk_src, .hid_width = 5, .parent_map = gcc_xo_gpll4_gpll0_gpll0_div2_map, - .clkr.hw.init = &(struct clk_init_data) { + .clkr.hw.init = &(const struct clk_init_data) { .name = "qdss_traceclkin_clk_src", .parent_data = gcc_xo_gpll4_gpll0_gpll0_div2, .num_parents = ARRAY_SIZE(gcc_xo_gpll4_gpll0_gpll0_div2), @@ -2923,7 +2990,7 @@ static struct clk_branch gcc_qdss_traceclkin_clk = { .clkr = { .enable_reg = 0x2d040, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_qdss_traceclkin_clk", .parent_hws = (const struct clk_hw *[]) { &qdss_traceclkin_clk_src.clkr.hw @@ -2945,7 +3012,7 @@ static struct clk_rcg2 qdss_tsctr_clk_src = { .freq_tbl = ftbl_qdss_tsctr_clk_src, .hid_width = 5, .parent_map = gcc_xo_gpll4_gpll0_gpll0_div2_map, - .clkr.hw.init = &(struct clk_init_data) { + .clkr.hw.init = &(const struct clk_init_data) { .name = "qdss_tsctr_clk_src", .parent_data = gcc_xo_gpll4_gpll0_gpll0_div2, .num_parents = ARRAY_SIZE(gcc_xo_gpll4_gpll0_gpll0_div2), @@ -2956,7 +3023,7 @@ static struct clk_rcg2 qdss_tsctr_clk_src = { static struct clk_fixed_factor qdss_tsctr_div2_clk_src = { .mult = 1, .div = 2, - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "qdss_tsctr_div2_clk_src", .parent_hws = (const struct clk_hw *[]) { &qdss_tsctr_clk_src.clkr.hw @@ -2972,7 +3039,7 @@ static struct clk_branch gcc_q6_tsctr_1to2_clk = { .clkr = { .enable_reg = 0x25020, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_q6_tsctr_1to2_clk", .parent_hws = (const struct clk_hw *[]) { &qdss_tsctr_div2_clk_src.hw @@ -2989,7 +3056,7 @@ static struct clk_branch gcc_wcss_dbg_ifc_nts_clk = { .clkr = { .enable_reg = 0x25040, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_wcss_dbg_ifc_nts_clk", .parent_hws = (const struct clk_hw *[]) { &qdss_tsctr_div2_clk_src.hw @@ -3006,7 +3073,7 @@ static struct clk_branch gcc_qdss_tsctr_div2_clk = { .clkr = { .enable_reg = 0x2d044, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_qdss_tsctr_div2_clk", .parent_hws = (const struct clk_hw *[]) { &qdss_tsctr_div2_clk_src.hw @@ -3029,7 +3096,7 @@ static struct clk_rcg2 uniphy_sys_clk_src = { .mnd_width = 8, .hid_width = 5, .parent_map = gcc_xo_map, - .clkr.hw.init = &(struct clk_init_data) { + .clkr.hw.init = &(const struct clk_init_data) { .name = "uniphy_sys_clk_src", .parent_data = gcc_xo_data, .num_parents = ARRAY_SIZE(gcc_xo_data), @@ -3043,7 +3110,7 @@ static struct clk_rcg2 nss_ts_clk_src = { .mnd_width = 8, .hid_width = 5, .parent_map = gcc_xo_map, - .clkr.hw.init = &(struct clk_init_data) { + .clkr.hw.init = &(const struct clk_init_data) { .name = "nss_ts_clk_src", .parent_data = gcc_xo_data, .num_parents = ARRAY_SIZE(gcc_xo_data), @@ -3056,7 +3123,7 @@ static struct clk_branch gcc_qdss_ts_clk = { .clkr = { .enable_reg = 0x2d078, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_qdss_ts_clk", .parent_hws = (const struct clk_hw *[]) { &nss_ts_clk_src.clkr.hw @@ -3071,7 +3138,7 @@ static struct clk_branch gcc_qdss_ts_clk = { static struct clk_fixed_factor qdss_dap_sync_clk_src = { .mult = 1, .div = 4, - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "qdss_dap_sync_clk_src", .parent_hws = (const struct clk_hw *[]) { &qdss_tsctr_clk_src.clkr.hw @@ -3086,7 +3153,7 @@ static struct clk_branch gcc_qdss_tsctr_div4_clk = { .clkr = { .enable_reg = 0x2d04c, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_qdss_tsctr_div4_clk", .parent_hws = (const struct clk_hw *[]) { &qdss_dap_sync_clk_src.hw @@ -3101,7 +3168,7 @@ static struct clk_branch gcc_qdss_tsctr_div4_clk = { static struct clk_fixed_factor qdss_tsctr_div8_clk_src = { .mult = 1, .div = 8, - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "qdss_tsctr_div8_clk_src", .parent_hws = (const struct clk_hw *[]) { &qdss_tsctr_clk_src.clkr.hw @@ -3116,7 +3183,7 @@ static struct clk_branch gcc_nss_ts_clk = { .clkr = { .enable_reg = 0x17018, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_nss_ts_clk", .parent_hws = (const struct clk_hw *[]) { &nss_ts_clk_src.clkr.hw @@ -3133,7 +3200,7 @@ static struct clk_branch gcc_qdss_tsctr_div8_clk = { .clkr = { .enable_reg = 0x2d050, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_qdss_tsctr_div8_clk", .parent_hws = (const struct clk_hw *[]) { &qdss_tsctr_div8_clk_src.hw @@ -3148,7 +3215,7 @@ static struct clk_branch gcc_qdss_tsctr_div8_clk = { static struct clk_fixed_factor qdss_tsctr_div16_clk_src = { .mult = 1, .div = 16, - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "qdss_tsctr_div16_clk_src", .parent_hws = (const struct clk_hw *[]) { &qdss_tsctr_clk_src.clkr.hw @@ -3163,7 +3230,7 @@ static struct clk_branch gcc_qdss_tsctr_div16_clk = { .clkr = { .enable_reg = 0x2d054, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_qdss_tsctr_div16_clk", .parent_hws = (const struct clk_hw *[]) { &qdss_tsctr_div16_clk_src.hw @@ -3180,7 +3247,7 @@ static struct clk_branch gcc_q6ss_pclkdbg_clk = { .clkr = { .enable_reg = 0x25024, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_q6ss_pclkdbg_clk", .parent_hws = (const struct clk_hw *[]) { &qdss_dap_sync_clk_src.hw @@ -3197,7 +3264,7 @@ static struct clk_branch gcc_q6ss_trig_clk = { .clkr = { .enable_reg = 0x25068, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_q6ss_trig_clk", .parent_hws = (const struct clk_hw *[]) { &qdss_dap_sync_clk_src.hw @@ -3214,7 +3281,7 @@ static struct clk_branch gcc_wcss_dbg_ifc_apb_clk = { .clkr = { .enable_reg = 0x25038, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_wcss_dbg_ifc_apb_clk", .parent_hws = (const struct clk_hw *[]) { &qdss_dap_sync_clk_src.hw @@ -3231,7 +3298,7 @@ static struct clk_branch gcc_wcss_dbg_ifc_dapbus_clk = { .clkr = { .enable_reg = 0x25044, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_wcss_dbg_ifc_dapbus_clk", .parent_hws = (const struct clk_hw *[]) { &qdss_dap_sync_clk_src.hw @@ -3248,7 +3315,7 @@ static struct clk_branch gcc_qdss_dap_clk = { .clkr = { .enable_reg = 0x2d058, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_qdss_dap_clk", .parent_hws = (const struct clk_hw *[]) { &qdss_dap_sync_clk_src.hw @@ -3265,7 +3332,7 @@ static struct clk_branch gcc_qdss_apb2jtag_clk = { .clkr = { .enable_reg = 0x2d05c, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_qdss_apb2jtag_clk", .parent_hws = (const struct clk_hw *[]) { &qdss_dap_sync_clk_src.hw @@ -3280,7 +3347,7 @@ static struct clk_branch gcc_qdss_apb2jtag_clk = { static struct clk_fixed_factor qdss_tsctr_div3_clk_src = { .mult = 1, .div = 3, - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "qdss_tsctr_div3_clk_src", .parent_hws = (const struct clk_hw *[]) { &qdss_tsctr_clk_src.clkr.hw @@ -3295,7 +3362,7 @@ static struct clk_branch gcc_qdss_tsctr_div3_clk = { .clkr = { .enable_reg = 0x2d048, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_qdss_tsctr_div3_clk", .parent_hws = (const struct clk_hw *[]) { &qdss_tsctr_div3_clk_src.hw @@ -3321,7 +3388,7 @@ static struct clk_rcg2 qpic_io_macro_clk_src = { .freq_tbl = ftbl_qpic_io_macro_clk_src, .hid_width = 5, .parent_map = gcc_xo_gpll0_gpll2_map, - .clkr.hw.init = &(struct clk_init_data) { + .clkr.hw.init = &(const struct clk_init_data) { .name = "qpic_io_macro_clk_src", .parent_data = gcc_xo_gpll0_gpll2, .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll2), @@ -3334,7 +3401,7 @@ static struct clk_branch gcc_qpic_io_macro_clk = { .clkr = { .enable_reg = 0x3200c, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data){ + .hw.init = &(const struct clk_init_data){ .name = "gcc_qpic_io_macro_clk", .parent_hws = (const struct clk_hw *[]){ &qpic_io_macro_clk_src.clkr.hw @@ -3356,7 +3423,7 @@ static struct clk_rcg2 q6_axi_clk_src = { .freq_tbl = ftbl_q6_axi_clk_src, .hid_width = 5, .parent_map = gcc_xo_gpll0_gpll2_gpll4_pi_sleep_map, - .clkr.hw.init = &(struct clk_init_data) { + .clkr.hw.init = &(const struct clk_init_data) { .name = "q6_axi_clk_src", .parent_data = gcc_xo_gpll0_gpll2_gpll4_pi_sleep, .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll2_gpll4_pi_sleep), @@ -3369,7 +3436,7 @@ static struct clk_branch gcc_q6_axim_clk = { .clkr = { .enable_reg = 0x2500c, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_q6_axim_clk", .parent_hws = (const struct clk_hw *[]) { &q6_axi_clk_src.clkr.hw @@ -3387,7 +3454,7 @@ static struct clk_branch gcc_wcss_q6_tbu_clk = { .clkr = { .enable_reg = 0xb00c, .enable_mask = BIT(6), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_wcss_q6_tbu_clk", .parent_hws = (const struct clk_hw *[]) { &q6_axi_clk_src.clkr.hw @@ -3404,7 +3471,7 @@ static struct clk_branch gcc_mem_noc_q6_axi_clk = { .clkr = { .enable_reg = 0x19010, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_mem_noc_q6_axi_clk", .parent_hws = (const struct clk_hw *[]) { &q6_axi_clk_src.clkr.hw @@ -3433,7 +3500,7 @@ static struct clk_rcg2 q6_axim2_clk_src = { .freq_tbl = ftbl_q6_axim2_clk_src, .hid_width = 5, .parent_map = gcc_xo_gpll0_gpll4_bias_pll_ubinc_clk_map, - .clkr.hw.init = &(struct clk_init_data) { + .clkr.hw.init = &(const struct clk_init_data) { .name = "q6_axim2_clk_src", .parent_data = gcc_xo_gpll0_gpll4_bias_pll_ubi_nc_clk, .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll4_bias_pll_ubi_nc_clk), @@ -3451,7 +3518,7 @@ static struct clk_rcg2 nssnoc_memnoc_bfdcd_clk_src = { .freq_tbl = ftbl_nssnoc_memnoc_bfdcd_clk_src, .hid_width = 5, .parent_map = gcc_xo_gpll0_gpll0_aux_gpll2_map, - .clkr.hw.init = &(struct clk_init_data) { + .clkr.hw.init = &(const struct clk_init_data) { .name = "nssnoc_memnoc_bfdcd_clk_src", .parent_data = gcc_xo_gpll0_gpll0_aux_gpll2, .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_aux_gpll2), @@ -3464,7 +3531,7 @@ static struct clk_branch gcc_nssnoc_memnoc_clk = { .clkr = { .enable_reg = 0x17024, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_nssnoc_memnoc_clk", .parent_hws = (const struct clk_hw *[]) { &nssnoc_memnoc_bfdcd_clk_src.clkr.hw @@ -3481,7 +3548,7 @@ static struct clk_branch gcc_nssnoc_mem_noc_1_clk = { .clkr = { .enable_reg = 0x17084, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_nssnoc_mem_noc_1_clk", .parent_hws = (const struct clk_hw *[]) { &nssnoc_memnoc_bfdcd_clk_src.clkr.hw @@ -3498,7 +3565,7 @@ static struct clk_branch gcc_nss_tbu_clk = { .clkr = { .enable_reg = 0xb00c, .enable_mask = BIT(4), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_nss_tbu_clk", .parent_hws = (const struct clk_hw *[]) { &nssnoc_memnoc_bfdcd_clk_src.clkr.hw @@ -3515,7 +3582,7 @@ static struct clk_branch gcc_mem_noc_nssnoc_clk = { .clkr = { .enable_reg = 0x19014, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_mem_noc_nssnoc_clk", .parent_hws = (const struct clk_hw *[]) { &nssnoc_memnoc_bfdcd_clk_src.clkr.hw @@ -3537,7 +3604,7 @@ static struct clk_rcg2 lpass_axim_clk_src = { .freq_tbl = ftbl_lpass_axim_clk_src, .hid_width = 5, .parent_map = gcc_xo_gpll0_map, - .clkr.hw.init = &(struct clk_init_data) { + .clkr.hw.init = &(const struct clk_init_data) { .name = "lpass_axim_clk_src", .parent_data = gcc_xo_gpll0, .num_parents = ARRAY_SIZE(gcc_xo_gpll0), @@ -3550,7 +3617,7 @@ static struct clk_rcg2 lpass_sway_clk_src = { .freq_tbl = ftbl_lpass_axim_clk_src, .hid_width = 5, .parent_map = gcc_xo_gpll0_map, - .clkr.hw.init = &(struct clk_init_data) { + .clkr.hw.init = &(const struct clk_init_data) { .name = "lpass_sway_clk_src", .parent_data = gcc_xo_gpll0, .num_parents = ARRAY_SIZE(gcc_xo_gpll0), @@ -3569,7 +3636,7 @@ static struct clk_rcg2 adss_pwm_clk_src = { .freq_tbl = ftbl_adss_pwm_clk_src, .hid_width = 5, .parent_map = gcc_xo_gpll0_map, - .clkr.hw.init = &(struct clk_init_data) { + .clkr.hw.init = &(const struct clk_init_data) { .name = "adss_pwm_clk_src", .parent_data = gcc_xo_gpll0, .num_parents = ARRAY_SIZE(gcc_xo_gpll0), @@ -3582,7 +3649,7 @@ static struct clk_branch gcc_adss_pwm_clk = { .clkr = { .enable_reg = 0x1c00c, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_adss_pwm_clk", .parent_hws = (const struct clk_hw *[]) { &adss_pwm_clk_src.clkr.hw @@ -3605,7 +3672,7 @@ static struct clk_rcg2 gp1_clk_src = { .freq_tbl = ftbl_gp1_clk_src, .hid_width = 5, .parent_map = gcc_xo_gpll0_gpll0_sleep_clk_map, - .clkr.hw.init = &(struct clk_init_data) { + .clkr.hw.init = &(const struct clk_init_data) { .name = "gp1_clk_src", .parent_data = gcc_xo_gpll0_gpll0_sleep_clk, .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_sleep_clk), @@ -3618,7 +3685,7 @@ static struct clk_rcg2 gp2_clk_src = { .freq_tbl = ftbl_gp1_clk_src, .hid_width = 5, .parent_map = gcc_xo_gpll0_gpll0_sleep_clk_map, - .clkr.hw.init = &(struct clk_init_data) { + .clkr.hw.init = &(const struct clk_init_data) { .name = "gp2_clk_src", .parent_data = gcc_xo_gpll0_gpll0_sleep_clk, .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_sleep_clk), @@ -3631,7 +3698,7 @@ static struct clk_rcg2 gp3_clk_src = { .freq_tbl = ftbl_gp1_clk_src, .hid_width = 5, .parent_map = gcc_xo_gpll0_gpll0_sleep_clk_map, - .clkr.hw.init = &(struct clk_init_data) { + .clkr.hw.init = &(const struct clk_init_data) { .name = "gp3_clk_src", .parent_data = gcc_xo_gpll0_gpll0_sleep_clk, .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_sleep_clk), @@ -3644,7 +3711,7 @@ static struct clk_branch gcc_xo_clk_src = { .clkr = { .enable_reg = 0x34004, .enable_mask = BIT(1), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_xo_clk_src", .parent_data = gcc_xo_data, .num_parents = ARRAY_SIZE(gcc_xo_data), @@ -3659,7 +3726,7 @@ static struct clk_branch gcc_nssnoc_xo_dcd_clk = { .clkr = { .enable_reg = 0x17074, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_nssnoc_xo_dcd_clk", .parent_hws = (const struct clk_hw *[]) { &gcc_xo_clk_src.clkr.hw @@ -3676,7 +3743,7 @@ static struct clk_branch gcc_xo_clk = { .clkr = { .enable_reg = 0x34018, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_xo_clk", .parent_hws = (const struct clk_hw *[]) { &gcc_xo_clk_src.clkr.hw @@ -3693,7 +3760,7 @@ static struct clk_branch gcc_uniphy0_sys_clk = { .clkr = { .enable_reg = 0x17048, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_uniphy0_sys_clk", .parent_hws = (const struct clk_hw *[]) { &uniphy_sys_clk_src.clkr.hw @@ -3710,7 +3777,7 @@ static struct clk_branch gcc_uniphy1_sys_clk = { .clkr = { .enable_reg = 0x17058, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_uniphy1_sys_clk", .parent_hws = (const struct clk_hw *[]) { &uniphy_sys_clk_src.clkr.hw @@ -3727,7 +3794,7 @@ static struct clk_branch gcc_uniphy2_sys_clk = { .clkr = { .enable_reg = 0x17068, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_uniphy2_sys_clk", .parent_hws = (const struct clk_hw *[]) { &uniphy_sys_clk_src.clkr.hw @@ -3744,7 +3811,7 @@ static struct clk_branch gcc_cmn_12gpll_sys_clk = { .clkr = { .enable_reg = 0x3a008, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_cmn_12gpll_sys_clk", .parent_hws = (const struct clk_hw *[]) { &uniphy_sys_clk_src.clkr.hw @@ -3759,7 +3826,7 @@ static struct clk_branch gcc_cmn_12gpll_sys_clk = { static struct clk_fixed_factor gcc_xo_div4_clk_src = { .mult = 1, .div = 4, - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_xo_div4_clk_src", .parent_hws = (const struct clk_hw *[]) { &gcc_xo_clk_src.clkr.hw @@ -3775,7 +3842,7 @@ static struct clk_branch gcc_nssnoc_qosgen_ref_clk = { .clkr = { .enable_reg = 0x1701c, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_nssnoc_qosgen_ref_clk", .parent_hws = (const struct clk_hw *[]) { &gcc_xo_div4_clk_src.hw @@ -3792,7 +3859,7 @@ static struct clk_branch gcc_nssnoc_timeout_ref_clk = { .clkr = { .enable_reg = 0x17020, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_nssnoc_timeout_ref_clk", .parent_hws = (const struct clk_hw *[]) { &gcc_xo_div4_clk_src.hw @@ -3809,7 +3876,7 @@ static struct clk_branch gcc_xo_div4_clk = { .clkr = { .enable_reg = 0x3401c, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data) { + .hw.init = &(const struct clk_init_data) { .name = "gcc_xo_div4_clk", .parent_hws = (const struct clk_hw *[]) { &gcc_xo_div4_clk_src.hw @@ -3880,6 +3947,10 @@ static struct clk_regmap *gcc_ipq9574_clks[] = { [GCC_BLSP1_UART4_APPS_CLK] = &gcc_blsp1_uart4_apps_clk.clkr, [GCC_BLSP1_UART5_APPS_CLK] = &gcc_blsp1_uart5_apps_clk.clkr, [GCC_BLSP1_UART6_APPS_CLK] = &gcc_blsp1_uart6_apps_clk.clkr, + [GCC_CRYPTO_AHB_CLK] = &gcc_crypto_ahb_clk.clkr, + [GCC_CRYPTO_AXI_CLK] = &gcc_crypto_axi_clk.clkr, + [GCC_CRYPTO_CLK] = &gcc_crypto_clk.clkr, + [GCC_CRYPTO_CLK_SRC] = &gcc_crypto_clk_src.clkr, [PCIE0_AXI_M_CLK_SRC] = &pcie0_axi_m_clk_src.clkr, [GCC_PCIE0_AXI_M_CLK] = &gcc_pcie0_axi_m_clk.clkr, [PCIE1_AXI_M_CLK_SRC] = &pcie1_axi_m_clk_src.clkr, @@ -4063,6 +4134,7 @@ static const struct qcom_reset_map gcc_ipq9574_resets[] = { [GCC_CMN_BLK_AHB_ARES] = { 0x3a010, 0 }, [GCC_CMN_BLK_SYS_ARES] = { 0x3a010, 1 }, [GCC_CMN_BLK_APU_ARES] = { 0x3a010, 2 }, + [GCC_CRYPTO_BCR] = { 0x16000, 0 }, [GCC_DCC_BCR] = { 0x35000, 0 }, [GCC_DDRSS_BCR] = { 0x11000, 0 }, [GCC_IMEM_BCR] = { 0x0e000, 0 }, diff --git a/drivers/clk/qcom/gcc-qcm2290.c b/drivers/clk/qcom/gcc-qcm2290.c index 096deff2ba257d1d3025b83fc0335938b6bc3315..48995e50c6bd70dcf89c1086b2aa4a4f5bc7ad88 100644 --- a/drivers/clk/qcom/gcc-qcm2290.c +++ b/drivers/clk/qcom/gcc-qcm2290.c @@ -650,7 +650,7 @@ static struct clk_rcg2 gcc_usb30_prim_mock_utmi_clk_src = { .name = "gcc_usb30_prim_mock_utmi_clk_src", .parent_data = gcc_parents_0, .num_parents = ARRAY_SIZE(gcc_parents_0), - .ops = &clk_rcg2_ops, + .ops = &clk_rcg2_shared_ops, }, }; @@ -686,7 +686,7 @@ static struct clk_rcg2 gcc_camss_axi_clk_src = { .name = "gcc_camss_axi_clk_src", .parent_data = gcc_parents_4, .num_parents = ARRAY_SIZE(gcc_parents_4), - .ops = &clk_rcg2_ops, + .ops = &clk_rcg2_shared_ops, }, }; @@ -706,7 +706,7 @@ static struct clk_rcg2 gcc_camss_cci_clk_src = { .name = "gcc_camss_cci_clk_src", .parent_data = gcc_parents_9, .num_parents = ARRAY_SIZE(gcc_parents_9), - .ops = &clk_rcg2_ops, + .ops = &clk_rcg2_shared_ops, }, }; @@ -728,7 +728,7 @@ static struct clk_rcg2 gcc_camss_csi0phytimer_clk_src = { .name = "gcc_camss_csi0phytimer_clk_src", .parent_data = gcc_parents_5, .num_parents = ARRAY_SIZE(gcc_parents_5), - .ops = &clk_rcg2_ops, + .ops = &clk_rcg2_shared_ops, }, }; @@ -742,7 +742,7 @@ static struct clk_rcg2 gcc_camss_csi1phytimer_clk_src = { .name = "gcc_camss_csi1phytimer_clk_src", .parent_data = gcc_parents_5, .num_parents = ARRAY_SIZE(gcc_parents_5), - .ops = &clk_rcg2_ops, + .ops = &clk_rcg2_shared_ops, }, }; @@ -764,7 +764,7 @@ static struct clk_rcg2 gcc_camss_mclk0_clk_src = { .parent_data = gcc_parents_3, .num_parents = ARRAY_SIZE(gcc_parents_3), .flags = CLK_OPS_PARENT_ENABLE, - .ops = &clk_rcg2_ops, + .ops = &clk_rcg2_shared_ops, }, }; @@ -779,7 +779,7 @@ static struct clk_rcg2 gcc_camss_mclk1_clk_src = { .parent_data = gcc_parents_3, .num_parents = ARRAY_SIZE(gcc_parents_3), .flags = CLK_OPS_PARENT_ENABLE, - .ops = &clk_rcg2_ops, + .ops = &clk_rcg2_shared_ops, }, }; @@ -794,7 +794,7 @@ static struct clk_rcg2 gcc_camss_mclk2_clk_src = { .parent_data = gcc_parents_3, .num_parents = ARRAY_SIZE(gcc_parents_3), .flags = CLK_OPS_PARENT_ENABLE, - .ops = &clk_rcg2_ops, + .ops = &clk_rcg2_shared_ops, }, }; @@ -809,7 +809,7 @@ static struct clk_rcg2 gcc_camss_mclk3_clk_src = { .parent_data = gcc_parents_3, .num_parents = ARRAY_SIZE(gcc_parents_3), .flags = CLK_OPS_PARENT_ENABLE, - .ops = &clk_rcg2_ops, + .ops = &clk_rcg2_shared_ops, }, }; @@ -830,7 +830,7 @@ static struct clk_rcg2 gcc_camss_ope_ahb_clk_src = { .name = "gcc_camss_ope_ahb_clk_src", .parent_data = gcc_parents_6, .num_parents = ARRAY_SIZE(gcc_parents_6), - .ops = &clk_rcg2_ops, + .ops = &clk_rcg2_shared_ops, }, }; @@ -854,7 +854,7 @@ static struct clk_rcg2 gcc_camss_ope_clk_src = { .parent_data = gcc_parents_6, .num_parents = ARRAY_SIZE(gcc_parents_6), .flags = CLK_SET_RATE_PARENT, - .ops = &clk_rcg2_ops, + .ops = &clk_rcg2_shared_ops, }, }; @@ -888,7 +888,7 @@ static struct clk_rcg2 gcc_camss_tfe_0_clk_src = { .name = "gcc_camss_tfe_0_clk_src", .parent_data = gcc_parents_7, .num_parents = ARRAY_SIZE(gcc_parents_7), - .ops = &clk_rcg2_ops, + .ops = &clk_rcg2_shared_ops, }, }; @@ -912,7 +912,7 @@ static struct clk_rcg2 gcc_camss_tfe_0_csid_clk_src = { .name = "gcc_camss_tfe_0_csid_clk_src", .parent_data = gcc_parents_8, .num_parents = ARRAY_SIZE(gcc_parents_8), - .ops = &clk_rcg2_ops, + .ops = &clk_rcg2_shared_ops, }, }; @@ -926,7 +926,7 @@ static struct clk_rcg2 gcc_camss_tfe_1_clk_src = { .name = "gcc_camss_tfe_1_clk_src", .parent_data = gcc_parents_7, .num_parents = ARRAY_SIZE(gcc_parents_7), - .ops = &clk_rcg2_ops, + .ops = &clk_rcg2_shared_ops, }, }; @@ -940,7 +940,7 @@ static struct clk_rcg2 gcc_camss_tfe_1_csid_clk_src = { .name = "gcc_camss_tfe_1_csid_clk_src", .parent_data = gcc_parents_8, .num_parents = ARRAY_SIZE(gcc_parents_8), - .ops = &clk_rcg2_ops, + .ops = &clk_rcg2_shared_ops, }, }; @@ -963,7 +963,7 @@ static struct clk_rcg2 gcc_camss_tfe_cphy_rx_clk_src = { .parent_data = gcc_parents_10, .num_parents = ARRAY_SIZE(gcc_parents_10), .flags = CLK_OPS_PARENT_ENABLE, - .ops = &clk_rcg2_ops, + .ops = &clk_rcg2_shared_ops, }, }; @@ -984,7 +984,7 @@ static struct clk_rcg2 gcc_camss_top_ahb_clk_src = { .name = "gcc_camss_top_ahb_clk_src", .parent_data = gcc_parents_4, .num_parents = ARRAY_SIZE(gcc_parents_4), - .ops = &clk_rcg2_ops, + .ops = &clk_rcg2_shared_ops, }, }; @@ -1006,7 +1006,7 @@ static struct clk_rcg2 gcc_gp1_clk_src = { .name = "gcc_gp1_clk_src", .parent_data = gcc_parents_2, .num_parents = ARRAY_SIZE(gcc_parents_2), - .ops = &clk_rcg2_ops, + .ops = &clk_rcg2_shared_ops, }, }; @@ -1020,7 +1020,7 @@ static struct clk_rcg2 gcc_gp2_clk_src = { .name = "gcc_gp2_clk_src", .parent_data = gcc_parents_2, .num_parents = ARRAY_SIZE(gcc_parents_2), - .ops = &clk_rcg2_ops, + .ops = &clk_rcg2_shared_ops, }, }; @@ -1034,7 +1034,7 @@ static struct clk_rcg2 gcc_gp3_clk_src = { .name = "gcc_gp3_clk_src", .parent_data = gcc_parents_2, .num_parents = ARRAY_SIZE(gcc_parents_2), - .ops = &clk_rcg2_ops, + .ops = &clk_rcg2_shared_ops, }, }; @@ -1054,7 +1054,7 @@ static struct clk_rcg2 gcc_pdm2_clk_src = { .name = "gcc_pdm2_clk_src", .parent_data = gcc_parents_0, .num_parents = ARRAY_SIZE(gcc_parents_0), - .ops = &clk_rcg2_ops, + .ops = &clk_rcg2_shared_ops, }, }; @@ -1082,7 +1082,7 @@ static struct clk_init_data gcc_qupv3_wrap0_s0_clk_src_init = { .name = "gcc_qupv3_wrap0_s0_clk_src", .parent_data = gcc_parents_1, .num_parents = ARRAY_SIZE(gcc_parents_1), - .ops = &clk_rcg2_ops, + .ops = &clk_rcg2_shared_ops, }; static struct clk_rcg2 gcc_qupv3_wrap0_s0_clk_src = { @@ -1098,7 +1098,7 @@ static struct clk_init_data gcc_qupv3_wrap0_s1_clk_src_init = { .name = "gcc_qupv3_wrap0_s1_clk_src", .parent_data = gcc_parents_1, .num_parents = ARRAY_SIZE(gcc_parents_1), - .ops = &clk_rcg2_ops, + .ops = &clk_rcg2_shared_ops, }; static struct clk_rcg2 gcc_qupv3_wrap0_s1_clk_src = { @@ -1114,7 +1114,7 @@ static struct clk_init_data gcc_qupv3_wrap0_s2_clk_src_init = { .name = "gcc_qupv3_wrap0_s2_clk_src", .parent_data = gcc_parents_1, .num_parents = ARRAY_SIZE(gcc_parents_1), - .ops = &clk_rcg2_ops, + .ops = &clk_rcg2_shared_ops, }; static struct clk_rcg2 gcc_qupv3_wrap0_s2_clk_src = { @@ -1130,7 +1130,7 @@ static struct clk_init_data gcc_qupv3_wrap0_s3_clk_src_init = { .name = "gcc_qupv3_wrap0_s3_clk_src", .parent_data = gcc_parents_1, .num_parents = ARRAY_SIZE(gcc_parents_1), - .ops = &clk_rcg2_ops, + .ops = &clk_rcg2_shared_ops, }; static struct clk_rcg2 gcc_qupv3_wrap0_s3_clk_src = { @@ -1146,7 +1146,7 @@ static struct clk_init_data gcc_qupv3_wrap0_s4_clk_src_init = { .name = "gcc_qupv3_wrap0_s4_clk_src", .parent_data = gcc_parents_1, .num_parents = ARRAY_SIZE(gcc_parents_1), - .ops = &clk_rcg2_ops, + .ops = &clk_rcg2_shared_ops, }; static struct clk_rcg2 gcc_qupv3_wrap0_s4_clk_src = { @@ -1162,7 +1162,7 @@ static struct clk_init_data gcc_qupv3_wrap0_s5_clk_src_init = { .name = "gcc_qupv3_wrap0_s5_clk_src", .parent_data = gcc_parents_1, .num_parents = ARRAY_SIZE(gcc_parents_1), - .ops = &clk_rcg2_ops, + .ops = &clk_rcg2_shared_ops, }; static struct clk_rcg2 gcc_qupv3_wrap0_s5_clk_src = { @@ -1219,7 +1219,7 @@ static struct clk_rcg2 gcc_sdcc1_ice_core_clk_src = { .name = "gcc_sdcc1_ice_core_clk_src", .parent_data = gcc_parents_0, .num_parents = ARRAY_SIZE(gcc_parents_0), - .ops = &clk_rcg2_ops, + .ops = &clk_rcg2_shared_ops, }, }; @@ -1266,7 +1266,7 @@ static struct clk_rcg2 gcc_usb30_prim_master_clk_src = { .name = "gcc_usb30_prim_master_clk_src", .parent_data = gcc_parents_0, .num_parents = ARRAY_SIZE(gcc_parents_0), - .ops = &clk_rcg2_ops, + .ops = &clk_rcg2_shared_ops, }, }; @@ -1280,7 +1280,7 @@ static struct clk_rcg2 gcc_usb3_prim_phy_aux_clk_src = { .name = "gcc_usb3_prim_phy_aux_clk_src", .parent_data = gcc_parents_13, .num_parents = ARRAY_SIZE(gcc_parents_13), - .ops = &clk_rcg2_ops, + .ops = &clk_rcg2_shared_ops, }, }; @@ -1303,7 +1303,7 @@ static struct clk_rcg2 gcc_video_venus_clk_src = { .parent_data = gcc_parents_14, .num_parents = ARRAY_SIZE(gcc_parents_14), .flags = CLK_SET_RATE_PARENT, - .ops = &clk_rcg2_ops, + .ops = &clk_rcg2_shared_ops, }, }; diff --git a/drivers/clk/qcom/gcc-sc8280xp.c b/drivers/clk/qcom/gcc-sc8280xp.c index 04a99dbaa57e0beaf2226f36c218e93beb00e903..b90c71637814b5105fa02c10e930aac679938c1e 100644 --- a/drivers/clk/qcom/gcc-sc8280xp.c +++ b/drivers/clk/qcom/gcc-sc8280xp.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -7421,9 +7422,19 @@ static int gcc_sc8280xp_probe(struct platform_device *pdev) struct regmap *regmap; int ret; + ret = devm_pm_runtime_enable(&pdev->dev); + if (ret) + return ret; + + ret = pm_runtime_resume_and_get(&pdev->dev); + if (ret) + return ret; + regmap = qcom_cc_map(pdev, &gcc_sc8280xp_desc); - if (IS_ERR(regmap)) + if (IS_ERR(regmap)) { + pm_runtime_put(&pdev->dev); return PTR_ERR(regmap); + } /* * Keep the clocks always-ON @@ -7445,7 +7456,10 @@ static int gcc_sc8280xp_probe(struct platform_device *pdev) if (ret) return ret; - return qcom_cc_really_probe(pdev, &gcc_sc8280xp_desc, regmap); + ret = qcom_cc_really_probe(pdev, &gcc_sc8280xp_desc, regmap); + pm_runtime_put(&pdev->dev); + + return ret; } static const struct of_device_id gcc_sc8280xp_match_table[] = { diff --git a/drivers/clk/qcom/gcc-sdm660.c b/drivers/clk/qcom/gcc-sdm660.c index db918c92a522c3e10a3bedb269edb174465b754c..6afce8e42ede718509f8a9ff1d2da28c5e6ce4a5 100644 --- a/drivers/clk/qcom/gcc-sdm660.c +++ b/drivers/clk/qcom/gcc-sdm660.c @@ -25,8 +25,6 @@ #include "reset.h" #include "gdsc.h" -#define F(f, s, h, m, n) { (f), (s), (2 * (h) - 1), (m), (n) } - enum { P_XO, P_SLEEP_CLK, diff --git a/drivers/clk/qcom/gcc-sdx75.c b/drivers/clk/qcom/gcc-sdx75.c new file mode 100644 index 0000000000000000000000000000000000000000..b6772abdcec5f102296ee440b1f63291757b76df --- /dev/null +++ b/drivers/clk/qcom/gcc-sdx75.c @@ -0,0 +1,2970 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#include +#include +#include +#include + +#include + +#include "clk-alpha-pll.h" +#include "clk-branch.h" +#include "clk-rcg.h" +#include "clk-regmap.h" +#include "clk-regmap-divider.h" +#include "clk-regmap-mux.h" +#include "clk-regmap-phy-mux.h" +#include "gdsc.h" +#include "reset.h" + +enum { + DT_BI_TCXO, + DT_SLEEP_CLK, + DT_EMAC0_SGMIIPHY_MAC_RCLK, + DT_EMAC0_SGMIIPHY_MAC_TCLK, + DT_EMAC0_SGMIIPHY_RCLK, + DT_EMAC0_SGMIIPHY_TCLK, + DT_EMAC1_SGMIIPHY_MAC_RCLK, + DT_EMAC1_SGMIIPHY_MAC_TCLK, + DT_EMAC1_SGMIIPHY_RCLK, + DT_EMAC1_SGMIIPHY_TCLK, + DT_PCIE20_PHY_AUX_CLK, + DT_PCIE_1_PIPE_CLK, + DT_PCIE_2_PIPE_CLK, + DT_PCIE_PIPE_CLK, + DT_USB3_PHY_WRAPPER_GCC_USB30_PIPE_CLK, +}; + +enum { + P_BI_TCXO, + P_EMAC0_SGMIIPHY_MAC_RCLK, + P_EMAC0_SGMIIPHY_MAC_TCLK, + P_EMAC0_SGMIIPHY_RCLK, + P_EMAC0_SGMIIPHY_TCLK, + P_EMAC1_SGMIIPHY_MAC_RCLK, + P_EMAC1_SGMIIPHY_MAC_TCLK, + P_EMAC1_SGMIIPHY_RCLK, + P_EMAC1_SGMIIPHY_TCLK, + P_GPLL0_OUT_EVEN, + P_GPLL0_OUT_MAIN, + P_GPLL4_OUT_MAIN, + P_GPLL5_OUT_MAIN, + P_GPLL6_OUT_MAIN, + P_GPLL8_OUT_MAIN, + P_PCIE20_PHY_AUX_CLK, + P_PCIE_1_PIPE_CLK, + P_PCIE_2_PIPE_CLK, + P_PCIE_PIPE_CLK, + P_SLEEP_CLK, + P_USB3_PHY_WRAPPER_GCC_USB30_PIPE_CLK, +}; + +static struct clk_alpha_pll gpll0 = { + .offset = 0x0, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE], + .clkr = { + .enable_reg = 0x7d000, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gpll0", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_fixed_lucid_ole_ops, + }, + }, +}; + +static const struct clk_div_table post_div_table_gpll0_out_even[] = { + { 0x1, 2 }, + { } +}; + +static struct clk_alpha_pll_postdiv gpll0_out_even = { + .offset = 0x0, + .post_div_shift = 10, + .post_div_table = post_div_table_gpll0_out_even, + .num_post_div = ARRAY_SIZE(post_div_table_gpll0_out_even), + .width = 4, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE], + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gpll0_out_even", + .parent_hws = (const struct clk_hw*[]) { + &gpll0.clkr.hw, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_postdiv_lucid_ole_ops, + }, +}; + +static struct clk_alpha_pll gpll4 = { + .offset = 0x4000, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE], + .clkr = { + .enable_reg = 0x7d000, + .enable_mask = BIT(4), + .hw.init = &(const struct clk_init_data) { + .name = "gpll4", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_fixed_lucid_ole_ops, + }, + }, +}; + +static struct clk_alpha_pll gpll5 = { + .offset = 0x5000, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE], + .clkr = { + .enable_reg = 0x7d000, + .enable_mask = BIT(5), + .hw.init = &(const struct clk_init_data) { + .name = "gpll5", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_fixed_lucid_ole_ops, + }, + }, +}; + +static struct clk_alpha_pll gpll6 = { + .offset = 0x6000, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE], + .clkr = { + .enable_reg = 0x7d000, + .enable_mask = BIT(6), + .hw.init = &(const struct clk_init_data) { + .name = "gpll6", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_fixed_lucid_ole_ops, + }, + }, +}; + +static struct clk_alpha_pll gpll8 = { + .offset = 0x8000, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE], + .clkr = { + .enable_reg = 0x7d000, + .enable_mask = BIT(8), + .hw.init = &(const struct clk_init_data) { + .name = "gpll8", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_fixed_lucid_ole_ops, + }, + }, +}; + +static const struct parent_map gcc_parent_map_0[] = { + { P_BI_TCXO, 0 }, + { P_GPLL0_OUT_MAIN, 1 }, + { P_GPLL0_OUT_EVEN, 6 }, +}; + +static const struct clk_parent_data gcc_parent_data_0[] = { + { .index = DT_BI_TCXO }, + { .hw = &gpll0.clkr.hw }, + { .hw = &gpll0_out_even.clkr.hw }, +}; + +static const struct parent_map gcc_parent_map_1[] = { + { P_BI_TCXO, 0 }, + { P_GPLL0_OUT_MAIN, 1 }, + { P_GPLL4_OUT_MAIN, 2 }, + { P_GPLL5_OUT_MAIN, 5 }, + { P_GPLL0_OUT_EVEN, 6 }, +}; + +static const struct clk_parent_data gcc_parent_data_1[] = { + { .index = DT_BI_TCXO }, + { .hw = &gpll0.clkr.hw }, + { .hw = &gpll4.clkr.hw }, + { .hw = &gpll5.clkr.hw }, + { .hw = &gpll0_out_even.clkr.hw }, +}; + +static const struct parent_map gcc_parent_map_2[] = { + { P_BI_TCXO, 0 }, + { P_GPLL0_OUT_MAIN, 1 }, + { P_SLEEP_CLK, 5 }, + { P_GPLL0_OUT_EVEN, 6 }, +}; + +static const struct clk_parent_data gcc_parent_data_2[] = { + { .index = DT_BI_TCXO }, + { .hw = &gpll0.clkr.hw }, + { .index = DT_SLEEP_CLK }, + { .hw = &gpll0_out_even.clkr.hw }, +}; + +static const struct parent_map gcc_parent_map_3[] = { + { P_BI_TCXO, 0 }, + { P_SLEEP_CLK, 5 }, +}; + +static const struct clk_parent_data gcc_parent_data_3[] = { + { .index = DT_BI_TCXO }, + { .index = DT_SLEEP_CLK }, +}; + +static const struct parent_map gcc_parent_map_4[] = { + { P_BI_TCXO, 0 }, + { P_GPLL0_OUT_MAIN, 1 }, + { P_SLEEP_CLK, 5 }, +}; + +static const struct clk_parent_data gcc_parent_data_4[] = { + { .index = DT_BI_TCXO }, + { .hw = &gpll0.clkr.hw }, + { .index = DT_SLEEP_CLK }, +}; + +static const struct parent_map gcc_parent_map_5[] = { + { P_EMAC0_SGMIIPHY_RCLK, 0 }, + { P_BI_TCXO, 2 }, +}; + +static const struct clk_parent_data gcc_parent_data_5[] = { + { .index = DT_EMAC0_SGMIIPHY_RCLK }, + { .index = DT_BI_TCXO }, +}; + +static const struct parent_map gcc_parent_map_6[] = { + { P_EMAC0_SGMIIPHY_TCLK, 0 }, + { P_BI_TCXO, 2 }, +}; + +static const struct clk_parent_data gcc_parent_data_6[] = { + { .index = DT_EMAC0_SGMIIPHY_TCLK }, + { .index = DT_BI_TCXO }, +}; + +static const struct parent_map gcc_parent_map_7[] = { + { P_EMAC0_SGMIIPHY_MAC_RCLK, 0 }, + { P_BI_TCXO, 2 }, +}; + +static const struct clk_parent_data gcc_parent_data_7[] = { + { .index = DT_EMAC0_SGMIIPHY_MAC_RCLK }, + { .index = DT_BI_TCXO }, +}; + +static const struct parent_map gcc_parent_map_8[] = { + { P_EMAC0_SGMIIPHY_MAC_TCLK, 0 }, + { P_BI_TCXO, 2 }, +}; + +static const struct clk_parent_data gcc_parent_data_8[] = { + { .index = DT_EMAC0_SGMIIPHY_MAC_TCLK }, + { .index = DT_BI_TCXO }, +}; + +static const struct parent_map gcc_parent_map_9[] = { + { P_EMAC1_SGMIIPHY_RCLK, 0 }, + { P_BI_TCXO, 2 }, +}; + +static const struct clk_parent_data gcc_parent_data_9[] = { + { .index = DT_EMAC1_SGMIIPHY_RCLK }, + { .index = DT_BI_TCXO }, +}; + +static const struct parent_map gcc_parent_map_10[] = { + { P_EMAC1_SGMIIPHY_TCLK, 0 }, + { P_BI_TCXO, 2 }, +}; + +static const struct clk_parent_data gcc_parent_data_10[] = { + { .index = DT_EMAC1_SGMIIPHY_TCLK }, + { .index = DT_BI_TCXO }, +}; + +static const struct parent_map gcc_parent_map_11[] = { + { P_EMAC1_SGMIIPHY_MAC_RCLK, 0 }, + { P_BI_TCXO, 2 }, +}; + +static const struct clk_parent_data gcc_parent_data_11[] = { + { .index = DT_EMAC1_SGMIIPHY_MAC_RCLK }, + { .index = DT_BI_TCXO }, +}; + +static const struct parent_map gcc_parent_map_12[] = { + { P_EMAC1_SGMIIPHY_MAC_TCLK, 0 }, + { P_BI_TCXO, 2 }, +}; + +static const struct clk_parent_data gcc_parent_data_12[] = { + { .index = DT_EMAC1_SGMIIPHY_MAC_TCLK }, + { .index = DT_BI_TCXO }, +}; + +static const struct parent_map gcc_parent_map_15[] = { + { P_PCIE20_PHY_AUX_CLK, 0 }, + { P_BI_TCXO, 2 }, +}; + +static const struct clk_parent_data gcc_parent_data_15[] = { + { .index = DT_PCIE20_PHY_AUX_CLK }, + { .index = DT_BI_TCXO }, +}; + +static const struct parent_map gcc_parent_map_17[] = { + { P_BI_TCXO, 0 }, + { P_GPLL0_OUT_MAIN, 1 }, + { P_GPLL6_OUT_MAIN, 2 }, + { P_GPLL0_OUT_EVEN, 6 }, +}; + +static const struct clk_parent_data gcc_parent_data_17[] = { + { .index = DT_BI_TCXO }, + { .hw = &gpll0.clkr.hw }, + { .hw = &gpll6.clkr.hw }, + { .hw = &gpll0_out_even.clkr.hw }, +}; + +static const struct parent_map gcc_parent_map_18[] = { + { P_BI_TCXO, 0 }, + { P_GPLL0_OUT_MAIN, 1 }, + { P_GPLL8_OUT_MAIN, 2 }, + { P_GPLL0_OUT_EVEN, 6 }, +}; + +static const struct clk_parent_data gcc_parent_data_18[] = { + { .index = DT_BI_TCXO }, + { .hw = &gpll0.clkr.hw }, + { .hw = &gpll8.clkr.hw }, + { .hw = &gpll0_out_even.clkr.hw }, +}; + +static const struct parent_map gcc_parent_map_19[] = { + { P_USB3_PHY_WRAPPER_GCC_USB30_PIPE_CLK, 0 }, + { P_BI_TCXO, 2 }, +}; + +static const struct clk_parent_data gcc_parent_data_19[] = { + { .index = DT_USB3_PHY_WRAPPER_GCC_USB30_PIPE_CLK }, + { .index = DT_BI_TCXO }, +}; + +static struct clk_regmap_mux gcc_emac0_cc_sgmiiphy_rx_clk_src = { + .reg = 0x71060, + .shift = 0, + .width = 2, + .parent_map = gcc_parent_map_5, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "gcc_emac0_cc_sgmiiphy_rx_clk_src", + .parent_data = gcc_parent_data_5, + .num_parents = ARRAY_SIZE(gcc_parent_data_5), + .ops = &clk_regmap_mux_closest_ops, + }, + }, +}; + +static struct clk_regmap_mux gcc_emac0_cc_sgmiiphy_tx_clk_src = { + .reg = 0x71058, + .shift = 0, + .width = 2, + .parent_map = gcc_parent_map_6, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "gcc_emac0_cc_sgmiiphy_tx_clk_src", + .parent_data = gcc_parent_data_6, + .num_parents = ARRAY_SIZE(gcc_parent_data_6), + .ops = &clk_regmap_mux_closest_ops, + }, + }, +}; + +static struct clk_regmap_mux gcc_emac0_sgmiiphy_mac_rclk_src = { + .reg = 0x71098, + .shift = 0, + .width = 2, + .parent_map = gcc_parent_map_7, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "gcc_emac0_sgmiiphy_mac_rclk_src", + .parent_data = gcc_parent_data_7, + .num_parents = ARRAY_SIZE(gcc_parent_data_7), + .ops = &clk_regmap_mux_closest_ops, + }, + }, +}; + +static struct clk_regmap_mux gcc_emac0_sgmiiphy_mac_tclk_src = { + .reg = 0x71094, + .shift = 0, + .width = 2, + .parent_map = gcc_parent_map_8, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "gcc_emac0_sgmiiphy_mac_tclk_src", + .parent_data = gcc_parent_data_8, + .num_parents = ARRAY_SIZE(gcc_parent_data_8), + .ops = &clk_regmap_mux_closest_ops, + }, + }, +}; + +static struct clk_regmap_mux gcc_emac1_cc_sgmiiphy_rx_clk_src = { + .reg = 0x72060, + .shift = 0, + .width = 2, + .parent_map = gcc_parent_map_9, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "gcc_emac1_cc_sgmiiphy_rx_clk_src", + .parent_data = gcc_parent_data_9, + .num_parents = ARRAY_SIZE(gcc_parent_data_9), + .ops = &clk_regmap_mux_closest_ops, + }, + }, +}; + +static struct clk_regmap_mux gcc_emac1_cc_sgmiiphy_tx_clk_src = { + .reg = 0x72058, + .shift = 0, + .width = 2, + .parent_map = gcc_parent_map_10, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "gcc_emac1_cc_sgmiiphy_tx_clk_src", + .parent_data = gcc_parent_data_10, + .num_parents = ARRAY_SIZE(gcc_parent_data_10), + .ops = &clk_regmap_mux_closest_ops, + }, + }, +}; + +static struct clk_regmap_mux gcc_emac1_sgmiiphy_mac_rclk_src = { + .reg = 0x72098, + .shift = 0, + .width = 2, + .parent_map = gcc_parent_map_11, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "gcc_emac1_sgmiiphy_mac_rclk_src", + .parent_data = gcc_parent_data_11, + .num_parents = ARRAY_SIZE(gcc_parent_data_11), + .ops = &clk_regmap_mux_closest_ops, + }, + }, +}; + +static struct clk_regmap_mux gcc_emac1_sgmiiphy_mac_tclk_src = { + .reg = 0x72094, + .shift = 0, + .width = 2, + .parent_map = gcc_parent_map_12, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "gcc_emac1_sgmiiphy_mac_tclk_src", + .parent_data = gcc_parent_data_12, + .num_parents = ARRAY_SIZE(gcc_parent_data_12), + .ops = &clk_regmap_mux_closest_ops, + }, + }, +}; + +static struct clk_regmap_phy_mux gcc_pcie_1_pipe_clk_src = { + .reg = 0x67084, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_1_pipe_clk_src", + .parent_data = &(const struct clk_parent_data) { + .index = DT_PCIE_1_PIPE_CLK, + }, + .num_parents = 1, + .ops = &clk_regmap_phy_mux_ops, + }, + }, +}; + +static struct clk_regmap_phy_mux gcc_pcie_2_pipe_clk_src = { + .reg = 0x68050, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_2_pipe_clk_src", + .parent_data = &(const struct clk_parent_data) { + .index = DT_PCIE_2_PIPE_CLK, + }, + .num_parents = 1, + .ops = &clk_regmap_phy_mux_ops, + }, + }, +}; + +static struct clk_regmap_mux gcc_pcie_aux_clk_src = { + .reg = 0x53074, + .shift = 0, + .width = 2, + .parent_map = gcc_parent_map_15, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_aux_clk_src", + .parent_data = gcc_parent_data_15, + .num_parents = ARRAY_SIZE(gcc_parent_data_15), + .ops = &clk_regmap_mux_closest_ops, + }, + }, +}; + +static struct clk_regmap_phy_mux gcc_pcie_pipe_clk_src = { + .reg = 0x53058, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_pipe_clk_src", + .parent_data = &(const struct clk_parent_data) { + .index = DT_PCIE_PIPE_CLK, + }, + .num_parents = 1, + .ops = &clk_regmap_phy_mux_ops, + }, + }, +}; + +static struct clk_regmap_mux gcc_usb3_phy_pipe_clk_src = { + .reg = 0x27070, + .shift = 0, + .width = 2, + .parent_map = gcc_parent_map_19, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb3_phy_pipe_clk_src", + .parent_data = gcc_parent_data_19, + .num_parents = ARRAY_SIZE(gcc_parent_data_19), + .ops = &clk_regmap_mux_closest_ops, + }, + }, +}; + +static const struct freq_tbl ftbl_gcc_eee_emac0_clk_src[] = { + F(100000000, P_GPLL0_OUT_EVEN, 3, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_eee_emac0_clk_src = { + .cmd_rcgr = 0x710b0, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_2, + .freq_tbl = ftbl_gcc_eee_emac0_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_eee_emac0_clk_src", + .parent_data = gcc_parent_data_2, + .num_parents = ARRAY_SIZE(gcc_parent_data_2), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 gcc_eee_emac1_clk_src = { + .cmd_rcgr = 0x720b0, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_2, + .freq_tbl = ftbl_gcc_eee_emac0_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_eee_emac1_clk_src", + .parent_data = gcc_parent_data_2, + .num_parents = ARRAY_SIZE(gcc_parent_data_2), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_emac0_phy_aux_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_emac0_phy_aux_clk_src = { + .cmd_rcgr = 0x7102c, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_4, + .freq_tbl = ftbl_gcc_emac0_phy_aux_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_emac0_phy_aux_clk_src", + .parent_data = gcc_parent_data_4, + .num_parents = ARRAY_SIZE(gcc_parent_data_4), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_emac0_ptp_clk_src[] = { + F(75000000, P_GPLL0_OUT_EVEN, 4, 0, 0), + F(125000000, P_GPLL4_OUT_MAIN, 4, 0, 0), + F(230400000, P_GPLL5_OUT_MAIN, 3.5, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_emac0_ptp_clk_src = { + .cmd_rcgr = 0x7107c, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_1, + .freq_tbl = ftbl_gcc_emac0_ptp_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_emac0_ptp_clk_src", + .parent_data = gcc_parent_data_1, + .num_parents = ARRAY_SIZE(gcc_parent_data_1), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_emac0_rgmii_clk_src[] = { + F(5000000, P_GPLL0_OUT_EVEN, 10, 1, 6), + F(50000000, P_GPLL0_OUT_EVEN, 6, 0, 0), + F(125000000, P_GPLL4_OUT_MAIN, 4, 0, 0), + F(250000000, P_GPLL4_OUT_MAIN, 2, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_emac0_rgmii_clk_src = { + .cmd_rcgr = 0x71064, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_1, + .freq_tbl = ftbl_gcc_emac0_rgmii_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_emac0_rgmii_clk_src", + .parent_data = gcc_parent_data_1, + .num_parents = ARRAY_SIZE(gcc_parent_data_1), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 gcc_emac1_phy_aux_clk_src = { + .cmd_rcgr = 0x7202c, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_4, + .freq_tbl = ftbl_gcc_emac0_phy_aux_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_emac1_phy_aux_clk_src", + .parent_data = gcc_parent_data_4, + .num_parents = ARRAY_SIZE(gcc_parent_data_4), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 gcc_emac1_ptp_clk_src = { + .cmd_rcgr = 0x7207c, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_1, + .freq_tbl = ftbl_gcc_emac0_ptp_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_emac1_ptp_clk_src", + .parent_data = gcc_parent_data_1, + .num_parents = ARRAY_SIZE(gcc_parent_data_1), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 gcc_emac1_rgmii_clk_src = { + .cmd_rcgr = 0x72064, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_1, + .freq_tbl = ftbl_gcc_emac0_rgmii_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_emac1_rgmii_clk_src", + .parent_data = gcc_parent_data_1, + .num_parents = ARRAY_SIZE(gcc_parent_data_1), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_gp1_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(50000000, P_GPLL0_OUT_EVEN, 6, 0, 0), + F(100000000, P_GPLL0_OUT_MAIN, 6, 0, 0), + F(200000000, P_GPLL0_OUT_MAIN, 3, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_gp1_clk_src = { + .cmd_rcgr = 0x47004, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_2, + .freq_tbl = ftbl_gcc_gp1_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_gp1_clk_src", + .parent_data = gcc_parent_data_2, + .num_parents = ARRAY_SIZE(gcc_parent_data_2), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 gcc_gp2_clk_src = { + .cmd_rcgr = 0x48004, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_2, + .freq_tbl = ftbl_gcc_gp1_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_gp2_clk_src", + .parent_data = gcc_parent_data_2, + .num_parents = ARRAY_SIZE(gcc_parent_data_2), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 gcc_gp3_clk_src = { + .cmd_rcgr = 0x49004, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_2, + .freq_tbl = ftbl_gcc_gp1_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_gp3_clk_src", + .parent_data = gcc_parent_data_2, + .num_parents = ARRAY_SIZE(gcc_parent_data_2), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 gcc_pcie_1_aux_phy_clk_src = { + .cmd_rcgr = 0x67044, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_3, + .freq_tbl = ftbl_gcc_emac0_phy_aux_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_1_aux_phy_clk_src", + .parent_data = gcc_parent_data_3, + .num_parents = ARRAY_SIZE(gcc_parent_data_3), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_pcie_1_phy_rchng_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(100000000, P_GPLL0_OUT_EVEN, 3, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_pcie_1_phy_rchng_clk_src = { + .cmd_rcgr = 0x6706c, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_2, + .freq_tbl = ftbl_gcc_pcie_1_phy_rchng_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_1_phy_rchng_clk_src", + .parent_data = gcc_parent_data_2, + .num_parents = ARRAY_SIZE(gcc_parent_data_2), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 gcc_pcie_2_aux_phy_clk_src = { + .cmd_rcgr = 0x68064, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_3, + .freq_tbl = ftbl_gcc_emac0_phy_aux_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_2_aux_phy_clk_src", + .parent_data = gcc_parent_data_3, + .num_parents = ARRAY_SIZE(gcc_parent_data_3), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 gcc_pcie_2_phy_rchng_clk_src = { + .cmd_rcgr = 0x68038, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_2, + .freq_tbl = ftbl_gcc_pcie_1_phy_rchng_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_2_phy_rchng_clk_src", + .parent_data = gcc_parent_data_2, + .num_parents = ARRAY_SIZE(gcc_parent_data_2), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 gcc_pcie_aux_phy_clk_src = { + .cmd_rcgr = 0x5305c, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_3, + .freq_tbl = ftbl_gcc_emac0_phy_aux_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_aux_phy_clk_src", + .parent_data = gcc_parent_data_3, + .num_parents = ARRAY_SIZE(gcc_parent_data_3), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 gcc_pcie_rchng_phy_clk_src = { + .cmd_rcgr = 0x53078, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_2, + .freq_tbl = ftbl_gcc_pcie_1_phy_rchng_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_rchng_phy_clk_src", + .parent_data = gcc_parent_data_2, + .num_parents = ARRAY_SIZE(gcc_parent_data_2), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_pdm2_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(60000000, P_GPLL0_OUT_MAIN, 10, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_pdm2_clk_src = { + .cmd_rcgr = 0x34010, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_pdm2_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_pdm2_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_qupv3_wrap0_s0_clk_src[] = { + F(7372800, P_GPLL0_OUT_EVEN, 1, 384, 15625), + F(14745600, P_GPLL0_OUT_EVEN, 1, 768, 15625), + F(19200000, P_BI_TCXO, 1, 0, 0), + F(29491200, P_GPLL0_OUT_EVEN, 1, 1536, 15625), + F(32000000, P_GPLL0_OUT_EVEN, 1, 8, 75), + F(48000000, P_GPLL0_OUT_EVEN, 1, 4, 25), + F(64000000, P_GPLL0_OUT_EVEN, 1, 16, 75), + F(75000000, P_GPLL0_OUT_EVEN, 4, 0, 0), + F(80000000, P_GPLL0_OUT_EVEN, 1, 4, 15), + F(96000000, P_GPLL0_OUT_EVEN, 1, 8, 25), + F(100000000, P_GPLL0_OUT_MAIN, 6, 0, 0), + { } +}; + +static struct clk_init_data gcc_qupv3_wrap0_s0_clk_src_init = { + .name = "gcc_qupv3_wrap0_s0_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .ops = &clk_rcg2_shared_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap0_s0_clk_src = { + .cmd_rcgr = 0x6c010, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .clkr.hw.init = &gcc_qupv3_wrap0_s0_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap0_s1_clk_src_init = { + .name = "gcc_qupv3_wrap0_s1_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .ops = &clk_rcg2_shared_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap0_s1_clk_src = { + .cmd_rcgr = 0x6c148, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .clkr.hw.init = &gcc_qupv3_wrap0_s1_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap0_s2_clk_src_init = { + .name = "gcc_qupv3_wrap0_s2_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .ops = &clk_rcg2_shared_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap0_s2_clk_src = { + .cmd_rcgr = 0x6c280, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .clkr.hw.init = &gcc_qupv3_wrap0_s2_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap0_s3_clk_src_init = { + .name = "gcc_qupv3_wrap0_s3_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .ops = &clk_rcg2_shared_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap0_s3_clk_src = { + .cmd_rcgr = 0x6c3b8, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .clkr.hw.init = &gcc_qupv3_wrap0_s3_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap0_s4_clk_src_init = { + .name = "gcc_qupv3_wrap0_s4_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .ops = &clk_rcg2_shared_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap0_s4_clk_src = { + .cmd_rcgr = 0x6c4f0, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .clkr.hw.init = &gcc_qupv3_wrap0_s4_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap0_s5_clk_src_init = { + .name = "gcc_qupv3_wrap0_s5_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .ops = &clk_rcg2_shared_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap0_s5_clk_src = { + .cmd_rcgr = 0x6c628, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .clkr.hw.init = &gcc_qupv3_wrap0_s5_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap0_s6_clk_src_init = { + .name = "gcc_qupv3_wrap0_s6_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .ops = &clk_rcg2_shared_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap0_s6_clk_src = { + .cmd_rcgr = 0x6c760, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .clkr.hw.init = &gcc_qupv3_wrap0_s6_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap0_s7_clk_src_init = { + .name = "gcc_qupv3_wrap0_s7_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .ops = &clk_rcg2_shared_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap0_s7_clk_src = { + .cmd_rcgr = 0x6c898, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .clkr.hw.init = &gcc_qupv3_wrap0_s7_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap0_s8_clk_src_init = { + .name = "gcc_qupv3_wrap0_s8_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .ops = &clk_rcg2_shared_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap0_s8_clk_src = { + .cmd_rcgr = 0x6c9d0, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .clkr.hw.init = &gcc_qupv3_wrap0_s8_clk_src_init, +}; + +static const struct freq_tbl ftbl_gcc_sdcc1_apps_clk_src[] = { + F(144000, P_BI_TCXO, 16, 3, 25), + F(400000, P_BI_TCXO, 12, 1, 4), + F(19200000, P_BI_TCXO, 1, 0, 0), + F(20000000, P_GPLL0_OUT_EVEN, 5, 1, 3), + F(25000000, P_GPLL0_OUT_EVEN, 12, 0, 0), + F(50000000, P_GPLL0_OUT_EVEN, 6, 0, 0), + F(100000000, P_GPLL0_OUT_EVEN, 3, 0, 0), + F(192000000, P_GPLL6_OUT_MAIN, 2, 0, 0), + F(384000000, P_GPLL6_OUT_MAIN, 1, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_sdcc1_apps_clk_src = { + .cmd_rcgr = 0x6b014, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_17, + .freq_tbl = ftbl_gcc_sdcc1_apps_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_sdcc1_apps_clk_src", + .parent_data = gcc_parent_data_17, + .num_parents = ARRAY_SIZE(gcc_parent_data_17), + .ops = &clk_rcg2_floor_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_sdcc2_apps_clk_src[] = { + F(400000, P_BI_TCXO, 12, 1, 4), + F(19200000, P_BI_TCXO, 1, 0, 0), + F(25000000, P_GPLL0_OUT_EVEN, 12, 0, 0), + F(50000000, P_GPLL0_OUT_EVEN, 6, 0, 0), + F(100000000, P_GPLL0_OUT_EVEN, 3, 0, 0), + F(202000000, P_GPLL8_OUT_MAIN, 4, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_sdcc2_apps_clk_src = { + .cmd_rcgr = 0x6a018, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_18, + .freq_tbl = ftbl_gcc_sdcc2_apps_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_sdcc2_apps_clk_src", + .parent_data = gcc_parent_data_18, + .num_parents = ARRAY_SIZE(gcc_parent_data_18), + .ops = &clk_rcg2_floor_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_usb30_master_clk_src[] = { + F(200000000, P_GPLL0_OUT_EVEN, 1.5, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_usb30_master_clk_src = { + .cmd_rcgr = 0x27034, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_usb30_master_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_usb30_master_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 gcc_usb30_mock_utmi_clk_src = { + .cmd_rcgr = 0x2704c, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_emac0_phy_aux_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_usb30_mock_utmi_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_usb3_phy_aux_clk_src[] = { + F(1000000, P_BI_TCXO, 1, 5, 96), + F(19200000, P_BI_TCXO, 1, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_usb3_phy_aux_clk_src = { + .cmd_rcgr = 0x27074, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_3, + .freq_tbl = ftbl_gcc_usb3_phy_aux_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_usb3_phy_aux_clk_src", + .parent_data = gcc_parent_data_3, + .num_parents = ARRAY_SIZE(gcc_parent_data_3), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_regmap_div gcc_pcie_1_pipe_div2_clk_src = { + .reg = 0x67088, + .shift = 0, + .width = 4, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_1_pipe_div2_clk_src", + .parent_hws = (const struct clk_hw*[]) { + &gcc_pcie_1_pipe_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_regmap_div_ro_ops, + }, +}; + +static struct clk_regmap_div gcc_pcie_2_pipe_div2_clk_src = { + .reg = 0x68088, + .shift = 0, + .width = 4, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_2_pipe_div2_clk_src", + .parent_hws = (const struct clk_hw*[]) { + &gcc_pcie_2_pipe_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_regmap_div_ro_ops, + }, +}; + +static struct clk_regmap_div gcc_usb30_mock_utmi_postdiv_clk_src = { + .reg = 0x27064, + .shift = 0, + .width = 4, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_usb30_mock_utmi_postdiv_clk_src", + .parent_hws = (const struct clk_hw*[]) { + &gcc_usb30_mock_utmi_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_regmap_div_ro_ops, + }, +}; + +static struct clk_branch gcc_boot_rom_ahb_clk = { + .halt_reg = 0x37004, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x37004, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x7d008, + .enable_mask = BIT(26), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_boot_rom_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_eee_emac0_clk = { + .halt_reg = 0x710ac, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x710ac, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_eee_emac0_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_eee_emac0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_eee_emac1_clk = { + .halt_reg = 0x720ac, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x720ac, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_eee_emac1_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_eee_emac1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_emac0_axi_clk = { + .halt_reg = 0x71018, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x71018, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x71018, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_emac0_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_emac0_cc_sgmiiphy_rx_clk = { + .halt_reg = 0x7105c, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x7105c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_emac0_cc_sgmiiphy_rx_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_emac0_cc_sgmiiphy_rx_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_emac0_cc_sgmiiphy_tx_clk = { + .halt_reg = 0x71054, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x71054, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_emac0_cc_sgmiiphy_tx_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_emac0_cc_sgmiiphy_tx_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_emac0_phy_aux_clk = { + .halt_reg = 0x71028, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x71028, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_emac0_phy_aux_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_emac0_phy_aux_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_emac0_ptp_clk = { + .halt_reg = 0x71044, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x71044, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_emac0_ptp_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_emac0_ptp_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_emac0_rgmii_clk = { + .halt_reg = 0x71050, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x71050, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_emac0_rgmii_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_emac0_rgmii_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_emac0_rpcs_rx_clk = { + .halt_reg = 0x710a0, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x710a0, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_emac0_rpcs_rx_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_emac0_sgmiiphy_mac_rclk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_emac0_rpcs_tx_clk = { + .halt_reg = 0x7109c, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x7109c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_emac0_rpcs_tx_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_emac0_sgmiiphy_mac_tclk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_emac0_slv_ahb_clk = { + .halt_reg = 0x71024, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x71024, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x71024, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_emac0_slv_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_emac0_xgxs_rx_clk = { + .halt_reg = 0x710a8, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x710a8, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_emac0_xgxs_rx_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_emac0_sgmiiphy_mac_rclk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_emac0_xgxs_tx_clk = { + .halt_reg = 0x710a4, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x710a4, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_emac0_xgxs_tx_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_emac0_sgmiiphy_mac_tclk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_emac1_axi_clk = { + .halt_reg = 0x72018, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x72018, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x72018, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_emac1_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_emac1_cc_sgmiiphy_rx_clk = { + .halt_reg = 0x7205c, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x7205c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_emac1_cc_sgmiiphy_rx_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_emac1_cc_sgmiiphy_rx_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_emac1_cc_sgmiiphy_tx_clk = { + .halt_reg = 0x72054, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x72054, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_emac1_cc_sgmiiphy_tx_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_emac1_cc_sgmiiphy_tx_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_emac1_phy_aux_clk = { + .halt_reg = 0x72028, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x72028, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_emac1_phy_aux_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_emac1_phy_aux_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_emac1_ptp_clk = { + .halt_reg = 0x72044, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x72044, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_emac1_ptp_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_emac1_ptp_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_emac1_rgmii_clk = { + .halt_reg = 0x72050, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x72050, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_emac1_rgmii_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_emac1_rgmii_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_emac1_rpcs_rx_clk = { + .halt_reg = 0x720a0, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x720a0, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_emac1_rpcs_rx_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_emac1_sgmiiphy_mac_rclk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_emac1_rpcs_tx_clk = { + .halt_reg = 0x7209c, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x7209c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_emac1_rpcs_tx_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_emac1_sgmiiphy_mac_tclk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_emac1_slv_ahb_clk = { + .halt_reg = 0x72024, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x72024, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x72024, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_emac1_slv_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_emac1_xgxs_rx_clk = { + .halt_reg = 0x720a8, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x720a8, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_emac1_xgxs_rx_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_emac1_sgmiiphy_mac_rclk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_emac1_xgxs_tx_clk = { + .halt_reg = 0x720a4, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x720a4, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_emac1_xgxs_tx_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_emac1_sgmiiphy_mac_tclk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_emac_0_clkref_en = { + .halt_reg = 0x98108, + .halt_check = BRANCH_HALT_ENABLE, + .clkr = { + .enable_reg = 0x98108, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_emac_0_clkref_en", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_emac_1_clkref_en = { + .halt_reg = 0x9810c, + .halt_check = BRANCH_HALT_ENABLE, + .clkr = { + .enable_reg = 0x9810c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_emac_1_clkref_en", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_gp1_clk = { + .halt_reg = 0x47000, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x47000, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_gp1_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_gp1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_gp2_clk = { + .halt_reg = 0x48000, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x48000, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_gp2_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_gp2_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_gp3_clk = { + .halt_reg = 0x49000, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x49000, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_gp3_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_gp3_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_0_clkref_en = { + .halt_reg = 0x98004, + .halt_check = BRANCH_HALT_ENABLE, + .clkr = { + .enable_reg = 0x98004, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_0_clkref_en", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_1_aux_clk = { + .halt_reg = 0x67038, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x7d010, + .enable_mask = BIT(22), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_1_aux_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_pcie_1_aux_phy_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_1_cfg_ahb_clk = { + .halt_reg = 0x67034, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x67034, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x7d010, + .enable_mask = BIT(21), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_1_cfg_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_1_clkref_en = { + .halt_reg = 0x98114, + .halt_check = BRANCH_HALT_ENABLE, + .clkr = { + .enable_reg = 0x98114, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_1_clkref_en", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_1_mstr_axi_clk = { + .halt_reg = 0x67028, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x7d010, + .enable_mask = BIT(20), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_1_mstr_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_1_phy_rchng_clk = { + .halt_reg = 0x67068, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x7d010, + .enable_mask = BIT(24), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_1_phy_rchng_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_pcie_1_phy_rchng_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_1_pipe_clk = { + .halt_reg = 0x6705c, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x7d010, + .enable_mask = BIT(23), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_1_pipe_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_pcie_1_pipe_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_1_pipe_div2_clk = { + .halt_reg = 0x6708c, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x7d020, + .enable_mask = BIT(3), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_1_pipe_div2_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_pcie_1_pipe_div2_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_1_slv_axi_clk = { + .halt_reg = 0x6701c, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x7d010, + .enable_mask = BIT(19), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_1_slv_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_1_slv_q2a_axi_clk = { + .halt_reg = 0x67018, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x7d010, + .enable_mask = BIT(18), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_1_slv_q2a_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_2_aux_clk = { + .halt_reg = 0x68058, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x7d010, + .enable_mask = BIT(29), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_2_aux_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_pcie_2_aux_phy_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_2_cfg_ahb_clk = { + .halt_reg = 0x68034, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x68034, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x7d010, + .enable_mask = BIT(28), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_2_cfg_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_2_clkref_en = { + .halt_reg = 0x98110, + .halt_check = BRANCH_HALT_ENABLE, + .clkr = { + .enable_reg = 0x98110, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_2_clkref_en", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_2_mstr_axi_clk = { + .halt_reg = 0x68028, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x7d008, + .enable_mask = BIT(8), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_2_mstr_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_2_phy_rchng_clk = { + .halt_reg = 0x68098, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x7d010, + .enable_mask = BIT(31), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_2_phy_rchng_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_pcie_2_phy_rchng_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_2_pipe_clk = { + .halt_reg = 0x6807c, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x7d010, + .enable_mask = BIT(30), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_2_pipe_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_pcie_2_pipe_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_2_pipe_div2_clk = { + .halt_reg = 0x6808c, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x7d020, + .enable_mask = BIT(4), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_2_pipe_div2_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_pcie_2_pipe_div2_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_2_slv_axi_clk = { + .halt_reg = 0x6801c, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x7d010, + .enable_mask = BIT(26), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_2_slv_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_2_slv_q2a_axi_clk = { + .halt_reg = 0x68018, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x7d010, + .enable_mask = BIT(25), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_2_slv_q2a_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_aux_clk = { + .halt_reg = 0x5303c, + .halt_check = BRANCH_HALT_DELAY, + .hwcg_reg = 0x5303c, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x7d010, + .enable_mask = BIT(15), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_aux_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_pcie_aux_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_cfg_ahb_clk = { + .halt_reg = 0x53034, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x53034, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x7d010, + .enable_mask = BIT(13), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_cfg_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_mstr_axi_clk = { + .halt_reg = 0x53028, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x53028, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x7d010, + .enable_mask = BIT(12), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_mstr_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_pipe_clk = { + .halt_reg = 0x5304c, + .halt_check = BRANCH_HALT_DELAY, + .hwcg_reg = 0x5304c, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x7d010, + .enable_mask = BIT(17), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_pipe_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_pcie_pipe_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_rchng_phy_clk = { + .halt_reg = 0x53038, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x53038, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x7d010, + .enable_mask = BIT(14), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_rchng_phy_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_pcie_rchng_phy_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_sleep_clk = { + .halt_reg = 0x53048, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x53048, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x7d010, + .enable_mask = BIT(16), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_sleep_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_pcie_aux_phy_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_slv_axi_clk = { + .halt_reg = 0x5301c, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x7d010, + .enable_mask = BIT(11), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_slv_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_slv_q2a_axi_clk = { + .halt_reg = 0x53018, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x53018, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x7d010, + .enable_mask = BIT(10), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_slv_q2a_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pdm2_clk = { + .halt_reg = 0x3400c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x3400c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pdm2_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_pdm2_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pdm_ahb_clk = { + .halt_reg = 0x34004, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x34004, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pdm_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pdm_xo4_clk = { + .halt_reg = 0x34008, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x34008, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pdm_xo4_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap0_core_2x_clk = { + .halt_reg = 0x2d018, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x7d008, + .enable_mask = BIT(15), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qupv3_wrap0_core_2x_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap0_core_clk = { + .halt_reg = 0x2d008, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x7d008, + .enable_mask = BIT(14), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qupv3_wrap0_core_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap0_s0_clk = { + .halt_reg = 0x6c004, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x7d008, + .enable_mask = BIT(16), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qupv3_wrap0_s0_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_qupv3_wrap0_s0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap0_s1_clk = { + .halt_reg = 0x6c13c, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x7d008, + .enable_mask = BIT(17), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qupv3_wrap0_s1_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_qupv3_wrap0_s1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap0_s2_clk = { + .halt_reg = 0x6c274, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x7d008, + .enable_mask = BIT(18), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qupv3_wrap0_s2_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_qupv3_wrap0_s2_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap0_s3_clk = { + .halt_reg = 0x6c3ac, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x7d008, + .enable_mask = BIT(19), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qupv3_wrap0_s3_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_qupv3_wrap0_s3_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap0_s4_clk = { + .halt_reg = 0x6c4e4, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x7d008, + .enable_mask = BIT(20), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qupv3_wrap0_s4_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_qupv3_wrap0_s4_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap0_s5_clk = { + .halt_reg = 0x6c61c, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x7d008, + .enable_mask = BIT(21), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qupv3_wrap0_s5_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_qupv3_wrap0_s5_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap0_s6_clk = { + .halt_reg = 0x6c754, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x7d008, + .enable_mask = BIT(22), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qupv3_wrap0_s6_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_qupv3_wrap0_s6_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap0_s7_clk = { + .halt_reg = 0x6c88c, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x7d008, + .enable_mask = BIT(23), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qupv3_wrap0_s7_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_qupv3_wrap0_s7_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap0_s8_clk = { + .halt_reg = 0x6c9c4, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x7d020, + .enable_mask = BIT(7), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qupv3_wrap0_s8_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_qupv3_wrap0_s8_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap_0_m_ahb_clk = { + .halt_reg = 0x2d000, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x2d000, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x7d008, + .enable_mask = BIT(12), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qupv3_wrap_0_m_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap_0_s_ahb_clk = { + .halt_reg = 0x2d004, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x2d004, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x7d008, + .enable_mask = BIT(13), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qupv3_wrap_0_s_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_sdcc1_ahb_clk = { + .halt_reg = 0x6b004, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x6b004, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_sdcc1_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_sdcc1_apps_clk = { + .halt_reg = 0x6b008, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x6b008, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_sdcc1_apps_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_sdcc1_apps_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_sdcc2_ahb_clk = { + .halt_reg = 0x6a010, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x6a010, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_sdcc2_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_sdcc2_apps_clk = { + .halt_reg = 0x6a004, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x6a004, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_sdcc2_apps_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_sdcc2_apps_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb2_clkref_en = { + .halt_reg = 0x98008, + .halt_check = BRANCH_HALT_ENABLE, + .clkr = { + .enable_reg = 0x98008, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb2_clkref_en", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb30_master_clk = { + .halt_reg = 0x27018, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x27018, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb30_master_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_usb30_master_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb30_mock_utmi_clk = { + .halt_reg = 0x27030, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x27030, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb30_mock_utmi_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_usb30_mock_utmi_postdiv_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb30_mstr_axi_clk = { + .halt_reg = 0x27024, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x27024, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb30_mstr_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb30_sleep_clk = { + .halt_reg = 0x2702c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x2702c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb30_sleep_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb30_slv_ahb_clk = { + .halt_reg = 0x27028, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x27028, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb30_slv_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb3_phy_aux_clk = { + .halt_reg = 0x27068, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x27068, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb3_phy_aux_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_usb3_phy_aux_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb3_phy_pipe_clk = { + .halt_reg = 0x2706c, + .halt_check = BRANCH_HALT_DELAY, + .hwcg_reg = 0x2706c, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x2706c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb3_phy_pipe_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_usb3_phy_pipe_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb3_prim_clkref_en = { + .halt_reg = 0x98000, + .halt_check = BRANCH_HALT_ENABLE, + .clkr = { + .enable_reg = 0x98000, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb3_prim_clkref_en", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb_phy_cfg_ahb2phy_clk = { + .halt_reg = 0x29004, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x29004, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x29004, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb_phy_cfg_ahb2phy_clk", + .ops = &clk_branch2_aon_ops, + }, + }, +}; + +static struct gdsc gcc_emac0_gdsc = { + .gdscr = 0x71004, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0xf, + .pd = { + .name = "gcc_emac0_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .flags = RETAIN_FF_ENABLE, +}; + +static struct gdsc gcc_emac1_gdsc = { + .gdscr = 0x72004, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0xf, + .pd = { + .name = "gcc_emac1_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .flags = RETAIN_FF_ENABLE, +}; + +static struct gdsc gcc_pcie_1_gdsc = { + .gdscr = 0x67004, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0xf, + .pd = { + .name = "gcc_pcie_1_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .flags = RETAIN_FF_ENABLE, +}; + +static struct gdsc gcc_pcie_1_phy_gdsc = { + .gdscr = 0x56004, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0x2, + .pd = { + .name = "gcc_pcie_1_phy_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .flags = RETAIN_FF_ENABLE, +}; + +static struct gdsc gcc_pcie_2_gdsc = { + .gdscr = 0x68004, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0xf, + .pd = { + .name = "gcc_pcie_2_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .flags = RETAIN_FF_ENABLE, +}; + +static struct gdsc gcc_pcie_2_phy_gdsc = { + .gdscr = 0x6e004, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0x2, + .pd = { + .name = "gcc_pcie_2_phy_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .flags = RETAIN_FF_ENABLE, +}; + +static struct gdsc gcc_pcie_gdsc = { + .gdscr = 0x53004, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0xf, + .pd = { + .name = "gcc_pcie_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .flags = RETAIN_FF_ENABLE, +}; + +static struct gdsc gcc_pcie_phy_gdsc = { + .gdscr = 0x54004, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0x2, + .pd = { + .name = "gcc_pcie_phy_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .flags = RETAIN_FF_ENABLE, +}; + +static struct gdsc gcc_usb30_gdsc = { + .gdscr = 0x27004, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0xf, + .pd = { + .name = "gcc_usb30_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .flags = RETAIN_FF_ENABLE, +}; + +static struct gdsc gcc_usb3_phy_gdsc = { + .gdscr = 0x28008, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0x2, + .pd = { + .name = "gcc_usb3_phy_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .flags = RETAIN_FF_ENABLE, +}; + +static struct clk_regmap *gcc_sdx75_clocks[] = { + [GCC_BOOT_ROM_AHB_CLK] = &gcc_boot_rom_ahb_clk.clkr, + [GCC_EEE_EMAC0_CLK] = &gcc_eee_emac0_clk.clkr, + [GCC_EEE_EMAC0_CLK_SRC] = &gcc_eee_emac0_clk_src.clkr, + [GCC_EEE_EMAC1_CLK] = &gcc_eee_emac1_clk.clkr, + [GCC_EEE_EMAC1_CLK_SRC] = &gcc_eee_emac1_clk_src.clkr, + [GCC_EMAC0_AXI_CLK] = &gcc_emac0_axi_clk.clkr, + [GCC_EMAC0_CC_SGMIIPHY_RX_CLK] = &gcc_emac0_cc_sgmiiphy_rx_clk.clkr, + [GCC_EMAC0_CC_SGMIIPHY_RX_CLK_SRC] = &gcc_emac0_cc_sgmiiphy_rx_clk_src.clkr, + [GCC_EMAC0_CC_SGMIIPHY_TX_CLK] = &gcc_emac0_cc_sgmiiphy_tx_clk.clkr, + [GCC_EMAC0_CC_SGMIIPHY_TX_CLK_SRC] = &gcc_emac0_cc_sgmiiphy_tx_clk_src.clkr, + [GCC_EMAC0_PHY_AUX_CLK] = &gcc_emac0_phy_aux_clk.clkr, + [GCC_EMAC0_PHY_AUX_CLK_SRC] = &gcc_emac0_phy_aux_clk_src.clkr, + [GCC_EMAC0_PTP_CLK] = &gcc_emac0_ptp_clk.clkr, + [GCC_EMAC0_PTP_CLK_SRC] = &gcc_emac0_ptp_clk_src.clkr, + [GCC_EMAC0_RGMII_CLK] = &gcc_emac0_rgmii_clk.clkr, + [GCC_EMAC0_RGMII_CLK_SRC] = &gcc_emac0_rgmii_clk_src.clkr, + [GCC_EMAC0_RPCS_RX_CLK] = &gcc_emac0_rpcs_rx_clk.clkr, + [GCC_EMAC0_RPCS_TX_CLK] = &gcc_emac0_rpcs_tx_clk.clkr, + [GCC_EMAC0_SGMIIPHY_MAC_RCLK_SRC] = &gcc_emac0_sgmiiphy_mac_rclk_src.clkr, + [GCC_EMAC0_SGMIIPHY_MAC_TCLK_SRC] = &gcc_emac0_sgmiiphy_mac_tclk_src.clkr, + [GCC_EMAC0_SLV_AHB_CLK] = &gcc_emac0_slv_ahb_clk.clkr, + [GCC_EMAC0_XGXS_RX_CLK] = &gcc_emac0_xgxs_rx_clk.clkr, + [GCC_EMAC0_XGXS_TX_CLK] = &gcc_emac0_xgxs_tx_clk.clkr, + [GCC_EMAC1_AXI_CLK] = &gcc_emac1_axi_clk.clkr, + [GCC_EMAC1_CC_SGMIIPHY_RX_CLK] = &gcc_emac1_cc_sgmiiphy_rx_clk.clkr, + [GCC_EMAC1_CC_SGMIIPHY_RX_CLK_SRC] = &gcc_emac1_cc_sgmiiphy_rx_clk_src.clkr, + [GCC_EMAC1_CC_SGMIIPHY_TX_CLK] = &gcc_emac1_cc_sgmiiphy_tx_clk.clkr, + [GCC_EMAC1_CC_SGMIIPHY_TX_CLK_SRC] = &gcc_emac1_cc_sgmiiphy_tx_clk_src.clkr, + [GCC_EMAC1_PHY_AUX_CLK] = &gcc_emac1_phy_aux_clk.clkr, + [GCC_EMAC1_PHY_AUX_CLK_SRC] = &gcc_emac1_phy_aux_clk_src.clkr, + [GCC_EMAC1_PTP_CLK] = &gcc_emac1_ptp_clk.clkr, + [GCC_EMAC1_PTP_CLK_SRC] = &gcc_emac1_ptp_clk_src.clkr, + [GCC_EMAC1_RGMII_CLK] = &gcc_emac1_rgmii_clk.clkr, + [GCC_EMAC1_RGMII_CLK_SRC] = &gcc_emac1_rgmii_clk_src.clkr, + [GCC_EMAC1_RPCS_RX_CLK] = &gcc_emac1_rpcs_rx_clk.clkr, + [GCC_EMAC1_RPCS_TX_CLK] = &gcc_emac1_rpcs_tx_clk.clkr, + [GCC_EMAC1_SGMIIPHY_MAC_RCLK_SRC] = &gcc_emac1_sgmiiphy_mac_rclk_src.clkr, + [GCC_EMAC1_SGMIIPHY_MAC_TCLK_SRC] = &gcc_emac1_sgmiiphy_mac_tclk_src.clkr, + [GCC_EMAC1_SLV_AHB_CLK] = &gcc_emac1_slv_ahb_clk.clkr, + [GCC_EMAC1_XGXS_RX_CLK] = &gcc_emac1_xgxs_rx_clk.clkr, + [GCC_EMAC1_XGXS_TX_CLK] = &gcc_emac1_xgxs_tx_clk.clkr, + [GCC_EMAC_0_CLKREF_EN] = &gcc_emac_0_clkref_en.clkr, + [GCC_EMAC_1_CLKREF_EN] = &gcc_emac_1_clkref_en.clkr, + [GCC_GP1_CLK] = &gcc_gp1_clk.clkr, + [GCC_GP1_CLK_SRC] = &gcc_gp1_clk_src.clkr, + [GCC_GP2_CLK] = &gcc_gp2_clk.clkr, + [GCC_GP2_CLK_SRC] = &gcc_gp2_clk_src.clkr, + [GCC_GP3_CLK] = &gcc_gp3_clk.clkr, + [GCC_GP3_CLK_SRC] = &gcc_gp3_clk_src.clkr, + [GCC_PCIE_0_CLKREF_EN] = &gcc_pcie_0_clkref_en.clkr, + [GCC_PCIE_1_AUX_CLK] = &gcc_pcie_1_aux_clk.clkr, + [GCC_PCIE_1_AUX_PHY_CLK_SRC] = &gcc_pcie_1_aux_phy_clk_src.clkr, + [GCC_PCIE_1_CFG_AHB_CLK] = &gcc_pcie_1_cfg_ahb_clk.clkr, + [GCC_PCIE_1_CLKREF_EN] = &gcc_pcie_1_clkref_en.clkr, + [GCC_PCIE_1_MSTR_AXI_CLK] = &gcc_pcie_1_mstr_axi_clk.clkr, + [GCC_PCIE_1_PHY_RCHNG_CLK] = &gcc_pcie_1_phy_rchng_clk.clkr, + [GCC_PCIE_1_PHY_RCHNG_CLK_SRC] = &gcc_pcie_1_phy_rchng_clk_src.clkr, + [GCC_PCIE_1_PIPE_CLK] = &gcc_pcie_1_pipe_clk.clkr, + [GCC_PCIE_1_PIPE_CLK_SRC] = &gcc_pcie_1_pipe_clk_src.clkr, + [GCC_PCIE_1_PIPE_DIV2_CLK] = &gcc_pcie_1_pipe_div2_clk.clkr, + [GCC_PCIE_1_PIPE_DIV2_CLK_SRC] = &gcc_pcie_1_pipe_div2_clk_src.clkr, + [GCC_PCIE_1_SLV_AXI_CLK] = &gcc_pcie_1_slv_axi_clk.clkr, + [GCC_PCIE_1_SLV_Q2A_AXI_CLK] = &gcc_pcie_1_slv_q2a_axi_clk.clkr, + [GCC_PCIE_2_AUX_CLK] = &gcc_pcie_2_aux_clk.clkr, + [GCC_PCIE_2_AUX_PHY_CLK_SRC] = &gcc_pcie_2_aux_phy_clk_src.clkr, + [GCC_PCIE_2_CFG_AHB_CLK] = &gcc_pcie_2_cfg_ahb_clk.clkr, + [GCC_PCIE_2_CLKREF_EN] = &gcc_pcie_2_clkref_en.clkr, + [GCC_PCIE_2_MSTR_AXI_CLK] = &gcc_pcie_2_mstr_axi_clk.clkr, + [GCC_PCIE_2_PHY_RCHNG_CLK] = &gcc_pcie_2_phy_rchng_clk.clkr, + [GCC_PCIE_2_PHY_RCHNG_CLK_SRC] = &gcc_pcie_2_phy_rchng_clk_src.clkr, + [GCC_PCIE_2_PIPE_CLK] = &gcc_pcie_2_pipe_clk.clkr, + [GCC_PCIE_2_PIPE_CLK_SRC] = &gcc_pcie_2_pipe_clk_src.clkr, + [GCC_PCIE_2_PIPE_DIV2_CLK] = &gcc_pcie_2_pipe_div2_clk.clkr, + [GCC_PCIE_2_PIPE_DIV2_CLK_SRC] = &gcc_pcie_2_pipe_div2_clk_src.clkr, + [GCC_PCIE_2_SLV_AXI_CLK] = &gcc_pcie_2_slv_axi_clk.clkr, + [GCC_PCIE_2_SLV_Q2A_AXI_CLK] = &gcc_pcie_2_slv_q2a_axi_clk.clkr, + [GCC_PCIE_AUX_CLK] = &gcc_pcie_aux_clk.clkr, + [GCC_PCIE_AUX_CLK_SRC] = &gcc_pcie_aux_clk_src.clkr, + [GCC_PCIE_AUX_PHY_CLK_SRC] = &gcc_pcie_aux_phy_clk_src.clkr, + [GCC_PCIE_CFG_AHB_CLK] = &gcc_pcie_cfg_ahb_clk.clkr, + [GCC_PCIE_MSTR_AXI_CLK] = &gcc_pcie_mstr_axi_clk.clkr, + [GCC_PCIE_PIPE_CLK] = &gcc_pcie_pipe_clk.clkr, + [GCC_PCIE_PIPE_CLK_SRC] = &gcc_pcie_pipe_clk_src.clkr, + [GCC_PCIE_RCHNG_PHY_CLK] = &gcc_pcie_rchng_phy_clk.clkr, + [GCC_PCIE_RCHNG_PHY_CLK_SRC] = &gcc_pcie_rchng_phy_clk_src.clkr, + [GCC_PCIE_SLEEP_CLK] = &gcc_pcie_sleep_clk.clkr, + [GCC_PCIE_SLV_AXI_CLK] = &gcc_pcie_slv_axi_clk.clkr, + [GCC_PCIE_SLV_Q2A_AXI_CLK] = &gcc_pcie_slv_q2a_axi_clk.clkr, + [GCC_PDM2_CLK] = &gcc_pdm2_clk.clkr, + [GCC_PDM2_CLK_SRC] = &gcc_pdm2_clk_src.clkr, + [GCC_PDM_AHB_CLK] = &gcc_pdm_ahb_clk.clkr, + [GCC_PDM_XO4_CLK] = &gcc_pdm_xo4_clk.clkr, + [GCC_QUPV3_WRAP0_CORE_2X_CLK] = &gcc_qupv3_wrap0_core_2x_clk.clkr, + [GCC_QUPV3_WRAP0_CORE_CLK] = &gcc_qupv3_wrap0_core_clk.clkr, + [GCC_QUPV3_WRAP0_S0_CLK] = &gcc_qupv3_wrap0_s0_clk.clkr, + [GCC_QUPV3_WRAP0_S0_CLK_SRC] = &gcc_qupv3_wrap0_s0_clk_src.clkr, + [GCC_QUPV3_WRAP0_S1_CLK] = &gcc_qupv3_wrap0_s1_clk.clkr, + [GCC_QUPV3_WRAP0_S1_CLK_SRC] = &gcc_qupv3_wrap0_s1_clk_src.clkr, + [GCC_QUPV3_WRAP0_S2_CLK] = &gcc_qupv3_wrap0_s2_clk.clkr, + [GCC_QUPV3_WRAP0_S2_CLK_SRC] = &gcc_qupv3_wrap0_s2_clk_src.clkr, + [GCC_QUPV3_WRAP0_S3_CLK] = &gcc_qupv3_wrap0_s3_clk.clkr, + [GCC_QUPV3_WRAP0_S3_CLK_SRC] = &gcc_qupv3_wrap0_s3_clk_src.clkr, + [GCC_QUPV3_WRAP0_S4_CLK] = &gcc_qupv3_wrap0_s4_clk.clkr, + [GCC_QUPV3_WRAP0_S4_CLK_SRC] = &gcc_qupv3_wrap0_s4_clk_src.clkr, + [GCC_QUPV3_WRAP0_S5_CLK] = &gcc_qupv3_wrap0_s5_clk.clkr, + [GCC_QUPV3_WRAP0_S5_CLK_SRC] = &gcc_qupv3_wrap0_s5_clk_src.clkr, + [GCC_QUPV3_WRAP0_S6_CLK] = &gcc_qupv3_wrap0_s6_clk.clkr, + [GCC_QUPV3_WRAP0_S6_CLK_SRC] = &gcc_qupv3_wrap0_s6_clk_src.clkr, + [GCC_QUPV3_WRAP0_S7_CLK] = &gcc_qupv3_wrap0_s7_clk.clkr, + [GCC_QUPV3_WRAP0_S7_CLK_SRC] = &gcc_qupv3_wrap0_s7_clk_src.clkr, + [GCC_QUPV3_WRAP0_S8_CLK] = &gcc_qupv3_wrap0_s8_clk.clkr, + [GCC_QUPV3_WRAP0_S8_CLK_SRC] = &gcc_qupv3_wrap0_s8_clk_src.clkr, + [GCC_QUPV3_WRAP_0_M_AHB_CLK] = &gcc_qupv3_wrap_0_m_ahb_clk.clkr, + [GCC_QUPV3_WRAP_0_S_AHB_CLK] = &gcc_qupv3_wrap_0_s_ahb_clk.clkr, + [GCC_SDCC1_AHB_CLK] = &gcc_sdcc1_ahb_clk.clkr, + [GCC_SDCC1_APPS_CLK] = &gcc_sdcc1_apps_clk.clkr, + [GCC_SDCC1_APPS_CLK_SRC] = &gcc_sdcc1_apps_clk_src.clkr, + [GCC_SDCC2_AHB_CLK] = &gcc_sdcc2_ahb_clk.clkr, + [GCC_SDCC2_APPS_CLK] = &gcc_sdcc2_apps_clk.clkr, + [GCC_SDCC2_APPS_CLK_SRC] = &gcc_sdcc2_apps_clk_src.clkr, + [GCC_USB2_CLKREF_EN] = &gcc_usb2_clkref_en.clkr, + [GCC_USB30_MASTER_CLK] = &gcc_usb30_master_clk.clkr, + [GCC_USB30_MASTER_CLK_SRC] = &gcc_usb30_master_clk_src.clkr, + [GCC_USB30_MOCK_UTMI_CLK] = &gcc_usb30_mock_utmi_clk.clkr, + [GCC_USB30_MOCK_UTMI_CLK_SRC] = &gcc_usb30_mock_utmi_clk_src.clkr, + [GCC_USB30_MOCK_UTMI_POSTDIV_CLK_SRC] = &gcc_usb30_mock_utmi_postdiv_clk_src.clkr, + [GCC_USB30_MSTR_AXI_CLK] = &gcc_usb30_mstr_axi_clk.clkr, + [GCC_USB30_SLEEP_CLK] = &gcc_usb30_sleep_clk.clkr, + [GCC_USB30_SLV_AHB_CLK] = &gcc_usb30_slv_ahb_clk.clkr, + [GCC_USB3_PHY_AUX_CLK] = &gcc_usb3_phy_aux_clk.clkr, + [GCC_USB3_PHY_AUX_CLK_SRC] = &gcc_usb3_phy_aux_clk_src.clkr, + [GCC_USB3_PHY_PIPE_CLK] = &gcc_usb3_phy_pipe_clk.clkr, + [GCC_USB3_PHY_PIPE_CLK_SRC] = &gcc_usb3_phy_pipe_clk_src.clkr, + [GCC_USB3_PRIM_CLKREF_EN] = &gcc_usb3_prim_clkref_en.clkr, + [GCC_USB_PHY_CFG_AHB2PHY_CLK] = &gcc_usb_phy_cfg_ahb2phy_clk.clkr, + [GPLL0] = &gpll0.clkr, + [GPLL0_OUT_EVEN] = &gpll0_out_even.clkr, + [GPLL4] = &gpll4.clkr, + [GPLL5] = &gpll5.clkr, + [GPLL6] = &gpll6.clkr, + [GPLL8] = &gpll8.clkr, +}; + +static struct gdsc *gcc_sdx75_gdscs[] = { + [GCC_EMAC0_GDSC] = &gcc_emac0_gdsc, + [GCC_EMAC1_GDSC] = &gcc_emac1_gdsc, + [GCC_PCIE_1_GDSC] = &gcc_pcie_1_gdsc, + [GCC_PCIE_1_PHY_GDSC] = &gcc_pcie_1_phy_gdsc, + [GCC_PCIE_2_GDSC] = &gcc_pcie_2_gdsc, + [GCC_PCIE_2_PHY_GDSC] = &gcc_pcie_2_phy_gdsc, + [GCC_PCIE_GDSC] = &gcc_pcie_gdsc, + [GCC_PCIE_PHY_GDSC] = &gcc_pcie_phy_gdsc, + [GCC_USB30_GDSC] = &gcc_usb30_gdsc, + [GCC_USB3_PHY_GDSC] = &gcc_usb3_phy_gdsc, +}; + +static const struct qcom_reset_map gcc_sdx75_resets[] = { + [GCC_EMAC0_BCR] = { 0x71000 }, + [GCC_EMAC0_RGMII_CLK_ARES] = { 0x71050, 2 }, + [GCC_EMAC1_BCR] = { 0x72000 }, + [GCC_EMMC_BCR] = { 0x6b000 }, + [GCC_PCIE_1_BCR] = { 0x67000 }, + [GCC_PCIE_1_LINK_DOWN_BCR] = { 0x9e700 }, + [GCC_PCIE_1_NOCSR_COM_PHY_BCR] = { 0x56120 }, + [GCC_PCIE_1_PHY_BCR] = { 0x56000 }, + [GCC_PCIE_2_BCR] = { 0x68000 }, + [GCC_PCIE_2_LINK_DOWN_BCR] = { 0x9f700 }, + [GCC_PCIE_2_NOCSR_COM_PHY_BCR] = { 0x6e130 }, + [GCC_PCIE_2_PHY_BCR] = { 0x6e000 }, + [GCC_PCIE_BCR] = { 0x53000 }, + [GCC_PCIE_LINK_DOWN_BCR] = { 0x87000 }, + [GCC_PCIE_NOCSR_COM_PHY_BCR] = { 0x88008 }, + [GCC_PCIE_PHY_BCR] = { 0x54000 }, + [GCC_PCIE_PHY_CFG_AHB_BCR] = { 0x88000 }, + [GCC_PCIE_PHY_COM_BCR] = { 0x88004 }, + [GCC_PCIE_PHY_NOCSR_COM_PHY_BCR] = { 0x8800c }, + [GCC_QUSB2PHY_BCR] = { 0x2a000 }, + [GCC_TCSR_PCIE_BCR] = { 0x84000 }, + [GCC_USB30_BCR] = { 0x27000 }, + [GCC_USB3_PHY_BCR] = { 0x28000 }, + [GCC_USB3PHY_PHY_BCR] = { 0x28004 }, + [GCC_USB_PHY_CFG_AHB2PHY_BCR] = { 0x29000 }, +}; + +static const struct clk_rcg_dfs_data gcc_dfs_clocks[] = { + DEFINE_RCG_DFS(gcc_qupv3_wrap0_s0_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap0_s1_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap0_s2_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap0_s3_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap0_s4_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap0_s5_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap0_s6_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap0_s7_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap0_s8_clk_src), +}; + +static const struct regmap_config gcc_sdx75_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0x1f41f0, + .fast_io = true, +}; + +static const struct qcom_cc_desc gcc_sdx75_desc = { + .config = &gcc_sdx75_regmap_config, + .clks = gcc_sdx75_clocks, + .num_clks = ARRAY_SIZE(gcc_sdx75_clocks), + .resets = gcc_sdx75_resets, + .num_resets = ARRAY_SIZE(gcc_sdx75_resets), + .gdscs = gcc_sdx75_gdscs, + .num_gdscs = ARRAY_SIZE(gcc_sdx75_gdscs), +}; + +static const struct of_device_id gcc_sdx75_match_table[] = { + { .compatible = "qcom,sdx75-gcc" }, + { } +}; +MODULE_DEVICE_TABLE(of, gcc_sdx75_match_table); + +static int gcc_sdx75_probe(struct platform_device *pdev) +{ + struct regmap *regmap; + int ret; + + regmap = qcom_cc_map(pdev, &gcc_sdx75_desc); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + + ret = qcom_cc_register_rcg_dfs(regmap, gcc_dfs_clocks, + ARRAY_SIZE(gcc_dfs_clocks)); + if (ret) + return ret; + + /* + * Keep clocks always enabled: + * gcc_ahb_pcie_link_clk + * gcc_xo_pcie_link_clk + */ + regmap_update_bits(regmap, 0x3e004, BIT(0), BIT(0)); + regmap_update_bits(regmap, 0x3e008, BIT(0), BIT(0)); + + return qcom_cc_really_probe(pdev, &gcc_sdx75_desc, regmap); +} + +static struct platform_driver gcc_sdx75_driver = { + .probe = gcc_sdx75_probe, + .driver = { + .name = "gcc-sdx75", + .of_match_table = gcc_sdx75_match_table, + }, +}; + +static int __init gcc_sdx75_init(void) +{ + return platform_driver_register(&gcc_sdx75_driver); +} +subsys_initcall(gcc_sdx75_init); + +static void __exit gcc_sdx75_exit(void) +{ + platform_driver_unregister(&gcc_sdx75_driver); +} +module_exit(gcc_sdx75_exit); + +MODULE_DESCRIPTION("QTI GCC SDX75 Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/qcom/gcc-sm6115.c b/drivers/clk/qcom/gcc-sm6115.c index 5f09aefa7fb927c856f97f2916b1320816358334..033e308ff865a7719ed88ca56ee2d13470f97187 100644 --- a/drivers/clk/qcom/gcc-sm6115.c +++ b/drivers/clk/qcom/gcc-sm6115.c @@ -119,6 +119,8 @@ static const struct alpha_pll_config gpll10_config = { .vco_mask = GENMASK(21, 20), .main_output_mask = BIT(0), .config_ctl_val = 0x4001055b, + .test_ctl_hi1_val = 0x1, + .test_ctl_hi_mask = 0x1, }; static struct clk_alpha_pll gpll10 = { @@ -170,6 +172,8 @@ static const struct alpha_pll_config gpll11_config = { .vco_val = 0x2 << 20, .vco_mask = GENMASK(21, 20), .config_ctl_val = 0x4001055b, + .test_ctl_hi1_val = 0x1, + .test_ctl_hi_mask = 0x1, }; static struct clk_alpha_pll gpll11 = { @@ -362,6 +366,8 @@ static const struct alpha_pll_config gpll8_config = { .post_div_val = 0x1 << 8, .post_div_mask = GENMASK(11, 8), .config_ctl_val = 0x4001055b, + .test_ctl_hi1_val = 0x1, + .test_ctl_hi_mask = 0x1, }; static struct clk_alpha_pll gpll8 = { @@ -413,6 +419,8 @@ static const struct alpha_pll_config gpll9_config = { .post_div_mask = GENMASK(9, 8), .main_output_mask = BIT(0), .config_ctl_val = 0x00004289, + .test_ctl_mask = GENMASK(31, 0), + .test_ctl_val = 0x08000000, }; static struct clk_alpha_pll gpll9 = { diff --git a/drivers/clk/qcom/gcc-sm8450.c b/drivers/clk/qcom/gcc-sm8450.c index 84764cc3db4ff1db99471016c9d0bb64bace6fbf..75635d40a12d312801111cc4229dc7927c7f021f 100644 --- a/drivers/clk/qcom/gcc-sm8450.c +++ b/drivers/clk/qcom/gcc-sm8450.c @@ -334,6 +334,7 @@ static struct clk_rcg2 gcc_gp1_clk_src = { .hid_width = 5, .parent_map = gcc_parent_map_1, .freq_tbl = ftbl_gcc_gp1_clk_src, + .hw_clk_ctrl = true, .clkr.hw.init = &(struct clk_init_data){ .name = "gcc_gp1_clk_src", .parent_data = gcc_parent_data_1, @@ -349,6 +350,7 @@ static struct clk_rcg2 gcc_gp2_clk_src = { .hid_width = 5, .parent_map = gcc_parent_map_1, .freq_tbl = ftbl_gcc_gp1_clk_src, + .hw_clk_ctrl = true, .clkr.hw.init = &(struct clk_init_data){ .name = "gcc_gp2_clk_src", .parent_data = gcc_parent_data_1, @@ -364,6 +366,7 @@ static struct clk_rcg2 gcc_gp3_clk_src = { .hid_width = 5, .parent_map = gcc_parent_map_1, .freq_tbl = ftbl_gcc_gp1_clk_src, + .hw_clk_ctrl = true, .clkr.hw.init = &(struct clk_init_data){ .name = "gcc_gp3_clk_src", .parent_data = gcc_parent_data_1, @@ -384,6 +387,7 @@ static struct clk_rcg2 gcc_pcie_0_aux_clk_src = { .hid_width = 5, .parent_map = gcc_parent_map_2, .freq_tbl = ftbl_gcc_pcie_0_aux_clk_src, + .hw_clk_ctrl = true, .clkr.hw.init = &(struct clk_init_data){ .name = "gcc_pcie_0_aux_clk_src", .parent_data = gcc_parent_data_2, @@ -405,6 +409,7 @@ static struct clk_rcg2 gcc_pcie_0_phy_rchng_clk_src = { .hid_width = 5, .parent_map = gcc_parent_map_0, .freq_tbl = ftbl_gcc_pcie_0_phy_rchng_clk_src, + .hw_clk_ctrl = true, .clkr.hw.init = &(struct clk_init_data){ .name = "gcc_pcie_0_phy_rchng_clk_src", .parent_data = gcc_parent_data_0, @@ -420,6 +425,7 @@ static struct clk_rcg2 gcc_pcie_1_aux_clk_src = { .hid_width = 5, .parent_map = gcc_parent_map_2, .freq_tbl = ftbl_gcc_pcie_0_aux_clk_src, + .hw_clk_ctrl = true, .clkr.hw.init = &(struct clk_init_data){ .name = "gcc_pcie_1_aux_clk_src", .parent_data = gcc_parent_data_2, @@ -435,6 +441,7 @@ static struct clk_rcg2 gcc_pcie_1_phy_rchng_clk_src = { .hid_width = 5, .parent_map = gcc_parent_map_0, .freq_tbl = ftbl_gcc_pcie_0_phy_rchng_clk_src, + .hw_clk_ctrl = true, .clkr.hw.init = &(struct clk_init_data){ .name = "gcc_pcie_1_phy_rchng_clk_src", .parent_data = gcc_parent_data_0, @@ -455,6 +462,7 @@ static struct clk_rcg2 gcc_pdm2_clk_src = { .hid_width = 5, .parent_map = gcc_parent_map_0, .freq_tbl = ftbl_gcc_pdm2_clk_src, + .hw_clk_ctrl = true, .clkr.hw.init = &(struct clk_init_data){ .name = "gcc_pdm2_clk_src", .parent_data = gcc_parent_data_0, @@ -493,6 +501,7 @@ static struct clk_rcg2 gcc_qupv3_wrap0_s0_clk_src = { .hid_width = 5, .parent_map = gcc_parent_map_0, .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .hw_clk_ctrl = true, .clkr.hw.init = &gcc_qupv3_wrap0_s0_clk_src_init, }; @@ -510,6 +519,7 @@ static struct clk_rcg2 gcc_qupv3_wrap0_s1_clk_src = { .hid_width = 5, .parent_map = gcc_parent_map_0, .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .hw_clk_ctrl = true, .clkr.hw.init = &gcc_qupv3_wrap0_s1_clk_src_init, }; @@ -527,6 +537,7 @@ static struct clk_rcg2 gcc_qupv3_wrap0_s2_clk_src = { .hid_width = 5, .parent_map = gcc_parent_map_0, .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .hw_clk_ctrl = true, .clkr.hw.init = &gcc_qupv3_wrap0_s2_clk_src_init, }; @@ -544,6 +555,7 @@ static struct clk_rcg2 gcc_qupv3_wrap0_s3_clk_src = { .hid_width = 5, .parent_map = gcc_parent_map_0, .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .hw_clk_ctrl = true, .clkr.hw.init = &gcc_qupv3_wrap0_s3_clk_src_init, }; @@ -561,6 +573,7 @@ static struct clk_rcg2 gcc_qupv3_wrap0_s4_clk_src = { .hid_width = 5, .parent_map = gcc_parent_map_0, .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .hw_clk_ctrl = true, .clkr.hw.init = &gcc_qupv3_wrap0_s4_clk_src_init, }; @@ -590,6 +603,7 @@ static struct clk_rcg2 gcc_qupv3_wrap0_s5_clk_src = { .hid_width = 5, .parent_map = gcc_parent_map_0, .freq_tbl = ftbl_gcc_qupv3_wrap0_s5_clk_src, + .hw_clk_ctrl = true, .clkr.hw.init = &gcc_qupv3_wrap0_s5_clk_src_init, }; @@ -607,6 +621,7 @@ static struct clk_rcg2 gcc_qupv3_wrap0_s6_clk_src = { .hid_width = 5, .parent_map = gcc_parent_map_0, .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .hw_clk_ctrl = true, .clkr.hw.init = &gcc_qupv3_wrap0_s6_clk_src_init, }; @@ -624,6 +639,7 @@ static struct clk_rcg2 gcc_qupv3_wrap0_s7_clk_src = { .hid_width = 5, .parent_map = gcc_parent_map_0, .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .hw_clk_ctrl = true, .clkr.hw.init = &gcc_qupv3_wrap0_s7_clk_src_init, }; @@ -660,6 +676,7 @@ static struct clk_rcg2 gcc_qupv3_wrap1_s0_clk_src = { .hid_width = 5, .parent_map = gcc_parent_map_0, .freq_tbl = ftbl_gcc_qupv3_wrap1_s0_clk_src, + .hw_clk_ctrl = true, .clkr.hw.init = &gcc_qupv3_wrap1_s0_clk_src_init, }; @@ -677,6 +694,7 @@ static struct clk_rcg2 gcc_qupv3_wrap1_s1_clk_src = { .hid_width = 5, .parent_map = gcc_parent_map_0, .freq_tbl = ftbl_gcc_qupv3_wrap1_s0_clk_src, + .hw_clk_ctrl = true, .clkr.hw.init = &gcc_qupv3_wrap1_s1_clk_src_init, }; @@ -694,6 +712,7 @@ static struct clk_rcg2 gcc_qupv3_wrap1_s2_clk_src = { .hid_width = 5, .parent_map = gcc_parent_map_0, .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .hw_clk_ctrl = true, .clkr.hw.init = &gcc_qupv3_wrap1_s2_clk_src_init, }; @@ -711,6 +730,7 @@ static struct clk_rcg2 gcc_qupv3_wrap1_s3_clk_src = { .hid_width = 5, .parent_map = gcc_parent_map_0, .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .hw_clk_ctrl = true, .clkr.hw.init = &gcc_qupv3_wrap1_s3_clk_src_init, }; @@ -728,6 +748,7 @@ static struct clk_rcg2 gcc_qupv3_wrap1_s4_clk_src = { .hid_width = 5, .parent_map = gcc_parent_map_0, .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .hw_clk_ctrl = true, .clkr.hw.init = &gcc_qupv3_wrap1_s4_clk_src_init, }; @@ -745,6 +766,7 @@ static struct clk_rcg2 gcc_qupv3_wrap1_s5_clk_src = { .hid_width = 5, .parent_map = gcc_parent_map_0, .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .hw_clk_ctrl = true, .clkr.hw.init = &gcc_qupv3_wrap1_s5_clk_src_init, }; @@ -762,6 +784,7 @@ static struct clk_rcg2 gcc_qupv3_wrap1_s6_clk_src = { .hid_width = 5, .parent_map = gcc_parent_map_0, .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .hw_clk_ctrl = true, .clkr.hw.init = &gcc_qupv3_wrap1_s6_clk_src_init, }; @@ -779,6 +802,7 @@ static struct clk_rcg2 gcc_qupv3_wrap2_s0_clk_src = { .hid_width = 5, .parent_map = gcc_parent_map_0, .freq_tbl = ftbl_gcc_qupv3_wrap1_s0_clk_src, + .hw_clk_ctrl = true, .clkr.hw.init = &gcc_qupv3_wrap2_s0_clk_src_init, }; @@ -796,6 +820,7 @@ static struct clk_rcg2 gcc_qupv3_wrap2_s1_clk_src = { .hid_width = 5, .parent_map = gcc_parent_map_0, .freq_tbl = ftbl_gcc_qupv3_wrap1_s0_clk_src, + .hw_clk_ctrl = true, .clkr.hw.init = &gcc_qupv3_wrap2_s1_clk_src_init, }; @@ -813,6 +838,7 @@ static struct clk_rcg2 gcc_qupv3_wrap2_s2_clk_src = { .hid_width = 5, .parent_map = gcc_parent_map_0, .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .hw_clk_ctrl = true, .clkr.hw.init = &gcc_qupv3_wrap2_s2_clk_src_init, }; @@ -830,6 +856,7 @@ static struct clk_rcg2 gcc_qupv3_wrap2_s3_clk_src = { .hid_width = 5, .parent_map = gcc_parent_map_0, .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .hw_clk_ctrl = true, .clkr.hw.init = &gcc_qupv3_wrap2_s3_clk_src_init, }; @@ -847,6 +874,7 @@ static struct clk_rcg2 gcc_qupv3_wrap2_s4_clk_src = { .hid_width = 5, .parent_map = gcc_parent_map_0, .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .hw_clk_ctrl = true, .clkr.hw.init = &gcc_qupv3_wrap2_s4_clk_src_init, }; @@ -864,6 +892,7 @@ static struct clk_rcg2 gcc_qupv3_wrap2_s5_clk_src = { .hid_width = 5, .parent_map = gcc_parent_map_0, .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .hw_clk_ctrl = true, .clkr.hw.init = &gcc_qupv3_wrap2_s5_clk_src_init, }; @@ -881,6 +910,7 @@ static struct clk_rcg2 gcc_qupv3_wrap2_s6_clk_src = { .hid_width = 5, .parent_map = gcc_parent_map_0, .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .hw_clk_ctrl = true, .clkr.hw.init = &gcc_qupv3_wrap2_s6_clk_src_init, }; @@ -899,6 +929,7 @@ static struct clk_rcg2 gcc_sdcc2_apps_clk_src = { .hid_width = 5, .parent_map = gcc_parent_map_7, .freq_tbl = ftbl_gcc_sdcc2_apps_clk_src, + .hw_clk_ctrl = true, .clkr.hw.init = &(struct clk_init_data){ .name = "gcc_sdcc2_apps_clk_src", .parent_data = gcc_parent_data_7, @@ -921,6 +952,7 @@ static struct clk_rcg2 gcc_sdcc4_apps_clk_src = { .hid_width = 5, .parent_map = gcc_parent_map_0, .freq_tbl = ftbl_gcc_sdcc4_apps_clk_src, + .hw_clk_ctrl = true, .clkr.hw.init = &(struct clk_init_data){ .name = "gcc_sdcc4_apps_clk_src", .parent_data = gcc_parent_data_0, @@ -944,6 +976,7 @@ static struct clk_rcg2 gcc_ufs_phy_axi_clk_src = { .hid_width = 5, .parent_map = gcc_parent_map_0, .freq_tbl = ftbl_gcc_ufs_phy_axi_clk_src, + .hw_clk_ctrl = true, .clkr.hw.init = &(struct clk_init_data){ .name = "gcc_ufs_phy_axi_clk_src", .parent_data = gcc_parent_data_0, @@ -966,6 +999,7 @@ static struct clk_rcg2 gcc_ufs_phy_ice_core_clk_src = { .hid_width = 5, .parent_map = gcc_parent_map_0, .freq_tbl = ftbl_gcc_ufs_phy_ice_core_clk_src, + .hw_clk_ctrl = true, .clkr.hw.init = &(struct clk_init_data){ .name = "gcc_ufs_phy_ice_core_clk_src", .parent_data = gcc_parent_data_0, @@ -987,6 +1021,7 @@ static struct clk_rcg2 gcc_ufs_phy_phy_aux_clk_src = { .hid_width = 5, .parent_map = gcc_parent_map_3, .freq_tbl = ftbl_gcc_ufs_phy_phy_aux_clk_src, + .hw_clk_ctrl = true, .clkr.hw.init = &(struct clk_init_data){ .name = "gcc_ufs_phy_phy_aux_clk_src", .parent_data = gcc_parent_data_3, @@ -1002,6 +1037,7 @@ static struct clk_rcg2 gcc_ufs_phy_unipro_core_clk_src = { .hid_width = 5, .parent_map = gcc_parent_map_0, .freq_tbl = ftbl_gcc_ufs_phy_ice_core_clk_src, + .hw_clk_ctrl = true, .clkr.hw.init = &(struct clk_init_data){ .name = "gcc_ufs_phy_unipro_core_clk_src", .parent_data = gcc_parent_data_0, @@ -1025,6 +1061,7 @@ static struct clk_rcg2 gcc_usb30_prim_master_clk_src = { .hid_width = 5, .parent_map = gcc_parent_map_0, .freq_tbl = ftbl_gcc_usb30_prim_master_clk_src, + .hw_clk_ctrl = true, .clkr.hw.init = &(struct clk_init_data){ .name = "gcc_usb30_prim_master_clk_src", .parent_data = gcc_parent_data_0, @@ -1040,6 +1077,7 @@ static struct clk_rcg2 gcc_usb30_prim_mock_utmi_clk_src = { .hid_width = 5, .parent_map = gcc_parent_map_0, .freq_tbl = ftbl_gcc_pcie_0_aux_clk_src, + .hw_clk_ctrl = true, .clkr.hw.init = &(struct clk_init_data){ .name = "gcc_usb30_prim_mock_utmi_clk_src", .parent_data = gcc_parent_data_0, @@ -1055,6 +1093,7 @@ static struct clk_rcg2 gcc_usb3_prim_phy_aux_clk_src = { .hid_width = 5, .parent_map = gcc_parent_map_2, .freq_tbl = ftbl_gcc_pcie_0_aux_clk_src, + .hw_clk_ctrl = true, .clkr.hw.init = &(struct clk_init_data){ .name = "gcc_usb3_prim_phy_aux_clk_src", .parent_data = gcc_parent_data_2, diff --git a/drivers/clk/qcom/gpucc-sc8280xp.c b/drivers/clk/qcom/gpucc-sc8280xp.c index ea1e9505c33598f1ee2d1146fbb6c8c167912815..8e147ee294eefcef7e40a53079c1c26b9edff431 100644 --- a/drivers/clk/qcom/gpucc-sc8280xp.c +++ b/drivers/clk/qcom/gpucc-sc8280xp.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -424,10 +425,21 @@ static struct qcom_cc_desc gpu_cc_sc8280xp_desc = { static int gpu_cc_sc8280xp_probe(struct platform_device *pdev) { struct regmap *regmap; + int ret; + + ret = devm_pm_runtime_enable(&pdev->dev); + if (ret) + return ret; + + ret = pm_runtime_resume_and_get(&pdev->dev); + if (ret) + return ret; regmap = qcom_cc_map(pdev, &gpu_cc_sc8280xp_desc); - if (IS_ERR(regmap)) + if (IS_ERR(regmap)) { + pm_runtime_put(&pdev->dev); return PTR_ERR(regmap); + } clk_lucid_pll_configure(&gpu_cc_pll0, regmap, &gpu_cc_pll0_config); clk_lucid_pll_configure(&gpu_cc_pll1, regmap, &gpu_cc_pll1_config); @@ -439,7 +451,10 @@ static int gpu_cc_sc8280xp_probe(struct platform_device *pdev) regmap_update_bits(regmap, 0x1170, BIT(0), BIT(0)); regmap_update_bits(regmap, 0x109c, BIT(0), BIT(0)); - return qcom_cc_really_probe(pdev, &gpu_cc_sc8280xp_desc, regmap); + ret = qcom_cc_really_probe(pdev, &gpu_cc_sc8280xp_desc, regmap); + pm_runtime_put(&pdev->dev); + + return ret; } static const struct of_device_id gpu_cc_sc8280xp_match_table[] = { diff --git a/drivers/clk/qcom/gpucc-sm6375.c b/drivers/clk/qcom/gpucc-sm6375.c index d3620344a00968b9471ef1306f51f275946a6f4f..2d863dc3d83bd9b03ef828f4695c5ff8595ff306 100644 --- a/drivers/clk/qcom/gpucc-sm6375.c +++ b/drivers/clk/qcom/gpucc-sm6375.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -434,15 +435,29 @@ MODULE_DEVICE_TABLE(of, gpucc_sm6375_match_table); static int gpucc_sm6375_probe(struct platform_device *pdev) { struct regmap *regmap; + int ret; + + ret = devm_pm_runtime_enable(&pdev->dev); + if (ret) + return ret; + + ret = pm_runtime_resume_and_get(&pdev->dev); + if (ret) + return ret; regmap = qcom_cc_map(pdev, &gpucc_sm6375_desc); - if (IS_ERR(regmap)) + if (IS_ERR(regmap)) { + pm_runtime_put(&pdev->dev); return PTR_ERR(regmap); + } clk_lucid_pll_configure(&gpucc_pll0, regmap, &gpucc_pll0_config); clk_lucid_pll_configure(&gpucc_pll1, regmap, &gpucc_pll1_config); - return qcom_cc_really_probe(pdev, &gpucc_sm6375_desc, regmap); + ret = qcom_cc_really_probe(pdev, &gpucc_sm6375_desc, regmap); + pm_runtime_put(&pdev->dev); + + return ret; } static struct platform_driver gpucc_sm6375_driver = { diff --git a/drivers/clk/qcom/gpucc-sm8450.c b/drivers/clk/qcom/gpucc-sm8450.c new file mode 100644 index 0000000000000000000000000000000000000000..16c0381b3087d9ed3e5157de1579d6d60da165d1 --- /dev/null +++ b/drivers/clk/qcom/gpucc-sm8450.c @@ -0,0 +1,766 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include + +#include +#include + +#include "clk-alpha-pll.h" +#include "clk-branch.h" +#include "clk-rcg.h" +#include "clk-regmap.h" +#include "clk-regmap-divider.h" +#include "clk-regmap-mux.h" +#include "clk-regmap-phy-mux.h" +#include "gdsc.h" +#include "reset.h" + +enum { + DT_BI_TCXO, + DT_GPLL0_OUT_MAIN, + DT_GPLL0_OUT_MAIN_DIV, +}; + +enum { + P_BI_TCXO, + P_GPLL0_OUT_MAIN, + P_GPLL0_OUT_MAIN_DIV, + P_GPU_CC_PLL0_OUT_MAIN, + P_GPU_CC_PLL1_OUT_MAIN, +}; + +static struct pll_vco lucid_evo_vco[] = { + { 249600000, 2000000000, 0 }, +}; + +static struct alpha_pll_config gpu_cc_pll0_config = { + .l = 0x1d, + .alpha = 0xb000, + .config_ctl_val = 0x20485699, + .config_ctl_hi_val = 0x00182261, + .config_ctl_hi1_val = 0x32aa299c, + .user_ctl_val = 0x00000000, + .user_ctl_hi_val = 0x00000805, +}; + +static struct clk_alpha_pll gpu_cc_pll0 = { + .offset = 0x0, + .vco_table = lucid_evo_vco, + .num_vco = ARRAY_SIZE(lucid_evo_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_EVO], + .clkr = { + .hw.init = &(struct clk_init_data){ + .name = "gpu_cc_pll0", + .parent_data = &(const struct clk_parent_data){ + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_lucid_evo_ops, + }, + }, +}; + +static struct alpha_pll_config gpu_cc_pll1_config = { + .l = 0x34, + .alpha = 0x1555, + .config_ctl_val = 0x20485699, + .config_ctl_hi_val = 0x00182261, + .config_ctl_hi1_val = 0x32aa299c, + .user_ctl_val = 0x00000000, + .user_ctl_hi_val = 0x00000805, +}; + +static struct clk_alpha_pll gpu_cc_pll1 = { + .offset = 0x1000, + .vco_table = lucid_evo_vco, + .num_vco = ARRAY_SIZE(lucid_evo_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_EVO], + .clkr = { + .hw.init = &(struct clk_init_data){ + .name = "gpu_cc_pll1", + .parent_data = &(const struct clk_parent_data){ + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_lucid_evo_ops, + }, + }, +}; + +static const struct parent_map gpu_cc_parent_map_0[] = { + { P_BI_TCXO, 0 }, + { P_GPLL0_OUT_MAIN, 5 }, + { P_GPLL0_OUT_MAIN_DIV, 6 }, +}; + +static const struct clk_parent_data gpu_cc_parent_data_0[] = { + { .index = DT_BI_TCXO }, + { .index = DT_GPLL0_OUT_MAIN }, + { .index = DT_GPLL0_OUT_MAIN_DIV }, +}; + +static const struct parent_map gpu_cc_parent_map_1[] = { + { P_BI_TCXO, 0 }, + { P_GPU_CC_PLL0_OUT_MAIN, 1 }, + { P_GPU_CC_PLL1_OUT_MAIN, 3 }, + { P_GPLL0_OUT_MAIN, 5 }, + { P_GPLL0_OUT_MAIN_DIV, 6 }, +}; + +static const struct clk_parent_data gpu_cc_parent_data_1[] = { + { .index = DT_BI_TCXO }, + { .hw = &gpu_cc_pll0.clkr.hw }, + { .hw = &gpu_cc_pll1.clkr.hw }, + { .index = DT_GPLL0_OUT_MAIN }, + { .index = DT_GPLL0_OUT_MAIN_DIV }, +}; + +static const struct parent_map gpu_cc_parent_map_2[] = { + { P_BI_TCXO, 0 }, + { P_GPU_CC_PLL1_OUT_MAIN, 3 }, + { P_GPLL0_OUT_MAIN, 5 }, + { P_GPLL0_OUT_MAIN_DIV, 6 }, +}; + +static const struct clk_parent_data gpu_cc_parent_data_2[] = { + { .index = DT_BI_TCXO }, + { .hw = &gpu_cc_pll1.clkr.hw }, + { .index = DT_GPLL0_OUT_MAIN }, + { .index = DT_GPLL0_OUT_MAIN_DIV }, +}; + +static const struct parent_map gpu_cc_parent_map_3[] = { + { P_BI_TCXO, 0 }, +}; + +static const struct clk_parent_data gpu_cc_parent_data_3[] = { + { .index = DT_BI_TCXO }, +}; + +static const struct freq_tbl ftbl_gpu_cc_ff_clk_src[] = { + F(200000000, P_GPLL0_OUT_MAIN_DIV, 1.5, 0, 0), + { } +}; + +static struct clk_rcg2 gpu_cc_ff_clk_src = { + .cmd_rcgr = 0x9474, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gpu_cc_parent_map_0, + .freq_tbl = ftbl_gpu_cc_ff_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gpu_cc_ff_clk_src", + .parent_data = gpu_cc_parent_data_0, + .num_parents = ARRAY_SIZE(gpu_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_gpu_cc_gmu_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(200000000, P_GPLL0_OUT_MAIN_DIV, 1.5, 0, 0), + F(500000000, P_GPU_CC_PLL1_OUT_MAIN, 2, 0, 0), + { } +}; + +static struct clk_rcg2 gpu_cc_gmu_clk_src = { + .cmd_rcgr = 0x9318, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gpu_cc_parent_map_1, + .freq_tbl = ftbl_gpu_cc_gmu_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gpu_cc_gmu_clk_src", + .parent_data = gpu_cc_parent_data_1, + .num_parents = ARRAY_SIZE(gpu_cc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_gpu_cc_hub_clk_src[] = { + F(150000000, P_GPLL0_OUT_MAIN_DIV, 2, 0, 0), + F(240000000, P_GPLL0_OUT_MAIN, 2.5, 0, 0), + F(300000000, P_GPLL0_OUT_MAIN, 2, 0, 0), + { } +}; + +static struct clk_rcg2 gpu_cc_hub_clk_src = { + .cmd_rcgr = 0x93ec, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gpu_cc_parent_map_2, + .freq_tbl = ftbl_gpu_cc_hub_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gpu_cc_hub_clk_src", + .parent_data = gpu_cc_parent_data_2, + .num_parents = ARRAY_SIZE(gpu_cc_parent_data_2), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_gpu_cc_xo_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + { } +}; + +static struct clk_rcg2 gpu_cc_xo_clk_src = { + .cmd_rcgr = 0x9010, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gpu_cc_parent_map_3, + .freq_tbl = ftbl_gpu_cc_xo_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gpu_cc_xo_clk_src", + .parent_data = gpu_cc_parent_data_3, + .num_parents = ARRAY_SIZE(gpu_cc_parent_data_3), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_regmap_div gpu_cc_demet_div_clk_src = { + .reg = 0x9054, + .shift = 0, + .width = 4, + .clkr.hw.init = &(struct clk_init_data) { + .name = "gpu_cc_demet_div_clk_src", + .parent_hws = (const struct clk_hw*[]){ + &gpu_cc_xo_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_regmap_div_ro_ops, + }, +}; + +static struct clk_regmap_div gpu_cc_hub_ahb_div_clk_src = { + .reg = 0x9430, + .shift = 0, + .width = 4, + .clkr.hw.init = &(struct clk_init_data) { + .name = "gpu_cc_hub_ahb_div_clk_src", + .parent_hws = (const struct clk_hw*[]){ + &gpu_cc_hub_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_regmap_div_ro_ops, + }, +}; + +static struct clk_regmap_div gpu_cc_hub_cx_int_div_clk_src = { + .reg = 0x942c, + .shift = 0, + .width = 4, + .clkr.hw.init = &(struct clk_init_data) { + .name = "gpu_cc_hub_cx_int_div_clk_src", + .parent_hws = (const struct clk_hw*[]){ + &gpu_cc_hub_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_regmap_div_ro_ops, + }, +}; + +static struct clk_regmap_div gpu_cc_xo_div_clk_src = { + .reg = 0x9050, + .shift = 0, + .width = 4, + .clkr.hw.init = &(struct clk_init_data) { + .name = "gpu_cc_xo_div_clk_src", + .parent_hws = (const struct clk_hw*[]){ + &gpu_cc_xo_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_regmap_div_ro_ops, + }, +}; + +static struct clk_branch gpu_cc_ahb_clk = { + .halt_reg = 0x911c, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x911c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gpu_cc_ahb_clk", + .parent_hws = (const struct clk_hw*[]) { + &gpu_cc_hub_ahb_div_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_crc_ahb_clk = { + .halt_reg = 0x9120, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x9120, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gpu_cc_crc_ahb_clk", + .parent_hws = (const struct clk_hw*[]) { + &gpu_cc_hub_ahb_div_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_cx_apb_clk = { + .halt_reg = 0x912c, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x912c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gpu_cc_cx_apb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_cx_ff_clk = { + .halt_reg = 0x914c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x914c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gpu_cc_cx_ff_clk", + .parent_hws = (const struct clk_hw*[]) { + &gpu_cc_ff_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_cx_gmu_clk = { + .halt_reg = 0x913c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x913c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gpu_cc_cx_gmu_clk", + .parent_hws = (const struct clk_hw*[]) { + &gpu_cc_gmu_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_aon_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_cx_snoc_dvm_clk = { + .halt_reg = 0x9130, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x9130, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gpu_cc_cx_snoc_dvm_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_cxo_aon_clk = { + .halt_reg = 0x9004, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x9004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gpu_cc_cxo_aon_clk", + .parent_hws = (const struct clk_hw*[]) { + &gpu_cc_xo_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_cxo_clk = { + .halt_reg = 0x9144, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x9144, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gpu_cc_cxo_clk", + .parent_hws = (const struct clk_hw*[]) { + &gpu_cc_xo_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_demet_clk = { + .halt_reg = 0x900c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x900c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gpu_cc_demet_clk", + .parent_hws = (const struct clk_hw*[]) { + &gpu_cc_demet_div_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_aon_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_freq_measure_clk = { + .halt_reg = 0x9008, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x9008, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gpu_cc_freq_measure_clk", + .parent_hws = (const struct clk_hw*[]) { + &gpu_cc_xo_div_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_gx_ff_clk = { + .halt_reg = 0x90c0, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x90c0, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gpu_cc_gx_ff_clk", + .parent_hws = (const struct clk_hw*[]) { + &gpu_cc_ff_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_gx_gfx3d_clk = { + .halt_reg = 0x90a8, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x90a8, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gpu_cc_gx_gfx3d_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_gx_gfx3d_rdvm_clk = { + .halt_reg = 0x90c8, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x90c8, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gpu_cc_gx_gfx3d_rdvm_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_gx_gmu_clk = { + .halt_reg = 0x90bc, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x90bc, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gpu_cc_gx_gmu_clk", + .parent_hws = (const struct clk_hw*[]) { + &gpu_cc_gmu_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_gx_vsense_clk = { + .halt_reg = 0x90b0, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x90b0, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gpu_cc_gx_vsense_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_hlos1_vote_gpu_smmu_clk = { + .halt_reg = 0x7000, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x7000, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gpu_cc_hlos1_vote_gpu_smmu_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_hub_aon_clk = { + .halt_reg = 0x93e8, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x93e8, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gpu_cc_hub_aon_clk", + .parent_hws = (const struct clk_hw*[]) { + &gpu_cc_hub_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_aon_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_hub_cx_int_clk = { + .halt_reg = 0x9148, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x9148, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gpu_cc_hub_cx_int_clk", + .parent_hws = (const struct clk_hw*[]) { + &gpu_cc_hub_cx_int_div_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_aon_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_memnoc_gfx_clk = { + .halt_reg = 0x9150, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x9150, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gpu_cc_memnoc_gfx_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_mnd1x_0_gfx3d_clk = { + .halt_reg = 0x9288, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x9288, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gpu_cc_mnd1x_0_gfx3d_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_mnd1x_1_gfx3d_clk = { + .halt_reg = 0x928c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x928c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gpu_cc_mnd1x_1_gfx3d_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_sleep_clk = { + .halt_reg = 0x9134, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x9134, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gpu_cc_sleep_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct gdsc gpu_cx_gdsc = { + .gdscr = 0x9108, + .gds_hw_ctrl = 0x953c, + .clk_dis_wait_val = 8, + .pd = { + .name = "gpu_cx_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .flags = VOTABLE | RETAIN_FF_ENABLE, +}; + +static struct gdsc gpu_gx_gdsc = { + .gdscr = 0x905c, + .clamp_io_ctrl = 0x9504, + .resets = (unsigned int []){ GPUCC_GPU_CC_GX_BCR, + GPUCC_GPU_CC_ACD_BCR, + GPUCC_GPU_CC_GX_ACD_IROOT_BCR }, + .reset_count = 3, + .pd = { + .name = "gpu_gx_gdsc", + .power_on = gdsc_gx_do_nothing_enable, + }, + .pwrsts = PWRSTS_OFF_ON, + .flags = CLAMP_IO | AON_RESET | SW_RESET | POLL_CFG_GDSCR, +}; + +static struct clk_regmap *gpu_cc_sm8450_clocks[] = { + [GPU_CC_AHB_CLK] = &gpu_cc_ahb_clk.clkr, + [GPU_CC_CRC_AHB_CLK] = &gpu_cc_crc_ahb_clk.clkr, + [GPU_CC_CX_APB_CLK] = &gpu_cc_cx_apb_clk.clkr, + [GPU_CC_CX_FF_CLK] = &gpu_cc_cx_ff_clk.clkr, + [GPU_CC_CX_GMU_CLK] = &gpu_cc_cx_gmu_clk.clkr, + [GPU_CC_CX_SNOC_DVM_CLK] = &gpu_cc_cx_snoc_dvm_clk.clkr, + [GPU_CC_CXO_AON_CLK] = &gpu_cc_cxo_aon_clk.clkr, + [GPU_CC_CXO_CLK] = &gpu_cc_cxo_clk.clkr, + [GPU_CC_DEMET_CLK] = &gpu_cc_demet_clk.clkr, + [GPU_CC_DEMET_DIV_CLK_SRC] = &gpu_cc_demet_div_clk_src.clkr, + [GPU_CC_FF_CLK_SRC] = &gpu_cc_ff_clk_src.clkr, + [GPU_CC_FREQ_MEASURE_CLK] = &gpu_cc_freq_measure_clk.clkr, + [GPU_CC_GMU_CLK_SRC] = &gpu_cc_gmu_clk_src.clkr, + [GPU_CC_GX_FF_CLK] = &gpu_cc_gx_ff_clk.clkr, + [GPU_CC_GX_GFX3D_CLK] = &gpu_cc_gx_gfx3d_clk.clkr, + [GPU_CC_GX_GFX3D_RDVM_CLK] = &gpu_cc_gx_gfx3d_rdvm_clk.clkr, + [GPU_CC_GX_GMU_CLK] = &gpu_cc_gx_gmu_clk.clkr, + [GPU_CC_GX_VSENSE_CLK] = &gpu_cc_gx_vsense_clk.clkr, + [GPU_CC_HLOS1_VOTE_GPU_SMMU_CLK] = &gpu_cc_hlos1_vote_gpu_smmu_clk.clkr, + [GPU_CC_HUB_AHB_DIV_CLK_SRC] = &gpu_cc_hub_ahb_div_clk_src.clkr, + [GPU_CC_HUB_AON_CLK] = &gpu_cc_hub_aon_clk.clkr, + [GPU_CC_HUB_CLK_SRC] = &gpu_cc_hub_clk_src.clkr, + [GPU_CC_HUB_CX_INT_CLK] = &gpu_cc_hub_cx_int_clk.clkr, + [GPU_CC_HUB_CX_INT_DIV_CLK_SRC] = &gpu_cc_hub_cx_int_div_clk_src.clkr, + [GPU_CC_MEMNOC_GFX_CLK] = &gpu_cc_memnoc_gfx_clk.clkr, + [GPU_CC_MND1X_0_GFX3D_CLK] = &gpu_cc_mnd1x_0_gfx3d_clk.clkr, + [GPU_CC_MND1X_1_GFX3D_CLK] = &gpu_cc_mnd1x_1_gfx3d_clk.clkr, + [GPU_CC_PLL0] = &gpu_cc_pll0.clkr, + [GPU_CC_PLL1] = &gpu_cc_pll1.clkr, + [GPU_CC_SLEEP_CLK] = &gpu_cc_sleep_clk.clkr, + [GPU_CC_XO_CLK_SRC] = &gpu_cc_xo_clk_src.clkr, + [GPU_CC_XO_DIV_CLK_SRC] = &gpu_cc_xo_div_clk_src.clkr, +}; + +static const struct qcom_reset_map gpu_cc_sm8450_resets[] = { + [GPUCC_GPU_CC_XO_BCR] = { 0x9000 }, + [GPUCC_GPU_CC_GX_BCR] = { 0x9058 }, + [GPUCC_GPU_CC_CX_BCR] = { 0x9104 }, + [GPUCC_GPU_CC_GFX3D_AON_BCR] = { 0x9198 }, + [GPUCC_GPU_CC_ACD_BCR] = { 0x9358 }, + [GPUCC_GPU_CC_FAST_HUB_BCR] = { 0x93e4 }, + [GPUCC_GPU_CC_FF_BCR] = { 0x9470 }, + [GPUCC_GPU_CC_GMU_BCR] = { 0x9314 }, + [GPUCC_GPU_CC_GX_ACD_IROOT_BCR] = { 0x958c }, +}; + +static struct gdsc *gpu_cc_sm8450_gdscs[] = { + [GPU_CX_GDSC] = &gpu_cx_gdsc, + [GPU_GX_GDSC] = &gpu_gx_gdsc, +}; + +static const struct regmap_config gpu_cc_sm8450_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0xa000, + .fast_io = true, +}; + +static const struct qcom_cc_desc gpu_cc_sm8450_desc = { + .config = &gpu_cc_sm8450_regmap_config, + .clks = gpu_cc_sm8450_clocks, + .num_clks = ARRAY_SIZE(gpu_cc_sm8450_clocks), + .resets = gpu_cc_sm8450_resets, + .num_resets = ARRAY_SIZE(gpu_cc_sm8450_resets), + .gdscs = gpu_cc_sm8450_gdscs, + .num_gdscs = ARRAY_SIZE(gpu_cc_sm8450_gdscs), +}; + +static const struct of_device_id gpu_cc_sm8450_match_table[] = { + { .compatible = "qcom,sm8450-gpucc" }, + { } +}; +MODULE_DEVICE_TABLE(of, gpu_cc_sm8450_match_table); + +static int gpu_cc_sm8450_probe(struct platform_device *pdev) +{ + struct regmap *regmap; + + regmap = qcom_cc_map(pdev, &gpu_cc_sm8450_desc); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + + clk_lucid_evo_pll_configure(&gpu_cc_pll0, regmap, &gpu_cc_pll0_config); + clk_lucid_evo_pll_configure(&gpu_cc_pll1, regmap, &gpu_cc_pll1_config); + + return qcom_cc_really_probe(pdev, &gpu_cc_sm8450_desc, regmap); +} + +static struct platform_driver gpu_cc_sm8450_driver = { + .probe = gpu_cc_sm8450_probe, + .driver = { + .name = "sm8450-gpucc", + .of_match_table = gpu_cc_sm8450_match_table, + }, +}; +module_platform_driver(gpu_cc_sm8450_driver); + +MODULE_DESCRIPTION("QTI GPU_CC SM8450 Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/qcom/gpucc-sm8550.c b/drivers/clk/qcom/gpucc-sm8550.c new file mode 100644 index 0000000000000000000000000000000000000000..8a2e3522af5127f18eba5bc4acf17de9112a86f7 --- /dev/null +++ b/drivers/clk/qcom/gpucc-sm8550.c @@ -0,0 +1,611 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2023, Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#include +#include +#include +#include + +#include + +#include "clk-alpha-pll.h" +#include "clk-branch.h" +#include "clk-rcg.h" +#include "clk-regmap.h" +#include "clk-regmap-divider.h" +#include "common.h" +#include "gdsc.h" +#include "reset.h" + +enum { + DT_BI_TCXO, + DT_GPLL0_OUT_MAIN, + DT_GPLL0_OUT_MAIN_DIV, +}; + +enum { + P_BI_TCXO, + P_GPLL0_OUT_MAIN, + P_GPLL0_OUT_MAIN_DIV, + P_GPU_CC_PLL0_OUT_MAIN, + P_GPU_CC_PLL1_OUT_MAIN, +}; + +static const struct pll_vco lucid_ole_vco[] = { + { 249600000, 2300000000, 0 }, +}; + +static const struct alpha_pll_config gpu_cc_pll0_config = { + /* .l includes RINGOSC_CAL_L_VAL, CAL_L_VAL, L_VAL fields */ + .l = 0x4444000d, + .alpha = 0x0, + .config_ctl_val = 0x20485699, + .config_ctl_hi_val = 0x00182261, + .config_ctl_hi1_val = 0x82aa299c, + .test_ctl_val = 0x00000000, + .test_ctl_hi_val = 0x00000003, + .test_ctl_hi1_val = 0x00009000, + .test_ctl_hi2_val = 0x00000034, + .user_ctl_val = 0x00000000, + .user_ctl_hi_val = 0x00000005, +}; + +static struct clk_alpha_pll gpu_cc_pll0 = { + .offset = 0x0, + .vco_table = lucid_ole_vco, + .num_vco = ARRAY_SIZE(lucid_ole_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE], + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "gpu_cc_pll0", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_lucid_evo_ops, + }, + }, +}; + +static const struct alpha_pll_config gpu_cc_pll1_config = { + /* .l includes RINGOSC_CAL_L_VAL, CAL_L_VAL, L_VAL fields */ + .l = 0x44440016, + .alpha = 0xeaaa, + .config_ctl_val = 0x20485699, + .config_ctl_hi_val = 0x00182261, + .config_ctl_hi1_val = 0x82aa299c, + .test_ctl_val = 0x00000000, + .test_ctl_hi_val = 0x00000003, + .test_ctl_hi1_val = 0x00009000, + .test_ctl_hi2_val = 0x00000034, + .user_ctl_val = 0x00000000, + .user_ctl_hi_val = 0x00000005, +}; + +static struct clk_alpha_pll gpu_cc_pll1 = { + .offset = 0x1000, + .vco_table = lucid_ole_vco, + .num_vco = ARRAY_SIZE(lucid_ole_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE], + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "gpu_cc_pll1", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_lucid_evo_ops, + }, + }, +}; + +static const struct parent_map gpu_cc_parent_map_0[] = { + { P_BI_TCXO, 0 }, + { P_GPLL0_OUT_MAIN, 5 }, + { P_GPLL0_OUT_MAIN_DIV, 6 }, +}; + +static const struct clk_parent_data gpu_cc_parent_data_0[] = { + { .index = DT_BI_TCXO }, + { .index = DT_GPLL0_OUT_MAIN }, + { .index = DT_GPLL0_OUT_MAIN_DIV }, +}; + +static const struct parent_map gpu_cc_parent_map_1[] = { + { P_BI_TCXO, 0 }, + { P_GPU_CC_PLL0_OUT_MAIN, 1 }, + { P_GPU_CC_PLL1_OUT_MAIN, 3 }, + { P_GPLL0_OUT_MAIN, 5 }, + { P_GPLL0_OUT_MAIN_DIV, 6 }, +}; + +static const struct clk_parent_data gpu_cc_parent_data_1[] = { + { .index = DT_BI_TCXO }, + { .hw = &gpu_cc_pll0.clkr.hw }, + { .hw = &gpu_cc_pll1.clkr.hw }, + { .index = DT_GPLL0_OUT_MAIN }, + { .index = DT_GPLL0_OUT_MAIN_DIV }, +}; + +static const struct parent_map gpu_cc_parent_map_2[] = { + { P_BI_TCXO, 0 }, + { P_GPU_CC_PLL1_OUT_MAIN, 3 }, + { P_GPLL0_OUT_MAIN, 5 }, + { P_GPLL0_OUT_MAIN_DIV, 6 }, +}; + +static const struct clk_parent_data gpu_cc_parent_data_2[] = { + { .index = DT_BI_TCXO }, + { .hw = &gpu_cc_pll1.clkr.hw }, + { .index = DT_GPLL0_OUT_MAIN }, + { .index = DT_GPLL0_OUT_MAIN_DIV }, +}; + +static const struct parent_map gpu_cc_parent_map_3[] = { + { P_BI_TCXO, 0 }, +}; + +static const struct clk_parent_data gpu_cc_parent_data_3[] = { + { .index = DT_BI_TCXO }, +}; + +static const struct freq_tbl ftbl_gpu_cc_ff_clk_src[] = { + F(200000000, P_GPLL0_OUT_MAIN, 3, 0, 0), + { } +}; + +static struct clk_rcg2 gpu_cc_ff_clk_src = { + .cmd_rcgr = 0x9474, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gpu_cc_parent_map_0, + .freq_tbl = ftbl_gpu_cc_ff_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gpu_cc_ff_clk_src", + .parent_data = gpu_cc_parent_data_0, + .num_parents = ARRAY_SIZE(gpu_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_gpu_cc_gmu_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(220000000, P_GPU_CC_PLL1_OUT_MAIN, 2, 0, 0), + F(550000000, P_GPU_CC_PLL1_OUT_MAIN, 2, 0, 0), + { } +}; + +static struct clk_rcg2 gpu_cc_gmu_clk_src = { + .cmd_rcgr = 0x9318, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gpu_cc_parent_map_1, + .freq_tbl = ftbl_gpu_cc_gmu_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gpu_cc_gmu_clk_src", + .parent_data = gpu_cc_parent_data_1, + .num_parents = ARRAY_SIZE(gpu_cc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_gpu_cc_hub_clk_src[] = { + F(200000000, P_GPLL0_OUT_MAIN, 3, 0, 0), + F(300000000, P_GPLL0_OUT_MAIN, 2, 0, 0), + F(400000000, P_GPLL0_OUT_MAIN, 1.5, 0, 0), + { } +}; + +static struct clk_rcg2 gpu_cc_hub_clk_src = { + .cmd_rcgr = 0x93ec, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gpu_cc_parent_map_2, + .freq_tbl = ftbl_gpu_cc_hub_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gpu_cc_hub_clk_src", + .parent_data = gpu_cc_parent_data_2, + .num_parents = ARRAY_SIZE(gpu_cc_parent_data_2), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_gpu_cc_xo_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + { } +}; + +static struct clk_rcg2 gpu_cc_xo_clk_src = { + .cmd_rcgr = 0x9010, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gpu_cc_parent_map_3, + .freq_tbl = ftbl_gpu_cc_xo_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gpu_cc_xo_clk_src", + .parent_data = gpu_cc_parent_data_3, + .num_parents = ARRAY_SIZE(gpu_cc_parent_data_3), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_regmap_div gpu_cc_demet_div_clk_src = { + .reg = 0x9054, + .shift = 0, + .width = 4, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gpu_cc_demet_div_clk_src", + .parent_hws = (const struct clk_hw*[]) { + &gpu_cc_xo_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_regmap_div_ro_ops, + }, +}; + +static struct clk_regmap_div gpu_cc_xo_div_clk_src = { + .reg = 0x9050, + .shift = 0, + .width = 4, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gpu_cc_xo_div_clk_src", + .parent_hws = (const struct clk_hw*[]) { + &gpu_cc_xo_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_regmap_div_ro_ops, + }, +}; + +static struct clk_branch gpu_cc_ahb_clk = { + .halt_reg = 0x911c, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x911c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gpu_cc_ahb_clk", + .parent_hws = (const struct clk_hw*[]) { + &gpu_cc_hub_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_crc_ahb_clk = { + .halt_reg = 0x9120, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x9120, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gpu_cc_crc_ahb_clk", + .parent_hws = (const struct clk_hw*[]) { + &gpu_cc_hub_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_cx_ff_clk = { + .halt_reg = 0x914c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x914c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gpu_cc_cx_ff_clk", + .parent_hws = (const struct clk_hw*[]) { + &gpu_cc_ff_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_cx_gmu_clk = { + .halt_reg = 0x913c, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x913c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gpu_cc_cx_gmu_clk", + .parent_hws = (const struct clk_hw*[]) { + &gpu_cc_gmu_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_aon_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_cxo_clk = { + .halt_reg = 0x9144, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x9144, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gpu_cc_cxo_clk", + .parent_hws = (const struct clk_hw*[]) { + &gpu_cc_xo_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_freq_measure_clk = { + .halt_reg = 0x9008, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x9008, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gpu_cc_freq_measure_clk", + .parent_hws = (const struct clk_hw*[]) { + &gpu_cc_xo_div_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_hlos1_vote_gpu_smmu_clk = { + .halt_reg = 0x7000, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x7000, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gpu_cc_hlos1_vote_gpu_smmu_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_hub_aon_clk = { + .halt_reg = 0x93e8, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x93e8, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gpu_cc_hub_aon_clk", + .parent_hws = (const struct clk_hw*[]) { + &gpu_cc_hub_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_aon_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_hub_cx_int_clk = { + .halt_reg = 0x9148, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x9148, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gpu_cc_hub_cx_int_clk", + .parent_hws = (const struct clk_hw*[]) { + &gpu_cc_hub_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_aon_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_memnoc_gfx_clk = { + .halt_reg = 0x9150, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x9150, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gpu_cc_memnoc_gfx_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_mnd1x_0_gfx3d_clk = { + .halt_reg = 0x9288, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x9288, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gpu_cc_mnd1x_0_gfx3d_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_mnd1x_1_gfx3d_clk = { + .halt_reg = 0x928c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x928c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gpu_cc_mnd1x_1_gfx3d_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_sleep_clk = { + .halt_reg = 0x9134, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x9134, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gpu_cc_sleep_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct gdsc gpu_cc_cx_gdsc = { + .gdscr = 0x9108, + .gds_hw_ctrl = 0x953c, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0xf, + .pd = { + .name = "gpu_cc_cx_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .flags = RETAIN_FF_ENABLE | VOTABLE, +}; + +static struct gdsc gpu_cc_gx_gdsc = { + .gdscr = 0x905c, + .clamp_io_ctrl = 0x9504, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0xf, + .pd = { + .name = "gpu_cc_gx_gdsc", + .power_on = gdsc_gx_do_nothing_enable, + }, + .pwrsts = PWRSTS_OFF_ON, + .flags = CLAMP_IO | POLL_CFG_GDSCR | RETAIN_FF_ENABLE, +}; + +static struct clk_regmap *gpu_cc_sm8550_clocks[] = { + [GPU_CC_AHB_CLK] = &gpu_cc_ahb_clk.clkr, + [GPU_CC_CRC_AHB_CLK] = &gpu_cc_crc_ahb_clk.clkr, + [GPU_CC_CX_FF_CLK] = &gpu_cc_cx_ff_clk.clkr, + [GPU_CC_CX_GMU_CLK] = &gpu_cc_cx_gmu_clk.clkr, + [GPU_CC_CXO_CLK] = &gpu_cc_cxo_clk.clkr, + [GPU_CC_DEMET_DIV_CLK_SRC] = &gpu_cc_demet_div_clk_src.clkr, + [GPU_CC_FF_CLK_SRC] = &gpu_cc_ff_clk_src.clkr, + [GPU_CC_FREQ_MEASURE_CLK] = &gpu_cc_freq_measure_clk.clkr, + [GPU_CC_GMU_CLK_SRC] = &gpu_cc_gmu_clk_src.clkr, + [GPU_CC_HLOS1_VOTE_GPU_SMMU_CLK] = &gpu_cc_hlos1_vote_gpu_smmu_clk.clkr, + [GPU_CC_HUB_AON_CLK] = &gpu_cc_hub_aon_clk.clkr, + [GPU_CC_HUB_CLK_SRC] = &gpu_cc_hub_clk_src.clkr, + [GPU_CC_HUB_CX_INT_CLK] = &gpu_cc_hub_cx_int_clk.clkr, + [GPU_CC_MEMNOC_GFX_CLK] = &gpu_cc_memnoc_gfx_clk.clkr, + [GPU_CC_MND1X_0_GFX3D_CLK] = &gpu_cc_mnd1x_0_gfx3d_clk.clkr, + [GPU_CC_MND1X_1_GFX3D_CLK] = &gpu_cc_mnd1x_1_gfx3d_clk.clkr, + [GPU_CC_PLL0] = &gpu_cc_pll0.clkr, + [GPU_CC_PLL1] = &gpu_cc_pll1.clkr, + [GPU_CC_SLEEP_CLK] = &gpu_cc_sleep_clk.clkr, + [GPU_CC_XO_CLK_SRC] = &gpu_cc_xo_clk_src.clkr, + [GPU_CC_XO_DIV_CLK_SRC] = &gpu_cc_xo_div_clk_src.clkr, +}; + +static struct gdsc *gpu_cc_sm8550_gdscs[] = { + [GPU_CC_CX_GDSC] = &gpu_cc_cx_gdsc, + [GPU_CC_GX_GDSC] = &gpu_cc_gx_gdsc, +}; + +static const struct qcom_reset_map gpu_cc_sm8550_resets[] = { + [GPUCC_GPU_CC_ACD_BCR] = { 0x9358 }, + [GPUCC_GPU_CC_CX_BCR] = { 0x9104 }, + [GPUCC_GPU_CC_FAST_HUB_BCR] = { 0x93e4 }, + [GPUCC_GPU_CC_FF_BCR] = { 0x9470 }, + [GPUCC_GPU_CC_GFX3D_AON_BCR] = { 0x9198 }, + [GPUCC_GPU_CC_GMU_BCR] = { 0x9314 }, + [GPUCC_GPU_CC_GX_BCR] = { 0x9058 }, + [GPUCC_GPU_CC_XO_BCR] = { 0x9000 }, +}; + +static const struct regmap_config gpu_cc_sm8550_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0x9988, + .fast_io = true, +}; + +static const struct qcom_cc_desc gpu_cc_sm8550_desc = { + .config = &gpu_cc_sm8550_regmap_config, + .clks = gpu_cc_sm8550_clocks, + .num_clks = ARRAY_SIZE(gpu_cc_sm8550_clocks), + .resets = gpu_cc_sm8550_resets, + .num_resets = ARRAY_SIZE(gpu_cc_sm8550_resets), + .gdscs = gpu_cc_sm8550_gdscs, + .num_gdscs = ARRAY_SIZE(gpu_cc_sm8550_gdscs), +}; + +static const struct of_device_id gpu_cc_sm8550_match_table[] = { + { .compatible = "qcom,sm8550-gpucc" }, + { } +}; +MODULE_DEVICE_TABLE(of, gpu_cc_sm8550_match_table); + +static int gpu_cc_sm8550_probe(struct platform_device *pdev) +{ + struct regmap *regmap; + + regmap = qcom_cc_map(pdev, &gpu_cc_sm8550_desc); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + + clk_lucid_evo_pll_configure(&gpu_cc_pll0, regmap, &gpu_cc_pll0_config); + clk_lucid_evo_pll_configure(&gpu_cc_pll1, regmap, &gpu_cc_pll1_config); + + /* + * Keep clocks always enabled: + * gpu_cc_cxo_aon_clk + * gpu_cc_demet_clk + */ + regmap_update_bits(regmap, 0x9004, BIT(0), BIT(0)); + regmap_update_bits(regmap, 0x900c, BIT(0), BIT(0)); + + return qcom_cc_really_probe(pdev, &gpu_cc_sm8550_desc, regmap); +} + +static struct platform_driver gpu_cc_sm8550_driver = { + .probe = gpu_cc_sm8550_probe, + .driver = { + .name = "gpu_cc-sm8550", + .of_match_table = gpu_cc_sm8550_match_table, + }, +}; + +static int __init gpu_cc_sm8550_init(void) +{ + return platform_driver_register(&gpu_cc_sm8550_driver); +} +subsys_initcall(gpu_cc_sm8550_init); + +static void __exit gpu_cc_sm8550_exit(void) +{ + platform_driver_unregister(&gpu_cc_sm8550_driver); +} +module_exit(gpu_cc_sm8550_exit); + +MODULE_DESCRIPTION("QTI GPUCC SM8550 Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/qcom/lpasscc-sc8280xp.c b/drivers/clk/qcom/lpasscc-sc8280xp.c new file mode 100644 index 0000000000000000000000000000000000000000..43b37ce397cf444ca9f193fdf6101c91a96c9f47 --- /dev/null +++ b/drivers/clk/qcom/lpasscc-sc8280xp.c @@ -0,0 +1,87 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2022, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include + +#include + +#include "common.h" +#include "reset.h" + +static const struct qcom_reset_map lpass_audiocc_sc8280xp_resets[] = { + [LPASS_AUDIO_SWR_RX_CGCR] = { 0xa0, 1 }, + [LPASS_AUDIO_SWR_WSA_CGCR] = { 0xb0, 1 }, + [LPASS_AUDIO_SWR_WSA2_CGCR] = { 0xd8, 1 }, +}; + +static struct regmap_config lpass_audiocc_sc8280xp_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .name = "lpass-audio-csr", + .max_register = 0x1000, +}; + +static const struct qcom_cc_desc lpass_audiocc_sc8280xp_reset_desc = { + .config = &lpass_audiocc_sc8280xp_regmap_config, + .resets = lpass_audiocc_sc8280xp_resets, + .num_resets = ARRAY_SIZE(lpass_audiocc_sc8280xp_resets), +}; + +static const struct qcom_reset_map lpasscc_sc8280xp_resets[] = { + [LPASS_AUDIO_SWR_TX_CGCR] = { 0xc010, 1 }, +}; + +static struct regmap_config lpasscc_sc8280xp_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .name = "lpass-tcsr", + .max_register = 0x12000, +}; + +static const struct qcom_cc_desc lpasscc_sc8280xp_reset_desc = { + .config = &lpasscc_sc8280xp_regmap_config, + .resets = lpasscc_sc8280xp_resets, + .num_resets = ARRAY_SIZE(lpasscc_sc8280xp_resets), +}; + +static const struct of_device_id lpasscc_sc8280xp_match_table[] = { + { + .compatible = "qcom,sc8280xp-lpassaudiocc", + .data = &lpass_audiocc_sc8280xp_reset_desc, + }, { + .compatible = "qcom,sc8280xp-lpasscc", + .data = &lpasscc_sc8280xp_reset_desc, + }, + { } +}; +MODULE_DEVICE_TABLE(of, lpasscc_sc8280xp_match_table); + +static int lpasscc_sc8280xp_probe(struct platform_device *pdev) +{ + const struct qcom_cc_desc *desc = of_device_get_match_data(&pdev->dev); + + return qcom_cc_probe_by_index(pdev, 0, desc); +} + +static struct platform_driver lpasscc_sc8280xp_driver = { + .probe = lpasscc_sc8280xp_probe, + .driver = { + .name = "lpasscc-sc8280xp", + .of_match_table = lpasscc_sc8280xp_match_table, + }, +}; + +module_platform_driver(lpasscc_sc8280xp_driver); + +MODULE_AUTHOR("Srinivas Kandagatla "); +MODULE_DESCRIPTION("QTI LPASSCC SC8280XP Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/qcom/mmcc-msm8974.c b/drivers/clk/qcom/mmcc-msm8974.c index 4273fce9a4a4c55ba5f1096f7334f64cc05d9a34..82f6bad144a9a41c4051cdb54dcf8a3e7416b57d 100644 --- a/drivers/clk/qcom/mmcc-msm8974.c +++ b/drivers/clk/qcom/mmcc-msm8974.c @@ -485,7 +485,7 @@ static struct clk_rcg2 mdp_clk_src = { .name = "mdp_clk_src", .parent_data = mmcc_xo_mmpll0_dsi_hdmi_gpll0, .num_parents = ARRAY_SIZE(mmcc_xo_mmpll0_dsi_hdmi_gpll0), - .ops = &clk_rcg2_ops, + .ops = &clk_rcg2_shared_ops, }, }; @@ -2204,23 +2204,6 @@ static struct clk_branch ocmemcx_ocmemnoc_clk = { }, }; -static struct clk_branch oxili_ocmemgx_clk = { - .halt_reg = 0x402c, - .clkr = { - .enable_reg = 0x402c, - .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data){ - .name = "oxili_ocmemgx_clk", - .parent_data = (const struct clk_parent_data[]){ - { .fw_name = "gfx3d_clk_src", .name = "gfx3d_clk_src" }, - }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, - .ops = &clk_branch2_ops, - }, - }, -}; - static struct clk_branch ocmemnoc_clk = { .halt_reg = 0x50b4, .clkr = { @@ -2401,7 +2384,7 @@ static struct gdsc mdss_gdsc = { .pd = { .name = "mdss", }, - .pwrsts = PWRSTS_RET_ON, + .pwrsts = PWRSTS_OFF_ON, }; static struct gdsc camss_jpeg_gdsc = { @@ -2512,7 +2495,6 @@ static struct clk_regmap *mmcc_msm8226_clocks[] = { [MMSS_MMSSNOC_AXI_CLK] = &mmss_mmssnoc_axi_clk.clkr, [MMSS_S0_AXI_CLK] = &mmss_s0_axi_clk.clkr, [OCMEMCX_AHB_CLK] = &ocmemcx_ahb_clk.clkr, - [OXILI_OCMEMGX_CLK] = &oxili_ocmemgx_clk.clkr, [OXILI_GFX3D_CLK] = &oxili_gfx3d_clk.clkr, [OXILICX_AHB_CLK] = &oxilicx_ahb_clk.clkr, [OXILICX_AXI_CLK] = &oxilicx_axi_clk.clkr, @@ -2670,7 +2652,6 @@ static struct clk_regmap *mmcc_msm8974_clocks[] = { [MMSS_S0_AXI_CLK] = &mmss_s0_axi_clk.clkr, [OCMEMCX_AHB_CLK] = &ocmemcx_ahb_clk.clkr, [OCMEMCX_OCMEMNOC_CLK] = &ocmemcx_ocmemnoc_clk.clkr, - [OXILI_OCMEMGX_CLK] = &oxili_ocmemgx_clk.clkr, [OCMEMNOC_CLK] = &ocmemnoc_clk.clkr, [OXILI_GFX3D_CLK] = &oxili_gfx3d_clk.clkr, [OXILICX_AHB_CLK] = &oxilicx_ahb_clk.clkr, diff --git a/drivers/clk/qcom/videocc-sm8350.c b/drivers/clk/qcom/videocc-sm8350.c new file mode 100644 index 0000000000000000000000000000000000000000..b148877fc73defe162ca770a26246a53213d815a --- /dev/null +++ b/drivers/clk/qcom/videocc-sm8350.c @@ -0,0 +1,552 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2023, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "clk-alpha-pll.h" +#include "clk-branch.h" +#include "clk-rcg.h" +#include "clk-regmap.h" +#include "clk-regmap-divider.h" +#include "common.h" +#include "reset.h" +#include "gdsc.h" + +enum { + DT_BI_TCXO, + DT_BI_TCXO_AO, + DT_SLEEP_CLK, +}; + +enum { + P_BI_TCXO, + P_BI_TCXO_AO, + P_SLEEP_CLK, + P_VIDEO_PLL0_OUT_MAIN, + P_VIDEO_PLL1_OUT_MAIN, +}; + +static const struct pll_vco lucid_5lpe_vco[] = { + { 249600000, 1750000000, 0 }, +}; + +static const struct alpha_pll_config video_pll0_config = { + .l = 0x25, + .alpha = 0x8000, + .config_ctl_val = 0x20485699, + .config_ctl_hi_val = 0x00002261, + .config_ctl_hi1_val = 0x2a9a699c, + .test_ctl_val = 0x00000000, + .test_ctl_hi_val = 0x00000000, + .test_ctl_hi1_val = 0x01800000, + .user_ctl_val = 0x00000000, + .user_ctl_hi_val = 0x00000805, + .user_ctl_hi1_val = 0x00000000, +}; + +static struct clk_alpha_pll video_pll0 = { + .offset = 0x42c, + .vco_table = lucid_5lpe_vco, + .num_vco = ARRAY_SIZE(lucid_5lpe_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID], + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "video_pll0", + .parent_data = &(const struct clk_parent_data){ + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_lucid_5lpe_ops, + }, + }, +}; + +static const struct alpha_pll_config video_pll1_config = { + .l = 0x2b, + .alpha = 0xc000, + .config_ctl_val = 0x20485699, + .config_ctl_hi_val = 0x00002261, + .config_ctl_hi1_val = 0x2a9a699c, + .test_ctl_val = 0x00000000, + .test_ctl_hi_val = 0x00000000, + .test_ctl_hi1_val = 0x01800000, + .user_ctl_val = 0x00000000, + .user_ctl_hi_val = 0x00000805, + .user_ctl_hi1_val = 0x00000000, +}; + +static struct clk_alpha_pll video_pll1 = { + .offset = 0x7d0, + .vco_table = lucid_5lpe_vco, + .num_vco = ARRAY_SIZE(lucid_5lpe_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID], + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "video_pll1", + .parent_data = &(const struct clk_parent_data){ + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_lucid_5lpe_ops, + }, + }, +}; + +static const struct parent_map video_cc_parent_map_0[] = { + { P_BI_TCXO_AO, 0 }, +}; + +static const struct clk_parent_data video_cc_parent_data_0[] = { + { .index = DT_BI_TCXO_AO }, +}; + +static const struct parent_map video_cc_parent_map_1[] = { + { P_BI_TCXO, 0 }, + { P_VIDEO_PLL0_OUT_MAIN, 1 }, +}; + +static const struct clk_parent_data video_cc_parent_data_1[] = { + { .index = DT_BI_TCXO }, + { .hw = &video_pll0.clkr.hw }, +}; + +static const struct parent_map video_cc_parent_map_2[] = { + { P_BI_TCXO, 0 }, + { P_VIDEO_PLL1_OUT_MAIN, 1 }, +}; + +static const struct clk_parent_data video_cc_parent_data_2[] = { + { .index = DT_BI_TCXO }, + { .hw = &video_pll1.clkr.hw }, +}; + +static const struct freq_tbl ftbl_video_cc_ahb_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + { } +}; + +static struct clk_rcg2 video_cc_ahb_clk_src = { + .cmd_rcgr = 0xbd4, + .mnd_width = 0, + .hid_width = 5, + .parent_map = video_cc_parent_map_0, + .freq_tbl = ftbl_video_cc_ahb_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "video_cc_ahb_clk_src", + .parent_data = video_cc_parent_data_0, + .num_parents = ARRAY_SIZE(video_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_video_cc_mvs0_clk_src[] = { + F(720000000, P_VIDEO_PLL0_OUT_MAIN, 1, 0, 0), + F(1014000000, P_VIDEO_PLL0_OUT_MAIN, 1, 0, 0), + F(1098000000, P_VIDEO_PLL0_OUT_MAIN, 1, 0, 0), + F(1332000000, P_VIDEO_PLL0_OUT_MAIN, 1, 0, 0), + { } +}; + +static struct clk_rcg2 video_cc_mvs0_clk_src = { + .cmd_rcgr = 0xb94, + .mnd_width = 0, + .hid_width = 5, + .parent_map = video_cc_parent_map_1, + .freq_tbl = ftbl_video_cc_mvs0_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "video_cc_mvs0_clk_src", + .parent_data = video_cc_parent_data_1, + .num_parents = ARRAY_SIZE(video_cc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_video_cc_mvs1_clk_src[] = { + F(840000000, P_VIDEO_PLL1_OUT_MAIN, 1, 0, 0), + F(1098000000, P_VIDEO_PLL1_OUT_MAIN, 1, 0, 0), + F(1332000000, P_VIDEO_PLL1_OUT_MAIN, 1, 0, 0), + { } +}; + +static struct clk_rcg2 video_cc_mvs1_clk_src = { + .cmd_rcgr = 0xbb4, + .mnd_width = 0, + .hid_width = 5, + .parent_map = video_cc_parent_map_2, + .freq_tbl = ftbl_video_cc_mvs1_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "video_cc_mvs1_clk_src", + .parent_data = video_cc_parent_data_2, + .num_parents = ARRAY_SIZE(video_cc_parent_data_2), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_video_cc_sleep_clk_src[] = { + F(32000, P_SLEEP_CLK, 1, 0, 0), + { } +}; + +static struct clk_rcg2 video_cc_sleep_clk_src = { + .cmd_rcgr = 0xef0, + .mnd_width = 0, + .hid_width = 5, + .freq_tbl = ftbl_video_cc_sleep_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "video_cc_sleep_clk_src", + .parent_data = &(const struct clk_parent_data){ + .index = DT_SLEEP_CLK, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 video_cc_xo_clk_src = { + .cmd_rcgr = 0xecc, + .mnd_width = 0, + .hid_width = 5, + .parent_map = video_cc_parent_map_0, + .freq_tbl = ftbl_video_cc_ahb_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "video_cc_xo_clk_src", + .parent_data = video_cc_parent_data_0, + .num_parents = ARRAY_SIZE(video_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_regmap_div video_cc_mvs0_div_clk_src = { + .reg = 0xd54, + .shift = 0, + .width = 4, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "video_cc_mvs0_div_clk_src", + .parent_hws = (const struct clk_hw*[]){ + &video_cc_mvs0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_regmap_div_ro_ops, + }, +}; + +static struct clk_regmap_div video_cc_mvs0c_div2_div_clk_src = { + .reg = 0xc54, + .shift = 0, + .width = 4, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "video_cc_mvs0c_div2_div_clk_src", + .parent_hws = (const struct clk_hw*[]){ + &video_cc_mvs0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_regmap_div_ro_ops, + }, +}; + +static struct clk_regmap_div video_cc_mvs1_div_clk_src = { + .reg = 0xdd4, + .shift = 0, + .width = 4, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "video_cc_mvs1_div_clk_src", + .parent_hws = (const struct clk_hw*[]){ + &video_cc_mvs1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_regmap_div_ro_ops, + }, +}; + +static struct clk_regmap_div video_cc_mvs1c_div2_div_clk_src = { + .reg = 0xcf4, + .shift = 0, + .width = 4, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "video_cc_mvs1c_div2_div_clk_src", + .parent_hws = (const struct clk_hw*[]){ + &video_cc_mvs1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_regmap_div_ro_ops, + }, +}; + +static struct clk_branch video_cc_mvs0_clk = { + .halt_reg = 0xd34, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0xd34, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0xd34, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "video_cc_mvs0_clk", + .parent_hws = (const struct clk_hw*[]){ + &video_cc_mvs0_div_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch video_cc_mvs0c_clk = { + .halt_reg = 0xc34, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xc34, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "video_cc_mvs0c_clk", + .parent_hws = (const struct clk_hw*[]){ + &video_cc_mvs0c_div2_div_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch video_cc_mvs1_clk = { + .halt_reg = 0xdb4, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0xdb4, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0xdb4, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "video_cc_mvs1_clk", + .parent_hws = (const struct clk_hw*[]){ + &video_cc_mvs1_div_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch video_cc_mvs1_div2_clk = { + .halt_reg = 0xdf4, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0xdf4, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0xdf4, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "video_cc_mvs1_div2_clk", + .parent_hws = (const struct clk_hw*[]){ + &video_cc_mvs1c_div2_div_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch video_cc_mvs1c_clk = { + .halt_reg = 0xcd4, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xcd4, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "video_cc_mvs1c_clk", + .parent_hws = (const struct clk_hw*[]){ + &video_cc_mvs1c_div2_div_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch video_cc_sleep_clk = { + .halt_reg = 0xf10, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xf10, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "video_cc_sleep_clk", + .parent_hws = (const struct clk_hw*[]){ + &video_cc_sleep_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct gdsc mvs0c_gdsc = { + .gdscr = 0xbf8, + .pd = { + .name = "mvs0c_gdsc", + }, + .flags = RETAIN_FF_ENABLE, + .pwrsts = PWRSTS_OFF_ON, +}; + +static struct gdsc mvs1c_gdsc = { + .gdscr = 0xc98, + .pd = { + .name = "mvs1c_gdsc", + }, + .flags = RETAIN_FF_ENABLE, + .pwrsts = PWRSTS_OFF_ON, +}; + +static struct gdsc mvs0_gdsc = { + .gdscr = 0xd18, + .pd = { + .name = "mvs0_gdsc", + }, + .flags = HW_CTRL | RETAIN_FF_ENABLE, + .pwrsts = PWRSTS_OFF_ON, +}; + +static struct gdsc mvs1_gdsc = { + .gdscr = 0xd98, + .pd = { + .name = "mvs1_gdsc", + }, + .flags = HW_CTRL | RETAIN_FF_ENABLE, + .pwrsts = PWRSTS_OFF_ON, +}; + +static struct clk_regmap *video_cc_sm8350_clocks[] = { + [VIDEO_CC_AHB_CLK_SRC] = &video_cc_ahb_clk_src.clkr, + [VIDEO_CC_MVS0_CLK] = &video_cc_mvs0_clk.clkr, + [VIDEO_CC_MVS0_CLK_SRC] = &video_cc_mvs0_clk_src.clkr, + [VIDEO_CC_MVS0_DIV_CLK_SRC] = &video_cc_mvs0_div_clk_src.clkr, + [VIDEO_CC_MVS0C_CLK] = &video_cc_mvs0c_clk.clkr, + [VIDEO_CC_MVS0C_DIV2_DIV_CLK_SRC] = &video_cc_mvs0c_div2_div_clk_src.clkr, + [VIDEO_CC_MVS1_CLK] = &video_cc_mvs1_clk.clkr, + [VIDEO_CC_MVS1_CLK_SRC] = &video_cc_mvs1_clk_src.clkr, + [VIDEO_CC_MVS1_DIV2_CLK] = &video_cc_mvs1_div2_clk.clkr, + [VIDEO_CC_MVS1_DIV_CLK_SRC] = &video_cc_mvs1_div_clk_src.clkr, + [VIDEO_CC_MVS1C_CLK] = &video_cc_mvs1c_clk.clkr, + [VIDEO_CC_MVS1C_DIV2_DIV_CLK_SRC] = &video_cc_mvs1c_div2_div_clk_src.clkr, + [VIDEO_CC_SLEEP_CLK] = &video_cc_sleep_clk.clkr, + [VIDEO_CC_SLEEP_CLK_SRC] = &video_cc_sleep_clk_src.clkr, + [VIDEO_CC_XO_CLK_SRC] = &video_cc_xo_clk_src.clkr, + [VIDEO_PLL0] = &video_pll0.clkr, + [VIDEO_PLL1] = &video_pll1.clkr, +}; + +static const struct qcom_reset_map video_cc_sm8350_resets[] = { + [VIDEO_CC_CVP_INTERFACE_BCR] = { 0xe54 }, + [VIDEO_CC_CVP_MVS0_BCR] = { 0xd14 }, + [VIDEO_CC_MVS0C_CLK_ARES] = { 0xc34, 2 }, + [VIDEO_CC_CVP_MVS0C_BCR] = { 0xbf4 }, + [VIDEO_CC_CVP_MVS1_BCR] = { 0xd94 }, + [VIDEO_CC_MVS1C_CLK_ARES] = { 0xcd4, 2 }, + [VIDEO_CC_CVP_MVS1C_BCR] = { 0xc94 }, +}; + +static struct gdsc *video_cc_sm8350_gdscs[] = { + [MVS0C_GDSC] = &mvs0c_gdsc, + [MVS1C_GDSC] = &mvs1c_gdsc, + [MVS0_GDSC] = &mvs0_gdsc, + [MVS1_GDSC] = &mvs1_gdsc, +}; + +static const struct regmap_config video_cc_sm8350_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0x10000, + .fast_io = true, +}; + +static struct qcom_cc_desc video_cc_sm8350_desc = { + .config = &video_cc_sm8350_regmap_config, + .clks = video_cc_sm8350_clocks, + .num_clks = ARRAY_SIZE(video_cc_sm8350_clocks), + .resets = video_cc_sm8350_resets, + .num_resets = ARRAY_SIZE(video_cc_sm8350_resets), + .gdscs = video_cc_sm8350_gdscs, + .num_gdscs = ARRAY_SIZE(video_cc_sm8350_gdscs), +}; + +static int video_cc_sm8350_probe(struct platform_device *pdev) +{ + struct regmap *regmap; + int ret; + + ret = devm_pm_runtime_enable(&pdev->dev); + if (ret) + return ret; + + ret = pm_runtime_resume_and_get(&pdev->dev); + if (ret) + return ret; + + regmap = qcom_cc_map(pdev, &video_cc_sm8350_desc); + if (IS_ERR(regmap)) { + pm_runtime_put(&pdev->dev); + return PTR_ERR(regmap); + } + + clk_lucid_pll_configure(&video_pll0, regmap, &video_pll0_config); + clk_lucid_pll_configure(&video_pll1, regmap, &video_pll1_config); + + /* + * Keep clocks always enabled: + * video_cc_ahb_clk + * video_cc_xo_clk + */ + regmap_update_bits(regmap, 0xe58, BIT(0), BIT(0)); + regmap_update_bits(regmap, 0xeec, BIT(0), BIT(0)); + + ret = qcom_cc_really_probe(pdev, &video_cc_sm8350_desc, regmap); + pm_runtime_put(&pdev->dev); + + return ret; +} + +static const struct of_device_id video_cc_sm8350_match_table[] = { + { .compatible = "qcom,sm8350-videocc" }, + { } +}; +MODULE_DEVICE_TABLE(of, video_cc_sm8350_match_table); + +static struct platform_driver video_cc_sm8350_driver = { + .probe = video_cc_sm8350_probe, + .driver = { + .name = "sm8350-videocc", + .of_match_table = video_cc_sm8350_match_table, + }, +}; +module_platform_driver(video_cc_sm8350_driver); + +MODULE_DESCRIPTION("QTI SM8350 VIDEOCC Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/qcom/videocc-sm8450.c b/drivers/clk/qcom/videocc-sm8450.c new file mode 100644 index 0000000000000000000000000000000000000000..7d0029b8b79999f498905a6fea9e28a2cdf856a0 --- /dev/null +++ b/drivers/clk/qcom/videocc-sm8450.c @@ -0,0 +1,463 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2023, Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#include +#include +#include +#include +#include + +#include + +#include "clk-alpha-pll.h" +#include "clk-branch.h" +#include "clk-rcg.h" +#include "clk-regmap.h" +#include "clk-regmap-divider.h" +#include "common.h" +#include "gdsc.h" +#include "reset.h" + +enum { + DT_BI_TCXO, +}; + +enum { + P_BI_TCXO, + P_VIDEO_CC_PLL0_OUT_MAIN, + P_VIDEO_CC_PLL1_OUT_MAIN, +}; + +static const struct pll_vco lucid_evo_vco[] = { + { 249600000, 2020000000, 0 }, +}; + +static const struct alpha_pll_config video_cc_pll0_config = { + /* .l includes CAL_L_VAL, L_VAL fields */ + .l = 0x0044001e, + .alpha = 0x0, + .config_ctl_val = 0x20485699, + .config_ctl_hi_val = 0x00182261, + .config_ctl_hi1_val = 0x32aa299c, + .user_ctl_val = 0x00000000, + .user_ctl_hi_val = 0x00000805, +}; + +static struct clk_alpha_pll video_cc_pll0 = { + .offset = 0x0, + .vco_table = lucid_evo_vco, + .num_vco = ARRAY_SIZE(lucid_evo_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_EVO], + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "video_cc_pll0", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_lucid_evo_ops, + }, + }, +}; + +static const struct alpha_pll_config video_cc_pll1_config = { + /* .l includes CAL_L_VAL, L_VAL fields */ + .l = 0x0044002b, + .alpha = 0xc000, + .config_ctl_val = 0x20485699, + .config_ctl_hi_val = 0x00182261, + .config_ctl_hi1_val = 0x32aa299c, + .user_ctl_val = 0x00000000, + .user_ctl_hi_val = 0x00000805, +}; + +static struct clk_alpha_pll video_cc_pll1 = { + .offset = 0x1000, + .vco_table = lucid_evo_vco, + .num_vco = ARRAY_SIZE(lucid_evo_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_EVO], + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "video_cc_pll1", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_lucid_evo_ops, + }, + }, +}; + +static const struct parent_map video_cc_parent_map_0[] = { + { P_BI_TCXO, 0 }, + { P_VIDEO_CC_PLL0_OUT_MAIN, 1 }, +}; + +static const struct clk_parent_data video_cc_parent_data_0[] = { + { .index = DT_BI_TCXO }, + { .hw = &video_cc_pll0.clkr.hw }, +}; + +static const struct parent_map video_cc_parent_map_1[] = { + { P_BI_TCXO, 0 }, + { P_VIDEO_CC_PLL1_OUT_MAIN, 1 }, +}; + +static const struct clk_parent_data video_cc_parent_data_1[] = { + { .index = DT_BI_TCXO }, + { .hw = &video_cc_pll1.clkr.hw }, +}; + +static const struct freq_tbl ftbl_video_cc_mvs0_clk_src[] = { + F(576000000, P_VIDEO_CC_PLL0_OUT_MAIN, 1, 0, 0), + F(720000000, P_VIDEO_CC_PLL0_OUT_MAIN, 1, 0, 0), + F(1014000000, P_VIDEO_CC_PLL0_OUT_MAIN, 1, 0, 0), + F(1098000000, P_VIDEO_CC_PLL0_OUT_MAIN, 1, 0, 0), + F(1332000000, P_VIDEO_CC_PLL0_OUT_MAIN, 1, 0, 0), + { } +}; + +static struct clk_rcg2 video_cc_mvs0_clk_src = { + .cmd_rcgr = 0x8000, + .mnd_width = 0, + .hid_width = 5, + .parent_map = video_cc_parent_map_0, + .freq_tbl = ftbl_video_cc_mvs0_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "video_cc_mvs0_clk_src", + .parent_data = video_cc_parent_data_0, + .num_parents = ARRAY_SIZE(video_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_video_cc_mvs1_clk_src[] = { + F(840000000, P_VIDEO_CC_PLL1_OUT_MAIN, 1, 0, 0), + F(1050000000, P_VIDEO_CC_PLL1_OUT_MAIN, 1, 0, 0), + F(1350000000, P_VIDEO_CC_PLL1_OUT_MAIN, 1, 0, 0), + F(1500000000, P_VIDEO_CC_PLL1_OUT_MAIN, 1, 0, 0), + F(1650000000, P_VIDEO_CC_PLL1_OUT_MAIN, 1, 0, 0), + { } +}; + +static struct clk_rcg2 video_cc_mvs1_clk_src = { + .cmd_rcgr = 0x8018, + .mnd_width = 0, + .hid_width = 5, + .parent_map = video_cc_parent_map_1, + .freq_tbl = ftbl_video_cc_mvs1_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "video_cc_mvs1_clk_src", + .parent_data = video_cc_parent_data_1, + .num_parents = ARRAY_SIZE(video_cc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_regmap_div video_cc_mvs0_div_clk_src = { + .reg = 0x80b8, + .shift = 0, + .width = 4, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "video_cc_mvs0_div_clk_src", + .parent_hws = (const struct clk_hw*[]) { + &video_cc_mvs0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_regmap_div_ro_ops, + }, +}; + +static struct clk_regmap_div video_cc_mvs0c_div2_div_clk_src = { + .reg = 0x806c, + .shift = 0, + .width = 4, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "video_cc_mvs0c_div2_div_clk_src", + .parent_hws = (const struct clk_hw*[]) { + &video_cc_mvs0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_regmap_div_ro_ops, + }, +}; + +static struct clk_regmap_div video_cc_mvs1_div_clk_src = { + .reg = 0x80dc, + .shift = 0, + .width = 4, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "video_cc_mvs1_div_clk_src", + .parent_hws = (const struct clk_hw*[]) { + &video_cc_mvs1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_regmap_div_ro_ops, + }, +}; + +static struct clk_regmap_div video_cc_mvs1c_div2_div_clk_src = { + .reg = 0x8094, + .shift = 0, + .width = 4, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "video_cc_mvs1c_div2_div_clk_src", + .parent_hws = (const struct clk_hw*[]) { + &video_cc_mvs1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_regmap_div_ro_ops, + }, +}; + +static struct clk_branch video_cc_mvs0_clk = { + .halt_reg = 0x80b0, + .halt_check = BRANCH_HALT_SKIP, + .hwcg_reg = 0x80b0, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x80b0, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "video_cc_mvs0_clk", + .parent_hws = (const struct clk_hw*[]) { + &video_cc_mvs0_div_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch video_cc_mvs0c_clk = { + .halt_reg = 0x8064, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x8064, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "video_cc_mvs0c_clk", + .parent_hws = (const struct clk_hw*[]) { + &video_cc_mvs0c_div2_div_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch video_cc_mvs1_clk = { + .halt_reg = 0x80d4, + .halt_check = BRANCH_HALT_SKIP, + .hwcg_reg = 0x80d4, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x80d4, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "video_cc_mvs1_clk", + .parent_hws = (const struct clk_hw*[]) { + &video_cc_mvs1_div_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch video_cc_mvs1c_clk = { + .halt_reg = 0x808c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x808c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "video_cc_mvs1c_clk", + .parent_hws = (const struct clk_hw*[]) { + &video_cc_mvs1c_div2_div_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct gdsc video_cc_mvs0c_gdsc = { + .gdscr = 0x804c, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0x6, + .pd = { + .name = "video_cc_mvs0c_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .flags = RETAIN_FF_ENABLE, +}; + +static struct gdsc video_cc_mvs0_gdsc = { + .gdscr = 0x809c, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0x6, + .pd = { + .name = "video_cc_mvs0_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .parent = &video_cc_mvs0c_gdsc.pd, + .flags = RETAIN_FF_ENABLE | HW_CTRL, +}; + +static struct gdsc video_cc_mvs1c_gdsc = { + .gdscr = 0x8074, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0x6, + .pd = { + .name = "video_cc_mvs1c_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .flags = RETAIN_FF_ENABLE, +}; + +static struct gdsc video_cc_mvs1_gdsc = { + .gdscr = 0x80c0, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0x6, + .pd = { + .name = "video_cc_mvs1_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .parent = &video_cc_mvs1c_gdsc.pd, + .flags = RETAIN_FF_ENABLE | HW_CTRL, +}; + +static struct clk_regmap *video_cc_sm8450_clocks[] = { + [VIDEO_CC_MVS0_CLK] = &video_cc_mvs0_clk.clkr, + [VIDEO_CC_MVS0_CLK_SRC] = &video_cc_mvs0_clk_src.clkr, + [VIDEO_CC_MVS0_DIV_CLK_SRC] = &video_cc_mvs0_div_clk_src.clkr, + [VIDEO_CC_MVS0C_CLK] = &video_cc_mvs0c_clk.clkr, + [VIDEO_CC_MVS0C_DIV2_DIV_CLK_SRC] = &video_cc_mvs0c_div2_div_clk_src.clkr, + [VIDEO_CC_MVS1_CLK] = &video_cc_mvs1_clk.clkr, + [VIDEO_CC_MVS1_CLK_SRC] = &video_cc_mvs1_clk_src.clkr, + [VIDEO_CC_MVS1_DIV_CLK_SRC] = &video_cc_mvs1_div_clk_src.clkr, + [VIDEO_CC_MVS1C_CLK] = &video_cc_mvs1c_clk.clkr, + [VIDEO_CC_MVS1C_DIV2_DIV_CLK_SRC] = &video_cc_mvs1c_div2_div_clk_src.clkr, + [VIDEO_CC_PLL0] = &video_cc_pll0.clkr, + [VIDEO_CC_PLL1] = &video_cc_pll1.clkr, +}; + +static struct gdsc *video_cc_sm8450_gdscs[] = { + [VIDEO_CC_MVS0C_GDSC] = &video_cc_mvs0c_gdsc, + [VIDEO_CC_MVS0_GDSC] = &video_cc_mvs0_gdsc, + [VIDEO_CC_MVS1C_GDSC] = &video_cc_mvs1c_gdsc, + [VIDEO_CC_MVS1_GDSC] = &video_cc_mvs1_gdsc, +}; + +static const struct qcom_reset_map video_cc_sm8450_resets[] = { + [CVP_VIDEO_CC_INTERFACE_BCR] = { 0x80e0 }, + [CVP_VIDEO_CC_MVS0_BCR] = { 0x8098 }, + [CVP_VIDEO_CC_MVS0C_BCR] = { 0x8048 }, + [CVP_VIDEO_CC_MVS1_BCR] = { 0x80bc }, + [CVP_VIDEO_CC_MVS1C_BCR] = { 0x8070 }, + [VIDEO_CC_MVS0C_CLK_ARES] = { 0x8064, 2 }, + [VIDEO_CC_MVS1C_CLK_ARES] = { 0x808c, 2 }, +}; + +static const struct regmap_config video_cc_sm8450_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0x9f4c, + .fast_io = true, +}; + +static struct qcom_cc_desc video_cc_sm8450_desc = { + .config = &video_cc_sm8450_regmap_config, + .clks = video_cc_sm8450_clocks, + .num_clks = ARRAY_SIZE(video_cc_sm8450_clocks), + .resets = video_cc_sm8450_resets, + .num_resets = ARRAY_SIZE(video_cc_sm8450_resets), + .gdscs = video_cc_sm8450_gdscs, + .num_gdscs = ARRAY_SIZE(video_cc_sm8450_gdscs), +}; + +static const struct of_device_id video_cc_sm8450_match_table[] = { + { .compatible = "qcom,sm8450-videocc" }, + { } +}; +MODULE_DEVICE_TABLE(of, video_cc_sm8450_match_table); + +static int video_cc_sm8450_probe(struct platform_device *pdev) +{ + struct regmap *regmap; + int ret; + + ret = devm_pm_runtime_enable(&pdev->dev); + if (ret) + return ret; + + ret = pm_runtime_resume_and_get(&pdev->dev); + if (ret) + return ret; + + regmap = qcom_cc_map(pdev, &video_cc_sm8450_desc); + if (IS_ERR(regmap)) { + pm_runtime_put(&pdev->dev); + return PTR_ERR(regmap); + } + + clk_lucid_evo_pll_configure(&video_cc_pll0, regmap, &video_cc_pll0_config); + clk_lucid_evo_pll_configure(&video_cc_pll1, regmap, &video_cc_pll1_config); + + /* + * Keep clocks always enabled: + * video_cc_ahb_clk + * video_cc_sleep_clk + * video_cc_xo_clk + */ + regmap_update_bits(regmap, 0x80e4, BIT(0), BIT(0)); + regmap_update_bits(regmap, 0x8130, BIT(0), BIT(0)); + regmap_update_bits(regmap, 0x8114, BIT(0), BIT(0)); + + ret = qcom_cc_really_probe(pdev, &video_cc_sm8450_desc, regmap); + + pm_runtime_put(&pdev->dev); + + return ret; +} + +static struct platform_driver video_cc_sm8450_driver = { + .probe = video_cc_sm8450_probe, + .driver = { + .name = "video_cc-sm8450", + .of_match_table = video_cc_sm8450_match_table, + }, +}; + +static int __init video_cc_sm8450_init(void) +{ + return platform_driver_register(&video_cc_sm8450_driver); +} +subsys_initcall(video_cc_sm8450_init); + +static void __exit video_cc_sm8450_exit(void) +{ + platform_driver_unregister(&video_cc_sm8450_driver); +} +module_exit(video_cc_sm8450_exit); + +MODULE_DESCRIPTION("QTI VIDEOCC SM8450 Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/qcom/videocc-sm8550.c b/drivers/clk/qcom/videocc-sm8550.c new file mode 100644 index 0000000000000000000000000000000000000000..e2400fe23e60277beced8e4280ab0cd761db7f6d --- /dev/null +++ b/drivers/clk/qcom/videocc-sm8550.c @@ -0,0 +1,470 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2023, Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#include +#include +#include +#include +#include + +#include + +#include "clk-alpha-pll.h" +#include "clk-branch.h" +#include "clk-rcg.h" +#include "clk-regmap.h" +#include "clk-regmap-divider.h" +#include "common.h" +#include "gdsc.h" +#include "reset.h" + +enum { + DT_BI_TCXO, +}; + +enum { + P_BI_TCXO, + P_VIDEO_CC_PLL0_OUT_MAIN, + P_VIDEO_CC_PLL1_OUT_MAIN, +}; + +static const struct pll_vco lucid_ole_vco[] = { + { 249600000, 2300000000, 0 }, +}; + +static const struct alpha_pll_config video_cc_pll0_config = { + /* .l includes RINGOSC_CAL_L_VAL, CAL_L_VAL, L_VAL fields */ + .l = 0x44440025, + .alpha = 0x8000, + .config_ctl_val = 0x20485699, + .config_ctl_hi_val = 0x00182261, + .config_ctl_hi1_val = 0x82aa299c, + .test_ctl_val = 0x00000000, + .test_ctl_hi_val = 0x00000003, + .test_ctl_hi1_val = 0x00009000, + .test_ctl_hi2_val = 0x00000034, + .user_ctl_val = 0x00000000, + .user_ctl_hi_val = 0x00000005, +}; + +static struct clk_alpha_pll video_cc_pll0 = { + .offset = 0x0, + .vco_table = lucid_ole_vco, + .num_vco = ARRAY_SIZE(lucid_ole_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE], + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "video_cc_pll0", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_lucid_evo_ops, + }, + }, +}; + +static const struct alpha_pll_config video_cc_pll1_config = { + /* .l includes RINGOSC_CAL_L_VAL, CAL_L_VAL, L_VAL fields */ + .l = 0x44440036, + .alpha = 0xb000, + .config_ctl_val = 0x20485699, + .config_ctl_hi_val = 0x00182261, + .config_ctl_hi1_val = 0x82aa299c, + .test_ctl_val = 0x00000000, + .test_ctl_hi_val = 0x00000003, + .test_ctl_hi1_val = 0x00009000, + .test_ctl_hi2_val = 0x00000034, + .user_ctl_val = 0x00000000, + .user_ctl_hi_val = 0x00000005, +}; + +static struct clk_alpha_pll video_cc_pll1 = { + .offset = 0x1000, + .vco_table = lucid_ole_vco, + .num_vco = ARRAY_SIZE(lucid_ole_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE], + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "video_cc_pll1", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_lucid_evo_ops, + }, + }, +}; + +static const struct parent_map video_cc_parent_map_0[] = { + { P_BI_TCXO, 0 }, + { P_VIDEO_CC_PLL0_OUT_MAIN, 1 }, +}; + +static const struct clk_parent_data video_cc_parent_data_0[] = { + { .index = DT_BI_TCXO }, + { .hw = &video_cc_pll0.clkr.hw }, +}; + +static const struct parent_map video_cc_parent_map_1[] = { + { P_BI_TCXO, 0 }, + { P_VIDEO_CC_PLL1_OUT_MAIN, 1 }, +}; + +static const struct clk_parent_data video_cc_parent_data_1[] = { + { .index = DT_BI_TCXO }, + { .hw = &video_cc_pll1.clkr.hw }, +}; + +static const struct freq_tbl ftbl_video_cc_mvs0_clk_src[] = { + F(720000000, P_VIDEO_CC_PLL0_OUT_MAIN, 1, 0, 0), + F(1014000000, P_VIDEO_CC_PLL0_OUT_MAIN, 1, 0, 0), + F(1098000000, P_VIDEO_CC_PLL0_OUT_MAIN, 1, 0, 0), + F(1332000000, P_VIDEO_CC_PLL0_OUT_MAIN, 1, 0, 0), + F(1600000000, P_VIDEO_CC_PLL0_OUT_MAIN, 1, 0, 0), + { } +}; + +static struct clk_rcg2 video_cc_mvs0_clk_src = { + .cmd_rcgr = 0x8000, + .mnd_width = 0, + .hid_width = 5, + .parent_map = video_cc_parent_map_0, + .freq_tbl = ftbl_video_cc_mvs0_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "video_cc_mvs0_clk_src", + .parent_data = video_cc_parent_data_0, + .num_parents = ARRAY_SIZE(video_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_video_cc_mvs1_clk_src[] = { + F(1050000000, P_VIDEO_CC_PLL1_OUT_MAIN, 1, 0, 0), + F(1350000000, P_VIDEO_CC_PLL1_OUT_MAIN, 1, 0, 0), + F(1500000000, P_VIDEO_CC_PLL1_OUT_MAIN, 1, 0, 0), + F(1650000000, P_VIDEO_CC_PLL1_OUT_MAIN, 1, 0, 0), + { } +}; + +static struct clk_rcg2 video_cc_mvs1_clk_src = { + .cmd_rcgr = 0x8018, + .mnd_width = 0, + .hid_width = 5, + .parent_map = video_cc_parent_map_1, + .freq_tbl = ftbl_video_cc_mvs1_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "video_cc_mvs1_clk_src", + .parent_data = video_cc_parent_data_1, + .num_parents = ARRAY_SIZE(video_cc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_regmap_div video_cc_mvs0_div_clk_src = { + .reg = 0x80c4, + .shift = 0, + .width = 4, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "video_cc_mvs0_div_clk_src", + .parent_hws = (const struct clk_hw*[]) { + &video_cc_mvs0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_regmap_div_ro_ops, + }, +}; + +static struct clk_regmap_div video_cc_mvs0c_div2_div_clk_src = { + .reg = 0x8070, + .shift = 0, + .width = 4, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "video_cc_mvs0c_div2_div_clk_src", + .parent_hws = (const struct clk_hw*[]) { + &video_cc_mvs0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_regmap_div_ro_ops, + }, +}; + +static struct clk_regmap_div video_cc_mvs1_div_clk_src = { + .reg = 0x80ec, + .shift = 0, + .width = 4, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "video_cc_mvs1_div_clk_src", + .parent_hws = (const struct clk_hw*[]) { + &video_cc_mvs1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_regmap_div_ro_ops, + }, +}; + +static struct clk_regmap_div video_cc_mvs1c_div2_div_clk_src = { + .reg = 0x809c, + .shift = 0, + .width = 4, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "video_cc_mvs1c_div2_div_clk_src", + .parent_hws = (const struct clk_hw*[]) { + &video_cc_mvs1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_regmap_div_ro_ops, + }, +}; + +static struct clk_branch video_cc_mvs0_clk = { + .halt_reg = 0x80b8, + .halt_check = BRANCH_HALT_SKIP, + .hwcg_reg = 0x80b8, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x80b8, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "video_cc_mvs0_clk", + .parent_hws = (const struct clk_hw*[]) { + &video_cc_mvs0_div_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch video_cc_mvs0c_clk = { + .halt_reg = 0x8064, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x8064, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "video_cc_mvs0c_clk", + .parent_hws = (const struct clk_hw*[]) { + &video_cc_mvs0c_div2_div_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch video_cc_mvs1_clk = { + .halt_reg = 0x80e0, + .halt_check = BRANCH_HALT_SKIP, + .hwcg_reg = 0x80e0, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x80e0, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "video_cc_mvs1_clk", + .parent_hws = (const struct clk_hw*[]) { + &video_cc_mvs1_div_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch video_cc_mvs1c_clk = { + .halt_reg = 0x8090, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x8090, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "video_cc_mvs1c_clk", + .parent_hws = (const struct clk_hw*[]) { + &video_cc_mvs1c_div2_div_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct gdsc video_cc_mvs0c_gdsc = { + .gdscr = 0x804c, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0x6, + .pd = { + .name = "video_cc_mvs0c_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE, +}; + +static struct gdsc video_cc_mvs0_gdsc = { + .gdscr = 0x80a4, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0x6, + .pd = { + .name = "video_cc_mvs0_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .parent = &video_cc_mvs0c_gdsc.pd, + .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE | HW_CTRL, +}; + +static struct gdsc video_cc_mvs1c_gdsc = { + .gdscr = 0x8078, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0x6, + .pd = { + .name = "video_cc_mvs1c_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE, +}; + +static struct gdsc video_cc_mvs1_gdsc = { + .gdscr = 0x80cc, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0x6, + .pd = { + .name = "video_cc_mvs1_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .parent = &video_cc_mvs1c_gdsc.pd, + .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE | HW_CTRL, +}; + +static struct clk_regmap *video_cc_sm8550_clocks[] = { + [VIDEO_CC_MVS0_CLK] = &video_cc_mvs0_clk.clkr, + [VIDEO_CC_MVS0_CLK_SRC] = &video_cc_mvs0_clk_src.clkr, + [VIDEO_CC_MVS0_DIV_CLK_SRC] = &video_cc_mvs0_div_clk_src.clkr, + [VIDEO_CC_MVS0C_CLK] = &video_cc_mvs0c_clk.clkr, + [VIDEO_CC_MVS0C_DIV2_DIV_CLK_SRC] = &video_cc_mvs0c_div2_div_clk_src.clkr, + [VIDEO_CC_MVS1_CLK] = &video_cc_mvs1_clk.clkr, + [VIDEO_CC_MVS1_CLK_SRC] = &video_cc_mvs1_clk_src.clkr, + [VIDEO_CC_MVS1_DIV_CLK_SRC] = &video_cc_mvs1_div_clk_src.clkr, + [VIDEO_CC_MVS1C_CLK] = &video_cc_mvs1c_clk.clkr, + [VIDEO_CC_MVS1C_DIV2_DIV_CLK_SRC] = &video_cc_mvs1c_div2_div_clk_src.clkr, + [VIDEO_CC_PLL0] = &video_cc_pll0.clkr, + [VIDEO_CC_PLL1] = &video_cc_pll1.clkr, +}; + +static struct gdsc *video_cc_sm8550_gdscs[] = { + [VIDEO_CC_MVS0C_GDSC] = &video_cc_mvs0c_gdsc, + [VIDEO_CC_MVS0_GDSC] = &video_cc_mvs0_gdsc, + [VIDEO_CC_MVS1C_GDSC] = &video_cc_mvs1c_gdsc, + [VIDEO_CC_MVS1_GDSC] = &video_cc_mvs1_gdsc, +}; + +static const struct qcom_reset_map video_cc_sm8550_resets[] = { + [CVP_VIDEO_CC_INTERFACE_BCR] = { 0x80f0 }, + [CVP_VIDEO_CC_MVS0_BCR] = { 0x80a0 }, + [CVP_VIDEO_CC_MVS0C_BCR] = { 0x8048 }, + [CVP_VIDEO_CC_MVS1_BCR] = { 0x80c8 }, + [CVP_VIDEO_CC_MVS1C_BCR] = { 0x8074 }, + [VIDEO_CC_MVS0C_CLK_ARES] = { 0x8064, 2 }, + [VIDEO_CC_MVS1C_CLK_ARES] = { 0x8090, 2 }, +}; + +static const struct regmap_config video_cc_sm8550_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0x9f4c, + .fast_io = true, +}; + +static struct qcom_cc_desc video_cc_sm8550_desc = { + .config = &video_cc_sm8550_regmap_config, + .clks = video_cc_sm8550_clocks, + .num_clks = ARRAY_SIZE(video_cc_sm8550_clocks), + .resets = video_cc_sm8550_resets, + .num_resets = ARRAY_SIZE(video_cc_sm8550_resets), + .gdscs = video_cc_sm8550_gdscs, + .num_gdscs = ARRAY_SIZE(video_cc_sm8550_gdscs), +}; + +static const struct of_device_id video_cc_sm8550_match_table[] = { + { .compatible = "qcom,sm8550-videocc" }, + { } +}; +MODULE_DEVICE_TABLE(of, video_cc_sm8550_match_table); + +static int video_cc_sm8550_probe(struct platform_device *pdev) +{ + struct regmap *regmap; + int ret; + + ret = devm_pm_runtime_enable(&pdev->dev); + if (ret) + return ret; + + ret = pm_runtime_resume_and_get(&pdev->dev); + if (ret) + return ret; + + regmap = qcom_cc_map(pdev, &video_cc_sm8550_desc); + if (IS_ERR(regmap)) { + pm_runtime_put(&pdev->dev); + return PTR_ERR(regmap); + } + + clk_lucid_evo_pll_configure(&video_cc_pll0, regmap, &video_cc_pll0_config); + clk_lucid_evo_pll_configure(&video_cc_pll1, regmap, &video_cc_pll1_config); + + /* + * Keep clocks always enabled: + * video_cc_ahb_clk + * video_cc_sleep_clk + * video_cc_xo_clk + */ + regmap_update_bits(regmap, 0x80f4, BIT(0), BIT(0)); + regmap_update_bits(regmap, 0x8140, BIT(0), BIT(0)); + regmap_update_bits(regmap, 0x8124, BIT(0), BIT(0)); + + ret = qcom_cc_really_probe(pdev, &video_cc_sm8550_desc, regmap); + + pm_runtime_put(&pdev->dev); + + return ret; +} + +static struct platform_driver video_cc_sm8550_driver = { + .probe = video_cc_sm8550_probe, + .driver = { + .name = "video_cc-sm8550", + .of_match_table = video_cc_sm8550_match_table, + }, +}; + +static int __init video_cc_sm8550_init(void) +{ + return platform_driver_register(&video_cc_sm8550_driver); +} +subsys_initcall(video_cc_sm8550_init); + +static void __exit video_cc_sm8550_exit(void) +{ + platform_driver_unregister(&video_cc_sm8550_driver); +} +module_exit(video_cc_sm8550_exit); + +MODULE_DESCRIPTION("QTI VIDEOCC SM8550 Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/ralink/Kconfig b/drivers/clk/ralink/Kconfig index 6580d5edc676be67aa8d0a8d6577f82cd10a3695..7c4f335864a88ed259454b882f3c4709fddefd02 100644 --- a/drivers/clk/ralink/Kconfig +++ b/drivers/clk/ralink/Kconfig @@ -9,3 +9,10 @@ config CLK_MT7621 select MFD_SYSCON help This driver supports MediaTek MT7621 basic clocks. + +config CLK_MTMIPS + bool "Clock driver for MTMIPS SoCs" + depends on SOC_RT305X || SOC_RT288X || SOC_RT3883 || SOC_MT7620 || COMPILE_TEST + select MFD_SYSCON + help + This driver supports MTMIPS basic clocks. diff --git a/drivers/clk/ralink/Makefile b/drivers/clk/ralink/Makefile index cf6f9216379d92de07eeaa57f65afd066dcc969f..398c1bf8cbc1cf74323abefdef9079773e4e6b77 100644 --- a/drivers/clk/ralink/Makefile +++ b/drivers/clk/ralink/Makefile @@ -1,2 +1,3 @@ # SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_CLK_MT7621) += clk-mt7621.o +obj-$(CONFIG_CLK_MTMIPS) += clk-mtmips.o diff --git a/drivers/clk/ralink/clk-mtmips.c b/drivers/clk/ralink/clk-mtmips.c new file mode 100644 index 0000000000000000000000000000000000000000..1e7991439527a8807aa2e3430e51caff372fd096 --- /dev/null +++ b/drivers/clk/ralink/clk-mtmips.c @@ -0,0 +1,1117 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * MTMIPS SoCs Clock Driver + * Author: Sergio Paracuellos + */ + +#include +#include +#include +#include +#include +#include +#include + +/* Configuration registers */ +#define SYSC_REG_SYSTEM_CONFIG 0x10 +#define SYSC_REG_CLKCFG0 0x2c +#define SYSC_REG_RESET_CTRL 0x34 +#define SYSC_REG_CPU_SYS_CLKCFG 0x3c +#define SYSC_REG_CPLL_CONFIG0 0x54 +#define SYSC_REG_CPLL_CONFIG1 0x58 + +/* RT2880 SoC */ +#define RT2880_CONFIG_CPUCLK_SHIFT 20 +#define RT2880_CONFIG_CPUCLK_MASK 0x3 +#define RT2880_CONFIG_CPUCLK_250 0x0 +#define RT2880_CONFIG_CPUCLK_266 0x1 +#define RT2880_CONFIG_CPUCLK_280 0x2 +#define RT2880_CONFIG_CPUCLK_300 0x3 + +/* RT305X SoC */ +#define RT305X_SYSCFG_CPUCLK_SHIFT 18 +#define RT305X_SYSCFG_CPUCLK_MASK 0x1 +#define RT305X_SYSCFG_CPUCLK_LOW 0x0 +#define RT305X_SYSCFG_CPUCLK_HIGH 0x1 + +/* RT3352 SoC */ +#define RT3352_SYSCFG0_CPUCLK_SHIFT 8 +#define RT3352_SYSCFG0_CPUCLK_MASK 0x1 +#define RT3352_SYSCFG0_CPUCLK_LOW 0x0 +#define RT3352_SYSCFG0_CPUCLK_HIGH 0x1 + +/* RT3383 SoC */ +#define RT3883_SYSCFG0_DRAM_TYPE_DDR2 BIT(17) +#define RT3883_SYSCFG0_CPUCLK_SHIFT 8 +#define RT3883_SYSCFG0_CPUCLK_MASK 0x3 +#define RT3883_SYSCFG0_CPUCLK_250 0x0 +#define RT3883_SYSCFG0_CPUCLK_384 0x1 +#define RT3883_SYSCFG0_CPUCLK_480 0x2 +#define RT3883_SYSCFG0_CPUCLK_500 0x3 + +/* RT5350 SoC */ +#define RT5350_CLKCFG0_XTAL_SEL BIT(20) +#define RT5350_SYSCFG0_CPUCLK_SHIFT 8 +#define RT5350_SYSCFG0_CPUCLK_MASK 0x3 +#define RT5350_SYSCFG0_CPUCLK_360 0x0 +#define RT5350_SYSCFG0_CPUCLK_320 0x2 +#define RT5350_SYSCFG0_CPUCLK_300 0x3 + +/* MT7620 and MT76x8 SoCs */ +#define MT7620_XTAL_FREQ_SEL BIT(6) +#define CPLL_CFG0_SW_CFG BIT(31) +#define CPLL_CFG0_PLL_MULT_RATIO_SHIFT 16 +#define CPLL_CFG0_PLL_MULT_RATIO_MASK 0x7 +#define CPLL_CFG0_LC_CURFCK BIT(15) +#define CPLL_CFG0_BYPASS_REF_CLK BIT(14) +#define CPLL_CFG0_PLL_DIV_RATIO_SHIFT 10 +#define CPLL_CFG0_PLL_DIV_RATIO_MASK 0x3 +#define CPLL_CFG1_CPU_AUX1 BIT(25) +#define CPLL_CFG1_CPU_AUX0 BIT(24) +#define CLKCFG0_PERI_CLK_SEL BIT(4) +#define CPU_SYS_CLKCFG_OCP_RATIO_SHIFT 16 +#define CPU_SYS_CLKCFG_OCP_RATIO_MASK 0xf +#define CPU_SYS_CLKCFG_OCP_RATIO_1 0 /* 1:1 (Reserved) */ +#define CPU_SYS_CLKCFG_OCP_RATIO_1_5 1 /* 1:1.5 (Reserved) */ +#define CPU_SYS_CLKCFG_OCP_RATIO_2 2 /* 1:2 */ +#define CPU_SYS_CLKCFG_OCP_RATIO_2_5 3 /* 1:2.5 (Reserved) */ +#define CPU_SYS_CLKCFG_OCP_RATIO_3 4 /* 1:3 */ +#define CPU_SYS_CLKCFG_OCP_RATIO_3_5 5 /* 1:3.5 (Reserved) */ +#define CPU_SYS_CLKCFG_OCP_RATIO_4 6 /* 1:4 */ +#define CPU_SYS_CLKCFG_OCP_RATIO_5 7 /* 1:5 */ +#define CPU_SYS_CLKCFG_OCP_RATIO_10 8 /* 1:10 */ +#define CPU_SYS_CLKCFG_CPU_FDIV_SHIFT 8 +#define CPU_SYS_CLKCFG_CPU_FDIV_MASK 0x1f +#define CPU_SYS_CLKCFG_CPU_FFRAC_SHIFT 0 +#define CPU_SYS_CLKCFG_CPU_FFRAC_MASK 0x1f + +/* clock scaling */ +#define CLKCFG_FDIV_MASK 0x1f00 +#define CLKCFG_FDIV_USB_VAL 0x0300 +#define CLKCFG_FFRAC_MASK 0x001f +#define CLKCFG_FFRAC_USB_VAL 0x0003 + +struct mtmips_clk; +struct mtmips_clk_fixed; +struct mtmips_clk_factor; + +struct mtmips_clk_data { + struct mtmips_clk *clk_base; + size_t num_clk_base; + struct mtmips_clk_fixed *clk_fixed; + size_t num_clk_fixed; + struct mtmips_clk_factor *clk_factor; + size_t num_clk_factor; + struct mtmips_clk *clk_periph; + size_t num_clk_periph; +}; + +struct mtmips_clk_priv { + struct regmap *sysc; + const struct mtmips_clk_data *data; +}; + +struct mtmips_clk { + struct clk_hw hw; + struct mtmips_clk_priv *priv; +}; + +struct mtmips_clk_fixed { + const char *name; + const char *parent; + unsigned long rate; + struct clk_hw *hw; +}; + +struct mtmips_clk_factor { + const char *name; + const char *parent; + int mult; + int div; + unsigned long flags; + struct clk_hw *hw; +}; + +static unsigned long mtmips_pherip_clk_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + return parent_rate; +} + +static const struct clk_ops mtmips_periph_clk_ops = { + .recalc_rate = mtmips_pherip_clk_rate, +}; + +#define CLK_PERIPH(_name, _parent) { \ + .init = &(const struct clk_init_data) { \ + .name = _name, \ + .ops = &mtmips_periph_clk_ops, \ + .parent_data = &(const struct clk_parent_data) {\ + .name = _parent, \ + .fw_name = _parent \ + }, \ + .num_parents = 1, \ + /* \ + * There are drivers for these SoCs that are \ + * older than clock driver and are not prepared \ + * for the clock. We don't want the kernel to \ + * disable anything so we add CLK_IS_CRITICAL \ + * flag here. \ + */ \ + .flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL \ + }, \ +} + +static struct mtmips_clk rt2880_pherip_clks[] = { + { CLK_PERIPH("300100.timer", "bus") }, + { CLK_PERIPH("300120.watchdog", "bus") }, + { CLK_PERIPH("300500.uart", "bus") }, + { CLK_PERIPH("300900.i2c", "bus") }, + { CLK_PERIPH("300c00.uartlite", "bus") }, + { CLK_PERIPH("400000.ethernet", "bus") }, + { CLK_PERIPH("480000.wmac", "xtal") } +}; + +static struct mtmips_clk rt305x_pherip_clks[] = { + { CLK_PERIPH("10000100.timer", "bus") }, + { CLK_PERIPH("10000120.watchdog", "bus") }, + { CLK_PERIPH("10000500.uart", "bus") }, + { CLK_PERIPH("10000900.i2c", "bus") }, + { CLK_PERIPH("10000a00.i2s", "bus") }, + { CLK_PERIPH("10000b00.spi", "bus") }, + { CLK_PERIPH("10000b40.spi", "bus") }, + { CLK_PERIPH("10000c00.uartlite", "bus") }, + { CLK_PERIPH("10100000.ethernet", "bus") }, + { CLK_PERIPH("10180000.wmac", "xtal") } +}; + +static struct mtmips_clk rt5350_pherip_clks[] = { + { CLK_PERIPH("10000100.timer", "bus") }, + { CLK_PERIPH("10000120.watchdog", "bus") }, + { CLK_PERIPH("10000500.uart", "periph") }, + { CLK_PERIPH("10000900.i2c", "periph") }, + { CLK_PERIPH("10000a00.i2s", "periph") }, + { CLK_PERIPH("10000b00.spi", "bus") }, + { CLK_PERIPH("10000b40.spi", "bus") }, + { CLK_PERIPH("10000c00.uartlite", "periph") }, + { CLK_PERIPH("10100000.ethernet", "bus") }, + { CLK_PERIPH("10180000.wmac", "xtal") } +}; + +static struct mtmips_clk mt7620_pherip_clks[] = { + { CLK_PERIPH("10000100.timer", "periph") }, + { CLK_PERIPH("10000120.watchdog", "periph") }, + { CLK_PERIPH("10000500.uart", "periph") }, + { CLK_PERIPH("10000900.i2c", "periph") }, + { CLK_PERIPH("10000a00.i2s", "periph") }, + { CLK_PERIPH("10000b00.spi", "bus") }, + { CLK_PERIPH("10000b40.spi", "bus") }, + { CLK_PERIPH("10000c00.uartlite", "periph") }, + { CLK_PERIPH("10180000.wmac", "xtal") } +}; + +static struct mtmips_clk mt76x8_pherip_clks[] = { + { CLK_PERIPH("10000100.timer", "periph") }, + { CLK_PERIPH("10000120.watchdog", "periph") }, + { CLK_PERIPH("10000900.i2c", "periph") }, + { CLK_PERIPH("10000a00.i2s", "pcmi2s") }, + { CLK_PERIPH("10000b00.spi", "bus") }, + { CLK_PERIPH("10000b40.spi", "bus") }, + { CLK_PERIPH("10000c00.uart0", "periph") }, + { CLK_PERIPH("10000d00.uart1", "periph") }, + { CLK_PERIPH("10000e00.uart2", "periph") }, + { CLK_PERIPH("10300000.wmac", "xtal") } +}; + +static int mtmips_register_pherip_clocks(struct device_node *np, + struct clk_hw_onecell_data *clk_data, + struct mtmips_clk_priv *priv) +{ + struct clk_hw **hws = clk_data->hws; + struct mtmips_clk *sclk; + size_t idx_start = priv->data->num_clk_base + priv->data->num_clk_fixed + + priv->data->num_clk_factor; + int ret, i; + + for (i = 0; i < priv->data->num_clk_periph; i++) { + int idx = idx_start + i; + + sclk = &priv->data->clk_periph[i]; + ret = of_clk_hw_register(np, &sclk->hw); + if (ret) { + pr_err("Couldn't register peripheral clock %d\n", idx); + goto err_clk_unreg; + } + + hws[idx] = &sclk->hw; + } + + return 0; + +err_clk_unreg: + while (--i >= 0) { + sclk = &priv->data->clk_periph[i]; + clk_hw_unregister(&sclk->hw); + } + return ret; +} + +#define CLK_FIXED(_name, _parent, _rate) \ + { \ + .name = _name, \ + .parent = _parent, \ + .rate = _rate \ + } + +static struct mtmips_clk_fixed rt305x_fixed_clocks[] = { + CLK_FIXED("xtal", NULL, 40000000) +}; + +static struct mtmips_clk_fixed rt3352_fixed_clocks[] = { + CLK_FIXED("periph", "xtal", 40000000) +}; + +static struct mtmips_clk_fixed mt76x8_fixed_clocks[] = { + CLK_FIXED("pcmi2s", "xtal", 480000000), + CLK_FIXED("periph", "xtal", 40000000) +}; + +static int mtmips_register_fixed_clocks(struct clk_hw_onecell_data *clk_data, + struct mtmips_clk_priv *priv) +{ + struct clk_hw **hws = clk_data->hws; + struct mtmips_clk_fixed *sclk; + size_t idx_start = priv->data->num_clk_base; + int ret, i; + + for (i = 0; i < priv->data->num_clk_fixed; i++) { + int idx = idx_start + i; + + sclk = &priv->data->clk_fixed[i]; + sclk->hw = clk_hw_register_fixed_rate(NULL, sclk->name, + sclk->parent, 0, + sclk->rate); + if (IS_ERR(sclk->hw)) { + ret = PTR_ERR(sclk->hw); + pr_err("Couldn't register fixed clock %d\n", idx); + goto err_clk_unreg; + } + + hws[idx] = sclk->hw; + } + + return 0; + +err_clk_unreg: + while (--i >= 0) { + sclk = &priv->data->clk_fixed[i]; + clk_hw_unregister_fixed_rate(sclk->hw); + } + return ret; +} + +#define CLK_FACTOR(_name, _parent, _mult, _div) \ + { \ + .name = _name, \ + .parent = _parent, \ + .mult = _mult, \ + .div = _div, \ + .flags = CLK_SET_RATE_PARENT \ + } + +static struct mtmips_clk_factor rt2880_factor_clocks[] = { + CLK_FACTOR("bus", "cpu", 1, 2) +}; + +static struct mtmips_clk_factor rt305x_factor_clocks[] = { + CLK_FACTOR("bus", "cpu", 1, 3) +}; + +static int mtmips_register_factor_clocks(struct clk_hw_onecell_data *clk_data, + struct mtmips_clk_priv *priv) +{ + struct clk_hw **hws = clk_data->hws; + struct mtmips_clk_factor *sclk; + size_t idx_start = priv->data->num_clk_base + priv->data->num_clk_fixed; + int ret, i; + + for (i = 0; i < priv->data->num_clk_factor; i++) { + int idx = idx_start + i; + + sclk = &priv->data->clk_factor[i]; + sclk->hw = clk_hw_register_fixed_factor(NULL, sclk->name, + sclk->parent, sclk->flags, + sclk->mult, sclk->div); + if (IS_ERR(sclk->hw)) { + ret = PTR_ERR(sclk->hw); + pr_err("Couldn't register factor clock %d\n", idx); + goto err_clk_unreg; + } + + hws[idx] = sclk->hw; + } + + return 0; + +err_clk_unreg: + while (--i >= 0) { + sclk = &priv->data->clk_factor[i]; + clk_hw_unregister_fixed_factor(sclk->hw); + } + return ret; +} + +static inline struct mtmips_clk *to_mtmips_clk(struct clk_hw *hw) +{ + return container_of(hw, struct mtmips_clk, hw); +} + +static unsigned long rt5350_xtal_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct mtmips_clk *clk = to_mtmips_clk(hw); + struct regmap *sysc = clk->priv->sysc; + u32 val; + + regmap_read(sysc, SYSC_REG_SYSTEM_CONFIG, &val); + if (!(val & RT5350_CLKCFG0_XTAL_SEL)) + return 20000000; + + return 40000000; +} + +static unsigned long rt5350_cpu_recalc_rate(struct clk_hw *hw, + unsigned long xtal_clk) +{ + struct mtmips_clk *clk = to_mtmips_clk(hw); + struct regmap *sysc = clk->priv->sysc; + u32 t; + + regmap_read(sysc, SYSC_REG_SYSTEM_CONFIG, &t); + t = (t >> RT5350_SYSCFG0_CPUCLK_SHIFT) & RT5350_SYSCFG0_CPUCLK_MASK; + + switch (t) { + case RT5350_SYSCFG0_CPUCLK_360: + return 360000000; + case RT5350_SYSCFG0_CPUCLK_320: + return 320000000; + case RT5350_SYSCFG0_CPUCLK_300: + return 300000000; + default: + BUG(); + } +} + +static unsigned long rt5350_bus_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + if (parent_rate == 320000000) + return parent_rate / 4; + + return parent_rate / 3; +} + +static unsigned long rt3352_cpu_recalc_rate(struct clk_hw *hw, + unsigned long xtal_clk) +{ + struct mtmips_clk *clk = to_mtmips_clk(hw); + struct regmap *sysc = clk->priv->sysc; + u32 t; + + regmap_read(sysc, SYSC_REG_SYSTEM_CONFIG, &t); + t = (t >> RT3352_SYSCFG0_CPUCLK_SHIFT) & RT3352_SYSCFG0_CPUCLK_MASK; + + switch (t) { + case RT3352_SYSCFG0_CPUCLK_LOW: + return 384000000; + case RT3352_SYSCFG0_CPUCLK_HIGH: + return 400000000; + default: + BUG(); + } +} + +static unsigned long rt305x_cpu_recalc_rate(struct clk_hw *hw, + unsigned long xtal_clk) +{ + struct mtmips_clk *clk = to_mtmips_clk(hw); + struct regmap *sysc = clk->priv->sysc; + u32 t; + + regmap_read(sysc, SYSC_REG_SYSTEM_CONFIG, &t); + t = (t >> RT305X_SYSCFG_CPUCLK_SHIFT) & RT305X_SYSCFG_CPUCLK_MASK; + + switch (t) { + case RT305X_SYSCFG_CPUCLK_LOW: + return 320000000; + case RT305X_SYSCFG_CPUCLK_HIGH: + return 384000000; + default: + BUG(); + } +} + +static unsigned long rt3883_cpu_recalc_rate(struct clk_hw *hw, + unsigned long xtal_clk) +{ + struct mtmips_clk *clk = to_mtmips_clk(hw); + struct regmap *sysc = clk->priv->sysc; + u32 t; + + regmap_read(sysc, SYSC_REG_SYSTEM_CONFIG, &t); + t = (t >> RT3883_SYSCFG0_CPUCLK_SHIFT) & RT3883_SYSCFG0_CPUCLK_MASK; + + switch (t) { + case RT3883_SYSCFG0_CPUCLK_250: + return 250000000; + case RT3883_SYSCFG0_CPUCLK_384: + return 384000000; + case RT3883_SYSCFG0_CPUCLK_480: + return 480000000; + case RT3883_SYSCFG0_CPUCLK_500: + return 500000000; + default: + BUG(); + } +} + +static unsigned long rt3883_bus_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct mtmips_clk *clk = to_mtmips_clk(hw); + struct regmap *sysc = clk->priv->sysc; + u32 ddr2; + u32 t; + + regmap_read(sysc, SYSC_REG_SYSTEM_CONFIG, &t); + ddr2 = t & RT3883_SYSCFG0_DRAM_TYPE_DDR2; + + switch (parent_rate) { + case 250000000: + return (ddr2) ? 125000000 : 83000000; + case 384000000: + return (ddr2) ? 128000000 : 96000000; + case 480000000: + return (ddr2) ? 160000000 : 120000000; + case 500000000: + return (ddr2) ? 166000000 : 125000000; + default: + WARN_ON_ONCE(parent_rate == 0); + return parent_rate / 4; + } +} + +static unsigned long rt2880_cpu_recalc_rate(struct clk_hw *hw, + unsigned long xtal_clk) +{ + struct mtmips_clk *clk = to_mtmips_clk(hw); + struct regmap *sysc = clk->priv->sysc; + u32 t; + + regmap_read(sysc, SYSC_REG_SYSTEM_CONFIG, &t); + t = (t >> RT2880_CONFIG_CPUCLK_SHIFT) & RT2880_CONFIG_CPUCLK_MASK; + + switch (t) { + case RT2880_CONFIG_CPUCLK_250: + return 250000000; + case RT2880_CONFIG_CPUCLK_266: + return 266000000; + case RT2880_CONFIG_CPUCLK_280: + return 280000000; + case RT2880_CONFIG_CPUCLK_300: + return 300000000; + default: + BUG(); + } +} + +static u32 mt7620_calc_rate(u32 ref_rate, u32 mul, u32 div) +{ + u64 t; + + t = ref_rate; + t *= mul; + t = div_u64(t, div); + + return t; +} + +static unsigned long mt7620_pll_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + static const u32 clk_divider[] = { 2, 3, 4, 8 }; + struct mtmips_clk *clk = to_mtmips_clk(hw); + struct regmap *sysc = clk->priv->sysc; + unsigned long cpu_pll; + u32 t; + u32 mul; + u32 div; + + regmap_read(sysc, SYSC_REG_CPLL_CONFIG0, &t); + if (t & CPLL_CFG0_BYPASS_REF_CLK) { + cpu_pll = parent_rate; + } else if ((t & CPLL_CFG0_SW_CFG) == 0) { + cpu_pll = 600000000; + } else { + mul = (t >> CPLL_CFG0_PLL_MULT_RATIO_SHIFT) & + CPLL_CFG0_PLL_MULT_RATIO_MASK; + mul += 24; + if (t & CPLL_CFG0_LC_CURFCK) + mul *= 2; + + div = (t >> CPLL_CFG0_PLL_DIV_RATIO_SHIFT) & + CPLL_CFG0_PLL_DIV_RATIO_MASK; + + WARN_ON_ONCE(div >= ARRAY_SIZE(clk_divider)); + + cpu_pll = mt7620_calc_rate(parent_rate, mul, clk_divider[div]); + } + + regmap_read(sysc, SYSC_REG_CPLL_CONFIG1, &t); + if (t & CPLL_CFG1_CPU_AUX1) + return parent_rate; + + if (t & CPLL_CFG1_CPU_AUX0) + return 480000000; + + return cpu_pll; +} + +static unsigned long mt7620_cpu_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct mtmips_clk *clk = to_mtmips_clk(hw); + struct regmap *sysc = clk->priv->sysc; + u32 t; + u32 mul; + u32 div; + + regmap_read(sysc, SYSC_REG_CPU_SYS_CLKCFG, &t); + mul = t & CPU_SYS_CLKCFG_CPU_FFRAC_MASK; + div = (t >> CPU_SYS_CLKCFG_CPU_FDIV_SHIFT) & + CPU_SYS_CLKCFG_CPU_FDIV_MASK; + + return mt7620_calc_rate(parent_rate, mul, div); +} + +static unsigned long mt7620_bus_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + static const u32 ocp_dividers[16] = { + [CPU_SYS_CLKCFG_OCP_RATIO_2] = 2, + [CPU_SYS_CLKCFG_OCP_RATIO_3] = 3, + [CPU_SYS_CLKCFG_OCP_RATIO_4] = 4, + [CPU_SYS_CLKCFG_OCP_RATIO_5] = 5, + [CPU_SYS_CLKCFG_OCP_RATIO_10] = 10, + }; + struct mtmips_clk *clk = to_mtmips_clk(hw); + struct regmap *sysc = clk->priv->sysc; + u32 t; + u32 ocp_ratio; + u32 div; + + regmap_read(sysc, SYSC_REG_CPU_SYS_CLKCFG, &t); + ocp_ratio = (t >> CPU_SYS_CLKCFG_OCP_RATIO_SHIFT) & + CPU_SYS_CLKCFG_OCP_RATIO_MASK; + + if (WARN_ON_ONCE(ocp_ratio >= ARRAY_SIZE(ocp_dividers))) + return parent_rate; + + div = ocp_dividers[ocp_ratio]; + + if (WARN(!div, "invalid divider for OCP ratio %u", ocp_ratio)) + return parent_rate; + + return parent_rate / div; +} + +static unsigned long mt7620_periph_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct mtmips_clk *clk = to_mtmips_clk(hw); + struct regmap *sysc = clk->priv->sysc; + u32 t; + + regmap_read(sysc, SYSC_REG_CLKCFG0, &t); + if (t & CLKCFG0_PERI_CLK_SEL) + return parent_rate; + + return 40000000; +} + +static unsigned long mt76x8_xtal_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct mtmips_clk *clk = to_mtmips_clk(hw); + struct regmap *sysc = clk->priv->sysc; + u32 t; + + regmap_read(sysc, SYSC_REG_SYSTEM_CONFIG, &t); + if (t & MT7620_XTAL_FREQ_SEL) + return 40000000; + + return 20000000; +} + +static unsigned long mt76x8_cpu_recalc_rate(struct clk_hw *hw, + unsigned long xtal_clk) +{ + if (xtal_clk == 40000000) + return 580000000; + + return 575000000; +} + +#define CLK_BASE(_name, _parent, _recalc) { \ + .init = &(const struct clk_init_data) { \ + .name = _name, \ + .ops = &(const struct clk_ops) { \ + .recalc_rate = _recalc, \ + }, \ + .parent_data = &(const struct clk_parent_data) { \ + .name = _parent, \ + .fw_name = _parent \ + }, \ + .num_parents = _parent ? 1 : 0 \ + }, \ +} + +static struct mtmips_clk rt2880_clks_base[] = { + { CLK_BASE("cpu", "xtal", rt2880_cpu_recalc_rate) } +}; + +static struct mtmips_clk rt305x_clks_base[] = { + { CLK_BASE("cpu", "xtal", rt305x_cpu_recalc_rate) } +}; + +static struct mtmips_clk rt3352_clks_base[] = { + { CLK_BASE("xtal", NULL, rt5350_xtal_recalc_rate) }, + { CLK_BASE("cpu", "xtal", rt3352_cpu_recalc_rate) } +}; + +static struct mtmips_clk rt3883_clks_base[] = { + { CLK_BASE("cpu", "xtal", rt3883_cpu_recalc_rate) }, + { CLK_BASE("bus", "cpu", rt3883_bus_recalc_rate) } +}; + +static struct mtmips_clk rt5350_clks_base[] = { + { CLK_BASE("xtal", NULL, rt5350_xtal_recalc_rate) }, + { CLK_BASE("cpu", "xtal", rt5350_cpu_recalc_rate) }, + { CLK_BASE("bus", "cpu", rt5350_bus_recalc_rate) } +}; + +static struct mtmips_clk mt7620_clks_base[] = { + { CLK_BASE("xtal", NULL, mt76x8_xtal_recalc_rate) }, + { CLK_BASE("pll", "xtal", mt7620_pll_recalc_rate) }, + { CLK_BASE("cpu", "pll", mt7620_cpu_recalc_rate) }, + { CLK_BASE("periph", "xtal", mt7620_periph_recalc_rate) }, + { CLK_BASE("bus", "cpu", mt7620_bus_recalc_rate) } +}; + +static struct mtmips_clk mt76x8_clks_base[] = { + { CLK_BASE("xtal", NULL, mt76x8_xtal_recalc_rate) }, + { CLK_BASE("cpu", "xtal", mt76x8_cpu_recalc_rate) } +}; + +static int mtmips_register_clocks(struct device_node *np, + struct clk_hw_onecell_data *clk_data, + struct mtmips_clk_priv *priv) +{ + struct clk_hw **hws = clk_data->hws; + struct mtmips_clk *sclk; + int ret, i; + + for (i = 0; i < priv->data->num_clk_base; i++) { + sclk = &priv->data->clk_base[i]; + sclk->priv = priv; + ret = of_clk_hw_register(np, &sclk->hw); + if (ret) { + pr_err("Couldn't register top clock %i\n", i); + goto err_clk_unreg; + } + + hws[i] = &sclk->hw; + } + + return 0; + +err_clk_unreg: + while (--i >= 0) { + sclk = &priv->data->clk_base[i]; + clk_hw_unregister(&sclk->hw); + } + return ret; +} + +static const struct mtmips_clk_data rt2880_clk_data = { + .clk_base = rt2880_clks_base, + .num_clk_base = ARRAY_SIZE(rt2880_clks_base), + .clk_fixed = rt305x_fixed_clocks, + .num_clk_fixed = ARRAY_SIZE(rt305x_fixed_clocks), + .clk_factor = rt2880_factor_clocks, + .num_clk_factor = ARRAY_SIZE(rt2880_factor_clocks), + .clk_periph = rt2880_pherip_clks, + .num_clk_periph = ARRAY_SIZE(rt2880_pherip_clks), +}; + +static const struct mtmips_clk_data rt305x_clk_data = { + .clk_base = rt305x_clks_base, + .num_clk_base = ARRAY_SIZE(rt305x_clks_base), + .clk_fixed = rt305x_fixed_clocks, + .num_clk_fixed = ARRAY_SIZE(rt305x_fixed_clocks), + .clk_factor = rt305x_factor_clocks, + .num_clk_factor = ARRAY_SIZE(rt305x_factor_clocks), + .clk_periph = rt305x_pherip_clks, + .num_clk_periph = ARRAY_SIZE(rt305x_pherip_clks), +}; + +static const struct mtmips_clk_data rt3352_clk_data = { + .clk_base = rt3352_clks_base, + .num_clk_base = ARRAY_SIZE(rt3352_clks_base), + .clk_fixed = rt3352_fixed_clocks, + .num_clk_fixed = ARRAY_SIZE(rt3352_fixed_clocks), + .clk_factor = rt305x_factor_clocks, + .num_clk_factor = ARRAY_SIZE(rt305x_factor_clocks), + .clk_periph = rt5350_pherip_clks, + .num_clk_periph = ARRAY_SIZE(rt5350_pherip_clks), +}; + +static const struct mtmips_clk_data rt3883_clk_data = { + .clk_base = rt3883_clks_base, + .num_clk_base = ARRAY_SIZE(rt3883_clks_base), + .clk_fixed = rt305x_fixed_clocks, + .num_clk_fixed = ARRAY_SIZE(rt305x_fixed_clocks), + .clk_factor = NULL, + .num_clk_factor = 0, + .clk_periph = rt5350_pherip_clks, + .num_clk_periph = ARRAY_SIZE(rt5350_pherip_clks), +}; + +static const struct mtmips_clk_data rt5350_clk_data = { + .clk_base = rt5350_clks_base, + .num_clk_base = ARRAY_SIZE(rt5350_clks_base), + .clk_fixed = rt3352_fixed_clocks, + .num_clk_fixed = ARRAY_SIZE(rt3352_fixed_clocks), + .clk_factor = NULL, + .num_clk_factor = 0, + .clk_periph = rt5350_pherip_clks, + .num_clk_periph = ARRAY_SIZE(rt5350_pherip_clks), +}; + +static const struct mtmips_clk_data mt7620_clk_data = { + .clk_base = mt7620_clks_base, + .num_clk_base = ARRAY_SIZE(mt7620_clks_base), + .clk_fixed = NULL, + .num_clk_fixed = 0, + .clk_factor = NULL, + .num_clk_factor = 0, + .clk_periph = mt7620_pherip_clks, + .num_clk_periph = ARRAY_SIZE(mt7620_pherip_clks), +}; + +static const struct mtmips_clk_data mt76x8_clk_data = { + .clk_base = mt76x8_clks_base, + .num_clk_base = ARRAY_SIZE(mt76x8_clks_base), + .clk_fixed = mt76x8_fixed_clocks, + .num_clk_fixed = ARRAY_SIZE(mt76x8_fixed_clocks), + .clk_factor = rt305x_factor_clocks, + .num_clk_factor = ARRAY_SIZE(rt305x_factor_clocks), + .clk_periph = mt76x8_pherip_clks, + .num_clk_periph = ARRAY_SIZE(mt76x8_pherip_clks), +}; + +static const struct of_device_id mtmips_of_match[] = { + { + .compatible = "ralink,rt2880-sysc", + .data = &rt2880_clk_data, + }, + { + .compatible = "ralink,rt3050-sysc", + .data = &rt305x_clk_data, + }, + { + .compatible = "ralink,rt3052-sysc", + .data = &rt305x_clk_data, + }, + { + .compatible = "ralink,rt3352-sysc", + .data = &rt3352_clk_data, + }, + { + .compatible = "ralink,rt3883-sysc", + .data = &rt3883_clk_data, + }, + { + .compatible = "ralink,rt5350-sysc", + .data = &rt5350_clk_data, + }, + { + .compatible = "ralink,mt7620-sysc", + .data = &mt7620_clk_data, + }, + { + .compatible = "ralink,mt7628-sysc", + .data = &mt76x8_clk_data, + }, + { + .compatible = "ralink,mt7688-sysc", + .data = &mt76x8_clk_data, + }, + {} +}; + +static void __init mtmips_clk_regs_init(struct device_node *node, + struct mtmips_clk_priv *priv) +{ + u32 t; + + if (!of_device_is_compatible(node, "ralink,mt7620-sysc")) + return; + + /* + * When the CPU goes into sleep mode, the BUS + * clock will be too low for USB to function properly. + * Adjust the busses fractional divider to fix this + */ + regmap_read(priv->sysc, SYSC_REG_CPU_SYS_CLKCFG, &t); + t &= ~(CLKCFG_FDIV_MASK | CLKCFG_FFRAC_MASK); + t |= CLKCFG_FDIV_USB_VAL | CLKCFG_FFRAC_USB_VAL; + regmap_write(priv->sysc, SYSC_REG_CPU_SYS_CLKCFG, t); +} + +static void __init mtmips_clk_init(struct device_node *node) +{ + const struct of_device_id *match; + const struct mtmips_clk_data *data; + struct mtmips_clk_priv *priv; + struct clk_hw_onecell_data *clk_data; + int ret, i, count; + + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return; + + priv->sysc = syscon_node_to_regmap(node); + if (IS_ERR(priv->sysc)) { + pr_err("Could not get sysc syscon regmap\n"); + goto free_clk_priv; + } + + mtmips_clk_regs_init(node, priv); + + match = of_match_node(mtmips_of_match, node); + if (WARN_ON(!match)) + return; + + data = match->data; + priv->data = data; + count = priv->data->num_clk_base + priv->data->num_clk_fixed + + priv->data->num_clk_factor + priv->data->num_clk_periph; + clk_data = kzalloc(struct_size(clk_data, hws, count), GFP_KERNEL); + if (!clk_data) + goto free_clk_priv; + + ret = mtmips_register_clocks(node, clk_data, priv); + if (ret) { + pr_err("Couldn't register top clocks\n"); + goto free_clk_data; + } + + ret = mtmips_register_fixed_clocks(clk_data, priv); + if (ret) { + pr_err("Couldn't register fixed clocks\n"); + goto unreg_clk_top; + } + + ret = mtmips_register_factor_clocks(clk_data, priv); + if (ret) { + pr_err("Couldn't register factor clocks\n"); + goto unreg_clk_fixed; + } + + ret = mtmips_register_pherip_clocks(node, clk_data, priv); + if (ret) { + pr_err("Couldn't register peripheral clocks\n"); + goto unreg_clk_factor; + } + + clk_data->num = count; + + ret = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (ret) { + pr_err("Couldn't add clk hw provider\n"); + goto unreg_clk_periph; + } + + return; + +unreg_clk_periph: + for (i = 0; i < priv->data->num_clk_periph; i++) { + struct mtmips_clk *sclk = &priv->data->clk_periph[i]; + + clk_hw_unregister(&sclk->hw); + } + +unreg_clk_factor: + for (i = 0; i < priv->data->num_clk_factor; i++) { + struct mtmips_clk_factor *sclk = &priv->data->clk_factor[i]; + + clk_hw_unregister_fixed_factor(sclk->hw); + } + +unreg_clk_fixed: + for (i = 0; i < priv->data->num_clk_fixed; i++) { + struct mtmips_clk_fixed *sclk = &priv->data->clk_fixed[i]; + + clk_hw_unregister_fixed_rate(sclk->hw); + } + +unreg_clk_top: + for (i = 0; i < priv->data->num_clk_base; i++) { + struct mtmips_clk *sclk = &priv->data->clk_base[i]; + + clk_hw_unregister(&sclk->hw); + } + +free_clk_data: + kfree(clk_data); + +free_clk_priv: + kfree(priv); +} +CLK_OF_DECLARE_DRIVER(rt2880_clk, "ralink,rt2880-sysc", mtmips_clk_init); +CLK_OF_DECLARE_DRIVER(rt3050_clk, "ralink,rt3050-sysc", mtmips_clk_init); +CLK_OF_DECLARE_DRIVER(rt3052_clk, "ralink,rt3052-sysc", mtmips_clk_init); +CLK_OF_DECLARE_DRIVER(rt3352_clk, "ralink,rt3352-sysc", mtmips_clk_init); +CLK_OF_DECLARE_DRIVER(rt3883_clk, "ralink,rt3883-sysc", mtmips_clk_init); +CLK_OF_DECLARE_DRIVER(rt5350_clk, "ralink,rt5350-sysc", mtmips_clk_init); +CLK_OF_DECLARE_DRIVER(mt7620_clk, "ralink,mt7620-sysc", mtmips_clk_init); +CLK_OF_DECLARE_DRIVER(mt7628_clk, "ralink,mt7628-sysc", mtmips_clk_init); +CLK_OF_DECLARE_DRIVER(mt7688_clk, "ralink,mt7688-sysc", mtmips_clk_init); + +struct mtmips_rst { + struct reset_controller_dev rcdev; + struct regmap *sysc; +}; + +static struct mtmips_rst *to_mtmips_rst(struct reset_controller_dev *dev) +{ + return container_of(dev, struct mtmips_rst, rcdev); +} + +static int mtmips_assert_device(struct reset_controller_dev *rcdev, + unsigned long id) +{ + struct mtmips_rst *data = to_mtmips_rst(rcdev); + struct regmap *sysc = data->sysc; + + return regmap_update_bits(sysc, SYSC_REG_RESET_CTRL, BIT(id), BIT(id)); +} + +static int mtmips_deassert_device(struct reset_controller_dev *rcdev, + unsigned long id) +{ + struct mtmips_rst *data = to_mtmips_rst(rcdev); + struct regmap *sysc = data->sysc; + + return regmap_update_bits(sysc, SYSC_REG_RESET_CTRL, BIT(id), 0); +} + +static int mtmips_reset_device(struct reset_controller_dev *rcdev, + unsigned long id) +{ + int ret; + + ret = mtmips_assert_device(rcdev, id); + if (ret < 0) + return ret; + + return mtmips_deassert_device(rcdev, id); +} + +static int mtmips_rst_xlate(struct reset_controller_dev *rcdev, + const struct of_phandle_args *reset_spec) +{ + unsigned long id = reset_spec->args[0]; + + if (id == 0 || id >= rcdev->nr_resets) + return -EINVAL; + + return id; +} + +static const struct reset_control_ops reset_ops = { + .reset = mtmips_reset_device, + .assert = mtmips_assert_device, + .deassert = mtmips_deassert_device +}; + +static int mtmips_reset_init(struct device *dev, struct regmap *sysc) +{ + struct mtmips_rst *rst_data; + + rst_data = devm_kzalloc(dev, sizeof(*rst_data), GFP_KERNEL); + if (!rst_data) + return -ENOMEM; + + rst_data->sysc = sysc; + rst_data->rcdev.ops = &reset_ops; + rst_data->rcdev.owner = THIS_MODULE; + rst_data->rcdev.nr_resets = 32; + rst_data->rcdev.of_reset_n_cells = 1; + rst_data->rcdev.of_xlate = mtmips_rst_xlate; + rst_data->rcdev.of_node = dev_of_node(dev); + + return devm_reset_controller_register(dev, &rst_data->rcdev); +} + +static int mtmips_clk_probe(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + struct device *dev = &pdev->dev; + struct mtmips_clk_priv *priv; + int ret; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->sysc = syscon_node_to_regmap(np); + if (IS_ERR(priv->sysc)) + return dev_err_probe(dev, PTR_ERR(priv->sysc), + "Could not get sysc syscon regmap\n"); + + ret = mtmips_reset_init(dev, priv->sysc); + if (ret) + return dev_err_probe(dev, ret, "Could not init reset controller\n"); + + return 0; +} + +static const struct of_device_id mtmips_clk_of_match[] = { + { .compatible = "ralink,rt2880-reset" }, + { .compatible = "ralink,rt2880-sysc" }, + { .compatible = "ralink,rt3050-sysc" }, + { .compatible = "ralink,rt3052-sysc" }, + { .compatible = "ralink,rt3352-sysc" }, + { .compatible = "ralink,rt3883-sysc" }, + { .compatible = "ralink,rt5350-sysc" }, + { .compatible = "ralink,mt7620-sysc" }, + { .compatible = "ralink,mt7628-sysc" }, + { .compatible = "ralink,mt7688-sysc" }, + {} +}; + +static struct platform_driver mtmips_clk_driver = { + .probe = mtmips_clk_probe, + .driver = { + .name = "mtmips-clk", + .of_match_table = mtmips_clk_of_match, + }, +}; + +static int __init mtmips_clk_reset_init(void) +{ + return platform_driver_register(&mtmips_clk_driver); +} +arch_initcall(mtmips_clk_reset_init); diff --git a/drivers/clk/renesas/clk-mstp.c b/drivers/clk/renesas/clk-mstp.c index 90804ac06fa538c683773c9b1a0c0a0bdfafa015..6280f4dfed714e6914dea8bc5dd63b55ee3432b8 100644 --- a/drivers/clk/renesas/clk-mstp.c +++ b/drivers/clk/renesas/clk-mstp.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -78,8 +79,8 @@ static int cpg_mstp_clock_endisable(struct clk_hw *hw, bool enable) struct mstp_clock_group *group = clock->group; u32 bitmask = BIT(clock->bit_index); unsigned long flags; - unsigned int i; u32 value; + int ret; spin_lock_irqsave(&group->lock, flags); @@ -101,19 +102,14 @@ static int cpg_mstp_clock_endisable(struct clk_hw *hw, bool enable) if (!enable || !group->mstpsr) return 0; - for (i = 1000; i > 0; --i) { - if (!(cpg_mstp_read(group, group->mstpsr) & bitmask)) - break; - cpu_relax(); - } - - if (!i) { + /* group->width_8bit is always false if group->mstpsr is present */ + ret = readl_poll_timeout_atomic(group->mstpsr, value, + !(value & bitmask), 0, 10); + if (ret) pr_err("%s: failed to enable %p[%d]\n", __func__, group->smstpcr, clock->bit_index); - return -ETIMEDOUT; - } - return 0; + return ret; } static int cpg_mstp_clock_enable(struct clk_hw *hw) diff --git a/drivers/clk/renesas/r8a779a0-cpg-mssr.c b/drivers/clk/renesas/r8a779a0-cpg-mssr.c index fcc8279647a6090b2259ef1c6b0017ac379d85bd..4c2872f45387ff91dc76ac982dfce4019a8c153c 100644 --- a/drivers/clk/renesas/r8a779a0-cpg-mssr.c +++ b/drivers/clk/renesas/r8a779a0-cpg-mssr.c @@ -170,6 +170,7 @@ static const struct mssr_mod_clk r8a779a0_mod_clks[] __initconst = { DEF_MOD("msi3", 621, R8A779A0_CLK_MSO), DEF_MOD("msi4", 622, R8A779A0_CLK_MSO), DEF_MOD("msi5", 623, R8A779A0_CLK_MSO), + DEF_MOD("pwm0", 628, R8A779A0_CLK_S1D8), DEF_MOD("rpc-if", 629, R8A779A0_CLK_RPCD2), DEF_MOD("scif0", 702, R8A779A0_CLK_S1D8), DEF_MOD("scif1", 703, R8A779A0_CLK_S1D8), diff --git a/drivers/clk/renesas/r9a06g032-clocks.c b/drivers/clk/renesas/r9a06g032-clocks.c index 40828616f723ea3e7515278ce45c4f2f72823ad8..55db63c7041a68a053ece2e973d3bfd973db8d27 100644 --- a/drivers/clk/renesas/r9a06g032-clocks.c +++ b/drivers/clk/renesas/r9a06g032-clocks.c @@ -1121,6 +1121,7 @@ static int r9a06g032_clk_mux_set_parent(struct clk_hw *hw, u8 index) } static const struct clk_ops clk_bitselect_ops = { + .determine_rate = clk_hw_determine_rate_no_reparent, .get_parent = r9a06g032_clk_mux_get_parent, .set_parent = r9a06g032_clk_mux_set_parent, }; diff --git a/drivers/clk/renesas/renesas-cpg-mssr.c b/drivers/clk/renesas/renesas-cpg-mssr.c index e9c0e341380e8f5562d1adcda9aa31f7763be3cc..2772499d20165127e71a2ab3d1b5dd4e258cd1a1 100644 --- a/drivers/clk/renesas/renesas-cpg-mssr.c +++ b/drivers/clk/renesas/renesas-cpg-mssr.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -196,8 +197,8 @@ static int cpg_mstp_clock_endisable(struct clk_hw *hw, bool enable) struct device *dev = priv->dev; u32 bitmask = BIT(bit); unsigned long flags; - unsigned int i; u32 value; + int error; dev_dbg(dev, "MSTP %u%02u/%pC %s\n", reg, bit, hw->clk, enable ? "ON" : "OFF"); @@ -228,19 +229,13 @@ static int cpg_mstp_clock_endisable(struct clk_hw *hw, bool enable) if (!enable || priv->reg_layout == CLK_REG_LAYOUT_RZ_A) return 0; - for (i = 1000; i > 0; --i) { - if (!(readl(priv->base + priv->status_regs[reg]) & bitmask)) - break; - cpu_relax(); - } - - if (!i) { + error = readl_poll_timeout_atomic(priv->base + priv->status_regs[reg], + value, !(value & bitmask), 0, 10); + if (error) dev_err(dev, "Failed to enable SMSTP %p[%d]\n", priv->base + priv->control_regs[reg], bit); - return -ETIMEDOUT; - } - return 0; + return error; } static int cpg_mstp_clock_enable(struct clk_hw *hw) @@ -896,8 +891,9 @@ static int cpg_mssr_suspend_noirq(struct device *dev) static int cpg_mssr_resume_noirq(struct device *dev) { struct cpg_mssr_priv *priv = dev_get_drvdata(dev); - unsigned int reg, i; + unsigned int reg; u32 mask, oldval, newval; + int error; /* This is the best we can do to check for the presence of PSCI */ if (!psci_ops.cpu_suspend) @@ -935,14 +931,9 @@ static int cpg_mssr_resume_noirq(struct device *dev) if (!mask) continue; - for (i = 1000; i > 0; --i) { - oldval = readl(priv->base + priv->status_regs[reg]); - if (!(oldval & mask)) - break; - cpu_relax(); - } - - if (!i) + error = readl_poll_timeout_atomic(priv->base + priv->status_regs[reg], + oldval, !(oldval & mask), 0, 10); + if (error) dev_warn(dev, "Failed to enable SMSTP%u[0x%x]\n", reg, oldval & mask); } diff --git a/drivers/clk/renesas/rzg2l-cpg.c b/drivers/clk/renesas/rzg2l-cpg.c index 93b02cdc98c25658a121446829227f600c1c05da..bc623515ad843cf57e047cde5b1ee888a3ba9952 100644 --- a/drivers/clk/renesas/rzg2l-cpg.c +++ b/drivers/clk/renesas/rzg2l-cpg.c @@ -603,10 +603,8 @@ static int rzg2l_cpg_sipll5_set_rate(struct clk_hw *hw, } /* Output clock setting 1 */ - writel(CPG_SIPLL5_CLK1_POSTDIV1_WEN | CPG_SIPLL5_CLK1_POSTDIV2_WEN | - CPG_SIPLL5_CLK1_REFDIV_WEN | (params.pl5_postdiv1 << 0) | - (params.pl5_postdiv2 << 4) | (params.pl5_refdiv << 8), - priv->base + CPG_SIPLL5_CLK1); + writel((params.pl5_postdiv1 << 0) | (params.pl5_postdiv2 << 4) | + (params.pl5_refdiv << 8), priv->base + CPG_SIPLL5_CLK1); /* Output clock setting, SSCG modulation value setting 3 */ writel((params.pl5_fracin << 8), priv->base + CPG_SIPLL5_CLK3); @@ -905,9 +903,9 @@ static int rzg2l_mod_clock_endisable(struct clk_hw *hw, bool enable) unsigned int reg = clock->off; struct device *dev = priv->dev; unsigned long flags; - unsigned int i; u32 bitmask = BIT(clock->bit); u32 value; + int error; if (!clock->off) { dev_dbg(dev, "%pC does not support ON/OFF\n", hw->clk); @@ -932,19 +930,13 @@ static int rzg2l_mod_clock_endisable(struct clk_hw *hw, bool enable) if (!priv->info->has_clk_mon_regs) return 0; - for (i = 1000; i > 0; --i) { - if (((readl(priv->base + CLK_MON_R(reg))) & bitmask)) - break; - cpu_relax(); - } - - if (!i) { + error = readl_poll_timeout_atomic(priv->base + CLK_MON_R(reg), value, + value & bitmask, 0, 10); + if (error) dev_err(dev, "Failed to enable CLK_ON %p\n", priv->base + CLK_ON_R(reg)); - return -ETIMEDOUT; - } - return 0; + return error; } static int rzg2l_mod_clock_enable(struct clk_hw *hw) diff --git a/drivers/clk/renesas/rzg2l-cpg.h b/drivers/clk/renesas/rzg2l-cpg.h index eee780276a9e22005e95674d5679421cf79b09db..6cee9e56acc7220072040aa854d0f2f387aa3011 100644 --- a/drivers/clk/renesas/rzg2l-cpg.h +++ b/drivers/clk/renesas/rzg2l-cpg.h @@ -32,9 +32,6 @@ #define CPG_SIPLL5_STBY_RESETB_WEN BIT(16) #define CPG_SIPLL5_STBY_SSCG_EN_WEN BIT(18) #define CPG_SIPLL5_STBY_DOWNSPREAD_WEN BIT(20) -#define CPG_SIPLL5_CLK1_POSTDIV1_WEN BIT(16) -#define CPG_SIPLL5_CLK1_POSTDIV2_WEN BIT(20) -#define CPG_SIPLL5_CLK1_REFDIV_WEN BIT(24) #define CPG_SIPLL5_CLK4_RESV_LSB (0xFF) #define CPG_SIPLL5_MON_PLL5_LOCK BIT(4) diff --git a/drivers/clk/samsung/Kconfig b/drivers/clk/samsung/Kconfig index c07bb50513bfe8ad94bdbaff7b5e3d59b6665e9e..76a494e95027af26272e30876a87ac293bd56dfa 100644 --- a/drivers/clk/samsung/Kconfig +++ b/drivers/clk/samsung/Kconfig @@ -2,6 +2,7 @@ # Recent Exynos platforms should just select COMMON_CLK_SAMSUNG: config COMMON_CLK_SAMSUNG bool "Samsung Exynos clock controller support" if COMPILE_TEST + depends on OF select S3C64XX_COMMON_CLK if ARM && ARCH_S3C64XX select S5PV210_COMMON_CLK if ARM && ARCH_S5PV210 select EXYNOS_3250_COMMON_CLK if ARM && SOC_EXYNOS3250 diff --git a/drivers/clk/samsung/clk-exynos-clkout.c b/drivers/clk/samsung/clk-exynos-clkout.c index 0cff1c94c35e67ae72f329dc24c86e04a6cb9d91..72b6cf83aff4d50e92365834d3b3d061ac0cbbf2 100644 --- a/drivers/clk/samsung/clk-exynos-clkout.c +++ b/drivers/clk/samsung/clk-exynos-clkout.c @@ -55,6 +55,9 @@ static const struct of_device_id exynos_clkout_ids[] = { }, { .compatible = "samsung,exynos4210-pmu", .data = &exynos_clkout_exynos4, + }, { + .compatible = "samsung,exynos4212-pmu", + .data = &exynos_clkout_exynos4, }, { .compatible = "samsung,exynos4412-pmu", .data = &exynos_clkout_exynos4, diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c index d7dbb38583471e86d5c1eeb3723196d1356addbf..43207257a9cc21f6157c034c92e26f11853a341e 100644 --- a/drivers/clk/samsung/clk-exynos4.c +++ b/drivers/clk/samsung/clk-exynos4.c @@ -138,7 +138,8 @@ /* the exynos4 soc type */ enum exynos4_soc { EXYNOS4210, - EXYNOS4X12, + EXYNOS4212, + EXYNOS4412, }; /* list of PLLs to be registered */ @@ -1205,6 +1206,24 @@ static const struct exynos_cpuclk_cfg_data e4210_armclk_d[] __initconst = { { 0 }, }; +static const struct exynos_cpuclk_cfg_data e4212_armclk_d[] __initconst = { + { 1500000, E4210_CPU_DIV0(2, 1, 6, 0, 7, 3), E4210_CPU_DIV1(2, 6), }, + { 1400000, E4210_CPU_DIV0(2, 1, 6, 0, 7, 3), E4210_CPU_DIV1(2, 6), }, + { 1300000, E4210_CPU_DIV0(2, 1, 5, 0, 7, 3), E4210_CPU_DIV1(2, 5), }, + { 1200000, E4210_CPU_DIV0(2, 1, 5, 0, 7, 3), E4210_CPU_DIV1(2, 5), }, + { 1100000, E4210_CPU_DIV0(2, 1, 4, 0, 6, 3), E4210_CPU_DIV1(2, 4), }, + { 1000000, E4210_CPU_DIV0(1, 1, 4, 0, 5, 2), E4210_CPU_DIV1(2, 4), }, + { 900000, E4210_CPU_DIV0(1, 1, 3, 0, 5, 2), E4210_CPU_DIV1(2, 3), }, + { 800000, E4210_CPU_DIV0(1, 1, 3, 0, 5, 2), E4210_CPU_DIV1(2, 3), }, + { 700000, E4210_CPU_DIV0(1, 1, 3, 0, 4, 2), E4210_CPU_DIV1(2, 3), }, + { 600000, E4210_CPU_DIV0(1, 1, 3, 0, 4, 2), E4210_CPU_DIV1(2, 3), }, + { 500000, E4210_CPU_DIV0(1, 1, 3, 0, 4, 2), E4210_CPU_DIV1(2, 3), }, + { 400000, E4210_CPU_DIV0(1, 1, 3, 0, 4, 2), E4210_CPU_DIV1(2, 3), }, + { 300000, E4210_CPU_DIV0(1, 1, 2, 0, 4, 2), E4210_CPU_DIV1(2, 3), }, + { 200000, E4210_CPU_DIV0(1, 1, 1, 0, 3, 1), E4210_CPU_DIV1(2, 3), }, + { 0 }, +}; + #define E4412_CPU_DIV1(cores, hpm, copy) \ (((cores) << 8) | ((hpm) << 4) | ((copy) << 0)) @@ -1233,6 +1252,11 @@ static const struct samsung_cpu_clock exynos4210_cpu_clks[] __initconst = { CLK_CPU_NEEDS_DEBUG_ALT_DIV | CLK_CPU_HAS_DIV1, 0x14200, e4210_armclk_d), }; +static const struct samsung_cpu_clock exynos4212_cpu_clks[] __initconst = { + CPU_CLK(CLK_ARM_CLK, "armclk", CLK_MOUT_APLL, CLK_MOUT_MPLL_USER_C, + CLK_CPU_NEEDS_DEBUG_ALT_DIV | CLK_CPU_HAS_DIV1, 0x14200, e4212_armclk_d), +}; + static const struct samsung_cpu_clock exynos4412_cpu_clks[] __initconst = { CPU_CLK(CLK_ARM_CLK, "armclk", CLK_MOUT_APLL, CLK_MOUT_MPLL_USER_C, CLK_CPU_NEEDS_DEBUG_ALT_DIV | CLK_CPU_HAS_DIV1, 0x14200, e4412_armclk_d), @@ -1326,11 +1350,15 @@ static void __init exynos4_clk_init(struct device_node *np, samsung_clk_register_fixed_factor(ctx, exynos4x12_fixed_factor_clks, ARRAY_SIZE(exynos4x12_fixed_factor_clks)); - samsung_clk_register_cpu(ctx, exynos4412_cpu_clks, - ARRAY_SIZE(exynos4412_cpu_clks)); + if (soc == EXYNOS4412) + samsung_clk_register_cpu(ctx, exynos4412_cpu_clks, + ARRAY_SIZE(exynos4412_cpu_clks)); + else + samsung_clk_register_cpu(ctx, exynos4212_cpu_clks, + ARRAY_SIZE(exynos4212_cpu_clks)); } - if (soc == EXYNOS4X12) + if (soc == EXYNOS4212 || soc == EXYNOS4412) exynos4x12_core_down_clock(); samsung_clk_extended_sleep_init(reg_base, @@ -1363,8 +1391,14 @@ static void __init exynos4210_clk_init(struct device_node *np) } CLK_OF_DECLARE(exynos4210_clk, "samsung,exynos4210-clock", exynos4210_clk_init); +static void __init exynos4212_clk_init(struct device_node *np) +{ + exynos4_clk_init(np, EXYNOS4212); +} +CLK_OF_DECLARE(exynos4212_clk, "samsung,exynos4212-clock", exynos4212_clk_init); + static void __init exynos4412_clk_init(struct device_node *np) { - exynos4_clk_init(np, EXYNOS4X12); + exynos4_clk_init(np, EXYNOS4412); } CLK_OF_DECLARE(exynos4412_clk, "samsung,exynos4412-clock", exynos4412_clk_init); diff --git a/drivers/clk/sifive/sifive-prci.c b/drivers/clk/sifive/sifive-prci.c index 916d2fc28b9c101b9b2a1a3c901adff834d6e0ee..e317f3454e93345b13307ed094a03ef342784333 100644 --- a/drivers/clk/sifive/sifive-prci.c +++ b/drivers/clk/sifive/sifive-prci.c @@ -567,7 +567,6 @@ static int __prci_register_clocks(struct device *dev, struct __prci_data *pd, static int sifive_prci_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; - struct resource *res; struct __prci_data *pd; const struct prci_clk_desc *desc; int r; @@ -578,8 +577,7 @@ static int sifive_prci_probe(struct platform_device *pdev) if (!pd) return -ENOMEM; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - pd->va = devm_ioremap_resource(dev, res); + pd->va = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(pd->va)) return PTR_ERR(pd->va); diff --git a/drivers/clk/socfpga/clk-gate.c b/drivers/clk/socfpga/clk-gate.c index 32ccda960f280c3b421c65802c753521e2419386..8dd601bd85389fb2faf6a9555927c13925d2d482 100644 --- a/drivers/clk/socfpga/clk-gate.c +++ b/drivers/clk/socfpga/clk-gate.c @@ -110,6 +110,7 @@ static unsigned long socfpga_clk_recalc_rate(struct clk_hw *hwclk, static struct clk_ops gateclk_ops = { .recalc_rate = socfpga_clk_recalc_rate, + .determine_rate = clk_hw_determine_rate_no_reparent, .get_parent = socfpga_clk_get_parent, .set_parent = socfpga_clk_set_parent, }; diff --git a/drivers/clk/sprd/composite.c b/drivers/clk/sprd/composite.c index ebb644820b1eb776d0b487fadf0753a56cde5d05..ad6b6383e21fe58f9dca67bc9422ce60093b51e5 100644 --- a/drivers/clk/sprd/composite.c +++ b/drivers/clk/sprd/composite.c @@ -9,13 +9,12 @@ #include "composite.h" -static long sprd_comp_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *parent_rate) +static int sprd_comp_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) { struct sprd_comp *cc = hw_to_sprd_comp(hw); - return sprd_div_helper_round_rate(&cc->common, &cc->div, - rate, parent_rate); + return divider_determine_rate(hw, req, NULL, cc->div.width, 0); } static unsigned long sprd_comp_recalc_rate(struct clk_hw *hw, @@ -53,7 +52,7 @@ const struct clk_ops sprd_comp_ops = { .get_parent = sprd_comp_get_parent, .set_parent = sprd_comp_set_parent, - .round_rate = sprd_comp_round_rate, + .determine_rate = sprd_comp_determine_rate, .recalc_rate = sprd_comp_recalc_rate, .set_rate = sprd_comp_set_rate, }; diff --git a/drivers/clk/sprd/div.c b/drivers/clk/sprd/div.c index 7621a1d1ab9c1a366829142ca9f0ac71eb216f89..c7261630cab410be5da31a2aa1130bd9ff2ed419 100644 --- a/drivers/clk/sprd/div.c +++ b/drivers/clk/sprd/div.c @@ -9,23 +9,13 @@ #include "div.h" -long sprd_div_helper_round_rate(struct sprd_clk_common *common, - const struct sprd_div_internal *div, - unsigned long rate, - unsigned long *parent_rate) -{ - return divider_round_rate(&common->hw, rate, parent_rate, - NULL, div->width, 0); -} -EXPORT_SYMBOL_GPL(sprd_div_helper_round_rate); - static long sprd_div_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *parent_rate) { struct sprd_div *cd = hw_to_sprd_div(hw); - return sprd_div_helper_round_rate(&cd->common, &cd->div, - rate, parent_rate); + return divider_round_rate(&cd->common.hw, rate, parent_rate, NULL, + cd->div.width, 0); } unsigned long sprd_div_helper_recalc_rate(struct sprd_clk_common *common, diff --git a/drivers/clk/sprd/div.h b/drivers/clk/sprd/div.h index 6acfe6b179fc20113e3f8ed5bd3fcc17a7f00384..f5d614b3dcf14e783266f04858a46ffc77523ef3 100644 --- a/drivers/clk/sprd/div.h +++ b/drivers/clk/sprd/div.h @@ -64,11 +64,6 @@ static inline struct sprd_div *hw_to_sprd_div(const struct clk_hw *hw) return container_of(common, struct sprd_div, common); } -long sprd_div_helper_round_rate(struct sprd_clk_common *common, - const struct sprd_div_internal *div, - unsigned long rate, - unsigned long *parent_rate); - unsigned long sprd_div_helper_recalc_rate(struct sprd_clk_common *common, const struct sprd_div_internal *div, unsigned long parent_rate); diff --git a/drivers/clk/st/clk-flexgen.c b/drivers/clk/st/clk-flexgen.c index 7ae4f656191e7244c3f799c48f18cc0bdc202115..5292208c4dd8b45edfe7c2722e934dd0299c6d34 100644 --- a/drivers/clk/st/clk-flexgen.c +++ b/drivers/clk/st/clk-flexgen.c @@ -119,20 +119,21 @@ clk_best_div(unsigned long parent_rate, unsigned long rate) return parent_rate / rate + ((rate > (2*(parent_rate % rate))) ? 0 : 1); } -static long flexgen_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *prate) +static int flexgen_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) { unsigned long div; /* Round div according to exact prate and wished rate */ - div = clk_best_div(*prate, rate); + div = clk_best_div(req->best_parent_rate, req->rate); if (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) { - *prate = rate * div; - return rate; + req->best_parent_rate = req->rate * div; + return 0; } - return *prate / div; + req->rate = req->best_parent_rate / div; + return 0; } static unsigned long flexgen_recalc_rate(struct clk_hw *hw, @@ -197,7 +198,7 @@ static const struct clk_ops flexgen_ops = { .is_enabled = flexgen_is_enabled, .get_parent = flexgen_get_parent, .set_parent = flexgen_set_parent, - .round_rate = flexgen_round_rate, + .determine_rate = flexgen_determine_rate, .recalc_rate = flexgen_recalc_rate, .set_rate = flexgen_set_rate, }; diff --git a/drivers/clk/stm32/clk-stm32-core.c b/drivers/clk/stm32/clk-stm32-core.c index 45a279e73779e6f5abb5d0e662a5c5b19737bd04..d5aa09e9fce4c2cd816f7dd75f9da3fa3c84b8dd 100644 --- a/drivers/clk/stm32/clk-stm32-core.c +++ b/drivers/clk/stm32/clk-stm32-core.c @@ -275,6 +275,7 @@ static int clk_stm32_mux_set_parent(struct clk_hw *hw, u8 index) } const struct clk_ops clk_stm32_mux_ops = { + .determine_rate = __clk_mux_determine_rate, .get_parent = clk_stm32_mux_get_parent, .set_parent = clk_stm32_mux_set_parent, }; @@ -425,15 +426,15 @@ static unsigned long clk_stm32_composite_recalc_rate(struct clk_hw *hw, composite->div_id, parent_rate); } -static long clk_stm32_composite_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *prate) +static int clk_stm32_composite_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) { struct clk_stm32_composite *composite = to_clk_stm32_composite(hw); - const struct stm32_div_cfg *divider; + unsigned long rate; if (composite->div_id == NO_STM32_DIV) - return rate; + return 0; divider = &composite->clock_data->dividers[composite->div_id]; @@ -444,14 +445,24 @@ static long clk_stm32_composite_round_rate(struct clk_hw *hw, unsigned long rate val = readl(composite->base + divider->offset) >> divider->shift; val &= clk_div_mask(divider->width); - return divider_ro_round_rate(hw, rate, prate, divider->table, - divider->width, divider->flags, - val); + rate = divider_ro_round_rate(hw, req->rate, &req->best_parent_rate, + divider->table, divider->width, divider->flags, + val); + if (rate < 0) + return rate; + + req->rate = rate; + return 0; } - return divider_round_rate_parent(hw, clk_hw_get_parent(hw), - rate, prate, divider->table, - divider->width, divider->flags); + rate = divider_round_rate_parent(hw, clk_hw_get_parent(hw), + req->rate, &req->best_parent_rate, + divider->table, divider->width, divider->flags); + if (rate < 0) + return rate; + + req->rate = rate; + return 0; } static u8 clk_stm32_composite_get_parent(struct clk_hw *hw) @@ -601,7 +612,7 @@ static void clk_stm32_composite_disable_unused(struct clk_hw *hw) const struct clk_ops clk_stm32_composite_ops = { .set_rate = clk_stm32_composite_set_rate, .recalc_rate = clk_stm32_composite_recalc_rate, - .round_rate = clk_stm32_composite_round_rate, + .determine_rate = clk_stm32_composite_determine_rate, .get_parent = clk_stm32_composite_get_parent, .set_parent = clk_stm32_composite_set_parent, .enable = clk_stm32_composite_gate_enable, diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c index 41519185600a09c4503591dcd1caa1912b8f5f65..eb36f8f77d5540d630c0bbeac773a8bf5efed516 100644 --- a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c +++ b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c @@ -528,11 +528,18 @@ static SUNXI_CCU_M_WITH_MUX_GATE(de_clk, "de", de_parents, 0x104, 0, 4, 24, 3, BIT(31), CLK_SET_RATE_PARENT); +/* + * DSI output seems to work only when PLL_MIPI selected. Set it and prevent + * the mux from reparenting. + */ +#define SUN50I_A64_TCON0_CLK_REG 0x118 + static const char * const tcon0_parents[] = { "pll-mipi", "pll-video0-2x" }; static const u8 tcon0_table[] = { 0, 2, }; static SUNXI_CCU_MUX_TABLE_WITH_GATE(tcon0_clk, "tcon0", tcon0_parents, tcon0_table, 0x118, 24, 3, BIT(31), - CLK_SET_RATE_PARENT); + CLK_SET_RATE_PARENT | + CLK_SET_RATE_NO_REPARENT); static const char * const tcon1_parents[] = { "pll-video0", "pll-video1" }; static const u8 tcon1_table[] = { 0, 2, }; @@ -953,6 +960,11 @@ static int sun50i_a64_ccu_probe(struct platform_device *pdev) writel(0x515, reg + SUN50I_A64_PLL_MIPI_REG); + /* Set PLL MIPI as parent for TCON0 */ + val = readl(reg + SUN50I_A64_TCON0_CLK_REG); + val &= ~GENMASK(26, 24); + writel(val | (0 << 24), reg + SUN50I_A64_TCON0_CLK_REG); + ret = devm_sunxi_ccu_probe(&pdev->dev, reg, &sun50i_a64_ccu_desc); if (ret) return ret; diff --git a/drivers/clk/tegra/clk-bpmp.c b/drivers/clk/tegra/clk-bpmp.c index 0ecdffaa6b16a6d3ca2f7bc8731968c804fcbc09..a9f3fb448de62070f8897421e2be174b25a4593a 100644 --- a/drivers/clk/tegra/clk-bpmp.c +++ b/drivers/clk/tegra/clk-bpmp.c @@ -286,6 +286,7 @@ static const struct clk_ops tegra_bpmp_clk_mux_ops = { .unprepare = tegra_bpmp_clk_unprepare, .is_prepared = tegra_bpmp_clk_is_prepared, .recalc_rate = tegra_bpmp_clk_recalc_rate, + .determine_rate = clk_hw_determine_rate_no_reparent, .set_parent = tegra_bpmp_clk_set_parent, .get_parent = tegra_bpmp_clk_get_parent, }; diff --git a/drivers/clk/tegra/clk-periph.c b/drivers/clk/tegra/clk-periph.c index 79ca3aa072b70747f8304c8aa7164fbd30fe1662..0626650a7011cc877c084fd93ba961c6fbd311cc 100644 --- a/drivers/clk/tegra/clk-periph.c +++ b/drivers/clk/tegra/clk-periph.c @@ -45,16 +45,22 @@ static unsigned long clk_periph_recalc_rate(struct clk_hw *hw, return div_ops->recalc_rate(div_hw, parent_rate); } -static long clk_periph_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *prate) +static int clk_periph_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) { struct tegra_clk_periph *periph = to_clk_periph(hw); const struct clk_ops *div_ops = periph->div_ops; struct clk_hw *div_hw = &periph->divider.hw; + unsigned long rate; __clk_hw_set_clk(div_hw, hw); - return div_ops->round_rate(div_hw, rate, prate); + rate = div_ops->round_rate(div_hw, req->rate, &req->best_parent_rate); + if (rate < 0) + return rate; + + req->rate = rate; + return 0; } static int clk_periph_set_rate(struct clk_hw *hw, unsigned long rate, @@ -130,7 +136,7 @@ const struct clk_ops tegra_clk_periph_ops = { .get_parent = clk_periph_get_parent, .set_parent = clk_periph_set_parent, .recalc_rate = clk_periph_recalc_rate, - .round_rate = clk_periph_round_rate, + .determine_rate = clk_periph_determine_rate, .set_rate = clk_periph_set_rate, .is_enabled = clk_periph_is_enabled, .enable = clk_periph_enable, @@ -140,6 +146,7 @@ const struct clk_ops tegra_clk_periph_ops = { }; static const struct clk_ops tegra_clk_periph_nodiv_ops = { + .determine_rate = clk_hw_determine_rate_no_reparent, .get_parent = clk_periph_get_parent, .set_parent = clk_periph_set_parent, .is_enabled = clk_periph_is_enabled, @@ -153,7 +160,7 @@ static const struct clk_ops tegra_clk_periph_no_gate_ops = { .get_parent = clk_periph_get_parent, .set_parent = clk_periph_set_parent, .recalc_rate = clk_periph_recalc_rate, - .round_rate = clk_periph_round_rate, + .determine_rate = clk_periph_determine_rate, .set_rate = clk_periph_set_rate, .restore_context = clk_periph_restore_context, }; diff --git a/drivers/clk/tegra/clk-super.c b/drivers/clk/tegra/clk-super.c index a98a420398fa1d5779125707f85240f145119c24..7ec47942720c5aa43f35107369b42804f4847b97 100644 --- a/drivers/clk/tegra/clk-super.c +++ b/drivers/clk/tegra/clk-super.c @@ -136,20 +136,28 @@ static void clk_super_mux_restore_context(struct clk_hw *hw) } static const struct clk_ops tegra_clk_super_mux_ops = { + .determine_rate = clk_hw_determine_rate_no_reparent, .get_parent = clk_super_get_parent, .set_parent = clk_super_set_parent, .restore_context = clk_super_mux_restore_context, }; -static long clk_super_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *parent_rate) +static int clk_super_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) { struct tegra_clk_super_mux *super = to_clk_super_mux(hw); struct clk_hw *div_hw = &super->frac_div.hw; + unsigned long rate; __clk_hw_set_clk(div_hw, hw); - return super->div_ops->round_rate(div_hw, rate, parent_rate); + rate = super->div_ops->round_rate(div_hw, req->rate, + &req->best_parent_rate); + if (rate < 0) + return rate; + + req->rate = rate; + return 0; } static unsigned long clk_super_recalc_rate(struct clk_hw *hw, @@ -192,7 +200,7 @@ const struct clk_ops tegra_clk_super_ops = { .get_parent = clk_super_get_parent, .set_parent = clk_super_set_parent, .set_rate = clk_super_set_rate, - .round_rate = clk_super_round_rate, + .determine_rate = clk_super_determine_rate, .recalc_rate = clk_super_recalc_rate, .restore_context = clk_super_restore_context, }; diff --git a/drivers/clk/tegra/clk-tegra-super-cclk.c b/drivers/clk/tegra/clk-tegra-super-cclk.c index 68d7bcd5fc8a12cc202360913860385682dc226c..3b22a4d0dffcb2f81d549e06ee65a4173a582d2f 100644 --- a/drivers/clk/tegra/clk-tegra-super-cclk.c +++ b/drivers/clk/tegra/clk-tegra-super-cclk.c @@ -86,9 +86,18 @@ static int cclk_super_determine_rate(struct clk_hw *hw, if (rate <= pllp_rate) { if (super->flags & TEGRA20_SUPER_CLK) rate = pllp_rate; - else - rate = tegra_clk_super_ops.round_rate(hw, rate, - &pllp_rate); + else { + struct clk_rate_request parent = { + .rate = req->rate, + .best_parent_rate = pllp_rate, + }; + + clk_hw_get_rate_range(hw, &parent.min_rate, + &parent.max_rate); + tegra_clk_super_ops.determine_rate(hw, &parent); + pllp_rate = parent.best_parent_rate; + rate = parent.rate; + } req->best_parent_rate = pllp_rate; req->best_parent_hw = pllp_hw; diff --git a/drivers/clk/tegra/clk-tegra124-emc.c b/drivers/clk/tegra/clk-tegra124-emc.c index 219c80653dbdb2e32ed9e9d0602e8b6cc5c90be7..2a6db0434281594cd5cef35d2ee8cd5f0760bacd 100644 --- a/drivers/clk/tegra/clk-tegra124-emc.c +++ b/drivers/clk/tegra/clk-tegra124-emc.c @@ -464,6 +464,7 @@ static int load_timings_from_dt(struct tegra_clk_emc *tegra, err = load_one_timing_from_dt(tegra, timing, child); if (err) { of_node_put(child); + kfree(tegra->timings); return err; } @@ -515,6 +516,7 @@ struct clk *tegra124_clk_register_emc(void __iomem *base, struct device_node *np err = load_timings_from_dt(tegra, node, node_ram_code); if (err) { of_node_put(node); + kfree(tegra); return ERR_PTR(err); } } diff --git a/drivers/clk/ti/clkctrl.c b/drivers/clk/ti/clkctrl.c index b6fce916967cea8c9e5dd000004983830648ec82..8c40f10280b74e0ee7a5e466b04ca5b51af21d6a 100644 --- a/drivers/clk/ti/clkctrl.c +++ b/drivers/clk/ti/clkctrl.c @@ -258,6 +258,9 @@ static const char * __init clkctrl_get_clock_name(struct device_node *np, if (clkctrl_name && !legacy_naming) { clock_name = kasprintf(GFP_KERNEL, "%s-clkctrl:%04x:%d", clkctrl_name, offset, index); + if (!clock_name) + return NULL; + strreplace(clock_name, '_', '-'); return clock_name; @@ -586,6 +589,10 @@ static void __init _ti_omap4_clkctrl_setup(struct device_node *node) if (clkctrl_name) { provider->clkdm_name = kasprintf(GFP_KERNEL, "%s_clkdm", clkctrl_name); + if (!provider->clkdm_name) { + kfree(provider); + return; + } goto clkdm_found; } diff --git a/drivers/clk/ux500/clk-prcmu.c b/drivers/clk/ux500/clk-prcmu.c index 4deb37f19a7ce331d039fd4c0463265457b48b22..5cbf24c94606081b0ec18c8aaa201ef89b54edf0 100644 --- a/drivers/clk/ux500/clk-prcmu.c +++ b/drivers/clk/ux500/clk-prcmu.c @@ -344,6 +344,7 @@ static const struct clk_ops clk_prcmu_clkout_ops = { .prepare = clk_prcmu_clkout_prepare, .unprepare = clk_prcmu_clkout_unprepare, .recalc_rate = clk_prcmu_clkout_recalc_rate, + .determine_rate = clk_hw_determine_rate_no_reparent, .get_parent = clk_prcmu_clkout_get_parent, .set_parent = clk_prcmu_clkout_set_parent, }; diff --git a/drivers/clk/ux500/clk-sysctrl.c b/drivers/clk/ux500/clk-sysctrl.c index 702f2f8b43fa1033ff32c55dad2a300477da3d4a..ba3258c88d28e101e3a37b737e2b58e9b583424a 100644 --- a/drivers/clk/ux500/clk-sysctrl.c +++ b/drivers/clk/ux500/clk-sysctrl.c @@ -110,6 +110,7 @@ static const struct clk_ops clk_sysctrl_gate_fixed_rate_ops = { }; static const struct clk_ops clk_sysctrl_set_parent_ops = { + .determine_rate = clk_hw_determine_rate_no_reparent, .set_parent = clk_sysctrl_set_parent, .get_parent = clk_sysctrl_get_parent, }; diff --git a/drivers/clk/versatile/clk-sp810.c b/drivers/clk/versatile/clk-sp810.c index caf0cd2fb5b6d88f658fddd720ea833bc610c2ab..45adac1b4630f03497fef1f7f8d087c9e7ed3590 100644 --- a/drivers/clk/versatile/clk-sp810.c +++ b/drivers/clk/versatile/clk-sp810.c @@ -63,6 +63,7 @@ static int clk_sp810_timerclken_set_parent(struct clk_hw *hw, u8 index) } static const struct clk_ops clk_sp810_timerclken_ops = { + .determine_rate = clk_hw_determine_rate_no_reparent, .get_parent = clk_sp810_timerclken_get_parent, .set_parent = clk_sp810_timerclken_set_parent, }; diff --git a/drivers/clk/xilinx/clk-xlnx-clock-wizard.c b/drivers/clk/xilinx/clk-xlnx-clock-wizard.c index e83f104fad029815ee245531cdac8413eaef2349..d56822ce6126c11939d4f628649eadacf0294e22 100644 --- a/drivers/clk/xilinx/clk-xlnx-clock-wizard.c +++ b/drivers/clk/xilinx/clk-xlnx-clock-wizard.c @@ -525,7 +525,7 @@ static struct clk *clk_wzrd_register_divider(struct device *dev, hw = &div->hw; ret = devm_clk_hw_register(dev, hw); if (ret) - hw = ERR_PTR(ret); + return ERR_PTR(ret); return hw->clk; } @@ -648,6 +648,11 @@ static int clk_wzrd_probe(struct platform_device *pdev) } clkout_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%s_out0", dev_name(&pdev->dev)); + if (!clkout_name) { + ret = -ENOMEM; + goto err_disable_clk; + } + if (nr_outputs == 1) { clk_wzrd->clkout[0] = clk_wzrd_register_divider (&pdev->dev, clkout_name, diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index 526382dc74822ab72decbff0c1f0e2476bce10ac..c4d671a5a13d9209e3ceec11e9a4294e669cc7c4 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -612,6 +612,15 @@ config TIMER_IMX_SYS_CTR Enable this option to use i.MX system counter timer as a clockevent. +config CLKSRC_LOONGSON1_PWM + bool "Clocksource using Loongson1 PWM" + depends on MACH_LOONGSON32 || COMPILE_TEST + select MIPS_EXTERNAL_TIMER + select TIMER_OF + help + Enable this option to use Loongson1 PWM timer as clocksource + instead of the performance counter. + config CLKSRC_ST_LPC bool "Low power clocksource found in the LPC" if COMPILE_TEST select TIMER_OF if OF diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile index f12d3987a96031631e794acd27382d4b921c4484..5d93c9e3fc558c86d868340ea9018edb561a5c8f 100644 --- a/drivers/clocksource/Makefile +++ b/drivers/clocksource/Makefile @@ -89,3 +89,4 @@ obj-$(CONFIG_MICROCHIP_PIT64B) += timer-microchip-pit64b.o obj-$(CONFIG_MSC313E_TIMER) += timer-msc313e.o obj-$(CONFIG_GOLDFISH_TIMER) += timer-goldfish.o obj-$(CONFIG_GXP_TIMER) += timer-gxp.o +obj-$(CONFIG_CLKSRC_LOONGSON1_PWM) += timer-loongson1-pwm.o diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index e09d4427f60499ea7d287d1d996aa5208ecbca7a..e733a2a1927a402f70e14585a2f98a76e6767cb7 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c @@ -191,22 +191,40 @@ u32 arch_timer_reg_read(int access, enum arch_timer_reg reg, return val; } -static notrace u64 arch_counter_get_cntpct_stable(void) +static noinstr u64 raw_counter_get_cntpct_stable(void) { return __arch_counter_get_cntpct_stable(); } -static notrace u64 arch_counter_get_cntpct(void) +static notrace u64 arch_counter_get_cntpct_stable(void) +{ + u64 val; + preempt_disable_notrace(); + val = __arch_counter_get_cntpct_stable(); + preempt_enable_notrace(); + return val; +} + +static noinstr u64 arch_counter_get_cntpct(void) { return __arch_counter_get_cntpct(); } -static notrace u64 arch_counter_get_cntvct_stable(void) +static noinstr u64 raw_counter_get_cntvct_stable(void) { return __arch_counter_get_cntvct_stable(); } -static notrace u64 arch_counter_get_cntvct(void) +static notrace u64 arch_counter_get_cntvct_stable(void) +{ + u64 val; + preempt_disable_notrace(); + val = __arch_counter_get_cntvct_stable(); + preempt_enable_notrace(); + return val; +} + +static noinstr u64 arch_counter_get_cntvct(void) { return __arch_counter_get_cntvct(); } @@ -753,14 +771,14 @@ static int arch_timer_set_next_event_phys(unsigned long evt, return 0; } -static u64 arch_counter_get_cnt_mem(struct arch_timer *t, int offset_lo) +static noinstr u64 arch_counter_get_cnt_mem(struct arch_timer *t, int offset_lo) { u32 cnt_lo, cnt_hi, tmp_hi; do { - cnt_hi = readl_relaxed(t->base + offset_lo + 4); - cnt_lo = readl_relaxed(t->base + offset_lo); - tmp_hi = readl_relaxed(t->base + offset_lo + 4); + cnt_hi = __le32_to_cpu((__le32 __force)__raw_readl(t->base + offset_lo + 4)); + cnt_lo = __le32_to_cpu((__le32 __force)__raw_readl(t->base + offset_lo)); + tmp_hi = __le32_to_cpu((__le32 __force)__raw_readl(t->base + offset_lo + 4)); } while (cnt_hi != tmp_hi); return ((u64) cnt_hi << 32) | cnt_lo; @@ -1060,7 +1078,7 @@ bool arch_timer_evtstrm_available(void) return cpumask_test_cpu(raw_smp_processor_id(), &evtstrm_available); } -static u64 arch_counter_get_cntvct_mem(void) +static noinstr u64 arch_counter_get_cntvct_mem(void) { return arch_counter_get_cnt_mem(arch_timer_mem, CNTVCT_LO); } @@ -1074,6 +1092,7 @@ struct arch_timer_kvm_info *arch_timer_get_kvm_info(void) static void __init arch_counter_register(unsigned type) { + u64 (*scr)(void); u64 start_count; int width; @@ -1083,21 +1102,28 @@ static void __init arch_counter_register(unsigned type) if ((IS_ENABLED(CONFIG_ARM64) && !is_hyp_mode_available()) || arch_timer_uses_ppi == ARCH_TIMER_VIRT_PPI) { - if (arch_timer_counter_has_wa()) + if (arch_timer_counter_has_wa()) { rd = arch_counter_get_cntvct_stable; - else + scr = raw_counter_get_cntvct_stable; + } else { rd = arch_counter_get_cntvct; + scr = arch_counter_get_cntvct; + } } else { - if (arch_timer_counter_has_wa()) + if (arch_timer_counter_has_wa()) { rd = arch_counter_get_cntpct_stable; - else + scr = raw_counter_get_cntpct_stable; + } else { rd = arch_counter_get_cntpct; + scr = arch_counter_get_cntpct; + } } arch_timer_read_counter = rd; clocksource_counter.vdso_clock_mode = vdso_default; } else { arch_timer_read_counter = arch_counter_get_cntvct_mem; + scr = arch_counter_get_cntvct_mem; } width = arch_counter_get_width(); @@ -1113,7 +1139,7 @@ static void __init arch_counter_register(unsigned type) timecounter_init(&arch_timer_kvm_info.timecounter, &cyclecounter, start_count); - sched_clock_register(arch_timer_read_counter, width, arch_timer_rate); + sched_clock_register(scr, width, arch_timer_rate); } static void arch_timer_stop(struct clock_event_device *clk) diff --git a/drivers/clocksource/hyperv_timer.c b/drivers/clocksource/hyperv_timer.c index bcd9042a0c9f460a4eeece614d0b032176ccc620..e56307a81f4dab0b955154d41eaf336a156a6918 100644 --- a/drivers/clocksource/hyperv_timer.c +++ b/drivers/clocksource/hyperv_timer.c @@ -365,6 +365,20 @@ void hv_stimer_global_cleanup(void) } EXPORT_SYMBOL_GPL(hv_stimer_global_cleanup); +static __always_inline u64 read_hv_clock_msr(void) +{ + /* + * Read the partition counter to get the current tick count. This count + * is set to 0 when the partition is created and is incremented in 100 + * nanosecond units. + * + * Use hv_raw_get_register() because this function is used from + * noinstr. Notable; while HV_REGISTER_TIME_REF_COUNT is a synthetic + * register it doesn't need the GHCB path. + */ + return hv_raw_get_register(HV_REGISTER_TIME_REF_COUNT); +} + /* * Code and definitions for the Hyper-V clocksources. Two * clocksources are defined: one that reads the Hyper-V defined MSR, and @@ -393,14 +407,20 @@ struct ms_hyperv_tsc_page *hv_get_tsc_page(void) } EXPORT_SYMBOL_GPL(hv_get_tsc_page); -static u64 notrace read_hv_clock_tsc(void) +static __always_inline u64 read_hv_clock_tsc(void) { - u64 current_tick = hv_read_tsc_page(hv_get_tsc_page()); + u64 cur_tsc, time; - if (current_tick == U64_MAX) - current_tick = hv_get_register(HV_REGISTER_TIME_REF_COUNT); + /* + * The Hyper-V Top-Level Function Spec (TLFS), section Timers, + * subsection Refererence Counter, guarantees that the TSC and MSR + * times are in sync and monotonic. Therefore we can fall back + * to the MSR in case the TSC page indicates unavailability. + */ + if (!hv_read_tsc_page_tsc(tsc_page, &cur_tsc, &time)) + time = read_hv_clock_msr(); - return current_tick; + return time; } static u64 notrace read_hv_clock_tsc_cs(struct clocksource *arg) @@ -408,7 +428,7 @@ static u64 notrace read_hv_clock_tsc_cs(struct clocksource *arg) return read_hv_clock_tsc(); } -static u64 notrace read_hv_sched_clock_tsc(void) +static u64 noinstr read_hv_sched_clock_tsc(void) { return (read_hv_clock_tsc() - hv_sched_clock_offset) * (NSEC_PER_SEC / HV_CLOCK_HZ); @@ -460,30 +480,14 @@ static struct clocksource hyperv_cs_tsc = { #endif }; -static u64 notrace read_hv_clock_msr(void) -{ - /* - * Read the partition counter to get the current tick count. This count - * is set to 0 when the partition is created and is incremented in - * 100 nanosecond units. - */ - return hv_get_register(HV_REGISTER_TIME_REF_COUNT); -} - static u64 notrace read_hv_clock_msr_cs(struct clocksource *arg) { return read_hv_clock_msr(); } -static u64 notrace read_hv_sched_clock_msr(void) -{ - return (read_hv_clock_msr() - hv_sched_clock_offset) * - (NSEC_PER_SEC / HV_CLOCK_HZ); -} - static struct clocksource hyperv_cs_msr = { .name = "hyperv_clocksource_msr", - .rating = 500, + .rating = 495, .read = read_hv_clock_msr_cs, .mask = CLOCKSOURCE_MASK(64), .flags = CLOCK_SOURCE_IS_CONTINUOUS, @@ -513,7 +517,7 @@ static __always_inline void hv_setup_sched_clock(void *sched_clock) static __always_inline void hv_setup_sched_clock(void *sched_clock) {} #endif /* CONFIG_GENERIC_SCHED_CLOCK */ -static bool __init hv_init_tsc_clocksource(void) +static void __init hv_init_tsc_clocksource(void) { union hv_reference_tsc_msr tsc_msr; @@ -524,17 +528,14 @@ static bool __init hv_init_tsc_clocksource(void) * Hyper-V Reference TSC rating, causing the generic TSC to be used. * TSC_INVARIANT is not offered on ARM64, so the Hyper-V Reference * TSC will be preferred over the virtualized ARM64 arch counter. - * While the Hyper-V MSR clocksource won't be used since the - * Reference TSC clocksource is present, change its rating as - * well for consistency. */ if (ms_hyperv.features & HV_ACCESS_TSC_INVARIANT) { hyperv_cs_tsc.rating = 250; - hyperv_cs_msr.rating = 250; + hyperv_cs_msr.rating = 245; } if (!(ms_hyperv.features & HV_MSR_REFERENCE_TSC_AVAILABLE)) - return false; + return; hv_read_reference_counter = read_hv_clock_tsc; @@ -565,33 +566,34 @@ static bool __init hv_init_tsc_clocksource(void) clocksource_register_hz(&hyperv_cs_tsc, NSEC_PER_SEC/100); - hv_sched_clock_offset = hv_read_reference_counter(); - hv_setup_sched_clock(read_hv_sched_clock_tsc); - - return true; + /* + * If TSC is invariant, then let it stay as the sched clock since it + * will be faster than reading the TSC page. But if not invariant, use + * the TSC page so that live migrations across hosts with different + * frequencies is handled correctly. + */ + if (!(ms_hyperv.features & HV_ACCESS_TSC_INVARIANT)) { + hv_sched_clock_offset = hv_read_reference_counter(); + hv_setup_sched_clock(read_hv_sched_clock_tsc); + } } void __init hv_init_clocksource(void) { /* - * Try to set up the TSC page clocksource. If it succeeds, we're - * done. Otherwise, set up the MSR clocksource. At least one of - * these will always be available except on very old versions of - * Hyper-V on x86. In that case we won't have a Hyper-V + * Try to set up the TSC page clocksource, then the MSR clocksource. + * At least one of these will always be available except on very old + * versions of Hyper-V on x86. In that case we won't have a Hyper-V * clocksource, but Linux will still run with a clocksource based * on the emulated PIT or LAPIC timer. + * + * Never use the MSR clocksource as sched clock. It's too slow. + * Better to use the native sched clock as the fallback. */ - if (hv_init_tsc_clocksource()) - return; - - if (!(ms_hyperv.features & HV_MSR_TIME_REF_COUNT_AVAILABLE)) - return; - - hv_read_reference_counter = read_hv_clock_msr; - clocksource_register_hz(&hyperv_cs_msr, NSEC_PER_SEC/100); + hv_init_tsc_clocksource(); - hv_sched_clock_offset = hv_read_reference_counter(); - hv_setup_sched_clock(read_hv_sched_clock_msr); + if (ms_hyperv.features & HV_MSR_TIME_REF_COUNT_AVAILABLE) + clocksource_register_hz(&hyperv_cs_msr, NSEC_PER_SEC/100); } void __init hv_remap_tsc_clocksource(void) diff --git a/drivers/clocksource/ingenic-timer.c b/drivers/clocksource/ingenic-timer.c index 089ce64b1c3f0a31c57cc5c1172d3b3368aa7a8f..154ee5f7954aa18751d9ff1e22504d2cd3f98543 100644 --- a/drivers/clocksource/ingenic-timer.c +++ b/drivers/clocksource/ingenic-timer.c @@ -369,7 +369,7 @@ static int __init ingenic_tcu_probe(struct platform_device *pdev) return 0; } -static int __maybe_unused ingenic_tcu_suspend(struct device *dev) +static int ingenic_tcu_suspend(struct device *dev) { struct ingenic_tcu *tcu = dev_get_drvdata(dev); unsigned int cpu; @@ -382,7 +382,7 @@ static int __maybe_unused ingenic_tcu_suspend(struct device *dev) return 0; } -static int __maybe_unused ingenic_tcu_resume(struct device *dev) +static int ingenic_tcu_resume(struct device *dev) { struct ingenic_tcu *tcu = dev_get_drvdata(dev); unsigned int cpu; @@ -406,7 +406,7 @@ static int __maybe_unused ingenic_tcu_resume(struct device *dev) return ret; } -static const struct dev_pm_ops __maybe_unused ingenic_tcu_pm_ops = { +static const struct dev_pm_ops ingenic_tcu_pm_ops = { /* _noirq: We want the TCU clocks to be gated last / ungated first */ .suspend_noirq = ingenic_tcu_suspend, .resume_noirq = ingenic_tcu_resume, @@ -415,9 +415,7 @@ static const struct dev_pm_ops __maybe_unused ingenic_tcu_pm_ops = { static struct platform_driver ingenic_tcu_driver = { .driver = { .name = "ingenic-tcu-timer", -#ifdef CONFIG_PM_SLEEP - .pm = &ingenic_tcu_pm_ops, -#endif + .pm = pm_sleep_ptr(&ingenic_tcu_pm_ops), .of_match_table = ingenic_tcu_of_match, }, }; diff --git a/drivers/clocksource/timer-cadence-ttc.c b/drivers/clocksource/timer-cadence-ttc.c index 4efd0cf3b602d60a304eb0e823b929935efbda47..0d52e28fea4ded6cd8aff791fefce2ad66484fb3 100644 --- a/drivers/clocksource/timer-cadence-ttc.c +++ b/drivers/clocksource/timer-cadence-ttc.c @@ -486,10 +486,10 @@ static int __init ttc_timer_probe(struct platform_device *pdev) * and use it. Note that the event timer uses the interrupt and it's the * 2nd TTC hence the irq_of_parse_and_map(,1) */ - timer_baseaddr = of_iomap(timer, 0); - if (!timer_baseaddr) { + timer_baseaddr = devm_of_iomap(&pdev->dev, timer, 0, NULL); + if (IS_ERR(timer_baseaddr)) { pr_err("ERROR: invalid timer base address\n"); - return -ENXIO; + return PTR_ERR(timer_baseaddr); } irq = irq_of_parse_and_map(timer, 1); @@ -513,20 +513,27 @@ static int __init ttc_timer_probe(struct platform_device *pdev) clk_ce = of_clk_get(timer, clksel); if (IS_ERR(clk_ce)) { pr_err("ERROR: timer input clock not found\n"); - return PTR_ERR(clk_ce); + ret = PTR_ERR(clk_ce); + goto put_clk_cs; } ret = ttc_setup_clocksource(clk_cs, timer_baseaddr, timer_width); if (ret) - return ret; + goto put_clk_ce; ret = ttc_setup_clockevent(clk_ce, timer_baseaddr + 4, irq); if (ret) - return ret; + goto put_clk_ce; pr_info("%pOFn #0 at %p, irq=%d\n", timer, timer_baseaddr, irq); return 0; + +put_clk_ce: + clk_put(clk_ce); +put_clk_cs: + clk_put(clk_cs); + return ret; } static const struct of_device_id ttc_timer_of_match[] = { diff --git a/drivers/clocksource/timer-imx-gpt.c b/drivers/clocksource/timer-imx-gpt.c index ca3e4cbc80c6792cbfd4bb7ca20e855173777b33..28ab4f1a7c713b4869ecc2bf5cc087773745b312 100644 --- a/drivers/clocksource/timer-imx-gpt.c +++ b/drivers/clocksource/timer-imx-gpt.c @@ -16,7 +16,6 @@ #include #include #include -#include /* * There are 4 versions of the timer hardware on Freescale MXC hardware. @@ -25,6 +24,12 @@ * - MX25, MX31, MX35, MX37, MX51, MX6Q(rev1.0) * - MX6DL, MX6SX, MX6Q(rev1.1+) */ +enum imx_gpt_type { + GPT_TYPE_IMX1, /* i.MX1 */ + GPT_TYPE_IMX21, /* i.MX21/27 */ + GPT_TYPE_IMX31, /* i.MX31/35/25/37/51/6Q */ + GPT_TYPE_IMX6DL, /* i.MX6DL/SX/SL */ +}; /* defines common for all i.MX */ #define MXC_TCTL 0x00 @@ -93,13 +98,11 @@ static void imx1_gpt_irq_disable(struct imx_timer *imxtm) tmp = readl_relaxed(imxtm->base + MXC_TCTL); writel_relaxed(tmp & ~MX1_2_TCTL_IRQEN, imxtm->base + MXC_TCTL); } -#define imx21_gpt_irq_disable imx1_gpt_irq_disable static void imx31_gpt_irq_disable(struct imx_timer *imxtm) { writel_relaxed(0, imxtm->base + V2_IR); } -#define imx6dl_gpt_irq_disable imx31_gpt_irq_disable static void imx1_gpt_irq_enable(struct imx_timer *imxtm) { @@ -108,13 +111,11 @@ static void imx1_gpt_irq_enable(struct imx_timer *imxtm) tmp = readl_relaxed(imxtm->base + MXC_TCTL); writel_relaxed(tmp | MX1_2_TCTL_IRQEN, imxtm->base + MXC_TCTL); } -#define imx21_gpt_irq_enable imx1_gpt_irq_enable static void imx31_gpt_irq_enable(struct imx_timer *imxtm) { writel_relaxed(1<<0, imxtm->base + V2_IR); } -#define imx6dl_gpt_irq_enable imx31_gpt_irq_enable static void imx1_gpt_irq_acknowledge(struct imx_timer *imxtm) { @@ -131,7 +132,6 @@ static void imx31_gpt_irq_acknowledge(struct imx_timer *imxtm) { writel_relaxed(V2_TSTAT_OF1, imxtm->base + V2_TSTAT); } -#define imx6dl_gpt_irq_acknowledge imx31_gpt_irq_acknowledge static void __iomem *sched_clock_reg; @@ -296,7 +296,6 @@ static void imx1_gpt_setup_tctl(struct imx_timer *imxtm) tctl_val = MX1_2_TCTL_FRR | MX1_2_TCTL_CLK_PCLK1 | MXC_TCTL_TEN; writel_relaxed(tctl_val, imxtm->base + MXC_TCTL); } -#define imx21_gpt_setup_tctl imx1_gpt_setup_tctl static void imx31_gpt_setup_tctl(struct imx_timer *imxtm) { @@ -343,10 +342,10 @@ static const struct imx_gpt_data imx21_gpt_data = { .reg_tstat = MX1_2_TSTAT, .reg_tcn = MX1_2_TCN, .reg_tcmp = MX1_2_TCMP, - .gpt_irq_enable = imx21_gpt_irq_enable, - .gpt_irq_disable = imx21_gpt_irq_disable, + .gpt_irq_enable = imx1_gpt_irq_enable, + .gpt_irq_disable = imx1_gpt_irq_disable, .gpt_irq_acknowledge = imx21_gpt_irq_acknowledge, - .gpt_setup_tctl = imx21_gpt_setup_tctl, + .gpt_setup_tctl = imx1_gpt_setup_tctl, .set_next_event = mx1_2_set_next_event, }; @@ -365,9 +364,9 @@ static const struct imx_gpt_data imx6dl_gpt_data = { .reg_tstat = V2_TSTAT, .reg_tcn = V2_TCN, .reg_tcmp = V2_TCMP, - .gpt_irq_enable = imx6dl_gpt_irq_enable, - .gpt_irq_disable = imx6dl_gpt_irq_disable, - .gpt_irq_acknowledge = imx6dl_gpt_irq_acknowledge, + .gpt_irq_enable = imx31_gpt_irq_enable, + .gpt_irq_disable = imx31_gpt_irq_disable, + .gpt_irq_acknowledge = imx31_gpt_irq_acknowledge, .gpt_setup_tctl = imx6dl_gpt_setup_tctl, .set_next_event = v2_set_next_event, }; diff --git a/drivers/clocksource/timer-loongson1-pwm.c b/drivers/clocksource/timer-loongson1-pwm.c new file mode 100644 index 0000000000000000000000000000000000000000..6335fee03017b507b65482d0a310ff52e29c258a --- /dev/null +++ b/drivers/clocksource/timer-loongson1-pwm.c @@ -0,0 +1,236 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Clocksource driver for Loongson-1 SoC + * + * Copyright (c) 2023 Keguang Zhang + */ + +#include +#include +#include +#include "timer-of.h" + +/* Loongson-1 PWM Timer Register Definitions */ +#define PWM_CNTR 0x0 +#define PWM_HRC 0x4 +#define PWM_LRC 0x8 +#define PWM_CTRL 0xc + +/* PWM Control Register Bits */ +#define INT_LRC_EN BIT(11) +#define INT_HRC_EN BIT(10) +#define CNTR_RST BIT(7) +#define INT_SR BIT(6) +#define INT_EN BIT(5) +#define PWM_SINGLE BIT(4) +#define PWM_OE BIT(3) +#define CNT_EN BIT(0) + +#define CNTR_WIDTH 24 + +DEFINE_RAW_SPINLOCK(ls1x_timer_lock); + +struct ls1x_clocksource { + void __iomem *reg_base; + unsigned long ticks_per_jiffy; + struct clocksource clksrc; +}; + +static inline struct ls1x_clocksource *to_ls1x_clksrc(struct clocksource *c) +{ + return container_of(c, struct ls1x_clocksource, clksrc); +} + +static inline void ls1x_pwmtimer_set_period(unsigned int period, + struct timer_of *to) +{ + writel(period, timer_of_base(to) + PWM_LRC); + writel(period, timer_of_base(to) + PWM_HRC); +} + +static inline void ls1x_pwmtimer_clear(struct timer_of *to) +{ + writel(0, timer_of_base(to) + PWM_CNTR); +} + +static inline void ls1x_pwmtimer_start(struct timer_of *to) +{ + writel((INT_EN | PWM_OE | CNT_EN), timer_of_base(to) + PWM_CTRL); +} + +static inline void ls1x_pwmtimer_stop(struct timer_of *to) +{ + writel(0, timer_of_base(to) + PWM_CTRL); +} + +static inline void ls1x_pwmtimer_irq_ack(struct timer_of *to) +{ + int val; + + val = readl(timer_of_base(to) + PWM_CTRL); + val |= INT_SR; + writel(val, timer_of_base(to) + PWM_CTRL); +} + +static irqreturn_t ls1x_clockevent_isr(int irq, void *dev_id) +{ + struct clock_event_device *clkevt = dev_id; + struct timer_of *to = to_timer_of(clkevt); + + ls1x_pwmtimer_irq_ack(to); + ls1x_pwmtimer_clear(to); + ls1x_pwmtimer_start(to); + + clkevt->event_handler(clkevt); + + return IRQ_HANDLED; +} + +static int ls1x_clockevent_set_state_periodic(struct clock_event_device *clkevt) +{ + struct timer_of *to = to_timer_of(clkevt); + + raw_spin_lock(&ls1x_timer_lock); + ls1x_pwmtimer_set_period(timer_of_period(to), to); + ls1x_pwmtimer_clear(to); + ls1x_pwmtimer_start(to); + raw_spin_unlock(&ls1x_timer_lock); + + return 0; +} + +static int ls1x_clockevent_tick_resume(struct clock_event_device *clkevt) +{ + raw_spin_lock(&ls1x_timer_lock); + ls1x_pwmtimer_start(to_timer_of(clkevt)); + raw_spin_unlock(&ls1x_timer_lock); + + return 0; +} + +static int ls1x_clockevent_set_state_shutdown(struct clock_event_device *clkevt) +{ + raw_spin_lock(&ls1x_timer_lock); + ls1x_pwmtimer_stop(to_timer_of(clkevt)); + raw_spin_unlock(&ls1x_timer_lock); + + return 0; +} + +static int ls1x_clockevent_set_next(unsigned long evt, + struct clock_event_device *clkevt) +{ + struct timer_of *to = to_timer_of(clkevt); + + raw_spin_lock(&ls1x_timer_lock); + ls1x_pwmtimer_set_period(evt, to); + ls1x_pwmtimer_clear(to); + ls1x_pwmtimer_start(to); + raw_spin_unlock(&ls1x_timer_lock); + + return 0; +} + +static struct timer_of ls1x_to = { + .flags = TIMER_OF_IRQ | TIMER_OF_BASE | TIMER_OF_CLOCK, + .clkevt = { + .name = "ls1x-pwmtimer", + .features = CLOCK_EVT_FEAT_PERIODIC | + CLOCK_EVT_FEAT_ONESHOT, + .rating = 300, + .set_next_event = ls1x_clockevent_set_next, + .set_state_periodic = ls1x_clockevent_set_state_periodic, + .set_state_oneshot = ls1x_clockevent_set_state_shutdown, + .set_state_shutdown = ls1x_clockevent_set_state_shutdown, + .tick_resume = ls1x_clockevent_tick_resume, + }, + .of_irq = { + .handler = ls1x_clockevent_isr, + .flags = IRQF_TIMER, + }, +}; + +/* + * Since the PWM timer overflows every two ticks, its not very useful + * to just read by itself. So use jiffies to emulate a free + * running counter: + */ +static u64 ls1x_clocksource_read(struct clocksource *cs) +{ + struct ls1x_clocksource *ls1x_cs = to_ls1x_clksrc(cs); + unsigned long flags; + int count; + u32 jifs; + static int old_count; + static u32 old_jifs; + + raw_spin_lock_irqsave(&ls1x_timer_lock, flags); + /* + * Although our caller may have the read side of xtime_lock, + * this is now a seqlock, and we are cheating in this routine + * by having side effects on state that we cannot undo if + * there is a collision on the seqlock and our caller has to + * retry. (Namely, old_jifs and old_count.) So we must treat + * jiffies as volatile despite the lock. We read jiffies + * before latching the timer count to guarantee that although + * the jiffies value might be older than the count (that is, + * the counter may underflow between the last point where + * jiffies was incremented and the point where we latch the + * count), it cannot be newer. + */ + jifs = jiffies; + /* read the count */ + count = readl(ls1x_cs->reg_base + PWM_CNTR); + + /* + * It's possible for count to appear to go the wrong way for this + * reason: + * + * The timer counter underflows, but we haven't handled the resulting + * interrupt and incremented jiffies yet. + * + * Previous attempts to handle these cases intelligently were buggy, so + * we just do the simple thing now. + */ + if (count < old_count && jifs == old_jifs) + count = old_count; + + old_count = count; + old_jifs = jifs; + + raw_spin_unlock_irqrestore(&ls1x_timer_lock, flags); + + return (u64)(jifs * ls1x_cs->ticks_per_jiffy) + count; +} + +static struct ls1x_clocksource ls1x_clocksource = { + .clksrc = { + .name = "ls1x-pwmtimer", + .rating = 300, + .read = ls1x_clocksource_read, + .mask = CLOCKSOURCE_MASK(CNTR_WIDTH), + .flags = CLOCK_SOURCE_IS_CONTINUOUS, + }, +}; + +static int __init ls1x_pwm_clocksource_init(struct device_node *np) +{ + struct timer_of *to = &ls1x_to; + int ret; + + ret = timer_of_init(np, to); + if (ret) + return ret; + + clockevents_config_and_register(&to->clkevt, timer_of_rate(to), + 0x1, GENMASK(CNTR_WIDTH - 1, 0)); + + ls1x_clocksource.reg_base = timer_of_base(to); + ls1x_clocksource.ticks_per_jiffy = timer_of_period(to); + + return clocksource_register_hz(&ls1x_clocksource.clksrc, + timer_of_rate(to)); +} + +TIMER_OF_DECLARE(ls1x_pwm_clocksource, "loongson,ls1b-pwmtimer", + ls1x_pwm_clocksource_init); diff --git a/drivers/clocksource/timer-riscv.c b/drivers/clocksource/timer-riscv.c index 5f0f10c7e2226700ea56686a08e0f85e6a591fcc..da3071b387eb59f6c003fcd7e58062d114d5c54a 100644 --- a/drivers/clocksource/timer-riscv.c +++ b/drivers/clocksource/timer-riscv.c @@ -10,6 +10,7 @@ #define pr_fmt(fmt) "riscv-timer: " fmt +#include #include #include #include @@ -124,61 +125,28 @@ static irqreturn_t riscv_timer_interrupt(int irq, void *dev_id) return IRQ_HANDLED; } -static int __init riscv_timer_init_dt(struct device_node *n) +static int __init riscv_timer_init_common(void) { - int cpuid, error; - unsigned long hartid; - struct device_node *child; + int error; struct irq_domain *domain; + struct fwnode_handle *intc_fwnode = riscv_get_intc_hwnode(); - error = riscv_of_processor_hartid(n, &hartid); - if (error < 0) { - pr_warn("Not valid hartid for node [%pOF] error = [%lu]\n", - n, hartid); - return error; - } - - cpuid = riscv_hartid_to_cpuid(hartid); - if (cpuid < 0) { - pr_warn("Invalid cpuid for hartid [%lu]\n", hartid); - return cpuid; - } - - if (cpuid != smp_processor_id()) - return 0; - - child = of_find_compatible_node(NULL, NULL, "riscv,timer"); - if (child) { - riscv_timer_cannot_wake_cpu = of_property_read_bool(child, - "riscv,timer-cannot-wake-cpu"); - of_node_put(child); - } - - domain = NULL; - child = of_get_compatible_child(n, "riscv,cpu-intc"); - if (!child) { - pr_err("Failed to find INTC node [%pOF]\n", n); - return -ENODEV; - } - domain = irq_find_host(child); - of_node_put(child); + domain = irq_find_matching_fwnode(intc_fwnode, DOMAIN_BUS_ANY); if (!domain) { - pr_err("Failed to find IRQ domain for node [%pOF]\n", n); + pr_err("Failed to find irq_domain for INTC node [%pfwP]\n", + intc_fwnode); return -ENODEV; } riscv_clock_event_irq = irq_create_mapping(domain, RV_IRQ_TIMER); if (!riscv_clock_event_irq) { - pr_err("Failed to map timer interrupt for node [%pOF]\n", n); + pr_err("Failed to map timer interrupt for node [%pfwP]\n", intc_fwnode); return -ENODEV; } - pr_info("%s: Registering clocksource cpuid [%d] hartid [%lu]\n", - __func__, cpuid, hartid); error = clocksource_register_hz(&riscv_clocksource, riscv_timebase); if (error) { - pr_err("RISCV timer register failed [%d] for cpu = [%d]\n", - error, cpuid); + pr_err("RISCV timer registration failed [%d]\n", error); return error; } @@ -207,4 +175,46 @@ static int __init riscv_timer_init_dt(struct device_node *n) return error; } +static int __init riscv_timer_init_dt(struct device_node *n) +{ + int cpuid, error; + unsigned long hartid; + struct device_node *child; + + error = riscv_of_processor_hartid(n, &hartid); + if (error < 0) { + pr_warn("Invalid hartid for node [%pOF] error = [%lu]\n", + n, hartid); + return error; + } + + cpuid = riscv_hartid_to_cpuid(hartid); + if (cpuid < 0) { + pr_warn("Invalid cpuid for hartid [%lu]\n", hartid); + return cpuid; + } + + if (cpuid != smp_processor_id()) + return 0; + + child = of_find_compatible_node(NULL, NULL, "riscv,timer"); + if (child) { + riscv_timer_cannot_wake_cpu = of_property_read_bool(child, + "riscv,timer-cannot-wake-cpu"); + of_node_put(child); + } + + return riscv_timer_init_common(); +} + TIMER_OF_DECLARE(riscv_timer, "riscv", riscv_timer_init_dt); + +#ifdef CONFIG_ACPI +static int __init riscv_timer_acpi_init(struct acpi_table_header *table) +{ + return riscv_timer_init_common(); +} + +TIMER_ACPI_DECLARE(aclint_mtimer, ACPI_SIG_RHCT, riscv_timer_acpi_init); + +#endif diff --git a/drivers/comedi/Kconfig b/drivers/comedi/Kconfig index 9af280735cbaa1db0d59dc154bcb3be7c1cc7df1..7a8d402f05be1668b1d084ad08f4834c8560cd5b 100644 --- a/drivers/comedi/Kconfig +++ b/drivers/comedi/Kconfig @@ -67,6 +67,7 @@ config COMEDI_TEST config COMEDI_PARPORT tristate "Parallel port support" + depends on HAS_IOPORT help Enable support for the standard parallel port. A cheap and easy way to get a few more digital I/O lines. Steal @@ -79,6 +80,7 @@ config COMEDI_PARPORT config COMEDI_SSV_DNP tristate "SSV Embedded Systems DIL/Net-PC support" depends on X86_32 || COMPILE_TEST + depends on HAS_IOPORT help Enable support for SSV Embedded Systems DIL/Net-PC @@ -89,6 +91,7 @@ endif # COMEDI_MISC_DRIVERS menuconfig COMEDI_ISA_DRIVERS bool "Comedi ISA and PC/104 drivers" + depends on ISA help Enable comedi ISA and PC/104 drivers to be built @@ -100,7 +103,8 @@ if COMEDI_ISA_DRIVERS config COMEDI_PCL711 tristate "Advantech PCL-711/711b and ADlink ACL-8112 ISA card support" - select COMEDI_8254 + depends on HAS_IOPORT + depends on COMEDI_8254 help Enable support for Advantech PCL-711 and 711b, ADlink ACL-8112 @@ -161,8 +165,9 @@ config COMEDI_PCL730 config COMEDI_PCL812 tristate "Advantech PCL-812/813 and ADlink ACL-8112/8113/8113/8216" + depends on HAS_IOPORT select COMEDI_ISADMA if ISA_DMA_API - select COMEDI_8254 + depends on COMEDI_8254 help Enable support for Advantech PCL-812/PG, PCL-813/B, ADLink ACL-8112DG/HG/PG, ACL-8113, ACL-8216, ICP DAS A-821PGH/PGL/PGL-NDA, @@ -173,8 +178,9 @@ config COMEDI_PCL812 config COMEDI_PCL816 tristate "Advantech PCL-814 and PCL-816 ISA card support" + depends on HAS_IOPORT select COMEDI_ISADMA if ISA_DMA_API - select COMEDI_8254 + depends on COMEDI_8254 help Enable support for Advantech PCL-814 and PCL-816 ISA cards @@ -183,8 +189,9 @@ config COMEDI_PCL816 config COMEDI_PCL818 tristate "Advantech PCL-718 and PCL-818 ISA card support" + depends on HAS_IOPORT select COMEDI_ISADMA if ISA_DMA_API - select COMEDI_8254 + depends on COMEDI_8254 help Enable support for Advantech PCL-818 ISA cards PCL-818L, PCL-818H, PCL-818HD, PCL-818HG, PCL-818 and PCL-718 @@ -203,7 +210,7 @@ config COMEDI_PCM3724 config COMEDI_AMPLC_DIO200_ISA tristate "Amplicon PC212E/PC214E/PC215E/PC218E/PC272E" - select COMEDI_AMPLC_DIO200 + depends on COMEDI_AMPLC_DIO200 help Enable support for Amplicon PC212E, PC214E, PC215E, PC218E and PC272E ISA DIO boards @@ -255,7 +262,8 @@ config COMEDI_DAC02 config COMEDI_DAS16M1 tristate "MeasurementComputing CIO-DAS16/M1DAS-16 ISA card support" - select COMEDI_8254 + depends on HAS_IOPORT + depends on COMEDI_8254 select COMEDI_8255 help Enable support for Measurement Computing CIO-DAS16/M1 ISA cards. @@ -265,7 +273,7 @@ config COMEDI_DAS16M1 config COMEDI_DAS08_ISA tristate "DAS-08 compatible ISA and PC/104 card support" - select COMEDI_DAS08 + depends on COMEDI_DAS08 help Enable support for Keithley Metrabyte/ComputerBoards DAS08 and compatible ISA and PC/104 cards: @@ -278,8 +286,9 @@ config COMEDI_DAS08_ISA config COMEDI_DAS16 tristate "DAS-16 compatible ISA and PC/104 card support" + depends on HAS_IOPORT select COMEDI_ISADMA if ISA_DMA_API - select COMEDI_8254 + depends on COMEDI_8254 select COMEDI_8255 help Enable support for Keithley Metrabyte/ComputerBoards DAS16 @@ -296,7 +305,8 @@ config COMEDI_DAS16 config COMEDI_DAS800 tristate "DAS800 and compatible ISA card support" - select COMEDI_8254 + depends on HAS_IOPORT + depends on COMEDI_8254 help Enable support for Keithley Metrabyte DAS800 and compatible ISA cards Keithley Metrabyte DAS-800, DAS-801, DAS-802 @@ -308,8 +318,9 @@ config COMEDI_DAS800 config COMEDI_DAS1800 tristate "DAS1800 and compatible ISA card support" + depends on HAS_IOPORT select COMEDI_ISADMA if ISA_DMA_API - select COMEDI_8254 + depends on COMEDI_8254 help Enable support for DAS1800 and compatible ISA cards Keithley Metrabyte DAS-1701ST, DAS-1701ST-DA, DAS-1701/AO, @@ -323,7 +334,8 @@ config COMEDI_DAS1800 config COMEDI_DAS6402 tristate "DAS6402 and compatible ISA card support" - select COMEDI_8254 + depends on HAS_IOPORT + depends on COMEDI_8254 help Enable support for DAS6402 and compatible ISA cards Computerboards, Keithley Metrabyte DAS6402 and compatibles @@ -402,7 +414,8 @@ config COMEDI_FL512 config COMEDI_AIO_AIO12_8 tristate "I/O Products PC/104 AIO12-8 Analog I/O Board support" - select COMEDI_8254 + depends on HAS_IOPORT + depends on COMEDI_8254 select COMEDI_8255 help Enable support for I/O Products PC/104 AIO12-8 Analog I/O Board @@ -456,8 +469,9 @@ config COMEDI_ADQ12B config COMEDI_NI_AT_A2150 tristate "NI AT-A2150 ISA card support" + depends on HAS_IOPORT select COMEDI_ISADMA if ISA_DMA_API - select COMEDI_8254 + depends on COMEDI_8254 help Enable support for National Instruments AT-A2150 cards @@ -466,7 +480,8 @@ config COMEDI_NI_AT_A2150 config COMEDI_NI_AT_AO tristate "NI AT-AO-6/10 EISA card support" - select COMEDI_8254 + depends on HAS_IOPORT + depends on COMEDI_8254 help Enable support for National Instruments AT-AO-6/10 cards @@ -497,7 +512,7 @@ config COMEDI_NI_ATMIO16D config COMEDI_NI_LABPC_ISA tristate "NI Lab-PC and compatibles ISA support" - select COMEDI_NI_LABPC + depends on COMEDI_NI_LABPC help Enable support for National Instruments Lab-PC and compatibles Lab-PC-1200, Lab-PC-1200AI, Lab-PC+. @@ -561,7 +576,7 @@ endif # COMEDI_ISA_DRIVERS menuconfig COMEDI_PCI_DRIVERS tristate "Comedi PCI drivers" - depends on PCI + depends on PCI && HAS_IOPORT help Enable support for comedi PCI drivers. @@ -710,7 +725,8 @@ config COMEDI_ADL_PCI8164 config COMEDI_ADL_PCI9111 tristate "ADLink PCI-9111HR support" - select COMEDI_8254 + depends on HAS_IOPORT + depends on COMEDI_8254 help Enable support for ADlink PCI9111 cards @@ -720,7 +736,7 @@ config COMEDI_ADL_PCI9111 config COMEDI_ADL_PCI9118 tristate "ADLink PCI-9118DG, PCI-9118HG, PCI-9118HR support" depends on HAS_DMA - select COMEDI_8254 + depends on COMEDI_8254 help Enable support for ADlink PCI-9118DG, PCI-9118HG, PCI-9118HR cards @@ -729,7 +745,8 @@ config COMEDI_ADL_PCI9118 config COMEDI_ADV_PCI1710 tristate "Advantech PCI-171x and PCI-1731 support" - select COMEDI_8254 + depends on HAS_IOPORT + depends on COMEDI_8254 help Enable support for Advantech PCI-1710, PCI-1710HG, PCI-1711, PCI-1713 and PCI-1731 @@ -773,7 +790,8 @@ config COMEDI_ADV_PCI1760 config COMEDI_ADV_PCI_DIO tristate "Advantech PCI DIO card support" - select COMEDI_8254 + depends on HAS_IOPORT + depends on COMEDI_8254 select COMEDI_8255 help Enable support for Advantech PCI DIO cards @@ -786,7 +804,7 @@ config COMEDI_ADV_PCI_DIO config COMEDI_AMPLC_DIO200_PCI tristate "Amplicon PCI215/PCI272/PCIe215/PCIe236/PCIe296 DIO support" - select COMEDI_AMPLC_DIO200 + depends on COMEDI_AMPLC_DIO200 help Enable support for Amplicon PCI215, PCI272, PCIe215, PCIe236 and PCIe296 DIO boards. @@ -814,7 +832,8 @@ config COMEDI_AMPLC_PC263_PCI config COMEDI_AMPLC_PCI224 tristate "Amplicon PCI224 and PCI234 support" - select COMEDI_8254 + depends on HAS_IOPORT + depends on COMEDI_8254 help Enable support for Amplicon PCI224 and PCI234 AO boards @@ -823,7 +842,8 @@ config COMEDI_AMPLC_PCI224 config COMEDI_AMPLC_PCI230 tristate "Amplicon PCI230 and PCI260 support" - select COMEDI_8254 + depends on HAS_IOPORT + depends on COMEDI_8254 select COMEDI_8255 help Enable support for Amplicon PCI230 and PCI260 Multifunction I/O @@ -842,7 +862,7 @@ config COMEDI_CONTEC_PCI_DIO config COMEDI_DAS08_PCI tristate "DAS-08 PCI support" - select COMEDI_DAS08 + depends on COMEDI_DAS08 help Enable support for PCI DAS-08 cards. @@ -929,7 +949,8 @@ config COMEDI_CB_PCIDAS64 config COMEDI_CB_PCIDAS tristate "MeasurementComputing PCI-DAS support" - select COMEDI_8254 + depends on HAS_IOPORT + depends on COMEDI_8254 select COMEDI_8255 help Enable support for ComputerBoards/MeasurementComputing PCI-DAS with @@ -953,7 +974,8 @@ config COMEDI_CB_PCIDDA config COMEDI_CB_PCIMDAS tristate "MeasurementComputing PCIM-DAS1602/16, PCIe-DAS1602/16 support" - select COMEDI_8254 + depends on HAS_IOPORT + depends on COMEDI_8254 select COMEDI_8255 help Enable support for ComputerBoards/MeasurementComputing PCI Migration @@ -973,7 +995,8 @@ config COMEDI_CB_PCIMDDA config COMEDI_ME4000 tristate "Meilhaus ME-4000 support" - select COMEDI_8254 + depends on HAS_IOPORT + depends on COMEDI_8254 help Enable support for Meilhaus PCI data acquisition cards ME-4650, ME-4670i, ME-4680, ME-4680i and ME-4680is @@ -1031,7 +1054,7 @@ config COMEDI_NI_670X config COMEDI_NI_LABPC_PCI tristate "NI Lab-PC PCI-1200 support" - select COMEDI_NI_LABPC + depends on COMEDI_NI_LABPC help Enable support for National Instruments Lab-PC PCI-1200. @@ -1053,6 +1076,7 @@ config COMEDI_NI_PCIDIO config COMEDI_NI_PCIMIO tristate "NI PCI-MIO-E series and M series support" depends on HAS_DMA + depends on HAS_IOPORT select COMEDI_NI_TIOCMD select COMEDI_8255 help @@ -1074,7 +1098,8 @@ config COMEDI_NI_PCIMIO config COMEDI_RTD520 tristate "Real Time Devices PCI4520/DM7520 support" - select COMEDI_8254 + depends on HAS_IOPORT + depends on COMEDI_8254 help Enable support for Real Time Devices PCI4520/DM7520 @@ -1114,7 +1139,8 @@ if COMEDI_PCMCIA_DRIVERS config COMEDI_CB_DAS16_CS tristate "CB DAS16 series PCMCIA support" - select COMEDI_8254 + depends on HAS_IOPORT + depends on COMEDI_8254 help Enable support for the ComputerBoards/MeasurementComputing PCMCIA cards DAS16/16, PCM-DAS16D/12 and PCM-DAS16s/16 @@ -1124,7 +1150,7 @@ config COMEDI_CB_DAS16_CS config COMEDI_DAS08_CS tristate "CB DAS08 PCMCIA support" - select COMEDI_DAS08 + depends on COMEDI_DAS08 help Enable support for the ComputerBoards/MeasurementComputing DAS-08 PCMCIA card @@ -1134,6 +1160,7 @@ config COMEDI_DAS08_CS config COMEDI_NI_DAQ_700_CS tristate "NI DAQCard-700 PCMCIA support" + depends on HAS_IOPORT help Enable support for the National Instruments PCMCIA DAQCard-700 DIO @@ -1142,6 +1169,7 @@ config COMEDI_NI_DAQ_700_CS config COMEDI_NI_DAQ_DIO24_CS tristate "NI DAQ-Card DIO-24 PCMCIA support" + depends on HAS_IOPORT select COMEDI_8255 help Enable support for the National Instruments PCMCIA DAQ-Card DIO-24 @@ -1151,7 +1179,7 @@ config COMEDI_NI_DAQ_DIO24_CS config COMEDI_NI_LABPC_CS tristate "NI DAQCard-1200 PCMCIA support" - select COMEDI_NI_LABPC + depends on COMEDI_NI_LABPC help Enable support for the National Instruments PCMCIA DAQCard-1200 @@ -1160,6 +1188,7 @@ config COMEDI_NI_LABPC_CS config COMEDI_NI_MIO_CS tristate "NI DAQCard E series PCMCIA support" + depends on HAS_IOPORT select COMEDI_NI_TIO select COMEDI_8255 help @@ -1172,6 +1201,7 @@ config COMEDI_NI_MIO_CS config COMEDI_QUATECH_DAQP_CS tristate "Quatech DAQP PCMCIA data capture card support" + depends on HAS_IOPORT help Enable support for the Quatech DAQP PCMCIA data capture cards DAQP-208 and DAQP-308 @@ -1248,12 +1278,14 @@ endif # COMEDI_USB_DRIVERS config COMEDI_8254 tristate + depends on HAS_IOPORT config COMEDI_8255 tristate config COMEDI_8255_SA tristate "Standalone 8255 support" + depends on HAS_IOPORT select COMEDI_8255 help Enable support for 8255 digital I/O as a standalone driver. @@ -1285,7 +1317,7 @@ config COMEDI_KCOMEDILIB called kcomedilib. config COMEDI_AMPLC_DIO200 - select COMEDI_8254 + depends on COMEDI_8254 tristate config COMEDI_AMPLC_PC236 @@ -1294,7 +1326,7 @@ config COMEDI_AMPLC_PC236 config COMEDI_DAS08 tristate - select COMEDI_8254 + depends on COMEDI_8254 select COMEDI_8255 config COMEDI_ISADMA @@ -1302,7 +1334,8 @@ config COMEDI_ISADMA config COMEDI_NI_LABPC tristate - select COMEDI_8254 + depends on HAS_IOPORT + depends on COMEDI_8254 select COMEDI_8255 config COMEDI_NI_LABPC_ISADMA diff --git a/drivers/comedi/comedi_fops.c b/drivers/comedi/comedi_fops.c index 8e43918d38c400fa99c62916a93bc9ca86c58f7f..1548dea15df140967d7c321834134d9ac43d0017 100644 --- a/drivers/comedi/comedi_fops.c +++ b/drivers/comedi/comedi_fops.c @@ -97,7 +97,6 @@ static DEFINE_MUTEX(comedi_subdevice_minor_table_lock); static struct comedi_subdevice *comedi_subdevice_minor_table[COMEDI_NUM_SUBDEVICE_MINORS]; -static struct class *comedi_class; static struct cdev comedi_cdev; static void comedi_device_init(struct comedi_device *dev) @@ -187,18 +186,6 @@ static struct comedi_device *comedi_clear_board_minor(unsigned int minor) return dev; } -static void comedi_free_board_dev(struct comedi_device *dev) -{ - if (dev) { - comedi_device_cleanup(dev); - if (dev->class_dev) { - device_destroy(comedi_class, - MKDEV(COMEDI_MAJOR, dev->minor)); - } - comedi_dev_put(dev); - } -} - static struct comedi_subdevice * comedi_subdevice_from_minor(const struct comedi_device *dev, unsigned int minor) { @@ -611,6 +598,23 @@ static struct attribute *comedi_dev_attrs[] = { }; ATTRIBUTE_GROUPS(comedi_dev); +static const struct class comedi_class = { + .name = "comedi", + .dev_groups = comedi_dev_groups, +}; + +static void comedi_free_board_dev(struct comedi_device *dev) +{ + if (dev) { + comedi_device_cleanup(dev); + if (dev->class_dev) { + device_destroy(&comedi_class, + MKDEV(COMEDI_MAJOR, dev->minor)); + } + comedi_dev_put(dev); + } +} + static void __comedi_clear_subdevice_runflags(struct comedi_subdevice *s, unsigned int bits) { @@ -3263,7 +3267,7 @@ struct comedi_device *comedi_alloc_board_minor(struct device *hardware_device) return ERR_PTR(-EBUSY); } dev->minor = i; - csdev = device_create(comedi_class, hardware_device, + csdev = device_create(&comedi_class, hardware_device, MKDEV(COMEDI_MAJOR, i), NULL, "comedi%i", i); if (!IS_ERR(csdev)) dev->class_dev = get_device(csdev); @@ -3312,7 +3316,7 @@ int comedi_alloc_subdevice_minor(struct comedi_subdevice *s) } i += COMEDI_NUM_BOARD_MINORS; s->minor = i; - csdev = device_create(comedi_class, dev->class_dev, + csdev = device_create(&comedi_class, dev->class_dev, MKDEV(COMEDI_MAJOR, i), NULL, "comedi%i_subd%i", dev->minor, s->index); if (!IS_ERR(csdev)) @@ -3337,7 +3341,7 @@ void comedi_free_subdevice_minor(struct comedi_subdevice *s) comedi_subdevice_minor_table[i] = NULL; mutex_unlock(&comedi_subdevice_minor_table_lock); if (s->class_dev) { - device_destroy(comedi_class, MKDEV(COMEDI_MAJOR, s->minor)); + device_destroy(&comedi_class, MKDEV(COMEDI_MAJOR, s->minor)); s->class_dev = NULL; } } @@ -3383,15 +3387,12 @@ static int __init comedi_init(void) if (retval) goto out_unregister_chrdev_region; - comedi_class = class_create("comedi"); - if (IS_ERR(comedi_class)) { - retval = PTR_ERR(comedi_class); + retval = class_register(&comedi_class); + if (retval) { pr_err("failed to create class\n"); goto out_cdev_del; } - comedi_class->dev_groups = comedi_dev_groups; - /* create devices files for legacy/manual use */ for (i = 0; i < comedi_num_legacy_minors; i++) { struct comedi_device *dev; @@ -3413,7 +3414,7 @@ static int __init comedi_init(void) out_cleanup_board_minors: comedi_cleanup_board_minors(); - class_destroy(comedi_class); + class_unregister(&comedi_class); out_cdev_del: cdev_del(&comedi_cdev); out_unregister_chrdev_region: @@ -3425,7 +3426,7 @@ module_init(comedi_init); static void __exit comedi_cleanup(void) { comedi_cleanup_board_minors(); - class_destroy(comedi_class); + class_unregister(&comedi_class); cdev_del(&comedi_cdev); unregister_chrdev_region(MKDEV(COMEDI_MAJOR, 0), COMEDI_NUM_MINORS); diff --git a/drivers/comedi/drivers/comedi_test.c b/drivers/comedi/drivers/comedi_test.c index c02dc19a679bdee3bfc0f57b642afc375044cca4..30ea8b53ebf8191db808b928041b0ac9a6e1512a 100644 --- a/drivers/comedi/drivers/comedi_test.c +++ b/drivers/comedi/drivers/comedi_test.c @@ -60,7 +60,9 @@ static bool config_mode; static unsigned int set_amplitude; static unsigned int set_period; -static struct class *ctcls; +static const struct class ctcls = { + .name = CLASS_NAME, +}; static struct device *ctdev; module_param_named(noauto, config_mode, bool, 0444); @@ -795,13 +797,13 @@ static int __init comedi_test_init(void) } if (!config_mode) { - ctcls = class_create(CLASS_NAME); - if (IS_ERR(ctcls)) { + ret = class_register(&ctcls); + if (ret) { pr_warn("comedi_test: unable to create class\n"); goto clean3; } - ctdev = device_create(ctcls, NULL, MKDEV(0, 0), NULL, DEV_NAME); + ctdev = device_create(&ctcls, NULL, MKDEV(0, 0), NULL, DEV_NAME); if (IS_ERR(ctdev)) { pr_warn("comedi_test: unable to create device\n"); goto clean2; @@ -817,13 +819,10 @@ static int __init comedi_test_init(void) return 0; clean: - device_destroy(ctcls, MKDEV(0, 0)); + device_destroy(&ctcls, MKDEV(0, 0)); clean2: - class_destroy(ctcls); - ctdev = NULL; + class_unregister(&ctcls); clean3: - ctcls = NULL; - return 0; } module_init(comedi_test_init); @@ -833,9 +832,9 @@ static void __exit comedi_test_exit(void) if (ctdev) comedi_auto_unconfig(ctdev); - if (ctcls) { - device_destroy(ctcls, MKDEV(0, 0)); - class_destroy(ctcls); + if (class_is_registered(&ctcls)) { + device_destroy(&ctcls, MKDEV(0, 0)); + class_unregister(&ctcls); } comedi_driver_unregister(&waveform_driver); diff --git a/drivers/counter/104-quad-8.c b/drivers/counter/104-quad-8.c index d9cb937665cfcf657a80bbb150b2b04858599c8c..ed1f57511955856af1bbb76fc8b3e81ce51ae7b8 100644 --- a/drivers/counter/104-quad-8.c +++ b/drivers/counter/104-quad-8.c @@ -5,10 +5,11 @@ * * This driver supports the ACCES 104-QUAD-8 and ACCES 104-QUAD-4. */ -#include +#include +#include #include #include -#include +#include #include #include #include @@ -17,8 +18,11 @@ #include #include #include -#include +#include #include +#include + +#include #define QUAD8_EXTENT 32 @@ -34,118 +38,196 @@ MODULE_PARM_DESC(irq, "ACCES 104-QUAD-8 interrupt line numbers"); #define QUAD8_NUM_COUNTERS 8 -/** - * struct channel_reg - channel register structure - * @data: Count data - * @control: Channel flags and control - */ -struct channel_reg { - u8 data; - u8 control; -}; - -/** - * struct quad8_reg - device register structure - * @channel: quadrature counter data and control - * @interrupt_status: channel interrupt status - * @channel_oper: enable/reset counters and interrupt functions - * @index_interrupt: enable channel interrupts - * @reserved: reserved for Factory Use - * @index_input_levels: index signal logical input level - * @cable_status: differential encoder cable status - */ -struct quad8_reg { - struct channel_reg channel[QUAD8_NUM_COUNTERS]; - u8 interrupt_status; - u8 channel_oper; - u8 index_interrupt; - u8 reserved[3]; - u8 index_input_levels; - u8 cable_status; -}; +#define QUAD8_DATA(_channel) ((_channel) * 2) +#define QUAD8_CONTROL(_channel) (QUAD8_DATA(_channel) + 1) +#define QUAD8_INTERRUPT_STATUS 0x10 +#define QUAD8_CHANNEL_OPERATION 0x11 +#define QUAD8_INDEX_INTERRUPT 0x12 +#define QUAD8_INDEX_INPUT_LEVELS 0x16 +#define QUAD8_CABLE_STATUS 0x17 /** * struct quad8 - device private data structure * @lock: lock to prevent clobbering device states during R/W ops - * @counter: instance of the counter_device + * @cmr: array of Counter Mode Register states + * @ior: array of Input / Output Control Register states + * @idr: array of Index Control Register states * @fck_prescaler: array of filter clock prescaler configurations * @preset: array of preset values - * @count_mode: array of count mode configurations - * @quadrature_mode: array of quadrature mode configurations - * @quadrature_scale: array of quadrature mode scale configurations - * @ab_enable: array of A and B inputs enable configurations - * @preset_enable: array of set_to_preset_on_index attribute configurations - * @irq_trigger: array of current IRQ trigger function configurations - * @synchronous_mode: array of index function synchronous mode configurations - * @index_polarity: array of index function polarity configurations * @cable_fault_enable: differential encoder cable status enable configurations - * @reg: I/O address offset for the device registers + * @map: regmap for the device */ struct quad8 { spinlock_t lock; + u8 cmr[QUAD8_NUM_COUNTERS]; + u8 ior[QUAD8_NUM_COUNTERS]; + u8 idr[QUAD8_NUM_COUNTERS]; unsigned int fck_prescaler[QUAD8_NUM_COUNTERS]; unsigned int preset[QUAD8_NUM_COUNTERS]; - unsigned int count_mode[QUAD8_NUM_COUNTERS]; - unsigned int quadrature_mode[QUAD8_NUM_COUNTERS]; - unsigned int quadrature_scale[QUAD8_NUM_COUNTERS]; - unsigned int ab_enable[QUAD8_NUM_COUNTERS]; - unsigned int preset_enable[QUAD8_NUM_COUNTERS]; - unsigned int irq_trigger[QUAD8_NUM_COUNTERS]; - unsigned int synchronous_mode[QUAD8_NUM_COUNTERS]; - unsigned int index_polarity[QUAD8_NUM_COUNTERS]; unsigned int cable_fault_enable; - struct quad8_reg __iomem *reg; + struct regmap *map; +}; + +static const struct regmap_range quad8_wr_ranges[] = { + regmap_reg_range(0x0, 0xF), regmap_reg_range(0x11, 0x12), regmap_reg_range(0x17, 0x17), +}; +static const struct regmap_range quad8_rd_ranges[] = { + regmap_reg_range(0x0, 0x12), regmap_reg_range(0x16, 0x18), +}; +static const struct regmap_access_table quad8_wr_table = { + .yes_ranges = quad8_wr_ranges, + .n_yes_ranges = ARRAY_SIZE(quad8_wr_ranges), +}; +static const struct regmap_access_table quad8_rd_table = { + .yes_ranges = quad8_rd_ranges, + .n_yes_ranges = ARRAY_SIZE(quad8_rd_ranges), +}; +static const struct regmap_config quad8_regmap_config = { + .reg_bits = 8, + .reg_stride = 1, + .val_bits = 8, + .io_port = true, + .wr_table = &quad8_wr_table, + .rd_table = &quad8_rd_table, }; /* Error flag */ -#define QUAD8_FLAG_E BIT(4) +#define FLAG_E BIT(4) /* Up/Down flag */ -#define QUAD8_FLAG_UD BIT(5) +#define FLAG_UD BIT(5) +/* Counting up */ +#define UP 0x1 + +#define REGISTER_SELECTION GENMASK(6, 5) + /* Reset and Load Signal Decoders */ -#define QUAD8_CTR_RLD 0x00 +#define SELECT_RLD u8_encode_bits(0x0, REGISTER_SELECTION) /* Counter Mode Register */ -#define QUAD8_CTR_CMR 0x20 +#define SELECT_CMR u8_encode_bits(0x1, REGISTER_SELECTION) /* Input / Output Control Register */ -#define QUAD8_CTR_IOR 0x40 +#define SELECT_IOR u8_encode_bits(0x2, REGISTER_SELECTION) /* Index Control Register */ -#define QUAD8_CTR_IDR 0x60 +#define SELECT_IDR u8_encode_bits(0x3, REGISTER_SELECTION) + +/* + * Reset and Load Signal Decoders + */ +#define RESETS GENMASK(2, 1) +#define LOADS GENMASK(4, 3) /* Reset Byte Pointer (three byte data pointer) */ -#define QUAD8_RLD_RESET_BP 0x01 -/* Reset Counter */ -#define QUAD8_RLD_RESET_CNTR 0x02 -/* Reset Borrow Toggle, Carry Toggle, Compare Toggle, and Sign flags */ -#define QUAD8_RLD_RESET_FLAGS 0x04 +#define RESET_BP BIT(0) +/* Reset Borrow Toggle, Carry toggle, Compare toggle, Sign, and Index flags */ +#define RESET_BT_CT_CPT_S_IDX u8_encode_bits(0x2, RESETS) /* Reset Error flag */ -#define QUAD8_RLD_RESET_E 0x06 +#define RESET_E u8_encode_bits(0x3, RESETS) /* Preset Register to Counter */ -#define QUAD8_RLD_PRESET_CNTR 0x08 +#define TRANSFER_PR_TO_CNTR u8_encode_bits(0x1, LOADS) /* Transfer Counter to Output Latch */ -#define QUAD8_RLD_CNTR_OUT 0x10 +#define TRANSFER_CNTR_TO_OL u8_encode_bits(0x2, LOADS) /* Transfer Preset Register LSB to FCK Prescaler */ -#define QUAD8_RLD_PRESET_PSC 0x18 -#define QUAD8_CHAN_OP_RESET_COUNTERS 0x01 -#define QUAD8_CHAN_OP_ENABLE_INTERRUPT_FUNC 0x04 -#define QUAD8_CMR_QUADRATURE_X1 0x08 -#define QUAD8_CMR_QUADRATURE_X2 0x10 -#define QUAD8_CMR_QUADRATURE_X4 0x18 +#define TRANSFER_PR0_TO_PSC u8_encode_bits(0x3, LOADS) + +/* + * Counter Mode Registers + */ +#define COUNT_ENCODING BIT(0) +#define COUNT_MODE GENMASK(2, 1) +#define QUADRATURE_MODE GENMASK(4, 3) +/* Binary count */ +#define BINARY u8_encode_bits(0x0, COUNT_ENCODING) +/* Normal count */ +#define NORMAL_COUNT 0x0 +/* Range Limit */ +#define RANGE_LIMIT 0x1 +/* Non-recycle count */ +#define NON_RECYCLE_COUNT 0x2 +/* Modulo-N */ +#define MODULO_N 0x3 +/* Non-quadrature */ +#define NON_QUADRATURE 0x0 +/* Quadrature X1 */ +#define QUADRATURE_X1 0x1 +/* Quadrature X2 */ +#define QUADRATURE_X2 0x2 +/* Quadrature X4 */ +#define QUADRATURE_X4 0x3 + +/* + * Input/Output Control Register + */ +#define AB_GATE BIT(0) +#define LOAD_PIN BIT(1) +#define FLG_PINS GENMASK(4, 3) +/* Disable inputs A and B */ +#define DISABLE_AB u8_encode_bits(0x0, AB_GATE) +/* Load Counter input */ +#define LOAD_CNTR 0x0 +/* FLG1 = CARRY(active low); FLG2 = BORROW(active low) */ +#define FLG1_CARRY_FLG2_BORROW 0x0 +/* FLG1 = COMPARE(active low); FLG2 = BORROW(active low) */ +#define FLG1_COMPARE_FLG2_BORROW 0x1 +/* FLG1 = Carry(active low)/Borrow(active low); FLG2 = U/D(active low) flag */ +#define FLG1_CARRYBORROW_FLG2_UD 0x2 +/* FLG1 = INDX (low pulse at INDEX pin active level); FLG2 = E flag */ +#define FLG1_INDX_FLG2_E 0x3 + +/* + * INDEX CONTROL REGISTERS + */ +#define INDEX_MODE BIT(0) +#define INDEX_POLARITY BIT(1) +/* Disable Index mode */ +#define DISABLE_INDEX_MODE 0x0 +/* Enable Index mode */ +#define ENABLE_INDEX_MODE 0x1 +/* Negative Index Polarity */ +#define NEGATIVE_INDEX_POLARITY 0x0 +/* Positive Index Polarity */ +#define POSITIVE_INDEX_POLARITY 0x1 + +/* + * Channel Operation Register + */ +#define COUNTERS_OPERATION BIT(0) +#define INTERRUPT_FUNCTION BIT(2) +/* Enable all Counters */ +#define ENABLE_COUNTERS u8_encode_bits(0x0, COUNTERS_OPERATION) +/* Reset all Counters */ +#define RESET_COUNTERS u8_encode_bits(0x1, COUNTERS_OPERATION) +/* Disable the interrupt function */ +#define DISABLE_INTERRUPT_FUNCTION u8_encode_bits(0x0, INTERRUPT_FUNCTION) +/* Enable the interrupt function */ +#define ENABLE_INTERRUPT_FUNCTION u8_encode_bits(0x1, INTERRUPT_FUNCTION) +/* Any write to the Channel Operation register clears any pending interrupts */ +#define CLEAR_PENDING_INTERRUPTS (ENABLE_COUNTERS | ENABLE_INTERRUPT_FUNCTION) /* Each Counter is 24 bits wide */ #define LS7267_CNTR_MAX GENMASK(23, 0) +static __always_inline int quad8_control_register_update(struct regmap *const map, u8 *const buf, + const size_t channel, const u8 val, + const u8 field) +{ + u8p_replace_bits(&buf[channel], val, field); + return regmap_write(map, QUAD8_CONTROL(channel), buf[channel]); +} + static int quad8_signal_read(struct counter_device *counter, struct counter_signal *signal, enum counter_signal_level *level) { const struct quad8 *const priv = counter_priv(counter); - unsigned int state; + int ret; /* Only Index signal levels can be read */ if (signal->id < 16) return -EINVAL; - state = ioread8(&priv->reg->index_input_levels) & BIT(signal->id - 16); + ret = regmap_test_bits(priv->map, QUAD8_INDEX_INPUT_LEVELS, BIT(signal->id - 16)); + if (ret < 0) + return ret; - *level = (state) ? COUNTER_SIGNAL_LEVEL_HIGH : COUNTER_SIGNAL_LEVEL_LOW; + *level = (ret) ? COUNTER_SIGNAL_LEVEL_HIGH : COUNTER_SIGNAL_LEVEL_LOW; return 0; } @@ -154,65 +236,81 @@ static int quad8_count_read(struct counter_device *counter, struct counter_count *count, u64 *val) { struct quad8 *const priv = counter_priv(counter); - struct channel_reg __iomem *const chan = priv->reg->channel + count->id; unsigned long irqflags; - int i; - - *val = 0; + u8 value[3]; + int ret; spin_lock_irqsave(&priv->lock, irqflags); - /* Reset Byte Pointer; transfer Counter to Output Latch */ - iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP | QUAD8_RLD_CNTR_OUT, - &chan->control); - - for (i = 0; i < 3; i++) - *val |= (unsigned long)ioread8(&chan->data) << (8 * i); + ret = regmap_write(priv->map, QUAD8_CONTROL(count->id), + SELECT_RLD | RESET_BP | TRANSFER_CNTR_TO_OL); + if (ret) + goto exit_unlock; + ret = regmap_noinc_read(priv->map, QUAD8_DATA(count->id), value, sizeof(value)); +exit_unlock: spin_unlock_irqrestore(&priv->lock, irqflags); - return 0; + *val = get_unaligned_le24(value); + + return ret; +} + +static int quad8_preset_register_set(struct quad8 *const priv, const size_t id, + const unsigned long preset) +{ + u8 value[3]; + int ret; + + put_unaligned_le24(preset, value); + + ret = regmap_write(priv->map, QUAD8_CONTROL(id), SELECT_RLD | RESET_BP); + if (ret) + return ret; + return regmap_noinc_write(priv->map, QUAD8_DATA(id), value, sizeof(value)); +} + +static int quad8_flag_register_reset(struct quad8 *const priv, const size_t id) +{ + int ret; + + ret = regmap_write(priv->map, QUAD8_CONTROL(id), SELECT_RLD | RESET_BT_CT_CPT_S_IDX); + if (ret) + return ret; + return regmap_write(priv->map, QUAD8_CONTROL(id), SELECT_RLD | RESET_E); } static int quad8_count_write(struct counter_device *counter, struct counter_count *count, u64 val) { struct quad8 *const priv = counter_priv(counter); - struct channel_reg __iomem *const chan = priv->reg->channel + count->id; unsigned long irqflags; - int i; + int ret; if (val > LS7267_CNTR_MAX) return -ERANGE; spin_lock_irqsave(&priv->lock, irqflags); - /* Reset Byte Pointer */ - iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, &chan->control); - /* Counter can only be set via Preset Register */ - for (i = 0; i < 3; i++) - iowrite8(val >> (8 * i), &chan->data); + ret = quad8_preset_register_set(priv, count->id, val); + if (ret) + goto exit_unlock; + ret = regmap_write(priv->map, QUAD8_CONTROL(count->id), SELECT_RLD | TRANSFER_PR_TO_CNTR); + if (ret) + goto exit_unlock; - /* Transfer Preset Register to Counter */ - iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_PRESET_CNTR, &chan->control); - - /* Reset Byte Pointer */ - iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, &chan->control); + ret = quad8_flag_register_reset(priv, count->id); + if (ret) + goto exit_unlock; /* Set Preset Register back to original value */ - val = priv->preset[count->id]; - for (i = 0; i < 3; i++) - iowrite8(val >> (8 * i), &chan->data); - - /* Reset Borrow, Carry, Compare, and Sign flags */ - iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_FLAGS, &chan->control); - /* Reset Error flag */ - iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_E, &chan->control); + ret = quad8_preset_register_set(priv, count->id, priv->preset[count->id]); +exit_unlock: spin_unlock_irqrestore(&priv->lock, irqflags); - return 0; + return ret; } static const enum counter_function quad8_count_functions_list[] = { @@ -225,19 +323,17 @@ static const enum counter_function quad8_count_functions_list[] = { static int quad8_function_get(const struct quad8 *const priv, const size_t id, enum counter_function *const function) { - if (!priv->quadrature_mode[id]) { + switch (u8_get_bits(priv->cmr[id], QUADRATURE_MODE)) { + case NON_QUADRATURE: *function = COUNTER_FUNCTION_PULSE_DIRECTION; return 0; - } - - switch (priv->quadrature_scale[id]) { - case 0: + case QUADRATURE_X1: *function = COUNTER_FUNCTION_QUADRATURE_X1_A; return 0; - case 1: + case QUADRATURE_X2: *function = COUNTER_FUNCTION_QUADRATURE_X2_A; return 0; - case 2: + case QUADRATURE_X4: *function = COUNTER_FUNCTION_QUADRATURE_X4; return 0; default: @@ -269,60 +365,46 @@ static int quad8_function_write(struct counter_device *counter, { struct quad8 *const priv = counter_priv(counter); const int id = count->id; - unsigned int *const quadrature_mode = priv->quadrature_mode + id; - unsigned int *const scale = priv->quadrature_scale + id; - unsigned int *const synchronous_mode = priv->synchronous_mode + id; - u8 __iomem *const control = &priv->reg->channel[id].control; unsigned long irqflags; unsigned int mode_cfg; - unsigned int idr_cfg; + bool synchronous_mode; + int ret; - spin_lock_irqsave(&priv->lock, irqflags); - - mode_cfg = priv->count_mode[id] << 1; - idr_cfg = priv->index_polarity[id] << 1; - - if (function == COUNTER_FUNCTION_PULSE_DIRECTION) { - *quadrature_mode = 0; - - /* Quadrature scaling only available in quadrature mode */ - *scale = 0; + switch (function) { + case COUNTER_FUNCTION_PULSE_DIRECTION: + mode_cfg = NON_QUADRATURE; + break; + case COUNTER_FUNCTION_QUADRATURE_X1_A: + mode_cfg = QUADRATURE_X1; + break; + case COUNTER_FUNCTION_QUADRATURE_X2_A: + mode_cfg = QUADRATURE_X2; + break; + case COUNTER_FUNCTION_QUADRATURE_X4: + mode_cfg = QUADRATURE_X4; + break; + default: + /* should never reach this path */ + return -EINVAL; + } - /* Synchronous function not supported in non-quadrature mode */ - if (*synchronous_mode) { - *synchronous_mode = 0; - /* Disable synchronous function mode */ - iowrite8(QUAD8_CTR_IDR | idr_cfg, control); - } - } else { - *quadrature_mode = 1; + spin_lock_irqsave(&priv->lock, irqflags); - switch (function) { - case COUNTER_FUNCTION_QUADRATURE_X1_A: - *scale = 0; - mode_cfg |= QUAD8_CMR_QUADRATURE_X1; - break; - case COUNTER_FUNCTION_QUADRATURE_X2_A: - *scale = 1; - mode_cfg |= QUAD8_CMR_QUADRATURE_X2; - break; - case COUNTER_FUNCTION_QUADRATURE_X4: - *scale = 2; - mode_cfg |= QUAD8_CMR_QUADRATURE_X4; - break; - default: - /* should never reach this path */ - spin_unlock_irqrestore(&priv->lock, irqflags); - return -EINVAL; - } + /* Synchronous function not supported in non-quadrature mode */ + synchronous_mode = u8_get_bits(priv->idr[id], INDEX_MODE) == ENABLE_INDEX_MODE; + if (synchronous_mode && mode_cfg == NON_QUADRATURE) { + ret = quad8_control_register_update(priv->map, priv->idr, id, DISABLE_INDEX_MODE, + INDEX_MODE); + if (ret) + goto exit_unlock; } - /* Load mode configuration to Counter Mode Register */ - iowrite8(QUAD8_CTR_CMR | mode_cfg, control); + ret = quad8_control_register_update(priv->map, priv->cmr, id, mode_cfg, QUADRATURE_MODE); +exit_unlock: spin_unlock_irqrestore(&priv->lock, irqflags); - return 0; + return ret; } static int quad8_direction_read(struct counter_device *counter, @@ -330,13 +412,13 @@ static int quad8_direction_read(struct counter_device *counter, enum counter_count_direction *direction) { const struct quad8 *const priv = counter_priv(counter); - unsigned int ud_flag; - u8 __iomem *const flag_addr = &priv->reg->channel[count->id].control; - - /* U/D flag: nonzero = up, zero = down */ - ud_flag = ioread8(flag_addr) & QUAD8_FLAG_UD; + unsigned int flag; + int ret; - *direction = (ud_flag) ? COUNTER_COUNT_DIRECTION_FORWARD : + ret = regmap_read(priv->map, QUAD8_CONTROL(count->id), &flag); + if (ret) + return ret; + *direction = (u8_get_bits(flag, FLAG_UD) == UP) ? COUNTER_COUNT_DIRECTION_FORWARD : COUNTER_COUNT_DIRECTION_BACKWARD; return 0; @@ -366,13 +448,13 @@ static int quad8_action_read(struct counter_device *counter, const size_t signal_a_id = count->synapses[0].signal->id; enum counter_count_direction direction; + /* Default action mode */ + *action = COUNTER_SYNAPSE_ACTION_NONE; + /* Handle Index signals */ if (synapse->signal->id >= 16) { - if (!priv->preset_enable[count->id]) + if (u8_get_bits(priv->ior[count->id], LOAD_PIN) == LOAD_CNTR) *action = COUNTER_SYNAPSE_ACTION_RISING_EDGE; - else - *action = COUNTER_SYNAPSE_ACTION_NONE; - return 0; } @@ -392,9 +474,6 @@ static int quad8_action_read(struct counter_device *counter, spin_unlock_irqrestore(&priv->lock, irqflags); - /* Default action mode */ - *action = COUNTER_SYNAPSE_ACTION_NONE; - /* Determine action mode based on current count function mode */ switch (function) { case COUNTER_FUNCTION_PULSE_DIRECTION: @@ -422,67 +501,57 @@ static int quad8_action_read(struct counter_device *counter, } } -enum { - QUAD8_EVENT_CARRY = 0, - QUAD8_EVENT_COMPARE = 1, - QUAD8_EVENT_CARRY_BORROW = 2, - QUAD8_EVENT_INDEX = 3, -}; - static int quad8_events_configure(struct counter_device *counter) { struct quad8 *const priv = counter_priv(counter); unsigned long irq_enabled = 0; unsigned long irqflags; struct counter_event_node *event_node; - unsigned int next_irq_trigger; - unsigned long ior_cfg; + u8 flg_pins; + int ret; spin_lock_irqsave(&priv->lock, irqflags); list_for_each_entry(event_node, &counter->events_list, l) { switch (event_node->event) { case COUNTER_EVENT_OVERFLOW: - next_irq_trigger = QUAD8_EVENT_CARRY; + flg_pins = FLG1_CARRY_FLG2_BORROW; break; case COUNTER_EVENT_THRESHOLD: - next_irq_trigger = QUAD8_EVENT_COMPARE; + flg_pins = FLG1_COMPARE_FLG2_BORROW; break; case COUNTER_EVENT_OVERFLOW_UNDERFLOW: - next_irq_trigger = QUAD8_EVENT_CARRY_BORROW; + flg_pins = FLG1_CARRYBORROW_FLG2_UD; break; case COUNTER_EVENT_INDEX: - next_irq_trigger = QUAD8_EVENT_INDEX; + flg_pins = FLG1_INDX_FLG2_E; break; default: /* should never reach this path */ - spin_unlock_irqrestore(&priv->lock, irqflags); - return -EINVAL; + ret = -EINVAL; + goto exit_unlock; } /* Enable IRQ line */ irq_enabled |= BIT(event_node->channel); /* Skip configuration if it is the same as previously set */ - if (priv->irq_trigger[event_node->channel] == next_irq_trigger) + if (flg_pins == u8_get_bits(priv->ior[event_node->channel], FLG_PINS)) continue; /* Save new IRQ function configuration */ - priv->irq_trigger[event_node->channel] = next_irq_trigger; - - /* Load configuration to I/O Control Register */ - ior_cfg = priv->ab_enable[event_node->channel] | - priv->preset_enable[event_node->channel] << 1 | - priv->irq_trigger[event_node->channel] << 3; - iowrite8(QUAD8_CTR_IOR | ior_cfg, - &priv->reg->channel[event_node->channel].control); + ret = quad8_control_register_update(priv->map, priv->ior, event_node->channel, + flg_pins, FLG_PINS); + if (ret) + goto exit_unlock; } - iowrite8(irq_enabled, &priv->reg->index_interrupt); + ret = regmap_write(priv->map, QUAD8_INDEX_INTERRUPT, irq_enabled); +exit_unlock: spin_unlock_irqrestore(&priv->lock, irqflags); - return 0; + return ret; } static int quad8_watch_validate(struct counter_device *counter, @@ -531,7 +600,7 @@ static int quad8_index_polarity_get(struct counter_device *counter, const struct quad8 *const priv = counter_priv(counter); const size_t channel_id = signal->id - 16; - *index_polarity = priv->index_polarity[channel_id]; + *index_polarity = u8_get_bits(priv->idr[channel_id], INDEX_POLARITY); return 0; } @@ -542,22 +611,17 @@ static int quad8_index_polarity_set(struct counter_device *counter, { struct quad8 *const priv = counter_priv(counter); const size_t channel_id = signal->id - 16; - u8 __iomem *const control = &priv->reg->channel[channel_id].control; unsigned long irqflags; - unsigned int idr_cfg = index_polarity << 1; + int ret; spin_lock_irqsave(&priv->lock, irqflags); - idr_cfg |= priv->synchronous_mode[channel_id]; - - priv->index_polarity[channel_id] = index_polarity; - - /* Load Index Control configuration to Index Control Register */ - iowrite8(QUAD8_CTR_IDR | idr_cfg, control); + ret = quad8_control_register_update(priv->map, priv->idr, channel_id, index_polarity, + INDEX_POLARITY); spin_unlock_irqrestore(&priv->lock, irqflags); - return 0; + return ret; } static int quad8_polarity_read(struct counter_device *counter, @@ -571,7 +635,7 @@ static int quad8_polarity_read(struct counter_device *counter, if (err) return err; - *polarity = (index_polarity) ? COUNTER_SIGNAL_POLARITY_POSITIVE : + *polarity = (index_polarity == POSITIVE_INDEX_POLARITY) ? COUNTER_SIGNAL_POLARITY_POSITIVE : COUNTER_SIGNAL_POLARITY_NEGATIVE; return 0; @@ -581,7 +645,8 @@ static int quad8_polarity_write(struct counter_device *counter, struct counter_signal *signal, enum counter_signal_polarity polarity) { - const u32 pol = (polarity == COUNTER_SIGNAL_POLARITY_POSITIVE) ? 1 : 0; + const u32 pol = (polarity == COUNTER_SIGNAL_POLARITY_POSITIVE) ? POSITIVE_INDEX_POLARITY : + NEGATIVE_INDEX_POLARITY; return quad8_index_polarity_set(counter, signal, pol); } @@ -598,7 +663,7 @@ static int quad8_synchronous_mode_get(struct counter_device *counter, const struct quad8 *const priv = counter_priv(counter); const size_t channel_id = signal->id - 16; - *synchronous_mode = priv->synchronous_mode[channel_id]; + *synchronous_mode = u8_get_bits(priv->idr[channel_id], INDEX_MODE); return 0; } @@ -609,28 +674,26 @@ static int quad8_synchronous_mode_set(struct counter_device *counter, { struct quad8 *const priv = counter_priv(counter); const size_t channel_id = signal->id - 16; - u8 __iomem *const control = &priv->reg->channel[channel_id].control; + u8 quadrature_mode; unsigned long irqflags; - unsigned int idr_cfg = synchronous_mode; + int ret; spin_lock_irqsave(&priv->lock, irqflags); - idr_cfg |= priv->index_polarity[channel_id] << 1; - /* Index function must be non-synchronous in non-quadrature mode */ - if (synchronous_mode && !priv->quadrature_mode[channel_id]) { - spin_unlock_irqrestore(&priv->lock, irqflags); - return -EINVAL; + quadrature_mode = u8_get_bits(priv->idr[channel_id], QUADRATURE_MODE); + if (synchronous_mode && quadrature_mode == NON_QUADRATURE) { + ret = -EINVAL; + goto exit_unlock; } - priv->synchronous_mode[channel_id] = synchronous_mode; - - /* Load Index Control configuration to Index Control Register */ - iowrite8(QUAD8_CTR_IDR | idr_cfg, control); + ret = quad8_control_register_update(priv->map, priv->idr, channel_id, synchronous_mode, + INDEX_MODE); +exit_unlock: spin_unlock_irqrestore(&priv->lock, irqflags); - return 0; + return ret; } static int quad8_count_floor_read(struct counter_device *counter, @@ -648,18 +711,17 @@ static int quad8_count_mode_read(struct counter_device *counter, { const struct quad8 *const priv = counter_priv(counter); - /* Map 104-QUAD-8 count mode to Generic Counter count mode */ - switch (priv->count_mode[count->id]) { - case 0: + switch (u8_get_bits(priv->cmr[count->id], COUNT_MODE)) { + case NORMAL_COUNT: *cnt_mode = COUNTER_COUNT_MODE_NORMAL; break; - case 1: + case RANGE_LIMIT: *cnt_mode = COUNTER_COUNT_MODE_RANGE_LIMIT; break; - case 2: + case NON_RECYCLE_COUNT: *cnt_mode = COUNTER_COUNT_MODE_NON_RECYCLE; break; - case 3: + case MODULO_N: *cnt_mode = COUNTER_COUNT_MODE_MODULO_N; break; } @@ -673,23 +735,21 @@ static int quad8_count_mode_write(struct counter_device *counter, { struct quad8 *const priv = counter_priv(counter); unsigned int count_mode; - unsigned int mode_cfg; - u8 __iomem *const control = &priv->reg->channel[count->id].control; unsigned long irqflags; + int ret; - /* Map Generic Counter count mode to 104-QUAD-8 count mode */ switch (cnt_mode) { case COUNTER_COUNT_MODE_NORMAL: - count_mode = 0; + count_mode = NORMAL_COUNT; break; case COUNTER_COUNT_MODE_RANGE_LIMIT: - count_mode = 1; + count_mode = RANGE_LIMIT; break; case COUNTER_COUNT_MODE_NON_RECYCLE: - count_mode = 2; + count_mode = NON_RECYCLE_COUNT; break; case COUNTER_COUNT_MODE_MODULO_N: - count_mode = 3; + count_mode = MODULO_N; break; default: /* should never reach this path */ @@ -698,21 +758,12 @@ static int quad8_count_mode_write(struct counter_device *counter, spin_lock_irqsave(&priv->lock, irqflags); - priv->count_mode[count->id] = count_mode; - - /* Set count mode configuration value */ - mode_cfg = count_mode << 1; - - /* Add quadrature mode configuration */ - if (priv->quadrature_mode[count->id]) - mode_cfg |= (priv->quadrature_scale[count->id] + 1) << 3; - - /* Load mode configuration to Counter Mode Register */ - iowrite8(QUAD8_CTR_CMR | mode_cfg, control); + ret = quad8_control_register_update(priv->map, priv->cmr, count->id, count_mode, + COUNT_MODE); spin_unlock_irqrestore(&priv->lock, irqflags); - return 0; + return ret; } static int quad8_count_enable_read(struct counter_device *counter, @@ -720,7 +771,7 @@ static int quad8_count_enable_read(struct counter_device *counter, { const struct quad8 *const priv = counter_priv(counter); - *enable = priv->ab_enable[count->id]; + *enable = u8_get_bits(priv->ior[count->id], AB_GATE); return 0; } @@ -729,23 +780,16 @@ static int quad8_count_enable_write(struct counter_device *counter, struct counter_count *count, u8 enable) { struct quad8 *const priv = counter_priv(counter); - u8 __iomem *const control = &priv->reg->channel[count->id].control; unsigned long irqflags; - unsigned int ior_cfg; + int ret; spin_lock_irqsave(&priv->lock, irqflags); - priv->ab_enable[count->id] = enable; - - ior_cfg = enable | priv->preset_enable[count->id] << 1 | - priv->irq_trigger[count->id] << 3; - - /* Load I/O control configuration */ - iowrite8(QUAD8_CTR_IOR | ior_cfg, control); + ret = quad8_control_register_update(priv->map, priv->ior, count->id, enable, AB_GATE); spin_unlock_irqrestore(&priv->lock, irqflags); - return 0; + return ret; } static const char *const quad8_noise_error_states[] = { @@ -757,9 +801,13 @@ static int quad8_error_noise_get(struct counter_device *counter, struct counter_count *count, u32 *noise_error) { const struct quad8 *const priv = counter_priv(counter); - u8 __iomem *const flag_addr = &priv->reg->channel[count->id].control; + unsigned int flag; + int ret; - *noise_error = !!(ioread8(flag_addr) & QUAD8_FLAG_E); + ret = regmap_read(priv->map, QUAD8_CONTROL(count->id), &flag); + if (ret) + return ret; + *noise_error = u8_get_bits(flag, FLAG_E); return 0; } @@ -774,38 +822,24 @@ static int quad8_count_preset_read(struct counter_device *counter, return 0; } -static void quad8_preset_register_set(struct quad8 *const priv, const int id, - const unsigned int preset) -{ - struct channel_reg __iomem *const chan = priv->reg->channel + id; - int i; - - priv->preset[id] = preset; - - /* Reset Byte Pointer */ - iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, &chan->control); - - /* Set Preset Register */ - for (i = 0; i < 3; i++) - iowrite8(preset >> (8 * i), &chan->data); -} - static int quad8_count_preset_write(struct counter_device *counter, struct counter_count *count, u64 preset) { struct quad8 *const priv = counter_priv(counter); unsigned long irqflags; + int ret; if (preset > LS7267_CNTR_MAX) return -ERANGE; spin_lock_irqsave(&priv->lock, irqflags); - quad8_preset_register_set(priv, count->id, preset); + priv->preset[count->id] = preset; + ret = quad8_preset_register_set(priv, count->id, preset); spin_unlock_irqrestore(&priv->lock, irqflags); - return 0; + return ret; } static int quad8_count_ceiling_read(struct counter_device *counter, @@ -817,9 +851,9 @@ static int quad8_count_ceiling_read(struct counter_device *counter, spin_lock_irqsave(&priv->lock, irqflags); /* Range Limit and Modulo-N count modes use preset value as ceiling */ - switch (priv->count_mode[count->id]) { - case 1: - case 3: + switch (u8_get_bits(priv->cmr[count->id], COUNT_MODE)) { + case RANGE_LIMIT: + case MODULO_N: *ceiling = priv->preset[count->id]; break; default: @@ -837,6 +871,7 @@ static int quad8_count_ceiling_write(struct counter_device *counter, { struct quad8 *const priv = counter_priv(counter); unsigned long irqflags; + int ret; if (ceiling > LS7267_CNTR_MAX) return -ERANGE; @@ -844,17 +879,20 @@ static int quad8_count_ceiling_write(struct counter_device *counter, spin_lock_irqsave(&priv->lock, irqflags); /* Range Limit and Modulo-N count modes use preset value as ceiling */ - switch (priv->count_mode[count->id]) { - case 1: - case 3: - quad8_preset_register_set(priv, count->id, ceiling); - spin_unlock_irqrestore(&priv->lock, irqflags); - return 0; + switch (u8_get_bits(priv->cmr[count->id], COUNT_MODE)) { + case RANGE_LIMIT: + case MODULO_N: + priv->preset[count->id] = ceiling; + ret = quad8_preset_register_set(priv, count->id, ceiling); + break; + default: + ret = -EINVAL; + break; } spin_unlock_irqrestore(&priv->lock, irqflags); - return -EINVAL; + return ret; } static int quad8_count_preset_enable_read(struct counter_device *counter, @@ -863,7 +901,8 @@ static int quad8_count_preset_enable_read(struct counter_device *counter, { const struct quad8 *const priv = counter_priv(counter); - *preset_enable = !priv->preset_enable[count->id]; + /* Preset enable is active low in Input/Output Control register */ + *preset_enable = !u8_get_bits(priv->ior[count->id], LOAD_PIN); return 0; } @@ -873,26 +912,18 @@ static int quad8_count_preset_enable_write(struct counter_device *counter, u8 preset_enable) { struct quad8 *const priv = counter_priv(counter); - u8 __iomem *const control = &priv->reg->channel[count->id].control; unsigned long irqflags; - unsigned int ior_cfg; - - /* Preset enable is active low in Input/Output Control register */ - preset_enable = !preset_enable; + int ret; spin_lock_irqsave(&priv->lock, irqflags); - priv->preset_enable[count->id] = preset_enable; - - ior_cfg = priv->ab_enable[count->id] | preset_enable << 1 | - priv->irq_trigger[count->id] << 3; - - /* Load I/O control configuration to Input / Output Control Register */ - iowrite8(QUAD8_CTR_IOR | ior_cfg, control); + /* Preset enable is active low in Input/Output Control register */ + ret = quad8_control_register_update(priv->map, priv->ior, count->id, !preset_enable, + LOAD_PIN); spin_unlock_irqrestore(&priv->lock, irqflags); - return 0; + return ret; } static int quad8_signal_cable_fault_read(struct counter_device *counter, @@ -903,7 +934,7 @@ static int quad8_signal_cable_fault_read(struct counter_device *counter, const size_t channel_id = signal->id / 2; unsigned long irqflags; bool disabled; - unsigned int status; + int ret; spin_lock_irqsave(&priv->lock, irqflags); @@ -914,13 +945,16 @@ static int quad8_signal_cable_fault_read(struct counter_device *counter, return -EINVAL; } - /* Logic 0 = cable fault */ - status = ioread8(&priv->reg->cable_status); + ret = regmap_test_bits(priv->map, QUAD8_CABLE_STATUS, BIT(channel_id)); + if (ret < 0) { + spin_unlock_irqrestore(&priv->lock, irqflags); + return ret; + } spin_unlock_irqrestore(&priv->lock, irqflags); - /* Mask respective channel and invert logic */ - *cable_fault = !(status & BIT(channel_id)); + /* Logic 0 = cable fault */ + *cable_fault = !ret; return 0; } @@ -945,6 +979,7 @@ static int quad8_signal_cable_fault_enable_write(struct counter_device *counter, const size_t channel_id = signal->id / 2; unsigned long irqflags; unsigned int cable_fault_enable; + int ret; spin_lock_irqsave(&priv->lock, irqflags); @@ -956,11 +991,11 @@ static int quad8_signal_cable_fault_enable_write(struct counter_device *counter, /* Enable is active low in Differential Encoder Cable Status register */ cable_fault_enable = ~priv->cable_fault_enable; - iowrite8(cable_fault_enable, &priv->reg->cable_status); + ret = regmap_write(priv->map, QUAD8_CABLE_STATUS, cable_fault_enable); spin_unlock_irqrestore(&priv->lock, irqflags); - return 0; + return ret; } static int quad8_signal_fck_prescaler_read(struct counter_device *counter, @@ -974,30 +1009,37 @@ static int quad8_signal_fck_prescaler_read(struct counter_device *counter, return 0; } +static int quad8_filter_clock_prescaler_set(struct quad8 *const priv, const size_t id, + const u8 prescaler) +{ + int ret; + + ret = regmap_write(priv->map, QUAD8_CONTROL(id), SELECT_RLD | RESET_BP); + if (ret) + return ret; + ret = regmap_write(priv->map, QUAD8_DATA(id), prescaler); + if (ret) + return ret; + return regmap_write(priv->map, QUAD8_CONTROL(id), SELECT_RLD | TRANSFER_PR0_TO_PSC); +} + static int quad8_signal_fck_prescaler_write(struct counter_device *counter, struct counter_signal *signal, u8 prescaler) { struct quad8 *const priv = counter_priv(counter); const size_t channel_id = signal->id / 2; - struct channel_reg __iomem *const chan = priv->reg->channel + channel_id; unsigned long irqflags; + int ret; spin_lock_irqsave(&priv->lock, irqflags); priv->fck_prescaler[channel_id] = prescaler; - - /* Reset Byte Pointer */ - iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, &chan->control); - - /* Set filter clock factor */ - iowrite8(prescaler, &chan->data); - iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP | QUAD8_RLD_PRESET_PSC, - &chan->control); + ret = quad8_filter_clock_prescaler_set(priv, channel_id, prescaler); spin_unlock_irqrestore(&priv->lock, irqflags); - return 0; + return ret; } static struct counter_comp quad8_signal_ext[] = { @@ -1150,77 +1192,93 @@ static irqreturn_t quad8_irq_handler(int irq, void *private) { struct counter_device *counter = private; struct quad8 *const priv = counter_priv(counter); + unsigned int status; unsigned long irq_status; unsigned long channel; + unsigned int flg_pins; u8 event; + int ret; - irq_status = ioread8(&priv->reg->interrupt_status); - if (!irq_status) + ret = regmap_read(priv->map, QUAD8_INTERRUPT_STATUS, &status); + if (ret) + return ret; + if (!status) return IRQ_NONE; + irq_status = status; for_each_set_bit(channel, &irq_status, QUAD8_NUM_COUNTERS) { - switch (priv->irq_trigger[channel]) { - case QUAD8_EVENT_CARRY: + flg_pins = u8_get_bits(priv->ior[channel], FLG_PINS); + switch (flg_pins) { + case FLG1_CARRY_FLG2_BORROW: event = COUNTER_EVENT_OVERFLOW; break; - case QUAD8_EVENT_COMPARE: + case FLG1_COMPARE_FLG2_BORROW: event = COUNTER_EVENT_THRESHOLD; break; - case QUAD8_EVENT_CARRY_BORROW: + case FLG1_CARRYBORROW_FLG2_UD: event = COUNTER_EVENT_OVERFLOW_UNDERFLOW; break; - case QUAD8_EVENT_INDEX: + case FLG1_INDX_FLG2_E: event = COUNTER_EVENT_INDEX; break; default: /* should never reach this path */ WARN_ONCE(true, "invalid interrupt trigger function %u configured for channel %lu\n", - priv->irq_trigger[channel], channel); + flg_pins, channel); continue; } counter_push_event(counter, event, channel); } - /* Clear pending interrupts on device */ - iowrite8(QUAD8_CHAN_OP_ENABLE_INTERRUPT_FUNC, &priv->reg->channel_oper); + ret = regmap_write(priv->map, QUAD8_CHANNEL_OPERATION, CLEAR_PENDING_INTERRUPTS); + if (ret) + return ret; return IRQ_HANDLED; } -static void quad8_init_counter(struct channel_reg __iomem *const chan) +static int quad8_init_counter(struct quad8 *const priv, const size_t channel) { - unsigned long i; + int ret; + + ret = quad8_filter_clock_prescaler_set(priv, channel, 0); + if (ret) + return ret; + ret = quad8_preset_register_set(priv, channel, 0); + if (ret) + return ret; + ret = quad8_flag_register_reset(priv, channel); + if (ret) + return ret; - /* Reset Byte Pointer */ - iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, &chan->control); - /* Reset filter clock factor */ - iowrite8(0, &chan->data); - iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP | QUAD8_RLD_PRESET_PSC, - &chan->control); - /* Reset Byte Pointer */ - iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, &chan->control); - /* Reset Preset Register */ - for (i = 0; i < 3; i++) - iowrite8(0x00, &chan->data); - /* Reset Borrow, Carry, Compare, and Sign flags */ - iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_FLAGS, &chan->control); - /* Reset Error flag */ - iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_E, &chan->control); /* Binary encoding; Normal count; non-quadrature mode */ - iowrite8(QUAD8_CTR_CMR, &chan->control); + priv->cmr[channel] = SELECT_CMR | BINARY | u8_encode_bits(NORMAL_COUNT, COUNT_MODE) | + u8_encode_bits(NON_QUADRATURE, QUADRATURE_MODE); + ret = regmap_write(priv->map, QUAD8_CONTROL(channel), priv->cmr[channel]); + if (ret) + return ret; + /* Disable A and B inputs; preset on index; FLG1 as Carry */ - iowrite8(QUAD8_CTR_IOR, &chan->control); + priv->ior[channel] = SELECT_IOR | DISABLE_AB | u8_encode_bits(LOAD_CNTR, LOAD_PIN) | + u8_encode_bits(FLG1_CARRY_FLG2_BORROW, FLG_PINS); + ret = regmap_write(priv->map, QUAD8_CONTROL(channel), priv->ior[channel]); + if (ret) + return ret; + /* Disable index function; negative index polarity */ - iowrite8(QUAD8_CTR_IDR, &chan->control); + priv->idr[channel] = SELECT_IDR | u8_encode_bits(DISABLE_INDEX_MODE, INDEX_MODE) | + u8_encode_bits(NEGATIVE_INDEX_POLARITY, INDEX_POLARITY); + return regmap_write(priv->map, QUAD8_CONTROL(channel), priv->idr[channel]); } static int quad8_probe(struct device *dev, unsigned int id) { struct counter_device *counter; struct quad8 *priv; + void __iomem *regs; unsigned long i; - int err; + int ret; if (!devm_request_region(dev, base[id], QUAD8_EXTENT, dev_name(dev))) { dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n", @@ -1233,10 +1291,15 @@ static int quad8_probe(struct device *dev, unsigned int id) return -ENOMEM; priv = counter_priv(counter); - priv->reg = devm_ioport_map(dev, base[id], QUAD8_EXTENT); - if (!priv->reg) + regs = devm_ioport_map(dev, base[id], QUAD8_EXTENT); + if (!regs) return -ENOMEM; + priv->map = devm_regmap_init_mmio(dev, regs, &quad8_regmap_config); + if (IS_ERR(priv->map)) + return dev_err_probe(dev, PTR_ERR(priv->map), + "Unable to initialize register map\n"); + /* Initialize Counter device and driver data */ counter->name = dev_name(dev); counter->parent = dev; @@ -1249,25 +1312,38 @@ static int quad8_probe(struct device *dev, unsigned int id) spin_lock_init(&priv->lock); /* Reset Index/Interrupt Register */ - iowrite8(0x00, &priv->reg->index_interrupt); + ret = regmap_write(priv->map, QUAD8_INDEX_INTERRUPT, 0x00); + if (ret) + return ret; /* Reset all counters and disable interrupt function */ - iowrite8(QUAD8_CHAN_OP_RESET_COUNTERS, &priv->reg->channel_oper); + ret = regmap_write(priv->map, QUAD8_CHANNEL_OPERATION, + RESET_COUNTERS | DISABLE_INTERRUPT_FUNCTION); + if (ret) + return ret; /* Set initial configuration for all counters */ - for (i = 0; i < QUAD8_NUM_COUNTERS; i++) - quad8_init_counter(priv->reg->channel + i); + for (i = 0; i < QUAD8_NUM_COUNTERS; i++) { + ret = quad8_init_counter(priv, i); + if (ret) + return ret; + } /* Disable Differential Encoder Cable Status for all channels */ - iowrite8(0xFF, &priv->reg->cable_status); + ret = regmap_write(priv->map, QUAD8_CABLE_STATUS, GENMASK(7, 0)); + if (ret) + return ret; /* Enable all counters and enable interrupt function */ - iowrite8(QUAD8_CHAN_OP_ENABLE_INTERRUPT_FUNC, &priv->reg->channel_oper); + ret = regmap_write(priv->map, QUAD8_CHANNEL_OPERATION, + ENABLE_COUNTERS | ENABLE_INTERRUPT_FUNCTION); + if (ret) + return ret; - err = devm_request_irq(&counter->dev, irq[id], quad8_irq_handler, + ret = devm_request_irq(&counter->dev, irq[id], quad8_irq_handler, IRQF_SHARED, counter->name, counter); - if (err) - return err; + if (ret) + return ret; - err = devm_counter_add(dev, counter); - if (err < 0) - return dev_err_probe(dev, err, "Failed to add counter\n"); + ret = devm_counter_add(dev, counter); + if (ret < 0) + return dev_err_probe(dev, ret, "Failed to add counter\n"); return 0; } diff --git a/drivers/counter/Kconfig b/drivers/counter/Kconfig index 4228be917038dec3ab3cd3ffe42c719c038b99b1..bca21df5116865b5fe8138c54f7003211c4ed8e2 100644 --- a/drivers/counter/Kconfig +++ b/drivers/counter/Kconfig @@ -10,20 +10,37 @@ menuconfig COUNTER interface. You only need to enable this, if you also want to enable one or more of the counter device drivers below. +config I8254 + tristate + select COUNTER + select REGMAP + help + Enables support for the i8254 interface library functions. The i8254 + interface library provides functions to facilitate communication with + interfaces compatible with the venerable Intel 8254 Programmable + Interval Timer (PIT). The Intel 825x family of chips was first + released in the early 1980s but compatible interfaces are nowadays + typically found embedded in larger VLSI processing chips and FPGA + components. + + If built as a module its name will be i8254. + if COUNTER config 104_QUAD_8 tristate "ACCES 104-QUAD-8 driver" depends on (PC104 && X86) || COMPILE_TEST + depends on HAS_IOPORT_MAP select ISA_BUS_API + select REGMAP_MMIO help Say yes here to build support for the ACCES 104-QUAD-8 quadrature encoder counter/interface device family (104-QUAD-8, 104-QUAD-4). A counter's respective error flag may be cleared by performing a write - operation on the respective count value attribute. Although the - 104-QUAD-8 counters have a 25-bit range, only the lower 24 bits may be - set, either directly or via the counter's preset attribute. + operation on the respective count value attribute. The 104-QUAD-8 + counters may be set either directly or via the counter's preset + attribute. The base port addresses for the devices may be configured via the base array module parameter. The interrupt line numbers for the devices may diff --git a/drivers/counter/Makefile b/drivers/counter/Makefile index 933fdd50b3e4cf7ee6e745e4ebebede77b28c317..fa3c1d08f7068835aa912aa13bc92bcfd44d16fb 100644 --- a/drivers/counter/Makefile +++ b/drivers/counter/Makefile @@ -6,6 +6,7 @@ obj-$(CONFIG_COUNTER) += counter.o counter-y := counter-core.o counter-sysfs.o counter-chrdev.o +obj-$(CONFIG_I8254) += i8254.o obj-$(CONFIG_104_QUAD_8) += 104-quad-8.o obj-$(CONFIG_INTERRUPT_CNT) += interrupt-cnt.o obj-$(CONFIG_RZ_MTU3_CNT) += rz-mtu3-cnt.o diff --git a/drivers/counter/counter-sysfs.c b/drivers/counter/counter-sysfs.c index b9efe66f9f8d86fb8e337a3d7ca285d0d9e39bbc..42c523343d32870834e29ef5b507eacdae00e302 100644 --- a/drivers/counter/counter-sysfs.c +++ b/drivers/counter/counter-sysfs.c @@ -88,7 +88,13 @@ static const char *const counter_count_mode_str[] = { [COUNTER_COUNT_MODE_NORMAL] = "normal", [COUNTER_COUNT_MODE_RANGE_LIMIT] = "range limit", [COUNTER_COUNT_MODE_NON_RECYCLE] = "non-recycle", - [COUNTER_COUNT_MODE_MODULO_N] = "modulo-n" + [COUNTER_COUNT_MODE_MODULO_N] = "modulo-n", + [COUNTER_COUNT_MODE_INTERRUPT_ON_TERMINAL_COUNT] = "interrupt on terminal count", + [COUNTER_COUNT_MODE_HARDWARE_RETRIGGERABLE_ONESHOT] = "hardware retriggerable one-shot", + [COUNTER_COUNT_MODE_RATE_GENERATOR] = "rate generator", + [COUNTER_COUNT_MODE_SQUARE_WAVE_MODE] = "square wave mode", + [COUNTER_COUNT_MODE_SOFTWARE_TRIGGERED_STROBE] = "software triggered strobe", + [COUNTER_COUNT_MODE_HARDWARE_TRIGGERED_STROBE] = "hardware triggered strobe", }; static const char *const counter_signal_polarity_str[] = { diff --git a/drivers/counter/i8254.c b/drivers/counter/i8254.c new file mode 100644 index 0000000000000000000000000000000000000000..c41e4fdc96011752a55b029a2a76e668cda16ce6 --- /dev/null +++ b/drivers/counter/i8254.c @@ -0,0 +1,447 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Intel 8254 Programmable Interval Timer + * Copyright (C) William Breathitt Gray + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define I8254_COUNTER_REG(_counter) (_counter) +#define I8254_CONTROL_REG 0x3 + +#define I8254_SC GENMASK(7, 6) +#define I8254_RW GENMASK(5, 4) +#define I8254_M GENMASK(3, 1) +#define I8254_CONTROL(_sc, _rw, _m) \ + (u8_encode_bits(_sc, I8254_SC) | u8_encode_bits(_rw, I8254_RW) | \ + u8_encode_bits(_m, I8254_M)) + +#define I8254_RW_TWO_BYTE 0x3 +#define I8254_MODE_INTERRUPT_ON_TERMINAL_COUNT 0 +#define I8254_MODE_HARDWARE_RETRIGGERABLE_ONESHOT 1 +#define I8254_MODE_RATE_GENERATOR 2 +#define I8254_MODE_SQUARE_WAVE_MODE 3 +#define I8254_MODE_SOFTWARE_TRIGGERED_STROBE 4 +#define I8254_MODE_HARDWARE_TRIGGERED_STROBE 5 + +#define I8254_COUNTER_LATCH(_counter) I8254_CONTROL(_counter, 0x0, 0x0) +#define I8254_PROGRAM_COUNTER(_counter, _mode) I8254_CONTROL(_counter, I8254_RW_TWO_BYTE, _mode) + +#define I8254_NUM_COUNTERS 3 + +/** + * struct i8254 - I8254 device private data structure + * @lock: synchronization lock to prevent I/O race conditions + * @preset: array of Counter Register states + * @out_mode: array of mode configuration states + * @map: Regmap for the device + */ +struct i8254 { + struct mutex lock; + u16 preset[I8254_NUM_COUNTERS]; + u8 out_mode[I8254_NUM_COUNTERS]; + struct regmap *map; +}; + +static int i8254_count_read(struct counter_device *const counter, struct counter_count *const count, + u64 *const val) +{ + struct i8254 *const priv = counter_priv(counter); + int ret; + u8 value[2]; + + mutex_lock(&priv->lock); + + ret = regmap_write(priv->map, I8254_CONTROL_REG, I8254_COUNTER_LATCH(count->id)); + if (ret) { + mutex_unlock(&priv->lock); + return ret; + } + ret = regmap_noinc_read(priv->map, I8254_COUNTER_REG(count->id), value, sizeof(value)); + if (ret) { + mutex_unlock(&priv->lock); + return ret; + } + + mutex_unlock(&priv->lock); + + *val = get_unaligned_le16(value); + + return ret; +} + +static int i8254_function_read(struct counter_device *const counter, + struct counter_count *const count, + enum counter_function *const function) +{ + *function = COUNTER_FUNCTION_DECREASE; + return 0; +} + +#define I8254_SYNAPSES_PER_COUNT 2 +#define I8254_SIGNAL_ID_CLK 0 +#define I8254_SIGNAL_ID_GATE 1 + +static int i8254_action_read(struct counter_device *const counter, + struct counter_count *const count, + struct counter_synapse *const synapse, + enum counter_synapse_action *const action) +{ + struct i8254 *const priv = counter_priv(counter); + + switch (synapse->signal->id % I8254_SYNAPSES_PER_COUNT) { + case I8254_SIGNAL_ID_CLK: + *action = COUNTER_SYNAPSE_ACTION_FALLING_EDGE; + return 0; + case I8254_SIGNAL_ID_GATE: + switch (priv->out_mode[count->id]) { + case I8254_MODE_HARDWARE_RETRIGGERABLE_ONESHOT: + case I8254_MODE_RATE_GENERATOR: + case I8254_MODE_SQUARE_WAVE_MODE: + case I8254_MODE_HARDWARE_TRIGGERED_STROBE: + *action = COUNTER_SYNAPSE_ACTION_RISING_EDGE; + return 0; + default: + *action = COUNTER_SYNAPSE_ACTION_NONE; + return 0; + } + default: + /* should never reach this path */ + return -EINVAL; + } +} + +static int i8254_count_ceiling_read(struct counter_device *const counter, + struct counter_count *const count, u64 *const ceiling) +{ + struct i8254 *const priv = counter_priv(counter); + + mutex_lock(&priv->lock); + + switch (priv->out_mode[count->id]) { + case I8254_MODE_RATE_GENERATOR: + /* Rate Generator decrements 0 by one and the counter "wraps around" */ + *ceiling = (priv->preset[count->id] == 0) ? U16_MAX : priv->preset[count->id]; + break; + case I8254_MODE_SQUARE_WAVE_MODE: + if (priv->preset[count->id] % 2) + *ceiling = priv->preset[count->id] - 1; + else if (priv->preset[count->id] == 0) + /* Square Wave Mode decrements 0 by two and the counter "wraps around" */ + *ceiling = U16_MAX - 1; + else + *ceiling = priv->preset[count->id]; + break; + default: + *ceiling = U16_MAX; + break; + } + + mutex_unlock(&priv->lock); + + return 0; +} + +static int i8254_count_mode_read(struct counter_device *const counter, + struct counter_count *const count, + enum counter_count_mode *const count_mode) +{ + const struct i8254 *const priv = counter_priv(counter); + + switch (priv->out_mode[count->id]) { + case I8254_MODE_INTERRUPT_ON_TERMINAL_COUNT: + *count_mode = COUNTER_COUNT_MODE_INTERRUPT_ON_TERMINAL_COUNT; + return 0; + case I8254_MODE_HARDWARE_RETRIGGERABLE_ONESHOT: + *count_mode = COUNTER_COUNT_MODE_HARDWARE_RETRIGGERABLE_ONESHOT; + return 0; + case I8254_MODE_RATE_GENERATOR: + *count_mode = COUNTER_COUNT_MODE_RATE_GENERATOR; + return 0; + case I8254_MODE_SQUARE_WAVE_MODE: + *count_mode = COUNTER_COUNT_MODE_SQUARE_WAVE_MODE; + return 0; + case I8254_MODE_SOFTWARE_TRIGGERED_STROBE: + *count_mode = COUNTER_COUNT_MODE_SOFTWARE_TRIGGERED_STROBE; + return 0; + case I8254_MODE_HARDWARE_TRIGGERED_STROBE: + *count_mode = COUNTER_COUNT_MODE_HARDWARE_TRIGGERED_STROBE; + return 0; + default: + /* should never reach this path */ + return -EINVAL; + } +} + +static int i8254_count_mode_write(struct counter_device *const counter, + struct counter_count *const count, + const enum counter_count_mode count_mode) +{ + struct i8254 *const priv = counter_priv(counter); + u8 out_mode; + int ret; + + switch (count_mode) { + case COUNTER_COUNT_MODE_INTERRUPT_ON_TERMINAL_COUNT: + out_mode = I8254_MODE_INTERRUPT_ON_TERMINAL_COUNT; + break; + case COUNTER_COUNT_MODE_HARDWARE_RETRIGGERABLE_ONESHOT: + out_mode = I8254_MODE_HARDWARE_RETRIGGERABLE_ONESHOT; + break; + case COUNTER_COUNT_MODE_RATE_GENERATOR: + out_mode = I8254_MODE_RATE_GENERATOR; + break; + case COUNTER_COUNT_MODE_SQUARE_WAVE_MODE: + out_mode = I8254_MODE_SQUARE_WAVE_MODE; + break; + case COUNTER_COUNT_MODE_SOFTWARE_TRIGGERED_STROBE: + out_mode = I8254_MODE_SOFTWARE_TRIGGERED_STROBE; + break; + case COUNTER_COUNT_MODE_HARDWARE_TRIGGERED_STROBE: + out_mode = I8254_MODE_HARDWARE_TRIGGERED_STROBE; + break; + default: + /* should never reach this path */ + return -EINVAL; + } + + mutex_lock(&priv->lock); + + /* Counter Register is cleared when the counter is programmed */ + priv->preset[count->id] = 0; + priv->out_mode[count->id] = out_mode; + ret = regmap_write(priv->map, I8254_CONTROL_REG, + I8254_PROGRAM_COUNTER(count->id, out_mode)); + + mutex_unlock(&priv->lock); + + return ret; +} + +static int i8254_count_floor_read(struct counter_device *const counter, + struct counter_count *const count, u64 *const floor) +{ + struct i8254 *const priv = counter_priv(counter); + + mutex_lock(&priv->lock); + + switch (priv->out_mode[count->id]) { + case I8254_MODE_RATE_GENERATOR: + /* counter is always reloaded after 1, but 0 is a possible reload value */ + *floor = (priv->preset[count->id] == 0) ? 0 : 1; + break; + case I8254_MODE_SQUARE_WAVE_MODE: + /* counter is always reloaded after 2 for even preset values */ + *floor = (priv->preset[count->id] % 2 || priv->preset[count->id] == 0) ? 0 : 2; + break; + default: + *floor = 0; + break; + } + + mutex_unlock(&priv->lock); + + return 0; +} + +static int i8254_count_preset_read(struct counter_device *const counter, + struct counter_count *const count, u64 *const preset) +{ + const struct i8254 *const priv = counter_priv(counter); + + *preset = priv->preset[count->id]; + + return 0; +} + +static int i8254_count_preset_write(struct counter_device *const counter, + struct counter_count *const count, const u64 preset) +{ + struct i8254 *const priv = counter_priv(counter); + int ret; + u8 value[2]; + + if (preset > U16_MAX) + return -ERANGE; + + mutex_lock(&priv->lock); + + if (priv->out_mode[count->id] == I8254_MODE_RATE_GENERATOR || + priv->out_mode[count->id] == I8254_MODE_SQUARE_WAVE_MODE) { + if (preset == 1) { + mutex_unlock(&priv->lock); + return -EINVAL; + } + } + + priv->preset[count->id] = preset; + + put_unaligned_le16(preset, value); + ret = regmap_noinc_write(priv->map, I8254_COUNTER_REG(count->id), value, 2); + + mutex_unlock(&priv->lock); + + return ret; +} + +static int i8254_init_hw(struct regmap *const map) +{ + unsigned long i; + int ret; + + for (i = 0; i < I8254_NUM_COUNTERS; i++) { + /* Initialize each counter to Mode 0 */ + ret = regmap_write(map, I8254_CONTROL_REG, + I8254_PROGRAM_COUNTER(i, I8254_MODE_INTERRUPT_ON_TERMINAL_COUNT)); + if (ret) + return ret; + } + + return 0; +} + +static const struct counter_ops i8254_ops = { + .count_read = i8254_count_read, + .function_read = i8254_function_read, + .action_read = i8254_action_read, +}; + +#define I8254_SIGNAL(_id, _name) { \ + .id = (_id), \ + .name = (_name), \ +} + +static struct counter_signal i8254_signals[] = { + I8254_SIGNAL(0, "CLK 0"), I8254_SIGNAL(1, "GATE 0"), + I8254_SIGNAL(2, "CLK 1"), I8254_SIGNAL(3, "GATE 1"), + I8254_SIGNAL(4, "CLK 2"), I8254_SIGNAL(5, "GATE 2"), +}; + +static const enum counter_synapse_action i8254_clk_actions[] = { + COUNTER_SYNAPSE_ACTION_FALLING_EDGE, +}; +static const enum counter_synapse_action i8254_gate_actions[] = { + COUNTER_SYNAPSE_ACTION_NONE, + COUNTER_SYNAPSE_ACTION_RISING_EDGE, +}; + +#define I8254_SYNAPSES_BASE(_id) ((_id) * I8254_SYNAPSES_PER_COUNT) +#define I8254_SYNAPSE_CLK(_id) { \ + .actions_list = i8254_clk_actions, \ + .num_actions = ARRAY_SIZE(i8254_clk_actions), \ + .signal = &i8254_signals[I8254_SYNAPSES_BASE(_id) + 0], \ +} +#define I8254_SYNAPSE_GATE(_id) { \ + .actions_list = i8254_gate_actions, \ + .num_actions = ARRAY_SIZE(i8254_gate_actions), \ + .signal = &i8254_signals[I8254_SYNAPSES_BASE(_id) + 1], \ +} + +static struct counter_synapse i8254_synapses[] = { + I8254_SYNAPSE_CLK(0), I8254_SYNAPSE_GATE(0), + I8254_SYNAPSE_CLK(1), I8254_SYNAPSE_GATE(1), + I8254_SYNAPSE_CLK(2), I8254_SYNAPSE_GATE(2), +}; + +static const enum counter_function i8254_functions_list[] = { + COUNTER_FUNCTION_DECREASE, +}; + +static const enum counter_count_mode i8254_count_modes[] = { + COUNTER_COUNT_MODE_INTERRUPT_ON_TERMINAL_COUNT, + COUNTER_COUNT_MODE_HARDWARE_RETRIGGERABLE_ONESHOT, + COUNTER_COUNT_MODE_RATE_GENERATOR, + COUNTER_COUNT_MODE_SQUARE_WAVE_MODE, + COUNTER_COUNT_MODE_SOFTWARE_TRIGGERED_STROBE, + COUNTER_COUNT_MODE_HARDWARE_TRIGGERED_STROBE, +}; + +static DEFINE_COUNTER_AVAILABLE(i8254_count_modes_available, i8254_count_modes); + +static struct counter_comp i8254_count_ext[] = { + COUNTER_COMP_CEILING(i8254_count_ceiling_read, NULL), + COUNTER_COMP_COUNT_MODE(i8254_count_mode_read, i8254_count_mode_write, + i8254_count_modes_available), + COUNTER_COMP_FLOOR(i8254_count_floor_read, NULL), + COUNTER_COMP_PRESET(i8254_count_preset_read, i8254_count_preset_write), +}; + +#define I8254_COUNT(_id, _name) { \ + .id = (_id), \ + .name = (_name), \ + .functions_list = i8254_functions_list, \ + .num_functions = ARRAY_SIZE(i8254_functions_list), \ + .synapses = &i8254_synapses[I8254_SYNAPSES_BASE(_id)], \ + .num_synapses = I8254_SYNAPSES_PER_COUNT, \ + .ext = i8254_count_ext, \ + .num_ext = ARRAY_SIZE(i8254_count_ext) \ +} + +static struct counter_count i8254_counts[I8254_NUM_COUNTERS] = { + I8254_COUNT(0, "Counter 0"), I8254_COUNT(1, "Counter 1"), I8254_COUNT(2, "Counter 2"), +}; + +/** + * devm_i8254_regmap_register - Register an i8254 Counter device + * @dev: device that is registering this i8254 Counter device + * @config: configuration for i8254_regmap_config + * + * Registers an Intel 8254 Programmable Interval Timer Counter device. Returns 0 on success and + * negative error number on failure. + */ +int devm_i8254_regmap_register(struct device *const dev, + const struct i8254_regmap_config *const config) +{ + struct counter_device *counter; + struct i8254 *priv; + int err; + + if (!config->parent) + return -EINVAL; + + if (!config->map) + return -EINVAL; + + counter = devm_counter_alloc(dev, sizeof(*priv)); + if (!counter) + return -ENOMEM; + priv = counter_priv(counter); + priv->map = config->map; + + counter->name = dev_name(config->parent); + counter->parent = config->parent; + counter->ops = &i8254_ops; + counter->counts = i8254_counts; + counter->num_counts = ARRAY_SIZE(i8254_counts); + counter->signals = i8254_signals; + counter->num_signals = ARRAY_SIZE(i8254_signals); + + mutex_init(&priv->lock); + + err = i8254_init_hw(priv->map); + if (err) + return err; + + err = devm_counter_add(dev, counter); + if (err < 0) + return dev_err_probe(dev, err, "Failed to add counter\n"); + + return 0; +} +EXPORT_SYMBOL_NS_GPL(devm_i8254_regmap_register, I8254); + +MODULE_AUTHOR("William Breathitt Gray"); +MODULE_DESCRIPTION("Intel 8254 Programmable Interval Timer"); +MODULE_LICENSE("GPL"); +MODULE_IMPORT_NS(COUNTER); diff --git a/drivers/counter/stm32-timer-cnt.c b/drivers/counter/stm32-timer-cnt.c index 9bf20a5d6bda8f9d4f47821708588a922bea36f8..6206d2dc3d47098aea85d854ad212dac9751baee 100644 --- a/drivers/counter/stm32-timer-cnt.c +++ b/drivers/counter/stm32-timer-cnt.c @@ -342,6 +342,9 @@ static int stm32_timer_cnt_probe(struct platform_device *pdev) platform_set_drvdata(pdev, priv); + /* Reset input selector to its default input */ + regmap_write(priv->regmap, TIM_TISEL, 0x0); + /* Register Counter device */ ret = devm_counter_add(dev, counter); if (ret < 0) diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig index 2c839bd2b051ed0d538c8ee89fdf2fa61ce63216..f429b9b37b76c7e45e0c0cd9eb38980666ff597d 100644 --- a/drivers/cpufreq/Kconfig +++ b/drivers/cpufreq/Kconfig @@ -38,7 +38,7 @@ choice prompt "Default CPUFreq governor" default CPU_FREQ_DEFAULT_GOV_USERSPACE if ARM_SA1110_CPUFREQ default CPU_FREQ_DEFAULT_GOV_SCHEDUTIL if ARM64 || ARM - default CPU_FREQ_DEFAULT_GOV_SCHEDUTIL if X86_INTEL_PSTATE && SMP + default CPU_FREQ_DEFAULT_GOV_SCHEDUTIL if (X86_INTEL_PSTATE || X86_AMD_PSTATE) && SMP default CPU_FREQ_DEFAULT_GOV_PERFORMANCE help This option sets which CPUFreq governor shall be loaded at @@ -218,7 +218,8 @@ config CPUFREQ_DT If in doubt, say N. config CPUFREQ_DT_PLATDEV - bool + tristate "Generic DT based cpufreq platdev driver" + depends on OF help This adds a generic DT based cpufreq platdev driver for frequency management. This creates a 'cpufreq-dt' platform device, on the diff --git a/drivers/cpufreq/Kconfig.x86 b/drivers/cpufreq/Kconfig.x86 index 00476e94db9059d69cf890906d18c67eacb5dd2a..438c9e75a04dc83d8b75f359935dfb1b021af9a0 100644 --- a/drivers/cpufreq/Kconfig.x86 +++ b/drivers/cpufreq/Kconfig.x86 @@ -51,6 +51,23 @@ config X86_AMD_PSTATE If in doubt, say N. +config X86_AMD_PSTATE_DEFAULT_MODE + int "AMD Processor P-State default mode" + depends on X86_AMD_PSTATE + default 3 if X86_AMD_PSTATE + range 1 4 + help + Select the default mode the amd-pstate driver will use on + supported hardware. + The value set has the following meanings: + 1 -> Disabled + 2 -> Passive + 3 -> Active (EPP) + 4 -> Guided + + For details, take a look at: + . + config X86_AMD_PSTATE_UT tristate "selftest for AMD Processor P-State driver" depends on X86 && ACPI_PROCESSOR diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c index ddd346a239e0b55acfaef158cb12ea1a8612f948..81fba0dcbee9904afc610a0aa7bffe9ebba6760e 100644 --- a/drivers/cpufreq/amd-pstate.c +++ b/drivers/cpufreq/amd-pstate.c @@ -62,7 +62,8 @@ static struct cpufreq_driver *current_pstate_driver; static struct cpufreq_driver amd_pstate_driver; static struct cpufreq_driver amd_pstate_epp_driver; -static int cppc_state = AMD_PSTATE_DISABLE; +static int cppc_state = AMD_PSTATE_UNDEFINED; +static bool cppc_enabled; /* * AMD Energy Preference Performance (EPP) @@ -228,7 +229,28 @@ static int amd_pstate_set_energy_pref_index(struct amd_cpudata *cpudata, static inline int pstate_enable(bool enable) { - return wrmsrl_safe(MSR_AMD_CPPC_ENABLE, enable); + int ret, cpu; + unsigned long logical_proc_id_mask = 0; + + if (enable == cppc_enabled) + return 0; + + for_each_present_cpu(cpu) { + unsigned long logical_id = topology_logical_die_id(cpu); + + if (test_bit(logical_id, &logical_proc_id_mask)) + continue; + + set_bit(logical_id, &logical_proc_id_mask); + + ret = wrmsrl_safe_on_cpu(cpu, MSR_AMD_CPPC_ENABLE, + enable); + if (ret) + return ret; + } + + cppc_enabled = enable; + return 0; } static int cppc_enable(bool enable) @@ -236,6 +258,9 @@ static int cppc_enable(bool enable) int cpu, ret = 0; struct cppc_perf_ctrls perf_ctrls; + if (enable == cppc_enabled) + return 0; + for_each_present_cpu(cpu) { ret = cppc_set_enable(cpu, enable); if (ret) @@ -251,6 +276,7 @@ static int cppc_enable(bool enable) } } + cppc_enabled = enable; return ret; } @@ -1045,6 +1071,26 @@ static const struct attribute_group amd_pstate_global_attr_group = { .attrs = pstate_global_attributes, }; +static bool amd_pstate_acpi_pm_profile_server(void) +{ + switch (acpi_gbl_FADT.preferred_profile) { + case PM_ENTERPRISE_SERVER: + case PM_SOHO_SERVER: + case PM_PERFORMANCE_SERVER: + return true; + } + return false; +} + +static bool amd_pstate_acpi_pm_profile_undefined(void) +{ + if (acpi_gbl_FADT.preferred_profile == PM_UNSPECIFIED) + return true; + if (acpi_gbl_FADT.preferred_profile >= NR_PM_PROFILES) + return true; + return false; +} + static int amd_pstate_epp_cpu_init(struct cpufreq_policy *policy) { int min_freq, max_freq, nominal_freq, lowest_nonlinear_freq, ret; @@ -1102,10 +1148,14 @@ static int amd_pstate_epp_cpu_init(struct cpufreq_policy *policy) policy->max = policy->cpuinfo.max_freq; /* - * Set the policy to powersave to provide a valid fallback value in case + * Set the policy to provide a valid fallback value in case * the default cpufreq governor is neither powersave nor performance. */ - policy->policy = CPUFREQ_POLICY_POWERSAVE; + if (amd_pstate_acpi_pm_profile_server() || + amd_pstate_acpi_pm_profile_undefined()) + policy->policy = CPUFREQ_POLICY_PERFORMANCE; + else + policy->policy = CPUFREQ_POLICY_POWERSAVE; if (boot_cpu_has(X86_FEATURE_CPPC)) { ret = rdmsrl_on_cpu(cpudata->cpu, MSR_AMD_CPPC_REQ, &value); @@ -1356,10 +1406,29 @@ static struct cpufreq_driver amd_pstate_epp_driver = { .online = amd_pstate_epp_cpu_online, .suspend = amd_pstate_epp_suspend, .resume = amd_pstate_epp_resume, - .name = "amd_pstate_epp", + .name = "amd-pstate-epp", .attr = amd_pstate_epp_attr, }; +static int __init amd_pstate_set_driver(int mode_idx) +{ + if (mode_idx >= AMD_PSTATE_DISABLE && mode_idx < AMD_PSTATE_MAX) { + cppc_state = mode_idx; + if (cppc_state == AMD_PSTATE_DISABLE) + pr_info("driver is explicitly disabled\n"); + + if (cppc_state == AMD_PSTATE_ACTIVE) + current_pstate_driver = &amd_pstate_epp_driver; + + if (cppc_state == AMD_PSTATE_PASSIVE || cppc_state == AMD_PSTATE_GUIDED) + current_pstate_driver = &amd_pstate_driver; + + return 0; + } + + return -EINVAL; +} + static int __init amd_pstate_init(void) { struct device *dev_root; @@ -1367,15 +1436,6 @@ static int __init amd_pstate_init(void) if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD) return -ENODEV; - /* - * by default the pstate driver is disabled to load - * enable the amd_pstate passive mode driver explicitly - * with amd_pstate=passive or other modes in kernel command line - */ - if (cppc_state == AMD_PSTATE_DISABLE) { - pr_info("driver load is disabled, boot with specific mode to enable this\n"); - return -ENODEV; - } if (!acpi_cpc_valid()) { pr_warn_once("the _CPC object is not present in SBIOS or ACPI disabled\n"); @@ -1386,6 +1446,33 @@ static int __init amd_pstate_init(void) if (cpufreq_get_current_driver()) return -EEXIST; + switch (cppc_state) { + case AMD_PSTATE_UNDEFINED: + /* Disable on the following configs by default: + * 1. Undefined platforms + * 2. Server platforms + * 3. Shared memory designs + */ + if (amd_pstate_acpi_pm_profile_undefined() || + amd_pstate_acpi_pm_profile_server() || + !boot_cpu_has(X86_FEATURE_CPPC)) { + pr_info("driver load is disabled, boot with specific mode to enable this\n"); + return -ENODEV; + } + ret = amd_pstate_set_driver(CONFIG_X86_AMD_PSTATE_DEFAULT_MODE); + if (ret) + return ret; + break; + case AMD_PSTATE_DISABLE: + return -ENODEV; + case AMD_PSTATE_PASSIVE: + case AMD_PSTATE_ACTIVE: + case AMD_PSTATE_GUIDED: + break; + default: + return -EINVAL; + } + /* capability check */ if (boot_cpu_has(X86_FEATURE_CPPC)) { pr_debug("AMD CPPC MSR based functionality is supported\n"); @@ -1438,21 +1525,7 @@ static int __init amd_pstate_param(char *str) size = strlen(str); mode_idx = get_mode_idx_from_str(str, size); - if (mode_idx >= AMD_PSTATE_DISABLE && mode_idx < AMD_PSTATE_MAX) { - cppc_state = mode_idx; - if (cppc_state == AMD_PSTATE_DISABLE) - pr_info("driver is explicitly disabled\n"); - - if (cppc_state == AMD_PSTATE_ACTIVE) - current_pstate_driver = &amd_pstate_epp_driver; - - if (cppc_state == AMD_PSTATE_PASSIVE || cppc_state == AMD_PSTATE_GUIDED) - current_pstate_driver = &amd_pstate_driver; - - return 0; - } - - return -EINVAL; + return amd_pstate_set_driver(mode_idx); } early_param("amd_pstate", amd_pstate_param); diff --git a/drivers/cpufreq/armada-8k-cpufreq.c b/drivers/cpufreq/armada-8k-cpufreq.c index b0fc5e84f8570f39e54b9be5137753ac02f8acab..8afefdea4d80c9da11d0762b37ae79475ec305b9 100644 --- a/drivers/cpufreq/armada-8k-cpufreq.c +++ b/drivers/cpufreq/armada-8k-cpufreq.c @@ -21,6 +21,13 @@ #include #include +static const struct of_device_id __maybe_unused armada_8k_cpufreq_of_match[] = { + { .compatible = "marvell,ap806-cpu-clock" }, + { .compatible = "marvell,ap807-cpu-clock" }, + { }, +}; +MODULE_DEVICE_TABLE(of, armada_8k_cpufreq_of_match); + /* * Setup the opps list with the divider for the max frequency, that * will be filled at runtime. @@ -127,7 +134,8 @@ static int __init armada_8k_cpufreq_init(void) struct device_node *node; struct cpumask cpus; - node = of_find_compatible_node(NULL, NULL, "marvell,ap806-cpu-clock"); + node = of_find_matching_node_and_match(NULL, armada_8k_cpufreq_of_match, + NULL); if (!node || !of_device_is_available(node)) { of_node_put(node); return -ENODEV; @@ -204,12 +212,6 @@ static void __exit armada_8k_cpufreq_exit(void) } module_exit(armada_8k_cpufreq_exit); -static const struct of_device_id __maybe_unused armada_8k_cpufreq_of_match[] = { - { .compatible = "marvell,ap806-cpu-clock" }, - { }, -}; -MODULE_DEVICE_TABLE(of, armada_8k_cpufreq_of_match); - MODULE_AUTHOR("Gregory Clement "); MODULE_DESCRIPTION("Armada 8K cpufreq driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c index 338cf6cc659604d7f686944ae004074c29d79245..e2b20080de3ab0819a3a76ff3251277bda9be160 100644 --- a/drivers/cpufreq/cpufreq-dt-platdev.c +++ b/drivers/cpufreq/cpufreq-dt-platdev.c @@ -5,6 +5,7 @@ */ #include +#include #include #include @@ -85,6 +86,8 @@ static const struct of_device_id allowlist[] __initconst = { { .compatible = "st-ericsson,u9500", }, { .compatible = "st-ericsson,u9540", }, + { .compatible = "starfive,jh7110", }, + { .compatible = "ti,omap2", }, { .compatible = "ti,omap4", }, { .compatible = "ti,omap5", }, @@ -165,6 +168,7 @@ static const struct of_device_id blocklist[] __initconst = { { .compatible = "ti,dra7", }, { .compatible = "ti,omap3", }, { .compatible = "ti,am625", }, + { .compatible = "ti,am62a7", }, { .compatible = "qcom,ipq8064", }, { .compatible = "qcom,apq8064", }, @@ -214,3 +218,4 @@ static int __init cpufreq_dt_platdev_init(void) sizeof(struct cpufreq_dt_platform_data))); } core_initcall(cpufreq_dt_platdev_init); +MODULE_LICENSE("GPL"); diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 6b52ebe5a890415cba039e513e04f285fea89dec..50bbc969ffe5309f429fbdc82f8e30cb68125d8e 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -2828,7 +2828,8 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data) (driver_data->setpolicy && (driver_data->target_index || driver_data->target)) || (!driver_data->get_intermediate != !driver_data->target_intermediate) || - (!driver_data->online != !driver_data->offline)) + (!driver_data->online != !driver_data->offline) || + (driver_data->adjust_perf && !driver_data->fast_switch)) return -EINVAL; pr_debug("trying to register driver %s\n", driver_data->name); diff --git a/drivers/cpufreq/imx6q-cpufreq.c b/drivers/cpufreq/imx6q-cpufreq.c index 48e1772e98fd8137d1f0cd8a1b6fc597ec172131..9fb1501033bba13952e74256cb8033684181403e 100644 --- a/drivers/cpufreq/imx6q-cpufreq.c +++ b/drivers/cpufreq/imx6q-cpufreq.c @@ -209,6 +209,14 @@ static struct cpufreq_driver imx6q_cpufreq_driver = { .suspend = cpufreq_generic_suspend, }; +static void imx6x_disable_freq_in_opp(struct device *dev, unsigned long freq) +{ + int ret = dev_pm_opp_disable(dev, freq); + + if (ret < 0 && ret != -ENODEV) + dev_warn(dev, "failed to disable %ldMHz OPP\n", freq / 1000000); +} + #define OCOTP_CFG3 0x440 #define OCOTP_CFG3_SPEED_SHIFT 16 #define OCOTP_CFG3_SPEED_1P2GHZ 0x3 @@ -254,17 +262,15 @@ static int imx6q_opp_check_speed_grading(struct device *dev) val &= 0x3; if (val < OCOTP_CFG3_SPEED_996MHZ) - if (dev_pm_opp_disable(dev, 996000000)) - dev_warn(dev, "failed to disable 996MHz OPP\n"); + imx6x_disable_freq_in_opp(dev, 996000000); if (of_machine_is_compatible("fsl,imx6q") || of_machine_is_compatible("fsl,imx6qp")) { if (val != OCOTP_CFG3_SPEED_852MHZ) - if (dev_pm_opp_disable(dev, 852000000)) - dev_warn(dev, "failed to disable 852MHz OPP\n"); + imx6x_disable_freq_in_opp(dev, 852000000); + if (val != OCOTP_CFG3_SPEED_1P2GHZ) - if (dev_pm_opp_disable(dev, 1200000000)) - dev_warn(dev, "failed to disable 1.2GHz OPP\n"); + imx6x_disable_freq_in_opp(dev, 1200000000); } return 0; @@ -316,20 +322,16 @@ static int imx6ul_opp_check_speed_grading(struct device *dev) val >>= OCOTP_CFG3_SPEED_SHIFT; val &= 0x3; - if (of_machine_is_compatible("fsl,imx6ul")) { + if (of_machine_is_compatible("fsl,imx6ul")) if (val != OCOTP_CFG3_6UL_SPEED_696MHZ) - if (dev_pm_opp_disable(dev, 696000000)) - dev_warn(dev, "failed to disable 696MHz OPP\n"); - } + imx6x_disable_freq_in_opp(dev, 696000000); if (of_machine_is_compatible("fsl,imx6ull")) { if (val != OCOTP_CFG3_6ULL_SPEED_792MHZ) - if (dev_pm_opp_disable(dev, 792000000)) - dev_warn(dev, "failed to disable 792MHz OPP\n"); + imx6x_disable_freq_in_opp(dev, 792000000); if (val != OCOTP_CFG3_6ULL_SPEED_900MHZ) - if (dev_pm_opp_disable(dev, 900000000)) - dev_warn(dev, "failed to disable 900MHz OPP\n"); + imx6x_disable_freq_in_opp(dev, 900000000); } return ret; diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c index 2548ec92faa2821098f6513f3ec14c53c081bf21..8ca2bce4341a4091d34afa2d3eb44dcecf59691b 100644 --- a/drivers/cpufreq/intel_pstate.c +++ b/drivers/cpufreq/intel_pstate.c @@ -302,6 +302,13 @@ static bool hwp_forced __read_mostly; static struct cpufreq_driver *intel_pstate_driver __read_mostly; +#define HYBRID_SCALING_FACTOR 78741 + +static inline int core_get_scaling(void) +{ + return 100000; +} + #ifdef CONFIG_ACPI static bool acpi_ppc; #endif @@ -400,6 +407,26 @@ static int intel_pstate_get_cppc_guaranteed(int cpu) return cppc_perf.nominal_perf; } + +static int intel_pstate_cppc_get_scaling(int cpu) +{ + struct cppc_perf_caps cppc_perf; + int ret; + + ret = cppc_get_perf_caps(cpu, &cppc_perf); + + /* + * If the nominal frequency and the nominal performance are not + * zero and the ratio between them is not 100, return the hybrid + * scaling factor. + */ + if (!ret && cppc_perf.nominal_perf && cppc_perf.nominal_freq && + cppc_perf.nominal_perf * 100 != cppc_perf.nominal_freq) + return HYBRID_SCALING_FACTOR; + + return core_get_scaling(); +} + #else /* CONFIG_ACPI_CPPC_LIB */ static inline void intel_pstate_set_itmt_prio(int cpu) { @@ -492,6 +519,11 @@ static inline int intel_pstate_get_cppc_guaranteed(int cpu) { return -ENOTSUPP; } + +static int intel_pstate_cppc_get_scaling(int cpu) +{ + return core_get_scaling(); +} #endif /* CONFIG_ACPI_CPPC_LIB */ /** @@ -824,6 +856,8 @@ static ssize_t store_energy_performance_preference( err = cpufreq_start_governor(policy); if (!ret) ret = err; + } else { + ret = 0; } } @@ -1895,11 +1929,6 @@ static int core_get_turbo_pstate(int cpu) return ret; } -static inline int core_get_scaling(void) -{ - return 100000; -} - static u64 core_get_val(struct cpudata *cpudata, int pstate) { u64 val; @@ -1936,16 +1965,28 @@ static void hybrid_get_type(void *data) *cpu_type = get_this_hybrid_cpu_type(); } -static int hybrid_get_cpu_scaling(int cpu) +static int hwp_get_cpu_scaling(int cpu) { u8 cpu_type = 0; smp_call_function_single(cpu, hybrid_get_type, &cpu_type, 1); /* P-cores have a smaller perf level-to-freqency scaling factor. */ if (cpu_type == 0x40) - return 78741; + return HYBRID_SCALING_FACTOR; - return core_get_scaling(); + /* Use default core scaling for E-cores */ + if (cpu_type == 0x20) + return core_get_scaling(); + + /* + * If reached here, this system is either non-hybrid (like Tiger + * Lake) or hybrid-capable (like Alder Lake or Raptor Lake) with + * no E cores (in which case CPUID for hybrid support is 0). + * + * The CPPC nominal_frequency field is 0 for non-hybrid systems, + * so the default core scaling will be used for them. + */ + return intel_pstate_cppc_get_scaling(cpu); } static void intel_pstate_set_pstate(struct cpudata *cpu, int pstate) @@ -3393,8 +3434,7 @@ static int __init intel_pstate_init(void) if (!default_driver) default_driver = &intel_pstate; - if (boot_cpu_has(X86_FEATURE_HYBRID_CPU)) - pstate_funcs.get_cpu_scaling = hybrid_get_cpu_scaling; + pstate_funcs.get_cpu_scaling = hwp_get_cpu_scaling; goto hwp_cpu_matched; } diff --git a/drivers/cpufreq/mediatek-cpufreq.c b/drivers/cpufreq/mediatek-cpufreq.c index 9a39a7ccfae9635cca2e56ec2322f0c538579e5c..fef68cb2b38f739160cf57b2c53ea31d0d4f9cb4 100644 --- a/drivers/cpufreq/mediatek-cpufreq.c +++ b/drivers/cpufreq/mediatek-cpufreq.c @@ -696,9 +696,16 @@ static const struct mtk_cpufreq_platform_data mt2701_platform_data = { static const struct mtk_cpufreq_platform_data mt7622_platform_data = { .min_volt_shift = 100000, .max_volt_shift = 200000, - .proc_max_volt = 1360000, + .proc_max_volt = 1350000, .sram_min_volt = 0, - .sram_max_volt = 1360000, + .sram_max_volt = 1350000, + .ccifreq_supported = false, +}; + +static const struct mtk_cpufreq_platform_data mt7623_platform_data = { + .min_volt_shift = 100000, + .max_volt_shift = 200000, + .proc_max_volt = 1300000, .ccifreq_supported = false, }; @@ -734,7 +741,7 @@ static const struct of_device_id mtk_cpufreq_machines[] __initconst = { { .compatible = "mediatek,mt2701", .data = &mt2701_platform_data }, { .compatible = "mediatek,mt2712", .data = &mt2701_platform_data }, { .compatible = "mediatek,mt7622", .data = &mt7622_platform_data }, - { .compatible = "mediatek,mt7623", .data = &mt7622_platform_data }, + { .compatible = "mediatek,mt7623", .data = &mt7623_platform_data }, { .compatible = "mediatek,mt8167", .data = &mt8516_platform_data }, { .compatible = "mediatek,mt817x", .data = &mt2701_platform_data }, { .compatible = "mediatek,mt8173", .data = &mt2701_platform_data }, diff --git a/drivers/cpufreq/qcom-cpufreq-hw.c b/drivers/cpufreq/qcom-cpufreq-hw.c index a78d7a27b4b56fd45da8423ef4776c0514358efc..f2830371d25f918dd83c8abe4f856652ea2d9b5b 100644 --- a/drivers/cpufreq/qcom-cpufreq-hw.c +++ b/drivers/cpufreq/qcom-cpufreq-hw.c @@ -661,7 +661,7 @@ static int qcom_cpufreq_hw_driver_probe(struct platform_device *pdev) ret = dev_pm_opp_of_find_icc_paths(cpu_dev, NULL); if (ret) - return ret; + return dev_err_probe(dev, ret, "Failed to find icc paths\n"); for (num_domains = 0; num_domains < MAX_FREQ_DOMAINS; num_domains++) if (!platform_get_resource(pdev, IORESOURCE_MEM, num_domains)) diff --git a/drivers/cpufreq/qcom-cpufreq-nvmem.c b/drivers/cpufreq/qcom-cpufreq-nvmem.c index a577586b23be26b74115e57adf326bf1bf770a20..a88b6fe5db50fed885822157d38e49ec3ae0a0fa 100644 --- a/drivers/cpufreq/qcom-cpufreq-nvmem.c +++ b/drivers/cpufreq/qcom-cpufreq-nvmem.c @@ -29,20 +29,7 @@ #include #include -#define MSM_ID_SMEM 137 - -enum _msm_id { - MSM8996V3 = 0xF6ul, - APQ8096V3 = 0x123ul, - MSM8996SG = 0x131ul, - APQ8096SG = 0x138ul, -}; - -enum _msm8996_version { - MSM8996_V3, - MSM8996_SG, - NUM_OF_MSM8996_VERSIONS, -}; +#include struct qcom_cpufreq_drv; @@ -140,60 +127,32 @@ static void get_krait_bin_format_b(struct device *cpu_dev, dev_dbg(cpu_dev, "PVS version: %d\n", *pvs_ver); } -static enum _msm8996_version qcom_cpufreq_get_msm_id(void) -{ - size_t len; - u32 *msm_id; - enum _msm8996_version version; - - msm_id = qcom_smem_get(QCOM_SMEM_HOST_ANY, MSM_ID_SMEM, &len); - if (IS_ERR(msm_id)) - return NUM_OF_MSM8996_VERSIONS; - - /* The first 4 bytes are format, next to them is the actual msm-id */ - msm_id++; - - switch ((enum _msm_id)*msm_id) { - case MSM8996V3: - case APQ8096V3: - version = MSM8996_V3; - break; - case MSM8996SG: - case APQ8096SG: - version = MSM8996_SG; - break; - default: - version = NUM_OF_MSM8996_VERSIONS; - } - - return version; -} - static int qcom_cpufreq_kryo_name_version(struct device *cpu_dev, struct nvmem_cell *speedbin_nvmem, char **pvs_name, struct qcom_cpufreq_drv *drv) { size_t len; + u32 msm_id; u8 *speedbin; - enum _msm8996_version msm8996_version; + int ret; *pvs_name = NULL; - msm8996_version = qcom_cpufreq_get_msm_id(); - if (NUM_OF_MSM8996_VERSIONS == msm8996_version) { - dev_err(cpu_dev, "Not Snapdragon 820/821!"); - return -ENODEV; - } + ret = qcom_smem_get_soc_id(&msm_id); + if (ret) + return ret; speedbin = nvmem_cell_read(speedbin_nvmem, &len); if (IS_ERR(speedbin)) return PTR_ERR(speedbin); - switch (msm8996_version) { - case MSM8996_V3: + switch (msm_id) { + case QCOM_ID_MSM8996: + case QCOM_ID_APQ8096: drv->versions = 1 << (unsigned int)(*speedbin); break; - case MSM8996_SG: + case QCOM_ID_MSM8996SG: + case QCOM_ID_APQ8096SG: drv->versions = 1 << ((unsigned int)(*speedbin) + 4); break; default: diff --git a/drivers/cpufreq/sparc-us2e-cpufreq.c b/drivers/cpufreq/sparc-us2e-cpufreq.c index 92acbb25abb3a82ffa1f692bf92268c1f91e706a..2783d3d55fceeefeb80e3ec8bc5ccddaceff671a 100644 --- a/drivers/cpufreq/sparc-us2e-cpufreq.c +++ b/drivers/cpufreq/sparc-us2e-cpufreq.c @@ -20,8 +20,6 @@ #include #include -static struct cpufreq_driver *cpufreq_us2e_driver; - struct us2e_freq_percpu_info { struct cpufreq_frequency_table table[6]; }; @@ -271,7 +269,7 @@ static int us2e_freq_target(struct cpufreq_policy *policy, unsigned int index) return smp_call_function_single(cpu, __us2e_freq_target, &index, 1); } -static int __init us2e_freq_cpu_init(struct cpufreq_policy *policy) +static int us2e_freq_cpu_init(struct cpufreq_policy *policy) { unsigned int cpu = policy->cpu; unsigned long clock_tick = sparc64_get_clock_tick(cpu) / 1000; @@ -300,12 +298,19 @@ static int __init us2e_freq_cpu_init(struct cpufreq_policy *policy) static int us2e_freq_cpu_exit(struct cpufreq_policy *policy) { - if (cpufreq_us2e_driver) - us2e_freq_target(policy, 0); - + us2e_freq_target(policy, 0); return 0; } +static struct cpufreq_driver cpufreq_us2e_driver = { + .name = "UltraSPARC-IIe", + .init = us2e_freq_cpu_init, + .verify = cpufreq_generic_frequency_table_verify, + .target_index = us2e_freq_target, + .get = us2e_freq_get, + .exit = us2e_freq_cpu_exit, +}; + static int __init us2e_freq_init(void) { unsigned long manuf, impl, ver; @@ -319,39 +324,15 @@ static int __init us2e_freq_init(void) impl = ((ver >> 32) & 0xffff); if (manuf == 0x17 && impl == 0x13) { - struct cpufreq_driver *driver; - - ret = -ENOMEM; - driver = kzalloc(sizeof(*driver), GFP_KERNEL); - if (!driver) - goto err_out; - - us2e_freq_table = kzalloc((NR_CPUS * sizeof(*us2e_freq_table)), - GFP_KERNEL); + us2e_freq_table = kzalloc(NR_CPUS * sizeof(*us2e_freq_table), + GFP_KERNEL); if (!us2e_freq_table) - goto err_out; - - driver->init = us2e_freq_cpu_init; - driver->verify = cpufreq_generic_frequency_table_verify; - driver->target_index = us2e_freq_target; - driver->get = us2e_freq_get; - driver->exit = us2e_freq_cpu_exit; - strcpy(driver->name, "UltraSPARC-IIe"); + return -ENOMEM; - cpufreq_us2e_driver = driver; - ret = cpufreq_register_driver(driver); + ret = cpufreq_register_driver(&cpufreq_us2e_driver); if (ret) - goto err_out; + kfree(us2e_freq_table); - return 0; - -err_out: - if (driver) { - kfree(driver); - cpufreq_us2e_driver = NULL; - } - kfree(us2e_freq_table); - us2e_freq_table = NULL; return ret; } @@ -360,13 +341,8 @@ static int __init us2e_freq_init(void) static void __exit us2e_freq_exit(void) { - if (cpufreq_us2e_driver) { - cpufreq_unregister_driver(cpufreq_us2e_driver); - kfree(cpufreq_us2e_driver); - cpufreq_us2e_driver = NULL; - kfree(us2e_freq_table); - us2e_freq_table = NULL; - } + cpufreq_unregister_driver(&cpufreq_us2e_driver); + kfree(us2e_freq_table); } MODULE_AUTHOR("David S. Miller "); diff --git a/drivers/cpufreq/sparc-us3-cpufreq.c b/drivers/cpufreq/sparc-us3-cpufreq.c index e41b35b16afd7ce6ac8b1124d10a7a6d3d9ade37..6c3657679a88089bad00319c8517e4524af45126 100644 --- a/drivers/cpufreq/sparc-us3-cpufreq.c +++ b/drivers/cpufreq/sparc-us3-cpufreq.c @@ -19,8 +19,6 @@ #include #include -static struct cpufreq_driver *cpufreq_us3_driver; - struct us3_freq_percpu_info { struct cpufreq_frequency_table table[4]; }; @@ -119,7 +117,7 @@ static int us3_freq_target(struct cpufreq_policy *policy, unsigned int index) return smp_call_function_single(cpu, update_safari_cfg, &new_bits, 1); } -static int __init us3_freq_cpu_init(struct cpufreq_policy *policy) +static int us3_freq_cpu_init(struct cpufreq_policy *policy) { unsigned int cpu = policy->cpu; unsigned long clock_tick = sparc64_get_clock_tick(cpu) / 1000; @@ -144,12 +142,19 @@ static int __init us3_freq_cpu_init(struct cpufreq_policy *policy) static int us3_freq_cpu_exit(struct cpufreq_policy *policy) { - if (cpufreq_us3_driver) - us3_freq_target(policy, 0); - + us3_freq_target(policy, 0); return 0; } +static struct cpufreq_driver cpufreq_us3_driver = { + .name = "UltraSPARC-III", + .init = us3_freq_cpu_init, + .verify = cpufreq_generic_frequency_table_verify, + .target_index = us3_freq_target, + .get = us3_freq_get, + .exit = us3_freq_cpu_exit, +}; + static int __init us3_freq_init(void) { unsigned long manuf, impl, ver; @@ -167,39 +172,15 @@ static int __init us3_freq_init(void) impl == CHEETAH_PLUS_IMPL || impl == JAGUAR_IMPL || impl == PANTHER_IMPL)) { - struct cpufreq_driver *driver; - - ret = -ENOMEM; - driver = kzalloc(sizeof(*driver), GFP_KERNEL); - if (!driver) - goto err_out; - - us3_freq_table = kzalloc((NR_CPUS * sizeof(*us3_freq_table)), - GFP_KERNEL); + us3_freq_table = kzalloc(NR_CPUS * sizeof(*us3_freq_table), + GFP_KERNEL); if (!us3_freq_table) - goto err_out; - - driver->init = us3_freq_cpu_init; - driver->verify = cpufreq_generic_frequency_table_verify; - driver->target_index = us3_freq_target; - driver->get = us3_freq_get; - driver->exit = us3_freq_cpu_exit; - strcpy(driver->name, "UltraSPARC-III"); + return -ENOMEM; - cpufreq_us3_driver = driver; - ret = cpufreq_register_driver(driver); + ret = cpufreq_register_driver(&cpufreq_us3_driver); if (ret) - goto err_out; + kfree(us3_freq_table); - return 0; - -err_out: - if (driver) { - kfree(driver); - cpufreq_us3_driver = NULL; - } - kfree(us3_freq_table); - us3_freq_table = NULL; return ret; } @@ -208,13 +189,8 @@ static int __init us3_freq_init(void) static void __exit us3_freq_exit(void) { - if (cpufreq_us3_driver) { - cpufreq_unregister_driver(cpufreq_us3_driver); - kfree(cpufreq_us3_driver); - cpufreq_us3_driver = NULL; - kfree(us3_freq_table); - us3_freq_table = NULL; - } + cpufreq_unregister_driver(&cpufreq_us3_driver); + kfree(us3_freq_table); } MODULE_AUTHOR("David S. Miller "); diff --git a/drivers/cpufreq/tegra194-cpufreq.c b/drivers/cpufreq/tegra194-cpufreq.c index c8d03346068ab1aaf488dd71da0154836795a7dd..36dad5ea59475b0a4e6d1d5cbc88864cd0d0bd4e 100644 --- a/drivers/cpufreq/tegra194-cpufreq.c +++ b/drivers/cpufreq/tegra194-cpufreq.c @@ -686,8 +686,10 @@ static int tegra194_cpufreq_probe(struct platform_device *pdev) /* Check for optional OPPv2 and interconnect paths on CPU0 to enable ICC scaling */ cpu_dev = get_cpu_device(0); - if (!cpu_dev) - return -EPROBE_DEFER; + if (!cpu_dev) { + err = -EPROBE_DEFER; + goto err_free_res; + } if (dev_pm_opp_of_get_opp_desc_node(cpu_dev)) { err = dev_pm_opp_of_find_icc_paths(cpu_dev, NULL); diff --git a/drivers/cpufreq/ti-cpufreq.c b/drivers/cpufreq/ti-cpufreq.c index be4209d97cb39ef65860adf4adb1264d2996ef23..d5cd2fd25cade21f58c13ea9851e5e644af3c559 100644 --- a/drivers/cpufreq/ti-cpufreq.c +++ b/drivers/cpufreq/ti-cpufreq.c @@ -337,6 +337,7 @@ static const struct of_device_id ti_cpufreq_of_match[] = { { .compatible = "ti,omap34xx", .data = &omap34xx_soc_data, }, { .compatible = "ti,omap36xx", .data = &omap36xx_soc_data, }, { .compatible = "ti,am625", .data = &am625_soc_data, }, + { .compatible = "ti,am62a7", .data = &am625_soc_data, }, /* legacy */ { .compatible = "ti,omap3430", .data = &omap34xx_soc_data, }, { .compatible = "ti,omap3630", .data = &omap36xx_soc_data, }, diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index 8e929f6602cef50508a075d5b4cd5c97631cce3e..737a026ef58a3835d07de4d89062e75e37d9cb86 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c @@ -145,7 +145,7 @@ static noinstr void enter_s2idle_proper(struct cpuidle_driver *drv, instrumentation_begin(); - time_start = ns_to_ktime(local_clock()); + time_start = ns_to_ktime(local_clock_noinstr()); tick_freeze(); /* @@ -169,7 +169,7 @@ static noinstr void enter_s2idle_proper(struct cpuidle_driver *drv, tick_unfreeze(); start_critical_timings(); - time_end = ns_to_ktime(local_clock()); + time_end = ns_to_ktime(local_clock_noinstr()); dev->states_usage[index].s2idle_time += ktime_us_delta(time_end, time_start); dev->states_usage[index].s2idle_usage++; @@ -243,7 +243,7 @@ noinstr int cpuidle_enter_state(struct cpuidle_device *dev, sched_idle_set_state(target_state); trace_cpu_idle(index, dev->cpu); - time_start = ns_to_ktime(local_clock()); + time_start = ns_to_ktime(local_clock_noinstr()); stop_critical_timings(); if (!(target_state->flags & CPUIDLE_FLAG_RCU_IDLE)) { @@ -276,7 +276,7 @@ noinstr int cpuidle_enter_state(struct cpuidle_device *dev, start_critical_timings(); sched_clock_idle_wakeup_event(); - time_end = ns_to_ktime(local_clock()); + time_end = ns_to_ktime(local_clock_noinstr()); trace_cpu_idle(PWR_EVENT_EXIT, dev->cpu); /* The cpu is no longer idle or about to enter idle. */ diff --git a/drivers/cpuidle/poll_state.c b/drivers/cpuidle/poll_state.c index bdcfeaecd2282ca1f250a829bfd302554860a93e..9b6d90a726019c61580671991539f9eaa95a8da2 100644 --- a/drivers/cpuidle/poll_state.c +++ b/drivers/cpuidle/poll_state.c @@ -15,7 +15,7 @@ static int __cpuidle poll_idle(struct cpuidle_device *dev, { u64 time_start; - time_start = local_clock(); + time_start = local_clock_noinstr(); dev->poll_time_limit = false; @@ -32,7 +32,7 @@ static int __cpuidle poll_idle(struct cpuidle_device *dev, continue; loop_count = 0; - if (local_clock() - time_start > limit) { + if (local_clock_noinstr() - time_start > limit) { dev->poll_time_limit = true; break; } diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig index 9c440cd0fed05e64d588746788a527dbc0e38a30..44e44b8d9ce67bce2d9bcc33329bf019fc62a4bd 100644 --- a/drivers/crypto/Kconfig +++ b/drivers/crypto/Kconfig @@ -92,17 +92,6 @@ config ZCRYPT_DEBUG If unsure, say N. -config ZCRYPT_MULTIDEVNODES - bool "Support for multiple zcrypt device nodes" - default y - depends on S390 - depends on ZCRYPT - help - With this option enabled the zcrypt device driver can - provide multiple devices nodes in /dev. Each device - node can get customized to limit access and narrow - down the use of the available crypto hardware. - config PKEY tristate "Kernel API for protected key handling" depends on S390 @@ -807,5 +796,6 @@ config CRYPTO_DEV_SA2UL acceleration for cryptographic algorithms on these devices. source "drivers/crypto/aspeed/Kconfig" +source "drivers/crypto/starfive/Kconfig" endif # CRYPTO_HW diff --git a/drivers/crypto/Makefile b/drivers/crypto/Makefile index 51d36701e7851acd33986169456ad1f4cd1a0313..d859d6a5f3a45439c6e14bb19d6240e121c9ac62 100644 --- a/drivers/crypto/Makefile +++ b/drivers/crypto/Makefile @@ -50,3 +50,4 @@ obj-y += xilinx/ obj-y += hisilicon/ obj-$(CONFIG_CRYPTO_DEV_AMLOGIC_GXL) += amlogic/ obj-y += intel/ +obj-y += starfive/ diff --git a/drivers/crypto/allwinner/sun4i-ss/sun4i-ss-cipher.c b/drivers/crypto/allwinner/sun4i-ss/sun4i-ss-cipher.c index 10fe9f73a5fb45097b8ae1537fd1879fe8e772db..f2dd66706c109ca195bc8f873499383c1b4ed0a4 100644 --- a/drivers/crypto/allwinner/sun4i-ss/sun4i-ss-cipher.c +++ b/drivers/crypto/allwinner/sun4i-ss/sun4i-ss-cipher.c @@ -8,7 +8,7 @@ * keysize in CBC and ECB mode. * Add support also for DES and 3DES in CBC and ECB mode. * - * You could find the datasheet in Documentation/arm/sunxi.rst + * You could find the datasheet in Documentation/arch/arm/sunxi.rst */ #include "sun4i-ss.h" diff --git a/drivers/crypto/allwinner/sun4i-ss/sun4i-ss-core.c b/drivers/crypto/allwinner/sun4i-ss/sun4i-ss-core.c index 006e40133c284ba252727a8b25652b0877a2aaed..51a3a7b5b9850dd4a102aa1a6ce31ff1ca2c76dc 100644 --- a/drivers/crypto/allwinner/sun4i-ss/sun4i-ss-core.c +++ b/drivers/crypto/allwinner/sun4i-ss/sun4i-ss-core.c @@ -6,7 +6,7 @@ * * Core file which registers crypto algorithms supported by the SS. * - * You could find a link for the datasheet in Documentation/arm/sunxi.rst + * You could find a link for the datasheet in Documentation/arch/arm/sunxi.rst */ #include #include diff --git a/drivers/crypto/allwinner/sun4i-ss/sun4i-ss-hash.c b/drivers/crypto/allwinner/sun4i-ss/sun4i-ss-hash.c index d28292762b3247a6c999b6f382d28a25d6c7fabe..f7893e4ac59dd8ceea2993d18ded40d6ee91f55a 100644 --- a/drivers/crypto/allwinner/sun4i-ss/sun4i-ss-hash.c +++ b/drivers/crypto/allwinner/sun4i-ss/sun4i-ss-hash.c @@ -6,7 +6,7 @@ * * This file add support for MD5 and SHA1. * - * You could find the datasheet in Documentation/arm/sunxi.rst + * You could find the datasheet in Documentation/arch/arm/sunxi.rst */ #include "sun4i-ss.h" #include diff --git a/drivers/crypto/allwinner/sun4i-ss/sun4i-ss.h b/drivers/crypto/allwinner/sun4i-ss/sun4i-ss.h index ba59c7a488252224d364b02ccb9c38176b473784..6c5d4aa6453c7fb3e3d55ac19e24bf154ee347ad 100644 --- a/drivers/crypto/allwinner/sun4i-ss/sun4i-ss.h +++ b/drivers/crypto/allwinner/sun4i-ss/sun4i-ss.h @@ -8,7 +8,7 @@ * Support MD5 and SHA1 hash algorithms. * Support DES and 3DES * - * You could find the datasheet in Documentation/arm/sunxi.rst + * You could find the datasheet in Documentation/arch/arm/sunxi.rst */ #include diff --git a/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-cipher.c b/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-cipher.c index 74b4e910a38d7bd790bf95dc817502d62d3cf947..c13550090785dd34ba02533381524d353c82b04d 100644 --- a/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-cipher.c +++ b/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-cipher.c @@ -8,7 +8,7 @@ * This file add support for AES cipher with 128,192,256 bits keysize in * CBC and ECB mode. * - * You could find a link for the datasheet in Documentation/arm/sunxi.rst + * You could find a link for the datasheet in Documentation/arch/arm/sunxi.rst */ #include diff --git a/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-core.c b/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-core.c index a6865ff4d400c493d0ce30433ce785ce0f945161..07ea0cc82b16c832c3c5f045d6ad4312f31a3cfd 100644 --- a/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-core.c +++ b/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-core.c @@ -7,7 +7,7 @@ * * Core file which registers crypto algorithms supported by the CryptoEngine. * - * You could find a link for the datasheet in Documentation/arm/sunxi.rst + * You could find a link for the datasheet in Documentation/arch/arm/sunxi.rst */ #include #include diff --git a/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-hash.c b/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-hash.c index 8b5b9b9d04c34217698755df18c77de43d5088de..930ad157004c67f530cbbd818301fc2f3d22bf15 100644 --- a/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-hash.c +++ b/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-hash.c @@ -7,7 +7,7 @@ * * This file add support for MD5 and SHA1/SHA224/SHA256/SHA384/SHA512. * - * You could find the datasheet in Documentation/arm/sunxi.rst + * You could find the datasheet in Documentation/arch/arm/sunxi.rst */ #include #include diff --git a/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-prng.c b/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-prng.c index b3cc43ea6c8a69db03844222696bdb738ab3eb87..80815379f6fc5500722426b3b45f240226dc0c47 100644 --- a/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-prng.c +++ b/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-prng.c @@ -7,7 +7,7 @@ * * This file handle the PRNG * - * You could find a link for the datasheet in Documentation/arm/sunxi.rst + * You could find a link for the datasheet in Documentation/arch/arm/sunxi.rst */ #include "sun8i-ce.h" #include diff --git a/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-trng.c b/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-trng.c index e2b9b9104694172fa264e275eae21de8b69b0ee3..9c35f2a83eda858d39f96c39fc75a5079fe1b33e 100644 --- a/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-trng.c +++ b/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-trng.c @@ -7,7 +7,7 @@ * * This file handle the TRNG * - * You could find a link for the datasheet in Documentation/arm/sunxi.rst + * You could find a link for the datasheet in Documentation/arch/arm/sunxi.rst */ #include "sun8i-ce.h" #include diff --git a/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-cipher.c b/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-cipher.c index 16966cc94e2470777a3bbd25ab170071792ab0a2..381a90fbeaffd49b0ba81dadf712246367eea82a 100644 --- a/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-cipher.c +++ b/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-cipher.c @@ -8,7 +8,7 @@ * This file add support for AES cipher with 128,192,256 bits keysize in * CBC and ECB mode. * - * You could find a link for the datasheet in Documentation/arm/sunxi.rst + * You could find a link for the datasheet in Documentation/arch/arm/sunxi.rst */ #include diff --git a/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-core.c b/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-core.c index c9dc06f97857c3dd4884d116bc66b2db82241295..3dd844b40ff7ff3e8c54de9f1a5b0f7689e2a44a 100644 --- a/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-core.c +++ b/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-core.c @@ -7,7 +7,7 @@ * * Core file which registers crypto algorithms supported by the SecuritySystem * - * You could find a link for the datasheet in Documentation/arm/sunxi.rst + * You could find a link for the datasheet in Documentation/arch/arm/sunxi.rst */ #include #include diff --git a/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-hash.c b/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-hash.c index 577bf636f7fb68e12f032e056a0034e4eed7adf6..a4b67d130d112ae158421c99d457ee8072908026 100644 --- a/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-hash.c +++ b/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-hash.c @@ -7,7 +7,7 @@ * * This file add support for MD5 and SHA1/SHA224/SHA256. * - * You could find the datasheet in Documentation/arm/sunxi.rst + * You could find the datasheet in Documentation/arch/arm/sunxi.rst */ #include #include diff --git a/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-prng.c b/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-prng.c index 70c7b5d571b841f1ddbdc75f60258b28c5ced0bb..a923cfc6553f42546b2908fa712c2102c197746b 100644 --- a/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-prng.c +++ b/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-prng.c @@ -7,7 +7,7 @@ * * This file handle the PRNG found in the SS * - * You could find a link for the datasheet in Documentation/arm/sunxi.rst + * You could find a link for the datasheet in Documentation/arch/arm/sunxi.rst */ #include "sun8i-ss.h" #include diff --git a/drivers/crypto/atmel-ecc.c b/drivers/crypto/atmel-ecc.c index aac64b55520420e82ae453afe0bcdce2eaa19474..432beabd79e68db84c99d69735dd11a90f68d507 100644 --- a/drivers/crypto/atmel-ecc.c +++ b/drivers/crypto/atmel-ecc.c @@ -389,7 +389,7 @@ static struct i2c_driver atmel_ecc_driver = { .name = "atmel-ecc", .of_match_table = of_match_ptr(atmel_ecc_dt_ids), }, - .probe_new = atmel_ecc_probe, + .probe = atmel_ecc_probe, .remove = atmel_ecc_remove, .id_table = atmel_ecc_id, }; diff --git a/drivers/crypto/atmel-sha204a.c b/drivers/crypto/atmel-sha204a.c index 44a185a84760a73f141afcf0a78cddb7c2a1db94..c77f482d2a97e905f453cdd7b5cc77f6cb36122f 100644 --- a/drivers/crypto/atmel-sha204a.c +++ b/drivers/crypto/atmel-sha204a.c @@ -141,7 +141,7 @@ static const struct i2c_device_id atmel_sha204a_id[] = { MODULE_DEVICE_TABLE(i2c, atmel_sha204a_id); static struct i2c_driver atmel_sha204a_driver = { - .probe_new = atmel_sha204a_probe, + .probe = atmel_sha204a_probe, .remove = atmel_sha204a_remove, .id_table = atmel_sha204a_id, diff --git a/drivers/crypto/caam/Kconfig b/drivers/crypto/caam/Kconfig index ec6a9e6ad4d237195a658da3e265c3c5cf9b1e1e..c631f99e415fcaeeb13a94d1eca03d3c00fa7068 100644 --- a/drivers/crypto/caam/Kconfig +++ b/drivers/crypto/caam/Kconfig @@ -162,6 +162,15 @@ config CRYPTO_DEV_FSL_CAAM_PRNG_API config CRYPTO_DEV_FSL_CAAM_BLOB_GEN bool +config CRYPTO_DEV_FSL_CAAM_RNG_TEST + bool "Test caam rng" + select CRYPTO_DEV_FSL_CAAM_RNG_API + help + Selecting this will enable a self-test to run for the + caam RNG. + This test is several minutes long and executes + just before the RNG is registered with the hw_random API. + endif # CRYPTO_DEV_FSL_CAAM_JR endif # CRYPTO_DEV_FSL_CAAM diff --git a/drivers/crypto/caam/caamalg_qi2.c b/drivers/crypto/caam/caamalg_qi2.c index 5c8d35edaa1cdc6ae60d7cf99053d9481bc1ad13..9156bbe038b7b0820608066e0c428f7daa260ce4 100644 --- a/drivers/crypto/caam/caamalg_qi2.c +++ b/drivers/crypto/caam/caamalg_qi2.c @@ -5402,7 +5402,7 @@ static int dpaa2_caam_probe(struct fsl_mc_device *dpseci_dev) return err; } -static int __cold dpaa2_caam_remove(struct fsl_mc_device *ls_dev) +static void __cold dpaa2_caam_remove(struct fsl_mc_device *ls_dev) { struct device *dev; struct dpaa2_caam_priv *priv; @@ -5443,8 +5443,6 @@ static int __cold dpaa2_caam_remove(struct fsl_mc_device *ls_dev) free_percpu(priv->ppriv); fsl_mc_portal_free(priv->mc_io); kmem_cache_destroy(qi_cache); - - return 0; } int dpaa2_caam_enqueue(struct device *dev, struct caam_request *req) diff --git a/drivers/crypto/caam/caamrng.c b/drivers/crypto/caam/caamrng.c index 50eb55da45c29ba1936625537d575d1c1928052c..b3d14a7f4dd1470ba3def1243e182883ff777761 100644 --- a/drivers/crypto/caam/caamrng.c +++ b/drivers/crypto/caam/caamrng.c @@ -172,6 +172,50 @@ static void caam_cleanup(struct hwrng *rng) kfifo_free(&ctx->fifo); } +#ifdef CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_TEST +static inline void test_len(struct hwrng *rng, size_t len, bool wait) +{ + u8 *buf; + int read_len; + struct caam_rng_ctx *ctx = to_caam_rng_ctx(rng); + struct device *dev = ctx->ctrldev; + + buf = kcalloc(CAAM_RNG_MAX_FIFO_STORE_SIZE, sizeof(u8), GFP_KERNEL); + + while (len > 0) { + read_len = rng->read(rng, buf, len, wait); + + if (read_len < 0 || (read_len == 0 && wait)) { + dev_err(dev, "RNG Read FAILED received %d bytes\n", + read_len); + kfree(buf); + return; + } + + print_hex_dump_debug("random bytes@: ", + DUMP_PREFIX_ADDRESS, 16, 4, + buf, read_len, 1); + + len = len - read_len; + } + + kfree(buf); +} + +static inline void test_mode_once(struct hwrng *rng, bool wait) +{ + test_len(rng, 32, wait); + test_len(rng, 64, wait); + test_len(rng, 128, wait); +} + +static void self_test(struct hwrng *rng) +{ + pr_info("Executing RNG SELF-TEST with wait\n"); + test_mode_once(rng, true); +} +#endif + static int caam_init(struct hwrng *rng) { struct caam_rng_ctx *ctx = to_caam_rng_ctx(rng); @@ -258,6 +302,10 @@ int caam_rng_init(struct device *ctrldev) return ret; } +#ifdef CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_TEST + self_test(&ctx->rng); +#endif + devres_close_group(ctrldev, caam_rng_init); return 0; } diff --git a/drivers/crypto/caam/ctrl.c b/drivers/crypto/caam/ctrl.c index bedcc2ab3a00a65efddae36317a91cbd5d5222fb..ff9ddbbca3774a698a96c09080d7ed2aa6b4188f 100644 --- a/drivers/crypto/caam/ctrl.c +++ b/drivers/crypto/caam/ctrl.c @@ -79,6 +79,15 @@ static void build_deinstantiation_desc(u32 *desc, int handle) append_jump(desc, JUMP_CLASS_CLASS1 | JUMP_TYPE_HALT); } +static const struct of_device_id imx8m_machine_match[] = { + { .compatible = "fsl,imx8mm", }, + { .compatible = "fsl,imx8mn", }, + { .compatible = "fsl,imx8mp", }, + { .compatible = "fsl,imx8mq", }, + { .compatible = "fsl,imx8ulp", }, + { } +}; + /* * run_descriptor_deco0 - runs a descriptor on DECO0, under direct control of * the software (no JR/QI used). @@ -105,10 +114,7 @@ static inline int run_descriptor_deco0(struct device *ctrldev, u32 *desc, * Apparently on i.MX8M{Q,M,N,P} it doesn't matter if virt_en == 1 * and the following steps should be performed regardless */ - of_machine_is_compatible("fsl,imx8mq") || - of_machine_is_compatible("fsl,imx8mm") || - of_machine_is_compatible("fsl,imx8mn") || - of_machine_is_compatible("fsl,imx8mp")) { + of_match_node(imx8m_machine_match, of_root)) { clrsetbits_32(&ctrl->deco_rsr, 0, DECORSR_JR0); while (!(rd_reg32(&ctrl->deco_rsr) & DECORSR_VALID) && @@ -344,16 +350,15 @@ static int instantiate_rng(struct device *ctrldev, int state_handle_mask, /* * kick_trng - sets the various parameters for enabling the initialization * of the RNG4 block in CAAM - * @pdev - pointer to the platform device + * @dev - pointer to the controller device * @ent_delay - Defines the length (in system clocks) of each entropy sample. */ -static void kick_trng(struct platform_device *pdev, int ent_delay) +static void kick_trng(struct device *dev, int ent_delay) { - struct device *ctrldev = &pdev->dev; - struct caam_drv_private *ctrlpriv = dev_get_drvdata(ctrldev); + struct caam_drv_private *ctrlpriv = dev_get_drvdata(dev); struct caam_ctrl __iomem *ctrl; struct rng4tst __iomem *r4tst; - u32 val; + u32 val, rtsdctl; ctrl = (struct caam_ctrl __iomem *)ctrlpriv->ctrl; r4tst = &ctrl->r4tst[0]; @@ -369,26 +374,38 @@ static void kick_trng(struct platform_device *pdev, int ent_delay) * Performance-wise, it does not make sense to * set the delay to a value that is lower * than the last one that worked (i.e. the state handles - * were instantiated properly. Thus, instead of wasting - * time trying to set the values controlling the sample - * frequency, the function simply returns. + * were instantiated properly). + */ + rtsdctl = rd_reg32(&r4tst->rtsdctl); + val = (rtsdctl & RTSDCTL_ENT_DLY_MASK) >> RTSDCTL_ENT_DLY_SHIFT; + if (ent_delay > val) { + val = ent_delay; + /* min. freq. count, equal to 1/4 of the entropy sample length */ + wr_reg32(&r4tst->rtfrqmin, val >> 2); + /* max. freq. count, equal to 16 times the entropy sample length */ + wr_reg32(&r4tst->rtfrqmax, val << 4); + } + + wr_reg32(&r4tst->rtsdctl, (val << RTSDCTL_ENT_DLY_SHIFT) | + RTSDCTL_SAMP_SIZE_VAL); + + /* + * To avoid reprogramming the self-test parameters over and over again, + * use RTSDCTL[SAMP_SIZE] as an indicator. */ - val = (rd_reg32(&r4tst->rtsdctl) & RTSDCTL_ENT_DLY_MASK) - >> RTSDCTL_ENT_DLY_SHIFT; - if (ent_delay <= val) - goto start_rng; - - val = rd_reg32(&r4tst->rtsdctl); - val = (val & ~RTSDCTL_ENT_DLY_MASK) | - (ent_delay << RTSDCTL_ENT_DLY_SHIFT); - wr_reg32(&r4tst->rtsdctl, val); - /* min. freq. count, equal to 1/4 of the entropy sample length */ - wr_reg32(&r4tst->rtfrqmin, ent_delay >> 2); - /* disable maximum frequency count */ - wr_reg32(&r4tst->rtfrqmax, RTFRQMAX_DISABLE); - /* read the control register */ - val = rd_reg32(&r4tst->rtmctl); -start_rng: + if ((rtsdctl & RTSDCTL_SAMP_SIZE_MASK) != RTSDCTL_SAMP_SIZE_VAL) { + wr_reg32(&r4tst->rtscmisc, (2 << 16) | 32); + wr_reg32(&r4tst->rtpkrrng, 570); + wr_reg32(&r4tst->rtpkrmax, 1600); + wr_reg32(&r4tst->rtscml, (122 << 16) | 317); + wr_reg32(&r4tst->rtscrl[0], (80 << 16) | 107); + wr_reg32(&r4tst->rtscrl[1], (57 << 16) | 62); + wr_reg32(&r4tst->rtscrl[2], (39 << 16) | 39); + wr_reg32(&r4tst->rtscrl[3], (27 << 16) | 26); + wr_reg32(&r4tst->rtscrl[4], (19 << 16) | 18); + wr_reg32(&r4tst->rtscrl[5], (18 << 16) | 17); + } + /* * select raw sampling in both entropy shifter * and statistical checker; ; put RNG4 into run mode @@ -618,10 +635,115 @@ static bool needs_entropy_delay_adjustment(void) return false; } +static int caam_ctrl_rng_init(struct device *dev) +{ + struct caam_drv_private *ctrlpriv = dev_get_drvdata(dev); + struct caam_ctrl __iomem *ctrl = ctrlpriv->ctrl; + int ret, gen_sk, ent_delay = RTSDCTL_ENT_DLY_MIN; + u8 rng_vid; + + if (ctrlpriv->era < 10) { + struct caam_perfmon __iomem *perfmon; + + perfmon = ctrlpriv->total_jobrs ? + (struct caam_perfmon __iomem *)&ctrlpriv->jr[0]->perfmon : + (struct caam_perfmon __iomem *)&ctrl->perfmon; + + rng_vid = (rd_reg32(&perfmon->cha_id_ls) & + CHA_ID_LS_RNG_MASK) >> CHA_ID_LS_RNG_SHIFT; + } else { + struct version_regs __iomem *vreg; + + vreg = ctrlpriv->total_jobrs ? + (struct version_regs __iomem *)&ctrlpriv->jr[0]->vreg : + (struct version_regs __iomem *)&ctrl->vreg; + + rng_vid = (rd_reg32(&vreg->rng) & CHA_VER_VID_MASK) >> + CHA_VER_VID_SHIFT; + } + + /* + * If SEC has RNG version >= 4 and RNG state handle has not been + * already instantiated, do RNG instantiation + * In case of SoCs with Management Complex, RNG is managed by MC f/w. + */ + if (!(ctrlpriv->mc_en && ctrlpriv->pr_support) && rng_vid >= 4) { + ctrlpriv->rng4_sh_init = + rd_reg32(&ctrl->r4tst[0].rdsta); + /* + * If the secure keys (TDKEK, JDKEK, TDSK), were already + * generated, signal this to the function that is instantiating + * the state handles. An error would occur if RNG4 attempts + * to regenerate these keys before the next POR. + */ + gen_sk = ctrlpriv->rng4_sh_init & RDSTA_SKVN ? 0 : 1; + ctrlpriv->rng4_sh_init &= RDSTA_MASK; + do { + int inst_handles = + rd_reg32(&ctrl->r4tst[0].rdsta) & RDSTA_MASK; + /* + * If either SH were instantiated by somebody else + * (e.g. u-boot) then it is assumed that the entropy + * parameters are properly set and thus the function + * setting these (kick_trng(...)) is skipped. + * Also, if a handle was instantiated, do not change + * the TRNG parameters. + */ + if (needs_entropy_delay_adjustment()) + ent_delay = 12000; + if (!(ctrlpriv->rng4_sh_init || inst_handles)) { + dev_info(dev, + "Entropy delay = %u\n", + ent_delay); + kick_trng(dev, ent_delay); + ent_delay += 400; + } + /* + * if instantiate_rng(...) fails, the loop will rerun + * and the kick_trng(...) function will modify the + * upper and lower limits of the entropy sampling + * interval, leading to a successful initialization of + * the RNG. + */ + ret = instantiate_rng(dev, inst_handles, + gen_sk); + /* + * Entropy delay is determined via TRNG characterization. + * TRNG characterization is run across different voltages + * and temperatures. + * If worst case value for ent_dly is identified, + * the loop can be skipped for that platform. + */ + if (needs_entropy_delay_adjustment()) + break; + if (ret == -EAGAIN) + /* + * if here, the loop will rerun, + * so don't hog the CPU + */ + cpu_relax(); + } while ((ret == -EAGAIN) && (ent_delay < RTSDCTL_ENT_DLY_MAX)); + if (ret) { + dev_err(dev, "failed to instantiate RNG"); + return ret; + } + /* + * Set handles initialized by this module as the complement of + * the already initialized ones + */ + ctrlpriv->rng4_sh_init = ~ctrlpriv->rng4_sh_init & RDSTA_MASK; + + /* Enable RDB bit so that RNG works faster */ + clrsetbits_32(&ctrl->scfgr, 0, SCFGR_RDBENABLE); + } + + return 0; +} + /* Probe routine for CAAM top (controller) level */ static int caam_probe(struct platform_device *pdev) { - int ret, ring, gen_sk, ent_delay = RTSDCTL_ENT_DLY_MIN; + int ret, ring; u64 caam_id; const struct soc_device_attribute *imx_soc_match; struct device *dev; @@ -631,10 +753,8 @@ static int caam_probe(struct platform_device *pdev) struct caam_perfmon __iomem *perfmon; struct dentry *dfs_root; u32 scfgr, comp_params; - u8 rng_vid; int pg_size; int BLOCK_OFFSET = 0; - bool pr_support = false; bool reg_access = true; ctrlpriv = devm_kzalloc(&pdev->dev, sizeof(*ctrlpriv), GFP_KERNEL); @@ -646,6 +766,9 @@ static int caam_probe(struct platform_device *pdev) nprop = pdev->dev.of_node; imx_soc_match = soc_device_match(caam_imx_soc_table); + if (!imx_soc_match && of_match_node(imx8m_machine_match, of_root)) + return -EPROBE_DEFER; + caam_imx = (bool)imx_soc_match; if (imx_soc_match) { @@ -770,7 +893,8 @@ static int caam_probe(struct platform_device *pdev) mc_version = fsl_mc_get_version(); if (mc_version) - pr_support = check_version(mc_version, 10, 20, 0); + ctrlpriv->pr_support = check_version(mc_version, 10, 20, + 0); else return -EPROBE_DEFER; } @@ -861,9 +985,6 @@ static int caam_probe(struct platform_device *pdev) return -ENOMEM; } - if (!reg_access) - goto report_live; - comp_params = rd_reg32(&perfmon->comp_parms_ls); ctrlpriv->blob_present = !!(comp_params & CTPR_LS_BLOB); @@ -873,8 +994,6 @@ static int caam_probe(struct platform_device *pdev) * check both here. */ if (ctrlpriv->era < 10) { - rng_vid = (rd_reg32(&perfmon->cha_id_ls) & - CHA_ID_LS_RNG_MASK) >> CHA_ID_LS_RNG_SHIFT; ctrlpriv->blob_present = ctrlpriv->blob_present && (rd_reg32(&perfmon->cha_num_ls) & CHA_ID_LS_AES_MASK); } else { @@ -884,91 +1003,16 @@ static int caam_probe(struct platform_device *pdev) (struct version_regs __iomem *)&ctrlpriv->jr[0]->vreg : (struct version_regs __iomem *)&ctrl->vreg; - rng_vid = (rd_reg32(&vreg->rng) & CHA_VER_VID_MASK) >> - CHA_VER_VID_SHIFT; ctrlpriv->blob_present = ctrlpriv->blob_present && (rd_reg32(&vreg->aesa) & CHA_VER_MISC_AES_NUM_MASK); } - /* - * If SEC has RNG version >= 4 and RNG state handle has not been - * already instantiated, do RNG instantiation - * In case of SoCs with Management Complex, RNG is managed by MC f/w. - */ - if (!(ctrlpriv->mc_en && pr_support) && rng_vid >= 4) { - ctrlpriv->rng4_sh_init = - rd_reg32(&ctrl->r4tst[0].rdsta); - /* - * If the secure keys (TDKEK, JDKEK, TDSK), were already - * generated, signal this to the function that is instantiating - * the state handles. An error would occur if RNG4 attempts - * to regenerate these keys before the next POR. - */ - gen_sk = ctrlpriv->rng4_sh_init & RDSTA_SKVN ? 0 : 1; - ctrlpriv->rng4_sh_init &= RDSTA_MASK; - do { - int inst_handles = - rd_reg32(&ctrl->r4tst[0].rdsta) & - RDSTA_MASK; - /* - * If either SH were instantiated by somebody else - * (e.g. u-boot) then it is assumed that the entropy - * parameters are properly set and thus the function - * setting these (kick_trng(...)) is skipped. - * Also, if a handle was instantiated, do not change - * the TRNG parameters. - */ - if (needs_entropy_delay_adjustment()) - ent_delay = 12000; - if (!(ctrlpriv->rng4_sh_init || inst_handles)) { - dev_info(dev, - "Entropy delay = %u\n", - ent_delay); - kick_trng(pdev, ent_delay); - ent_delay += 400; - } - /* - * if instantiate_rng(...) fails, the loop will rerun - * and the kick_trng(...) function will modify the - * upper and lower limits of the entropy sampling - * interval, leading to a successful initialization of - * the RNG. - */ - ret = instantiate_rng(dev, inst_handles, - gen_sk); - /* - * Entropy delay is determined via TRNG characterization. - * TRNG characterization is run across different voltages - * and temperatures. - * If worst case value for ent_dly is identified, - * the loop can be skipped for that platform. - */ - if (needs_entropy_delay_adjustment()) - break; - if (ret == -EAGAIN) - /* - * if here, the loop will rerun, - * so don't hog the CPU - */ - cpu_relax(); - } while ((ret == -EAGAIN) && (ent_delay < RTSDCTL_ENT_DLY_MAX)); - if (ret) { - dev_err(dev, "failed to instantiate RNG"); + if (reg_access) { + ret = caam_ctrl_rng_init(dev); + if (ret) return ret; - } - /* - * Set handles initialized by this module as the complement of - * the already initialized ones - */ - ctrlpriv->rng4_sh_init = ~ctrlpriv->rng4_sh_init & RDSTA_MASK; - - /* Enable RDB bit so that RNG works faster */ - clrsetbits_32(&ctrl->scfgr, 0, SCFGR_RDBENABLE); } -report_live: - /* NOTE: RTIC detection ought to go here, around Si time */ - caam_id = (u64)rd_reg32(&perfmon->caam_id_ms) << 32 | (u64)rd_reg32(&perfmon->caam_id_ls); diff --git a/drivers/crypto/caam/intern.h b/drivers/crypto/caam/intern.h index 86ed1b91c22d4da0d7b142d9e0b1dab66f97c8a7..b4f7bf77f4873041fce23ff457c71a749466542a 100644 --- a/drivers/crypto/caam/intern.h +++ b/drivers/crypto/caam/intern.h @@ -95,6 +95,7 @@ struct caam_drv_private { u8 blob_present; /* Nonzero if BLOB support present in device */ u8 mc_en; /* Nonzero if MC f/w is active */ u8 optee_en; /* Nonzero if OP-TEE f/w is active */ + bool pr_support; /* RNG prediction resistance available */ int secvio_irq; /* Security violation interrupt number */ int virt_en; /* Virtualization enabled in CAAM */ int era; /* CAAM Era (internal HW revision) */ diff --git a/drivers/crypto/caam/regs.h b/drivers/crypto/caam/regs.h index 66928f8a0c4b1e8baa4507eb70a1b5e6bce41c33..189e74c21f0cb48f79453e627a4aa3f155eb0bf9 100644 --- a/drivers/crypto/caam/regs.h +++ b/drivers/crypto/caam/regs.h @@ -3,7 +3,7 @@ * CAAM hardware register-level view * * Copyright 2008-2011 Freescale Semiconductor, Inc. - * Copyright 2018 NXP + * Copyright 2018, 2023 NXP */ #ifndef REGS_H @@ -523,6 +523,8 @@ struct rng4tst { #define RTSDCTL_ENT_DLY_MASK (0xffff << RTSDCTL_ENT_DLY_SHIFT) #define RTSDCTL_ENT_DLY_MIN 3200 #define RTSDCTL_ENT_DLY_MAX 12800 +#define RTSDCTL_SAMP_SIZE_MASK 0xffff +#define RTSDCTL_SAMP_SIZE_VAL 512 u32 rtsdctl; /* seed control register */ union { u32 rtsblim; /* PRGM=1: sparse bit limit register */ @@ -534,7 +536,15 @@ struct rng4tst { u32 rtfrqmax; /* PRGM=1: freq. count max. limit register */ u32 rtfrqcnt; /* PRGM=0: freq. count register */ }; - u32 rsvd1[40]; + union { + u32 rtscmc; /* statistical check run monobit count */ + u32 rtscml; /* statistical check run monobit limit */ + }; + union { + u32 rtscrc[6]; /* statistical check run length count */ + u32 rtscrl[6]; /* statistical check run length limit */ + }; + u32 rsvd1[33]; #define RDSTA_SKVT 0x80000000 #define RDSTA_SKVN 0x40000000 #define RDSTA_PR0 BIT(4) diff --git a/drivers/crypto/ccp/platform-access.c b/drivers/crypto/ccp/platform-access.c index 939c924fc38321a3eb3bd4f54ea23445804df673..94367bc49e35b869dc5093a918c21f325459fce6 100644 --- a/drivers/crypto/ccp/platform-access.c +++ b/drivers/crypto/ccp/platform-access.c @@ -67,6 +67,11 @@ int psp_send_platform_access_msg(enum psp_platform_access_msg msg, return -ENODEV; pa_dev = psp->platform_access_data; + + if (!pa_dev->vdata->cmdresp_reg || !pa_dev->vdata->cmdbuff_addr_lo_reg || + !pa_dev->vdata->cmdbuff_addr_hi_reg) + return -ENODEV; + cmd = psp->io_regs + pa_dev->vdata->cmdresp_reg; lo = psp->io_regs + pa_dev->vdata->cmdbuff_addr_lo_reg; hi = psp->io_regs + pa_dev->vdata->cmdbuff_addr_hi_reg; diff --git a/drivers/crypto/ccp/sp-pci.c b/drivers/crypto/ccp/sp-pci.c index aa15bc4cac2be50a661009a6f41f09e9b9841663..b603ad9b8341be8b5b75f5fd4820c3c275fabe22 100644 --- a/drivers/crypto/ccp/sp-pci.c +++ b/drivers/crypto/ccp/sp-pci.c @@ -361,6 +361,14 @@ static const struct tee_vdata teev1 = { .ring_rptr_reg = 0x10554, /* C2PMSG_21 */ }; +static const struct tee_vdata teev2 = { + .cmdresp_reg = 0x10944, /* C2PMSG_17 */ + .cmdbuff_addr_lo_reg = 0x10948, /* C2PMSG_18 */ + .cmdbuff_addr_hi_reg = 0x1094c, /* C2PMSG_19 */ + .ring_wptr_reg = 0x10950, /* C2PMSG_20 */ + .ring_rptr_reg = 0x10954, /* C2PMSG_21 */ +}; + static const struct platform_access_vdata pa_v1 = { .cmdresp_reg = 0x10570, /* C2PMSG_28 */ .cmdbuff_addr_lo_reg = 0x10574, /* C2PMSG_29 */ @@ -369,6 +377,11 @@ static const struct platform_access_vdata pa_v1 = { .doorbell_cmd_reg = 0x10a40, /* C2PMSG_80 */ }; +static const struct platform_access_vdata pa_v2 = { + .doorbell_button_reg = 0x10a24, /* C2PMSG_73 */ + .doorbell_cmd_reg = 0x10a40, /* C2PMSG_80 */ +}; + static const struct psp_vdata pspv1 = { .sev = &sevv1, .feature_reg = 0x105fc, /* C2PMSG_63 */ @@ -399,6 +412,22 @@ static const struct psp_vdata pspv4 = { .intsts_reg = 0x10694, /* P2CMSG_INTSTS */ }; +static const struct psp_vdata pspv5 = { + .tee = &teev2, + .platform_access = &pa_v2, + .feature_reg = 0x109fc, /* C2PMSG_63 */ + .inten_reg = 0x10510, /* P2CMSG_INTEN */ + .intsts_reg = 0x10514, /* P2CMSG_INTSTS */ +}; + +static const struct psp_vdata pspv6 = { + .sev = &sevv2, + .tee = &teev2, + .feature_reg = 0x109fc, /* C2PMSG_63 */ + .inten_reg = 0x10510, /* P2CMSG_INTEN */ + .intsts_reg = 0x10514, /* P2CMSG_INTSTS */ +}; + #endif static const struct sp_dev_vdata dev_vdata[] = { @@ -451,6 +480,18 @@ static const struct sp_dev_vdata dev_vdata[] = { .bar = 2, #ifdef CONFIG_CRYPTO_DEV_SP_PSP .psp_vdata = &pspv3, +#endif + }, + { /* 7 */ + .bar = 2, +#ifdef CONFIG_CRYPTO_DEV_SP_PSP + .psp_vdata = &pspv5, +#endif + }, + { /* 8 */ + .bar = 2, +#ifdef CONFIG_CRYPTO_DEV_SP_PSP + .psp_vdata = &pspv6, #endif }, }; @@ -463,6 +504,8 @@ static const struct pci_device_id sp_pci_table[] = { { PCI_VDEVICE(AMD, 0x14CA), (kernel_ulong_t)&dev_vdata[5] }, { PCI_VDEVICE(AMD, 0x15C7), (kernel_ulong_t)&dev_vdata[6] }, { PCI_VDEVICE(AMD, 0x1649), (kernel_ulong_t)&dev_vdata[6] }, + { PCI_VDEVICE(AMD, 0x17E0), (kernel_ulong_t)&dev_vdata[7] }, + { PCI_VDEVICE(AMD, 0x156E), (kernel_ulong_t)&dev_vdata[8] }, /* Last entry must be zero */ { 0, } }; diff --git a/drivers/crypto/hisilicon/Kconfig b/drivers/crypto/hisilicon/Kconfig index e8690c223584e90d24c93537c87cffdb21cc7795..4137a8bf131f0cb3362f3560b963e056df3af3d0 100644 --- a/drivers/crypto/hisilicon/Kconfig +++ b/drivers/crypto/hisilicon/Kconfig @@ -82,10 +82,3 @@ config CRYPTO_DEV_HISI_TRNG select CRYPTO_RNG help Support for HiSilicon TRNG Driver. - -config CRYPTO_DEV_HISTB_TRNG - tristate "Support for HiSTB TRNG Driver" - depends on ARCH_HISI || COMPILE_TEST - select HW_RANDOM - help - Support for HiSTB TRNG Driver. diff --git a/drivers/crypto/hisilicon/Makefile b/drivers/crypto/hisilicon/Makefile index fc51e0edec696281ba5680b16f3471815a892616..8595a5a5d22888d2e9e3d090f170057971f77fe8 100644 --- a/drivers/crypto/hisilicon/Makefile +++ b/drivers/crypto/hisilicon/Makefile @@ -5,4 +5,4 @@ obj-$(CONFIG_CRYPTO_DEV_HISI_SEC2) += sec2/ obj-$(CONFIG_CRYPTO_DEV_HISI_QM) += hisi_qm.o hisi_qm-objs = qm.o sgl.o debugfs.o obj-$(CONFIG_CRYPTO_DEV_HISI_ZIP) += zip/ -obj-y += trng/ +obj-$(CONFIG_CRYPTO_DEV_HISI_TRNG) += trng/ diff --git a/drivers/crypto/hisilicon/qm.c b/drivers/crypto/hisilicon/qm.c index ad0c042b5e665f762c4c634770a193b25ca473f3..edc6fd44e7ca9b46dd78c6ba0007fe908925a8da 100644 --- a/drivers/crypto/hisilicon/qm.c +++ b/drivers/crypto/hisilicon/qm.c @@ -610,7 +610,10 @@ EXPORT_SYMBOL_GPL(hisi_qm_wait_mb_ready); static void qm_mb_write(struct hisi_qm *qm, const void *src) { void __iomem *fun_base = qm->io_base + QM_MB_CMD_SEND_BASE; + +#if IS_ENABLED(CONFIG_ARM64) unsigned long tmp0 = 0, tmp1 = 0; +#endif if (!IS_ENABLED(CONFIG_ARM64)) { memcpy_toio(fun_base, src, 16); @@ -618,6 +621,7 @@ static void qm_mb_write(struct hisi_qm *qm, const void *src) return; } +#if IS_ENABLED(CONFIG_ARM64) asm volatile("ldp %0, %1, %3\n" "stp %0, %1, %2\n" "dmb oshst\n" @@ -626,6 +630,7 @@ static void qm_mb_write(struct hisi_qm *qm, const void *src) "+Q" (*((char __iomem *)fun_base)) : "Q" (*((char *)src)) : "memory"); +#endif } static int qm_mb_nolock(struct hisi_qm *qm, struct qm_mailbox *mailbox) diff --git a/drivers/crypto/hisilicon/trng/Makefile b/drivers/crypto/hisilicon/trng/Makefile index cf20b057c66b63f92a1adad42e384a028e514b6d..d909079f351c64e335c83c9b8d670ec5cdedab69 100644 --- a/drivers/crypto/hisilicon/trng/Makefile +++ b/drivers/crypto/hisilicon/trng/Makefile @@ -1,5 +1,2 @@ obj-$(CONFIG_CRYPTO_DEV_HISI_TRNG) += hisi-trng-v2.o hisi-trng-v2-objs = trng.o - -obj-$(CONFIG_CRYPTO_DEV_HISTB_TRNG) += histb-trng.o -histb-trng-objs += trng-stb.o diff --git a/drivers/crypto/intel/ixp4xx/ixp4xx_crypto.c b/drivers/crypto/intel/ixp4xx/ixp4xx_crypto.c index ed15379a9818b3c59bfb290fce4731fd71b05e91..4a18095ae5d8082b90dc87c9338b06bd2ad818b8 100644 --- a/drivers/crypto/intel/ixp4xx/ixp4xx_crypto.c +++ b/drivers/crypto/intel/ixp4xx/ixp4xx_crypto.c @@ -1175,9 +1175,9 @@ static int aead_perform(struct aead_request *req, int encrypt, /* The 12 hmac bytes are scattered, * we need to copy them into a safe buffer */ req_ctx->hmac_virt = dma_pool_alloc(buffer_pool, flags, &dma); - crypt->icv_rev_aes = dma; if (unlikely(!req_ctx->hmac_virt)) goto free_buf_dst; + crypt->icv_rev_aes = dma; if (!encrypt) { scatterwalk_map_and_copy(req_ctx->hmac_virt, req->src, cryptlen, authsize, 0); diff --git a/drivers/crypto/intel/qat/qat_4xxx/adf_4xxx_hw_data.c b/drivers/crypto/intel/qat/qat_4xxx/adf_4xxx_hw_data.c index 7324b86a4f40edec47e44282b6742d69fda82e5d..e543a9e24a06f28da9c0517fb1a1cb7d4f7d837b 100644 --- a/drivers/crypto/intel/qat/qat_4xxx/adf_4xxx_hw_data.c +++ b/drivers/crypto/intel/qat/qat_4xxx/adf_4xxx_hw_data.c @@ -11,37 +11,76 @@ #include "adf_4xxx_hw_data.h" #include "icp_qat_hw.h" +enum adf_fw_objs { + ADF_FW_SYM_OBJ, + ADF_FW_ASYM_OBJ, + ADF_FW_DC_OBJ, + ADF_FW_ADMIN_OBJ, +}; + +static const char * const adf_4xxx_fw_objs[] = { + [ADF_FW_SYM_OBJ] = ADF_4XXX_SYM_OBJ, + [ADF_FW_ASYM_OBJ] = ADF_4XXX_ASYM_OBJ, + [ADF_FW_DC_OBJ] = ADF_4XXX_DC_OBJ, + [ADF_FW_ADMIN_OBJ] = ADF_4XXX_ADMIN_OBJ, +}; + +static const char * const adf_402xx_fw_objs[] = { + [ADF_FW_SYM_OBJ] = ADF_402XX_SYM_OBJ, + [ADF_FW_ASYM_OBJ] = ADF_402XX_ASYM_OBJ, + [ADF_FW_DC_OBJ] = ADF_402XX_DC_OBJ, + [ADF_FW_ADMIN_OBJ] = ADF_402XX_ADMIN_OBJ, +}; + struct adf_fw_config { u32 ae_mask; - char *obj_name; + enum adf_fw_objs obj; }; -static struct adf_fw_config adf_4xxx_fw_cy_config[] = { - {0xF0, ADF_4XXX_SYM_OBJ}, - {0xF, ADF_4XXX_ASYM_OBJ}, - {0x100, ADF_4XXX_ADMIN_OBJ}, +static const struct adf_fw_config adf_fw_cy_config[] = { + {0xF0, ADF_FW_SYM_OBJ}, + {0xF, ADF_FW_ASYM_OBJ}, + {0x100, ADF_FW_ADMIN_OBJ}, }; -static struct adf_fw_config adf_4xxx_fw_dc_config[] = { - {0xF0, ADF_4XXX_DC_OBJ}, - {0xF, ADF_4XXX_DC_OBJ}, - {0x100, ADF_4XXX_ADMIN_OBJ}, +static const struct adf_fw_config adf_fw_dc_config[] = { + {0xF0, ADF_FW_DC_OBJ}, + {0xF, ADF_FW_DC_OBJ}, + {0x100, ADF_FW_ADMIN_OBJ}, }; -static struct adf_fw_config adf_402xx_fw_cy_config[] = { - {0xF0, ADF_402XX_SYM_OBJ}, - {0xF, ADF_402XX_ASYM_OBJ}, - {0x100, ADF_402XX_ADMIN_OBJ}, +static const struct adf_fw_config adf_fw_sym_config[] = { + {0xF0, ADF_FW_SYM_OBJ}, + {0xF, ADF_FW_SYM_OBJ}, + {0x100, ADF_FW_ADMIN_OBJ}, }; -static struct adf_fw_config adf_402xx_fw_dc_config[] = { - {0xF0, ADF_402XX_DC_OBJ}, - {0xF, ADF_402XX_DC_OBJ}, - {0x100, ADF_402XX_ADMIN_OBJ}, +static const struct adf_fw_config adf_fw_asym_config[] = { + {0xF0, ADF_FW_ASYM_OBJ}, + {0xF, ADF_FW_ASYM_OBJ}, + {0x100, ADF_FW_ADMIN_OBJ}, }; +static const struct adf_fw_config adf_fw_asym_dc_config[] = { + {0xF0, ADF_FW_ASYM_OBJ}, + {0xF, ADF_FW_DC_OBJ}, + {0x100, ADF_FW_ADMIN_OBJ}, +}; + +static const struct adf_fw_config adf_fw_sym_dc_config[] = { + {0xF0, ADF_FW_SYM_OBJ}, + {0xF, ADF_FW_DC_OBJ}, + {0x100, ADF_FW_ADMIN_OBJ}, +}; + +static_assert(ARRAY_SIZE(adf_fw_cy_config) == ARRAY_SIZE(adf_fw_dc_config)); +static_assert(ARRAY_SIZE(adf_fw_cy_config) == ARRAY_SIZE(adf_fw_sym_config)); +static_assert(ARRAY_SIZE(adf_fw_cy_config) == ARRAY_SIZE(adf_fw_asym_config)); +static_assert(ARRAY_SIZE(adf_fw_cy_config) == ARRAY_SIZE(adf_fw_asym_dc_config)); +static_assert(ARRAY_SIZE(adf_fw_cy_config) == ARRAY_SIZE(adf_fw_sym_dc_config)); + /* Worker thread to service arbiter mappings */ -static const u32 thrd_to_arb_map_cy[ADF_4XXX_MAX_ACCELENGINES] = { +static const u32 default_thrd_to_arb_map[ADF_4XXX_MAX_ACCELENGINES] = { 0x5555555, 0x5555555, 0x5555555, 0x5555555, 0xAAAAAAA, 0xAAAAAAA, 0xAAAAAAA, 0xAAAAAAA, 0x0 @@ -61,12 +100,26 @@ static struct adf_hw_device_class adf_4xxx_class = { enum dev_services { SVC_CY = 0, + SVC_CY2, SVC_DC, + SVC_SYM, + SVC_ASYM, + SVC_DC_ASYM, + SVC_ASYM_DC, + SVC_DC_SYM, + SVC_SYM_DC, }; static const char *const dev_cfg_services[] = { [SVC_CY] = ADF_CFG_CY, + [SVC_CY2] = ADF_CFG_ASYM_SYM, [SVC_DC] = ADF_CFG_DC, + [SVC_SYM] = ADF_CFG_SYM, + [SVC_ASYM] = ADF_CFG_ASYM, + [SVC_DC_ASYM] = ADF_CFG_DC_ASYM, + [SVC_ASYM_DC] = ADF_CFG_ASYM_DC, + [SVC_DC_SYM] = ADF_CFG_DC_SYM, + [SVC_SYM_DC] = ADF_CFG_SYM_DC, }; static int get_service_enabled(struct adf_accel_dev *accel_dev) @@ -156,45 +209,50 @@ static void set_msix_default_rttable(struct adf_accel_dev *accel_dev) static u32 get_accel_cap(struct adf_accel_dev *accel_dev) { struct pci_dev *pdev = accel_dev->accel_pci_dev.pci_dev; - u32 capabilities_cy, capabilities_dc; + u32 capabilities_sym, capabilities_asym, capabilities_dc; u32 fusectl1; /* Read accelerator capabilities mask */ pci_read_config_dword(pdev, ADF_4XXX_FUSECTL1_OFFSET, &fusectl1); - capabilities_cy = ICP_ACCEL_CAPABILITIES_CRYPTO_SYMMETRIC | - ICP_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC | + capabilities_sym = ICP_ACCEL_CAPABILITIES_CRYPTO_SYMMETRIC | ICP_ACCEL_CAPABILITIES_CIPHER | ICP_ACCEL_CAPABILITIES_AUTHENTICATION | ICP_ACCEL_CAPABILITIES_SHA3 | ICP_ACCEL_CAPABILITIES_SHA3_EXT | ICP_ACCEL_CAPABILITIES_HKDF | - ICP_ACCEL_CAPABILITIES_ECEDMONT | ICP_ACCEL_CAPABILITIES_CHACHA_POLY | ICP_ACCEL_CAPABILITIES_AESGCM_SPC | ICP_ACCEL_CAPABILITIES_AES_V2; /* A set bit in fusectl1 means the feature is OFF in this SKU */ if (fusectl1 & ICP_ACCEL_4XXX_MASK_CIPHER_SLICE) { - capabilities_cy &= ~ICP_ACCEL_CAPABILITIES_CRYPTO_SYMMETRIC; - capabilities_cy &= ~ICP_ACCEL_CAPABILITIES_HKDF; - capabilities_cy &= ~ICP_ACCEL_CAPABILITIES_CIPHER; + capabilities_sym &= ~ICP_ACCEL_CAPABILITIES_CRYPTO_SYMMETRIC; + capabilities_sym &= ~ICP_ACCEL_CAPABILITIES_HKDF; + capabilities_sym &= ~ICP_ACCEL_CAPABILITIES_CIPHER; } + if (fusectl1 & ICP_ACCEL_4XXX_MASK_UCS_SLICE) { - capabilities_cy &= ~ICP_ACCEL_CAPABILITIES_CHACHA_POLY; - capabilities_cy &= ~ICP_ACCEL_CAPABILITIES_AESGCM_SPC; - capabilities_cy &= ~ICP_ACCEL_CAPABILITIES_AES_V2; - capabilities_cy &= ~ICP_ACCEL_CAPABILITIES_CIPHER; + capabilities_sym &= ~ICP_ACCEL_CAPABILITIES_CHACHA_POLY; + capabilities_sym &= ~ICP_ACCEL_CAPABILITIES_AESGCM_SPC; + capabilities_sym &= ~ICP_ACCEL_CAPABILITIES_AES_V2; + capabilities_sym &= ~ICP_ACCEL_CAPABILITIES_CIPHER; } + if (fusectl1 & ICP_ACCEL_4XXX_MASK_AUTH_SLICE) { - capabilities_cy &= ~ICP_ACCEL_CAPABILITIES_AUTHENTICATION; - capabilities_cy &= ~ICP_ACCEL_CAPABILITIES_SHA3; - capabilities_cy &= ~ICP_ACCEL_CAPABILITIES_SHA3_EXT; - capabilities_cy &= ~ICP_ACCEL_CAPABILITIES_CIPHER; + capabilities_sym &= ~ICP_ACCEL_CAPABILITIES_AUTHENTICATION; + capabilities_sym &= ~ICP_ACCEL_CAPABILITIES_SHA3; + capabilities_sym &= ~ICP_ACCEL_CAPABILITIES_SHA3_EXT; + capabilities_sym &= ~ICP_ACCEL_CAPABILITIES_CIPHER; } + + capabilities_asym = ICP_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC | + ICP_ACCEL_CAPABILITIES_CIPHER | + ICP_ACCEL_CAPABILITIES_ECEDMONT; + if (fusectl1 & ICP_ACCEL_4XXX_MASK_PKE_SLICE) { - capabilities_cy &= ~ICP_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC; - capabilities_cy &= ~ICP_ACCEL_CAPABILITIES_ECEDMONT; + capabilities_asym &= ~ICP_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC; + capabilities_asym &= ~ICP_ACCEL_CAPABILITIES_ECEDMONT; } capabilities_dc = ICP_ACCEL_CAPABILITIES_COMPRESSION | @@ -211,12 +269,23 @@ static u32 get_accel_cap(struct adf_accel_dev *accel_dev) switch (get_service_enabled(accel_dev)) { case SVC_CY: - return capabilities_cy; + case SVC_CY2: + return capabilities_sym | capabilities_asym; case SVC_DC: return capabilities_dc; + case SVC_SYM: + return capabilities_sym; + case SVC_ASYM: + return capabilities_asym; + case SVC_ASYM_DC: + case SVC_DC_ASYM: + return capabilities_asym | capabilities_dc; + case SVC_SYM_DC: + case SVC_DC_SYM: + return capabilities_sym | capabilities_dc; + default: + return 0; } - - return 0; } static enum dev_sku_info get_sku(struct adf_hw_device_data *self) @@ -227,13 +296,11 @@ static enum dev_sku_info get_sku(struct adf_hw_device_data *self) static const u32 *adf_get_arbiter_mapping(struct adf_accel_dev *accel_dev) { switch (get_service_enabled(accel_dev)) { - case SVC_CY: - return thrd_to_arb_map_cy; case SVC_DC: return thrd_to_arb_map_dc; + default: + return default_thrd_to_arb_map; } - - return NULL; } static void get_arb_info(struct arb_info *arb_info) @@ -304,47 +371,83 @@ static int adf_init_device(struct adf_accel_dev *accel_dev) static u32 uof_get_num_objs(void) { - BUILD_BUG_ON_MSG(ARRAY_SIZE(adf_4xxx_fw_cy_config) != - ARRAY_SIZE(adf_4xxx_fw_dc_config), - "Size mismatch between adf_4xxx_fw_*_config arrays"); - - return ARRAY_SIZE(adf_4xxx_fw_cy_config); + return ARRAY_SIZE(adf_fw_cy_config); } -static char *uof_get_name_4xxx(struct adf_accel_dev *accel_dev, u32 obj_num) +static const char *uof_get_name(struct adf_accel_dev *accel_dev, u32 obj_num, + const char * const fw_objs[], int num_objs) { + int id; + switch (get_service_enabled(accel_dev)) { case SVC_CY: - return adf_4xxx_fw_cy_config[obj_num].obj_name; + case SVC_CY2: + id = adf_fw_cy_config[obj_num].obj; + break; case SVC_DC: - return adf_4xxx_fw_dc_config[obj_num].obj_name; + id = adf_fw_dc_config[obj_num].obj; + break; + case SVC_SYM: + id = adf_fw_sym_config[obj_num].obj; + break; + case SVC_ASYM: + id = adf_fw_asym_config[obj_num].obj; + break; + case SVC_ASYM_DC: + case SVC_DC_ASYM: + id = adf_fw_asym_dc_config[obj_num].obj; + break; + case SVC_SYM_DC: + case SVC_DC_SYM: + id = adf_fw_sym_dc_config[obj_num].obj; + break; + default: + id = -EINVAL; + break; } - return NULL; + if (id < 0 || id > num_objs) + return NULL; + + return fw_objs[id]; } -static char *uof_get_name_402xx(struct adf_accel_dev *accel_dev, u32 obj_num) +static const char *uof_get_name_4xxx(struct adf_accel_dev *accel_dev, u32 obj_num) { - switch (get_service_enabled(accel_dev)) { - case SVC_CY: - return adf_402xx_fw_cy_config[obj_num].obj_name; - case SVC_DC: - return adf_402xx_fw_dc_config[obj_num].obj_name; - } + int num_fw_objs = ARRAY_SIZE(adf_4xxx_fw_objs); - return NULL; + return uof_get_name(accel_dev, obj_num, adf_4xxx_fw_objs, num_fw_objs); +} + +static const char *uof_get_name_402xx(struct adf_accel_dev *accel_dev, u32 obj_num) +{ + int num_fw_objs = ARRAY_SIZE(adf_402xx_fw_objs); + + return uof_get_name(accel_dev, obj_num, adf_402xx_fw_objs, num_fw_objs); } static u32 uof_get_ae_mask(struct adf_accel_dev *accel_dev, u32 obj_num) { switch (get_service_enabled(accel_dev)) { case SVC_CY: - return adf_4xxx_fw_cy_config[obj_num].ae_mask; + return adf_fw_cy_config[obj_num].ae_mask; case SVC_DC: - return adf_4xxx_fw_dc_config[obj_num].ae_mask; + return adf_fw_dc_config[obj_num].ae_mask; + case SVC_CY2: + return adf_fw_cy_config[obj_num].ae_mask; + case SVC_SYM: + return adf_fw_sym_config[obj_num].ae_mask; + case SVC_ASYM: + return adf_fw_asym_config[obj_num].ae_mask; + case SVC_ASYM_DC: + case SVC_DC_ASYM: + return adf_fw_asym_dc_config[obj_num].ae_mask; + case SVC_SYM_DC: + case SVC_DC_SYM: + return adf_fw_sym_dc_config[obj_num].ae_mask; + default: + return 0; } - - return 0; } void adf_init_hw_data_4xxx(struct adf_hw_device_data *hw_data, u32 dev_id) diff --git a/drivers/crypto/intel/qat/qat_4xxx/adf_4xxx_hw_data.h b/drivers/crypto/intel/qat/qat_4xxx/adf_4xxx_hw_data.h index 085e259c245a51c47bea57581764a4f05d5aa4f8..e5b314d2b60e65f39328ff39a9def80ae23c867b 100644 --- a/drivers/crypto/intel/qat/qat_4xxx/adf_4xxx_hw_data.h +++ b/drivers/crypto/intel/qat/qat_4xxx/adf_4xxx_hw_data.h @@ -72,7 +72,7 @@ enum icp_qat_4xxx_slice_mask { ICP_ACCEL_4XXX_MASK_COMPRESS_SLICE = BIT(3), ICP_ACCEL_4XXX_MASK_UCS_SLICE = BIT(4), ICP_ACCEL_4XXX_MASK_EIA3_SLICE = BIT(5), - ICP_ACCEL_4XXX_MASK_SMX_SLICE = BIT(6), + ICP_ACCEL_4XXX_MASK_SMX_SLICE = BIT(7), }; void adf_init_hw_data_4xxx(struct adf_hw_device_data *hw_data, u32 dev_id); diff --git a/drivers/crypto/intel/qat/qat_4xxx/adf_drv.c b/drivers/crypto/intel/qat/qat_4xxx/adf_drv.c index ceb87327a5fe0f8cfdaf24c972c8192165c20a7e..1a15600361d0e5c8acf7e2f976a178052cfd6eb5 100644 --- a/drivers/crypto/intel/qat/qat_4xxx/adf_drv.c +++ b/drivers/crypto/intel/qat/qat_4xxx/adf_drv.c @@ -7,6 +7,7 @@ #include #include #include +#include #include "adf_4xxx_hw_data.h" #include "qat_compression.h" @@ -24,11 +25,25 @@ MODULE_DEVICE_TABLE(pci, adf_pci_tbl); enum configs { DEV_CFG_CY = 0, DEV_CFG_DC, + DEV_CFG_SYM, + DEV_CFG_ASYM, + DEV_CFG_ASYM_SYM, + DEV_CFG_ASYM_DC, + DEV_CFG_DC_ASYM, + DEV_CFG_SYM_DC, + DEV_CFG_DC_SYM, }; static const char * const services_operations[] = { ADF_CFG_CY, ADF_CFG_DC, + ADF_CFG_SYM, + ADF_CFG_ASYM, + ADF_CFG_ASYM_SYM, + ADF_CFG_ASYM_DC, + ADF_CFG_DC_ASYM, + ADF_CFG_SYM_DC, + ADF_CFG_DC_SYM, }; static void adf_cleanup_accel(struct adf_accel_dev *accel_dev) @@ -37,8 +52,8 @@ static void adf_cleanup_accel(struct adf_accel_dev *accel_dev) adf_clean_hw_data_4xxx(accel_dev->hw_device); accel_dev->hw_device = NULL; } + adf_dbgfs_exit(accel_dev); adf_cfg_dev_remove(accel_dev); - debugfs_remove(accel_dev->debugfs_dir); adf_devmgr_rm_dev(accel_dev, NULL); } @@ -241,6 +256,21 @@ static int adf_comp_dev_config(struct adf_accel_dev *accel_dev) return ret; } +static int adf_no_dev_config(struct adf_accel_dev *accel_dev) +{ + unsigned long val; + int ret; + + val = 0; + ret = adf_cfg_add_key_value_param(accel_dev, ADF_KERNEL_SEC, ADF_NUM_DC, + &val, ADF_DEC); + if (ret) + return ret; + + return adf_cfg_add_key_value_param(accel_dev, ADF_KERNEL_SEC, ADF_NUM_CY, + &val, ADF_DEC); +} + int adf_gen4_dev_config(struct adf_accel_dev *accel_dev) { char services[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = {0}; @@ -265,11 +295,15 @@ int adf_gen4_dev_config(struct adf_accel_dev *accel_dev) switch (ret) { case DEV_CFG_CY: + case DEV_CFG_ASYM_SYM: ret = adf_crypto_dev_config(accel_dev); break; case DEV_CFG_DC: ret = adf_comp_dev_config(accel_dev); break; + default: + ret = adf_no_dev_config(accel_dev); + break; } if (ret) @@ -289,7 +323,6 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) struct adf_accel_dev *accel_dev; struct adf_accel_pci *accel_pci_dev; struct adf_hw_device_data *hw_data; - char name[ADF_DEVICE_NAME_LENGTH]; unsigned int i, bar_nr; unsigned long bar_mask; struct adf_bar *bar; @@ -348,12 +381,6 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) goto out_err; } - /* Create dev top level debugfs entry */ - snprintf(name, sizeof(name), "%s%s_%s", ADF_DEVICE_NAME_PREFIX, - hw_data->dev_class->name, pci_name(pdev)); - - accel_dev->debugfs_dir = debugfs_create_dir(name, NULL); - /* Create device configuration table */ ret = adf_cfg_dev_add(accel_dev); if (ret) @@ -410,6 +437,8 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) goto out_err; } + adf_dbgfs_init(accel_dev); + ret = adf_dev_up(accel_dev, true); if (ret) goto out_err_dev_stop; diff --git a/drivers/crypto/intel/qat/qat_c3xxx/adf_drv.c b/drivers/crypto/intel/qat/qat_c3xxx/adf_drv.c index bb4dca735ab5ad8894b961301d969e8e56c07e5d..468c9102093fce93303fe2cfeb3ed27df10a8598 100644 --- a/drivers/crypto/intel/qat/qat_c3xxx/adf_drv.c +++ b/drivers/crypto/intel/qat/qat_c3xxx/adf_drv.c @@ -16,6 +16,7 @@ #include #include #include +#include #include "adf_c3xxx_hw_data.h" static const struct pci_device_id adf_pci_tbl[] = { @@ -65,8 +66,8 @@ static void adf_cleanup_accel(struct adf_accel_dev *accel_dev) kfree(accel_dev->hw_device); accel_dev->hw_device = NULL; } + adf_dbgfs_exit(accel_dev); adf_cfg_dev_remove(accel_dev); - debugfs_remove(accel_dev->debugfs_dir); adf_devmgr_rm_dev(accel_dev, NULL); } @@ -75,7 +76,6 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) struct adf_accel_dev *accel_dev; struct adf_accel_pci *accel_pci_dev; struct adf_hw_device_data *hw_data; - char name[ADF_DEVICE_NAME_LENGTH]; unsigned int i, bar_nr; unsigned long bar_mask; int ret; @@ -142,12 +142,6 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) goto out_err; } - /* Create dev top level debugfs entry */ - snprintf(name, sizeof(name), "%s%s_%s", ADF_DEVICE_NAME_PREFIX, - hw_data->dev_class->name, pci_name(pdev)); - - accel_dev->debugfs_dir = debugfs_create_dir(name, NULL); - /* Create device configuration table */ ret = adf_cfg_dev_add(accel_dev); if (ret) @@ -199,6 +193,8 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) goto out_err_free_reg; } + adf_dbgfs_init(accel_dev); + ret = adf_dev_up(accel_dev, true); if (ret) goto out_err_dev_stop; diff --git a/drivers/crypto/intel/qat/qat_c3xxxvf/adf_drv.c b/drivers/crypto/intel/qat/qat_c3xxxvf/adf_drv.c index e8cc10f641343786b02354032804b3d3c3379202..d5a0ecca9d0bba4929863448d479d52258d00a8d 100644 --- a/drivers/crypto/intel/qat/qat_c3xxxvf/adf_drv.c +++ b/drivers/crypto/intel/qat/qat_c3xxxvf/adf_drv.c @@ -16,6 +16,7 @@ #include #include #include +#include #include "adf_c3xxxvf_hw_data.h" static const struct pci_device_id adf_pci_tbl[] = { @@ -64,8 +65,8 @@ static void adf_cleanup_accel(struct adf_accel_dev *accel_dev) kfree(accel_dev->hw_device); accel_dev->hw_device = NULL; } + adf_dbgfs_exit(accel_dev); adf_cfg_dev_remove(accel_dev); - debugfs_remove(accel_dev->debugfs_dir); pf = adf_devmgr_pci_to_accel_dev(accel_pci_dev->pci_dev->physfn); adf_devmgr_rm_dev(accel_dev, pf); } @@ -76,7 +77,6 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) struct adf_accel_dev *pf; struct adf_accel_pci *accel_pci_dev; struct adf_hw_device_data *hw_data; - char name[ADF_DEVICE_NAME_LENGTH]; unsigned int i, bar_nr; unsigned long bar_mask; int ret; @@ -123,12 +123,6 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) hw_data->ae_mask = hw_data->get_ae_mask(hw_data); accel_pci_dev->sku = hw_data->get_sku(hw_data); - /* Create dev top level debugfs entry */ - snprintf(name, sizeof(name), "%s%s_%s", ADF_DEVICE_NAME_PREFIX, - hw_data->dev_class->name, pci_name(pdev)); - - accel_dev->debugfs_dir = debugfs_create_dir(name, NULL); - /* Create device configuration table */ ret = adf_cfg_dev_add(accel_dev); if (ret) @@ -173,6 +167,8 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) /* Completion for VF2PF request/response message exchange */ init_completion(&accel_dev->vf.msg_received); + adf_dbgfs_init(accel_dev); + ret = adf_dev_up(accel_dev, false); if (ret) goto out_err_dev_stop; diff --git a/drivers/crypto/intel/qat/qat_c62x/adf_drv.c b/drivers/crypto/intel/qat/qat_c62x/adf_drv.c index ca18ae14c09972d33b07f49a99ce11173b5d9cd9..0186921be93689d041b0e0b7a88ef4437ae49907 100644 --- a/drivers/crypto/intel/qat/qat_c62x/adf_drv.c +++ b/drivers/crypto/intel/qat/qat_c62x/adf_drv.c @@ -16,6 +16,7 @@ #include #include #include +#include #include "adf_c62x_hw_data.h" static const struct pci_device_id adf_pci_tbl[] = { @@ -65,8 +66,8 @@ static void adf_cleanup_accel(struct adf_accel_dev *accel_dev) kfree(accel_dev->hw_device); accel_dev->hw_device = NULL; } + adf_dbgfs_exit(accel_dev); adf_cfg_dev_remove(accel_dev); - debugfs_remove(accel_dev->debugfs_dir); adf_devmgr_rm_dev(accel_dev, NULL); } @@ -75,7 +76,6 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) struct adf_accel_dev *accel_dev; struct adf_accel_pci *accel_pci_dev; struct adf_hw_device_data *hw_data; - char name[ADF_DEVICE_NAME_LENGTH]; unsigned int i, bar_nr; unsigned long bar_mask; int ret; @@ -142,12 +142,6 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) goto out_err; } - /* Create dev top level debugfs entry */ - snprintf(name, sizeof(name), "%s%s_%s", ADF_DEVICE_NAME_PREFIX, - hw_data->dev_class->name, pci_name(pdev)); - - accel_dev->debugfs_dir = debugfs_create_dir(name, NULL); - /* Create device configuration table */ ret = adf_cfg_dev_add(accel_dev); if (ret) @@ -199,6 +193,8 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) goto out_err_free_reg; } + adf_dbgfs_init(accel_dev); + ret = adf_dev_up(accel_dev, true); if (ret) goto out_err_dev_stop; diff --git a/drivers/crypto/intel/qat/qat_c62xvf/adf_drv.c b/drivers/crypto/intel/qat/qat_c62xvf/adf_drv.c index 37566309df943a931ced86abcfc73f75be859a55..c9ae6c0d0dca2ec39b872de9d0e8e443c8605b3a 100644 --- a/drivers/crypto/intel/qat/qat_c62xvf/adf_drv.c +++ b/drivers/crypto/intel/qat/qat_c62xvf/adf_drv.c @@ -16,6 +16,7 @@ #include #include #include +#include #include "adf_c62xvf_hw_data.h" static const struct pci_device_id adf_pci_tbl[] = { @@ -64,8 +65,8 @@ static void adf_cleanup_accel(struct adf_accel_dev *accel_dev) kfree(accel_dev->hw_device); accel_dev->hw_device = NULL; } + adf_dbgfs_exit(accel_dev); adf_cfg_dev_remove(accel_dev); - debugfs_remove(accel_dev->debugfs_dir); pf = adf_devmgr_pci_to_accel_dev(accel_pci_dev->pci_dev->physfn); adf_devmgr_rm_dev(accel_dev, pf); } @@ -76,7 +77,6 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) struct adf_accel_dev *pf; struct adf_accel_pci *accel_pci_dev; struct adf_hw_device_data *hw_data; - char name[ADF_DEVICE_NAME_LENGTH]; unsigned int i, bar_nr; unsigned long bar_mask; int ret; @@ -123,12 +123,6 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) hw_data->ae_mask = hw_data->get_ae_mask(hw_data); accel_pci_dev->sku = hw_data->get_sku(hw_data); - /* Create dev top level debugfs entry */ - snprintf(name, sizeof(name), "%s%s_%s", ADF_DEVICE_NAME_PREFIX, - hw_data->dev_class->name, pci_name(pdev)); - - accel_dev->debugfs_dir = debugfs_create_dir(name, NULL); - /* Create device configuration table */ ret = adf_cfg_dev_add(accel_dev); if (ret) @@ -173,6 +167,8 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) /* Completion for VF2PF request/response message exchange */ init_completion(&accel_dev->vf.msg_received); + adf_dbgfs_init(accel_dev); + ret = adf_dev_up(accel_dev, false); if (ret) goto out_err_dev_stop; diff --git a/drivers/crypto/intel/qat/qat_common/Makefile b/drivers/crypto/intel/qat/qat_common/Makefile index 1fb8d50f509f82c24361a1d93e6148b8244e2c94..38de3aba6e8ce360b0c92fac9a2667ecb6a51f11 100644 --- a/drivers/crypto/intel/qat/qat_common/Makefile +++ b/drivers/crypto/intel/qat/qat_common/Makefile @@ -27,7 +27,9 @@ intel_qat-objs := adf_cfg.o \ qat_hal.o \ qat_bl.o -intel_qat-$(CONFIG_DEBUG_FS) += adf_transport_debug.o +intel_qat-$(CONFIG_DEBUG_FS) += adf_transport_debug.o \ + adf_dbgfs.o + intel_qat-$(CONFIG_PCI_IOV) += adf_sriov.o adf_vf_isr.o adf_pfvf_utils.o \ adf_pfvf_pf_msg.o adf_pfvf_pf_proto.o \ adf_pfvf_vf_msg.o adf_pfvf_vf_proto.o \ diff --git a/drivers/crypto/intel/qat/qat_common/adf_accel_devices.h b/drivers/crypto/intel/qat/qat_common/adf_accel_devices.h index bd19e646089970b01cb7b1b55d0ba1f1eaf04f23..0399417b91fc7f31e8096c2e2c5b125089abd9fb 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_accel_devices.h +++ b/drivers/crypto/intel/qat/qat_common/adf_accel_devices.h @@ -202,7 +202,7 @@ struct adf_hw_device_data { int (*ring_pair_reset)(struct adf_accel_dev *accel_dev, u32 bank_nr); void (*reset_device)(struct adf_accel_dev *accel_dev); void (*set_msix_rttable)(struct adf_accel_dev *accel_dev); - char *(*uof_get_name)(struct adf_accel_dev *accel_dev, u32 obj_num); + const char *(*uof_get_name)(struct adf_accel_dev *accel_dev, u32 obj_num); u32 (*uof_get_num_objs)(void); u32 (*uof_get_ae_mask)(struct adf_accel_dev *accel_dev, u32 obj_num); int (*dev_config)(struct adf_accel_dev *accel_dev); diff --git a/drivers/crypto/intel/qat/qat_common/adf_accel_engine.c b/drivers/crypto/intel/qat/qat_common/adf_accel_engine.c index 4ce2b666929e66f10034039e06750c8a9429d4b1..6be064dc64c8e8daa769baf9c28d0d453eb4d749 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_accel_engine.c +++ b/drivers/crypto/intel/qat/qat_common/adf_accel_engine.c @@ -13,7 +13,7 @@ static int adf_ae_fw_load_images(struct adf_accel_dev *accel_dev, void *fw_addr, struct adf_fw_loader_data *loader_data = accel_dev->fw_loader; struct adf_hw_device_data *hw_device = accel_dev->hw_device; struct icp_qat_fw_loader_handle *loader; - char *obj_name; + const char *obj_name; u32 num_objs; u32 ae_mask; int i; diff --git a/drivers/crypto/intel/qat/qat_common/adf_admin.c b/drivers/crypto/intel/qat/qat_common/adf_admin.c index 3b6184c350811f86bbc284e9c220fee2e8bec4c2..118775ee02f297a552651df88a15640844f82e5b 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_admin.c +++ b/drivers/crypto/intel/qat/qat_common/adf_admin.c @@ -286,7 +286,6 @@ int adf_init_admin_pm(struct adf_accel_dev *accel_dev, u32 idle_delay) return adf_send_admin(accel_dev, &req, &resp, ae_mask); } -EXPORT_SYMBOL_GPL(adf_init_admin_pm); int adf_init_admin_comms(struct adf_accel_dev *accel_dev) { diff --git a/drivers/crypto/intel/qat/qat_common/adf_cfg.c b/drivers/crypto/intel/qat/qat_common/adf_cfg.c index 1931e5b37f2bd16d84b493a369aaaac74f0c53d1..8836f015c39c41e0fbdb9c2db230c1aa8b9952c9 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_cfg.c +++ b/drivers/crypto/intel/qat/qat_common/adf_cfg.c @@ -74,15 +74,30 @@ int adf_cfg_dev_add(struct adf_accel_dev *accel_dev) INIT_LIST_HEAD(&dev_cfg_data->sec_list); init_rwsem(&dev_cfg_data->lock); accel_dev->cfg = dev_cfg_data; + return 0; +} +EXPORT_SYMBOL_GPL(adf_cfg_dev_add); - /* accel_dev->debugfs_dir should always be non-NULL here */ - dev_cfg_data->debug = debugfs_create_file("dev_cfg", S_IRUSR, +void adf_cfg_dev_dbgfs_add(struct adf_accel_dev *accel_dev) +{ + struct adf_cfg_device_data *dev_cfg_data = accel_dev->cfg; + + dev_cfg_data->debug = debugfs_create_file("dev_cfg", 0400, accel_dev->debugfs_dir, dev_cfg_data, &qat_dev_cfg_fops); - return 0; } -EXPORT_SYMBOL_GPL(adf_cfg_dev_add); + +void adf_cfg_dev_dbgfs_rm(struct adf_accel_dev *accel_dev) +{ + struct adf_cfg_device_data *dev_cfg_data = accel_dev->cfg; + + if (!dev_cfg_data) + return; + + debugfs_remove(dev_cfg_data->debug); + dev_cfg_data->debug = NULL; +} static void adf_cfg_section_del_all(struct list_head *head); @@ -116,7 +131,6 @@ void adf_cfg_dev_remove(struct adf_accel_dev *accel_dev) down_write(&dev_cfg_data->lock); adf_cfg_section_del_all(&dev_cfg_data->sec_list); up_write(&dev_cfg_data->lock); - debugfs_remove(dev_cfg_data->debug); kfree(dev_cfg_data); accel_dev->cfg = NULL; } diff --git a/drivers/crypto/intel/qat/qat_common/adf_cfg.h b/drivers/crypto/intel/qat/qat_common/adf_cfg.h index 376cde61a60ea7094444103c0dfccd47a417efb8..c0c9052b22135c8e4227d08ed50fceb7da6a5d47 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_cfg.h +++ b/drivers/crypto/intel/qat/qat_common/adf_cfg.h @@ -31,6 +31,8 @@ struct adf_cfg_device_data { int adf_cfg_dev_add(struct adf_accel_dev *accel_dev); void adf_cfg_dev_remove(struct adf_accel_dev *accel_dev); +void adf_cfg_dev_dbgfs_add(struct adf_accel_dev *accel_dev); +void adf_cfg_dev_dbgfs_rm(struct adf_accel_dev *accel_dev); int adf_cfg_section_add(struct adf_accel_dev *accel_dev, const char *name); void adf_cfg_del_all(struct adf_accel_dev *accel_dev); int adf_cfg_add_key_value_param(struct adf_accel_dev *accel_dev, diff --git a/drivers/crypto/intel/qat/qat_common/adf_cfg_strings.h b/drivers/crypto/intel/qat/qat_common/adf_cfg_strings.h index 5d8c3bdb258c18042f551ecfe00330b18c561710..3ae1e5caee0ee2a6833e2b941d68037fa891c7ad 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_cfg_strings.h +++ b/drivers/crypto/intel/qat/qat_common/adf_cfg_strings.h @@ -25,7 +25,15 @@ #define ADF_DC "Dc" #define ADF_CFG_DC "dc" #define ADF_CFG_CY "sym;asym" +#define ADF_CFG_SYM "sym" +#define ADF_CFG_ASYM "asym" +#define ADF_CFG_ASYM_SYM "asym;sym" +#define ADF_CFG_ASYM_DC "asym;dc" +#define ADF_CFG_DC_ASYM "dc;asym" +#define ADF_CFG_SYM_DC "sym;dc" +#define ADF_CFG_DC_SYM "dc;sym" #define ADF_SERVICES_ENABLED "ServicesEnabled" +#define ADF_PM_IDLE_SUPPORT "PmIdleSupport" #define ADF_ETRMGR_COALESCING_ENABLED "InterruptCoalescingEnabled" #define ADF_ETRMGR_COALESCING_ENABLED_FORMAT \ ADF_ETRMGR_BANK "%d" ADF_ETRMGR_COALESCING_ENABLED diff --git a/drivers/crypto/intel/qat/qat_common/adf_common_drv.h b/drivers/crypto/intel/qat/qat_common/adf_common_drv.h index db79759bee6175e1ed7716f743ff9697ffc6f6c0..b8132eb9bc2a0279d386634c731d1c8bb003a43d 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_common_drv.h +++ b/drivers/crypto/intel/qat/qat_common/adf_common_drv.h @@ -187,7 +187,7 @@ void qat_uclo_del_obj(struct icp_qat_fw_loader_handle *handle); int qat_uclo_wr_mimage(struct icp_qat_fw_loader_handle *handle, void *addr_ptr, int mem_size); int qat_uclo_map_obj(struct icp_qat_fw_loader_handle *handle, - void *addr_ptr, u32 mem_size, char *obj_name); + void *addr_ptr, u32 mem_size, const char *obj_name); int qat_uclo_set_cfg_ae_mask(struct icp_qat_fw_loader_handle *handle, unsigned int cfg_ae_mask); int adf_init_misc_wq(void); diff --git a/drivers/crypto/intel/qat/qat_common/adf_dbgfs.c b/drivers/crypto/intel/qat/qat_common/adf_dbgfs.c new file mode 100644 index 0000000000000000000000000000000000000000..d0a2f892e6eb976f755ba77a945a04dc0725ae58 --- /dev/null +++ b/drivers/crypto/intel/qat/qat_common/adf_dbgfs.c @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* Copyright(c) 2023 Intel Corporation */ + +#include +#include "adf_accel_devices.h" +#include "adf_cfg.h" +#include "adf_common_drv.h" +#include "adf_dbgfs.h" + +/** + * adf_dbgfs_init() - add persistent debugfs entries + * @accel_dev: Pointer to acceleration device. + * + * This function creates debugfs entries that are persistent through a device + * state change (from up to down or vice versa). + */ +void adf_dbgfs_init(struct adf_accel_dev *accel_dev) +{ + char name[ADF_DEVICE_NAME_LENGTH]; + void *ret; + + /* Create dev top level debugfs entry */ + snprintf(name, sizeof(name), "%s%s_%s", ADF_DEVICE_NAME_PREFIX, + accel_dev->hw_device->dev_class->name, + pci_name(accel_dev->accel_pci_dev.pci_dev)); + + ret = debugfs_create_dir(name, NULL); + if (IS_ERR_OR_NULL(ret)) + return; + + accel_dev->debugfs_dir = ret; + + adf_cfg_dev_dbgfs_add(accel_dev); +} +EXPORT_SYMBOL_GPL(adf_dbgfs_init); + +/** + * adf_dbgfs_exit() - remove persistent debugfs entries + * @accel_dev: Pointer to acceleration device. + */ +void adf_dbgfs_exit(struct adf_accel_dev *accel_dev) +{ + adf_cfg_dev_dbgfs_rm(accel_dev); + debugfs_remove(accel_dev->debugfs_dir); +} +EXPORT_SYMBOL_GPL(adf_dbgfs_exit); + +/** + * adf_dbgfs_add() - add non-persistent debugfs entries + * @accel_dev: Pointer to acceleration device. + * + * This function creates debugfs entries that are not persistent through + * a device state change (from up to down or vice versa). + */ +void adf_dbgfs_add(struct adf_accel_dev *accel_dev) +{ + if (!accel_dev->debugfs_dir) + return; +} + +/** + * adf_dbgfs_rm() - remove non-persistent debugfs entries + * @accel_dev: Pointer to acceleration device. + */ +void adf_dbgfs_rm(struct adf_accel_dev *accel_dev) +{ + if (!accel_dev->debugfs_dir) + return; +} diff --git a/drivers/crypto/intel/qat/qat_common/adf_dbgfs.h b/drivers/crypto/intel/qat/qat_common/adf_dbgfs.h new file mode 100644 index 0000000000000000000000000000000000000000..e0cb2c2a2ed0b47c65e03c8790ee5d300445e6e7 --- /dev/null +++ b/drivers/crypto/intel/qat/qat_common/adf_dbgfs.h @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* Copyright(c) 2023 Intel Corporation */ + +#ifndef ADF_DBGFS_H +#define ADF_DBGFS_H + +#ifdef CONFIG_DEBUG_FS +void adf_dbgfs_init(struct adf_accel_dev *accel_dev); +void adf_dbgfs_add(struct adf_accel_dev *accel_dev); +void adf_dbgfs_rm(struct adf_accel_dev *accel_dev); +void adf_dbgfs_exit(struct adf_accel_dev *accel_dev); +#else +static inline void adf_dbgfs_init(struct adf_accel_dev *accel_dev) +{ +} + +static inline void adf_dbgfs_add(struct adf_accel_dev *accel_dev) +{ +} + +static inline void adf_dbgfs_rm(struct adf_accel_dev *accel_dev) +{ +} + +static inline void adf_dbgfs_exit(struct adf_accel_dev *accel_dev) +{ +} +#endif +#endif diff --git a/drivers/crypto/intel/qat/qat_common/adf_gen4_pm.c b/drivers/crypto/intel/qat/qat_common/adf_gen4_pm.c index 7037c0892a8a2737f085f3c1c578ab4b2bea84da..34c6cd8e27c0b58d16db092e0a1cbc875c0dd1e6 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_gen4_pm.c +++ b/drivers/crypto/intel/qat/qat_common/adf_gen4_pm.c @@ -23,15 +23,25 @@ struct adf_gen4_pm_data { static int send_host_msg(struct adf_accel_dev *accel_dev) { + char pm_idle_support_cfg[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = {}; void __iomem *pmisc = adf_get_pmisc_base(accel_dev); + bool pm_idle_support; u32 msg; + int ret; msg = ADF_CSR_RD(pmisc, ADF_GEN4_PM_HOST_MSG); if (msg & ADF_GEN4_PM_MSG_PENDING) return -EBUSY; + adf_cfg_get_param_value(accel_dev, ADF_GENERAL_SEC, + ADF_PM_IDLE_SUPPORT, pm_idle_support_cfg); + ret = kstrtobool(pm_idle_support_cfg, &pm_idle_support); + if (ret) + pm_idle_support = true; + /* Send HOST_MSG */ - msg = FIELD_PREP(ADF_GEN4_PM_MSG_PAYLOAD_BIT_MASK, PM_SET_MIN); + msg = FIELD_PREP(ADF_GEN4_PM_MSG_PAYLOAD_BIT_MASK, + pm_idle_support ? PM_SET_MIN : PM_NO_CHANGE); msg |= ADF_GEN4_PM_MSG_PENDING; ADF_CSR_WR(pmisc, ADF_GEN4_PM_HOST_MSG, msg); diff --git a/drivers/crypto/intel/qat/qat_common/adf_gen4_pm.h b/drivers/crypto/intel/qat/qat_common/adf_gen4_pm.h index f8f8a9ee29e5b9b6bf58f90a03098fb0111bd8f3..dd112923e006d0276ff24d53f8057079007de1d6 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_gen4_pm.h +++ b/drivers/crypto/intel/qat/qat_common/adf_gen4_pm.h @@ -37,6 +37,7 @@ #define ADF_GEN4_PM_DEFAULT_IDLE_FILTER (0x0) #define ADF_GEN4_PM_MAX_IDLE_FILTER (0x7) +#define ADF_GEN4_PM_DEFAULT_IDLE_SUPPORT (0x1) int adf_gen4_enable_pm(struct adf_accel_dev *accel_dev); bool adf_gen4_handle_pm_interrupt(struct adf_accel_dev *accel_dev); diff --git a/drivers/crypto/intel/qat/qat_common/adf_init.c b/drivers/crypto/intel/qat/qat_common/adf_init.c index 0985f64ab11ab5c623f324ae8c2d43f5f045a245..826179c985241d15eb4b76e4bc832915de8e21a9 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_init.c +++ b/drivers/crypto/intel/qat/qat_common/adf_init.c @@ -7,6 +7,7 @@ #include "adf_accel_devices.h" #include "adf_cfg.h" #include "adf_common_drv.h" +#include "adf_dbgfs.h" static LIST_HEAD(service_table); static DEFINE_MUTEX(service_lock); @@ -216,6 +217,9 @@ static int adf_dev_start(struct adf_accel_dev *accel_dev) clear_bit(ADF_STATUS_STARTED, &accel_dev->status); return -EFAULT; } + + adf_dbgfs_add(accel_dev); + return 0; } @@ -240,6 +244,8 @@ static void adf_dev_stop(struct adf_accel_dev *accel_dev) !test_bit(ADF_STATUS_STARTING, &accel_dev->status)) return; + adf_dbgfs_rm(accel_dev); + clear_bit(ADF_STATUS_STARTING, &accel_dev->status); clear_bit(ADF_STATUS_STARTED, &accel_dev->status); diff --git a/drivers/crypto/intel/qat/qat_common/adf_sysfs.c b/drivers/crypto/intel/qat/qat_common/adf_sysfs.c index 3eb6611ab1b119190d1208dff5cdcaded76102a6..a74d2f93036709375c7939f553543ea34223bf74 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_sysfs.c +++ b/drivers/crypto/intel/qat/qat_common/adf_sysfs.c @@ -78,6 +78,13 @@ static ssize_t state_store(struct device *dev, struct device_attribute *attr, static const char * const services_operations[] = { ADF_CFG_CY, ADF_CFG_DC, + ADF_CFG_SYM, + ADF_CFG_ASYM, + ADF_CFG_ASYM_SYM, + ADF_CFG_ASYM_DC, + ADF_CFG_DC_ASYM, + ADF_CFG_SYM_DC, + ADF_CFG_DC_SYM, }; static ssize_t cfg_services_show(struct device *dev, struct device_attribute *attr, @@ -145,12 +152,65 @@ static ssize_t cfg_services_store(struct device *dev, struct device_attribute *a return count; } +static ssize_t pm_idle_enabled_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + char pm_idle_enabled[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = {}; + struct adf_accel_dev *accel_dev; + int ret; + + accel_dev = adf_devmgr_pci_to_accel_dev(to_pci_dev(dev)); + if (!accel_dev) + return -EINVAL; + + ret = adf_cfg_get_param_value(accel_dev, ADF_GENERAL_SEC, + ADF_PM_IDLE_SUPPORT, pm_idle_enabled); + if (ret) + return sysfs_emit(buf, "1\n"); + + return sysfs_emit(buf, "%s\n", pm_idle_enabled); +} + +static ssize_t pm_idle_enabled_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + unsigned long pm_idle_enabled_cfg_val; + struct adf_accel_dev *accel_dev; + bool pm_idle_enabled; + int ret; + + ret = kstrtobool(buf, &pm_idle_enabled); + if (ret) + return ret; + + pm_idle_enabled_cfg_val = pm_idle_enabled; + accel_dev = adf_devmgr_pci_to_accel_dev(to_pci_dev(dev)); + if (!accel_dev) + return -EINVAL; + + if (adf_dev_started(accel_dev)) { + dev_info(dev, "Device qat_dev%d must be down to set pm_idle_enabled.\n", + accel_dev->accel_id); + return -EINVAL; + } + + ret = adf_cfg_add_key_value_param(accel_dev, ADF_GENERAL_SEC, + ADF_PM_IDLE_SUPPORT, &pm_idle_enabled_cfg_val, + ADF_DEC); + if (ret) + return ret; + + return count; +} +static DEVICE_ATTR_RW(pm_idle_enabled); + static DEVICE_ATTR_RW(state); static DEVICE_ATTR_RW(cfg_services); static struct attribute *qat_attrs[] = { &dev_attr_state.attr, &dev_attr_cfg_services.attr, + &dev_attr_pm_idle_enabled.attr, NULL, }; diff --git a/drivers/crypto/intel/qat/qat_common/icp_qat_hw.h b/drivers/crypto/intel/qat/qat_common/icp_qat_hw.h index 4042739bb6fa9d38412c76d889623706c32ed712..a65059e56248ab162c98ff170964ebc8daf809d3 100644 --- a/drivers/crypto/intel/qat/qat_common/icp_qat_hw.h +++ b/drivers/crypto/intel/qat/qat_common/icp_qat_hw.h @@ -87,8 +87,7 @@ enum icp_qat_capabilities_mask { ICP_ACCEL_CAPABILITIES_AUTHENTICATION = BIT(3), ICP_ACCEL_CAPABILITIES_RESERVED_1 = BIT(4), ICP_ACCEL_CAPABILITIES_COMPRESSION = BIT(5), - ICP_ACCEL_CAPABILITIES_LZS_COMPRESSION = BIT(6), - ICP_ACCEL_CAPABILITIES_RAND = BIT(7), + /* Bits 6-7 are currently reserved */ ICP_ACCEL_CAPABILITIES_ZUC = BIT(8), ICP_ACCEL_CAPABILITIES_SHA3 = BIT(9), /* Bits 10-11 are currently reserved */ diff --git a/drivers/crypto/intel/qat/qat_common/qat_algs.c b/drivers/crypto/intel/qat/qat_common/qat_algs.c index 538dcbfbcd261828bed01c36c13f5c5ea9698051..3c4bba4a87795ee1f800e6207917a1362899aafe 100644 --- a/drivers/crypto/intel/qat/qat_common/qat_algs.c +++ b/drivers/crypto/intel/qat/qat_common/qat_algs.c @@ -106,7 +106,6 @@ static int qat_get_inter_state_size(enum icp_qat_hw_auth_algo qat_hash_alg) default: return -EFAULT; } - return -EFAULT; } static int qat_alg_do_precomputes(struct icp_qat_hw_auth_algo_blk *hash, diff --git a/drivers/crypto/intel/qat/qat_common/qat_asym_algs.c b/drivers/crypto/intel/qat/qat_common/qat_asym_algs.c index 935a7e012946e30b3b703e7d427449909b53ec1e..4128200a903293ba66e5fe9c337407fddf93ebbe 100644 --- a/drivers/crypto/intel/qat/qat_common/qat_asym_algs.c +++ b/drivers/crypto/intel/qat/qat_common/qat_asym_algs.c @@ -170,15 +170,14 @@ static void qat_dh_cb(struct icp_qat_fw_pke_resp *resp) } areq->dst_len = req->ctx.dh->p_size; + dma_unmap_single(dev, req->out.dh.r, req->ctx.dh->p_size, + DMA_FROM_DEVICE); if (req->dst_align) { scatterwalk_map_and_copy(req->dst_align, areq->dst, 0, areq->dst_len, 1); kfree_sensitive(req->dst_align); } - dma_unmap_single(dev, req->out.dh.r, req->ctx.dh->p_size, - DMA_FROM_DEVICE); - dma_unmap_single(dev, req->phy_in, sizeof(struct qat_dh_input_params), DMA_TO_DEVICE); dma_unmap_single(dev, req->phy_out, @@ -521,12 +520,14 @@ static void qat_rsa_cb(struct icp_qat_fw_pke_resp *resp) err = (err == ICP_QAT_FW_COMN_STATUS_FLAG_OK) ? 0 : -EINVAL; - kfree_sensitive(req->src_align); - dma_unmap_single(dev, req->in.rsa.enc.m, req->ctx.rsa->key_sz, DMA_TO_DEVICE); + kfree_sensitive(req->src_align); + areq->dst_len = req->ctx.rsa->key_sz; + dma_unmap_single(dev, req->out.rsa.enc.c, req->ctx.rsa->key_sz, + DMA_FROM_DEVICE); if (req->dst_align) { scatterwalk_map_and_copy(req->dst_align, areq->dst, 0, areq->dst_len, 1); @@ -534,9 +535,6 @@ static void qat_rsa_cb(struct icp_qat_fw_pke_resp *resp) kfree_sensitive(req->dst_align); } - dma_unmap_single(dev, req->out.rsa.enc.c, req->ctx.rsa->key_sz, - DMA_FROM_DEVICE); - dma_unmap_single(dev, req->phy_in, sizeof(struct qat_rsa_input_params), DMA_TO_DEVICE); dma_unmap_single(dev, req->phy_out, diff --git a/drivers/crypto/intel/qat/qat_common/qat_uclo.c b/drivers/crypto/intel/qat/qat_common/qat_uclo.c index 3ba8ca20b3d763c6c081ddf86141186380ea793c..ce837bcc1caba48fd6ad9f94df2d03e5cca10f53 100644 --- a/drivers/crypto/intel/qat/qat_common/qat_uclo.c +++ b/drivers/crypto/intel/qat/qat_common/qat_uclo.c @@ -1685,7 +1685,7 @@ static void qat_uclo_del_mof(struct icp_qat_fw_loader_handle *handle) } static int qat_uclo_seek_obj_inside_mof(struct icp_qat_mof_handle *mobj_handle, - char *obj_name, char **obj_ptr, + const char *obj_name, char **obj_ptr, unsigned int *obj_size) { struct icp_qat_mof_objhdr *obj_hdr = mobj_handle->obj_table.obj_hdr; @@ -1837,8 +1837,8 @@ static int qat_uclo_check_mof_format(struct icp_qat_mof_file_hdr *mof_hdr) static int qat_uclo_map_mof_obj(struct icp_qat_fw_loader_handle *handle, struct icp_qat_mof_file_hdr *mof_ptr, - u32 mof_size, char *obj_name, char **obj_ptr, - unsigned int *obj_size) + u32 mof_size, const char *obj_name, + char **obj_ptr, unsigned int *obj_size) { struct icp_qat_mof_chunkhdr *mof_chunkhdr; unsigned int file_id = mof_ptr->file_id; @@ -1888,7 +1888,7 @@ static int qat_uclo_map_mof_obj(struct icp_qat_fw_loader_handle *handle, } int qat_uclo_map_obj(struct icp_qat_fw_loader_handle *handle, - void *addr_ptr, u32 mem_size, char *obj_name) + void *addr_ptr, u32 mem_size, const char *obj_name) { char *obj_addr; u32 obj_size; diff --git a/drivers/crypto/intel/qat/qat_dh895xcc/adf_drv.c b/drivers/crypto/intel/qat/qat_dh895xcc/adf_drv.c index e18860ab5c8e4d8f863f013e3a419f831e72ec88..1e748e8ce12d5df17d92d7f921c1ffb16f8598cf 100644 --- a/drivers/crypto/intel/qat/qat_dh895xcc/adf_drv.c +++ b/drivers/crypto/intel/qat/qat_dh895xcc/adf_drv.c @@ -16,6 +16,7 @@ #include #include #include +#include #include "adf_dh895xcc_hw_data.h" static const struct pci_device_id adf_pci_tbl[] = { @@ -65,8 +66,8 @@ static void adf_cleanup_accel(struct adf_accel_dev *accel_dev) kfree(accel_dev->hw_device); accel_dev->hw_device = NULL; } + adf_dbgfs_exit(accel_dev); adf_cfg_dev_remove(accel_dev); - debugfs_remove(accel_dev->debugfs_dir); adf_devmgr_rm_dev(accel_dev, NULL); } @@ -75,7 +76,6 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) struct adf_accel_dev *accel_dev; struct adf_accel_pci *accel_pci_dev; struct adf_hw_device_data *hw_data; - char name[ADF_DEVICE_NAME_LENGTH]; unsigned int i, bar_nr; unsigned long bar_mask; int ret; @@ -140,12 +140,6 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) goto out_err; } - /* Create dev top level debugfs entry */ - snprintf(name, sizeof(name), "%s%s_%s", ADF_DEVICE_NAME_PREFIX, - hw_data->dev_class->name, pci_name(pdev)); - - accel_dev->debugfs_dir = debugfs_create_dir(name, NULL); - /* Create device configuration table */ ret = adf_cfg_dev_add(accel_dev); if (ret) @@ -199,6 +193,8 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) goto out_err_free_reg; } + adf_dbgfs_init(accel_dev); + ret = adf_dev_up(accel_dev, true); if (ret) goto out_err_dev_stop; diff --git a/drivers/crypto/intel/qat/qat_dh895xccvf/adf_drv.c b/drivers/crypto/intel/qat/qat_dh895xccvf/adf_drv.c index 96854a1cd87e8c6a9e7a610152ac72b60ecc257c..fefb85ceaeb9a2b261a06a1b8a1702e019c26d4a 100644 --- a/drivers/crypto/intel/qat/qat_dh895xccvf/adf_drv.c +++ b/drivers/crypto/intel/qat/qat_dh895xccvf/adf_drv.c @@ -16,6 +16,7 @@ #include #include #include +#include #include "adf_dh895xccvf_hw_data.h" static const struct pci_device_id adf_pci_tbl[] = { @@ -64,8 +65,8 @@ static void adf_cleanup_accel(struct adf_accel_dev *accel_dev) kfree(accel_dev->hw_device); accel_dev->hw_device = NULL; } + adf_dbgfs_exit(accel_dev); adf_cfg_dev_remove(accel_dev); - debugfs_remove(accel_dev->debugfs_dir); pf = adf_devmgr_pci_to_accel_dev(accel_pci_dev->pci_dev->physfn); adf_devmgr_rm_dev(accel_dev, pf); } @@ -76,7 +77,6 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) struct adf_accel_dev *pf; struct adf_accel_pci *accel_pci_dev; struct adf_hw_device_data *hw_data; - char name[ADF_DEVICE_NAME_LENGTH]; unsigned int i, bar_nr; unsigned long bar_mask; int ret; @@ -123,12 +123,6 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) hw_data->ae_mask = hw_data->get_ae_mask(hw_data); accel_pci_dev->sku = hw_data->get_sku(hw_data); - /* Create dev top level debugfs entry */ - snprintf(name, sizeof(name), "%s%s_%s", ADF_DEVICE_NAME_PREFIX, - hw_data->dev_class->name, pci_name(pdev)); - - accel_dev->debugfs_dir = debugfs_create_dir(name, NULL); - /* Create device configuration table */ ret = adf_cfg_dev_add(accel_dev); if (ret) @@ -173,6 +167,8 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) /* Completion for VF2PF request/response message exchange */ init_completion(&accel_dev->vf.msg_received); + adf_dbgfs_init(accel_dev); + ret = adf_dev_up(accel_dev, false); if (ret) goto out_err_dev_stop; diff --git a/drivers/crypto/marvell/cesa/cipher.c b/drivers/crypto/marvell/cesa/cipher.c index c6f2fa753b7c039fec909c545c3e34ca92ce0e3a..0f37dfd42d850954ab214992ccbf19b4c057202b 100644 --- a/drivers/crypto/marvell/cesa/cipher.c +++ b/drivers/crypto/marvell/cesa/cipher.c @@ -297,7 +297,7 @@ static int mv_cesa_des_setkey(struct crypto_skcipher *cipher, const u8 *key, static int mv_cesa_des3_ede_setkey(struct crypto_skcipher *cipher, const u8 *key, unsigned int len) { - struct mv_cesa_des_ctx *ctx = crypto_skcipher_ctx(cipher); + struct mv_cesa_des3_ctx *ctx = crypto_skcipher_ctx(cipher); int err; err = verify_skcipher_des3_key(cipher, key); diff --git a/drivers/crypto/marvell/octeontx2/otx2_cpt_common.h b/drivers/crypto/marvell/octeontx2/otx2_cpt_common.h index 6019066a6451a09112c9928e393b982cbfbb2002..46b778bbbee44c536c7e29bff01012488b18d5f6 100644 --- a/drivers/crypto/marvell/octeontx2/otx2_cpt_common.h +++ b/drivers/crypto/marvell/octeontx2/otx2_cpt_common.h @@ -40,10 +40,25 @@ enum otx2_cpt_eng_type { }; /* Take mbox id from end of CPT mbox range in AF (range 0xA00 - 0xBFF) */ +#define MBOX_MSG_RX_INLINE_IPSEC_LF_CFG 0xBFE #define MBOX_MSG_GET_ENG_GRP_NUM 0xBFF #define MBOX_MSG_GET_CAPS 0xBFD #define MBOX_MSG_GET_KVF_LIMITS 0xBFC +/* + * Message request to config cpt lf for inline inbound ipsec. + * This message is only used between CPT PF <-> CPT VF + */ +struct otx2_cpt_rx_inline_lf_cfg { + struct mbox_msghdr hdr; + u16 sso_pf_func; + u16 param1; + u16 param2; + u16 opcode; + u32 credit; + u32 reserved; +}; + /* * Message request and response to get engine group number * which has attached a given type of engines (SE, AE, IE) diff --git a/drivers/crypto/marvell/octeontx2/otx2_cpt_mbox_common.c b/drivers/crypto/marvell/octeontx2/otx2_cpt_mbox_common.c index 115997475beb39e1dd07460ef9bdfcdaa4b34352..273ee5352a50b49b9916e95e16b279212953b6d1 100644 --- a/drivers/crypto/marvell/octeontx2/otx2_cpt_mbox_common.c +++ b/drivers/crypto/marvell/octeontx2/otx2_cpt_mbox_common.c @@ -141,6 +141,8 @@ int otx2_cpt_attach_rscrs_msg(struct otx2_cptlfs_info *lfs) req->hdr.sig = OTX2_MBOX_REQ_SIG; req->hdr.pcifunc = 0; req->cptlfs = lfs->lfs_num; + req->cpt_blkaddr = lfs->blkaddr; + req->modify = 1; ret = otx2_cpt_send_mbox_msg(mbox, lfs->pdev); if (ret) return ret; @@ -168,6 +170,7 @@ int otx2_cpt_detach_rsrcs_msg(struct otx2_cptlfs_info *lfs) req->hdr.id = MBOX_MSG_DETACH_RESOURCES; req->hdr.sig = OTX2_MBOX_REQ_SIG; req->hdr.pcifunc = 0; + req->cptlfs = 1; ret = otx2_cpt_send_mbox_msg(mbox, lfs->pdev); if (ret) return ret; diff --git a/drivers/crypto/marvell/octeontx2/otx2_cptlf.c b/drivers/crypto/marvell/octeontx2/otx2_cptlf.c index 71e5f79431afaca1d5116bf9cfe2bb74a87152bb..6edd27ff8c4e3c763c7c062e29db96c579a08943 100644 --- a/drivers/crypto/marvell/octeontx2/otx2_cptlf.c +++ b/drivers/crypto/marvell/octeontx2/otx2_cptlf.c @@ -13,10 +13,10 @@ static void cptlf_do_set_done_time_wait(struct otx2_cptlf_info *lf, { union otx2_cptx_lf_done_wait done_wait; - done_wait.u = otx2_cpt_read64(lf->lfs->reg_base, BLKADDR_CPT0, lf->slot, - OTX2_CPT_LF_DONE_WAIT); + done_wait.u = otx2_cpt_read64(lf->lfs->reg_base, lf->lfs->blkaddr, + lf->slot, OTX2_CPT_LF_DONE_WAIT); done_wait.s.time_wait = time_wait; - otx2_cpt_write64(lf->lfs->reg_base, BLKADDR_CPT0, lf->slot, + otx2_cpt_write64(lf->lfs->reg_base, lf->lfs->blkaddr, lf->slot, OTX2_CPT_LF_DONE_WAIT, done_wait.u); } @@ -24,10 +24,10 @@ static void cptlf_do_set_done_num_wait(struct otx2_cptlf_info *lf, int num_wait) { union otx2_cptx_lf_done_wait done_wait; - done_wait.u = otx2_cpt_read64(lf->lfs->reg_base, BLKADDR_CPT0, lf->slot, - OTX2_CPT_LF_DONE_WAIT); + done_wait.u = otx2_cpt_read64(lf->lfs->reg_base, lf->lfs->blkaddr, + lf->slot, OTX2_CPT_LF_DONE_WAIT); done_wait.s.num_wait = num_wait; - otx2_cpt_write64(lf->lfs->reg_base, BLKADDR_CPT0, lf->slot, + otx2_cpt_write64(lf->lfs->reg_base, lf->lfs->blkaddr, lf->slot, OTX2_CPT_LF_DONE_WAIT, done_wait.u); } @@ -147,7 +147,7 @@ static void cptlf_set_misc_intrs(struct otx2_cptlfs_info *lfs, u8 enable) irq_misc.s.nwrp = 0x1; for (slot = 0; slot < lfs->lfs_num; slot++) - otx2_cpt_write64(lfs->reg_base, BLKADDR_CPT0, slot, reg, + otx2_cpt_write64(lfs->reg_base, lfs->blkaddr, slot, reg, irq_misc.u); } @@ -157,7 +157,7 @@ static void cptlf_enable_intrs(struct otx2_cptlfs_info *lfs) /* Enable done interrupts */ for (slot = 0; slot < lfs->lfs_num; slot++) - otx2_cpt_write64(lfs->reg_base, BLKADDR_CPT0, slot, + otx2_cpt_write64(lfs->reg_base, lfs->blkaddr, slot, OTX2_CPT_LF_DONE_INT_ENA_W1S, 0x1); /* Enable Misc interrupts */ cptlf_set_misc_intrs(lfs, true); @@ -168,7 +168,7 @@ static void cptlf_disable_intrs(struct otx2_cptlfs_info *lfs) int slot; for (slot = 0; slot < lfs->lfs_num; slot++) - otx2_cpt_write64(lfs->reg_base, BLKADDR_CPT0, slot, + otx2_cpt_write64(lfs->reg_base, lfs->blkaddr, slot, OTX2_CPT_LF_DONE_INT_ENA_W1C, 0x1); cptlf_set_misc_intrs(lfs, false); } @@ -177,7 +177,7 @@ static inline int cptlf_read_done_cnt(struct otx2_cptlf_info *lf) { union otx2_cptx_lf_done irq_cnt; - irq_cnt.u = otx2_cpt_read64(lf->lfs->reg_base, BLKADDR_CPT0, lf->slot, + irq_cnt.u = otx2_cpt_read64(lf->lfs->reg_base, lf->lfs->blkaddr, lf->slot, OTX2_CPT_LF_DONE); return irq_cnt.s.done; } @@ -189,8 +189,8 @@ static irqreturn_t cptlf_misc_intr_handler(int __always_unused irq, void *arg) struct device *dev; dev = &lf->lfs->pdev->dev; - irq_misc.u = otx2_cpt_read64(lf->lfs->reg_base, BLKADDR_CPT0, lf->slot, - OTX2_CPT_LF_MISC_INT); + irq_misc.u = otx2_cpt_read64(lf->lfs->reg_base, lf->lfs->blkaddr, + lf->slot, OTX2_CPT_LF_MISC_INT); irq_misc_ack.u = 0x0; if (irq_misc.s.fault) { @@ -222,7 +222,7 @@ static irqreturn_t cptlf_misc_intr_handler(int __always_unused irq, void *arg) } /* Acknowledge interrupts */ - otx2_cpt_write64(lf->lfs->reg_base, BLKADDR_CPT0, lf->slot, + otx2_cpt_write64(lf->lfs->reg_base, lf->lfs->blkaddr, lf->slot, OTX2_CPT_LF_MISC_INT, irq_misc_ack.u); return IRQ_HANDLED; @@ -237,13 +237,13 @@ static irqreturn_t cptlf_done_intr_handler(int irq, void *arg) /* Read the number of completed requests */ irq_cnt = cptlf_read_done_cnt(lf); if (irq_cnt) { - done_wait.u = otx2_cpt_read64(lf->lfs->reg_base, BLKADDR_CPT0, + done_wait.u = otx2_cpt_read64(lf->lfs->reg_base, lf->lfs->blkaddr, lf->slot, OTX2_CPT_LF_DONE_WAIT); /* Acknowledge the number of completed requests */ - otx2_cpt_write64(lf->lfs->reg_base, BLKADDR_CPT0, lf->slot, + otx2_cpt_write64(lf->lfs->reg_base, lf->lfs->blkaddr, lf->slot, OTX2_CPT_LF_DONE_ACK, irq_cnt); - otx2_cpt_write64(lf->lfs->reg_base, BLKADDR_CPT0, lf->slot, + otx2_cpt_write64(lf->lfs->reg_base, lf->lfs->blkaddr, lf->slot, OTX2_CPT_LF_DONE_WAIT, done_wait.u); if (unlikely(!lf->wqe)) { dev_err(&lf->lfs->pdev->dev, "No work for LF %d\n", @@ -393,7 +393,7 @@ int otx2_cptlf_init(struct otx2_cptlfs_info *lfs, u8 eng_grp_mask, int pri, OTX2_CPT_LMT_LF_LMTLINEX(0)); lfs->lf[slot].ioreg = lfs->reg_base + - OTX2_CPT_RVU_FUNC_ADDR_S(BLKADDR_CPT0, slot, + OTX2_CPT_RVU_FUNC_ADDR_S(lfs->blkaddr, slot, OTX2_CPT_LF_NQX(0)); } /* Send request to attach LFs */ diff --git a/drivers/crypto/marvell/octeontx2/otx2_cptlf.h b/drivers/crypto/marvell/octeontx2/otx2_cptlf.h index 4fcaf61a70e36b092b0d96afb332c654be7edb4d..5302fe3d0e6f8bba1375c6aadedabde42602d2a6 100644 --- a/drivers/crypto/marvell/octeontx2/otx2_cptlf.h +++ b/drivers/crypto/marvell/octeontx2/otx2_cptlf.h @@ -180,7 +180,7 @@ static inline void otx2_cptlf_set_iqueues_base_addr( for (slot = 0; slot < lfs->lfs_num; slot++) { lf_q_base.u = lfs->lf[slot].iqueue.dma_addr; - otx2_cpt_write64(lfs->reg_base, BLKADDR_CPT0, slot, + otx2_cpt_write64(lfs->reg_base, lfs->blkaddr, slot, OTX2_CPT_LF_Q_BASE, lf_q_base.u); } } @@ -191,7 +191,7 @@ static inline void otx2_cptlf_do_set_iqueue_size(struct otx2_cptlf_info *lf) lf_q_size.s.size_div40 = OTX2_CPT_SIZE_DIV40 + OTX2_CPT_EXTRA_SIZE_DIV40; - otx2_cpt_write64(lf->lfs->reg_base, BLKADDR_CPT0, lf->slot, + otx2_cpt_write64(lf->lfs->reg_base, lf->lfs->blkaddr, lf->slot, OTX2_CPT_LF_Q_SIZE, lf_q_size.u); } @@ -207,15 +207,16 @@ static inline void otx2_cptlf_do_disable_iqueue(struct otx2_cptlf_info *lf) { union otx2_cptx_lf_ctl lf_ctl = { .u = 0x0 }; union otx2_cptx_lf_inprog lf_inprog; + u8 blkaddr = lf->lfs->blkaddr; int timeout = 20; /* Disable instructions enqueuing */ - otx2_cpt_write64(lf->lfs->reg_base, BLKADDR_CPT0, lf->slot, + otx2_cpt_write64(lf->lfs->reg_base, blkaddr, lf->slot, OTX2_CPT_LF_CTL, lf_ctl.u); /* Wait for instruction queue to become empty */ do { - lf_inprog.u = otx2_cpt_read64(lf->lfs->reg_base, BLKADDR_CPT0, + lf_inprog.u = otx2_cpt_read64(lf->lfs->reg_base, blkaddr, lf->slot, OTX2_CPT_LF_INPROG); if (!lf_inprog.s.inflight) break; @@ -234,7 +235,7 @@ static inline void otx2_cptlf_do_disable_iqueue(struct otx2_cptlf_info *lf) * the queue should be empty at this point */ lf_inprog.s.eena = 0x0; - otx2_cpt_write64(lf->lfs->reg_base, BLKADDR_CPT0, lf->slot, + otx2_cpt_write64(lf->lfs->reg_base, blkaddr, lf->slot, OTX2_CPT_LF_INPROG, lf_inprog.u); } @@ -249,14 +250,15 @@ static inline void otx2_cptlf_disable_iqueues(struct otx2_cptlfs_info *lfs) static inline void otx2_cptlf_set_iqueue_enq(struct otx2_cptlf_info *lf, bool enable) { + u8 blkaddr = lf->lfs->blkaddr; union otx2_cptx_lf_ctl lf_ctl; - lf_ctl.u = otx2_cpt_read64(lf->lfs->reg_base, BLKADDR_CPT0, lf->slot, + lf_ctl.u = otx2_cpt_read64(lf->lfs->reg_base, blkaddr, lf->slot, OTX2_CPT_LF_CTL); /* Set iqueue's enqueuing */ lf_ctl.s.ena = enable ? 0x1 : 0x0; - otx2_cpt_write64(lf->lfs->reg_base, BLKADDR_CPT0, lf->slot, + otx2_cpt_write64(lf->lfs->reg_base, blkaddr, lf->slot, OTX2_CPT_LF_CTL, lf_ctl.u); } @@ -269,13 +271,14 @@ static inline void otx2_cptlf_set_iqueue_exec(struct otx2_cptlf_info *lf, bool enable) { union otx2_cptx_lf_inprog lf_inprog; + u8 blkaddr = lf->lfs->blkaddr; - lf_inprog.u = otx2_cpt_read64(lf->lfs->reg_base, BLKADDR_CPT0, lf->slot, + lf_inprog.u = otx2_cpt_read64(lf->lfs->reg_base, blkaddr, lf->slot, OTX2_CPT_LF_INPROG); /* Set iqueue's execution */ lf_inprog.s.eena = enable ? 0x1 : 0x0; - otx2_cpt_write64(lf->lfs->reg_base, BLKADDR_CPT0, lf->slot, + otx2_cpt_write64(lf->lfs->reg_base, blkaddr, lf->slot, OTX2_CPT_LF_INPROG, lf_inprog.u); } @@ -364,6 +367,18 @@ static inline bool otx2_cptlf_started(struct otx2_cptlfs_info *lfs) return atomic_read(&lfs->state) == OTX2_CPTLF_STARTED; } +static inline void otx2_cptlf_set_dev_info(struct otx2_cptlfs_info *lfs, + struct pci_dev *pdev, + void __iomem *reg_base, + struct otx2_mbox *mbox, + int blkaddr) +{ + lfs->pdev = pdev; + lfs->reg_base = reg_base; + lfs->mbox = mbox; + lfs->blkaddr = blkaddr; +} + int otx2_cptlf_init(struct otx2_cptlfs_info *lfs, u8 eng_grp_msk, int pri, int lfs_num); void otx2_cptlf_shutdown(struct otx2_cptlfs_info *lfs); diff --git a/drivers/crypto/marvell/octeontx2/otx2_cptpf.h b/drivers/crypto/marvell/octeontx2/otx2_cptpf.h index 936174b012e8e54553a7cd6767f70938bbc90e87..a209ec5af381f1484feb3381764bd69bb93e6df4 100644 --- a/drivers/crypto/marvell/octeontx2/otx2_cptpf.h +++ b/drivers/crypto/marvell/octeontx2/otx2_cptpf.h @@ -31,6 +31,7 @@ struct otx2_cptpf_dev { struct otx2_cptvf_info vf[OTX2_CPT_MAX_VFS_NUM]; struct otx2_cpt_eng_grps eng_grps;/* Engine groups information */ struct otx2_cptlfs_info lfs; /* CPT LFs attached to this PF */ + struct otx2_cptlfs_info cpt1_lfs; /* CPT1 LFs attached to this PF */ /* HW capabilities for each engine type */ union otx2_cpt_eng_caps eng_caps[OTX2_CPT_MAX_ENG_TYPES]; bool is_eng_caps_discovered; @@ -40,6 +41,9 @@ struct otx2_cptpf_dev { struct work_struct afpf_mbox_work; struct workqueue_struct *afpf_mbox_wq; + struct otx2_mbox afpf_mbox_up; + struct work_struct afpf_mbox_up_work; + /* VF <=> PF mbox */ struct otx2_mbox vfpf_mbox; struct workqueue_struct *vfpf_mbox_wq; @@ -52,8 +56,10 @@ struct otx2_cptpf_dev { u8 pf_id; /* RVU PF number */ u8 max_vfs; /* Maximum number of VFs supported by CPT */ u8 enabled_vfs; /* Number of enabled VFs */ + u8 sso_pf_func_ovrd; /* SSO PF_FUNC override bit */ u8 kvf_limits; /* Kernel crypto limits */ bool has_cpt1; + u8 rsrc_req_blkaddr; /* Devlink */ struct devlink *dl; @@ -61,6 +67,7 @@ struct otx2_cptpf_dev { irqreturn_t otx2_cptpf_afpf_mbox_intr(int irq, void *arg); void otx2_cptpf_afpf_mbox_handler(struct work_struct *work); +void otx2_cptpf_afpf_mbox_up_handler(struct work_struct *work); irqreturn_t otx2_cptpf_vfpf_mbox_intr(int irq, void *arg); void otx2_cptpf_vfpf_mbox_handler(struct work_struct *work); diff --git a/drivers/crypto/marvell/octeontx2/otx2_cptpf_main.c b/drivers/crypto/marvell/octeontx2/otx2_cptpf_main.c index ddf6e913c1c45902e5d1e5bdf116f11d4c2e3b9b..e34223daa327af119bd479d828a50de1c912ce7e 100644 --- a/drivers/crypto/marvell/octeontx2/otx2_cptpf_main.c +++ b/drivers/crypto/marvell/octeontx2/otx2_cptpf_main.c @@ -13,6 +13,8 @@ #define OTX2_CPT_DRV_NAME "rvu_cptpf" #define OTX2_CPT_DRV_STRING "Marvell RVU CPT Physical Function Driver" +#define CPT_UC_RID_CN9K_B0 1 + static void cptpf_enable_vfpf_mbox_intr(struct otx2_cptpf_dev *cptpf, int num_vfs) { @@ -357,9 +359,9 @@ static int cptpf_vfpf_mbox_init(struct otx2_cptpf_dev *cptpf, int num_vfs) u64 vfpf_mbox_base; int err, i; - cptpf->vfpf_mbox_wq = alloc_workqueue("cpt_vfpf_mailbox", - WQ_UNBOUND | WQ_HIGHPRI | - WQ_MEM_RECLAIM, 1); + cptpf->vfpf_mbox_wq = + alloc_ordered_workqueue("cpt_vfpf_mailbox", + WQ_HIGHPRI | WQ_MEM_RECLAIM); if (!cptpf->vfpf_mbox_wq) return -ENOMEM; @@ -453,9 +455,9 @@ static int cptpf_afpf_mbox_init(struct otx2_cptpf_dev *cptpf) resource_size_t offset; int err; - cptpf->afpf_mbox_wq = alloc_workqueue("cpt_afpf_mailbox", - WQ_UNBOUND | WQ_HIGHPRI | - WQ_MEM_RECLAIM, 1); + cptpf->afpf_mbox_wq = + alloc_ordered_workqueue("cpt_afpf_mailbox", + WQ_HIGHPRI | WQ_MEM_RECLAIM); if (!cptpf->afpf_mbox_wq) return -ENOMEM; @@ -473,10 +475,19 @@ static int cptpf_afpf_mbox_init(struct otx2_cptpf_dev *cptpf) if (err) goto error; + err = otx2_mbox_init(&cptpf->afpf_mbox_up, cptpf->afpf_mbox_base, + pdev, cptpf->reg_base, MBOX_DIR_PFAF_UP, 1); + if (err) + goto mbox_cleanup; + INIT_WORK(&cptpf->afpf_mbox_work, otx2_cptpf_afpf_mbox_handler); + INIT_WORK(&cptpf->afpf_mbox_up_work, otx2_cptpf_afpf_mbox_up_handler); mutex_init(&cptpf->lock); + return 0; +mbox_cleanup: + otx2_mbox_destroy(&cptpf->afpf_mbox); error: destroy_workqueue(cptpf->afpf_mbox_wq); return err; @@ -486,6 +497,33 @@ static void cptpf_afpf_mbox_destroy(struct otx2_cptpf_dev *cptpf) { destroy_workqueue(cptpf->afpf_mbox_wq); otx2_mbox_destroy(&cptpf->afpf_mbox); + otx2_mbox_destroy(&cptpf->afpf_mbox_up); +} + +static ssize_t sso_pf_func_ovrd_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct otx2_cptpf_dev *cptpf = dev_get_drvdata(dev); + + return sprintf(buf, "%d\n", cptpf->sso_pf_func_ovrd); +} + +static ssize_t sso_pf_func_ovrd_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct otx2_cptpf_dev *cptpf = dev_get_drvdata(dev); + u8 sso_pf_func_ovrd; + + if (!(cptpf->pdev->revision == CPT_UC_RID_CN9K_B0)) + return count; + + if (kstrtou8(buf, 0, &sso_pf_func_ovrd)) + return -EINVAL; + + cptpf->sso_pf_func_ovrd = sso_pf_func_ovrd; + + return count; } static ssize_t kvf_limits_show(struct device *dev, @@ -518,8 +556,11 @@ static ssize_t kvf_limits_store(struct device *dev, } static DEVICE_ATTR_RW(kvf_limits); +static DEVICE_ATTR_RW(sso_pf_func_ovrd); + static struct attribute *cptpf_attrs[] = { &dev_attr_kvf_limits.attr, + &dev_attr_sso_pf_func_ovrd.attr, NULL }; diff --git a/drivers/crypto/marvell/octeontx2/otx2_cptpf_mbox.c b/drivers/crypto/marvell/octeontx2/otx2_cptpf_mbox.c index dee0aa60b698524ae2d672affdc8e6eba8ceca35..480b3720f15ab4423f03160e8454380ed129cc41 100644 --- a/drivers/crypto/marvell/octeontx2/otx2_cptpf_mbox.c +++ b/drivers/crypto/marvell/octeontx2/otx2_cptpf_mbox.c @@ -5,6 +5,20 @@ #include "otx2_cptpf.h" #include "rvu_reg.h" +/* Fastpath ipsec opcode with inplace processing */ +#define CPT_INLINE_RX_OPCODE (0x26 | (1 << 6)) +#define CN10K_CPT_INLINE_RX_OPCODE (0x29 | (1 << 6)) + +#define cpt_inline_rx_opcode(pdev) \ +({ \ + u8 opcode; \ + if (is_dev_otx2(pdev)) \ + opcode = CPT_INLINE_RX_OPCODE; \ + else \ + opcode = CN10K_CPT_INLINE_RX_OPCODE; \ + (opcode); \ +}) + /* * CPT PF driver version, It will be incremented by 1 for every feature * addition in CPT mailbox messages. @@ -112,6 +126,139 @@ static int handle_msg_kvf_limits(struct otx2_cptpf_dev *cptpf, return 0; } +static int send_inline_ipsec_inbound_msg(struct otx2_cptpf_dev *cptpf, + int sso_pf_func, u8 slot) +{ + struct cpt_inline_ipsec_cfg_msg *req; + struct pci_dev *pdev = cptpf->pdev; + + req = (struct cpt_inline_ipsec_cfg_msg *) + otx2_mbox_alloc_msg_rsp(&cptpf->afpf_mbox, 0, + sizeof(*req), sizeof(struct msg_rsp)); + if (req == NULL) { + dev_err(&pdev->dev, "RVU MBOX failed to get message.\n"); + return -EFAULT; + } + memset(req, 0, sizeof(*req)); + req->hdr.id = MBOX_MSG_CPT_INLINE_IPSEC_CFG; + req->hdr.sig = OTX2_MBOX_REQ_SIG; + req->hdr.pcifunc = OTX2_CPT_RVU_PFFUNC(cptpf->pf_id, 0); + req->dir = CPT_INLINE_INBOUND; + req->slot = slot; + req->sso_pf_func_ovrd = cptpf->sso_pf_func_ovrd; + req->sso_pf_func = sso_pf_func; + req->enable = 1; + + return otx2_cpt_send_mbox_msg(&cptpf->afpf_mbox, pdev); +} + +static int rx_inline_ipsec_lf_cfg(struct otx2_cptpf_dev *cptpf, u8 egrp, + struct otx2_cpt_rx_inline_lf_cfg *req) +{ + struct nix_inline_ipsec_cfg *nix_req; + struct pci_dev *pdev = cptpf->pdev; + int ret; + + nix_req = (struct nix_inline_ipsec_cfg *) + otx2_mbox_alloc_msg_rsp(&cptpf->afpf_mbox, 0, + sizeof(*nix_req), + sizeof(struct msg_rsp)); + if (nix_req == NULL) { + dev_err(&pdev->dev, "RVU MBOX failed to get message.\n"); + return -EFAULT; + } + memset(nix_req, 0, sizeof(*nix_req)); + nix_req->hdr.id = MBOX_MSG_NIX_INLINE_IPSEC_CFG; + nix_req->hdr.sig = OTX2_MBOX_REQ_SIG; + nix_req->enable = 1; + if (!req->credit || req->credit > OTX2_CPT_INST_QLEN_MSGS) + nix_req->cpt_credit = OTX2_CPT_INST_QLEN_MSGS - 1; + else + nix_req->cpt_credit = req->credit - 1; + nix_req->gen_cfg.egrp = egrp; + if (req->opcode) + nix_req->gen_cfg.opcode = req->opcode; + else + nix_req->gen_cfg.opcode = cpt_inline_rx_opcode(pdev); + nix_req->gen_cfg.param1 = req->param1; + nix_req->gen_cfg.param2 = req->param2; + nix_req->inst_qsel.cpt_pf_func = OTX2_CPT_RVU_PFFUNC(cptpf->pf_id, 0); + nix_req->inst_qsel.cpt_slot = 0; + ret = otx2_cpt_send_mbox_msg(&cptpf->afpf_mbox, pdev); + if (ret) + return ret; + + if (cptpf->has_cpt1) { + ret = send_inline_ipsec_inbound_msg(cptpf, req->sso_pf_func, 1); + if (ret) + return ret; + } + + return send_inline_ipsec_inbound_msg(cptpf, req->sso_pf_func, 0); +} + +static int handle_msg_rx_inline_ipsec_lf_cfg(struct otx2_cptpf_dev *cptpf, + struct mbox_msghdr *req) +{ + struct otx2_cpt_rx_inline_lf_cfg *cfg_req; + u8 egrp; + int ret; + + cfg_req = (struct otx2_cpt_rx_inline_lf_cfg *)req; + if (cptpf->lfs.lfs_num) { + dev_err(&cptpf->pdev->dev, + "LF is already configured for RX inline ipsec.\n"); + return -EEXIST; + } + /* + * Allow LFs to execute requests destined to only grp IE_TYPES and + * set queue priority of each LF to high + */ + egrp = otx2_cpt_get_eng_grp(&cptpf->eng_grps, OTX2_CPT_IE_TYPES); + if (egrp == OTX2_CPT_INVALID_CRYPTO_ENG_GRP) { + dev_err(&cptpf->pdev->dev, + "Engine group for inline ipsec is not available\n"); + return -ENOENT; + } + + otx2_cptlf_set_dev_info(&cptpf->lfs, cptpf->pdev, cptpf->reg_base, + &cptpf->afpf_mbox, BLKADDR_CPT0); + ret = otx2_cptlf_init(&cptpf->lfs, 1 << egrp, OTX2_CPT_QUEUE_HI_PRIO, + 1); + if (ret) { + dev_err(&cptpf->pdev->dev, + "LF configuration failed for RX inline ipsec.\n"); + return ret; + } + + if (cptpf->has_cpt1) { + cptpf->rsrc_req_blkaddr = BLKADDR_CPT1; + otx2_cptlf_set_dev_info(&cptpf->cpt1_lfs, cptpf->pdev, + cptpf->reg_base, &cptpf->afpf_mbox, + BLKADDR_CPT1); + ret = otx2_cptlf_init(&cptpf->cpt1_lfs, 1 << egrp, + OTX2_CPT_QUEUE_HI_PRIO, 1); + if (ret) { + dev_err(&cptpf->pdev->dev, + "LF configuration failed for RX inline ipsec.\n"); + goto lf_cleanup; + } + cptpf->rsrc_req_blkaddr = 0; + } + + ret = rx_inline_ipsec_lf_cfg(cptpf, egrp, cfg_req); + if (ret) + goto lf1_cleanup; + + return 0; + +lf1_cleanup: + otx2_cptlf_shutdown(&cptpf->cpt1_lfs); +lf_cleanup: + otx2_cptlf_shutdown(&cptpf->lfs); + return ret; +} + static int cptpf_handle_vf_req(struct otx2_cptpf_dev *cptpf, struct otx2_cptvf_info *vf, struct mbox_msghdr *req, int size) @@ -132,6 +279,10 @@ static int cptpf_handle_vf_req(struct otx2_cptpf_dev *cptpf, case MBOX_MSG_GET_KVF_LIMITS: err = handle_msg_kvf_limits(cptpf, vf, req); break; + case MBOX_MSG_RX_INLINE_IPSEC_LF_CFG: + err = handle_msg_rx_inline_ipsec_lf_cfg(cptpf, req); + break; + default: err = forward_to_af(cptpf, vf, req, size); break; @@ -224,14 +375,28 @@ void otx2_cptpf_vfpf_mbox_handler(struct work_struct *work) irqreturn_t otx2_cptpf_afpf_mbox_intr(int __always_unused irq, void *arg) { struct otx2_cptpf_dev *cptpf = arg; + struct otx2_mbox_dev *mdev; + struct otx2_mbox *mbox; + struct mbox_hdr *hdr; u64 intr; /* Read the interrupt bits */ intr = otx2_cpt_read64(cptpf->reg_base, BLKADDR_RVUM, 0, RVU_PF_INT); if (intr & 0x1ULL) { - /* Schedule work queue function to process the MBOX request */ - queue_work(cptpf->afpf_mbox_wq, &cptpf->afpf_mbox_work); + mbox = &cptpf->afpf_mbox; + mdev = &mbox->dev[0]; + hdr = mdev->mbase + mbox->rx_start; + if (hdr->num_msgs) + /* Schedule work queue function to process the MBOX request */ + queue_work(cptpf->afpf_mbox_wq, &cptpf->afpf_mbox_work); + + mbox = &cptpf->afpf_mbox_up; + mdev = &mbox->dev[0]; + hdr = mdev->mbase + mbox->rx_start; + if (hdr->num_msgs) + /* Schedule work queue function to process the MBOX request */ + queue_work(cptpf->afpf_mbox_wq, &cptpf->afpf_mbox_up_work); /* Clear and ack the interrupt */ otx2_cpt_write64(cptpf->reg_base, BLKADDR_RVUM, 0, RVU_PF_INT, 0x1ULL); @@ -242,6 +407,7 @@ irqreturn_t otx2_cptpf_afpf_mbox_intr(int __always_unused irq, void *arg) static void process_afpf_mbox_msg(struct otx2_cptpf_dev *cptpf, struct mbox_msghdr *msg) { + struct otx2_cptlfs_info *lfs = &cptpf->lfs; struct device *dev = &cptpf->pdev->dev; struct cpt_rd_wr_reg_msg *rsp_rd_wr; @@ -254,6 +420,8 @@ static void process_afpf_mbox_msg(struct otx2_cptpf_dev *cptpf, msg->sig, msg->id); return; } + if (cptpf->rsrc_req_blkaddr == BLKADDR_CPT1) + lfs = &cptpf->cpt1_lfs; switch (msg->id) { case MBOX_MSG_READY: @@ -273,11 +441,14 @@ static void process_afpf_mbox_msg(struct otx2_cptpf_dev *cptpf, break; case MBOX_MSG_ATTACH_RESOURCES: if (!msg->rc) - cptpf->lfs.are_lfs_attached = 1; + lfs->are_lfs_attached = 1; break; case MBOX_MSG_DETACH_RESOURCES: if (!msg->rc) - cptpf->lfs.are_lfs_attached = 0; + lfs->are_lfs_attached = 0; + break; + case MBOX_MSG_CPT_INLINE_IPSEC_CFG: + case MBOX_MSG_NIX_INLINE_IPSEC_CFG: break; default: @@ -367,3 +538,71 @@ void otx2_cptpf_afpf_mbox_handler(struct work_struct *work) } otx2_mbox_reset(afpf_mbox, 0); } + +static void handle_msg_cpt_inst_lmtst(struct otx2_cptpf_dev *cptpf, + struct mbox_msghdr *msg) +{ + struct cpt_inst_lmtst_req *req = (struct cpt_inst_lmtst_req *)msg; + struct otx2_cptlfs_info *lfs = &cptpf->lfs; + struct msg_rsp *rsp; + + if (cptpf->lfs.lfs_num) + lfs->ops->send_cmd((union otx2_cpt_inst_s *)req->inst, 1, + &lfs->lf[0]); + + rsp = (struct msg_rsp *)otx2_mbox_alloc_msg(&cptpf->afpf_mbox_up, 0, + sizeof(*rsp)); + if (!rsp) + return; + + rsp->hdr.id = msg->id; + rsp->hdr.sig = OTX2_MBOX_RSP_SIG; + rsp->hdr.pcifunc = 0; + rsp->hdr.rc = 0; +} + +static void process_afpf_mbox_up_msg(struct otx2_cptpf_dev *cptpf, + struct mbox_msghdr *msg) +{ + if (msg->id >= MBOX_MSG_MAX) { + dev_err(&cptpf->pdev->dev, + "MBOX msg with unknown ID %d\n", msg->id); + return; + } + + switch (msg->id) { + case MBOX_MSG_CPT_INST_LMTST: + handle_msg_cpt_inst_lmtst(cptpf, msg); + break; + default: + otx2_reply_invalid_msg(&cptpf->afpf_mbox_up, 0, 0, msg->id); + } +} + +void otx2_cptpf_afpf_mbox_up_handler(struct work_struct *work) +{ + struct otx2_cptpf_dev *cptpf; + struct otx2_mbox_dev *mdev; + struct mbox_hdr *rsp_hdr; + struct mbox_msghdr *msg; + struct otx2_mbox *mbox; + int offset, i; + + cptpf = container_of(work, struct otx2_cptpf_dev, afpf_mbox_up_work); + mbox = &cptpf->afpf_mbox_up; + mdev = &mbox->dev[0]; + /* Sync mbox data into memory */ + smp_wmb(); + + rsp_hdr = (struct mbox_hdr *)(mdev->mbase + mbox->rx_start); + offset = mbox->rx_start + ALIGN(sizeof(*rsp_hdr), MBOX_MSG_ALIGN); + + for (i = 0; i < rsp_hdr->num_msgs; i++) { + msg = (struct mbox_msghdr *)(mdev->mbase + offset); + + process_afpf_mbox_up_msg(cptpf, msg); + + offset = mbox->rx_start + msg->next_msgoff; + } + otx2_mbox_msg_send(mbox, 0); +} diff --git a/drivers/crypto/marvell/octeontx2/otx2_cptpf_ucode.c b/drivers/crypto/marvell/octeontx2/otx2_cptpf_ucode.c index 1577986677f60d25f4170d56a8f5b140d215b98b..1958b797a42100517c35e6e581903fad885231d2 100644 --- a/drivers/crypto/marvell/octeontx2/otx2_cptpf_ucode.c +++ b/drivers/crypto/marvell/octeontx2/otx2_cptpf_ucode.c @@ -1504,11 +1504,9 @@ int otx2_cpt_discover_eng_capabilities(struct otx2_cptpf_dev *cptpf) if (ret) goto delete_grps; - lfs->pdev = pdev; - lfs->reg_base = cptpf->reg_base; - lfs->mbox = &cptpf->afpf_mbox; - lfs->blkaddr = BLKADDR_CPT0; - ret = otx2_cptlf_init(&cptpf->lfs, OTX2_CPT_ALL_ENG_GRPS_MASK, + otx2_cptlf_set_dev_info(lfs, cptpf->pdev, cptpf->reg_base, + &cptpf->afpf_mbox, BLKADDR_CPT0); + ret = otx2_cptlf_init(lfs, OTX2_CPT_ALL_ENG_GRPS_MASK, OTX2_CPT_QUEUE_HI_PRIO, 1); if (ret) goto delete_grps; @@ -1562,7 +1560,7 @@ int otx2_cpt_discover_eng_capabilities(struct otx2_cptpf_dev *cptpf) free_result: kfree(result); lf_cleanup: - otx2_cptlf_shutdown(&cptpf->lfs); + otx2_cptlf_shutdown(lfs); delete_grps: delete_engine_grps(pdev, &cptpf->eng_grps); diff --git a/drivers/crypto/marvell/octeontx2/otx2_cptvf.h b/drivers/crypto/marvell/octeontx2/otx2_cptvf.h index 4207e2236903ee49c2982356b02bd90dff66158e..994291e90da1241035369258c11b813ef8ff8293 100644 --- a/drivers/crypto/marvell/octeontx2/otx2_cptvf.h +++ b/drivers/crypto/marvell/octeontx2/otx2_cptvf.h @@ -19,6 +19,7 @@ struct otx2_cptvf_dev { struct otx2_mbox pfvf_mbox; struct work_struct pfvf_mbox_work; struct workqueue_struct *pfvf_mbox_wq; + int blkaddr; void *bbuf_base; unsigned long cap_flag; }; diff --git a/drivers/crypto/marvell/octeontx2/otx2_cptvf_main.c b/drivers/crypto/marvell/octeontx2/otx2_cptvf_main.c index 392e9fee05e81c4fff89ca326d7e998542471b56..bac729c885f960fc2893001e842c427098802ef2 100644 --- a/drivers/crypto/marvell/octeontx2/otx2_cptvf_main.c +++ b/drivers/crypto/marvell/octeontx2/otx2_cptvf_main.c @@ -75,9 +75,9 @@ static int cptvf_pfvf_mbox_init(struct otx2_cptvf_dev *cptvf) resource_size_t offset, size; int ret; - cptvf->pfvf_mbox_wq = alloc_workqueue("cpt_pfvf_mailbox", - WQ_UNBOUND | WQ_HIGHPRI | - WQ_MEM_RECLAIM, 1); + cptvf->pfvf_mbox_wq = + alloc_ordered_workqueue("cpt_pfvf_mailbox", + WQ_HIGHPRI | WQ_MEM_RECLAIM); if (!cptvf->pfvf_mbox_wq) return -ENOMEM; @@ -277,12 +277,11 @@ static int cptvf_lf_init(struct otx2_cptvf_dev *cptvf) if (ret) return ret; - lfs->reg_base = cptvf->reg_base; - lfs->pdev = cptvf->pdev; - lfs->mbox = &cptvf->pfvf_mbox; - lfs_num = cptvf->lfs.kvf_limits ? cptvf->lfs.kvf_limits : num_online_cpus(); + + otx2_cptlf_set_dev_info(lfs, cptvf->pdev, cptvf->reg_base, + &cptvf->pfvf_mbox, cptvf->blkaddr); ret = otx2_cptlf_init(lfs, eng_grp_msk, OTX2_CPT_QUEUE_HI_PRIO, lfs_num); if (ret) @@ -380,6 +379,7 @@ static int otx2_cptvf_probe(struct pci_dev *pdev, if (ret) goto destroy_pfvf_mbox; + cptvf->blkaddr = BLKADDR_CPT0; /* Initialize CPT LFs */ ret = cptvf_lf_init(cptvf); if (ret) diff --git a/drivers/crypto/n2_core.c b/drivers/crypto/n2_core.c index 20d0dcd50344b3335448adb83c0ef32c36e5596c..4f6ca229ee5e855ffd1207d4603047158daf67ce 100644 --- a/drivers/crypto/n2_core.c +++ b/drivers/crypto/n2_core.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -1795,11 +1796,9 @@ static int grab_mdesc_irq_props(struct mdesc_handle *mdesc, struct spu_mdesc_info *ip, const char *node_name) { - const unsigned int *reg; - u64 node; + u64 node, reg; - reg = of_get_property(dev->dev.of_node, "reg", NULL); - if (!reg) + if (of_property_read_reg(dev->dev.of_node, 0, ®, NULL) < 0) return -ENODEV; mdesc_for_each_node_by_name(mdesc, node, "virtual-device") { @@ -1810,7 +1809,7 @@ static int grab_mdesc_irq_props(struct mdesc_handle *mdesc, if (!name || strcmp(name, node_name)) continue; chdl = mdesc_get_property(mdesc, node, "cfg-handle", NULL); - if (!chdl || (*chdl != *reg)) + if (!chdl || (*chdl != reg)) continue; ip->cfg_handle = *chdl; return get_irq_props(mdesc, node, ip); diff --git a/drivers/crypto/nx/Makefile b/drivers/crypto/nx/Makefile index d00181a26dd652ee39bcdf6a3c30dd893a754bd3..483cef62acee88098d2125f6e683db5540045562 100644 --- a/drivers/crypto/nx/Makefile +++ b/drivers/crypto/nx/Makefile @@ -1,7 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_CRYPTO_DEV_NX_ENCRYPT) += nx-crypto.o nx-crypto-objs := nx.o \ - nx_debugfs.o \ nx-aes-cbc.o \ nx-aes-ecb.o \ nx-aes-gcm.o \ @@ -11,6 +10,7 @@ nx-crypto-objs := nx.o \ nx-sha256.o \ nx-sha512.o +nx-crypto-$(CONFIG_DEBUG_FS) += nx_debugfs.o obj-$(CONFIG_CRYPTO_DEV_NX_COMPRESS_PSERIES) += nx-compress-pseries.o nx-compress.o obj-$(CONFIG_CRYPTO_DEV_NX_COMPRESS_POWERNV) += nx-compress-powernv.o nx-compress.o nx-compress-objs := nx-842.o diff --git a/drivers/crypto/nx/nx.h b/drivers/crypto/nx/nx.h index c6233173c612ef3d8ab5c861125cedfde4cf7a81..2697baebb6a3543fadab395d236ec6727985324d 100644 --- a/drivers/crypto/nx/nx.h +++ b/drivers/crypto/nx/nx.h @@ -170,8 +170,8 @@ struct nx_sg *nx_walk_and_build(struct nx_sg *, unsigned int, void nx_debugfs_init(struct nx_crypto_driver *); void nx_debugfs_fini(struct nx_crypto_driver *); #else -#define NX_DEBUGFS_INIT(drv) (0) -#define NX_DEBUGFS_FINI(drv) (0) +#define NX_DEBUGFS_INIT(drv) do {} while (0) +#define NX_DEBUGFS_FINI(drv) do {} while (0) #endif #define NX_PAGE_NUM(x) ((u64)(x) & 0xfffffffffffff000ULL) diff --git a/drivers/crypto/sa2ul.h b/drivers/crypto/sa2ul.h index 92bf97232a292e365c84133a76e0f80088c3cfb0..12c17a68d35058a6ce743417c7d919ef3ca09001 100644 --- a/drivers/crypto/sa2ul.h +++ b/drivers/crypto/sa2ul.h @@ -170,7 +170,7 @@ struct sa_tfm_ctx; * the following range, so avoid using it. */ #define SA_UNSAFE_DATA_SZ_MIN 240 -#define SA_UNSAFE_DATA_SZ_MAX 256 +#define SA_UNSAFE_DATA_SZ_MAX 255 struct sa_match_data; diff --git a/drivers/crypto/starfive/Kconfig b/drivers/crypto/starfive/Kconfig new file mode 100644 index 0000000000000000000000000000000000000000..df745fcb09dfccb5946297f0181e7e6b88bedd6e --- /dev/null +++ b/drivers/crypto/starfive/Kconfig @@ -0,0 +1,20 @@ +# +# StarFive crypto drivers configuration +# + +config CRYPTO_DEV_JH7110 + tristate "StarFive JH7110 cryptographic engine driver" + depends on SOC_STARFIVE || AMBA_PL08X || COMPILE_TEST + depends on HAS_DMA + select CRYPTO_ENGINE + select CRYPTO_HMAC + select CRYPTO_SHA256 + select CRYPTO_SHA512 + select CRYPTO_SM3_GENERIC + select CRYPTO_RSA + help + Support for StarFive JH7110 crypto hardware acceleration engine. + This module provides acceleration for public key algo, + skciphers, AEAD and hash functions. + + If you choose 'M' here, this module will be called jh7110-crypto. diff --git a/drivers/crypto/starfive/Makefile b/drivers/crypto/starfive/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..98b01d2f1ccf3b02257133657a080808fb6ef414 --- /dev/null +++ b/drivers/crypto/starfive/Makefile @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 + +obj-$(CONFIG_CRYPTO_DEV_JH7110) += jh7110-crypto.o +jh7110-crypto-objs := jh7110-cryp.o jh7110-hash.o jh7110-rsa.o diff --git a/drivers/crypto/starfive/jh7110-cryp.c b/drivers/crypto/starfive/jh7110-cryp.c new file mode 100644 index 0000000000000000000000000000000000000000..cc43556b6c8052e8896e29edf82015ca8bddc451 --- /dev/null +++ b/drivers/crypto/starfive/jh7110-cryp.c @@ -0,0 +1,258 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Cryptographic API. + * + * Support for StarFive hardware cryptographic engine. + * Copyright (c) 2022 StarFive Technology + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "jh7110-cryp.h" + +#define DRIVER_NAME "jh7110-crypto" + +struct starfive_dev_list { + struct list_head dev_list; + spinlock_t lock; /* protect dev_list */ +}; + +static struct starfive_dev_list dev_list = { + .dev_list = LIST_HEAD_INIT(dev_list.dev_list), + .lock = __SPIN_LOCK_UNLOCKED(dev_list.lock), +}; + +struct starfive_cryp_dev *starfive_cryp_find_dev(struct starfive_cryp_ctx *ctx) +{ + struct starfive_cryp_dev *cryp = NULL, *tmp; + + spin_lock_bh(&dev_list.lock); + if (!ctx->cryp) { + list_for_each_entry(tmp, &dev_list.dev_list, list) { + cryp = tmp; + break; + } + ctx->cryp = cryp; + } else { + cryp = ctx->cryp; + } + + spin_unlock_bh(&dev_list.lock); + + return cryp; +} + +static int starfive_dma_init(struct starfive_cryp_dev *cryp) +{ + dma_cap_mask_t mask; + + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE, mask); + + cryp->tx = dma_request_chan(cryp->dev, "tx"); + if (IS_ERR(cryp->tx)) + return dev_err_probe(cryp->dev, PTR_ERR(cryp->tx), + "Error requesting tx dma channel.\n"); + + cryp->rx = dma_request_chan(cryp->dev, "rx"); + if (IS_ERR(cryp->rx)) { + dma_release_channel(cryp->tx); + return dev_err_probe(cryp->dev, PTR_ERR(cryp->rx), + "Error requesting rx dma channel.\n"); + } + + return 0; +} + +static void starfive_dma_cleanup(struct starfive_cryp_dev *cryp) +{ + dma_release_channel(cryp->tx); + dma_release_channel(cryp->rx); +} + +static irqreturn_t starfive_cryp_irq(int irq, void *priv) +{ + u32 status; + struct starfive_cryp_dev *cryp = (struct starfive_cryp_dev *)priv; + + status = readl(cryp->base + STARFIVE_IE_FLAG_OFFSET); + if (status & STARFIVE_IE_FLAG_HASH_DONE) { + status = readl(cryp->base + STARFIVE_IE_MASK_OFFSET); + status |= STARFIVE_IE_MASK_HASH_DONE; + writel(status, cryp->base + STARFIVE_IE_MASK_OFFSET); + tasklet_schedule(&cryp->hash_done); + } + + if (status & STARFIVE_IE_FLAG_PKA_DONE) { + status = readl(cryp->base + STARFIVE_IE_MASK_OFFSET); + status |= STARFIVE_IE_MASK_PKA_DONE; + writel(status, cryp->base + STARFIVE_IE_MASK_OFFSET); + complete(&cryp->pka_done); + } + + return IRQ_HANDLED; +} + +static int starfive_cryp_probe(struct platform_device *pdev) +{ + struct starfive_cryp_dev *cryp; + struct resource *res; + int irq; + int ret; + + cryp = devm_kzalloc(&pdev->dev, sizeof(*cryp), GFP_KERNEL); + if (!cryp) + return -ENOMEM; + + platform_set_drvdata(pdev, cryp); + cryp->dev = &pdev->dev; + + cryp->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); + if (IS_ERR(cryp->base)) + return dev_err_probe(&pdev->dev, PTR_ERR(cryp->base), + "Error remapping memory for platform device\n"); + + tasklet_init(&cryp->hash_done, starfive_hash_done_task, (unsigned long)cryp); + + cryp->phys_base = res->start; + cryp->dma_maxburst = 32; + + cryp->hclk = devm_clk_get(&pdev->dev, "hclk"); + if (IS_ERR(cryp->hclk)) + return dev_err_probe(&pdev->dev, PTR_ERR(cryp->hclk), + "Error getting hardware reference clock\n"); + + cryp->ahb = devm_clk_get(&pdev->dev, "ahb"); + if (IS_ERR(cryp->ahb)) + return dev_err_probe(&pdev->dev, PTR_ERR(cryp->ahb), + "Error getting ahb reference clock\n"); + + cryp->rst = devm_reset_control_get_shared(cryp->dev, NULL); + if (IS_ERR(cryp->rst)) + return dev_err_probe(&pdev->dev, PTR_ERR(cryp->rst), + "Error getting hardware reset line\n"); + + init_completion(&cryp->pka_done); + + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return irq; + + ret = devm_request_irq(&pdev->dev, irq, starfive_cryp_irq, 0, pdev->name, + (void *)cryp); + if (ret) + return dev_err_probe(&pdev->dev, irq, + "Failed to register interrupt handler\n"); + + clk_prepare_enable(cryp->hclk); + clk_prepare_enable(cryp->ahb); + reset_control_deassert(cryp->rst); + + spin_lock(&dev_list.lock); + list_add(&cryp->list, &dev_list.dev_list); + spin_unlock(&dev_list.lock); + + ret = starfive_dma_init(cryp); + if (ret) { + if (ret == -EPROBE_DEFER) + goto err_probe_defer; + else + goto err_dma_init; + } + + /* Initialize crypto engine */ + cryp->engine = crypto_engine_alloc_init(&pdev->dev, 1); + if (!cryp->engine) { + ret = -ENOMEM; + goto err_engine; + } + + ret = crypto_engine_start(cryp->engine); + if (ret) + goto err_engine_start; + + ret = starfive_hash_register_algs(); + if (ret) + goto err_algs_hash; + + ret = starfive_rsa_register_algs(); + if (ret) + goto err_algs_rsa; + + return 0; + +err_algs_rsa: + starfive_hash_unregister_algs(); +err_algs_hash: + crypto_engine_stop(cryp->engine); +err_engine_start: + crypto_engine_exit(cryp->engine); +err_engine: + starfive_dma_cleanup(cryp); +err_dma_init: + spin_lock(&dev_list.lock); + list_del(&cryp->list); + spin_unlock(&dev_list.lock); + + clk_disable_unprepare(cryp->hclk); + clk_disable_unprepare(cryp->ahb); + reset_control_assert(cryp->rst); + + tasklet_kill(&cryp->hash_done); +err_probe_defer: + return ret; +} + +static int starfive_cryp_remove(struct platform_device *pdev) +{ + struct starfive_cryp_dev *cryp = platform_get_drvdata(pdev); + + starfive_hash_unregister_algs(); + starfive_rsa_unregister_algs(); + + tasklet_kill(&cryp->hash_done); + + crypto_engine_stop(cryp->engine); + crypto_engine_exit(cryp->engine); + + starfive_dma_cleanup(cryp); + + spin_lock(&dev_list.lock); + list_del(&cryp->list); + spin_unlock(&dev_list.lock); + + clk_disable_unprepare(cryp->hclk); + clk_disable_unprepare(cryp->ahb); + reset_control_assert(cryp->rst); + + return 0; +} + +static const struct of_device_id starfive_dt_ids[] __maybe_unused = { + { .compatible = "starfive,jh7110-crypto", .data = NULL}, + {}, +}; +MODULE_DEVICE_TABLE(of, starfive_dt_ids); + +static struct platform_driver starfive_cryp_driver = { + .probe = starfive_cryp_probe, + .remove = starfive_cryp_remove, + .driver = { + .name = DRIVER_NAME, + .of_match_table = starfive_dt_ids, + }, +}; + +module_platform_driver(starfive_cryp_driver); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("StarFive JH7110 Cryptographic Module"); diff --git a/drivers/crypto/starfive/jh7110-cryp.h b/drivers/crypto/starfive/jh7110-cryp.h new file mode 100644 index 0000000000000000000000000000000000000000..0cdcffc0d7d427211c1902392ce31e5016c0e1b0 --- /dev/null +++ b/drivers/crypto/starfive/jh7110-cryp.h @@ -0,0 +1,172 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __STARFIVE_STR_H__ +#define __STARFIVE_STR_H__ + +#include +#include +#include + +#include +#include +#include + +#define STARFIVE_ALG_CR_OFFSET 0x0 +#define STARFIVE_ALG_FIFO_OFFSET 0x4 +#define STARFIVE_IE_MASK_OFFSET 0x8 +#define STARFIVE_IE_FLAG_OFFSET 0xc +#define STARFIVE_DMA_IN_LEN_OFFSET 0x10 +#define STARFIVE_DMA_OUT_LEN_OFFSET 0x14 + +#define STARFIVE_IE_MASK_HASH_DONE 0x4 +#define STARFIVE_IE_MASK_PKA_DONE 0x8 +#define STARFIVE_IE_FLAG_HASH_DONE 0x4 +#define STARFIVE_IE_FLAG_PKA_DONE 0x8 + +#define STARFIVE_MSG_BUFFER_SIZE SZ_16K +#define MAX_KEY_SIZE SHA512_BLOCK_SIZE + +union starfive_hash_csr { + u32 v; + struct { + u32 start :1; + u32 reset :1; + u32 ie :1; + u32 firstb :1; +#define STARFIVE_HASH_SM3 0x0 +#define STARFIVE_HASH_SHA224 0x3 +#define STARFIVE_HASH_SHA256 0x4 +#define STARFIVE_HASH_SHA384 0x5 +#define STARFIVE_HASH_SHA512 0x6 +#define STARFIVE_HASH_MODE_MASK 0x7 + u32 mode :3; + u32 rsvd_1 :1; + u32 final :1; + u32 rsvd_2 :2; +#define STARFIVE_HASH_HMAC_FLAGS 0x800 + u32 hmac :1; + u32 rsvd_3 :1; +#define STARFIVE_HASH_KEY_DONE BIT(13) + u32 key_done :1; + u32 key_flag :1; + u32 hmac_done :1; +#define STARFIVE_HASH_BUSY BIT(16) + u32 busy :1; + u32 hashdone :1; + u32 rsvd_4 :14; + }; +}; + +union starfive_pka_cacr { + u32 v; + struct { + u32 start :1; + u32 reset :1; + u32 ie :1; + u32 rsvd_0 :1; + u32 fifo_mode :1; + u32 not_r2 :1; + u32 ecc_sub :1; + u32 pre_expf :1; + u32 cmd :4; + u32 rsvd_1 :1; + u32 ctrl_dummy :1; + u32 ctrl_false :1; + u32 cln_done :1; + u32 opsize :6; + u32 rsvd_2 :2; + u32 exposize :6; + u32 rsvd_3 :1; + u32 bigendian :1; + }; +}; + +struct starfive_rsa_key { + u8 *n; + u8 *e; + u8 *d; + int e_bitlen; + int d_bitlen; + int bitlen; + size_t key_sz; +}; + +union starfive_alg_cr { + u32 v; + struct { + u32 start :1; + u32 aes_dma_en :1; + u32 rsvd_0 :1; + u32 hash_dma_en :1; + u32 alg_done :1; + u32 rsvd_1 :3; + u32 clear :1; + u32 rsvd_2 :23; + }; +}; + +struct starfive_cryp_ctx { + struct crypto_engine_ctx enginectx; + struct starfive_cryp_dev *cryp; + struct starfive_cryp_request_ctx *rctx; + + unsigned int hash_mode; + u8 key[MAX_KEY_SIZE]; + int keylen; + bool is_hmac; + struct starfive_rsa_key rsa_key; + struct crypto_akcipher *akcipher_fbk; + struct crypto_ahash *ahash_fbk; +}; + +struct starfive_cryp_dev { + struct list_head list; + struct device *dev; + struct clk *hclk; + struct clk *ahb; + struct reset_control *rst; + + void __iomem *base; + phys_addr_t phys_base; + + u32 dma_maxburst; + struct dma_chan *tx; + struct dma_chan *rx; + struct dma_slave_config cfg_in; + struct dma_slave_config cfg_out; + struct crypto_engine *engine; + struct tasklet_struct hash_done; + struct completion pka_done; + int err; + union starfive_alg_cr alg_cr; + union { + struct ahash_request *hreq; + } req; +}; + +struct starfive_cryp_request_ctx { + union { + union starfive_hash_csr hash; + union starfive_pka_cacr pka; + } csr; + + struct scatterlist *in_sg; + struct scatterlist *out_sg; + struct ahash_request ahash_fbk_req; + size_t total; + size_t nents; + unsigned int blksize; + unsigned int digsize; + unsigned long in_sg_len; + u8 rsa_data[] __aligned(sizeof(u32)); +}; + +struct starfive_cryp_dev *starfive_cryp_find_dev(struct starfive_cryp_ctx *ctx); + +int starfive_hash_register_algs(void); +void starfive_hash_unregister_algs(void); + +int starfive_rsa_register_algs(void); +void starfive_rsa_unregister_algs(void); + +void starfive_hash_done_task(unsigned long param); +#endif diff --git a/drivers/crypto/starfive/jh7110-hash.c b/drivers/crypto/starfive/jh7110-hash.c new file mode 100644 index 0000000000000000000000000000000000000000..5064150b8a1ce40ea5067b19590304fe1c9d9fd0 --- /dev/null +++ b/drivers/crypto/starfive/jh7110-hash.c @@ -0,0 +1,899 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Hash function and HMAC support for StarFive driver + * + * Copyright (c) 2022 StarFive Technology + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "jh7110-cryp.h" + +#define STARFIVE_HASH_REGS_OFFSET 0x300 +#define STARFIVE_HASH_SHACSR (STARFIVE_HASH_REGS_OFFSET + 0x0) +#define STARFIVE_HASH_SHAWDR (STARFIVE_HASH_REGS_OFFSET + 0x4) +#define STARFIVE_HASH_SHARDR (STARFIVE_HASH_REGS_OFFSET + 0x8) +#define STARFIVE_HASH_SHAWSR (STARFIVE_HASH_REGS_OFFSET + 0xC) +#define STARFIVE_HASH_SHAWLEN3 (STARFIVE_HASH_REGS_OFFSET + 0x10) +#define STARFIVE_HASH_SHAWLEN2 (STARFIVE_HASH_REGS_OFFSET + 0x14) +#define STARFIVE_HASH_SHAWLEN1 (STARFIVE_HASH_REGS_OFFSET + 0x18) +#define STARFIVE_HASH_SHAWLEN0 (STARFIVE_HASH_REGS_OFFSET + 0x1C) +#define STARFIVE_HASH_SHAWKR (STARFIVE_HASH_REGS_OFFSET + 0x20) +#define STARFIVE_HASH_SHAWKLEN (STARFIVE_HASH_REGS_OFFSET + 0x24) + +#define STARFIVE_HASH_BUFLEN SHA512_BLOCK_SIZE +#define STARFIVE_HASH_RESET 0x2 + +static inline int starfive_hash_wait_busy(struct starfive_cryp_ctx *ctx) +{ + struct starfive_cryp_dev *cryp = ctx->cryp; + u32 status; + + return readl_relaxed_poll_timeout(cryp->base + STARFIVE_HASH_SHACSR, status, + !(status & STARFIVE_HASH_BUSY), 10, 100000); +} + +static inline int starfive_hash_wait_key_done(struct starfive_cryp_ctx *ctx) +{ + struct starfive_cryp_dev *cryp = ctx->cryp; + u32 status; + + return readl_relaxed_poll_timeout(cryp->base + STARFIVE_HASH_SHACSR, status, + (status & STARFIVE_HASH_KEY_DONE), 10, 100000); +} + +static int starfive_hash_hmac_key(struct starfive_cryp_ctx *ctx) +{ + struct starfive_cryp_request_ctx *rctx = ctx->rctx; + struct starfive_cryp_dev *cryp = ctx->cryp; + int klen = ctx->keylen, loop; + unsigned int *key = (unsigned int *)ctx->key; + unsigned char *cl; + + writel(ctx->keylen, cryp->base + STARFIVE_HASH_SHAWKLEN); + + rctx->csr.hash.hmac = 1; + rctx->csr.hash.key_flag = 1; + + writel(rctx->csr.hash.v, cryp->base + STARFIVE_HASH_SHACSR); + + for (loop = 0; loop < klen / sizeof(unsigned int); loop++, key++) + writel(*key, cryp->base + STARFIVE_HASH_SHAWKR); + + if (klen & 0x3) { + cl = (unsigned char *)key; + for (loop = 0; loop < (klen & 0x3); loop++, cl++) + writeb(*cl, cryp->base + STARFIVE_HASH_SHAWKR); + } + + if (starfive_hash_wait_key_done(ctx)) + return dev_err_probe(cryp->dev, -ETIMEDOUT, "starfive_hash_wait_key_done error\n"); + + return 0; +} + +static void starfive_hash_start(void *param) +{ + struct starfive_cryp_ctx *ctx = param; + struct starfive_cryp_request_ctx *rctx = ctx->rctx; + struct starfive_cryp_dev *cryp = ctx->cryp; + union starfive_alg_cr alg_cr; + union starfive_hash_csr csr; + u32 stat; + + dma_unmap_sg(cryp->dev, rctx->in_sg, rctx->in_sg_len, DMA_TO_DEVICE); + + alg_cr.v = 0; + alg_cr.clear = 1; + + writel(alg_cr.v, cryp->base + STARFIVE_ALG_CR_OFFSET); + + csr.v = readl(cryp->base + STARFIVE_HASH_SHACSR); + csr.firstb = 0; + csr.final = 1; + + stat = readl(cryp->base + STARFIVE_IE_MASK_OFFSET); + stat &= ~STARFIVE_IE_MASK_HASH_DONE; + writel(stat, cryp->base + STARFIVE_IE_MASK_OFFSET); + writel(csr.v, cryp->base + STARFIVE_HASH_SHACSR); +} + +static int starfive_hash_xmit_dma(struct starfive_cryp_ctx *ctx) +{ + struct starfive_cryp_request_ctx *rctx = ctx->rctx; + struct starfive_cryp_dev *cryp = ctx->cryp; + struct dma_async_tx_descriptor *in_desc; + union starfive_alg_cr alg_cr; + int total_len; + int ret; + + if (!rctx->total) { + starfive_hash_start(ctx); + return 0; + } + + writel(rctx->total, cryp->base + STARFIVE_DMA_IN_LEN_OFFSET); + + total_len = rctx->total; + total_len = (total_len & 0x3) ? (((total_len >> 2) + 1) << 2) : total_len; + sg_dma_len(rctx->in_sg) = total_len; + + alg_cr.v = 0; + alg_cr.start = 1; + alg_cr.hash_dma_en = 1; + + writel(alg_cr.v, cryp->base + STARFIVE_ALG_CR_OFFSET); + + ret = dma_map_sg(cryp->dev, rctx->in_sg, rctx->in_sg_len, DMA_TO_DEVICE); + if (!ret) + return dev_err_probe(cryp->dev, -EINVAL, "dma_map_sg() error\n"); + + cryp->cfg_in.direction = DMA_MEM_TO_DEV; + cryp->cfg_in.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; + cryp->cfg_in.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; + cryp->cfg_in.src_maxburst = cryp->dma_maxburst; + cryp->cfg_in.dst_maxburst = cryp->dma_maxburst; + cryp->cfg_in.dst_addr = cryp->phys_base + STARFIVE_ALG_FIFO_OFFSET; + + dmaengine_slave_config(cryp->tx, &cryp->cfg_in); + + in_desc = dmaengine_prep_slave_sg(cryp->tx, rctx->in_sg, + ret, DMA_MEM_TO_DEV, + DMA_PREP_INTERRUPT | DMA_CTRL_ACK); + + if (!in_desc) + return -EINVAL; + + in_desc->callback = starfive_hash_start; + in_desc->callback_param = ctx; + + dmaengine_submit(in_desc); + dma_async_issue_pending(cryp->tx); + + return 0; +} + +static int starfive_hash_xmit(struct starfive_cryp_ctx *ctx) +{ + struct starfive_cryp_request_ctx *rctx = ctx->rctx; + struct starfive_cryp_dev *cryp = ctx->cryp; + int ret = 0; + + rctx->csr.hash.v = 0; + rctx->csr.hash.reset = 1; + writel(rctx->csr.hash.v, cryp->base + STARFIVE_HASH_SHACSR); + + if (starfive_hash_wait_busy(ctx)) + return dev_err_probe(cryp->dev, -ETIMEDOUT, "Error resetting engine.\n"); + + rctx->csr.hash.v = 0; + rctx->csr.hash.mode = ctx->hash_mode; + rctx->csr.hash.ie = 1; + + if (ctx->is_hmac) { + ret = starfive_hash_hmac_key(ctx); + if (ret) + return ret; + } else { + rctx->csr.hash.start = 1; + rctx->csr.hash.firstb = 1; + writel(rctx->csr.hash.v, cryp->base + STARFIVE_HASH_SHACSR); + } + + return starfive_hash_xmit_dma(ctx); +} + +static int starfive_hash_copy_hash(struct ahash_request *req) +{ + struct starfive_cryp_request_ctx *rctx = ahash_request_ctx(req); + struct starfive_cryp_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req)); + int count, *data; + int mlen; + + if (!req->result) + return 0; + + mlen = rctx->digsize / sizeof(u32); + data = (u32 *)req->result; + + for (count = 0; count < mlen; count++) + data[count] = readl(ctx->cryp->base + STARFIVE_HASH_SHARDR); + + return 0; +} + +void starfive_hash_done_task(unsigned long param) +{ + struct starfive_cryp_dev *cryp = (struct starfive_cryp_dev *)param; + int err = cryp->err; + + if (!err) + err = starfive_hash_copy_hash(cryp->req.hreq); + + /* Reset to clear hash_done in irq register*/ + writel(STARFIVE_HASH_RESET, cryp->base + STARFIVE_HASH_SHACSR); + + crypto_finalize_hash_request(cryp->engine, cryp->req.hreq, err); +} + +static int starfive_hash_check_aligned(struct scatterlist *sg, size_t total, size_t align) +{ + int len = 0; + + if (!total) + return 0; + + if (!IS_ALIGNED(total, align)) + return -EINVAL; + + while (sg) { + if (!IS_ALIGNED(sg->offset, sizeof(u32))) + return -EINVAL; + + if (!IS_ALIGNED(sg->length, align)) + return -EINVAL; + + len += sg->length; + sg = sg_next(sg); + } + + if (len != total) + return -EINVAL; + + return 0; +} + +static int starfive_hash_one_request(struct crypto_engine *engine, void *areq) +{ + struct ahash_request *req = container_of(areq, struct ahash_request, + base); + struct starfive_cryp_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req)); + struct starfive_cryp_dev *cryp = ctx->cryp; + + if (!cryp) + return -ENODEV; + + return starfive_hash_xmit(ctx); +} + +static int starfive_hash_init(struct ahash_request *req) +{ + struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); + struct starfive_cryp_request_ctx *rctx = ahash_request_ctx(req); + struct starfive_cryp_ctx *ctx = crypto_ahash_ctx(tfm); + + ahash_request_set_tfm(&rctx->ahash_fbk_req, ctx->ahash_fbk); + ahash_request_set_callback(&rctx->ahash_fbk_req, + req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP, + req->base.complete, req->base.data); + + ahash_request_set_crypt(&rctx->ahash_fbk_req, req->src, + req->result, req->nbytes); + + return crypto_ahash_init(&rctx->ahash_fbk_req); +} + +static int starfive_hash_update(struct ahash_request *req) +{ + struct starfive_cryp_request_ctx *rctx = ahash_request_ctx(req); + struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); + struct starfive_cryp_ctx *ctx = crypto_ahash_ctx(tfm); + + ahash_request_set_tfm(&rctx->ahash_fbk_req, ctx->ahash_fbk); + ahash_request_set_callback(&rctx->ahash_fbk_req, + req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP, + req->base.complete, req->base.data); + + ahash_request_set_crypt(&rctx->ahash_fbk_req, req->src, + req->result, req->nbytes); + + return crypto_ahash_update(&rctx->ahash_fbk_req); +} + +static int starfive_hash_final(struct ahash_request *req) +{ + struct starfive_cryp_request_ctx *rctx = ahash_request_ctx(req); + struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); + struct starfive_cryp_ctx *ctx = crypto_ahash_ctx(tfm); + + ahash_request_set_tfm(&rctx->ahash_fbk_req, ctx->ahash_fbk); + ahash_request_set_callback(&rctx->ahash_fbk_req, + req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP, + req->base.complete, req->base.data); + + ahash_request_set_crypt(&rctx->ahash_fbk_req, req->src, + req->result, req->nbytes); + + return crypto_ahash_final(&rctx->ahash_fbk_req); +} + +static int starfive_hash_finup(struct ahash_request *req) +{ + struct starfive_cryp_request_ctx *rctx = ahash_request_ctx(req); + struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); + struct starfive_cryp_ctx *ctx = crypto_ahash_ctx(tfm); + + ahash_request_set_tfm(&rctx->ahash_fbk_req, ctx->ahash_fbk); + ahash_request_set_callback(&rctx->ahash_fbk_req, + req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP, + req->base.complete, req->base.data); + + ahash_request_set_crypt(&rctx->ahash_fbk_req, req->src, + req->result, req->nbytes); + + return crypto_ahash_finup(&rctx->ahash_fbk_req); +} + +static int starfive_hash_digest_fb(struct ahash_request *req) +{ + struct starfive_cryp_request_ctx *rctx = ahash_request_ctx(req); + struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); + struct starfive_cryp_ctx *ctx = crypto_ahash_ctx(tfm); + + ahash_request_set_tfm(&rctx->ahash_fbk_req, ctx->ahash_fbk); + ahash_request_set_callback(&rctx->ahash_fbk_req, req->base.flags, + req->base.complete, req->base.data); + + ahash_request_set_crypt(&rctx->ahash_fbk_req, req->src, + req->result, req->nbytes); + + return crypto_ahash_digest(&rctx->ahash_fbk_req); +} + +static int starfive_hash_digest(struct ahash_request *req) +{ + struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); + struct starfive_cryp_ctx *ctx = crypto_ahash_ctx(tfm); + struct starfive_cryp_request_ctx *rctx = ahash_request_ctx(req); + struct starfive_cryp_dev *cryp = ctx->cryp; + + memset(rctx, 0, sizeof(struct starfive_cryp_request_ctx)); + + cryp->req.hreq = req; + rctx->total = req->nbytes; + rctx->in_sg = req->src; + rctx->blksize = crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm)); + rctx->digsize = crypto_ahash_digestsize(tfm); + rctx->in_sg_len = sg_nents_for_len(rctx->in_sg, rctx->total); + ctx->rctx = rctx; + + if (starfive_hash_check_aligned(rctx->in_sg, rctx->total, rctx->blksize)) + return starfive_hash_digest_fb(req); + + return crypto_transfer_hash_request_to_engine(cryp->engine, req); +} + +static int starfive_hash_export(struct ahash_request *req, void *out) +{ + struct starfive_cryp_request_ctx *rctx = ahash_request_ctx(req); + struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); + struct starfive_cryp_ctx *ctx = crypto_ahash_ctx(tfm); + + ahash_request_set_tfm(&rctx->ahash_fbk_req, ctx->ahash_fbk); + ahash_request_set_callback(&rctx->ahash_fbk_req, + req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP, + req->base.complete, req->base.data); + + return crypto_ahash_export(&rctx->ahash_fbk_req, out); +} + +static int starfive_hash_import(struct ahash_request *req, const void *in) +{ + struct starfive_cryp_request_ctx *rctx = ahash_request_ctx(req); + struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); + struct starfive_cryp_ctx *ctx = crypto_ahash_ctx(tfm); + + ahash_request_set_tfm(&rctx->ahash_fbk_req, ctx->ahash_fbk); + ahash_request_set_callback(&rctx->ahash_fbk_req, + req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP, + req->base.complete, req->base.data); + + return crypto_ahash_import(&rctx->ahash_fbk_req, in); +} + +static int starfive_hash_init_tfm(struct crypto_ahash *hash, + const char *alg_name, + unsigned int mode) +{ + struct starfive_cryp_ctx *ctx = crypto_ahash_ctx(hash); + + ctx->cryp = starfive_cryp_find_dev(ctx); + + if (!ctx->cryp) + return -ENODEV; + + ctx->ahash_fbk = crypto_alloc_ahash(alg_name, 0, + CRYPTO_ALG_NEED_FALLBACK); + + if (IS_ERR(ctx->ahash_fbk)) + return dev_err_probe(ctx->cryp->dev, PTR_ERR(ctx->ahash_fbk), + "starfive_hash: Could not load fallback driver.\n"); + + crypto_ahash_set_statesize(hash, crypto_ahash_statesize(ctx->ahash_fbk)); + crypto_ahash_set_reqsize(hash, sizeof(struct starfive_cryp_request_ctx) + + crypto_ahash_reqsize(ctx->ahash_fbk)); + + ctx->keylen = 0; + ctx->hash_mode = mode; + + ctx->enginectx.op.do_one_request = starfive_hash_one_request; + ctx->enginectx.op.prepare_request = NULL; + ctx->enginectx.op.unprepare_request = NULL; + + return 0; +} + +static void starfive_hash_exit_tfm(struct crypto_ahash *hash) +{ + struct starfive_cryp_ctx *ctx = crypto_ahash_ctx(hash); + + crypto_free_ahash(ctx->ahash_fbk); + + ctx->ahash_fbk = NULL; + ctx->enginectx.op.do_one_request = NULL; + ctx->enginectx.op.prepare_request = NULL; + ctx->enginectx.op.unprepare_request = NULL; +} + +static int starfive_hash_long_setkey(struct starfive_cryp_ctx *ctx, + const u8 *key, unsigned int keylen, + const char *alg_name) +{ + struct crypto_wait wait; + struct ahash_request *req; + struct scatterlist sg; + struct crypto_ahash *ahash_tfm; + u8 *buf; + int ret; + + ahash_tfm = crypto_alloc_ahash(alg_name, 0, 0); + if (IS_ERR(ahash_tfm)) + return PTR_ERR(ahash_tfm); + + req = ahash_request_alloc(ahash_tfm, GFP_KERNEL); + if (!req) { + ret = -ENOMEM; + goto err_free_ahash; + } + + crypto_init_wait(&wait); + ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, + crypto_req_done, &wait); + crypto_ahash_clear_flags(ahash_tfm, ~0); + + buf = kzalloc(keylen + STARFIVE_HASH_BUFLEN, GFP_KERNEL); + if (!buf) { + ret = -ENOMEM; + goto err_free_req; + } + + memcpy(buf, key, keylen); + sg_init_one(&sg, buf, keylen); + ahash_request_set_crypt(req, &sg, ctx->key, keylen); + + ret = crypto_wait_req(crypto_ahash_digest(req), &wait); + + kfree(buf); +err_free_req: + ahash_request_free(req); +err_free_ahash: + crypto_free_ahash(ahash_tfm); + return ret; +} + +static int starfive_hash_setkey(struct crypto_ahash *hash, + const u8 *key, unsigned int keylen) +{ + struct starfive_cryp_ctx *ctx = crypto_ahash_ctx(hash); + unsigned int digestsize = crypto_ahash_digestsize(hash); + unsigned int blocksize = crypto_ahash_blocksize(hash); + const char *alg_name; + + crypto_ahash_setkey(ctx->ahash_fbk, key, keylen); + + if (keylen <= blocksize) { + memcpy(ctx->key, key, keylen); + ctx->keylen = keylen; + return 0; + } + + ctx->keylen = digestsize; + + switch (digestsize) { + case SHA224_DIGEST_SIZE: + alg_name = "sha224-starfive"; + break; + case SHA256_DIGEST_SIZE: + if (ctx->hash_mode == STARFIVE_HASH_SM3) + alg_name = "sm3-starfive"; + else + alg_name = "sha256-starfive"; + break; + case SHA384_DIGEST_SIZE: + alg_name = "sha384-starfive"; + break; + case SHA512_DIGEST_SIZE: + alg_name = "sha512-starfive"; + break; + default: + return -EINVAL; + } + + return starfive_hash_long_setkey(ctx, key, keylen, alg_name); +} + +static int starfive_sha224_init_tfm(struct crypto_ahash *hash) +{ + return starfive_hash_init_tfm(hash, "sha224-generic", + STARFIVE_HASH_SHA224); +} + +static int starfive_sha256_init_tfm(struct crypto_ahash *hash) +{ + return starfive_hash_init_tfm(hash, "sha256-generic", + STARFIVE_HASH_SHA256); +} + +static int starfive_sha384_init_tfm(struct crypto_ahash *hash) +{ + return starfive_hash_init_tfm(hash, "sha384-generic", + STARFIVE_HASH_SHA384); +} + +static int starfive_sha512_init_tfm(struct crypto_ahash *hash) +{ + return starfive_hash_init_tfm(hash, "sha512-generic", + STARFIVE_HASH_SHA512); +} + +static int starfive_sm3_init_tfm(struct crypto_ahash *hash) +{ + return starfive_hash_init_tfm(hash, "sm3-generic", + STARFIVE_HASH_SM3); +} + +static int starfive_hmac_sha224_init_tfm(struct crypto_ahash *hash) +{ + struct starfive_cryp_ctx *ctx = crypto_ahash_ctx(hash); + + ctx->is_hmac = true; + + return starfive_hash_init_tfm(hash, "hmac(sha224-generic)", + STARFIVE_HASH_SHA224); +} + +static int starfive_hmac_sha256_init_tfm(struct crypto_ahash *hash) +{ + struct starfive_cryp_ctx *ctx = crypto_ahash_ctx(hash); + + ctx->is_hmac = true; + + return starfive_hash_init_tfm(hash, "hmac(sha256-generic)", + STARFIVE_HASH_SHA256); +} + +static int starfive_hmac_sha384_init_tfm(struct crypto_ahash *hash) +{ + struct starfive_cryp_ctx *ctx = crypto_ahash_ctx(hash); + + ctx->is_hmac = true; + + return starfive_hash_init_tfm(hash, "hmac(sha384-generic)", + STARFIVE_HASH_SHA384); +} + +static int starfive_hmac_sha512_init_tfm(struct crypto_ahash *hash) +{ + struct starfive_cryp_ctx *ctx = crypto_ahash_ctx(hash); + + ctx->is_hmac = true; + + return starfive_hash_init_tfm(hash, "hmac(sha512-generic)", + STARFIVE_HASH_SHA512); +} + +static int starfive_hmac_sm3_init_tfm(struct crypto_ahash *hash) +{ + struct starfive_cryp_ctx *ctx = crypto_ahash_ctx(hash); + + ctx->is_hmac = true; + + return starfive_hash_init_tfm(hash, "hmac(sm3-generic)", + STARFIVE_HASH_SM3); +} + +static struct ahash_alg algs_sha2_sm3[] = { +{ + .init = starfive_hash_init, + .update = starfive_hash_update, + .final = starfive_hash_final, + .finup = starfive_hash_finup, + .digest = starfive_hash_digest, + .export = starfive_hash_export, + .import = starfive_hash_import, + .init_tfm = starfive_sha224_init_tfm, + .exit_tfm = starfive_hash_exit_tfm, + .halg = { + .digestsize = SHA224_DIGEST_SIZE, + .statesize = sizeof(struct sha256_state), + .base = { + .cra_name = "sha224", + .cra_driver_name = "sha224-starfive", + .cra_priority = 200, + .cra_flags = CRYPTO_ALG_ASYNC | + CRYPTO_ALG_TYPE_AHASH | + CRYPTO_ALG_NEED_FALLBACK, + .cra_blocksize = SHA224_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct starfive_cryp_ctx), + .cra_alignmask = 3, + .cra_module = THIS_MODULE, + } + } +}, { + .init = starfive_hash_init, + .update = starfive_hash_update, + .final = starfive_hash_final, + .finup = starfive_hash_finup, + .digest = starfive_hash_digest, + .export = starfive_hash_export, + .import = starfive_hash_import, + .init_tfm = starfive_hmac_sha224_init_tfm, + .exit_tfm = starfive_hash_exit_tfm, + .setkey = starfive_hash_setkey, + .halg = { + .digestsize = SHA224_DIGEST_SIZE, + .statesize = sizeof(struct sha256_state), + .base = { + .cra_name = "hmac(sha224)", + .cra_driver_name = "sha224-hmac-starfive", + .cra_priority = 200, + .cra_flags = CRYPTO_ALG_ASYNC | + CRYPTO_ALG_TYPE_AHASH | + CRYPTO_ALG_NEED_FALLBACK, + .cra_blocksize = SHA224_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct starfive_cryp_ctx), + .cra_alignmask = 3, + .cra_module = THIS_MODULE, + } + } +}, { + .init = starfive_hash_init, + .update = starfive_hash_update, + .final = starfive_hash_final, + .finup = starfive_hash_finup, + .digest = starfive_hash_digest, + .export = starfive_hash_export, + .import = starfive_hash_import, + .init_tfm = starfive_sha256_init_tfm, + .exit_tfm = starfive_hash_exit_tfm, + .halg = { + .digestsize = SHA256_DIGEST_SIZE, + .statesize = sizeof(struct sha256_state), + .base = { + .cra_name = "sha256", + .cra_driver_name = "sha256-starfive", + .cra_priority = 200, + .cra_flags = CRYPTO_ALG_ASYNC | + CRYPTO_ALG_TYPE_AHASH | + CRYPTO_ALG_NEED_FALLBACK, + .cra_blocksize = SHA256_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct starfive_cryp_ctx), + .cra_alignmask = 3, + .cra_module = THIS_MODULE, + } + } +}, { + .init = starfive_hash_init, + .update = starfive_hash_update, + .final = starfive_hash_final, + .finup = starfive_hash_finup, + .digest = starfive_hash_digest, + .export = starfive_hash_export, + .import = starfive_hash_import, + .init_tfm = starfive_hmac_sha256_init_tfm, + .exit_tfm = starfive_hash_exit_tfm, + .setkey = starfive_hash_setkey, + .halg = { + .digestsize = SHA256_DIGEST_SIZE, + .statesize = sizeof(struct sha256_state), + .base = { + .cra_name = "hmac(sha256)", + .cra_driver_name = "sha256-hmac-starfive", + .cra_priority = 200, + .cra_flags = CRYPTO_ALG_ASYNC | + CRYPTO_ALG_TYPE_AHASH | + CRYPTO_ALG_NEED_FALLBACK, + .cra_blocksize = SHA256_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct starfive_cryp_ctx), + .cra_alignmask = 3, + .cra_module = THIS_MODULE, + } + } +}, { + .init = starfive_hash_init, + .update = starfive_hash_update, + .final = starfive_hash_final, + .finup = starfive_hash_finup, + .digest = starfive_hash_digest, + .export = starfive_hash_export, + .import = starfive_hash_import, + .init_tfm = starfive_sha384_init_tfm, + .exit_tfm = starfive_hash_exit_tfm, + .halg = { + .digestsize = SHA384_DIGEST_SIZE, + .statesize = sizeof(struct sha512_state), + .base = { + .cra_name = "sha384", + .cra_driver_name = "sha384-starfive", + .cra_priority = 200, + .cra_flags = CRYPTO_ALG_ASYNC | + CRYPTO_ALG_TYPE_AHASH | + CRYPTO_ALG_NEED_FALLBACK, + .cra_blocksize = SHA384_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct starfive_cryp_ctx), + .cra_alignmask = 3, + .cra_module = THIS_MODULE, + } + } +}, { + .init = starfive_hash_init, + .update = starfive_hash_update, + .final = starfive_hash_final, + .finup = starfive_hash_finup, + .digest = starfive_hash_digest, + .export = starfive_hash_export, + .import = starfive_hash_import, + .init_tfm = starfive_hmac_sha384_init_tfm, + .exit_tfm = starfive_hash_exit_tfm, + .setkey = starfive_hash_setkey, + .halg = { + .digestsize = SHA384_DIGEST_SIZE, + .statesize = sizeof(struct sha512_state), + .base = { + .cra_name = "hmac(sha384)", + .cra_driver_name = "sha384-hmac-starfive", + .cra_priority = 200, + .cra_flags = CRYPTO_ALG_ASYNC | + CRYPTO_ALG_TYPE_AHASH | + CRYPTO_ALG_NEED_FALLBACK, + .cra_blocksize = SHA384_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct starfive_cryp_ctx), + .cra_alignmask = 3, + .cra_module = THIS_MODULE, + } + } +}, { + .init = starfive_hash_init, + .update = starfive_hash_update, + .final = starfive_hash_final, + .finup = starfive_hash_finup, + .digest = starfive_hash_digest, + .export = starfive_hash_export, + .import = starfive_hash_import, + .init_tfm = starfive_sha512_init_tfm, + .exit_tfm = starfive_hash_exit_tfm, + .halg = { + .digestsize = SHA512_DIGEST_SIZE, + .statesize = sizeof(struct sha512_state), + .base = { + .cra_name = "sha512", + .cra_driver_name = "sha512-starfive", + .cra_priority = 200, + .cra_flags = CRYPTO_ALG_ASYNC | + CRYPTO_ALG_TYPE_AHASH | + CRYPTO_ALG_NEED_FALLBACK, + .cra_blocksize = SHA512_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct starfive_cryp_ctx), + .cra_alignmask = 3, + .cra_module = THIS_MODULE, + } + } +}, { + .init = starfive_hash_init, + .update = starfive_hash_update, + .final = starfive_hash_final, + .finup = starfive_hash_finup, + .digest = starfive_hash_digest, + .export = starfive_hash_export, + .import = starfive_hash_import, + .init_tfm = starfive_hmac_sha512_init_tfm, + .exit_tfm = starfive_hash_exit_tfm, + .setkey = starfive_hash_setkey, + .halg = { + .digestsize = SHA512_DIGEST_SIZE, + .statesize = sizeof(struct sha512_state), + .base = { + .cra_name = "hmac(sha512)", + .cra_driver_name = "sha512-hmac-starfive", + .cra_priority = 200, + .cra_flags = CRYPTO_ALG_ASYNC | + CRYPTO_ALG_TYPE_AHASH | + CRYPTO_ALG_NEED_FALLBACK, + .cra_blocksize = SHA512_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct starfive_cryp_ctx), + .cra_alignmask = 3, + .cra_module = THIS_MODULE, + } + } +}, { + .init = starfive_hash_init, + .update = starfive_hash_update, + .final = starfive_hash_final, + .finup = starfive_hash_finup, + .digest = starfive_hash_digest, + .export = starfive_hash_export, + .import = starfive_hash_import, + .init_tfm = starfive_sm3_init_tfm, + .exit_tfm = starfive_hash_exit_tfm, + .halg = { + .digestsize = SM3_DIGEST_SIZE, + .statesize = sizeof(struct sm3_state), + .base = { + .cra_name = "sm3", + .cra_driver_name = "sm3-starfive", + .cra_priority = 200, + .cra_flags = CRYPTO_ALG_ASYNC | + CRYPTO_ALG_TYPE_AHASH | + CRYPTO_ALG_NEED_FALLBACK, + .cra_blocksize = SM3_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct starfive_cryp_ctx), + .cra_alignmask = 3, + .cra_module = THIS_MODULE, + } + } +}, { + .init = starfive_hash_init, + .update = starfive_hash_update, + .final = starfive_hash_final, + .finup = starfive_hash_finup, + .digest = starfive_hash_digest, + .export = starfive_hash_export, + .import = starfive_hash_import, + .init_tfm = starfive_hmac_sm3_init_tfm, + .exit_tfm = starfive_hash_exit_tfm, + .setkey = starfive_hash_setkey, + .halg = { + .digestsize = SM3_DIGEST_SIZE, + .statesize = sizeof(struct sm3_state), + .base = { + .cra_name = "hmac(sm3)", + .cra_driver_name = "sm3-hmac-starfive", + .cra_priority = 200, + .cra_flags = CRYPTO_ALG_ASYNC | + CRYPTO_ALG_TYPE_AHASH | + CRYPTO_ALG_NEED_FALLBACK, + .cra_blocksize = SM3_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct starfive_cryp_ctx), + .cra_alignmask = 3, + .cra_module = THIS_MODULE, + } + } +}, +}; + +int starfive_hash_register_algs(void) +{ + return crypto_register_ahashes(algs_sha2_sm3, ARRAY_SIZE(algs_sha2_sm3)); +} + +void starfive_hash_unregister_algs(void) +{ + crypto_unregister_ahashes(algs_sha2_sm3, ARRAY_SIZE(algs_sha2_sm3)); +} diff --git a/drivers/crypto/starfive/jh7110-rsa.c b/drivers/crypto/starfive/jh7110-rsa.c new file mode 100644 index 0000000000000000000000000000000000000000..f31bbd825f883fbe17a6737209dc5a781aad923f --- /dev/null +++ b/drivers/crypto/starfive/jh7110-rsa.c @@ -0,0 +1,617 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * StarFive Public Key Algo acceleration driver + * + * Copyright (c) 2022 StarFive Technology + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "jh7110-cryp.h" + +#define STARFIVE_PKA_REGS_OFFSET 0x400 +#define STARFIVE_PKA_CACR_OFFSET (STARFIVE_PKA_REGS_OFFSET + 0x0) +#define STARFIVE_PKA_CASR_OFFSET (STARFIVE_PKA_REGS_OFFSET + 0x4) +#define STARFIVE_PKA_CAAR_OFFSET (STARFIVE_PKA_REGS_OFFSET + 0x8) +#define STARFIVE_PKA_CAER_OFFSET (STARFIVE_PKA_REGS_OFFSET + 0x108) +#define STARFIVE_PKA_CANR_OFFSET (STARFIVE_PKA_REGS_OFFSET + 0x208) + +// R^2 mod N and N0' +#define CRYPTO_CMD_PRE 0x0 +// A * R mod N ==> A +#define CRYPTO_CMD_ARN 0x5 +// A * E * R mod N ==> A +#define CRYPTO_CMD_AERN 0x6 +// A * A * R mod N ==> A +#define CRYPTO_CMD_AARN 0x7 + +#define STARFIVE_RSA_MAX_KEYSZ 256 +#define STARFIVE_RSA_RESET 0x2 + +static inline int starfive_pka_wait_done(struct starfive_cryp_ctx *ctx) +{ + struct starfive_cryp_dev *cryp = ctx->cryp; + + return wait_for_completion_timeout(&cryp->pka_done, + usecs_to_jiffies(100000)); +} + +static inline void starfive_pka_irq_mask_clear(struct starfive_cryp_ctx *ctx) +{ + struct starfive_cryp_dev *cryp = ctx->cryp; + u32 stat; + + stat = readl(cryp->base + STARFIVE_IE_MASK_OFFSET); + stat &= ~STARFIVE_IE_MASK_PKA_DONE; + writel(stat, cryp->base + STARFIVE_IE_MASK_OFFSET); + + reinit_completion(&cryp->pka_done); +} + +static void starfive_rsa_free_key(struct starfive_rsa_key *key) +{ + if (key->d) + kfree_sensitive(key->d); + if (key->e) + kfree_sensitive(key->e); + if (key->n) + kfree_sensitive(key->n); + memset(key, 0, sizeof(*key)); +} + +static unsigned int starfive_rsa_get_nbit(u8 *pa, u32 snum, int key_sz) +{ + u32 i; + u8 value; + + i = snum >> 3; + + value = pa[key_sz - i - 1]; + value >>= snum & 0x7; + value &= 0x1; + + return value; +} + +static int starfive_rsa_montgomery_form(struct starfive_cryp_ctx *ctx, + u32 *out, u32 *in, u8 mont, + u32 *mod, int bit_len) +{ + struct starfive_cryp_dev *cryp = ctx->cryp; + struct starfive_cryp_request_ctx *rctx = ctx->rctx; + int count = rctx->total / sizeof(u32) - 1; + int loop; + u32 temp; + u8 opsize; + + opsize = (bit_len - 1) >> 5; + rctx->csr.pka.v = 0; + + writel(rctx->csr.pka.v, cryp->base + STARFIVE_PKA_CACR_OFFSET); + + for (loop = 0; loop <= opsize; loop++) + writel(mod[opsize - loop], cryp->base + STARFIVE_PKA_CANR_OFFSET + loop * 4); + + if (mont) { + rctx->csr.pka.v = 0; + rctx->csr.pka.cln_done = 1; + rctx->csr.pka.opsize = opsize; + rctx->csr.pka.exposize = opsize; + rctx->csr.pka.cmd = CRYPTO_CMD_PRE; + rctx->csr.pka.start = 1; + rctx->csr.pka.not_r2 = 1; + rctx->csr.pka.ie = 1; + + starfive_pka_irq_mask_clear(ctx); + writel(rctx->csr.pka.v, cryp->base + STARFIVE_PKA_CACR_OFFSET); + + if (!starfive_pka_wait_done(ctx)) + return -ETIMEDOUT; + + for (loop = 0; loop <= opsize; loop++) + writel(in[opsize - loop], cryp->base + STARFIVE_PKA_CAAR_OFFSET + loop * 4); + + writel(0x1000000, cryp->base + STARFIVE_PKA_CAER_OFFSET); + + for (loop = 1; loop <= opsize; loop++) + writel(0, cryp->base + STARFIVE_PKA_CAER_OFFSET + loop * 4); + + rctx->csr.pka.v = 0; + rctx->csr.pka.cln_done = 1; + rctx->csr.pka.opsize = opsize; + rctx->csr.pka.exposize = opsize; + rctx->csr.pka.cmd = CRYPTO_CMD_AERN; + rctx->csr.pka.start = 1; + rctx->csr.pka.ie = 1; + + starfive_pka_irq_mask_clear(ctx); + writel(rctx->csr.pka.v, cryp->base + STARFIVE_PKA_CACR_OFFSET); + + if (!starfive_pka_wait_done(ctx)) + return -ETIMEDOUT; + } else { + rctx->csr.pka.v = 0; + rctx->csr.pka.cln_done = 1; + rctx->csr.pka.opsize = opsize; + rctx->csr.pka.exposize = opsize; + rctx->csr.pka.cmd = CRYPTO_CMD_PRE; + rctx->csr.pka.start = 1; + rctx->csr.pka.pre_expf = 1; + rctx->csr.pka.ie = 1; + + starfive_pka_irq_mask_clear(ctx); + writel(rctx->csr.pka.v, cryp->base + STARFIVE_PKA_CACR_OFFSET); + + if (!starfive_pka_wait_done(ctx)) + return -ETIMEDOUT; + + for (loop = 0; loop <= count; loop++) + writel(in[count - loop], cryp->base + STARFIVE_PKA_CAER_OFFSET + loop * 4); + + /*pad with 0 up to opsize*/ + for (loop = count + 1; loop <= opsize; loop++) + writel(0, cryp->base + STARFIVE_PKA_CAER_OFFSET + loop * 4); + + rctx->csr.pka.v = 0; + rctx->csr.pka.cln_done = 1; + rctx->csr.pka.opsize = opsize; + rctx->csr.pka.exposize = opsize; + rctx->csr.pka.cmd = CRYPTO_CMD_ARN; + rctx->csr.pka.start = 1; + rctx->csr.pka.ie = 1; + + starfive_pka_irq_mask_clear(ctx); + writel(rctx->csr.pka.v, cryp->base + STARFIVE_PKA_CACR_OFFSET); + + if (!starfive_pka_wait_done(ctx)) + return -ETIMEDOUT; + } + + for (loop = 0; loop <= opsize; loop++) { + temp = readl(cryp->base + STARFIVE_PKA_CAAR_OFFSET + 0x4 * loop); + out[opsize - loop] = temp; + } + + return 0; +} + +static int starfive_rsa_cpu_start(struct starfive_cryp_ctx *ctx, u32 *result, + u8 *de, u32 *n, int key_sz) +{ + struct starfive_cryp_dev *cryp = ctx->cryp; + struct starfive_cryp_request_ctx *rctx = ctx->rctx; + struct starfive_rsa_key *key = &ctx->rsa_key; + u32 temp; + int ret = 0; + int opsize, mlen, loop; + unsigned int *mta; + + opsize = (key_sz - 1) >> 2; + + mta = kmalloc(key_sz, GFP_KERNEL); + if (!mta) + return -ENOMEM; + + ret = starfive_rsa_montgomery_form(ctx, mta, (u32 *)rctx->rsa_data, + 0, n, key_sz << 3); + if (ret) { + dev_err_probe(cryp->dev, ret, "Conversion to Montgomery failed"); + goto rsa_err; + } + + for (loop = 0; loop <= opsize; loop++) + writel(mta[opsize - loop], + cryp->base + STARFIVE_PKA_CAER_OFFSET + loop * 4); + + for (loop = key->bitlen - 1; loop > 0; loop--) { + mlen = starfive_rsa_get_nbit(de, loop - 1, key_sz); + + rctx->csr.pka.v = 0; + rctx->csr.pka.cln_done = 1; + rctx->csr.pka.opsize = opsize; + rctx->csr.pka.exposize = opsize; + rctx->csr.pka.cmd = CRYPTO_CMD_AARN; + rctx->csr.pka.start = 1; + rctx->csr.pka.ie = 1; + + starfive_pka_irq_mask_clear(ctx); + writel(rctx->csr.pka.v, cryp->base + STARFIVE_PKA_CACR_OFFSET); + + ret = -ETIMEDOUT; + if (!starfive_pka_wait_done(ctx)) + goto rsa_err; + + if (mlen) { + rctx->csr.pka.v = 0; + rctx->csr.pka.cln_done = 1; + rctx->csr.pka.opsize = opsize; + rctx->csr.pka.exposize = opsize; + rctx->csr.pka.cmd = CRYPTO_CMD_AERN; + rctx->csr.pka.start = 1; + rctx->csr.pka.ie = 1; + + starfive_pka_irq_mask_clear(ctx); + writel(rctx->csr.pka.v, cryp->base + STARFIVE_PKA_CACR_OFFSET); + + if (!starfive_pka_wait_done(ctx)) + goto rsa_err; + } + } + + for (loop = 0; loop <= opsize; loop++) { + temp = readl(cryp->base + STARFIVE_PKA_CAAR_OFFSET + 0x4 * loop); + result[opsize - loop] = temp; + } + + ret = starfive_rsa_montgomery_form(ctx, result, result, 1, n, key_sz << 3); + if (ret) + dev_err_probe(cryp->dev, ret, "Conversion from Montgomery failed"); +rsa_err: + kfree(mta); + return ret; +} + +static int starfive_rsa_start(struct starfive_cryp_ctx *ctx, u8 *result, + u8 *de, u8 *n, int key_sz) +{ + return starfive_rsa_cpu_start(ctx, (u32 *)result, de, (u32 *)n, key_sz); +} + +static int starfive_rsa_enc_core(struct starfive_cryp_ctx *ctx, int enc) +{ + struct starfive_cryp_dev *cryp = ctx->cryp; + struct starfive_cryp_request_ctx *rctx = ctx->rctx; + struct starfive_rsa_key *key = &ctx->rsa_key; + int ret = 0; + + writel(STARFIVE_RSA_RESET, cryp->base + STARFIVE_PKA_CACR_OFFSET); + + rctx->total = sg_copy_to_buffer(rctx->in_sg, rctx->nents, + rctx->rsa_data, rctx->total); + + if (enc) { + key->bitlen = key->e_bitlen; + ret = starfive_rsa_start(ctx, rctx->rsa_data, key->e, + key->n, key->key_sz); + } else { + key->bitlen = key->d_bitlen; + ret = starfive_rsa_start(ctx, rctx->rsa_data, key->d, + key->n, key->key_sz); + } + + if (ret) + goto err_rsa_crypt; + + sg_copy_buffer(rctx->out_sg, sg_nents(rctx->out_sg), + rctx->rsa_data, key->key_sz, 0, 0); + +err_rsa_crypt: + writel(STARFIVE_RSA_RESET, cryp->base + STARFIVE_PKA_CACR_OFFSET); + kfree(rctx->rsa_data); + return ret; +} + +static int starfive_rsa_enc(struct akcipher_request *req) +{ + struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req); + struct starfive_cryp_ctx *ctx = akcipher_tfm_ctx(tfm); + struct starfive_cryp_dev *cryp = ctx->cryp; + struct starfive_rsa_key *key = &ctx->rsa_key; + struct starfive_cryp_request_ctx *rctx = akcipher_request_ctx(req); + int ret; + + if (!key->key_sz) { + akcipher_request_set_tfm(req, ctx->akcipher_fbk); + ret = crypto_akcipher_encrypt(req); + akcipher_request_set_tfm(req, tfm); + return ret; + } + + if (unlikely(!key->n || !key->e)) + return -EINVAL; + + if (req->dst_len < key->key_sz) + return dev_err_probe(cryp->dev, -EOVERFLOW, + "Output buffer length less than parameter n\n"); + + rctx->in_sg = req->src; + rctx->out_sg = req->dst; + rctx->total = req->src_len; + rctx->nents = sg_nents(rctx->in_sg); + ctx->rctx = rctx; + + return starfive_rsa_enc_core(ctx, 1); +} + +static int starfive_rsa_dec(struct akcipher_request *req) +{ + struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req); + struct starfive_cryp_ctx *ctx = akcipher_tfm_ctx(tfm); + struct starfive_cryp_dev *cryp = ctx->cryp; + struct starfive_rsa_key *key = &ctx->rsa_key; + struct starfive_cryp_request_ctx *rctx = akcipher_request_ctx(req); + int ret; + + if (!key->key_sz) { + akcipher_request_set_tfm(req, ctx->akcipher_fbk); + ret = crypto_akcipher_decrypt(req); + akcipher_request_set_tfm(req, tfm); + return ret; + } + + if (unlikely(!key->n || !key->d)) + return -EINVAL; + + if (req->dst_len < key->key_sz) + return dev_err_probe(cryp->dev, -EOVERFLOW, + "Output buffer length less than parameter n\n"); + + rctx->in_sg = req->src; + rctx->out_sg = req->dst; + ctx->rctx = rctx; + rctx->total = req->src_len; + + return starfive_rsa_enc_core(ctx, 0); +} + +static int starfive_rsa_set_n(struct starfive_rsa_key *rsa_key, + const char *value, size_t vlen) +{ + const char *ptr = value; + unsigned int bitslen; + int ret; + + while (!*ptr && vlen) { + ptr++; + vlen--; + } + rsa_key->key_sz = vlen; + bitslen = rsa_key->key_sz << 3; + + /* check valid key size */ + if (bitslen & 0x1f) + return -EINVAL; + + ret = -ENOMEM; + rsa_key->n = kmemdup(ptr, rsa_key->key_sz, GFP_KERNEL); + if (!rsa_key->n) + goto err; + + return 0; + err: + rsa_key->key_sz = 0; + rsa_key->n = NULL; + starfive_rsa_free_key(rsa_key); + return ret; +} + +static int starfive_rsa_set_e(struct starfive_rsa_key *rsa_key, + const char *value, size_t vlen) +{ + const char *ptr = value; + unsigned char pt; + int loop; + + while (!*ptr && vlen) { + ptr++; + vlen--; + } + pt = *ptr; + + if (!rsa_key->key_sz || !vlen || vlen > rsa_key->key_sz) { + rsa_key->e = NULL; + return -EINVAL; + } + + rsa_key->e = kzalloc(rsa_key->key_sz, GFP_KERNEL); + if (!rsa_key->e) + return -ENOMEM; + + for (loop = 8; loop > 0; loop--) { + if (pt >> (loop - 1)) + break; + } + + rsa_key->e_bitlen = (vlen - 1) * 8 + loop; + + memcpy(rsa_key->e + (rsa_key->key_sz - vlen), ptr, vlen); + + return 0; +} + +static int starfive_rsa_set_d(struct starfive_rsa_key *rsa_key, + const char *value, size_t vlen) +{ + const char *ptr = value; + unsigned char pt; + int loop; + int ret; + + while (!*ptr && vlen) { + ptr++; + vlen--; + } + pt = *ptr; + + ret = -EINVAL; + if (!rsa_key->key_sz || !vlen || vlen > rsa_key->key_sz) + goto err; + + ret = -ENOMEM; + rsa_key->d = kzalloc(rsa_key->key_sz, GFP_KERNEL); + if (!rsa_key->d) + goto err; + + for (loop = 8; loop > 0; loop--) { + if (pt >> (loop - 1)) + break; + } + + rsa_key->d_bitlen = (vlen - 1) * 8 + loop; + + memcpy(rsa_key->d + (rsa_key->key_sz - vlen), ptr, vlen); + + return 0; + err: + rsa_key->d = NULL; + return ret; +} + +static int starfive_rsa_setkey(struct crypto_akcipher *tfm, const void *key, + unsigned int keylen, bool private) +{ + struct starfive_cryp_ctx *ctx = akcipher_tfm_ctx(tfm); + struct rsa_key raw_key = {NULL}; + struct starfive_rsa_key *rsa_key = &ctx->rsa_key; + int ret; + + if (private) + ret = rsa_parse_priv_key(&raw_key, key, keylen); + else + ret = rsa_parse_pub_key(&raw_key, key, keylen); + if (ret < 0) + goto err; + + starfive_rsa_free_key(rsa_key); + + /* Use fallback for mod > 256 + 1 byte prefix */ + if (raw_key.n_sz > STARFIVE_RSA_MAX_KEYSZ + 1) + return 0; + + ret = starfive_rsa_set_n(rsa_key, raw_key.n, raw_key.n_sz); + if (ret) + return ret; + + ret = starfive_rsa_set_e(rsa_key, raw_key.e, raw_key.e_sz); + if (ret) + goto err; + + if (private) { + ret = starfive_rsa_set_d(rsa_key, raw_key.d, raw_key.d_sz); + if (ret) + goto err; + } + + if (!rsa_key->n || !rsa_key->e) { + ret = -EINVAL; + goto err; + } + + if (private && !rsa_key->d) { + ret = -EINVAL; + goto err; + } + + return 0; + err: + starfive_rsa_free_key(rsa_key); + return ret; +} + +static int starfive_rsa_set_pub_key(struct crypto_akcipher *tfm, const void *key, + unsigned int keylen) +{ + struct starfive_cryp_ctx *ctx = akcipher_tfm_ctx(tfm); + int ret; + + ret = crypto_akcipher_set_pub_key(ctx->akcipher_fbk, key, keylen); + if (ret) + return ret; + + return starfive_rsa_setkey(tfm, key, keylen, false); +} + +static int starfive_rsa_set_priv_key(struct crypto_akcipher *tfm, const void *key, + unsigned int keylen) +{ + struct starfive_cryp_ctx *ctx = akcipher_tfm_ctx(tfm); + int ret; + + ret = crypto_akcipher_set_priv_key(ctx->akcipher_fbk, key, keylen); + if (ret) + return ret; + + return starfive_rsa_setkey(tfm, key, keylen, true); +} + +static unsigned int starfive_rsa_max_size(struct crypto_akcipher *tfm) +{ + struct starfive_cryp_ctx *ctx = akcipher_tfm_ctx(tfm); + + if (ctx->rsa_key.key_sz) + return ctx->rsa_key.key_sz; + + return crypto_akcipher_maxsize(ctx->akcipher_fbk); +} + +static int starfive_rsa_init_tfm(struct crypto_akcipher *tfm) +{ + struct starfive_cryp_ctx *ctx = akcipher_tfm_ctx(tfm); + + ctx->akcipher_fbk = crypto_alloc_akcipher("rsa-generic", 0, 0); + if (IS_ERR(ctx->akcipher_fbk)) + return PTR_ERR(ctx->akcipher_fbk); + + ctx->cryp = starfive_cryp_find_dev(ctx); + if (!ctx->cryp) { + crypto_free_akcipher(ctx->akcipher_fbk); + return -ENODEV; + } + + akcipher_set_reqsize(tfm, sizeof(struct starfive_cryp_request_ctx) + + sizeof(struct crypto_akcipher) + 32); + + return 0; +} + +static void starfive_rsa_exit_tfm(struct crypto_akcipher *tfm) +{ + struct starfive_cryp_ctx *ctx = akcipher_tfm_ctx(tfm); + struct starfive_rsa_key *key = (struct starfive_rsa_key *)&ctx->rsa_key; + + crypto_free_akcipher(ctx->akcipher_fbk); + starfive_rsa_free_key(key); +} + +static struct akcipher_alg starfive_rsa = { + .encrypt = starfive_rsa_enc, + .decrypt = starfive_rsa_dec, + .sign = starfive_rsa_dec, + .verify = starfive_rsa_enc, + .set_pub_key = starfive_rsa_set_pub_key, + .set_priv_key = starfive_rsa_set_priv_key, + .max_size = starfive_rsa_max_size, + .init = starfive_rsa_init_tfm, + .exit = starfive_rsa_exit_tfm, + .base = { + .cra_name = "rsa", + .cra_driver_name = "starfive-rsa", + .cra_flags = CRYPTO_ALG_TYPE_AKCIPHER | + CRYPTO_ALG_NEED_FALLBACK, + .cra_priority = 3000, + .cra_module = THIS_MODULE, + .cra_ctxsize = sizeof(struct starfive_cryp_ctx), + }, +}; + +int starfive_rsa_register_algs(void) +{ + return crypto_register_akcipher(&starfive_rsa); +} + +void starfive_rsa_unregister_algs(void) +{ + crypto_unregister_akcipher(&starfive_rsa); +} diff --git a/drivers/crypto/virtio/virtio_crypto_core.c b/drivers/crypto/virtio/virtio_crypto_core.c index 1198bd3063655a87d7de886c7e9eecbd008d55ab..94849fa3bd74aaa85e7467a571b778e8e373417f 100644 --- a/drivers/crypto/virtio/virtio_crypto_core.c +++ b/drivers/crypto/virtio/virtio_crypto_core.c @@ -480,6 +480,7 @@ static void virtcrypto_free_unused_reqs(struct virtio_crypto *vcrypto) kfree(vc_req->req_data); kfree(vc_req->sgs); } + cond_resched(); } } diff --git a/drivers/cxl/Kconfig b/drivers/cxl/Kconfig index ff4e78117b31655e38cca2fc59686862929737c3..fcbf8295fde3745139a76bff512449ffe2c236a5 100644 --- a/drivers/cxl/Kconfig +++ b/drivers/cxl/Kconfig @@ -82,6 +82,7 @@ config CXL_PMEM config CXL_MEM tristate "CXL: Memory Expansion" depends on CXL_PCI + select FW_UPLOAD default CXL_BUS help The CXL.mem protocol allows a device to act as a provider of "System @@ -139,4 +140,17 @@ config CXL_REGION_INVALIDATION_TEST If unsure, or if this kernel is meant for production environments, say N. +config CXL_PMU + tristate "CXL Performance Monitoring Unit" + default CXL_BUS + depends on PERF_EVENTS + help + Support performance monitoring as defined in CXL rev 3.0 + section 13.2: Performance Monitoring. CXL components may have + one or more CXL Performance Monitoring Units (CPMUs). + + Say 'y/m' to enable a driver that will attach to performance + monitoring units and provide standard perf based interfaces. + + If unsure say 'm'. endif diff --git a/drivers/cxl/acpi.c b/drivers/cxl/acpi.c index 7e1765b09e04a6da4ab71e6036280838baa2b9ae..658e6b84a76920486c9955e8b61b3750b3f2c930 100644 --- a/drivers/cxl/acpi.c +++ b/drivers/cxl/acpi.c @@ -258,7 +258,7 @@ static int cxl_parse_cfmws(union acpi_subtable_headers *header, void *arg, cxld = &cxlrd->cxlsd.cxld; cxld->flags = cfmws_to_decoder_flags(cfmws->restrictions); - cxld->target_type = CXL_DECODER_EXPANDER; + cxld->target_type = CXL_DECODER_HOSTONLYMEM; cxld->hpa_range = (struct range) { .start = res->start, .end = res->end, @@ -327,66 +327,21 @@ __mock struct acpi_device *to_cxl_host_bridge(struct device *host, return NULL; } -/* - * A host bridge is a dport to a CFMWS decode and it is a uport to the - * dport (PCIe Root Ports) in the host bridge. - */ -static int add_host_bridge_uport(struct device *match, void *arg) -{ - struct cxl_port *root_port = arg; - struct device *host = root_port->dev.parent; - struct acpi_device *hb = to_cxl_host_bridge(host, match); - struct acpi_pci_root *pci_root; - struct cxl_dport *dport; - struct cxl_port *port; - struct device *bridge; - int rc; - - if (!hb) - return 0; - - pci_root = acpi_pci_find_root(hb->handle); - bridge = pci_root->bus->bridge; - dport = cxl_find_dport_by_dev(root_port, bridge); - if (!dport) { - dev_dbg(host, "host bridge expected and not found\n"); - return 0; - } - - if (dport->rch) { - dev_info(bridge, "host supports CXL (restricted)\n"); - return 0; - } - - rc = devm_cxl_register_pci_bus(host, bridge, pci_root->bus); - if (rc) - return rc; - - port = devm_cxl_add_port(host, bridge, dport->component_reg_phys, - dport); - if (IS_ERR(port)) - return PTR_ERR(port); - - dev_info(bridge, "host supports CXL\n"); - - return 0; -} - +/* Note, @dev is used by mock_acpi_table_parse_cedt() */ struct cxl_chbs_context { struct device *dev; unsigned long long uid; - resource_size_t rcrb; - resource_size_t chbcr; + resource_size_t base; u32 cxl_version; }; -static int cxl_get_chbcr(union acpi_subtable_headers *header, void *arg, - const unsigned long end) +static int cxl_get_chbs_iter(union acpi_subtable_headers *header, void *arg, + const unsigned long end) { struct cxl_chbs_context *ctx = arg; struct acpi_cedt_chbs *chbs; - if (ctx->chbcr) + if (ctx->base != CXL_RESOURCE_NONE) return 0; chbs = (struct acpi_cedt_chbs *) header; @@ -395,23 +350,39 @@ static int cxl_get_chbcr(union acpi_subtable_headers *header, void *arg, return 0; ctx->cxl_version = chbs->cxl_version; - ctx->rcrb = CXL_RESOURCE_NONE; - ctx->chbcr = CXL_RESOURCE_NONE; - if (!chbs->base) return 0; - if (chbs->cxl_version != ACPI_CEDT_CHBS_VERSION_CXL11) { - ctx->chbcr = chbs->base; + if (chbs->cxl_version == ACPI_CEDT_CHBS_VERSION_CXL11 && + chbs->length != CXL_RCRB_SIZE) return 0; + + ctx->base = chbs->base; + + return 0; +} + +static int cxl_get_chbs(struct device *dev, struct acpi_device *hb, + struct cxl_chbs_context *ctx) +{ + unsigned long long uid; + int rc; + + rc = acpi_evaluate_integer(hb->handle, METHOD_NAME__UID, NULL, &uid); + if (rc != AE_OK) { + dev_err(dev, "unable to retrieve _UID\n"); + return -ENOENT; } - if (chbs->length != CXL_RCRB_SIZE) - return 0; + dev_dbg(dev, "UID found: %lld\n", uid); + *ctx = (struct cxl_chbs_context) { + .dev = dev, + .uid = uid, + .base = CXL_RESOURCE_NONE, + .cxl_version = UINT_MAX, + }; - ctx->rcrb = chbs->base; - ctx->chbcr = cxl_rcrb_to_component(ctx->dev, chbs->base, - CXL_RCRB_DOWNSTREAM); + acpi_table_parse_cedt(ACPI_CEDT_TYPE_CHBS, cxl_get_chbs_iter, ctx); return 0; } @@ -420,7 +391,6 @@ static int add_host_bridge_dport(struct device *match, void *arg) { acpi_status rc; struct device *bridge; - unsigned long long uid; struct cxl_dport *dport; struct cxl_chbs_context ctx; struct acpi_pci_root *pci_root; @@ -431,51 +401,107 @@ static int add_host_bridge_dport(struct device *match, void *arg) if (!hb) return 0; - rc = acpi_evaluate_integer(hb->handle, METHOD_NAME__UID, NULL, &uid); - if (rc != AE_OK) { - dev_err(match, "unable to retrieve _UID\n"); - return -ENODEV; - } - - dev_dbg(match, "UID found: %lld\n", uid); - - ctx = (struct cxl_chbs_context) { - .dev = match, - .uid = uid, - }; - acpi_table_parse_cedt(ACPI_CEDT_TYPE_CHBS, cxl_get_chbcr, &ctx); + rc = cxl_get_chbs(match, hb, &ctx); + if (rc) + return rc; - if (!ctx.chbcr) { + if (ctx.cxl_version == UINT_MAX) { dev_warn(match, "No CHBS found for Host Bridge (UID %lld)\n", - uid); + ctx.uid); return 0; } - if (ctx.rcrb != CXL_RESOURCE_NONE) - dev_dbg(match, "RCRB found for UID %lld: %pa\n", uid, &ctx.rcrb); - - if (ctx.chbcr == CXL_RESOURCE_NONE) { - dev_warn(match, "CHBCR invalid for Host Bridge (UID %lld)\n", - uid); + if (ctx.base == CXL_RESOURCE_NONE) { + dev_warn(match, "CHBS invalid for Host Bridge (UID %lld)\n", + ctx.uid); return 0; } - dev_dbg(match, "CHBCR found: %pa\n", &ctx.chbcr); - pci_root = acpi_pci_find_root(hb->handle); bridge = pci_root->bus->bridge; - if (ctx.cxl_version == ACPI_CEDT_CHBS_VERSION_CXL11) - dport = devm_cxl_add_rch_dport(root_port, bridge, uid, - ctx.chbcr, ctx.rcrb); - else - dport = devm_cxl_add_dport(root_port, bridge, uid, - ctx.chbcr); + + /* + * In RCH mode, bind the component regs base to the dport. In + * VH mode it will be bound to the CXL host bridge's port + * object later in add_host_bridge_uport(). + */ + if (ctx.cxl_version == ACPI_CEDT_CHBS_VERSION_CXL11) { + dev_dbg(match, "RCRB found for UID %lld: %pa\n", ctx.uid, + &ctx.base); + dport = devm_cxl_add_rch_dport(root_port, bridge, ctx.uid, + ctx.base); + } else { + dport = devm_cxl_add_dport(root_port, bridge, ctx.uid, + CXL_RESOURCE_NONE); + } + if (IS_ERR(dport)) return PTR_ERR(dport); return 0; } +/* + * A host bridge is a dport to a CFMWS decode and it is a uport to the + * dport (PCIe Root Ports) in the host bridge. + */ +static int add_host_bridge_uport(struct device *match, void *arg) +{ + struct cxl_port *root_port = arg; + struct device *host = root_port->dev.parent; + struct acpi_device *hb = to_cxl_host_bridge(host, match); + struct acpi_pci_root *pci_root; + struct cxl_dport *dport; + struct cxl_port *port; + struct device *bridge; + struct cxl_chbs_context ctx; + resource_size_t component_reg_phys; + int rc; + + if (!hb) + return 0; + + pci_root = acpi_pci_find_root(hb->handle); + bridge = pci_root->bus->bridge; + dport = cxl_find_dport_by_dev(root_port, bridge); + if (!dport) { + dev_dbg(host, "host bridge expected and not found\n"); + return 0; + } + + if (dport->rch) { + dev_info(bridge, "host supports CXL (restricted)\n"); + return 0; + } + + rc = cxl_get_chbs(match, hb, &ctx); + if (rc) + return rc; + + if (ctx.cxl_version == ACPI_CEDT_CHBS_VERSION_CXL11) { + dev_warn(bridge, + "CXL CHBS version mismatch, skip port registration\n"); + return 0; + } + + component_reg_phys = ctx.base; + if (component_reg_phys != CXL_RESOURCE_NONE) + dev_dbg(match, "CHBCR found for UID %lld: %pa\n", + ctx.uid, &component_reg_phys); + + rc = devm_cxl_register_pci_bus(host, bridge, pci_root->bus); + if (rc) + return rc; + + port = devm_cxl_add_port(host, bridge, component_reg_phys, dport); + if (IS_ERR(port)) + return PTR_ERR(port); + + dev_info(bridge, "host supports CXL\n"); + + return 0; +} + static int add_root_nvdimm_bridge(struct device *match, void *data) { struct cxl_decoder *cxld; diff --git a/drivers/cxl/core/Makefile b/drivers/cxl/core/Makefile index ca4ae31d8f57fb5bf70d64e78e677b010326e616..1f66b5d4d93556868a5d413b520882f3d94b2f6f 100644 --- a/drivers/cxl/core/Makefile +++ b/drivers/cxl/core/Makefile @@ -12,5 +12,6 @@ cxl_core-y += memdev.o cxl_core-y += mbox.o cxl_core-y += pci.o cxl_core-y += hdm.o +cxl_core-y += pmu.o cxl_core-$(CONFIG_TRACING) += trace.o cxl_core-$(CONFIG_CXL_REGION) += region.o diff --git a/drivers/cxl/core/core.h b/drivers/cxl/core/core.h index 27f0968449de61437cd413096f3354c623c37c33..45e7e044cf4a0452b873680200d0379a245b3f49 100644 --- a/drivers/cxl/core/core.h +++ b/drivers/cxl/core/core.h @@ -6,6 +6,7 @@ extern const struct device_type cxl_nvdimm_bridge_type; extern const struct device_type cxl_nvdimm_type; +extern const struct device_type cxl_pmu_type; extern struct attribute_group cxl_base_attribute_group; @@ -63,6 +64,16 @@ int cxl_dpa_alloc(struct cxl_endpoint_decoder *cxled, unsigned long long size); int cxl_dpa_free(struct cxl_endpoint_decoder *cxled); resource_size_t cxl_dpa_size(struct cxl_endpoint_decoder *cxled); resource_size_t cxl_dpa_resource_start(struct cxl_endpoint_decoder *cxled); + +enum cxl_rcrb { + CXL_RCRB_DOWNSTREAM, + CXL_RCRB_UPSTREAM, +}; +struct cxl_rcrb_info; +resource_size_t __rcrb_to_component(struct device *dev, + struct cxl_rcrb_info *ri, + enum cxl_rcrb which); + extern struct rw_semaphore cxl_dpa_rwsem; int cxl_memdev_init(void); diff --git a/drivers/cxl/core/hdm.c b/drivers/cxl/core/hdm.c index 7889ff203a341cbd9779172a856f307505ff9f7f..4449b34a80cc9b8cf19893ef32984e1b01fdde20 100644 --- a/drivers/cxl/core/hdm.c +++ b/drivers/cxl/core/hdm.c @@ -85,6 +85,7 @@ static int map_hdm_decoder_regs(struct cxl_port *port, void __iomem *crb, struct cxl_component_regs *regs) { struct cxl_register_map map = { + .dev = &port->dev, .resource = port->component_reg_phys, .base = crb, .max_size = CXL_COMPONENT_REG_BLOCK_SIZE, @@ -97,8 +98,7 @@ static int map_hdm_decoder_regs(struct cxl_port *port, void __iomem *crb, return -ENODEV; } - return cxl_map_component_regs(&port->dev, regs, &map, - BIT(CXL_CM_CAP_CAP_ID_HDM)); + return cxl_map_component_regs(&map, regs, BIT(CXL_CM_CAP_CAP_ID_HDM)); } static bool should_emulate_decoders(struct cxl_endpoint_dvsec_info *info) @@ -570,8 +570,9 @@ static void cxld_set_interleave(struct cxl_decoder *cxld, u32 *ctrl) static void cxld_set_type(struct cxl_decoder *cxld, u32 *ctrl) { - u32p_replace_bits(ctrl, !!(cxld->target_type == 3), - CXL_HDM_DECODER0_CTRL_TYPE); + u32p_replace_bits(ctrl, + !!(cxld->target_type == CXL_DECODER_HOSTONLYMEM), + CXL_HDM_DECODER0_CTRL_HOSTONLY); } static int cxlsd_set_targets(struct cxl_switch_decoder *cxlsd, u64 *tgt) @@ -764,7 +765,7 @@ static int cxl_setup_hdm_decoder_from_dvsec( if (!len) return -ENOENT; - cxld->target_type = CXL_DECODER_EXPANDER; + cxld->target_type = CXL_DECODER_HOSTONLYMEM; cxld->commit = NULL; cxld->reset = NULL; cxld->hpa_range = info->dvsec_range[which]; @@ -793,8 +794,8 @@ static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld, int *target_map, void __iomem *hdm, int which, u64 *dpa_base, struct cxl_endpoint_dvsec_info *info) { + struct cxl_endpoint_decoder *cxled = NULL; u64 size, base, skip, dpa_size, lo, hi; - struct cxl_endpoint_decoder *cxled; bool committed; u32 remainder; int i, rc; @@ -827,6 +828,8 @@ static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld, return -ENXIO; } + if (info) + cxled = to_cxl_endpoint_decoder(&cxld->dev); cxld->hpa_range = (struct range) { .start = base, .end = base + size - 1, @@ -837,10 +840,10 @@ static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld, cxld->flags |= CXL_DECODER_F_ENABLE; if (ctrl & CXL_HDM_DECODER0_CTRL_LOCK) cxld->flags |= CXL_DECODER_F_LOCK; - if (FIELD_GET(CXL_HDM_DECODER0_CTRL_TYPE, ctrl)) - cxld->target_type = CXL_DECODER_EXPANDER; + if (FIELD_GET(CXL_HDM_DECODER0_CTRL_HOSTONLY, ctrl)) + cxld->target_type = CXL_DECODER_HOSTONLYMEM; else - cxld->target_type = CXL_DECODER_ACCELERATOR; + cxld->target_type = CXL_DECODER_DEVMEM; if (cxld->id != port->commit_end + 1) { dev_warn(&port->dev, "decoder%d.%d: Committed out of order\n", @@ -856,12 +859,28 @@ static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld, } port->commit_end = cxld->id; } else { - /* unless / until type-2 drivers arrive, assume type-3 */ - if (FIELD_GET(CXL_HDM_DECODER0_CTRL_TYPE, ctrl) == 0) { - ctrl |= CXL_HDM_DECODER0_CTRL_TYPE; + if (cxled) { + struct cxl_memdev *cxlmd = cxled_to_memdev(cxled); + struct cxl_dev_state *cxlds = cxlmd->cxlds; + + /* + * Default by devtype until a device arrives that needs + * more precision. + */ + if (cxlds->type == CXL_DEVTYPE_CLASSMEM) + cxld->target_type = CXL_DECODER_HOSTONLYMEM; + else + cxld->target_type = CXL_DECODER_DEVMEM; + } else { + /* To be overridden by region type at commit time */ + cxld->target_type = CXL_DECODER_HOSTONLYMEM; + } + + if (!FIELD_GET(CXL_HDM_DECODER0_CTRL_HOSTONLY, ctrl) && + cxld->target_type == CXL_DECODER_HOSTONLYMEM) { + ctrl |= CXL_HDM_DECODER0_CTRL_HOSTONLY; writel(ctrl, hdm + CXL_HDM_DECODER0_CTRL_OFFSET(which)); } - cxld->target_type = CXL_DECODER_EXPANDER; } rc = eiw_to_ways(FIELD_GET(CXL_HDM_DECODER0_CTRL_IW_MASK, ctrl), &cxld->interleave_ways); @@ -880,7 +899,7 @@ static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld, port->id, cxld->id, cxld->hpa_range.start, cxld->hpa_range.end, cxld->interleave_ways, cxld->interleave_granularity); - if (!info) { + if (!cxled) { lo = readl(hdm + CXL_HDM_DECODER0_TL_LOW(which)); hi = readl(hdm + CXL_HDM_DECODER0_TL_HIGH(which)); target_list.value = (hi << 32) + lo; @@ -903,7 +922,6 @@ static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld, lo = readl(hdm + CXL_HDM_DECODER0_SKIP_LOW(which)); hi = readl(hdm + CXL_HDM_DECODER0_SKIP_HIGH(which)); skip = (hi << 32) + lo; - cxled = to_cxl_endpoint_decoder(&cxld->dev); rc = devm_cxl_dpa_reserve(cxled, *dpa_base + skip, dpa_size, skip); if (rc) { dev_err(&port->dev, diff --git a/drivers/cxl/core/mbox.c b/drivers/cxl/core/mbox.c index bea9cf31a12df9a3f258e47e98ca5af3582ea856..d6d067fbee970e49670e92746145566ed6925332 100644 --- a/drivers/cxl/core/mbox.c +++ b/drivers/cxl/core/mbox.c @@ -182,7 +182,7 @@ static const char *cxl_mem_opcode_to_name(u16 opcode) /** * cxl_internal_send_cmd() - Kernel internal interface to send a mailbox command - * @cxlds: The device data for the operation + * @mds: The driver data for the operation * @mbox_cmd: initialized command to execute * * Context: Any context. @@ -198,19 +198,19 @@ static const char *cxl_mem_opcode_to_name(u16 opcode) * error. While this distinction can be useful for commands from userspace, the * kernel will only be able to use results when both are successful. */ -int cxl_internal_send_cmd(struct cxl_dev_state *cxlds, +int cxl_internal_send_cmd(struct cxl_memdev_state *mds, struct cxl_mbox_cmd *mbox_cmd) { size_t out_size, min_out; int rc; - if (mbox_cmd->size_in > cxlds->payload_size || - mbox_cmd->size_out > cxlds->payload_size) + if (mbox_cmd->size_in > mds->payload_size || + mbox_cmd->size_out > mds->payload_size) return -E2BIG; out_size = mbox_cmd->size_out; min_out = mbox_cmd->min_out; - rc = cxlds->mbox_send(cxlds, mbox_cmd); + rc = mds->mbox_send(mds, mbox_cmd); /* * EIO is reserved for a payload size mismatch and mbox_send() * may not return this error. @@ -220,7 +220,8 @@ int cxl_internal_send_cmd(struct cxl_dev_state *cxlds, if (rc) return rc; - if (mbox_cmd->return_code != CXL_MBOX_CMD_RC_SUCCESS) + if (mbox_cmd->return_code != CXL_MBOX_CMD_RC_SUCCESS && + mbox_cmd->return_code != CXL_MBOX_CMD_RC_BACKGROUND) return cxl_mbox_cmd_rc2errno(mbox_cmd); if (!out_size) @@ -297,7 +298,7 @@ static bool cxl_payload_from_user_allowed(u16 opcode, void *payload_in) } static int cxl_mbox_cmd_ctor(struct cxl_mbox_cmd *mbox, - struct cxl_dev_state *cxlds, u16 opcode, + struct cxl_memdev_state *mds, u16 opcode, size_t in_size, size_t out_size, u64 in_payload) { *mbox = (struct cxl_mbox_cmd) { @@ -312,7 +313,7 @@ static int cxl_mbox_cmd_ctor(struct cxl_mbox_cmd *mbox, return PTR_ERR(mbox->payload_in); if (!cxl_payload_from_user_allowed(opcode, mbox->payload_in)) { - dev_dbg(cxlds->dev, "%s: input payload not allowed\n", + dev_dbg(mds->cxlds.dev, "%s: input payload not allowed\n", cxl_mem_opcode_to_name(opcode)); kvfree(mbox->payload_in); return -EBUSY; @@ -321,7 +322,7 @@ static int cxl_mbox_cmd_ctor(struct cxl_mbox_cmd *mbox, /* Prepare to handle a full payload for variable sized output */ if (out_size == CXL_VARIABLE_PAYLOAD) - mbox->size_out = cxlds->payload_size; + mbox->size_out = mds->payload_size; else mbox->size_out = out_size; @@ -343,7 +344,7 @@ static void cxl_mbox_cmd_dtor(struct cxl_mbox_cmd *mbox) static int cxl_to_mem_cmd_raw(struct cxl_mem_command *mem_cmd, const struct cxl_send_command *send_cmd, - struct cxl_dev_state *cxlds) + struct cxl_memdev_state *mds) { if (send_cmd->raw.rsvd) return -EINVAL; @@ -353,13 +354,13 @@ static int cxl_to_mem_cmd_raw(struct cxl_mem_command *mem_cmd, * gets passed along without further checking, so it must be * validated here. */ - if (send_cmd->out.size > cxlds->payload_size) + if (send_cmd->out.size > mds->payload_size) return -EINVAL; if (!cxl_mem_raw_command_allowed(send_cmd->raw.opcode)) return -EPERM; - dev_WARN_ONCE(cxlds->dev, true, "raw command path used\n"); + dev_WARN_ONCE(mds->cxlds.dev, true, "raw command path used\n"); *mem_cmd = (struct cxl_mem_command) { .info = { @@ -375,7 +376,7 @@ static int cxl_to_mem_cmd_raw(struct cxl_mem_command *mem_cmd, static int cxl_to_mem_cmd(struct cxl_mem_command *mem_cmd, const struct cxl_send_command *send_cmd, - struct cxl_dev_state *cxlds) + struct cxl_memdev_state *mds) { struct cxl_mem_command *c = &cxl_mem_commands[send_cmd->id]; const struct cxl_command_info *info = &c->info; @@ -390,11 +391,11 @@ static int cxl_to_mem_cmd(struct cxl_mem_command *mem_cmd, return -EINVAL; /* Check that the command is enabled for hardware */ - if (!test_bit(info->id, cxlds->enabled_cmds)) + if (!test_bit(info->id, mds->enabled_cmds)) return -ENOTTY; /* Check that the command is not claimed for exclusive kernel use */ - if (test_bit(info->id, cxlds->exclusive_cmds)) + if (test_bit(info->id, mds->exclusive_cmds)) return -EBUSY; /* Check the input buffer is the expected size */ @@ -423,7 +424,7 @@ static int cxl_to_mem_cmd(struct cxl_mem_command *mem_cmd, /** * cxl_validate_cmd_from_user() - Check fields for CXL_MEM_SEND_COMMAND. * @mbox_cmd: Sanitized and populated &struct cxl_mbox_cmd. - * @cxlds: The device data for the operation + * @mds: The driver data for the operation * @send_cmd: &struct cxl_send_command copied in from userspace. * * Return: @@ -438,7 +439,7 @@ static int cxl_to_mem_cmd(struct cxl_mem_command *mem_cmd, * safe to send to the hardware. */ static int cxl_validate_cmd_from_user(struct cxl_mbox_cmd *mbox_cmd, - struct cxl_dev_state *cxlds, + struct cxl_memdev_state *mds, const struct cxl_send_command *send_cmd) { struct cxl_mem_command mem_cmd; @@ -452,20 +453,20 @@ static int cxl_validate_cmd_from_user(struct cxl_mbox_cmd *mbox_cmd, * supports, but output can be arbitrarily large (simply write out as * much data as the hardware provides). */ - if (send_cmd->in.size > cxlds->payload_size) + if (send_cmd->in.size > mds->payload_size) return -EINVAL; /* Sanitize and construct a cxl_mem_command */ if (send_cmd->id == CXL_MEM_COMMAND_ID_RAW) - rc = cxl_to_mem_cmd_raw(&mem_cmd, send_cmd, cxlds); + rc = cxl_to_mem_cmd_raw(&mem_cmd, send_cmd, mds); else - rc = cxl_to_mem_cmd(&mem_cmd, send_cmd, cxlds); + rc = cxl_to_mem_cmd(&mem_cmd, send_cmd, mds); if (rc) return rc; /* Sanitize and construct a cxl_mbox_cmd */ - return cxl_mbox_cmd_ctor(mbox_cmd, cxlds, mem_cmd.opcode, + return cxl_mbox_cmd_ctor(mbox_cmd, mds, mem_cmd.opcode, mem_cmd.info.size_in, mem_cmd.info.size_out, send_cmd->in.payload); } @@ -473,6 +474,7 @@ static int cxl_validate_cmd_from_user(struct cxl_mbox_cmd *mbox_cmd, int cxl_query_cmd(struct cxl_memdev *cxlmd, struct cxl_mem_query_commands __user *q) { + struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds); struct device *dev = &cxlmd->dev; struct cxl_mem_command *cmd; u32 n_commands; @@ -494,9 +496,9 @@ int cxl_query_cmd(struct cxl_memdev *cxlmd, cxl_for_each_cmd(cmd) { struct cxl_command_info info = cmd->info; - if (test_bit(info.id, cxlmd->cxlds->enabled_cmds)) + if (test_bit(info.id, mds->enabled_cmds)) info.flags |= CXL_MEM_COMMAND_FLAG_ENABLED; - if (test_bit(info.id, cxlmd->cxlds->exclusive_cmds)) + if (test_bit(info.id, mds->exclusive_cmds)) info.flags |= CXL_MEM_COMMAND_FLAG_EXCLUSIVE; if (copy_to_user(&q->commands[j++], &info, sizeof(info))) @@ -511,7 +513,7 @@ int cxl_query_cmd(struct cxl_memdev *cxlmd, /** * handle_mailbox_cmd_from_user() - Dispatch a mailbox command for userspace. - * @cxlds: The device data for the operation + * @mds: The driver data for the operation * @mbox_cmd: The validated mailbox command. * @out_payload: Pointer to userspace's output payload. * @size_out: (Input) Max payload size to copy out. @@ -532,12 +534,12 @@ int cxl_query_cmd(struct cxl_memdev *cxlmd, * * See cxl_send_cmd(). */ -static int handle_mailbox_cmd_from_user(struct cxl_dev_state *cxlds, +static int handle_mailbox_cmd_from_user(struct cxl_memdev_state *mds, struct cxl_mbox_cmd *mbox_cmd, u64 out_payload, s32 *size_out, u32 *retval) { - struct device *dev = cxlds->dev; + struct device *dev = mds->cxlds.dev; int rc; dev_dbg(dev, @@ -547,7 +549,7 @@ static int handle_mailbox_cmd_from_user(struct cxl_dev_state *cxlds, cxl_mem_opcode_to_name(mbox_cmd->opcode), mbox_cmd->opcode, mbox_cmd->size_in); - rc = cxlds->mbox_send(cxlds, mbox_cmd); + rc = mds->mbox_send(mds, mbox_cmd); if (rc) goto out; @@ -576,7 +578,7 @@ static int handle_mailbox_cmd_from_user(struct cxl_dev_state *cxlds, int cxl_send_cmd(struct cxl_memdev *cxlmd, struct cxl_send_command __user *s) { - struct cxl_dev_state *cxlds = cxlmd->cxlds; + struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds); struct device *dev = &cxlmd->dev; struct cxl_send_command send; struct cxl_mbox_cmd mbox_cmd; @@ -587,11 +589,11 @@ int cxl_send_cmd(struct cxl_memdev *cxlmd, struct cxl_send_command __user *s) if (copy_from_user(&send, s, sizeof(send))) return -EFAULT; - rc = cxl_validate_cmd_from_user(&mbox_cmd, cxlmd->cxlds, &send); + rc = cxl_validate_cmd_from_user(&mbox_cmd, mds, &send); if (rc) return rc; - rc = handle_mailbox_cmd_from_user(cxlds, &mbox_cmd, send.out.payload, + rc = handle_mailbox_cmd_from_user(mds, &mbox_cmd, send.out.payload, &send.out.size, &send.retval); if (rc) return rc; @@ -602,13 +604,14 @@ int cxl_send_cmd(struct cxl_memdev *cxlmd, struct cxl_send_command __user *s) return 0; } -static int cxl_xfer_log(struct cxl_dev_state *cxlds, uuid_t *uuid, u32 *size, u8 *out) +static int cxl_xfer_log(struct cxl_memdev_state *mds, uuid_t *uuid, + u32 *size, u8 *out) { u32 remaining = *size; u32 offset = 0; while (remaining) { - u32 xfer_size = min_t(u32, remaining, cxlds->payload_size); + u32 xfer_size = min_t(u32, remaining, mds->payload_size); struct cxl_mbox_cmd mbox_cmd; struct cxl_mbox_get_log log; int rc; @@ -627,7 +630,7 @@ static int cxl_xfer_log(struct cxl_dev_state *cxlds, uuid_t *uuid, u32 *size, u8 .payload_out = out, }; - rc = cxl_internal_send_cmd(cxlds, &mbox_cmd); + rc = cxl_internal_send_cmd(mds, &mbox_cmd); /* * The output payload length that indicates the number @@ -654,17 +657,18 @@ static int cxl_xfer_log(struct cxl_dev_state *cxlds, uuid_t *uuid, u32 *size, u8 /** * cxl_walk_cel() - Walk through the Command Effects Log. - * @cxlds: The device data for the operation + * @mds: The driver data for the operation * @size: Length of the Command Effects Log. * @cel: CEL * * Iterate over each entry in the CEL and determine if the driver supports the * command. If so, the command is enabled for the device and can be used later. */ -static void cxl_walk_cel(struct cxl_dev_state *cxlds, size_t size, u8 *cel) +static void cxl_walk_cel(struct cxl_memdev_state *mds, size_t size, u8 *cel) { struct cxl_cel_entry *cel_entry; const int cel_entries = size / sizeof(*cel_entry); + struct device *dev = mds->cxlds.dev; int i; cel_entry = (struct cxl_cel_entry *) cel; @@ -674,39 +678,39 @@ static void cxl_walk_cel(struct cxl_dev_state *cxlds, size_t size, u8 *cel) struct cxl_mem_command *cmd = cxl_mem_find_command(opcode); if (!cmd && !cxl_is_poison_command(opcode)) { - dev_dbg(cxlds->dev, + dev_dbg(dev, "Opcode 0x%04x unsupported by driver\n", opcode); continue; } if (cmd) - set_bit(cmd->info.id, cxlds->enabled_cmds); + set_bit(cmd->info.id, mds->enabled_cmds); if (cxl_is_poison_command(opcode)) - cxl_set_poison_cmd_enabled(&cxlds->poison, opcode); + cxl_set_poison_cmd_enabled(&mds->poison, opcode); - dev_dbg(cxlds->dev, "Opcode 0x%04x enabled\n", opcode); + dev_dbg(dev, "Opcode 0x%04x enabled\n", opcode); } } -static struct cxl_mbox_get_supported_logs *cxl_get_gsl(struct cxl_dev_state *cxlds) +static struct cxl_mbox_get_supported_logs *cxl_get_gsl(struct cxl_memdev_state *mds) { struct cxl_mbox_get_supported_logs *ret; struct cxl_mbox_cmd mbox_cmd; int rc; - ret = kvmalloc(cxlds->payload_size, GFP_KERNEL); + ret = kvmalloc(mds->payload_size, GFP_KERNEL); if (!ret) return ERR_PTR(-ENOMEM); mbox_cmd = (struct cxl_mbox_cmd) { .opcode = CXL_MBOX_OP_GET_SUPPORTED_LOGS, - .size_out = cxlds->payload_size, + .size_out = mds->payload_size, .payload_out = ret, /* At least the record number field must be valid */ .min_out = 2, }; - rc = cxl_internal_send_cmd(cxlds, &mbox_cmd); + rc = cxl_internal_send_cmd(mds, &mbox_cmd); if (rc < 0) { kvfree(ret); return ERR_PTR(rc); @@ -729,22 +733,22 @@ static const uuid_t log_uuid[] = { /** * cxl_enumerate_cmds() - Enumerate commands for a device. - * @cxlds: The device data for the operation + * @mds: The driver data for the operation * * Returns 0 if enumerate completed successfully. * * CXL devices have optional support for certain commands. This function will * determine the set of supported commands for the hardware and update the - * enabled_cmds bitmap in the @cxlds. + * enabled_cmds bitmap in the @mds. */ -int cxl_enumerate_cmds(struct cxl_dev_state *cxlds) +int cxl_enumerate_cmds(struct cxl_memdev_state *mds) { struct cxl_mbox_get_supported_logs *gsl; - struct device *dev = cxlds->dev; + struct device *dev = mds->cxlds.dev; struct cxl_mem_command *cmd; int i, rc; - gsl = cxl_get_gsl(cxlds); + gsl = cxl_get_gsl(mds); if (IS_ERR(gsl)) return PTR_ERR(gsl); @@ -765,19 +769,19 @@ int cxl_enumerate_cmds(struct cxl_dev_state *cxlds) goto out; } - rc = cxl_xfer_log(cxlds, &uuid, &size, log); + rc = cxl_xfer_log(mds, &uuid, &size, log); if (rc) { kvfree(log); goto out; } - cxl_walk_cel(cxlds, size, log); + cxl_walk_cel(mds, size, log); kvfree(log); /* In case CEL was bogus, enable some default commands. */ cxl_for_each_cmd(cmd) if (cmd->flags & CXL_CMD_FLAG_FORCE_ENABLE) - set_bit(cmd->info.id, cxlds->enabled_cmds); + set_bit(cmd->info.id, mds->enabled_cmds); /* Found the required CEL */ rc = 0; @@ -838,7 +842,7 @@ static void cxl_event_trace_record(const struct cxl_memdev *cxlmd, } } -static int cxl_clear_event_record(struct cxl_dev_state *cxlds, +static int cxl_clear_event_record(struct cxl_memdev_state *mds, enum cxl_event_log_type log, struct cxl_get_event_payload *get_pl) { @@ -852,9 +856,9 @@ static int cxl_clear_event_record(struct cxl_dev_state *cxlds, int i; /* Payload size may limit the max handles */ - if (pl_size > cxlds->payload_size) { - max_handles = (cxlds->payload_size - sizeof(*payload)) / - sizeof(__le16); + if (pl_size > mds->payload_size) { + max_handles = (mds->payload_size - sizeof(*payload)) / + sizeof(__le16); pl_size = struct_size(payload, handles, max_handles); } @@ -879,12 +883,12 @@ static int cxl_clear_event_record(struct cxl_dev_state *cxlds, i = 0; for (cnt = 0; cnt < total; cnt++) { payload->handles[i++] = get_pl->records[cnt].hdr.handle; - dev_dbg(cxlds->dev, "Event log '%d': Clearing %u\n", - log, le16_to_cpu(payload->handles[i])); + dev_dbg(mds->cxlds.dev, "Event log '%d': Clearing %u\n", log, + le16_to_cpu(payload->handles[i])); if (i == max_handles) { payload->nr_recs = i; - rc = cxl_internal_send_cmd(cxlds, &mbox_cmd); + rc = cxl_internal_send_cmd(mds, &mbox_cmd); if (rc) goto free_pl; i = 0; @@ -895,7 +899,7 @@ static int cxl_clear_event_record(struct cxl_dev_state *cxlds, if (i) { payload->nr_recs = i; mbox_cmd.size_in = struct_size(payload, handles, i); - rc = cxl_internal_send_cmd(cxlds, &mbox_cmd); + rc = cxl_internal_send_cmd(mds, &mbox_cmd); if (rc) goto free_pl; } @@ -905,32 +909,34 @@ static int cxl_clear_event_record(struct cxl_dev_state *cxlds, return rc; } -static void cxl_mem_get_records_log(struct cxl_dev_state *cxlds, +static void cxl_mem_get_records_log(struct cxl_memdev_state *mds, enum cxl_event_log_type type) { + struct cxl_memdev *cxlmd = mds->cxlds.cxlmd; + struct device *dev = mds->cxlds.dev; struct cxl_get_event_payload *payload; struct cxl_mbox_cmd mbox_cmd; u8 log_type = type; u16 nr_rec; - mutex_lock(&cxlds->event.log_lock); - payload = cxlds->event.buf; + mutex_lock(&mds->event.log_lock); + payload = mds->event.buf; mbox_cmd = (struct cxl_mbox_cmd) { .opcode = CXL_MBOX_OP_GET_EVENT_RECORD, .payload_in = &log_type, .size_in = sizeof(log_type), .payload_out = payload, - .size_out = cxlds->payload_size, + .size_out = mds->payload_size, .min_out = struct_size(payload, records, 0), }; do { int rc, i; - rc = cxl_internal_send_cmd(cxlds, &mbox_cmd); + rc = cxl_internal_send_cmd(mds, &mbox_cmd); if (rc) { - dev_err_ratelimited(cxlds->dev, + dev_err_ratelimited(dev, "Event log '%d': Failed to query event records : %d", type, rc); break; @@ -941,27 +947,27 @@ static void cxl_mem_get_records_log(struct cxl_dev_state *cxlds, break; for (i = 0; i < nr_rec; i++) - cxl_event_trace_record(cxlds->cxlmd, type, + cxl_event_trace_record(cxlmd, type, &payload->records[i]); if (payload->flags & CXL_GET_EVENT_FLAG_OVERFLOW) - trace_cxl_overflow(cxlds->cxlmd, type, payload); + trace_cxl_overflow(cxlmd, type, payload); - rc = cxl_clear_event_record(cxlds, type, payload); + rc = cxl_clear_event_record(mds, type, payload); if (rc) { - dev_err_ratelimited(cxlds->dev, + dev_err_ratelimited(dev, "Event log '%d': Failed to clear events : %d", type, rc); break; } } while (nr_rec); - mutex_unlock(&cxlds->event.log_lock); + mutex_unlock(&mds->event.log_lock); } /** * cxl_mem_get_event_records - Get Event Records from the device - * @cxlds: The device data for the operation + * @mds: The driver data for the operation * @status: Event Status register value identifying which events are available. * * Retrieve all event records available on the device, report them as trace @@ -970,24 +976,24 @@ static void cxl_mem_get_records_log(struct cxl_dev_state *cxlds, * See CXL rev 3.0 @8.2.9.2.2 Get Event Records * See CXL rev 3.0 @8.2.9.2.3 Clear Event Records */ -void cxl_mem_get_event_records(struct cxl_dev_state *cxlds, u32 status) +void cxl_mem_get_event_records(struct cxl_memdev_state *mds, u32 status) { - dev_dbg(cxlds->dev, "Reading event logs: %x\n", status); + dev_dbg(mds->cxlds.dev, "Reading event logs: %x\n", status); if (status & CXLDEV_EVENT_STATUS_FATAL) - cxl_mem_get_records_log(cxlds, CXL_EVENT_TYPE_FATAL); + cxl_mem_get_records_log(mds, CXL_EVENT_TYPE_FATAL); if (status & CXLDEV_EVENT_STATUS_FAIL) - cxl_mem_get_records_log(cxlds, CXL_EVENT_TYPE_FAIL); + cxl_mem_get_records_log(mds, CXL_EVENT_TYPE_FAIL); if (status & CXLDEV_EVENT_STATUS_WARN) - cxl_mem_get_records_log(cxlds, CXL_EVENT_TYPE_WARN); + cxl_mem_get_records_log(mds, CXL_EVENT_TYPE_WARN); if (status & CXLDEV_EVENT_STATUS_INFO) - cxl_mem_get_records_log(cxlds, CXL_EVENT_TYPE_INFO); + cxl_mem_get_records_log(mds, CXL_EVENT_TYPE_INFO); } EXPORT_SYMBOL_NS_GPL(cxl_mem_get_event_records, CXL); /** * cxl_mem_get_partition_info - Get partition info - * @cxlds: The device data for the operation + * @mds: The driver data for the operation * * Retrieve the current partition info for the device specified. The active * values are the current capacity in bytes. If not 0, the 'next' values are @@ -997,7 +1003,7 @@ EXPORT_SYMBOL_NS_GPL(cxl_mem_get_event_records, CXL); * * See CXL @8.2.9.5.2.1 Get Partition Info */ -static int cxl_mem_get_partition_info(struct cxl_dev_state *cxlds) +static int cxl_mem_get_partition_info(struct cxl_memdev_state *mds) { struct cxl_mbox_get_partition_info pi; struct cxl_mbox_cmd mbox_cmd; @@ -1008,17 +1014,17 @@ static int cxl_mem_get_partition_info(struct cxl_dev_state *cxlds) .size_out = sizeof(pi), .payload_out = &pi, }; - rc = cxl_internal_send_cmd(cxlds, &mbox_cmd); + rc = cxl_internal_send_cmd(mds, &mbox_cmd); if (rc) return rc; - cxlds->active_volatile_bytes = + mds->active_volatile_bytes = le64_to_cpu(pi.active_volatile_cap) * CXL_CAPACITY_MULTIPLIER; - cxlds->active_persistent_bytes = + mds->active_persistent_bytes = le64_to_cpu(pi.active_persistent_cap) * CXL_CAPACITY_MULTIPLIER; - cxlds->next_volatile_bytes = + mds->next_volatile_bytes = le64_to_cpu(pi.next_volatile_cap) * CXL_CAPACITY_MULTIPLIER; - cxlds->next_persistent_bytes = + mds->next_persistent_bytes = le64_to_cpu(pi.next_volatile_cap) * CXL_CAPACITY_MULTIPLIER; return 0; @@ -1026,14 +1032,14 @@ static int cxl_mem_get_partition_info(struct cxl_dev_state *cxlds) /** * cxl_dev_state_identify() - Send the IDENTIFY command to the device. - * @cxlds: The device data for the operation + * @mds: The driver data for the operation * * Return: 0 if identify was executed successfully or media not ready. * * This will dispatch the identify command to the device and on success populate * structures to be exported to sysfs. */ -int cxl_dev_state_identify(struct cxl_dev_state *cxlds) +int cxl_dev_state_identify(struct cxl_memdev_state *mds) { /* See CXL 2.0 Table 175 Identify Memory Device Output Payload */ struct cxl_mbox_identify id; @@ -1041,7 +1047,7 @@ int cxl_dev_state_identify(struct cxl_dev_state *cxlds) u32 val; int rc; - if (!cxlds->media_ready) + if (!mds->cxlds.media_ready) return 0; mbox_cmd = (struct cxl_mbox_cmd) { @@ -1049,31 +1055,92 @@ int cxl_dev_state_identify(struct cxl_dev_state *cxlds) .size_out = sizeof(id), .payload_out = &id, }; - rc = cxl_internal_send_cmd(cxlds, &mbox_cmd); + rc = cxl_internal_send_cmd(mds, &mbox_cmd); if (rc < 0) return rc; - cxlds->total_bytes = + mds->total_bytes = le64_to_cpu(id.total_capacity) * CXL_CAPACITY_MULTIPLIER; - cxlds->volatile_only_bytes = + mds->volatile_only_bytes = le64_to_cpu(id.volatile_capacity) * CXL_CAPACITY_MULTIPLIER; - cxlds->persistent_only_bytes = + mds->persistent_only_bytes = le64_to_cpu(id.persistent_capacity) * CXL_CAPACITY_MULTIPLIER; - cxlds->partition_align_bytes = + mds->partition_align_bytes = le64_to_cpu(id.partition_align) * CXL_CAPACITY_MULTIPLIER; - cxlds->lsa_size = le32_to_cpu(id.lsa_size); - memcpy(cxlds->firmware_version, id.fw_revision, sizeof(id.fw_revision)); + mds->lsa_size = le32_to_cpu(id.lsa_size); + memcpy(mds->firmware_version, id.fw_revision, + sizeof(id.fw_revision)); - if (test_bit(CXL_POISON_ENABLED_LIST, cxlds->poison.enabled_cmds)) { + if (test_bit(CXL_POISON_ENABLED_LIST, mds->poison.enabled_cmds)) { val = get_unaligned_le24(id.poison_list_max_mer); - cxlds->poison.max_errors = min_t(u32, val, CXL_POISON_LIST_MAX); + mds->poison.max_errors = min_t(u32, val, CXL_POISON_LIST_MAX); } return 0; } EXPORT_SYMBOL_NS_GPL(cxl_dev_state_identify, CXL); +/** + * cxl_mem_sanitize() - Send a sanitization command to the device. + * @mds: The device data for the operation + * @cmd: The specific sanitization command opcode + * + * Return: 0 if the command was executed successfully, regardless of + * whether or not the actual security operation is done in the background, + * such as for the Sanitize case. + * Error return values can be the result of the mailbox command, -EINVAL + * when security requirements are not met or invalid contexts. + * + * See CXL 3.0 @8.2.9.8.5.1 Sanitize and @8.2.9.8.5.2 Secure Erase. + */ +int cxl_mem_sanitize(struct cxl_memdev_state *mds, u16 cmd) +{ + int rc; + u32 sec_out = 0; + struct cxl_get_security_output { + __le32 flags; + } out; + struct cxl_mbox_cmd sec_cmd = { + .opcode = CXL_MBOX_OP_GET_SECURITY_STATE, + .payload_out = &out, + .size_out = sizeof(out), + }; + struct cxl_mbox_cmd mbox_cmd = { .opcode = cmd }; + struct cxl_dev_state *cxlds = &mds->cxlds; + + if (cmd != CXL_MBOX_OP_SANITIZE && cmd != CXL_MBOX_OP_SECURE_ERASE) + return -EINVAL; + + rc = cxl_internal_send_cmd(mds, &sec_cmd); + if (rc < 0) { + dev_err(cxlds->dev, "Failed to get security state : %d", rc); + return rc; + } + + /* + * Prior to using these commands, any security applied to + * the user data areas of the device shall be DISABLED (or + * UNLOCKED for secure erase case). + */ + sec_out = le32_to_cpu(out.flags); + if (sec_out & CXL_PMEM_SEC_STATE_USER_PASS_SET) + return -EINVAL; + + if (cmd == CXL_MBOX_OP_SECURE_ERASE && + sec_out & CXL_PMEM_SEC_STATE_LOCKED) + return -EINVAL; + + rc = cxl_internal_send_cmd(mds, &mbox_cmd); + if (rc < 0) { + dev_err(cxlds->dev, "Failed to sanitize device : %d", rc); + return rc; + } + + return 0; +} +EXPORT_SYMBOL_NS_GPL(cxl_mem_sanitize, CXL); + static int add_dpa_res(struct device *dev, struct resource *parent, struct resource *res, resource_size_t start, resource_size_t size, const char *type) @@ -1100,8 +1167,9 @@ static int add_dpa_res(struct device *dev, struct resource *parent, return 0; } -int cxl_mem_create_range_info(struct cxl_dev_state *cxlds) +int cxl_mem_create_range_info(struct cxl_memdev_state *mds) { + struct cxl_dev_state *cxlds = &mds->cxlds; struct device *dev = cxlds->dev; int rc; @@ -1113,35 +1181,35 @@ int cxl_mem_create_range_info(struct cxl_dev_state *cxlds) } cxlds->dpa_res = - (struct resource)DEFINE_RES_MEM(0, cxlds->total_bytes); + (struct resource)DEFINE_RES_MEM(0, mds->total_bytes); - if (cxlds->partition_align_bytes == 0) { + if (mds->partition_align_bytes == 0) { rc = add_dpa_res(dev, &cxlds->dpa_res, &cxlds->ram_res, 0, - cxlds->volatile_only_bytes, "ram"); + mds->volatile_only_bytes, "ram"); if (rc) return rc; return add_dpa_res(dev, &cxlds->dpa_res, &cxlds->pmem_res, - cxlds->volatile_only_bytes, - cxlds->persistent_only_bytes, "pmem"); + mds->volatile_only_bytes, + mds->persistent_only_bytes, "pmem"); } - rc = cxl_mem_get_partition_info(cxlds); + rc = cxl_mem_get_partition_info(mds); if (rc) { dev_err(dev, "Failed to query partition information\n"); return rc; } rc = add_dpa_res(dev, &cxlds->dpa_res, &cxlds->ram_res, 0, - cxlds->active_volatile_bytes, "ram"); + mds->active_volatile_bytes, "ram"); if (rc) return rc; return add_dpa_res(dev, &cxlds->dpa_res, &cxlds->pmem_res, - cxlds->active_volatile_bytes, - cxlds->active_persistent_bytes, "pmem"); + mds->active_volatile_bytes, + mds->active_persistent_bytes, "pmem"); } EXPORT_SYMBOL_NS_GPL(cxl_mem_create_range_info, CXL); -int cxl_set_timestamp(struct cxl_dev_state *cxlds) +int cxl_set_timestamp(struct cxl_memdev_state *mds) { struct cxl_mbox_cmd mbox_cmd; struct cxl_mbox_set_timestamp_in pi; @@ -1154,7 +1222,7 @@ int cxl_set_timestamp(struct cxl_dev_state *cxlds) .payload_in = &pi, }; - rc = cxl_internal_send_cmd(cxlds, &mbox_cmd); + rc = cxl_internal_send_cmd(mds, &mbox_cmd); /* * Command is optional. Devices may have another way of providing * a timestamp, or may return all 0s in timestamp fields. @@ -1170,18 +1238,18 @@ EXPORT_SYMBOL_NS_GPL(cxl_set_timestamp, CXL); int cxl_mem_get_poison(struct cxl_memdev *cxlmd, u64 offset, u64 len, struct cxl_region *cxlr) { - struct cxl_dev_state *cxlds = cxlmd->cxlds; + struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds); struct cxl_mbox_poison_out *po; struct cxl_mbox_poison_in pi; struct cxl_mbox_cmd mbox_cmd; int nr_records = 0; int rc; - rc = mutex_lock_interruptible(&cxlds->poison.lock); + rc = mutex_lock_interruptible(&mds->poison.lock); if (rc) return rc; - po = cxlds->poison.list_out; + po = mds->poison.list_out; pi.offset = cpu_to_le64(offset); pi.length = cpu_to_le64(len / CXL_POISON_LEN_MULT); @@ -1189,13 +1257,13 @@ int cxl_mem_get_poison(struct cxl_memdev *cxlmd, u64 offset, u64 len, .opcode = CXL_MBOX_OP_GET_POISON, .size_in = sizeof(pi), .payload_in = &pi, - .size_out = cxlds->payload_size, + .size_out = mds->payload_size, .payload_out = po, .min_out = struct_size(po, record, 0), }; do { - rc = cxl_internal_send_cmd(cxlds, &mbox_cmd); + rc = cxl_internal_send_cmd(mds, &mbox_cmd); if (rc) break; @@ -1206,14 +1274,14 @@ int cxl_mem_get_poison(struct cxl_memdev *cxlmd, u64 offset, u64 len, /* Protect against an uncleared _FLAG_MORE */ nr_records = nr_records + le16_to_cpu(po->count); - if (nr_records >= cxlds->poison.max_errors) { + if (nr_records >= mds->poison.max_errors) { dev_dbg(&cxlmd->dev, "Max Error Records reached: %d\n", nr_records); break; } } while (po->flags & CXL_POISON_FLAG_MORE); - mutex_unlock(&cxlds->poison.lock); + mutex_unlock(&mds->poison.lock); return rc; } EXPORT_SYMBOL_NS_GPL(cxl_mem_get_poison, CXL); @@ -1223,52 +1291,53 @@ static void free_poison_buf(void *buf) kvfree(buf); } -/* Get Poison List output buffer is protected by cxlds->poison.lock */ -static int cxl_poison_alloc_buf(struct cxl_dev_state *cxlds) +/* Get Poison List output buffer is protected by mds->poison.lock */ +static int cxl_poison_alloc_buf(struct cxl_memdev_state *mds) { - cxlds->poison.list_out = kvmalloc(cxlds->payload_size, GFP_KERNEL); - if (!cxlds->poison.list_out) + mds->poison.list_out = kvmalloc(mds->payload_size, GFP_KERNEL); + if (!mds->poison.list_out) return -ENOMEM; - return devm_add_action_or_reset(cxlds->dev, free_poison_buf, - cxlds->poison.list_out); + return devm_add_action_or_reset(mds->cxlds.dev, free_poison_buf, + mds->poison.list_out); } -int cxl_poison_state_init(struct cxl_dev_state *cxlds) +int cxl_poison_state_init(struct cxl_memdev_state *mds) { int rc; - if (!test_bit(CXL_POISON_ENABLED_LIST, cxlds->poison.enabled_cmds)) + if (!test_bit(CXL_POISON_ENABLED_LIST, mds->poison.enabled_cmds)) return 0; - rc = cxl_poison_alloc_buf(cxlds); + rc = cxl_poison_alloc_buf(mds); if (rc) { - clear_bit(CXL_POISON_ENABLED_LIST, cxlds->poison.enabled_cmds); + clear_bit(CXL_POISON_ENABLED_LIST, mds->poison.enabled_cmds); return rc; } - mutex_init(&cxlds->poison.lock); + mutex_init(&mds->poison.lock); return 0; } EXPORT_SYMBOL_NS_GPL(cxl_poison_state_init, CXL); -struct cxl_dev_state *cxl_dev_state_create(struct device *dev) +struct cxl_memdev_state *cxl_memdev_state_create(struct device *dev) { - struct cxl_dev_state *cxlds; + struct cxl_memdev_state *mds; - cxlds = devm_kzalloc(dev, sizeof(*cxlds), GFP_KERNEL); - if (!cxlds) { + mds = devm_kzalloc(dev, sizeof(*mds), GFP_KERNEL); + if (!mds) { dev_err(dev, "No memory available\n"); return ERR_PTR(-ENOMEM); } - mutex_init(&cxlds->mbox_mutex); - mutex_init(&cxlds->event.log_lock); - cxlds->dev = dev; + mutex_init(&mds->mbox_mutex); + mutex_init(&mds->event.log_lock); + mds->cxlds.dev = dev; + mds->cxlds.type = CXL_DEVTYPE_CLASSMEM; - return cxlds; + return mds; } -EXPORT_SYMBOL_NS_GPL(cxl_dev_state_create, CXL); +EXPORT_SYMBOL_NS_GPL(cxl_memdev_state_create, CXL); void __init cxl_mbox_init(void) { diff --git a/drivers/cxl/core/memdev.c b/drivers/cxl/core/memdev.c index 057a432672900d913743aa6842c96b508d34683a..f99e7ec3cc40e8179d91f1765b82f22623236041 100644 --- a/drivers/cxl/core/memdev.c +++ b/drivers/cxl/core/memdev.c @@ -1,6 +1,8 @@ // SPDX-License-Identifier: GPL-2.0-only /* Copyright(c) 2020 Intel Corporation. */ +#include +#include #include #include #include @@ -39,8 +41,11 @@ static ssize_t firmware_version_show(struct device *dev, { struct cxl_memdev *cxlmd = to_cxl_memdev(dev); struct cxl_dev_state *cxlds = cxlmd->cxlds; + struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlds); - return sysfs_emit(buf, "%.16s\n", cxlds->firmware_version); + if (!mds) + return sysfs_emit(buf, "\n"); + return sysfs_emit(buf, "%.16s\n", mds->firmware_version); } static DEVICE_ATTR_RO(firmware_version); @@ -49,8 +54,11 @@ static ssize_t payload_max_show(struct device *dev, { struct cxl_memdev *cxlmd = to_cxl_memdev(dev); struct cxl_dev_state *cxlds = cxlmd->cxlds; + struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlds); - return sysfs_emit(buf, "%zu\n", cxlds->payload_size); + if (!mds) + return sysfs_emit(buf, "\n"); + return sysfs_emit(buf, "%zu\n", mds->payload_size); } static DEVICE_ATTR_RO(payload_max); @@ -59,8 +67,11 @@ static ssize_t label_storage_size_show(struct device *dev, { struct cxl_memdev *cxlmd = to_cxl_memdev(dev); struct cxl_dev_state *cxlds = cxlmd->cxlds; + struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlds); - return sysfs_emit(buf, "%zu\n", cxlds->lsa_size); + if (!mds) + return sysfs_emit(buf, "\n"); + return sysfs_emit(buf, "%zu\n", mds->lsa_size); } static DEVICE_ATTR_RO(label_storage_size); @@ -107,6 +118,89 @@ static ssize_t numa_node_show(struct device *dev, struct device_attribute *attr, } static DEVICE_ATTR_RO(numa_node); +static ssize_t security_state_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct cxl_memdev *cxlmd = to_cxl_memdev(dev); + struct cxl_dev_state *cxlds = cxlmd->cxlds; + struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlds); + u64 reg = readq(cxlds->regs.mbox + CXLDEV_MBOX_BG_CMD_STATUS_OFFSET); + u32 pct = FIELD_GET(CXLDEV_MBOX_BG_CMD_COMMAND_PCT_MASK, reg); + u16 cmd = FIELD_GET(CXLDEV_MBOX_BG_CMD_COMMAND_OPCODE_MASK, reg); + unsigned long state = mds->security.state; + + if (cmd == CXL_MBOX_OP_SANITIZE && pct != 100) + return sysfs_emit(buf, "sanitize\n"); + + if (!(state & CXL_PMEM_SEC_STATE_USER_PASS_SET)) + return sysfs_emit(buf, "disabled\n"); + if (state & CXL_PMEM_SEC_STATE_FROZEN || + state & CXL_PMEM_SEC_STATE_MASTER_PLIMIT || + state & CXL_PMEM_SEC_STATE_USER_PLIMIT) + return sysfs_emit(buf, "frozen\n"); + if (state & CXL_PMEM_SEC_STATE_LOCKED) + return sysfs_emit(buf, "locked\n"); + else + return sysfs_emit(buf, "unlocked\n"); +} +static struct device_attribute dev_attr_security_state = + __ATTR(state, 0444, security_state_show, NULL); + +static ssize_t security_sanitize_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +{ + struct cxl_memdev *cxlmd = to_cxl_memdev(dev); + struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds); + struct cxl_port *port = cxlmd->endpoint; + bool sanitize; + ssize_t rc; + + if (kstrtobool(buf, &sanitize) || !sanitize) + return -EINVAL; + + if (!port || !is_cxl_endpoint(port)) + return -EINVAL; + + /* ensure no regions are mapped to this memdev */ + if (port->commit_end != -1) + return -EBUSY; + + rc = cxl_mem_sanitize(mds, CXL_MBOX_OP_SANITIZE); + + return rc ? rc : len; +} +static struct device_attribute dev_attr_security_sanitize = + __ATTR(sanitize, 0200, NULL, security_sanitize_store); + +static ssize_t security_erase_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +{ + struct cxl_memdev *cxlmd = to_cxl_memdev(dev); + struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds); + struct cxl_port *port = cxlmd->endpoint; + ssize_t rc; + bool erase; + + if (kstrtobool(buf, &erase) || !erase) + return -EINVAL; + + if (!port || !is_cxl_endpoint(port)) + return -EINVAL; + + /* ensure no regions are mapped to this memdev */ + if (port->commit_end != -1) + return -EBUSY; + + rc = cxl_mem_sanitize(mds, CXL_MBOX_OP_SECURE_ERASE); + + return rc ? rc : len; +} +static struct device_attribute dev_attr_security_erase = + __ATTR(erase, 0200, NULL, security_erase_store); + static int cxl_get_poison_by_memdev(struct cxl_memdev *cxlmd) { struct cxl_dev_state *cxlds = cxlmd->cxlds; @@ -140,7 +234,7 @@ int cxl_trigger_poison_list(struct cxl_memdev *cxlmd) struct cxl_port *port; int rc; - port = dev_get_drvdata(&cxlmd->dev); + port = cxlmd->endpoint; if (!port || !is_cxl_endpoint(port)) return -EINVAL; @@ -198,7 +292,7 @@ static struct cxl_region *cxl_dpa_to_region(struct cxl_memdev *cxlmd, u64 dpa) ctx = (struct cxl_dpa_to_region_context) { .dpa = dpa, }; - port = dev_get_drvdata(&cxlmd->dev); + port = cxlmd->endpoint; if (port && is_cxl_endpoint(port) && port->commit_end != -1) device_for_each_child(&port->dev, &ctx, __cxl_dpa_to_region); @@ -231,7 +325,7 @@ static int cxl_validate_poison_dpa(struct cxl_memdev *cxlmd, u64 dpa) int cxl_inject_poison(struct cxl_memdev *cxlmd, u64 dpa) { - struct cxl_dev_state *cxlds = cxlmd->cxlds; + struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds); struct cxl_mbox_inject_poison inject; struct cxl_poison_record record; struct cxl_mbox_cmd mbox_cmd; @@ -255,13 +349,13 @@ int cxl_inject_poison(struct cxl_memdev *cxlmd, u64 dpa) .size_in = sizeof(inject), .payload_in = &inject, }; - rc = cxl_internal_send_cmd(cxlds, &mbox_cmd); + rc = cxl_internal_send_cmd(mds, &mbox_cmd); if (rc) goto out; cxlr = cxl_dpa_to_region(cxlmd, dpa); if (cxlr) - dev_warn_once(cxlds->dev, + dev_warn_once(mds->cxlds.dev, "poison inject dpa:%#llx region: %s\n", dpa, dev_name(&cxlr->dev)); @@ -279,7 +373,7 @@ EXPORT_SYMBOL_NS_GPL(cxl_inject_poison, CXL); int cxl_clear_poison(struct cxl_memdev *cxlmd, u64 dpa) { - struct cxl_dev_state *cxlds = cxlmd->cxlds; + struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds); struct cxl_mbox_clear_poison clear; struct cxl_poison_record record; struct cxl_mbox_cmd mbox_cmd; @@ -312,14 +406,15 @@ int cxl_clear_poison(struct cxl_memdev *cxlmd, u64 dpa) .payload_in = &clear, }; - rc = cxl_internal_send_cmd(cxlds, &mbox_cmd); + rc = cxl_internal_send_cmd(mds, &mbox_cmd); if (rc) goto out; cxlr = cxl_dpa_to_region(cxlmd, dpa); if (cxlr) - dev_warn_once(cxlds->dev, "poison clear dpa:%#llx region: %s\n", - dpa, dev_name(&cxlr->dev)); + dev_warn_once(mds->cxlds.dev, + "poison clear dpa:%#llx region: %s\n", dpa, + dev_name(&cxlr->dev)); record = (struct cxl_poison_record) { .address = cpu_to_le64(dpa), @@ -352,6 +447,13 @@ static struct attribute *cxl_memdev_ram_attributes[] = { NULL, }; +static struct attribute *cxl_memdev_security_attributes[] = { + &dev_attr_security_state.attr, + &dev_attr_security_sanitize.attr, + &dev_attr_security_erase.attr, + NULL, +}; + static umode_t cxl_memdev_visible(struct kobject *kobj, struct attribute *a, int n) { @@ -375,10 +477,16 @@ static struct attribute_group cxl_memdev_pmem_attribute_group = { .attrs = cxl_memdev_pmem_attributes, }; +static struct attribute_group cxl_memdev_security_attribute_group = { + .name = "security", + .attrs = cxl_memdev_security_attributes, +}; + static const struct attribute_group *cxl_memdev_attribute_groups[] = { &cxl_memdev_attribute_group, &cxl_memdev_ram_attribute_group, &cxl_memdev_pmem_attribute_group, + &cxl_memdev_security_attribute_group, NULL, }; @@ -397,17 +505,18 @@ EXPORT_SYMBOL_NS_GPL(is_cxl_memdev, CXL); /** * set_exclusive_cxl_commands() - atomically disable user cxl commands - * @cxlds: The device state to operate on + * @mds: The device state to operate on * @cmds: bitmap of commands to mark exclusive * * Grab the cxl_memdev_rwsem in write mode to flush in-flight * invocations of the ioctl path and then disable future execution of * commands with the command ids set in @cmds. */ -void set_exclusive_cxl_commands(struct cxl_dev_state *cxlds, unsigned long *cmds) +void set_exclusive_cxl_commands(struct cxl_memdev_state *mds, + unsigned long *cmds) { down_write(&cxl_memdev_rwsem); - bitmap_or(cxlds->exclusive_cmds, cxlds->exclusive_cmds, cmds, + bitmap_or(mds->exclusive_cmds, mds->exclusive_cmds, cmds, CXL_MEM_COMMAND_ID_MAX); up_write(&cxl_memdev_rwsem); } @@ -415,23 +524,34 @@ EXPORT_SYMBOL_NS_GPL(set_exclusive_cxl_commands, CXL); /** * clear_exclusive_cxl_commands() - atomically enable user cxl commands - * @cxlds: The device state to modify + * @mds: The device state to modify * @cmds: bitmap of commands to mark available for userspace */ -void clear_exclusive_cxl_commands(struct cxl_dev_state *cxlds, unsigned long *cmds) +void clear_exclusive_cxl_commands(struct cxl_memdev_state *mds, + unsigned long *cmds) { down_write(&cxl_memdev_rwsem); - bitmap_andnot(cxlds->exclusive_cmds, cxlds->exclusive_cmds, cmds, + bitmap_andnot(mds->exclusive_cmds, mds->exclusive_cmds, cmds, CXL_MEM_COMMAND_ID_MAX); up_write(&cxl_memdev_rwsem); } EXPORT_SYMBOL_NS_GPL(clear_exclusive_cxl_commands, CXL); +static void cxl_memdev_security_shutdown(struct device *dev) +{ + struct cxl_memdev *cxlmd = to_cxl_memdev(dev); + struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds); + + if (mds->security.poll) + cancel_delayed_work_sync(&mds->security.poll_dwork); +} + static void cxl_memdev_shutdown(struct device *dev) { struct cxl_memdev *cxlmd = to_cxl_memdev(dev); down_write(&cxl_memdev_rwsem); + cxl_memdev_security_shutdown(dev); cxlmd->cxlds = NULL; up_write(&cxl_memdev_rwsem); } @@ -511,10 +631,12 @@ static long cxl_memdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct cxl_memdev *cxlmd = file->private_data; + struct cxl_dev_state *cxlds; int rc = -ENXIO; down_read(&cxl_memdev_rwsem); - if (cxlmd->cxlds) + cxlds = cxlmd->cxlds; + if (cxlds && cxlds->type == CXL_DEVTYPE_CLASSMEM) rc = __cxl_memdev_ioctl(cxlmd, cmd, arg); up_read(&cxl_memdev_rwsem); @@ -542,6 +664,316 @@ static int cxl_memdev_release_file(struct inode *inode, struct file *file) return 0; } +/** + * cxl_mem_get_fw_info - Get Firmware info + * @mds: The device data for the operation + * + * Retrieve firmware info for the device specified. + * + * Return: 0 if no error: or the result of the mailbox command. + * + * See CXL-3.0 8.2.9.3.1 Get FW Info + */ +static int cxl_mem_get_fw_info(struct cxl_memdev_state *mds) +{ + struct cxl_mbox_get_fw_info info; + struct cxl_mbox_cmd mbox_cmd; + int rc; + + mbox_cmd = (struct cxl_mbox_cmd) { + .opcode = CXL_MBOX_OP_GET_FW_INFO, + .size_out = sizeof(info), + .payload_out = &info, + }; + + rc = cxl_internal_send_cmd(mds, &mbox_cmd); + if (rc < 0) + return rc; + + mds->fw.num_slots = info.num_slots; + mds->fw.cur_slot = FIELD_GET(CXL_FW_INFO_SLOT_INFO_CUR_MASK, + info.slot_info); + + return 0; +} + +/** + * cxl_mem_activate_fw - Activate Firmware + * @mds: The device data for the operation + * @slot: slot number to activate + * + * Activate firmware in a given slot for the device specified. + * + * Return: 0 if no error: or the result of the mailbox command. + * + * See CXL-3.0 8.2.9.3.3 Activate FW + */ +static int cxl_mem_activate_fw(struct cxl_memdev_state *mds, int slot) +{ + struct cxl_mbox_activate_fw activate; + struct cxl_mbox_cmd mbox_cmd; + + if (slot == 0 || slot > mds->fw.num_slots) + return -EINVAL; + + mbox_cmd = (struct cxl_mbox_cmd) { + .opcode = CXL_MBOX_OP_ACTIVATE_FW, + .size_in = sizeof(activate), + .payload_in = &activate, + }; + + /* Only offline activation supported for now */ + activate.action = CXL_FW_ACTIVATE_OFFLINE; + activate.slot = slot; + + return cxl_internal_send_cmd(mds, &mbox_cmd); +} + +/** + * cxl_mem_abort_fw_xfer - Abort an in-progress FW transfer + * @mds: The device data for the operation + * + * Abort an in-progress firmware transfer for the device specified. + * + * Return: 0 if no error: or the result of the mailbox command. + * + * See CXL-3.0 8.2.9.3.2 Transfer FW + */ +static int cxl_mem_abort_fw_xfer(struct cxl_memdev_state *mds) +{ + struct cxl_mbox_transfer_fw *transfer; + struct cxl_mbox_cmd mbox_cmd; + int rc; + + transfer = kzalloc(struct_size(transfer, data, 0), GFP_KERNEL); + if (!transfer) + return -ENOMEM; + + /* Set a 1s poll interval and a total wait time of 30s */ + mbox_cmd = (struct cxl_mbox_cmd) { + .opcode = CXL_MBOX_OP_TRANSFER_FW, + .size_in = sizeof(*transfer), + .payload_in = transfer, + .poll_interval_ms = 1000, + .poll_count = 30, + }; + + transfer->action = CXL_FW_TRANSFER_ACTION_ABORT; + + rc = cxl_internal_send_cmd(mds, &mbox_cmd); + kfree(transfer); + return rc; +} + +static void cxl_fw_cleanup(struct fw_upload *fwl) +{ + struct cxl_memdev_state *mds = fwl->dd_handle; + + mds->fw.next_slot = 0; +} + +static int cxl_fw_do_cancel(struct fw_upload *fwl) +{ + struct cxl_memdev_state *mds = fwl->dd_handle; + struct cxl_dev_state *cxlds = &mds->cxlds; + struct cxl_memdev *cxlmd = cxlds->cxlmd; + int rc; + + rc = cxl_mem_abort_fw_xfer(mds); + if (rc < 0) + dev_err(&cxlmd->dev, "Error aborting FW transfer: %d\n", rc); + + return FW_UPLOAD_ERR_CANCELED; +} + +static enum fw_upload_err cxl_fw_prepare(struct fw_upload *fwl, const u8 *data, + u32 size) +{ + struct cxl_memdev_state *mds = fwl->dd_handle; + struct cxl_mbox_transfer_fw *transfer; + + if (!size) + return FW_UPLOAD_ERR_INVALID_SIZE; + + mds->fw.oneshot = struct_size(transfer, data, size) < + mds->payload_size; + + if (cxl_mem_get_fw_info(mds)) + return FW_UPLOAD_ERR_HW_ERROR; + + /* + * So far no state has been changed, hence no other cleanup is + * necessary. Simply return the cancelled status. + */ + if (test_and_clear_bit(CXL_FW_CANCEL, mds->fw.state)) + return FW_UPLOAD_ERR_CANCELED; + + return FW_UPLOAD_ERR_NONE; +} + +static enum fw_upload_err cxl_fw_write(struct fw_upload *fwl, const u8 *data, + u32 offset, u32 size, u32 *written) +{ + struct cxl_memdev_state *mds = fwl->dd_handle; + struct cxl_dev_state *cxlds = &mds->cxlds; + struct cxl_memdev *cxlmd = cxlds->cxlmd; + struct cxl_mbox_transfer_fw *transfer; + struct cxl_mbox_cmd mbox_cmd; + u32 cur_size, remaining; + size_t size_in; + int rc; + + *written = 0; + + /* Offset has to be aligned to 128B (CXL-3.0 8.2.9.3.2 Table 8-57) */ + if (!IS_ALIGNED(offset, CXL_FW_TRANSFER_ALIGNMENT)) { + dev_err(&cxlmd->dev, + "misaligned offset for FW transfer slice (%u)\n", + offset); + return FW_UPLOAD_ERR_RW_ERROR; + } + + /* + * Pick transfer size based on mds->payload_size @size must bw 128-byte + * aligned, ->payload_size is a power of 2 starting at 256 bytes, and + * sizeof(*transfer) is 128. These constraints imply that @cur_size + * will always be 128b aligned. + */ + cur_size = min_t(size_t, size, mds->payload_size - sizeof(*transfer)); + + remaining = size - cur_size; + size_in = struct_size(transfer, data, cur_size); + + if (test_and_clear_bit(CXL_FW_CANCEL, mds->fw.state)) + return cxl_fw_do_cancel(fwl); + + /* + * Slot numbers are 1-indexed + * cur_slot is the 0-indexed next_slot (i.e. 'cur_slot - 1 + 1') + * Check for rollover using modulo, and 1-index it by adding 1 + */ + mds->fw.next_slot = (mds->fw.cur_slot % mds->fw.num_slots) + 1; + + /* Do the transfer via mailbox cmd */ + transfer = kzalloc(size_in, GFP_KERNEL); + if (!transfer) + return FW_UPLOAD_ERR_RW_ERROR; + + transfer->offset = cpu_to_le32(offset / CXL_FW_TRANSFER_ALIGNMENT); + memcpy(transfer->data, data + offset, cur_size); + if (mds->fw.oneshot) { + transfer->action = CXL_FW_TRANSFER_ACTION_FULL; + transfer->slot = mds->fw.next_slot; + } else { + if (offset == 0) { + transfer->action = CXL_FW_TRANSFER_ACTION_INITIATE; + } else if (remaining == 0) { + transfer->action = CXL_FW_TRANSFER_ACTION_END; + transfer->slot = mds->fw.next_slot; + } else { + transfer->action = CXL_FW_TRANSFER_ACTION_CONTINUE; + } + } + + mbox_cmd = (struct cxl_mbox_cmd) { + .opcode = CXL_MBOX_OP_TRANSFER_FW, + .size_in = size_in, + .payload_in = transfer, + .poll_interval_ms = 1000, + .poll_count = 30, + }; + + rc = cxl_internal_send_cmd(mds, &mbox_cmd); + if (rc < 0) { + rc = FW_UPLOAD_ERR_RW_ERROR; + goto out_free; + } + + *written = cur_size; + + /* Activate FW if oneshot or if the last slice was written */ + if (mds->fw.oneshot || remaining == 0) { + dev_dbg(&cxlmd->dev, "Activating firmware slot: %d\n", + mds->fw.next_slot); + rc = cxl_mem_activate_fw(mds, mds->fw.next_slot); + if (rc < 0) { + dev_err(&cxlmd->dev, "Error activating firmware: %d\n", + rc); + rc = FW_UPLOAD_ERR_HW_ERROR; + goto out_free; + } + } + + rc = FW_UPLOAD_ERR_NONE; + +out_free: + kfree(transfer); + return rc; +} + +static enum fw_upload_err cxl_fw_poll_complete(struct fw_upload *fwl) +{ + struct cxl_memdev_state *mds = fwl->dd_handle; + + /* + * cxl_internal_send_cmd() handles background operations synchronously. + * No need to wait for completions here - any errors would've been + * reported and handled during the ->write() call(s). + * Just check if a cancel request was received, and return success. + */ + if (test_and_clear_bit(CXL_FW_CANCEL, mds->fw.state)) + return cxl_fw_do_cancel(fwl); + + return FW_UPLOAD_ERR_NONE; +} + +static void cxl_fw_cancel(struct fw_upload *fwl) +{ + struct cxl_memdev_state *mds = fwl->dd_handle; + + set_bit(CXL_FW_CANCEL, mds->fw.state); +} + +static const struct fw_upload_ops cxl_memdev_fw_ops = { + .prepare = cxl_fw_prepare, + .write = cxl_fw_write, + .poll_complete = cxl_fw_poll_complete, + .cancel = cxl_fw_cancel, + .cleanup = cxl_fw_cleanup, +}; + +static void devm_cxl_remove_fw_upload(void *fwl) +{ + firmware_upload_unregister(fwl); +} + +int cxl_memdev_setup_fw_upload(struct cxl_memdev_state *mds) +{ + struct cxl_dev_state *cxlds = &mds->cxlds; + struct device *dev = &cxlds->cxlmd->dev; + struct fw_upload *fwl; + int rc; + + if (!test_bit(CXL_MEM_COMMAND_ID_GET_FW_INFO, mds->enabled_cmds)) + return 0; + + fwl = firmware_upload_register(THIS_MODULE, dev, dev_name(dev), + &cxl_memdev_fw_ops, mds); + if (IS_ERR(fwl)) + return dev_err_probe(dev, PTR_ERR(fwl), + "Failed to register firmware loader\n"); + + rc = devm_add_action_or_reset(cxlds->dev, devm_cxl_remove_fw_upload, + fwl); + if (rc) + dev_err(dev, + "Failed to add firmware loader remove action: %d\n", + rc); + + return rc; +} +EXPORT_SYMBOL_NS_GPL(cxl_memdev_setup_fw_upload, CXL); + static const struct file_operations cxl_memdev_fops = { .owner = THIS_MODULE, .unlocked_ioctl = cxl_memdev_ioctl, @@ -551,6 +983,35 @@ static const struct file_operations cxl_memdev_fops = { .llseek = noop_llseek, }; +static void put_sanitize(void *data) +{ + struct cxl_memdev_state *mds = data; + + sysfs_put(mds->security.sanitize_node); +} + +static int cxl_memdev_security_init(struct cxl_memdev *cxlmd) +{ + struct cxl_dev_state *cxlds = cxlmd->cxlds; + struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlds); + struct device *dev = &cxlmd->dev; + struct kernfs_node *sec; + + sec = sysfs_get_dirent(dev->kobj.sd, "security"); + if (!sec) { + dev_err(dev, "sysfs_get_dirent 'security' failed\n"); + return -ENODEV; + } + mds->security.sanitize_node = sysfs_get_dirent(sec, "state"); + sysfs_put(sec); + if (!mds->security.sanitize_node) { + dev_err(dev, "sysfs_get_dirent 'state' failed\n"); + return -ENODEV; + } + + return devm_add_action_or_reset(cxlds->dev, put_sanitize, mds); + } + struct cxl_memdev *devm_cxl_add_memdev(struct cxl_dev_state *cxlds) { struct cxl_memdev *cxlmd; @@ -579,6 +1040,10 @@ struct cxl_memdev *devm_cxl_add_memdev(struct cxl_dev_state *cxlds) if (rc) goto err; + rc = cxl_memdev_security_init(cxlmd); + if (rc) + goto err; + rc = devm_add_action_or_reset(cxlds->dev, cxl_memdev_unregister, cxlmd); if (rc) return ERR_PTR(rc); diff --git a/drivers/cxl/core/pci.c b/drivers/cxl/core/pci.c index 67f4ab6daa34f0144380c27d41d9ca252c52ef04..c7a7887ebdcff859bac675e6f41322aae1b50794 100644 --- a/drivers/cxl/core/pci.c +++ b/drivers/cxl/core/pci.c @@ -67,7 +67,7 @@ static int match_add_dports(struct pci_dev *pdev, void *data) /** * devm_cxl_port_enumerate_dports - enumerate downstream ports of the upstream port - * @port: cxl_port whose ->uport is the upstream of dports to be enumerated + * @port: cxl_port whose ->uport_dev is the upstream of dports to be enumerated * * Returns a positive number of dports enumerated or a negative error * code. @@ -308,36 +308,17 @@ static void disable_hdm(void *_cxlhdm) hdm + CXL_HDM_DECODER_CTRL_OFFSET); } -int devm_cxl_enable_hdm(struct cxl_port *port, struct cxl_hdm *cxlhdm) +static int devm_cxl_enable_hdm(struct device *host, struct cxl_hdm *cxlhdm) { - void __iomem *hdm; + void __iomem *hdm = cxlhdm->regs.hdm_decoder; u32 global_ctrl; - /* - * If the hdm capability was not mapped there is nothing to enable and - * the caller is responsible for what happens next. For example, - * emulate a passthrough decoder. - */ - if (IS_ERR(cxlhdm)) - return 0; - - hdm = cxlhdm->regs.hdm_decoder; global_ctrl = readl(hdm + CXL_HDM_DECODER_CTRL_OFFSET); - - /* - * If the HDM decoder capability was enabled on entry, skip - * registering disable_hdm() since this decode capability may be - * owned by platform firmware. - */ - if (global_ctrl & CXL_HDM_DECODER_ENABLE) - return 0; - writel(global_ctrl | CXL_HDM_DECODER_ENABLE, hdm + CXL_HDM_DECODER_CTRL_OFFSET); - return devm_add_action_or_reset(&port->dev, disable_hdm, cxlhdm); + return devm_add_action_or_reset(host, disable_hdm, cxlhdm); } -EXPORT_SYMBOL_NS_GPL(devm_cxl_enable_hdm, CXL); int cxl_dvsec_rr_decode(struct device *dev, int d, struct cxl_endpoint_dvsec_info *info) @@ -511,7 +492,7 @@ int cxl_hdm_decode_init(struct cxl_dev_state *cxlds, struct cxl_hdm *cxlhdm, if (info->mem_enabled) return 0; - rc = devm_cxl_enable_hdm(port, cxlhdm); + rc = devm_cxl_enable_hdm(&port->dev, cxlhdm); if (rc) return rc; @@ -622,7 +603,7 @@ static int cxl_cdat_read_table(struct device *dev, */ void read_cdat_data(struct cxl_port *port) { - struct cxl_memdev *cxlmd = to_cxl_memdev(port->uport); + struct cxl_memdev *cxlmd = to_cxl_memdev(port->uport_dev); struct device *host = cxlmd->dev.parent; struct device *dev = &port->dev; struct pci_doe_mb *cdat_doe; diff --git a/drivers/cxl/core/pmem.c b/drivers/cxl/core/pmem.c index f8c38d9972522a605e9bf94f436343f62df0e64f..fc94f5240327127743336b47e9228f8871deb67d 100644 --- a/drivers/cxl/core/pmem.c +++ b/drivers/cxl/core/pmem.c @@ -64,7 +64,7 @@ static int match_nvdimm_bridge(struct device *dev, void *data) struct cxl_nvdimm_bridge *cxl_find_nvdimm_bridge(struct cxl_memdev *cxlmd) { - struct cxl_port *port = find_cxl_root(dev_get_drvdata(&cxlmd->dev)); + struct cxl_port *port = find_cxl_root(cxlmd->endpoint); struct device *dev; if (!port) diff --git a/drivers/cxl/core/pmu.c b/drivers/cxl/core/pmu.c new file mode 100644 index 0000000000000000000000000000000000000000..7684c843e5a59c51c6d41556bfb18150c9cbfd26 --- /dev/null +++ b/drivers/cxl/core/pmu.c @@ -0,0 +1,68 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* Copyright(c) 2023 Huawei. All rights reserved. */ + +#include +#include +#include +#include +#include +#include +#include "core.h" + +static void cxl_pmu_release(struct device *dev) +{ + struct cxl_pmu *pmu = to_cxl_pmu(dev); + + kfree(pmu); +} + +const struct device_type cxl_pmu_type = { + .name = "cxl_pmu", + .release = cxl_pmu_release, +}; + +static void remove_dev(void *dev) +{ + device_del(dev); +} + +int devm_cxl_pmu_add(struct device *parent, struct cxl_pmu_regs *regs, + int assoc_id, int index, enum cxl_pmu_type type) +{ + struct cxl_pmu *pmu; + struct device *dev; + int rc; + + pmu = kzalloc(sizeof(*pmu), GFP_KERNEL); + if (!pmu) + return -ENOMEM; + + pmu->assoc_id = assoc_id; + pmu->index = index; + pmu->type = type; + pmu->base = regs->pmu; + dev = &pmu->dev; + device_initialize(dev); + device_set_pm_not_required(dev); + dev->parent = parent; + dev->bus = &cxl_bus_type; + dev->type = &cxl_pmu_type; + switch (pmu->type) { + case CXL_PMU_MEMDEV: + rc = dev_set_name(dev, "pmu_mem%d.%d", assoc_id, index); + break; + } + if (rc) + goto err; + + rc = device_add(dev); + if (rc) + goto err; + + return devm_add_action_or_reset(parent, remove_dev, dev); + +err: + put_device(&pmu->dev); + return rc; +} +EXPORT_SYMBOL_NS_GPL(devm_cxl_pmu_add, CXL); diff --git a/drivers/cxl/core/port.c b/drivers/cxl/core/port.c index e7c284c890bc111eeefd19e369e996b4b6966f3f..724be8448eb4a52542bc3e0cd6b16de508f7979f 100644 --- a/drivers/cxl/core/port.c +++ b/drivers/cxl/core/port.c @@ -56,6 +56,8 @@ static int cxl_device_id(const struct device *dev) return CXL_DEVICE_MEMORY_EXPANDER; if (dev->type == CXL_REGION_TYPE()) return CXL_DEVICE_REGION; + if (dev->type == &cxl_pmu_type) + return CXL_DEVICE_PMU; return 0; } @@ -117,9 +119,9 @@ static ssize_t target_type_show(struct device *dev, struct cxl_decoder *cxld = to_cxl_decoder(dev); switch (cxld->target_type) { - case CXL_DECODER_ACCELERATOR: + case CXL_DECODER_DEVMEM: return sysfs_emit(buf, "accelerator\n"); - case CXL_DECODER_EXPANDER: + case CXL_DECODER_HOSTONLYMEM: return sysfs_emit(buf, "expander\n"); } return -ENXIO; @@ -561,9 +563,9 @@ static void unregister_port(void *_port) * unregistered while holding their parent port lock. */ if (!parent) - lock_dev = port->uport; + lock_dev = port->uport_dev; else if (is_cxl_root(parent)) - lock_dev = parent->uport; + lock_dev = parent->uport_dev; else lock_dev = &parent->dev; @@ -583,7 +585,8 @@ static int devm_cxl_link_uport(struct device *host, struct cxl_port *port) { int rc; - rc = sysfs_create_link(&port->dev.kobj, &port->uport->kobj, "uport"); + rc = sysfs_create_link(&port->dev.kobj, &port->uport_dev->kobj, + "uport"); if (rc) return rc; return devm_add_action_or_reset(host, cxl_unlink_uport, port); @@ -605,7 +608,7 @@ static int devm_cxl_link_parent_dport(struct device *host, if (!parent_dport) return 0; - rc = sysfs_create_link(&port->dev.kobj, &parent_dport->dport->kobj, + rc = sysfs_create_link(&port->dev.kobj, &parent_dport->dport_dev->kobj, "parent_dport"); if (rc) return rc; @@ -614,7 +617,7 @@ static int devm_cxl_link_parent_dport(struct device *host, static struct lock_class_key cxl_port_key; -static struct cxl_port *cxl_port_alloc(struct device *uport, +static struct cxl_port *cxl_port_alloc(struct device *uport_dev, resource_size_t component_reg_phys, struct cxl_dport *parent_dport) { @@ -630,7 +633,7 @@ static struct cxl_port *cxl_port_alloc(struct device *uport, if (rc < 0) goto err; port->id = rc; - port->uport = uport; + port->uport_dev = uport_dev; /* * The top-level cxl_port "cxl_root" does not have a cxl_port as @@ -658,12 +661,13 @@ static struct cxl_port *cxl_port_alloc(struct device *uport, if (iter->host_bridge) port->host_bridge = iter->host_bridge; else if (parent_dport->rch) - port->host_bridge = parent_dport->dport; + port->host_bridge = parent_dport->dport_dev; else - port->host_bridge = iter->uport; - dev_dbg(uport, "host-bridge: %s\n", dev_name(port->host_bridge)); + port->host_bridge = iter->uport_dev; + dev_dbg(uport_dev, "host-bridge: %s\n", + dev_name(port->host_bridge)); } else - dev->parent = uport; + dev->parent = uport_dev; port->component_reg_phys = component_reg_phys; ida_init(&port->decoder_ida); @@ -686,8 +690,38 @@ static struct cxl_port *cxl_port_alloc(struct device *uport, return ERR_PTR(rc); } +static int cxl_setup_comp_regs(struct device *dev, struct cxl_register_map *map, + resource_size_t component_reg_phys) +{ + if (component_reg_phys == CXL_RESOURCE_NONE) + return 0; + + *map = (struct cxl_register_map) { + .dev = dev, + .reg_type = CXL_REGLOC_RBI_COMPONENT, + .resource = component_reg_phys, + .max_size = CXL_COMPONENT_REG_BLOCK_SIZE, + }; + + return cxl_setup_regs(map); +} + +static inline int cxl_port_setup_regs(struct cxl_port *port, + resource_size_t component_reg_phys) +{ + return cxl_setup_comp_regs(&port->dev, &port->comp_map, + component_reg_phys); +} + +static inline int cxl_dport_setup_regs(struct cxl_dport *dport, + resource_size_t component_reg_phys) +{ + return cxl_setup_comp_regs(dport->dport_dev, &dport->comp_map, + component_reg_phys); +} + static struct cxl_port *__devm_cxl_add_port(struct device *host, - struct device *uport, + struct device *uport_dev, resource_size_t component_reg_phys, struct cxl_dport *parent_dport) { @@ -695,12 +729,12 @@ static struct cxl_port *__devm_cxl_add_port(struct device *host, struct device *dev; int rc; - port = cxl_port_alloc(uport, component_reg_phys, parent_dport); + port = cxl_port_alloc(uport_dev, component_reg_phys, parent_dport); if (IS_ERR(port)) return port; dev = &port->dev; - if (is_cxl_memdev(uport)) + if (is_cxl_memdev(uport_dev)) rc = dev_set_name(dev, "endpoint%d", port->id); else if (parent_dport) rc = dev_set_name(dev, "port%d", port->id); @@ -709,6 +743,10 @@ static struct cxl_port *__devm_cxl_add_port(struct device *host, if (rc) goto err; + rc = cxl_port_setup_regs(port, component_reg_phys); + if (rc) + goto err; + rc = device_add(dev); if (rc) goto err; @@ -735,28 +773,29 @@ static struct cxl_port *__devm_cxl_add_port(struct device *host, /** * devm_cxl_add_port - register a cxl_port in CXL memory decode hierarchy * @host: host device for devm operations - * @uport: "physical" device implementing this upstream port + * @uport_dev: "physical" device implementing this upstream port * @component_reg_phys: (optional) for configurable cxl_port instances * @parent_dport: next hop up in the CXL memory decode hierarchy */ -struct cxl_port *devm_cxl_add_port(struct device *host, struct device *uport, +struct cxl_port *devm_cxl_add_port(struct device *host, + struct device *uport_dev, resource_size_t component_reg_phys, struct cxl_dport *parent_dport) { struct cxl_port *port, *parent_port; - port = __devm_cxl_add_port(host, uport, component_reg_phys, + port = __devm_cxl_add_port(host, uport_dev, component_reg_phys, parent_dport); parent_port = parent_dport ? parent_dport->port : NULL; if (IS_ERR(port)) { - dev_dbg(uport, "Failed to add%s%s%s: %ld\n", + dev_dbg(uport_dev, "Failed to add%s%s%s: %ld\n", parent_port ? " port to " : "", parent_port ? dev_name(&parent_port->dev) : "", parent_port ? "" : " root port", PTR_ERR(port)); } else { - dev_dbg(uport, "%s added%s%s%s\n", + dev_dbg(uport_dev, "%s added%s%s%s\n", dev_name(&port->dev), parent_port ? " to " : "", parent_port ? dev_name(&parent_port->dev) : "", @@ -773,33 +812,34 @@ struct pci_bus *cxl_port_to_pci_bus(struct cxl_port *port) if (is_cxl_root(port)) return NULL; - if (dev_is_pci(port->uport)) { - struct pci_dev *pdev = to_pci_dev(port->uport); + if (dev_is_pci(port->uport_dev)) { + struct pci_dev *pdev = to_pci_dev(port->uport_dev); return pdev->subordinate; } - return xa_load(&cxl_root_buses, (unsigned long)port->uport); + return xa_load(&cxl_root_buses, (unsigned long)port->uport_dev); } EXPORT_SYMBOL_NS_GPL(cxl_port_to_pci_bus, CXL); -static void unregister_pci_bus(void *uport) +static void unregister_pci_bus(void *uport_dev) { - xa_erase(&cxl_root_buses, (unsigned long)uport); + xa_erase(&cxl_root_buses, (unsigned long)uport_dev); } -int devm_cxl_register_pci_bus(struct device *host, struct device *uport, +int devm_cxl_register_pci_bus(struct device *host, struct device *uport_dev, struct pci_bus *bus) { int rc; - if (dev_is_pci(uport)) + if (dev_is_pci(uport_dev)) return -EINVAL; - rc = xa_insert(&cxl_root_buses, (unsigned long)uport, bus, GFP_KERNEL); + rc = xa_insert(&cxl_root_buses, (unsigned long)uport_dev, bus, + GFP_KERNEL); if (rc) return rc; - return devm_add_action_or_reset(host, unregister_pci_bus, uport); + return devm_add_action_or_reset(host, unregister_pci_bus, uport_dev); } EXPORT_SYMBOL_NS_GPL(devm_cxl_register_pci_bus, CXL); @@ -847,22 +887,22 @@ static struct cxl_dport *find_dport(struct cxl_port *port, int id) return NULL; } -static int add_dport(struct cxl_port *port, struct cxl_dport *new) +static int add_dport(struct cxl_port *port, struct cxl_dport *dport) { struct cxl_dport *dup; int rc; device_lock_assert(&port->dev); - dup = find_dport(port, new->port_id); + dup = find_dport(port, dport->port_id); if (dup) { dev_err(&port->dev, "unable to add dport%d-%s non-unique port id (%s)\n", - new->port_id, dev_name(new->dport), - dev_name(dup->dport)); + dport->port_id, dev_name(dport->dport_dev), + dev_name(dup->dport_dev)); return -EBUSY; } - rc = xa_insert(&port->dports, (unsigned long)new->dport, new, + rc = xa_insert(&port->dports, (unsigned long)dport->dport_dev, dport, GFP_KERNEL); if (rc) return rc; @@ -895,8 +935,8 @@ static void cxl_dport_remove(void *data) struct cxl_dport *dport = data; struct cxl_port *port = dport->port; - xa_erase(&port->dports, (unsigned long) dport->dport); - put_device(dport->dport); + xa_erase(&port->dports, (unsigned long) dport->dport_dev); + put_device(dport->dport_dev); } static void cxl_dport_unlink(void *data) @@ -920,7 +960,7 @@ __devm_cxl_add_dport(struct cxl_port *port, struct device *dport_dev, int rc; if (is_cxl_root(port)) - host = port->uport; + host = port->uport_dev; else host = &port->dev; @@ -938,13 +978,29 @@ __devm_cxl_add_dport(struct cxl_port *port, struct device *dport_dev, if (!dport) return ERR_PTR(-ENOMEM); - dport->dport = dport_dev; + if (rcrb != CXL_RESOURCE_NONE) { + dport->rcrb.base = rcrb; + component_reg_phys = __rcrb_to_component(dport_dev, &dport->rcrb, + CXL_RCRB_DOWNSTREAM); + if (component_reg_phys == CXL_RESOURCE_NONE) { + dev_warn(dport_dev, "Invalid Component Registers in RCRB"); + return ERR_PTR(-ENXIO); + } + + dport->rch = true; + } + + if (component_reg_phys != CXL_RESOURCE_NONE) + dev_dbg(dport_dev, "Component Registers found for dport: %pa\n", + &component_reg_phys); + + dport->dport_dev = dport_dev; dport->port_id = port_id; - dport->component_reg_phys = component_reg_phys; dport->port = port; - if (rcrb != CXL_RESOURCE_NONE) - dport->rch = true; - dport->rcrb = rcrb; + + rc = cxl_dport_setup_regs(dport, component_reg_phys); + if (rc) + return ERR_PTR(rc); cond_cxl_root_lock(port); rc = add_dport(port, dport); @@ -1004,14 +1060,12 @@ EXPORT_SYMBOL_NS_GPL(devm_cxl_add_dport, CXL); * @port: the cxl_port that references this dport * @dport_dev: firmware or PCI device representing the dport * @port_id: identifier for this dport in a decoder's target list - * @component_reg_phys: optional location of CXL component registers * @rcrb: mandatory location of a Root Complex Register Block * * See CXL 3.0 9.11.8 CXL Devices Attached to an RCH */ struct cxl_dport *devm_cxl_add_rch_dport(struct cxl_port *port, struct device *dport_dev, int port_id, - resource_size_t component_reg_phys, resource_size_t rcrb) { struct cxl_dport *dport; @@ -1022,7 +1076,7 @@ struct cxl_dport *devm_cxl_add_rch_dport(struct cxl_port *port, } dport = __devm_cxl_add_dport(port, dport_dev, port_id, - component_reg_phys, rcrb); + CXL_RESOURCE_NONE, rcrb); if (IS_ERR(dport)) { dev_dbg(dport_dev, "failed to add RCH dport to %s: %ld\n", dev_name(&port->dev), PTR_ERR(dport)); @@ -1161,7 +1215,7 @@ static struct device *grandparent(struct device *dev) static void delete_endpoint(void *data) { struct cxl_memdev *cxlmd = data; - struct cxl_port *endpoint = dev_get_drvdata(&cxlmd->dev); + struct cxl_port *endpoint = cxlmd->endpoint; struct cxl_port *parent_port; struct device *parent; @@ -1176,6 +1230,7 @@ static void delete_endpoint(void *data) devm_release_action(parent, cxl_unlink_uport, endpoint); devm_release_action(parent, unregister_port, endpoint); } + cxlmd->endpoint = NULL; device_unlock(parent); put_device(parent); out: @@ -1187,7 +1242,7 @@ int cxl_endpoint_autoremove(struct cxl_memdev *cxlmd, struct cxl_port *endpoint) struct device *dev = &cxlmd->dev; get_device(&endpoint->dev); - dev_set_drvdata(dev, endpoint); + cxlmd->endpoint = endpoint; cxlmd->depth = endpoint->depth; return devm_add_action_or_reset(dev, delete_endpoint, cxlmd); } @@ -1363,7 +1418,7 @@ static int add_port_attach_ep(struct cxl_memdev *cxlmd, rc = PTR_ERR(port); else { dev_dbg(&cxlmd->dev, "add to new port %s:%s\n", - dev_name(&port->dev), dev_name(port->uport)); + dev_name(&port->dev), dev_name(port->uport_dev)); rc = cxl_add_ep(dport, &cxlmd->dev); if (rc == -EBUSY) { /* @@ -1425,7 +1480,8 @@ int devm_cxl_enumerate_ports(struct cxl_memdev *cxlmd) if (port) { dev_dbg(&cxlmd->dev, "found already registered port %s:%s\n", - dev_name(&port->dev), dev_name(port->uport)); + dev_name(&port->dev), + dev_name(port->uport_dev)); rc = cxl_add_ep(dport, &cxlmd->dev); /* @@ -1465,6 +1521,13 @@ int devm_cxl_enumerate_ports(struct cxl_memdev *cxlmd) } EXPORT_SYMBOL_NS_GPL(devm_cxl_enumerate_ports, CXL); +struct cxl_port *cxl_pci_find_port(struct pci_dev *pdev, + struct cxl_dport **dport) +{ + return find_cxl_port(pdev->dev.parent, dport); +} +EXPORT_SYMBOL_NS_GPL(cxl_pci_find_port, CXL); + struct cxl_port *cxl_mem_find_port(struct cxl_memdev *cxlmd, struct cxl_dport **dport) { @@ -1550,7 +1613,7 @@ static int cxl_decoder_init(struct cxl_port *port, struct cxl_decoder *cxld) /* Pre initialize an "empty" decoder */ cxld->interleave_ways = 1; cxld->interleave_granularity = PAGE_SIZE; - cxld->target_type = CXL_DECODER_EXPANDER; + cxld->target_type = CXL_DECODER_HOSTONLYMEM; cxld->hpa_range = (struct range) { .start = 0, .end = -1, diff --git a/drivers/cxl/core/region.c b/drivers/cxl/core/region.c index f822de44bee0a15beb65ff75ba928bd85f0e19d9..e115ba382e0445dc6c8ec1881e0e95ec307c4918 100644 --- a/drivers/cxl/core/region.c +++ b/drivers/cxl/core/region.c @@ -125,10 +125,38 @@ static struct cxl_region_ref *cxl_rr_load(struct cxl_port *port, return xa_load(&port->regions, (unsigned long)cxlr); } +static int cxl_region_invalidate_memregion(struct cxl_region *cxlr) +{ + if (!cpu_cache_has_invalidate_memregion()) { + if (IS_ENABLED(CONFIG_CXL_REGION_INVALIDATION_TEST)) { + dev_warn_once( + &cxlr->dev, + "Bypassing cpu_cache_invalidate_memregion() for testing!\n"); + return 0; + } else { + dev_err(&cxlr->dev, + "Failed to synchronize CPU cache state\n"); + return -ENXIO; + } + } + + cpu_cache_invalidate_memregion(IORES_DESC_CXL); + return 0; +} + static int cxl_region_decode_reset(struct cxl_region *cxlr, int count) { struct cxl_region_params *p = &cxlr->params; - int i; + int i, rc = 0; + + /* + * Before region teardown attempt to flush, and if the flush + * fails cancel the region teardown for data consistency + * concerns + */ + rc = cxl_region_invalidate_memregion(cxlr); + if (rc) + return rc; for (i = count - 1; i >= 0; i--) { struct cxl_endpoint_decoder *cxled = p->targets[i]; @@ -136,7 +164,6 @@ static int cxl_region_decode_reset(struct cxl_region *cxlr, int count) struct cxl_port *iter = cxled_to_port(cxled); struct cxl_dev_state *cxlds = cxlmd->cxlds; struct cxl_ep *ep; - int rc = 0; if (cxlds->rcd) goto endpoint_reset; @@ -155,14 +182,19 @@ static int cxl_region_decode_reset(struct cxl_region *cxlr, int count) rc = cxld->reset(cxld); if (rc) return rc; + set_bit(CXL_REGION_F_NEEDS_RESET, &cxlr->flags); } endpoint_reset: rc = cxled->cxld.reset(&cxled->cxld); if (rc) return rc; + set_bit(CXL_REGION_F_NEEDS_RESET, &cxlr->flags); } + /* all decoders associated with this region have been torn down */ + clear_bit(CXL_REGION_F_NEEDS_RESET, &cxlr->flags); + return 0; } @@ -256,9 +288,19 @@ static ssize_t commit_store(struct device *dev, struct device_attribute *attr, goto out; } - if (commit) + /* + * Invalidate caches before region setup to drop any speculative + * consumption of this address space + */ + rc = cxl_region_invalidate_memregion(cxlr); + if (rc) + return rc; + + if (commit) { rc = cxl_region_decode_commit(cxlr); - else { + if (rc == 0) + p->state = CXL_CONFIG_COMMIT; + } else { p->state = CXL_CONFIG_RESET_PENDING; up_write(&cxl_region_rwsem); device_release_driver(&cxlr->dev); @@ -268,18 +310,20 @@ static ssize_t commit_store(struct device *dev, struct device_attribute *attr, * The lock was dropped, so need to revalidate that the reset is * still pending. */ - if (p->state == CXL_CONFIG_RESET_PENDING) + if (p->state == CXL_CONFIG_RESET_PENDING) { rc = cxl_region_decode_reset(cxlr, p->interleave_ways); + /* + * Revert to committed since there may still be active + * decoders associated with this region, or move forward + * to active to mark the reset successful + */ + if (rc) + p->state = CXL_CONFIG_COMMIT; + else + p->state = CXL_CONFIG_ACTIVE; + } } - if (rc) - goto out; - - if (commit) - p->state = CXL_CONFIG_COMMIT; - else if (p->state == CXL_CONFIG_RESET_PENDING) - p->state = CXL_CONFIG_ACTIVE; - out: up_write(&cxl_region_rwsem); @@ -809,6 +853,18 @@ static int cxl_rr_alloc_decoder(struct cxl_port *port, struct cxl_region *cxlr, return -EBUSY; } + /* + * Endpoints should already match the region type, but backstop that + * assumption with an assertion. Switch-decoders change mapping-type + * based on what is mapped when they are assigned to a region. + */ + dev_WARN_ONCE(&cxlr->dev, + port == cxled_to_port(cxled) && + cxld->target_type != cxlr->type, + "%s:%s mismatch decoder type %d -> %d\n", + dev_name(&cxled_to_memdev(cxled)->dev), + dev_name(&cxld->dev), cxld->target_type, cxlr->type); + cxld->target_type = cxlr->type; cxl_rr->decoder = cxld; return 0; } @@ -906,10 +962,10 @@ static int cxl_port_attach_region(struct cxl_port *port, dev_dbg(&cxlr->dev, "%s:%s %s add: %s:%s @ %d next: %s nr_eps: %d nr_targets: %d\n", - dev_name(port->uport), dev_name(&port->dev), + dev_name(port->uport_dev), dev_name(&port->dev), dev_name(&cxld->dev), dev_name(&cxlmd->dev), dev_name(&cxled->cxld.dev), pos, - ep ? ep->next ? dev_name(ep->next->uport) : + ep ? ep->next ? dev_name(ep->next->uport_dev) : dev_name(&cxlmd->dev) : "none", cxl_rr->nr_eps, cxl_rr->nr_targets); @@ -984,7 +1040,7 @@ static int check_last_peer(struct cxl_endpoint_decoder *cxled, */ if (pos < distance) { dev_dbg(&cxlr->dev, "%s:%s: cannot host %s:%s at %d\n", - dev_name(port->uport), dev_name(&port->dev), + dev_name(port->uport_dev), dev_name(&port->dev), dev_name(&cxlmd->dev), dev_name(&cxled->cxld.dev), pos); return -ENXIO; } @@ -994,7 +1050,7 @@ static int check_last_peer(struct cxl_endpoint_decoder *cxled, if (ep->dport != ep_peer->dport) { dev_dbg(&cxlr->dev, "%s:%s: %s:%s pos %d mismatched peer %s:%s\n", - dev_name(port->uport), dev_name(&port->dev), + dev_name(port->uport_dev), dev_name(&port->dev), dev_name(&cxlmd->dev), dev_name(&cxled->cxld.dev), pos, dev_name(&cxlmd_peer->dev), dev_name(&cxled_peer->cxld.dev)); @@ -1026,7 +1082,7 @@ static int cxl_port_setup_targets(struct cxl_port *port, */ if (!is_power_of_2(cxl_rr->nr_targets)) { dev_dbg(&cxlr->dev, "%s:%s: invalid target count %d\n", - dev_name(port->uport), dev_name(&port->dev), + dev_name(port->uport_dev), dev_name(&port->dev), cxl_rr->nr_targets); return -EINVAL; } @@ -1076,7 +1132,7 @@ static int cxl_port_setup_targets(struct cxl_port *port, rc = granularity_to_eig(parent_ig, &peig); if (rc) { dev_dbg(&cxlr->dev, "%s:%s: invalid parent granularity: %d\n", - dev_name(parent_port->uport), + dev_name(parent_port->uport_dev), dev_name(&parent_port->dev), parent_ig); return rc; } @@ -1084,7 +1140,7 @@ static int cxl_port_setup_targets(struct cxl_port *port, rc = ways_to_eiw(parent_iw, &peiw); if (rc) { dev_dbg(&cxlr->dev, "%s:%s: invalid parent interleave: %d\n", - dev_name(parent_port->uport), + dev_name(parent_port->uport_dev), dev_name(&parent_port->dev), parent_iw); return rc; } @@ -1093,7 +1149,7 @@ static int cxl_port_setup_targets(struct cxl_port *port, rc = ways_to_eiw(iw, &eiw); if (rc) { dev_dbg(&cxlr->dev, "%s:%s: invalid port interleave: %d\n", - dev_name(port->uport), dev_name(&port->dev), iw); + dev_name(port->uport_dev), dev_name(&port->dev), iw); return rc; } @@ -1113,7 +1169,7 @@ static int cxl_port_setup_targets(struct cxl_port *port, rc = eig_to_granularity(eig, &ig); if (rc) { dev_dbg(&cxlr->dev, "%s:%s: invalid interleave: %d\n", - dev_name(port->uport), dev_name(&port->dev), + dev_name(port->uport_dev), dev_name(&port->dev), 256 << eig); return rc; } @@ -1126,11 +1182,11 @@ static int cxl_port_setup_targets(struct cxl_port *port, ((cxld->flags & CXL_DECODER_F_ENABLE) == 0)) { dev_err(&cxlr->dev, "%s:%s %s expected iw: %d ig: %d %pr\n", - dev_name(port->uport), dev_name(&port->dev), + dev_name(port->uport_dev), dev_name(&port->dev), __func__, iw, ig, p->res); dev_err(&cxlr->dev, "%s:%s %s got iw: %d ig: %d state: %s %#llx:%#llx\n", - dev_name(port->uport), dev_name(&port->dev), + dev_name(port->uport_dev), dev_name(&port->dev), __func__, cxld->interleave_ways, cxld->interleave_granularity, (cxld->flags & CXL_DECODER_F_ENABLE) ? @@ -1147,22 +1203,22 @@ static int cxl_port_setup_targets(struct cxl_port *port, .end = p->res->end, }; } - dev_dbg(&cxlr->dev, "%s:%s iw: %d ig: %d\n", dev_name(port->uport), + dev_dbg(&cxlr->dev, "%s:%s iw: %d ig: %d\n", dev_name(port->uport_dev), dev_name(&port->dev), iw, ig); add_target: if (cxl_rr->nr_targets_set == cxl_rr->nr_targets) { dev_dbg(&cxlr->dev, "%s:%s: targets full trying to add %s:%s at %d\n", - dev_name(port->uport), dev_name(&port->dev), + dev_name(port->uport_dev), dev_name(&port->dev), dev_name(&cxlmd->dev), dev_name(&cxled->cxld.dev), pos); return -ENXIO; } if (test_bit(CXL_REGION_F_AUTO, &cxlr->flags)) { if (cxlsd->target[cxl_rr->nr_targets_set] != ep->dport) { dev_dbg(&cxlr->dev, "%s:%s: %s expected %s at %d\n", - dev_name(port->uport), dev_name(&port->dev), + dev_name(port->uport_dev), dev_name(&port->dev), dev_name(&cxlsd->cxld.dev), - dev_name(ep->dport->dport), + dev_name(ep->dport->dport_dev), cxl_rr->nr_targets_set); return -ENXIO; } @@ -1172,8 +1228,8 @@ static int cxl_port_setup_targets(struct cxl_port *port, out_target_set: cxl_rr->nr_targets_set += inc; dev_dbg(&cxlr->dev, "%s:%s target[%d] = %s for %s:%s @ %d\n", - dev_name(port->uport), dev_name(&port->dev), - cxl_rr->nr_targets_set - 1, dev_name(ep->dport->dport), + dev_name(port->uport_dev), dev_name(&port->dev), + cxl_rr->nr_targets_set - 1, dev_name(ep->dport->dport_dev), dev_name(&cxlmd->dev), dev_name(&cxled->cxld.dev), pos); return 0; @@ -1492,7 +1548,7 @@ static int cmp_decode_pos(const void *a, const void *b) if (!dev) { struct range *range = &cxled_a->cxld.hpa_range; - dev_err(port->uport, + dev_err(port->uport_dev, "failed to find decoder that maps %#llx-%#llx\n", range->start, range->end); goto err; @@ -1507,14 +1563,15 @@ static int cmp_decode_pos(const void *a, const void *b) put_device(dev); if (a_pos < 0 || b_pos < 0) { - dev_err(port->uport, + dev_err(port->uport_dev, "failed to find shared decoder for %s and %s\n", dev_name(cxlmd_a->dev.parent), dev_name(cxlmd_b->dev.parent)); goto err; } - dev_dbg(port->uport, "%s comes %s %s\n", dev_name(cxlmd_a->dev.parent), + dev_dbg(port->uport_dev, "%s comes %s %s\n", + dev_name(cxlmd_a->dev.parent), a_pos - b_pos < 0 ? "before" : "after", dev_name(cxlmd_b->dev.parent)); @@ -1674,7 +1731,6 @@ static int cxl_region_attach(struct cxl_region *cxlr, if (rc) goto err_decrement; p->state = CXL_CONFIG_ACTIVE; - set_bit(CXL_REGION_F_INCOHERENT, &cxlr->flags); } cxled->cxld.interleave_ways = p->interleave_ways; @@ -2059,11 +2115,11 @@ static struct cxl_region *devm_cxl_add_region(struct cxl_root_decoder *cxlrd, if (rc) goto err; - rc = devm_add_action_or_reset(port->uport, unregister_region, cxlr); + rc = devm_add_action_or_reset(port->uport_dev, unregister_region, cxlr); if (rc) return ERR_PTR(rc); - dev_dbg(port->uport, "%s: created %s\n", + dev_dbg(port->uport_dev, "%s: created %s\n", dev_name(&cxlrd->cxlsd.cxld.dev), dev_name(dev)); return cxlr; @@ -2103,7 +2159,7 @@ static struct cxl_region *__create_region(struct cxl_root_decoder *cxlrd, return ERR_PTR(-EBUSY); } - return devm_cxl_add_region(cxlrd, id, mode, CXL_DECODER_EXPANDER); + return devm_cxl_add_region(cxlrd, id, mode, CXL_DECODER_HOSTONLYMEM); } static ssize_t create_pmem_region_store(struct device *dev, @@ -2191,7 +2247,7 @@ static ssize_t delete_region_store(struct device *dev, if (IS_ERR(cxlr)) return PTR_ERR(cxlr); - devm_release_action(port->uport, unregister_region, cxlr); + devm_release_action(port->uport_dev, unregister_region, cxlr); put_device(&cxlr->dev); return len; @@ -2356,7 +2412,8 @@ int cxl_get_poison_by_endpoint(struct cxl_port *port) rc = device_for_each_child(&port->dev, &ctx, poison_by_decoder); if (rc == 1) - rc = cxl_get_poison_unmapped(to_cxl_memdev(port->uport), &ctx); + rc = cxl_get_poison_unmapped(to_cxl_memdev(port->uport_dev), + &ctx); up_read(&cxl_region_rwsem); return rc; @@ -2732,7 +2789,7 @@ static struct cxl_region *construct_region(struct cxl_root_decoder *cxlrd, err: up_write(&cxl_region_rwsem); - devm_release_action(port->uport, unregister_region, cxlr); + devm_release_action(port->uport_dev, unregister_region, cxlr); return ERR_PTR(rc); } @@ -2803,30 +2860,6 @@ int cxl_add_to_region(struct cxl_port *root, struct cxl_endpoint_decoder *cxled) } EXPORT_SYMBOL_NS_GPL(cxl_add_to_region, CXL); -static int cxl_region_invalidate_memregion(struct cxl_region *cxlr) -{ - if (!test_bit(CXL_REGION_F_INCOHERENT, &cxlr->flags)) - return 0; - - if (!cpu_cache_has_invalidate_memregion()) { - if (IS_ENABLED(CONFIG_CXL_REGION_INVALIDATION_TEST)) { - dev_warn_once( - &cxlr->dev, - "Bypassing cpu_cache_invalidate_memregion() for testing!\n"); - clear_bit(CXL_REGION_F_INCOHERENT, &cxlr->flags); - return 0; - } else { - dev_err(&cxlr->dev, - "Failed to synchronize CPU cache state\n"); - return -ENXIO; - } - } - - cpu_cache_invalidate_memregion(IORES_DESC_CXL); - clear_bit(CXL_REGION_F_INCOHERENT, &cxlr->flags); - return 0; -} - static int is_system_ram(struct resource *res, void *arg) { struct cxl_region *cxlr = arg; @@ -2854,7 +2887,12 @@ static int cxl_region_probe(struct device *dev) goto out; } - rc = cxl_region_invalidate_memregion(cxlr); + if (test_bit(CXL_REGION_F_NEEDS_RESET, &cxlr->flags)) { + dev_err(&cxlr->dev, + "failed to activate, re-commit region and retry\n"); + rc = -ENXIO; + goto out; + } /* * From this point on any path that changes the region's state away from diff --git a/drivers/cxl/core/regs.c b/drivers/cxl/core/regs.c index 1476a0299c9b688e739ddb622072ef6dcb256f9d..6281127b3e9d97223d9a4c733c98b9a1fb2271c7 100644 --- a/drivers/cxl/core/regs.c +++ b/drivers/cxl/core/regs.c @@ -6,6 +6,7 @@ #include #include #include +#include #include "core.h" @@ -199,11 +200,13 @@ void __iomem *devm_cxl_iomap_block(struct device *dev, resource_size_t addr, return ret_val; } -int cxl_map_component_regs(struct device *dev, struct cxl_component_regs *regs, - struct cxl_register_map *map, unsigned long map_mask) +int cxl_map_component_regs(const struct cxl_register_map *map, + struct cxl_component_regs *regs, + unsigned long map_mask) { + struct device *dev = map->dev; struct mapinfo { - struct cxl_reg_map *rmap; + const struct cxl_reg_map *rmap; void __iomem **addr; } mapinfo[] = { { &map->component_map.hdm_decoder, ®s->hdm_decoder }, @@ -231,13 +234,13 @@ int cxl_map_component_regs(struct device *dev, struct cxl_component_regs *regs, } EXPORT_SYMBOL_NS_GPL(cxl_map_component_regs, CXL); -int cxl_map_device_regs(struct device *dev, - struct cxl_device_regs *regs, - struct cxl_register_map *map) +int cxl_map_device_regs(const struct cxl_register_map *map, + struct cxl_device_regs *regs) { + struct device *dev = map->dev; resource_size_t phys_addr = map->resource; struct mapinfo { - struct cxl_reg_map *rmap; + const struct cxl_reg_map *rmap; void __iomem **addr; } mapinfo[] = { { &map->device_map.status, ®s->status, }, @@ -286,23 +289,30 @@ static bool cxl_decode_regblock(struct pci_dev *pdev, u32 reg_lo, u32 reg_hi, } /** - * cxl_find_regblock() - Locate register blocks by type + * cxl_find_regblock_instance() - Locate a register block by type / index * @pdev: The CXL PCI device to enumerate. * @type: Register Block Indicator id * @map: Enumeration output, clobbered on error + * @index: Index into which particular instance of a regblock wanted in the + * order found in register locator DVSEC. * * Return: 0 if register block enumerated, negative error code otherwise * * A CXL DVSEC may point to one or more register blocks, search for them - * by @type. + * by @type and @index. */ -int cxl_find_regblock(struct pci_dev *pdev, enum cxl_regloc_type type, - struct cxl_register_map *map) +int cxl_find_regblock_instance(struct pci_dev *pdev, enum cxl_regloc_type type, + struct cxl_register_map *map, int index) { u32 regloc_size, regblocks; + int instance = 0; int regloc, i; - map->resource = CXL_RESOURCE_NONE; + *map = (struct cxl_register_map) { + .dev = &pdev->dev, + .resource = CXL_RESOURCE_NONE, + }; + regloc = pci_find_dvsec_capability(pdev, PCI_DVSEC_VENDOR_ID_CXL, CXL_DVSEC_REG_LOCATOR); if (!regloc) @@ -323,20 +333,148 @@ int cxl_find_regblock(struct pci_dev *pdev, enum cxl_regloc_type type, if (!cxl_decode_regblock(pdev, reg_lo, reg_hi, map)) continue; - if (map->reg_type == type) - return 0; + if (map->reg_type == type) { + if (index == instance) + return 0; + instance++; + } } map->resource = CXL_RESOURCE_NONE; return -ENODEV; } +EXPORT_SYMBOL_NS_GPL(cxl_find_regblock_instance, CXL); + +/** + * cxl_find_regblock() - Locate register blocks by type + * @pdev: The CXL PCI device to enumerate. + * @type: Register Block Indicator id + * @map: Enumeration output, clobbered on error + * + * Return: 0 if register block enumerated, negative error code otherwise + * + * A CXL DVSEC may point to one or more register blocks, search for them + * by @type. + */ +int cxl_find_regblock(struct pci_dev *pdev, enum cxl_regloc_type type, + struct cxl_register_map *map) +{ + return cxl_find_regblock_instance(pdev, type, map, 0); +} EXPORT_SYMBOL_NS_GPL(cxl_find_regblock, CXL); -resource_size_t cxl_rcrb_to_component(struct device *dev, - resource_size_t rcrb, - enum cxl_rcrb which) +/** + * cxl_count_regblock() - Count instances of a given regblock type. + * @pdev: The CXL PCI device to enumerate. + * @type: Register Block Indicator id + * + * Some regblocks may be repeated. Count how many instances. + * + * Return: count of matching regblocks. + */ +int cxl_count_regblock(struct pci_dev *pdev, enum cxl_regloc_type type) +{ + struct cxl_register_map map; + int rc, count = 0; + + while (1) { + rc = cxl_find_regblock_instance(pdev, type, &map, count); + if (rc) + return count; + count++; + } +} +EXPORT_SYMBOL_NS_GPL(cxl_count_regblock, CXL); + +int cxl_map_pmu_regs(struct pci_dev *pdev, struct cxl_pmu_regs *regs, + struct cxl_register_map *map) +{ + struct device *dev = &pdev->dev; + resource_size_t phys_addr; + + phys_addr = map->resource; + regs->pmu = devm_cxl_iomap_block(dev, phys_addr, CXL_PMU_REGMAP_SIZE); + if (!regs->pmu) + return -ENOMEM; + + return 0; +} +EXPORT_SYMBOL_NS_GPL(cxl_map_pmu_regs, CXL); + +static int cxl_map_regblock(struct cxl_register_map *map) +{ + struct device *dev = map->dev; + + map->base = ioremap(map->resource, map->max_size); + if (!map->base) { + dev_err(dev, "failed to map registers\n"); + return -ENOMEM; + } + + dev_dbg(dev, "Mapped CXL Memory Device resource %pa\n", &map->resource); + return 0; +} + +static void cxl_unmap_regblock(struct cxl_register_map *map) +{ + iounmap(map->base); + map->base = NULL; +} + +static int cxl_probe_regs(struct cxl_register_map *map) +{ + struct cxl_component_reg_map *comp_map; + struct cxl_device_reg_map *dev_map; + struct device *dev = map->dev; + void __iomem *base = map->base; + + switch (map->reg_type) { + case CXL_REGLOC_RBI_COMPONENT: + comp_map = &map->component_map; + cxl_probe_component_regs(dev, base, comp_map); + dev_dbg(dev, "Set up component registers\n"); + break; + case CXL_REGLOC_RBI_MEMDEV: + dev_map = &map->device_map; + cxl_probe_device_regs(dev, base, dev_map); + if (!dev_map->status.valid || !dev_map->mbox.valid || + !dev_map->memdev.valid) { + dev_err(dev, "registers not found: %s%s%s\n", + !dev_map->status.valid ? "status " : "", + !dev_map->mbox.valid ? "mbox " : "", + !dev_map->memdev.valid ? "memdev " : ""); + return -ENXIO; + } + + dev_dbg(dev, "Probing device registers...\n"); + break; + default: + break; + } + + return 0; +} + +int cxl_setup_regs(struct cxl_register_map *map) +{ + int rc; + + rc = cxl_map_regblock(map); + if (rc) + return rc; + + rc = cxl_probe_regs(map); + cxl_unmap_regblock(map); + + return rc; +} +EXPORT_SYMBOL_NS_GPL(cxl_setup_regs, CXL); + +resource_size_t __rcrb_to_component(struct device *dev, struct cxl_rcrb_info *ri, + enum cxl_rcrb which) { resource_size_t component_reg_phys; + resource_size_t rcrb = ri->base; void __iomem *addr; u32 bar0, bar1; u16 cmd; @@ -395,4 +533,12 @@ resource_size_t cxl_rcrb_to_component(struct device *dev, return component_reg_phys; } -EXPORT_SYMBOL_NS_GPL(cxl_rcrb_to_component, CXL); + +resource_size_t cxl_rcd_component_reg_phys(struct device *dev, + struct cxl_dport *dport) +{ + if (!dport->rch) + return CXL_RESOURCE_NONE; + return __rcrb_to_component(dev, &dport->rcrb, CXL_RCRB_UPSTREAM); +} +EXPORT_SYMBOL_NS_GPL(cxl_rcd_component_reg_phys, CXL); diff --git a/drivers/cxl/cxl.h b/drivers/cxl/cxl.h index f93a285389621cc77e86ae792c095b1671f30c85..76d92561af29499d2fe14629bdd11247039d5dab 100644 --- a/drivers/cxl/cxl.h +++ b/drivers/cxl/cxl.h @@ -56,7 +56,7 @@ #define CXL_HDM_DECODER0_CTRL_COMMIT BIT(9) #define CXL_HDM_DECODER0_CTRL_COMMITTED BIT(10) #define CXL_HDM_DECODER0_CTRL_COMMIT_ERROR BIT(11) -#define CXL_HDM_DECODER0_CTRL_TYPE BIT(12) +#define CXL_HDM_DECODER0_CTRL_HOSTONLY BIT(12) #define CXL_HDM_DECODER0_TL_LOW(i) (0x20 * (i) + 0x24) #define CXL_HDM_DECODER0_TL_HIGH(i) (0x20 * (i) + 0x28) #define CXL_HDM_DECODER0_SKIP_LOW(i) CXL_HDM_DECODER0_TL_LOW(i) @@ -176,14 +176,22 @@ static inline int ways_to_eiw(unsigned int ways, u8 *eiw) /* CXL 2.0 8.2.8.4 Mailbox Registers */ #define CXLDEV_MBOX_CAPS_OFFSET 0x00 #define CXLDEV_MBOX_CAP_PAYLOAD_SIZE_MASK GENMASK(4, 0) +#define CXLDEV_MBOX_CAP_BG_CMD_IRQ BIT(6) +#define CXLDEV_MBOX_CAP_IRQ_MSGNUM_MASK GENMASK(10, 7) #define CXLDEV_MBOX_CTRL_OFFSET 0x04 #define CXLDEV_MBOX_CTRL_DOORBELL BIT(0) +#define CXLDEV_MBOX_CTRL_BG_CMD_IRQ BIT(2) #define CXLDEV_MBOX_CMD_OFFSET 0x08 #define CXLDEV_MBOX_CMD_COMMAND_OPCODE_MASK GENMASK_ULL(15, 0) #define CXLDEV_MBOX_CMD_PAYLOAD_LENGTH_MASK GENMASK_ULL(36, 16) #define CXLDEV_MBOX_STATUS_OFFSET 0x10 +#define CXLDEV_MBOX_STATUS_BG_CMD BIT(0) #define CXLDEV_MBOX_STATUS_RET_CODE_MASK GENMASK_ULL(47, 32) #define CXLDEV_MBOX_BG_CMD_STATUS_OFFSET 0x18 +#define CXLDEV_MBOX_BG_CMD_COMMAND_OPCODE_MASK GENMASK_ULL(15, 0) +#define CXLDEV_MBOX_BG_CMD_COMMAND_PCT_MASK GENMASK_ULL(22, 16) +#define CXLDEV_MBOX_BG_CMD_COMMAND_RC_MASK GENMASK_ULL(47, 32) +#define CXLDEV_MBOX_BG_CMD_COMMAND_VENDOR_MASK GENMASK_ULL(63, 48) #define CXLDEV_MBOX_PAYLOAD_OFFSET 0x20 /* @@ -209,6 +217,10 @@ struct cxl_regs { struct_group_tagged(cxl_device_regs, device_regs, void __iomem *status, *mbox, *memdev; ); + + struct_group_tagged(cxl_pmu_regs, pmu_regs, + void __iomem *pmu; + ); }; struct cxl_reg_map { @@ -229,16 +241,23 @@ struct cxl_device_reg_map { struct cxl_reg_map memdev; }; +struct cxl_pmu_reg_map { + struct cxl_reg_map pmu; +}; + /** * struct cxl_register_map - DVSEC harvested register block mapping parameters + * @dev: device for devm operations and logging * @base: virtual base of the register-block-BAR + @block_offset * @resource: physical resource base of the register block * @max_size: maximum mapping size to perform register search * @reg_type: see enum cxl_regloc_type * @component_map: cxl_reg_map for component registers * @device_map: cxl_reg_maps for device registers + * @pmu_map: cxl_reg_maps for CXL Performance Monitoring Units */ struct cxl_register_map { + struct device *dev; void __iomem *base; resource_size_t resource; resource_size_t max_size; @@ -246,6 +265,7 @@ struct cxl_register_map { union { struct cxl_component_reg_map component_map; struct cxl_device_reg_map device_map; + struct cxl_pmu_reg_map pmu_map; }; }; @@ -253,23 +273,24 @@ void cxl_probe_component_regs(struct device *dev, void __iomem *base, struct cxl_component_reg_map *map); void cxl_probe_device_regs(struct device *dev, void __iomem *base, struct cxl_device_reg_map *map); -int cxl_map_component_regs(struct device *dev, struct cxl_component_regs *regs, - struct cxl_register_map *map, +int cxl_map_component_regs(const struct cxl_register_map *map, + struct cxl_component_regs *regs, unsigned long map_mask); -int cxl_map_device_regs(struct device *dev, struct cxl_device_regs *regs, - struct cxl_register_map *map); +int cxl_map_device_regs(const struct cxl_register_map *map, + struct cxl_device_regs *regs); +int cxl_map_pmu_regs(struct pci_dev *pdev, struct cxl_pmu_regs *regs, + struct cxl_register_map *map); enum cxl_regloc_type; +int cxl_count_regblock(struct pci_dev *pdev, enum cxl_regloc_type type); +int cxl_find_regblock_instance(struct pci_dev *pdev, enum cxl_regloc_type type, + struct cxl_register_map *map, int index); int cxl_find_regblock(struct pci_dev *pdev, enum cxl_regloc_type type, struct cxl_register_map *map); - -enum cxl_rcrb { - CXL_RCRB_DOWNSTREAM, - CXL_RCRB_UPSTREAM, -}; -resource_size_t cxl_rcrb_to_component(struct device *dev, - resource_size_t rcrb, - enum cxl_rcrb which); +int cxl_setup_regs(struct cxl_register_map *map); +struct cxl_dport; +resource_size_t cxl_rcd_component_reg_phys(struct device *dev, + struct cxl_dport *dport); #define CXL_RESOURCE_NONE ((resource_size_t) -1) #define CXL_TARGET_STRLEN 20 @@ -290,8 +311,8 @@ resource_size_t cxl_rcrb_to_component(struct device *dev, #define CXL_DECODER_F_MASK GENMASK(5, 0) enum cxl_decoder_type { - CXL_DECODER_ACCELERATOR = 2, - CXL_DECODER_EXPANDER = 3, + CXL_DECODER_DEVMEM = 2, + CXL_DECODER_HOSTONLYMEM = 3, }; /* @@ -462,18 +483,20 @@ struct cxl_region_params { int nr_targets; }; -/* - * Flag whether this region needs to have its HPA span synchronized with - * CPU cache state at region activation time. - */ -#define CXL_REGION_F_INCOHERENT 0 - /* * Indicate whether this region has been assembled by autodetection or * userspace assembly. Prevent endpoint decoders outside of automatic * detection from being added to the region. */ -#define CXL_REGION_F_AUTO 1 +#define CXL_REGION_F_AUTO 0 + +/* + * Require that a committed region successfully complete a teardown once + * any of its associated decoders have been torn down. This maintains + * the commit state for the region since there are committed decoders, + * but blocks cxl_region_probe(). + */ +#define CXL_REGION_F_NEEDS_RESET 1 /** * struct cxl_region - CXL region @@ -541,7 +564,7 @@ struct cxl_dax_region { * downstream port devices to construct a CXL memory * decode hierarchy. * @dev: this port's device - * @uport: PCI or platform device implementing the upstream port capability + * @uport_dev: PCI or platform device implementing the upstream port capability * @host_bridge: Shortcut to the platform attach point for this port * @id: id for port device-name * @dports: cxl_dport instances referenced by decoders @@ -549,6 +572,7 @@ struct cxl_dax_region { * @regions: cxl_region_ref instances, regions mapped by this port * @parent_dport: dport that points to this port in the parent * @decoder_ida: allocator for decoder ids + * @comp_map: component register capability mappings * @nr_dports: number of entries in @dports * @hdm_end: track last allocated HDM decoder instance for allocation ordering * @commit_end: cursor to track highest committed decoder for commit ordering @@ -560,7 +584,7 @@ struct cxl_dax_region { */ struct cxl_port { struct device dev; - struct device *uport; + struct device *uport_dev; struct device *host_bridge; int id; struct xarray dports; @@ -568,6 +592,7 @@ struct cxl_port { struct xarray regions; struct cxl_dport *parent_dport; struct ida decoder_ida; + struct cxl_register_map comp_map; int nr_dports; int hdm_end; int commit_end; @@ -587,20 +612,25 @@ cxl_find_dport_by_dev(struct cxl_port *port, const struct device *dport_dev) return xa_load(&port->dports, (unsigned long)dport_dev); } +struct cxl_rcrb_info { + resource_size_t base; + u16 aer_cap; +}; + /** * struct cxl_dport - CXL downstream port - * @dport: PCI bridge or firmware device representing the downstream link + * @dport_dev: PCI bridge or firmware device representing the downstream link + * @comp_map: component register capability mappings * @port_id: unique hardware identifier for dport in decoder target list - * @component_reg_phys: downstream port component registers - * @rcrb: base address for the Root Complex Register Block + * @rcrb: Data about the Root Complex Register Block layout * @rch: Indicate whether this dport was enumerated in RCH or VH mode * @port: reference to cxl_port that contains this downstream port */ struct cxl_dport { - struct device *dport; + struct device *dport_dev; + struct cxl_register_map comp_map; int port_id; - resource_size_t component_reg_phys; - resource_size_t rcrb; + struct cxl_rcrb_info rcrb; bool rch; struct cxl_port *port; }; @@ -641,27 +671,30 @@ struct cxl_region_ref { /* * The platform firmware device hosting the root is also the top of the * CXL port topology. All other CXL ports have another CXL port as their - * parent and their ->uport / host device is out-of-line of the port + * parent and their ->uport_dev / host device is out-of-line of the port * ancestry. */ static inline bool is_cxl_root(struct cxl_port *port) { - return port->uport == port->dev.parent; + return port->uport_dev == port->dev.parent; } bool is_cxl_port(const struct device *dev); struct cxl_port *to_cxl_port(const struct device *dev); struct pci_bus; -int devm_cxl_register_pci_bus(struct device *host, struct device *uport, +int devm_cxl_register_pci_bus(struct device *host, struct device *uport_dev, struct pci_bus *bus); struct pci_bus *cxl_port_to_pci_bus(struct cxl_port *port); -struct cxl_port *devm_cxl_add_port(struct device *host, struct device *uport, +struct cxl_port *devm_cxl_add_port(struct device *host, + struct device *uport_dev, resource_size_t component_reg_phys, struct cxl_dport *parent_dport); struct cxl_port *find_cxl_root(struct cxl_port *port); int devm_cxl_enumerate_ports(struct cxl_memdev *cxlmd); void cxl_bus_rescan(void); void cxl_bus_drain(void); +struct cxl_port *cxl_pci_find_port(struct pci_dev *pdev, + struct cxl_dport **dport); struct cxl_port *cxl_mem_find_port(struct cxl_memdev *cxlmd, struct cxl_dport **dport); bool schedule_cxl_memdev_detach(struct cxl_memdev *cxlmd); @@ -671,7 +704,6 @@ struct cxl_dport *devm_cxl_add_dport(struct cxl_port *port, resource_size_t component_reg_phys); struct cxl_dport *devm_cxl_add_rch_dport(struct cxl_port *port, struct device *dport_dev, int port_id, - resource_size_t component_reg_phys, resource_size_t rcrb); struct cxl_decoder *to_cxl_decoder(struct device *dev); @@ -710,7 +742,6 @@ struct cxl_endpoint_dvsec_info { struct cxl_hdm; struct cxl_hdm *devm_cxl_setup_hdm(struct cxl_port *port, struct cxl_endpoint_dvsec_info *info); -int devm_cxl_enable_hdm(struct cxl_port *port, struct cxl_hdm *cxlhdm); int devm_cxl_enumerate_decoders(struct cxl_hdm *cxlhdm, struct cxl_endpoint_dvsec_info *info); int devm_cxl_add_passthrough_decoder(struct cxl_port *port); @@ -750,6 +781,7 @@ void cxl_driver_unregister(struct cxl_driver *cxl_drv); #define CXL_DEVICE_REGION 6 #define CXL_DEVICE_PMEM_REGION 7 #define CXL_DEVICE_DAX_REGION 8 +#define CXL_DEVICE_PMU 9 #define MODULE_ALIAS_CXL(type) MODULE_ALIAS("cxl:t" __stringify(type) "*") #define CXL_MODALIAS_FMT "cxl:t%d" diff --git a/drivers/cxl/cxlmem.h b/drivers/cxl/cxlmem.h index a2845a7a69d820d9b4f04ae6a681839728d0f31c..79e99c873ca2022e93d62e6ce90c278dd8bc2204 100644 --- a/drivers/cxl/cxlmem.h +++ b/drivers/cxl/cxlmem.h @@ -5,6 +5,7 @@ #include #include #include +#include #include "cxl.h" /* CXL 2.0 8.2.8.5.1.1 Memory Device Status Register */ @@ -38,6 +39,7 @@ * @detach_work: active memdev lost a port in its ancestry * @cxl_nvb: coordinate removal of @cxl_nvd if present * @cxl_nvd: optional bridge to an nvdimm if the device supports pmem + * @endpoint: connection to the CXL port topology for this memory device * @id: id number of this memdev instance. * @depth: endpoint port depth */ @@ -48,6 +50,7 @@ struct cxl_memdev { struct work_struct detach_work; struct cxl_nvdimm_bridge *cxl_nvb; struct cxl_nvdimm *cxl_nvd; + struct cxl_port *endpoint; int id; int depth; }; @@ -72,16 +75,18 @@ cxled_to_memdev(struct cxl_endpoint_decoder *cxled) { struct cxl_port *port = to_cxl_port(cxled->cxld.dev.parent); - return to_cxl_memdev(port->uport); + return to_cxl_memdev(port->uport_dev); } bool is_cxl_memdev(const struct device *dev); static inline bool is_cxl_endpoint(struct cxl_port *port) { - return is_cxl_memdev(port->uport); + return is_cxl_memdev(port->uport_dev); } struct cxl_memdev *devm_cxl_add_memdev(struct cxl_dev_state *cxlds); +struct cxl_memdev_state; +int cxl_memdev_setup_fw_upload(struct cxl_memdev_state *mds); int devm_cxl_dpa_reserve(struct cxl_endpoint_decoder *cxled, resource_size_t base, resource_size_t len, resource_size_t skipped); @@ -108,6 +113,9 @@ static inline struct cxl_ep *cxl_ep_load(struct cxl_port *port, * variable sized output commands, it tells the exact number of bytes * written. * @min_out: (input) internal command output payload size validation + * @poll_count: (input) Number of timeouts to attempt. + * @poll_interval_ms: (input) Time between mailbox background command polling + * interval timeouts. * @return_code: (output) Error code returned from hardware. * * This is the primary mechanism used to send commands to the hardware. @@ -123,6 +131,8 @@ struct cxl_mbox_cmd { size_t size_in; size_t size_out; size_t min_out; + int poll_count; + int poll_interval_ms; u16 return_code; }; @@ -195,7 +205,7 @@ static inline int cxl_mbox_cmd_rc2errno(struct cxl_mbox_cmd *mbox_cmd) */ #define CXL_CAPACITY_MULTIPLIER SZ_256M -/** +/* * Event Interrupt Policy * * CXL rev 3.0 section 8.2.9.2.4; Table 8-52 @@ -215,8 +225,8 @@ struct cxl_event_interrupt_policy { /** * struct cxl_event_state - Event log driver state * - * @event_buf: Buffer to receive event data - * @event_log_lock: Serialize event_buf and log use + * @buf: Buffer to receive event data + * @log_lock: Serialize event_buf and log use */ struct cxl_event_state { struct cxl_get_event_payload *buf; @@ -254,6 +264,115 @@ struct cxl_poison_state { struct mutex lock; /* Protect reads of poison list */ }; +/* + * Get FW Info + * CXL rev 3.0 section 8.2.9.3.1; Table 8-56 + */ +struct cxl_mbox_get_fw_info { + u8 num_slots; + u8 slot_info; + u8 activation_cap; + u8 reserved[13]; + char slot_1_revision[16]; + char slot_2_revision[16]; + char slot_3_revision[16]; + char slot_4_revision[16]; +} __packed; + +#define CXL_FW_INFO_SLOT_INFO_CUR_MASK GENMASK(2, 0) +#define CXL_FW_INFO_SLOT_INFO_NEXT_MASK GENMASK(5, 3) +#define CXL_FW_INFO_SLOT_INFO_NEXT_SHIFT 3 +#define CXL_FW_INFO_ACTIVATION_CAP_HAS_LIVE_ACTIVATE BIT(0) + +/* + * Transfer FW Input Payload + * CXL rev 3.0 section 8.2.9.3.2; Table 8-57 + */ +struct cxl_mbox_transfer_fw { + u8 action; + u8 slot; + u8 reserved[2]; + __le32 offset; + u8 reserved2[0x78]; + u8 data[]; +} __packed; + +#define CXL_FW_TRANSFER_ACTION_FULL 0x0 +#define CXL_FW_TRANSFER_ACTION_INITIATE 0x1 +#define CXL_FW_TRANSFER_ACTION_CONTINUE 0x2 +#define CXL_FW_TRANSFER_ACTION_END 0x3 +#define CXL_FW_TRANSFER_ACTION_ABORT 0x4 + +/* + * CXL rev 3.0 section 8.2.9.3.2 mandates 128-byte alignment for FW packages + * and for each part transferred in a Transfer FW command. + */ +#define CXL_FW_TRANSFER_ALIGNMENT 128 + +/* + * Activate FW Input Payload + * CXL rev 3.0 section 8.2.9.3.3; Table 8-58 + */ +struct cxl_mbox_activate_fw { + u8 action; + u8 slot; +} __packed; + +#define CXL_FW_ACTIVATE_ONLINE 0x0 +#define CXL_FW_ACTIVATE_OFFLINE 0x1 + +/* FW state bits */ +#define CXL_FW_STATE_BITS 32 +#define CXL_FW_CANCEL BIT(0) + +/** + * struct cxl_fw_state - Firmware upload / activation state + * + * @state: fw_uploader state bitmask + * @oneshot: whether the fw upload fits in a single transfer + * @num_slots: Number of FW slots available + * @cur_slot: Slot number currently active + * @next_slot: Slot number for the new firmware + */ +struct cxl_fw_state { + DECLARE_BITMAP(state, CXL_FW_STATE_BITS); + bool oneshot; + int num_slots; + int cur_slot; + int next_slot; +}; + +/** + * struct cxl_security_state - Device security state + * + * @state: state of last security operation + * @poll: polling for sanitization is enabled, device has no mbox irq support + * @poll_tmo_secs: polling timeout + * @poll_dwork: polling work item + * @sanitize_node: sanitation sysfs file to notify + */ +struct cxl_security_state { + unsigned long state; + bool poll; + int poll_tmo_secs; + struct delayed_work poll_dwork; + struct kernfs_node *sanitize_node; +}; + +/* + * enum cxl_devtype - delineate type-2 from a generic type-3 device + * @CXL_DEVTYPE_DEVMEM - Vendor specific CXL Type-2 device implementing HDM-D or + * HDM-DB, no requirement that this device implements a + * mailbox, or other memory-device-standard manageability + * flows. + * @CXL_DEVTYPE_CLASSMEM - Common class definition of a CXL Type-3 device with + * HDM-H and class-mandatory memory device registers + */ +enum cxl_devtype { + CXL_DEVTYPE_DEVMEM, + CXL_DEVTYPE_CLASSMEM, +}; + /** * struct cxl_dev_state - The driver device state * @@ -267,6 +386,36 @@ struct cxl_poison_state { * @cxl_dvsec: Offset to the PCIe device DVSEC * @rcd: operating in RCD mode (CXL 3.0 9.11.8 CXL Devices Attached to an RCH) * @media_ready: Indicate whether the device media is usable + * @dpa_res: Overall DPA resource tree for the device + * @pmem_res: Active Persistent memory capacity configuration + * @ram_res: Active Volatile memory capacity configuration + * @component_reg_phys: register base of component registers + * @serial: PCIe Device Serial Number + * @type: Generic Memory Class device or Vendor Specific Memory device + */ +struct cxl_dev_state { + struct device *dev; + struct cxl_memdev *cxlmd; + struct cxl_regs regs; + int cxl_dvsec; + bool rcd; + bool media_ready; + struct resource dpa_res; + struct resource pmem_res; + struct resource ram_res; + resource_size_t component_reg_phys; + u64 serial; + enum cxl_devtype type; +}; + +/** + * struct cxl_memdev_state - Generic Type-3 Memory Device Class driver data + * + * CXL 8.1.12.1 PCI Header - Class Code Register Memory Device defines + * common memory device functionality like the presence of a mailbox and + * the functionality related to that like Identify Memory Device and Get + * Partition Info + * @cxlds: Core driver state common across Type-2 and Type-3 devices * @payload_size: Size of space for payload * (CXL 2.0 8.2.8.4.3 Mailbox Capabilities Register) * @lsa_size: Size of Label Storage Area @@ -275,9 +424,6 @@ struct cxl_poison_state { * @firmware_version: Firmware version for the memory device. * @enabled_cmds: Hardware commands found enabled in CEL. * @exclusive_cmds: Commands that are kernel-internal only - * @dpa_res: Overall DPA resource tree for the device - * @pmem_res: Active Persistent memory capacity configuration - * @ram_res: Active Volatile memory capacity configuration * @total_bytes: sum of all possible capacities * @volatile_only_bytes: hard volatile capacity * @persistent_only_bytes: hard persistent capacity @@ -286,54 +432,48 @@ struct cxl_poison_state { * @active_persistent_bytes: sum of hard + soft persistent * @next_volatile_bytes: volatile capacity change pending device reset * @next_persistent_bytes: persistent capacity change pending device reset - * @component_reg_phys: register base of component registers - * @info: Cached DVSEC information about the device. - * @serial: PCIe Device Serial Number * @event: event log driver state * @poison: poison driver state info + * @fw: firmware upload / activation state * @mbox_send: @dev specific transport for transmitting mailbox commands * - * See section 8.2.9.5.2 Capacity Configuration and Label Storage for + * See CXL 3.0 8.2.9.8.2 Capacity Configuration and Label Storage for * details on capacity parameters. */ -struct cxl_dev_state { - struct device *dev; - struct cxl_memdev *cxlmd; - - struct cxl_regs regs; - int cxl_dvsec; - - bool rcd; - bool media_ready; +struct cxl_memdev_state { + struct cxl_dev_state cxlds; size_t payload_size; size_t lsa_size; struct mutex mbox_mutex; /* Protects device mailbox and firmware */ char firmware_version[0x10]; DECLARE_BITMAP(enabled_cmds, CXL_MEM_COMMAND_ID_MAX); DECLARE_BITMAP(exclusive_cmds, CXL_MEM_COMMAND_ID_MAX); - - struct resource dpa_res; - struct resource pmem_res; - struct resource ram_res; u64 total_bytes; u64 volatile_only_bytes; u64 persistent_only_bytes; u64 partition_align_bytes; - u64 active_volatile_bytes; u64 active_persistent_bytes; u64 next_volatile_bytes; u64 next_persistent_bytes; - - resource_size_t component_reg_phys; - u64 serial; - struct cxl_event_state event; struct cxl_poison_state poison; + struct cxl_security_state security; + struct cxl_fw_state fw; - int (*mbox_send)(struct cxl_dev_state *cxlds, struct cxl_mbox_cmd *cmd); + struct rcuwait mbox_wait; + int (*mbox_send)(struct cxl_memdev_state *mds, + struct cxl_mbox_cmd *cmd); }; +static inline struct cxl_memdev_state * +to_cxl_memdev_state(struct cxl_dev_state *cxlds) +{ + if (cxlds->type != CXL_DEVTYPE_CLASSMEM) + return NULL; + return container_of(cxlds, struct cxl_memdev_state, cxlds); +} + enum cxl_opcode { CXL_MBOX_OP_INVALID = 0x0000, CXL_MBOX_OP_RAW = CXL_MBOX_OP_INVALID, @@ -342,6 +482,7 @@ enum cxl_opcode { CXL_MBOX_OP_GET_EVT_INT_POLICY = 0x0102, CXL_MBOX_OP_SET_EVT_INT_POLICY = 0x0103, CXL_MBOX_OP_GET_FW_INFO = 0x0200, + CXL_MBOX_OP_TRANSFER_FW = 0x0201, CXL_MBOX_OP_ACTIVATE_FW = 0x0202, CXL_MBOX_OP_SET_TIMESTAMP = 0x0301, CXL_MBOX_OP_GET_SUPPORTED_LOGS = 0x0400, @@ -362,6 +503,8 @@ enum cxl_opcode { CXL_MBOX_OP_GET_SCAN_MEDIA_CAPS = 0x4303, CXL_MBOX_OP_SCAN_MEDIA = 0x4304, CXL_MBOX_OP_GET_SCAN_MEDIA = 0x4305, + CXL_MBOX_OP_SANITIZE = 0x4400, + CXL_MBOX_OP_SECURE_ERASE = 0x4401, CXL_MBOX_OP_GET_SECURITY_STATE = 0x4500, CXL_MBOX_OP_SET_PASSPHRASE = 0x4501, CXL_MBOX_OP_DISABLE_PASSPHRASE = 0x4502, @@ -692,18 +835,20 @@ enum { CXL_PMEM_SEC_PASS_USER, }; -int cxl_internal_send_cmd(struct cxl_dev_state *cxlds, +int cxl_internal_send_cmd(struct cxl_memdev_state *mds, struct cxl_mbox_cmd *cmd); -int cxl_dev_state_identify(struct cxl_dev_state *cxlds); +int cxl_dev_state_identify(struct cxl_memdev_state *mds); int cxl_await_media_ready(struct cxl_dev_state *cxlds); -int cxl_enumerate_cmds(struct cxl_dev_state *cxlds); -int cxl_mem_create_range_info(struct cxl_dev_state *cxlds); -struct cxl_dev_state *cxl_dev_state_create(struct device *dev); -void set_exclusive_cxl_commands(struct cxl_dev_state *cxlds, unsigned long *cmds); -void clear_exclusive_cxl_commands(struct cxl_dev_state *cxlds, unsigned long *cmds); -void cxl_mem_get_event_records(struct cxl_dev_state *cxlds, u32 status); -int cxl_set_timestamp(struct cxl_dev_state *cxlds); -int cxl_poison_state_init(struct cxl_dev_state *cxlds); +int cxl_enumerate_cmds(struct cxl_memdev_state *mds); +int cxl_mem_create_range_info(struct cxl_memdev_state *mds); +struct cxl_memdev_state *cxl_memdev_state_create(struct device *dev); +void set_exclusive_cxl_commands(struct cxl_memdev_state *mds, + unsigned long *cmds); +void clear_exclusive_cxl_commands(struct cxl_memdev_state *mds, + unsigned long *cmds); +void cxl_mem_get_event_records(struct cxl_memdev_state *mds, u32 status); +int cxl_set_timestamp(struct cxl_memdev_state *mds); +int cxl_poison_state_init(struct cxl_memdev_state *mds); int cxl_mem_get_poison(struct cxl_memdev *cxlmd, u64 offset, u64 len, struct cxl_region *cxlr); int cxl_trigger_poison_list(struct cxl_memdev *cxlmd); @@ -722,6 +867,8 @@ static inline void cxl_mem_active_dec(void) } #endif +int cxl_mem_sanitize(struct cxl_memdev_state *mds, u16 cmd); + struct cxl_hdm { struct cxl_component_regs regs; unsigned int decoder_count; diff --git a/drivers/cxl/cxlpci.h b/drivers/cxl/cxlpci.h index 7c02e55b80429a9390d3322407701033bb6c01ce..0fa4799ea316cd802c97feda11fb6e3c88aaa138 100644 --- a/drivers/cxl/cxlpci.h +++ b/drivers/cxl/cxlpci.h @@ -67,6 +67,7 @@ enum cxl_regloc_type { CXL_REGLOC_RBI_COMPONENT, CXL_REGLOC_RBI_VIRT, CXL_REGLOC_RBI_MEMDEV, + CXL_REGLOC_RBI_PMU, CXL_REGLOC_RBI_TYPES }; diff --git a/drivers/cxl/mem.c b/drivers/cxl/mem.c index 519edd0eb1967d8c0d0ec7bb5e934b267e37c1ff..317c7548e4e9b4596686a8dfb04c96e3140bf783 100644 --- a/drivers/cxl/mem.c +++ b/drivers/cxl/mem.c @@ -51,7 +51,6 @@ static int devm_cxl_add_endpoint(struct device *host, struct cxl_memdev *cxlmd, struct cxl_port *parent_port = parent_dport->port; struct cxl_dev_state *cxlds = cxlmd->cxlds; struct cxl_port *endpoint, *iter, *down; - resource_size_t component_reg_phys; int rc; /* @@ -66,17 +65,8 @@ static int devm_cxl_add_endpoint(struct device *host, struct cxl_memdev *cxlmd, ep->next = down; } - /* - * The component registers for an RCD might come from the - * host-bridge RCRB if they are not already mapped via the - * typical register locator mechanism. - */ - if (parent_dport->rch && cxlds->component_reg_phys == CXL_RESOURCE_NONE) - component_reg_phys = cxl_rcrb_to_component( - &cxlmd->dev, parent_dport->rcrb, CXL_RCRB_UPSTREAM); - else - component_reg_phys = cxlds->component_reg_phys; - endpoint = devm_cxl_add_port(host, &cxlmd->dev, component_reg_phys, + endpoint = devm_cxl_add_port(host, &cxlmd->dev, + cxlds->component_reg_phys, parent_dport); if (IS_ERR(endpoint)) return PTR_ERR(endpoint); @@ -117,6 +107,7 @@ DEFINE_DEBUGFS_ATTRIBUTE(cxl_poison_clear_fops, NULL, static int cxl_mem_probe(struct device *dev) { struct cxl_memdev *cxlmd = to_cxl_memdev(dev); + struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds); struct cxl_dev_state *cxlds = cxlmd->cxlds; struct device *endpoint_parent; struct cxl_port *parent_port; @@ -141,10 +132,10 @@ static int cxl_mem_probe(struct device *dev) dentry = cxl_debugfs_create_dir(dev_name(dev)); debugfs_create_devm_seqfile(dev, "dpamem", dentry, cxl_mem_dpa_show); - if (test_bit(CXL_POISON_ENABLED_INJECT, cxlds->poison.enabled_cmds)) + if (test_bit(CXL_POISON_ENABLED_INJECT, mds->poison.enabled_cmds)) debugfs_create_file("inject_poison", 0200, dentry, cxlmd, &cxl_poison_inject_fops); - if (test_bit(CXL_POISON_ENABLED_CLEAR, cxlds->poison.enabled_cmds)) + if (test_bit(CXL_POISON_ENABLED_CLEAR, mds->poison.enabled_cmds)) debugfs_create_file("clear_poison", 0200, dentry, cxlmd, &cxl_poison_clear_fops); @@ -163,7 +154,7 @@ static int cxl_mem_probe(struct device *dev) } if (dport->rch) - endpoint_parent = parent_port->uport; + endpoint_parent = parent_port->uport_dev; else endpoint_parent = &parent_port->dev; @@ -227,9 +218,12 @@ static umode_t cxl_mem_visible(struct kobject *kobj, struct attribute *a, int n) { if (a == &dev_attr_trigger_poison_list.attr) { struct device *dev = kobj_to_dev(kobj); + struct cxl_memdev *cxlmd = to_cxl_memdev(dev); + struct cxl_memdev_state *mds = + to_cxl_memdev_state(cxlmd->cxlds); if (!test_bit(CXL_POISON_ENABLED_LIST, - to_cxl_memdev(dev)->cxlds->poison.enabled_cmds)) + mds->poison.enabled_cmds)) return 0; } return a->mode; diff --git a/drivers/cxl/pci.c b/drivers/cxl/pci.c index 0872f2233ed0c88aa9fec7e9e93935dfa1f0e740..1cb1494c28fe82c36f0e75f9a1ee64f6ed77fc38 100644 --- a/drivers/cxl/pci.c +++ b/drivers/cxl/pci.c @@ -13,6 +13,7 @@ #include "cxlmem.h" #include "cxlpci.h" #include "cxl.h" +#include "pmu.h" /** * DOC: cxl pci @@ -84,9 +85,92 @@ static int cxl_pci_mbox_wait_for_doorbell(struct cxl_dev_state *cxlds) status & CXLMDEV_DEV_FATAL ? " fatal" : "", \ status & CXLMDEV_FW_HALT ? " firmware-halt" : "") +struct cxl_dev_id { + struct cxl_dev_state *cxlds; +}; + +static int cxl_request_irq(struct cxl_dev_state *cxlds, int irq, + irq_handler_t handler, irq_handler_t thread_fn) +{ + struct device *dev = cxlds->dev; + struct cxl_dev_id *dev_id; + + /* dev_id must be globally unique and must contain the cxlds */ + dev_id = devm_kzalloc(dev, sizeof(*dev_id), GFP_KERNEL); + if (!dev_id) + return -ENOMEM; + dev_id->cxlds = cxlds; + + return devm_request_threaded_irq(dev, irq, handler, thread_fn, + IRQF_SHARED | IRQF_ONESHOT, + NULL, dev_id); +} + +static bool cxl_mbox_background_complete(struct cxl_dev_state *cxlds) +{ + u64 reg; + + reg = readq(cxlds->regs.mbox + CXLDEV_MBOX_BG_CMD_STATUS_OFFSET); + return FIELD_GET(CXLDEV_MBOX_BG_CMD_COMMAND_PCT_MASK, reg) == 100; +} + +static irqreturn_t cxl_pci_mbox_irq(int irq, void *id) +{ + u64 reg; + u16 opcode; + struct cxl_dev_id *dev_id = id; + struct cxl_dev_state *cxlds = dev_id->cxlds; + struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlds); + + if (!cxl_mbox_background_complete(cxlds)) + return IRQ_NONE; + + reg = readq(cxlds->regs.mbox + CXLDEV_MBOX_BG_CMD_STATUS_OFFSET); + opcode = FIELD_GET(CXLDEV_MBOX_BG_CMD_COMMAND_OPCODE_MASK, reg); + if (opcode == CXL_MBOX_OP_SANITIZE) { + if (mds->security.sanitize_node) + sysfs_notify_dirent(mds->security.sanitize_node); + + dev_dbg(cxlds->dev, "Sanitization operation ended\n"); + } else { + /* short-circuit the wait in __cxl_pci_mbox_send_cmd() */ + rcuwait_wake_up(&mds->mbox_wait); + } + + return IRQ_HANDLED; +} + +/* + * Sanitization operation polling mode. + */ +static void cxl_mbox_sanitize_work(struct work_struct *work) +{ + struct cxl_memdev_state *mds = + container_of(work, typeof(*mds), security.poll_dwork.work); + struct cxl_dev_state *cxlds = &mds->cxlds; + + mutex_lock(&mds->mbox_mutex); + if (cxl_mbox_background_complete(cxlds)) { + mds->security.poll_tmo_secs = 0; + put_device(cxlds->dev); + + if (mds->security.sanitize_node) + sysfs_notify_dirent(mds->security.sanitize_node); + + dev_dbg(cxlds->dev, "Sanitization operation ended\n"); + } else { + int timeout = mds->security.poll_tmo_secs + 10; + + mds->security.poll_tmo_secs = min(15 * 60, timeout); + queue_delayed_work(system_wq, &mds->security.poll_dwork, + timeout * HZ); + } + mutex_unlock(&mds->mbox_mutex); +} + /** * __cxl_pci_mbox_send_cmd() - Execute a mailbox command - * @cxlds: The device state to communicate with. + * @mds: The memory device driver data * @mbox_cmd: Command to send to the memory device. * * Context: Any context. Expects mbox_mutex to be held. @@ -106,16 +190,17 @@ static int cxl_pci_mbox_wait_for_doorbell(struct cxl_dev_state *cxlds) * not need to coordinate with each other. The driver only uses the primary * mailbox. */ -static int __cxl_pci_mbox_send_cmd(struct cxl_dev_state *cxlds, +static int __cxl_pci_mbox_send_cmd(struct cxl_memdev_state *mds, struct cxl_mbox_cmd *mbox_cmd) { + struct cxl_dev_state *cxlds = &mds->cxlds; void __iomem *payload = cxlds->regs.mbox + CXLDEV_MBOX_PAYLOAD_OFFSET; struct device *dev = cxlds->dev; u64 cmd_reg, status_reg; size_t out_len; int rc; - lockdep_assert_held(&cxlds->mbox_mutex); + lockdep_assert_held(&mds->mbox_mutex); /* * Here are the steps from 8.2.8.4 of the CXL 2.0 spec. @@ -144,6 +229,16 @@ static int __cxl_pci_mbox_send_cmd(struct cxl_dev_state *cxlds, return -EBUSY; } + /* + * With sanitize polling, hardware might be done and the poller still + * not be in sync. Ensure no new command comes in until so. Keep the + * hardware semantics and only allow device health status. + */ + if (mds->security.poll_tmo_secs > 0) { + if (mbox_cmd->opcode != CXL_MBOX_OP_GET_HEALTH_INFO) + return -EBUSY; + } + cmd_reg = FIELD_PREP(CXLDEV_MBOX_CMD_COMMAND_OPCODE_MASK, mbox_cmd->opcode); if (mbox_cmd->size_in) { @@ -177,12 +272,80 @@ static int __cxl_pci_mbox_send_cmd(struct cxl_dev_state *cxlds, mbox_cmd->return_code = FIELD_GET(CXLDEV_MBOX_STATUS_RET_CODE_MASK, status_reg); + /* + * Handle the background command in a synchronous manner. + * + * All other mailbox commands will serialize/queue on the mbox_mutex, + * which we currently hold. Furthermore this also guarantees that + * cxl_mbox_background_complete() checks are safe amongst each other, + * in that no new bg operation can occur in between. + * + * Background operations are timesliced in accordance with the nature + * of the command. In the event of timeout, the mailbox state is + * indeterminate until the next successful command submission and the + * driver can get back in sync with the hardware state. + */ + if (mbox_cmd->return_code == CXL_MBOX_CMD_RC_BACKGROUND) { + u64 bg_status_reg; + int i, timeout; + + /* + * Sanitization is a special case which monopolizes the device + * and cannot be timesliced. Handle asynchronously instead, + * and allow userspace to poll(2) for completion. + */ + if (mbox_cmd->opcode == CXL_MBOX_OP_SANITIZE) { + if (mds->security.poll) { + /* hold the device throughout */ + get_device(cxlds->dev); + + /* give first timeout a second */ + timeout = 1; + mds->security.poll_tmo_secs = timeout; + queue_delayed_work(system_wq, + &mds->security.poll_dwork, + timeout * HZ); + } + + dev_dbg(dev, "Sanitization operation started\n"); + goto success; + } + + dev_dbg(dev, "Mailbox background operation (0x%04x) started\n", + mbox_cmd->opcode); + + timeout = mbox_cmd->poll_interval_ms; + for (i = 0; i < mbox_cmd->poll_count; i++) { + if (rcuwait_wait_event_timeout(&mds->mbox_wait, + cxl_mbox_background_complete(cxlds), + TASK_UNINTERRUPTIBLE, + msecs_to_jiffies(timeout)) > 0) + break; + } + + if (!cxl_mbox_background_complete(cxlds)) { + dev_err(dev, "timeout waiting for background (%d ms)\n", + timeout * mbox_cmd->poll_count); + return -ETIMEDOUT; + } + + bg_status_reg = readq(cxlds->regs.mbox + + CXLDEV_MBOX_BG_CMD_STATUS_OFFSET); + mbox_cmd->return_code = + FIELD_GET(CXLDEV_MBOX_BG_CMD_COMMAND_RC_MASK, + bg_status_reg); + dev_dbg(dev, + "Mailbox background operation (0x%04x) completed\n", + mbox_cmd->opcode); + } + if (mbox_cmd->return_code != CXL_MBOX_CMD_RC_SUCCESS) { dev_dbg(dev, "Mailbox operation had an error: %s\n", cxl_mbox_cmd_rc2str(mbox_cmd)); return 0; /* completed but caller must check return_code */ } +success: /* #7 */ cmd_reg = readq(cxlds->regs.mbox + CXLDEV_MBOX_CMD_OFFSET); out_len = FIELD_GET(CXLDEV_MBOX_CMD_PAYLOAD_LENGTH_MASK, cmd_reg); @@ -196,8 +359,9 @@ static int __cxl_pci_mbox_send_cmd(struct cxl_dev_state *cxlds, * have requested less data than the hardware supplied even * within spec. */ - size_t n = min3(mbox_cmd->size_out, cxlds->payload_size, out_len); + size_t n; + n = min3(mbox_cmd->size_out, mds->payload_size, out_len); memcpy_fromio(mbox_cmd->payload_out, payload, n); mbox_cmd->size_out = n; } else { @@ -207,20 +371,23 @@ static int __cxl_pci_mbox_send_cmd(struct cxl_dev_state *cxlds, return 0; } -static int cxl_pci_mbox_send(struct cxl_dev_state *cxlds, struct cxl_mbox_cmd *cmd) +static int cxl_pci_mbox_send(struct cxl_memdev_state *mds, + struct cxl_mbox_cmd *cmd) { int rc; - mutex_lock_io(&cxlds->mbox_mutex); - rc = __cxl_pci_mbox_send_cmd(cxlds, cmd); - mutex_unlock(&cxlds->mbox_mutex); + mutex_lock_io(&mds->mbox_mutex); + rc = __cxl_pci_mbox_send_cmd(mds, cmd); + mutex_unlock(&mds->mbox_mutex); return rc; } -static int cxl_pci_setup_mailbox(struct cxl_dev_state *cxlds) +static int cxl_pci_setup_mailbox(struct cxl_memdev_state *mds) { + struct cxl_dev_state *cxlds = &mds->cxlds; const int cap = readl(cxlds->regs.mbox + CXLDEV_MBOX_CAPS_OFFSET); + struct device *dev = cxlds->dev; unsigned long timeout; u64 md_status; @@ -234,8 +401,7 @@ static int cxl_pci_setup_mailbox(struct cxl_dev_state *cxlds) } while (!time_after(jiffies, timeout)); if (!(md_status & CXLMDEV_MBOX_IF_READY)) { - cxl_err(cxlds->dev, md_status, - "timeout awaiting mailbox ready"); + cxl_err(dev, md_status, "timeout awaiting mailbox ready"); return -ETIMEDOUT; } @@ -246,12 +412,12 @@ static int cxl_pci_setup_mailbox(struct cxl_dev_state *cxlds) * source for future doorbell busy events. */ if (cxl_pci_mbox_wait_for_doorbell(cxlds) != 0) { - cxl_err(cxlds->dev, md_status, "timeout awaiting mailbox idle"); + cxl_err(dev, md_status, "timeout awaiting mailbox idle"); return -ETIMEDOUT; } - cxlds->mbox_send = cxl_pci_mbox_send; - cxlds->payload_size = + mds->mbox_send = cxl_pci_mbox_send; + mds->payload_size = 1 << FIELD_GET(CXLDEV_MBOX_CAP_PAYLOAD_SIZE_MASK, cap); /* @@ -261,121 +427,104 @@ static int cxl_pci_setup_mailbox(struct cxl_dev_state *cxlds) * there's no point in going forward. If the size is too large, there's * no harm is soft limiting it. */ - cxlds->payload_size = min_t(size_t, cxlds->payload_size, SZ_1M); - if (cxlds->payload_size < 256) { - dev_err(cxlds->dev, "Mailbox is too small (%zub)", - cxlds->payload_size); + mds->payload_size = min_t(size_t, mds->payload_size, SZ_1M); + if (mds->payload_size < 256) { + dev_err(dev, "Mailbox is too small (%zub)", + mds->payload_size); return -ENXIO; } - dev_dbg(cxlds->dev, "Mailbox payload sized %zu", - cxlds->payload_size); + dev_dbg(dev, "Mailbox payload sized %zu", mds->payload_size); - return 0; -} + rcuwait_init(&mds->mbox_wait); -static int cxl_map_regblock(struct pci_dev *pdev, struct cxl_register_map *map) -{ - struct device *dev = &pdev->dev; + if (cap & CXLDEV_MBOX_CAP_BG_CMD_IRQ) { + u32 ctrl; + int irq, msgnum; + struct pci_dev *pdev = to_pci_dev(cxlds->dev); - map->base = ioremap(map->resource, map->max_size); - if (!map->base) { - dev_err(dev, "failed to map registers\n"); - return -ENOMEM; + msgnum = FIELD_GET(CXLDEV_MBOX_CAP_IRQ_MSGNUM_MASK, cap); + irq = pci_irq_vector(pdev, msgnum); + if (irq < 0) + goto mbox_poll; + + if (cxl_request_irq(cxlds, irq, cxl_pci_mbox_irq, NULL)) + goto mbox_poll; + + /* enable background command mbox irq support */ + ctrl = readl(cxlds->regs.mbox + CXLDEV_MBOX_CTRL_OFFSET); + ctrl |= CXLDEV_MBOX_CTRL_BG_CMD_IRQ; + writel(ctrl, cxlds->regs.mbox + CXLDEV_MBOX_CTRL_OFFSET); + + return 0; } - dev_dbg(dev, "Mapped CXL Memory Device resource %pa\n", &map->resource); +mbox_poll: + mds->security.poll = true; + INIT_DELAYED_WORK(&mds->security.poll_dwork, cxl_mbox_sanitize_work); + + dev_dbg(cxlds->dev, "Mailbox interrupts are unsupported"); return 0; } -static void cxl_unmap_regblock(struct pci_dev *pdev, - struct cxl_register_map *map) +/* + * Assume that any RCIEP that emits the CXL memory expander class code + * is an RCD + */ +static bool is_cxl_restricted(struct pci_dev *pdev) { - iounmap(map->base); - map->base = NULL; + return pci_pcie_type(pdev) == PCI_EXP_TYPE_RC_END; } -static int cxl_probe_regs(struct pci_dev *pdev, struct cxl_register_map *map) +static int cxl_rcrb_get_comp_regs(struct pci_dev *pdev, + struct cxl_register_map *map) { - struct cxl_component_reg_map *comp_map; - struct cxl_device_reg_map *dev_map; - struct device *dev = &pdev->dev; - void __iomem *base = map->base; - - switch (map->reg_type) { - case CXL_REGLOC_RBI_COMPONENT: - comp_map = &map->component_map; - cxl_probe_component_regs(dev, base, comp_map); - if (!comp_map->hdm_decoder.valid) { - dev_err(dev, "HDM decoder registers not found\n"); - return -ENXIO; - } + struct cxl_port *port; + struct cxl_dport *dport; + resource_size_t component_reg_phys; - if (!comp_map->ras.valid) - dev_dbg(dev, "RAS registers not found\n"); - - dev_dbg(dev, "Set up component registers\n"); - break; - case CXL_REGLOC_RBI_MEMDEV: - dev_map = &map->device_map; - cxl_probe_device_regs(dev, base, dev_map); - if (!dev_map->status.valid || !dev_map->mbox.valid || - !dev_map->memdev.valid) { - dev_err(dev, "registers not found: %s%s%s\n", - !dev_map->status.valid ? "status " : "", - !dev_map->mbox.valid ? "mbox " : "", - !dev_map->memdev.valid ? "memdev " : ""); - return -ENXIO; - } + *map = (struct cxl_register_map) { + .dev = &pdev->dev, + .resource = CXL_RESOURCE_NONE, + }; - dev_dbg(dev, "Probing device registers...\n"); - break; - default: - break; - } + port = cxl_pci_find_port(pdev, &dport); + if (!port) + return -EPROBE_DEFER; + + component_reg_phys = cxl_rcd_component_reg_phys(&pdev->dev, dport); + + put_device(&port->dev); + + if (component_reg_phys == CXL_RESOURCE_NONE) + return -ENXIO; + + map->resource = component_reg_phys; + map->reg_type = CXL_REGLOC_RBI_COMPONENT; + map->max_size = CXL_COMPONENT_REG_BLOCK_SIZE; return 0; } -static int cxl_setup_regs(struct pci_dev *pdev, enum cxl_regloc_type type, - struct cxl_register_map *map) +static int cxl_pci_setup_regs(struct pci_dev *pdev, enum cxl_regloc_type type, + struct cxl_register_map *map) { int rc; rc = cxl_find_regblock(pdev, type, map); - if (rc) - return rc; - rc = cxl_map_regblock(pdev, map); + /* + * If the Register Locator DVSEC does not exist, check if it + * is an RCH and try to extract the Component Registers from + * an RCRB. + */ + if (rc && type == CXL_REGLOC_RBI_COMPONENT && is_cxl_restricted(pdev)) + rc = cxl_rcrb_get_comp_regs(pdev, map); + if (rc) return rc; - rc = cxl_probe_regs(pdev, map); - cxl_unmap_regblock(pdev, map); - - return rc; -} - -/* - * Assume that any RCIEP that emits the CXL memory expander class code - * is an RCD - */ -static bool is_cxl_restricted(struct pci_dev *pdev) -{ - return pci_pcie_type(pdev) == PCI_EXP_TYPE_RC_END; -} - -/* - * CXL v3.0 6.2.3 Table 6-4 - * The table indicates that if PCIe Flit Mode is set, then CXL is in 256B flits - * mode, otherwise it's 68B flits mode. - */ -static bool cxl_pci_flit_256(struct pci_dev *pdev) -{ - u16 lnksta2; - - pcie_capability_read_word(pdev, PCI_EXP_LNKSTA2, &lnksta2); - return lnksta2 & PCI_EXP_LNKSTA2_FLIT; + return cxl_setup_regs(map); } static int cxl_pci_ras_unmask(struct pci_dev *pdev) @@ -404,9 +553,8 @@ static int cxl_pci_ras_unmask(struct pci_dev *pdev) addr = cxlds->regs.ras + CXL_RAS_UNCORRECTABLE_MASK_OFFSET; orig_val = readl(addr); - mask = CXL_RAS_UNCORRECTABLE_MASK_MASK; - if (!cxl_pci_flit_256(pdev)) - mask &= ~CXL_RAS_UNCORRECTABLE_MASK_F256B_MASK; + mask = CXL_RAS_UNCORRECTABLE_MASK_MASK | + CXL_RAS_UNCORRECTABLE_MASK_F256B_MASK; val = orig_val & ~mask; writel(val, addr); dev_dbg(&pdev->dev, @@ -433,18 +581,18 @@ static void free_event_buf(void *buf) /* * There is a single buffer for reading event logs from the mailbox. All logs - * share this buffer protected by the cxlds->event_log_lock. + * share this buffer protected by the mds->event_log_lock. */ -static int cxl_mem_alloc_event_buf(struct cxl_dev_state *cxlds) +static int cxl_mem_alloc_event_buf(struct cxl_memdev_state *mds) { struct cxl_get_event_payload *buf; - buf = kvmalloc(cxlds->payload_size, GFP_KERNEL); + buf = kvmalloc(mds->payload_size, GFP_KERNEL); if (!buf) return -ENOMEM; - cxlds->event.buf = buf; + mds->event.buf = buf; - return devm_add_action_or_reset(cxlds->dev, free_event_buf, buf); + return devm_add_action_or_reset(mds->cxlds.dev, free_event_buf, buf); } static int cxl_alloc_irq_vectors(struct pci_dev *pdev) @@ -469,14 +617,11 @@ static int cxl_alloc_irq_vectors(struct pci_dev *pdev) return 0; } -struct cxl_dev_id { - struct cxl_dev_state *cxlds; -}; - static irqreturn_t cxl_event_thread(int irq, void *id) { struct cxl_dev_id *dev_id = id; struct cxl_dev_state *cxlds = dev_id->cxlds; + struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlds); u32 status; do { @@ -489,7 +634,7 @@ static irqreturn_t cxl_event_thread(int irq, void *id) status &= CXLDEV_EVENT_STATUS_ALL; if (!status) break; - cxl_mem_get_event_records(cxlds, status); + cxl_mem_get_event_records(mds, status); cond_resched(); } while (status); @@ -498,31 +643,21 @@ static irqreturn_t cxl_event_thread(int irq, void *id) static int cxl_event_req_irq(struct cxl_dev_state *cxlds, u8 setting) { - struct device *dev = cxlds->dev; - struct pci_dev *pdev = to_pci_dev(dev); - struct cxl_dev_id *dev_id; + struct pci_dev *pdev = to_pci_dev(cxlds->dev); int irq; if (FIELD_GET(CXLDEV_EVENT_INT_MODE_MASK, setting) != CXL_INT_MSI_MSIX) return -ENXIO; - /* dev_id must be globally unique and must contain the cxlds */ - dev_id = devm_kzalloc(dev, sizeof(*dev_id), GFP_KERNEL); - if (!dev_id) - return -ENOMEM; - dev_id->cxlds = cxlds; - irq = pci_irq_vector(pdev, FIELD_GET(CXLDEV_EVENT_INT_MSGNUM_MASK, setting)); if (irq < 0) return irq; - return devm_request_threaded_irq(dev, irq, NULL, cxl_event_thread, - IRQF_SHARED | IRQF_ONESHOT, NULL, - dev_id); + return cxl_request_irq(cxlds, irq, NULL, cxl_event_thread); } -static int cxl_event_get_int_policy(struct cxl_dev_state *cxlds, +static int cxl_event_get_int_policy(struct cxl_memdev_state *mds, struct cxl_event_interrupt_policy *policy) { struct cxl_mbox_cmd mbox_cmd = { @@ -532,15 +667,15 @@ static int cxl_event_get_int_policy(struct cxl_dev_state *cxlds, }; int rc; - rc = cxl_internal_send_cmd(cxlds, &mbox_cmd); + rc = cxl_internal_send_cmd(mds, &mbox_cmd); if (rc < 0) - dev_err(cxlds->dev, "Failed to get event interrupt policy : %d", - rc); + dev_err(mds->cxlds.dev, + "Failed to get event interrupt policy : %d", rc); return rc; } -static int cxl_event_config_msgnums(struct cxl_dev_state *cxlds, +static int cxl_event_config_msgnums(struct cxl_memdev_state *mds, struct cxl_event_interrupt_policy *policy) { struct cxl_mbox_cmd mbox_cmd; @@ -559,23 +694,24 @@ static int cxl_event_config_msgnums(struct cxl_dev_state *cxlds, .size_in = sizeof(*policy), }; - rc = cxl_internal_send_cmd(cxlds, &mbox_cmd); + rc = cxl_internal_send_cmd(mds, &mbox_cmd); if (rc < 0) { - dev_err(cxlds->dev, "Failed to set event interrupt policy : %d", + dev_err(mds->cxlds.dev, "Failed to set event interrupt policy : %d", rc); return rc; } /* Retrieve final interrupt settings */ - return cxl_event_get_int_policy(cxlds, policy); + return cxl_event_get_int_policy(mds, policy); } -static int cxl_event_irqsetup(struct cxl_dev_state *cxlds) +static int cxl_event_irqsetup(struct cxl_memdev_state *mds) { + struct cxl_dev_state *cxlds = &mds->cxlds; struct cxl_event_interrupt_policy policy; int rc; - rc = cxl_event_config_msgnums(cxlds, &policy); + rc = cxl_event_config_msgnums(mds, &policy); if (rc) return rc; @@ -614,7 +750,7 @@ static bool cxl_event_int_is_fw(u8 setting) } static int cxl_event_config(struct pci_host_bridge *host_bridge, - struct cxl_dev_state *cxlds) + struct cxl_memdev_state *mds) { struct cxl_event_interrupt_policy policy; int rc; @@ -626,11 +762,11 @@ static int cxl_event_config(struct pci_host_bridge *host_bridge, if (!host_bridge->native_cxl_error) return 0; - rc = cxl_mem_alloc_event_buf(cxlds); + rc = cxl_mem_alloc_event_buf(mds); if (rc) return rc; - rc = cxl_event_get_int_policy(cxlds, &policy); + rc = cxl_event_get_int_policy(mds, &policy); if (rc) return rc; @@ -638,15 +774,16 @@ static int cxl_event_config(struct pci_host_bridge *host_bridge, cxl_event_int_is_fw(policy.warn_settings) || cxl_event_int_is_fw(policy.failure_settings) || cxl_event_int_is_fw(policy.fatal_settings)) { - dev_err(cxlds->dev, "FW still in control of Event Logs despite _OSC settings\n"); + dev_err(mds->cxlds.dev, + "FW still in control of Event Logs despite _OSC settings\n"); return -EBUSY; } - rc = cxl_event_irqsetup(cxlds); + rc = cxl_event_irqsetup(mds); if (rc) return rc; - cxl_mem_get_event_records(cxlds, CXLDEV_EVENT_STATUS_ALL); + cxl_mem_get_event_records(mds, CXLDEV_EVENT_STATUS_ALL); return 0; } @@ -654,10 +791,11 @@ static int cxl_event_config(struct pci_host_bridge *host_bridge, static int cxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) { struct pci_host_bridge *host_bridge = pci_find_host_bridge(pdev->bus); + struct cxl_memdev_state *mds; + struct cxl_dev_state *cxlds; struct cxl_register_map map; struct cxl_memdev *cxlmd; - struct cxl_dev_state *cxlds; - int rc; + int i, rc, pmu_count; /* * Double check the anonymous union trickery in struct cxl_regs @@ -671,9 +809,10 @@ static int cxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) return rc; pci_set_master(pdev); - cxlds = cxl_dev_state_create(&pdev->dev); - if (IS_ERR(cxlds)) - return PTR_ERR(cxlds); + mds = cxl_memdev_state_create(&pdev->dev); + if (IS_ERR(mds)) + return PTR_ERR(mds); + cxlds = &mds->cxlds; pci_set_drvdata(pdev, cxlds); cxlds->rcd = is_cxl_restricted(pdev); @@ -684,11 +823,11 @@ static int cxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) dev_warn(&pdev->dev, "Device DVSEC not present, skip CXL.mem init\n"); - rc = cxl_setup_regs(pdev, CXL_REGLOC_RBI_MEMDEV, &map); + rc = cxl_pci_setup_regs(pdev, CXL_REGLOC_RBI_MEMDEV, &map); if (rc) return rc; - rc = cxl_map_device_regs(&pdev->dev, &cxlds->regs.device_regs, &map); + rc = cxl_map_device_regs(&map, &cxlds->regs.device_regs); if (rc) return rc; @@ -697,14 +836,16 @@ static int cxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) * still be useful for management functions so don't return an error. */ cxlds->component_reg_phys = CXL_RESOURCE_NONE; - rc = cxl_setup_regs(pdev, CXL_REGLOC_RBI_COMPONENT, &map); + rc = cxl_pci_setup_regs(pdev, CXL_REGLOC_RBI_COMPONENT, &map); if (rc) dev_warn(&pdev->dev, "No component registers (%d)\n", rc); + else if (!map.component_map.ras.valid) + dev_dbg(&pdev->dev, "RAS registers not found\n"); cxlds->component_reg_phys = map.resource; - rc = cxl_map_component_regs(&pdev->dev, &cxlds->regs.component, - &map, BIT(CXL_CM_CAP_CAP_ID_RAS)); + rc = cxl_map_component_regs(&map, &cxlds->regs.component, + BIT(CXL_CM_CAP_CAP_ID_RAS)); if (rc) dev_dbg(&pdev->dev, "Failed to map RAS capability.\n"); @@ -714,31 +855,31 @@ static int cxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) else dev_warn(&pdev->dev, "Media not active (%d)\n", rc); - rc = cxl_pci_setup_mailbox(cxlds); + rc = cxl_alloc_irq_vectors(pdev); if (rc) return rc; - rc = cxl_enumerate_cmds(cxlds); + rc = cxl_pci_setup_mailbox(mds); if (rc) return rc; - rc = cxl_set_timestamp(cxlds); + rc = cxl_enumerate_cmds(mds); if (rc) return rc; - rc = cxl_poison_state_init(cxlds); + rc = cxl_set_timestamp(mds); if (rc) return rc; - rc = cxl_dev_state_identify(cxlds); + rc = cxl_poison_state_init(mds); if (rc) return rc; - rc = cxl_mem_create_range_info(cxlds); + rc = cxl_dev_state_identify(mds); if (rc) return rc; - rc = cxl_alloc_irq_vectors(pdev); + rc = cxl_mem_create_range_info(mds); if (rc) return rc; @@ -746,7 +887,34 @@ static int cxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) if (IS_ERR(cxlmd)) return PTR_ERR(cxlmd); - rc = cxl_event_config(host_bridge, cxlds); + rc = cxl_memdev_setup_fw_upload(mds); + if (rc) + return rc; + + pmu_count = cxl_count_regblock(pdev, CXL_REGLOC_RBI_PMU); + for (i = 0; i < pmu_count; i++) { + struct cxl_pmu_regs pmu_regs; + + rc = cxl_find_regblock_instance(pdev, CXL_REGLOC_RBI_PMU, &map, i); + if (rc) { + dev_dbg(&pdev->dev, "Could not find PMU regblock\n"); + break; + } + + rc = cxl_map_pmu_regs(pdev, &pmu_regs, &map); + if (rc) { + dev_dbg(&pdev->dev, "Could not map PMU regs\n"); + break; + } + + rc = devm_cxl_pmu_add(cxlds->dev, &pmu_regs, cxlmd->id, i, CXL_PMU_MEMDEV); + if (rc) { + dev_dbg(&pdev->dev, "Could not add PMU instance\n"); + break; + } + } + + rc = cxl_event_config(host_bridge, mds); if (rc) return rc; diff --git a/drivers/cxl/pmem.c b/drivers/cxl/pmem.c index 71cfa1fdf902714e1e97cfafc20302cf84e34138..7cb8994f88097599c7bd17f9adec6273b981e7a5 100644 --- a/drivers/cxl/pmem.c +++ b/drivers/cxl/pmem.c @@ -15,9 +15,9 @@ extern const struct nvdimm_security_ops *cxl_security_ops; static __read_mostly DECLARE_BITMAP(exclusive_cmds, CXL_MEM_COMMAND_ID_MAX); -static void clear_exclusive(void *cxlds) +static void clear_exclusive(void *mds) { - clear_exclusive_cxl_commands(cxlds, exclusive_cmds); + clear_exclusive_cxl_commands(mds, exclusive_cmds); } static void unregister_nvdimm(void *nvdimm) @@ -65,13 +65,13 @@ static int cxl_nvdimm_probe(struct device *dev) struct cxl_nvdimm *cxl_nvd = to_cxl_nvdimm(dev); struct cxl_memdev *cxlmd = cxl_nvd->cxlmd; struct cxl_nvdimm_bridge *cxl_nvb = cxlmd->cxl_nvb; + struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds); unsigned long flags = 0, cmd_mask = 0; - struct cxl_dev_state *cxlds = cxlmd->cxlds; struct nvdimm *nvdimm; int rc; - set_exclusive_cxl_commands(cxlds, exclusive_cmds); - rc = devm_add_action_or_reset(dev, clear_exclusive, cxlds); + set_exclusive_cxl_commands(mds, exclusive_cmds); + rc = devm_add_action_or_reset(dev, clear_exclusive, mds); if (rc) return rc; @@ -100,22 +100,23 @@ static struct cxl_driver cxl_nvdimm_driver = { }, }; -static int cxl_pmem_get_config_size(struct cxl_dev_state *cxlds, +static int cxl_pmem_get_config_size(struct cxl_memdev_state *mds, struct nd_cmd_get_config_size *cmd, unsigned int buf_len) { if (sizeof(*cmd) > buf_len) return -EINVAL; - *cmd = (struct nd_cmd_get_config_size) { - .config_size = cxlds->lsa_size, - .max_xfer = cxlds->payload_size - sizeof(struct cxl_mbox_set_lsa), + *cmd = (struct nd_cmd_get_config_size){ + .config_size = mds->lsa_size, + .max_xfer = + mds->payload_size - sizeof(struct cxl_mbox_set_lsa), }; return 0; } -static int cxl_pmem_get_config_data(struct cxl_dev_state *cxlds, +static int cxl_pmem_get_config_data(struct cxl_memdev_state *mds, struct nd_cmd_get_config_data_hdr *cmd, unsigned int buf_len) { @@ -140,13 +141,13 @@ static int cxl_pmem_get_config_data(struct cxl_dev_state *cxlds, .payload_out = cmd->out_buf, }; - rc = cxl_internal_send_cmd(cxlds, &mbox_cmd); + rc = cxl_internal_send_cmd(mds, &mbox_cmd); cmd->status = 0; return rc; } -static int cxl_pmem_set_config_data(struct cxl_dev_state *cxlds, +static int cxl_pmem_set_config_data(struct cxl_memdev_state *mds, struct nd_cmd_set_config_hdr *cmd, unsigned int buf_len) { @@ -176,7 +177,7 @@ static int cxl_pmem_set_config_data(struct cxl_dev_state *cxlds, .size_in = struct_size(set_lsa, data, cmd->in_length), }; - rc = cxl_internal_send_cmd(cxlds, &mbox_cmd); + rc = cxl_internal_send_cmd(mds, &mbox_cmd); /* * Set "firmware" status (4-packed bytes at the end of the input @@ -194,18 +195,18 @@ static int cxl_pmem_nvdimm_ctl(struct nvdimm *nvdimm, unsigned int cmd, struct cxl_nvdimm *cxl_nvd = nvdimm_provider_data(nvdimm); unsigned long cmd_mask = nvdimm_cmd_mask(nvdimm); struct cxl_memdev *cxlmd = cxl_nvd->cxlmd; - struct cxl_dev_state *cxlds = cxlmd->cxlds; + struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds); if (!test_bit(cmd, &cmd_mask)) return -ENOTTY; switch (cmd) { case ND_CMD_GET_CONFIG_SIZE: - return cxl_pmem_get_config_size(cxlds, buf, buf_len); + return cxl_pmem_get_config_size(mds, buf, buf_len); case ND_CMD_GET_CONFIG_DATA: - return cxl_pmem_get_config_data(cxlds, buf, buf_len); + return cxl_pmem_get_config_data(mds, buf, buf_len); case ND_CMD_SET_CONFIG_DATA: - return cxl_pmem_set_config_data(cxlds, buf, buf_len); + return cxl_pmem_set_config_data(mds, buf, buf_len); default: return -ENOTTY; } diff --git a/drivers/cxl/pmu.h b/drivers/cxl/pmu.h new file mode 100644 index 0000000000000000000000000000000000000000..b1e9bcd9f28cffa318e015c17c97a55daad7c02b --- /dev/null +++ b/drivers/cxl/pmu.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright(c) 2023 Huawei + * CXL Specification rev 3.0 Setion 8.2.7 (CPMU Register Interface) + */ +#ifndef CXL_PMU_H +#define CXL_PMU_H +#include + +enum cxl_pmu_type { + CXL_PMU_MEMDEV, +}; + +#define CXL_PMU_REGMAP_SIZE 0xe00 /* Table 8-32 CXL 3.0 specification */ +struct cxl_pmu { + struct device dev; + void __iomem *base; + int assoc_id; + int index; + enum cxl_pmu_type type; +}; + +#define to_cxl_pmu(dev) container_of(dev, struct cxl_pmu, dev) +struct cxl_pmu_regs; +int devm_cxl_pmu_add(struct device *parent, struct cxl_pmu_regs *regs, + int assoc_id, int idx, enum cxl_pmu_type type); + +#endif diff --git a/drivers/cxl/port.c b/drivers/cxl/port.c index c23b6164e1c0fa5c1e9a9c671c2e1d29da604c69..6240e05b95424b9c9627fcde4a0e50171bde1761 100644 --- a/drivers/cxl/port.c +++ b/drivers/cxl/port.c @@ -60,17 +60,13 @@ static int discover_region(struct device *dev, void *root) static int cxl_switch_port_probe(struct cxl_port *port) { struct cxl_hdm *cxlhdm; - int rc, nr_dports; - - nr_dports = devm_cxl_port_enumerate_dports(port); - if (nr_dports < 0) - return nr_dports; + int rc; - cxlhdm = devm_cxl_setup_hdm(port, NULL); - rc = devm_cxl_enable_hdm(port, cxlhdm); - if (rc) + rc = devm_cxl_port_enumerate_dports(port); + if (rc < 0) return rc; + cxlhdm = devm_cxl_setup_hdm(port, NULL); if (!IS_ERR(cxlhdm)) return devm_cxl_enumerate_decoders(cxlhdm, NULL); @@ -79,7 +75,7 @@ static int cxl_switch_port_probe(struct cxl_port *port) return PTR_ERR(cxlhdm); } - if (nr_dports == 1) { + if (rc == 1) { dev_dbg(&port->dev, "Fallback to passthrough decoder\n"); return devm_cxl_add_passthrough_decoder(port); } @@ -91,7 +87,7 @@ static int cxl_switch_port_probe(struct cxl_port *port) static int cxl_endpoint_port_probe(struct cxl_port *port) { struct cxl_endpoint_dvsec_info info = { .port = port }; - struct cxl_memdev *cxlmd = to_cxl_memdev(port->uport); + struct cxl_memdev *cxlmd = to_cxl_memdev(port->uport_dev); struct cxl_dev_state *cxlds = cxlmd->cxlds; struct cxl_hdm *cxlhdm; struct cxl_port *root; @@ -102,8 +98,11 @@ static int cxl_endpoint_port_probe(struct cxl_port *port) return rc; cxlhdm = devm_cxl_setup_hdm(port, &info); - if (IS_ERR(cxlhdm)) + if (IS_ERR(cxlhdm)) { + if (PTR_ERR(cxlhdm) == -ENODEV) + dev_err(&port->dev, "HDM decoder registers not found\n"); return PTR_ERR(cxlhdm); + } /* Cache the data early to ensure is_visible() works */ read_cdat_data(port); diff --git a/drivers/cxl/security.c b/drivers/cxl/security.c index 4ad4bda2d18e0f5df98dd32626a1f33c20d13012..21856a3f408eee530c69da2748e7f1a0c311d9d8 100644 --- a/drivers/cxl/security.c +++ b/drivers/cxl/security.c @@ -14,7 +14,7 @@ static unsigned long cxl_pmem_get_security_flags(struct nvdimm *nvdimm, { struct cxl_nvdimm *cxl_nvd = nvdimm_provider_data(nvdimm); struct cxl_memdev *cxlmd = cxl_nvd->cxlmd; - struct cxl_dev_state *cxlds = cxlmd->cxlds; + struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds); unsigned long security_flags = 0; struct cxl_get_security_output { __le32 flags; @@ -29,11 +29,14 @@ static unsigned long cxl_pmem_get_security_flags(struct nvdimm *nvdimm, .payload_out = &out, }; - rc = cxl_internal_send_cmd(cxlds, &mbox_cmd); + rc = cxl_internal_send_cmd(mds, &mbox_cmd); if (rc < 0) return 0; sec_out = le32_to_cpu(out.flags); + /* cache security state */ + mds->security.state = sec_out; + if (ptype == NVDIMM_MASTER) { if (sec_out & CXL_PMEM_SEC_STATE_MASTER_PASS_SET) set_bit(NVDIMM_SECURITY_UNLOCKED, &security_flags); @@ -67,7 +70,7 @@ static int cxl_pmem_security_change_key(struct nvdimm *nvdimm, { struct cxl_nvdimm *cxl_nvd = nvdimm_provider_data(nvdimm); struct cxl_memdev *cxlmd = cxl_nvd->cxlmd; - struct cxl_dev_state *cxlds = cxlmd->cxlds; + struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds); struct cxl_mbox_cmd mbox_cmd; struct cxl_set_pass set_pass; @@ -84,7 +87,7 @@ static int cxl_pmem_security_change_key(struct nvdimm *nvdimm, .payload_in = &set_pass, }; - return cxl_internal_send_cmd(cxlds, &mbox_cmd); + return cxl_internal_send_cmd(mds, &mbox_cmd); } static int __cxl_pmem_security_disable(struct nvdimm *nvdimm, @@ -93,7 +96,7 @@ static int __cxl_pmem_security_disable(struct nvdimm *nvdimm, { struct cxl_nvdimm *cxl_nvd = nvdimm_provider_data(nvdimm); struct cxl_memdev *cxlmd = cxl_nvd->cxlmd; - struct cxl_dev_state *cxlds = cxlmd->cxlds; + struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds); struct cxl_disable_pass dis_pass; struct cxl_mbox_cmd mbox_cmd; @@ -109,7 +112,7 @@ static int __cxl_pmem_security_disable(struct nvdimm *nvdimm, .payload_in = &dis_pass, }; - return cxl_internal_send_cmd(cxlds, &mbox_cmd); + return cxl_internal_send_cmd(mds, &mbox_cmd); } static int cxl_pmem_security_disable(struct nvdimm *nvdimm, @@ -128,12 +131,12 @@ static int cxl_pmem_security_freeze(struct nvdimm *nvdimm) { struct cxl_nvdimm *cxl_nvd = nvdimm_provider_data(nvdimm); struct cxl_memdev *cxlmd = cxl_nvd->cxlmd; - struct cxl_dev_state *cxlds = cxlmd->cxlds; + struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds); struct cxl_mbox_cmd mbox_cmd = { .opcode = CXL_MBOX_OP_FREEZE_SECURITY, }; - return cxl_internal_send_cmd(cxlds, &mbox_cmd); + return cxl_internal_send_cmd(mds, &mbox_cmd); } static int cxl_pmem_security_unlock(struct nvdimm *nvdimm, @@ -141,7 +144,7 @@ static int cxl_pmem_security_unlock(struct nvdimm *nvdimm, { struct cxl_nvdimm *cxl_nvd = nvdimm_provider_data(nvdimm); struct cxl_memdev *cxlmd = cxl_nvd->cxlmd; - struct cxl_dev_state *cxlds = cxlmd->cxlds; + struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds); u8 pass[NVDIMM_PASSPHRASE_LEN]; struct cxl_mbox_cmd mbox_cmd; int rc; @@ -153,7 +156,7 @@ static int cxl_pmem_security_unlock(struct nvdimm *nvdimm, .payload_in = pass, }; - rc = cxl_internal_send_cmd(cxlds, &mbox_cmd); + rc = cxl_internal_send_cmd(mds, &mbox_cmd); if (rc < 0) return rc; @@ -166,7 +169,7 @@ static int cxl_pmem_security_passphrase_erase(struct nvdimm *nvdimm, { struct cxl_nvdimm *cxl_nvd = nvdimm_provider_data(nvdimm); struct cxl_memdev *cxlmd = cxl_nvd->cxlmd; - struct cxl_dev_state *cxlds = cxlmd->cxlds; + struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds); struct cxl_mbox_cmd mbox_cmd; struct cxl_pass_erase erase; int rc; @@ -182,7 +185,7 @@ static int cxl_pmem_security_passphrase_erase(struct nvdimm *nvdimm, .payload_in = &erase, }; - rc = cxl_internal_send_cmd(cxlds, &mbox_cmd); + rc = cxl_internal_send_cmd(mds, &mbox_cmd); if (rc < 0) return rc; diff --git a/drivers/dax/bus.c b/drivers/dax/bus.c index 227800053309f8d6adbf2592cc77865a724a4ea4..0ee96e6fc42658ac617f7e4c163c1781e9611491 100644 --- a/drivers/dax/bus.c +++ b/drivers/dax/bus.c @@ -446,18 +446,33 @@ static void unregister_dev_dax(void *dev) put_device(dev); } +static void dax_region_free(struct kref *kref) +{ + struct dax_region *dax_region; + + dax_region = container_of(kref, struct dax_region, kref); + kfree(dax_region); +} + +static void dax_region_put(struct dax_region *dax_region) +{ + kref_put(&dax_region->kref, dax_region_free); +} + /* a return value >= 0 indicates this invocation invalidated the id */ static int __free_dev_dax_id(struct dev_dax *dev_dax) { - struct dax_region *dax_region = dev_dax->region; struct device *dev = &dev_dax->dev; + struct dax_region *dax_region; int rc = dev_dax->id; device_lock_assert(dev); - if (is_static(dax_region) || dev_dax->id < 0) + if (!dev_dax->dyn_id || dev_dax->id < 0) return -1; + dax_region = dev_dax->region; ida_free(&dax_region->ida, dev_dax->id); + dax_region_put(dax_region); dev_dax->id = -1; return rc; } @@ -473,6 +488,20 @@ static int free_dev_dax_id(struct dev_dax *dev_dax) return rc; } +static int alloc_dev_dax_id(struct dev_dax *dev_dax) +{ + struct dax_region *dax_region = dev_dax->region; + int id; + + id = ida_alloc(&dax_region->ida, GFP_KERNEL); + if (id < 0) + return id; + kref_get(&dax_region->kref); + dev_dax->dyn_id = true; + dev_dax->id = id; + return id; +} + static ssize_t delete_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { @@ -560,20 +589,6 @@ static const struct attribute_group *dax_region_attribute_groups[] = { NULL, }; -static void dax_region_free(struct kref *kref) -{ - struct dax_region *dax_region; - - dax_region = container_of(kref, struct dax_region, kref); - kfree(dax_region); -} - -void dax_region_put(struct dax_region *dax_region) -{ - kref_put(&dax_region->kref, dax_region_free); -} -EXPORT_SYMBOL_GPL(dax_region_put); - static void dax_region_unregister(void *region) { struct dax_region *dax_region = region; @@ -625,7 +640,6 @@ struct dax_region *alloc_dax_region(struct device *parent, int region_id, return NULL; } - kref_get(&dax_region->kref); if (devm_add_action_or_reset(parent, dax_region_unregister, dax_region)) return NULL; return dax_region; @@ -635,10 +649,12 @@ EXPORT_SYMBOL_GPL(alloc_dax_region); static void dax_mapping_release(struct device *dev) { struct dax_mapping *mapping = to_dax_mapping(dev); - struct dev_dax *dev_dax = to_dev_dax(dev->parent); + struct device *parent = dev->parent; + struct dev_dax *dev_dax = to_dev_dax(parent); ida_free(&dev_dax->ida, mapping->id); kfree(mapping); + put_device(parent); } static void unregister_dax_mapping(void *data) @@ -655,8 +671,7 @@ static void unregister_dax_mapping(void *data) dev_dax->ranges[mapping->range_id].mapping = NULL; mapping->range_id = -1; - device_del(dev); - put_device(dev); + device_unregister(dev); } static struct dev_dax_range *get_dax_range(struct device *dev) @@ -778,6 +793,7 @@ static int devm_register_dax_mapping(struct dev_dax *dev_dax, int range_id) dev = &mapping->dev; device_initialize(dev); dev->parent = &dev_dax->dev; + get_device(dev->parent); dev->type = &dax_mapping_type; dev_set_name(dev, "mapping%d", mapping->id); rc = device_add(dev); @@ -1295,12 +1311,10 @@ static const struct attribute_group *dax_attribute_groups[] = { static void dev_dax_release(struct device *dev) { struct dev_dax *dev_dax = to_dev_dax(dev); - struct dax_region *dax_region = dev_dax->region; struct dax_device *dax_dev = dev_dax->dax_dev; put_dax(dax_dev); free_dev_dax_id(dev_dax); - dax_region_put(dax_region); kfree(dev_dax->pgmap); kfree(dev_dax); } @@ -1324,6 +1338,7 @@ struct dev_dax *devm_create_dev_dax(struct dev_dax_data *data) if (!dev_dax) return ERR_PTR(-ENOMEM); + dev_dax->region = dax_region; if (is_static(dax_region)) { if (dev_WARN_ONCE(parent, data->id < 0, "dynamic id specified to static region\n")) { @@ -1339,13 +1354,11 @@ struct dev_dax *devm_create_dev_dax(struct dev_dax_data *data) goto err_id; } - rc = ida_alloc(&dax_region->ida, GFP_KERNEL); + rc = alloc_dev_dax_id(dev_dax); if (rc < 0) goto err_id; - dev_dax->id = rc; } - dev_dax->region = dax_region; dev = &dev_dax->dev; device_initialize(dev); dev_set_name(dev, "dax%d.%d", dax_region->id, dev_dax->id); @@ -1386,7 +1399,6 @@ struct dev_dax *devm_create_dev_dax(struct dev_dax_data *data) dev_dax->target_node = dax_region->target_node; dev_dax->align = dax_region->align; ida_init(&dev_dax->ida); - kref_get(&dax_region->kref); inode = dax_inode(dax_dev); dev->devt = inode->i_rdev; diff --git a/drivers/dax/bus.h b/drivers/dax/bus.h index 8cd79ab34292c7267f10f9bb7e44194aec108d6c..1ccd233601248505b2b29ab1cdeb101ed79abe4d 100644 --- a/drivers/dax/bus.h +++ b/drivers/dax/bus.h @@ -9,7 +9,6 @@ struct dev_dax; struct resource; struct dax_device; struct dax_region; -void dax_region_put(struct dax_region *dax_region); /* dax bus specific ioresource flags */ #define IORESOURCE_DAX_STATIC BIT(0) @@ -49,13 +48,6 @@ void dax_driver_unregister(struct dax_device_driver *dax_drv); void kill_dev_dax(struct dev_dax *dev_dax); bool static_dev_dax(struct dev_dax *dev_dax); -/* - * While run_dax() is potentially a generic operation that could be - * defined in include/linux/dax.h we don't want to grow any users - * outside of drivers/dax/ - */ -void run_dax(struct dax_device *dax_dev); - #define MODULE_ALIAS_DAX_DEVICE(type) \ MODULE_ALIAS("dax:t" __stringify(type) "*") #define DAX_DEVICE_MODALIAS_FMT "dax:t%d" diff --git a/drivers/dax/cxl.c b/drivers/dax/cxl.c index ccdf8de85bd5f8b1d9b970a2aca5c81d92f7aebe..8bc9d04034d65e210deabe8bc5b2d9d8dba03aa1 100644 --- a/drivers/dax/cxl.c +++ b/drivers/dax/cxl.c @@ -13,7 +13,6 @@ static int cxl_dax_region_probe(struct device *dev) struct cxl_region *cxlr = cxlr_dax->cxlr; struct dax_region *dax_region; struct dev_dax_data data; - struct dev_dax *dev_dax; if (nid == NUMA_NO_NODE) nid = memory_add_physaddr_to_nid(cxlr_dax->hpa_range.start); @@ -28,13 +27,8 @@ static int cxl_dax_region_probe(struct device *dev) .id = -1, .size = range_len(&cxlr_dax->hpa_range), }; - dev_dax = devm_create_dev_dax(&data); - if (IS_ERR(dev_dax)) - return PTR_ERR(dev_dax); - /* child dev_dax instances now own the lifetime of the dax_region */ - dax_region_put(dax_region); - return 0; + return PTR_ERR_OR_ZERO(devm_create_dev_dax(&data)); } static struct cxl_driver cxl_dax_region_driver = { diff --git a/drivers/dax/dax-private.h b/drivers/dax/dax-private.h index 1c974b7caae6ed9cd58942d00afe2cef22e93d91..27cf2daaaa795ad9b8236b985d01aa0e6cea5c40 100644 --- a/drivers/dax/dax-private.h +++ b/drivers/dax/dax-private.h @@ -52,7 +52,8 @@ struct dax_mapping { * @region - parent region * @dax_dev - core dax functionality * @target_node: effective numa node if dev_dax memory range is onlined - * @id: ida allocated id + * @dyn_id: is this a dynamic or statically created instance + * @id: ida allocated id when the dax_region is not static * @ida: mapping id allocator * @dev - device core * @pgmap - pgmap for memmap setup / lifetime (driver owned) @@ -64,6 +65,7 @@ struct dev_dax { struct dax_device *dax_dev; unsigned int align; int target_node; + bool dyn_id; int id; struct ida ida; struct device dev; @@ -76,6 +78,13 @@ struct dev_dax { } *ranges; }; +/* + * While run_dax() is potentially a generic operation that could be + * defined in include/linux/dax.h we don't want to grow any users + * outside of drivers/dax/ + */ +void run_dax(struct dax_device *dax_dev); + static inline struct dev_dax *to_dev_dax(struct device *dev) { return container_of(dev, struct dev_dax, dev); diff --git a/drivers/dax/device.c b/drivers/dax/device.c index af9930c03c9cf2f054e1ccd745797dab5f547250..30665a3ff6ea365cdfff2fe71b62c43489573e32 100644 --- a/drivers/dax/device.c +++ b/drivers/dax/device.c @@ -396,7 +396,7 @@ static void dev_dax_kill(void *dev_dax) kill_dev_dax(dev_dax); } -int dev_dax_probe(struct dev_dax *dev_dax) +static int dev_dax_probe(struct dev_dax *dev_dax) { struct dax_device *dax_dev = dev_dax->dax_dev; struct device *dev = &dev_dax->dev; @@ -471,7 +471,6 @@ int dev_dax_probe(struct dev_dax *dev_dax) run_dax(dax_dev); return devm_add_action_or_reset(dev, dev_dax_kill, dev_dax); } -EXPORT_SYMBOL_GPL(dev_dax_probe); static struct dax_device_driver device_dax_driver = { .probe = dev_dax_probe, diff --git a/drivers/dax/hmem/hmem.c b/drivers/dax/hmem/hmem.c index e5fe8b39fb94beea985cfb0702ec3a6405977385..5d2ddef0f8f525b8651aa128887aeaa3b02da2aa 100644 --- a/drivers/dax/hmem/hmem.c +++ b/drivers/dax/hmem/hmem.c @@ -16,7 +16,6 @@ static int dax_hmem_probe(struct platform_device *pdev) struct dax_region *dax_region; struct memregion_info *mri; struct dev_dax_data data; - struct dev_dax *dev_dax; /* * @region_idle == true indicates that an administrative agent @@ -38,13 +37,8 @@ static int dax_hmem_probe(struct platform_device *pdev) .id = -1, .size = region_idle ? 0 : range_len(&mri->range), }; - dev_dax = devm_create_dev_dax(&data); - if (IS_ERR(dev_dax)) - return PTR_ERR(dev_dax); - /* child dev_dax instances now own the lifetime of the dax_region */ - dax_region_put(dax_region); - return 0; + return PTR_ERR_OR_ZERO(devm_create_dev_dax(&data)); } static struct platform_driver dax_hmem_driver = { diff --git a/drivers/dax/kmem.c b/drivers/dax/kmem.c index 7b36db6f1cbdcc4dfb20257f26d8b6e26a6f5ff0..898ca95057547ccff02dfe87a019c52c33bf7741 100644 --- a/drivers/dax/kmem.c +++ b/drivers/dax/kmem.c @@ -99,7 +99,7 @@ static int dev_dax_kmem_probe(struct dev_dax *dev_dax) if (!data->res_name) goto err_res_name; - rc = memory_group_register_static(numa_node, total_len); + rc = memory_group_register_static(numa_node, PFN_UP(total_len)); if (rc < 0) goto err_reg_mgid; data->mgid = rc; diff --git a/drivers/dax/pmem.c b/drivers/dax/pmem.c index f050ea78bb83b3df47648fc696d0e3e6d3eadf97..ae0cb113a5d32e5ccaa025ff080b826d7cdfea94 100644 --- a/drivers/dax/pmem.c +++ b/drivers/dax/pmem.c @@ -13,7 +13,6 @@ static struct dev_dax *__dax_pmem_probe(struct device *dev) int rc, id, region_id; resource_size_t offset; struct nd_pfn_sb *pfn_sb; - struct dev_dax *dev_dax; struct dev_dax_data data; struct nd_namespace_io *nsio; struct dax_region *dax_region; @@ -65,12 +64,8 @@ static struct dev_dax *__dax_pmem_probe(struct device *dev) .pgmap = &pgmap, .size = range_len(&range), }; - dev_dax = devm_create_dev_dax(&data); - /* child dev_dax instances now own the lifetime of the dax_region */ - dax_region_put(dax_region); - - return dev_dax; + return devm_create_dev_dax(&data); } static int dax_pmem_probe(struct device *dev) diff --git a/drivers/dax/super.c b/drivers/dax/super.c index c4c4728a36e43380e0fc122139fcee2566bcf382..0da9232ea1754b862455fe6d2d1c0e57398cfde1 100644 --- a/drivers/dax/super.c +++ b/drivers/dax/super.c @@ -203,6 +203,8 @@ size_t dax_copy_to_iter(struct dax_device *dax_dev, pgoff_t pgoff, void *addr, int dax_zero_page_range(struct dax_device *dax_dev, pgoff_t pgoff, size_t nr_pages) { + int ret; + if (!dax_alive(dax_dev)) return -ENXIO; /* @@ -213,7 +215,8 @@ int dax_zero_page_range(struct dax_device *dax_dev, pgoff_t pgoff, if (nr_pages != 1) return -EIO; - return dax_dev->ops->zero_page_range(dax_dev, pgoff, nr_pages); + ret = dax_dev->ops->zero_page_range(dax_dev, pgoff, nr_pages); + return dax_mem2blk_err(ret); } EXPORT_SYMBOL_GPL(dax_zero_page_range); diff --git a/drivers/devfreq/exynos-bus.c b/drivers/devfreq/exynos-bus.c index 88414445adf3a65c66a2a955746811b4d8ec65c1..245898f1a88e231a19e978361b184c1fa2f962cc 100644 --- a/drivers/devfreq/exynos-bus.c +++ b/drivers/devfreq/exynos-bus.c @@ -518,6 +518,7 @@ static struct platform_driver exynos_bus_platdrv = { }; module_platform_driver(exynos_bus_platdrv); +MODULE_SOFTDEP("pre: exynos_ppmu"); MODULE_DESCRIPTION("Generic Exynos Bus frequency driver"); MODULE_AUTHOR("Chanwoo Choi "); MODULE_LICENSE("GPL v2"); diff --git a/drivers/devfreq/mtk-cci-devfreq.c b/drivers/devfreq/mtk-cci-devfreq.c index e5458ada5197a1d5a40d889268205d6c029e2f01..6354622eda65a715b8a3d2ee9110e231cc307790 100644 --- a/drivers/devfreq/mtk-cci-devfreq.c +++ b/drivers/devfreq/mtk-cci-devfreq.c @@ -127,7 +127,7 @@ static int mtk_ccifreq_target(struct device *dev, unsigned long *freq, u32 flags) { struct mtk_ccifreq_drv *drv = dev_get_drvdata(dev); - struct clk *cci_pll = clk_get_parent(drv->cci_clk); + struct clk *cci_pll; struct dev_pm_opp *opp; unsigned long opp_rate; int voltage, pre_voltage, inter_voltage, target_voltage, ret; @@ -139,6 +139,7 @@ static int mtk_ccifreq_target(struct device *dev, unsigned long *freq, return 0; inter_voltage = drv->inter_voltage; + cci_pll = clk_get_parent(drv->cci_clk); opp_rate = *freq; opp = devfreq_recommended_opp(dev, &opp_rate, 1); diff --git a/drivers/dma-buf/dma-fence-unwrap.c b/drivers/dma-buf/dma-fence-unwrap.c index 7002bca792ff0832cc626b5dcb8db659d428272e..c625bb2b5d563647f7a0ec40e0322a519056ea94 100644 --- a/drivers/dma-buf/dma-fence-unwrap.c +++ b/drivers/dma-buf/dma-fence-unwrap.c @@ -66,18 +66,36 @@ struct dma_fence *__dma_fence_unwrap_merge(unsigned int num_fences, { struct dma_fence_array *result; struct dma_fence *tmp, **array; + ktime_t timestamp; unsigned int i; size_t count; count = 0; + timestamp = ns_to_ktime(0); for (i = 0; i < num_fences; ++i) { - dma_fence_unwrap_for_each(tmp, &iter[i], fences[i]) - if (!dma_fence_is_signaled(tmp)) + dma_fence_unwrap_for_each(tmp, &iter[i], fences[i]) { + if (!dma_fence_is_signaled(tmp)) { ++count; + } else if (test_bit(DMA_FENCE_FLAG_TIMESTAMP_BIT, + &tmp->flags)) { + if (ktime_after(tmp->timestamp, timestamp)) + timestamp = tmp->timestamp; + } else { + /* + * Use the current time if the fence is + * currently signaling. + */ + timestamp = ktime_get(); + } + } } + /* + * If we couldn't find a pending fence just return a private signaled + * fence with the timestamp of the last signaled one. + */ if (count == 0) - return dma_fence_get_stub(); + return dma_fence_allocate_private_stub(timestamp); array = kmalloc_array(count, sizeof(*array), GFP_KERNEL); if (!array) @@ -138,7 +156,7 @@ struct dma_fence *__dma_fence_unwrap_merge(unsigned int num_fences, } while (tmp); if (count == 0) { - tmp = dma_fence_get_stub(); + tmp = dma_fence_allocate_private_stub(ktime_get()); goto return_tmp; } diff --git a/drivers/dma-buf/dma-fence.c b/drivers/dma-buf/dma-fence.c index f177c56269bb095cea113da495067cbca39bea79..8aa8f8cb7071efcce29b62cf5ac3bd96c7308056 100644 --- a/drivers/dma-buf/dma-fence.c +++ b/drivers/dma-buf/dma-fence.c @@ -150,16 +150,17 @@ EXPORT_SYMBOL(dma_fence_get_stub); /** * dma_fence_allocate_private_stub - return a private, signaled fence + * @timestamp: timestamp when the fence was signaled * * Return a newly allocated and signaled stub fence. */ -struct dma_fence *dma_fence_allocate_private_stub(void) +struct dma_fence *dma_fence_allocate_private_stub(ktime_t timestamp) { struct dma_fence *fence; fence = kzalloc(sizeof(*fence), GFP_KERNEL); if (fence == NULL) - return ERR_PTR(-ENOMEM); + return NULL; dma_fence_init(fence, &dma_fence_stub_ops, @@ -169,7 +170,7 @@ struct dma_fence *dma_fence_allocate_private_stub(void) set_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT, &fence->flags); - dma_fence_signal(fence); + dma_fence_signal_timestamp(fence, timestamp); return fence; } diff --git a/drivers/dma-buf/udmabuf.c b/drivers/dma-buf/udmabuf.c index 06729cd60136748ac77b60f52eff1fe11eed402e..c406459996489ce7c7844f5a2687ddd76d4c9113 100644 --- a/drivers/dma-buf/udmabuf.c +++ b/drivers/dma-buf/udmabuf.c @@ -12,7 +12,6 @@ #include #include #include -#include #include #include @@ -205,9 +204,7 @@ static long udmabuf_create(struct miscdevice *device, struct udmabuf *ubuf; struct dma_buf *buf; pgoff_t pgoff, pgcnt, pgidx, pgbuf = 0, pglimit; - struct page *page, *hpage = NULL; - pgoff_t subpgoff, maxsubpgs; - struct hstate *hpstate; + struct page *page; int seals, ret = -EINVAL; u32 i, flags; @@ -243,7 +240,7 @@ static long udmabuf_create(struct miscdevice *device, if (!memfd) goto err; mapping = memfd->f_mapping; - if (!shmem_mapping(mapping) && !is_file_hugepages(memfd)) + if (!shmem_mapping(mapping)) goto err; seals = memfd_fcntl(memfd, F_GET_SEALS, 0); if (seals == -EINVAL) @@ -254,48 +251,16 @@ static long udmabuf_create(struct miscdevice *device, goto err; pgoff = list[i].offset >> PAGE_SHIFT; pgcnt = list[i].size >> PAGE_SHIFT; - if (is_file_hugepages(memfd)) { - hpstate = hstate_file(memfd); - pgoff = list[i].offset >> huge_page_shift(hpstate); - subpgoff = (list[i].offset & - ~huge_page_mask(hpstate)) >> PAGE_SHIFT; - maxsubpgs = huge_page_size(hpstate) >> PAGE_SHIFT; - } for (pgidx = 0; pgidx < pgcnt; pgidx++) { - if (is_file_hugepages(memfd)) { - if (!hpage) { - hpage = find_get_page_flags(mapping, pgoff, - FGP_ACCESSED); - if (!hpage) { - ret = -EINVAL; - goto err; - } - } - page = hpage + subpgoff; - get_page(page); - subpgoff++; - if (subpgoff == maxsubpgs) { - put_page(hpage); - hpage = NULL; - subpgoff = 0; - pgoff++; - } - } else { - page = shmem_read_mapping_page(mapping, - pgoff + pgidx); - if (IS_ERR(page)) { - ret = PTR_ERR(page); - goto err; - } + page = shmem_read_mapping_page(mapping, pgoff + pgidx); + if (IS_ERR(page)) { + ret = PTR_ERR(page); + goto err; } ubuf->pages[pgbuf++] = page; } fput(memfd); memfd = NULL; - if (hpage) { - put_page(hpage); - hpage = NULL; - } } exp_info.ops = &udmabuf_ops; diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index f5f422f9b85079b82dee894605c5b77ee7a33d0a..644c188d6a1103ebf6877337dc418fbffe7ea754 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -553,6 +553,7 @@ config STE_DMA40 bool "ST-Ericsson DMA40 support" depends on ARCH_U8500 select DMA_ENGINE + select SRAM help Support for ST-Ericsson DMA40 controller diff --git a/drivers/dma/dma-axi-dmac.c b/drivers/dma/dma-axi-dmac.c index a812b9b00e6bee1fc72edc6ede9a249b7c30aad3..fc7cdad371616adfc8422dc382e7cb9c4b3728d0 100644 --- a/drivers/dma/dma-axi-dmac.c +++ b/drivers/dma/dma-axi-dmac.c @@ -963,7 +963,6 @@ static int axi_dmac_probe(struct platform_device *pdev) dma_dev->device_terminate_all = axi_dmac_terminate_all; dma_dev->device_synchronize = axi_dmac_synchronize; dma_dev->dev = &pdev->dev; - dma_dev->chancnt = 1; dma_dev->src_addr_widths = BIT(dmac->chan.src_width); dma_dev->dst_addr_widths = BIT(dmac->chan.dest_width); dma_dev->directions = BIT(dmac->chan.direction); diff --git a/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c b/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c index 6937cc0c0b653bb60d6a2ecc1339a1026857ce96..796b6caf0babe185dfd4cfd59ee77f55fc64b65e 100644 --- a/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c +++ b/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c @@ -1466,7 +1466,6 @@ static int dw_probe(struct platform_device *pdev) dma_cap_set(DMA_CYCLIC, dw->dma.cap_mask); /* DMA capabilities */ - dw->dma.chancnt = hdata->nr_channels; dw->dma.max_burst = hdata->axi_rw_burst_len; dw->dma.src_addr_widths = AXI_DMA_BUSWIDTHS; dw->dma.dst_addr_widths = AXI_DMA_BUSWIDTHS; diff --git a/drivers/dma/dw-edma/Makefile b/drivers/dma/dw-edma/Makefile index 8d45c0d5689d5738a81455fa50fd9647ccee8552..83ab58f87760831883bcfad788306e1722634a83 100644 --- a/drivers/dma/dw-edma/Makefile +++ b/drivers/dma/dw-edma/Makefile @@ -1,7 +1,9 @@ # SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_DW_EDMA) += dw-edma.o -dw-edma-$(CONFIG_DEBUG_FS) := dw-edma-v0-debugfs.o -dw-edma-objs := dw-edma-core.o \ - dw-edma-v0-core.o $(dw-edma-y) +dw-edma-$(CONFIG_DEBUG_FS) := dw-edma-v0-debugfs.o \ + dw-hdma-v0-debugfs.o +dw-edma-objs := dw-edma-core.o \ + dw-edma-v0-core.o \ + dw-hdma-v0-core.o $(dw-edma-y) obj-$(CONFIG_DW_EDMA_PCIE) += dw-edma-pcie.o diff --git a/drivers/dma/dw-edma/dw-edma-core.c b/drivers/dma/dw-edma/dw-edma-core.c index 7d2b73ef08727a855153d84a914a2a80dcec733a..68236247059d13ae9ece498f393d4c84f345a580 100644 --- a/drivers/dma/dw-edma/dw-edma-core.c +++ b/drivers/dma/dw-edma/dw-edma-core.c @@ -18,6 +18,7 @@ #include "dw-edma-core.h" #include "dw-edma-v0-core.h" +#include "dw-hdma-v0-core.h" #include "../dmaengine.h" #include "../virt-dma.h" @@ -183,6 +184,7 @@ static void vchan_free_desc(struct virt_dma_desc *vdesc) static int dw_edma_start_transfer(struct dw_edma_chan *chan) { + struct dw_edma *dw = chan->dw; struct dw_edma_chunk *child; struct dw_edma_desc *desc; struct virt_dma_desc *vd; @@ -200,7 +202,7 @@ static int dw_edma_start_transfer(struct dw_edma_chan *chan) if (!child) return 0; - dw_edma_v0_core_start(child, !desc->xfer_sz); + dw_edma_core_start(dw, child, !desc->xfer_sz); desc->xfer_sz += child->ll_region.sz; dw_edma_free_burst(child); list_del(&child->list); @@ -287,7 +289,7 @@ static int dw_edma_device_terminate_all(struct dma_chan *dchan) chan->configured = false; } else if (chan->status == EDMA_ST_IDLE) { chan->configured = false; - } else if (dw_edma_v0_core_ch_status(chan) == DMA_COMPLETE) { + } else if (dw_edma_core_ch_status(chan) == DMA_COMPLETE) { /* * The channel is in a false BUSY state, probably didn't * receive or lost an interrupt @@ -599,8 +601,6 @@ static void dw_edma_done_interrupt(struct dw_edma_chan *chan) struct virt_dma_desc *vd; unsigned long flags; - dw_edma_v0_core_clear_done_int(chan); - spin_lock_irqsave(&chan->vc.lock, flags); vd = vchan_next_desc(&chan->vc); if (vd) { @@ -641,8 +641,6 @@ static void dw_edma_abort_interrupt(struct dw_edma_chan *chan) struct virt_dma_desc *vd; unsigned long flags; - dw_edma_v0_core_clear_abort_int(chan); - spin_lock_irqsave(&chan->vc.lock, flags); vd = vchan_next_desc(&chan->vc); if (vd) { @@ -654,63 +652,32 @@ static void dw_edma_abort_interrupt(struct dw_edma_chan *chan) chan->status = EDMA_ST_IDLE; } -static irqreturn_t dw_edma_interrupt(int irq, void *data, bool write) +static inline irqreturn_t dw_edma_interrupt_write(int irq, void *data) { struct dw_edma_irq *dw_irq = data; - struct dw_edma *dw = dw_irq->dw; - unsigned long total, pos, val; - unsigned long off; - u32 mask; - - if (write) { - total = dw->wr_ch_cnt; - off = 0; - mask = dw_irq->wr_mask; - } else { - total = dw->rd_ch_cnt; - off = dw->wr_ch_cnt; - mask = dw_irq->rd_mask; - } - - val = dw_edma_v0_core_status_done_int(dw, write ? - EDMA_DIR_WRITE : - EDMA_DIR_READ); - val &= mask; - for_each_set_bit(pos, &val, total) { - struct dw_edma_chan *chan = &dw->chan[pos + off]; - - dw_edma_done_interrupt(chan); - } - - val = dw_edma_v0_core_status_abort_int(dw, write ? - EDMA_DIR_WRITE : - EDMA_DIR_READ); - val &= mask; - for_each_set_bit(pos, &val, total) { - struct dw_edma_chan *chan = &dw->chan[pos + off]; - - dw_edma_abort_interrupt(chan); - } - return IRQ_HANDLED; -} - -static inline irqreturn_t dw_edma_interrupt_write(int irq, void *data) -{ - return dw_edma_interrupt(irq, data, true); + return dw_edma_core_handle_int(dw_irq, EDMA_DIR_WRITE, + dw_edma_done_interrupt, + dw_edma_abort_interrupt); } static inline irqreturn_t dw_edma_interrupt_read(int irq, void *data) { - return dw_edma_interrupt(irq, data, false); + struct dw_edma_irq *dw_irq = data; + + return dw_edma_core_handle_int(dw_irq, EDMA_DIR_READ, + dw_edma_done_interrupt, + dw_edma_abort_interrupt); } static irqreturn_t dw_edma_interrupt_common(int irq, void *data) { - dw_edma_interrupt(irq, data, true); - dw_edma_interrupt(irq, data, false); + irqreturn_t ret = IRQ_NONE; + + ret |= dw_edma_interrupt_write(irq, data); + ret |= dw_edma_interrupt_read(irq, data); - return IRQ_HANDLED; + return ret; } static int dw_edma_alloc_chan_resources(struct dma_chan *dchan) @@ -811,7 +778,7 @@ static int dw_edma_channel_setup(struct dw_edma *dw, u32 wr_alloc, u32 rd_alloc) vchan_init(&chan->vc, dma); - dw_edma_v0_core_device_config(chan); + dw_edma_core_ch_config(chan); } /* Set DMA channel capabilities */ @@ -956,14 +923,19 @@ int dw_edma_probe(struct dw_edma_chip *chip) dw->chip = chip; + if (dw->chip->mf == EDMA_MF_HDMA_NATIVE) + dw_hdma_v0_core_register(dw); + else + dw_edma_v0_core_register(dw); + raw_spin_lock_init(&dw->lock); dw->wr_ch_cnt = min_t(u16, chip->ll_wr_cnt, - dw_edma_v0_core_ch_count(dw, EDMA_DIR_WRITE)); + dw_edma_core_ch_count(dw, EDMA_DIR_WRITE)); dw->wr_ch_cnt = min_t(u16, dw->wr_ch_cnt, EDMA_MAX_WR_CH); dw->rd_ch_cnt = min_t(u16, chip->ll_rd_cnt, - dw_edma_v0_core_ch_count(dw, EDMA_DIR_READ)); + dw_edma_core_ch_count(dw, EDMA_DIR_READ)); dw->rd_ch_cnt = min_t(u16, dw->rd_ch_cnt, EDMA_MAX_RD_CH); if (!dw->wr_ch_cnt && !dw->rd_ch_cnt) @@ -982,7 +954,7 @@ int dw_edma_probe(struct dw_edma_chip *chip) dev_name(chip->dev)); /* Disable eDMA, only to establish the ideal initial conditions */ - dw_edma_v0_core_off(dw); + dw_edma_core_off(dw); /* Request IRQs */ err = dw_edma_irq_request(dw, &wr_alloc, &rd_alloc); @@ -995,7 +967,7 @@ int dw_edma_probe(struct dw_edma_chip *chip) goto err_irq_free; /* Turn debugfs on */ - dw_edma_v0_core_debugfs_on(dw); + dw_edma_core_debugfs_on(dw); chip->dw = dw; @@ -1021,7 +993,7 @@ int dw_edma_remove(struct dw_edma_chip *chip) return -ENODEV; /* Disable eDMA */ - dw_edma_v0_core_off(dw); + dw_edma_core_off(dw); /* Free irqs */ for (i = (dw->nr_irqs - 1); i >= 0; i--) diff --git a/drivers/dma/dw-edma/dw-edma-core.h b/drivers/dma/dw-edma/dw-edma-core.h index 0ab2b6dba880478f5c2932d2f3645328fb230a6a..71894b9e0b1539c636171738963e80a0a5ef43a4 100644 --- a/drivers/dma/dw-edma/dw-edma-core.h +++ b/drivers/dma/dw-edma/dw-edma-core.h @@ -111,6 +111,21 @@ struct dw_edma { raw_spinlock_t lock; /* Only for legacy */ struct dw_edma_chip *chip; + + const struct dw_edma_core_ops *core; +}; + +typedef void (*dw_edma_handler_t)(struct dw_edma_chan *); + +struct dw_edma_core_ops { + void (*off)(struct dw_edma *dw); + u16 (*ch_count)(struct dw_edma *dw, enum dw_edma_dir dir); + enum dma_status (*ch_status)(struct dw_edma_chan *chan); + irqreturn_t (*handle_int)(struct dw_edma_irq *dw_irq, enum dw_edma_dir dir, + dw_edma_handler_t done, dw_edma_handler_t abort); + void (*start)(struct dw_edma_chunk *chunk, bool first); + void (*ch_config)(struct dw_edma_chan *chan); + void (*debugfs_on)(struct dw_edma *dw); }; struct dw_edma_sg { @@ -148,4 +163,47 @@ struct dw_edma_chan *dchan2dw_edma_chan(struct dma_chan *dchan) return vc2dw_edma_chan(to_virt_chan(dchan)); } +static inline +void dw_edma_core_off(struct dw_edma *dw) +{ + dw->core->off(dw); +} + +static inline +u16 dw_edma_core_ch_count(struct dw_edma *dw, enum dw_edma_dir dir) +{ + return dw->core->ch_count(dw, dir); +} + +static inline +enum dma_status dw_edma_core_ch_status(struct dw_edma_chan *chan) +{ + return chan->dw->core->ch_status(chan); +} + +static inline irqreturn_t +dw_edma_core_handle_int(struct dw_edma_irq *dw_irq, enum dw_edma_dir dir, + dw_edma_handler_t done, dw_edma_handler_t abort) +{ + return dw_irq->dw->core->handle_int(dw_irq, dir, done, abort); +} + +static inline +void dw_edma_core_start(struct dw_edma *dw, struct dw_edma_chunk *chunk, bool first) +{ + dw->core->start(chunk, first); +} + +static inline +void dw_edma_core_ch_config(struct dw_edma_chan *chan) +{ + chan->dw->core->ch_config(chan); +} + +static inline +void dw_edma_core_debugfs_on(struct dw_edma *dw) +{ + dw->core->debugfs_on(dw); +} + #endif /* _DW_EDMA_CORE_H */ diff --git a/drivers/dma/dw-edma/dw-edma-pcie.c b/drivers/dma/dw-edma/dw-edma-pcie.c index 2b40f2b44f5e19b801b99401ddf2700553a241de..1c6043751dc92548164d5fd99c0c8f61f642f489 100644 --- a/drivers/dma/dw-edma/dw-edma-pcie.c +++ b/drivers/dma/dw-edma/dw-edma-pcie.c @@ -109,7 +109,7 @@ static u64 dw_edma_pcie_address(struct device *dev, phys_addr_t cpu_addr) return region.start; } -static const struct dw_edma_core_ops dw_edma_pcie_core_ops = { +static const struct dw_edma_plat_ops dw_edma_pcie_plat_ops = { .irq_vector = dw_edma_pcie_irq_vector, .pci_address = dw_edma_pcie_address, }; @@ -225,7 +225,7 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev, chip->mf = vsec_data.mf; chip->nr_irqs = nr_irqs; - chip->ops = &dw_edma_pcie_core_ops; + chip->ops = &dw_edma_pcie_plat_ops; chip->ll_wr_cnt = vsec_data.wr_ch_cnt; chip->ll_rd_cnt = vsec_data.rd_ch_cnt; diff --git a/drivers/dma/dw-edma/dw-edma-v0-core.c b/drivers/dma/dw-edma/dw-edma-v0-core.c index 32f834a3848a15dbd909d5893d3c3a3b119bd1a2..b38786f0ad7995d9b0d22aa18fdd6d2407320c26 100644 --- a/drivers/dma/dw-edma/dw-edma-v0-core.c +++ b/drivers/dma/dw-edma/dw-edma-v0-core.c @@ -7,7 +7,7 @@ */ #include - +#include #include #include "dw-edma-core.h" @@ -160,7 +160,7 @@ static inline u32 readl_ch(struct dw_edma *dw, enum dw_edma_dir dir, u16 ch, readl_ch(dw, dir, ch, &(__dw_ch_regs(dw, dir, ch)->name)) /* eDMA management callbacks */ -void dw_edma_v0_core_off(struct dw_edma *dw) +static void dw_edma_v0_core_off(struct dw_edma *dw) { SET_BOTH_32(dw, int_mask, EDMA_V0_DONE_INT_MASK | EDMA_V0_ABORT_INT_MASK); @@ -169,7 +169,7 @@ void dw_edma_v0_core_off(struct dw_edma *dw) SET_BOTH_32(dw, engine_en, 0); } -u16 dw_edma_v0_core_ch_count(struct dw_edma *dw, enum dw_edma_dir dir) +static u16 dw_edma_v0_core_ch_count(struct dw_edma *dw, enum dw_edma_dir dir) { u32 num_ch; @@ -186,7 +186,7 @@ u16 dw_edma_v0_core_ch_count(struct dw_edma *dw, enum dw_edma_dir dir) return (u16)num_ch; } -enum dma_status dw_edma_v0_core_ch_status(struct dw_edma_chan *chan) +static enum dma_status dw_edma_v0_core_ch_status(struct dw_edma_chan *chan) { struct dw_edma *dw = chan->dw; u32 tmp; @@ -202,7 +202,7 @@ enum dma_status dw_edma_v0_core_ch_status(struct dw_edma_chan *chan) return DMA_ERROR; } -void dw_edma_v0_core_clear_done_int(struct dw_edma_chan *chan) +static void dw_edma_v0_core_clear_done_int(struct dw_edma_chan *chan) { struct dw_edma *dw = chan->dw; @@ -210,7 +210,7 @@ void dw_edma_v0_core_clear_done_int(struct dw_edma_chan *chan) FIELD_PREP(EDMA_V0_DONE_INT_MASK, BIT(chan->id))); } -void dw_edma_v0_core_clear_abort_int(struct dw_edma_chan *chan) +static void dw_edma_v0_core_clear_abort_int(struct dw_edma_chan *chan) { struct dw_edma *dw = chan->dw; @@ -218,18 +218,64 @@ void dw_edma_v0_core_clear_abort_int(struct dw_edma_chan *chan) FIELD_PREP(EDMA_V0_ABORT_INT_MASK, BIT(chan->id))); } -u32 dw_edma_v0_core_status_done_int(struct dw_edma *dw, enum dw_edma_dir dir) +static u32 dw_edma_v0_core_status_done_int(struct dw_edma *dw, enum dw_edma_dir dir) { return FIELD_GET(EDMA_V0_DONE_INT_MASK, GET_RW_32(dw, dir, int_status)); } -u32 dw_edma_v0_core_status_abort_int(struct dw_edma *dw, enum dw_edma_dir dir) +static u32 dw_edma_v0_core_status_abort_int(struct dw_edma *dw, enum dw_edma_dir dir) { return FIELD_GET(EDMA_V0_ABORT_INT_MASK, GET_RW_32(dw, dir, int_status)); } +static irqreturn_t +dw_edma_v0_core_handle_int(struct dw_edma_irq *dw_irq, enum dw_edma_dir dir, + dw_edma_handler_t done, dw_edma_handler_t abort) +{ + struct dw_edma *dw = dw_irq->dw; + unsigned long total, pos, val; + irqreturn_t ret = IRQ_NONE; + struct dw_edma_chan *chan; + unsigned long off; + u32 mask; + + if (dir == EDMA_DIR_WRITE) { + total = dw->wr_ch_cnt; + off = 0; + mask = dw_irq->wr_mask; + } else { + total = dw->rd_ch_cnt; + off = dw->wr_ch_cnt; + mask = dw_irq->rd_mask; + } + + val = dw_edma_v0_core_status_done_int(dw, dir); + val &= mask; + for_each_set_bit(pos, &val, total) { + chan = &dw->chan[pos + off]; + + dw_edma_v0_core_clear_done_int(chan); + done(chan); + + ret = IRQ_HANDLED; + } + + val = dw_edma_v0_core_status_abort_int(dw, dir); + val &= mask; + for_each_set_bit(pos, &val, total) { + chan = &dw->chan[pos + off]; + + dw_edma_v0_core_clear_abort_int(chan); + abort(chan); + + ret = IRQ_HANDLED; + } + + return ret; +} + static void dw_edma_v0_write_ll_data(struct dw_edma_chunk *chunk, int i, u32 control, u32 size, u64 sar, u64 dar) { @@ -300,7 +346,7 @@ static void dw_edma_v0_core_write_chunk(struct dw_edma_chunk *chunk) dw_edma_v0_write_ll_link(chunk, i, control, chunk->ll_region.paddr); } -void dw_edma_v0_core_start(struct dw_edma_chunk *chunk, bool first) +static void dw_edma_v0_core_start(struct dw_edma_chunk *chunk, bool first) { struct dw_edma_chan *chan = chunk->chan; struct dw_edma *dw = chan->dw; @@ -371,7 +417,7 @@ void dw_edma_v0_core_start(struct dw_edma_chunk *chunk, bool first) FIELD_PREP(EDMA_V0_DOORBELL_CH_MASK, chan->id)); } -int dw_edma_v0_core_device_config(struct dw_edma_chan *chan) +static void dw_edma_v0_core_ch_config(struct dw_edma_chan *chan) { struct dw_edma *dw = chan->dw; u32 tmp = 0; @@ -438,12 +484,25 @@ int dw_edma_v0_core_device_config(struct dw_edma_chan *chan) SET_RW_32(dw, chan->dir, ch67_imwr_data, tmp); break; } - - return 0; } /* eDMA debugfs callbacks */ -void dw_edma_v0_core_debugfs_on(struct dw_edma *dw) +static void dw_edma_v0_core_debugfs_on(struct dw_edma *dw) { dw_edma_v0_debugfs_on(dw); } + +static const struct dw_edma_core_ops dw_edma_v0_core = { + .off = dw_edma_v0_core_off, + .ch_count = dw_edma_v0_core_ch_count, + .ch_status = dw_edma_v0_core_ch_status, + .handle_int = dw_edma_v0_core_handle_int, + .start = dw_edma_v0_core_start, + .ch_config = dw_edma_v0_core_ch_config, + .debugfs_on = dw_edma_v0_core_debugfs_on, +}; + +void dw_edma_v0_core_register(struct dw_edma *dw) +{ + dw->core = &dw_edma_v0_core; +} diff --git a/drivers/dma/dw-edma/dw-edma-v0-core.h b/drivers/dma/dw-edma/dw-edma-v0-core.h index ab96a1f480809af76b01e6f338bdaa5d4a39505b..04a882222f99e362f9ebe56d9be9b787f187ce6b 100644 --- a/drivers/dma/dw-edma/dw-edma-v0-core.h +++ b/drivers/dma/dw-edma/dw-edma-v0-core.h @@ -11,17 +11,7 @@ #include -/* eDMA management callbacks */ -void dw_edma_v0_core_off(struct dw_edma *chan); -u16 dw_edma_v0_core_ch_count(struct dw_edma *chan, enum dw_edma_dir dir); -enum dma_status dw_edma_v0_core_ch_status(struct dw_edma_chan *chan); -void dw_edma_v0_core_clear_done_int(struct dw_edma_chan *chan); -void dw_edma_v0_core_clear_abort_int(struct dw_edma_chan *chan); -u32 dw_edma_v0_core_status_done_int(struct dw_edma *chan, enum dw_edma_dir dir); -u32 dw_edma_v0_core_status_abort_int(struct dw_edma *chan, enum dw_edma_dir dir); -void dw_edma_v0_core_start(struct dw_edma_chunk *chunk, bool first); -int dw_edma_v0_core_device_config(struct dw_edma_chan *chan); -/* eDMA debug fs callbacks */ -void dw_edma_v0_core_debugfs_on(struct dw_edma *dw); +/* eDMA core register */ +void dw_edma_v0_core_register(struct dw_edma *dw); #endif /* _DW_EDMA_V0_CORE_H */ diff --git a/drivers/dma/dw-edma/dw-hdma-v0-core.c b/drivers/dma/dw-edma/dw-hdma-v0-core.c new file mode 100644 index 0000000000000000000000000000000000000000..00b735a0202ab2e8e030910db2747c02be8bf75e --- /dev/null +++ b/drivers/dma/dw-edma/dw-hdma-v0-core.c @@ -0,0 +1,296 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2023 Cai Huoqing + * Synopsys DesignWare HDMA v0 core + */ + +#include +#include +#include + +#include "dw-edma-core.h" +#include "dw-hdma-v0-core.h" +#include "dw-hdma-v0-regs.h" +#include "dw-hdma-v0-debugfs.h" + +enum dw_hdma_control { + DW_HDMA_V0_CB = BIT(0), + DW_HDMA_V0_TCB = BIT(1), + DW_HDMA_V0_LLP = BIT(2), + DW_HDMA_V0_LIE = BIT(3), + DW_HDMA_V0_RIE = BIT(4), + DW_HDMA_V0_CCS = BIT(8), + DW_HDMA_V0_LLE = BIT(9), +}; + +static inline struct dw_hdma_v0_regs __iomem *__dw_regs(struct dw_edma *dw) +{ + return dw->chip->reg_base; +} + +static inline struct dw_hdma_v0_ch_regs __iomem * +__dw_ch_regs(struct dw_edma *dw, enum dw_edma_dir dir, u16 ch) +{ + if (dir == EDMA_DIR_WRITE) + return &(__dw_regs(dw)->ch[ch].wr); + else + return &(__dw_regs(dw)->ch[ch].rd); +} + +#define SET_CH_32(dw, dir, ch, name, value) \ + writel(value, &(__dw_ch_regs(dw, dir, ch)->name)) + +#define GET_CH_32(dw, dir, ch, name) \ + readl(&(__dw_ch_regs(dw, dir, ch)->name)) + +#define SET_BOTH_CH_32(dw, ch, name, value) \ + do { \ + writel(value, &(__dw_ch_regs(dw, EDMA_DIR_WRITE, ch)->name)); \ + writel(value, &(__dw_ch_regs(dw, EDMA_DIR_READ, ch)->name)); \ + } while (0) + +/* HDMA management callbacks */ +static void dw_hdma_v0_core_off(struct dw_edma *dw) +{ + int id; + + for (id = 0; id < HDMA_V0_MAX_NR_CH; id++) { + SET_BOTH_CH_32(dw, id, int_setup, + HDMA_V0_STOP_INT_MASK | HDMA_V0_ABORT_INT_MASK); + SET_BOTH_CH_32(dw, id, int_clear, + HDMA_V0_STOP_INT_MASK | HDMA_V0_ABORT_INT_MASK); + SET_BOTH_CH_32(dw, id, ch_en, 0); + } +} + +static u16 dw_hdma_v0_core_ch_count(struct dw_edma *dw, enum dw_edma_dir dir) +{ + u32 num_ch = 0; + int id; + + for (id = 0; id < HDMA_V0_MAX_NR_CH; id++) { + if (GET_CH_32(dw, id, dir, ch_en) & BIT(0)) + num_ch++; + } + + if (num_ch > HDMA_V0_MAX_NR_CH) + num_ch = HDMA_V0_MAX_NR_CH; + + return (u16)num_ch; +} + +static enum dma_status dw_hdma_v0_core_ch_status(struct dw_edma_chan *chan) +{ + struct dw_edma *dw = chan->dw; + u32 tmp; + + tmp = FIELD_GET(HDMA_V0_CH_STATUS_MASK, + GET_CH_32(dw, chan->id, chan->dir, ch_stat)); + + if (tmp == 1) + return DMA_IN_PROGRESS; + else if (tmp == 3) + return DMA_COMPLETE; + else + return DMA_ERROR; +} + +static void dw_hdma_v0_core_clear_done_int(struct dw_edma_chan *chan) +{ + struct dw_edma *dw = chan->dw; + + SET_CH_32(dw, chan->dir, chan->id, int_clear, HDMA_V0_STOP_INT_MASK); +} + +static void dw_hdma_v0_core_clear_abort_int(struct dw_edma_chan *chan) +{ + struct dw_edma *dw = chan->dw; + + SET_CH_32(dw, chan->dir, chan->id, int_clear, HDMA_V0_ABORT_INT_MASK); +} + +static u32 dw_hdma_v0_core_status_int(struct dw_edma_chan *chan) +{ + struct dw_edma *dw = chan->dw; + + return GET_CH_32(dw, chan->dir, chan->id, int_stat); +} + +static irqreturn_t +dw_hdma_v0_core_handle_int(struct dw_edma_irq *dw_irq, enum dw_edma_dir dir, + dw_edma_handler_t done, dw_edma_handler_t abort) +{ + struct dw_edma *dw = dw_irq->dw; + unsigned long total, pos, val; + irqreturn_t ret = IRQ_NONE; + struct dw_edma_chan *chan; + unsigned long off, mask; + + if (dir == EDMA_DIR_WRITE) { + total = dw->wr_ch_cnt; + off = 0; + mask = dw_irq->wr_mask; + } else { + total = dw->rd_ch_cnt; + off = dw->wr_ch_cnt; + mask = dw_irq->rd_mask; + } + + for_each_set_bit(pos, &mask, total) { + chan = &dw->chan[pos + off]; + + val = dw_hdma_v0_core_status_int(chan); + if (FIELD_GET(HDMA_V0_STOP_INT_MASK, val)) { + dw_hdma_v0_core_clear_done_int(chan); + done(chan); + + ret = IRQ_HANDLED; + } + + if (FIELD_GET(HDMA_V0_ABORT_INT_MASK, val)) { + dw_hdma_v0_core_clear_abort_int(chan); + abort(chan); + + ret = IRQ_HANDLED; + } + } + + return ret; +} + +static void dw_hdma_v0_write_ll_data(struct dw_edma_chunk *chunk, int i, + u32 control, u32 size, u64 sar, u64 dar) +{ + ptrdiff_t ofs = i * sizeof(struct dw_hdma_v0_lli); + + if (chunk->chan->dw->chip->flags & DW_EDMA_CHIP_LOCAL) { + struct dw_hdma_v0_lli *lli = chunk->ll_region.vaddr.mem + ofs; + + lli->control = control; + lli->transfer_size = size; + lli->sar.reg = sar; + lli->dar.reg = dar; + } else { + struct dw_hdma_v0_lli __iomem *lli = chunk->ll_region.vaddr.io + ofs; + + writel(control, &lli->control); + writel(size, &lli->transfer_size); + writeq(sar, &lli->sar.reg); + writeq(dar, &lli->dar.reg); + } +} + +static void dw_hdma_v0_write_ll_link(struct dw_edma_chunk *chunk, + int i, u32 control, u64 pointer) +{ + ptrdiff_t ofs = i * sizeof(struct dw_hdma_v0_lli); + + if (chunk->chan->dw->chip->flags & DW_EDMA_CHIP_LOCAL) { + struct dw_hdma_v0_llp *llp = chunk->ll_region.vaddr.mem + ofs; + + llp->control = control; + llp->llp.reg = pointer; + } else { + struct dw_hdma_v0_llp __iomem *llp = chunk->ll_region.vaddr.io + ofs; + + writel(control, &llp->control); + writeq(pointer, &llp->llp.reg); + } +} + +static void dw_hdma_v0_core_write_chunk(struct dw_edma_chunk *chunk) +{ + struct dw_edma_burst *child; + struct dw_edma_chan *chan = chunk->chan; + u32 control = 0, i = 0; + int j; + + if (chunk->cb) + control = DW_HDMA_V0_CB; + + j = chunk->bursts_alloc; + list_for_each_entry(child, &chunk->burst->list, list) { + j--; + if (!j) { + control |= DW_HDMA_V0_LIE; + if (!(chan->dw->chip->flags & DW_EDMA_CHIP_LOCAL)) + control |= DW_HDMA_V0_RIE; + } + + dw_hdma_v0_write_ll_data(chunk, i++, control, child->sz, + child->sar, child->dar); + } + + control = DW_HDMA_V0_LLP | DW_HDMA_V0_TCB; + if (!chunk->cb) + control |= DW_HDMA_V0_CB; + + dw_hdma_v0_write_ll_link(chunk, i, control, chunk->ll_region.paddr); +} + +static void dw_hdma_v0_core_start(struct dw_edma_chunk *chunk, bool first) +{ + struct dw_edma_chan *chan = chunk->chan; + struct dw_edma *dw = chan->dw; + u32 tmp; + + dw_hdma_v0_core_write_chunk(chunk); + + if (first) { + /* Enable engine */ + SET_CH_32(dw, chan->dir, chan->id, ch_en, BIT(0)); + /* Interrupt enable&unmask - done, abort */ + tmp = GET_CH_32(dw, chan->dir, chan->id, int_setup) | + HDMA_V0_STOP_INT_MASK | HDMA_V0_ABORT_INT_MASK | + HDMA_V0_LOCAL_STOP_INT_EN | HDMA_V0_LOCAL_STOP_INT_EN; + SET_CH_32(dw, chan->dir, chan->id, int_setup, tmp); + /* Channel control */ + SET_CH_32(dw, chan->dir, chan->id, control1, HDMA_V0_LINKLIST_EN); + /* Linked list */ + /* llp is not aligned on 64bit -> keep 32bit accesses */ + SET_CH_32(dw, chan->dir, chan->id, llp.lsb, + lower_32_bits(chunk->ll_region.paddr)); + SET_CH_32(dw, chan->dir, chan->id, llp.msb, + upper_32_bits(chunk->ll_region.paddr)); + } + /* Set consumer cycle */ + SET_CH_32(dw, chan->dir, chan->id, cycle_sync, + HDMA_V0_CONSUMER_CYCLE_STAT | HDMA_V0_CONSUMER_CYCLE_BIT); + /* Doorbell */ + SET_CH_32(dw, chan->dir, chan->id, doorbell, HDMA_V0_DOORBELL_START); +} + +static void dw_hdma_v0_core_ch_config(struct dw_edma_chan *chan) +{ + struct dw_edma *dw = chan->dw; + + /* MSI done addr - low, high */ + SET_CH_32(dw, chan->dir, chan->id, msi_stop.lsb, chan->msi.address_lo); + SET_CH_32(dw, chan->dir, chan->id, msi_stop.msb, chan->msi.address_hi); + /* MSI abort addr - low, high */ + SET_CH_32(dw, chan->dir, chan->id, msi_abort.lsb, chan->msi.address_lo); + SET_CH_32(dw, chan->dir, chan->id, msi_abort.msb, chan->msi.address_hi); + /* config MSI data */ + SET_CH_32(dw, chan->dir, chan->id, msi_msgdata, chan->msi.data); +} + +/* HDMA debugfs callbacks */ +static void dw_hdma_v0_core_debugfs_on(struct dw_edma *dw) +{ + dw_hdma_v0_debugfs_on(dw); +} + +static const struct dw_edma_core_ops dw_hdma_v0_core = { + .off = dw_hdma_v0_core_off, + .ch_count = dw_hdma_v0_core_ch_count, + .ch_status = dw_hdma_v0_core_ch_status, + .handle_int = dw_hdma_v0_core_handle_int, + .start = dw_hdma_v0_core_start, + .ch_config = dw_hdma_v0_core_ch_config, + .debugfs_on = dw_hdma_v0_core_debugfs_on, +}; + +void dw_hdma_v0_core_register(struct dw_edma *dw) +{ + dw->core = &dw_hdma_v0_core; +} diff --git a/drivers/dma/dw-edma/dw-hdma-v0-core.h b/drivers/dma/dw-edma/dw-hdma-v0-core.h new file mode 100644 index 0000000000000000000000000000000000000000..c373b4f0bd8ac71846de5e575c35dc258ab3f1f2 --- /dev/null +++ b/drivers/dma/dw-edma/dw-hdma-v0-core.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2023 Cai Huoqing + * Synopsys DesignWare HDMA v0 core + * + * Author: Cai Huoqing + */ + +#ifndef _DW_HDMA_V0_CORE_H +#define _DW_HDMA_V0_CORE_H + +#include + +/* HDMA core register */ +void dw_hdma_v0_core_register(struct dw_edma *dw); + +#endif /* _DW_HDMA_V0_CORE_H */ diff --git a/drivers/dma/dw-edma/dw-hdma-v0-debugfs.c b/drivers/dma/dw-edma/dw-hdma-v0-debugfs.c new file mode 100644 index 0000000000000000000000000000000000000000..520c81978b085fb244311d041faf1786ec7b5750 --- /dev/null +++ b/drivers/dma/dw-edma/dw-hdma-v0-debugfs.c @@ -0,0 +1,170 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2023 Cai Huoqing + * Synopsys DesignWare HDMA v0 debugfs + * + * Author: Cai Huoqing + */ + +#include +#include + +#include "dw-hdma-v0-debugfs.h" +#include "dw-hdma-v0-regs.h" +#include "dw-edma-core.h" + +#define REGS_ADDR(dw, name) \ + ({ \ + struct dw_hdma_v0_regs __iomem *__regs = (dw)->chip->reg_base; \ + \ + (void __iomem *)&__regs->name; \ + }) + +#define REGS_CH_ADDR(dw, name, _dir, _ch) \ + ({ \ + struct dw_hdma_v0_ch_regs __iomem *__ch_regs; \ + \ + if (_dir == EDMA_DIR_READ) \ + __ch_regs = REGS_ADDR(dw, ch[_ch].rd); \ + else \ + __ch_regs = REGS_ADDR(dw, ch[_ch].wr); \ + \ + (void __iomem *)&__ch_regs->name; \ + }) + +#define CTX_REGISTER(dw, name, dir, ch) \ + {#name, REGS_CH_ADDR(dw, name, dir, ch)} + +#define WRITE_STR "write" +#define READ_STR "read" +#define CHANNEL_STR "channel" +#define REGISTERS_STR "registers" + +struct dw_hdma_debugfs_entry { + const char *name; + void __iomem *reg; +}; + +static int dw_hdma_debugfs_u32_get(void *data, u64 *val) +{ + struct dw_hdma_debugfs_entry *entry = data; + void __iomem *reg = entry->reg; + + *val = readl(reg); + + return 0; +} +DEFINE_DEBUGFS_ATTRIBUTE(fops_x32, dw_hdma_debugfs_u32_get, NULL, "0x%08llx\n"); + +static void dw_hdma_debugfs_create_x32(struct dw_edma *dw, + const struct dw_hdma_debugfs_entry ini[], + int nr_entries, struct dentry *dent) +{ + struct dw_hdma_debugfs_entry *entries; + int i; + + entries = devm_kcalloc(dw->chip->dev, nr_entries, sizeof(*entries), + GFP_KERNEL); + if (!entries) + return; + + for (i = 0; i < nr_entries; i++) { + entries[i] = ini[i]; + + debugfs_create_file_unsafe(entries[i].name, 0444, dent, + &entries[i], &fops_x32); + } +} + +static void dw_hdma_debugfs_regs_ch(struct dw_edma *dw, enum dw_edma_dir dir, + u16 ch, struct dentry *dent) +{ + const struct dw_hdma_debugfs_entry debugfs_regs[] = { + CTX_REGISTER(dw, ch_en, dir, ch), + CTX_REGISTER(dw, doorbell, dir, ch), + CTX_REGISTER(dw, prefetch, dir, ch), + CTX_REGISTER(dw, handshake, dir, ch), + CTX_REGISTER(dw, llp.lsb, dir, ch), + CTX_REGISTER(dw, llp.msb, dir, ch), + CTX_REGISTER(dw, cycle_sync, dir, ch), + CTX_REGISTER(dw, transfer_size, dir, ch), + CTX_REGISTER(dw, sar.lsb, dir, ch), + CTX_REGISTER(dw, sar.msb, dir, ch), + CTX_REGISTER(dw, dar.lsb, dir, ch), + CTX_REGISTER(dw, dar.msb, dir, ch), + CTX_REGISTER(dw, watermark_en, dir, ch), + CTX_REGISTER(dw, control1, dir, ch), + CTX_REGISTER(dw, func_num, dir, ch), + CTX_REGISTER(dw, qos, dir, ch), + CTX_REGISTER(dw, ch_stat, dir, ch), + CTX_REGISTER(dw, int_stat, dir, ch), + CTX_REGISTER(dw, int_setup, dir, ch), + CTX_REGISTER(dw, int_clear, dir, ch), + CTX_REGISTER(dw, msi_stop.lsb, dir, ch), + CTX_REGISTER(dw, msi_stop.msb, dir, ch), + CTX_REGISTER(dw, msi_watermark.lsb, dir, ch), + CTX_REGISTER(dw, msi_watermark.msb, dir, ch), + CTX_REGISTER(dw, msi_abort.lsb, dir, ch), + CTX_REGISTER(dw, msi_abort.msb, dir, ch), + CTX_REGISTER(dw, msi_msgdata, dir, ch), + }; + int nr_entries = ARRAY_SIZE(debugfs_regs); + + dw_hdma_debugfs_create_x32(dw, debugfs_regs, nr_entries, dent); +} + +static void dw_hdma_debugfs_regs_wr(struct dw_edma *dw, struct dentry *dent) +{ + struct dentry *regs_dent, *ch_dent; + char name[16]; + int i; + + regs_dent = debugfs_create_dir(WRITE_STR, dent); + + for (i = 0; i < dw->wr_ch_cnt; i++) { + snprintf(name, sizeof(name), "%s:%d", CHANNEL_STR, i); + + ch_dent = debugfs_create_dir(name, regs_dent); + + dw_hdma_debugfs_regs_ch(dw, EDMA_DIR_WRITE, i, ch_dent); + } +} + +static void dw_hdma_debugfs_regs_rd(struct dw_edma *dw, struct dentry *dent) +{ + struct dentry *regs_dent, *ch_dent; + char name[16]; + int i; + + regs_dent = debugfs_create_dir(READ_STR, dent); + + for (i = 0; i < dw->rd_ch_cnt; i++) { + snprintf(name, sizeof(name), "%s:%d", CHANNEL_STR, i); + + ch_dent = debugfs_create_dir(name, regs_dent); + + dw_hdma_debugfs_regs_ch(dw, EDMA_DIR_READ, i, ch_dent); + } +} + +static void dw_hdma_debugfs_regs(struct dw_edma *dw) +{ + struct dentry *regs_dent; + + regs_dent = debugfs_create_dir(REGISTERS_STR, dw->dma.dbg_dev_root); + + dw_hdma_debugfs_regs_wr(dw, regs_dent); + dw_hdma_debugfs_regs_rd(dw, regs_dent); +} + +void dw_hdma_v0_debugfs_on(struct dw_edma *dw) +{ + if (!debugfs_initialized()) + return; + + debugfs_create_u32("mf", 0444, dw->dma.dbg_dev_root, &dw->chip->mf); + debugfs_create_u16("wr_ch_cnt", 0444, dw->dma.dbg_dev_root, &dw->wr_ch_cnt); + debugfs_create_u16("rd_ch_cnt", 0444, dw->dma.dbg_dev_root, &dw->rd_ch_cnt); + + dw_hdma_debugfs_regs(dw); +} diff --git a/drivers/dma/dw-edma/dw-hdma-v0-debugfs.h b/drivers/dma/dw-edma/dw-hdma-v0-debugfs.h new file mode 100644 index 0000000000000000000000000000000000000000..e6842c83777dd6ecb14ba08db914fa042a7e38ec --- /dev/null +++ b/drivers/dma/dw-edma/dw-hdma-v0-debugfs.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2023 Cai Huoqing + * Synopsys DesignWare HDMA v0 debugfs + * + * Author: Cai Huoqing + */ + +#ifndef _DW_HDMA_V0_DEBUG_FS_H +#define _DW_HDMA_V0_DEBUG_FS_H + +#include + +#ifdef CONFIG_DEBUG_FS +void dw_hdma_v0_debugfs_on(struct dw_edma *dw); +#else +static inline void dw_hdma_v0_debugfs_on(struct dw_edma *dw) +{ +} +#endif /* CONFIG_DEBUG_FS */ + +#endif /* _DW_HDMA_V0_DEBUG_FS_H */ diff --git a/drivers/dma/dw-edma/dw-hdma-v0-regs.h b/drivers/dma/dw-edma/dw-hdma-v0-regs.h new file mode 100644 index 0000000000000000000000000000000000000000..a974abdf8aaf5ecd83eadd56f191a313ec37e9ff --- /dev/null +++ b/drivers/dma/dw-edma/dw-hdma-v0-regs.h @@ -0,0 +1,129 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2023 Cai Huoqing + * Synopsys DesignWare HDMA v0 reg + * + * Author: Cai Huoqing + */ + +#ifndef _DW_HDMA_V0_REGS_H +#define _DW_HDMA_V0_REGS_H + +#include + +#define HDMA_V0_MAX_NR_CH 8 +#define HDMA_V0_LOCAL_ABORT_INT_EN BIT(6) +#define HDMA_V0_REMOTE_ABORT_INT_EN BIT(5) +#define HDMA_V0_LOCAL_STOP_INT_EN BIT(4) +#define HDMA_V0_REMOTEL_STOP_INT_EN BIT(3) +#define HDMA_V0_ABORT_INT_MASK BIT(2) +#define HDMA_V0_STOP_INT_MASK BIT(0) +#define HDMA_V0_LINKLIST_EN BIT(0) +#define HDMA_V0_CONSUMER_CYCLE_STAT BIT(1) +#define HDMA_V0_CONSUMER_CYCLE_BIT BIT(0) +#define HDMA_V0_DOORBELL_START BIT(0) +#define HDMA_V0_CH_STATUS_MASK GENMASK(1, 0) + +struct dw_hdma_v0_ch_regs { + u32 ch_en; /* 0x0000 */ + u32 doorbell; /* 0x0004 */ + u32 prefetch; /* 0x0008 */ + u32 handshake; /* 0x000c */ + union { + u64 reg; /* 0x0010..0x0014 */ + struct { + u32 lsb; /* 0x0010 */ + u32 msb; /* 0x0014 */ + }; + } llp; + u32 cycle_sync; /* 0x0018 */ + u32 transfer_size; /* 0x001c */ + union { + u64 reg; /* 0x0020..0x0024 */ + struct { + u32 lsb; /* 0x0020 */ + u32 msb; /* 0x0024 */ + }; + } sar; + union { + u64 reg; /* 0x0028..0x002c */ + struct { + u32 lsb; /* 0x0028 */ + u32 msb; /* 0x002c */ + }; + } dar; + u32 watermark_en; /* 0x0030 */ + u32 control1; /* 0x0034 */ + u32 func_num; /* 0x0038 */ + u32 qos; /* 0x003c */ + u32 padding_1[16]; /* 0x0040..0x007c */ + u32 ch_stat; /* 0x0080 */ + u32 int_stat; /* 0x0084 */ + u32 int_setup; /* 0x0088 */ + u32 int_clear; /* 0x008c */ + union { + u64 reg; /* 0x0090..0x0094 */ + struct { + u32 lsb; /* 0x0090 */ + u32 msb; /* 0x0094 */ + }; + } msi_stop; + union { + u64 reg; /* 0x0098..0x009c */ + struct { + u32 lsb; /* 0x0098 */ + u32 msb; /* 0x009c */ + }; + } msi_watermark; + union { + u64 reg; /* 0x00a0..0x00a4 */ + struct { + u32 lsb; /* 0x00a0 */ + u32 msb; /* 0x00a4 */ + }; + } msi_abort; + u32 msi_msgdata; /* 0x00a8 */ + u32 padding_2[21]; /* 0x00ac..0x00fc */ +} __packed; + +struct dw_hdma_v0_ch { + struct dw_hdma_v0_ch_regs wr; /* 0x0000 */ + struct dw_hdma_v0_ch_regs rd; /* 0x0100 */ +} __packed; + +struct dw_hdma_v0_regs { + struct dw_hdma_v0_ch ch[HDMA_V0_MAX_NR_CH]; /* 0x0000..0x0fa8 */ +} __packed; + +struct dw_hdma_v0_lli { + u32 control; + u32 transfer_size; + union { + u64 reg; + struct { + u32 lsb; + u32 msb; + }; + } sar; + union { + u64 reg; + struct { + u32 lsb; + u32 msb; + }; + } dar; +} __packed; + +struct dw_hdma_v0_llp { + u32 control; + u32 reserved; + union { + u64 reg; + struct { + u32 lsb; + u32 msb; + }; + } llp; +} __packed; + +#endif /* _DW_HDMA_V0_REGS_H */ diff --git a/drivers/dma/fsl-dpaa2-qdma/dpaa2-qdma.c b/drivers/dma/fsl-dpaa2-qdma/dpaa2-qdma.c index 8dd40d00a672a7ac5943ebf0bcbc22fafd058011..a42a37634881b29f1184000d066edd404841188a 100644 --- a/drivers/dma/fsl-dpaa2-qdma/dpaa2-qdma.c +++ b/drivers/dma/fsl-dpaa2-qdma/dpaa2-qdma.c @@ -765,7 +765,7 @@ static int dpaa2_qdma_probe(struct fsl_mc_device *dpdmai_dev) return err; } -static int dpaa2_qdma_remove(struct fsl_mc_device *ls_dev) +static void dpaa2_qdma_remove(struct fsl_mc_device *ls_dev) { struct dpaa2_qdma_engine *dpaa2_qdma; struct dpaa2_qdma_priv *priv; @@ -787,8 +787,6 @@ static int dpaa2_qdma_remove(struct fsl_mc_device *ls_dev) dma_async_device_unregister(&dpaa2_qdma->dma_dev); kfree(priv); kfree(dpaa2_qdma); - - return 0; } static void dpaa2_qdma_shutdown(struct fsl_mc_device *ls_dev) diff --git a/drivers/dma/ioat/dma.c b/drivers/dma/ioat/dma.c index 79d244011093cfb95e6195d0bfde045bcea3c8de..79d8957f9e60fc6e031806edf2c454f49b88cdae 100644 --- a/drivers/dma/ioat/dma.c +++ b/drivers/dma/ioat/dma.c @@ -584,11 +584,11 @@ desc_get_errstat(struct ioatdma_chan *ioat_chan, struct ioat_ring_ent *desc) } /** - * __cleanup - reclaim used descriptors + * __ioat_cleanup - reclaim used descriptors * @ioat_chan: channel (ring) to clean * @phys_complete: zeroed (or not) completion address (from status) */ -static void __cleanup(struct ioatdma_chan *ioat_chan, dma_addr_t phys_complete) +static void __ioat_cleanup(struct ioatdma_chan *ioat_chan, dma_addr_t phys_complete) { struct ioatdma_device *ioat_dma = ioat_chan->ioat_dma; struct ioat_ring_ent *desc; @@ -675,7 +675,7 @@ static void ioat_cleanup(struct ioatdma_chan *ioat_chan) spin_lock_bh(&ioat_chan->cleanup_lock); if (ioat_cleanup_preamble(ioat_chan, &phys_complete)) - __cleanup(ioat_chan, phys_complete); + __ioat_cleanup(ioat_chan, phys_complete); if (is_ioat_halted(*ioat_chan->completion)) { u32 chanerr = readl(ioat_chan->reg_base + IOAT_CHANERR_OFFSET); @@ -712,7 +712,7 @@ static void ioat_restart_channel(struct ioatdma_chan *ioat_chan) ioat_quiesce(ioat_chan, 0); if (ioat_cleanup_preamble(ioat_chan, &phys_complete)) - __cleanup(ioat_chan, phys_complete); + __ioat_cleanup(ioat_chan, phys_complete); __ioat_restart_chan(ioat_chan); } @@ -786,7 +786,7 @@ static void ioat_eh(struct ioatdma_chan *ioat_chan) /* cleanup so tail points to descriptor that caused the error */ if (ioat_cleanup_preamble(ioat_chan, &phys_complete)) - __cleanup(ioat_chan, phys_complete); + __ioat_cleanup(ioat_chan, phys_complete); chanerr = readl(ioat_chan->reg_base + IOAT_CHANERR_OFFSET); pci_read_config_dword(pdev, IOAT_PCI_CHANERR_INT_OFFSET, &chanerr_int); @@ -943,7 +943,7 @@ void ioat_timer_event(struct timer_list *t) /* timer restarted in ioat_cleanup_preamble * and IOAT_COMPLETION_ACK cleared */ - __cleanup(ioat_chan, phys_complete); + __ioat_cleanup(ioat_chan, phys_complete); goto unlock_out; } diff --git a/drivers/dma/plx_dma.c b/drivers/dma/plx_dma.c index 12725fa1655ff104e4264b148c7252a5bfb7f25a..34b6416c3287e604bcc4bacff83acb76ea5924f2 100644 --- a/drivers/dma/plx_dma.c +++ b/drivers/dma/plx_dma.c @@ -517,7 +517,6 @@ static int plx_dma_create(struct pci_dev *pdev) plxdev->bar = pcim_iomap_table(pdev)[0]; dma = &plxdev->dma_dev; - dma->chancnt = 1; INIT_LIST_HEAD(&dma->channels); dma_cap_set(DMA_MEMCPY, dma->cap_mask); dma->copy_align = DMAENGINE_ALIGN_1_BYTE; diff --git a/drivers/dma/qcom/Kconfig b/drivers/dma/qcom/Kconfig index 3f926a653bd889cbf9b745c0985832c9c29bac9b..ace75d7b835a2f921b02287647ca2ec3a553e47b 100644 --- a/drivers/dma/qcom/Kconfig +++ b/drivers/dma/qcom/Kconfig @@ -45,6 +45,7 @@ config QCOM_HIDMA_MGMT config QCOM_HIDMA tristate "Qualcomm Technologies HIDMA Channel support" + depends on HAS_IOMEM select DMA_ENGINE help Enable support for the Qualcomm Technologies HIDMA controller. diff --git a/drivers/dma/qcom/bam_dma.c b/drivers/dma/qcom/bam_dma.c index 1e47d27e1f814b2681ffce8654ff369c81f44ff5..4c3eb972039d600a9ed26ca262daf167b50822f8 100644 --- a/drivers/dma/qcom/bam_dma.c +++ b/drivers/dma/qcom/bam_dma.c @@ -1272,7 +1272,15 @@ static int bam_dma_probe(struct platform_device *pdev) bdev->powered_remotely = of_property_read_bool(pdev->dev.of_node, "qcom,powered-remotely"); - if (bdev->controlled_remotely || bdev->powered_remotely) { + if (bdev->controlled_remotely || bdev->powered_remotely) + bdev->bamclk = devm_clk_get_optional(bdev->dev, "bam_clk"); + else + bdev->bamclk = devm_clk_get(bdev->dev, "bam_clk"); + + if (IS_ERR(bdev->bamclk)) + return PTR_ERR(bdev->bamclk); + + if (!bdev->bamclk) { ret = of_property_read_u32(pdev->dev.of_node, "num-channels", &bdev->num_channels); if (ret) @@ -1284,14 +1292,6 @@ static int bam_dma_probe(struct platform_device *pdev) dev_err(bdev->dev, "num-ees unspecified in dt\n"); } - if (bdev->controlled_remotely || bdev->powered_remotely) - bdev->bamclk = devm_clk_get_optional(bdev->dev, "bam_clk"); - else - bdev->bamclk = devm_clk_get(bdev->dev, "bam_clk"); - - if (IS_ERR(bdev->bamclk)) - return PTR_ERR(bdev->bamclk); - ret = clk_prepare_enable(bdev->bamclk); if (ret) { dev_err(bdev->dev, "failed to prepare/enable clock\n"); diff --git a/drivers/dma/qcom/hidma.c b/drivers/dma/qcom/hidma.c index 04d1c33afc1296466e250aa865ee935a306131c5..344525c3a32fafbb7995b09bf2163bf1674fa95e 100644 --- a/drivers/dma/qcom/hidma.c +++ b/drivers/dma/qcom/hidma.c @@ -214,7 +214,6 @@ static int hidma_chan_init(struct hidma_dev *dmadev, u32 dma_sig) spin_lock_init(&mchan->lock); list_add_tail(&mchan->chan.device_node, &ddev->channels); - dmadev->ddev.chancnt++; return 0; } diff --git a/drivers/dma/sprd-dma.c b/drivers/dma/sprd-dma.c index 474d3ba8ec9f914cc3f6974dcf94a0c6c05ea1fc..2b639adb48ba501d207c5668cd0d7b25653fa7c8 100644 --- a/drivers/dma/sprd-dma.c +++ b/drivers/dma/sprd-dma.c @@ -1169,7 +1169,6 @@ static int sprd_dma_probe(struct platform_device *pdev) dma_cap_set(DMA_MEMCPY, sdev->dma_dev.cap_mask); sdev->total_chns = chn_count; - sdev->dma_dev.chancnt = chn_count; INIT_LIST_HEAD(&sdev->dma_dev.channels); INIT_LIST_HEAD(&sdev->dma_dev.global_node); sdev->dma_dev.dev = &pdev->dev; diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c index f093e08c23b160d8e5a15a1c647f9ce0b50f1c70..825001bde42c4bf249c15edb2eab8a2f4320d1a2 100644 --- a/drivers/dma/ste_dma40.c +++ b/drivers/dma/ste_dma40.c @@ -19,14 +19,43 @@ #include #include #include +#include #include #include #include -#include #include "dmaengine.h" +#include "ste_dma40.h" #include "ste_dma40_ll.h" +/** + * struct stedma40_platform_data - Configuration struct for the dma device. + * + * @dev_tx: mapping between destination event line and io address + * @dev_rx: mapping between source event line and io address + * @disabled_channels: A vector, ending with -1, that marks physical channels + * that are for different reasons not available for the driver. + * @soft_lli_chans: A vector, that marks physical channels will use LLI by SW + * which avoids HW bug that exists in some versions of the controller. + * SoftLLI introduces relink overhead that could impact performace for + * certain use cases. + * @num_of_soft_lli_chans: The number of channels that needs to be configured + * to use SoftLLI. + * @use_esram_lcla: flag for mapping the lcla into esram region + * @num_of_memcpy_chans: The number of channels reserved for memcpy. + * @num_of_phy_chans: The number of physical channels implemented in HW. + * 0 means reading the number of channels from DMA HW but this is only valid + * for 'multiple of 4' channels, like 8. + */ +struct stedma40_platform_data { + int disabled_channels[STEDMA40_MAX_PHYS]; + int *soft_lli_chans; + int num_of_soft_lli_chans; + bool use_esram_lcla; + int num_of_memcpy_chans; + int num_of_phy_chans; +}; + #define D40_NAME "dma40" #define D40_PHY_CHAN -1 @@ -107,7 +136,7 @@ static const struct stedma40_chan_cfg dma40_memcpy_conf_log = { }; /** - * enum 40_command - The different commands and/or statuses. + * enum d40_command - The different commands and/or statuses. * * @D40_DMA_STOP: DMA channel command STOP or status STOPPED, * @D40_DMA_RUN: The DMA channel is RUNNING of the command RUN. @@ -525,8 +554,6 @@ struct d40_gen_dmac { * @virtbase: The virtual base address of the DMA's register. * @rev: silicon revision detected. * @clk: Pointer to the DMA clock structure. - * @phy_start: Physical memory start of the DMA registers. - * @phy_size: Size of the DMA register map. * @irq: The IRQ number. * @num_memcpy_chans: The number of channels used for memcpy (mem-to-mem * transfers). @@ -570,8 +597,6 @@ struct d40_base { void __iomem *virtbase; u8 rev:4; struct clk *clk; - phys_addr_t phy_start; - resource_size_t phy_size; int irq; int num_memcpy_chans; int num_phy_chans; @@ -2268,7 +2293,7 @@ d40_prep_sg(struct dma_chan *dchan, struct scatterlist *sg_src, return NULL; } -bool stedma40_filter(struct dma_chan *chan, void *data) +static bool stedma40_filter(struct dma_chan *chan, void *data) { struct stedma40_chan_cfg *info = data; struct d40_chan *d40c = @@ -2287,7 +2312,6 @@ bool stedma40_filter(struct dma_chan *chan, void *data) return err == 0; } -EXPORT_SYMBOL(stedma40_filter); static void __d40_set_prio_rt(struct d40_chan *d40c, int dev_type, bool src) { @@ -3100,64 +3124,57 @@ static int __init d40_phy_res_init(struct d40_base *base) return num_phy_chans_avail; } -static struct d40_base * __init d40_hw_detect_init(struct platform_device *pdev) +/* Called from the registered devm action */ +static void d40_drop_kmem_cache_action(void *d) +{ + struct kmem_cache *desc_slab = d; + + kmem_cache_destroy(desc_slab); +} + +static int __init d40_hw_detect_init(struct platform_device *pdev, + struct d40_base **retbase) { struct stedma40_platform_data *plat_data = dev_get_platdata(&pdev->dev); + struct device *dev = &pdev->dev; struct clk *clk; void __iomem *virtbase; - struct resource *res; struct d40_base *base; int num_log_chans; int num_phy_chans; int num_memcpy_chans; - int clk_ret = -EINVAL; int i; u32 pid; u32 cid; u8 rev; + int ret; - clk = clk_get(&pdev->dev, NULL); - if (IS_ERR(clk)) { - d40_err(&pdev->dev, "No matching clock found\n"); - goto check_prepare_enabled; - } - - clk_ret = clk_prepare_enable(clk); - if (clk_ret) { - d40_err(&pdev->dev, "Failed to prepare/enable clock\n"); - goto disable_unprepare; - } + clk = devm_clk_get_enabled(dev, NULL); + if (IS_ERR(clk)) + return PTR_ERR(clk); /* Get IO for DMAC base address */ - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "base"); - if (!res) - goto disable_unprepare; - - if (request_mem_region(res->start, resource_size(res), - D40_NAME " I/O base") == NULL) - goto release_region; - - virtbase = ioremap(res->start, resource_size(res)); - if (!virtbase) - goto release_region; + virtbase = devm_platform_ioremap_resource_byname(pdev, "base"); + if (IS_ERR(virtbase)) + return PTR_ERR(virtbase); /* This is just a regular AMBA PrimeCell ID actually */ for (pid = 0, i = 0; i < 4; i++) - pid |= (readl(virtbase + resource_size(res) - 0x20 + 4 * i) + pid |= (readl(virtbase + SZ_4K - 0x20 + 4 * i) & 255) << (i * 8); for (cid = 0, i = 0; i < 4; i++) - cid |= (readl(virtbase + resource_size(res) - 0x10 + 4 * i) + cid |= (readl(virtbase + SZ_4K - 0x10 + 4 * i) & 255) << (i * 8); if (cid != AMBA_CID) { - d40_err(&pdev->dev, "Unknown hardware! No PrimeCell ID\n"); - goto unmap_io; + d40_err(dev, "Unknown hardware! No PrimeCell ID\n"); + return -EINVAL; } if (AMBA_MANF_BITS(pid) != AMBA_VENDOR_ST) { - d40_err(&pdev->dev, "Unknown designer! Got %x wanted %x\n", + d40_err(dev, "Unknown designer! Got %x wanted %x\n", AMBA_MANF_BITS(pid), AMBA_VENDOR_ST); - goto unmap_io; + return -EINVAL; } /* * HW revision: @@ -3170,8 +3187,8 @@ static struct d40_base * __init d40_hw_detect_init(struct platform_device *pdev) */ rev = AMBA_REV_BITS(pid); if (rev < 2) { - d40_err(&pdev->dev, "hardware revision: %d is not supported", rev); - goto unmap_io; + d40_err(dev, "hardware revision: %d is not supported", rev); + return -EINVAL; } /* The number of physical channels on this HW */ @@ -3188,27 +3205,26 @@ static struct d40_base * __init d40_hw_detect_init(struct platform_device *pdev) num_log_chans = num_phy_chans * D40_MAX_LOG_CHAN_PER_PHY; - dev_info(&pdev->dev, - "hardware rev: %d @ %pa with %d physical and %d logical channels\n", - rev, &res->start, num_phy_chans, num_log_chans); + dev_info(dev, + "hardware rev: %d with %d physical and %d logical channels\n", + rev, num_phy_chans, num_log_chans); - base = kzalloc(ALIGN(sizeof(struct d40_base), 4) + - (num_phy_chans + num_log_chans + num_memcpy_chans) * - sizeof(struct d40_chan), GFP_KERNEL); + base = devm_kzalloc(dev, + ALIGN(sizeof(struct d40_base), 4) + + (num_phy_chans + num_log_chans + num_memcpy_chans) * + sizeof(struct d40_chan), GFP_KERNEL); - if (base == NULL) - goto unmap_io; + if (!base) + return -ENOMEM; base->rev = rev; base->clk = clk; base->num_memcpy_chans = num_memcpy_chans; base->num_phy_chans = num_phy_chans; base->num_log_chans = num_log_chans; - base->phy_start = res->start; - base->phy_size = resource_size(res); base->virtbase = virtbase; base->plat_data = plat_data; - base->dev = &pdev->dev; + base->dev = dev; base->phy_chans = ((void *)base) + ALIGN(sizeof(struct d40_base), 4); base->log_chans = &base->phy_chans[num_phy_chans]; @@ -3242,76 +3258,57 @@ static struct d40_base * __init d40_hw_detect_init(struct platform_device *pdev) base->gen_dmac.init_reg_size = ARRAY_SIZE(dma_init_reg_v4a); } - base->phy_res = kcalloc(num_phy_chans, - sizeof(*base->phy_res), - GFP_KERNEL); + base->phy_res = devm_kcalloc(dev, num_phy_chans, + sizeof(*base->phy_res), + GFP_KERNEL); if (!base->phy_res) - goto free_base; + return -ENOMEM; - base->lookup_phy_chans = kcalloc(num_phy_chans, - sizeof(*base->lookup_phy_chans), - GFP_KERNEL); + base->lookup_phy_chans = devm_kcalloc(dev, num_phy_chans, + sizeof(*base->lookup_phy_chans), + GFP_KERNEL); if (!base->lookup_phy_chans) - goto free_phy_res; + return -ENOMEM; - base->lookup_log_chans = kcalloc(num_log_chans, - sizeof(*base->lookup_log_chans), - GFP_KERNEL); + base->lookup_log_chans = devm_kcalloc(dev, num_log_chans, + sizeof(*base->lookup_log_chans), + GFP_KERNEL); if (!base->lookup_log_chans) - goto free_phy_chans; + return -ENOMEM; - base->reg_val_backup_chan = kmalloc_array(base->num_phy_chans, + base->reg_val_backup_chan = devm_kmalloc_array(dev, base->num_phy_chans, sizeof(d40_backup_regs_chan), GFP_KERNEL); if (!base->reg_val_backup_chan) - goto free_log_chans; + return -ENOMEM; - base->lcla_pool.alloc_map = kcalloc(num_phy_chans + base->lcla_pool.alloc_map = devm_kcalloc(dev, num_phy_chans * D40_LCLA_LINK_PER_EVENT_GRP, sizeof(*base->lcla_pool.alloc_map), GFP_KERNEL); if (!base->lcla_pool.alloc_map) - goto free_backup_chan; + return -ENOMEM; - base->regs_interrupt = kmalloc_array(base->gen_dmac.il_size, + base->regs_interrupt = devm_kmalloc_array(dev, base->gen_dmac.il_size, sizeof(*base->regs_interrupt), GFP_KERNEL); if (!base->regs_interrupt) - goto free_map; + return -ENOMEM; base->desc_slab = kmem_cache_create(D40_NAME, sizeof(struct d40_desc), 0, SLAB_HWCACHE_ALIGN, NULL); - if (base->desc_slab == NULL) - goto free_regs; - - - return base; - free_regs: - kfree(base->regs_interrupt); - free_map: - kfree(base->lcla_pool.alloc_map); - free_backup_chan: - kfree(base->reg_val_backup_chan); - free_log_chans: - kfree(base->lookup_log_chans); - free_phy_chans: - kfree(base->lookup_phy_chans); - free_phy_res: - kfree(base->phy_res); - free_base: - kfree(base); - unmap_io: - iounmap(virtbase); - release_region: - release_mem_region(res->start, resource_size(res)); - check_prepare_enabled: - if (!clk_ret) - disable_unprepare: - clk_disable_unprepare(clk); - if (!IS_ERR(clk)) - clk_put(clk); - return NULL; + if (!base->desc_slab) + return -ENOMEM; + + ret = devm_add_action_or_reset(dev, d40_drop_kmem_cache_action, + base->desc_slab); + if (ret) + return ret; + + *retbase = base; + + return 0; } static void __init d40_hw_init(struct d40_base *base) @@ -3451,14 +3448,14 @@ static int __init d40_lcla_allocate(struct d40_base *base) return ret; } -static int __init d40_of_probe(struct platform_device *pdev, +static int __init d40_of_probe(struct device *dev, struct device_node *np) { struct stedma40_platform_data *pdata; int num_phy = 0, num_memcpy = 0, num_disabled = 0; const __be32 *list; - pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); + pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); if (!pdata) return -ENOMEM; @@ -3471,7 +3468,7 @@ static int __init d40_of_probe(struct platform_device *pdev, num_memcpy /= sizeof(*list); if (num_memcpy > D40_MEMCPY_MAX_CHANS || num_memcpy <= 0) { - d40_err(&pdev->dev, + d40_err(dev, "Invalid number of memcpy channels specified (%d)\n", num_memcpy); return -EINVAL; @@ -3486,7 +3483,7 @@ static int __init d40_of_probe(struct platform_device *pdev, num_disabled /= sizeof(*list); if (num_disabled >= STEDMA40_MAX_PHYS || num_disabled < 0) { - d40_err(&pdev->dev, + d40_err(dev, "Invalid number of disabled channels specified (%d)\n", num_disabled); return -EINVAL; @@ -3497,35 +3494,30 @@ static int __init d40_of_probe(struct platform_device *pdev, num_disabled); pdata->disabled_channels[num_disabled] = -1; - pdev->dev.platform_data = pdata; + dev->platform_data = pdata; return 0; } static int __init d40_probe(struct platform_device *pdev) { - struct stedma40_platform_data *plat_data = dev_get_platdata(&pdev->dev); + struct device *dev = &pdev->dev; struct device_node *np = pdev->dev.of_node; - int ret = -ENOENT; + struct device_node *np_lcpa; struct d40_base *base; struct resource *res; + struct resource res_lcpa; int num_reserved_chans; u32 val; + int ret; - if (!plat_data) { - if (np) { - if (d40_of_probe(pdev, np)) { - ret = -ENOMEM; - goto report_failure; - } - } else { - d40_err(&pdev->dev, "No pdata or Device Tree provided\n"); - goto report_failure; - } + if (d40_of_probe(dev, np)) { + ret = -ENOMEM; + goto report_failure; } - base = d40_hw_detect_init(pdev); - if (!base) + ret = d40_hw_detect_init(pdev, &base); + if (ret) goto report_failure; num_reserved_chans = d40_phy_res_init(base); @@ -3535,37 +3527,38 @@ static int __init d40_probe(struct platform_device *pdev) spin_lock_init(&base->interrupt_lock); spin_lock_init(&base->execmd_lock); - /* Get IO for logical channel parameter address */ - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "lcpa"); - if (!res) { - ret = -ENOENT; - d40_err(&pdev->dev, "No \"lcpa\" memory resource\n"); - goto destroy_cache; + /* Get IO for logical channel parameter address (LCPA) */ + np_lcpa = of_parse_phandle(np, "sram", 0); + if (!np_lcpa) { + dev_err(dev, "no LCPA SRAM node\n"); + ret = -EINVAL; + goto report_failure; } - base->lcpa_size = resource_size(res); - base->phy_lcpa = res->start; - - if (request_mem_region(res->start, resource_size(res), - D40_NAME " I/O lcpa") == NULL) { - ret = -EBUSY; - d40_err(&pdev->dev, "Failed to request LCPA region %pR\n", res); - goto destroy_cache; + /* This is no device so read the address directly from the node */ + ret = of_address_to_resource(np_lcpa, 0, &res_lcpa); + if (ret) { + dev_err(dev, "no LCPA SRAM resource\n"); + goto report_failure; } + base->lcpa_size = resource_size(&res_lcpa); + base->phy_lcpa = res_lcpa.start; + dev_info(dev, "found LCPA SRAM at %pad, size %pa\n", + &base->phy_lcpa, &base->lcpa_size); /* We make use of ESRAM memory for this. */ val = readl(base->virtbase + D40_DREG_LCPA); - if (res->start != val && val != 0) { - dev_warn(&pdev->dev, - "[%s] Mismatch LCPA dma 0x%x, def %pa\n", - __func__, val, &res->start); + if (base->phy_lcpa != val && val != 0) { + dev_warn(dev, + "[%s] Mismatch LCPA dma 0x%x, def %08x\n", + __func__, val, (u32)base->phy_lcpa); } else - writel(res->start, base->virtbase + D40_DREG_LCPA); + writel(base->phy_lcpa, base->virtbase + D40_DREG_LCPA); - base->lcpa_base = ioremap(res->start, resource_size(res)); + base->lcpa_base = devm_ioremap(dev, base->phy_lcpa, base->lcpa_size); if (!base->lcpa_base) { ret = -ENOMEM; - d40_err(&pdev->dev, "Failed to ioremap LCPA region\n"); - goto destroy_cache; + d40_err(dev, "Failed to ioremap LCPA region\n"); + goto report_failure; } /* If lcla has to be located in ESRAM we don't need to allocate */ if (base->plat_data->use_esram_lcla) { @@ -3573,23 +3566,23 @@ static int __init d40_probe(struct platform_device *pdev) "lcla_esram"); if (!res) { ret = -ENOENT; - d40_err(&pdev->dev, + d40_err(dev, "No \"lcla_esram\" memory resource\n"); - goto destroy_cache; + goto report_failure; } - base->lcla_pool.base = ioremap(res->start, - resource_size(res)); + base->lcla_pool.base = devm_ioremap(dev, res->start, + resource_size(res)); if (!base->lcla_pool.base) { ret = -ENOMEM; - d40_err(&pdev->dev, "Failed to ioremap LCLA region\n"); - goto destroy_cache; + d40_err(dev, "Failed to ioremap LCLA region\n"); + goto report_failure; } writel(res->start, base->virtbase + D40_DREG_LCLA); } else { ret = d40_lcla_allocate(base); if (ret) { - d40_err(&pdev->dev, "Failed to allocate LCLA area\n"); + d40_err(dev, "Failed to allocate LCLA area\n"); goto destroy_cache; } } @@ -3600,7 +3593,7 @@ static int __init d40_probe(struct platform_device *pdev) ret = request_irq(base->irq, d40_handle_interrupt, 0, D40_NAME, base); if (ret) { - d40_err(&pdev->dev, "No IRQ defined\n"); + d40_err(dev, "No IRQ defined\n"); goto destroy_cache; } @@ -3608,7 +3601,7 @@ static int __init d40_probe(struct platform_device *pdev) base->lcpa_regulator = regulator_get(base->dev, "lcla_esram"); if (IS_ERR(base->lcpa_regulator)) { - d40_err(&pdev->dev, "Failed to get lcpa_regulator\n"); + d40_err(dev, "Failed to get lcpa_regulator\n"); ret = PTR_ERR(base->lcpa_regulator); base->lcpa_regulator = NULL; goto destroy_cache; @@ -3616,7 +3609,7 @@ static int __init d40_probe(struct platform_device *pdev) ret = regulator_enable(base->lcpa_regulator); if (ret) { - d40_err(&pdev->dev, + d40_err(dev, "Failed to enable lcpa_regulator\n"); regulator_put(base->lcpa_regulator); base->lcpa_regulator = NULL; @@ -3639,31 +3632,23 @@ static int __init d40_probe(struct platform_device *pdev) ret = dma_set_max_seg_size(base->dev, STEDMA40_MAX_SEG_SIZE); if (ret) { - d40_err(&pdev->dev, "Failed to set dma max seg size\n"); + d40_err(dev, "Failed to set dma max seg size\n"); goto destroy_cache; } d40_hw_init(base); - if (np) { - ret = of_dma_controller_register(np, d40_xlate, NULL); - if (ret) - dev_err(&pdev->dev, - "could not register of_dma_controller\n"); + ret = of_dma_controller_register(np, d40_xlate, NULL); + if (ret) { + dev_err(dev, + "could not register of_dma_controller\n"); + goto destroy_cache; } dev_info(base->dev, "initialized\n"); return 0; - destroy_cache: - kmem_cache_destroy(base->desc_slab); - if (base->virtbase) - iounmap(base->virtbase); - - if (base->lcla_pool.base && base->plat_data->use_esram_lcla) { - iounmap(base->lcla_pool.base); - base->lcla_pool.base = NULL; - } + destroy_cache: if (base->lcla_pool.dma_addr) dma_unmap_single(base->dev, base->lcla_pool.dma_addr, SZ_1K * base->num_phy_chans, @@ -3675,32 +3660,13 @@ static int __init d40_probe(struct platform_device *pdev) kfree(base->lcla_pool.base_unaligned); - if (base->lcpa_base) - iounmap(base->lcpa_base); - - if (base->phy_lcpa) - release_mem_region(base->phy_lcpa, - base->lcpa_size); - if (base->phy_start) - release_mem_region(base->phy_start, - base->phy_size); - if (base->clk) { - clk_disable_unprepare(base->clk); - clk_put(base->clk); - } - if (base->lcpa_regulator) { regulator_disable(base->lcpa_regulator); regulator_put(base->lcpa_regulator); } - kfree(base->lcla_pool.alloc_map); - kfree(base->lookup_log_chans); - kfree(base->lookup_phy_chans); - kfree(base->phy_res); - kfree(base); report_failure: - d40_err(&pdev->dev, "probe failed\n"); + d40_err(dev, "probe failed\n"); return ret; } diff --git a/include/linux/platform_data/dma-ste-dma40.h b/drivers/dma/ste_dma40.h similarity index 51% rename from include/linux/platform_data/dma-ste-dma40.h rename to drivers/dma/ste_dma40.h index 10641633facc87e2077c9ca6ab5f9ac6a4d43d61..c697bfe16a0172f1aec081a0cce85466a120c270 100644 --- a/include/linux/platform_data/dma-ste-dma40.h +++ b/drivers/dma/ste_dma40.h @@ -1,19 +1,8 @@ /* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright (C) ST-Ericsson SA 2007-2010 - * Author: Per Forlin for ST-Ericsson - * Author: Jonas Aaberg for ST-Ericsson - */ - #ifndef STE_DMA40_H #define STE_DMA40_H -#include -#include -#include -#include - /* * Maxium size for a single dma descriptor * Size is limited to 16 bits. @@ -118,92 +107,4 @@ struct stedma40_chan_cfg { int phy_channel; }; -/** - * struct stedma40_platform_data - Configuration struct for the dma device. - * - * @dev_tx: mapping between destination event line and io address - * @dev_rx: mapping between source event line and io address - * @disabled_channels: A vector, ending with -1, that marks physical channels - * that are for different reasons not available for the driver. - * @soft_lli_chans: A vector, that marks physical channels will use LLI by SW - * which avoids HW bug that exists in some versions of the controller. - * SoftLLI introduces relink overhead that could impact performace for - * certain use cases. - * @num_of_soft_lli_chans: The number of channels that needs to be configured - * to use SoftLLI. - * @use_esram_lcla: flag for mapping the lcla into esram region - * @num_of_memcpy_chans: The number of channels reserved for memcpy. - * @num_of_phy_chans: The number of physical channels implemented in HW. - * 0 means reading the number of channels from DMA HW but this is only valid - * for 'multiple of 4' channels, like 8. - */ -struct stedma40_platform_data { - int disabled_channels[STEDMA40_MAX_PHYS]; - int *soft_lli_chans; - int num_of_soft_lli_chans; - bool use_esram_lcla; - int num_of_memcpy_chans; - int num_of_phy_chans; -}; - -#ifdef CONFIG_STE_DMA40 - -/** - * stedma40_filter() - Provides stedma40_chan_cfg to the - * ste_dma40 dma driver via the dmaengine framework. - * does some checking of what's provided. - * - * Never directly called by client. It used by dmaengine. - * @chan: dmaengine handle. - * @data: Must be of type: struct stedma40_chan_cfg and is - * the configuration of the framework. - * - * - */ - -bool stedma40_filter(struct dma_chan *chan, void *data); - -/** - * stedma40_slave_mem() - Transfers a raw data buffer to or from a slave - * (=device) - * - * @chan: dmaengine handle - * @addr: source or destination physicall address. - * @size: bytes to transfer - * @direction: direction of transfer - * @flags: is actually enum dma_ctrl_flags. See dmaengine.h - */ - -static inline struct -dma_async_tx_descriptor *stedma40_slave_mem(struct dma_chan *chan, - dma_addr_t addr, - unsigned int size, - enum dma_transfer_direction direction, - unsigned long flags) -{ - struct scatterlist sg; - sg_init_table(&sg, 1); - sg.dma_address = addr; - sg.length = size; - - return dmaengine_prep_slave_sg(chan, &sg, 1, direction, flags); -} - -#else -static inline bool stedma40_filter(struct dma_chan *chan, void *data) -{ - return false; -} - -static inline struct -dma_async_tx_descriptor *stedma40_slave_mem(struct dma_chan *chan, - dma_addr_t addr, - unsigned int size, - enum dma_transfer_direction direction, - unsigned long flags) -{ - return NULL; -} -#endif - -#endif +#endif /* STE_DMA40_H */ diff --git a/drivers/dma/ste_dma40_ll.c b/drivers/dma/ste_dma40_ll.c index b5287c661eb7ad595fe07e2f3faada87684198c7..4c489b126cb2773eae595c7ef5819736c81e3702 100644 --- a/drivers/dma/ste_dma40_ll.c +++ b/drivers/dma/ste_dma40_ll.c @@ -6,8 +6,9 @@ */ #include -#include +#include +#include "ste_dma40.h" #include "ste_dma40_ll.h" static u8 d40_width_to_bits(enum dma_slave_buswidth width) diff --git a/drivers/dma/ti/k3-psil-j721s2.c b/drivers/dma/ti/k3-psil-j721s2.c index a488c22506233830a4797b3827420a888b866968..1d5430fc5724d26640e56b9fe51ee44134349521 100644 --- a/drivers/dma/ti/k3-psil-j721s2.c +++ b/drivers/dma/ti/k3-psil-j721s2.c @@ -99,6 +99,8 @@ static struct psil_ep j721s2_src_ep_map[] = { PSIL_PDMA_XY_PKT(0x461d), PSIL_PDMA_XY_PKT(0x461e), PSIL_PDMA_XY_PKT(0x461f), + /* MAIN_CPSW2G */ + PSIL_ETHERNET(0x4640), /* PDMA_USART_G0 - UART0-1 */ PSIL_PDMA_XY_PKT(0x4700), PSIL_PDMA_XY_PKT(0x4701), @@ -161,6 +163,15 @@ static struct psil_ep j721s2_dst_ep_map[] = { PSIL_ETHERNET(0xf005), PSIL_ETHERNET(0xf006), PSIL_ETHERNET(0xf007), + /* MAIN_CPSW2G */ + PSIL_ETHERNET(0xc640), + PSIL_ETHERNET(0xc641), + PSIL_ETHERNET(0xc642), + PSIL_ETHERNET(0xc643), + PSIL_ETHERNET(0xc644), + PSIL_ETHERNET(0xc645), + PSIL_ETHERNET(0xc646), + PSIL_ETHERNET(0xc647), /* SA2UL */ PSIL_SA2UL(0xf500, 1), PSIL_SA2UL(0xf501, 1), diff --git a/drivers/dma/ti/k3-udma.c b/drivers/dma/ti/k3-udma.c index b8329a23728d73f2a8a29e1c3965181b2712d635..eb4dc5fffe6468d3b32ba7e4eed614bb21dc7708 100644 --- a/drivers/dma/ti/k3-udma.c +++ b/drivers/dma/ti/k3-udma.c @@ -4308,6 +4308,15 @@ static struct udma_soc_data am62a_dmss_csi_soc_data = { }, }; +static struct udma_soc_data j721s2_bcdma_csi_soc_data = { + .oes = { + .bcdma_tchan_data = 0x800, + .bcdma_tchan_ring = 0xa00, + .bcdma_rchan_data = 0xe00, + .bcdma_rchan_ring = 0x1000, + }, +}; + static struct udma_match_data am62a_bcdma_csirx_data = { .type = DMA_TYPE_BCDMA, .psil_base = 0x3100, @@ -4346,6 +4355,18 @@ static struct udma_match_data am64_pktdma_data = { }, }; +static struct udma_match_data j721s2_bcdma_csi_data = { + .type = DMA_TYPE_BCDMA, + .psil_base = 0x2000, + .enable_memcpy_support = false, + .burst_size = { + TI_SCI_RM_UDMAP_CHAN_BURST_SIZE_64_BYTES, /* Normal Channels */ + 0, /* No H Channels */ + 0, /* No UH Channels */ + }, + .soc_data = &j721s2_bcdma_csi_soc_data, +}; + static const struct of_device_id udma_of_match[] = { { .compatible = "ti,am654-navss-main-udmap", @@ -4373,6 +4394,10 @@ static const struct of_device_id udma_of_match[] = { .compatible = "ti,am62a-dmss-bcdma-csirx", .data = &am62a_bcdma_csirx_data, }, + { + .compatible = "ti,j721s2-dmss-bcdma-csi", + .data = &j721s2_bcdma_csi_data, + }, { /* Sentinel */ }, }; diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig index 68f576700911f42c9cbe6baef5b74c1ed802e9e3..110e99b86a66a3a292c5f0bce9717728476e7dff 100644 --- a/drivers/edac/Kconfig +++ b/drivers/edac/Kconfig @@ -550,4 +550,15 @@ config EDAC_ZYNQMP Xilinx ZynqMP OCM (On Chip Memory) controller. It can also be built as a module. In that case it will be called zynqmp_edac. +config EDAC_NPCM + tristate "Nuvoton NPCM DDR Memory Controller" + depends on (ARCH_NPCM || COMPILE_TEST) + help + Support for error detection and correction on the Nuvoton NPCM DDR + memory controller. + + The memory controller supports single bit error correction, double bit + error detection (in-line ECC in which a section 1/8th of the memory + device used to store data is used for ECC storage). + endif # EDAC diff --git a/drivers/edac/Makefile b/drivers/edac/Makefile index 9b025c5b30617dfe1d8020c05e70a38b1b6bb692..61945d3113cc3299e3e92e075f71e0da90e3283d 100644 --- a/drivers/edac/Makefile +++ b/drivers/edac/Makefile @@ -84,4 +84,5 @@ obj-$(CONFIG_EDAC_QCOM) += qcom_edac.o obj-$(CONFIG_EDAC_ASPEED) += aspeed_edac.o obj-$(CONFIG_EDAC_BLUEFIELD) += bluefield_edac.o obj-$(CONFIG_EDAC_DMC520) += dmc520_edac.o +obj-$(CONFIG_EDAC_NPCM) += npcm_edac.o obj-$(CONFIG_EDAC_ZYNQMP) += zynqmp_edac.o diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index 5c4292e65b96e09fde948b7301b348f971b798b1..597dae7692b1296842c1d9fe9e54c8d045156a46 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c @@ -975,6 +975,74 @@ static int sys_addr_to_csrow(struct mem_ctl_info *mci, u64 sys_addr) return csrow; } +/* + * See AMD PPR DF::LclNodeTypeMap + * + * This register gives information for nodes of the same type within a system. + * + * Reading this register from a GPU node will tell how many GPU nodes are in the + * system and what the lowest AMD Node ID value is for the GPU nodes. Use this + * info to fixup the Linux logical "Node ID" value set in the AMD NB code and EDAC. + */ +static struct local_node_map { + u16 node_count; + u16 base_node_id; +} gpu_node_map; + +#define PCI_DEVICE_ID_AMD_MI200_DF_F1 0x14d1 +#define REG_LOCAL_NODE_TYPE_MAP 0x144 + +/* Local Node Type Map (LNTM) fields */ +#define LNTM_NODE_COUNT GENMASK(27, 16) +#define LNTM_BASE_NODE_ID GENMASK(11, 0) + +static int gpu_get_node_map(void) +{ + struct pci_dev *pdev; + int ret; + u32 tmp; + + /* + * Node ID 0 is reserved for CPUs. + * Therefore, a non-zero Node ID means we've already cached the values. + */ + if (gpu_node_map.base_node_id) + return 0; + + pdev = pci_get_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_MI200_DF_F1, NULL); + if (!pdev) { + ret = -ENODEV; + goto out; + } + + ret = pci_read_config_dword(pdev, REG_LOCAL_NODE_TYPE_MAP, &tmp); + if (ret) + goto out; + + gpu_node_map.node_count = FIELD_GET(LNTM_NODE_COUNT, tmp); + gpu_node_map.base_node_id = FIELD_GET(LNTM_BASE_NODE_ID, tmp); + +out: + pci_dev_put(pdev); + return ret; +} + +static int fixup_node_id(int node_id, struct mce *m) +{ + /* MCA_IPID[InstanceIdHi] give the AMD Node ID for the bank. */ + u8 nid = (m->ipid >> 44) & 0xF; + + if (smca_get_bank_type(m->extcpu, m->bank) != SMCA_UMC_V2) + return node_id; + + /* Nodes below the GPU base node are CPU nodes and don't need a fixup. */ + if (nid < gpu_node_map.base_node_id) + return node_id; + + /* Convert the hardware-provided AMD Node ID to a Linux logical one. */ + return nid - gpu_node_map.base_node_id + 1; +} + /* Protect the PCI config register pairs used for DF indirect access. */ static DEFINE_MUTEX(df_indirect_mutex); @@ -1426,12 +1494,47 @@ static int umc_get_cs_mode(int dimm, u8 ctrl, struct amd64_pvt *pvt) return cs_mode; } +static int __addr_mask_to_cs_size(u32 addr_mask_orig, unsigned int cs_mode, + int csrow_nr, int dimm) +{ + u32 msb, weight, num_zero_bits; + u32 addr_mask_deinterleaved; + int size = 0; + + /* + * The number of zero bits in the mask is equal to the number of bits + * in a full mask minus the number of bits in the current mask. + * + * The MSB is the number of bits in the full mask because BIT[0] is + * always 0. + * + * In the special 3 Rank interleaving case, a single bit is flipped + * without swapping with the most significant bit. This can be handled + * by keeping the MSB where it is and ignoring the single zero bit. + */ + msb = fls(addr_mask_orig) - 1; + weight = hweight_long(addr_mask_orig); + num_zero_bits = msb - weight - !!(cs_mode & CS_3R_INTERLEAVE); + + /* Take the number of zero bits off from the top of the mask. */ + addr_mask_deinterleaved = GENMASK_ULL(msb - num_zero_bits, 1); + + edac_dbg(1, "CS%d DIMM%d AddrMasks:\n", csrow_nr, dimm); + edac_dbg(1, " Original AddrMask: 0x%x\n", addr_mask_orig); + edac_dbg(1, " Deinterleaved AddrMask: 0x%x\n", addr_mask_deinterleaved); + + /* Register [31:1] = Address [39:9]. Size is in kBs here. */ + size = (addr_mask_deinterleaved >> 2) + 1; + + /* Return size in MBs. */ + return size >> 10; +} + static int umc_addr_mask_to_cs_size(struct amd64_pvt *pvt, u8 umc, unsigned int cs_mode, int csrow_nr) { - u32 addr_mask_orig, addr_mask_deinterleaved; - u32 msb, weight, num_zero_bits; int cs_mask_nr = csrow_nr; + u32 addr_mask_orig; int dimm, size = 0; /* No Chip Selects are enabled. */ @@ -1475,33 +1578,7 @@ static int umc_addr_mask_to_cs_size(struct amd64_pvt *pvt, u8 umc, else addr_mask_orig = pvt->csels[umc].csmasks[cs_mask_nr]; - /* - * The number of zero bits in the mask is equal to the number of bits - * in a full mask minus the number of bits in the current mask. - * - * The MSB is the number of bits in the full mask because BIT[0] is - * always 0. - * - * In the special 3 Rank interleaving case, a single bit is flipped - * without swapping with the most significant bit. This can be handled - * by keeping the MSB where it is and ignoring the single zero bit. - */ - msb = fls(addr_mask_orig) - 1; - weight = hweight_long(addr_mask_orig); - num_zero_bits = msb - weight - !!(cs_mode & CS_3R_INTERLEAVE); - - /* Take the number of zero bits off from the top of the mask. */ - addr_mask_deinterleaved = GENMASK_ULL(msb - num_zero_bits, 1); - - edac_dbg(1, "CS%d DIMM%d AddrMasks:\n", csrow_nr, dimm); - edac_dbg(1, " Original AddrMask: 0x%x\n", addr_mask_orig); - edac_dbg(1, " Deinterleaved AddrMask: 0x%x\n", addr_mask_deinterleaved); - - /* Register [31:1] = Address [39:9]. Size is in kBs here. */ - size = (addr_mask_deinterleaved >> 2) + 1; - - /* Return size in MBs. */ - return size >> 10; + return __addr_mask_to_cs_size(addr_mask_orig, cs_mode, csrow_nr, dimm); } static void umc_debug_display_dimm_sizes(struct amd64_pvt *pvt, u8 ctrl) @@ -2992,6 +3069,8 @@ static void decode_umc_error(int node_id, struct mce *m) struct err_info err; u64 sys_addr; + node_id = fixup_node_id(node_id, m); + mci = edac_mc_find(node_id); if (!mci) return; @@ -3675,6 +3754,227 @@ static int umc_hw_info_get(struct amd64_pvt *pvt) return 0; } +/* + * The CPUs have one channel per UMC, so UMC number is equivalent to a + * channel number. The GPUs have 8 channels per UMC, so the UMC number no + * longer works as a channel number. + * + * The channel number within a GPU UMC is given in MCA_IPID[15:12]. + * However, the IDs are split such that two UMC values go to one UMC, and + * the channel numbers are split in two groups of four. + * + * Refer to comment on gpu_get_umc_base(). + * + * For example, + * UMC0 CH[3:0] = 0x0005[3:0]000 + * UMC0 CH[7:4] = 0x0015[3:0]000 + * UMC1 CH[3:0] = 0x0025[3:0]000 + * UMC1 CH[7:4] = 0x0035[3:0]000 + */ +static void gpu_get_err_info(struct mce *m, struct err_info *err) +{ + u8 ch = (m->ipid & GENMASK(31, 0)) >> 20; + u8 phy = ((m->ipid >> 12) & 0xf); + + err->channel = ch % 2 ? phy + 4 : phy; + err->csrow = phy; +} + +static int gpu_addr_mask_to_cs_size(struct amd64_pvt *pvt, u8 umc, + unsigned int cs_mode, int csrow_nr) +{ + u32 addr_mask_orig = pvt->csels[umc].csmasks[csrow_nr]; + + return __addr_mask_to_cs_size(addr_mask_orig, cs_mode, csrow_nr, csrow_nr >> 1); +} + +static void gpu_debug_display_dimm_sizes(struct amd64_pvt *pvt, u8 ctrl) +{ + int size, cs_mode, cs = 0; + + edac_printk(KERN_DEBUG, EDAC_MC, "UMC%d chip selects:\n", ctrl); + + cs_mode = CS_EVEN_PRIMARY | CS_ODD_PRIMARY; + + for_each_chip_select(cs, ctrl, pvt) { + size = gpu_addr_mask_to_cs_size(pvt, ctrl, cs_mode, cs); + amd64_info(EDAC_MC ": %d: %5dMB\n", cs, size); + } +} + +static void gpu_dump_misc_regs(struct amd64_pvt *pvt) +{ + struct amd64_umc *umc; + u32 i; + + for_each_umc(i) { + umc = &pvt->umc[i]; + + edac_dbg(1, "UMC%d UMC cfg: 0x%x\n", i, umc->umc_cfg); + edac_dbg(1, "UMC%d SDP ctrl: 0x%x\n", i, umc->sdp_ctrl); + edac_dbg(1, "UMC%d ECC ctrl: 0x%x\n", i, umc->ecc_ctrl); + edac_dbg(1, "UMC%d All HBMs support ECC: yes\n", i); + + gpu_debug_display_dimm_sizes(pvt, i); + } +} + +static u32 gpu_get_csrow_nr_pages(struct amd64_pvt *pvt, u8 dct, int csrow_nr) +{ + u32 nr_pages; + int cs_mode = CS_EVEN_PRIMARY | CS_ODD_PRIMARY; + + nr_pages = gpu_addr_mask_to_cs_size(pvt, dct, cs_mode, csrow_nr); + nr_pages <<= 20 - PAGE_SHIFT; + + edac_dbg(0, "csrow: %d, channel: %d\n", csrow_nr, dct); + edac_dbg(0, "nr_pages/channel: %u\n", nr_pages); + + return nr_pages; +} + +static void gpu_init_csrows(struct mem_ctl_info *mci) +{ + struct amd64_pvt *pvt = mci->pvt_info; + struct dimm_info *dimm; + u8 umc, cs; + + for_each_umc(umc) { + for_each_chip_select(cs, umc, pvt) { + if (!csrow_enabled(cs, umc, pvt)) + continue; + + dimm = mci->csrows[umc]->channels[cs]->dimm; + + edac_dbg(1, "MC node: %d, csrow: %d\n", + pvt->mc_node_id, cs); + + dimm->nr_pages = gpu_get_csrow_nr_pages(pvt, umc, cs); + dimm->edac_mode = EDAC_SECDED; + dimm->mtype = MEM_HBM2; + dimm->dtype = DEV_X16; + dimm->grain = 64; + } + } +} + +static void gpu_setup_mci_misc_attrs(struct mem_ctl_info *mci) +{ + struct amd64_pvt *pvt = mci->pvt_info; + + mci->mtype_cap = MEM_FLAG_HBM2; + mci->edac_ctl_cap = EDAC_FLAG_SECDED; + + mci->edac_cap = EDAC_FLAG_EC; + mci->mod_name = EDAC_MOD_STR; + mci->ctl_name = pvt->ctl_name; + mci->dev_name = pci_name(pvt->F3); + mci->ctl_page_to_phys = NULL; + + gpu_init_csrows(mci); +} + +/* ECC is enabled by default on GPU nodes */ +static bool gpu_ecc_enabled(struct amd64_pvt *pvt) +{ + return true; +} + +static inline u32 gpu_get_umc_base(u8 umc, u8 channel) +{ + /* + * On CPUs, there is one channel per UMC, so UMC numbering equals + * channel numbering. On GPUs, there are eight channels per UMC, + * so the channel numbering is different from UMC numbering. + * + * On CPU nodes channels are selected in 6th nibble + * UMC chY[3:0]= [(chY*2 + 1) : (chY*2)]50000; + * + * On GPU nodes channels are selected in 3rd nibble + * HBM chX[3:0]= [Y ]5X[3:0]000; + * HBM chX[7:4]= [Y+1]5X[3:0]000 + */ + umc *= 2; + + if (channel >= 4) + umc++; + + return 0x50000 + (umc << 20) + ((channel % 4) << 12); +} + +static void gpu_read_mc_regs(struct amd64_pvt *pvt) +{ + u8 nid = pvt->mc_node_id; + struct amd64_umc *umc; + u32 i, umc_base; + + /* Read registers from each UMC */ + for_each_umc(i) { + umc_base = gpu_get_umc_base(i, 0); + umc = &pvt->umc[i]; + + amd_smn_read(nid, umc_base + UMCCH_UMC_CFG, &umc->umc_cfg); + amd_smn_read(nid, umc_base + UMCCH_SDP_CTRL, &umc->sdp_ctrl); + amd_smn_read(nid, umc_base + UMCCH_ECC_CTRL, &umc->ecc_ctrl); + } +} + +static void gpu_read_base_mask(struct amd64_pvt *pvt) +{ + u32 base_reg, mask_reg; + u32 *base, *mask; + int umc, cs; + + for_each_umc(umc) { + for_each_chip_select(cs, umc, pvt) { + base_reg = gpu_get_umc_base(umc, cs) + UMCCH_BASE_ADDR; + base = &pvt->csels[umc].csbases[cs]; + + if (!amd_smn_read(pvt->mc_node_id, base_reg, base)) { + edac_dbg(0, " DCSB%d[%d]=0x%08x reg: 0x%x\n", + umc, cs, *base, base_reg); + } + + mask_reg = gpu_get_umc_base(umc, cs) + UMCCH_ADDR_MASK; + mask = &pvt->csels[umc].csmasks[cs]; + + if (!amd_smn_read(pvt->mc_node_id, mask_reg, mask)) { + edac_dbg(0, " DCSM%d[%d]=0x%08x reg: 0x%x\n", + umc, cs, *mask, mask_reg); + } + } + } +} + +static void gpu_prep_chip_selects(struct amd64_pvt *pvt) +{ + int umc; + + for_each_umc(umc) { + pvt->csels[umc].b_cnt = 8; + pvt->csels[umc].m_cnt = 8; + } +} + +static int gpu_hw_info_get(struct amd64_pvt *pvt) +{ + int ret; + + ret = gpu_get_node_map(); + if (ret) + return ret; + + pvt->umc = kcalloc(pvt->max_mcs, sizeof(struct amd64_umc), GFP_KERNEL); + if (!pvt->umc) + return -ENOMEM; + + gpu_prep_chip_selects(pvt); + gpu_read_base_mask(pvt); + gpu_read_mc_regs(pvt); + + return 0; +} + static void hw_info_put(struct amd64_pvt *pvt) { pci_dev_put(pvt->F1); @@ -3690,6 +3990,14 @@ static struct low_ops umc_ops = { .get_err_info = umc_get_err_info, }; +static struct low_ops gpu_ops = { + .hw_info_get = gpu_hw_info_get, + .ecc_enabled = gpu_ecc_enabled, + .setup_mci_misc_attrs = gpu_setup_mci_misc_attrs, + .dump_misc_regs = gpu_dump_misc_regs, + .get_err_info = gpu_get_err_info, +}; + /* Use Family 16h versions for defaults and adjust as needed below. */ static struct low_ops dct_ops = { .map_sysaddr_to_csrow = f1x_map_sysaddr_to_csrow, @@ -3813,9 +4121,27 @@ static int per_family_init(struct amd64_pvt *pvt) case 0x20 ... 0x2f: pvt->ctl_name = "F19h_M20h"; break; + case 0x30 ... 0x3f: + if (pvt->F3->device == PCI_DEVICE_ID_AMD_MI200_DF_F3) { + pvt->ctl_name = "MI200"; + pvt->max_mcs = 4; + pvt->ops = &gpu_ops; + } else { + pvt->ctl_name = "F19h_M30h"; + pvt->max_mcs = 8; + } + break; case 0x50 ... 0x5f: pvt->ctl_name = "F19h_M50h"; break; + case 0x60 ... 0x6f: + pvt->ctl_name = "F19h_M60h"; + pvt->flags.zn_regs_v2 = 1; + break; + case 0x70 ... 0x7f: + pvt->ctl_name = "F19h_M70h"; + pvt->flags.zn_regs_v2 = 1; + break; case 0xa0 ... 0xaf: pvt->ctl_name = "F19h_MA0h"; pvt->max_mcs = 12; @@ -3846,11 +4172,17 @@ static int init_one_instance(struct amd64_pvt *pvt) struct edac_mc_layer layers[2]; int ret = -ENOMEM; + /* + * For Heterogeneous family EDAC CHIP_SELECT and CHANNEL layers should + * be swapped to fit into the layers. + */ layers[0].type = EDAC_MC_LAYER_CHIP_SELECT; - layers[0].size = pvt->csels[0].b_cnt; + layers[0].size = (pvt->F3->device == PCI_DEVICE_ID_AMD_MI200_DF_F3) ? + pvt->max_mcs : pvt->csels[0].b_cnt; layers[0].is_virt_csrow = true; layers[1].type = EDAC_MC_LAYER_CHANNEL; - layers[1].size = pvt->max_mcs; + layers[1].size = (pvt->F3->device == PCI_DEVICE_ID_AMD_MI200_DF_F3) ? + pvt->csels[0].b_cnt : pvt->max_mcs; layers[1].is_virt_csrow = false; mci = edac_mc_alloc(pvt->mc_node_id, ARRAY_SIZE(layers), layers, 0); @@ -4074,8 +4406,6 @@ static int __init amd64_edac_init(void) amd64_err("%s on 32-bit is unsupported. USE AT YOUR OWN RISK!\n", EDAC_MOD_STR); #endif - printk(KERN_INFO "AMD64 EDAC driver v%s\n", EDAC_AMD64_VERSION); - return 0; err_pci: @@ -4121,7 +4451,7 @@ module_exit(amd64_edac_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("SoftwareBitMaker: Doug Thompson, Dave Peterson, Thayne Harbaugh; AMD"); -MODULE_DESCRIPTION("MC support for AMD64 memory controllers - " EDAC_AMD64_VERSION); +MODULE_DESCRIPTION("MC support for AMD64 memory controllers"); module_param(edac_op_state, int, 0444); MODULE_PARM_DESC(edac_op_state, "EDAC Error Reporting state: 0=Poll,1=NMI"); diff --git a/drivers/edac/amd64_edac.h b/drivers/edac/amd64_edac.h index e84fe0d4120a2c24769be988d445a2f1d9564784..5a4e4a59682b062b1c396ad1a75f9de3a206279d 100644 --- a/drivers/edac/amd64_edac.h +++ b/drivers/edac/amd64_edac.h @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include "edac_module.h" @@ -85,7 +86,6 @@ * sections 3.5.4 and 3.5.5 for more information. */ -#define EDAC_AMD64_VERSION "3.5.0" #define EDAC_MOD_STR "amd64_edac" /* Extended Model from CPUID, for CPU Revision numbers */ diff --git a/drivers/edac/mce_amd.c b/drivers/edac/mce_amd.c index cc5c63feb26a26693bad86647600b88a0cf55351..9215c06783df5f19dd64cb07b2f275f9ff8ee118 100644 --- a/drivers/edac/mce_amd.c +++ b/drivers/edac/mce_amd.c @@ -1186,7 +1186,8 @@ static void decode_smca_error(struct mce *m) if (xec < smca_mce_descs[bank_type].num_descs) pr_cont(", %s.\n", smca_mce_descs[bank_type].descs[xec]); - if (bank_type == SMCA_UMC && xec == 0 && decode_dram_ecc) + if ((bank_type == SMCA_UMC || bank_type == SMCA_UMC_V2) && + xec == 0 && decode_dram_ecc) decode_dram_ecc(topology_die_id(m->extcpu), m); } diff --git a/drivers/edac/npcm_edac.c b/drivers/edac/npcm_edac.c new file mode 100644 index 0000000000000000000000000000000000000000..12b95be3e9892a3c5ce0de13f01879833167581f --- /dev/null +++ b/drivers/edac/npcm_edac.c @@ -0,0 +1,543 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Copyright (c) 2022 Nuvoton Technology Corporation + +#include +#include +#include +#include +#include "edac_module.h" + +#define EDAC_MOD_NAME "npcm-edac" +#define EDAC_MSG_SIZE 256 + +/* chip serials */ +#define NPCM7XX_CHIP BIT(0) +#define NPCM8XX_CHIP BIT(1) + +/* syndrome values */ +#define UE_SYNDROME 0x03 + +/* error injection */ +#define ERROR_TYPE_CORRECTABLE 0 +#define ERROR_TYPE_UNCORRECTABLE 1 +#define ERROR_LOCATION_DATA 0 +#define ERROR_LOCATION_CHECKCODE 1 +#define ERROR_BIT_DATA_MAX 63 +#define ERROR_BIT_CHECKCODE_MAX 7 + +static char data_synd[] = { + 0xf4, 0xf1, 0xec, 0xea, 0xe9, 0xe6, 0xe5, 0xe3, + 0xdc, 0xda, 0xd9, 0xd6, 0xd5, 0xd3, 0xce, 0xcb, + 0xb5, 0xb0, 0xad, 0xab, 0xa8, 0xa7, 0xa4, 0xa2, + 0x9d, 0x9b, 0x98, 0x97, 0x94, 0x92, 0x8f, 0x8a, + 0x75, 0x70, 0x6d, 0x6b, 0x68, 0x67, 0x64, 0x62, + 0x5e, 0x5b, 0x58, 0x57, 0x54, 0x52, 0x4f, 0x4a, + 0x34, 0x31, 0x2c, 0x2a, 0x29, 0x26, 0x25, 0x23, + 0x1c, 0x1a, 0x19, 0x16, 0x15, 0x13, 0x0e, 0x0b +}; + +static struct regmap *npcm_regmap; + +struct npcm_platform_data { + /* chip serials */ + int chip; + + /* memory controller registers */ + u32 ctl_ecc_en; + u32 ctl_int_status; + u32 ctl_int_ack; + u32 ctl_int_mask_master; + u32 ctl_int_mask_ecc; + u32 ctl_ce_addr_l; + u32 ctl_ce_addr_h; + u32 ctl_ce_data_l; + u32 ctl_ce_data_h; + u32 ctl_ce_synd; + u32 ctl_ue_addr_l; + u32 ctl_ue_addr_h; + u32 ctl_ue_data_l; + u32 ctl_ue_data_h; + u32 ctl_ue_synd; + u32 ctl_source_id; + u32 ctl_controller_busy; + u32 ctl_xor_check_bits; + + /* masks and shifts */ + u32 ecc_en_mask; + u32 int_status_ce_mask; + u32 int_status_ue_mask; + u32 int_ack_ce_mask; + u32 int_ack_ue_mask; + u32 int_mask_master_non_ecc_mask; + u32 int_mask_master_global_mask; + u32 int_mask_ecc_non_event_mask; + u32 ce_addr_h_mask; + u32 ce_synd_mask; + u32 ce_synd_shift; + u32 ue_addr_h_mask; + u32 ue_synd_mask; + u32 ue_synd_shift; + u32 source_id_ce_mask; + u32 source_id_ce_shift; + u32 source_id_ue_mask; + u32 source_id_ue_shift; + u32 controller_busy_mask; + u32 xor_check_bits_mask; + u32 xor_check_bits_shift; + u32 writeback_en_mask; + u32 fwc_mask; +}; + +struct priv_data { + void __iomem *reg; + char message[EDAC_MSG_SIZE]; + const struct npcm_platform_data *pdata; + + /* error injection */ + struct dentry *debugfs; + u8 error_type; + u8 location; + u8 bit; +}; + +static void handle_ce(struct mem_ctl_info *mci) +{ + struct priv_data *priv = mci->pvt_info; + const struct npcm_platform_data *pdata; + u32 val_h = 0, val_l, id, synd; + u64 addr = 0, data = 0; + + pdata = priv->pdata; + regmap_read(npcm_regmap, pdata->ctl_ce_addr_l, &val_l); + if (pdata->chip == NPCM8XX_CHIP) { + regmap_read(npcm_regmap, pdata->ctl_ce_addr_h, &val_h); + val_h &= pdata->ce_addr_h_mask; + } + addr = ((addr | val_h) << 32) | val_l; + + regmap_read(npcm_regmap, pdata->ctl_ce_data_l, &val_l); + if (pdata->chip == NPCM8XX_CHIP) + regmap_read(npcm_regmap, pdata->ctl_ce_data_h, &val_h); + data = ((data | val_h) << 32) | val_l; + + regmap_read(npcm_regmap, pdata->ctl_source_id, &id); + id = (id & pdata->source_id_ce_mask) >> pdata->source_id_ce_shift; + + regmap_read(npcm_regmap, pdata->ctl_ce_synd, &synd); + synd = (synd & pdata->ce_synd_mask) >> pdata->ce_synd_shift; + + snprintf(priv->message, EDAC_MSG_SIZE, + "addr = 0x%llx, data = 0x%llx, id = 0x%x", addr, data, id); + + edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, addr >> PAGE_SHIFT, + addr & ~PAGE_MASK, synd, 0, 0, -1, priv->message, ""); +} + +static void handle_ue(struct mem_ctl_info *mci) +{ + struct priv_data *priv = mci->pvt_info; + const struct npcm_platform_data *pdata; + u32 val_h = 0, val_l, id, synd; + u64 addr = 0, data = 0; + + pdata = priv->pdata; + regmap_read(npcm_regmap, pdata->ctl_ue_addr_l, &val_l); + if (pdata->chip == NPCM8XX_CHIP) { + regmap_read(npcm_regmap, pdata->ctl_ue_addr_h, &val_h); + val_h &= pdata->ue_addr_h_mask; + } + addr = ((addr | val_h) << 32) | val_l; + + regmap_read(npcm_regmap, pdata->ctl_ue_data_l, &val_l); + if (pdata->chip == NPCM8XX_CHIP) + regmap_read(npcm_regmap, pdata->ctl_ue_data_h, &val_h); + data = ((data | val_h) << 32) | val_l; + + regmap_read(npcm_regmap, pdata->ctl_source_id, &id); + id = (id & pdata->source_id_ue_mask) >> pdata->source_id_ue_shift; + + regmap_read(npcm_regmap, pdata->ctl_ue_synd, &synd); + synd = (synd & pdata->ue_synd_mask) >> pdata->ue_synd_shift; + + snprintf(priv->message, EDAC_MSG_SIZE, + "addr = 0x%llx, data = 0x%llx, id = 0x%x", addr, data, id); + + edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, addr >> PAGE_SHIFT, + addr & ~PAGE_MASK, synd, 0, 0, -1, priv->message, ""); +} + +static irqreturn_t edac_ecc_isr(int irq, void *dev_id) +{ + const struct npcm_platform_data *pdata; + struct mem_ctl_info *mci = dev_id; + u32 status; + + pdata = ((struct priv_data *)mci->pvt_info)->pdata; + regmap_read(npcm_regmap, pdata->ctl_int_status, &status); + if (status & pdata->int_status_ce_mask) { + handle_ce(mci); + + /* acknowledge the CE interrupt */ + regmap_write(npcm_regmap, pdata->ctl_int_ack, + pdata->int_ack_ce_mask); + return IRQ_HANDLED; + } else if (status & pdata->int_status_ue_mask) { + handle_ue(mci); + + /* acknowledge the UE interrupt */ + regmap_write(npcm_regmap, pdata->ctl_int_ack, + pdata->int_ack_ue_mask); + return IRQ_HANDLED; + } + + WARN_ON_ONCE(1); + return IRQ_NONE; +} + +static ssize_t force_ecc_error(struct file *file, const char __user *data, + size_t count, loff_t *ppos) +{ + struct device *dev = file->private_data; + struct mem_ctl_info *mci = to_mci(dev); + struct priv_data *priv = mci->pvt_info; + const struct npcm_platform_data *pdata; + u32 val, syndrome; + int ret; + + pdata = priv->pdata; + edac_printk(KERN_INFO, EDAC_MOD_NAME, + "force an ECC error, type = %d, location = %d, bit = %d\n", + priv->error_type, priv->location, priv->bit); + + /* ensure no pending writes */ + ret = regmap_read_poll_timeout(npcm_regmap, pdata->ctl_controller_busy, + val, !(val & pdata->controller_busy_mask), + 1000, 10000); + if (ret) { + edac_printk(KERN_INFO, EDAC_MOD_NAME, + "wait pending writes timeout\n"); + return count; + } + + regmap_read(npcm_regmap, pdata->ctl_xor_check_bits, &val); + val &= ~pdata->xor_check_bits_mask; + + /* write syndrome to XOR_CHECK_BITS */ + if (priv->error_type == ERROR_TYPE_CORRECTABLE) { + if (priv->location == ERROR_LOCATION_DATA && + priv->bit > ERROR_BIT_DATA_MAX) { + edac_printk(KERN_INFO, EDAC_MOD_NAME, + "data bit should not exceed %d (%d)\n", + ERROR_BIT_DATA_MAX, priv->bit); + return count; + } + + if (priv->location == ERROR_LOCATION_CHECKCODE && + priv->bit > ERROR_BIT_CHECKCODE_MAX) { + edac_printk(KERN_INFO, EDAC_MOD_NAME, + "checkcode bit should not exceed %d (%d)\n", + ERROR_BIT_CHECKCODE_MAX, priv->bit); + return count; + } + + syndrome = priv->location ? 1 << priv->bit + : data_synd[priv->bit]; + + regmap_write(npcm_regmap, pdata->ctl_xor_check_bits, + val | (syndrome << pdata->xor_check_bits_shift) | + pdata->writeback_en_mask); + } else if (priv->error_type == ERROR_TYPE_UNCORRECTABLE) { + regmap_write(npcm_regmap, pdata->ctl_xor_check_bits, + val | (UE_SYNDROME << pdata->xor_check_bits_shift)); + } + + /* force write check */ + regmap_update_bits(npcm_regmap, pdata->ctl_xor_check_bits, + pdata->fwc_mask, pdata->fwc_mask); + + return count; +} + +static const struct file_operations force_ecc_error_fops = { + .open = simple_open, + .write = force_ecc_error, + .llseek = generic_file_llseek, +}; + +/* + * Setup debugfs for error injection. + * + * Nodes: + * error_type - 0: CE, 1: UE + * location - 0: data, 1: checkcode + * bit - 0 ~ 63 for data and 0 ~ 7 for checkcode + * force_ecc_error - trigger + * + * Examples: + * 1. Inject a correctable error (CE) at checkcode bit 7. + * ~# echo 0 > /sys/kernel/debug/edac/npcm-edac/error_type + * ~# echo 1 > /sys/kernel/debug/edac/npcm-edac/location + * ~# echo 7 > /sys/kernel/debug/edac/npcm-edac/bit + * ~# echo 1 > /sys/kernel/debug/edac/npcm-edac/force_ecc_error + * + * 2. Inject an uncorrectable error (UE). + * ~# echo 1 > /sys/kernel/debug/edac/npcm-edac/error_type + * ~# echo 1 > /sys/kernel/debug/edac/npcm-edac/force_ecc_error + */ +static void setup_debugfs(struct mem_ctl_info *mci) +{ + struct priv_data *priv = mci->pvt_info; + + priv->debugfs = edac_debugfs_create_dir(mci->mod_name); + if (!priv->debugfs) + return; + + edac_debugfs_create_x8("error_type", 0644, priv->debugfs, &priv->error_type); + edac_debugfs_create_x8("location", 0644, priv->debugfs, &priv->location); + edac_debugfs_create_x8("bit", 0644, priv->debugfs, &priv->bit); + edac_debugfs_create_file("force_ecc_error", 0200, priv->debugfs, + &mci->dev, &force_ecc_error_fops); +} + +static int setup_irq(struct mem_ctl_info *mci, struct platform_device *pdev) +{ + const struct npcm_platform_data *pdata; + int ret, irq; + + pdata = ((struct priv_data *)mci->pvt_info)->pdata; + irq = platform_get_irq(pdev, 0); + if (irq < 0) { + edac_printk(KERN_ERR, EDAC_MOD_NAME, "IRQ not defined in DTS\n"); + return irq; + } + + ret = devm_request_irq(&pdev->dev, irq, edac_ecc_isr, 0, + dev_name(&pdev->dev), mci); + if (ret < 0) { + edac_printk(KERN_ERR, EDAC_MOD_NAME, "failed to request IRQ\n"); + return ret; + } + + /* enable the functional group of ECC and mask the others */ + regmap_write(npcm_regmap, pdata->ctl_int_mask_master, + pdata->int_mask_master_non_ecc_mask); + + if (pdata->chip == NPCM8XX_CHIP) + regmap_write(npcm_regmap, pdata->ctl_int_mask_ecc, + pdata->int_mask_ecc_non_event_mask); + + return 0; +} + +static const struct regmap_config npcm_regmap_cfg = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, +}; + +static int edac_probe(struct platform_device *pdev) +{ + const struct npcm_platform_data *pdata; + struct device *dev = &pdev->dev; + struct edac_mc_layer layers[1]; + struct mem_ctl_info *mci; + struct priv_data *priv; + void __iomem *reg; + u32 val; + int rc; + + reg = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(reg)) + return PTR_ERR(reg); + + npcm_regmap = devm_regmap_init_mmio(dev, reg, &npcm_regmap_cfg); + if (IS_ERR(npcm_regmap)) + return PTR_ERR(npcm_regmap); + + pdata = of_device_get_match_data(dev); + if (!pdata) + return -EINVAL; + + /* bail out if ECC is not enabled */ + regmap_read(npcm_regmap, pdata->ctl_ecc_en, &val); + if (!(val & pdata->ecc_en_mask)) { + edac_printk(KERN_ERR, EDAC_MOD_NAME, "ECC is not enabled\n"); + return -EPERM; + } + + edac_op_state = EDAC_OPSTATE_INT; + + layers[0].type = EDAC_MC_LAYER_ALL_MEM; + layers[0].size = 1; + + mci = edac_mc_alloc(0, ARRAY_SIZE(layers), layers, + sizeof(struct priv_data)); + if (!mci) + return -ENOMEM; + + mci->pdev = &pdev->dev; + priv = mci->pvt_info; + priv->reg = reg; + priv->pdata = pdata; + platform_set_drvdata(pdev, mci); + + mci->mtype_cap = MEM_FLAG_DDR4; + mci->edac_ctl_cap = EDAC_FLAG_SECDED; + mci->scrub_cap = SCRUB_FLAG_HW_SRC; + mci->scrub_mode = SCRUB_HW_SRC; + mci->edac_cap = EDAC_FLAG_SECDED; + mci->ctl_name = "npcm_ddr_controller"; + mci->dev_name = dev_name(&pdev->dev); + mci->mod_name = EDAC_MOD_NAME; + mci->ctl_page_to_phys = NULL; + + rc = setup_irq(mci, pdev); + if (rc) + goto free_edac_mc; + + rc = edac_mc_add_mc(mci); + if (rc) + goto free_edac_mc; + + if (IS_ENABLED(CONFIG_EDAC_DEBUG) && pdata->chip == NPCM8XX_CHIP) + setup_debugfs(mci); + + return rc; + +free_edac_mc: + edac_mc_free(mci); + return rc; +} + +static int edac_remove(struct platform_device *pdev) +{ + struct mem_ctl_info *mci = platform_get_drvdata(pdev); + struct priv_data *priv = mci->pvt_info; + const struct npcm_platform_data *pdata; + + pdata = priv->pdata; + if (IS_ENABLED(CONFIG_EDAC_DEBUG) && pdata->chip == NPCM8XX_CHIP) + edac_debugfs_remove_recursive(priv->debugfs); + + edac_mc_del_mc(&pdev->dev); + edac_mc_free(mci); + + regmap_write(npcm_regmap, pdata->ctl_int_mask_master, + pdata->int_mask_master_global_mask); + regmap_update_bits(npcm_regmap, pdata->ctl_ecc_en, pdata->ecc_en_mask, 0); + + return 0; +} + +static const struct npcm_platform_data npcm750_edac = { + .chip = NPCM7XX_CHIP, + + /* memory controller registers */ + .ctl_ecc_en = 0x174, + .ctl_int_status = 0x1d0, + .ctl_int_ack = 0x1d4, + .ctl_int_mask_master = 0x1d8, + .ctl_ce_addr_l = 0x188, + .ctl_ce_data_l = 0x190, + .ctl_ce_synd = 0x18c, + .ctl_ue_addr_l = 0x17c, + .ctl_ue_data_l = 0x184, + .ctl_ue_synd = 0x180, + .ctl_source_id = 0x194, + + /* masks and shifts */ + .ecc_en_mask = BIT(24), + .int_status_ce_mask = GENMASK(4, 3), + .int_status_ue_mask = GENMASK(6, 5), + .int_ack_ce_mask = GENMASK(4, 3), + .int_ack_ue_mask = GENMASK(6, 5), + .int_mask_master_non_ecc_mask = GENMASK(30, 7) | GENMASK(2, 0), + .int_mask_master_global_mask = BIT(31), + .ce_synd_mask = GENMASK(6, 0), + .ce_synd_shift = 0, + .ue_synd_mask = GENMASK(6, 0), + .ue_synd_shift = 0, + .source_id_ce_mask = GENMASK(29, 16), + .source_id_ce_shift = 16, + .source_id_ue_mask = GENMASK(13, 0), + .source_id_ue_shift = 0, +}; + +static const struct npcm_platform_data npcm845_edac = { + .chip = NPCM8XX_CHIP, + + /* memory controller registers */ + .ctl_ecc_en = 0x16c, + .ctl_int_status = 0x228, + .ctl_int_ack = 0x244, + .ctl_int_mask_master = 0x220, + .ctl_int_mask_ecc = 0x260, + .ctl_ce_addr_l = 0x18c, + .ctl_ce_addr_h = 0x190, + .ctl_ce_data_l = 0x194, + .ctl_ce_data_h = 0x198, + .ctl_ce_synd = 0x190, + .ctl_ue_addr_l = 0x17c, + .ctl_ue_addr_h = 0x180, + .ctl_ue_data_l = 0x184, + .ctl_ue_data_h = 0x188, + .ctl_ue_synd = 0x180, + .ctl_source_id = 0x19c, + .ctl_controller_busy = 0x20c, + .ctl_xor_check_bits = 0x174, + + /* masks and shifts */ + .ecc_en_mask = GENMASK(17, 16), + .int_status_ce_mask = GENMASK(1, 0), + .int_status_ue_mask = GENMASK(3, 2), + .int_ack_ce_mask = GENMASK(1, 0), + .int_ack_ue_mask = GENMASK(3, 2), + .int_mask_master_non_ecc_mask = GENMASK(30, 3) | GENMASK(1, 0), + .int_mask_master_global_mask = BIT(31), + .int_mask_ecc_non_event_mask = GENMASK(8, 4), + .ce_addr_h_mask = GENMASK(1, 0), + .ce_synd_mask = GENMASK(15, 8), + .ce_synd_shift = 8, + .ue_addr_h_mask = GENMASK(1, 0), + .ue_synd_mask = GENMASK(15, 8), + .ue_synd_shift = 8, + .source_id_ce_mask = GENMASK(29, 16), + .source_id_ce_shift = 16, + .source_id_ue_mask = GENMASK(13, 0), + .source_id_ue_shift = 0, + .controller_busy_mask = BIT(0), + .xor_check_bits_mask = GENMASK(23, 16), + .xor_check_bits_shift = 16, + .writeback_en_mask = BIT(24), + .fwc_mask = BIT(8), +}; + +static const struct of_device_id npcm_edac_of_match[] = { + { + .compatible = "nuvoton,npcm750-memory-controller", + .data = &npcm750_edac + }, + { + .compatible = "nuvoton,npcm845-memory-controller", + .data = &npcm845_edac + }, + {}, +}; + +MODULE_DEVICE_TABLE(of, npcm_edac_of_match); + +static struct platform_driver npcm_edac_driver = { + .driver = { + .name = "npcm-edac", + .of_match_table = npcm_edac_of_match, + }, + .probe = edac_probe, + .remove = edac_remove, +}; + +module_platform_driver(npcm_edac_driver); + +MODULE_AUTHOR("Medad CChien "); +MODULE_AUTHOR("Marvin Lin "); +MODULE_DESCRIPTION("Nuvoton NPCM EDAC Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/edac/thunderx_edac.c b/drivers/edac/thunderx_edac.c index 0bcd9f02c84a482a54b7b2cb445c3fb18b796459..b9c5772da959cce5200f0845c0a1d4c9281892b9 100644 --- a/drivers/edac/thunderx_edac.c +++ b/drivers/edac/thunderx_edac.c @@ -481,7 +481,7 @@ static int thunderx_create_debugfs_nodes(struct dentry *parent, ent = edac_debugfs_create_file(attrs[i]->name, attrs[i]->mode, parent, data, &attrs[i]->fops); - if (!ent) + if (IS_ERR(ent)) break; } diff --git a/drivers/extcon/Kconfig b/drivers/extcon/Kconfig index 290186e44e6bdbe34d1f41805bca894e38c7e741..0ef1971d22bb0b76796f02c2d608430e7b77dc3d 100644 --- a/drivers/extcon/Kconfig +++ b/drivers/extcon/Kconfig @@ -185,6 +185,7 @@ config EXTCON_USBC_TUSB320 tristate "TI TUSB320 USB-C extcon support" depends on I2C && TYPEC select REGMAP_I2C + depends on USB_ROLE_SWITCH || !USB_ROLE_SWITCH help Say Y here to enable support for USB Type C cable detection extcon support using a TUSB320. diff --git a/drivers/extcon/extcon-axp288.c b/drivers/extcon/extcon-axp288.c index 180be768c2157b6c79f5718ef411d498ed2ffc34..a703a8315634df6aea13e1c43e53d3f643925638 100644 --- a/drivers/extcon/extcon-axp288.c +++ b/drivers/extcon/extcon-axp288.c @@ -393,7 +393,7 @@ static int axp288_extcon_probe(struct platform_device *pdev) adev = acpi_dev_get_first_match_dev("INT3496", NULL, -1); if (adev) { info->id_extcon = extcon_get_extcon_dev(acpi_dev_name(adev)); - put_device(&adev->dev); + acpi_dev_put(adev); if (IS_ERR(info->id_extcon)) return PTR_ERR(info->id_extcon); diff --git a/drivers/extcon/extcon-fsa9480.c b/drivers/extcon/extcon-fsa9480.c index e8b2671eb29bce67e660fa05c04cafd75b77fb2d..e458ce0c45ab70ba607b756e0f75eb59f12e6353 100644 --- a/drivers/extcon/extcon-fsa9480.c +++ b/drivers/extcon/extcon-fsa9480.c @@ -369,7 +369,7 @@ static struct i2c_driver fsa9480_i2c_driver = { .pm = &fsa9480_pm_ops, .of_match_table = fsa9480_of_match, }, - .probe_new = fsa9480_probe, + .probe = fsa9480_probe, .id_table = fsa9480_id, }; diff --git a/drivers/extcon/extcon-palmas.c b/drivers/extcon/extcon-palmas.c index 32f8b541770bf0f7d7223c1794fed598dd76f17a..d339b86804455b8863944a93edef68f3af9d71ca 100644 --- a/drivers/extcon/extcon-palmas.c +++ b/drivers/extcon/extcon-palmas.c @@ -18,7 +18,6 @@ #include #include #include -#include #include #include diff --git a/drivers/extcon/extcon-ptn5150.c b/drivers/extcon/extcon-ptn5150.c index 017a07197f380e55dac9f3cc9e5b4580cbe02867..4616da7e5430ea54849b06c47d06b35a42917ac4 100644 --- a/drivers/extcon/extcon-ptn5150.c +++ b/drivers/extcon/extcon-ptn5150.c @@ -348,7 +348,7 @@ static struct i2c_driver ptn5150_i2c_driver = { .name = "ptn5150", .of_match_table = ptn5150_dt_match, }, - .probe_new = ptn5150_i2c_probe, + .probe = ptn5150_i2c_probe, .id_table = ptn5150_i2c_id, }; module_i2c_driver(ptn5150_i2c_driver); diff --git a/drivers/extcon/extcon-qcom-spmi-misc.c b/drivers/extcon/extcon-qcom-spmi-misc.c index eb02cb962b5e18585ef4be6266351314527a8493..f72e90ceca53d5909a5c01e0ade3f5005d2d2323 100644 --- a/drivers/extcon/extcon-qcom-spmi-misc.c +++ b/drivers/extcon/extcon-qcom-spmi-misc.c @@ -123,7 +123,7 @@ static int qcom_usb_extcon_probe(struct platform_device *pdev) if (ret) return ret; - info->id_irq = platform_get_irq_byname(pdev, "usb_id"); + info->id_irq = platform_get_irq_byname_optional(pdev, "usb_id"); if (info->id_irq > 0) { ret = devm_request_threaded_irq(dev, info->id_irq, NULL, qcom_usb_irq_handler, @@ -136,7 +136,7 @@ static int qcom_usb_extcon_probe(struct platform_device *pdev) } } - info->vbus_irq = platform_get_irq_byname(pdev, "usb_vbus"); + info->vbus_irq = platform_get_irq_byname_optional(pdev, "usb_vbus"); if (info->vbus_irq > 0) { ret = devm_request_threaded_irq(dev, info->vbus_irq, NULL, qcom_usb_irq_handler, diff --git a/drivers/extcon/extcon-rt8973a.c b/drivers/extcon/extcon-rt8973a.c index afc9b405d103010936a7881771bf57473d684f92..19bb49f13fb08c9f36eccca56e96de52bb263554 100644 --- a/drivers/extcon/extcon-rt8973a.c +++ b/drivers/extcon/extcon-rt8973a.c @@ -695,7 +695,7 @@ static struct i2c_driver rt8973a_muic_i2c_driver = { .pm = &rt8973a_muic_pm_ops, .of_match_table = rt8973a_dt_match, }, - .probe_new = rt8973a_muic_i2c_probe, + .probe = rt8973a_muic_i2c_probe, .remove = rt8973a_muic_i2c_remove, .id_table = rt8973a_i2c_id, }; diff --git a/drivers/extcon/extcon-sm5502.c b/drivers/extcon/extcon-sm5502.c index 8401e8b277889a9b695baf39051cf4e4aecd986e..c8c4b9ef72aa1fe4d50d76bcecea53224dd6a328 100644 --- a/drivers/extcon/extcon-sm5502.c +++ b/drivers/extcon/extcon-sm5502.c @@ -840,7 +840,7 @@ static struct i2c_driver sm5502_muic_i2c_driver = { .pm = &sm5502_muic_pm_ops, .of_match_table = sm5502_dt_match, }, - .probe_new = sm5022_muic_i2c_probe, + .probe = sm5022_muic_i2c_probe, .id_table = sm5502_i2c_id, }; diff --git a/drivers/extcon/extcon-usbc-tusb320.c b/drivers/extcon/extcon-usbc-tusb320.c index b408ce989c223900878be758ba44c9237a47966c..4d08c2123e5980e27cfe262607ee8320fb004242 100644 --- a/drivers/extcon/extcon-usbc-tusb320.c +++ b/drivers/extcon/extcon-usbc-tusb320.c @@ -15,6 +15,8 @@ #include #include #include +#include +#include #define TUSB320_REG8 0x8 #define TUSB320_REG8_CURRENT_MODE_ADVERTISE GENMASK(7, 6) @@ -26,16 +28,16 @@ #define TUSB320_REG8_CURRENT_MODE_DETECT_MED 0x1 #define TUSB320_REG8_CURRENT_MODE_DETECT_ACC 0x2 #define TUSB320_REG8_CURRENT_MODE_DETECT_HI 0x3 -#define TUSB320_REG8_ACCESSORY_CONNECTED GENMASK(3, 2) +#define TUSB320_REG8_ACCESSORY_CONNECTED GENMASK(3, 1) #define TUSB320_REG8_ACCESSORY_CONNECTED_NONE 0x0 #define TUSB320_REG8_ACCESSORY_CONNECTED_AUDIO 0x4 -#define TUSB320_REG8_ACCESSORY_CONNECTED_ACC 0x5 -#define TUSB320_REG8_ACCESSORY_CONNECTED_DEBUG 0x6 +#define TUSB320_REG8_ACCESSORY_CONNECTED_ACHRG 0x5 +#define TUSB320_REG8_ACCESSORY_CONNECTED_DBGDFP 0x6 +#define TUSB320_REG8_ACCESSORY_CONNECTED_DBGUFP 0x7 #define TUSB320_REG8_ACTIVE_CABLE_DETECTION BIT(0) #define TUSB320_REG9 0x9 -#define TUSB320_REG9_ATTACHED_STATE_SHIFT 6 -#define TUSB320_REG9_ATTACHED_STATE_MASK 0x3 +#define TUSB320_REG9_ATTACHED_STATE GENMASK(7, 6) #define TUSB320_REG9_CABLE_DIRECTION BIT(5) #define TUSB320_REG9_INTERRUPT_STATUS BIT(4) @@ -78,6 +80,8 @@ struct tusb320_priv { struct typec_capability cap; enum typec_port_type port_type; enum typec_pwr_opmode pwr_opmode; + struct fwnode_handle *connector_fwnode; + struct usb_role_switch *role_sw; }; static const char * const tusb_attached_states[] = { @@ -249,8 +253,7 @@ static void tusb320_extcon_irq_handler(struct tusb320_priv *priv, u8 reg) { int state, polarity; - state = (reg >> TUSB320_REG9_ATTACHED_STATE_SHIFT) & - TUSB320_REG9_ATTACHED_STATE_MASK; + state = FIELD_GET(TUSB320_REG9_ATTACHED_STATE, reg); polarity = !!(reg & TUSB320_REG9_CABLE_DIRECTION); dev_dbg(priv->dev, "attached state: %s, polarity: %d\n", @@ -276,32 +279,86 @@ static void tusb320_typec_irq_handler(struct tusb320_priv *priv, u8 reg9) { struct typec_port *port = priv->port; struct device *dev = priv->dev; - u8 mode, role, state; + int typec_mode; + enum usb_role usb_role; + enum typec_role pwr_role; + enum typec_data_role data_role; + u8 state, mode, accessory; int ret, reg8; bool ori; + ret = regmap_read(priv->regmap, TUSB320_REG8, ®8); + if (ret) { + dev_err(dev, "error during reg8 i2c read, ret=%d!\n", ret); + return; + } + ori = reg9 & TUSB320_REG9_CABLE_DIRECTION; typec_set_orientation(port, ori ? TYPEC_ORIENTATION_REVERSE : TYPEC_ORIENTATION_NORMAL); - state = (reg9 >> TUSB320_REG9_ATTACHED_STATE_SHIFT) & - TUSB320_REG9_ATTACHED_STATE_MASK; - if (state == TUSB320_ATTACHED_STATE_DFP) - role = TYPEC_SOURCE; - else - role = TYPEC_SINK; + state = FIELD_GET(TUSB320_REG9_ATTACHED_STATE, reg9); + accessory = FIELD_GET(TUSB320_REG8_ACCESSORY_CONNECTED, reg8); + + switch (state) { + case TUSB320_ATTACHED_STATE_DFP: + typec_mode = TYPEC_MODE_USB2; + usb_role = USB_ROLE_HOST; + pwr_role = TYPEC_SOURCE; + data_role = TYPEC_HOST; + break; + case TUSB320_ATTACHED_STATE_UFP: + typec_mode = TYPEC_MODE_USB2; + usb_role = USB_ROLE_DEVICE; + pwr_role = TYPEC_SINK; + data_role = TYPEC_DEVICE; + break; + case TUSB320_ATTACHED_STATE_ACC: + /* + * Accessory detected. For debug accessories, just make some + * qualified guesses as to the role for lack of a better option. + */ + if (accessory == TUSB320_REG8_ACCESSORY_CONNECTED_AUDIO || + accessory == TUSB320_REG8_ACCESSORY_CONNECTED_ACHRG) { + typec_mode = TYPEC_MODE_AUDIO; + usb_role = USB_ROLE_NONE; + pwr_role = TYPEC_SINK; + data_role = TYPEC_DEVICE; + break; + } else if (accessory == + TUSB320_REG8_ACCESSORY_CONNECTED_DBGDFP) { + typec_mode = TYPEC_MODE_DEBUG; + pwr_role = TYPEC_SOURCE; + usb_role = USB_ROLE_HOST; + data_role = TYPEC_HOST; + break; + } else if (accessory == + TUSB320_REG8_ACCESSORY_CONNECTED_DBGUFP) { + typec_mode = TYPEC_MODE_DEBUG; + pwr_role = TYPEC_SINK; + usb_role = USB_ROLE_DEVICE; + data_role = TYPEC_DEVICE; + break; + } - typec_set_vconn_role(port, role); - typec_set_pwr_role(port, role); - typec_set_data_role(port, role == TYPEC_SOURCE ? - TYPEC_HOST : TYPEC_DEVICE); + dev_warn(priv->dev, "unexpected ACCESSORY_CONNECTED state %d\n", + accessory); - ret = regmap_read(priv->regmap, TUSB320_REG8, ®8); - if (ret) { - dev_err(dev, "error during reg8 i2c read, ret=%d!\n", ret); - return; + fallthrough; + default: + typec_mode = TYPEC_MODE_USB2; + usb_role = USB_ROLE_NONE; + pwr_role = TYPEC_SINK; + data_role = TYPEC_DEVICE; + break; } + typec_set_vconn_role(port, pwr_role); + typec_set_pwr_role(port, pwr_role); + typec_set_data_role(port, data_role); + typec_set_mode(port, typec_mode); + usb_role_switch_set_role(priv->role_sw, usb_role); + mode = FIELD_GET(TUSB320_REG8_CURRENT_MODE_DETECT, reg8); if (mode == TUSB320_REG8_CURRENT_MODE_DETECT_DEF) typec_set_pwr_opmode(port, TYPEC_PWR_MODE_USB); @@ -391,27 +448,25 @@ static int tusb320_typec_probe(struct i2c_client *client, /* Type-C connector found. */ ret = typec_get_fw_cap(&priv->cap, connector); if (ret) - return ret; + goto err_put; priv->port_type = priv->cap.type; /* This goes into register 0x8 field CURRENT_MODE_ADVERTISE */ ret = fwnode_property_read_string(connector, "typec-power-opmode", &cap_str); if (ret) - return ret; + goto err_put; ret = typec_find_pwr_opmode(cap_str); if (ret < 0) - return ret; - if (ret == TYPEC_PWR_MODE_PD) - return -EINVAL; + goto err_put; priv->pwr_opmode = ret; /* Initialize the hardware with the devicetree settings. */ ret = tusb320_set_adv_pwr_mode(priv); if (ret) - return ret; + goto err_put; priv->cap.revision = USB_TYPEC_REV_1_1; priv->cap.accessory[0] = TYPEC_ACCESSORY_AUDIO; @@ -422,10 +477,36 @@ static int tusb320_typec_probe(struct i2c_client *client, priv->cap.fwnode = connector; priv->port = typec_register_port(&client->dev, &priv->cap); - if (IS_ERR(priv->port)) - return PTR_ERR(priv->port); + if (IS_ERR(priv->port)) { + ret = PTR_ERR(priv->port); + goto err_put; + } + + /* Find any optional USB role switch that needs reporting to */ + priv->role_sw = fwnode_usb_role_switch_get(connector); + if (IS_ERR(priv->role_sw)) { + ret = PTR_ERR(priv->role_sw); + goto err_unreg; + } + + priv->connector_fwnode = connector; return 0; + +err_unreg: + typec_unregister_port(priv->port); + +err_put: + fwnode_handle_put(connector); + + return ret; +} + +static void tusb320_typec_remove(struct tusb320_priv *priv) +{ + usb_role_switch_put(priv->role_sw); + typec_unregister_port(priv->port); + fwnode_handle_put(priv->connector_fwnode); } static int tusb320_probe(struct i2c_client *client) @@ -438,7 +519,9 @@ static int tusb320_probe(struct i2c_client *client) priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; + priv->dev = &client->dev; + i2c_set_clientdata(client, priv); priv->regmap = devm_regmap_init_i2c(client, &tusb320_regmap_config); if (IS_ERR(priv->regmap)) @@ -489,10 +572,19 @@ static int tusb320_probe(struct i2c_client *client) tusb320_irq_handler, IRQF_TRIGGER_FALLING | IRQF_ONESHOT, client->name, priv); + if (ret) + tusb320_typec_remove(priv); return ret; } +static void tusb320_remove(struct i2c_client *client) +{ + struct tusb320_priv *priv = i2c_get_clientdata(client); + + tusb320_typec_remove(priv); +} + static const struct of_device_id tusb320_extcon_dt_match[] = { { .compatible = "ti,tusb320", .data = &tusb320_ops, }, { .compatible = "ti,tusb320l", .data = &tusb320l_ops, }, @@ -501,7 +593,8 @@ static const struct of_device_id tusb320_extcon_dt_match[] = { MODULE_DEVICE_TABLE(of, tusb320_extcon_dt_match); static struct i2c_driver tusb320_extcon_driver = { - .probe_new = tusb320_probe, + .probe = tusb320_probe, + .remove = tusb320_remove, .driver = { .name = "extcon-tusb320", .of_match_table = tusb320_extcon_dt_match, diff --git a/drivers/extcon/extcon.c b/drivers/extcon/extcon.c index d43ba8e7260dd03ad893612669d3fde1104fc830..6f7a60d2ed9161b21625a5949c9a24868cf4de33 100644 --- a/drivers/extcon/extcon.c +++ b/drivers/extcon/extcon.c @@ -16,6 +16,7 @@ #include #include +#include #include #include #include @@ -206,6 +207,14 @@ static const struct __extcon_info { * @attr_name: "name" sysfs entry * @attr_state: "state" sysfs entry * @attrs: the array pointing to attr_name and attr_state for attr_g + * @usb_propval: the array of USB connector properties + * @chg_propval: the array of charger connector properties + * @jack_propval: the array of jack connector properties + * @disp_propval: the array of display connector properties + * @usb_bits: the bit array of the USB connector property capabilities + * @chg_bits: the bit array of the charger connector property capabilities + * @jack_bits: the bit array of the jack connector property capabilities + * @disp_bits: the bit array of the display connector property capabilities */ struct extcon_cable { struct extcon_dev *edev; @@ -222,20 +231,21 @@ struct extcon_cable { union extcon_property_value jack_propval[EXTCON_PROP_JACK_CNT]; union extcon_property_value disp_propval[EXTCON_PROP_DISP_CNT]; - unsigned long usb_bits[BITS_TO_LONGS(EXTCON_PROP_USB_CNT)]; - unsigned long chg_bits[BITS_TO_LONGS(EXTCON_PROP_CHG_CNT)]; - unsigned long jack_bits[BITS_TO_LONGS(EXTCON_PROP_JACK_CNT)]; - unsigned long disp_bits[BITS_TO_LONGS(EXTCON_PROP_DISP_CNT)]; + DECLARE_BITMAP(usb_bits, EXTCON_PROP_USB_CNT); + DECLARE_BITMAP(chg_bits, EXTCON_PROP_CHG_CNT); + DECLARE_BITMAP(jack_bits, EXTCON_PROP_JACK_CNT); + DECLARE_BITMAP(disp_bits, EXTCON_PROP_DISP_CNT); }; static struct class *extcon_class; +static DEFINE_IDA(extcon_dev_ids); static LIST_HEAD(extcon_dev_list); static DEFINE_MUTEX(extcon_dev_list_lock); static int check_mutually_exclusive(struct extcon_dev *edev, u32 new_state) { - int i = 0; + int i; if (!edev->mutually_exclusive) return 0; @@ -362,12 +372,12 @@ static ssize_t state_show(struct device *dev, struct device_attribute *attr, struct extcon_dev *edev = dev_get_drvdata(dev); if (edev->max_supported == 0) - return sprintf(buf, "%u\n", edev->state); + return sysfs_emit(buf, "%u\n", edev->state); for (i = 0; i < edev->max_supported; i++) { - count += sprintf(buf + count, "%s=%d\n", - extcon_info[edev->supported_cable[i]].name, - !!(edev->state & BIT(i))); + count += sysfs_emit_at(buf, count, "%s=%d\n", + extcon_info[edev->supported_cable[i]].name, + !!(edev->state & BIT(i))); } return count; @@ -379,7 +389,7 @@ static ssize_t name_show(struct device *dev, struct device_attribute *attr, { struct extcon_dev *edev = dev_get_drvdata(dev); - return sprintf(buf, "%s\n", edev->name); + return sysfs_emit(buf, "%s\n", edev->name); } static DEVICE_ATTR_RO(name); @@ -390,8 +400,8 @@ static ssize_t cable_name_show(struct device *dev, attr_name); int i = cable->cable_index; - return sprintf(buf, "%s\n", - extcon_info[cable->edev->supported_cable[i]].name); + return sysfs_emit(buf, "%s\n", + extcon_info[cable->edev->supported_cable[i]].name); } static ssize_t cable_state_show(struct device *dev, @@ -402,8 +412,8 @@ static ssize_t cable_state_show(struct device *dev, int i = cable->cable_index; - return sprintf(buf, "%d\n", - extcon_get_state(cable->edev, cable->edev->supported_cable[i])); + return sysfs_emit(buf, "%d\n", + extcon_get_state(cable->edev, cable->edev->supported_cable[i])); } /** @@ -1012,12 +1022,13 @@ ATTRIBUTE_GROUPS(extcon); static int create_extcon_class(void) { - if (!extcon_class) { - extcon_class = class_create("extcon"); - if (IS_ERR(extcon_class)) - return PTR_ERR(extcon_class); - extcon_class->dev_groups = extcon_groups; - } + if (extcon_class) + return 0; + + extcon_class = class_create("extcon"); + if (IS_ERR(extcon_class)) + return PTR_ERR(extcon_class); + extcon_class->dev_groups = extcon_groups; return 0; } @@ -1069,6 +1080,156 @@ void extcon_dev_free(struct extcon_dev *edev) } EXPORT_SYMBOL_GPL(extcon_dev_free); +/** + * extcon_alloc_cables() - alloc the cables for extcon device + * @edev: extcon device which has cables + * + * Returns 0 if success or error number if fail. + */ +static int extcon_alloc_cables(struct extcon_dev *edev) +{ + int index; + char *str; + struct extcon_cable *cable; + + if (!edev) + return -EINVAL; + + if (!edev->max_supported) + return 0; + + edev->cables = kcalloc(edev->max_supported, sizeof(*edev->cables), + GFP_KERNEL); + if (!edev->cables) + return -ENOMEM; + + for (index = 0; index < edev->max_supported; index++) { + cable = &edev->cables[index]; + + str = kasprintf(GFP_KERNEL, "cable.%d", index); + if (!str) { + for (index--; index >= 0; index--) { + cable = &edev->cables[index]; + kfree(cable->attr_g.name); + } + + kfree(edev->cables); + return -ENOMEM; + } + + cable->edev = edev; + cable->cable_index = index; + cable->attrs[0] = &cable->attr_name.attr; + cable->attrs[1] = &cable->attr_state.attr; + cable->attrs[2] = NULL; + cable->attr_g.name = str; + cable->attr_g.attrs = cable->attrs; + + sysfs_attr_init(&cable->attr_name.attr); + cable->attr_name.attr.name = "name"; + cable->attr_name.attr.mode = 0444; + cable->attr_name.show = cable_name_show; + + sysfs_attr_init(&cable->attr_state.attr); + cable->attr_state.attr.name = "state"; + cable->attr_state.attr.mode = 0444; + cable->attr_state.show = cable_state_show; + } + + return 0; +} + +/** + * extcon_alloc_muex() - alloc the mutual exclusive for extcon device + * @edev: extcon device + * + * Returns 0 if success or error number if fail. + */ +static int extcon_alloc_muex(struct extcon_dev *edev) +{ + char *name; + int index; + + if (!edev) + return -EINVAL; + + if (!(edev->max_supported && edev->mutually_exclusive)) + return 0; + + /* Count the size of mutually_exclusive array */ + for (index = 0; edev->mutually_exclusive[index]; index++) + ; + + edev->attrs_muex = kcalloc(index + 1, sizeof(*edev->attrs_muex), + GFP_KERNEL); + if (!edev->attrs_muex) + return -ENOMEM; + + edev->d_attrs_muex = kcalloc(index, sizeof(*edev->d_attrs_muex), + GFP_KERNEL); + if (!edev->d_attrs_muex) { + kfree(edev->attrs_muex); + return -ENOMEM; + } + + for (index = 0; edev->mutually_exclusive[index]; index++) { + name = kasprintf(GFP_KERNEL, "0x%x", + edev->mutually_exclusive[index]); + if (!name) { + for (index--; index >= 0; index--) + kfree(edev->d_attrs_muex[index].attr.name); + + kfree(edev->d_attrs_muex); + kfree(edev->attrs_muex); + return -ENOMEM; + } + sysfs_attr_init(&edev->d_attrs_muex[index].attr); + edev->d_attrs_muex[index].attr.name = name; + edev->d_attrs_muex[index].attr.mode = 0000; + edev->attrs_muex[index] = &edev->d_attrs_muex[index].attr; + } + edev->attr_g_muex.name = muex_name; + edev->attr_g_muex.attrs = edev->attrs_muex; + + return 0; +} + +/** + * extcon_alloc_groups() - alloc the groups for extcon device + * @edev: extcon device + * + * Returns 0 if success or error number if fail. + */ +static int extcon_alloc_groups(struct extcon_dev *edev) +{ + int index; + + if (!edev) + return -EINVAL; + + if (!edev->max_supported) + return 0; + + edev->extcon_dev_type.groups = kcalloc(edev->max_supported + 2, + sizeof(*edev->extcon_dev_type.groups), + GFP_KERNEL); + if (!edev->extcon_dev_type.groups) + return -ENOMEM; + + edev->extcon_dev_type.name = dev_name(&edev->dev); + edev->extcon_dev_type.release = dummy_sysfs_dev_release; + + for (index = 0; index < edev->max_supported; index++) + edev->extcon_dev_type.groups[index] = &edev->cables[index].attr_g; + + if (edev->mutually_exclusive) + edev->extcon_dev_type.groups[index] = &edev->attr_g_muex; + + edev->dev.type = &edev->extcon_dev_type; + + return 0; +} + /** * extcon_dev_register() - Register an new extcon device * @edev: the extcon device to be registered @@ -1085,19 +1246,16 @@ EXPORT_SYMBOL_GPL(extcon_dev_free); */ int extcon_dev_register(struct extcon_dev *edev) { - int ret, index = 0; - static atomic_t edev_no = ATOMIC_INIT(-1); + int ret, index; - if (!extcon_class) { - ret = create_extcon_class(); - if (ret < 0) - return ret; - } + ret = create_extcon_class(); + if (ret < 0) + return ret; if (!edev || !edev->supported_cable) return -EINVAL; - for (; edev->supported_cable[index] != EXTCON_NONE; index++); + for (index = 0; edev->supported_cable[index] != EXTCON_NONE; index++); edev->max_supported = index; if (index > SUPPORTED_CABLE_MAX) { @@ -1115,124 +1273,26 @@ int extcon_dev_register(struct extcon_dev *edev) "extcon device name is null\n"); return -EINVAL; } - dev_set_name(&edev->dev, "extcon%lu", - (unsigned long)atomic_inc_return(&edev_no)); - - if (edev->max_supported) { - char *str; - struct extcon_cable *cable; - - edev->cables = kcalloc(edev->max_supported, - sizeof(struct extcon_cable), - GFP_KERNEL); - if (!edev->cables) { - ret = -ENOMEM; - goto err_sysfs_alloc; - } - for (index = 0; index < edev->max_supported; index++) { - cable = &edev->cables[index]; - - str = kasprintf(GFP_KERNEL, "cable.%d", index); - if (!str) { - for (index--; index >= 0; index--) { - cable = &edev->cables[index]; - kfree(cable->attr_g.name); - } - ret = -ENOMEM; - - goto err_alloc_cables; - } - - cable->edev = edev; - cable->cable_index = index; - cable->attrs[0] = &cable->attr_name.attr; - cable->attrs[1] = &cable->attr_state.attr; - cable->attrs[2] = NULL; - cable->attr_g.name = str; - cable->attr_g.attrs = cable->attrs; - - sysfs_attr_init(&cable->attr_name.attr); - cable->attr_name.attr.name = "name"; - cable->attr_name.attr.mode = 0444; - cable->attr_name.show = cable_name_show; - - sysfs_attr_init(&cable->attr_state.attr); - cable->attr_state.attr.name = "state"; - cable->attr_state.attr.mode = 0444; - cable->attr_state.show = cable_state_show; - } - } - if (edev->max_supported && edev->mutually_exclusive) { - char *name; - - /* Count the size of mutually_exclusive array */ - for (index = 0; edev->mutually_exclusive[index]; index++) - ; - - edev->attrs_muex = kcalloc(index + 1, - sizeof(struct attribute *), - GFP_KERNEL); - if (!edev->attrs_muex) { - ret = -ENOMEM; - goto err_muex; - } - - edev->d_attrs_muex = kcalloc(index, - sizeof(struct device_attribute), - GFP_KERNEL); - if (!edev->d_attrs_muex) { - ret = -ENOMEM; - kfree(edev->attrs_muex); - goto err_muex; - } - - for (index = 0; edev->mutually_exclusive[index]; index++) { - name = kasprintf(GFP_KERNEL, "0x%x", - edev->mutually_exclusive[index]); - if (!name) { - for (index--; index >= 0; index--) { - kfree(edev->d_attrs_muex[index].attr. - name); - } - kfree(edev->d_attrs_muex); - kfree(edev->attrs_muex); - ret = -ENOMEM; - goto err_muex; - } - sysfs_attr_init(&edev->d_attrs_muex[index].attr); - edev->d_attrs_muex[index].attr.name = name; - edev->d_attrs_muex[index].attr.mode = 0000; - edev->attrs_muex[index] = &edev->d_attrs_muex[index] - .attr; - } - edev->attr_g_muex.name = muex_name; - edev->attr_g_muex.attrs = edev->attrs_muex; + ret = ida_alloc(&extcon_dev_ids, GFP_KERNEL); + if (ret < 0) + return ret; - } + edev->id = ret; - if (edev->max_supported) { - edev->extcon_dev_type.groups = - kcalloc(edev->max_supported + 2, - sizeof(struct attribute_group *), - GFP_KERNEL); - if (!edev->extcon_dev_type.groups) { - ret = -ENOMEM; - goto err_alloc_groups; - } + dev_set_name(&edev->dev, "extcon%d", edev->id); - edev->extcon_dev_type.name = dev_name(&edev->dev); - edev->extcon_dev_type.release = dummy_sysfs_dev_release; + ret = extcon_alloc_cables(edev); + if (ret < 0) + goto err_alloc_cables; - for (index = 0; index < edev->max_supported; index++) - edev->extcon_dev_type.groups[index] = - &edev->cables[index].attr_g; - if (edev->mutually_exclusive) - edev->extcon_dev_type.groups[index] = - &edev->attr_g_muex; + ret = extcon_alloc_muex(edev); + if (ret < 0) + goto err_alloc_muex; - edev->dev.type = &edev->extcon_dev_type; - } + ret = extcon_alloc_groups(edev); + if (ret < 0) + goto err_alloc_groups; spin_lock_init(&edev->lock); if (edev->max_supported) { @@ -1277,13 +1337,14 @@ int extcon_dev_register(struct extcon_dev *edev) kfree(edev->d_attrs_muex); kfree(edev->attrs_muex); } -err_muex: +err_alloc_muex: for (index = 0; index < edev->max_supported; index++) kfree(edev->cables[index].attr_g.name); -err_alloc_cables: if (edev->max_supported) kfree(edev->cables); -err_sysfs_alloc: +err_alloc_cables: + ida_free(&extcon_dev_ids, edev->id); + return ret; } EXPORT_SYMBOL_GPL(extcon_dev_register); @@ -1306,12 +1367,13 @@ void extcon_dev_unregister(struct extcon_dev *edev) list_del(&edev->entry); mutex_unlock(&extcon_dev_list_lock); - if (IS_ERR_OR_NULL(get_device(&edev->dev))) { - dev_err(&edev->dev, "Failed to unregister extcon_dev (%s)\n", - dev_name(&edev->dev)); + if (!get_device(&edev->dev)) { + dev_err(&edev->dev, "Failed to unregister extcon_dev\n"); return; } + ida_free(&extcon_dev_ids, edev->id); + device_unregister(&edev->dev); if (edev->mutually_exclusive && edev->max_supported) { @@ -1349,7 +1411,7 @@ struct extcon_dev *extcon_find_edev_by_node(struct device_node *node) mutex_lock(&extcon_dev_list_lock); list_for_each_entry(edev, &extcon_dev_list, entry) - if (edev->dev.parent && edev->dev.parent->of_node == node) + if (edev->dev.parent && device_match_of_node(edev->dev.parent, node)) goto out; edev = ERR_PTR(-EPROBE_DEFER); out: @@ -1367,21 +1429,17 @@ struct extcon_dev *extcon_find_edev_by_node(struct device_node *node) */ struct extcon_dev *extcon_get_edev_by_phandle(struct device *dev, int index) { - struct device_node *node; + struct device_node *node, *np = dev_of_node(dev); struct extcon_dev *edev; - if (!dev) - return ERR_PTR(-EINVAL); - - if (!dev->of_node) { + if (!np) { dev_dbg(dev, "device does not have a device node entry\n"); return ERR_PTR(-EINVAL); } - node = of_parse_phandle(dev->of_node, "extcon", index); + node = of_parse_phandle(np, "extcon", index); if (!node) { - dev_dbg(dev, "failed to get phandle in %pOF node\n", - dev->of_node); + dev_dbg(dev, "failed to get phandle in %pOF node\n", np); return ERR_PTR(-ENODEV); } diff --git a/drivers/extcon/extcon.h b/drivers/extcon/extcon.h index 93b5e0306966d50bb1e582ff3bb5049a0ad6f8f4..94618268778603bf66a8330a26f536214cc35311 100644 --- a/drivers/extcon/extcon.h +++ b/drivers/extcon/extcon.h @@ -13,13 +13,14 @@ * are disabled. * @mutually_exclusive: Array of mutually exclusive set of cables that cannot * be attached simultaneously. The array should be - * ending with NULL or be NULL (no mutually exclusive - * cables). For example, if it is { 0x7, 0x30, 0}, then, + * ending with 0 or be NULL (no mutually exclusive cables). + * For example, if it is {0x7, 0x30, 0}, then, * {0, 1}, {0, 1, 2}, {0, 2}, {1, 2}, or {4, 5} cannot * be attached simulataneously. {0x7, 0} is equivalent to * {0x3, 0x6, 0x5, 0}. If it is {0xFFFFFFFF, 0}, there * can be no simultaneous connections. * @dev: Device of this extcon. + * @id: Unique device ID of this extcon. * @state: Attach/detach state of this extcon. Do not provide at * register-time. * @nh_all: Notifier for the state change events for all supported @@ -27,7 +28,7 @@ * @nh: Notifier for the state change events from this extcon * @entry: To support list of extcon devices so that users can * search for extcon devices based on the extcon name. - * @lock: + * @lock: Protects device state and serialises device registration * @max_supported: Internal value to store the number of cables. * @extcon_dev_type: Device_type struct to provide attribute_groups * customized for each extcon device. @@ -46,6 +47,7 @@ struct extcon_dev { /* Internal data. Please do not set. */ struct device dev; + unsigned int id; struct raw_notifier_head nh_all; struct raw_notifier_head *nh; struct list_head entry; diff --git a/drivers/firewire/.kunitconfig b/drivers/firewire/.kunitconfig new file mode 100644 index 0000000000000000000000000000000000000000..1599e069395fc1abefbee6db34117fb0aeec5a1e --- /dev/null +++ b/drivers/firewire/.kunitconfig @@ -0,0 +1,4 @@ +CONFIG_KUNIT=y +CONFIG_PCI=y +CONFIG_FIREWIRE=y +CONFIG_FIREWIRE_KUNIT_UAPI_TEST=y diff --git a/drivers/firewire/Kconfig b/drivers/firewire/Kconfig index ec00a6f70da8100d2d733ea81afc2d07f9b7cf44..0a6596b027db9ab10a082a2b9bab59603dcaf150 100644 --- a/drivers/firewire/Kconfig +++ b/drivers/firewire/Kconfig @@ -18,6 +18,22 @@ config FIREWIRE To compile this driver as a module, say M here: the module will be called firewire-core. +config FIREWIRE_KUNIT_UAPI_TEST + tristate "KUnit tests for layout of structure in UAPI" if !KUNIT_ALL_TESTS + depends on FIREWIRE && KUNIT + default KUNIT_ALL_TESTS + help + This builds the KUnit tests whether structures exposed to user + space have expected layout. + + KUnit tests run during boot and output the results to the debug + log in TAP format (https://testanything.org/). Only useful for + kernel devs running KUnit test harness and are not for inclusion + into a production build. + + For more information on KUnit and unit tests in general, refer + to the KUnit documentation in Documentation/dev-tools/kunit/. + config FIREWIRE_OHCI tristate "OHCI-1394 controllers" depends on PCI && FIREWIRE && MMU diff --git a/drivers/firewire/Makefile b/drivers/firewire/Makefile index e58c8c7947782f56dfcbac2b9afa3a86d664b98e..b24b2879ac34ff6fe3f5cfeb322fdf7824bf3fcd 100644 --- a/drivers/firewire/Makefile +++ b/drivers/firewire/Makefile @@ -15,3 +15,6 @@ obj-$(CONFIG_FIREWIRE_SBP2) += firewire-sbp2.o obj-$(CONFIG_FIREWIRE_NET) += firewire-net.o obj-$(CONFIG_FIREWIRE_NOSY) += nosy.o obj-$(CONFIG_PROVIDE_OHCI1394_DMA_INIT) += init_ohci1394_dma.o + +firewire-uapi-test-objs += uapi-test.o +obj-$(CONFIG_FIREWIRE_KUNIT_UAPI_TEST) += firewire-uapi-test.o diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c index 2c16ee8fd842d3bb89de458e1049e4ffbcea2cec..6274b86eb943774bc9ec9b362c7ef20f7461f1dd 100644 --- a/drivers/firewire/core-cdev.c +++ b/drivers/firewire/core-cdev.c @@ -43,6 +43,7 @@ #define FW_CDEV_VERSION_EVENT_REQUEST2 4 #define FW_CDEV_VERSION_ALLOCATE_REGION_END 4 #define FW_CDEV_VERSION_AUTO_FLUSH_ISO_OVERFLOW 5 +#define FW_CDEV_VERSION_EVENT_ASYNC_TSTAMP 6 struct client { u32 version; @@ -169,7 +170,10 @@ struct outbound_transaction_event { struct event event; struct client *client; struct outbound_transaction_resource r; - struct fw_cdev_event_response response; + union { + struct fw_cdev_event_response without_tstamp; + struct fw_cdev_event_response2 with_tstamp; + } rsp; }; struct inbound_transaction_event { @@ -177,6 +181,7 @@ struct inbound_transaction_event { union { struct fw_cdev_event_request request; struct fw_cdev_event_request2 request2; + struct fw_cdev_event_request3 with_tstamp; } req; }; @@ -199,12 +204,18 @@ struct outbound_phy_packet_event { struct event event; struct client *client; struct fw_packet p; - struct fw_cdev_event_phy_packet phy_packet; + union { + struct fw_cdev_event_phy_packet without_tstamp; + struct fw_cdev_event_phy_packet2 with_tstamp; + } phy_packet; }; struct inbound_phy_packet_event { struct event event; - struct fw_cdev_event_phy_packet phy_packet; + union { + struct fw_cdev_event_phy_packet without_tstamp; + struct fw_cdev_event_phy_packet2 with_tstamp; + } phy_packet; }; #ifdef CONFIG_COMPAT @@ -534,41 +545,64 @@ static void release_transaction(struct client *client, { } -static void complete_transaction(struct fw_card *card, int rcode, - void *payload, size_t length, void *data) +static void complete_transaction(struct fw_card *card, int rcode, u32 request_tstamp, + u32 response_tstamp, void *payload, size_t length, void *data) { struct outbound_transaction_event *e = data; - struct fw_cdev_event_response *rsp = &e->response; struct client *client = e->client; unsigned long flags; - if (length < rsp->length) - rsp->length = length; - if (rcode == RCODE_COMPLETE) - memcpy(rsp->data, payload, rsp->length); - spin_lock_irqsave(&client->lock, flags); idr_remove(&client->resource_idr, e->r.resource.handle); if (client->in_shutdown) wake_up(&client->tx_flush_wait); spin_unlock_irqrestore(&client->lock, flags); - rsp->type = FW_CDEV_EVENT_RESPONSE; - rsp->rcode = rcode; + switch (e->rsp.without_tstamp.type) { + case FW_CDEV_EVENT_RESPONSE: + { + struct fw_cdev_event_response *rsp = &e->rsp.without_tstamp; + + if (length < rsp->length) + rsp->length = length; + if (rcode == RCODE_COMPLETE) + memcpy(rsp->data, payload, rsp->length); + + rsp->rcode = rcode; + + // In the case that sizeof(*rsp) doesn't align with the position of the + // data, and the read is short, preserve an extra copy of the data + // to stay compatible with a pre-2.6.27 bug. Since the bug is harmless + // for short reads and some apps depended on it, this is both safe + // and prudent for compatibility. + if (rsp->length <= sizeof(*rsp) - offsetof(typeof(*rsp), data)) + queue_event(client, &e->event, rsp, sizeof(*rsp), rsp->data, rsp->length); + else + queue_event(client, &e->event, rsp, sizeof(*rsp) + rsp->length, NULL, 0); - /* - * In the case that sizeof(*rsp) doesn't align with the position of the - * data, and the read is short, preserve an extra copy of the data - * to stay compatible with a pre-2.6.27 bug. Since the bug is harmless - * for short reads and some apps depended on it, this is both safe - * and prudent for compatibility. - */ - if (rsp->length <= sizeof(*rsp) - offsetof(typeof(*rsp), data)) - queue_event(client, &e->event, rsp, sizeof(*rsp), - rsp->data, rsp->length); - else - queue_event(client, &e->event, rsp, sizeof(*rsp) + rsp->length, - NULL, 0); + break; + } + case FW_CDEV_EVENT_RESPONSE2: + { + struct fw_cdev_event_response2 *rsp = &e->rsp.with_tstamp; + + if (length < rsp->length) + rsp->length = length; + if (rcode == RCODE_COMPLETE) + memcpy(rsp->data, payload, rsp->length); + + rsp->rcode = rcode; + rsp->request_tstamp = request_tstamp; + rsp->response_tstamp = response_tstamp; + + queue_event(client, &e->event, rsp, sizeof(*rsp) + rsp->length, NULL, 0); + + break; + default: + WARN_ON(1); + break; + } + } /* Drop the idr's reference */ client_put(client); @@ -579,6 +613,7 @@ static int init_request(struct client *client, int destination_id, int speed) { struct outbound_transaction_event *e; + void *payload; int ret; if (request->tcode != TCODE_STREAM_DATA && @@ -592,14 +627,25 @@ static int init_request(struct client *client, e = kmalloc(sizeof(*e) + request->length, GFP_KERNEL); if (e == NULL) return -ENOMEM; - e->client = client; - e->response.length = request->length; - e->response.closure = request->closure; - if (request->data && - copy_from_user(e->response.data, - u64_to_uptr(request->data), request->length)) { + if (client->version < FW_CDEV_VERSION_EVENT_ASYNC_TSTAMP) { + struct fw_cdev_event_response *rsp = &e->rsp.without_tstamp; + + rsp->type = FW_CDEV_EVENT_RESPONSE; + rsp->length = request->length; + rsp->closure = request->closure; + payload = rsp->data; + } else { + struct fw_cdev_event_response2 *rsp = &e->rsp.with_tstamp; + + rsp->type = FW_CDEV_EVENT_RESPONSE2; + rsp->length = request->length; + rsp->closure = request->closure; + payload = rsp->data; + } + + if (request->data && copy_from_user(payload, u64_to_uptr(request->data), request->length)) { ret = -EFAULT; goto failed; } @@ -609,10 +655,9 @@ static int init_request(struct client *client, if (ret < 0) goto failed; - fw_send_request(client->device->card, &e->r.transaction, - request->tcode, destination_id, request->generation, - speed, request->offset, e->response.data, - request->length, complete_transaction, e); + fw_send_request_with_tstamp(client->device->card, &e->r.transaction, request->tcode, + destination_id, request->generation, speed, request->offset, + payload, request->length, complete_transaction, e); return 0; failed: @@ -708,7 +753,7 @@ static void handle_request(struct fw_card *card, struct fw_request *request, req->handle = r->resource.handle; req->closure = handler->closure; event_size0 = sizeof(*req); - } else { + } else if (handler->client->version < FW_CDEV_VERSION_EVENT_ASYNC_TSTAMP) { struct fw_cdev_event_request2 *req = &e->req.request2; req->type = FW_CDEV_EVENT_REQUEST2; @@ -722,6 +767,21 @@ static void handle_request(struct fw_card *card, struct fw_request *request, req->handle = r->resource.handle; req->closure = handler->closure; event_size0 = sizeof(*req); + } else { + struct fw_cdev_event_request3 *req = &e->req.with_tstamp; + + req->type = FW_CDEV_EVENT_REQUEST3; + req->tcode = tcode; + req->offset = offset; + req->source_node_id = source; + req->destination_node_id = destination; + req->card = card->index; + req->generation = generation; + req->length = length; + req->handle = r->resource.handle; + req->closure = handler->closure; + req->tstamp = fw_request_get_timestamp(request); + event_size0 = sizeof(*req); } queue_event(handler->client, &e->event, @@ -1495,26 +1555,61 @@ static void outbound_phy_packet_callback(struct fw_packet *packet, { struct outbound_phy_packet_event *e = container_of(packet, struct outbound_phy_packet_event, p); - struct client *e_client; + struct client *e_client = e->client; + u32 rcode; switch (status) { - /* expected: */ - case ACK_COMPLETE: e->phy_packet.rcode = RCODE_COMPLETE; break; - /* should never happen with PHY packets: */ - case ACK_PENDING: e->phy_packet.rcode = RCODE_COMPLETE; break; + // expected: + case ACK_COMPLETE: + rcode = RCODE_COMPLETE; + break; + // should never happen with PHY packets: + case ACK_PENDING: + rcode = RCODE_COMPLETE; + break; case ACK_BUSY_X: case ACK_BUSY_A: - case ACK_BUSY_B: e->phy_packet.rcode = RCODE_BUSY; break; - case ACK_DATA_ERROR: e->phy_packet.rcode = RCODE_DATA_ERROR; break; - case ACK_TYPE_ERROR: e->phy_packet.rcode = RCODE_TYPE_ERROR; break; - /* stale generation; cancelled; on certain controllers: no ack */ - default: e->phy_packet.rcode = status; break; + case ACK_BUSY_B: + rcode = RCODE_BUSY; + break; + case ACK_DATA_ERROR: + rcode = RCODE_DATA_ERROR; + break; + case ACK_TYPE_ERROR: + rcode = RCODE_TYPE_ERROR; + break; + // stale generation; cancelled; on certain controllers: no ack + default: + rcode = status; + break; + } + + switch (e->phy_packet.without_tstamp.type) { + case FW_CDEV_EVENT_PHY_PACKET_SENT: + { + struct fw_cdev_event_phy_packet *pp = &e->phy_packet.without_tstamp; + + pp->rcode = rcode; + pp->data[0] = packet->timestamp; + queue_event(e->client, &e->event, &e->phy_packet, sizeof(*pp) + pp->length, + NULL, 0); + break; + } + case FW_CDEV_EVENT_PHY_PACKET_SENT2: + { + struct fw_cdev_event_phy_packet2 *pp = &e->phy_packet.with_tstamp; + + pp->rcode = rcode; + pp->tstamp = packet->timestamp; + queue_event(e->client, &e->event, &e->phy_packet, sizeof(*pp) + pp->length, + NULL, 0); + break; + } + default: + WARN_ON(1); + break; } - e->phy_packet.data[0] = packet->timestamp; - e_client = e->client; - queue_event(e->client, &e->event, &e->phy_packet, - sizeof(e->phy_packet) + e->phy_packet.length, NULL, 0); client_put(e_client); } @@ -1528,7 +1623,7 @@ static int ioctl_send_phy_packet(struct client *client, union ioctl_arg *arg) if (!client->device->is_local) return -ENOSYS; - e = kzalloc(sizeof(*e) + 4, GFP_KERNEL); + e = kzalloc(sizeof(*e) + sizeof(a->data), GFP_KERNEL); if (e == NULL) return -ENOMEM; @@ -1541,10 +1636,24 @@ static int ioctl_send_phy_packet(struct client *client, union ioctl_arg *arg) e->p.header[2] = a->data[1]; e->p.header_length = 12; e->p.callback = outbound_phy_packet_callback; - e->phy_packet.closure = a->closure; - e->phy_packet.type = FW_CDEV_EVENT_PHY_PACKET_SENT; - if (is_ping_packet(a->data)) - e->phy_packet.length = 4; + + if (client->version < FW_CDEV_VERSION_EVENT_ASYNC_TSTAMP) { + struct fw_cdev_event_phy_packet *pp = &e->phy_packet.without_tstamp; + + pp->closure = a->closure; + pp->type = FW_CDEV_EVENT_PHY_PACKET_SENT; + if (is_ping_packet(a->data)) + pp->length = 4; + } else { + struct fw_cdev_event_phy_packet2 *pp = &e->phy_packet.with_tstamp; + + pp->closure = a->closure; + pp->type = FW_CDEV_EVENT_PHY_PACKET_SENT2; + // Keep the data field so that application can match the response event to the + // request. + pp->length = sizeof(a->data); + memcpy(pp->data, a->data, sizeof(a->data)); + } card->driver->send_request(card, &e->p); @@ -1583,14 +1692,29 @@ void fw_cdev_handle_phy_packet(struct fw_card *card, struct fw_packet *p) if (e == NULL) break; - e->phy_packet.closure = client->phy_receiver_closure; - e->phy_packet.type = FW_CDEV_EVENT_PHY_PACKET_RECEIVED; - e->phy_packet.rcode = RCODE_COMPLETE; - e->phy_packet.length = 8; - e->phy_packet.data[0] = p->header[1]; - e->phy_packet.data[1] = p->header[2]; - queue_event(client, &e->event, - &e->phy_packet, sizeof(e->phy_packet) + 8, NULL, 0); + if (client->version < FW_CDEV_VERSION_EVENT_ASYNC_TSTAMP) { + struct fw_cdev_event_phy_packet *pp = &e->phy_packet.without_tstamp; + + pp->closure = client->phy_receiver_closure; + pp->type = FW_CDEV_EVENT_PHY_PACKET_RECEIVED; + pp->rcode = RCODE_COMPLETE; + pp->length = 8; + pp->data[0] = p->header[1]; + pp->data[1] = p->header[2]; + queue_event(client, &e->event, &e->phy_packet, sizeof(*pp) + 8, NULL, 0); + } else { + struct fw_cdev_event_phy_packet2 *pp = &e->phy_packet.with_tstamp; + + pp = &e->phy_packet.with_tstamp; + pp->closure = client->phy_receiver_closure; + pp->type = FW_CDEV_EVENT_PHY_PACKET_RECEIVED2; + pp->rcode = RCODE_COMPLETE; + pp->length = 8; + pp->tstamp = p->timestamp; + pp->data[0] = p->header[1]; + pp->data[1] = p->header[2]; + queue_event(client, &e->event, &e->phy_packet, sizeof(*pp) + 8, NULL, 0); + } } spin_unlock_irqrestore(&card->lock, flags); diff --git a/drivers/firewire/core-device.c b/drivers/firewire/core-device.c index aa597cda0d88741334c68bf1f9f23fcf8e43c292..a3104e35412c150b65fb5e9c213893ad34e37e5c 100644 --- a/drivers/firewire/core-device.c +++ b/drivers/firewire/core-device.c @@ -1211,7 +1211,7 @@ void fw_node_event(struct fw_card *card, struct fw_node *node, int event) * without actually having a link. */ create: - device = kzalloc(sizeof(*device), GFP_ATOMIC); + device = kzalloc(sizeof(*device), GFP_KERNEL); if (device == NULL) break; diff --git a/drivers/firewire/core-topology.c b/drivers/firewire/core-topology.c index f40c81534381219b1d968a4351391eb27ca02758..88466b663482f1a867c51fd103772fc06296cc27 100644 --- a/drivers/firewire/core-topology.c +++ b/drivers/firewire/core-topology.c @@ -101,7 +101,7 @@ static struct fw_node *fw_node_create(u32 sid, int port_count, int color) { struct fw_node *node; - node = kzalloc(struct_size(node, ports, port_count), GFP_ATOMIC); + node = kzalloc(struct_size(node, ports, port_count), GFP_KERNEL); if (node == NULL) return NULL; diff --git a/drivers/firewire/core-transaction.c b/drivers/firewire/core-transaction.c index a9f70c96323e6a3eb677d38fd01fe9ee6c1f7cb4..130b95aca629022d183461a0ec215c14366678c4 100644 --- a/drivers/firewire/core-transaction.c +++ b/drivers/firewire/core-transaction.c @@ -70,8 +70,8 @@ static int try_cancel_split_timeout(struct fw_transaction *t) return 1; } -static int close_transaction(struct fw_transaction *transaction, - struct fw_card *card, int rcode) +static int close_transaction(struct fw_transaction *transaction, struct fw_card *card, int rcode, + u32 response_tstamp) { struct fw_transaction *t = NULL, *iter; unsigned long flags; @@ -92,7 +92,12 @@ static int close_transaction(struct fw_transaction *transaction, spin_unlock_irqrestore(&card->lock, flags); if (t) { - t->callback(card, rcode, NULL, 0, t->callback_data); + if (!t->with_tstamp) { + t->callback.without_tstamp(card, rcode, NULL, 0, t->callback_data); + } else { + t->callback.with_tstamp(card, rcode, t->packet.timestamp, response_tstamp, + NULL, 0, t->callback_data); + } return 0; } @@ -107,6 +112,8 @@ static int close_transaction(struct fw_transaction *transaction, int fw_cancel_transaction(struct fw_card *card, struct fw_transaction *transaction) { + u32 tstamp; + /* * Cancel the packet transmission if it's still queued. That * will call the packet transmission callback which cancels @@ -121,7 +128,17 @@ int fw_cancel_transaction(struct fw_card *card, * if the transaction is still pending and remove it in that case. */ - return close_transaction(transaction, card, RCODE_CANCELLED); + if (transaction->packet.ack == 0) { + // The timestamp is reused since it was just read now. + tstamp = transaction->packet.timestamp; + } else { + u32 curr_cycle_time = 0; + + (void)fw_card_read_cycle_time(card, &curr_cycle_time); + tstamp = cycle_time_to_ohci_tstamp(curr_cycle_time); + } + + return close_transaction(transaction, card, RCODE_CANCELLED, tstamp); } EXPORT_SYMBOL(fw_cancel_transaction); @@ -140,7 +157,12 @@ static void split_transaction_timeout_callback(struct timer_list *timer) card->tlabel_mask &= ~(1ULL << t->tlabel); spin_unlock_irqrestore(&card->lock, flags); - t->callback(card, RCODE_CANCELLED, NULL, 0, t->callback_data); + if (!t->with_tstamp) { + t->callback.without_tstamp(card, RCODE_CANCELLED, NULL, 0, t->callback_data); + } else { + t->callback.with_tstamp(card, RCODE_CANCELLED, t->packet.timestamp, + t->split_timeout_cycle, NULL, 0, t->callback_data); + } } static void start_split_transaction_timeout(struct fw_transaction *t, @@ -162,6 +184,8 @@ static void start_split_transaction_timeout(struct fw_transaction *t, spin_unlock_irqrestore(&card->lock, flags); } +static u32 compute_split_timeout_timestamp(struct fw_card *card, u32 request_timestamp); + static void transmit_complete_callback(struct fw_packet *packet, struct fw_card *card, int status) { @@ -170,28 +194,32 @@ static void transmit_complete_callback(struct fw_packet *packet, switch (status) { case ACK_COMPLETE: - close_transaction(t, card, RCODE_COMPLETE); + close_transaction(t, card, RCODE_COMPLETE, packet->timestamp); break; case ACK_PENDING: + { + t->split_timeout_cycle = + compute_split_timeout_timestamp(card, packet->timestamp) & 0xffff; start_split_transaction_timeout(t, card); break; + } case ACK_BUSY_X: case ACK_BUSY_A: case ACK_BUSY_B: - close_transaction(t, card, RCODE_BUSY); + close_transaction(t, card, RCODE_BUSY, packet->timestamp); break; case ACK_DATA_ERROR: - close_transaction(t, card, RCODE_DATA_ERROR); + close_transaction(t, card, RCODE_DATA_ERROR, packet->timestamp); break; case ACK_TYPE_ERROR: - close_transaction(t, card, RCODE_TYPE_ERROR); + close_transaction(t, card, RCODE_TYPE_ERROR, packet->timestamp); break; default: /* * In this case the ack is really a juju specific * rcode, so just forward that to the callback. */ - close_transaction(t, card, status); + close_transaction(t, card, status, packet->timestamp); break; } } @@ -288,7 +316,8 @@ static int allocate_tlabel(struct fw_card *card) } /** - * fw_send_request() - submit a request packet for transmission + * __fw_send_request() - submit a request packet for transmission to generate callback for response + * subaction with or without time stamp. * @card: interface to send the request at * @t: transaction instance to which the request belongs * @tcode: transaction code @@ -298,7 +327,9 @@ static int allocate_tlabel(struct fw_card *card) * @offset: 48bit wide offset into destination's address space * @payload: data payload for the request subaction * @length: length of the payload, in bytes - * @callback: function to be called when the transaction is completed + * @callback: union of two functions whether to receive time stamp or not for response + * subaction. + * @with_tstamp: Whether to receive time stamp or not for response subaction. * @callback_data: data to be passed to the transaction completion callback * * Submit a request packet into the asynchronous request transmission queue. @@ -335,10 +366,10 @@ static int allocate_tlabel(struct fw_card *card) * transaction completion and hence execution of @callback may happen even * before fw_send_request() returns. */ -void fw_send_request(struct fw_card *card, struct fw_transaction *t, int tcode, - int destination_id, int generation, int speed, - unsigned long long offset, void *payload, size_t length, - fw_transaction_callback_t callback, void *callback_data) +void __fw_send_request(struct fw_card *card, struct fw_transaction *t, int tcode, + int destination_id, int generation, int speed, unsigned long long offset, + void *payload, size_t length, union fw_transaction_callback callback, + bool with_tstamp, void *callback_data) { unsigned long flags; int tlabel; @@ -353,7 +384,19 @@ void fw_send_request(struct fw_card *card, struct fw_transaction *t, int tcode, tlabel = allocate_tlabel(card); if (tlabel < 0) { spin_unlock_irqrestore(&card->lock, flags); - callback(card, RCODE_SEND_ERROR, NULL, 0, callback_data); + if (!with_tstamp) { + callback.without_tstamp(card, RCODE_SEND_ERROR, NULL, 0, callback_data); + } else { + // Timestamping on behalf of hardware. + u32 curr_cycle_time = 0; + u32 tstamp; + + (void)fw_card_read_cycle_time(card, &curr_cycle_time); + tstamp = cycle_time_to_ohci_tstamp(curr_cycle_time); + + callback.with_tstamp(card, RCODE_SEND_ERROR, tstamp, tstamp, NULL, 0, + callback_data); + } return; } @@ -361,13 +404,12 @@ void fw_send_request(struct fw_card *card, struct fw_transaction *t, int tcode, t->tlabel = tlabel; t->card = card; t->is_split_transaction = false; - timer_setup(&t->split_timeout_timer, - split_transaction_timeout_callback, 0); + timer_setup(&t->split_timeout_timer, split_transaction_timeout_callback, 0); t->callback = callback; + t->with_tstamp = with_tstamp; t->callback_data = callback_data; - fw_fill_request(&t->packet, tcode, t->tlabel, - destination_id, card->node_id, generation, + fw_fill_request(&t->packet, tcode, t->tlabel, destination_id, card->node_id, generation, speed, offset, payload, length); t->packet.callback = transmit_complete_callback; @@ -377,7 +419,7 @@ void fw_send_request(struct fw_card *card, struct fw_transaction *t, int tcode, card->driver->send_request(card, &t->packet); } -EXPORT_SYMBOL(fw_send_request); +EXPORT_SYMBOL_GPL(__fw_send_request); struct transaction_callback_data { struct completion done; @@ -1047,7 +1089,12 @@ void fw_core_handle_response(struct fw_card *card, struct fw_packet *p) */ card->driver->cancel_packet(card, &t->packet); - t->callback(card, rcode, data, data_length, t->callback_data); + if (!t->with_tstamp) { + t->callback.without_tstamp(card, rcode, data, data_length, t->callback_data); + } else { + t->callback.with_tstamp(card, rcode, t->packet.timestamp, p->timestamp, data, + data_length, t->callback_data); + } } EXPORT_SYMBOL(fw_core_handle_response); diff --git a/drivers/firewire/core.h b/drivers/firewire/core.h index eafa4eaae737ac76152ac138283824d4df60fb2f..2a05f411328fd45c81bd2a9e55c10370d504d40e 100644 --- a/drivers/firewire/core.h +++ b/drivers/firewire/core.h @@ -247,6 +247,13 @@ void fw_fill_response(struct fw_packet *response, u32 *request_header, void fw_request_get(struct fw_request *request); void fw_request_put(struct fw_request *request); +// Convert the value of IEEE 1394 CYCLE_TIME register to the format of timeStamp field in +// descriptors of 1394 OHCI. +static inline u32 cycle_time_to_ohci_tstamp(u32 tstamp) +{ + return (tstamp & 0x0ffff000) >> 12; +} + #define FW_PHY_CONFIG_NO_NODE_ID -1 #define FW_PHY_CONFIG_CURRENT_GAP_COUNT -1 void fw_send_phy_config(struct fw_card *card, diff --git a/drivers/firewire/net.c b/drivers/firewire/net.c index 538bd677c254a9a148b5d2772d56f16559db4f07..7a4d1a478e33e2ccace6bc5b2ef184113f335ca3 100644 --- a/drivers/firewire/net.c +++ b/drivers/firewire/net.c @@ -479,7 +479,7 @@ static int fwnet_finish_incoming_packet(struct net_device *net, struct sk_buff *skb, u16 source_node_id, bool is_broadcast, u16 ether_type) { - int status; + int status, len; switch (ether_type) { case ETH_P_ARP: @@ -533,13 +533,15 @@ static int fwnet_finish_incoming_packet(struct net_device *net, } skb->protocol = protocol; } + + len = skb->len; status = netif_rx(skb); if (status == NET_RX_DROP) { net->stats.rx_errors++; net->stats.rx_dropped++; } else { net->stats.rx_packets++; - net->stats.rx_bytes += skb->len; + net->stats.rx_bytes += len; } return 0; diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c index 17c9d825188bb4c7f622b39b4e466d40391fa5d3..7e88fd4897414be5cffb7c82def09fc3d7c2f453 100644 --- a/drivers/firewire/ohci.c +++ b/drivers/firewire/ohci.c @@ -677,6 +677,9 @@ static void ar_context_release(struct ar_context *ctx) struct device *dev = ctx->ohci->card.device; unsigned int i; + if (!ctx->buffer) + return; + vunmap(ctx->buffer); for (i = 0; i < AR_BUFFERS; i++) { @@ -1105,8 +1108,7 @@ static int context_add_buffer(struct context *ctx) if (ctx->total_allocation >= 16*1024*1024) return -ENOMEM; - desc = dma_alloc_coherent(ctx->ohci->card.device, PAGE_SIZE, - &bus_addr, GFP_ATOMIC); + desc = dmam_alloc_coherent(ctx->ohci->card.device, PAGE_SIZE, &bus_addr, GFP_ATOMIC); if (!desc) return -ENOMEM; @@ -1165,10 +1167,10 @@ static void context_release(struct context *ctx) struct fw_card *card = &ctx->ohci->card; struct descriptor_buffer *desc, *tmp; - list_for_each_entry_safe(desc, tmp, &ctx->buffer_list, list) - dma_free_coherent(card->device, PAGE_SIZE, desc, - desc->buffer_bus - - ((void *)&desc->buffer - (void *)desc)); + list_for_each_entry_safe(desc, tmp, &ctx->buffer_list, list) { + dmam_free_coherent(card->device, PAGE_SIZE, desc, + desc->buffer_bus - ((void *)&desc->buffer - (void *)desc)); + } } /* Must be called with ohci->lock held */ @@ -1623,6 +1625,8 @@ 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; @@ -1633,6 +1637,10 @@ static void at_context_transmit(struct context *ctx, struct fw_packet *packet) if (HEADER_GET_DESTINATION(packet->header[0]) == ctx->ohci->node_id && ctx->ohci->generation == packet->generation) { spin_unlock_irqrestore(&ctx->ohci->lock, flags); + + // Timestamping on behalf of the hardware. + packet->timestamp = cycle_time_to_ohci_tstamp(get_cycle_time(ctx->ohci)); + handle_local_request(ctx, packet); return; } @@ -1640,9 +1648,12 @@ static void at_context_transmit(struct context *ctx, struct fw_packet *packet) ret = at_context_queue_packet(ctx, packet); spin_unlock_irqrestore(&ctx->ohci->lock, flags); - if (ret < 0) - packet->callback(packet, &ctx->ohci->card, packet->ack); + if (ret < 0) { + // Timestamping on behalf of the hardware. + packet->timestamp = cycle_time_to_ohci_tstamp(get_cycle_time(ctx->ohci)); + packet->callback(packet, &ctx->ohci->card, packet->ack); + } } static void detect_dead_context(struct fw_ohci *ohci, @@ -2044,8 +2055,7 @@ static void bus_reset_work(struct work_struct *work) spin_unlock_irq(&ohci->lock); if (free_rom) - dma_free_coherent(ohci->card.device, CONFIG_ROM_SIZE, - free_rom, free_rom_bus); + dmam_free_coherent(ohci->card.device, CONFIG_ROM_SIZE, free_rom, free_rom_bus); log_selfids(ohci, generation, self_id_count); @@ -2377,10 +2387,8 @@ static int ohci_enable(struct fw_card *card, */ if (config_rom) { - ohci->next_config_rom = - dma_alloc_coherent(ohci->card.device, CONFIG_ROM_SIZE, - &ohci->next_config_rom_bus, - GFP_KERNEL); + ohci->next_config_rom = dmam_alloc_coherent(ohci->card.device, CONFIG_ROM_SIZE, + &ohci->next_config_rom_bus, GFP_KERNEL); if (ohci->next_config_rom == NULL) return -ENOMEM; @@ -2472,9 +2480,8 @@ static int ohci_set_config_rom(struct fw_card *card, * ohci->next_config_rom to NULL (see bus_reset_work). */ - next_config_rom = - dma_alloc_coherent(ohci->card.device, CONFIG_ROM_SIZE, - &next_config_rom_bus, GFP_KERNEL); + next_config_rom = dmam_alloc_coherent(ohci->card.device, CONFIG_ROM_SIZE, + &next_config_rom_bus, GFP_KERNEL); if (next_config_rom == NULL) return -ENOMEM; @@ -2507,9 +2514,10 @@ static int ohci_set_config_rom(struct fw_card *card, spin_unlock_irq(&ohci->lock); /* If we didn't use the DMA allocation, delete it. */ - if (next_config_rom != NULL) - dma_free_coherent(ohci->card.device, CONFIG_ROM_SIZE, - next_config_rom, next_config_rom_bus); + if (next_config_rom != NULL) { + dmam_free_coherent(ohci->card.device, CONFIG_ROM_SIZE, next_config_rom, + next_config_rom_bus); + } /* * Now initiate a bus reset to have the changes take @@ -2557,6 +2565,10 @@ static int ohci_cancel_packet(struct fw_card *card, struct fw_packet *packet) log_ar_at_event(ohci, 'T', packet->speed, packet->header, 0x20); driver_data->packet = NULL; packet->ack = RCODE_CANCELLED; + + // Timestamping on behalf of the hardware. + packet->timestamp = cycle_time_to_ohci_tstamp(get_cycle_time(ohci)); + packet->callback(packet, &ohci->card, packet->ack); ret = 0; out: @@ -3544,6 +3556,19 @@ static inline void pmac_ohci_on(struct pci_dev *dev) {} static inline void pmac_ohci_off(struct pci_dev *dev) {} #endif /* CONFIG_PPC_PMAC */ +static void release_ohci(struct device *dev, void *data) +{ + struct pci_dev *pdev = to_pci_dev(dev); + struct fw_ohci *ohci = pci_get_drvdata(pdev); + + pmac_ohci_off(pdev); + + ar_context_release(&ohci->ar_response_ctx); + ar_context_release(&ohci->ar_request_ctx); + + dev_notice(dev, "removed fw-ohci device\n"); +} + static int pci_probe(struct pci_dev *dev, const struct pci_device_id *ent) { @@ -3558,25 +3583,22 @@ static int pci_probe(struct pci_dev *dev, return -ENOSYS; } - ohci = kzalloc(sizeof(*ohci), GFP_KERNEL); - if (ohci == NULL) { - err = -ENOMEM; - goto fail; - } - + ohci = devres_alloc(release_ohci, sizeof(*ohci), GFP_KERNEL); + if (ohci == NULL) + return -ENOMEM; fw_card_initialize(&ohci->card, &ohci_driver, &dev->dev); - + pci_set_drvdata(dev, ohci); pmac_ohci_on(dev); + devres_add(&dev->dev, ohci); - err = pci_enable_device(dev); + err = pcim_enable_device(dev); if (err) { dev_err(&dev->dev, "failed to enable OHCI hardware\n"); - goto fail_free; + return err; } pci_set_master(dev); pci_write_config_dword(dev, OHCI1394_PCI_HCI_Control, 0); - pci_set_drvdata(dev, ohci); spin_lock_init(&ohci->lock); mutex_init(&ohci->phy_reg_mutex); @@ -3586,22 +3608,15 @@ static int pci_probe(struct pci_dev *dev, if (!(pci_resource_flags(dev, 0) & IORESOURCE_MEM) || pci_resource_len(dev, 0) < OHCI1394_REGISTER_SIZE) { ohci_err(ohci, "invalid MMIO resource\n"); - err = -ENXIO; - goto fail_disable; + return -ENXIO; } - err = pci_request_region(dev, 0, ohci_driver_name); + err = pcim_iomap_regions(dev, 1 << 0, ohci_driver_name); if (err) { - ohci_err(ohci, "MMIO resource unavailable\n"); - goto fail_disable; - } - - ohci->registers = pci_iomap(dev, 0, OHCI1394_REGISTER_SIZE); - if (ohci->registers == NULL) { - ohci_err(ohci, "failed to remap registers\n"); - err = -ENXIO; - goto fail_iomem; + ohci_err(ohci, "request and map MMIO resource unavailable\n"); + return -ENXIO; } + ohci->registers = pcim_iomap_table(dev)[0]; for (i = 0; i < ARRAY_SIZE(ohci_quirks); i++) if ((ohci_quirks[i].vendor == dev->vendor) && @@ -3622,34 +3637,30 @@ static int pci_probe(struct pci_dev *dev, */ BUILD_BUG_ON(AR_BUFFERS * sizeof(struct descriptor) > PAGE_SIZE/4); BUILD_BUG_ON(SELF_ID_BUF_SIZE > PAGE_SIZE/2); - ohci->misc_buffer = dma_alloc_coherent(ohci->card.device, - PAGE_SIZE, - &ohci->misc_buffer_bus, - GFP_KERNEL); - if (!ohci->misc_buffer) { - err = -ENOMEM; - goto fail_iounmap; - } + ohci->misc_buffer = dmam_alloc_coherent(&dev->dev, PAGE_SIZE, &ohci->misc_buffer_bus, + GFP_KERNEL); + if (!ohci->misc_buffer) + return -ENOMEM; err = ar_context_init(&ohci->ar_request_ctx, ohci, 0, OHCI1394_AsReqRcvContextControlSet); if (err < 0) - goto fail_misc_buf; + return err; err = ar_context_init(&ohci->ar_response_ctx, ohci, PAGE_SIZE/4, OHCI1394_AsRspRcvContextControlSet); if (err < 0) - goto fail_arreq_ctx; + return err; err = context_init(&ohci->at_request_ctx, ohci, OHCI1394_AsReqTrContextControlSet, handle_at_packet); if (err < 0) - goto fail_arrsp_ctx; + return err; err = context_init(&ohci->at_response_ctx, ohci, OHCI1394_AsRspTrContextControlSet, handle_at_packet); if (err < 0) - goto fail_atreq_ctx; + return err; reg_write(ohci, OHCI1394_IsoRecvIntMaskSet, ~0); ohci->ir_context_channels = ~0ULL; @@ -3658,7 +3669,9 @@ static int pci_probe(struct pci_dev *dev, ohci->ir_context_mask = ohci->ir_context_support; ohci->n_ir = hweight32(ohci->ir_context_mask); size = sizeof(struct iso_context) * ohci->n_ir; - ohci->ir_context_list = kzalloc(size, GFP_KERNEL); + ohci->ir_context_list = devm_kzalloc(&dev->dev, size, GFP_KERNEL); + if (!ohci->ir_context_list) + return -ENOMEM; reg_write(ohci, OHCI1394_IsoXmitIntMaskSet, ~0); ohci->it_context_support = reg_read(ohci, OHCI1394_IsoXmitIntMaskSet); @@ -3671,12 +3684,9 @@ static int pci_probe(struct pci_dev *dev, ohci->it_context_mask = ohci->it_context_support; ohci->n_it = hweight32(ohci->it_context_mask); size = sizeof(struct iso_context) * ohci->n_it; - ohci->it_context_list = kzalloc(size, GFP_KERNEL); - - if (ohci->it_context_list == NULL || ohci->ir_context_list == NULL) { - err = -ENOMEM; - goto fail_contexts; - } + ohci->it_context_list = devm_kzalloc(&dev->dev, size, GFP_KERNEL); + if (!ohci->it_context_list) + return -ENOMEM; ohci->self_id = ohci->misc_buffer + PAGE_SIZE/2; ohci->self_id_bus = ohci->misc_buffer_bus + PAGE_SIZE/2; @@ -3689,17 +3699,16 @@ static int pci_probe(struct pci_dev *dev, if (!(ohci->quirks & QUIRK_NO_MSI)) pci_enable_msi(dev); - if (request_irq(dev->irq, irq_handler, - pci_dev_msi_enabled(dev) ? 0 : IRQF_SHARED, - ohci_driver_name, ohci)) { + err = devm_request_irq(&dev->dev, dev->irq, irq_handler, + pci_dev_msi_enabled(dev) ? 0 : IRQF_SHARED, ohci_driver_name, ohci); + if (err < 0) { ohci_err(ohci, "failed to allocate interrupt %d\n", dev->irq); - err = -EIO; goto fail_msi; } err = fw_card_add(&ohci->card, max_receive, link_speed, guid); if (err) - goto fail_irq; + goto fail_msi; version = reg_read(ohci, OHCI1394_Version) & 0x00ff00ff; ohci_notice(ohci, @@ -3712,33 +3721,9 @@ static int pci_probe(struct pci_dev *dev, return 0; - fail_irq: - free_irq(dev->irq, ohci); fail_msi: pci_disable_msi(dev); - fail_contexts: - kfree(ohci->ir_context_list); - kfree(ohci->it_context_list); - context_release(&ohci->at_response_ctx); - fail_atreq_ctx: - context_release(&ohci->at_request_ctx); - fail_arrsp_ctx: - ar_context_release(&ohci->ar_response_ctx); - fail_arreq_ctx: - ar_context_release(&ohci->ar_request_ctx); - fail_misc_buf: - dma_free_coherent(ohci->card.device, PAGE_SIZE, - ohci->misc_buffer, ohci->misc_buffer_bus); - fail_iounmap: - pci_iounmap(dev, ohci->registers); - fail_iomem: - pci_release_region(dev, 0); - fail_disable: - pci_disable_device(dev); - fail_free: - kfree(ohci); - pmac_ohci_off(dev); - fail: + return err; } @@ -3763,30 +3748,10 @@ static void pci_remove(struct pci_dev *dev) */ software_reset(ohci); - free_irq(dev->irq, ohci); - - if (ohci->next_config_rom && ohci->next_config_rom != ohci->config_rom) - dma_free_coherent(ohci->card.device, CONFIG_ROM_SIZE, - ohci->next_config_rom, ohci->next_config_rom_bus); - if (ohci->config_rom) - dma_free_coherent(ohci->card.device, CONFIG_ROM_SIZE, - ohci->config_rom, ohci->config_rom_bus); - ar_context_release(&ohci->ar_request_ctx); - ar_context_release(&ohci->ar_response_ctx); - dma_free_coherent(ohci->card.device, PAGE_SIZE, - ohci->misc_buffer, ohci->misc_buffer_bus); - context_release(&ohci->at_request_ctx); - context_release(&ohci->at_response_ctx); - kfree(ohci->it_context_list); - kfree(ohci->ir_context_list); + pci_disable_msi(dev); - pci_iounmap(dev, ohci->registers); - pci_release_region(dev, 0); - pci_disable_device(dev); - kfree(ohci); - pmac_ohci_off(dev); - dev_notice(&dev->dev, "removed fw-ohci device\n"); + dev_notice(&dev->dev, "removing fw-ohci device\n"); } #ifdef CONFIG_PM diff --git a/drivers/firewire/uapi-test.c b/drivers/firewire/uapi-test.c new file mode 100644 index 0000000000000000000000000000000000000000..2fcbede4fab1f51a622df0511b9695fc9d400175 --- /dev/null +++ b/drivers/firewire/uapi-test.c @@ -0,0 +1,89 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// uapi_test.c - An application of Kunit to check layout of structures exposed to user space for +// FireWire subsystem. +// +// Copyright (c) 2023 Takashi Sakamoto + +#include +#include + +// Known issue added at v2.6.27 kernel. +static void structure_layout_event_response(struct kunit *test) +{ +#if defined(CONFIG_X86_32) + // 4 bytes alignment for aggregate type including 8 bytes storage types. + KUNIT_EXPECT_EQ(test, 20, sizeof(struct fw_cdev_event_response)); +#else + // 8 bytes alignment for aggregate type including 8 bytes storage types. + KUNIT_EXPECT_EQ(test, 24, sizeof(struct fw_cdev_event_response)); +#endif + + KUNIT_EXPECT_EQ(test, 0, offsetof(struct fw_cdev_event_response, closure)); + KUNIT_EXPECT_EQ(test, 8, offsetof(struct fw_cdev_event_response, type)); + KUNIT_EXPECT_EQ(test, 12, offsetof(struct fw_cdev_event_response, rcode)); + KUNIT_EXPECT_EQ(test, 16, offsetof(struct fw_cdev_event_response, length)); + KUNIT_EXPECT_EQ(test, 20, offsetof(struct fw_cdev_event_response, data)); +} + +// Added at v6.5. +static void structure_layout_event_request3(struct kunit *test) +{ + KUNIT_EXPECT_EQ(test, 56, sizeof(struct fw_cdev_event_request3)); + + KUNIT_EXPECT_EQ(test, 0, offsetof(struct fw_cdev_event_request3, closure)); + KUNIT_EXPECT_EQ(test, 8, offsetof(struct fw_cdev_event_request3, type)); + KUNIT_EXPECT_EQ(test, 12, offsetof(struct fw_cdev_event_request3, tcode)); + KUNIT_EXPECT_EQ(test, 16, offsetof(struct fw_cdev_event_request3, offset)); + KUNIT_EXPECT_EQ(test, 24, offsetof(struct fw_cdev_event_request3, source_node_id)); + KUNIT_EXPECT_EQ(test, 28, offsetof(struct fw_cdev_event_request3, destination_node_id)); + KUNIT_EXPECT_EQ(test, 32, offsetof(struct fw_cdev_event_request3, card)); + KUNIT_EXPECT_EQ(test, 36, offsetof(struct fw_cdev_event_request3, generation)); + KUNIT_EXPECT_EQ(test, 40, offsetof(struct fw_cdev_event_request3, handle)); + KUNIT_EXPECT_EQ(test, 44, offsetof(struct fw_cdev_event_request3, length)); + KUNIT_EXPECT_EQ(test, 48, offsetof(struct fw_cdev_event_request3, tstamp)); + KUNIT_EXPECT_EQ(test, 56, offsetof(struct fw_cdev_event_request3, data)); +} + +// Added at v6.5. +static void structure_layout_event_response2(struct kunit *test) +{ + KUNIT_EXPECT_EQ(test, 32, sizeof(struct fw_cdev_event_response2)); + + KUNIT_EXPECT_EQ(test, 0, offsetof(struct fw_cdev_event_response2, closure)); + KUNIT_EXPECT_EQ(test, 8, offsetof(struct fw_cdev_event_response2, type)); + KUNIT_EXPECT_EQ(test, 12, offsetof(struct fw_cdev_event_response2, rcode)); + KUNIT_EXPECT_EQ(test, 16, offsetof(struct fw_cdev_event_response2, length)); + KUNIT_EXPECT_EQ(test, 20, offsetof(struct fw_cdev_event_response2, request_tstamp)); + KUNIT_EXPECT_EQ(test, 24, offsetof(struct fw_cdev_event_response2, response_tstamp)); + KUNIT_EXPECT_EQ(test, 32, offsetof(struct fw_cdev_event_response2, data)); +} + +// Added at v6.5. +static void structure_layout_event_phy_packet2(struct kunit *test) +{ + KUNIT_EXPECT_EQ(test, 24, sizeof(struct fw_cdev_event_phy_packet2)); + + KUNIT_EXPECT_EQ(test, 0, offsetof(struct fw_cdev_event_phy_packet2, closure)); + KUNIT_EXPECT_EQ(test, 8, offsetof(struct fw_cdev_event_phy_packet2, type)); + KUNIT_EXPECT_EQ(test, 12, offsetof(struct fw_cdev_event_phy_packet2, rcode)); + KUNIT_EXPECT_EQ(test, 16, offsetof(struct fw_cdev_event_phy_packet2, length)); + KUNIT_EXPECT_EQ(test, 20, offsetof(struct fw_cdev_event_phy_packet2, tstamp)); + KUNIT_EXPECT_EQ(test, 24, offsetof(struct fw_cdev_event_phy_packet2, data)); +} + +static struct kunit_case structure_layout_test_cases[] = { + KUNIT_CASE(structure_layout_event_response), + KUNIT_CASE(structure_layout_event_request3), + KUNIT_CASE(structure_layout_event_response2), + KUNIT_CASE(structure_layout_event_phy_packet2), + {} +}; + +static struct kunit_suite structure_layout_test_suite = { + .name = "firewire-uapi-structure-layout", + .test_cases = structure_layout_test_cases, +}; +kunit_test_suite(structure_layout_test_suite); + +MODULE_LICENSE("GPL"); diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c index e7d97b59963b0ba989798ba9e31bb14458ad2871..b5957cc12fee669d43936d9c7e2173e9d7581f93 100644 --- a/drivers/firmware/arm_scmi/driver.c +++ b/drivers/firmware/arm_scmi/driver.c @@ -2914,6 +2914,7 @@ static const struct of_device_id scmi_of_match[] = { #endif #ifdef CONFIG_ARM_SCMI_TRANSPORT_SMC { .compatible = "arm,scmi-smc", .data = &scmi_smc_desc}, + { .compatible = "arm,scmi-smc-param", .data = &scmi_smc_desc}, #endif #ifdef CONFIG_ARM_SCMI_TRANSPORT_VIRTIO { .compatible = "arm,scmi-virtio", .data = &scmi_virtio_desc}, diff --git a/drivers/firmware/arm_scmi/powercap.c b/drivers/firmware/arm_scmi/powercap.c index 83b90bde755cad1e4dc3e0218c2c3759c96b8e43..244929cb4f3ee29b7d88a48372cc8d8219f44adf 100644 --- a/drivers/firmware/arm_scmi/powercap.c +++ b/drivers/firmware/arm_scmi/powercap.c @@ -108,6 +108,8 @@ struct scmi_powercap_meas_changed_notify_payld { }; struct scmi_powercap_state { + bool enabled; + u32 last_pcap; bool meas_notif_enabled; u64 thresholds; #define THRESH_LOW(p, id) \ @@ -313,24 +315,33 @@ static int scmi_powercap_xfer_cap_get(const struct scmi_protocol_handle *ph, return ret; } -static int scmi_powercap_cap_get(const struct scmi_protocol_handle *ph, - u32 domain_id, u32 *power_cap) +static int __scmi_powercap_cap_get(const struct scmi_protocol_handle *ph, + const struct scmi_powercap_info *dom, + u32 *power_cap) { - struct scmi_powercap_info *dom; - struct powercap_info *pi = ph->get_priv(ph); - - if (!power_cap || domain_id >= pi->num_domains) - return -EINVAL; - - dom = pi->powercaps + domain_id; if (dom->fc_info && dom->fc_info[POWERCAP_FC_CAP].get_addr) { *power_cap = ioread32(dom->fc_info[POWERCAP_FC_CAP].get_addr); trace_scmi_fc_call(SCMI_PROTOCOL_POWERCAP, POWERCAP_CAP_GET, - domain_id, *power_cap, 0); + dom->id, *power_cap, 0); return 0; } - return scmi_powercap_xfer_cap_get(ph, domain_id, power_cap); + return scmi_powercap_xfer_cap_get(ph, dom->id, power_cap); +} + +static int scmi_powercap_cap_get(const struct scmi_protocol_handle *ph, + u32 domain_id, u32 *power_cap) +{ + const struct scmi_powercap_info *dom; + + if (!power_cap) + return -EINVAL; + + dom = scmi_powercap_dom_info_get(ph, domain_id); + if (!dom) + return -EINVAL; + + return __scmi_powercap_cap_get(ph, dom, power_cap); } static int scmi_powercap_xfer_cap_set(const struct scmi_protocol_handle *ph, @@ -375,17 +386,20 @@ static int scmi_powercap_xfer_cap_set(const struct scmi_protocol_handle *ph, return ret; } -static int scmi_powercap_cap_set(const struct scmi_protocol_handle *ph, - u32 domain_id, u32 power_cap, - bool ignore_dresp) +static int __scmi_powercap_cap_set(const struct scmi_protocol_handle *ph, + struct powercap_info *pi, u32 domain_id, + u32 power_cap, bool ignore_dresp) { + int ret = -EINVAL; const struct scmi_powercap_info *pc; pc = scmi_powercap_dom_info_get(ph, domain_id); - if (!pc || !pc->powercap_cap_config || !power_cap || - power_cap < pc->min_power_cap || - power_cap > pc->max_power_cap) - return -EINVAL; + if (!pc || !pc->powercap_cap_config) + return ret; + + if (power_cap && + (power_cap < pc->min_power_cap || power_cap > pc->max_power_cap)) + return ret; if (pc->fc_info && pc->fc_info[POWERCAP_FC_CAP].set_addr) { struct scmi_fc_info *fci = &pc->fc_info[POWERCAP_FC_CAP]; @@ -394,10 +408,41 @@ static int scmi_powercap_cap_set(const struct scmi_protocol_handle *ph, ph->hops->fastchannel_db_ring(fci->set_db); trace_scmi_fc_call(SCMI_PROTOCOL_POWERCAP, POWERCAP_CAP_SET, domain_id, power_cap, 0); + ret = 0; + } else { + ret = scmi_powercap_xfer_cap_set(ph, pc, power_cap, + ignore_dresp); + } + + /* Save the last explicitly set non-zero powercap value */ + if (PROTOCOL_REV_MAJOR(pi->version) >= 0x2 && !ret && power_cap) + pi->states[domain_id].last_pcap = power_cap; + + return ret; +} + +static int scmi_powercap_cap_set(const struct scmi_protocol_handle *ph, + u32 domain_id, u32 power_cap, + bool ignore_dresp) +{ + struct powercap_info *pi = ph->get_priv(ph); + + /* + * Disallow zero as a possible explicitly requested powercap: + * there are enable/disable operations for this. + */ + if (!power_cap) + return -EINVAL; + + /* Just log the last set request if acting on a disabled domain */ + if (PROTOCOL_REV_MAJOR(pi->version) >= 0x2 && + !pi->states[domain_id].enabled) { + pi->states[domain_id].last_pcap = power_cap; return 0; } - return scmi_powercap_xfer_cap_set(ph, pc, power_cap, ignore_dresp); + return __scmi_powercap_cap_set(ph, pi, domain_id, + power_cap, ignore_dresp); } static int scmi_powercap_xfer_pai_get(const struct scmi_protocol_handle *ph, @@ -564,11 +609,78 @@ scmi_powercap_measurements_threshold_set(const struct scmi_protocol_handle *ph, return ret; } +static int scmi_powercap_cap_enable_set(const struct scmi_protocol_handle *ph, + u32 domain_id, bool enable) +{ + int ret; + u32 power_cap; + struct powercap_info *pi = ph->get_priv(ph); + + if (PROTOCOL_REV_MAJOR(pi->version) < 0x2) + return -EINVAL; + + if (enable == pi->states[domain_id].enabled) + return 0; + + if (enable) { + /* Cannot enable with a zero powercap. */ + if (!pi->states[domain_id].last_pcap) + return -EINVAL; + + ret = __scmi_powercap_cap_set(ph, pi, domain_id, + pi->states[domain_id].last_pcap, + true); + } else { + ret = __scmi_powercap_cap_set(ph, pi, domain_id, 0, true); + } + + if (ret) + return ret; + + /* + * Update our internal state to reflect final platform state: the SCMI + * server could have ignored a disable request and kept enforcing some + * powercap limit requested by other agents. + */ + ret = scmi_powercap_cap_get(ph, domain_id, &power_cap); + if (!ret) + pi->states[domain_id].enabled = !!power_cap; + + return ret; +} + +static int scmi_powercap_cap_enable_get(const struct scmi_protocol_handle *ph, + u32 domain_id, bool *enable) +{ + int ret; + u32 power_cap; + struct powercap_info *pi = ph->get_priv(ph); + + *enable = true; + if (PROTOCOL_REV_MAJOR(pi->version) < 0x2) + return 0; + + /* + * Report always real platform state; platform could have ignored + * a previous disable request. Default true on any error. + */ + ret = scmi_powercap_cap_get(ph, domain_id, &power_cap); + if (!ret) + *enable = !!power_cap; + + /* Update internal state with current real platform state */ + pi->states[domain_id].enabled = *enable; + + return 0; +} + static const struct scmi_powercap_proto_ops powercap_proto_ops = { .num_domains_get = scmi_powercap_num_domains_get, .info_get = scmi_powercap_dom_info_get, .cap_get = scmi_powercap_cap_get, .cap_set = scmi_powercap_cap_set, + .cap_enable_set = scmi_powercap_cap_enable_set, + .cap_enable_get = scmi_powercap_cap_enable_get, .pai_get = scmi_powercap_pai_get, .pai_set = scmi_powercap_pai_set, .measurements_get = scmi_powercap_measurements_get, @@ -829,6 +941,11 @@ scmi_powercap_protocol_init(const struct scmi_protocol_handle *ph) if (!pinfo->powercaps) return -ENOMEM; + pinfo->states = devm_kcalloc(ph->dev, pinfo->num_domains, + sizeof(*pinfo->states), GFP_KERNEL); + if (!pinfo->states) + return -ENOMEM; + /* * Note that any failure in retrieving any domain attribute leads to * the whole Powercap protocol initialization failure: this way the @@ -843,15 +960,21 @@ scmi_powercap_protocol_init(const struct scmi_protocol_handle *ph) if (pinfo->powercaps[domain].fastchannels) scmi_powercap_domain_init_fc(ph, domain, &pinfo->powercaps[domain].fc_info); - } - pinfo->states = devm_kcalloc(ph->dev, pinfo->num_domains, - sizeof(*pinfo->states), GFP_KERNEL); - if (!pinfo->states) - return -ENOMEM; + /* Grab initial state when disable is supported. */ + if (PROTOCOL_REV_MAJOR(version) >= 0x2) { + ret = __scmi_powercap_cap_get(ph, + &pinfo->powercaps[domain], + &pinfo->states[domain].last_pcap); + if (ret) + return ret; - pinfo->version = version; + pinfo->states[domain].enabled = + !!pinfo->states[domain].last_pcap; + } + } + pinfo->version = version; return ph->set_priv(ph, pinfo); } diff --git a/drivers/firmware/arm_scmi/smc.c b/drivers/firmware/arm_scmi/smc.c index 93272e4bbd12b96629129c0ec8635231b6f2e247..621c37efe3ec49a2d28e15b9ff18718c614f46b4 100644 --- a/drivers/firmware/arm_scmi/smc.c +++ b/drivers/firmware/arm_scmi/smc.c @@ -20,6 +20,23 @@ #include "common.h" +/* + * The shmem address is split into 4K page and offset. + * This is to make sure the parameters fit in 32bit arguments of the + * smc/hvc call to keep it uniform across smc32/smc64 conventions. + * This however limits the shmem address to 44 bit. + * + * These optional parameters can be used to distinguish among multiple + * scmi instances that are using the same smc-id. + * The page parameter is passed in r1/x1/w1 register and the offset parameter + * is passed in r2/x2/w2 register. + */ + +#define SHMEM_SIZE (SZ_4K) +#define SHMEM_SHIFT 12 +#define SHMEM_PAGE(x) (_UL((x) >> SHMEM_SHIFT)) +#define SHMEM_OFFSET(x) ((x) & (SHMEM_SIZE - 1)) + /** * struct scmi_smc - Structure representing a SCMI smc transport * @@ -30,6 +47,8 @@ * @inflight: Atomic flag to protect access to Tx/Rx shared memory area. * Used when operating in atomic mode. * @func_id: smc/hvc call function id + * @param_page: 4K page number of the shmem channel + * @param_offset: Offset within the 4K page of the shmem channel */ struct scmi_smc { @@ -40,6 +59,8 @@ struct scmi_smc { #define INFLIGHT_NONE MSG_TOKEN_MAX atomic_t inflight; u32 func_id; + u32 param_page; + u32 param_offset; }; static irqreturn_t smc_msg_done_isr(int irq, void *data) @@ -137,6 +158,10 @@ static int smc_chan_setup(struct scmi_chan_info *cinfo, struct device *dev, if (ret < 0) return ret; + if (of_device_is_compatible(dev->of_node, "arm,scmi-smc-param")) { + scmi_info->param_page = SHMEM_PAGE(res.start); + scmi_info->param_offset = SHMEM_OFFSET(res.start); + } /* * If there is an interrupt named "a2p", then the service and * completion of a message is signaled by an interrupt rather than by @@ -179,6 +204,8 @@ static int smc_send_message(struct scmi_chan_info *cinfo, { struct scmi_smc *scmi_info = cinfo->transport_info; struct arm_smccc_res res; + unsigned long page = scmi_info->param_page; + unsigned long offset = scmi_info->param_offset; /* * Channel will be released only once response has been @@ -188,7 +215,8 @@ static int smc_send_message(struct scmi_chan_info *cinfo, shmem_tx_prepare(scmi_info->shmem, xfer, cinfo); - arm_smccc_1_1_invoke(scmi_info->func_id, 0, 0, 0, 0, 0, 0, 0, &res); + arm_smccc_1_1_invoke(scmi_info->func_id, page, offset, 0, 0, 0, 0, 0, + &res); /* Only SMCCC_RET_NOT_SUPPORTED is valid error code */ if (res.a0) { diff --git a/drivers/firmware/cirrus/cs_dsp.c b/drivers/firmware/cirrus/cs_dsp.c index ec056f6f40ce81ddd5a09578193811e9b9d1b9c1..6a9aa97373d37f2403d5e1bfa4e9121017beaa33 100644 --- a/drivers/firmware/cirrus/cs_dsp.c +++ b/drivers/firmware/cirrus/cs_dsp.c @@ -2059,10 +2059,10 @@ static int cs_dsp_load_coeff(struct cs_dsp *dsp, const struct firmware *firmware goto out_fw; } - cs_dsp_dbg(dsp, "%s: v%d.%d.%d\n", file, - (le32_to_cpu(hdr->ver) >> 16) & 0xff, - (le32_to_cpu(hdr->ver) >> 8) & 0xff, - le32_to_cpu(hdr->ver) & 0xff); + cs_dsp_info(dsp, "%s: v%d.%d.%d\n", file, + (le32_to_cpu(hdr->ver) >> 16) & 0xff, + (le32_to_cpu(hdr->ver) >> 8) & 0xff, + le32_to_cpu(hdr->ver) & 0xff); pos = le32_to_cpu(hdr->len); diff --git a/drivers/firmware/dmi-sysfs.c b/drivers/firmware/dmi-sysfs.c index 03708ab64e56c45f5a7eb02b8e05e710b0e8785c..8d91997036e4c39731019e8082e80da3d733d4e3 100644 --- a/drivers/firmware/dmi-sysfs.c +++ b/drivers/firmware/dmi-sysfs.c @@ -310,6 +310,7 @@ static const struct kobj_type dmi_system_event_log_ktype = { .default_groups = dmi_sysfs_sel_groups, }; +#ifdef CONFIG_HAS_IOPORT typedef u8 (*sel_io_reader)(const struct dmi_system_event_log *sel, loff_t offset); @@ -374,6 +375,7 @@ static ssize_t dmi_sel_raw_read_io(struct dmi_sysfs_entry *entry, return wrote; } +#endif static ssize_t dmi_sel_raw_read_phys32(struct dmi_sysfs_entry *entry, const struct dmi_system_event_log *sel, @@ -409,11 +411,13 @@ static ssize_t dmi_sel_raw_read_helper(struct dmi_sysfs_entry *entry, memcpy(&sel, dh, sizeof(sel)); switch (sel.access_method) { +#ifdef CONFIG_HAS_IOPORT case DMI_SEL_ACCESS_METHOD_IO8: case DMI_SEL_ACCESS_METHOD_IO2x8: case DMI_SEL_ACCESS_METHOD_IO16: return dmi_sel_raw_read_io(entry, &sel, state->buf, state->pos, state->count); +#endif case DMI_SEL_ACCESS_METHOD_PHYS32: return dmi_sel_raw_read_phys32(entry, &sel, state->buf, state->pos, state->count); diff --git a/drivers/firmware/efi/Kconfig b/drivers/firmware/efi/Kconfig index 043ca31c114ebf2a51ea5e111d28ccbe80637a7a..231f1c70d1db548566b56a63bc52dcbe324a4a3d 100644 --- a/drivers/firmware/efi/Kconfig +++ b/drivers/firmware/efi/Kconfig @@ -269,6 +269,20 @@ config EFI_COCO_SECRET virt/coco/efi_secret module to access the secrets, which in turn allows userspace programs to access the injected secrets. +config UNACCEPTED_MEMORY + bool + depends on EFI_STUB + help + Some Virtual Machine platforms, such as Intel TDX, require + some memory to be "accepted" by the guest before it can be used. + This mechanism helps prevent malicious hosts from making changes + to guest memory. + + UEFI specification v2.9 introduced EFI_UNACCEPTED_MEMORY memory type. + + This option adds support for unaccepted memory and makes such memory + usable by the kernel. + config EFI_EMBEDDED_FIRMWARE bool select CRYPTO_LIB_SHA256 diff --git a/drivers/firmware/efi/Makefile b/drivers/firmware/efi/Makefile index b51f2a4c821e943340aaa9b0aa732c2b11874714..e489fefd23dae0bc21baaf48be6c1499ca5d63c7 100644 --- a/drivers/firmware/efi/Makefile +++ b/drivers/firmware/efi/Makefile @@ -41,3 +41,4 @@ obj-$(CONFIG_EFI_CAPSULE_LOADER) += capsule-loader.o obj-$(CONFIG_EFI_EARLYCON) += earlycon.o obj-$(CONFIG_UEFI_CPER_ARM) += cper-arm.o obj-$(CONFIG_UEFI_CPER_X86) += cper-x86.o +obj-$(CONFIG_UNACCEPTED_MEMORY) += unaccepted_memory.o diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c index abeff7dc0b581f8661b2d6a22edeb108d36497a6..1599f11768426d8ff72c9c2cfc9387728af2efa3 100644 --- a/drivers/firmware/efi/efi.c +++ b/drivers/firmware/efi/efi.c @@ -50,6 +50,9 @@ struct efi __read_mostly efi = { #ifdef CONFIG_EFI_COCO_SECRET .coco_secret = EFI_INVALID_TABLE_ADDR, #endif +#ifdef CONFIG_UNACCEPTED_MEMORY + .unaccepted = EFI_INVALID_TABLE_ADDR, +#endif }; EXPORT_SYMBOL(efi); @@ -211,6 +214,7 @@ static int generic_ops_register(void) generic_ops.get_variable = efi.get_variable; generic_ops.get_next_variable = efi.get_next_variable; generic_ops.query_variable_store = efi_query_variable_store; + generic_ops.query_variable_info = efi.query_variable_info; if (efi_rt_services_supported(EFI_RT_SUPPORTED_SET_VARIABLE)) { generic_ops.set_variable = efi.set_variable; @@ -361,24 +365,6 @@ static void __init efi_debugfs_init(void) static inline void efi_debugfs_init(void) {} #endif -static void refresh_nv_rng_seed(struct work_struct *work) -{ - u8 seed[EFI_RANDOM_SEED_SIZE]; - - get_random_bytes(seed, sizeof(seed)); - efi.set_variable(L"RandomSeed", &LINUX_EFI_RANDOM_SEED_TABLE_GUID, - EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | - EFI_VARIABLE_RUNTIME_ACCESS, sizeof(seed), seed); - memzero_explicit(seed, sizeof(seed)); -} -static int refresh_nv_rng_seed_notification(struct notifier_block *nb, unsigned long action, void *data) -{ - static DECLARE_WORK(work, refresh_nv_rng_seed); - schedule_work(&work); - return NOTIFY_DONE; -} -static struct notifier_block refresh_nv_rng_seed_nb = { .notifier_call = refresh_nv_rng_seed_notification }; - /* * We register the efi subsystem with the firmware subsystem and the * efivars subsystem with the efi subsystem, if the system was booted with @@ -451,9 +437,6 @@ static int __init efisubsys_init(void) platform_device_register_simple("efi_secret", 0, NULL, 0); #endif - if (efi_rt_services_supported(EFI_RT_SUPPORTED_SET_VARIABLE)) - execute_with_initialized_rng(&refresh_nv_rng_seed_nb); - return 0; err_remove_group: @@ -605,6 +588,9 @@ static const efi_config_table_type_t common_tables[] __initconst = { #ifdef CONFIG_EFI_COCO_SECRET {LINUX_EFI_COCO_SECRET_AREA_GUID, &efi.coco_secret, "CocoSecret" }, #endif +#ifdef CONFIG_UNACCEPTED_MEMORY + {LINUX_EFI_UNACCEPTED_MEM_TABLE_GUID, &efi.unaccepted, "Unaccepted" }, +#endif #ifdef CONFIG_EFI_GENERIC_STUB {LINUX_EFI_SCREEN_INFO_TABLE_GUID, &screen_info_table }, #endif @@ -759,6 +745,25 @@ int __init efi_config_parse_tables(const efi_config_table_t *config_tables, } } + if (IS_ENABLED(CONFIG_UNACCEPTED_MEMORY) && + efi.unaccepted != EFI_INVALID_TABLE_ADDR) { + struct efi_unaccepted_memory *unaccepted; + + unaccepted = early_memremap(efi.unaccepted, sizeof(*unaccepted)); + if (unaccepted) { + unsigned long size; + + if (unaccepted->version == 1) { + size = sizeof(*unaccepted) + unaccepted->size; + memblock_reserve(efi.unaccepted, size); + } else { + efi.unaccepted = EFI_INVALID_TABLE_ADDR; + } + + early_memunmap(unaccepted, sizeof(*unaccepted)); + } + } + return 0; } @@ -843,6 +848,7 @@ static __initdata char memory_type_name[][13] = { "MMIO Port", "PAL Code", "Persistent", + "Unaccepted", }; char * __init efi_md_typeattr_format(char *buf, size_t size, diff --git a/drivers/firmware/efi/esrt.c b/drivers/firmware/efi/esrt.c index 87729c365be1a804bb84e0b1ab874042848327b4..7a81c0ce4780593d01bcabbbbb8920d0e5d8b690 100644 --- a/drivers/firmware/efi/esrt.c +++ b/drivers/firmware/efi/esrt.c @@ -95,10 +95,6 @@ static ssize_t esre_attr_show(struct kobject *kobj, struct esre_entry *entry = to_entry(kobj); struct esre_attribute *attr = to_attr(_attr); - /* Don't tell normal users what firmware versions we've got... */ - if (!capable(CAP_SYS_ADMIN)) - return -EACCES; - return attr->show(entry, buf); } @@ -156,7 +152,7 @@ static void esre_release(struct kobject *kobj) kfree(entry); } -static struct kobj_type esre1_ktype = { +static const struct kobj_type esre1_ktype = { .release = esre_release, .sysfs_ops = &esre_attr_ops, .default_groups = esre1_groups, diff --git a/drivers/firmware/efi/libstub/Makefile b/drivers/firmware/efi/libstub/Makefile index 3abb2b357482a416e95b4ffedb6a9bd94e75d514..16d64a34d1e1946544e8b8cbef3fc35069364a3c 100644 --- a/drivers/firmware/efi/libstub/Makefile +++ b/drivers/firmware/efi/libstub/Makefile @@ -96,6 +96,8 @@ CFLAGS_arm32-stub.o := -DTEXT_OFFSET=$(TEXT_OFFSET) zboot-obj-$(CONFIG_RISCV) := lib-clz_ctz.o lib-ashldi3.o lib-$(CONFIG_EFI_ZBOOT) += zboot.o $(zboot-obj-y) +lib-$(CONFIG_UNACCEPTED_MEMORY) += unaccepted_memory.o bitmap.o find.o + extra-y := $(lib-y) lib-y := $(patsubst %.o,%.stub.o,$(lib-y)) diff --git a/drivers/firmware/efi/libstub/bitmap.c b/drivers/firmware/efi/libstub/bitmap.c new file mode 100644 index 0000000000000000000000000000000000000000..5c9bba0d549be20e984d3ed3906aa9f8dd459d62 --- /dev/null +++ b/drivers/firmware/efi/libstub/bitmap.c @@ -0,0 +1,41 @@ +#include + +void __bitmap_set(unsigned long *map, unsigned int start, int len) +{ + unsigned long *p = map + BIT_WORD(start); + const unsigned int size = start + len; + int bits_to_set = BITS_PER_LONG - (start % BITS_PER_LONG); + unsigned long mask_to_set = BITMAP_FIRST_WORD_MASK(start); + + while (len - bits_to_set >= 0) { + *p |= mask_to_set; + len -= bits_to_set; + bits_to_set = BITS_PER_LONG; + mask_to_set = ~0UL; + p++; + } + if (len) { + mask_to_set &= BITMAP_LAST_WORD_MASK(size); + *p |= mask_to_set; + } +} + +void __bitmap_clear(unsigned long *map, unsigned int start, int len) +{ + unsigned long *p = map + BIT_WORD(start); + const unsigned int size = start + len; + int bits_to_clear = BITS_PER_LONG - (start % BITS_PER_LONG); + unsigned long mask_to_clear = BITMAP_FIRST_WORD_MASK(start); + + while (len - bits_to_clear >= 0) { + *p &= ~mask_to_clear; + len -= bits_to_clear; + bits_to_clear = BITS_PER_LONG; + mask_to_clear = ~0UL; + p++; + } + if (len) { + mask_to_clear &= BITMAP_LAST_WORD_MASK(size); + *p &= ~mask_to_clear; + } +} diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c index 1e0203d74691ffcc4dcfbc7f861f1bc4e12b76a9..732984295295fb6d11cdbbd53bc85a4130ee5c97 100644 --- a/drivers/firmware/efi/libstub/efi-stub-helper.c +++ b/drivers/firmware/efi/libstub/efi-stub-helper.c @@ -378,6 +378,9 @@ efi_status_t efi_exit_boot_services(void *handle, void *priv, struct efi_boot_memmap *map; efi_status_t status; + if (efi_disable_pci_dma) + efi_pci_disable_bridge_busmaster(); + status = efi_get_memory_map(&map, true); if (status != EFI_SUCCESS) return status; @@ -388,9 +391,6 @@ efi_status_t efi_exit_boot_services(void *handle, void *priv, return status; } - if (efi_disable_pci_dma) - efi_pci_disable_bridge_busmaster(); - status = efi_bs_call(exit_boot_services, handle, map->map_key); if (status == EFI_INVALID_PARAMETER) { diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h index 54a2822cae7714584c668dd9e0650350e30922df..6aa38a1bf1265d83aa6f87ccb379a6659653a519 100644 --- a/drivers/firmware/efi/libstub/efistub.h +++ b/drivers/firmware/efi/libstub/efistub.h @@ -1136,4 +1136,10 @@ void efi_remap_image(unsigned long image_base, unsigned alloc_size, asmlinkage efi_status_t __efiapi efi_zboot_entry(efi_handle_t handle, efi_system_table_t *systab); +efi_status_t allocate_unaccepted_bitmap(__u32 nr_desc, + struct efi_boot_memmap *map); +void process_unaccepted_memory(u64 start, u64 end); +void accept_memory(phys_addr_t start, phys_addr_t end); +void arch_accept_memory(phys_addr_t start, phys_addr_t end); + #endif diff --git a/drivers/firmware/efi/libstub/find.c b/drivers/firmware/efi/libstub/find.c new file mode 100644 index 0000000000000000000000000000000000000000..4e7740d289875d3fa29a36dcc0bc7ba27d323296 --- /dev/null +++ b/drivers/firmware/efi/libstub/find.c @@ -0,0 +1,43 @@ +// SPDX-License-Identifier: GPL-2.0-only +#include +#include +#include + +/* + * Common helper for find_next_bit() function family + * @FETCH: The expression that fetches and pre-processes each word of bitmap(s) + * @MUNGE: The expression that post-processes a word containing found bit (may be empty) + * @size: The bitmap size in bits + * @start: The bitnumber to start searching at + */ +#define FIND_NEXT_BIT(FETCH, MUNGE, size, start) \ +({ \ + unsigned long mask, idx, tmp, sz = (size), __start = (start); \ + \ + if (unlikely(__start >= sz)) \ + goto out; \ + \ + mask = MUNGE(BITMAP_FIRST_WORD_MASK(__start)); \ + idx = __start / BITS_PER_LONG; \ + \ + for (tmp = (FETCH) & mask; !tmp; tmp = (FETCH)) { \ + if ((idx + 1) * BITS_PER_LONG >= sz) \ + goto out; \ + idx++; \ + } \ + \ + sz = min(idx * BITS_PER_LONG + __ffs(MUNGE(tmp)), sz); \ +out: \ + sz; \ +}) + +unsigned long _find_next_bit(const unsigned long *addr, unsigned long nbits, unsigned long start) +{ + return FIND_NEXT_BIT(addr[idx], /* nop */, nbits, start); +} + +unsigned long _find_next_zero_bit(const unsigned long *addr, unsigned long nbits, + unsigned long start) +{ + return FIND_NEXT_BIT(~addr[idx], /* nop */, nbits, start); +} diff --git a/drivers/firmware/efi/libstub/unaccepted_memory.c b/drivers/firmware/efi/libstub/unaccepted_memory.c new file mode 100644 index 0000000000000000000000000000000000000000..ca61f4733ea5869356489a8f2709a23cbf591601 --- /dev/null +++ b/drivers/firmware/efi/libstub/unaccepted_memory.c @@ -0,0 +1,222 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include +#include +#include "efistub.h" + +struct efi_unaccepted_memory *unaccepted_table; + +efi_status_t allocate_unaccepted_bitmap(__u32 nr_desc, + struct efi_boot_memmap *map) +{ + efi_guid_t unaccepted_table_guid = LINUX_EFI_UNACCEPTED_MEM_TABLE_GUID; + u64 unaccepted_start = ULLONG_MAX, unaccepted_end = 0, bitmap_size; + efi_status_t status; + int i; + + /* Check if the table is already installed */ + unaccepted_table = get_efi_config_table(unaccepted_table_guid); + if (unaccepted_table) { + if (unaccepted_table->version != 1) { + efi_err("Unknown version of unaccepted memory table\n"); + return EFI_UNSUPPORTED; + } + return EFI_SUCCESS; + } + + /* Check if there's any unaccepted memory and find the max address */ + for (i = 0; i < nr_desc; i++) { + efi_memory_desc_t *d; + unsigned long m = (unsigned long)map->map; + + d = efi_early_memdesc_ptr(m, map->desc_size, i); + if (d->type != EFI_UNACCEPTED_MEMORY) + continue; + + unaccepted_start = min(unaccepted_start, d->phys_addr); + unaccepted_end = max(unaccepted_end, + d->phys_addr + d->num_pages * PAGE_SIZE); + } + + if (unaccepted_start == ULLONG_MAX) + return EFI_SUCCESS; + + unaccepted_start = round_down(unaccepted_start, + EFI_UNACCEPTED_UNIT_SIZE); + unaccepted_end = round_up(unaccepted_end, EFI_UNACCEPTED_UNIT_SIZE); + + /* + * If unaccepted memory is present, allocate a bitmap to track what + * memory has to be accepted before access. + * + * One bit in the bitmap represents 2MiB in the address space: + * A 4k bitmap can track 64GiB of physical address space. + * + * In the worst case scenario -- a huge hole in the middle of the + * address space -- It needs 256MiB to handle 4PiB of the address + * space. + * + * The bitmap will be populated in setup_e820() according to the memory + * map after efi_exit_boot_services(). + */ + bitmap_size = DIV_ROUND_UP(unaccepted_end - unaccepted_start, + EFI_UNACCEPTED_UNIT_SIZE * BITS_PER_BYTE); + + status = efi_bs_call(allocate_pool, EFI_LOADER_DATA, + sizeof(*unaccepted_table) + bitmap_size, + (void **)&unaccepted_table); + if (status != EFI_SUCCESS) { + efi_err("Failed to allocate unaccepted memory config table\n"); + return status; + } + + unaccepted_table->version = 1; + unaccepted_table->unit_size = EFI_UNACCEPTED_UNIT_SIZE; + unaccepted_table->phys_base = unaccepted_start; + unaccepted_table->size = bitmap_size; + memset(unaccepted_table->bitmap, 0, bitmap_size); + + status = efi_bs_call(install_configuration_table, + &unaccepted_table_guid, unaccepted_table); + if (status != EFI_SUCCESS) { + efi_bs_call(free_pool, unaccepted_table); + efi_err("Failed to install unaccepted memory config table!\n"); + } + + return status; +} + +/* + * The accepted memory bitmap only works at unit_size granularity. Take + * unaligned start/end addresses and either: + * 1. Accepts the memory immediately and in its entirety + * 2. Accepts unaligned parts, and marks *some* aligned part unaccepted + * + * The function will never reach the bitmap_set() with zero bits to set. + */ +void process_unaccepted_memory(u64 start, u64 end) +{ + u64 unit_size = unaccepted_table->unit_size; + u64 unit_mask = unaccepted_table->unit_size - 1; + u64 bitmap_size = unaccepted_table->size; + + /* + * Ensure that at least one bit will be set in the bitmap by + * immediately accepting all regions under 2*unit_size. This is + * imprecise and may immediately accept some areas that could + * have been represented in the bitmap. But, results in simpler + * code below + * + * Consider case like this (assuming unit_size == 2MB): + * + * | 4k | 2044k | 2048k | + * ^ 0x0 ^ 2MB ^ 4MB + * + * Only the first 4k has been accepted. The 0MB->2MB region can not be + * represented in the bitmap. The 2MB->4MB region can be represented in + * the bitmap. But, the 0MB->4MB region is <2*unit_size and will be + * immediately accepted in its entirety. + */ + if (end - start < 2 * unit_size) { + arch_accept_memory(start, end); + return; + } + + /* + * No matter how the start and end are aligned, at least one unaccepted + * unit_size area will remain to be marked in the bitmap. + */ + + /* Immediately accept a phys_base) { + arch_accept_memory(start, + min(unaccepted_table->phys_base, end)); + start = unaccepted_table->phys_base; + } + + /* Nothing to record */ + if (end < unaccepted_table->phys_base) + return; + + /* Translate to offsets from the beginning of the bitmap */ + start -= unaccepted_table->phys_base; + end -= unaccepted_table->phys_base; + + /* Accept memory that doesn't fit into bitmap */ + if (end > bitmap_size * unit_size * BITS_PER_BYTE) { + unsigned long phys_start, phys_end; + + phys_start = bitmap_size * unit_size * BITS_PER_BYTE + + unaccepted_table->phys_base; + phys_end = end + unaccepted_table->phys_base; + + arch_accept_memory(phys_start, phys_end); + end = bitmap_size * unit_size * BITS_PER_BYTE; + } + + /* + * 'start' and 'end' are now both unit_size-aligned. + * Record the range as being unaccepted: + */ + bitmap_set(unaccepted_table->bitmap, + start / unit_size, (end - start) / unit_size); +} + +void accept_memory(phys_addr_t start, phys_addr_t end) +{ + unsigned long range_start, range_end; + unsigned long bitmap_size; + u64 unit_size; + + if (!unaccepted_table) + return; + + unit_size = unaccepted_table->unit_size; + + /* + * Only care for the part of the range that is represented + * in the bitmap. + */ + if (start < unaccepted_table->phys_base) + start = unaccepted_table->phys_base; + if (end < unaccepted_table->phys_base) + return; + + /* Translate to offsets from the beginning of the bitmap */ + start -= unaccepted_table->phys_base; + end -= unaccepted_table->phys_base; + + /* Make sure not to overrun the bitmap */ + if (end > unaccepted_table->size * unit_size * BITS_PER_BYTE) + end = unaccepted_table->size * unit_size * BITS_PER_BYTE; + + range_start = start / unit_size; + bitmap_size = DIV_ROUND_UP(end, unit_size); + + for_each_set_bitrange_from(range_start, range_end, + unaccepted_table->bitmap, bitmap_size) { + unsigned long phys_start, phys_end; + + phys_start = range_start * unit_size + unaccepted_table->phys_base; + phys_end = range_end * unit_size + unaccepted_table->phys_base; + + arch_accept_memory(phys_start, phys_end); + bitmap_clear(unaccepted_table->bitmap, + range_start, range_end - range_start); + } +} diff --git a/drivers/firmware/efi/libstub/x86-stub.c b/drivers/firmware/efi/libstub/x86-stub.c index a0bfd31358ba97b1ac8b604c98b1981b19364ee2..220be75a5cdc1f4c7e5e6fb38832fedfd15a8369 100644 --- a/drivers/firmware/efi/libstub/x86-stub.c +++ b/drivers/firmware/efi/libstub/x86-stub.c @@ -26,6 +26,17 @@ const efi_dxe_services_table_t *efi_dxe_table; u32 image_offset __section(".data"); static efi_loaded_image_t *image = NULL; +typedef union sev_memory_acceptance_protocol sev_memory_acceptance_protocol_t; +union sev_memory_acceptance_protocol { + struct { + efi_status_t (__efiapi * allow_unaccepted_memory)( + sev_memory_acceptance_protocol_t *); + }; + struct { + u32 allow_unaccepted_memory; + } mixed_mode; +}; + static efi_status_t preserve_pci_rom_image(efi_pci_io_protocol_t *pci, struct pci_setup_rom **__rom) { @@ -310,6 +321,29 @@ setup_memory_protection(unsigned long image_base, unsigned long image_size) #endif } +static void setup_unaccepted_memory(void) +{ + efi_guid_t mem_acceptance_proto = OVMF_SEV_MEMORY_ACCEPTANCE_PROTOCOL_GUID; + sev_memory_acceptance_protocol_t *proto; + efi_status_t status; + + if (!IS_ENABLED(CONFIG_UNACCEPTED_MEMORY)) + return; + + /* + * Enable unaccepted memory before calling exit boot services in order + * for the UEFI to not accept all memory on EBS. + */ + status = efi_bs_call(locate_protocol, &mem_acceptance_proto, NULL, + (void **)&proto); + if (status != EFI_SUCCESS) + return; + + status = efi_call_proto(proto, allow_unaccepted_memory); + if (status != EFI_SUCCESS) + efi_err("Memory acceptance protocol failed\n"); +} + static const efi_char16_t apple[] = L"Apple"; static void setup_quirks(struct boot_params *boot_params, @@ -613,6 +647,16 @@ setup_e820(struct boot_params *params, struct setup_data *e820ext, u32 e820ext_s e820_type = E820_TYPE_PMEM; break; + case EFI_UNACCEPTED_MEMORY: + if (!IS_ENABLED(CONFIG_UNACCEPTED_MEMORY)) { + efi_warn_once( +"The system has unaccepted memory, but kernel does not support it\nConsider enabling CONFIG_UNACCEPTED_MEMORY\n"); + continue; + } + e820_type = E820_TYPE_RAM; + process_unaccepted_memory(d->phys_addr, + d->phys_addr + PAGE_SIZE * d->num_pages); + break; default: continue; } @@ -681,28 +725,27 @@ static efi_status_t allocate_e820(struct boot_params *params, struct setup_data **e820ext, u32 *e820ext_size) { - unsigned long map_size, desc_size, map_key; + struct efi_boot_memmap *map; efi_status_t status; - __u32 nr_desc, desc_version; - - /* Only need the size of the mem map and size of each mem descriptor */ - map_size = 0; - status = efi_bs_call(get_memory_map, &map_size, NULL, &map_key, - &desc_size, &desc_version); - if (status != EFI_BUFFER_TOO_SMALL) - return (status != EFI_SUCCESS) ? status : EFI_UNSUPPORTED; + __u32 nr_desc; - nr_desc = map_size / desc_size + EFI_MMAP_NR_SLACK_SLOTS; + status = efi_get_memory_map(&map, false); + if (status != EFI_SUCCESS) + return status; - if (nr_desc > ARRAY_SIZE(params->e820_table)) { - u32 nr_e820ext = nr_desc - ARRAY_SIZE(params->e820_table); + nr_desc = map->map_size / map->desc_size; + if (nr_desc > ARRAY_SIZE(params->e820_table) - EFI_MMAP_NR_SLACK_SLOTS) { + u32 nr_e820ext = nr_desc - ARRAY_SIZE(params->e820_table) + + EFI_MMAP_NR_SLACK_SLOTS; status = alloc_e820ext(nr_e820ext, e820ext, e820ext_size); - if (status != EFI_SUCCESS) - return status; } - return EFI_SUCCESS; + if (IS_ENABLED(CONFIG_UNACCEPTED_MEMORY) && status == EFI_SUCCESS) + status = allocate_unaccepted_bitmap(nr_desc, map); + + efi_bs_call(free_pool, map); + return status; } struct exit_boot_struct { @@ -899,6 +942,8 @@ asmlinkage unsigned long efi_main(efi_handle_t handle, setup_quirks(boot_params, bzimage_addr, buffer_end - buffer_start); + setup_unaccepted_memory(); + status = exit_boot(boot_params, handle); if (status != EFI_SUCCESS) { efi_err("exit_boot() failed!\n"); diff --git a/drivers/firmware/efi/unaccepted_memory.c b/drivers/firmware/efi/unaccepted_memory.c new file mode 100644 index 0000000000000000000000000000000000000000..853f7dc3c21d8f0dafed9d43f57ebdf13fcf911a --- /dev/null +++ b/drivers/firmware/efi/unaccepted_memory.c @@ -0,0 +1,147 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include +#include +#include +#include + +/* Protects unaccepted memory bitmap */ +static DEFINE_SPINLOCK(unaccepted_memory_lock); + +/* + * accept_memory() -- Consult bitmap and accept the memory if needed. + * + * Only memory that is explicitly marked as unaccepted in the bitmap requires + * an action. All the remaining memory is implicitly accepted and doesn't need + * acceptance. + * + * No need to accept: + * - anything if the system has no unaccepted table; + * - memory that is below phys_base; + * - memory that is above the memory that addressable by the bitmap; + */ +void accept_memory(phys_addr_t start, phys_addr_t end) +{ + struct efi_unaccepted_memory *unaccepted; + unsigned long range_start, range_end; + unsigned long flags; + u64 unit_size; + + unaccepted = efi_get_unaccepted_table(); + if (!unaccepted) + return; + + unit_size = unaccepted->unit_size; + + /* + * Only care for the part of the range that is represented + * in the bitmap. + */ + if (start < unaccepted->phys_base) + start = unaccepted->phys_base; + if (end < unaccepted->phys_base) + return; + + /* Translate to offsets from the beginning of the bitmap */ + start -= unaccepted->phys_base; + end -= unaccepted->phys_base; + + /* + * load_unaligned_zeropad() can lead to unwanted loads across page + * boundaries. The unwanted loads are typically harmless. But, they + * might be made to totally unrelated or even unmapped memory. + * load_unaligned_zeropad() relies on exception fixup (#PF, #GP and now + * #VE) to recover from these unwanted loads. + * + * But, this approach does not work for unaccepted memory. For TDX, a + * load from unaccepted memory will not lead to a recoverable exception + * within the guest. The guest will exit to the VMM where the only + * recourse is to terminate the guest. + * + * There are two parts to fix this issue and comprehensively avoid + * access to unaccepted memory. Together these ensure that an extra + * "guard" page is accepted in addition to the memory that needs to be + * used: + * + * 1. Implicitly extend the range_contains_unaccepted_memory(start, end) + * checks up to end+unit_size if 'end' is aligned on a unit_size + * boundary. + * + * 2. Implicitly extend accept_memory(start, end) to end+unit_size if + * 'end' is aligned on a unit_size boundary. (immediately following + * this comment) + */ + if (!(end % unit_size)) + end += unit_size; + + /* Make sure not to overrun the bitmap */ + if (end > unaccepted->size * unit_size * BITS_PER_BYTE) + end = unaccepted->size * unit_size * BITS_PER_BYTE; + + range_start = start / unit_size; + + spin_lock_irqsave(&unaccepted_memory_lock, flags); + for_each_set_bitrange_from(range_start, range_end, unaccepted->bitmap, + DIV_ROUND_UP(end, unit_size)) { + unsigned long phys_start, phys_end; + unsigned long len = range_end - range_start; + + phys_start = range_start * unit_size + unaccepted->phys_base; + phys_end = range_end * unit_size + unaccepted->phys_base; + + arch_accept_memory(phys_start, phys_end); + bitmap_clear(unaccepted->bitmap, range_start, len); + } + spin_unlock_irqrestore(&unaccepted_memory_lock, flags); +} + +bool range_contains_unaccepted_memory(phys_addr_t start, phys_addr_t end) +{ + struct efi_unaccepted_memory *unaccepted; + unsigned long flags; + bool ret = false; + u64 unit_size; + + unaccepted = efi_get_unaccepted_table(); + if (!unaccepted) + return false; + + unit_size = unaccepted->unit_size; + + /* + * Only care for the part of the range that is represented + * in the bitmap. + */ + if (start < unaccepted->phys_base) + start = unaccepted->phys_base; + if (end < unaccepted->phys_base) + return false; + + /* Translate to offsets from the beginning of the bitmap */ + start -= unaccepted->phys_base; + end -= unaccepted->phys_base; + + /* + * Also consider the unaccepted state of the *next* page. See fix #1 in + * the comment on load_unaligned_zeropad() in accept_memory(). + */ + if (!(end % unit_size)) + end += unit_size; + + /* Make sure not to overrun the bitmap */ + if (end > unaccepted->size * unit_size * BITS_PER_BYTE) + end = unaccepted->size * unit_size * BITS_PER_BYTE; + + spin_lock_irqsave(&unaccepted_memory_lock, flags); + while (start < end) { + if (test_bit(start / unit_size, unaccepted->bitmap)) { + ret = true; + break; + } + + start += unit_size; + } + spin_unlock_irqrestore(&unaccepted_memory_lock, flags); + + return ret; +} diff --git a/drivers/firmware/efi/vars.c b/drivers/firmware/efi/vars.c index bfc5fa6aa47b687cc43623b3a238d8564ac1565e..e9dc7116daf133e68750ed7148f2661f6c5ffc34 100644 --- a/drivers/firmware/efi/vars.c +++ b/drivers/firmware/efi/vars.c @@ -245,3 +245,15 @@ efi_status_t efivar_set_variable(efi_char16_t *name, efi_guid_t *vendor, return status; } EXPORT_SYMBOL_NS_GPL(efivar_set_variable, EFIVAR); + +efi_status_t efivar_query_variable_info(u32 attr, + u64 *storage_space, + u64 *remaining_space, + u64 *max_variable_size) +{ + if (!__efivars->ops->query_variable_info) + return EFI_UNSUPPORTED; + return __efivars->ops->query_variable_info(attr, storage_space, + remaining_space, max_variable_size); +} +EXPORT_SYMBOL_NS_GPL(efivar_query_variable_info, EFIVAR); diff --git a/drivers/firmware/iscsi_ibft_find.c b/drivers/firmware/iscsi_ibft_find.c index 94b49ccd23ac3656495b6cbc48220624bd559b63..71f51303c2ba695c46b2591fa87476ff3d28f68d 100644 --- a/drivers/firmware/iscsi_ibft_find.c +++ b/drivers/firmware/iscsi_ibft_find.c @@ -42,8 +42,6 @@ static const struct { }; #define IBFT_SIGN_LEN 4 -#define IBFT_START 0x80000 /* 512kB */ -#define IBFT_END 0x100000 /* 1MB */ #define VGA_MEM 0xA0000 /* VGA buffer */ #define VGA_SIZE 0x20000 /* 128kB */ @@ -52,9 +50,9 @@ static const struct { */ void __init reserve_ibft_region(void) { - unsigned long pos; + unsigned long pos, virt_pos = 0; unsigned int len = 0; - void *virt; + void *virt = NULL; int i; ibft_phys_addr = 0; @@ -70,13 +68,20 @@ void __init reserve_ibft_region(void) * so skip that area */ if (pos == VGA_MEM) pos += VGA_SIZE; - virt = isa_bus_to_virt(pos); + + /* Map page by page */ + if (offset_in_page(pos) == 0) { + if (virt) + early_memunmap(virt, PAGE_SIZE); + virt = early_memremap_ro(pos, PAGE_SIZE); + virt_pos = pos; + } for (i = 0; i < ARRAY_SIZE(ibft_signs); i++) { - if (memcmp(virt, ibft_signs[i].sign, IBFT_SIGN_LEN) == - 0) { + if (memcmp(virt + (pos - virt_pos), ibft_signs[i].sign, + IBFT_SIGN_LEN) == 0) { unsigned long *addr = - (unsigned long *)isa_bus_to_virt(pos + 4); + (unsigned long *)(virt + pos - virt_pos + 4); len = *addr; /* if the length of the table extends past 1M, * the table cannot be valid. */ @@ -84,9 +89,12 @@ void __init reserve_ibft_region(void) ibft_phys_addr = pos; memblock_reserve(ibft_phys_addr, PAGE_ALIGN(len)); pr_info("iBFT found at %pa.\n", &ibft_phys_addr); - return; + goto out; } } } } + +out: + early_memunmap(virt, PAGE_SIZE); } diff --git a/drivers/firmware/stratix10-svc.c b/drivers/firmware/stratix10-svc.c index 80f4e2d14e046210e6ac4e55c173b3aa6c9ed20e..2d674126160fe3c12873c47d9d886d4abcc0c3a2 100644 --- a/drivers/firmware/stratix10-svc.c +++ b/drivers/firmware/stratix10-svc.c @@ -755,7 +755,7 @@ svc_create_memory_pool(struct platform_device *pdev, end = rounddown(sh_memory->addr + sh_memory->size, PAGE_SIZE); paddr = begin; size = end - begin; - va = memremap(paddr, size, MEMREMAP_WC); + va = devm_memremap(dev, paddr, size, MEMREMAP_WC); if (!va) { dev_err(dev, "fail to remap shared memory\n"); return ERR_PTR(-EINVAL); diff --git a/drivers/firmware/tegra/bpmp-tegra186.c b/drivers/firmware/tegra/bpmp-tegra186.c index 2e26199041cd2d8c798dcb05b513495e3aef440f..6f0d0511b4866d3f8c9021c0501e806b17992bab 100644 --- a/drivers/firmware/tegra/bpmp-tegra186.c +++ b/drivers/firmware/tegra/bpmp-tegra186.c @@ -4,7 +4,9 @@ */ #include +#include #include +#include #include #include @@ -18,7 +20,10 @@ struct tegra186_bpmp { struct { struct gen_pool *pool; - void __iomem *virt; + union { + void __iomem *sram; + void *dram; + }; dma_addr_t phys; } tx, rx; @@ -118,8 +123,13 @@ static int tegra186_bpmp_channel_init(struct tegra_bpmp_channel *channel, queue_size = tegra_ivc_total_queue_size(message_size); offset = queue_size * index; - iosys_map_set_vaddr_iomem(&rx, priv->rx.virt + offset); - iosys_map_set_vaddr_iomem(&tx, priv->tx.virt + offset); + if (priv->rx.pool) { + iosys_map_set_vaddr_iomem(&rx, priv->rx.sram + offset); + iosys_map_set_vaddr_iomem(&tx, priv->tx.sram + offset); + } else { + iosys_map_set_vaddr(&rx, priv->rx.dram + offset); + iosys_map_set_vaddr(&tx, priv->tx.dram + offset); + } err = tegra_ivc_init(channel->ivc, NULL, &rx, priv->rx.phys + offset, &tx, priv->tx.phys + offset, 1, message_size, tegra186_bpmp_ivc_notify, @@ -158,18 +168,72 @@ static void mbox_handle_rx(struct mbox_client *client, void *data) tegra_bpmp_handle_rx(bpmp); } -static int tegra186_bpmp_init(struct tegra_bpmp *bpmp) +static void tegra186_bpmp_teardown_channels(struct tegra_bpmp *bpmp) { - struct tegra186_bpmp *priv; + struct tegra186_bpmp *priv = bpmp->priv; unsigned int i; + + for (i = 0; i < bpmp->threaded.count; i++) { + if (!bpmp->threaded_channels[i].bpmp) + continue; + + tegra186_bpmp_channel_cleanup(&bpmp->threaded_channels[i]); + } + + tegra186_bpmp_channel_cleanup(bpmp->rx_channel); + tegra186_bpmp_channel_cleanup(bpmp->tx_channel); + + if (priv->tx.pool) { + gen_pool_free(priv->tx.pool, (unsigned long)priv->tx.sram, 4096); + gen_pool_free(priv->rx.pool, (unsigned long)priv->rx.sram, 4096); + } +} + +static int tegra186_bpmp_dram_init(struct tegra_bpmp *bpmp) +{ + struct tegra186_bpmp *priv = bpmp->priv; + struct device_node *np; + struct resource res; + size_t size; int err; - priv = devm_kzalloc(bpmp->dev, sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; + np = of_parse_phandle(bpmp->dev->of_node, "memory-region", 0); + if (!np) + return -ENODEV; - bpmp->priv = priv; - priv->parent = bpmp; + err = of_address_to_resource(np, 0, &res); + if (err < 0) { + dev_warn(bpmp->dev, "failed to parse memory region: %d\n", err); + return err; + } + + size = resource_size(&res); + + if (size < SZ_8K) { + dev_warn(bpmp->dev, "DRAM region must be larger than 8 KiB\n"); + return -EINVAL; + } + + priv->tx.phys = res.start; + priv->rx.phys = res.start + SZ_4K; + + priv->tx.dram = devm_memremap(bpmp->dev, priv->tx.phys, size, + MEMREMAP_WC); + if (IS_ERR(priv->tx.dram)) { + err = PTR_ERR(priv->tx.dram); + dev_warn(bpmp->dev, "failed to map DRAM region: %d\n", err); + return err; + } + + priv->rx.dram = priv->tx.dram + SZ_4K; + + return 0; +} + +static int tegra186_bpmp_sram_init(struct tegra_bpmp *bpmp) +{ + struct tegra186_bpmp *priv = bpmp->priv; + int err; priv->tx.pool = of_gen_pool_get(bpmp->dev->of_node, "shmem", 0); if (!priv->tx.pool) { @@ -177,8 +241,9 @@ static int tegra186_bpmp_init(struct tegra_bpmp *bpmp) return -EPROBE_DEFER; } - priv->tx.virt = (void __iomem *)gen_pool_dma_alloc(priv->tx.pool, 4096, &priv->tx.phys); - if (!priv->tx.virt) { + priv->tx.sram = (void __iomem *)gen_pool_dma_alloc(priv->tx.pool, 4096, + &priv->tx.phys); + if (!priv->tx.sram) { dev_err(bpmp->dev, "failed to allocate from TX pool\n"); return -ENOMEM; } @@ -190,22 +255,45 @@ static int tegra186_bpmp_init(struct tegra_bpmp *bpmp) goto free_tx; } - priv->rx.virt = (void __iomem *)gen_pool_dma_alloc(priv->rx.pool, 4096, &priv->rx.phys); - if (!priv->rx.virt) { + priv->rx.sram = (void __iomem *)gen_pool_dma_alloc(priv->rx.pool, 4096, + &priv->rx.phys); + if (!priv->rx.sram) { dev_err(bpmp->dev, "failed to allocate from RX pool\n"); err = -ENOMEM; goto free_tx; } + return 0; + +free_tx: + gen_pool_free(priv->tx.pool, (unsigned long)priv->tx.sram, 4096); + + return err; +} + +static int tegra186_bpmp_setup_channels(struct tegra_bpmp *bpmp) +{ + unsigned int i; + int err; + + err = tegra186_bpmp_dram_init(bpmp); + if (err == -ENODEV) { + err = tegra186_bpmp_sram_init(bpmp); + if (err < 0) + return err; + } + err = tegra186_bpmp_channel_init(bpmp->tx_channel, bpmp, bpmp->soc->channels.cpu_tx.offset); if (err < 0) - goto free_rx; + return err; err = tegra186_bpmp_channel_init(bpmp->rx_channel, bpmp, bpmp->soc->channels.cpu_rx.offset); - if (err < 0) - goto cleanup_tx_channel; + if (err < 0) { + tegra186_bpmp_channel_cleanup(bpmp->tx_channel); + return err; + } for (i = 0; i < bpmp->threaded.count; i++) { unsigned int index = bpmp->soc->channels.thread.offset + i; @@ -213,9 +301,43 @@ static int tegra186_bpmp_init(struct tegra_bpmp *bpmp) err = tegra186_bpmp_channel_init(&bpmp->threaded_channels[i], bpmp, index); if (err < 0) - goto cleanup_channels; + break; } + if (err < 0) + tegra186_bpmp_teardown_channels(bpmp); + + return err; +} + +static void tegra186_bpmp_reset_channels(struct tegra_bpmp *bpmp) +{ + unsigned int i; + + /* reset message channels */ + tegra186_bpmp_channel_reset(bpmp->tx_channel); + tegra186_bpmp_channel_reset(bpmp->rx_channel); + + for (i = 0; i < bpmp->threaded.count; i++) + tegra186_bpmp_channel_reset(&bpmp->threaded_channels[i]); +} + +static int tegra186_bpmp_init(struct tegra_bpmp *bpmp) +{ + struct tegra186_bpmp *priv; + int err; + + priv = devm_kzalloc(bpmp->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->parent = bpmp; + bpmp->priv = priv; + + err = tegra186_bpmp_setup_channels(bpmp); + if (err < 0) + return err; + /* mbox registration */ priv->mbox.client.dev = bpmp->dev; priv->mbox.client.rx_callback = mbox_handle_rx; @@ -226,63 +348,27 @@ static int tegra186_bpmp_init(struct tegra_bpmp *bpmp) if (IS_ERR(priv->mbox.channel)) { err = PTR_ERR(priv->mbox.channel); dev_err(bpmp->dev, "failed to get HSP mailbox: %d\n", err); - goto cleanup_channels; + tegra186_bpmp_teardown_channels(bpmp); + return err; } - tegra186_bpmp_channel_reset(bpmp->tx_channel); - tegra186_bpmp_channel_reset(bpmp->rx_channel); - - for (i = 0; i < bpmp->threaded.count; i++) - tegra186_bpmp_channel_reset(&bpmp->threaded_channels[i]); + tegra186_bpmp_reset_channels(bpmp); return 0; - -cleanup_channels: - for (i = 0; i < bpmp->threaded.count; i++) { - if (!bpmp->threaded_channels[i].bpmp) - continue; - - tegra186_bpmp_channel_cleanup(&bpmp->threaded_channels[i]); - } - - tegra186_bpmp_channel_cleanup(bpmp->rx_channel); -cleanup_tx_channel: - tegra186_bpmp_channel_cleanup(bpmp->tx_channel); -free_rx: - gen_pool_free(priv->rx.pool, (unsigned long)priv->rx.virt, 4096); -free_tx: - gen_pool_free(priv->tx.pool, (unsigned long)priv->tx.virt, 4096); - - return err; } static void tegra186_bpmp_deinit(struct tegra_bpmp *bpmp) { struct tegra186_bpmp *priv = bpmp->priv; - unsigned int i; mbox_free_channel(priv->mbox.channel); - for (i = 0; i < bpmp->threaded.count; i++) - tegra186_bpmp_channel_cleanup(&bpmp->threaded_channels[i]); - - tegra186_bpmp_channel_cleanup(bpmp->rx_channel); - tegra186_bpmp_channel_cleanup(bpmp->tx_channel); - - gen_pool_free(priv->rx.pool, (unsigned long)priv->rx.virt, 4096); - gen_pool_free(priv->tx.pool, (unsigned long)priv->tx.virt, 4096); + tegra186_bpmp_teardown_channels(bpmp); } static int tegra186_bpmp_resume(struct tegra_bpmp *bpmp) { - unsigned int i; - - /* reset message channels */ - tegra186_bpmp_channel_reset(bpmp->tx_channel); - tegra186_bpmp_channel_reset(bpmp->rx_channel); - - for (i = 0; i < bpmp->threaded.count; i++) - tegra186_bpmp_channel_reset(&bpmp->threaded_channels[i]); + tegra186_bpmp_reset_channels(bpmp); return 0; } diff --git a/drivers/firmware/tegra/bpmp.c b/drivers/firmware/tegra/bpmp.c index 8b5e5daa9fae346ce42ea2fb69978364ae87ab91..17bd3590aaa24baffef11ed831db0d978093d4b3 100644 --- a/drivers/firmware/tegra/bpmp.c +++ b/drivers/firmware/tegra/bpmp.c @@ -735,6 +735,8 @@ static int tegra_bpmp_probe(struct platform_device *pdev) if (!bpmp->threaded_channels) return -ENOMEM; + platform_set_drvdata(pdev, bpmp); + err = bpmp->soc->ops->init(bpmp); if (err < 0) return err; @@ -758,8 +760,6 @@ static int tegra_bpmp_probe(struct platform_device *pdev) dev_info(&pdev->dev, "firmware: %.*s\n", (int)sizeof(tag), tag); - platform_set_drvdata(pdev, bpmp); - err = of_platform_default_populate(pdev->dev.of_node, NULL, &pdev->dev); if (err < 0) goto free_mrq; diff --git a/drivers/firmware/xilinx/zynqmp-debug.c b/drivers/firmware/xilinx/zynqmp-debug.c index 99606b34975e93a6719d2ff565f275b32396e900..8528850af889265c16614bcac5219a41565db0da 100644 --- a/drivers/firmware/xilinx/zynqmp-debug.c +++ b/drivers/firmware/xilinx/zynqmp-debug.c @@ -4,7 +4,7 @@ * * Copyright (C) 2014-2018 Xilinx, Inc. * - * Michal Simek + * Michal Simek * Davorin Mista * Jolly Shah * Rajan Vaja diff --git a/drivers/firmware/xilinx/zynqmp-debug.h b/drivers/firmware/xilinx/zynqmp-debug.h index 9929f8b433f50678f7b71dfd4ff0a459cd0a81af..e1515a93e9e99b1f2dd79d86d35722e83545960f 100644 --- a/drivers/firmware/xilinx/zynqmp-debug.h +++ b/drivers/firmware/xilinx/zynqmp-debug.h @@ -4,7 +4,7 @@ * * Copyright (C) 2014-2018 Xilinx * - * Michal Simek + * Michal Simek * Davorin Mista * Jolly Shah * Rajan Vaja diff --git a/drivers/firmware/xilinx/zynqmp.c b/drivers/firmware/xilinx/zynqmp.c index a736db4a582574c315585996c2d54cc8fcf80cbb..f8c4eb2b43f8d122ca7159a97602adbb43d6d0d1 100644 --- a/drivers/firmware/xilinx/zynqmp.c +++ b/drivers/firmware/xilinx/zynqmp.c @@ -4,7 +4,7 @@ * * Copyright (C) 2014-2022 Xilinx, Inc. * - * Michal Simek + * Michal Simek * Davorin Mista * Jolly Shah * Rajan Vaja @@ -942,8 +942,16 @@ EXPORT_SYMBOL_GPL(zynqmp_pm_reset_get_status); */ int zynqmp_pm_fpga_load(const u64 address, const u32 size, const u32 flags) { - return zynqmp_pm_invoke_fn(PM_FPGA_LOAD, lower_32_bits(address), - upper_32_bits(address), size, flags, NULL); + u32 ret_payload[PAYLOAD_ARG_CNT]; + int ret; + + ret = zynqmp_pm_invoke_fn(PM_FPGA_LOAD, lower_32_bits(address), + upper_32_bits(address), size, flags, + ret_payload); + if (ret_payload[0]) + return -ret_payload[0]; + + return ret; } EXPORT_SYMBOL_GPL(zynqmp_pm_fpga_load); diff --git a/drivers/fpga/dfl-fme-main.c b/drivers/fpga/dfl-fme-main.c index 77ea04d4edbef52cbe272c500448924e5d1785d9..bcb5d34b3b820c7ba8e92011c2d6898384d76889 100644 --- a/drivers/fpga/dfl-fme-main.c +++ b/drivers/fpga/dfl-fme-main.c @@ -265,7 +265,7 @@ static const struct hwmon_ops thermal_hwmon_ops = { .read = thermal_hwmon_read, }; -static const struct hwmon_channel_info *thermal_hwmon_info[] = { +static const struct hwmon_channel_info * const thermal_hwmon_info[] = { HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT | HWMON_T_EMERGENCY | HWMON_T_MAX | HWMON_T_MAX_ALARM | HWMON_T_CRIT | HWMON_T_CRIT_ALARM), @@ -465,7 +465,7 @@ static const struct hwmon_ops power_hwmon_ops = { .write = power_hwmon_write, }; -static const struct hwmon_channel_info *power_hwmon_info[] = { +static const struct hwmon_channel_info * const power_hwmon_info[] = { HWMON_CHANNEL_INFO(power, HWMON_P_INPUT | HWMON_P_MAX | HWMON_P_MAX_ALARM | HWMON_P_CRIT | HWMON_P_CRIT_ALARM), diff --git a/drivers/fpga/intel-m10-bmc-sec-update.c b/drivers/fpga/intel-m10-bmc-sec-update.c index d7e2f9f461bcab3bd196699076ba47e660f82719..31af2e08c825fa716606faf5f4ecc03b015a2b6f 100644 --- a/drivers/fpga/intel-m10-bmc-sec-update.c +++ b/drivers/fpga/intel-m10-bmc-sec-update.c @@ -376,12 +376,11 @@ static enum fw_upload_err rsu_update_init(struct m10bmc_sec *sec) u32 doorbell_reg, progress, status; int ret, err; - ret = regmap_update_bits(sec->m10bmc->regmap, - csr_map->base + csr_map->doorbell, - DRBL_RSU_REQUEST | DRBL_HOST_STATUS, - DRBL_RSU_REQUEST | - FIELD_PREP(DRBL_HOST_STATUS, - HOST_STATUS_IDLE)); + ret = m10bmc_sys_update_bits(sec->m10bmc, csr_map->doorbell, + DRBL_RSU_REQUEST | DRBL_HOST_STATUS, + DRBL_RSU_REQUEST | + FIELD_PREP(DRBL_HOST_STATUS, + HOST_STATUS_IDLE)); if (ret) return FW_UPLOAD_ERR_RW_ERROR; @@ -450,11 +449,10 @@ static enum fw_upload_err rsu_send_data(struct m10bmc_sec *sec) u32 doorbell_reg, status; int ret; - ret = regmap_update_bits(sec->m10bmc->regmap, - csr_map->base + csr_map->doorbell, - DRBL_HOST_STATUS, - FIELD_PREP(DRBL_HOST_STATUS, - HOST_STATUS_WRITE_DONE)); + ret = m10bmc_sys_update_bits(sec->m10bmc, csr_map->doorbell, + DRBL_HOST_STATUS, + FIELD_PREP(DRBL_HOST_STATUS, + HOST_STATUS_WRITE_DONE)); if (ret) return FW_UPLOAD_ERR_RW_ERROR; @@ -517,11 +515,10 @@ static enum fw_upload_err rsu_cancel(struct m10bmc_sec *sec) if (rsu_prog(doorbell) != RSU_PROG_READY) return FW_UPLOAD_ERR_BUSY; - ret = regmap_update_bits(sec->m10bmc->regmap, - csr_map->base + csr_map->doorbell, - DRBL_HOST_STATUS, - FIELD_PREP(DRBL_HOST_STATUS, - HOST_STATUS_ABORT_RSU)); + ret = m10bmc_sys_update_bits(sec->m10bmc, csr_map->doorbell, + DRBL_HOST_STATUS, + FIELD_PREP(DRBL_HOST_STATUS, + HOST_STATUS_ABORT_RSU)); if (ret) return FW_UPLOAD_ERR_RW_ERROR; @@ -547,21 +544,28 @@ static enum fw_upload_err m10bmc_sec_prepare(struct fw_upload *fwl, if (ret != FW_UPLOAD_ERR_NONE) goto unlock_flash; + m10bmc_fw_state_set(sec->m10bmc, M10BMC_FW_STATE_SEC_UPDATE_PREPARE); + ret = rsu_update_init(sec); if (ret != FW_UPLOAD_ERR_NONE) - goto unlock_flash; + goto fw_state_exit; ret = rsu_prog_ready(sec); if (ret != FW_UPLOAD_ERR_NONE) - goto unlock_flash; + goto fw_state_exit; if (sec->cancel_request) { ret = rsu_cancel(sec); - goto unlock_flash; + goto fw_state_exit; } + m10bmc_fw_state_set(sec->m10bmc, M10BMC_FW_STATE_SEC_UPDATE_WRITE); + return FW_UPLOAD_ERR_NONE; +fw_state_exit: + m10bmc_fw_state_set(sec->m10bmc, M10BMC_FW_STATE_NORMAL); + unlock_flash: if (sec->m10bmc->flash_bulk_ops) sec->m10bmc->flash_bulk_ops->unlock_write(sec->m10bmc); @@ -610,6 +614,8 @@ static enum fw_upload_err m10bmc_sec_poll_complete(struct fw_upload *fwl) if (sec->cancel_request) return rsu_cancel(sec); + m10bmc_fw_state_set(sec->m10bmc, M10BMC_FW_STATE_SEC_UPDATE_PROGRAM); + result = rsu_send_data(sec); if (result != FW_UPLOAD_ERR_NONE) return result; @@ -653,6 +659,8 @@ static void m10bmc_sec_cleanup(struct fw_upload *fwl) (void)rsu_cancel(sec); + m10bmc_fw_state_set(sec->m10bmc, M10BMC_FW_STATE_NORMAL); + if (sec->m10bmc->flash_bulk_ops) sec->m10bmc->flash_bulk_ops->unlock_write(sec->m10bmc); } @@ -764,3 +772,4 @@ module_platform_driver(intel_m10bmc_sec_driver); MODULE_AUTHOR("Intel Corporation"); MODULE_DESCRIPTION("Intel MAX10 BMC Secure Update"); MODULE_LICENSE("GPL"); +MODULE_IMPORT_NS(INTEL_M10_BMC_CORE); diff --git a/drivers/fpga/zynq-fpga.c b/drivers/fpga/zynq-fpga.c index ae0da361e6c6282448995155fa2aa6e8cd5f11be..f8214cae9b6eca7bdd7a49d24ee89bca3d6c7ccd 100644 --- a/drivers/fpga/zynq-fpga.c +++ b/drivers/fpga/zynq-fpga.c @@ -493,15 +493,15 @@ static int zynq_fpga_ops_write_complete(struct fpga_manager *mgr, if (err) return err; - /* Release 'PR' control back to the ICAP */ - zynq_fpga_write(priv, CTRL_OFFSET, - zynq_fpga_read(priv, CTRL_OFFSET) & ~CTRL_PCAP_PR_MASK); - err = zynq_fpga_poll_timeout(priv, INT_STS_OFFSET, intr_status, intr_status & IXR_PCFG_DONE_MASK, INIT_POLL_DELAY, INIT_POLL_TIMEOUT); + /* Release 'PR' control back to the ICAP */ + zynq_fpga_write(priv, CTRL_OFFSET, + zynq_fpga_read(priv, CTRL_OFFSET) & ~CTRL_PCAP_PR_MASK); + clk_disable(priv->clk); if (err) diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index f45c6a36551c75533a92d6c6bf5897162b9ee5e8..e382dfebad7c6551861ee064525e1cd148f5446e 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -704,18 +704,6 @@ config GPIO_VISCONTI help Say yes here to support GPIO on Tohisba Visconti. -config GPIO_VX855 - tristate "VIA VX855/VX875 GPIO" - depends on (X86 || COMPILE_TEST) && PCI - select MFD_CORE - select MFD_VX855 - help - Support access to the VX855/VX875 GPIO lines through the GPIO library. - - This driver provides common support for accessing the device. - Additional drivers must be enabled in order to use the - functionality of the device. - config GPIO_WCD934X tristate "Qualcomm Technologies Inc WCD9340/WCD9341 GPIO controller driver" depends on MFD_WCD934X && OF_GPIO @@ -835,7 +823,19 @@ config GPIO_IDT3243X endmenu menu "Port-mapped I/O GPIO drivers" - depends on X86 # Unconditional I/O space access + depends on X86 && HAS_IOPORT # I/O space access + +config GPIO_VX855 + tristate "VIA VX855/VX875 GPIO" + depends on PCI + select MFD_CORE + select MFD_VX855 + help + Support access to the VX855/VX875 GPIO lines through the GPIO library. + + This driver provides common support for accessing the device. + Additional drivers must be enabled in order to use the + functionality of the device. config GPIO_I8255 tristate @@ -1440,6 +1440,22 @@ config GPIO_TPS65218 Select this option to enable GPIO driver for the TPS65218 chip family. +config GPIO_TPS65219 + tristate "TPS65219 GPIO" + depends on MFD_TPS65219 + default MFD_TPS65219 + help + Select this option to enable GPIO driver for the TPS65219 chip + family. + GPIO0 is statically configured as either input or output prior to + Linux boot. It is used for MULTI_DEVICE_ENABLE function. This setting + is statically configured by NVM. GPIO0 can't be used as a generic + GPIO. It's either a GPO when MULTI_DEVICE_EN=0 or a GPI when + MULTI_DEVICE_EN=1. + + This driver can also be built as a module. If so, the module will be + called gpio_tps65219. + config GPIO_TPS6586X bool "TPS6586X GPIO" depends on MFD_TPS6586X @@ -1583,6 +1599,19 @@ config GPIO_MLXBF2 help Say Y here if you want GPIO support on Mellanox BlueField 2 SoC. +config GPIO_MLXBF3 + tristate "Mellanox BlueField 3 SoC GPIO" + depends on (MELLANOX_PLATFORM && ARM64) || COMPILE_TEST + select GPIO_GENERIC + select GPIOLIB_IRQCHIP + help + Say Y if you want GPIO support on Mellanox BlueField 3 SoC. + This GPIO controller supports interrupt handling and enables the + manipulation of certain GPIO pins. + This controller should be used in parallel with pinctrl-mlxbf3 to + control the desired GPIOs. + This driver can also be built as a module called mlxbf3-gpio. + config GPIO_ML_IOH tristate "OKI SEMICONDUCTOR ML7213 IOH GPIO support" depends on X86 || COMPILE_TEST diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 20036af3acb1db364ebfeb50790b3e76a2c713d6..c3ac51d47aa94cd5c3d97e91b476fa7793ace6fd 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -104,6 +104,7 @@ obj-$(CONFIG_GPIO_MERRIFIELD) += gpio-merrifield.o obj-$(CONFIG_GPIO_ML_IOH) += gpio-ml-ioh.o obj-$(CONFIG_GPIO_MLXBF) += gpio-mlxbf.o obj-$(CONFIG_GPIO_MLXBF2) += gpio-mlxbf2.o +obj-$(CONFIG_GPIO_MLXBF3) += gpio-mlxbf3.o obj-$(CONFIG_GPIO_MM_LANTIQ) += gpio-mm-lantiq.o obj-$(CONFIG_GPIO_MOCKUP) += gpio-mockup.o obj-$(CONFIG_GPIO_MOXTET) += gpio-moxtet.o @@ -160,6 +161,7 @@ obj-$(CONFIG_GPIO_TN48M_CPLD) += gpio-tn48m.o obj-$(CONFIG_GPIO_TPIC2810) += gpio-tpic2810.o obj-$(CONFIG_GPIO_TPS65086) += gpio-tps65086.o obj-$(CONFIG_GPIO_TPS65218) += gpio-tps65218.o +obj-$(CONFIG_GPIO_TPS65219) += gpio-tps65219.o obj-$(CONFIG_GPIO_TPS6586X) += gpio-tps6586x.o obj-$(CONFIG_GPIO_TPS65910) += gpio-tps65910.o obj-$(CONFIG_GPIO_TPS65912) += gpio-tps65912.o diff --git a/drivers/gpio/gpio-104-dio-48e.c b/drivers/gpio/gpio-104-dio-48e.c index f2253fd5ab4bbf0ad1fbffb44b0802d2330df24a..8ff5f4ff5958bc1a33d69a1405934ecca9e1590d 100644 --- a/drivers/gpio/gpio-104-dio-48e.c +++ b/drivers/gpio/gpio-104-dio-48e.c @@ -100,13 +100,23 @@ static const struct regmap_irq dio48e_regmap_irqs[] = { DIO48E_REGMAP_IRQ(0), DIO48E_REGMAP_IRQ(1), }; -static int dio48e_handle_mask_sync(struct regmap *const map, const int index, +/** + * struct dio48e_gpio - GPIO device private data structure + * @map: Regmap for the device + * @irq_mask: Current IRQ mask state on the device + */ +struct dio48e_gpio { + struct regmap *map; + unsigned int irq_mask; +}; + +static int dio48e_handle_mask_sync(const int index, const unsigned int mask_buf_def, const unsigned int mask_buf, void *const irq_drv_data) { - unsigned int *const irq_mask = irq_drv_data; - const unsigned int prev_mask = *irq_mask; + struct dio48e_gpio *const dio48egpio = irq_drv_data; + const unsigned int prev_mask = dio48egpio->irq_mask; int err; unsigned int val; @@ -115,19 +125,19 @@ static int dio48e_handle_mask_sync(struct regmap *const map, const int index, return 0; /* remember the current mask for the next mask sync */ - *irq_mask = mask_buf; + dio48egpio->irq_mask = mask_buf; /* if all previously masked, enable interrupts when unmasking */ if (prev_mask == mask_buf_def) { - err = regmap_write(map, DIO48E_CLEAR_INTERRUPT, 0x00); + err = regmap_write(dio48egpio->map, DIO48E_CLEAR_INTERRUPT, 0x00); if (err) return err; - return regmap_write(map, DIO48E_ENABLE_INTERRUPT, 0x00); + return regmap_write(dio48egpio->map, DIO48E_ENABLE_INTERRUPT, 0x00); } /* if all are currently masked, disable interrupts */ if (mask_buf == mask_buf_def) - return regmap_read(map, DIO48E_DISABLE_INTERRUPT, &val); + return regmap_read(dio48egpio->map, DIO48E_DISABLE_INTERRUPT, &val); return 0; } @@ -168,7 +178,7 @@ static int dio48e_probe(struct device *dev, unsigned int id) struct regmap *map; int err; struct regmap_irq_chip *chip; - unsigned int irq_mask; + struct dio48e_gpio *dio48egpio; struct regmap_irq_chip_data *chip_data; if (!devm_request_region(dev, base[id], DIO48E_EXTENT, name)) { @@ -186,12 +196,14 @@ static int dio48e_probe(struct device *dev, unsigned int id) return dev_err_probe(dev, PTR_ERR(map), "Unable to initialize register map\n"); - chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL); - if (!chip) + dio48egpio = devm_kzalloc(dev, sizeof(*dio48egpio), GFP_KERNEL); + if (!dio48egpio) return -ENOMEM; - chip->irq_drv_data = devm_kzalloc(dev, sizeof(irq_mask), GFP_KERNEL); - if (!chip->irq_drv_data) + dio48egpio->map = map; + + chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL); + if (!chip) return -ENOMEM; chip->name = name; @@ -202,6 +214,7 @@ static int dio48e_probe(struct device *dev, unsigned int id) chip->irqs = dio48e_regmap_irqs; chip->num_irqs = ARRAY_SIZE(dio48e_regmap_irqs); chip->handle_mask_sync = dio48e_handle_mask_sync; + chip->irq_drv_data = dio48egpio; /* Initialize to prevent spurious interrupts before we're ready */ err = dio48e_irq_init_hw(map); diff --git a/drivers/gpio/gpio-adnp.c b/drivers/gpio/gpio-adnp.c index 9b01c391efce4657553df0e72da869d0f31ebe94..6dafab0cf964ed6250d4d956b150daec20ff7d16 100644 --- a/drivers/gpio/gpio-adnp.c +++ b/drivers/gpio/gpio-adnp.c @@ -535,7 +535,7 @@ static struct i2c_driver adnp_i2c_driver = { .name = "gpio-adnp", .of_match_table = adnp_of_match, }, - .probe_new = adnp_i2c_probe, + .probe = adnp_i2c_probe, .id_table = adnp_i2c_id, }; module_i2c_driver(adnp_i2c_driver); diff --git a/drivers/gpio/gpio-aggregator.c b/drivers/gpio/gpio-aggregator.c index 20a686f12df7f9857e31871f15db90c2bf9a7ce4..38e0fff9afe7225b916f5a8b5b998a9ba8f42a37 100644 --- a/drivers/gpio/gpio-aggregator.c +++ b/drivers/gpio/gpio-aggregator.c @@ -10,12 +10,15 @@ #include #include #include +#include #include #include +#include #include #include #include #include +#include #include #include #include @@ -239,6 +242,11 @@ static void __exit gpio_aggregator_remove_all(void) * GPIO Forwarder */ +struct gpiochip_fwd_timing { + u32 ramp_up_us; + u32 ramp_down_us; +}; + struct gpiochip_fwd { struct gpio_chip chip; struct gpio_desc **descs; @@ -246,6 +254,7 @@ struct gpiochip_fwd { struct mutex mlock; /* protects tmp[] if can_sleep */ spinlock_t slock; /* protects tmp[] if !can_sleep */ }; + struct gpiochip_fwd_timing *delay_timings; unsigned long tmp[]; /* values and descs for multiple ops */ }; @@ -330,6 +339,27 @@ static int gpio_fwd_get_multiple_locked(struct gpio_chip *chip, return error; } +static void gpio_fwd_delay(struct gpio_chip *chip, unsigned int offset, int value) +{ + struct gpiochip_fwd *fwd = gpiochip_get_data(chip); + const struct gpiochip_fwd_timing *delay_timings; + bool is_active_low = gpiod_is_active_low(fwd->descs[offset]); + u32 delay_us; + + delay_timings = &fwd->delay_timings[offset]; + if ((!is_active_low && value) || (is_active_low && !value)) + delay_us = delay_timings->ramp_up_us; + else + delay_us = delay_timings->ramp_down_us; + if (!delay_us) + return; + + if (chip->can_sleep) + fsleep(delay_us); + else + udelay(delay_us); +} + static void gpio_fwd_set(struct gpio_chip *chip, unsigned int offset, int value) { struct gpiochip_fwd *fwd = gpiochip_get_data(chip); @@ -338,6 +368,9 @@ static void gpio_fwd_set(struct gpio_chip *chip, unsigned int offset, int value) gpiod_set_value_cansleep(fwd->descs[offset], value); else gpiod_set_value(fwd->descs[offset], value); + + if (fwd->delay_timings) + gpio_fwd_delay(chip, offset, value); } static void gpio_fwd_set_multiple(struct gpiochip_fwd *fwd, unsigned long *mask, @@ -390,6 +423,59 @@ static int gpio_fwd_to_irq(struct gpio_chip *chip, unsigned int offset) return gpiod_to_irq(fwd->descs[offset]); } +/* + * The GPIO delay provides a way to configure platform specific delays + * for the GPIO ramp-up or ramp-down delays. This can serve the following + * purposes: + * - Open-drain output using an RC filter + */ +#define FWD_FEATURE_DELAY BIT(0) + +#ifdef CONFIG_OF_GPIO +static int gpiochip_fwd_delay_of_xlate(struct gpio_chip *chip, + const struct of_phandle_args *gpiospec, + u32 *flags) +{ + struct gpiochip_fwd *fwd = gpiochip_get_data(chip); + struct gpiochip_fwd_timing *timings; + u32 line; + + if (gpiospec->args_count != chip->of_gpio_n_cells) + return -EINVAL; + + line = gpiospec->args[0]; + if (line >= chip->ngpio) + return -EINVAL; + + timings = &fwd->delay_timings[line]; + timings->ramp_up_us = gpiospec->args[1]; + timings->ramp_down_us = gpiospec->args[2]; + + return line; +} + +static int gpiochip_fwd_setup_delay_line(struct device *dev, struct gpio_chip *chip, + struct gpiochip_fwd *fwd) +{ + fwd->delay_timings = devm_kcalloc(dev, chip->ngpio, + sizeof(*fwd->delay_timings), + GFP_KERNEL); + if (!fwd->delay_timings) + return -ENOMEM; + + chip->of_xlate = gpiochip_fwd_delay_of_xlate; + chip->of_gpio_n_cells = 3; + + return 0; +} +#else +static int gpiochip_fwd_setup_delay_line(struct device *dev, struct gpio_chip *chip, + struct gpiochip_fwd *fwd) +{ + return 0; +} +#endif /* !CONFIG_OF_GPIO */ + /** * gpiochip_fwd_create() - Create a new GPIO forwarder * @dev: Parent device pointer @@ -397,6 +483,7 @@ static int gpio_fwd_to_irq(struct gpio_chip *chip, unsigned int offset) * @descs: Array containing the GPIO descriptors to forward to. * This array must contain @ngpios entries, and must not be deallocated * before the forwarder has been destroyed again. + * @features: Bitwise ORed features as defined with FWD_FEATURE_*. * * This function creates a new gpiochip, which forwards all GPIO operations to * the passed GPIO descriptors. @@ -406,7 +493,8 @@ static int gpio_fwd_to_irq(struct gpio_chip *chip, unsigned int offset) */ static struct gpiochip_fwd *gpiochip_fwd_create(struct device *dev, unsigned int ngpios, - struct gpio_desc *descs[]) + struct gpio_desc *descs[], + unsigned long features) { const char *label = dev_name(dev); struct gpiochip_fwd *fwd; @@ -459,6 +547,12 @@ static struct gpiochip_fwd *gpiochip_fwd_create(struct device *dev, else spin_lock_init(&fwd->slock); + if (features & FWD_FEATURE_DELAY) { + error = gpiochip_fwd_setup_delay_line(dev, chip, fwd); + if (error) + return ERR_PTR(error); + } + error = devm_gpiochip_add_data(dev, chip, fwd); if (error) return ERR_PTR(error); @@ -476,6 +570,7 @@ static int gpio_aggregator_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct gpio_desc **descs; struct gpiochip_fwd *fwd; + unsigned long features; int i, n; n = gpiod_count(dev, NULL); @@ -492,7 +587,8 @@ static int gpio_aggregator_probe(struct platform_device *pdev) return PTR_ERR(descs[i]); } - fwd = gpiochip_fwd_create(dev, n, descs); + features = (uintptr_t)device_get_match_data(dev); + fwd = gpiochip_fwd_create(dev, n, descs, features); if (IS_ERR(fwd)) return PTR_ERR(fwd); @@ -500,23 +596,25 @@ static int gpio_aggregator_probe(struct platform_device *pdev) return 0; } -#ifdef CONFIG_OF static const struct of_device_id gpio_aggregator_dt_ids[] = { + { + .compatible = "gpio-delay", + .data = (void *)FWD_FEATURE_DELAY, + }, /* * Add GPIO-operated devices controlled from userspace below, - * or use "driver_override" in sysfs + * or use "driver_override" in sysfs. */ {} }; MODULE_DEVICE_TABLE(of, gpio_aggregator_dt_ids); -#endif static struct platform_driver gpio_aggregator_driver = { .probe = gpio_aggregator_probe, .driver = { .name = DRV_NAME, .groups = gpio_aggregator_groups, - .of_match_table = of_match_ptr(gpio_aggregator_dt_ids), + .of_match_table = gpio_aggregator_dt_ids, }, }; diff --git a/drivers/gpio/gpio-brcmstb.c b/drivers/gpio/gpio-brcmstb.c index c55b35da61a0f57fb0b07dc0f900a0743e69ee57..6566517fe0d881d54ba49efe7d7914063838742b 100644 --- a/drivers/gpio/gpio-brcmstb.c +++ b/drivers/gpio/gpio-brcmstb.c @@ -609,8 +609,7 @@ static int brcmstb_gpio_probe(struct platform_device *pdev) platform_set_drvdata(pdev, priv); INIT_LIST_HEAD(&priv->bank_list); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - reg_base = devm_ioremap_resource(dev, res); + reg_base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); if (IS_ERR(reg_base)) return PTR_ERR(reg_base); diff --git a/drivers/gpio/gpio-davinci.c b/drivers/gpio/gpio-davinci.c index aaaf61dc26321cf8a63aeecbc3108505ba7a65c3..fff510d86e31144a0a2210bd93d0348eb020c670 100644 --- a/drivers/gpio/gpio-davinci.c +++ b/drivers/gpio/gpio-davinci.c @@ -692,7 +692,7 @@ static int davinci_gpio_resume(struct device *dev) return 0; } -DEFINE_SIMPLE_DEV_PM_OPS(davinci_gpio_dev_pm_ops, davinci_gpio_suspend, +static DEFINE_SIMPLE_DEV_PM_OPS(davinci_gpio_dev_pm_ops, davinci_gpio_suspend, davinci_gpio_resume); static const struct of_device_id davinci_gpio_ids[] = { @@ -712,7 +712,7 @@ static struct platform_driver davinci_gpio_driver = { }, }; -/** +/* * GPIO driver registration needs to be done before machine_init functions * access GPIO. Hence davinci_gpio_drv_reg() is a postcore_initcall. */ diff --git a/drivers/gpio/gpio-fxl6408.c b/drivers/gpio/gpio-fxl6408.c index 208fa851e82a17567ffcd7a3f24d7235a6922cdb..c14b5cc5e5192dd6122777ab32c89869b47e47c5 100644 --- a/drivers/gpio/gpio-fxl6408.c +++ b/drivers/gpio/gpio-fxl6408.c @@ -148,7 +148,7 @@ static struct i2c_driver fxl6408_driver = { .name = "fxl6408", .of_match_table = fxl6408_dt_ids, }, - .probe_new = fxl6408_probe, + .probe = fxl6408_probe, .id_table = fxl6408_id, }; module_i2c_driver(fxl6408_driver); diff --git a/drivers/gpio/gpio-gw-pld.c b/drivers/gpio/gpio-gw-pld.c index 5057fa9ad6108a26f093f24eafbc51e91fd4b5b9..899335da93c78bcb7a04770db97141091a67cb2c 100644 --- a/drivers/gpio/gpio-gw-pld.c +++ b/drivers/gpio/gpio-gw-pld.c @@ -125,7 +125,7 @@ static struct i2c_driver gw_pld_driver = { .name = "gw_pld", .of_match_table = gw_pld_dt_ids, }, - .probe_new = gw_pld_probe, + .probe = gw_pld_probe, .id_table = gw_pld_id, }; module_i2c_driver(gw_pld_driver); diff --git a/drivers/gpio/gpio-ixp4xx.c b/drivers/gpio/gpio-ixp4xx.c index 56656fb519f8553e783998188473c88db9a6e1b1..1e29de1671d465a69c388ca578574122d1e6f4e5 100644 --- a/drivers/gpio/gpio-ixp4xx.c +++ b/drivers/gpio/gpio-ixp4xx.c @@ -199,7 +199,6 @@ static int ixp4xx_gpio_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct device_node *np = dev->of_node; struct irq_domain *parent; - struct resource *res; struct ixp4xx_gpio *g; struct gpio_irq_chip *girq; struct device_node *irq_parent; @@ -210,8 +209,7 @@ static int ixp4xx_gpio_probe(struct platform_device *pdev) return -ENOMEM; g->dev = dev; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - g->base = devm_ioremap_resource(dev, res); + g->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(g->base)) return PTR_ERR(g->base); diff --git a/drivers/gpio/gpio-lpc18xx.c b/drivers/gpio/gpio-lpc18xx.c index d711ae06747eeff69e2a0b9b6972fb9b2bef6427..ed3f653a1dfcc7c02b99d8b8210d6fc28d712fc0 100644 --- a/drivers/gpio/gpio-lpc18xx.c +++ b/drivers/gpio/gpio-lpc18xx.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/gpio/gpio-max7300.c b/drivers/gpio/gpio-max7300.c index cf482f4f0098297a3ab59348082ee051634fdd37..31c2b95321cc20e9c1589ae08f3e27c16f8897f1 100644 --- a/drivers/gpio/gpio-max7300.c +++ b/drivers/gpio/gpio-max7300.c @@ -62,7 +62,7 @@ static struct i2c_driver max7300_driver = { .driver = { .name = "max7300", }, - .probe_new = max7300_probe, + .probe = max7300_probe, .remove = max7300_remove, .id_table = max7300_id, }; diff --git a/drivers/gpio/gpio-max732x.c b/drivers/gpio/gpio-max732x.c index 7f2fde191755aade8a7bdfbb15610bd15c2760bc..fca9ca68e3870f292a49b0fc72022b18d2f67cd5 100644 --- a/drivers/gpio/gpio-max732x.c +++ b/drivers/gpio/gpio-max732x.c @@ -711,7 +711,7 @@ static struct i2c_driver max732x_driver = { .name = "max732x", .of_match_table = of_match_ptr(max732x_of_table), }, - .probe_new = max732x_probe, + .probe = max732x_probe, .id_table = max732x_id, }; diff --git a/drivers/gpio/gpio-mlxbf3.c b/drivers/gpio/gpio-mlxbf3.c new file mode 100644 index 0000000000000000000000000000000000000000..e30cee108986bb7eebc2a113b4ca52c307f556e8 --- /dev/null +++ b/drivers/gpio/gpio-mlxbf3.c @@ -0,0 +1,248 @@ +// SPDX-License-Identifier: GPL-2.0-only or BSD-3-Clause +/* Copyright (C) 2022 NVIDIA CORPORATION & AFFILIATES */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * There are 2 YU GPIO blocks: + * gpio[0]: HOST_GPIO0->HOST_GPIO31 + * gpio[1]: HOST_GPIO32->HOST_GPIO55 + */ +#define MLXBF3_GPIO_MAX_PINS_PER_BLOCK 32 + +/* + * fw_gpio[x] block registers and their offset + */ +#define MLXBF_GPIO_FW_OUTPUT_ENABLE_SET 0x00 +#define MLXBF_GPIO_FW_DATA_OUT_SET 0x04 + +#define MLXBF_GPIO_FW_OUTPUT_ENABLE_CLEAR 0x00 +#define MLXBF_GPIO_FW_DATA_OUT_CLEAR 0x04 + +#define MLXBF_GPIO_CAUSE_RISE_EN 0x00 +#define MLXBF_GPIO_CAUSE_FALL_EN 0x04 +#define MLXBF_GPIO_READ_DATA_IN 0x08 + +#define MLXBF_GPIO_CAUSE_OR_CAUSE_EVTEN0 0x00 +#define MLXBF_GPIO_CAUSE_OR_EVTEN0 0x14 +#define MLXBF_GPIO_CAUSE_OR_CLRCAUSE 0x18 + +struct mlxbf3_gpio_context { + struct gpio_chip gc; + + /* YU GPIO block address */ + void __iomem *gpio_set_io; + void __iomem *gpio_clr_io; + void __iomem *gpio_io; + + /* YU GPIO cause block address */ + void __iomem *gpio_cause_io; +}; + +static void mlxbf3_gpio_irq_enable(struct irq_data *irqd) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd); + struct mlxbf3_gpio_context *gs = gpiochip_get_data(gc); + irq_hw_number_t offset = irqd_to_hwirq(irqd); + unsigned long flags; + u32 val; + + gpiochip_enable_irq(gc, offset); + + raw_spin_lock_irqsave(&gs->gc.bgpio_lock, flags); + writel(BIT(offset), gs->gpio_cause_io + MLXBF_GPIO_CAUSE_OR_CLRCAUSE); + + val = readl(gs->gpio_cause_io + MLXBF_GPIO_CAUSE_OR_EVTEN0); + val |= BIT(offset); + writel(val, gs->gpio_cause_io + MLXBF_GPIO_CAUSE_OR_EVTEN0); + raw_spin_unlock_irqrestore(&gs->gc.bgpio_lock, flags); +} + +static void mlxbf3_gpio_irq_disable(struct irq_data *irqd) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd); + struct mlxbf3_gpio_context *gs = gpiochip_get_data(gc); + irq_hw_number_t offset = irqd_to_hwirq(irqd); + unsigned long flags; + u32 val; + + raw_spin_lock_irqsave(&gs->gc.bgpio_lock, flags); + val = readl(gs->gpio_cause_io + MLXBF_GPIO_CAUSE_OR_EVTEN0); + val &= ~BIT(offset); + writel(val, gs->gpio_cause_io + MLXBF_GPIO_CAUSE_OR_EVTEN0); + raw_spin_unlock_irqrestore(&gs->gc.bgpio_lock, flags); + + gpiochip_disable_irq(gc, offset); +} + +static irqreturn_t mlxbf3_gpio_irq_handler(int irq, void *ptr) +{ + struct mlxbf3_gpio_context *gs = ptr; + struct gpio_chip *gc = &gs->gc; + unsigned long pending; + u32 level; + + pending = readl(gs->gpio_cause_io + MLXBF_GPIO_CAUSE_OR_CAUSE_EVTEN0); + writel(pending, gs->gpio_cause_io + MLXBF_GPIO_CAUSE_OR_CLRCAUSE); + + for_each_set_bit(level, &pending, gc->ngpio) + generic_handle_domain_irq(gc->irq.domain, level); + + return IRQ_RETVAL(pending); +} + +static int +mlxbf3_gpio_irq_set_type(struct irq_data *irqd, unsigned int type) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd); + struct mlxbf3_gpio_context *gs = gpiochip_get_data(gc); + irq_hw_number_t offset = irqd_to_hwirq(irqd); + unsigned long flags; + u32 val; + + raw_spin_lock_irqsave(&gs->gc.bgpio_lock, flags); + + switch (type & IRQ_TYPE_SENSE_MASK) { + case IRQ_TYPE_EDGE_BOTH: + val = readl(gs->gpio_io + MLXBF_GPIO_CAUSE_FALL_EN); + val |= BIT(offset); + writel(val, gs->gpio_io + MLXBF_GPIO_CAUSE_FALL_EN); + val = readl(gs->gpio_io + MLXBF_GPIO_CAUSE_RISE_EN); + val |= BIT(offset); + writel(val, gs->gpio_io + MLXBF_GPIO_CAUSE_RISE_EN); + break; + case IRQ_TYPE_EDGE_RISING: + val = readl(gs->gpio_io + MLXBF_GPIO_CAUSE_RISE_EN); + val |= BIT(offset); + writel(val, gs->gpio_io + MLXBF_GPIO_CAUSE_RISE_EN); + break; + case IRQ_TYPE_EDGE_FALLING: + val = readl(gs->gpio_io + MLXBF_GPIO_CAUSE_FALL_EN); + val |= BIT(offset); + writel(val, gs->gpio_io + MLXBF_GPIO_CAUSE_FALL_EN); + break; + default: + raw_spin_unlock_irqrestore(&gs->gc.bgpio_lock, flags); + return -EINVAL; + } + + raw_spin_unlock_irqrestore(&gs->gc.bgpio_lock, flags); + + irq_set_handler_locked(irqd, handle_edge_irq); + + return 0; +} + +/* This function needs to be defined for handle_edge_irq() */ +static void mlxbf3_gpio_irq_ack(struct irq_data *data) +{ +} + +static const struct irq_chip gpio_mlxbf3_irqchip = { + .name = "MLNXBF33", + .irq_ack = mlxbf3_gpio_irq_ack, + .irq_set_type = mlxbf3_gpio_irq_set_type, + .irq_enable = mlxbf3_gpio_irq_enable, + .irq_disable = mlxbf3_gpio_irq_disable, + .flags = IRQCHIP_IMMUTABLE, + GPIOCHIP_IRQ_RESOURCE_HELPERS, +}; + +static int mlxbf3_gpio_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct mlxbf3_gpio_context *gs; + struct gpio_irq_chip *girq; + struct gpio_chip *gc; + int ret, irq; + + gs = devm_kzalloc(dev, sizeof(*gs), GFP_KERNEL); + if (!gs) + return -ENOMEM; + + gs->gpio_io = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(gs->gpio_io)) + return PTR_ERR(gs->gpio_io); + + gs->gpio_cause_io = devm_platform_ioremap_resource(pdev, 1); + if (IS_ERR(gs->gpio_cause_io)) + return PTR_ERR(gs->gpio_cause_io); + + gs->gpio_set_io = devm_platform_ioremap_resource(pdev, 2); + if (IS_ERR(gs->gpio_set_io)) + return PTR_ERR(gs->gpio_set_io); + + gs->gpio_clr_io = devm_platform_ioremap_resource(pdev, 3); + if (IS_ERR(gs->gpio_clr_io)) + return PTR_ERR(gs->gpio_clr_io); + gc = &gs->gc; + + ret = bgpio_init(gc, dev, 4, + gs->gpio_io + MLXBF_GPIO_READ_DATA_IN, + gs->gpio_set_io + MLXBF_GPIO_FW_DATA_OUT_SET, + gs->gpio_clr_io + MLXBF_GPIO_FW_DATA_OUT_CLEAR, + gs->gpio_set_io + MLXBF_GPIO_FW_OUTPUT_ENABLE_SET, + gs->gpio_clr_io + MLXBF_GPIO_FW_OUTPUT_ENABLE_CLEAR, 0); + + gc->request = gpiochip_generic_request; + gc->free = gpiochip_generic_free; + gc->owner = THIS_MODULE; + + irq = platform_get_irq(pdev, 0); + if (irq >= 0) { + girq = &gs->gc.irq; + gpio_irq_chip_set_chip(girq, &gpio_mlxbf3_irqchip); + girq->default_type = IRQ_TYPE_NONE; + /* This will let us handle the parent IRQ in the driver */ + girq->num_parents = 0; + girq->parents = NULL; + girq->parent_handler = NULL; + girq->handler = handle_bad_irq; + + /* + * Directly request the irq here instead of passing + * a flow-handler because the irq is shared. + */ + ret = devm_request_irq(dev, irq, mlxbf3_gpio_irq_handler, + IRQF_SHARED, dev_name(dev), gs); + if (ret) + return dev_err_probe(dev, ret, "failed to request IRQ"); + } + + platform_set_drvdata(pdev, gs); + + ret = devm_gpiochip_add_data(dev, &gs->gc, gs); + if (ret) + dev_err_probe(dev, ret, "Failed adding memory mapped gpiochip\n"); + + return 0; +} + +static const struct acpi_device_id mlxbf3_gpio_acpi_match[] = { + { "MLNXBF33", 0 }, + {} +}; +MODULE_DEVICE_TABLE(acpi, mlxbf3_gpio_acpi_match); + +static struct platform_driver mlxbf3_gpio_driver = { + .driver = { + .name = "mlxbf3_gpio", + .acpi_match_table = mlxbf3_gpio_acpi_match, + }, + .probe = mlxbf3_gpio_probe, +}; +module_platform_driver(mlxbf3_gpio_driver); + +MODULE_DESCRIPTION("NVIDIA BlueField-3 GPIO Driver"); +MODULE_AUTHOR("Asmaa Mnebhi "); +MODULE_LICENSE("Dual BSD/GPL"); diff --git a/drivers/gpio/gpio-mpc8xxx.c b/drivers/gpio/gpio-mpc8xxx.c index 3eb08cd1fdc0818a89458b5ad72a4761b2b31a9c..5979a36bf754c780515bc55c27a2b1d1bcbf09c7 100644 --- a/drivers/gpio/gpio-mpc8xxx.c +++ b/drivers/gpio/gpio-mpc8xxx.c @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include @@ -375,8 +374,12 @@ static int mpc8xxx_probe(struct platform_device *pdev) if (of_device_is_compatible(np, "fsl,qoriq-gpio") || of_device_is_compatible(np, "fsl,ls1028a-gpio") || of_device_is_compatible(np, "fsl,ls1088a-gpio") || - is_acpi_node(fwnode)) + is_acpi_node(fwnode)) { gc->write_reg(mpc8xxx_gc->regs + GPIO_IBE, 0xffffffff); + /* Also, latch state of GPIOs configured as output by bootloader. */ + gc->bgpio_data = gc->read_reg(mpc8xxx_gc->regs + GPIO_DAT) & + gc->read_reg(mpc8xxx_gc->regs + GPIO_DIR); + } ret = devm_gpiochip_add_data(&pdev->dev, gc, mpc8xxx_gc); if (ret) { diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index 1286b22ef23af608b42a9a8b6b6b539875c90ca4..a806a3c1b80187453a689cf591561438df94b3ac 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -1375,7 +1375,7 @@ static struct i2c_driver pca953x_driver = { .of_match_table = pca953x_dt_ids, .acpi_match_table = pca953x_acpi_ids, }, - .probe_new = pca953x_probe, + .probe = pca953x_probe, .remove = pca953x_remove, .id_table = pca953x_id, }; diff --git a/drivers/gpio/gpio-pca9570.c b/drivers/gpio/gpio-pca9570.c index 6a5a8e593ed555a317e405854b0ae40e2d0ab57f..d8db80ef1293ad05b86ec20d92657a70be1fdbdf 100644 --- a/drivers/gpio/gpio-pca9570.c +++ b/drivers/gpio/gpio-pca9570.c @@ -175,7 +175,7 @@ static struct i2c_driver pca9570_driver = { .name = "pca9570", .of_match_table = pca9570_of_match_table, }, - .probe_new = pca9570_probe, + .probe = pca9570_probe, .id_table = pca9570_id_table, }; module_i2c_driver(pca9570_driver); diff --git a/drivers/gpio/gpio-pcf857x.c b/drivers/gpio/gpio-pcf857x.c index 3de1d3ad7472cbd5d3febd4aaf8f706f24d63fdd..c4c7855484080849915d4ce17dc7271374561609 100644 --- a/drivers/gpio/gpio-pcf857x.c +++ b/drivers/gpio/gpio-pcf857x.c @@ -419,7 +419,7 @@ static struct i2c_driver pcf857x_driver = { .name = "pcf857x", .of_match_table = pcf857x_of_table, }, - .probe_new = pcf857x_probe, + .probe = pcf857x_probe, .shutdown = pcf857x_shutdown, .id_table = pcf857x_id, }; diff --git a/drivers/gpio/gpio-sa1100.c b/drivers/gpio/gpio-sa1100.c index edff5e81489ff7cb4e75358d8727177de821d7f9..242dad763ac4d5ea913cf1ac4332348615217332 100644 --- a/drivers/gpio/gpio-sa1100.c +++ b/drivers/gpio/gpio-sa1100.c @@ -12,6 +12,7 @@ #include #include #include +#include struct sa1100_gpio_chip { struct gpio_chip chip; diff --git a/drivers/gpio/gpio-sch311x.c b/drivers/gpio/gpio-sch311x.c index da01e1cad7cb24af74944205ea12e23e4046f00f..ba4fccf3cc94f108f036936bc2d5006fb4d060a3 100644 --- a/drivers/gpio/gpio-sch311x.c +++ b/drivers/gpio/gpio-sch311x.c @@ -281,8 +281,6 @@ static int sch311x_gpio_probe(struct platform_device *pdev) if (!priv) return -ENOMEM; - platform_set_drvdata(pdev, priv); - for (i = 0; i < ARRAY_SIZE(priv->blocks); i++) { block = &priv->blocks[i]; @@ -305,42 +303,22 @@ static int sch311x_gpio_probe(struct platform_device *pdev) block->data_reg = sch311x_gpio_blocks[i].data_reg; block->runtime_reg = pdata->runtime_reg; - err = gpiochip_add_data(&block->chip, block); + err = devm_gpiochip_add_data(&pdev->dev, &block->chip, block); if (err < 0) { dev_err(&pdev->dev, "Could not register gpiochip, %d\n", err); - goto exit_err; + return err; } dev_info(&pdev->dev, "SMSC SCH311x GPIO block %d registered.\n", i); } return 0; - -exit_err: - /* release already registered chips */ - for (--i; i >= 0; i--) - gpiochip_remove(&priv->blocks[i].chip); - return err; -} - -static int sch311x_gpio_remove(struct platform_device *pdev) -{ - struct sch311x_gpio_priv *priv = platform_get_drvdata(pdev); - int i; - - for (i = 0; i < ARRAY_SIZE(priv->blocks); i++) { - gpiochip_remove(&priv->blocks[i].chip); - dev_info(&pdev->dev, - "SMSC SCH311x GPIO block %d unregistered.\n", i); - } - return 0; } static struct platform_driver sch311x_gpio_driver = { .driver.name = DRV_NAME, .probe = sch311x_gpio_probe, - .remove = sch311x_gpio_remove, }; diff --git a/drivers/gpio/gpio-sifive.c b/drivers/gpio/gpio-sifive.c index 98939cd4a71e65777ed88c073da4ecba4f7233bc..745e5f67254ea2715ae7d3241468bd7ffe85fed1 100644 --- a/drivers/gpio/gpio-sifive.c +++ b/drivers/gpio/gpio-sifive.c @@ -221,8 +221,12 @@ static int sifive_gpio_probe(struct platform_device *pdev) return -ENODEV; } - for (i = 0; i < ngpio; i++) - chip->irq_number[i] = platform_get_irq(pdev, i); + for (i = 0; i < ngpio; i++) { + ret = platform_get_irq(pdev, i); + if (ret < 0) + return ret; + chip->irq_number[i] = ret; + } ret = bgpio_init(&chip->gc, dev, 4, chip->base + SIFIVE_GPIO_INPUT_VAL, diff --git a/drivers/gpio/gpio-tangier.c b/drivers/gpio/gpio-tangier.c index e990781935baccaadbd30b83c650ea318423a66a..7ce3eddaed2572b4b14431d8170dd1332292e297 100644 --- a/drivers/gpio/gpio-tangier.c +++ b/drivers/gpio/gpio-tangier.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -428,10 +429,11 @@ static int tng_gpio_add_pin_ranges(struct gpio_chip *chip) int devm_tng_gpio_probe(struct device *dev, struct tng_gpio *gpio) { const struct tng_gpio_info *info = &gpio->info; + size_t nctx = DIV_ROUND_UP(info->ngpio, 32); struct gpio_irq_chip *girq; int ret; - gpio->ctx = devm_kcalloc(dev, DIV_ROUND_UP(info->ngpio, 32), sizeof(*gpio->ctx), GFP_KERNEL); + gpio->ctx = devm_kcalloc(dev, nctx, sizeof(*gpio->ctx), GFP_KERNEL); if (!gpio->ctx) return -ENOMEM; diff --git a/drivers/gpio/gpio-tegra186.c b/drivers/gpio/gpio-tegra186.c index b904de0b1784816d8006f0856b55f112a6f82c66..80d08ddde40e865701602e18dfb6046de7d9ad92 100644 --- a/drivers/gpio/gpio-tegra186.c +++ b/drivers/gpio/gpio-tegra186.c @@ -27,6 +27,22 @@ #define TEGRA186_GPIO_INT_ROUTE_MAPPING(p, x) (0x14 + (p) * 0x20 + (x) * 4) +#define TEGRA186_GPIO_VM 0x00 +#define TEGRA186_GPIO_VM_RW_MASK 0x03 +#define TEGRA186_GPIO_SCR 0x04 +#define TEGRA186_GPIO_SCR_PIN_SIZE 0x08 +#define TEGRA186_GPIO_SCR_PORT_SIZE 0x40 +#define TEGRA186_GPIO_SCR_SEC_WEN BIT(28) +#define TEGRA186_GPIO_SCR_SEC_REN BIT(27) +#define TEGRA186_GPIO_SCR_SEC_G1W BIT(9) +#define TEGRA186_GPIO_SCR_SEC_G1R BIT(1) +#define TEGRA186_GPIO_FULL_ACCESS (TEGRA186_GPIO_SCR_SEC_WEN | \ + TEGRA186_GPIO_SCR_SEC_REN | \ + TEGRA186_GPIO_SCR_SEC_G1R | \ + TEGRA186_GPIO_SCR_SEC_G1W) +#define TEGRA186_GPIO_SCR_SEC_ENABLE (TEGRA186_GPIO_SCR_SEC_WEN | \ + TEGRA186_GPIO_SCR_SEC_REN) + /* control registers */ #define TEGRA186_GPIO_ENABLE_CONFIG 0x00 #define TEGRA186_GPIO_ENABLE_CONFIG_ENABLE BIT(0) @@ -81,6 +97,7 @@ struct tegra_gpio_soc { unsigned int num_pin_ranges; const char *pinmux; bool has_gte; + bool has_vm_support; }; struct tegra_gpio { @@ -130,6 +147,58 @@ static void __iomem *tegra186_gpio_get_base(struct tegra_gpio *gpio, return gpio->base + offset + pin * 0x20; } +static void __iomem *tegra186_gpio_get_secure_base(struct tegra_gpio *gpio, + unsigned int pin) +{ + const struct tegra_gpio_port *port; + unsigned int offset; + + port = tegra186_gpio_get_port(gpio, &pin); + if (!port) + return NULL; + + offset = port->bank * 0x1000 + port->port * TEGRA186_GPIO_SCR_PORT_SIZE; + + return gpio->secure + offset + pin * TEGRA186_GPIO_SCR_PIN_SIZE; +} + +static inline bool tegra186_gpio_is_accessible(struct tegra_gpio *gpio, unsigned int pin) +{ + void __iomem *secure; + u32 value; + + secure = tegra186_gpio_get_secure_base(gpio, pin); + + if (gpio->soc->has_vm_support) { + value = readl(secure + TEGRA186_GPIO_VM); + if ((value & TEGRA186_GPIO_VM_RW_MASK) != TEGRA186_GPIO_VM_RW_MASK) + return false; + } + + value = __raw_readl(secure + TEGRA186_GPIO_SCR); + + if ((value & TEGRA186_GPIO_SCR_SEC_ENABLE) == 0) + return true; + + if ((value & TEGRA186_GPIO_FULL_ACCESS) == TEGRA186_GPIO_FULL_ACCESS) + return true; + + return false; +} + +static int tegra186_init_valid_mask(struct gpio_chip *chip, + unsigned long *valid_mask, unsigned int ngpios) +{ + struct tegra_gpio *gpio = gpiochip_get_data(chip); + unsigned int j; + + for (j = 0; j < ngpios; j++) { + if (!tegra186_gpio_is_accessible(gpio, j)) + clear_bit(j, valid_mask); + } + return 0; +} + static int tegra186_gpio_get_direction(struct gpio_chip *chip, unsigned int offset) { @@ -816,6 +885,7 @@ static int tegra186_gpio_probe(struct platform_device *pdev) gpio->gpio.set = tegra186_gpio_set; gpio->gpio.set_config = tegra186_gpio_set_config; gpio->gpio.add_pin_ranges = tegra186_gpio_add_pin_ranges; + gpio->gpio.init_valid_mask = tegra186_init_valid_mask; if (gpio->soc->has_gte) { gpio->gpio.en_hw_timestamp = tegra186_gpio_en_hw_ts; gpio->gpio.dis_hw_timestamp = tegra186_gpio_dis_hw_ts; @@ -894,11 +964,15 @@ static int tegra186_gpio_probe(struct platform_device *pdev) np = of_find_matching_node(NULL, tegra186_pmc_of_match); if (np) { - irq->parent_domain = irq_find_host(np); - of_node_put(np); - - if (!irq->parent_domain) - return -EPROBE_DEFER; + if (of_device_is_available(np)) { + irq->parent_domain = irq_find_host(np); + of_node_put(np); + + if (!irq->parent_domain) + return -EPROBE_DEFER; + } else { + of_node_put(np); + } } irq->map = devm_kcalloc(&pdev->dev, gpio->gpio.ngpio, @@ -958,6 +1032,7 @@ static const struct tegra_gpio_soc tegra186_main_soc = { .name = "tegra186-gpio", .instance = 0, .num_irqs_per_bank = 1, + .has_vm_support = false, }; #define TEGRA186_AON_GPIO_PORT(_name, _bank, _port, _pins) \ @@ -985,6 +1060,7 @@ static const struct tegra_gpio_soc tegra186_aon_soc = { .name = "tegra186-gpio-aon", .instance = 1, .num_irqs_per_bank = 1, + .has_vm_support = false, }; #define TEGRA194_MAIN_GPIO_PORT(_name, _bank, _port, _pins) \ @@ -1040,6 +1116,7 @@ static const struct tegra_gpio_soc tegra194_main_soc = { .num_pin_ranges = ARRAY_SIZE(tegra194_main_pin_ranges), .pin_ranges = tegra194_main_pin_ranges, .pinmux = "nvidia,tegra194-pinmux", + .has_vm_support = true, }; #define TEGRA194_AON_GPIO_PORT(_name, _bank, _port, _pins) \ @@ -1065,6 +1142,7 @@ static const struct tegra_gpio_soc tegra194_aon_soc = { .instance = 1, .num_irqs_per_bank = 8, .has_gte = true, + .has_vm_support = false, }; #define TEGRA234_MAIN_GPIO_PORT(_name, _bank, _port, _pins) \ @@ -1109,6 +1187,7 @@ static const struct tegra_gpio_soc tegra234_main_soc = { .name = "tegra234-gpio", .instance = 0, .num_irqs_per_bank = 8, + .has_vm_support = true, }; #define TEGRA234_AON_GPIO_PORT(_name, _bank, _port, _pins) \ @@ -1135,6 +1214,7 @@ static const struct tegra_gpio_soc tegra234_aon_soc = { .instance = 1, .num_irqs_per_bank = 8, .has_gte = true, + .has_vm_support = false, }; #define TEGRA241_MAIN_GPIO_PORT(_name, _bank, _port, _pins) \ @@ -1165,6 +1245,7 @@ static const struct tegra_gpio_soc tegra241_main_soc = { .name = "tegra241-gpio", .instance = 0, .num_irqs_per_bank = 8, + .has_vm_support = false, }; #define TEGRA241_AON_GPIO_PORT(_name, _bank, _port, _pins) \ @@ -1186,6 +1267,7 @@ static const struct tegra_gpio_soc tegra241_aon_soc = { .name = "tegra241-gpio-aon", .instance = 1, .num_irqs_per_bank = 8, + .has_vm_support = false, }; static const struct of_device_id tegra186_gpio_of_match[] = { diff --git a/drivers/gpio/gpio-tpic2810.c b/drivers/gpio/gpio-tpic2810.c index 349c5fbd9b0274334dc549de78b0826a75d0a9f0..effb7b8ff81fd51664b7f51a124aaafbf3504feb 100644 --- a/drivers/gpio/gpio-tpic2810.c +++ b/drivers/gpio/gpio-tpic2810.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/ - * Andrew F. Davis + * Copyright (C) 2015-2023 Texas Instruments Incorporated - https://www.ti.com/ + * Andrew Davis */ #include @@ -101,14 +101,11 @@ MODULE_DEVICE_TABLE(of, tpic2810_of_match_table); static int tpic2810_probe(struct i2c_client *client) { struct tpic2810 *gpio; - int ret; gpio = devm_kzalloc(&client->dev, sizeof(*gpio), GFP_KERNEL); if (!gpio) return -ENOMEM; - i2c_set_clientdata(client, gpio); - gpio->chip = template_chip; gpio->chip.parent = &client->dev; @@ -116,20 +113,7 @@ static int tpic2810_probe(struct i2c_client *client) mutex_init(&gpio->lock); - ret = gpiochip_add_data(&gpio->chip, gpio); - if (ret < 0) { - dev_err(&client->dev, "Unable to register gpiochip\n"); - return ret; - } - - return 0; -} - -static void tpic2810_remove(struct i2c_client *client) -{ - struct tpic2810 *gpio = i2c_get_clientdata(client); - - gpiochip_remove(&gpio->chip); + return devm_gpiochip_add_data(&client->dev, &gpio->chip, gpio); } static const struct i2c_device_id tpic2810_id_table[] = { @@ -143,12 +127,11 @@ static struct i2c_driver tpic2810_driver = { .name = "tpic2810", .of_match_table = tpic2810_of_match_table, }, - .probe_new = tpic2810_probe, - .remove = tpic2810_remove, + .probe = tpic2810_probe, .id_table = tpic2810_id_table, }; module_i2c_driver(tpic2810_driver); -MODULE_AUTHOR("Andrew F. Davis "); +MODULE_AUTHOR("Andrew Davis "); MODULE_DESCRIPTION("TPIC2810 8-Bit LED Driver GPIO Driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/gpio/gpio-tps65086.c b/drivers/gpio/gpio-tps65086.c index 1e9d8262d0ffc44094b36ce4f1a52177aef5a768..8f5827554e1e89b2cc2cac0e43521246fc986408 100644 --- a/drivers/gpio/gpio-tps65086.c +++ b/drivers/gpio/gpio-tps65086.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/ - * Andrew F. Davis + * Copyright (C) 2015-2023 Texas Instruments Incorporated - https://www.ti.com/ + * Andrew Davis * * Based on the TPS65912 driver */ @@ -80,34 +80,16 @@ static const struct gpio_chip template_chip = { static int tps65086_gpio_probe(struct platform_device *pdev) { struct tps65086_gpio *gpio; - int ret; gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL); if (!gpio) return -ENOMEM; - platform_set_drvdata(pdev, gpio); - gpio->tps = dev_get_drvdata(pdev->dev.parent); gpio->chip = template_chip; gpio->chip.parent = gpio->tps->dev; - ret = gpiochip_add_data(&gpio->chip, gpio); - if (ret < 0) { - dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret); - return ret; - } - - return 0; -} - -static int tps65086_gpio_remove(struct platform_device *pdev) -{ - struct tps65086_gpio *gpio = platform_get_drvdata(pdev); - - gpiochip_remove(&gpio->chip); - - return 0; + return devm_gpiochip_add_data(&pdev->dev, &gpio->chip, gpio); } static const struct platform_device_id tps65086_gpio_id_table[] = { @@ -121,11 +103,10 @@ static struct platform_driver tps65086_gpio_driver = { .name = "tps65086-gpio", }, .probe = tps65086_gpio_probe, - .remove = tps65086_gpio_remove, .id_table = tps65086_gpio_id_table, }; module_platform_driver(tps65086_gpio_driver); -MODULE_AUTHOR("Andrew F. Davis "); +MODULE_AUTHOR("Andrew Davis "); MODULE_DESCRIPTION("TPS65086 GPIO driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/gpio/gpio-tps65219.c b/drivers/gpio/gpio-tps65219.c new file mode 100644 index 0000000000000000000000000000000000000000..7b38aa36011284ff735296257692fe29d0d3452e --- /dev/null +++ b/drivers/gpio/gpio-tps65219.c @@ -0,0 +1,185 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * GPIO driver for TI TPS65219 PMICs + * + * Copyright (C) 2022 Texas Instruments Incorporated - http://www.ti.com/ + */ + +#include +#include +#include +#include +#include +#include + +#define TPS65219_GPIO0_DIR_MASK BIT(3) +#define TPS65219_GPIO0_OFFSET 2 +#define TPS65219_GPIO0_IDX 0 +#define TPS65219_GPIO_DIR_IN 1 +#define TPS65219_GPIO_DIR_OUT 0 + +struct tps65219_gpio { + struct gpio_chip gpio_chip; + struct tps65219 *tps; +}; + +static int tps65219_gpio_get_direction(struct gpio_chip *gc, unsigned int offset) +{ + struct tps65219_gpio *gpio = gpiochip_get_data(gc); + int ret, val; + + if (offset != TPS65219_GPIO0_IDX) + return GPIO_LINE_DIRECTION_OUT; + + ret = regmap_read(gpio->tps->regmap, TPS65219_REG_MFP_1_CONFIG, &val); + if (ret) + return ret; + + return !!(val & TPS65219_GPIO0_DIR_MASK); +} + +static int tps65219_gpio_get(struct gpio_chip *gc, unsigned int offset) +{ + struct tps65219_gpio *gpio = gpiochip_get_data(gc); + struct device *dev = gpio->tps->dev; + int ret, val; + + if (offset != TPS65219_GPIO0_IDX) { + dev_err(dev, "GPIO%d is output only, cannot get\n", offset); + return -ENOTSUPP; + } + + ret = regmap_read(gpio->tps->regmap, TPS65219_REG_MFP_CTRL, &val); + if (ret) + return ret; + + ret = !!(val & BIT(TPS65219_MFP_GPIO_STATUS_MASK)); + dev_warn(dev, "GPIO%d = %d, MULTI_DEVICE_ENABLE, not a standard GPIO\n", offset, ret); + + /* + * Depending on NVM config, return an error if direction is output, otherwise the GPIO0 + * status bit. + */ + + if (tps65219_gpio_get_direction(gc, offset) == TPS65219_GPIO_DIR_OUT) + return -ENOTSUPP; + + return ret; +} + +static void tps65219_gpio_set(struct gpio_chip *gc, unsigned int offset, int value) +{ + struct tps65219_gpio *gpio = gpiochip_get_data(gc); + struct device *dev = gpio->tps->dev; + int v, mask, bit; + + bit = (offset == TPS65219_GPIO0_IDX) ? TPS65219_GPIO0_OFFSET : offset - 1; + + mask = BIT(bit); + v = value ? mask : 0; + + if (regmap_update_bits(gpio->tps->regmap, TPS65219_REG_GENERAL_CONFIG, mask, v)) + dev_err(dev, "GPIO%d, set to value %d failed.\n", offset, value); +} + +static int tps65219_gpio_change_direction(struct gpio_chip *gc, unsigned int offset, + unsigned int direction) +{ + struct tps65219_gpio *gpio = gpiochip_get_data(gc); + struct device *dev = gpio->tps->dev; + + /* + * Documentation is stating that GPIO0 direction must not be changed in Linux: + * Table 8-34. MFP_1_CONFIG(3): MULTI_DEVICE_ENABLE, should only be changed in INITIALIZE + * state (prior to ON Request). + * Set statically by NVM, changing direction in application can cause a hang. + * Below can be used for test purpose only. + */ + + if (IS_ENABLED(CONFIG_DEBUG_GPIO)) { + int ret = regmap_update_bits(gpio->tps->regmap, TPS65219_REG_MFP_1_CONFIG, + TPS65219_GPIO0_DIR_MASK, direction); + if (ret) { + dev_err(dev, + "GPIO DEBUG enabled: Fail to change direction to %u for GPIO%d.\n", + direction, offset); + return ret; + } + } + + dev_err(dev, + "GPIO%d direction set by NVM, change to %u failed, not allowed by specification\n", + offset, direction); + + return -ENOTSUPP; +} + +static int tps65219_gpio_direction_input(struct gpio_chip *gc, unsigned int offset) +{ + struct tps65219_gpio *gpio = gpiochip_get_data(gc); + struct device *dev = gpio->tps->dev; + + if (offset != TPS65219_GPIO0_IDX) { + dev_err(dev, "GPIO%d is output only, cannot change to input\n", offset); + return -ENOTSUPP; + } + + if (tps65219_gpio_get_direction(gc, offset) == TPS65219_GPIO_DIR_IN) + return 0; + + return tps65219_gpio_change_direction(gc, offset, TPS65219_GPIO_DIR_IN); +} + +static int tps65219_gpio_direction_output(struct gpio_chip *gc, unsigned int offset, int value) +{ + tps65219_gpio_set(gc, offset, value); + if (offset != TPS65219_GPIO0_IDX) + return 0; + + if (tps65219_gpio_get_direction(gc, offset) == TPS65219_GPIO_DIR_OUT) + return 0; + + return tps65219_gpio_change_direction(gc, offset, TPS65219_GPIO_DIR_OUT); +} + +static const struct gpio_chip tps65219_template_chip = { + .label = "tps65219-gpio", + .owner = THIS_MODULE, + .get_direction = tps65219_gpio_get_direction, + .direction_input = tps65219_gpio_direction_input, + .direction_output = tps65219_gpio_direction_output, + .get = tps65219_gpio_get, + .set = tps65219_gpio_set, + .base = -1, + .ngpio = 3, + .can_sleep = true, +}; + +static int tps65219_gpio_probe(struct platform_device *pdev) +{ + struct tps65219 *tps = dev_get_drvdata(pdev->dev.parent); + struct tps65219_gpio *gpio; + + gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL); + if (!gpio) + return -ENOMEM; + + gpio->tps = tps; + gpio->gpio_chip = tps65219_template_chip; + gpio->gpio_chip.parent = tps->dev; + + return devm_gpiochip_add_data(&pdev->dev, &gpio->gpio_chip, gpio); +} + +static struct platform_driver tps65219_gpio_driver = { + .driver = { + .name = "tps65219-gpio", + }, + .probe = tps65219_gpio_probe, +}; +module_platform_driver(tps65219_gpio_driver); + +MODULE_ALIAS("platform:tps65219-gpio"); +MODULE_AUTHOR("Jonathan Cormier "); +MODULE_DESCRIPTION("TPS65219 GPIO driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/gpio/gpio-ts4900.c b/drivers/gpio/gpio-ts4900.c index 43e8b66e04f781deb7f466e299ead30e6f449a99..eba96319dac2ff2a11fbae644969aeacf414ea30 100644 --- a/drivers/gpio/gpio-ts4900.c +++ b/drivers/gpio/gpio-ts4900.c @@ -185,7 +185,7 @@ static struct i2c_driver ts4900_gpio_driver = { .name = "ts4900-gpio", .of_match_table = ts4900_gpio_of_match_table, }, - .probe_new = ts4900_gpio_probe, + .probe = ts4900_gpio_probe, .id_table = ts4900_gpio_id_table, }; module_i2c_driver(ts4900_gpio_driver); diff --git a/drivers/gpio/gpio-twl4030.c b/drivers/gpio/gpio-twl4030.c index c1bb2c3ca6f298308bd51d58d6f6e93b942978cf..bcd692229c7c73c51cffab353d78b63e1fc2151d 100644 --- a/drivers/gpio/gpio-twl4030.c +++ b/drivers/gpio/gpio-twl4030.c @@ -17,7 +17,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -465,8 +467,7 @@ static int gpio_twl4030_debounce(u32 debounce, u8 mmc_cd) REG_GPIO_DEBEN1, 3); } -static struct twl4030_gpio_platform_data *of_gpio_twl4030(struct device *dev, - struct twl4030_gpio_platform_data *pdata) +static struct twl4030_gpio_platform_data *of_gpio_twl4030(struct device *dev) { struct twl4030_gpio_platform_data *omap_twl_info; @@ -474,9 +475,6 @@ static struct twl4030_gpio_platform_data *of_gpio_twl4030(struct device *dev, if (!omap_twl_info) return NULL; - if (pdata) - *omap_twl_info = *pdata; - omap_twl_info->use_leds = of_property_read_bool(dev->of_node, "ti,use-leds"); @@ -492,21 +490,18 @@ static struct twl4030_gpio_platform_data *of_gpio_twl4030(struct device *dev, return omap_twl_info; } -/* Cannot use as gpio_twl4030_probe() calls us */ -static int gpio_twl4030_remove(struct platform_device *pdev) +/* Called from the registered devm action */ +static void gpio_twl4030_power_off_action(void *data) { - struct gpio_twl4030_priv *priv = platform_get_drvdata(pdev); - - gpiochip_remove(&priv->gpio_chip); + struct gpio_desc *d = data; - /* REVISIT no support yet for deregistering all the IRQs */ - WARN_ON(!is_module()); - return 0; + gpiod_unexport(d); + gpiochip_free_own_desc(d); } static int gpio_twl4030_probe(struct platform_device *pdev) { - struct twl4030_gpio_platform_data *pdata = dev_get_platdata(&pdev->dev); + struct twl4030_gpio_platform_data *pdata; struct device_node *node = pdev->dev.of_node; struct gpio_twl4030_priv *priv; int ret, irq_base; @@ -546,9 +541,7 @@ static int gpio_twl4030_probe(struct platform_device *pdev) mutex_init(&priv->mutex); - if (node) - pdata = of_gpio_twl4030(&pdev->dev, pdata); - + pdata = of_gpio_twl4030(&pdev->dev); if (pdata == NULL) { dev_err(&pdev->dev, "Platform data is missing\n"); return -ENXIO; @@ -577,27 +570,39 @@ static int gpio_twl4030_probe(struct platform_device *pdev) if (pdata->use_leds) priv->gpio_chip.ngpio += 2; - ret = gpiochip_add_data(&priv->gpio_chip, priv); + ret = devm_gpiochip_add_data(&pdev->dev, &priv->gpio_chip, priv); if (ret < 0) { dev_err(&pdev->dev, "could not register gpiochip, %d\n", ret); priv->gpio_chip.ngpio = 0; - gpio_twl4030_remove(pdev); - goto out; + return ret; } - platform_set_drvdata(pdev, priv); + /* + * Special quirk for the OMAP3 to hog and export a WLAN power + * GPIO. + */ + if (IS_ENABLED(CONFIG_ARCH_OMAP3) && + of_machine_is_compatible("compulab,omap3-sbc-t3730")) { + struct gpio_desc *d; + + d = gpiochip_request_own_desc(&priv->gpio_chip, + 2, "wlan pwr", + GPIO_ACTIVE_HIGH, + GPIOD_OUT_HIGH); + if (IS_ERR(d)) + return dev_err_probe(&pdev->dev, PTR_ERR(d), + "unable to hog wlan pwr GPIO\n"); + + gpiod_export(d, 0); - if (pdata->setup) { - int status; + ret = devm_add_action_or_reset(&pdev->dev, gpio_twl4030_power_off_action, d); + if (ret) + return dev_err_probe(&pdev->dev, ret, + "failed to install power off handler\n"); - status = pdata->setup(&pdev->dev, priv->gpio_chip.base, - TWL4030_GPIO_MAX); - if (status) - dev_dbg(&pdev->dev, "setup --> %d\n", status); } -out: - return ret; + return 0; } static const struct of_device_id twl_gpio_match[] = { @@ -615,7 +620,6 @@ static struct platform_driver gpio_twl4030_driver = { .of_match_table = twl_gpio_match, }, .probe = gpio_twl4030_probe, - .remove = gpio_twl4030_remove, }; static int __init gpio_twl4030_init(void) diff --git a/drivers/gpio/gpio-xra1403.c b/drivers/gpio/gpio-xra1403.c index 51d6119e1bb4d7d0379b2bd40486440048a8fe34..bbc06cdd963477ba7bf1c46f613d74d83808e1ce 100644 --- a/drivers/gpio/gpio-xra1403.c +++ b/drivers/gpio/gpio-xra1403.c @@ -11,7 +11,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/gpio/gpio-zynq.c b/drivers/gpio/gpio-zynq.c index 06c6401f02b89e0113f58ece5ef77e5307eb6ccf..0a7264aabe48834d5d1830340caab0bdd752fc77 100644 --- a/drivers/gpio/gpio-zynq.c +++ b/drivers/gpio/gpio-zynq.c @@ -151,8 +151,8 @@ struct zynq_platform_data { int bank_max[ZYNQMP_GPIO_MAX_BANK]; }; -static struct irq_chip zynq_gpio_level_irqchip; -static struct irq_chip zynq_gpio_edge_irqchip; +static const struct irq_chip zynq_gpio_level_irqchip; +static const struct irq_chip zynq_gpio_edge_irqchip; /** * zynq_gpio_is_zynq - test if HW is zynq or zynqmp @@ -404,9 +404,12 @@ static int zynq_gpio_get_direction(struct gpio_chip *chip, unsigned int pin) static void zynq_gpio_irq_mask(struct irq_data *irq_data) { unsigned int device_pin_num, bank_num, bank_pin_num; + const unsigned long offset = irqd_to_hwirq(irq_data); + struct gpio_chip *chip = irq_data_get_irq_chip_data(irq_data); struct zynq_gpio *gpio = gpiochip_get_data(irq_data_get_irq_chip_data(irq_data)); + gpiochip_disable_irq(chip, offset); device_pin_num = irq_data->hwirq; zynq_gpio_get_bank_pin(device_pin_num, &bank_num, &bank_pin_num, gpio); writel_relaxed(BIT(bank_pin_num), @@ -425,9 +428,12 @@ static void zynq_gpio_irq_mask(struct irq_data *irq_data) static void zynq_gpio_irq_unmask(struct irq_data *irq_data) { unsigned int device_pin_num, bank_num, bank_pin_num; + const unsigned long offset = irqd_to_hwirq(irq_data); + struct gpio_chip *chip = irq_data_get_irq_chip_data(irq_data); struct zynq_gpio *gpio = gpiochip_get_data(irq_data_get_irq_chip_data(irq_data)); + gpiochip_enable_irq(chip, offset); device_pin_num = irq_data->hwirq; zynq_gpio_get_bank_pin(device_pin_num, &bank_num, &bank_pin_num, gpio); writel_relaxed(BIT(bank_pin_num), @@ -569,28 +575,8 @@ static int zynq_gpio_set_wake(struct irq_data *data, unsigned int on) return 0; } -static int zynq_gpio_irq_reqres(struct irq_data *d) -{ - struct gpio_chip *chip = irq_data_get_irq_chip_data(d); - int ret; - - ret = pm_runtime_resume_and_get(chip->parent); - if (ret < 0) - return ret; - - return gpiochip_reqres_irq(chip, d->hwirq); -} - -static void zynq_gpio_irq_relres(struct irq_data *d) -{ - struct gpio_chip *chip = irq_data_get_irq_chip_data(d); - - gpiochip_relres_irq(chip, d->hwirq); - pm_runtime_put(chip->parent); -} - /* irq chip descriptor */ -static struct irq_chip zynq_gpio_level_irqchip = { +static const struct irq_chip zynq_gpio_level_irqchip = { .name = DRIVER_NAME, .irq_enable = zynq_gpio_irq_enable, .irq_eoi = zynq_gpio_irq_ack, @@ -598,13 +584,12 @@ static struct irq_chip zynq_gpio_level_irqchip = { .irq_unmask = zynq_gpio_irq_unmask, .irq_set_type = zynq_gpio_set_irq_type, .irq_set_wake = zynq_gpio_set_wake, - .irq_request_resources = zynq_gpio_irq_reqres, - .irq_release_resources = zynq_gpio_irq_relres, .flags = IRQCHIP_EOI_THREADED | IRQCHIP_EOI_IF_HANDLED | - IRQCHIP_MASK_ON_SUSPEND, + IRQCHIP_MASK_ON_SUSPEND | IRQCHIP_IMMUTABLE, + GPIOCHIP_IRQ_RESOURCE_HELPERS, }; -static struct irq_chip zynq_gpio_edge_irqchip = { +static const struct irq_chip zynq_gpio_edge_irqchip = { .name = DRIVER_NAME, .irq_enable = zynq_gpio_irq_enable, .irq_ack = zynq_gpio_irq_ack, @@ -612,9 +597,8 @@ static struct irq_chip zynq_gpio_edge_irqchip = { .irq_unmask = zynq_gpio_irq_unmask, .irq_set_type = zynq_gpio_set_irq_type, .irq_set_wake = zynq_gpio_set_wake, - .irq_request_resources = zynq_gpio_irq_reqres, - .irq_release_resources = zynq_gpio_irq_relres, - .flags = IRQCHIP_MASK_ON_SUSPEND, + .flags = IRQCHIP_MASK_ON_SUSPEND | IRQCHIP_IMMUTABLE, + GPIOCHIP_IRQ_RESOURCE_HELPERS, }; static void zynq_gpio_handle_bank_irq(struct zynq_gpio *gpio, @@ -962,7 +946,7 @@ static int zynq_gpio_probe(struct platform_device *pdev) /* Set up the GPIO irqchip */ girq = &chip->irq; - girq->chip = &zynq_gpio_edge_irqchip; + gpio_irq_chip_set_chip(girq, &zynq_gpio_edge_irqchip); girq->parent_handler = zynq_gpio_irqhandler; girq->num_parents = 1; girq->parents = devm_kcalloc(&pdev->dev, 1, diff --git a/drivers/gpio/gpiolib-legacy.c b/drivers/gpio/gpiolib-legacy.c index 30e2476a6dc4e0a2342e7c4bbe0aa88cc948523d..97f4b498e343d1c9f6fdffb026dc5a3ede6075c7 100644 --- a/drivers/gpio/gpiolib-legacy.c +++ b/drivers/gpio/gpiolib-legacy.c @@ -33,12 +33,6 @@ int gpio_request_one(unsigned gpio, unsigned long flags, const char *label) if (err) return err; - if (flags & GPIOF_OPEN_DRAIN) - set_bit(FLAG_OPEN_DRAIN, &desc->flags); - - if (flags & GPIOF_OPEN_SOURCE) - set_bit(FLAG_OPEN_SOURCE, &desc->flags); - if (flags & GPIOF_ACTIVE_LOW) set_bit(FLAG_ACTIVE_LOW, &desc->flags); @@ -51,12 +45,6 @@ int gpio_request_one(unsigned gpio, unsigned long flags, const char *label) if (err) goto free_gpio; - if (flags & GPIOF_EXPORT) { - err = gpiod_export(desc, flags & GPIOF_EXPORT_CHANGEABLE); - if (err) - goto free_gpio; - } - return 0; free_gpio: diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index a7220e04a93e562dbc345705c36738a8464282f4..251c875b5c34cc563e113cf1f4ec257b31a2c213 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -465,6 +465,12 @@ static unsigned long *gpiochip_allocate_mask(struct gpio_chip *gc) return p; } +static void gpiochip_free_mask(unsigned long **p) +{ + bitmap_free(*p); + *p = NULL; +} + static unsigned int gpiochip_count_reserved_ranges(struct gpio_chip *gc) { struct device *dev = &gc->gpiodev->dev; @@ -478,18 +484,6 @@ static unsigned int gpiochip_count_reserved_ranges(struct gpio_chip *gc) return 0; } -static int gpiochip_alloc_valid_mask(struct gpio_chip *gc) -{ - if (!(gpiochip_count_reserved_ranges(gc) || gc->init_valid_mask)) - return 0; - - gc->valid_mask = gpiochip_allocate_mask(gc); - if (!gc->valid_mask) - return -ENOMEM; - - return 0; -} - static int gpiochip_apply_reserved_ranges(struct gpio_chip *gc) { struct device *dev = &gc->gpiodev->dev; @@ -530,6 +524,13 @@ static int gpiochip_init_valid_mask(struct gpio_chip *gc) { int ret; + if (!(gpiochip_count_reserved_ranges(gc) || gc->init_valid_mask)) + return 0; + + gc->valid_mask = gpiochip_allocate_mask(gc); + if (!gc->valid_mask) + return -ENOMEM; + ret = gpiochip_apply_reserved_ranges(gc); if (ret) return ret; @@ -544,8 +545,7 @@ static int gpiochip_init_valid_mask(struct gpio_chip *gc) static void gpiochip_free_valid_mask(struct gpio_chip *gc) { - bitmap_free(gc->valid_mask); - gc->valid_mask = NULL; + gpiochip_free_mask(&gc->valid_mask); } static int gpiochip_add_pin_ranges(struct gpio_chip *gc) @@ -857,7 +857,7 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data, if (ret) goto err_remove_from_list; - ret = gpiochip_alloc_valid_mask(gc); + ret = gpiochip_init_valid_mask(gc); if (ret) goto err_remove_from_list; @@ -865,10 +865,6 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data, if (ret) goto err_free_gpiochip_mask; - ret = gpiochip_init_valid_mask(gc); - if (ret) - goto err_remove_of_chip; - for (i = 0; i < gc->ngpio; i++) { struct gpio_desc *desc = &gdev->descs[i]; @@ -1089,8 +1085,7 @@ static int gpiochip_irqchip_init_valid_mask(struct gpio_chip *gc) static void gpiochip_irqchip_free_valid_mask(struct gpio_chip *gc) { - bitmap_free(gc->irq.valid_mask); - gc->irq.valid_mask = NULL; + gpiochip_free_mask(&gc->irq.valid_mask); } bool gpiochip_irqchip_irq_valid(const struct gpio_chip *gc, @@ -1676,11 +1671,10 @@ static int gpiochip_add_irqchip(struct gpio_chip *gc, if (ret) return ret; } else { - /* Some drivers provide custom irqdomain ops */ gc->irq.domain = irq_domain_create_simple(fwnode, gc->ngpio, gc->irq.first, - gc->irq.domain_ops ?: &gpiochip_domain_ops, + &gpiochip_domain_ops, gc); if (!gc->irq.domain) return -EINVAL; @@ -1745,7 +1739,7 @@ static void gpiochip_irqchip_remove(struct gpio_chip *gc) } /* Remove all IRQ mappings and delete the domain */ - if (gc->irq.domain) { + if (!gc->irq.domain_is_allocated_externally && gc->irq.domain) { unsigned int irq; for (offset = 0; offset < gc->ngpio; offset++) { @@ -1791,6 +1785,15 @@ int gpiochip_irqchip_add_domain(struct gpio_chip *gc, gc->to_irq = gpiochip_to_irq; gc->irq.domain = domain; + gc->irq.domain_is_allocated_externally = true; + + /* + * Using barrier() here to prevent compiler from reordering + * gc->irq.initialized before adding irqdomain. + */ + barrier(); + + gc->irq.initialized = true; return 0; } @@ -2124,8 +2127,6 @@ static bool gpiod_free_commit(struct gpio_desc *desc) might_sleep(); - gpiod_unexport(desc); - spin_lock_irqsave(&gpio_lock, flags); gc = desc->gdev->chip; @@ -4243,7 +4244,7 @@ int gpiod_hog(struct gpio_desc *desc, const char *name, /* Mark GPIO as hogged so it can be identified and removed later */ set_bit(FLAG_IS_HOGGED, &desc->flags); - gpiod_info(desc, "hogged as %s%s\n", + gpiod_dbg(desc, "hogged as %s%s\n", (dflags & GPIOD_FLAGS_BIT_DIR_OUT) ? "output" : "input", (dflags & GPIOD_FLAGS_BIT_DIR_OUT) ? (dflags & GPIOD_FLAGS_BIT_DIR_VAL) ? "/high" : "/low" : ""); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index b49c34a5c04b9e86fc728b630cbc66e4b5751a54..8f2255b3a38a437c133e2fd6d2bb4c4d9d8552c8 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -285,6 +285,9 @@ extern int amdgpu_user_partt_mode; #define AMDGPU_SMARTSHIFT_MAX_BIAS (100) #define AMDGPU_SMARTSHIFT_MIN_BIAS (-100) +/* Extra time delay(in ms) to eliminate the influence of temperature momentary fluctuation */ +#define AMDGPU_SWCTF_EXTRA_DELAY 50 + struct amdgpu_xcp_mgr; struct amdgpu_device; struct amdgpu_irq_src; @@ -1276,9 +1279,10 @@ int emu_soc_asic_init(struct amdgpu_device *adev); #define amdgpu_inc_vram_lost(adev) atomic_inc(&((adev)->vram_lost_counter)); -#define for_each_inst(i, inst_mask) \ - for (i = ffs(inst_mask) - 1; inst_mask; \ - inst_mask &= ~(1U << i), i = ffs(inst_mask) - 1) +#define BIT_MASK_UPPER(i) ((i) >= BITS_PER_LONG ? 0 : ~0UL << (i)) +#define for_each_inst(i, inst_mask) \ + for (i = ffs(inst_mask); i-- != 0; \ + i = ffs(inst_mask & BIT_MASK_UPPER(i + 1))) #define MIN(X, Y) ((X) < (Y) ? (X) : (Y)) @@ -1291,6 +1295,7 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev, void amdgpu_device_pci_config_reset(struct amdgpu_device *adev); int amdgpu_device_pci_reset(struct amdgpu_device *adev); bool amdgpu_device_need_post(struct amdgpu_device *adev); +bool amdgpu_device_pcie_dynamic_switching_supported(void); bool amdgpu_device_should_use_aspm(struct amdgpu_device *adev); bool amdgpu_device_aspm_support_quirk(void); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c index dedfee14acce885ac97237b94bc4ba4a7f90ddcd..edb35a88cb788412b15b1d50ab151e42215e3eba 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c @@ -2814,6 +2814,9 @@ int amdgpu_amdkfd_gpuvm_restore_process_bos(void *info, struct dma_fence **ef) if (!attachment->is_mapped) continue; + if (attachment->bo_va->base.bo->tbo.pin_count) + continue; + kfd_mem_dmaunmap_attachment(mem, attachment); ret = update_gpuvm_pte(mem, attachment, &sync_obj); if (ret) { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c index 9ba4817a91484eadf36159cb6102010a8afd17b4..f4e3c133a16ca0c56dd4e3b8d893d877aaf0928c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c @@ -1791,6 +1791,15 @@ const struct attribute_group amdgpu_vbios_version_attr_group = { .attrs = amdgpu_vbios_version_attrs }; +int amdgpu_atombios_sysfs_init(struct amdgpu_device *adev) +{ + if (adev->mode_info.atom_context) + return devm_device_add_group(adev->dev, + &amdgpu_vbios_version_attr_group); + + return 0; +} + /** * amdgpu_atombios_fini - free the driver info and callbacks for atombios * diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.h index 4153d520e2a369b796c660768ab6f72a0901b9c4..b639a80ee3fcaf113cc22332e57f3071163afd99 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.h @@ -217,5 +217,6 @@ int amdgpu_atombios_get_data_table(struct amdgpu_device *adev, void amdgpu_atombios_fini(struct amdgpu_device *adev); int amdgpu_atombios_init(struct amdgpu_device *adev); +int amdgpu_atombios_sysfs_init(struct amdgpu_device *adev); #endif diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c index ef4b9a41f20ad4b134bb565388be3779999d73a3..0b7f4c4d58e58828d48f5a1435fb99b263e5cf35 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c @@ -327,10 +327,13 @@ amdgpu_atomfirmware_get_vram_info(struct amdgpu_device *adev, mem_channel_number = igp_info->v11.umachannelnumber; if (!mem_channel_number) mem_channel_number = 1; - /* channel width is 64 */ - if (vram_width) - *vram_width = mem_channel_number * 64; mem_type = igp_info->v11.memorytype; + if (mem_type == LpDdr5MemType) + mem_channel_width = 32; + else + mem_channel_width = 64; + if (vram_width) + *vram_width = mem_channel_number * mem_channel_width; if (vram_type) *vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type); break; @@ -345,10 +348,13 @@ amdgpu_atomfirmware_get_vram_info(struct amdgpu_device *adev, mem_channel_number = igp_info->v21.umachannelnumber; if (!mem_channel_number) mem_channel_number = 1; - /* channel width is 64 */ - if (vram_width) - *vram_width = mem_channel_number * 64; mem_type = igp_info->v21.memorytype; + if (mem_type == LpDdr5MemType) + mem_channel_width = 32; + else + mem_channel_width = 64; + if (vram_width) + *vram_width = mem_channel_number * mem_channel_width; if (vram_type) *vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type); break; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index 41f1f7429dcacaae456bbd686b4773eb6813c234..977e1804718d0671e820a2dd6c22226a1b0f4264 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -1625,15 +1625,15 @@ static int amdgpu_cs_wait_all_fences(struct amdgpu_device *adev, continue; r = dma_fence_wait_timeout(fence, true, timeout); + if (r > 0 && fence->error) + r = fence->error; + dma_fence_put(fence); if (r < 0) return r; if (r == 0) break; - - if (fence->error) - return fence->error; } memset(wait, 0, sizeof(*wait)); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index e25f085ee8867419605bcbe74f8ab869bf72b526..a2cdde0ca0a72f42ef7cc4e2929fda910c066548 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -1458,6 +1458,25 @@ bool amdgpu_device_need_post(struct amdgpu_device *adev) return true; } +/* + * Intel hosts such as Raptor Lake and Sapphire Rapids don't support dynamic + * speed switching. Until we have confirmation from Intel that a specific host + * supports it, it's safer that we keep it disabled for all. + * + * https://edc.intel.com/content/www/us/en/design/products/platforms/details/raptor-lake-s/13th-generation-core-processors-datasheet-volume-1-of-2/005/pci-express-support/ + * https://gitlab.freedesktop.org/drm/amd/-/issues/2663 + */ +bool amdgpu_device_pcie_dynamic_switching_supported(void) +{ +#if IS_ENABLED(CONFIG_X86) + struct cpuinfo_x86 *c = &cpu_data(0); + + if (c->x86_vendor == X86_VENDOR_INTEL) + return false; +#endif + return true; +} + /** * amdgpu_device_should_use_aspm - check if the device should program ASPM * @@ -2552,7 +2571,7 @@ static int amdgpu_device_ip_init(struct amdgpu_device *adev) adev->ip_blocks[i].status.hw = true; /* right after GMC hw init, we create CSA */ - if (amdgpu_mcbp) { + if (adev->gfx.mcbp) { r = amdgpu_allocate_static_csa(adev, &adev->virt.csa_obj, AMDGPU_GEM_DOMAIN_VRAM | AMDGPU_GEM_DOMAIN_GTT, @@ -3673,6 +3692,23 @@ static const struct attribute *amdgpu_dev_attributes[] = { NULL }; +static void amdgpu_device_set_mcbp(struct amdgpu_device *adev) +{ + if (amdgpu_mcbp == 1) + adev->gfx.mcbp = true; + + if ((adev->ip_versions[GC_HWIP][0] >= IP_VERSION(9, 0, 0)) && + (adev->ip_versions[GC_HWIP][0] < IP_VERSION(10, 0, 0)) && + adev->gfx.num_gfx_rings) + adev->gfx.mcbp = true; + + if (amdgpu_sriov_vf(adev)) + adev->gfx.mcbp = true; + + if (adev->gfx.mcbp) + DRM_INFO("MCBP is enabled\n"); +} + /** * amdgpu_device_init - initialize the driver * @@ -3824,9 +3860,6 @@ int amdgpu_device_init(struct amdgpu_device *adev, DRM_INFO("register mmio base: 0x%08X\n", (uint32_t)adev->rmmio_base); DRM_INFO("register mmio size: %u\n", (unsigned)adev->rmmio_size); - if (amdgpu_mcbp) - DRM_INFO("MCBP is enabled\n"); - /* * Reset domain needs to be present early, before XGMI hive discovered * (if any) and intitialized to use reset sem and in_gpu reset flag @@ -3852,6 +3885,8 @@ int amdgpu_device_init(struct amdgpu_device *adev, if (r) return r; + amdgpu_device_set_mcbp(adev); + /* Get rid of things like offb */ r = drm_aperture_remove_conflicting_pci_framebuffers(adev->pdev, &amdgpu_kms_driver); if (r) @@ -4018,6 +4053,11 @@ int amdgpu_device_init(struct amdgpu_device *adev, /* Get a log2 for easy divisions. */ adev->mm_stats.log2_max_MBps = ilog2(max(1u, max_MBps)); + r = amdgpu_atombios_sysfs_init(adev); + if (r) + drm_err(&adev->ddev, + "registering atombios sysfs failed (%d).\n", r); + r = amdgpu_pm_sysfs_init(adev); if (r) DRM_ERROR("registering pm sysfs failed (%d).\n", r); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index 56dc69bc8b89a5707c0f58d014c285c35cb1089a..e90f730eb715d9fadd26e4c670ac5278e12883b8 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -180,7 +180,7 @@ uint amdgpu_dc_feature_mask = 2; uint amdgpu_dc_debug_mask; uint amdgpu_dc_visual_confirm; int amdgpu_async_gfx_ring = 1; -int amdgpu_mcbp; +int amdgpu_mcbp = -1; int amdgpu_discovery = -1; int amdgpu_mes; int amdgpu_mes_kiq; @@ -634,10 +634,10 @@ module_param_named(async_gfx_ring, amdgpu_async_gfx_ring, int, 0444); /** * DOC: mcbp (int) - * It is used to enable mid command buffer preemption. (0 = disabled (default), 1 = enabled) + * It is used to enable mid command buffer preemption. (0 = disabled, 1 = enabled, -1 auto (default)) */ MODULE_PARM_DESC(mcbp, - "Enable Mid-command buffer preemption (0 = disabled (default), 1 = enabled)"); + "Enable Mid-command buffer preemption (0 = disabled, 1 = enabled), -1 = auto (default)"); module_param_named(mcbp, amdgpu_mcbp, int, 0444); /** @@ -2893,12 +2893,10 @@ static struct pci_error_handlers amdgpu_pci_err_handler = { extern const struct attribute_group amdgpu_vram_mgr_attr_group; extern const struct attribute_group amdgpu_gtt_mgr_attr_group; -extern const struct attribute_group amdgpu_vbios_version_attr_group; static const struct attribute_group *amdgpu_sysfs_groups[] = { &amdgpu_vram_mgr_attr_group, &amdgpu_gtt_mgr_attr_group, - &amdgpu_vbios_version_attr_group, NULL, }; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h index ce0f7a8ad4b87355cfd8408fe3ad00475e10b1a7..a4ff515ce8966ae4e12aad8997d6113b3d63540c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h @@ -434,6 +434,7 @@ struct amdgpu_gfx { uint16_t xcc_mask; uint32_t num_xcc_per_xcp; struct mutex partition_mutex; + bool mcbp; /* mid command buffer preemption */ }; struct amdgpu_gfx_ras_reg_entry { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.c index 3add4b4f0667f4ace2696b9d46f9ea87dcc9f224..2ff2897fd1db6ccf9bc6b1e597a389fb5db36b8d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.c @@ -255,7 +255,8 @@ int amdgpu_jpeg_ras_late_init(struct amdgpu_device *adev, struct ras_common_if * if (amdgpu_ras_is_supported(adev, ras_block->block)) { for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) { - if (adev->jpeg.harvest_config & (1 << i)) + if (adev->jpeg.harvest_config & (1 << i) || + !adev->jpeg.inst[i].ras_poison_irq.funcs) continue; r = amdgpu_irq_get(adev, &adev->jpeg.inst[i].ras_poison_irq, 0); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c index e3531aa3c8bd101935314b6214f8181c5a0c05aa..cca5a495611f3ba1454d0ecfb231618f64e019cb 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c @@ -805,7 +805,7 @@ int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) dev_info->ids_flags = 0; if (adev->flags & AMD_IS_APU) dev_info->ids_flags |= AMDGPU_IDS_FLAGS_FUSION; - if (amdgpu_mcbp) + if (adev->gfx.mcbp) dev_info->ids_flags |= AMDGPU_IDS_FLAGS_PREEMPTION; if (amdgpu_is_tmz(adev)) dev_info->ids_flags |= AMDGPU_IDS_FLAGS_TMZ; @@ -1247,7 +1247,7 @@ int amdgpu_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv) goto error_vm; } - if (amdgpu_mcbp) { + if (adev->gfx.mcbp) { uint64_t csa_addr = amdgpu_csa_vaddr(adev) & AMDGPU_GMC_HOLE_MASK; r = amdgpu_map_static_csa(adev, &fpriv->vm, adev->virt.csa_obj, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c index e15c27e05564c7347be5a5f3a70f0fa4c5c23f90..6d676bdd1505b17deab4639413ee06ba8ca8eeaf 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c @@ -839,6 +839,7 @@ static bool psp_skip_tmr(struct psp_context *psp) case IP_VERSION(11, 0, 9): case IP_VERSION(11, 0, 7): case IP_VERSION(13, 0, 2): + case IP_VERSION(13, 0, 6): case IP_VERSION(13, 0, 10): return true; default: @@ -2039,6 +2040,8 @@ static int psp_securedisplay_initialize(struct psp_context *psp) psp_securedisplay_parse_resp_status(psp, securedisplay_cmd->status); dev_err(psp->adev->dev, "SECUREDISPLAY: query securedisplay TA failed. ret 0x%x\n", securedisplay_cmd->securedisplay_out_message.query_ta.query_cmd_ret); + /* don't try again */ + psp->securedisplay_context.context.bin_desc.size_bytes = 0; } return 0; @@ -3703,7 +3706,6 @@ static DEVICE_ATTR(psp_vbflash_status, 0440, amdgpu_psp_vbflash_status, NULL); int amdgpu_psp_sysfs_init(struct amdgpu_device *adev) { int ret = 0; - struct psp_context *psp = &adev->psp; if (amdgpu_sriov_vf(adev)) return -EINVAL; @@ -3712,10 +3714,6 @@ int amdgpu_psp_sysfs_init(struct amdgpu_device *adev) case IP_VERSION(13, 0, 0): case IP_VERSION(13, 0, 7): case IP_VERSION(13, 0, 10): - if (!psp->adev) { - psp->adev = adev; - psp_v13_0_set_psp_funcs(psp); - } ret = sysfs_create_bin_file(&adev->dev->kobj, &psp_vbflash_bin_attr); if (ret) dev_err(adev->dev, "Failed to create device file psp_vbflash"); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_rap.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_rap.c index 12010c988c8b59b43c82cc28be0a7c08f73e746d..123bcf5c2bb138dc3544c20d7b7a773f56cb8084 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_rap.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_rap.c @@ -116,7 +116,6 @@ static const struct file_operations amdgpu_rap_debugfs_ops = { void amdgpu_rap_debugfs_init(struct amdgpu_device *adev) { -#if defined(CONFIG_DEBUG_FS) struct drm_minor *minor = adev_to_drm(adev)->primary; if (!adev->psp.rap_context.context.initialized) @@ -124,5 +123,4 @@ void amdgpu_rap_debugfs_init(struct amdgpu_device *adev) debugfs_create_file("rap_test", S_IWUSR, minor->debugfs_root, adev, &amdgpu_rap_debugfs_ops); -#endif } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index 4769a18304d7a4435403ffce859902b25e70f816..8aaa427f8c0f63cfe824eb3c2f360737bfe7933a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -2065,6 +2065,14 @@ static void amdgpu_ras_do_recovery(struct work_struct *work) ras->gpu_reset_flags &= ~AMDGPU_RAS_GPU_RESET_MODE2_RESET; reset_context.method = AMD_RESET_METHOD_MODE2; } + + /* Fatal error occurs in poison mode, mode1 reset is used to + * recover gpu. + */ + if (ras->gpu_reset_flags & AMDGPU_RAS_GPU_RESET_MODE1_RESET) { + ras->gpu_reset_flags &= ~AMDGPU_RAS_GPU_RESET_MODE1_RESET; + set_bit(AMDGPU_NEED_FULL_RESET, &reset_context.flags); + } } amdgpu_device_gpu_recover(ras->adev, NULL, &reset_context); @@ -2955,9 +2963,12 @@ void amdgpu_ras_global_ras_isr(struct amdgpu_device *adev) return; if (atomic_cmpxchg(&amdgpu_ras_in_intr, 0, 1) == 0) { + struct amdgpu_ras *ras = amdgpu_ras_get_context(adev); + dev_info(adev->dev, "uncorrectable hardware error" "(ERREVENT_ATHUB_INTERRUPT) detected!\n"); + ras->gpu_reset_flags |= AMDGPU_RAS_GPU_RESET_MODE1_RESET; amdgpu_ras_reset_gpu(adev); } } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h index 46bf1889a9d753defcd5c8acace7b047bd4f98cf..ffb49b2d533adcf3ab07c1655e289022655907fc 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h @@ -340,6 +340,7 @@ enum amdgpu_ras_ret { #define AMDGPU_RAS_ERR_ADDRESS_VALID (1 << 2) #define AMDGPU_RAS_GPU_RESET_MODE2_RESET (0x1 << 0) +#define AMDGPU_RAS_GPU_RESET_MODE1_RESET (0x1 << 1) struct amdgpu_ras_err_status_reg_entry { uint32_t hwip; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring_mux.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring_mux.c index 73516abef662f00f8b418a78a757adefb7bf7eef..b779ee4bbaa7b36273247638de6f3f478e98a0d4 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring_mux.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring_mux.c @@ -423,6 +423,9 @@ void amdgpu_sw_ring_ib_mark_offset(struct amdgpu_ring *ring, enum amdgpu_ring_mu struct amdgpu_ring_mux *mux = &adev->gfx.muxer; unsigned offset; + if (ring->hw_prio > AMDGPU_RING_PRIO_DEFAULT) + return; + offset = ring->wptr & ring->buf_mask; amdgpu_ring_mux_ib_mark_offset(mux, ring, offset, type); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c index 78ec3420ef85307ba81e40d2876bab90ff20833c..dacf281d2b217594490ebb11b4ebe937b236c959 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c @@ -72,7 +72,7 @@ uint64_t amdgpu_sdma_get_csa_mc_addr(struct amdgpu_ring *ring, int r; /* don't enable OS preemption on SDMA under SRIOV */ - if (amdgpu_sriov_vf(adev) || vmid == 0 || !amdgpu_mcbp) + if (amdgpu_sriov_vf(adev) || vmid == 0 || !adev->gfx.mcbp) return 0; if (ring->is_mes_queue) { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c index acbef1a24b9c2e3afc7e3e1654cdc2fa0ce65afb..ae455aab5d29ddfd154e0533796b88b96cdfc98a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c @@ -1198,7 +1198,8 @@ int amdgpu_vcn_ras_late_init(struct amdgpu_device *adev, struct ras_common_if *r if (amdgpu_ras_is_supported(adev, ras_block->block)) { for (i = 0; i < adev->vcn.num_vcn_inst; i++) { - if (adev->vcn.harvest_config & (1 << i)) + if (adev->vcn.harvest_config & (1 << i) || + !adev->vcn.inst[i].ras_poison_irq.funcs) continue; r = amdgpu_irq_get(adev, &adev->vcn.inst[i].ras_poison_irq, 0); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c index 25b4d7f0bd35996b4bb69d952dcb3ef2008bf57b..41aa853a07d24d3bada2f7e1f6a44c6f3981f473 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c @@ -66,9 +66,6 @@ void amdgpu_virt_init_setting(struct amdgpu_device *adev) adev->cg_flags = 0; adev->pg_flags = 0; - /* enable mcbp for sriov */ - amdgpu_mcbp = 1; - /* Reduce kcq number to 2 to reduce latency */ if (amdgpu_num_kcq == -1) amdgpu_num_kcq = 2; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index 854260171dfdf1c885800c450c35635813ea3e2a..d0e6009a985bc0ce8748bbc88c902aae1dd506ed 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -1767,18 +1767,30 @@ int amdgpu_vm_bo_clear_mappings(struct amdgpu_device *adev, /* Insert partial mapping before the range */ if (!list_empty(&before->list)) { + struct amdgpu_bo *bo = before->bo_va->base.bo; + amdgpu_vm_it_insert(before, &vm->va); if (before->flags & AMDGPU_PTE_PRT) amdgpu_vm_prt_get(adev); + + if (bo && bo->tbo.base.resv == vm->root.bo->tbo.base.resv && + !before->bo_va->base.moved) + amdgpu_vm_bo_moved(&before->bo_va->base); } else { kfree(before); } /* Insert partial mapping after the range */ if (!list_empty(&after->list)) { + struct amdgpu_bo *bo = after->bo_va->base.bo; + amdgpu_vm_it_insert(after, &vm->va); if (after->flags & AMDGPU_PTE_PRT) amdgpu_vm_prt_get(adev); + + if (bo && bo->tbo.base.resv == vm->root.bo->tbo.base.resv && + !after->bo_va->base.moved) + amdgpu_vm_bo_moved(&after->bo_va->base); } else { kfree(after); } @@ -2229,16 +2241,16 @@ int amdgpu_vm_make_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm) if (r) return r; - /* Sanity checks */ - if (!amdgpu_vm_pt_is_root_clean(adev, vm)) { - r = -EINVAL; - goto unreserve_bo; - } - /* Check if PD needs to be reinitialized and do it before * changing any other state, in case it fails. */ if (pte_support_ats != vm->pte_support_ats) { + /* Sanity checks */ + if (!amdgpu_vm_pt_is_root_clean(adev, vm)) { + r = -EINVAL; + goto unreserve_bo; + } + vm->pte_support_ats = pte_support_ats; r = amdgpu_vm_pt_clear(adev, vm, to_amdgpu_bo_vm(vm->root.bo), false); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c index d733fa6e7477e75f4f71c1895dd5e68953b868f8..d175e862f2226a3d13dcce57b161d7223aa13adf 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c @@ -132,6 +132,9 @@ int amdgpu_xcp_init(struct amdgpu_xcp_mgr *xcp_mgr, int num_xcps, int mode) for (i = 0; i < MAX_XCP; ++i) xcp_mgr->xcp[i].valid = false; + /* This is needed for figuring out memory id of xcp */ + xcp_mgr->num_xcp_per_mem_partition = num_xcps / xcp_mgr->adev->gmc.num_mem_partitions; + for (i = 0; i < num_xcps; ++i) { for (j = AMDGPU_XCP_GFXHUB; j < AMDGPU_XCP_MAX_BLOCKS; ++j) { ret = xcp_mgr->funcs->get_ip_details(xcp_mgr, i, j, @@ -157,7 +160,6 @@ int amdgpu_xcp_init(struct amdgpu_xcp_mgr *xcp_mgr, int num_xcps, int mode) xcp_mgr->num_xcps = num_xcps; amdgpu_xcp_update_partition_sched_list(adev); - xcp_mgr->num_xcp_per_mem_partition = num_xcps / xcp_mgr->adev->gmc.num_mem_partitions; return 0; } @@ -232,7 +234,10 @@ static int amdgpu_xcp_dev_alloc(struct amdgpu_device *adev) ddev = adev_to_drm(adev); - for (i = 0; i < MAX_XCP; i++) { + /* xcp #0 shares drm device setting with adev */ + adev->xcp_mgr->xcp->ddev = ddev; + + for (i = 1; i < MAX_XCP; i++) { ret = amdgpu_xcp_drm_dev_alloc(&p_ddev); if (ret) return ret; @@ -322,7 +327,7 @@ int amdgpu_xcp_dev_register(struct amdgpu_device *adev, if (!adev->xcp_mgr) return 0; - for (i = 0; i < MAX_XCP; i++) { + for (i = 1; i < MAX_XCP; i++) { ret = drm_dev_register(adev->xcp_mgr->xcp[i].ddev, ent->driver_data); if (ret) return ret; @@ -339,7 +344,7 @@ void amdgpu_xcp_dev_unplug(struct amdgpu_device *adev) if (!adev->xcp_mgr) return; - for (i = 0; i < MAX_XCP; i++) { + for (i = 1; i < MAX_XCP; i++) { p_ddev = adev->xcp_mgr->xcp[i].ddev; drm_dev_unplug(p_ddev); p_ddev->render->dev = adev->xcp_mgr->xcp[i].rdev; diff --git a/drivers/gpu/drm/amd/amdgpu/atom.c b/drivers/gpu/drm/amd/amdgpu/atom.c index 1c5d9388ad0bb930a0aab5df6e7c6f6b5ebe1bda..5f610e9a5f0f839fb25a67cb1357580818c7ed01 100644 --- a/drivers/gpu/drm/amd/amdgpu/atom.c +++ b/drivers/gpu/drm/amd/amdgpu/atom.c @@ -1509,7 +1509,7 @@ struct atom_context *amdgpu_atom_parse(struct card_info *card, void *bios) str = CSTR(idx); if (*str != '\0') { pr_info("ATOM BIOS: %s\n", str); - strlcpy(ctx->vbios_version, str, sizeof(ctx->vbios_version)); + strscpy(ctx->vbios_version, str, sizeof(ctx->vbios_version)); } atom_rom_header = (struct _ATOM_ROM_HEADER *)CSTR(base); diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c index be984f8c71c7b1dca28bbe1188b4d87f847af1d9..44af8022b89fa96900f751c3e224b5b82995f2f4 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c @@ -8307,7 +8307,7 @@ static void gfx_v10_0_ring_emit_ib_gfx(struct amdgpu_ring *ring, control |= ib->length_dw | (vmid << 24); - if (amdgpu_mcbp && (ib->flags & AMDGPU_IB_FLAG_PREEMPT)) { + if (ring->adev->gfx.mcbp && (ib->flags & AMDGPU_IB_FLAG_PREEMPT)) { control |= INDIRECT_BUFFER_PRE_ENB(1); if (flags & AMDGPU_IB_PREEMPTED) @@ -8482,7 +8482,7 @@ static void gfx_v10_0_ring_emit_cntxcntl(struct amdgpu_ring *ring, { uint32_t dw2 = 0; - if (amdgpu_mcbp) + if (ring->adev->gfx.mcbp) gfx_v10_0_ring_emit_ce_meta(ring, (!amdgpu_sriov_vf(ring->adev) && flags & AMDGPU_IB_PREEMPTED) ? true : false); diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c index 690e121d9ddaa7fed47a63cdfbaa80f5afe4f2d1..3a7af59e83ca11ea1409e8903899d302b5b3187c 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c @@ -5311,7 +5311,7 @@ static void gfx_v11_0_ring_emit_ib_gfx(struct amdgpu_ring *ring, control |= ib->length_dw | (vmid << 24); - if (amdgpu_mcbp && (ib->flags & AMDGPU_IB_FLAG_PREEMPT)) { + if (ring->adev->gfx.mcbp && (ib->flags & AMDGPU_IB_FLAG_PREEMPT)) { control |= INDIRECT_BUFFER_PRE_ENB(1); if (flags & AMDGPU_IB_PREEMPTED) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c index c1ee54d4c3d3dc198b4983dbc6c9f690cf289cf8..9e3b835bdbb263ca8263215b759909900e54c14e 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c @@ -623,12 +623,28 @@ static void gfx_v9_4_3_select_me_pipe_q(struct amdgpu_device *adev, static int gfx_v9_4_3_switch_compute_partition(struct amdgpu_device *adev, int num_xccs_per_xcp) { - int ret; - - ret = psp_spatial_partition(&adev->psp, NUM_XCC(adev->gfx.xcc_mask) / - num_xccs_per_xcp); - if (ret) - return ret; + int ret, i, num_xcc; + u32 tmp = 0; + + if (adev->psp.funcs) { + ret = psp_spatial_partition(&adev->psp, + NUM_XCC(adev->gfx.xcc_mask) / + num_xccs_per_xcp); + if (ret) + return ret; + } else { + num_xcc = NUM_XCC(adev->gfx.xcc_mask); + + for (i = 0; i < num_xcc; i++) { + tmp = REG_SET_FIELD(tmp, CP_HYP_XCP_CTL, NUM_XCC_IN_XCP, + num_xccs_per_xcp); + tmp = REG_SET_FIELD(tmp, CP_HYP_XCP_CTL, VIRTUAL_XCC_ID, + i % num_xccs_per_xcp); + WREG32_SOC15(GC, GET_INST(GC, i), regCP_HYP_XCP_CTL, + tmp); + } + ret = 0; + } adev->gfx.num_xcc_per_xcp = num_xccs_per_xcp; @@ -1762,6 +1778,8 @@ static int gfx_v9_4_3_xcc_kiq_init_queue(struct amdgpu_ring *ring, int xcc_id) ((struct v9_mqd_allocation *)mqd)->dynamic_cu_mask = 0xFFFFFFFF; ((struct v9_mqd_allocation *)mqd)->dynamic_rb_mask = 0xFFFFFFFF; mutex_lock(&adev->srbm_mutex); + if (amdgpu_sriov_vf(adev) && adev->in_suspend) + amdgpu_ring_clear_ring(ring); soc15_grbm_select(adev, ring->me, ring->pipe, ring->queue, 0, GET_INST(GC, xcc_id)); gfx_v9_4_3_xcc_mqd_init(ring, xcc_id); gfx_v9_4_3_xcc_kiq_init_register(ring, xcc_id); @@ -1960,6 +1978,16 @@ static void gfx_v9_4_3_xcc_fini(struct amdgpu_device *adev, int xcc_id) if (amdgpu_gfx_disable_kcq(adev, xcc_id)) DRM_ERROR("XCD %d KCQ disable failed\n", xcc_id); + if (amdgpu_sriov_vf(adev)) { + /* must disable polling for SRIOV when hw finished, otherwise + * CPC engine may still keep fetching WB address which is already + * invalid after sw finished and trigger DMAR reading error in + * hypervisor side. + */ + WREG32_FIELD15_PREREG(GC, GET_INST(GC, xcc_id), CP_PQ_WPTR_POLL_CNTL, EN, 0); + return; + } + /* Use deinitialize sequence from CAIL when unbinding device * from driver, otherwise KIQ is hanging when binding back */ @@ -1984,7 +2012,8 @@ static int gfx_v9_4_3_hw_init(void *handle) int r; struct amdgpu_device *adev = (struct amdgpu_device *)handle; - gfx_v9_4_3_init_golden_registers(adev); + if (!amdgpu_sriov_vf(adev)) + gfx_v9_4_3_init_golden_registers(adev); gfx_v9_4_3_constants_init(adev); diff --git a/drivers/gpu/drm/amd/amdgpu/nbio_v2_3.c b/drivers/gpu/drm/amd/amdgpu/nbio_v2_3.c index aa761ff3a5faec4e383b93f7467d13b27974bce6..4038455d799845ce199a11c88d32711a8a76d00d 100644 --- a/drivers/gpu/drm/amd/amdgpu/nbio_v2_3.c +++ b/drivers/gpu/drm/amd/amdgpu/nbio_v2_3.c @@ -345,8 +345,8 @@ static void nbio_v2_3_init_registers(struct amdgpu_device *adev) } #define NAVI10_PCIE__LC_L0S_INACTIVITY_DEFAULT 0x00000000 // off by default, no gains over L1 -#define NAVI10_PCIE__LC_L1_INACTIVITY_DEFAULT 0x00000009 // 1=1us, 9=1ms -#define NAVI10_PCIE__LC_L1_INACTIVITY_TBT_DEFAULT 0x0000000E // 4ms +#define NAVI10_PCIE__LC_L1_INACTIVITY_DEFAULT 0x0000000A // 1=1us, 9=1ms, 10=4ms +#define NAVI10_PCIE__LC_L1_INACTIVITY_TBT_DEFAULT 0x0000000E // 400ms static void nbio_v2_3_enable_aspm(struct amdgpu_device *adev, bool enable) @@ -479,9 +479,12 @@ static void nbio_v2_3_program_aspm(struct amdgpu_device *adev) WREG32_SOC15(NBIO, 0, mmRCC_BIF_STRAP5, data); def = data = RREG32_PCIE(smnPCIE_LC_CNTL); - data &= ~PCIE_LC_CNTL__LC_L0S_INACTIVITY_MASK; - data |= 0x9 << PCIE_LC_CNTL__LC_L1_INACTIVITY__SHIFT; - data |= 0x1 << PCIE_LC_CNTL__LC_PMI_TO_L1_DIS__SHIFT; + data |= NAVI10_PCIE__LC_L0S_INACTIVITY_DEFAULT << PCIE_LC_CNTL__LC_L0S_INACTIVITY__SHIFT; + if (pci_is_thunderbolt_attached(adev->pdev)) + data |= NAVI10_PCIE__LC_L1_INACTIVITY_TBT_DEFAULT << PCIE_LC_CNTL__LC_L1_INACTIVITY__SHIFT; + else + data |= NAVI10_PCIE__LC_L1_INACTIVITY_DEFAULT << PCIE_LC_CNTL__LC_L1_INACTIVITY__SHIFT; + data &= ~PCIE_LC_CNTL__LC_PMI_TO_L1_DIS_MASK; if (def != data) WREG32_PCIE(smnPCIE_LC_CNTL, data); 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 ea5e12390d182830f3bcce6a531154b082a00479..f413898dda37dbe75788f3b69db22f968c7d484f 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c @@ -578,6 +578,9 @@ static void sdma_v4_4_2_inst_enable(struct amdgpu_device *adev, bool enable, return; } + if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) + return; + for_each_inst(i, inst_mask) { f32_cntl = RREG32_SDMA(i, regSDMA_F32_CNTL); f32_cntl = REG_SET_FIELD(f32_cntl, SDMA_F32_CNTL, HALT, enable ? 0 : 1); @@ -899,15 +902,12 @@ static int sdma_v4_4_2_inst_start(struct amdgpu_device *adev, WREG32_SDMA(i, regSDMA_CNTL, temp); if (!amdgpu_sriov_vf(adev)) { - ring = &adev->sdma.instance[i].ring; - adev->nbio.funcs->sdma_doorbell_range(adev, i, - ring->use_doorbell, ring->doorbell_index, - adev->doorbell_index.sdma_doorbell_range); - - /* unhalt engine */ - temp = RREG32_SDMA(i, regSDMA_F32_CNTL); - temp = REG_SET_FIELD(temp, SDMA_F32_CNTL, HALT, 0); - WREG32_SDMA(i, regSDMA_F32_CNTL, temp); + if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP) { + /* unhalt engine */ + temp = RREG32_SDMA(i, regSDMA_F32_CNTL); + temp = REG_SET_FIELD(temp, SDMA_F32_CNTL, HALT, 0); + WREG32_SDMA(i, regSDMA_F32_CNTL, temp); + } } } diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c index b48bb52124884a90aab32eaeb3209d861f63866d..259795098173ac5cb7800959536bb51e1342abeb 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c @@ -1424,8 +1424,10 @@ static int vcn_v4_0_start_sriov(struct amdgpu_device *adev) */ static void vcn_v4_0_stop_dpg_mode(struct amdgpu_device *adev, int inst_idx) { + struct dpg_pause_state state = {.fw_based = VCN_DPG_STATE__UNPAUSE}; uint32_t tmp; + vcn_v4_0_pause_dpg_mode(adev, inst_idx, &state); /* Wait for power status to be 1 */ SOC15_WAIT_ON_RREG(VCN, inst_idx, regUVD_POWER_STATUS, 1, UVD_POWER_STATUS__UVD_POWER_STATUS_MASK); diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device.c b/drivers/gpu/drm/amd/amdkfd/kfd_device.c index 9d4abfd8b55ebb70d979e0362488c1cfc2a8e17b..0b3dc754e06ba264bf25835f33c7607a6fae4dfe 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device.c @@ -138,9 +138,12 @@ static void kfd_device_info_set_event_interrupt_class(struct kfd_dev *kfd) case IP_VERSION(9, 4, 0): /* VEGA20 */ case IP_VERSION(9, 4, 1): /* ARCTURUS */ case IP_VERSION(9, 4, 2): /* ALDEBARAN */ - case IP_VERSION(9, 4, 3): /* GC 9.4.3 */ kfd->device_info.event_interrupt_class = &event_interrupt_class_v9; break; + case IP_VERSION(9, 4, 3): /* GC 9.4.3 */ + kfd->device_info.event_interrupt_class = + &event_interrupt_class_v9_4_3; + break; case IP_VERSION(10, 3, 1): /* VANGOGH */ case IP_VERSION(10, 3, 3): /* YELLOW_CARP */ case IP_VERSION(10, 3, 6): /* GC 10.3.6 */ @@ -518,6 +521,7 @@ static int kfd_gws_init(struct kfd_node *node) && kfd->mec2_fw_version >= 0x30) || (KFD_GC_VERSION(node) == IP_VERSION(9, 4, 2) && kfd->mec2_fw_version >= 0x28) || + (KFD_GC_VERSION(node) == IP_VERSION(9, 4, 3)) || (KFD_GC_VERSION(node) >= IP_VERSION(10, 3, 0) && KFD_GC_VERSION(node) < IP_VERSION(11, 0, 0) && kfd->mec2_fw_version >= 0x6b)))) @@ -598,6 +602,41 @@ static void kfd_cleanup_nodes(struct kfd_dev *kfd, unsigned int num_nodes) } } +static void kfd_setup_interrupt_bitmap(struct kfd_node *node, + unsigned int kfd_node_idx) +{ + struct amdgpu_device *adev = node->adev; + uint32_t xcc_mask = node->xcc_mask; + uint32_t xcc, mapped_xcc; + /* + * Interrupt bitmap is setup for processing interrupts from + * different XCDs and AIDs. + * Interrupt bitmap is defined as follows: + * 1. Bits 0-15 - correspond to the NodeId field. + * Each bit corresponds to NodeId number. For example, if + * a KFD node has interrupt bitmap set to 0x7, then this + * KFD node will process interrupts with NodeId = 0, 1 and 2 + * in the IH cookie. + * 2. Bits 16-31 - unused. + * + * Please note that the kfd_node_idx argument passed to this + * function is not related to NodeId field received in the + * IH cookie. + * + * In CPX mode, a KFD node will process an interrupt if: + * - the Node Id matches the corresponding bit set in + * Bits 0-15. + * - AND VMID reported in the interrupt lies within the + * VMID range of the node. + */ + for_each_inst(xcc, xcc_mask) { + mapped_xcc = GET_INST(GC, xcc); + node->interrupt_bitmap |= (mapped_xcc % 2 ? 5 : 3) << (4 * (mapped_xcc / 2)); + } + dev_info(kfd_device, "Node: %d, interrupt_bitmap: %x\n", kfd_node_idx, + node->interrupt_bitmap); +} + bool kgd2kfd_device_init(struct kfd_dev *kfd, const struct kgd2kfd_shared_resources *gpu_resources) { @@ -797,6 +836,9 @@ bool kgd2kfd_device_init(struct kfd_dev *kfd, amdgpu_amdkfd_get_local_mem_info(kfd->adev, &node->local_mem_info, node->xcp); + if (KFD_GC_VERSION(kfd) == IP_VERSION(9, 4, 3)) + kfd_setup_interrupt_bitmap(node, i); + /* Initialize the KFD node */ if (kfd_init_node(node)) { dev_err(kfd_device, "Error initializing KFD node\n"); 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 d5c9f30552e3bd17e7621b33896ebe6a1f9b92ef..f0731a6a5306cd14b6ed2e3e660cb2a45ade3499 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c @@ -446,7 +446,36 @@ static void event_interrupt_wq_v9(struct kfd_node *dev, } } +static bool event_interrupt_isr_v9_4_3(struct kfd_node *node, + const uint32_t *ih_ring_entry, + uint32_t *patched_ihre, + bool *patched_flag) +{ + uint16_t node_id, vmid; + + /* + * For GFX 9.4.3, process the interrupt if: + * - NodeID field in IH entry matches the corresponding bit + * set in interrupt_bitmap Bits 0-15. + * OR + * - If partition mode is CPX and interrupt came from + * Node_id 0,4,8,12, then check if the Bit (16 + client id) + * is set in interrupt bitmap Bits 16-31. + */ + node_id = SOC15_NODEID_FROM_IH_ENTRY(ih_ring_entry); + vmid = SOC15_VMID_FROM_IH_ENTRY(ih_ring_entry); + if (kfd_irq_is_from_node(node, node_id, vmid)) + return event_interrupt_isr_v9(node, ih_ring_entry, + patched_ihre, patched_flag); + return false; +} + const struct kfd_event_interrupt_class event_interrupt_class_v9 = { .interrupt_isr = event_interrupt_isr_v9, .interrupt_wq = event_interrupt_wq_v9, }; + +const struct kfd_event_interrupt_class event_interrupt_class_v9_4_3 = { + .interrupt_isr = event_interrupt_isr_v9_4_3, + .interrupt_wq = event_interrupt_wq_v9, +}; diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h index 7364a5d77c6ee065487df119c817bed2921821a5..d4c9ee3f99533acc685d63c13b624a9c6a408f6b 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h @@ -1444,6 +1444,7 @@ uint64_t kfd_get_number_elems(struct kfd_dev *kfd); /* Events */ extern const struct kfd_event_interrupt_class event_interrupt_class_cik; extern const struct kfd_event_interrupt_class event_interrupt_class_v9; +extern const struct kfd_event_interrupt_class event_interrupt_class_v9_4_3; extern const struct kfd_event_interrupt_class event_interrupt_class_v10; extern const struct kfd_event_interrupt_class event_interrupt_class_v11; diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c index 3d3611705d4199b90c8cd9b249b9d5b594852e5f..a844e68211accf10dd188d5c6f44ebe4c3486ca0 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c @@ -2142,6 +2142,7 @@ void kfd_flush_tlb(struct kfd_process_device *pdd, enum TLB_FLUSH_TYPE type) int kfd_process_drain_interrupts(struct kfd_process_device *pdd) { uint32_t irq_drain_fence[8]; + uint8_t node_id = 0; int r = 0; if (!KFD_IS_SOC15(pdd->dev)) @@ -2154,6 +2155,14 @@ int kfd_process_drain_interrupts(struct kfd_process_device *pdd) KFD_IRQ_FENCE_CLIENTID; irq_drain_fence[3] = pdd->process->pasid; + /* + * For GFX 9.4.3, send the NodeId also in IH cookie DW[3] + */ + if (KFD_GC_VERSION(pdd->dev->kfd) == IP_VERSION(9, 4, 3)) { + node_id = ffs(pdd->dev->interrupt_bitmap) - 1; + irq_drain_fence[3] |= node_id << 16; + } + /* ensure stale irqs scheduled KFD interrupts and send drain fence. */ if (amdgpu_amdkfd_send_close_event_drain_irq(pdd->dev->adev, irq_drain_fence)) { diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c index 9ad1a2186a245ef74c07681d9324648d2dfb9628..ba9d690541193a2579c4a2aefd9e76ddc0073f11 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c @@ -123,16 +123,24 @@ int pqm_set_gws(struct process_queue_manager *pqm, unsigned int qid, if (!gws && pdd->qpd.num_gws == 0) return -EINVAL; - if (gws) - ret = amdgpu_amdkfd_add_gws_to_process(pdd->process->kgd_process_info, - gws, &mem); - else - ret = amdgpu_amdkfd_remove_gws_from_process(pdd->process->kgd_process_info, - pqn->q->gws); - if (unlikely(ret)) - return ret; + if (KFD_GC_VERSION(dev) != IP_VERSION(9, 4, 3)) { + if (gws) + ret = amdgpu_amdkfd_add_gws_to_process(pdd->process->kgd_process_info, + gws, &mem); + else + ret = amdgpu_amdkfd_remove_gws_from_process(pdd->process->kgd_process_info, + pqn->q->gws); + if (unlikely(ret)) + return ret; + pqn->q->gws = mem; + } else { + /* + * Intentionally set GWS to a non-NULL value + * for GFX 9.4.3. + */ + pqn->q->gws = gws ? ERR_PTR(-ENOMEM) : NULL; + } - pqn->q->gws = mem; pdd->qpd.num_gws = gws ? dev->adev->gds.gws_size : 0; return pqn->q->device->dqm->ops.update_queue(pqn->q->device->dqm, @@ -164,7 +172,8 @@ void pqm_uninit(struct process_queue_manager *pqm) struct process_queue_node *pqn, *next; list_for_each_entry_safe(pqn, next, &pqm->queues, process_queue_list) { - if (pqn->q && pqn->q->gws) + if (pqn->q && pqn->q->gws && + KFD_GC_VERSION(pqn->q->device) != IP_VERSION(9, 4, 3)) amdgpu_amdkfd_remove_gws_from_process(pqm->process->kgd_process_info, pqn->q->gws); kfd_procfs_del_queue(pqn->q); @@ -446,8 +455,10 @@ int pqm_destroy_queue(struct process_queue_manager *pqm, unsigned int qid) } if (pqn->q->gws) { - amdgpu_amdkfd_remove_gws_from_process(pqm->process->kgd_process_info, - pqn->q->gws); + if (KFD_GC_VERSION(pqn->q->device) != IP_VERSION(9, 4, 3)) + amdgpu_amdkfd_remove_gws_from_process( + pqm->process->kgd_process_info, + pqn->q->gws); pdd->qpd.num_gws = 0; } diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c index 90b86a6ac7bd63f030a1ccef73fa0e582cb19ea3..61fc62f3e0034a1b129ddb4ad298cb2667fa556d 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c @@ -2107,6 +2107,10 @@ int kfd_topology_add_device(struct kfd_node *gpu) if (KFD_IS_SVM_API_SUPPORTED(dev->gpu->adev)) dev->node_props.capability |= HSA_CAP_SVMAPI_SUPPORTED; + if (dev->gpu->adev->gmc.is_app_apu || + dev->gpu->adev->gmc.xgmi.connected_to_cpu) + dev->node_props.capability |= HSA_CAP_FLAGS_COHERENTHOSTACCESS; + kfd_debug_print_topology(); kfd_notify_gpu_change(gpu_id, 1); diff --git a/drivers/gpu/drm/amd/amdkfd/soc15_int.h b/drivers/gpu/drm/amd/amdkfd/soc15_int.h index e3f3b0b93a59a426a27c2f464b8128e34301193a..10138676f27fd79503db9356ce4d436198bb0c70 100644 --- a/drivers/gpu/drm/amd/amdkfd/soc15_int.h +++ b/drivers/gpu/drm/amd/amdkfd/soc15_int.h @@ -40,6 +40,7 @@ #define SOC15_VMID_FROM_IH_ENTRY(entry) (le32_to_cpu(entry[0]) >> 24 & 0xf) #define SOC15_VMID_TYPE_FROM_IH_ENTRY(entry) (le32_to_cpu(entry[0]) >> 31 & 0x1) #define SOC15_PASID_FROM_IH_ENTRY(entry) (le32_to_cpu(entry[3]) & 0xffff) +#define SOC15_NODEID_FROM_IH_ENTRY(entry) (le32_to_cpu(entry[3]) >> 16 & 0xff) #define SOC15_CONTEXT_ID0_FROM_IH_ENTRY(entry) (le32_to_cpu(entry[4])) #define SOC15_CONTEXT_ID1_FROM_IH_ENTRY(entry) (le32_to_cpu(entry[5])) #define SOC15_CONTEXT_ID2_FROM_IH_ENTRY(entry) (le32_to_cpu(entry[6])) 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 514f6785a02093ea3b19221d6fac4ad18e078cee..ff0a217b9d567b8cb768e7d9e42f2c663e3536dd 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -5063,11 +5063,7 @@ static inline void fill_dc_dirty_rect(struct drm_plane *plane, s32 y, s32 width, s32 height, int *i, bool ffu) { - if (*i > DC_MAX_DIRTY_RECTS) - return; - - if (*i == DC_MAX_DIRTY_RECTS) - goto out; + WARN_ON(*i >= DC_MAX_DIRTY_RECTS); dirty_rect->x = x; dirty_rect->y = y; @@ -5083,7 +5079,6 @@ static inline void fill_dc_dirty_rect(struct drm_plane *plane, "[PLANE:%d] PSR SU dirty rect at (%d, %d) size (%d, %d)", plane->base.id, x, y, width, height); -out: (*i)++; } @@ -5170,6 +5165,9 @@ static void fill_dc_dirty_rects(struct drm_plane *plane, *dirty_regions_changed = bb_changed; + if ((num_clips + (bb_changed ? 2 : 0)) > DC_MAX_DIRTY_RECTS) + goto ffu; + if (bb_changed) { fill_dc_dirty_rect(new_plane_state->plane, &dirty_rects[i], new_plane_state->crtc_x, @@ -5199,9 +5197,6 @@ static void fill_dc_dirty_rects(struct drm_plane *plane, new_plane_state->crtc_h, &i, false); } - if (i > DC_MAX_DIRTY_RECTS) - goto ffu; - flip_addrs->dirty_rect_count = i; return; @@ -7258,13 +7253,7 @@ static int amdgpu_dm_connector_get_modes(struct drm_connector *connector) drm_add_modes_noedid(connector, 1920, 1080); } else { amdgpu_dm_connector_ddc_get_modes(connector, edid); - /* most eDP supports only timings from its edid, - * usually only detailed timings are available - * from eDP edid. timings which are not from edid - * may damage eDP - */ - if (connector->connector_type != DRM_MODE_CONNECTOR_eDP) - amdgpu_dm_connector_add_common_modes(encoder, connector); + amdgpu_dm_connector_add_common_modes(encoder, connector); amdgpu_dm_connector_add_freesync_modes(connector, edid); } amdgpu_dm_fbc_init(connector); 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 5ea3284b2b77f0ce189e89d279f3b23c4004c4fd..d63ee636483b86a1b6691d15766cd28a9b376a48 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 @@ -336,6 +336,153 @@ static ssize_t dp_link_settings_write(struct file *f, const char __user *buf, return size; } +static bool dp_mst_is_end_device(struct amdgpu_dm_connector *aconnector) +{ + bool is_end_device = false; + struct drm_dp_mst_topology_mgr *mgr = NULL; + struct drm_dp_mst_port *port = NULL; + + if (aconnector->mst_root && aconnector->mst_root->mst_mgr.mst_state) { + mgr = &aconnector->mst_root->mst_mgr; + port = aconnector->mst_output_port; + + drm_modeset_lock(&mgr->base.lock, NULL); + if (port->pdt == DP_PEER_DEVICE_SST_SINK || + port->pdt == DP_PEER_DEVICE_DP_LEGACY_CONV) + is_end_device = true; + drm_modeset_unlock(&mgr->base.lock); + } + + return is_end_device; +} + +/* Change MST link setting + * + * valid lane count value: 1, 2, 4 + * valid link rate value: + * 06h = 1.62Gbps per lane + * 0Ah = 2.7Gbps per lane + * 0Ch = 3.24Gbps per lane + * 14h = 5.4Gbps per lane + * 1Eh = 8.1Gbps per lane + * 3E8h = 10.0Gbps per lane + * 546h = 13.5Gbps per lane + * 7D0h = 20.0Gbps per lane + * + * debugfs is located at /sys/kernel/debug/dri/0/DP-x/mst_link_settings + * + * for example, to force to 2 lane, 10.0GHz, + * echo 2 0x3e8 > /sys/kernel/debug/dri/0/DP-x/mst_link_settings + * + * Valid input will trigger hotplug event to get new link setting applied + * Invalid input will trigger training setting reset + * + * The usage can be referred to link_settings entry + * + */ +static ssize_t dp_mst_link_setting(struct file *f, const char __user *buf, + size_t size, loff_t *pos) +{ + struct amdgpu_dm_connector *aconnector = file_inode(f)->i_private; + struct dc_link *link = aconnector->dc_link; + struct amdgpu_device *adev = drm_to_adev(aconnector->base.dev); + struct dc *dc = (struct dc *)link->dc; + struct dc_link_settings prefer_link_settings; + char *wr_buf = NULL; + const uint32_t wr_buf_size = 40; + /* 0: lane_count; 1: link_rate */ + int max_param_num = 2; + uint8_t param_nums = 0; + long param[2]; + bool valid_input = true; + + if (!dp_mst_is_end_device(aconnector)) + return -EINVAL; + + if (size == 0) + return -EINVAL; + + wr_buf = kcalloc(wr_buf_size, sizeof(char), GFP_KERNEL); + if (!wr_buf) + return -ENOSPC; + + if (parse_write_buffer_into_params(wr_buf, wr_buf_size, + (long *)param, buf, + max_param_num, + ¶m_nums)) { + kfree(wr_buf); + return -EINVAL; + } + + if (param_nums <= 0) { + kfree(wr_buf); + DRM_DEBUG_DRIVER("user data not be read\n"); + return -EINVAL; + } + + switch (param[0]) { + case LANE_COUNT_ONE: + case LANE_COUNT_TWO: + case LANE_COUNT_FOUR: + break; + default: + valid_input = false; + break; + } + + switch (param[1]) { + case LINK_RATE_LOW: + case LINK_RATE_HIGH: + case LINK_RATE_RBR2: + case LINK_RATE_HIGH2: + case LINK_RATE_HIGH3: + case LINK_RATE_UHBR10: + case LINK_RATE_UHBR13_5: + case LINK_RATE_UHBR20: + break; + default: + valid_input = false; + break; + } + + if (!valid_input) { + kfree(wr_buf); + DRM_DEBUG_DRIVER("Invalid Input value No HW will be programmed\n"); + mutex_lock(&adev->dm.dc_lock); + dc_link_set_preferred_training_settings(dc, NULL, NULL, link, false); + mutex_unlock(&adev->dm.dc_lock); + return -EINVAL; + } + + /* save user force lane_count, link_rate to preferred settings + * spread spectrum will not be changed + */ + prefer_link_settings.link_spread = link->cur_link_settings.link_spread; + prefer_link_settings.use_link_rate_set = false; + prefer_link_settings.lane_count = param[0]; + prefer_link_settings.link_rate = param[1]; + + /* skip immediate retrain, and train to new link setting after hotplug event triggered */ + mutex_lock(&adev->dm.dc_lock); + dc_link_set_preferred_training_settings(dc, &prefer_link_settings, NULL, link, true); + mutex_unlock(&adev->dm.dc_lock); + + mutex_lock(&aconnector->base.dev->mode_config.mutex); + aconnector->base.force = DRM_FORCE_OFF; + mutex_unlock(&aconnector->base.dev->mode_config.mutex); + drm_kms_helper_hotplug_event(aconnector->base.dev); + + msleep(100); + + mutex_lock(&aconnector->base.dev->mode_config.mutex); + aconnector->base.force = DRM_FORCE_UNSPECIFIED; + mutex_unlock(&aconnector->base.dev->mode_config.mutex); + drm_kms_helper_hotplug_event(aconnector->base.dev); + + kfree(wr_buf); + return size; +} + /* function: get current DP PHY settings: voltage swing, pre-emphasis, * post-cursor2 (defined by VESA DP specification) * @@ -2668,6 +2815,12 @@ static const struct file_operations dp_dsc_disable_passthrough_debugfs_fops = { .llseek = default_llseek }; +static const struct file_operations dp_mst_link_settings_debugfs_fops = { + .owner = THIS_MODULE, + .write = dp_mst_link_setting, + .llseek = default_llseek +}; + static const struct { char *name; const struct file_operations *fops; @@ -2691,7 +2844,8 @@ static const struct { {"dsc_disable_passthrough", &dp_dsc_disable_passthrough_debugfs_fops}, {"is_mst_connector", &dp_is_mst_connector_fops}, {"mst_progress_status", &dp_mst_progress_status_fops}, - {"is_dpia_link", &is_dpia_link_fops} + {"is_dpia_link", &is_dpia_link_fops}, + {"mst_link_settings", &dp_mst_link_settings_debugfs_fops} }; static const struct { diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c index cd20cfc049969bfbb9b74d9d05863fda8364666a..d9a482908380dfd06bbac67b42ca6b5795c52997 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c @@ -44,6 +44,30 @@ #include "dm_helpers.h" #include "ddc_service_types.h" +static u32 edid_extract_panel_id(struct edid *edid) +{ + return (u32)edid->mfg_id[0] << 24 | + (u32)edid->mfg_id[1] << 16 | + (u32)EDID_PRODUCT_ID(edid); +} + +static void apply_edid_quirks(struct edid *edid, struct dc_edid_caps *edid_caps) +{ + uint32_t panel_id = edid_extract_panel_id(edid); + + switch (panel_id) { + /* Workaround for some monitors which does not work well with FAMS */ + case drm_edid_encode_panel_id('S', 'A', 'M', 0x0E5E): + case drm_edid_encode_panel_id('S', 'A', 'M', 0x7053): + case drm_edid_encode_panel_id('S', 'A', 'M', 0x71AC): + DRM_DEBUG_DRIVER("Disabling FAMS on monitor with panel id %X\n", panel_id); + edid_caps->panel_patch.disable_fams = true; + break; + default: + return; + } +} + /* dm_helpers_parse_edid_caps * * Parse edid caps @@ -115,6 +139,8 @@ enum dc_edid_status dm_helpers_parse_edid_caps( else edid_caps->speaker_flags = DEFAULT_SPEAKER_LOCATION; + apply_edid_quirks(edid_buf, edid_caps); + kfree(sads); kfree(sadb); diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.c index d647f68fd5630e9609c27dabe2890f6776ef821a..4f61d4f257cd7a908fcbfaeae9540451ec6111b0 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.c @@ -24,6 +24,7 @@ */ #include "amdgpu_dm_psr.h" +#include "dc_dmub_srv.h" #include "dc.h" #include "dm_helpers.h" #include "amdgpu_dm.h" @@ -50,7 +51,7 @@ static bool link_supports_psrsu(struct dc_link *link) !link->dpcd_caps.psr_info.psr2_su_y_granularity_cap) return false; - return true; + return dc_dmub_check_min_version(dc->ctx->dmub_srv->dmub); } /* diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c index 6a811755e2e6f4fa01763f6dd66d1ee02da69efb..cb992aca760dc4690da4b6c348a045be6cd0733e 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c @@ -541,9 +541,18 @@ static void dcn32_update_clocks(struct clk_mgr *clk_mgr_base, clk_mgr_base->clks.p_state_change_support = p_state_change_support; /* to disable P-State switching, set UCLK min = max */ - if (!clk_mgr_base->clks.p_state_change_support) - dcn32_smu_set_hard_min_by_freq(clk_mgr, PPCLK_UCLK, - clk_mgr_base->bw_params->clk_table.entries[clk_mgr_base->bw_params->clk_table.num_entries_per_clk.num_memclk_levels - 1].memclk_mhz); + if (!clk_mgr_base->clks.p_state_change_support) { + if (dc->clk_mgr->dc_mode_softmax_enabled) { + /* On DCN32x we will never have the functional UCLK min above the softmax + * since we calculate mode support based on softmax being the max UCLK + * frequency. + */ + dcn32_smu_set_hard_min_by_freq(clk_mgr, PPCLK_UCLK, + dc->clk_mgr->bw_params->dc_mode_softmax_memclk); + } else { + dcn32_smu_set_hard_min_by_freq(clk_mgr, PPCLK_UCLK, dc->clk_mgr->bw_params->max_memclk_mhz); + } + } } /* Always update saved value, even if new value not set due to P-State switching unsupported. Also check safe_to_lower for FCLK */ @@ -808,8 +817,7 @@ static void dcn32_set_hard_max_memclk(struct clk_mgr *clk_mgr_base) if (!clk_mgr->smu_present) return; - dcn30_smu_set_hard_max_by_freq(clk_mgr, PPCLK_UCLK, - clk_mgr_base->bw_params->clk_table.entries[clk_mgr_base->bw_params->clk_table.num_entries_per_clk.num_memclk_levels - 1].memclk_mhz); + dcn30_smu_set_hard_max_by_freq(clk_mgr, PPCLK_UCLK, clk_mgr_base->bw_params->max_memclk_mhz); } /* Get current memclk states, update bounding box */ @@ -827,6 +835,7 @@ static void dcn32_get_memclk_states_from_smu(struct clk_mgr *clk_mgr_base) &clk_mgr_base->bw_params->clk_table.entries[0].memclk_mhz, &num_entries_per_clk->num_memclk_levels); clk_mgr_base->bw_params->dc_mode_limit.memclk_mhz = dcn30_smu_get_dc_mode_max_dpm_freq(clk_mgr, PPCLK_UCLK); + clk_mgr_base->bw_params->dc_mode_softmax_memclk = clk_mgr_base->bw_params->dc_mode_limit.memclk_mhz; /* memclk must have at least one level */ num_entries_per_clk->num_memclk_levels = num_entries_per_clk->num_memclk_levels ? num_entries_per_clk->num_memclk_levels : 1; @@ -841,7 +850,8 @@ static void dcn32_get_memclk_states_from_smu(struct clk_mgr *clk_mgr_base) } else { num_levels = num_entries_per_clk->num_fclk_levels; } - + clk_mgr_base->bw_params->max_memclk_mhz = + clk_mgr_base->bw_params->clk_table.entries[num_entries_per_clk->num_memclk_levels - 1].memclk_mhz; clk_mgr_base->bw_params->clk_table.num_entries = num_levels ? num_levels : 1; if (clk_mgr->dpm_present && !num_levels) @@ -894,6 +904,25 @@ static bool dcn32_is_smu_present(struct clk_mgr *clk_mgr_base) return clk_mgr->smu_present; } +static void dcn32_set_max_memclk(struct clk_mgr *clk_mgr_base, unsigned int memclk_mhz) +{ + struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base); + + if (!clk_mgr->smu_present) + return; + + dcn30_smu_set_hard_max_by_freq(clk_mgr, PPCLK_UCLK, memclk_mhz); +} + +static void dcn32_set_min_memclk(struct clk_mgr *clk_mgr_base, unsigned int memclk_mhz) +{ + struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base); + + if (!clk_mgr->smu_present) + return; + + dcn32_smu_set_hard_min_by_freq(clk_mgr, PPCLK_UCLK, memclk_mhz); +} static struct clk_mgr_funcs dcn32_funcs = { .get_dp_ref_clk_frequency = dce12_get_dp_ref_freq_khz, @@ -904,6 +933,8 @@ static struct clk_mgr_funcs dcn32_funcs = { .notify_wm_ranges = dcn32_notify_wm_ranges, .set_hard_min_memclk = dcn32_set_hard_min_memclk, .set_hard_max_memclk = dcn32_set_hard_max_memclk, + .set_max_memclk = dcn32_set_max_memclk, + .set_min_memclk = dcn32_set_min_memclk, .get_memclk_states_from_smu = dcn32_get_memclk_states_from_smu, .are_clock_states_equal = dcn32_are_clock_states_equal, .enable_pme_wa = dcn32_enable_pme_wa, diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index dd3a9d06c6e21127e6791219cd0b51eafb8f96f9..d133e4186a52017615f2d430261a2721d9a190bf 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1629,6 +1629,9 @@ bool dc_validate_boot_timing(const struct dc *dc, return false; } + if (dc->debug.force_odm_combine) + return false; + /* Check for enabled DIG to identify enabled display */ if (!link->link_enc->funcs->is_dig_enabled(link->link_enc)) return false; @@ -3577,6 +3580,13 @@ static void commit_planes_for_stream_fast(struct dc *dc, hwss_execute_sequence(dc, context->block_sequence, context->block_sequence_steps); + /* Clear update flags so next flip doesn't have redundant programming + * (if there's no stream update, the update flags are not cleared). + */ + if (top_pipe_to_program->plane_state) + top_pipe_to_program->plane_state->update_flags.raw = 0; + if (top_pipe_to_program->stream) + top_pipe_to_program->stream->update_flags.raw = 0; } static void commit_planes_for_stream(struct dc *dc, @@ -4233,6 +4243,117 @@ static void update_seamless_boot_flags(struct dc *dc, } } +static void populate_fast_updates(struct dc_fast_update *fast_update, + struct dc_surface_update *srf_updates, + int surface_count, + struct dc_stream_update *stream_update) +{ + int i = 0; + + if (stream_update) { + fast_update[0].out_transfer_func = stream_update->out_transfer_func; + fast_update[0].output_csc_transform = stream_update->output_csc_transform; + } + + for (i = 0; i < surface_count; i++) { + fast_update[i].flip_addr = srf_updates[i].flip_addr; + fast_update[i].gamma = srf_updates[i].gamma; + fast_update[i].gamut_remap_matrix = srf_updates[i].gamut_remap_matrix; + fast_update[i].input_csc_color_matrix = srf_updates[i].input_csc_color_matrix; + fast_update[i].coeff_reduction_factor = srf_updates[i].coeff_reduction_factor; + } +} + +static bool fast_updates_exist(struct dc_fast_update *fast_update, int surface_count) +{ + int i; + + if (fast_update[0].out_transfer_func || + fast_update[0].output_csc_transform) + return true; + + for (i = 0; i < surface_count; i++) { + if (fast_update[i].flip_addr || + fast_update[i].gamma || + fast_update[i].gamut_remap_matrix || + fast_update[i].input_csc_color_matrix || + fast_update[i].coeff_reduction_factor) + return true; + } + + return false; +} + +static bool full_update_required(struct dc_surface_update *srf_updates, + int surface_count, + struct dc_stream_update *stream_update, + struct dc_stream_state *stream) +{ + + int i; + struct dc_stream_status *stream_status; + + for (i = 0; i < surface_count; i++) { + if (srf_updates && + (srf_updates[i].plane_info || + srf_updates[i].scaling_info || + (srf_updates[i].hdr_mult.value && + srf_updates[i].hdr_mult.value != srf_updates->surface->hdr_mult.value) || + srf_updates[i].in_transfer_func || + srf_updates[i].func_shaper || + srf_updates[i].lut3d_func || + srf_updates[i].blend_tf)) + return true; + } + + if (stream_update && + (((stream_update->src.height != 0 && stream_update->src.width != 0) || + (stream_update->dst.height != 0 && stream_update->dst.width != 0) || + stream_update->integer_scaling_update) || + stream_update->hdr_static_metadata || + stream_update->abm_level || + stream_update->periodic_interrupt || + stream_update->vrr_infopacket || + stream_update->vsc_infopacket || + stream_update->vsp_infopacket || + stream_update->hfvsif_infopacket || + stream_update->vtem_infopacket || + stream_update->adaptive_sync_infopacket || + stream_update->dpms_off || + stream_update->allow_freesync || + stream_update->vrr_active_variable || + stream_update->vrr_active_fixed || + stream_update->gamut_remap || + stream_update->output_color_space || + stream_update->dither_option || + stream_update->wb_update || + stream_update->dsc_config || + stream_update->mst_bw_update || + stream_update->func_shaper || + stream_update->lut3d_func || + stream_update->pending_test_pattern || + stream_update->crtc_timing_adjust)) + return true; + + if (stream) { + stream_status = dc_stream_get_status(stream); + if (stream_status == NULL || stream_status->plane_count != surface_count) + return true; + } + + return false; +} + +static bool fast_update_only(struct dc_fast_update *fast_update, + struct dc_surface_update *srf_updates, + int surface_count, + struct dc_stream_update *stream_update, + struct dc_stream_state *stream) +{ + return fast_updates_exist(fast_update, surface_count) + && !full_update_required(srf_updates, surface_count, stream_update, stream); +} + bool dc_update_planes_and_stream(struct dc *dc, struct dc_surface_update *srf_updates, int surface_count, struct dc_stream_state *stream, @@ -4242,6 +4363,7 @@ bool dc_update_planes_and_stream(struct dc *dc, enum surface_update_type update_type; int i; struct mall_temp_config mall_temp_config; + struct dc_fast_update fast_update[MAX_SURFACES] = {0}; /* In cases where MPO and split or ODM are used transitions can * cause underflow. Apply stream configuration with minimal pipe @@ -4250,6 +4372,7 @@ bool dc_update_planes_and_stream(struct dc *dc, bool force_minimal_pipe_splitting; bool is_plane_addition; + populate_fast_updates(fast_update, srf_updates, surface_count, stream_update); force_minimal_pipe_splitting = could_mpcc_tree_change_for_active_pipes( dc, stream, @@ -4300,7 +4423,8 @@ bool dc_update_planes_and_stream(struct dc *dc, } update_seamless_boot_flags(dc, context, surface_count, stream); - if (!dc->debug.enable_legacy_fast_update && update_type == UPDATE_TYPE_FAST) { + if (fast_update_only(fast_update, srf_updates, surface_count, stream_update, stream) && + !dc->debug.enable_legacy_fast_update) { commit_planes_for_stream_fast(dc, srf_updates, surface_count, @@ -4357,7 +4481,9 @@ void dc_commit_updates_for_stream(struct dc *dc, struct dc_state *context; struct dc_context *dc_ctx = dc->ctx; int i, j; + struct dc_fast_update fast_update[MAX_SURFACES] = {0}; + populate_fast_updates(fast_update, srf_updates, surface_count, stream_update); stream_status = dc_stream_get_status(stream); context = dc->current_state; @@ -4443,7 +4569,8 @@ void dc_commit_updates_for_stream(struct dc *dc, TRACE_DC_PIPE_STATE(pipe_ctx, i, MAX_PIPES); update_seamless_boot_flags(dc, context, surface_count, stream); - if (!dc->debug.enable_legacy_fast_update && update_type == UPDATE_TYPE_FAST) { + if (fast_update_only(fast_update, srf_updates, surface_count, stream_update, stream) && + !dc->debug.enable_legacy_fast_update) { commit_planes_for_stream_fast(dc, srf_updates, surface_count, @@ -4753,15 +4880,17 @@ static void blank_and_force_memclk(struct dc *dc, bool apply, unsigned int memcl */ void dc_enable_dcmode_clk_limit(struct dc *dc, bool enable) { - uint32_t hw_internal_rev = dc->ctx->asic_id.hw_internal_rev; - unsigned int softMax, maxDPM, funcMin; + unsigned int softMax = 0, maxDPM = 0, funcMin = 0, i; bool p_state_change_support; - if (!ASICREV_IS_BEIGE_GOBY_P(hw_internal_rev)) + if (!dc->config.dc_mode_clk_limit_support) return; softMax = dc->clk_mgr->bw_params->dc_mode_softmax_memclk; - maxDPM = dc->clk_mgr->bw_params->clk_table.entries[dc->clk_mgr->bw_params->clk_table.num_entries - 1].memclk_mhz; + for (i = 0; i < dc->clk_mgr->bw_params->clk_table.num_entries; i++) { + if (dc->clk_mgr->bw_params->clk_table.entries[i].memclk_mhz > maxDPM) + maxDPM = dc->clk_mgr->bw_params->clk_table.entries[i].memclk_mhz; + } funcMin = (dc->clk_mgr->clks.dramclk_khz + 999) / 1000; p_state_change_support = dc->clk_mgr->clks.p_state_change_support; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c index d7d00fefaab9be09343c8356d221317b1680d851..cb2bf9a466f5fba52111b29abeaeb489b4ad582d 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c @@ -610,7 +610,7 @@ void hwss_build_fast_sequence(struct dc *dc, current_mpc_pipe = current_pipe; while (current_mpc_pipe) { - if (!current_mpc_pipe->bottom_pipe && !pipe_ctx->next_odm_pipe && + if (!current_mpc_pipe->bottom_pipe && !current_mpc_pipe->next_odm_pipe && current_mpc_pipe->stream && current_mpc_pipe->plane_state && current_mpc_pipe->plane_state->update_flags.bits.addr_update && !current_mpc_pipe->plane_state->skip_manual_trigger) { diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 26d05e2250888f8df3603d14330734eba8484259..63948170fd6d9d78cb86abe7ddf8a59b5c4b5a25 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -45,7 +45,7 @@ struct aux_payload; struct set_config_cmd_payload; struct dmub_notification; -#define DC_VER "3.2.239" +#define DC_VER "3.2.241" #define MAX_SURFACES 3 #define MAX_PLANES 6 @@ -416,7 +416,7 @@ struct dc_config { uint8_t force_bios_fixed_vs; int sdpif_request_limit_words_per_umc; bool use_old_fixed_vs_sequence; - bool disable_subvp_drr; + bool dc_mode_clk_limit_support; }; enum visual_confirm { @@ -850,6 +850,7 @@ struct dc_debug_options { /* Enable dmub aux for legacy ddc */ bool enable_dmub_aux_for_legacy_ddc; bool disable_fams; + bool disable_fams_gaming; /* FEC/PSR1 sequence enable delay in 100us */ uint8_t fec_enable_delay_in100us; bool enable_driver_sequence_debug; @@ -1264,6 +1265,16 @@ struct dc_scaling_info { struct scaling_taps scaling_quality; }; +struct dc_fast_update { + const struct dc_flip_addrs *flip_addr; + const struct dc_gamma *gamma; + const struct colorspace_transform *gamut_remap_matrix; + const struct dc_csc_transform *input_csc_color_matrix; + const struct fixed31_32 *coeff_reduction_factor; + struct dc_transfer_func *out_transfer_func; + struct dc_csc_transform *output_csc_transform; +}; + struct dc_surface_update { struct dc_plane_state *surface; @@ -1525,6 +1536,7 @@ struct dc_link { bool dpia_forced_tbt3_mode; bool dongle_mode_timing_override; bool blank_stream_on_ocs_change; + bool read_dpcd204h_on_irq_hpd; } wa_flags; struct link_mst_stream_allocation_table mst_stream_alloc_table; diff --git a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c index c52c40b1638722e10a4703de3e808eca0d83a919..c753c6f30dd71445fc9476e41d20985b366f27ff 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c +++ b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c @@ -1011,3 +1011,10 @@ void dc_send_update_cursor_info_to_dmu( dm_execute_dmub_cmd_list(pCtx->stream->ctx, 2, cmd, DM_DMUB_WAIT_TYPE_WAIT); } } + +bool dc_dmub_check_min_version(struct dmub_srv *srv) +{ + if (!srv->hw_funcs.is_psrsu_supported) + return true; + return srv->hw_funcs.is_psrsu_supported(srv); +} diff --git a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h index a5196a9292b356576b4bc0ef596da76b45da26b7..099f94b6107cff21ff7958a704e9d9f13e81ac4f 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h +++ b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h @@ -86,4 +86,5 @@ void dc_dmub_setup_subvp_dmub_command(struct dc *dc, struct dc_state *context, b void dc_dmub_srv_log_diagnostic_data(struct dc_dmub_srv *dc_dmub_srv); void dc_send_update_cursor_info_to_dmu(struct pipe_ctx *pCtx, uint8_t pipe_idx); +bool dc_dmub_check_min_version(struct dmub_srv *srv); #endif /* _DMUB_DC_SRV_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.h b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.h index e6c06325742a0709469f34d1f7d0e982beab95a0..168cb7094c95ff9735818af57f443248d359e56a 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.h @@ -266,7 +266,24 @@ type MASTER_COMM_INTERRUPT; \ type MASTER_COMM_CMD_REG_BYTE0; \ type MASTER_COMM_CMD_REG_BYTE1; \ - type MASTER_COMM_CMD_REG_BYTE2 + type MASTER_COMM_CMD_REG_BYTE2; \ + type ABM1_HG_BIN_33_40_SHIFT_INDEX; \ + type ABM1_HG_BIN_33_64_SHIFT_FLAG; \ + type ABM1_HG_BIN_41_48_SHIFT_INDEX; \ + type ABM1_HG_BIN_49_56_SHIFT_INDEX; \ + type ABM1_HG_BIN_57_64_SHIFT_INDEX; \ + type ABM1_HG_RESULT_DATA; \ + type ABM1_HG_RESULT_INDEX; \ + type ABM1_ACE_SLOPE_DATA; \ + type ABM1_ACE_OFFSET_DATA; \ + type ABM1_ACE_OFFSET_SLOPE_INDEX; \ + type ABM1_ACE_THRES_INDEX; \ + type ABM1_ACE_IGNORE_MASTER_LOCK_EN; \ + type ABM1_ACE_READBACK_DB_REG_VALUE_EN; \ + type ABM1_ACE_DBUF_REG_UPDATE_PENDING; \ + type ABM1_ACE_LOCK; \ + type ABM1_ACE_THRES_DATA_1; \ + type ABM1_ACE_THRES_DATA_2 struct dce_abm_shift { ABM_REG_FIELD_LIST(uint8_t); @@ -288,6 +305,16 @@ struct dce_abm_registers { uint32_t DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES; uint32_t DC_ABM1_HGLS_REG_READ_PROGRESS; uint32_t DC_ABM1_ACE_OFFSET_SLOPE_0; + uint32_t DC_ABM1_ACE_OFFSET_SLOPE_DATA; + uint32_t DC_ABM1_ACE_PWL_CNTL; + uint32_t DC_ABM1_HG_BIN_33_40_SHIFT_INDEX; + uint32_t DC_ABM1_HG_BIN_33_64_SHIFT_FLAG; + uint32_t DC_ABM1_HG_BIN_41_48_SHIFT_INDEX; + uint32_t DC_ABM1_HG_BIN_49_56_SHIFT_INDEX; + uint32_t DC_ABM1_HG_BIN_57_64_SHIFT_INDEX; + uint32_t DC_ABM1_HG_RESULT_DATA; + uint32_t DC_ABM1_HG_RESULT_INDEX; + uint32_t DC_ABM1_ACE_THRES_DATA; uint32_t DC_ABM1_ACE_THRES_12; uint32_t MASTER_COMM_CNTL_REG; uint32_t MASTER_COMM_CMD_REG; diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index 8088558861836a73d07a41f8ffba46f7fd55892a..e115ff91aaaaefe5b9dbd094acc8bfccb7bd079e 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -974,10 +974,12 @@ enum dc_status resource_map_phy_clock_resources( || dc_is_virtual_signal(pipe_ctx->stream->signal)) pipe_ctx->clock_source = dc->res_pool->dp_clock_source; - else - pipe_ctx->clock_source = find_matching_pll( - &context->res_ctx, dc->res_pool, - stream); + else { + if (stream && stream->link && stream->link->link_enc) + pipe_ctx->clock_source = find_matching_pll( + &context->res_ctx, dc->res_pool, + stream); + } if (pipe_ctx->clock_source == NULL) return DC_NO_CLOCK_SOURCE_RESOURCE; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.c index 7a00fe525dfbafa58cf5637b416330b4bb17d212..3538973bd0c6cb7a23a7ffdd2f70883e354ed34f 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.c @@ -308,7 +308,10 @@ bool cm_helper_convert_to_custom_float( #define NUMBER_REGIONS 32 #define NUMBER_SW_SEGMENTS 16 -bool cm_helper_translate_curve_to_hw_format( +#define DC_LOGGER \ + ctx->logger + +bool cm_helper_translate_curve_to_hw_format(struct dc_context *ctx, const struct dc_transfer_func *output_tf, struct pwl_params *lut_params, bool fixpoint) { @@ -482,10 +485,18 @@ bool cm_helper_translate_curve_to_hw_format( rgb->delta_green = dc_fixpt_sub(rgb_plus_1->green, rgb->green); rgb->delta_blue = dc_fixpt_sub(rgb_plus_1->blue, rgb->blue); + if (fixpoint == true) { - rgb->delta_red_reg = dc_fixpt_clamp_u0d10(rgb->delta_red); - rgb->delta_green_reg = dc_fixpt_clamp_u0d10(rgb->delta_green); - rgb->delta_blue_reg = dc_fixpt_clamp_u0d10(rgb->delta_blue); + uint32_t red_clamp = dc_fixpt_clamp_u0d14(rgb->delta_red); + uint32_t green_clamp = dc_fixpt_clamp_u0d14(rgb->delta_green); + uint32_t blue_clamp = dc_fixpt_clamp_u0d14(rgb->delta_blue); + + if (red_clamp >> 10 || green_clamp >> 10 || blue_clamp >> 10) + DC_LOG_WARNING("Losing delta precision while programming shaper LUT."); + + rgb->delta_red_reg = red_clamp & 0x3ff; + rgb->delta_green_reg = green_clamp & 0x3ff; + rgb->delta_blue_reg = blue_clamp & 0x3ff; rgb->red_reg = dc_fixpt_clamp_u0d14(rgb->red); rgb->green_reg = dc_fixpt_clamp_u0d14(rgb->green); rgb->blue_reg = dc_fixpt_clamp_u0d14(rgb->blue); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.h index 3b8cd7410498a11ee62c2b7e60965f6674753bdc..0a68b63d61260b4118ffe11ff48980ef80e5189d 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.h @@ -106,6 +106,7 @@ bool cm_helper_convert_to_custom_float( bool fixpoint); bool cm_helper_translate_curve_to_hw_format( + struct dc_context *ctx, const struct dc_transfer_func *output_tf, struct pwl_params *lut_params, bool fixpoint); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 20a1582be0b13e77819283d2650be3e0aca8bc74..a50309039d083dfa23a339761fa5652cd82d8d83 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -1843,7 +1843,7 @@ bool dcn10_set_output_transfer_func(struct dc *dc, struct pipe_ctx *pipe_ctx, /* dcn10_translate_regamma_to_hw_format takes 750us, only do it when full * update. */ - else if (cm_helper_translate_curve_to_hw_format( + else if (cm_helper_translate_curve_to_hw_format(dc->ctx, stream->out_transfer_func, &dpp->regamma_params, false)) { dpp->funcs->dpp_program_regamma_pwl( diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c index eaf9e9ccad2a7089c2637fcb82b501fde81569bf..4492bc2392b63c92078ac0a7b94636393ba7a48a 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c @@ -867,7 +867,7 @@ bool dcn20_set_output_transfer_func(struct dc *dc, struct pipe_ctx *pipe_ctx, params = &stream->out_transfer_func->pwl; else if (pipe_ctx->stream->out_transfer_func->type == TF_TYPE_DISTRIBUTED_POINTS && - cm_helper_translate_curve_to_hw_format( + cm_helper_translate_curve_to_hw_format(dc->ctx, stream->out_transfer_func, &mpc->blender_params, false)) params = &mpc->blender_params; @@ -896,7 +896,7 @@ bool dcn20_set_blend_lut( if (plane_state->blend_tf->type == TF_TYPE_HWPWL) blend_lut = &plane_state->blend_tf->pwl; else if (plane_state->blend_tf->type == TF_TYPE_DISTRIBUTED_POINTS) { - cm_helper_translate_curve_to_hw_format( + cm_helper_translate_curve_to_hw_format(plane_state->ctx, plane_state->blend_tf, &dpp_base->regamma_params, false); blend_lut = &dpp_base->regamma_params; @@ -918,7 +918,7 @@ bool dcn20_set_shaper_3dlut( if (plane_state->in_shaper_func->type == TF_TYPE_HWPWL) shaper_lut = &plane_state->in_shaper_func->pwl; else if (plane_state->in_shaper_func->type == TF_TYPE_DISTRIBUTED_POINTS) { - cm_helper_translate_curve_to_hw_format( + cm_helper_translate_curve_to_hw_format(plane_state->ctx, plane_state->in_shaper_func, &dpp_base->shaper_params, true); shaper_lut = &dpp_base->shaper_params; @@ -1764,8 +1764,9 @@ static void dcn20_program_pipe( hws->funcs.set_hdr_multiplier(pipe_ctx); if (pipe_ctx->update_flags.bits.enable || - pipe_ctx->plane_state->update_flags.bits.in_transfer_func_change || - pipe_ctx->plane_state->update_flags.bits.gamma_change) + pipe_ctx->plane_state->update_flags.bits.in_transfer_func_change || + pipe_ctx->plane_state->update_flags.bits.gamma_change || + pipe_ctx->plane_state->update_flags.bits.lut_3d) hws->funcs.set_input_transfer_func(dc, pipe_ctx, pipe_ctx->plane_state); /* dcn10_translate_regamma_to_hw_format takes 750us to finish diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dwb_cm.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dwb_cm.c index 6a3d3a0ec0a36f0d5bde3955618e4b5dc5336190..701c7d8bc038ae7520c1a28ac3321170af69e89b 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dwb_cm.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dwb_cm.c @@ -280,7 +280,7 @@ bool dwb3_ogam_set_input_transfer_func( dwb_ogam_lut = kzalloc(sizeof(*dwb_ogam_lut), GFP_KERNEL); if (dwb_ogam_lut) { - cm_helper_translate_curve_to_hw_format( + cm_helper_translate_curve_to_hw_format(dwbc->ctx, in_transfer_func_dwb_ogam, dwb_ogam_lut, false); diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c index b9753867d97b00313566d82081dbcaa582b30bac..bf8864bc8a99ee6e38abb2d55f08c28442f61a7e 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c @@ -106,7 +106,7 @@ static bool dcn30_set_mpc_shaper_3dlut(struct pipe_ctx *pipe_ctx, if (stream->func_shaper->type == TF_TYPE_HWPWL) { shaper_lut = &stream->func_shaper->pwl; } else if (stream->func_shaper->type == TF_TYPE_DISTRIBUTED_POINTS) { - cm_helper_translate_curve_to_hw_format(stream->func_shaper, + cm_helper_translate_curve_to_hw_format(stream->ctx, stream->func_shaper, &dpp_base->shaper_params, true); shaper_lut = &dpp_base->shaper_params; } diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c index 1a0284a068b2a74e24a96d79af6f6272dc303ac5..abe4c12a10b5b6d8b725536535fa25f6dec9fb39 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c @@ -725,7 +725,8 @@ static const struct dc_debug_options debug_defaults_drv = { .dwb_fi_phase = -1, // -1 = disable, .dmub_command_table = true, .use_max_lb = true, - .exit_idle_opt_for_cursor_updates = true + .exit_idle_opt_for_cursor_updates = true, + .enable_legacy_fast_update = false, }; static const struct dc_panel_config panel_config_defaults = { @@ -1986,11 +1987,10 @@ bool dcn30_can_support_mclk_switch_using_fw_based_vblank_stretch(struct dc *dc, if (!is_refresh_rate_support_mclk_switch_using_fw_based_vblank_stretch(context)) return false; - // check if freesync enabled if (!context->streams[0]->allow_freesync) return false; - if (context->streams[0]->vrr_active_variable) + if (context->streams[0]->vrr_active_variable && dc->debug.disable_fams_gaming) return false; context->streams[0]->fpo_in_use = true; diff --git a/drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.c b/drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.c index 7dc065ea247a1824175ef8bf0fcf94334d86f977..5ad6a22ee47dabb2b50716543e7c5d77bfeb4421 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.c @@ -95,7 +95,8 @@ static const struct dc_debug_options debug_defaults_drv = { .dwb_fi_phase = -1, // -1 = disable, .dmub_command_table = true, .use_max_lb = true, - .exit_idle_opt_for_cursor_updates = true + .exit_idle_opt_for_cursor_updates = true, + .enable_legacy_fast_update = false, }; static const struct dc_panel_config panel_config_defaults = { diff --git a/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.c b/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.c index 6d9761395288db268ca69df92c8ce9a7a557885e..45956ef6f3f9dd2b4ede34a40a7077051f4e4ebc 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.c @@ -1190,6 +1190,7 @@ static bool dcn303_resource_construct( dc->caps.dp_hdmi21_pcon_support = true; + dc->config.dc_mode_clk_limit_support = true; /* read VBIOS LTTPR caps */ if (ctx->dc_bios->funcs->get_lttpr_caps) { enum bp_result bp_query_result; diff --git a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_dccg.c b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_dccg.c index cf23d7bc560a6c92aef84c00f1b081a59b21a6bd..0746ed31d1d14ae9d511b6db9efe04a41c251d68 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_dccg.c +++ b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_dccg.c @@ -332,7 +332,7 @@ static void dccg314_dpp_root_clock_control( { struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); - if (dccg->dpp_clock_gated[dpp_inst] == clock_on) + if (dccg->dpp_clock_gated[dpp_inst] != clock_on) return; if (clock_on) { diff --git a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_hwseq.c index 7a43f88685006395a9f7f30aabb44414b15d39de..4d2820ffe4682fbe45eccc58b55b1b7983999034 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_hwseq.c @@ -337,13 +337,14 @@ void dcn314_enable_power_gating_plane(struct dce_hwseq *hws, bool enable) REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 0); } -void dcn314_calculate_dccg_k1_k2_values(struct pipe_ctx *pipe_ctx, unsigned int *k1_div, unsigned int *k2_div) +unsigned int dcn314_calculate_dccg_k1_k2_values(struct pipe_ctx *pipe_ctx, unsigned int *k1_div, unsigned int *k2_div) { struct dc_stream_state *stream = pipe_ctx->stream; + unsigned int odm_combine_factor = 0; bool two_pix_per_container = false; two_pix_per_container = optc2_is_two_pixels_per_containter(&stream->timing); - get_odm_config(pipe_ctx, NULL); + odm_combine_factor = get_odm_config(pipe_ctx, NULL); if (stream->ctx->dc->link_srv->dp_is_128b_132b_signal(pipe_ctx)) { *k1_div = PIXEL_RATE_DIV_BY_1; @@ -361,11 +362,15 @@ void dcn314_calculate_dccg_k1_k2_values(struct pipe_ctx *pipe_ctx, unsigned int } else { *k1_div = PIXEL_RATE_DIV_BY_1; *k2_div = PIXEL_RATE_DIV_BY_4; + if (odm_combine_factor == 2) + *k2_div = PIXEL_RATE_DIV_BY_2; } } if ((*k1_div == PIXEL_RATE_DIV_NA) && (*k2_div == PIXEL_RATE_DIV_NA)) ASSERT(false); + + return odm_combine_factor; } void dcn314_set_pixels_per_cycle(struct pipe_ctx *pipe_ctx) @@ -424,27 +429,6 @@ void dcn314_dpp_root_clock_control(struct dce_hwseq *hws, unsigned int dpp_inst, hws->ctx->dc->res_pool->dccg, dpp_inst, clock_on); } -void dcn314_hubp_pg_control(struct dce_hwseq *hws, unsigned int hubp_inst, bool power_on) -{ - struct dc_context *ctx = hws->ctx; - union dmub_rb_cmd cmd; - - if (hws->ctx->dc->debug.disable_hubp_power_gate) - return; - - PERF_TRACE(); - - memset(&cmd, 0, sizeof(cmd)); - cmd.domain_control.header.type = DMUB_CMD__VBIOS; - cmd.domain_control.header.sub_type = DMUB_CMD__VBIOS_DOMAIN_CONTROL; - cmd.domain_control.header.payload_bytes = sizeof(cmd.domain_control.data); - cmd.domain_control.data.inst = hubp_inst; - cmd.domain_control.data.power_gate = !power_on; - - dm_execute_dmub_cmd(ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); - - PERF_TRACE(); -} static void apply_symclk_on_tx_off_wa(struct dc_link *link) { /* There are use cases where SYMCLK is referenced by OTG. For instance diff --git a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_hwseq.h b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_hwseq.h index 96035c75e0dfe20d3d713a6d9f33b916a86d8fc2..eafcc4ea6d2498262863c337572bb2c71d0283c5 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_hwseq.h @@ -37,14 +37,12 @@ void dcn314_dsc_pg_control(struct dce_hwseq *hws, unsigned int dsc_inst, bool po void dcn314_enable_power_gating_plane(struct dce_hwseq *hws, bool enable); -void dcn314_calculate_dccg_k1_k2_values(struct pipe_ctx *pipe_ctx, unsigned int *k1_div, unsigned int *k2_div); +unsigned int dcn314_calculate_dccg_k1_k2_values(struct pipe_ctx *pipe_ctx, unsigned int *k1_div, unsigned int *k2_div); void dcn314_set_pixels_per_cycle(struct pipe_ctx *pipe_ctx); void dcn314_resync_fifo_dccg_dio(struct dce_hwseq *hws, struct dc *dc, struct dc_state *context); -void dcn314_hubp_pg_control(struct dce_hwseq *hws, unsigned int hubp_inst, bool power_on); - void dcn314_dpp_root_clock_control(struct dce_hwseq *hws, unsigned int dpp_inst, bool clock_on); void dcn314_disable_link_output(struct dc_link *link, const struct link_resource *link_res, enum signal_type signal); diff --git a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_init.c b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_init.c index 86d6a514dec0b42beeda042220636fa5df276c37..ca8fe55c33b8ddf737200bce0bbee23b76ee789d 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_init.c +++ b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_init.c @@ -139,7 +139,7 @@ static const struct hwseq_private_funcs dcn314_private_funcs = { .plane_atomic_power_down = dcn10_plane_atomic_power_down, .enable_power_gating_plane = dcn314_enable_power_gating_plane, .dpp_root_clock_control = dcn314_dpp_root_clock_control, - .hubp_pg_control = dcn314_hubp_pg_control, + .hubp_pg_control = dcn31_hubp_pg_control, .program_all_writeback_pipes_in_tree = dcn30_program_all_writeback_pipes_in_tree, .update_odm = dcn314_update_odm, .dsc_pg_control = dcn314_dsc_pg_control, diff --git a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.c b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.c index a840b008d660305436f80fcd4cf0ff3ed73147e9..6a9024aa32853178d94e661ccecbde93e3aeaf37 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.c @@ -1883,13 +1883,6 @@ static bool dcn314_resource_construct( /* Use pipe context based otg sync logic */ dc->config.use_pipe_ctx_sync_logic = true; - /* Disable pipe power gating when unsupported */ - if (ctx->asic_id.hw_internal_rev == 0x01 || - ctx->asic_id.hw_internal_rev == 0x80) { - dc->debug.disable_dpp_power_gate = true; - dc->debug.disable_hubp_power_gate = true; - } - /* read VBIOS LTTPR caps */ { if (ctx->dc_bios->funcs->get_lttpr_caps) { @@ -1910,6 +1903,14 @@ static bool dcn314_resource_construct( dc->debug = debug_defaults_drv; else dc->debug = debug_defaults_diags; + + /* Disable pipe power gating */ + dc->debug.disable_dpp_power_gate = true; + dc->debug.disable_hubp_power_gate = true; + + /* Disable root clock optimization */ + dc->debug.root_clock_optimization.u32All = 0; + // Init the vm_helper if (dc->vm_helper) vm_helper_init(dc->vm_helper, 16); diff --git a/drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.c b/drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.c index f1153941907e6a14dd243cc4b17964bed5e8c625..df3a438abda82c9f433696d930fa58e76e00a012 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.c @@ -1610,7 +1610,7 @@ static int source_format_to_bpp (enum source_format_class SourcePixelFormat) { if (SourcePixelFormat == dm_444_64) return 8; - else if (SourcePixelFormat == dm_444_16 || SourcePixelFormat == dm_444_16) + else if (SourcePixelFormat == dm_444_16) return 2; else if (SourcePixelFormat == dm_444_8) return 1; diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hubp.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hubp.c index 2d604f7ee7824da021677c6e3e203e5e020e6f0b..ca5b4b28a66441bca370578d11d4e05097db9d4c 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hubp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hubp.c @@ -179,6 +179,7 @@ static struct hubp_funcs dcn32_hubp_funcs = { .hubp_setup_interdependent = hubp2_setup_interdependent, .hubp_set_vm_system_aperture_settings = hubp3_set_vm_system_aperture_settings, .set_blank = hubp2_set_blank, + .set_blank_regs = hubp2_set_blank_regs, .dcc_control = hubp3_dcc_control, .mem_program_viewport = min_set_viewport, .set_cursor_attributes = hubp32_cursor_set_attributes, diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c index c586468872e2a0fc5bbd4d78fb0d954c830bf476..d52d5feeb311bac3113c92380b8bf34acbe24786 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c @@ -448,7 +448,7 @@ bool dcn32_set_mpc_shaper_3dlut( if (stream->func_shaper->type == TF_TYPE_HWPWL) shaper_lut = &stream->func_shaper->pwl; else if (stream->func_shaper->type == TF_TYPE_DISTRIBUTED_POINTS) { - cm_helper_translate_curve_to_hw_format( + cm_helper_translate_curve_to_hw_format(stream->ctx, stream->func_shaper, &dpp_base->shaper_params, true); shaper_lut = &dpp_base->shaper_params; @@ -484,7 +484,7 @@ bool dcn32_set_mcm_luts( if (plane_state->blend_tf->type == TF_TYPE_HWPWL) lut_params = &plane_state->blend_tf->pwl; else if (plane_state->blend_tf->type == TF_TYPE_DISTRIBUTED_POINTS) { - cm_helper_translate_curve_to_hw_format( + cm_helper_translate_curve_to_hw_format(plane_state->ctx, plane_state->blend_tf, &dpp_base->regamma_params, false); lut_params = &dpp_base->regamma_params; @@ -499,7 +499,7 @@ bool dcn32_set_mcm_luts( else if (plane_state->in_shaper_func->type == TF_TYPE_DISTRIBUTED_POINTS) { // TODO: dpp_base replace ASSERT(false); - cm_helper_translate_curve_to_hw_format( + cm_helper_translate_curve_to_hw_format(plane_state->ctx, plane_state->in_shaper_func, &dpp_base->shaper_params, true); lut_params = &dpp_base->shaper_params; @@ -1141,16 +1141,14 @@ void dcn32_update_odm(struct dc *dc, struct dc_state *context, struct pipe_ctx * } } -void dcn32_calculate_dccg_k1_k2_values(struct pipe_ctx *pipe_ctx, unsigned int *k1_div, unsigned int *k2_div) +unsigned int dcn32_calculate_dccg_k1_k2_values(struct pipe_ctx *pipe_ctx, unsigned int *k1_div, unsigned int *k2_div) { struct dc_stream_state *stream = pipe_ctx->stream; + unsigned int odm_combine_factor = 0; bool two_pix_per_container = false; - // For phantom pipes, use the same programming as the main pipes - if (pipe_ctx->stream->mall_stream_config.type == SUBVP_PHANTOM) { - stream = pipe_ctx->stream->mall_stream_config.paired_stream; - } two_pix_per_container = optc2_is_two_pixels_per_containter(&stream->timing); + odm_combine_factor = get_odm_config(pipe_ctx, NULL); if (stream->ctx->dc->link_srv->dp_is_128b_132b_signal(pipe_ctx)) { *k1_div = PIXEL_RATE_DIV_BY_1; @@ -1168,13 +1166,15 @@ void dcn32_calculate_dccg_k1_k2_values(struct pipe_ctx *pipe_ctx, unsigned int * } else { *k1_div = PIXEL_RATE_DIV_BY_1; *k2_div = PIXEL_RATE_DIV_BY_4; - if (dcn32_is_dp_dig_pixel_rate_div_policy(pipe_ctx)) + if ((odm_combine_factor == 2) || dcn32_is_dp_dig_pixel_rate_div_policy(pipe_ctx)) *k2_div = PIXEL_RATE_DIV_BY_2; } } if ((*k1_div == PIXEL_RATE_DIV_NA) && (*k2_div == PIXEL_RATE_DIV_NA)) ASSERT(false); + + return odm_combine_factor; } void dcn32_set_pixels_per_cycle(struct pipe_ctx *pipe_ctx) diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.h b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.h index bf9bffabe0c03133eee8e568a3b9aa358b2f5e9a..2d2628f31bed7dd827014172efe2dd2765cf45e3 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.h @@ -71,7 +71,7 @@ void dcn32_update_force_pstate(struct dc *dc, struct dc_state *context); void dcn32_update_odm(struct dc *dc, struct dc_state *context, struct pipe_ctx *pipe_ctx); -void dcn32_calculate_dccg_k1_k2_values(struct pipe_ctx *pipe_ctx, unsigned int *k1_div, unsigned int *k2_div); +unsigned int dcn32_calculate_dccg_k1_k2_values(struct pipe_ctx *pipe_ctx, unsigned int *k1_div, unsigned int *k2_div); void dcn32_set_pixels_per_cycle(struct pipe_ctx *pipe_ctx); diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_init.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_init.c index c2490e16a66a6c99cfb268226ee9acae54607e68..777b2fac20c4efa8a65f71131967ba603b4c04be 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_init.c +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_init.c @@ -56,6 +56,7 @@ static const struct hw_sequencer_funcs dcn32_funcs = { .enable_audio_stream = dce110_enable_audio_stream, .disable_audio_stream = dce110_disable_audio_stream, .disable_plane = dcn20_disable_plane, + .disable_pixel_data = dcn20_disable_pixel_data, .pipe_control_lock = dcn20_pipe_control_lock, .interdependent_update_lock = dcn10_lock_all_pipes, .cursor_lock = dcn10_cursor_lock, diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c index 19f134caa8adba9125f2f886c6b6639a982d95a2..1cc09799f92d386ca338fa5a1cd77d63dfc28c7a 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c @@ -732,6 +732,7 @@ static const struct dc_debug_options debug_defaults_drv = { .disable_dp_plus_plus_wa = true, .fpo_vactive_min_active_margin_us = 200, .fpo_vactive_max_blank_us = 1000, + .enable_legacy_fast_update = false, }; static struct dce_aux *dcn32_aux_engine_create( @@ -2214,6 +2215,7 @@ static bool dcn32_resource_construct( /* Use pipe context based otg sync logic */ dc->config.use_pipe_ctx_sync_logic = true; + dc->config.dc_mode_clk_limit_support = true; /* read VBIOS LTTPR caps */ { if (ctx->dc_bios->funcs->get_lttpr_caps) { diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c index a9c41ef0751fbf3f89f8fb49e3ffc59b8f58872c..5be242a1b82c4c3768505c034167140f458a6497 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c @@ -595,11 +595,10 @@ struct dc_stream_state *dcn32_can_support_mclk_switch_using_fw_based_vblank_stre if (!is_refresh_rate_support_mclk_switch_using_fw_based_vblank_stretch(fpo_candidate_stream, fpo_vactive_margin_us)) return NULL; - // check if freesync enabled if (!fpo_candidate_stream->allow_freesync) return NULL; - if (fpo_candidate_stream->vrr_active_variable) + if (fpo_candidate_stream->vrr_active_variable && dc->debug.disable_fams_gaming) return NULL; return fpo_candidate_stream; diff --git a/drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c b/drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c index ea204742ad35455baa093e38d6fd7945aaa16c9c..a53478e15ce3a899aae7289db9fb949f72f595a7 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c @@ -730,6 +730,8 @@ static const struct dc_debug_options debug_defaults_drv = { .disable_subvp_high_refresh = false, .fpo_vactive_min_active_margin_us = 200, .fpo_vactive_max_blank_us = 1000, + .enable_legacy_fast_update = false, + .disable_dc_mode_overwrite = true, }; static struct dce_aux *dcn321_aux_engine_create( @@ -1754,6 +1756,7 @@ static bool dcn321_resource_construct( dc->caps.color.mpc.ogam_rom_caps.hlg = 0; dc->caps.color.mpc.ocsc = 1; + dc->config.dc_mode_clk_limit_support = true; /* read VBIOS LTTPR caps */ { if (ctx->dc_bios->funcs->get_lttpr_caps) { diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20.c b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20.c index 6266b0788387ec981d04cbc6e461a2d40407a445..7bf4bb7ad0448428105e34d2d4361c6d535d61e4 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20.c @@ -4356,12 +4356,16 @@ void dml20_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l locals->PSCL_FACTOR[k] / locals->ReturnBWPerState[i][0], locals->EffectiveLBLatencyHidingSourceLinesLuma), locals->SwathHeightYPerState[i][j][k]); - - locals->EffectiveDETLBLinesChroma = dml_floor(locals->LinesInDETChroma + dml_min( - locals->LinesInDETChroma * locals->RequiredDISPCLK[i][j] * locals->BytePerPixelInDETC[k] * - locals->PSCL_FACTOR_CHROMA[k] / locals->ReturnBWPerState[i][0], - locals->EffectiveLBLatencyHidingSourceLinesChroma), - locals->SwathHeightCPerState[i][j][k]); + if (locals->LinesInDETChroma) { + locals->EffectiveDETLBLinesChroma = dml_floor(locals->LinesInDETChroma + + dml_min(locals->LinesInDETChroma * locals->RequiredDISPCLK[i][j] * + locals->BytePerPixelInDETC[k] * + locals->PSCL_FACTOR_CHROMA[k] / locals->ReturnBWPerState[i][0], + locals->EffectiveLBLatencyHidingSourceLinesChroma), + locals->SwathHeightCPerState[i][j][k]); + } else { + locals->EffectiveDETLBLinesChroma = 0; + } if (locals->BytePerPixelInDETC[k] == 0) { locals->UrgentLatencySupportUsPerState[i][j][k] = locals->EffectiveDETLBLinesLuma * (locals->HTotal[k] / locals->PixelClock[k]) diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.c index c9afddd11589b5ec60a2f313d8747309c604a151..d9e049e7ff0a6e9ca6c755dd72869a39461983be 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.c @@ -33,7 +33,7 @@ #include "dml/display_mode_vba.h" struct _vcs_dpi_ip_params_st dcn3_14_ip = { - .VBlankNomDefaultUS = 800, + .VBlankNomDefaultUS = 668, .gpuvm_enable = 1, .gpuvm_max_page_table_levels = 1, .hostvm_enable = 1, diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c index e2bb2b9971f304f3c6bf5699e9e54f0b9cde21cf..a950348017128bcead306d0b6f7de9b3b4517ad3 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c @@ -485,24 +485,20 @@ static void get_optimal_ntuple(struct _vcs_dpi_voltage_scaling_st *entry) } } -void insert_entry_into_table_sorted(struct _vcs_dpi_voltage_scaling_st *table, +static void insert_entry_into_table_sorted(struct _vcs_dpi_voltage_scaling_st *table, unsigned int *num_entries, struct _vcs_dpi_voltage_scaling_st *entry) { int i = 0; int index = 0; - float net_bw_of_new_state = 0; dc_assert_fp_enabled(); - get_optimal_ntuple(entry); - if (*num_entries == 0) { table[0] = *entry; (*num_entries)++; } else { - net_bw_of_new_state = calculate_net_bw_in_kbytes_sec(entry); - while (net_bw_of_new_state > calculate_net_bw_in_kbytes_sec(&table[index])) { + while (entry->net_bw_in_kbytes_sec > table[index].net_bw_in_kbytes_sec) { index++; if (index >= *num_entries) break; @@ -2349,6 +2345,63 @@ void dcn32_patch_dpm_table(struct clk_bw_params *bw_params) bw_params->clk_table.entries[0].memclk_mhz = dcn3_2_soc.clock_limits[0].dram_speed_mts / 16; } +static void swap_table_entries(struct _vcs_dpi_voltage_scaling_st *first_entry, + struct _vcs_dpi_voltage_scaling_st *second_entry) +{ + struct _vcs_dpi_voltage_scaling_st temp_entry = *first_entry; + *first_entry = *second_entry; + *second_entry = temp_entry; +} + +/* + * sort_entries_with_same_bw - Sort entries sharing the same bandwidth by DCFCLK + */ +static void sort_entries_with_same_bw(struct _vcs_dpi_voltage_scaling_st *table, unsigned int *num_entries) +{ + unsigned int start_index = 0; + unsigned int end_index = 0; + unsigned int current_bw = 0; + + for (int i = 0; i < (*num_entries - 1); i++) { + if (table[i].net_bw_in_kbytes_sec == table[i+1].net_bw_in_kbytes_sec) { + current_bw = table[i].net_bw_in_kbytes_sec; + start_index = i; + end_index = ++i; + + while ((i < (*num_entries - 1)) && (table[i+1].net_bw_in_kbytes_sec == current_bw)) + end_index = ++i; + } + + if (start_index != end_index) { + for (int j = start_index; j < end_index; j++) { + for (int k = start_index; k < end_index; k++) { + if (table[k].dcfclk_mhz > table[k+1].dcfclk_mhz) + swap_table_entries(&table[k], &table[k+1]); + } + } + } + + start_index = 0; + end_index = 0; + + } +} + +/* + * remove_inconsistent_entries - Ensure entries with the same bandwidth have MEMCLK and FCLK monotonically increasing + * and remove entries that do not + */ +static void remove_inconsistent_entries(struct _vcs_dpi_voltage_scaling_st *table, unsigned int *num_entries) +{ + for (int i = 0; i < (*num_entries - 1); i++) { + if (table[i].net_bw_in_kbytes_sec == table[i+1].net_bw_in_kbytes_sec) { + if ((table[i].dram_speed_mts > table[i+1].dram_speed_mts) || + (table[i].fabricclk_mhz > table[i+1].fabricclk_mhz)) + remove_entry_from_table_at_index(table, num_entries, i); + } + } +} + /* * override_max_clk_values - Overwrite the max clock frequencies with the max DC mode timings * Input: @@ -2480,6 +2533,8 @@ static int build_synthetic_soc_states(bool disable_dc_mode_overwrite, struct clk entry.fabricclk_mhz = 0; entry.dram_speed_mts = 0; + get_optimal_ntuple(&entry); + entry.net_bw_in_kbytes_sec = calculate_net_bw_in_kbytes_sec(&entry); insert_entry_into_table_sorted(table, num_entries, &entry); } @@ -2488,6 +2543,8 @@ static int build_synthetic_soc_states(bool disable_dc_mode_overwrite, struct clk entry.fabricclk_mhz = 0; entry.dram_speed_mts = 0; + get_optimal_ntuple(&entry); + entry.net_bw_in_kbytes_sec = calculate_net_bw_in_kbytes_sec(&entry); insert_entry_into_table_sorted(table, num_entries, &entry); // Insert the UCLK DPMS @@ -2496,6 +2553,8 @@ static int build_synthetic_soc_states(bool disable_dc_mode_overwrite, struct clk entry.fabricclk_mhz = 0; entry.dram_speed_mts = bw_params->clk_table.entries[i].memclk_mhz * 16; + get_optimal_ntuple(&entry); + entry.net_bw_in_kbytes_sec = calculate_net_bw_in_kbytes_sec(&entry); insert_entry_into_table_sorted(table, num_entries, &entry); } @@ -2506,6 +2565,8 @@ static int build_synthetic_soc_states(bool disable_dc_mode_overwrite, struct clk entry.fabricclk_mhz = bw_params->clk_table.entries[i].fclk_mhz; entry.dram_speed_mts = 0; + get_optimal_ntuple(&entry); + entry.net_bw_in_kbytes_sec = calculate_net_bw_in_kbytes_sec(&entry); insert_entry_into_table_sorted(table, num_entries, &entry); } } @@ -2515,6 +2576,8 @@ static int build_synthetic_soc_states(bool disable_dc_mode_overwrite, struct clk entry.fabricclk_mhz = max_clk_data.fclk_mhz; entry.dram_speed_mts = 0; + get_optimal_ntuple(&entry); + entry.net_bw_in_kbytes_sec = calculate_net_bw_in_kbytes_sec(&entry); insert_entry_into_table_sorted(table, num_entries, &entry); } @@ -2530,6 +2593,21 @@ static int build_synthetic_soc_states(bool disable_dc_mode_overwrite, struct clk remove_entry_from_table_at_index(table, num_entries, i); } + // Insert entry with all max dc limits without bandwidth matching + if (!disable_dc_mode_overwrite) { + struct _vcs_dpi_voltage_scaling_st max_dc_limits_entry = entry; + + max_dc_limits_entry.dcfclk_mhz = max_clk_data.dcfclk_mhz; + max_dc_limits_entry.fabricclk_mhz = max_clk_data.fclk_mhz; + max_dc_limits_entry.dram_speed_mts = max_clk_data.memclk_mhz * 16; + + max_dc_limits_entry.net_bw_in_kbytes_sec = calculate_net_bw_in_kbytes_sec(&max_dc_limits_entry); + insert_entry_into_table_sorted(table, num_entries, &max_dc_limits_entry); + + sort_entries_with_same_bw(table, num_entries); + remove_inconsistent_entries(table, num_entries); + } + // At this point, the table only contains supported points of interest // it could be used as is, but some states may be redundant due to // coarse grained nature of some clocks, so we want to round up to diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.h b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.h index a4206b71d650a99c24f7c543972618132f67aaca..defbee866be686537019e53e4822dcab388e964a 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.h +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.h @@ -39,10 +39,6 @@ void dcn32_helper_populate_phantom_dlg_params(struct dc *dc, uint8_t dcn32_predict_pipe_split(struct dc_state *context, display_e2e_pipe_params_st *pipe_e2e); -void insert_entry_into_table_sorted(struct _vcs_dpi_voltage_scaling_st *table, - unsigned int *num_entries, - struct _vcs_dpi_voltage_scaling_st *entry); - void dcn32_set_phantom_stream_timing(struct dc *dc, struct dc_state *context, struct pipe_ctx *ref_pipe, diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn321/dcn321_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn321/dcn321_fpu.c index f0683fd9d3f06d2b78f109558b363d4072d3eaa6..b26fcf86014c70cff2e8805984f83f94eeec80f7 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn321/dcn321_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn321/dcn321_fpu.c @@ -207,24 +207,20 @@ static float calculate_net_bw_in_kbytes_sec(struct _vcs_dpi_voltage_scaling_st * return limiting_bw_kbytes_sec; } -void dcn321_insert_entry_into_table_sorted(struct _vcs_dpi_voltage_scaling_st *table, +static void dcn321_insert_entry_into_table_sorted(struct _vcs_dpi_voltage_scaling_st *table, unsigned int *num_entries, struct _vcs_dpi_voltage_scaling_st *entry) { int i = 0; int index = 0; - float net_bw_of_new_state = 0; dc_assert_fp_enabled(); - get_optimal_ntuple(entry); - if (*num_entries == 0) { table[0] = *entry; (*num_entries)++; } else { - net_bw_of_new_state = calculate_net_bw_in_kbytes_sec(entry); - while (net_bw_of_new_state > calculate_net_bw_in_kbytes_sec(&table[index])) { + while (entry->net_bw_in_kbytes_sec > table[index].net_bw_in_kbytes_sec) { index++; if (index >= *num_entries) break; @@ -252,6 +248,63 @@ static void remove_entry_from_table_at_index(struct _vcs_dpi_voltage_scaling_st memset(&table[--(*num_entries)], 0, sizeof(struct _vcs_dpi_voltage_scaling_st)); } +static void swap_table_entries(struct _vcs_dpi_voltage_scaling_st *first_entry, + struct _vcs_dpi_voltage_scaling_st *second_entry) +{ + struct _vcs_dpi_voltage_scaling_st temp_entry = *first_entry; + *first_entry = *second_entry; + *second_entry = temp_entry; +} + +/* + * sort_entries_with_same_bw - Sort entries sharing the same bandwidth by DCFCLK + */ +static void sort_entries_with_same_bw(struct _vcs_dpi_voltage_scaling_st *table, unsigned int *num_entries) +{ + unsigned int start_index = 0; + unsigned int end_index = 0; + unsigned int current_bw = 0; + + for (int i = 0; i < (*num_entries - 1); i++) { + if (table[i].net_bw_in_kbytes_sec == table[i+1].net_bw_in_kbytes_sec) { + current_bw = table[i].net_bw_in_kbytes_sec; + start_index = i; + end_index = ++i; + + while ((i < (*num_entries - 1)) && (table[i+1].net_bw_in_kbytes_sec == current_bw)) + end_index = ++i; + } + + if (start_index != end_index) { + for (int j = start_index; j < end_index; j++) { + for (int k = start_index; k < end_index; k++) { + if (table[k].dcfclk_mhz > table[k+1].dcfclk_mhz) + swap_table_entries(&table[k], &table[k+1]); + } + } + } + + start_index = 0; + end_index = 0; + + } +} + +/* + * remove_inconsistent_entries - Ensure entries with the same bandwidth have MEMCLK and FCLK monotonically increasing + * and remove entries that do not follow this order + */ +static void remove_inconsistent_entries(struct _vcs_dpi_voltage_scaling_st *table, unsigned int *num_entries) +{ + for (int i = 0; i < (*num_entries - 1); i++) { + if (table[i].net_bw_in_kbytes_sec == table[i+1].net_bw_in_kbytes_sec) { + if ((table[i].dram_speed_mts > table[i+1].dram_speed_mts) || + (table[i].fabricclk_mhz > table[i+1].fabricclk_mhz)) + remove_entry_from_table_at_index(table, num_entries, i); + } + } +} + /* * override_max_clk_values - Overwrite the max clock frequencies with the max DC mode timings * Input: @@ -362,11 +415,11 @@ static int build_synthetic_soc_states(bool disable_dc_mode_overwrite, struct clk if (max_clk_data.fclk_mhz == 0) max_clk_data.fclk_mhz = max_clk_data.dcfclk_mhz * - dcn3_2_soc.pct_ideal_sdp_bw_after_urgent / - dcn3_2_soc.pct_ideal_fabric_bw_after_urgent; + dcn3_21_soc.pct_ideal_sdp_bw_after_urgent / + dcn3_21_soc.pct_ideal_fabric_bw_after_urgent; if (max_clk_data.phyclk_mhz == 0) - max_clk_data.phyclk_mhz = dcn3_2_soc.clock_limits[0].phyclk_mhz; + max_clk_data.phyclk_mhz = dcn3_21_soc.clock_limits[0].phyclk_mhz; *num_entries = 0; entry.dispclk_mhz = max_clk_data.dispclk_mhz; @@ -374,8 +427,8 @@ static int build_synthetic_soc_states(bool disable_dc_mode_overwrite, struct clk entry.dppclk_mhz = max_clk_data.dppclk_mhz; entry.dtbclk_mhz = max_clk_data.dtbclk_mhz; entry.phyclk_mhz = max_clk_data.phyclk_mhz; - entry.phyclk_d18_mhz = dcn3_2_soc.clock_limits[0].phyclk_d18_mhz; - entry.phyclk_d32_mhz = dcn3_2_soc.clock_limits[0].phyclk_d32_mhz; + entry.phyclk_d18_mhz = dcn3_21_soc.clock_limits[0].phyclk_d18_mhz; + entry.phyclk_d32_mhz = dcn3_21_soc.clock_limits[0].phyclk_d32_mhz; // Insert all the DCFCLK STAs for (i = 0; i < num_dcfclk_stas; i++) { @@ -383,6 +436,8 @@ static int build_synthetic_soc_states(bool disable_dc_mode_overwrite, struct clk entry.fabricclk_mhz = 0; entry.dram_speed_mts = 0; + get_optimal_ntuple(&entry); + entry.net_bw_in_kbytes_sec = calculate_net_bw_in_kbytes_sec(&entry); dcn321_insert_entry_into_table_sorted(table, num_entries, &entry); } @@ -391,6 +446,8 @@ static int build_synthetic_soc_states(bool disable_dc_mode_overwrite, struct clk entry.fabricclk_mhz = 0; entry.dram_speed_mts = 0; + get_optimal_ntuple(&entry); + entry.net_bw_in_kbytes_sec = calculate_net_bw_in_kbytes_sec(&entry); dcn321_insert_entry_into_table_sorted(table, num_entries, &entry); // Insert the UCLK DPMS @@ -399,6 +456,8 @@ static int build_synthetic_soc_states(bool disable_dc_mode_overwrite, struct clk entry.fabricclk_mhz = 0; entry.dram_speed_mts = bw_params->clk_table.entries[i].memclk_mhz * 16; + get_optimal_ntuple(&entry); + entry.net_bw_in_kbytes_sec = calculate_net_bw_in_kbytes_sec(&entry); dcn321_insert_entry_into_table_sorted(table, num_entries, &entry); } @@ -409,6 +468,8 @@ static int build_synthetic_soc_states(bool disable_dc_mode_overwrite, struct clk entry.fabricclk_mhz = bw_params->clk_table.entries[i].fclk_mhz; entry.dram_speed_mts = 0; + get_optimal_ntuple(&entry); + entry.net_bw_in_kbytes_sec = calculate_net_bw_in_kbytes_sec(&entry); dcn321_insert_entry_into_table_sorted(table, num_entries, &entry); } } @@ -418,6 +479,8 @@ static int build_synthetic_soc_states(bool disable_dc_mode_overwrite, struct clk entry.fabricclk_mhz = max_clk_data.fclk_mhz; entry.dram_speed_mts = 0; + get_optimal_ntuple(&entry); + entry.net_bw_in_kbytes_sec = calculate_net_bw_in_kbytes_sec(&entry); dcn321_insert_entry_into_table_sorted(table, num_entries, &entry); } @@ -433,6 +496,23 @@ static int build_synthetic_soc_states(bool disable_dc_mode_overwrite, struct clk remove_entry_from_table_at_index(table, num_entries, i); } + // Insert entry with all max dc limits without bandwitch matching + if (!disable_dc_mode_overwrite) { + struct _vcs_dpi_voltage_scaling_st max_dc_limits_entry = entry; + + max_dc_limits_entry.dcfclk_mhz = max_clk_data.dcfclk_mhz; + max_dc_limits_entry.fabricclk_mhz = max_clk_data.fclk_mhz; + max_dc_limits_entry.dram_speed_mts = max_clk_data.memclk_mhz * 16; + + max_dc_limits_entry.net_bw_in_kbytes_sec = calculate_net_bw_in_kbytes_sec(&max_dc_limits_entry); + dcn321_insert_entry_into_table_sorted(table, num_entries, &max_dc_limits_entry); + + sort_entries_with_same_bw(table, num_entries); + remove_inconsistent_entries(table, num_entries); + } + + + // At this point, the table only contains supported points of interest // it could be used as is, but some states may be redundant due to // coarse grained nature of some clocks, so we want to round up to diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn321/dcn321_fpu.h b/drivers/gpu/drm/amd/display/dc/dml/dcn321/dcn321_fpu.h index e8fad9b4be69309eae5be22d632d3d2cd1634b94..c6623b3705ca702398ad615f87923d313a75ae2d 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn321/dcn321_fpu.h +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn321/dcn321_fpu.h @@ -29,10 +29,6 @@ #include "dml/display_mode_vba.h" -void dcn321_insert_entry_into_table_sorted(struct _vcs_dpi_voltage_scaling_st *table, - unsigned int *num_entries, - struct _vcs_dpi_voltage_scaling_st *entry); - void dcn321_update_bw_bounding_box_fpu(struct dc *dc, struct clk_bw_params *bw_params); #endif diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h index ff0246a9458fdc895ef443766cbce0f156237fe7..fb17f8868cb4c3040f4f035a31bdf7cfd0f314a4 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h @@ -167,6 +167,7 @@ struct _vcs_dpi_voltage_scaling_st { double phyclk_mhz; double dppclk_mhz; double dtbclk_mhz; + float net_bw_in_kbytes_sec; }; /** diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr.h b/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr.h index 6faf40fa5c695ecef2dc295b5cc04d684be7febf..ecb7bcc3946935e1a901c41ba1d822cc0639b21c 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr.h @@ -230,6 +230,7 @@ struct clk_bw_params { unsigned int dram_channel_width_bytes; unsigned int dispclk_vco_khz; unsigned int dc_mode_softmax_memclk; + unsigned int max_memclk_mhz; struct clk_limit_table clk_table; struct wm_table wm_table; struct dummy_pstate_entry dummy_pstate_table[4]; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer_private.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer_private.h index a151865a3a20d8509c63994ca03e3ec2a0a73260..4ca4192c1e127bb74fed37c56ef5d1b8923931c3 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer_private.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer_private.h @@ -156,7 +156,7 @@ struct hwseq_private_funcs { void (*program_mall_pipe_config)(struct dc *dc, struct dc_state *context); void (*update_force_pstate)(struct dc *dc, struct dc_state *context); void (*update_mall_sel)(struct dc *dc, struct dc_state *context); - void (*calculate_dccg_k1_k2_values)(struct pipe_ctx *pipe_ctx, + unsigned int (*calculate_dccg_k1_k2_values)(struct pipe_ctx *pipe_ctx, unsigned int *k1_div, unsigned int *k2_div); void (*set_pixels_per_cycle)(struct pipe_ctx *pipe_ctx); diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_irq_handler.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_irq_handler.c index ba95facc4ee867706ba66deb672dd28e44b59d4a..ef8739df91bcc79b519b4ee8e51e18b754c704a4 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_irq_handler.c +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_irq_handler.c @@ -82,8 +82,15 @@ bool dp_parse_link_loss_status( } /* Check interlane align.*/ - if (sink_status_changed || - !hpd_irq_dpcd_data->bytes.lane_status_updated.bits.INTERLANE_ALIGN_DONE) { + if (link_dp_get_encoding_format(&link->cur_link_settings) == DP_128b_132b_ENCODING && + (!hpd_irq_dpcd_data->bytes.lane_status_updated.bits.EQ_INTERLANE_ALIGN_DONE_128b_132b || + !hpd_irq_dpcd_data->bytes.lane_status_updated.bits.CDS_INTERLANE_ALIGN_DONE_128b_132b)) { + sink_status_changed = true; + } else if (!hpd_irq_dpcd_data->bytes.lane_status_updated.bits.INTERLANE_ALIGN_DONE) { + sink_status_changed = true; + } + + if (sink_status_changed) { DC_LOG_HW_HPD_IRQ("%s: Link Status changed.\n", __func__); @@ -201,6 +208,25 @@ void dp_handle_link_loss(struct dc_link *link) } } +static void read_dpcd204h_on_irq_hpd(struct dc_link *link, union hpd_irq_data *irq_data) +{ + enum dc_status retval; + union lane_align_status_updated dpcd_lane_status_updated; + + retval = core_link_read_dpcd( + link, + DP_LANE_ALIGN_STATUS_UPDATED, + &dpcd_lane_status_updated.raw, + sizeof(union lane_align_status_updated)); + + if (retval == DC_OK) { + irq_data->bytes.lane_status_updated.bits.EQ_INTERLANE_ALIGN_DONE_128b_132b = + dpcd_lane_status_updated.bits.EQ_INTERLANE_ALIGN_DONE_128b_132b; + irq_data->bytes.lane_status_updated.bits.CDS_INTERLANE_ALIGN_DONE_128b_132b = + dpcd_lane_status_updated.bits.CDS_INTERLANE_ALIGN_DONE_128b_132b; + } +} + enum dc_status dp_read_hpd_rx_irq_data( struct dc_link *link, union hpd_irq_data *irq_data) @@ -242,6 +268,13 @@ enum dc_status dp_read_hpd_rx_irq_data( irq_data->bytes.lane23_status.raw = tmp[DP_LANE2_3_STATUS_ESI - DP_SINK_COUNT_ESI]; irq_data->bytes.lane_status_updated.raw = tmp[DP_LANE_ALIGN_STATUS_UPDATED_ESI - DP_SINK_COUNT_ESI]; irq_data->bytes.sink_status.raw = tmp[DP_SINK_STATUS_ESI - DP_SINK_COUNT_ESI]; + + /* + * This display doesn't have correct values in DPCD200Eh. + * Read and check DPCD204h instead. + */ + if (link->wa_flags.read_dpcd204h_on_irq_hpd) + read_dpcd204h_on_irq_hpd(link, irq_data); } return retval; diff --git a/drivers/gpu/drm/amd/display/dmub/dmub_srv.h b/drivers/gpu/drm/amd/display/dmub/dmub_srv.h index 7c9a2b34bd05cda5b5112a6f876dd5847a4591b8..4585e0419da615d2791401d9f8cd973d4b86426f 100644 --- a/drivers/gpu/drm/amd/display/dmub/dmub_srv.h +++ b/drivers/gpu/drm/amd/display/dmub/dmub_srv.h @@ -367,6 +367,8 @@ struct dmub_srv_hw_funcs { bool (*is_supported)(struct dmub_srv *dmub); + bool (*is_psrsu_supported)(struct dmub_srv *dmub); + bool (*is_hw_init)(struct dmub_srv *dmub); void (*enable_dmub_boot_options)(struct dmub_srv *dmub, @@ -492,7 +494,7 @@ struct dmub_notification { * of a firmware to know if feature or functionality is supported or present. */ #define DMUB_FW_VERSION(major, minor, revision) \ - ((((major) & 0xFF) << 24) | (((minor) & 0xFF) << 16) | ((revision) & 0xFFFF)) + ((((major) & 0xFF) << 24) | (((minor) & 0xFF) << 16) | (((revision) & 0xFF) << 8)) /** * dmub_srv_create() - creates the DMUB service. diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c index ebf7aeec4029cb8a7b03bcf0c6a705a846990c1b..5e952541e72d5160edb6bd3eeae7356aebf8618e 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c @@ -302,6 +302,11 @@ bool dmub_dcn31_is_supported(struct dmub_srv *dmub) return supported; } +bool dmub_dcn31_is_psrsu_supported(struct dmub_srv *dmub) +{ + return dmub->fw_version >= DMUB_FW_VERSION(4, 0, 59); +} + void dmub_dcn31_set_gpint(struct dmub_srv *dmub, union dmub_gpint_data_register reg) { diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.h b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.h index 7d5c10ee539b413f4b4c34c52c3e30c92def6584..89c5a948b67d5c1228c4d73c7cd029902e5575c6 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.h +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.h @@ -221,6 +221,8 @@ bool dmub_dcn31_is_hw_init(struct dmub_srv *dmub); bool dmub_dcn31_is_supported(struct dmub_srv *dmub); +bool dmub_dcn31_is_psrsu_supported(struct dmub_srv *dmub); + void dmub_dcn31_set_gpint(struct dmub_srv *dmub, union dmub_gpint_data_register reg); diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn314.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn314.c index 48a06dbd9be78687a12f1574ba43906ccf35c13a..f161aeb7e7c4a0d68614c7b6483fb81a3d9527b1 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn314.c +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn314.c @@ -60,3 +60,8 @@ const struct dmub_srv_dcn31_regs dmub_srv_dcn314_regs = { { DMUB_DCN31_FIELDS() }, #undef DMUB_SF }; + +bool dmub_dcn314_is_psrsu_supported(struct dmub_srv *dmub) +{ + return dmub->fw_version >= DMUB_FW_VERSION(8, 0, 16); +} diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn314.h b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn314.h index 674267a2940e91cb1e5d971dac573da313b9e3d7..f213bd82c9110aa86db3dec79f2f4c87ec043128 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn314.h +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn314.h @@ -30,4 +30,6 @@ extern const struct dmub_srv_dcn31_regs dmub_srv_dcn314_regs; +bool dmub_dcn314_is_psrsu_supported(struct dmub_srv *dmub); + #endif /* _DMUB_DCN314_H_ */ diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c index 9e9a6a44a7ac4b4a949a2e8261d21dd3f218a15a..bdaf43892f47bbcf83d4a9d3b20a9756697672b1 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c @@ -226,14 +226,17 @@ static bool dmub_srv_hw_setup(struct dmub_srv *dmub, enum dmub_asic asic) case DMUB_ASIC_DCN314: case DMUB_ASIC_DCN315: case DMUB_ASIC_DCN316: - if (asic == DMUB_ASIC_DCN314) + if (asic == DMUB_ASIC_DCN314) { dmub->regs_dcn31 = &dmub_srv_dcn314_regs; - else if (asic == DMUB_ASIC_DCN315) + funcs->is_psrsu_supported = dmub_dcn314_is_psrsu_supported; + } else if (asic == DMUB_ASIC_DCN315) { dmub->regs_dcn31 = &dmub_srv_dcn315_regs; - else if (asic == DMUB_ASIC_DCN316) + } else if (asic == DMUB_ASIC_DCN316) { dmub->regs_dcn31 = &dmub_srv_dcn316_regs; - else + } else { dmub->regs_dcn31 = &dmub_srv_dcn31_regs; + funcs->is_psrsu_supported = dmub_dcn31_is_psrsu_supported; + } funcs->reset = dmub_dcn31_reset; funcs->reset_release = dmub_dcn31_reset_release; funcs->backdoor_load = dmub_dcn31_backdoor_load; diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c index a57952b93e73fa727e45f1d6e6a8afd9346f1c1a..9ef88a0b1b57e46112c1b9cecfaf4794811ce196 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c @@ -35,44 +35,6 @@ #include #include -static const struct cg_flag_name clocks[] = { - {AMD_CG_SUPPORT_GFX_FGCG, "Graphics Fine Grain Clock Gating"}, - {AMD_CG_SUPPORT_GFX_MGCG, "Graphics Medium Grain Clock Gating"}, - {AMD_CG_SUPPORT_GFX_MGLS, "Graphics Medium Grain memory Light Sleep"}, - {AMD_CG_SUPPORT_GFX_CGCG, "Graphics Coarse Grain Clock Gating"}, - {AMD_CG_SUPPORT_GFX_CGLS, "Graphics Coarse Grain memory Light Sleep"}, - {AMD_CG_SUPPORT_GFX_CGTS, "Graphics Coarse Grain Tree Shader Clock Gating"}, - {AMD_CG_SUPPORT_GFX_CGTS_LS, "Graphics Coarse Grain Tree Shader Light Sleep"}, - {AMD_CG_SUPPORT_GFX_CP_LS, "Graphics Command Processor Light Sleep"}, - {AMD_CG_SUPPORT_GFX_RLC_LS, "Graphics Run List Controller Light Sleep"}, - {AMD_CG_SUPPORT_GFX_3D_CGCG, "Graphics 3D Coarse Grain Clock Gating"}, - {AMD_CG_SUPPORT_GFX_3D_CGLS, "Graphics 3D Coarse Grain memory Light Sleep"}, - {AMD_CG_SUPPORT_MC_LS, "Memory Controller Light Sleep"}, - {AMD_CG_SUPPORT_MC_MGCG, "Memory Controller Medium Grain Clock Gating"}, - {AMD_CG_SUPPORT_SDMA_LS, "System Direct Memory Access Light Sleep"}, - {AMD_CG_SUPPORT_SDMA_MGCG, "System Direct Memory Access Medium Grain Clock Gating"}, - {AMD_CG_SUPPORT_BIF_MGCG, "Bus Interface Medium Grain Clock Gating"}, - {AMD_CG_SUPPORT_BIF_LS, "Bus Interface Light Sleep"}, - {AMD_CG_SUPPORT_UVD_MGCG, "Unified Video Decoder Medium Grain Clock Gating"}, - {AMD_CG_SUPPORT_VCE_MGCG, "Video Compression Engine Medium Grain Clock Gating"}, - {AMD_CG_SUPPORT_HDP_LS, "Host Data Path Light Sleep"}, - {AMD_CG_SUPPORT_HDP_MGCG, "Host Data Path Medium Grain Clock Gating"}, - {AMD_CG_SUPPORT_DRM_MGCG, "Digital Right Management Medium Grain Clock Gating"}, - {AMD_CG_SUPPORT_DRM_LS, "Digital Right Management Light Sleep"}, - {AMD_CG_SUPPORT_ROM_MGCG, "Rom Medium Grain Clock Gating"}, - {AMD_CG_SUPPORT_DF_MGCG, "Data Fabric Medium Grain Clock Gating"}, - {AMD_CG_SUPPORT_VCN_MGCG, "VCN Medium Grain Clock Gating"}, - {AMD_CG_SUPPORT_HDP_DS, "Host Data Path Deep Sleep"}, - {AMD_CG_SUPPORT_HDP_SD, "Host Data Path Shutdown"}, - {AMD_CG_SUPPORT_IH_CG, "Interrupt Handler Clock Gating"}, - {AMD_CG_SUPPORT_JPEG_MGCG, "JPEG Medium Grain Clock Gating"}, - {AMD_CG_SUPPORT_REPEATER_FGCG, "Repeater Fine Grain Clock Gating"}, - {AMD_CG_SUPPORT_GFX_PERF_CLK, "Perfmon Clock Gating"}, - {AMD_CG_SUPPORT_ATHUB_MGCG, "Address Translation Hub Medium Grain Clock Gating"}, - {AMD_CG_SUPPORT_ATHUB_LS, "Address Translation Hub Light Sleep"}, - {0, NULL}, -}; - static const struct hwmon_temp_label { enum PP_HWMON_TEMP channel; const char *label; @@ -2110,6 +2072,7 @@ static int default_attr_update(struct amdgpu_device *adev, struct amdgpu_device_ case IP_VERSION(9, 4, 0): case IP_VERSION(9, 4, 1): case IP_VERSION(9, 4, 2): + case IP_VERSION(9, 4, 3): case IP_VERSION(10, 3, 0): case IP_VERSION(11, 0, 0): case IP_VERSION(11, 0, 1): @@ -2120,7 +2083,9 @@ static int default_attr_update(struct amdgpu_device *adev, struct amdgpu_device_ *states = ATTR_STATE_UNSUPPORTED; } } else if (DEVICE_ATTR_IS(pp_features)) { - if (adev->flags & AMD_IS_APU || gc_ver < IP_VERSION(9, 0, 0)) + if ((adev->flags & AMD_IS_APU && + gc_ver != IP_VERSION(9, 4, 3)) || + gc_ver < IP_VERSION(9, 0, 0)) *states = ATTR_STATE_UNSUPPORTED; } else if (DEVICE_ATTR_IS(gpu_metrics)) { if (gc_ver < IP_VERSION(9, 1, 0)) @@ -3684,6 +3649,44 @@ static int amdgpu_debugfs_pm_info_pp(struct seq_file *m, struct amdgpu_device *a return 0; } +static const struct cg_flag_name clocks[] = { + {AMD_CG_SUPPORT_GFX_FGCG, "Graphics Fine Grain Clock Gating"}, + {AMD_CG_SUPPORT_GFX_MGCG, "Graphics Medium Grain Clock Gating"}, + {AMD_CG_SUPPORT_GFX_MGLS, "Graphics Medium Grain memory Light Sleep"}, + {AMD_CG_SUPPORT_GFX_CGCG, "Graphics Coarse Grain Clock Gating"}, + {AMD_CG_SUPPORT_GFX_CGLS, "Graphics Coarse Grain memory Light Sleep"}, + {AMD_CG_SUPPORT_GFX_CGTS, "Graphics Coarse Grain Tree Shader Clock Gating"}, + {AMD_CG_SUPPORT_GFX_CGTS_LS, "Graphics Coarse Grain Tree Shader Light Sleep"}, + {AMD_CG_SUPPORT_GFX_CP_LS, "Graphics Command Processor Light Sleep"}, + {AMD_CG_SUPPORT_GFX_RLC_LS, "Graphics Run List Controller Light Sleep"}, + {AMD_CG_SUPPORT_GFX_3D_CGCG, "Graphics 3D Coarse Grain Clock Gating"}, + {AMD_CG_SUPPORT_GFX_3D_CGLS, "Graphics 3D Coarse Grain memory Light Sleep"}, + {AMD_CG_SUPPORT_MC_LS, "Memory Controller Light Sleep"}, + {AMD_CG_SUPPORT_MC_MGCG, "Memory Controller Medium Grain Clock Gating"}, + {AMD_CG_SUPPORT_SDMA_LS, "System Direct Memory Access Light Sleep"}, + {AMD_CG_SUPPORT_SDMA_MGCG, "System Direct Memory Access Medium Grain Clock Gating"}, + {AMD_CG_SUPPORT_BIF_MGCG, "Bus Interface Medium Grain Clock Gating"}, + {AMD_CG_SUPPORT_BIF_LS, "Bus Interface Light Sleep"}, + {AMD_CG_SUPPORT_UVD_MGCG, "Unified Video Decoder Medium Grain Clock Gating"}, + {AMD_CG_SUPPORT_VCE_MGCG, "Video Compression Engine Medium Grain Clock Gating"}, + {AMD_CG_SUPPORT_HDP_LS, "Host Data Path Light Sleep"}, + {AMD_CG_SUPPORT_HDP_MGCG, "Host Data Path Medium Grain Clock Gating"}, + {AMD_CG_SUPPORT_DRM_MGCG, "Digital Right Management Medium Grain Clock Gating"}, + {AMD_CG_SUPPORT_DRM_LS, "Digital Right Management Light Sleep"}, + {AMD_CG_SUPPORT_ROM_MGCG, "Rom Medium Grain Clock Gating"}, + {AMD_CG_SUPPORT_DF_MGCG, "Data Fabric Medium Grain Clock Gating"}, + {AMD_CG_SUPPORT_VCN_MGCG, "VCN Medium Grain Clock Gating"}, + {AMD_CG_SUPPORT_HDP_DS, "Host Data Path Deep Sleep"}, + {AMD_CG_SUPPORT_HDP_SD, "Host Data Path Shutdown"}, + {AMD_CG_SUPPORT_IH_CG, "Interrupt Handler Clock Gating"}, + {AMD_CG_SUPPORT_JPEG_MGCG, "JPEG Medium Grain Clock Gating"}, + {AMD_CG_SUPPORT_REPEATER_FGCG, "Repeater Fine Grain Clock Gating"}, + {AMD_CG_SUPPORT_GFX_PERF_CLK, "Perfmon Clock Gating"}, + {AMD_CG_SUPPORT_ATHUB_MGCG, "Address Translation Hub Medium Grain Clock Gating"}, + {AMD_CG_SUPPORT_ATHUB_LS, "Address Translation Hub Light Sleep"}, + {0, NULL}, +}; + static void amdgpu_parse_cg_state(struct seq_file *m, u64 flags) { int i; diff --git a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h index d178f3f4408168d7f892fc7684c19542f7c30731..42172b00be66df41009af76cf6b034403f3081d9 100644 --- a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h +++ b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h @@ -89,6 +89,8 @@ struct amdgpu_dpm_thermal { int max_mem_crit_temp; /* memory max emergency(shutdown) temp */ int max_mem_emergency_temp; + /* SWCTF threshold */ + int sw_ctf_threshold; /* was last interrupt low to high or high to low */ bool high_to_low; /* interrupt source */ diff --git a/drivers/gpu/drm/amd/pm/legacy-dpm/legacy_dpm.c b/drivers/gpu/drm/amd/pm/legacy-dpm/legacy_dpm.c index d3fe149d8476561796015a0a98f6f43a46f0423f..81fb4e5dd804bda00cbeca84c9b790a6ed439f6f 100644 --- a/drivers/gpu/drm/amd/pm/legacy-dpm/legacy_dpm.c +++ b/drivers/gpu/drm/amd/pm/legacy-dpm/legacy_dpm.c @@ -794,7 +794,7 @@ void amdgpu_add_thermal_controller(struct amdgpu_device *adev) struct i2c_board_info info = { }; const char *name = pp_lib_thermal_controller_names[controller->ucType]; info.addr = controller->ucI2cAddress >> 1; - strlcpy(info.type, name, sizeof(info.type)); + strscpy(info.type, name, sizeof(info.type)); i2c_new_client_device(&adev->pm.i2c_bus->adapter, &info); } } else { diff --git a/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c b/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c index 11b7b4cffaae09de52cfb104838c30f22ffaf26b..ff360c69917121cd45cd83397f019a64810730ae 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c +++ b/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c @@ -26,6 +26,7 @@ #include #include #include +#include #include "amd_shared.h" #include "amd_powerplay.h" #include "power_state.h" @@ -91,6 +92,45 @@ static int pp_early_init(void *handle) return 0; } +static void pp_swctf_delayed_work_handler(struct work_struct *work) +{ + struct pp_hwmgr *hwmgr = + container_of(work, struct pp_hwmgr, swctf_delayed_work.work); + struct amdgpu_device *adev = hwmgr->adev; + struct amdgpu_dpm_thermal *range = + &adev->pm.dpm.thermal; + uint32_t gpu_temperature, size; + int ret; + + /* + * If the hotspot/edge temperature is confirmed as below SW CTF setting point + * after the delay enforced, nothing will be done. + * Otherwise, a graceful shutdown will be performed to prevent further damage. + */ + if (range->sw_ctf_threshold && + hwmgr->hwmgr_func->read_sensor) { + ret = hwmgr->hwmgr_func->read_sensor(hwmgr, + AMDGPU_PP_SENSOR_HOTSPOT_TEMP, + &gpu_temperature, + &size); + /* + * For some legacy ASICs, hotspot temperature retrieving might be not + * supported. Check the edge temperature instead then. + */ + if (ret == -EOPNOTSUPP) + ret = hwmgr->hwmgr_func->read_sensor(hwmgr, + AMDGPU_PP_SENSOR_EDGE_TEMP, + &gpu_temperature, + &size); + if (!ret && gpu_temperature / 1000 < range->sw_ctf_threshold) + return; + } + + dev_emerg(adev->dev, "ERROR: GPU over temperature range(SW CTF) detected!\n"); + dev_emerg(adev->dev, "ERROR: System is going to shutdown due to GPU SW CTF!\n"); + orderly_poweroff(true); +} + static int pp_sw_init(void *handle) { struct amdgpu_device *adev = handle; @@ -101,6 +141,10 @@ static int pp_sw_init(void *handle) pr_debug("powerplay sw init %s\n", ret ? "failed" : "successfully"); + if (!ret) + INIT_DELAYED_WORK(&hwmgr->swctf_delayed_work, + pp_swctf_delayed_work_handler); + return ret; } @@ -135,6 +179,8 @@ static int pp_hw_fini(void *handle) struct amdgpu_device *adev = handle; struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle; + cancel_delayed_work_sync(&hwmgr->swctf_delayed_work); + hwmgr_hw_fini(hwmgr); return 0; @@ -221,6 +267,8 @@ static int pp_suspend(void *handle) struct amdgpu_device *adev = handle; struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle; + cancel_delayed_work_sync(&hwmgr->swctf_delayed_work); + return hwmgr_suspend(hwmgr); } diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/hardwaremanager.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/hardwaremanager.c index 981dc8c7112d697f101ad449e136f2db86cd9e04..90452b66e107133592e5ffdef3417a45f54875f6 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/hardwaremanager.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/hardwaremanager.c @@ -241,7 +241,8 @@ int phm_start_thermal_controller(struct pp_hwmgr *hwmgr) TEMP_RANGE_MAX, TEMP_RANGE_MIN, TEMP_RANGE_MAX, - TEMP_RANGE_MAX}; + TEMP_RANGE_MAX, + 0}; struct amdgpu_device *adev = hwmgr->adev; if (!hwmgr->not_vf) @@ -265,6 +266,7 @@ int phm_start_thermal_controller(struct pp_hwmgr *hwmgr) adev->pm.dpm.thermal.min_mem_temp = range.mem_min; adev->pm.dpm.thermal.max_mem_crit_temp = range.mem_crit_max; adev->pm.dpm.thermal.max_mem_emergency_temp = range.mem_emergency_max; + adev->pm.dpm.thermal.sw_ctf_threshold = range.sw_ctf_threshold; return ret; } diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c index e10cc5e7928e68e0d47ccfcdf9fb4f8f51bd8773..6841a4bce186f1c3102b88b67edeb949bdf5ea83 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c @@ -5432,6 +5432,8 @@ static int smu7_get_thermal_temperature_range(struct pp_hwmgr *hwmgr, thermal_data->max = data->thermal_temp_setting.temperature_shutdown * PP_TEMPERATURE_UNITS_PER_CENTIGRADES; + thermal_data->sw_ctf_threshold = thermal_data->max; + return 0; } diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu_helper.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu_helper.c index bfe80ac0ad8c8751dbad4c3cf7818c17030c43a2..d0b1ab6c452312720d1aa600e7d23e1ffa7175d3 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu_helper.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu_helper.c @@ -603,21 +603,17 @@ int phm_irq_process(struct amdgpu_device *adev, struct amdgpu_irq_src *source, struct amdgpu_iv_entry *entry) { + struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle; uint32_t client_id = entry->client_id; uint32_t src_id = entry->src_id; if (client_id == AMDGPU_IRQ_CLIENTID_LEGACY) { if (src_id == VISLANDS30_IV_SRCID_CG_TSS_THERMAL_LOW_TO_HIGH) { - dev_emerg(adev->dev, "ERROR: GPU over temperature range(SW CTF) detected!\n"); - /* - * SW CTF just occurred. - * Try to do a graceful shutdown to prevent further damage. - */ - dev_emerg(adev->dev, "ERROR: System is going to shutdown due to GPU SW CTF!\n"); - orderly_poweroff(true); - } else if (src_id == VISLANDS30_IV_SRCID_CG_TSS_THERMAL_HIGH_TO_LOW) + schedule_delayed_work(&hwmgr->swctf_delayed_work, + msecs_to_jiffies(AMDGPU_SWCTF_EXTRA_DELAY)); + } else if (src_id == VISLANDS30_IV_SRCID_CG_TSS_THERMAL_HIGH_TO_LOW) { dev_emerg(adev->dev, "ERROR: GPU under temperature range detected!\n"); - else if (src_id == VISLANDS30_IV_SRCID_GPIO_19) { + } else if (src_id == VISLANDS30_IV_SRCID_GPIO_19) { dev_emerg(adev->dev, "ERROR: GPU HW Critical Temperature Fault(aka CTF) detected!\n"); /* * HW CTF just occurred. Shutdown to prevent further damage. @@ -626,15 +622,10 @@ int phm_irq_process(struct amdgpu_device *adev, orderly_poweroff(true); } } else if (client_id == SOC15_IH_CLIENTID_THM) { - if (src_id == 0) { - dev_emerg(adev->dev, "ERROR: GPU over temperature range(SW CTF) detected!\n"); - /* - * SW CTF just occurred. - * Try to do a graceful shutdown to prevent further damage. - */ - dev_emerg(adev->dev, "ERROR: System is going to shutdown due to GPU SW CTF!\n"); - orderly_poweroff(true); - } else + if (src_id == 0) + schedule_delayed_work(&hwmgr->swctf_delayed_work, + msecs_to_jiffies(AMDGPU_SWCTF_EXTRA_DELAY)); + else dev_emerg(adev->dev, "ERROR: GPU under temperature range detected!\n"); } else if (client_id == SOC15_IH_CLIENTID_ROM_SMUIO) { dev_emerg(adev->dev, "ERROR: GPU HW Critical Temperature Fault(aka CTF) detected!\n"); diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c index 99cd2e63afdd4369594eef59a334766817875a2d..c51dd4c74fe9db3fc52121a042f570a94e1d9e59 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c @@ -5241,6 +5241,9 @@ static int vega10_get_thermal_temperature_range(struct pp_hwmgr *hwmgr, { struct vega10_hwmgr *data = hwmgr->backend; PPTable_t *pp_table = &(data->smc_state_table.pp_table); + struct phm_ppt_v2_information *pp_table_info = + (struct phm_ppt_v2_information *)(hwmgr->pptable); + struct phm_tdp_table *tdp_table = pp_table_info->tdp_table; memcpy(thermal_data, &SMU7ThermalWithDelayPolicy[0], sizeof(struct PP_TemperatureRange)); @@ -5257,6 +5260,13 @@ static int vega10_get_thermal_temperature_range(struct pp_hwmgr *hwmgr, thermal_data->mem_emergency_max = (pp_table->ThbmLimit + CTF_OFFSET_HBM)* PP_TEMPERATURE_UNITS_PER_CENTIGRADES; + if (tdp_table->usSoftwareShutdownTemp > pp_table->ThotspotLimit && + tdp_table->usSoftwareShutdownTemp < VEGA10_THERMAL_MAXIMUM_ALERT_TEMP) + thermal_data->sw_ctf_threshold = tdp_table->usSoftwareShutdownTemp; + else + thermal_data->sw_ctf_threshold = VEGA10_THERMAL_MAXIMUM_ALERT_TEMP; + thermal_data->sw_ctf_threshold *= PP_TEMPERATURE_UNITS_PER_CENTIGRADES; + return 0; } diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_hwmgr.c index e9db137cd1c6cb79abb6894c03077ddd4f5a2fb9..1937be1cf5b464c3399c116c2ae30e809a4f1966 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_hwmgr.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_hwmgr.c @@ -2763,6 +2763,8 @@ static int vega12_notify_cac_buffer_info(struct pp_hwmgr *hwmgr, static int vega12_get_thermal_temperature_range(struct pp_hwmgr *hwmgr, struct PP_TemperatureRange *thermal_data) { + struct phm_ppt_v3_information *pptable_information = + (struct phm_ppt_v3_information *)hwmgr->pptable; struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend); PPTable_t *pp_table = &(data->smc_state_table.pp_table); @@ -2781,6 +2783,8 @@ static int vega12_get_thermal_temperature_range(struct pp_hwmgr *hwmgr, PP_TEMPERATURE_UNITS_PER_CENTIGRADES; thermal_data->mem_emergency_max = (pp_table->ThbmLimit + CTF_OFFSET_HBM)* PP_TEMPERATURE_UNITS_PER_CENTIGRADES; + thermal_data->sw_ctf_threshold = pptable_information->us_software_shutdown_temp * + PP_TEMPERATURE_UNITS_PER_CENTIGRADES; return 0; } diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_thermal.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_thermal.c index ed3dff0b52d217b9e76c448c3ac8af46b1d95870..ae342c58cd3ecff94faf9df0ed96dd1621dcdc4b 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_thermal.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_thermal.c @@ -192,7 +192,9 @@ static int vega12_thermal_set_temperature_range(struct pp_hwmgr *hwmgr, val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, THERM_IH_HW_ENA, 1); val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTH, high); val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTL, low); - val = val & (~THM_THERMAL_INT_CTRL__THERM_TRIGGER_MASK_MASK); + val &= ~THM_THERMAL_INT_CTRL__THERM_TRIGGER_MASK_MASK; + val &= ~THM_THERMAL_INT_CTRL__THERM_INTH_MASK_MASK; + val &= ~THM_THERMAL_INT_CTRL__THERM_INTL_MASK_MASK; WREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_CTRL, val); diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_hwmgr.c index 0d4d4811527c641a030ba3f0a6663dcbd1b35b95..4e19ccbdb8077e84a7fae095d540f2d85ebfb6ac 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_hwmgr.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_hwmgr.c @@ -4206,6 +4206,8 @@ static int vega20_notify_cac_buffer_info(struct pp_hwmgr *hwmgr, static int vega20_get_thermal_temperature_range(struct pp_hwmgr *hwmgr, struct PP_TemperatureRange *thermal_data) { + struct phm_ppt_v3_information *pptable_information = + (struct phm_ppt_v3_information *)hwmgr->pptable; struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); PPTable_t *pp_table = &(data->smc_state_table.pp_table); @@ -4224,6 +4226,8 @@ static int vega20_get_thermal_temperature_range(struct pp_hwmgr *hwmgr, PP_TEMPERATURE_UNITS_PER_CENTIGRADES; thermal_data->mem_emergency_max = (pp_table->ThbmLimit + CTF_OFFSET_HBM)* PP_TEMPERATURE_UNITS_PER_CENTIGRADES; + thermal_data->sw_ctf_threshold = pptable_information->us_software_shutdown_temp * + PP_TEMPERATURE_UNITS_PER_CENTIGRADES; return 0; } diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_thermal.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_thermal.c index f4f4efdbda79b6c33f76db09ccd3b2389d9bdb1b..e9737ca8418a5242855a6054b978bc2586fb294c 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_thermal.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_thermal.c @@ -263,7 +263,9 @@ static int vega20_thermal_set_temperature_range(struct pp_hwmgr *hwmgr, val = CGS_REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, THERM_IH_HW_ENA, 1); val = CGS_REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTH, high); val = CGS_REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTL, low); - val = val & (~THM_THERMAL_INT_CTRL__THERM_TRIGGER_MASK_MASK); + val &= ~THM_THERMAL_INT_CTRL__THERM_TRIGGER_MASK_MASK; + val &= ~THM_THERMAL_INT_CTRL__THERM_INTH_MASK_MASK; + val &= ~THM_THERMAL_INT_CTRL__THERM_INTL_MASK_MASK; WREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_CTRL, val); diff --git a/drivers/gpu/drm/amd/pm/powerplay/inc/hwmgr.h b/drivers/gpu/drm/amd/pm/powerplay/inc/hwmgr.h index f1580a26a85061039b380e1ae0b7627a6629c9c5..612d66aeaab99f3aad4ba6b417276db36e476bd4 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/inc/hwmgr.h +++ b/drivers/gpu/drm/amd/pm/powerplay/inc/hwmgr.h @@ -811,6 +811,8 @@ struct pp_hwmgr { bool gfxoff_state_changed_by_workload; uint32_t pstate_sclk_peak; uint32_t pstate_mclk_peak; + + struct delayed_work swctf_delayed_work; }; int hwmgr_early_init(struct pp_hwmgr *hwmgr); diff --git a/drivers/gpu/drm/amd/pm/powerplay/inc/power_state.h b/drivers/gpu/drm/amd/pm/powerplay/inc/power_state.h index a5f2227a3971cec50683eaea2ab871eeb3b974ad..0ffc2347829d0bff8fe2100434fa4a2c0b3864a7 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/inc/power_state.h +++ b/drivers/gpu/drm/amd/pm/powerplay/inc/power_state.h @@ -131,6 +131,7 @@ struct PP_TemperatureRange { int mem_min; int mem_crit_max; int mem_emergency_max; + int sw_ctf_threshold; }; struct PP_StateValidationBlock { diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c index 4dea79a0c5b5e182f178cf058406d83e5f778685..ce41a8309582c91dca9d901df46691ad36079560 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -24,6 +24,7 @@ #include #include +#include #include "amdgpu.h" #include "amdgpu_smu.h" @@ -1078,6 +1079,34 @@ static void smu_interrupt_work_fn(struct work_struct *work) smu->ppt_funcs->interrupt_work(smu); } +static void smu_swctf_delayed_work_handler(struct work_struct *work) +{ + struct smu_context *smu = + container_of(work, struct smu_context, swctf_delayed_work.work); + struct smu_temperature_range *range = + &smu->thermal_range; + struct amdgpu_device *adev = smu->adev; + uint32_t hotspot_tmp, size; + + /* + * If the hotspot temperature is confirmed as below SW CTF setting point + * after the delay enforced, nothing will be done. + * Otherwise, a graceful shutdown will be performed to prevent further damage. + */ + if (range->software_shutdown_temp && + smu->ppt_funcs->read_sensor && + !smu->ppt_funcs->read_sensor(smu, + AMDGPU_PP_SENSOR_HOTSPOT_TEMP, + &hotspot_tmp, + &size) && + hotspot_tmp / 1000 < range->software_shutdown_temp) + return; + + dev_emerg(adev->dev, "ERROR: GPU over temperature range(SW CTF) detected!\n"); + dev_emerg(adev->dev, "ERROR: System is going to shutdown due to GPU SW CTF!\n"); + orderly_poweroff(true); +} + static int smu_sw_init(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; @@ -1120,6 +1149,9 @@ static int smu_sw_init(void *handle) smu->smu_dpm.dpm_level = AMD_DPM_FORCED_LEVEL_AUTO; smu->smu_dpm.requested_dpm_level = AMD_DPM_FORCED_LEVEL_AUTO; + INIT_DELAYED_WORK(&smu->swctf_delayed_work, + smu_swctf_delayed_work_handler); + ret = smu_smc_table_sw_init(smu); if (ret) { dev_err(adev->dev, "Failed to sw init smc table!\n"); @@ -1600,6 +1632,8 @@ static int smu_smc_hw_cleanup(struct smu_context *smu) return ret; } + cancel_delayed_work_sync(&smu->swctf_delayed_work); + ret = smu_disable_dpms(smu); if (ret) { dev_err(adev->dev, "Fail to disable dpm features!\n"); diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h index 09469c750a96bd4a22d601170ba3eb0938356644..6e2069dcb6b9d64b4d692d69d7469cd4827289f6 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h @@ -573,6 +573,8 @@ struct smu_context u32 debug_param_reg; u32 debug_msg_reg; u32 debug_resp_reg; + + struct delayed_work swctf_delayed_work; }; struct i2c_adapter; diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h index 6a0ac0bbaace995764351cd19add1b25367cfa7d..355c156d871aff86aff1c64d8bc1278c14ea9cbb 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h @@ -295,5 +295,9 @@ int smu_v13_0_get_pptable_from_firmware(struct smu_context *smu, uint32_t *size, uint32_t pptable_id); +int smu_v13_0_update_pcie_parameters(struct smu_context *smu, + uint32_t pcie_gen_cap, + uint32_t pcie_width_cap); + #endif #endif diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c index 9cd005131f5661683e193f57bfc0dda66b2332e5..3bb18396d2f9d3d52ed5e877b0ae942822656627 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c @@ -2113,7 +2113,6 @@ static int arcturus_i2c_xfer(struct i2c_adapter *i2c_adap, } mutex_lock(&adev->pm.mutex); r = smu_cmn_update_table(smu, SMU_TABLE_I2C_COMMANDS, 0, req, true); - mutex_unlock(&adev->pm.mutex); if (r) goto fail; @@ -2130,6 +2129,7 @@ static int arcturus_i2c_xfer(struct i2c_adapter *i2c_adap, } r = num_msgs; fail: + mutex_unlock(&adev->pm.mutex); kfree(req); return r; } diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c index 275f708db63626183e2a45b14782a7b54ac12328..95f6d821bacbcb57513ed2904f03b383f58661b7 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c @@ -1654,7 +1654,7 @@ static int navi10_force_clk_levels(struct smu_context *smu, enum smu_clk_type clk_type, uint32_t mask) { - int ret = 0, size = 0; + int ret = 0; uint32_t soft_min_level = 0, soft_max_level = 0, min_freq = 0, max_freq = 0; soft_min_level = mask ? (ffs(mask) - 1) : 0; @@ -1675,15 +1675,15 @@ static int navi10_force_clk_levels(struct smu_context *smu, ret = smu_v11_0_get_dpm_freq_by_index(smu, clk_type, soft_min_level, &min_freq); if (ret) - return size; + return 0; ret = smu_v11_0_get_dpm_freq_by_index(smu, clk_type, soft_max_level, &max_freq); if (ret) - return size; + return 0; ret = smu_v11_0_set_soft_freq_limited_range(smu, clk_type, min_freq, max_freq); if (ret) - return size; + return 0; break; case SMU_DCEFCLK: dev_info(smu->adev->dev,"Setting DCEFCLK min/max dpm level is not supported!\n"); @@ -1693,7 +1693,7 @@ static int navi10_force_clk_levels(struct smu_context *smu, break; } - return size; + return 0; } static int navi10_populate_umd_state_clk(struct smu_context *smu) @@ -3021,7 +3021,6 @@ static int navi10_i2c_xfer(struct i2c_adapter *i2c_adap, } mutex_lock(&adev->pm.mutex); r = smu_cmn_update_table(smu, SMU_TABLE_I2C_COMMANDS, 0, req, true); - mutex_unlock(&adev->pm.mutex); if (r) goto fail; @@ -3038,6 +3037,7 @@ static int navi10_i2c_xfer(struct i2c_adapter *i2c_adap, } r = num_msgs; fail: + mutex_unlock(&adev->pm.mutex); kfree(req); return r; } diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c index f7ed3e655e39796861ec9e34f342d8eed6f147de..f6599c00a6fdcc59c55bbfb72406eb0067d59ee5 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c @@ -2077,89 +2077,36 @@ static int sienna_cichlid_display_disable_memory_clock_switch(struct smu_context return ret; } -static void sienna_cichlid_get_override_pcie_settings(struct smu_context *smu, - uint32_t *gen_speed_override, - uint32_t *lane_width_override) -{ - struct amdgpu_device *adev = smu->adev; - - *gen_speed_override = 0xff; - *lane_width_override = 0xff; - - switch (adev->pdev->device) { - case 0x73A0: - case 0x73A1: - case 0x73A2: - case 0x73A3: - case 0x73AB: - case 0x73AE: - /* Bit 7:0: PCIE lane width, 1 to 7 corresponds is x1 to x32 */ - *lane_width_override = 6; - break; - case 0x73E0: - case 0x73E1: - case 0x73E3: - *lane_width_override = 4; - break; - case 0x7420: - case 0x7421: - case 0x7422: - case 0x7423: - case 0x7424: - *lane_width_override = 3; - break; - default: - break; - } -} - -#define MAX(a, b) ((a) > (b) ? (a) : (b)) - static int sienna_cichlid_update_pcie_parameters(struct smu_context *smu, uint32_t pcie_gen_cap, uint32_t pcie_width_cap) { struct smu_11_0_dpm_context *dpm_context = smu->smu_dpm.dpm_context; struct smu_11_0_pcie_table *pcie_table = &dpm_context->dpm_tables.pcie_table; - uint32_t gen_speed_override, lane_width_override; - uint8_t *table_member1, *table_member2; - uint32_t min_gen_speed, max_gen_speed; - uint32_t min_lane_width, max_lane_width; - uint32_t smu_pcie_arg; + u32 smu_pcie_arg; int ret, i; - GET_PPTABLE_MEMBER(PcieGenSpeed, &table_member1); - GET_PPTABLE_MEMBER(PcieLaneCount, &table_member2); - - sienna_cichlid_get_override_pcie_settings(smu, - &gen_speed_override, - &lane_width_override); + /* PCIE gen speed and lane width override */ + if (!amdgpu_device_pcie_dynamic_switching_supported()) { + if (pcie_table->pcie_gen[NUM_LINK_LEVELS - 1] < pcie_gen_cap) + pcie_gen_cap = pcie_table->pcie_gen[NUM_LINK_LEVELS - 1]; - /* PCIE gen speed override */ - if (gen_speed_override != 0xff) { - min_gen_speed = MIN(pcie_gen_cap, gen_speed_override); - max_gen_speed = MIN(pcie_gen_cap, gen_speed_override); - } else { - min_gen_speed = MAX(0, table_member1[0]); - max_gen_speed = MIN(pcie_gen_cap, table_member1[1]); - min_gen_speed = min_gen_speed > max_gen_speed ? - max_gen_speed : min_gen_speed; - } - pcie_table->pcie_gen[0] = min_gen_speed; - pcie_table->pcie_gen[1] = max_gen_speed; + if (pcie_table->pcie_lane[NUM_LINK_LEVELS - 1] < pcie_width_cap) + pcie_width_cap = pcie_table->pcie_lane[NUM_LINK_LEVELS - 1]; - /* PCIE lane width override */ - if (lane_width_override != 0xff) { - min_lane_width = MIN(pcie_width_cap, lane_width_override); - max_lane_width = MIN(pcie_width_cap, lane_width_override); + /* Force all levels to use the same settings */ + for (i = 0; i < NUM_LINK_LEVELS; i++) { + pcie_table->pcie_gen[i] = pcie_gen_cap; + pcie_table->pcie_lane[i] = pcie_width_cap; + } } else { - min_lane_width = MAX(1, table_member2[0]); - max_lane_width = MIN(pcie_width_cap, table_member2[1]); - min_lane_width = min_lane_width > max_lane_width ? - max_lane_width : min_lane_width; + for (i = 0; i < NUM_LINK_LEVELS; i++) { + if (pcie_table->pcie_gen[i] > pcie_gen_cap) + pcie_table->pcie_gen[i] = pcie_gen_cap; + if (pcie_table->pcie_lane[i] > pcie_width_cap) + pcie_table->pcie_lane[i] = pcie_width_cap; + } } - pcie_table->pcie_lane[0] = min_lane_width; - pcie_table->pcie_lane[1] = max_lane_width; for (i = 0; i < NUM_LINK_LEVELS; i++) { smu_pcie_arg = (i << 16 | @@ -3842,7 +3789,6 @@ static int sienna_cichlid_i2c_xfer(struct i2c_adapter *i2c_adap, } mutex_lock(&adev->pm.mutex); r = smu_cmn_update_table(smu, SMU_TABLE_I2C_COMMANDS, 0, req, true); - mutex_unlock(&adev->pm.mutex); if (r) goto fail; @@ -3859,6 +3805,7 @@ static int sienna_cichlid_i2c_xfer(struct i2c_adapter *i2c_adap, } r = num_msgs; fail: + mutex_unlock(&adev->pm.mutex); kfree(req); return r; } diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c index e1ef88ee1ed393fb768934dab53c16ae3cff981a..aa4a5498a12f73726947733ace08b150bd490bf8 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c @@ -1412,13 +1412,8 @@ static int smu_v11_0_irq_process(struct amdgpu_device *adev, if (client_id == SOC15_IH_CLIENTID_THM) { switch (src_id) { case THM_11_0__SRCID__THM_DIG_THERM_L2H: - dev_emerg(adev->dev, "ERROR: GPU over temperature range(SW CTF) detected!\n"); - /* - * SW CTF just occurred. - * Try to do a graceful shutdown to prevent further damage. - */ - dev_emerg(adev->dev, "ERROR: System is going to shutdown due to GPU SW CTF!\n"); - orderly_poweroff(true); + schedule_delayed_work(&smu->swctf_delayed_work, + msecs_to_jiffies(AMDGPU_SWCTF_EXTRA_DELAY)); break; case THM_11_0__SRCID__THM_DIG_THERM_H2L: dev_emerg(adev->dev, "ERROR: GPU under temperature range detected\n"); diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c index e80f122d8aec5bab03ad03b53f71dade1fe5e377..ce50ef46e73fc2a6ab50b5cc8bbae738e168976a 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c @@ -1525,7 +1525,6 @@ static int aldebaran_i2c_xfer(struct i2c_adapter *i2c_adap, } mutex_lock(&adev->pm.mutex); r = smu_cmn_update_table(smu, SMU_TABLE_I2C_COMMANDS, 0, req, true); - mutex_unlock(&adev->pm.mutex); if (r) goto fail; @@ -1542,6 +1541,7 @@ static int aldebaran_i2c_xfer(struct i2c_adapter *i2c_adap, } r = num_msgs; fail: + mutex_unlock(&adev->pm.mutex); kfree(req); return r; } diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c index e52c563f0dacc50a4aeed6dbe0e6c0809cec5f8b..9b62b45ebb7f0a38d9527ba19eec124a52bed591 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c @@ -1353,13 +1353,8 @@ static int smu_v13_0_irq_process(struct amdgpu_device *adev, if (client_id == SOC15_IH_CLIENTID_THM) { switch (src_id) { case THM_11_0__SRCID__THM_DIG_THERM_L2H: - dev_emerg(adev->dev, "ERROR: GPU over temperature range(SW CTF) detected!\n"); - /* - * SW CTF just occurred. - * Try to do a graceful shutdown to prevent further damage. - */ - dev_emerg(adev->dev, "ERROR: System is going to shutdown due to GPU SW CTF!\n"); - orderly_poweroff(true); + schedule_delayed_work(&smu->swctf_delayed_work, + msecs_to_jiffies(AMDGPU_SWCTF_EXTRA_DELAY)); break; case THM_11_0__SRCID__THM_DIG_THERM_H2L: dev_emerg(adev->dev, "ERROR: GPU under temperature range detected\n"); @@ -2429,3 +2424,51 @@ int smu_v13_0_mode1_reset(struct smu_context *smu) return ret; } + +int smu_v13_0_update_pcie_parameters(struct smu_context *smu, + uint32_t pcie_gen_cap, + uint32_t pcie_width_cap) +{ + struct smu_13_0_dpm_context *dpm_context = smu->smu_dpm.dpm_context; + struct smu_13_0_pcie_table *pcie_table = + &dpm_context->dpm_tables.pcie_table; + int num_of_levels = pcie_table->num_of_link_levels; + uint32_t smu_pcie_arg; + int ret, i; + + if (!amdgpu_device_pcie_dynamic_switching_supported()) { + if (pcie_table->pcie_gen[num_of_levels - 1] < pcie_gen_cap) + pcie_gen_cap = pcie_table->pcie_gen[num_of_levels - 1]; + + if (pcie_table->pcie_lane[num_of_levels - 1] < pcie_width_cap) + pcie_width_cap = pcie_table->pcie_lane[num_of_levels - 1]; + + /* Force all levels to use the same settings */ + for (i = 0; i < num_of_levels; i++) { + pcie_table->pcie_gen[i] = pcie_gen_cap; + pcie_table->pcie_lane[i] = pcie_width_cap; + } + } else { + for (i = 0; i < num_of_levels; i++) { + if (pcie_table->pcie_gen[i] > pcie_gen_cap) + pcie_table->pcie_gen[i] = pcie_gen_cap; + if (pcie_table->pcie_lane[i] > pcie_width_cap) + pcie_table->pcie_lane[i] = pcie_width_cap; + } + } + + for (i = 0; i < num_of_levels; i++) { + smu_pcie_arg = i << 16; + smu_pcie_arg |= pcie_table->pcie_gen[i] << 8; + smu_pcie_arg |= pcie_table->pcie_lane[i]; + + ret = smu_cmn_send_smc_msg_with_param(smu, + SMU_MSG_OverridePcieParameters, + smu_pcie_arg, + NULL); + if (ret) + return ret; + } + + return 0; +} diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c index a6083957ae51b531896bc582b7b77269e3cb8cb7..b9bde5fa8f8f5c9b8fc7cf3faef0f0f38536090c 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c @@ -1645,37 +1645,6 @@ static int smu_v13_0_0_force_clk_levels(struct smu_context *smu, return ret; } -static int smu_v13_0_0_update_pcie_parameters(struct smu_context *smu, - uint32_t pcie_gen_cap, - uint32_t pcie_width_cap) -{ - struct smu_13_0_dpm_context *dpm_context = smu->smu_dpm.dpm_context; - struct smu_13_0_pcie_table *pcie_table = - &dpm_context->dpm_tables.pcie_table; - uint32_t smu_pcie_arg; - int ret, i; - - for (i = 0; i < pcie_table->num_of_link_levels; i++) { - if (pcie_table->pcie_gen[i] > pcie_gen_cap) - pcie_table->pcie_gen[i] = pcie_gen_cap; - if (pcie_table->pcie_lane[i] > pcie_width_cap) - pcie_table->pcie_lane[i] = pcie_width_cap; - - smu_pcie_arg = i << 16; - smu_pcie_arg |= pcie_table->pcie_gen[i] << 8; - smu_pcie_arg |= pcie_table->pcie_lane[i]; - - ret = smu_cmn_send_smc_msg_with_param(smu, - SMU_MSG_OverridePcieParameters, - smu_pcie_arg, - NULL); - if (ret) - return ret; - } - - return 0; -} - static const struct smu_temperature_range smu13_thermal_policy[] = { {-273150, 99000, 99000, -273150, 99000, 99000, -273150, 99000, 99000}, { 120000, 120000, 120000, 120000, 120000, 120000, 120000, 120000, 120000}, @@ -1710,6 +1679,7 @@ static int smu_v13_0_0_get_thermal_temperature_range(struct smu_context *smu, range->mem_emergency_max = (pptable->SkuTable.TemperatureLimit[TEMP_MEM] + CTF_OFFSET_MEM)* SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; range->software_shutdown_temp = powerplay_table->software_shutdown_temp; + range->software_shutdown_temp_offset = pptable->SkuTable.FanAbnormalTempLimitOffset; return 0; } @@ -2319,7 +2289,6 @@ static int smu_v13_0_0_i2c_xfer(struct i2c_adapter *i2c_adap, } mutex_lock(&adev->pm.mutex); r = smu_cmn_update_table(smu, SMU_TABLE_I2C_COMMANDS, 0, req, true); - mutex_unlock(&adev->pm.mutex); if (r) goto fail; @@ -2336,6 +2305,7 @@ static int smu_v13_0_0_i2c_xfer(struct i2c_adapter *i2c_adap, } r = num_msgs; fail: + mutex_unlock(&adev->pm.mutex); kfree(req); return r; } @@ -2653,7 +2623,7 @@ static const struct pptable_funcs smu_v13_0_0_ppt_funcs = { .feature_is_enabled = smu_cmn_feature_is_enabled, .print_clk_levels = smu_v13_0_0_print_clk_levels, .force_clk_levels = smu_v13_0_0_force_clk_levels, - .update_pcie_parameters = smu_v13_0_0_update_pcie_parameters, + .update_pcie_parameters = smu_v13_0_update_pcie_parameters, .get_thermal_temperature_range = smu_v13_0_0_get_thermal_temperature_range, .register_irq_handler = smu_v13_0_register_irq_handler, .enable_thermal_alert = smu_v13_0_enable_thermal_alert, diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c index a92ea4601ea4740d4fb14223f2d605316ccc4017..1ac552142763f8ab2a8f21b9234ded19c6fd3b8b 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c @@ -200,7 +200,6 @@ struct PPTable_t { }; #define SMUQ10_TO_UINT(x) ((x) >> 10) -#define SMUQ16_TO_UINT(x) ((x) >> 16) struct smu_v13_0_6_dpm_map { enum smu_clk_type clk_type; @@ -1764,7 +1763,6 @@ static int smu_v13_0_6_i2c_xfer(struct i2c_adapter *i2c_adap, } mutex_lock(&adev->pm.mutex); r = smu_v13_0_6_request_i2c_xfer(smu, req); - mutex_unlock(&adev->pm.mutex); if (r) goto fail; @@ -1781,6 +1779,7 @@ static int smu_v13_0_6_i2c_xfer(struct i2c_adapter *i2c_adap, } r = num_msgs; fail: + mutex_unlock(&adev->pm.mutex); kfree(req); return r; } @@ -1994,8 +1993,9 @@ static ssize_t smu_v13_0_6_get_gpu_metrics(struct smu_context *smu, void **table gpu_metrics->average_socket_power = SMUQ10_TO_UINT(metrics->SocketPower); + /* Energy is reported in 15.625mJ units */ gpu_metrics->energy_accumulator = - SMUQ16_TO_UINT(metrics->SocketEnergyAcc); + SMUQ10_TO_UINT(metrics->SocketEnergyAcc); gpu_metrics->current_gfxclk = SMUQ10_TO_UINT(metrics->GfxclkFrequency[xcc0]); diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c index cda4e818aab7e9381273f5ee4739d88f54a41305..3ba02131e682be3babf6b90e1c14466964779cf5 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c @@ -1635,37 +1635,6 @@ static int smu_v13_0_7_force_clk_levels(struct smu_context *smu, return ret; } -static int smu_v13_0_7_update_pcie_parameters(struct smu_context *smu, - uint32_t pcie_gen_cap, - uint32_t pcie_width_cap) -{ - struct smu_13_0_dpm_context *dpm_context = smu->smu_dpm.dpm_context; - struct smu_13_0_pcie_table *pcie_table = - &dpm_context->dpm_tables.pcie_table; - uint32_t smu_pcie_arg; - int ret, i; - - for (i = 0; i < pcie_table->num_of_link_levels; i++) { - if (pcie_table->pcie_gen[i] > pcie_gen_cap) - pcie_table->pcie_gen[i] = pcie_gen_cap; - if (pcie_table->pcie_lane[i] > pcie_width_cap) - pcie_table->pcie_lane[i] = pcie_width_cap; - - smu_pcie_arg = i << 16; - smu_pcie_arg |= pcie_table->pcie_gen[i] << 8; - smu_pcie_arg |= pcie_table->pcie_lane[i]; - - ret = smu_cmn_send_smc_msg_with_param(smu, - SMU_MSG_OverridePcieParameters, - smu_pcie_arg, - NULL); - if (ret) - return ret; - } - - return 0; -} - static const struct smu_temperature_range smu13_thermal_policy[] = { {-273150, 99000, 99000, -273150, 99000, 99000, -273150, 99000, 99000}, @@ -2234,7 +2203,7 @@ static const struct pptable_funcs smu_v13_0_7_ppt_funcs = { .feature_is_enabled = smu_cmn_feature_is_enabled, .print_clk_levels = smu_v13_0_7_print_clk_levels, .force_clk_levels = smu_v13_0_7_force_clk_levels, - .update_pcie_parameters = smu_v13_0_7_update_pcie_parameters, + .update_pcie_parameters = smu_v13_0_update_pcie_parameters, .get_thermal_temperature_range = smu_v13_0_7_get_thermal_temperature_range, .register_irq_handler = smu_v13_0_register_irq_handler, .enable_thermal_alert = smu_v13_0_enable_thermal_alert, diff --git a/drivers/gpu/drm/armada/armada_fbdev.c b/drivers/gpu/drm/armada/armada_fbdev.c index 3943e89cc06c826b768009222aef337cbbc7e2af..e40a95e5178565aaac05651858fce8e0b9416679 100644 --- a/drivers/gpu/drm/armada/armada_fbdev.c +++ b/drivers/gpu/drm/armada/armada_fbdev.c @@ -209,10 +209,6 @@ void armada_fbdev_setup(struct drm_device *dev) goto err_drm_client_init; } - ret = armada_fbdev_client_hotplug(&fbh->client); - if (ret) - drm_dbg_kms(dev, "client hotplug ret=%d\n", ret); - drm_client_register(&fbh->client); return; diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c index 977f3a544d4d6339d4decf6fb5d70959f550a2e5..b23214b0c49648d87e9a7d26f23235fb36fd6209 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c @@ -1412,9 +1412,9 @@ void dw_hdmi_set_high_tmds_clock_ratio(struct dw_hdmi *hdmi, /* Control for TMDS Bit Period/TMDS Clock-Period Ratio */ if (dw_hdmi_support_scdc(hdmi, display)) { if (mtmdsclock > HDMI14_MAX_TMDSCLK) - drm_scdc_set_high_tmds_clock_ratio(&hdmi->connector, 1); + drm_scdc_set_high_tmds_clock_ratio(hdmi->curr_conn, 1); else - drm_scdc_set_high_tmds_clock_ratio(&hdmi->connector, 0); + drm_scdc_set_high_tmds_clock_ratio(hdmi->curr_conn, 0); } } EXPORT_SYMBOL_GPL(dw_hdmi_set_high_tmds_clock_ratio); @@ -2102,7 +2102,7 @@ static void hdmi_av_composer(struct dw_hdmi *hdmi, min_t(u8, bytes, SCDC_MIN_SOURCE_VERSION)); /* Enabled Scrambling in the Sink */ - drm_scdc_set_scrambling(&hdmi->connector, 1); + drm_scdc_set_scrambling(hdmi->curr_conn, 1); /* * To activate the scrambler feature, you must ensure @@ -2118,7 +2118,7 @@ static void hdmi_av_composer(struct dw_hdmi *hdmi, hdmi_writeb(hdmi, 0, HDMI_FC_SCRAMBLER_CTRL); hdmi_writeb(hdmi, (u8)~HDMI_MC_SWRSTZ_TMDSSWRST_REQ, HDMI_MC_SWRSTZ); - drm_scdc_set_scrambling(&hdmi->connector, 0); + drm_scdc_set_scrambling(hdmi->curr_conn, 0); } } @@ -3546,6 +3546,7 @@ struct dw_hdmi *dw_hdmi_probe(struct platform_device *pdev, hdmi->bridge.ops = DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_EDID | DRM_BRIDGE_OP_HPD; hdmi->bridge.interlace_allowed = true; + hdmi->bridge.ddc = hdmi->ddc; #ifdef CONFIG_OF hdmi->bridge.of_node = pdev->dev.of_node; #endif diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi86.c b/drivers/gpu/drm/bridge/ti-sn65dsi86.c index c499a14d0b980a12333d6ea809d198ec568c16f3..f448b903e19075676247fc72d30a1a9b1f501085 100644 --- a/drivers/gpu/drm/bridge/ti-sn65dsi86.c +++ b/drivers/gpu/drm/bridge/ti-sn65dsi86.c @@ -170,10 +170,10 @@ * @pwm_refclk_freq: Cache for the reference clock input to the PWM. */ struct ti_sn65dsi86 { - struct auxiliary_device bridge_aux; - struct auxiliary_device gpio_aux; - struct auxiliary_device aux_aux; - struct auxiliary_device pwm_aux; + struct auxiliary_device *bridge_aux; + struct auxiliary_device *gpio_aux; + struct auxiliary_device *aux_aux; + struct auxiliary_device *pwm_aux; struct device *dev; struct regmap *regmap; @@ -468,27 +468,34 @@ static void ti_sn65dsi86_delete_aux(void *data) auxiliary_device_delete(data); } -/* - * AUX bus docs say that a non-NULL release is mandatory, but it makes no - * sense for the model used here where all of the aux devices are allocated - * in the single shared structure. We'll use this noop as a workaround. - */ -static void ti_sn65dsi86_noop(struct device *dev) {} +static void ti_sn65dsi86_aux_device_release(struct device *dev) +{ + struct auxiliary_device *aux = container_of(dev, struct auxiliary_device, dev); + + kfree(aux); +} static int ti_sn65dsi86_add_aux_device(struct ti_sn65dsi86 *pdata, - struct auxiliary_device *aux, + struct auxiliary_device **aux_out, const char *name) { struct device *dev = pdata->dev; + struct auxiliary_device *aux; int ret; + aux = kzalloc(sizeof(*aux), GFP_KERNEL); + if (!aux) + return -ENOMEM; + aux->name = name; aux->dev.parent = dev; - aux->dev.release = ti_sn65dsi86_noop; + aux->dev.release = ti_sn65dsi86_aux_device_release; device_set_of_node_from_dev(&aux->dev, dev); ret = auxiliary_device_init(aux); - if (ret) + if (ret) { + kfree(aux); return ret; + } ret = devm_add_action_or_reset(dev, ti_sn65dsi86_uninit_aux, aux); if (ret) return ret; @@ -497,6 +504,8 @@ static int ti_sn65dsi86_add_aux_device(struct ti_sn65dsi86 *pdata, if (ret) return ret; ret = devm_add_action_or_reset(dev, ti_sn65dsi86_delete_aux, aux); + if (!ret) + *aux_out = aux; return ret; } diff --git a/drivers/gpu/drm/display/drm_dp_helper.c b/drivers/gpu/drm/display/drm_dp_helper.c index 16565a0a5da6d98d1001cfd3acb9cd547e73b105..e6a78fd32380a1e73d58ecd4f5f4221ec5b599db 100644 --- a/drivers/gpu/drm/display/drm_dp_helper.c +++ b/drivers/gpu/drm/display/drm_dp_helper.c @@ -2103,7 +2103,7 @@ int drm_dp_aux_register(struct drm_dp_aux *aux) aux->ddc.owner = THIS_MODULE; aux->ddc.dev.parent = aux->dev; - strlcpy(aux->ddc.name, aux->name ? aux->name : dev_name(aux->dev), + strscpy(aux->ddc.name, aux->name ? aux->name : dev_name(aux->dev), sizeof(aux->ddc.name)); ret = drm_dp_aux_register_devnode(aux); diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c index 8fe7b635e5bb261d2f3499845fcfdafdb9b405f8..ed96cfcfa304013158dbaa3629529d32ed07cc7d 100644 --- a/drivers/gpu/drm/display/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c @@ -3404,7 +3404,7 @@ int drm_dp_add_payload_part2(struct drm_dp_mst_topology_mgr *mgr, /* Skip failed payloads */ if (payload->vc_start_slot == -1) { - drm_dbg_kms(state->dev, "Part 1 of payload creation for %s failed, skipping part 2\n", + drm_dbg_kms(mgr->dev, "Part 1 of payload creation for %s failed, skipping part 2\n", payload->port->connector->name); return -EIO; } @@ -5773,7 +5773,7 @@ static int drm_dp_mst_register_i2c_bus(struct drm_dp_mst_port *port) aux->ddc.dev.parent = parent_dev; aux->ddc.dev.of_node = parent_dev->of_node; - strlcpy(aux->ddc.name, aux->name ? aux->name : dev_name(parent_dev), + strscpy(aux->ddc.name, aux->name ? aux->name : dev_name(parent_dev), sizeof(aux->ddc.name)); return i2c_add_adapter(&aux->ddc); diff --git a/drivers/gpu/drm/drm_client.c b/drivers/gpu/drm/drm_client.c index f6292ba0e6fc378371dcbde10857144ce501a619..037e36f2049c1793d287ca6cbeff7d7a8870a610 100644 --- a/drivers/gpu/drm/drm_client.c +++ b/drivers/gpu/drm/drm_client.c @@ -122,13 +122,34 @@ EXPORT_SYMBOL(drm_client_init); * drm_client_register() it is no longer permissible to call drm_client_release() * directly (outside the unregister callback), instead cleanup will happen * automatically on driver unload. + * + * Registering a client generates a hotplug event that allows the client + * to set up its display from pre-existing outputs. The client must have + * initialized its state to able to handle the hotplug event successfully. */ void drm_client_register(struct drm_client_dev *client) { struct drm_device *dev = client->dev; + int ret; mutex_lock(&dev->clientlist_mutex); list_add(&client->list, &dev->clientlist); + + if (client->funcs && client->funcs->hotplug) { + /* + * Perform an initial hotplug event to pick up the + * display configuration for the client. This step + * has to be performed *after* registering the client + * in the list of clients, or a concurrent hotplug + * event might be lost; leaving the display off. + * + * Hold the clientlist_mutex as for a regular hotplug + * event. + */ + ret = client->funcs->hotplug(client); + if (ret) + drm_dbg_kms(dev, "client hotplug ret=%d\n", ret); + } mutex_unlock(&dev->clientlist_mutex); } EXPORT_SYMBOL(drm_client_register); diff --git a/drivers/gpu/drm/drm_fbdev_dma.c b/drivers/gpu/drm/drm_fbdev_dma.c index 8217f1ddc0075b4ecfc52216773d4c11d4e4e647..73b8e99faad7afbdada7d2426cfc521130bbab17 100644 --- a/drivers/gpu/drm/drm_fbdev_dma.c +++ b/drivers/gpu/drm/drm_fbdev_dma.c @@ -213,7 +213,7 @@ static const struct drm_client_funcs drm_fbdev_dma_client_funcs = { * drm_fbdev_dma_setup() - Setup fbdev emulation for GEM DMA helpers * @dev: DRM device * @preferred_bpp: Preferred bits per pixel for the device. - * @dev->mode_config.preferred_depth is used if this is zero. + * 32 is used if this is zero. * * This function sets up fbdev emulation for GEM DMA drivers that support * dumb buffers with a virtual address and that can be mmap'ed. @@ -248,10 +248,6 @@ void drm_fbdev_dma_setup(struct drm_device *dev, unsigned int preferred_bpp) goto err_drm_client_init; } - ret = drm_fbdev_dma_client_hotplug(&fb_helper->client); - if (ret) - drm_dbg_kms(dev, "client hotplug ret=%d\n", ret); - drm_client_register(&fb_helper->client); return; diff --git a/drivers/gpu/drm/drm_fbdev_generic.c b/drivers/gpu/drm/drm_fbdev_generic.c index 98ae703848a02fa34b947de96511853fab4fbee3..b9343fb6cf13e93953e70cf41e58189e0bd2ee34 100644 --- a/drivers/gpu/drm/drm_fbdev_generic.c +++ b/drivers/gpu/drm/drm_fbdev_generic.c @@ -339,10 +339,6 @@ void drm_fbdev_generic_setup(struct drm_device *dev, unsigned int preferred_bpp) goto err_drm_client_init; } - ret = drm_fbdev_generic_client_hotplug(&fb_helper->client); - if (ret) - drm_dbg_kms(dev, "client hotplug ret=%d\n", ret); - drm_client_register(&fb_helper->client); return; diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c index dfe76c70bcb364930712141a02adb7bfde46e076..6129b89bb36618db7686cec9cc0a7a4c8d9d5410 100644 --- a/drivers/gpu/drm/drm_gem.c +++ b/drivers/gpu/drm/drm_gem.c @@ -499,13 +499,13 @@ int drm_gem_create_mmap_offset(struct drm_gem_object *obj) EXPORT_SYMBOL(drm_gem_create_mmap_offset); /* - * Move pages to appropriate lru and release the pagevec, decrementing the - * ref count of those pages. + * Move folios to appropriate lru and release the folios, decrementing the + * ref count of those folios. */ -static void drm_gem_check_release_pagevec(struct pagevec *pvec) +static void drm_gem_check_release_batch(struct folio_batch *fbatch) { - check_move_unevictable_pages(pvec); - __pagevec_release(pvec); + check_move_unevictable_folios(fbatch); + __folio_batch_release(fbatch); cond_resched(); } @@ -537,10 +537,10 @@ static void drm_gem_check_release_pagevec(struct pagevec *pvec) struct page **drm_gem_get_pages(struct drm_gem_object *obj) { struct address_space *mapping; - struct page *p, **pages; - struct pagevec pvec; - int i, npages; - + struct page **pages; + struct folio *folio; + struct folio_batch fbatch; + int i, j, npages; if (WARN_ON(!obj->filp)) return ERR_PTR(-EINVAL); @@ -562,11 +562,14 @@ struct page **drm_gem_get_pages(struct drm_gem_object *obj) mapping_set_unevictable(mapping); - for (i = 0; i < npages; i++) { - p = shmem_read_mapping_page(mapping, i); - if (IS_ERR(p)) + i = 0; + while (i < npages) { + folio = shmem_read_folio_gfp(mapping, i, + mapping_gfp_mask(mapping)); + if (IS_ERR(folio)) goto fail; - pages[i] = p; + for (j = 0; j < folio_nr_pages(folio); j++, i++) + pages[i] = folio_file_page(folio, i); /* Make sure shmem keeps __GFP_DMA32 allocated pages in the * correct region during swapin. Note that this requires @@ -574,23 +577,26 @@ struct page **drm_gem_get_pages(struct drm_gem_object *obj) * so shmem can relocate pages during swapin if required. */ BUG_ON(mapping_gfp_constraint(mapping, __GFP_DMA32) && - (page_to_pfn(p) >= 0x00100000UL)); + (folio_pfn(folio) >= 0x00100000UL)); } return pages; fail: mapping_clear_unevictable(mapping); - pagevec_init(&pvec); - while (i--) { - if (!pagevec_add(&pvec, pages[i])) - drm_gem_check_release_pagevec(&pvec); + folio_batch_init(&fbatch); + j = 0; + while (j < i) { + struct folio *f = page_folio(pages[j]); + if (!folio_batch_add(&fbatch, f)) + drm_gem_check_release_batch(&fbatch); + j += folio_nr_pages(f); } - if (pagevec_count(&pvec)) - drm_gem_check_release_pagevec(&pvec); + if (fbatch.nr) + drm_gem_check_release_batch(&fbatch); kvfree(pages); - return ERR_CAST(p); + return ERR_CAST(folio); } EXPORT_SYMBOL(drm_gem_get_pages); @@ -606,7 +612,7 @@ void drm_gem_put_pages(struct drm_gem_object *obj, struct page **pages, { int i, npages; struct address_space *mapping; - struct pagevec pvec; + struct folio_batch fbatch; mapping = file_inode(obj->filp)->i_mapping; mapping_clear_unevictable(mapping); @@ -619,23 +625,27 @@ void drm_gem_put_pages(struct drm_gem_object *obj, struct page **pages, npages = obj->size >> PAGE_SHIFT; - pagevec_init(&pvec); + folio_batch_init(&fbatch); for (i = 0; i < npages; i++) { + struct folio *folio; + if (!pages[i]) continue; + folio = page_folio(pages[i]); if (dirty) - set_page_dirty(pages[i]); + folio_mark_dirty(folio); if (accessed) - mark_page_accessed(pages[i]); + folio_mark_accessed(folio); /* Undo the reference we took when populating the table */ - if (!pagevec_add(&pvec, pages[i])) - drm_gem_check_release_pagevec(&pvec); + if (!folio_batch_add(&fbatch, folio)) + drm_gem_check_release_batch(&fbatch); + i += folio_nr_pages(folio) - 1; } - if (pagevec_count(&pvec)) - drm_gem_check_release_pagevec(&pvec); + if (folio_batch_count(&fbatch)) + drm_gem_check_release_batch(&fbatch); kvfree(pages); } diff --git a/drivers/gpu/drm/drm_managed.c b/drivers/gpu/drm/drm_managed.c index 50e2e2ed9d99d8b7986fba8fabeeb33036cd63b0..bcd111404b128aacb5081cfb4a489dab636923e2 100644 --- a/drivers/gpu/drm/drm_managed.c +++ b/drivers/gpu/drm/drm_managed.c @@ -49,10 +49,10 @@ struct drmres { * Some archs want to perform DMA into kmalloc caches * and need a guaranteed alignment larger than * the alignment of a 64-bit integer. - * Thus we use ARCH_KMALLOC_MINALIGN here and get exactly the same - * buffer alignment as if it was allocated by plain kmalloc(). + * Thus we use ARCH_DMA_MINALIGN for data[] which will force the same + * alignment for struct drmres when allocated by kmalloc(). */ - u8 __aligned(ARCH_KMALLOC_MINALIGN) data[]; + u8 __aligned(ARCH_DMA_MINALIGN) data[]; }; static void free_dr(struct drmres *dr) diff --git a/drivers/gpu/drm/drm_mipi_dsi.c b/drivers/gpu/drm/drm_mipi_dsi.c index bc35f1057486ec23907774e3f22ab598f8f4b7c2..14201f73aab1340ac8cc8f050f742a419588e369 100644 --- a/drivers/gpu/drm/drm_mipi_dsi.c +++ b/drivers/gpu/drm/drm_mipi_dsi.c @@ -224,7 +224,7 @@ mipi_dsi_device_register_full(struct mipi_dsi_host *host, device_set_node(&dsi->dev, of_fwnode_handle(info->node)); dsi->channel = info->channel; - strlcpy(dsi->name, info->type, sizeof(dsi->name)); + strscpy(dsi->name, info->type, sizeof(dsi->name)); ret = mipi_dsi_device_add(dsi); if (ret) { diff --git a/drivers/gpu/drm/drm_syncobj.c b/drivers/gpu/drm/drm_syncobj.c index be3e8787d207c81eb5ae80651da191cdf1392320..f7003d1ec5ef1e080b8ea7e5c2dc22e16ff95d0d 100644 --- a/drivers/gpu/drm/drm_syncobj.c +++ b/drivers/gpu/drm/drm_syncobj.c @@ -400,10 +400,10 @@ EXPORT_SYMBOL(drm_syncobj_replace_fence); */ static int drm_syncobj_assign_null_handle(struct drm_syncobj *syncobj) { - struct dma_fence *fence = dma_fence_allocate_private_stub(); + struct dma_fence *fence = dma_fence_allocate_private_stub(ktime_get()); - if (IS_ERR(fence)) - return PTR_ERR(fence); + if (!fence) + return -ENOMEM; drm_syncobj_replace_fence(syncobj, fence); dma_fence_put(fence); diff --git a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c index fdf65587f1fe015868b2095cd120a27e5db596e4..226310c765d833d3f4c74e6541981b6493950e15 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c @@ -215,10 +215,6 @@ void exynos_drm_fbdev_setup(struct drm_device *dev) if (ret) goto err_drm_client_init; - ret = exynos_drm_fbdev_client_hotplug(&fb_helper->client); - if (ret) - drm_dbg_kms(dev, "client hotplug ret=%d\n", ret); - drm_client_register(&fb_helper->client); return; diff --git a/drivers/gpu/drm/gma500/fbdev.c b/drivers/gpu/drm/gma500/fbdev.c index 955cbe9f05a72eab99a671bc456a0ee19d6ee22e..054426549fc68447123ee0a74793b1b7da7d03ce 100644 --- a/drivers/gpu/drm/gma500/fbdev.c +++ b/drivers/gpu/drm/gma500/fbdev.c @@ -328,10 +328,6 @@ void psb_fbdev_setup(struct drm_psb_private *dev_priv) goto err_drm_fb_helper_unprepare; } - ret = psb_fbdev_client_hotplug(&fb_helper->client); - if (ret) - drm_dbg_kms(dev, "client hotplug ret=%d\n", ret); - drm_client_register(&fb_helper->client); return; diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c index 40bcd9067e69d036cb29160d01ac152e396d45f0..d8d7de18dd65271a3b82bdec792c49aa3e009d5b 100644 --- a/drivers/gpu/drm/i2c/tda998x_drv.c +++ b/drivers/gpu/drm/i2c/tda998x_drv.c @@ -1951,7 +1951,7 @@ static int tda998x_create(struct device *dev) * offset. */ memset(&cec_info, 0, sizeof(cec_info)); - strlcpy(cec_info.type, "tda9950", sizeof(cec_info.type)); + strscpy(cec_info.type, "tda9950", sizeof(cec_info.type)); cec_info.addr = priv->cec_addr; cec_info.platform_data = &priv->cec_glue; cec_info.irq = client->irq; diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c b/drivers/gpu/drm/i915/display/intel_cx0_phy.c index 0600fdcd06ef2a4bd76deec7869e379a302c22cc..719447ce86e7012431f1a7f302c90b78eecc7724 100644 --- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c @@ -2435,7 +2435,8 @@ static void intel_program_port_clock_ctl(struct intel_encoder *encoder, intel_de_rmw(i915, XELPDP_PORT_CLOCK_CTL(encoder->port), XELPDP_LANE1_PHY_CLOCK_SELECT | XELPDP_FORWARD_CLOCK_UNGATE | - XELPDP_DDI_CLOCK_SELECT_MASK | XELPDP_SSC_ENABLE_PLLB, val); + XELPDP_DDI_CLOCK_SELECT_MASK | XELPDP_SSC_ENABLE_PLLA | + XELPDP_SSC_ENABLE_PLLB, val); } static u32 intel_cx0_get_powerdown_update(u8 lane_mask) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index d8533603ad0523e1b621a4f6a95877df461ac433..16603d591f567cd69a2c9670a5680378f1037ba4 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -4564,7 +4564,6 @@ copy_bigjoiner_crtc_state_modeset(struct intel_atomic_state *state, saved_state->uapi = slave_crtc_state->uapi; saved_state->scaler_state = slave_crtc_state->scaler_state; saved_state->shared_dpll = slave_crtc_state->shared_dpll; - saved_state->dpll_hw_state = slave_crtc_state->dpll_hw_state; saved_state->crc_enabled = slave_crtc_state->crc_enabled; intel_crtc_free_hw_state(slave_crtc_state); diff --git a/drivers/gpu/drm/i915/display/intel_display_power.h b/drivers/gpu/drm/i915/display/intel_display_power.h index be1a87bde0c9dec69f27b39405ef43cb66435540..df38632c6237146ed7428bf4293fb7c2a53dfb27 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.h +++ b/drivers/gpu/drm/i915/display/intel_display_power.h @@ -6,6 +6,9 @@ #ifndef __INTEL_DISPLAY_POWER_H__ #define __INTEL_DISPLAY_POWER_H__ +#include +#include + #include "intel_wakeref.h" enum aux_ch; @@ -16,6 +19,7 @@ enum port; struct drm_i915_private; struct i915_power_well; struct intel_encoder; +struct seq_file; /* * Keep the pipe, transcoder, port (DDI_LANES,DDI_IO,AUX) domain instances diff --git a/drivers/gpu/drm/i915/display/intel_display_power_map.c b/drivers/gpu/drm/i915/display/intel_display_power_map.c index 1118ee9d224cabe25be352d0ce55410dd2b0086f..5ad04cd42c158e5e3aaf72201f5fd37c5d6d3373 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power_map.c +++ b/drivers/gpu/drm/i915/display/intel_display_power_map.c @@ -1252,10 +1252,18 @@ I915_DECL_PW_DOMAINS(xelpd_pwdoms_pw_a, POWER_DOMAIN_INIT); #define XELPD_DC_OFF_PORT_POWER_DOMAINS \ + POWER_DOMAIN_PORT_DDI_LANES_C, \ + POWER_DOMAIN_PORT_DDI_LANES_D, \ + POWER_DOMAIN_PORT_DDI_LANES_E, \ POWER_DOMAIN_PORT_DDI_LANES_TC1, \ POWER_DOMAIN_PORT_DDI_LANES_TC2, \ POWER_DOMAIN_PORT_DDI_LANES_TC3, \ POWER_DOMAIN_PORT_DDI_LANES_TC4, \ + POWER_DOMAIN_VGA, \ + POWER_DOMAIN_AUDIO_PLAYBACK, \ + POWER_DOMAIN_AUX_IO_C, \ + POWER_DOMAIN_AUX_IO_D, \ + POWER_DOMAIN_AUX_IO_E, \ POWER_DOMAIN_AUX_C, \ POWER_DOMAIN_AUX_D, \ POWER_DOMAIN_AUX_E, \ @@ -1272,14 +1280,6 @@ I915_DECL_PW_DOMAINS(xelpd_pwdoms_pw_a, XELPD_PW_B_POWER_DOMAINS, \ XELPD_PW_C_POWER_DOMAINS, \ XELPD_PW_D_POWER_DOMAINS, \ - POWER_DOMAIN_PORT_DDI_LANES_C, \ - POWER_DOMAIN_PORT_DDI_LANES_D, \ - POWER_DOMAIN_PORT_DDI_LANES_E, \ - POWER_DOMAIN_VGA, \ - POWER_DOMAIN_AUDIO_PLAYBACK, \ - POWER_DOMAIN_AUX_IO_C, \ - POWER_DOMAIN_AUX_IO_D, \ - POWER_DOMAIN_AUX_IO_E, \ XELPD_DC_OFF_PORT_POWER_DOMAINS I915_DECL_PW_DOMAINS(xelpd_pwdoms_pw_2, diff --git a/drivers/gpu/drm/i915/display/intel_display_power_well.h b/drivers/gpu/drm/i915/display/intel_display_power_well.h index e494df379e6c23fd52a29dd07a8994b357b74103..1015bba4af01e9f8149e5576db55e7ad7c778edf 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power_well.h +++ b/drivers/gpu/drm/i915/display/intel_display_power_well.h @@ -12,6 +12,8 @@ struct drm_i915_private; struct i915_power_well; +struct i915_power_well_ops; +struct intel_encoder; #define for_each_power_well(__dev_priv, __power_well) \ for ((__power_well) = (__dev_priv)->display.power.domains.power_wells; \ diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c b/drivers/gpu/drm/i915/display/intel_hdcp.c index 5ed450111f77c4387503351ed2c3a79f071937b0..34fabadefaf66991e50b2ddb507fd9cd62a497ce 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_hdcp.c @@ -2358,7 +2358,7 @@ int intel_hdcp_enable(struct intel_atomic_state *state, mutex_lock(&dig_port->hdcp_mutex); drm_WARN_ON(&i915->drm, hdcp->value == DRM_MODE_CONTENT_PROTECTION_ENABLED); - hdcp->content_type = (u8)conn_state->content_type; + hdcp->content_type = (u8)conn_state->hdcp_content_type; if (intel_crtc_has_type(pipe_config, INTEL_OUTPUT_DP_MST)) { hdcp->cpu_transcoder = pipe_config->mst_master_transcoder; diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c index d58ed9b62e6775df4b27ed9cfc433b01cceae11b..56c17283ba2d5bddd77989b99c62d3033b08dbc5 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.c +++ b/drivers/gpu/drm/i915/display/intel_psr.c @@ -933,9 +933,9 @@ static bool _compute_psr2_wake_times(struct intel_dp *intel_dp, } io_wake_lines = intel_usecs_to_scanlines( - &crtc_state->uapi.adjusted_mode, io_wake_time); + &crtc_state->hw.adjusted_mode, io_wake_time); fast_wake_lines = intel_usecs_to_scanlines( - &crtc_state->uapi.adjusted_mode, fast_wake_time); + &crtc_state->hw.adjusted_mode, fast_wake_time); if (io_wake_lines > max_wake_lines || fast_wake_lines > max_wake_lines) diff --git a/drivers/gpu/drm/i915/display/intel_psr_regs.h b/drivers/gpu/drm/i915/display/intel_psr_regs.h index 0f7db617425a357dc361ff3bbeac5cc5b63ff115..8750cb0d8d9dd0e74011c870219f81d6af35cd1f 100644 --- a/drivers/gpu/drm/i915/display/intel_psr_regs.h +++ b/drivers/gpu/drm/i915/display/intel_psr_regs.h @@ -81,7 +81,7 @@ #define _SRD_AUX_DATA_A 0x60814 #define _SRD_AUX_DATA_EDP 0x6f814 -#define EDP_PSR_AUX_DATA(tran, i) _MMIO_TRANS2(tran, _SRD_AUX_DATA_A + (i) + 4) /* 5 registers */ +#define EDP_PSR_AUX_DATA(tran, i) _MMIO_TRANS2(tran, _SRD_AUX_DATA_A + (i) * 4) /* 5 registers */ #define _SRD_STATUS_A 0x60840 #define _SRD_STATUS_EDP 0x6f840 diff --git a/drivers/gpu/drm/i915/gem/i915_gem_mman.c b/drivers/gpu/drm/i915/gem/i915_gem_mman.c index 4e7a838ab7bd9805f5612fd16006156f1c28ac20..aa4d842d4c5a8a4ceaf81dd07773f8b1582f943b 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_mman.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_mman.c @@ -1085,8 +1085,8 @@ int i915_gem_fb_mmap(struct drm_i915_gem_object *obj, struct vm_area_struct *vma /* handle stolen and smem objects */ mmap_type = i915_ggtt_has_aperture(ggtt) ? I915_MMAP_TYPE_GTT : I915_MMAP_TYPE_WC; mmo = mmap_offset_attach(obj, mmap_type, NULL); - if (!mmo) - return -ENODEV; + if (IS_ERR(mmo)) + return PTR_ERR(mmo); } /* diff --git a/drivers/gpu/drm/i915/gem/i915_gem_shmem.c b/drivers/gpu/drm/i915/gem/i915_gem_shmem.c index 33d5d5178103b78f8d6a6cd3287f65ef59480bf5..8f1633c3fb9352cc0678ff80329736187cef39b8 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_shmem.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_shmem.c @@ -19,13 +19,13 @@ #include "i915_trace.h" /* - * Move pages to appropriate lru and release the pagevec, decrementing the - * ref count of those pages. + * Move folios to appropriate lru and release the batch, decrementing the + * ref count of those folios. */ -static void check_release_pagevec(struct pagevec *pvec) +static void check_release_folio_batch(struct folio_batch *fbatch) { - check_move_unevictable_pages(pvec); - __pagevec_release(pvec); + check_move_unevictable_folios(fbatch); + __folio_batch_release(fbatch); cond_resched(); } @@ -33,24 +33,29 @@ void shmem_sg_free_table(struct sg_table *st, struct address_space *mapping, bool dirty, bool backup) { struct sgt_iter sgt_iter; - struct pagevec pvec; + struct folio_batch fbatch; + struct folio *last = NULL; struct page *page; mapping_clear_unevictable(mapping); - pagevec_init(&pvec); + folio_batch_init(&fbatch); for_each_sgt_page(page, sgt_iter, st) { - if (dirty) - set_page_dirty(page); + struct folio *folio = page_folio(page); + if (folio == last) + continue; + last = folio; + if (dirty) + folio_mark_dirty(folio); if (backup) - mark_page_accessed(page); + folio_mark_accessed(folio); - if (!pagevec_add(&pvec, page)) - check_release_pagevec(&pvec); + if (!folio_batch_add(&fbatch, folio)) + check_release_folio_batch(&fbatch); } - if (pagevec_count(&pvec)) - check_release_pagevec(&pvec); + if (fbatch.nr) + check_release_folio_batch(&fbatch); sg_free_table(st); } @@ -63,8 +68,7 @@ int shmem_sg_alloc_table(struct drm_i915_private *i915, struct sg_table *st, unsigned int page_count; /* restricted by sg_alloc_table */ unsigned long i; struct scatterlist *sg; - struct page *page; - unsigned long last_pfn = 0; /* suppress gcc warning */ + unsigned long next_pfn = 0; /* suppress gcc warning */ gfp_t noreclaim; int ret; @@ -95,6 +99,7 @@ int shmem_sg_alloc_table(struct drm_i915_private *i915, struct sg_table *st, sg = st->sgl; st->nents = 0; for (i = 0; i < page_count; i++) { + struct folio *folio; const unsigned int shrink[] = { I915_SHRINK_BOUND | I915_SHRINK_UNBOUND, 0, @@ -103,12 +108,12 @@ int shmem_sg_alloc_table(struct drm_i915_private *i915, struct sg_table *st, do { cond_resched(); - page = shmem_read_mapping_page_gfp(mapping, i, gfp); - if (!IS_ERR(page)) + folio = shmem_read_folio_gfp(mapping, i, gfp); + if (!IS_ERR(folio)) break; if (!*s) { - ret = PTR_ERR(page); + ret = PTR_ERR(folio); goto err_sg; } @@ -147,19 +152,21 @@ int shmem_sg_alloc_table(struct drm_i915_private *i915, struct sg_table *st, if (!i || sg->length >= max_segment || - page_to_pfn(page) != last_pfn + 1) { + folio_pfn(folio) != next_pfn) { if (i) sg = sg_next(sg); st->nents++; - sg_set_page(sg, page, PAGE_SIZE, 0); + sg_set_folio(sg, folio, folio_size(folio), 0); } else { - sg->length += PAGE_SIZE; + /* XXX: could overflow? */ + sg->length += folio_size(folio); } - last_pfn = page_to_pfn(page); + next_pfn = folio_pfn(folio) + folio_nr_pages(folio); + i += folio_nr_pages(folio) - 1; /* Check that the i965g/gm workaround works. */ - GEM_BUG_ON(gfp & __GFP_DMA32 && last_pfn >= 0x00100000UL); + GEM_BUG_ON(gfp & __GFP_DMA32 && next_pfn >= 0x00100000UL); } if (sg) /* loop terminated early; short sg table */ sg_mark_end(sg); diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c index a93d8f9f8bc14e613eebef8f705694aa1042b106..72957a36a36be3e4f893c77648e66a051db264a9 100644 --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c @@ -1681,7 +1681,9 @@ static int igt_mmap_gpu(void *arg) static int check_present_pte(pte_t *pte, unsigned long addr, void *data) { - if (!pte_present(*pte) || pte_none(*pte)) { + pte_t ptent = ptep_get(pte); + + if (!pte_present(ptent) || pte_none(ptent)) { pr_err("missing PTE:%lx\n", (addr - (unsigned long)data) >> PAGE_SHIFT); return -EINVAL; @@ -1692,7 +1694,9 @@ static int check_present_pte(pte_t *pte, unsigned long addr, void *data) static int check_absent_pte(pte_t *pte, unsigned long addr, void *data) { - if (pte_present(*pte) && !pte_none(*pte)) { + pte_t ptent = ptep_get(pte); + + if (pte_present(ptent) && !pte_none(ptent)) { pr_err("present PTE:%lx; expected to be revoked\n", (addr - (unsigned long)data) >> PAGE_SHIFT); return -EINVAL; diff --git a/drivers/gpu/drm/i915/gt/gen8_ppgtt.c b/drivers/gpu/drm/i915/gt/gen8_ppgtt.c index f948d33e5ec5aa81bb027d36b4bfdd749ca3c5aa..c8568e5d11479dcd09609cba6c91c748349a90c4 100644 --- a/drivers/gpu/drm/i915/gt/gen8_ppgtt.c +++ b/drivers/gpu/drm/i915/gt/gen8_ppgtt.c @@ -37,9 +37,6 @@ static u64 gen8_pte_encode(dma_addr_t addr, if (unlikely(flags & PTE_READ_ONLY)) pte &= ~GEN8_PAGE_RW; - if (flags & PTE_LM) - pte |= GEN12_PPGTT_PTE_LM; - /* * For pre-gen12 platforms pat_index is the same as enum * i915_cache_level, so the switch-case here is still valid. diff --git a/drivers/gpu/drm/i915/gt/intel_gtt.c b/drivers/gpu/drm/i915/gt/intel_gtt.c index 2f6a9be0ffe61a8ecfdf4d0d0bb42cbbd9d5bb22..731d9f2bbc5643c3dd1ebbd6695496453f8525f7 100644 --- a/drivers/gpu/drm/i915/gt/intel_gtt.c +++ b/drivers/gpu/drm/i915/gt/intel_gtt.c @@ -670,7 +670,7 @@ __vm_create_scratch_for_read(struct i915_address_space *vm, unsigned long size) if (IS_ERR(obj)) return ERR_CAST(obj); - i915_gem_object_set_cache_coherency(obj, I915_CACHING_CACHED); + i915_gem_object_set_cache_coherency(obj, I915_CACHE_LLC); vma = i915_vma_instance(obj, vm, NULL); if (IS_ERR(vma)) { diff --git a/drivers/gpu/drm/i915/gt/uc/intel_gsc_fw.c b/drivers/gpu/drm/i915/gt/uc/intel_gsc_fw.c index f46eb17a7a98700842985022446d26f57bee1b5a..60e9c6c9e7756a22021a4e11eeb97630f75b00e6 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_gsc_fw.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_gsc_fw.c @@ -24,21 +24,27 @@ static bool gsc_is_in_reset(struct intel_uncore *uncore) GSC_FW_CURRENT_STATE_RESET; } -bool intel_gsc_uc_fw_proxy_init_done(struct intel_gsc_uc *gsc) +static u32 gsc_uc_get_fw_status(struct intel_uncore *uncore) { - struct intel_uncore *uncore = gsc_uc_to_gt(gsc)->uncore; - u32 fw_status = intel_uncore_read(uncore, GSC_FW_STATUS_REG); + intel_wakeref_t wakeref; + u32 fw_status = 0; - return REG_FIELD_GET(GSC_FW_CURRENT_STATE, fw_status) == + with_intel_runtime_pm(uncore->rpm, wakeref) + fw_status = intel_uncore_read(uncore, GSC_FW_STATUS_REG); + + return fw_status; +} + +bool intel_gsc_uc_fw_proxy_init_done(struct intel_gsc_uc *gsc) +{ + return REG_FIELD_GET(GSC_FW_CURRENT_STATE, + gsc_uc_get_fw_status(gsc_uc_to_gt(gsc)->uncore)) == GSC_FW_PROXY_STATE_NORMAL; } bool intel_gsc_uc_fw_init_done(struct intel_gsc_uc *gsc) { - struct intel_uncore *uncore = gsc_uc_to_gt(gsc)->uncore; - u32 fw_status = intel_uncore_read(uncore, GSC_FW_STATUS_REG); - - return fw_status & GSC_FW_INIT_COMPLETE_BIT; + return gsc_uc_get_fw_status(gsc_uc_to_gt(gsc)->uncore) & GSC_FW_INIT_COMPLETE_BIT; } static int emit_gsc_fw_load(struct i915_request *rq, struct intel_gsc_uc *gsc) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c index 01b75529311c8503d2be0bf0af92642ab612e96e..ee9f83af7cf68863fb1369367c853b5b832a43c5 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c @@ -606,7 +606,7 @@ static int slpc_set_softlimits(struct intel_guc_slpc *slpc) if (unlikely(ret)) return ret; slpc_to_gt(slpc)->defaults.min_freq = slpc->min_freq_softlimit; - } else if (slpc->min_freq_softlimit != slpc->min_freq) { + } else { return intel_guc_slpc_set_min_freq(slpc, slpc->min_freq_softlimit); } diff --git a/drivers/gpu/drm/i915/gt/uc/intel_huc.c b/drivers/gpu/drm/i915/gt/uc/intel_huc.c index e0afd8f895026cc3dae26e3e1230d234fc1cac60..ddd146265beb42b399b2c9b49f459fbebddc9ee8 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_huc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_huc.c @@ -384,6 +384,7 @@ int intel_huc_init(struct intel_huc *huc) vma = intel_guc_allocate_vma(>->uc.guc, PXP43_HUC_AUTH_INOUT_SIZE * 2); if (IS_ERR(vma)) { + err = PTR_ERR(vma); huc_info(huc, "Failed to allocate heci pkt\n"); goto out; } diff --git a/drivers/gpu/drm/i915/i915_driver.c b/drivers/gpu/drm/i915/i915_driver.c index 171f4db9e5e31be638830d5a5c2a30b7525d48c9..222d0a1f3b5588f848b0358f3ff0cb2e3566fc26 100644 --- a/drivers/gpu/drm/i915/i915_driver.c +++ b/drivers/gpu/drm/i915/i915_driver.c @@ -1816,7 +1816,7 @@ static const struct drm_driver i915_drm_driver = { .open = i915_driver_open, .lastclose = i915_driver_lastclose, .postclose = i915_driver_postclose, - .show_fdinfo = i915_drm_client_fdinfo, + .show_fdinfo = PTR_IF(IS_ENABLED(CONFIG_PROC_FS), i915_drm_client_fdinfo), .gem_prime_import = i915_gem_prime_import, diff --git a/drivers/gpu/drm/i915/i915_drm_client.h b/drivers/gpu/drm/i915/i915_drm_client.h index 4c18b99e10a4e2ea947731310cce55d838da9204..67816c912bca1377a65049bfeb3892688b46a8d1 100644 --- a/drivers/gpu/drm/i915/i915_drm_client.h +++ b/drivers/gpu/drm/i915/i915_drm_client.h @@ -47,8 +47,6 @@ static inline void i915_drm_client_put(struct i915_drm_client *client) struct i915_drm_client *i915_drm_client_alloc(void); -#ifdef CONFIG_PROC_FS void i915_drm_client_fdinfo(struct drm_printer *p, struct drm_file *file); -#endif #endif /* !__I915_DRM_CLIENT_H__ */ diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index ec368e700235453d709c3eb229704a3ad5e248bb..0c38bfb60c9a86e275f4c7eeccfe5ad6b1a18328 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -187,64 +187,64 @@ i915_error_printer(struct drm_i915_error_state_buf *e) } /* single threaded page allocator with a reserved stash for emergencies */ -static void pool_fini(struct pagevec *pv) +static void pool_fini(struct folio_batch *fbatch) { - pagevec_release(pv); + folio_batch_release(fbatch); } -static int pool_refill(struct pagevec *pv, gfp_t gfp) +static int pool_refill(struct folio_batch *fbatch, gfp_t gfp) { - while (pagevec_space(pv)) { - struct page *p; + while (folio_batch_space(fbatch)) { + struct folio *folio; - p = alloc_page(gfp); - if (!p) + folio = folio_alloc(gfp, 0); + if (!folio) return -ENOMEM; - pagevec_add(pv, p); + folio_batch_add(fbatch, folio); } return 0; } -static int pool_init(struct pagevec *pv, gfp_t gfp) +static int pool_init(struct folio_batch *fbatch, gfp_t gfp) { int err; - pagevec_init(pv); + folio_batch_init(fbatch); - err = pool_refill(pv, gfp); + err = pool_refill(fbatch, gfp); if (err) - pool_fini(pv); + pool_fini(fbatch); return err; } -static void *pool_alloc(struct pagevec *pv, gfp_t gfp) +static void *pool_alloc(struct folio_batch *fbatch, gfp_t gfp) { - struct page *p; + struct folio *folio; - p = alloc_page(gfp); - if (!p && pagevec_count(pv)) - p = pv->pages[--pv->nr]; + folio = folio_alloc(gfp, 0); + if (!folio && folio_batch_count(fbatch)) + folio = fbatch->folios[--fbatch->nr]; - return p ? page_address(p) : NULL; + return folio ? folio_address(folio) : NULL; } -static void pool_free(struct pagevec *pv, void *addr) +static void pool_free(struct folio_batch *fbatch, void *addr) { - struct page *p = virt_to_page(addr); + struct folio *folio = virt_to_folio(addr); - if (pagevec_space(pv)) - pagevec_add(pv, p); + if (folio_batch_space(fbatch)) + folio_batch_add(fbatch, folio); else - __free_page(p); + folio_put(folio); } #ifdef CONFIG_DRM_I915_COMPRESS_ERROR struct i915_vma_compress { - struct pagevec pool; + struct folio_batch pool; struct z_stream_s zstream; void *tmp; }; @@ -381,7 +381,7 @@ static void err_compression_marker(struct drm_i915_error_state_buf *m) #else struct i915_vma_compress { - struct pagevec pool; + struct folio_batch pool; }; static bool compress_init(struct i915_vma_compress *c) diff --git a/drivers/gpu/drm/i915/i915_perf.c b/drivers/gpu/drm/i915/i915_perf.c index 0a111b281578ba0fc95b7902923e44ed2ae894bf..7413c11fb562e9f37215e9ea6a10ee3155c4a496 100644 --- a/drivers/gpu/drm/i915/i915_perf.c +++ b/drivers/gpu/drm/i915/i915_perf.c @@ -868,8 +868,17 @@ static int gen8_append_oa_reports(struct i915_perf_stream *stream, oa_report_id_clear(stream, report32); oa_timestamp_clear(stream, report32); } else { + u8 *oa_buf_end = stream->oa_buffer.vaddr + + OA_BUFFER_SIZE; + u32 part = oa_buf_end - (u8 *)report32; + /* Zero out the entire report */ - memset(report32, 0, report_size); + if (report_size <= part) { + memset(report32, 0, report_size); + } else { + memset(report32, 0, part); + memset(oa_buf_base, 0, report_size - part); + } } } diff --git a/drivers/gpu/drm/i915/selftests/mock_gem_device.c b/drivers/gpu/drm/i915/selftests/mock_gem_device.c index 09d4bbcdcdbfec57695bd40dc9637de67d143228..4de6a4e8280d59539f535e76c53e9ba7fd8e3bca 100644 --- a/drivers/gpu/drm/i915/selftests/mock_gem_device.c +++ b/drivers/gpu/drm/i915/selftests/mock_gem_device.c @@ -118,15 +118,31 @@ static void mock_gt_probe(struct drm_i915_private *i915) i915->gt[0]->name = "Mock GT"; } +static const struct intel_device_info mock_info = { + .__runtime.graphics.ip.ver = -1, + .__runtime.page_sizes = (I915_GTT_PAGE_SIZE_4K | + I915_GTT_PAGE_SIZE_64K | + I915_GTT_PAGE_SIZE_2M), + .__runtime.memory_regions = REGION_SMEM, + .__runtime.platform_engine_mask = BIT(0), + + /* simply use legacy cache level for mock device */ + .max_pat_index = 3, + .cachelevel_to_pat = { + [I915_CACHE_NONE] = 0, + [I915_CACHE_LLC] = 1, + [I915_CACHE_L3_LLC] = 2, + [I915_CACHE_WT] = 3, + }, +}; + struct drm_i915_private *mock_gem_device(void) { #if IS_ENABLED(CONFIG_IOMMU_API) && defined(CONFIG_INTEL_IOMMU) static struct dev_iommu fake_iommu = { .priv = (void *)-1 }; #endif struct drm_i915_private *i915; - struct intel_device_info *i915_info; struct pci_dev *pdev; - unsigned int i; int ret; pdev = kzalloc(sizeof(*pdev), GFP_KERNEL); @@ -159,15 +175,18 @@ struct drm_i915_private *mock_gem_device(void) pci_set_drvdata(pdev, i915); + /* Device parameters start as a copy of module parameters. */ + i915_params_copy(&i915->params, &i915_modparams); + + /* Set up device info and initial runtime info. */ + intel_device_info_driver_create(i915, pdev->device, &mock_info); + dev_pm_domain_set(&pdev->dev, &pm_domain); pm_runtime_enable(&pdev->dev); pm_runtime_dont_use_autosuspend(&pdev->dev); if (pm_runtime_enabled(&pdev->dev)) WARN_ON(pm_runtime_get_sync(&pdev->dev)); - - i915_params_copy(&i915->params, &i915_modparams); - intel_runtime_pm_init_early(&i915->runtime_pm); /* wakeref tracking has significant overhead */ i915->runtime_pm.no_wakeref_tracking = true; @@ -175,21 +194,6 @@ struct drm_i915_private *mock_gem_device(void) /* Using the global GTT may ask questions about KMS users, so prepare */ drm_mode_config_init(&i915->drm); - RUNTIME_INFO(i915)->graphics.ip.ver = -1; - - RUNTIME_INFO(i915)->page_sizes = - I915_GTT_PAGE_SIZE_4K | - I915_GTT_PAGE_SIZE_64K | - I915_GTT_PAGE_SIZE_2M; - - RUNTIME_INFO(i915)->memory_regions = REGION_SMEM; - - /* simply use legacy cache level for mock device */ - i915_info = (struct intel_device_info *)INTEL_INFO(i915); - i915_info->max_pat_index = 3; - for (i = 0; i < I915_MAX_CACHE_LEVEL; i++) - i915_info->cachelevel_to_pat[i] = i; - intel_memory_regions_hw_probe(i915); spin_lock_init(&i915->gpu_error.lock); @@ -223,7 +227,6 @@ struct drm_i915_private *mock_gem_device(void) mock_init_ggtt(to_gt(i915)); to_gt(i915)->vm = i915_vm_get(&to_gt(i915)->ggtt->vm); - RUNTIME_INFO(i915)->platform_engine_mask = BIT(0); to_gt(i915)->info.engine_mask = BIT(0); to_gt(i915)->engine[RCS0] = mock_engine(i915, "mock", RCS0); diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi_ddc.c b/drivers/gpu/drm/mediatek/mtk_hdmi_ddc.c index 2fc9214ffa82b10fffc2762de017f7babc0165c4..4d39ea0a05ca4844cbfcd765ed4c1ca89af48126 100644 --- a/drivers/gpu/drm/mediatek/mtk_hdmi_ddc.c +++ b/drivers/gpu/drm/mediatek/mtk_hdmi_ddc.c @@ -295,7 +295,7 @@ static int mtk_hdmi_ddc_probe(struct platform_device *pdev) return ret; } - strlcpy(ddc->adap.name, "mediatek-hdmi-ddc", sizeof(ddc->adap.name)); + strscpy(ddc->adap.name, "mediatek-hdmi-ddc", sizeof(ddc->adap.name)); ddc->adap.owner = THIS_MODULE; ddc->adap.class = I2C_CLASS_DDC; ddc->adap.algo = &mtk_hdmi_ddc_algorithm; diff --git a/drivers/gpu/drm/msm/msm_fbdev.c b/drivers/gpu/drm/msm/msm_fbdev.c index b933a85420f6d54237e6fb9e18b6cb62d4b45f54..bf1e17dc4550ce03ac4eea69a47731fa34b0e051 100644 --- a/drivers/gpu/drm/msm/msm_fbdev.c +++ b/drivers/gpu/drm/msm/msm_fbdev.c @@ -246,10 +246,6 @@ void msm_fbdev_setup(struct drm_device *dev) goto err_drm_fb_helper_unprepare; } - ret = msm_fbdev_client_hotplug(&helper->client); - if (ret) - drm_dbg_kms(dev, "client hotplug ret=%d\n", ret); - drm_client_register(&helper->client); return; diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c index 33066b3ab7f19315e7edaa92fb010144c492fa39..d18e24b6f1eba9ab9bcc614e2ecc49698adac555 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c @@ -910,15 +910,19 @@ nv50_msto_prepare(struct drm_atomic_state *state, struct nouveau_drm *drm = nouveau_drm(msto->encoder.dev); struct nv50_mstc *mstc = msto->mstc; struct nv50_mstm *mstm = mstc->mstm; - struct drm_dp_mst_atomic_payload *payload; + struct drm_dp_mst_topology_state *old_mst_state; + struct drm_dp_mst_atomic_payload *payload, *old_payload; NV_ATOMIC(drm, "%s: msto prepare\n", msto->encoder.name); + old_mst_state = drm_atomic_get_old_mst_topology_state(state, mgr); + payload = drm_atomic_get_mst_payload_state(mst_state, mstc->port); + old_payload = drm_atomic_get_mst_payload_state(old_mst_state, mstc->port); // TODO: Figure out if we want to do a better job of handling VCPI allocation failures here? if (msto->disabled) { - drm_dp_remove_payload(mgr, mst_state, payload, payload); + drm_dp_remove_payload(mgr, mst_state, old_payload, payload); nvif_outp_dp_mst_vcpi(&mstm->outp->outp, msto->head->base.index, 0, 0, 0, 0); } else { diff --git a/drivers/gpu/drm/nouveau/nouveau_chan.c b/drivers/gpu/drm/nouveau/nouveau_chan.c index e648ecd0c1a03fb9ed614f2ce1f30f90c21b3dea..3dfbc374478e6ac88a053aa9e53add5855f62504 100644 --- a/drivers/gpu/drm/nouveau/nouveau_chan.c +++ b/drivers/gpu/drm/nouveau/nouveau_chan.c @@ -90,6 +90,7 @@ nouveau_channel_del(struct nouveau_channel **pchan) if (cli) nouveau_svmm_part(chan->vmm->svmm, chan->inst); + nvif_object_dtor(&chan->blit); nvif_object_dtor(&chan->nvsw); nvif_object_dtor(&chan->gart); nvif_object_dtor(&chan->vram); diff --git a/drivers/gpu/drm/nouveau/nouveau_chan.h b/drivers/gpu/drm/nouveau/nouveau_chan.h index e06a8ffed31a8bc10e084d61dfc05b1ec90e0ba4..bad7466bd0d596044df5a84feca05911df47b251 100644 --- a/drivers/gpu/drm/nouveau/nouveau_chan.h +++ b/drivers/gpu/drm/nouveau/nouveau_chan.h @@ -53,6 +53,7 @@ struct nouveau_channel { u32 user_put; struct nvif_object user; + struct nvif_object blit; struct nvif_event kill; atomic_t killed; diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index ca3bb8075357ba975a39ae4784407d0ab2e482e6..8325fcf35c5e6ae7a7db0cda541d62168e281be1 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c @@ -375,15 +375,29 @@ nouveau_accel_gr_init(struct nouveau_drm *drm) ret = nvif_object_ctor(&drm->channel->user, "drmNvsw", NVDRM_NVSW, nouveau_abi16_swclass(drm), NULL, 0, &drm->channel->nvsw); + + if (ret == 0 && device->info.chipset >= 0x11) { + ret = nvif_object_ctor(&drm->channel->user, "drmBlit", + 0x005f, 0x009f, + NULL, 0, &drm->channel->blit); + } + if (ret == 0) { struct nvif_push *push = drm->channel->chan.push; - ret = PUSH_WAIT(push, 2); - if (ret == 0) + ret = PUSH_WAIT(push, 8); + if (ret == 0) { + if (device->info.chipset >= 0x11) { + PUSH_NVSQ(push, NV05F, 0x0000, drm->channel->blit.handle); + PUSH_NVSQ(push, NV09F, 0x0120, 0, + 0x0124, 1, + 0x0128, 2); + } PUSH_NVSQ(push, NV_SW, 0x0000, drm->channel->nvsw.handle); + } } if (ret) { - NV_ERROR(drm, "failed to allocate sw class, %d\n", ret); + NV_ERROR(drm, "failed to allocate sw or blit class, %d\n", ret); nouveau_accel_gr_fini(drm); return; } diff --git a/drivers/gpu/drm/nouveau/nouveau_ttm.c b/drivers/gpu/drm/nouveau/nouveau_ttm.c index 1469a88910e45d7d401c3447e8b5149c2932c304..486f39f31a38df3a6b078a2959945944c028ff69 100644 --- a/drivers/gpu/drm/nouveau/nouveau_ttm.c +++ b/drivers/gpu/drm/nouveau/nouveau_ttm.c @@ -24,9 +24,9 @@ */ #include -#include #include +#include #include "nouveau_drv.h" #include "nouveau_gem.h" @@ -265,7 +265,6 @@ nouveau_ttm_init(struct nouveau_drm *drm) struct nvkm_pci *pci = device->pci; struct nvif_mmu *mmu = &drm->client.mmu; struct drm_device *dev = drm->dev; - bool need_swiotlb = false; int typei, ret; ret = nouveau_ttm_init_host(drm, 0); @@ -300,13 +299,10 @@ nouveau_ttm_init(struct nouveau_drm *drm) drm->agp.cma = pci->agp.cma; } -#if IS_ENABLED(CONFIG_SWIOTLB) && IS_ENABLED(CONFIG_X86) - need_swiotlb = is_swiotlb_active(dev->dev); -#endif - ret = ttm_device_init(&drm->ttm.bdev, &nouveau_bo_driver, drm->dev->dev, dev->anon_inode->i_mapping, - dev->vma_offset_manager, need_swiotlb, + dev->vma_offset_manager, + drm_need_swiotlb(drm->client.mmu.dmabits), drm->client.mmu.dmabits <= 32); if (ret) { NV_ERROR(drm, "error initialising bo driver, %d\n", ret); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/g94.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/g94.c index a4853c4e5ee3a8257564ac818f258e035617b88c..67ef889a0c5f4728d62d80be74357b13881acebc 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/g94.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/g94.c @@ -295,6 +295,7 @@ g94_sor = { .clock = nv50_sor_clock, .war_2 = g94_sor_war_2, .war_3 = g94_sor_war_3, + .hdmi = &g84_sor_hdmi, .dp = &g94_sor_dp, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gt215.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gt215.c index a2c7c6f83dcdbda80b5474482974cb51721403b7..506ffbe7b84216fd7045a759e68648c9c8c6f3a5 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gt215.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gt215.c @@ -125,7 +125,7 @@ gt215_sor_hdmi_infoframe_avi(struct nvkm_ior *ior, int head, void *data, u32 siz pack_hdmi_infoframe(&avi, data, size); nvkm_mask(device, 0x61c520 + soff, 0x00000001, 0x00000000); - if (size) + if (!size) return; nvkm_wr32(device, 0x61c528 + soff, avi.header); diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c index 795f3a649b122172013a50f879419d6dcdf6d1a5..9b8ca4e898f903661eb588843698ca11e0d7c200 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c @@ -224,7 +224,7 @@ nvkm_acr_oneinit(struct nvkm_subdev *subdev) u64 falcons; int ret, i; - if (list_empty(&acr->hsfw)) { + if (list_empty(&acr->hsfw) || !acr->func || !acr->func->wpr_layout) { nvkm_debug(subdev, "No HSFW(s)\n"); nvkm_acr_cleanup(acr); return 0; diff --git a/drivers/gpu/drm/omapdrm/omap_fbdev.c b/drivers/gpu/drm/omapdrm/omap_fbdev.c index b7ccce0704a39de45e17983a9dc5056efc080e09..fe6639c1cdf34888ed9d9e65e404cd72e6ac9cc7 100644 --- a/drivers/gpu/drm/omapdrm/omap_fbdev.c +++ b/drivers/gpu/drm/omapdrm/omap_fbdev.c @@ -318,10 +318,6 @@ void omap_fbdev_setup(struct drm_device *dev) INIT_WORK(&fbdev->work, pan_worker); - ret = omap_fbdev_client_hotplug(&helper->client); - if (ret) - drm_dbg_kms(dev, "client hotplug ret=%d\n", ret); - drm_client_register(&helper->client); return; diff --git a/drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c b/drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c index e60e3488773d0548730fab910ce1a2650702d3ae..5ac926281d2c65e1c6e7b652a29570940a33f017 100644 --- a/drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c +++ b/drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c @@ -2138,9 +2138,9 @@ static const struct panel_desc starry_himax83102_j02_desc = { static const struct drm_display_mode starry_ili9882t_default_mode = { .clock = 165280, .hdisplay = 1200, - .hsync_start = 1200 + 32, - .hsync_end = 1200 + 32 + 30, - .htotal = 1200 + 32 + 30 + 32, + .hsync_start = 1200 + 72, + .hsync_end = 1200 + 72 + 30, + .htotal = 1200 + 72 + 30 + 72, .vdisplay = 1920, .vsync_start = 1920 + 68, .vsync_end = 1920 + 68 + 2, diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c index 77cfc606df48e74696de73a506fa52b859aa1b99..4badda6570d5d868da8b5427aeddef38792bcf3c 100644 --- a/drivers/gpu/drm/panel/panel-simple.c +++ b/drivers/gpu/drm/panel/panel-simple.c @@ -2174,6 +2174,7 @@ static const struct panel_desc innolux_at043tn24 = { .height = 54, }, .bus_format = MEDIA_BUS_FMT_RGB888_1X24, + .connector_type = DRM_MODE_CONNECTOR_DPI, .bus_flags = DRM_BUS_FLAG_DE_HIGH | DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE, }; @@ -3198,6 +3199,7 @@ static const struct drm_display_mode powertip_ph800480t013_idf02_mode = { .vsync_start = 480 + 49, .vsync_end = 480 + 49 + 2, .vtotal = 480 + 49 + 2 + 22, + .flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC, }; static const struct panel_desc powertip_ph800480t013_idf02 = { diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index 4ad5a328d9202d99b8dec4ca0f60065218faa3aa..bf3c411a55c5d3aac8f9c9ee9c78b4971fd08f89 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -2105,7 +2105,7 @@ static int radeon_atombios_parse_power_table_1_3(struct radeon_device *rdev) const char *name = thermal_controller_names[power_info->info. ucOverdriveThermalController]; info.addr = power_info->info.ucOverdriveControllerAddress >> 1; - strlcpy(info.type, name, sizeof(info.type)); + strscpy(info.type, name, sizeof(info.type)); i2c_new_client_device(&rdev->pm.i2c_bus->adapter, &info); } } @@ -2355,7 +2355,7 @@ static void radeon_atombios_add_pplib_thermal_controller(struct radeon_device *r struct i2c_board_info info = { }; const char *name = pp_lib_thermal_controller_names[controller->ucType]; info.addr = controller->ucI2cAddress >> 1; - strlcpy(info.type, name, sizeof(info.type)); + strscpy(info.type, name, sizeof(info.type)); i2c_new_client_device(&rdev->pm.i2c_bus->adapter, &info); } } else { diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c index 783a6b8802d5d8f049e83287570b540e7ac635f8..795c3667f6d60a6b4759e8f5d9fd1eb4ab6a69dc 100644 --- a/drivers/gpu/drm/radeon/radeon_combios.c +++ b/drivers/gpu/drm/radeon/radeon_combios.c @@ -2702,7 +2702,7 @@ void radeon_combios_get_power_modes(struct radeon_device *rdev) struct i2c_board_info info = { }; const char *name = thermal_controller_names[thermal_controller]; info.addr = i2c_addr >> 1; - strlcpy(info.type, name, sizeof(info.type)); + strscpy(info.type, name, sizeof(info.type)); i2c_new_client_device(&rdev->pm.i2c_bus->adapter, &info); } } @@ -2719,7 +2719,7 @@ void radeon_combios_get_power_modes(struct radeon_device *rdev) struct i2c_board_info info = { }; const char *name = "f75375"; info.addr = 0x28; - strlcpy(info.type, name, sizeof(info.type)); + strscpy(info.type, name, sizeof(info.type)); i2c_new_client_device(&rdev->pm.i2c_bus->adapter, &info); DRM_INFO("Possible %s thermal controller at 0x%02x\n", name, info.addr); diff --git a/drivers/gpu/drm/radeon/radeon_fbdev.c b/drivers/gpu/drm/radeon/radeon_fbdev.c index ab9c1abbac979e50934f8a28c8341877aaf19e28..f941e2e7cae64a65c80b2fd06a7e3ec8244d3e49 100644 --- a/drivers/gpu/drm/radeon/radeon_fbdev.c +++ b/drivers/gpu/drm/radeon/radeon_fbdev.c @@ -383,10 +383,6 @@ void radeon_fbdev_setup(struct radeon_device *rdev) goto err_drm_client_init; } - ret = radeon_fbdev_client_hotplug(&fb_helper->client); - if (ret) - drm_dbg_kms(rdev->ddev, "client hotplug ret=%d\n", ret); - drm_client_register(&fb_helper->client); return; diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index 10794be3023903abf89426355f92b165c1659ed3..4eb83ccc4906ad4574c09f2ed37ea020b7c6ab52 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c @@ -358,7 +358,7 @@ static int radeon_ttm_tt_pin_userptr(struct ttm_device *bdev, struct ttm_tt *ttm struct page **pages = ttm->pages + pinned; r = get_user_pages(userptr, num_pages, write ? FOLL_WRITE : 0, - pages, NULL); + pages); if (r < 0) goto release_pages; diff --git a/drivers/gpu/drm/rockchip/inno_hdmi.c b/drivers/gpu/drm/rockchip/inno_hdmi.c index fc3c878be1f3017dc88d59af49cacf8fee8d4b7b..6e5b922a121e243c733d7e88032f33d095354f15 100644 --- a/drivers/gpu/drm/rockchip/inno_hdmi.c +++ b/drivers/gpu/drm/rockchip/inno_hdmi.c @@ -798,7 +798,7 @@ static struct i2c_adapter *inno_hdmi_i2c_adapter(struct inno_hdmi *hdmi) adap->dev.parent = hdmi->dev; adap->dev.of_node = hdmi->dev->of_node; adap->algo = &inno_hdmi_algorithm; - strlcpy(adap->name, "Inno HDMI", sizeof(adap->name)); + strscpy(adap->name, "Inno HDMI", sizeof(adap->name)); i2c_set_adapdata(adap, hdmi); ret = i2c_add_adapter(adap); diff --git a/drivers/gpu/drm/rockchip/rk3066_hdmi.c b/drivers/gpu/drm/rockchip/rk3066_hdmi.c index 5e6ac27ea15562fbbd086c137218a4c5b7432e54..fa6e592e0276c3458bf815d9d4e27a100a6b65c8 100644 --- a/drivers/gpu/drm/rockchip/rk3066_hdmi.c +++ b/drivers/gpu/drm/rockchip/rk3066_hdmi.c @@ -730,7 +730,7 @@ static struct i2c_adapter *rk3066_hdmi_i2c_adapter(struct rk3066_hdmi *hdmi) adap->dev.parent = hdmi->dev; adap->dev.of_node = hdmi->dev->of_node; adap->algo = &rk3066_hdmi_algorithm; - strlcpy(adap->name, "RK3066 HDMI", sizeof(adap->name)); + strscpy(adap->name, "RK3066 HDMI", sizeof(adap->name)); i2c_set_adapdata(adap, hdmi); ret = i2c_add_adapter(adap); diff --git a/drivers/gpu/drm/scheduler/sched_entity.c b/drivers/gpu/drm/scheduler/sched_entity.c index b2bbc8a68b30562d14b53cf8fc2e5bcf3bb3c75d..a42763e1429dc16ea653e62023174348e0002b5a 100644 --- a/drivers/gpu/drm/scheduler/sched_entity.c +++ b/drivers/gpu/drm/scheduler/sched_entity.c @@ -176,16 +176,32 @@ static void drm_sched_entity_kill_jobs_cb(struct dma_fence *f, { struct drm_sched_job *job = container_of(cb, struct drm_sched_job, finish_cb); - int r; + unsigned long index; dma_fence_put(f); /* Wait for all dependencies to avoid data corruptions */ - while (!xa_empty(&job->dependencies)) { - f = xa_erase(&job->dependencies, job->last_dependency++); - r = dma_fence_add_callback(f, &job->finish_cb, - drm_sched_entity_kill_jobs_cb); - if (!r) + xa_for_each(&job->dependencies, index, f) { + struct drm_sched_fence *s_fence = to_drm_sched_fence(f); + + if (s_fence && f == &s_fence->scheduled) { + /* The dependencies array had a reference on the scheduled + * fence, and the finished fence refcount might have + * dropped to zero. Use dma_fence_get_rcu() so we get + * a NULL fence in that case. + */ + f = dma_fence_get_rcu(&s_fence->finished); + + /* Now that we have a reference on the finished fence, + * we can release the reference the dependencies array + * had on the scheduled fence. + */ + dma_fence_put(&s_fence->scheduled); + } + + xa_erase(&job->dependencies, index); + if (f && !dma_fence_add_callback(f, &job->finish_cb, + drm_sched_entity_kill_jobs_cb)) return; dma_fence_put(f); @@ -415,8 +431,17 @@ static struct dma_fence * drm_sched_job_dependency(struct drm_sched_job *job, struct drm_sched_entity *entity) { - if (!xa_empty(&job->dependencies)) - return xa_erase(&job->dependencies, job->last_dependency++); + struct dma_fence *f; + + /* We keep the fence around, so we can iterate over all dependencies + * in drm_sched_entity_kill_jobs_cb() to ensure all deps are signaled + * before killing the job. + */ + f = xa_load(&job->dependencies, job->last_dependency); + if (f) { + job->last_dependency++; + return dma_fence_get(f); + } if (job->sched->ops->prepare_job) return job->sched->ops->prepare_job(job, entity); diff --git a/drivers/gpu/drm/scheduler/sched_fence.c b/drivers/gpu/drm/scheduler/sched_fence.c index ef120475e7c618c0a7de2266e2f5bb0d940f179a..06cedfe4b4867a7c2d42622f7a143512e665d812 100644 --- a/drivers/gpu/drm/scheduler/sched_fence.c +++ b/drivers/gpu/drm/scheduler/sched_fence.c @@ -48,8 +48,32 @@ static void __exit drm_sched_fence_slab_fini(void) kmem_cache_destroy(sched_fence_slab); } -void drm_sched_fence_scheduled(struct drm_sched_fence *fence) +static void drm_sched_fence_set_parent(struct drm_sched_fence *s_fence, + struct dma_fence *fence) { + /* + * smp_store_release() to ensure another thread racing us + * in drm_sched_fence_set_deadline_finished() sees the + * fence's parent set before test_bit() + */ + smp_store_release(&s_fence->parent, dma_fence_get(fence)); + if (test_bit(DRM_SCHED_FENCE_FLAG_HAS_DEADLINE_BIT, + &s_fence->finished.flags)) + dma_fence_set_deadline(fence, s_fence->deadline); +} + +void drm_sched_fence_scheduled(struct drm_sched_fence *fence, + struct dma_fence *parent) +{ + /* Set the parent before signaling the scheduled fence, such that, + * any waiter expecting the parent to be filled after the job has + * been scheduled (which is the case for drivers delegating waits + * to some firmware) doesn't have to busy wait for parent to show + * up. + */ + if (!IS_ERR_OR_NULL(parent)) + drm_sched_fence_set_parent(fence, parent); + dma_fence_signal(&fence->scheduled); } @@ -181,20 +205,6 @@ struct drm_sched_fence *to_drm_sched_fence(struct dma_fence *f) } EXPORT_SYMBOL(to_drm_sched_fence); -void drm_sched_fence_set_parent(struct drm_sched_fence *s_fence, - struct dma_fence *fence) -{ - /* - * smp_store_release() to ensure another thread racing us - * in drm_sched_fence_set_deadline_finished() sees the - * fence's parent set before test_bit() - */ - smp_store_release(&s_fence->parent, dma_fence_get(fence)); - if (test_bit(DRM_SCHED_FENCE_FLAG_HAS_DEADLINE_BIT, - &s_fence->finished.flags)) - dma_fence_set_deadline(fence, s_fence->deadline); -} - struct drm_sched_fence *drm_sched_fence_alloc(struct drm_sched_entity *entity, void *owner) { diff --git a/drivers/gpu/drm/scheduler/sched_main.c b/drivers/gpu/drm/scheduler/sched_main.c index 7b2bfc10c1a54c497020451841a5ffafef512399..506371c427451a07f8b57662f33a5115b09bc062 100644 --- a/drivers/gpu/drm/scheduler/sched_main.c +++ b/drivers/gpu/drm/scheduler/sched_main.c @@ -1043,10 +1043,9 @@ static int drm_sched_main(void *param) trace_drm_run_job(sched_job, entity); fence = sched->ops->run_job(sched_job); complete_all(&entity->entity_idle); - drm_sched_fence_scheduled(s_fence); + drm_sched_fence_scheduled(s_fence, fence); if (!IS_ERR_OR_NULL(fence)) { - drm_sched_fence_set_parent(s_fence, fence); /* Drop for original kref_init of the fence */ dma_fence_put(fence); diff --git a/drivers/gpu/drm/sun4i/sun4i_hdmi_i2c.c b/drivers/gpu/drm/sun4i/sun4i_hdmi_i2c.c index c7d7e9fff91c433d241d1ef0d4df517ab09d9b92..d1a65a921f5afaf5f3332239a7a9f6be44e8c475 100644 --- a/drivers/gpu/drm/sun4i/sun4i_hdmi_i2c.c +++ b/drivers/gpu/drm/sun4i/sun4i_hdmi_i2c.c @@ -304,7 +304,7 @@ int sun4i_hdmi_i2c_create(struct device *dev, struct sun4i_hdmi *hdmi) adap->owner = THIS_MODULE; adap->class = I2C_CLASS_DDC; adap->algo = &sun4i_hdmi_i2c_algorithm; - strlcpy(adap->name, "sun4i_hdmi_i2c adapter", sizeof(adap->name)); + strscpy(adap->name, "sun4i_hdmi_i2c adapter", sizeof(adap->name)); i2c_set_adapdata(adap, hdmi); ret = i2c_add_adapter(adap); diff --git a/drivers/gpu/drm/tegra/fbdev.c b/drivers/gpu/drm/tegra/fbdev.c index e74d9be981c7949344690c235fc876be10baa00a..d042234e18077ce4db7bd4a120747f3c1e42c8cd 100644 --- a/drivers/gpu/drm/tegra/fbdev.c +++ b/drivers/gpu/drm/tegra/fbdev.c @@ -225,10 +225,6 @@ void tegra_fbdev_setup(struct drm_device *dev) if (ret) goto err_drm_client_init; - ret = tegra_fbdev_client_hotplug(&helper->client); - if (ret) - drm_dbg_kms(dev, "client hotplug ret=%d\n", ret); - drm_client_register(&helper->client); return; diff --git a/drivers/gpu/drm/tegra/sor.c b/drivers/gpu/drm/tegra/sor.c index 899bb280f56e4ad8a5644993d6b0c0831c76f739..93471b70e18066cb2bdf562ee77ed624ea556695 100644 --- a/drivers/gpu/drm/tegra/sor.c +++ b/drivers/gpu/drm/tegra/sor.c @@ -586,6 +586,7 @@ static u8 tegra_clk_sor_pad_get_parent(struct clk_hw *hw) } static const struct clk_ops tegra_clk_sor_pad_ops = { + .determine_rate = clk_hw_determine_rate_no_reparent, .set_parent = tegra_clk_sor_pad_set_parent, .get_parent = tegra_clk_sor_pad_get_parent, }; diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index 758f980e3e161d006211df4ce781b79784af89af..aa8ab1a418afd02992d91a4a9aeff0e4734c356e 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -459,18 +459,18 @@ static int ttm_bo_evict(struct ttm_buffer_object *bo, goto out; } -bounce: - ret = ttm_bo_handle_move_mem(bo, evict_mem, true, ctx, &hop); - if (ret == -EMULTIHOP) { + do { + ret = ttm_bo_handle_move_mem(bo, evict_mem, true, ctx, &hop); + if (ret != -EMULTIHOP) + break; + ret = ttm_bo_bounce_temp_buffer(bo, &evict_mem, ctx, &hop); - if (ret) { - if (ret != -ERESTARTSYS && ret != -EINTR) - pr_err("Buffer eviction failed\n"); - ttm_resource_free(bo, &evict_mem); - goto out; - } - /* try and move to final place now. */ - goto bounce; + } while (!ret); + + if (ret) { + ttm_resource_free(bo, &evict_mem); + if (ret != -ERESTARTSYS && ret != -EINTR) + pr_err("Buffer eviction failed\n"); } out: return ret; @@ -518,6 +518,12 @@ static bool ttm_bo_evict_swapout_allowable(struct ttm_buffer_object *bo, { bool ret = false; + if (bo->pin_count) { + *locked = false; + *busy = false; + return false; + } + if (bo->base.resv == ctx->resv) { dma_resv_assert_held(bo->base.resv); if (ctx->allow_res_evict) @@ -1167,6 +1173,7 @@ int ttm_bo_swapout(struct ttm_buffer_object *bo, struct ttm_operation_ctx *ctx, ret = ttm_bo_handle_move_mem(bo, evict_mem, true, ctx, &hop); if (unlikely(ret != 0)) { WARN(ret == -EMULTIHOP, "Unexpected multihop in swaput - likely driver bug.\n"); + ttm_resource_free(bo, &evict_mem); goto out; } } diff --git a/drivers/gpu/drm/ttm/ttm_resource.c b/drivers/gpu/drm/ttm/ttm_resource.c index 7333f7a87a2fbfc7c93e50624650cf732da15fbe..46ff9c75bb124ae73cc45439ddd33cf9e02e305f 100644 --- a/drivers/gpu/drm/ttm/ttm_resource.c +++ b/drivers/gpu/drm/ttm/ttm_resource.c @@ -86,6 +86,8 @@ static void ttm_lru_bulk_move_pos_tail(struct ttm_lru_bulk_move_pos *pos, struct ttm_resource *res) { if (pos->last != res) { + if (pos->first == res) + pos->first = list_next_entry(res, lru); list_move(&res->lru, &pos->last->lru); pos->last = res; } @@ -111,7 +113,8 @@ static void ttm_lru_bulk_move_del(struct ttm_lru_bulk_move *bulk, { struct ttm_lru_bulk_move_pos *pos = ttm_lru_bulk_move_pos(bulk, res); - if (unlikely(pos->first == res && pos->last == res)) { + if (unlikely(WARN_ON(!pos->first || !pos->last) || + (pos->first == res && pos->last == res))) { pos->first = NULL; pos->last = NULL; } else if (pos->first == res) { diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_msg_x86.h b/drivers/gpu/drm/vmwgfx/vmwgfx_msg_x86.h index 0b74ca2dfb7bd2fd55160836784f2172f551553f..23899d743a9035af7da6ddcc15a218004a25703c 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_msg_x86.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_msg_x86.h @@ -105,10 +105,14 @@ flags, magic, bp, \ eax, ebx, ecx, edx, si, di) \ ({ \ - asm volatile ("push %%rbp;" \ + asm volatile ( \ + UNWIND_HINT_SAVE \ + "push %%rbp;" \ + UNWIND_HINT_UNDEFINED \ "mov %12, %%rbp;" \ VMWARE_HYPERCALL_HB_OUT \ - "pop %%rbp;" : \ + "pop %%rbp;" \ + UNWIND_HINT_RESTORE : \ "=a"(eax), \ "=b"(ebx), \ "=c"(ecx), \ @@ -130,10 +134,14 @@ flags, magic, bp, \ eax, ebx, ecx, edx, si, di) \ ({ \ - asm volatile ("push %%rbp;" \ + asm volatile ( \ + UNWIND_HINT_SAVE \ + "push %%rbp;" \ + UNWIND_HINT_UNDEFINED \ "mov %12, %%rbp;" \ VMWARE_HYPERCALL_HB_IN \ - "pop %%rbp" : \ + "pop %%rbp;" \ + UNWIND_HINT_RESTORE : \ "=a"(eax), \ "=b"(ebx), \ "=c"(ecx), \ diff --git a/drivers/greybus/connection.c b/drivers/greybus/connection.c index e3799a53a193066ec87e277ad643e8091e41d26d..9c88861986c8e3e859740469ecdaa2ec505a737e 100644 --- a/drivers/greybus/connection.c +++ b/drivers/greybus/connection.c @@ -187,8 +187,8 @@ _gb_connection_create(struct gb_host_device *hd, int hd_cport_id, spin_lock_init(&connection->lock); INIT_LIST_HEAD(&connection->operations); - connection->wq = alloc_workqueue("%s:%d", WQ_UNBOUND, 1, - dev_name(&hd->dev), hd_cport_id); + connection->wq = alloc_ordered_workqueue("%s:%d", 0, dev_name(&hd->dev), + hd_cport_id); if (!connection->wq) { ret = -ENOMEM; goto err_free_connection; diff --git a/drivers/greybus/svc.c b/drivers/greybus/svc.c index 16cced80867a6ad7d0bba699c985d4cc6af7082d..0d7e749174a48c65eeb0c5918f68ed75b2726613 100644 --- a/drivers/greybus/svc.c +++ b/drivers/greybus/svc.c @@ -1318,7 +1318,7 @@ struct gb_svc *gb_svc_create(struct gb_host_device *hd) if (!svc) return NULL; - svc->wq = alloc_workqueue("%s:svc", WQ_UNBOUND, 1, dev_name(&hd->dev)); + svc->wq = alloc_ordered_workqueue("%s:svc", 0, dev_name(&hd->dev)); if (!svc->wq) { kfree(svc); return NULL; diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index 4ce012f83253ec9f12e3c12b5f95c12142cb4e8c..e11c1c8036769423cd1c2b37d7b2bf4f8e7098d2 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig @@ -788,6 +788,24 @@ config HID_NTRIG help Support for N-Trig touch screen. +config HID_NVIDIA_SHIELD + tristate "NVIDIA SHIELD devices" + depends on USB_HID + depends on BT_HIDP + help + Support for NVIDIA SHIELD accessories. + + Supported devices: + - Thunderstrike (NVIDIA SHIELD Controller 2017) + +config NVIDIA_SHIELD_FF + bool "NVIDIA SHIELD force feedback support" + depends on HID_NVIDIA_SHIELD + select INPUT_FF_MEMLESS + help + Say Y here if you would like to enable force feedback support for + NVIDIA SHIELD accessories with haptics capabilities. + config HID_ORTEK tristate "Ortek PKB-1700/WKB-2000/Skycable wireless keyboard and mouse trackpad" help @@ -1285,7 +1303,7 @@ config HID_MCP2221 config HID_KUNIT_TEST tristate "KUnit tests for HID" if !KUNIT_ALL_TESTS - depends on KUNIT=y + depends on KUNIT depends on HID_BATTERY_STRENGTH depends on HID_UCLOGIC default KUNIT_ALL_TESTS diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile index 5d37cacbde33dfc8bac5ac848bc55b70fa86f574..7a9e160158f7e64799ad6ad040f56ea554df5124 100644 --- a/drivers/hid/Makefile +++ b/drivers/hid/Makefile @@ -87,6 +87,7 @@ obj-$(CONFIG_HID_MULTITOUCH) += hid-multitouch.o obj-$(CONFIG_HID_NINTENDO) += hid-nintendo.o obj-$(CONFIG_HID_NTI) += hid-nti.o obj-$(CONFIG_HID_NTRIG) += hid-ntrig.o +obj-$(CONFIG_HID_NVIDIA_SHIELD) += hid-nvidia-shield.o obj-$(CONFIG_HID_ORTEK) += hid-ortek.o obj-$(CONFIG_HID_PRODIKEYS) += hid-prodikeys.o obj-$(CONFIG_HID_PANTHERLORD) += hid-pl.o diff --git a/drivers/hid/amd-sfh-hid/amd_sfh_client.c b/drivers/hid/amd-sfh-hid/amd_sfh_client.c index d9b7b01900b590137c54a3e60fedfcd3e2a97037..bdb578e0899f55bb1b632cd17ef10200b52e3dd9 100644 --- a/drivers/hid/amd-sfh-hid/amd_sfh_client.c +++ b/drivers/hid/amd-sfh-hid/amd_sfh_client.c @@ -215,7 +215,7 @@ int amd_sfh_hid_client_init(struct amd_mp2_dev *privdata) struct device *dev; u32 feature_report_size; u32 input_report_size; - int rc, i, status; + int rc, i; u8 cl_idx; req_list = &cl_data->req_list; @@ -286,56 +286,37 @@ int amd_sfh_hid_client_init(struct amd_mp2_dev *privdata) if (rc) goto cleanup; mp2_ops->start(privdata, info); - status = amd_sfh_wait_for_response - (privdata, cl_data->sensor_idx[i], SENSOR_ENABLED); - if (status == SENSOR_ENABLED) { + cl_data->sensor_sts[i] = amd_sfh_wait_for_response + (privdata, cl_data->sensor_idx[i], SENSOR_ENABLED); + } + + for (i = 0; i < cl_data->num_hid_devices; i++) { + cl_data->cur_hid_dev = i; + if (cl_data->sensor_sts[i] == SENSOR_ENABLED) { cl_data->is_any_sensor_enabled = true; - cl_data->sensor_sts[i] = SENSOR_ENABLED; - rc = amdtp_hid_probe(cl_data->cur_hid_dev, cl_data); - if (rc) { - mp2_ops->stop(privdata, cl_data->sensor_idx[i]); - status = amd_sfh_wait_for_response - (privdata, cl_data->sensor_idx[i], SENSOR_DISABLED); - if (status != SENSOR_ENABLED) - cl_data->sensor_sts[i] = SENSOR_DISABLED; - dev_dbg(dev, "sid 0x%x (%s) status 0x%x\n", - cl_data->sensor_idx[i], - get_sensor_name(cl_data->sensor_idx[i]), - cl_data->sensor_sts[i]); + rc = amdtp_hid_probe(i, cl_data); + if (rc) goto cleanup; - } } else { cl_data->sensor_sts[i] = SENSOR_DISABLED; - dev_dbg(dev, "sid 0x%x (%s) status 0x%x\n", - cl_data->sensor_idx[i], - get_sensor_name(cl_data->sensor_idx[i]), - cl_data->sensor_sts[i]); } dev_dbg(dev, "sid 0x%x (%s) status 0x%x\n", cl_data->sensor_idx[i], get_sensor_name(cl_data->sensor_idx[i]), cl_data->sensor_sts[i]); } + if (!cl_data->is_any_sensor_enabled || (mp2_ops->discovery_status && mp2_ops->discovery_status(privdata) == 0)) { - amd_sfh_hid_client_deinit(privdata); - for (i = 0; i < cl_data->num_hid_devices; i++) { - devm_kfree(dev, cl_data->feature_report[i]); - devm_kfree(dev, in_data->input_report[i]); - devm_kfree(dev, cl_data->report_descr[i]); - } dev_warn(dev, "Failed to discover, sensors not enabled is %d\n", cl_data->is_any_sensor_enabled); - return -EOPNOTSUPP; + rc = -EOPNOTSUPP; + goto cleanup; } schedule_delayed_work(&cl_data->work_buffer, msecs_to_jiffies(AMD_SFH_IDLE_LOOP)); return 0; cleanup: + amd_sfh_hid_client_deinit(privdata); for (i = 0; i < cl_data->num_hid_devices; i++) { - if (in_data->sensor_virt_addr[i]) { - dma_free_coherent(&privdata->pdev->dev, 8 * sizeof(int), - in_data->sensor_virt_addr[i], - cl_data->sensor_dma_addr[i]); - } devm_kfree(dev, cl_data->feature_report[i]); devm_kfree(dev, in_data->input_report[i]); devm_kfree(dev, cl_data->report_descr[i]); diff --git a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_desc.c b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_desc.c index 6f0d332ccf51c7d5f873ff2518c4b7282eddda63..06bdcf072d10cf908c421b7d94de66643b777691 100644 --- a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_desc.c +++ b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_desc.c @@ -132,29 +132,45 @@ static void get_common_inputs(struct common_input_property *common, int report_i common->event_type = HID_USAGE_SENSOR_EVENT_DATA_UPDATED_ENUM; } -static int float_to_int(u32 float32) +static int float_to_int(u32 flt32_val) { int fraction, shift, mantissa, sign, exp, zeropre; - mantissa = float32 & GENMASK(22, 0); - sign = (float32 & BIT(31)) ? -1 : 1; - exp = (float32 & ~BIT(31)) >> 23; + mantissa = flt32_val & GENMASK(22, 0); + sign = (flt32_val & BIT(31)) ? -1 : 1; + exp = (flt32_val & ~BIT(31)) >> 23; if (!exp && !mantissa) return 0; + /* + * Calculate the exponent and fraction part of floating + * point representation. + */ exp -= 127; if (exp < 0) { exp = -exp; + if (exp >= BITS_PER_TYPE(u32)) + return 0; zeropre = (((BIT(23) + mantissa) * 100) >> 23) >> exp; return zeropre >= 50 ? sign : 0; } shift = 23 - exp; - float32 = BIT(exp) + (mantissa >> shift); - fraction = mantissa & GENMASK(shift - 1, 0); + if (abs(shift) >= BITS_PER_TYPE(u32)) + return 0; + + if (shift < 0) { + shift = -shift; + flt32_val = BIT(exp) + (mantissa << shift); + shift = 0; + } else { + flt32_val = BIT(exp) + (mantissa >> shift); + } + + fraction = (shift == 0) ? 0 : mantissa & GENMASK(shift - 1, 0); - return (((fraction * 100) >> shift) >= 50) ? sign * (float32 + 1) : sign * float32; + return (((fraction * 100) >> shift) >= 50) ? sign * (flt32_val + 1) : sign * flt32_val; } static u8 get_input_rep(u8 current_index, int sensor_idx, int report_id, diff --git a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c index bb8bd7892b674634016e407ac612bd15c9df9eef..e9c6413af24a079959f693db36f760fed1a77950 100644 --- a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c +++ b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c @@ -168,28 +168,16 @@ static int amd_sfh1_1_hid_client_init(struct amd_mp2_dev *privdata) status = amd_sfh_wait_for_response (privdata, cl_data->sensor_idx[i], ENABLE_SENSOR); - status = (status == 0) ? SENSOR_ENABLED : SENSOR_DISABLED; + cl_data->sensor_sts[i] = (status == 0) ? SENSOR_ENABLED : SENSOR_DISABLED; + } - if (status == SENSOR_ENABLED) { + for (i = 0; i < cl_data->num_hid_devices; i++) { + cl_data->cur_hid_dev = i; + if (cl_data->sensor_sts[i] == SENSOR_ENABLED) { cl_data->is_any_sensor_enabled = true; - cl_data->sensor_sts[i] = SENSOR_ENABLED; rc = amdtp_hid_probe(i, cl_data); - if (rc) { - mp2_ops->stop(privdata, cl_data->sensor_idx[i]); - status = amd_sfh_wait_for_response - (privdata, cl_data->sensor_idx[i], DISABLE_SENSOR); - if (status == 0) - status = SENSOR_DISABLED; - if (status != SENSOR_ENABLED) - cl_data->sensor_sts[i] = SENSOR_DISABLED; - dev_dbg(dev, "sid 0x%x (%s) status 0x%x\n", - cl_data->sensor_idx[i], - get_sensor_name(cl_data->sensor_idx[i]), - cl_data->sensor_sts[i]); + if (rc) goto cleanup; - } - } else { - cl_data->sensor_sts[i] = SENSOR_DISABLED; } dev_dbg(dev, "sid 0x%x (%s) status 0x%x\n", cl_data->sensor_idx[i], get_sensor_name(cl_data->sensor_idx[i]), diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c index cc535d2d6e8c62194d5f746d7c7f9ba1bef7b3a9..d7b932925730db33b1547e8fabc14d2782791186 100644 --- a/drivers/hid/hid-apple.c +++ b/drivers/hid/hid-apple.c @@ -58,7 +58,7 @@ static unsigned int swap_opt_cmd; module_param(swap_opt_cmd, uint, 0644); MODULE_PARM_DESC(swap_opt_cmd, "Swap the Option (\"Alt\") and Command (\"Flag\") keys. " "(For people who want to keep Windows PC keyboard muscle memory. " - "[0] = as-is, Mac layout. 1 = swapped, Windows layout.)"); + "[0] = as-is, Mac layout. 1 = swapped, Windows layout., 2 = swapped, Swap only left side)"); static unsigned int swap_ctrl_cmd; module_param(swap_ctrl_cmd, uint, 0644); @@ -319,6 +319,12 @@ static const struct apple_key_translation swapped_option_cmd_keys[] = { { } }; +static const struct apple_key_translation swapped_option_cmd_left_keys[] = { + { KEY_LEFTALT, KEY_LEFTMETA }, + { KEY_LEFTMETA, KEY_LEFTALT }, + { } +}; + static const struct apple_key_translation swapped_ctrl_cmd_keys[] = { { KEY_LEFTCTRL, KEY_LEFTMETA }, { KEY_LEFTMETA, KEY_LEFTCTRL }, @@ -416,7 +422,10 @@ static int hidinput_apple_event(struct hid_device *hid, struct input_dev *input, } if (swap_opt_cmd) { - trans = apple_find_translation(swapped_option_cmd_keys, code); + if (swap_opt_cmd == 2) + trans = apple_find_translation(swapped_option_cmd_left_keys, code); + else + trans = apple_find_translation(swapped_option_cmd_keys, code); if (trans) code = trans->to; diff --git a/drivers/hid/hid-asus.c b/drivers/hid/hid-asus.c index 01a27579ec0202c016bf143fa7fd84c9b4b6587b..fd61dba882338e022685fca453e2d70a0e093106 100644 --- a/drivers/hid/hid-asus.c +++ b/drivers/hid/hid-asus.c @@ -884,33 +884,20 @@ static int asus_input_mapping(struct hid_device *hdev, case 0xb5: asus_map_key_clear(KEY_CALC); break; case 0xc4: asus_map_key_clear(KEY_KBDILLUMUP); break; case 0xc5: asus_map_key_clear(KEY_KBDILLUMDOWN); break; + case 0xc7: asus_map_key_clear(KEY_KBDILLUMTOGGLE); break; - /* ASUS touchpad toggle */ - case 0x6b: asus_map_key_clear(KEY_F21); break; + case 0x6b: asus_map_key_clear(KEY_F21); break; /* ASUS touchpad toggle */ + case 0x38: asus_map_key_clear(KEY_PROG1); break; /* ROG key */ + case 0xba: asus_map_key_clear(KEY_PROG2); break; /* Fn+C ASUS Splendid */ + case 0x5c: asus_map_key_clear(KEY_PROG3); break; /* Fn+Space Power4Gear */ + case 0x99: asus_map_key_clear(KEY_PROG4); break; /* Fn+F5 "fan" symbol */ + case 0xae: asus_map_key_clear(KEY_PROG4); break; /* Fn+F5 "fan" symbol */ + case 0x92: asus_map_key_clear(KEY_CALC); break; /* Fn+Ret "Calc" symbol */ + case 0xb2: asus_map_key_clear(KEY_PROG2); break; /* Fn+Left previous aura */ + case 0xb3: asus_map_key_clear(KEY_PROG3); break; /* Fn+Left next aura */ + case 0x6a: asus_map_key_clear(KEY_F13); break; /* Screenpad toggle */ + case 0x4b: asus_map_key_clear(KEY_F14); break; /* Arrows/Pg-Up/Dn toggle */ - /* ROG key */ - case 0x38: asus_map_key_clear(KEY_PROG1); break; - - /* Fn+C ASUS Splendid */ - case 0xba: asus_map_key_clear(KEY_PROG2); break; - - /* Fn+Space Power4Gear Hybrid */ - case 0x5c: asus_map_key_clear(KEY_PROG3); break; - - /* Fn+F5 "fan" symbol on FX503VD */ - case 0x99: asus_map_key_clear(KEY_PROG4); break; - - /* Fn+F5 "fan" symbol on N-Key keyboard */ - case 0xae: asus_map_key_clear(KEY_PROG4); break; - - /* Fn+Ret "Calc" symbol on N-Key keyboard */ - case 0x92: asus_map_key_clear(KEY_CALC); break; - - /* Fn+Left Aura mode previous on N-Key keyboard */ - case 0xb2: asus_map_key_clear(KEY_PROG2); break; - - /* Fn+Right Aura mode next on N-Key keyboard */ - case 0xb3: asus_map_key_clear(KEY_PROG3); break; default: /* ASUS lazily declares 256 usages, ignore the rest, @@ -1268,6 +1255,9 @@ static const struct hid_device_id asus_devices[] = { { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_ROG_NKEY_KEYBOARD2), QUIRK_USE_KBD_BACKLIGHT | QUIRK_ROG_NKEY_KEYBOARD }, + { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, + USB_DEVICE_ID_ASUSTEK_ROG_NKEY_KEYBOARD3), + QUIRK_USE_KBD_BACKLIGHT | QUIRK_ROG_NKEY_KEYBOARD }, { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_ROG_CLAYMORE_II_KEYBOARD), QUIRK_ROG_CLAYMORE_II_KEYBOARD }, @@ -1310,4 +1300,4 @@ static struct hid_driver asus_driver = { }; module_hid_driver(asus_driver); -MODULE_LICENSE("GPL"); +MODULE_LICENSE("GPL"); \ No newline at end of file diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 22623eb4f72f2979b8f282b85c7fb006faa47241..8992e3c1e7698eeaeeb7711876d66022ef5ec9d0 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -2587,64 +2587,84 @@ bool hid_compare_device_paths(struct hid_device *hdev_a, } EXPORT_SYMBOL_GPL(hid_compare_device_paths); +static bool hid_check_device_match(struct hid_device *hdev, + struct hid_driver *hdrv, + const struct hid_device_id **id) +{ + *id = hid_match_device(hdev, hdrv); + if (!*id) + return false; + + if (hdrv->match) + return hdrv->match(hdev, hid_ignore_special_drivers); + + /* + * hid-generic implements .match(), so we must be dealing with a + * different HID driver here, and can simply check if + * hid_ignore_special_drivers is set or not. + */ + return !hid_ignore_special_drivers; +} + +static int __hid_device_probe(struct hid_device *hdev, struct hid_driver *hdrv) +{ + const struct hid_device_id *id; + int ret; + + if (!hid_check_device_match(hdev, hdrv, &id)) + return -ENODEV; + + hdev->devres_group_id = devres_open_group(&hdev->dev, NULL, GFP_KERNEL); + if (!hdev->devres_group_id) + return -ENOMEM; + + /* reset the quirks that has been previously set */ + hdev->quirks = hid_lookup_quirk(hdev); + hdev->driver = hdrv; + + if (hdrv->probe) { + ret = hdrv->probe(hdev, id); + } else { /* default probe */ + ret = hid_open_report(hdev); + if (!ret) + ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); + } + + /* + * Note that we are not closing the devres group opened above so + * even resources that were attached to the device after probe is + * run are released when hid_device_remove() is executed. This is + * needed as some drivers would allocate additional resources, + * for example when updating firmware. + */ + + if (ret) { + devres_release_group(&hdev->dev, hdev->devres_group_id); + hid_close_report(hdev); + hdev->driver = NULL; + } + + return ret; +} + static int hid_device_probe(struct device *dev) { - struct hid_driver *hdrv = to_hid_driver(dev->driver); struct hid_device *hdev = to_hid_device(dev); - const struct hid_device_id *id; + struct hid_driver *hdrv = to_hid_driver(dev->driver); int ret = 0; - if (down_interruptible(&hdev->driver_input_lock)) { - ret = -EINTR; - goto end; - } - hdev->io_started = false; + if (down_interruptible(&hdev->driver_input_lock)) + return -EINTR; + hdev->io_started = false; clear_bit(ffs(HID_STAT_REPROBED), &hdev->status); - if (!hdev->driver) { - id = hid_match_device(hdev, hdrv); - if (id == NULL) { - ret = -ENODEV; - goto unlock; - } - - if (hdrv->match) { - if (!hdrv->match(hdev, hid_ignore_special_drivers)) { - ret = -ENODEV; - goto unlock; - } - } else { - /* - * hid-generic implements .match(), so if - * hid_ignore_special_drivers is set, we can safely - * return. - */ - if (hid_ignore_special_drivers) { - ret = -ENODEV; - goto unlock; - } - } + if (!hdev->driver) + ret = __hid_device_probe(hdev, hdrv); - /* reset the quirks that has been previously set */ - hdev->quirks = hid_lookup_quirk(hdev); - hdev->driver = hdrv; - if (hdrv->probe) { - ret = hdrv->probe(hdev, id); - } else { /* default probe */ - ret = hid_open_report(hdev); - if (!ret) - ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); - } - if (ret) { - hid_close_report(hdev); - hdev->driver = NULL; - } - } -unlock: if (!hdev->io_started) up(&hdev->driver_input_lock); -end: + return ret; } @@ -2662,6 +2682,10 @@ static void hid_device_remove(struct device *dev) hdrv->remove(hdev); else /* default remove */ hid_hw_stop(hdev); + + /* Release all devres resources allocated by the driver */ + devres_release_group(&hdev->dev, hdev->devres_group_id); + hid_close_report(hdev); hdev->driver = NULL; } diff --git a/drivers/hid/hid-hyperv.c b/drivers/hid/hid-hyperv.c index 49d4a26895e76791be50237d37ccf7490197c7bd..f33485d83d24ff9ca5c80c36bab775f26ae8e68d 100644 --- a/drivers/hid/hid-hyperv.c +++ b/drivers/hid/hid-hyperv.c @@ -258,19 +258,17 @@ static void mousevsc_on_receive(struct hv_device *device, switch (hid_msg_hdr->type) { case SYNTH_HID_PROTOCOL_RESPONSE: + len = struct_size(pipe_msg, data, pipe_msg->size); + /* * While it will be impossible for us to protect against * malicious/buggy hypervisor/host, add a check here to * ensure we don't corrupt memory. */ - if (struct_size(pipe_msg, data, pipe_msg->size) - > sizeof(struct mousevsc_prt_msg)) { - WARN_ON(1); + if (WARN_ON(len > sizeof(struct mousevsc_prt_msg))) break; - } - memcpy(&input_dev->protocol_resp, pipe_msg, - struct_size(pipe_msg, data, pipe_msg->size)); + memcpy(&input_dev->protocol_resp, pipe_msg, len); complete(&input_dev->wait_event); break; diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 5d29abac2300e40c75b0b6eedb803969cac1a84a..8a310f8ff20f56b5f7f830e0315fc5959225ad13 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -207,6 +207,7 @@ #define USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD3 0x1822 #define USB_DEVICE_ID_ASUSTEK_ROG_NKEY_KEYBOARD 0x1866 #define USB_DEVICE_ID_ASUSTEK_ROG_NKEY_KEYBOARD2 0x19b6 +#define USB_DEVICE_ID_ASUSTEK_ROG_NKEY_KEYBOARD3 0x1a30 #define USB_DEVICE_ID_ASUSTEK_ROG_CLAYMORE_II_KEYBOARD 0x196b #define USB_DEVICE_ID_ASUSTEK_FX503VD_KEYBOARD 0x1869 @@ -620,6 +621,7 @@ #define USB_DEVICE_ID_UGCI_FIGHTING 0x0030 #define USB_VENDOR_ID_HP 0x03f0 +#define USB_PRODUCT_ID_HP_ELITE_PRESENTER_MOUSE_464A 0x464a #define USB_PRODUCT_ID_HP_LOGITECH_OEM_USB_OPTICAL_MOUSE_0A4A 0x0a4a #define USB_PRODUCT_ID_HP_LOGITECH_OEM_USB_OPTICAL_MOUSE_0B4A 0x0b4a #define USB_PRODUCT_ID_HP_PIXART_OEM_USB_OPTICAL_MOUSE 0x134a @@ -934,7 +936,15 @@ #define USB_DEVICE_ID_MS_TYPE_COVER_2 0x07a9 #define USB_DEVICE_ID_MS_POWER_COVER 0x07da #define USB_DEVICE_ID_MS_SURFACE3_COVER 0x07de -#define USB_DEVICE_ID_MS_XBOX_ONE_S_CONTROLLER 0x02fd +/* + * For a description of the Xbox controller models, refer to: + * https://en.wikipedia.org/wiki/Xbox_Wireless_Controller#Summary + */ +#define USB_DEVICE_ID_MS_XBOX_CONTROLLER_MODEL_1708 0x02fd +#define USB_DEVICE_ID_MS_XBOX_CONTROLLER_MODEL_1708_BLE 0x0b20 +#define USB_DEVICE_ID_MS_XBOX_CONTROLLER_MODEL_1914 0x0b13 +#define USB_DEVICE_ID_MS_XBOX_CONTROLLER_MODEL_1797 0x0b05 +#define USB_DEVICE_ID_MS_XBOX_CONTROLLER_MODEL_1797_BLE 0x0b22 #define USB_DEVICE_ID_MS_PIXART_MOUSE 0x00cb #define USB_DEVICE_ID_8BITDO_SN30_PRO_PLUS 0x02e0 #define USB_DEVICE_ID_MS_MOUSE_0783 0x0783 @@ -1005,6 +1015,9 @@ #define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_18 0x0014 #define USB_DEVICE_ID_NTRIG_DUOSENSE 0x1500 +#define USB_VENDOR_ID_NVIDIA 0x0955 +#define USB_DEVICE_ID_NVIDIA_THUNDERSTRIKE_CONTROLLER 0x7214 + #define USB_VENDOR_ID_ONTRAK 0x0a07 #define USB_DEVICE_ID_ONTRAK_ADU100 0x0064 diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index a1d2690a1a0deeea0d021e8b4d31ddb84de3b20b..851ee86eff32a4085e9a640620c8ea9a5e2211c8 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c @@ -1093,6 +1093,10 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel case 0x074: map_key_clear(KEY_BRIGHTNESS_MAX); break; case 0x075: map_key_clear(KEY_BRIGHTNESS_AUTO); break; + case 0x076: map_key_clear(KEY_CAMERA_ACCESS_ENABLE); break; + case 0x077: map_key_clear(KEY_CAMERA_ACCESS_DISABLE); break; + case 0x078: map_key_clear(KEY_CAMERA_ACCESS_TOGGLE); break; + case 0x079: map_key_clear(KEY_KBDILLUMUP); break; case 0x07a: map_key_clear(KEY_KBDILLUMDOWN); break; case 0x07c: map_key_clear(KEY_KBDILLUMTOGGLE); break; @@ -1139,9 +1143,6 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel case 0x0cd: map_key_clear(KEY_PLAYPAUSE); break; case 0x0cf: map_key_clear(KEY_VOICECOMMAND); break; - case 0x0d5: map_key_clear(KEY_CAMERA_ACCESS_ENABLE); break; - case 0x0d6: map_key_clear(KEY_CAMERA_ACCESS_DISABLE); break; - case 0x0d7: map_key_clear(KEY_CAMERA_ACCESS_TOGGLE); break; case 0x0d8: map_key_clear(KEY_DICTATE); break; case 0x0d9: map_key_clear(KEY_EMOJI_PICKER); break; diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c index 5e1a412fd28fa125ba84ee35ce570cc4827d755f..129b01be488d2ff88678c8913a0ec467e47d2634 100644 --- a/drivers/hid/hid-logitech-hidpp.c +++ b/drivers/hid/hid-logitech-hidpp.c @@ -4553,7 +4553,7 @@ static const struct hid_device_id hidpp_devices[] = { { /* wireless touchpad T651 */ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_T651), - .driver_data = HIDPP_QUIRK_CLASS_WTP }, + .driver_data = HIDPP_QUIRK_CLASS_WTP | HIDPP_QUIRK_DELAYED_INIT }, { /* Mouse Logitech Anywhere MX */ LDJ_DEVICE(0x1017), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_1P0 }, { /* Mouse logitech M560 */ @@ -4598,6 +4598,8 @@ static const struct hid_device_id hidpp_devices[] = { { /* Logitech G403 Wireless Gaming Mouse over USB */ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC082) }, + { /* Logitech G502 Lightspeed Wireless Gaming Mouse over USB */ + HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC08D) }, { /* Logitech G703 Gaming Mouse over USB */ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC087) }, { /* Logitech G703 Hero Gaming Mouse over USB */ @@ -4608,6 +4610,8 @@ static const struct hid_device_id hidpp_devices[] = { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC086) }, { /* Logitech G903 Hero Gaming Mouse over USB */ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC091) }, + { /* Logitech G915 TKL Keyboard over USB */ + HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC343) }, { /* Logitech G920 Wheel over USB */ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G920_WHEEL), .driver_data = HIDPP_QUIRK_CLASS_G920 | HIDPP_QUIRK_FORCE_OUTPUT_REPORTS}, @@ -4630,6 +4634,8 @@ static const struct hid_device_id hidpp_devices[] = { { /* MX5500 keyboard over Bluetooth */ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb30b), .driver_data = HIDPP_QUIRK_HIDPP_CONSUMER_VENDOR_KEYS }, + { /* Logitech G915 TKL keyboard over Bluetooth */ + HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb35f) }, { /* M-RCQ142 V470 Cordless Laser Mouse over Bluetooth */ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb008) }, { /* MX Master mouse over Bluetooth */ diff --git a/drivers/hid/hid-microsoft.c b/drivers/hid/hid-microsoft.c index 071fd093a5f4e139893ccf53befe23f14b8bf974..9345e2bfd56edecbfce593ea93efca5ccbf78fb6 100644 --- a/drivers/hid/hid-microsoft.c +++ b/drivers/hid/hid-microsoft.c @@ -446,7 +446,16 @@ static const struct hid_device_id ms_devices[] = { .driver_data = MS_PRESENTER }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, 0x091B), .driver_data = MS_SURFACE_DIAL }, - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_XBOX_ONE_S_CONTROLLER), + + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_XBOX_CONTROLLER_MODEL_1708), + .driver_data = MS_QUIRK_FF }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_XBOX_CONTROLLER_MODEL_1708_BLE), + .driver_data = MS_QUIRK_FF }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_XBOX_CONTROLLER_MODEL_1914), + .driver_data = MS_QUIRK_FF }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_XBOX_CONTROLLER_MODEL_1797), + .driver_data = MS_QUIRK_FF }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_XBOX_CONTROLLER_MODEL_1797_BLE), .driver_data = MS_QUIRK_FF }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_8BITDO_SN30_PRO_PLUS), .driver_data = MS_QUIRK_FF }, diff --git a/drivers/hid/hid-nvidia-shield.c b/drivers/hid/hid-nvidia-shield.c new file mode 100644 index 0000000000000000000000000000000000000000..a928ad2be62dbe21c8fc2f01be18ff9a7bc7d488 --- /dev/null +++ b/drivers/hid/hid-nvidia-shield.c @@ -0,0 +1,738 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved. + * + * HID driver for NVIDIA SHIELD peripherals. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "hid-ids.h" + +#define NOT_INIT_STR "NOT INITIALIZED" +#define android_map_key(c) hid_map_usage(hi, usage, bit, max, EV_KEY, (c)) + +enum { + HID_USAGE_ANDROID_PLAYPAUSE_BTN = 0xcd, /* Double-tap volume slider */ + HID_USAGE_ANDROID_VOLUMEUP_BTN = 0xe9, + HID_USAGE_ANDROID_VOLUMEDOWN_BTN = 0xea, + HID_USAGE_ANDROID_SEARCH_BTN = 0x221, /* NVIDIA btn on Thunderstrike */ + HID_USAGE_ANDROID_HOME_BTN = 0x223, + HID_USAGE_ANDROID_BACK_BTN = 0x224, +}; + +enum { + SHIELD_FW_VERSION_INITIALIZED = 0, + SHIELD_BOARD_INFO_INITIALIZED, +}; + +enum { + THUNDERSTRIKE_FW_VERSION_UPDATE = 0, + THUNDERSTRIKE_BOARD_INFO_UPDATE, + THUNDERSTRIKE_HAPTICS_UPDATE, + THUNDERSTRIKE_LED_UPDATE, +}; + +enum { + THUNDERSTRIKE_HOSTCMD_REPORT_SIZE = 33, + THUNDERSTRIKE_HOSTCMD_REQ_REPORT_ID = 0x4, + THUNDERSTRIKE_HOSTCMD_RESP_REPORT_ID = 0x3, +}; + +enum { + THUNDERSTRIKE_HOSTCMD_ID_FW_VERSION = 1, + THUNDERSTRIKE_HOSTCMD_ID_LED = 6, + THUNDERSTRIKE_HOSTCMD_ID_BOARD_INFO = 16, + THUNDERSTRIKE_HOSTCMD_ID_USB_INIT = 53, + THUNDERSTRIKE_HOSTCMD_ID_HAPTICS = 57, + THUNDERSTRIKE_HOSTCMD_ID_BLUETOOTH_INIT = 58, +}; + +enum thunderstrike_led_state { + THUNDERSTRIKE_LED_OFF = 1, + THUNDERSTRIKE_LED_ON = 8, +} __packed; +static_assert(sizeof(enum thunderstrike_led_state) == 1); + +struct thunderstrike_hostcmd_board_info { + __le16 revision; + __le16 serial[7]; +} __packed; + +struct thunderstrike_hostcmd_haptics { + u8 motor_left; + u8 motor_right; +} __packed; + +struct thunderstrike_hostcmd_resp_report { + u8 report_id; /* THUNDERSTRIKE_HOSTCMD_RESP_REPORT_ID */ + u8 cmd_id; + u8 reserved_at_10; + + union { + struct thunderstrike_hostcmd_board_info board_info; + struct thunderstrike_hostcmd_haptics motors; + __le16 fw_version; + enum thunderstrike_led_state led_state; + u8 payload[30]; + } __packed; +} __packed; +static_assert(sizeof(struct thunderstrike_hostcmd_resp_report) == + THUNDERSTRIKE_HOSTCMD_REPORT_SIZE); + +struct thunderstrike_hostcmd_req_report { + u8 report_id; /* THUNDERSTRIKE_HOSTCMD_REQ_REPORT_ID */ + u8 cmd_id; + u8 reserved_at_10; + + union { + struct __packed { + u8 update; + enum thunderstrike_led_state state; + } led; + struct __packed { + u8 update; + struct thunderstrike_hostcmd_haptics motors; + } haptics; + } __packed; + u8 reserved_at_30[27]; +} __packed; +static_assert(sizeof(struct thunderstrike_hostcmd_req_report) == + THUNDERSTRIKE_HOSTCMD_REPORT_SIZE); + +/* Common struct for shield accessories. */ +struct shield_device { + struct hid_device *hdev; + + unsigned long initialized_flags; + const char *codename; + u16 fw_version; + struct { + u16 revision; + char serial_number[15]; + } board_info; +}; + +struct thunderstrike { + struct shield_device base; + + /* Sub-devices */ + struct input_dev *haptics_dev; + struct led_classdev led_dev; + + /* Resources */ + void *req_report_dmabuf; + unsigned long update_flags; + struct thunderstrike_hostcmd_haptics haptics_val; + spinlock_t haptics_update_lock; + u8 led_state : 1; + enum thunderstrike_led_state led_value; + struct work_struct hostcmd_req_work; +}; + +static inline void thunderstrike_hostcmd_req_report_init( + struct thunderstrike_hostcmd_req_report *report, u8 cmd_id) +{ + memset(report, 0, sizeof(*report)); + report->report_id = THUNDERSTRIKE_HOSTCMD_REQ_REPORT_ID; + report->cmd_id = cmd_id; +} + +static inline void shield_strrev(char *dest, size_t len, u16 rev) +{ + dest[0] = ('A' - 1) + (rev >> 8); + snprintf(&dest[1], len - 1, "%02X", 0xff & rev); +} + +static struct input_dev *shield_allocate_input_dev(struct hid_device *hdev, + const char *name_suffix) +{ + struct input_dev *idev; + + idev = input_allocate_device(); + if (!idev) + goto err_device; + + idev->id.bustype = hdev->bus; + idev->id.vendor = hdev->vendor; + idev->id.product = hdev->product; + idev->id.version = hdev->version; + idev->uniq = hdev->uniq; + idev->name = devm_kasprintf(&idev->dev, GFP_KERNEL, "%s %s", hdev->name, + name_suffix); + if (!idev->name) + goto err_name; + + input_set_drvdata(idev, hdev); + + return idev; + +err_name: + input_free_device(idev); +err_device: + return ERR_PTR(-ENOMEM); +} + +static struct input_dev *shield_haptics_create( + struct shield_device *dev, + int (*play_effect)(struct input_dev *, void *, struct ff_effect *)) +{ + struct input_dev *haptics; + int ret; + + if (!IS_ENABLED(CONFIG_NVIDIA_SHIELD_FF)) + return NULL; + + haptics = shield_allocate_input_dev(dev->hdev, "Haptics"); + if (IS_ERR(haptics)) + return haptics; + + input_set_capability(haptics, EV_FF, FF_RUMBLE); + input_ff_create_memless(haptics, NULL, play_effect); + + ret = input_register_device(haptics); + if (ret) + goto err; + + return haptics; + +err: + input_free_device(haptics); + return ERR_PTR(ret); +} + +static inline void thunderstrike_send_hostcmd_request(struct thunderstrike *ts) +{ + struct thunderstrike_hostcmd_req_report *report = ts->req_report_dmabuf; + struct shield_device *shield_dev = &ts->base; + int ret; + + ret = hid_hw_raw_request(shield_dev->hdev, report->report_id, + ts->req_report_dmabuf, + THUNDERSTRIKE_HOSTCMD_REPORT_SIZE, + HID_OUTPUT_REPORT, HID_REQ_SET_REPORT); + + if (ret < 0) { + hid_err(shield_dev->hdev, + "Failed to output Thunderstrike HOSTCMD request HID report due to %pe\n", + ERR_PTR(ret)); + } +} + +static void thunderstrike_hostcmd_req_work_handler(struct work_struct *work) +{ + struct thunderstrike *ts = + container_of(work, struct thunderstrike, hostcmd_req_work); + struct thunderstrike_hostcmd_req_report *report; + unsigned long flags; + + report = ts->req_report_dmabuf; + + if (test_and_clear_bit(THUNDERSTRIKE_FW_VERSION_UPDATE, &ts->update_flags)) { + thunderstrike_hostcmd_req_report_init( + report, THUNDERSTRIKE_HOSTCMD_ID_FW_VERSION); + thunderstrike_send_hostcmd_request(ts); + } + + if (test_and_clear_bit(THUNDERSTRIKE_LED_UPDATE, &ts->update_flags)) { + thunderstrike_hostcmd_req_report_init(report, THUNDERSTRIKE_HOSTCMD_ID_LED); + report->led.update = 1; + report->led.state = ts->led_value; + thunderstrike_send_hostcmd_request(ts); + } + + if (test_and_clear_bit(THUNDERSTRIKE_BOARD_INFO_UPDATE, &ts->update_flags)) { + thunderstrike_hostcmd_req_report_init( + report, THUNDERSTRIKE_HOSTCMD_ID_BOARD_INFO); + thunderstrike_send_hostcmd_request(ts); + } + + if (test_and_clear_bit(THUNDERSTRIKE_HAPTICS_UPDATE, &ts->update_flags)) { + thunderstrike_hostcmd_req_report_init( + report, THUNDERSTRIKE_HOSTCMD_ID_HAPTICS); + + report->haptics.update = 1; + spin_lock_irqsave(&ts->haptics_update_lock, flags); + report->haptics.motors = ts->haptics_val; + spin_unlock_irqrestore(&ts->haptics_update_lock, flags); + + thunderstrike_send_hostcmd_request(ts); + } +} + +static inline void thunderstrike_request_firmware_version(struct thunderstrike *ts) +{ + set_bit(THUNDERSTRIKE_FW_VERSION_UPDATE, &ts->update_flags); + schedule_work(&ts->hostcmd_req_work); +} + +static inline void thunderstrike_request_board_info(struct thunderstrike *ts) +{ + set_bit(THUNDERSTRIKE_BOARD_INFO_UPDATE, &ts->update_flags); + schedule_work(&ts->hostcmd_req_work); +} + +static inline int +thunderstrike_update_haptics(struct thunderstrike *ts, + struct thunderstrike_hostcmd_haptics *motors) +{ + unsigned long flags; + + spin_lock_irqsave(&ts->haptics_update_lock, flags); + ts->haptics_val = *motors; + spin_unlock_irqrestore(&ts->haptics_update_lock, flags); + + set_bit(THUNDERSTRIKE_HAPTICS_UPDATE, &ts->update_flags); + schedule_work(&ts->hostcmd_req_work); + + return 0; +} + +static int thunderstrike_play_effect(struct input_dev *idev, void *data, + struct ff_effect *effect) +{ + struct hid_device *hdev = input_get_drvdata(idev); + struct thunderstrike_hostcmd_haptics motors; + struct shield_device *shield_dev; + struct thunderstrike *ts; + + if (effect->type != FF_RUMBLE) + return 0; + + shield_dev = hid_get_drvdata(hdev); + ts = container_of(shield_dev, struct thunderstrike, base); + + /* Thunderstrike motor values range from 0 to 32 inclusively */ + motors.motor_left = effect->u.rumble.strong_magnitude / 2047; + motors.motor_right = effect->u.rumble.weak_magnitude / 2047; + + hid_dbg(hdev, "Thunderstrike FF_RUMBLE request, left: %u right: %u\n", + motors.motor_left, motors.motor_right); + + return thunderstrike_update_haptics(ts, &motors); +} + +static enum led_brightness +thunderstrike_led_get_brightness(struct led_classdev *led) +{ + struct hid_device *hdev = to_hid_device(led->dev->parent); + struct shield_device *shield_dev = hid_get_drvdata(hdev); + struct thunderstrike *ts; + + ts = container_of(shield_dev, struct thunderstrike, base); + + return ts->led_state; +} + +static void thunderstrike_led_set_brightness(struct led_classdev *led, + enum led_brightness value) +{ + struct hid_device *hdev = to_hid_device(led->dev->parent); + struct shield_device *shield_dev = hid_get_drvdata(hdev); + struct thunderstrike *ts; + + ts = container_of(shield_dev, struct thunderstrike, base); + + switch (value) { + case LED_OFF: + ts->led_value = THUNDERSTRIKE_LED_OFF; + break; + default: + ts->led_value = THUNDERSTRIKE_LED_ON; + break; + } + + set_bit(THUNDERSTRIKE_LED_UPDATE, &ts->update_flags); + schedule_work(&ts->hostcmd_req_work); +} + +static void +thunderstrike_parse_fw_version_payload(struct shield_device *shield_dev, + __le16 fw_version) +{ + shield_dev->fw_version = le16_to_cpu(fw_version); + + set_bit(SHIELD_FW_VERSION_INITIALIZED, &shield_dev->initialized_flags); + + hid_dbg(shield_dev->hdev, "Thunderstrike firmware version 0x%04X\n", + shield_dev->fw_version); +} + +static void +thunderstrike_parse_board_info_payload(struct shield_device *shield_dev, + struct thunderstrike_hostcmd_board_info *board_info) +{ + char board_revision_str[4]; + int i; + + shield_dev->board_info.revision = le16_to_cpu(board_info->revision); + for (i = 0; i < 7; ++i) { + u16 val = le16_to_cpu(board_info->serial[i]); + + shield_dev->board_info.serial_number[2 * i] = val & 0xFF; + shield_dev->board_info.serial_number[2 * i + 1] = val >> 8; + } + shield_dev->board_info.serial_number[14] = '\0'; + + set_bit(SHIELD_BOARD_INFO_INITIALIZED, &shield_dev->initialized_flags); + + shield_strrev(board_revision_str, 4, shield_dev->board_info.revision); + hid_dbg(shield_dev->hdev, + "Thunderstrike BOARD_REVISION_%s (0x%04X) S/N: %s\n", + board_revision_str, shield_dev->board_info.revision, + shield_dev->board_info.serial_number); +} + +static inline void +thunderstrike_parse_haptics_payload(struct shield_device *shield_dev, + struct thunderstrike_hostcmd_haptics *haptics) +{ + hid_dbg(shield_dev->hdev, + "Thunderstrike haptics HOSTCMD response, left: %u right: %u\n", + haptics->motor_left, haptics->motor_right); +} + +static void +thunderstrike_parse_led_payload(struct shield_device *shield_dev, + enum thunderstrike_led_state led_state) +{ + struct thunderstrike *ts = container_of(shield_dev, struct thunderstrike, base); + + switch (led_state) { + case THUNDERSTRIKE_LED_OFF: + ts->led_state = 0; + break; + case THUNDERSTRIKE_LED_ON: + ts->led_state = 1; + break; + } + + hid_dbg(shield_dev->hdev, "Thunderstrike led HOSTCMD response, 0x%02X\n", led_state); +} + +static int thunderstrike_parse_report(struct shield_device *shield_dev, + struct hid_report *report, u8 *data, + int size) +{ + struct thunderstrike_hostcmd_resp_report *hostcmd_resp_report; + struct thunderstrike *ts = + container_of(shield_dev, struct thunderstrike, base); + struct hid_device *hdev = shield_dev->hdev; + + switch (report->id) { + case THUNDERSTRIKE_HOSTCMD_RESP_REPORT_ID: + if (size != THUNDERSTRIKE_HOSTCMD_REPORT_SIZE) { + hid_err(hdev, + "Encountered Thunderstrike HOSTCMD HID report with unexpected size %d\n", + size); + return -EINVAL; + } + + hostcmd_resp_report = + (struct thunderstrike_hostcmd_resp_report *)data; + + switch (hostcmd_resp_report->cmd_id) { + case THUNDERSTRIKE_HOSTCMD_ID_FW_VERSION: + thunderstrike_parse_fw_version_payload( + shield_dev, hostcmd_resp_report->fw_version); + break; + case THUNDERSTRIKE_HOSTCMD_ID_LED: + thunderstrike_parse_led_payload(shield_dev, hostcmd_resp_report->led_state); + break; + case THUNDERSTRIKE_HOSTCMD_ID_BOARD_INFO: + thunderstrike_parse_board_info_payload( + shield_dev, &hostcmd_resp_report->board_info); + break; + case THUNDERSTRIKE_HOSTCMD_ID_HAPTICS: + thunderstrike_parse_haptics_payload( + shield_dev, &hostcmd_resp_report->motors); + break; + + case THUNDERSTRIKE_HOSTCMD_ID_USB_INIT: + case THUNDERSTRIKE_HOSTCMD_ID_BLUETOOTH_INIT: + /* May block HOSTCMD requests till received initially */ + thunderstrike_request_firmware_version(ts); + thunderstrike_request_board_info(ts); + /* Only HOSTCMD that can be triggered without a request */ + return 0; + default: + hid_warn(hdev, + "Unhandled Thunderstrike HOSTCMD id %d\n", + hostcmd_resp_report->cmd_id); + return -ENOENT; + } + + break; + default: + return 0; + } + + return 0; +} + +static inline int thunderstrike_led_create(struct thunderstrike *ts) +{ + struct led_classdev *led = &ts->led_dev; + + led->name = "thunderstrike:blue:led"; + led->max_brightness = 1; + led->flags = LED_CORE_SUSPENDRESUME; + led->brightness_get = &thunderstrike_led_get_brightness; + led->brightness_set = &thunderstrike_led_set_brightness; + + return led_classdev_register(&ts->base.hdev->dev, led); +} + +static struct shield_device *thunderstrike_create(struct hid_device *hdev) +{ + struct shield_device *shield_dev; + struct thunderstrike *ts; + int ret; + + ts = devm_kzalloc(&hdev->dev, sizeof(*ts), GFP_KERNEL); + if (!ts) + return ERR_PTR(-ENOMEM); + + ts->req_report_dmabuf = devm_kzalloc( + &hdev->dev, THUNDERSTRIKE_HOSTCMD_REPORT_SIZE, GFP_KERNEL); + if (!ts->req_report_dmabuf) + return ERR_PTR(-ENOMEM); + + shield_dev = &ts->base; + shield_dev->hdev = hdev; + shield_dev->codename = "Thunderstrike"; + + spin_lock_init(&ts->haptics_update_lock); + INIT_WORK(&ts->hostcmd_req_work, thunderstrike_hostcmd_req_work_handler); + + hid_set_drvdata(hdev, shield_dev); + + ret = thunderstrike_led_create(ts); + if (ret) { + hid_err(hdev, "Failed to create Thunderstrike LED instance\n"); + return ERR_PTR(ret); + } + + ts->haptics_dev = shield_haptics_create(shield_dev, thunderstrike_play_effect); + if (IS_ERR(ts->haptics_dev)) + goto err; + + hid_info(hdev, "Registered Thunderstrike controller\n"); + return shield_dev; + +err: + led_classdev_unregister(&ts->led_dev); + return ERR_CAST(ts->haptics_dev); +} + +static int android_input_mapping(struct hid_device *hdev, struct hid_input *hi, + struct hid_field *field, + struct hid_usage *usage, unsigned long **bit, + int *max) +{ + if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER) + return 0; + + switch (usage->hid & HID_USAGE) { + case HID_USAGE_ANDROID_PLAYPAUSE_BTN: + android_map_key(KEY_PLAYPAUSE); + break; + case HID_USAGE_ANDROID_VOLUMEUP_BTN: + android_map_key(KEY_VOLUMEUP); + break; + case HID_USAGE_ANDROID_VOLUMEDOWN_BTN: + android_map_key(KEY_VOLUMEDOWN); + break; + case HID_USAGE_ANDROID_SEARCH_BTN: + android_map_key(BTN_Z); + break; + case HID_USAGE_ANDROID_HOME_BTN: + android_map_key(BTN_MODE); + break; + case HID_USAGE_ANDROID_BACK_BTN: + android_map_key(BTN_SELECT); + break; + default: + return 0; + } + + return 1; +} + +static ssize_t firmware_version_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct hid_device *hdev = to_hid_device(dev); + struct shield_device *shield_dev; + int ret; + + shield_dev = hid_get_drvdata(hdev); + + if (test_bit(SHIELD_FW_VERSION_INITIALIZED, &shield_dev->initialized_flags)) + ret = sysfs_emit(buf, "0x%04X\n", shield_dev->fw_version); + else + ret = sysfs_emit(buf, NOT_INIT_STR "\n"); + + return ret; +} + +static DEVICE_ATTR_RO(firmware_version); + +static ssize_t hardware_version_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct hid_device *hdev = to_hid_device(dev); + struct shield_device *shield_dev; + char board_revision_str[4]; + int ret; + + shield_dev = hid_get_drvdata(hdev); + + if (test_bit(SHIELD_BOARD_INFO_INITIALIZED, &shield_dev->initialized_flags)) { + shield_strrev(board_revision_str, 4, shield_dev->board_info.revision); + ret = sysfs_emit(buf, "%s BOARD_REVISION_%s (0x%04X)\n", + shield_dev->codename, board_revision_str, + shield_dev->board_info.revision); + } else + ret = sysfs_emit(buf, NOT_INIT_STR "\n"); + + return ret; +} + +static DEVICE_ATTR_RO(hardware_version); + +static ssize_t serial_number_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct hid_device *hdev = to_hid_device(dev); + struct shield_device *shield_dev; + int ret; + + shield_dev = hid_get_drvdata(hdev); + + if (test_bit(SHIELD_BOARD_INFO_INITIALIZED, &shield_dev->initialized_flags)) + ret = sysfs_emit(buf, "%s\n", shield_dev->board_info.serial_number); + else + ret = sysfs_emit(buf, NOT_INIT_STR "\n"); + + return ret; +} + +static DEVICE_ATTR_RO(serial_number); + +static struct attribute *shield_device_attrs[] = { + &dev_attr_firmware_version.attr, + &dev_attr_hardware_version.attr, + &dev_attr_serial_number.attr, + NULL, +}; +ATTRIBUTE_GROUPS(shield_device); + +static int shield_raw_event(struct hid_device *hdev, struct hid_report *report, + u8 *data, int size) +{ + struct shield_device *dev = hid_get_drvdata(hdev); + + return thunderstrike_parse_report(dev, report, data, size); +} + +static int shield_probe(struct hid_device *hdev, const struct hid_device_id *id) +{ + struct shield_device *shield_dev = NULL; + struct thunderstrike *ts; + int ret; + + ret = hid_parse(hdev); + if (ret) { + hid_err(hdev, "Parse failed\n"); + return ret; + } + + switch (id->product) { + case USB_DEVICE_ID_NVIDIA_THUNDERSTRIKE_CONTROLLER: + shield_dev = thunderstrike_create(hdev); + break; + } + + if (unlikely(!shield_dev)) { + hid_err(hdev, "Failed to identify SHIELD device\n"); + return -ENODEV; + } + if (IS_ERR(shield_dev)) { + hid_err(hdev, "Failed to create SHIELD device\n"); + return PTR_ERR(shield_dev); + } + + ts = container_of(shield_dev, struct thunderstrike, base); + + ret = hid_hw_start(hdev, HID_CONNECT_HIDINPUT); + if (ret) { + hid_err(hdev, "Failed to start HID device\n"); + goto err_haptics; + } + + ret = hid_hw_open(hdev); + if (ret) { + hid_err(hdev, "Failed to open HID device\n"); + goto err_stop; + } + + thunderstrike_request_firmware_version(ts); + thunderstrike_request_board_info(ts); + + return ret; + +err_stop: + hid_hw_stop(hdev); +err_haptics: + if (ts->haptics_dev) + input_unregister_device(ts->haptics_dev); + return ret; +} + +static void shield_remove(struct hid_device *hdev) +{ + struct shield_device *dev = hid_get_drvdata(hdev); + struct thunderstrike *ts; + + ts = container_of(dev, struct thunderstrike, base); + + hid_hw_close(hdev); + led_classdev_unregister(&ts->led_dev); + if (ts->haptics_dev) + input_unregister_device(ts->haptics_dev); + cancel_work_sync(&ts->hostcmd_req_work); + hid_hw_stop(hdev); +} + +static const struct hid_device_id shield_devices[] = { + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_NVIDIA, + USB_DEVICE_ID_NVIDIA_THUNDERSTRIKE_CONTROLLER) }, + { HID_USB_DEVICE(USB_VENDOR_ID_NVIDIA, + USB_DEVICE_ID_NVIDIA_THUNDERSTRIKE_CONTROLLER) }, + { } +}; +MODULE_DEVICE_TABLE(hid, shield_devices); + +static struct hid_driver shield_driver = { + .name = "shield", + .id_table = shield_devices, + .input_mapping = android_input_mapping, + .probe = shield_probe, + .remove = shield_remove, + .raw_event = shield_raw_event, + .driver = { + .dev_groups = shield_device_groups, + }, +}; +module_hid_driver(shield_driver); + +MODULE_AUTHOR("Rahul Rameshbabu "); +MODULE_DESCRIPTION("HID Driver for NVIDIA SHIELD peripherals."); +MODULE_LICENSE("GPL"); diff --git a/drivers/hid/hid-quirks.c b/drivers/hid/hid-quirks.c index 804fc03600cc9c2964ede6626a4084380feab363..3983b4f282f8f8cfd0e169bc529e89ac9a89b0c9 100644 --- a/drivers/hid/hid-quirks.c +++ b/drivers/hid/hid-quirks.c @@ -96,6 +96,7 @@ static const struct hid_device_id hid_quirks[] = { { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_KEYBOARD_A096), HID_QUIRK_NO_INIT_REPORTS }, { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_KEYBOARD_A293), HID_QUIRK_ALWAYS_POLL }, { HID_USB_DEVICE(USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_LOGITECH_OEM_USB_OPTICAL_MOUSE_0A4A), HID_QUIRK_ALWAYS_POLL }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_ELITE_PRESENTER_MOUSE_464A), HID_QUIRK_MULTI_INPUT }, { HID_USB_DEVICE(USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_LOGITECH_OEM_USB_OPTICAL_MOUSE_0B4A), HID_QUIRK_ALWAYS_POLL }, { HID_USB_DEVICE(USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_PIXART_OEM_USB_OPTICAL_MOUSE), HID_QUIRK_ALWAYS_POLL }, { HID_USB_DEVICE(USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_PIXART_OEM_USB_OPTICAL_MOUSE_094A), HID_QUIRK_ALWAYS_POLL }, diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c index 93e62b161501cca7afaee1af80d86a58962968ed..e63c56a0d57fb43281c61e7b40816d5caff89702 100644 --- a/drivers/hid/hidraw.c +++ b/drivers/hid/hidraw.c @@ -272,7 +272,12 @@ static int hidraw_open(struct inode *inode, struct file *file) goto out; } - down_read(&minors_rwsem); + /* + * Technically not writing to the hidraw_table but a write lock is + * required to protect the device refcount. This is symmetrical to + * hidraw_release(). + */ + down_write(&minors_rwsem); if (!hidraw_table[minor] || !hidraw_table[minor]->exist) { err = -ENODEV; goto out_unlock; @@ -301,7 +306,7 @@ static int hidraw_open(struct inode *inode, struct file *file) spin_unlock_irqrestore(&hidraw_table[minor]->list_lock, flags); file->private_data = list; out_unlock: - up_read(&minors_rwsem); + up_write(&minors_rwsem); out: if (err < 0) kfree(list); diff --git a/drivers/hid/i2c-hid/i2c-hid-acpi.c b/drivers/hid/i2c-hid/i2c-hid-acpi.c index 3a7e2bcb5412044339107c15042521c0a3c89408..ac918a9ea8d34440df8ad9c6a009d60a4ffdbbf0 100644 --- a/drivers/hid/i2c-hid/i2c-hid-acpi.c +++ b/drivers/hid/i2c-hid/i2c-hid-acpi.c @@ -118,7 +118,7 @@ static struct i2c_driver i2c_hid_acpi_driver = { .acpi_match_table = i2c_hid_acpi_match, }, - .probe_new = i2c_hid_acpi_probe, + .probe = i2c_hid_acpi_probe, .remove = i2c_hid_core_remove, .shutdown = i2c_hid_core_shutdown, }; diff --git a/drivers/hid/i2c-hid/i2c-hid-of-elan.c b/drivers/hid/i2c-hid/i2c-hid-of-elan.c index 76ddc8be1cbbc6c853fec5c292bf9af57e8c32a9..029045d9661c6e23b1f5a9ba0caaf67a5c9a5372 100644 --- a/drivers/hid/i2c-hid/i2c-hid-of-elan.c +++ b/drivers/hid/i2c-hid/i2c-hid-of-elan.c @@ -118,7 +118,7 @@ static struct i2c_driver elan_i2c_hid_ts_driver = { .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = of_match_ptr(elan_i2c_hid_of_match), }, - .probe_new = i2c_hid_of_elan_probe, + .probe = i2c_hid_of_elan_probe, .remove = i2c_hid_core_remove, .shutdown = i2c_hid_core_shutdown, }; diff --git a/drivers/hid/i2c-hid/i2c-hid-of-goodix.c b/drivers/hid/i2c-hid/i2c-hid-of-goodix.c index 0060e3dcd775d8fe081c7df4ecf34d3ff557bf20..f1597ad67e7c8a8d3c5799d11b9d0a206c95be7b 100644 --- a/drivers/hid/i2c-hid/i2c-hid-of-goodix.c +++ b/drivers/hid/i2c-hid/i2c-hid-of-goodix.c @@ -28,6 +28,7 @@ struct i2c_hid_of_goodix { struct regulator *vdd; struct regulator *vddio; struct gpio_desc *reset_gpio; + bool no_reset_during_suspend; const struct goodix_i2c_hid_timing_data *timings; }; @@ -37,6 +38,14 @@ static int goodix_i2c_hid_power_up(struct i2chid_ops *ops) container_of(ops, struct i2c_hid_of_goodix, ops); int ret; + /* + * We assert reset GPIO here (instead of during power-down) to ensure + * the device will have a clean state after powering up, just like the + * normal scenarios will have. + */ + if (ihid_goodix->no_reset_during_suspend) + gpiod_set_value_cansleep(ihid_goodix->reset_gpio, 1); + ret = regulator_enable(ihid_goodix->vdd); if (ret) return ret; @@ -60,7 +69,9 @@ static void goodix_i2c_hid_power_down(struct i2chid_ops *ops) struct i2c_hid_of_goodix *ihid_goodix = container_of(ops, struct i2c_hid_of_goodix, ops); - gpiod_set_value_cansleep(ihid_goodix->reset_gpio, 1); + if (!ihid_goodix->no_reset_during_suspend) + gpiod_set_value_cansleep(ihid_goodix->reset_gpio, 1); + regulator_disable(ihid_goodix->vddio); regulator_disable(ihid_goodix->vdd); } @@ -91,6 +102,9 @@ static int i2c_hid_of_goodix_probe(struct i2c_client *client) if (IS_ERR(ihid_goodix->vddio)) return PTR_ERR(ihid_goodix->vddio); + ihid_goodix->no_reset_during_suspend = + of_property_read_bool(client->dev.of_node, "goodix,no-reset-during-suspend"); + ihid_goodix->timings = device_get_match_data(&client->dev); return i2c_hid_core_probe(client, &ihid_goodix->ops, 0x0001, 0); @@ -114,7 +128,7 @@ static struct i2c_driver goodix_i2c_hid_ts_driver = { .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = of_match_ptr(goodix_i2c_hid_of_match), }, - .probe_new = i2c_hid_of_goodix_probe, + .probe = i2c_hid_of_goodix_probe, .remove = i2c_hid_core_remove, .shutdown = i2c_hid_core_shutdown, }; diff --git a/drivers/hid/i2c-hid/i2c-hid-of.c b/drivers/hid/i2c-hid/i2c-hid-of.c index 855f53092f4e37b34fd94c04224cdafb8febdb4a..c4e1fa0273c84c3b2e3b438e04673727b05e6f6e 100644 --- a/drivers/hid/i2c-hid/i2c-hid-of.c +++ b/drivers/hid/i2c-hid/i2c-hid-of.c @@ -157,7 +157,7 @@ static struct i2c_driver i2c_hid_of_driver = { .of_match_table = of_match_ptr(i2c_hid_of_match), }, - .probe_new = i2c_hid_of_probe, + .probe = i2c_hid_of_probe, .remove = i2c_hid_core_remove, .shutdown = i2c_hid_core_shutdown, .id_table = i2c_hid_of_id_table, diff --git a/drivers/hid/intel-ish-hid/ipc/hw-ish.h b/drivers/hid/intel-ish-hid/ipc/hw-ish.h index fc108f19a64c3e15ab1c48338d820cf7fd470df5..e99f3a3c65e1559a8828c3b75435bdb2264fddbd 100644 --- a/drivers/hid/intel-ish-hid/ipc/hw-ish.h +++ b/drivers/hid/intel-ish-hid/ipc/hw-ish.h @@ -33,6 +33,7 @@ #define ADL_N_DEVICE_ID 0x54FC #define RPL_S_DEVICE_ID 0x7A78 #define MTL_P_DEVICE_ID 0x7E45 +#define ARL_H_DEVICE_ID 0x7745 #define REVISION_ID_CHT_A0 0x6 #define REVISION_ID_CHT_Ax_SI 0x0 diff --git a/drivers/hid/intel-ish-hid/ipc/pci-ish.c b/drivers/hid/intel-ish-hid/ipc/pci-ish.c index 7120b30ac51d063769759bbbf6ad5e1565557d2e..55cb25038e632bcfa962612fcd89b974a9bb8554 100644 --- a/drivers/hid/intel-ish-hid/ipc/pci-ish.c +++ b/drivers/hid/intel-ish-hid/ipc/pci-ish.c @@ -44,6 +44,7 @@ static const struct pci_device_id ish_pci_tbl[] = { {PCI_DEVICE(PCI_VENDOR_ID_INTEL, ADL_N_DEVICE_ID)}, {PCI_DEVICE(PCI_VENDOR_ID_INTEL, RPL_S_DEVICE_ID)}, {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MTL_P_DEVICE_ID)}, + {PCI_DEVICE(PCI_VENDOR_ID_INTEL, ARL_H_DEVICE_ID)}, {0, } }; MODULE_DEVICE_TABLE(pci, ish_pci_tbl); diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index 2ccf838371343da1628bec555896caba7843d2eb..174bf03908d7c4d108bfeb0c6c494bd3d4cfe93f 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -1314,7 +1314,7 @@ static void wacom_intuos_pro2_bt_pen(struct wacom_wac *wacom) struct input_dev *pen_input = wacom->pen_input; unsigned char *data = wacom->data; int number_of_valid_frames = 0; - int time_interval = 15000000; + ktime_t time_interval = 15000000; ktime_t time_packet_received = ktime_get(); int i; @@ -1348,7 +1348,7 @@ static void wacom_intuos_pro2_bt_pen(struct wacom_wac *wacom) if (number_of_valid_frames) { if (wacom->hid_data.time_delayed) time_interval = ktime_get() - wacom->hid_data.time_delayed; - time_interval /= number_of_valid_frames; + time_interval = div_u64(time_interval, number_of_valid_frames); wacom->hid_data.time_delayed = time_packet_received; } @@ -1359,7 +1359,7 @@ static void wacom_intuos_pro2_bt_pen(struct wacom_wac *wacom) bool range = frame[0] & 0x20; bool invert = frame[0] & 0x10; int frames_number_reversed = number_of_valid_frames - i - 1; - int event_timestamp = time_packet_received - frames_number_reversed * time_interval; + ktime_t event_timestamp = time_packet_received - frames_number_reversed * time_interval; if (!valid) continue; diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h index 1a40bb8c5810ce560e2da9e4bfac1fa3c186938f..ee21bb260f22f83b85ff1ea66659595aa69d92bd 100644 --- a/drivers/hid/wacom_wac.h +++ b/drivers/hid/wacom_wac.h @@ -324,7 +324,7 @@ struct hid_data { int ps_connected; bool pad_input_event_flag; unsigned short sequence_number; - int time_delayed; + ktime_t time_delayed; }; struct wacom_remote_data { diff --git a/drivers/hsi/clients/ssi_protocol.c b/drivers/hsi/clients/ssi_protocol.c index 38e572faff4357808d80df9cf25571651337deb6..da6a7abd584f7fb51c11c7fc75f03a832d363935 100644 --- a/drivers/hsi/clients/ssi_protocol.c +++ b/drivers/hsi/clients/ssi_protocol.c @@ -32,8 +32,6 @@ #include #include -void ssi_waketest(struct hsi_client *cl, unsigned int enable); - #define SSIP_TXQUEUE_LEN 100 #define SSIP_MAX_MTU 65535 #define SSIP_DEFAULT_MTU 4000 diff --git a/drivers/hsi/controllers/omap_ssi_core.c b/drivers/hsi/controllers/omap_ssi_core.c index 26f2c3c0129783e045e7d26243a9a1493e81d976..84ba8b875199617111d30256972ba1e5b06c2829 100644 --- a/drivers/hsi/controllers/omap_ssi_core.c +++ b/drivers/hsi/controllers/omap_ssi_core.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include diff --git a/drivers/hsi/controllers/omap_ssi_port.c b/drivers/hsi/controllers/omap_ssi_port.c index b9495b720f1bd121970deaf4f151a517c27b33d4..c78d9c9f73712c9e8bfee0718115eb87fdacf509 100644 --- a/drivers/hsi/controllers/omap_ssi_port.c +++ b/drivers/hsi/controllers/omap_ssi_port.c @@ -151,23 +151,17 @@ static int ssi_div_set(void *data, u64 val) DEFINE_DEBUGFS_ATTRIBUTE(ssi_sst_div_fops, ssi_div_get, ssi_div_set, "%llu\n"); -static int ssi_debug_add_port(struct omap_ssi_port *omap_port, +static void ssi_debug_add_port(struct omap_ssi_port *omap_port, struct dentry *dir) { struct hsi_port *port = to_hsi_port(omap_port->dev); dir = debugfs_create_dir(dev_name(omap_port->dev), dir); - if (!dir) - return -ENOMEM; omap_port->dir = dir; debugfs_create_file("regs", S_IRUGO, dir, port, &ssi_port_regs_fops); dir = debugfs_create_dir("sst", dir); - if (!dir) - return -ENOMEM; debugfs_create_file_unsafe("divisor", 0644, dir, port, &ssi_sst_div_fops); - - return 0; } #endif @@ -1217,11 +1211,7 @@ static int ssi_port_probe(struct platform_device *pd) pm_runtime_enable(omap_port->pdev); #ifdef CONFIG_DEBUG_FS - err = ssi_debug_add_port(omap_port, omap_ssi->dir); - if (err < 0) { - pm_runtime_disable(omap_port->pdev); - goto error; - } + ssi_debug_add_port(omap_port, omap_ssi->dir); #endif hsi_add_clients_from_dt(port, np); diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c index 007f26d5f1a45214710559af9529f88fc878ab68..2f4d09ce027a3f6b07132da55c6b31cdbbfaf25b 100644 --- a/drivers/hv/channel_mgmt.c +++ b/drivers/hv/channel_mgmt.c @@ -829,11 +829,22 @@ static void vmbus_wait_for_unload(void) if (completion_done(&vmbus_connection.unload_event)) goto completed; - for_each_online_cpu(cpu) { + for_each_present_cpu(cpu) { struct hv_per_cpu_context *hv_cpu = per_cpu_ptr(hv_context.cpu_context, cpu); + /* + * In a CoCo VM the synic_message_page is not allocated + * in hv_synic_alloc(). Instead it is set/cleared in + * hv_synic_enable_regs() and hv_synic_disable_regs() + * such that it is set only when the CPU is online. If + * not all present CPUs are online, the message page + * might be NULL, so skip such CPUs. + */ page_addr = hv_cpu->synic_message_page; + if (!page_addr) + continue; + msg = (struct hv_message *)page_addr + VMBUS_MESSAGE_SINT; @@ -867,11 +878,14 @@ static void vmbus_wait_for_unload(void) * maybe-pending messages on all CPUs to be able to receive new * messages after we reconnect. */ - for_each_online_cpu(cpu) { + for_each_present_cpu(cpu) { struct hv_per_cpu_context *hv_cpu = per_cpu_ptr(hv_context.cpu_context, cpu); page_addr = hv_cpu->synic_message_page; + if (!page_addr) + continue; + msg = (struct hv_message *)page_addr + VMBUS_MESSAGE_SINT; msg->header.message_type = HVMSG_NONE; } diff --git a/drivers/hv/hv_common.c b/drivers/hv/hv_common.c index 64f9ceca887b9ea628489d0625d2e87f90cf698d..542a1d53b303e295f026a46d7cd2bab7ee4e206d 100644 --- a/drivers/hv/hv_common.c +++ b/drivers/hv/hv_common.c @@ -364,13 +364,20 @@ int hv_common_cpu_init(unsigned int cpu) flags = irqs_disabled() ? GFP_ATOMIC : GFP_KERNEL; inputarg = (void **)this_cpu_ptr(hyperv_pcpu_input_arg); - *inputarg = kmalloc(pgcount * HV_HYP_PAGE_SIZE, flags); - if (!(*inputarg)) - return -ENOMEM; - if (hv_root_partition) { - outputarg = (void **)this_cpu_ptr(hyperv_pcpu_output_arg); - *outputarg = (char *)(*inputarg) + HV_HYP_PAGE_SIZE; + /* + * hyperv_pcpu_input_arg and hyperv_pcpu_output_arg memory is already + * allocated if this CPU was previously online and then taken offline + */ + if (!*inputarg) { + *inputarg = kmalloc(pgcount * HV_HYP_PAGE_SIZE, flags); + if (!(*inputarg)) + return -ENOMEM; + + if (hv_root_partition) { + outputarg = (void **)this_cpu_ptr(hyperv_pcpu_output_arg); + *outputarg = (char *)(*inputarg) + HV_HYP_PAGE_SIZE; + } } msr_vp_index = hv_get_register(HV_REGISTER_VP_INDEX); @@ -385,24 +392,17 @@ int hv_common_cpu_init(unsigned int cpu) int hv_common_cpu_die(unsigned int cpu) { - unsigned long flags; - void **inputarg, **outputarg; - void *mem; - - local_irq_save(flags); - - inputarg = (void **)this_cpu_ptr(hyperv_pcpu_input_arg); - mem = *inputarg; - *inputarg = NULL; - - if (hv_root_partition) { - outputarg = (void **)this_cpu_ptr(hyperv_pcpu_output_arg); - *outputarg = NULL; - } - - local_irq_restore(flags); - - kfree(mem); + /* + * The hyperv_pcpu_input_arg and hyperv_pcpu_output_arg memory + * is not freed when the CPU goes offline as the hyperv_pcpu_input_arg + * may be used by the Hyper-V vPCI driver in reassigning interrupts + * as part of the offlining process. The interrupt reassignment + * happens *after* the CPUHP_AP_HYPERV_ONLINE state has run and + * called this function. + * + * If a previously offlined CPU is brought back online again, the + * originally allocated memory is reused in hv_common_cpu_init(). + */ return 0; } diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c index 1c65a6dfb9fae58c4cd29c7f6f028776caf54e9c..67f95a29aeca5b8e0b7f3755448724f4c7e726fb 100644 --- a/drivers/hv/vmbus_drv.c +++ b/drivers/hv/vmbus_drv.c @@ -1372,7 +1372,7 @@ static int vmbus_bus_init(void) ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "hyperv/vmbus:online", hv_synic_init, hv_synic_cleanup); if (ret < 0) - goto err_cpuhp; + goto err_alloc; hyperv_cpuhp_online = ret; ret = vmbus_connect(); @@ -1392,9 +1392,8 @@ static int vmbus_bus_init(void) err_connect: cpuhp_remove_state(hyperv_cpuhp_online); -err_cpuhp: - hv_synic_free(); err_alloc: + hv_synic_free(); if (vmbus_irq == -1) { hv_remove_vmbus_handler(); } else { diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index fc640201a2dea31b81dff388e9df5c841352076e..307477b8a371bdf76560b058bb993ae29ec357d6 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -255,10 +255,11 @@ config SENSORS_ADT7475 will be called adt7475. config SENSORS_AHT10 - tristate "Aosong AHT10" + tristate "Aosong AHT10, AHT20" depends on I2C + select CRC8 help - If you say yes here, you get support for the Aosong AHT10 + If you say yes here, you get support for the Aosong AHT10 and AHT20 temperature and humidity sensors This driver can also be built as a module. If so, the module @@ -1097,6 +1098,17 @@ config SENSORS_MAX31760 This driver can also be built as a module. If so, the module will be called max31760. +config MAX31827 + tristate "MAX31827 low-power temperature switch and similar devices" + depends on I2C + select REGMAP_I2C + help + If you say yes here you get support for MAX31827, MAX31828 and + MAX31829 low-power temperature switches and sensors connected with I2C. + + This driver can also be built as a module. If so, the module + will be called max31827. + config SENSORS_MAX6620 tristate "Maxim MAX6620 fan controller" depends on I2C @@ -2409,6 +2421,18 @@ config SENSORS_ASUS_EC This driver can also be built as a module. If so, the module will be called asus_ec_sensors. +config SENSORS_HP_WMI + tristate "HP WMI Sensors" + depends on ACPI_WMI + help + If you say yes here you get support for the ACPI hardware monitoring + interface found in HP (and some HP Compaq) business-class computers. + Available sensors vary between systems. Temperature and fan speed + sensors are the most common. + + This driver can also be built as a module. If so, the module + will be called hp_wmi_sensors. + endif # ACPI endif # HWMON diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index cd8c568c80a9bc09fe6989aef7662db691193a04..3f4b0fda099800de2167bbd8f20c47ef6f66e508 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile @@ -11,6 +11,7 @@ obj-$(CONFIG_SENSORS_ACPI_POWER) += acpi_power_meter.o obj-$(CONFIG_SENSORS_ATK0110) += asus_atk0110.o obj-$(CONFIG_SENSORS_ASUS_EC) += asus-ec-sensors.o obj-$(CONFIG_SENSORS_ASUS_WMI) += asus_wmi_sensors.o +obj-$(CONFIG_SENSORS_HP_WMI) += hp-wmi-sensors.o # Native drivers # asb100, then w83781d go first, as they can override other drivers' addresses. @@ -149,6 +150,7 @@ obj-$(CONFIG_SENSORS_MAX6642) += max6642.o obj-$(CONFIG_SENSORS_MAX6650) += max6650.o obj-$(CONFIG_SENSORS_MAX6697) += max6697.o obj-$(CONFIG_SENSORS_MAX31790) += max31790.o +obj-$(CONFIG_MAX31827) += max31827.o obj-$(CONFIG_SENSORS_MC13783_ADC)+= mc13783-adc.o obj-$(CONFIG_SENSORS_MC34VR500) += mc34vr500.o obj-$(CONFIG_SENSORS_MCP3021) += mcp3021.o @@ -224,4 +226,3 @@ obj-$(CONFIG_SENSORS_PECI) += peci/ obj-$(CONFIG_PMBUS) += pmbus/ ccflags-$(CONFIG_HWMON_DEBUG_CHIP) := -DDEBUG - diff --git a/drivers/hwmon/ad7414.c b/drivers/hwmon/ad7414.c index 0afb89c4629db8f52a55a3e59f8cb0a80d2b960b..7f1bef59046f09b8989f286519194615ea032ab9 100644 --- a/drivers/hwmon/ad7414.c +++ b/drivers/hwmon/ad7414.c @@ -221,7 +221,7 @@ static struct i2c_driver ad7414_driver = { .name = "ad7414", .of_match_table = of_match_ptr(ad7414_of_match), }, - .probe_new = ad7414_probe, + .probe = ad7414_probe, .id_table = ad7414_id, }; diff --git a/drivers/hwmon/ad7418.c b/drivers/hwmon/ad7418.c index 22bdb7e5b9e0344091c345ed4b458a3de9727c18..ffe81e445010a8a1924249281b91bed752afc907 100644 --- a/drivers/hwmon/ad7418.c +++ b/drivers/hwmon/ad7418.c @@ -306,7 +306,7 @@ static struct i2c_driver ad7418_driver = { .name = "ad7418", .of_match_table = ad7418_dt_ids, }, - .probe_new = ad7418_probe, + .probe = ad7418_probe, .id_table = ad7418_id, }; diff --git a/drivers/hwmon/adc128d818.c b/drivers/hwmon/adc128d818.c index 97b330b6c165c0fa5f6cfe9e906a3804bd13c154..46e3c8c507657366a9377e23d1f73fbb2b152ceb 100644 --- a/drivers/hwmon/adc128d818.c +++ b/drivers/hwmon/adc128d818.c @@ -521,7 +521,7 @@ static struct i2c_driver adc128_driver = { .name = "adc128d818", .of_match_table = of_match_ptr(adc128_of_match), }, - .probe_new = adc128_probe, + .probe = adc128_probe, .remove = adc128_remove, .id_table = adc128_id, .detect = adc128_detect, diff --git a/drivers/hwmon/adm1021.c b/drivers/hwmon/adm1021.c index 2dc45e958730e6d0a9557d4dc8ad5682df15deb0..7c15398ebb378e4abbe769c71a060c08461846c4 100644 --- a/drivers/hwmon/adm1021.c +++ b/drivers/hwmon/adm1021.c @@ -488,7 +488,7 @@ static struct i2c_driver adm1021_driver = { .driver = { .name = "adm1021", }, - .probe_new = adm1021_probe, + .probe = adm1021_probe, .id_table = adm1021_id, .detect = adm1021_detect, .address_list = normal_i2c, diff --git a/drivers/hwmon/adm1025.c b/drivers/hwmon/adm1025.c index 2984c4f98496fe41a0681319d1e0b73a45592489..389382d54752e4b1b3bc687706aae0cba4046f4f 100644 --- a/drivers/hwmon/adm1025.c +++ b/drivers/hwmon/adm1025.c @@ -559,7 +559,7 @@ static struct i2c_driver adm1025_driver = { .driver = { .name = "adm1025", }, - .probe_new = adm1025_probe, + .probe = adm1025_probe, .id_table = adm1025_id, .detect = adm1025_detect, .address_list = normal_i2c, diff --git a/drivers/hwmon/adm1026.c b/drivers/hwmon/adm1026.c index 1f084f7087435decd1095a834e03bce61945acc9..581d8edf70ea4e1720f9cfe25ea70a0e42cef1b7 100644 --- a/drivers/hwmon/adm1026.c +++ b/drivers/hwmon/adm1026.c @@ -1859,7 +1859,7 @@ static struct i2c_driver adm1026_driver = { .driver = { .name = "adm1026", }, - .probe_new = adm1026_probe, + .probe = adm1026_probe, .id_table = adm1026_id, .detect = adm1026_detect, .address_list = normal_i2c, diff --git a/drivers/hwmon/adm1029.c b/drivers/hwmon/adm1029.c index eaf6e5e04aac13ec46d82915f359c6c9ecf0519c..9a465f3f71c863aa7748f20ec3ff895d157ee51b 100644 --- a/drivers/hwmon/adm1029.c +++ b/drivers/hwmon/adm1029.c @@ -389,7 +389,7 @@ static struct i2c_driver adm1029_driver = { .driver = { .name = "adm1029", }, - .probe_new = adm1029_probe, + .probe = adm1029_probe, .id_table = adm1029_id, .detect = adm1029_detect, .address_list = normal_i2c, diff --git a/drivers/hwmon/adm1031.c b/drivers/hwmon/adm1031.c index b42797bcb5b479ed22fa9089299f4fb7e36ba240..88c7e0d62d089db9e579d4ab951c0dd31cf25790 100644 --- a/drivers/hwmon/adm1031.c +++ b/drivers/hwmon/adm1031.c @@ -1068,7 +1068,7 @@ static struct i2c_driver adm1031_driver = { .driver = { .name = "adm1031", }, - .probe_new = adm1031_probe, + .probe = adm1031_probe, .id_table = adm1031_id, .detect = adm1031_detect, .address_list = normal_i2c, diff --git a/drivers/hwmon/adm1177.c b/drivers/hwmon/adm1177.c index bfe070a1b501c4cfa2384a812e1a404ee0caa9d2..60a893f271597bc57b919983b4752a65b6cc443b 100644 --- a/drivers/hwmon/adm1177.c +++ b/drivers/hwmon/adm1177.c @@ -255,7 +255,7 @@ static struct i2c_driver adm1177_driver = { .name = "adm1177", .of_match_table = adm1177_dt_ids, }, - .probe_new = adm1177_probe, + .probe = adm1177_probe, .id_table = adm1177_id, }; module_i2c_driver(adm1177_driver); diff --git a/drivers/hwmon/adm9240.c b/drivers/hwmon/adm9240.c index 9eb973a38e4b27474a9dce6d9dc23829e37f5831..6dfbeb6acf00608a214b9b3a925bd16086117859 100644 --- a/drivers/hwmon/adm9240.c +++ b/drivers/hwmon/adm9240.c @@ -819,7 +819,7 @@ static struct i2c_driver adm9240_driver = { .driver = { .name = "adm9240", }, - .probe_new = adm9240_probe, + .probe = adm9240_probe, .id_table = adm9240_id, .detect = adm9240_detect, .address_list = normal_i2c, diff --git a/drivers/hwmon/ads7828.c b/drivers/hwmon/ads7828.c index 7246198f09013a95ab675d3a2300cf50af490c87..1932613ec0953f90183c8bfc47f568ab80e7d5d1 100644 --- a/drivers/hwmon/ads7828.c +++ b/drivers/hwmon/ads7828.c @@ -208,7 +208,7 @@ static struct i2c_driver ads7828_driver = { }, .id_table = ads7828_device_ids, - .probe_new = ads7828_probe, + .probe = ads7828_probe, }; module_i2c_driver(ads7828_driver); diff --git a/drivers/hwmon/adt7410.c b/drivers/hwmon/adt7410.c index 0cebf6777239eb3e0c090f5b2c01e44032e16b87..95250677933650bae438b937d3e0b3fa6feb315d 100644 --- a/drivers/hwmon/adt7410.c +++ b/drivers/hwmon/adt7410.c @@ -100,7 +100,7 @@ static struct i2c_driver adt7410_driver = { .name = "adt7410", .pm = pm_sleep_ptr(&adt7x10_dev_pm_ops), }, - .probe_new = adt7410_i2c_probe, + .probe = adt7410_i2c_probe, .id_table = adt7410_ids, .address_list = I2C_ADDRS(0x48, 0x49, 0x4a, 0x4b), }; diff --git a/drivers/hwmon/adt7411.c b/drivers/hwmon/adt7411.c index 6ba84921614fa044b735b9adc9d9e84d1ccf2bdb..45fe4e8aae4e2509114ef96b1a3d47a83dc705b4 100644 --- a/drivers/hwmon/adt7411.c +++ b/drivers/hwmon/adt7411.c @@ -706,7 +706,7 @@ static struct i2c_driver adt7411_driver = { .driver = { .name = "adt7411", }, - .probe_new = adt7411_probe, + .probe = adt7411_probe, .id_table = adt7411_id, .detect = adt7411_detect, .address_list = normal_i2c, diff --git a/drivers/hwmon/adt7462.c b/drivers/hwmon/adt7462.c index 9c0235849d4b6882ff85c1a245a40321853f9642..429566c4245d08352600d8aaca1c7b2127cf69d5 100644 --- a/drivers/hwmon/adt7462.c +++ b/drivers/hwmon/adt7462.c @@ -1819,7 +1819,7 @@ static struct i2c_driver adt7462_driver = { .driver = { .name = "adt7462", }, - .probe_new = adt7462_probe, + .probe = adt7462_probe, .id_table = adt7462_id, .detect = adt7462_detect, .address_list = normal_i2c, diff --git a/drivers/hwmon/adt7470.c b/drivers/hwmon/adt7470.c index 64f801b859ff604205d923a8ad0ed3b970051e17..c4b3a4a18670c1a62edef572468c45466551c0f1 100644 --- a/drivers/hwmon/adt7470.c +++ b/drivers/hwmon/adt7470.c @@ -1314,7 +1314,7 @@ static struct i2c_driver adt7470_driver = { .driver = { .name = "adt7470", }, - .probe_new = adt7470_probe, + .probe = adt7470_probe, .remove = adt7470_remove, .id_table = adt7470_id, .detect = adt7470_detect, diff --git a/drivers/hwmon/adt7475.c b/drivers/hwmon/adt7475.c index 6a6ebcc896b1d1da514995053569535aa26aed9a..c0ce88324ea6e69b0a2da563f824e7b6a536d4d8 100644 --- a/drivers/hwmon/adt7475.c +++ b/drivers/hwmon/adt7475.c @@ -1468,7 +1468,7 @@ static int load_config3(const struct i2c_client *client, const char *propname) u8 config3; int ret; - ret = of_property_read_string(client->dev.of_node, propname, &function); + ret = device_property_read_string(&client->dev, propname, &function); if (!ret) { ret = adt7475_read(REG_CONFIG3); if (ret < 0) @@ -1494,7 +1494,7 @@ static int load_config4(const struct i2c_client *client, const char *propname) u8 config4; int ret; - ret = of_property_read_string(client->dev.of_node, propname, &function); + ret = device_property_read_string(&client->dev, propname, &function); if (!ret) { ret = adt7475_read(REG_CONFIG4); if (ret < 0) @@ -1556,8 +1556,8 @@ static int set_property_bit(const struct i2c_client *client, char *property, u8 *config, u8 bit_index) { u32 prop_value = 0; - int ret = of_property_read_u32(client->dev.of_node, property, - &prop_value); + int ret = device_property_read_u32(&client->dev, property, + &prop_value); if (!ret) { if (prop_value) @@ -1821,7 +1821,7 @@ static struct i2c_driver adt7475_driver = { .name = "adt7475", .of_match_table = of_match_ptr(adt7475_of_match), }, - .probe_new = adt7475_probe, + .probe = adt7475_probe, .id_table = adt7475_id, .detect = adt7475_detect, .address_list = normal_i2c, diff --git a/drivers/hwmon/aht10.c b/drivers/hwmon/aht10.c index b8fe3f7248bafdcda00554f956c963fc4fbf1cae..f136bf3ff40adf377f721f789b5eec8172aecbb2 100644 --- a/drivers/hwmon/aht10.c +++ b/drivers/hwmon/aht10.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * aht10.c - Linux hwmon driver for AHT10 Temperature and Humidity sensor + * aht10.c - Linux hwmon driver for AHT10/AHT20 Temperature and Humidity sensors * Copyright (C) 2020 Johannes Cornelis Draaijer */ @@ -10,9 +10,13 @@ #include #include #include +#include #define AHT10_MEAS_SIZE 6 +#define AHT20_MEAS_SIZE 7 +#define AHT20_CRC8_POLY 0x31 + /* * Poll intervals (in milliseconds) */ @@ -44,9 +48,18 @@ #define AHT10_MAX_POLL_INTERVAL_LEN 30 +enum aht10_variant { aht10, aht20 }; + +static const struct i2c_device_id aht10_id[] = { + { "aht10", aht10 }, + { "aht20", aht20 }, + { }, +}; +MODULE_DEVICE_TABLE(i2c, aht10_id); + /** - * struct aht10_data - All the data required to operate an AHT10 chip - * @client: the i2c client associated with the AHT10 + * struct aht10_data - All the data required to operate an AHT10/AHT20 chip + * @client: the i2c client associated with the AHT10/AHT20 * @lock: a mutex that is used to prevent parallel access to the * i2c client * @min_poll_interval: the minimum poll interval @@ -56,12 +69,14 @@ * the chip from warming up due to the heat it generates. * If it's unwanted, it can be ignored setting it to * it to 0. Default value is 2000 ms - * @previous_poll_time: the previous time that the AHT10 + * @previous_poll_time: the previous time that the AHT10/AHT20 * was polled * @temperature: the latest temperature value received from - * the AHT10 + * the AHT10/AHT20 * @humidity: the latest humidity value received from the - * AHT10 + * AHT10/AHT20 + * @crc8: crc8 support flag + * @meas_size: measurements data size */ struct aht10_data { @@ -75,12 +90,14 @@ struct aht10_data { ktime_t previous_poll_time; int temperature; int humidity; + bool crc8; + unsigned int meas_size; }; /** - * aht10_init() - Initialize an AHT10 chip - * @data: the data associated with this AHT10 chip - * Return: 0 if succesfull, 1 if not + * aht10_init() - Initialize an AHT10/AHT20 chip + * @data: the data associated with this AHT10/AHT20 chip + * Return: 0 if successful, 1 if not */ static int aht10_init(struct aht10_data *data) { @@ -121,54 +138,78 @@ static int aht10_polltime_expired(struct aht10_data *data) return ktime_after(difference, data->min_poll_interval); } +DECLARE_CRC8_TABLE(crc8_table); + /** - * aht10_read_values() - read and parse the raw data from the AHT10 + * crc8_check() - check crc of the sensor's measurements + * @raw_data: data frame received from sensor(including crc as the last byte) + * @count: size of the data frame + * Return: 0 if successful, 1 if not + */ +static int crc8_check(u8 *raw_data, int count) +{ + /* + * crc calculated on the whole frame(including crc byte) should yield + * zero in case of correctly received bytes + */ + return crc8(crc8_table, raw_data, count, CRC8_INIT_VALUE); +} + +/** + * aht10_read_values() - read and parse the raw data from the AHT10/AHT20 * @data: the struct aht10_data to use for the lock - * Return: 0 if succesfull, 1 if not + * Return: 0 if successful, 1 if not */ static int aht10_read_values(struct aht10_data *data) { const u8 cmd_meas[] = {AHT10_CMD_MEAS, 0x33, 0x00}; u32 temp, hum; int res; - u8 raw_data[AHT10_MEAS_SIZE]; + u8 raw_data[AHT20_MEAS_SIZE]; struct i2c_client *client = data->client; mutex_lock(&data->lock); - if (aht10_polltime_expired(data)) { - res = i2c_master_send(client, cmd_meas, sizeof(cmd_meas)); - if (res < 0) { - mutex_unlock(&data->lock); - return res; - } - - usleep_range(AHT10_MEAS_DELAY, - AHT10_MEAS_DELAY + AHT10_DELAY_EXTRA); - - res = i2c_master_recv(client, raw_data, AHT10_MEAS_SIZE); - if (res != AHT10_MEAS_SIZE) { - mutex_unlock(&data->lock); - if (res >= 0) - return -ENODATA; - else - return res; - } - - hum = ((u32)raw_data[1] << 12u) | - ((u32)raw_data[2] << 4u) | - ((raw_data[3] & 0xF0u) >> 4u); - - temp = ((u32)(raw_data[3] & 0x0Fu) << 16u) | - ((u32)raw_data[4] << 8u) | - raw_data[5]; - - temp = ((temp * 625) >> 15u) * 10; - hum = ((hum * 625) >> 16u) * 10; - - data->temperature = (int)temp - 50000; - data->humidity = hum; - data->previous_poll_time = ktime_get_boottime(); + if (!aht10_polltime_expired(data)) { + mutex_unlock(&data->lock); + return 0; + } + + res = i2c_master_send(client, cmd_meas, sizeof(cmd_meas)); + if (res < 0) { + mutex_unlock(&data->lock); + return res; } + + usleep_range(AHT10_MEAS_DELAY, AHT10_MEAS_DELAY + AHT10_DELAY_EXTRA); + + res = i2c_master_recv(client, raw_data, data->meas_size); + if (res != data->meas_size) { + mutex_unlock(&data->lock); + if (res >= 0) + return -ENODATA; + return res; + } + + if (data->crc8 && crc8_check(raw_data, data->meas_size)) { + mutex_unlock(&data->lock); + return -EIO; + } + + hum = ((u32)raw_data[1] << 12u) | + ((u32)raw_data[2] << 4u) | + ((raw_data[3] & 0xF0u) >> 4u); + + temp = ((u32)(raw_data[3] & 0x0Fu) << 16u) | + ((u32)raw_data[4] << 8u) | + raw_data[5]; + + temp = ((temp * 625) >> 15u) * 10; + hum = ((hum * 625) >> 16u) * 10; + + data->temperature = (int)temp - 50000; + data->humidity = hum; + data->previous_poll_time = ktime_get_boottime(); + mutex_unlock(&data->lock); return 0; } @@ -290,6 +331,8 @@ static const struct hwmon_chip_info aht10_chip_info = { static int aht10_probe(struct i2c_client *client) { + const struct i2c_device_id *id = i2c_match_id(aht10_id, client); + enum aht10_variant variant = id->driver_data; struct device *device = &client->dev; struct device *hwmon_dev; struct aht10_data *data; @@ -305,6 +348,17 @@ static int aht10_probe(struct i2c_client *client) data->min_poll_interval = ms_to_ktime(AHT10_DEFAULT_MIN_POLL_INTERVAL); data->client = client; + switch (variant) { + case aht20: + data->meas_size = AHT20_MEAS_SIZE; + data->crc8 = true; + crc8_populate_msb(crc8_table, AHT20_CRC8_POLY); + break; + default: + data->meas_size = AHT10_MEAS_SIZE; + break; + } + mutex_init(&data->lock); res = aht10_init(data); @@ -324,23 +378,17 @@ static int aht10_probe(struct i2c_client *client) return PTR_ERR_OR_ZERO(hwmon_dev); } -static const struct i2c_device_id aht10_id[] = { - { "aht10", 0 }, - { }, -}; -MODULE_DEVICE_TABLE(i2c, aht10_id); - static struct i2c_driver aht10_driver = { .driver = { .name = "aht10", }, - .probe_new = aht10_probe, + .probe = aht10_probe, .id_table = aht10_id, }; module_i2c_driver(aht10_driver); MODULE_AUTHOR("Johannes Cornelis Draaijer "); -MODULE_DESCRIPTION("AHT10 Temperature and Humidity sensor driver"); +MODULE_DESCRIPTION("AHT10/AHT20 Temperature and Humidity sensor driver"); MODULE_VERSION("1.0"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/hwmon/amc6821.c b/drivers/hwmon/amc6821.c index 3bfd12ff4b3ca67aa2cc2883524a9b93b8f26f7d..2a7a4b6b00942b34ee411ef1d2276176f4a132f7 100644 --- a/drivers/hwmon/amc6821.c +++ b/drivers/hwmon/amc6821.c @@ -939,7 +939,7 @@ static struct i2c_driver amc6821_driver = { .driver = { .name = "amc6821", }, - .probe_new = amc6821_probe, + .probe = amc6821_probe, .id_table = amc6821_id, .detect = amc6821_detect, .address_list = normal_i2c, diff --git a/drivers/hwmon/aquacomputer_d5next.c b/drivers/hwmon/aquacomputer_d5next.c index a4fcd4ebf76c2b30c9393210bba0618e51c04dae..a981f7086114da407962370f094b5eddd07c7f8a 100644 --- a/drivers/hwmon/aquacomputer_d5next.c +++ b/drivers/hwmon/aquacomputer_d5next.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0+ /* * hwmon driver for Aquacomputer devices (D5 Next, Farbwerk, Farbwerk 360, Octo, - * Quadro, High Flow Next, Aquaero, Aquastream Ultimate) + * Quadro, High Flow Next, Aquaero, Aquastream Ultimate, Leakshield) * * Aquacomputer devices send HID reports (with ID 0x01) every second to report * sensor values, except for devices that communicate through the @@ -29,6 +29,7 @@ #define USB_PRODUCT_ID_FARBWERK360 0xf010 #define USB_PRODUCT_ID_OCTO 0xf011 #define USB_PRODUCT_ID_HIGHFLOWNEXT 0xf012 +#define USB_PRODUCT_ID_LEAKSHIELD 0xf014 #define USB_PRODUCT_ID_AQUASTREAMXT 0xf0b6 #define USB_PRODUCT_ID_AQUASTREAMULT 0xf00b #define USB_PRODUCT_ID_POWERADJUST3 0xf0bd @@ -36,7 +37,7 @@ enum kinds { d5next, farbwerk, farbwerk360, octo, quadro, highflownext, aquaero, poweradjust3, aquastreamult, - aquastreamxt + aquastreamxt, leakshield }; static const char *const aqc_device_names[] = { @@ -46,6 +47,7 @@ static const char *const aqc_device_names[] = { [octo] = "octo", [quadro] = "quadro", [highflownext] = "highflownext", + [leakshield] = "leakshield", [aquastreamxt] = "aquastreamxt", [aquaero] = "aquaero", [aquastreamult] = "aquastreamultimate", @@ -93,7 +95,7 @@ static u8 aquaero_secondary_ctrl_report[] = { #define AQC_FIRMWARE_VERSION 0xD #define AQC_SENSOR_SIZE 0x02 -#define AQC_TEMP_SENSOR_DISCONNECTED 0x7FFF +#define AQC_SENSOR_NA 0x7FFF #define AQC_FAN_PERCENT_OFFSET 0x00 #define AQC_FAN_VOLTAGE_OFFSET 0x02 #define AQC_FAN_CURRENT_OFFSET 0x04 @@ -236,6 +238,21 @@ static u16 quadro_ctrl_fan_offsets[] = { 0x37, 0x8c, 0xe1, 0x136 }; /* Fan speed #define HIGHFLOWNEXT_5V_VOLTAGE 97 #define HIGHFLOWNEXT_5V_VOLTAGE_USB 99 +/* Specs of the Leakshield */ +#define LEAKSHIELD_NUM_SENSORS 2 + +/* Sensor report offsets for Leakshield */ +#define LEAKSHIELD_PRESSURE_ADJUSTED 285 +#define LEAKSHIELD_TEMPERATURE_1 265 +#define LEAKSHIELD_TEMPERATURE_2 287 +#define LEAKSHIELD_PRESSURE_MIN 291 +#define LEAKSHIELD_PRESSURE_TARGET 293 +#define LEAKSHIELD_PRESSURE_MAX 295 +#define LEAKSHIELD_PUMP_RPM_IN 101 +#define LEAKSHIELD_FLOW_IN 111 +#define LEAKSHIELD_RESERVOIR_VOLUME 313 +#define LEAKSHIELD_RESERVOIR_FILLED 311 + /* Specs of the Aquastream XT pump */ #define AQUASTREAMXT_SERIAL_START 0x3a #define AQUASTREAMXT_FIRMWARE_VERSION 0x32 @@ -411,6 +428,20 @@ static const char *const label_highflownext_voltage[] = { "+5V USB voltage" }; +/* Labels for Leakshield */ +static const char *const label_leakshield_temp_sensors[] = { + "Temperature 1", + "Temperature 2" +}; + +static const char *const label_leakshield_fan_speed[] = { + "Pressure [ubar]", + "User-Provided Pump Speed", + "User-Provided Flow [dL/h]", + "Reservoir Volume [ml]", + "Reservoir Filled [ml]", +}; + /* Labels for Aquastream XT */ static const char *const label_aquastreamxt_temp_sensors[] = { "Fan IC temp", @@ -529,7 +560,10 @@ struct aqc_data { /* Sensor values */ s32 temp_input[20]; /* Max 4 physical and 16 virtual or 8 physical and 12 virtual */ - u16 speed_input[8]; + s32 speed_input[8]; + u32 speed_input_min[1]; + u32 speed_input_target[1]; + u32 speed_input_max[1]; u32 power_input[8]; u16 voltage_input[8]; u16 current_input[8]; @@ -747,6 +781,11 @@ static umode_t aqc_is_visible(const void *data, enum hwmon_sensor_types type, u3 if (channel < 3) return 0444; break; + case leakshield: + /* Special case for Leakshield sensors */ + if (channel < 5) + return 0444; + break; case aquaero: case quadro: /* Special case to support flow sensors */ @@ -764,6 +803,13 @@ static umode_t aqc_is_visible(const void *data, enum hwmon_sensor_types type, u3 if (priv->kind == quadro && channel == priv->num_fans) return 0644; break; + case hwmon_fan_min: + case hwmon_fan_max: + case hwmon_fan_target: + /* Special case for Leakshield pressure sensor */ + if (priv->kind == leakshield && channel == 0) + return 0444; + break; default: break; } @@ -938,8 +984,20 @@ static int aqc_read(struct device *dev, enum hwmon_sensor_types type, u32 attr, case hwmon_fan: switch (attr) { case hwmon_fan_input: + if (priv->speed_input[channel] == -ENODATA) + return -ENODATA; + *val = priv->speed_input[channel]; break; + case hwmon_fan_min: + *val = priv->speed_input_min[channel]; + break; + case hwmon_fan_max: + *val = priv->speed_input_max[channel]; + break; + case hwmon_fan_target: + *val = priv->speed_input_target[channel]; + break; case hwmon_fan_pulses: ret = aqc_get_ctrl_val(priv, priv->flow_pulses_ctrl_offset, val, AQC_BE16); @@ -1151,7 +1209,8 @@ static const struct hwmon_channel_info * const aqc_info[] = { HWMON_T_INPUT | HWMON_T_LABEL, HWMON_T_INPUT | HWMON_T_LABEL), HWMON_CHANNEL_INFO(fan, - HWMON_F_INPUT | HWMON_F_LABEL, + HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_MIN | HWMON_F_MAX | + HWMON_F_TARGET, HWMON_F_INPUT | HWMON_F_LABEL, HWMON_F_INPUT | HWMON_F_LABEL, HWMON_F_INPUT | HWMON_F_LABEL, @@ -1224,7 +1283,7 @@ static int aqc_raw_event(struct hid_device *hdev, struct hid_report *report, u8 sensor_value = get_unaligned_be16(data + priv->temp_sensor_start_offset + i * AQC_SENSOR_SIZE); - if (sensor_value == AQC_TEMP_SENSOR_DISCONNECTED) + if (sensor_value == AQC_SENSOR_NA) priv->temp_input[i] = -ENODATA; else priv->temp_input[i] = sensor_value * 10; @@ -1235,7 +1294,7 @@ static int aqc_raw_event(struct hid_device *hdev, struct hid_report *report, u8 sensor_value = get_unaligned_be16(data + priv->virtual_temp_sensor_start_offset + j * AQC_SENSOR_SIZE); - if (sensor_value == AQC_TEMP_SENSOR_DISCONNECTED) + if (sensor_value == AQC_SENSOR_NA) priv->temp_input[i] = -ENODATA; else priv->temp_input[i] = sensor_value * 10; @@ -1277,7 +1336,7 @@ static int aqc_raw_event(struct hid_device *hdev, struct hid_report *report, u8 sensor_value = get_unaligned_be16(data + priv->calc_virt_temp_sensor_start_offset + j * AQC_SENSOR_SIZE); - if (sensor_value == AQC_TEMP_SENSOR_DISCONNECTED) + if (sensor_value == AQC_SENSOR_NA) priv->temp_input[i] = -ENODATA; else priv->temp_input[i] = sensor_value * 10; @@ -1314,6 +1373,28 @@ static int aqc_raw_event(struct hid_device *hdev, struct hid_report *report, u8 priv->speed_input[1] = get_unaligned_be16(data + HIGHFLOWNEXT_WATER_QUALITY); priv->speed_input[2] = get_unaligned_be16(data + HIGHFLOWNEXT_CONDUCTIVITY); break; + case leakshield: + priv->speed_input[0] = + ((s16)get_unaligned_be16(data + LEAKSHIELD_PRESSURE_ADJUSTED)) * 100; + priv->speed_input_min[0] = get_unaligned_be16(data + LEAKSHIELD_PRESSURE_MIN) * 100; + priv->speed_input_target[0] = + get_unaligned_be16(data + LEAKSHIELD_PRESSURE_TARGET) * 100; + priv->speed_input_max[0] = get_unaligned_be16(data + LEAKSHIELD_PRESSURE_MAX) * 100; + + priv->speed_input[1] = get_unaligned_be16(data + LEAKSHIELD_PUMP_RPM_IN); + if (priv->speed_input[1] == AQC_SENSOR_NA) + priv->speed_input[1] = -ENODATA; + + priv->speed_input[2] = get_unaligned_be16(data + LEAKSHIELD_FLOW_IN); + if (priv->speed_input[2] == AQC_SENSOR_NA) + priv->speed_input[2] = -ENODATA; + + priv->speed_input[3] = get_unaligned_be16(data + LEAKSHIELD_RESERVOIR_VOLUME); + priv->speed_input[4] = get_unaligned_be16(data + LEAKSHIELD_RESERVOIR_FILLED); + + /* Second temp sensor is not positioned after the first one, read it here */ + priv->temp_input[1] = get_unaligned_be16(data + LEAKSHIELD_TEMPERATURE_2) * 10; + break; default: break; } @@ -1571,6 +1652,25 @@ static int aqc_probe(struct hid_device *hdev, const struct hid_device_id *id) priv->power_label = label_highflownext_power; priv->voltage_label = label_highflownext_voltage; break; + case USB_PRODUCT_ID_LEAKSHIELD: + /* + * Choose the right Leakshield device, because + * the other one acts as a keyboard + */ + if (hdev->type != 2) { + ret = -ENODEV; + goto fail_and_close; + } + + priv->kind = leakshield; + + priv->num_fans = 0; + priv->num_temp_sensors = LEAKSHIELD_NUM_SENSORS; + priv->temp_sensor_start_offset = LEAKSHIELD_TEMPERATURE_1; + + priv->temp_label = label_leakshield_temp_sensors; + priv->speed_label = label_leakshield_fan_speed; + break; case USB_PRODUCT_ID_AQUASTREAMXT: priv->kind = aquastreamxt; @@ -1707,6 +1807,7 @@ static const struct hid_device_id aqc_table[] = { { HID_USB_DEVICE(USB_VENDOR_ID_AQUACOMPUTER, USB_PRODUCT_ID_OCTO) }, { HID_USB_DEVICE(USB_VENDOR_ID_AQUACOMPUTER, USB_PRODUCT_ID_QUADRO) }, { HID_USB_DEVICE(USB_VENDOR_ID_AQUACOMPUTER, USB_PRODUCT_ID_HIGHFLOWNEXT) }, + { HID_USB_DEVICE(USB_VENDOR_ID_AQUACOMPUTER, USB_PRODUCT_ID_LEAKSHIELD) }, { HID_USB_DEVICE(USB_VENDOR_ID_AQUACOMPUTER, USB_PRODUCT_ID_AQUASTREAMXT) }, { HID_USB_DEVICE(USB_VENDOR_ID_AQUACOMPUTER, USB_PRODUCT_ID_AQUASTREAMULT) }, { HID_USB_DEVICE(USB_VENDOR_ID_AQUACOMPUTER, USB_PRODUCT_ID_POWERADJUST3) }, diff --git a/drivers/hwmon/asb100.c b/drivers/hwmon/asb100.c index ce4da836765c1d8447e4970a9bcdc95c67031deb..974521e9b6b4056e86be81b97e39c497845dfb68 100644 --- a/drivers/hwmon/asb100.c +++ b/drivers/hwmon/asb100.c @@ -223,7 +223,7 @@ static struct i2c_driver asb100_driver = { .driver = { .name = "asb100", }, - .probe_new = asb100_probe, + .probe = asb100_probe, .remove = asb100_remove, .id_table = asb100_id, .detect = asb100_detect, diff --git a/drivers/hwmon/asc7621.c b/drivers/hwmon/asc7621.c index 54595454537bd1162ed76ae4f7372d64afe9ef5c..87e1867008499b4e60b0dcf0294758f32801bc38 100644 --- a/drivers/hwmon/asc7621.c +++ b/drivers/hwmon/asc7621.c @@ -1191,7 +1191,7 @@ static struct i2c_driver asc7621_driver = { .driver = { .name = "asc7621", }, - .probe_new = asc7621_probe, + .probe = asc7621_probe, .remove = asc7621_remove, .id_table = asc7621_id, .detect = asc7621_detect, diff --git a/drivers/hwmon/asus-ec-sensors.c b/drivers/hwmon/asus-ec-sensors.c index e5be0cf472fc93832d704d42dc3d95810355f59d..f52a539eb33e960e609893ca06c354ee074130ca 100644 --- a/drivers/hwmon/asus-ec-sensors.c +++ b/drivers/hwmon/asus-ec-sensors.c @@ -101,6 +101,8 @@ enum ec_sensors { ec_sensor_temp_chipset, /* CPU temperature [℃] */ ec_sensor_temp_cpu, + /* CPU package temperature [℃] */ + ec_sensor_temp_cpu_package, /* motherboard temperature [℃] */ ec_sensor_temp_mb, /* "T_Sensor" temperature sensor reading [℃] */ @@ -139,6 +141,7 @@ enum ec_sensors { #define SENSOR_TEMP_CHIPSET BIT(ec_sensor_temp_chipset) #define SENSOR_TEMP_CPU BIT(ec_sensor_temp_cpu) +#define SENSOR_TEMP_CPU_PACKAGE BIT(ec_sensor_temp_cpu_package) #define SENSOR_TEMP_MB BIT(ec_sensor_temp_mb) #define SENSOR_TEMP_T_SENSOR BIT(ec_sensor_temp_t_sensor) #define SENSOR_TEMP_VRM BIT(ec_sensor_temp_vrm) @@ -161,6 +164,7 @@ enum board_family { family_unknown, family_amd_400_series, family_amd_500_series, + family_amd_600_series, family_intel_300_series, family_intel_600_series }; @@ -233,6 +237,19 @@ static const struct ec_sensor_info sensors_family_amd_500[] = { EC_SENSOR("Extra_3", hwmon_temp, 1, 0x01, 0x0c), }; +static const struct ec_sensor_info sensors_family_amd_600[] = { + [ec_sensor_temp_cpu] = EC_SENSOR("CPU", hwmon_temp, 1, 0x00, 0x30), + [ec_sensor_temp_cpu_package] = EC_SENSOR("CPU Package", hwmon_temp, 1, 0x00, 0x31), + [ec_sensor_temp_mb] = + EC_SENSOR("Motherboard", hwmon_temp, 1, 0x00, 0x32), + [ec_sensor_temp_vrm] = + EC_SENSOR("VRM", hwmon_temp, 1, 0x00, 0x33), + [ec_sensor_temp_water_in] = + EC_SENSOR("Water_In", hwmon_temp, 1, 0x01, 0x00), + [ec_sensor_temp_water_out] = + EC_SENSOR("Water_Out", hwmon_temp, 1, 0x01, 0x01), +}; + static const struct ec_sensor_info sensors_family_intel_300[] = { [ec_sensor_temp_chipset] = EC_SENSOR("Chipset", hwmon_temp, 1, 0x00, 0x3a), @@ -319,6 +336,14 @@ static const struct ec_board_info board_info_pro_ws_x570_ace = { .family = family_amd_500_series, }; +static const struct ec_board_info board_info_crosshair_x670e_hero = { + .sensors = SENSOR_TEMP_CPU | SENSOR_TEMP_CPU_PACKAGE | + SENSOR_TEMP_MB | SENSOR_TEMP_VRM | + SENSOR_SET_TEMP_WATER, + .mutex_path = ASUS_HW_ACCESS_MUTEX_RMTW_ASMX, + .family = family_amd_600_series, +}; + static const struct ec_board_info board_info_crosshair_viii_dark_hero = { .sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB | SENSOR_TEMP_T_SENSOR | @@ -463,6 +488,8 @@ static const struct dmi_system_id dmi_table[] = { &board_info_crosshair_viii_hero), DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG CROSSHAIR VIII HERO (WI-FI)", &board_info_crosshair_viii_hero), + DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG CROSSHAIR X670E HERO", + &board_info_crosshair_x670e_hero), DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG MAXIMUS XI HERO", &board_info_maximus_xi_hero), DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG MAXIMUS XI HERO (WI-FI)", @@ -946,6 +973,9 @@ static int asus_ec_probe(struct platform_device *pdev) case family_amd_500_series: ec_data->sensors_info = sensors_family_amd_500; break; + case family_amd_600_series: + ec_data->sensors_info = sensors_family_amd_600; + break; case family_intel_300_series: ec_data->sensors_info = sensors_family_intel_300; break; diff --git a/drivers/hwmon/atxp1.c b/drivers/hwmon/atxp1.c index 118297ea1dcfa65c32c59a34e13cd3e86e6356d4..d1de020abec6aa95749aed8ab01dbf33756f210f 100644 --- a/drivers/hwmon/atxp1.c +++ b/drivers/hwmon/atxp1.c @@ -288,7 +288,7 @@ static struct i2c_driver atxp1_driver = { .driver = { .name = "atxp1", }, - .probe_new = atxp1_probe, + .probe = atxp1_probe, .id_table = atxp1_id, }; diff --git a/drivers/hwmon/corsair-psu.c b/drivers/hwmon/corsair-psu.c index dc24c566d08b27493362f40f8ebbcc5f02bea828..904890598c116b9de1bac58e8d7a68e87aa1a8fc 100644 --- a/drivers/hwmon/corsair-psu.c +++ b/drivers/hwmon/corsair-psu.c @@ -32,23 +32,25 @@ * but it is better to not rely on this (it is also hard to parse) * - the driver uses raw events to be accessible from userspace (though this is not really * supported, it is just there for convenience, may be removed in the future) - * - a reply always start with the length and command in the same order the request used it + * - a reply always starts with the length and command in the same order the request used it * - length of the reply data is specific to the command used * - some of the commands work on a rail and can be switched to a specific rail (0 = 12v, * 1 = 5v, 2 = 3.3v) * - the format of the init command 0xFE is swapped length/command bytes * - parameter bytes amount and values are specific to the command (rail setting is the only - * for now that uses non-zero values) - * - there are much more commands, especially for configuring the device, but they are not - * supported because a wrong command/length can lockup the micro-controller + * one for now that uses non-zero values) * - the driver supports debugfs for values not fitting into the hwmon class - * - not every device class (HXi, RMi or AXi) supports all commands - * - it is a pure sensors reading driver (will not support configuring) + * - not every device class (HXi or RMi) supports all commands + * - if configured wrong the PSU resets or shuts down, often before actually hitting the + * reported critical temperature + * - new models like HX1500i Series 2023 have changes in the reported vendor and product + * strings, both are slightly longer now, report vendor and product in one string and are + * the same now */ #define DRIVER_NAME "corsair-psu" -#define REPLY_SIZE 16 /* max length of a reply to a single command */ +#define REPLY_SIZE 24 /* max length of a reply to a single command */ #define CMD_BUFFER_SIZE 64 #define CMD_TIMEOUT_MS 250 #define SECONDS_PER_HOUR (60 * 60) @@ -58,7 +60,8 @@ #define OCP_MULTI_RAIL 0x02 #define PSU_CMD_SELECT_RAIL 0x00 /* expects length 2 */ -#define PSU_CMD_RAIL_VOLTS_HCRIT 0x40 /* the rest of the commands expect length 3 */ +#define PSU_CMD_FAN_PWM 0x3B /* the rest of the commands expect length 3 */ +#define PSU_CMD_RAIL_VOLTS_HCRIT 0x40 #define PSU_CMD_RAIL_VOLTS_LCRIT 0x44 #define PSU_CMD_RAIL_AMPS_HCRIT 0x46 #define PSU_CMD_TEMP_HCRIT 0x4F @@ -76,6 +79,7 @@ #define PSU_CMD_UPTIME 0xD2 #define PSU_CMD_OCPMODE 0xD8 #define PSU_CMD_TOTAL_WATTS 0xEE +#define PSU_CMD_FAN_PWM_ENABLE 0xF0 #define PSU_CMD_INIT 0xFE #define L_IN_VOLTS "v_in" @@ -145,6 +149,14 @@ static int corsairpsu_linear11_to_int(const u16 val, const int scale) return (exp >= 0) ? (result << exp) : (result >> -exp); } +/* the micro-controller uses percentage values to control pwm */ +static int corsairpsu_dutycycle_to_pwm(const long dutycycle) +{ + const int result = (256 << 16) / 100; + + return (result * dutycycle) >> 16; +} + static int corsairpsu_usb_cmd(struct corsairpsu_data *priv, u8 p0, u8 p1, u8 p2, void *data) { unsigned long time; @@ -244,8 +256,8 @@ static int corsairpsu_get_value(struct corsairpsu_data *priv, u8 cmd, u8 rail, l /* * the biggest value here comes from the uptime command and to exceed MAXINT total uptime * needs to be about 68 years, the rest are u16 values and the biggest value coming out of - * the LINEAR11 conversion are the watts values which are about 1200 for the strongest psu - * supported (HX1200i) + * the LINEAR11 conversion are the watts values which are about 1500 for the strongest psu + * supported (HX1500i) */ tmp = ((long)data[3] << 24) + (data[2] << 16) + (data[1] << 8) + data[0]; switch (cmd) { @@ -264,6 +276,24 @@ static int corsairpsu_get_value(struct corsairpsu_data *priv, u8 cmd, u8 rail, l case PSU_CMD_FAN: *val = corsairpsu_linear11_to_int(tmp & 0xFFFF, 1); break; + case PSU_CMD_FAN_PWM_ENABLE: + *val = corsairpsu_linear11_to_int(tmp & 0xFFFF, 1); + /* + * 0 = automatic mode, means the micro-controller controls the fan using a plan + * which can be modified, but changing this plan is not supported by this + * driver, the matching PWM mode is automatic fan speed control = PWM 2 + * 1 = fixed mode, fan runs at a fixed speed represented by a percentage + * value 0-100, this matches the PWM manual fan speed control = PWM 1 + * technically there is no PWM no fan speed control mode, it would be a combination + * of 1 at 100% + */ + if (*val == 0) + *val = 2; + break; + case PSU_CMD_FAN_PWM: + *val = corsairpsu_linear11_to_int(tmp & 0xFFFF, 1); + *val = corsairpsu_dutycycle_to_pwm(*val); + break; case PSU_CMD_RAIL_WATTS: case PSU_CMD_TOTAL_WATTS: *val = corsairpsu_linear11_to_int(tmp & 0xFFFF, 1000000); @@ -349,6 +379,18 @@ static umode_t corsairpsu_hwmon_fan_is_visible(const struct corsairpsu_data *pri } } +static umode_t corsairpsu_hwmon_pwm_is_visible(const struct corsairpsu_data *priv, u32 attr, + int channel) +{ + switch (attr) { + case hwmon_pwm_input: + case hwmon_pwm_enable: + return 0444; + default: + return 0; + } +} + static umode_t corsairpsu_hwmon_power_is_visible(const struct corsairpsu_data *priv, u32 attr, int channel) { @@ -416,6 +458,8 @@ static umode_t corsairpsu_hwmon_ops_is_visible(const void *data, enum hwmon_sens return corsairpsu_hwmon_temp_is_visible(priv, attr, channel); case hwmon_fan: return corsairpsu_hwmon_fan_is_visible(priv, attr, channel); + case hwmon_pwm: + return corsairpsu_hwmon_pwm_is_visible(priv, attr, channel); case hwmon_power: return corsairpsu_hwmon_power_is_visible(priv, attr, channel); case hwmon_in: @@ -447,6 +491,20 @@ static int corsairpsu_hwmon_temp_read(struct corsairpsu_data *priv, u32 attr, in return err; } +static int corsairpsu_hwmon_pwm_read(struct corsairpsu_data *priv, u32 attr, int channel, long *val) +{ + switch (attr) { + case hwmon_pwm_input: + return corsairpsu_get_value(priv, PSU_CMD_FAN_PWM, 0, val); + case hwmon_pwm_enable: + return corsairpsu_get_value(priv, PSU_CMD_FAN_PWM_ENABLE, 0, val); + default: + break; + } + + return -EOPNOTSUPP; +} + static int corsairpsu_hwmon_power_read(struct corsairpsu_data *priv, u32 attr, int channel, long *val) { @@ -531,6 +589,8 @@ static int corsairpsu_hwmon_ops_read(struct device *dev, enum hwmon_sensor_types if (attr == hwmon_fan_input) return corsairpsu_get_value(priv, PSU_CMD_FAN, 0, val); return -EOPNOTSUPP; + case hwmon_pwm: + return corsairpsu_hwmon_pwm_read(priv, attr, channel, val); case hwmon_power: return corsairpsu_hwmon_power_read(priv, attr, channel, val); case hwmon_in: @@ -571,7 +631,7 @@ static const struct hwmon_ops corsairpsu_hwmon_ops = { .read_string = corsairpsu_hwmon_ops_read_string, }; -static const struct hwmon_channel_info * const corsairpsu_info[] = { +static const struct hwmon_channel_info *const corsairpsu_info[] = { HWMON_CHANNEL_INFO(chip, HWMON_C_REGISTER_TZ), HWMON_CHANNEL_INFO(temp, @@ -579,6 +639,8 @@ static const struct hwmon_channel_info * const corsairpsu_info[] = { HWMON_T_INPUT | HWMON_T_LABEL | HWMON_T_CRIT), HWMON_CHANNEL_INFO(fan, HWMON_F_INPUT | HWMON_F_LABEL), + HWMON_CHANNEL_INFO(pwm, + HWMON_PWM_INPUT | HWMON_PWM_ENABLE), HWMON_CHANNEL_INFO(power, HWMON_P_INPUT | HWMON_P_LABEL, HWMON_P_INPUT | HWMON_P_LABEL, @@ -813,15 +875,15 @@ static const struct hid_device_id corsairpsu_idtable[] = { { HID_USB_DEVICE(0x1b1c, 0x1c04) }, /* Corsair HX650i */ { HID_USB_DEVICE(0x1b1c, 0x1c05) }, /* Corsair HX750i */ { HID_USB_DEVICE(0x1b1c, 0x1c06) }, /* Corsair HX850i */ - { HID_USB_DEVICE(0x1b1c, 0x1c07) }, /* Corsair HX1000i revision 1 */ + { HID_USB_DEVICE(0x1b1c, 0x1c07) }, /* Corsair HX1000i Series 2022 */ { HID_USB_DEVICE(0x1b1c, 0x1c08) }, /* Corsair HX1200i */ { HID_USB_DEVICE(0x1b1c, 0x1c09) }, /* Corsair RM550i */ { HID_USB_DEVICE(0x1b1c, 0x1c0a) }, /* Corsair RM650i */ { HID_USB_DEVICE(0x1b1c, 0x1c0b) }, /* Corsair RM750i */ { HID_USB_DEVICE(0x1b1c, 0x1c0c) }, /* Corsair RM850i */ { HID_USB_DEVICE(0x1b1c, 0x1c0d) }, /* Corsair RM1000i */ - { HID_USB_DEVICE(0x1b1c, 0x1c1e) }, /* Corsair HX1000i revision 2 */ - { HID_USB_DEVICE(0x1b1c, 0x1c1f) }, /* Corsair HX1500i */ + { HID_USB_DEVICE(0x1b1c, 0x1c1e) }, /* Corsair HX1000i Series 2023 */ + { HID_USB_DEVICE(0x1b1c, 0x1c1f) }, /* Corsair HX1500i Series 2022 and 2023 */ { }, }; MODULE_DEVICE_TABLE(hid, corsairpsu_idtable); diff --git a/drivers/hwmon/dme1737.c b/drivers/hwmon/dme1737.c index 66c48f70fae73b0f3a94c23c4f749711dcb68e83..cdbf3dff9172989a74040fd29f7f694d3e7d79d3 100644 --- a/drivers/hwmon/dme1737.c +++ b/drivers/hwmon/dme1737.c @@ -2528,7 +2528,7 @@ static struct i2c_driver dme1737_i2c_driver = { .driver = { .name = "dme1737", }, - .probe_new = dme1737_i2c_probe, + .probe = dme1737_i2c_probe, .remove = dme1737_i2c_remove, .id_table = dme1737_id, .detect = dme1737_i2c_detect, diff --git a/drivers/hwmon/ds1621.c b/drivers/hwmon/ds1621.c index e803d6393b9e50a73d6359b2b66ab1c0a89d618a..21b6350465211f621d1fcba1e781c6dcdaddf4ff 100644 --- a/drivers/hwmon/ds1621.c +++ b/drivers/hwmon/ds1621.c @@ -384,7 +384,7 @@ static struct i2c_driver ds1621_driver = { .driver = { .name = "ds1621", }, - .probe_new = ds1621_probe, + .probe = ds1621_probe, .id_table = ds1621_id, }; diff --git a/drivers/hwmon/ds620.c b/drivers/hwmon/ds620.c index 82d7c3d58f49bd7020557c9ece7e96005370c8c9..2b09536630cb6abb06cc68847dd055dea69e0eea 100644 --- a/drivers/hwmon/ds620.c +++ b/drivers/hwmon/ds620.c @@ -245,7 +245,7 @@ static struct i2c_driver ds620_driver = { .driver = { .name = "ds620", }, - .probe_new = ds620_probe, + .probe = ds620_probe, .id_table = ds620_id, }; diff --git a/drivers/hwmon/emc1403.c b/drivers/hwmon/emc1403.c index 61d59189a6d10759fd03d1ab832adb191a84d10f..bb7c859e799dc38f00d4e9c1eb0c7c2179bbcf9f 100644 --- a/drivers/hwmon/emc1403.c +++ b/drivers/hwmon/emc1403.c @@ -454,7 +454,7 @@ static struct i2c_driver sensor_emc1403 = { .name = "emc1403", }, .detect = emc1403_detect, - .probe_new = emc1403_probe, + .probe = emc1403_probe, .id_table = emc1403_idtable, .address_list = emc1403_address_list, }; diff --git a/drivers/hwmon/emc2103.c b/drivers/hwmon/emc2103.c index 361cf9292456d62e3b6138c17bd5d1dfd84d1e5f..b59472bbe5bf44b7c2f167a1f60c9c3fddf57365 100644 --- a/drivers/hwmon/emc2103.c +++ b/drivers/hwmon/emc2103.c @@ -653,7 +653,7 @@ static struct i2c_driver emc2103_driver = { .driver = { .name = "emc2103", }, - .probe_new = emc2103_probe, + .probe = emc2103_probe, .id_table = emc2103_ids, .detect = emc2103_detect, .address_list = normal_i2c, diff --git a/drivers/hwmon/emc2305.c b/drivers/hwmon/emc2305.c index 723f57518c9a29bd72ba5a5f9b9f2592381b5581..29f0e4945f1924eabd30b055da16e596bc25ebef 100644 --- a/drivers/hwmon/emc2305.c +++ b/drivers/hwmon/emc2305.c @@ -615,7 +615,7 @@ static struct i2c_driver emc2305_driver = { .driver = { .name = "emc2305", }, - .probe_new = emc2305_probe, + .probe = emc2305_probe, .remove = emc2305_remove, .id_table = emc2305_ids, .address_list = emc2305_normal_i2c, diff --git a/drivers/hwmon/emc6w201.c b/drivers/hwmon/emc6w201.c index bcd93f0fe982b9e911dd8b1bea1a0bb89653e75b..9a4f868bf1e64e58a4ad81679b53c11c277ba743 100644 --- a/drivers/hwmon/emc6w201.c +++ b/drivers/hwmon/emc6w201.c @@ -474,7 +474,7 @@ static struct i2c_driver emc6w201_driver = { .driver = { .name = "emc6w201", }, - .probe_new = emc6w201_probe, + .probe = emc6w201_probe, .id_table = emc6w201_id, .detect = emc6w201_detect, .address_list = normal_i2c, diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c index 70121482a6173ace70888e201676f6d9980355db..27207ec6f7febd239f6642ce3c253ffecec82433 100644 --- a/drivers/hwmon/f71882fg.c +++ b/drivers/hwmon/f71882fg.c @@ -1096,8 +1096,11 @@ static ssize_t show_pwm(struct device *dev, val = data->pwm[nr]; else { /* RPM mode */ - val = 255 * fan_from_reg(data->fan_target[nr]) - / fan_from_reg(data->fan_full_speed[nr]); + if (fan_from_reg(data->fan_full_speed[nr])) + val = 255 * fan_from_reg(data->fan_target[nr]) + / fan_from_reg(data->fan_full_speed[nr]); + else + val = 0; } mutex_unlock(&data->update_lock); return sprintf(buf, "%d\n", val); diff --git a/drivers/hwmon/f75375s.c b/drivers/hwmon/f75375s.c index 64fbb8cf687c078cc9cafc9e7b0cda936eb4e9ed..8c572bb64f5dc1e6243948c4b6a30aa9caffef46 100644 --- a/drivers/hwmon/f75375s.c +++ b/drivers/hwmon/f75375s.c @@ -129,7 +129,7 @@ static struct i2c_driver f75375_driver = { .driver = { .name = "f75375", }, - .probe_new = f75375_probe, + .probe = f75375_probe, .remove = f75375_remove, .id_table = f75375_id, .detect = f75375_detect, diff --git a/drivers/hwmon/fschmd.c b/drivers/hwmon/fschmd.c index e1f426e86f36c22a3ad58cb75f0c23ba3fa0d759..b30512a705a7920c2b1fcca64e13a424b979013c 100644 --- a/drivers/hwmon/fschmd.c +++ b/drivers/hwmon/fschmd.c @@ -241,7 +241,7 @@ static struct i2c_driver fschmd_driver = { .driver = { .name = "fschmd", }, - .probe_new = fschmd_probe, + .probe = fschmd_probe, .remove = fschmd_remove, .id_table = fschmd_id, .detect = fschmd_detect, diff --git a/drivers/hwmon/ftsteutates.c b/drivers/hwmon/ftsteutates.c index f5a4d91a7e90b60b49ecf61bc4793c3fb84a0957..b74a2665e73321c39854e6627f639e33739e31e3 100644 --- a/drivers/hwmon/ftsteutates.c +++ b/drivers/hwmon/ftsteutates.c @@ -678,7 +678,7 @@ static struct i2c_driver fts_driver = { .name = "ftsteutates", }, .id_table = fts_id, - .probe_new = fts_probe, + .probe = fts_probe, .detect = fts_detect, .address_list = normal_i2c, }; diff --git a/drivers/hwmon/g760a.c b/drivers/hwmon/g760a.c index 36717b524dbd5f1447dcadebd24c30954a3aa43b..b5edee00267bf501c4c6f83a77c28616a4289c47 100644 --- a/drivers/hwmon/g760a.c +++ b/drivers/hwmon/g760a.c @@ -206,7 +206,7 @@ static struct i2c_driver g760a_driver = { .driver = { .name = "g760a", }, - .probe_new = g760a_probe, + .probe = g760a_probe, .id_table = g760a_id, }; diff --git a/drivers/hwmon/g762.c b/drivers/hwmon/g762.c index e2c3c34f06e80843911c965fe78efc2594919e4e..1b6ff4712138d26abbd5a707e38a4dc4283cd297 100644 --- a/drivers/hwmon/g762.c +++ b/drivers/hwmon/g762.c @@ -1084,7 +1084,7 @@ static struct i2c_driver g762_driver = { .name = DRVNAME, .of_match_table = of_match_ptr(g762_dt_match), }, - .probe_new = g762_probe, + .probe = g762_probe, .id_table = g762_id, }; diff --git a/drivers/hwmon/gl518sm.c b/drivers/hwmon/gl518sm.c index 95286c40f55a966e94ad7d64478985cecea84272..03db6158b13ad4972f051798ba4e320b5b7fdc57 100644 --- a/drivers/hwmon/gl518sm.c +++ b/drivers/hwmon/gl518sm.c @@ -652,7 +652,7 @@ static struct i2c_driver gl518_driver = { .driver = { .name = "gl518sm", }, - .probe_new = gl518_probe, + .probe = gl518_probe, .id_table = gl518_id, .detect = gl518_detect, .address_list = normal_i2c, diff --git a/drivers/hwmon/gl520sm.c b/drivers/hwmon/gl520sm.c index 394da4ac977c5a8613e24e6be1454928f0815e72..8bbc6a4f2928be4347b3a738516b98a22a3c7262 100644 --- a/drivers/hwmon/gl520sm.c +++ b/drivers/hwmon/gl520sm.c @@ -895,7 +895,7 @@ static struct i2c_driver gl520_driver = { .driver = { .name = "gl520sm", }, - .probe_new = gl520_probe, + .probe = gl520_probe, .id_table = gl520_id, .detect = gl520_detect, .address_list = normal_i2c, diff --git a/drivers/hwmon/gsc-hwmon.c b/drivers/hwmon/gsc-hwmon.c index 73e5d92b200b0c348c627ebb91d1372a6e2b8809..1501ceb551e796f75082a1a786220d9ac089e66f 100644 --- a/drivers/hwmon/gsc-hwmon.c +++ b/drivers/hwmon/gsc-hwmon.c @@ -82,8 +82,8 @@ static ssize_t pwm_auto_point_temp_store(struct device *dev, if (kstrtol(buf, 10, &temp)) return -EINVAL; - temp = clamp_val(temp, 0, 10000); - temp = DIV_ROUND_CLOSEST(temp, 10); + temp = clamp_val(temp, 0, 100000); + temp = DIV_ROUND_CLOSEST(temp, 100); regs[0] = temp & 0xff; regs[1] = (temp >> 8) & 0xff; @@ -100,7 +100,7 @@ static ssize_t pwm_auto_point_pwm_show(struct device *dev, { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - return sprintf(buf, "%d\n", 255 * (50 + (attr->index * 10)) / 100); + return sprintf(buf, "%d\n", 255 * (50 + (attr->index * 10))); } static SENSOR_DEVICE_ATTR_RO(pwm1_auto_point1_pwm, pwm_auto_point_pwm, 0); diff --git a/drivers/hwmon/hih6130.c b/drivers/hwmon/hih6130.c index 3a7582824f945dc519486820d9a40c9f098adc5d..a9726b5370fb11815a49a1ca24e95907ec79ac83 100644 --- a/drivers/hwmon/hih6130.c +++ b/drivers/hwmon/hih6130.c @@ -249,7 +249,7 @@ static struct i2c_driver hih6130_driver = { .name = "hih6130", .of_match_table = of_match_ptr(hih6130_of_match), }, - .probe_new = hih6130_probe, + .probe = hih6130_probe, .id_table = hih6130_id, }; diff --git a/drivers/hwmon/hp-wmi-sensors.c b/drivers/hwmon/hp-wmi-sensors.c new file mode 100644 index 0000000000000000000000000000000000000000..ebe2fb5134805df261bfe4248ac6186e192abfc6 --- /dev/null +++ b/drivers/hwmon/hp-wmi-sensors.c @@ -0,0 +1,2004 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * hwmon driver for HP (and some HP Compaq) business-class computers that + * report numeric sensor data via Windows Management Instrumentation (WMI). + * + * Copyright (C) 2023 James Seo + * + * References: + * [1] Hewlett-Packard Development Company, L.P., + * "HP Client Management Interface Technical White Paper", 2005. [Online]. + * Available: https://h20331.www2.hp.com/hpsub/downloads/cmi_whitepaper.pdf + * [2] Hewlett-Packard Development Company, L.P., + * "HP Retail Manageability", 2012. [Online]. + * Available: http://h10032.www1.hp.com/ctg/Manual/c03291135.pdf + * [3] Linux Hardware Project, A. Ponomarenko et al., + * "linuxhw/ACPI - Collect ACPI table dumps", 2018. [Online]. + * Available: https://github.com/linuxhw/ACPI + * [4] P. Rohár, "bmfdec - Decompile binary MOF file (BMF) from WMI buffer", + * 2017. [Online]. Available: https://github.com/pali/bmfdec + */ + +#include +#include +#include +#include +#include +#include +#include + +#define HP_WMI_EVENT_NAMESPACE "root\\WMI" +#define HP_WMI_EVENT_CLASS "HPBIOS_BIOSEvent" +#define HP_WMI_EVENT_GUID "95F24279-4D7B-4334-9387-ACCDC67EF61C" +#define HP_WMI_NUMERIC_SENSOR_GUID "8F1F6435-9F42-42C8-BADC-0E9424F20C9A" +#define HP_WMI_PLATFORM_EVENTS_GUID "41227C2D-80E1-423F-8B8E-87E32755A0EB" + +/* Patterns for recognizing sensors and matching events to channels. */ + +#define HP_WMI_PATTERN_SYS_TEMP "Chassis Thermal Index" +#define HP_WMI_PATTERN_SYS_TEMP2 "System Ambient Temperature" +#define HP_WMI_PATTERN_CPU_TEMP "CPU Thermal Index" +#define HP_WMI_PATTERN_CPU_TEMP2 "CPU Temperature" +#define HP_WMI_PATTERN_TEMP_SENSOR "Thermal Index" +#define HP_WMI_PATTERN_TEMP_ALARM "Thermal Critical" +#define HP_WMI_PATTERN_INTRUSION_ALARM "Hood Intrusion" +#define HP_WMI_PATTERN_FAN_ALARM "Stall" +#define HP_WMI_PATTERN_TEMP "Temperature" +#define HP_WMI_PATTERN_CPU "CPU" + +/* These limits are arbitrary. The WMI implementation may vary by system. */ + +#define HP_WMI_MAX_STR_SIZE 128U +#define HP_WMI_MAX_PROPERTIES 32U +#define HP_WMI_MAX_INSTANCES 32U + +enum hp_wmi_type { + HP_WMI_TYPE_OTHER = 1, + HP_WMI_TYPE_TEMPERATURE = 2, + HP_WMI_TYPE_VOLTAGE = 3, + HP_WMI_TYPE_CURRENT = 4, + HP_WMI_TYPE_AIR_FLOW = 12, + HP_WMI_TYPE_INTRUSION = 0xabadb01, /* Custom. */ +}; + +enum hp_wmi_category { + HP_WMI_CATEGORY_SENSOR = 3, +}; + +enum hp_wmi_severity { + HP_WMI_SEVERITY_UNKNOWN = 0, + HP_WMI_SEVERITY_OK = 5, + HP_WMI_SEVERITY_DEGRADED_WARNING = 10, + HP_WMI_SEVERITY_MINOR_FAILURE = 15, + HP_WMI_SEVERITY_MAJOR_FAILURE = 20, + HP_WMI_SEVERITY_CRITICAL_FAILURE = 25, + HP_WMI_SEVERITY_NON_RECOVERABLE_ERROR = 30, +}; + +enum hp_wmi_status { + HP_WMI_STATUS_OK = 2, + HP_WMI_STATUS_DEGRADED = 3, + HP_WMI_STATUS_STRESSED = 4, + HP_WMI_STATUS_PREDICTIVE_FAILURE = 5, + HP_WMI_STATUS_ERROR = 6, + HP_WMI_STATUS_NON_RECOVERABLE_ERROR = 7, + HP_WMI_STATUS_NO_CONTACT = 12, + HP_WMI_STATUS_LOST_COMMUNICATION = 13, + HP_WMI_STATUS_ABORTED = 14, + HP_WMI_STATUS_SUPPORTING_ENTITY_IN_ERROR = 16, + + /* Occurs combined with one of "OK", "Degraded", and "Error" [1]. */ + HP_WMI_STATUS_COMPLETED = 17, +}; + +enum hp_wmi_units { + HP_WMI_UNITS_OTHER = 1, + HP_WMI_UNITS_DEGREES_C = 2, + HP_WMI_UNITS_DEGREES_F = 3, + HP_WMI_UNITS_DEGREES_K = 4, + HP_WMI_UNITS_VOLTS = 5, + HP_WMI_UNITS_AMPS = 6, + HP_WMI_UNITS_RPM = 19, +}; + +enum hp_wmi_property { + HP_WMI_PROPERTY_NAME = 0, + HP_WMI_PROPERTY_DESCRIPTION = 1, + HP_WMI_PROPERTY_SENSOR_TYPE = 2, + HP_WMI_PROPERTY_OTHER_SENSOR_TYPE = 3, + HP_WMI_PROPERTY_OPERATIONAL_STATUS = 4, + HP_WMI_PROPERTY_SIZE = 5, + HP_WMI_PROPERTY_POSSIBLE_STATES = 6, + HP_WMI_PROPERTY_CURRENT_STATE = 7, + HP_WMI_PROPERTY_BASE_UNITS = 8, + HP_WMI_PROPERTY_UNIT_MODIFIER = 9, + HP_WMI_PROPERTY_CURRENT_READING = 10, + HP_WMI_PROPERTY_RATE_UNITS = 11, +}; + +static const acpi_object_type hp_wmi_property_map[] = { + [HP_WMI_PROPERTY_NAME] = ACPI_TYPE_STRING, + [HP_WMI_PROPERTY_DESCRIPTION] = ACPI_TYPE_STRING, + [HP_WMI_PROPERTY_SENSOR_TYPE] = ACPI_TYPE_INTEGER, + [HP_WMI_PROPERTY_OTHER_SENSOR_TYPE] = ACPI_TYPE_STRING, + [HP_WMI_PROPERTY_OPERATIONAL_STATUS] = ACPI_TYPE_INTEGER, + [HP_WMI_PROPERTY_SIZE] = ACPI_TYPE_INTEGER, + [HP_WMI_PROPERTY_POSSIBLE_STATES] = ACPI_TYPE_STRING, + [HP_WMI_PROPERTY_CURRENT_STATE] = ACPI_TYPE_STRING, + [HP_WMI_PROPERTY_BASE_UNITS] = ACPI_TYPE_INTEGER, + [HP_WMI_PROPERTY_UNIT_MODIFIER] = ACPI_TYPE_INTEGER, + [HP_WMI_PROPERTY_CURRENT_READING] = ACPI_TYPE_INTEGER, + [HP_WMI_PROPERTY_RATE_UNITS] = ACPI_TYPE_INTEGER, +}; + +enum hp_wmi_platform_events_property { + HP_WMI_PLATFORM_EVENTS_PROPERTY_NAME = 0, + HP_WMI_PLATFORM_EVENTS_PROPERTY_DESCRIPTION = 1, + HP_WMI_PLATFORM_EVENTS_PROPERTY_SOURCE_NAMESPACE = 2, + HP_WMI_PLATFORM_EVENTS_PROPERTY_SOURCE_CLASS = 3, + HP_WMI_PLATFORM_EVENTS_PROPERTY_CATEGORY = 4, + HP_WMI_PLATFORM_EVENTS_PROPERTY_POSSIBLE_SEVERITY = 5, + HP_WMI_PLATFORM_EVENTS_PROPERTY_POSSIBLE_STATUS = 6, +}; + +static const acpi_object_type hp_wmi_platform_events_property_map[] = { + [HP_WMI_PLATFORM_EVENTS_PROPERTY_NAME] = ACPI_TYPE_STRING, + [HP_WMI_PLATFORM_EVENTS_PROPERTY_DESCRIPTION] = ACPI_TYPE_STRING, + [HP_WMI_PLATFORM_EVENTS_PROPERTY_SOURCE_NAMESPACE] = ACPI_TYPE_STRING, + [HP_WMI_PLATFORM_EVENTS_PROPERTY_SOURCE_CLASS] = ACPI_TYPE_STRING, + [HP_WMI_PLATFORM_EVENTS_PROPERTY_CATEGORY] = ACPI_TYPE_INTEGER, + [HP_WMI_PLATFORM_EVENTS_PROPERTY_POSSIBLE_SEVERITY] = ACPI_TYPE_INTEGER, + [HP_WMI_PLATFORM_EVENTS_PROPERTY_POSSIBLE_STATUS] = ACPI_TYPE_INTEGER, +}; + +enum hp_wmi_event_property { + HP_WMI_EVENT_PROPERTY_NAME = 0, + HP_WMI_EVENT_PROPERTY_DESCRIPTION = 1, + HP_WMI_EVENT_PROPERTY_CATEGORY = 2, + HP_WMI_EVENT_PROPERTY_SEVERITY = 3, + HP_WMI_EVENT_PROPERTY_STATUS = 4, +}; + +static const acpi_object_type hp_wmi_event_property_map[] = { + [HP_WMI_EVENT_PROPERTY_NAME] = ACPI_TYPE_STRING, + [HP_WMI_EVENT_PROPERTY_DESCRIPTION] = ACPI_TYPE_STRING, + [HP_WMI_EVENT_PROPERTY_CATEGORY] = ACPI_TYPE_INTEGER, + [HP_WMI_EVENT_PROPERTY_SEVERITY] = ACPI_TYPE_INTEGER, + [HP_WMI_EVENT_PROPERTY_STATUS] = ACPI_TYPE_INTEGER, +}; + +static const enum hwmon_sensor_types hp_wmi_hwmon_type_map[] = { + [HP_WMI_TYPE_TEMPERATURE] = hwmon_temp, + [HP_WMI_TYPE_VOLTAGE] = hwmon_in, + [HP_WMI_TYPE_CURRENT] = hwmon_curr, + [HP_WMI_TYPE_AIR_FLOW] = hwmon_fan, +}; + +static const u32 hp_wmi_hwmon_attributes[hwmon_max] = { + [hwmon_chip] = HWMON_C_REGISTER_TZ, + [hwmon_temp] = HWMON_T_INPUT | HWMON_T_LABEL | HWMON_T_FAULT, + [hwmon_in] = HWMON_I_INPUT | HWMON_I_LABEL, + [hwmon_curr] = HWMON_C_INPUT | HWMON_C_LABEL, + [hwmon_fan] = HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_FAULT, + [hwmon_intrusion] = HWMON_INTRUSION_ALARM, +}; + +/* + * struct hp_wmi_numeric_sensor - a HPBIOS_BIOSNumericSensor instance + * + * Two variants of HPBIOS_BIOSNumericSensor are known. The first is specified + * in [1] and appears to be much more widespread. The second was discovered by + * decoding BMOF blobs [4], seems to be found only in some newer ZBook systems + * [3], and has two new properties and a slightly different property order. + * + * These differences don't matter on Windows, where WMI object properties are + * accessed by name. For us, supporting both variants gets ugly and hacky at + * times. The fun begins now; this struct is defined as per the new variant. + * + * Effective MOF definition: + * + * #pragma namespace("\\\\.\\root\\HP\\InstrumentedBIOS"); + * class HPBIOS_BIOSNumericSensor { + * [read] string Name; + * [read] string Description; + * [read, ValueMap {"0","1","2","3","4","5","6","7","8","9", + * "10","11","12"}, Values {"Unknown","Other","Temperature", + * "Voltage","Current","Tachometer","Counter","Switch","Lock", + * "Humidity","Smoke Detection","Presence","Air Flow"}] + * uint32 SensorType; + * [read] string OtherSensorType; + * [read, ValueMap {"0","1","2","3","4","5","6","7","8","9", + * "10","11","12","13","14","15","16","17","18","..", + * "0x8000.."}, Values {"Unknown","Other","OK","Degraded", + * "Stressed","Predictive Failure","Error", + * "Non-Recoverable Error","Starting","Stopping","Stopped", + * "In Service","No Contact","Lost Communication","Aborted", + * "Dormant","Supporting Entity in Error","Completed", + * "Power Mode","DMTF Reserved","Vendor Reserved"}] + * uint32 OperationalStatus; + * [read] uint32 Size; + * [read] string PossibleStates[]; + * [read] string CurrentState; + * [read, ValueMap {"0","1","2","3","4","5","6","7","8","9", + * "10","11","12","13","14","15","16","17","18","19","20", + * "21","22","23","24","25","26","27","28","29","30","31", + * "32","33","34","35","36","37","38","39","40","41","42", + * "43","44","45","46","47","48","49","50","51","52","53", + * "54","55","56","57","58","59","60","61","62","63","64", + * "65"}, Values {"Unknown","Other","Degrees C","Degrees F", + * "Degrees K","Volts","Amps","Watts","Joules","Coulombs", + * "VA","Nits","Lumens","Lux","Candelas","kPa","PSI", + * "Newtons","CFM","RPM","Hertz","Seconds","Minutes", + * "Hours","Days","Weeks","Mils","Inches","Feet", + * "Cubic Inches","Cubic Feet","Meters","Cubic Centimeters", + * "Cubic Meters","Liters","Fluid Ounces","Radians", + * "Steradians","Revolutions","Cycles","Gravities","Ounces", + * "Pounds","Foot-Pounds","Ounce-Inches","Gauss","Gilberts", + * "Henries","Farads","Ohms","Siemens","Moles","Becquerels", + * "PPM (parts/million)","Decibels","DbA","DbC","Grays", + * "Sieverts","Color Temperature Degrees K","Bits","Bytes", + * "Words (data)","DoubleWords","QuadWords","Percentage"}] + * uint32 BaseUnits; + * [read] sint32 UnitModifier; + * [read] uint32 CurrentReading; + * [read] uint32 RateUnits; + * }; + * + * Effective MOF definition of old variant [1] (sans redundant info): + * + * class HPBIOS_BIOSNumericSensor { + * [read] string Name; + * [read] string Description; + * [read] uint32 SensorType; + * [read] string OtherSensorType; + * [read] uint32 OperationalStatus; + * [read] string CurrentState; + * [read] string PossibleStates[]; + * [read] uint32 BaseUnits; + * [read] sint32 UnitModifier; + * [read] uint32 CurrentReading; + * }; + */ +struct hp_wmi_numeric_sensor { + const char *name; + const char *description; + u32 sensor_type; + const char *other_sensor_type; /* Explains "Other" SensorType. */ + u32 operational_status; + u8 size; /* Count of PossibleStates[]. */ + const char **possible_states; + const char *current_state; + u32 base_units; + s32 unit_modifier; + u32 current_reading; + u32 rate_units; +}; + +/* + * struct hp_wmi_platform_events - a HPBIOS_PlatformEvents instance + * + * Instances of this object reveal the set of possible HPBIOS_BIOSEvent + * instances for the current system, but it may not always be present. + * + * Effective MOF definition: + * + * #pragma namespace("\\\\.\\root\\HP\\InstrumentedBIOS"); + * class HPBIOS_PlatformEvents { + * [read] string Name; + * [read] string Description; + * [read] string SourceNamespace; + * [read] string SourceClass; + * [read, ValueMap {"0","1","2","3","4",".."}, Values { + * "Unknown","Configuration Change","Button Pressed", + * "Sensor","BIOS Settings","Reserved"}] + * uint32 Category; + * [read, ValueMap{"0","5","10","15","20","25","30",".."}, + * Values{"Unknown","OK","Degraded/Warning","Minor Failure", + * "Major Failure","Critical Failure","Non-recoverable Error", + * "DMTF Reserved"}] + * uint32 PossibleSeverity; + * [read, ValueMap {"0","1","2","3","4","5","6","7","8","9", + * "10","11","12","13","14","15","16","17","18","..", + * "0x8000.."}, Values {"Unknown","Other","OK","Degraded", + * "Stressed","Predictive Failure","Error", + * "Non-Recoverable Error","Starting","Stopping","Stopped", + * "In Service","No Contact","Lost Communication","Aborted", + * "Dormant","Supporting Entity in Error","Completed", + * "Power Mode","DMTF Reserved","Vendor Reserved"}] + * uint32 PossibleStatus; + * }; + */ +struct hp_wmi_platform_events { + const char *name; + const char *description; + const char *source_namespace; + const char *source_class; + u32 category; + u32 possible_severity; + u32 possible_status; +}; + +/* + * struct hp_wmi_event - a HPBIOS_BIOSEvent instance + * + * Effective MOF definition [1] (corrected below from original): + * + * #pragma namespace("\\\\.\\root\\WMI"); + * class HPBIOS_BIOSEvent : WMIEvent { + * [read] string Name; + * [read] string Description; + * [read ValueMap {"0","1","2","3","4"}, Values {"Unknown", + * "Configuration Change","Button Pressed","Sensor", + * "BIOS Settings"}] + * uint32 Category; + * [read, ValueMap {"0","5","10","15","20","25","30"}, + * Values {"Unknown","OK","Degraded/Warning", + * "Minor Failure","Major Failure","Critical Failure", + * "Non-recoverable Error"}] + * uint32 Severity; + * [read, ValueMap {"0","1","2","3","4","5","6","7","8", + * "9","10","11","12","13","14","15","16","17","18","..", + * "0x8000.."}, Values {"Unknown","Other","OK","Degraded", + * "Stressed","Predictive Failure","Error", + * "Non-Recoverable Error","Starting","Stopping","Stopped", + * "In Service","No Contact","Lost Communication","Aborted", + * "Dormant","Supporting Entity in Error","Completed", + * "Power Mode","DMTF Reserved","Vendor Reserved"}] + * uint32 Status; + * }; + */ +struct hp_wmi_event { + const char *name; + const char *description; + u32 category; +}; + +/* + * struct hp_wmi_info - sensor info + * @nsensor: numeric sensor properties + * @instance: its WMI instance number + * @state: pointer to driver state + * @has_alarm: whether sensor has an alarm flag + * @alarm: alarm flag + * @type: its hwmon sensor type + * @cached_val: current sensor reading value, scaled for hwmon + * @last_updated: when these readings were last updated + */ +struct hp_wmi_info { + struct hp_wmi_numeric_sensor nsensor; + u8 instance; + void *state; /* void *: Avoid forward declaration. */ + bool has_alarm; + bool alarm; + enum hwmon_sensor_types type; + long cached_val; + unsigned long last_updated; /* In jiffies. */ + +}; + +/* + * struct hp_wmi_sensors - driver state + * @wdev: pointer to the parent WMI device + * @info_map: sensor info structs by hwmon type and channel number + * @channel_count: count of hwmon channels by hwmon type + * @has_intrusion: whether an intrusion sensor is present + * @intrusion: intrusion flag + * @lock: mutex to lock polling WMI and changes to driver state + */ +struct hp_wmi_sensors { + struct wmi_device *wdev; + struct hp_wmi_info **info_map[hwmon_max]; + u8 channel_count[hwmon_max]; + bool has_intrusion; + bool intrusion; + + struct mutex lock; /* Lock polling WMI and driver state changes. */ +}; + +/* hp_wmi_strdup - devm_kstrdup, but length-limited */ +static char *hp_wmi_strdup(struct device *dev, const char *src) +{ + char *dst; + size_t len; + + len = strnlen(src, HP_WMI_MAX_STR_SIZE - 1); + + dst = devm_kmalloc(dev, (len + 1) * sizeof(*dst), GFP_KERNEL); + if (!dst) + return NULL; + + strscpy(dst, src, len + 1); + + return dst; +} + +/* + * hp_wmi_get_wobj - poll WMI for a WMI object instance + * @guid: WMI object GUID + * @instance: WMI object instance number + * + * Returns a new WMI object instance on success, or NULL on error. + * Caller must kfree() the result. + */ +static union acpi_object *hp_wmi_get_wobj(const char *guid, u8 instance) +{ + struct acpi_buffer out = { ACPI_ALLOCATE_BUFFER, NULL }; + acpi_status err; + + err = wmi_query_block(guid, instance, &out); + if (ACPI_FAILURE(err)) + return NULL; + + return out.pointer; +} + +/* hp_wmi_wobj_instance_count - find count of WMI object instances */ +static u8 hp_wmi_wobj_instance_count(const char *guid) +{ + u8 hi = HP_WMI_MAX_INSTANCES; + union acpi_object *wobj; + u8 lo = 0; + u8 mid; + + while (lo < hi) { + mid = (lo + hi) / 2; + + wobj = hp_wmi_get_wobj(guid, mid); + if (!wobj) { + hi = mid; + continue; + } + + lo = mid + 1; + kfree(wobj); + } + + return lo; +} + +static int check_wobj(const union acpi_object *wobj, + const acpi_object_type property_map[], int last_prop) +{ + acpi_object_type type = wobj->type; + acpi_object_type valid_type; + union acpi_object *elements; + u32 elem_count; + int prop; + + if (type != ACPI_TYPE_PACKAGE) + return -EINVAL; + + elem_count = wobj->package.count; + if (elem_count != last_prop + 1) + return -EINVAL; + + elements = wobj->package.elements; + for (prop = 0; prop <= last_prop; prop++) { + type = elements[prop].type; + valid_type = property_map[prop]; + if (type != valid_type) + return -EINVAL; + } + + return 0; +} + +static int extract_acpi_value(struct device *dev, + union acpi_object *element, + acpi_object_type type, + u32 *out_value, char **out_string) +{ + switch (type) { + case ACPI_TYPE_INTEGER: + *out_value = element->integer.value; + break; + + case ACPI_TYPE_STRING: + *out_string = hp_wmi_strdup(dev, strim(element->string.pointer)); + if (!*out_string) + return -ENOMEM; + break; + + default: + return -EINVAL; + } + + return 0; +} + +/* + * check_numeric_sensor_wobj - validate a HPBIOS_BIOSNumericSensor instance + * @wobj: pointer to WMI object instance to check + * @out_size: out pointer to count of possible states + * @out_is_new: out pointer to whether this is a "new" variant object + * + * Returns 0 on success, or a negative error code on error. + */ +static int check_numeric_sensor_wobj(const union acpi_object *wobj, + u8 *out_size, bool *out_is_new) +{ + acpi_object_type type = wobj->type; + int prop = HP_WMI_PROPERTY_NAME; + acpi_object_type valid_type; + union acpi_object *elements; + u32 elem_count; + int last_prop; + bool is_new; + u8 count; + u32 j; + u32 i; + + if (type != ACPI_TYPE_PACKAGE) + return -EINVAL; + + /* + * elements is a variable-length array of ACPI objects, one for + * each property of the WMI object instance, except that the + * strings in PossibleStates[] are flattened into this array + * as if each individual string were a property by itself. + */ + elements = wobj->package.elements; + + elem_count = wobj->package.count; + if (elem_count <= HP_WMI_PROPERTY_SIZE || + elem_count > HP_WMI_MAX_PROPERTIES) + return -EINVAL; + + type = elements[HP_WMI_PROPERTY_SIZE].type; + switch (type) { + case ACPI_TYPE_INTEGER: + is_new = true; + last_prop = HP_WMI_PROPERTY_RATE_UNITS; + break; + + case ACPI_TYPE_STRING: + is_new = false; + last_prop = HP_WMI_PROPERTY_CURRENT_READING; + break; + + default: + return -EINVAL; + } + + /* + * In general, the count of PossibleStates[] must be > 0. + * Also, the old variant lacks the Size property, so we may need to + * reduce the value of last_prop by 1 when doing arithmetic with it. + */ + if (elem_count < last_prop - !is_new + 1) + return -EINVAL; + + count = elem_count - (last_prop - !is_new); + + for (i = 0; i < elem_count && prop <= last_prop; i++, prop++) { + type = elements[i].type; + valid_type = hp_wmi_property_map[prop]; + if (type != valid_type) + return -EINVAL; + + switch (prop) { + case HP_WMI_PROPERTY_OPERATIONAL_STATUS: + /* Old variant: CurrentState follows OperationalStatus. */ + if (!is_new) + prop = HP_WMI_PROPERTY_CURRENT_STATE - 1; + break; + + case HP_WMI_PROPERTY_SIZE: + /* New variant: Size == count of PossibleStates[]. */ + if (count != elements[i].integer.value) + return -EINVAL; + break; + + case HP_WMI_PROPERTY_POSSIBLE_STATES: + /* PossibleStates[0] has already been type-checked. */ + for (j = 0; i + 1 < elem_count && j + 1 < count; j++) { + type = elements[++i].type; + if (type != valid_type) + return -EINVAL; + } + + /* Old variant: BaseUnits follows PossibleStates[]. */ + if (!is_new) + prop = HP_WMI_PROPERTY_BASE_UNITS - 1; + break; + + case HP_WMI_PROPERTY_CURRENT_STATE: + /* Old variant: PossibleStates[] follows CurrentState. */ + if (!is_new) + prop = HP_WMI_PROPERTY_POSSIBLE_STATES - 1; + break; + } + } + + if (prop != last_prop + 1) + return -EINVAL; + + *out_size = count; + *out_is_new = is_new; + + return 0; +} + +static int +numeric_sensor_is_connected(const struct hp_wmi_numeric_sensor *nsensor) +{ + u32 operational_status = nsensor->operational_status; + + return operational_status != HP_WMI_STATUS_NO_CONTACT; +} + +static int numeric_sensor_has_fault(const struct hp_wmi_numeric_sensor *nsensor) +{ + u32 operational_status = nsensor->operational_status; + + switch (operational_status) { + case HP_WMI_STATUS_DEGRADED: + case HP_WMI_STATUS_STRESSED: /* e.g. Overload, overtemp. */ + case HP_WMI_STATUS_PREDICTIVE_FAILURE: /* e.g. Fan removed. */ + case HP_WMI_STATUS_ERROR: + case HP_WMI_STATUS_NON_RECOVERABLE_ERROR: + case HP_WMI_STATUS_NO_CONTACT: + case HP_WMI_STATUS_LOST_COMMUNICATION: + case HP_WMI_STATUS_ABORTED: + case HP_WMI_STATUS_SUPPORTING_ENTITY_IN_ERROR: + + /* Assume combination by addition; bitwise OR doesn't make sense. */ + case HP_WMI_STATUS_COMPLETED + HP_WMI_STATUS_DEGRADED: + case HP_WMI_STATUS_COMPLETED + HP_WMI_STATUS_ERROR: + return true; + } + + return false; +} + +/* scale_numeric_sensor - scale sensor reading for hwmon */ +static long scale_numeric_sensor(const struct hp_wmi_numeric_sensor *nsensor) +{ + u32 current_reading = nsensor->current_reading; + s32 unit_modifier = nsensor->unit_modifier; + u32 sensor_type = nsensor->sensor_type; + u32 base_units = nsensor->base_units; + s32 target_modifier; + long val; + + /* Fan readings are in RPM units; others are in milliunits. */ + target_modifier = sensor_type == HP_WMI_TYPE_AIR_FLOW ? 0 : -3; + + val = current_reading; + + for (; unit_modifier < target_modifier; unit_modifier++) + val = DIV_ROUND_CLOSEST(val, 10); + + for (; unit_modifier > target_modifier; unit_modifier--) { + if (val > LONG_MAX / 10) { + val = LONG_MAX; + break; + } + val *= 10; + } + + if (sensor_type == HP_WMI_TYPE_TEMPERATURE) { + switch (base_units) { + case HP_WMI_UNITS_DEGREES_F: + val -= MILLI * 32; + val = val <= LONG_MAX / 5 ? + DIV_ROUND_CLOSEST(val * 5, 9) : + DIV_ROUND_CLOSEST(val, 9) * 5; + break; + + case HP_WMI_UNITS_DEGREES_K: + val = milli_kelvin_to_millicelsius(val); + break; + } + } + + return val; +} + +/* + * classify_numeric_sensor - classify a numeric sensor + * @nsensor: pointer to numeric sensor struct + * + * Returns an enum hp_wmi_type value on success, + * or a negative value if the sensor type is unsupported. + */ +static int classify_numeric_sensor(const struct hp_wmi_numeric_sensor *nsensor) +{ + u32 sensor_type = nsensor->sensor_type; + u32 base_units = nsensor->base_units; + const char *name = nsensor->name; + + switch (sensor_type) { + case HP_WMI_TYPE_TEMPERATURE: + /* + * Some systems have sensors named "X Thermal Index" in "Other" + * units. Tested CPU sensor examples were found to be in °C, + * albeit perhaps "differently" accurate; e.g. readings were + * reliably -6°C vs. coretemp on a HP Compaq Elite 8300, and + * +8°C on an EliteOne G1 800. But this is still within the + * realm of plausibility for cheaply implemented motherboard + * sensors, and chassis readings were about as expected. + */ + if ((base_units == HP_WMI_UNITS_OTHER && + strstr(name, HP_WMI_PATTERN_TEMP_SENSOR)) || + base_units == HP_WMI_UNITS_DEGREES_C || + base_units == HP_WMI_UNITS_DEGREES_F || + base_units == HP_WMI_UNITS_DEGREES_K) + return HP_WMI_TYPE_TEMPERATURE; + break; + + case HP_WMI_TYPE_VOLTAGE: + if (base_units == HP_WMI_UNITS_VOLTS) + return HP_WMI_TYPE_VOLTAGE; + break; + + case HP_WMI_TYPE_CURRENT: + if (base_units == HP_WMI_UNITS_AMPS) + return HP_WMI_TYPE_CURRENT; + break; + + case HP_WMI_TYPE_AIR_FLOW: + /* + * Strangely, HP considers fan RPM sensor type to be + * "Air Flow" instead of the more intuitive "Tachometer". + */ + if (base_units == HP_WMI_UNITS_RPM) + return HP_WMI_TYPE_AIR_FLOW; + break; + } + + return -EINVAL; +} + +static int +populate_numeric_sensor_from_wobj(struct device *dev, + struct hp_wmi_numeric_sensor *nsensor, + union acpi_object *wobj, bool *out_is_new) +{ + int last_prop = HP_WMI_PROPERTY_RATE_UNITS; + int prop = HP_WMI_PROPERTY_NAME; + const char **possible_states; + union acpi_object *element; + acpi_object_type type; + char *string; + bool is_new; + u32 value; + u8 size; + int err; + + err = check_numeric_sensor_wobj(wobj, &size, &is_new); + if (err) + return err; + + possible_states = devm_kcalloc(dev, size, sizeof(*possible_states), + GFP_KERNEL); + if (!possible_states) + return -ENOMEM; + + element = wobj->package.elements; + nsensor->possible_states = possible_states; + nsensor->size = size; + + if (!is_new) + last_prop = HP_WMI_PROPERTY_CURRENT_READING; + + for (; prop <= last_prop; prop++) { + type = hp_wmi_property_map[prop]; + + err = extract_acpi_value(dev, element, type, &value, &string); + if (err) + return err; + + element++; + + switch (prop) { + case HP_WMI_PROPERTY_NAME: + nsensor->name = string; + break; + + case HP_WMI_PROPERTY_DESCRIPTION: + nsensor->description = string; + break; + + case HP_WMI_PROPERTY_SENSOR_TYPE: + if (value > HP_WMI_TYPE_AIR_FLOW) + return -EINVAL; + + nsensor->sensor_type = value; + break; + + case HP_WMI_PROPERTY_OTHER_SENSOR_TYPE: + nsensor->other_sensor_type = string; + break; + + case HP_WMI_PROPERTY_OPERATIONAL_STATUS: + nsensor->operational_status = value; + + /* Old variant: CurrentState follows OperationalStatus. */ + if (!is_new) + prop = HP_WMI_PROPERTY_CURRENT_STATE - 1; + break; + + case HP_WMI_PROPERTY_SIZE: + break; /* Already set. */ + + case HP_WMI_PROPERTY_POSSIBLE_STATES: + *possible_states++ = string; + if (--size) + prop--; + + /* Old variant: BaseUnits follows PossibleStates[]. */ + if (!is_new && !size) + prop = HP_WMI_PROPERTY_BASE_UNITS - 1; + break; + + case HP_WMI_PROPERTY_CURRENT_STATE: + nsensor->current_state = string; + + /* Old variant: PossibleStates[] follows CurrentState. */ + if (!is_new) + prop = HP_WMI_PROPERTY_POSSIBLE_STATES - 1; + break; + + case HP_WMI_PROPERTY_BASE_UNITS: + nsensor->base_units = value; + break; + + case HP_WMI_PROPERTY_UNIT_MODIFIER: + /* UnitModifier is signed. */ + nsensor->unit_modifier = (s32)value; + break; + + case HP_WMI_PROPERTY_CURRENT_READING: + nsensor->current_reading = value; + break; + + case HP_WMI_PROPERTY_RATE_UNITS: + nsensor->rate_units = value; + break; + + default: + return -EINVAL; + } + } + + *out_is_new = is_new; + + return 0; +} + +/* update_numeric_sensor_from_wobj - update fungible sensor properties */ +static void +update_numeric_sensor_from_wobj(struct device *dev, + struct hp_wmi_numeric_sensor *nsensor, + const union acpi_object *wobj) +{ + const union acpi_object *elements; + const union acpi_object *element; + const char *string; + bool is_new; + int offset; + u8 size; + int err; + + err = check_numeric_sensor_wobj(wobj, &size, &is_new); + if (err) + return; + + elements = wobj->package.elements; + + element = &elements[HP_WMI_PROPERTY_OPERATIONAL_STATUS]; + nsensor->operational_status = element->integer.value; + + /* + * In general, an index offset is needed after PossibleStates[0]. + * On a new variant, CurrentState is after PossibleStates[]. This is + * not the case on an old variant, but we still need to offset the + * read because CurrentState is where Size would be on a new variant. + */ + offset = is_new ? size - 1 : -2; + + element = &elements[HP_WMI_PROPERTY_CURRENT_STATE + offset]; + string = strim(element->string.pointer); + + if (strcmp(string, nsensor->current_state)) { + devm_kfree(dev, nsensor->current_state); + nsensor->current_state = hp_wmi_strdup(dev, string); + } + + /* Old variant: -2 (not -1) because it lacks the Size property. */ + if (!is_new) + offset = (int)size - 2; /* size is > 0, i.e. may be 1. */ + + element = &elements[HP_WMI_PROPERTY_UNIT_MODIFIER + offset]; + nsensor->unit_modifier = (s32)element->integer.value; + + element = &elements[HP_WMI_PROPERTY_CURRENT_READING + offset]; + nsensor->current_reading = element->integer.value; +} + +/* + * check_platform_events_wobj - validate a HPBIOS_PlatformEvents instance + * @wobj: pointer to WMI object instance to check + * + * Returns 0 on success, or a negative error code on error. + */ +static int check_platform_events_wobj(const union acpi_object *wobj) +{ + return check_wobj(wobj, hp_wmi_platform_events_property_map, + HP_WMI_PLATFORM_EVENTS_PROPERTY_POSSIBLE_STATUS); +} + +static int +populate_platform_events_from_wobj(struct device *dev, + struct hp_wmi_platform_events *pevents, + union acpi_object *wobj) +{ + int last_prop = HP_WMI_PLATFORM_EVENTS_PROPERTY_POSSIBLE_STATUS; + int prop = HP_WMI_PLATFORM_EVENTS_PROPERTY_NAME; + union acpi_object *element; + acpi_object_type type; + char *string; + u32 value; + int err; + + err = check_platform_events_wobj(wobj); + if (err) + return err; + + element = wobj->package.elements; + + for (; prop <= last_prop; prop++, element++) { + type = hp_wmi_platform_events_property_map[prop]; + + err = extract_acpi_value(dev, element, type, &value, &string); + if (err) + return err; + + switch (prop) { + case HP_WMI_PLATFORM_EVENTS_PROPERTY_NAME: + pevents->name = string; + break; + + case HP_WMI_PLATFORM_EVENTS_PROPERTY_DESCRIPTION: + pevents->description = string; + break; + + case HP_WMI_PLATFORM_EVENTS_PROPERTY_SOURCE_NAMESPACE: + if (strcasecmp(HP_WMI_EVENT_NAMESPACE, string)) + return -EINVAL; + + pevents->source_namespace = string; + break; + + case HP_WMI_PLATFORM_EVENTS_PROPERTY_SOURCE_CLASS: + if (strcasecmp(HP_WMI_EVENT_CLASS, string)) + return -EINVAL; + + pevents->source_class = string; + break; + + case HP_WMI_PLATFORM_EVENTS_PROPERTY_CATEGORY: + pevents->category = value; + break; + + case HP_WMI_PLATFORM_EVENTS_PROPERTY_POSSIBLE_SEVERITY: + pevents->possible_severity = value; + break; + + case HP_WMI_PLATFORM_EVENTS_PROPERTY_POSSIBLE_STATUS: + pevents->possible_status = value; + break; + + default: + return -EINVAL; + } + } + + return 0; +} + +/* + * check_event_wobj - validate a HPBIOS_BIOSEvent instance + * @wobj: pointer to WMI object instance to check + * + * Returns 0 on success, or a negative error code on error. + */ +static int check_event_wobj(const union acpi_object *wobj) +{ + return check_wobj(wobj, hp_wmi_event_property_map, + HP_WMI_EVENT_PROPERTY_STATUS); +} + +static int populate_event_from_wobj(struct hp_wmi_event *event, + union acpi_object *wobj) +{ + int prop = HP_WMI_EVENT_PROPERTY_NAME; + union acpi_object *element; + int err; + + err = check_event_wobj(wobj); + if (err) + return err; + + element = wobj->package.elements; + + /* Extracted strings are NOT device-managed copies. */ + + for (; prop <= HP_WMI_EVENT_PROPERTY_CATEGORY; prop++, element++) { + switch (prop) { + case HP_WMI_EVENT_PROPERTY_NAME: + event->name = strim(element->string.pointer); + break; + + case HP_WMI_EVENT_PROPERTY_DESCRIPTION: + event->description = strim(element->string.pointer); + break; + + case HP_WMI_EVENT_PROPERTY_CATEGORY: + event->category = element->integer.value; + break; + + default: + return -EINVAL; + } + } + + return 0; +} + +/* + * classify_event - classify an event + * @name: event name + * @category: event category + * + * Classify instances of both HPBIOS_PlatformEvents and HPBIOS_BIOSEvent from + * property values. Recognition criteria are based on multiple ACPI dumps [3]. + * + * Returns an enum hp_wmi_type value on success, + * or a negative value if the event type is unsupported. + */ +static int classify_event(const char *event_name, u32 category) +{ + if (category != HP_WMI_CATEGORY_SENSOR) + return -EINVAL; + + /* Fan events have Name "X Stall". */ + if (strstr(event_name, HP_WMI_PATTERN_FAN_ALARM)) + return HP_WMI_TYPE_AIR_FLOW; + + /* Intrusion events have Name "Hood Intrusion". */ + if (!strcmp(event_name, HP_WMI_PATTERN_INTRUSION_ALARM)) + return HP_WMI_TYPE_INTRUSION; + + /* + * Temperature events have Name either "Thermal Caution" or + * "Thermal Critical". Deal only with "Thermal Critical" events. + * + * "Thermal Caution" events have Status "Stressed", informing us that + * the OperationalStatus of the related sensor has become "Stressed". + * However, this is already a fault condition that will clear itself + * when the sensor recovers, so we have no further interest in them. + */ + if (!strcmp(event_name, HP_WMI_PATTERN_TEMP_ALARM)) + return HP_WMI_TYPE_TEMPERATURE; + + return -EINVAL; +} + +/* + * interpret_info - interpret sensor for hwmon + * @info: pointer to sensor info struct + * + * Should be called after the numeric sensor member has been updated. + */ +static void interpret_info(struct hp_wmi_info *info) +{ + const struct hp_wmi_numeric_sensor *nsensor = &info->nsensor; + + info->cached_val = scale_numeric_sensor(nsensor); + info->last_updated = jiffies; +} + +/* + * hp_wmi_update_info - poll WMI to update sensor info + * @state: pointer to driver state + * @info: pointer to sensor info struct + * + * Returns 0 on success, or a negative error code on error. + */ +static int hp_wmi_update_info(struct hp_wmi_sensors *state, + struct hp_wmi_info *info) +{ + struct hp_wmi_numeric_sensor *nsensor = &info->nsensor; + struct device *dev = &state->wdev->dev; + const union acpi_object *wobj; + u8 instance = info->instance; + int ret = 0; + + if (time_after(jiffies, info->last_updated + HZ)) { + mutex_lock(&state->lock); + + wobj = hp_wmi_get_wobj(HP_WMI_NUMERIC_SENSOR_GUID, instance); + if (!wobj) { + ret = -EIO; + goto out_unlock; + } + + update_numeric_sensor_from_wobj(dev, nsensor, wobj); + + interpret_info(info); + + kfree(wobj); + +out_unlock: + mutex_unlock(&state->lock); + } + + return ret; +} + +static int basic_string_show(struct seq_file *seqf, void *ignored) +{ + const char *str = seqf->private; + + seq_printf(seqf, "%s\n", str); + + return 0; +} +DEFINE_SHOW_ATTRIBUTE(basic_string); + +static int fungible_show(struct seq_file *seqf, enum hp_wmi_property prop) +{ + struct hp_wmi_numeric_sensor *nsensor; + struct hp_wmi_sensors *state; + struct hp_wmi_info *info; + int err; + + info = seqf->private; + state = info->state; + nsensor = &info->nsensor; + + err = hp_wmi_update_info(state, info); + if (err) + return err; + + switch (prop) { + case HP_WMI_PROPERTY_OPERATIONAL_STATUS: + seq_printf(seqf, "%u\n", nsensor->operational_status); + break; + + case HP_WMI_PROPERTY_CURRENT_STATE: + seq_printf(seqf, "%s\n", nsensor->current_state); + break; + + case HP_WMI_PROPERTY_UNIT_MODIFIER: + seq_printf(seqf, "%d\n", nsensor->unit_modifier); + break; + + case HP_WMI_PROPERTY_CURRENT_READING: + seq_printf(seqf, "%u\n", nsensor->current_reading); + break; + + default: + return -EOPNOTSUPP; + } + + return 0; +} + +static int operational_status_show(struct seq_file *seqf, void *ignored) +{ + return fungible_show(seqf, HP_WMI_PROPERTY_OPERATIONAL_STATUS); +} +DEFINE_SHOW_ATTRIBUTE(operational_status); + +static int current_state_show(struct seq_file *seqf, void *ignored) +{ + return fungible_show(seqf, HP_WMI_PROPERTY_CURRENT_STATE); +} +DEFINE_SHOW_ATTRIBUTE(current_state); + +static int possible_states_show(struct seq_file *seqf, void *ignored) +{ + struct hp_wmi_numeric_sensor *nsensor = seqf->private; + u8 i; + + for (i = 0; i < nsensor->size; i++) + seq_printf(seqf, "%s%s", i ? "," : "", + nsensor->possible_states[i]); + + seq_puts(seqf, "\n"); + + return 0; +} +DEFINE_SHOW_ATTRIBUTE(possible_states); + +static int unit_modifier_show(struct seq_file *seqf, void *ignored) +{ + return fungible_show(seqf, HP_WMI_PROPERTY_UNIT_MODIFIER); +} +DEFINE_SHOW_ATTRIBUTE(unit_modifier); + +static int current_reading_show(struct seq_file *seqf, void *ignored) +{ + return fungible_show(seqf, HP_WMI_PROPERTY_CURRENT_READING); +} +DEFINE_SHOW_ATTRIBUTE(current_reading); + +/* hp_wmi_devm_debugfs_remove - devm callback for debugfs cleanup */ +static void hp_wmi_devm_debugfs_remove(void *res) +{ + debugfs_remove_recursive(res); +} + +/* hp_wmi_debugfs_init - create and populate debugfs directory tree */ +static void hp_wmi_debugfs_init(struct device *dev, struct hp_wmi_info *info, + struct hp_wmi_platform_events *pevents, + u8 icount, u8 pcount, bool is_new) +{ + struct hp_wmi_numeric_sensor *nsensor; + char buf[HP_WMI_MAX_STR_SIZE]; + struct dentry *debugfs; + struct dentry *entries; + struct dentry *dir; + int err; + u8 i; + + /* dev_name() gives a not-very-friendly GUID for WMI devices. */ + scnprintf(buf, sizeof(buf), "hp-wmi-sensors-%u", dev->id); + + debugfs = debugfs_create_dir(buf, NULL); + if (IS_ERR(debugfs)) + return; + + err = devm_add_action_or_reset(dev, hp_wmi_devm_debugfs_remove, + debugfs); + if (err) + return; + + entries = debugfs_create_dir("sensor", debugfs); + + for (i = 0; i < icount; i++, info++) { + nsensor = &info->nsensor; + + scnprintf(buf, sizeof(buf), "%u", i); + dir = debugfs_create_dir(buf, entries); + + debugfs_create_file("name", 0444, dir, + (void *)nsensor->name, + &basic_string_fops); + + debugfs_create_file("description", 0444, dir, + (void *)nsensor->description, + &basic_string_fops); + + debugfs_create_u32("sensor_type", 0444, dir, + &nsensor->sensor_type); + + debugfs_create_file("other_sensor_type", 0444, dir, + (void *)nsensor->other_sensor_type, + &basic_string_fops); + + debugfs_create_file("operational_status", 0444, dir, + info, &operational_status_fops); + + debugfs_create_file("possible_states", 0444, dir, + nsensor, &possible_states_fops); + + debugfs_create_file("current_state", 0444, dir, + info, ¤t_state_fops); + + debugfs_create_u32("base_units", 0444, dir, + &nsensor->base_units); + + debugfs_create_file("unit_modifier", 0444, dir, + info, &unit_modifier_fops); + + debugfs_create_file("current_reading", 0444, dir, + info, ¤t_reading_fops); + + if (is_new) + debugfs_create_u32("rate_units", 0444, dir, + &nsensor->rate_units); + } + + if (!pcount) + return; + + entries = debugfs_create_dir("platform_events", debugfs); + + for (i = 0; i < pcount; i++, pevents++) { + scnprintf(buf, sizeof(buf), "%u", i); + dir = debugfs_create_dir(buf, entries); + + debugfs_create_file("name", 0444, dir, + (void *)pevents->name, + &basic_string_fops); + + debugfs_create_file("description", 0444, dir, + (void *)pevents->description, + &basic_string_fops); + + debugfs_create_file("source_namespace", 0444, dir, + (void *)pevents->source_namespace, + &basic_string_fops); + + debugfs_create_file("source_class", 0444, dir, + (void *)pevents->source_class, + &basic_string_fops); + + debugfs_create_u32("category", 0444, dir, + &pevents->category); + + debugfs_create_u32("possible_severity", 0444, dir, + &pevents->possible_severity); + + debugfs_create_u32("possible_status", 0444, dir, + &pevents->possible_status); + } +} + +static umode_t hp_wmi_hwmon_is_visible(const void *drvdata, + enum hwmon_sensor_types type, + u32 attr, int channel) +{ + const struct hp_wmi_sensors *state = drvdata; + const struct hp_wmi_info *info; + + if (type == hwmon_intrusion) + return state->has_intrusion ? 0644 : 0; + + if (!state->info_map[type] || !state->info_map[type][channel]) + return 0; + + info = state->info_map[type][channel]; + + if ((type == hwmon_temp && attr == hwmon_temp_alarm) || + (type == hwmon_fan && attr == hwmon_fan_alarm)) + return info->has_alarm ? 0444 : 0; + + return 0444; +} + +static int hp_wmi_hwmon_read(struct device *dev, enum hwmon_sensor_types type, + u32 attr, int channel, long *out_val) +{ + struct hp_wmi_sensors *state = dev_get_drvdata(dev); + const struct hp_wmi_numeric_sensor *nsensor; + struct hp_wmi_info *info; + int err; + + if (type == hwmon_intrusion) { + *out_val = state->intrusion ? 1 : 0; + + return 0; + } + + info = state->info_map[type][channel]; + + if ((type == hwmon_temp && attr == hwmon_temp_alarm) || + (type == hwmon_fan && attr == hwmon_fan_alarm)) { + *out_val = info->alarm ? 1 : 0; + info->alarm = false; + + return 0; + } + + nsensor = &info->nsensor; + + err = hp_wmi_update_info(state, info); + if (err) + return err; + + if ((type == hwmon_temp && attr == hwmon_temp_fault) || + (type == hwmon_fan && attr == hwmon_fan_fault)) + *out_val = numeric_sensor_has_fault(nsensor); + else + *out_val = info->cached_val; + + return 0; +} + +static int hp_wmi_hwmon_read_string(struct device *dev, + enum hwmon_sensor_types type, u32 attr, + int channel, const char **out_str) +{ + const struct hp_wmi_sensors *state = dev_get_drvdata(dev); + const struct hp_wmi_info *info; + + info = state->info_map[type][channel]; + *out_str = info->nsensor.name; + + return 0; +} + +static int hp_wmi_hwmon_write(struct device *dev, enum hwmon_sensor_types type, + u32 attr, int channel, long val) +{ + struct hp_wmi_sensors *state = dev_get_drvdata(dev); + + if (val) + return -EINVAL; + + mutex_lock(&state->lock); + + state->intrusion = false; + + mutex_unlock(&state->lock); + + return 0; +} + +static const struct hwmon_ops hp_wmi_hwmon_ops = { + .is_visible = hp_wmi_hwmon_is_visible, + .read = hp_wmi_hwmon_read, + .read_string = hp_wmi_hwmon_read_string, + .write = hp_wmi_hwmon_write, +}; + +static struct hwmon_chip_info hp_wmi_chip_info = { + .ops = &hp_wmi_hwmon_ops, + .info = NULL, +}; + +static struct hp_wmi_info *match_fan_event(struct hp_wmi_sensors *state, + const char *event_description) +{ + struct hp_wmi_info **ptr_info = state->info_map[hwmon_fan]; + u8 fan_count = state->channel_count[hwmon_fan]; + struct hp_wmi_info *info; + const char *name; + u8 i; + + /* Fan event has Description "X Speed". Sensor has Name "X[ Speed]". */ + + for (i = 0; i < fan_count; i++, ptr_info++) { + info = *ptr_info; + name = info->nsensor.name; + + if (strstr(event_description, name)) + return info; + } + + return NULL; +} + +static u8 match_temp_events(struct hp_wmi_sensors *state, + const char *event_description, + struct hp_wmi_info *temp_info[]) +{ + struct hp_wmi_info **ptr_info = state->info_map[hwmon_temp]; + u8 temp_count = state->channel_count[hwmon_temp]; + struct hp_wmi_info *info; + const char *name; + u8 count = 0; + bool is_cpu; + bool is_sys; + u8 i; + + /* Description is either "CPU Thermal Index" or "Chassis Thermal Index". */ + + is_cpu = !strcmp(event_description, HP_WMI_PATTERN_CPU_TEMP); + is_sys = !strcmp(event_description, HP_WMI_PATTERN_SYS_TEMP); + if (!is_cpu && !is_sys) + return 0; + + /* + * CPU event: Match one sensor with Name either "CPU Thermal Index" or + * "CPU Temperature", or multiple with Name(s) "CPU[#] Temperature". + * + * Chassis event: Match one sensor with Name either + * "Chassis Thermal Index" or "System Ambient Temperature". + */ + + for (i = 0; i < temp_count; i++, ptr_info++) { + info = *ptr_info; + name = info->nsensor.name; + + if ((is_cpu && (!strcmp(name, HP_WMI_PATTERN_CPU_TEMP) || + !strcmp(name, HP_WMI_PATTERN_CPU_TEMP2))) || + (is_sys && (!strcmp(name, HP_WMI_PATTERN_SYS_TEMP) || + !strcmp(name, HP_WMI_PATTERN_SYS_TEMP2)))) { + temp_info[0] = info; + return 1; + } + + if (is_cpu && (strstr(name, HP_WMI_PATTERN_CPU) && + strstr(name, HP_WMI_PATTERN_TEMP))) + temp_info[count++] = info; + } + + return count; +} + +/* hp_wmi_devm_debugfs_remove - devm callback for WMI event handler removal */ +static void hp_wmi_devm_notify_remove(void *ignored) +{ + wmi_remove_notify_handler(HP_WMI_EVENT_GUID); +} + +/* hp_wmi_notify - WMI event notification handler */ +static void hp_wmi_notify(u32 value, void *context) +{ + struct hp_wmi_info *temp_info[HP_WMI_MAX_INSTANCES] = {}; + struct acpi_buffer out = { ACPI_ALLOCATE_BUFFER, NULL }; + struct hp_wmi_sensors *state = context; + struct device *dev = &state->wdev->dev; + struct hp_wmi_info *fan_info; + struct hp_wmi_event event; + union acpi_object *wobj; + acpi_status err; + int event_type; + u8 count; + + /* + * The following warning may occur in the kernel log: + * + * ACPI Warning: \_SB.WMID._WED: Return type mismatch - + * found Package, expected Integer/String/Buffer + * + * After using [4] to decode BMOF blobs found in [3], careless copying + * of BIOS code seems the most likely explanation for this warning. + * HP_WMI_EVENT_GUID refers to \\.\root\WMI\HPBIOS_BIOSEvent on + * business-class systems, but it refers to \\.\root\WMI\hpqBEvnt on + * non-business-class systems. Per the existing hp-wmi driver, it + * looks like an instance of hpqBEvnt delivered as event data may + * indeed take the form of a raw ACPI_BUFFER on non-business-class + * systems ("may" because ASL shows some BIOSes do strange things). + * + * In any case, we can ignore this warning, because we always validate + * the event data to ensure it is an ACPI_PACKAGE containing a + * HPBIOS_BIOSEvent instance. + */ + + mutex_lock(&state->lock); + + err = wmi_get_event_data(value, &out); + if (ACPI_FAILURE(err)) + goto out_unlock; + + wobj = out.pointer; + + err = populate_event_from_wobj(&event, wobj); + if (err) { + dev_warn(dev, "Bad event data (ACPI type %d)\n", wobj->type); + goto out_free_wobj; + } + + event_type = classify_event(event.name, event.category); + switch (event_type) { + case HP_WMI_TYPE_AIR_FLOW: + fan_info = match_fan_event(state, event.description); + if (fan_info) + fan_info->alarm = true; + break; + + case HP_WMI_TYPE_INTRUSION: + state->intrusion = true; + break; + + case HP_WMI_TYPE_TEMPERATURE: + count = match_temp_events(state, event.description, temp_info); + while (count) + temp_info[--count]->alarm = true; + break; + + default: + break; + } + +out_free_wobj: + kfree(wobj); + +out_unlock: + mutex_unlock(&state->lock); +} + +static int init_platform_events(struct device *dev, + struct hp_wmi_platform_events **out_pevents, + u8 *out_pcount) +{ + struct hp_wmi_platform_events *pevents_arr; + struct hp_wmi_platform_events *pevents; + union acpi_object *wobj; + u8 count; + int err; + u8 i; + + count = hp_wmi_wobj_instance_count(HP_WMI_PLATFORM_EVENTS_GUID); + if (!count) { + *out_pcount = 0; + + dev_dbg(dev, "No platform events\n"); + + return 0; + } + + pevents_arr = devm_kcalloc(dev, count, sizeof(*pevents), GFP_KERNEL); + if (!pevents_arr) + return -ENOMEM; + + for (i = 0, pevents = pevents_arr; i < count; i++, pevents++) { + wobj = hp_wmi_get_wobj(HP_WMI_PLATFORM_EVENTS_GUID, i); + if (!wobj) + return -EIO; + + err = populate_platform_events_from_wobj(dev, pevents, wobj); + + kfree(wobj); + + if (err) + return err; + } + + *out_pevents = pevents_arr; + *out_pcount = count; + + dev_dbg(dev, "Found %u platform events\n", count); + + return 0; +} + +static int init_numeric_sensors(struct hp_wmi_sensors *state, + struct hp_wmi_info *connected[], + struct hp_wmi_info **out_info, + u8 *out_icount, u8 *out_count, + bool *out_is_new) +{ + struct hp_wmi_info ***info_map = state->info_map; + u8 *channel_count = state->channel_count; + struct device *dev = &state->wdev->dev; + struct hp_wmi_numeric_sensor *nsensor; + u8 channel_index[hwmon_max] = {}; + enum hwmon_sensor_types type; + struct hp_wmi_info *info_arr; + struct hp_wmi_info *info; + union acpi_object *wobj; + u8 count = 0; + bool is_new; + u8 icount; + int wtype; + int err; + u8 c; + u8 i; + + icount = hp_wmi_wobj_instance_count(HP_WMI_NUMERIC_SENSOR_GUID); + if (!icount) + return -ENODATA; + + info_arr = devm_kcalloc(dev, icount, sizeof(*info), GFP_KERNEL); + if (!info_arr) + return -ENOMEM; + + for (i = 0, info = info_arr; i < icount; i++, info++) { + wobj = hp_wmi_get_wobj(HP_WMI_NUMERIC_SENSOR_GUID, i); + if (!wobj) + return -EIO; + + info->instance = i; + info->state = state; + nsensor = &info->nsensor; + + err = populate_numeric_sensor_from_wobj(dev, nsensor, wobj, + &is_new); + + kfree(wobj); + + if (err) + return err; + + if (!numeric_sensor_is_connected(nsensor)) + continue; + + wtype = classify_numeric_sensor(nsensor); + if (wtype < 0) + continue; + + type = hp_wmi_hwmon_type_map[wtype]; + + channel_count[type]++; + + info->type = type; + + interpret_info(info); + + connected[count++] = info; + } + + dev_dbg(dev, "Found %u sensors (%u connected)\n", i, count); + + for (i = 0; i < count; i++) { + info = connected[i]; + type = info->type; + c = channel_index[type]++; + + if (!info_map[type]) { + info_map[type] = devm_kcalloc(dev, channel_count[type], + sizeof(*info_map), + GFP_KERNEL); + if (!info_map[type]) + return -ENOMEM; + } + + info_map[type][c] = info; + } + + *out_info = info_arr; + *out_icount = icount; + *out_count = count; + *out_is_new = is_new; + + return 0; +} + +static bool find_event_attributes(struct hp_wmi_sensors *state, + struct hp_wmi_platform_events *pevents, + u8 pevents_count) +{ + /* + * The existence of this HPBIOS_PlatformEvents instance: + * + * { + * Name = "Rear Chassis Fan0 Stall"; + * Description = "Rear Chassis Fan0 Speed"; + * Category = 3; // "Sensor" + * PossibleSeverity = 25; // "Critical Failure" + * PossibleStatus = 5; // "Predictive Failure" + * [...] + * } + * + * means that this HPBIOS_BIOSEvent instance may occur: + * + * { + * Name = "Rear Chassis Fan0 Stall"; + * Description = "Rear Chassis Fan0 Speed"; + * Category = 3; // "Sensor" + * Severity = 25; // "Critical Failure" + * Status = 5; // "Predictive Failure" + * } + * + * After the event occurs (e.g. because the fan was unplugged), + * polling the related HPBIOS_BIOSNumericSensor instance gives: + * + * { + * Name = "Rear Chassis Fan0"; + * Description = "Reports rear chassis fan0 speed"; + * OperationalStatus = 5; // "Predictive Failure", was 3 ("OK") + * CurrentReading = 0; + * [...] + * } + * + * In this example, the hwmon fan channel for "Rear Chassis Fan0" + * should support the alarm flag and have it be set if the related + * HPBIOS_BIOSEvent instance occurs. + * + * In addition to fan events, temperature (CPU/chassis) and intrusion + * events are relevant to hwmon [2]. Note that much information in [2] + * is unreliable; it is referenced in addition to ACPI dumps [3] merely + * to support the conclusion that sensor and event names/descriptions + * are systematic enough to allow this driver to match them. + * + * Complications and limitations: + * + * - Strings are freeform and may vary, cf. sensor Name "CPU0 Fan" + * on a Z420 vs. "CPU Fan Speed" on an EliteOne 800 G1. + * - Leading/trailing whitespace is a rare but real possibility [3]. + * - The HPBIOS_PlatformEvents object may not exist or its instances + * may show that the system only has e.g. BIOS setting-related + * events (cf. the ProBook 4540s and ProBook 470 G0 [3]). + */ + + struct hp_wmi_info *temp_info[HP_WMI_MAX_INSTANCES] = {}; + const char *event_description; + struct hp_wmi_info *fan_info; + bool has_events = false; + const char *event_name; + u32 event_category; + int event_type; + u8 count; + u8 i; + + for (i = 0; i < pevents_count; i++, pevents++) { + event_name = pevents->name; + event_description = pevents->description; + event_category = pevents->category; + + event_type = classify_event(event_name, event_category); + switch (event_type) { + case HP_WMI_TYPE_AIR_FLOW: + fan_info = match_fan_event(state, event_description); + if (!fan_info) + break; + + fan_info->has_alarm = true; + has_events = true; + break; + + case HP_WMI_TYPE_INTRUSION: + state->has_intrusion = true; + has_events = true; + break; + + case HP_WMI_TYPE_TEMPERATURE: + count = match_temp_events(state, event_description, + temp_info); + if (!count) + break; + + while (count) + temp_info[--count]->has_alarm = true; + has_events = true; + break; + + default: + break; + } + } + + return has_events; +} + +static int make_chip_info(struct hp_wmi_sensors *state, bool has_events) +{ + const struct hwmon_channel_info **ptr_channel_info; + struct hp_wmi_info ***info_map = state->info_map; + u8 *channel_count = state->channel_count; + struct hwmon_channel_info *channel_info; + struct device *dev = &state->wdev->dev; + enum hwmon_sensor_types type; + u8 type_count = 0; + u32 *config; + u32 attr; + u8 count; + u8 i; + + if (channel_count[hwmon_temp]) + channel_count[hwmon_chip] = 1; + + if (has_events && state->has_intrusion) + channel_count[hwmon_intrusion] = 1; + + for (type = hwmon_chip; type < hwmon_max; type++) + if (channel_count[type]) + type_count++; + + channel_info = devm_kcalloc(dev, type_count, + sizeof(*channel_info), GFP_KERNEL); + if (!channel_info) + return -ENOMEM; + + ptr_channel_info = devm_kcalloc(dev, type_count + 1, + sizeof(*ptr_channel_info), GFP_KERNEL); + if (!ptr_channel_info) + return -ENOMEM; + + hp_wmi_chip_info.info = ptr_channel_info; + + for (type = hwmon_chip; type < hwmon_max; type++) { + count = channel_count[type]; + if (!count) + continue; + + config = devm_kcalloc(dev, count + 1, + sizeof(*config), GFP_KERNEL); + if (!config) + return -ENOMEM; + + attr = hp_wmi_hwmon_attributes[type]; + channel_info->type = type; + channel_info->config = config; + memset32(config, attr, count); + + *ptr_channel_info++ = channel_info++; + + if (!has_events || (type != hwmon_temp && type != hwmon_fan)) + continue; + + attr = type == hwmon_temp ? HWMON_T_ALARM : HWMON_F_ALARM; + + for (i = 0; i < count; i++) + if (info_map[type][i]->has_alarm) + config[i] |= attr; + } + + return 0; +} + +static bool add_event_handler(struct hp_wmi_sensors *state) +{ + struct device *dev = &state->wdev->dev; + int err; + + err = wmi_install_notify_handler(HP_WMI_EVENT_GUID, + hp_wmi_notify, state); + if (err) { + dev_info(dev, "Failed to subscribe to WMI event\n"); + return false; + } + + err = devm_add_action_or_reset(dev, hp_wmi_devm_notify_remove, NULL); + if (err) + return false; + + return true; +} + +static int hp_wmi_sensors_init(struct hp_wmi_sensors *state) +{ + struct hp_wmi_info *connected[HP_WMI_MAX_INSTANCES]; + struct hp_wmi_platform_events *pevents; + struct device *dev = &state->wdev->dev; + struct hp_wmi_info *info; + struct device *hwdev; + bool has_events; + bool is_new; + u8 icount; + u8 pcount; + u8 count; + int err; + + err = init_platform_events(dev, &pevents, &pcount); + if (err) + return err; + + err = init_numeric_sensors(state, connected, &info, + &icount, &count, &is_new); + if (err) + return err; + + if (IS_ENABLED(CONFIG_DEBUG_FS)) + hp_wmi_debugfs_init(dev, info, pevents, icount, pcount, is_new); + + if (!count) + return 0; /* No connected sensors; debugfs only. */ + + has_events = find_event_attributes(state, pevents, pcount); + + /* Survive failure to install WMI event handler. */ + if (has_events && !add_event_handler(state)) + has_events = false; + + err = make_chip_info(state, has_events); + if (err) + return err; + + hwdev = devm_hwmon_device_register_with_info(dev, "hp_wmi_sensors", + state, &hp_wmi_chip_info, + NULL); + return PTR_ERR_OR_ZERO(hwdev); +} + +static int hp_wmi_sensors_probe(struct wmi_device *wdev, const void *context) +{ + struct device *dev = &wdev->dev; + struct hp_wmi_sensors *state; + + state = devm_kzalloc(dev, sizeof(*state), GFP_KERNEL); + if (!state) + return -ENOMEM; + + state->wdev = wdev; + + mutex_init(&state->lock); + + dev_set_drvdata(dev, state); + + return hp_wmi_sensors_init(state); +} + +static const struct wmi_device_id hp_wmi_sensors_id_table[] = { + { HP_WMI_NUMERIC_SENSOR_GUID, NULL }, + {}, +}; + +static struct wmi_driver hp_wmi_sensors_driver = { + .driver = { .name = "hp-wmi-sensors" }, + .id_table = hp_wmi_sensors_id_table, + .probe = hp_wmi_sensors_probe, +}; +module_wmi_driver(hp_wmi_sensors_driver); + +MODULE_AUTHOR("James Seo "); +MODULE_DESCRIPTION("HP WMI Sensors driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/hwmon/hwmon.c b/drivers/hwmon/hwmon.c index 573b83b6c08cc41cc4f78f91698013a850a3f572..c7dd3f5b2bd5499cc6bb4b0b896d477631533403 100644 --- a/drivers/hwmon/hwmon.c +++ b/drivers/hwmon/hwmon.c @@ -456,6 +456,7 @@ static const char * const hwmon_chip_attrs[] = { [hwmon_chip_in_samples] = "in_samples", [hwmon_chip_power_samples] = "power_samples", [hwmon_chip_temp_samples] = "temp_samples", + [hwmon_chip_beep_enable] = "beep_enable", }; static const char * const hwmon_temp_attr_templates[] = { @@ -486,6 +487,7 @@ static const char * const hwmon_temp_attr_templates[] = { [hwmon_temp_reset_history] = "temp%d_reset_history", [hwmon_temp_rated_min] = "temp%d_rated_min", [hwmon_temp_rated_max] = "temp%d_rated_max", + [hwmon_temp_beep] = "temp%d_beep", }; static const char * const hwmon_in_attr_templates[] = { @@ -507,6 +509,7 @@ static const char * const hwmon_in_attr_templates[] = { [hwmon_in_crit_alarm] = "in%d_crit_alarm", [hwmon_in_rated_min] = "in%d_rated_min", [hwmon_in_rated_max] = "in%d_rated_max", + [hwmon_in_beep] = "in%d_beep", }; static const char * const hwmon_curr_attr_templates[] = { @@ -528,6 +531,7 @@ static const char * const hwmon_curr_attr_templates[] = { [hwmon_curr_crit_alarm] = "curr%d_crit_alarm", [hwmon_curr_rated_min] = "curr%d_rated_min", [hwmon_curr_rated_max] = "curr%d_rated_max", + [hwmon_curr_beep] = "curr%d_beep", }; static const char * const hwmon_power_attr_templates[] = { @@ -597,6 +601,7 @@ static const char * const hwmon_fan_attr_templates[] = { [hwmon_fan_min_alarm] = "fan%d_min_alarm", [hwmon_fan_max_alarm] = "fan%d_max_alarm", [hwmon_fan_fault] = "fan%d_fault", + [hwmon_fan_beep] = "fan%d_beep", }; static const char * const hwmon_pwm_attr_templates[] = { @@ -1029,7 +1034,7 @@ EXPORT_SYMBOL_GPL(devm_hwmon_device_register_with_groups); * @name: hwmon name attribute * @drvdata: driver data to attach to created device * @chip: pointer to hwmon chip information - * @groups: pointer to list of driver specific attribute groups + * @extra_groups: pointer to list of driver specific attribute groups * * Returns the pointer to the new device. The new device is automatically * unregistered with the parent device. @@ -1038,7 +1043,7 @@ struct device * devm_hwmon_device_register_with_info(struct device *dev, const char *name, void *drvdata, const struct hwmon_chip_info *chip, - const struct attribute_group **groups) + const struct attribute_group **extra_groups) { struct device **ptr, *hwdev; @@ -1050,7 +1055,7 @@ devm_hwmon_device_register_with_info(struct device *dev, const char *name, return ERR_PTR(-ENOMEM); hwdev = hwmon_device_register_with_info(dev, name, drvdata, chip, - groups); + extra_groups); if (IS_ERR(hwdev)) goto error; diff --git a/drivers/hwmon/ina209.c b/drivers/hwmon/ina209.c index 9b58655d2de4a9c7ead354770a6f201c194a9fb2..c558143e5285da77f85834e7a654f90b15270fb9 100644 --- a/drivers/hwmon/ina209.c +++ b/drivers/hwmon/ina209.c @@ -594,7 +594,7 @@ static struct i2c_driver ina209_driver = { .name = "ina209", .of_match_table = of_match_ptr(ina209_of_match), }, - .probe_new = ina209_probe, + .probe = ina209_probe, .remove = ina209_remove, .id_table = ina209_id, }; diff --git a/drivers/hwmon/ina238.c b/drivers/hwmon/ina238.c index 8af07bc0c50e0c5396cabfc515a01632677c16ca..f519c22d3907cdf0df95d0b3c2925191bc3dea29 100644 --- a/drivers/hwmon/ina238.c +++ b/drivers/hwmon/ina238.c @@ -633,7 +633,7 @@ static struct i2c_driver ina238_driver = { .name = "ina238", .of_match_table = of_match_ptr(ina238_of_match), }, - .probe_new = ina238_probe, + .probe = ina238_probe, .id_table = ina238_id, }; diff --git a/drivers/hwmon/ina2xx.c b/drivers/hwmon/ina2xx.c index fd50d9785ccbbecc1f9179a245565da77a5324e6..cfd7efef5cdf4376547827c813836345786c1730 100644 --- a/drivers/hwmon/ina2xx.c +++ b/drivers/hwmon/ina2xx.c @@ -721,7 +721,7 @@ static struct i2c_driver ina2xx_driver = { .name = "ina2xx", .of_match_table = of_match_ptr(ina2xx_of_match), }, - .probe_new = ina2xx_probe, + .probe = ina2xx_probe, .id_table = ina2xx_id, }; diff --git a/drivers/hwmon/ina3221.c b/drivers/hwmon/ina3221.c index 2735e3782ffb4291a2badbb5c351ecf2740fa7d9..5ab944056ec08c033a7f9e86326c24da38356930 100644 --- a/drivers/hwmon/ina3221.c +++ b/drivers/hwmon/ina3221.c @@ -1010,7 +1010,7 @@ static const struct i2c_device_id ina3221_ids[] = { MODULE_DEVICE_TABLE(i2c, ina3221_ids); static struct i2c_driver ina3221_i2c_driver = { - .probe_new = ina3221_probe, + .probe = ina3221_probe, .remove = ina3221_remove, .driver = { .name = INA3221_DRIVER_NAME, diff --git a/drivers/hwmon/intel-m10-bmc-hwmon.c b/drivers/hwmon/intel-m10-bmc-hwmon.c index 6512f4bec79aad848e5193599858b0f15d9c24e2..6500ca548f9c73f1b2c9ebdce6ae59a82e63c55a 100644 --- a/drivers/hwmon/intel-m10-bmc-hwmon.c +++ b/drivers/hwmon/intel-m10-bmc-hwmon.c @@ -794,3 +794,4 @@ MODULE_DEVICE_TABLE(platform, intel_m10bmc_hwmon_ids); MODULE_AUTHOR("Intel Corporation"); MODULE_DESCRIPTION("Intel MAX 10 BMC hardware monitor"); MODULE_LICENSE("GPL"); +MODULE_IMPORT_NS(INTEL_M10_BMC_CORE); diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c index eb38f54ebeb6167bf0f7fa1d34b228ba18371134..5deff5e5f6932846819ebd4e95567e1846df5604 100644 --- a/drivers/hwmon/it87.c +++ b/drivers/hwmon/it87.c @@ -317,31 +317,37 @@ struct it87_devices { * chips to avoid the problem. */ #define FEAT_CONF_NOEXIT BIT(19) /* Chip should not exit conf mode */ +#define FEAT_FOUR_FANS BIT(20) /* Supports four fans */ +#define FEAT_FOUR_PWM BIT(21) /* Supports four fan controls */ +#define FEAT_FOUR_TEMP BIT(22) +#define FEAT_FANCTL_ONOFF BIT(23) /* chip has FAN_CTL ON/OFF */ static const struct it87_devices it87_devices[] = { [it87] = { .name = "it87", .model = "IT87F", - .features = FEAT_OLD_AUTOPWM, /* may need to overwrite */ + .features = FEAT_OLD_AUTOPWM | FEAT_FANCTL_ONOFF, + /* may need to overwrite */ }, [it8712] = { .name = "it8712", .model = "IT8712F", - .features = FEAT_OLD_AUTOPWM | FEAT_VID, - /* may need to overwrite */ + .features = FEAT_OLD_AUTOPWM | FEAT_VID | FEAT_FANCTL_ONOFF, + /* may need to overwrite */ }, [it8716] = { .name = "it8716", .model = "IT8716F", .features = FEAT_16BIT_FANS | FEAT_TEMP_OFFSET | FEAT_VID - | FEAT_FAN16_CONFIG | FEAT_FIVE_FANS | FEAT_PWM_FREQ2, + | FEAT_FAN16_CONFIG | FEAT_FIVE_FANS | FEAT_PWM_FREQ2 + | FEAT_FANCTL_ONOFF, }, [it8718] = { .name = "it8718", .model = "IT8718F", .features = FEAT_16BIT_FANS | FEAT_TEMP_OFFSET | FEAT_VID | FEAT_TEMP_OLD_PECI | FEAT_FAN16_CONFIG | FEAT_FIVE_FANS - | FEAT_PWM_FREQ2, + | FEAT_PWM_FREQ2 | FEAT_FANCTL_ONOFF, .old_peci_mask = 0x4, }, [it8720] = { @@ -349,7 +355,7 @@ static const struct it87_devices it87_devices[] = { .model = "IT8720F", .features = FEAT_16BIT_FANS | FEAT_TEMP_OFFSET | FEAT_VID | FEAT_TEMP_OLD_PECI | FEAT_FAN16_CONFIG | FEAT_FIVE_FANS - | FEAT_PWM_FREQ2, + | FEAT_PWM_FREQ2 | FEAT_FANCTL_ONOFF, .old_peci_mask = 0x4, }, [it8721] = { @@ -358,7 +364,7 @@ static const struct it87_devices it87_devices[] = { .features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS | FEAT_TEMP_OFFSET | FEAT_TEMP_OLD_PECI | FEAT_TEMP_PECI | FEAT_FAN16_CONFIG | FEAT_FIVE_FANS | FEAT_IN7_INTERNAL - | FEAT_PWM_FREQ2, + | FEAT_PWM_FREQ2 | FEAT_FANCTL_ONOFF, .peci_mask = 0x05, .old_peci_mask = 0x02, /* Actually reports PCH */ }, @@ -367,7 +373,8 @@ static const struct it87_devices it87_devices[] = { .model = "IT8728F", .features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS | FEAT_TEMP_OFFSET | FEAT_TEMP_PECI | FEAT_FIVE_FANS - | FEAT_IN7_INTERNAL | FEAT_PWM_FREQ2, + | FEAT_IN7_INTERNAL | FEAT_PWM_FREQ2 + | FEAT_FANCTL_ONOFF, .peci_mask = 0x07, }, [it8732] = { @@ -375,7 +382,8 @@ static const struct it87_devices it87_devices[] = { .model = "IT8732F", .features = FEAT_NEWER_AUTOPWM | FEAT_16BIT_FANS | FEAT_TEMP_OFFSET | FEAT_TEMP_OLD_PECI | FEAT_TEMP_PECI - | FEAT_10_9MV_ADC | FEAT_IN7_INTERNAL, + | FEAT_10_9MV_ADC | FEAT_IN7_INTERNAL | FEAT_FOUR_FANS + | FEAT_FOUR_PWM | FEAT_FANCTL_ONOFF, .peci_mask = 0x07, .old_peci_mask = 0x02, /* Actually reports PCH */ }, @@ -384,7 +392,7 @@ static const struct it87_devices it87_devices[] = { .model = "IT8771E", .features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS | FEAT_TEMP_OFFSET | FEAT_TEMP_PECI | FEAT_IN7_INTERNAL - | FEAT_PWM_FREQ2, + | FEAT_PWM_FREQ2 | FEAT_FANCTL_ONOFF, /* PECI: guesswork */ /* 12mV ADC (OHM) */ /* 16 bit fans (OHM) */ @@ -396,7 +404,7 @@ static const struct it87_devices it87_devices[] = { .model = "IT8772E", .features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS | FEAT_TEMP_OFFSET | FEAT_TEMP_PECI | FEAT_IN7_INTERNAL - | FEAT_PWM_FREQ2, + | FEAT_PWM_FREQ2 | FEAT_FANCTL_ONOFF, /* PECI (coreboot) */ /* 12mV ADC (HWSensors4, OHM) */ /* 16 bit fans (HWSensors4, OHM) */ @@ -407,21 +415,24 @@ static const struct it87_devices it87_devices[] = { .name = "it8781", .model = "IT8781F", .features = FEAT_16BIT_FANS | FEAT_TEMP_OFFSET - | FEAT_TEMP_OLD_PECI | FEAT_FAN16_CONFIG | FEAT_PWM_FREQ2, + | FEAT_TEMP_OLD_PECI | FEAT_FAN16_CONFIG | FEAT_PWM_FREQ2 + | FEAT_FANCTL_ONOFF, .old_peci_mask = 0x4, }, [it8782] = { .name = "it8782", .model = "IT8782F", .features = FEAT_16BIT_FANS | FEAT_TEMP_OFFSET - | FEAT_TEMP_OLD_PECI | FEAT_FAN16_CONFIG | FEAT_PWM_FREQ2, + | FEAT_TEMP_OLD_PECI | FEAT_FAN16_CONFIG | FEAT_PWM_FREQ2 + | FEAT_FANCTL_ONOFF, .old_peci_mask = 0x4, }, [it8783] = { .name = "it8783", .model = "IT8783E/F", .features = FEAT_16BIT_FANS | FEAT_TEMP_OFFSET - | FEAT_TEMP_OLD_PECI | FEAT_FAN16_CONFIG | FEAT_PWM_FREQ2, + | FEAT_TEMP_OLD_PECI | FEAT_FAN16_CONFIG | FEAT_PWM_FREQ2 + | FEAT_FANCTL_ONOFF, .old_peci_mask = 0x4, }, [it8786] = { @@ -429,7 +440,7 @@ static const struct it87_devices it87_devices[] = { .model = "IT8786E", .features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS | FEAT_TEMP_OFFSET | FEAT_TEMP_PECI | FEAT_IN7_INTERNAL - | FEAT_PWM_FREQ2, + | FEAT_PWM_FREQ2 | FEAT_FANCTL_ONOFF, .peci_mask = 0x07, }, [it8790] = { @@ -437,7 +448,7 @@ static const struct it87_devices it87_devices[] = { .model = "IT8790E", .features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS | FEAT_TEMP_OFFSET | FEAT_TEMP_PECI | FEAT_IN7_INTERNAL - | FEAT_PWM_FREQ2 | FEAT_CONF_NOEXIT, + | FEAT_PWM_FREQ2 | FEAT_FANCTL_ONOFF | FEAT_CONF_NOEXIT, .peci_mask = 0x07, }, [it8792] = { @@ -445,7 +456,8 @@ static const struct it87_devices it87_devices[] = { .model = "IT8792E/IT8795E", .features = FEAT_NEWER_AUTOPWM | FEAT_16BIT_FANS | FEAT_TEMP_OFFSET | FEAT_TEMP_OLD_PECI | FEAT_TEMP_PECI - | FEAT_10_9MV_ADC | FEAT_IN7_INTERNAL | FEAT_CONF_NOEXIT, + | FEAT_10_9MV_ADC | FEAT_IN7_INTERNAL | FEAT_FANCTL_ONOFF + | FEAT_CONF_NOEXIT, .peci_mask = 0x07, .old_peci_mask = 0x02, /* Actually reports PCH */ }, @@ -463,7 +475,7 @@ static const struct it87_devices it87_devices[] = { .features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS | FEAT_TEMP_OFFSET | FEAT_TEMP_PECI | FEAT_SIX_FANS | FEAT_IN7_INTERNAL | FEAT_SIX_PWM | FEAT_PWM_FREQ2 - | FEAT_SIX_TEMP | FEAT_VIN3_5V, + | FEAT_SIX_TEMP | FEAT_VIN3_5V | FEAT_FANCTL_ONOFF, .peci_mask = 0x07, }, [it8622] = { @@ -472,7 +484,7 @@ static const struct it87_devices it87_devices[] = { .features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS | FEAT_TEMP_OFFSET | FEAT_TEMP_PECI | FEAT_FIVE_FANS | FEAT_FIVE_PWM | FEAT_IN7_INTERNAL | FEAT_PWM_FREQ2 - | FEAT_AVCC3 | FEAT_VIN3_5V, + | FEAT_AVCC3 | FEAT_VIN3_5V | FEAT_FOUR_TEMP, .peci_mask = 0x07, .smbus_bitmap = BIT(1) | BIT(2), }, @@ -482,7 +494,7 @@ static const struct it87_devices it87_devices[] = { .features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS | FEAT_TEMP_OFFSET | FEAT_TEMP_PECI | FEAT_SIX_FANS | FEAT_IN7_INTERNAL | FEAT_SIX_PWM | FEAT_PWM_FREQ2 - | FEAT_SIX_TEMP | FEAT_VIN3_5V, + | FEAT_SIX_TEMP | FEAT_VIN3_5V | FEAT_FANCTL_ONOFF, .peci_mask = 0x07, }, [it87952] = { @@ -490,7 +502,8 @@ static const struct it87_devices it87_devices[] = { .model = "IT87952E", .features = FEAT_NEWER_AUTOPWM | FEAT_16BIT_FANS | FEAT_TEMP_OFFSET | FEAT_TEMP_OLD_PECI | FEAT_TEMP_PECI - | FEAT_10_9MV_ADC | FEAT_IN7_INTERNAL | FEAT_CONF_NOEXIT, + | FEAT_10_9MV_ADC | FEAT_IN7_INTERNAL | FEAT_FANCTL_ONOFF + | FEAT_CONF_NOEXIT, .peci_mask = 0x07, .old_peci_mask = 0x02, /* Actually reports PCH */ }, @@ -508,21 +521,29 @@ static const struct it87_devices it87_devices[] = { (((data)->features & FEAT_TEMP_OLD_PECI) && \ ((data)->old_peci_mask & BIT(nr))) #define has_fan16_config(data) ((data)->features & FEAT_FAN16_CONFIG) +#define has_four_fans(data) ((data)->features & (FEAT_FOUR_FANS | \ + FEAT_FIVE_FANS | \ + FEAT_SIX_FANS)) #define has_five_fans(data) ((data)->features & (FEAT_FIVE_FANS | \ FEAT_SIX_FANS)) +#define has_six_fans(data) ((data)->features & FEAT_SIX_FANS) #define has_vid(data) ((data)->features & FEAT_VID) #define has_in7_internal(data) ((data)->features & FEAT_IN7_INTERNAL) -#define has_six_fans(data) ((data)->features & FEAT_SIX_FANS) #define has_avcc3(data) ((data)->features & FEAT_AVCC3) -#define has_five_pwm(data) ((data)->features & (FEAT_FIVE_PWM \ - | FEAT_SIX_PWM)) +#define has_four_pwm(data) ((data)->features & (FEAT_FOUR_PWM | \ + FEAT_FIVE_PWM | \ + FEAT_SIX_PWM)) +#define has_five_pwm(data) ((data)->features & (FEAT_FIVE_PWM | \ + FEAT_SIX_PWM)) #define has_six_pwm(data) ((data)->features & FEAT_SIX_PWM) #define has_pwm_freq2(data) ((data)->features & FEAT_PWM_FREQ2) +#define has_four_temp(data) ((data)->features & FEAT_FOUR_TEMP) #define has_six_temp(data) ((data)->features & FEAT_SIX_TEMP) #define has_vin3_5v(data) ((data)->features & FEAT_VIN3_5V) #define has_conf_noexit(data) ((data)->features & FEAT_CONF_NOEXIT) #define has_scaling(data) ((data)->features & (FEAT_12MV_ADC | \ FEAT_10_9MV_ADC)) +#define has_fanctl_onoff(data) ((data)->features & FEAT_FANCTL_ONOFF) struct it87_sio_data { int sioaddr; @@ -1229,11 +1250,12 @@ static SENSOR_DEVICE_ATTR(temp3_type, S_IRUGO | S_IWUSR, show_temp_type, static int pwm_mode(const struct it87_data *data, int nr) { - if (data->type != it8603 && nr < 3 && !(data->fan_main_ctrl & BIT(nr))) - return 0; /* Full speed */ + if (has_fanctl_onoff(data) && nr < 3 && + !(data->fan_main_ctrl & BIT(nr))) + return 0; /* Full speed */ if (data->pwm_ctrl[nr] & 0x80) - return 2; /* Automatic mode */ - if ((data->type == it8603 || nr >= 3) && + return 2; /* Automatic mode */ + if ((!has_fanctl_onoff(data) || nr >= 3) && data->pwm_duty[nr] == pwm_to_reg(data, 0xff)) return 0; /* Full speed */ @@ -1470,7 +1492,7 @@ static ssize_t set_pwm_enable(struct device *dev, struct device_attribute *attr, return err; if (val == 0) { - if (nr < 3 && data->type != it8603) { + if (nr < 3 && has_fanctl_onoff(data)) { int tmp; /* make sure the fan is on when in on/off mode */ tmp = it87_read_value(data, IT87_REG_FAN_CTL); @@ -1510,7 +1532,7 @@ static ssize_t set_pwm_enable(struct device *dev, struct device_attribute *attr, data->pwm_ctrl[nr] = ctrl; it87_write_value(data, IT87_REG_PWM[nr], ctrl); - if (data->type != it8603 && nr < 3) { + if (has_fanctl_onoff(data) && nr < 3) { /* set SmartGuardian mode */ data->fan_main_ctrl |= BIT(nr); it87_write_value(data, IT87_REG_FAN_MAIN_CTRL, @@ -2730,8 +2752,10 @@ static int __init it87_find(int sioaddr, unsigned short *address, else sio_data->skip_in |= BIT(9); - if (!has_five_pwm(config)) + if (!has_four_pwm(config)) sio_data->skip_pwm |= BIT(3) | BIT(4) | BIT(5); + else if (!has_five_pwm(config)) + sio_data->skip_pwm |= BIT(4) | BIT(5); else if (!has_six_pwm(config)) sio_data->skip_pwm |= BIT(5); @@ -2922,6 +2946,34 @@ static int __init it87_find(int sioaddr, unsigned short *address, if (!(reg & BIT(0))) sio_data->skip_in |= BIT(9); + sio_data->beep_pin = superio_inb(sioaddr, + IT87_SIO_BEEP_PIN_REG) & 0x3f; + } else if (sio_data->type == it8732) { + int reg; + + superio_select(sioaddr, GPIO); + + /* Check for pwm2, fan2 */ + reg = superio_inb(sioaddr, IT87_SIO_GPIO5_REG); + if (reg & BIT(1)) + sio_data->skip_pwm |= BIT(1); + if (reg & BIT(2)) + sio_data->skip_fan |= BIT(1); + + /* Check for pwm3, fan3, fan4 */ + reg = superio_inb(sioaddr, IT87_SIO_GPIO3_REG); + if (reg & BIT(6)) + sio_data->skip_pwm |= BIT(2); + if (reg & BIT(7)) + sio_data->skip_fan |= BIT(2); + if (reg & BIT(5)) + sio_data->skip_fan |= BIT(3); + + /* Check if AVCC is on VIN3 */ + reg = superio_inb(sioaddr, IT87_SIO_PINX2_REG); + if (reg & BIT(0)) + sio_data->internal |= BIT(0); + sio_data->beep_pin = superio_inb(sioaddr, IT87_SIO_BEEP_PIN_REG) & 0x3f; } else { @@ -3169,16 +3221,14 @@ static void it87_init_device(struct platform_device *pdev) it87_check_tachometers_16bit_mode(pdev); /* Check for additional fans */ - if (has_five_fans(data)) { - tmp = it87_read_value(data, IT87_REG_FAN_16BIT); - - if (tmp & BIT(4)) - data->has_fan |= BIT(3); /* fan4 enabled */ - if (tmp & BIT(5)) - data->has_fan |= BIT(4); /* fan5 enabled */ - if (has_six_fans(data) && (tmp & BIT(2))) - data->has_fan |= BIT(5); /* fan6 enabled */ - } + tmp = it87_read_value(data, IT87_REG_FAN_16BIT); + + if (has_four_fans(data) && (tmp & BIT(4))) + data->has_fan |= BIT(3); /* fan4 enabled */ + if (has_five_fans(data) && (tmp & BIT(5))) + data->has_fan |= BIT(4); /* fan5 enabled */ + if (has_six_fans(data) && (tmp & BIT(2))) + data->has_fan |= BIT(5); /* fan6 enabled */ /* Fan input pins may be used for alternative functions */ data->has_fan &= ~sio_data->skip_fan; @@ -3356,7 +3406,9 @@ static int it87_probe(struct platform_device *pdev) data->need_in7_reroute = sio_data->need_in7_reroute; data->has_in = 0x3ff & ~sio_data->skip_in; - if (has_six_temp(data)) { + if (has_four_temp(data)) { + data->has_temp |= BIT(3); + } else if (has_six_temp(data)) { u8 reg = it87_read_value(data, IT87_REG_TEMP456_ENABLE); /* Check for additional temperature sensors */ diff --git a/drivers/hwmon/jc42.c b/drivers/hwmon/jc42.c index 4c60dc520b12186b852ec81f4059d68b938c8ad7..f958e830b23cfabc23fb415370fbfefdb25da07d 100644 --- a/drivers/hwmon/jc42.c +++ b/drivers/hwmon/jc42.c @@ -629,7 +629,7 @@ static struct i2c_driver jc42_driver = { .pm = JC42_DEV_PM_OPS, .of_match_table = of_match_ptr(jc42_of_ids), }, - .probe_new = jc42_probe, + .probe = jc42_probe, .remove = jc42_remove, .id_table = jc42_id, .detect = jc42_detect, diff --git a/drivers/hwmon/lineage-pem.c b/drivers/hwmon/lineage-pem.c index ef5a49cd91498aa49e84bd19821cdf803808b99f..df69c380cde7ed06eb6e6d469313536799ef4422 100644 --- a/drivers/hwmon/lineage-pem.c +++ b/drivers/hwmon/lineage-pem.c @@ -511,7 +511,7 @@ static struct i2c_driver pem_driver = { .driver = { .name = "lineage_pem", }, - .probe_new = pem_probe, + .probe = pem_probe, .id_table = pem_id, }; diff --git a/drivers/hwmon/lm63.c b/drivers/hwmon/lm63.c index 9ab2cab4c7106d00d7e329d30bd10d9c5693bb1f..6972454eb4e00b53910b826bc9b9c2d87de1ccf1 100644 --- a/drivers/hwmon/lm63.c +++ b/drivers/hwmon/lm63.c @@ -1164,7 +1164,7 @@ static struct i2c_driver lm63_driver = { .name = "lm63", .of_match_table = of_match_ptr(lm63_of_match), }, - .probe_new = lm63_probe, + .probe = lm63_probe, .id_table = lm63_id, .detect = lm63_detect, .address_list = normal_i2c, diff --git a/drivers/hwmon/lm73.c b/drivers/hwmon/lm73.c index b6433ae2d75c3b92dc995af27916da7358dce578..637d35c5ae23a1eda93cc2efa1d3e11985b5ce6e 100644 --- a/drivers/hwmon/lm73.c +++ b/drivers/hwmon/lm73.c @@ -277,7 +277,7 @@ static struct i2c_driver lm73_driver = { .name = "lm73", .of_match_table = lm73_of_match, }, - .probe_new = lm73_probe, + .probe = lm73_probe, .id_table = lm73_ids, .detect = lm73_detect, .address_list = normal_i2c, diff --git a/drivers/hwmon/lm75.c b/drivers/hwmon/lm75.c index dbb99ea4a0eccf8b9ee31bbfdfc91a59cd7a9ea9..72e634d1b857bb27368e2512382dd0480a1657e8 100644 --- a/drivers/hwmon/lm75.c +++ b/drivers/hwmon/lm75.c @@ -548,7 +548,7 @@ static const struct regmap_config lm75_regmap_config = { .writeable_reg = lm75_is_writeable_reg, .volatile_reg = lm75_is_volatile_reg, .val_format_endian = REGMAP_ENDIAN_BIG, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, .use_single_read = true, .use_single_write = true, }; @@ -945,7 +945,7 @@ static struct i2c_driver lm75_driver = { .of_match_table = of_match_ptr(lm75_of_match), .pm = LM75_DEV_PM_OPS, }, - .probe_new = lm75_probe, + .probe = lm75_probe, .id_table = lm75_ids, .detect = lm75_detect, .address_list = normal_i2c, diff --git a/drivers/hwmon/lm77.c b/drivers/hwmon/lm77.c index 645cb2191abe433ee25b6f302e766cfc70bfb929..8b986251917841448e0bfe2e931507be5ad627b3 100644 --- a/drivers/hwmon/lm77.c +++ b/drivers/hwmon/lm77.c @@ -348,7 +348,7 @@ static struct i2c_driver lm77_driver = { .driver = { .name = "lm77", }, - .probe_new = lm77_probe, + .probe = lm77_probe, .id_table = lm77_id, .detect = lm77_detect, .address_list = normal_i2c, diff --git a/drivers/hwmon/lm78.c b/drivers/hwmon/lm78.c index 694e171cab7f02700d8b741b247e4ec1681ebafc..b739c354311b001f52197a3df8098e6f24f706d7 100644 --- a/drivers/hwmon/lm78.c +++ b/drivers/hwmon/lm78.c @@ -662,7 +662,7 @@ static struct i2c_driver lm78_driver = { .driver = { .name = "lm78", }, - .probe_new = lm78_i2c_probe, + .probe = lm78_i2c_probe, .id_table = lm78_i2c_id, .detect = lm78_i2c_detect, .address_list = normal_i2c, diff --git a/drivers/hwmon/lm80.c b/drivers/hwmon/lm80.c index 35db0b97f9128b174ec9ef7c7866fe445e893774..63c7831bd3e11b4789e9a8b8d802671e9a313e51 100644 --- a/drivers/hwmon/lm80.c +++ b/drivers/hwmon/lm80.c @@ -633,7 +633,7 @@ static struct i2c_driver lm80_driver = { .driver = { .name = "lm80", }, - .probe_new = lm80_probe, + .probe = lm80_probe, .id_table = lm80_id, .detect = lm80_detect, .address_list = normal_i2c, diff --git a/drivers/hwmon/lm83.c b/drivers/hwmon/lm83.c index bcaf31ec176e9c4bbc2e29a07b9e9bd3216d15f7..5befedca6abb4fd76c4e56c831d564f7aea023f8 100644 --- a/drivers/hwmon/lm83.c +++ b/drivers/hwmon/lm83.c @@ -454,7 +454,7 @@ static struct i2c_driver lm83_driver = { .driver = { .name = "lm83", }, - .probe_new = lm83_probe, + .probe = lm83_probe, .id_table = lm83_id, .detect = lm83_detect, .address_list = normal_i2c, diff --git a/drivers/hwmon/lm85.c b/drivers/hwmon/lm85.c index 8d33c24847553459ccd6e20c6b8bd5c37cfbbb92..8540178f5b74112772982b66828b6873cc6b2b73 100644 --- a/drivers/hwmon/lm85.c +++ b/drivers/hwmon/lm85.c @@ -1698,7 +1698,7 @@ static struct i2c_driver lm85_driver = { .name = "lm85", .of_match_table = of_match_ptr(lm85_of_match), }, - .probe_new = lm85_probe, + .probe = lm85_probe, .id_table = lm85_id, .detect = lm85_detect, .address_list = normal_i2c, diff --git a/drivers/hwmon/lm87.c b/drivers/hwmon/lm87.c index 818fb619524572ba4f167b312401123f115eb1c7..2195a735d28e0ef68d4c65941dc0655cf5410afb 100644 --- a/drivers/hwmon/lm87.c +++ b/drivers/hwmon/lm87.c @@ -994,7 +994,7 @@ static struct i2c_driver lm87_driver = { .name = "lm87", .of_match_table = lm87_of_match, }, - .probe_new = lm87_probe, + .probe = lm87_probe, .id_table = lm87_id, .detect = lm87_detect, .address_list = normal_i2c, diff --git a/drivers/hwmon/lm90.c b/drivers/hwmon/lm90.c index 6498d5acf70555cc49f96591f837708fe2d88d8d..90101c236f356579daa1c255f7430c8b57d977fc 100644 --- a/drivers/hwmon/lm90.c +++ b/drivers/hwmon/lm90.c @@ -2972,7 +2972,7 @@ static struct i2c_driver lm90_driver = { .of_match_table = of_match_ptr(lm90_of_match), .pm = pm_sleep_ptr(&lm90_pm_ops), }, - .probe_new = lm90_probe, + .probe = lm90_probe, .alert = lm90_alert, .id_table = lm90_id, .detect = lm90_detect, diff --git a/drivers/hwmon/lm92.c b/drivers/hwmon/lm92.c index 2ff3044a677d896acc7b3b0c17994562f5d14cb1..46579a3e1715c94d6ecfedbdacf8532822ae5f09 100644 --- a/drivers/hwmon/lm92.c +++ b/drivers/hwmon/lm92.c @@ -330,7 +330,7 @@ static struct i2c_driver lm92_driver = { .driver = { .name = "lm92", }, - .probe_new = lm92_probe, + .probe = lm92_probe, .id_table = lm92_id, .detect = lm92_detect, .address_list = normal_i2c, diff --git a/drivers/hwmon/lm93.c b/drivers/hwmon/lm93.c index 4cf50d5f4f5949e90145f7818ef6cf8caac34550..75bca805720e7158713d1acfb8cf6d7f0a16e77a 100644 --- a/drivers/hwmon/lm93.c +++ b/drivers/hwmon/lm93.c @@ -2635,7 +2635,7 @@ static struct i2c_driver lm93_driver = { .driver = { .name = "lm93", }, - .probe_new = lm93_probe, + .probe = lm93_probe, .id_table = lm93_id, .detect = lm93_detect, .address_list = normal_i2c, diff --git a/drivers/hwmon/lm95234.c b/drivers/hwmon/lm95234.c index b4a9d0c223c4a1a1d119935ed76bb5e1489e37ad..67b9d7636ee4276617de38c978b91ba3a6abca9a 100644 --- a/drivers/hwmon/lm95234.c +++ b/drivers/hwmon/lm95234.c @@ -720,7 +720,7 @@ static struct i2c_driver lm95234_driver = { .driver = { .name = DRVNAME, }, - .probe_new = lm95234_probe, + .probe = lm95234_probe, .id_table = lm95234_id, .detect = lm95234_detect, .address_list = normal_i2c, diff --git a/drivers/hwmon/lm95241.c b/drivers/hwmon/lm95241.c index 647a90570bc6dff34881964c2963c6c0a211aaea..475551f5024b4710619b455501d0719a8c129931 100644 --- a/drivers/hwmon/lm95241.c +++ b/drivers/hwmon/lm95241.c @@ -468,7 +468,7 @@ static struct i2c_driver lm95241_driver = { .driver = { .name = DEVNAME, }, - .probe_new = lm95241_probe, + .probe = lm95241_probe, .id_table = lm95241_id, .detect = lm95241_detect, .address_list = normal_i2c, diff --git a/drivers/hwmon/lm95245.c b/drivers/hwmon/lm95245.c index 4236d1e0544d7f2432fae2b268d2bd6a3f5ae5b2..17ff54bd40151b0aee8c40846b1e0560c3ce1621 100644 --- a/drivers/hwmon/lm95245.c +++ b/drivers/hwmon/lm95245.c @@ -518,7 +518,7 @@ static const struct regmap_config lm95245_regmap_config = { .val_bits = 8, .writeable_reg = lm95245_is_writeable_reg, .volatile_reg = lm95245_is_volatile_reg, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, .use_single_read = true, .use_single_write = true, }; @@ -597,7 +597,7 @@ static struct i2c_driver lm95245_driver = { .name = "lm95245", .of_match_table = of_match_ptr(lm95245_of_match), }, - .probe_new = lm95245_probe, + .probe = lm95245_probe, .id_table = lm95245_id, .detect = lm95245_detect, .address_list = normal_i2c, diff --git a/drivers/hwmon/ltc2945.c b/drivers/hwmon/ltc2945.c index 3494f7261ebf5ed93c3ee492b9aa564b82867d72..45b87a863cae45222523f0569585cf3617518c70 100644 --- a/drivers/hwmon/ltc2945.c +++ b/drivers/hwmon/ltc2945.c @@ -519,7 +519,7 @@ static struct i2c_driver ltc2945_driver = { .name = "ltc2945", .of_match_table = of_match_ptr(ltc2945_of_match), }, - .probe_new = ltc2945_probe, + .probe = ltc2945_probe, .id_table = ltc2945_id, }; diff --git a/drivers/hwmon/ltc2947-i2c.c b/drivers/hwmon/ltc2947-i2c.c index 96852bc8a96415cbde2d07615e27c62092acd56e..33f574bf2ce76ac8347f3cdf01554d5b2e3b162a 100644 --- a/drivers/hwmon/ltc2947-i2c.c +++ b/drivers/hwmon/ltc2947-i2c.c @@ -38,7 +38,7 @@ static struct i2c_driver ltc2947_driver = { .of_match_table = ltc2947_of_match, .pm = pm_sleep_ptr(<c2947_pm_ops), }, - .probe_new = ltc2947_probe, + .probe = ltc2947_probe, .id_table = ltc2947_id, }; module_i2c_driver(ltc2947_driver); diff --git a/drivers/hwmon/ltc2990.c b/drivers/hwmon/ltc2990.c index 689f788b856338d14677b62c12d09496e1d21ba9..1ad362c0fd2ccc9512e918d6322019330aebc5ad 100644 --- a/drivers/hwmon/ltc2990.c +++ b/drivers/hwmon/ltc2990.c @@ -268,7 +268,7 @@ static struct i2c_driver ltc2990_i2c_driver = { .driver = { .name = "ltc2990", }, - .probe_new = ltc2990_i2c_probe, + .probe = ltc2990_i2c_probe, .id_table = ltc2990_i2c_id, }; diff --git a/drivers/hwmon/ltc2992.c b/drivers/hwmon/ltc2992.c index 429a7f5837f0910448f461335e6a6ebb47969dd8..589bcd07ce7f718d98baa5ca2b960396969b9c37 100644 --- a/drivers/hwmon/ltc2992.c +++ b/drivers/hwmon/ltc2992.c @@ -928,7 +928,7 @@ static struct i2c_driver ltc2992_i2c_driver = { .name = "ltc2992", .of_match_table = ltc2992_of_match, }, - .probe_new = ltc2992_i2c_probe, + .probe = ltc2992_i2c_probe, .id_table = ltc2992_i2c_id, }; diff --git a/drivers/hwmon/ltc4151.c b/drivers/hwmon/ltc4151.c index e3ac004c1ed12a10e5d822fefb344dba4a5447d2..f42ac3c9475ea1275718fe9ba2db1302e2182416 100644 --- a/drivers/hwmon/ltc4151.c +++ b/drivers/hwmon/ltc4151.c @@ -205,7 +205,7 @@ static struct i2c_driver ltc4151_driver = { .name = "ltc4151", .of_match_table = of_match_ptr(ltc4151_match), }, - .probe_new = ltc4151_probe, + .probe = ltc4151_probe, .id_table = ltc4151_id, }; diff --git a/drivers/hwmon/ltc4215.c b/drivers/hwmon/ltc4215.c index fa43d26ddd4fd17b1fb3b5341a9f326929bd4dd9..66fd28f713ab19b9c9885c3aaba279a098aedddd 100644 --- a/drivers/hwmon/ltc4215.c +++ b/drivers/hwmon/ltc4215.c @@ -255,7 +255,7 @@ static struct i2c_driver ltc4215_driver = { .driver = { .name = "ltc4215", }, - .probe_new = ltc4215_probe, + .probe = ltc4215_probe, .id_table = ltc4215_id, }; diff --git a/drivers/hwmon/ltc4222.c b/drivers/hwmon/ltc4222.c index d2027ca5c925499329a4b5a45e10077692b70e30..9098ef521739e00a6ffe5781ad07df81edbf3899 100644 --- a/drivers/hwmon/ltc4222.c +++ b/drivers/hwmon/ltc4222.c @@ -210,7 +210,7 @@ static struct i2c_driver ltc4222_driver = { .driver = { .name = "ltc4222", }, - .probe_new = ltc4222_probe, + .probe = ltc4222_probe, .id_table = ltc4222_id, }; diff --git a/drivers/hwmon/ltc4245.c b/drivers/hwmon/ltc4245.c index fb9bc8dbe99bc2821392a759db58fa7488e75f4b..b90184a3e0ec3bfbd31827582a65610c0d51f85b 100644 --- a/drivers/hwmon/ltc4245.c +++ b/drivers/hwmon/ltc4245.c @@ -479,7 +479,7 @@ static struct i2c_driver ltc4245_driver = { .driver = { .name = "ltc4245", }, - .probe_new = ltc4245_probe, + .probe = ltc4245_probe, .id_table = ltc4245_id, }; diff --git a/drivers/hwmon/ltc4260.c b/drivers/hwmon/ltc4260.c index 75e89cec381ea6f3bb652b70b5b1f7dfdd4d7793..52f7a809b27b01d74197bf3323b83796cc9db88f 100644 --- a/drivers/hwmon/ltc4260.c +++ b/drivers/hwmon/ltc4260.c @@ -173,7 +173,7 @@ static struct i2c_driver ltc4260_driver = { .driver = { .name = "ltc4260", }, - .probe_new = ltc4260_probe, + .probe = ltc4260_probe, .id_table = ltc4260_id, }; diff --git a/drivers/hwmon/ltc4261.c b/drivers/hwmon/ltc4261.c index b91cc4fe84e538850921690f4a7bffd1afe07d5c..509e68176c7af8b9db99886616bdf6987124221e 100644 --- a/drivers/hwmon/ltc4261.c +++ b/drivers/hwmon/ltc4261.c @@ -233,7 +233,7 @@ static struct i2c_driver ltc4261_driver = { .driver = { .name = "ltc4261", }, - .probe_new = ltc4261_probe, + .probe = ltc4261_probe, .id_table = ltc4261_id, }; diff --git a/drivers/hwmon/max1111.c b/drivers/hwmon/max1111.c index 4c5487aeb3cfca487c0518554e4e61bc7a16e753..5cc08c720b52f744687b521dd1dd9f2d289517d3 100644 --- a/drivers/hwmon/max1111.c +++ b/drivers/hwmon/max1111.c @@ -80,6 +80,7 @@ static int max1111_read(struct device *dev, int channel) #ifdef CONFIG_SHARPSL_PM static struct max1111_data *the_max1111; +int max1111_read_channel(int channel); int max1111_read_channel(int channel) { if (!the_max1111 || !the_max1111->spi) diff --git a/drivers/hwmon/max127.c b/drivers/hwmon/max127.c index 49de1d2be2949c3c81e16b47ec1a270e39f423ed..ee5ead06d612df21bcfab212fa5d5d5ecfc7fa42 100644 --- a/drivers/hwmon/max127.c +++ b/drivers/hwmon/max127.c @@ -339,7 +339,7 @@ static struct i2c_driver max127_driver = { .driver = { .name = "max127", }, - .probe_new = max127_probe, + .probe = max127_probe, .id_table = max127_id, }; diff --git a/drivers/hwmon/max16065.c b/drivers/hwmon/max16065.c index daa5d8af1e69d81965da1b436ebace34287cbb99..aa38c45adc09e22122634697aab58506f29b00ae 100644 --- a/drivers/hwmon/max16065.c +++ b/drivers/hwmon/max16065.c @@ -600,7 +600,7 @@ static struct i2c_driver max16065_driver = { .driver = { .name = "max16065", }, - .probe_new = max16065_probe, + .probe = max16065_probe, .id_table = max16065_id, }; diff --git a/drivers/hwmon/max1619.c b/drivers/hwmon/max1619.c index 445c77197f69f12097c521e14396a6a6bc1e8ecb..500dc926a7a7f5cac7c2b516a9759205bf877f90 100644 --- a/drivers/hwmon/max1619.c +++ b/drivers/hwmon/max1619.c @@ -305,7 +305,7 @@ static struct i2c_driver max1619_driver = { .name = "max1619", .of_match_table = of_match_ptr(max1619_of_match), }, - .probe_new = max1619_probe, + .probe = max1619_probe, .id_table = max1619_id, .detect = max1619_detect, .address_list = normal_i2c, diff --git a/drivers/hwmon/max1668.c b/drivers/hwmon/max1668.c index 9f748973d6a371d62aa15ead2b38e4afc911b36e..c4a02edefbee7a43947085107c140a599f336f06 100644 --- a/drivers/hwmon/max1668.c +++ b/drivers/hwmon/max1668.c @@ -435,7 +435,7 @@ static struct i2c_driver max1668_driver = { .driver = { .name = "max1668", }, - .probe_new = max1668_probe, + .probe = max1668_probe, .id_table = max1668_id, .detect = max1668_detect, .address_list = max1668_addr_list, diff --git a/drivers/hwmon/max31730.c b/drivers/hwmon/max31730.c index 924333d89ce4da7ec7c1858ac479c03c25cb1327..b1300ca9db1f746dfff416670c80e2e74f84a23d 100644 --- a/drivers/hwmon/max31730.c +++ b/drivers/hwmon/max31730.c @@ -427,7 +427,7 @@ static struct i2c_driver max31730_driver = { .of_match_table = of_match_ptr(max31730_of_match), .pm = pm_sleep_ptr(&max31730_pm_ops), }, - .probe_new = max31730_probe, + .probe = max31730_probe, .id_table = max31730_ids, .detect = max31730_detect, .address_list = normal_i2c, diff --git a/drivers/hwmon/max31760.c b/drivers/hwmon/max31760.c index 4489110f109c52d9d686468bb916d367f48db69d..79945eb466ae43e5925ae25322f1338c0cda6549 100644 --- a/drivers/hwmon/max31760.c +++ b/drivers/hwmon/max31760.c @@ -584,7 +584,7 @@ static struct i2c_driver max31760_driver = { .of_match_table = max31760_of_match, .pm = pm_ptr(&max31760_pm_ops) }, - .probe_new = max31760_probe, + .probe = max31760_probe, .id_table = max31760_id }; module_i2c_driver(max31760_driver); diff --git a/drivers/hwmon/max31790.c b/drivers/hwmon/max31790.c index 6caba6e8ee8f33ab25fdcd12b374520de4284099..0cd44c1e998a2e093da4e706063f0c113dde213e 100644 --- a/drivers/hwmon/max31790.c +++ b/drivers/hwmon/max31790.c @@ -544,7 +544,7 @@ MODULE_DEVICE_TABLE(i2c, max31790_id); static struct i2c_driver max31790_driver = { .class = I2C_CLASS_HWMON, - .probe_new = max31790_probe, + .probe = max31790_probe, .driver = { .name = "max31790", }, diff --git a/drivers/hwmon/max31827.c b/drivers/hwmon/max31827.c new file mode 100644 index 0000000000000000000000000000000000000000..602f4e4f81ff926a9b3bf6f86739a5261f378db3 --- /dev/null +++ b/drivers/hwmon/max31827.c @@ -0,0 +1,466 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * max31827.c - Support for Maxim Low-Power Switch + * + * Copyright (c) 2023 Daniel Matyas + */ + +#include +#include +#include +#include +#include +#include +#include + +#define MAX31827_T_REG 0x0 +#define MAX31827_CONFIGURATION_REG 0x2 +#define MAX31827_TH_REG 0x4 +#define MAX31827_TL_REG 0x6 +#define MAX31827_TH_HYST_REG 0x8 +#define MAX31827_TL_HYST_REG 0xA + +#define MAX31827_CONFIGURATION_1SHOT_MASK BIT(0) +#define MAX31827_CONFIGURATION_CNV_RATE_MASK GENMASK(3, 1) +#define MAX31827_CONFIGURATION_U_TEMP_STAT_MASK BIT(14) +#define MAX31827_CONFIGURATION_O_TEMP_STAT_MASK BIT(15) + +#define MAX31827_12_BIT_CNV_TIME 141 + +#define MAX31827_CNV_1_DIV_64_HZ 0x1 +#define MAX31827_CNV_1_DIV_32_HZ 0x2 +#define MAX31827_CNV_1_DIV_16_HZ 0x3 +#define MAX31827_CNV_1_DIV_4_HZ 0x4 +#define MAX31827_CNV_1_HZ 0x5 +#define MAX31827_CNV_4_HZ 0x6 +#define MAX31827_CNV_8_HZ 0x7 + +#define MAX31827_16_BIT_TO_M_DGR(x) (sign_extend32(x, 15) * 1000 / 16) +#define MAX31827_M_DGR_TO_16_BIT(x) (((x) << 4) / 1000) +#define MAX31827_DEVICE_ENABLE(x) ((x) ? 0xA : 0x0) + +struct max31827_state { + /* + * Prevent simultaneous access to the i2c client. + */ + struct mutex lock; + struct regmap *regmap; + bool enable; +}; + +static const struct regmap_config max31827_regmap = { + .reg_bits = 8, + .val_bits = 16, + .max_register = 0xA, +}; + +static int write_alarm_val(struct max31827_state *st, unsigned int reg, + long val) +{ + unsigned int cfg; + unsigned int tmp; + int ret; + + val = MAX31827_M_DGR_TO_16_BIT(val); + + /* + * Before the Temperature Threshold Alarm and Alarm Hysteresis Threshold + * register values are changed over I2C, the part must be in shutdown + * mode. + * + * Mutex is used to ensure, that some other process doesn't change the + * configuration register. + */ + mutex_lock(&st->lock); + + if (!st->enable) { + ret = regmap_write(st->regmap, reg, val); + goto unlock; + } + + ret = regmap_read(st->regmap, MAX31827_CONFIGURATION_REG, &cfg); + if (ret) + goto unlock; + + tmp = cfg & ~(MAX31827_CONFIGURATION_1SHOT_MASK | + MAX31827_CONFIGURATION_CNV_RATE_MASK); + ret = regmap_write(st->regmap, MAX31827_CONFIGURATION_REG, tmp); + if (ret) + goto unlock; + + ret = regmap_write(st->regmap, reg, val); + if (ret) + goto unlock; + + ret = regmap_write(st->regmap, MAX31827_CONFIGURATION_REG, cfg); + +unlock: + mutex_unlock(&st->lock); + return ret; +} + +static umode_t max31827_is_visible(const void *state, + enum hwmon_sensor_types type, u32 attr, + int channel) +{ + if (type == hwmon_temp) { + switch (attr) { + case hwmon_temp_enable: + case hwmon_temp_max: + case hwmon_temp_min: + case hwmon_temp_max_hyst: + case hwmon_temp_min_hyst: + return 0644; + case hwmon_temp_input: + case hwmon_temp_min_alarm: + case hwmon_temp_max_alarm: + return 0444; + default: + return 0; + } + } else if (type == hwmon_chip) { + if (attr == hwmon_chip_update_interval) + return 0644; + } + + return 0; +} + +static int max31827_read(struct device *dev, enum hwmon_sensor_types type, + u32 attr, int channel, long *val) +{ + struct max31827_state *st = dev_get_drvdata(dev); + unsigned int uval; + int ret = 0; + + switch (type) { + case hwmon_temp: + switch (attr) { + case hwmon_temp_enable: + ret = regmap_read(st->regmap, + MAX31827_CONFIGURATION_REG, &uval); + if (ret) + break; + + uval = FIELD_GET(MAX31827_CONFIGURATION_1SHOT_MASK | + MAX31827_CONFIGURATION_CNV_RATE_MASK, + uval); + *val = !!uval; + + break; + case hwmon_temp_input: + mutex_lock(&st->lock); + + if (!st->enable) { + /* + * This operation requires mutex protection, + * because the chip configuration should not + * be changed during the conversion process. + */ + + ret = regmap_update_bits(st->regmap, + MAX31827_CONFIGURATION_REG, + MAX31827_CONFIGURATION_1SHOT_MASK, + 1); + if (ret) { + mutex_unlock(&st->lock); + return ret; + } + + msleep(MAX31827_12_BIT_CNV_TIME); + } + ret = regmap_read(st->regmap, MAX31827_T_REG, &uval); + + mutex_unlock(&st->lock); + + if (ret) + break; + + *val = MAX31827_16_BIT_TO_M_DGR(uval); + + break; + case hwmon_temp_max: + ret = regmap_read(st->regmap, MAX31827_TH_REG, &uval); + if (ret) + break; + + *val = MAX31827_16_BIT_TO_M_DGR(uval); + break; + case hwmon_temp_max_hyst: + ret = regmap_read(st->regmap, MAX31827_TH_HYST_REG, + &uval); + if (ret) + break; + + *val = MAX31827_16_BIT_TO_M_DGR(uval); + break; + case hwmon_temp_max_alarm: + ret = regmap_read(st->regmap, + MAX31827_CONFIGURATION_REG, &uval); + if (ret) + break; + + *val = FIELD_GET(MAX31827_CONFIGURATION_O_TEMP_STAT_MASK, + uval); + break; + case hwmon_temp_min: + ret = regmap_read(st->regmap, MAX31827_TL_REG, &uval); + if (ret) + break; + + *val = MAX31827_16_BIT_TO_M_DGR(uval); + break; + case hwmon_temp_min_hyst: + ret = regmap_read(st->regmap, MAX31827_TL_HYST_REG, + &uval); + if (ret) + break; + + *val = MAX31827_16_BIT_TO_M_DGR(uval); + break; + case hwmon_temp_min_alarm: + ret = regmap_read(st->regmap, + MAX31827_CONFIGURATION_REG, &uval); + if (ret) + break; + + *val = FIELD_GET(MAX31827_CONFIGURATION_U_TEMP_STAT_MASK, + uval); + break; + default: + ret = -EOPNOTSUPP; + break; + } + + break; + + case hwmon_chip: + if (attr == hwmon_chip_update_interval) { + ret = regmap_read(st->regmap, + MAX31827_CONFIGURATION_REG, &uval); + if (ret) + break; + + uval = FIELD_GET(MAX31827_CONFIGURATION_CNV_RATE_MASK, + uval); + switch (uval) { + case MAX31827_CNV_1_DIV_64_HZ: + *val = 64000; + break; + case MAX31827_CNV_1_DIV_32_HZ: + *val = 32000; + break; + case MAX31827_CNV_1_DIV_16_HZ: + *val = 16000; + break; + case MAX31827_CNV_1_DIV_4_HZ: + *val = 4000; + break; + case MAX31827_CNV_1_HZ: + *val = 1000; + break; + case MAX31827_CNV_4_HZ: + *val = 250; + break; + case MAX31827_CNV_8_HZ: + *val = 125; + break; + default: + *val = 0; + break; + } + } + break; + + default: + ret = -EOPNOTSUPP; + break; + } + + return ret; +} + +static int max31827_write(struct device *dev, enum hwmon_sensor_types type, + u32 attr, int channel, long val) +{ + struct max31827_state *st = dev_get_drvdata(dev); + int ret; + + switch (type) { + case hwmon_temp: + switch (attr) { + case hwmon_temp_enable: + if (val >> 1) + return -EINVAL; + + mutex_lock(&st->lock); + /** + * The chip should not be enabled while a conversion is + * performed. Neither should the chip be enabled when + * the alarm values are changed. + */ + + st->enable = val; + + ret = regmap_update_bits(st->regmap, + MAX31827_CONFIGURATION_REG, + MAX31827_CONFIGURATION_1SHOT_MASK | + MAX31827_CONFIGURATION_CNV_RATE_MASK, + MAX31827_DEVICE_ENABLE(val)); + + mutex_unlock(&st->lock); + + return ret; + + case hwmon_temp_max: + return write_alarm_val(st, MAX31827_TH_REG, val); + + case hwmon_temp_max_hyst: + return write_alarm_val(st, MAX31827_TH_HYST_REG, val); + + case hwmon_temp_min: + return write_alarm_val(st, MAX31827_TL_REG, val); + + case hwmon_temp_min_hyst: + return write_alarm_val(st, MAX31827_TL_HYST_REG, val); + + default: + return -EOPNOTSUPP; + } + + case hwmon_chip: + if (attr == hwmon_chip_update_interval) { + if (!st->enable) + return -EINVAL; + + switch (val) { + case 125: + val = MAX31827_CNV_8_HZ; + break; + case 250: + val = MAX31827_CNV_4_HZ; + break; + case 1000: + val = MAX31827_CNV_1_HZ; + break; + case 4000: + val = MAX31827_CNV_1_DIV_4_HZ; + break; + case 16000: + val = MAX31827_CNV_1_DIV_16_HZ; + break; + case 32000: + val = MAX31827_CNV_1_DIV_32_HZ; + break; + case 64000: + val = MAX31827_CNV_1_DIV_64_HZ; + break; + default: + return -EINVAL; + } + + val = FIELD_PREP(MAX31827_CONFIGURATION_CNV_RATE_MASK, + val); + + return regmap_update_bits(st->regmap, + MAX31827_CONFIGURATION_REG, + MAX31827_CONFIGURATION_CNV_RATE_MASK, + val); + } + break; + + default: + return -EOPNOTSUPP; + } + + return -EOPNOTSUPP; +} + +static int max31827_init_client(struct max31827_state *st) +{ + st->enable = true; + + return regmap_update_bits(st->regmap, MAX31827_CONFIGURATION_REG, + MAX31827_CONFIGURATION_1SHOT_MASK | + MAX31827_CONFIGURATION_CNV_RATE_MASK, + MAX31827_DEVICE_ENABLE(1)); +} + +static const struct hwmon_channel_info *max31827_info[] = { + HWMON_CHANNEL_INFO(temp, HWMON_T_ENABLE | HWMON_T_INPUT | HWMON_T_MIN | + HWMON_T_MIN_HYST | HWMON_T_MIN_ALARM | + HWMON_T_MAX | HWMON_T_MAX_HYST | + HWMON_T_MAX_ALARM), + HWMON_CHANNEL_INFO(chip, HWMON_C_UPDATE_INTERVAL), + NULL, +}; + +static const struct hwmon_ops max31827_hwmon_ops = { + .is_visible = max31827_is_visible, + .read = max31827_read, + .write = max31827_write, +}; + +static const struct hwmon_chip_info max31827_chip_info = { + .ops = &max31827_hwmon_ops, + .info = max31827_info, +}; + +static int max31827_probe(struct i2c_client *client) +{ + struct device *dev = &client->dev; + struct device *hwmon_dev; + struct max31827_state *st; + int err; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WORD_DATA)) + return -EOPNOTSUPP; + + st = devm_kzalloc(dev, sizeof(*st), GFP_KERNEL); + if (!st) + return -ENOMEM; + + mutex_init(&st->lock); + + st->regmap = devm_regmap_init_i2c(client, &max31827_regmap); + if (IS_ERR(st->regmap)) + return dev_err_probe(dev, PTR_ERR(st->regmap), + "Failed to allocate regmap.\n"); + + err = max31827_init_client(st); + if (err) + return err; + + hwmon_dev = devm_hwmon_device_register_with_info(dev, client->name, st, + &max31827_chip_info, + NULL); + + return PTR_ERR_OR_ZERO(hwmon_dev); +} + +static const struct i2c_device_id max31827_i2c_ids[] = { + { "max31827", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, max31827_i2c_ids); + +static const struct of_device_id max31827_of_match[] = { + { .compatible = "adi,max31827" }, + { } +}; +MODULE_DEVICE_TABLE(of, max31827_of_match); + +static struct i2c_driver max31827_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "max31827", + .of_match_table = max31827_of_match, + }, + .probe = max31827_probe, + .id_table = max31827_i2c_ids, +}; +module_i2c_driver(max31827_driver); + +MODULE_AUTHOR("Daniel Matyas "); +MODULE_DESCRIPTION("Maxim MAX31827 low-power temperature switch driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/hwmon/max6620.c b/drivers/hwmon/max6620.c index 0f277d945ea20d452196119b43c185984e91a748..5d12fb9c97862256a129ef9f8358474893b2330b 100644 --- a/drivers/hwmon/max6620.c +++ b/drivers/hwmon/max6620.c @@ -503,7 +503,7 @@ static struct i2c_driver max6620_driver = { .driver = { .name = "max6620", }, - .probe_new = max6620_probe, + .probe = max6620_probe, .id_table = max6620_id, }; diff --git a/drivers/hwmon/max6621.c b/drivers/hwmon/max6621.c index 0656eb1e7959b5c8cb9c729607bc4ada21c12e77..7f709fd1af8958ebbda6f7f7a69e9f63f6b40f99 100644 --- a/drivers/hwmon/max6621.c +++ b/drivers/hwmon/max6621.c @@ -554,7 +554,7 @@ static struct i2c_driver max6621_driver = { .name = MAX6621_DRV_NAME, .of_match_table = of_match_ptr(max6621_of_match), }, - .probe_new = max6621_probe, + .probe = max6621_probe, .id_table = max6621_id, }; diff --git a/drivers/hwmon/max6639.c b/drivers/hwmon/max6639.c index 9b895402c80d386523d4a71d18df79a0ce2d8b24..caf527154fca856eee57c1eaad794e56ec5b8407 100644 --- a/drivers/hwmon/max6639.c +++ b/drivers/hwmon/max6639.c @@ -624,7 +624,7 @@ static struct i2c_driver max6639_driver = { .name = "max6639", .pm = pm_sleep_ptr(&max6639_pm_ops), }, - .probe_new = max6639_probe, + .probe = max6639_probe, .id_table = max6639_id, .detect = max6639_detect, .address_list = normal_i2c, diff --git a/drivers/hwmon/max6642.c b/drivers/hwmon/max6642.c index 47ea34ff78f3d1a5a677595e702158dfd585b8cc..8b2e4d6101a20a1bb1618bbf8c6cc69b7591e5c5 100644 --- a/drivers/hwmon/max6642.c +++ b/drivers/hwmon/max6642.c @@ -301,7 +301,7 @@ static struct i2c_driver max6642_driver = { .driver = { .name = "max6642", }, - .probe_new = max6642_probe, + .probe = max6642_probe, .id_table = max6642_id, .detect = max6642_detect, .address_list = normal_i2c, diff --git a/drivers/hwmon/max6650.c b/drivers/hwmon/max6650.c index 19e2c762ed2d6110137ef5c195b5f4cac71da47c..cc8428a3045d88dd577e448441a41a0693ad3265 100644 --- a/drivers/hwmon/max6650.c +++ b/drivers/hwmon/max6650.c @@ -819,7 +819,7 @@ static struct i2c_driver max6650_driver = { .name = "max6650", .of_match_table = of_match_ptr(max6650_dt_match), }, - .probe_new = max6650_probe, + .probe = max6650_probe, .id_table = max6650_id, }; diff --git a/drivers/hwmon/max6697.c b/drivers/hwmon/max6697.c index 2895cea5419349b0fd010e4a9c6045cc2a4c0a79..3a67778f111cdc5d4c4661c41f412af9b0875b0a 100644 --- a/drivers/hwmon/max6697.c +++ b/drivers/hwmon/max6697.c @@ -786,7 +786,7 @@ static struct i2c_driver max6697_driver = { .name = "max6697", .of_match_table = of_match_ptr(max6697_of_match), }, - .probe_new = max6697_probe, + .probe = max6697_probe, .id_table = max6697_id, }; diff --git a/drivers/hwmon/mc34vr500.c b/drivers/hwmon/mc34vr500.c index 6a7a950a9332907342cfddf966c97adddfc5dff9..0c8fd3fce83ef0822d7952797b97fddb17cc9365 100644 --- a/drivers/hwmon/mc34vr500.c +++ b/drivers/hwmon/mc34vr500.c @@ -251,7 +251,7 @@ static struct i2c_driver mc34vr500_driver = { .name = "mc34vr500", .of_match_table = of_match_ptr(mc34vr500_of_match), }, - .probe_new = mc34vr500_probe, + .probe = mc34vr500_probe, .id_table = mc34vr500_id, }; diff --git a/drivers/hwmon/mcp3021.c b/drivers/hwmon/mcp3021.c index a5f7a294f33d0953f2cd7fb7ffdb4a7118569cc0..127e15ff3e76430c8e13f471239f169a85a967de 100644 --- a/drivers/hwmon/mcp3021.c +++ b/drivers/hwmon/mcp3021.c @@ -198,7 +198,7 @@ static struct i2c_driver mcp3021_driver = { .name = "mcp3021", .of_match_table = of_match_ptr(of_mcp3021_match), }, - .probe_new = mcp3021_probe, + .probe = mcp3021_probe, .id_table = mcp3021_id, }; diff --git a/drivers/hwmon/nct6683.c b/drivers/hwmon/nct6683.c index a872f783e9cc374ee9f40631260eef452ba5c3c9..f673f7d0794123d3193eb7f0cad42c1090ba52d4 100644 --- a/drivers/hwmon/nct6683.c +++ b/drivers/hwmon/nct6683.c @@ -173,6 +173,7 @@ superio_exit(int ioreg) #define NCT6683_CUSTOMER_ID_INTEL 0x805 #define NCT6683_CUSTOMER_ID_MITAC 0xa0e #define NCT6683_CUSTOMER_ID_MSI 0x201 +#define NCT6683_CUSTOMER_ID_MSI2 0x200 #define NCT6683_CUSTOMER_ID_ASROCK 0xe2c #define NCT6683_CUSTOMER_ID_ASROCK2 0xe1b @@ -1220,6 +1221,8 @@ static int nct6683_probe(struct platform_device *pdev) break; case NCT6683_CUSTOMER_ID_MSI: break; + case NCT6683_CUSTOMER_ID_MSI2: + break; case NCT6683_CUSTOMER_ID_ASROCK: break; case NCT6683_CUSTOMER_ID_ASROCK2: diff --git a/drivers/hwmon/nct6775-core.c b/drivers/hwmon/nct6775-core.c index c54233f0369b2487376d13a76b453f191dc5c0f4..236dc97f4d2292beb8bfc7cd688b9846bf74aa40 100644 --- a/drivers/hwmon/nct6775-core.c +++ b/drivers/hwmon/nct6775-core.c @@ -33,6 +33,7 @@ * (0xd451) * nct6798d 14 7 7 2+6 0xd428 0xc1 0x5ca3 * (0xd429) + * nct6799d 14 7 7 2+6 0xd802 0xc1 0x5ca3 * * #temp lists the number of monitored temperature sources (first value) plus * the number of directly connectable temperature sensors (second value). @@ -73,6 +74,7 @@ static const char * const nct6775_device_names[] = { "nct6796", "nct6797", "nct6798", + "nct6799", }; /* Common and NCT6775 specific data */ @@ -381,7 +383,7 @@ static const u16 NCT6779_REG_TEMP_OVER[ARRAY_SIZE(NCT6779_REG_TEMP)] = { 0x39, 0x155 }; static const u16 NCT6779_REG_TEMP_OFFSET[] = { - 0x454, 0x455, 0x456, 0x44a, 0x44b, 0x44c }; + 0x454, 0x455, 0x456, 0x44a, 0x44b, 0x44c, 0x44d, 0x449 }; static const char *const nct6779_temp_label[] = { "", @@ -654,6 +656,44 @@ static const char *const nct6798_temp_label[] = { #define NCT6798_TEMP_MASK 0xbfff0ffe #define NCT6798_VIRT_TEMP_MASK 0x80000c00 +static const char *const nct6799_temp_label[] = { + "", + "SYSTIN", + "CPUTIN", + "AUXTIN0", + "AUXTIN1", + "AUXTIN2", + "AUXTIN3", + "AUXTIN4", + "SMBUSMASTER 0", + "SMBUSMASTER 1", + "Virtual_TEMP", + "Virtual_TEMP", + "", + "AUXTIN5", + "", + "", + "PECI Agent 0", + "PECI Agent 1", + "PCH_CHIP_CPU_MAX_TEMP", + "PCH_CHIP_TEMP", + "PCH_CPU_TEMP", + "PCH_MCH_TEMP", + "Agent0 Dimm0", + "Agent0 Dimm1", + "Agent1 Dimm0", + "Agent1 Dimm1", + "BYTE_TEMP0", + "BYTE_TEMP1", + "PECI Agent 0 Calibration", /* undocumented */ + "PECI Agent 1 Calibration", /* undocumented */ + "", + "Virtual_TEMP" +}; + +#define NCT6799_TEMP_MASK 0xbfff2ffe +#define NCT6799_VIRT_TEMP_MASK 0x80000c00 + /* NCT6102D/NCT6106D specific data */ #define NCT6106_REG_VBAT 0x318 @@ -1109,6 +1149,7 @@ bool nct6775_reg_is_word_sized(struct nct6775_data *data, u16 reg) case nct6796: case nct6797: case nct6798: + case nct6799: return reg == 0x150 || reg == 0x153 || reg == 0x155 || (reg & 0xfff0) == 0x4c0 || reg == 0x402 || @@ -1462,6 +1503,7 @@ static int nct6775_update_pwm_limits(struct device *dev) case nct6796: case nct6797: case nct6798: + case nct6799: err = nct6775_read_value(data, data->REG_CRITICAL_PWM_ENABLE[i], ®); if (err) return err; @@ -3109,6 +3151,7 @@ store_auto_pwm(struct device *dev, struct device_attribute *attr, case nct6796: case nct6797: case nct6798: + case nct6799: err = nct6775_write_value(data, data->REG_CRITICAL_PWM[nr], val); if (err) break; @@ -3807,10 +3850,12 @@ int nct6775_probe(struct device *dev, struct nct6775_data *data, case nct6796: case nct6797: case nct6798: + case nct6799: data->in_num = 15; data->pwm_num = (data->kind == nct6796 || data->kind == nct6797 || - data->kind == nct6798) ? 7 : 6; + data->kind == nct6798 || + data->kind == nct6799) ? 7 : 6; data->auto_pwm_num = 4; data->has_fan_div = false; data->temp_fixed_num = 6; @@ -3859,6 +3904,11 @@ int nct6775_probe(struct device *dev, struct nct6775_data *data, data->temp_mask = NCT6798_TEMP_MASK; data->virt_temp_mask = NCT6798_VIRT_TEMP_MASK; break; + case nct6799: + data->temp_label = nct6799_temp_label; + data->temp_mask = NCT6799_TEMP_MASK; + data->virt_temp_mask = NCT6799_VIRT_TEMP_MASK; + break; } data->REG_CONFIG = NCT6775_REG_CONFIG; @@ -3918,6 +3968,7 @@ int nct6775_probe(struct device *dev, struct nct6775_data *data, case nct6796: case nct6797: case nct6798: + case nct6799: data->REG_TSI_TEMP = NCT6796_REG_TSI_TEMP; num_reg_tsi_temp = ARRAY_SIZE(NCT6796_REG_TSI_TEMP); break; diff --git a/drivers/hwmon/nct6775-i2c.c b/drivers/hwmon/nct6775-i2c.c index e1bcd11461913134d1a2b500142075c390ad5dcc..87a4fc78c5711f2539ac7ed8ddf3f81c43ca85f1 100644 --- a/drivers/hwmon/nct6775-i2c.c +++ b/drivers/hwmon/nct6775-i2c.c @@ -87,6 +87,7 @@ static const struct of_device_id __maybe_unused nct6775_i2c_of_match[] = { { .compatible = "nuvoton,nct6796", .data = (void *)nct6796, }, { .compatible = "nuvoton,nct6797", .data = (void *)nct6797, }, { .compatible = "nuvoton,nct6798", .data = (void *)nct6798, }, + { .compatible = "nuvoton,nct6799", .data = (void *)nct6799, }, { }, }; MODULE_DEVICE_TABLE(of, nct6775_i2c_of_match); @@ -104,6 +105,7 @@ static const struct i2c_device_id nct6775_i2c_id[] = { { "nct6796", nct6796 }, { "nct6797", nct6797 }, { "nct6798", nct6798 }, + { "nct6799", nct6799 }, { } }; MODULE_DEVICE_TABLE(i2c, nct6775_i2c_id); @@ -183,7 +185,7 @@ static struct i2c_driver nct6775_i2c_driver = { .name = "nct6775-i2c", .of_match_table = of_match_ptr(nct6775_i2c_of_match), }, - .probe_new = nct6775_i2c_probe, + .probe = nct6775_i2c_probe, .id_table = nct6775_i2c_id, }; diff --git a/drivers/hwmon/nct6775-platform.c b/drivers/hwmon/nct6775-platform.c index 5782acfb4ee1beec0e847ec7a1d8111e64bbeb28..ada867d6b98acd4092e59bbe916218fa68d88805 100644 --- a/drivers/hwmon/nct6775-platform.c +++ b/drivers/hwmon/nct6775-platform.c @@ -35,6 +35,7 @@ static const char * const nct6775_sio_names[] __initconst = { "NCT6796D", "NCT6797D", "NCT6798D", + "NCT6799D", }; static unsigned short force_id; @@ -85,6 +86,7 @@ MODULE_PARM_DESC(fan_debounce, "Enable debouncing for fan RPM signal"); #define SIO_NCT6796_ID 0xd420 #define SIO_NCT6797_ID 0xd450 #define SIO_NCT6798_ID 0xd428 +#define SIO_NCT6799_ID 0xd800 #define SIO_ID_MASK 0xFFF8 /* @@ -418,7 +420,7 @@ static int nct6775_resume(struct device *dev) if (data->kind == nct6791 || data->kind == nct6792 || data->kind == nct6793 || data->kind == nct6795 || data->kind == nct6796 || data->kind == nct6797 || - data->kind == nct6798) + data->kind == nct6798 || data->kind == nct6799) nct6791_enable_io_mapping(sio_data); sio_data->sio_exit(sio_data); @@ -565,7 +567,7 @@ nct6775_check_fan_inputs(struct nct6775_data *data, struct nct6775_sio_data *sio } else { /* * NCT6779D, NCT6791D, NCT6792D, NCT6793D, NCT6795D, NCT6796D, - * NCT6797D, NCT6798D + * NCT6797D, NCT6798D, NCT6799D */ int cr1a = sio_data->sio_inb(sio_data, 0x1a); int cr1b = sio_data->sio_inb(sio_data, 0x1b); @@ -575,12 +577,17 @@ nct6775_check_fan_inputs(struct nct6775_data *data, struct nct6775_sio_data *sio int cr2b = sio_data->sio_inb(sio_data, 0x2b); int cr2d = sio_data->sio_inb(sio_data, 0x2d); int cr2f = sio_data->sio_inb(sio_data, 0x2f); + bool vsb_ctl_en = cr2f & BIT(0); bool dsw_en = cr2f & BIT(3); bool ddr4_en = cr2f & BIT(4); + bool as_seq1_en = cr2f & BIT(7); int cre0; + int cre6; int creb; int cred; + cre6 = sio_data->sio_inb(sio_data, 0xe0); + sio_data->sio_select(sio_data, NCT6775_LD_12); cre0 = sio_data->sio_inb(sio_data, 0xe0); creb = sio_data->sio_inb(sio_data, 0xeb); @@ -683,6 +690,29 @@ nct6775_check_fan_inputs(struct nct6775_data *data, struct nct6775_sio_data *sio pwm7pin = !(cr1d & (BIT(2) | BIT(3))); pwm7pin |= cr2d & BIT(7); pwm7pin |= creb & BIT(2); + break; + case nct6799: + fan4pin = cr1c & BIT(6); + fan5pin = cr1c & BIT(7); + + fan6pin = !(cr1b & BIT(0)) && (cre0 & BIT(3)); + fan6pin |= cre6 & BIT(5); + fan6pin |= creb & BIT(5); + fan6pin |= !as_seq1_en && (cr2a & BIT(4)); + + fan7pin = cr1b & BIT(5); + fan7pin |= !vsb_ctl_en && !(cr2b & BIT(2)); + fan7pin |= creb & BIT(3); + + pwm6pin = !(cr1b & BIT(0)) && (cre0 & BIT(4)); + pwm6pin |= !as_seq1_en && !(cred & BIT(2)) && (cr2a & BIT(3)); + pwm6pin |= (creb & BIT(4)) && !(cr2a & BIT(0)); + pwm6pin |= cre6 & BIT(3); + + pwm7pin = !vsb_ctl_en && !(cr1d & (BIT(2) | BIT(3))); + pwm7pin |= creb & BIT(2); + pwm7pin |= cr2d & BIT(7); + break; default: /* NCT6779D */ break; @@ -838,6 +868,7 @@ static int nct6775_platform_probe_init(struct nct6775_data *data) case nct6796: case nct6797: case nct6798: + case nct6799: break; } @@ -876,6 +907,7 @@ static int nct6775_platform_probe_init(struct nct6775_data *data) case nct6796: case nct6797: case nct6798: + case nct6799: tmp |= 0x7e; break; } @@ -1005,6 +1037,9 @@ static int __init nct6775_find(int sioaddr, struct nct6775_sio_data *sio_data) case SIO_NCT6798_ID: sio_data->kind = nct6798; break; + case SIO_NCT6799_ID: + sio_data->kind = nct6799; + break; default: if (val != 0xffff) pr_debug("unsupported chip ID: 0x%04x\n", val); @@ -1033,7 +1068,7 @@ static int __init nct6775_find(int sioaddr, struct nct6775_sio_data *sio_data) if (sio_data->kind == nct6791 || sio_data->kind == nct6792 || sio_data->kind == nct6793 || sio_data->kind == nct6795 || sio_data->kind == nct6796 || sio_data->kind == nct6797 || - sio_data->kind == nct6798) + sio_data->kind == nct6798 || sio_data->kind == nct6799) nct6791_enable_io_mapping(sio_data); sio_data->sio_exit(sio_data); diff --git a/drivers/hwmon/nct6775.h b/drivers/hwmon/nct6775.h index be41848c3cd29fd8c207ee4703c3e4acb70e0ec8..44f79c5726a9c1ec72a8cb54e780c48344fe0166 100644 --- a/drivers/hwmon/nct6775.h +++ b/drivers/hwmon/nct6775.h @@ -5,7 +5,7 @@ #include enum kinds { nct6106, nct6116, nct6775, nct6776, nct6779, nct6791, nct6792, - nct6793, nct6795, nct6796, nct6797, nct6798 }; + nct6793, nct6795, nct6796, nct6797, nct6798, nct6799 }; enum pwm_enable { off, manual, thermal_cruise, speed_cruise, sf3, sf4 }; #define NUM_TEMP 10 /* Max number of temp attribute sets w/ limits*/ diff --git a/drivers/hwmon/nct7802.c b/drivers/hwmon/nct7802.c index a175f8283695e459ff52fd679a0054748275b35f..9339bfc02a3efc375b31a70138a1c603457171fc 100644 --- a/drivers/hwmon/nct7802.c +++ b/drivers/hwmon/nct7802.c @@ -1223,7 +1223,7 @@ static struct i2c_driver nct7802_driver = { .name = DRVNAME, }, .detect = nct7802_detect, - .probe_new = nct7802_probe, + .probe = nct7802_probe, .id_table = nct7802_idtable, .address_list = nct7802_address_list, }; diff --git a/drivers/hwmon/nct7904.c b/drivers/hwmon/nct7904.c index 007bae4c7028f7ead7b099343f854414c4c4c834..8f867d4570e181979151401f6b12b1eae836be0d 100644 --- a/drivers/hwmon/nct7904.c +++ b/drivers/hwmon/nct7904.c @@ -1171,7 +1171,7 @@ static struct i2c_driver nct7904_driver = { .driver = { .name = "nct7904", }, - .probe_new = nct7904_probe, + .probe = nct7904_probe, .id_table = nct7904_id, .detect = nct7904_detect, .address_list = normal_i2c, diff --git a/drivers/hwmon/occ/p8_i2c.c b/drivers/hwmon/occ/p8_i2c.c index 9e1744fccb35308e3f76858bff0173fcecb5c483..06095975f5c8d2fe014a574a7490cf17399b1677 100644 --- a/drivers/hwmon/occ/p8_i2c.c +++ b/drivers/hwmon/occ/p8_i2c.c @@ -246,7 +246,7 @@ static struct i2c_driver p8_i2c_occ_driver = { .name = "occ-hwmon", .of_match_table = p8_i2c_occ_of_match, }, - .probe_new = p8_i2c_occ_probe, + .probe = p8_i2c_occ_probe, .remove = p8_i2c_occ_remove, }; diff --git a/drivers/hwmon/oxp-sensors.c b/drivers/hwmon/oxp-sensors.c index ae67207030e8a3a2ea2933f57d4eecccac019c80..e1a907cae820e7734cd2c96c940c85870d45e279 100644 --- a/drivers/hwmon/oxp-sensors.c +++ b/drivers/hwmon/oxp-sensors.c @@ -16,7 +16,6 @@ */ #include -#include #include #include #include @@ -42,53 +41,97 @@ static bool unlock_global_acpi_lock(void) enum oxp_board { aok_zoe_a1 = 1, + aya_neo_2, aya_neo_air, aya_neo_air_pro, + aya_neo_geek, oxp_mini_amd, + oxp_mini_amd_a07, oxp_mini_amd_pro, }; static enum oxp_board board; +/* Fan reading and PWM */ #define OXP_SENSOR_FAN_REG 0x76 /* Fan reading is 2 registers long */ #define OXP_SENSOR_PWM_ENABLE_REG 0x4A /* PWM enable is 1 register long */ #define OXP_SENSOR_PWM_REG 0x4B /* PWM reading is 1 register long */ +/* Turbo button takeover function + * Older boards have different values and EC registers + * for the same function + */ +#define OXP_OLD_TURBO_SWITCH_REG 0x1E +#define OXP_OLD_TURBO_TAKE_VAL 0x01 +#define OXP_OLD_TURBO_RETURN_VAL 0x00 + +#define OXP_TURBO_SWITCH_REG 0xF1 +#define OXP_TURBO_TAKE_VAL 0x40 +#define OXP_TURBO_RETURN_VAL 0x00 + static const struct dmi_system_id dmi_table[] = { { .matches = { DMI_MATCH(DMI_BOARD_VENDOR, "AOKZOE"), DMI_EXACT_MATCH(DMI_BOARD_NAME, "AOKZOE A1 AR07"), }, - .driver_data = (void *) &(enum oxp_board) {aok_zoe_a1}, + .driver_data = (void *)aok_zoe_a1, + }, + { + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "AOKZOE"), + DMI_EXACT_MATCH(DMI_BOARD_NAME, "AOKZOE A1 Pro"), + }, + .driver_data = (void *)aok_zoe_a1, + }, + { + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "AYANEO"), + DMI_EXACT_MATCH(DMI_BOARD_NAME, "AYANEO 2"), + }, + .driver_data = (void *)aya_neo_2, }, { .matches = { DMI_MATCH(DMI_BOARD_VENDOR, "AYANEO"), DMI_EXACT_MATCH(DMI_BOARD_NAME, "AIR"), }, - .driver_data = (void *) &(enum oxp_board) {aya_neo_air}, + .driver_data = (void *)aya_neo_air, }, { .matches = { DMI_MATCH(DMI_BOARD_VENDOR, "AYANEO"), DMI_EXACT_MATCH(DMI_BOARD_NAME, "AIR Pro"), }, - .driver_data = (void *) &(enum oxp_board) {aya_neo_air_pro}, + .driver_data = (void *)aya_neo_air_pro, + }, + { + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "AYANEO"), + DMI_EXACT_MATCH(DMI_BOARD_NAME, "GEEK"), + }, + .driver_data = (void *)aya_neo_geek, }, { .matches = { DMI_MATCH(DMI_BOARD_VENDOR, "ONE-NETBOOK"), DMI_EXACT_MATCH(DMI_BOARD_NAME, "ONE XPLAYER"), }, - .driver_data = (void *) &(enum oxp_board) {oxp_mini_amd}, + .driver_data = (void *)oxp_mini_amd, + }, + { + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "ONE-NETBOOK"), + DMI_EXACT_MATCH(DMI_BOARD_NAME, "ONEXPLAYER mini A07"), + }, + .driver_data = (void *)oxp_mini_amd_a07, }, { .matches = { DMI_MATCH(DMI_BOARD_VENDOR, "ONE-NETBOOK"), DMI_EXACT_MATCH(DMI_BOARD_NAME, "ONEXPLAYER Mini Pro"), }, - .driver_data = (void *) &(enum oxp_board) {oxp_mini_amd_pro}, + .driver_data = (void *)oxp_mini_amd_pro, }, {}, }; @@ -118,7 +161,7 @@ static int read_from_ec(u8 reg, int size, long *val) return 0; } -static int write_to_ec(const struct device *dev, u8 reg, u8 value) +static int write_to_ec(u8 reg, u8 value) { int ret; @@ -133,14 +176,109 @@ static int write_to_ec(const struct device *dev, u8 reg, u8 value) return ret; } -static int oxp_pwm_enable(const struct device *dev) +/* Turbo button toggle functions */ +static int tt_toggle_enable(void) +{ + u8 reg; + u8 val; + + switch (board) { + case oxp_mini_amd_a07: + reg = OXP_OLD_TURBO_SWITCH_REG; + val = OXP_OLD_TURBO_TAKE_VAL; + break; + case oxp_mini_amd_pro: + case aok_zoe_a1: + reg = OXP_TURBO_SWITCH_REG; + val = OXP_TURBO_TAKE_VAL; + break; + default: + return -EINVAL; + } + return write_to_ec(reg, val); +} + +static int tt_toggle_disable(void) +{ + u8 reg; + u8 val; + + switch (board) { + case oxp_mini_amd_a07: + reg = OXP_OLD_TURBO_SWITCH_REG; + val = OXP_OLD_TURBO_RETURN_VAL; + break; + case oxp_mini_amd_pro: + case aok_zoe_a1: + reg = OXP_TURBO_SWITCH_REG; + val = OXP_TURBO_RETURN_VAL; + break; + default: + return -EINVAL; + } + return write_to_ec(reg, val); +} + +/* Callbacks for turbo toggle attribute */ +static ssize_t tt_toggle_store(struct device *dev, + struct device_attribute *attr, const char *buf, + size_t count) +{ + int rval; + bool value; + + rval = kstrtobool(buf, &value); + if (rval) + return rval; + + if (value) { + rval = tt_toggle_enable(); + } else { + rval = tt_toggle_disable(); + } + if (rval) + return rval; + + return count; +} + +static ssize_t tt_toggle_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int retval; + u8 reg; + long val; + + switch (board) { + case oxp_mini_amd_a07: + reg = OXP_OLD_TURBO_SWITCH_REG; + break; + case oxp_mini_amd_pro: + case aok_zoe_a1: + reg = OXP_TURBO_SWITCH_REG; + break; + default: + return -EINVAL; + } + + retval = read_from_ec(reg, 1, &val); + if (retval) + return retval; + + return sysfs_emit(buf, "%d\n", !!val); +} + +static DEVICE_ATTR_RW(tt_toggle); + +/* PWM enable/disable functions */ +static int oxp_pwm_enable(void) { - return write_to_ec(dev, OXP_SENSOR_PWM_ENABLE_REG, 0x01); + return write_to_ec(OXP_SENSOR_PWM_ENABLE_REG, 0x01); } -static int oxp_pwm_disable(const struct device *dev) +static int oxp_pwm_disable(void) { - return write_to_ec(dev, OXP_SENSOR_PWM_ENABLE_REG, 0x00); + return write_to_ec(OXP_SENSOR_PWM_ENABLE_REG, 0x00); } /* Callbacks for hwmon interface */ @@ -178,9 +316,12 @@ static int oxp_platform_read(struct device *dev, enum hwmon_sensor_types type, if (ret) return ret; switch (board) { + case aya_neo_2: case aya_neo_air: case aya_neo_air_pro: + case aya_neo_geek: case oxp_mini_amd: + case oxp_mini_amd_a07: *val = (*val * 255) / 100; break; case oxp_mini_amd_pro: @@ -209,17 +350,20 @@ static int oxp_platform_write(struct device *dev, enum hwmon_sensor_types type, switch (attr) { case hwmon_pwm_enable: if (val == 1) - return oxp_pwm_enable(dev); + return oxp_pwm_enable(); else if (val == 0) - return oxp_pwm_disable(dev); + return oxp_pwm_disable(); return -EINVAL; case hwmon_pwm_input: if (val < 0 || val > 255) return -EINVAL; switch (board) { + case aya_neo_2: case aya_neo_air: case aya_neo_air_pro: + case aya_neo_geek: case oxp_mini_amd: + case oxp_mini_amd_a07: val = (val * 100) / 255; break; case aok_zoe_a1: @@ -227,7 +371,7 @@ static int oxp_platform_write(struct device *dev, enum hwmon_sensor_types type, default: break; } - return write_to_ec(dev, OXP_SENSOR_PWM_REG, val); + return write_to_ec(OXP_SENSOR_PWM_REG, val); default: break; } @@ -247,6 +391,13 @@ static const struct hwmon_channel_info * const oxp_platform_sensors[] = { NULL, }; +static struct attribute *oxp_ec_attrs[] = { + &dev_attr_tt_toggle.attr, + NULL +}; + +ATTRIBUTE_GROUPS(oxp_ec); + static const struct hwmon_ops oxp_ec_hwmon_ops = { .is_visible = oxp_ec_hwmon_is_visible, .read = oxp_platform_read, @@ -264,6 +415,7 @@ static int oxp_platform_probe(struct platform_device *pdev) const struct dmi_system_id *dmi_entry; struct device *dev = &pdev->dev; struct device *hwdev; + int ret; /* * Have to check for AMD processor here because DMI strings are the @@ -276,7 +428,19 @@ static int oxp_platform_probe(struct platform_device *pdev) if (!dmi_entry || boot_cpu_data.x86_vendor != X86_VENDOR_AMD) return -ENODEV; - board = *((enum oxp_board *) dmi_entry->driver_data); + board = (enum oxp_board)(unsigned long)dmi_entry->driver_data; + + switch (board) { + case aok_zoe_a1: + case oxp_mini_amd_a07: + case oxp_mini_amd_pro: + ret = devm_device_add_groups(dev, oxp_ec_groups); + if (ret) + return ret; + break; + default: + break; + } hwdev = devm_hwmon_device_register_with_info(dev, "oxpec", NULL, &oxp_ec_chip_info, NULL); diff --git a/drivers/hwmon/pcf8591.c b/drivers/hwmon/pcf8591.c index 1dbe209ae13f5fd757a13254586272b4a9df0165..66c76b28c9e0aa57d62d1122b7333058ead60146 100644 --- a/drivers/hwmon/pcf8591.c +++ b/drivers/hwmon/pcf8591.c @@ -294,7 +294,7 @@ static struct i2c_driver pcf8591_driver = { .driver = { .name = "pcf8591", }, - .probe_new = pcf8591_probe, + .probe = pcf8591_probe, .remove = pcf8591_remove, .id_table = pcf8591_id, }; diff --git a/drivers/hwmon/pmbus/acbel-fsg032.c b/drivers/hwmon/pmbus/acbel-fsg032.c index 28a25f30e2cfd567a1f4ea230066bf6ad9de5b95..0a0ef4ce34933c6616e18417703135ba393d0015 100644 --- a/drivers/hwmon/pmbus/acbel-fsg032.c +++ b/drivers/hwmon/pmbus/acbel-fsg032.c @@ -73,7 +73,7 @@ static struct i2c_driver acbel_fsg032_driver = { .name = "acbel-fsg032", .of_match_table = acbel_fsg032_of_match, }, - .probe_new = acbel_fsg032_probe, + .probe = acbel_fsg032_probe, .id_table = acbel_fsg032_id, }; diff --git a/drivers/hwmon/pmbus/adm1266.c b/drivers/hwmon/pmbus/adm1266.c index 1ac2b2f4c5705f5a142579e3085c703675d5b01b..ed0a7b9fae4bf269fb37ef1578e9d6afe19b2eba 100644 --- a/drivers/hwmon/pmbus/adm1266.c +++ b/drivers/hwmon/pmbus/adm1266.c @@ -340,8 +340,6 @@ static void adm1266_init_debugfs(struct adm1266_data *data) return; data->debugfs_dir = debugfs_create_dir(data->client->name, root); - if (!data->debugfs_dir) - return; debugfs_create_devm_seqfile(&data->client->dev, "sequencer_state", data->debugfs_dir, adm1266_state_read); @@ -502,7 +500,7 @@ static struct i2c_driver adm1266_driver = { .name = "adm1266", .of_match_table = adm1266_of_match, }, - .probe_new = adm1266_probe, + .probe = adm1266_probe, .id_table = adm1266_id, }; diff --git a/drivers/hwmon/pmbus/adm1275.c b/drivers/hwmon/pmbus/adm1275.c index 3b07bfb43e93704677bfe57bed8c6d547789bd1d..e2c61d6fa521b1ca78e83328a14d2c315822d6c4 100644 --- a/drivers/hwmon/pmbus/adm1275.c +++ b/drivers/hwmon/pmbus/adm1275.c @@ -27,8 +27,11 @@ enum chips { adm1075, adm1272, adm1275, adm1276, adm1278, adm1293, adm1294 }; #define ADM1275_PEAK_IOUT 0xd0 #define ADM1275_PEAK_VIN 0xd1 #define ADM1275_PEAK_VOUT 0xd2 +#define ADM1275_PMON_CONTROL 0xd3 #define ADM1275_PMON_CONFIG 0xd4 +#define ADM1275_CONVERT_EN BIT(0) + #define ADM1275_VIN_VOUT_SELECT BIT(6) #define ADM1275_VRANGE BIT(5) #define ADM1075_IRANGE_50 BIT(4) @@ -37,10 +40,13 @@ enum chips { adm1075, adm1272, adm1275, adm1276, adm1278, adm1293, adm1294 }; #define ADM1272_IRANGE BIT(0) +#define ADM1278_TSFILT BIT(15) #define ADM1278_TEMP1_EN BIT(3) #define ADM1278_VIN_EN BIT(2) #define ADM1278_VOUT_EN BIT(1) +#define ADM1278_PMON_DEFCONFIG (ADM1278_VOUT_EN | ADM1278_TEMP1_EN | ADM1278_TSFILT) + #define ADM1293_IRANGE_25 0 #define ADM1293_IRANGE_50 BIT(6) #define ADM1293_IRANGE_100 BIT(7) @@ -170,8 +176,8 @@ static const struct coefficients adm1293_coefficients[] = { [18] = { 7658, 0, -3 }, /* power, 21V, irange200 */ }; -static int adm1275_read_pmon_config(const struct adm1275_data *data, - struct i2c_client *client, bool is_power) +static int adm1275_read_samples(const struct adm1275_data *data, + struct i2c_client *client, bool is_power) { int shift, ret; u16 mask; @@ -197,8 +203,36 @@ static int adm1275_read_pmon_config(const struct adm1275_data *data, } static int adm1275_write_pmon_config(const struct adm1275_data *data, - struct i2c_client *client, - bool is_power, u16 word) + struct i2c_client *client, u16 word) +{ + int ret, ret2; + + ret = i2c_smbus_write_byte_data(client, ADM1275_PMON_CONTROL, 0); + if (ret) + return ret; + + if (data->have_power_sampling) + ret = i2c_smbus_write_word_data(client, ADM1275_PMON_CONFIG, + word); + else + ret = i2c_smbus_write_byte_data(client, ADM1275_PMON_CONFIG, + word); + + /* + * We still want to re-enable conversions if writing into + * ADM1275_PMON_CONFIG failed. + */ + ret2 = i2c_smbus_write_byte_data(client, ADM1275_PMON_CONTROL, + ADM1275_CONVERT_EN); + if (!ret) + ret = ret2; + + return ret; +} + +static int adm1275_write_samples(const struct adm1275_data *data, + struct i2c_client *client, + bool is_power, u16 word) { int shift, ret; u16 mask; @@ -216,14 +250,8 @@ static int adm1275_write_pmon_config(const struct adm1275_data *data, return ret; word = (ret & ~mask) | ((word << shift) & mask); - if (data->have_power_sampling) - ret = i2c_smbus_write_word_data(client, ADM1275_PMON_CONFIG, - word); - else - ret = i2c_smbus_write_byte_data(client, ADM1275_PMON_CONFIG, - word); - return ret; + return adm1275_write_pmon_config(data, client, word); } static int adm1275_read_word_data(struct i2c_client *client, int page, @@ -318,14 +346,14 @@ static int adm1275_read_word_data(struct i2c_client *client, int page, case PMBUS_VIRT_POWER_SAMPLES: if (!data->have_power_sampling) return -ENXIO; - ret = adm1275_read_pmon_config(data, client, true); + ret = adm1275_read_samples(data, client, true); if (ret < 0) break; ret = BIT(ret); break; case PMBUS_VIRT_IN_SAMPLES: case PMBUS_VIRT_CURR_SAMPLES: - ret = adm1275_read_pmon_config(data, client, false); + ret = adm1275_read_samples(data, client, false); if (ret < 0) break; ret = BIT(ret); @@ -378,14 +406,12 @@ static int adm1275_write_word_data(struct i2c_client *client, int page, int reg, if (!data->have_power_sampling) return -ENXIO; word = clamp_val(word, 1, ADM1275_SAMPLES_AVG_MAX); - ret = adm1275_write_pmon_config(data, client, true, - ilog2(word)); + ret = adm1275_write_samples(data, client, true, ilog2(word)); break; case PMBUS_VIRT_IN_SAMPLES: case PMBUS_VIRT_CURR_SAMPLES: word = clamp_val(word, 1, ADM1275_SAMPLES_AVG_MAX); - ret = adm1275_write_pmon_config(data, client, false, - ilog2(word)); + ret = adm1275_write_samples(data, client, false, ilog2(word)); break; default: ret = -ENODATA; @@ -462,6 +488,23 @@ static const struct i2c_device_id adm1275_id[] = { }; MODULE_DEVICE_TABLE(i2c, adm1275_id); +/* Enable VOUT & TEMP1 if not enabled (disabled by default) */ +static int adm1275_enable_vout_temp(struct adm1275_data *data, + struct i2c_client *client, int config) +{ + int ret; + + if ((config & ADM1278_PMON_DEFCONFIG) != ADM1278_PMON_DEFCONFIG) { + config |= ADM1278_PMON_DEFCONFIG; + ret = adm1275_write_pmon_config(data, client, config); + if (ret < 0) { + dev_err(&client->dev, "Failed to enable VOUT/TEMP1 monitoring\n"); + return ret; + } + } + return 0; +} + static int adm1275_probe(struct i2c_client *client) { s32 (*config_read_fn)(const struct i2c_client *client, u8 reg); @@ -615,19 +658,10 @@ static int adm1275_probe(struct i2c_client *client) PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP; - /* Enable VOUT & TEMP1 if not enabled (disabled by default) */ - if ((config & (ADM1278_VOUT_EN | ADM1278_TEMP1_EN)) != - (ADM1278_VOUT_EN | ADM1278_TEMP1_EN)) { - config |= ADM1278_VOUT_EN | ADM1278_TEMP1_EN; - ret = i2c_smbus_write_byte_data(client, - ADM1275_PMON_CONFIG, - config); - if (ret < 0) { - dev_err(&client->dev, - "Failed to enable VOUT monitoring\n"); - return -ENODEV; - } - } + ret = adm1275_enable_vout_temp(data, client, config); + if (ret) + return ret; + if (config & ADM1278_VIN_EN) info->func[0] |= PMBUS_HAVE_VIN; break; @@ -684,19 +718,9 @@ static int adm1275_probe(struct i2c_client *client) PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP; - /* Enable VOUT & TEMP1 if not enabled (disabled by default) */ - if ((config & (ADM1278_VOUT_EN | ADM1278_TEMP1_EN)) != - (ADM1278_VOUT_EN | ADM1278_TEMP1_EN)) { - config |= ADM1278_VOUT_EN | ADM1278_TEMP1_EN; - ret = i2c_smbus_write_word_data(client, - ADM1275_PMON_CONFIG, - config); - if (ret < 0) { - dev_err(&client->dev, - "Failed to enable VOUT monitoring\n"); - return -ENODEV; - } - } + ret = adm1275_enable_vout_temp(data, client, config); + if (ret) + return ret; if (config & ADM1278_VIN_EN) info->func[0] |= PMBUS_HAVE_VIN; @@ -766,8 +790,7 @@ static int adm1275_probe(struct i2c_client *client) "Invalid number of power samples"); return -EINVAL; } - ret = adm1275_write_pmon_config(data, client, true, - ilog2(avg)); + ret = adm1275_write_samples(data, client, true, ilog2(avg)); if (ret < 0) { dev_err(&client->dev, "Setting power sample averaging failed with error %d", @@ -784,8 +807,7 @@ static int adm1275_probe(struct i2c_client *client) "Invalid number of voltage/current samples"); return -EINVAL; } - ret = adm1275_write_pmon_config(data, client, false, - ilog2(avg)); + ret = adm1275_write_samples(data, client, false, ilog2(avg)); if (ret < 0) { dev_err(&client->dev, "Setting voltage and current sample averaging failed with error %d", @@ -832,7 +854,7 @@ static struct i2c_driver adm1275_driver = { .driver = { .name = "adm1275", }, - .probe_new = adm1275_probe, + .probe = adm1275_probe, .id_table = adm1275_id, }; diff --git a/drivers/hwmon/pmbus/bel-pfe.c b/drivers/hwmon/pmbus/bel-pfe.c index 4100eefb7ac3237dfbca8912a789d547c272d5d2..fa5070ae26bc43d4a362493c2c6a8bacce2284c3 100644 --- a/drivers/hwmon/pmbus/bel-pfe.c +++ b/drivers/hwmon/pmbus/bel-pfe.c @@ -120,7 +120,7 @@ static struct i2c_driver pfe_pmbus_driver = { .driver = { .name = "bel-pfe", }, - .probe_new = pfe_pmbus_probe, + .probe = pfe_pmbus_probe, .id_table = pfe_device_id, }; diff --git a/drivers/hwmon/pmbus/bpa-rs600.c b/drivers/hwmon/pmbus/bpa-rs600.c index f2d4e378a775720133c554e03580fc2812b4f40a..0dce26c355565815130e975295118b095d5a2caf 100644 --- a/drivers/hwmon/pmbus/bpa-rs600.c +++ b/drivers/hwmon/pmbus/bpa-rs600.c @@ -196,7 +196,7 @@ static struct i2c_driver bpa_rs600_driver = { .name = "bpa-rs600", .of_match_table = of_match_ptr(bpa_rs600_of_match), }, - .probe_new = bpa_rs600_probe, + .probe = bpa_rs600_probe, .id_table = bpa_rs600_id, }; diff --git a/drivers/hwmon/pmbus/delta-ahe50dc-fan.c b/drivers/hwmon/pmbus/delta-ahe50dc-fan.c index f546f0c12497b01812b6d50f4bed2d29ef01dddb..4dd3b6686d6a44288f3f368daa6c09d20e2cd780 100644 --- a/drivers/hwmon/pmbus/delta-ahe50dc-fan.c +++ b/drivers/hwmon/pmbus/delta-ahe50dc-fan.c @@ -119,7 +119,7 @@ static struct i2c_driver ahe50dc_fan_driver = { .name = "ahe50dc_fan", .of_match_table = of_match_ptr(ahe50dc_fan_of_match), }, - .probe_new = ahe50dc_fan_probe, + .probe = ahe50dc_fan_probe, .id_table = ahe50dc_fan_id, }; module_i2c_driver(ahe50dc_fan_driver); diff --git a/drivers/hwmon/pmbus/dps920ab.c b/drivers/hwmon/pmbus/dps920ab.c index d3941f6eb29a9f1876dfd8f6615ccd32ad7dd6c2..f7ff3e4650b71e66bb0981d9e331cb705e1c9904 100644 --- a/drivers/hwmon/pmbus/dps920ab.c +++ b/drivers/hwmon/pmbus/dps920ab.c @@ -195,7 +195,7 @@ static struct i2c_driver dps920ab_driver = { .name = "dps920ab", .of_match_table = of_match_ptr(dps920ab_of_match), }, - .probe_new = dps920ab_probe, + .probe = dps920ab_probe, }; module_i2c_driver(dps920ab_driver); diff --git a/drivers/hwmon/pmbus/fsp-3y.c b/drivers/hwmon/pmbus/fsp-3y.c index c7469d2cdedcf738d02daec0ec9ce0b9870013f8..72a7c261ef068db4166591bbad3cbbb3f9c98d0d 100644 --- a/drivers/hwmon/pmbus/fsp-3y.c +++ b/drivers/hwmon/pmbus/fsp-3y.c @@ -282,7 +282,7 @@ static struct i2c_driver fsp3y_driver = { .driver = { .name = "fsp3y", }, - .probe_new = fsp3y_probe, + .probe = fsp3y_probe, .id_table = fsp3y_id }; diff --git a/drivers/hwmon/pmbus/ibm-cffps.c b/drivers/hwmon/pmbus/ibm-cffps.c index 76e72e9acda7817eb388396c4f7943f387e69065..c791925b89077be8b2abd30deadb0c4cc0d51389 100644 --- a/drivers/hwmon/pmbus/ibm-cffps.c +++ b/drivers/hwmon/pmbus/ibm-cffps.c @@ -605,7 +605,7 @@ static struct i2c_driver ibm_cffps_driver = { .name = "ibm-cffps", .of_match_table = ibm_cffps_of_match, }, - .probe_new = ibm_cffps_probe, + .probe = ibm_cffps_probe, .id_table = ibm_cffps_id, }; diff --git a/drivers/hwmon/pmbus/inspur-ipsps.c b/drivers/hwmon/pmbus/inspur-ipsps.c index 0f614e8d95f674083a7f2c4db12e65efd2bbb4fb..dfeae68b5e52d37eeba43708935be815a1a135bf 100644 --- a/drivers/hwmon/pmbus/inspur-ipsps.c +++ b/drivers/hwmon/pmbus/inspur-ipsps.c @@ -215,7 +215,7 @@ static struct i2c_driver ipsps_driver = { .name = "inspur-ipsps", .of_match_table = of_match_ptr(ipsps_of_match), }, - .probe_new = ipsps_probe, + .probe = ipsps_probe, .id_table = ipsps_id, }; diff --git a/drivers/hwmon/pmbus/ir35221.c b/drivers/hwmon/pmbus/ir35221.c index a6cf98e496664e1c5b3e7b1197e08f41ac9e1aaa..e3ee5c1bd9675ccd14fd9d73023d371d864b2ce8 100644 --- a/drivers/hwmon/pmbus/ir35221.c +++ b/drivers/hwmon/pmbus/ir35221.c @@ -136,7 +136,7 @@ static struct i2c_driver ir35221_driver = { .driver = { .name = "ir35221", }, - .probe_new = ir35221_probe, + .probe = ir35221_probe, .id_table = ir35221_id, }; diff --git a/drivers/hwmon/pmbus/ir36021.c b/drivers/hwmon/pmbus/ir36021.c index 4dca4767f571389775e451822fb465910dd84401..382ba6b6031a0374ac03d20a3738b7c3c1a3e7e6 100644 --- a/drivers/hwmon/pmbus/ir36021.c +++ b/drivers/hwmon/pmbus/ir36021.c @@ -68,7 +68,7 @@ static struct i2c_driver ir36021_driver = { .name = "ir36021", .of_match_table = of_match_ptr(ir36021_of_id), }, - .probe_new = ir36021_probe, + .probe = ir36021_probe, .id_table = ir36021_id, }; diff --git a/drivers/hwmon/pmbus/ir38064.c b/drivers/hwmon/pmbus/ir38064.c index 09276e397194524b04ff8cf668cf45701dc44234..871c322d3d515447cf49f63f3c487601867386cd 100644 --- a/drivers/hwmon/pmbus/ir38064.c +++ b/drivers/hwmon/pmbus/ir38064.c @@ -78,7 +78,7 @@ static struct i2c_driver ir38064_driver = { .name = "ir38064", .of_match_table = of_match_ptr(ir38064_of_match), }, - .probe_new = ir38064_probe, + .probe = ir38064_probe, .id_table = ir38064_id, }; diff --git a/drivers/hwmon/pmbus/irps5401.c b/drivers/hwmon/pmbus/irps5401.c index de3449e4d77a60d60b8aba53b895e99363ebcc61..146d32a35a7c06809db5af8c564d3aee62678e69 100644 --- a/drivers/hwmon/pmbus/irps5401.c +++ b/drivers/hwmon/pmbus/irps5401.c @@ -54,7 +54,7 @@ static struct i2c_driver irps5401_driver = { .driver = { .name = "irps5401", }, - .probe_new = irps5401_probe, + .probe = irps5401_probe, .id_table = irps5401_id, }; diff --git a/drivers/hwmon/pmbus/isl68137.c b/drivers/hwmon/pmbus/isl68137.c index 1a8caff1ac5f6b03cd7f17d26a69a8074de14c92..7e53fb1d5ea3036434501cb090434ecc18e4820f 100644 --- a/drivers/hwmon/pmbus/isl68137.c +++ b/drivers/hwmon/pmbus/isl68137.c @@ -323,7 +323,7 @@ static struct i2c_driver isl68137_driver = { .driver = { .name = "isl68137", }, - .probe_new = isl68137_probe, + .probe = isl68137_probe, .id_table = raa_dmpvr_id, }; diff --git a/drivers/hwmon/pmbus/lm25066.c b/drivers/hwmon/pmbus/lm25066.c index 09792cd03d9fde584f903adf7bff558690e4c0fa..929fa6d34efdc5e19b79ef8bd8728afec6bf1928 100644 --- a/drivers/hwmon/pmbus/lm25066.c +++ b/drivers/hwmon/pmbus/lm25066.c @@ -568,7 +568,7 @@ static struct i2c_driver lm25066_driver = { .name = "lm25066", .of_match_table = of_match_ptr(lm25066_of_match), }, - .probe_new = lm25066_probe, + .probe = lm25066_probe, .id_table = lm25066_id, }; diff --git a/drivers/hwmon/pmbus/lt7182s.c b/drivers/hwmon/pmbus/lt7182s.c index 4cfe476fc92d2125758b87404d7a9c672ffe67b1..28afc5f15ae8cc51a33e38a2452f606a0dec945b 100644 --- a/drivers/hwmon/pmbus/lt7182s.c +++ b/drivers/hwmon/pmbus/lt7182s.c @@ -183,7 +183,7 @@ static struct i2c_driver lt7182s_driver = { .name = "lt7182s", .of_match_table = of_match_ptr(lt7182s_of_match), }, - .probe_new = lt7182s_probe, + .probe = lt7182s_probe, .id_table = lt7182s_id, }; diff --git a/drivers/hwmon/pmbus/ltc2978.c b/drivers/hwmon/pmbus/ltc2978.c index 91df8e895147272d0384616c53c24f45e804c476..73a86f4d647288be97615f19a5c6314e4036e6a3 100644 --- a/drivers/hwmon/pmbus/ltc2978.c +++ b/drivers/hwmon/pmbus/ltc2978.c @@ -927,7 +927,7 @@ static struct i2c_driver ltc2978_driver = { .name = "ltc2978", .of_match_table = of_match_ptr(ltc2978_of_match), }, - .probe_new = ltc2978_probe, + .probe = ltc2978_probe, .id_table = ltc2978_id, }; diff --git a/drivers/hwmon/pmbus/ltc3815.c b/drivers/hwmon/pmbus/ltc3815.c index 8e13a7ddcb4270e6198f8787cf1812566eb2c189..f2023b17aa8da677ef5b225665f59b1990cf9588 100644 --- a/drivers/hwmon/pmbus/ltc3815.c +++ b/drivers/hwmon/pmbus/ltc3815.c @@ -199,7 +199,7 @@ static struct i2c_driver ltc3815_driver = { .driver = { .name = "ltc3815", }, - .probe_new = ltc3815_probe, + .probe = ltc3815_probe, .id_table = ltc3815_id, }; diff --git a/drivers/hwmon/pmbus/max15301.c b/drivers/hwmon/pmbus/max15301.c index 0b6f88428ea81dfde9fa699e2f2d83e73c93d8e5..2cfaa62aedd610a9a43a711deeac70a7de8426be 100644 --- a/drivers/hwmon/pmbus/max15301.c +++ b/drivers/hwmon/pmbus/max15301.c @@ -178,7 +178,7 @@ static struct i2c_driver max15301_driver = { .driver = { .name = "max15301", }, - .probe_new = max15301_probe, + .probe = max15301_probe, .id_table = max15301_id, }; diff --git a/drivers/hwmon/pmbus/max16064.c b/drivers/hwmon/pmbus/max16064.c index 94f86903907194eb4f5124f12b7c2a1a8e151218..a573a0ab9e48522026e3b56447f18bbd1d8bc04f 100644 --- a/drivers/hwmon/pmbus/max16064.c +++ b/drivers/hwmon/pmbus/max16064.c @@ -102,7 +102,7 @@ static struct i2c_driver max16064_driver = { .driver = { .name = "max16064", }, - .probe_new = max16064_probe, + .probe = max16064_probe, .id_table = max16064_id, }; diff --git a/drivers/hwmon/pmbus/max16601.c b/drivers/hwmon/pmbus/max16601.c index 6724f723f74ced0c1b5aea16b02755b872bd8e6e..3ab2195046007a5c9e9611616322eaf10f17ec58 100644 --- a/drivers/hwmon/pmbus/max16601.c +++ b/drivers/hwmon/pmbus/max16601.c @@ -283,10 +283,10 @@ static int max16601_get_id(struct i2c_client *client) return -ENODEV; /* - * PMBUS_IC_DEVICE_ID is expected to return MAX1660[012]y.xx" or - * "MAX16500y.xx".cdxxcccccccccc + * PMBUS_IC_DEVICE_ID is expected to return MAX1660[012]y.xx", + * "MAX16500y.xx".cdxxcccccccccc, or "MAX16508y.xx". */ - if (!strncmp(buf, "MAX16500", 8)) { + if (!strncmp(buf, "MAX16500", 8) || !strncmp(buf, "MAX16508", 8)) { id = max16508; } else if (!strncmp(buf, "MAX16600", 8)) { id = max16600; @@ -357,7 +357,7 @@ static struct i2c_driver max16601_driver = { .driver = { .name = "max16601", }, - .probe_new = max16601_probe, + .probe = max16601_probe, .id_table = max16601_id, }; diff --git a/drivers/hwmon/pmbus/max20730.c b/drivers/hwmon/pmbus/max20730.c index ba39f03c63744922a254f1fbdb237d00f957af6a..7bcf279950331f70315e1ff198d35ca534363f0b 100644 --- a/drivers/hwmon/pmbus/max20730.c +++ b/drivers/hwmon/pmbus/max20730.c @@ -776,7 +776,7 @@ static struct i2c_driver max20730_driver = { .name = "max20730", .of_match_table = max20730_of_match, }, - .probe_new = max20730_probe, + .probe = max20730_probe, .id_table = max20730_id, }; diff --git a/drivers/hwmon/pmbus/max20751.c b/drivers/hwmon/pmbus/max20751.c index 2272dc8c2e380a870087c2fc1d32c60ce3c196fa..6ebd71cd081bf98fe0b1128600f6952e768dc4d4 100644 --- a/drivers/hwmon/pmbus/max20751.c +++ b/drivers/hwmon/pmbus/max20751.c @@ -42,7 +42,7 @@ static struct i2c_driver max20751_driver = { .driver = { .name = "max20751", }, - .probe_new = max20751_probe, + .probe = max20751_probe, .id_table = max20751_id, }; diff --git a/drivers/hwmon/pmbus/max31785.c b/drivers/hwmon/pmbus/max31785.c index 95d79a64b4836c0ae59ae28f6fa99511a0dbabbd..f9aa576495a50fdc57ef0b1ea143594b269d9a7d 100644 --- a/drivers/hwmon/pmbus/max31785.c +++ b/drivers/hwmon/pmbus/max31785.c @@ -394,7 +394,7 @@ static struct i2c_driver max31785_driver = { .name = "max31785", .of_match_table = max31785_of_match, }, - .probe_new = max31785_probe, + .probe = max31785_probe, .id_table = max31785_id, }; diff --git a/drivers/hwmon/pmbus/max34440.c b/drivers/hwmon/pmbus/max34440.c index ea7609058a12fc305d1c59c5e6911f7514c5bbdf..fe7f6b1b09851e725c0d6f2f5616f9aa470d9339 100644 --- a/drivers/hwmon/pmbus/max34440.c +++ b/drivers/hwmon/pmbus/max34440.c @@ -520,7 +520,7 @@ static struct i2c_driver max34440_driver = { .driver = { .name = "max34440", }, - .probe_new = max34440_probe, + .probe = max34440_probe, .id_table = max34440_id, }; diff --git a/drivers/hwmon/pmbus/max8688.c b/drivers/hwmon/pmbus/max8688.c index 5e66c28c0b7186d2e76e5d9ba992e67d71e3baea..ae8573fdf5bac723e706a3255ff2fa328feec209 100644 --- a/drivers/hwmon/pmbus/max8688.c +++ b/drivers/hwmon/pmbus/max8688.c @@ -182,7 +182,7 @@ static struct i2c_driver max8688_driver = { .driver = { .name = "max8688", }, - .probe_new = max8688_probe, + .probe = max8688_probe, .id_table = max8688_id, }; diff --git a/drivers/hwmon/pmbus/mp2888.c b/drivers/hwmon/pmbus/mp2888.c index 24e5194706cf66137ed86439b703e6c4e42b3df1..50662ed8e3d58309a8ef428a19b766cb05a23fb9 100644 --- a/drivers/hwmon/pmbus/mp2888.c +++ b/drivers/hwmon/pmbus/mp2888.c @@ -395,7 +395,7 @@ static struct i2c_driver mp2888_driver = { .name = "mp2888", .of_match_table = of_match_ptr(mp2888_of_match), }, - .probe_new = mp2888_probe, + .probe = mp2888_probe, .id_table = mp2888_id, }; diff --git a/drivers/hwmon/pmbus/mp2975.c b/drivers/hwmon/pmbus/mp2975.c index 51986adfbf47c56f653576f027ccbc4913e214be..2109b0458a8b5b4ac579afe6cae792aad43783f8 100644 --- a/drivers/hwmon/pmbus/mp2975.c +++ b/drivers/hwmon/pmbus/mp2975.c @@ -757,7 +757,7 @@ static struct i2c_driver mp2975_driver = { .name = "mp2975", .of_match_table = of_match_ptr(mp2975_of_match), }, - .probe_new = mp2975_probe, + .probe = mp2975_probe, .id_table = mp2975_id, }; diff --git a/drivers/hwmon/pmbus/mp5023.c b/drivers/hwmon/pmbus/mp5023.c index 791a06c3c54a40de1f2fb91648b297356a5e4bc0..c4c4324d2b7466c64f347db6e138410420dbf7db 100644 --- a/drivers/hwmon/pmbus/mp5023.c +++ b/drivers/hwmon/pmbus/mp5023.c @@ -56,7 +56,7 @@ static struct i2c_driver mp5023_driver = { .name = "mp5023", .of_match_table = of_match_ptr(mp5023_of_match), }, - .probe_new = mp5023_probe, + .probe = mp5023_probe, }; module_i2c_driver(mp5023_driver); diff --git a/drivers/hwmon/pmbus/mpq7932.c b/drivers/hwmon/pmbus/mpq7932.c index ff939881dc3bb513bfa6382232478cc1e3e61e88..865d42edda1a5417e5642e48775ffd5e65768723 100644 --- a/drivers/hwmon/pmbus/mpq7932.c +++ b/drivers/hwmon/pmbus/mpq7932.c @@ -145,7 +145,7 @@ static struct i2c_driver mpq7932_regulator_driver = { .name = "mpq7932", .of_match_table = mpq7932_of_match, }, - .probe_new = mpq7932_probe, + .probe = mpq7932_probe, .id_table = mpq7932_id, }; module_i2c_driver(mpq7932_regulator_driver); diff --git a/drivers/hwmon/pmbus/pim4328.c b/drivers/hwmon/pmbus/pim4328.c index 273ff6e576549b8760fce79524b31ddb59701f92..31d9ae06379a1ae000342c5686e852d4131e5861 100644 --- a/drivers/hwmon/pmbus/pim4328.c +++ b/drivers/hwmon/pmbus/pim4328.c @@ -221,7 +221,7 @@ static struct i2c_driver pim4328_driver = { .driver = { .name = "pim4328", }, - .probe_new = pim4328_probe, + .probe = pim4328_probe, .id_table = pim4328_id, }; diff --git a/drivers/hwmon/pmbus/pli1209bc.c b/drivers/hwmon/pmbus/pli1209bc.c index 05b4ee35ba270004e140229f586f9a461f4f46ad..7d8bd3167b213ebb40c14142c00fb970691ef357 100644 --- a/drivers/hwmon/pmbus/pli1209bc.c +++ b/drivers/hwmon/pmbus/pli1209bc.c @@ -134,7 +134,7 @@ static struct i2c_driver pli1209bc_driver = { .name = "pli1209bc", .of_match_table = of_match_ptr(pli1209bc_of_match), }, - .probe_new = pli1209bc_probe, + .probe = pli1209bc_probe, .id_table = pli1209bc_id, }; diff --git a/drivers/hwmon/pmbus/pm6764tr.c b/drivers/hwmon/pmbus/pm6764tr.c index e0bbc8a30d21efb08dcb974d552fd00828289d7e..2a16504c85b78ae4802d32ccfda10f2d624b3e25 100644 --- a/drivers/hwmon/pmbus/pm6764tr.c +++ b/drivers/hwmon/pmbus/pm6764tr.c @@ -64,7 +64,7 @@ static struct i2c_driver pm6764tr_driver = { .name = "pm6764tr", .of_match_table = of_match_ptr(pm6764tr_of_match), }, - .probe_new = pm6764tr_probe, + .probe = pm6764tr_probe, .id_table = pm6764tr_id, }; diff --git a/drivers/hwmon/pmbus/pmbus.c b/drivers/hwmon/pmbus/pmbus.c index d0d386990af5eb8ab1fad01564796323cf77e5a8..ec40c5c599543a77c0820a34b17426b3b9f951ee 100644 --- a/drivers/hwmon/pmbus/pmbus.c +++ b/drivers/hwmon/pmbus/pmbus.c @@ -252,7 +252,7 @@ static struct i2c_driver pmbus_driver = { .driver = { .name = "pmbus", }, - .probe_new = pmbus_probe, + .probe = pmbus_probe, .id_table = pmbus_id, }; diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c index 9d14954da94fbc14c85947e7825fd997570de1fc..fa06325f5a7cb8b1ccb12dc9d3100f6fe13253e1 100644 --- a/drivers/hwmon/pmbus/pmbus_core.c +++ b/drivers/hwmon/pmbus/pmbus_core.c @@ -1191,9 +1191,9 @@ static int pmbus_add_attribute(struct pmbus_data *data, struct attribute *attr) { if (data->num_attributes >= data->max_attributes - 1) { int new_max_attrs = data->max_attributes + PMBUS_ATTR_ALLOC_SIZE; - void *new_attrs = devm_krealloc(data->dev, data->group.attrs, - new_max_attrs * sizeof(void *), - GFP_KERNEL); + void *new_attrs = devm_krealloc_array(data->dev, data->group.attrs, + new_max_attrs, sizeof(void *), + GFP_KERNEL); if (!new_attrs) return -ENOMEM; data->group.attrs = new_attrs; diff --git a/drivers/hwmon/pmbus/pxe1610.c b/drivers/hwmon/pmbus/pxe1610.c index 52bee5de2988359abdfb3fe15ddc0244eaa1ef6c..e2790a682dc80cedd9be3e2b99738af47e93aa18 100644 --- a/drivers/hwmon/pmbus/pxe1610.c +++ b/drivers/hwmon/pmbus/pxe1610.c @@ -139,7 +139,7 @@ static struct i2c_driver pxe1610_driver = { .driver = { .name = "pxe1610", }, - .probe_new = pxe1610_probe, + .probe = pxe1610_probe, .id_table = pxe1610_id, }; diff --git a/drivers/hwmon/pmbus/q54sj108a2.c b/drivers/hwmon/pmbus/q54sj108a2.c index d3ba129513240ac79a31ed9b16af7e5fda8667ec..b830f3b02bcc9b7dd314b53e7acbcb11da8c5e56 100644 --- a/drivers/hwmon/pmbus/q54sj108a2.c +++ b/drivers/hwmon/pmbus/q54sj108a2.c @@ -412,7 +412,7 @@ static struct i2c_driver q54sj108a2_driver = { .name = "q54sj108a2", .of_match_table = q54sj108a2_of_match, }, - .probe_new = q54sj108a2_probe, + .probe = q54sj108a2_probe, .id_table = q54sj108a2_id, }; diff --git a/drivers/hwmon/pmbus/stpddc60.c b/drivers/hwmon/pmbus/stpddc60.c index 357b9d9d896b53c46e450a3dcb2c129024b254be..be9076dcc2dbf224427c1f4909c7372ce817f31a 100644 --- a/drivers/hwmon/pmbus/stpddc60.c +++ b/drivers/hwmon/pmbus/stpddc60.c @@ -237,7 +237,7 @@ static struct i2c_driver stpddc60_driver = { .driver = { .name = "stpddc60", }, - .probe_new = stpddc60_probe, + .probe = stpddc60_probe, .id_table = stpddc60_id, }; diff --git a/drivers/hwmon/pmbus/tda38640.c b/drivers/hwmon/pmbus/tda38640.c index c3e781319cd1dfe5890428c1251f34ae3bfa25df..450b0273fb59324443f65aaa5694695b1d22fc1b 100644 --- a/drivers/hwmon/pmbus/tda38640.c +++ b/drivers/hwmon/pmbus/tda38640.c @@ -62,7 +62,7 @@ static struct i2c_driver tda38640_driver = { .name = "tda38640", .of_match_table = of_match_ptr(tda38640_of_match), }, - .probe_new = tda38640_probe, + .probe = tda38640_probe, .id_table = tda38640_id, }; diff --git a/drivers/hwmon/pmbus/tps40422.c b/drivers/hwmon/pmbus/tps40422.c index 31bb83c0ef3e407f0a2546f716aa5268e18223b8..ea0074a6b9fc8ded8f8a0ecc341176f9cba2d792 100644 --- a/drivers/hwmon/pmbus/tps40422.c +++ b/drivers/hwmon/pmbus/tps40422.c @@ -42,7 +42,7 @@ static struct i2c_driver tps40422_driver = { .driver = { .name = "tps40422", }, - .probe_new = tps40422_probe, + .probe = tps40422_probe, .id_table = tps40422_id, }; diff --git a/drivers/hwmon/pmbus/tps53679.c b/drivers/hwmon/pmbus/tps53679.c index 81b9d813655ad2d02206cdbdfdc1cc29ad382ed8..ef99005a3af5ec7d1f8039a5fa7e3c67c735d420 100644 --- a/drivers/hwmon/pmbus/tps53679.c +++ b/drivers/hwmon/pmbus/tps53679.c @@ -299,7 +299,7 @@ static struct i2c_driver tps53679_driver = { .name = "tps53679", .of_match_table = of_match_ptr(tps53679_of_match), }, - .probe_new = tps53679_probe, + .probe = tps53679_probe, .id_table = tps53679_id, }; diff --git a/drivers/hwmon/pmbus/tps546d24.c b/drivers/hwmon/pmbus/tps546d24.c index 435f94304ad8b3f3d36263bd2be422794b6ccda3..69bbdb6c680bdff947ee32ada4b21de86baecb35 100644 --- a/drivers/hwmon/pmbus/tps546d24.c +++ b/drivers/hwmon/pmbus/tps546d24.c @@ -59,7 +59,7 @@ static struct i2c_driver tps546d24_driver = { .name = "tps546d24", .of_match_table = of_match_ptr(tps546d24_of_match), }, - .probe_new = tps546d24_probe, + .probe = tps546d24_probe, .id_table = tps546d24_id, }; diff --git a/drivers/hwmon/pmbus/ucd9000.c b/drivers/hwmon/pmbus/ucd9000.c index 3daaf22378322f6c2d0074bcad0f96220e227003..c404d306e8f7f0f00c1ea1cb79cab9b01ae1ea47 100644 --- a/drivers/hwmon/pmbus/ucd9000.c +++ b/drivers/hwmon/pmbus/ucd9000.c @@ -512,8 +512,6 @@ static int ucd9000_init_debugfs(struct i2c_client *client, return -ENOENT; data->debugfs = debugfs_create_dir(client->name, debugfs); - if (!data->debugfs) - return -ENOENT; /* * Of the chips this driver supports, only the UCD9090, UCD90160, @@ -695,7 +693,7 @@ static struct i2c_driver ucd9000_driver = { .name = "ucd9000", .of_match_table = of_match_ptr(ucd9000_of_match), }, - .probe_new = ucd9000_probe, + .probe = ucd9000_probe, .id_table = ucd9000_id, }; diff --git a/drivers/hwmon/pmbus/ucd9200.c b/drivers/hwmon/pmbus/ucd9200.c index 3ad375a76f3ecb20699a68776bf127744c37e0c1..a82847945508814624f5cd9e01089ed709ec7ebf 100644 --- a/drivers/hwmon/pmbus/ucd9200.c +++ b/drivers/hwmon/pmbus/ucd9200.c @@ -200,7 +200,7 @@ static struct i2c_driver ucd9200_driver = { .name = "ucd9200", .of_match_table = of_match_ptr(ucd9200_of_match), }, - .probe_new = ucd9200_probe, + .probe = ucd9200_probe, .id_table = ucd9200_id, }; diff --git a/drivers/hwmon/pmbus/xdpe12284.c b/drivers/hwmon/pmbus/xdpe12284.c index 32bc7736d609e38565b85d0ce1640b8e408a8e5a..37d08dd427d570009578bceba77405b1e20c4cd8 100644 --- a/drivers/hwmon/pmbus/xdpe12284.c +++ b/drivers/hwmon/pmbus/xdpe12284.c @@ -185,7 +185,7 @@ static struct i2c_driver xdpe122_driver = { .name = "xdpe12284", .of_match_table = of_match_ptr(xdpe122_of_match), }, - .probe_new = xdpe122_probe, + .probe = xdpe122_probe, .id_table = xdpe122_id, }; diff --git a/drivers/hwmon/pmbus/xdpe152c4.c b/drivers/hwmon/pmbus/xdpe152c4.c index b8a36ef73e45409527b5ed756e41731be9d9862a..235e6b41ae4c7eae6130d7422dc285f2cab0b4a2 100644 --- a/drivers/hwmon/pmbus/xdpe152c4.c +++ b/drivers/hwmon/pmbus/xdpe152c4.c @@ -63,7 +63,7 @@ static struct i2c_driver xdpe152_driver = { .name = "xdpe152c4", .of_match_table = of_match_ptr(xdpe152_of_match), }, - .probe_new = xdpe152_probe, + .probe = xdpe152_probe, .id_table = xdpe152_id, }; diff --git a/drivers/hwmon/pmbus/zl6100.c b/drivers/hwmon/pmbus/zl6100.c index e9df0c56d91e9ddf8a7053ac15fbb82a9eed4809..83458df0d0cfafd501b92f74121b70c4f56844b1 100644 --- a/drivers/hwmon/pmbus/zl6100.c +++ b/drivers/hwmon/pmbus/zl6100.c @@ -461,7 +461,7 @@ static struct i2c_driver zl6100_driver = { .driver = { .name = "zl6100", }, - .probe_new = zl6100_probe, + .probe = zl6100_probe, .id_table = zl6100_id, }; diff --git a/drivers/hwmon/powr1220.c b/drivers/hwmon/powr1220.c index 9cb0c2de5219314779a62f48577442da0ea33afd..4120cadb00aebc4f8a3629926ca769410e0023b5 100644 --- a/drivers/hwmon/powr1220.c +++ b/drivers/hwmon/powr1220.c @@ -327,7 +327,7 @@ static struct i2c_driver powr1220_driver = { .driver = { .name = "powr1220", }, - .probe_new = powr1220_probe, + .probe = powr1220_probe, .id_table = powr1220_ids, }; diff --git a/drivers/hwmon/sbrmi.c b/drivers/hwmon/sbrmi.c index 529f0e766319be7c47fb86f9f4c3479664ce0e97..484703f0ea5f882e266c096e6920ae79460974a6 100644 --- a/drivers/hwmon/sbrmi.c +++ b/drivers/hwmon/sbrmi.c @@ -347,7 +347,7 @@ static struct i2c_driver sbrmi_driver = { .name = "sbrmi", .of_match_table = of_match_ptr(sbrmi_of_match), }, - .probe_new = sbrmi_probe, + .probe = sbrmi_probe, .id_table = sbrmi_id, }; diff --git a/drivers/hwmon/sbtsi_temp.c b/drivers/hwmon/sbtsi_temp.c index 7049d9464ac6d47da240bf053347ec5e7492d84b..b79cece4ac9aba5e4475a8853ab7191fb87cf91a 100644 --- a/drivers/hwmon/sbtsi_temp.c +++ b/drivers/hwmon/sbtsi_temp.c @@ -238,7 +238,7 @@ static struct i2c_driver sbtsi_driver = { .name = "sbtsi", .of_match_table = of_match_ptr(sbtsi_of_match), }, - .probe_new = sbtsi_probe, + .probe = sbtsi_probe, .id_table = sbtsi_id, }; diff --git a/drivers/hwmon/sht21.c b/drivers/hwmon/sht21.c index f50b90198f2394356c8099d497912a41be3ba7ac..55c1794752085fd537cf5bab5715e7b5acb114cc 100644 --- a/drivers/hwmon/sht21.c +++ b/drivers/hwmon/sht21.c @@ -285,7 +285,7 @@ MODULE_DEVICE_TABLE(i2c, sht21_id); static struct i2c_driver sht21_driver = { .driver.name = "sht21", - .probe_new = sht21_probe, + .probe = sht21_probe, .id_table = sht21_id, }; diff --git a/drivers/hwmon/sht3x.c b/drivers/hwmon/sht3x.c index 8305e44d9ab207780aa29dc47955c6685be75437..bf18630619e0e8308b2e62f37cd9835e67823b96 100644 --- a/drivers/hwmon/sht3x.c +++ b/drivers/hwmon/sht3x.c @@ -20,15 +20,15 @@ #include #include #include -#include -/* commands (high precision mode) */ -static const unsigned char sht3x_cmd_measure_blocking_hpm[] = { 0x2c, 0x06 }; -static const unsigned char sht3x_cmd_measure_nonblocking_hpm[] = { 0x24, 0x00 }; +/* commands (high repeatability mode) */ +static const unsigned char sht3x_cmd_measure_single_hpm[] = { 0x24, 0x00 }; -/* commands (low power mode) */ -static const unsigned char sht3x_cmd_measure_blocking_lpm[] = { 0x2c, 0x10 }; -static const unsigned char sht3x_cmd_measure_nonblocking_lpm[] = { 0x24, 0x16 }; +/* commands (medium repeatability mode) */ +static const unsigned char sht3x_cmd_measure_single_mpm[] = { 0x24, 0x0b }; + +/* commands (low repeatability mode) */ +static const unsigned char sht3x_cmd_measure_single_lpm[] = { 0x24, 0x16 }; /* commands for periodic mode */ static const unsigned char sht3x_cmd_measure_periodic_mode[] = { 0xe0, 0x00 }; @@ -42,9 +42,10 @@ static const unsigned char sht3x_cmd_heater_off[] = { 0x30, 0x66 }; static const unsigned char sht3x_cmd_read_status_reg[] = { 0xf3, 0x2d }; static const unsigned char sht3x_cmd_clear_status_reg[] = { 0x30, 0x41 }; -/* delays for non-blocking i2c commands, both in us */ -#define SHT3X_NONBLOCKING_WAIT_TIME_HPM 15000 -#define SHT3X_NONBLOCKING_WAIT_TIME_LPM 4000 +/* delays for single-shot mode i2c commands, both in us */ +#define SHT3X_SINGLE_WAIT_TIME_HPM 15000 +#define SHT3X_SINGLE_WAIT_TIME_MPM 6000 +#define SHT3X_SINGLE_WAIT_TIME_LPM 4000 #define SHT3X_WORD_LEN 2 #define SHT3X_CMD_LENGTH 2 @@ -69,9 +70,15 @@ enum sht3x_limits { limit_min_hyst, }; +enum sht3x_repeatability { + low_repeatability, + medium_repeatability, + high_repeatability, +}; + DECLARE_CRC8_TABLE(sht3x_crc8_table); -/* periodic measure commands (high precision mode) */ +/* periodic measure commands (high repeatability mode) */ static const char periodic_measure_commands_hpm[][SHT3X_CMD_LENGTH] = { /* 0.5 measurements per second */ {0x20, 0x32}, @@ -85,7 +92,21 @@ static const char periodic_measure_commands_hpm[][SHT3X_CMD_LENGTH] = { {0x27, 0x37}, }; -/* periodic measure commands (low power mode) */ +/* periodic measure commands (medium repeatability) */ +static const char periodic_measure_commands_mpm[][SHT3X_CMD_LENGTH] = { + /* 0.5 measurements per second */ + {0x20, 0x24}, + /* 1 measurements per second */ + {0x21, 0x26}, + /* 2 measurements per second */ + {0x22, 0x20}, + /* 4 measurements per second */ + {0x23, 0x22}, + /* 10 measurements per second */ + {0x27, 0x21}, +}; + +/* periodic measure commands (low repeatability mode) */ static const char periodic_measure_commands_lpm[][SHT3X_CMD_LENGTH] = { /* 0.5 measurements per second */ {0x20, 0x2f}, @@ -135,8 +156,7 @@ struct sht3x_data { const unsigned char *command; u32 wait_time; /* in us*/ unsigned long last_update; /* last update in periodic mode*/ - - struct sht3x_platform_data setup; + enum sht3x_repeatability repeatability; /* * cached values for temperature and humidity and limits @@ -433,26 +453,22 @@ static ssize_t humidity1_limit_store(struct device *dev, static void sht3x_select_command(struct sht3x_data *data) { /* - * In blocking mode (clock stretching mode) the I2C bus - * is blocked for other traffic, thus the call to i2c_master_recv() - * will wait until the data is ready. For non blocking mode, we - * have to wait ourselves. + * For single-shot mode, only non blocking mode is support, + * we have to wait ourselves for result. */ if (data->mode > 0) { data->command = sht3x_cmd_measure_periodic_mode; data->wait_time = 0; - } else if (data->setup.blocking_io) { - data->command = data->setup.high_precision ? - sht3x_cmd_measure_blocking_hpm : - sht3x_cmd_measure_blocking_lpm; - data->wait_time = 0; } else { - if (data->setup.high_precision) { - data->command = sht3x_cmd_measure_nonblocking_hpm; - data->wait_time = SHT3X_NONBLOCKING_WAIT_TIME_HPM; + if (data->repeatability == high_repeatability) { + data->command = sht3x_cmd_measure_single_hpm; + data->wait_time = SHT3X_SINGLE_WAIT_TIME_HPM; + } else if (data->repeatability == medium_repeatability) { + data->command = sht3x_cmd_measure_single_mpm; + data->wait_time = SHT3X_SINGLE_WAIT_TIME_MPM; } else { - data->command = sht3x_cmd_measure_nonblocking_lpm; - data->wait_time = SHT3X_NONBLOCKING_WAIT_TIME_LPM; + data->command = sht3x_cmd_measure_single_lpm; + data->wait_time = SHT3X_SINGLE_WAIT_TIME_LPM; } } } @@ -595,8 +611,10 @@ static ssize_t update_interval_store(struct device *dev, } if (mode > 0) { - if (data->setup.high_precision) + if (data->repeatability == high_repeatability) command = periodic_measure_commands_hpm[mode - 1]; + else if (data->repeatability == medium_repeatability) + command = periodic_measure_commands_mpm[mode - 1]; else command = periodic_measure_commands_lpm[mode - 1]; @@ -619,6 +637,37 @@ static ssize_t update_interval_store(struct device *dev, return count; } +static ssize_t repeatability_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct sht3x_data *data = dev_get_drvdata(dev); + + return sysfs_emit(buf, "%d\n", data->repeatability); +} + +static ssize_t repeatability_store(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t count) +{ + int ret; + u8 val; + + struct sht3x_data *data = dev_get_drvdata(dev); + + ret = kstrtou8(buf, 0, &val); + if (ret) + return ret; + + if (val > 2) + return -EINVAL; + + data->repeatability = val; + + return count; +} + static SENSOR_DEVICE_ATTR_RO(temp1_input, temp1_input, 0); static SENSOR_DEVICE_ATTR_RO(humidity1_input, humidity1_input, 0); static SENSOR_DEVICE_ATTR_RW(temp1_max, temp1_limit, limit_max); @@ -635,6 +684,7 @@ static SENSOR_DEVICE_ATTR_RO(temp1_alarm, temp1_alarm, 0); static SENSOR_DEVICE_ATTR_RO(humidity1_alarm, humidity1_alarm, 0); static SENSOR_DEVICE_ATTR_RW(heater_enable, heater_enable, 0); static SENSOR_DEVICE_ATTR_RW(update_interval, update_interval, 0); +static SENSOR_DEVICE_ATTR_RW(repeatability, repeatability, 0); static struct attribute *sht3x_attrs[] = { &sensor_dev_attr_temp1_input.dev_attr.attr, @@ -651,11 +701,20 @@ static struct attribute *sht3x_attrs[] = { &sensor_dev_attr_humidity1_alarm.dev_attr.attr, &sensor_dev_attr_heater_enable.dev_attr.attr, &sensor_dev_attr_update_interval.dev_attr.attr, + &sensor_dev_attr_repeatability.dev_attr.attr, NULL }; static struct attribute *sts3x_attrs[] = { &sensor_dev_attr_temp1_input.dev_attr.attr, + &sensor_dev_attr_temp1_max.dev_attr.attr, + &sensor_dev_attr_temp1_max_hyst.dev_attr.attr, + &sensor_dev_attr_temp1_min.dev_attr.attr, + &sensor_dev_attr_temp1_min_hyst.dev_attr.attr, + &sensor_dev_attr_temp1_alarm.dev_attr.attr, + &sensor_dev_attr_heater_enable.dev_attr.attr, + &sensor_dev_attr_update_interval.dev_attr.attr, + &sensor_dev_attr_repeatability.dev_attr.attr, NULL }; @@ -690,16 +749,12 @@ static int sht3x_probe(struct i2c_client *client) if (!data) return -ENOMEM; - data->setup.blocking_io = false; - data->setup.high_precision = true; + data->repeatability = high_repeatability; data->mode = 0; data->last_update = jiffies - msecs_to_jiffies(3000); data->client = client; crc8_populate_msb(sht3x_crc8_table, SHT3X_CRC8_POLYNOMIAL); - if (client->dev.platform_data) - data->setup = *(struct sht3x_platform_data *)dev->platform_data; - sht3x_select_command(data); mutex_init(&data->i2c_lock); @@ -743,7 +798,7 @@ MODULE_DEVICE_TABLE(i2c, sht3x_ids); static struct i2c_driver sht3x_i2c_driver = { .driver.name = "sht3x", - .probe_new = sht3x_probe, + .probe = sht3x_probe, .id_table = sht3x_ids, }; diff --git a/drivers/hwmon/sht4x.c b/drivers/hwmon/sht4x.c index 5bbe09135ab9d8b432151c616c0263ef376b6128..7ee7974104580c5bc0b6c2659f557149d8842dbf 100644 --- a/drivers/hwmon/sht4x.c +++ b/drivers/hwmon/sht4x.c @@ -291,7 +291,7 @@ static struct i2c_driver sht4x_driver = { .name = "sht4x", .of_match_table = sht4x_of_match, }, - .probe_new = sht4x_probe, + .probe = sht4x_probe, .id_table = sht4x_id, }; diff --git a/drivers/hwmon/shtc1.c b/drivers/hwmon/shtc1.c index 18546ebc8e9f7710edba6c782f6cfc02ff650699..1f96e94967ee8db09371860519d98a65ed022d7a 100644 --- a/drivers/hwmon/shtc1.c +++ b/drivers/hwmon/shtc1.c @@ -279,7 +279,7 @@ static struct i2c_driver shtc1_i2c_driver = { .name = "shtc1", .of_match_table = shtc1_of_match, }, - .probe_new = shtc1_probe, + .probe = shtc1_probe, .id_table = shtc1_id, }; diff --git a/drivers/hwmon/smm665.c b/drivers/hwmon/smm665.c index c36bdbe423de001223263bcd2c7dab5cdbdf14ad..026c76f8c22e806b29d64478fa0b1ef1a47b5207 100644 --- a/drivers/hwmon/smm665.c +++ b/drivers/hwmon/smm665.c @@ -694,7 +694,7 @@ static struct i2c_driver smm665_driver = { .driver = { .name = "smm665", }, - .probe_new = smm665_probe, + .probe = smm665_probe, .remove = smm665_remove, .id_table = smm665_id, }; diff --git a/drivers/hwmon/smsc47m192.c b/drivers/hwmon/smsc47m192.c index 70d2152234e210700cbe32b67f767d43dd631b77..d20800a1f02bc8a4573a933d31e83dd5a9f1aa39 100644 --- a/drivers/hwmon/smsc47m192.c +++ b/drivers/hwmon/smsc47m192.c @@ -628,7 +628,7 @@ static struct i2c_driver smsc47m192_driver = { .driver = { .name = "smsc47m192", }, - .probe_new = smsc47m192_probe, + .probe = smsc47m192_probe, .id_table = smsc47m192_id, .detect = smsc47m192_detect, .address_list = normal_i2c, diff --git a/drivers/hwmon/stts751.c b/drivers/hwmon/stts751.c index 2f67c6747eadbf4f80a029c77dcf1ef1a57f06e5..847c99376930742143261fdbed44b9eeddacf228 100644 --- a/drivers/hwmon/stts751.c +++ b/drivers/hwmon/stts751.c @@ -821,7 +821,7 @@ static struct i2c_driver stts751_driver = { .name = DEVNAME, .of_match_table = of_match_ptr(stts751_of_match), }, - .probe_new = stts751_probe, + .probe = stts751_probe, .id_table = stts751_id, .detect = stts751_detect, .alert = stts751_alert, diff --git a/drivers/hwmon/tc654.c b/drivers/hwmon/tc654.c index 54cd33d096884499265f6e2892d197d4e77d64cc..42a9658f1bc2b79bdae577ea46d466ebbc85a17c 100644 --- a/drivers/hwmon/tc654.c +++ b/drivers/hwmon/tc654.c @@ -561,7 +561,7 @@ static struct i2c_driver tc654_driver = { .driver = { .name = "tc654", }, - .probe_new = tc654_probe, + .probe = tc654_probe, .id_table = tc654_id, }; diff --git a/drivers/hwmon/tc74.c b/drivers/hwmon/tc74.c index ace55da97fc29f717dc2eef9055196d9a9f41e0a..03950670bd782272e8157f809f399e3a9242e6c2 100644 --- a/drivers/hwmon/tc74.c +++ b/drivers/hwmon/tc74.c @@ -160,7 +160,7 @@ static struct i2c_driver tc74_driver = { .driver = { .name = "tc74", }, - .probe_new = tc74_probe, + .probe = tc74_probe, .id_table = tc74_id, }; diff --git a/drivers/hwmon/thmc50.c b/drivers/hwmon/thmc50.c index 81cdb012993caca0ce4072e9aa7043bad390ea81..68ba26bc90142e110ed9952c5d6318f368c8e23b 100644 --- a/drivers/hwmon/thmc50.c +++ b/drivers/hwmon/thmc50.c @@ -420,7 +420,7 @@ static struct i2c_driver thmc50_driver = { .driver = { .name = "thmc50", }, - .probe_new = thmc50_probe, + .probe = thmc50_probe, .id_table = thmc50_id, .detect = thmc50_detect, .address_list = normal_i2c, diff --git a/drivers/hwmon/tmp102.c b/drivers/hwmon/tmp102.c index e271556efe0b86ece8b71c064953588f49569d36..2506c78590afe3729d0245617ce34aca1cf214d2 100644 --- a/drivers/hwmon/tmp102.c +++ b/drivers/hwmon/tmp102.c @@ -184,7 +184,7 @@ static const struct regmap_config tmp102_regmap_config = { .writeable_reg = tmp102_is_writeable_reg, .volatile_reg = tmp102_is_volatile_reg, .val_format_endian = REGMAP_ENDIAN_BIG, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, .use_single_read = true, .use_single_write = true, }; @@ -301,7 +301,7 @@ static struct i2c_driver tmp102_driver = { .driver.name = DRIVER_NAME, .driver.of_match_table = of_match_ptr(tmp102_of_match), .driver.pm = pm_sleep_ptr(&tmp102_dev_pm_ops), - .probe_new = tmp102_probe, + .probe = tmp102_probe, .id_table = tmp102_id, }; diff --git a/drivers/hwmon/tmp103.c b/drivers/hwmon/tmp103.c index d257bb91fc6954c456f4fdbb0fe50e4cf9aac79a..a84c29a3a765a78887e10ecaab9088355a6d0679 100644 --- a/drivers/hwmon/tmp103.c +++ b/drivers/hwmon/tmp103.c @@ -214,7 +214,7 @@ static struct i2c_driver tmp103_driver = { .of_match_table = of_match_ptr(tmp103_of_match), .pm = pm_sleep_ptr(&tmp103_dev_pm_ops), }, - .probe_new = tmp103_probe, + .probe = tmp103_probe, .id_table = tmp103_id, }; diff --git a/drivers/hwmon/tmp108.c b/drivers/hwmon/tmp108.c index 43784c289a9e9418c57cd801a81e043fbb9ec968..d7a09ab2bc11224b027eee0a33c032e23bd8657f 100644 --- a/drivers/hwmon/tmp108.c +++ b/drivers/hwmon/tmp108.c @@ -318,7 +318,7 @@ static const struct regmap_config tmp108_regmap_config = { .writeable_reg = tmp108_is_writeable_reg, .volatile_reg = tmp108_is_volatile_reg, .val_format_endian = REGMAP_ENDIAN_BIG, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, .use_single_read = true, .use_single_write = true, }; @@ -432,7 +432,7 @@ static struct i2c_driver tmp108_driver = { .pm = pm_sleep_ptr(&tmp108_dev_pm_ops), .of_match_table = of_match_ptr(tmp108_of_ids), }, - .probe_new = tmp108_probe, + .probe = tmp108_probe, .id_table = tmp108_i2c_ids, }; diff --git a/drivers/hwmon/tmp401.c b/drivers/hwmon/tmp401.c index f358ba67962675352fae9cfa3daa024dac4b8453..91f2314568cfaf6342552f57c24d6a9647aff727 100644 --- a/drivers/hwmon/tmp401.c +++ b/drivers/hwmon/tmp401.c @@ -766,7 +766,7 @@ static struct i2c_driver tmp401_driver = { .name = "tmp401", .of_match_table = of_match_ptr(tmp4xx_of_match), }, - .probe_new = tmp401_probe, + .probe = tmp401_probe, .id_table = tmp401_id, .detect = tmp401_detect, .address_list = normal_i2c, diff --git a/drivers/hwmon/tmp421.c b/drivers/hwmon/tmp421.c index 45fd7fb5ee01f5c688d5b80d8922ef0353de0e9b..3cde3916ab6d5d5b49dc62172d4cc738526004e7 100644 --- a/drivers/hwmon/tmp421.c +++ b/drivers/hwmon/tmp421.c @@ -487,7 +487,7 @@ static struct i2c_driver tmp421_driver = { .name = "tmp421", .of_match_table = of_match_ptr(tmp421_of_match), }, - .probe_new = tmp421_probe, + .probe = tmp421_probe, .id_table = tmp421_id, .detect = tmp421_detect, .address_list = normal_i2c, diff --git a/drivers/hwmon/tmp464.c b/drivers/hwmon/tmp464.c index 9213a493a590a58957f240b251f777770653a739..4b79c3f4d9fe4aafc520495b25a283253b2dec25 100644 --- a/drivers/hwmon/tmp464.c +++ b/drivers/hwmon/tmp464.c @@ -644,7 +644,7 @@ static const struct regmap_config tmp464_regmap_config = { .max_register = TMP464_DEVICE_ID_REG, .volatile_reg = tmp464_is_volatile_reg, .val_format_endian = REGMAP_ENDIAN_BIG, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, .use_single_read = true, .use_single_write = true, }; @@ -699,7 +699,7 @@ static struct i2c_driver tmp464_driver = { .name = "tmp464", .of_match_table = of_match_ptr(tmp464_of_match), }, - .probe_new = tmp464_probe, + .probe = tmp464_probe, .id_table = tmp464_id, .detect = tmp464_detect, .address_list = normal_i2c, diff --git a/drivers/hwmon/tmp513.c b/drivers/hwmon/tmp513.c index 0693eaee054ffe90fd70e47c577c51c770e69161..bff10f4b56e199928768adf8b0226ac02c288dc8 100644 --- a/drivers/hwmon/tmp513.c +++ b/drivers/hwmon/tmp513.c @@ -760,7 +760,7 @@ static struct i2c_driver tmp51x_driver = { .name = "tmp51x", .of_match_table = tmp51x_of_match, }, - .probe_new = tmp51x_probe, + .probe = tmp51x_probe, .id_table = tmp51x_id, }; diff --git a/drivers/hwmon/tps23861.c b/drivers/hwmon/tps23861.c index 85a75f55114893ec0743094bbbb239f584bc479c..8fbbb29ae11d2e74f38e18ebd23584798575e3e6 100644 --- a/drivers/hwmon/tps23861.c +++ b/drivers/hwmon/tps23861.c @@ -581,7 +581,7 @@ static const struct of_device_id __maybe_unused tps23861_of_match[] = { MODULE_DEVICE_TABLE(of, tps23861_of_match); static struct i2c_driver tps23861_driver = { - .probe_new = tps23861_probe, + .probe = tps23861_probe, .remove = tps23861_remove, .driver = { .name = "tps23861", diff --git a/drivers/hwmon/w83773g.c b/drivers/hwmon/w83773g.c index 8dbcd05abd9ad219b74273c4ee77926199e30173..7f3615f5587cc3c2ae19c00603cb9c72aba73956 100644 --- a/drivers/hwmon/w83773g.c +++ b/drivers/hwmon/w83773g.c @@ -295,7 +295,7 @@ static struct i2c_driver w83773_driver = { .name = "w83773g", .of_match_table = of_match_ptr(w83773_of_match), }, - .probe_new = w83773_probe, + .probe = w83773_probe, .id_table = w83773_id, }; diff --git a/drivers/hwmon/w83781d.c b/drivers/hwmon/w83781d.c index dacabf25e83ff6e7df9e2b35211f15ecd4f53ead..b33f382f238ddd8c74301ed10d39fee7e3e21766 100644 --- a/drivers/hwmon/w83781d.c +++ b/drivers/hwmon/w83781d.c @@ -1585,7 +1585,7 @@ static struct i2c_driver w83781d_driver = { .name = "w83781d", .of_match_table = w83781d_of_match, }, - .probe_new = w83781d_probe, + .probe = w83781d_probe, .remove = w83781d_remove, .id_table = w83781d_ids, .detect = w83781d_detect, diff --git a/drivers/hwmon/w83791d.c b/drivers/hwmon/w83791d.c index eaf6913650231c4f078ccef4f9e7fe4aac3ca324..9681eaa06c8e084522f108f8cc760a8614272689 100644 --- a/drivers/hwmon/w83791d.c +++ b/drivers/hwmon/w83791d.c @@ -338,7 +338,7 @@ static struct i2c_driver w83791d_driver = { .driver = { .name = "w83791d", }, - .probe_new = w83791d_probe, + .probe = w83791d_probe, .remove = w83791d_remove, .id_table = w83791d_id, .detect = w83791d_detect, diff --git a/drivers/hwmon/w83792d.c b/drivers/hwmon/w83792d.c index 6d160eee1446077ea07b47433df477e4afba3985..69ce379a9e1311c33752d94c3ea4f9a62bf71498 100644 --- a/drivers/hwmon/w83792d.c +++ b/drivers/hwmon/w83792d.c @@ -306,7 +306,7 @@ static struct i2c_driver w83792d_driver = { .driver = { .name = "w83792d", }, - .probe_new = w83792d_probe, + .probe = w83792d_probe, .remove = w83792d_remove, .id_table = w83792d_id, .detect = w83792d_detect, diff --git a/drivers/hwmon/w83793.c b/drivers/hwmon/w83793.c index a4926d907198c2cbc234531344e8507efedb4246..96bab94ba8996bf857fcc4dbcd406c600b079e31 100644 --- a/drivers/hwmon/w83793.c +++ b/drivers/hwmon/w83793.c @@ -301,7 +301,7 @@ static struct i2c_driver w83793_driver = { .driver = { .name = "w83793", }, - .probe_new = w83793_probe, + .probe = w83793_probe, .remove = w83793_remove, .id_table = w83793_id, .detect = w83793_detect, diff --git a/drivers/hwmon/w83795.c b/drivers/hwmon/w83795.c index 84ff5c57e98c28eab2cbeebc37756057d9d6ebd7..c446e00db65860f0025cc7136f41418d563d9c8d 100644 --- a/drivers/hwmon/w83795.c +++ b/drivers/hwmon/w83795.c @@ -2255,7 +2255,7 @@ static struct i2c_driver w83795_driver = { .driver = { .name = "w83795", }, - .probe_new = w83795_probe, + .probe = w83795_probe, .remove = w83795_remove, .id_table = w83795_id, diff --git a/drivers/hwmon/w83l785ts.c b/drivers/hwmon/w83l785ts.c index f3622de0d96fe224bf5c7376efd9dc31cfb0a4a7..9c11ed69c055ba22d130dc0ca357d4a8d88a8fb1 100644 --- a/drivers/hwmon/w83l785ts.c +++ b/drivers/hwmon/w83l785ts.c @@ -84,7 +84,7 @@ static struct i2c_driver w83l785ts_driver = { .driver = { .name = "w83l785ts", }, - .probe_new = w83l785ts_probe, + .probe = w83l785ts_probe, .remove = w83l785ts_remove, .id_table = w83l785ts_id, .detect = w83l785ts_detect, diff --git a/drivers/hwmon/w83l786ng.c b/drivers/hwmon/w83l786ng.c index 5597e1c2d95cf3c1651ccbc57215011a02e3f175..75874cf7851cb34365a90ea5b11d7733dc2e9403 100644 --- a/drivers/hwmon/w83l786ng.c +++ b/drivers/hwmon/w83l786ng.c @@ -751,7 +751,7 @@ static struct i2c_driver w83l786ng_driver = { .driver = { .name = "w83l786ng", }, - .probe_new = w83l786ng_probe, + .probe = w83l786ng_probe, .id_table = w83l786ng_id, .detect = w83l786ng_detect, .address_list = normal_i2c, diff --git a/drivers/hwspinlock/omap_hwspinlock.c b/drivers/hwspinlock/omap_hwspinlock.c index 1fb3a2550e2929c46b9394fff5a1a42509249aa0..dfe82952671b1584ade4c48c6864352fd211e468 100644 --- a/drivers/hwspinlock/omap_hwspinlock.c +++ b/drivers/hwspinlock/omap_hwspinlock.c @@ -174,7 +174,7 @@ static struct platform_driver omap_hwspinlock_driver = { .remove = omap_hwspinlock_remove, .driver = { .name = "omap_hwspinlock", - .of_match_table = of_match_ptr(omap_hwspinlock_of_match), + .of_match_table = omap_hwspinlock_of_match, }, }; diff --git a/drivers/hwtracing/coresight/Kconfig b/drivers/hwtracing/coresight/Kconfig index 2b5bbfffbc4f64b8671df6579e624b9abbc5c12f..06f0a7594169c5f03ca5f893b7debd294587de78 100644 --- a/drivers/hwtracing/coresight/Kconfig +++ b/drivers/hwtracing/coresight/Kconfig @@ -236,4 +236,15 @@ config CORESIGHT_TPDA To compile this driver as a module, choose M here: the module will be called coresight-tpda. + +config CORESIGHT_DUMMY + tristate "Dummy driver support" + help + Enables support for dummy driver. Dummy driver can be used for + CoreSight sources/sinks that are owned and configured by some + other subsystem and use Linux drivers to configure rest of trace + path. + + To compile this driver as a module, choose M here: the module will be + called coresight-dummy. endif diff --git a/drivers/hwtracing/coresight/Makefile b/drivers/hwtracing/coresight/Makefile index 33bcc3f7b8aef6385874ab972bbab5dbda7cc961..995d3b2c76df2d08c9ae26e7c5747621f71ac278 100644 --- a/drivers/hwtracing/coresight/Makefile +++ b/drivers/hwtracing/coresight/Makefile @@ -30,3 +30,4 @@ obj-$(CONFIG_CORESIGHT_TPDA) += coresight-tpda.o coresight-cti-y := coresight-cti-core.o coresight-cti-platform.o \ coresight-cti-sysfs.o obj-$(CONFIG_ULTRASOC_SMB) += ultrasoc-smb.o +obj-$(CONFIG_CORESIGHT_DUMMY) += coresight-dummy.o diff --git a/drivers/hwtracing/coresight/coresight-catu.c b/drivers/hwtracing/coresight/coresight-catu.c index bc90a03f478fd0364335ddadd32299ac23da7efe..3949ded0d4fa590b3422b109f9fa80346dcccb51 100644 --- a/drivers/hwtracing/coresight/coresight-catu.c +++ b/drivers/hwtracing/coresight/coresight-catu.c @@ -395,13 +395,18 @@ static inline int catu_wait_for_ready(struct catu_drvdata *drvdata) return coresight_timeout(csa, CATU_STATUS, CATU_STATUS_READY, 1); } -static int catu_enable_hw(struct catu_drvdata *drvdata, void *data) +static int catu_enable_hw(struct catu_drvdata *drvdata, enum cs_mode cs_mode, + void *data) { int rc; u32 control, mode; - struct etr_buf *etr_buf = data; + struct etr_buf *etr_buf = NULL; struct device *dev = &drvdata->csdev->dev; struct coresight_device *csdev = drvdata->csdev; + struct coresight_device *etrdev; + union coresight_dev_subtype etr_subtype = { + .sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_SYSMEM + }; if (catu_wait_for_ready(drvdata)) dev_warn(dev, "Timeout while waiting for READY\n"); @@ -416,6 +421,13 @@ static int catu_enable_hw(struct catu_drvdata *drvdata, void *data) if (rc) return rc; + etrdev = coresight_find_input_type( + csdev->pdata, CORESIGHT_DEV_TYPE_SINK, etr_subtype); + if (etrdev) { + etr_buf = tmc_etr_get_buffer(etrdev, cs_mode, data); + if (IS_ERR(etr_buf)) + return PTR_ERR(etr_buf); + } control |= BIT(CATU_CONTROL_ENABLE); if (etr_buf && etr_buf->mode == ETR_MODE_CATU) { @@ -441,13 +453,14 @@ static int catu_enable_hw(struct catu_drvdata *drvdata, void *data) return 0; } -static int catu_enable(struct coresight_device *csdev, void *data) +static int catu_enable(struct coresight_device *csdev, enum cs_mode mode, + void *data) { int rc; struct catu_drvdata *catu_drvdata = csdev_to_catu_drvdata(csdev); CS_UNLOCK(catu_drvdata->base); - rc = catu_enable_hw(catu_drvdata, data); + rc = catu_enable_hw(catu_drvdata, mode, data); CS_LOCK(catu_drvdata->base); return rc; } diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c index d3bf82c0de1d87c8bcfee30d35e4c0331812dc1c..118fcf27854d5e59561d89d0e4f3ce3286f292ab 100644 --- a/drivers/hwtracing/coresight/coresight-core.c +++ b/drivers/hwtracing/coresight/coresight-core.c @@ -3,6 +3,7 @@ * Copyright (c) 2012, The Linux Foundation. All rights reserved. */ +#include #include #include #include @@ -112,40 +113,24 @@ struct coresight_device *coresight_get_percpu_sink(int cpu) } EXPORT_SYMBOL_GPL(coresight_get_percpu_sink); -static int coresight_find_link_inport(struct coresight_device *csdev, - struct coresight_device *parent) +static struct coresight_connection * +coresight_find_out_connection(struct coresight_device *src_dev, + struct coresight_device *dest_dev) { int i; struct coresight_connection *conn; - for (i = 0; i < parent->pdata->nr_outport; i++) { - conn = &parent->pdata->conns[i]; - if (conn->child_dev == csdev) - return conn->child_port; + for (i = 0; i < src_dev->pdata->nr_outconns; i++) { + conn = src_dev->pdata->out_conns[i]; + if (conn->dest_dev == dest_dev) + return conn; } - dev_err(&csdev->dev, "couldn't find inport, parent: %s, child: %s\n", - dev_name(&parent->dev), dev_name(&csdev->dev)); + dev_err(&src_dev->dev, + "couldn't find output connection, src_dev: %s, dest_dev: %s\n", + dev_name(&src_dev->dev), dev_name(&dest_dev->dev)); - return -ENODEV; -} - -static int coresight_find_link_outport(struct coresight_device *csdev, - struct coresight_device *child) -{ - int i; - struct coresight_connection *conn; - - for (i = 0; i < csdev->pdata->nr_outport; i++) { - conn = &csdev->pdata->conns[i]; - if (conn->child_dev == child) - return conn->outport; - } - - dev_err(&csdev->dev, "couldn't find outport, parent: %s, child: %s\n", - dev_name(&csdev->dev), dev_name(&child->dev)); - - return -ENODEV; + return ERR_PTR(-ENODEV); } static inline u32 coresight_read_claim_tags(struct coresight_device *csdev) @@ -252,63 +237,47 @@ void coresight_disclaim_device(struct coresight_device *csdev) } EXPORT_SYMBOL_GPL(coresight_disclaim_device); -/* enable or disable an associated CTI device of the supplied CS device */ -static int -coresight_control_assoc_ectdev(struct coresight_device *csdev, bool enable) +/* + * Add a helper as an output device. This function takes the @coresight_mutex + * because it's assumed that it's called from the helper device, outside of the + * core code where the mutex would already be held. Don't add new calls to this + * from inside the core code, instead try to add the new helper to the DT and + * ACPI where it will be picked up and linked automatically. + */ +void coresight_add_helper(struct coresight_device *csdev, + struct coresight_device *helper) { - int ect_ret = 0; - struct coresight_device *ect_csdev = csdev->ect_dev; - struct module *mod; + int i; + struct coresight_connection conn = {}; + struct coresight_connection *new_conn; - if (!ect_csdev) - return 0; - if ((!ect_ops(ect_csdev)->enable) || (!ect_ops(ect_csdev)->disable)) - return 0; + mutex_lock(&coresight_mutex); + conn.dest_fwnode = fwnode_handle_get(dev_fwnode(&helper->dev)); + conn.dest_dev = helper; + conn.dest_port = conn.src_port = -1; + conn.src_dev = csdev; - mod = ect_csdev->dev.parent->driver->owner; - if (enable) { - if (try_module_get(mod)) { - ect_ret = ect_ops(ect_csdev)->enable(ect_csdev); - if (ect_ret) { - module_put(mod); - } else { - get_device(ect_csdev->dev.parent); - csdev->ect_enabled = true; - } - } else - ect_ret = -ENODEV; - } else { - if (csdev->ect_enabled) { - ect_ret = ect_ops(ect_csdev)->disable(ect_csdev); - put_device(ect_csdev->dev.parent); - module_put(mod); - csdev->ect_enabled = false; - } - } + /* + * Check for duplicates because this is called every time a helper + * device is re-loaded. Existing connections will get re-linked + * automatically. + */ + for (i = 0; i < csdev->pdata->nr_outconns; ++i) + if (csdev->pdata->out_conns[i]->dest_fwnode == conn.dest_fwnode) + goto unlock; - /* output warning if ECT enable is preventing trace operation */ - if (ect_ret) - dev_info(&csdev->dev, "Associated ECT device (%s) %s failed\n", - dev_name(&ect_csdev->dev), - enable ? "enable" : "disable"); - return ect_ret; -} + new_conn = coresight_add_out_conn(csdev->dev.parent, csdev->pdata, + &conn); + if (!IS_ERR(new_conn)) + coresight_add_in_conn(new_conn); -/* - * Set the associated ect / cti device while holding the coresight_mutex - * to avoid a race with coresight_enable that may try to use this value. - */ -void coresight_set_assoc_ectdev_mutex(struct coresight_device *csdev, - struct coresight_device *ect_csdev) -{ - mutex_lock(&coresight_mutex); - csdev->ect_dev = ect_csdev; +unlock: mutex_unlock(&coresight_mutex); } -EXPORT_SYMBOL_GPL(coresight_set_assoc_ectdev_mutex); +EXPORT_SYMBOL_GPL(coresight_add_helper); static int coresight_enable_sink(struct coresight_device *csdev, - u32 mode, void *data) + enum cs_mode mode, void *data) { int ret; @@ -319,14 +288,10 @@ static int coresight_enable_sink(struct coresight_device *csdev, if (!sink_ops(csdev)->enable) return -EINVAL; - ret = coresight_control_assoc_ectdev(csdev, true); - if (ret) - return ret; ret = sink_ops(csdev)->enable(csdev, mode, data); - if (ret) { - coresight_control_assoc_ectdev(csdev, false); + if (ret) return ret; - } + csdev->enable = true; return 0; @@ -342,7 +307,6 @@ static void coresight_disable_sink(struct coresight_device *csdev) ret = sink_ops(csdev)->disable(csdev); if (ret) return; - coresight_control_assoc_ectdev(csdev, false); csdev->enable = false; } @@ -352,32 +316,26 @@ static int coresight_enable_link(struct coresight_device *csdev, { int ret = 0; int link_subtype; - int inport, outport; + struct coresight_connection *inconn, *outconn; if (!parent || !child) return -EINVAL; - inport = coresight_find_link_inport(csdev, parent); - outport = coresight_find_link_outport(csdev, child); + inconn = coresight_find_out_connection(parent, csdev); + outconn = coresight_find_out_connection(csdev, child); link_subtype = csdev->subtype.link_subtype; - if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_MERG && inport < 0) - return inport; - if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_SPLIT && outport < 0) - return outport; + if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_MERG && IS_ERR(inconn)) + return PTR_ERR(inconn); + if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_SPLIT && IS_ERR(outconn)) + return PTR_ERR(outconn); if (link_ops(csdev)->enable) { - ret = coresight_control_assoc_ectdev(csdev, true); - if (!ret) { - ret = link_ops(csdev)->enable(csdev, inport, outport); - if (ret) - coresight_control_assoc_ectdev(csdev, false); - } + ret = link_ops(csdev)->enable(csdev, inconn, outconn); + if (!ret) + csdev->enable = true; } - if (!ret) - csdev->enable = true; - return ret; } @@ -385,78 +343,125 @@ static void coresight_disable_link(struct coresight_device *csdev, struct coresight_device *parent, struct coresight_device *child) { - int i, nr_conns; + int i; int link_subtype; - int inport, outport; + struct coresight_connection *inconn, *outconn; if (!parent || !child) return; - inport = coresight_find_link_inport(csdev, parent); - outport = coresight_find_link_outport(csdev, child); + inconn = coresight_find_out_connection(parent, csdev); + outconn = coresight_find_out_connection(csdev, child); link_subtype = csdev->subtype.link_subtype; - if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_MERG) { - nr_conns = csdev->pdata->nr_inport; - } else if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_SPLIT) { - nr_conns = csdev->pdata->nr_outport; - } else { - nr_conns = 1; - } - if (link_ops(csdev)->disable) { - link_ops(csdev)->disable(csdev, inport, outport); - coresight_control_assoc_ectdev(csdev, false); + link_ops(csdev)->disable(csdev, inconn, outconn); } - for (i = 0; i < nr_conns; i++) - if (atomic_read(&csdev->refcnt[i]) != 0) + if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_MERG) { + for (i = 0; i < csdev->pdata->nr_inconns; i++) + if (atomic_read(&csdev->pdata->in_conns[i]->dest_refcnt) != + 0) + return; + } else if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_SPLIT) { + for (i = 0; i < csdev->pdata->nr_outconns; i++) + if (atomic_read(&csdev->pdata->out_conns[i]->src_refcnt) != + 0) + return; + } else { + if (atomic_read(&csdev->refcnt) != 0) return; + } csdev->enable = false; } -static int coresight_enable_source(struct coresight_device *csdev, u32 mode) +int coresight_enable_source(struct coresight_device *csdev, enum cs_mode mode, + void *data) { int ret; if (!csdev->enable) { if (source_ops(csdev)->enable) { - ret = coresight_control_assoc_ectdev(csdev, true); + ret = source_ops(csdev)->enable(csdev, data, mode); if (ret) return ret; - ret = source_ops(csdev)->enable(csdev, NULL, mode); - if (ret) { - coresight_control_assoc_ectdev(csdev, false); - return ret; - } } csdev->enable = true; } - atomic_inc(csdev->refcnt); + atomic_inc(&csdev->refcnt); + + return 0; +} +EXPORT_SYMBOL_GPL(coresight_enable_source); + +static bool coresight_is_helper(struct coresight_device *csdev) +{ + return csdev->type == CORESIGHT_DEV_TYPE_HELPER; +} + +static int coresight_enable_helper(struct coresight_device *csdev, + enum cs_mode mode, void *data) +{ + int ret; + + if (!helper_ops(csdev)->enable) + return 0; + ret = helper_ops(csdev)->enable(csdev, mode, data); + if (ret) + return ret; + csdev->enable = true; return 0; } +static void coresight_disable_helper(struct coresight_device *csdev) +{ + int ret; + + if (!helper_ops(csdev)->disable) + return; + + ret = helper_ops(csdev)->disable(csdev, NULL); + if (ret) + return; + csdev->enable = false; +} + +static void coresight_disable_helpers(struct coresight_device *csdev) +{ + int i; + struct coresight_device *helper; + + for (i = 0; i < csdev->pdata->nr_outconns; ++i) { + helper = csdev->pdata->out_conns[i]->dest_dev; + if (helper && coresight_is_helper(helper)) + coresight_disable_helper(helper); + } +} + /** * coresight_disable_source - Drop the reference count by 1 and disable * the device if there are no users left. * * @csdev: The coresight device to disable + * @data: Opaque data to pass on to the disable function of the source device. + * For example in perf mode this is a pointer to the struct perf_event. * * Returns true if the device has been disabled. */ -static bool coresight_disable_source(struct coresight_device *csdev) +bool coresight_disable_source(struct coresight_device *csdev, void *data) { - if (atomic_dec_return(csdev->refcnt) == 0) { + if (atomic_dec_return(&csdev->refcnt) == 0) { if (source_ops(csdev)->disable) - source_ops(csdev)->disable(csdev, NULL); - coresight_control_assoc_ectdev(csdev, false); + source_ops(csdev)->disable(csdev, data); + coresight_disable_helpers(csdev); csdev->enable = false; } return !csdev->enable; } +EXPORT_SYMBOL_GPL(coresight_disable_source); /* * coresight_disable_path_from : Disable components in the given path beyond @@ -507,6 +512,9 @@ static void coresight_disable_path_from(struct list_head *path, default: break; } + + /* Disable all helpers adjacent along the path last */ + coresight_disable_helpers(csdev); } } @@ -516,9 +524,28 @@ void coresight_disable_path(struct list_head *path) } EXPORT_SYMBOL_GPL(coresight_disable_path); -int coresight_enable_path(struct list_head *path, u32 mode, void *sink_data) +static int coresight_enable_helpers(struct coresight_device *csdev, + enum cs_mode mode, void *data) { + int i, ret = 0; + struct coresight_device *helper; + for (i = 0; i < csdev->pdata->nr_outconns; ++i) { + helper = csdev->pdata->out_conns[i]->dest_dev; + if (!helper || !coresight_is_helper(helper)) + continue; + + ret = coresight_enable_helper(helper, mode, data); + if (ret) + return ret; + } + + return 0; +} + +int coresight_enable_path(struct list_head *path, enum cs_mode mode, + void *sink_data) +{ int ret = 0; u32 type; struct coresight_node *nd; @@ -528,6 +555,10 @@ int coresight_enable_path(struct list_head *path, u32 mode, void *sink_data) csdev = nd->csdev; type = csdev->type; + /* Enable all helpers adjacent to the path first */ + ret = coresight_enable_helpers(csdev, mode, sink_data); + if (ret) + goto err; /* * ETF devices are tricky... They can be a link or a sink, * depending on how they are configured. If an ETF has been @@ -602,10 +633,10 @@ coresight_find_enabled_sink(struct coresight_device *csdev) /* * Recursively explore each port found on this element. */ - for (i = 0; i < csdev->pdata->nr_outport; i++) { + for (i = 0; i < csdev->pdata->nr_outconns; i++) { struct coresight_device *child_dev; - child_dev = csdev->pdata->conns[i].child_dev; + child_dev = csdev->pdata->out_conns[i]->dest_dev; if (child_dev) sink = coresight_find_enabled_sink(child_dev); if (sink) @@ -718,11 +749,11 @@ static int coresight_grab_device(struct coresight_device *csdev) { int i; - for (i = 0; i < csdev->pdata->nr_outport; i++) { + for (i = 0; i < csdev->pdata->nr_outconns; i++) { struct coresight_device *child; - child = csdev->pdata->conns[i].child_dev; - if (child && child->type == CORESIGHT_DEV_TYPE_HELPER) + child = csdev->pdata->out_conns[i]->dest_dev; + if (child && coresight_is_helper(child)) if (!coresight_get_ref(child)) goto err; } @@ -732,8 +763,8 @@ static int coresight_grab_device(struct coresight_device *csdev) for (i--; i >= 0; i--) { struct coresight_device *child; - child = csdev->pdata->conns[i].child_dev; - if (child && child->type == CORESIGHT_DEV_TYPE_HELPER) + child = csdev->pdata->out_conns[i]->dest_dev; + if (child && coresight_is_helper(child)) coresight_put_ref(child); } return -ENODEV; @@ -748,11 +779,11 @@ static void coresight_drop_device(struct coresight_device *csdev) int i; coresight_put_ref(csdev); - for (i = 0; i < csdev->pdata->nr_outport; i++) { + for (i = 0; i < csdev->pdata->nr_outconns; i++) { struct coresight_device *child; - child = csdev->pdata->conns[i].child_dev; - if (child && child->type == CORESIGHT_DEV_TYPE_HELPER) + child = csdev->pdata->out_conns[i]->dest_dev; + if (child && coresight_is_helper(child)) coresight_put_ref(child); } } @@ -790,10 +821,10 @@ static int _coresight_build_path(struct coresight_device *csdev, } /* Not a sink - recursively explore each port found on this element */ - for (i = 0; i < csdev->pdata->nr_outport; i++) { + for (i = 0; i < csdev->pdata->nr_outconns; i++) { struct coresight_device *child_dev; - child_dev = csdev->pdata->conns[i].child_dev; + child_dev = csdev->pdata->out_conns[i]->dest_dev; if (child_dev && _coresight_build_path(child_dev, sink, path) == 0) { found = true; @@ -959,11 +990,11 @@ coresight_find_sink(struct coresight_device *csdev, int *depth) * Not a sink we want - or possible child sink may be better. * recursively explore each port found on this element. */ - for (i = 0; i < csdev->pdata->nr_outport; i++) { + for (i = 0; i < csdev->pdata->nr_outconns; i++) { struct coresight_device *child_dev, *sink = NULL; int child_depth = curr_depth; - child_dev = csdev->pdata->conns[i].child_dev; + child_dev = csdev->pdata->out_conns[i]->dest_dev; if (child_dev) sink = coresight_find_sink(child_dev, &child_depth); @@ -1093,7 +1124,7 @@ int coresight_enable(struct coresight_device *csdev) * source is already enabled. */ if (subtype == CORESIGHT_DEV_SUBTYPE_SOURCE_SOFTWARE) - atomic_inc(csdev->refcnt); + atomic_inc(&csdev->refcnt); goto out; } @@ -1114,7 +1145,7 @@ int coresight_enable(struct coresight_device *csdev) if (ret) goto err_path; - ret = coresight_enable_source(csdev, CS_MODE_SYSFS); + ret = coresight_enable_source(csdev, CS_MODE_SYSFS, NULL); if (ret) goto err_source; @@ -1171,7 +1202,7 @@ void coresight_disable(struct coresight_device *csdev) if (ret) goto out; - if (!csdev->enable || !coresight_disable_source(csdev)) + if (!csdev->enable || !coresight_disable_source(csdev, NULL)) goto out; switch (csdev->subtype.source_subtype) { @@ -1296,18 +1327,16 @@ static struct device_type coresight_dev_type[] = { }, { .name = "helper", - }, - { - .name = "ect", - }, + } }; +/* Ensure the enum matches the names and groups */ +static_assert(ARRAY_SIZE(coresight_dev_type) == CORESIGHT_DEV_TYPE_MAX); static void coresight_device_release(struct device *dev) { struct coresight_device *csdev = to_coresight_device(dev); fwnode_handle_put(csdev->dev.fwnode); - kfree(csdev->refcnt); kfree(csdev); } @@ -1315,45 +1344,57 @@ static int coresight_orphan_match(struct device *dev, void *data) { int i, ret = 0; bool still_orphan = false; - struct coresight_device *csdev, *i_csdev; + struct coresight_device *dst_csdev = data; + struct coresight_device *src_csdev = to_coresight_device(dev); struct coresight_connection *conn; - - csdev = data; - i_csdev = to_coresight_device(dev); - - /* No need to check oneself */ - if (csdev == i_csdev) - return 0; + bool fixup_self = (src_csdev == dst_csdev); /* Move on to another component if no connection is orphan */ - if (!i_csdev->orphan) + if (!src_csdev->orphan) return 0; /* - * Circle throuch all the connection of that component. If we find - * an orphan connection whose name matches @csdev, link it. + * Circle through all the connections of that component. If we find + * an orphan connection whose name matches @dst_csdev, link it. */ - for (i = 0; i < i_csdev->pdata->nr_outport; i++) { - conn = &i_csdev->pdata->conns[i]; + for (i = 0; i < src_csdev->pdata->nr_outconns; i++) { + conn = src_csdev->pdata->out_conns[i]; - /* Skip the port if FW doesn't describe it */ - if (!conn->child_fwnode) + /* Skip the port if it's already connected. */ + if (conn->dest_dev) continue; - /* We have found at least one orphan connection */ - if (conn->child_dev == NULL) { - /* Does it match this newly added device? */ - if (conn->child_fwnode == csdev->dev.fwnode) { - ret = coresight_make_links(i_csdev, - conn, csdev); - if (ret) - return ret; - } else { - /* This component still has an orphan */ - still_orphan = true; - } + + /* + * If we are at the "new" device, which triggered this search, + * we must find the remote device from the fwnode in the + * connection. + */ + if (fixup_self) + dst_csdev = coresight_find_csdev_by_fwnode( + conn->dest_fwnode); + + /* Does it match this newly added device? */ + if (dst_csdev && conn->dest_fwnode == dst_csdev->dev.fwnode) { + ret = coresight_make_links(src_csdev, conn, dst_csdev); + if (ret) + return ret; + + /* + * Install the device connection. This also indicates that + * the links are operational on both ends. + */ + conn->dest_dev = dst_csdev; + conn->src_dev = src_csdev; + + ret = coresight_add_in_conn(conn); + if (ret) + return ret; + } else { + /* This component still has an orphan */ + still_orphan = true; } } - i_csdev->orphan = still_orphan; + src_csdev->orphan = still_orphan; /* * Returning '0' in case we didn't encounter any error, @@ -1368,91 +1409,43 @@ static int coresight_fixup_orphan_conns(struct coresight_device *csdev) csdev, coresight_orphan_match); } - -static int coresight_fixup_device_conns(struct coresight_device *csdev) -{ - int i, ret = 0; - - for (i = 0; i < csdev->pdata->nr_outport; i++) { - struct coresight_connection *conn = &csdev->pdata->conns[i]; - - if (!conn->child_fwnode) - continue; - conn->child_dev = - coresight_find_csdev_by_fwnode(conn->child_fwnode); - if (conn->child_dev && conn->child_dev->has_conns_grp) { - ret = coresight_make_links(csdev, conn, - conn->child_dev); - if (ret) - break; - } else { - csdev->orphan = true; - } - } - - return ret; -} - -static int coresight_remove_match(struct device *dev, void *data) +/* coresight_remove_conns - Remove other device's references to this device */ +static void coresight_remove_conns(struct coresight_device *csdev) { - int i; - struct coresight_device *csdev, *iterator; + int i, j; struct coresight_connection *conn; - csdev = data; - iterator = to_coresight_device(dev); - - /* No need to check oneself */ - if (csdev == iterator) - return 0; - /* - * Circle throuch all the connection of that component. If we find - * a connection whose name matches @csdev, remove it. + * Remove the input connection references from the destination device + * for each output connection. */ - for (i = 0; i < iterator->pdata->nr_outport; i++) { - conn = &iterator->pdata->conns[i]; - - if (conn->child_dev == NULL || conn->child_fwnode == NULL) + for (i = 0; i < csdev->pdata->nr_outconns; i++) { + conn = csdev->pdata->out_conns[i]; + if (!conn->dest_dev) continue; - if (csdev->dev.fwnode == conn->child_fwnode) { - iterator->orphan = true; - coresight_remove_links(iterator, conn); - /* - * Drop the reference to the handle for the remote - * device acquired in parsing the connections from - * platform data. - */ - fwnode_handle_put(conn->child_fwnode); - conn->child_fwnode = NULL; - /* No need to continue */ - break; - } + for (j = 0; j < conn->dest_dev->pdata->nr_inconns; ++j) + if (conn->dest_dev->pdata->in_conns[j] == conn) { + conn->dest_dev->pdata->in_conns[j] = NULL; + break; + } } /* - * Returning '0' ensures that all known component on the - * bus will be checked. + * For all input connections, remove references to this device. + * Connection objects are shared so modifying this device's input + * connections affects the other device's output connection. */ - return 0; -} + for (i = 0; i < csdev->pdata->nr_inconns; ++i) { + conn = csdev->pdata->in_conns[i]; + /* Input conns array is sparse */ + if (!conn) + continue; -/* - * coresight_remove_conns - Remove references to this given devices - * from the connections of other devices. - */ -static void coresight_remove_conns(struct coresight_device *csdev) -{ - /* - * Another device will point to this device only if there is - * an output port connected to this one. i.e, if the device - * doesn't have at least one input port, there is no point - * in searching all the devices. - */ - if (csdev->pdata->nr_inport) - bus_for_each_dev(&coresight_bustype, NULL, - csdev, coresight_remove_match); + conn->src_dev->orphan = true; + coresight_remove_links(conn->src_dev, conn); + conn->dest_dev = NULL; + } } /** @@ -1544,24 +1537,27 @@ void coresight_write64(struct coresight_device *csdev, u64 val, u32 offset) * to the output port of this device. */ void coresight_release_platform_data(struct coresight_device *csdev, + struct device *dev, struct coresight_platform_data *pdata) { int i; - struct coresight_connection *conns = pdata->conns; + struct coresight_connection **conns = pdata->out_conns; - for (i = 0; i < pdata->nr_outport; i++) { + for (i = 0; i < pdata->nr_outconns; i++) { /* If we have made the links, remove them now */ - if (csdev && conns[i].child_dev) - coresight_remove_links(csdev, &conns[i]); + if (csdev && conns[i]->dest_dev) + coresight_remove_links(csdev, conns[i]); /* * Drop the refcount and clear the handle as this device * is going away */ - if (conns[i].child_fwnode) { - fwnode_handle_put(conns[i].child_fwnode); - pdata->conns[i].child_fwnode = NULL; - } + fwnode_handle_put(conns[i]->dest_fwnode); + conns[i]->dest_fwnode = NULL; + devm_kfree(dev, conns[i]); } + devm_kfree(dev, pdata->out_conns); + devm_kfree(dev, pdata->in_conns); + devm_kfree(dev, pdata); if (csdev) coresight_remove_conns_sysfs_group(csdev); } @@ -1569,9 +1565,6 @@ void coresight_release_platform_data(struct coresight_device *csdev, struct coresight_device *coresight_register(struct coresight_desc *desc) { int ret; - int link_subtype; - int nr_refcnts = 1; - atomic_t *refcnts = NULL; struct coresight_device *csdev; bool registered = false; @@ -1581,32 +1574,13 @@ struct coresight_device *coresight_register(struct coresight_desc *desc) goto err_out; } - if (desc->type == CORESIGHT_DEV_TYPE_LINK || - desc->type == CORESIGHT_DEV_TYPE_LINKSINK) { - link_subtype = desc->subtype.link_subtype; - - if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_MERG) - nr_refcnts = desc->pdata->nr_inport; - else if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_SPLIT) - nr_refcnts = desc->pdata->nr_outport; - } - - refcnts = kcalloc(nr_refcnts, sizeof(*refcnts), GFP_KERNEL); - if (!refcnts) { - ret = -ENOMEM; - kfree(csdev); - goto err_out; - } - - csdev->refcnt = refcnts; - csdev->pdata = desc->pdata; csdev->type = desc->type; csdev->subtype = desc->subtype; csdev->ops = desc->ops; csdev->access = desc->access; - csdev->orphan = false; + csdev->orphan = true; csdev->dev.type = &coresight_dev_type[desc->type]; csdev->dev.groups = desc->groups; @@ -1656,8 +1630,6 @@ struct coresight_device *coresight_register(struct coresight_desc *desc) registered = true; ret = coresight_create_conns_sysfs_group(csdev); - if (!ret) - ret = coresight_fixup_device_conns(csdev); if (!ret) ret = coresight_fixup_orphan_conns(csdev); @@ -1678,7 +1650,7 @@ struct coresight_device *coresight_register(struct coresight_desc *desc) err_out: /* Cleanup the connection information */ - coresight_release_platform_data(NULL, desc->pdata); + coresight_release_platform_data(NULL, desc->dev, desc->pdata); return ERR_PTR(ret); } EXPORT_SYMBOL_GPL(coresight_register); @@ -1691,7 +1663,7 @@ void coresight_unregister(struct coresight_device *csdev) cti_assoc_ops->remove(csdev); coresight_remove_conns(csdev); coresight_clear_default_sink(csdev); - coresight_release_platform_data(csdev, csdev->pdata); + coresight_release_platform_data(csdev, csdev->dev.parent, csdev->pdata); device_unregister(&csdev->dev); } EXPORT_SYMBOL_GPL(coresight_unregister); @@ -1714,6 +1686,69 @@ static inline int coresight_search_device_idx(struct coresight_dev_list *dict, return -ENOENT; } +static bool coresight_compare_type(enum coresight_dev_type type_a, + union coresight_dev_subtype subtype_a, + enum coresight_dev_type type_b, + union coresight_dev_subtype subtype_b) +{ + if (type_a != type_b) + return false; + + switch (type_a) { + case CORESIGHT_DEV_TYPE_SINK: + return subtype_a.sink_subtype == subtype_b.sink_subtype; + case CORESIGHT_DEV_TYPE_LINK: + return subtype_a.link_subtype == subtype_b.link_subtype; + case CORESIGHT_DEV_TYPE_LINKSINK: + return subtype_a.link_subtype == subtype_b.link_subtype && + subtype_a.sink_subtype == subtype_b.sink_subtype; + case CORESIGHT_DEV_TYPE_SOURCE: + return subtype_a.source_subtype == subtype_b.source_subtype; + case CORESIGHT_DEV_TYPE_HELPER: + return subtype_a.helper_subtype == subtype_b.helper_subtype; + default: + return false; + } +} + +struct coresight_device * +coresight_find_input_type(struct coresight_platform_data *pdata, + enum coresight_dev_type type, + union coresight_dev_subtype subtype) +{ + int i; + struct coresight_connection *conn; + + for (i = 0; i < pdata->nr_inconns; ++i) { + conn = pdata->in_conns[i]; + if (conn && + coresight_compare_type(type, subtype, conn->src_dev->type, + conn->src_dev->subtype)) + return conn->src_dev; + } + return NULL; +} +EXPORT_SYMBOL_GPL(coresight_find_input_type); + +struct coresight_device * +coresight_find_output_type(struct coresight_platform_data *pdata, + enum coresight_dev_type type, + union coresight_dev_subtype subtype) +{ + int i; + struct coresight_connection *conn; + + for (i = 0; i < pdata->nr_outconns; ++i) { + conn = pdata->out_conns[i]; + if (conn->dest_dev && + coresight_compare_type(type, subtype, conn->dest_dev->type, + conn->dest_dev->subtype)) + return conn->dest_dev; + } + return NULL; +} +EXPORT_SYMBOL_GPL(coresight_find_output_type); + bool coresight_loses_context_with_cpu(struct device *dev) { return fwnode_property_present(dev_fwnode(dev), diff --git a/drivers/hwtracing/coresight/coresight-cti-core.c b/drivers/hwtracing/coresight/coresight-cti-core.c index 277c890a1f1f2b4355eef8f29ca52ddb66b7c755..7023ff70cc285420ab95f6240e48040cd51df027 100644 --- a/drivers/hwtracing/coresight/coresight-cti-core.c +++ b/drivers/hwtracing/coresight/coresight-cti-core.c @@ -555,7 +555,10 @@ static void cti_add_assoc_to_csdev(struct coresight_device *csdev) mutex_lock(&ect_mutex); /* exit if current is an ECT device.*/ - if ((csdev->type == CORESIGHT_DEV_TYPE_ECT) || list_empty(&ect_net)) + if ((csdev->type == CORESIGHT_DEV_TYPE_HELPER && + csdev->subtype.helper_subtype == + CORESIGHT_DEV_SUBTYPE_HELPER_ECT_CTI) || + list_empty(&ect_net)) goto cti_add_done; /* if we didn't find the csdev previously we used the fwnode name */ @@ -571,8 +574,7 @@ static void cti_add_assoc_to_csdev(struct coresight_device *csdev) * if we found a matching csdev then update the ECT * association pointer for the device with this CTI. */ - coresight_set_assoc_ectdev_mutex(csdev, - ect_item->csdev); + coresight_add_helper(csdev, ect_item->csdev); break; } } @@ -582,26 +584,30 @@ static void cti_add_assoc_to_csdev(struct coresight_device *csdev) /* * Removing the associated devices is easier. - * A CTI will not have a value for csdev->ect_dev. */ static void cti_remove_assoc_from_csdev(struct coresight_device *csdev) { struct cti_drvdata *ctidrv; struct cti_trig_con *tc; struct cti_device *ctidev; + union coresight_dev_subtype cti_subtype = { + .helper_subtype = CORESIGHT_DEV_SUBTYPE_HELPER_ECT_CTI + }; + struct coresight_device *cti_csdev = coresight_find_output_type( + csdev->pdata, CORESIGHT_DEV_TYPE_HELPER, cti_subtype); + + if (!cti_csdev) + return; mutex_lock(&ect_mutex); - if (csdev->ect_dev) { - ctidrv = csdev_to_cti_drvdata(csdev->ect_dev); - ctidev = &ctidrv->ctidev; - list_for_each_entry(tc, &ctidev->trig_cons, node) { - if (tc->con_dev == csdev) { - cti_remove_sysfs_link(ctidrv, tc); - tc->con_dev = NULL; - break; - } + ctidrv = csdev_to_cti_drvdata(cti_csdev); + ctidev = &ctidrv->ctidev; + list_for_each_entry(tc, &ctidev->trig_cons, node) { + if (tc->con_dev == csdev) { + cti_remove_sysfs_link(ctidrv, tc); + tc->con_dev = NULL; + break; } - csdev->ect_dev = NULL; } mutex_unlock(&ect_mutex); } @@ -630,8 +636,8 @@ static void cti_update_conn_xrefs(struct cti_drvdata *drvdata) /* if we can set the sysfs link */ if (cti_add_sysfs_link(drvdata, tc)) /* set the CTI/csdev association */ - coresight_set_assoc_ectdev_mutex(tc->con_dev, - drvdata->csdev); + coresight_add_helper(tc->con_dev, + drvdata->csdev); else /* otherwise remove reference from CTI */ tc->con_dev = NULL; @@ -646,8 +652,6 @@ static void cti_remove_conn_xrefs(struct cti_drvdata *drvdata) list_for_each_entry(tc, &ctidev->trig_cons, node) { if (tc->con_dev) { - coresight_set_assoc_ectdev_mutex(tc->con_dev, - NULL); cti_remove_sysfs_link(drvdata, tc); tc->con_dev = NULL; } @@ -795,27 +799,27 @@ static void cti_pm_release(struct cti_drvdata *drvdata) } /** cti ect operations **/ -int cti_enable(struct coresight_device *csdev) +int cti_enable(struct coresight_device *csdev, enum cs_mode mode, void *data) { struct cti_drvdata *drvdata = csdev_to_cti_drvdata(csdev); return cti_enable_hw(drvdata); } -int cti_disable(struct coresight_device *csdev) +int cti_disable(struct coresight_device *csdev, void *data) { struct cti_drvdata *drvdata = csdev_to_cti_drvdata(csdev); return cti_disable_hw(drvdata); } -static const struct coresight_ops_ect cti_ops_ect = { +static const struct coresight_ops_helper cti_ops_ect = { .enable = cti_enable, .disable = cti_disable, }; static const struct coresight_ops cti_ops = { - .ect_ops = &cti_ops_ect, + .helper_ops = &cti_ops_ect, }; /* @@ -922,8 +926,8 @@ static int cti_probe(struct amba_device *adev, const struct amba_id *id) /* set up coresight component description */ cti_desc.pdata = pdata; - cti_desc.type = CORESIGHT_DEV_TYPE_ECT; - cti_desc.subtype.ect_subtype = CORESIGHT_DEV_SUBTYPE_ECT_CTI; + cti_desc.type = CORESIGHT_DEV_TYPE_HELPER; + cti_desc.subtype.helper_subtype = CORESIGHT_DEV_SUBTYPE_HELPER_ECT_CTI; cti_desc.ops = &cti_ops; cti_desc.groups = drvdata->ctidev.con_groups; cti_desc.dev = dev; diff --git a/drivers/hwtracing/coresight/coresight-cti-sysfs.c b/drivers/hwtracing/coresight/coresight-cti-sysfs.c index e528cff9d4e2752da05ae1abf91889bad6618463..d25dd2737b49d4251af03a37c20bc58919f377f2 100644 --- a/drivers/hwtracing/coresight/coresight-cti-sysfs.c +++ b/drivers/hwtracing/coresight/coresight-cti-sysfs.c @@ -112,11 +112,11 @@ static ssize_t enable_store(struct device *dev, ret = pm_runtime_resume_and_get(dev->parent); if (ret) return ret; - ret = cti_enable(drvdata->csdev); + ret = cti_enable(drvdata->csdev, CS_MODE_SYSFS, NULL); if (ret) pm_runtime_put(dev->parent); } else { - ret = cti_disable(drvdata->csdev); + ret = cti_disable(drvdata->csdev, NULL); if (!ret) pm_runtime_put(dev->parent); } diff --git a/drivers/hwtracing/coresight/coresight-cti.h b/drivers/hwtracing/coresight/coresight-cti.h index 8b106b13a244441f92d3d449e072cc26c5e3d7d6..cb9ee616d01f3410a726d7777da8244c68129b91 100644 --- a/drivers/hwtracing/coresight/coresight-cti.h +++ b/drivers/hwtracing/coresight/coresight-cti.h @@ -215,8 +215,8 @@ int cti_add_connection_entry(struct device *dev, struct cti_drvdata *drvdata, const char *assoc_dev_name); struct cti_trig_con *cti_allocate_trig_con(struct device *dev, int in_sigs, int out_sigs); -int cti_enable(struct coresight_device *csdev); -int cti_disable(struct coresight_device *csdev); +int cti_enable(struct coresight_device *csdev, enum cs_mode mode, void *data); +int cti_disable(struct coresight_device *csdev, void *data); void cti_write_all_hw_regs(struct cti_drvdata *drvdata); void cti_write_intack(struct device *dev, u32 ackval); void cti_write_single_reg(struct cti_drvdata *drvdata, int offset, u32 value); diff --git a/drivers/hwtracing/coresight/coresight-dummy.c b/drivers/hwtracing/coresight/coresight-dummy.c new file mode 100644 index 0000000000000000000000000000000000000000..8035120b70b37b5a931b48cdf9451156ec82f533 --- /dev/null +++ b/drivers/hwtracing/coresight/coresight-dummy.c @@ -0,0 +1,163 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include + +#include "coresight-priv.h" + +struct dummy_drvdata { + struct device *dev; + struct coresight_device *csdev; +}; + +DEFINE_CORESIGHT_DEVLIST(source_devs, "dummy_source"); +DEFINE_CORESIGHT_DEVLIST(sink_devs, "dummy_sink"); + +static int dummy_source_enable(struct coresight_device *csdev, + struct perf_event *event, enum cs_mode mode) +{ + dev_dbg(csdev->dev.parent, "Dummy source enabled\n"); + + return 0; +} + +static void dummy_source_disable(struct coresight_device *csdev, + struct perf_event *event) +{ + dev_dbg(csdev->dev.parent, "Dummy source disabled\n"); +} + +static int dummy_sink_enable(struct coresight_device *csdev, enum cs_mode mode, + void *data) +{ + dev_dbg(csdev->dev.parent, "Dummy sink enabled\n"); + + return 0; +} + +static int dummy_sink_disable(struct coresight_device *csdev) +{ + dev_dbg(csdev->dev.parent, "Dummy sink disabled\n"); + + return 0; +} + +static const struct coresight_ops_source dummy_source_ops = { + .enable = dummy_source_enable, + .disable = dummy_source_disable, +}; + +static const struct coresight_ops dummy_source_cs_ops = { + .source_ops = &dummy_source_ops, +}; + +static const struct coresight_ops_sink dummy_sink_ops = { + .enable = dummy_sink_enable, + .disable = dummy_sink_disable, +}; + +static const struct coresight_ops dummy_sink_cs_ops = { + .sink_ops = &dummy_sink_ops, +}; + +static int dummy_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *node = dev->of_node; + struct coresight_platform_data *pdata; + struct dummy_drvdata *drvdata; + struct coresight_desc desc = { 0 }; + + if (of_device_is_compatible(node, "arm,coresight-dummy-source")) { + + desc.name = coresight_alloc_device_name(&source_devs, dev); + if (!desc.name) + return -ENOMEM; + + desc.type = CORESIGHT_DEV_TYPE_SOURCE; + desc.subtype.source_subtype = + CORESIGHT_DEV_SUBTYPE_SOURCE_OTHERS; + desc.ops = &dummy_source_cs_ops; + } else if (of_device_is_compatible(node, "arm,coresight-dummy-sink")) { + desc.name = coresight_alloc_device_name(&sink_devs, dev); + if (!desc.name) + return -ENOMEM; + + desc.type = CORESIGHT_DEV_TYPE_SINK; + desc.subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_DUMMY; + desc.ops = &dummy_sink_cs_ops; + } else { + dev_err(dev, "Device type not set\n"); + return -EINVAL; + } + + pdata = coresight_get_platform_data(dev); + if (IS_ERR(pdata)) + return PTR_ERR(pdata); + pdev->dev.platform_data = pdata; + + drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL); + if (!drvdata) + return -ENOMEM; + + drvdata->dev = &pdev->dev; + platform_set_drvdata(pdev, drvdata); + + desc.pdata = pdev->dev.platform_data; + desc.dev = &pdev->dev; + drvdata->csdev = coresight_register(&desc); + if (IS_ERR(drvdata->csdev)) + return PTR_ERR(drvdata->csdev); + + pm_runtime_enable(dev); + dev_dbg(dev, "Dummy device initialized\n"); + + return 0; +} + +static int dummy_remove(struct platform_device *pdev) +{ + struct dummy_drvdata *drvdata = platform_get_drvdata(pdev); + struct device *dev = &pdev->dev; + + pm_runtime_disable(dev); + coresight_unregister(drvdata->csdev); + return 0; +} + +static const struct of_device_id dummy_match[] = { + {.compatible = "arm,coresight-dummy-source"}, + {.compatible = "arm,coresight-dummy-sink"}, + {}, +}; + +static struct platform_driver dummy_driver = { + .probe = dummy_probe, + .remove = dummy_remove, + .driver = { + .name = "coresight-dummy", + .of_match_table = dummy_match, + }, +}; + +static int __init dummy_init(void) +{ + return platform_driver_register(&dummy_driver); +} +module_init(dummy_init); + +static void __exit dummy_exit(void) +{ + platform_driver_unregister(&dummy_driver); +} +module_exit(dummy_exit); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("CoreSight dummy driver"); diff --git a/drivers/hwtracing/coresight/coresight-etb10.c b/drivers/hwtracing/coresight/coresight-etb10.c index 8aa6e4f83e42b58eaff64f1f373bb67b03cda2c7..fa80039e0821f095b954d445e913c8f516cef4f4 100644 --- a/drivers/hwtracing/coresight/coresight-etb10.c +++ b/drivers/hwtracing/coresight/coresight-etb10.c @@ -163,7 +163,7 @@ static int etb_enable_sysfs(struct coresight_device *csdev) drvdata->mode = CS_MODE_SYSFS; } - atomic_inc(csdev->refcnt); + atomic_inc(&csdev->refcnt); out: spin_unlock_irqrestore(&drvdata->spinlock, flags); return ret; @@ -199,7 +199,7 @@ static int etb_enable_perf(struct coresight_device *csdev, void *data) * use for this session. */ if (drvdata->pid == pid) { - atomic_inc(csdev->refcnt); + atomic_inc(&csdev->refcnt); goto out; } @@ -217,7 +217,7 @@ static int etb_enable_perf(struct coresight_device *csdev, void *data) /* Associate with monitored process. */ drvdata->pid = pid; drvdata->mode = CS_MODE_PERF; - atomic_inc(csdev->refcnt); + atomic_inc(&csdev->refcnt); } out: @@ -225,7 +225,8 @@ static int etb_enable_perf(struct coresight_device *csdev, void *data) return ret; } -static int etb_enable(struct coresight_device *csdev, u32 mode, void *data) +static int etb_enable(struct coresight_device *csdev, enum cs_mode mode, + void *data) { int ret; @@ -355,7 +356,7 @@ static int etb_disable(struct coresight_device *csdev) spin_lock_irqsave(&drvdata->spinlock, flags); - if (atomic_dec_return(csdev->refcnt)) { + if (atomic_dec_return(&csdev->refcnt)) { spin_unlock_irqrestore(&drvdata->spinlock, flags); return -EBUSY; } @@ -446,7 +447,7 @@ static unsigned long etb_update_buffer(struct coresight_device *csdev, spin_lock_irqsave(&drvdata->spinlock, flags); /* Don't do anything if another tracer is using this sink */ - if (atomic_read(csdev->refcnt) != 1) + if (atomic_read(&csdev->refcnt) != 1) goto out; __etb_disable_hw(drvdata); diff --git a/drivers/hwtracing/coresight/coresight-etm-perf.c b/drivers/hwtracing/coresight/coresight-etm-perf.c index 89e8ed214ea4967620c20ad1c1a1e39f9d068400..5ca6278baff4fa70ff6856458dce44beeecc6339 100644 --- a/drivers/hwtracing/coresight/coresight-etm-perf.c +++ b/drivers/hwtracing/coresight/coresight-etm-perf.c @@ -493,7 +493,7 @@ static void etm_event_start(struct perf_event *event, int flags) goto fail_end_stop; /* Finally enable the tracer */ - if (source_ops(csdev)->enable(csdev, event, CS_MODE_PERF)) + if (coresight_enable_source(csdev, CS_MODE_PERF, event)) goto fail_disable_path; /* @@ -587,7 +587,7 @@ static void etm_event_stop(struct perf_event *event, int mode) return; /* stop tracer */ - source_ops(csdev)->disable(csdev, event); + coresight_disable_source(csdev, event); /* tell the core */ event->hw.state = PERF_HES_STOPPED; diff --git a/drivers/hwtracing/coresight/coresight-etm3x-core.c b/drivers/hwtracing/coresight/coresight-etm3x-core.c index afc57195ee525a178c063d2274efd5c2a153c8b5..116a91d90ac20a86ba7650b6b2f466ce5e1fa7e2 100644 --- a/drivers/hwtracing/coresight/coresight-etm3x-core.c +++ b/drivers/hwtracing/coresight/coresight-etm3x-core.c @@ -552,8 +552,8 @@ static int etm_enable_sysfs(struct coresight_device *csdev) return ret; } -static int etm_enable(struct coresight_device *csdev, - struct perf_event *event, u32 mode) +static int etm_enable(struct coresight_device *csdev, struct perf_event *event, + enum cs_mode mode) { int ret; u32 val; @@ -671,7 +671,7 @@ static void etm_disable_sysfs(struct coresight_device *csdev) static void etm_disable(struct coresight_device *csdev, struct perf_event *event) { - u32 mode; + enum cs_mode mode; struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); /* diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c index 4c15fae534f3a353c814610647f55e132c4a76a2..7e307022303ae55a3123e3676a9376d92dad08f3 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x-core.c +++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c @@ -822,8 +822,8 @@ static int etm4_enable_sysfs(struct coresight_device *csdev) return ret; } -static int etm4_enable(struct coresight_device *csdev, - struct perf_event *event, u32 mode) +static int etm4_enable(struct coresight_device *csdev, struct perf_event *event, + enum cs_mode mode) { int ret; u32 val; @@ -989,7 +989,7 @@ static void etm4_disable_sysfs(struct coresight_device *csdev) static void etm4_disable(struct coresight_device *csdev, struct perf_event *event) { - u32 mode; + enum cs_mode mode; struct etmv4_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); /* @@ -2190,7 +2190,7 @@ static void clear_etmdrvdata(void *info) per_cpu(delayed_probe, cpu) = NULL; } -static int __exit etm4_remove_dev(struct etmv4_drvdata *drvdata) +static void __exit etm4_remove_dev(struct etmv4_drvdata *drvdata) { bool had_delayed_probe; /* @@ -2217,8 +2217,6 @@ static int __exit etm4_remove_dev(struct etmv4_drvdata *drvdata) cscfg_unregister_csdev(drvdata->csdev); coresight_unregister(drvdata->csdev); } - - return 0; } static void __exit etm4_remove_amba(struct amba_device *adev) @@ -2231,13 +2229,12 @@ static void __exit etm4_remove_amba(struct amba_device *adev) static int __exit etm4_remove_platform_dev(struct platform_device *pdev) { - int ret = 0; struct etmv4_drvdata *drvdata = dev_get_drvdata(&pdev->dev); if (drvdata) - ret = etm4_remove_dev(drvdata); + etm4_remove_dev(drvdata); pm_runtime_disable(&pdev->dev); - return ret; + return 0; } static const struct amba_id etm4_ids[] = { @@ -2260,6 +2257,11 @@ static const struct amba_id etm4_ids[] = { CS_AMBA_UCI_ID(0x000cc0af, uci_id_etm4),/* Marvell ThunderX2 */ CS_AMBA_UCI_ID(0x000b6d01, uci_id_etm4),/* HiSilicon-Hip08 */ CS_AMBA_UCI_ID(0x000b6d02, uci_id_etm4),/* HiSilicon-Hip09 */ + /* + * Match all PIDs with ETM4 DEVARCH. No need for adding any of the new + * CPUs to the list here. + */ + CS_AMBA_MATCH_ALL_UCI(uci_id_etm4), {}, }; diff --git a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c b/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c index 5e62aa40ecd0f423dc4ef05d139012ac0f724c1a..a9f19629f3f84cf58ec3086ff06ffabb15dc8c52 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c +++ b/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c @@ -2411,7 +2411,6 @@ static ssize_t trctraceid_show(struct device *dev, return sysfs_emit(buf, "0x%x\n", trace_id); } -static DEVICE_ATTR_RO(trctraceid); struct etmv4_reg { struct coresight_device *csdev; @@ -2528,13 +2527,23 @@ coresight_etm4x_attr_reg_implemented(struct kobject *kobj, return 0; } -#define coresight_etm4x_reg(name, offset) \ - &((struct dev_ext_attribute[]) { \ - { \ - __ATTR(name, 0444, coresight_etm4x_reg_show, NULL), \ - (void *)(unsigned long)offset \ - } \ - })[0].attr.attr +/* + * Macro to set an RO ext attribute with offset and show function. + * Offset is used in mgmt group to ensure only correct registers for + * the ETM / ETE variant are visible. + */ +#define coresight_etm4x_reg_showfn(name, offset, showfn) ( \ + &((struct dev_ext_attribute[]) { \ + { \ + __ATTR(name, 0444, showfn, NULL), \ + (void *)(unsigned long)offset \ + } \ + })[0].attr.attr \ + ) + +/* macro using the default coresight_etm4x_reg_show function */ +#define coresight_etm4x_reg(name, offset) \ + coresight_etm4x_reg_showfn(name, offset, coresight_etm4x_reg_show) static struct attribute *coresight_etmv4_mgmt_attrs[] = { coresight_etm4x_reg(trcpdcr, TRCPDCR), @@ -2549,7 +2558,7 @@ static struct attribute *coresight_etmv4_mgmt_attrs[] = { coresight_etm4x_reg(trcpidr3, TRCPIDR3), coresight_etm4x_reg(trcoslsr, TRCOSLSR), coresight_etm4x_reg(trcconfig, TRCCONFIGR), - &dev_attr_trctraceid.attr, + coresight_etm4x_reg_showfn(trctraceid, TRCTRACEIDR, trctraceid_show), coresight_etm4x_reg(trcdevarch, TRCDEVARCH), NULL, }; diff --git a/drivers/hwtracing/coresight/coresight-funnel.c b/drivers/hwtracing/coresight/coresight-funnel.c index b363dd6bc510eb20810f415fe8a67e62505462b8..b8e150e45b272d21409696cab6da8bef9d8e2aa4 100644 --- a/drivers/hwtracing/coresight/coresight-funnel.c +++ b/drivers/hwtracing/coresight/coresight-funnel.c @@ -74,8 +74,9 @@ static int dynamic_funnel_enable_hw(struct funnel_drvdata *drvdata, int port) return rc; } -static int funnel_enable(struct coresight_device *csdev, int inport, - int outport) +static int funnel_enable(struct coresight_device *csdev, + struct coresight_connection *in, + struct coresight_connection *out) { int rc = 0; struct funnel_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); @@ -83,18 +84,19 @@ static int funnel_enable(struct coresight_device *csdev, int inport, bool first_enable = false; spin_lock_irqsave(&drvdata->spinlock, flags); - if (atomic_read(&csdev->refcnt[inport]) == 0) { + if (atomic_read(&in->dest_refcnt) == 0) { if (drvdata->base) - rc = dynamic_funnel_enable_hw(drvdata, inport); + rc = dynamic_funnel_enable_hw(drvdata, in->dest_port); if (!rc) first_enable = true; } if (!rc) - atomic_inc(&csdev->refcnt[inport]); + atomic_inc(&in->dest_refcnt); spin_unlock_irqrestore(&drvdata->spinlock, flags); if (first_enable) - dev_dbg(&csdev->dev, "FUNNEL inport %d enabled\n", inport); + dev_dbg(&csdev->dev, "FUNNEL inport %d enabled\n", + in->dest_port); return rc; } @@ -117,23 +119,25 @@ static void dynamic_funnel_disable_hw(struct funnel_drvdata *drvdata, CS_LOCK(drvdata->base); } -static void funnel_disable(struct coresight_device *csdev, int inport, - int outport) +static void funnel_disable(struct coresight_device *csdev, + struct coresight_connection *in, + struct coresight_connection *out) { struct funnel_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); unsigned long flags; bool last_disable = false; spin_lock_irqsave(&drvdata->spinlock, flags); - if (atomic_dec_return(&csdev->refcnt[inport]) == 0) { + if (atomic_dec_return(&in->dest_refcnt) == 0) { if (drvdata->base) - dynamic_funnel_disable_hw(drvdata, inport); + dynamic_funnel_disable_hw(drvdata, in->dest_port); last_disable = true; } spin_unlock_irqrestore(&drvdata->spinlock, flags); if (last_disable) - dev_dbg(&csdev->dev, "FUNNEL inport %d disabled\n", inport); + dev_dbg(&csdev->dev, "FUNNEL inport %d disabled\n", + in->dest_port); } static const struct coresight_ops_link funnel_link_ops = { diff --git a/drivers/hwtracing/coresight/coresight-platform.c b/drivers/hwtracing/coresight/coresight-platform.c index 47589971410467a64c16100bfddce51e997cf01f..3e2e135cb8f6d2c62713b5a484f4fa1ececda097 100644 --- a/drivers/hwtracing/coresight/coresight-platform.c +++ b/drivers/hwtracing/coresight/coresight-platform.c @@ -19,22 +19,85 @@ #include #include "coresight-priv.h" + /* - * coresight_alloc_conns: Allocate connections record for each output - * port from the device. + * Add an entry to the connection list and assign @conn's contents to it. + * + * If the output port is already assigned on this device, return -EINVAL */ -static int coresight_alloc_conns(struct device *dev, - struct coresight_platform_data *pdata) +struct coresight_connection * +coresight_add_out_conn(struct device *dev, + struct coresight_platform_data *pdata, + const struct coresight_connection *new_conn) { - if (pdata->nr_outport) { - pdata->conns = devm_kcalloc(dev, pdata->nr_outport, - sizeof(*pdata->conns), GFP_KERNEL); - if (!pdata->conns) - return -ENOMEM; + int i; + struct coresight_connection *conn; + + /* + * Warn on any existing duplicate output port. + */ + for (i = 0; i < pdata->nr_outconns; ++i) { + conn = pdata->out_conns[i]; + /* Output == -1 means ignore the port for example for helpers */ + if (conn->src_port != -1 && + conn->src_port == new_conn->src_port) { + dev_warn(dev, "Duplicate output port %d\n", + conn->src_port); + return ERR_PTR(-EINVAL); + } } + pdata->nr_outconns++; + pdata->out_conns = + devm_krealloc_array(dev, pdata->out_conns, pdata->nr_outconns, + sizeof(*pdata->out_conns), GFP_KERNEL); + if (!pdata->out_conns) + return ERR_PTR(-ENOMEM); + + conn = devm_kmalloc(dev, sizeof(struct coresight_connection), + GFP_KERNEL); + if (!conn) + return ERR_PTR(-ENOMEM); + + /* + * Copy the new connection into the allocation, save the pointer to the + * end of the connection array and also return it in case it needs to be + * used right away. + */ + *conn = *new_conn; + pdata->out_conns[pdata->nr_outconns - 1] = conn; + return conn; +} +EXPORT_SYMBOL_GPL(coresight_add_out_conn); + +/* + * Add an input connection reference to @out_conn in the target's in_conns array + * + * @out_conn: Existing output connection to store as an input on the + * connection's remote device. + */ +int coresight_add_in_conn(struct coresight_connection *out_conn) +{ + int i; + struct device *dev = out_conn->dest_dev->dev.parent; + struct coresight_platform_data *pdata = out_conn->dest_dev->pdata; + + for (i = 0; i < pdata->nr_inconns; ++i) + if (!pdata->in_conns[i]) { + pdata->in_conns[i] = out_conn; + return 0; + } + + pdata->nr_inconns++; + pdata->in_conns = + devm_krealloc_array(dev, pdata->in_conns, pdata->nr_inconns, + sizeof(*pdata->in_conns), GFP_KERNEL); + if (!pdata->in_conns) + return -ENOMEM; + pdata->in_conns[pdata->nr_inconns - 1] = out_conn; return 0; } +EXPORT_SYMBOL_GPL(coresight_add_in_conn); static struct device * coresight_find_device_by_fwnode(struct fwnode_handle *fwnode) @@ -83,41 +146,6 @@ static inline bool of_coresight_legacy_ep_is_input(struct device_node *ep) return of_property_read_bool(ep, "slave-mode"); } -static void of_coresight_get_ports_legacy(const struct device_node *node, - int *nr_inport, int *nr_outport) -{ - struct device_node *ep = NULL; - struct of_endpoint endpoint; - int in = 0, out = 0; - - /* - * Avoid warnings in of_graph_get_next_endpoint() - * if the device doesn't have any graph connections - */ - if (!of_graph_is_present(node)) - return; - do { - ep = of_graph_get_next_endpoint(node, ep); - if (!ep) - break; - - if (of_graph_parse_endpoint(ep, &endpoint)) - continue; - - if (of_coresight_legacy_ep_is_input(ep)) { - in = (endpoint.port + 1 > in) ? - endpoint.port + 1 : in; - } else { - out = (endpoint.port + 1) > out ? - endpoint.port + 1 : out; - } - - } while (ep); - - *nr_inport = in; - *nr_outport = out; -} - static struct device_node *of_coresight_get_port_parent(struct device_node *ep) { struct device_node *parent = of_graph_get_port_parent(ep); @@ -133,59 +161,12 @@ static struct device_node *of_coresight_get_port_parent(struct device_node *ep) return parent; } -static inline struct device_node * -of_coresight_get_input_ports_node(const struct device_node *node) -{ - return of_get_child_by_name(node, "in-ports"); -} - static inline struct device_node * of_coresight_get_output_ports_node(const struct device_node *node) { return of_get_child_by_name(node, "out-ports"); } -static inline int -of_coresight_count_ports(struct device_node *port_parent) -{ - int i = 0; - struct device_node *ep = NULL; - struct of_endpoint endpoint; - - while ((ep = of_graph_get_next_endpoint(port_parent, ep))) { - /* Defer error handling to parsing */ - if (of_graph_parse_endpoint(ep, &endpoint)) - continue; - if (endpoint.port + 1 > i) - i = endpoint.port + 1; - } - - return i; -} - -static void of_coresight_get_ports(const struct device_node *node, - int *nr_inport, int *nr_outport) -{ - struct device_node *input_ports = NULL, *output_ports = NULL; - - input_ports = of_coresight_get_input_ports_node(node); - output_ports = of_coresight_get_output_ports_node(node); - - if (input_ports || output_ports) { - if (input_ports) { - *nr_inport = of_coresight_count_ports(input_ports); - of_node_put(input_ports); - } - if (output_ports) { - *nr_outport = of_coresight_count_ports(output_ports); - of_node_put(output_ports); - } - } else { - /* Fall back to legacy DT bindings parsing */ - of_coresight_get_ports_legacy(node, nr_inport, nr_outport); - } -} - static int of_coresight_get_cpu(struct device *dev) { int cpu; @@ -206,7 +187,7 @@ static int of_coresight_get_cpu(struct device *dev) /* * of_coresight_parse_endpoint : Parse the given output endpoint @ep - * and fill the connection information in @conn + * and fill the connection information in @pdata->out_conns * * Parses the local port, remote device name and the remote port. * @@ -224,7 +205,8 @@ static int of_coresight_parse_endpoint(struct device *dev, struct device_node *rep = NULL; struct device *rdev = NULL; struct fwnode_handle *rdev_fwnode; - struct coresight_connection *conn; + struct coresight_connection conn = {}; + struct coresight_connection *new_conn; do { /* Parse the local port details */ @@ -251,14 +233,7 @@ static int of_coresight_parse_endpoint(struct device *dev, break; } - conn = &pdata->conns[endpoint.port]; - if (conn->child_fwnode) { - dev_warn(dev, "Duplicate output port %d\n", - endpoint.port); - ret = -EINVAL; - break; - } - conn->outport = endpoint.port; + conn.src_port = endpoint.port; /* * Hold the refcount to the target device. This could be * released via: @@ -267,8 +242,14 @@ static int of_coresight_parse_endpoint(struct device *dev, * 2) While removing the target device via * coresight_remove_match() */ - conn->child_fwnode = fwnode_handle_get(rdev_fwnode); - conn->child_port = rendpoint.port; + conn.dest_fwnode = fwnode_handle_get(rdev_fwnode); + conn.dest_port = rendpoint.port; + + new_conn = coresight_add_out_conn(dev, pdata, &conn); + if (IS_ERR_VALUE(new_conn)) { + fwnode_handle_put(conn.dest_fwnode); + return PTR_ERR(new_conn); + } /* Connection record updated */ } while (0); @@ -288,17 +269,6 @@ static int of_get_coresight_platform_data(struct device *dev, bool legacy_binding = false; struct device_node *node = dev->of_node; - /* Get the number of input and output port for this component */ - of_coresight_get_ports(node, &pdata->nr_inport, &pdata->nr_outport); - - /* If there are no output connections, we are done */ - if (!pdata->nr_outport) - return 0; - - ret = coresight_alloc_conns(dev, pdata); - if (ret) - return ret; - parent = of_coresight_get_output_ports_node(node); /* * If the DT uses obsoleted bindings, the ports are listed @@ -306,6 +276,12 @@ static int of_get_coresight_platform_data(struct device *dev, * ports. */ if (!parent) { + /* + * Avoid warnings in of_graph_get_next_endpoint() + * if the device doesn't have any graph connections + */ + if (!of_graph_is_present(node)) + return 0; legacy_binding = true; parent = node; dev_warn_once(dev, "Uses obsolete Coresight DT bindings\n"); @@ -649,8 +625,8 @@ static int acpi_coresight_parse_link(struct acpi_device *adev, dir = fields[3].integer.value; if (dir == ACPI_CORESIGHT_LINK_MASTER) { - conn->outport = fields[0].integer.value; - conn->child_port = fields[1].integer.value; + conn->src_port = fields[0].integer.value; + conn->dest_port = fields[1].integer.value; rdev = coresight_find_device_by_fwnode(&r_adev->fwnode); if (!rdev) return -EPROBE_DEFER; @@ -662,14 +638,14 @@ static int acpi_coresight_parse_link(struct acpi_device *adev, * 2) While removing the target device via * coresight_remove_match(). */ - conn->child_fwnode = fwnode_handle_get(&r_adev->fwnode); + conn->dest_fwnode = fwnode_handle_get(&r_adev->fwnode); } else if (dir == ACPI_CORESIGHT_LINK_SLAVE) { /* * We are only interested in the port number * for the input ports at this component. * Store the port number in child_port. */ - conn->child_port = fields[0].integer.value; + conn->dest_port = fields[0].integer.value; } else { /* Invalid direction */ return -EINVAL; @@ -683,14 +659,15 @@ static int acpi_coresight_parse_link(struct acpi_device *adev, * connection information and populate the supplied coresight_platform_data * instance. */ -static int acpi_coresight_parse_graph(struct acpi_device *adev, +static int acpi_coresight_parse_graph(struct device *dev, + struct acpi_device *adev, struct coresight_platform_data *pdata) { - int rc, i, nlinks; + int i, nlinks; const union acpi_object *graph; - struct coresight_connection *conns, *ptr; + struct coresight_connection conn, zero_conn = {}; + struct coresight_connection *new_conn; - pdata->nr_inport = pdata->nr_outport = 0; graph = acpi_get_coresight_graph(adev); if (!graph) return -ENOENT; @@ -699,56 +676,22 @@ static int acpi_coresight_parse_graph(struct acpi_device *adev, if (!nlinks) return 0; - /* - * To avoid scanning the table twice (once for finding the number of - * output links and then later for parsing the output links), - * cache the links information in one go and then later copy - * it to the pdata. - */ - conns = devm_kcalloc(&adev->dev, nlinks, sizeof(*conns), GFP_KERNEL); - if (!conns) - return -ENOMEM; - ptr = conns; for (i = 0; i < nlinks; i++) { const union acpi_object *link = &graph->package.elements[3 + i]; int dir; - dir = acpi_coresight_parse_link(adev, link, ptr); + conn = zero_conn; + dir = acpi_coresight_parse_link(adev, link, &conn); if (dir < 0) return dir; if (dir == ACPI_CORESIGHT_LINK_MASTER) { - if (ptr->outport >= pdata->nr_outport) - pdata->nr_outport = ptr->outport + 1; - ptr++; - } else { - WARN_ON(pdata->nr_inport == ptr->child_port + 1); - /* - * We do not track input port connections for a device. - * However we need the highest port number described, - * which can be recorded now and reuse this connection - * record for an output connection. Hence, do not move - * the ptr for input connections - */ - if (ptr->child_port >= pdata->nr_inport) - pdata->nr_inport = ptr->child_port + 1; + new_conn = coresight_add_out_conn(dev, pdata, &conn); + if (IS_ERR(new_conn)) + return PTR_ERR(new_conn); } } - rc = coresight_alloc_conns(&adev->dev, pdata); - if (rc) - return rc; - - /* Copy the connection information to the final location */ - for (i = 0; conns + i < ptr; i++) { - int port = conns[i].outport; - - /* Duplicate output port */ - WARN_ON(pdata->conns[port].child_fwnode); - pdata->conns[port] = conns[i]; - } - - devm_kfree(&adev->dev, conns); return 0; } @@ -809,7 +752,7 @@ acpi_get_coresight_platform_data(struct device *dev, if (!adev) return -EINVAL; - return acpi_coresight_parse_graph(adev, pdata); + return acpi_coresight_parse_graph(dev, adev, pdata); } #else @@ -863,7 +806,7 @@ coresight_get_platform_data(struct device *dev) error: if (!IS_ERR_OR_NULL(pdata)) /* Cleanup the connection information */ - coresight_release_platform_data(NULL, pdata); + coresight_release_platform_data(NULL, dev, pdata); return ERR_PTR(ret); } EXPORT_SYMBOL_GPL(coresight_get_platform_data); diff --git a/drivers/hwtracing/coresight/coresight-priv.h b/drivers/hwtracing/coresight/coresight-priv.h index 595ce58620567226c77e0600d5a2164e1e6e07ce..767076e07970117c890af346a48b8246ce92a246 100644 --- a/drivers/hwtracing/coresight/coresight-priv.h +++ b/drivers/hwtracing/coresight/coresight-priv.h @@ -82,12 +82,6 @@ enum etm_addr_type { ETM_ADDR_TYPE_STOP, }; -enum cs_mode { - CS_MODE_DISABLED, - CS_MODE_SYSFS, - CS_MODE_PERF, -}; - /** * struct cs_buffer - keep track of a recording session' specifics * @cur: index of the current buffer @@ -133,7 +127,8 @@ static inline void CS_UNLOCK(void __iomem *addr) } void coresight_disable_path(struct list_head *path); -int coresight_enable_path(struct list_head *path, u32 mode, void *sink_data); +int coresight_enable_path(struct list_head *path, enum cs_mode mode, + void *sink_data); struct coresight_device *coresight_get_sink(struct list_head *path); struct coresight_device * coresight_get_enabled_sink(struct coresight_device *source); @@ -193,12 +188,27 @@ extern void coresight_remove_cti_ops(void); } /* coresight AMBA ID, full UCI structure: id table entry. */ -#define CS_AMBA_UCI_ID(pid, uci_ptr) \ +#define __CS_AMBA_UCI_ID(pid, m, uci_ptr) \ { \ .id = pid, \ - .mask = 0x000fffff, \ + .mask = m, \ .data = (void *)uci_ptr \ } +#define CS_AMBA_UCI_ID(pid, uci) __CS_AMBA_UCI_ID(pid, 0x000fffff, uci) +/* + * PIDR2[JEDEC], BIT(3) must be 1 (Read As One) to indicate that rest of the + * PIDR1, PIDR2 DES_* fields follow JEDEC encoding for the designer. Use that + * as a match value for blanket matching all devices in the given CoreSight + * device type and architecture. + */ +#define PIDR2_JEDEC BIT(3) +#define PID_PIDR2_JEDEC (PIDR2_JEDEC << 16) +/* + * Match all PIDs in a given CoreSight device type and architecture, defined + * by the uci. + */ +#define CS_AMBA_MATCH_ALL_UCI(uci) \ + __CS_AMBA_UCI_ID(PID_PIDR2_JEDEC, PID_PIDR2_JEDEC, uci) /* extract the data value from a UCI structure given amba_id pointer. */ static inline void *coresight_get_uci_data(const struct amba_id *id) @@ -212,13 +222,17 @@ static inline void *coresight_get_uci_data(const struct amba_id *id) } void coresight_release_platform_data(struct coresight_device *csdev, + struct device *dev, struct coresight_platform_data *pdata); struct coresight_device * coresight_find_csdev_by_fwnode(struct fwnode_handle *r_fwnode); -void coresight_set_assoc_ectdev_mutex(struct coresight_device *csdev, - struct coresight_device *ect_csdev); +void coresight_add_helper(struct coresight_device *csdev, + struct coresight_device *helper); void coresight_set_percpu_sink(int cpu, struct coresight_device *csdev); struct coresight_device *coresight_get_percpu_sink(int cpu); +int coresight_enable_source(struct coresight_device *csdev, enum cs_mode mode, + void *data); +bool coresight_disable_source(struct coresight_device *csdev, void *data); #endif diff --git a/drivers/hwtracing/coresight/coresight-replicator.c b/drivers/hwtracing/coresight/coresight-replicator.c index 4dd50546d7e4376ef1e35d18d3d3e40807621619..b6be730349968a4218b348b9684a8d220518cdcc 100644 --- a/drivers/hwtracing/coresight/coresight-replicator.c +++ b/drivers/hwtracing/coresight/coresight-replicator.c @@ -114,8 +114,9 @@ static int dynamic_replicator_enable(struct replicator_drvdata *drvdata, return rc; } -static int replicator_enable(struct coresight_device *csdev, int inport, - int outport) +static int replicator_enable(struct coresight_device *csdev, + struct coresight_connection *in, + struct coresight_connection *out) { int rc = 0; struct replicator_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); @@ -123,15 +124,15 @@ static int replicator_enable(struct coresight_device *csdev, int inport, bool first_enable = false; spin_lock_irqsave(&drvdata->spinlock, flags); - if (atomic_read(&csdev->refcnt[outport]) == 0) { + if (atomic_read(&out->src_refcnt) == 0) { if (drvdata->base) - rc = dynamic_replicator_enable(drvdata, inport, - outport); + rc = dynamic_replicator_enable(drvdata, in->dest_port, + out->src_port); if (!rc) first_enable = true; } if (!rc) - atomic_inc(&csdev->refcnt[outport]); + atomic_inc(&out->src_refcnt); spin_unlock_irqrestore(&drvdata->spinlock, flags); if (first_enable) @@ -168,17 +169,19 @@ static void dynamic_replicator_disable(struct replicator_drvdata *drvdata, CS_LOCK(drvdata->base); } -static void replicator_disable(struct coresight_device *csdev, int inport, - int outport) +static void replicator_disable(struct coresight_device *csdev, + struct coresight_connection *in, + struct coresight_connection *out) { struct replicator_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); unsigned long flags; bool last_disable = false; spin_lock_irqsave(&drvdata->spinlock, flags); - if (atomic_dec_return(&csdev->refcnt[outport]) == 0) { + if (atomic_dec_return(&out->src_refcnt) == 0) { if (drvdata->base) - dynamic_replicator_disable(drvdata, inport, outport); + dynamic_replicator_disable(drvdata, in->dest_port, + out->src_port); last_disable = true; } spin_unlock_irqrestore(&drvdata->spinlock, flags); diff --git a/drivers/hwtracing/coresight/coresight-stm.c b/drivers/hwtracing/coresight/coresight-stm.c index 66a614c5492c99699f11add12aaa78d659fcb1fb..a1c27c901ad17bb26af078f0628e315716f29142 100644 --- a/drivers/hwtracing/coresight/coresight-stm.c +++ b/drivers/hwtracing/coresight/coresight-stm.c @@ -119,7 +119,7 @@ DEFINE_CORESIGHT_DEVLIST(stm_devs, "stm"); * @spinlock: only one at a time pls. * @chs: the channels accociated to this STM. * @stm: structure associated to the generic STM interface. - * @mode: this tracer's mode, i.e sysFS, or disabled. + * @mode: this tracer's mode (enum cs_mode), i.e sysFS, or disabled. * @traceid: value of the current ID for this component. * @write_bytes: Maximus bytes this STM can write at a time. * @stmsper: settings for register STMSPER. @@ -192,8 +192,8 @@ static void stm_enable_hw(struct stm_drvdata *drvdata) CS_LOCK(drvdata->base); } -static int stm_enable(struct coresight_device *csdev, - struct perf_event *event, u32 mode) +static int stm_enable(struct coresight_device *csdev, struct perf_event *event, + enum cs_mode mode) { u32 val; struct stm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); diff --git a/drivers/hwtracing/coresight/coresight-sysfs.c b/drivers/hwtracing/coresight/coresight-sysfs.c index 34d2a2d31d003b0468c0b8715338c3e9dcf7c1ae..dd78e9fcfc4dc991c0651e620187c8746068a325 100644 --- a/drivers/hwtracing/coresight/coresight-sysfs.c +++ b/drivers/hwtracing/coresight/coresight-sysfs.c @@ -148,13 +148,17 @@ int coresight_make_links(struct coresight_device *orig, char *outs = NULL, *ins = NULL; struct coresight_sysfs_link *link = NULL; + /* Helper devices aren't shown in sysfs */ + if (conn->dest_port == -1 && conn->src_port == -1) + return 0; + do { outs = devm_kasprintf(&orig->dev, GFP_KERNEL, - "out:%d", conn->outport); + "out:%d", conn->src_port); if (!outs) break; ins = devm_kasprintf(&target->dev, GFP_KERNEL, - "in:%d", conn->child_port); + "in:%d", conn->dest_port); if (!ins) break; link = devm_kzalloc(&orig->dev, @@ -173,12 +177,6 @@ int coresight_make_links(struct coresight_device *orig, break; conn->link = link; - - /* - * Install the device connection. This also indicates that - * the links are operational on both ends. - */ - conn->child_dev = target; return 0; } while (0); @@ -198,9 +196,8 @@ void coresight_remove_links(struct coresight_device *orig, coresight_remove_sysfs_link(conn->link); - devm_kfree(&conn->child_dev->dev, conn->link->target_name); + devm_kfree(&conn->dest_dev->dev, conn->link->target_name); devm_kfree(&orig->dev, conn->link->orig_name); devm_kfree(&orig->dev, conn->link); conn->link = NULL; - conn->child_dev = NULL; } diff --git a/drivers/hwtracing/coresight/coresight-tmc-etf.c b/drivers/hwtracing/coresight/coresight-tmc-etf.c index 0ab1f73c2d06a56becefd29f56d5ce693c8275e8..79d8c64eac4947385741345337335d42d238014c 100644 --- a/drivers/hwtracing/coresight/coresight-tmc-etf.c +++ b/drivers/hwtracing/coresight/coresight-tmc-etf.c @@ -206,7 +206,7 @@ static int tmc_enable_etf_sink_sysfs(struct coresight_device *csdev) * touched. */ if (drvdata->mode == CS_MODE_SYSFS) { - atomic_inc(csdev->refcnt); + atomic_inc(&csdev->refcnt); goto out; } @@ -229,7 +229,7 @@ static int tmc_enable_etf_sink_sysfs(struct coresight_device *csdev) ret = tmc_etb_enable_hw(drvdata); if (!ret) { drvdata->mode = CS_MODE_SYSFS; - atomic_inc(csdev->refcnt); + atomic_inc(&csdev->refcnt); } else { /* Free up the buffer if we failed to enable */ used = false; @@ -284,7 +284,7 @@ static int tmc_enable_etf_sink_perf(struct coresight_device *csdev, void *data) * use for this session. */ if (drvdata->pid == pid) { - atomic_inc(csdev->refcnt); + atomic_inc(&csdev->refcnt); break; } @@ -293,7 +293,7 @@ static int tmc_enable_etf_sink_perf(struct coresight_device *csdev, void *data) /* Associate with monitored process. */ drvdata->pid = pid; drvdata->mode = CS_MODE_PERF; - atomic_inc(csdev->refcnt); + atomic_inc(&csdev->refcnt); } } while (0); spin_unlock_irqrestore(&drvdata->spinlock, flags); @@ -302,7 +302,7 @@ static int tmc_enable_etf_sink_perf(struct coresight_device *csdev, void *data) } static int tmc_enable_etf_sink(struct coresight_device *csdev, - u32 mode, void *data) + enum cs_mode mode, void *data) { int ret; @@ -338,7 +338,7 @@ static int tmc_disable_etf_sink(struct coresight_device *csdev) return -EBUSY; } - if (atomic_dec_return(csdev->refcnt)) { + if (atomic_dec_return(&csdev->refcnt)) { spin_unlock_irqrestore(&drvdata->spinlock, flags); return -EBUSY; } @@ -357,7 +357,8 @@ static int tmc_disable_etf_sink(struct coresight_device *csdev) } static int tmc_enable_etf_link(struct coresight_device *csdev, - int inport, int outport) + struct coresight_connection *in, + struct coresight_connection *out) { int ret = 0; unsigned long flags; @@ -370,7 +371,7 @@ static int tmc_enable_etf_link(struct coresight_device *csdev, return -EBUSY; } - if (atomic_read(&csdev->refcnt[0]) == 0) { + if (atomic_read(&csdev->refcnt) == 0) { ret = tmc_etf_enable_hw(drvdata); if (!ret) { drvdata->mode = CS_MODE_SYSFS; @@ -378,7 +379,7 @@ static int tmc_enable_etf_link(struct coresight_device *csdev, } } if (!ret) - atomic_inc(&csdev->refcnt[0]); + atomic_inc(&csdev->refcnt); spin_unlock_irqrestore(&drvdata->spinlock, flags); if (first_enable) @@ -387,7 +388,8 @@ static int tmc_enable_etf_link(struct coresight_device *csdev, } static void tmc_disable_etf_link(struct coresight_device *csdev, - int inport, int outport) + struct coresight_connection *in, + struct coresight_connection *out) { unsigned long flags; struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); @@ -399,7 +401,7 @@ static void tmc_disable_etf_link(struct coresight_device *csdev, return; } - if (atomic_dec_return(&csdev->refcnt[0]) == 0) { + if (atomic_dec_return(&csdev->refcnt) == 0) { tmc_etf_disable_hw(drvdata); drvdata->mode = CS_MODE_DISABLED; last_disable = true; @@ -487,7 +489,7 @@ static unsigned long tmc_update_etf_buffer(struct coresight_device *csdev, spin_lock_irqsave(&drvdata->spinlock, flags); /* Don't do anything if another tracer is using this sink */ - if (atomic_read(csdev->refcnt) != 1) + if (atomic_read(&csdev->refcnt) != 1) goto out; CS_UNLOCK(drvdata->base); diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c index eaa296ced167893770a3695a1e9b8fb24098d861..766325de0e29bdb0b83a332a1195149eadc284c1 100644 --- a/drivers/hwtracing/coresight/coresight-tmc-etr.c +++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c @@ -775,40 +775,19 @@ static const struct etr_buf_operations etr_sg_buf_ops = { struct coresight_device * tmc_etr_get_catu_device(struct tmc_drvdata *drvdata) { - int i; - struct coresight_device *tmp, *etr = drvdata->csdev; + struct coresight_device *etr = drvdata->csdev; + union coresight_dev_subtype catu_subtype = { + .helper_subtype = CORESIGHT_DEV_SUBTYPE_HELPER_CATU + }; if (!IS_ENABLED(CONFIG_CORESIGHT_CATU)) return NULL; - for (i = 0; i < etr->pdata->nr_outport; i++) { - tmp = etr->pdata->conns[i].child_dev; - if (tmp && coresight_is_catu_device(tmp)) - return tmp; - } - - return NULL; + return coresight_find_output_type(etr->pdata, CORESIGHT_DEV_TYPE_HELPER, + catu_subtype); } EXPORT_SYMBOL_GPL(tmc_etr_get_catu_device); -static inline int tmc_etr_enable_catu(struct tmc_drvdata *drvdata, - struct etr_buf *etr_buf) -{ - struct coresight_device *catu = tmc_etr_get_catu_device(drvdata); - - if (catu && helper_ops(catu)->enable) - return helper_ops(catu)->enable(catu, etr_buf); - return 0; -} - -static inline void tmc_etr_disable_catu(struct tmc_drvdata *drvdata) -{ - struct coresight_device *catu = tmc_etr_get_catu_device(drvdata); - - if (catu && helper_ops(catu)->disable) - helper_ops(catu)->disable(catu, drvdata->etr_buf); -} - static const struct etr_buf_operations *etr_buf_ops[] = { [ETR_MODE_FLAT] = &etr_flat_buf_ops, [ETR_MODE_ETR_SG] = &etr_sg_buf_ops, @@ -1058,13 +1037,6 @@ static int tmc_etr_enable_hw(struct tmc_drvdata *drvdata, if (WARN_ON(drvdata->etr_buf)) return -EBUSY; - /* - * If this ETR is connected to a CATU, enable it before we turn - * this on. - */ - rc = tmc_etr_enable_catu(drvdata, etr_buf); - if (rc) - return rc; rc = coresight_claim_device(drvdata->csdev); if (!rc) { drvdata->etr_buf = etr_buf; @@ -1072,7 +1044,6 @@ static int tmc_etr_enable_hw(struct tmc_drvdata *drvdata, if (rc) { drvdata->etr_buf = NULL; coresight_disclaim_device(drvdata->csdev); - tmc_etr_disable_catu(drvdata); } } @@ -1162,14 +1133,12 @@ static void __tmc_etr_disable_hw(struct tmc_drvdata *drvdata) void tmc_etr_disable_hw(struct tmc_drvdata *drvdata) { __tmc_etr_disable_hw(drvdata); - /* Disable CATU device if this ETR is connected to one */ - tmc_etr_disable_catu(drvdata); coresight_disclaim_device(drvdata->csdev); /* Reset the ETR buf used by hardware */ drvdata->etr_buf = NULL; } -static int tmc_enable_etr_sink_sysfs(struct coresight_device *csdev) +static struct etr_buf *tmc_etr_get_sysfs_buffer(struct coresight_device *csdev) { int ret = 0; unsigned long flags; @@ -1192,7 +1161,7 @@ static int tmc_enable_etr_sink_sysfs(struct coresight_device *csdev) /* Allocate memory with the locks released */ free_buf = new_buf = tmc_etr_setup_sysfs_buf(drvdata); if (IS_ERR(new_buf)) - return PTR_ERR(new_buf); + return new_buf; /* Let's try again */ spin_lock_irqsave(&drvdata->spinlock, flags); @@ -1209,7 +1178,7 @@ static int tmc_enable_etr_sink_sysfs(struct coresight_device *csdev) * touched, even if the buffer size has changed. */ if (drvdata->mode == CS_MODE_SYSFS) { - atomic_inc(csdev->refcnt); + atomic_inc(&csdev->refcnt); goto out; } @@ -1223,17 +1192,33 @@ static int tmc_enable_etr_sink_sysfs(struct coresight_device *csdev) drvdata->sysfs_buf = new_buf; } - ret = tmc_etr_enable_hw(drvdata, drvdata->sysfs_buf); - if (!ret) { - drvdata->mode = CS_MODE_SYSFS; - atomic_inc(csdev->refcnt); - } out: spin_unlock_irqrestore(&drvdata->spinlock, flags); /* Free memory outside the spinlock if need be */ if (free_buf) tmc_etr_free_sysfs_buf(free_buf); + return ret ? ERR_PTR(ret) : drvdata->sysfs_buf; +} + +static int tmc_enable_etr_sink_sysfs(struct coresight_device *csdev) +{ + int ret; + unsigned long flags; + struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); + struct etr_buf *sysfs_buf = tmc_etr_get_sysfs_buffer(csdev); + + if (IS_ERR(sysfs_buf)) + return PTR_ERR(sysfs_buf); + + spin_lock_irqsave(&drvdata->spinlock, flags); + ret = tmc_etr_enable_hw(drvdata, sysfs_buf); + if (!ret) { + drvdata->mode = CS_MODE_SYSFS; + atomic_inc(&csdev->refcnt); + } + + spin_unlock_irqrestore(&drvdata->spinlock, flags); if (!ret) dev_dbg(&csdev->dev, "TMC-ETR enabled\n"); @@ -1241,6 +1226,26 @@ static int tmc_enable_etr_sink_sysfs(struct coresight_device *csdev) return ret; } +struct etr_buf *tmc_etr_get_buffer(struct coresight_device *csdev, + enum cs_mode mode, void *data) +{ + struct perf_output_handle *handle = data; + struct etr_perf_buffer *etr_perf; + + switch (mode) { + case CS_MODE_SYSFS: + return tmc_etr_get_sysfs_buffer(csdev); + case CS_MODE_PERF: + etr_perf = etm_perf_sink_config(handle); + if (WARN_ON(!etr_perf || !etr_perf->etr_buf)) + return ERR_PTR(-EINVAL); + return etr_perf->etr_buf; + default: + return ERR_PTR(-EINVAL); + } +} +EXPORT_SYMBOL_GPL(tmc_etr_get_buffer); + /* * alloc_etr_buf: Allocate ETR buffer for use by perf. * The size of the hardware buffer is dependent on the size configured @@ -1535,7 +1540,7 @@ tmc_update_etr_buffer(struct coresight_device *csdev, spin_lock_irqsave(&drvdata->spinlock, flags); /* Don't do anything if another tracer is using this sink */ - if (atomic_read(csdev->refcnt) != 1) { + if (atomic_read(&csdev->refcnt) != 1) { spin_unlock_irqrestore(&drvdata->spinlock, flags); goto out; } @@ -1647,7 +1652,7 @@ static int tmc_enable_etr_sink_perf(struct coresight_device *csdev, void *data) * use for this session. */ if (drvdata->pid == pid) { - atomic_inc(csdev->refcnt); + atomic_inc(&csdev->refcnt); goto unlock_out; } @@ -1657,7 +1662,7 @@ static int tmc_enable_etr_sink_perf(struct coresight_device *csdev, void *data) drvdata->pid = pid; drvdata->mode = CS_MODE_PERF; drvdata->perf_buf = etr_perf->etr_buf; - atomic_inc(csdev->refcnt); + atomic_inc(&csdev->refcnt); } unlock_out: @@ -1666,17 +1671,16 @@ static int tmc_enable_etr_sink_perf(struct coresight_device *csdev, void *data) } static int tmc_enable_etr_sink(struct coresight_device *csdev, - u32 mode, void *data) + enum cs_mode mode, void *data) { switch (mode) { case CS_MODE_SYSFS: return tmc_enable_etr_sink_sysfs(csdev); case CS_MODE_PERF: return tmc_enable_etr_sink_perf(csdev, data); + default: + return -EINVAL; } - - /* We shouldn't be here */ - return -EINVAL; } static int tmc_disable_etr_sink(struct coresight_device *csdev) @@ -1691,7 +1695,7 @@ static int tmc_disable_etr_sink(struct coresight_device *csdev) return -EBUSY; } - if (atomic_dec_return(csdev->refcnt)) { + if (atomic_dec_return(&csdev->refcnt)) { spin_unlock_irqrestore(&drvdata->spinlock, flags); return -EBUSY; } diff --git a/drivers/hwtracing/coresight/coresight-tmc.h b/drivers/hwtracing/coresight/coresight-tmc.h index 01c0382a29c0a9808c317ae4d2f2d83b1ab1b85f..b97da39652d26dd205a2ac844bc6b8894bfcd4f9 100644 --- a/drivers/hwtracing/coresight/coresight-tmc.h +++ b/drivers/hwtracing/coresight/coresight-tmc.h @@ -332,5 +332,7 @@ struct coresight_device *tmc_etr_get_catu_device(struct tmc_drvdata *drvdata); void tmc_etr_set_catu_ops(const struct etr_buf_operations *catu); void tmc_etr_remove_catu_ops(void); +struct etr_buf *tmc_etr_get_buffer(struct coresight_device *csdev, + enum cs_mode mode, void *data); #endif diff --git a/drivers/hwtracing/coresight/coresight-tpda.c b/drivers/hwtracing/coresight/coresight-tpda.c index f712e112ecff23a8b7b72446f2024237761ceffc..8d2b9d29237d47323515c54dc017dc0e20ca8d85 100644 --- a/drivers/hwtracing/coresight/coresight-tpda.c +++ b/drivers/hwtracing/coresight/coresight-tpda.c @@ -54,18 +54,20 @@ static void __tpda_enable(struct tpda_drvdata *drvdata, int port) CS_LOCK(drvdata->base); } -static int tpda_enable(struct coresight_device *csdev, int inport, int outport) +static int tpda_enable(struct coresight_device *csdev, + struct coresight_connection *in, + struct coresight_connection *out) { struct tpda_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); spin_lock(&drvdata->spinlock); - if (atomic_read(&csdev->refcnt[inport]) == 0) - __tpda_enable(drvdata, inport); + if (atomic_read(&in->dest_refcnt) == 0) + __tpda_enable(drvdata, in->dest_port); - atomic_inc(&csdev->refcnt[inport]); + atomic_inc(&in->dest_refcnt); spin_unlock(&drvdata->spinlock); - dev_dbg(drvdata->dev, "TPDA inport %d enabled.\n", inport); + dev_dbg(drvdata->dev, "TPDA inport %d enabled.\n", in->dest_port); return 0; } @@ -82,18 +84,19 @@ static void __tpda_disable(struct tpda_drvdata *drvdata, int port) CS_LOCK(drvdata->base); } -static void tpda_disable(struct coresight_device *csdev, int inport, - int outport) +static void tpda_disable(struct coresight_device *csdev, + struct coresight_connection *in, + struct coresight_connection *out) { struct tpda_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); spin_lock(&drvdata->spinlock); - if (atomic_dec_return(&csdev->refcnt[inport]) == 0) - __tpda_disable(drvdata, inport); + if (atomic_dec_return(&in->dest_refcnt) == 0) + __tpda_disable(drvdata, in->dest_port); spin_unlock(&drvdata->spinlock); - dev_dbg(drvdata->dev, "TPDA inport %d disabled\n", inport); + dev_dbg(drvdata->dev, "TPDA inport %d disabled\n", in->dest_port); } static const struct coresight_ops_link tpda_link_ops = { diff --git a/drivers/hwtracing/coresight/coresight-tpdm.c b/drivers/hwtracing/coresight/coresight-tpdm.c index 9479a5e8c6721d032da51b754b81ec7357067878..f4854af0431e11069ec521311fd1225e53490174 100644 --- a/drivers/hwtracing/coresight/coresight-tpdm.c +++ b/drivers/hwtracing/coresight/coresight-tpdm.c @@ -42,8 +42,8 @@ static void __tpdm_enable(struct tpdm_drvdata *drvdata) CS_LOCK(drvdata->base); } -static int tpdm_enable(struct coresight_device *csdev, - struct perf_event *event, u32 mode) +static int tpdm_enable(struct coresight_device *csdev, struct perf_event *event, + enum cs_mode mode) { struct tpdm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); diff --git a/drivers/hwtracing/coresight/coresight-tpiu.c b/drivers/hwtracing/coresight/coresight-tpiu.c index 34d37abd2c8de1481d7d9d55522345684a512701..59eac93fd6bb9eb6ce1fdb7fa83beaf0bf36cab4 100644 --- a/drivers/hwtracing/coresight/coresight-tpiu.c +++ b/drivers/hwtracing/coresight/coresight-tpiu.c @@ -69,10 +69,11 @@ static void tpiu_enable_hw(struct csdev_access *csa) CS_LOCK(csa->base); } -static int tpiu_enable(struct coresight_device *csdev, u32 mode, void *__unused) +static int tpiu_enable(struct coresight_device *csdev, enum cs_mode mode, + void *__unused) { tpiu_enable_hw(&csdev->access); - atomic_inc(csdev->refcnt); + atomic_inc(&csdev->refcnt); dev_dbg(&csdev->dev, "TPIU enabled\n"); return 0; } @@ -95,7 +96,7 @@ static void tpiu_disable_hw(struct csdev_access *csa) static int tpiu_disable(struct coresight_device *csdev) { - if (atomic_dec_return(csdev->refcnt)) + if (atomic_dec_return(&csdev->refcnt)) return -EBUSY; tpiu_disable_hw(&csdev->access); diff --git a/drivers/hwtracing/coresight/coresight-trbe.c b/drivers/hwtracing/coresight/coresight-trbe.c index 1fc4fd79a1c69c7a094f47acebb8f91ba9adffab..7720619909d65caa0a3e126df925afcac4be88b8 100644 --- a/drivers/hwtracing/coresight/coresight-trbe.c +++ b/drivers/hwtracing/coresight/coresight-trbe.c @@ -218,7 +218,7 @@ static inline void set_trbe_enabled(struct trbe_cpudata *cpudata, u64 trblimitr) * Enable the TRBE without clearing LIMITPTR which * might be required for fetching the buffer limits. */ - trblimitr |= TRBLIMITR_ENABLE; + trblimitr |= TRBLIMITR_EL1_E; write_sysreg_s(trblimitr, SYS_TRBLIMITR_EL1); /* Synchronize the TRBE enable event */ @@ -236,7 +236,7 @@ static inline void set_trbe_disabled(struct trbe_cpudata *cpudata) * Disable the TRBE without clearing LIMITPTR which * might be required for fetching the buffer limits. */ - trblimitr &= ~TRBLIMITR_ENABLE; + trblimitr &= ~TRBLIMITR_EL1_E; write_sysreg_s(trblimitr, SYS_TRBLIMITR_EL1); if (trbe_needs_drain_after_disable(cpudata)) @@ -582,12 +582,12 @@ static void clr_trbe_status(void) u64 trbsr = read_sysreg_s(SYS_TRBSR_EL1); WARN_ON(is_trbe_enabled()); - trbsr &= ~TRBSR_IRQ; - trbsr &= ~TRBSR_TRG; - trbsr &= ~TRBSR_WRAP; - trbsr &= ~(TRBSR_EC_MASK << TRBSR_EC_SHIFT); - trbsr &= ~(TRBSR_BSC_MASK << TRBSR_BSC_SHIFT); - trbsr &= ~TRBSR_STOP; + trbsr &= ~TRBSR_EL1_IRQ; + trbsr &= ~TRBSR_EL1_TRG; + trbsr &= ~TRBSR_EL1_WRAP; + trbsr &= ~TRBSR_EL1_EC_MASK; + trbsr &= ~TRBSR_EL1_BSC_MASK; + trbsr &= ~TRBSR_EL1_S; write_sysreg_s(trbsr, SYS_TRBSR_EL1); } @@ -596,13 +596,13 @@ static void set_trbe_limit_pointer_enabled(struct trbe_buf *buf) u64 trblimitr = read_sysreg_s(SYS_TRBLIMITR_EL1); unsigned long addr = buf->trbe_limit; - WARN_ON(!IS_ALIGNED(addr, (1UL << TRBLIMITR_LIMIT_SHIFT))); + WARN_ON(!IS_ALIGNED(addr, (1UL << TRBLIMITR_EL1_LIMIT_SHIFT))); WARN_ON(!IS_ALIGNED(addr, PAGE_SIZE)); - trblimitr &= ~TRBLIMITR_NVM; - trblimitr &= ~(TRBLIMITR_FILL_MODE_MASK << TRBLIMITR_FILL_MODE_SHIFT); - trblimitr &= ~(TRBLIMITR_TRIG_MODE_MASK << TRBLIMITR_TRIG_MODE_SHIFT); - trblimitr &= ~(TRBLIMITR_LIMIT_MASK << TRBLIMITR_LIMIT_SHIFT); + trblimitr &= ~TRBLIMITR_EL1_nVM; + trblimitr &= ~TRBLIMITR_EL1_FM_MASK; + trblimitr &= ~TRBLIMITR_EL1_TM_MASK; + trblimitr &= ~TRBLIMITR_EL1_LIMIT_MASK; /* * Fill trace buffer mode is used here while configuring the @@ -613,14 +613,15 @@ static void set_trbe_limit_pointer_enabled(struct trbe_buf *buf) * trace data in the interrupt handler, before reconfiguring * the TRBE. */ - trblimitr |= (TRBE_FILL_MODE_FILL & TRBLIMITR_FILL_MODE_MASK) << TRBLIMITR_FILL_MODE_SHIFT; + trblimitr |= (TRBLIMITR_EL1_FM_FILL << TRBLIMITR_EL1_FM_SHIFT) & + TRBLIMITR_EL1_FM_MASK; /* * Trigger mode is not used here while configuring the TRBE for * the trace capture. Hence just keep this in the ignore mode. */ - trblimitr |= (TRBE_TRIG_MODE_IGNORE & TRBLIMITR_TRIG_MODE_MASK) << - TRBLIMITR_TRIG_MODE_SHIFT; + trblimitr |= (TRBLIMITR_EL1_TM_IGNR << TRBLIMITR_EL1_TM_SHIFT) & + TRBLIMITR_EL1_TM_MASK; trblimitr |= (addr & PAGE_MASK); set_trbe_enabled(buf->cpudata, trblimitr); } @@ -1005,7 +1006,8 @@ static int __arm_trbe_enable(struct trbe_buf *buf, return ret; } -static int arm_trbe_enable(struct coresight_device *csdev, u32 mode, void *data) +static int arm_trbe_enable(struct coresight_device *csdev, enum cs_mode mode, + void *data) { struct trbe_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); struct trbe_cpudata *cpudata = dev_get_drvdata(&csdev->dev); diff --git a/drivers/hwtracing/coresight/coresight-trbe.h b/drivers/hwtracing/coresight/coresight-trbe.h index 98ff1b17ad079d333f5285d21074fbef1a683941..77cbb5c6387833a3892112fc9a6aa3b778a62713 100644 --- a/drivers/hwtracing/coresight/coresight-trbe.h +++ b/drivers/hwtracing/coresight/coresight-trbe.h @@ -30,7 +30,7 @@ static inline bool is_trbe_enabled(void) { u64 trblimitr = read_sysreg_s(SYS_TRBLIMITR_EL1); - return trblimitr & TRBLIMITR_ENABLE; + return trblimitr & TRBLIMITR_EL1_E; } #define TRBE_EC_OTHERS 0 @@ -39,7 +39,7 @@ static inline bool is_trbe_enabled(void) static inline int get_trbe_ec(u64 trbsr) { - return (trbsr >> TRBSR_EC_SHIFT) & TRBSR_EC_MASK; + return (trbsr & TRBSR_EL1_EC_MASK) >> TRBSR_EL1_EC_SHIFT; } #define TRBE_BSC_NOT_STOPPED 0 @@ -48,63 +48,55 @@ static inline int get_trbe_ec(u64 trbsr) static inline int get_trbe_bsc(u64 trbsr) { - return (trbsr >> TRBSR_BSC_SHIFT) & TRBSR_BSC_MASK; + return (trbsr & TRBSR_EL1_BSC_MASK) >> TRBSR_EL1_BSC_SHIFT; } static inline void clr_trbe_irq(void) { u64 trbsr = read_sysreg_s(SYS_TRBSR_EL1); - trbsr &= ~TRBSR_IRQ; + trbsr &= ~TRBSR_EL1_IRQ; write_sysreg_s(trbsr, SYS_TRBSR_EL1); } static inline bool is_trbe_irq(u64 trbsr) { - return trbsr & TRBSR_IRQ; + return trbsr & TRBSR_EL1_IRQ; } static inline bool is_trbe_trg(u64 trbsr) { - return trbsr & TRBSR_TRG; + return trbsr & TRBSR_EL1_TRG; } static inline bool is_trbe_wrap(u64 trbsr) { - return trbsr & TRBSR_WRAP; + return trbsr & TRBSR_EL1_WRAP; } static inline bool is_trbe_abort(u64 trbsr) { - return trbsr & TRBSR_ABORT; + return trbsr & TRBSR_EL1_EA; } static inline bool is_trbe_running(u64 trbsr) { - return !(trbsr & TRBSR_STOP); + return !(trbsr & TRBSR_EL1_S); } -#define TRBE_TRIG_MODE_STOP 0 -#define TRBE_TRIG_MODE_IRQ 1 -#define TRBE_TRIG_MODE_IGNORE 3 - -#define TRBE_FILL_MODE_FILL 0 -#define TRBE_FILL_MODE_WRAP 1 -#define TRBE_FILL_MODE_CIRCULAR_BUFFER 3 - static inline bool get_trbe_flag_update(u64 trbidr) { - return trbidr & TRBIDR_FLAG; + return trbidr & TRBIDR_EL1_F; } static inline bool is_trbe_programmable(u64 trbidr) { - return !(trbidr & TRBIDR_PROG); + return !(trbidr & TRBIDR_EL1_P); } static inline int get_trbe_address_align(u64 trbidr) { - return (trbidr >> TRBIDR_ALIGN_SHIFT) & TRBIDR_ALIGN_MASK; + return (trbidr & TRBIDR_EL1_Align_MASK) >> TRBIDR_EL1_Align_SHIFT; } static inline unsigned long get_trbe_write_pointer(void) @@ -121,7 +113,7 @@ static inline void set_trbe_write_pointer(unsigned long addr) static inline unsigned long get_trbe_limit_pointer(void) { u64 trblimitr = read_sysreg_s(SYS_TRBLIMITR_EL1); - unsigned long addr = trblimitr & (TRBLIMITR_LIMIT_MASK << TRBLIMITR_LIMIT_SHIFT); + unsigned long addr = trblimitr & TRBLIMITR_EL1_LIMIT_MASK; WARN_ON(!IS_ALIGNED(addr, PAGE_SIZE)); return addr; @@ -130,7 +122,7 @@ static inline unsigned long get_trbe_limit_pointer(void) static inline unsigned long get_trbe_base_pointer(void) { u64 trbbaser = read_sysreg_s(SYS_TRBBASER_EL1); - unsigned long addr = trbbaser & (TRBBASER_BASE_MASK << TRBBASER_BASE_SHIFT); + unsigned long addr = trbbaser & TRBBASER_EL1_BASE_MASK; WARN_ON(!IS_ALIGNED(addr, PAGE_SIZE)); return addr; @@ -139,7 +131,7 @@ static inline unsigned long get_trbe_base_pointer(void) static inline void set_trbe_base_pointer(unsigned long addr) { WARN_ON(is_trbe_enabled()); - WARN_ON(!IS_ALIGNED(addr, (1UL << TRBBASER_BASE_SHIFT))); + WARN_ON(!IS_ALIGNED(addr, (1UL << TRBBASER_EL1_BASE_SHIFT))); WARN_ON(!IS_ALIGNED(addr, PAGE_SIZE)); write_sysreg_s(addr, SYS_TRBBASER_EL1); } diff --git a/drivers/hwtracing/coresight/ultrasoc-smb.c b/drivers/hwtracing/coresight/ultrasoc-smb.c index b317342c7ce5a55f68f2d2b2aebed9c884f09716..e9a32a97fbee6912aa0a2a4852f634f7579b56c4 100644 --- a/drivers/hwtracing/coresight/ultrasoc-smb.c +++ b/drivers/hwtracing/coresight/ultrasoc-smb.c @@ -106,7 +106,7 @@ static int smb_open(struct inode *inode, struct file *file) goto out; } - if (atomic_read(drvdata->csdev->refcnt)) { + if (atomic_read(&drvdata->csdev->refcnt)) { ret = -EBUSY; goto out; } @@ -256,7 +256,8 @@ static int smb_enable_perf(struct coresight_device *csdev, void *data) return 0; } -static int smb_enable(struct coresight_device *csdev, u32 mode, void *data) +static int smb_enable(struct coresight_device *csdev, enum cs_mode mode, + void *data) { struct smb_drv_data *drvdata = dev_get_drvdata(csdev->dev.parent); int ret = 0; @@ -289,7 +290,7 @@ static int smb_enable(struct coresight_device *csdev, u32 mode, void *data) if (ret) goto out; - atomic_inc(csdev->refcnt); + atomic_inc(&csdev->refcnt); dev_dbg(&csdev->dev, "Ultrasoc SMB enabled\n"); out: @@ -310,7 +311,7 @@ static int smb_disable(struct coresight_device *csdev) goto out; } - if (atomic_dec_return(csdev->refcnt)) { + if (atomic_dec_return(&csdev->refcnt)) { ret = -EBUSY; goto out; } @@ -410,7 +411,7 @@ static unsigned long smb_update_buffer(struct coresight_device *csdev, mutex_lock(&drvdata->mutex); /* Don't do anything if another tracer is using this sink. */ - if (atomic_read(csdev->refcnt) != 1) + if (atomic_read(&csdev->refcnt) != 1) goto out; smb_disable_hw(drvdata); diff --git a/drivers/hwtracing/coresight/ultrasoc-smb.h b/drivers/hwtracing/coresight/ultrasoc-smb.h index 7dfbe42e37a058554730f7daffbcc81bb1838481..d2e14e8d2c8a8c5004f106792fbd0de8241dde39 100644 --- a/drivers/hwtracing/coresight/ultrasoc-smb.h +++ b/drivers/hwtracing/coresight/ultrasoc-smb.h @@ -119,7 +119,7 @@ struct smb_drv_data { struct mutex mutex; bool reading; pid_t pid; - u32 mode; + enum cs_mode mode; }; #endif diff --git a/drivers/hwtracing/ptt/hisi_ptt.c b/drivers/hwtracing/ptt/hisi_ptt.c index 30f1525639b5736e94ee047e14a950a59864c577..ba081b6d2435ec063f5265cd833efe736ce8e125 100644 --- a/drivers/hwtracing/ptt/hisi_ptt.c +++ b/drivers/hwtracing/ptt/hisi_ptt.c @@ -341,19 +341,319 @@ static int hisi_ptt_register_irq(struct hisi_ptt *hisi_ptt) if (ret < 0) return ret; - ret = devm_request_threaded_irq(&pdev->dev, - pci_irq_vector(pdev, HISI_PTT_TRACE_DMA_IRQ), + hisi_ptt->trace_irq = pci_irq_vector(pdev, HISI_PTT_TRACE_DMA_IRQ); + ret = devm_request_threaded_irq(&pdev->dev, hisi_ptt->trace_irq, NULL, hisi_ptt_isr, 0, DRV_NAME, hisi_ptt); if (ret) { pci_err(pdev, "failed to request irq %d, ret = %d\n", - pci_irq_vector(pdev, HISI_PTT_TRACE_DMA_IRQ), ret); + hisi_ptt->trace_irq, ret); return ret; } return 0; } +static void hisi_ptt_del_free_filter(struct hisi_ptt *hisi_ptt, + struct hisi_ptt_filter_desc *filter) +{ + if (filter->is_port) + hisi_ptt->port_mask &= ~hisi_ptt_get_filter_val(filter->devid, true); + + list_del(&filter->list); + kfree(filter->name); + kfree(filter); +} + +static struct hisi_ptt_filter_desc * +hisi_ptt_alloc_add_filter(struct hisi_ptt *hisi_ptt, u16 devid, bool is_port) +{ + struct hisi_ptt_filter_desc *filter; + u8 devfn = devid & 0xff; + char *filter_name; + + filter_name = kasprintf(GFP_KERNEL, "%04x:%02x:%02x.%d", pci_domain_nr(hisi_ptt->pdev->bus), + PCI_BUS_NUM(devid), PCI_SLOT(devfn), PCI_FUNC(devfn)); + if (!filter_name) { + pci_err(hisi_ptt->pdev, "failed to allocate name for filter %04x:%02x:%02x.%d\n", + pci_domain_nr(hisi_ptt->pdev->bus), PCI_BUS_NUM(devid), + PCI_SLOT(devfn), PCI_FUNC(devfn)); + return NULL; + } + + filter = kzalloc(sizeof(*filter), GFP_KERNEL); + if (!filter) { + pci_err(hisi_ptt->pdev, "failed to add filter for %s\n", + filter_name); + kfree(filter_name); + return NULL; + } + + filter->name = filter_name; + filter->is_port = is_port; + filter->devid = devid; + + if (filter->is_port) { + list_add_tail(&filter->list, &hisi_ptt->port_filters); + + /* Update the available port mask */ + hisi_ptt->port_mask |= hisi_ptt_get_filter_val(filter->devid, true); + } else { + list_add_tail(&filter->list, &hisi_ptt->req_filters); + } + + return filter; +} + +static ssize_t hisi_ptt_filter_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct hisi_ptt_filter_desc *filter; + unsigned long filter_val; + + filter = container_of(attr, struct hisi_ptt_filter_desc, attr); + filter_val = hisi_ptt_get_filter_val(filter->devid, filter->is_port) | + (filter->is_port ? HISI_PTT_PMU_FILTER_IS_PORT : 0); + + return sysfs_emit(buf, "0x%05lx\n", filter_val); +} + +static int hisi_ptt_create_rp_filter_attr(struct hisi_ptt *hisi_ptt, + struct hisi_ptt_filter_desc *filter) +{ + struct kobject *kobj = &hisi_ptt->hisi_ptt_pmu.dev->kobj; + + sysfs_attr_init(&filter->attr.attr); + filter->attr.attr.name = filter->name; + filter->attr.attr.mode = 0400; /* DEVICE_ATTR_ADMIN_RO */ + filter->attr.show = hisi_ptt_filter_show; + + return sysfs_add_file_to_group(kobj, &filter->attr.attr, + HISI_PTT_RP_FILTERS_GRP_NAME); +} + +static void hisi_ptt_remove_rp_filter_attr(struct hisi_ptt *hisi_ptt, + struct hisi_ptt_filter_desc *filter) +{ + struct kobject *kobj = &hisi_ptt->hisi_ptt_pmu.dev->kobj; + + sysfs_remove_file_from_group(kobj, &filter->attr.attr, + HISI_PTT_RP_FILTERS_GRP_NAME); +} + +static int hisi_ptt_create_req_filter_attr(struct hisi_ptt *hisi_ptt, + struct hisi_ptt_filter_desc *filter) +{ + struct kobject *kobj = &hisi_ptt->hisi_ptt_pmu.dev->kobj; + + sysfs_attr_init(&filter->attr.attr); + filter->attr.attr.name = filter->name; + filter->attr.attr.mode = 0400; /* DEVICE_ATTR_ADMIN_RO */ + filter->attr.show = hisi_ptt_filter_show; + + return sysfs_add_file_to_group(kobj, &filter->attr.attr, + HISI_PTT_REQ_FILTERS_GRP_NAME); +} + +static void hisi_ptt_remove_req_filter_attr(struct hisi_ptt *hisi_ptt, + struct hisi_ptt_filter_desc *filter) +{ + struct kobject *kobj = &hisi_ptt->hisi_ptt_pmu.dev->kobj; + + sysfs_remove_file_from_group(kobj, &filter->attr.attr, + HISI_PTT_REQ_FILTERS_GRP_NAME); +} + +static int hisi_ptt_create_filter_attr(struct hisi_ptt *hisi_ptt, + struct hisi_ptt_filter_desc *filter) +{ + int ret; + + if (filter->is_port) + ret = hisi_ptt_create_rp_filter_attr(hisi_ptt, filter); + else + ret = hisi_ptt_create_req_filter_attr(hisi_ptt, filter); + + if (ret) + pci_err(hisi_ptt->pdev, "failed to create sysfs attribute for filter %s\n", + filter->name); + + return ret; +} + +static void hisi_ptt_remove_filter_attr(struct hisi_ptt *hisi_ptt, + struct hisi_ptt_filter_desc *filter) +{ + if (filter->is_port) + hisi_ptt_remove_rp_filter_attr(hisi_ptt, filter); + else + hisi_ptt_remove_req_filter_attr(hisi_ptt, filter); +} + +static void hisi_ptt_remove_all_filter_attributes(void *data) +{ + struct hisi_ptt_filter_desc *filter; + struct hisi_ptt *hisi_ptt = data; + + mutex_lock(&hisi_ptt->filter_lock); + + list_for_each_entry(filter, &hisi_ptt->req_filters, list) + hisi_ptt_remove_filter_attr(hisi_ptt, filter); + + list_for_each_entry(filter, &hisi_ptt->port_filters, list) + hisi_ptt_remove_filter_attr(hisi_ptt, filter); + + hisi_ptt->sysfs_inited = false; + mutex_unlock(&hisi_ptt->filter_lock); +} + +static int hisi_ptt_init_filter_attributes(struct hisi_ptt *hisi_ptt) +{ + struct hisi_ptt_filter_desc *filter; + int ret; + + mutex_lock(&hisi_ptt->filter_lock); + + /* + * Register the reset callback in the first stage. In reset we traverse + * the filters list to remove the sysfs attributes so the callback can + * be called safely even without below filter attributes creation. + */ + ret = devm_add_action(&hisi_ptt->pdev->dev, + hisi_ptt_remove_all_filter_attributes, + hisi_ptt); + if (ret) + goto out; + + list_for_each_entry(filter, &hisi_ptt->port_filters, list) { + ret = hisi_ptt_create_filter_attr(hisi_ptt, filter); + if (ret) + goto out; + } + + list_for_each_entry(filter, &hisi_ptt->req_filters, list) { + ret = hisi_ptt_create_filter_attr(hisi_ptt, filter); + if (ret) + goto out; + } + + hisi_ptt->sysfs_inited = true; +out: + mutex_unlock(&hisi_ptt->filter_lock); + return ret; +} + +static void hisi_ptt_update_filters(struct work_struct *work) +{ + struct delayed_work *delayed_work = to_delayed_work(work); + struct hisi_ptt_filter_update_info info; + struct hisi_ptt_filter_desc *filter; + struct hisi_ptt *hisi_ptt; + + hisi_ptt = container_of(delayed_work, struct hisi_ptt, work); + + if (!mutex_trylock(&hisi_ptt->filter_lock)) { + schedule_delayed_work(&hisi_ptt->work, HISI_PTT_WORK_DELAY_MS); + return; + } + + while (kfifo_get(&hisi_ptt->filter_update_kfifo, &info)) { + if (info.is_add) { + /* + * Notify the users if failed to add this filter, others + * still work and available. See the comments in + * hisi_ptt_init_filters(). + */ + filter = hisi_ptt_alloc_add_filter(hisi_ptt, info.devid, info.is_port); + if (!filter) + continue; + + /* + * If filters' sysfs entries hasn't been initialized, + * then we're still at probe stage. Add the filters to + * the list and later hisi_ptt_init_filter_attributes() + * will create sysfs attributes for all the filters. + */ + if (hisi_ptt->sysfs_inited && + hisi_ptt_create_filter_attr(hisi_ptt, filter)) { + hisi_ptt_del_free_filter(hisi_ptt, filter); + continue; + } + } else { + struct hisi_ptt_filter_desc *tmp; + struct list_head *target_list; + + target_list = info.is_port ? &hisi_ptt->port_filters : + &hisi_ptt->req_filters; + + list_for_each_entry_safe(filter, tmp, target_list, list) + if (filter->devid == info.devid) { + if (hisi_ptt->sysfs_inited) + hisi_ptt_remove_filter_attr(hisi_ptt, filter); + + hisi_ptt_del_free_filter(hisi_ptt, filter); + break; + } + } + } + + mutex_unlock(&hisi_ptt->filter_lock); +} + +/* + * A PCI bus notifier is used here for dynamically updating the filter + * list. + */ +static int hisi_ptt_notifier_call(struct notifier_block *nb, unsigned long action, + void *data) +{ + struct hisi_ptt *hisi_ptt = container_of(nb, struct hisi_ptt, hisi_ptt_nb); + struct hisi_ptt_filter_update_info info; + struct pci_dev *pdev, *root_port; + struct device *dev = data; + u32 port_devid; + + pdev = to_pci_dev(dev); + root_port = pcie_find_root_port(pdev); + if (!root_port) + return 0; + + port_devid = PCI_DEVID(root_port->bus->number, root_port->devfn); + if (port_devid < hisi_ptt->lower_bdf || + port_devid > hisi_ptt->upper_bdf) + return 0; + + info.is_port = pci_pcie_type(pdev) == PCI_EXP_TYPE_ROOT_PORT; + info.devid = PCI_DEVID(pdev->bus->number, pdev->devfn); + + switch (action) { + case BUS_NOTIFY_ADD_DEVICE: + info.is_add = true; + break; + case BUS_NOTIFY_DEL_DEVICE: + info.is_add = false; + break; + default: + return 0; + } + + /* + * The FIFO size is 16 which is sufficient for almost all the cases, + * since each PCIe core will have most 8 Root Ports (typically only + * 1~4 Root Ports). On failure log the failed filter and let user + * handle it. + */ + if (kfifo_in_spinlocked(&hisi_ptt->filter_update_kfifo, &info, 1, + &hisi_ptt->filter_update_lock)) + schedule_delayed_work(&hisi_ptt->work, 0); + else + pci_warn(hisi_ptt->pdev, + "filter update fifo overflow for target %s\n", + pci_name(pdev)); + + return 0; +} + static int hisi_ptt_init_filters(struct pci_dev *pdev, void *data) { struct pci_dev *root_port = pcie_find_root_port(pdev); @@ -374,23 +674,10 @@ static int hisi_ptt_init_filters(struct pci_dev *pdev, void *data) * should be partial initialized and users would know which filter fails * through the log. Other functions of PTT device are still available. */ - filter = kzalloc(sizeof(*filter), GFP_KERNEL); - if (!filter) { - pci_err(hisi_ptt->pdev, "failed to add filter %s\n", pci_name(pdev)); + filter = hisi_ptt_alloc_add_filter(hisi_ptt, PCI_DEVID(pdev->bus->number, pdev->devfn), + pci_pcie_type(pdev) == PCI_EXP_TYPE_ROOT_PORT); + if (!filter) return -ENOMEM; - } - - filter->devid = PCI_DEVID(pdev->bus->number, pdev->devfn); - - if (pci_pcie_type(pdev) == PCI_EXP_TYPE_ROOT_PORT) { - filter->is_port = true; - list_add_tail(&filter->list, &hisi_ptt->port_filters); - - /* Update the available port mask */ - hisi_ptt->port_mask |= hisi_ptt_get_filter_val(filter->devid, true); - } else { - list_add_tail(&filter->list, &hisi_ptt->req_filters); - } return 0; } @@ -400,15 +687,11 @@ static void hisi_ptt_release_filters(void *data) struct hisi_ptt_filter_desc *filter, *tmp; struct hisi_ptt *hisi_ptt = data; - list_for_each_entry_safe(filter, tmp, &hisi_ptt->req_filters, list) { - list_del(&filter->list); - kfree(filter); - } + list_for_each_entry_safe(filter, tmp, &hisi_ptt->req_filters, list) + hisi_ptt_del_free_filter(hisi_ptt, filter); - list_for_each_entry_safe(filter, tmp, &hisi_ptt->port_filters, list) { - list_del(&filter->list); - kfree(filter); - } + list_for_each_entry_safe(filter, tmp, &hisi_ptt->port_filters, list) + hisi_ptt_del_free_filter(hisi_ptt, filter); } static int hisi_ptt_config_trace_buf(struct hisi_ptt *hisi_ptt) @@ -451,8 +734,13 @@ static int hisi_ptt_init_ctrls(struct hisi_ptt *hisi_ptt) int ret; u32 reg; + INIT_DELAYED_WORK(&hisi_ptt->work, hisi_ptt_update_filters); + INIT_KFIFO(hisi_ptt->filter_update_kfifo); + spin_lock_init(&hisi_ptt->filter_update_lock); + INIT_LIST_HEAD(&hisi_ptt->port_filters); INIT_LIST_HEAD(&hisi_ptt->req_filters); + mutex_init(&hisi_ptt->filter_lock); ret = hisi_ptt_config_trace_buf(hisi_ptt); if (ret) @@ -528,10 +816,58 @@ static struct attribute_group hisi_ptt_pmu_format_group = { .attrs = hisi_ptt_pmu_format_attrs, }; +static ssize_t hisi_ptt_filter_multiselect_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct dev_ext_attribute *ext_attr; + + ext_attr = container_of(attr, struct dev_ext_attribute, attr); + return sysfs_emit(buf, "%s\n", (char *)ext_attr->var); +} + +static struct dev_ext_attribute root_port_filters_multiselect = { + .attr = { + .attr = { .name = "multiselect", .mode = 0400 }, + .show = hisi_ptt_filter_multiselect_show, + }, + .var = "1", +}; + +static struct attribute *hisi_ptt_pmu_root_ports_attrs[] = { + &root_port_filters_multiselect.attr.attr, + NULL +}; + +static struct attribute_group hisi_ptt_pmu_root_ports_group = { + .name = HISI_PTT_RP_FILTERS_GRP_NAME, + .attrs = hisi_ptt_pmu_root_ports_attrs, +}; + +static struct dev_ext_attribute requester_filters_multiselect = { + .attr = { + .attr = { .name = "multiselect", .mode = 0400 }, + .show = hisi_ptt_filter_multiselect_show, + }, + .var = "0", +}; + +static struct attribute *hisi_ptt_pmu_requesters_attrs[] = { + &requester_filters_multiselect.attr.attr, + NULL +}; + +static struct attribute_group hisi_ptt_pmu_requesters_group = { + .name = HISI_PTT_REQ_FILTERS_GRP_NAME, + .attrs = hisi_ptt_pmu_requesters_attrs, +}; + static const struct attribute_group *hisi_ptt_pmu_groups[] = { &hisi_ptt_cpumask_attr_group, &hisi_ptt_pmu_format_group, &hisi_ptt_tune_group, + &hisi_ptt_pmu_root_ports_group, + &hisi_ptt_pmu_requesters_group, NULL }; @@ -605,6 +941,7 @@ static int hisi_ptt_trace_valid_filter(struct hisi_ptt *hisi_ptt, u64 config) { unsigned long val, port_mask = hisi_ptt->port_mask; struct hisi_ptt_filter_desc *filter; + int ret = 0; hisi_ptt->trace_ctrl.is_port = FIELD_GET(HISI_PTT_PMU_FILTER_IS_PORT, config); val = FIELD_GET(HISI_PTT_PMU_FILTER_VAL_MASK, config); @@ -618,16 +955,20 @@ static int hisi_ptt_trace_valid_filter(struct hisi_ptt *hisi_ptt, u64 config) * For Requester ID filters, walk the available filter list to see * whether we have one matched. */ + mutex_lock(&hisi_ptt->filter_lock); if (!hisi_ptt->trace_ctrl.is_port) { list_for_each_entry(filter, &hisi_ptt->req_filters, list) { if (val == hisi_ptt_get_filter_val(filter->devid, filter->is_port)) - return 0; + goto out; } } else if (bitmap_subset(&val, &port_mask, BITS_PER_LONG)) { - return 0; + goto out; } - return -EINVAL; + ret = -EINVAL; +out: + mutex_unlock(&hisi_ptt->filter_lock); + return ret; } static void hisi_ptt_pmu_init_configs(struct hisi_ptt *hisi_ptt, struct perf_event *event) @@ -757,8 +1098,7 @@ static void hisi_ptt_pmu_start(struct perf_event *event, int flags) * core in event_function_local(). If CPU passed is offline we'll fail * here, just log it since we can do nothing here. */ - ret = irq_set_affinity(pci_irq_vector(hisi_ptt->pdev, HISI_PTT_TRACE_DMA_IRQ), - cpumask_of(cpu)); + ret = irq_set_affinity(hisi_ptt->trace_irq, cpumask_of(cpu)); if (ret) dev_warn(dev, "failed to set the affinity of trace interrupt\n"); @@ -871,7 +1211,7 @@ static int hisi_ptt_register_pmu(struct hisi_ptt *hisi_ptt) hisi_ptt->hisi_ptt_pmu = (struct pmu) { .module = THIS_MODULE, - .capabilities = PERF_PMU_CAP_EXCLUSIVE | PERF_PMU_CAP_ITRACE, + .capabilities = PERF_PMU_CAP_EXCLUSIVE | PERF_PMU_CAP_NO_EXCLUDE, .task_ctx_nr = perf_sw_context, .attr_groups = hisi_ptt_pmu_groups, .event_init = hisi_ptt_pmu_event_init, @@ -901,6 +1241,31 @@ static int hisi_ptt_register_pmu(struct hisi_ptt *hisi_ptt) &hisi_ptt->hisi_ptt_pmu); } +static void hisi_ptt_unregister_filter_update_notifier(void *data) +{ + struct hisi_ptt *hisi_ptt = data; + + bus_unregister_notifier(&pci_bus_type, &hisi_ptt->hisi_ptt_nb); + + /* Cancel any work that has been queued */ + cancel_delayed_work_sync(&hisi_ptt->work); +} + +/* Register the bus notifier for dynamically updating the filter list */ +static int hisi_ptt_register_filter_update_notifier(struct hisi_ptt *hisi_ptt) +{ + int ret; + + hisi_ptt->hisi_ptt_nb.notifier_call = hisi_ptt_notifier_call; + ret = bus_register_notifier(&pci_bus_type, &hisi_ptt->hisi_ptt_nb); + if (ret) + return ret; + + return devm_add_action_or_reset(&hisi_ptt->pdev->dev, + hisi_ptt_unregister_filter_update_notifier, + hisi_ptt); +} + /* * The DMA of PTT trace can only use direct mappings due to some * hardware restriction. Check whether there is no IOMMU or the @@ -972,12 +1337,22 @@ static int hisi_ptt_probe(struct pci_dev *pdev, return ret; } + ret = hisi_ptt_register_filter_update_notifier(hisi_ptt); + if (ret) + pci_warn(pdev, "failed to register filter update notifier, ret = %d", ret); + ret = hisi_ptt_register_pmu(hisi_ptt); if (ret) { pci_err(pdev, "failed to register PMU device, ret = %d", ret); return ret; } + ret = hisi_ptt_init_filter_attributes(hisi_ptt); + if (ret) { + pci_err(pdev, "failed to init sysfs filter attributes, ret = %d", ret); + return ret; + } + return 0; } @@ -1018,8 +1393,7 @@ static int hisi_ptt_cpu_teardown(unsigned int cpu, struct hlist_node *node) * Also make sure the interrupt bind to the migrated CPU as well. Warn * the user on failure here. */ - if (irq_set_affinity(pci_irq_vector(hisi_ptt->pdev, HISI_PTT_TRACE_DMA_IRQ), - cpumask_of(target))) + if (irq_set_affinity(hisi_ptt->trace_irq, cpumask_of(target))) dev_warn(dev, "failed to set the affinity of trace interrupt\n"); hisi_ptt->trace_ctrl.on_cpu = target; diff --git a/drivers/hwtracing/ptt/hisi_ptt.h b/drivers/hwtracing/ptt/hisi_ptt.h index 5beb1648c93ab7a1aa1f0c27432f4144f06ee049..e17f045d7e72597bc6bb0909722a0492e8db0e43 100644 --- a/drivers/hwtracing/ptt/hisi_ptt.h +++ b/drivers/hwtracing/ptt/hisi_ptt.h @@ -11,12 +11,16 @@ #include #include +#include +#include #include #include +#include #include #include #include #include +#include #define DRV_NAME "hisi_ptt" @@ -71,6 +75,11 @@ #define HISI_PTT_WAIT_TRACE_TIMEOUT_US 100UL #define HISI_PTT_WAIT_POLL_INTERVAL_US 10UL +/* FIFO size for dynamically updating the PTT trace filter list. */ +#define HISI_PTT_FILTER_UPDATE_FIFO_SIZE 16 +/* Delay time for filter updating work */ +#define HISI_PTT_WORK_DELAY_MS 100UL + #define HISI_PCIE_CORE_PORT_ID(devfn) ((PCI_SLOT(devfn) & 0x7) << 1) /* Definition of the PMU configs */ @@ -131,15 +140,40 @@ struct hisi_ptt_trace_ctrl { u32 type:4; }; +/* + * sysfs attribute group name for root port filters and requester filters: + * /sys/devices/hisi_ptt_/root_port_filters + * and + * /sys/devices/hisi_ptt_/requester_filters + */ +#define HISI_PTT_RP_FILTERS_GRP_NAME "root_port_filters" +#define HISI_PTT_REQ_FILTERS_GRP_NAME "requester_filters" + /** * struct hisi_ptt_filter_desc - Descriptor of the PTT trace filter + * @attr: sysfs attribute of this filter * @list: entry of this descriptor in the filter list * @is_port: the PCI device of the filter is a Root Port or not + * @name: name of this filter, same as the name of the related PCI device * @devid: the PCI device's devid of the filter */ struct hisi_ptt_filter_desc { + struct device_attribute attr; struct list_head list; bool is_port; + char *name; + u16 devid; +}; + +/** + * struct hisi_ptt_filter_update_info - Information for PTT filter updating + * @is_port: the PCI device to update is a Root Port or not + * @is_add: adding to the filter or not + * @devid: the PCI device's devid of the filter + */ +struct hisi_ptt_filter_update_info { + bool is_port; + bool is_add; u16 devid; }; @@ -160,26 +194,35 @@ struct hisi_ptt_pmu_buf { /** * struct hisi_ptt - Per PTT device data * @trace_ctrl: the control information of PTT trace + * @hisi_ptt_nb: dynamic filter update notifier * @hotplug_node: node for register cpu hotplug event * @hisi_ptt_pmu: the pum device of trace * @iobase: base IO address of the device * @pdev: pci_dev of this PTT device * @tune_lock: lock to serialize the tune process * @pmu_lock: lock to serialize the perf process + * @trace_irq: interrupt number used by trace * @upper_bdf: the upper BDF range of the PCI devices managed by this PTT device * @lower_bdf: the lower BDF range of the PCI devices managed by this PTT device * @port_filters: the filter list of root ports * @req_filters: the filter list of requester ID + * @filter_lock: lock to protect the filters + * @sysfs_inited: whether the filters' sysfs entries has been initialized * @port_mask: port mask of the managed root ports + * @work: delayed work for filter updating + * @filter_update_lock: spinlock to protect the filter update fifo + * @filter_update_fifo: fifo of the filters waiting to update the filter list */ struct hisi_ptt { struct hisi_ptt_trace_ctrl trace_ctrl; + struct notifier_block hisi_ptt_nb; struct hlist_node hotplug_node; struct pmu hisi_ptt_pmu; void __iomem *iobase; struct pci_dev *pdev; struct mutex tune_lock; spinlock_t pmu_lock; + int trace_irq; u32 upper_bdf; u32 lower_bdf; @@ -192,7 +235,20 @@ struct hisi_ptt { */ struct list_head port_filters; struct list_head req_filters; + struct mutex filter_lock; + bool sysfs_inited; u16 port_mask; + + /* + * We use a delayed work here to avoid indefinitely waiting for + * the hisi_ptt->mutex which protecting the filter list. The + * work will be delayed only if the mutex can not be held, + * otherwise no delay will be applied. + */ + struct delayed_work work; + spinlock_t filter_update_lock; + DECLARE_KFIFO(filter_update_kfifo, struct hisi_ptt_filter_update_info, + HISI_PTT_FILTER_UPDATE_FIFO_SIZE); }; #define to_hisi_ptt(pmu) container_of(pmu, struct hisi_ptt, hisi_ptt_pmu) diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 87600b4aacb3fba4ebb83ad03d2b5c236d963d80..9cfe8fc509d7d6618cdad2bd74c30d9b4f3d672e 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -157,7 +157,7 @@ config I2C_I801 Emmitsburg (PCH) Alder Lake (PCH) Raptor Lake (PCH) - Meteor Lake (SOC) + Meteor Lake (SOC and PCH) This driver can also be built as a module. If so, the module will be called i2c-i801. @@ -1025,7 +1025,7 @@ config I2C_RZV2M depends on ARCH_RENESAS || COMPILE_TEST help If you say yes to this option, support will be included for the - Renesas RZ/V2M I2C interface. + Renesas RZ/V2M I2C interface. This driver can also be built as a module. If so, the module will be called i2c-rzv2m. diff --git a/drivers/i2c/busses/i2c-altera.c b/drivers/i2c/busses/i2c-altera.c index 50e7f3f670b6f0d2400ba21d8dc3bc675d67ad65..252fbd175fb1ccc82878d1fa7b274285554e369b 100644 --- a/drivers/i2c/busses/i2c-altera.c +++ b/drivers/i2c/busses/i2c-altera.c @@ -465,14 +465,12 @@ static int altr_i2c_probe(struct platform_device *pdev) return 0; } -static int altr_i2c_remove(struct platform_device *pdev) +static void altr_i2c_remove(struct platform_device *pdev) { struct altr_i2c_dev *idev = platform_get_drvdata(pdev); clk_disable_unprepare(idev->i2c_clk); i2c_del_adapter(&idev->adapter); - - return 0; } /* Match table for of_platform binding */ @@ -484,7 +482,7 @@ MODULE_DEVICE_TABLE(of, altr_i2c_of_match); static struct platform_driver altr_i2c_driver = { .probe = altr_i2c_probe, - .remove = altr_i2c_remove, + .remove_new = altr_i2c_remove, .driver = { .name = "altera-i2c", .of_match_table = altr_i2c_of_match, diff --git a/drivers/i2c/busses/i2c-amd-mp2-plat.c b/drivers/i2c/busses/i2c-amd-mp2-plat.c index 423fe0c8a471e0b29ae455811a12b379b5f16e2c..112fe2bc5662b29052fbed9727bafaa597cdaf11 100644 --- a/drivers/i2c/busses/i2c-amd-mp2-plat.c +++ b/drivers/i2c/busses/i2c-amd-mp2-plat.c @@ -322,7 +322,7 @@ static int i2c_amd_probe(struct platform_device *pdev) return ret; } -static int i2c_amd_remove(struct platform_device *pdev) +static void i2c_amd_remove(struct platform_device *pdev) { struct amd_i2c_dev *i2c_dev = platform_get_drvdata(pdev); struct amd_i2c_common *i2c_common = &i2c_dev->common; @@ -336,7 +336,6 @@ static int i2c_amd_remove(struct platform_device *pdev) i2c_unlock_bus(&i2c_dev->adap, I2C_LOCK_ROOT_ADAPTER); i2c_del_adapter(&i2c_dev->adap); - return 0; } static const struct acpi_device_id i2c_amd_acpi_match[] = { @@ -347,7 +346,7 @@ MODULE_DEVICE_TABLE(acpi, i2c_amd_acpi_match); static struct platform_driver i2c_amd_plat_driver = { .probe = i2c_amd_probe, - .remove = i2c_amd_remove, + .remove_new = i2c_amd_remove, .driver = { .name = "i2c_amd_mp2", .acpi_match_table = ACPI_PTR(i2c_amd_acpi_match), diff --git a/drivers/i2c/busses/i2c-aspeed.c b/drivers/i2c/busses/i2c-aspeed.c index d3c99c5b324788da554fcd07a803cd3a4fef9b03..2e5acfeb76c818a3058ffbd75d59930b35e17df8 100644 --- a/drivers/i2c/busses/i2c-aspeed.c +++ b/drivers/i2c/busses/i2c-aspeed.c @@ -1061,7 +1061,7 @@ static int aspeed_i2c_probe_bus(struct platform_device *pdev) return 0; } -static int aspeed_i2c_remove_bus(struct platform_device *pdev) +static void aspeed_i2c_remove_bus(struct platform_device *pdev) { struct aspeed_i2c_bus *bus = platform_get_drvdata(pdev); unsigned long flags; @@ -1077,13 +1077,11 @@ static int aspeed_i2c_remove_bus(struct platform_device *pdev) reset_control_assert(bus->rst); i2c_del_adapter(&bus->adap); - - return 0; } static struct platform_driver aspeed_i2c_bus_driver = { .probe = aspeed_i2c_probe_bus, - .remove = aspeed_i2c_remove_bus, + .remove_new = aspeed_i2c_remove_bus, .driver = { .name = "aspeed-i2c-bus", .of_match_table = aspeed_i2c_bus_of_table, diff --git a/drivers/i2c/busses/i2c-at91-core.c b/drivers/i2c/busses/i2c-at91-core.c index 2df9df585131494f9f014ab96e3776246e2c9ccc..05ad3bc3578ac67dcb02adc483c4fdad4c53f993 100644 --- a/drivers/i2c/busses/i2c-at91-core.c +++ b/drivers/i2c/busses/i2c-at91-core.c @@ -273,7 +273,7 @@ static int at91_twi_probe(struct platform_device *pdev) return 0; } -static int at91_twi_remove(struct platform_device *pdev) +static void at91_twi_remove(struct platform_device *pdev) { struct at91_twi_dev *dev = platform_get_drvdata(pdev); @@ -282,8 +282,6 @@ static int at91_twi_remove(struct platform_device *pdev) pm_runtime_disable(dev->dev); pm_runtime_set_suspended(dev->dev); - - return 0; } static int __maybe_unused at91_twi_runtime_suspend(struct device *dev) @@ -342,7 +340,7 @@ static const struct dev_pm_ops __maybe_unused at91_twi_pm = { static struct platform_driver at91_twi_driver = { .probe = at91_twi_probe, - .remove = at91_twi_remove, + .remove_new = at91_twi_remove, .id_table = at91_twi_devtypes, .driver = { .name = "at91_i2c", diff --git a/drivers/i2c/busses/i2c-au1550.c b/drivers/i2c/busses/i2c-au1550.c index 7b42d35b1294253dbb2e35725f627bc9f5116fc6..e66c12ecf27063627535367fc801188de3501f64 100644 --- a/drivers/i2c/busses/i2c-au1550.c +++ b/drivers/i2c/busses/i2c-au1550.c @@ -334,13 +334,12 @@ i2c_au1550_probe(struct platform_device *pdev) return 0; } -static int i2c_au1550_remove(struct platform_device *pdev) +static void i2c_au1550_remove(struct platform_device *pdev) { struct i2c_au1550_data *priv = platform_get_drvdata(pdev); i2c_del_adapter(&priv->adap); i2c_au1550_disable(priv); - return 0; } #ifdef CONFIG_PM @@ -379,7 +378,7 @@ static struct platform_driver au1xpsc_smbus_driver = { .pm = AU1XPSC_SMBUS_PMOPS, }, .probe = i2c_au1550_probe, - .remove = i2c_au1550_remove, + .remove_new = i2c_au1550_remove, }; module_platform_driver(au1xpsc_smbus_driver); diff --git a/drivers/i2c/busses/i2c-axxia.c b/drivers/i2c/busses/i2c-axxia.c index c1c74ce084071c9f5a94d8cd0f05cb086b0419db..d7f1e98777ace48b929c3eccd51f841b805d27d7 100644 --- a/drivers/i2c/busses/i2c-axxia.c +++ b/drivers/i2c/busses/i2c-axxia.c @@ -804,14 +804,12 @@ static int axxia_i2c_probe(struct platform_device *pdev) return ret; } -static int axxia_i2c_remove(struct platform_device *pdev) +static void axxia_i2c_remove(struct platform_device *pdev) { struct axxia_i2c_dev *idev = platform_get_drvdata(pdev); clk_disable_unprepare(idev->i2c_clk); i2c_del_adapter(&idev->adapter); - - return 0; } /* Match table for of_platform binding */ @@ -824,7 +822,7 @@ MODULE_DEVICE_TABLE(of, axxia_i2c_of_match); static struct platform_driver axxia_i2c_driver = { .probe = axxia_i2c_probe, - .remove = axxia_i2c_remove, + .remove_new = axxia_i2c_remove, .driver = { .name = "axxia-i2c", .of_match_table = axxia_i2c_of_match, diff --git a/drivers/i2c/busses/i2c-bcm-iproc.c b/drivers/i2c/busses/i2c-bcm-iproc.c index 85d8a6b0488564ee2a672017927436cc556fb28b..2d8342fdc25de6bb330233414e54130e2e9f67b8 100644 --- a/drivers/i2c/busses/i2c-bcm-iproc.c +++ b/drivers/i2c/busses/i2c-bcm-iproc.c @@ -1107,7 +1107,7 @@ static int bcm_iproc_i2c_probe(struct platform_device *pdev) return i2c_add_adapter(adap); } -static int bcm_iproc_i2c_remove(struct platform_device *pdev) +static void bcm_iproc_i2c_remove(struct platform_device *pdev) { struct bcm_iproc_i2c_dev *iproc_i2c = platform_get_drvdata(pdev); @@ -1123,8 +1123,6 @@ static int bcm_iproc_i2c_remove(struct platform_device *pdev) i2c_del_adapter(&iproc_i2c->adapter); bcm_iproc_i2c_enable_disable(iproc_i2c, false); - - return 0; } #ifdef CONFIG_PM_SLEEP @@ -1260,7 +1258,7 @@ static struct platform_driver bcm_iproc_i2c_driver = { .pm = BCM_IPROC_I2C_PM_OPS, }, .probe = bcm_iproc_i2c_probe, - .remove = bcm_iproc_i2c_remove, + .remove_new = bcm_iproc_i2c_remove, }; module_platform_driver(bcm_iproc_i2c_driver); diff --git a/drivers/i2c/busses/i2c-bcm-kona.c b/drivers/i2c/busses/i2c-bcm-kona.c index f3e369f0fd402056d00656bfb3e1ee98523781aa..a57088ec2b064d141dcbf52f167f5dc61614b939 100644 --- a/drivers/i2c/busses/i2c-bcm-kona.c +++ b/drivers/i2c/busses/i2c-bcm-kona.c @@ -859,13 +859,11 @@ static int bcm_kona_i2c_probe(struct platform_device *pdev) return rc; } -static int bcm_kona_i2c_remove(struct platform_device *pdev) +static void bcm_kona_i2c_remove(struct platform_device *pdev) { struct bcm_kona_i2c_dev *dev = platform_get_drvdata(pdev); i2c_del_adapter(&dev->adapter); - - return 0; } static const struct of_device_id bcm_kona_i2c_of_match[] = { @@ -880,7 +878,7 @@ static struct platform_driver bcm_kona_i2c_driver = { .of_match_table = bcm_kona_i2c_of_match, }, .probe = bcm_kona_i2c_probe, - .remove = bcm_kona_i2c_remove, + .remove_new = bcm_kona_i2c_remove, }; module_platform_driver(bcm_kona_i2c_driver); diff --git a/drivers/i2c/busses/i2c-bcm2835.c b/drivers/i2c/busses/i2c-bcm2835.c index 09a077b31bfe1759305b8a3cabfd2fbf84871377..8ce6d3f4955160a834800d9ff9108dc227ed1d11 100644 --- a/drivers/i2c/busses/i2c-bcm2835.c +++ b/drivers/i2c/busses/i2c-bcm2835.c @@ -503,7 +503,7 @@ static int bcm2835_i2c_probe(struct platform_device *pdev) return ret; } -static int bcm2835_i2c_remove(struct platform_device *pdev) +static void bcm2835_i2c_remove(struct platform_device *pdev) { struct bcm2835_i2c_dev *i2c_dev = platform_get_drvdata(pdev); @@ -512,8 +512,6 @@ static int bcm2835_i2c_remove(struct platform_device *pdev) free_irq(i2c_dev->irq, i2c_dev); i2c_del_adapter(&i2c_dev->adapter); - - return 0; } static const struct of_device_id bcm2835_i2c_of_match[] = { @@ -525,7 +523,7 @@ MODULE_DEVICE_TABLE(of, bcm2835_i2c_of_match); static struct platform_driver bcm2835_i2c_driver = { .probe = bcm2835_i2c_probe, - .remove = bcm2835_i2c_remove, + .remove_new = bcm2835_i2c_remove, .driver = { .name = "i2c-bcm2835", .of_match_table = bcm2835_i2c_of_match, diff --git a/drivers/i2c/busses/i2c-brcmstb.c b/drivers/i2c/busses/i2c-brcmstb.c index ef942714642a71503f0b222281121025c5564ac4..cf92cbcb8c86bb8b23ffe46609cd5837b76349e0 100644 --- a/drivers/i2c/busses/i2c-brcmstb.c +++ b/drivers/i2c/busses/i2c-brcmstb.c @@ -690,12 +690,11 @@ static int brcmstb_i2c_probe(struct platform_device *pdev) return rc; } -static int brcmstb_i2c_remove(struct platform_device *pdev) +static void brcmstb_i2c_remove(struct platform_device *pdev) { struct brcmstb_i2c_dev *dev = platform_get_drvdata(pdev); i2c_del_adapter(&dev->adapter); - return 0; } #ifdef CONFIG_PM_SLEEP @@ -736,7 +735,7 @@ static struct platform_driver brcmstb_i2c_driver = { .pm = &brcmstb_i2c_pm, }, .probe = brcmstb_i2c_probe, - .remove = brcmstb_i2c_remove, + .remove_new = brcmstb_i2c_remove, }; module_platform_driver(brcmstb_i2c_driver); diff --git a/drivers/i2c/busses/i2c-cadence.c b/drivers/i2c/busses/i2c-cadence.c index 3a4edf7e75f9fdcc7184d969cff8f486bc95ce97..9849f450257002e3ce41d5bbac6432646377c4ba 100644 --- a/drivers/i2c/busses/i2c-cadence.c +++ b/drivers/i2c/busses/i2c-cadence.c @@ -1415,7 +1415,7 @@ static int cdns_i2c_probe(struct platform_device *pdev) * * Return: 0 always */ -static int cdns_i2c_remove(struct platform_device *pdev) +static void cdns_i2c_remove(struct platform_device *pdev) { struct cdns_i2c *id = platform_get_drvdata(pdev); @@ -1427,8 +1427,6 @@ static int cdns_i2c_remove(struct platform_device *pdev) clk_notifier_unregister(id->clk, &id->clk_rate_change_nb); reset_control_assert(id->reset); clk_disable_unprepare(id->clk); - - return 0; } static struct platform_driver cdns_i2c_drv = { @@ -1438,7 +1436,7 @@ static struct platform_driver cdns_i2c_drv = { .pm = &cdns_i2c_dev_pm_ops, }, .probe = cdns_i2c_probe, - .remove = cdns_i2c_remove, + .remove_new = cdns_i2c_remove, }; module_platform_driver(cdns_i2c_drv); diff --git a/drivers/i2c/busses/i2c-cbus-gpio.c b/drivers/i2c/busses/i2c-cbus-gpio.c index d97c61eec95c16311d079edfae89207416fe97b3..fdc1758a32756e943dd2d304e7582c584300a511 100644 --- a/drivers/i2c/busses/i2c-cbus-gpio.c +++ b/drivers/i2c/busses/i2c-cbus-gpio.c @@ -200,13 +200,11 @@ static const struct i2c_algorithm cbus_i2c_algo = { .functionality = cbus_i2c_func, }; -static int cbus_i2c_remove(struct platform_device *pdev) +static void cbus_i2c_remove(struct platform_device *pdev) { struct i2c_adapter *adapter = platform_get_drvdata(pdev); i2c_del_adapter(adapter); - - return 0; } static int cbus_i2c_probe(struct platform_device *pdev) @@ -266,7 +264,7 @@ MODULE_DEVICE_TABLE(of, i2c_cbus_dt_ids); static struct platform_driver cbus_i2c_driver = { .probe = cbus_i2c_probe, - .remove = cbus_i2c_remove, + .remove_new = cbus_i2c_remove, .driver = { .name = "i2c-cbus-gpio", .of_match_table = of_match_ptr(i2c_cbus_dt_ids), diff --git a/drivers/i2c/busses/i2c-cht-wc.c b/drivers/i2c/busses/i2c-cht-wc.c index 2b2c3d090089ec77f817289ec9df79d36388eeec..0209933b9a847580602efbe6b4229add453345f5 100644 --- a/drivers/i2c/busses/i2c-cht-wc.c +++ b/drivers/i2c/busses/i2c-cht-wc.c @@ -529,15 +529,13 @@ static int cht_wc_i2c_adap_i2c_probe(struct platform_device *pdev) return ret; } -static int cht_wc_i2c_adap_i2c_remove(struct platform_device *pdev) +static void cht_wc_i2c_adap_i2c_remove(struct platform_device *pdev) { struct cht_wc_i2c_adap *adap = platform_get_drvdata(pdev); i2c_unregister_device(adap->client); i2c_del_adapter(&adap->adapter); irq_domain_remove(adap->irq_domain); - - return 0; } static const struct platform_device_id cht_wc_i2c_adap_id_table[] = { @@ -548,7 +546,7 @@ MODULE_DEVICE_TABLE(platform, cht_wc_i2c_adap_id_table); static struct platform_driver cht_wc_i2c_adap_driver = { .probe = cht_wc_i2c_adap_i2c_probe, - .remove = cht_wc_i2c_adap_i2c_remove, + .remove_new = cht_wc_i2c_adap_i2c_remove, .driver = { .name = "cht_wcove_ext_chgr", }, diff --git a/drivers/i2c/busses/i2c-cpm.c b/drivers/i2c/busses/i2c-cpm.c index 24d584a1c9a78fc333b1b46b33d640c7041aebc1..732daf6a932b3263493f4c7a4abfed2873ef22d0 100644 --- a/drivers/i2c/busses/i2c-cpm.c +++ b/drivers/i2c/busses/i2c-cpm.c @@ -676,7 +676,7 @@ static int cpm_i2c_probe(struct platform_device *ofdev) return result; } -static int cpm_i2c_remove(struct platform_device *ofdev) +static void cpm_i2c_remove(struct platform_device *ofdev) { struct cpm_i2c *cpm = platform_get_drvdata(ofdev); @@ -685,8 +685,6 @@ static int cpm_i2c_remove(struct platform_device *ofdev) cpm_i2c_shutdown(cpm); kfree(cpm); - - return 0; } static const struct of_device_id cpm_i2c_match[] = { @@ -703,7 +701,7 @@ MODULE_DEVICE_TABLE(of, cpm_i2c_match); static struct platform_driver cpm_i2c_driver = { .probe = cpm_i2c_probe, - .remove = cpm_i2c_remove, + .remove_new = cpm_i2c_remove, .driver = { .name = "fsl-i2c-cpm", .of_match_table = cpm_i2c_match, diff --git a/drivers/i2c/busses/i2c-cros-ec-tunnel.c b/drivers/i2c/busses/i2c-cros-ec-tunnel.c index 8b3ff5bb14d8da76703d9eb45c6d7c9009e07354..2737fd8abd32494b2aaed2727f9cfe6a824edaf0 100644 --- a/drivers/i2c/busses/i2c-cros-ec-tunnel.c +++ b/drivers/i2c/busses/i2c-cros-ec-tunnel.c @@ -283,13 +283,11 @@ static int ec_i2c_probe(struct platform_device *pdev) return err; } -static int ec_i2c_remove(struct platform_device *dev) +static void ec_i2c_remove(struct platform_device *dev) { struct ec_i2c_device *bus = platform_get_drvdata(dev); i2c_del_adapter(&bus->adap); - - return 0; } static const struct of_device_id cros_ec_i2c_of_match[] __maybe_unused = { @@ -306,7 +304,7 @@ MODULE_DEVICE_TABLE(acpi, cros_ec_i2c_tunnel_acpi_id); static struct platform_driver ec_i2c_tunnel_driver = { .probe = ec_i2c_probe, - .remove = ec_i2c_remove, + .remove_new = ec_i2c_remove, .driver = { .name = "cros-ec-i2c-tunnel", .acpi_match_table = ACPI_PTR(cros_ec_i2c_tunnel_acpi_id), diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c index 9750310f2c961180f6d8e7e7a84801eedc768c75..71b60778c643ddb0d471ca96b0ef2346ec52bf7c 100644 --- a/drivers/i2c/busses/i2c-davinci.c +++ b/drivers/i2c/busses/i2c-davinci.c @@ -767,12 +767,9 @@ static int davinci_i2c_probe(struct platform_device *pdev) if (irq < 0) return dev_err_probe(&pdev->dev, irq, "can't get irq resource\n"); - dev = devm_kzalloc(&pdev->dev, sizeof(struct davinci_i2c_dev), - GFP_KERNEL); - if (!dev) { - dev_err(&pdev->dev, "Memory allocation failed\n"); + dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL); + if (!dev) return -ENOMEM; - } init_completion(&dev->cmd_complete); @@ -885,7 +882,7 @@ static int davinci_i2c_probe(struct platform_device *pdev) return r; } -static int davinci_i2c_remove(struct platform_device *pdev) +static void davinci_i2c_remove(struct platform_device *pdev) { struct davinci_i2c_dev *dev = platform_get_drvdata(pdev); int ret; @@ -894,17 +891,15 @@ static int davinci_i2c_remove(struct platform_device *pdev) i2c_del_adapter(&dev->adapter); - ret = pm_runtime_resume_and_get(&pdev->dev); + ret = pm_runtime_get_sync(&pdev->dev); if (ret < 0) - return ret; - - davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, 0); + dev_err(&pdev->dev, "Failed to resume device\n"); + else + davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, 0); pm_runtime_dont_use_autosuspend(dev->dev); pm_runtime_put_sync(dev->dev); pm_runtime_disable(dev->dev); - - return 0; } #ifdef CONFIG_PM @@ -940,12 +935,16 @@ static const struct dev_pm_ops davinci_i2c_pm = { #define davinci_i2c_pm_ops NULL #endif -/* work with hotplug and coldplug */ -MODULE_ALIAS("platform:i2c_davinci"); +static const struct platform_device_id davinci_i2c_driver_ids[] = { + { .name = "i2c_davinci", }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(platform, davinci_i2c_driver_ids); static struct platform_driver davinci_i2c_driver = { .probe = davinci_i2c_probe, - .remove = davinci_i2c_remove, + .remove_new = davinci_i2c_remove, + .id_table = davinci_i2c_driver_ids, .driver = { .name = "i2c_davinci", .pm = davinci_i2c_pm_ops, diff --git a/drivers/i2c/busses/i2c-designware-common.c b/drivers/i2c/busses/i2c-designware-common.c index 0dc6b1ce663f747b6747ffa3bde2f3817c7d35ef..cdd8c67d91298681f5243f307fc77cd7a5536f15 100644 --- a/drivers/i2c/busses/i2c-designware-common.c +++ b/drivers/i2c/busses/i2c-designware-common.c @@ -575,6 +575,14 @@ int i2c_dw_set_fifo_size(struct dw_i2c_dev *dev) unsigned int param; int ret; + /* DW_IC_COMP_PARAM_1 not implement for IP issue */ + if ((dev->flags & MODEL_MASK) == MODEL_WANGXUN_SP) { + dev->tx_fifo_depth = TXGBE_TX_FIFO_DEPTH; + dev->rx_fifo_depth = TXGBE_RX_FIFO_DEPTH; + + return 0; + } + /* * Try to detect the FIFO depth if not set by interface driver, * the depth could be from 2 to 256 from HW spec. diff --git a/drivers/i2c/busses/i2c-designware-core.h b/drivers/i2c/busses/i2c-designware-core.h index bf23bfb51aead1e45c00cb2e44e28d609ecb40d1..cf4f684f535664ff59275d604cdbbbe7dc60939c 100644 --- a/drivers/i2c/busses/i2c-designware-core.h +++ b/drivers/i2c/busses/i2c-designware-core.h @@ -304,6 +304,7 @@ struct dw_i2c_dev { #define MODEL_MSCC_OCELOT BIT(8) #define MODEL_BAIKAL_BT1 BIT(9) #define MODEL_AMD_NAVI_GPU BIT(10) +#define MODEL_WANGXUN_SP BIT(11) #define MODEL_MASK GENMASK(11, 8) /* @@ -313,6 +314,9 @@ struct dw_i2c_dev { #define AMD_UCSI_INTR_REG 0x474 #define AMD_UCSI_INTR_EN 0xd +#define TXGBE_TX_FIFO_DEPTH 4 +#define TXGBE_RX_FIFO_DEPTH 0 + struct i2c_dw_semaphore_callbacks { int (*probe)(struct dw_i2c_dev *dev); void (*remove)(struct dw_i2c_dev *dev); diff --git a/drivers/i2c/busses/i2c-designware-master.c b/drivers/i2c/busses/i2c-designware-master.c index 55ea91a6338290c8844076067709f870edfcdcef..3bfd7a2232dbd0bb2fe2dfdfe0bece21c15c82a2 100644 --- a/drivers/i2c/busses/i2c-designware-master.c +++ b/drivers/i2c/busses/i2c-designware-master.c @@ -354,6 +354,68 @@ static int amd_i2c_dw_xfer_quirk(struct i2c_adapter *adap, struct i2c_msg *msgs, return 0; } +static int i2c_dw_poll_tx_empty(struct dw_i2c_dev *dev) +{ + u32 val; + + return regmap_read_poll_timeout(dev->map, DW_IC_RAW_INTR_STAT, val, + val & DW_IC_INTR_TX_EMPTY, + 100, 1000); +} + +static int i2c_dw_poll_rx_full(struct dw_i2c_dev *dev) +{ + u32 val; + + return regmap_read_poll_timeout(dev->map, DW_IC_RAW_INTR_STAT, val, + val & DW_IC_INTR_RX_FULL, + 100, 1000); +} + +static int txgbe_i2c_dw_xfer_quirk(struct i2c_adapter *adap, struct i2c_msg *msgs, + int num_msgs) +{ + struct dw_i2c_dev *dev = i2c_get_adapdata(adap); + int msg_idx, buf_len, data_idx, ret; + unsigned int val, stop = 0; + u8 *buf; + + dev->msgs = msgs; + dev->msgs_num = num_msgs; + i2c_dw_xfer_init(dev); + regmap_write(dev->map, DW_IC_INTR_MASK, 0); + + for (msg_idx = 0; msg_idx < num_msgs; msg_idx++) { + buf = msgs[msg_idx].buf; + buf_len = msgs[msg_idx].len; + + for (data_idx = 0; data_idx < buf_len; data_idx++) { + if (msg_idx == num_msgs - 1 && data_idx == buf_len - 1) + stop |= BIT(9); + + if (msgs[msg_idx].flags & I2C_M_RD) { + regmap_write(dev->map, DW_IC_DATA_CMD, 0x100 | stop); + + ret = i2c_dw_poll_rx_full(dev); + if (ret) + return ret; + + regmap_read(dev->map, DW_IC_DATA_CMD, &val); + buf[data_idx] = val; + } else { + ret = i2c_dw_poll_tx_empty(dev); + if (ret) + return ret; + + regmap_write(dev->map, DW_IC_DATA_CMD, + buf[data_idx] | stop); + } + } + } + + return num_msgs; +} + /* * Initiate (and continue) low level master read/write transaction. * This function is only called from i2c_dw_isr, and pumping i2c_msg @@ -559,13 +621,19 @@ i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) pm_runtime_get_sync(dev->dev); /* - * Initiate I2C message transfer when AMD NAVI GPU card is enabled, + * Initiate I2C message transfer when polling mode is enabled, * As it is polling based transfer mechanism, which does not support * interrupt based functionalities of existing DesignWare driver. */ - if ((dev->flags & MODEL_MASK) == MODEL_AMD_NAVI_GPU) { + switch (dev->flags & MODEL_MASK) { + case MODEL_AMD_NAVI_GPU: ret = amd_i2c_dw_xfer_quirk(adap, msgs, num); goto done_nolock; + case MODEL_WANGXUN_SP: + ret = txgbe_i2c_dw_xfer_quirk(adap, msgs, num); + goto done_nolock; + default: + break; } reinit_completion(&dev->cmd_complete); @@ -848,7 +916,7 @@ static int i2c_dw_init_recovery_info(struct dw_i2c_dev *dev) return 0; } -static int amd_i2c_adap_quirk(struct dw_i2c_dev *dev) +static int i2c_dw_poll_adap_quirk(struct dw_i2c_dev *dev) { struct i2c_adapter *adap = &dev->adapter; int ret; @@ -862,6 +930,17 @@ static int amd_i2c_adap_quirk(struct dw_i2c_dev *dev) return ret; } +static bool i2c_dw_is_model_poll(struct dw_i2c_dev *dev) +{ + switch (dev->flags & MODEL_MASK) { + case MODEL_AMD_NAVI_GPU: + case MODEL_WANGXUN_SP: + return true; + default: + return false; + } +} + int i2c_dw_probe_master(struct dw_i2c_dev *dev) { struct i2c_adapter *adap = &dev->adapter; @@ -917,8 +996,8 @@ int i2c_dw_probe_master(struct dw_i2c_dev *dev) adap->dev.parent = dev->dev; i2c_set_adapdata(adap, dev); - if ((dev->flags & MODEL_MASK) == MODEL_AMD_NAVI_GPU) - return amd_i2c_adap_quirk(dev); + if (i2c_dw_is_model_poll(dev)) + return i2c_dw_poll_adap_quirk(dev); if (dev->flags & ACCESS_NO_IRQ_SUSPEND) { irq_flags = IRQF_NO_SUSPEND; diff --git a/drivers/i2c/busses/i2c-designware-pcidrv.c b/drivers/i2c/busses/i2c-designware-pcidrv.c index 782fe1ef3ca10ec26eae70c8a0386dff90881000..61d7a27aa070184db6a7754561ad42c25c79de6c 100644 --- a/drivers/i2c/busses/i2c-designware-pcidrv.c +++ b/drivers/i2c/busses/i2c-designware-pcidrv.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -234,6 +235,16 @@ static const struct dev_pm_ops i2c_dw_pm_ops = { SET_RUNTIME_PM_OPS(i2c_dw_pci_runtime_suspend, i2c_dw_pci_runtime_resume, NULL) }; +static const struct property_entry dgpu_properties[] = { + /* USB-C doesn't power the system */ + PROPERTY_ENTRY_U8("scope", POWER_SUPPLY_SCOPE_DEVICE), + {} +}; + +static const struct software_node dgpu_node = { + .properties = dgpu_properties, +}; + static int i2c_dw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) { @@ -325,7 +336,7 @@ static int i2c_dw_pci_probe(struct pci_dev *pdev, } if ((dev->flags & MODEL_MASK) == MODEL_AMD_NAVI_GPU) { - dev->slave = i2c_new_ccgx_ucsi(&dev->adapter, dev->irq, NULL); + dev->slave = i2c_new_ccgx_ucsi(&dev->adapter, dev->irq, &dgpu_node); if (IS_ERR(dev->slave)) return dev_err_probe(dev->dev, PTR_ERR(dev->slave), "register UCSI failed\n"); diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c b/drivers/i2c/busses/i2c-designware-platdrv.c index 89ad88c547544b30cd6d961ef92e203145c7052b..970c1c3b0402753511e5619476547c184e40b60a 100644 --- a/drivers/i2c/busses/i2c-designware-platdrv.c +++ b/drivers/i2c/busses/i2c-designware-platdrv.c @@ -168,6 +168,15 @@ static inline int dw_i2c_of_configure(struct platform_device *pdev) } #endif +static int txgbe_i2c_request_regs(struct dw_i2c_dev *dev) +{ + dev->map = dev_get_regmap(dev->dev->parent, NULL); + if (!dev->map) + return -ENODEV; + + return 0; +} + static void dw_i2c_plat_pm_cleanup(struct dw_i2c_dev *dev) { pm_runtime_disable(dev->dev); @@ -185,6 +194,9 @@ static int dw_i2c_plat_request_regs(struct dw_i2c_dev *dev) case MODEL_BAIKAL_BT1: ret = bt1_i2c_request_regs(dev); break; + case MODEL_WANGXUN_SP: + ret = txgbe_i2c_request_regs(dev); + break; default: dev->base = devm_platform_ioremap_resource(pdev, 0); ret = PTR_ERR_OR_ZERO(dev->base); @@ -277,6 +289,9 @@ static int dw_i2c_plat_probe(struct platform_device *pdev) return -ENOMEM; dev->flags = (uintptr_t)device_get_match_data(&pdev->dev); + if (device_property_present(&pdev->dev, "wx,i2c-snps-model")) + dev->flags = MODEL_WANGXUN_SP; + dev->dev = &pdev->dev; dev->irq = irq; platform_set_drvdata(pdev, dev); @@ -384,7 +399,7 @@ static int dw_i2c_plat_probe(struct platform_device *pdev) return ret; } -static int dw_i2c_plat_remove(struct platform_device *pdev) +static void dw_i2c_plat_remove(struct platform_device *pdev) { struct dw_i2c_dev *dev = platform_get_drvdata(pdev); @@ -401,8 +416,6 @@ static int dw_i2c_plat_remove(struct platform_device *pdev) i2c_dw_remove_lock_support(dev); reset_control_assert(dev->rst); - - return 0; } #ifdef CONFIG_PM_SLEEP @@ -481,7 +494,7 @@ MODULE_ALIAS("platform:i2c_designware"); static struct platform_driver dw_i2c_driver = { .probe = dw_i2c_plat_probe, - .remove = dw_i2c_plat_remove, + .remove_new = dw_i2c_plat_remove, .driver = { .name = "i2c_designware", .of_match_table = of_match_ptr(dw_i2c_of_match), diff --git a/drivers/i2c/busses/i2c-digicolor.c b/drivers/i2c/busses/i2c-digicolor.c index 50925d97fa429c5a9b3dd306e753ef227d2b09fa..3462f2bc0fa87042a3a4f6f0790ad14b9dbfbab5 100644 --- a/drivers/i2c/busses/i2c-digicolor.c +++ b/drivers/i2c/busses/i2c-digicolor.c @@ -347,14 +347,12 @@ static int dc_i2c_probe(struct platform_device *pdev) return 0; } -static int dc_i2c_remove(struct platform_device *pdev) +static void dc_i2c_remove(struct platform_device *pdev) { struct dc_i2c *i2c = platform_get_drvdata(pdev); i2c_del_adapter(&i2c->adap); clk_disable_unprepare(i2c->clk); - - return 0; } static const struct of_device_id dc_i2c_match[] = { @@ -365,7 +363,7 @@ MODULE_DEVICE_TABLE(of, dc_i2c_match); static struct platform_driver dc_i2c_driver = { .probe = dc_i2c_probe, - .remove = dc_i2c_remove, + .remove_new = dc_i2c_remove, .driver = { .name = "digicolor-i2c", .of_match_table = dc_i2c_match, diff --git a/drivers/i2c/busses/i2c-dln2.c b/drivers/i2c/busses/i2c-dln2.c index 2a2089db71a5e0ee95420e2d8b8d5b5a3036146b..4f02cc2fb567559984d0469fa73a4eebde80cfdb 100644 --- a/drivers/i2c/busses/i2c-dln2.c +++ b/drivers/i2c/busses/i2c-dln2.c @@ -236,20 +236,18 @@ static int dln2_i2c_probe(struct platform_device *pdev) return ret; } -static int dln2_i2c_remove(struct platform_device *pdev) +static void dln2_i2c_remove(struct platform_device *pdev) { struct dln2_i2c *dln2 = platform_get_drvdata(pdev); i2c_del_adapter(&dln2->adapter); dln2_i2c_enable(dln2, false); - - return 0; } static struct platform_driver dln2_i2c_driver = { .driver.name = "dln2-i2c", .probe = dln2_i2c_probe, - .remove = dln2_i2c_remove, + .remove_new = dln2_i2c_remove, }; module_platform_driver(dln2_i2c_driver); diff --git a/drivers/i2c/busses/i2c-emev2.c b/drivers/i2c/busses/i2c-emev2.c index f2e537b137b2004f87e24d7bc7180e3bdca7a9b7..4ba93cd91c0f01431595c1bb557b431fa57a611c 100644 --- a/drivers/i2c/busses/i2c-emev2.c +++ b/drivers/i2c/busses/i2c-emev2.c @@ -419,14 +419,12 @@ static int em_i2c_probe(struct platform_device *pdev) return ret; } -static int em_i2c_remove(struct platform_device *dev) +static void em_i2c_remove(struct platform_device *dev) { struct em_i2c_device *priv = platform_get_drvdata(dev); i2c_del_adapter(&priv->adap); clk_disable_unprepare(priv->sclk); - - return 0; } static const struct of_device_id em_i2c_ids[] = { @@ -436,7 +434,7 @@ static const struct of_device_id em_i2c_ids[] = { static struct platform_driver em_i2c_driver = { .probe = em_i2c_probe, - .remove = em_i2c_remove, + .remove_new = em_i2c_remove, .driver = { .name = "em-i2c", .of_match_table = em_i2c_ids, diff --git a/drivers/i2c/busses/i2c-exynos5.c b/drivers/i2c/busses/i2c-exynos5.c index 4a6260d04db2810fdd89505211428e97d1401c51..f378cd479e558429b860e2b06e67609b3dcd8ce0 100644 --- a/drivers/i2c/busses/i2c-exynos5.c +++ b/drivers/i2c/busses/i2c-exynos5.c @@ -882,7 +882,7 @@ static int exynos5_i2c_probe(struct platform_device *pdev) return ret; } -static int exynos5_i2c_remove(struct platform_device *pdev) +static void exynos5_i2c_remove(struct platform_device *pdev) { struct exynos5_i2c *i2c = platform_get_drvdata(pdev); @@ -890,8 +890,6 @@ static int exynos5_i2c_remove(struct platform_device *pdev) clk_unprepare(i2c->clk); clk_unprepare(i2c->pclk); - - return 0; } #ifdef CONFIG_PM_SLEEP @@ -945,7 +943,7 @@ static const struct dev_pm_ops exynos5_i2c_dev_pm_ops = { static struct platform_driver exynos5_i2c_driver = { .probe = exynos5_i2c_probe, - .remove = exynos5_i2c_remove, + .remove_new = exynos5_i2c_remove, .driver = { .name = "exynos5-hsi2c", .pm = &exynos5_i2c_dev_pm_ops, diff --git a/drivers/i2c/busses/i2c-gpio.c b/drivers/i2c/busses/i2c-gpio.c index 1794c0399f22d453127dbe1af6f36e694c3f6768..e5a5b9e8bf2c760719eafa5298cf22755c9f25a0 100644 --- a/drivers/i2c/busses/i2c-gpio.c +++ b/drivers/i2c/busses/i2c-gpio.c @@ -475,7 +475,7 @@ static int i2c_gpio_probe(struct platform_device *pdev) return 0; } -static int i2c_gpio_remove(struct platform_device *pdev) +static void i2c_gpio_remove(struct platform_device *pdev) { struct i2c_gpio_private_data *priv; struct i2c_adapter *adap; @@ -486,8 +486,6 @@ static int i2c_gpio_remove(struct platform_device *pdev) adap = &priv->adap; i2c_del_adapter(adap); - - return 0; } static const struct of_device_id i2c_gpio_dt_ids[] = { @@ -510,7 +508,7 @@ static struct platform_driver i2c_gpio_driver = { .acpi_match_table = i2c_gpio_acpi_match, }, .probe = i2c_gpio_probe, - .remove = i2c_gpio_remove, + .remove_new = i2c_gpio_remove, }; static int __init i2c_gpio_init(void) diff --git a/drivers/i2c/busses/i2c-gxp.c b/drivers/i2c/busses/i2c-gxp.c index 8ea3fb5e4c7f7f9100000977489b6754e5a73acb..70b0de07ed99a1156821c12fa44c0186c87a07d7 100644 --- a/drivers/i2c/busses/i2c-gxp.c +++ b/drivers/i2c/busses/i2c-gxp.c @@ -577,15 +577,13 @@ static int gxp_i2c_probe(struct platform_device *pdev) return 0; } -static int gxp_i2c_remove(struct platform_device *pdev) +static void gxp_i2c_remove(struct platform_device *pdev) { struct gxp_i2c_drvdata *drvdata = platform_get_drvdata(pdev); /* Disable interrupt */ regmap_update_bits(i2cg_map, GXP_I2CINTEN, BIT(drvdata->engine), 0); i2c_del_adapter(&drvdata->adapter); - - return 0; } static const struct of_device_id gxp_i2c_of_match[] = { @@ -596,7 +594,7 @@ MODULE_DEVICE_TABLE(of, gxp_i2c_of_match); static struct platform_driver gxp_i2c_driver = { .probe = gxp_i2c_probe, - .remove = gxp_i2c_remove, + .remove_new = gxp_i2c_remove, .driver = { .name = "gxp-i2c", .of_match_table = gxp_i2c_of_match, diff --git a/drivers/i2c/busses/i2c-highlander.c b/drivers/i2c/busses/i2c-highlander.c index 4374a8677271765783ac31e9e42a3c2d32a34315..7922bc917c33a7a41255bdc10bf1892a325ede9c 100644 --- a/drivers/i2c/busses/i2c-highlander.c +++ b/drivers/i2c/busses/i2c-highlander.c @@ -435,7 +435,7 @@ static int highlander_i2c_probe(struct platform_device *pdev) return ret; } -static int highlander_i2c_remove(struct platform_device *pdev) +static void highlander_i2c_remove(struct platform_device *pdev) { struct highlander_i2c_dev *dev = platform_get_drvdata(pdev); @@ -446,8 +446,6 @@ static int highlander_i2c_remove(struct platform_device *pdev) iounmap(dev->base); kfree(dev); - - return 0; } static struct platform_driver highlander_i2c_driver = { @@ -456,7 +454,7 @@ static struct platform_driver highlander_i2c_driver = { }, .probe = highlander_i2c_probe, - .remove = highlander_i2c_remove, + .remove_new = highlander_i2c_remove, }; module_platform_driver(highlander_i2c_driver); diff --git a/drivers/i2c/busses/i2c-hix5hd2.c b/drivers/i2c/busses/i2c-hix5hd2.c index 0e34cbaca22dc37c4bcc7a39a60dda6104f0971b..784a5f56eb76507c1e883c72c4b9f8f552a6223c 100644 --- a/drivers/i2c/busses/i2c-hix5hd2.c +++ b/drivers/i2c/busses/i2c-hix5hd2.c @@ -360,7 +360,11 @@ static int hix5hd2_i2c_xfer(struct i2c_adapter *adap, pm_runtime_get_sync(priv->dev); for (i = 0; i < num; i++, msgs++) { - stop = (i == num - 1); + if ((i == num - 1) || (msgs->flags & I2C_M_STOP)) + stop = 1; + else + stop = 0; + ret = hix5hd2_i2c_xfer_msg(priv, msgs, stop); if (ret < 0) goto out; @@ -416,12 +420,11 @@ static int hix5hd2_i2c_probe(struct platform_device *pdev) if (irq < 0) return irq; - priv->clk = devm_clk_get(&pdev->dev, NULL); + priv->clk = devm_clk_get_enabled(&pdev->dev, NULL); if (IS_ERR(priv->clk)) { - dev_err(&pdev->dev, "cannot get clock\n"); + dev_err(&pdev->dev, "cannot enable clock\n"); return PTR_ERR(priv->clk); } - clk_prepare_enable(priv->clk); strscpy(priv->adap.name, "hix5hd2-i2c", sizeof(priv->adap.name)); priv->dev = &pdev->dev; @@ -442,7 +445,7 @@ static int hix5hd2_i2c_probe(struct platform_device *pdev) IRQF_NO_SUSPEND, dev_name(&pdev->dev), priv); if (ret != 0) { dev_err(&pdev->dev, "cannot request HS-I2C IRQ %d\n", irq); - goto err_clk; + return ret; } pm_runtime_set_autosuspend_delay(priv->dev, MSEC_PER_SEC); @@ -459,21 +462,17 @@ static int hix5hd2_i2c_probe(struct platform_device *pdev) err_runtime: pm_runtime_disable(priv->dev); pm_runtime_set_suspended(priv->dev); -err_clk: - clk_disable_unprepare(priv->clk); + return ret; } -static int hix5hd2_i2c_remove(struct platform_device *pdev) +static void hix5hd2_i2c_remove(struct platform_device *pdev) { struct hix5hd2_i2c_priv *priv = platform_get_drvdata(pdev); i2c_del_adapter(&priv->adap); pm_runtime_disable(priv->dev); pm_runtime_set_suspended(priv->dev); - clk_disable_unprepare(priv->clk); - - return 0; } #ifdef CONFIG_PM @@ -511,7 +510,7 @@ MODULE_DEVICE_TABLE(of, hix5hd2_i2c_match); static struct platform_driver hix5hd2_i2c_driver = { .probe = hix5hd2_i2c_probe, - .remove = hix5hd2_i2c_remove, + .remove_new = hix5hd2_i2c_remove, .driver = { .name = "hix5hd2-i2c", .pm = &hix5hd2_i2c_pm_ops, diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index ac5326747c5197630eb8b85ab3ca14ac907f17c7..943b8e6d026dab31aa254e14099f818eca36378b 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -77,6 +77,8 @@ * Alder Lake-M (PCH) 0x54a3 32 hard yes yes yes * Raptor Lake-S (PCH) 0x7a23 32 hard yes yes yes * Meteor Lake-P (SOC) 0x7e22 32 hard yes yes yes + * Meteor Lake SoC-S (SOC) 0xae22 32 hard yes yes yes + * Meteor Lake PCH-S (PCH) 0x7f23 32 hard yes yes yes * * Features supported by this driver: * Software PEC no @@ -233,6 +235,7 @@ #define PCI_DEVICE_ID_INTEL_RAPTOR_LAKE_S_SMBUS 0x7a23 #define PCI_DEVICE_ID_INTEL_ALDER_LAKE_S_SMBUS 0x7aa3 #define PCI_DEVICE_ID_INTEL_METEOR_LAKE_P_SMBUS 0x7e22 +#define PCI_DEVICE_ID_INTEL_METEOR_LAKE_PCH_S_SMBUS 0x7f23 #define PCI_DEVICE_ID_INTEL_LYNXPOINT_SMBUS 0x8c22 #define PCI_DEVICE_ID_INTEL_WILDCATPOINT_SMBUS 0x8ca2 #define PCI_DEVICE_ID_INTEL_WELLSBURG_SMBUS 0x8d22 @@ -250,6 +253,7 @@ #define PCI_DEVICE_ID_INTEL_KABYLAKE_PCH_H_SMBUS 0xa2a3 #define PCI_DEVICE_ID_INTEL_CANNONLAKE_H_SMBUS 0xa323 #define PCI_DEVICE_ID_INTEL_COMETLAKE_V_SMBUS 0xa3a3 +#define PCI_DEVICE_ID_INTEL_METEOR_LAKE_SOC_S_SMBUS 0xae22 struct i801_mux_config { char *gpio_chip; @@ -977,67 +981,69 @@ static const struct i2c_algorithm smbus_algorithm = { FEATURE_HOST_NOTIFY) static const struct pci_device_id i801_ids[] = { - { PCI_DEVICE_DATA(INTEL, 82801AA_3, 0) }, - { PCI_DEVICE_DATA(INTEL, 82801AB_3, 0) }, - { PCI_DEVICE_DATA(INTEL, 82801BA_2, 0) }, - { PCI_DEVICE_DATA(INTEL, 82801CA_3, FEATURE_HOST_NOTIFY) }, - { PCI_DEVICE_DATA(INTEL, 82801DB_3, FEATURES_ICH4) }, - { PCI_DEVICE_DATA(INTEL, 82801EB_3, FEATURES_ICH5) }, - { PCI_DEVICE_DATA(INTEL, ESB_4, FEATURES_ICH5) }, - { PCI_DEVICE_DATA(INTEL, ICH6_16, FEATURES_ICH5) }, - { PCI_DEVICE_DATA(INTEL, ICH7_17, FEATURES_ICH5) }, - { PCI_DEVICE_DATA(INTEL, ESB2_17, FEATURES_ICH5) }, - { PCI_DEVICE_DATA(INTEL, ICH8_5, FEATURES_ICH5) }, - { PCI_DEVICE_DATA(INTEL, ICH9_6, FEATURES_ICH5) }, - { PCI_DEVICE_DATA(INTEL, EP80579_1, FEATURES_ICH5) }, - { PCI_DEVICE_DATA(INTEL, ICH10_4, FEATURES_ICH5) }, - { PCI_DEVICE_DATA(INTEL, ICH10_5, FEATURES_ICH5) }, - { PCI_DEVICE_DATA(INTEL, 5_3400_SERIES_SMBUS, FEATURES_ICH5) }, - { PCI_DEVICE_DATA(INTEL, COUGARPOINT_SMBUS, FEATURES_ICH5) }, - { PCI_DEVICE_DATA(INTEL, PATSBURG_SMBUS, FEATURES_ICH5) }, - { PCI_DEVICE_DATA(INTEL, PATSBURG_SMBUS_IDF0, FEATURES_ICH5 | FEATURE_IDF) }, - { PCI_DEVICE_DATA(INTEL, PATSBURG_SMBUS_IDF1, FEATURES_ICH5 | FEATURE_IDF) }, - { PCI_DEVICE_DATA(INTEL, PATSBURG_SMBUS_IDF2, FEATURES_ICH5 | FEATURE_IDF) }, - { PCI_DEVICE_DATA(INTEL, DH89XXCC_SMBUS, FEATURES_ICH5) }, - { PCI_DEVICE_DATA(INTEL, PANTHERPOINT_SMBUS, FEATURES_ICH5) }, - { PCI_DEVICE_DATA(INTEL, LYNXPOINT_SMBUS, FEATURES_ICH5) }, - { PCI_DEVICE_DATA(INTEL, LYNXPOINT_LP_SMBUS, FEATURES_ICH5) }, - { PCI_DEVICE_DATA(INTEL, AVOTON_SMBUS, FEATURES_ICH5) }, - { PCI_DEVICE_DATA(INTEL, WELLSBURG_SMBUS, FEATURES_ICH5) }, - { PCI_DEVICE_DATA(INTEL, WELLSBURG_SMBUS_MS0, FEATURES_ICH5 | FEATURE_IDF) }, - { PCI_DEVICE_DATA(INTEL, WELLSBURG_SMBUS_MS1, FEATURES_ICH5 | FEATURE_IDF) }, - { PCI_DEVICE_DATA(INTEL, WELLSBURG_SMBUS_MS2, FEATURES_ICH5 | FEATURE_IDF) }, - { PCI_DEVICE_DATA(INTEL, COLETOCREEK_SMBUS, FEATURES_ICH5) }, - { PCI_DEVICE_DATA(INTEL, GEMINILAKE_SMBUS, FEATURES_ICH5) }, - { PCI_DEVICE_DATA(INTEL, WILDCATPOINT_SMBUS, FEATURES_ICH5) }, - { PCI_DEVICE_DATA(INTEL, WILDCATPOINT_LP_SMBUS, FEATURES_ICH5) }, - { PCI_DEVICE_DATA(INTEL, BAYTRAIL_SMBUS, FEATURES_ICH5) }, - { PCI_DEVICE_DATA(INTEL, BRASWELL_SMBUS, FEATURES_ICH5) }, - { PCI_DEVICE_DATA(INTEL, SUNRISEPOINT_H_SMBUS, FEATURES_ICH5 | FEATURE_TCO_SPT) }, - { PCI_DEVICE_DATA(INTEL, SUNRISEPOINT_LP_SMBUS, FEATURES_ICH5 | FEATURE_TCO_SPT) }, - { PCI_DEVICE_DATA(INTEL, CDF_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, - { PCI_DEVICE_DATA(INTEL, DNV_SMBUS, FEATURES_ICH5 | FEATURE_TCO_SPT) }, - { PCI_DEVICE_DATA(INTEL, EBG_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, - { PCI_DEVICE_DATA(INTEL, BROXTON_SMBUS, FEATURES_ICH5) }, - { PCI_DEVICE_DATA(INTEL, LEWISBURG_SMBUS, FEATURES_ICH5 | FEATURE_TCO_SPT) }, - { PCI_DEVICE_DATA(INTEL, LEWISBURG_SSKU_SMBUS, FEATURES_ICH5 | FEATURE_TCO_SPT) }, - { PCI_DEVICE_DATA(INTEL, KABYLAKE_PCH_H_SMBUS, FEATURES_ICH5 | FEATURE_TCO_SPT) }, - { PCI_DEVICE_DATA(INTEL, CANNONLAKE_H_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, - { PCI_DEVICE_DATA(INTEL, CANNONLAKE_LP_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, - { PCI_DEVICE_DATA(INTEL, ICELAKE_LP_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, - { PCI_DEVICE_DATA(INTEL, ICELAKE_N_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, - { PCI_DEVICE_DATA(INTEL, COMETLAKE_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, - { PCI_DEVICE_DATA(INTEL, COMETLAKE_H_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, - { PCI_DEVICE_DATA(INTEL, COMETLAKE_V_SMBUS, FEATURES_ICH5 | FEATURE_TCO_SPT) }, - { PCI_DEVICE_DATA(INTEL, ELKHART_LAKE_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, - { PCI_DEVICE_DATA(INTEL, TIGERLAKE_LP_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, - { PCI_DEVICE_DATA(INTEL, TIGERLAKE_H_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, - { PCI_DEVICE_DATA(INTEL, JASPER_LAKE_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, - { PCI_DEVICE_DATA(INTEL, ALDER_LAKE_S_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, - { PCI_DEVICE_DATA(INTEL, ALDER_LAKE_P_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, - { PCI_DEVICE_DATA(INTEL, ALDER_LAKE_M_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, - { PCI_DEVICE_DATA(INTEL, RAPTOR_LAKE_S_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, - { PCI_DEVICE_DATA(INTEL, METEOR_LAKE_P_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, + { PCI_DEVICE_DATA(INTEL, 82801AA_3, 0) }, + { PCI_DEVICE_DATA(INTEL, 82801AB_3, 0) }, + { PCI_DEVICE_DATA(INTEL, 82801BA_2, 0) }, + { PCI_DEVICE_DATA(INTEL, 82801CA_3, FEATURE_HOST_NOTIFY) }, + { PCI_DEVICE_DATA(INTEL, 82801DB_3, FEATURES_ICH4) }, + { PCI_DEVICE_DATA(INTEL, 82801EB_3, FEATURES_ICH5) }, + { PCI_DEVICE_DATA(INTEL, ESB_4, FEATURES_ICH5) }, + { PCI_DEVICE_DATA(INTEL, ICH6_16, FEATURES_ICH5) }, + { PCI_DEVICE_DATA(INTEL, ICH7_17, FEATURES_ICH5) }, + { PCI_DEVICE_DATA(INTEL, ESB2_17, FEATURES_ICH5) }, + { PCI_DEVICE_DATA(INTEL, ICH8_5, FEATURES_ICH5) }, + { PCI_DEVICE_DATA(INTEL, ICH9_6, FEATURES_ICH5) }, + { PCI_DEVICE_DATA(INTEL, EP80579_1, FEATURES_ICH5) }, + { PCI_DEVICE_DATA(INTEL, ICH10_4, FEATURES_ICH5) }, + { PCI_DEVICE_DATA(INTEL, ICH10_5, FEATURES_ICH5) }, + { PCI_DEVICE_DATA(INTEL, 5_3400_SERIES_SMBUS, FEATURES_ICH5) }, + { PCI_DEVICE_DATA(INTEL, COUGARPOINT_SMBUS, FEATURES_ICH5) }, + { PCI_DEVICE_DATA(INTEL, PATSBURG_SMBUS, FEATURES_ICH5) }, + { PCI_DEVICE_DATA(INTEL, PATSBURG_SMBUS_IDF0, FEATURES_ICH5 | FEATURE_IDF) }, + { PCI_DEVICE_DATA(INTEL, PATSBURG_SMBUS_IDF1, FEATURES_ICH5 | FEATURE_IDF) }, + { PCI_DEVICE_DATA(INTEL, PATSBURG_SMBUS_IDF2, FEATURES_ICH5 | FEATURE_IDF) }, + { PCI_DEVICE_DATA(INTEL, DH89XXCC_SMBUS, FEATURES_ICH5) }, + { PCI_DEVICE_DATA(INTEL, PANTHERPOINT_SMBUS, FEATURES_ICH5) }, + { PCI_DEVICE_DATA(INTEL, LYNXPOINT_SMBUS, FEATURES_ICH5) }, + { PCI_DEVICE_DATA(INTEL, LYNXPOINT_LP_SMBUS, FEATURES_ICH5) }, + { PCI_DEVICE_DATA(INTEL, AVOTON_SMBUS, FEATURES_ICH5) }, + { PCI_DEVICE_DATA(INTEL, WELLSBURG_SMBUS, FEATURES_ICH5) }, + { PCI_DEVICE_DATA(INTEL, WELLSBURG_SMBUS_MS0, FEATURES_ICH5 | FEATURE_IDF) }, + { PCI_DEVICE_DATA(INTEL, WELLSBURG_SMBUS_MS1, FEATURES_ICH5 | FEATURE_IDF) }, + { PCI_DEVICE_DATA(INTEL, WELLSBURG_SMBUS_MS2, FEATURES_ICH5 | FEATURE_IDF) }, + { PCI_DEVICE_DATA(INTEL, COLETOCREEK_SMBUS, FEATURES_ICH5) }, + { PCI_DEVICE_DATA(INTEL, GEMINILAKE_SMBUS, FEATURES_ICH5) }, + { PCI_DEVICE_DATA(INTEL, WILDCATPOINT_SMBUS, FEATURES_ICH5) }, + { PCI_DEVICE_DATA(INTEL, WILDCATPOINT_LP_SMBUS, FEATURES_ICH5) }, + { PCI_DEVICE_DATA(INTEL, BAYTRAIL_SMBUS, FEATURES_ICH5) }, + { PCI_DEVICE_DATA(INTEL, BRASWELL_SMBUS, FEATURES_ICH5) }, + { PCI_DEVICE_DATA(INTEL, SUNRISEPOINT_H_SMBUS, FEATURES_ICH5 | FEATURE_TCO_SPT) }, + { PCI_DEVICE_DATA(INTEL, SUNRISEPOINT_LP_SMBUS, FEATURES_ICH5 | FEATURE_TCO_SPT) }, + { PCI_DEVICE_DATA(INTEL, CDF_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, + { PCI_DEVICE_DATA(INTEL, DNV_SMBUS, FEATURES_ICH5 | FEATURE_TCO_SPT) }, + { PCI_DEVICE_DATA(INTEL, EBG_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, + { PCI_DEVICE_DATA(INTEL, BROXTON_SMBUS, FEATURES_ICH5) }, + { PCI_DEVICE_DATA(INTEL, LEWISBURG_SMBUS, FEATURES_ICH5 | FEATURE_TCO_SPT) }, + { PCI_DEVICE_DATA(INTEL, LEWISBURG_SSKU_SMBUS, FEATURES_ICH5 | FEATURE_TCO_SPT) }, + { PCI_DEVICE_DATA(INTEL, KABYLAKE_PCH_H_SMBUS, FEATURES_ICH5 | FEATURE_TCO_SPT) }, + { PCI_DEVICE_DATA(INTEL, CANNONLAKE_H_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, + { PCI_DEVICE_DATA(INTEL, CANNONLAKE_LP_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, + { PCI_DEVICE_DATA(INTEL, ICELAKE_LP_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, + { PCI_DEVICE_DATA(INTEL, ICELAKE_N_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, + { PCI_DEVICE_DATA(INTEL, COMETLAKE_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, + { PCI_DEVICE_DATA(INTEL, COMETLAKE_H_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, + { PCI_DEVICE_DATA(INTEL, COMETLAKE_V_SMBUS, FEATURES_ICH5 | FEATURE_TCO_SPT) }, + { PCI_DEVICE_DATA(INTEL, ELKHART_LAKE_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, + { PCI_DEVICE_DATA(INTEL, TIGERLAKE_LP_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, + { PCI_DEVICE_DATA(INTEL, TIGERLAKE_H_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, + { PCI_DEVICE_DATA(INTEL, JASPER_LAKE_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, + { PCI_DEVICE_DATA(INTEL, ALDER_LAKE_S_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, + { PCI_DEVICE_DATA(INTEL, ALDER_LAKE_P_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, + { PCI_DEVICE_DATA(INTEL, ALDER_LAKE_M_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, + { PCI_DEVICE_DATA(INTEL, RAPTOR_LAKE_S_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, + { PCI_DEVICE_DATA(INTEL, METEOR_LAKE_P_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, + { PCI_DEVICE_DATA(INTEL, METEOR_LAKE_SOC_S_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, + { PCI_DEVICE_DATA(INTEL, METEOR_LAKE_PCH_S_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, { 0, } }; diff --git a/drivers/i2c/busses/i2c-ibm_iic.c b/drivers/i2c/busses/i2c-ibm_iic.c index eeb80e34f9ad711337879106655628d32993be31..1ad9d3b26dd3f6da1bef39ebde308df97ee96069 100644 --- a/drivers/i2c/busses/i2c-ibm_iic.c +++ b/drivers/i2c/busses/i2c-ibm_iic.c @@ -694,10 +694,8 @@ static int iic_probe(struct platform_device *ofdev) int ret; dev = kzalloc(sizeof(*dev), GFP_KERNEL); - if (!dev) { - dev_err(&ofdev->dev, "failed to allocate device data\n"); + if (!dev) return -ENOMEM; - } platform_set_drvdata(ofdev, dev); @@ -769,7 +767,7 @@ static int iic_probe(struct platform_device *ofdev) /* * Cleanup initialized IIC interface */ -static int iic_remove(struct platform_device *ofdev) +static void iic_remove(struct platform_device *ofdev) { struct ibm_iic_private *dev = platform_get_drvdata(ofdev); @@ -782,8 +780,6 @@ static int iic_remove(struct platform_device *ofdev) iounmap(dev->vaddr); kfree(dev); - - return 0; } static const struct of_device_id ibm_iic_match[] = { @@ -798,7 +794,7 @@ static struct platform_driver ibm_iic_driver = { .of_match_table = ibm_iic_match, }, .probe = iic_probe, - .remove = iic_remove, + .remove_new = iic_remove, }; module_platform_driver(ibm_iic_driver); diff --git a/drivers/i2c/busses/i2c-img-scb.c b/drivers/i2c/busses/i2c-img-scb.c index 39c479f96eb58564b75e91f4650cf31e1345433f..66ba36949ab59c0414fd3df004aec219aa67013c 100644 --- a/drivers/i2c/busses/i2c-img-scb.c +++ b/drivers/i2c/busses/i2c-img-scb.c @@ -913,7 +913,7 @@ static unsigned int img_i2c_auto(struct img_i2c *i2c, static irqreturn_t img_i2c_isr(int irq, void *dev_id) { - struct img_i2c *i2c = (struct img_i2c *)dev_id; + struct img_i2c *i2c = dev_id; u32 int_status, line_status; /* We handle transaction completion AFTER accessing registers */ unsigned int hret; @@ -1413,7 +1413,7 @@ static int img_i2c_probe(struct platform_device *pdev) return ret; } -static int img_i2c_remove(struct platform_device *dev) +static void img_i2c_remove(struct platform_device *dev) { struct img_i2c *i2c = platform_get_drvdata(dev); @@ -1421,8 +1421,6 @@ static int img_i2c_remove(struct platform_device *dev) pm_runtime_disable(&dev->dev); if (!pm_runtime_status_suspended(&dev->dev)) img_i2c_runtime_suspend(&dev->dev); - - return 0; } static int img_i2c_runtime_suspend(struct device *dev) @@ -1506,7 +1504,7 @@ static struct platform_driver img_scb_i2c_driver = { .pm = &img_i2c_pm, }, .probe = img_i2c_probe, - .remove = img_i2c_remove, + .remove_new = img_i2c_remove, }; module_platform_driver(img_scb_i2c_driver); diff --git a/drivers/i2c/busses/i2c-imx-lpi2c.c b/drivers/i2c/busses/i2c-imx-lpi2c.c index 1af0a637d7f1414b033f5c0231c75a4ece2353bd..c3287c887c6fa78428ccc2f2bd0f855632da5da2 100644 --- a/drivers/i2c/busses/i2c-imx-lpi2c.c +++ b/drivers/i2c/busses/i2c-imx-lpi2c.c @@ -201,8 +201,8 @@ static void lpi2c_imx_stop(struct lpi2c_imx_struct *lpi2c_imx) /* CLKLO = I2C_CLK_RATIO * CLKHI, SETHOLD = CLKHI, DATAVD = CLKHI/2 */ static int lpi2c_imx_config(struct lpi2c_imx_struct *lpi2c_imx) { - u8 prescale, filt, sethold, clkhi, clklo, datavd; - unsigned int clk_rate, clk_cycle; + u8 prescale, filt, sethold, datavd; + unsigned int clk_rate, clk_cycle, clkhi, clklo; enum lpi2c_imx_pincfg pincfg; unsigned int temp; @@ -217,7 +217,7 @@ static int lpi2c_imx_config(struct lpi2c_imx_struct *lpi2c_imx) for (prescale = 0; prescale <= 7; prescale++) { clk_cycle = clk_rate / ((1 << prescale) * lpi2c_imx->bitrate) - 3 - (filt >> 1); - clkhi = (clk_cycle + I2C_CLK_RATIO) / (I2C_CLK_RATIO + 1); + clkhi = DIV_ROUND_UP(clk_cycle, I2C_CLK_RATIO + 1); clklo = clk_cycle - clkhi; if (clklo < 64) break; @@ -623,7 +623,7 @@ static int lpi2c_imx_probe(struct platform_device *pdev) return ret; } -static int lpi2c_imx_remove(struct platform_device *pdev) +static void lpi2c_imx_remove(struct platform_device *pdev) { struct lpi2c_imx_struct *lpi2c_imx = platform_get_drvdata(pdev); @@ -631,8 +631,6 @@ static int lpi2c_imx_remove(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); pm_runtime_dont_use_autosuspend(&pdev->dev); - - return 0; } static int __maybe_unused lpi2c_runtime_suspend(struct device *dev) @@ -669,7 +667,7 @@ static const struct dev_pm_ops lpi2c_pm_ops = { static struct platform_driver lpi2c_imx_driver = { .probe = lpi2c_imx_probe, - .remove = lpi2c_imx_remove, + .remove_new = lpi2c_imx_remove, .driver = { .name = DRIVER_NAME, .of_match_table = lpi2c_imx_of_match, diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c index 42189a5f29051d63619884a65fac0c48b87058b9..65128a73e8a325eda8ed8ff4eddc554a8695e617 100644 --- a/drivers/i2c/busses/i2c-imx.c +++ b/drivers/i2c/busses/i2c-imx.c @@ -1561,7 +1561,7 @@ static int i2c_imx_probe(struct platform_device *pdev) return ret; } -static int i2c_imx_remove(struct platform_device *pdev) +static void i2c_imx_remove(struct platform_device *pdev) { struct imx_i2c_struct *i2c_imx = platform_get_drvdata(pdev); int irq, ret; @@ -1592,8 +1592,6 @@ static int i2c_imx_remove(struct platform_device *pdev) pm_runtime_put_noidle(&pdev->dev); pm_runtime_disable(&pdev->dev); - - return 0; } static int __maybe_unused i2c_imx_runtime_suspend(struct device *dev) @@ -1624,7 +1622,7 @@ static const struct dev_pm_ops i2c_imx_pm_ops = { static struct platform_driver i2c_imx_driver = { .probe = i2c_imx_probe, - .remove = i2c_imx_remove, + .remove_new = i2c_imx_remove, .driver = { .name = DRIVER_NAME, .pm = &i2c_imx_pm_ops, diff --git a/drivers/i2c/busses/i2c-iop3xx.c b/drivers/i2c/busses/i2c-iop3xx.c index 4a6ff54d87fe8ce158010edc5809338fa269d68f..f2f7ebeeaecb0345edb1e8c9cc7aa222d1970d88 100644 --- a/drivers/i2c/busses/i2c-iop3xx.c +++ b/drivers/i2c/busses/i2c-iop3xx.c @@ -388,7 +388,7 @@ static const struct i2c_algorithm iop3xx_i2c_algo = { .functionality = iop3xx_i2c_func, }; -static int +static void iop3xx_i2c_remove(struct platform_device *pdev) { struct i2c_adapter *padapter = platform_get_drvdata(pdev); @@ -408,8 +408,6 @@ iop3xx_i2c_remove(struct platform_device *pdev) release_mem_region(res->start, IOP3XX_I2C_IO_SIZE); kfree(adapter_data); kfree(padapter); - - return 0; } static int @@ -529,7 +527,7 @@ MODULE_DEVICE_TABLE(of, i2c_iop3xx_match); static struct platform_driver iop3xx_i2c_driver = { .probe = iop3xx_i2c_probe, - .remove = iop3xx_i2c_remove, + .remove_new = iop3xx_i2c_remove, .driver = { .name = "IOP3xx-I2C", .of_match_table = i2c_iop3xx_match, diff --git a/drivers/i2c/busses/i2c-isch.c b/drivers/i2c/busses/i2c-isch.c index 2dc7ada06ac5058c913780c3471d7c5cb4dee6ad..1dc1ceaa44439f67566008606f6b543e8f386509 100644 --- a/drivers/i2c/busses/i2c-isch.c +++ b/drivers/i2c/busses/i2c-isch.c @@ -286,14 +286,12 @@ static int smbus_sch_probe(struct platform_device *dev) return retval; } -static int smbus_sch_remove(struct platform_device *pdev) +static void smbus_sch_remove(struct platform_device *pdev) { if (sch_smba) { i2c_del_adapter(&sch_adapter); sch_smba = 0; } - - return 0; } static struct platform_driver smbus_sch_driver = { @@ -301,7 +299,7 @@ static struct platform_driver smbus_sch_driver = { .name = "isch_smbus", }, .probe = smbus_sch_probe, - .remove = smbus_sch_remove, + .remove_new = smbus_sch_remove, }; module_platform_driver(smbus_sch_driver); diff --git a/drivers/i2c/busses/i2c-jz4780.c b/drivers/i2c/busses/i2c-jz4780.c index baa7319eee53973bb8dc26242d189f0d480f06a5..0dfe6039952147c7d3ef96ae79c54625f7f47fe1 100644 --- a/drivers/i2c/busses/i2c-jz4780.c +++ b/drivers/i2c/busses/i2c-jz4780.c @@ -845,18 +845,17 @@ static int jz4780_i2c_probe(struct platform_device *pdev) return ret; } -static int jz4780_i2c_remove(struct platform_device *pdev) +static void jz4780_i2c_remove(struct platform_device *pdev) { struct jz4780_i2c *i2c = platform_get_drvdata(pdev); clk_disable_unprepare(i2c->clk); i2c_del_adapter(&i2c->adap); - return 0; } static struct platform_driver jz4780_i2c_driver = { .probe = jz4780_i2c_probe, - .remove = jz4780_i2c_remove, + .remove_new = jz4780_i2c_remove, .driver = { .name = "jz4780-i2c", .of_match_table = jz4780_i2c_of_matches, diff --git a/drivers/i2c/busses/i2c-kempld.c b/drivers/i2c/busses/i2c-kempld.c index cf857cf22507043a1024ab9a04e63131e878b136..281058e3ea4632703e0d4d7b9093dd6c52bfab5a 100644 --- a/drivers/i2c/busses/i2c-kempld.c +++ b/drivers/i2c/busses/i2c-kempld.c @@ -329,7 +329,7 @@ static int kempld_i2c_probe(struct platform_device *pdev) return 0; } -static int kempld_i2c_remove(struct platform_device *pdev) +static void kempld_i2c_remove(struct platform_device *pdev) { struct kempld_i2c_data *i2c = platform_get_drvdata(pdev); struct kempld_device_data *pld = i2c->pld; @@ -348,8 +348,6 @@ static int kempld_i2c_remove(struct platform_device *pdev) kempld_release_mutex(pld); i2c_del_adapter(&i2c->adap); - - return 0; } #ifdef CONFIG_PM @@ -389,7 +387,7 @@ static struct platform_driver kempld_i2c_driver = { .name = "kempld-i2c", }, .probe = kempld_i2c_probe, - .remove = kempld_i2c_remove, + .remove_new = kempld_i2c_remove, .suspend = kempld_i2c_suspend, .resume = kempld_i2c_resume, }; diff --git a/drivers/i2c/busses/i2c-lpc2k.c b/drivers/i2c/busses/i2c-lpc2k.c index 8fff6fbb7065c0d9cf34a603cf0ea521007f6c12..5c6d965547539134dc34899751e821bc10b3735e 100644 --- a/drivers/i2c/busses/i2c-lpc2k.c +++ b/drivers/i2c/busses/i2c-lpc2k.c @@ -365,23 +365,17 @@ static int i2c_lpc2k_probe(struct platform_device *pdev) init_waitqueue_head(&i2c->wait); - i2c->clk = devm_clk_get(&pdev->dev, NULL); + i2c->clk = devm_clk_get_enabled(&pdev->dev, NULL); if (IS_ERR(i2c->clk)) { - dev_err(&pdev->dev, "error getting clock\n"); + dev_err(&pdev->dev, "failed to enable clock.\n"); return PTR_ERR(i2c->clk); } - ret = clk_prepare_enable(i2c->clk); - if (ret) { - dev_err(&pdev->dev, "unable to enable clock.\n"); - return ret; - } - ret = devm_request_irq(&pdev->dev, i2c->irq, i2c_lpc2k_handler, 0, dev_name(&pdev->dev), i2c); if (ret < 0) { dev_err(&pdev->dev, "can't request interrupt.\n"); - goto fail_clk; + return ret; } disable_irq_nosync(i2c->irq); @@ -397,8 +391,7 @@ static int i2c_lpc2k_probe(struct platform_device *pdev) clkrate = clk_get_rate(i2c->clk); if (clkrate == 0) { dev_err(&pdev->dev, "can't get I2C base clock\n"); - ret = -EINVAL; - goto fail_clk; + return -EINVAL; } /* Setup I2C dividers to generate clock with proper duty cycle */ @@ -424,25 +417,18 @@ static int i2c_lpc2k_probe(struct platform_device *pdev) ret = i2c_add_adapter(&i2c->adap); if (ret < 0) - goto fail_clk; + return ret; dev_info(&pdev->dev, "LPC2K I2C adapter\n"); return 0; - -fail_clk: - clk_disable_unprepare(i2c->clk); - return ret; } -static int i2c_lpc2k_remove(struct platform_device *dev) +static void i2c_lpc2k_remove(struct platform_device *dev) { struct lpc2k_i2c *i2c = platform_get_drvdata(dev); i2c_del_adapter(&i2c->adap); - clk_disable_unprepare(i2c->clk); - - return 0; } #ifdef CONFIG_PM @@ -483,7 +469,7 @@ MODULE_DEVICE_TABLE(of, lpc2k_i2c_match); static struct platform_driver i2c_lpc2k_driver = { .probe = i2c_lpc2k_probe, - .remove = i2c_lpc2k_remove, + .remove_new = i2c_lpc2k_remove, .driver = { .name = "lpc2k-i2c", .pm = I2C_LPC2K_DEV_PM_OPS, diff --git a/drivers/i2c/busses/i2c-meson.c b/drivers/i2c/busses/i2c-meson.c index 889eff06b78f4a9b58a0e3dc6b5653621218444c..16026c895bb65ae27634dde9ca5fb34719490a1b 100644 --- a/drivers/i2c/busses/i2c-meson.c +++ b/drivers/i2c/busses/i2c-meson.c @@ -535,14 +535,12 @@ static int meson_i2c_probe(struct platform_device *pdev) return 0; } -static int meson_i2c_remove(struct platform_device *pdev) +static void meson_i2c_remove(struct platform_device *pdev) { struct meson_i2c *i2c = platform_get_drvdata(pdev); i2c_del_adapter(&i2c->adap); clk_disable_unprepare(i2c->clk); - - return 0; } static const struct meson_i2c_data i2c_meson6_data = { @@ -568,7 +566,7 @@ MODULE_DEVICE_TABLE(of, meson_i2c_match); static struct platform_driver meson_i2c_driver = { .probe = meson_i2c_probe, - .remove = meson_i2c_remove, + .remove_new = meson_i2c_remove, .driver = { .name = "meson-i2c", .of_match_table = meson_i2c_match, diff --git a/drivers/i2c/busses/i2c-microchip-corei2c.c b/drivers/i2c/busses/i2c-microchip-corei2c.c index 4d7e9b25f018b6ff379062b3a7b12ad56c2dd717..7f58f7eaabb63f8d543941b9a5aebbabed71bab0 100644 --- a/drivers/i2c/busses/i2c-microchip-corei2c.c +++ b/drivers/i2c/busses/i2c-microchip-corei2c.c @@ -446,14 +446,12 @@ static int mchp_corei2c_probe(struct platform_device *pdev) return 0; } -static int mchp_corei2c_remove(struct platform_device *pdev) +static void mchp_corei2c_remove(struct platform_device *pdev) { struct mchp_corei2c_dev *idev = platform_get_drvdata(pdev); clk_disable_unprepare(idev->i2c_clk); i2c_del_adapter(&idev->adapter); - - return 0; } static const struct of_device_id mchp_corei2c_of_match[] = { @@ -465,7 +463,7 @@ MODULE_DEVICE_TABLE(of, mchp_corei2c_of_match); static struct platform_driver mchp_corei2c_driver = { .probe = mchp_corei2c_probe, - .remove = mchp_corei2c_remove, + .remove_new = mchp_corei2c_remove, .driver = { .name = "microchip-corei2c", .of_match_table = mchp_corei2c_of_match, diff --git a/drivers/i2c/busses/i2c-mlxbf.c b/drivers/i2c/busses/i2c-mlxbf.c index 1810d5791b3d7563adc4dc9f5d41f865d0d01964..ae66bdd1b7379e47c2ac6d33a677ace36e715012 100644 --- a/drivers/i2c/busses/i2c-mlxbf.c +++ b/drivers/i2c/busses/i2c-mlxbf.c @@ -2433,7 +2433,7 @@ static int mlxbf_i2c_probe(struct platform_device *pdev) return 0; } -static int mlxbf_i2c_remove(struct platform_device *pdev) +static void mlxbf_i2c_remove(struct platform_device *pdev) { struct mlxbf_i2c_priv *priv = platform_get_drvdata(pdev); struct device *dev = &pdev->dev; @@ -2474,13 +2474,11 @@ static int mlxbf_i2c_remove(struct platform_device *pdev) devm_free_irq(dev, priv->irq, priv); i2c_del_adapter(&priv->adap); - - return 0; } static struct platform_driver mlxbf_i2c_driver = { .probe = mlxbf_i2c_probe, - .remove = mlxbf_i2c_remove, + .remove_new = mlxbf_i2c_remove, .driver = { .name = "i2c-mlxbf", .acpi_match_table = ACPI_PTR(mlxbf_i2c_acpi_ids), diff --git a/drivers/i2c/busses/i2c-mlxcpld.c b/drivers/i2c/busses/i2c-mlxcpld.c index 081f51ef0551baddc73d023d8b4197c0ef356734..c42fd4b329e4b1e1b4e9b97b2a96b4180f8c4921 100644 --- a/drivers/i2c/busses/i2c-mlxcpld.c +++ b/drivers/i2c/busses/i2c-mlxcpld.c @@ -571,19 +571,17 @@ static int mlxcpld_i2c_probe(struct platform_device *pdev) return err; } -static int mlxcpld_i2c_remove(struct platform_device *pdev) +static void mlxcpld_i2c_remove(struct platform_device *pdev) { struct mlxcpld_i2c_priv *priv = platform_get_drvdata(pdev); i2c_del_adapter(&priv->adap); mutex_destroy(&priv->lock); - - return 0; } static struct platform_driver mlxcpld_i2c_driver = { .probe = mlxcpld_i2c_probe, - .remove = mlxcpld_i2c_remove, + .remove_new = mlxcpld_i2c_remove, .driver = { .name = MLXCPLD_I2C_DEVICE_NAME, }, diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c index cfd074ee6d5479df6908d7c9d201cb32c9a2dfb8..f460a7fb4eae6ff03f07ffe3c95bb3d732fe1d6c 100644 --- a/drivers/i2c/busses/i2c-mpc.c +++ b/drivers/i2c/busses/i2c-mpc.c @@ -307,7 +307,6 @@ static void mpc_i2c_setup_512x(struct device_node *node, { struct device_node *node_ctrl; void __iomem *ctrl; - const u32 *pval; u32 idx; /* Enable I2C interrupts for mpc5121 */ @@ -316,9 +315,10 @@ static void mpc_i2c_setup_512x(struct device_node *node, if (node_ctrl) { ctrl = of_iomap(node_ctrl, 0); if (ctrl) { + u64 addr; /* Interrupt enable bits for i2c-0/1/2: bit 24/26/28 */ - pval = of_get_property(node, "reg", NULL); - idx = (*pval & 0xff) / 0x20; + of_property_read_reg(node, 0, &addr, NULL); + idx = (addr & 0xff) / 0x20; setbits32(ctrl, 1 << (24 + idx * 2)); iounmap(ctrl); } @@ -890,15 +890,13 @@ static int fsl_i2c_probe(struct platform_device *op) return result; }; -static int fsl_i2c_remove(struct platform_device *op) +static void fsl_i2c_remove(struct platform_device *op) { struct mpc_i2c *i2c = platform_get_drvdata(op); i2c_del_adapter(&i2c->adap); clk_disable_unprepare(i2c->clk_per); - - return 0; }; static int __maybe_unused mpc_i2c_suspend(struct device *dev) @@ -959,7 +957,7 @@ MODULE_DEVICE_TABLE(of, mpc_i2c_of_match); /* Structure for a device driver */ static struct platform_driver mpc_i2c_driver = { .probe = fsl_i2c_probe, - .remove = fsl_i2c_remove, + .remove_new = fsl_i2c_remove, .driver = { .name = DRV_NAME, .of_match_table = mpc_i2c_of_match, diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c index a43c4d77739ab9846b35c5bdf28dbeb1f6c2f76d..7ca3f2221ba69ed2c0093fd372f1f9813410cd8d 100644 --- a/drivers/i2c/busses/i2c-mt65xx.c +++ b/drivers/i2c/busses/i2c-mt65xx.c @@ -1505,15 +1505,13 @@ static int mtk_i2c_probe(struct platform_device *pdev) return ret; } -static int mtk_i2c_remove(struct platform_device *pdev) +static void mtk_i2c_remove(struct platform_device *pdev) { struct mtk_i2c *i2c = platform_get_drvdata(pdev); i2c_del_adapter(&i2c->adap); clk_bulk_unprepare(I2C_MT65XX_CLK_MAX, i2c->clocks); - - return 0; } #ifdef CONFIG_PM_SLEEP @@ -1555,7 +1553,7 @@ static const struct dev_pm_ops mtk_i2c_pm = { static struct platform_driver mtk_i2c_driver = { .probe = mtk_i2c_probe, - .remove = mtk_i2c_remove, + .remove_new = mtk_i2c_remove, .driver = { .name = I2C_DRV_NAME, .pm = &mtk_i2c_pm, diff --git a/drivers/i2c/busses/i2c-mt7621.c b/drivers/i2c/busses/i2c-mt7621.c index 20eda5738ac494ff28edbd5df207234b275d1496..104bb194e9906d68c6a59019acb1ca27a77139f8 100644 --- a/drivers/i2c/busses/i2c-mt7621.c +++ b/drivers/i2c/busses/i2c-mt7621.c @@ -282,16 +282,11 @@ static int mtk_i2c_probe(struct platform_device *pdev) if (IS_ERR(i2c->base)) return PTR_ERR(i2c->base); - i2c->clk = devm_clk_get(&pdev->dev, NULL); + i2c->clk = devm_clk_get_enabled(&pdev->dev, NULL); if (IS_ERR(i2c->clk)) { - dev_err(&pdev->dev, "no clock defined\n"); + dev_err(&pdev->dev, "Failed to enable clock\n"); return PTR_ERR(i2c->clk); } - ret = clk_prepare_enable(i2c->clk); - if (ret) { - dev_err(&pdev->dev, "Unable to enable clock\n"); - return ret; - } i2c->dev = &pdev->dev; @@ -301,8 +296,7 @@ static int mtk_i2c_probe(struct platform_device *pdev) if (i2c->bus_freq == 0) { dev_warn(i2c->dev, "clock-frequency 0 not supported\n"); - ret = -EINVAL; - goto err_disable_clk; + return -EINVAL; } adap = &i2c->adap; @@ -320,31 +314,23 @@ static int mtk_i2c_probe(struct platform_device *pdev) ret = i2c_add_adapter(adap); if (ret < 0) - goto err_disable_clk; + return ret; dev_info(&pdev->dev, "clock %u kHz\n", i2c->bus_freq / 1000); return 0; - -err_disable_clk: - clk_disable_unprepare(i2c->clk); - - return ret; } -static int mtk_i2c_remove(struct platform_device *pdev) +static void mtk_i2c_remove(struct platform_device *pdev) { struct mtk_i2c *i2c = platform_get_drvdata(pdev); - clk_disable_unprepare(i2c->clk); i2c_del_adapter(&i2c->adap); - - return 0; } static struct platform_driver mtk_i2c_driver = { .probe = mtk_i2c_probe, - .remove = mtk_i2c_remove, + .remove_new = mtk_i2c_remove, .driver = { .name = "i2c-mt7621", .of_match_table = i2c_mtk_dt_ids, diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c index 878c076ebdc6b2ab5e30f8441094db198da28fcd..fd8403b07fa61545de036306dee52a20ada121a1 100644 --- a/drivers/i2c/busses/i2c-mv64xxx.c +++ b/drivers/i2c/busses/i2c-mv64xxx.c @@ -1084,7 +1084,7 @@ mv64xxx_i2c_probe(struct platform_device *pd) return rc; } -static int +static void mv64xxx_i2c_remove(struct platform_device *pd) { struct mv64xxx_i2c_data *drv_data = platform_get_drvdata(pd); @@ -1094,8 +1094,6 @@ mv64xxx_i2c_remove(struct platform_device *pd) pm_runtime_disable(&pd->dev); if (!pm_runtime_status_suspended(&pd->dev)) mv64xxx_i2c_runtime_suspend(&pd->dev); - - return 0; } static const struct dev_pm_ops mv64xxx_i2c_pm_ops = { @@ -1107,7 +1105,7 @@ static const struct dev_pm_ops mv64xxx_i2c_pm_ops = { static struct platform_driver mv64xxx_i2c_driver = { .probe = mv64xxx_i2c_probe, - .remove = mv64xxx_i2c_remove, + .remove_new = mv64xxx_i2c_remove, .driver = { .name = MV64XXX_I2C_CTLR_NAME, .pm = &mv64xxx_i2c_pm_ops, diff --git a/drivers/i2c/busses/i2c-mxs.c b/drivers/i2c/busses/i2c-mxs.c index e0f3b3545cfe4984dad9c582c419737ce448b506..1d76f1c4dc06a3d2cad9c772332291276f568bf7 100644 --- a/drivers/i2c/busses/i2c-mxs.c +++ b/drivers/i2c/busses/i2c-mxs.c @@ -864,7 +864,7 @@ static int mxs_i2c_probe(struct platform_device *pdev) return 0; } -static int mxs_i2c_remove(struct platform_device *pdev) +static void mxs_i2c_remove(struct platform_device *pdev) { struct mxs_i2c_dev *i2c = platform_get_drvdata(pdev); @@ -874,8 +874,6 @@ static int mxs_i2c_remove(struct platform_device *pdev) dma_release_channel(i2c->dmach); writel(MXS_I2C_CTRL0_SFTRST, i2c->regs + MXS_I2C_CTRL0_SET); - - return 0; } static struct platform_driver mxs_i2c_driver = { @@ -884,7 +882,7 @@ static struct platform_driver mxs_i2c_driver = { .of_match_table = mxs_i2c_dt_ids, }, .probe = mxs_i2c_probe, - .remove = mxs_i2c_remove, + .remove_new = mxs_i2c_remove, }; static int __init mxs_i2c_init(void) diff --git a/drivers/i2c/busses/i2c-nomadik.c b/drivers/i2c/busses/i2c-nomadik.c index a2d12a5b1c34c1265cbe9bc6c0215bef621d5bd0..212f412f1c74959e4b5b5f2f141a2917b7c551c5 100644 --- a/drivers/i2c/busses/i2c-nomadik.c +++ b/drivers/i2c/busses/i2c-nomadik.c @@ -970,12 +970,10 @@ static int nmk_i2c_probe(struct amba_device *adev, const struct amba_id *id) struct i2c_vendor_data *vendor = id->data; u32 max_fifo_threshold = (vendor->fifodepth / 2) - 1; - dev = devm_kzalloc(&adev->dev, sizeof(struct nmk_i2c_dev), GFP_KERNEL); - if (!dev) { - dev_err(&adev->dev, "cannot allocate memory\n"); - ret = -ENOMEM; - goto err_no_mem; - } + dev = devm_kzalloc(&adev->dev, sizeof(*dev), GFP_KERNEL); + if (!dev) + return -ENOMEM; + dev->vendor = vendor; dev->adev = adev; nmk_i2c_of_probe(np, dev); @@ -996,31 +994,20 @@ static int nmk_i2c_probe(struct amba_device *adev, const struct amba_id *id) dev->virtbase = devm_ioremap(&adev->dev, adev->res.start, resource_size(&adev->res)); - if (!dev->virtbase) { - ret = -ENOMEM; - goto err_no_mem; - } + if (!dev->virtbase) + return -ENOMEM; dev->irq = adev->irq[0]; ret = devm_request_irq(&adev->dev, dev->irq, i2c_irq_handler, 0, DRIVER_NAME, dev); - if (ret) { - dev_err(&adev->dev, "cannot claim the irq %d\n", dev->irq); - goto err_no_mem; - } - - dev->clk = devm_clk_get(&adev->dev, NULL); - if (IS_ERR(dev->clk)) { - dev_err(&adev->dev, "could not get i2c clock\n"); - ret = PTR_ERR(dev->clk); - goto err_no_mem; - } + if (ret) + return dev_err_probe(&adev->dev, ret, + "cannot claim the irq %d\n", dev->irq); - ret = clk_prepare_enable(dev->clk); - if (ret) { - dev_err(&adev->dev, "can't prepare_enable clock\n"); - goto err_no_mem; - } + dev->clk = devm_clk_get_enabled(&adev->dev, NULL); + if (IS_ERR(dev->clk)) + return dev_err_probe(&adev->dev, PTR_ERR(dev->clk), + "could enable i2c clock\n"); init_hw(dev); @@ -1042,22 +1029,15 @@ static int nmk_i2c_probe(struct amba_device *adev, const struct amba_id *id) ret = i2c_add_adapter(adap); if (ret) - goto err_no_adap; + return ret; pm_runtime_put(&adev->dev); return 0; - - err_no_adap: - clk_disable_unprepare(dev->clk); - err_no_mem: - - return ret; } static void nmk_i2c_remove(struct amba_device *adev) { - struct resource *res = &adev->res; struct nmk_i2c_dev *dev = amba_get_drvdata(adev); i2c_del_adapter(&dev->adap); @@ -1066,8 +1046,6 @@ static void nmk_i2c_remove(struct amba_device *adev) clear_all_interrupts(dev); /* disable the controller */ i2c_clr_bit(dev->virtbase + I2C_CR, I2C_CR_PE); - clk_disable_unprepare(dev->clk); - release_mem_region(res->start, resource_size(res)); } static struct i2c_vendor_data vendor_stn8815 = { diff --git a/drivers/i2c/busses/i2c-npcm7xx.c b/drivers/i2c/busses/i2c-npcm7xx.c index 38d5864d0cb5bd8d9b4baeef7f3c87693b44e2f1..53b65ffb6a6477bf10fdb2130827859e8810428c 100644 --- a/drivers/i2c/busses/i2c-npcm7xx.c +++ b/drivers/i2c/busses/i2c-npcm7xx.c @@ -2361,7 +2361,7 @@ static int npcm_i2c_probe_bus(struct platform_device *pdev) return 0; } -static int npcm_i2c_remove_bus(struct platform_device *pdev) +static void npcm_i2c_remove_bus(struct platform_device *pdev) { unsigned long lock_flags; struct npcm_i2c *bus = platform_get_drvdata(pdev); @@ -2371,7 +2371,6 @@ static int npcm_i2c_remove_bus(struct platform_device *pdev) npcm_i2c_disable(bus); spin_unlock_irqrestore(&bus->lock, lock_flags); i2c_del_adapter(&bus->adap); - return 0; } static const struct of_device_id npcm_i2c_bus_of_table[] = { @@ -2383,7 +2382,7 @@ MODULE_DEVICE_TABLE(of, npcm_i2c_bus_of_table); static struct platform_driver npcm_i2c_bus_driver = { .probe = npcm_i2c_probe_bus, - .remove = npcm_i2c_remove_bus, + .remove_new = npcm_i2c_remove_bus, .driver = { .name = "nuvoton-i2c", .of_match_table = npcm_i2c_bus_of_table, diff --git a/drivers/i2c/busses/i2c-nvidia-gpu.c b/drivers/i2c/busses/i2c-nvidia-gpu.c index a8b99e7f6262ab5f7fe4bf08afc96d1dcc7756a8..26622d24bb1b2d40e3ffbaa90791cf4d7574f215 100644 --- a/drivers/i2c/busses/i2c-nvidia-gpu.c +++ b/drivers/i2c/busses/i2c-nvidia-gpu.c @@ -14,6 +14,7 @@ #include #include #include +#include #include @@ -261,6 +262,8 @@ MODULE_DEVICE_TABLE(pci, gpu_i2c_ids); static const struct property_entry ccgx_props[] = { /* Use FW built for NVIDIA GPU only */ PROPERTY_ENTRY_STRING("firmware-name", "nvidia,gpu"), + /* USB-C doesn't power the system */ + PROPERTY_ENTRY_U8("scope", POWER_SUPPLY_SCOPE_DEVICE), { } }; diff --git a/drivers/i2c/busses/i2c-ocores.c b/drivers/i2c/busses/i2c-ocores.c index 2e575856c5cd5dfa57a7fa28bce0ac17d62bfa30..4ac77e57bbbfe19726c3a79fd4059bb7eb5ad685 100644 --- a/drivers/i2c/busses/i2c-ocores.c +++ b/drivers/i2c/busses/i2c-ocores.c @@ -552,28 +552,20 @@ static int ocores_i2c_of_probe(struct platform_device *pdev, &clock_frequency); i2c->bus_clock_khz = 100; - i2c->clk = devm_clk_get(&pdev->dev, NULL); - - if (!IS_ERR(i2c->clk)) { - int ret = clk_prepare_enable(i2c->clk); - - if (ret) { - dev_err(&pdev->dev, - "clk_prepare_enable failed: %d\n", ret); - return ret; - } - i2c->ip_clock_khz = clk_get_rate(i2c->clk) / 1000; - if (clock_frequency_present) - i2c->bus_clock_khz = clock_frequency / 1000; - } - + i2c->clk = devm_clk_get_optional_enabled(&pdev->dev, NULL); + if (IS_ERR(i2c->clk)) + return dev_err_probe(&pdev->dev, PTR_ERR(i2c->clk), + "devm_clk_get_optional_enabled failed\n"); + + i2c->ip_clock_khz = clk_get_rate(i2c->clk) / 1000; + if (clock_frequency_present) + i2c->bus_clock_khz = clock_frequency / 1000; if (i2c->ip_clock_khz == 0) { if (of_property_read_u32(np, "opencores,ip-clock-frequency", &val)) { if (!clock_frequency_present) { dev_err(&pdev->dev, "Missing required parameter 'opencores,ip-clock-frequency'\n"); - clk_disable_unprepare(i2c->clk); return -ENODEV; } i2c->ip_clock_khz = clock_frequency / 1000; @@ -678,8 +670,7 @@ static int ocores_i2c_probe(struct platform_device *pdev) default: dev_err(&pdev->dev, "Unsupported I/O width (%d)\n", i2c->reg_io_width); - ret = -EINVAL; - goto err_clk; + return -EINVAL; } } @@ -710,13 +701,13 @@ static int ocores_i2c_probe(struct platform_device *pdev) pdev->name, i2c); if (ret) { dev_err(&pdev->dev, "Cannot claim IRQ\n"); - goto err_clk; + return ret; } } ret = ocores_init(&pdev->dev, i2c); if (ret) - goto err_clk; + return ret; /* hook up driver to tree */ platform_set_drvdata(pdev, i2c); @@ -728,7 +719,7 @@ static int ocores_i2c_probe(struct platform_device *pdev) /* add i2c adapter to i2c tree */ ret = i2c_add_adapter(&i2c->adap); if (ret) - goto err_clk; + return ret; /* add in known devices to the bus */ if (pdata) { @@ -737,13 +728,9 @@ static int ocores_i2c_probe(struct platform_device *pdev) } return 0; - -err_clk: - clk_disable_unprepare(i2c->clk); - return ret; } -static int ocores_i2c_remove(struct platform_device *pdev) +static void ocores_i2c_remove(struct platform_device *pdev) { struct ocores_i2c *i2c = platform_get_drvdata(pdev); u8 ctrl = oc_getreg(i2c, OCI2C_CONTROL); @@ -754,11 +741,6 @@ static int ocores_i2c_remove(struct platform_device *pdev) /* remove adapter & data */ i2c_del_adapter(&i2c->adap); - - if (!IS_ERR(i2c->clk)) - clk_disable_unprepare(i2c->clk); - - return 0; } #ifdef CONFIG_PM_SLEEP @@ -771,28 +753,22 @@ static int ocores_i2c_suspend(struct device *dev) ctrl &= ~(OCI2C_CTRL_EN | OCI2C_CTRL_IEN); oc_setreg(i2c, OCI2C_CONTROL, ctrl); - if (!IS_ERR(i2c->clk)) - clk_disable_unprepare(i2c->clk); + clk_disable_unprepare(i2c->clk); return 0; } static int ocores_i2c_resume(struct device *dev) { struct ocores_i2c *i2c = dev_get_drvdata(dev); + unsigned long rate; + int ret; - if (!IS_ERR(i2c->clk)) { - unsigned long rate; - int ret = clk_prepare_enable(i2c->clk); - - if (ret) { - dev_err(dev, - "clk_prepare_enable failed: %d\n", ret); - return ret; - } - rate = clk_get_rate(i2c->clk) / 1000; - if (rate) - i2c->ip_clock_khz = rate; - } + ret = clk_prepare_enable(i2c->clk); + if (ret) + return dev_err_probe(dev, ret, "clk_prepare_enable failed\n"); + rate = clk_get_rate(i2c->clk) / 1000; + if (rate) + i2c->ip_clock_khz = rate; return ocores_init(dev, i2c); } @@ -804,7 +780,7 @@ static SIMPLE_DEV_PM_OPS(ocores_i2c_pm, ocores_i2c_suspend, ocores_i2c_resume); static struct platform_driver ocores_i2c_driver = { .probe = ocores_i2c_probe, - .remove = ocores_i2c_remove, + .remove_new = ocores_i2c_remove, .driver = { .name = "ocores-i2c", .of_match_table = ocores_i2c_match, diff --git a/drivers/i2c/busses/i2c-octeon-platdrv.c b/drivers/i2c/busses/i2c-octeon-platdrv.c index 0c227963c8d699db758dc01dd2dae8823b45f7e8..7d54b3203f71665711641dd74562ca327acebba4 100644 --- a/drivers/i2c/busses/i2c-octeon-platdrv.c +++ b/drivers/i2c/busses/i2c-octeon-platdrv.c @@ -253,12 +253,11 @@ static int octeon_i2c_probe(struct platform_device *pdev) return result; }; -static int octeon_i2c_remove(struct platform_device *pdev) +static void octeon_i2c_remove(struct platform_device *pdev) { struct octeon_i2c *i2c = platform_get_drvdata(pdev); i2c_del_adapter(&i2c->adap); - return 0; }; static const struct of_device_id octeon_i2c_match[] = { @@ -270,7 +269,7 @@ MODULE_DEVICE_TABLE(of, octeon_i2c_match); static struct platform_driver octeon_i2c_driver = { .probe = octeon_i2c_probe, - .remove = octeon_i2c_remove, + .remove_new = octeon_i2c_remove, .driver = { .name = DRV_NAME, .of_match_table = octeon_i2c_match, diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index 4199f57a6bf299b142d5344a1a916fca2197b26d..58fd6fa3edf1449c30fe713adca8273e054e52fd 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -1519,7 +1519,7 @@ omap_i2c_probe(struct platform_device *pdev) return r; } -static int omap_i2c_remove(struct platform_device *pdev) +static void omap_i2c_remove(struct platform_device *pdev) { struct omap_i2c_dev *omap = platform_get_drvdata(pdev); int ret; @@ -1535,8 +1535,6 @@ static int omap_i2c_remove(struct platform_device *pdev) pm_runtime_dont_use_autosuspend(&pdev->dev); pm_runtime_put_sync(&pdev->dev); pm_runtime_disable(&pdev->dev); - - return 0; } static int __maybe_unused omap_i2c_runtime_suspend(struct device *dev) @@ -1588,7 +1586,7 @@ static const struct dev_pm_ops omap_i2c_pm_ops = { static struct platform_driver omap_i2c_driver = { .probe = omap_i2c_probe, - .remove = omap_i2c_remove, + .remove_new = omap_i2c_remove, .driver = { .name = "omap_i2c", .pm = &omap_i2c_pm_ops, diff --git a/drivers/i2c/busses/i2c-opal.c b/drivers/i2c/busses/i2c-opal.c index 9f773b4f5ed8e439d60c4033fb962e5d089d9e3a..17ef87d50f7c7d51d5c8d0187fb3663f5a742a58 100644 --- a/drivers/i2c/busses/i2c-opal.c +++ b/drivers/i2c/busses/i2c-opal.c @@ -232,13 +232,11 @@ static int i2c_opal_probe(struct platform_device *pdev) return rc; } -static int i2c_opal_remove(struct platform_device *pdev) +static void i2c_opal_remove(struct platform_device *pdev) { struct i2c_adapter *adapter = platform_get_drvdata(pdev); i2c_del_adapter(adapter); - - return 0; } static const struct of_device_id i2c_opal_of_match[] = { @@ -251,7 +249,7 @@ MODULE_DEVICE_TABLE(of, i2c_opal_of_match); static struct platform_driver i2c_opal_driver = { .probe = i2c_opal_probe, - .remove = i2c_opal_remove, + .remove_new = i2c_opal_remove, .driver = { .name = "i2c-opal", .of_match_table = i2c_opal_of_match, diff --git a/drivers/i2c/busses/i2c-owl.c b/drivers/i2c/busses/i2c-owl.c index 99ddd889496451e6b86fbe4333122f18b518afae..5f0ef8c351418544dcfd050cc7792f643f70939a 100644 --- a/drivers/i2c/busses/i2c-owl.c +++ b/drivers/i2c/busses/i2c-owl.c @@ -461,21 +461,16 @@ static int owl_i2c_probe(struct platform_device *pdev) return -EINVAL; } - i2c_dev->clk = devm_clk_get(dev, NULL); + i2c_dev->clk = devm_clk_get_enabled(dev, NULL); if (IS_ERR(i2c_dev->clk)) { - dev_err(dev, "failed to get clock\n"); + dev_err(dev, "failed to enable clock\n"); return PTR_ERR(i2c_dev->clk); } - ret = clk_prepare_enable(i2c_dev->clk); - if (ret) - return ret; - i2c_dev->clk_rate = clk_get_rate(i2c_dev->clk); if (!i2c_dev->clk_rate) { dev_err(dev, "input clock rate should not be zero\n"); - ret = -EINVAL; - goto disable_clk; + return -EINVAL; } init_completion(&i2c_dev->msg_complete); @@ -496,15 +491,10 @@ static int owl_i2c_probe(struct platform_device *pdev) i2c_dev); if (ret) { dev_err(dev, "failed to request irq %d\n", irq); - goto disable_clk; + return ret; } return i2c_add_adapter(&i2c_dev->adap); - -disable_clk: - clk_disable_unprepare(i2c_dev->clk); - - return ret; } static const struct of_device_id owl_i2c_of_match[] = { diff --git a/drivers/i2c/busses/i2c-pasemi-platform.c b/drivers/i2c/busses/i2c-pasemi-platform.c index e35945a91dbef40b5c58301ca0da7d694fc4afa6..5fbfb9b41744022c9eb4d09c56331efa09e4efaf 100644 --- a/drivers/i2c/busses/i2c-pasemi-platform.c +++ b/drivers/i2c/busses/i2c-pasemi-platform.c @@ -66,22 +66,18 @@ static int pasemi_platform_i2c_probe(struct platform_device *pdev) if (of_property_read_u32(dev->of_node, "clock-frequency", &frequency)) frequency = I2C_MAX_STANDARD_MODE_FREQ; - data->clk_ref = devm_clk_get(dev, NULL); + data->clk_ref = devm_clk_get_enabled(dev, NULL); if (IS_ERR(data->clk_ref)) return PTR_ERR(data->clk_ref); - error = clk_prepare_enable(data->clk_ref); - if (error) - return error; - error = pasemi_platform_i2c_calc_clk_div(data, frequency); if (error) - goto out_clk_disable; + return error; smbus->adapter.dev.of_node = pdev->dev.of_node; error = pasemi_i2c_common_probe(smbus); if (error) - goto out_clk_disable; + return error; irq_num = platform_get_irq(pdev, 0); error = devm_request_irq(smbus->dev, irq_num, pasemi_irq_handler, 0, "pasemi_apple_i2c", (void *)smbus); @@ -91,20 +87,9 @@ static int pasemi_platform_i2c_probe(struct platform_device *pdev) platform_set_drvdata(pdev, data); return 0; - -out_clk_disable: - clk_disable_unprepare(data->clk_ref); - - return error; } -static int pasemi_platform_i2c_remove(struct platform_device *pdev) -{ - struct pasemi_platform_i2c_data *data = platform_get_drvdata(pdev); - - clk_disable_unprepare(data->clk_ref); - return 0; -} +static void pasemi_platform_i2c_remove(struct platform_device *pdev) { } static const struct of_device_id pasemi_platform_i2c_of_match[] = { { .compatible = "apple,t8103-i2c" }, @@ -119,7 +104,7 @@ static struct platform_driver pasemi_platform_i2c_driver = { .of_match_table = pasemi_platform_i2c_of_match, }, .probe = pasemi_platform_i2c_probe, - .remove = pasemi_platform_i2c_remove, + .remove_new = pasemi_platform_i2c_remove, }; module_platform_driver(pasemi_platform_i2c_driver); diff --git a/drivers/i2c/busses/i2c-pca-platform.c b/drivers/i2c/busses/i2c-pca-platform.c index 86d4f75ef8d3f4262edab97307933a5d5e53f1f9..d2a9e7b61c1abdc49f5791e293cfde34c8aa4588 100644 --- a/drivers/i2c/busses/i2c-pca-platform.c +++ b/drivers/i2c/busses/i2c-pca-platform.c @@ -221,13 +221,11 @@ static int i2c_pca_pf_probe(struct platform_device *pdev) return 0; } -static int i2c_pca_pf_remove(struct platform_device *pdev) +static void i2c_pca_pf_remove(struct platform_device *pdev) { struct i2c_pca_pf_data *i2c = platform_get_drvdata(pdev); i2c_del_adapter(&i2c->adap); - - return 0; } #ifdef CONFIG_OF @@ -241,7 +239,7 @@ MODULE_DEVICE_TABLE(of, i2c_pca_of_match_table); static struct platform_driver i2c_pca_pf_driver = { .probe = i2c_pca_pf_probe, - .remove = i2c_pca_pf_remove, + .remove_new = i2c_pca_pf_remove, .driver = { .name = "i2c-pca-platform", .of_match_table = of_match_ptr(i2c_pca_of_match_table), diff --git a/drivers/i2c/busses/i2c-pnx.c b/drivers/i2c/busses/i2c-pnx.c index 50f21cdbe90d3cbfae78f65238908a604a64e7c5..82400057f810a5feaa0e05b58e1d9efaa06cfbd1 100644 --- a/drivers/i2c/busses/i2c-pnx.c +++ b/drivers/i2c/busses/i2c-pnx.c @@ -743,14 +743,12 @@ static int i2c_pnx_probe(struct platform_device *pdev) return ret; } -static int i2c_pnx_remove(struct platform_device *pdev) +static void i2c_pnx_remove(struct platform_device *pdev) { struct i2c_pnx_algo_data *alg_data = platform_get_drvdata(pdev); i2c_del_adapter(&alg_data->adapter); clk_disable_unprepare(alg_data->clk); - - return 0; } #ifdef CONFIG_OF @@ -768,7 +766,7 @@ static struct platform_driver i2c_pnx_driver = { .pm = PNX_I2C_PM, }, .probe = i2c_pnx_probe, - .remove = i2c_pnx_remove, + .remove_new = i2c_pnx_remove, }; static int __init i2c_adap_pnx_init(void) diff --git a/drivers/i2c/busses/i2c-powermac.c b/drivers/i2c/busses/i2c-powermac.c index ec706a3aba26c577ab89e804cd253a0b50308940..4996a628fdae1bb41fee3bd440e685dcfcdab6df 100644 --- a/drivers/i2c/busses/i2c-powermac.c +++ b/drivers/i2c/busses/i2c-powermac.c @@ -188,14 +188,12 @@ static const struct i2c_adapter_quirks i2c_powermac_quirks = { .max_num_msgs = 1, }; -static int i2c_powermac_remove(struct platform_device *dev) +static void i2c_powermac_remove(struct platform_device *dev) { struct i2c_adapter *adapter = platform_get_drvdata(dev); i2c_del_adapter(adapter); memset(adapter, 0, sizeof(*adapter)); - - return 0; } static u32 i2c_powermac_get_addr(struct i2c_adapter *adap, @@ -439,7 +437,7 @@ static int i2c_powermac_probe(struct platform_device *dev) static struct platform_driver i2c_powermac_driver = { .probe = i2c_powermac_probe, - .remove = i2c_powermac_remove, + .remove_new = i2c_powermac_remove, .driver = { .name = "i2c-powermac", .bus = &platform_bus_type, diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c index f9fa5308556b77f4b89e8e31d8c5af5519b2ee1d..937f7eebe90675f72b43dd0f89a8152b649e41dd 100644 --- a/drivers/i2c/busses/i2c-pxa.c +++ b/drivers/i2c/busses/i2c-pxa.c @@ -1482,15 +1482,13 @@ static int i2c_pxa_probe(struct platform_device *dev) return ret; } -static int i2c_pxa_remove(struct platform_device *dev) +static void i2c_pxa_remove(struct platform_device *dev) { struct pxa_i2c *i2c = platform_get_drvdata(dev); i2c_del_adapter(&i2c->adap); clk_disable_unprepare(i2c->clk); - - return 0; } #ifdef CONFIG_PM @@ -1525,7 +1523,7 @@ static const struct dev_pm_ops i2c_pxa_dev_pm_ops = { static struct platform_driver i2c_pxa_driver = { .probe = i2c_pxa_probe, - .remove = i2c_pxa_remove, + .remove_new = i2c_pxa_remove, .driver = { .name = "pxa2xx-i2c", .pm = I2C_PXA_DEV_PM_OPS, diff --git a/drivers/i2c/busses/i2c-qcom-cci.c b/drivers/i2c/busses/i2c-qcom-cci.c index 01358472680c4cd905217ee257225874fdf65873..622dc14add9d7a92ff237eb12092b87af7201e78 100644 --- a/drivers/i2c/busses/i2c-qcom-cci.c +++ b/drivers/i2c/busses/i2c-qcom-cci.c @@ -581,8 +581,7 @@ static int cci_probe(struct platform_device *pdev) /* Memory */ - r = platform_get_resource(pdev, IORESOURCE_MEM, 0); - cci->base = devm_ioremap_resource(dev, r); + cci->base = devm_platform_get_and_ioremap_resource(pdev, 0, &r); if (IS_ERR(cci->base)) return PTR_ERR(cci->base); @@ -675,7 +674,7 @@ static int cci_probe(struct platform_device *pdev) return ret; } -static int cci_remove(struct platform_device *pdev) +static void cci_remove(struct platform_device *pdev) { struct cci *cci = platform_get_drvdata(pdev); int i; @@ -691,8 +690,6 @@ static int cci_remove(struct platform_device *pdev) disable_irq(cci->irq); pm_runtime_disable(&pdev->dev); pm_runtime_set_suspended(&pdev->dev); - - return 0; } static const struct cci_data cci_v1_data = { @@ -829,7 +826,7 @@ MODULE_DEVICE_TABLE(of, cci_dt_match); static struct platform_driver qcom_cci_driver = { .probe = cci_probe, - .remove = cci_remove, + .remove_new = cci_remove, .driver = { .name = "i2c-qcom-cci", .of_match_table = cci_dt_match, diff --git a/drivers/i2c/busses/i2c-qcom-geni.c b/drivers/i2c/busses/i2c-qcom-geni.c index 83909b02a03ee063b1d82358bc261a7a51f78a31..b670a67c4fdd00e068010718dbfd6a7ed970c2bd 100644 --- a/drivers/i2c/busses/i2c-qcom-geni.c +++ b/drivers/i2c/busses/i2c-qcom-geni.c @@ -936,14 +936,13 @@ static int geni_i2c_probe(struct platform_device *pdev) return ret; } -static int geni_i2c_remove(struct platform_device *pdev) +static void geni_i2c_remove(struct platform_device *pdev) { struct geni_i2c_dev *gi2c = platform_get_drvdata(pdev); i2c_del_adapter(&gi2c->adap); release_gpi_dma(gi2c); pm_runtime_disable(gi2c->se.dev); - return 0; } static void geni_i2c_shutdown(struct platform_device *pdev) @@ -1041,7 +1040,7 @@ MODULE_DEVICE_TABLE(of, geni_i2c_dt_match); static struct platform_driver geni_i2c_driver = { .probe = geni_i2c_probe, - .remove = geni_i2c_remove, + .remove_new = geni_i2c_remove, .shutdown = geni_i2c_shutdown, .driver = { .name = "geni_i2c", diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c index 2e153f2f71b6d8e9cde863759033d46c3c850ad7..ae90170023b0075b10808364783acd9da5c97482 100644 --- a/drivers/i2c/busses/i2c-qup.c +++ b/drivers/i2c/busses/i2c-qup.c @@ -1752,16 +1752,21 @@ static int qup_i2c_probe(struct platform_device *pdev) if (!clk_freq || clk_freq > I2C_MAX_FAST_MODE_PLUS_FREQ) { dev_err(qup->dev, "clock frequency not supported %d\n", clk_freq); - return -EINVAL; + ret = -EINVAL; + goto fail_dma; } qup->base = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(qup->base)) - return PTR_ERR(qup->base); + if (IS_ERR(qup->base)) { + ret = PTR_ERR(qup->base); + goto fail_dma; + } qup->irq = platform_get_irq(pdev, 0); - if (qup->irq < 0) - return qup->irq; + if (qup->irq < 0) { + ret = qup->irq; + goto fail_dma; + } if (has_acpi_companion(qup->dev)) { ret = device_property_read_u32(qup->dev, @@ -1775,13 +1780,15 @@ static int qup_i2c_probe(struct platform_device *pdev) qup->clk = devm_clk_get(qup->dev, "core"); if (IS_ERR(qup->clk)) { dev_err(qup->dev, "Could not get core clock\n"); - return PTR_ERR(qup->clk); + ret = PTR_ERR(qup->clk); + goto fail_dma; } qup->pclk = devm_clk_get(qup->dev, "iface"); if (IS_ERR(qup->pclk)) { dev_err(qup->dev, "Could not get iface clock\n"); - return PTR_ERR(qup->pclk); + ret = PTR_ERR(qup->pclk); + goto fail_dma; } qup_i2c_enable_clocks(qup); src_clk_freq = clk_get_rate(qup->clk); @@ -1904,7 +1911,7 @@ static int qup_i2c_probe(struct platform_device *pdev) return ret; } -static int qup_i2c_remove(struct platform_device *pdev) +static void qup_i2c_remove(struct platform_device *pdev) { struct qup_i2c_dev *qup = platform_get_drvdata(pdev); @@ -1918,7 +1925,6 @@ static int qup_i2c_remove(struct platform_device *pdev) i2c_del_adapter(&qup->adap); pm_runtime_disable(qup->dev); pm_runtime_set_suspended(qup->dev); - return 0; } #ifdef CONFIG_PM @@ -1978,7 +1984,7 @@ MODULE_DEVICE_TABLE(of, qup_i2c_dt_match); static struct platform_driver qup_i2c_driver = { .probe = qup_i2c_probe, - .remove = qup_i2c_remove, + .remove_new = qup_i2c_remove, .driver = { .name = "i2c_qup", .pm = &qup_i2c_qup_pm_ops, diff --git a/drivers/i2c/busses/i2c-rcar.c b/drivers/i2c/busses/i2c-rcar.c index cef82b205c261ccb993b8ec2cae136d51b977546..2d9c37410ebd0f1f397d91b3589b28b2bcdcf954 100644 --- a/drivers/i2c/busses/i2c-rcar.c +++ b/drivers/i2c/busses/i2c-rcar.c @@ -1155,7 +1155,7 @@ static int rcar_i2c_probe(struct platform_device *pdev) return ret; } -static int rcar_i2c_remove(struct platform_device *pdev) +static void rcar_i2c_remove(struct platform_device *pdev) { struct rcar_i2c_priv *priv = platform_get_drvdata(pdev); struct device *dev = &pdev->dev; @@ -1167,8 +1167,6 @@ static int rcar_i2c_remove(struct platform_device *pdev) if (priv->flags & ID_P_PM_BLOCKED) pm_runtime_put(dev); pm_runtime_disable(dev); - - return 0; } #ifdef CONFIG_PM_SLEEP @@ -1204,7 +1202,7 @@ static struct platform_driver rcar_i2c_driver = { .pm = DEV_PM_OPS, }, .probe = rcar_i2c_probe, - .remove = rcar_i2c_remove, + .remove_new = rcar_i2c_remove, }; module_platform_driver(rcar_i2c_driver); diff --git a/drivers/i2c/busses/i2c-riic.c b/drivers/i2c/busses/i2c-riic.c index 849848ccb08022825cd13d14fe3f5adfbc453c17..5f8c0bd508d2f3edb28e2d12b0de33769686465c 100644 --- a/drivers/i2c/busses/i2c-riic.c +++ b/drivers/i2c/busses/i2c-riic.c @@ -477,7 +477,7 @@ static int riic_i2c_probe(struct platform_device *pdev) return ret; } -static int riic_i2c_remove(struct platform_device *pdev) +static void riic_i2c_remove(struct platform_device *pdev) { struct riic_dev *riic = platform_get_drvdata(pdev); @@ -486,8 +486,6 @@ static int riic_i2c_remove(struct platform_device *pdev) pm_runtime_put(&pdev->dev); i2c_del_adapter(&riic->adapter); pm_runtime_disable(&pdev->dev); - - return 0; } static const struct of_device_id riic_i2c_dt_ids[] = { @@ -497,7 +495,7 @@ static const struct of_device_id riic_i2c_dt_ids[] = { static struct platform_driver riic_i2c_driver = { .probe = riic_i2c_probe, - .remove = riic_i2c_remove, + .remove_new = riic_i2c_remove, .driver = { .name = "i2c-riic", .of_match_table = riic_i2c_dt_ids, diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c index b31cf4f18f8548571dc8f387ad8e3c29ebe6fdc1..a044ca0c35a193e9f8abeb3cff88707285a7028d 100644 --- a/drivers/i2c/busses/i2c-rk3x.c +++ b/drivers/i2c/busses/i2c-rk3x.c @@ -1372,7 +1372,7 @@ static int rk3x_i2c_probe(struct platform_device *pdev) return ret; } -static int rk3x_i2c_remove(struct platform_device *pdev) +static void rk3x_i2c_remove(struct platform_device *pdev) { struct rk3x_i2c *i2c = platform_get_drvdata(pdev); @@ -1381,15 +1381,13 @@ static int rk3x_i2c_remove(struct platform_device *pdev) clk_notifier_unregister(i2c->clk, &i2c->clk_rate_nb); clk_unprepare(i2c->pclk); clk_unprepare(i2c->clk); - - return 0; } static SIMPLE_DEV_PM_OPS(rk3x_i2c_pm_ops, NULL, rk3x_i2c_resume); static struct platform_driver rk3x_i2c_driver = { .probe = rk3x_i2c_probe, - .remove = rk3x_i2c_remove, + .remove_new = rk3x_i2c_remove, .driver = { .name = "rk3x-i2c", .of_match_table = rk3x_i2c_match, diff --git a/drivers/i2c/busses/i2c-rzv2m.c b/drivers/i2c/busses/i2c-rzv2m.c index 56d0faee5c46e7cf1da71adbd435b11fbdae2ea9..b0bfc96b9ede7f6fd292b60fc1e747a1475e4835 100644 --- a/drivers/i2c/busses/i2c-rzv2m.c +++ b/drivers/i2c/busses/i2c-rzv2m.c @@ -50,9 +50,6 @@ #define IICB0MDSC BIT(7) /* Bus Mode */ #define IICB0SLSE BIT(1) /* Start condition output */ -#define bit_setl(addr, val) writel(readl(addr) | (val), (addr)) -#define bit_clrl(addr, val) writel(readl(addr) & ~(val), (addr)) - struct rzv2m_i2c_priv { void __iomem *base; struct i2c_adapter adap; @@ -78,6 +75,16 @@ static const struct bitrate_config bitrate_configs[] = { [RZV2M_I2C_400K] = { 52, 900 }, }; +static inline void bit_setl(void __iomem *addr, u32 val) +{ + writel(readl(addr) | val, addr); +} + +static inline void bit_clrl(void __iomem *addr, u32 val) +{ + writel(readl(addr) & ~val, addr); +} + static irqreturn_t rzv2m_i2c_tia_irq_handler(int this_irq, void *dev_id) { struct rzv2m_i2c_priv *priv = dev_id; @@ -382,6 +389,20 @@ static u32 rzv2m_i2c_func(struct i2c_adapter *adap) I2C_FUNC_10BIT_ADDR; } +static int rzv2m_i2c_disable(struct device *dev, struct rzv2m_i2c_priv *priv) +{ + int ret; + + ret = pm_runtime_resume_and_get(dev); + if (ret < 0) + return ret; + + bit_clrl(priv->base + IICB0CTL0, IICB0IICE); + pm_runtime_put(dev); + + return 0; +} + static const struct i2c_adapter_quirks rzv2m_i2c_quirks = { .flags = I2C_AQ_NO_ZERO_LEN, }; @@ -454,37 +475,29 @@ static int rzv2m_i2c_probe(struct platform_device *pdev) platform_set_drvdata(pdev, priv); ret = i2c_add_numbered_adapter(adap); - if (ret < 0) + if (ret < 0) { + rzv2m_i2c_disable(dev, priv); pm_runtime_disable(dev); + } return ret; } -static int rzv2m_i2c_remove(struct platform_device *pdev) +static void rzv2m_i2c_remove(struct platform_device *pdev) { struct rzv2m_i2c_priv *priv = platform_get_drvdata(pdev); struct device *dev = priv->adap.dev.parent; i2c_del_adapter(&priv->adap); - bit_clrl(priv->base + IICB0CTL0, IICB0IICE); + rzv2m_i2c_disable(dev, priv); pm_runtime_disable(dev); - - return 0; } static int rzv2m_i2c_suspend(struct device *dev) { struct rzv2m_i2c_priv *priv = dev_get_drvdata(dev); - int ret; - ret = pm_runtime_resume_and_get(dev); - if (ret < 0) - return ret; - - bit_clrl(priv->base + IICB0CTL0, IICB0IICE); - pm_runtime_put(dev); - - return 0; + return rzv2m_i2c_disable(dev, priv); } static int rzv2m_i2c_resume(struct device *dev) @@ -523,7 +536,7 @@ static struct platform_driver rzv2m_i2c_driver = { .pm = pm_sleep_ptr(&rzv2m_i2c_pm_ops), }, .probe = rzv2m_i2c_probe, - .remove = rzv2m_i2c_remove, + .remove_new = rzv2m_i2c_remove, }; module_platform_driver(rzv2m_i2c_driver); diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c index 45e9df81345a1a0508583d26402196b545f29c07..28f0e5c64f32ec0b4c9b3cfa9e9b493189a2ea1e 100644 --- a/drivers/i2c/busses/i2c-s3c2410.c +++ b/drivers/i2c/busses/i2c-s3c2410.c @@ -1114,7 +1114,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev) return 0; } -static int s3c24xx_i2c_remove(struct platform_device *pdev) +static void s3c24xx_i2c_remove(struct platform_device *pdev) { struct s3c24xx_i2c *i2c = platform_get_drvdata(pdev); @@ -1123,8 +1123,6 @@ static int s3c24xx_i2c_remove(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); i2c_del_adapter(&i2c->adap); - - return 0; } #ifdef CONFIG_PM_SLEEP @@ -1172,7 +1170,7 @@ static const struct dev_pm_ops s3c24xx_i2c_dev_pm_ops = { static struct platform_driver s3c24xx_i2c_driver = { .probe = s3c24xx_i2c_probe, - .remove = s3c24xx_i2c_remove, + .remove_new = s3c24xx_i2c_remove, .id_table = s3c24xx_driver_ids, .driver = { .name = "s3c-i2c", diff --git a/drivers/i2c/busses/i2c-scmi.c b/drivers/i2c/busses/i2c-scmi.c index 0239e134b90f425ece63c0dcde8326ad75a27af0..421735acfa141f2394aaca68b0b872f3accd09b1 100644 --- a/drivers/i2c/busses/i2c-scmi.c +++ b/drivers/i2c/busses/i2c-scmi.c @@ -13,9 +13,6 @@ #include #include -/* SMBUS HID definition as supported by Microsoft Windows */ -#define ACPI_SMBUS_MS_HID "SMB0001" - struct smbus_methods_t { char *mt_info; char *mt_sbr; @@ -404,19 +401,17 @@ static int smbus_cmi_probe(struct platform_device *device) return ret; } -static int smbus_cmi_remove(struct platform_device *device) +static void smbus_cmi_remove(struct platform_device *device) { struct acpi_smbus_cmi *smbus_cmi = platform_get_drvdata(device); i2c_del_adapter(&smbus_cmi->adapter); kfree(smbus_cmi); - - return 0; } static struct platform_driver smbus_cmi_driver = { .probe = smbus_cmi_probe, - .remove = smbus_cmi_remove, + .remove_new = smbus_cmi_remove, .driver = { .name = "smbus_cmi", .acpi_match_table = acpi_smbus_cmi_ids, diff --git a/drivers/i2c/busses/i2c-sh7760.c b/drivers/i2c/busses/i2c-sh7760.c index 319d1fa617c883e1ff7b890c76ffb4d5e97f0388..1ad2a26156d17703022548e6b432014f7fb64df9 100644 --- a/drivers/i2c/busses/i2c-sh7760.c +++ b/drivers/i2c/busses/i2c-sh7760.c @@ -443,9 +443,8 @@ static int sh7760_i2c_probe(struct platform_device *pdev) goto out0; } - id = kzalloc(sizeof(struct cami2c), GFP_KERNEL); + id = kzalloc(sizeof(*id), GFP_KERNEL); if (!id) { - dev_err(&pdev->dev, "no mem for private data\n"); ret = -ENOMEM; goto out0; } @@ -536,7 +535,7 @@ static int sh7760_i2c_probe(struct platform_device *pdev) return ret; } -static int sh7760_i2c_remove(struct platform_device *pdev) +static void sh7760_i2c_remove(struct platform_device *pdev) { struct cami2c *id = platform_get_drvdata(pdev); @@ -546,8 +545,6 @@ static int sh7760_i2c_remove(struct platform_device *pdev) release_resource(id->ioarea); kfree(id->ioarea); kfree(id); - - return 0; } static struct platform_driver sh7760_i2c_drv = { @@ -555,7 +552,7 @@ static struct platform_driver sh7760_i2c_drv = { .name = SH7760_I2C_DEVNAME, }, .probe = sh7760_i2c_probe, - .remove = sh7760_i2c_remove, + .remove_new = sh7760_i2c_remove, }; module_platform_driver(sh7760_i2c_drv); diff --git a/drivers/i2c/busses/i2c-sh_mobile.c b/drivers/i2c/busses/i2c-sh_mobile.c index 29330ee64c9c039f0c9f760b27ac48e910de440a..21717b943a9e0044d049dc3d881eb32bc40a3829 100644 --- a/drivers/i2c/busses/i2c-sh_mobile.c +++ b/drivers/i2c/busses/i2c-sh_mobile.c @@ -956,14 +956,13 @@ static int sh_mobile_i2c_probe(struct platform_device *dev) return 0; } -static int sh_mobile_i2c_remove(struct platform_device *dev) +static void sh_mobile_i2c_remove(struct platform_device *dev) { struct sh_mobile_i2c_data *pd = platform_get_drvdata(dev); i2c_del_adapter(&pd->adap); sh_mobile_i2c_release_dma(pd); pm_runtime_disable(&dev->dev); - return 0; } #ifdef CONFIG_PM_SLEEP @@ -1000,7 +999,7 @@ static struct platform_driver sh_mobile_i2c_driver = { .pm = DEV_PM_OPS, }, .probe = sh_mobile_i2c_probe, - .remove = sh_mobile_i2c_remove, + .remove_new = sh_mobile_i2c_remove, }; static int __init sh_mobile_i2c_adap_init(void) diff --git a/drivers/i2c/busses/i2c-simtec.c b/drivers/i2c/busses/i2c-simtec.c index 87701744752fb77f89c32e2ed49e93b69bae6b2c..18516bc64e046b93543fd0039df2851cd3c1bb51 100644 --- a/drivers/i2c/busses/i2c-simtec.c +++ b/drivers/i2c/busses/i2c-simtec.c @@ -126,7 +126,7 @@ static int simtec_i2c_probe(struct platform_device *dev) return ret; } -static int simtec_i2c_remove(struct platform_device *dev) +static void simtec_i2c_remove(struct platform_device *dev) { struct simtec_i2c_data *pd = platform_get_drvdata(dev); @@ -135,8 +135,6 @@ static int simtec_i2c_remove(struct platform_device *dev) iounmap(pd->reg); release_mem_region(pd->ioarea->start, resource_size(pd->ioarea)); kfree(pd); - - return 0; } /* device driver */ @@ -146,7 +144,7 @@ static struct platform_driver simtec_i2c_driver = { .name = "simtec-i2c", }, .probe = simtec_i2c_probe, - .remove = simtec_i2c_remove, + .remove_new = simtec_i2c_remove, }; module_platform_driver(simtec_i2c_driver); diff --git a/drivers/i2c/busses/i2c-st.c b/drivers/i2c/busses/i2c-st.c index f823913b75a6fc60250d42e6e973a552fe995e8b..25c3521cae0e35a433e52d9d91047bc197e1a2ca 100644 --- a/drivers/i2c/busses/i2c-st.c +++ b/drivers/i2c/busses/i2c-st.c @@ -876,13 +876,11 @@ static int st_i2c_probe(struct platform_device *pdev) return 0; } -static int st_i2c_remove(struct platform_device *pdev) +static void st_i2c_remove(struct platform_device *pdev) { struct st_i2c_dev *i2c_dev = platform_get_drvdata(pdev); i2c_del_adapter(&i2c_dev->adap); - - return 0; } static const struct of_device_id st_i2c_match[] = { @@ -899,7 +897,7 @@ static struct platform_driver st_i2c_driver = { .pm = pm_sleep_ptr(&st_i2c_pm), }, .probe = st_i2c_probe, - .remove = st_i2c_remove, + .remove_new = st_i2c_remove, }; module_platform_driver(st_i2c_driver); diff --git a/drivers/i2c/busses/i2c-stm32f4.c b/drivers/i2c/busses/i2c-stm32f4.c index eebce7ecef25b7c887e3f654cbcc0266d2a59066..6ad06a5a22b43b22cf14a9d95064a8d69f192a09 100644 --- a/drivers/i2c/busses/i2c-stm32f4.c +++ b/drivers/i2c/busses/i2c-stm32f4.c @@ -861,15 +861,13 @@ static int stm32f4_i2c_probe(struct platform_device *pdev) return ret; } -static int stm32f4_i2c_remove(struct platform_device *pdev) +static void stm32f4_i2c_remove(struct platform_device *pdev) { struct stm32f4_i2c_dev *i2c_dev = platform_get_drvdata(pdev); i2c_del_adapter(&i2c_dev->adap); clk_unprepare(i2c_dev->clk); - - return 0; } static const struct of_device_id stm32f4_i2c_match[] = { @@ -884,7 +882,7 @@ static struct platform_driver stm32f4_i2c_driver = { .of_match_table = stm32f4_i2c_match, }, .probe = stm32f4_i2c_probe, - .remove = stm32f4_i2c_remove, + .remove_new = stm32f4_i2c_remove, }; module_platform_driver(stm32f4_i2c_driver); diff --git a/drivers/i2c/busses/i2c-stm32f7.c b/drivers/i2c/busses/i2c-stm32f7.c index d1c59d83a65b96ca7eb2d7bf541aa17391984ec8..e897d9101434dccb15ab32f54bc0cf8396c1b08d 100644 --- a/drivers/i2c/busses/i2c-stm32f7.c +++ b/drivers/i2c/busses/i2c-stm32f7.c @@ -2309,7 +2309,7 @@ static int stm32f7_i2c_probe(struct platform_device *pdev) return ret; } -static int stm32f7_i2c_remove(struct platform_device *pdev) +static void stm32f7_i2c_remove(struct platform_device *pdev) { struct stm32f7_i2c_dev *i2c_dev = platform_get_drvdata(pdev); @@ -2341,8 +2341,6 @@ static int stm32f7_i2c_remove(struct platform_device *pdev) stm32f7_i2c_write_fm_plus_bits(i2c_dev, false); clk_disable_unprepare(i2c_dev->clk); - - return 0; } static int __maybe_unused stm32f7_i2c_runtime_suspend(struct device *dev) @@ -2486,7 +2484,7 @@ static struct platform_driver stm32f7_i2c_driver = { .pm = &stm32f7_i2c_pm_ops, }, .probe = stm32f7_i2c_probe, - .remove = stm32f7_i2c_remove, + .remove_new = stm32f7_i2c_remove, }; module_platform_driver(stm32f7_i2c_driver); diff --git a/drivers/i2c/busses/i2c-sun6i-p2wi.c b/drivers/i2c/busses/i2c-sun6i-p2wi.c index 9e3483f507ff5aa78989d951bb6ea8265b8b4977..ad8270cdbd3ebe82df9ba319593b0a694f5421c0 100644 --- a/drivers/i2c/busses/i2c-sun6i-p2wi.c +++ b/drivers/i2c/busses/i2c-sun6i-p2wi.c @@ -239,15 +239,9 @@ static int p2wi_probe(struct platform_device *pdev) if (irq < 0) return irq; - p2wi->clk = devm_clk_get(dev, NULL); + p2wi->clk = devm_clk_get_enabled(dev, NULL); if (IS_ERR(p2wi->clk)) { ret = PTR_ERR(p2wi->clk); - dev_err(dev, "failed to retrieve clk: %d\n", ret); - return ret; - } - - ret = clk_prepare_enable(p2wi->clk); - if (ret) { dev_err(dev, "failed to enable clk: %d\n", ret); return ret; } @@ -256,15 +250,14 @@ static int p2wi_probe(struct platform_device *pdev) p2wi->rstc = devm_reset_control_get_exclusive(dev, NULL); if (IS_ERR(p2wi->rstc)) { - ret = PTR_ERR(p2wi->rstc); dev_err(dev, "failed to retrieve reset controller: %d\n", ret); - goto err_clk_disable; + return PTR_ERR(p2wi->rstc); } ret = reset_control_deassert(p2wi->rstc); if (ret) { dev_err(dev, "failed to deassert reset line: %d\n", ret); - goto err_clk_disable; + return ret; } init_completion(&p2wi->complete); @@ -307,26 +300,20 @@ static int p2wi_probe(struct platform_device *pdev) err_reset_assert: reset_control_assert(p2wi->rstc); -err_clk_disable: - clk_disable_unprepare(p2wi->clk); - return ret; } -static int p2wi_remove(struct platform_device *dev) +static void p2wi_remove(struct platform_device *dev) { struct p2wi *p2wi = platform_get_drvdata(dev); reset_control_assert(p2wi->rstc); - clk_disable_unprepare(p2wi->clk); i2c_del_adapter(&p2wi->adapter); - - return 0; } static struct platform_driver p2wi_driver = { .probe = p2wi_probe, - .remove = p2wi_remove, + .remove_new = p2wi_remove, .driver = { .name = "i2c-sunxi-p2wi", .of_match_table = p2wi_of_match_table, diff --git a/drivers/i2c/busses/i2c-synquacer.c b/drivers/i2c/busses/i2c-synquacer.c index 50d19cf99a03a75c693430c4a2b9bbf5ff179147..4cc196ca8f6dcca5a4d425b393e9c68a5ecb2cc3 100644 --- a/drivers/i2c/busses/i2c-synquacer.c +++ b/drivers/i2c/busses/i2c-synquacer.c @@ -618,15 +618,13 @@ static int synquacer_i2c_probe(struct platform_device *pdev) return 0; } -static int synquacer_i2c_remove(struct platform_device *pdev) +static void synquacer_i2c_remove(struct platform_device *pdev) { struct synquacer_i2c *i2c = platform_get_drvdata(pdev); i2c_del_adapter(&i2c->adapter); if (!IS_ERR(i2c->pclk)) clk_disable_unprepare(i2c->pclk); - - return 0; }; static const struct of_device_id synquacer_i2c_dt_ids[] __maybe_unused = { @@ -645,7 +643,7 @@ MODULE_DEVICE_TABLE(acpi, synquacer_i2c_acpi_ids); static struct platform_driver synquacer_i2c_driver = { .probe = synquacer_i2c_probe, - .remove = synquacer_i2c_remove, + .remove_new = synquacer_i2c_remove, .driver = { .name = "synquacer_i2c", .of_match_table = of_match_ptr(synquacer_i2c_dt_ids), diff --git a/drivers/i2c/busses/i2c-tegra-bpmp.c b/drivers/i2c/busses/i2c-tegra-bpmp.c index 95139985b2d5efdaa390c556dc9041be63a1edcd..bc3f94561746e9b7a3e48cc04bfc44dc9f4f0b68 100644 --- a/drivers/i2c/busses/i2c-tegra-bpmp.c +++ b/drivers/i2c/busses/i2c-tegra-bpmp.c @@ -316,13 +316,11 @@ static int tegra_bpmp_i2c_probe(struct platform_device *pdev) return i2c_add_adapter(&i2c->adapter); } -static int tegra_bpmp_i2c_remove(struct platform_device *pdev) +static void tegra_bpmp_i2c_remove(struct platform_device *pdev) { struct tegra_bpmp_i2c *i2c = platform_get_drvdata(pdev); i2c_del_adapter(&i2c->adapter); - - return 0; } static const struct of_device_id tegra_bpmp_i2c_of_match[] = { @@ -337,7 +335,7 @@ static struct platform_driver tegra_bpmp_i2c_driver = { .of_match_table = tegra_bpmp_i2c_of_match, }, .probe = tegra_bpmp_i2c_probe, - .remove = tegra_bpmp_i2c_remove, + .remove_new = tegra_bpmp_i2c_remove, }; module_platform_driver(tegra_bpmp_i2c_driver); diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index 157066f06a32d7b296c86429175212d2a6f71f99..bcbbf23aa530c946749464abe0af4385e920df31 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -249,8 +249,7 @@ struct tegra_i2c_hw_feature { * @msg_read: indicates that the transfer is a read access * @timings: i2c timings information like bus frequency * @multimaster_mode: indicates that I2C controller is in multi-master mode - * @tx_dma_chan: DMA transmit channel - * @rx_dma_chan: DMA receive channel + * @dma_chan: DMA channel * @dma_phys: handle to DMA resources * @dma_buf: pointer to allocated DMA buffer * @dma_buf_size: DMA buffer size @@ -283,8 +282,7 @@ struct tegra_i2c_dev { u8 *msg_buf; struct completion dma_complete; - struct dma_chan *tx_dma_chan; - struct dma_chan *rx_dma_chan; + struct dma_chan *dma_chan; unsigned int dma_buf_size; struct device *dma_dev; dma_addr_t dma_phys; @@ -298,6 +296,9 @@ struct tegra_i2c_dev { bool is_vi; }; +#define IS_DVC(dev) (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC) && (dev)->is_dvc) +#define IS_VI(dev) (IS_ENABLED(CONFIG_ARCH_TEGRA_210_SOC) && (dev)->is_vi) + static void dvc_writel(struct tegra_i2c_dev *i2c_dev, u32 val, unsigned int reg) { @@ -315,9 +316,9 @@ static u32 dvc_readl(struct tegra_i2c_dev *i2c_dev, unsigned int reg) */ static u32 tegra_i2c_reg_addr(struct tegra_i2c_dev *i2c_dev, unsigned int reg) { - if (i2c_dev->is_dvc) + if (IS_DVC(i2c_dev)) reg += (reg >= I2C_TX_FIFO) ? 0x10 : 0x40; - else if (i2c_dev->is_vi) + else if (IS_VI(i2c_dev)) reg = 0xc00 + (reg << 2); return reg; @@ -330,7 +331,7 @@ static void i2c_writel(struct tegra_i2c_dev *i2c_dev, u32 val, unsigned int reg) /* read back register to make sure that register writes completed */ if (reg != I2C_TX_FIFO) readl_relaxed(i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, reg)); - else if (i2c_dev->is_vi) + else if (IS_VI(i2c_dev)) readl_relaxed(i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, I2C_INT_STATUS)); } @@ -393,16 +394,14 @@ static int tegra_i2c_dma_submit(struct tegra_i2c_dev *i2c_dev, size_t len) { struct dma_async_tx_descriptor *dma_desc; enum dma_transfer_direction dir; - struct dma_chan *chan; dev_dbg(i2c_dev->dev, "starting DMA for length: %zu\n", len); reinit_completion(&i2c_dev->dma_complete); dir = i2c_dev->msg_read ? DMA_DEV_TO_MEM : DMA_MEM_TO_DEV; - chan = i2c_dev->msg_read ? i2c_dev->rx_dma_chan : i2c_dev->tx_dma_chan; - dma_desc = dmaengine_prep_slave_single(chan, i2c_dev->dma_phys, + dma_desc = dmaengine_prep_slave_single(i2c_dev->dma_chan, i2c_dev->dma_phys, len, dir, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); if (!dma_desc) { @@ -415,7 +414,7 @@ static int tegra_i2c_dma_submit(struct tegra_i2c_dev *i2c_dev, size_t len) dma_desc->callback_param = i2c_dev; dmaengine_submit(dma_desc); - dma_async_issue_pending(chan); + dma_async_issue_pending(i2c_dev->dma_chan); return 0; } @@ -428,25 +427,19 @@ static void tegra_i2c_release_dma(struct tegra_i2c_dev *i2c_dev) i2c_dev->dma_buf = NULL; } - if (i2c_dev->tx_dma_chan) { - dma_release_channel(i2c_dev->tx_dma_chan); - i2c_dev->tx_dma_chan = NULL; - } - - if (i2c_dev->rx_dma_chan) { - dma_release_channel(i2c_dev->rx_dma_chan); - i2c_dev->rx_dma_chan = NULL; + if (i2c_dev->dma_chan) { + dma_release_channel(i2c_dev->dma_chan); + i2c_dev->dma_chan = NULL; } } static int tegra_i2c_init_dma(struct tegra_i2c_dev *i2c_dev) { - struct dma_chan *chan; dma_addr_t dma_phys; u32 *dma_buf; int err; - if (i2c_dev->is_vi) + if (IS_VI(i2c_dev)) return 0; if (!i2c_dev->hw->has_apb_dma) { @@ -459,25 +452,18 @@ static int tegra_i2c_init_dma(struct tegra_i2c_dev *i2c_dev) return 0; } - chan = dma_request_chan(i2c_dev->dev, "rx"); - if (IS_ERR(chan)) { - err = PTR_ERR(chan); - goto err_out; - } - - i2c_dev->rx_dma_chan = chan; - - chan = dma_request_chan(i2c_dev->dev, "tx"); - if (IS_ERR(chan)) { - err = PTR_ERR(chan); + /* + * The same channel will be used for both RX and TX. + * Keeping the name as "tx" for backward compatibility + * with existing devicetrees. + */ + i2c_dev->dma_chan = dma_request_chan(i2c_dev->dev, "tx"); + if (IS_ERR(i2c_dev->dma_chan)) { + err = PTR_ERR(i2c_dev->dma_chan); goto err_out; } - i2c_dev->tx_dma_chan = chan; - - WARN_ON(i2c_dev->tx_dma_chan->device != i2c_dev->rx_dma_chan->device); - i2c_dev->dma_dev = chan->device->dev; - + i2c_dev->dma_dev = i2c_dev->dma_chan->device->dev; i2c_dev->dma_buf_size = i2c_dev->hw->quirks->max_write_len + I2C_PACKET_HEADER_SIZE; @@ -639,7 +625,7 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev) WARN_ON_ONCE(err); - if (i2c_dev->is_dvc) + if (IS_DVC(i2c_dev)) tegra_dvc_init(i2c_dev); val = I2C_CNFG_NEW_MASTER_FSM | I2C_CNFG_PACKET_MODE_EN | @@ -651,7 +637,7 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev) i2c_writel(i2c_dev, val, I2C_CNFG); i2c_writel(i2c_dev, 0, I2C_INT_MASK); - if (i2c_dev->is_vi) + if (IS_VI(i2c_dev)) tegra_i2c_vi_init(i2c_dev); switch (t->bus_freq_hz) { @@ -703,7 +689,7 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev) return err; } - if (!i2c_dev->is_dvc && !i2c_dev->is_vi) { + if (!IS_DVC(i2c_dev) && !IS_VI(i2c_dev)) { u32 sl_cfg = i2c_readl(i2c_dev, I2C_SL_CNFG); sl_cfg |= I2C_SL_CNFG_NACK | I2C_SL_CNFG_NEWSL; @@ -846,7 +832,7 @@ static int tegra_i2c_fill_tx_fifo(struct tegra_i2c_dev *i2c_dev) i2c_dev->msg_buf_remaining = buf_remaining; i2c_dev->msg_buf = buf + words_to_transfer * BYTES_PER_FIFO_WORD; - if (i2c_dev->is_vi) + if (IS_VI(i2c_dev)) i2c_writesl_vi(i2c_dev, buf, I2C_TX_FIFO, words_to_transfer); else i2c_writesl(i2c_dev, buf, I2C_TX_FIFO, words_to_transfer); @@ -933,7 +919,7 @@ static irqreturn_t tegra_i2c_isr(int irq, void *dev_id) } i2c_writel(i2c_dev, status, I2C_INT_STATUS); - if (i2c_dev->is_dvc) + if (IS_DVC(i2c_dev)) dvc_writel(i2c_dev, DVC_STATUS_I2C_DONE_INTR, DVC_STATUS); /* @@ -972,15 +958,11 @@ static irqreturn_t tegra_i2c_isr(int irq, void *dev_id) i2c_writel(i2c_dev, status, I2C_INT_STATUS); - if (i2c_dev->is_dvc) + if (IS_DVC(i2c_dev)) dvc_writel(i2c_dev, DVC_STATUS_I2C_DONE_INTR, DVC_STATUS); if (i2c_dev->dma_mode) { - if (i2c_dev->msg_read) - dmaengine_terminate_async(i2c_dev->rx_dma_chan); - else - dmaengine_terminate_async(i2c_dev->tx_dma_chan); - + dmaengine_terminate_async(i2c_dev->dma_chan); complete(&i2c_dev->dma_complete); } @@ -994,7 +976,6 @@ static void tegra_i2c_config_fifo_trig(struct tegra_i2c_dev *i2c_dev, { struct dma_slave_config slv_config = {0}; u32 val, reg, dma_burst, reg_offset; - struct dma_chan *chan; int err; if (i2c_dev->hw->has_mst_fifo) @@ -1011,7 +992,6 @@ static void tegra_i2c_config_fifo_trig(struct tegra_i2c_dev *i2c_dev, dma_burst = 8; if (i2c_dev->msg_read) { - chan = i2c_dev->rx_dma_chan; reg_offset = tegra_i2c_reg_addr(i2c_dev, I2C_RX_FIFO); slv_config.src_addr = i2c_dev->base_phys + reg_offset; @@ -1023,7 +1003,6 @@ static void tegra_i2c_config_fifo_trig(struct tegra_i2c_dev *i2c_dev, else val = I2C_FIFO_CONTROL_RX_TRIG(dma_burst); } else { - chan = i2c_dev->tx_dma_chan; reg_offset = tegra_i2c_reg_addr(i2c_dev, I2C_TX_FIFO); slv_config.dst_addr = i2c_dev->base_phys + reg_offset; @@ -1037,7 +1016,7 @@ static void tegra_i2c_config_fifo_trig(struct tegra_i2c_dev *i2c_dev, } slv_config.device_fc = true; - err = dmaengine_slave_config(chan, &slv_config); + err = dmaengine_slave_config(i2c_dev->dma_chan, &slv_config); if (err) { dev_err(i2c_dev->dev, "DMA config failed: %d\n", err); dev_err(i2c_dev->dev, "falling back to PIO\n"); @@ -1347,13 +1326,8 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev, * performs synchronization after the transfer's termination * and we want to get a completion if transfer succeeded. */ - dmaengine_synchronize(i2c_dev->msg_read ? - i2c_dev->rx_dma_chan : - i2c_dev->tx_dma_chan); - - dmaengine_terminate_sync(i2c_dev->msg_read ? - i2c_dev->rx_dma_chan : - i2c_dev->tx_dma_chan); + dmaengine_synchronize(i2c_dev->dma_chan); + dmaengine_terminate_sync(i2c_dev->dma_chan); if (!time_left && !completion_done(&i2c_dev->dma_complete)) { dev_err(i2c_dev->dev, "DMA transfer timed out\n"); @@ -1654,13 +1628,17 @@ static const struct tegra_i2c_hw_feature tegra194_i2c_hw = { static const struct of_device_id tegra_i2c_of_match[] = { { .compatible = "nvidia,tegra194-i2c", .data = &tegra194_i2c_hw, }, { .compatible = "nvidia,tegra186-i2c", .data = &tegra186_i2c_hw, }, +#if IS_ENABLED(CONFIG_ARCH_TEGRA_210_SOC) { .compatible = "nvidia,tegra210-i2c-vi", .data = &tegra210_i2c_hw, }, +#endif { .compatible = "nvidia,tegra210-i2c", .data = &tegra210_i2c_hw, }, { .compatible = "nvidia,tegra124-i2c", .data = &tegra124_i2c_hw, }, { .compatible = "nvidia,tegra114-i2c", .data = &tegra114_i2c_hw, }, { .compatible = "nvidia,tegra30-i2c", .data = &tegra30_i2c_hw, }, { .compatible = "nvidia,tegra20-i2c", .data = &tegra20_i2c_hw, }, +#if IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC) { .compatible = "nvidia,tegra20-i2c-dvc", .data = &tegra20_i2c_hw, }, +#endif {}, }; MODULE_DEVICE_TABLE(of, tegra_i2c_of_match); @@ -1675,10 +1653,12 @@ static void tegra_i2c_parse_dt(struct tegra_i2c_dev *i2c_dev) multi_mode = device_property_read_bool(i2c_dev->dev, "multi-master"); i2c_dev->multimaster_mode = multi_mode; - if (of_device_is_compatible(np, "nvidia,tegra20-i2c-dvc")) + if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC) && + of_device_is_compatible(np, "nvidia,tegra20-i2c-dvc")) i2c_dev->is_dvc = true; - if (of_device_is_compatible(np, "nvidia,tegra210-i2c-vi")) + if (IS_ENABLED(CONFIG_ARCH_TEGRA_210_SOC) && + of_device_is_compatible(np, "nvidia,tegra210-i2c-vi")) i2c_dev->is_vi = true; } @@ -1707,7 +1687,7 @@ static int tegra_i2c_init_clocks(struct tegra_i2c_dev *i2c_dev) if (i2c_dev->hw == &tegra20_i2c_hw || i2c_dev->hw == &tegra30_i2c_hw) i2c_dev->clocks[i2c_dev->nclocks++].id = "fast-clk"; - if (i2c_dev->is_vi) + if (IS_VI(i2c_dev)) i2c_dev->clocks[i2c_dev->nclocks++].id = "slow"; err = devm_clk_bulk_get(i2c_dev->dev, i2c_dev->nclocks, @@ -1825,7 +1805,7 @@ static int tegra_i2c_probe(struct platform_device *pdev) * VI I2C device shouldn't be marked as IRQ-safe because VI I2C won't * be used for atomic transfers. */ - if (!i2c_dev->is_vi) + if (!IS_VI(i2c_dev)) pm_runtime_irq_safe(i2c_dev->dev); pm_runtime_enable(i2c_dev->dev); @@ -1868,7 +1848,7 @@ static int tegra_i2c_probe(struct platform_device *pdev) return err; } -static int tegra_i2c_remove(struct platform_device *pdev) +static void tegra_i2c_remove(struct platform_device *pdev) { struct tegra_i2c_dev *i2c_dev = platform_get_drvdata(pdev); @@ -1877,8 +1857,6 @@ static int tegra_i2c_remove(struct platform_device *pdev) tegra_i2c_release_dma(i2c_dev); tegra_i2c_release_clocks(i2c_dev); - - return 0; } static int __maybe_unused tegra_i2c_runtime_resume(struct device *dev) @@ -1899,7 +1877,7 @@ static int __maybe_unused tegra_i2c_runtime_resume(struct device *dev) * power ON/OFF during runtime PM resume/suspend, meaning that * controller needs to be re-initialized after power ON. */ - if (i2c_dev->is_vi) { + if (IS_VI(i2c_dev)) { err = tegra_i2c_init(i2c_dev); if (err) goto disable_clocks; @@ -1987,7 +1965,7 @@ MODULE_DEVICE_TABLE(acpi, tegra_i2c_acpi_match); static struct platform_driver tegra_i2c_driver = { .probe = tegra_i2c_probe, - .remove = tegra_i2c_remove, + .remove_new = tegra_i2c_remove, .driver = { .name = "tegra-i2c", .of_match_table = tegra_i2c_of_match, diff --git a/drivers/i2c/busses/i2c-tiny-usb.c b/drivers/i2c/busses/i2c-tiny-usb.c index 7279ca0eaa2d0ca723995e4b3b2e28d306745e85..d1fa9ff5aeab48f809eb8a928222a5bfb1587a0a 100644 --- a/drivers/i2c/busses/i2c-tiny-usb.c +++ b/drivers/i2c/busses/i2c-tiny-usb.c @@ -226,10 +226,8 @@ static int i2c_tiny_usb_probe(struct usb_interface *interface, /* allocate memory for our device state and initialize it */ dev = kzalloc(sizeof(*dev), GFP_KERNEL); - if (dev == NULL) { - dev_err(&interface->dev, "Out of memory\n"); + if (!dev) goto error; - } dev->usb_dev = usb_get_dev(interface_to_usbdev(interface)); dev->interface = interface; diff --git a/drivers/i2c/busses/i2c-uniphier-f.c b/drivers/i2c/busses/i2c-uniphier-f.c index d7b622891e52decb3e313ec3aa656fd122c4e23e..dbc91c7c3788ff8b5700de5598d29032404dc8bb 100644 --- a/drivers/i2c/busses/i2c-uniphier-f.c +++ b/drivers/i2c/busses/i2c-uniphier-f.c @@ -540,21 +540,16 @@ static int uniphier_fi2c_probe(struct platform_device *pdev) return -EINVAL; } - priv->clk = devm_clk_get(dev, NULL); + priv->clk = devm_clk_get_enabled(dev, NULL); if (IS_ERR(priv->clk)) { - dev_err(dev, "failed to get clock\n"); + dev_err(dev, "failed to enable clock\n"); return PTR_ERR(priv->clk); } - ret = clk_prepare_enable(priv->clk); - if (ret) - return ret; - clk_rate = clk_get_rate(priv->clk); if (!clk_rate) { dev_err(dev, "input clock rate should not be zero\n"); - ret = -EINVAL; - goto disable_clk; + return -EINVAL; } priv->clk_cycle = clk_rate / bus_speed; @@ -575,25 +570,17 @@ static int uniphier_fi2c_probe(struct platform_device *pdev) pdev->name, priv); if (ret) { dev_err(dev, "failed to request irq %d\n", irq); - goto disable_clk; + return ret; } - ret = i2c_add_adapter(&priv->adap); -disable_clk: - if (ret) - clk_disable_unprepare(priv->clk); - - return ret; + return i2c_add_adapter(&priv->adap); } -static int uniphier_fi2c_remove(struct platform_device *pdev) +static void uniphier_fi2c_remove(struct platform_device *pdev) { struct uniphier_fi2c_priv *priv = platform_get_drvdata(pdev); i2c_del_adapter(&priv->adap); - clk_disable_unprepare(priv->clk); - - return 0; } static int __maybe_unused uniphier_fi2c_suspend(struct device *dev) @@ -631,7 +618,7 @@ MODULE_DEVICE_TABLE(of, uniphier_fi2c_match); static struct platform_driver uniphier_fi2c_drv = { .probe = uniphier_fi2c_probe, - .remove = uniphier_fi2c_remove, + .remove_new = uniphier_fi2c_remove, .driver = { .name = "uniphier-fi2c", .of_match_table = uniphier_fi2c_match, diff --git a/drivers/i2c/busses/i2c-uniphier.c b/drivers/i2c/busses/i2c-uniphier.c index e3ebae381f08af31c5c10034600305a5f415ad38..854ac25b586285a1d79e1c2f7e0fe6ad504016e8 100644 --- a/drivers/i2c/busses/i2c-uniphier.c +++ b/drivers/i2c/busses/i2c-uniphier.c @@ -335,21 +335,16 @@ static int uniphier_i2c_probe(struct platform_device *pdev) return -EINVAL; } - priv->clk = devm_clk_get(dev, NULL); + priv->clk = devm_clk_get_enabled(dev, NULL); if (IS_ERR(priv->clk)) { - dev_err(dev, "failed to get clock\n"); + dev_err(dev, "failed to enable clock\n"); return PTR_ERR(priv->clk); } - ret = clk_prepare_enable(priv->clk); - if (ret) - return ret; - clk_rate = clk_get_rate(priv->clk); if (!clk_rate) { dev_err(dev, "input clock rate should not be zero\n"); - ret = -EINVAL; - goto disable_clk; + return -EINVAL; } priv->clk_cycle = clk_rate / bus_speed; @@ -369,25 +364,17 @@ static int uniphier_i2c_probe(struct platform_device *pdev) priv); if (ret) { dev_err(dev, "failed to request irq %d\n", irq); - goto disable_clk; + return ret; } - ret = i2c_add_adapter(&priv->adap); -disable_clk: - if (ret) - clk_disable_unprepare(priv->clk); - - return ret; + return i2c_add_adapter(&priv->adap); } -static int uniphier_i2c_remove(struct platform_device *pdev) +static void uniphier_i2c_remove(struct platform_device *pdev) { struct uniphier_i2c_priv *priv = platform_get_drvdata(pdev); i2c_del_adapter(&priv->adap); - clk_disable_unprepare(priv->clk); - - return 0; } static int __maybe_unused uniphier_i2c_suspend(struct device *dev) @@ -425,7 +412,7 @@ MODULE_DEVICE_TABLE(of, uniphier_i2c_match); static struct platform_driver uniphier_i2c_drv = { .probe = uniphier_i2c_probe, - .remove = uniphier_i2c_remove, + .remove_new = uniphier_i2c_remove, .driver = { .name = "uniphier-i2c", .of_match_table = uniphier_i2c_match, diff --git a/drivers/i2c/busses/i2c-versatile.c b/drivers/i2c/busses/i2c-versatile.c index 1ab419f8fa527f08428a7b2646af9e86a91838cc..76abfa77e200170196488f533430df0ed908036b 100644 --- a/drivers/i2c/busses/i2c-versatile.c +++ b/drivers/i2c/busses/i2c-versatile.c @@ -64,15 +64,13 @@ static const struct i2c_algo_bit_data i2c_versatile_algo = { static int i2c_versatile_probe(struct platform_device *dev) { struct i2c_versatile *i2c; - struct resource *r; int ret; i2c = devm_kzalloc(&dev->dev, sizeof(struct i2c_versatile), GFP_KERNEL); if (!i2c) return -ENOMEM; - r = platform_get_resource(dev, IORESOURCE_MEM, 0); - i2c->base = devm_ioremap_resource(&dev->dev, r); + i2c->base = devm_platform_get_and_ioremap_resource(dev, 0, NULL); if (IS_ERR(i2c->base)) return PTR_ERR(i2c->base); @@ -96,12 +94,11 @@ static int i2c_versatile_probe(struct platform_device *dev) return 0; } -static int i2c_versatile_remove(struct platform_device *dev) +static void i2c_versatile_remove(struct platform_device *dev) { struct i2c_versatile *i2c = platform_get_drvdata(dev); i2c_del_adapter(&i2c->adap); - return 0; } static const struct of_device_id i2c_versatile_match[] = { @@ -112,7 +109,7 @@ MODULE_DEVICE_TABLE(of, i2c_versatile_match); static struct platform_driver i2c_versatile_driver = { .probe = i2c_versatile_probe, - .remove = i2c_versatile_remove, + .remove_new = i2c_versatile_remove, .driver = { .name = "versatile-i2c", .of_match_table = i2c_versatile_match, diff --git a/drivers/i2c/busses/i2c-viperboard.c b/drivers/i2c/busses/i2c-viperboard.c index 8b5322c3bce0ea7d144aa748bba2b5ca0ae7b56d..9e153b5b0e8e425b2b3113a09aa879096ba6142b 100644 --- a/drivers/i2c/busses/i2c-viperboard.c +++ b/drivers/i2c/busses/i2c-viperboard.c @@ -407,20 +407,18 @@ static int vprbrd_i2c_probe(struct platform_device *pdev) return 0; } -static int vprbrd_i2c_remove(struct platform_device *pdev) +static void vprbrd_i2c_remove(struct platform_device *pdev) { struct vprbrd_i2c *vb_i2c = platform_get_drvdata(pdev); i2c_del_adapter(&vb_i2c->i2c); - - return 0; } static struct platform_driver vprbrd_i2c_driver = { .driver.name = "viperboard-i2c", .driver.owner = THIS_MODULE, .probe = vprbrd_i2c_probe, - .remove = vprbrd_i2c_remove, + .remove_new = vprbrd_i2c_remove, }; static int __init vprbrd_i2c_init(void) diff --git a/drivers/i2c/busses/i2c-wmt.c b/drivers/i2c/busses/i2c-wmt.c index 7d4bc8736079323784dbff65b833e98dce303353..76118abc6e104d083047714e9cb036116ab9ef85 100644 --- a/drivers/i2c/busses/i2c-wmt.c +++ b/drivers/i2c/busses/i2c-wmt.c @@ -372,7 +372,6 @@ static int wmt_i2c_probe(struct platform_device *pdev) struct device_node *np = pdev->dev.of_node; struct wmt_i2c_dev *i2c_dev; struct i2c_adapter *adap; - struct resource *res; int err; u32 clk_rate; @@ -380,8 +379,7 @@ static int wmt_i2c_probe(struct platform_device *pdev) if (!i2c_dev) return -ENOMEM; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - i2c_dev->base = devm_ioremap_resource(&pdev->dev, res); + i2c_dev->base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL); if (IS_ERR(i2c_dev->base)) return PTR_ERR(i2c_dev->base); @@ -436,7 +434,7 @@ static int wmt_i2c_probe(struct platform_device *pdev) return 0; } -static int wmt_i2c_remove(struct platform_device *pdev) +static void wmt_i2c_remove(struct platform_device *pdev) { struct wmt_i2c_dev *i2c_dev = platform_get_drvdata(pdev); @@ -444,8 +442,6 @@ static int wmt_i2c_remove(struct platform_device *pdev) writew(0, i2c_dev->base + REG_IMR); clk_disable_unprepare(i2c_dev->clk); i2c_del_adapter(&i2c_dev->adapter); - - return 0; } static const struct of_device_id wmt_i2c_dt_ids[] = { @@ -455,7 +451,7 @@ static const struct of_device_id wmt_i2c_dt_ids[] = { static struct platform_driver wmt_i2c_driver = { .probe = wmt_i2c_probe, - .remove = wmt_i2c_remove, + .remove_new = wmt_i2c_remove, .driver = { .name = "wmt-i2c", .of_match_table = wmt_i2c_dt_ids, diff --git a/drivers/i2c/busses/i2c-xgene-slimpro.c b/drivers/i2c/busses/i2c-xgene-slimpro.c index 3538d36368a90b5fcf5f8e18e01826908c2198ec..fbc1ffbd2fa7d6643601fc47769e3af715474483 100644 --- a/drivers/i2c/busses/i2c-xgene-slimpro.c +++ b/drivers/i2c/busses/i2c-xgene-slimpro.c @@ -560,7 +560,7 @@ static int xgene_slimpro_i2c_probe(struct platform_device *pdev) return rc; } -static int xgene_slimpro_i2c_remove(struct platform_device *pdev) +static void xgene_slimpro_i2c_remove(struct platform_device *pdev) { struct slimpro_i2c_dev *ctx = platform_get_drvdata(pdev); @@ -570,8 +570,6 @@ static int xgene_slimpro_i2c_remove(struct platform_device *pdev) mbox_free_channel(ctx->mbox_chan); else pcc_mbox_free_channel(ctx->pcc_chan); - - return 0; } static const struct of_device_id xgene_slimpro_i2c_dt_ids[] = { @@ -591,7 +589,7 @@ MODULE_DEVICE_TABLE(acpi, xgene_slimpro_i2c_acpi_ids); static struct platform_driver xgene_slimpro_i2c_driver = { .probe = xgene_slimpro_i2c_probe, - .remove = xgene_slimpro_i2c_remove, + .remove_new = xgene_slimpro_i2c_remove, .driver = { .name = "xgene-slimpro-i2c", .of_match_table = of_match_ptr(xgene_slimpro_i2c_dt_ids), diff --git a/drivers/i2c/busses/i2c-xiic.c b/drivers/i2c/busses/i2c-xiic.c index 8a3d9817cb41cae3d54f7291e6279b5a59ce5627..b3bb97762c859fcdc04c3b21491055d9f105ce4e 100644 --- a/drivers/i2c/busses/i2c-xiic.c +++ b/drivers/i2c/busses/i2c-xiic.c @@ -721,6 +721,8 @@ static irqreturn_t xiic_process(int irq, void *dev_id) wakeup_req = 1; wakeup_code = STATE_ERROR; } + /* don't try to handle other events */ + goto out; } if (pend & XIIC_INTR_RX_FULL_MASK) { /* Receive register/FIFO is full */ @@ -1256,16 +1258,11 @@ static int xiic_i2c_probe(struct platform_device *pdev) mutex_init(&i2c->lock); - i2c->clk = devm_clk_get(&pdev->dev, NULL); + i2c->clk = devm_clk_get_enabled(&pdev->dev, NULL); if (IS_ERR(i2c->clk)) return dev_err_probe(&pdev->dev, PTR_ERR(i2c->clk), - "input clock not found.\n"); + "failed to enable input clock.\n"); - ret = clk_prepare_enable(i2c->clk); - if (ret) { - dev_err(&pdev->dev, "Unable to enable clock.\n"); - return ret; - } i2c->dev = &pdev->dev; pm_runtime_set_autosuspend_delay(i2c->dev, XIIC_PM_TIMEOUT); pm_runtime_use_autosuspend(i2c->dev); @@ -1286,7 +1283,7 @@ static int xiic_i2c_probe(struct platform_device *pdev) if (ret < 0) { dev_err(&pdev->dev, "Cannot claim IRQ\n"); - goto err_clk_dis; + goto err_pm_disable; } i2c->singlemaster = @@ -1307,14 +1304,14 @@ static int xiic_i2c_probe(struct platform_device *pdev) ret = xiic_reinit(i2c); if (ret < 0) { dev_err(&pdev->dev, "Cannot xiic_reinit\n"); - goto err_clk_dis; + goto err_pm_disable; } /* add i2c adapter to i2c tree */ ret = i2c_add_adapter(&i2c->adap); if (ret) { xiic_deinit(i2c); - goto err_clk_dis; + goto err_pm_disable; } if (pdata) { @@ -1328,14 +1325,14 @@ static int xiic_i2c_probe(struct platform_device *pdev) return 0; -err_clk_dis: +err_pm_disable: pm_runtime_set_suspended(&pdev->dev); pm_runtime_disable(&pdev->dev); - clk_disable_unprepare(i2c->clk); + return ret; } -static int xiic_i2c_remove(struct platform_device *pdev) +static void xiic_i2c_remove(struct platform_device *pdev) { struct xiic_i2c *i2c = platform_get_drvdata(pdev); int ret; @@ -1352,12 +1349,9 @@ static int xiic_i2c_remove(struct platform_device *pdev) xiic_deinit(i2c); pm_runtime_put_sync(i2c->dev); - clk_disable_unprepare(i2c->clk); pm_runtime_disable(&pdev->dev); pm_runtime_set_suspended(&pdev->dev); pm_runtime_dont_use_autosuspend(&pdev->dev); - - return 0; } static int __maybe_unused xiic_i2c_runtime_suspend(struct device *dev) @@ -1390,7 +1384,7 @@ static const struct dev_pm_ops xiic_dev_pm_ops = { static struct platform_driver xiic_i2c_driver = { .probe = xiic_i2c_probe, - .remove = xiic_i2c_remove, + .remove_new = xiic_i2c_remove, .driver = { .name = DRIVER_NAME, .of_match_table = of_match_ptr(xiic_of_match), diff --git a/drivers/i2c/busses/i2c-xlp9xx.c b/drivers/i2c/busses/i2c-xlp9xx.c index 4e3b11c0f73251f7782644ccd0daca49c1a13ab6..f59e8c544f36655b87cc23d466cf393b78f2c7cd 100644 --- a/drivers/i2c/busses/i2c-xlp9xx.c +++ b/drivers/i2c/busses/i2c-xlp9xx.c @@ -559,7 +559,7 @@ static int xlp9xx_i2c_probe(struct platform_device *pdev) return 0; } -static int xlp9xx_i2c_remove(struct platform_device *pdev) +static void xlp9xx_i2c_remove(struct platform_device *pdev) { struct xlp9xx_i2c_dev *priv; @@ -568,8 +568,6 @@ static int xlp9xx_i2c_remove(struct platform_device *pdev) synchronize_irq(priv->irq); i2c_del_adapter(&priv->adapter); xlp9xx_write_i2c_reg(priv, XLP9XX_I2C_CTRL, 0); - - return 0; } #ifdef CONFIG_ACPI @@ -583,7 +581,7 @@ MODULE_DEVICE_TABLE(acpi, xlp9xx_i2c_acpi_ids); static struct platform_driver xlp9xx_i2c_driver = { .probe = xlp9xx_i2c_probe, - .remove = xlp9xx_i2c_remove, + .remove_new = xlp9xx_i2c_remove, .driver = { .name = "xlp9xx-i2c", .acpi_match_table = ACPI_PTR(xlp9xx_i2c_acpi_ids), diff --git a/drivers/i2c/busses/scx200_acb.c b/drivers/i2c/busses/scx200_acb.c index 7b42a18bd05c2690a7c67eacec72d146ed89ad26..83c1db610f54b8c6d64139466e777dccc95c330f 100644 --- a/drivers/i2c/busses/scx200_acb.c +++ b/drivers/i2c/busses/scx200_acb.c @@ -523,14 +523,12 @@ static void scx200_cleanup_iface(struct scx200_acb_iface *iface) kfree(iface); } -static int scx200_remove(struct platform_device *pdev) +static void scx200_remove(struct platform_device *pdev) { struct scx200_acb_iface *iface; iface = platform_get_drvdata(pdev); scx200_cleanup_iface(iface); - - return 0; } static struct platform_driver scx200_pci_driver = { @@ -538,7 +536,7 @@ static struct platform_driver scx200_pci_driver = { .name = "cs5535-smb", }, .probe = scx200_probe, - .remove = scx200_remove, + .remove_new = scx200_remove, }; static const struct pci_device_id scx200_isa[] = { diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c index ae3af738b03f5cf73c54eb893ccec45d28ef627d..60746652fd5255cb998c5690f985430aaf0d773c 100644 --- a/drivers/i2c/i2c-core-base.c +++ b/drivers/i2c/i2c-core-base.c @@ -114,6 +114,25 @@ const struct i2c_device_id *i2c_match_id(const struct i2c_device_id *id, } EXPORT_SYMBOL_GPL(i2c_match_id); +const void *i2c_get_match_data(const struct i2c_client *client) +{ + struct i2c_driver *driver = to_i2c_driver(client->dev.driver); + const struct i2c_device_id *match; + const void *data; + + data = device_get_match_data(&client->dev); + if (!data) { + match = i2c_match_id(driver->id_table, client); + if (!match) + return NULL; + + data = (const void *)match->driver_data; + } + + return data; +} +EXPORT_SYMBOL(i2c_get_match_data); + static int i2c_device_match(struct device *dev, struct device_driver *drv) { struct i2c_client *client = i2c_verify_client(dev); diff --git a/drivers/i2c/muxes/i2c-arb-gpio-challenge.c b/drivers/i2c/muxes/i2c-arb-gpio-challenge.c index 1c78657631f4f838196aa093640bd218b880e1c6..24168e9f7df4c15299b72846d23c8d62bb5410cc 100644 --- a/drivers/i2c/muxes/i2c-arb-gpio-challenge.c +++ b/drivers/i2c/muxes/i2c-arb-gpio-challenge.c @@ -174,13 +174,12 @@ static int i2c_arbitrator_probe(struct platform_device *pdev) return ret; } -static int i2c_arbitrator_remove(struct platform_device *pdev) +static void i2c_arbitrator_remove(struct platform_device *pdev) { struct i2c_mux_core *muxc = platform_get_drvdata(pdev); i2c_mux_del_adapters(muxc); i2c_put_adapter(muxc->parent); - return 0; } static const struct of_device_id i2c_arbitrator_of_match[] = { @@ -191,7 +190,7 @@ MODULE_DEVICE_TABLE(of, i2c_arbitrator_of_match); static struct platform_driver i2c_arbitrator_driver = { .probe = i2c_arbitrator_probe, - .remove = i2c_arbitrator_remove, + .remove_new = i2c_arbitrator_remove, .driver = { .name = "i2c-arb-gpio-challenge", .of_match_table = i2c_arbitrator_of_match, diff --git a/drivers/i2c/muxes/i2c-demux-pinctrl.c b/drivers/i2c/muxes/i2c-demux-pinctrl.c index f7a7405d4350a10718b7948d546ca31fc11dabdb..a3a122fae71e09853200069e668b326e139eb90f 100644 --- a/drivers/i2c/muxes/i2c-demux-pinctrl.c +++ b/drivers/i2c/muxes/i2c-demux-pinctrl.c @@ -282,7 +282,7 @@ static int i2c_demux_pinctrl_probe(struct platform_device *pdev) return err; } -static int i2c_demux_pinctrl_remove(struct platform_device *pdev) +static void i2c_demux_pinctrl_remove(struct platform_device *pdev) { struct i2c_demux_pinctrl_priv *priv = platform_get_drvdata(pdev); int i; @@ -296,8 +296,6 @@ static int i2c_demux_pinctrl_remove(struct platform_device *pdev) of_node_put(priv->chan[i].parent_np); of_changeset_destroy(&priv->chan[i].chgset); } - - return 0; } static const struct of_device_id i2c_demux_pinctrl_of_match[] = { @@ -312,7 +310,7 @@ static struct platform_driver i2c_demux_pinctrl_driver = { .of_match_table = i2c_demux_pinctrl_of_match, }, .probe = i2c_demux_pinctrl_probe, - .remove = i2c_demux_pinctrl_remove, + .remove_new = i2c_demux_pinctrl_remove, }; module_platform_driver(i2c_demux_pinctrl_driver); diff --git a/drivers/i2c/muxes/i2c-mux-gpio.c b/drivers/i2c/muxes/i2c-mux-gpio.c index 73a23e117ebec4e8118efb6de4f8c1a049dd3fe5..5d5cbe0130cdf99de1917d5c013b8894c622a727 100644 --- a/drivers/i2c/muxes/i2c-mux-gpio.c +++ b/drivers/i2c/muxes/i2c-mux-gpio.c @@ -225,14 +225,12 @@ static int i2c_mux_gpio_probe(struct platform_device *pdev) return ret; } -static int i2c_mux_gpio_remove(struct platform_device *pdev) +static void i2c_mux_gpio_remove(struct platform_device *pdev) { struct i2c_mux_core *muxc = platform_get_drvdata(pdev); i2c_mux_del_adapters(muxc); i2c_put_adapter(muxc->parent); - - return 0; } static const struct of_device_id i2c_mux_gpio_of_match[] = { @@ -243,7 +241,7 @@ MODULE_DEVICE_TABLE(of, i2c_mux_gpio_of_match); static struct platform_driver i2c_mux_gpio_driver = { .probe = i2c_mux_gpio_probe, - .remove = i2c_mux_gpio_remove, + .remove_new = i2c_mux_gpio_remove, .driver = { .name = "i2c-mux-gpio", .of_match_table = i2c_mux_gpio_of_match, diff --git a/drivers/i2c/muxes/i2c-mux-gpmux.c b/drivers/i2c/muxes/i2c-mux-gpmux.c index 33024acaac02b8083751eec245374b79649d0bd4..0405af0e15104993d0e186cbc98c097044ba9ff8 100644 --- a/drivers/i2c/muxes/i2c-mux-gpmux.c +++ b/drivers/i2c/muxes/i2c-mux-gpmux.c @@ -142,19 +142,17 @@ static int i2c_mux_probe(struct platform_device *pdev) return ret; } -static int i2c_mux_remove(struct platform_device *pdev) +static void i2c_mux_remove(struct platform_device *pdev) { struct i2c_mux_core *muxc = platform_get_drvdata(pdev); i2c_mux_del_adapters(muxc); i2c_put_adapter(muxc->parent); - - return 0; } static struct platform_driver i2c_mux_driver = { .probe = i2c_mux_probe, - .remove = i2c_mux_remove, + .remove_new = i2c_mux_remove, .driver = { .name = "i2c-mux-gpmux", .of_match_table = i2c_mux_of_match, diff --git a/drivers/i2c/muxes/i2c-mux-mlxcpld.c b/drivers/i2c/muxes/i2c-mux-mlxcpld.c index 1a879f6a31efdf5378600e4aba51ac19b7062ad1..3dda00f1df78da36e29a335d8da13181ea16df7c 100644 --- a/drivers/i2c/muxes/i2c-mux-mlxcpld.c +++ b/drivers/i2c/muxes/i2c-mux-mlxcpld.c @@ -170,12 +170,11 @@ static int mlxcpld_mux_probe(struct platform_device *pdev) return err; } -static int mlxcpld_mux_remove(struct platform_device *pdev) +static void mlxcpld_mux_remove(struct platform_device *pdev) { struct i2c_mux_core *muxc = platform_get_drvdata(pdev); i2c_mux_del_adapters(muxc); - return 0; } static struct platform_driver mlxcpld_mux_driver = { @@ -183,7 +182,7 @@ static struct platform_driver mlxcpld_mux_driver = { .name = "i2c-mux-mlxcpld", }, .probe = mlxcpld_mux_probe, - .remove = mlxcpld_mux_remove, + .remove_new = mlxcpld_mux_remove, }; module_platform_driver(mlxcpld_mux_driver); diff --git a/drivers/i2c/muxes/i2c-mux-pinctrl.c b/drivers/i2c/muxes/i2c-mux-pinctrl.c index d5ad904756fdf3c5005c66c7b3cffc5bcdc45edc..18236b9fa14a9558dfb08bf656da442090d4611f 100644 --- a/drivers/i2c/muxes/i2c-mux-pinctrl.c +++ b/drivers/i2c/muxes/i2c-mux-pinctrl.c @@ -166,14 +166,12 @@ static int i2c_mux_pinctrl_probe(struct platform_device *pdev) return ret; } -static int i2c_mux_pinctrl_remove(struct platform_device *pdev) +static void i2c_mux_pinctrl_remove(struct platform_device *pdev) { struct i2c_mux_core *muxc = platform_get_drvdata(pdev); i2c_mux_del_adapters(muxc); i2c_put_adapter(muxc->parent); - - return 0; } static const struct of_device_id i2c_mux_pinctrl_of_match[] = { @@ -188,7 +186,7 @@ static struct platform_driver i2c_mux_pinctrl_driver = { .of_match_table = i2c_mux_pinctrl_of_match, }, .probe = i2c_mux_pinctrl_probe, - .remove = i2c_mux_pinctrl_remove, + .remove_new = i2c_mux_pinctrl_remove, }; module_platform_driver(i2c_mux_pinctrl_driver); diff --git a/drivers/i2c/muxes/i2c-mux-reg.c b/drivers/i2c/muxes/i2c-mux-reg.c index 30a6de1694e0791ea6d70b75b4c35df2ff7cc0d0..9efc1ed01577b1987f3493c686bd8133eb31fcdb 100644 --- a/drivers/i2c/muxes/i2c-mux-reg.c +++ b/drivers/i2c/muxes/i2c-mux-reg.c @@ -233,14 +233,12 @@ static int i2c_mux_reg_probe(struct platform_device *pdev) return ret; } -static int i2c_mux_reg_remove(struct platform_device *pdev) +static void i2c_mux_reg_remove(struct platform_device *pdev) { struct i2c_mux_core *muxc = platform_get_drvdata(pdev); i2c_mux_del_adapters(muxc); i2c_put_adapter(muxc->parent); - - return 0; } static const struct of_device_id i2c_mux_reg_of_match[] = { @@ -251,7 +249,7 @@ MODULE_DEVICE_TABLE(of, i2c_mux_reg_of_match); static struct platform_driver i2c_mux_reg_driver = { .probe = i2c_mux_reg_probe, - .remove = i2c_mux_reg_remove, + .remove_new = i2c_mux_reg_remove, .driver = { .name = "i2c-mux-reg", .of_match_table = of_match_ptr(i2c_mux_reg_of_match), diff --git a/drivers/i3c/master/svc-i3c-master.c b/drivers/i3c/master/svc-i3c-master.c index e3f454123805e1efe68ccd05a8edb1e2b5c6f74f..0d63b732ef0c82d076164c15ff455bd8e0fdeb54 100644 --- a/drivers/i3c/master/svc-i3c-master.c +++ b/drivers/i3c/master/svc-i3c-master.c @@ -92,6 +92,7 @@ #define SVC_I3C_MINTCLR 0x094 #define SVC_I3C_MINTMASKED 0x098 #define SVC_I3C_MERRWARN 0x09C +#define SVC_I3C_MERRWARN_NACK BIT(2) #define SVC_I3C_MDMACTRL 0x0A0 #define SVC_I3C_MDATACTRL 0x0AC #define SVC_I3C_MDATACTRL_FLUSHTB BIT(0) @@ -145,6 +146,11 @@ struct svc_i3c_xfer { struct svc_i3c_cmd cmds[]; }; +struct svc_i3c_regs_save { + u32 mconfig; + u32 mdynaddr; +}; + /** * struct svc_i3c_master - Silvaco I3C Master structure * @base: I3C master controller @@ -173,6 +179,7 @@ struct svc_i3c_master { struct i3c_master_controller base; struct device *dev; void __iomem *regs; + struct svc_i3c_regs_save saved_regs; u32 free_slots; u8 addrs[SVC_I3C_MAX_DEVS]; struct i3c_dev_desc *descs[SVC_I3C_MAX_DEVS]; @@ -1008,6 +1015,11 @@ static int svc_i3c_master_xfer(struct svc_i3c_master *master, if (ret) goto emit_stop; + if (readl(master->regs + SVC_I3C_MERRWARN) & SVC_I3C_MERRWARN_NACK) { + ret = -ENXIO; + goto emit_stop; + } + if (rnw) ret = svc_i3c_master_read(master, in, xfer_len); else @@ -1090,12 +1102,6 @@ static void svc_i3c_master_start_xfer_locked(struct svc_i3c_master *master) if (!xfer) return; - ret = pm_runtime_resume_and_get(master->dev); - if (ret < 0) { - dev_err(master->dev, "<%s> Cannot get runtime PM.\n", __func__); - return; - } - svc_i3c_master_clear_merrwarn(master); svc_i3c_master_flush_fifo(master); @@ -1110,9 +1116,6 @@ static void svc_i3c_master_start_xfer_locked(struct svc_i3c_master *master) break; } - pm_runtime_mark_last_busy(master->dev); - pm_runtime_put_autosuspend(master->dev); - xfer->ret = ret; complete(&xfer->comp); @@ -1133,6 +1136,13 @@ static void svc_i3c_master_enqueue_xfer(struct svc_i3c_master *master, struct svc_i3c_xfer *xfer) { unsigned long flags; + int ret; + + ret = pm_runtime_resume_and_get(master->dev); + if (ret < 0) { + dev_err(master->dev, "<%s> Cannot get runtime PM.\n", __func__); + return; + } init_completion(&xfer->comp); spin_lock_irqsave(&master->xferqueue.lock, flags); @@ -1143,6 +1153,9 @@ static void svc_i3c_master_enqueue_xfer(struct svc_i3c_master *master, svc_i3c_master_start_xfer_locked(master); } spin_unlock_irqrestore(&master->xferqueue.lock, flags); + + pm_runtime_mark_last_busy(master->dev); + pm_runtime_put_autosuspend(master->dev); } static bool @@ -1579,10 +1592,28 @@ static void svc_i3c_master_remove(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); } +static void svc_i3c_save_regs(struct svc_i3c_master *master) +{ + master->saved_regs.mconfig = readl(master->regs + SVC_I3C_MCONFIG); + master->saved_regs.mdynaddr = readl(master->regs + SVC_I3C_MDYNADDR); +} + +static void svc_i3c_restore_regs(struct svc_i3c_master *master) +{ + if (readl(master->regs + SVC_I3C_MDYNADDR) != + master->saved_regs.mdynaddr) { + writel(master->saved_regs.mconfig, + master->regs + SVC_I3C_MCONFIG); + writel(master->saved_regs.mdynaddr, + master->regs + SVC_I3C_MDYNADDR); + } +} + static int __maybe_unused svc_i3c_runtime_suspend(struct device *dev) { struct svc_i3c_master *master = dev_get_drvdata(dev); + svc_i3c_save_regs(master); svc_i3c_master_unprepare_clks(master); pinctrl_pm_select_sleep_state(dev); @@ -1596,6 +1627,8 @@ static int __maybe_unused svc_i3c_runtime_resume(struct device *dev) pinctrl_pm_select_default_state(dev); svc_i3c_master_prepare_clks(master); + svc_i3c_restore_regs(master); + return 0; } diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c index aa2d19db2b1d93cdff3638421b07126d33012907..b930036edbbef6f7fc202c262873b0f85d3fede1 100644 --- a/drivers/idle/intel_idle.c +++ b/drivers/idle/intel_idle.c @@ -199,6 +199,43 @@ static __cpuidle int intel_idle_xstate(struct cpuidle_device *dev, return __intel_idle(dev, drv, index); } +static __always_inline int __intel_idle_hlt(struct cpuidle_device *dev, + struct cpuidle_driver *drv, int index) +{ + raw_safe_halt(); + raw_local_irq_disable(); + return index; +} + +/** + * intel_idle_hlt - Ask the processor to enter the given idle state using hlt. + * @dev: cpuidle device of the target CPU. + * @drv: cpuidle driver (assumed to point to intel_idle_driver). + * @index: Target idle state index. + * + * Use the HLT instruction to notify the processor that the CPU represented by + * @dev is idle and it can try to enter the idle state corresponding to @index. + * + * Must be called under local_irq_disable(). + */ +static __cpuidle int intel_idle_hlt(struct cpuidle_device *dev, + struct cpuidle_driver *drv, int index) +{ + return __intel_idle_hlt(dev, drv, index); +} + +static __cpuidle int intel_idle_hlt_irq_on(struct cpuidle_device *dev, + struct cpuidle_driver *drv, int index) +{ + int ret; + + raw_local_irq_enable(); + ret = __intel_idle_hlt(dev, drv, index); + raw_local_irq_disable(); + + return ret; +} + /** * intel_idle_s2idle - Ask the processor to enter the given idle state. * @dev: cpuidle device of the target CPU. @@ -1242,6 +1279,25 @@ static struct cpuidle_state snr_cstates[] __initdata = { .enter = NULL } }; +static struct cpuidle_state vmguest_cstates[] __initdata = { + { + .name = "C1", + .desc = "HLT", + .flags = MWAIT2flg(0x00) | CPUIDLE_FLAG_IRQ_ENABLE, + .exit_latency = 5, + .target_residency = 10, + .enter = &intel_idle_hlt, }, + { + .name = "C1L", + .desc = "Long HLT", + .flags = MWAIT2flg(0x00) | CPUIDLE_FLAG_TLB_FLUSHED, + .exit_latency = 5, + .target_residency = 200, + .enter = &intel_idle_hlt, }, + { + .enter = NULL } +}; + static const struct idle_cpu idle_cpu_nehalem __initconst = { .state_table = nehalem_cstates, .auto_demotion_disable_flags = NHM_C1_AUTO_DEMOTE | NHM_C3_AUTO_DEMOTE, @@ -1839,6 +1895,66 @@ static bool __init intel_idle_verify_cstate(unsigned int mwait_hint) return true; } +static void state_update_enter_method(struct cpuidle_state *state, int cstate) +{ + if (state->enter == intel_idle_hlt) { + if (force_irq_on) { + pr_info("forced intel_idle_irq for state %d\n", cstate); + state->enter = intel_idle_hlt_irq_on; + } + return; + } + if (state->enter == intel_idle_hlt_irq_on) + return; /* no update scenarios */ + + if (state->flags & CPUIDLE_FLAG_INIT_XSTATE) { + /* + * Combining with XSTATE with IBRS or IRQ_ENABLE flags + * is not currently supported but this driver. + */ + WARN_ON_ONCE(state->flags & CPUIDLE_FLAG_IBRS); + WARN_ON_ONCE(state->flags & CPUIDLE_FLAG_IRQ_ENABLE); + state->enter = intel_idle_xstate; + return; + } + + if (cpu_feature_enabled(X86_FEATURE_KERNEL_IBRS) && + state->flags & CPUIDLE_FLAG_IBRS) { + /* + * IBRS mitigation requires that C-states are entered + * with interrupts disabled. + */ + WARN_ON_ONCE(state->flags & CPUIDLE_FLAG_IRQ_ENABLE); + state->enter = intel_idle_ibrs; + return; + } + + if (state->flags & CPUIDLE_FLAG_IRQ_ENABLE) { + state->enter = intel_idle_irq; + return; + } + + if (force_irq_on) { + pr_info("forced intel_idle_irq for state %d\n", cstate); + state->enter = intel_idle_irq; + } +} + +/* + * For mwait based states, we want to verify the cpuid data to see if the state + * is actually supported by this specific CPU. + * For non-mwait based states, this check should be skipped. + */ +static bool should_verify_mwait(struct cpuidle_state *state) +{ + if (state->enter == intel_idle_hlt) + return false; + if (state->enter == intel_idle_hlt_irq_on) + return false; + + return true; +} + static void __init intel_idle_init_cstates_icpu(struct cpuidle_driver *drv) { int cstate; @@ -1887,35 +2003,15 @@ static void __init intel_idle_init_cstates_icpu(struct cpuidle_driver *drv) } mwait_hint = flg2MWAIT(cpuidle_state_table[cstate].flags); - if (!intel_idle_verify_cstate(mwait_hint)) + if (should_verify_mwait(&cpuidle_state_table[cstate]) && !intel_idle_verify_cstate(mwait_hint)) continue; /* Structure copy. */ drv->states[drv->state_count] = cpuidle_state_table[cstate]; state = &drv->states[drv->state_count]; - if (state->flags & CPUIDLE_FLAG_INIT_XSTATE) { - /* - * Combining with XSTATE with IBRS or IRQ_ENABLE flags - * is not currently supported but this driver. - */ - WARN_ON_ONCE(state->flags & CPUIDLE_FLAG_IBRS); - WARN_ON_ONCE(state->flags & CPUIDLE_FLAG_IRQ_ENABLE); - state->enter = intel_idle_xstate; - } else if (cpu_feature_enabled(X86_FEATURE_KERNEL_IBRS) && - state->flags & CPUIDLE_FLAG_IBRS) { - /* - * IBRS mitigation requires that C-states are entered - * with interrupts disabled. - */ - WARN_ON_ONCE(state->flags & CPUIDLE_FLAG_IRQ_ENABLE); - state->enter = intel_idle_ibrs; - } else if (state->flags & CPUIDLE_FLAG_IRQ_ENABLE) { - state->enter = intel_idle_irq; - } else if (force_irq_on) { - pr_info("forced intel_idle_irq for state %d\n", cstate); - state->enter = intel_idle_irq; - } + state_update_enter_method(state, cstate); + if ((disabled_states_mask & BIT(drv->state_count)) || ((icpu->use_acpi || force_use_acpi) && @@ -2041,6 +2137,93 @@ static void __init intel_idle_cpuidle_devices_uninit(void) cpuidle_unregister_device(per_cpu_ptr(intel_idle_cpuidle_devices, i)); } +/* + * Match up the latency and break even point of the bare metal (cpu based) + * states with the deepest VM available state. + * + * We only want to do this for the deepest state, the ones that has + * the TLB_FLUSHED flag set on the . + * + * All our short idle states are dominated by vmexit/vmenter latencies, + * not the underlying hardware latencies so we keep our values for these. + */ +static void __init matchup_vm_state_with_baremetal(void) +{ + int cstate; + + for (cstate = 0; cstate < CPUIDLE_STATE_MAX; ++cstate) { + int matching_cstate; + + if (intel_idle_max_cstate_reached(cstate)) + break; + + if (!cpuidle_state_table[cstate].enter) + break; + + if (!(cpuidle_state_table[cstate].flags & CPUIDLE_FLAG_TLB_FLUSHED)) + continue; + + for (matching_cstate = 0; matching_cstate < CPUIDLE_STATE_MAX; ++matching_cstate) { + if (!icpu->state_table[matching_cstate].enter) + break; + if (icpu->state_table[matching_cstate].exit_latency > cpuidle_state_table[cstate].exit_latency) { + cpuidle_state_table[cstate].exit_latency = icpu->state_table[matching_cstate].exit_latency; + cpuidle_state_table[cstate].target_residency = icpu->state_table[matching_cstate].target_residency; + } + } + + } +} + + +static int __init intel_idle_vminit(const struct x86_cpu_id *id) +{ + int retval; + + cpuidle_state_table = vmguest_cstates; + + icpu = (const struct idle_cpu *)id->driver_data; + + pr_debug("v" INTEL_IDLE_VERSION " model 0x%X\n", + boot_cpu_data.x86_model); + + intel_idle_cpuidle_devices = alloc_percpu(struct cpuidle_device); + if (!intel_idle_cpuidle_devices) + return -ENOMEM; + + /* + * We don't know exactly what the host will do when we go idle, but as a worst estimate + * we can assume that the exit latency of the deepest host state will be hit for our + * deep (long duration) guest idle state. + * The same logic applies to the break even point for the long duration guest idle state. + * So lets copy these two properties from the table we found for the host CPU type. + */ + matchup_vm_state_with_baremetal(); + + intel_idle_cpuidle_driver_init(&intel_idle_driver); + + retval = cpuidle_register_driver(&intel_idle_driver); + if (retval) { + struct cpuidle_driver *drv = cpuidle_get_driver(); + printk(KERN_DEBUG pr_fmt("intel_idle yielding to %s\n"), + drv ? drv->name : "none"); + goto init_driver_fail; + } + + retval = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "idle/intel:online", + intel_idle_cpu_online, NULL); + if (retval < 0) + goto hp_setup_fail; + + return 0; +hp_setup_fail: + intel_idle_cpuidle_devices_uninit(); + cpuidle_unregister_driver(&intel_idle_driver); +init_driver_fail: + free_percpu(intel_idle_cpuidle_devices); + return retval; +} + static int __init intel_idle_init(void) { const struct x86_cpu_id *id; @@ -2059,6 +2242,8 @@ static int __init intel_idle_init(void) id = x86_match_cpu(intel_idle_ids); if (id) { if (!boot_cpu_has(X86_FEATURE_MWAIT)) { + if (boot_cpu_has(X86_FEATURE_HYPERVISOR)) + return intel_idle_vminit(id); pr_debug("Please enable MWAIT in BIOS SETUP\n"); return -ENODEV; } diff --git a/drivers/iio/accel/adxl313_i2c.c b/drivers/iio/accel/adxl313_i2c.c index 99cc7fc294882bcb4426756d9279372625b490e8..524327ea3663159da417b1a9381930e81843e8b2 100644 --- a/drivers/iio/accel/adxl313_i2c.c +++ b/drivers/iio/accel/adxl313_i2c.c @@ -85,7 +85,7 @@ static struct i2c_driver adxl313_i2c_driver = { .name = "adxl313_i2c", .of_match_table = adxl313_of_match, }, - .probe_new = adxl313_i2c_probe, + .probe = adxl313_i2c_probe, .id_table = adxl313_i2c_id, }; diff --git a/drivers/iio/accel/adxl345_i2c.c b/drivers/iio/accel/adxl345_i2c.c index 098cd83f95b219463f581ce71827abac74fddaa7..e47d12f19602c28b8076a0e75f10d6ea6a51563f 100644 --- a/drivers/iio/accel/adxl345_i2c.c +++ b/drivers/iio/accel/adxl345_i2c.c @@ -56,7 +56,7 @@ static struct i2c_driver adxl345_i2c_driver = { .of_match_table = adxl345_of_match, .acpi_match_table = adxl345_acpi_match, }, - .probe_new = adxl345_i2c_probe, + .probe = adxl345_i2c_probe, .id_table = adxl345_i2c_id, }; module_i2c_driver(adxl345_i2c_driver); diff --git a/drivers/iio/accel/adxl355_i2c.c b/drivers/iio/accel/adxl355_i2c.c index 6cde5ccac06b8597366032731f5424db5b0106ce..d5beea61479d9b0cb2e1f12daac54a3315c17878 100644 --- a/drivers/iio/accel/adxl355_i2c.c +++ b/drivers/iio/accel/adxl355_i2c.c @@ -68,7 +68,7 @@ static struct i2c_driver adxl355_i2c_driver = { .name = "adxl355_i2c", .of_match_table = adxl355_of_match, }, - .probe_new = adxl355_i2c_probe, + .probe = adxl355_i2c_probe, .id_table = adxl355_i2c_id, }; module_i2c_driver(adxl355_i2c_driver); diff --git a/drivers/iio/accel/adxl367_i2c.c b/drivers/iio/accel/adxl367_i2c.c index 070aad724abd41ea25a665efc3e48fc3b2891e62..b595fe94f3a321b2d8fc986d64d29dbc4f024ccc 100644 --- a/drivers/iio/accel/adxl367_i2c.c +++ b/drivers/iio/accel/adxl367_i2c.c @@ -77,7 +77,7 @@ static struct i2c_driver adxl367_i2c_driver = { .name = "adxl367_i2c", .of_match_table = adxl367_of_match, }, - .probe_new = adxl367_i2c_probe, + .probe = adxl367_i2c_probe, .id_table = adxl367_i2c_id, }; diff --git a/drivers/iio/accel/adxl372_i2c.c b/drivers/iio/accel/adxl372_i2c.c index e5f310ea65fff3565eae9caa90364b2521983515..d0690417fd36f2cd037b5c62acfd17bdb320a20e 100644 --- a/drivers/iio/accel/adxl372_i2c.c +++ b/drivers/iio/accel/adxl372_i2c.c @@ -58,7 +58,7 @@ static struct i2c_driver adxl372_i2c_driver = { .name = "adxl372_i2c", .of_match_table = adxl372_of_match, }, - .probe_new = adxl372_i2c_probe, + .probe = adxl372_i2c_probe, .id_table = adxl372_i2c_id, }; diff --git a/drivers/iio/accel/bma180.c b/drivers/iio/accel/bma180.c index eb697eeb4301ba8dba1ddd48d09c0364483c7371..e8ab0d249351da35903b6c0fd2ba9a6507046369 100644 --- a/drivers/iio/accel/bma180.c +++ b/drivers/iio/accel/bma180.c @@ -1134,7 +1134,7 @@ static struct i2c_driver bma180_driver = { .pm = pm_sleep_ptr(&bma180_pm_ops), .of_match_table = bma180_of_match, }, - .probe_new = bma180_probe, + .probe = bma180_probe, .remove = bma180_remove, .id_table = bma180_ids, }; diff --git a/drivers/iio/accel/bma400_core.c b/drivers/iio/accel/bma400_core.c index a68b845f5b4f25dfe2a733260b681891bd86200c..e90e2f01550ad375b5b0e781982b3ecbf595dce8 100644 --- a/drivers/iio/accel/bma400_core.c +++ b/drivers/iio/accel/bma400_core.c @@ -868,8 +868,7 @@ static int bma400_init(struct bma400_data *data) ARRAY_SIZE(regulator_names), regulator_names); if (ret) - return dev_err_probe(data->dev, ret, "Failed to get regulators: %d\n", - ret); + return dev_err_probe(data->dev, ret, "Failed to get regulators\n"); /* Try to read chip_id register. It must return 0x90. */ ret = regmap_read(data->regmap, BMA400_CHIP_ID_REG, &val); diff --git a/drivers/iio/accel/bma400_i2c.c b/drivers/iio/accel/bma400_i2c.c index 688b06dae669b1ab12f18f84467f0629f3acf7dc..adf4e3fd2e1dff5a2055b36b8600519c2a5d7988 100644 --- a/drivers/iio/accel/bma400_i2c.c +++ b/drivers/iio/accel/bma400_i2c.c @@ -44,7 +44,7 @@ static struct i2c_driver bma400_i2c_driver = { .name = "bma400", .of_match_table = bma400_of_i2c_match, }, - .probe_new = bma400_i2c_probe, + .probe = bma400_i2c_probe, .id_table = bma400_i2c_ids, }; diff --git a/drivers/iio/accel/bmc150-accel-i2c.c b/drivers/iio/accel/bmc150-accel-i2c.c index 509cab2bd6947249ca95d30ec2c00529fe75c6a2..ee1ba134ad4237269ea39411563580ca2d1163c5 100644 --- a/drivers/iio/accel/bmc150-accel-i2c.c +++ b/drivers/iio/accel/bmc150-accel-i2c.c @@ -269,7 +269,7 @@ static struct i2c_driver bmc150_accel_driver = { .acpi_match_table = ACPI_PTR(bmc150_accel_acpi_match), .pm = &bmc150_accel_pm_ops, }, - .probe_new = bmc150_accel_probe, + .probe = bmc150_accel_probe, .remove = bmc150_accel_remove, .id_table = bmc150_accel_id, }; diff --git a/drivers/iio/accel/da280.c b/drivers/iio/accel/da280.c index 38a7d811610e786496ee9d704a6d3efa3c1c619a..2f27a5ded94ceb8358b2e1f3c79b7e7280861091 100644 --- a/drivers/iio/accel/da280.c +++ b/drivers/iio/accel/da280.c @@ -184,7 +184,7 @@ static struct i2c_driver da280_driver = { .acpi_match_table = ACPI_PTR(da280_acpi_match), .pm = pm_sleep_ptr(&da280_pm_ops), }, - .probe_new = da280_probe, + .probe = da280_probe, .id_table = da280_i2c_id, }; diff --git a/drivers/iio/accel/da311.c b/drivers/iio/accel/da311.c index 080335fa2ad655ccc339b226a3cd4d94afa8f55e..8f919920ced5d825be71d58cd55a2c2fee00ff43 100644 --- a/drivers/iio/accel/da311.c +++ b/drivers/iio/accel/da311.c @@ -278,7 +278,7 @@ static struct i2c_driver da311_driver = { .name = "da311", .pm = pm_sleep_ptr(&da311_pm_ops), }, - .probe_new = da311_probe, + .probe = da311_probe, .id_table = da311_i2c_id, }; diff --git a/drivers/iio/accel/dmard06.c b/drivers/iio/accel/dmard06.c index 7390509aaac0531308c9a917902df13b0498ef3b..2e719d60fff8a89ef461f3119c25dd79544b08bd 100644 --- a/drivers/iio/accel/dmard06.c +++ b/drivers/iio/accel/dmard06.c @@ -217,7 +217,7 @@ static const struct of_device_id dmard06_of_match[] = { MODULE_DEVICE_TABLE(of, dmard06_of_match); static struct i2c_driver dmard06_driver = { - .probe_new = dmard06_probe, + .probe = dmard06_probe, .id_table = dmard06_id, .driver = { .name = DMARD06_DRV_NAME, diff --git a/drivers/iio/accel/dmard09.c b/drivers/iio/accel/dmard09.c index 4b7a537f617d51f69387ae21fbdf4ee90fd9fe1f..fa98623de579b946c570473a19f2b405d3609285 100644 --- a/drivers/iio/accel/dmard09.c +++ b/drivers/iio/accel/dmard09.c @@ -135,7 +135,7 @@ static struct i2c_driver dmard09_driver = { .driver = { .name = DMARD09_DRV_NAME }, - .probe_new = dmard09_probe, + .probe = dmard09_probe, .id_table = dmard09_id, }; diff --git a/drivers/iio/accel/dmard10.c b/drivers/iio/accel/dmard10.c index 07e68aed8a13c7cb2a360743e6f71bdde7f41baa..7745b6ffd1ad567fe5c3ffa50d25d34eec322b1e 100644 --- a/drivers/iio/accel/dmard10.c +++ b/drivers/iio/accel/dmard10.c @@ -241,7 +241,7 @@ static struct i2c_driver dmard10_driver = { .name = "dmard10", .pm = pm_sleep_ptr(&dmard10_pm_ops), }, - .probe_new = dmard10_probe, + .probe = dmard10_probe, .id_table = dmard10_i2c_id, }; diff --git a/drivers/iio/accel/fxls8962af-core.c b/drivers/iio/accel/fxls8962af-core.c index 0d672b1469e8d1798bfe739f81394432a2ad1ef2..be8a15cb945fdf9c007eac135347e2af3c7b7b09 100644 --- a/drivers/iio/accel/fxls8962af-core.c +++ b/drivers/iio/accel/fxls8962af-core.c @@ -724,8 +724,7 @@ static const struct iio_event_spec fxls8962af_event[] = { .sign = 's', \ .realbits = 12, \ .storagebits = 16, \ - .shift = 4, \ - .endianness = IIO_BE, \ + .endianness = IIO_LE, \ }, \ .event_spec = fxls8962af_event, \ .num_event_specs = ARRAY_SIZE(fxls8962af_event), \ @@ -904,9 +903,10 @@ static int fxls8962af_fifo_transfer(struct fxls8962af_data *data, int total_length = samples * sample_length; int ret; - if (i2c_verify_client(dev)) + if (i2c_verify_client(dev) && + data->chip_info->chip_id == FXLS8962AF_DEVICE_ID) /* - * Due to errata bug: + * Due to errata bug (only applicable on fxls8962af): * E3: FIFO burst read operation error using I2C interface * We have to avoid burst reads on I2C.. */ diff --git a/drivers/iio/accel/fxls8962af-i2c.c b/drivers/iio/accel/fxls8962af-i2c.c index 22640eaebac739ad53fac7f98151d44227a775f5..160124673308307f11303ac484118be8a07f86b4 100644 --- a/drivers/iio/accel/fxls8962af-i2c.c +++ b/drivers/iio/accel/fxls8962af-i2c.c @@ -47,7 +47,7 @@ static struct i2c_driver fxls8962af_driver = { .of_match_table = fxls8962af_of_match, .pm = pm_ptr(&fxls8962af_pm_ops), }, - .probe_new = fxls8962af_probe, + .probe = fxls8962af_probe, .id_table = fxls8962af_id, }; module_i2c_driver(fxls8962af_driver); diff --git a/drivers/iio/accel/kionix-kx022a-i2c.c b/drivers/iio/accel/kionix-kx022a-i2c.c index e6fd02d931b60f3b3a6aa6c1fee56f9ae055a7cb..b0ac78e85dada1d1daeaa345cc7e5ddc5ebb4d11 100644 --- a/drivers/iio/accel/kionix-kx022a-i2c.c +++ b/drivers/iio/accel/kionix-kx022a-i2c.c @@ -40,8 +40,9 @@ static struct i2c_driver kx022a_i2c_driver = { .driver = { .name = "kx022a-i2c", .of_match_table = kx022a_of_match, + .probe_type = PROBE_PREFER_ASYNCHRONOUS, }, - .probe_new = kx022a_i2c_probe, + .probe = kx022a_i2c_probe, }; module_i2c_driver(kx022a_i2c_driver); diff --git a/drivers/iio/accel/kionix-kx022a-spi.c b/drivers/iio/accel/kionix-kx022a-spi.c index 9cd047f7b34678a6e754232e86501688d30b31d9..f45a46899a5f63d4d6a9021190d7a2b6091db3ec 100644 --- a/drivers/iio/accel/kionix-kx022a-spi.c +++ b/drivers/iio/accel/kionix-kx022a-spi.c @@ -46,6 +46,7 @@ static struct spi_driver kx022a_spi_driver = { .driver = { .name = "kx022a-spi", .of_match_table = kx022a_of_match, + .probe_type = PROBE_PREFER_ASYNCHRONOUS, }, .probe = kx022a_spi_probe, .id_table = kx022a_id, diff --git a/drivers/iio/accel/kionix-kx022a.c b/drivers/iio/accel/kionix-kx022a.c index b8636fa8eaeb68d740300d75e06365f9e887dd25..4ea3c6718ed49dec8d0119b7d6cf5e66e63a05ab 100644 --- a/drivers/iio/accel/kionix-kx022a.c +++ b/drivers/iio/accel/kionix-kx022a.c @@ -516,17 +516,6 @@ static int kx022a_read_raw(struct iio_dev *idev, return -EINVAL; }; -static int kx022a_validate_trigger(struct iio_dev *idev, - struct iio_trigger *trig) -{ - struct kx022a_data *data = iio_priv(idev); - - if (data->trig != trig) - return -EINVAL; - - return 0; -} - static int kx022a_set_watermark(struct iio_dev *idev, unsigned int val) { struct kx022a_data *data = iio_priv(idev); @@ -725,7 +714,7 @@ static const struct iio_info kx022a_info = { .write_raw = &kx022a_write_raw, .read_avail = &kx022a_read_avail, - .validate_trigger = kx022a_validate_trigger, + .validate_trigger = iio_validate_own_trigger, .hwfifo_set_watermark = kx022a_set_watermark, .hwfifo_flush_to_buffer = kx022a_fifo_flush, }; diff --git a/drivers/iio/accel/kxcjk-1013.c b/drivers/iio/accel/kxcjk-1013.c index 98da4bda22dfe0761d3d456147d354dd2b1921f8..894709286b0ccb22ff45cc0ac71729f28e06f487 100644 --- a/drivers/iio/accel/kxcjk-1013.c +++ b/drivers/iio/accel/kxcjk-1013.c @@ -1732,7 +1732,7 @@ static struct i2c_driver kxcjk1013_driver = { .of_match_table = kxcjk1013_of_match, .pm = &kxcjk1013_pm_ops, }, - .probe_new = kxcjk1013_probe, + .probe = kxcjk1013_probe, .remove = kxcjk1013_remove, .id_table = kxcjk1013_id, }; diff --git a/drivers/iio/accel/kxsd9-i2c.c b/drivers/iio/accel/kxsd9-i2c.c index 6b3683ddce36d92dd2d09cd03fd22b3e91949bfd..3bc9ee1f9db3a9cce65bcb5b30eb3735b717f2b1 100644 --- a/drivers/iio/accel/kxsd9-i2c.c +++ b/drivers/iio/accel/kxsd9-i2c.c @@ -54,7 +54,7 @@ static struct i2c_driver kxsd9_i2c_driver = { .of_match_table = kxsd9_of_match, .pm = pm_ptr(&kxsd9_dev_pm_ops), }, - .probe_new = kxsd9_i2c_probe, + .probe = kxsd9_i2c_probe, .remove = kxsd9_i2c_remove, .id_table = kxsd9_i2c_id, }; diff --git a/drivers/iio/accel/mc3230.c b/drivers/iio/accel/mc3230.c index efc21871de42b7852526151675825071311408f6..6b87c2c9945ca9e68d2e543bee739c0ce1a4eaf7 100644 --- a/drivers/iio/accel/mc3230.c +++ b/drivers/iio/accel/mc3230.c @@ -190,7 +190,7 @@ static struct i2c_driver mc3230_driver = { .name = "mc3230", .pm = pm_sleep_ptr(&mc3230_pm_ops), }, - .probe_new = mc3230_probe, + .probe = mc3230_probe, .remove = mc3230_remove, .id_table = mc3230_i2c_id, }; diff --git a/drivers/iio/accel/mma7455_i2c.c b/drivers/iio/accel/mma7455_i2c.c index a3864dbe27613c20686c664db94891d003b94fe1..14f7850a22f043dde2c47484aec55a24e2f7441d 100644 --- a/drivers/iio/accel/mma7455_i2c.c +++ b/drivers/iio/accel/mma7455_i2c.c @@ -46,7 +46,7 @@ static const struct of_device_id mma7455_of_match[] = { MODULE_DEVICE_TABLE(of, mma7455_of_match); static struct i2c_driver mma7455_i2c_driver = { - .probe_new = mma7455_i2c_probe, + .probe = mma7455_i2c_probe, .remove = mma7455_i2c_remove, .id_table = mma7455_i2c_ids, .driver = { diff --git a/drivers/iio/accel/mma7660.c b/drivers/iio/accel/mma7660.c index b279ca4dcdc05637d2e7d74ef608bfc805c25b95..260cbceaa15189a625ff119580ea11894473713a 100644 --- a/drivers/iio/accel/mma7660.c +++ b/drivers/iio/accel/mma7660.c @@ -266,7 +266,7 @@ static struct i2c_driver mma7660_driver = { .of_match_table = mma7660_of_match, .acpi_match_table = mma7660_acpi_id, }, - .probe_new = mma7660_probe, + .probe = mma7660_probe, .remove = mma7660_remove, .id_table = mma7660_i2c_id, }; diff --git a/drivers/iio/accel/mma8452.c b/drivers/iio/accel/mma8452.c index ea14e3aaa30a03c0f7150e56964fdd2e40030bc8..6e7399e722214cff270dc408080a818f9b302afb 100644 --- a/drivers/iio/accel/mma8452.c +++ b/drivers/iio/accel/mma8452.c @@ -1846,7 +1846,7 @@ static struct i2c_driver mma8452_driver = { .of_match_table = mma8452_dt_ids, .pm = &mma8452_pm_ops, }, - .probe_new = mma8452_probe, + .probe = mma8452_probe, .remove = mma8452_remove, .id_table = mma8452_id, }; diff --git a/drivers/iio/accel/mma9551.c b/drivers/iio/accel/mma9551.c index aa4f5842859ef863ea5769966b76642a76ef1402..d823f2edc6d425b6b775ea1f05fc65a27cccd387 100644 --- a/drivers/iio/accel/mma9551.c +++ b/drivers/iio/accel/mma9551.c @@ -607,7 +607,7 @@ static struct i2c_driver mma9551_driver = { .acpi_match_table = ACPI_PTR(mma9551_acpi_match), .pm = pm_ptr(&mma9551_pm_ops), }, - .probe_new = mma9551_probe, + .probe = mma9551_probe, .remove = mma9551_remove, .id_table = mma9551_id, }; diff --git a/drivers/iio/accel/mma9553.c b/drivers/iio/accel/mma9553.c index 0af578ef9d3d0e5e218beef8586c4b58dc417b29..d01aba4aecba5204507562f8b84c6fb88f7afb41 100644 --- a/drivers/iio/accel/mma9553.c +++ b/drivers/iio/accel/mma9553.c @@ -1246,7 +1246,7 @@ static struct i2c_driver mma9553_driver = { .acpi_match_table = ACPI_PTR(mma9553_acpi_match), .pm = pm_ptr(&mma9553_pm_ops), }, - .probe_new = mma9553_probe, + .probe = mma9553_probe, .remove = mma9553_remove, .id_table = mma9553_id, }; diff --git a/drivers/iio/accel/msa311.c b/drivers/iio/accel/msa311.c index 6690fa37da8fee5dbe90cbffc9b432fa89d3e161..6ddcc3c2f840915d7ed2fb447d3c1154874c1d69 100644 --- a/drivers/iio/accel/msa311.c +++ b/drivers/iio/accel/msa311.c @@ -1294,7 +1294,7 @@ static struct i2c_driver msa311_driver = { .of_match_table = msa311_of_match, .pm = pm_ptr(&msa311_pm_ops), }, - .probe_new = msa311_probe, + .probe = msa311_probe, .id_table = msa311_i2c_id, }; module_i2c_driver(msa311_driver); diff --git a/drivers/iio/accel/mxc4005.c b/drivers/iio/accel/mxc4005.c index b146fc82738f6734eb45d8a18b939574094eeb7c..75d142bc14b4f2180e4ef0b027f842e74fe2f071 100644 --- a/drivers/iio/accel/mxc4005.c +++ b/drivers/iio/accel/mxc4005.c @@ -488,7 +488,7 @@ static struct i2c_driver mxc4005_driver = { .name = MXC4005_DRV_NAME, .acpi_match_table = ACPI_PTR(mxc4005_acpi_match), }, - .probe_new = mxc4005_probe, + .probe = mxc4005_probe, .id_table = mxc4005_id, }; diff --git a/drivers/iio/accel/mxc6255.c b/drivers/iio/accel/mxc6255.c index aa2e660545f841bd8bae0a29c0a9e9dc8a4d8d73..33c2253561e6b2289465f87f517477b9121ca2dd 100644 --- a/drivers/iio/accel/mxc6255.c +++ b/drivers/iio/accel/mxc6255.c @@ -183,7 +183,7 @@ static struct i2c_driver mxc6255_driver = { .name = MXC6255_DRV_NAME, .acpi_match_table = ACPI_PTR(mxc6255_acpi_match), }, - .probe_new = mxc6255_probe, + .probe = mxc6255_probe, .id_table = mxc6255_id, }; diff --git a/drivers/iio/accel/st_accel_core.c b/drivers/iio/accel/st_accel_core.c index 282e539157f87cb223c2ad985d964b0cd5a7a0b3..d2104e14e2559d58616fe048a67c13703fac73f1 100644 --- a/drivers/iio/accel/st_accel_core.c +++ b/drivers/iio/accel/st_accel_core.c @@ -1007,6 +1007,7 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = { .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS, .sensors_supported = { [0] = LSM9DS0_IMU_DEV_NAME, + [1] = LSM303D_IMU_DEV_NAME, }, .ch = (struct iio_chan_spec *)st_accel_16bit_channels, .odr = { diff --git a/drivers/iio/accel/st_accel_i2c.c b/drivers/iio/accel/st_accel_i2c.c index fb9e2d6f421034a210b5de34c559e5f5fa955110..71ee861b29808e9a1768c5d5d48afc8245973bfb 100644 --- a/drivers/iio/accel/st_accel_i2c.c +++ b/drivers/iio/accel/st_accel_i2c.c @@ -206,7 +206,7 @@ static struct i2c_driver st_accel_driver = { .of_match_table = st_accel_of_match, .acpi_match_table = ACPI_PTR(st_accel_acpi_match), }, - .probe_new = st_accel_i2c_probe, + .probe = st_accel_i2c_probe, .id_table = st_accel_id_table, }; module_i2c_driver(st_accel_driver); diff --git a/drivers/iio/accel/stk8312.c b/drivers/iio/accel/stk8312.c index 68f680db750513cac3ae4677a84e9bf8650b76c6..ef0ae76722538aefafb8cff199a0e19b51e7be99 100644 --- a/drivers/iio/accel/stk8312.c +++ b/drivers/iio/accel/stk8312.c @@ -644,7 +644,7 @@ static struct i2c_driver stk8312_driver = { .name = STK8312_DRIVER_NAME, .pm = pm_sleep_ptr(&stk8312_pm_ops), }, - .probe_new = stk8312_probe, + .probe = stk8312_probe, .remove = stk8312_remove, .id_table = stk8312_i2c_id, }; diff --git a/drivers/iio/accel/stk8ba50.c b/drivers/iio/accel/stk8ba50.c index 44f6e0fbdfcc6441394185837dcbf9a64786f7c5..3415ac1b449535fbf796f40463604f696ad1f2f0 100644 --- a/drivers/iio/accel/stk8ba50.c +++ b/drivers/iio/accel/stk8ba50.c @@ -543,7 +543,7 @@ static struct i2c_driver stk8ba50_driver = { .pm = pm_sleep_ptr(&stk8ba50_pm_ops), .acpi_match_table = ACPI_PTR(stk8ba50_acpi_id), }, - .probe_new = stk8ba50_probe, + .probe = stk8ba50_probe, .remove = stk8ba50_remove, .id_table = stk8ba50_i2c_id, }; diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index eb2b09ef5d5b7944fd47f2d54444f9b3867bc915..dc14bde31ac11676aaee68fce7b909e6aa01675d 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -145,7 +145,7 @@ config AD7606 config AD7606_IFACE_PARALLEL tristate "Analog Devices AD7606 ADC driver with parallel interface support" - depends on HAS_IOMEM + depends on HAS_IOPORT select AD7606 help Say yes here to build parallel interface support for Analog Devices: @@ -735,6 +735,17 @@ config MAX1363 To compile this driver as a module, choose M here: the module will be called max1363. +config MAX77541_ADC + tristate "Analog Devices MAX77541 ADC driver" + depends on MFD_MAX77541 + help + This driver controls a Analog Devices MAX77541 ADC + via I2C bus. This device has one adc. Say yes here to build + support for Analog Devices MAX77541 ADC interface. + + To compile this driver as a module, choose M here: + the module will be called max77541-adc. + config MAX9611 tristate "Maxim max9611/max9612 ADC driver" depends on I2C diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile index e07e4a3e62377f7dc9f01f9806fd9a187a964bf5..eb6e891790fbe9b52b05586abc8a59e778446606 100644 --- a/drivers/iio/adc/Makefile +++ b/drivers/iio/adc/Makefile @@ -67,6 +67,7 @@ obj-$(CONFIG_MAX11205) += max11205.o obj-$(CONFIG_MAX11410) += max11410.o obj-$(CONFIG_MAX1241) += max1241.o obj-$(CONFIG_MAX1363) += max1363.o +obj-$(CONFIG_MAX77541_ADC) += max77541-adc.o obj-$(CONFIG_MAX9611) += max9611.o obj-$(CONFIG_MCP320X) += mcp320x.o obj-$(CONFIG_MCP3422) += mcp3422.o diff --git a/drivers/iio/adc/ad7091r5.c b/drivers/iio/adc/ad7091r5.c index 7d6709da1005fe2cbc6021318e79bc769af1f417..2f048527b7b786728f2099209a17497d97d9a233 100644 --- a/drivers/iio/adc/ad7091r5.c +++ b/drivers/iio/adc/ad7091r5.c @@ -103,7 +103,7 @@ static struct i2c_driver ad7091r5_driver = { .name = "ad7091r5", .of_match_table = ad7091r5_dt_ids, }, - .probe_new = ad7091r5_i2c_probe, + .probe = ad7091r5_i2c_probe, .id_table = ad7091r5_i2c_ids, }; module_i2c_driver(ad7091r5_driver); diff --git a/drivers/iio/adc/ad7192.c b/drivers/iio/adc/ad7192.c index 99bb604b78c8cf904271b1832bde8a91a1c13bc3..8685e0b58a83854ce64c6fe6b38b82c519064223 100644 --- a/drivers/iio/adc/ad7192.c +++ b/drivers/iio/adc/ad7192.c @@ -367,7 +367,7 @@ static int ad7192_of_clock_select(struct ad7192_state *st) clock_sel = AD7192_CLK_INT; /* use internal clock */ - if (st->mclk) { + if (!st->mclk) { if (of_property_read_bool(np, "adi,int-clock-output-enable")) clock_sel = AD7192_CLK_INT_CO; } else { @@ -380,9 +380,9 @@ static int ad7192_of_clock_select(struct ad7192_state *st) return clock_sel; } -static int ad7192_setup(struct ad7192_state *st, struct device_node *np) +static int ad7192_setup(struct iio_dev *indio_dev, struct device_node *np) { - struct iio_dev *indio_dev = spi_get_drvdata(st->sd.spi); + struct ad7192_state *st = iio_priv(indio_dev); bool rej60_en, refin2_en; bool buf_en, bipolar, burnout_curr_en; unsigned long long scale_uv; @@ -1069,7 +1069,7 @@ static int ad7192_probe(struct spi_device *spi) } } - ret = ad7192_setup(st, spi->dev.of_node); + ret = ad7192_setup(indio_dev, spi->dev.of_node); if (ret) return ret; diff --git a/drivers/iio/adc/ad7291.c b/drivers/iio/adc/ad7291.c index f9ee189925dec0a90c9ee576cc72172e3eb0974c..14d02b085d3bc81d2f846be30b58412d02bbaa06 100644 --- a/drivers/iio/adc/ad7291.c +++ b/drivers/iio/adc/ad7291.c @@ -553,7 +553,7 @@ static struct i2c_driver ad7291_driver = { .name = KBUILD_MODNAME, .of_match_table = ad7291_of_match, }, - .probe_new = ad7291_probe, + .probe = ad7291_probe, .id_table = ad7291_id, }; module_i2c_driver(ad7291_driver); diff --git a/drivers/iio/adc/ad799x.c b/drivers/iio/adc/ad799x.c index 8f0a3a35e727e84934855c783e4a1d22e6f0c98f..b757cc45c4decf8420a85a4615b6f2e2465ceef1 100644 --- a/drivers/iio/adc/ad799x.c +++ b/drivers/iio/adc/ad799x.c @@ -968,7 +968,7 @@ static struct i2c_driver ad799x_driver = { .name = "ad799x", .pm = pm_sleep_ptr(&ad799x_pm_ops), }, - .probe_new = ad799x_probe, + .probe = ad799x_probe, .remove = ad799x_remove, .id_table = ad799x_id, }; diff --git a/drivers/iio/adc/ina2xx-adc.c b/drivers/iio/adc/ina2xx-adc.c index 38d9d7b2313ea1932b9897f75e23192f937eed08..213526c1592f1c1f3f168b2a68fc4f9b0e86cd2f 100644 --- a/drivers/iio/adc/ina2xx-adc.c +++ b/drivers/iio/adc/ina2xx-adc.c @@ -1090,7 +1090,7 @@ static struct i2c_driver ina2xx_driver = { .name = KBUILD_MODNAME, .of_match_table = ina2xx_of_match, }, - .probe_new = ina2xx_probe, + .probe = ina2xx_probe, .remove = ina2xx_remove, .id_table = ina2xx_id, }; diff --git a/drivers/iio/adc/ltc2471.c b/drivers/iio/adc/ltc2471.c index eeb2945829eb27207d436198fa817df761480893..97c417c3a4eb066cc8181df7b6ff916f10a7c541 100644 --- a/drivers/iio/adc/ltc2471.c +++ b/drivers/iio/adc/ltc2471.c @@ -146,7 +146,7 @@ static struct i2c_driver ltc2471_i2c_driver = { .driver = { .name = "ltc2471", }, - .probe_new = ltc2471_i2c_probe, + .probe = ltc2471_i2c_probe, .id_table = ltc2471_i2c_id, }; diff --git a/drivers/iio/adc/ltc2485.c b/drivers/iio/adc/ltc2485.c index 6a23427344ecd176515ccbd65125138271ecc073..859e4314cfa2d4714ac13175e0d468a60d45ddad 100644 --- a/drivers/iio/adc/ltc2485.c +++ b/drivers/iio/adc/ltc2485.c @@ -133,7 +133,7 @@ static struct i2c_driver ltc2485_driver = { .driver = { .name = "ltc2485", }, - .probe_new = ltc2485_probe, + .probe = ltc2485_probe, .id_table = ltc2485_id, }; module_i2c_driver(ltc2485_driver); diff --git a/drivers/iio/adc/ltc2497.c b/drivers/iio/adc/ltc2497.c index ec198c6f13d6bc9a1aaafedb590ff64feca4aa75..5bdd4072961158370798f2febc957215489abd78 100644 --- a/drivers/iio/adc/ltc2497.c +++ b/drivers/iio/adc/ltc2497.c @@ -163,7 +163,7 @@ static struct i2c_driver ltc2497_driver = { .name = "ltc2497", .of_match_table = ltc2497_of_match, }, - .probe_new = ltc2497_probe, + .probe = ltc2497_probe, .remove = ltc2497_remove, .id_table = ltc2497_id, }; diff --git a/drivers/iio/adc/max1363.c b/drivers/iio/adc/max1363.c index 73b783b430d72def9217f61b1cad9d40128b917f..b31581616ce34ea9af3a44a6284d052cb8bb8a88 100644 --- a/drivers/iio/adc/max1363.c +++ b/drivers/iio/adc/max1363.c @@ -1718,7 +1718,7 @@ static struct i2c_driver max1363_driver = { .name = "max1363", .of_match_table = max1363_of_match, }, - .probe_new = max1363_probe, + .probe = max1363_probe, .id_table = max1363_id, }; module_i2c_driver(max1363_driver); diff --git a/drivers/iio/adc/max77541-adc.c b/drivers/iio/adc/max77541-adc.c new file mode 100644 index 0000000000000000000000000000000000000000..21d024bde16ba00332ee7ae77f87425f169dec20 --- /dev/null +++ b/drivers/iio/adc/max77541-adc.c @@ -0,0 +1,194 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2022 Analog Devices, Inc. + * ADI MAX77541 ADC Driver with IIO interface + */ + +#include +#include +#include +#include +#include +#include + +#include + +enum max77541_adc_range { + LOW_RANGE, + MID_RANGE, + HIGH_RANGE, +}; + +enum max77541_adc_channel { + MAX77541_ADC_VSYS_V, + MAX77541_ADC_VOUT1_V, + MAX77541_ADC_VOUT2_V, + MAX77541_ADC_TEMP, +}; + +static int max77541_adc_offset(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2) +{ + switch (chan->channel) { + case MAX77541_ADC_TEMP: + *val = DIV_ROUND_CLOSEST(ABSOLUTE_ZERO_MILLICELSIUS, 1725); + return IIO_VAL_INT; + default: + return -EINVAL; + } +} + +static int max77541_adc_scale(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2) +{ + struct regmap **regmap = iio_priv(indio_dev); + unsigned int reg_val; + int ret; + + switch (chan->channel) { + case MAX77541_ADC_VSYS_V: + *val = 25; + return IIO_VAL_INT; + case MAX77541_ADC_VOUT1_V: + case MAX77541_ADC_VOUT2_V: + ret = regmap_read(*regmap, MAX77541_REG_M2_CFG1, ®_val); + if (ret) + return ret; + + reg_val = FIELD_GET(MAX77541_BITS_MX_CFG1_RNG, reg_val); + switch (reg_val) { + case LOW_RANGE: + *val = 6; + *val2 = 250000; + break; + case MID_RANGE: + *val = 12; + *val2 = 500000; + break; + case HIGH_RANGE: + *val = 25; + return IIO_VAL_INT; + default: + return -EINVAL; + } + + return IIO_VAL_INT_PLUS_MICRO; + case MAX77541_ADC_TEMP: + *val = 1725; + return IIO_VAL_INT; + default: + return -EINVAL; + } +} + +static int max77541_adc_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val) +{ + struct regmap **regmap = iio_priv(indio_dev); + int ret; + + ret = regmap_read(*regmap, chan->address, val); + if (ret) + return ret; + + return IIO_VAL_INT; +} + +#define MAX77541_ADC_CHANNEL_V(_channel, _name, _type, _reg) \ + { \ + .type = _type, \ + .indexed = 1, \ + .channel = _channel, \ + .address = _reg, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ + BIT(IIO_CHAN_INFO_SCALE), \ + .datasheet_name = _name, \ + } + +#define MAX77541_ADC_CHANNEL_TEMP(_channel, _name, _type, _reg) \ + { \ + .type = _type, \ + .indexed = 1, \ + .channel = _channel, \ + .address = _reg, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ + BIT(IIO_CHAN_INFO_SCALE) |\ + BIT(IIO_CHAN_INFO_OFFSET),\ + .datasheet_name = _name, \ + } + +static const struct iio_chan_spec max77541_adc_channels[] = { + MAX77541_ADC_CHANNEL_V(MAX77541_ADC_VSYS_V, "vsys_v", IIO_VOLTAGE, + MAX77541_REG_ADC_DATA_CH1), + MAX77541_ADC_CHANNEL_V(MAX77541_ADC_VOUT1_V, "vout1_v", IIO_VOLTAGE, + MAX77541_REG_ADC_DATA_CH2), + MAX77541_ADC_CHANNEL_V(MAX77541_ADC_VOUT2_V, "vout2_v", IIO_VOLTAGE, + MAX77541_REG_ADC_DATA_CH3), + MAX77541_ADC_CHANNEL_TEMP(MAX77541_ADC_TEMP, "temp", IIO_TEMP, + MAX77541_REG_ADC_DATA_CH6), +}; + +static int max77541_adc_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + switch (mask) { + case IIO_CHAN_INFO_OFFSET: + return max77541_adc_offset(indio_dev, chan, val, val2); + case IIO_CHAN_INFO_SCALE: + return max77541_adc_scale(indio_dev, chan, val, val2); + case IIO_CHAN_INFO_RAW: + return max77541_adc_raw(indio_dev, chan, val); + default: + return -EINVAL; + } +} + +static const struct iio_info max77541_adc_info = { + .read_raw = max77541_adc_read_raw, +}; + +static int max77541_adc_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct iio_dev *indio_dev; + struct regmap **regmap; + + indio_dev = devm_iio_device_alloc(dev, sizeof(*regmap)); + if (!indio_dev) + return -ENOMEM; + + regmap = iio_priv(indio_dev); + + *regmap = dev_get_regmap(dev->parent, NULL); + indio_dev->modes = INDIO_DIRECT_MODE; + + indio_dev->name = "max77541"; + indio_dev->info = &max77541_adc_info; + indio_dev->channels = max77541_adc_channels; + indio_dev->num_channels = ARRAY_SIZE(max77541_adc_channels); + + return devm_iio_device_register(dev, indio_dev); +} + +static const struct platform_device_id max77541_adc_platform_id[] = { + { "max77541-adc" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(platform, max77541_adc_platform_id); + +static struct platform_driver max77541_adc_driver = { + .driver = { + .name = "max77541-adc", + }, + .probe = max77541_adc_probe, + .id_table = max77541_adc_platform_id, +}; +module_platform_driver(max77541_adc_driver); + +MODULE_AUTHOR("Okan Sahin "); +MODULE_DESCRIPTION("MAX77541 ADC driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/iio/adc/max9611.c b/drivers/iio/adc/max9611.c index cb7f4785423a2f2da8d6778b1c36fb7a7496bee1..76e517b7b1e4f3375ad570838e825f91839103d2 100644 --- a/drivers/iio/adc/max9611.c +++ b/drivers/iio/adc/max9611.c @@ -556,7 +556,7 @@ static struct i2c_driver max9611_driver = { .name = DRIVER_NAME, .of_match_table = max9611_of_table, }, - .probe_new = max9611_probe, + .probe = max9611_probe, }; module_i2c_driver(max9611_driver); diff --git a/drivers/iio/adc/mcp3422.c b/drivers/iio/adc/mcp3422.c index ada844c3f7eccd2c243e86c223f1fc0f65239e08..0778a8fb68665c3e47d8a41fccc057e84c35599a 100644 --- a/drivers/iio/adc/mcp3422.c +++ b/drivers/iio/adc/mcp3422.c @@ -417,7 +417,7 @@ static struct i2c_driver mcp3422_driver = { .name = "mcp3422", .of_match_table = mcp3422_of_match, }, - .probe_new = mcp3422_probe, + .probe = mcp3422_probe, .id_table = mcp3422_id, }; module_i2c_driver(mcp3422_driver); diff --git a/drivers/iio/adc/meson_saradc.c b/drivers/iio/adc/meson_saradc.c index 18937a262af6f8b2ae04180e479033bc84ede006..af6bfcc190752e9b674a5294004dcd6a35b51dd0 100644 --- a/drivers/iio/adc/meson_saradc.c +++ b/drivers/iio/adc/meson_saradc.c @@ -72,7 +72,7 @@ #define MESON_SAR_ADC_REG3_PANEL_DETECT_COUNT_MASK GENMASK(20, 18) #define MESON_SAR_ADC_REG3_PANEL_DETECT_FILTER_TB_MASK GENMASK(17, 16) #define MESON_SAR_ADC_REG3_ADC_CLK_DIV_SHIFT 10 - #define MESON_SAR_ADC_REG3_ADC_CLK_DIV_WIDTH 5 + #define MESON_SAR_ADC_REG3_ADC_CLK_DIV_WIDTH 6 #define MESON_SAR_ADC_REG3_BLOCK_DLY_SEL_MASK GENMASK(9, 8) #define MESON_SAR_ADC_REG3_BLOCK_DLY_MASK GENMASK(7, 0) diff --git a/drivers/iio/adc/nau7802.c b/drivers/iio/adc/nau7802.c index c1261ecd400c4167120c39ffa24260af28729e00..d9e1696df7ae453630e276aec39265563ccceb84 100644 --- a/drivers/iio/adc/nau7802.c +++ b/drivers/iio/adc/nau7802.c @@ -544,7 +544,7 @@ static const struct of_device_id nau7802_dt_ids[] = { MODULE_DEVICE_TABLE(of, nau7802_dt_ids); static struct i2c_driver nau7802_driver = { - .probe_new = nau7802_probe, + .probe = nau7802_probe, .id_table = nau7802_i2c_id, .driver = { .name = "nau7802", diff --git a/drivers/iio/adc/palmas_gpadc.c b/drivers/iio/adc/palmas_gpadc.c index 7dfc9c927a23f121e6ea08ddb0b06a15601d4aa3..27b2632c103766a0bf4f2aa38541cadf8377f11c 100644 --- a/drivers/iio/adc/palmas_gpadc.c +++ b/drivers/iio/adc/palmas_gpadc.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/iio/adc/qcom-spmi-adc5.c b/drivers/iio/adc/qcom-spmi-adc5.c index c2d5e06f137a7e64f66a112b9cc47c5de2e6d309..0a4fd3a461138be882426e869dee17d4e31fb21f 100644 --- a/drivers/iio/adc/qcom-spmi-adc5.c +++ b/drivers/iio/adc/qcom-spmi-adc5.c @@ -114,7 +114,7 @@ enum adc5_cal_val { * that is an average of multiple measurements. * @scale_fn_type: Represents the scaling function to convert voltage * physical units desired by the client for the channel. - * @datasheet_name: Channel name used in device tree. + * @channel_name: Channel name used in device tree. */ struct adc5_channel_prop { unsigned int channel; @@ -126,7 +126,7 @@ struct adc5_channel_prop { unsigned int hw_settle_time; unsigned int avg_samples; enum vadc_scale_fn_type scale_fn_type; - const char *datasheet_name; + const char *channel_name; }; /** @@ -657,8 +657,7 @@ static int adc5_get_fw_channel_data(struct adc5_chip *adc, chan = chan & ADC_CHANNEL_MASK; } - if (chan > ADC5_PARALLEL_ISENSE_VBAT_IDATA || - !data->adc_chans[chan].datasheet_name) { + if (chan > ADC5_PARALLEL_ISENSE_VBAT_IDATA) { dev_err(dev, "%s invalid channel number %d\n", name, chan); return -EINVAL; } @@ -669,9 +668,9 @@ static int adc5_get_fw_channel_data(struct adc5_chip *adc, ret = fwnode_property_read_string(fwnode, "label", &channel_name); if (ret) - channel_name = name; + channel_name = data->adc_chans[chan].datasheet_name; - prop->datasheet_name = channel_name; + prop->channel_name = channel_name; ret = fwnode_property_read_u32(fwnode, "qcom,decimation", &value); if (!ret) { @@ -861,8 +860,8 @@ static int adc5_get_fw_data(struct adc5_chip *adc) adc_chan = &adc->data->adc_chans[prop.channel]; iio_chan->channel = prop.channel; - iio_chan->datasheet_name = prop.datasheet_name; - iio_chan->extend_name = prop.datasheet_name; + iio_chan->datasheet_name = adc_chan->datasheet_name; + iio_chan->extend_name = prop.channel_name; iio_chan->info_mask_separate = adc_chan->info_mask; iio_chan->type = adc_chan->type; iio_chan->address = index; diff --git a/drivers/iio/adc/qcom-spmi-vadc.c b/drivers/iio/adc/qcom-spmi-vadc.c index bcff0f62b70e05b388dd4b097f55366bbe7092dd..f5c6f1f27b2c7de16326c0465f6c3c7899abb746 100644 --- a/drivers/iio/adc/qcom-spmi-vadc.c +++ b/drivers/iio/adc/qcom-spmi-vadc.c @@ -84,6 +84,7 @@ * that is an average of multiple measurements. * @scale_fn_type: Represents the scaling function to convert voltage * physical units desired by the client for the channel. + * @channel_name: Channel name used in device tree. */ struct vadc_channel_prop { unsigned int channel; @@ -93,6 +94,7 @@ struct vadc_channel_prop { unsigned int hw_settle_time; unsigned int avg_samples; enum vadc_scale_fn_type scale_fn_type; + const char *channel_name; }; /** @@ -495,8 +497,18 @@ static int vadc_fwnode_xlate(struct iio_dev *indio_dev, return -EINVAL; } +static int vadc_read_label(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, char *label) +{ + struct vadc_priv *vadc = iio_priv(indio_dev); + const char *name = vadc->chan_props[chan->address].channel_name; + + return sysfs_emit(label, "%s\n", name); +} + static const struct iio_info vadc_info = { .read_raw = vadc_read_raw, + .read_label = vadc_read_label, .fwnode_xlate = vadc_fwnode_xlate, }; @@ -652,7 +664,7 @@ static int vadc_get_fw_channel_data(struct device *dev, struct vadc_channel_prop *prop, struct fwnode_handle *fwnode) { - const char *name = fwnode_get_name(fwnode); + const char *name = fwnode_get_name(fwnode), *label; u32 chan, value, varr[2]; int ret; @@ -667,6 +679,11 @@ static int vadc_get_fw_channel_data(struct device *dev, return -EINVAL; } + ret = fwnode_property_read_string(fwnode, "label", &label); + if (ret) + label = vadc_chans[chan].datasheet_name; + prop->channel_name = label; + /* the channel has DT description */ prop->channel = chan; diff --git a/drivers/iio/adc/rockchip_saradc.c b/drivers/iio/adc/rockchip_saradc.c index 79448c5ffc2ae2d4306026dd879e978a4f709214..4b011f7eddec3a61abb92bce55ffc50457db1d04 100644 --- a/drivers/iio/adc/rockchip_saradc.c +++ b/drivers/iio/adc/rockchip_saradc.c @@ -4,6 +4,7 @@ * Copyright (C) 2014 ROCKCHIP, Inc. */ +#include #include #include #include @@ -38,10 +39,31 @@ #define SARADC_TIMEOUT msecs_to_jiffies(100) #define SARADC_MAX_CHANNELS 8 +/* v2 registers */ +#define SARADC2_CONV_CON 0x000 +#define SARADC_T_PD_SOC 0x004 +#define SARADC_T_DAS_SOC 0x00c +#define SARADC2_END_INT_EN 0x104 +#define SARADC2_ST_CON 0x108 +#define SARADC2_STATUS 0x10c +#define SARADC2_END_INT_ST 0x110 +#define SARADC2_DATA_BASE 0x120 + +#define SARADC2_EN_END_INT BIT(0) +#define SARADC2_START BIT(4) +#define SARADC2_SINGLE_MODE BIT(5) + +#define SARADC2_CONV_CHANNELS GENMASK(15, 0) + +struct rockchip_saradc; + struct rockchip_saradc_data { const struct iio_chan_spec *channels; int num_channels; unsigned long clk_rate; + void (*start)(struct rockchip_saradc *info, int chn); + int (*read)(struct rockchip_saradc *info); + void (*power_down)(struct rockchip_saradc *info); }; struct rockchip_saradc { @@ -60,27 +82,81 @@ struct rockchip_saradc { struct notifier_block nb; }; -static void rockchip_saradc_power_down(struct rockchip_saradc *info) +static void rockchip_saradc_reset_controller(struct reset_control *reset); + +static void rockchip_saradc_start_v1(struct rockchip_saradc *info, int chn) +{ + /* 8 clock periods as delay between power up and start cmd */ + writel_relaxed(8, info->regs + SARADC_DLY_PU_SOC); + /* Select the channel to be used and trigger conversion */ + writel(SARADC_CTRL_POWER_CTRL | (chn & SARADC_CTRL_CHN_MASK) | + SARADC_CTRL_IRQ_ENABLE, info->regs + SARADC_CTRL); +} + +static void rockchip_saradc_start_v2(struct rockchip_saradc *info, int chn) +{ + int val; + + if (info->reset) + rockchip_saradc_reset_controller(info->reset); + + writel_relaxed(0xc, info->regs + SARADC_T_DAS_SOC); + writel_relaxed(0x20, info->regs + SARADC_T_PD_SOC); + val = FIELD_PREP(SARADC2_EN_END_INT, 1); + val |= val << 16; + writel_relaxed(val, info->regs + SARADC2_END_INT_EN); + val = FIELD_PREP(SARADC2_START, 1) | + FIELD_PREP(SARADC2_SINGLE_MODE, 1) | + FIELD_PREP(SARADC2_CONV_CHANNELS, chn); + val |= val << 16; + writel(val, info->regs + SARADC2_CONV_CON); +} + +static void rockchip_saradc_start(struct rockchip_saradc *info, int chn) +{ + info->data->start(info, chn); +} + +static int rockchip_saradc_read_v1(struct rockchip_saradc *info) +{ + return readl_relaxed(info->regs + SARADC_DATA); +} + +static int rockchip_saradc_read_v2(struct rockchip_saradc *info) +{ + int offset; + + /* Clear irq */ + writel_relaxed(0x1, info->regs + SARADC2_END_INT_ST); + + offset = SARADC2_DATA_BASE + info->last_chan->channel * 0x4; + + return readl_relaxed(info->regs + offset); +} + +static int rockchip_saradc_read(struct rockchip_saradc *info) +{ + return info->data->read(info); +} + +static void rockchip_saradc_power_down_v1(struct rockchip_saradc *info) { - /* Clear irq & power down adc */ writel_relaxed(0, info->regs + SARADC_CTRL); } +static void rockchip_saradc_power_down(struct rockchip_saradc *info) +{ + if (info->data->power_down) + info->data->power_down(info); +} + static int rockchip_saradc_conversion(struct rockchip_saradc *info, - struct iio_chan_spec const *chan) + struct iio_chan_spec const *chan) { reinit_completion(&info->completion); - /* 8 clock periods as delay between power up and start cmd */ - writel_relaxed(8, info->regs + SARADC_DLY_PU_SOC); - info->last_chan = chan; - - /* Select the channel to be used and trigger conversion */ - writel(SARADC_CTRL_POWER_CTRL - | (chan->channel & SARADC_CTRL_CHN_MASK) - | SARADC_CTRL_IRQ_ENABLE, - info->regs + SARADC_CTRL); + rockchip_saradc_start(info, chan->channel); if (!wait_for_completion_timeout(&info->completion, SARADC_TIMEOUT)) return -ETIMEDOUT; @@ -123,7 +199,7 @@ static irqreturn_t rockchip_saradc_isr(int irq, void *dev_id) struct rockchip_saradc *info = dev_id; /* Read value */ - info->last_val = readl_relaxed(info->regs + SARADC_DATA); + info->last_val = rockchip_saradc_read(info); info->last_val &= GENMASK(info->last_chan->scan_type.realbits - 1, 0); rockchip_saradc_power_down(info); @@ -163,6 +239,9 @@ static const struct rockchip_saradc_data saradc_data = { .channels = rockchip_saradc_iio_channels, .num_channels = ARRAY_SIZE(rockchip_saradc_iio_channels), .clk_rate = 1000000, + .start = rockchip_saradc_start_v1, + .read = rockchip_saradc_read_v1, + .power_down = rockchip_saradc_power_down_v1, }; static const struct iio_chan_spec rockchip_rk3066_tsadc_iio_channels[] = { @@ -174,6 +253,9 @@ static const struct rockchip_saradc_data rk3066_tsadc_data = { .channels = rockchip_rk3066_tsadc_iio_channels, .num_channels = ARRAY_SIZE(rockchip_rk3066_tsadc_iio_channels), .clk_rate = 50000, + .start = rockchip_saradc_start_v1, + .read = rockchip_saradc_read_v1, + .power_down = rockchip_saradc_power_down_v1, }; static const struct iio_chan_spec rockchip_rk3399_saradc_iio_channels[] = { @@ -189,6 +271,9 @@ static const struct rockchip_saradc_data rk3399_saradc_data = { .channels = rockchip_rk3399_saradc_iio_channels, .num_channels = ARRAY_SIZE(rockchip_rk3399_saradc_iio_channels), .clk_rate = 1000000, + .start = rockchip_saradc_start_v1, + .read = rockchip_saradc_read_v1, + .power_down = rockchip_saradc_power_down_v1, }; static const struct iio_chan_spec rockchip_rk3568_saradc_iio_channels[] = { @@ -206,6 +291,28 @@ static const struct rockchip_saradc_data rk3568_saradc_data = { .channels = rockchip_rk3568_saradc_iio_channels, .num_channels = ARRAY_SIZE(rockchip_rk3568_saradc_iio_channels), .clk_rate = 1000000, + .start = rockchip_saradc_start_v1, + .read = rockchip_saradc_read_v1, + .power_down = rockchip_saradc_power_down_v1, +}; + +static const struct iio_chan_spec rockchip_rk3588_saradc_iio_channels[] = { + SARADC_CHANNEL(0, "adc0", 12), + SARADC_CHANNEL(1, "adc1", 12), + SARADC_CHANNEL(2, "adc2", 12), + SARADC_CHANNEL(3, "adc3", 12), + SARADC_CHANNEL(4, "adc4", 12), + SARADC_CHANNEL(5, "adc5", 12), + SARADC_CHANNEL(6, "adc6", 12), + SARADC_CHANNEL(7, "adc7", 12), +}; + +static const struct rockchip_saradc_data rk3588_saradc_data = { + .channels = rockchip_rk3588_saradc_iio_channels, + .num_channels = ARRAY_SIZE(rockchip_rk3588_saradc_iio_channels), + .clk_rate = 1000000, + .start = rockchip_saradc_start_v2, + .read = rockchip_saradc_read_v2, }; static const struct of_device_id rockchip_saradc_match[] = { @@ -221,6 +328,9 @@ static const struct of_device_id rockchip_saradc_match[] = { }, { .compatible = "rockchip,rk3568-saradc", .data = &rk3568_saradc_data, + }, { + .compatible = "rockchip,rk3588-saradc", + .data = &rk3588_saradc_data, }, {}, }; @@ -236,20 +346,6 @@ static void rockchip_saradc_reset_controller(struct reset_control *reset) reset_control_deassert(reset); } -static void rockchip_saradc_clk_disable(void *data) -{ - struct rockchip_saradc *info = data; - - clk_disable_unprepare(info->clk); -} - -static void rockchip_saradc_pclk_disable(void *data) -{ - struct rockchip_saradc *info = data; - - clk_disable_unprepare(info->pclk); -} - static void rockchip_saradc_regulator_disable(void *data) { struct rockchip_saradc *info = data; @@ -298,8 +394,7 @@ static irqreturn_t rockchip_saradc_trigger_handler(int irq, void *p) } static int rockchip_saradc_volt_notify(struct notifier_block *nb, - unsigned long event, - void *data) + unsigned long event, void *data) { struct rockchip_saradc *info = container_of(nb, struct rockchip_saradc, nb); @@ -319,10 +414,10 @@ static void rockchip_saradc_regulator_unreg_notifier(void *data) static int rockchip_saradc_probe(struct platform_device *pdev) { + const struct rockchip_saradc_data *match_data; struct rockchip_saradc *info = NULL; struct device_node *np = pdev->dev.of_node; struct iio_dev *indio_dev = NULL; - const struct of_device_id *match; int ret; int irq; @@ -330,25 +425,23 @@ static int rockchip_saradc_probe(struct platform_device *pdev) return -ENODEV; indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*info)); - if (!indio_dev) { - dev_err(&pdev->dev, "failed allocating iio device\n"); - return -ENOMEM; - } + if (!indio_dev) + return dev_err_probe(&pdev->dev, -ENOMEM, + "failed allocating iio device\n"); + info = iio_priv(indio_dev); - match = of_match_device(rockchip_saradc_match, &pdev->dev); - if (!match) { - dev_err(&pdev->dev, "failed to match device\n"); - return -ENODEV; - } + match_data = of_device_get_match_data(&pdev->dev); + if (!match_data) + return dev_err_probe(&pdev->dev, -ENODEV, + "failed to match device\n"); - info->data = match->data; + info->data = match_data; /* Sanity check for possible later IP variants with more channels */ - if (info->data->num_channels > SARADC_MAX_CHANNELS) { - dev_err(&pdev->dev, "max channels exceeded"); - return -EINVAL; - } + if (info->data->num_channels > SARADC_MAX_CHANNELS) + return dev_err_probe(&pdev->dev, -EINVAL, + "max channels exceeded"); info->regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(info->regs)) @@ -383,16 +476,6 @@ static int rockchip_saradc_probe(struct platform_device *pdev) return ret; } - info->pclk = devm_clk_get(&pdev->dev, "apb_pclk"); - if (IS_ERR(info->pclk)) - return dev_err_probe(&pdev->dev, PTR_ERR(info->pclk), - "failed to get pclk\n"); - - info->clk = devm_clk_get(&pdev->dev, "saradc"); - if (IS_ERR(info->clk)) - return dev_err_probe(&pdev->dev, PTR_ERR(info->clk), - "failed to get adc clock\n"); - info->vref = devm_regulator_get(&pdev->dev, "vref"); if (IS_ERR(info->vref)) return dev_err_probe(&pdev->dev, PTR_ERR(info->vref), @@ -406,23 +489,20 @@ static int rockchip_saradc_probe(struct platform_device *pdev) * This may become user-configurable in the future. */ ret = clk_set_rate(info->clk, info->data->clk_rate); - if (ret < 0) { - dev_err(&pdev->dev, "failed to set adc clk rate, %d\n", ret); - return ret; - } + if (ret < 0) + return dev_err_probe(&pdev->dev, ret, + "failed to set adc clk rate\n"); ret = regulator_enable(info->vref); - if (ret < 0) { - dev_err(&pdev->dev, "failed to enable vref regulator\n"); - return ret; - } + if (ret < 0) + return dev_err_probe(&pdev->dev, ret, + "failed to enable vref regulator\n"); + ret = devm_add_action_or_reset(&pdev->dev, rockchip_saradc_regulator_disable, info); - if (ret) { - dev_err(&pdev->dev, "failed to register devm action, %d\n", - ret); - return ret; - } + if (ret) + return dev_err_probe(&pdev->dev, ret, + "failed to register devm action\n"); ret = regulator_get_voltage(info->vref); if (ret < 0) @@ -430,31 +510,15 @@ static int rockchip_saradc_probe(struct platform_device *pdev) info->uv_vref = ret; - ret = clk_prepare_enable(info->pclk); - if (ret < 0) { - dev_err(&pdev->dev, "failed to enable pclk\n"); - return ret; - } - ret = devm_add_action_or_reset(&pdev->dev, - rockchip_saradc_pclk_disable, info); - if (ret) { - dev_err(&pdev->dev, "failed to register devm action, %d\n", - ret); - return ret; - } + info->pclk = devm_clk_get_enabled(&pdev->dev, "apb_pclk"); + if (IS_ERR(info->pclk)) + return dev_err_probe(&pdev->dev, PTR_ERR(info->pclk), + "failed to get pclk\n"); - ret = clk_prepare_enable(info->clk); - if (ret < 0) { - dev_err(&pdev->dev, "failed to enable converter clock\n"); - return ret; - } - ret = devm_add_action_or_reset(&pdev->dev, - rockchip_saradc_clk_disable, info); - if (ret) { - dev_err(&pdev->dev, "failed to register devm action, %d\n", - ret); - return ret; - } + info->clk = devm_clk_get_enabled(&pdev->dev, "saradc"); + if (IS_ERR(info->clk)) + return dev_err_probe(&pdev->dev, PTR_ERR(info->clk), + "failed to get adc clock\n"); platform_set_drvdata(pdev, indio_dev); diff --git a/drivers/iio/adc/rtq6056.c b/drivers/iio/adc/rtq6056.c index c1b2e8dc9a26687c20ca565abe6a7e6600a1a5f3..ad4cea6839b271de330829e5bdfc1c3d86db7e6f 100644 --- a/drivers/iio/adc/rtq6056.c +++ b/drivers/iio/adc/rtq6056.c @@ -652,7 +652,7 @@ static struct i2c_driver rtq6056_driver = { .of_match_table = rtq6056_device_match, .pm = pm_ptr(&rtq6056_pm_ops), }, - .probe_new = rtq6056_probe, + .probe = rtq6056_probe, }; module_i2c_driver(rtq6056_driver); diff --git a/drivers/iio/adc/stm32-adc.c b/drivers/iio/adc/stm32-adc.c index bd7e2408bf281da5a90e40472cf7a2da3703f2bd..f7613efb870d58796b0c06e994e7ef79e1349f6f 100644 --- a/drivers/iio/adc/stm32-adc.c +++ b/drivers/iio/adc/stm32-adc.c @@ -1993,6 +1993,8 @@ static int stm32_adc_get_legacy_chan_count(struct iio_dev *indio_dev, struct stm const struct stm32_adc_info *adc_info = adc->cfg->adc_info; int num_channels = 0, ret; + dev_dbg(&indio_dev->dev, "using legacy channel config\n"); + ret = device_property_count_u32(dev, "st,adc-channels"); if (ret > adc_info->max_channels) { dev_err(&indio_dev->dev, "Bad st,adc-channels?\n"); diff --git a/drivers/iio/adc/ti-adc081c.c b/drivers/iio/adc/ti-adc081c.c index c663dc59d45901b2c5cd55cf172b00c6ce6e0619..50c450e7a55fd1f0f5b1f0568674c245eefc99fc 100644 --- a/drivers/iio/adc/ti-adc081c.c +++ b/drivers/iio/adc/ti-adc081c.c @@ -235,7 +235,7 @@ static struct i2c_driver adc081c_driver = { .of_match_table = adc081c_of_match, .acpi_match_table = adc081c_acpi_match, }, - .probe_new = adc081c_probe, + .probe = adc081c_probe, .id_table = adc081c_id, }; module_i2c_driver(adc081c_driver); diff --git a/drivers/iio/adc/ti-ads1015.c b/drivers/iio/adc/ti-ads1015.c index 56af5e148802252c785cf1c626a3e570a467016d..075c75a875449e7c47b149f8a820c9fd4d2df973 100644 --- a/drivers/iio/adc/ti-ads1015.c +++ b/drivers/iio/adc/ti-ads1015.c @@ -1195,7 +1195,7 @@ static struct i2c_driver ads1015_driver = { .of_match_table = ads1015_of_match, .pm = &ads1015_pm_ops, }, - .probe_new = ads1015_probe, + .probe = ads1015_probe, .remove = ads1015_remove, .id_table = ads1015_id, }; diff --git a/drivers/iio/adc/ti-ads1100.c b/drivers/iio/adc/ti-ads1100.c index 6b5aebb82455143765dec5725aacc00557f09428..1e46f07a9ca6a805ea65d51e636caa30bb59e3b1 100644 --- a/drivers/iio/adc/ti-ads1100.c +++ b/drivers/iio/adc/ti-ads1100.c @@ -434,7 +434,7 @@ static struct i2c_driver ads1100_driver = { .of_match_table = ads1100_of_match, .pm = pm_ptr(&ads1100_pm_ops), }, - .probe_new = ads1100_probe, + .probe = ads1100_probe, .id_table = ads1100_id, }; diff --git a/drivers/iio/adc/ti-ads7924.c b/drivers/iio/adc/ti-ads7924.c index b02abb0269662d15e2dad83022cbf5b525280f20..afdbd04778a87ebb2e7421f32c32ccacf8753c0d 100644 --- a/drivers/iio/adc/ti-ads7924.c +++ b/drivers/iio/adc/ti-ads7924.c @@ -463,7 +463,7 @@ static struct i2c_driver ads7924_driver = { .name = "ads7924", .of_match_table = ads7924_of_match, }, - .probe_new = ads7924_probe, + .probe = ads7924_probe, .id_table = ads7924_id, }; diff --git a/drivers/iio/adc/xilinx-ams.c b/drivers/iio/adc/xilinx-ams.c index 34cf336b34902a334a4acf4f30b51e7513e787ec..f0b71a1220e02e5cc6ffcb4f3120b9b0090dc22f 100644 --- a/drivers/iio/adc/xilinx-ams.c +++ b/drivers/iio/adc/xilinx-ams.c @@ -1263,7 +1263,7 @@ static int ams_parse_firmware(struct iio_dev *indio_dev) struct device *dev = indio_dev->dev.parent; struct fwnode_handle *child = NULL; struct fwnode_handle *fwnode = dev_fwnode(dev); - size_t ams_size, dev_size; + size_t ams_size; int ret, ch_cnt = 0, i, rising_off, falling_off; unsigned int num_channels = 0; @@ -1320,11 +1320,8 @@ static int ams_parse_firmware(struct iio_dev *indio_dev) } } - dev_size = array_size(sizeof(*dev_channels), num_channels); - if (dev_size == SIZE_MAX) - return -ENOMEM; - - dev_channels = devm_krealloc(dev, ams_channels, dev_size, GFP_KERNEL); + dev_channels = devm_krealloc_array(dev, ams_channels, num_channels, + sizeof(*dev_channels), GFP_KERNEL); if (!dev_channels) return -ENOMEM; diff --git a/drivers/iio/adc/xilinx-xadc-core.c b/drivers/iio/adc/xilinx-xadc-core.c index 292f2892d223a0573d86ecad75e969deae06cb37..dba73300f89482ba5dc285ddc93c29ab353feff3 100644 --- a/drivers/iio/adc/xilinx-xadc-core.c +++ b/drivers/iio/adc/xilinx-xadc-core.c @@ -613,20 +613,17 @@ static int xadc_update_scan_mode(struct iio_dev *indio_dev, const unsigned long *mask) { struct xadc *xadc = iio_priv(indio_dev); - size_t new_size, n; + size_t n; void *data; n = bitmap_weight(mask, indio_dev->masklength); - if (check_mul_overflow(n, sizeof(*xadc->data), &new_size)) - return -ENOMEM; - - data = devm_krealloc(indio_dev->dev.parent, xadc->data, - new_size, GFP_KERNEL); + data = devm_krealloc_array(indio_dev->dev.parent, xadc->data, + n, sizeof(*xadc->data), GFP_KERNEL); if (!data) return -ENOMEM; - memset(data, 0, new_size); + memset(data, 0, n * sizeof(*xadc->data)); xadc->data = data; return 0; @@ -1281,9 +1278,9 @@ static int xadc_parse_dt(struct iio_dev *indio_dev, unsigned int *conf, int irq) } indio_dev->num_channels = num_channels; - indio_dev->channels = devm_krealloc(dev, channels, - sizeof(*channels) * num_channels, - GFP_KERNEL); + indio_dev->channels = devm_krealloc_array(dev, channels, + num_channels, sizeof(*channels), + GFP_KERNEL); /* If we can't resize the channels array, just use the original */ if (!indio_dev->channels) indio_dev->channels = channels; diff --git a/drivers/iio/addac/ad74413r.c b/drivers/iio/addac/ad74413r.c index e3366cf5eb31943c006e059eda6fc26558073431..6b0e8218f1507ed2688484f33178d2df69648333 100644 --- a/drivers/iio/addac/ad74413r.c +++ b/drivers/iio/addac/ad74413r.c @@ -1317,13 +1317,14 @@ static int ad74413r_setup_gpios(struct ad74413r_state *st) } if (config->func == CH_FUNC_DIGITAL_INPUT_LOGIC || - config->func == CH_FUNC_DIGITAL_INPUT_LOOP_POWER) + config->func == CH_FUNC_DIGITAL_INPUT_LOOP_POWER) { st->comp_gpio_offsets[comp_gpio_i++] = i; - strength = config->drive_strength; - ret = ad74413r_set_comp_drive_strength(st, i, strength); - if (ret) - return ret; + strength = config->drive_strength; + ret = ad74413r_set_comp_drive_strength(st, i, strength); + if (ret) + return ret; + } ret = ad74413r_set_gpo_config(st, i, gpo_config); if (ret) diff --git a/drivers/iio/amplifiers/ad8366.c b/drivers/iio/amplifiers/ad8366.c index f2c2ea79a07f3defd1e0b607631e06d4531d6207..8d8c8ea94258fa0e543947e9b86a29e529b948ce 100644 --- a/drivers/iio/amplifiers/ad8366.c +++ b/drivers/iio/amplifiers/ad8366.c @@ -281,7 +281,7 @@ static int ad8366_probe(struct spi_device *spi) indio_dev->info = &ad8366_info; indio_dev->modes = INDIO_DIRECT_MODE; - ret = ad8366_write(indio_dev, 0 , 0); + ret = ad8366_write(indio_dev, 0, 0); if (ret < 0) goto error_disable_reg; diff --git a/drivers/iio/cdc/ad7150.c b/drivers/iio/cdc/ad7150.c index 79aeb0aaea67d05e529755d2c29585d8ed8e392f..d656d2f1275540aae44b5da9c0004b5fa5e9a780 100644 --- a/drivers/iio/cdc/ad7150.c +++ b/drivers/iio/cdc/ad7150.c @@ -647,7 +647,7 @@ static struct i2c_driver ad7150_driver = { .name = "ad7150", .of_match_table = ad7150_of_match, }, - .probe_new = ad7150_probe, + .probe = ad7150_probe, .id_table = ad7150_id, }; module_i2c_driver(ad7150_driver); diff --git a/drivers/iio/cdc/ad7746.c b/drivers/iio/cdc/ad7746.c index a1db5469f2d1e81d786d7f28264dfa6851655829..d11bc3496dda29bbe46974f3207be2e6ade6717d 100644 --- a/drivers/iio/cdc/ad7746.c +++ b/drivers/iio/cdc/ad7746.c @@ -809,7 +809,7 @@ static struct i2c_driver ad7746_driver = { .name = KBUILD_MODNAME, .of_match_table = ad7746_of_match, }, - .probe_new = ad7746_probe, + .probe = ad7746_probe, .id_table = ad7746_id, }; module_i2c_driver(ad7746_driver); diff --git a/drivers/iio/chemical/ams-iaq-core.c b/drivers/iio/chemical/ams-iaq-core.c index 0a0fbcdd446922142627448c0aa2e21d3da7cc06..164facac5db615536c154214f63cdaf9d958dcff 100644 --- a/drivers/iio/chemical/ams-iaq-core.c +++ b/drivers/iio/chemical/ams-iaq-core.c @@ -179,7 +179,7 @@ static struct i2c_driver ams_iaqcore_driver = { .name = "ams-iaq-core", .of_match_table = ams_iaqcore_dt_ids, }, - .probe_new = ams_iaqcore_probe, + .probe = ams_iaqcore_probe, .id_table = ams_iaqcore_id, }; module_i2c_driver(ams_iaqcore_driver); diff --git a/drivers/iio/chemical/atlas-ezo-sensor.c b/drivers/iio/chemical/atlas-ezo-sensor.c index 307c3488f4bdddaa78a460d7bcdf4614c9a95651..8fc926a2d33bbece6e967895d478c7ce0b569d2d 100644 --- a/drivers/iio/chemical/atlas-ezo-sensor.c +++ b/drivers/iio/chemical/atlas-ezo-sensor.c @@ -238,7 +238,7 @@ static struct i2c_driver atlas_ezo_driver = { .name = ATLAS_EZO_DRV_NAME, .of_match_table = atlas_ezo_dt_ids, }, - .probe_new = atlas_ezo_probe, + .probe = atlas_ezo_probe, .id_table = atlas_ezo_id, }; module_i2c_driver(atlas_ezo_driver); diff --git a/drivers/iio/chemical/atlas-sensor.c b/drivers/iio/chemical/atlas-sensor.c index 024657bc59e171e36673b484655fa2131e7ae649..fb15bb216019389d7887596f0212d9d4b90f222b 100644 --- a/drivers/iio/chemical/atlas-sensor.c +++ b/drivers/iio/chemical/atlas-sensor.c @@ -767,7 +767,7 @@ static struct i2c_driver atlas_driver = { .of_match_table = atlas_dt_ids, .pm = pm_ptr(&atlas_pm_ops), }, - .probe_new = atlas_probe, + .probe = atlas_probe, .remove = atlas_remove, .id_table = atlas_id, }; diff --git a/drivers/iio/chemical/bme680_i2c.c b/drivers/iio/chemical/bme680_i2c.c index 61b12079858d21ec86f878388fb846d0d242ea63..1c7076cf91cafa613ae1c3a9bf2084618befee63 100644 --- a/drivers/iio/chemical/bme680_i2c.c +++ b/drivers/iio/chemical/bme680_i2c.c @@ -52,7 +52,7 @@ static struct i2c_driver bme680_i2c_driver = { .name = "bme680_i2c", .of_match_table = bme680_of_i2c_match, }, - .probe_new = bme680_i2c_probe, + .probe = bme680_i2c_probe, .id_table = bme680_i2c_id, }; module_i2c_driver(bme680_i2c_driver); diff --git a/drivers/iio/chemical/ccs811.c b/drivers/iio/chemical/ccs811.c index 6ead80c089240cfddc7110efb1a1016546e85b12..87741f155c32b632cd44e2cc5e56a7ee529c592f 100644 --- a/drivers/iio/chemical/ccs811.c +++ b/drivers/iio/chemical/ccs811.c @@ -567,7 +567,7 @@ static struct i2c_driver ccs811_driver = { .name = "ccs811", .of_match_table = ccs811_dt_ids, }, - .probe_new = ccs811_probe, + .probe = ccs811_probe, .remove = ccs811_remove, .id_table = ccs811_id, }; diff --git a/drivers/iio/chemical/scd30_i2c.c b/drivers/iio/chemical/scd30_i2c.c index bae479a4721f3b4977f72da16d7cd31086ba90bb..bd3b01ded246e0b9f5a0cafcbe8c030b38e58b19 100644 --- a/drivers/iio/chemical/scd30_i2c.c +++ b/drivers/iio/chemical/scd30_i2c.c @@ -130,7 +130,7 @@ static struct i2c_driver scd30_i2c_driver = { .of_match_table = scd30_i2c_of_match, .pm = pm_sleep_ptr(&scd30_pm_ops), }, - .probe_new = scd30_i2c_probe, + .probe = scd30_i2c_probe, }; module_i2c_driver(scd30_i2c_driver); diff --git a/drivers/iio/chemical/scd4x.c b/drivers/iio/chemical/scd4x.c index f7ed9455b3c8fada9e5de7c2f35738092e581988..a4f22d926400c60a7984b2a91068ee346cb038c2 100644 --- a/drivers/iio/chemical/scd4x.c +++ b/drivers/iio/chemical/scd4x.c @@ -690,7 +690,7 @@ static struct i2c_driver scd4x_i2c_driver = { .of_match_table = scd4x_dt_ids, .pm = pm_sleep_ptr(&scd4x_pm_ops), }, - .probe_new = scd4x_probe, + .probe = scd4x_probe, }; module_i2c_driver(scd4x_i2c_driver); diff --git a/drivers/iio/chemical/sgp30.c b/drivers/iio/chemical/sgp30.c index 9d0c68485b63f2e2eb3a4d399a839c8a635be9e7..b509cff9ce3748aa34ffcbec4f8136dfa9749f69 100644 --- a/drivers/iio/chemical/sgp30.c +++ b/drivers/iio/chemical/sgp30.c @@ -575,7 +575,7 @@ static struct i2c_driver sgp_driver = { .name = "sgp30", .of_match_table = sgp_dt_ids, }, - .probe_new = sgp_probe, + .probe = sgp_probe, .remove = sgp_remove, .id_table = sgp_id, }; diff --git a/drivers/iio/chemical/sgp40.c b/drivers/iio/chemical/sgp40.c index c0ea0130090810267b62a07ca4421fdf7ea945e6..7f0de14a1956fe31da520554ae33f8ab7951a668 100644 --- a/drivers/iio/chemical/sgp40.c +++ b/drivers/iio/chemical/sgp40.c @@ -368,7 +368,7 @@ static struct i2c_driver sgp40_driver = { .name = "sgp40", .of_match_table = sgp40_dt_ids, }, - .probe_new = sgp40_probe, + .probe = sgp40_probe, .id_table = sgp40_id, }; module_i2c_driver(sgp40_driver); diff --git a/drivers/iio/chemical/sps30_i2c.c b/drivers/iio/chemical/sps30_i2c.c index 0cb5d9b65d625263cf362836892833a7355e8f17..5c31299813ecf92a8b9f498fa44b9366aa4d195f 100644 --- a/drivers/iio/chemical/sps30_i2c.c +++ b/drivers/iio/chemical/sps30_i2c.c @@ -249,7 +249,7 @@ static struct i2c_driver sps30_i2c_driver = { .of_match_table = sps30_i2c_of_match, }, .id_table = sps30_i2c_id, - .probe_new = sps30_i2c_probe, + .probe = sps30_i2c_probe, }; module_i2c_driver(sps30_i2c_driver); diff --git a/drivers/iio/chemical/sunrise_co2.c b/drivers/iio/chemical/sunrise_co2.c index 8440dc0c77cfe9bff06dfe4067c1310e85445c26..cdb8696a4e814ef3e4089c3e74abe437ca8ce7e9 100644 --- a/drivers/iio/chemical/sunrise_co2.c +++ b/drivers/iio/chemical/sunrise_co2.c @@ -528,7 +528,7 @@ static struct i2c_driver sunrise_driver = { .name = DRIVER_NAME, .of_match_table = sunrise_of_match, }, - .probe_new = sunrise_probe, + .probe = sunrise_probe, }; module_i2c_driver(sunrise_driver); diff --git a/drivers/iio/chemical/vz89x.c b/drivers/iio/chemical/vz89x.c index d4604f7ccd1e0e559f34db0beb6759e2d2837096..13555f4f401afc5f43f2db15ab1c40b2b148c94e 100644 --- a/drivers/iio/chemical/vz89x.c +++ b/drivers/iio/chemical/vz89x.c @@ -402,7 +402,7 @@ static struct i2c_driver vz89x_driver = { .name = "vz89x", .of_match_table = vz89x_dt_ids, }, - .probe_new = vz89x_probe, + .probe = vz89x_probe, .id_table = vz89x_id, }; module_i2c_driver(vz89x_driver); diff --git a/drivers/iio/dac/ad5064.c b/drivers/iio/dac/ad5064.c index f01249c1ba93cfbc89bf470b07bd8b49109b0e22..7712dc6be608f3f07bfc47487e952d2a7ef585fc 100644 --- a/drivers/iio/dac/ad5064.c +++ b/drivers/iio/dac/ad5064.c @@ -1056,7 +1056,7 @@ static struct i2c_driver ad5064_i2c_driver = { .driver = { .name = "ad5064", }, - .probe_new = ad5064_i2c_probe, + .probe = ad5064_i2c_probe, .id_table = ad5064_i2c_ids, }; diff --git a/drivers/iio/dac/ad5380.c b/drivers/iio/dac/ad5380.c index 64b4519f8f5e6d52a5b2387f44a59b653e17064d..2e3e33f92bc0afebe30c5cdbef177648a0bc969c 100644 --- a/drivers/iio/dac/ad5380.c +++ b/drivers/iio/dac/ad5380.c @@ -589,7 +589,7 @@ static struct i2c_driver ad5380_i2c_driver = { .driver = { .name = "ad5380", }, - .probe_new = ad5380_i2c_probe, + .probe = ad5380_i2c_probe, .remove = ad5380_i2c_remove, .id_table = ad5380_i2c_ids, }; diff --git a/drivers/iio/dac/ad5446.c b/drivers/iio/dac/ad5446.c index aa3130b3345638e2d77056c942f7fe240e618140..8103d2cd13f66f3415d666436458fd1d1d1a0079 100644 --- a/drivers/iio/dac/ad5446.c +++ b/drivers/iio/dac/ad5446.c @@ -595,7 +595,7 @@ static struct i2c_driver ad5446_i2c_driver = { .driver = { .name = "ad5446", }, - .probe_new = ad5446_i2c_probe, + .probe = ad5446_i2c_probe, .remove = ad5446_i2c_remove, .id_table = ad5446_i2c_ids, }; diff --git a/drivers/iio/dac/ad5593r.c b/drivers/iio/dac/ad5593r.c index d311567ab324a68db56bd80bb7f78ba716483c0e..fae5e5a0e72fca1a6cc5de37b4581d36c5c7e0d3 100644 --- a/drivers/iio/dac/ad5593r.c +++ b/drivers/iio/dac/ad5593r.c @@ -138,7 +138,7 @@ static struct i2c_driver ad5593r_driver = { .of_match_table = ad5593r_of_match, .acpi_match_table = ad5593r_acpi_match, }, - .probe_new = ad5593r_i2c_probe, + .probe = ad5593r_i2c_probe, .remove = ad5593r_i2c_remove, .id_table = ad5593r_i2c_ids, }; diff --git a/drivers/iio/dac/ad5696-i2c.c b/drivers/iio/dac/ad5696-i2c.c index 8a95f027801850ba3cdb8fbe17015078087d064c..81541f755a3e1bb34a5c5621a803e3fb6e3c3a17 100644 --- a/drivers/iio/dac/ad5696-i2c.c +++ b/drivers/iio/dac/ad5696-i2c.c @@ -115,7 +115,7 @@ static struct i2c_driver ad5686_i2c_driver = { .name = "ad5696", .of_match_table = ad5686_of_match, }, - .probe_new = ad5686_i2c_probe, + .probe = ad5686_i2c_probe, .remove = ad5686_i2c_remove, .id_table = ad5686_i2c_id, }; diff --git a/drivers/iio/dac/ds4424.c b/drivers/iio/dac/ds4424.c index a16a6a934d9d97b987028e2ba12788b68c44a7e4..e89e4c0546531f186563da3c5e312e1811e8a79a 100644 --- a/drivers/iio/dac/ds4424.c +++ b/drivers/iio/dac/ds4424.c @@ -312,7 +312,7 @@ static struct i2c_driver ds4424_driver = { .of_match_table = ds4424_of_match, .pm = pm_sleep_ptr(&ds4424_pm_ops), }, - .probe_new = ds4424_probe, + .probe = ds4424_probe, .remove = ds4424_remove, .id_table = ds4424_id, }; diff --git a/drivers/iio/dac/m62332.c b/drivers/iio/dac/m62332.c index b692459b0f231599e31470a77bba096a2022f971..ae53baccec91493d15107aea9dbadddd5c31edd9 100644 --- a/drivers/iio/dac/m62332.c +++ b/drivers/iio/dac/m62332.c @@ -238,7 +238,7 @@ static struct i2c_driver m62332_driver = { .name = "m62332", .pm = pm_sleep_ptr(&m62332_pm_ops), }, - .probe_new = m62332_probe, + .probe = m62332_probe, .remove = m62332_remove, .id_table = m62332_id, }; diff --git a/drivers/iio/dac/max517.c b/drivers/iio/dac/max517.c index 25967c39365d2bbd841b49da4d230e888b61bbd7..685980184d3c82ed16728ace493ed3cf545bd7a7 100644 --- a/drivers/iio/dac/max517.c +++ b/drivers/iio/dac/max517.c @@ -203,7 +203,7 @@ static struct i2c_driver max517_driver = { .name = MAX517_DRV_NAME, .pm = pm_sleep_ptr(&max517_pm_ops), }, - .probe_new = max517_probe, + .probe = max517_probe, .id_table = max517_id, }; module_i2c_driver(max517_driver); diff --git a/drivers/iio/dac/max5821.c b/drivers/iio/dac/max5821.c index 23da345b9250cf7570bf752c0795ccbcac785de3..18ba3eaaad7564ebb043d9984dbf5c8302ab8353 100644 --- a/drivers/iio/dac/max5821.c +++ b/drivers/iio/dac/max5821.c @@ -377,7 +377,7 @@ static struct i2c_driver max5821_driver = { .of_match_table = max5821_of_match, .pm = pm_sleep_ptr(&max5821_pm_ops), }, - .probe_new = max5821_probe, + .probe = max5821_probe, .id_table = max5821_id, }; module_i2c_driver(max5821_driver); diff --git a/drivers/iio/dac/mcp4725.c b/drivers/iio/dac/mcp4725.c index 3f5661a3718fe87577d30c0ac039fdbfda4c9292..f4a3124d29f21a4b73067070a6afafd05ec114ac 100644 --- a/drivers/iio/dac/mcp4725.c +++ b/drivers/iio/dac/mcp4725.c @@ -536,7 +536,7 @@ static struct i2c_driver mcp4725_driver = { .of_match_table = mcp4725_of_match, .pm = pm_sleep_ptr(&mcp4725_pm_ops), }, - .probe_new = mcp4725_probe, + .probe = mcp4725_probe, .remove = mcp4725_remove, .id_table = mcp4725_id, }; diff --git a/drivers/iio/dac/ti-dac5571.c b/drivers/iio/dac/ti-dac5571.c index 40191947fea321aa2ffe54aead757e9ac9110475..bab11b9adc25252feb4ad22def830dd8111b3aa2 100644 --- a/drivers/iio/dac/ti-dac5571.c +++ b/drivers/iio/dac/ti-dac5571.c @@ -426,7 +426,7 @@ static struct i2c_driver dac5571_driver = { .name = "ti-dac5571", .of_match_table = dac5571_of_id, }, - .probe_new = dac5571_probe, + .probe = dac5571_probe, .remove = dac5571_remove, .id_table = dac5571_id, }; diff --git a/drivers/iio/gyro/bmg160_i2c.c b/drivers/iio/gyro/bmg160_i2c.c index 2b019ee5b2eb5ed1a27f7022698662150002a59d..2f9675596138b2663fd00a8c844183ea4c4cd710 100644 --- a/drivers/iio/gyro/bmg160_i2c.c +++ b/drivers/iio/gyro/bmg160_i2c.c @@ -70,7 +70,7 @@ static struct i2c_driver bmg160_i2c_driver = { .of_match_table = bmg160_of_match, .pm = &bmg160_pm_ops, }, - .probe_new = bmg160_i2c_probe, + .probe = bmg160_i2c_probe, .remove = bmg160_i2c_remove, .id_table = bmg160_i2c_id, }; diff --git a/drivers/iio/gyro/fxas21002c_i2c.c b/drivers/iio/gyro/fxas21002c_i2c.c index 9e2d0f34a672ea0a473b91cd1270bbbea3f31070..ee7f21b718e2db57752581bd71210f70297f747a 100644 --- a/drivers/iio/gyro/fxas21002c_i2c.c +++ b/drivers/iio/gyro/fxas21002c_i2c.c @@ -56,7 +56,7 @@ static struct i2c_driver fxas21002c_i2c_driver = { .pm = pm_ptr(&fxas21002c_pm_ops), .of_match_table = fxas21002c_i2c_of_match, }, - .probe_new = fxas21002c_i2c_probe, + .probe = fxas21002c_i2c_probe, .remove = fxas21002c_i2c_remove, .id_table = fxas21002c_i2c_id, }; diff --git a/drivers/iio/gyro/itg3200_core.c b/drivers/iio/gyro/itg3200_core.c index ceacd863d3eaaf23be14418e72fc5c164363c1be..53fb92f0ac7ef909551a73fc400dfc88a51ca13c 100644 --- a/drivers/iio/gyro/itg3200_core.c +++ b/drivers/iio/gyro/itg3200_core.c @@ -405,7 +405,7 @@ static struct i2c_driver itg3200_driver = { .pm = pm_sleep_ptr(&itg3200_pm_ops), }, .id_table = itg3200_id, - .probe_new = itg3200_probe, + .probe = itg3200_probe, .remove = itg3200_remove, }; diff --git a/drivers/iio/gyro/mpu3050-i2c.c b/drivers/iio/gyro/mpu3050-i2c.c index 2116798226bf28b6440540eef7c42442b756a84b..52b6feed26379a78bfab3af3180b4cec19c936ea 100644 --- a/drivers/iio/gyro/mpu3050-i2c.c +++ b/drivers/iio/gyro/mpu3050-i2c.c @@ -108,7 +108,7 @@ static const struct of_device_id mpu3050_i2c_of_match[] = { MODULE_DEVICE_TABLE(of, mpu3050_i2c_of_match); static struct i2c_driver mpu3050_i2c_driver = { - .probe_new = mpu3050_i2c_probe, + .probe = mpu3050_i2c_probe, .remove = mpu3050_i2c_remove, .id_table = mpu3050_i2c_id, .driver = { diff --git a/drivers/iio/gyro/st_gyro_i2c.c b/drivers/iio/gyro/st_gyro_i2c.c index 797a1c6a0402063f8124b8f79d00fe69b165d71f..5a10a3556ab054fd3871f2636c595ef6f0c98dfc 100644 --- a/drivers/iio/gyro/st_gyro_i2c.c +++ b/drivers/iio/gyro/st_gyro_i2c.c @@ -111,7 +111,7 @@ static struct i2c_driver st_gyro_driver = { .name = "st-gyro-i2c", .of_match_table = st_gyro_of_match, }, - .probe_new = st_gyro_i2c_probe, + .probe = st_gyro_i2c_probe, .id_table = st_gyro_id_table, }; module_i2c_driver(st_gyro_driver); diff --git a/drivers/iio/health/afe4404.c b/drivers/iio/health/afe4404.c index 21a6378b70524930e038ca0eea0bc1570b14587c..ede1e82013118c24c005ec4fa7a33c88f373525d 100644 --- a/drivers/iio/health/afe4404.c +++ b/drivers/iio/health/afe4404.c @@ -609,7 +609,7 @@ static struct i2c_driver afe4404_i2c_driver = { .of_match_table = afe4404_of_match, .pm = pm_sleep_ptr(&afe4404_pm_ops), }, - .probe_new = afe4404_probe, + .probe = afe4404_probe, .remove = afe4404_remove, .id_table = afe4404_ids, }; diff --git a/drivers/iio/health/max30100.c b/drivers/iio/health/max30100.c index a80fa9852c220fe995c0515be9b0e45ae97aa7bc..6236b4d9613786201d797749a4df99c8787a8345 100644 --- a/drivers/iio/health/max30100.c +++ b/drivers/iio/health/max30100.c @@ -499,7 +499,7 @@ static struct i2c_driver max30100_driver = { .name = MAX30100_DRV_NAME, .of_match_table = max30100_dt_ids, }, - .probe_new = max30100_probe, + .probe = max30100_probe, .remove = max30100_remove, .id_table = max30100_id, }; diff --git a/drivers/iio/health/max30102.c b/drivers/iio/health/max30102.c index 7edcf9e05687bf8475eb2a989c187a523c594942..37e619827e8a11711230d93aa5950d979cb96c99 100644 --- a/drivers/iio/health/max30102.c +++ b/drivers/iio/health/max30102.c @@ -631,7 +631,7 @@ static struct i2c_driver max30102_driver = { .name = MAX30102_DRV_NAME, .of_match_table = max30102_dt_ids, }, - .probe_new = max30102_probe, + .probe = max30102_probe, .remove = max30102_remove, .id_table = max30102_id, }; diff --git a/drivers/iio/humidity/am2315.c b/drivers/iio/humidity/am2315.c index f246516bd45eab7b886fd7893c7f0574aba1ded7..37a35d1153d5023f049d9efbe85c6216eff36a1c 100644 --- a/drivers/iio/humidity/am2315.c +++ b/drivers/iio/humidity/am2315.c @@ -262,7 +262,7 @@ static struct i2c_driver am2315_driver = { .driver = { .name = "am2315", }, - .probe_new = am2315_probe, + .probe = am2315_probe, .id_table = am2315_i2c_id, }; diff --git a/drivers/iio/humidity/hdc100x.c b/drivers/iio/humidity/hdc100x.c index 49a950d739e44301c431b3a47fc554a948d388f5..202014da2785c74a9bbaa1ec89544c802f507fb1 100644 --- a/drivers/iio/humidity/hdc100x.c +++ b/drivers/iio/humidity/hdc100x.c @@ -428,7 +428,7 @@ static struct i2c_driver hdc100x_driver = { .of_match_table = hdc100x_dt_ids, .acpi_match_table = hdc100x_acpi_match, }, - .probe_new = hdc100x_probe, + .probe = hdc100x_probe, .id_table = hdc100x_id, }; module_i2c_driver(hdc100x_driver); diff --git a/drivers/iio/humidity/hdc2010.c b/drivers/iio/humidity/hdc2010.c index c8fddd612e060a77d79a85bab1c19cdd562e07e8..f5867659e00fcea0f866191dbd7f234da88f4ab8 100644 --- a/drivers/iio/humidity/hdc2010.c +++ b/drivers/iio/humidity/hdc2010.c @@ -338,7 +338,7 @@ static struct i2c_driver hdc2010_driver = { .name = "hdc2010", .of_match_table = hdc2010_dt_ids, }, - .probe_new = hdc2010_probe, + .probe = hdc2010_probe, .remove = hdc2010_remove, .id_table = hdc2010_id, }; diff --git a/drivers/iio/humidity/hts221_i2c.c b/drivers/iio/humidity/hts221_i2c.c index d81869423cf031564a07d095e20339b68bbaf918..30f2068ea156675cac8e976cff982263bc2c623c 100644 --- a/drivers/iio/humidity/hts221_i2c.c +++ b/drivers/iio/humidity/hts221_i2c.c @@ -65,7 +65,7 @@ static struct i2c_driver hts221_driver = { .of_match_table = hts221_i2c_of_match, .acpi_match_table = ACPI_PTR(hts221_acpi_match), }, - .probe_new = hts221_i2c_probe, + .probe = hts221_i2c_probe, .id_table = hts221_i2c_id_table, }; module_i2c_driver(hts221_driver); diff --git a/drivers/iio/humidity/htu21.c b/drivers/iio/humidity/htu21.c index 8411a9f3e828aaca3cb2cbdc9ddbc083a76c2b4d..39e886075299ea4648cc1e140fbe019e7823719e 100644 --- a/drivers/iio/humidity/htu21.c +++ b/drivers/iio/humidity/htu21.c @@ -244,7 +244,7 @@ static const struct of_device_id htu21_of_match[] = { MODULE_DEVICE_TABLE(of, htu21_of_match); static struct i2c_driver htu21_driver = { - .probe_new = htu21_probe, + .probe = htu21_probe, .id_table = htu21_id, .driver = { .name = "htu21", diff --git a/drivers/iio/humidity/si7005.c b/drivers/iio/humidity/si7005.c index fa1faf168c8d9e00304cf0e7d878ee429b186e94..ebfb79bc9edc5ae8822324601dabb2728f92b091 100644 --- a/drivers/iio/humidity/si7005.c +++ b/drivers/iio/humidity/si7005.c @@ -173,7 +173,7 @@ static struct i2c_driver si7005_driver = { .driver = { .name = "si7005", }, - .probe_new = si7005_probe, + .probe = si7005_probe, .id_table = si7005_id, }; module_i2c_driver(si7005_driver); diff --git a/drivers/iio/humidity/si7020.c b/drivers/iio/humidity/si7020.c index 3e50592e8e68bee1b1343422a4db19bb2674e9a7..fb10066493288829a15c3b83fb254ed6b6bd9bab 100644 --- a/drivers/iio/humidity/si7020.c +++ b/drivers/iio/humidity/si7020.c @@ -155,7 +155,7 @@ static struct i2c_driver si7020_driver = { .name = "si7020", .of_match_table = si7020_dt_ids, }, - .probe_new = si7020_probe, + .probe = si7020_probe, .id_table = si7020_id, }; diff --git a/drivers/iio/imu/bmi160/bmi160_i2c.c b/drivers/iio/imu/bmi160/bmi160_i2c.c index 2ca907d396a01579e724c11fc633af6d7a6b1125..81652c08e6441c4472b847c40a4d42e64a5d668e 100644 --- a/drivers/iio/imu/bmi160/bmi160_i2c.c +++ b/drivers/iio/imu/bmi160/bmi160_i2c.c @@ -60,7 +60,7 @@ static struct i2c_driver bmi160_i2c_driver = { .acpi_match_table = bmi160_acpi_match, .of_match_table = bmi160_of_match, }, - .probe_new = bmi160_i2c_probe, + .probe = bmi160_i2c_probe, .id_table = bmi160_i2c_id, }; module_i2c_driver(bmi160_i2c_driver); diff --git a/drivers/iio/imu/bno055/bno055_i2c.c b/drivers/iio/imu/bno055/bno055_i2c.c index c1bbc0fe34f9bdd467c2506f46d3957699e6da29..6ecd750c6b7640b9e68b33fd5f848e603d0df669 100644 --- a/drivers/iio/imu/bno055/bno055_i2c.c +++ b/drivers/iio/imu/bno055/bno055_i2c.c @@ -46,7 +46,7 @@ static struct i2c_driver bno055_driver = { .name = "bno055-i2c", .of_match_table = bno055_i2c_of_match, }, - .probe_new = bno055_i2c_probe, + .probe = bno055_i2c_probe, .id_table = bno055_i2c_id, }; module_i2c_driver(bno055_driver); diff --git a/drivers/iio/imu/fxos8700_i2c.c b/drivers/iio/imu/fxos8700_i2c.c index a74a15fda8cbb5975d650e565c7ddb893fb00ab3..2ace306d0f9ab81b5124d451b0f3f2257874f1a6 100644 --- a/drivers/iio/imu/fxos8700_i2c.c +++ b/drivers/iio/imu/fxos8700_i2c.c @@ -60,7 +60,7 @@ static struct i2c_driver fxos8700_i2c_driver = { .acpi_match_table = ACPI_PTR(fxos8700_acpi_match), .of_match_table = fxos8700_of_match, }, - .probe_new = fxos8700_i2c_probe, + .probe = fxos8700_i2c_probe, .id_table = fxos8700_i2c_id, }; module_i2c_driver(fxos8700_i2c_driver); diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_i2c.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_i2c.c index eb2681ad375f224b3b0f07dfbbc49ba59abf1c8c..1af559403ba66d6cfebf4e392505f022b2892efa 100644 --- a/drivers/iio/imu/inv_icm42600/inv_icm42600_i2c.c +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_i2c.c @@ -98,7 +98,7 @@ static struct i2c_driver inv_icm42600_driver = { .of_match_table = inv_icm42600_of_matches, .pm = pm_ptr(&inv_icm42600_pm_ops), }, - .probe_new = inv_icm42600_probe, + .probe = inv_icm42600_probe, }; module_i2c_driver(inv_icm42600_driver); diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_timestamp.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_timestamp.c index 7f2dc41f807bbec946c5ac96bd9a02c5e28d0069..37cbf08acb3a17303b38986ce7dbe8c80e6720d0 100644 --- a/drivers/iio/imu/inv_icm42600/inv_icm42600_timestamp.c +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_timestamp.c @@ -93,8 +93,8 @@ static bool inv_validate_period(uint32_t period, uint32_t mult) return false; } -static bool inv_compute_chip_period(struct inv_icm42600_timestamp *ts, - uint32_t mult, uint32_t period) +static bool inv_update_chip_period(struct inv_icm42600_timestamp *ts, + uint32_t mult, uint32_t period) { uint32_t new_chip_period; @@ -104,10 +104,31 @@ static bool inv_compute_chip_period(struct inv_icm42600_timestamp *ts, /* update chip internal period estimation */ new_chip_period = period / mult; inv_update_acc(&ts->chip_period, new_chip_period); + ts->period = ts->mult * ts->chip_period.val; return true; } +static void inv_align_timestamp_it(struct inv_icm42600_timestamp *ts) +{ + int64_t delta, jitter; + int64_t adjust; + + /* delta time between last sample and last interrupt */ + delta = ts->it.lo - ts->timestamp; + + /* adjust timestamp while respecting jitter */ + jitter = div_s64((int64_t)ts->period * INV_ICM42600_TIMESTAMP_JITTER, 100); + if (delta > jitter) + adjust = jitter; + else if (delta < -jitter) + adjust = -jitter; + else + adjust = 0; + + ts->timestamp += adjust; +} + void inv_icm42600_timestamp_interrupt(struct inv_icm42600_timestamp *ts, uint32_t fifo_period, size_t fifo_nb, size_t sensor_nb, int64_t timestamp) @@ -116,7 +137,6 @@ void inv_icm42600_timestamp_interrupt(struct inv_icm42600_timestamp *ts, int64_t delta, interval; const uint32_t fifo_mult = fifo_period / INV_ICM42600_TIMESTAMP_PERIOD; uint32_t period = ts->period; - int32_t m; bool valid = false; if (fifo_nb == 0) @@ -130,10 +150,7 @@ void inv_icm42600_timestamp_interrupt(struct inv_icm42600_timestamp *ts, if (it->lo != 0) { /* compute period: delta time divided by number of samples */ period = div_s64(delta, fifo_nb); - valid = inv_compute_chip_period(ts, fifo_mult, period); - /* update sensor period if chip internal period is updated */ - if (valid) - ts->period = ts->mult * ts->chip_period.val; + valid = inv_update_chip_period(ts, fifo_mult, period); } /* no previous data, compute theoritical value from interrupt */ @@ -145,22 +162,8 @@ void inv_icm42600_timestamp_interrupt(struct inv_icm42600_timestamp *ts, } /* if interrupt interval is valid, sync with interrupt timestamp */ - if (valid) { - /* compute measured fifo_period */ - fifo_period = fifo_mult * ts->chip_period.val; - /* delta time between last sample and last interrupt */ - delta = it->lo - ts->timestamp; - /* if there are multiple samples, go back to first one */ - while (delta >= (fifo_period * 3 / 2)) - delta -= fifo_period; - /* compute maximal adjustment value */ - m = INV_ICM42600_TIMESTAMP_MAX_PERIOD(ts->period) - ts->period; - if (delta > m) - delta = m; - else if (delta < -m) - delta = -m; - ts->timestamp += delta; - } + if (valid) + inv_align_timestamp_it(ts); } void inv_icm42600_timestamp_apply_odr(struct inv_icm42600_timestamp *ts, diff --git a/drivers/iio/imu/inv_mpu6050/Kconfig b/drivers/iio/imu/inv_mpu6050/Kconfig index 3636b1bc90f1c2dcf3c899ab2776cf834b00a284..64dd73dcc4bab48fe611e819d5b706c9f5078a10 100644 --- a/drivers/iio/imu/inv_mpu6050/Kconfig +++ b/drivers/iio/imu/inv_mpu6050/Kconfig @@ -16,7 +16,7 @@ config INV_MPU6050_I2C select REGMAP_I2C help This driver supports the Invensense MPU6050/9150, - MPU6500/6515/6880/9250/9255, ICM20608(D)/20609/20689, ICM20602/ICM20690 + MPU6500/6515/6880/9250/9255, ICM20608(D)/20609/20689, ICM20600/20602/20690 and IAM20680 motion tracking devices over I2C. This driver can be built as a module. The module will be called inv-mpu6050-i2c. @@ -28,7 +28,7 @@ config INV_MPU6050_SPI select REGMAP_SPI help This driver supports the Invensense MPU6000, - MPU6500/6515/6880/9250/9255, ICM20608(D)/20609/20689, ICM20602/ICM20690 + MPU6500/6515/6880/9250/9255, ICM20608(D)/20609/20689, ICM20600/20602/20690 and IAM20680 motion tracking devices over SPI. This driver can be built as a module. The module will be called inv-mpu6050-spi. diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c index 8a129120b73dd1f7fd1016ea7e5fc762d0a136ce..592a6e60b4131e0d79d091121fd5a1f0793d19ad 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c @@ -244,6 +244,15 @@ static const struct inv_mpu6050_hw hw_info[] = { .temp = {INV_ICM20608_TEMP_OFFSET, INV_ICM20608_TEMP_SCALE}, .startup_time = {INV_MPU6500_GYRO_STARTUP_TIME, INV_MPU6500_ACCEL_STARTUP_TIME}, }, + { + .whoami = INV_ICM20600_WHOAMI_VALUE, + .name = "ICM20600", + .reg = ®_set_icm20602, + .config = &chip_config_6500, + .fifo_size = 1008, + .temp = {INV_ICM20608_TEMP_OFFSET, INV_ICM20608_TEMP_SCALE}, + .startup_time = {INV_ICM20602_GYRO_STARTUP_TIME, INV_ICM20602_ACCEL_STARTUP_TIME}, + }, { .whoami = INV_ICM20602_WHOAMI_VALUE, .name = "ICM20602", @@ -1597,6 +1606,7 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name, indio_dev->num_channels = ARRAY_SIZE(inv_mpu9250_channels); indio_dev->available_scan_masks = inv_mpu9x50_scan_masks; break; + case INV_ICM20600: case INV_ICM20602: indio_dev->channels = inv_mpu_channels; indio_dev->num_channels = ARRAY_SIZE(inv_mpu_channels); diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c index 2f2da4cb732156fc4e7874027464ca17f2e4b9e7..410ea39fd495a693aebd365647c3e47c38c5976a 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c @@ -32,6 +32,7 @@ static bool inv_mpu_i2c_aux_bus(struct device *dev) case INV_ICM20608D: case INV_ICM20609: case INV_ICM20689: + case INV_ICM20600: case INV_ICM20602: case INV_IAM20680: /* no i2c auxiliary bus on the chip */ @@ -183,6 +184,7 @@ static const struct i2c_device_id inv_mpu_id[] = { {"icm20608d", INV_ICM20608D}, {"icm20609", INV_ICM20609}, {"icm20689", INV_ICM20689}, + {"icm20600", INV_ICM20600}, {"icm20602", INV_ICM20602}, {"icm20690", INV_ICM20690}, {"iam20680", INV_IAM20680}, @@ -236,6 +238,10 @@ static const struct of_device_id inv_of_match[] = { .compatible = "invensense,icm20689", .data = (void *)INV_ICM20689 }, + { + .compatible = "invensense,icm20600", + .data = (void *)INV_ICM20600 + }, { .compatible = "invensense,icm20602", .data = (void *)INV_ICM20602 @@ -259,7 +265,7 @@ static const struct acpi_device_id inv_acpi_match[] = { MODULE_DEVICE_TABLE(acpi, inv_acpi_match); static struct i2c_driver inv_mpu_driver = { - .probe_new = inv_mpu_probe, + .probe = inv_mpu_probe, .remove = inv_mpu_remove, .id_table = inv_mpu_id, .driver = { diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h index 94b54c501ec0a663c0a805a32201c379b018be0c..b4ab2c397d0fce92c9ed28f604d81b5fe8a9efb4 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h @@ -79,6 +79,7 @@ enum inv_devices { INV_ICM20608D, INV_ICM20609, INV_ICM20689, + INV_ICM20600, INV_ICM20602, INV_ICM20690, INV_IAM20680, @@ -398,6 +399,7 @@ struct inv_mpu6050_state { #define INV_ICM20608D_WHOAMI_VALUE 0xAE #define INV_ICM20609_WHOAMI_VALUE 0xA6 #define INV_ICM20689_WHOAMI_VALUE 0x98 +#define INV_ICM20600_WHOAMI_VALUE 0x11 #define INV_ICM20602_WHOAMI_VALUE 0x12 #define INV_ICM20690_WHOAMI_VALUE 0x20 #define INV_IAM20680_WHOAMI_VALUE 0xA9 diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c index 89f46c2f213d8fb179075027cce6305ca6cc3dce..05451ca1580b637a66a30efe82fbd2a2b63e55d5 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c @@ -76,6 +76,7 @@ static const struct spi_device_id inv_mpu_id[] = { {"icm20608d", INV_ICM20608D}, {"icm20609", INV_ICM20609}, {"icm20689", INV_ICM20689}, + {"icm20600", INV_ICM20600}, {"icm20602", INV_ICM20602}, {"icm20690", INV_ICM20690}, {"iam20680", INV_IAM20680}, @@ -125,6 +126,10 @@ static const struct of_device_id inv_of_match[] = { .compatible = "invensense,icm20689", .data = (void *)INV_ICM20689 }, + { + .compatible = "invensense,icm20600", + .data = (void *)INV_ICM20600 + }, { .compatible = "invensense,icm20602", .data = (void *)INV_ICM20602 diff --git a/drivers/iio/imu/kmx61.c b/drivers/iio/imu/kmx61.c index 53ba020fa5d00b59f854ca89abb84a297b414c2f..958167b31241e639002090941ed044580949bde2 100644 --- a/drivers/iio/imu/kmx61.c +++ b/drivers/iio/imu/kmx61.c @@ -1517,7 +1517,7 @@ static struct i2c_driver kmx61_driver = { .acpi_match_table = ACPI_PTR(kmx61_acpi_match), .pm = pm_ptr(&kmx61_pm_ops), }, - .probe_new = kmx61_probe, + .probe = kmx61_probe, .remove = kmx61_remove, .id_table = kmx61_id, }; diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c index 020717f92363cd6294471efde0ae54f9f7236822..911444ec57c0166bda209709e11543f9c7b2980d 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c @@ -179,7 +179,7 @@ static struct i2c_driver st_lsm6dsx_driver = { .of_match_table = st_lsm6dsx_i2c_of_match, .acpi_match_table = st_lsm6dsx_i2c_acpi_match, }, - .probe_new = st_lsm6dsx_i2c_probe, + .probe = st_lsm6dsx_i2c_probe, .id_table = st_lsm6dsx_i2c_id_table, }; module_i2c_driver(st_lsm6dsx_driver); diff --git a/drivers/iio/imu/st_lsm9ds0/Kconfig b/drivers/iio/imu/st_lsm9ds0/Kconfig index d29558edee60414d96797821674f72cc3c5cdffb..7aef714b6ecb6fa48c5318f4d160c9b2eaa3fbb4 100644 --- a/drivers/iio/imu/st_lsm9ds0/Kconfig +++ b/drivers/iio/imu/st_lsm9ds0/Kconfig @@ -10,7 +10,8 @@ config IIO_ST_LSM9DS0 help Say yes here to build support for STMicroelectronics LSM9DS0 IMU - sensor. Supported devices: accelerometer/magnetometer of lsm9ds0. + sensor. Supported devices: accelerometer/magnetometer of lsm9ds0 + and lsm303d. To compile this driver as a module, choose M here: the module will be called st_lsm9ds0. diff --git a/drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_i2c.c b/drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_i2c.c index a90138d8b06a86e6cc09d6af8330846267a71d59..61d855083aa012e770dbb8107f6f5e2d5130e593 100644 --- a/drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_i2c.c +++ b/drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_i2c.c @@ -18,6 +18,10 @@ #include "st_lsm9ds0.h" static const struct of_device_id st_lsm9ds0_of_match[] = { + { + .compatible = "st,lsm303d-imu", + .data = LSM303D_IMU_DEV_NAME, + }, { .compatible = "st,lsm9ds0-imu", .data = LSM9DS0_IMU_DEV_NAME, @@ -27,11 +31,18 @@ static const struct of_device_id st_lsm9ds0_of_match[] = { MODULE_DEVICE_TABLE(of, st_lsm9ds0_of_match); static const struct i2c_device_id st_lsm9ds0_id_table[] = { + { LSM303D_IMU_DEV_NAME }, { LSM9DS0_IMU_DEV_NAME }, {} }; MODULE_DEVICE_TABLE(i2c, st_lsm9ds0_id_table); +static const struct acpi_device_id st_lsm9ds0_acpi_match[] = { + {"ACCL0001", (kernel_ulong_t)LSM303D_IMU_DEV_NAME}, + { }, +}; +MODULE_DEVICE_TABLE(acpi, st_lsm9ds0_acpi_match); + static const struct regmap_config st_lsm9ds0_regmap_config = { .reg_bits = 8, .val_bits = 8, @@ -68,8 +79,9 @@ static struct i2c_driver st_lsm9ds0_driver = { .driver = { .name = "st-lsm9ds0-i2c", .of_match_table = st_lsm9ds0_of_match, + .acpi_match_table = st_lsm9ds0_acpi_match, }, - .probe_new = st_lsm9ds0_i2c_probe, + .probe = st_lsm9ds0_i2c_probe, .id_table = st_lsm9ds0_id_table, }; module_i2c_driver(st_lsm9ds0_driver); diff --git a/drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_spi.c b/drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_spi.c index b743bf3546a7f960e88e0865060afa60631dd1be..8cc041d56cf76257105c4c114cb2bbbdca7860d8 100644 --- a/drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_spi.c +++ b/drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_spi.c @@ -18,6 +18,10 @@ #include "st_lsm9ds0.h" static const struct of_device_id st_lsm9ds0_of_match[] = { + { + .compatible = "st,lsm303d-imu", + .data = LSM303D_IMU_DEV_NAME, + }, { .compatible = "st,lsm9ds0-imu", .data = LSM9DS0_IMU_DEV_NAME, @@ -27,6 +31,7 @@ static const struct of_device_id st_lsm9ds0_of_match[] = { MODULE_DEVICE_TABLE(of, st_lsm9ds0_of_match); static const struct spi_device_id st_lsm9ds0_id_table[] = { + { LSM303D_IMU_DEV_NAME }, { LSM9DS0_IMU_DEV_NAME }, {} }; diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c index a7a080bed1808f1f763bdb6dfff7c939c95a2bc8..176d31d9f9d807ed2b8d83ab706c085cf2e56590 100644 --- a/drivers/iio/industrialio-buffer.c +++ b/drivers/iio/industrialio-buffer.c @@ -194,7 +194,7 @@ static ssize_t iio_buffer_write(struct file *filp, const char __user *buf, written = 0; add_wait_queue(&rb->pollq, &wait); do { - if (indio_dev->info == NULL) + if (!indio_dev->info) return -ENODEV; if (!iio_buffer_space_available(rb)) { @@ -210,7 +210,7 @@ static ssize_t iio_buffer_write(struct file *filp, const char __user *buf, } wait_woken(&wait, TASK_INTERRUPTIBLE, - MAX_SCHEDULE_TIMEOUT); + MAX_SCHEDULE_TIMEOUT); continue; } @@ -242,7 +242,7 @@ static __poll_t iio_buffer_poll(struct file *filp, struct iio_buffer *rb = ib->buffer; struct iio_dev *indio_dev = ib->indio_dev; - if (!indio_dev->info || rb == NULL) + if (!indio_dev->info || !rb) return 0; poll_wait(filp, &rb->pollq, wait); @@ -407,9 +407,9 @@ static ssize_t iio_scan_el_show(struct device *dev, /* Note NULL used as error indicator as it doesn't make sense. */ static const unsigned long *iio_scan_mask_match(const unsigned long *av_masks, - unsigned int masklength, - const unsigned long *mask, - bool strict) + unsigned int masklength, + const unsigned long *mask, + bool strict) { if (bitmap_empty(mask, masklength)) return NULL; @@ -427,7 +427,7 @@ static const unsigned long *iio_scan_mask_match(const unsigned long *av_masks, } static bool iio_validate_scan_mask(struct iio_dev *indio_dev, - const unsigned long *mask) + const unsigned long *mask) { if (!indio_dev->setup_ops->validate_scan_mask) return true; @@ -446,7 +446,7 @@ static bool iio_validate_scan_mask(struct iio_dev *indio_dev, * individual buffers request is plausible. */ static int iio_scan_mask_set(struct iio_dev *indio_dev, - struct iio_buffer *buffer, int bit) + struct iio_buffer *buffer, int bit) { const unsigned long *mask; unsigned long *trialmask; @@ -539,7 +539,6 @@ static ssize_t iio_scan_el_store(struct device *dev, mutex_unlock(&iio_dev_opaque->mlock); return ret < 0 ? ret : len; - } static ssize_t iio_scan_el_ts_show(struct device *dev, @@ -706,7 +705,7 @@ static unsigned int iio_storage_bytes_for_timestamp(struct iio_dev *indio_dev) } static int iio_compute_scan_bytes(struct iio_dev *indio_dev, - const unsigned long *mask, bool timestamp) + const unsigned long *mask, bool timestamp) { unsigned int bytes = 0; int length, i, largest = 0; @@ -732,7 +731,7 @@ static int iio_compute_scan_bytes(struct iio_dev *indio_dev, } static void iio_buffer_activate(struct iio_dev *indio_dev, - struct iio_buffer *buffer) + struct iio_buffer *buffer) { struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); @@ -753,12 +752,12 @@ static void iio_buffer_deactivate_all(struct iio_dev *indio_dev) struct iio_buffer *buffer, *_buffer; list_for_each_entry_safe(buffer, _buffer, - &iio_dev_opaque->buffer_list, buffer_list) + &iio_dev_opaque->buffer_list, buffer_list) iio_buffer_deactivate(buffer); } static int iio_buffer_enable(struct iio_buffer *buffer, - struct iio_dev *indio_dev) + struct iio_dev *indio_dev) { if (!buffer->access->enable) return 0; @@ -766,7 +765,7 @@ static int iio_buffer_enable(struct iio_buffer *buffer, } static int iio_buffer_disable(struct iio_buffer *buffer, - struct iio_dev *indio_dev) + struct iio_dev *indio_dev) { if (!buffer->access->disable) return 0; @@ -774,7 +773,7 @@ static int iio_buffer_disable(struct iio_buffer *buffer, } static void iio_buffer_update_bytes_per_datum(struct iio_dev *indio_dev, - struct iio_buffer *buffer) + struct iio_buffer *buffer) { unsigned int bytes; @@ -782,13 +781,13 @@ static void iio_buffer_update_bytes_per_datum(struct iio_dev *indio_dev, return; bytes = iio_compute_scan_bytes(indio_dev, buffer->scan_mask, - buffer->scan_timestamp); + buffer->scan_timestamp); buffer->access->set_bytes_per_datum(buffer, bytes); } static int iio_buffer_request_update(struct iio_dev *indio_dev, - struct iio_buffer *buffer) + struct iio_buffer *buffer) { int ret; @@ -797,7 +796,7 @@ static int iio_buffer_request_update(struct iio_dev *indio_dev, ret = buffer->access->request_update(buffer); if (ret) { dev_dbg(&indio_dev->dev, - "Buffer not started: buffer parameter update failed (%d)\n", + "Buffer not started: buffer parameter update failed (%d)\n", ret); return ret; } @@ -807,7 +806,7 @@ static int iio_buffer_request_update(struct iio_dev *indio_dev, } static void iio_free_scan_mask(struct iio_dev *indio_dev, - const unsigned long *mask) + const unsigned long *mask) { /* If the mask is dynamically allocated free it, otherwise do nothing */ if (!indio_dev->available_scan_masks) @@ -823,8 +822,9 @@ struct iio_device_config { }; static int iio_verify_update(struct iio_dev *indio_dev, - struct iio_buffer *insert_buffer, struct iio_buffer *remove_buffer, - struct iio_device_config *config) + struct iio_buffer *insert_buffer, + struct iio_buffer *remove_buffer, + struct iio_device_config *config) { struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); unsigned long *compound_mask; @@ -864,7 +864,7 @@ static int iio_verify_update(struct iio_dev *indio_dev, if (insert_buffer) { modes &= insert_buffer->access->modes; config->watermark = min(config->watermark, - insert_buffer->watermark); + insert_buffer->watermark); } /* Definitely possible for devices to support both of these. */ @@ -890,7 +890,7 @@ static int iio_verify_update(struct iio_dev *indio_dev, /* What scan mask do we actually have? */ compound_mask = bitmap_zalloc(indio_dev->masklength, GFP_KERNEL); - if (compound_mask == NULL) + if (!compound_mask) return -ENOMEM; scan_timestamp = false; @@ -911,18 +911,18 @@ static int iio_verify_update(struct iio_dev *indio_dev, if (indio_dev->available_scan_masks) { scan_mask = iio_scan_mask_match(indio_dev->available_scan_masks, - indio_dev->masklength, - compound_mask, - strict_scanmask); + indio_dev->masklength, + compound_mask, + strict_scanmask); bitmap_free(compound_mask); - if (scan_mask == NULL) + if (!scan_mask) return -EINVAL; } else { scan_mask = compound_mask; } config->scan_bytes = iio_compute_scan_bytes(indio_dev, - scan_mask, scan_timestamp); + scan_mask, scan_timestamp); config->scan_mask = scan_mask; config->scan_timestamp = scan_timestamp; @@ -954,16 +954,16 @@ static void iio_buffer_demux_free(struct iio_buffer *buffer) } static int iio_buffer_add_demux(struct iio_buffer *buffer, - struct iio_demux_table **p, unsigned int in_loc, unsigned int out_loc, - unsigned int length) + struct iio_demux_table **p, unsigned int in_loc, + unsigned int out_loc, + unsigned int length) { - if (*p && (*p)->from + (*p)->length == in_loc && - (*p)->to + (*p)->length == out_loc) { + (*p)->to + (*p)->length == out_loc) { (*p)->length += length; } else { *p = kmalloc(sizeof(**p), GFP_KERNEL); - if (*p == NULL) + if (!(*p)) return -ENOMEM; (*p)->from = in_loc; (*p)->to = out_loc; @@ -1027,7 +1027,7 @@ static int iio_buffer_update_demux(struct iio_dev *indio_dev, out_loc += length; } buffer->demux_bounce = kzalloc(out_loc, GFP_KERNEL); - if (buffer->demux_bounce == NULL) { + if (!buffer->demux_bounce) { ret = -ENOMEM; goto error_clear_mux_table; } @@ -1060,7 +1060,7 @@ static int iio_update_demux(struct iio_dev *indio_dev) } static int iio_enable_buffers(struct iio_dev *indio_dev, - struct iio_device_config *config) + struct iio_device_config *config) { struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); struct iio_buffer *buffer, *tmp = NULL; @@ -1078,7 +1078,7 @@ static int iio_enable_buffers(struct iio_dev *indio_dev, ret = indio_dev->setup_ops->preenable(indio_dev); if (ret) { dev_dbg(&indio_dev->dev, - "Buffer not started: buffer preenable failed (%d)\n", ret); + "Buffer not started: buffer preenable failed (%d)\n", ret); goto err_undo_config; } } @@ -1118,7 +1118,7 @@ static int iio_enable_buffers(struct iio_dev *indio_dev, ret = indio_dev->setup_ops->postenable(indio_dev); if (ret) { dev_dbg(&indio_dev->dev, - "Buffer not started: postenable failed (%d)\n", ret); + "Buffer not started: postenable failed (%d)\n", ret); goto err_detach_pollfunc; } } @@ -1194,15 +1194,15 @@ static int iio_disable_buffers(struct iio_dev *indio_dev) } static int __iio_update_buffers(struct iio_dev *indio_dev, - struct iio_buffer *insert_buffer, - struct iio_buffer *remove_buffer) + struct iio_buffer *insert_buffer, + struct iio_buffer *remove_buffer) { struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); struct iio_device_config new_config; int ret; ret = iio_verify_update(indio_dev, insert_buffer, remove_buffer, - &new_config); + &new_config); if (ret) return ret; @@ -1258,7 +1258,7 @@ int iio_update_buffers(struct iio_dev *indio_dev, return 0; if (insert_buffer && - (insert_buffer->direction == IIO_BUFFER_DIRECTION_OUT)) + insert_buffer->direction == IIO_BUFFER_DIRECTION_OUT) return -EINVAL; mutex_lock(&iio_dev_opaque->info_exist_lock); @@ -1275,7 +1275,7 @@ int iio_update_buffers(struct iio_dev *indio_dev, goto out_unlock; } - if (indio_dev->info == NULL) { + if (!indio_dev->info) { ret = -ENODEV; goto out_unlock; } @@ -1615,7 +1615,7 @@ static int __iio_buffer_alloc_sysfs_and_mask(struct iio_buffer *buffer, buffer_attrcount = 0; if (buffer->attrs) { - while (buffer->attrs[buffer_attrcount] != NULL) + while (buffer->attrs[buffer_attrcount]) buffer_attrcount++; } buffer_attrcount += ARRAY_SIZE(iio_buffer_attrs); @@ -1643,7 +1643,7 @@ static int __iio_buffer_alloc_sysfs_and_mask(struct iio_buffer *buffer, } ret = iio_buffer_add_channel_sysfs(indio_dev, buffer, - &channels[i]); + &channels[i]); if (ret < 0) goto error_cleanup_dynamic; scan_el_attrcount += ret; @@ -1651,10 +1651,10 @@ static int __iio_buffer_alloc_sysfs_and_mask(struct iio_buffer *buffer, iio_dev_opaque->scan_index_timestamp = channels[i].scan_index; } - if (indio_dev->masklength && buffer->scan_mask == NULL) { + if (indio_dev->masklength && !buffer->scan_mask) { buffer->scan_mask = bitmap_zalloc(indio_dev->masklength, GFP_KERNEL); - if (buffer->scan_mask == NULL) { + if (!buffer->scan_mask) { ret = -ENOMEM; goto error_cleanup_dynamic; } @@ -1771,7 +1771,7 @@ int iio_buffers_alloc_sysfs_and_mask(struct iio_dev *indio_dev) goto error_unwind_sysfs_and_mask; } - sz = sizeof(*(iio_dev_opaque->buffer_ioctl_handler)); + sz = sizeof(*iio_dev_opaque->buffer_ioctl_handler); iio_dev_opaque->buffer_ioctl_handler = kzalloc(sz, GFP_KERNEL); if (!iio_dev_opaque->buffer_ioctl_handler) { ret = -ENOMEM; @@ -1820,14 +1820,14 @@ void iio_buffers_free_sysfs_and_mask(struct iio_dev *indio_dev) * a time. */ bool iio_validate_scan_mask_onehot(struct iio_dev *indio_dev, - const unsigned long *mask) + const unsigned long *mask) { return bitmap_weight(mask, indio_dev->masklength) == 1; } EXPORT_SYMBOL_GPL(iio_validate_scan_mask_onehot); static const void *iio_demux(struct iio_buffer *buffer, - const void *datain) + const void *datain) { struct iio_demux_table *t; diff --git a/drivers/iio/industrialio-trigger.c b/drivers/iio/industrialio-trigger.c index 784dc1e00310b987174ddf59b8b7f1c0e4e1445f..f207e36b12cc9df59649da75fb3f120a0e604572 100644 --- a/drivers/iio/industrialio-trigger.c +++ b/drivers/iio/industrialio-trigger.c @@ -322,7 +322,7 @@ int iio_trigger_attach_poll_func(struct iio_trigger *trig, * this is the case if the IIO device and the trigger device share the * same parent device. */ - if (pf->indio_dev->dev.parent == trig->dev.parent) + if (iio_validate_own_trigger(pf->indio_dev, trig)) trig->attached_own_device = true; return ret; @@ -728,6 +728,26 @@ bool iio_trigger_using_own(struct iio_dev *indio_dev) } EXPORT_SYMBOL(iio_trigger_using_own); +/** + * iio_validate_own_trigger - Check if a trigger and IIO device belong to + * the same device + * @idev: the IIO device to check + * @trig: the IIO trigger to check + * + * This function can be used as the validate_trigger callback for triggers that + * can only be attached to their own device. + * + * Return: 0 if both the trigger and the IIO device belong to the same + * device, -EINVAL otherwise. + */ +int iio_validate_own_trigger(struct iio_dev *idev, struct iio_trigger *trig) +{ + if (idev->dev.parent != trig->dev.parent) + return -EINVAL; + return 0; +} +EXPORT_SYMBOL_GPL(iio_validate_own_trigger); + /** * iio_trigger_validate_own_device - Check if a trigger and IIO device belong to * the same device diff --git a/drivers/iio/light/Kconfig b/drivers/iio/light/Kconfig index 6fa31fcd71a17fff4b396d158dca91a6964159d0..45edba797e4c7e9dfd89e43a250ac5dddffa215c 100644 --- a/drivers/iio/light/Kconfig +++ b/drivers/iio/light/Kconfig @@ -289,6 +289,20 @@ config JSA1212 To compile this driver as a module, choose M here: the module will be called jsa1212. +config ROHM_BU27008 + tristate "ROHM BU27008 color (RGB+C/IR) sensor" + depends on I2C + select REGMAP_I2C + select IIO_GTS_HELPER + help + Enable support for the ROHM BU27008 color sensor. + The ROHM BU27008 is a sensor with 5 photodiodes (red, green, + blue, clear and IR) with four configurable channels. Red and + green being always available and two out of the rest three + (blue, clear, IR) can be selected to be simultaneously measured. + Typical application is adjusting LCD backlight of TVs, + mobile phones and tablet PCs. + config ROHM_BU27034 tristate "ROHM BU27034 ambient light sensor" depends on I2C @@ -413,6 +427,17 @@ config OPT3001 If built as a dynamically linked module, it will be called opt3001. +config OPT4001 + tristate "Texas Instruments OPT4001 Light Sensor" + depends on I2C + select REGMAP_I2C + help + If you say Y or M here, you get support for Texas Instruments + OPT4001 Ambient Light Sensor. + + If built as a dynamically linked module, it will be called + opt4001. + config PA12203001 tristate "TXC PA12203001 light and proximity sensor" depends on I2C diff --git a/drivers/iio/light/Makefile b/drivers/iio/light/Makefile index 985f6feaccd4fc3cea4d9146d6785ec818ab1540..c0db4c4c36ec9f1ed9aefeb02fb583b94e361874 100644 --- a/drivers/iio/light/Makefile +++ b/drivers/iio/light/Makefile @@ -37,7 +37,9 @@ obj-$(CONFIG_MAX44000) += max44000.o obj-$(CONFIG_MAX44009) += max44009.o obj-$(CONFIG_NOA1305) += noa1305.o obj-$(CONFIG_OPT3001) += opt3001.o +obj-$(CONFIG_OPT4001) += opt4001.o obj-$(CONFIG_PA12203001) += pa12203001.o +obj-$(CONFIG_ROHM_BU27008) += rohm-bu27008.o obj-$(CONFIG_ROHM_BU27034) += rohm-bu27034.o obj-$(CONFIG_RPR0521) += rpr0521.o obj-$(CONFIG_SI1133) += si1133.o diff --git a/drivers/iio/light/adjd_s311.c b/drivers/iio/light/adjd_s311.c index 210a90f44c5323d2cccb635fd38e5ceece6233ab..5fd775a20176dbc3debffd1e9b9f0538869c684e 100644 --- a/drivers/iio/light/adjd_s311.c +++ b/drivers/iio/light/adjd_s311.c @@ -270,7 +270,7 @@ static struct i2c_driver adjd_s311_driver = { .driver = { .name = ADJD_S311_DRV_NAME, }, - .probe_new = adjd_s311_probe, + .probe = adjd_s311_probe, .id_table = adjd_s311_id, }; module_i2c_driver(adjd_s311_driver); diff --git a/drivers/iio/light/adux1020.c b/drivers/iio/light/adux1020.c index 606075350d01c559ea5ceee132855b5f2d5db05d..aa4a6c78f0aa86476fd0d26120e80542b6113f18 100644 --- a/drivers/iio/light/adux1020.c +++ b/drivers/iio/light/adux1020.c @@ -837,7 +837,7 @@ static struct i2c_driver adux1020_driver = { .name = ADUX1020_DRV_NAME, .of_match_table = adux1020_of_match, }, - .probe_new = adux1020_probe, + .probe = adux1020_probe, .id_table = adux1020_id, }; module_i2c_driver(adux1020_driver); diff --git a/drivers/iio/light/al3010.c b/drivers/iio/light/al3010.c index 69cc723e2ac4ad6b9b36d50f0f8d1f1f5493b093..8f0119f392b7051ce07abc746d7fdaf2e56c082f 100644 --- a/drivers/iio/light/al3010.c +++ b/drivers/iio/light/al3010.c @@ -229,7 +229,7 @@ static struct i2c_driver al3010_driver = { .of_match_table = al3010_of_match, .pm = pm_sleep_ptr(&al3010_pm_ops), }, - .probe_new = al3010_probe, + .probe = al3010_probe, .id_table = al3010_id, }; module_i2c_driver(al3010_driver); diff --git a/drivers/iio/light/al3320a.c b/drivers/iio/light/al3320a.c index 9ff28bbf34bbed0d8d6ec71b1f63b2d25a008178..d5957d85c27866e1997c7372425f0f75e80b0951 100644 --- a/drivers/iio/light/al3320a.c +++ b/drivers/iio/light/al3320a.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -247,13 +248,20 @@ static const struct of_device_id al3320a_of_match[] = { }; MODULE_DEVICE_TABLE(of, al3320a_of_match); +static const struct acpi_device_id al3320a_acpi_match[] = { + {"CALS0001"}, + { }, +}; +MODULE_DEVICE_TABLE(acpi, al3320a_acpi_match); + static struct i2c_driver al3320a_driver = { .driver = { .name = AL3320A_DRV_NAME, .of_match_table = al3320a_of_match, .pm = pm_sleep_ptr(&al3320a_pm_ops), + .acpi_match_table = al3320a_acpi_match, }, - .probe_new = al3320a_probe, + .probe = al3320a_probe, .id_table = al3320a_id, }; diff --git a/drivers/iio/light/apds9300.c b/drivers/iio/light/apds9300.c index 15dfb753734fa0ceea947128a39274eec166862e..0f978b30a232ca8f8c1462fa5382b0cda22b6abd 100644 --- a/drivers/iio/light/apds9300.c +++ b/drivers/iio/light/apds9300.c @@ -504,7 +504,7 @@ static struct i2c_driver apds9300_driver = { .name = APDS9300_DRV_NAME, .pm = pm_sleep_ptr(&apds9300_pm_ops), }, - .probe_new = apds9300_probe, + .probe = apds9300_probe, .remove = apds9300_remove, .id_table = apds9300_id, }; diff --git a/drivers/iio/light/apds9960.c b/drivers/iio/light/apds9960.c index cc5974a95bd3364995a991bd91edeea1dfacd7b2..1065a340b12bf9cb6984e9b95d711435e5c5a5a2 100644 --- a/drivers/iio/light/apds9960.c +++ b/drivers/iio/light/apds9960.c @@ -1131,7 +1131,7 @@ static struct i2c_driver apds9960_driver = { .pm = &apds9960_pm_ops, .acpi_match_table = apds9960_acpi_match, }, - .probe_new = apds9960_probe, + .probe = apds9960_probe, .remove = apds9960_remove, .id_table = apds9960_id, }; diff --git a/drivers/iio/light/as73211.c b/drivers/iio/light/as73211.c index 2307fc531752ba414403eddaa85d9c31d8cd28ff..ec97a3a468392d8b79207546d60114d2f85c98c1 100644 --- a/drivers/iio/light/as73211.c +++ b/drivers/iio/light/as73211.c @@ -790,7 +790,7 @@ static struct i2c_driver as73211_driver = { .of_match_table = as73211_of_match, .pm = pm_sleep_ptr(&as73211_pm_ops), }, - .probe_new = as73211_probe, + .probe = as73211_probe, .id_table = as73211_id, }; module_i2c_driver(as73211_driver); diff --git a/drivers/iio/light/bh1750.c b/drivers/iio/light/bh1750.c index 390c5b3ad4f6717ee3bb29bff44b6441c49c3921..4b869fa9e5b17ed179b2c357fff1cb244e9172f2 100644 --- a/drivers/iio/light/bh1750.c +++ b/drivers/iio/light/bh1750.c @@ -320,7 +320,7 @@ static struct i2c_driver bh1750_driver = { .of_match_table = bh1750_of_match, .pm = pm_sleep_ptr(&bh1750_pm_ops), }, - .probe_new = bh1750_probe, + .probe = bh1750_probe, .remove = bh1750_remove, .id_table = bh1750_id, diff --git a/drivers/iio/light/bh1780.c b/drivers/iio/light/bh1780.c index da9039e5a83918f364b00f9f761e1da2c4a0e071..b84166c5fa06eec1287856159ea1a7dd49fc587e 100644 --- a/drivers/iio/light/bh1780.c +++ b/drivers/iio/light/bh1780.c @@ -269,7 +269,7 @@ static const struct of_device_id of_bh1780_match[] = { MODULE_DEVICE_TABLE(of, of_bh1780_match); static struct i2c_driver bh1780_driver = { - .probe_new = bh1780_probe, + .probe = bh1780_probe, .remove = bh1780_remove, .id_table = bh1780_id, .driver = { diff --git a/drivers/iio/light/cm32181.c b/drivers/iio/light/cm32181.c index d4a34a3bf00d9503fbeff879f1a86278ad159d4e..9df85b3999fa88e4e7e0a6c2692de1ea748bb82b 100644 --- a/drivers/iio/light/cm32181.c +++ b/drivers/iio/light/cm32181.c @@ -542,7 +542,7 @@ static struct i2c_driver cm32181_driver = { .of_match_table = cm32181_of_match, .pm = pm_sleep_ptr(&cm32181_pm_ops), }, - .probe_new = cm32181_probe, + .probe = cm32181_probe, }; module_i2c_driver(cm32181_driver); diff --git a/drivers/iio/light/cm3232.c b/drivers/iio/light/cm3232.c index 43e492f5051d1718a6e0daa6e8947ea800ffa5a7..d48a70efca69ff87d70a93630a13a96f9ed00af2 100644 --- a/drivers/iio/light/cm3232.c +++ b/drivers/iio/light/cm3232.c @@ -417,7 +417,7 @@ static struct i2c_driver cm3232_driver = { .pm = pm_sleep_ptr(&cm3232_pm_ops), }, .id_table = cm3232_id, - .probe_new = cm3232_probe, + .probe = cm3232_probe, .remove = cm3232_remove, }; diff --git a/drivers/iio/light/cm3323.c b/drivers/iio/light/cm3323.c index e5ce7d0fd272e0f629e757541eff9b053a23ec27..35d20207a6481aa39eed6ab2fc1b0b5350c6d2ed 100644 --- a/drivers/iio/light/cm3323.c +++ b/drivers/iio/light/cm3323.c @@ -266,7 +266,7 @@ static struct i2c_driver cm3323_driver = { .name = CM3323_DRV_NAME, .of_match_table = cm3323_of_match, }, - .probe_new = cm3323_probe, + .probe = cm3323_probe, .id_table = cm3323_id, }; diff --git a/drivers/iio/light/cm36651.c b/drivers/iio/light/cm36651.c index 1707dbf2ce26784b5f62f1c7542de17d37717e32..97e559acba2b25947a2cfcb1e7e55d91dfbaaa1a 100644 --- a/drivers/iio/light/cm36651.c +++ b/drivers/iio/light/cm36651.c @@ -730,7 +730,7 @@ static struct i2c_driver cm36651_driver = { .name = "cm36651", .of_match_table = cm36651_of_match, }, - .probe_new = cm36651_probe, + .probe = cm36651_probe, .remove = cm36651_remove, .id_table = cm36651_id, }; diff --git a/drivers/iio/light/gp2ap002.c b/drivers/iio/light/gp2ap002.c index c0430db0038afde7db8fde3a5ca98ca27a355b05..fec10d5e037ec1739d0756d2b1e23212557702a6 100644 --- a/drivers/iio/light/gp2ap002.c +++ b/drivers/iio/light/gp2ap002.c @@ -710,7 +710,7 @@ static struct i2c_driver gp2ap002_driver = { .of_match_table = gp2ap002_of_match, .pm = pm_ptr(&gp2ap002_dev_pm_ops), }, - .probe_new = gp2ap002_probe, + .probe = gp2ap002_probe, .remove = gp2ap002_remove, .id_table = gp2ap002_id_table, }; diff --git a/drivers/iio/light/gp2ap020a00f.c b/drivers/iio/light/gp2ap020a00f.c index a5bf9da0d2f38f0335121b303b689e70545930fa..9f41724819b61260558d2368c65ea94ea1316b34 100644 --- a/drivers/iio/light/gp2ap020a00f.c +++ b/drivers/iio/light/gp2ap020a00f.c @@ -1609,7 +1609,7 @@ static struct i2c_driver gp2ap020a00f_driver = { .name = GP2A_I2C_NAME, .of_match_table = gp2ap020a00f_of_match, }, - .probe_new = gp2ap020a00f_probe, + .probe = gp2ap020a00f_probe, .remove = gp2ap020a00f_remove, .id_table = gp2ap020a00f_id, }; diff --git a/drivers/iio/light/isl29018.c b/drivers/iio/light/isl29018.c index 141845fb47f960e427c180c71dac9c5eeab35511..43484c18b1014237af9bd1e44086d2568bea338a 100644 --- a/drivers/iio/light/isl29018.c +++ b/drivers/iio/light/isl29018.c @@ -865,7 +865,7 @@ static struct i2c_driver isl29018_driver = { .pm = pm_sleep_ptr(&isl29018_pm_ops), .of_match_table = isl29018_of_match, }, - .probe_new = isl29018_probe, + .probe = isl29018_probe, .id_table = isl29018_id, }; module_i2c_driver(isl29018_driver); diff --git a/drivers/iio/light/isl29028.c b/drivers/iio/light/isl29028.c index bcf3a556e41ad711b8bbc279ae5a991086c31078..5694683389bec1c20f8fcc020f2971370ad19fa4 100644 --- a/drivers/iio/light/isl29028.c +++ b/drivers/iio/light/isl29028.c @@ -698,7 +698,7 @@ static struct i2c_driver isl29028_driver = { .pm = pm_ptr(&isl29028_pm_ops), .of_match_table = isl29028_of_match, }, - .probe_new = isl29028_probe, + .probe = isl29028_probe, .remove = isl29028_remove, .id_table = isl29028_id, }; diff --git a/drivers/iio/light/isl29125.c b/drivers/iio/light/isl29125.c index b4bd656ca16984459c1074c908c32ecc0cdd63cf..f1d3356d33697a4e4e24c57f593525d3038e216d 100644 --- a/drivers/iio/light/isl29125.c +++ b/drivers/iio/light/isl29125.c @@ -337,7 +337,7 @@ static struct i2c_driver isl29125_driver = { .name = ISL29125_DRV_NAME, .pm = pm_sleep_ptr(&isl29125_pm_ops), }, - .probe_new = isl29125_probe, + .probe = isl29125_probe, .remove = isl29125_remove, .id_table = isl29125_id, }; diff --git a/drivers/iio/light/jsa1212.c b/drivers/iio/light/jsa1212.c index d3834d0a0635aa034feb743fe4a90d900a9113c2..37e2807041a1dd3ca8fd90fb9daee73cbeb3b6a6 100644 --- a/drivers/iio/light/jsa1212.c +++ b/drivers/iio/light/jsa1212.c @@ -440,7 +440,7 @@ static struct i2c_driver jsa1212_driver = { .pm = pm_sleep_ptr(&jsa1212_pm_ops), .acpi_match_table = ACPI_PTR(jsa1212_acpi_match), }, - .probe_new = jsa1212_probe, + .probe = jsa1212_probe, .remove = jsa1212_remove, .id_table = jsa1212_id, }; diff --git a/drivers/iio/light/ltr501.c b/drivers/iio/light/ltr501.c index bdbd918213e45cfc402e1afcab88397c33796485..061c122fdc5e70f5c0e2f3abef1386536202cedf 100644 --- a/drivers/iio/light/ltr501.c +++ b/drivers/iio/light/ltr501.c @@ -1641,7 +1641,7 @@ static struct i2c_driver ltr501_driver = { .pm = pm_sleep_ptr(<r501_pm_ops), .acpi_match_table = ACPI_PTR(ltr_acpi_match), }, - .probe_new = ltr501_probe, + .probe = ltr501_probe, .remove = ltr501_remove, .id_table = ltr501_id, }; diff --git a/drivers/iio/light/ltrf216a.c b/drivers/iio/light/ltrf216a.c index 4b8ef36b691251f826b987784e63fb448d6add4c..8de4dd849936d403684159eb4a5e26698963e666 100644 --- a/drivers/iio/light/ltrf216a.c +++ b/drivers/iio/light/ltrf216a.c @@ -539,7 +539,7 @@ static struct i2c_driver ltrf216a_driver = { .pm = pm_ptr(<rf216a_pm_ops), .of_match_table = ltrf216a_of_match, }, - .probe_new = ltrf216a_probe, + .probe = ltrf216a_probe, .id_table = ltrf216a_id, }; module_i2c_driver(ltrf216a_driver); diff --git a/drivers/iio/light/lv0104cs.c b/drivers/iio/light/lv0104cs.c index c041fa0faa5df61cf0720fb02963a23eee29b105..a5445d58fddfc3a5c13b3f28f31e7f5ee843600d 100644 --- a/drivers/iio/light/lv0104cs.c +++ b/drivers/iio/light/lv0104cs.c @@ -520,7 +520,7 @@ static struct i2c_driver lv0104cs_i2c_driver = { .name = "lv0104cs", }, .id_table = lv0104cs_id, - .probe_new = lv0104cs_probe, + .probe = lv0104cs_probe, }; module_i2c_driver(lv0104cs_i2c_driver); diff --git a/drivers/iio/light/max44000.c b/drivers/iio/light/max44000.c index 5dcabc43a30e6e3694f505180ae614cc8ea8325f..db96c5b73100c6047f3a9a3f6f18240f6217e70f 100644 --- a/drivers/iio/light/max44000.c +++ b/drivers/iio/light/max44000.c @@ -616,7 +616,7 @@ static struct i2c_driver max44000_driver = { .name = MAX44000_DRV_NAME, .acpi_match_table = ACPI_PTR(max44000_acpi_match), }, - .probe_new = max44000_probe, + .probe = max44000_probe, .id_table = max44000_id, }; diff --git a/drivers/iio/light/max44009.c b/drivers/iio/light/max44009.c index 176dcad6e8e8a31d5616196be9b33627012a3aad..61ce276e86f7c242043eed65d8644dac7fb81126 100644 --- a/drivers/iio/light/max44009.c +++ b/drivers/iio/light/max44009.c @@ -544,7 +544,7 @@ static struct i2c_driver max44009_driver = { .name = MAX44009_DRV_NAME, .of_match_table = max44009_of_match, }, - .probe_new = max44009_probe, + .probe = max44009_probe, .id_table = max44009_id, }; module_i2c_driver(max44009_driver); diff --git a/drivers/iio/light/noa1305.c b/drivers/iio/light/noa1305.c index eaf548d4649ea9ea811e2d718c27fcdf73a47548..1574310020e3d5e7a8ee0fee2c2356fa77bea6d1 100644 --- a/drivers/iio/light/noa1305.c +++ b/drivers/iio/light/noa1305.c @@ -278,7 +278,7 @@ static struct i2c_driver noa1305_driver = { .name = NOA1305_DRIVER_NAME, .of_match_table = noa1305_of_match, }, - .probe_new = noa1305_probe, + .probe = noa1305_probe, .id_table = noa1305_ids, }; diff --git a/drivers/iio/light/opt3001.c b/drivers/iio/light/opt3001.c index ec4f5c2369c42640a2de69a026a6df6f4dba745c..cb41e5ee8ec10baa23d0bc9175656e035a4cad65 100644 --- a/drivers/iio/light/opt3001.c +++ b/drivers/iio/light/opt3001.c @@ -834,7 +834,7 @@ static const struct of_device_id opt3001_of_match[] = { MODULE_DEVICE_TABLE(of, opt3001_of_match); static struct i2c_driver opt3001_driver = { - .probe_new = opt3001_probe, + .probe = opt3001_probe, .remove = opt3001_remove, .id_table = opt3001_id, diff --git a/drivers/iio/light/opt4001.c b/drivers/iio/light/opt4001.c new file mode 100644 index 0000000000000000000000000000000000000000..502946bf9f946f9ef97ff3f60d81b89f55ebadf6 --- /dev/null +++ b/drivers/iio/light/opt4001.c @@ -0,0 +1,467 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2023 Axis Communications AB + * + * Datasheet: https://www.ti.com/lit/gpn/opt4001 + * + * Device driver for the Texas Instruments OPT4001. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* OPT4001 register set */ +#define OPT4001_LIGHT1_MSB 0x00 +#define OPT4001_LIGHT1_LSB 0x01 +#define OPT4001_CTRL 0x0A +#define OPT4001_DEVICE_ID 0x11 + +/* OPT4001 register mask */ +#define OPT4001_EXPONENT_MASK GENMASK(15, 12) +#define OPT4001_MSB_MASK GENMASK(11, 0) +#define OPT4001_LSB_MASK GENMASK(15, 8) +#define OPT4001_COUNTER_MASK GENMASK(7, 4) +#define OPT4001_CRC_MASK GENMASK(3, 0) + +/* OPT4001 device id mask */ +#define OPT4001_DEVICE_ID_MASK GENMASK(11, 0) + +/* OPT4001 control registers mask */ +#define OPT4001_CTRL_QWAKE_MASK GENMASK(15, 15) +#define OPT4001_CTRL_RANGE_MASK GENMASK(13, 10) +#define OPT4001_CTRL_CONV_TIME_MASK GENMASK(9, 6) +#define OPT4001_CTRL_OPER_MODE_MASK GENMASK(5, 4) +#define OPT4001_CTRL_LATCH_MASK GENMASK(3, 3) +#define OPT4001_CTRL_INT_POL_MASK GENMASK(2, 2) +#define OPT4001_CTRL_FAULT_COUNT GENMASK(0, 1) + +/* OPT4001 constants */ +#define OPT4001_DEVICE_ID_VAL 0x121 + +/* OPT4001 operating modes */ +#define OPT4001_CTRL_OPER_MODE_OFF 0x0 +#define OPT4001_CTRL_OPER_MODE_FORCED 0x1 +#define OPT4001_CTRL_OPER_MODE_ONE_SHOT 0x2 +#define OPT4001_CTRL_OPER_MODE_CONTINUOUS 0x3 + +/* OPT4001 conversion control register definitions */ +#define OPT4001_CTRL_CONVERSION_0_6MS 0x0 +#define OPT4001_CTRL_CONVERSION_1MS 0x1 +#define OPT4001_CTRL_CONVERSION_1_8MS 0x2 +#define OPT4001_CTRL_CONVERSION_3_4MS 0x3 +#define OPT4001_CTRL_CONVERSION_6_5MS 0x4 +#define OPT4001_CTRL_CONVERSION_12_7MS 0x5 +#define OPT4001_CTRL_CONVERSION_25MS 0x6 +#define OPT4001_CTRL_CONVERSION_50MS 0x7 +#define OPT4001_CTRL_CONVERSION_100MS 0x8 +#define OPT4001_CTRL_CONVERSION_200MS 0x9 +#define OPT4001_CTRL_CONVERSION_400MS 0xa +#define OPT4001_CTRL_CONVERSION_800MS 0xb + +/* OPT4001 scale light level range definitions */ +#define OPT4001_CTRL_LIGHT_SCALE_AUTO 12 + +/* OPT4001 default values */ +#define OPT4001_DEFAULT_CONVERSION_TIME OPT4001_CTRL_CONVERSION_800MS + +/* + * The different packaging of OPT4001 has different constants used when calculating + * lux values. + */ +struct opt4001_chip_info { + int mul; + int div; + const char *name; +}; + +struct opt4001_chip { + struct regmap *regmap; + struct i2c_client *client; + u8 int_time; + const struct opt4001_chip_info *chip_info; +}; + +static const struct opt4001_chip_info opt4001_sot_5x3_info = { + .mul = 4375, + .div = 10000000, + .name = "opt4001-sot-5x3" +}; + +static const struct opt4001_chip_info opt4001_picostar_info = { + .mul = 3125, + .div = 10000000, + .name = "opt4001-picostar" +}; + +static const int opt4001_int_time_available[][2] = { + { 0, 600 }, + { 0, 1000 }, + { 0, 1800 }, + { 0, 3400 }, + { 0, 6500 }, + { 0, 12700 }, + { 0, 25000 }, + { 0, 50000 }, + { 0, 100000 }, + { 0, 200000 }, + { 0, 400000 }, + { 0, 800000 }, +}; + +/* + * Conversion time is integration time + time to set register + * this is used as integration time. + */ +static const int opt4001_int_time_reg[][2] = { + { 600, OPT4001_CTRL_CONVERSION_0_6MS }, + { 1000, OPT4001_CTRL_CONVERSION_1MS }, + { 1800, OPT4001_CTRL_CONVERSION_1_8MS }, + { 3400, OPT4001_CTRL_CONVERSION_3_4MS }, + { 6500, OPT4001_CTRL_CONVERSION_6_5MS }, + { 12700, OPT4001_CTRL_CONVERSION_12_7MS }, + { 25000, OPT4001_CTRL_CONVERSION_25MS }, + { 50000, OPT4001_CTRL_CONVERSION_50MS }, + { 100000, OPT4001_CTRL_CONVERSION_100MS }, + { 200000, OPT4001_CTRL_CONVERSION_200MS }, + { 400000, OPT4001_CTRL_CONVERSION_400MS }, + { 800000, OPT4001_CTRL_CONVERSION_800MS }, +}; + +static int opt4001_als_time_to_index(const u32 als_integration_time) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(opt4001_int_time_available); i++) { + if (als_integration_time == opt4001_int_time_available[i][1]) + return i; + } + + return -EINVAL; +} + +static u8 opt4001_calculate_crc(u8 exp, u32 mantissa, u8 count) +{ + u8 crc; + + crc = (hweight32(mantissa) + hweight32(exp) + hweight32(count)) % 2; + crc |= ((hweight32(mantissa & 0xAAAAA) + hweight32(exp & 0xA) + + hweight32(count & 0xA)) % 2) << 1; + crc |= ((hweight32(mantissa & 0x88888) + hweight32(exp & 0x8) + + hweight32(count & 0x8)) % 2) << 2; + crc |= (hweight32(mantissa & 0x80808) % 2) << 3; + + return crc; +} + +static int opt4001_read_lux_value(struct iio_dev *indio_dev, + int *val, int *val2) +{ + struct opt4001_chip *chip = iio_priv(indio_dev); + struct device *dev = &chip->client->dev; + unsigned int light1; + unsigned int light2; + u16 msb; + u16 lsb; + u8 exp; + u8 count; + u8 crc; + u8 calc_crc; + u64 lux_raw; + int ret; + + ret = regmap_read(chip->regmap, OPT4001_LIGHT1_MSB, &light1); + if (ret < 0) { + dev_err(dev, "Failed to read data bytes"); + return ret; + } + + ret = regmap_read(chip->regmap, OPT4001_LIGHT1_LSB, &light2); + if (ret < 0) { + dev_err(dev, "Failed to read data bytes"); + return ret; + } + + count = FIELD_GET(OPT4001_COUNTER_MASK, light2); + exp = FIELD_GET(OPT4001_EXPONENT_MASK, light1); + crc = FIELD_GET(OPT4001_CRC_MASK, light2); + msb = FIELD_GET(OPT4001_MSB_MASK, light1); + lsb = FIELD_GET(OPT4001_LSB_MASK, light2); + lux_raw = (msb << 8) + lsb; + calc_crc = opt4001_calculate_crc(exp, lux_raw, count); + if (calc_crc != crc) + return -EIO; + + lux_raw = lux_raw << exp; + lux_raw = lux_raw * chip->chip_info->mul; + *val = div_u64_rem(lux_raw, chip->chip_info->div, val2); + *val2 = *val2 * 100; + + return IIO_VAL_INT_PLUS_NANO; +} + +static int opt4001_set_conf(struct opt4001_chip *chip) +{ + struct device *dev = &chip->client->dev; + u16 reg; + int ret; + + reg = FIELD_PREP(OPT4001_CTRL_RANGE_MASK, OPT4001_CTRL_LIGHT_SCALE_AUTO); + reg |= FIELD_PREP(OPT4001_CTRL_CONV_TIME_MASK, chip->int_time); + reg |= FIELD_PREP(OPT4001_CTRL_OPER_MODE_MASK, OPT4001_CTRL_OPER_MODE_CONTINUOUS); + + ret = regmap_write(chip->regmap, OPT4001_CTRL, reg); + if (ret) + dev_err(dev, "Failed to set configuration\n"); + + return ret; +} + +static int opt4001_power_down(struct opt4001_chip *chip) +{ + struct device *dev = &chip->client->dev; + int ret; + unsigned int reg; + + ret = regmap_read(chip->regmap, OPT4001_DEVICE_ID, ®); + if (ret) { + dev_err(dev, "Failed to read configuration\n"); + return ret; + } + + /* MODE_OFF is 0x0 so just set bits to 0 */ + reg &= ~OPT4001_CTRL_OPER_MODE_MASK; + + ret = regmap_write(chip->regmap, OPT4001_CTRL, reg); + if (ret) + dev_err(dev, "Failed to set configuration to power down\n"); + + return ret; +} + +static void opt4001_chip_off_action(void *data) +{ + struct opt4001_chip *chip = data; + + opt4001_power_down(chip); +} + +static const struct iio_chan_spec opt4001_channels[] = { + { + .type = IIO_LIGHT, + .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), + .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_INT_TIME), + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_INT_TIME) + }, +}; + +static int opt4001_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct opt4001_chip *chip = iio_priv(indio_dev); + + switch (mask) { + case IIO_CHAN_INFO_PROCESSED: + return opt4001_read_lux_value(indio_dev, val, val2); + case IIO_CHAN_INFO_INT_TIME: + *val = 0; + *val2 = opt4001_int_time_reg[chip->int_time][0]; + return IIO_VAL_INT_PLUS_MICRO; + default: + return -EINVAL; + } +} + +static int opt4001_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, int val2, long mask) +{ + struct opt4001_chip *chip = iio_priv(indio_dev); + int int_time; + + switch (mask) { + case IIO_CHAN_INFO_INT_TIME: + int_time = opt4001_als_time_to_index(val2); + if (int_time < 0) + return int_time; + chip->int_time = int_time; + return opt4001_set_conf(chip); + default: + return -EINVAL; + } +} + +static int opt4001_read_available(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + const int **vals, int *type, int *length, + long mask) +{ + switch (mask) { + case IIO_CHAN_INFO_INT_TIME: + *length = ARRAY_SIZE(opt4001_int_time_available) * 2; + *vals = (const int *)opt4001_int_time_available; + *type = IIO_VAL_INT_PLUS_MICRO; + return IIO_AVAIL_LIST; + + default: + return -EINVAL; + } +} + +static const struct iio_info opt4001_info_no_irq = { + .read_raw = opt4001_read_raw, + .write_raw = opt4001_write_raw, + .read_avail = opt4001_read_available, +}; + +static int opt4001_load_defaults(struct opt4001_chip *chip) +{ + chip->int_time = OPT4001_DEFAULT_CONVERSION_TIME; + + return opt4001_set_conf(chip); +} + +static bool opt4001_readable_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case OPT4001_LIGHT1_MSB: + case OPT4001_LIGHT1_LSB: + case OPT4001_CTRL: + case OPT4001_DEVICE_ID: + return true; + default: + return false; + } +} + +static bool opt4001_writable_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case OPT4001_CTRL: + return true; + default: + return false; + } +} + +static bool opt4001_volatile_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case OPT4001_LIGHT1_MSB: + case OPT4001_LIGHT1_LSB: + return true; + default: + return false; + } +} + +static const struct regmap_config opt4001_regmap_config = { + .name = "opt4001", + .reg_bits = 8, + .val_bits = 16, + .cache_type = REGCACHE_RBTREE, + .max_register = OPT4001_DEVICE_ID, + .readable_reg = opt4001_readable_reg, + .writeable_reg = opt4001_writable_reg, + .volatile_reg = opt4001_volatile_reg, + .val_format_endian = REGMAP_ENDIAN_BIG, +}; + +static int opt4001_probe(struct i2c_client *client) +{ + struct opt4001_chip *chip; + struct iio_dev *indio_dev; + int ret; + uint dev_id; + + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*chip)); + if (!indio_dev) + return -ENOMEM; + + chip = iio_priv(indio_dev); + + ret = devm_regulator_get_enable(&client->dev, "vdd"); + if (ret) + return dev_err_probe(&client->dev, ret, "Failed to enable vdd supply\n"); + + chip->regmap = devm_regmap_init_i2c(client, &opt4001_regmap_config); + if (IS_ERR(chip->regmap)) + return dev_err_probe(&client->dev, PTR_ERR(chip->regmap), + "regmap initialization failed\n"); + chip->client = client; + + indio_dev->info = &opt4001_info_no_irq; + + ret = regmap_reinit_cache(chip->regmap, &opt4001_regmap_config); + if (ret) + return dev_err_probe(&client->dev, ret, + "failed to reinit regmap cache\n"); + + ret = regmap_read(chip->regmap, OPT4001_DEVICE_ID, &dev_id); + if (ret < 0) + return dev_err_probe(&client->dev, ret, + "Failed to read the device ID register\n"); + + dev_id = FIELD_GET(OPT4001_DEVICE_ID_MASK, dev_id); + if (dev_id != OPT4001_DEVICE_ID_VAL) + dev_warn(&client->dev, "Device ID: %#04x unknown\n", dev_id); + + chip->chip_info = device_get_match_data(&client->dev); + + indio_dev->channels = opt4001_channels; + indio_dev->num_channels = ARRAY_SIZE(opt4001_channels); + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->name = chip->chip_info->name; + + ret = opt4001_load_defaults(chip); + if (ret < 0) + return dev_err_probe(&client->dev, ret, + "Failed to set sensor defaults\n"); + + ret = devm_add_action_or_reset(&client->dev, + opt4001_chip_off_action, + chip); + if (ret < 0) + return dev_err_probe(&client->dev, ret, + "Failed to setup power off action\n"); + + return devm_iio_device_register(&client->dev, indio_dev); +} + +/* + * The compatible string determines which constants to use depending on + * opt4001 packaging + */ +static const struct i2c_device_id opt4001_id[] = { + { "opt4001-sot-5x3", (kernel_ulong_t)&opt4001_sot_5x3_info }, + { "opt4001-picostar", (kernel_ulong_t)&opt4001_picostar_info }, + { } +}; +MODULE_DEVICE_TABLE(i2c, opt4001_id); + +static const struct of_device_id opt4001_of_match[] = { + { .compatible = "ti,opt4001-sot-5x3", .data = &opt4001_sot_5x3_info}, + { .compatible = "ti,opt4001-picostar", .data = &opt4001_picostar_info}, + {} +}; +MODULE_DEVICE_TABLE(of, opt4001_of_match); + +static struct i2c_driver opt4001_driver = { + .driver = { + .name = "opt4001", + .of_match_table = opt4001_of_match, + }, + .probe = opt4001_probe, + .id_table = opt4001_id, +}; +module_i2c_driver(opt4001_driver); + +MODULE_AUTHOR("Stefan Windfeldt-Prytz "); +MODULE_DESCRIPTION("Texas Instruments opt4001 ambient light sensor driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/iio/light/pa12203001.c b/drivers/iio/light/pa12203001.c index 15a666f15c275f23f44390c2807efcd75aedde83..ed241598aefbe41c7b70f648e8df8c13e01140a3 100644 --- a/drivers/iio/light/pa12203001.c +++ b/drivers/iio/light/pa12203001.c @@ -474,7 +474,7 @@ static struct i2c_driver pa12203001_driver = { .pm = &pa12203001_pm_ops, .acpi_match_table = ACPI_PTR(pa12203001_acpi_match), }, - .probe_new = pa12203001_probe, + .probe = pa12203001_probe, .remove = pa12203001_remove, .id_table = pa12203001_id, diff --git a/drivers/iio/light/rohm-bu27008.c b/drivers/iio/light/rohm-bu27008.c new file mode 100644 index 0000000000000000000000000000000000000000..489902bed7f0ec3bb4d32adf07d4947f10cb431b --- /dev/null +++ b/drivers/iio/light/rohm-bu27008.c @@ -0,0 +1,1026 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * BU27008 ROHM Colour Sensor + * + * Copyright (c) 2023, ROHM Semiconductor. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#define BU27008_REG_SYSTEM_CONTROL 0x40 +#define BU27008_MASK_SW_RESET BIT(7) +#define BU27008_MASK_PART_ID GENMASK(5, 0) +#define BU27008_ID 0x1a +#define BU27008_REG_MODE_CONTROL1 0x41 +#define BU27008_MASK_MEAS_MODE GENMASK(2, 0) +#define BU27008_MASK_CHAN_SEL GENMASK(3, 2) + +#define BU27008_REG_MODE_CONTROL2 0x42 +#define BU27008_MASK_RGBC_GAIN GENMASK(7, 3) +#define BU27008_MASK_IR_GAIN_LO GENMASK(2, 0) +#define BU27008_SHIFT_IR_GAIN 3 + +#define BU27008_REG_MODE_CONTROL3 0x43 +#define BU27008_MASK_VALID BIT(7) +#define BU27008_MASK_INT_EN BIT(1) +#define BU27008_INT_EN BU27008_MASK_INT_EN +#define BU27008_INT_DIS 0 +#define BU27008_MASK_MEAS_EN BIT(0) +#define BU27008_MEAS_EN BIT(0) +#define BU27008_MEAS_DIS 0 + +#define BU27008_REG_DATA0_LO 0x50 +#define BU27008_REG_DATA1_LO 0x52 +#define BU27008_REG_DATA2_LO 0x54 +#define BU27008_REG_DATA3_LO 0x56 +#define BU27008_REG_DATA3_HI 0x57 +#define BU27008_REG_MANUFACTURER_ID 0x92 +#define BU27008_REG_MAX BU27008_REG_MANUFACTURER_ID + +/** + * enum bu27008_chan_type - BU27008 channel types + * @BU27008_RED: Red channel. Always via data0. + * @BU27008_GREEN: Green channel. Always via data1. + * @BU27008_BLUE: Blue channel. Via data2 (when used). + * @BU27008_CLEAR: Clear channel. Via data2 or data3 (when used). + * @BU27008_IR: IR channel. Via data3 (when used). + * @BU27008_NUM_CHANS: Number of channel types. + */ +enum bu27008_chan_type { + BU27008_RED, + BU27008_GREEN, + BU27008_BLUE, + BU27008_CLEAR, + BU27008_IR, + BU27008_NUM_CHANS +}; + +/** + * enum bu27008_chan - BU27008 physical data channel + * @BU27008_DATA0: Always red. + * @BU27008_DATA1: Always green. + * @BU27008_DATA2: Blue or clear. + * @BU27008_DATA3: IR or clear. + * @BU27008_NUM_HW_CHANS: Number of physical channels + */ +enum bu27008_chan { + BU27008_DATA0, + BU27008_DATA1, + BU27008_DATA2, + BU27008_DATA3, + BU27008_NUM_HW_CHANS +}; + +/* We can always measure red and green at same time */ +#define ALWAYS_SCANNABLE (BIT(BU27008_RED) | BIT(BU27008_GREEN)) + +/* We use these data channel configs. Ensure scan_masks below follow them too */ +#define BU27008_BLUE2_CLEAR3 0x0 /* buffer is R, G, B, C */ +#define BU27008_CLEAR2_IR3 0x1 /* buffer is R, G, C, IR */ +#define BU27008_BLUE2_IR3 0x2 /* buffer is R, G, B, IR */ + +static const unsigned long bu27008_scan_masks[] = { + /* buffer is R, G, B, C */ + ALWAYS_SCANNABLE | BIT(BU27008_BLUE) | BIT(BU27008_CLEAR), + /* buffer is R, G, C, IR */ + ALWAYS_SCANNABLE | BIT(BU27008_CLEAR) | BIT(BU27008_IR), + /* buffer is R, G, B, IR */ + ALWAYS_SCANNABLE | BIT(BU27008_BLUE) | BIT(BU27008_IR), + 0 +}; + +/* + * Available scales with gain 1x - 1024x, timings 55, 100, 200, 400 mS + * Time impacts to gain: 1x, 2x, 4x, 8x. + * + * => Max total gain is HWGAIN * gain by integration time (8 * 1024) = 8192 + * + * Max amplification is (HWGAIN * MAX integration-time multiplier) 1024 * 8 + * = 8192. With NANO scale we get rid of accuracy loss when we start with the + * scale 16.0 for HWGAIN1, INT-TIME 55 mS. This way the nano scale for MAX + * total gain 8192 will be 1953125 + */ +#define BU27008_SCALE_1X 16 + +/* See the data sheet for the "Gain Setting" table */ +#define BU27008_GSEL_1X 0x00 +#define BU27008_GSEL_4X 0x08 +#define BU27008_GSEL_8X 0x09 +#define BU27008_GSEL_16X 0x0a +#define BU27008_GSEL_32X 0x0b +#define BU27008_GSEL_64X 0x0c +#define BU27008_GSEL_256X 0x18 +#define BU27008_GSEL_512X 0x19 +#define BU27008_GSEL_1024X 0x1a + +static const struct iio_gain_sel_pair bu27008_gains[] = { + GAIN_SCALE_GAIN(1, BU27008_GSEL_1X), + GAIN_SCALE_GAIN(4, BU27008_GSEL_4X), + GAIN_SCALE_GAIN(8, BU27008_GSEL_8X), + GAIN_SCALE_GAIN(16, BU27008_GSEL_16X), + GAIN_SCALE_GAIN(32, BU27008_GSEL_32X), + GAIN_SCALE_GAIN(64, BU27008_GSEL_64X), + GAIN_SCALE_GAIN(256, BU27008_GSEL_256X), + GAIN_SCALE_GAIN(512, BU27008_GSEL_512X), + GAIN_SCALE_GAIN(1024, BU27008_GSEL_1024X), +}; + +static const struct iio_gain_sel_pair bu27008_gains_ir[] = { + GAIN_SCALE_GAIN(2, BU27008_GSEL_1X), + GAIN_SCALE_GAIN(4, BU27008_GSEL_4X), + GAIN_SCALE_GAIN(8, BU27008_GSEL_8X), + GAIN_SCALE_GAIN(16, BU27008_GSEL_16X), + GAIN_SCALE_GAIN(32, BU27008_GSEL_32X), + GAIN_SCALE_GAIN(64, BU27008_GSEL_64X), + GAIN_SCALE_GAIN(256, BU27008_GSEL_256X), + GAIN_SCALE_GAIN(512, BU27008_GSEL_512X), + GAIN_SCALE_GAIN(1024, BU27008_GSEL_1024X), +}; + +#define BU27008_MEAS_MODE_100MS 0x00 +#define BU27008_MEAS_MODE_55MS 0x01 +#define BU27008_MEAS_MODE_200MS 0x02 +#define BU27008_MEAS_MODE_400MS 0x04 +#define BU27008_MEAS_TIME_MAX_MS 400 + +static const struct iio_itime_sel_mul bu27008_itimes[] = { + GAIN_SCALE_ITIME_US(400000, BU27008_MEAS_MODE_400MS, 8), + GAIN_SCALE_ITIME_US(200000, BU27008_MEAS_MODE_200MS, 4), + GAIN_SCALE_ITIME_US(100000, BU27008_MEAS_MODE_100MS, 2), + GAIN_SCALE_ITIME_US(55000, BU27008_MEAS_MODE_55MS, 1), +}; + +/* + * All the RGBC channels share the same gain. + * IR gain can be fine-tuned from the gain set for the RGBC by 2 bit, but this + * would yield quite complex gain setting. Especially since not all bit + * compinations are supported. And in any case setting GAIN for RGBC will + * always also change the IR-gain. + * + * On top of this, the selector '0' which corresponds to hw-gain 1X on RGBC, + * corresponds to gain 2X on IR. Rest of the selctors correspond to same gains + * though. This, however, makes it not possible to use shared gain for all + * RGBC and IR settings even though they are all changed at the one go. + */ +#define BU27008_CHAN(color, data, separate_avail) \ +{ \ + .type = IIO_INTENSITY, \ + .modified = 1, \ + .channel2 = IIO_MOD_LIGHT_##color, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ + BIT(IIO_CHAN_INFO_SCALE), \ + .info_mask_separate_available = (separate_avail), \ + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_INT_TIME), \ + .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_INT_TIME), \ + .address = BU27008_REG_##data##_LO, \ + .scan_index = BU27008_##color, \ + .scan_type = { \ + .sign = 's', \ + .realbits = 16, \ + .storagebits = 16, \ + .endianness = IIO_LE, \ + }, \ +} + +/* For raw reads we always configure DATA3 for CLEAR */ +static const struct iio_chan_spec bu27008_channels[] = { + BU27008_CHAN(RED, DATA0, BIT(IIO_CHAN_INFO_SCALE)), + BU27008_CHAN(GREEN, DATA1, BIT(IIO_CHAN_INFO_SCALE)), + BU27008_CHAN(BLUE, DATA2, BIT(IIO_CHAN_INFO_SCALE)), + BU27008_CHAN(CLEAR, DATA2, BIT(IIO_CHAN_INFO_SCALE)), + /* + * We don't allow setting scale for IR (because of shared gain bits). + * Hence we don't advertise available ones either. + */ + BU27008_CHAN(IR, DATA3, 0), + IIO_CHAN_SOFT_TIMESTAMP(BU27008_NUM_CHANS), +}; + +struct bu27008_data { + struct regmap *regmap; + struct iio_trigger *trig; + struct device *dev; + struct iio_gts gts; + struct iio_gts gts_ir; + int irq; + + /* + * Prevent changing gain/time config when scale is read/written. + * Similarly, protect the integration_time read/change sequence. + * Prevent changing gain/time when data is read. + */ + struct mutex mutex; +}; + +static const struct regmap_range bu27008_volatile_ranges[] = { + { + .range_min = BU27008_REG_SYSTEM_CONTROL, /* SWRESET */ + .range_max = BU27008_REG_SYSTEM_CONTROL, + }, { + .range_min = BU27008_REG_MODE_CONTROL3, /* VALID */ + .range_max = BU27008_REG_MODE_CONTROL3, + }, { + .range_min = BU27008_REG_DATA0_LO, /* DATA */ + .range_max = BU27008_REG_DATA3_HI, + }, +}; + +static const struct regmap_access_table bu27008_volatile_regs = { + .yes_ranges = &bu27008_volatile_ranges[0], + .n_yes_ranges = ARRAY_SIZE(bu27008_volatile_ranges), +}; + +static const struct regmap_range bu27008_read_only_ranges[] = { + { + .range_min = BU27008_REG_DATA0_LO, + .range_max = BU27008_REG_DATA3_HI, + }, { + .range_min = BU27008_REG_MANUFACTURER_ID, + .range_max = BU27008_REG_MANUFACTURER_ID, + }, +}; + +static const struct regmap_access_table bu27008_ro_regs = { + .no_ranges = &bu27008_read_only_ranges[0], + .n_no_ranges = ARRAY_SIZE(bu27008_read_only_ranges), +}; + +static const struct regmap_config bu27008_regmap = { + .reg_bits = 8, + .val_bits = 8, + .max_register = BU27008_REG_MAX, + .cache_type = REGCACHE_RBTREE, + .volatile_table = &bu27008_volatile_regs, + .wr_table = &bu27008_ro_regs, + /* + * All register writes are serialized by the mutex which protects the + * scale setting/getting. This is needed because scale is combined by + * gain and integration time settings and we need to ensure those are + * not read / written when scale is being computed. + * + * As a result of this serializing, we don't need regmap locking. Note, + * this is not true if we add any configurations which are not + * serialized by the mutex and which may need for example a protected + * read-modify-write cycle (eg. regmap_update_bits()). Please, revise + * this when adding features to the driver. + */ + .disable_locking = true, +}; + +#define BU27008_MAX_VALID_RESULT_WAIT_US 50000 +#define BU27008_VALID_RESULT_WAIT_QUANTA_US 1000 + +static int bu27008_chan_read_data(struct bu27008_data *data, int reg, int *val) +{ + int ret, valid; + __le16 tmp; + + ret = regmap_read_poll_timeout(data->regmap, BU27008_REG_MODE_CONTROL3, + valid, (valid & BU27008_MASK_VALID), + BU27008_VALID_RESULT_WAIT_QUANTA_US, + BU27008_MAX_VALID_RESULT_WAIT_US); + if (ret) + return ret; + + ret = regmap_bulk_read(data->regmap, reg, &tmp, sizeof(tmp)); + if (ret) + dev_err(data->dev, "Reading channel data failed\n"); + + *val = le16_to_cpu(tmp); + + return ret; +} + +static int bu27008_get_gain(struct bu27008_data *data, struct iio_gts *gts, int *gain) +{ + int ret, sel; + + ret = regmap_read(data->regmap, BU27008_REG_MODE_CONTROL2, &sel); + if (ret) + return ret; + + sel = FIELD_GET(BU27008_MASK_RGBC_GAIN, sel); + + ret = iio_gts_find_gain_by_sel(gts, sel); + if (ret < 0) { + dev_err(data->dev, "unknown gain value 0x%x\n", sel); + return ret; + } + + *gain = ret; + + return 0; +} + +static int bu27008_write_gain_sel(struct bu27008_data *data, int sel) +{ + int regval; + + regval = FIELD_PREP(BU27008_MASK_RGBC_GAIN, sel); + + /* + * We do always set also the LOW bits of IR-gain because othervice we + * would risk resulting an invalid GAIN register value. + * + * We could allow setting separate gains for RGBC and IR when the + * values were such that HW could support both gain settings. + * Eg, when the shared bits were same for both gain values. + * + * This, however, has a negligible benefit compared to the increased + * software complexity when we would need to go through the gains + * for both channels separately when the integration time changes. + * This would end up with nasty logic for computing gain values for + * both channels - and rejecting them if shared bits changed. + * + * We should then build the logic by guessing what a user prefers. + * RGBC or IR gains correctly set while other jumps to odd value? + * Maybe look-up a value where both gains are somehow optimized + * . Or maybe user would + * expect us to reject changes when optimal gains can't be set to both + * channels w/given integration time. At best that would result + * solution that works well for a very specific subset of + * configurations but causes unexpected corner-cases. + * + * So, we keep it simple. Always set same selector to IR and RGBC. + * We disallow setting IR (as I expect that most of the users are + * interested in RGBC). This way we can show the user that the scales + * for RGBC and IR channels are different (1X Vs 2X with sel 0) while + * still keeping the operation deterministic. + */ + regval |= FIELD_PREP(BU27008_MASK_IR_GAIN_LO, sel); + + return regmap_update_bits(data->regmap, BU27008_REG_MODE_CONTROL2, + BU27008_MASK_RGBC_GAIN, regval); +} + +static int bu27008_set_gain(struct bu27008_data *data, int gain) +{ + int ret; + + ret = iio_gts_find_sel_by_gain(&data->gts, gain); + if (ret < 0) + return ret; + + return bu27008_write_gain_sel(data, ret); +} + +static int bu27008_get_int_time_sel(struct bu27008_data *data, int *sel) +{ + int ret, val; + + ret = regmap_read(data->regmap, BU27008_REG_MODE_CONTROL1, &val); + *sel = FIELD_GET(BU27008_MASK_MEAS_MODE, val); + + return ret; +} + +static int bu27008_set_int_time_sel(struct bu27008_data *data, int sel) +{ + return regmap_update_bits(data->regmap, BU27008_REG_MODE_CONTROL1, + BU27008_MASK_MEAS_MODE, sel); +} + +static int bu27008_get_int_time_us(struct bu27008_data *data) +{ + int ret, sel; + + ret = bu27008_get_int_time_sel(data, &sel); + if (ret) + return ret; + + return iio_gts_find_int_time_by_sel(&data->gts, sel); +} + +static int _bu27008_get_scale(struct bu27008_data *data, bool ir, int *val, + int *val2) +{ + struct iio_gts *gts; + int gain, ret; + + if (ir) + gts = &data->gts_ir; + else + gts = &data->gts; + + ret = bu27008_get_gain(data, gts, &gain); + if (ret) + return ret; + + ret = bu27008_get_int_time_us(data); + if (ret < 0) + return ret; + + return iio_gts_get_scale(gts, gain, ret, val, val2); +} + +static int bu27008_get_scale(struct bu27008_data *data, bool ir, int *val, + int *val2) +{ + int ret; + + mutex_lock(&data->mutex); + ret = _bu27008_get_scale(data, ir, val, val2); + mutex_unlock(&data->mutex); + + return ret; +} + +static int bu27008_set_int_time(struct bu27008_data *data, int time) +{ + int ret; + + ret = iio_gts_find_sel_by_int_time(&data->gts, time); + if (ret < 0) + return ret; + + return regmap_update_bits(data->regmap, BU27008_REG_MODE_CONTROL1, + BU27008_MASK_MEAS_MODE, ret); +} + +/* Try to change the time so that the scale is maintained */ +static int bu27008_try_set_int_time(struct bu27008_data *data, int int_time_new) +{ + int ret, old_time_sel, new_time_sel, old_gain, new_gain; + + mutex_lock(&data->mutex); + + ret = bu27008_get_int_time_sel(data, &old_time_sel); + if (ret < 0) + goto unlock_out; + + if (!iio_gts_valid_time(&data->gts, int_time_new)) { + dev_dbg(data->dev, "Unsupported integration time %u\n", + int_time_new); + + ret = -EINVAL; + goto unlock_out; + } + + /* If we already use requested time, then we're done */ + new_time_sel = iio_gts_find_sel_by_int_time(&data->gts, int_time_new); + if (new_time_sel == old_time_sel) + goto unlock_out; + + ret = bu27008_get_gain(data, &data->gts, &old_gain); + if (ret) + goto unlock_out; + + ret = iio_gts_find_new_gain_sel_by_old_gain_time(&data->gts, old_gain, + old_time_sel, new_time_sel, &new_gain); + if (ret) { + int scale1, scale2; + bool ok; + + _bu27008_get_scale(data, false, &scale1, &scale2); + dev_dbg(data->dev, + "Can't support time %u with current scale %u %u\n", + int_time_new, scale1, scale2); + + if (new_gain < 0) + goto unlock_out; + + /* + * If caller requests for integration time change and we + * can't support the scale - then the caller should be + * prepared to 'pick up the pieces and deal with the + * fact that the scale changed'. + */ + ret = iio_find_closest_gain_low(&data->gts, new_gain, &ok); + if (!ok) + dev_dbg(data->dev, "optimal gain out of range\n"); + + if (ret < 0) { + dev_dbg(data->dev, + "Total gain increase. Risk of saturation"); + ret = iio_gts_get_min_gain(&data->gts); + if (ret < 0) + goto unlock_out; + } + new_gain = ret; + dev_dbg(data->dev, "scale changed, new gain %u\n", new_gain); + } + + ret = bu27008_set_gain(data, new_gain); + if (ret) + goto unlock_out; + + ret = bu27008_set_int_time(data, int_time_new); + +unlock_out: + mutex_unlock(&data->mutex); + + return ret; +} + +static int bu27008_meas_set(struct bu27008_data *data, int state) +{ + return regmap_update_bits(data->regmap, BU27008_REG_MODE_CONTROL3, + BU27008_MASK_MEAS_EN, state); +} + +static int bu27008_chan_cfg(struct bu27008_data *data, + struct iio_chan_spec const *chan) +{ + int chan_sel; + + if (chan->scan_index == BU27008_BLUE) + chan_sel = BU27008_BLUE2_CLEAR3; + else + chan_sel = BU27008_CLEAR2_IR3; + + chan_sel = FIELD_PREP(BU27008_MASK_CHAN_SEL, chan_sel); + + return regmap_update_bits(data->regmap, BU27008_REG_MODE_CONTROL3, + BU27008_MASK_CHAN_SEL, chan_sel); +} + +static int bu27008_read_one(struct bu27008_data *data, struct iio_dev *idev, + struct iio_chan_spec const *chan, int *val, int *val2) +{ + int ret, int_time; + + ret = bu27008_chan_cfg(data, chan); + if (ret) + return ret; + + ret = bu27008_meas_set(data, BU27008_MEAS_EN); + if (ret) + return ret; + + ret = bu27008_get_int_time_us(data); + if (ret < 0) + int_time = BU27008_MEAS_TIME_MAX_MS; + else + int_time = ret / USEC_PER_MSEC; + + msleep(int_time); + + ret = bu27008_chan_read_data(data, chan->address, val); + if (!ret) + ret = IIO_VAL_INT; + + if (bu27008_meas_set(data, BU27008_MEAS_DIS)) + dev_warn(data->dev, "measurement disabling failed\n"); + + return ret; +} + +static int bu27008_read_raw(struct iio_dev *idev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct bu27008_data *data = iio_priv(idev); + int busy, ret; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + busy = iio_device_claim_direct_mode(idev); + if (busy) + return -EBUSY; + + mutex_lock(&data->mutex); + ret = bu27008_read_one(data, idev, chan, val, val2); + mutex_unlock(&data->mutex); + + iio_device_release_direct_mode(idev); + + return ret; + + case IIO_CHAN_INFO_SCALE: + ret = bu27008_get_scale(data, chan->scan_index == BU27008_IR, + val, val2); + if (ret) + return ret; + + return IIO_VAL_INT_PLUS_NANO; + + case IIO_CHAN_INFO_INT_TIME: + ret = bu27008_get_int_time_us(data); + if (ret < 0) + return ret; + + *val = 0; + *val2 = ret; + + return IIO_VAL_INT_PLUS_MICRO; + + default: + return -EINVAL; + } +} + +/* Called if the new scale could not be supported with existing int-time */ +static int bu27008_try_find_new_time_gain(struct bu27008_data *data, int val, + int val2, int *gain_sel) +{ + int i, ret, new_time_sel; + + for (i = 0; i < data->gts.num_itime; i++) { + new_time_sel = data->gts.itime_table[i].sel; + ret = iio_gts_find_gain_sel_for_scale_using_time(&data->gts, + new_time_sel, val, val2 * 1000, gain_sel); + if (!ret) + break; + } + if (i == data->gts.num_itime) { + dev_err(data->dev, "Can't support scale %u %u\n", val, val2); + + return -EINVAL; + } + + return bu27008_set_int_time_sel(data, new_time_sel); +} + +static int bu27008_set_scale(struct bu27008_data *data, + struct iio_chan_spec const *chan, + int val, int val2) +{ + int ret, gain_sel, time_sel; + + if (chan->scan_index == BU27008_IR) + return -EINVAL; + + mutex_lock(&data->mutex); + + ret = bu27008_get_int_time_sel(data, &time_sel); + if (ret < 0) + goto unlock_out; + + ret = iio_gts_find_gain_sel_for_scale_using_time(&data->gts, time_sel, + val, val2 * 1000, &gain_sel); + if (ret) { + ret = bu27008_try_find_new_time_gain(data, val, val2, &gain_sel); + if (ret) + goto unlock_out; + + } + ret = bu27008_write_gain_sel(data, gain_sel); + +unlock_out: + mutex_unlock(&data->mutex); + + return ret; +} + +static int bu27008_write_raw(struct iio_dev *idev, + struct iio_chan_spec const *chan, + int val, int val2, long mask) +{ + struct bu27008_data *data = iio_priv(idev); + int ret; + + /* + * Do not allow changing scale when measurement is ongoing as doing so + * could make values in the buffer inconsistent. + */ + ret = iio_device_claim_direct_mode(idev); + if (ret) + return ret; + + switch (mask) { + case IIO_CHAN_INFO_SCALE: + ret = bu27008_set_scale(data, chan, val, val2); + break; + case IIO_CHAN_INFO_INT_TIME: + if (val) { + ret = -EINVAL; + break; + } + ret = bu27008_try_set_int_time(data, val2); + break; + default: + ret = -EINVAL; + break; + } + iio_device_release_direct_mode(idev); + + return ret; +} + +static int bu27008_read_avail(struct iio_dev *idev, + struct iio_chan_spec const *chan, const int **vals, + int *type, int *length, long mask) +{ + struct bu27008_data *data = iio_priv(idev); + + switch (mask) { + case IIO_CHAN_INFO_INT_TIME: + return iio_gts_avail_times(&data->gts, vals, type, length); + case IIO_CHAN_INFO_SCALE: + if (chan->channel2 == IIO_MOD_LIGHT_IR) + return iio_gts_all_avail_scales(&data->gts_ir, vals, + type, length); + return iio_gts_all_avail_scales(&data->gts, vals, type, length); + default: + return -EINVAL; + } +} + +static int bu27008_update_scan_mode(struct iio_dev *idev, + const unsigned long *scan_mask) +{ + struct bu27008_data *data = iio_priv(idev); + int chan_sel; + + /* Configure channel selection */ + if (test_bit(BU27008_BLUE, idev->active_scan_mask)) { + if (test_bit(BU27008_CLEAR, idev->active_scan_mask)) + chan_sel = BU27008_BLUE2_CLEAR3; + else + chan_sel = BU27008_BLUE2_IR3; + } else { + chan_sel = BU27008_CLEAR2_IR3; + } + + chan_sel = FIELD_PREP(BU27008_MASK_CHAN_SEL, chan_sel); + + return regmap_update_bits(data->regmap, BU27008_REG_MODE_CONTROL3, + BU27008_MASK_CHAN_SEL, chan_sel); +} + +static const struct iio_info bu27008_info = { + .read_raw = &bu27008_read_raw, + .write_raw = &bu27008_write_raw, + .read_avail = &bu27008_read_avail, + .update_scan_mode = bu27008_update_scan_mode, + .validate_trigger = iio_validate_own_trigger, +}; + +static int bu27008_chip_init(struct bu27008_data *data) +{ + int ret; + + ret = regmap_write_bits(data->regmap, BU27008_REG_SYSTEM_CONTROL, + BU27008_MASK_SW_RESET, BU27008_MASK_SW_RESET); + if (ret) + return dev_err_probe(data->dev, ret, "Sensor reset failed\n"); + + /* + * The data-sheet does not tell how long performing the IC reset takes. + * However, the data-sheet says the minimum time it takes the IC to be + * able to take inputs after power is applied, is 100 uS. I'd assume + * > 1 mS is enough. + */ + msleep(1); + + ret = regmap_reinit_cache(data->regmap, &bu27008_regmap); + if (ret) + dev_err(data->dev, "Failed to reinit reg cache\n"); + + return ret; +} + +static int bu27008_set_drdy_irq(struct bu27008_data *data, int state) +{ + return regmap_update_bits(data->regmap, BU27008_REG_MODE_CONTROL3, + BU27008_MASK_INT_EN, state); +} + +static int bu27008_trigger_set_state(struct iio_trigger *trig, + bool state) +{ + struct bu27008_data *data = iio_trigger_get_drvdata(trig); + int ret; + + if (state) + ret = bu27008_set_drdy_irq(data, BU27008_INT_EN); + else + ret = bu27008_set_drdy_irq(data, BU27008_INT_DIS); + if (ret) + dev_err(data->dev, "Failed to set trigger state\n"); + + return ret; +} + +static void bu27008_trigger_reenable(struct iio_trigger *trig) +{ + struct bu27008_data *data = iio_trigger_get_drvdata(trig); + + enable_irq(data->irq); +} + +static const struct iio_trigger_ops bu27008_trigger_ops = { + .set_trigger_state = bu27008_trigger_set_state, + .reenable = bu27008_trigger_reenable, +}; + +static irqreturn_t bu27008_trigger_handler(int irq, void *p) +{ + struct iio_poll_func *pf = p; + struct iio_dev *idev = pf->indio_dev; + struct bu27008_data *data = iio_priv(idev); + struct { + __le16 chan[BU27008_NUM_HW_CHANS]; + s64 ts __aligned(8); + } raw; + int ret, dummy; + + memset(&raw, 0, sizeof(raw)); + + /* + * After some measurements, it seems reading the + * BU27008_REG_MODE_CONTROL3 debounces the IRQ line + */ + ret = regmap_read(data->regmap, BU27008_REG_MODE_CONTROL3, &dummy); + if (ret < 0) + goto err_read; + + ret = regmap_bulk_read(data->regmap, BU27008_REG_DATA0_LO, &raw.chan, + sizeof(raw.chan)); + if (ret < 0) + goto err_read; + + iio_push_to_buffers_with_timestamp(idev, &raw, pf->timestamp); +err_read: + iio_trigger_notify_done(idev->trig); + + return IRQ_HANDLED; +} + +static int bu27008_buffer_preenable(struct iio_dev *idev) +{ + struct bu27008_data *data = iio_priv(idev); + + return bu27008_meas_set(data, BU27008_MEAS_EN); +} + +static int bu27008_buffer_postdisable(struct iio_dev *idev) +{ + struct bu27008_data *data = iio_priv(idev); + + return bu27008_meas_set(data, BU27008_MEAS_DIS); +} + +static const struct iio_buffer_setup_ops bu27008_buffer_ops = { + .preenable = bu27008_buffer_preenable, + .postdisable = bu27008_buffer_postdisable, +}; + +static irqreturn_t bu27008_data_rdy_poll(int irq, void *private) +{ + /* + * The BU27008 keeps IRQ asserted until we read the VALID bit from + * a register. We need to keep the IRQ disabled until then. + */ + disable_irq_nosync(irq); + iio_trigger_poll(private); + + return IRQ_HANDLED; +} + +static int bu27008_setup_trigger(struct bu27008_data *data, struct iio_dev *idev) +{ + struct iio_trigger *itrig; + char *name; + int ret; + + ret = devm_iio_triggered_buffer_setup(data->dev, idev, + &iio_pollfunc_store_time, + bu27008_trigger_handler, + &bu27008_buffer_ops); + if (ret) + return dev_err_probe(data->dev, ret, + "iio_triggered_buffer_setup_ext FAIL\n"); + + itrig = devm_iio_trigger_alloc(data->dev, "%sdata-rdy-dev%d", + idev->name, iio_device_id(idev)); + if (!itrig) + return -ENOMEM; + + data->trig = itrig; + + itrig->ops = &bu27008_trigger_ops; + iio_trigger_set_drvdata(itrig, data); + + name = devm_kasprintf(data->dev, GFP_KERNEL, "%s-bu27008", + dev_name(data->dev)); + + ret = devm_request_irq(data->dev, data->irq, + &bu27008_data_rdy_poll, + 0, name, itrig); + if (ret) + return dev_err_probe(data->dev, ret, "Could not request IRQ\n"); + + ret = devm_iio_trigger_register(data->dev, itrig); + if (ret) + return dev_err_probe(data->dev, ret, + "Trigger registration failed\n"); + + /* set default trigger */ + idev->trig = iio_trigger_get(itrig); + + return 0; +} + +static int bu27008_probe(struct i2c_client *i2c) +{ + struct device *dev = &i2c->dev; + struct bu27008_data *data; + struct regmap *regmap; + unsigned int part_id, reg; + struct iio_dev *idev; + int ret; + + regmap = devm_regmap_init_i2c(i2c, &bu27008_regmap); + if (IS_ERR(regmap)) + return dev_err_probe(dev, PTR_ERR(regmap), + "Failed to initialize Regmap\n"); + + idev = devm_iio_device_alloc(dev, sizeof(*data)); + if (!idev) + return -ENOMEM; + + ret = devm_regulator_get_enable(dev, "vdd"); + if (ret) + return dev_err_probe(dev, ret, "Failed to get regulator\n"); + + data = iio_priv(idev); + + ret = regmap_read(regmap, BU27008_REG_SYSTEM_CONTROL, ®); + if (ret) + return dev_err_probe(dev, ret, "Failed to access sensor\n"); + + part_id = FIELD_GET(BU27008_MASK_PART_ID, reg); + + if (part_id != BU27008_ID) + dev_warn(dev, "unknown device 0x%x\n", part_id); + + ret = devm_iio_init_iio_gts(dev, BU27008_SCALE_1X, 0, bu27008_gains, + ARRAY_SIZE(bu27008_gains), bu27008_itimes, + ARRAY_SIZE(bu27008_itimes), &data->gts); + if (ret) + return ret; + + ret = devm_iio_init_iio_gts(dev, BU27008_SCALE_1X, 0, bu27008_gains_ir, + ARRAY_SIZE(bu27008_gains_ir), bu27008_itimes, + ARRAY_SIZE(bu27008_itimes), &data->gts_ir); + if (ret) + return ret; + + mutex_init(&data->mutex); + data->regmap = regmap; + data->dev = dev; + data->irq = i2c->irq; + + idev->channels = bu27008_channels; + idev->num_channels = ARRAY_SIZE(bu27008_channels); + idev->name = "bu27008"; + idev->info = &bu27008_info; + idev->modes = INDIO_DIRECT_MODE; + idev->available_scan_masks = bu27008_scan_masks; + + ret = bu27008_chip_init(data); + if (ret) + return ret; + + if (i2c->irq) { + ret = bu27008_setup_trigger(data, idev); + if (ret) + return ret; + } else { + dev_info(dev, "No IRQ, buffered mode disabled\n"); + } + + ret = devm_iio_device_register(dev, idev); + if (ret) + return dev_err_probe(dev, ret, + "Unable to register iio device\n"); + + return 0; +} + +static const struct of_device_id bu27008_of_match[] = { + { .compatible = "rohm,bu27008" }, + { } +}; +MODULE_DEVICE_TABLE(of, bu27008_of_match); + +static struct i2c_driver bu27008_i2c_driver = { + .driver = { + .name = "bu27008", + .of_match_table = bu27008_of_match, + .probe_type = PROBE_PREFER_ASYNCHRONOUS, + }, + .probe = bu27008_probe, +}; +module_i2c_driver(bu27008_i2c_driver); + +MODULE_DESCRIPTION("ROHM BU27008 colour sensor driver"); +MODULE_AUTHOR("Matti Vaittinen "); +MODULE_LICENSE("GPL"); +MODULE_IMPORT_NS(IIO_GTS_HELPER); diff --git a/drivers/iio/light/rohm-bu27034.c b/drivers/iio/light/rohm-bu27034.c index f85194fda6b093d5de2c487fb268e89ea3b2b14d..e63ef5789cde1e4fd17b4485761b461308007283 100644 --- a/drivers/iio/light/rohm-bu27034.c +++ b/drivers/iio/light/rohm-bu27034.c @@ -1500,8 +1500,9 @@ static struct i2c_driver bu27034_i2c_driver = { .driver = { .name = "bu27034-als", .of_match_table = bu27034_of_match, + .probe_type = PROBE_PREFER_ASYNCHRONOUS, }, - .probe_new = bu27034_probe, + .probe = bu27034_probe, }; module_i2c_driver(bu27034_i2c_driver); diff --git a/drivers/iio/light/rpr0521.c b/drivers/iio/light/rpr0521.c index 9d0218b7426ee77c42411b4ca802ca1ab901bd4b..bbb8581622f29d358f3f04415725b802a0952793 100644 --- a/drivers/iio/light/rpr0521.c +++ b/drivers/iio/light/rpr0521.c @@ -1121,7 +1121,7 @@ static struct i2c_driver rpr0521_driver = { .pm = pm_ptr(&rpr0521_pm_ops), .acpi_match_table = ACPI_PTR(rpr0521_acpi_match), }, - .probe_new = rpr0521_probe, + .probe = rpr0521_probe, .remove = rpr0521_remove, .id_table = rpr0521_id, }; diff --git a/drivers/iio/light/si1133.c b/drivers/iio/light/si1133.c index a08fbc8f5adb1bdfd0624b7f7672c510f68849c5..ea2c437199c0fb37739b4e5b40360f16f2a74b8f 100644 --- a/drivers/iio/light/si1133.c +++ b/drivers/iio/light/si1133.c @@ -1064,7 +1064,7 @@ static struct i2c_driver si1133_driver = { .driver = { .name = "si1133", }, - .probe_new = si1133_probe, + .probe = si1133_probe, .id_table = si1133_ids, }; diff --git a/drivers/iio/light/si1145.c b/drivers/iio/light/si1145.c index f7126235f94c91cbd954e774c2edf4fa388acd04..77666b780a5c5a264522cd52dd2b6b1bad58ecea 100644 --- a/drivers/iio/light/si1145.c +++ b/drivers/iio/light/si1145.c @@ -1352,7 +1352,7 @@ static struct i2c_driver si1145_driver = { .driver = { .name = "si1145", }, - .probe_new = si1145_probe, + .probe = si1145_probe, .id_table = si1145_ids, }; diff --git a/drivers/iio/light/st_uvis25_i2c.c b/drivers/iio/light/st_uvis25_i2c.c index 2160e87bb498e7790153a328aa15ff4bf29be439..6bc2ddfb77ca633361682b3637f2c45e558a0f6f 100644 --- a/drivers/iio/light/st_uvis25_i2c.c +++ b/drivers/iio/light/st_uvis25_i2c.c @@ -57,7 +57,7 @@ static struct i2c_driver st_uvis25_driver = { .pm = pm_sleep_ptr(&st_uvis25_pm_ops), .of_match_table = st_uvis25_i2c_of_match, }, - .probe_new = st_uvis25_i2c_probe, + .probe = st_uvis25_i2c_probe, .id_table = st_uvis25_i2c_id_table, }; module_i2c_driver(st_uvis25_driver); diff --git a/drivers/iio/light/stk3310.c b/drivers/iio/light/stk3310.c index 48ae6ff0015e1eb91b9ad26638a41f5667537105..72b08d870d337b9ca583e2449f0b8a02a8e5dc19 100644 --- a/drivers/iio/light/stk3310.c +++ b/drivers/iio/light/stk3310.c @@ -714,7 +714,7 @@ static struct i2c_driver stk3310_driver = { .pm = pm_sleep_ptr(&stk3310_pm_ops), .acpi_match_table = ACPI_PTR(stk3310_acpi_id), }, - .probe_new = stk3310_probe, + .probe = stk3310_probe, .remove = stk3310_remove, .id_table = stk3310_i2c_id, }; diff --git a/drivers/iio/light/tcs3414.c b/drivers/iio/light/tcs3414.c index 5100732fbaf0a1255c89e17e622ada20601a5c0e..dcdd85b006be0b9e7f4cb073160cafca93ffd915 100644 --- a/drivers/iio/light/tcs3414.c +++ b/drivers/iio/light/tcs3414.c @@ -373,7 +373,7 @@ static struct i2c_driver tcs3414_driver = { .name = TCS3414_DRV_NAME, .pm = pm_sleep_ptr(&tcs3414_pm_ops), }, - .probe_new = tcs3414_probe, + .probe = tcs3414_probe, .id_table = tcs3414_id, }; module_i2c_driver(tcs3414_driver); diff --git a/drivers/iio/light/tcs3472.c b/drivers/iio/light/tcs3472.c index 6187c54879162d035e0129737c3116eeda948d33..75fcf2c93717b67d9ba0e144b03a5b21cbcfad71 100644 --- a/drivers/iio/light/tcs3472.c +++ b/drivers/iio/light/tcs3472.c @@ -609,7 +609,7 @@ static struct i2c_driver tcs3472_driver = { .name = TCS3472_DRV_NAME, .pm = pm_sleep_ptr(&tcs3472_pm_ops), }, - .probe_new = tcs3472_probe, + .probe = tcs3472_probe, .remove = tcs3472_remove, .id_table = tcs3472_id, }; diff --git a/drivers/iio/light/tsl2563.c b/drivers/iio/light/tsl2563.c index f2f55239a072f97670362d94b9e86e3714f9ae19..1a6f514bced6e0bd542c14a279071d5820a462c8 100644 --- a/drivers/iio/light/tsl2563.c +++ b/drivers/iio/light/tsl2563.c @@ -862,7 +862,7 @@ static struct i2c_driver tsl2563_i2c_driver = { .of_match_table = tsl2563_of_match, .pm = pm_sleep_ptr(&tsl2563_pm_ops), }, - .probe_new = tsl2563_probe, + .probe = tsl2563_probe, .remove = tsl2563_remove, .id_table = tsl2563_id, }; diff --git a/drivers/iio/light/tsl2583.c b/drivers/iio/light/tsl2583.c index a05f1c0453d16d3455283b765b1cdce339141e02..02ad11611b9c576afa7e09515ed6fbeb8c4f0db2 100644 --- a/drivers/iio/light/tsl2583.c +++ b/drivers/iio/light/tsl2583.c @@ -942,7 +942,7 @@ static struct i2c_driver tsl2583_driver = { .of_match_table = tsl2583_of_match, }, .id_table = tsl2583_idtable, - .probe_new = tsl2583_probe, + .probe = tsl2583_probe, .remove = tsl2583_remove, }; module_i2c_driver(tsl2583_driver); diff --git a/drivers/iio/light/tsl2591.c b/drivers/iio/light/tsl2591.c index e485a556e6da8086247b99c7ee6c177bdb4d7896..7bdbfe72f0f0413625c9c2ee5b3aac05ac974e4f 100644 --- a/drivers/iio/light/tsl2591.c +++ b/drivers/iio/light/tsl2591.c @@ -1214,7 +1214,7 @@ static struct i2c_driver tsl2591_driver = { .pm = pm_ptr(&tsl2591_pm_ops), .of_match_table = tsl2591_of_match, }, - .probe_new = tsl2591_probe + .probe = tsl2591_probe }; module_i2c_driver(tsl2591_driver); diff --git a/drivers/iio/light/tsl2772.c b/drivers/iio/light/tsl2772.c index e823c145f6792ee4204697f902d238c0a1b9f440..cab468a82b616a23394977da1d8822d29d8941d3 100644 --- a/drivers/iio/light/tsl2772.c +++ b/drivers/iio/light/tsl2772.c @@ -1932,7 +1932,7 @@ static struct i2c_driver tsl2772_driver = { .pm = &tsl2772_pm_ops, }, .id_table = tsl2772_idtable, - .probe_new = tsl2772_probe, + .probe = tsl2772_probe, }; module_i2c_driver(tsl2772_driver); diff --git a/drivers/iio/light/tsl4531.c b/drivers/iio/light/tsl4531.c index d95397eb15263bd456bef5922e4991e69207de15..4da7d78906d4a361b0d43f3ba2fd11305300533e 100644 --- a/drivers/iio/light/tsl4531.c +++ b/drivers/iio/light/tsl4531.c @@ -237,7 +237,7 @@ static struct i2c_driver tsl4531_driver = { .name = TSL4531_DRV_NAME, .pm = pm_sleep_ptr(&tsl4531_pm_ops), }, - .probe_new = tsl4531_probe, + .probe = tsl4531_probe, .remove = tsl4531_remove, .id_table = tsl4531_id, }; diff --git a/drivers/iio/light/us5182d.c b/drivers/iio/light/us5182d.c index 8b2a0c99c8e6f856be4f5e322512a4c7d1bdae2d..61b3b2aea626fb2322a5ab87be28085447f8e443 100644 --- a/drivers/iio/light/us5182d.c +++ b/drivers/iio/light/us5182d.c @@ -974,7 +974,7 @@ static struct i2c_driver us5182d_driver = { .of_match_table = us5182d_of_match, .acpi_match_table = ACPI_PTR(us5182d_acpi_match), }, - .probe_new = us5182d_probe, + .probe = us5182d_probe, .remove = us5182d_remove, .id_table = us5182d_id, diff --git a/drivers/iio/light/vcnl4000.c b/drivers/iio/light/vcnl4000.c index 56d3963d3d66a3285ce0632f37eebd624daff962..7c7362e2882137592652d7b7e030b135a82e6628 100644 --- a/drivers/iio/light/vcnl4000.c +++ b/drivers/iio/light/vcnl4000.c @@ -1500,7 +1500,7 @@ static struct i2c_driver vcnl4000_driver = { .pm = pm_ptr(&vcnl4000_pm_ops), .of_match_table = vcnl_4000_of_match, }, - .probe_new = vcnl4000_probe, + .probe = vcnl4000_probe, .id_table = vcnl4000_id, .remove = vcnl4000_remove, }; diff --git a/drivers/iio/light/vcnl4035.c b/drivers/iio/light/vcnl4035.c index 94f5d611e98c3c80225737dd837a3d25d834aa9d..56bbefbc0ae6434514670f2e84bca38db1118ee3 100644 --- a/drivers/iio/light/vcnl4035.c +++ b/drivers/iio/light/vcnl4035.c @@ -670,7 +670,7 @@ static struct i2c_driver vcnl4035_driver = { .pm = pm_ptr(&vcnl4035_pm_ops), .of_match_table = vcnl4035_of_match, }, - .probe_new = vcnl4035_probe, + .probe = vcnl4035_probe, .remove = vcnl4035_remove, .id_table = vcnl4035_id, }; diff --git a/drivers/iio/light/veml6030.c b/drivers/iio/light/veml6030.c index e7d2d5d177d43c8cc28d3a8ddb4a59d4946c27b3..043f233d9bdb068dea467c5a6068519f9501dabc 100644 --- a/drivers/iio/light/veml6030.c +++ b/drivers/iio/light/veml6030.c @@ -892,7 +892,7 @@ static struct i2c_driver veml6030_driver = { .of_match_table = veml6030_of_match, .pm = pm_ptr(&veml6030_pm_ops), }, - .probe_new = veml6030_probe, + .probe = veml6030_probe, .id_table = veml6030_id, }; module_i2c_driver(veml6030_driver); diff --git a/drivers/iio/light/veml6070.c b/drivers/iio/light/veml6070.c index ee76a68deb24af1ed34dd149812af29149ea9b10..d99bf3ae0fe8e943d13016568fb8ed2a4dff8c0d 100644 --- a/drivers/iio/light/veml6070.c +++ b/drivers/iio/light/veml6070.c @@ -198,7 +198,7 @@ static struct i2c_driver veml6070_driver = { .driver = { .name = VEML6070_DRV_NAME, }, - .probe_new = veml6070_probe, + .probe = veml6070_probe, .remove = veml6070_remove, .id_table = veml6070_id, }; diff --git a/drivers/iio/light/vl6180.c b/drivers/iio/light/vl6180.c index 8b56df26c59e8fff7f6a2a79ad8dc8c3792cb888..d4948dfc31ff14ab13bed360c7889dfd94cda762 100644 --- a/drivers/iio/light/vl6180.c +++ b/drivers/iio/light/vl6180.c @@ -538,7 +538,7 @@ static struct i2c_driver vl6180_driver = { .name = VL6180_DRV_NAME, .of_match_table = vl6180_of_match, }, - .probe_new = vl6180_probe, + .probe = vl6180_probe, .id_table = vl6180_id, }; diff --git a/drivers/iio/light/zopt2201.c b/drivers/iio/light/zopt2201.c index e3bac8b563807427dd4f3982996682f75d99ccc9..d370193a4742347db7fc7de1846c3a5ac9180b2f 100644 --- a/drivers/iio/light/zopt2201.c +++ b/drivers/iio/light/zopt2201.c @@ -554,7 +554,7 @@ static struct i2c_driver zopt2201_driver = { .driver = { .name = ZOPT2201_DRV_NAME, }, - .probe_new = zopt2201_probe, + .probe = zopt2201_probe, .id_table = zopt2201_id, }; diff --git a/drivers/iio/magnetometer/ak8974.c b/drivers/iio/magnetometer/ak8974.c index 45abdcce6bc0ad1f3849827238a215c2ad974846..c74d11943ec797b3cfde6efece6f73a6fa446e4b 100644 --- a/drivers/iio/magnetometer/ak8974.c +++ b/drivers/iio/magnetometer/ak8974.c @@ -1046,7 +1046,7 @@ static struct i2c_driver ak8974_driver = { .pm = pm_ptr(&ak8974_dev_pm_ops), .of_match_table = ak8974_of_match, }, - .probe_new = ak8974_probe, + .probe = ak8974_probe, .remove = ak8974_remove, .id_table = ak8974_id, }; diff --git a/drivers/iio/magnetometer/ak8975.c b/drivers/iio/magnetometer/ak8975.c index 924b481a3034aac393a8d1bb0e621caba0bb139c..eb706d0bf70bc0d6354a44d1b99e704b63561b83 100644 --- a/drivers/iio/magnetometer/ak8975.c +++ b/drivers/iio/magnetometer/ak8975.c @@ -1110,7 +1110,7 @@ static struct i2c_driver ak8975_driver = { .of_match_table = ak8975_of_match, .acpi_match_table = ak_acpi_match, }, - .probe_new = ak8975_probe, + .probe = ak8975_probe, .remove = ak8975_remove, .id_table = ak8975_id, }; diff --git a/drivers/iio/magnetometer/bmc150_magn_i2c.c b/drivers/iio/magnetometer/bmc150_magn_i2c.c index 44b8960eea175fb744e772fa5dbad5bcb2bf3de3..281d1fa31c8e17dc71f6a92e9e33b02904bc7f2c 100644 --- a/drivers/iio/magnetometer/bmc150_magn_i2c.c +++ b/drivers/iio/magnetometer/bmc150_magn_i2c.c @@ -71,7 +71,7 @@ static struct i2c_driver bmc150_magn_driver = { .acpi_match_table = ACPI_PTR(bmc150_magn_acpi_match), .pm = &bmc150_magn_pm_ops, }, - .probe_new = bmc150_magn_i2c_probe, + .probe = bmc150_magn_i2c_probe, .remove = bmc150_magn_i2c_remove, .id_table = bmc150_magn_i2c_id, }; diff --git a/drivers/iio/magnetometer/hmc5843_i2c.c b/drivers/iio/magnetometer/hmc5843_i2c.c index 7ef2b1d562898ee4d21c106759b9355e5e076371..bdd2784a9f863b0c872501a93438aa7e2d074b98 100644 --- a/drivers/iio/magnetometer/hmc5843_i2c.c +++ b/drivers/iio/magnetometer/hmc5843_i2c.c @@ -95,7 +95,7 @@ static struct i2c_driver hmc5843_driver = { .of_match_table = hmc5843_of_match, }, .id_table = hmc5843_id, - .probe_new = hmc5843_i2c_probe, + .probe = hmc5843_i2c_probe, .remove = hmc5843_i2c_remove, }; module_i2c_driver(hmc5843_driver); diff --git a/drivers/iio/magnetometer/mag3110.c b/drivers/iio/magnetometer/mag3110.c index 661176a885ad763e8a387a88c6e184551c76de70..deffe3ca90043bbeba9055470fa244842a2d0c1a 100644 --- a/drivers/iio/magnetometer/mag3110.c +++ b/drivers/iio/magnetometer/mag3110.c @@ -641,7 +641,7 @@ static struct i2c_driver mag3110_driver = { .of_match_table = mag3110_of_match, .pm = pm_sleep_ptr(&mag3110_pm_ops), }, - .probe_new = mag3110_probe, + .probe = mag3110_probe, .remove = mag3110_remove, .id_table = mag3110_id, }; diff --git a/drivers/iio/magnetometer/mmc35240.c b/drivers/iio/magnetometer/mmc35240.c index 756dadbad106f73d0736b1ca2af8188c38a05c1b..b495b8a6392848e3eca7dc278eacdcc21803291a 100644 --- a/drivers/iio/magnetometer/mmc35240.c +++ b/drivers/iio/magnetometer/mmc35240.c @@ -575,7 +575,7 @@ static struct i2c_driver mmc35240_driver = { .pm = pm_sleep_ptr(&mmc35240_pm_ops), .acpi_match_table = ACPI_PTR(mmc35240_acpi_match), }, - .probe_new = mmc35240_probe, + .probe = mmc35240_probe, .id_table = mmc35240_id, }; diff --git a/drivers/iio/magnetometer/rm3100-i2c.c b/drivers/iio/magnetometer/rm3100-i2c.c index ba669ab7113dbe011c8e02810c67fbd67aa0c0dc..ac7276b3798c07290669f19ccac3f163fd15838f 100644 --- a/drivers/iio/magnetometer/rm3100-i2c.c +++ b/drivers/iio/magnetometer/rm3100-i2c.c @@ -45,7 +45,7 @@ static struct i2c_driver rm3100_driver = { .name = "rm3100-i2c", .of_match_table = rm3100_dt_match, }, - .probe_new = rm3100_probe, + .probe = rm3100_probe, }; module_i2c_driver(rm3100_driver); diff --git a/drivers/iio/magnetometer/st_magn_core.c b/drivers/iio/magnetometer/st_magn_core.c index 8faa7409d9e12d6a9192b3f9ec38bd659fe2d429..6cc0dfd31821b094735f04b0bc0e15319407a759 100644 --- a/drivers/iio/magnetometer/st_magn_core.c +++ b/drivers/iio/magnetometer/st_magn_core.c @@ -427,6 +427,7 @@ static const struct st_sensor_settings st_magn_sensors_settings[] = { .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS, .sensors_supported = { [0] = LSM9DS0_IMU_DEV_NAME, + [1] = LSM303D_IMU_DEV_NAME, }, .ch = (struct iio_chan_spec *)st_magn_4_16bit_channels, .odr = { diff --git a/drivers/iio/magnetometer/st_magn_i2c.c b/drivers/iio/magnetometer/st_magn_i2c.c index cc0e0e94b129c12eb5f39cbf3fa734d9b82d10b1..950826dd20bf5f16bf0f0c7b4f02ea2dc095de8c 100644 --- a/drivers/iio/magnetometer/st_magn_i2c.c +++ b/drivers/iio/magnetometer/st_magn_i2c.c @@ -111,7 +111,7 @@ static struct i2c_driver st_magn_driver = { .name = "st-magn-i2c", .of_match_table = st_magn_of_match, }, - .probe_new = st_magn_i2c_probe, + .probe = st_magn_i2c_probe, .id_table = st_magn_id_table, }; module_i2c_driver(st_magn_driver); diff --git a/drivers/iio/magnetometer/tmag5273.c b/drivers/iio/magnetometer/tmag5273.c index e155a75b3cd29d3563b59b8a9fd98889f0ac9bf9..c5e5c4ad681e644760acd4ddb67bbe7105a9f293 100644 --- a/drivers/iio/magnetometer/tmag5273.c +++ b/drivers/iio/magnetometer/tmag5273.c @@ -734,7 +734,7 @@ static struct i2c_driver tmag5273_driver = { .of_match_table = tmag5273_of_match, .pm = pm_ptr(&tmag5273_pm_ops), }, - .probe_new = tmag5273_probe, + .probe = tmag5273_probe, .id_table = tmag5273_id, }; module_i2c_driver(tmag5273_driver); diff --git a/drivers/iio/magnetometer/yamaha-yas530.c b/drivers/iio/magnetometer/yamaha-yas530.c index 753717158b073c24884dcad168107957733acd59..c5e485bfc6fc03d9ba92e70ef1de014fca6ab4a4 100644 --- a/drivers/iio/magnetometer/yamaha-yas530.c +++ b/drivers/iio/magnetometer/yamaha-yas530.c @@ -1605,7 +1605,7 @@ static struct i2c_driver yas5xx_driver = { .of_match_table = yas5xx_of_match, .pm = pm_ptr(&yas5xx_dev_pm_ops), }, - .probe_new = yas5xx_probe, + .probe = yas5xx_probe, .remove = yas5xx_remove, .id_table = yas5xx_id, }; diff --git a/drivers/iio/potentiometer/Kconfig b/drivers/iio/potentiometer/Kconfig index 01dd3f858d99cb78df9b5dadbaa2b1bf53125cf6..e6a9a3c67845cb961ed5e53d6dce9d6043d7da83 100644 --- a/drivers/iio/potentiometer/Kconfig +++ b/drivers/iio/potentiometer/Kconfig @@ -136,4 +136,14 @@ config TPL0102 To compile this driver as a module, choose M here: the module will be called tpl0102. +config X9250 + tristate "Renesas X9250 quad controlled potentiometers" + depends on SPI + help + Enable support for the Renesas X9250 quad controlled + potentiometers. + + To compile this driver as a module, choose M here: the module + will be called x9250. + endmenu diff --git a/drivers/iio/potentiometer/Makefile b/drivers/iio/potentiometer/Makefile index 5ebb8e3bbd76cfe620ed0efd7b18137a179c840f..d11fb739176cc922f6dd382c1c0a7e1926434873 100644 --- a/drivers/iio/potentiometer/Makefile +++ b/drivers/iio/potentiometer/Makefile @@ -15,3 +15,4 @@ obj-$(CONFIG_MCP4131) += mcp4131.o obj-$(CONFIG_MCP4531) += mcp4531.o obj-$(CONFIG_MCP41010) += mcp41010.o obj-$(CONFIG_TPL0102) += tpl0102.o +obj-$(CONFIG_X9250) += x9250.o diff --git a/drivers/iio/potentiometer/ad5110.c b/drivers/iio/potentiometer/ad5110.c index 8fbcce4829898fd5fa1c6d65b53ca6ad11b4f27f..991e745c4f937272db6e178a1d78ce00486788c5 100644 --- a/drivers/iio/potentiometer/ad5110.c +++ b/drivers/iio/potentiometer/ad5110.c @@ -334,7 +334,7 @@ static struct i2c_driver ad5110_driver = { .name = "ad5110", .of_match_table = ad5110_of_match, }, - .probe_new = ad5110_probe, + .probe = ad5110_probe, .id_table = ad5110_id, }; module_i2c_driver(ad5110_driver); diff --git a/drivers/iio/potentiometer/ad5272.c b/drivers/iio/potentiometer/ad5272.c index aa140d63210161d736900455ce88726abca57879..b17941e4c2f7c543e64e4eedde642520e0d3e405 100644 --- a/drivers/iio/potentiometer/ad5272.c +++ b/drivers/iio/potentiometer/ad5272.c @@ -218,7 +218,7 @@ static struct i2c_driver ad5272_driver = { .name = "ad5272", .of_match_table = ad5272_dt_ids, }, - .probe_new = ad5272_probe, + .probe = ad5272_probe, .id_table = ad5272_id, }; diff --git a/drivers/iio/potentiometer/ds1803.c b/drivers/iio/potentiometer/ds1803.c index 0b5e475807cbcaea920d7fe836090a9c8351e6be..fc183e0790dafb989a1260a6e10526dc458b61db 100644 --- a/drivers/iio/potentiometer/ds1803.c +++ b/drivers/iio/potentiometer/ds1803.c @@ -252,7 +252,7 @@ static struct i2c_driver ds1803_driver = { .name = "ds1803", .of_match_table = ds1803_dt_ids, }, - .probe_new = ds1803_probe, + .probe = ds1803_probe, .id_table = ds1803_id, }; diff --git a/drivers/iio/potentiometer/max5432.c b/drivers/iio/potentiometer/max5432.c index 94ef27ef3fb57981947e37b665e0647383ad6ef9..c8e2481dadb5330fed5ba0eaa5d29121296c4cc2 100644 --- a/drivers/iio/potentiometer/max5432.c +++ b/drivers/iio/potentiometer/max5432.c @@ -123,7 +123,7 @@ static struct i2c_driver max5432_driver = { .name = "max5432", .of_match_table = max5432_dt_ids, }, - .probe_new = max5432_probe, + .probe = max5432_probe, }; module_i2c_driver(max5432_driver); diff --git a/drivers/iio/potentiometer/mcp4018.c b/drivers/iio/potentiometer/mcp4018.c index c0e171fec0629a5ab3ce6b8f1c7eed6f4b04ad26..89daecc90305a1893a74c5101a8b3652af66f3b9 100644 --- a/drivers/iio/potentiometer/mcp4018.c +++ b/drivers/iio/potentiometer/mcp4018.c @@ -174,7 +174,7 @@ static struct i2c_driver mcp4018_driver = { .name = "mcp4018", .of_match_table = mcp4018_of_match, }, - .probe_new = mcp4018_probe, + .probe = mcp4018_probe, .id_table = mcp4018_id, }; diff --git a/drivers/iio/potentiometer/mcp4531.c b/drivers/iio/potentiometer/mcp4531.c index c25f84b4a270b14b482aa9916d6cdc8a90b5eac9..c513c00c82435661636f6ecbb6ab62cae0620b29 100644 --- a/drivers/iio/potentiometer/mcp4531.c +++ b/drivers/iio/potentiometer/mcp4531.c @@ -385,7 +385,7 @@ static struct i2c_driver mcp4531_driver = { .name = "mcp4531", .of_match_table = mcp4531_of_match, }, - .probe_new = mcp4531_probe, + .probe = mcp4531_probe, .id_table = mcp4531_id, }; diff --git a/drivers/iio/potentiometer/tpl0102.c b/drivers/iio/potentiometer/tpl0102.c index a3465b413b0caa4f22fbadb36464b2e968070568..8923ccb0fc4f793c64e01c5b6c2143255e27ab5c 100644 --- a/drivers/iio/potentiometer/tpl0102.c +++ b/drivers/iio/potentiometer/tpl0102.c @@ -161,7 +161,7 @@ static struct i2c_driver tpl0102_driver = { .driver = { .name = "tpl0102", }, - .probe_new = tpl0102_probe, + .probe = tpl0102_probe, .id_table = tpl0102_id, }; diff --git a/drivers/iio/potentiometer/x9250.c b/drivers/iio/potentiometer/x9250.c new file mode 100644 index 0000000000000000000000000000000000000000..7353484926997fc8eb14a0e15bcaa5a790290799 --- /dev/null +++ b/drivers/iio/potentiometer/x9250.c @@ -0,0 +1,220 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * + * x9250.c -- Renesas X9250 potentiometers IIO driver + * + * Copyright 2023 CS GROUP France + * + * Author: Herve Codina + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +struct x9250_cfg { + const char *name; + int kohms; +}; + +struct x9250 { + struct spi_device *spi; + const struct x9250_cfg *cfg; + struct gpio_desc *wp_gpio; +}; + +#define X9250_ID 0x50 +#define X9250_CMD_RD_WCR(_p) (0x90 | (_p)) +#define X9250_CMD_WR_WCR(_p) (0xa0 | (_p)) + +static int x9250_write8(struct x9250 *x9250, u8 cmd, u8 val) +{ + u8 txbuf[3]; + + txbuf[0] = X9250_ID; + txbuf[1] = cmd; + txbuf[2] = val; + + return spi_write_then_read(x9250->spi, txbuf, ARRAY_SIZE(txbuf), NULL, 0); +} + +static int x9250_read8(struct x9250 *x9250, u8 cmd, u8 *val) +{ + u8 txbuf[2]; + + txbuf[0] = X9250_ID; + txbuf[1] = cmd; + + return spi_write_then_read(x9250->spi, txbuf, ARRAY_SIZE(txbuf), val, 1); +} + +#define X9250_CHANNEL(ch) { \ + .type = IIO_RESISTANCE, \ + .indexed = 1, \ + .output = 1, \ + .channel = (ch), \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ + .info_mask_shared_by_type_available = BIT(IIO_CHAN_INFO_RAW), \ +} + +static const struct iio_chan_spec x9250_channels[] = { + X9250_CHANNEL(0), + X9250_CHANNEL(1), + X9250_CHANNEL(2), + X9250_CHANNEL(3), +}; + +static int x9250_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct x9250 *x9250 = iio_priv(indio_dev); + int ch = chan->channel; + int ret; + u8 v; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + ret = x9250_read8(x9250, X9250_CMD_RD_WCR(ch), &v); + if (ret) + return ret; + *val = v; + return IIO_VAL_INT; + + case IIO_CHAN_INFO_SCALE: + *val = 1000 * x9250->cfg->kohms; + *val2 = U8_MAX; + return IIO_VAL_FRACTIONAL; + } + + return -EINVAL; +} + +static int x9250_read_avail(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, + const int **vals, int *type, int *length, long mask) +{ + static const int range[] = {0, 1, 255}; /* min, step, max */ + + switch (mask) { + case IIO_CHAN_INFO_RAW: + *length = ARRAY_SIZE(range); + *vals = range; + *type = IIO_VAL_INT; + return IIO_AVAIL_RANGE; + } + + return -EINVAL; +} + +static int x9250_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, + int val, int val2, long mask) +{ + struct x9250 *x9250 = iio_priv(indio_dev); + int ch = chan->channel; + int ret; + + if (mask != IIO_CHAN_INFO_RAW) + return -EINVAL; + + if (val > U8_MAX || val < 0) + return -EINVAL; + + gpiod_set_value_cansleep(x9250->wp_gpio, 0); + ret = x9250_write8(x9250, X9250_CMD_WR_WCR(ch), val); + gpiod_set_value_cansleep(x9250->wp_gpio, 1); + + return ret; +} + +static const struct iio_info x9250_info = { + .read_raw = x9250_read_raw, + .read_avail = x9250_read_avail, + .write_raw = x9250_write_raw, +}; + +enum x9250_type { + X9250T, + X9250U, +}; + +static const struct x9250_cfg x9250_cfg[] = { + [X9250T] = { .name = "x9250t", .kohms = 100, }, + [X9250U] = { .name = "x9250u", .kohms = 50, }, +}; + +static const char *const x9250_regulator_names[] = { + "vcc", + "avp", + "avn", +}; + +static int x9250_probe(struct spi_device *spi) +{ + struct iio_dev *indio_dev; + struct x9250 *x9250; + int ret; + + ret = devm_regulator_bulk_get_enable(&spi->dev, ARRAY_SIZE(x9250_regulator_names), + x9250_regulator_names); + if (ret) + return dev_err_probe(&spi->dev, ret, "Failed to get regulators\n"); + + /* + * The x9250 needs a 5ms maximum delay after the power-supplies are set + * before performing the first write (1ms for the first read). + */ + usleep_range(5000, 6000); + + indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*x9250)); + if (!indio_dev) + return -ENOMEM; + + x9250 = iio_priv(indio_dev); + x9250->spi = spi; + x9250->cfg = spi_get_device_match_data(spi); + x9250->wp_gpio = devm_gpiod_get_optional(&spi->dev, "wp", GPIOD_OUT_LOW); + if (IS_ERR(x9250->wp_gpio)) + return dev_err_probe(&spi->dev, PTR_ERR(x9250->wp_gpio), + "failed to get wp gpio\n"); + + indio_dev->info = &x9250_info; + indio_dev->channels = x9250_channels; + indio_dev->num_channels = ARRAY_SIZE(x9250_channels); + indio_dev->name = x9250->cfg->name; + + return devm_iio_device_register(&spi->dev, indio_dev); +} + +static const struct of_device_id x9250_of_match[] = { + { .compatible = "renesas,x9250t", .data = &x9250_cfg[X9250T]}, + { .compatible = "renesas,x9250u", .data = &x9250_cfg[X9250U]}, + { } +}; +MODULE_DEVICE_TABLE(of, x9250_of_match); + +static const struct spi_device_id x9250_id_table[] = { + { "x9250t", (kernel_ulong_t)&x9250_cfg[X9250T] }, + { "x9250u", (kernel_ulong_t)&x9250_cfg[X9250U] }, + { } +}; +MODULE_DEVICE_TABLE(spi, x9250_id_table); + +static struct spi_driver x9250_spi_driver = { + .driver = { + .name = "x9250", + .of_match_table = x9250_of_match, + }, + .id_table = x9250_id_table, + .probe = x9250_probe, +}; + +module_spi_driver(x9250_spi_driver); + +MODULE_AUTHOR("Herve Codina "); +MODULE_DESCRIPTION("X9250 ALSA SoC driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/iio/potentiostat/lmp91000.c b/drivers/iio/potentiostat/lmp91000.c index 0083e858c21ecbc7f1e9674bb18c9176c8f94c15..bd0f2c3bf2f2d0b33c3f613bf77f6b355bc44fcb 100644 --- a/drivers/iio/potentiostat/lmp91000.c +++ b/drivers/iio/potentiostat/lmp91000.c @@ -416,7 +416,7 @@ static struct i2c_driver lmp91000_driver = { .name = LMP91000_DRV_NAME, .of_match_table = lmp91000_of_match, }, - .probe_new = lmp91000_probe, + .probe = lmp91000_probe, .remove = lmp91000_remove, .id_table = lmp91000_id, }; diff --git a/drivers/iio/pressure/Kconfig b/drivers/iio/pressure/Kconfig index 02b97e89de505d249b7408c51a17c165b9508f64..7b4c2af32852f6e5849be8402b6aaa9bb8291816 100644 --- a/drivers/iio/pressure/Kconfig +++ b/drivers/iio/pressure/Kconfig @@ -148,6 +148,19 @@ config MPL3115 To compile this driver as a module, choose M here: the module will be called mpl3115. +config MPRLS0025PA + tristate "Honeywell MPRLS0025PA (MicroPressure sensors series)" + depends on I2C + select IIO_BUFFER + select IIO_TRIGGERED_BUFFER + help + Say Y here to build support for the Honeywell MicroPressure pressure + sensor series. There are many different types with different pressure + range. These ranges can be set up in the device tree. + + To compile this driver as a module, choose M here: the module will be + called mprls0025pa. + config MS5611 tristate "Measurement Specialties MS5611 pressure sensor driver" select IIO_BUFFER diff --git a/drivers/iio/pressure/Makefile b/drivers/iio/pressure/Makefile index 083ae87ff48f5d24c9931de8549100f6a6cdef45..c90f77210e94d9079b4e8655aa8a75e8e36d8987 100644 --- a/drivers/iio/pressure/Makefile +++ b/drivers/iio/pressure/Makefile @@ -19,6 +19,7 @@ obj-$(CONFIG_MPL115) += mpl115.o obj-$(CONFIG_MPL115_I2C) += mpl115_i2c.o obj-$(CONFIG_MPL115_SPI) += mpl115_spi.o obj-$(CONFIG_MPL3115) += mpl3115.o +obj-$(CONFIG_MPRLS0025PA) += mprls0025pa.o obj-$(CONFIG_MS5611) += ms5611_core.o obj-$(CONFIG_MS5611_I2C) += ms5611_i2c.o obj-$(CONFIG_MS5611_SPI) += ms5611_spi.o diff --git a/drivers/iio/pressure/abp060mg.c b/drivers/iio/pressure/abp060mg.c index c0140779366aff6e6e14d7c7332f386dadb22e31..752a63c06b44c11c1d935732d00ffac41e5ff591 100644 --- a/drivers/iio/pressure/abp060mg.c +++ b/drivers/iio/pressure/abp060mg.c @@ -255,7 +255,7 @@ static struct i2c_driver abp060mg_driver = { .driver = { .name = "abp060mg", }, - .probe_new = abp060mg_probe, + .probe = abp060mg_probe, .id_table = abp060mg_id_table, }; module_i2c_driver(abp060mg_driver); diff --git a/drivers/iio/pressure/bmp280-i2c.c b/drivers/iio/pressure/bmp280-i2c.c index 567b945e6427af979bb8c6adf7f98f73daf2ed3c..dbe630ad05b5a8c820230806b46caecf53904d56 100644 --- a/drivers/iio/pressure/bmp280-i2c.c +++ b/drivers/iio/pressure/bmp280-i2c.c @@ -56,7 +56,7 @@ static struct i2c_driver bmp280_i2c_driver = { .of_match_table = bmp280_of_i2c_match, .pm = pm_ptr(&bmp280_dev_pm_ops), }, - .probe_new = bmp280_i2c_probe, + .probe = bmp280_i2c_probe, .id_table = bmp280_i2c_id, }; module_i2c_driver(bmp280_i2c_driver); diff --git a/drivers/iio/pressure/dlhl60d.c b/drivers/iio/pressure/dlhl60d.c index 43650b048d6295e2f9fac9cd4dc1e20f0e524977..28c8269ba65d31f1547fc0e35c0fc9465c4b9740 100644 --- a/drivers/iio/pressure/dlhl60d.c +++ b/drivers/iio/pressure/dlhl60d.c @@ -362,7 +362,7 @@ static struct i2c_driver dlh_driver = { .name = "dlhl60d", .of_match_table = dlh_of_match, }, - .probe_new = dlh_probe, + .probe = dlh_probe, .id_table = dlh_id, }; module_i2c_driver(dlh_driver); diff --git a/drivers/iio/pressure/dps310.c b/drivers/iio/pressure/dps310.c index 2af275a24ff9e29fbab8d7aed58a5b63c7e03eea..b10dbf5cf494091a60d281178a7785653b6d2eb1 100644 --- a/drivers/iio/pressure/dps310.c +++ b/drivers/iio/pressure/dps310.c @@ -887,7 +887,7 @@ static struct i2c_driver dps310_driver = { .name = DPS310_DEV_NAME, .acpi_match_table = dps310_acpi_match, }, - .probe_new = dps310_probe, + .probe = dps310_probe, .id_table = dps310_id, }; module_i2c_driver(dps310_driver); diff --git a/drivers/iio/pressure/hp03.c b/drivers/iio/pressure/hp03.c index bd1f71a99cfa3d24f96b947514117224ce1de2c0..8bdb279129fa21df271c3b2dfe0ff95571baf667 100644 --- a/drivers/iio/pressure/hp03.c +++ b/drivers/iio/pressure/hp03.c @@ -282,7 +282,7 @@ static struct i2c_driver hp03_driver = { .name = "hp03", .of_match_table = hp03_of_match, }, - .probe_new = hp03_probe, + .probe = hp03_probe, .id_table = hp03_id, }; module_i2c_driver(hp03_driver); diff --git a/drivers/iio/pressure/hp206c.c b/drivers/iio/pressure/hp206c.c index b6d2ff46434194a681bd9e96acf20fdb0256d97e..a072de6cb59c7f82240156e73cc2699fcc29c152 100644 --- a/drivers/iio/pressure/hp206c.c +++ b/drivers/iio/pressure/hp206c.c @@ -409,7 +409,7 @@ MODULE_DEVICE_TABLE(acpi, hp206c_acpi_match); #endif static struct i2c_driver hp206c_driver = { - .probe_new = hp206c_probe, + .probe = hp206c_probe, .id_table = hp206c_id, .driver = { .name = "hp206c", diff --git a/drivers/iio/pressure/icp10100.c b/drivers/iio/pressure/icp10100.c index 407cf25ea0e335e7dde1373260db4d01b76f8323..2086f3ef338fefb6519c92b59d461beff15ef596 100644 --- a/drivers/iio/pressure/icp10100.c +++ b/drivers/iio/pressure/icp10100.c @@ -648,7 +648,7 @@ static struct i2c_driver icp10100_driver = { .pm = pm_ptr(&icp10100_pm), .of_match_table = icp10100_of_match, }, - .probe_new = icp10100_probe, + .probe = icp10100_probe, .id_table = icp10100_id, }; module_i2c_driver(icp10100_driver); diff --git a/drivers/iio/pressure/mpl115_i2c.c b/drivers/iio/pressure/mpl115_i2c.c index ade4dd854ddf1b57f3ef1aa30086d0d1efeb8313..fcbdadf4a51189e34f0b58fc9154fed4ea2e96d6 100644 --- a/drivers/iio/pressure/mpl115_i2c.c +++ b/drivers/iio/pressure/mpl115_i2c.c @@ -55,7 +55,7 @@ static struct i2c_driver mpl115_i2c_driver = { .name = "mpl115", .pm = pm_ptr(&mpl115_dev_pm_ops), }, - .probe_new = mpl115_i2c_probe, + .probe = mpl115_i2c_probe, .id_table = mpl115_i2c_id, }; module_i2c_driver(mpl115_i2c_driver); diff --git a/drivers/iio/pressure/mpl3115.c b/drivers/iio/pressure/mpl3115.c index 72e811a5c96e607bf63e26eb5b755263d916cf26..7aa19584c340c16c836822b93a527570a51e5755 100644 --- a/drivers/iio/pressure/mpl3115.c +++ b/drivers/iio/pressure/mpl3115.c @@ -335,7 +335,7 @@ static struct i2c_driver mpl3115_driver = { .of_match_table = mpl3115_of_match, .pm = pm_sleep_ptr(&mpl3115_pm_ops), }, - .probe_new = mpl3115_probe, + .probe = mpl3115_probe, .remove = mpl3115_remove, .id_table = mpl3115_id, }; diff --git a/drivers/iio/pressure/mprls0025pa.c b/drivers/iio/pressure/mprls0025pa.c new file mode 100644 index 0000000000000000000000000000000000000000..30fb2de368210f40705f7d9f251d735354a46936 --- /dev/null +++ b/drivers/iio/pressure/mprls0025pa.c @@ -0,0 +1,450 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * MPRLS0025PA - Honeywell MicroPressure pressure sensor series driver + * + * Copyright (c) Andreas Klinger + * + * Data sheet: + * https://prod-edam.honeywell.com/content/dam/honeywell-edam/sps/siot/en-us/ + * products/sensors/pressure-sensors/board-mount-pressure-sensors/ + * micropressure-mpr-series/documents/ + * sps-siot-mpr-series-datasheet-32332628-ciid-172626.pdf + * + * 7-bit I2C default slave address: 0x18 + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include + +#include + +/* bits in i2c status byte */ +#define MPR_I2C_POWER BIT(6) /* device is powered */ +#define MPR_I2C_BUSY BIT(5) /* device is busy */ +#define MPR_I2C_MEMORY BIT(2) /* integrity test passed */ +#define MPR_I2C_MATH BIT(0) /* internal math saturation */ + +/* + * support _RAW sysfs interface: + * + * Calculation formula from the datasheet: + * pressure = (press_cnt - outputmin) * scale + pmin + * with: + * * pressure - measured pressure in Pascal + * * press_cnt - raw value read from sensor + * * pmin - minimum pressure range value of sensor (data->pmin) + * * pmax - maximum pressure range value of sensor (data->pmax) + * * outputmin - minimum numerical range raw value delivered by sensor + * (mpr_func_spec.output_min) + * * outputmax - maximum numerical range raw value delivered by sensor + * (mpr_func_spec.output_max) + * * scale - (pmax - pmin) / (outputmax - outputmin) + * + * formula of the userspace: + * pressure = (raw + offset) * scale + * + * Values given to the userspace in sysfs interface: + * * raw - press_cnt + * * offset - (-1 * outputmin) - pmin / scale + * note: With all sensors from the datasheet pmin = 0 + * which reduces the offset to (-1 * outputmin) + */ + +/* + * transfer function A: 10% to 90% of 2^24 + * transfer function B: 2.5% to 22.5% of 2^24 + * transfer function C: 20% to 80% of 2^24 + */ +enum mpr_func_id { + MPR_FUNCTION_A, + MPR_FUNCTION_B, + MPR_FUNCTION_C, +}; + +struct mpr_func_spec { + u32 output_min; + u32 output_max; +}; + +static const struct mpr_func_spec mpr_func_spec[] = { + [MPR_FUNCTION_A] = {.output_min = 1677722, .output_max = 15099494}, + [MPR_FUNCTION_B] = {.output_min = 419430, .output_max = 3774874}, + [MPR_FUNCTION_C] = {.output_min = 3355443, .output_max = 13421773}, +}; + +struct mpr_chan { + s32 pres; /* pressure value */ + s64 ts; /* timestamp */ +}; + +struct mpr_data { + struct i2c_client *client; + struct mutex lock; /* + * access to device during read + */ + u32 pmin; /* minimal pressure in pascal */ + u32 pmax; /* maximal pressure in pascal */ + enum mpr_func_id function; /* transfer function */ + u32 outmin; /* + * minimal numerical range raw + * value from sensor + */ + u32 outmax; /* + * maximal numerical range raw + * value from sensor + */ + int scale; /* int part of scale */ + int scale2; /* nano part of scale */ + int offset; /* int part of offset */ + int offset2; /* nano part of offset */ + struct gpio_desc *gpiod_reset; /* reset */ + int irq; /* + * end of conversion irq; + * used to distinguish between + * irq mode and reading in a + * loop until data is ready + */ + struct completion completion; /* handshake from irq to read */ + struct mpr_chan chan; /* + * channel values for buffered + * mode + */ +}; + +static const struct iio_chan_spec mpr_channels[] = { + { + .type = IIO_PRESSURE, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_SCALE) | + BIT(IIO_CHAN_INFO_OFFSET), + .scan_index = 0, + .scan_type = { + .sign = 's', + .realbits = 32, + .storagebits = 32, + .endianness = IIO_CPU, + }, + }, + IIO_CHAN_SOFT_TIMESTAMP(1), +}; + +static void mpr_reset(struct mpr_data *data) +{ + if (data->gpiod_reset) { + gpiod_set_value(data->gpiod_reset, 0); + udelay(10); + gpiod_set_value(data->gpiod_reset, 1); + } +} + +/** + * mpr_read_pressure() - Read pressure value from sensor via I2C + * @data: Pointer to private data struct. + * @press: Output value read from sensor. + * + * Reading from the sensor by sending and receiving I2C telegrams. + * + * If there is an end of conversion (EOC) interrupt registered the function + * waits for a maximum of one second for the interrupt. + * + * Context: The function can sleep and data->lock should be held when calling it + * Return: + * * 0 - OK, the pressure value could be read + * * -ETIMEDOUT - Timeout while waiting for the EOC interrupt or busy flag is + * still set after nloops attempts of reading + */ +static int mpr_read_pressure(struct mpr_data *data, s32 *press) +{ + struct device *dev = &data->client->dev; + int ret, i; + u8 wdata[] = {0xAA, 0x00, 0x00}; + s32 status; + int nloops = 10; + u8 buf[4]; + + reinit_completion(&data->completion); + + ret = i2c_master_send(data->client, wdata, sizeof(wdata)); + if (ret < 0) { + dev_err(dev, "error while writing ret: %d\n", ret); + return ret; + } + if (ret != sizeof(wdata)) { + dev_err(dev, "received size doesn't fit - ret: %d / %u\n", ret, + (u32)sizeof(wdata)); + return -EIO; + } + + if (data->irq > 0) { + ret = wait_for_completion_timeout(&data->completion, HZ); + if (!ret) { + dev_err(dev, "timeout while waiting for eoc irq\n"); + return -ETIMEDOUT; + } + } else { + /* wait until status indicates data is ready */ + for (i = 0; i < nloops; i++) { + /* + * datasheet only says to wait at least 5 ms for the + * data but leave the maximum response time open + * --> let's try it nloops (10) times which seems to be + * quite long + */ + usleep_range(5000, 10000); + status = i2c_smbus_read_byte(data->client); + if (status < 0) { + dev_err(dev, + "error while reading, status: %d\n", + status); + return status; + } + if (!(status & MPR_I2C_BUSY)) + break; + } + if (i == nloops) { + dev_err(dev, "timeout while reading\n"); + return -ETIMEDOUT; + } + } + + ret = i2c_master_recv(data->client, buf, sizeof(buf)); + if (ret < 0) { + dev_err(dev, "error in i2c_master_recv ret: %d\n", ret); + return ret; + } + if (ret != sizeof(buf)) { + dev_err(dev, "received size doesn't fit - ret: %d / %u\n", ret, + (u32)sizeof(buf)); + return -EIO; + } + + if (buf[0] & MPR_I2C_BUSY) { + /* + * it should never be the case that status still indicates + * business + */ + dev_err(dev, "data still not ready: %08x\n", buf[0]); + return -ETIMEDOUT; + } + + *press = get_unaligned_be24(&buf[1]); + + dev_dbg(dev, "received: %*ph cnt: %d\n", ret, buf, *press); + + return 0; +} + +static irqreturn_t mpr_eoc_handler(int irq, void *p) +{ + struct mpr_data *data = p; + + complete(&data->completion); + + return IRQ_HANDLED; +} + +static irqreturn_t mpr_trigger_handler(int irq, void *p) +{ + int ret; + struct iio_poll_func *pf = p; + struct iio_dev *indio_dev = pf->indio_dev; + struct mpr_data *data = iio_priv(indio_dev); + + mutex_lock(&data->lock); + ret = mpr_read_pressure(data, &data->chan.pres); + if (ret < 0) + goto err; + + iio_push_to_buffers_with_timestamp(indio_dev, &data->chan, + iio_get_time_ns(indio_dev)); + +err: + mutex_unlock(&data->lock); + iio_trigger_notify_done(indio_dev->trig); + + return IRQ_HANDLED; +} + +static int mpr_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int *val, int *val2, long mask) +{ + int ret; + s32 pressure; + struct mpr_data *data = iio_priv(indio_dev); + + if (chan->type != IIO_PRESSURE) + return -EINVAL; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + mutex_lock(&data->lock); + ret = mpr_read_pressure(data, &pressure); + mutex_unlock(&data->lock); + if (ret < 0) + return ret; + *val = pressure; + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + *val = data->scale; + *val2 = data->scale2; + return IIO_VAL_INT_PLUS_NANO; + case IIO_CHAN_INFO_OFFSET: + *val = data->offset; + *val2 = data->offset2; + return IIO_VAL_INT_PLUS_NANO; + default: + return -EINVAL; + } +} + +static const struct iio_info mpr_info = { + .read_raw = &mpr_read_raw, +}; + +static int mpr_probe(struct i2c_client *client) +{ + int ret; + struct mpr_data *data; + struct iio_dev *indio_dev; + struct device *dev = &client->dev; + s64 scale, offset; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_BYTE)) + return dev_err_probe(dev, -EOPNOTSUPP, + "I2C functionality not supported\n"); + + indio_dev = devm_iio_device_alloc(dev, sizeof(*data)); + if (!indio_dev) + return dev_err_probe(dev, -ENOMEM, "couldn't get iio_dev\n"); + + data = iio_priv(indio_dev); + data->client = client; + data->irq = client->irq; + + mutex_init(&data->lock); + init_completion(&data->completion); + + indio_dev->name = "mprls0025pa"; + indio_dev->info = &mpr_info; + indio_dev->channels = mpr_channels; + indio_dev->num_channels = ARRAY_SIZE(mpr_channels); + indio_dev->modes = INDIO_DIRECT_MODE; + + ret = devm_regulator_get_enable(dev, "vdd"); + if (ret) + return dev_err_probe(dev, ret, + "can't get and enable vdd supply\n"); + + if (dev_fwnode(dev)) { + ret = device_property_read_u32(dev, "honeywell,pmin-pascal", + &data->pmin); + if (ret) + return dev_err_probe(dev, ret, + "honeywell,pmin-pascal could not be read\n"); + ret = device_property_read_u32(dev, "honeywell,pmax-pascal", + &data->pmax); + if (ret) + return dev_err_probe(dev, ret, + "honeywell,pmax-pascal could not be read\n"); + ret = device_property_read_u32(dev, + "honeywell,transfer-function", &data->function); + if (ret) + return dev_err_probe(dev, ret, + "honeywell,transfer-function could not be read\n"); + if (data->function > MPR_FUNCTION_C) + return dev_err_probe(dev, -EINVAL, + "honeywell,transfer-function %d invalid\n", + data->function); + } else { + /* when loaded as i2c device we need to use default values */ + dev_notice(dev, "firmware node not found; using defaults\n"); + data->pmin = 0; + data->pmax = 172369; /* 25 psi */ + data->function = MPR_FUNCTION_A; + } + + data->outmin = mpr_func_spec[data->function].output_min; + data->outmax = mpr_func_spec[data->function].output_max; + + /* use 64 bit calculation for preserving a reasonable precision */ + scale = div_s64(((s64)(data->pmax - data->pmin)) * NANO, + data->outmax - data->outmin); + data->scale = div_s64_rem(scale, NANO, &data->scale2); + /* + * multiply with NANO before dividing by scale and later divide by NANO + * again. + */ + offset = ((-1LL) * (s64)data->outmin) * NANO - + div_s64(div_s64((s64)data->pmin * NANO, scale), NANO); + data->offset = div_s64_rem(offset, NANO, &data->offset2); + + if (data->irq > 0) { + ret = devm_request_irq(dev, data->irq, mpr_eoc_handler, + IRQF_TRIGGER_RISING, client->name, data); + if (ret) + return dev_err_probe(dev, ret, + "request irq %d failed\n", data->irq); + } + + data->gpiod_reset = devm_gpiod_get_optional(dev, "reset", + GPIOD_OUT_HIGH); + if (IS_ERR(data->gpiod_reset)) + return dev_err_probe(dev, PTR_ERR(data->gpiod_reset), + "request reset-gpio failed\n"); + + mpr_reset(data); + + ret = devm_iio_triggered_buffer_setup(dev, indio_dev, NULL, + mpr_trigger_handler, NULL); + if (ret) + return dev_err_probe(dev, ret, + "iio triggered buffer setup failed\n"); + + ret = devm_iio_device_register(dev, indio_dev); + if (ret) + return dev_err_probe(dev, ret, + "unable to register iio device\n"); + + return 0; +} + +static const struct of_device_id mpr_matches[] = { + { .compatible = "honeywell,mprls0025pa" }, + { } +}; +MODULE_DEVICE_TABLE(of, mpr_matches); + +static const struct i2c_device_id mpr_id[] = { + { "mprls0025pa" }, + { } +}; +MODULE_DEVICE_TABLE(i2c, mpr_id); + +static struct i2c_driver mpr_driver = { + .probe = mpr_probe, + .id_table = mpr_id, + .driver = { + .name = "mprls0025pa", + .of_match_table = mpr_matches, + }, +}; +module_i2c_driver(mpr_driver); + +MODULE_AUTHOR("Andreas Klinger "); +MODULE_DESCRIPTION("Honeywell MPRLS0025PA I2C driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/iio/pressure/ms5611_i2c.c b/drivers/iio/pressure/ms5611_i2c.c index e3c68a3ed76ace11148cd034e231a4d3bca85ca2..9a0f52321fcb9d9bbf08acb4b5e527aea7caa8ba 100644 --- a/drivers/iio/pressure/ms5611_i2c.c +++ b/drivers/iio/pressure/ms5611_i2c.c @@ -125,7 +125,7 @@ static struct i2c_driver ms5611_driver = { .of_match_table = ms5611_i2c_matches, }, .id_table = ms5611_id, - .probe_new = ms5611_i2c_probe, + .probe = ms5611_i2c_probe, }; module_i2c_driver(ms5611_driver); diff --git a/drivers/iio/pressure/ms5637.c b/drivers/iio/pressure/ms5637.c index c4981b29dccb1716c87af5a793962d81c709c7d6..9b3abffb724b600d5ed6a25d4691937d3b5d0a64 100644 --- a/drivers/iio/pressure/ms5637.c +++ b/drivers/iio/pressure/ms5637.c @@ -238,7 +238,7 @@ static const struct of_device_id ms5637_of_match[] = { MODULE_DEVICE_TABLE(of, ms5637_of_match); static struct i2c_driver ms5637_driver = { - .probe_new = ms5637_probe, + .probe = ms5637_probe, .id_table = ms5637_id, .driver = { .name = "ms5637", diff --git a/drivers/iio/pressure/st_pressure_i2c.c b/drivers/iio/pressure/st_pressure_i2c.c index f2c3bb568d16ba3f1bb71b37f8ec450090757c96..5101552e3f3849dd9b9660438a50ad482b51f56f 100644 --- a/drivers/iio/pressure/st_pressure_i2c.c +++ b/drivers/iio/pressure/st_pressure_i2c.c @@ -116,7 +116,7 @@ static struct i2c_driver st_press_driver = { .of_match_table = st_press_of_match, .acpi_match_table = ACPI_PTR(st_press_acpi_match), }, - .probe_new = st_press_i2c_probe, + .probe = st_press_i2c_probe, .id_table = st_press_id_table, }; module_i2c_driver(st_press_driver); diff --git a/drivers/iio/pressure/t5403.c b/drivers/iio/pressure/t5403.c index 2fbf14aff03392e29d6b58bf585f85084d21ef6d..a6463c06975eb5fcb416cea086941fa6c7d0e17a 100644 --- a/drivers/iio/pressure/t5403.c +++ b/drivers/iio/pressure/t5403.c @@ -260,7 +260,7 @@ static struct i2c_driver t5403_driver = { .driver = { .name = "t5403", }, - .probe_new = t5403_probe, + .probe = t5403_probe, .id_table = t5403_id, }; module_i2c_driver(t5403_driver); diff --git a/drivers/iio/pressure/zpa2326_i2c.c b/drivers/iio/pressure/zpa2326_i2c.c index ade465014be1ed61f7910689ce442771b2200d97..c7fffbe7c788ab3263e45c78c348433a3f9257da 100644 --- a/drivers/iio/pressure/zpa2326_i2c.c +++ b/drivers/iio/pressure/zpa2326_i2c.c @@ -76,7 +76,7 @@ static struct i2c_driver zpa2326_i2c_driver = { .of_match_table = zpa2326_i2c_matches, .pm = ZPA2326_PM_OPS, }, - .probe_new = zpa2326_probe_i2c, + .probe = zpa2326_probe_i2c, .remove = zpa2326_remove_i2c, .id_table = zpa2326_i2c_ids, }; diff --git a/drivers/iio/proximity/isl29501.c b/drivers/iio/proximity/isl29501.c index 7b8f40b7ccf33081654b6d4dcdf95f06677bd457..fe45ca35a124e53c7a6c44b799a1c48e755c85c4 100644 --- a/drivers/iio/proximity/isl29501.c +++ b/drivers/iio/proximity/isl29501.c @@ -1008,7 +1008,7 @@ static struct i2c_driver isl29501_driver = { .name = "isl29501", }, .id_table = isl29501_id, - .probe_new = isl29501_probe, + .probe = isl29501_probe, }; module_i2c_driver(isl29501_driver); diff --git a/drivers/iio/proximity/mb1232.c b/drivers/iio/proximity/mb1232.c index e70cac8240afc7d72d1d8d172b22ad3a6e76c0aa..fb1073c8d9f7892fce9a3df61a89bf801a885ec7 100644 --- a/drivers/iio/proximity/mb1232.c +++ b/drivers/iio/proximity/mb1232.c @@ -264,7 +264,7 @@ static struct i2c_driver mb1232_driver = { .name = "maxbotix-mb1232", .of_match_table = of_mb1232_match, }, - .probe_new = mb1232_probe, + .probe = mb1232_probe, .id_table = mb1232_id, }; module_i2c_driver(mb1232_driver); diff --git a/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c b/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c index c9eead01a0314c92affc6cef7f3a7d33f4e8d7e4..2913d5e0fe4f99576ed2b7cf7e5c0645e6844c94 100644 --- a/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c +++ b/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c @@ -365,7 +365,7 @@ static struct i2c_driver lidar_driver = { .of_match_table = lidar_dt_ids, .pm = pm_ptr(&lidar_pm_ops), }, - .probe_new = lidar_probe, + .probe = lidar_probe, .remove = lidar_remove, .id_table = lidar_id, }; diff --git a/drivers/iio/proximity/rfd77402.c b/drivers/iio/proximity/rfd77402.c index 44f72b78bd5063a797c10e3f12d7f570575495fd..f02e83e3f15f34628da3be5fab40d6d3e5befd21 100644 --- a/drivers/iio/proximity/rfd77402.c +++ b/drivers/iio/proximity/rfd77402.c @@ -318,7 +318,7 @@ static struct i2c_driver rfd77402_driver = { .name = RFD77402_DRV_NAME, .pm = pm_sleep_ptr(&rfd77402_pm_ops), }, - .probe_new = rfd77402_probe, + .probe = rfd77402_probe, .id_table = rfd77402_id, }; diff --git a/drivers/iio/proximity/srf08.c b/drivers/iio/proximity/srf08.c index 61866d0440f76f7827ee6d64aea51395d96d9da3..a75ea50428767cba22bc5306460674762aa5b9b1 100644 --- a/drivers/iio/proximity/srf08.c +++ b/drivers/iio/proximity/srf08.c @@ -549,7 +549,7 @@ static struct i2c_driver srf08_driver = { .name = "srf08", .of_match_table = of_srf08_match, }, - .probe_new = srf08_probe, + .probe = srf08_probe, .id_table = srf08_id, }; module_i2c_driver(srf08_driver); diff --git a/drivers/iio/proximity/sx9310.c b/drivers/iio/proximity/sx9310.c index 0e4747ccd3cf74c6c2cb7ebc64a4d80b730ba1aa..d977aacb74919a3473039cea004cb32d1c8bfaa8 100644 --- a/drivers/iio/proximity/sx9310.c +++ b/drivers/iio/proximity/sx9310.c @@ -1050,7 +1050,7 @@ static struct i2c_driver sx9310_driver = { */ .probe_type = PROBE_PREFER_ASYNCHRONOUS, }, - .probe_new = sx9310_probe, + .probe = sx9310_probe, .id_table = sx9310_id, }; module_i2c_driver(sx9310_driver); diff --git a/drivers/iio/proximity/sx9324.c b/drivers/iio/proximity/sx9324.c index 9a40ca32bb1ca637dd5f5837390a4049f41cabe5..438f9c9aba6eaf9b8135bd6bb697798db72c25a4 100644 --- a/drivers/iio/proximity/sx9324.c +++ b/drivers/iio/proximity/sx9324.c @@ -1152,7 +1152,7 @@ static struct i2c_driver sx9324_driver = { */ .probe_type = PROBE_PREFER_ASYNCHRONOUS, }, - .probe_new = sx9324_probe, + .probe = sx9324_probe, .id_table = sx9324_id, }; module_i2c_driver(sx9324_driver); diff --git a/drivers/iio/proximity/sx9360.c b/drivers/iio/proximity/sx9360.c index a50d9176411a1345b89444a0f94bd79db18994ab..2c4e14a4fe9fbde8005bbdc1807e20f3c5b218f3 100644 --- a/drivers/iio/proximity/sx9360.c +++ b/drivers/iio/proximity/sx9360.c @@ -896,7 +896,7 @@ static struct i2c_driver sx9360_driver = { */ .probe_type = PROBE_PREFER_ASYNCHRONOUS, }, - .probe_new = sx9360_probe, + .probe = sx9360_probe, .id_table = sx9360_id, }; module_i2c_driver(sx9360_driver); diff --git a/drivers/iio/proximity/sx9500.c b/drivers/iio/proximity/sx9500.c index 9b2cfcade6a49bf4f1f4d558d6f9d6e80ac6dc65..550e7d3cd5ee5ed2346d7ca0319fe2640471a8e8 100644 --- a/drivers/iio/proximity/sx9500.c +++ b/drivers/iio/proximity/sx9500.c @@ -1055,7 +1055,7 @@ static struct i2c_driver sx9500_driver = { .of_match_table = sx9500_of_match, .pm = pm_sleep_ptr(&sx9500_pm_ops), }, - .probe_new = sx9500_probe, + .probe = sx9500_probe, .remove = sx9500_remove, .id_table = sx9500_id, }; diff --git a/drivers/iio/proximity/vcnl3020.c b/drivers/iio/proximity/vcnl3020.c index cbc8400c773c4664da5fe7e8677846999cbe8a4e..d1ddf85f53836ec34464d382426b187804964a57 100644 --- a/drivers/iio/proximity/vcnl3020.c +++ b/drivers/iio/proximity/vcnl3020.c @@ -662,7 +662,7 @@ static struct i2c_driver vcnl3020_driver = { .name = "vcnl3020", .of_match_table = vcnl3020_of_match, }, - .probe_new = vcnl3020_probe, + .probe = vcnl3020_probe, }; module_i2c_driver(vcnl3020_driver); diff --git a/drivers/iio/proximity/vl53l0x-i2c.c b/drivers/iio/proximity/vl53l0x-i2c.c index c7c4d33d340f0adfa701464b0569728156f3b2f5..2cea64bea9098657bd482c52223c12836e984404 100644 --- a/drivers/iio/proximity/vl53l0x-i2c.c +++ b/drivers/iio/proximity/vl53l0x-i2c.c @@ -294,7 +294,7 @@ static struct i2c_driver vl53l0x_driver = { .name = "vl53l0x-i2c", .of_match_table = st_vl53l0x_dt_match, }, - .probe_new = vl53l0x_probe, + .probe = vl53l0x_probe, .id_table = vl53l0x_id, }; module_i2c_driver(vl53l0x_driver); diff --git a/drivers/iio/temperature/max30208.c b/drivers/iio/temperature/max30208.c index c85c21474711f47d8a345271b135d6c7645cfb5b..48be03852cd8dfa869ebe244be7458758e1c1fb4 100644 --- a/drivers/iio/temperature/max30208.c +++ b/drivers/iio/temperature/max30208.c @@ -242,7 +242,7 @@ static struct i2c_driver max30208_driver = { .of_match_table = max30208_of_match, .acpi_match_table = max30208_acpi_match, }, - .probe_new = max30208_probe, + .probe = max30208_probe, .id_table = max30208_id_table, }; module_i2c_driver(max30208_driver); diff --git a/drivers/iio/temperature/mlx90614.c b/drivers/iio/temperature/mlx90614.c index 909fadb623491ee7fe0ef940772aeba48371cf6e..676dc870192443e023c4d6596c127b380687fd30 100644 --- a/drivers/iio/temperature/mlx90614.c +++ b/drivers/iio/temperature/mlx90614.c @@ -1,12 +1,15 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * mlx90614.c - Support for Melexis MLX90614 contactless IR temperature sensor + * mlx90614.c - Support for Melexis MLX90614/MLX90615 contactless IR temperature sensor * * Copyright (c) 2014 Peter Meerwald * Copyright (c) 2015 Essensium NV * Copyright (c) 2015 Melexis * - * Driver for the Melexis MLX90614 I2C 16-bit IR thermopile sensor + * Driver for the Melexis MLX90614/MLX90615 I2C 16-bit IR thermopile sensor + * + * MLX90614 - 17-bit ADC + MLX90302 DSP + * MLX90615 - 16-bit ADC + MLX90325 DSP * * (7-bit I2C slave address 0x5a, 100KHz bus speed only!) * @@ -19,12 +22,13 @@ * the "wakeup" GPIO is not given, power management will be disabled. */ +#include #include +#include #include -#include -#include #include -#include +#include +#include #include #include @@ -34,16 +38,9 @@ #define MLX90614_OP_EEPROM 0x20 #define MLX90614_OP_SLEEP 0xff -/* RAM offsets with 16-bit data, MSB first */ -#define MLX90614_RAW1 (MLX90614_OP_RAM | 0x04) /* raw data IR channel 1 */ -#define MLX90614_RAW2 (MLX90614_OP_RAM | 0x05) /* raw data IR channel 2 */ -#define MLX90614_TA (MLX90614_OP_RAM | 0x06) /* ambient temperature */ -#define MLX90614_TOBJ1 (MLX90614_OP_RAM | 0x07) /* object 1 temperature */ -#define MLX90614_TOBJ2 (MLX90614_OP_RAM | 0x08) /* object 2 temperature */ - -/* EEPROM offsets with 16-bit data, MSB first */ -#define MLX90614_EMISSIVITY (MLX90614_OP_EEPROM | 0x04) /* emissivity correction coefficient */ -#define MLX90614_CONFIG (MLX90614_OP_EEPROM | 0x05) /* configuration register */ +#define MLX90615_OP_EEPROM 0x10 +#define MLX90615_OP_RAM 0x20 +#define MLX90615_OP_SLEEP 0xc6 /* Control bits in configuration register */ #define MLX90614_CONFIG_IIR_SHIFT 0 /* IIR coefficient */ @@ -52,44 +49,61 @@ #define MLX90614_CONFIG_DUAL_MASK (1 << MLX90614_CONFIG_DUAL_SHIFT) #define MLX90614_CONFIG_FIR_SHIFT 8 /* FIR coefficient */ #define MLX90614_CONFIG_FIR_MASK (0x7 << MLX90614_CONFIG_FIR_SHIFT) -#define MLX90614_CONFIG_GAIN_SHIFT 11 /* gain */ -#define MLX90614_CONFIG_GAIN_MASK (0x7 << MLX90614_CONFIG_GAIN_SHIFT) + +#define MLX90615_CONFIG_IIR_SHIFT 12 /* IIR coefficient */ +#define MLX90615_CONFIG_IIR_MASK (0x7 << MLX90615_CONFIG_IIR_SHIFT) /* Timings (in ms) */ #define MLX90614_TIMING_EEPROM 20 /* time for EEPROM write/erase to complete */ #define MLX90614_TIMING_WAKEUP 34 /* time to hold SDA low for wake-up */ #define MLX90614_TIMING_STARTUP 250 /* time before first data after wake-up */ +#define MLX90615_TIMING_WAKEUP 22 /* time to hold SCL low for wake-up */ + #define MLX90614_AUTOSLEEP_DELAY 5000 /* default autosleep delay */ /* Magic constants */ #define MLX90614_CONST_OFFSET_DEC -13657 /* decimal part of the Kelvin offset */ #define MLX90614_CONST_OFFSET_REM 500000 /* remainder of offset (273.15*50) */ #define MLX90614_CONST_SCALE 20 /* Scale in milliKelvin (0.02 * 1000) */ -#define MLX90614_CONST_RAW_EMISSIVITY_MAX 65535 /* max value for emissivity */ -#define MLX90614_CONST_EMISSIVITY_RESOLUTION 15259 /* 1/65535 ~ 0.000015259 */ #define MLX90614_CONST_FIR 0x7 /* Fixed value for FIR part of low pass filter */ +/* Non-constant mask variant of FIELD_GET() and FIELD_PREP() */ +#define field_get(_mask, _reg) (((_reg) & (_mask)) >> (ffs(_mask) - 1)) +#define field_prep(_mask, _val) (((_val) << (ffs(_mask) - 1)) & (_mask)) + +struct mlx_chip_info { + /* EEPROM offsets with 16-bit data, MSB first */ + /* emissivity correction coefficient */ + u8 op_eeprom_emissivity; + u8 op_eeprom_config1; + /* RAM offsets with 16-bit data, MSB first */ + /* ambient temperature */ + u8 op_ram_ta; + /* object 1 temperature */ + u8 op_ram_tobj1; + /* object 2 temperature */ + u8 op_ram_tobj2; + u8 op_sleep; + /* support for two input channels (MLX90614 only) */ + u8 dual_channel; + u8 wakeup_delay_ms; + u16 emissivity_max; + u16 fir_config_mask; + u16 iir_config_mask; + int iir_valid_offset; + u16 iir_values[8]; + int iir_freqs[8][2]; +}; + struct mlx90614_data { struct i2c_client *client; struct mutex lock; /* for EEPROM access only */ struct gpio_desc *wakeup_gpio; /* NULL to disable sleep/wake-up */ + const struct mlx_chip_info *chip_info; /* Chip hardware details */ unsigned long ready_timestamp; /* in jiffies */ }; -/* Bandwidth values for IIR filtering */ -static const int mlx90614_iir_values[] = {77, 31, 20, 15, 723, 153, 110, 86}; -static const int mlx90614_freqs[][2] = { - {0, 150000}, - {0, 200000}, - {0, 310000}, - {0, 770000}, - {0, 860000}, - {1, 100000}, - {1, 530000}, - {7, 230000} -}; - /* * Erase an address and write word. * The mutex must be locked before calling. @@ -129,21 +143,26 @@ static s32 mlx90614_write_word(const struct i2c_client *client, u8 command, } /* - * Find the IIR value inside mlx90614_iir_values array and return its position + * Find the IIR value inside iir_values array and return its position * which is equivalent to the bit value in sensor register */ static inline s32 mlx90614_iir_search(const struct i2c_client *client, int value) { + struct iio_dev *indio_dev = i2c_get_clientdata(client); + struct mlx90614_data *data = iio_priv(indio_dev); + const struct mlx_chip_info *chip_info = data->chip_info; int i; s32 ret; - for (i = 0; i < ARRAY_SIZE(mlx90614_iir_values); ++i) { - if (value == mlx90614_iir_values[i]) + for (i = chip_info->iir_valid_offset; + i < ARRAY_SIZE(chip_info->iir_values); + i++) { + if (value == chip_info->iir_values[i]) break; } - if (i == ARRAY_SIZE(mlx90614_iir_values)) + if (i == ARRAY_SIZE(chip_info->iir_values)) return -EINVAL; /* @@ -151,17 +170,21 @@ static inline s32 mlx90614_iir_search(const struct i2c_client *client, * we must read them before we actually write * changes */ - ret = i2c_smbus_read_word_data(client, MLX90614_CONFIG); + ret = i2c_smbus_read_word_data(client, chip_info->op_eeprom_config1); if (ret < 0) return ret; - ret &= ~MLX90614_CONFIG_FIR_MASK; - ret |= MLX90614_CONST_FIR << MLX90614_CONFIG_FIR_SHIFT; - ret &= ~MLX90614_CONFIG_IIR_MASK; - ret |= i << MLX90614_CONFIG_IIR_SHIFT; + /* Modify FIR on parts which have configurable FIR filter */ + if (chip_info->fir_config_mask) { + ret &= ~chip_info->fir_config_mask; + ret |= field_prep(chip_info->fir_config_mask, MLX90614_CONST_FIR); + } + + ret &= ~chip_info->iir_config_mask; + ret |= field_prep(chip_info->iir_config_mask, i); /* Write changed values */ - ret = mlx90614_write_word(client, MLX90614_CONFIG, ret); + ret = mlx90614_write_word(client, chip_info->op_eeprom_config1, ret); return ret; } @@ -221,22 +244,26 @@ static int mlx90614_read_raw(struct iio_dev *indio_dev, int *val2, long mask) { struct mlx90614_data *data = iio_priv(indio_dev); - u8 cmd; + const struct mlx_chip_info *chip_info = data->chip_info; + u8 cmd, idx; s32 ret; switch (mask) { case IIO_CHAN_INFO_RAW: /* 0.02K / LSB */ switch (channel->channel2) { case IIO_MOD_TEMP_AMBIENT: - cmd = MLX90614_TA; + cmd = chip_info->op_ram_ta; break; case IIO_MOD_TEMP_OBJECT: + if (chip_info->dual_channel && channel->channel) + return -EINVAL; + switch (channel->channel) { case 0: - cmd = MLX90614_TOBJ1; + cmd = chip_info->op_ram_tobj1; break; case 1: - cmd = MLX90614_TOBJ2; + cmd = chip_info->op_ram_tobj2; break; default: return -EINVAL; @@ -268,45 +295,48 @@ static int mlx90614_read_raw(struct iio_dev *indio_dev, case IIO_CHAN_INFO_SCALE: *val = MLX90614_CONST_SCALE; return IIO_VAL_INT; - case IIO_CHAN_INFO_CALIBEMISSIVITY: /* 1/65535 / LSB */ + case IIO_CHAN_INFO_CALIBEMISSIVITY: /* 1/emissivity_max / LSB */ ret = mlx90614_power_get(data, false); if (ret < 0) return ret; mutex_lock(&data->lock); ret = i2c_smbus_read_word_data(data->client, - MLX90614_EMISSIVITY); + chip_info->op_eeprom_emissivity); mutex_unlock(&data->lock); mlx90614_power_put(data); if (ret < 0) return ret; - if (ret == MLX90614_CONST_RAW_EMISSIVITY_MAX) { + if (ret == chip_info->emissivity_max) { *val = 1; *val2 = 0; } else { *val = 0; - *val2 = ret * MLX90614_CONST_EMISSIVITY_RESOLUTION; + *val2 = ret * NSEC_PER_SEC / chip_info->emissivity_max; } return IIO_VAL_INT_PLUS_NANO; - case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: /* IIR setting with - FIR = 1024 */ + /* IIR setting with FIR=1024 (MLX90614) or FIR=65536 (MLX90615) */ + case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: ret = mlx90614_power_get(data, false); if (ret < 0) return ret; mutex_lock(&data->lock); - ret = i2c_smbus_read_word_data(data->client, MLX90614_CONFIG); + ret = i2c_smbus_read_word_data(data->client, + chip_info->op_eeprom_config1); mutex_unlock(&data->lock); mlx90614_power_put(data); if (ret < 0) return ret; - *val = mlx90614_iir_values[ret & MLX90614_CONFIG_IIR_MASK] / 100; - *val2 = (mlx90614_iir_values[ret & MLX90614_CONFIG_IIR_MASK] % 100) * - 10000; + idx = field_get(chip_info->iir_config_mask, ret) - + chip_info->iir_valid_offset; + + *val = chip_info->iir_values[idx] / 100; + *val2 = (chip_info->iir_values[idx] % 100) * 10000; return IIO_VAL_INT_PLUS_MICRO; default: return -EINVAL; @@ -318,22 +348,23 @@ static int mlx90614_write_raw(struct iio_dev *indio_dev, int val2, long mask) { struct mlx90614_data *data = iio_priv(indio_dev); + const struct mlx_chip_info *chip_info = data->chip_info; s32 ret; switch (mask) { - case IIO_CHAN_INFO_CALIBEMISSIVITY: /* 1/65535 / LSB */ + case IIO_CHAN_INFO_CALIBEMISSIVITY: /* 1/emissivity_max / LSB */ if (val < 0 || val2 < 0 || val > 1 || (val == 1 && val2 != 0)) return -EINVAL; - val = val * MLX90614_CONST_RAW_EMISSIVITY_MAX + - val2 / MLX90614_CONST_EMISSIVITY_RESOLUTION; + val = val * chip_info->emissivity_max + + val2 * chip_info->emissivity_max / NSEC_PER_SEC; ret = mlx90614_power_get(data, false); if (ret < 0) return ret; mutex_lock(&data->lock); - ret = mlx90614_write_word(data->client, MLX90614_EMISSIVITY, - val); + ret = mlx90614_write_word(data->client, + chip_info->op_eeprom_emissivity, val); mutex_unlock(&data->lock); mlx90614_power_put(data); @@ -377,11 +408,15 @@ static int mlx90614_read_avail(struct iio_dev *indio_dev, const int **vals, int *type, int *length, long mask) { + struct mlx90614_data *data = iio_priv(indio_dev); + const struct mlx_chip_info *chip_info = data->chip_info; + switch (mask) { case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: - *vals = (int *)mlx90614_freqs; + *vals = (int *)chip_info->iir_freqs; *type = IIO_VAL_INT_PLUS_MICRO; - *length = 2 * ARRAY_SIZE(mlx90614_freqs); + *length = 2 * (ARRAY_SIZE(chip_info->iir_freqs) - + chip_info->iir_valid_offset); return IIO_AVAIL_LIST; default: return -EINVAL; @@ -435,6 +470,7 @@ static const struct iio_info mlx90614_info = { #ifdef CONFIG_PM static int mlx90614_sleep(struct mlx90614_data *data) { + const struct mlx_chip_info *chip_info = data->chip_info; s32 ret; if (!data->wakeup_gpio) { @@ -447,7 +483,7 @@ static int mlx90614_sleep(struct mlx90614_data *data) mutex_lock(&data->lock); ret = i2c_smbus_xfer(data->client->adapter, data->client->addr, data->client->flags | I2C_CLIENT_PEC, - I2C_SMBUS_WRITE, MLX90614_OP_SLEEP, + I2C_SMBUS_WRITE, chip_info->op_sleep, I2C_SMBUS_BYTE, NULL); mutex_unlock(&data->lock); @@ -456,6 +492,8 @@ static int mlx90614_sleep(struct mlx90614_data *data) static int mlx90614_wakeup(struct mlx90614_data *data) { + const struct mlx_chip_info *chip_info = data->chip_info; + if (!data->wakeup_gpio) { dev_dbg(&data->client->dev, "Wake-up disabled"); return -ENOSYS; @@ -465,7 +503,7 @@ static int mlx90614_wakeup(struct mlx90614_data *data) i2c_lock_bus(data->client->adapter, I2C_LOCK_ROOT_ADAPTER); gpiod_direction_output(data->wakeup_gpio, 0); - msleep(MLX90614_TIMING_WAKEUP); + msleep(chip_info->wakeup_delay_ms); gpiod_direction_input(data->wakeup_gpio); i2c_unlock_bus(data->client->adapter, I2C_LOCK_ROOT_ADAPTER); @@ -478,7 +516,7 @@ static int mlx90614_wakeup(struct mlx90614_data *data) * If the read fails, the controller will probably be reset so that * further reads will work. */ - i2c_smbus_read_word_data(data->client, MLX90614_CONFIG); + i2c_smbus_read_word_data(data->client, chip_info->op_eeprom_config1); return 0; } @@ -527,9 +565,15 @@ static inline struct gpio_desc *mlx90614_probe_wakeup(struct i2c_client *client) /* Return 0 for single sensor, 1 for dual sensor, <0 on error. */ static int mlx90614_probe_num_ir_sensors(struct i2c_client *client) { + struct iio_dev *indio_dev = i2c_get_clientdata(client); + struct mlx90614_data *data = iio_priv(indio_dev); + const struct mlx_chip_info *chip_info = data->chip_info; s32 ret; - ret = i2c_smbus_read_word_data(client, MLX90614_CONFIG); + if (chip_info->dual_channel) + return 0; + + ret = i2c_smbus_read_word_data(client, chip_info->op_eeprom_config1); if (ret < 0) return ret; @@ -556,6 +600,7 @@ static int mlx90614_probe(struct i2c_client *client) data->client = client; mutex_init(&data->lock); data->wakeup_gpio = mlx90614_probe_wakeup(client); + data->chip_info = device_get_match_data(&client->dev); mlx90614_wakeup(data); @@ -605,14 +650,68 @@ static void mlx90614_remove(struct i2c_client *client) } } +static const struct mlx_chip_info mlx90614_chip_info = { + .op_eeprom_emissivity = MLX90614_OP_EEPROM | 0x04, + .op_eeprom_config1 = MLX90614_OP_EEPROM | 0x05, + .op_ram_ta = MLX90614_OP_RAM | 0x06, + .op_ram_tobj1 = MLX90614_OP_RAM | 0x07, + .op_ram_tobj2 = MLX90614_OP_RAM | 0x08, + .op_sleep = MLX90614_OP_SLEEP, + .dual_channel = true, + .wakeup_delay_ms = MLX90614_TIMING_WAKEUP, + .emissivity_max = 65535, + .fir_config_mask = MLX90614_CONFIG_FIR_MASK, + .iir_config_mask = MLX90614_CONFIG_IIR_MASK, + .iir_valid_offset = 0, + .iir_values = { 77, 31, 20, 15, 723, 153, 110, 86 }, + .iir_freqs = { + { 0, 150000 }, /* 13% ~= 0.15 Hz */ + { 0, 200000 }, /* 17% ~= 0.20 Hz */ + { 0, 310000 }, /* 25% ~= 0.31 Hz */ + { 0, 770000 }, /* 50% ~= 0.77 Hz */ + { 0, 860000 }, /* 57% ~= 0.86 Hz */ + { 1, 100000 }, /* 67% ~= 1.10 Hz */ + { 1, 530000 }, /* 80% ~= 1.53 Hz */ + { 7, 230000 } /* 100% ~= 7.23 Hz */ + }, +}; + +static const struct mlx_chip_info mlx90615_chip_info = { + .op_eeprom_emissivity = MLX90615_OP_EEPROM | 0x03, + .op_eeprom_config1 = MLX90615_OP_EEPROM | 0x02, + .op_ram_ta = MLX90615_OP_RAM | 0x06, + .op_ram_tobj1 = MLX90615_OP_RAM | 0x07, + .op_ram_tobj2 = MLX90615_OP_RAM | 0x08, + .op_sleep = MLX90615_OP_SLEEP, + .dual_channel = false, + .wakeup_delay_ms = MLX90615_TIMING_WAKEUP, + .emissivity_max = 16383, + .fir_config_mask = 0, /* MLX90615 FIR is fixed */ + .iir_config_mask = MLX90615_CONFIG_IIR_MASK, + /* IIR value 0 is FORBIDDEN COMBINATION on MLX90615 */ + .iir_valid_offset = 1, + .iir_values = { 500, 50, 30, 20, 15, 13, 10 }, + .iir_freqs = { + { 0, 100000 }, /* 14% ~= 0.10 Hz */ + { 0, 130000 }, /* 17% ~= 0.13 Hz */ + { 0, 150000 }, /* 20% ~= 0.15 Hz */ + { 0, 200000 }, /* 25% ~= 0.20 Hz */ + { 0, 300000 }, /* 33% ~= 0.30 Hz */ + { 0, 500000 }, /* 50% ~= 0.50 Hz */ + { 5, 000000 }, /* 100% ~= 5.00 Hz */ + }, +}; + static const struct i2c_device_id mlx90614_id[] = { - { "mlx90614", 0 }, + { "mlx90614", .driver_data = (kernel_ulong_t)&mlx90614_chip_info }, + { "mlx90615", .driver_data = (kernel_ulong_t)&mlx90615_chip_info }, { } }; MODULE_DEVICE_TABLE(i2c, mlx90614_id); static const struct of_device_id mlx90614_of_match[] = { - { .compatible = "melexis,mlx90614" }, + { .compatible = "melexis,mlx90614", .data = &mlx90614_chip_info }, + { .compatible = "melexis,mlx90615", .data = &mlx90615_chip_info }, { } }; MODULE_DEVICE_TABLE(of, mlx90614_of_match); @@ -675,7 +774,7 @@ static struct i2c_driver mlx90614_driver = { .of_match_table = mlx90614_of_match, .pm = pm_ptr(&mlx90614_pm_ops), }, - .probe_new = mlx90614_probe, + .probe = mlx90614_probe, .remove = mlx90614_remove, .id_table = mlx90614_id, }; diff --git a/drivers/iio/temperature/mlx90632.c b/drivers/iio/temperature/mlx90632.c index 753b7a4ccfddc2886f01f283fb692c3c16b582b7..8a57be108620af2733bb9f8a170b542960487163 100644 --- a/drivers/iio/temperature/mlx90632.c +++ b/drivers/iio/temperature/mlx90632.c @@ -1337,7 +1337,7 @@ static struct i2c_driver mlx90632_driver = { .of_match_table = mlx90632_of_match, .pm = pm_ptr(&mlx90632_pm_ops), }, - .probe_new = mlx90632_probe, + .probe = mlx90632_probe, .id_table = mlx90632_id, }; module_i2c_driver(mlx90632_driver); diff --git a/drivers/iio/temperature/tmp006.c b/drivers/iio/temperature/tmp006.c index cdf08477e63f7bc04649ce2f6ddad2643dba442d..3a3904fe138c116e03b435f1a73cab45af4c42b9 100644 --- a/drivers/iio/temperature/tmp006.c +++ b/drivers/iio/temperature/tmp006.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -272,6 +273,12 @@ static int tmp006_resume(struct device *dev) static DEFINE_SIMPLE_DEV_PM_OPS(tmp006_pm_ops, tmp006_suspend, tmp006_resume); +static const struct of_device_id tmp006_of_match[] = { + { .compatible = "ti,tmp006" }, + { } +}; +MODULE_DEVICE_TABLE(of, tmp006_of_match); + static const struct i2c_device_id tmp006_id[] = { { "tmp006", 0 }, { } @@ -281,9 +288,10 @@ MODULE_DEVICE_TABLE(i2c, tmp006_id); static struct i2c_driver tmp006_driver = { .driver = { .name = "tmp006", + .of_match_table = tmp006_of_match, .pm = pm_sleep_ptr(&tmp006_pm_ops), }, - .probe_new = tmp006_probe, + .probe = tmp006_probe, .id_table = tmp006_id, }; module_i2c_driver(tmp006_driver); diff --git a/drivers/iio/temperature/tmp007.c b/drivers/iio/temperature/tmp007.c index 8d27aa3bdd6dae45e4b5963d75d519531dfede0e..decef689636238d2bfa7954a5fda885236c0efdd 100644 --- a/drivers/iio/temperature/tmp007.c +++ b/drivers/iio/temperature/tmp007.c @@ -574,7 +574,7 @@ static struct i2c_driver tmp007_driver = { .of_match_table = tmp007_of_match, .pm = pm_sleep_ptr(&tmp007_pm_ops), }, - .probe_new = tmp007_probe, + .probe = tmp007_probe, .id_table = tmp007_id, }; module_i2c_driver(tmp007_driver); diff --git a/drivers/iio/temperature/tmp117.c b/drivers/iio/temperature/tmp117.c index 638e3a5bd6b84621636a96705d73213ae490ad34..fc02f491688b53622015fa71437a1b7bd3ac17ea 100644 --- a/drivers/iio/temperature/tmp117.c +++ b/drivers/iio/temperature/tmp117.c @@ -217,7 +217,7 @@ static struct i2c_driver tmp117_driver = { .name = "tmp117", .of_match_table = tmp117_of_match, }, - .probe_new = tmp117_probe, + .probe = tmp117_probe, .id_table = tmp117_id, }; module_i2c_driver(tmp117_driver); diff --git a/drivers/iio/temperature/tsys01.c b/drivers/iio/temperature/tsys01.c index 30b268ba82ccf91521582b2132886c4db68f38db..53ef56fbfe1defd1353382c1ecf73575852363c7 100644 --- a/drivers/iio/temperature/tsys01.c +++ b/drivers/iio/temperature/tsys01.c @@ -218,7 +218,7 @@ static const struct of_device_id tsys01_of_match[] = { MODULE_DEVICE_TABLE(of, tsys01_of_match); static struct i2c_driver tsys01_driver = { - .probe_new = tsys01_i2c_probe, + .probe = tsys01_i2c_probe, .id_table = tsys01_id, .driver = { .name = "tsys01", diff --git a/drivers/iio/temperature/tsys02d.c b/drivers/iio/temperature/tsys02d.c index cdefe046ab17d784f664f8ddd0119226b5e0fe39..6191db92ef9a53751e26725567bd75e7e80130b1 100644 --- a/drivers/iio/temperature/tsys02d.c +++ b/drivers/iio/temperature/tsys02d.c @@ -174,7 +174,7 @@ static const struct i2c_device_id tsys02d_id[] = { MODULE_DEVICE_TABLE(i2c, tsys02d_id); static struct i2c_driver tsys02d_driver = { - .probe_new = tsys02d_probe, + .probe = tsys02d_probe, .id_table = tsys02d_id, .driver = { .name = "tsys02d", diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index 6b3f4384e46acbfcbc0f6cee7ed8e31d048c924f..1ee87c3aaeabc9ceec26c8ef8f6b06762233d1c0 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c @@ -4805,8 +4805,7 @@ static void cma_make_mc_event(int status, struct rdma_id_private *id_priv, event->param.ud.qkey = id_priv->qkey; out: - if (ndev) - dev_put(ndev); + dev_put(ndev); } static int cma_ib_mc_handler(int status, struct ib_sa_multicast *multicast) diff --git a/drivers/infiniband/hw/bnxt_re/bnxt_re.h b/drivers/infiniband/hw/bnxt_re/bnxt_re.h index 2c95e6f3d47acc6c43aceb627907f66579c142c8..ea81b2497511a4ced31f7e65846d3bb877710855 100644 --- a/drivers/infiniband/hw/bnxt_re/bnxt_re.h +++ b/drivers/infiniband/hw/bnxt_re/bnxt_re.h @@ -39,6 +39,7 @@ #ifndef __BNXT_RE_H__ #define __BNXT_RE_H__ +#include #include "hw_counters.h" #define ROCE_DRV_MODULE_NAME "bnxt_re" @@ -179,10 +180,14 @@ struct bnxt_re_dev { #define BNXT_RE_ROCEV2_IPV4_PACKET 2 #define BNXT_RE_ROCEV2_IPV6_PACKET 3 +#define BNXT_RE_CHECK_RC(x) ((x) && ((x) != -ETIMEDOUT)) + static inline struct device *rdev_to_dev(struct bnxt_re_dev *rdev) { if (rdev) return &rdev->ibdev.dev; return NULL; } + +extern const struct uapi_definition bnxt_re_uapi_defs[]; #endif diff --git a/drivers/infiniband/hw/bnxt_re/ib_verbs.c b/drivers/infiniband/hw/bnxt_re/ib_verbs.c index 952811c40c54be64d52532f455399a1a1417d96c..abef0b8baa7c31b43b0e8f93bf4d7f48e5466a3d 100644 --- a/drivers/infiniband/hw/bnxt_re/ib_verbs.c +++ b/drivers/infiniband/hw/bnxt_re/ib_verbs.c @@ -61,6 +61,15 @@ #include "bnxt_re.h" #include "ib_verbs.h" + +#include +#include + +#include + +#define UVERBS_MODULE_NAME bnxt_re +#include + #include static int __from_ib_access_flags(int iflags) @@ -534,12 +543,57 @@ static int bnxt_re_create_fence_mr(struct bnxt_re_pd *pd) return rc; } +static struct bnxt_re_user_mmap_entry* +bnxt_re_mmap_entry_insert(struct bnxt_re_ucontext *uctx, u64 mem_offset, + enum bnxt_re_mmap_flag mmap_flag, u64 *offset) +{ + struct bnxt_re_user_mmap_entry *entry; + int ret; + + entry = kzalloc(sizeof(*entry), GFP_KERNEL); + if (!entry) + return NULL; + + entry->mem_offset = mem_offset; + entry->mmap_flag = mmap_flag; + entry->uctx = uctx; + + switch (mmap_flag) { + case BNXT_RE_MMAP_SH_PAGE: + ret = rdma_user_mmap_entry_insert_exact(&uctx->ib_uctx, + &entry->rdma_entry, PAGE_SIZE, 0); + break; + case BNXT_RE_MMAP_UC_DB: + case BNXT_RE_MMAP_WC_DB: + ret = rdma_user_mmap_entry_insert(&uctx->ib_uctx, + &entry->rdma_entry, PAGE_SIZE); + break; + default: + ret = -EINVAL; + break; + } + + if (ret) { + kfree(entry); + return NULL; + } + if (offset) + *offset = rdma_user_mmap_get_offset(&entry->rdma_entry); + + return entry; +} + /* Protection Domains */ int bnxt_re_dealloc_pd(struct ib_pd *ib_pd, struct ib_udata *udata) { struct bnxt_re_pd *pd = container_of(ib_pd, struct bnxt_re_pd, ib_pd); struct bnxt_re_dev *rdev = pd->rdev; + if (udata) { + rdma_user_mmap_entry_remove(pd->pd_db_mmap); + pd->pd_db_mmap = NULL; + } + bnxt_re_destroy_fence_mr(pd); if (pd->qplib_pd.id) { @@ -558,7 +612,8 @@ int bnxt_re_alloc_pd(struct ib_pd *ibpd, struct ib_udata *udata) struct bnxt_re_ucontext *ucntx = rdma_udata_to_drv_context( udata, struct bnxt_re_ucontext, ib_uctx); struct bnxt_re_pd *pd = container_of(ibpd, struct bnxt_re_pd, ib_pd); - int rc; + struct bnxt_re_user_mmap_entry *entry = NULL; + int rc = 0; pd->rdev = rdev; if (bnxt_qplib_alloc_pd(&rdev->qplib_res.pd_tbl, &pd->qplib_pd)) { @@ -568,15 +623,15 @@ int bnxt_re_alloc_pd(struct ib_pd *ibpd, struct ib_udata *udata) } if (udata) { - struct bnxt_re_pd_resp resp; + struct bnxt_re_pd_resp resp = {}; if (!ucntx->dpi.dbr) { /* Allocate DPI in alloc_pd to avoid failing of * ibv_devinfo and family of application when DPIs * are depleted. */ - if (bnxt_qplib_alloc_dpi(&rdev->qplib_res.dpi_tbl, - &ucntx->dpi, ucntx)) { + if (bnxt_qplib_alloc_dpi(&rdev->qplib_res, + &ucntx->dpi, ucntx, BNXT_QPLIB_DPI_TYPE_UC)) { rc = -ENOMEM; goto dbfail; } @@ -585,12 +640,21 @@ int bnxt_re_alloc_pd(struct ib_pd *ibpd, struct ib_udata *udata) resp.pdid = pd->qplib_pd.id; /* Still allow mapping this DBR to the new user PD. */ resp.dpi = ucntx->dpi.dpi; - resp.dbr = (u64)ucntx->dpi.umdbr; - rc = ib_copy_to_udata(udata, &resp, sizeof(resp)); + entry = bnxt_re_mmap_entry_insert(ucntx, (u64)ucntx->dpi.umdbr, + BNXT_RE_MMAP_UC_DB, &resp.dbr); + + if (!entry) { + rc = -ENOMEM; + goto dbfail; + } + + pd->pd_db_mmap = &entry->rdma_entry; + + rc = ib_copy_to_udata(udata, &resp, min(sizeof(resp), udata->outlen)); if (rc) { - ibdev_err(&rdev->ibdev, - "Failed to copy user response\n"); + rdma_user_mmap_entry_remove(pd->pd_db_mmap); + rc = -EFAULT; goto dbfail; } } @@ -614,12 +678,20 @@ int bnxt_re_destroy_ah(struct ib_ah *ib_ah, u32 flags) { struct bnxt_re_ah *ah = container_of(ib_ah, struct bnxt_re_ah, ib_ah); struct bnxt_re_dev *rdev = ah->rdev; + bool block = true; + int rc = 0; - bnxt_qplib_destroy_ah(&rdev->qplib_res, &ah->qplib_ah, - !(flags & RDMA_DESTROY_AH_SLEEPABLE)); + block = !(flags & RDMA_DESTROY_AH_SLEEPABLE); + rc = bnxt_qplib_destroy_ah(&rdev->qplib_res, &ah->qplib_ah, block); + if (BNXT_RE_CHECK_RC(rc)) { + if (rc == -ETIMEDOUT) + rc = 0; + else + goto fail; + } atomic_dec(&rdev->ah_count); - - return 0; +fail: + return rc; } static u8 bnxt_re_stack_to_dev_nw_type(enum rdma_network_type ntype) @@ -3955,6 +4027,7 @@ int bnxt_re_alloc_ucontext(struct ib_ucontext *ctx, struct ib_udata *udata) container_of(ctx, struct bnxt_re_ucontext, ib_uctx); struct bnxt_re_dev *rdev = to_bnxt_re_dev(ibdev, ibdev); struct bnxt_qplib_dev_attr *dev_attr = &rdev->dev_attr; + struct bnxt_re_user_mmap_entry *entry; struct bnxt_re_uctx_resp resp = {}; u32 chip_met_rev_num = 0; int rc; @@ -3993,6 +4066,16 @@ int bnxt_re_alloc_ucontext(struct ib_ucontext *ctx, struct ib_udata *udata) resp.comp_mask |= BNXT_RE_UCNTX_CMASK_HAVE_MODE; resp.mode = rdev->chip_ctx->modes.wqe_mode; + if (rdev->chip_ctx->modes.db_push) + resp.comp_mask |= BNXT_RE_UCNTX_CMASK_WC_DPI_ENABLED; + + entry = bnxt_re_mmap_entry_insert(uctx, 0, BNXT_RE_MMAP_SH_PAGE, NULL); + if (!entry) { + rc = -ENOMEM; + goto cfail; + } + uctx->shpage_mmap = &entry->rdma_entry; + rc = ib_copy_to_udata(udata, &resp, min(udata->outlen, sizeof(resp))); if (rc) { ibdev_err(ibdev, "Failed to copy user context"); @@ -4016,6 +4099,8 @@ void bnxt_re_dealloc_ucontext(struct ib_ucontext *ib_uctx) struct bnxt_re_dev *rdev = uctx->rdev; + rdma_user_mmap_entry_remove(uctx->shpage_mmap); + uctx->shpage_mmap = NULL; if (uctx->shpg) free_page((unsigned long)uctx->shpg); @@ -4023,8 +4108,7 @@ void bnxt_re_dealloc_ucontext(struct ib_ucontext *ib_uctx) /* Free DPI only if this is the first PD allocated by the * application and mark the context dpi as NULL */ - bnxt_qplib_dealloc_dpi(&rdev->qplib_res, - &rdev->qplib_res.dpi_tbl, &uctx->dpi); + bnxt_qplib_dealloc_dpi(&rdev->qplib_res, &uctx->dpi); uctx->dpi.dbr = NULL; } } @@ -4035,27 +4119,177 @@ int bnxt_re_mmap(struct ib_ucontext *ib_uctx, struct vm_area_struct *vma) struct bnxt_re_ucontext *uctx = container_of(ib_uctx, struct bnxt_re_ucontext, ib_uctx); - struct bnxt_re_dev *rdev = uctx->rdev; + struct bnxt_re_user_mmap_entry *bnxt_entry; + struct rdma_user_mmap_entry *rdma_entry; + int ret = 0; u64 pfn; - if (vma->vm_end - vma->vm_start != PAGE_SIZE) + rdma_entry = rdma_user_mmap_entry_get(&uctx->ib_uctx, vma); + if (!rdma_entry) return -EINVAL; - if (vma->vm_pgoff) { - vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); - if (io_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, - PAGE_SIZE, vma->vm_page_prot)) { - ibdev_err(&rdev->ibdev, "Failed to map DPI"); - return -EAGAIN; - } - } else { - pfn = virt_to_phys(uctx->shpg) >> PAGE_SHIFT; - if (remap_pfn_range(vma, vma->vm_start, - pfn, PAGE_SIZE, vma->vm_page_prot)) { - ibdev_err(&rdev->ibdev, "Failed to map shared page"); - return -EAGAIN; + bnxt_entry = container_of(rdma_entry, struct bnxt_re_user_mmap_entry, + rdma_entry); + + switch (bnxt_entry->mmap_flag) { + case BNXT_RE_MMAP_WC_DB: + pfn = bnxt_entry->mem_offset >> PAGE_SHIFT; + ret = rdma_user_mmap_io(ib_uctx, vma, pfn, PAGE_SIZE, + pgprot_writecombine(vma->vm_page_prot), + rdma_entry); + break; + case BNXT_RE_MMAP_UC_DB: + pfn = bnxt_entry->mem_offset >> PAGE_SHIFT; + ret = rdma_user_mmap_io(ib_uctx, vma, pfn, PAGE_SIZE, + pgprot_noncached(vma->vm_page_prot), + rdma_entry); + break; + case BNXT_RE_MMAP_SH_PAGE: + ret = vm_insert_page(vma, vma->vm_start, virt_to_page(uctx->shpg)); + break; + default: + ret = -EINVAL; + break; + } + + rdma_user_mmap_entry_put(rdma_entry); + return ret; +} + +void bnxt_re_mmap_free(struct rdma_user_mmap_entry *rdma_entry) +{ + struct bnxt_re_user_mmap_entry *bnxt_entry; + + bnxt_entry = container_of(rdma_entry, struct bnxt_re_user_mmap_entry, + rdma_entry); + + kfree(bnxt_entry); +} + +static int UVERBS_HANDLER(BNXT_RE_METHOD_ALLOC_PAGE)(struct uverbs_attr_bundle *attrs) +{ + struct ib_uobject *uobj = uverbs_attr_get_uobject(attrs, BNXT_RE_ALLOC_PAGE_HANDLE); + enum bnxt_re_alloc_page_type alloc_type; + struct bnxt_re_user_mmap_entry *entry; + enum bnxt_re_mmap_flag mmap_flag; + struct bnxt_qplib_chip_ctx *cctx; + struct bnxt_re_ucontext *uctx; + struct bnxt_re_dev *rdev; + u64 mmap_offset; + u32 length; + u32 dpi; + u64 dbr; + int err; + + uctx = container_of(ib_uverbs_get_ucontext(attrs), struct bnxt_re_ucontext, ib_uctx); + if (IS_ERR(uctx)) + return PTR_ERR(uctx); + + err = uverbs_get_const(&alloc_type, attrs, BNXT_RE_ALLOC_PAGE_TYPE); + if (err) + return err; + + rdev = uctx->rdev; + cctx = rdev->chip_ctx; + + switch (alloc_type) { + case BNXT_RE_ALLOC_WC_PAGE: + if (cctx->modes.db_push) { + if (bnxt_qplib_alloc_dpi(&rdev->qplib_res, &uctx->wcdpi, + uctx, BNXT_QPLIB_DPI_TYPE_WC)) + return -ENOMEM; + length = PAGE_SIZE; + dpi = uctx->wcdpi.dpi; + dbr = (u64)uctx->wcdpi.umdbr; + mmap_flag = BNXT_RE_MMAP_WC_DB; + } else { + return -EINVAL; } + + break; + + default: + return -EOPNOTSUPP; } + entry = bnxt_re_mmap_entry_insert(uctx, dbr, mmap_flag, &mmap_offset); + if (!entry) + return -ENOMEM; + + uobj->object = entry; + uverbs_finalize_uobj_create(attrs, BNXT_RE_ALLOC_PAGE_HANDLE); + err = uverbs_copy_to(attrs, BNXT_RE_ALLOC_PAGE_MMAP_OFFSET, + &mmap_offset, sizeof(mmap_offset)); + if (err) + return err; + + err = uverbs_copy_to(attrs, BNXT_RE_ALLOC_PAGE_MMAP_LENGTH, + &length, sizeof(length)); + if (err) + return err; + + err = uverbs_copy_to(attrs, BNXT_RE_ALLOC_PAGE_DPI, + &dpi, sizeof(length)); + if (err) + return err; + return 0; } + +static int alloc_page_obj_cleanup(struct ib_uobject *uobject, + enum rdma_remove_reason why, + struct uverbs_attr_bundle *attrs) +{ + struct bnxt_re_user_mmap_entry *entry = uobject->object; + struct bnxt_re_ucontext *uctx = entry->uctx; + + switch (entry->mmap_flag) { + case BNXT_RE_MMAP_WC_DB: + if (uctx && uctx->wcdpi.dbr) { + struct bnxt_re_dev *rdev = uctx->rdev; + + bnxt_qplib_dealloc_dpi(&rdev->qplib_res, &uctx->wcdpi); + uctx->wcdpi.dbr = NULL; + } + break; + default: + goto exit; + } + rdma_user_mmap_entry_remove(&entry->rdma_entry); +exit: + return 0; +} + +DECLARE_UVERBS_NAMED_METHOD(BNXT_RE_METHOD_ALLOC_PAGE, + UVERBS_ATTR_IDR(BNXT_RE_ALLOC_PAGE_HANDLE, + BNXT_RE_OBJECT_ALLOC_PAGE, + UVERBS_ACCESS_NEW, + UA_MANDATORY), + UVERBS_ATTR_CONST_IN(BNXT_RE_ALLOC_PAGE_TYPE, + enum bnxt_re_alloc_page_type, + UA_MANDATORY), + UVERBS_ATTR_PTR_OUT(BNXT_RE_ALLOC_PAGE_MMAP_OFFSET, + UVERBS_ATTR_TYPE(u64), + UA_MANDATORY), + UVERBS_ATTR_PTR_OUT(BNXT_RE_ALLOC_PAGE_MMAP_LENGTH, + UVERBS_ATTR_TYPE(u32), + UA_MANDATORY), + UVERBS_ATTR_PTR_OUT(BNXT_RE_ALLOC_PAGE_DPI, + UVERBS_ATTR_TYPE(u32), + UA_MANDATORY)); + +DECLARE_UVERBS_NAMED_METHOD_DESTROY(BNXT_RE_METHOD_DESTROY_PAGE, + UVERBS_ATTR_IDR(BNXT_RE_DESTROY_PAGE_HANDLE, + BNXT_RE_OBJECT_ALLOC_PAGE, + UVERBS_ACCESS_DESTROY, + UA_MANDATORY)); + +DECLARE_UVERBS_NAMED_OBJECT(BNXT_RE_OBJECT_ALLOC_PAGE, + UVERBS_TYPE_ALLOC_IDR(alloc_page_obj_cleanup), + &UVERBS_METHOD(BNXT_RE_METHOD_ALLOC_PAGE), + &UVERBS_METHOD(BNXT_RE_METHOD_DESTROY_PAGE)); + +const struct uapi_definition bnxt_re_uapi_defs[] = { + UAPI_DEF_CHAIN_OBJ_TREE_NAMED(BNXT_RE_OBJECT_ALLOC_PAGE), + {} +}; diff --git a/drivers/infiniband/hw/bnxt_re/ib_verbs.h b/drivers/infiniband/hw/bnxt_re/ib_verbs.h index 31f7e34040f79d25705aa458f64c85554a9b98b5..32d9e9d09791ef48d56e5643747d9e733d2f57d5 100644 --- a/drivers/infiniband/hw/bnxt_re/ib_verbs.h +++ b/drivers/infiniband/hw/bnxt_re/ib_verbs.h @@ -60,6 +60,8 @@ struct bnxt_re_pd { struct bnxt_re_dev *rdev; struct bnxt_qplib_pd qplib_pd; struct bnxt_re_fence_data fence; + struct rdma_user_mmap_entry *pd_db_mmap; + struct rdma_user_mmap_entry *pd_wcdb_mmap; }; struct bnxt_re_ah { @@ -134,8 +136,23 @@ struct bnxt_re_ucontext { struct ib_ucontext ib_uctx; struct bnxt_re_dev *rdev; struct bnxt_qplib_dpi dpi; + struct bnxt_qplib_dpi wcdpi; void *shpg; spinlock_t sh_lock; /* protect shpg */ + struct rdma_user_mmap_entry *shpage_mmap; +}; + +enum bnxt_re_mmap_flag { + BNXT_RE_MMAP_SH_PAGE, + BNXT_RE_MMAP_UC_DB, + BNXT_RE_MMAP_WC_DB, +}; + +struct bnxt_re_user_mmap_entry { + struct rdma_user_mmap_entry rdma_entry; + struct bnxt_re_ucontext *uctx; + u64 mem_offset; + u8 mmap_flag; }; static inline u16 bnxt_re_get_swqe_size(int nsge) @@ -213,6 +230,8 @@ struct ib_mr *bnxt_re_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, int bnxt_re_alloc_ucontext(struct ib_ucontext *ctx, struct ib_udata *udata); void bnxt_re_dealloc_ucontext(struct ib_ucontext *context); int bnxt_re_mmap(struct ib_ucontext *context, struct vm_area_struct *vma); +void bnxt_re_mmap_free(struct rdma_user_mmap_entry *rdma_entry); + unsigned long bnxt_re_lock_cqs(struct bnxt_re_qp *qp); void bnxt_re_unlock_cqs(struct bnxt_re_qp *qp, unsigned long flags); diff --git a/drivers/infiniband/hw/bnxt_re/main.c b/drivers/infiniband/hw/bnxt_re/main.c index 3073398a218341e67f5742f00247461276bc4bdf..b42166fe7454045c87a442d62695129ec7e83b7a 100644 --- a/drivers/infiniband/hw/bnxt_re/main.c +++ b/drivers/infiniband/hw/bnxt_re/main.c @@ -83,6 +83,45 @@ static int bnxt_re_netdev_event(struct notifier_block *notifier, unsigned long event, void *ptr); static struct bnxt_re_dev *bnxt_re_from_netdev(struct net_device *netdev); static void bnxt_re_dev_uninit(struct bnxt_re_dev *rdev); +static int bnxt_re_hwrm_qcaps(struct bnxt_re_dev *rdev); + +static int bnxt_re_hwrm_qcfg(struct bnxt_re_dev *rdev, u32 *db_len, + u32 *offset); +static void bnxt_re_set_db_offset(struct bnxt_re_dev *rdev) +{ + struct bnxt_qplib_chip_ctx *cctx; + struct bnxt_en_dev *en_dev; + struct bnxt_qplib_res *res; + u32 l2db_len = 0; + u32 offset = 0; + u32 barlen; + int rc; + + res = &rdev->qplib_res; + en_dev = rdev->en_dev; + cctx = rdev->chip_ctx; + + /* Issue qcfg */ + rc = bnxt_re_hwrm_qcfg(rdev, &l2db_len, &offset); + if (rc) + dev_info(rdev_to_dev(rdev), + "Couldn't get DB bar size, Low latency framework is disabled\n"); + /* set register offsets for both UC and WC */ + res->dpi_tbl.ucreg.offset = res->is_vf ? BNXT_QPLIB_DBR_VF_DB_OFFSET : + BNXT_QPLIB_DBR_PF_DB_OFFSET; + res->dpi_tbl.wcreg.offset = res->dpi_tbl.ucreg.offset; + + /* If WC mapping is disabled by L2 driver then en_dev->l2_db_size + * is equal to the DB-Bar actual size. This indicates that L2 + * is mapping entire bar as UC-. RoCE driver can't enable WC mapping + * in such cases and DB-push will be disabled. + */ + barlen = pci_resource_len(res->pdev, RCFW_DBR_PCI_BAR_REGION); + if (cctx->modes.db_push && l2db_len && en_dev->l2_db_size != barlen) { + res->dpi_tbl.wcreg.offset = en_dev->l2_db_size; + dev_info(rdev_to_dev(rdev), "Low latency framework is enabled\n"); + } +} static void bnxt_re_set_drv_mode(struct bnxt_re_dev *rdev, u8 mode) { @@ -91,6 +130,9 @@ static void bnxt_re_set_drv_mode(struct bnxt_re_dev *rdev, u8 mode) cctx = rdev->chip_ctx; cctx->modes.wqe_mode = bnxt_qplib_is_chip_gen_p5(rdev->chip_ctx) ? mode : BNXT_QPLIB_WQE_MODE_STATIC; + if (bnxt_re_hwrm_qcaps(rdev)) + dev_err(rdev_to_dev(rdev), + "Failed to query hwrm qcaps\n"); } static void bnxt_re_destroy_chip_ctx(struct bnxt_re_dev *rdev) @@ -112,6 +154,7 @@ static int bnxt_re_setup_chip_ctx(struct bnxt_re_dev *rdev, u8 wqe_mode) { struct bnxt_qplib_chip_ctx *chip_ctx; struct bnxt_en_dev *en_dev; + int rc; en_dev = rdev->en_dev; @@ -130,6 +173,12 @@ static int bnxt_re_setup_chip_ctx(struct bnxt_re_dev *rdev, u8 wqe_mode) rdev->qplib_res.is_vf = BNXT_EN_VF(en_dev); bnxt_re_set_drv_mode(rdev, wqe_mode); + + bnxt_re_set_db_offset(rdev); + rc = bnxt_qplib_map_db_bar(&rdev->qplib_res); + if (rc) + return rc; + if (bnxt_qplib_determine_atomics(en_dev->pdev)) ibdev_info(&rdev->ibdev, "platform doesn't support global atomics."); @@ -283,15 +332,21 @@ static void bnxt_re_start_irq(void *handle, struct bnxt_msix_entry *ent) for (indx = 0; indx < rdev->num_msix; indx++) rdev->en_dev->msix_entries[indx].vector = ent[indx].vector; - bnxt_qplib_rcfw_start_irq(rcfw, msix_ent[BNXT_RE_AEQ_IDX].vector, - false); + rc = bnxt_qplib_rcfw_start_irq(rcfw, msix_ent[BNXT_RE_AEQ_IDX].vector, + false); + if (rc) { + ibdev_warn(&rdev->ibdev, "Failed to reinit CREQ\n"); + return; + } for (indx = BNXT_RE_NQ_IDX ; indx < rdev->num_msix; indx++) { nq = &rdev->nq[indx - 1]; rc = bnxt_qplib_nq_start_irq(nq, indx - 1, msix_ent[indx].vector, false); - if (rc) + if (rc) { ibdev_warn(&rdev->ibdev, "Failed to reinit NQ index %d\n", indx - 1); + return; + } } } @@ -315,12 +370,11 @@ static int bnxt_re_register_netdev(struct bnxt_re_dev *rdev) return rc; } -static void bnxt_re_init_hwrm_hdr(struct bnxt_re_dev *rdev, struct input *hdr, - u16 opcd, u16 crid, u16 trid) +static void bnxt_re_init_hwrm_hdr(struct input *hdr, u16 opcd) { hdr->req_type = cpu_to_le16(opcd); - hdr->cmpl_ring = cpu_to_le16(crid); - hdr->target_id = cpu_to_le16(trid); + hdr->cmpl_ring = cpu_to_le16(-1); + hdr->target_id = cpu_to_le16(-1); } static void bnxt_re_fill_fw_msg(struct bnxt_fw_msg *fw_msg, void *msg, @@ -334,13 +388,60 @@ static void bnxt_re_fill_fw_msg(struct bnxt_fw_msg *fw_msg, void *msg, fw_msg->timeout = timeout; } +/* Query device config using common hwrm */ +static int bnxt_re_hwrm_qcfg(struct bnxt_re_dev *rdev, u32 *db_len, + u32 *offset) +{ + struct bnxt_en_dev *en_dev = rdev->en_dev; + struct hwrm_func_qcfg_output resp = {0}; + struct hwrm_func_qcfg_input req = {0}; + struct bnxt_fw_msg fw_msg; + int rc; + + memset(&fw_msg, 0, sizeof(fw_msg)); + bnxt_re_init_hwrm_hdr((void *)&req, HWRM_FUNC_QCFG); + req.fid = cpu_to_le16(0xffff); + bnxt_re_fill_fw_msg(&fw_msg, (void *)&req, sizeof(req), (void *)&resp, + sizeof(resp), DFLT_HWRM_CMD_TIMEOUT); + rc = bnxt_send_msg(en_dev, &fw_msg); + if (!rc) { + *db_len = PAGE_ALIGN(le16_to_cpu(resp.l2_doorbell_bar_size_kb) * 1024); + *offset = PAGE_ALIGN(le16_to_cpu(resp.legacy_l2_db_size_kb) * 1024); + } + return rc; +} + +/* Query function capabilities using common hwrm */ +int bnxt_re_hwrm_qcaps(struct bnxt_re_dev *rdev) +{ + struct bnxt_en_dev *en_dev = rdev->en_dev; + struct hwrm_func_qcaps_output resp = {}; + struct hwrm_func_qcaps_input req = {}; + struct bnxt_qplib_chip_ctx *cctx; + struct bnxt_fw_msg fw_msg = {}; + int rc; + + cctx = rdev->chip_ctx; + bnxt_re_init_hwrm_hdr((void *)&req, HWRM_FUNC_QCAPS); + req.fid = cpu_to_le16(0xffff); + bnxt_re_fill_fw_msg(&fw_msg, (void *)&req, sizeof(req), (void *)&resp, + sizeof(resp), DFLT_HWRM_CMD_TIMEOUT); + + rc = bnxt_send_msg(en_dev, &fw_msg); + if (rc) + return rc; + cctx->modes.db_push = le32_to_cpu(resp.flags) & FUNC_QCAPS_RESP_FLAGS_WCB_PUSH_MODE; + + return 0; +} + static int bnxt_re_net_ring_free(struct bnxt_re_dev *rdev, u16 fw_ring_id, int type) { struct bnxt_en_dev *en_dev; - struct hwrm_ring_free_input req = {0}; + struct hwrm_ring_free_input req = {}; struct hwrm_ring_free_output resp; - struct bnxt_fw_msg fw_msg; + struct bnxt_fw_msg fw_msg = {}; int rc = -EINVAL; if (!rdev) @@ -354,9 +455,7 @@ static int bnxt_re_net_ring_free(struct bnxt_re_dev *rdev, if (test_bit(BNXT_RE_FLAG_ERR_DEVICE_DETACHED, &rdev->flags)) return 0; - memset(&fw_msg, 0, sizeof(fw_msg)); - - bnxt_re_init_hwrm_hdr(rdev, (void *)&req, HWRM_RING_FREE, -1, -1); + bnxt_re_init_hwrm_hdr((void *)&req, HWRM_RING_FREE); req.ring_type = type; req.ring_id = cpu_to_le16(fw_ring_id); bnxt_re_fill_fw_msg(&fw_msg, (void *)&req, sizeof(req), (void *)&resp, @@ -373,16 +472,15 @@ static int bnxt_re_net_ring_alloc(struct bnxt_re_dev *rdev, u16 *fw_ring_id) { struct bnxt_en_dev *en_dev = rdev->en_dev; - struct hwrm_ring_alloc_input req = {0}; + struct hwrm_ring_alloc_input req = {}; struct hwrm_ring_alloc_output resp; - struct bnxt_fw_msg fw_msg; + struct bnxt_fw_msg fw_msg = {}; int rc = -EINVAL; if (!en_dev) return rc; - memset(&fw_msg, 0, sizeof(fw_msg)); - bnxt_re_init_hwrm_hdr(rdev, (void *)&req, HWRM_RING_ALLOC, -1, -1); + bnxt_re_init_hwrm_hdr((void *)&req, HWRM_RING_ALLOC); req.enables = 0; req.page_tbl_addr = cpu_to_le64(ring_attr->dma_arr[0]); if (ring_attr->pages > 1) { @@ -411,7 +509,7 @@ static int bnxt_re_net_stats_ctx_free(struct bnxt_re_dev *rdev, struct bnxt_en_dev *en_dev = rdev->en_dev; struct hwrm_stat_ctx_free_input req = {}; struct hwrm_stat_ctx_free_output resp = {}; - struct bnxt_fw_msg fw_msg; + struct bnxt_fw_msg fw_msg = {}; int rc = -EINVAL; if (!en_dev) @@ -420,9 +518,7 @@ static int bnxt_re_net_stats_ctx_free(struct bnxt_re_dev *rdev, if (test_bit(BNXT_RE_FLAG_ERR_DEVICE_DETACHED, &rdev->flags)) return 0; - memset(&fw_msg, 0, sizeof(fw_msg)); - - bnxt_re_init_hwrm_hdr(rdev, (void *)&req, HWRM_STAT_CTX_FREE, -1, -1); + bnxt_re_init_hwrm_hdr((void *)&req, HWRM_STAT_CTX_FREE); req.stat_ctx_id = cpu_to_le32(fw_stats_ctx_id); bnxt_re_fill_fw_msg(&fw_msg, (void *)&req, sizeof(req), (void *)&resp, sizeof(resp), DFLT_HWRM_CMD_TIMEOUT); @@ -439,10 +535,10 @@ static int bnxt_re_net_stats_ctx_alloc(struct bnxt_re_dev *rdev, u32 *fw_stats_ctx_id) { struct bnxt_qplib_chip_ctx *chip_ctx = rdev->chip_ctx; - struct hwrm_stat_ctx_alloc_output resp = {0}; - struct hwrm_stat_ctx_alloc_input req = {0}; + struct hwrm_stat_ctx_alloc_output resp = {}; + struct hwrm_stat_ctx_alloc_input req = {}; struct bnxt_en_dev *en_dev = rdev->en_dev; - struct bnxt_fw_msg fw_msg; + struct bnxt_fw_msg fw_msg = {}; int rc = -EINVAL; *fw_stats_ctx_id = INVALID_STATS_CTX_ID; @@ -450,9 +546,7 @@ static int bnxt_re_net_stats_ctx_alloc(struct bnxt_re_dev *rdev, if (!en_dev) return rc; - memset(&fw_msg, 0, sizeof(fw_msg)); - - bnxt_re_init_hwrm_hdr(rdev, (void *)&req, HWRM_STAT_CTX_ALLOC, -1, -1); + bnxt_re_init_hwrm_hdr((void *)&req, HWRM_STAT_CTX_ALLOC); req.update_period_ms = cpu_to_le32(1000); req.stats_dma_addr = cpu_to_le64(dma_map); req.stats_dma_length = cpu_to_le16(chip_ctx->hw_stats_size); @@ -466,6 +560,10 @@ static int bnxt_re_net_stats_ctx_alloc(struct bnxt_re_dev *rdev, return rc; } +static void bnxt_re_disassociate_ucontext(struct ib_ucontext *ibcontext) +{ +} + /* Device */ static struct bnxt_re_dev *bnxt_re_from_netdev(struct net_device *netdev) @@ -532,6 +630,7 @@ static const struct ib_device_ops bnxt_re_dev_ops = { .destroy_qp = bnxt_re_destroy_qp, .destroy_srq = bnxt_re_destroy_srq, .device_group = &bnxt_re_dev_attr_group, + .disassociate_ucontext = bnxt_re_disassociate_ucontext, .get_dev_fw_str = bnxt_re_query_fw_str, .get_dma_mr = bnxt_re_get_dma_mr, .get_hw_stats = bnxt_re_ib_get_hw_stats, @@ -539,6 +638,7 @@ static const struct ib_device_ops bnxt_re_dev_ops = { .get_port_immutable = bnxt_re_get_port_immutable, .map_mr_sg = bnxt_re_map_mr_sg, .mmap = bnxt_re_mmap, + .mmap_free = bnxt_re_mmap_free, .modify_qp = bnxt_re_modify_qp, .modify_srq = bnxt_re_modify_srq, .poll_cq = bnxt_re_poll_cq, @@ -579,6 +679,9 @@ static int bnxt_re_register_ib(struct bnxt_re_dev *rdev) ibdev->dev.parent = &rdev->en_dev->pdev->dev; ibdev->local_dma_lkey = BNXT_QPLIB_RSVD_LKEY; + if (IS_ENABLED(CONFIG_INFINIBAND_USER_ACCESS)) + ibdev->driver_def = bnxt_re_uapi_defs; + ib_set_device_ops(ibdev, &bnxt_re_dev_ops); ret = ib_device_set_netdev(&rdev->ibdev, rdev->netdev, 1); if (ret) @@ -822,7 +925,6 @@ static void bnxt_re_free_res(struct bnxt_re_dev *rdev) if (rdev->qplib_res.dpi_tbl.max) { bnxt_qplib_dealloc_dpi(&rdev->qplib_res, - &rdev->qplib_res.dpi_tbl, &rdev->dpi_privileged); } if (rdev->qplib_res.rcfw) { @@ -850,9 +952,9 @@ static int bnxt_re_alloc_res(struct bnxt_re_dev *rdev) if (rc) goto fail; - rc = bnxt_qplib_alloc_dpi(&rdev->qplib_res.dpi_tbl, + rc = bnxt_qplib_alloc_dpi(&rdev->qplib_res, &rdev->dpi_privileged, - rdev); + rdev, BNXT_QPLIB_DPI_TYPE_KERNEL); if (rc) goto dealloc_res; @@ -892,7 +994,6 @@ static int bnxt_re_alloc_res(struct bnxt_re_dev *rdev) bnxt_qplib_free_nq(&rdev->nq[i]); } bnxt_qplib_dealloc_dpi(&rdev->qplib_res, - &rdev->qplib_res.dpi_tbl, &rdev->dpi_privileged); dealloc_res: bnxt_qplib_free_res(&rdev->qplib_res); @@ -963,12 +1064,6 @@ static int bnxt_re_update_gid(struct bnxt_re_dev *rdev) if (!ib_device_try_get(&rdev->ibdev)) return 0; - if (!sgid_tbl) { - ibdev_err(&rdev->ibdev, "QPLIB: SGID table not allocated"); - rc = -EINVAL; - goto out; - } - for (index = 0; index < sgid_tbl->active; index++) { gid_idx = sgid_tbl->hw_id[index]; @@ -986,7 +1081,7 @@ static int bnxt_re_update_gid(struct bnxt_re_dev *rdev) rc = bnxt_qplib_update_sgid(sgid_tbl, &gid, gid_idx, rdev->qplib_res.netdev->dev_addr); } -out: + ib_device_put(&rdev->ibdev); return rc; } @@ -1039,14 +1134,13 @@ static int bnxt_re_setup_qos(struct bnxt_re_dev *rdev) static void bnxt_re_query_hwrm_intf_version(struct bnxt_re_dev *rdev) { struct bnxt_en_dev *en_dev = rdev->en_dev; - struct hwrm_ver_get_output resp = {0}; - struct hwrm_ver_get_input req = {0}; - struct bnxt_fw_msg fw_msg; + struct hwrm_ver_get_output resp = {}; + struct hwrm_ver_get_input req = {}; + struct bnxt_qplib_chip_ctx *cctx; + struct bnxt_fw_msg fw_msg = {}; int rc = 0; - memset(&fw_msg, 0, sizeof(fw_msg)); - bnxt_re_init_hwrm_hdr(rdev, (void *)&req, - HWRM_VER_GET, -1, -1); + bnxt_re_init_hwrm_hdr((void *)&req, HWRM_VER_GET); req.hwrm_intf_maj = HWRM_VERSION_MAJOR; req.hwrm_intf_min = HWRM_VERSION_MINOR; req.hwrm_intf_upd = HWRM_VERSION_UPDATE; @@ -1058,11 +1152,18 @@ static void bnxt_re_query_hwrm_intf_version(struct bnxt_re_dev *rdev) rc); return; } - rdev->qplib_ctx.hwrm_intf_ver = + + cctx = rdev->chip_ctx; + cctx->hwrm_intf_ver = (u64)le16_to_cpu(resp.hwrm_intf_major) << 48 | (u64)le16_to_cpu(resp.hwrm_intf_minor) << 32 | (u64)le16_to_cpu(resp.hwrm_intf_build) << 16 | le16_to_cpu(resp.hwrm_intf_patch); + + cctx->hwrm_cmd_max_timeout = le16_to_cpu(resp.max_req_timeout); + + if (!cctx->hwrm_cmd_max_timeout) + cctx->hwrm_cmd_max_timeout = RCFW_FW_STALL_MAX_TIMEOUT; } static int bnxt_re_ib_init(struct bnxt_re_dev *rdev) @@ -1200,7 +1301,7 @@ static int bnxt_re_dev_init(struct bnxt_re_dev *rdev, u8 wqe_mode) db_offt = bnxt_re_get_nqdb_offset(rdev, BNXT_RE_AEQ_IDX); vid = rdev->en_dev->msix_entries[BNXT_RE_AEQ_IDX].vector; rc = bnxt_qplib_enable_rcfw_channel(&rdev->rcfw, - vid, db_offt, rdev->is_virtfn, + vid, db_offt, &bnxt_re_aeq_handler); if (rc) { ibdev_err(&rdev->ibdev, "Failed to enable RCFW channel: %#x\n", @@ -1497,6 +1598,7 @@ static int bnxt_re_suspend(struct auxiliary_device *adev, pm_message_t state) */ set_bit(BNXT_RE_FLAG_ERR_DEVICE_DETACHED, &rdev->flags); set_bit(ERR_DEVICE_DETACHED, &rdev->rcfw.cmdq.flags); + wake_up_all(&rdev->rcfw.cmdq.waitq); mutex_unlock(&bnxt_re_mutex); return 0; diff --git a/drivers/infiniband/hw/bnxt_re/qplib_fp.c b/drivers/infiniband/hw/bnxt_re/qplib_fp.c index 8974f6235cfaa83a9e658faf08e2085a23738f4e..91aed77ce40d5f91f4622588ba691c100bc520bc 100644 --- a/drivers/infiniband/hw/bnxt_re/qplib_fp.c +++ b/drivers/infiniband/hw/bnxt_re/qplib_fp.c @@ -399,6 +399,9 @@ static irqreturn_t bnxt_qplib_nq_irq(int irq, void *dev_instance) void bnxt_qplib_nq_stop_irq(struct bnxt_qplib_nq *nq, bool kill) { + if (!nq->requested) + return; + tasklet_disable(&nq->nq_tasklet); /* Mask h/w interrupt */ bnxt_qplib_ring_nq_db(&nq->nq_db.dbinfo, nq->res->cctx, false); @@ -406,11 +409,12 @@ void bnxt_qplib_nq_stop_irq(struct bnxt_qplib_nq *nq, bool kill) synchronize_irq(nq->msix_vec); if (kill) tasklet_kill(&nq->nq_tasklet); - if (nq->requested) { - irq_set_affinity_hint(nq->msix_vec, NULL); - free_irq(nq->msix_vec, nq); - nq->requested = false; - } + + irq_set_affinity_hint(nq->msix_vec, NULL); + free_irq(nq->msix_vec, nq); + kfree(nq->name); + nq->name = NULL; + nq->requested = false; } void bnxt_qplib_disable_nq(struct bnxt_qplib_nq *nq) @@ -436,6 +440,7 @@ void bnxt_qplib_disable_nq(struct bnxt_qplib_nq *nq) int bnxt_qplib_nq_start_irq(struct bnxt_qplib_nq *nq, int nq_indx, int msix_vector, bool need_init) { + struct bnxt_qplib_res *res = nq->res; int rc; if (nq->requested) @@ -447,10 +452,17 @@ int bnxt_qplib_nq_start_irq(struct bnxt_qplib_nq *nq, int nq_indx, else tasklet_enable(&nq->nq_tasklet); - snprintf(nq->name, sizeof(nq->name), "bnxt_qplib_nq-%d", nq_indx); + nq->name = kasprintf(GFP_KERNEL, "bnxt_re-nq-%d@pci:%s", + nq_indx, pci_name(res->pdev)); + if (!nq->name) + return -ENOMEM; rc = request_irq(nq->msix_vec, bnxt_qplib_nq_irq, 0, nq->name, nq); - if (rc) + if (rc) { + kfree(nq->name); + nq->name = NULL; + tasklet_disable(&nq->nq_tasklet); return rc; + } cpumask_clear(&nq->mask); cpumask_set_cpu(nq_indx, &nq->mask); @@ -461,7 +473,7 @@ int bnxt_qplib_nq_start_irq(struct bnxt_qplib_nq *nq, int nq_indx, nq->msix_vec, nq_indx); } nq->requested = true; - bnxt_qplib_ring_nq_db(&nq->nq_db.dbinfo, nq->res->cctx, true); + bnxt_qplib_ring_nq_db(&nq->nq_db.dbinfo, res->cctx, true); return rc; } @@ -471,7 +483,6 @@ static int bnxt_qplib_map_nq_db(struct bnxt_qplib_nq *nq, u32 reg_offt) resource_size_t reg_base; struct bnxt_qplib_nq_db *nq_db; struct pci_dev *pdev; - int rc = 0; pdev = nq->pdev; nq_db = &nq->nq_db; @@ -481,8 +492,7 @@ static int bnxt_qplib_map_nq_db(struct bnxt_qplib_nq *nq, u32 reg_offt) if (!nq_db->reg.bar_base) { dev_err(&pdev->dev, "QPLIB: NQ BAR region %d resc start is 0!", nq_db->reg.bar_id); - rc = -ENOMEM; - goto fail; + return -ENOMEM; } reg_base = nq_db->reg.bar_base + reg_offt; @@ -492,15 +502,14 @@ static int bnxt_qplib_map_nq_db(struct bnxt_qplib_nq *nq, u32 reg_offt) if (!nq_db->reg.bar_reg) { dev_err(&pdev->dev, "QPLIB: NQ BAR region %d mapping failed", nq_db->reg.bar_id); - rc = -ENOMEM; - goto fail; + return -ENOMEM; } nq_db->dbinfo.db = nq_db->reg.bar_reg; nq_db->dbinfo.hwq = &nq->hwq; nq_db->dbinfo.xid = nq->ring_id; -fail: - return rc; + + return 0; } int bnxt_qplib_enable_nq(struct pci_dev *pdev, struct bnxt_qplib_nq *nq, @@ -614,7 +623,7 @@ int bnxt_qplib_create_srq(struct bnxt_qplib_res *res, hwq_attr.type = HWQ_TYPE_QUEUE; rc = bnxt_qplib_alloc_init_hwq(&srq->hwq, &hwq_attr); if (rc) - goto exit; + return rc; srq->swq = kcalloc(srq->hwq.max_elements, sizeof(*srq->swq), GFP_KERNEL); @@ -659,7 +668,7 @@ int bnxt_qplib_create_srq(struct bnxt_qplib_res *res, srq->dbinfo.xid = srq->id; srq->dbinfo.db = srq->dpi->dbr; srq->dbinfo.max_slot = 1; - srq->dbinfo.priv_db = res->dpi_tbl.dbr_bar_reg_iomem; + srq->dbinfo.priv_db = res->dpi_tbl.priv_db; if (srq->threshold) bnxt_qplib_armen_db(&srq->dbinfo, DBC_DBC_TYPE_SRQ_ARMENA); srq->arm_req = false; @@ -668,7 +677,7 @@ int bnxt_qplib_create_srq(struct bnxt_qplib_res *res, fail: bnxt_qplib_free_hwq(res, &srq->hwq); kfree(srq->swq); -exit: + return rc; } @@ -732,15 +741,14 @@ int bnxt_qplib_post_srq_recv(struct bnxt_qplib_srq *srq, struct rq_wqe *srqe; struct sq_sge *hw_sge; u32 sw_prod, sw_cons, count = 0; - int i, rc = 0, next; + int i, next; spin_lock(&srq_hwq->lock); if (srq->start_idx == srq->last_idx) { dev_err(&srq_hwq->pdev->dev, "FP: SRQ (0x%x) is full!\n", srq->id); - rc = -EINVAL; spin_unlock(&srq_hwq->lock); - goto done; + return -EINVAL; } next = srq->start_idx; srq->start_idx = srq->swq[next].next_idx; @@ -781,22 +789,19 @@ int bnxt_qplib_post_srq_recv(struct bnxt_qplib_srq *srq, srq->arm_req = false; bnxt_qplib_srq_arm_db(&srq->dbinfo, srq->threshold); } -done: - return rc; + + return 0; } /* QP */ static int bnxt_qplib_alloc_init_swq(struct bnxt_qplib_q *que) { - int rc = 0; int indx; que->swq = kcalloc(que->max_wqe, sizeof(*que->swq), GFP_KERNEL); - if (!que->swq) { - rc = -ENOMEM; - goto out; - } + if (!que->swq) + return -ENOMEM; que->swq_start = 0; que->swq_last = que->max_wqe - 1; @@ -804,8 +809,8 @@ static int bnxt_qplib_alloc_init_swq(struct bnxt_qplib_q *que) que->swq[indx].next_idx = indx + 1; que->swq[que->swq_last].next_idx = 0; /* Make it circular */ que->swq_last = 0; -out: - return rc; + + return 0; } int bnxt_qplib_create_qp1(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp) @@ -839,7 +844,7 @@ int bnxt_qplib_create_qp1(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp) hwq_attr.type = HWQ_TYPE_QUEUE; rc = bnxt_qplib_alloc_init_hwq(&sq->hwq, &hwq_attr); if (rc) - goto exit; + return rc; rc = bnxt_qplib_alloc_init_swq(sq); if (rc) @@ -927,7 +932,6 @@ int bnxt_qplib_create_qp1(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp) kfree(sq->swq); fail_sq: bnxt_qplib_free_hwq(res, &sq->hwq); -exit: return rc; } @@ -992,7 +996,7 @@ int bnxt_qplib_create_qp(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp) hwq_attr.type = HWQ_TYPE_QUEUE; rc = bnxt_qplib_alloc_init_hwq(&sq->hwq, &hwq_attr); if (rc) - goto exit; + return rc; rc = bnxt_qplib_alloc_init_swq(sq); if (rc) @@ -1140,7 +1144,6 @@ int bnxt_qplib_create_qp(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp) kfree(sq->swq); fail_sq: bnxt_qplib_free_hwq(res, &sq->hwq); -exit: return rc; } @@ -1614,7 +1617,7 @@ static int bnxt_qplib_put_inline(struct bnxt_qplib_qp *qp, il_src = (void *)wqe->sg_list[indx].addr; t_len += len; if (t_len > qp->max_inline_data) - goto bad; + return -ENOMEM; while (len) { if (pull_dst) { pull_dst = false; @@ -1638,8 +1641,6 @@ static int bnxt_qplib_put_inline(struct bnxt_qplib_qp *qp, } return t_len; -bad: - return -ENOMEM; } static u32 bnxt_qplib_put_sges(struct bnxt_qplib_hwq *hwq, @@ -2069,7 +2070,7 @@ int bnxt_qplib_create_cq(struct bnxt_qplib_res *res, struct bnxt_qplib_cq *cq) hwq_attr.sginfo = &cq->sg_info; rc = bnxt_qplib_alloc_init_hwq(&cq->hwq, &hwq_attr); if (rc) - goto exit; + return rc; bnxt_qplib_rcfw_cmd_prep((struct cmdq_base *)&req, CMDQ_BASE_OPCODE_CREATE_CQ, @@ -2104,7 +2105,7 @@ int bnxt_qplib_create_cq(struct bnxt_qplib_res *res, struct bnxt_qplib_cq *cq) cq->dbinfo.hwq = &cq->hwq; cq->dbinfo.xid = cq->id; cq->dbinfo.db = cq->dpi->dbr; - cq->dbinfo.priv_db = res->dpi_tbl.dbr_bar_reg_iomem; + cq->dbinfo.priv_db = res->dpi_tbl.priv_db; bnxt_qplib_armen_db(&cq->dbinfo, DBC_DBC_TYPE_CQ_ARMENA); @@ -2112,7 +2113,6 @@ int bnxt_qplib_create_cq(struct bnxt_qplib_res *res, struct bnxt_qplib_cq *cq) fail: bnxt_qplib_free_hwq(res, &cq->hwq); -exit: return rc; } @@ -2505,7 +2505,6 @@ static int bnxt_qplib_cq_process_res_rc(struct bnxt_qplib_cq *cq, struct bnxt_qplib_qp *qp; struct bnxt_qplib_q *rq; u32 wr_id_idx; - int rc = 0; qp = (struct bnxt_qplib_qp *)((unsigned long) le64_to_cpu(hwcqe->qp_handle)); @@ -2516,7 +2515,7 @@ static int bnxt_qplib_cq_process_res_rc(struct bnxt_qplib_cq *cq, if (qp->rq.flushed) { dev_dbg(&cq->hwq.pdev->dev, "%s: QP in Flush QP = %p\n", __func__, qp); - goto done; + return 0; } cqe = *pcqe; @@ -2572,8 +2571,7 @@ static int bnxt_qplib_cq_process_res_rc(struct bnxt_qplib_cq *cq, } } -done: - return rc; + return 0; } static int bnxt_qplib_cq_process_res_ud(struct bnxt_qplib_cq *cq, @@ -2586,7 +2584,6 @@ static int bnxt_qplib_cq_process_res_ud(struct bnxt_qplib_cq *cq, struct bnxt_qplib_qp *qp; struct bnxt_qplib_q *rq; u32 wr_id_idx; - int rc = 0; qp = (struct bnxt_qplib_qp *)((unsigned long) le64_to_cpu(hwcqe->qp_handle)); @@ -2597,7 +2594,7 @@ static int bnxt_qplib_cq_process_res_ud(struct bnxt_qplib_cq *cq, if (qp->rq.flushed) { dev_dbg(&cq->hwq.pdev->dev, "%s: QP in Flush QP = %p\n", __func__, qp); - goto done; + return 0; } cqe = *pcqe; cqe->opcode = hwcqe->cqe_type_toggle & CQ_BASE_CQE_TYPE_MASK; @@ -2659,8 +2656,8 @@ static int bnxt_qplib_cq_process_res_ud(struct bnxt_qplib_cq *cq, bnxt_qplib_add_flush_qp(qp); } } -done: - return rc; + + return 0; } bool bnxt_qplib_is_cq_empty(struct bnxt_qplib_cq *cq) @@ -2687,7 +2684,6 @@ static int bnxt_qplib_cq_process_res_raweth_qp1(struct bnxt_qplib_cq *cq, struct bnxt_qplib_srq *srq; struct bnxt_qplib_cqe *cqe; u32 wr_id_idx; - int rc = 0; qp = (struct bnxt_qplib_qp *)((unsigned long) le64_to_cpu(hwcqe->qp_handle)); @@ -2698,7 +2694,7 @@ static int bnxt_qplib_cq_process_res_raweth_qp1(struct bnxt_qplib_cq *cq, if (qp->rq.flushed) { dev_dbg(&cq->hwq.pdev->dev, "%s: QP in Flush QP = %p\n", __func__, qp); - goto done; + return 0; } cqe = *pcqe; cqe->opcode = hwcqe->cqe_type_toggle & CQ_BASE_CQE_TYPE_MASK; @@ -2767,8 +2763,7 @@ static int bnxt_qplib_cq_process_res_raweth_qp1(struct bnxt_qplib_cq *cq, } } -done: - return rc; + return 0; } static int bnxt_qplib_cq_process_terminal(struct bnxt_qplib_cq *cq, @@ -2790,11 +2785,8 @@ static int bnxt_qplib_cq_process_terminal(struct bnxt_qplib_cq *cq, qp = (struct bnxt_qplib_qp *)((unsigned long) le64_to_cpu(hwcqe->qp_handle)); - if (!qp) { - dev_err(&cq->hwq.pdev->dev, - "FP: CQ Process terminal qp is NULL\n"); + if (!qp) return -EINVAL; - } /* Must block new posting of SQ and RQ */ qp->state = CMDQ_MODIFY_QP_NEW_STATE_ERR; diff --git a/drivers/infiniband/hw/bnxt_re/qplib_fp.h b/drivers/infiniband/hw/bnxt_re/qplib_fp.h index d74d5ead2e32a2de2e8a05969af4ad0ccc859c2d..a42820821c473073973331750924c7f8421cb9b6 100644 --- a/drivers/infiniband/hw/bnxt_re/qplib_fp.h +++ b/drivers/infiniband/hw/bnxt_re/qplib_fp.h @@ -472,7 +472,7 @@ typedef int (*srqn_handler_t)(struct bnxt_qplib_nq *nq, struct bnxt_qplib_nq { struct pci_dev *pdev; struct bnxt_qplib_res *res; - char name[32]; + char *name; struct bnxt_qplib_hwq hwq; struct bnxt_qplib_nq_db nq_db; u16 ring_id; diff --git a/drivers/infiniband/hw/bnxt_re/qplib_rcfw.c b/drivers/infiniband/hw/bnxt_re/qplib_rcfw.c index de9069103177307279f65b12a3a8e76e26579915..b30e66b64827b241bae8f5d121eff790febae227 100644 --- a/drivers/infiniband/hw/bnxt_re/qplib_rcfw.c +++ b/drivers/infiniband/hw/bnxt_re/qplib_rcfw.c @@ -53,112 +53,289 @@ static void bnxt_qplib_service_creq(struct tasklet_struct *t); -/* Hardware communication channel */ +/** + * bnxt_qplib_map_rc - map return type based on opcode + * @opcode - roce slow path opcode + * + * case #1 + * Firmware initiated error recovery is a safe state machine and + * driver can consider all the underlying rdma resources are free. + * In this state, it is safe to return success for opcodes related to + * destroying rdma resources (like destroy qp, destroy cq etc.). + * + * case #2 + * If driver detect potential firmware stall, it is not safe state machine + * and the driver can not consider all the underlying rdma resources are + * freed. + * In this state, it is not safe to return success for opcodes related to + * destroying rdma resources (like destroy qp, destroy cq etc.). + * + * Scope of this helper function is only for case #1. + * + * Returns: + * 0 to communicate success to caller. + * Non zero error code to communicate failure to caller. + */ +static int bnxt_qplib_map_rc(u8 opcode) +{ + switch (opcode) { + case CMDQ_BASE_OPCODE_DESTROY_QP: + case CMDQ_BASE_OPCODE_DESTROY_SRQ: + case CMDQ_BASE_OPCODE_DESTROY_CQ: + case CMDQ_BASE_OPCODE_DEALLOCATE_KEY: + case CMDQ_BASE_OPCODE_DEREGISTER_MR: + case CMDQ_BASE_OPCODE_DELETE_GID: + case CMDQ_BASE_OPCODE_DESTROY_QP1: + case CMDQ_BASE_OPCODE_DESTROY_AH: + case CMDQ_BASE_OPCODE_DEINITIALIZE_FW: + case CMDQ_BASE_OPCODE_MODIFY_ROCE_CC: + case CMDQ_BASE_OPCODE_SET_LINK_AGGR_MODE: + return 0; + default: + return -ETIMEDOUT; + } +} + +/** + * bnxt_re_is_fw_stalled - Check firmware health + * @rcfw - rcfw channel instance of rdev + * @cookie - cookie to track the command + * + * If firmware has not responded any rcfw command within + * rcfw->max_timeout, consider firmware as stalled. + * + * Returns: + * 0 if firmware is responding + * -ENODEV if firmware is not responding + */ +static int bnxt_re_is_fw_stalled(struct bnxt_qplib_rcfw *rcfw, + u16 cookie) +{ + struct bnxt_qplib_cmdq_ctx *cmdq; + struct bnxt_qplib_crsqe *crsqe; + + crsqe = &rcfw->crsqe_tbl[cookie]; + cmdq = &rcfw->cmdq; + + if (time_after(jiffies, cmdq->last_seen + + (rcfw->max_timeout * HZ))) { + dev_warn_ratelimited(&rcfw->pdev->dev, + "%s: FW STALL Detected. cmdq[%#x]=%#x waited (%d > %d) msec active %d ", + __func__, cookie, crsqe->opcode, + jiffies_to_msecs(jiffies - cmdq->last_seen), + rcfw->max_timeout * 1000, + crsqe->is_in_used); + return -ENODEV; + } + + return 0; +} + +/** + * __wait_for_resp - Don't hold the cpu context and wait for response + * @rcfw - rcfw channel instance of rdev + * @cookie - cookie to track the command + * + * Wait for command completion in sleepable context. + * + * Returns: + * 0 if command is completed by firmware. + * Non zero error code for rest of the case. + */ static int __wait_for_resp(struct bnxt_qplib_rcfw *rcfw, u16 cookie) { struct bnxt_qplib_cmdq_ctx *cmdq; - u16 cbit; - int rc; + struct bnxt_qplib_crsqe *crsqe; + int ret; cmdq = &rcfw->cmdq; - cbit = cookie % rcfw->cmdq_depth; - rc = wait_event_timeout(cmdq->waitq, - !test_bit(cbit, cmdq->cmdq_bitmap), - msecs_to_jiffies(RCFW_CMD_WAIT_TIME_MS)); - return rc ? 0 : -ETIMEDOUT; + crsqe = &rcfw->crsqe_tbl[cookie]; + + do { + if (test_bit(ERR_DEVICE_DETACHED, &cmdq->flags)) + return bnxt_qplib_map_rc(crsqe->opcode); + if (test_bit(FIRMWARE_STALL_DETECTED, &cmdq->flags)) + return -ETIMEDOUT; + + wait_event_timeout(cmdq->waitq, + !crsqe->is_in_used || + test_bit(ERR_DEVICE_DETACHED, &cmdq->flags), + msecs_to_jiffies(rcfw->max_timeout * 1000)); + + if (!crsqe->is_in_used) + return 0; + + bnxt_qplib_service_creq(&rcfw->creq.creq_tasklet); + + if (!crsqe->is_in_used) + return 0; + + ret = bnxt_re_is_fw_stalled(rcfw, cookie); + if (ret) + return ret; + + } while (true); }; +/** + * __block_for_resp - hold the cpu context and wait for response + * @rcfw - rcfw channel instance of rdev + * @cookie - cookie to track the command + * + * This function will hold the cpu (non-sleepable context) and + * wait for command completion. Maximum holding interval is 8 second. + * + * Returns: + * -ETIMEOUT if command is not completed in specific time interval. + * 0 if command is completed by firmware. + */ static int __block_for_resp(struct bnxt_qplib_rcfw *rcfw, u16 cookie) { - u32 count = RCFW_BLOCKED_CMD_WAIT_COUNT; - struct bnxt_qplib_cmdq_ctx *cmdq; - u16 cbit; + struct bnxt_qplib_cmdq_ctx *cmdq = &rcfw->cmdq; + struct bnxt_qplib_crsqe *crsqe; + unsigned long issue_time = 0; + + issue_time = jiffies; + crsqe = &rcfw->crsqe_tbl[cookie]; - cmdq = &rcfw->cmdq; - cbit = cookie % rcfw->cmdq_depth; - if (!test_bit(cbit, cmdq->cmdq_bitmap)) - goto done; do { + if (test_bit(ERR_DEVICE_DETACHED, &cmdq->flags)) + return bnxt_qplib_map_rc(crsqe->opcode); + if (test_bit(FIRMWARE_STALL_DETECTED, &cmdq->flags)) + return -ETIMEDOUT; + udelay(1); + bnxt_qplib_service_creq(&rcfw->creq.creq_tasklet); - } while (test_bit(cbit, cmdq->cmdq_bitmap) && --count); -done: - return count ? 0 : -ETIMEDOUT; + if (!crsqe->is_in_used) + return 0; + + } while (time_before(jiffies, issue_time + (8 * HZ))); + + return -ETIMEDOUT; }; -static int __send_message(struct bnxt_qplib_rcfw *rcfw, - struct bnxt_qplib_cmdqmsg *msg) +/* __send_message_no_waiter - get cookie and post the message. + * @rcfw - rcfw channel instance of rdev + * @msg - qplib message internal + * + * This function will just post and don't bother about completion. + * Current design of this function is - + * user must hold the completion queue hwq->lock. + * user must have used existing completion and free the resources. + * this function will not check queue full condition. + * this function will explicitly set is_waiter_alive=false. + * current use case is - send destroy_ah if create_ah is return + * after waiter of create_ah is lost. It can be extended for other + * use case as well. + * + * Returns: Nothing + * + */ +static void __send_message_no_waiter(struct bnxt_qplib_rcfw *rcfw, + struct bnxt_qplib_cmdqmsg *msg) { struct bnxt_qplib_cmdq_ctx *cmdq = &rcfw->cmdq; struct bnxt_qplib_hwq *hwq = &cmdq->hwq; struct bnxt_qplib_crsqe *crsqe; struct bnxt_qplib_cmdqe *cmdqe; u32 sw_prod, cmdq_prod; - struct pci_dev *pdev; - unsigned long flags; - u32 bsize, opcode; - u16 cookie, cbit; + u16 cookie; + u32 bsize; u8 *preq; - pdev = rcfw->pdev; + cookie = cmdq->seq_num & RCFW_MAX_COOKIE_VALUE; + __set_cmdq_base_cookie(msg->req, msg->req_sz, cpu_to_le16(cookie)); + crsqe = &rcfw->crsqe_tbl[cookie]; - opcode = __get_cmdq_base_opcode(msg->req, msg->req_sz); - if (!test_bit(FIRMWARE_INITIALIZED_FLAG, &cmdq->flags) && - (opcode != CMDQ_BASE_OPCODE_QUERY_FUNC && - opcode != CMDQ_BASE_OPCODE_INITIALIZE_FW && - opcode != CMDQ_BASE_OPCODE_QUERY_VERSION)) { - dev_err(&pdev->dev, - "RCFW not initialized, reject opcode 0x%x\n", opcode); - return -EINVAL; - } + /* Set cmd_size in terms of 16B slots in req. */ + bsize = bnxt_qplib_set_cmd_slots(msg->req); + /* GET_CMD_SIZE would return number of slots in either case of tlv + * and non-tlv commands after call to bnxt_qplib_set_cmd_slots() + */ + crsqe->is_internal_cmd = true; + crsqe->is_waiter_alive = false; + crsqe->is_in_used = true; + crsqe->req_size = __get_cmdq_base_cmd_size(msg->req, msg->req_sz); - if (test_bit(FIRMWARE_INITIALIZED_FLAG, &cmdq->flags) && - opcode == CMDQ_BASE_OPCODE_INITIALIZE_FW) { - dev_err(&pdev->dev, "RCFW already initialized!\n"); - return -EINVAL; - } + preq = (u8 *)msg->req; + do { + /* Locate the next cmdq slot */ + sw_prod = HWQ_CMP(hwq->prod, hwq); + cmdqe = bnxt_qplib_get_qe(hwq, sw_prod, NULL); + /* Copy a segment of the req cmd to the cmdq */ + memset(cmdqe, 0, sizeof(*cmdqe)); + memcpy(cmdqe, preq, min_t(u32, bsize, sizeof(*cmdqe))); + preq += min_t(u32, bsize, sizeof(*cmdqe)); + bsize -= min_t(u32, bsize, sizeof(*cmdqe)); + hwq->prod++; + } while (bsize > 0); + cmdq->seq_num++; - if (test_bit(FIRMWARE_TIMED_OUT, &cmdq->flags)) - return -ETIMEDOUT; + cmdq_prod = hwq->prod; + atomic_inc(&rcfw->timeout_send); + /* ring CMDQ DB */ + wmb(); + writel(cmdq_prod, cmdq->cmdq_mbox.prod); + writel(RCFW_CMDQ_TRIG_VAL, cmdq->cmdq_mbox.db); +} + +static int __send_message(struct bnxt_qplib_rcfw *rcfw, + struct bnxt_qplib_cmdqmsg *msg, u8 opcode) +{ + u32 bsize, free_slots, required_slots; + struct bnxt_qplib_cmdq_ctx *cmdq; + struct bnxt_qplib_crsqe *crsqe; + struct bnxt_qplib_cmdqe *cmdqe; + struct bnxt_qplib_hwq *hwq; + u32 sw_prod, cmdq_prod; + struct pci_dev *pdev; + unsigned long flags; + u16 cookie; + u8 *preq; + + cmdq = &rcfw->cmdq; + hwq = &cmdq->hwq; + pdev = rcfw->pdev; /* Cmdq are in 16-byte units, each request can consume 1 or more * cmdqe */ spin_lock_irqsave(&hwq->lock, flags); - if (msg->req->cmd_size >= HWQ_FREE_SLOTS(hwq)) { - dev_err(&pdev->dev, "RCFW: CMDQ is full!\n"); + required_slots = bnxt_qplib_get_cmd_slots(msg->req); + free_slots = HWQ_FREE_SLOTS(hwq); + cookie = cmdq->seq_num & RCFW_MAX_COOKIE_VALUE; + crsqe = &rcfw->crsqe_tbl[cookie]; + + if (required_slots >= free_slots) { + dev_info_ratelimited(&pdev->dev, + "CMDQ is full req/free %d/%d!", + required_slots, free_slots); spin_unlock_irqrestore(&hwq->lock, flags); return -EAGAIN; } - - - cookie = cmdq->seq_num & RCFW_MAX_COOKIE_VALUE; - cbit = cookie % rcfw->cmdq_depth; if (msg->block) cookie |= RCFW_CMD_IS_BLOCKING; - - set_bit(cbit, cmdq->cmdq_bitmap); __set_cmdq_base_cookie(msg->req, msg->req_sz, cpu_to_le16(cookie)); - crsqe = &rcfw->crsqe_tbl[cbit]; - if (crsqe->resp) { - spin_unlock_irqrestore(&hwq->lock, flags); - return -EBUSY; - } - /* change the cmd_size to the number of 16byte cmdq unit. - * req->cmd_size is modified here - */ bsize = bnxt_qplib_set_cmd_slots(msg->req); - - memset(msg->resp, 0, sizeof(*msg->resp)); + crsqe->free_slots = free_slots; crsqe->resp = (struct creq_qp_event *)msg->resp; crsqe->resp->cookie = cpu_to_le16(cookie); + crsqe->is_internal_cmd = false; + crsqe->is_waiter_alive = true; + crsqe->is_in_used = true; + crsqe->opcode = opcode; + crsqe->req_size = __get_cmdq_base_cmd_size(msg->req, msg->req_sz); if (__get_cmdq_base_resp_size(msg->req, msg->req_sz) && msg->sb) { struct bnxt_qplib_rcfw_sbuf *sbuf = msg->sb; - __set_cmdq_base_resp_addr(msg->req, msg->req_sz, cpu_to_le64(sbuf->dma_addr)); + + __set_cmdq_base_resp_addr(msg->req, msg->req_sz, + cpu_to_le64(sbuf->dma_addr)); __set_cmdq_base_resp_size(msg->req, msg->req_sz, - ALIGN(sbuf->size, BNXT_QPLIB_CMDQE_UNITS)); + ALIGN(sbuf->size, + BNXT_QPLIB_CMDQE_UNITS)); } preq = (u8 *)msg->req; @@ -166,11 +343,6 @@ static int __send_message(struct bnxt_qplib_rcfw *rcfw, /* Locate the next cmdq slot */ sw_prod = HWQ_CMP(hwq->prod, hwq); cmdqe = bnxt_qplib_get_qe(hwq, sw_prod, NULL); - if (!cmdqe) { - dev_err(&pdev->dev, - "RCFW request failed with no cmdqe!\n"); - goto done; - } /* Copy a segment of the req cmd to the cmdq */ memset(cmdqe, 0, sizeof(*cmdqe)); memcpy(cmdqe, preq, min_t(u32, bsize, sizeof(*cmdqe))); @@ -180,7 +352,7 @@ static int __send_message(struct bnxt_qplib_rcfw *rcfw, } while (bsize > 0); cmdq->seq_num++; - cmdq_prod = hwq->prod; + cmdq_prod = hwq->prod & 0xFFFF; if (test_bit(FIRMWARE_FIRST_FLAG, &cmdq->flags)) { /* The very first doorbell write * is required to set this flag @@ -194,51 +366,158 @@ static int __send_message(struct bnxt_qplib_rcfw *rcfw, wmb(); writel(cmdq_prod, cmdq->cmdq_mbox.prod); writel(RCFW_CMDQ_TRIG_VAL, cmdq->cmdq_mbox.db); -done: spin_unlock_irqrestore(&hwq->lock, flags); /* Return the CREQ response pointer */ return 0; } -int bnxt_qplib_rcfw_send_message(struct bnxt_qplib_rcfw *rcfw, - struct bnxt_qplib_cmdqmsg *msg) +/** + * __poll_for_resp - self poll completion for rcfw command + * @rcfw - rcfw channel instance of rdev + * @cookie - cookie to track the command + * + * It works same as __wait_for_resp except this function will + * do self polling in sort interval since interrupt is disabled. + * This function can not be called from non-sleepable context. + * + * Returns: + * -ETIMEOUT if command is not completed in specific time interval. + * 0 if command is completed by firmware. + */ +static int __poll_for_resp(struct bnxt_qplib_rcfw *rcfw, u16 cookie) +{ + struct bnxt_qplib_cmdq_ctx *cmdq = &rcfw->cmdq; + struct bnxt_qplib_crsqe *crsqe; + unsigned long issue_time; + int ret; + + issue_time = jiffies; + crsqe = &rcfw->crsqe_tbl[cookie]; + + do { + if (test_bit(ERR_DEVICE_DETACHED, &cmdq->flags)) + return bnxt_qplib_map_rc(crsqe->opcode); + if (test_bit(FIRMWARE_STALL_DETECTED, &cmdq->flags)) + return -ETIMEDOUT; + + usleep_range(1000, 1001); + + bnxt_qplib_service_creq(&rcfw->creq.creq_tasklet); + if (!crsqe->is_in_used) + return 0; + if (jiffies_to_msecs(jiffies - issue_time) > + (rcfw->max_timeout * 1000)) { + ret = bnxt_re_is_fw_stalled(rcfw, cookie); + if (ret) + return ret; + } + } while (true); +}; + +static int __send_message_basic_sanity(struct bnxt_qplib_rcfw *rcfw, + struct bnxt_qplib_cmdqmsg *msg, + u8 opcode) +{ + struct bnxt_qplib_cmdq_ctx *cmdq; + + cmdq = &rcfw->cmdq; + + /* Prevent posting if f/w is not in a state to process */ + if (test_bit(ERR_DEVICE_DETACHED, &rcfw->cmdq.flags)) + return bnxt_qplib_map_rc(opcode); + if (test_bit(FIRMWARE_STALL_DETECTED, &cmdq->flags)) + return -ETIMEDOUT; + + if (test_bit(FIRMWARE_INITIALIZED_FLAG, &cmdq->flags) && + opcode == CMDQ_BASE_OPCODE_INITIALIZE_FW) { + dev_err(&rcfw->pdev->dev, "QPLIB: RCFW already initialized!"); + return -EINVAL; + } + + if (!test_bit(FIRMWARE_INITIALIZED_FLAG, &cmdq->flags) && + (opcode != CMDQ_BASE_OPCODE_QUERY_FUNC && + opcode != CMDQ_BASE_OPCODE_INITIALIZE_FW && + opcode != CMDQ_BASE_OPCODE_QUERY_VERSION)) { + dev_err(&rcfw->pdev->dev, + "QPLIB: RCFW not initialized, reject opcode 0x%x", + opcode); + return -EOPNOTSUPP; + } + + return 0; +} + +/* This function will just post and do not bother about completion */ +static void __destroy_timedout_ah(struct bnxt_qplib_rcfw *rcfw, + struct creq_create_ah_resp *create_ah_resp) +{ + struct bnxt_qplib_cmdqmsg msg = {}; + struct cmdq_destroy_ah req = {}; + + bnxt_qplib_rcfw_cmd_prep((struct cmdq_base *)&req, + CMDQ_BASE_OPCODE_DESTROY_AH, + sizeof(req)); + req.ah_cid = create_ah_resp->xid; + msg.req = (struct cmdq_base *)&req; + msg.req_sz = sizeof(req); + __send_message_no_waiter(rcfw, &msg); + dev_info_ratelimited(&rcfw->pdev->dev, + "From %s: ah_cid = %d timeout_send %d\n", + __func__, req.ah_cid, + atomic_read(&rcfw->timeout_send)); +} + +/** + * __bnxt_qplib_rcfw_send_message - qplib interface to send + * and complete rcfw command. + * @rcfw - rcfw channel instance of rdev + * @msg - qplib message internal + * + * This function does not account shadow queue depth. It will send + * all the command unconditionally as long as send queue is not full. + * + * Returns: + * 0 if command completed by firmware. + * Non zero if the command is not completed by firmware. + */ +static int __bnxt_qplib_rcfw_send_message(struct bnxt_qplib_rcfw *rcfw, + struct bnxt_qplib_cmdqmsg *msg) { struct creq_qp_event *evnt = (struct creq_qp_event *)msg->resp; + struct bnxt_qplib_crsqe *crsqe; + unsigned long flags; u16 cookie; - u8 opcode, retry_cnt = 0xFF; int rc = 0; + u8 opcode; - /* Prevent posting if f/w is not in a state to process */ - if (test_bit(ERR_DEVICE_DETACHED, &rcfw->cmdq.flags)) - return 0; + opcode = __get_cmdq_base_opcode(msg->req, msg->req_sz); - do { - opcode = __get_cmdq_base_opcode(msg->req, msg->req_sz); - rc = __send_message(rcfw, msg); - cookie = le16_to_cpu(__get_cmdq_base_cookie(msg->req, msg->req_sz)) & - RCFW_MAX_COOKIE_VALUE; - if (!rc) - break; - if (!retry_cnt || (rc != -EAGAIN && rc != -EBUSY)) { - /* send failed */ - dev_err(&rcfw->pdev->dev, "cmdq[%#x]=%#x send failed\n", - cookie, opcode); - return rc; - } - msg->block ? mdelay(1) : usleep_range(500, 1000); + rc = __send_message_basic_sanity(rcfw, msg, opcode); + if (rc) + return rc; - } while (retry_cnt--); + rc = __send_message(rcfw, msg, opcode); + if (rc) + return rc; + + cookie = le16_to_cpu(__get_cmdq_base_cookie(msg->req, msg->req_sz)) + & RCFW_MAX_COOKIE_VALUE; if (msg->block) rc = __block_for_resp(rcfw, cookie); - else + else if (atomic_read(&rcfw->rcfw_intr_enabled)) rc = __wait_for_resp(rcfw, cookie); + else + rc = __poll_for_resp(rcfw, cookie); + if (rc) { - /* timed out */ - dev_err(&rcfw->pdev->dev, "cmdq[%#x]=%#x timedout (%d)msec\n", - cookie, opcode, RCFW_CMD_WAIT_TIME_MS); - set_bit(FIRMWARE_TIMED_OUT, &rcfw->cmdq.flags); - return rc; + spin_lock_irqsave(&rcfw->cmdq.hwq.lock, flags); + crsqe = &rcfw->crsqe_tbl[cookie]; + crsqe->is_waiter_alive = false; + if (rc == -ENODEV) + set_bit(FIRMWARE_STALL_DETECTED, &rcfw->cmdq.flags); + spin_unlock_irqrestore(&rcfw->cmdq.hwq.lock, flags); + return -ETIMEDOUT; } if (evnt->status) { @@ -250,6 +529,48 @@ int bnxt_qplib_rcfw_send_message(struct bnxt_qplib_rcfw *rcfw, return rc; } + +/** + * bnxt_qplib_rcfw_send_message - qplib interface to send + * and complete rcfw command. + * @rcfw - rcfw channel instance of rdev + * @msg - qplib message internal + * + * Driver interact with Firmware through rcfw channel/slow path in two ways. + * a. Blocking rcfw command send. In this path, driver cannot hold + * the context for longer period since it is holding cpu until + * command is not completed. + * b. Non-blocking rcfw command send. In this path, driver can hold the + * context for longer period. There may be many pending command waiting + * for completion because of non-blocking nature. + * + * Driver will use shadow queue depth. Current queue depth of 8K + * (due to size of rcfw message there can be actual ~4K rcfw outstanding) + * is not optimal for rcfw command processing in firmware. + * + * Restrict at max #RCFW_CMD_NON_BLOCKING_SHADOW_QD Non-Blocking rcfw commands. + * Allow all blocking commands until there is no queue full. + * + * Returns: + * 0 if command completed by firmware. + * Non zero if the command is not completed by firmware. + */ +int bnxt_qplib_rcfw_send_message(struct bnxt_qplib_rcfw *rcfw, + struct bnxt_qplib_cmdqmsg *msg) +{ + int ret; + + if (!msg->block) { + down(&rcfw->rcfw_inflight); + ret = __bnxt_qplib_rcfw_send_message(rcfw, msg); + up(&rcfw->rcfw_inflight); + } else { + ret = __bnxt_qplib_rcfw_send_message(rcfw, msg); + } + + return ret; +} + /* Completions */ static int bnxt_qplib_process_func_event(struct bnxt_qplib_rcfw *rcfw, struct creq_func_event *func_event) @@ -295,19 +616,20 @@ static int bnxt_qplib_process_func_event(struct bnxt_qplib_rcfw *rcfw, } static int bnxt_qplib_process_qp_event(struct bnxt_qplib_rcfw *rcfw, - struct creq_qp_event *qp_event) + struct creq_qp_event *qp_event, + u32 *num_wait) { struct creq_qp_error_notification *err_event; struct bnxt_qplib_hwq *hwq = &rcfw->cmdq.hwq; struct bnxt_qplib_crsqe *crsqe; + u32 qp_id, tbl_indx, req_size; struct bnxt_qplib_qp *qp; - u16 cbit, blocked = 0; + u16 cookie, blocked = 0; + bool is_waiter_alive; struct pci_dev *pdev; unsigned long flags; - __le16 mcookie; - u16 cookie; + u32 wait_cmds = 0; int rc = 0; - u32 qp_id, tbl_indx; pdev = rcfw->pdev; switch (qp_event->event) { @@ -339,33 +661,60 @@ static int bnxt_qplib_process_qp_event(struct bnxt_qplib_rcfw *rcfw, spin_lock_irqsave_nested(&hwq->lock, flags, SINGLE_DEPTH_NESTING); cookie = le16_to_cpu(qp_event->cookie); - mcookie = qp_event->cookie; blocked = cookie & RCFW_CMD_IS_BLOCKING; cookie &= RCFW_MAX_COOKIE_VALUE; - cbit = cookie % rcfw->cmdq_depth; - crsqe = &rcfw->crsqe_tbl[cbit]; - if (crsqe->resp && - crsqe->resp->cookie == mcookie) { - memcpy(crsqe->resp, qp_event, sizeof(*qp_event)); - crsqe->resp = NULL; - } else { - if (crsqe->resp && crsqe->resp->cookie) - dev_err(&pdev->dev, - "CMD %s cookie sent=%#x, recd=%#x\n", - crsqe->resp ? "mismatch" : "collision", - crsqe->resp ? crsqe->resp->cookie : 0, - mcookie); + crsqe = &rcfw->crsqe_tbl[cookie]; + crsqe->is_in_used = false; + + if (WARN_ONCE(test_bit(FIRMWARE_STALL_DETECTED, + &rcfw->cmdq.flags), + "QPLIB: Unreponsive rcfw channel detected.!!")) { + dev_info(&pdev->dev, + "rcfw timedout: cookie = %#x, free_slots = %d", + cookie, crsqe->free_slots); + spin_unlock_irqrestore(&hwq->lock, flags); + return rc; } - if (!test_and_clear_bit(cbit, rcfw->cmdq.cmdq_bitmap)) - dev_warn(&pdev->dev, - "CMD bit %d was not requested\n", cbit); - hwq->cons += crsqe->req_size; + + if (crsqe->is_internal_cmd && !qp_event->status) + atomic_dec(&rcfw->timeout_send); + + if (crsqe->is_waiter_alive) { + if (crsqe->resp) + memcpy(crsqe->resp, qp_event, sizeof(*qp_event)); + if (!blocked) + wait_cmds++; + } + + req_size = crsqe->req_size; + is_waiter_alive = crsqe->is_waiter_alive; + crsqe->req_size = 0; + if (!is_waiter_alive) + crsqe->resp = NULL; - if (!blocked) - wake_up(&rcfw->cmdq.waitq); + hwq->cons += req_size; + + /* This is a case to handle below scenario - + * Create AH is completed successfully by firmware, + * but completion took more time and driver already lost + * the context of create_ah from caller. + * We have already return failure for create_ah verbs, + * so let's destroy the same address vector since it is + * no more used in stack. We don't care about completion + * in __send_message_no_waiter. + * If destroy_ah is failued by firmware, there will be AH + * resource leak and relatively not critical + unlikely + * scenario. Current design is not to handle such case. + */ + if (!is_waiter_alive && !qp_event->status && + qp_event->event == CREQ_QP_EVENT_EVENT_CREATE_AH) + __destroy_timedout_ah(rcfw, + (struct creq_create_ah_resp *) + qp_event); spin_unlock_irqrestore(&hwq->lock, flags); } + *num_wait += wait_cmds; return rc; } @@ -379,6 +728,7 @@ static void bnxt_qplib_service_creq(struct tasklet_struct *t) struct creq_base *creqe; u32 sw_cons, raw_cons; unsigned long flags; + u32 num_wakeup = 0; /* Service the CREQ until budget is over */ spin_lock_irqsave(&hwq->lock, flags); @@ -392,12 +742,14 @@ static void bnxt_qplib_service_creq(struct tasklet_struct *t) * reading any further. */ dma_rmb(); + rcfw->cmdq.last_seen = jiffies; type = creqe->type & CREQ_BASE_TYPE_MASK; switch (type) { case CREQ_BASE_TYPE_QP_EVENT: bnxt_qplib_process_qp_event - (rcfw, (struct creq_qp_event *)creqe); + (rcfw, (struct creq_qp_event *)creqe, + &num_wakeup); creq->stats.creq_qp_event_processed++; break; case CREQ_BASE_TYPE_FUNC_EVENT: @@ -425,6 +777,8 @@ static void bnxt_qplib_service_creq(struct tasklet_struct *t) rcfw->res->cctx, true); } spin_unlock_irqrestore(&hwq->lock, flags); + if (num_wakeup) + wake_up_nr(&rcfw->cmdq.waitq, num_wakeup); } static irqreturn_t bnxt_qplib_creq_irq(int irq, void *dev_instance) @@ -556,7 +910,6 @@ int bnxt_qplib_init_rcfw(struct bnxt_qplib_rcfw *rcfw, void bnxt_qplib_free_rcfw_channel(struct bnxt_qplib_rcfw *rcfw) { - bitmap_free(rcfw->cmdq.cmdq_bitmap); kfree(rcfw->qp_tbl); kfree(rcfw->crsqe_tbl); bnxt_qplib_free_hwq(rcfw->res, &rcfw->cmdq.hwq); @@ -593,13 +946,11 @@ int bnxt_qplib_alloc_rcfw_channel(struct bnxt_qplib_res *res, "HW channel CREQ allocation failed\n"); goto fail; } - if (ctx->hwrm_intf_ver < HWRM_VERSION_RCFW_CMDQ_DEPTH_CHECK) - rcfw->cmdq_depth = BNXT_QPLIB_CMDQE_MAX_CNT_256; - else - rcfw->cmdq_depth = BNXT_QPLIB_CMDQE_MAX_CNT_8192; + + rcfw->cmdq_depth = BNXT_QPLIB_CMDQE_MAX_CNT; sginfo.pgsize = bnxt_qplib_cmdqe_page_size(rcfw->cmdq_depth); - hwq_attr.depth = rcfw->cmdq_depth; + hwq_attr.depth = rcfw->cmdq_depth & 0x7FFFFFFF; hwq_attr.stride = BNXT_QPLIB_CMDQE_UNITS; hwq_attr.type = HWQ_TYPE_CTX; if (bnxt_qplib_alloc_init_hwq(&cmdq->hwq, &hwq_attr)) { @@ -613,10 +964,6 @@ int bnxt_qplib_alloc_rcfw_channel(struct bnxt_qplib_res *res, if (!rcfw->crsqe_tbl) goto fail; - cmdq->cmdq_bitmap = bitmap_zalloc(rcfw->cmdq_depth, GFP_KERNEL); - if (!cmdq->cmdq_bitmap) - goto fail; - /* Allocate one extra to hold the QP1 entries */ rcfw->qp_tbl_size = qp_tbl_sz + 1; rcfw->qp_tbl = kcalloc(rcfw->qp_tbl_size, sizeof(struct bnxt_qplib_qp_node), @@ -624,6 +971,8 @@ int bnxt_qplib_alloc_rcfw_channel(struct bnxt_qplib_res *res, if (!rcfw->qp_tbl) goto fail; + rcfw->max_timeout = res->cctx->hwrm_cmd_max_timeout; + return 0; fail: @@ -636,6 +985,10 @@ void bnxt_qplib_rcfw_stop_irq(struct bnxt_qplib_rcfw *rcfw, bool kill) struct bnxt_qplib_creq_ctx *creq; creq = &rcfw->creq; + + if (!creq->requested) + return; + tasklet_disable(&creq->creq_tasklet); /* Mask h/w interrupts */ bnxt_qplib_ring_nq_db(&creq->creq_db.dbinfo, rcfw->res->cctx, false); @@ -644,17 +997,17 @@ void bnxt_qplib_rcfw_stop_irq(struct bnxt_qplib_rcfw *rcfw, bool kill) if (kill) tasklet_kill(&creq->creq_tasklet); - if (creq->requested) { - free_irq(creq->msix_vec, rcfw); - creq->requested = false; - } + free_irq(creq->msix_vec, rcfw); + kfree(creq->irq_name); + creq->irq_name = NULL; + creq->requested = false; + atomic_set(&rcfw->rcfw_intr_enabled, 0); } void bnxt_qplib_disable_rcfw_channel(struct bnxt_qplib_rcfw *rcfw) { struct bnxt_qplib_creq_ctx *creq; struct bnxt_qplib_cmdq_ctx *cmdq; - unsigned long indx; creq = &rcfw->creq; cmdq = &rcfw->cmdq; @@ -664,11 +1017,6 @@ void bnxt_qplib_disable_rcfw_channel(struct bnxt_qplib_rcfw *rcfw) iounmap(cmdq->cmdq_mbox.reg.bar_reg); iounmap(creq->creq_db.reg.bar_reg); - indx = find_first_bit(cmdq->cmdq_bitmap, rcfw->cmdq_depth); - if (indx != rcfw->cmdq_depth) - dev_err(&rcfw->pdev->dev, - "disabling RCFW with pending cmd-bit %lx\n", indx); - cmdq->cmdq_mbox.reg.bar_reg = NULL; creq->creq_db.reg.bar_reg = NULL; creq->aeq_handler = NULL; @@ -679,9 +1027,11 @@ int bnxt_qplib_rcfw_start_irq(struct bnxt_qplib_rcfw *rcfw, int msix_vector, bool need_init) { struct bnxt_qplib_creq_ctx *creq; + struct bnxt_qplib_res *res; int rc; creq = &rcfw->creq; + res = rcfw->res; if (creq->requested) return -EFAULT; @@ -691,24 +1041,32 @@ int bnxt_qplib_rcfw_start_irq(struct bnxt_qplib_rcfw *rcfw, int msix_vector, tasklet_setup(&creq->creq_tasklet, bnxt_qplib_service_creq); else tasklet_enable(&creq->creq_tasklet); + + creq->irq_name = kasprintf(GFP_KERNEL, "bnxt_re-creq@pci:%s", + pci_name(res->pdev)); + if (!creq->irq_name) + return -ENOMEM; rc = request_irq(creq->msix_vec, bnxt_qplib_creq_irq, 0, - "bnxt_qplib_creq", rcfw); - if (rc) + creq->irq_name, rcfw); + if (rc) { + kfree(creq->irq_name); + creq->irq_name = NULL; + tasklet_disable(&creq->creq_tasklet); return rc; + } creq->requested = true; - bnxt_qplib_ring_nq_db(&creq->creq_db.dbinfo, rcfw->res->cctx, true); + bnxt_qplib_ring_nq_db(&creq->creq_db.dbinfo, res->cctx, true); + atomic_inc(&rcfw->rcfw_intr_enabled); return 0; } -static int bnxt_qplib_map_cmdq_mbox(struct bnxt_qplib_rcfw *rcfw, bool is_vf) +static int bnxt_qplib_map_cmdq_mbox(struct bnxt_qplib_rcfw *rcfw) { struct bnxt_qplib_cmdq_mbox *mbox; resource_size_t bar_reg; struct pci_dev *pdev; - u16 prod_offt; - int rc = 0; pdev = rcfw->pdev; mbox = &rcfw->cmdq.cmdq_mbox; @@ -733,11 +1091,10 @@ static int bnxt_qplib_map_cmdq_mbox(struct bnxt_qplib_rcfw *rcfw, bool is_vf) return -ENOMEM; } - prod_offt = is_vf ? RCFW_VF_COMM_PROD_OFFSET : - RCFW_PF_COMM_PROD_OFFSET; - mbox->prod = (void __iomem *)(mbox->reg.bar_reg + prod_offt); + mbox->prod = (void __iomem *)(mbox->reg.bar_reg + + RCFW_PF_VF_COMM_PROD_OFFSET); mbox->db = (void __iomem *)(mbox->reg.bar_reg + RCFW_COMM_TRIG_OFFSET); - return rc; + return 0; } static int bnxt_qplib_map_creq_db(struct bnxt_qplib_rcfw *rcfw, u32 reg_offt) @@ -798,7 +1155,7 @@ static void bnxt_qplib_start_rcfw(struct bnxt_qplib_rcfw *rcfw) int bnxt_qplib_enable_rcfw_channel(struct bnxt_qplib_rcfw *rcfw, int msix_vector, - int cp_bar_reg_off, int virt_fn, + int cp_bar_reg_off, aeq_handler_t aeq_handler) { struct bnxt_qplib_cmdq_ctx *cmdq; @@ -818,7 +1175,7 @@ int bnxt_qplib_enable_rcfw_channel(struct bnxt_qplib_rcfw *rcfw, creq->stats.creq_func_event_processed = 0; creq->aeq_handler = aeq_handler; - rc = bnxt_qplib_map_cmdq_mbox(rcfw, virt_fn); + rc = bnxt_qplib_map_cmdq_mbox(rcfw); if (rc) return rc; @@ -834,6 +1191,7 @@ int bnxt_qplib_enable_rcfw_channel(struct bnxt_qplib_rcfw *rcfw, return rc; } + sema_init(&rcfw->rcfw_inflight, RCFW_CMD_NON_BLOCKING_SHADOW_QD); bnxt_qplib_start_rcfw(rcfw); return 0; diff --git a/drivers/infiniband/hw/bnxt_re/qplib_rcfw.h b/drivers/infiniband/hw/bnxt_re/qplib_rcfw.h index dd5651478bbb77be1c1f343c48265178853353ba..7b31bee3e000548042c93df33d595e08f028a19e 100644 --- a/drivers/infiniband/hw/bnxt_re/qplib_rcfw.h +++ b/drivers/infiniband/hw/bnxt_re/qplib_rcfw.h @@ -45,13 +45,13 @@ #define RCFW_COMM_PCI_BAR_REGION 0 #define RCFW_COMM_CONS_PCI_BAR_REGION 2 #define RCFW_COMM_BASE_OFFSET 0x600 -#define RCFW_PF_COMM_PROD_OFFSET 0xc -#define RCFW_VF_COMM_PROD_OFFSET 0xc +#define RCFW_PF_VF_COMM_PROD_OFFSET 0xc #define RCFW_COMM_TRIG_OFFSET 0x100 #define RCFW_COMM_SIZE 0x104 #define RCFW_DBR_PCI_BAR_REGION 2 #define RCFW_DBR_BASE_PAGE_SHIFT 12 +#define RCFW_FW_STALL_MAX_TIMEOUT 40 /* Cmdq contains a fix number of a 16-Byte slots */ struct bnxt_qplib_cmdqe { @@ -67,11 +67,12 @@ static inline void bnxt_qplib_rcfw_cmd_prep(struct cmdq_base *req, req->cmd_size = cmd_size; } +/* Shadow queue depth for non blocking command */ +#define RCFW_CMD_NON_BLOCKING_SHADOW_QD 64 #define RCFW_CMD_WAIT_TIME_MS 20000 /* 20 Seconds timeout */ /* CMDQ elements */ -#define BNXT_QPLIB_CMDQE_MAX_CNT_256 256 -#define BNXT_QPLIB_CMDQE_MAX_CNT_8192 8192 +#define BNXT_QPLIB_CMDQE_MAX_CNT 8192 #define BNXT_QPLIB_CMDQE_BYTES(depth) ((depth) * BNXT_QPLIB_CMDQE_UNITS) static inline u32 bnxt_qplib_cmdqe_npages(u32 depth) @@ -89,6 +90,26 @@ static inline u32 bnxt_qplib_cmdqe_page_size(u32 depth) return (bnxt_qplib_cmdqe_npages(depth) * PAGE_SIZE); } +/* Get the number of command units required for the req. The + * function returns correct value only if called before + * setting using bnxt_qplib_set_cmd_slots + */ +static inline u32 bnxt_qplib_get_cmd_slots(struct cmdq_base *req) +{ + u32 cmd_units = 0; + + if (HAS_TLV_HEADER(req)) { + struct roce_tlv *tlv_req = (struct roce_tlv *)req; + + cmd_units = tlv_req->total_size; + } else { + cmd_units = (req->cmd_size + BNXT_QPLIB_CMDQE_UNITS - 1) / + BNXT_QPLIB_CMDQE_UNITS; + } + + return cmd_units; +} + static inline u32 bnxt_qplib_set_cmd_slots(struct cmdq_base *req) { u32 cmd_byte = 0; @@ -106,11 +127,10 @@ static inline u32 bnxt_qplib_set_cmd_slots(struct cmdq_base *req) return cmd_byte; } -#define RCFW_MAX_COOKIE_VALUE 0x7FFF +#define RCFW_MAX_COOKIE_VALUE (BNXT_QPLIB_CMDQE_MAX_CNT - 1) #define RCFW_CMD_IS_BLOCKING 0x8000 -#define RCFW_BLOCKED_CMD_WAIT_COUNT 20000000UL /* 20 sec */ -#define HWRM_VERSION_RCFW_CMDQ_DEPTH_CHECK 0x1000900020011ULL +#define HWRM_VERSION_DEV_ATTR_MAX_DPI 0x1000A0000000DULL /* Crsq buf is 1024-Byte */ struct bnxt_qplib_crsbe { @@ -132,6 +152,12 @@ typedef int (*aeq_handler_t)(struct bnxt_qplib_rcfw *, void *, void *); struct bnxt_qplib_crsqe { struct creq_qp_event *resp; u32 req_size; + /* Free slots at the time of submission */ + u32 free_slots; + u8 opcode; + bool is_waiter_alive; + bool is_internal_cmd; + bool is_in_used; }; struct bnxt_qplib_rcfw_sbuf { @@ -149,7 +175,7 @@ struct bnxt_qplib_qp_node { #define FIRMWARE_INITIALIZED_FLAG (0) #define FIRMWARE_FIRST_FLAG (31) -#define FIRMWARE_TIMED_OUT (3) +#define FIRMWARE_STALL_DETECTED (3) #define ERR_DEVICE_DETACHED (4) struct bnxt_qplib_cmdq_mbox { @@ -163,7 +189,7 @@ struct bnxt_qplib_cmdq_ctx { struct bnxt_qplib_cmdq_mbox cmdq_mbox; wait_queue_head_t waitq; unsigned long flags; - unsigned long *cmdq_bitmap; + unsigned long last_seen; u32 seq_num; }; @@ -186,6 +212,7 @@ struct bnxt_qplib_creq_ctx { u16 ring_id; int msix_vec; bool requested; /*irq handler installed */ + char *irq_name; }; /* RCFW Communication Channels */ @@ -200,6 +227,11 @@ struct bnxt_qplib_rcfw { u64 oos_prev; u32 init_oos_stats; u32 cmdq_depth; + atomic_t rcfw_intr_enabled; + struct semaphore rcfw_inflight; + atomic_t timeout_send; + /* cached from chip cctx for quick reference in slow path */ + u16 max_timeout; }; struct bnxt_qplib_cmdqmsg { @@ -234,7 +266,7 @@ int bnxt_qplib_rcfw_start_irq(struct bnxt_qplib_rcfw *rcfw, int msix_vector, bool need_init); int bnxt_qplib_enable_rcfw_channel(struct bnxt_qplib_rcfw *rcfw, int msix_vector, - int cp_bar_reg_off, int virt_fn, + int cp_bar_reg_off, aeq_handler_t aeq_handler); struct bnxt_qplib_rcfw_sbuf *bnxt_qplib_rcfw_alloc_sbuf( diff --git a/drivers/infiniband/hw/bnxt_re/qplib_res.c b/drivers/infiniband/hw/bnxt_re/qplib_res.c index 81b0c5e879f9e857a77875dd104530eb4edaee91..5fd8f7c90bb06a8b734f568c1c24c06a70457282 100644 --- a/drivers/infiniband/hw/bnxt_re/qplib_res.c +++ b/drivers/infiniband/hw/bnxt_re/qplib_res.c @@ -696,44 +696,76 @@ static int bnxt_qplib_alloc_pd_tbl(struct bnxt_qplib_res *res, } /* DPIs */ -int bnxt_qplib_alloc_dpi(struct bnxt_qplib_dpi_tbl *dpit, - struct bnxt_qplib_dpi *dpi, - void *app) +int bnxt_qplib_alloc_dpi(struct bnxt_qplib_res *res, + struct bnxt_qplib_dpi *dpi, + void *app, u8 type) { + struct bnxt_qplib_dpi_tbl *dpit = &res->dpi_tbl; + struct bnxt_qplib_reg_desc *reg; u32 bit_num; + u64 umaddr; + + reg = &dpit->wcreg; + mutex_lock(&res->dpi_tbl_lock); bit_num = find_first_bit(dpit->tbl, dpit->max); - if (bit_num == dpit->max) + if (bit_num == dpit->max) { + mutex_unlock(&res->dpi_tbl_lock); return -ENOMEM; + } /* Found unused DPI */ clear_bit(bit_num, dpit->tbl); dpit->app_tbl[bit_num] = app; - dpi->dpi = bit_num; - dpi->dbr = dpit->dbr_bar_reg_iomem + (bit_num * PAGE_SIZE); - dpi->umdbr = dpit->unmapped_dbr + (bit_num * PAGE_SIZE); + dpi->bit = bit_num; + dpi->dpi = bit_num + (reg->offset - dpit->ucreg.offset) / PAGE_SIZE; + + umaddr = reg->bar_base + reg->offset + bit_num * PAGE_SIZE; + dpi->umdbr = umaddr; + + switch (type) { + case BNXT_QPLIB_DPI_TYPE_KERNEL: + /* privileged dbr was already mapped just initialize it. */ + dpi->umdbr = dpit->ucreg.bar_base + + dpit->ucreg.offset + bit_num * PAGE_SIZE; + dpi->dbr = dpit->priv_db; + dpi->dpi = dpi->bit; + break; + case BNXT_QPLIB_DPI_TYPE_WC: + dpi->dbr = ioremap_wc(umaddr, PAGE_SIZE); + break; + default: + dpi->dbr = ioremap(umaddr, PAGE_SIZE); + break; + } + dpi->type = type; + mutex_unlock(&res->dpi_tbl_lock); return 0; + } int bnxt_qplib_dealloc_dpi(struct bnxt_qplib_res *res, - struct bnxt_qplib_dpi_tbl *dpit, - struct bnxt_qplib_dpi *dpi) + struct bnxt_qplib_dpi *dpi) { - if (dpi->dpi >= dpit->max) { - dev_warn(&res->pdev->dev, "Invalid DPI? dpi = %d\n", dpi->dpi); - return -EINVAL; - } - if (test_and_set_bit(dpi->dpi, dpit->tbl)) { - dev_warn(&res->pdev->dev, "Freeing an unused DPI? dpi = %d\n", - dpi->dpi); + struct bnxt_qplib_dpi_tbl *dpit = &res->dpi_tbl; + + mutex_lock(&res->dpi_tbl_lock); + if (dpi->dpi && dpi->type != BNXT_QPLIB_DPI_TYPE_KERNEL) + pci_iounmap(res->pdev, dpi->dbr); + + if (test_and_set_bit(dpi->bit, dpit->tbl)) { + dev_warn(&res->pdev->dev, + "Freeing an unused DPI? dpi = %d, bit = %d\n", + dpi->dpi, dpi->bit); + mutex_unlock(&res->dpi_tbl_lock); return -EINVAL; } if (dpit->app_tbl) - dpit->app_tbl[dpi->dpi] = NULL; + dpit->app_tbl[dpi->bit] = NULL; memset(dpi, 0, sizeof(*dpi)); - + mutex_unlock(&res->dpi_tbl_lock); return 0; } @@ -742,52 +774,38 @@ static void bnxt_qplib_free_dpi_tbl(struct bnxt_qplib_res *res, { kfree(dpit->tbl); kfree(dpit->app_tbl); - if (dpit->dbr_bar_reg_iomem) - pci_iounmap(res->pdev, dpit->dbr_bar_reg_iomem); - memset(dpit, 0, sizeof(*dpit)); + dpit->tbl = NULL; + dpit->app_tbl = NULL; + dpit->max = 0; } -static int bnxt_qplib_alloc_dpi_tbl(struct bnxt_qplib_res *res, - struct bnxt_qplib_dpi_tbl *dpit, - u32 dbr_offset) +static int bnxt_qplib_alloc_dpi_tbl(struct bnxt_qplib_res *res, + struct bnxt_qplib_dev_attr *dev_attr) { - u32 dbr_bar_reg = RCFW_DBR_PCI_BAR_REGION; - resource_size_t bar_reg_base; - u32 dbr_len, bytes; - - if (dpit->dbr_bar_reg_iomem) { - dev_err(&res->pdev->dev, "DBR BAR region %d already mapped\n", - dbr_bar_reg); - return -EALREADY; - } - - bar_reg_base = pci_resource_start(res->pdev, dbr_bar_reg); - if (!bar_reg_base) { - dev_err(&res->pdev->dev, "BAR region %d resc start failed\n", - dbr_bar_reg); - return -ENOMEM; - } + struct bnxt_qplib_dpi_tbl *dpit; + struct bnxt_qplib_reg_desc *reg; + unsigned long bar_len; + u32 dbr_offset; + u32 bytes; - dbr_len = pci_resource_len(res->pdev, dbr_bar_reg) - dbr_offset; - if (!dbr_len || ((dbr_len & (PAGE_SIZE - 1)) != 0)) { - dev_err(&res->pdev->dev, "Invalid DBR length %d\n", dbr_len); - return -ENOMEM; - } + dpit = &res->dpi_tbl; + reg = &dpit->wcreg; - dpit->dbr_bar_reg_iomem = ioremap(bar_reg_base + dbr_offset, - dbr_len); - if (!dpit->dbr_bar_reg_iomem) { - dev_err(&res->pdev->dev, - "FP: DBR BAR region %d mapping failed\n", dbr_bar_reg); - return -ENOMEM; + if (!bnxt_qplib_is_chip_gen_p5(res->cctx)) { + /* Offest should come from L2 driver */ + dbr_offset = dev_attr->l2_db_size; + dpit->ucreg.offset = dbr_offset; + dpit->wcreg.offset = dbr_offset; } - dpit->unmapped_dbr = bar_reg_base + dbr_offset; - dpit->max = dbr_len / PAGE_SIZE; + bar_len = pci_resource_len(res->pdev, reg->bar_id); + dpit->max = (bar_len - reg->offset) / PAGE_SIZE; + if (dev_attr->max_dpi) + dpit->max = min_t(u32, dpit->max, dev_attr->max_dpi); - dpit->app_tbl = kcalloc(dpit->max, sizeof(void *), GFP_KERNEL); + dpit->app_tbl = kcalloc(dpit->max, sizeof(void *), GFP_KERNEL); if (!dpit->app_tbl) - goto unmap_io; + return -ENOMEM; bytes = dpit->max >> 3; if (!bytes) @@ -797,17 +815,14 @@ static int bnxt_qplib_alloc_dpi_tbl(struct bnxt_qplib_res *res, if (!dpit->tbl) { kfree(dpit->app_tbl); dpit->app_tbl = NULL; - goto unmap_io; + return -ENOMEM; } memset((u8 *)dpit->tbl, 0xFF, bytes); + dpit->priv_db = dpit->ucreg.bar_reg + dpit->ucreg.offset; return 0; -unmap_io: - pci_iounmap(res->pdev, dpit->dbr_bar_reg_iomem); - dpit->dbr_bar_reg_iomem = NULL; - return -ENOMEM; } /* Stats */ @@ -874,7 +889,7 @@ int bnxt_qplib_alloc_res(struct bnxt_qplib_res *res, struct pci_dev *pdev, if (rc) goto fail; - rc = bnxt_qplib_alloc_dpi_tbl(res, &res->dpi_tbl, dev_attr->l2_db_size); + rc = bnxt_qplib_alloc_dpi_tbl(res, dev_attr); if (rc) goto fail; @@ -884,6 +899,46 @@ int bnxt_qplib_alloc_res(struct bnxt_qplib_res *res, struct pci_dev *pdev, return rc; } +void bnxt_qplib_unmap_db_bar(struct bnxt_qplib_res *res) +{ + struct bnxt_qplib_reg_desc *reg; + + reg = &res->dpi_tbl.ucreg; + if (reg->bar_reg) + pci_iounmap(res->pdev, reg->bar_reg); + reg->bar_reg = NULL; + reg->bar_base = 0; + reg->len = 0; + reg->bar_id = 0; +} + +int bnxt_qplib_map_db_bar(struct bnxt_qplib_res *res) +{ + struct bnxt_qplib_reg_desc *ucreg; + struct bnxt_qplib_reg_desc *wcreg; + + wcreg = &res->dpi_tbl.wcreg; + wcreg->bar_id = RCFW_DBR_PCI_BAR_REGION; + wcreg->bar_base = pci_resource_start(res->pdev, wcreg->bar_id); + + ucreg = &res->dpi_tbl.ucreg; + ucreg->bar_id = RCFW_DBR_PCI_BAR_REGION; + ucreg->bar_base = pci_resource_start(res->pdev, ucreg->bar_id); + ucreg->len = ucreg->offset + PAGE_SIZE; + if (!ucreg->len || ((ucreg->len & (PAGE_SIZE - 1)) != 0)) { + dev_err(&res->pdev->dev, "QPLIB: invalid dbr length %d", + (int)ucreg->len); + return -EINVAL; + } + ucreg->bar_reg = ioremap(ucreg->bar_base, ucreg->len); + if (!ucreg->bar_reg) { + dev_err(&res->pdev->dev, "privileged dpi map failed!"); + return -ENOMEM; + } + + return 0; +} + int bnxt_qplib_determine_atomics(struct pci_dev *dev) { int comp; diff --git a/drivers/infiniband/hw/bnxt_re/qplib_res.h b/drivers/infiniband/hw/bnxt_re/qplib_res.h index 982e2c96dac2d19c50b711d82f637e2331e0a78b..d850a553821e398c474f1a89507313ca4e958394 100644 --- a/drivers/infiniband/hw/bnxt_re/qplib_res.h +++ b/drivers/infiniband/hw/bnxt_re/qplib_res.h @@ -47,7 +47,7 @@ extern const struct bnxt_qplib_gid bnxt_qplib_gid_zero; struct bnxt_qplib_drv_modes { u8 wqe_mode; - /* Other modes to follow here */ + bool db_push; }; struct bnxt_qplib_chip_ctx { @@ -55,9 +55,14 @@ struct bnxt_qplib_chip_ctx { u8 chip_rev; u8 chip_metal; u16 hw_stats_size; + u16 hwrm_cmd_max_timeout; struct bnxt_qplib_drv_modes modes; + u64 hwrm_intf_ver; }; +#define BNXT_QPLIB_DBR_PF_DB_OFFSET 0x10000 +#define BNXT_QPLIB_DBR_VF_DB_OFFSET 0x4000 + #define PTR_CNT_PER_PG (PAGE_SIZE / sizeof(void *)) #define PTR_MAX_IDX_PER_PG (PTR_CNT_PER_PG - 1) #define PTR_PG(x) (((x) & ~PTR_MAX_IDX_PER_PG) / PTR_CNT_PER_PG) @@ -109,6 +114,7 @@ enum bnxt_qplib_hwrm_pg_size { struct bnxt_qplib_reg_desc { u8 bar_id; resource_size_t bar_base; + unsigned long offset; void __iomem *bar_reg; size_t len; }; @@ -185,18 +191,27 @@ struct bnxt_qplib_sgid_tbl { u8 *vlan; }; +enum { + BNXT_QPLIB_DPI_TYPE_KERNEL = 0, + BNXT_QPLIB_DPI_TYPE_UC = 1, + BNXT_QPLIB_DPI_TYPE_WC = 2 +}; + struct bnxt_qplib_dpi { u32 dpi; + u32 bit; void __iomem *dbr; u64 umdbr; + u8 type; }; struct bnxt_qplib_dpi_tbl { void **app_tbl; unsigned long *tbl; u16 max; - void __iomem *dbr_bar_reg_iomem; - u64 unmapped_dbr; + struct bnxt_qplib_reg_desc ucreg; /* Hold entire DB bar. */ + struct bnxt_qplib_reg_desc wcreg; + void __iomem *priv_db; }; struct bnxt_qplib_stats { @@ -241,7 +256,6 @@ struct bnxt_qplib_ctx { struct bnxt_qplib_tqm_ctx tqm_ctx; struct bnxt_qplib_stats stats; struct bnxt_qplib_vf_res vf_res; - u64 hwrm_intf_ver; }; struct bnxt_qplib_res { @@ -253,6 +267,8 @@ struct bnxt_qplib_res { struct bnxt_qplib_pd_tbl pd_tbl; struct bnxt_qplib_sgid_tbl sgid_tbl; struct bnxt_qplib_dpi_tbl dpi_tbl; + /* To protect the dpi table bit map */ + struct mutex dpi_tbl_lock; bool prio; bool is_vf; }; @@ -344,11 +360,10 @@ int bnxt_qplib_alloc_pd(struct bnxt_qplib_pd_tbl *pd_tbl, int bnxt_qplib_dealloc_pd(struct bnxt_qplib_res *res, struct bnxt_qplib_pd_tbl *pd_tbl, struct bnxt_qplib_pd *pd); -int bnxt_qplib_alloc_dpi(struct bnxt_qplib_dpi_tbl *dpit, - struct bnxt_qplib_dpi *dpi, - void *app); +int bnxt_qplib_alloc_dpi(struct bnxt_qplib_res *res, + struct bnxt_qplib_dpi *dpi, + void *app, u8 type); int bnxt_qplib_dealloc_dpi(struct bnxt_qplib_res *res, - struct bnxt_qplib_dpi_tbl *dpi_tbl, struct bnxt_qplib_dpi *dpi); void bnxt_qplib_cleanup_res(struct bnxt_qplib_res *res); int bnxt_qplib_init_res(struct bnxt_qplib_res *res); @@ -361,6 +376,9 @@ void bnxt_qplib_free_ctx(struct bnxt_qplib_res *res, int bnxt_qplib_alloc_ctx(struct bnxt_qplib_res *res, struct bnxt_qplib_ctx *ctx, bool virt_fn, bool is_p5); +int bnxt_qplib_map_db_bar(struct bnxt_qplib_res *res); +void bnxt_qplib_unmap_db_bar(struct bnxt_qplib_res *res); + int bnxt_qplib_determine_atomics(struct pci_dev *dev); static inline void bnxt_qplib_hwq_incr_prod(struct bnxt_qplib_hwq *hwq, u32 cnt) diff --git a/drivers/infiniband/hw/bnxt_re/qplib_sp.c b/drivers/infiniband/hw/bnxt_re/qplib_sp.c index b967a17a44bebcc282547488eb9209781dda3450..ab45f9d4bb02fecfb448136875a6addf0286a12d 100644 --- a/drivers/infiniband/hw/bnxt_re/qplib_sp.c +++ b/drivers/infiniband/hw/bnxt_re/qplib_sp.c @@ -170,6 +170,9 @@ int bnxt_qplib_get_dev_attr(struct bnxt_qplib_rcfw *rcfw, attr->tqm_alloc_reqs[i * 4 + 3] = *(++tqm_alloc); } + if (rcfw->res->cctx->hwrm_intf_ver >= HWRM_VERSION_DEV_ATTR_MAX_DPI) + attr->max_dpi = le32_to_cpu(sb->max_dpi); + attr->is_atomic = bnxt_qplib_is_atomic_cap(rcfw); bail: bnxt_qplib_rcfw_free_sbuf(rcfw, sbuf); @@ -233,10 +236,6 @@ int bnxt_qplib_del_sgid(struct bnxt_qplib_sgid_tbl *sgid_tbl, struct bnxt_qplib_rcfw *rcfw = res->rcfw; int index; - if (!sgid_tbl) { - dev_err(&res->pdev->dev, "SGID table not allocated\n"); - return -EINVAL; - } /* Do we need a sgid_lock here? */ if (!sgid_tbl->active) { dev_err(&res->pdev->dev, "SGID table has no active entries\n"); @@ -297,10 +296,6 @@ int bnxt_qplib_add_sgid(struct bnxt_qplib_sgid_tbl *sgid_tbl, struct bnxt_qplib_rcfw *rcfw = res->rcfw; int i, free_idx; - if (!sgid_tbl) { - dev_err(&res->pdev->dev, "SGID table not allocated\n"); - return -EINVAL; - } /* Do we need a sgid_lock here? */ if (sgid_tbl->active == sgid_tbl->max) { dev_err(&res->pdev->dev, "SGID table is full\n"); @@ -468,13 +463,14 @@ int bnxt_qplib_create_ah(struct bnxt_qplib_res *res, struct bnxt_qplib_ah *ah, return 0; } -void bnxt_qplib_destroy_ah(struct bnxt_qplib_res *res, struct bnxt_qplib_ah *ah, - bool block) +int bnxt_qplib_destroy_ah(struct bnxt_qplib_res *res, struct bnxt_qplib_ah *ah, + bool block) { struct bnxt_qplib_rcfw *rcfw = res->rcfw; struct creq_destroy_ah_resp resp = {}; struct bnxt_qplib_cmdqmsg msg = {}; struct cmdq_destroy_ah req = {}; + int rc; /* Clean up the AH table in the device */ bnxt_qplib_rcfw_cmd_prep((struct cmdq_base *)&req, @@ -485,7 +481,8 @@ void bnxt_qplib_destroy_ah(struct bnxt_qplib_res *res, struct bnxt_qplib_ah *ah, bnxt_qplib_fill_cmdqmsg(&msg, &req, &resp, NULL, sizeof(req), sizeof(resp), block); - bnxt_qplib_rcfw_send_message(rcfw, &msg); + rc = bnxt_qplib_rcfw_send_message(rcfw, &msg); + return rc; } /* MRW */ diff --git a/drivers/infiniband/hw/bnxt_re/qplib_sp.h b/drivers/infiniband/hw/bnxt_re/qplib_sp.h index 5de874659cdfa3b3f2b9b51d50dbd92aa51edfde..264ef3cedc45b0e3e1b6847b03fc177e62a04505 100644 --- a/drivers/infiniband/hw/bnxt_re/qplib_sp.h +++ b/drivers/infiniband/hw/bnxt_re/qplib_sp.h @@ -72,6 +72,7 @@ struct bnxt_qplib_dev_attr { u8 tqm_alloc_reqs[MAX_TQM_ALLOC_REQ]; bool is_atomic; u16 dev_cap_flags; + u32 max_dpi; }; struct bnxt_qplib_pd { @@ -327,8 +328,8 @@ int bnxt_qplib_set_func_resources(struct bnxt_qplib_res *res, struct bnxt_qplib_ctx *ctx); int bnxt_qplib_create_ah(struct bnxt_qplib_res *res, struct bnxt_qplib_ah *ah, bool block); -void bnxt_qplib_destroy_ah(struct bnxt_qplib_res *res, struct bnxt_qplib_ah *ah, - bool block); +int bnxt_qplib_destroy_ah(struct bnxt_qplib_res *res, struct bnxt_qplib_ah *ah, + bool block); int bnxt_qplib_alloc_mrw(struct bnxt_qplib_res *res, struct bnxt_qplib_mrw *mrw); int bnxt_qplib_dereg_mrw(struct bnxt_qplib_res *res, struct bnxt_qplib_mrw *mrw, diff --git a/drivers/infiniband/hw/erdma/erdma.h b/drivers/infiniband/hw/erdma/erdma.h index e819e403249034956276ce2da69b7f83a663a7c3..f190111840e97f83cdba469e4c7fe48c5a2b6555 100644 --- a/drivers/infiniband/hw/erdma/erdma.h +++ b/drivers/infiniband/hw/erdma/erdma.h @@ -128,13 +128,8 @@ struct erdma_devattr { int numa_node; enum erdma_cc_alg cc; - u32 grp_num; u32 irq_num; - bool disable_dwqe; - u16 dwqe_pages; - u16 dwqe_entries; - u32 max_qp; u32 max_send_wr; u32 max_recv_wr; @@ -215,15 +210,6 @@ struct erdma_dev { u32 next_alloc_qpn; u32 next_alloc_cqn; - spinlock_t db_bitmap_lock; - /* We provide max 64 uContexts that each has one SQ doorbell Page. */ - DECLARE_BITMAP(sdb_page, ERDMA_DWQE_TYPE0_CNT); - /* - * We provide max 496 uContexts that each has one SQ normal Db, - * and one directWQE db. - */ - DECLARE_BITMAP(sdb_entry, ERDMA_DWQE_TYPE1_CNT); - atomic_t num_ctx; struct list_head cep_list; }; @@ -268,6 +254,8 @@ static inline u32 erdma_reg_read32_filed(struct erdma_dev *dev, u32 reg, return FIELD_GET(filed_mask, val); } +#define ERDMA_GET(val, name) FIELD_GET(ERDMA_CMD_##name##_MASK, val) + int erdma_cmdq_init(struct erdma_dev *dev); void erdma_finish_cmdq_init(struct erdma_dev *dev); void erdma_cmdq_destroy(struct erdma_dev *dev); diff --git a/drivers/infiniband/hw/erdma/erdma_hw.h b/drivers/infiniband/hw/erdma/erdma_hw.h index 76ce2856be28a68aae3c440fc564ce64301cab55..a882b57aa118585351215678d7bc4e26f5d06f07 100644 --- a/drivers/infiniband/hw/erdma/erdma_hw.h +++ b/drivers/infiniband/hw/erdma/erdma_hw.h @@ -82,19 +82,6 @@ #define ERDMA_BAR_CQDB_SPACE_OFFSET \ (ERDMA_BAR_RQDB_SPACE_OFFSET + ERDMA_BAR_RQDB_SPACE_SIZE) -/* Doorbell page resources related. */ -/* - * Max # of parallelly issued directSQE is 3072 per device, - * hardware organizes this into 24 group, per group has 128 credits. - */ -#define ERDMA_DWQE_MAX_GRP_CNT 24 -#define ERDMA_DWQE_NUM_PER_GRP 128 - -#define ERDMA_DWQE_TYPE0_CNT 64 -#define ERDMA_DWQE_TYPE1_CNT 496 -/* type1 DB contains 2 DBs, takes 256Byte. */ -#define ERDMA_DWQE_TYPE1_CNT_PER_PAGE 16 - #define ERDMA_SDB_SHARED_PAGE_INDEX 95 /* Doorbell related. */ @@ -134,7 +121,7 @@ /* CMDQ related. */ #define ERDMA_CMDQ_MAX_OUTSTANDING 128 -#define ERDMA_CMDQ_SQE_SIZE 64 +#define ERDMA_CMDQ_SQE_SIZE 128 /* cmdq sub module definition. */ enum CMDQ_WQE_SUB_MOD { @@ -159,6 +146,9 @@ enum CMDQ_COMMON_OPCODE { CMDQ_OPCODE_DESTROY_EQ = 1, CMDQ_OPCODE_QUERY_FW_INFO = 2, CMDQ_OPCODE_CONF_MTU = 3, + CMDQ_OPCODE_CONF_DEVICE = 5, + CMDQ_OPCODE_ALLOC_DB = 8, + CMDQ_OPCODE_FREE_DB = 9, }; /* cmdq-SQE HDR */ @@ -196,11 +186,41 @@ struct erdma_cmdq_destroy_eq_req { u8 qtype; }; +/* config device cfg */ +#define ERDMA_CMD_CONFIG_DEVICE_PS_EN_MASK BIT(31) +#define ERDMA_CMD_CONFIG_DEVICE_PGSHIFT_MASK GENMASK(4, 0) + +struct erdma_cmdq_config_device_req { + u64 hdr; + u32 cfg; + u32 rsvd[5]; +}; + struct erdma_cmdq_config_mtu_req { u64 hdr; u32 mtu; }; +/* ext db requests(alloc and free) cfg */ +#define ERDMA_CMD_EXT_DB_CQ_EN_MASK BIT(2) +#define ERDMA_CMD_EXT_DB_RQ_EN_MASK BIT(1) +#define ERDMA_CMD_EXT_DB_SQ_EN_MASK BIT(0) + +struct erdma_cmdq_ext_db_req { + u64 hdr; + u32 cfg; + u16 rdb_off; + u16 sdb_off; + u16 rsvd0; + u16 cdb_off; + u32 rsvd1[3]; +}; + +/* alloc db response qword 0 definition */ +#define ERDMA_CMD_ALLOC_DB_RESP_RDB_MASK GENMASK_ULL(63, 48) +#define ERDMA_CMD_ALLOC_DB_RESP_CDB_MASK GENMASK_ULL(47, 32) +#define ERDMA_CMD_ALLOC_DB_RESP_SDB_MASK GENMASK_ULL(15, 0) + /* create_cq cfg0 */ #define ERDMA_CMD_CREATE_CQ_DEPTH_MASK GENMASK(31, 24) #define ERDMA_CMD_CREATE_CQ_PAGESIZE_MASK GENMASK(23, 20) @@ -209,8 +229,12 @@ struct erdma_cmdq_config_mtu_req { /* create_cq cfg1 */ #define ERDMA_CMD_CREATE_CQ_MTT_CNT_MASK GENMASK(31, 16) #define ERDMA_CMD_CREATE_CQ_MTT_TYPE_MASK BIT(15) +#define ERDMA_CMD_CREATE_CQ_MTT_DB_CFG_MASK BIT(11) #define ERDMA_CMD_CREATE_CQ_EQN_MASK GENMASK(9, 0) +/* create_cq cfg2 */ +#define ERDMA_CMD_CREATE_CQ_DB_CFG_MASK GENMASK(15, 0) + struct erdma_cmdq_create_cq_req { u64 hdr; u32 cfg0; @@ -219,6 +243,7 @@ struct erdma_cmdq_create_cq_req { u32 cfg1; u64 cq_db_info_addr; u32 first_page_offset; + u32 cfg2; }; /* regmr/deregmr cfg0 */ @@ -278,6 +303,7 @@ struct erdma_cmdq_modify_qp_req { /* create qp cqn_mtt_cfg */ #define ERDMA_CMD_CREATE_QP_PAGE_SIZE_MASK GENMASK(31, 28) +#define ERDMA_CMD_CREATE_QP_DB_CFG_MASK BIT(25) #define ERDMA_CMD_CREATE_QP_CQN_MASK GENMASK(23, 0) /* create qp mtt_cfg */ @@ -285,6 +311,10 @@ struct erdma_cmdq_modify_qp_req { #define ERDMA_CMD_CREATE_QP_MTT_CNT_MASK GENMASK(11, 1) #define ERDMA_CMD_CREATE_QP_MTT_TYPE_MASK BIT(0) +/* create qp db cfg */ +#define ERDMA_CMD_CREATE_QP_SQDB_CFG_MASK GENMASK(31, 16) +#define ERDMA_CMD_CREATE_QP_RQDB_CFG_MASK GENMASK(15, 0) + #define ERDMA_CMDQ_CREATE_QP_RESP_COOKIE_MASK GENMASK_ULL(31, 0) struct erdma_cmdq_create_qp_req { @@ -299,6 +329,11 @@ struct erdma_cmdq_create_qp_req { u32 rq_mtt_cfg; u64 sq_db_info_dma_addr; u64 rq_db_info_dma_addr; + + u64 sq_mtt_entry[3]; + u64 rq_mtt_entry[3]; + + u32 db_cfg; }; struct erdma_cmdq_destroy_qp_req { @@ -329,6 +364,7 @@ struct erdma_cmdq_reflush_req { enum { ERDMA_DEV_CAP_FLAGS_ATOMIC = 1 << 7, + ERDMA_DEV_CAP_FLAGS_EXTEND_DB = 1 << 3, }; #define ERDMA_CMD_INFO0_FW_VER_MASK GENMASK_ULL(31, 0) diff --git a/drivers/infiniband/hw/erdma/erdma_main.c b/drivers/infiniband/hw/erdma/erdma_main.c index 7c74abeee864cc39758c86b2e2b956a5c08adb6f..0880c79a978c2873abcf6835559a457eeb7278a0 100644 --- a/drivers/infiniband/hw/erdma/erdma_main.c +++ b/drivers/infiniband/hw/erdma/erdma_main.c @@ -130,33 +130,6 @@ static irqreturn_t erdma_comm_irq_handler(int irq, void *data) return IRQ_HANDLED; } -static void erdma_dwqe_resource_init(struct erdma_dev *dev) -{ - int total_pages, type0, type1; - - dev->attrs.grp_num = erdma_reg_read32(dev, ERDMA_REGS_GRP_NUM_REG); - - if (dev->attrs.grp_num < 4) - dev->attrs.disable_dwqe = true; - else - dev->attrs.disable_dwqe = false; - - /* One page contains 4 goups. */ - total_pages = dev->attrs.grp_num * 4; - - if (dev->attrs.grp_num >= ERDMA_DWQE_MAX_GRP_CNT) { - dev->attrs.grp_num = ERDMA_DWQE_MAX_GRP_CNT; - type0 = ERDMA_DWQE_TYPE0_CNT; - type1 = ERDMA_DWQE_TYPE1_CNT / ERDMA_DWQE_TYPE1_CNT_PER_PAGE; - } else { - type1 = total_pages / 3; - type0 = total_pages - type1 - 1; - } - - dev->attrs.dwqe_pages = type0; - dev->attrs.dwqe_entries = type1 * ERDMA_DWQE_TYPE1_CNT_PER_PAGE; -} - static int erdma_request_vectors(struct erdma_dev *dev) { int expect_irq_num = min(num_possible_cpus() + 1, ERDMA_NUM_MSIX_VEC); @@ -199,8 +172,6 @@ static int erdma_device_init(struct erdma_dev *dev, struct pci_dev *pdev) { int ret; - erdma_dwqe_resource_init(dev); - ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(ERDMA_PCI_WIDTH)); if (ret) @@ -426,6 +397,22 @@ static int erdma_dev_attrs_init(struct erdma_dev *dev) return err; } +static int erdma_device_config(struct erdma_dev *dev) +{ + struct erdma_cmdq_config_device_req req = {}; + + if (!(dev->attrs.cap_flags & ERDMA_DEV_CAP_FLAGS_EXTEND_DB)) + return 0; + + erdma_cmdq_build_reqhdr(&req.hdr, CMDQ_SUBMOD_COMMON, + CMDQ_OPCODE_CONF_DEVICE); + + req.cfg = FIELD_PREP(ERDMA_CMD_CONFIG_DEVICE_PGSHIFT_MASK, PAGE_SHIFT) | + FIELD_PREP(ERDMA_CMD_CONFIG_DEVICE_PS_EN_MASK, 1); + + return erdma_post_cmd_wait(&dev->cmdq, &req, sizeof(req), NULL, NULL); +} + static int erdma_res_cb_init(struct erdma_dev *dev) { int i, j; @@ -512,6 +499,10 @@ static int erdma_ib_device_add(struct pci_dev *pdev) if (ret) return ret; + ret = erdma_device_config(dev); + if (ret) + return ret; + ibdev->node_type = RDMA_NODE_RNIC; memcpy(ibdev->node_desc, ERDMA_NODE_DESC, sizeof(ERDMA_NODE_DESC)); @@ -537,10 +528,6 @@ static int erdma_ib_device_add(struct pci_dev *pdev) if (ret) return ret; - spin_lock_init(&dev->db_bitmap_lock); - bitmap_zero(dev->sdb_page, ERDMA_DWQE_TYPE0_CNT); - bitmap_zero(dev->sdb_entry, ERDMA_DWQE_TYPE1_CNT); - atomic_set(&dev->num_ctx, 0); mac = erdma_reg_read32(dev, ERDMA_REGS_NETDEV_MAC_L_REG); diff --git a/drivers/infiniband/hw/erdma/erdma_verbs.c b/drivers/infiniband/hw/erdma/erdma_verbs.c index 83e1b0d55977129a559ba33e2f43a6c3316417c7..517676fbb8b111283736fd09b95c16128e6b3450 100644 --- a/drivers/infiniband/hw/erdma/erdma_verbs.c +++ b/drivers/infiniband/hw/erdma/erdma_verbs.c @@ -19,10 +19,11 @@ #include "erdma_cm.h" #include "erdma_verbs.h" -static int create_qp_cmd(struct erdma_dev *dev, struct erdma_qp *qp) +static int create_qp_cmd(struct erdma_ucontext *uctx, struct erdma_qp *qp) { - struct erdma_cmdq_create_qp_req req; + struct erdma_dev *dev = to_edev(qp->ibqp.device); struct erdma_pd *pd = to_epd(qp->ibqp.pd); + struct erdma_cmdq_create_qp_req req; struct erdma_uqp *user_qp; u64 resp0, resp1; int err; @@ -93,6 +94,16 @@ static int create_qp_cmd(struct erdma_dev *dev, struct erdma_qp *qp) req.sq_db_info_dma_addr = user_qp->sq_db_info_dma_addr; req.rq_db_info_dma_addr = user_qp->rq_db_info_dma_addr; + + if (uctx->ext_db.enable) { + req.sq_cqn_mtt_cfg |= + FIELD_PREP(ERDMA_CMD_CREATE_QP_DB_CFG_MASK, 1); + req.db_cfg = + FIELD_PREP(ERDMA_CMD_CREATE_QP_SQDB_CFG_MASK, + uctx->ext_db.sdb_off) | + FIELD_PREP(ERDMA_CMD_CREATE_QP_RQDB_CFG_MASK, + uctx->ext_db.rdb_off); + } } err = erdma_post_cmd_wait(&dev->cmdq, &req, sizeof(req), &resp0, @@ -146,11 +157,12 @@ static int regmr_cmd(struct erdma_dev *dev, struct erdma_mr *mr) return erdma_post_cmd_wait(&dev->cmdq, &req, sizeof(req), NULL, NULL); } -static int create_cq_cmd(struct erdma_dev *dev, struct erdma_cq *cq) +static int create_cq_cmd(struct erdma_ucontext *uctx, struct erdma_cq *cq) { + struct erdma_dev *dev = to_edev(cq->ibcq.device); struct erdma_cmdq_create_cq_req req; - u32 page_size; struct erdma_mem *mtt; + u32 page_size; erdma_cmdq_build_reqhdr(&req.hdr, CMDQ_SUBMOD_RDMA, CMDQ_OPCODE_CREATE_CQ); @@ -192,6 +204,13 @@ static int create_cq_cmd(struct erdma_dev *dev, struct erdma_cq *cq) req.first_page_offset = mtt->page_offset; req.cq_db_info_addr = cq->user_cq.db_info_dma_addr; + + if (uctx->ext_db.enable) { + req.cfg1 |= FIELD_PREP( + ERDMA_CMD_CREATE_CQ_MTT_DB_CFG_MASK, 1); + req.cfg2 = FIELD_PREP(ERDMA_CMD_CREATE_CQ_DB_CFG_MASK, + uctx->ext_db.cdb_off); + } } return erdma_post_cmd_wait(&dev->cmdq, &req, sizeof(req), NULL, NULL); @@ -753,7 +772,7 @@ int erdma_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs, qp->attrs.state = ERDMA_QP_STATE_IDLE; INIT_DELAYED_WORK(&qp->reflush_dwork, erdma_flush_worker); - ret = create_qp_cmd(dev, qp); + ret = create_qp_cmd(uctx, qp); if (ret) goto err_out_cmd; @@ -1130,62 +1149,73 @@ void erdma_mmap_free(struct rdma_user_mmap_entry *rdma_entry) kfree(entry); } -#define ERDMA_SDB_PAGE 0 -#define ERDMA_SDB_ENTRY 1 -#define ERDMA_SDB_SHARED 2 - -static void alloc_db_resources(struct erdma_dev *dev, - struct erdma_ucontext *ctx) +static int alloc_db_resources(struct erdma_dev *dev, struct erdma_ucontext *ctx, + bool ext_db_en) { - u32 bitmap_idx; - struct erdma_devattr *attrs = &dev->attrs; - - if (attrs->disable_dwqe) - goto alloc_normal_db; - - /* Try to alloc independent SDB page. */ - spin_lock(&dev->db_bitmap_lock); - bitmap_idx = find_first_zero_bit(dev->sdb_page, attrs->dwqe_pages); - if (bitmap_idx != attrs->dwqe_pages) { - set_bit(bitmap_idx, dev->sdb_page); - spin_unlock(&dev->db_bitmap_lock); - - ctx->sdb_type = ERDMA_SDB_PAGE; - ctx->sdb_idx = bitmap_idx; - ctx->sdb_page_idx = bitmap_idx; - ctx->sdb = dev->func_bar_addr + ERDMA_BAR_SQDB_SPACE_OFFSET + - (bitmap_idx << PAGE_SHIFT); - ctx->sdb_page_off = 0; + struct erdma_cmdq_ext_db_req req = {}; + u64 val0, val1; + int ret; - return; + /* + * CAP_SYS_RAWIO is required if hardware does not support extend + * doorbell mechanism. + */ + if (!ext_db_en && !capable(CAP_SYS_RAWIO)) + return -EPERM; + + if (!ext_db_en) { + ctx->sdb = dev->func_bar_addr + ERDMA_BAR_SQDB_SPACE_OFFSET; + ctx->rdb = dev->func_bar_addr + ERDMA_BAR_RQDB_SPACE_OFFSET; + ctx->cdb = dev->func_bar_addr + ERDMA_BAR_CQDB_SPACE_OFFSET; + return 0; } - bitmap_idx = find_first_zero_bit(dev->sdb_entry, attrs->dwqe_entries); - if (bitmap_idx != attrs->dwqe_entries) { - set_bit(bitmap_idx, dev->sdb_entry); - spin_unlock(&dev->db_bitmap_lock); + erdma_cmdq_build_reqhdr(&req.hdr, CMDQ_SUBMOD_COMMON, + CMDQ_OPCODE_ALLOC_DB); + + req.cfg = FIELD_PREP(ERDMA_CMD_EXT_DB_CQ_EN_MASK, 1) | + FIELD_PREP(ERDMA_CMD_EXT_DB_RQ_EN_MASK, 1) | + FIELD_PREP(ERDMA_CMD_EXT_DB_SQ_EN_MASK, 1); + + ret = erdma_post_cmd_wait(&dev->cmdq, &req, sizeof(req), &val0, &val1); + if (ret) + return ret; - ctx->sdb_type = ERDMA_SDB_ENTRY; - ctx->sdb_idx = bitmap_idx; - ctx->sdb_page_idx = attrs->dwqe_pages + - bitmap_idx / ERDMA_DWQE_TYPE1_CNT_PER_PAGE; - ctx->sdb_page_off = bitmap_idx % ERDMA_DWQE_TYPE1_CNT_PER_PAGE; + ctx->ext_db.enable = true; + ctx->ext_db.sdb_off = ERDMA_GET(val0, ALLOC_DB_RESP_SDB); + ctx->ext_db.rdb_off = ERDMA_GET(val0, ALLOC_DB_RESP_RDB); + ctx->ext_db.cdb_off = ERDMA_GET(val0, ALLOC_DB_RESP_CDB); - ctx->sdb = dev->func_bar_addr + ERDMA_BAR_SQDB_SPACE_OFFSET + - (ctx->sdb_page_idx << PAGE_SHIFT); + ctx->sdb = dev->func_bar_addr + (ctx->ext_db.sdb_off << PAGE_SHIFT); + ctx->cdb = dev->func_bar_addr + (ctx->ext_db.rdb_off << PAGE_SHIFT); + ctx->rdb = dev->func_bar_addr + (ctx->ext_db.cdb_off << PAGE_SHIFT); + + return 0; +} +static void free_db_resources(struct erdma_dev *dev, struct erdma_ucontext *ctx) +{ + struct erdma_cmdq_ext_db_req req = {}; + int ret; + + if (!ctx->ext_db.enable) return; - } - spin_unlock(&dev->db_bitmap_lock); + erdma_cmdq_build_reqhdr(&req.hdr, CMDQ_SUBMOD_COMMON, + CMDQ_OPCODE_FREE_DB); + + req.cfg = FIELD_PREP(ERDMA_CMD_EXT_DB_CQ_EN_MASK, 1) | + FIELD_PREP(ERDMA_CMD_EXT_DB_RQ_EN_MASK, 1) | + FIELD_PREP(ERDMA_CMD_EXT_DB_SQ_EN_MASK, 1); -alloc_normal_db: - ctx->sdb_type = ERDMA_SDB_SHARED; - ctx->sdb_idx = 0; - ctx->sdb_page_idx = ERDMA_SDB_SHARED_PAGE_INDEX; - ctx->sdb_page_off = 0; + req.sdb_off = ctx->ext_db.sdb_off; + req.rdb_off = ctx->ext_db.rdb_off; + req.cdb_off = ctx->ext_db.cdb_off; - ctx->sdb = dev->func_bar_addr + (ctx->sdb_page_idx << PAGE_SHIFT); + ret = erdma_post_cmd_wait(&dev->cmdq, &req, sizeof(req), NULL, NULL); + if (ret) + ibdev_err_ratelimited(&dev->ibdev, + "free db resources failed %d", ret); } static void erdma_uctx_user_mmap_entries_remove(struct erdma_ucontext *uctx) @@ -1207,71 +1237,67 @@ int erdma_alloc_ucontext(struct ib_ucontext *ibctx, struct ib_udata *udata) goto err_out; } - INIT_LIST_HEAD(&ctx->dbrecords_page_list); - mutex_init(&ctx->dbrecords_page_mutex); - - alloc_db_resources(dev, ctx); - - ctx->rdb = dev->func_bar_addr + ERDMA_BAR_RQDB_SPACE_OFFSET; - ctx->cdb = dev->func_bar_addr + ERDMA_BAR_CQDB_SPACE_OFFSET; - if (udata->outlen < sizeof(uresp)) { ret = -EINVAL; goto err_out; } + INIT_LIST_HEAD(&ctx->dbrecords_page_list); + mutex_init(&ctx->dbrecords_page_mutex); + + ret = alloc_db_resources(dev, ctx, + !!(dev->attrs.cap_flags & + ERDMA_DEV_CAP_FLAGS_EXTEND_DB)); + if (ret) + goto err_out; + ctx->sq_db_mmap_entry = erdma_user_mmap_entry_insert( ctx, (void *)ctx->sdb, PAGE_SIZE, ERDMA_MMAP_IO_NC, &uresp.sdb); if (!ctx->sq_db_mmap_entry) { ret = -ENOMEM; - goto err_out; + goto err_free_ext_db; } ctx->rq_db_mmap_entry = erdma_user_mmap_entry_insert( ctx, (void *)ctx->rdb, PAGE_SIZE, ERDMA_MMAP_IO_NC, &uresp.rdb); if (!ctx->rq_db_mmap_entry) { ret = -EINVAL; - goto err_out; + goto err_put_mmap_entries; } ctx->cq_db_mmap_entry = erdma_user_mmap_entry_insert( ctx, (void *)ctx->cdb, PAGE_SIZE, ERDMA_MMAP_IO_NC, &uresp.cdb); if (!ctx->cq_db_mmap_entry) { ret = -EINVAL; - goto err_out; + goto err_put_mmap_entries; } uresp.dev_id = dev->pdev->device; - uresp.sdb_type = ctx->sdb_type; - uresp.sdb_offset = ctx->sdb_page_off; ret = ib_copy_to_udata(udata, &uresp, sizeof(uresp)); if (ret) - goto err_out; + goto err_put_mmap_entries; return 0; -err_out: +err_put_mmap_entries: erdma_uctx_user_mmap_entries_remove(ctx); + +err_free_ext_db: + free_db_resources(dev, ctx); + +err_out: atomic_dec(&dev->num_ctx); return ret; } void erdma_dealloc_ucontext(struct ib_ucontext *ibctx) { - struct erdma_ucontext *ctx = to_ectx(ibctx); struct erdma_dev *dev = to_edev(ibctx->device); - - spin_lock(&dev->db_bitmap_lock); - if (ctx->sdb_type == ERDMA_SDB_PAGE) - clear_bit(ctx->sdb_idx, dev->sdb_page); - else if (ctx->sdb_type == ERDMA_SDB_ENTRY) - clear_bit(ctx->sdb_idx, dev->sdb_entry); + struct erdma_ucontext *ctx = to_ectx(ibctx); erdma_uctx_user_mmap_entries_remove(ctx); - - spin_unlock(&dev->db_bitmap_lock); - + free_db_resources(dev, ctx); atomic_dec(&dev->num_ctx); } @@ -1438,7 +1464,7 @@ int erdma_create_cq(struct ib_cq *ibcq, const struct ib_cq_init_attr *attr, goto err_out_xa; } - ret = create_cq_cmd(dev, cq); + ret = create_cq_cmd(ctx, cq); if (ret) goto err_free_res; diff --git a/drivers/infiniband/hw/erdma/erdma_verbs.h b/drivers/infiniband/hw/erdma/erdma_verbs.h index 131cf5f409822cb50daa57a8a24b17d4136dd393..429fc3063f980715e2a1ed9b842f2d565c748cd3 100644 --- a/drivers/infiniband/hw/erdma/erdma_verbs.h +++ b/drivers/infiniband/hw/erdma/erdma_verbs.h @@ -31,13 +31,18 @@ struct erdma_user_mmap_entry { u8 mmap_flag; }; +struct erdma_ext_db_info { + bool enable; + u16 sdb_off; + u16 rdb_off; + u16 cdb_off; +}; + struct erdma_ucontext { struct ib_ucontext ibucontext; - u32 sdb_type; - u32 sdb_idx; - u32 sdb_page_idx; - u32 sdb_page_off; + struct erdma_ext_db_info ext_db; + u64 sdb; u64 rdb; u64 cdb; diff --git a/drivers/infiniband/hw/hfi1/ipoib_tx.c b/drivers/infiniband/hw/hfi1/ipoib_tx.c index 8973a081d641e6d21cea6b88d0f57b8efe69307f..e7d831330278d6a49cc8ace98c984630575d7c92 100644 --- a/drivers/infiniband/hw/hfi1/ipoib_tx.c +++ b/drivers/infiniband/hw/hfi1/ipoib_tx.c @@ -215,11 +215,11 @@ static int hfi1_ipoib_build_ulp_payload(struct ipoib_txreq *tx, const skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; ret = sdma_txadd_page(dd, - NULL, txreq, skb_frag_page(frag), frag->bv_offset, - skb_frag_size(frag)); + skb_frag_size(frag), + NULL, NULL, NULL); if (unlikely(ret)) break; } diff --git a/drivers/infiniband/hw/hfi1/mmu_rb.c b/drivers/infiniband/hw/hfi1/mmu_rb.c index 1cea8b0c78e0f038bfa62b4d3868268ef5f4b843..7a51f7d73b61170bb8f8b580230b7ac80baaf18f 100644 --- a/drivers/infiniband/hw/hfi1/mmu_rb.c +++ b/drivers/infiniband/hw/hfi1/mmu_rb.c @@ -19,8 +19,7 @@ static int mmu_notifier_range_start(struct mmu_notifier *, const struct mmu_notifier_range *); static struct mmu_rb_node *__mmu_rb_search(struct mmu_rb_handler *, unsigned long, unsigned long); -static void do_remove(struct mmu_rb_handler *handler, - struct list_head *del_list); +static void release_immediate(struct kref *refcount); static void handle_remove(struct work_struct *work); static const struct mmu_notifier_ops mn_opts = { @@ -106,7 +105,11 @@ void hfi1_mmu_rb_unregister(struct mmu_rb_handler *handler) } spin_unlock_irqrestore(&handler->lock, flags); - do_remove(handler, &del_list); + while (!list_empty(&del_list)) { + rbnode = list_first_entry(&del_list, struct mmu_rb_node, list); + list_del(&rbnode->list); + kref_put(&rbnode->refcount, release_immediate); + } /* Now the mm may be freed. */ mmdrop(handler->mn.mm); @@ -121,7 +124,7 @@ int hfi1_mmu_rb_insert(struct mmu_rb_handler *handler, unsigned long flags; int ret = 0; - trace_hfi1_mmu_rb_insert(mnode->addr, mnode->len); + trace_hfi1_mmu_rb_insert(mnode); if (current->mm != handler->mn.mm) return -EPERM; @@ -134,12 +137,6 @@ int hfi1_mmu_rb_insert(struct mmu_rb_handler *handler, } __mmu_int_rb_insert(mnode, &handler->root); list_add_tail(&mnode->list, &handler->lru_list); - - ret = handler->ops->insert(handler->ops_arg, mnode); - if (ret) { - __mmu_int_rb_remove(mnode, &handler->root); - list_del(&mnode->list); /* remove from LRU list */ - } mnode->handler = handler; unlock: spin_unlock_irqrestore(&handler->lock, flags); @@ -183,6 +180,49 @@ static struct mmu_rb_node *__mmu_rb_search(struct mmu_rb_handler *handler, return node; } +/* + * Must NOT call while holding mnode->handler->lock. + * mnode->handler->ops->remove() may sleep and mnode->handler->lock is a + * spinlock. + */ +static void release_immediate(struct kref *refcount) +{ + struct mmu_rb_node *mnode = + container_of(refcount, struct mmu_rb_node, refcount); + trace_hfi1_mmu_release_node(mnode); + mnode->handler->ops->remove(mnode->handler->ops_arg, mnode); +} + +/* Caller must hold mnode->handler->lock */ +static void release_nolock(struct kref *refcount) +{ + struct mmu_rb_node *mnode = + container_of(refcount, struct mmu_rb_node, refcount); + list_move(&mnode->list, &mnode->handler->del_list); + queue_work(mnode->handler->wq, &mnode->handler->del_work); +} + +/* + * struct mmu_rb_node->refcount kref_put() callback. + * Adds mmu_rb_node to mmu_rb_node->handler->del_list and queues + * handler->del_work on handler->wq. + * Does not remove mmu_rb_node from handler->lru_list or handler->rb_root. + * Acquires mmu_rb_node->handler->lock; do not call while already holding + * handler->lock. + */ +void hfi1_mmu_rb_release(struct kref *refcount) +{ + struct mmu_rb_node *mnode = + container_of(refcount, struct mmu_rb_node, refcount); + struct mmu_rb_handler *handler = mnode->handler; + unsigned long flags; + + spin_lock_irqsave(&handler->lock, flags); + list_move(&mnode->list, &mnode->handler->del_list); + spin_unlock_irqrestore(&handler->lock, flags); + queue_work(handler->wq, &handler->del_work); +} + void hfi1_mmu_rb_evict(struct mmu_rb_handler *handler, void *evict_arg) { struct mmu_rb_node *rbnode, *ptr; @@ -197,6 +237,10 @@ void hfi1_mmu_rb_evict(struct mmu_rb_handler *handler, void *evict_arg) spin_lock_irqsave(&handler->lock, flags); list_for_each_entry_safe(rbnode, ptr, &handler->lru_list, list) { + /* refcount == 1 implies mmu_rb_handler has only rbnode ref */ + if (kref_read(&rbnode->refcount) > 1) + continue; + if (handler->ops->evict(handler->ops_arg, rbnode, evict_arg, &stop)) { __mmu_int_rb_remove(rbnode, &handler->root); @@ -209,7 +253,8 @@ void hfi1_mmu_rb_evict(struct mmu_rb_handler *handler, void *evict_arg) spin_unlock_irqrestore(&handler->lock, flags); list_for_each_entry_safe(rbnode, ptr, &del_list, list) { - handler->ops->remove(handler->ops_arg, rbnode); + trace_hfi1_mmu_rb_evict(rbnode); + kref_put(&rbnode->refcount, release_immediate); } } @@ -221,7 +266,6 @@ static int mmu_notifier_range_start(struct mmu_notifier *mn, struct rb_root_cached *root = &handler->root; struct mmu_rb_node *node, *ptr = NULL; unsigned long flags; - bool added = false; spin_lock_irqsave(&handler->lock, flags); for (node = __mmu_int_rb_iter_first(root, range->start, range->end-1); @@ -229,39 +273,17 @@ static int mmu_notifier_range_start(struct mmu_notifier *mn, /* Guard against node removal. */ ptr = __mmu_int_rb_iter_next(node, range->start, range->end - 1); - trace_hfi1_mmu_mem_invalidate(node->addr, node->len); - if (handler->ops->invalidate(handler->ops_arg, node)) { - __mmu_int_rb_remove(node, root); - /* move from LRU list to delete list */ - list_move(&node->list, &handler->del_list); - added = true; - } + trace_hfi1_mmu_mem_invalidate(node); + /* Remove from rb tree and lru_list. */ + __mmu_int_rb_remove(node, root); + list_del_init(&node->list); + kref_put(&node->refcount, release_nolock); } spin_unlock_irqrestore(&handler->lock, flags); - if (added) - queue_work(handler->wq, &handler->del_work); - return 0; } -/* - * Call the remove function for the given handler and the list. This - * is expected to be called with a delete list extracted from handler. - * The caller should not be holding the handler lock. - */ -static void do_remove(struct mmu_rb_handler *handler, - struct list_head *del_list) -{ - struct mmu_rb_node *node; - - while (!list_empty(del_list)) { - node = list_first_entry(del_list, struct mmu_rb_node, list); - list_del(&node->list); - handler->ops->remove(handler->ops_arg, node); - } -} - /* * Work queue function to remove all nodes that have been queued up to * be removed. The key feature is that mm->mmap_lock is not being held @@ -274,11 +296,17 @@ static void handle_remove(struct work_struct *work) del_work); struct list_head del_list; unsigned long flags; + struct mmu_rb_node *node; /* remove anything that is queued to get removed */ spin_lock_irqsave(&handler->lock, flags); list_replace_init(&handler->del_list, &del_list); spin_unlock_irqrestore(&handler->lock, flags); - do_remove(handler, &del_list); + while (!list_empty(&del_list)) { + node = list_first_entry(&del_list, struct mmu_rb_node, list); + list_del(&node->list); + trace_hfi1_mmu_release_node(node); + handler->ops->remove(handler->ops_arg, node); + } } diff --git a/drivers/infiniband/hw/hfi1/mmu_rb.h b/drivers/infiniband/hw/hfi1/mmu_rb.h index c4da064188c9d31dc316e64332cb8ef624342a4a..751dc3fe1e02973f455d704f2e936dfc384fda11 100644 --- a/drivers/infiniband/hw/hfi1/mmu_rb.h +++ b/drivers/infiniband/hw/hfi1/mmu_rb.h @@ -16,18 +16,14 @@ struct mmu_rb_node { struct rb_node node; struct mmu_rb_handler *handler; struct list_head list; + struct kref refcount; }; -/* - * NOTE: filter, insert, invalidate, and evict must not sleep. Only remove is - * allowed to sleep. - */ +/* filter and evict must not sleep. Only remove is allowed to sleep. */ struct mmu_rb_ops { bool (*filter)(struct mmu_rb_node *node, unsigned long addr, unsigned long len); - int (*insert)(void *ops_arg, struct mmu_rb_node *mnode); void (*remove)(void *ops_arg, struct mmu_rb_node *mnode); - int (*invalidate)(void *ops_arg, struct mmu_rb_node *node); int (*evict)(void *ops_arg, struct mmu_rb_node *mnode, void *evict_arg, bool *stop); }; @@ -61,6 +57,8 @@ int hfi1_mmu_rb_register(void *ops_arg, void hfi1_mmu_rb_unregister(struct mmu_rb_handler *handler); int hfi1_mmu_rb_insert(struct mmu_rb_handler *handler, struct mmu_rb_node *mnode); +void hfi1_mmu_rb_release(struct kref *refcount); + void hfi1_mmu_rb_evict(struct mmu_rb_handler *handler, void *evict_arg); struct mmu_rb_node *hfi1_mmu_rb_get_first(struct mmu_rb_handler *handler, unsigned long addr, diff --git a/drivers/infiniband/hw/hfi1/sdma.c b/drivers/infiniband/hw/hfi1/sdma.c index bb2552dd29c1e29ae2c9959c2714f9a691e569ab..26c62162759bab6e4d3c14809f389296a345865b 100644 --- a/drivers/infiniband/hw/hfi1/sdma.c +++ b/drivers/infiniband/hw/hfi1/sdma.c @@ -1593,7 +1593,20 @@ static inline void sdma_unmap_desc( struct hfi1_devdata *dd, struct sdma_desc *descp) { - system_descriptor_complete(dd, descp); + switch (sdma_mapping_type(descp)) { + case SDMA_MAP_SINGLE: + dma_unmap_single(&dd->pcidev->dev, sdma_mapping_addr(descp), + sdma_mapping_len(descp), DMA_TO_DEVICE); + break; + case SDMA_MAP_PAGE: + dma_unmap_page(&dd->pcidev->dev, sdma_mapping_addr(descp), + sdma_mapping_len(descp), DMA_TO_DEVICE); + break; + } + + if (descp->pinning_ctx && descp->ctx_put) + descp->ctx_put(descp->pinning_ctx); + descp->pinning_ctx = NULL; } /* @@ -3113,8 +3126,8 @@ int ext_coal_sdma_tx_descs(struct hfi1_devdata *dd, struct sdma_txreq *tx, /* Add descriptor for coalesce buffer */ tx->desc_limit = MAX_DESC; - return _sdma_txadd_daddr(dd, SDMA_MAP_SINGLE, NULL, tx, - addr, tx->tlen); + return _sdma_txadd_daddr(dd, SDMA_MAP_SINGLE, tx, + addr, tx->tlen, NULL, NULL, NULL); } return 1; @@ -3157,9 +3170,9 @@ int _pad_sdma_tx_descs(struct hfi1_devdata *dd, struct sdma_txreq *tx) make_tx_sdma_desc( tx, SDMA_MAP_NONE, - NULL, dd->sdma_pad_phys, - sizeof(u32) - (tx->packet_len & (sizeof(u32) - 1))); + sizeof(u32) - (tx->packet_len & (sizeof(u32) - 1)), + NULL, NULL, NULL); tx->num_desc++; _sdma_close_tx(dd, tx); return rval; diff --git a/drivers/infiniband/hw/hfi1/sdma.h b/drivers/infiniband/hw/hfi1/sdma.h index 95aaec14c6c2882e1559309a6ab33e95ac2f479c..7fdebab202c4f3c037819d462cb7060711927b5e 100644 --- a/drivers/infiniband/hw/hfi1/sdma.h +++ b/drivers/infiniband/hw/hfi1/sdma.h @@ -594,9 +594,11 @@ static inline dma_addr_t sdma_mapping_addr(struct sdma_desc *d) static inline void make_tx_sdma_desc( struct sdma_txreq *tx, int type, - void *pinning_ctx, dma_addr_t addr, - size_t len) + size_t len, + void *pinning_ctx, + void (*ctx_get)(void *), + void (*ctx_put)(void *)) { struct sdma_desc *desc = &tx->descp[tx->num_desc]; @@ -613,7 +615,11 @@ static inline void make_tx_sdma_desc( << SDMA_DESC0_PHY_ADDR_SHIFT) | (((u64)len & SDMA_DESC0_BYTE_COUNT_MASK) << SDMA_DESC0_BYTE_COUNT_SHIFT); + desc->pinning_ctx = pinning_ctx; + desc->ctx_put = ctx_put; + if (pinning_ctx && ctx_get) + ctx_get(pinning_ctx); } /* helper to extend txreq */ @@ -645,18 +651,20 @@ static inline void _sdma_close_tx(struct hfi1_devdata *dd, static inline int _sdma_txadd_daddr( struct hfi1_devdata *dd, int type, - void *pinning_ctx, struct sdma_txreq *tx, dma_addr_t addr, - u16 len) + u16 len, + void *pinning_ctx, + void (*ctx_get)(void *), + void (*ctx_put)(void *)) { int rval = 0; make_tx_sdma_desc( tx, type, - pinning_ctx, - addr, len); + addr, len, + pinning_ctx, ctx_get, ctx_put); WARN_ON(len > tx->tlen); tx->num_desc++; tx->tlen -= len; @@ -676,11 +684,18 @@ static inline int _sdma_txadd_daddr( /** * sdma_txadd_page() - add a page to the sdma_txreq * @dd: the device to use for mapping - * @pinning_ctx: context to be released at descriptor retirement * @tx: tx request to which the page is added * @page: page to map * @offset: offset within the page * @len: length in bytes + * @pinning_ctx: context to be stored on struct sdma_desc .pinning_ctx. Not + * added if coalesce buffer is used. E.g. pointer to pinned-page + * cache entry for the sdma_desc. + * @ctx_get: optional function to take reference to @pinning_ctx. Not called if + * @pinning_ctx is NULL. + * @ctx_put: optional function to release reference to @pinning_ctx after + * sdma_desc completes. May be called in interrupt context so must + * not sleep. Not called if @pinning_ctx is NULL. * * This is used to add a page/offset/length descriptor. * @@ -692,11 +707,13 @@ static inline int _sdma_txadd_daddr( */ static inline int sdma_txadd_page( struct hfi1_devdata *dd, - void *pinning_ctx, struct sdma_txreq *tx, struct page *page, unsigned long offset, - u16 len) + u16 len, + void *pinning_ctx, + void (*ctx_get)(void *), + void (*ctx_put)(void *)) { dma_addr_t addr; int rval; @@ -720,7 +737,8 @@ static inline int sdma_txadd_page( return -ENOSPC; } - return _sdma_txadd_daddr(dd, SDMA_MAP_PAGE, pinning_ctx, tx, addr, len); + return _sdma_txadd_daddr(dd, SDMA_MAP_PAGE, tx, addr, len, + pinning_ctx, ctx_get, ctx_put); } /** @@ -754,8 +772,8 @@ static inline int sdma_txadd_daddr( return rval; } - return _sdma_txadd_daddr(dd, SDMA_MAP_NONE, NULL, tx, - addr, len); + return _sdma_txadd_daddr(dd, SDMA_MAP_NONE, tx, addr, len, + NULL, NULL, NULL); } /** @@ -801,7 +819,8 @@ static inline int sdma_txadd_kvaddr( return -ENOSPC; } - return _sdma_txadd_daddr(dd, SDMA_MAP_SINGLE, NULL, tx, addr, len); + return _sdma_txadd_daddr(dd, SDMA_MAP_SINGLE, tx, addr, len, + NULL, NULL, NULL); } struct iowait_work; @@ -1034,6 +1053,4 @@ u16 sdma_get_descq_cnt(void); extern uint mod_num_sdma; void sdma_update_lmc(struct hfi1_devdata *dd, u64 mask, u32 lid); - -void system_descriptor_complete(struct hfi1_devdata *dd, struct sdma_desc *descp); #endif diff --git a/drivers/infiniband/hw/hfi1/sdma_txreq.h b/drivers/infiniband/hw/hfi1/sdma_txreq.h index fad946cb5e0d86372c9837f165eebfcd082d0f42..85ae7293c27410b26a207a7d8cd62875d3f083b6 100644 --- a/drivers/infiniband/hw/hfi1/sdma_txreq.h +++ b/drivers/infiniband/hw/hfi1/sdma_txreq.h @@ -20,6 +20,8 @@ struct sdma_desc { /* private: don't use directly */ u64 qw[2]; void *pinning_ctx; + /* Release reference to @pinning_ctx. May be called in interrupt context. Must not sleep. */ + void (*ctx_put)(void *ctx); }; /** diff --git a/drivers/infiniband/hw/hfi1/trace_mmu.h b/drivers/infiniband/hw/hfi1/trace_mmu.h index 57900ebb7702e52f9115f8f0a220cc606816d6f4..82cc12aa3fb8b9986f31a5403382516283e02394 100644 --- a/drivers/infiniband/hw/hfi1/trace_mmu.h +++ b/drivers/infiniband/hw/hfi1/trace_mmu.h @@ -15,31 +15,53 @@ #define TRACE_SYSTEM hfi1_mmu DECLARE_EVENT_CLASS(hfi1_mmu_rb_template, - TP_PROTO(unsigned long addr, unsigned long len), - TP_ARGS(addr, len), + TP_PROTO(struct mmu_rb_node *node), + TP_ARGS(node), TP_STRUCT__entry(__field(unsigned long, addr) __field(unsigned long, len) + __field(unsigned int, refcount) ), - TP_fast_assign(__entry->addr = addr; - __entry->len = len; + TP_fast_assign(__entry->addr = node->addr; + __entry->len = node->len; + __entry->refcount = kref_read(&node->refcount); ), - TP_printk("MMU node addr 0x%lx, len %lu", + TP_printk("MMU node addr 0x%lx, len %lu, refcount %u", __entry->addr, - __entry->len + __entry->len, + __entry->refcount ) ); DEFINE_EVENT(hfi1_mmu_rb_template, hfi1_mmu_rb_insert, - TP_PROTO(unsigned long addr, unsigned long len), - TP_ARGS(addr, len)); + TP_PROTO(struct mmu_rb_node *node), + TP_ARGS(node)); -DEFINE_EVENT(hfi1_mmu_rb_template, hfi1_mmu_rb_search, - TP_PROTO(unsigned long addr, unsigned long len), - TP_ARGS(addr, len)); +TRACE_EVENT(hfi1_mmu_rb_search, + TP_PROTO(unsigned long addr, unsigned long len), + TP_ARGS(addr, len), + TP_STRUCT__entry(__field(unsigned long, addr) + __field(unsigned long, len) + ), + TP_fast_assign(__entry->addr = addr; + __entry->len = len; + ), + TP_printk("MMU node addr 0x%lx, len %lu", + __entry->addr, + __entry->len + ) +); DEFINE_EVENT(hfi1_mmu_rb_template, hfi1_mmu_mem_invalidate, - TP_PROTO(unsigned long addr, unsigned long len), - TP_ARGS(addr, len)); + TP_PROTO(struct mmu_rb_node *node), + TP_ARGS(node)); + +DEFINE_EVENT(hfi1_mmu_rb_template, hfi1_mmu_rb_evict, + TP_PROTO(struct mmu_rb_node *node), + TP_ARGS(node)); + +DEFINE_EVENT(hfi1_mmu_rb_template, hfi1_mmu_release_node, + TP_PROTO(struct mmu_rb_node *node), + TP_ARGS(node)); #endif /* __HFI1_TRACE_RC_H */ diff --git a/drivers/infiniband/hw/hfi1/user_sdma.c b/drivers/infiniband/hw/hfi1/user_sdma.c index ae58b48afe0749bd3a9a5537f9b91d0da0142fc1..02bd62b857b75beae5e5d741bca6ebb2fe5df625 100644 --- a/drivers/infiniband/hw/hfi1/user_sdma.c +++ b/drivers/infiniband/hw/hfi1/user_sdma.c @@ -62,18 +62,14 @@ static int defer_packet_queue( static void activate_packet_queue(struct iowait *wait, int reason); static bool sdma_rb_filter(struct mmu_rb_node *node, unsigned long addr, unsigned long len); -static int sdma_rb_insert(void *arg, struct mmu_rb_node *mnode); static int sdma_rb_evict(void *arg, struct mmu_rb_node *mnode, void *arg2, bool *stop); static void sdma_rb_remove(void *arg, struct mmu_rb_node *mnode); -static int sdma_rb_invalidate(void *arg, struct mmu_rb_node *mnode); static struct mmu_rb_ops sdma_rb_ops = { .filter = sdma_rb_filter, - .insert = sdma_rb_insert, .evict = sdma_rb_evict, .remove = sdma_rb_remove, - .invalidate = sdma_rb_invalidate }; static int add_system_pages_to_sdma_packet(struct user_sdma_request *req, @@ -247,14 +243,14 @@ int hfi1_user_sdma_free_queues(struct hfi1_filedata *fd, spin_unlock(&fd->pq_rcu_lock); synchronize_srcu(&fd->pq_srcu); /* at this point there can be no more new requests */ - if (pq->handler) - hfi1_mmu_rb_unregister(pq->handler); iowait_sdma_drain(&pq->busy); /* Wait until all requests have been freed. */ wait_event_interruptible( pq->wait, !atomic_read(&pq->n_reqs)); kfree(pq->reqs); + if (pq->handler) + hfi1_mmu_rb_unregister(pq->handler); bitmap_free(pq->req_in_use); kmem_cache_destroy(pq->txreq_cache); flush_pq_iowait(pq); @@ -1275,25 +1271,17 @@ static void free_system_node(struct sdma_mmu_node *node) kfree(node); } -static inline void acquire_node(struct sdma_mmu_node *node) -{ - atomic_inc(&node->refcount); - WARN_ON(atomic_read(&node->refcount) < 0); -} - -static inline void release_node(struct mmu_rb_handler *handler, - struct sdma_mmu_node *node) -{ - atomic_dec(&node->refcount); - WARN_ON(atomic_read(&node->refcount) < 0); -} - +/* + * kref_get()'s an additional kref on the returned rb_node to prevent rb_node + * from being released until after rb_node is assigned to an SDMA descriptor + * (struct sdma_desc) under add_system_iovec_to_sdma_packet(), even if the + * virtual address range for rb_node is invalidated between now and then. + */ static struct sdma_mmu_node *find_system_node(struct mmu_rb_handler *handler, unsigned long start, unsigned long end) { struct mmu_rb_node *rb_node; - struct sdma_mmu_node *node; unsigned long flags; spin_lock_irqsave(&handler->lock, flags); @@ -1302,11 +1290,12 @@ static struct sdma_mmu_node *find_system_node(struct mmu_rb_handler *handler, spin_unlock_irqrestore(&handler->lock, flags); return NULL; } - node = container_of(rb_node, struct sdma_mmu_node, rb); - acquire_node(node); + + /* "safety" kref to prevent release before add_system_iovec_to_sdma_packet() */ + kref_get(&rb_node->refcount); spin_unlock_irqrestore(&handler->lock, flags); - return node; + return container_of(rb_node, struct sdma_mmu_node, rb); } static int pin_system_pages(struct user_sdma_request *req, @@ -1355,6 +1344,13 @@ static int pin_system_pages(struct user_sdma_request *req, return 0; } +/* + * kref refcount on *node_p will be 2 on successful addition: one kref from + * kref_init() for mmu_rb_handler and one kref to prevent *node_p from being + * released until after *node_p is assigned to an SDMA descriptor (struct + * sdma_desc) under add_system_iovec_to_sdma_packet(), even if the virtual + * address range for *node_p is invalidated between now and then. + */ static int add_system_pinning(struct user_sdma_request *req, struct sdma_mmu_node **node_p, unsigned long start, unsigned long len) @@ -1368,6 +1364,12 @@ static int add_system_pinning(struct user_sdma_request *req, if (!node) return -ENOMEM; + /* First kref "moves" to mmu_rb_handler */ + kref_init(&node->rb.refcount); + + /* "safety" kref to prevent release before add_system_iovec_to_sdma_packet() */ + kref_get(&node->rb.refcount); + node->pq = pq; ret = pin_system_pages(req, start, len, node, PFN_DOWN(len)); if (ret == 0) { @@ -1431,15 +1433,15 @@ static int get_system_cache_entry(struct user_sdma_request *req, return 0; } - SDMA_DBG(req, "prepend: node->rb.addr %lx, node->refcount %d", - node->rb.addr, atomic_read(&node->refcount)); + SDMA_DBG(req, "prepend: node->rb.addr %lx, node->rb.refcount %d", + node->rb.addr, kref_read(&node->rb.refcount)); prepend_len = node->rb.addr - start; /* * This node will not be returned, instead a new node * will be. So release the reference. */ - release_node(handler, node); + kref_put(&node->rb.refcount, hfi1_mmu_rb_release); /* Prepend a node to cover the beginning of the allocation */ ret = add_system_pinning(req, node_p, start, prepend_len); @@ -1451,6 +1453,20 @@ static int get_system_cache_entry(struct user_sdma_request *req, } } +static void sdma_mmu_rb_node_get(void *ctx) +{ + struct mmu_rb_node *node = ctx; + + kref_get(&node->refcount); +} + +static void sdma_mmu_rb_node_put(void *ctx) +{ + struct sdma_mmu_node *node = ctx; + + kref_put(&node->rb.refcount, hfi1_mmu_rb_release); +} + static int add_mapping_to_sdma_packet(struct user_sdma_request *req, struct user_sdma_txreq *tx, struct sdma_mmu_node *cache_entry, @@ -1494,9 +1510,12 @@ static int add_mapping_to_sdma_packet(struct user_sdma_request *req, ctx = cache_entry; } - ret = sdma_txadd_page(pq->dd, ctx, &tx->txreq, + ret = sdma_txadd_page(pq->dd, &tx->txreq, cache_entry->pages[page_index], - page_offset, from_this_page); + page_offset, from_this_page, + ctx, + sdma_mmu_rb_node_get, + sdma_mmu_rb_node_put); if (ret) { /* * When there's a failure, the entire request is freed by @@ -1518,8 +1537,6 @@ static int add_system_iovec_to_sdma_packet(struct user_sdma_request *req, struct user_sdma_iovec *iovec, size_t from_this_iovec) { - struct mmu_rb_handler *handler = req->pq->handler; - while (from_this_iovec > 0) { struct sdma_mmu_node *cache_entry; size_t from_this_cache_entry; @@ -1540,15 +1557,15 @@ static int add_system_iovec_to_sdma_packet(struct user_sdma_request *req, ret = add_mapping_to_sdma_packet(req, tx, cache_entry, start, from_this_cache_entry); + + /* + * Done adding cache_entry to zero or more sdma_desc. Can + * kref_put() the "safety" kref taken under + * get_system_cache_entry(). + */ + kref_put(&cache_entry->rb.refcount, hfi1_mmu_rb_release); + if (ret) { - /* - * We're guaranteed that there will be no descriptor - * completion callback that releases this node - * because only the last descriptor referencing it - * has a context attached, and a failure means the - * last descriptor was never added. - */ - release_node(handler, cache_entry); SDMA_DBG(req, "add system segment failed %d", ret); return ret; } @@ -1599,42 +1616,12 @@ static int add_system_pages_to_sdma_packet(struct user_sdma_request *req, return 0; } -void system_descriptor_complete(struct hfi1_devdata *dd, - struct sdma_desc *descp) -{ - switch (sdma_mapping_type(descp)) { - case SDMA_MAP_SINGLE: - dma_unmap_single(&dd->pcidev->dev, sdma_mapping_addr(descp), - sdma_mapping_len(descp), DMA_TO_DEVICE); - break; - case SDMA_MAP_PAGE: - dma_unmap_page(&dd->pcidev->dev, sdma_mapping_addr(descp), - sdma_mapping_len(descp), DMA_TO_DEVICE); - break; - } - - if (descp->pinning_ctx) { - struct sdma_mmu_node *node = descp->pinning_ctx; - - release_node(node->rb.handler, node); - } -} - static bool sdma_rb_filter(struct mmu_rb_node *node, unsigned long addr, unsigned long len) { return (bool)(node->addr == addr); } -static int sdma_rb_insert(void *arg, struct mmu_rb_node *mnode) -{ - struct sdma_mmu_node *node = - container_of(mnode, struct sdma_mmu_node, rb); - - atomic_inc(&node->refcount); - return 0; -} - /* * Return 1 to remove the node from the rb tree and call the remove op. * @@ -1647,10 +1634,6 @@ static int sdma_rb_evict(void *arg, struct mmu_rb_node *mnode, container_of(mnode, struct sdma_mmu_node, rb); struct evict_data *evict_data = evict_arg; - /* is this node still being used? */ - if (atomic_read(&node->refcount)) - return 0; /* keep this node */ - /* this node will be evicted, add its pages to our count */ evict_data->cleared += node->npages; @@ -1668,13 +1651,3 @@ static void sdma_rb_remove(void *arg, struct mmu_rb_node *mnode) free_system_node(node); } - -static int sdma_rb_invalidate(void *arg, struct mmu_rb_node *mnode) -{ - struct sdma_mmu_node *node = - container_of(mnode, struct sdma_mmu_node, rb); - - if (!atomic_read(&node->refcount)) - return 1; - return 0; -} diff --git a/drivers/infiniband/hw/hfi1/user_sdma.h b/drivers/infiniband/hw/hfi1/user_sdma.h index a241836371dc13259979d274feadff4a2c421b2b..548347d4c5bc274e4751897d75404b33f4fa6fe4 100644 --- a/drivers/infiniband/hw/hfi1/user_sdma.h +++ b/drivers/infiniband/hw/hfi1/user_sdma.h @@ -104,7 +104,6 @@ struct hfi1_user_sdma_comp_q { struct sdma_mmu_node { struct mmu_rb_node rb; struct hfi1_user_sdma_pkt_q *pq; - atomic_t refcount; struct page **pages; unsigned int npages; }; diff --git a/drivers/infiniband/hw/hfi1/vnic_sdma.c b/drivers/infiniband/hw/hfi1/vnic_sdma.c index 727eedfba332a932a0f3553b9745d8d543244dcc..cc6324d2d1ddcf8560688ddd62aa7f9c81eb2e3c 100644 --- a/drivers/infiniband/hw/hfi1/vnic_sdma.c +++ b/drivers/infiniband/hw/hfi1/vnic_sdma.c @@ -64,11 +64,11 @@ static noinline int build_vnic_ulp_payload(struct sdma_engine *sde, /* combine physically continuous fragments later? */ ret = sdma_txadd_page(sde->dd, - NULL, &tx->txreq, skb_frag_page(frag), skb_frag_off(frag), - skb_frag_size(frag)); + skb_frag_size(frag), + NULL, NULL, NULL); if (unlikely(ret)) goto bail_txadd; } diff --git a/drivers/infiniband/hw/hns/hns_roce_hem.c b/drivers/infiniband/hw/hns/hns_roce_hem.c index aa8a08d1c01456b1c546f27b40a87cd002015f85..47c0efed18211a31d38df3e7f8ee9f76038e279c 100644 --- a/drivers/infiniband/hw/hns/hns_roce_hem.c +++ b/drivers/infiniband/hw/hns/hns_roce_hem.c @@ -595,11 +595,12 @@ int hns_roce_table_get(struct hns_roce_dev *hr_dev, } /* Set HEM base address(128K/page, pa) to Hardware */ - if (hr_dev->hw->set_hem(hr_dev, table, obj, HEM_HOP_STEP_DIRECT)) { + ret = hr_dev->hw->set_hem(hr_dev, table, obj, HEM_HOP_STEP_DIRECT); + if (ret) { hns_roce_free_hem(hr_dev, table->hem[i]); table->hem[i] = NULL; - ret = -ENODEV; - dev_err(dev, "set HEM base address to HW failed.\n"); + dev_err(dev, "set HEM base address to HW failed, ret = %d.\n", + ret); goto out; } @@ -618,6 +619,7 @@ static void clear_mhop_hem(struct hns_roce_dev *hr_dev, u32 hop_num = mhop->hop_num; u32 chunk_ba_num; u32 step_idx; + int ret; index->inited = HEM_INDEX_BUF; chunk_ba_num = mhop->bt_chunk_size / BA_BYTE_LEN; @@ -641,16 +643,24 @@ static void clear_mhop_hem(struct hns_roce_dev *hr_dev, else step_idx = hop_num; - if (hr_dev->hw->clear_hem(hr_dev, table, obj, step_idx)) - ibdev_warn(ibdev, "failed to clear hop%u HEM.\n", hop_num); - - if (index->inited & HEM_INDEX_L1) - if (hr_dev->hw->clear_hem(hr_dev, table, obj, 1)) - ibdev_warn(ibdev, "failed to clear HEM step 1.\n"); + ret = hr_dev->hw->clear_hem(hr_dev, table, obj, step_idx); + if (ret) + ibdev_warn(ibdev, "failed to clear hop%u HEM, ret = %d.\n", + hop_num, ret); + + if (index->inited & HEM_INDEX_L1) { + ret = hr_dev->hw->clear_hem(hr_dev, table, obj, 1); + if (ret) + ibdev_warn(ibdev, "failed to clear HEM step 1, ret = %d.\n", + ret); + } - if (index->inited & HEM_INDEX_L0) - if (hr_dev->hw->clear_hem(hr_dev, table, obj, 0)) - ibdev_warn(ibdev, "failed to clear HEM step 0.\n"); + if (index->inited & HEM_INDEX_L0) { + ret = hr_dev->hw->clear_hem(hr_dev, table, obj, 0); + if (ret) + ibdev_warn(ibdev, "failed to clear HEM step 0, ret = %d.\n", + ret); + } } } @@ -687,6 +697,7 @@ void hns_roce_table_put(struct hns_roce_dev *hr_dev, { struct device *dev = hr_dev->dev; unsigned long i; + int ret; if (hns_roce_check_whether_mhop(hr_dev, table->type)) { hns_roce_table_mhop_put(hr_dev, table, obj, 1); @@ -699,8 +710,10 @@ void hns_roce_table_put(struct hns_roce_dev *hr_dev, &table->mutex)) return; - if (hr_dev->hw->clear_hem(hr_dev, table, obj, HEM_HOP_STEP_DIRECT)) - dev_warn(dev, "failed to clear HEM base address.\n"); + ret = hr_dev->hw->clear_hem(hr_dev, table, obj, HEM_HOP_STEP_DIRECT); + if (ret) + dev_warn(dev, "failed to clear HEM base address, ret = %d.\n", + ret); hns_roce_free_hem(hr_dev, table->hem[i]); table->hem[i] = NULL; @@ -916,6 +929,8 @@ void hns_roce_cleanup_hem_table(struct hns_roce_dev *hr_dev, { struct device *dev = hr_dev->dev; unsigned long i; + int obj; + int ret; if (hns_roce_check_whether_mhop(hr_dev, table->type)) { hns_roce_cleanup_mhop_hem_table(hr_dev, table); @@ -924,9 +939,11 @@ void hns_roce_cleanup_hem_table(struct hns_roce_dev *hr_dev, for (i = 0; i < table->num_hem; ++i) if (table->hem[i]) { - if (hr_dev->hw->clear_hem(hr_dev, table, - i * table->table_chunk_size / table->obj_size, 0)) - dev_err(dev, "clear HEM base address failed.\n"); + obj = i * table->table_chunk_size / table->obj_size; + ret = hr_dev->hw->clear_hem(hr_dev, table, obj, 0); + if (ret) + dev_err(dev, "clear HEM base address failed, ret = %d.\n", + ret); hns_roce_free_hem(hr_dev, table->hem[i]); } diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c index d4c6b9bc0a4ea222e7d4bff78ab3010d452a049c..8f7eb11066b43e8a12f9db59cbb5dafe6a6de7ca 100644 --- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c +++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c @@ -373,17 +373,10 @@ static int check_send_valid(struct hns_roce_dev *hr_dev, struct hns_roce_qp *hr_qp) { struct ib_device *ibdev = &hr_dev->ib_dev; - struct ib_qp *ibqp = &hr_qp->ibqp; - if (unlikely(ibqp->qp_type != IB_QPT_RC && - ibqp->qp_type != IB_QPT_GSI && - ibqp->qp_type != IB_QPT_UD)) { - ibdev_err(ibdev, "not supported QP(0x%x)type!\n", - ibqp->qp_type); - return -EOPNOTSUPP; - } else if (unlikely(hr_qp->state == IB_QPS_RESET || - hr_qp->state == IB_QPS_INIT || - hr_qp->state == IB_QPS_RTR)) { + if (unlikely(hr_qp->state == IB_QPS_RESET || + hr_qp->state == IB_QPS_INIT || + hr_qp->state == IB_QPS_RTR)) { ibdev_err(ibdev, "failed to post WQE, QP state %u!\n", hr_qp->state); return -EINVAL; @@ -771,17 +764,6 @@ static int hns_roce_v2_post_send(struct ib_qp *ibqp, static int check_recv_valid(struct hns_roce_dev *hr_dev, struct hns_roce_qp *hr_qp) { - struct ib_device *ibdev = &hr_dev->ib_dev; - struct ib_qp *ibqp = &hr_qp->ibqp; - - if (unlikely(ibqp->qp_type != IB_QPT_RC && - ibqp->qp_type != IB_QPT_GSI && - ibqp->qp_type != IB_QPT_UD)) { - ibdev_err(ibdev, "unsupported qp type, qp_type = %d.\n", - ibqp->qp_type); - return -EOPNOTSUPP; - } - if (unlikely(hr_dev->state >= HNS_ROCE_DEVICE_STATE_RST_DOWN)) return -EIO; diff --git a/drivers/infiniband/hw/irdma/uk.c b/drivers/infiniband/hw/irdma/uk.c index 16183e894da77b1742291591e15321c56405b06e..dd428d915c1759b858dea3dfff91c575bb74096b 100644 --- a/drivers/infiniband/hw/irdma/uk.c +++ b/drivers/infiniband/hw/irdma/uk.c @@ -93,16 +93,18 @@ static int irdma_nop_1(struct irdma_qp_uk *qp) */ void irdma_clr_wqes(struct irdma_qp_uk *qp, u32 qp_wqe_idx) { - __le64 *wqe; + struct irdma_qp_quanta *sq; u32 wqe_idx; if (!(qp_wqe_idx & 0x7F)) { wqe_idx = (qp_wqe_idx + 128) % qp->sq_ring.size; - wqe = qp->sq_base[wqe_idx].elem; + sq = qp->sq_base + wqe_idx; if (wqe_idx) - memset(wqe, qp->swqe_polarity ? 0 : 0xFF, 0x1000); + memset(sq, qp->swqe_polarity ? 0 : 0xFF, + 128 * sizeof(*sq)); else - memset(wqe, qp->swqe_polarity ? 0xFF : 0, 0x1000); + memset(sq, qp->swqe_polarity ? 0xFF : 0, + 128 * sizeof(*sq)); } } diff --git a/drivers/infiniband/hw/irdma/verbs.c b/drivers/infiniband/hw/irdma/verbs.c index eaa12c124598285beaa891761d8a2ec6aaa17ada..9c4fe4fa90018142f67fd0bd7bd56a9c57b8cdce 100644 --- a/drivers/infiniband/hw/irdma/verbs.c +++ b/drivers/infiniband/hw/irdma/verbs.c @@ -4452,8 +4452,16 @@ static const struct ib_device_ops irdma_roce_dev_ops = { }; static const struct ib_device_ops irdma_iw_dev_ops = { - .modify_qp = irdma_modify_qp, .get_port_immutable = irdma_iw_port_immutable, + .iw_accept = irdma_accept, + .iw_add_ref = irdma_qp_add_ref, + .iw_connect = irdma_connect, + .iw_create_listen = irdma_create_listen, + .iw_destroy_listen = irdma_destroy_listen, + .iw_get_qp = irdma_get_qp, + .iw_reject = irdma_reject, + .iw_rem_ref = irdma_qp_rem_ref, + .modify_qp = irdma_modify_qp, .query_gid = irdma_query_gid, }; @@ -4517,50 +4525,35 @@ static void irdma_init_roce_device(struct irdma_device *iwdev) * irdma_init_iw_device - initialization of iwarp rdma device * @iwdev: irdma device */ -static int irdma_init_iw_device(struct irdma_device *iwdev) +static void irdma_init_iw_device(struct irdma_device *iwdev) { struct net_device *netdev = iwdev->netdev; iwdev->ibdev.node_type = RDMA_NODE_RNIC; addrconf_addr_eui48((u8 *)&iwdev->ibdev.node_guid, netdev->dev_addr); - iwdev->ibdev.ops.iw_add_ref = irdma_qp_add_ref; - iwdev->ibdev.ops.iw_rem_ref = irdma_qp_rem_ref; - iwdev->ibdev.ops.iw_get_qp = irdma_get_qp; - iwdev->ibdev.ops.iw_connect = irdma_connect; - iwdev->ibdev.ops.iw_accept = irdma_accept; - iwdev->ibdev.ops.iw_reject = irdma_reject; - iwdev->ibdev.ops.iw_create_listen = irdma_create_listen; - iwdev->ibdev.ops.iw_destroy_listen = irdma_destroy_listen; memcpy(iwdev->ibdev.iw_ifname, netdev->name, sizeof(iwdev->ibdev.iw_ifname)); ib_set_device_ops(&iwdev->ibdev, &irdma_iw_dev_ops); - - return 0; } /** * irdma_init_rdma_device - initialization of rdma device * @iwdev: irdma device */ -static int irdma_init_rdma_device(struct irdma_device *iwdev) +static void irdma_init_rdma_device(struct irdma_device *iwdev) { struct pci_dev *pcidev = iwdev->rf->pcidev; - int ret; - if (iwdev->roce_mode) { + if (iwdev->roce_mode) irdma_init_roce_device(iwdev); - } else { - ret = irdma_init_iw_device(iwdev); - if (ret) - return ret; - } + else + irdma_init_iw_device(iwdev); + iwdev->ibdev.phys_port_cnt = 1; iwdev->ibdev.num_comp_vectors = iwdev->rf->ceqs_count; iwdev->ibdev.dev.parent = &pcidev->dev; ib_set_device_ops(&iwdev->ibdev, &irdma_dev_ops); - - return 0; } /** @@ -4598,9 +4591,7 @@ int irdma_ib_register_device(struct irdma_device *iwdev) { int ret; - ret = irdma_init_rdma_device(iwdev); - if (ret) - return ret; + irdma_init_rdma_device(iwdev); ret = ib_device_set_netdev(&iwdev->ibdev, iwdev->netdev, 1); if (ret) diff --git a/drivers/infiniband/hw/mana/qp.c b/drivers/infiniband/hw/mana/qp.c index 54b61930a7fdb317b98348af287a737cda873d9b..4b3b5b274e8498006102decf0e87743a98a7445e 100644 --- a/drivers/infiniband/hw/mana/qp.c +++ b/drivers/infiniband/hw/mana/qp.c @@ -13,7 +13,7 @@ static int mana_ib_cfg_vport_steering(struct mana_ib_dev *dev, u8 *rx_hash_key) { struct mana_port_context *mpc = netdev_priv(ndev); - struct mana_cfg_rx_steer_req *req = NULL; + struct mana_cfg_rx_steer_req_v2 *req; struct mana_cfg_rx_steer_resp resp = {}; mana_handle_t *req_indir_tab; struct gdma_context *gc; @@ -33,6 +33,8 @@ static int mana_ib_cfg_vport_steering(struct mana_ib_dev *dev, mana_gd_init_req_hdr(&req->hdr, MANA_CONFIG_VPORT_RX, req_buf_size, sizeof(resp)); + req->hdr.req.msg_version = GDMA_MESSAGE_V2; + req->vport = mpc->port_handle; req->rx_enable = 1; req->update_default_rxobj = 1; @@ -46,6 +48,7 @@ static int mana_ib_cfg_vport_steering(struct mana_ib_dev *dev, req->num_indir_entries = MANA_INDIRECT_TABLE_SIZE; req->indir_tab_offset = sizeof(*req); req->update_indir_tab = true; + req->cqe_coalescing_enable = 1; req_indir_tab = (mana_handle_t *)(req + 1); /* The ind table passed to the hardware must have diff --git a/drivers/infiniband/hw/mlx5/ib_rep.c b/drivers/infiniband/hw/mlx5/ib_rep.c index ddcfc116b19a525b0bbee87a4d5d9481b13d34dc..c7a4ee89612145f8c7168dad6d1b5399f79b3dd7 100644 --- a/drivers/infiniband/hw/mlx5/ib_rep.c +++ b/drivers/infiniband/hw/mlx5/ib_rep.c @@ -30,45 +30,65 @@ mlx5_ib_set_vport_rep(struct mlx5_core_dev *dev, static void mlx5_ib_register_peer_vport_reps(struct mlx5_core_dev *mdev); +static void mlx5_ib_num_ports_update(struct mlx5_core_dev *dev, u32 *num_ports) +{ + struct mlx5_core_dev *peer_dev; + int i; + + mlx5_lag_for_each_peer_mdev(dev, peer_dev, i) { + u32 peer_num_ports = mlx5_eswitch_get_total_vports(peer_dev); + + if (mlx5_lag_is_mpesw(peer_dev)) + *num_ports += peer_num_ports; + else + /* Only 1 ib port is the representor for all uplinks */ + *num_ports += peer_num_ports - 1; + } +} + static int mlx5_ib_vport_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep) { u32 num_ports = mlx5_eswitch_get_total_vports(dev); + struct mlx5_core_dev *lag_master = dev; const struct mlx5_ib_profile *profile; struct mlx5_core_dev *peer_dev; struct mlx5_ib_dev *ibdev; - int second_uplink = false; - u32 peer_num_ports; + int new_uplink = false; int vport_index; int ret; + int i; vport_index = rep->vport_index; if (mlx5_lag_is_shared_fdb(dev)) { - peer_dev = mlx5_lag_get_peer_mdev(dev); - peer_num_ports = mlx5_eswitch_get_total_vports(peer_dev); if (mlx5_lag_is_master(dev)) { - if (mlx5_lag_is_mpesw(dev)) - num_ports += peer_num_ports; - else - num_ports += peer_num_ports - 1; - + mlx5_ib_num_ports_update(dev, &num_ports); } else { if (rep->vport == MLX5_VPORT_UPLINK) { if (!mlx5_lag_is_mpesw(dev)) return 0; - second_uplink = true; + new_uplink = true; } + mlx5_lag_for_each_peer_mdev(dev, peer_dev, i) { + u32 peer_n_ports = mlx5_eswitch_get_total_vports(peer_dev); + + if (mlx5_lag_is_master(peer_dev)) + lag_master = peer_dev; + else if (!mlx5_lag_is_mpesw(dev)) + /* Only 1 ib port is the representor for all uplinks */ + peer_n_ports--; - vport_index += peer_num_ports; - dev = peer_dev; + if (mlx5_get_dev_index(peer_dev) < mlx5_get_dev_index(dev)) + vport_index += peer_n_ports; + } } } - if (rep->vport == MLX5_VPORT_UPLINK && !second_uplink) + if (rep->vport == MLX5_VPORT_UPLINK && !new_uplink) profile = &raw_eth_profile; else - return mlx5_ib_set_vport_rep(dev, rep, vport_index); + return mlx5_ib_set_vport_rep(lag_master, rep, vport_index); ibdev = ib_alloc_device(mlx5_ib_dev, ib_dev); if (!ibdev) @@ -85,8 +105,8 @@ mlx5_ib_vport_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep) vport_index = rep->vport_index; ibdev->port[vport_index].rep = rep; ibdev->port[vport_index].roce.netdev = - mlx5_ib_get_rep_netdev(dev->priv.eswitch, rep->vport); - ibdev->mdev = dev; + mlx5_ib_get_rep_netdev(lag_master->priv.eswitch, rep->vport); + ibdev->mdev = lag_master; ibdev->num_ports = num_ports; ret = __mlx5_ib_add(ibdev, profile); @@ -94,8 +114,8 @@ mlx5_ib_vport_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep) goto fail_add; rep->rep_data[REP_IB].priv = ibdev; - if (mlx5_lag_is_shared_fdb(dev)) - mlx5_ib_register_peer_vport_reps(dev); + if (mlx5_lag_is_shared_fdb(lag_master)) + mlx5_ib_register_peer_vport_reps(lag_master); return 0; @@ -118,23 +138,27 @@ mlx5_ib_vport_rep_unload(struct mlx5_eswitch_rep *rep) struct mlx5_ib_dev *dev = mlx5_ib_rep_to_dev(rep); int vport_index = rep->vport_index; struct mlx5_ib_port *port; + int i; if (WARN_ON(!mdev)) return; + if (!dev) + return; + if (mlx5_lag_is_shared_fdb(mdev) && !mlx5_lag_is_master(mdev)) { - struct mlx5_core_dev *peer_mdev; - - if (rep->vport == MLX5_VPORT_UPLINK) + if (rep->vport == MLX5_VPORT_UPLINK && !mlx5_lag_is_mpesw(mdev)) return; - peer_mdev = mlx5_lag_get_peer_mdev(mdev); - vport_index += mlx5_eswitch_get_total_vports(peer_mdev); + for (i = 0; i < dev->num_ports; i++) { + if (dev->port[i].rep == rep) + break; + } + if (WARN_ON(i == dev->num_ports)) + return; + vport_index = i; } - if (!dev) - return; - port = &dev->port[vport_index]; write_lock(&port->roce.netdev_lock); port->roce.netdev = NULL; @@ -143,13 +167,18 @@ mlx5_ib_vport_rep_unload(struct mlx5_eswitch_rep *rep) port->rep = NULL; if (rep->vport == MLX5_VPORT_UPLINK) { - struct mlx5_core_dev *peer_mdev; - struct mlx5_eswitch *esw; + + if (mlx5_lag_is_shared_fdb(mdev) && !mlx5_lag_is_master(mdev)) + return; if (mlx5_lag_is_shared_fdb(mdev)) { - peer_mdev = mlx5_lag_get_peer_mdev(mdev); - esw = peer_mdev->priv.eswitch; - mlx5_eswitch_unregister_vport_reps(esw, REP_IB); + struct mlx5_core_dev *peer_mdev; + struct mlx5_eswitch *esw; + + mlx5_lag_for_each_peer_mdev(mdev, peer_mdev, i) { + esw = peer_mdev->priv.eswitch; + mlx5_eswitch_unregister_vport_reps(esw, REP_IB); + } } __mlx5_ib_remove(dev, dev->profile, MLX5_IB_STAGE_MAX); } @@ -163,14 +192,14 @@ static const struct mlx5_eswitch_rep_ops rep_ops = { static void mlx5_ib_register_peer_vport_reps(struct mlx5_core_dev *mdev) { - struct mlx5_core_dev *peer_mdev = mlx5_lag_get_peer_mdev(mdev); + struct mlx5_core_dev *peer_mdev; struct mlx5_eswitch *esw; + int i; - if (!peer_mdev) - return; - - esw = peer_mdev->priv.eswitch; - mlx5_eswitch_register_vport_reps(esw, &rep_ops, REP_IB); + mlx5_lag_for_each_peer_mdev(mdev, peer_mdev, i) { + esw = peer_mdev->priv.eswitch; + mlx5_eswitch_register_vport_reps(esw, &rep_ops, REP_IB); + } } struct net_device *mlx5_ib_get_rep_netdev(struct mlx5_eswitch *esw, diff --git a/drivers/infiniband/hw/mlx5/mlx5_ib.h b/drivers/infiniband/hw/mlx5/mlx5_ib.h index 2dfa6f49a6f4816c7c0bad61d5928a6e38187e5f..9c33d960af3c5cd3887be7546ad496f2666c1394 100644 --- a/drivers/infiniband/hw/mlx5/mlx5_ib.h +++ b/drivers/infiniband/hw/mlx5/mlx5_ib.h @@ -25,6 +25,7 @@ #include #include "srq.h" +#include "qp.h" #define mlx5_ib_dbg(_dev, format, arg...) \ dev_dbg(&(_dev)->ib_dev.dev, "%s:%d:(pid %d): " format, __func__, \ diff --git a/drivers/infiniband/hw/mlx5/qp.h b/drivers/infiniband/hw/mlx5/qp.h index 77f9b4a548166103ef1c625a90f73d2f3951eba7..b6ee7c3ee1ca1b1a96ce4994cfaaf7d000828727 100644 --- a/drivers/infiniband/hw/mlx5/qp.h +++ b/drivers/infiniband/hw/mlx5/qp.h @@ -6,7 +6,17 @@ #ifndef _MLX5_IB_QP_H #define _MLX5_IB_QP_H -#include "mlx5_ib.h" +struct mlx5_ib_dev; + +struct mlx5_qp_table { + struct notifier_block nb; + struct xarray dct_xa; + + /* protect radix tree + */ + spinlock_t lock; + struct radix_tree_root tree; +}; int mlx5_init_qp_table(struct mlx5_ib_dev *dev); void mlx5_cleanup_qp_table(struct mlx5_ib_dev *dev); diff --git a/drivers/infiniband/hw/mlx5/qpc.c b/drivers/infiniband/hw/mlx5/qpc.c index bae0334d6e7f18bc1b0a746379f053961bd88520..d9cf6982d645ed38fd084dfdca1e74a0564c9156 100644 --- a/drivers/infiniband/hw/mlx5/qpc.c +++ b/drivers/infiniband/hw/mlx5/qpc.c @@ -88,23 +88,35 @@ static bool is_event_type_allowed(int rsc_type, int event_type) } } +static int dct_event_notifier(struct mlx5_ib_dev *dev, struct mlx5_eqe *eqe) +{ + struct mlx5_core_dct *dct; + unsigned long flags; + u32 qpn; + + qpn = be32_to_cpu(eqe->data.dct.dctn) & 0xFFFFFF; + xa_lock_irqsave(&dev->qp_table.dct_xa, flags); + dct = xa_load(&dev->qp_table.dct_xa, qpn); + if (dct) + complete(&dct->drained); + xa_unlock_irqrestore(&dev->qp_table.dct_xa, flags); + return NOTIFY_OK; +} + static int rsc_event_notifier(struct notifier_block *nb, unsigned long type, void *data) { + struct mlx5_ib_dev *dev = + container_of(nb, struct mlx5_ib_dev, qp_table.nb); struct mlx5_core_rsc_common *common; - struct mlx5_qp_table *table; - struct mlx5_core_dct *dct; + struct mlx5_eqe *eqe = data; u8 event_type = (u8)type; struct mlx5_core_qp *qp; - struct mlx5_eqe *eqe; u32 rsn; switch (event_type) { case MLX5_EVENT_TYPE_DCT_DRAINED: - eqe = data; - rsn = be32_to_cpu(eqe->data.dct.dctn) & 0xffffff; - rsn |= (MLX5_RES_DCT << MLX5_USER_INDEX_LEN); - break; + return dct_event_notifier(dev, eqe); case MLX5_EVENT_TYPE_PATH_MIG: case MLX5_EVENT_TYPE_COMM_EST: case MLX5_EVENT_TYPE_SQ_DRAINED: @@ -113,7 +125,6 @@ static int rsc_event_notifier(struct notifier_block *nb, case MLX5_EVENT_TYPE_PATH_MIG_FAILED: case MLX5_EVENT_TYPE_WQ_INVAL_REQ_ERROR: case MLX5_EVENT_TYPE_WQ_ACCESS_ERROR: - eqe = data; rsn = be32_to_cpu(eqe->data.qp_srq.qp_srq_n) & 0xffffff; rsn |= (eqe->data.qp_srq.type << MLX5_USER_INDEX_LEN); break; @@ -121,8 +132,7 @@ static int rsc_event_notifier(struct notifier_block *nb, return NOTIFY_DONE; } - table = container_of(nb, struct mlx5_qp_table, nb); - common = mlx5_get_rsc(table, rsn); + common = mlx5_get_rsc(&dev->qp_table, rsn); if (!common) return NOTIFY_OK; @@ -137,11 +147,6 @@ static int rsc_event_notifier(struct notifier_block *nb, qp->event(qp, event_type); /* Need to put resource in event handler */ return NOTIFY_OK; - case MLX5_RES_DCT: - dct = (struct mlx5_core_dct *)common; - if (event_type == MLX5_EVENT_TYPE_DCT_DRAINED) - complete(&dct->drained); - break; default: break; } @@ -188,28 +193,15 @@ static void destroy_resource_common(struct mlx5_ib_dev *dev, } static int _mlx5_core_destroy_dct(struct mlx5_ib_dev *dev, - struct mlx5_core_dct *dct, bool need_cleanup) + struct mlx5_core_dct *dct) { u32 in[MLX5_ST_SZ_DW(destroy_dct_in)] = {}; struct mlx5_core_qp *qp = &dct->mqp; - int err; - err = mlx5_core_drain_dct(dev, dct); - if (err) { - if (dev->mdev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR) - goto destroy; - - return err; - } - wait_for_completion(&dct->drained); -destroy: - if (need_cleanup) - destroy_resource_common(dev, &dct->mqp); MLX5_SET(destroy_dct_in, in, opcode, MLX5_CMD_OP_DESTROY_DCT); MLX5_SET(destroy_dct_in, in, dctn, qp->qpn); MLX5_SET(destroy_dct_in, in, uid, qp->uid); - err = mlx5_cmd_exec_in(dev->mdev, destroy_dct, in); - return err; + return mlx5_cmd_exec_in(dev->mdev, destroy_dct, in); } int mlx5_core_create_dct(struct mlx5_ib_dev *dev, struct mlx5_core_dct *dct, @@ -227,13 +219,13 @@ int mlx5_core_create_dct(struct mlx5_ib_dev *dev, struct mlx5_core_dct *dct, qp->qpn = MLX5_GET(create_dct_out, out, dctn); qp->uid = MLX5_GET(create_dct_in, in, uid); - err = create_resource_common(dev, qp, MLX5_RES_DCT); + err = xa_err(xa_store_irq(&dev->qp_table.dct_xa, qp->qpn, dct, GFP_KERNEL)); if (err) goto err_cmd; return 0; err_cmd: - _mlx5_core_destroy_dct(dev, dct, false); + _mlx5_core_destroy_dct(dev, dct); return err; } @@ -284,7 +276,31 @@ static int mlx5_core_drain_dct(struct mlx5_ib_dev *dev, int mlx5_core_destroy_dct(struct mlx5_ib_dev *dev, struct mlx5_core_dct *dct) { - return _mlx5_core_destroy_dct(dev, dct, true); + struct mlx5_qp_table *table = &dev->qp_table; + struct mlx5_core_dct *tmp; + int err; + + err = mlx5_core_drain_dct(dev, dct); + if (err) { + if (dev->mdev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR) + goto destroy; + + return err; + } + wait_for_completion(&dct->drained); + +destroy: + tmp = xa_cmpxchg_irq(&table->dct_xa, dct->mqp.qpn, dct, XA_ZERO_ENTRY, GFP_KERNEL); + if (WARN_ON(tmp != dct)) + return xa_err(tmp) ?: -EINVAL; + + err = _mlx5_core_destroy_dct(dev, dct); + if (err) { + xa_cmpxchg_irq(&table->dct_xa, dct->mqp.qpn, XA_ZERO_ENTRY, dct, 0); + return err; + } + xa_erase_irq(&table->dct_xa, dct->mqp.qpn); + return 0; } int mlx5_core_destroy_qp(struct mlx5_ib_dev *dev, struct mlx5_core_qp *qp) @@ -298,8 +314,7 @@ int mlx5_core_destroy_qp(struct mlx5_ib_dev *dev, struct mlx5_core_qp *qp) MLX5_SET(destroy_qp_in, in, opcode, MLX5_CMD_OP_DESTROY_QP); MLX5_SET(destroy_qp_in, in, qpn, qp->qpn); MLX5_SET(destroy_qp_in, in, uid, qp->uid); - mlx5_cmd_exec_in(dev->mdev, destroy_qp, in); - return 0; + return mlx5_cmd_exec_in(dev->mdev, destroy_qp, in); } int mlx5_core_set_delay_drop(struct mlx5_ib_dev *dev, @@ -488,6 +503,7 @@ int mlx5_init_qp_table(struct mlx5_ib_dev *dev) spin_lock_init(&table->lock); INIT_RADIX_TREE(&table->tree, GFP_ATOMIC); + xa_init(&table->dct_xa); mlx5_qp_debugfs_init(dev->mdev); table->nb.notifier_call = rsc_event_notifier; @@ -551,14 +567,14 @@ int mlx5_core_xrcd_dealloc(struct mlx5_ib_dev *dev, u32 xrcdn) return mlx5_cmd_exec_in(dev->mdev, dealloc_xrcd, in); } -static void destroy_rq_tracked(struct mlx5_ib_dev *dev, u32 rqn, u16 uid) +static int destroy_rq_tracked(struct mlx5_ib_dev *dev, u32 rqn, u16 uid) { u32 in[MLX5_ST_SZ_DW(destroy_rq_in)] = {}; MLX5_SET(destroy_rq_in, in, opcode, MLX5_CMD_OP_DESTROY_RQ); MLX5_SET(destroy_rq_in, in, rqn, rqn); MLX5_SET(destroy_rq_in, in, uid, uid); - mlx5_cmd_exec_in(dev->mdev, destroy_rq, in); + return mlx5_cmd_exec_in(dev->mdev, destroy_rq, in); } int mlx5_core_create_rq_tracked(struct mlx5_ib_dev *dev, u32 *in, int inlen, @@ -589,8 +605,7 @@ int mlx5_core_destroy_rq_tracked(struct mlx5_ib_dev *dev, struct mlx5_core_qp *rq) { destroy_resource_common(dev, rq); - destroy_rq_tracked(dev, rq->qpn, rq->uid); - return 0; + return destroy_rq_tracked(dev, rq->qpn, rq->uid); } static void destroy_sq_tracked(struct mlx5_ib_dev *dev, u32 sqn, u16 uid) diff --git a/drivers/infiniband/hw/qib/qib_user_pages.c b/drivers/infiniband/hw/qib/qib_user_pages.c index f693bc753b6b1de8a45cd1e379ef98ea9342d44e..1bb7507325bcf65d7bbb23f5b970476b0fc712b5 100644 --- a/drivers/infiniband/hw/qib/qib_user_pages.c +++ b/drivers/infiniband/hw/qib/qib_user_pages.c @@ -111,7 +111,7 @@ int qib_get_user_pages(unsigned long start_page, size_t num_pages, ret = pin_user_pages(start_page + got * PAGE_SIZE, num_pages - got, FOLL_LONGTERM | FOLL_WRITE, - p + got, NULL); + p + got); if (ret < 0) { mmap_read_unlock(current->mm); goto bail_release; diff --git a/drivers/infiniband/hw/usnic/usnic_uiom.c b/drivers/infiniband/hw/usnic/usnic_uiom.c index 2a5cac2658eccb81d22fe85763297ec89bd0385f..84e0f41e7dfa9ce581411bf56e386d3b8a22b776 100644 --- a/drivers/infiniband/hw/usnic/usnic_uiom.c +++ b/drivers/infiniband/hw/usnic/usnic_uiom.c @@ -140,7 +140,7 @@ static int usnic_uiom_get_pages(unsigned long addr, size_t size, int writable, ret = pin_user_pages(cur_base, min_t(unsigned long, npages, PAGE_SIZE / sizeof(struct page *)), - gup_flags, page_list, NULL); + gup_flags, page_list); if (ret < 0) goto out; diff --git a/drivers/infiniband/hw/vmw_pvrdma/pvrdma_qp.c b/drivers/infiniband/hw/vmw_pvrdma/pvrdma_qp.c index f83cd4a9d99234c64bebddba19b9f0205f121af6..98b2a0090bf2a13f54eecf7277fdbc26f506eac0 100644 --- a/drivers/infiniband/hw/vmw_pvrdma/pvrdma_qp.c +++ b/drivers/infiniband/hw/vmw_pvrdma/pvrdma_qp.c @@ -709,14 +709,6 @@ int pvrdma_post_send(struct ib_qp *ibqp, const struct ib_send_wr *wr, goto out; } - if (unlikely(wr->opcode < 0)) { - dev_warn_ratelimited(&dev->pdev->dev, - "invalid send opcode\n"); - *bad_wr = wr; - ret = -EINVAL; - goto out; - } - /* * Only support UD, RC. * Need to check opcode table for thorough checking. diff --git a/drivers/infiniband/sw/rxe/rxe.c b/drivers/infiniband/sw/rxe/rxe.c index 7a7e713de52db392af0080611cdde475fd771228..54c723a6eddacef625cccbc47184a46cb93fe9a3 100644 --- a/drivers/infiniband/sw/rxe/rxe.c +++ b/drivers/infiniband/sw/rxe/rxe.c @@ -212,10 +212,16 @@ static int __init rxe_module_init(void) { int err; - err = rxe_net_init(); + err = rxe_alloc_wq(); if (err) return err; + err = rxe_net_init(); + if (err) { + rxe_destroy_wq(); + return err; + } + rdma_link_register(&rxe_link_ops); pr_info("loaded\n"); return 0; @@ -226,6 +232,7 @@ static void __exit rxe_module_exit(void) rdma_link_unregister(&rxe_link_ops); ib_unregister_driver(RDMA_DRIVER_RXE); rxe_net_exit(); + rxe_destroy_wq(); pr_info("unloaded\n"); } diff --git a/drivers/infiniband/sw/rxe/rxe_comp.c b/drivers/infiniband/sw/rxe/rxe_comp.c index f46c5a5fd0aea4d4c0530d054949a8867013053a..5111735aafaed8286a72a4972750a11e2c4cedbc 100644 --- a/drivers/infiniband/sw/rxe/rxe_comp.c +++ b/drivers/infiniband/sw/rxe/rxe_comp.c @@ -832,7 +832,7 @@ int rxe_completer(struct rxe_qp *qp) } /* A non-zero return value will cause rxe_do_task to - * exit its loop and end the tasklet. A zero return + * exit its loop and end the work item. A zero return * will continue looping and return to rxe_completer */ done: diff --git a/drivers/infiniband/sw/rxe/rxe_cq.c b/drivers/infiniband/sw/rxe/rxe_cq.c index 6ca2a05b6a2ab262594b7a3fbbc799f86fba4eff..d5486cbb3f100404808e1e1df5b68452239292cc 100644 --- a/drivers/infiniband/sw/rxe/rxe_cq.c +++ b/drivers/infiniband/sw/rxe/rxe_cq.c @@ -113,10 +113,9 @@ int rxe_cq_post(struct rxe_cq *cq, struct rxe_cqe *cqe, int solicited) queue_advance_producer(cq->queue, QUEUE_TYPE_TO_CLIENT); - if ((cq->notify == IB_CQ_NEXT_COMP) || - (cq->notify == IB_CQ_SOLICITED && solicited)) { + if ((cq->notify & IB_CQ_NEXT_COMP) || + (cq->notify & IB_CQ_SOLICITED && solicited)) { cq->notify = 0; - cq->ibcq.comp_handler(&cq->ibcq, cq->ibcq.cq_context); } diff --git a/drivers/infiniband/sw/rxe/rxe_loc.h b/drivers/infiniband/sw/rxe/rxe_loc.h index 804b15e929dd990127941bbfe2f65d512047f997..666e06a82bc9e7de16bb3a8f9ca9a677038e39b3 100644 --- a/drivers/infiniband/sw/rxe/rxe_loc.h +++ b/drivers/infiniband/sw/rxe/rxe_loc.h @@ -31,8 +31,6 @@ int rxe_cq_resize_queue(struct rxe_cq *cq, int new_cqe, int rxe_cq_post(struct rxe_cq *cq, struct rxe_cqe *cqe, int solicited); -void rxe_cq_disable(struct rxe_cq *cq); - void rxe_cq_cleanup(struct rxe_pool_elem *elem); /* rxe_mcast.c */ diff --git a/drivers/infiniband/sw/rxe/rxe_mr.c b/drivers/infiniband/sw/rxe/rxe_mr.c index 0e538fafcc20ff7ab99d2f6781cb1328a479554b..f54042e9aeb2687c781aa142d621c44e687ccc4f 100644 --- a/drivers/infiniband/sw/rxe/rxe_mr.c +++ b/drivers/infiniband/sw/rxe/rxe_mr.c @@ -45,22 +45,17 @@ int mr_check_range(struct rxe_mr *mr, u64 iova, size_t length) } } -#define IB_ACCESS_REMOTE (IB_ACCESS_REMOTE_READ \ - | IB_ACCESS_REMOTE_WRITE \ - | IB_ACCESS_REMOTE_ATOMIC) - static void rxe_mr_init(int access, struct rxe_mr *mr) { - u32 lkey = mr->elem.index << 8 | rxe_get_next_key(-1); - u32 rkey = (access & IB_ACCESS_REMOTE) ? lkey : 0; + u32 key = mr->elem.index << 8 | rxe_get_next_key(-1); /* set ibmr->l/rkey and also copy into private l/rkey * for user MRs these will always be the same * for cases where caller 'owns' the key portion * they may be different until REG_MR WQE is executed. */ - mr->lkey = mr->ibmr.lkey = lkey; - mr->rkey = mr->ibmr.rkey = rkey; + mr->lkey = mr->ibmr.lkey = key; + mr->rkey = mr->ibmr.rkey = key; mr->access = access; mr->ibmr.page_size = PAGE_SIZE; @@ -195,7 +190,7 @@ int rxe_mr_init_fast(int max_pages, struct rxe_mr *mr) int err; /* always allow remote access for FMRs */ - rxe_mr_init(IB_ACCESS_REMOTE, mr); + rxe_mr_init(RXE_ACCESS_REMOTE, mr); err = rxe_mr_alloc(mr, max_pages); if (err) @@ -644,6 +639,7 @@ int rxe_invalidate_mr(struct rxe_qp *qp, u32 key) { struct rxe_dev *rxe = to_rdev(qp->ibqp.device); struct rxe_mr *mr; + int remote; int ret; mr = rxe_pool_get_index(&rxe->mr_pool, key >> 8); @@ -653,9 +649,10 @@ int rxe_invalidate_mr(struct rxe_qp *qp, u32 key) goto err; } - if (mr->rkey ? (key != mr->rkey) : (key != mr->lkey)) { + remote = mr->access & RXE_ACCESS_REMOTE; + if (remote ? (key != mr->rkey) : (key != mr->lkey)) { rxe_dbg_mr(mr, "wr key (%#x) doesn't match mr key (%#x)\n", - key, (mr->rkey ? mr->rkey : mr->lkey)); + key, (remote ? mr->rkey : mr->lkey)); ret = -EINVAL; goto err_drop_ref; } @@ -715,7 +712,7 @@ int rxe_reg_fast_mr(struct rxe_qp *qp, struct rxe_send_wqe *wqe) mr->access = access; mr->lkey = key; - mr->rkey = (access & IB_ACCESS_REMOTE) ? key : 0; + mr->rkey = key; mr->ibmr.iova = wqe->wr.wr.reg.mr->iova; mr->state = RXE_MR_STATE_VALID; diff --git a/drivers/infiniband/sw/rxe/rxe_mw.c b/drivers/infiniband/sw/rxe/rxe_mw.c index afa5ce1a711667e90bc501f908ad49c00013564e..d8a43d87de9390c814e55f40d2106f3385415ac4 100644 --- a/drivers/infiniband/sw/rxe/rxe_mw.c +++ b/drivers/infiniband/sw/rxe/rxe_mw.c @@ -48,7 +48,7 @@ int rxe_dealloc_mw(struct ib_mw *ibmw) } static int rxe_check_bind_mw(struct rxe_qp *qp, struct rxe_send_wqe *wqe, - struct rxe_mw *mw, struct rxe_mr *mr) + struct rxe_mw *mw, struct rxe_mr *mr, int access) { if (mw->ibmw.type == IB_MW_TYPE_1) { if (unlikely(mw->state != RXE_MW_STATE_VALID)) { @@ -58,7 +58,7 @@ static int rxe_check_bind_mw(struct rxe_qp *qp, struct rxe_send_wqe *wqe, } /* o10-36.2.2 */ - if (unlikely((mw->access & IB_ZERO_BASED))) { + if (unlikely((access & IB_ZERO_BASED))) { rxe_dbg_mw(mw, "attempt to bind a zero based type 1 MW\n"); return -EINVAL; } @@ -104,7 +104,7 @@ static int rxe_check_bind_mw(struct rxe_qp *qp, struct rxe_send_wqe *wqe, } /* C10-74 */ - if (unlikely((mw->access & + if (unlikely((access & (IB_ACCESS_REMOTE_WRITE | IB_ACCESS_REMOTE_ATOMIC)) && !(mr->access & IB_ACCESS_LOCAL_WRITE))) { rxe_dbg_mw(mw, @@ -113,7 +113,7 @@ static int rxe_check_bind_mw(struct rxe_qp *qp, struct rxe_send_wqe *wqe, } /* C10-75 */ - if (mw->access & IB_ZERO_BASED) { + if (access & IB_ZERO_BASED) { if (unlikely(wqe->wr.wr.mw.length > mr->ibmr.length)) { rxe_dbg_mw(mw, "attempt to bind a ZB MW outside of the MR\n"); @@ -133,12 +133,12 @@ static int rxe_check_bind_mw(struct rxe_qp *qp, struct rxe_send_wqe *wqe, } static void rxe_do_bind_mw(struct rxe_qp *qp, struct rxe_send_wqe *wqe, - struct rxe_mw *mw, struct rxe_mr *mr) + struct rxe_mw *mw, struct rxe_mr *mr, int access) { u32 key = wqe->wr.wr.mw.rkey & 0xff; mw->rkey = (mw->rkey & ~0xff) | key; - mw->access = wqe->wr.wr.mw.access; + mw->access = access; mw->state = RXE_MW_STATE_VALID; mw->addr = wqe->wr.wr.mw.addr; mw->length = wqe->wr.wr.mw.length; @@ -169,6 +169,7 @@ int rxe_bind_mw(struct rxe_qp *qp, struct rxe_send_wqe *wqe) struct rxe_dev *rxe = to_rdev(qp->ibqp.device); u32 mw_rkey = wqe->wr.wr.mw.mw_rkey; u32 mr_lkey = wqe->wr.wr.mw.mr_lkey; + int access = wqe->wr.wr.mw.access; mw = rxe_pool_get_index(&rxe->mw_pool, mw_rkey >> 8); if (unlikely(!mw)) { @@ -196,13 +197,18 @@ int rxe_bind_mw(struct rxe_qp *qp, struct rxe_send_wqe *wqe) mr = NULL; } + if (access & ~RXE_ACCESS_SUPPORTED_MW) { + rxe_err_mw(mw, "access %#x not supported", access); + return -EOPNOTSUPP; + } + spin_lock_bh(&mw->lock); - ret = rxe_check_bind_mw(qp, wqe, mw, mr); + ret = rxe_check_bind_mw(qp, wqe, mw, mr, access); if (ret) goto err_unlock; - rxe_do_bind_mw(qp, wqe, mw, mr); + rxe_do_bind_mw(qp, wqe, mw, mr, access); err_unlock: spin_unlock_bh(&mw->lock); err_drop_mr: diff --git a/drivers/infiniband/sw/rxe/rxe_opcode.h b/drivers/infiniband/sw/rxe/rxe_opcode.h index cea4e0a639199cd9d2aa829aa36f2415d845e359..5686b691d6b80386fd2925eb9970393ea758c83f 100644 --- a/drivers/infiniband/sw/rxe/rxe_opcode.h +++ b/drivers/infiniband/sw/rxe/rxe_opcode.h @@ -91,6 +91,9 @@ enum rxe_hdr_mask { RXE_READ_OR_ATOMIC_MASK = (RXE_READ_MASK | RXE_ATOMIC_MASK), RXE_WRITE_OR_SEND_MASK = (RXE_WRITE_MASK | RXE_SEND_MASK), RXE_READ_OR_WRITE_MASK = (RXE_READ_MASK | RXE_WRITE_MASK), + RXE_RDMA_OP_MASK = (RXE_READ_MASK | RXE_WRITE_MASK | + RXE_ATOMIC_WRITE_MASK | RXE_FLUSH_MASK | + RXE_ATOMIC_MASK), }; #define OPCODE_NONE (-1) diff --git a/drivers/infiniband/sw/rxe/rxe_param.h b/drivers/infiniband/sw/rxe/rxe_param.h index 7b41d79e72b2dffc7709838046fbc43081d46592..d2f57ead78ad12d9328520c38289a21b7fe9906e 100644 --- a/drivers/infiniband/sw/rxe/rxe_param.h +++ b/drivers/infiniband/sw/rxe/rxe_param.h @@ -112,7 +112,7 @@ enum rxe_device_param { RXE_INFLIGHT_SKBS_PER_QP_HIGH = 64, RXE_INFLIGHT_SKBS_PER_QP_LOW = 16, - /* Max number of interations of each tasklet + /* Max number of interations of each work item * before yielding the cpu to let other * work make progress */ diff --git a/drivers/infiniband/sw/rxe/rxe_qp.c b/drivers/infiniband/sw/rxe/rxe_qp.c index a0f206431cf8eb82d21573888290f2826367b803..a569b111a9d2a88c79b5a99350e5d261942b45a5 100644 --- a/drivers/infiniband/sw/rxe/rxe_qp.c +++ b/drivers/infiniband/sw/rxe/rxe_qp.c @@ -392,6 +392,13 @@ int rxe_qp_chk_attr(struct rxe_dev *rxe, struct rxe_qp *qp, if (mask & IB_QP_CAP && rxe_qp_chk_cap(rxe, &attr->cap, !!qp->srq)) goto err1; + if (mask & IB_QP_ACCESS_FLAGS) { + if (!(qp_type(qp) == IB_QPT_RC || qp_type(qp) == IB_QPT_UC)) + goto err1; + if (attr->qp_access_flags & ~RXE_ACCESS_SUPPORTED_QP) + goto err1; + } + if (mask & IB_QP_AV && rxe_av_chk_attr(qp, &attr->ah_attr)) goto err1; diff --git a/drivers/infiniband/sw/rxe/rxe_req.c b/drivers/infiniband/sw/rxe/rxe_req.c index 5fe7cbae30313c0ce5f2ab61e00e33e6778b19ad..2171f19494bca131971d3cfaee6dba78281d1276 100644 --- a/drivers/infiniband/sw/rxe/rxe_req.c +++ b/drivers/infiniband/sw/rxe/rxe_req.c @@ -857,7 +857,7 @@ int rxe_requester(struct rxe_qp *qp) update_state(qp, &pkt); /* A non-zero return value will cause rxe_do_task to - * exit its loop and end the tasklet. A zero return + * exit its loop and end the work item. A zero return * will continue looping and return to rxe_requester */ done: diff --git a/drivers/infiniband/sw/rxe/rxe_resp.c b/drivers/infiniband/sw/rxe/rxe_resp.c index ee68306555b990ca169175bae2c31003737d62aa..64c64f5f36a810addfa84284268fb8699a6be772 100644 --- a/drivers/infiniband/sw/rxe/rxe_resp.c +++ b/drivers/infiniband/sw/rxe/rxe_resp.c @@ -387,7 +387,10 @@ static enum resp_states rxe_resp_check_length(struct rxe_qp *qp, } } - return RESPST_CHK_RKEY; + if (pkt->mask & RXE_RDMA_OP_MASK) + return RESPST_CHK_RKEY; + else + return RESPST_EXECUTE; } /* if the reth length field is zero we can assume nothing @@ -434,6 +437,10 @@ static enum resp_states check_rkey(struct rxe_qp *qp, enum resp_states state; int access = 0; + /* parse RETH or ATMETH header for first/only packets + * for va, length, rkey, etc. or use current value for + * middle/last packets. + */ if (pkt->mask & (RXE_READ_OR_WRITE_MASK | RXE_ATOMIC_WRITE_MASK)) { if (pkt->mask & RXE_RETH_MASK) qp_resp_from_reth(qp, pkt); @@ -454,7 +461,8 @@ static enum resp_states check_rkey(struct rxe_qp *qp, qp_resp_from_atmeth(qp, pkt); access = IB_ACCESS_REMOTE_ATOMIC; } else { - return RESPST_EXECUTE; + /* shouldn't happen */ + WARN_ON(1); } /* A zero-byte read or write op is not required to @@ -1449,8 +1457,17 @@ static void flush_recv_queue(struct rxe_qp *qp, bool notify) struct rxe_recv_wqe *wqe; int err; - if (qp->srq) + if (qp->srq) { + if (notify && qp->ibqp.event_handler) { + struct ib_event ev; + + ev.device = qp->ibqp.device; + ev.element.qp = &qp->ibqp; + ev.event = IB_EVENT_QP_LAST_WQE_REACHED; + qp->ibqp.event_handler(&ev, qp->ibqp.qp_context); + } return; + } while ((wqe = queue_head(q, q->type))) { if (notify) { @@ -1657,7 +1674,7 @@ int rxe_responder(struct rxe_qp *qp) } /* A non-zero return value will cause rxe_do_task to - * exit its loop and end the tasklet. A zero return + * exit its loop and end the work item. A zero return * will continue looping and return to rxe_responder */ done: diff --git a/drivers/infiniband/sw/rxe/rxe_task.c b/drivers/infiniband/sw/rxe/rxe_task.c index fb9a6bc8e62047e7dff8b93ca146fb9d0d78f1b4..1501120d4f5241dcca89120c37cb90883811165c 100644 --- a/drivers/infiniband/sw/rxe/rxe_task.c +++ b/drivers/infiniband/sw/rxe/rxe_task.c @@ -6,8 +6,24 @@ #include "rxe.h" +static struct workqueue_struct *rxe_wq; + +int rxe_alloc_wq(void) +{ + rxe_wq = alloc_workqueue("rxe_wq", WQ_UNBOUND, WQ_MAX_ACTIVE); + if (!rxe_wq) + return -ENOMEM; + + return 0; +} + +void rxe_destroy_wq(void) +{ + destroy_workqueue(rxe_wq); +} + /* Check if task is idle i.e. not running, not scheduled in - * tasklet queue and not draining. If so move to busy to + * work queue and not draining. If so move to busy to * reserve a slot in do_task() by setting to busy and taking * a qp reference to cover the gap from now until the task finishes. * state will move out of busy if task returns a non zero value @@ -21,9 +37,6 @@ static bool __reserve_if_idle(struct rxe_task *task) { WARN_ON(rxe_read(task->qp) <= 0); - if (task->tasklet.state & BIT(TASKLET_STATE_SCHED)) - return false; - if (task->state == TASK_STATE_IDLE) { rxe_get(task->qp); task->state = TASK_STATE_BUSY; @@ -38,7 +51,7 @@ static bool __reserve_if_idle(struct rxe_task *task) } /* check if task is idle or drained and not currently - * scheduled in the tasklet queue. This routine is + * scheduled in the work queue. This routine is * called by rxe_cleanup_task or rxe_disable_task to * see if the queue is empty. * Context: caller should hold task->lock. @@ -46,7 +59,7 @@ static bool __reserve_if_idle(struct rxe_task *task) */ static bool __is_done(struct rxe_task *task) { - if (task->tasklet.state & BIT(TASKLET_STATE_SCHED)) + if (work_pending(&task->work)) return false; if (task->state == TASK_STATE_IDLE || @@ -77,23 +90,23 @@ static bool is_done(struct rxe_task *task) * schedules the task. They must call __reserve_if_idle to * move the task to busy before calling or scheduling. * The task can also be moved to drained or invalid - * by calls to rxe-cleanup_task or rxe_disable_task. + * by calls to rxe_cleanup_task or rxe_disable_task. * In that case tasks which get here are not executed but * just flushed. The tasks are designed to look to see if - * there is work to do and do part of it before returning + * there is work to do and then do part of it before returning * here with a return value of zero until all the work - * has been consumed then it retuens a non-zero value. + * has been consumed then it returns a non-zero value. * The number of times the task can be run is limited by * max iterations so one task cannot hold the cpu forever. + * If the limit is hit and work remains the task is rescheduled. */ -static void do_task(struct tasklet_struct *t) +static void do_task(struct rxe_task *task) { - int cont; - int ret; - struct rxe_task *task = from_tasklet(task, t, tasklet); unsigned int iterations; unsigned long flags; int resched = 0; + int cont; + int ret; WARN_ON(rxe_read(task->qp) <= 0); @@ -115,25 +128,22 @@ static void do_task(struct tasklet_struct *t) } while (ret == 0 && iterations-- > 0); spin_lock_irqsave(&task->lock, flags); + /* we're not done yet but we ran out of iterations. + * yield the cpu and reschedule the task + */ + if (!ret) { + task->state = TASK_STATE_IDLE; + resched = 1; + goto exit; + } + switch (task->state) { case TASK_STATE_BUSY: - if (ret) { - task->state = TASK_STATE_IDLE; - } else { - /* This can happen if the client - * can add work faster than the - * tasklet can finish it. - * Reschedule the tasklet and exit - * the loop to give up the cpu - */ - task->state = TASK_STATE_IDLE; - resched = 1; - } + task->state = TASK_STATE_IDLE; break; - /* someone tried to run the task since the last time we called - * func, so we will call one more time regardless of the - * return value + /* someone tried to schedule the task while we + * were running, keep going */ case TASK_STATE_ARMED: task->state = TASK_STATE_BUSY; @@ -141,22 +151,24 @@ static void do_task(struct tasklet_struct *t) break; case TASK_STATE_DRAINING: - if (ret) - task->state = TASK_STATE_DRAINED; - else - cont = 1; + task->state = TASK_STATE_DRAINED; break; default: WARN_ON(1); - rxe_info_qp(task->qp, "unexpected task state = %d", task->state); + rxe_dbg_qp(task->qp, "unexpected task state = %d", + task->state); + task->state = TASK_STATE_IDLE; } +exit: if (!cont) { task->num_done++; if (WARN_ON(task->num_done != task->num_sched)) - rxe_err_qp(task->qp, "%ld tasks scheduled, %ld tasks done", - task->num_sched, task->num_done); + rxe_dbg_qp( + task->qp, + "%ld tasks scheduled, %ld tasks done", + task->num_sched, task->num_done); } spin_unlock_irqrestore(&task->lock, flags); } while (cont); @@ -169,6 +181,12 @@ static void do_task(struct tasklet_struct *t) rxe_put(task->qp); } +/* wrapper around do_task to fix argument for work queue */ +static void do_work(struct work_struct *work) +{ + do_task(container_of(work, struct rxe_task, work)); +} + int rxe_init_task(struct rxe_task *task, struct rxe_qp *qp, int (*func)(struct rxe_qp *)) { @@ -176,11 +194,9 @@ int rxe_init_task(struct rxe_task *task, struct rxe_qp *qp, task->qp = qp; task->func = func; - - tasklet_setup(&task->tasklet, do_task); - task->state = TASK_STATE_IDLE; spin_lock_init(&task->lock); + INIT_WORK(&task->work, do_work); return 0; } @@ -213,8 +229,6 @@ void rxe_cleanup_task(struct rxe_task *task) while (!is_done(task)) cond_resched(); - tasklet_kill(&task->tasklet); - spin_lock_irqsave(&task->lock, flags); task->state = TASK_STATE_INVALID; spin_unlock_irqrestore(&task->lock, flags); @@ -226,7 +240,7 @@ void rxe_cleanup_task(struct rxe_task *task) void rxe_run_task(struct rxe_task *task) { unsigned long flags; - int run; + bool run; WARN_ON(rxe_read(task->qp) <= 0); @@ -235,11 +249,11 @@ void rxe_run_task(struct rxe_task *task) spin_unlock_irqrestore(&task->lock, flags); if (run) - do_task(&task->tasklet); + do_task(task); } -/* schedule the task to run later as a tasklet. - * the tasklet)schedule call can be called holding +/* schedule the task to run later as a work queue entry. + * the queue_work call can be called holding * the lock. */ void rxe_sched_task(struct rxe_task *task) @@ -250,7 +264,7 @@ void rxe_sched_task(struct rxe_task *task) spin_lock_irqsave(&task->lock, flags); if (__reserve_if_idle(task)) - tasklet_schedule(&task->tasklet); + queue_work(rxe_wq, &task->work); spin_unlock_irqrestore(&task->lock, flags); } @@ -277,7 +291,9 @@ void rxe_disable_task(struct rxe_task *task) while (!is_done(task)) cond_resched(); - tasklet_disable(&task->tasklet); + spin_lock_irqsave(&task->lock, flags); + task->state = TASK_STATE_DRAINED; + spin_unlock_irqrestore(&task->lock, flags); } void rxe_enable_task(struct rxe_task *task) @@ -291,7 +307,7 @@ void rxe_enable_task(struct rxe_task *task) spin_unlock_irqrestore(&task->lock, flags); return; } + task->state = TASK_STATE_IDLE; - tasklet_enable(&task->tasklet); spin_unlock_irqrestore(&task->lock, flags); } diff --git a/drivers/infiniband/sw/rxe/rxe_task.h b/drivers/infiniband/sw/rxe/rxe_task.h index facb7c8e3729579ec5cab4da64181b10e68fb40e..a63e258b3d66353bce216a1bddc71699d08f5e0a 100644 --- a/drivers/infiniband/sw/rxe/rxe_task.h +++ b/drivers/infiniband/sw/rxe/rxe_task.h @@ -22,7 +22,7 @@ enum { * called again. */ struct rxe_task { - struct tasklet_struct tasklet; + struct work_struct work; int state; spinlock_t lock; struct rxe_qp *qp; @@ -32,6 +32,10 @@ struct rxe_task { long num_done; }; +int rxe_alloc_wq(void); + +void rxe_destroy_wq(void); + /* * init rxe_task structure * qp => parameter to pass to func diff --git a/drivers/infiniband/sw/rxe/rxe_verbs.c b/drivers/infiniband/sw/rxe/rxe_verbs.c index 4d8f6b8051ff7db5509b2e9961af54c1479373cb..903f0b71447e6d059334962deeb71d4ba3a51819 100644 --- a/drivers/infiniband/sw/rxe/rxe_verbs.c +++ b/drivers/infiniband/sw/rxe/rxe_verbs.c @@ -1182,9 +1182,7 @@ static int rxe_req_notify_cq(struct ib_cq *ibcq, enum ib_cq_notify_flags flags) unsigned long irq_flags; spin_lock_irqsave(&cq->cq_lock, irq_flags); - if (cq->notify != IB_CQ_NEXT_COMP) - cq->notify = flags & IB_CQ_SOLICITED_MASK; - + cq->notify |= flags & IB_CQ_SOLICITED_MASK; empty = queue_empty(cq->queue, QUEUE_TYPE_TO_ULP); if ((flags & IB_CQ_REPORT_MISSED_EVENTS) && !empty) @@ -1261,6 +1259,12 @@ static struct ib_mr *rxe_reg_user_mr(struct ib_pd *ibpd, u64 start, struct rxe_mr *mr; int err, cleanup_err; + if (access & ~RXE_ACCESS_SUPPORTED_MR) { + rxe_err_pd(pd, "access = %#x not supported (%#x)", access, + RXE_ACCESS_SUPPORTED_MR); + return ERR_PTR(-EOPNOTSUPP); + } + mr = kzalloc(sizeof(*mr), GFP_KERNEL); if (!mr) return ERR_PTR(-ENOMEM); @@ -1294,6 +1298,40 @@ static struct ib_mr *rxe_reg_user_mr(struct ib_pd *ibpd, u64 start, return ERR_PTR(err); } +static struct ib_mr *rxe_rereg_user_mr(struct ib_mr *ibmr, int flags, + u64 start, u64 length, u64 iova, + int access, struct ib_pd *ibpd, + struct ib_udata *udata) +{ + struct rxe_mr *mr = to_rmr(ibmr); + struct rxe_pd *old_pd = to_rpd(ibmr->pd); + struct rxe_pd *pd = to_rpd(ibpd); + + /* for now only support the two easy cases: + * rereg_pd and rereg_access + */ + if (flags & ~RXE_MR_REREG_SUPPORTED) { + rxe_err_mr(mr, "flags = %#x not supported", flags); + return ERR_PTR(-EOPNOTSUPP); + } + + if (flags & IB_MR_REREG_PD) { + rxe_put(old_pd); + rxe_get(pd); + mr->ibmr.pd = ibpd; + } + + if (flags & IB_MR_REREG_ACCESS) { + if (access & ~RXE_ACCESS_SUPPORTED_MR) { + rxe_err_mr(mr, "access = %#x not supported", access); + return ERR_PTR(-EOPNOTSUPP); + } + mr->access = access; + } + + return NULL; +} + static struct ib_mr *rxe_alloc_mr(struct ib_pd *ibpd, enum ib_mr_type mr_type, u32 max_num_sg) { @@ -1357,7 +1395,7 @@ static int rxe_dereg_mr(struct ib_mr *ibmr, struct ib_udata *udata) if (cleanup_err) rxe_err_mr(mr, "cleanup failed, err = %d", cleanup_err); - kfree_rcu(mr); + kfree_rcu_mightsleep(mr); return 0; err_out: @@ -1446,6 +1484,7 @@ static const struct ib_device_ops rxe_dev_ops = { .query_srq = rxe_query_srq, .reg_user_mr = rxe_reg_user_mr, .req_notify_cq = rxe_req_notify_cq, + .rereg_user_mr = rxe_rereg_user_mr, .resize_cq = rxe_resize_cq, INIT_RDMA_OBJ_SIZE(ib_ah, rxe_ah, ibah), diff --git a/drivers/infiniband/sw/rxe/rxe_verbs.h b/drivers/infiniband/sw/rxe/rxe_verbs.h index 26a20f088692876b6bfa2a747c2383135c61e4c1..ccb9d19ffe8ab37b907dec8f03649b3e754ce7a8 100644 --- a/drivers/infiniband/sw/rxe/rxe_verbs.h +++ b/drivers/infiniband/sw/rxe/rxe_verbs.h @@ -253,6 +253,22 @@ struct rxe_qp { struct execute_work cleanup_work; }; +enum { + RXE_ACCESS_REMOTE = IB_ACCESS_REMOTE_READ + | IB_ACCESS_REMOTE_WRITE + | IB_ACCESS_REMOTE_ATOMIC, + RXE_ACCESS_SUPPORTED_MR = RXE_ACCESS_REMOTE + | IB_ACCESS_LOCAL_WRITE + | IB_ACCESS_MW_BIND + | IB_ACCESS_ON_DEMAND + | IB_ACCESS_FLUSH_GLOBAL + | IB_ACCESS_FLUSH_PERSISTENT + | IB_ACCESS_OPTIONAL, + RXE_ACCESS_SUPPORTED_QP = RXE_ACCESS_SUPPORTED_MR, + RXE_ACCESS_SUPPORTED_MW = RXE_ACCESS_SUPPORTED_MR + | IB_ZERO_BASED, +}; + enum rxe_mr_state { RXE_MR_STATE_INVALID, RXE_MR_STATE_FREE, @@ -269,6 +285,11 @@ enum rxe_mr_lookup_type { RXE_LOOKUP_REMOTE, }; +enum rxe_rereg { + RXE_MR_REREG_SUPPORTED = IB_MR_REREG_PD + | IB_MR_REREG_ACCESS, +}; + static inline int rkey_is_mw(u32 rkey) { u32 index = rkey >> 8; diff --git a/drivers/infiniband/sw/siw/siw_mem.c b/drivers/infiniband/sw/siw/siw_mem.c index f51ab2ccf1511f6bed99b3d7a003417e44ab7a53..e6e25f15567d43bd3b382db609d15bef46788eb1 100644 --- a/drivers/infiniband/sw/siw/siw_mem.c +++ b/drivers/infiniband/sw/siw/siw_mem.c @@ -422,7 +422,7 @@ struct siw_umem *siw_umem_get(u64 start, u64 len, bool writable) umem->page_chunk[i].plist = plist; while (nents) { rv = pin_user_pages(first_page_va, nents, foll_flags, - plist, NULL); + plist); if (rv < 0) goto out_sem_up; diff --git a/drivers/infiniband/sw/siw/siw_qp_tx.c b/drivers/infiniband/sw/siw/siw_qp_tx.c index 4b292e0504f1a1229699ea0aded1cfe0225d8bf2..7c7a51d36d0cda2f41f395143250e0afffef02f9 100644 --- a/drivers/infiniband/sw/siw/siw_qp_tx.c +++ b/drivers/infiniband/sw/siw/siw_qp_tx.c @@ -312,7 +312,7 @@ static int siw_tx_ctrl(struct siw_iwarp_tx *c_tx, struct socket *s, } /* - * 0copy TCP transmit interface: Use do_tcp_sendpages. + * 0copy TCP transmit interface: Use MSG_SPLICE_PAGES. * * Using sendpage to push page by page appears to be less efficient * than using sendmsg, even if data are copied. @@ -323,20 +323,26 @@ static int siw_tx_ctrl(struct siw_iwarp_tx *c_tx, struct socket *s, static int siw_tcp_sendpages(struct socket *s, struct page **page, int offset, size_t size) { + struct bio_vec bvec; + struct msghdr msg = { + .msg_flags = (MSG_MORE | MSG_DONTWAIT | MSG_SPLICE_PAGES), + }; struct sock *sk = s->sk; - int i = 0, rv = 0, sent = 0, - flags = MSG_MORE | MSG_DONTWAIT | MSG_SENDPAGE_NOTLAST; + int i = 0, rv = 0, sent = 0; while (size) { size_t bytes = min_t(size_t, PAGE_SIZE - offset, size); if (size + offset <= PAGE_SIZE) - flags = MSG_MORE | MSG_DONTWAIT; + msg.msg_flags &= ~MSG_MORE; tcp_rate_check_app_limited(sk); + bvec_set_page(&bvec, page[i], bytes, offset); + iov_iter_bvec(&msg.msg_iter, ITER_SOURCE, &bvec, 1, size); + try_page_again: lock_sock(sk); - rv = do_tcp_sendpages(sk, page[i], offset, bytes, flags); + rv = tcp_sendmsg_locked(sk, &msg, size); release_sock(sk); if (rv > 0) { diff --git a/drivers/infiniband/ulp/rtrs/rtrs-clt.c b/drivers/infiniband/ulp/rtrs/rtrs-clt.c index cfb50bfe53c3c9a1eeecd5398d2883ecdeb5a2cf..b32941dd67cb90d5b1260369d227316b418a1ec3 100644 --- a/drivers/infiniband/ulp/rtrs/rtrs-clt.c +++ b/drivers/infiniband/ulp/rtrs/rtrs-clt.c @@ -1710,7 +1710,6 @@ static int create_con_cq_qp(struct rtrs_clt_con *con) return -ENOMEM; con->queue_num = cq_num; } - cq_num = max_send_wr + max_recv_wr; cq_vector = con->cpu % clt_path->s.dev->ib_dev->num_comp_vectors; if (con->c.cid >= clt_path->s.irq_con_num) err = rtrs_cq_qp_create(&clt_path->s, &con->c, max_send_sge, diff --git a/drivers/input/Kconfig b/drivers/input/Kconfig index 735f90b74ee5ad44b34e85ad9c7888ec2b6c3261..3bdbd34314b3495ab39e8b0212c0cc643bd8406c 100644 --- a/drivers/input/Kconfig +++ b/drivers/input/Kconfig @@ -168,7 +168,7 @@ config INPUT_EVBUG config INPUT_KUNIT_TEST tristate "KUnit tests for Input" if !KUNIT_ALL_TESTS - depends on INPUT && KUNIT=y + depends on INPUT && KUNIT default KUNIT_ALL_TESTS help Say Y here if you want to build the KUnit tests for the input diff --git a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c index db58a01b23d33034e868963ef98f9bc18cbb4021..a1443320b419554a6199589e27ff634a28c15e05 100644 --- a/drivers/input/gameport/gameport.c +++ b/drivers/input/gameport/gameport.c @@ -11,6 +11,7 @@ #include #include +#include #include #include #include @@ -21,8 +22,6 @@ #include #include -/*#include */ - MODULE_AUTHOR("Vojtech Pavlik "); MODULE_DESCRIPTION("Generic gameport layer"); MODULE_LICENSE("GPL"); @@ -518,6 +517,16 @@ void gameport_set_phys(struct gameport *gameport, const char *fmt, ...) } EXPORT_SYMBOL(gameport_set_phys); +static void gameport_default_trigger(struct gameport *gameport) +{ + outb(0xff, gameport->io); +} + +static unsigned char gameport_default_read(struct gameport *gameport) +{ + return inb(gameport->io); +} + /* * Prepare gameport port for registration. */ @@ -536,6 +545,11 @@ static void gameport_init_port(struct gameport *gameport) if (gameport->parent) gameport->dev.parent = &gameport->parent->dev; + if (!gameport->trigger) + gameport->trigger = gameport_default_trigger; + if (!gameport->read) + gameport->read = gameport_default_read; + INIT_LIST_HEAD(&gameport->node); spin_lock_init(&gameport->timer_lock); timer_setup(&gameport->poll_timer, gameport_run_poll_handler, 0); diff --git a/drivers/input/input.c b/drivers/input/input.c index 641eb86f276e6da05e86ea1ddd9ae10069cefe7a..8c5fdb0f858ab5102926c0f6858f6a0f022c44b2 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -190,6 +190,7 @@ static int input_handle_abs_event(struct input_dev *dev, unsigned int code, int *pval) { struct input_mt *mt = dev->mt; + bool is_new_slot = false; bool is_mt_event; int *pold; @@ -210,6 +211,7 @@ static int input_handle_abs_event(struct input_dev *dev, pold = &dev->absinfo[code].value; } else if (mt) { pold = &mt->slots[mt->slot].abs[code - ABS_MT_FIRST]; + is_new_slot = mt->slot != dev->absinfo[ABS_MT_SLOT].value; } else { /* * Bypass filtering for multi-touch events when @@ -228,8 +230,8 @@ static int input_handle_abs_event(struct input_dev *dev, } /* Flush pending "slot" event */ - if (is_mt_event && mt && mt->slot != input_abs_get_val(dev, ABS_MT_SLOT)) { - input_abs_set_val(dev, ABS_MT_SLOT, mt->slot); + if (is_new_slot) { + dev->absinfo[ABS_MT_SLOT].value = mt->slot; return INPUT_PASS_TO_HANDLERS | INPUT_SLOT; } diff --git a/drivers/input/joystick/Kconfig b/drivers/input/joystick/Kconfig index 04ca3d1c28162f87288882d1ec0f4fdc7d7a2a15..ac6925ce836670ead078f44816e97fc2fe7008ab 100644 --- a/drivers/input/joystick/Kconfig +++ b/drivers/input/joystick/Kconfig @@ -292,33 +292,33 @@ config JOYSTICK_JOYDUMP module will be called joydump. config JOYSTICK_XPAD - tristate "X-Box gamepad support" + tristate "Xbox gamepad support" depends on USB_ARCH_HAS_HCD select USB help - Say Y here if you want to use the X-Box pad with your computer. + Say Y here if you want to use Xbox pads with your computer. Make sure to say Y to "Joystick support" (CONFIG_INPUT_JOYDEV) and/or "Event interface support" (CONFIG_INPUT_EVDEV) as well. - For information about how to connect the X-Box pad to USB, see + For information about how to connect the Xbox pad to USB, see . To compile this driver as a module, choose M here: the module will be called xpad. config JOYSTICK_XPAD_FF - bool "X-Box gamepad rumble support" + bool "Xbox gamepad rumble support" depends on JOYSTICK_XPAD && INPUT select INPUT_FF_MEMLESS help - Say Y here if you want to take advantage of xbox 360 rumble features. + Say Y here if you want to take advantage of Xbox 360 rumble features. config JOYSTICK_XPAD_LEDS - bool "LED Support for Xbox360 controller 'BigX' LED" + bool "LED Support for the Xbox 360 controller Guide button" depends on JOYSTICK_XPAD && (LEDS_CLASS=y || LEDS_CLASS=JOYSTICK_XPAD) help This option enables support for the LED which surrounds the Big X on - XBox 360 controller. + Xbox 360 controllers. config JOYSTICK_WALKERA0701 tristate "Walkera WK-0701 RC transmitter" diff --git a/drivers/input/joystick/as5011.c b/drivers/input/joystick/as5011.c index 3b88f0b49e01b689a31cbd95c84d7ee69f7bc407..bf8b1cc0ea9c7681aab5feb4d968607866c6f70f 100644 --- a/drivers/input/joystick/as5011.c +++ b/drivers/input/joystick/as5011.c @@ -348,7 +348,7 @@ static struct i2c_driver as5011_driver = { .driver = { .name = "as5011", }, - .probe_new = as5011_probe, + .probe = as5011_probe, .remove = as5011_remove, .id_table = as5011_id, }; diff --git a/drivers/input/joystick/qwiic-joystick.c b/drivers/input/joystick/qwiic-joystick.c index d4da31c0616c3a886d558d9e474560c363f1e7d4..7d88d76b14d6c92f8236e3bfac70c33925f38f4b 100644 --- a/drivers/input/joystick/qwiic-joystick.c +++ b/drivers/input/joystick/qwiic-joystick.c @@ -137,7 +137,7 @@ static struct i2c_driver qwiic_driver = { .of_match_table = of_match_ptr(of_qwiic_match), }, .id_table = qwiic_id_table, - .probe_new = qwiic_probe, + .probe = qwiic_probe, }; module_i2c_driver(qwiic_driver); diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c index f33622fe946f657380155fd1db111ab9d23e39f3..cdb193317c3b6825af9b4f84317b4af52fa6684a 100644 --- a/drivers/input/joystick/xpad.c +++ b/drivers/input/joystick/xpad.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* - * X-Box gamepad driver + * Xbox gamepad driver * * Copyright (c) 2002 Marko Friedemann * 2004 Oliver Schwartz , @@ -23,8 +23,8 @@ * - ITO Takayuki for providing essential xpad information on his website * - Vojtech Pavlik - iforce driver / input subsystem * - Greg Kroah-Hartman - usb-skeleton driver - * - XBOX Linux project - extra USB id's - * - Pekka Pöyry (quantus) - Xbox One controller reverse engineering + * - Xbox Linux project - extra USB IDs + * - Pekka Pöyry (quantus) - Xbox One controller reverse-engineering * * TODO: * - fine tune axes (especially trigger axes) @@ -52,7 +52,7 @@ * 2002-07-17 - 0.0.5 : simplified d-pad handling * * 2004-10-02 - 0.0.6 : DDR pad support - * - borrowed from the XBOX linux kernel + * - borrowed from the Xbox Linux kernel * - USB id's for commonly used dance pads are present * - dance pads will map D-PAD to buttons, not axes * - pass the module paramater 'dpad_to_buttons' to force @@ -454,49 +454,49 @@ static const signed short xpad_btn_paddles[] = { { XPAD_XBOXONE_VENDOR_PROTOCOL((vend), 208) } static const struct usb_device_id xpad_table[] = { - { USB_INTERFACE_INFO('X', 'B', 0) }, /* X-Box USB-IF not approved class */ - XPAD_XBOX360_VENDOR(0x0079), /* GPD Win 2 Controller */ + { USB_INTERFACE_INFO('X', 'B', 0) }, /* Xbox USB-IF not-approved class */ + XPAD_XBOX360_VENDOR(0x0079), /* GPD Win 2 controller */ XPAD_XBOX360_VENDOR(0x03eb), /* Wooting Keyboards (Legacy) */ - XPAD_XBOX360_VENDOR(0x044f), /* Thrustmaster X-Box 360 controllers */ - XPAD_XBOX360_VENDOR(0x045e), /* Microsoft X-Box 360 controllers */ - XPAD_XBOXONE_VENDOR(0x045e), /* Microsoft X-Box One controllers */ - XPAD_XBOX360_VENDOR(0x046d), /* Logitech X-Box 360 style controllers */ + XPAD_XBOX360_VENDOR(0x044f), /* Thrustmaster Xbox 360 controllers */ + XPAD_XBOX360_VENDOR(0x045e), /* Microsoft Xbox 360 controllers */ + XPAD_XBOXONE_VENDOR(0x045e), /* Microsoft Xbox One controllers */ + XPAD_XBOX360_VENDOR(0x046d), /* Logitech Xbox 360-style controllers */ XPAD_XBOX360_VENDOR(0x056e), /* Elecom JC-U3613M */ XPAD_XBOX360_VENDOR(0x06a3), /* Saitek P3600 */ - XPAD_XBOX360_VENDOR(0x0738), /* Mad Catz X-Box 360 controllers */ + XPAD_XBOX360_VENDOR(0x0738), /* Mad Catz Xbox 360 controllers */ { USB_DEVICE(0x0738, 0x4540) }, /* Mad Catz Beat Pad */ XPAD_XBOXONE_VENDOR(0x0738), /* Mad Catz FightStick TE 2 */ - XPAD_XBOX360_VENDOR(0x07ff), /* Mad Catz GamePad */ + XPAD_XBOX360_VENDOR(0x07ff), /* Mad Catz Gamepad */ XPAD_XBOX360_VENDOR(0x0c12), /* Zeroplus X-Box 360 controllers */ - XPAD_XBOX360_VENDOR(0x0e6f), /* 0x0e6f X-Box 360 controllers */ - XPAD_XBOXONE_VENDOR(0x0e6f), /* 0x0e6f X-Box One controllers */ - XPAD_XBOX360_VENDOR(0x0f0d), /* Hori Controllers */ - XPAD_XBOXONE_VENDOR(0x0f0d), /* Hori Controllers */ - XPAD_XBOX360_VENDOR(0x1038), /* SteelSeries Controllers */ + XPAD_XBOX360_VENDOR(0x0e6f), /* 0x0e6f Xbox 360 controllers */ + XPAD_XBOXONE_VENDOR(0x0e6f), /* 0x0e6f Xbox One controllers */ + XPAD_XBOX360_VENDOR(0x0f0d), /* Hori controllers */ + XPAD_XBOXONE_VENDOR(0x0f0d), /* Hori controllers */ + XPAD_XBOX360_VENDOR(0x1038), /* SteelSeries controllers */ XPAD_XBOXONE_VENDOR(0x10f5), /* Turtle Beach Controllers */ XPAD_XBOX360_VENDOR(0x11c9), /* Nacon GC100XF */ XPAD_XBOX360_VENDOR(0x1209), /* Ardwiino Controllers */ - XPAD_XBOX360_VENDOR(0x12ab), /* X-Box 360 dance pads */ - XPAD_XBOX360_VENDOR(0x1430), /* RedOctane X-Box 360 controllers */ - XPAD_XBOX360_VENDOR(0x146b), /* BigBen Interactive Controllers */ + XPAD_XBOX360_VENDOR(0x12ab), /* Xbox 360 dance pads */ + XPAD_XBOX360_VENDOR(0x1430), /* RedOctane Xbox 360 controllers */ + XPAD_XBOX360_VENDOR(0x146b), /* Bigben Interactive controllers */ XPAD_XBOX360_VENDOR(0x1532), /* Razer Sabertooth */ XPAD_XBOXONE_VENDOR(0x1532), /* Razer Wildcat */ - XPAD_XBOX360_VENDOR(0x15e4), /* Numark X-Box 360 controllers */ - XPAD_XBOX360_VENDOR(0x162e), /* Joytech X-Box 360 controllers */ + XPAD_XBOX360_VENDOR(0x15e4), /* Numark Xbox 360 controllers */ + XPAD_XBOX360_VENDOR(0x162e), /* Joytech Xbox 360 controllers */ XPAD_XBOX360_VENDOR(0x1689), /* Razer Onza */ XPAD_XBOX360_VENDOR(0x1949), /* Amazon controllers */ - XPAD_XBOX360_VENDOR(0x1bad), /* Harminix Rock Band Guitar and Drums */ - XPAD_XBOX360_VENDOR(0x20d6), /* PowerA Controllers */ - XPAD_XBOXONE_VENDOR(0x20d6), /* PowerA Controllers */ - XPAD_XBOX360_VENDOR(0x24c6), /* PowerA Controllers */ - XPAD_XBOXONE_VENDOR(0x24c6), /* PowerA Controllers */ + XPAD_XBOX360_VENDOR(0x1bad), /* Harmonix Rock Band guitar and drums */ + XPAD_XBOX360_VENDOR(0x20d6), /* PowerA controllers */ + XPAD_XBOXONE_VENDOR(0x20d6), /* PowerA controllers */ + XPAD_XBOX360_VENDOR(0x24c6), /* PowerA controllers */ + XPAD_XBOXONE_VENDOR(0x24c6), /* PowerA controllers */ XPAD_XBOX360_VENDOR(0x2563), /* OneXPlayer Gamepad */ XPAD_XBOX360_VENDOR(0x260d), /* Dareu H101 */ XPAD_XBOX360_VENDOR(0x2c22), /* Qanba Controllers */ XPAD_XBOX360_VENDOR(0x2dc8), /* 8BitDo Pro 2 Wired Controller */ XPAD_XBOXONE_VENDOR(0x2dc8), /* 8BitDo Pro 2 Wired Controller for Xbox */ - XPAD_XBOXONE_VENDOR(0x2e24), /* Hyperkin Duke X-Box One pad */ - XPAD_XBOX360_VENDOR(0x2f24), /* GameSir Controllers */ + XPAD_XBOXONE_VENDOR(0x2e24), /* Hyperkin Duke Xbox One pad */ + XPAD_XBOX360_VENDOR(0x2f24), /* GameSir controllers */ XPAD_XBOX360_VENDOR(0x31e3), /* Wooting Keyboards */ XPAD_XBOX360_VENDOR(0x3285), /* Nacon GC-100 */ { } @@ -724,7 +724,7 @@ static void xpad360w_poweroff_controller(struct usb_xpad *xpad); * Completes a request by converting the data into events for the * input subsystem. * - * The used report descriptor was taken from ITO Takayukis website: + * The used report descriptor was taken from ITO Takayuki's website: * http://euc.jp/periphs/xbox-controller.ja.html */ static void xpad_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *data) @@ -1569,7 +1569,7 @@ struct xpad_led { }; /* - * set the LEDs on Xbox360 / Wireless Controllers + * set the LEDs on Xbox 360 / Wireless Controllers * @param command * 0: off * 1: all blink, then previous setting @@ -2229,5 +2229,5 @@ static struct usb_driver xpad_driver = { module_usb_driver(xpad_driver); MODULE_AUTHOR("Marko Friedemann "); -MODULE_DESCRIPTION("X-Box pad driver"); +MODULE_DESCRIPTION("Xbox pad driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/input/keyboard/adp5588-keys.c b/drivers/input/keyboard/adp5588-keys.c index 72ae5ce7295651a98468ba23a98fb01d3cfed490..896a5a989ddcecca26dd5348d1742269e32b6b9b 100644 --- a/drivers/input/keyboard/adp5588-keys.c +++ b/drivers/input/keyboard/adp5588-keys.c @@ -866,7 +866,7 @@ static struct i2c_driver adp5588_driver = { .of_match_table = adp5588_of_match, .pm = pm_sleep_ptr(&adp5588_dev_pm_ops), }, - .probe_new = adp5588_probe, + .probe = adp5588_probe, .remove = adp5588_remove, .id_table = adp5588_id, }; diff --git a/drivers/input/keyboard/adp5589-keys.c b/drivers/input/keyboard/adp5589-keys.c index 38d7073863a872d52e3eb0e53a654c53b72a95f2..8996e00cd63a8203ec53d46ccb922c21ddb47355 100644 --- a/drivers/input/keyboard/adp5589-keys.c +++ b/drivers/input/keyboard/adp5589-keys.c @@ -1054,7 +1054,7 @@ static struct i2c_driver adp5589_driver = { .name = KBUILD_MODNAME, .pm = pm_sleep_ptr(&adp5589_dev_pm_ops), }, - .probe_new = adp5589_probe, + .probe = adp5589_probe, .id_table = adp5589_id, }; diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c index 246958795f606ea72d0a5855d0f21ccc675930be..c92e544c792df830ed7814c101a8f0b3664f8a2f 100644 --- a/drivers/input/keyboard/atkbd.c +++ b/drivers/input/keyboard/atkbd.c @@ -309,12 +309,19 @@ static ssize_t atkbd_show_function_row_physmap(struct atkbd *atkbd, char *buf) return vivaldi_function_row_physmap_show(&atkbd->vdata, buf); } +static struct atkbd *atkbd_from_serio(struct serio *serio) +{ + struct ps2dev *ps2dev = serio_get_drvdata(serio); + + return container_of(ps2dev, struct atkbd, ps2dev); +} + static umode_t atkbd_attr_is_visible(struct kobject *kobj, struct attribute *attr, int i) { struct device *dev = kobj_to_dev(kobj); struct serio *serio = to_serio_port(dev); - struct atkbd *atkbd = serio_get_drvdata(serio); + struct atkbd *atkbd = atkbd_from_serio(serio); if (attr == &atkbd_attr_function_row_physmap.attr && !atkbd->vdata.num_function_row_keys) @@ -392,46 +399,60 @@ static unsigned int atkbd_compat_scancode(struct atkbd *atkbd, unsigned int code } /* - * atkbd_interrupt(). Here takes place processing of data received from - * the keyboard into events. + * Tries to handle frame or parity error by requesting the keyboard controller + * to resend the last byte. This historically not done on x86 as controllers + * there typically do not implement this command. */ - -static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data, - unsigned int flags) +static bool __maybe_unused atkbd_handle_frame_error(struct ps2dev *ps2dev, + u8 data, unsigned int flags) { - struct atkbd *atkbd = serio_get_drvdata(serio); - struct input_dev *dev = atkbd->dev; - unsigned int code = data; - int scroll = 0, hscroll = 0, click = -1; - int value; - unsigned short keycode; - - dev_dbg(&serio->dev, "Received %02x flags %02x\n", data, flags); + struct atkbd *atkbd = container_of(ps2dev, struct atkbd, ps2dev); + struct serio *serio = ps2dev->serio; -#if !defined(__i386__) && !defined (__x86_64__) - if ((flags & (SERIO_FRAME | SERIO_PARITY)) && (~flags & SERIO_TIMEOUT) && !atkbd->resend && atkbd->write) { + if ((flags & (SERIO_FRAME | SERIO_PARITY)) && + (~flags & SERIO_TIMEOUT) && + !atkbd->resend && atkbd->write) { dev_warn(&serio->dev, "Frame/parity error: %02x\n", flags); serio_write(serio, ATKBD_CMD_RESEND); atkbd->resend = true; - goto out; + return true; } if (!flags && data == ATKBD_RET_ACK) atkbd->resend = false; + + return false; +} + +static enum ps2_disposition atkbd_pre_receive_byte(struct ps2dev *ps2dev, + u8 data, unsigned int flags) +{ + struct serio *serio = ps2dev->serio; + + dev_dbg(&serio->dev, "Received %02x flags %02x\n", data, flags); + +#if !defined(__i386__) && !defined (__x86_64__) + if (atkbd_handle_frame_error(ps2dev, data, flags)) + return PS2_IGNORE; #endif - if (unlikely(atkbd->ps2dev.flags & PS2_FLAG_ACK)) - if (ps2_handle_ack(&atkbd->ps2dev, data)) - goto out; + return PS2_PROCESS; +} - if (unlikely(atkbd->ps2dev.flags & PS2_FLAG_CMD)) - if (ps2_handle_response(&atkbd->ps2dev, data)) - goto out; +static void atkbd_receive_byte(struct ps2dev *ps2dev, u8 data) +{ + struct serio *serio = ps2dev->serio; + struct atkbd *atkbd = container_of(ps2dev, struct atkbd, ps2dev); + struct input_dev *dev = atkbd->dev; + unsigned int code = data; + int scroll = 0, hscroll = 0, click = -1; + int value; + unsigned short keycode; pm_wakeup_event(&serio->dev, 0); if (!atkbd->enabled) - goto out; + return; input_event(dev, EV_MSC, MSC_RAW, code); @@ -453,16 +474,16 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data, case ATKBD_RET_BAT: atkbd->enabled = false; serio_reconnect(atkbd->ps2dev.serio); - goto out; + return; case ATKBD_RET_EMUL0: atkbd->emul = 1; - goto out; + return; case ATKBD_RET_EMUL1: atkbd->emul = 2; - goto out; + return; case ATKBD_RET_RELEASE: atkbd->release = true; - goto out; + return; case ATKBD_RET_ACK: case ATKBD_RET_NAK: if (printk_ratelimit()) @@ -470,18 +491,18 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data, "Spurious %s on %s. " "Some program might be trying to access hardware directly.\n", data == ATKBD_RET_ACK ? "ACK" : "NAK", serio->phys); - goto out; + return; case ATKBD_RET_ERR: atkbd->err_count++; dev_dbg(&serio->dev, "Keyboard on %s reports too many keys pressed.\n", serio->phys); - goto out; + return; } code = atkbd_compat_scancode(atkbd, code); if (atkbd->emul && --atkbd->emul) - goto out; + return; keycode = atkbd->keycode[code]; @@ -557,8 +578,6 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data, } atkbd->release = false; -out: - return IRQ_HANDLED; } static int atkbd_set_repeat_rate(struct atkbd *atkbd) @@ -909,7 +928,7 @@ static int atkbd_reset_state(struct atkbd *atkbd) static void atkbd_cleanup(struct serio *serio) { - struct atkbd *atkbd = serio_get_drvdata(serio); + struct atkbd *atkbd = atkbd_from_serio(serio); atkbd_disable(atkbd); ps2_command(&atkbd->ps2dev, NULL, ATKBD_CMD_RESET_DEF); @@ -922,7 +941,7 @@ static void atkbd_cleanup(struct serio *serio) static void atkbd_disconnect(struct serio *serio) { - struct atkbd *atkbd = serio_get_drvdata(serio); + struct atkbd *atkbd = atkbd_from_serio(serio); atkbd_disable(atkbd); @@ -1188,7 +1207,7 @@ static void atkbd_set_device_attrs(struct atkbd *atkbd) static void atkbd_parse_fwnode_data(struct serio *serio) { - struct atkbd *atkbd = serio_get_drvdata(serio); + struct atkbd *atkbd = atkbd_from_serio(serio); struct device *dev = &serio->dev; int n; @@ -1222,7 +1241,8 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv) goto fail1; atkbd->dev = dev; - ps2_init(&atkbd->ps2dev, serio); + ps2_init(&atkbd->ps2dev, serio, + atkbd_pre_receive_byte, atkbd_receive_byte); INIT_DELAYED_WORK(&atkbd->event_work, atkbd_event_work); mutex_init(&atkbd->mutex); @@ -1295,7 +1315,7 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv) static int atkbd_reconnect(struct serio *serio) { - struct atkbd *atkbd = serio_get_drvdata(serio); + struct atkbd *atkbd = atkbd_from_serio(serio); struct serio_driver *drv = serio->drv; int retval = -1; @@ -1378,7 +1398,7 @@ static struct serio_driver atkbd_drv = { }, .description = DRIVER_DESC, .id_table = atkbd_serio_ids, - .interrupt = atkbd_interrupt, + .interrupt = ps2_interrupt, .connect = atkbd_connect, .reconnect = atkbd_reconnect, .disconnect = atkbd_disconnect, @@ -1389,7 +1409,7 @@ static ssize_t atkbd_attr_show_helper(struct device *dev, char *buf, ssize_t (*handler)(struct atkbd *, char *)) { struct serio *serio = to_serio_port(dev); - struct atkbd *atkbd = serio_get_drvdata(serio); + struct atkbd *atkbd = atkbd_from_serio(serio); return handler(atkbd, buf); } @@ -1398,7 +1418,7 @@ static ssize_t atkbd_attr_set_helper(struct device *dev, const char *buf, size_t ssize_t (*handler)(struct atkbd *, const char *, size_t)) { struct serio *serio = to_serio_port(dev); - struct atkbd *atkbd = serio_get_drvdata(serio); + struct atkbd *atkbd = atkbd_from_serio(serio); int retval; retval = mutex_lock_interruptible(&atkbd->mutex); diff --git a/drivers/input/keyboard/cap11xx.c b/drivers/input/keyboard/cap11xx.c index 040696d0e49ccb03b20ef7afca6593c789a82b8e..1b4937dce6725f8a94da1eaec79d1987dc6920a6 100644 --- a/drivers/input/keyboard/cap11xx.c +++ b/drivers/input/keyboard/cap11xx.c @@ -518,7 +518,7 @@ static struct i2c_driver cap11xx_i2c_driver = { .of_match_table = cap11xx_dt_ids, }, .id_table = cap11xx_i2c_ids, - .probe_new = cap11xx_i2c_probe, + .probe = cap11xx_i2c_probe, }; module_i2c_driver(cap11xx_i2c_driver); diff --git a/drivers/input/keyboard/cypress-sf.c b/drivers/input/keyboard/cypress-sf.c index 686388f40317b630850173c1980fba54d2589372..2bacd9d80ecf717836eaffd5075d4a10c2dec063 100644 --- a/drivers/input/keyboard/cypress-sf.c +++ b/drivers/input/keyboard/cypress-sf.c @@ -229,7 +229,7 @@ static struct i2c_driver cypress_sf_driver = { .of_match_table = of_match_ptr(cypress_sf_of_match), }, .id_table = cypress_sf_id_table, - .probe_new = cypress_sf_probe, + .probe = cypress_sf_probe, }; module_i2c_driver(cypress_sf_driver); diff --git a/drivers/input/keyboard/dlink-dir685-touchkeys.c b/drivers/input/keyboard/dlink-dir685-touchkeys.c index ddba2bc861da6416629aaf7b75fea72840aefc01..6c065eff5a5a5f29645a63b8476063cc2321eab7 100644 --- a/drivers/input/keyboard/dlink-dir685-touchkeys.c +++ b/drivers/input/keyboard/dlink-dir685-touchkeys.c @@ -145,7 +145,7 @@ static struct i2c_driver dir685_tk_i2c_driver = { .name = "dlink-dir685-touchkeys", .of_match_table = of_match_ptr(dir685_tk_of_match), }, - .probe_new = dir685_tk_probe, + .probe = dir685_tk_probe, .id_table = dir685_tk_id, }; module_i2c_driver(dir685_tk_i2c_driver); diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c index c42f86ad0766b560f54ca45b32dd9341fea4ea02..c928829a8b0cea53b35899f2e6f99dec9b7773f7 100644 --- a/drivers/input/keyboard/gpio_keys.c +++ b/drivers/input/keyboard/gpio_keys.c @@ -456,7 +456,7 @@ static enum hrtimer_restart gpio_keys_irq_timer(struct hrtimer *t) struct input_dev *input = bdata->input; if (bdata->key_pressed) { - input_event(input, EV_KEY, *bdata->code, 0); + input_report_key(input, *bdata->code, 0); input_sync(input); bdata->key_pressed = false; } @@ -478,11 +478,11 @@ static irqreturn_t gpio_keys_irq_isr(int irq, void *dev_id) if (bdata->button->wakeup) pm_wakeup_event(bdata->input->dev.parent, 0); - input_event(input, EV_KEY, *bdata->code, 1); + input_report_key(input, *bdata->code, 1); input_sync(input); if (!bdata->release_delay) { - input_event(input, EV_KEY, *bdata->code, 0); + input_report_key(input, *bdata->code, 0); input_sync(input); goto out; } diff --git a/drivers/input/keyboard/lm8323.c b/drivers/input/keyboard/lm8323.c index 5df4d5a7ed9e259811b7c5f58e2a05a40271991f..3964f6e0f6afad9b59147a95035ea850ed760e5b 100644 --- a/drivers/input/keyboard/lm8323.c +++ b/drivers/input/keyboard/lm8323.c @@ -826,7 +826,7 @@ static struct i2c_driver lm8323_i2c_driver = { .name = "lm8323", .pm = pm_sleep_ptr(&lm8323_pm_ops), }, - .probe_new = lm8323_probe, + .probe = lm8323_probe, .remove = lm8323_remove, .id_table = lm8323_id, }; diff --git a/drivers/input/keyboard/lm8333.c b/drivers/input/keyboard/lm8333.c index 7457c3220f90a8143fa67cbd2df254130ef008e6..c9f05764e36df1049331fec9903639235085afb2 100644 --- a/drivers/input/keyboard/lm8333.c +++ b/drivers/input/keyboard/lm8333.c @@ -218,7 +218,7 @@ static struct i2c_driver lm8333_driver = { .driver = { .name = "lm8333", }, - .probe_new = lm8333_probe, + .probe = lm8333_probe, .remove = lm8333_remove, .id_table = lm8333_id, }; diff --git a/drivers/input/keyboard/max7359_keypad.c b/drivers/input/keyboard/max7359_keypad.c index b363749d02e23bb1f63d3e71e7a3e563afdb3802..faab7691c21975805a04c374a3e63b357272edd1 100644 --- a/drivers/input/keyboard/max7359_keypad.c +++ b/drivers/input/keyboard/max7359_keypad.c @@ -280,7 +280,7 @@ static struct i2c_driver max7359_i2c_driver = { .name = "max7359", .pm = pm_sleep_ptr(&max7359_pm), }, - .probe_new = max7359_probe, + .probe = max7359_probe, .id_table = max7359_ids, }; diff --git a/drivers/input/keyboard/mcs_touchkey.c b/drivers/input/keyboard/mcs_touchkey.c index d414e19e455930379d42c2cf72283bbc4929a9d9..de312d8eb974d543b44eb1a18ce60e908182c590 100644 --- a/drivers/input/keyboard/mcs_touchkey.c +++ b/drivers/input/keyboard/mcs_touchkey.c @@ -258,7 +258,7 @@ static struct i2c_driver mcs_touchkey_driver = { .name = "mcs_touchkey", .pm = pm_sleep_ptr(&mcs_touchkey_pm_ops), }, - .probe_new = mcs_touchkey_probe, + .probe = mcs_touchkey_probe, .remove = mcs_touchkey_remove, .shutdown = mcs_touchkey_shutdown, .id_table = mcs_touchkey_id, diff --git a/drivers/input/keyboard/mpr121_touchkey.c b/drivers/input/keyboard/mpr121_touchkey.c index 74ad353462a3fc844f291641d9afe4007b640e2e..d434753afab11fc84d208380dba4e96e3c938bf2 100644 --- a/drivers/input/keyboard/mpr121_touchkey.c +++ b/drivers/input/keyboard/mpr121_touchkey.c @@ -389,7 +389,7 @@ static struct i2c_driver mpr_touchkey_driver = { .of_match_table = of_match_ptr(mpr121_touchkey_dt_match_table), }, .id_table = mpr121_id, - .probe_new = mpr_touchkey_probe, + .probe = mpr_touchkey_probe, }; module_i2c_driver(mpr_touchkey_driver); diff --git a/drivers/input/keyboard/pinephone-keyboard.c b/drivers/input/keyboard/pinephone-keyboard.c index 5548699b8b389f75d5fe123343dd5661445f41f1..038ff3549a7ac999e99cf6a9dfb3c83de0ce4a1c 100644 --- a/drivers/input/keyboard/pinephone-keyboard.c +++ b/drivers/input/keyboard/pinephone-keyboard.c @@ -455,7 +455,7 @@ static const struct of_device_id ppkb_of_match[] = { MODULE_DEVICE_TABLE(of, ppkb_of_match); static struct i2c_driver ppkb_driver = { - .probe_new = ppkb_probe, + .probe = ppkb_probe, .driver = { .name = DRV_NAME, .of_match_table = ppkb_of_match, diff --git a/drivers/input/keyboard/qt1050.c b/drivers/input/keyboard/qt1050.c index 317fe2b1f827fe28dab8ed14cde33c7f2124d160..6953097db4456f27cc698ce208841280762f37ca 100644 --- a/drivers/input/keyboard/qt1050.c +++ b/drivers/input/keyboard/qt1050.c @@ -588,7 +588,7 @@ static struct i2c_driver qt1050_driver = { .of_match_table = of_match_ptr(qt1050_of_match), .pm = pm_sleep_ptr(&qt1050_pm_ops), }, - .probe_new = qt1050_probe, + .probe = qt1050_probe, }; module_i2c_driver(qt1050_driver); diff --git a/drivers/input/keyboard/qt1070.c b/drivers/input/keyboard/qt1070.c index fabb50bde844468e6819d3d4d04637c7a56263bf..91aaa9fc43a4a5774bfeea1b7079407c936d7a85 100644 --- a/drivers/input/keyboard/qt1070.c +++ b/drivers/input/keyboard/qt1070.c @@ -271,7 +271,7 @@ static struct i2c_driver qt1070_driver = { .pm = pm_sleep_ptr(&qt1070_pm_ops), }, .id_table = qt1070_id, - .probe_new = qt1070_probe, + .probe = qt1070_probe, .remove = qt1070_remove, }; diff --git a/drivers/input/keyboard/qt2160.c b/drivers/input/keyboard/qt2160.c index 04d2ee6ff577ea0ceee38920d1b7fdccb017783a..599ea85cfd30c7c0f95def09593288e7f7bc5fb5 100644 --- a/drivers/input/keyboard/qt2160.c +++ b/drivers/input/keyboard/qt2160.c @@ -460,7 +460,7 @@ static struct i2c_driver qt2160_driver = { }, .id_table = qt2160_idtable, - .probe_new = qt2160_probe, + .probe = qt2160_probe, .remove = qt2160_remove, }; diff --git a/drivers/input/keyboard/tca6416-keypad.c b/drivers/input/keyboard/tca6416-keypad.c index 673b905af6fe57672ae613e69cfae600a7f096f0..2f745cabf4f248aec628ef4422e1e1cd8d373254 100644 --- a/drivers/input/keyboard/tca6416-keypad.c +++ b/drivers/input/keyboard/tca6416-keypad.c @@ -350,7 +350,7 @@ static struct i2c_driver tca6416_keypad_driver = { .name = "tca6416-keypad", .pm = pm_sleep_ptr(&tca6416_keypad_dev_pm_ops), }, - .probe_new = tca6416_keypad_probe, + .probe = tca6416_keypad_probe, .remove = tca6416_keypad_remove, .id_table = tca6416_id, }; diff --git a/drivers/input/keyboard/tca8418_keypad.c b/drivers/input/keyboard/tca8418_keypad.c index 3d7492f38337314ddb8c6fb986a20d6a130386a0..76fc19ffe21d2fefae90724a157ae89041acb226 100644 --- a/drivers/input/keyboard/tca8418_keypad.c +++ b/drivers/input/keyboard/tca8418_keypad.c @@ -370,7 +370,7 @@ static struct i2c_driver tca8418_keypad_driver = { .name = "tca8418_keypad", .of_match_table = tca8418_dt_ids, }, - .probe_new = tca8418_keypad_probe, + .probe = tca8418_keypad_probe, .id_table = tca8418_id, }; diff --git a/drivers/input/keyboard/tm2-touchkey.c b/drivers/input/keyboard/tm2-touchkey.c index 4e20571cb4c3820c026271aec5493e59628373e1..75bd3ea5119490da8ca83c20809a33ab5e4f9c6a 100644 --- a/drivers/input/keyboard/tm2-touchkey.c +++ b/drivers/input/keyboard/tm2-touchkey.c @@ -356,7 +356,7 @@ static struct i2c_driver tm2_touchkey_driver = { .pm = pm_sleep_ptr(&tm2_touchkey_pm_ops), .of_match_table = tm2_touchkey_of_match, }, - .probe_new = tm2_touchkey_probe, + .probe = tm2_touchkey_probe, .id_table = tm2_touchkey_id_table, }; module_i2c_driver(tm2_touchkey_driver); diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index 81a54a59e13c4411e7f831e49f7c99424aae2750..8a320e6218e372a36b385bc04a8fa0bfb455cbd2 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig @@ -609,7 +609,7 @@ config INPUT_PWM_VIBRA config INPUT_RK805_PWRKEY tristate "Rockchip RK805 PMIC power key support" - depends on MFD_RK808 + depends on MFD_RK8XX help Select this option to enable power key driver for RK805. diff --git a/drivers/input/misc/ad714x-i2c.c b/drivers/input/misc/ad714x-i2c.c index d8e39f4a57acc2804b4e0136f6c4302a7c146451..679fcfea942c2f701d69bd70ed88d3b53ebd1d18 100644 --- a/drivers/input/misc/ad714x-i2c.c +++ b/drivers/input/misc/ad714x-i2c.c @@ -86,7 +86,7 @@ static struct i2c_driver ad714x_i2c_driver = { .name = "ad714x_captouch", .pm = pm_sleep_ptr(&ad714x_pm), }, - .probe_new = ad714x_i2c_probe, + .probe = ad714x_i2c_probe, .id_table = ad714x_id, }; diff --git a/drivers/input/misc/adxl34x-i2c.c b/drivers/input/misc/adxl34x-i2c.c index 1c75d98c85a7856b268b5f4f5d2e9b7e23be3780..6b880e282d9906b393f219724dd99b4c24be4087 100644 --- a/drivers/input/misc/adxl34x-i2c.c +++ b/drivers/input/misc/adxl34x-i2c.c @@ -135,7 +135,7 @@ static struct i2c_driver adxl34x_driver = { .pm = pm_sleep_ptr(&adxl34x_pm), .of_match_table = adxl34x_of_id, }, - .probe_new = adxl34x_i2c_probe, + .probe = adxl34x_i2c_probe, .remove = adxl34x_i2c_remove, .id_table = adxl34x_id, }; diff --git a/drivers/input/misc/adxl34x.c b/drivers/input/misc/adxl34x.c index eecca671b5884b98dd894de300d1b8c05f9b6144..a3f45e0ee0c754080a137f8d71289079fc3701dc 100644 --- a/drivers/input/misc/adxl34x.c +++ b/drivers/input/misc/adxl34x.c @@ -817,8 +817,7 @@ struct adxl34x *adxl34x_probe(struct device *dev, int irq, AC_WRITE(ac, POWER_CTL, 0); err = request_threaded_irq(ac->irq, NULL, adxl34x_irq, - IRQF_TRIGGER_HIGH | IRQF_ONESHOT, - dev_name(dev), ac); + IRQF_ONESHOT, dev_name(dev), ac); if (err) { dev_err(dev, "irq %d busy?\n", ac->irq); goto err_free_mem; diff --git a/drivers/input/misc/apanel.c b/drivers/input/misc/apanel.c index f42d3219cdcc4c162f9f8b1f004cb118a982d431..b5219bbe856db7790240d6d6900d6471d5ecfaa1 100644 --- a/drivers/input/misc/apanel.c +++ b/drivers/input/misc/apanel.c @@ -201,7 +201,7 @@ static struct i2c_driver apanel_driver = { .driver = { .name = APANEL, }, - .probe_new = apanel_probe, + .probe = apanel_probe, .shutdown = apanel_shutdown, .id_table = apanel_id, }; diff --git a/drivers/input/misc/atmel_captouch.c b/drivers/input/misc/atmel_captouch.c index d9704b174d3a202d116de556dbf34f90c10e2c1e..b6a30044e814bdbe3419ae233ed6f4c7b9f710ee 100644 --- a/drivers/input/misc/atmel_captouch.c +++ b/drivers/input/misc/atmel_captouch.c @@ -263,7 +263,7 @@ static const struct i2c_device_id atmel_captouch_id[] = { MODULE_DEVICE_TABLE(i2c, atmel_captouch_id); static struct i2c_driver atmel_captouch_driver = { - .probe_new = atmel_captouch_probe, + .probe = atmel_captouch_probe, .id_table = atmel_captouch_id, .driver = { .name = "atmel_captouch", diff --git a/drivers/input/misc/bma150.c b/drivers/input/misc/bma150.c index 3f9da5c3cb53463f26fb55be6c105f8ccdcbc8f3..0fb4cc628f29cf4be2287116385d4e65b4be74cf 100644 --- a/drivers/input/misc/bma150.c +++ b/drivers/input/misc/bma150.c @@ -551,7 +551,7 @@ static struct i2c_driver bma150_driver = { }, .class = I2C_CLASS_HWMON, .id_table = bma150_id, - .probe_new = bma150_probe, + .probe = bma150_probe, .remove = bma150_remove, }; diff --git a/drivers/input/misc/cma3000_d0x_i2c.c b/drivers/input/misc/cma3000_d0x_i2c.c index 136eb3715870cdc6ac0783683d9b5721a150e196..a4dfb3052dc092722975757f169c7639082d77f1 100644 --- a/drivers/input/misc/cma3000_d0x_i2c.c +++ b/drivers/input/misc/cma3000_d0x_i2c.c @@ -97,7 +97,7 @@ static const struct i2c_device_id cma3000_i2c_id[] = { MODULE_DEVICE_TABLE(i2c, cma3000_i2c_id); static struct i2c_driver cma3000_i2c_driver = { - .probe_new = cma3000_i2c_probe, + .probe = cma3000_i2c_probe, .remove = cma3000_i2c_remove, .id_table = cma3000_i2c_id, .driver = { diff --git a/drivers/input/misc/da7280.c b/drivers/input/misc/da7280.c index b85a19e3554f516bcb68d92c6a2e3fbfd81591c4..ce82548916bbc688470812465f3c3c3baf0e1fc8 100644 --- a/drivers/input/misc/da7280.c +++ b/drivers/input/misc/da7280.c @@ -1321,7 +1321,7 @@ static struct i2c_driver da7280_driver = { .of_match_table = of_match_ptr(da7280_of_match), .pm = pm_sleep_ptr(&da7280_pm_ops), }, - .probe_new = da7280_probe, + .probe = da7280_probe, .id_table = da7280_i2c_id, }; module_i2c_driver(da7280_driver); diff --git a/drivers/input/misc/drv260x.c b/drivers/input/misc/drv260x.c index 8a9ebfc04a2d95985363bbedf4fe9d868e4da06d..6717e3c9549b25dbc2782d480ca635d530b0e93e 100644 --- a/drivers/input/misc/drv260x.c +++ b/drivers/input/misc/drv260x.c @@ -149,7 +149,7 @@ /* Control 3 Register */ #define DRV260X_LRA_OPEN_LOOP (1 << 0) -#define DRV260X_ANANLOG_IN (1 << 1) +#define DRV260X_ANALOG_IN (1 << 1) #define DRV260X_LRA_DRV_MODE (1 << 2) #define DRV260X_RTP_UNSIGNED_DATA (1 << 3) #define DRV260X_SUPPLY_COMP_DIS (1 << 4) @@ -186,51 +186,13 @@ struct drv260x_data { struct work_struct work; struct gpio_desc *enable_gpio; struct regulator *regulator; - u32 magnitude; + u8 magnitude; u32 mode; u32 library; int rated_voltage; int overdrive_voltage; }; -static const struct reg_default drv260x_reg_defs[] = { - { DRV260X_STATUS, 0xe0 }, - { DRV260X_MODE, 0x40 }, - { DRV260X_RT_PB_IN, 0x00 }, - { DRV260X_LIB_SEL, 0x00 }, - { DRV260X_WV_SEQ_1, 0x01 }, - { DRV260X_WV_SEQ_2, 0x00 }, - { DRV260X_WV_SEQ_3, 0x00 }, - { DRV260X_WV_SEQ_4, 0x00 }, - { DRV260X_WV_SEQ_5, 0x00 }, - { DRV260X_WV_SEQ_6, 0x00 }, - { DRV260X_WV_SEQ_7, 0x00 }, - { DRV260X_WV_SEQ_8, 0x00 }, - { DRV260X_GO, 0x00 }, - { DRV260X_OVERDRIVE_OFF, 0x00 }, - { DRV260X_SUSTAIN_P_OFF, 0x00 }, - { DRV260X_SUSTAIN_N_OFF, 0x00 }, - { DRV260X_BRAKE_OFF, 0x00 }, - { DRV260X_A_TO_V_CTRL, 0x05 }, - { DRV260X_A_TO_V_MIN_INPUT, 0x19 }, - { DRV260X_A_TO_V_MAX_INPUT, 0xff }, - { DRV260X_A_TO_V_MIN_OUT, 0x19 }, - { DRV260X_A_TO_V_MAX_OUT, 0xff }, - { DRV260X_RATED_VOLT, 0x3e }, - { DRV260X_OD_CLAMP_VOLT, 0x8c }, - { DRV260X_CAL_COMP, 0x0c }, - { DRV260X_CAL_BACK_EMF, 0x6c }, - { DRV260X_FEEDBACK_CTRL, 0x36 }, - { DRV260X_CTRL1, 0x93 }, - { DRV260X_CTRL2, 0xfa }, - { DRV260X_CTRL3, 0xa0 }, - { DRV260X_CTRL4, 0x20 }, - { DRV260X_CTRL5, 0x80 }, - { DRV260X_LRA_LOOP_PERIOD, 0x33 }, - { DRV260X_VBAT_MON, 0x00 }, - { DRV260X_LRA_RES_PERIOD, 0x00 }, -}; - #define DRV260X_DEF_RATED_VOLT 0x90 #define DRV260X_DEF_OD_CLAMP_VOLT 0x90 @@ -275,10 +237,11 @@ static int drv260x_haptics_play(struct input_dev *input, void *data, haptics->mode = DRV260X_LRA_NO_CAL_MODE; + /* Scale u16 magnitude into u8 register value */ if (effect->u.rumble.strong_magnitude > 0) - haptics->magnitude = effect->u.rumble.strong_magnitude; + haptics->magnitude = effect->u.rumble.strong_magnitude >> 8; else if (effect->u.rumble.weak_magnitude > 0) - haptics->magnitude = effect->u.rumble.weak_magnitude; + haptics->magnitude = effect->u.rumble.weak_magnitude >> 8; else haptics->magnitude = 0; @@ -304,7 +267,7 @@ static void drv260x_close(struct input_dev *input) static const struct reg_sequence drv260x_lra_cal_regs[] = { { DRV260X_MODE, DRV260X_AUTO_CAL }, - { DRV260X_CTRL3, DRV260X_NG_THRESH_2 }, + { DRV260X_CTRL3, DRV260X_NG_THRESH_2 | DRV260X_RTP_UNSIGNED_DATA }, { DRV260X_FEEDBACK_CTRL, DRV260X_FB_REG_LRA_MODE | DRV260X_BRAKE_FACTOR_4X | DRV260X_LOOP_GAIN_HIGH }, }; @@ -322,7 +285,7 @@ static const struct reg_sequence drv260x_lra_init_regs[] = { DRV260X_BEMF_GAIN_3 }, { DRV260X_CTRL1, DRV260X_STARTUP_BOOST }, { DRV260X_CTRL2, DRV260X_SAMP_TIME_250 }, - { DRV260X_CTRL3, DRV260X_NG_THRESH_2 | DRV260X_ANANLOG_IN }, + { DRV260X_CTRL3, DRV260X_NG_THRESH_2 | DRV260X_RTP_UNSIGNED_DATA | DRV260X_ANALOG_IN }, { DRV260X_CTRL4, DRV260X_AUTOCAL_TIME_500MS }, }; @@ -337,7 +300,7 @@ static const struct reg_sequence drv260x_erm_cal_regs[] = { { DRV260X_CTRL1, DRV260X_STARTUP_BOOST }, { DRV260X_CTRL2, DRV260X_SAMP_TIME_250 | DRV260X_BLANK_TIME_75 | DRV260X_IDISS_TIME_75 }, - { DRV260X_CTRL3, DRV260X_NG_THRESH_2 | DRV260X_ERM_OPEN_LOOP }, + { DRV260X_CTRL3, DRV260X_NG_THRESH_2 | DRV260X_RTP_UNSIGNED_DATA }, { DRV260X_CTRL4, DRV260X_AUTOCAL_TIME_500MS }, }; @@ -435,6 +398,7 @@ static int drv260x_init(struct drv260x_data *haptics) } do { + usleep_range(15000, 15500); error = regmap_read(haptics->regmap, DRV260X_GO, &cal_buf); if (error) { dev_err(&haptics->client->dev, @@ -452,8 +416,6 @@ static const struct regmap_config drv260x_regmap_config = { .val_bits = 8, .max_register = DRV260X_MAX_REG, - .reg_defaults = drv260x_reg_defs, - .num_reg_defaults = ARRAY_SIZE(drv260x_reg_defs), .cache_type = REGCACHE_NONE, }; @@ -653,7 +615,7 @@ static const struct of_device_id drv260x_of_match[] = { MODULE_DEVICE_TABLE(of, drv260x_of_match); static struct i2c_driver drv260x_driver = { - .probe_new = drv260x_probe, + .probe = drv260x_probe, .driver = { .name = "drv260x-haptics", .of_match_table = drv260x_of_match, diff --git a/drivers/input/misc/drv2665.c b/drivers/input/misc/drv2665.c index 9145096f80ea7c7c3bb8fd1ab294b34558bf0cf5..de27e6079d84f40f22cb483986e8d394ea644de6 100644 --- a/drivers/input/misc/drv2665.c +++ b/drivers/input/misc/drv2665.c @@ -297,7 +297,7 @@ MODULE_DEVICE_TABLE(of, drv2665_of_match); #endif static struct i2c_driver drv2665_driver = { - .probe_new = drv2665_probe, + .probe = drv2665_probe, .driver = { .name = "drv2665-haptics", .of_match_table = of_match_ptr(drv2665_of_match), diff --git a/drivers/input/misc/drv2667.c b/drivers/input/misc/drv2667.c index 88b4dbe3e5b52e5af55fafaceb3ec12f3cc1cd97..11c5855256e8c5a69547295e089b6e68f8ff0bbb 100644 --- a/drivers/input/misc/drv2667.c +++ b/drivers/input/misc/drv2667.c @@ -474,7 +474,7 @@ MODULE_DEVICE_TABLE(of, drv2667_of_match); #endif static struct i2c_driver drv2667_driver = { - .probe_new = drv2667_probe, + .probe = drv2667_probe, .driver = { .name = "drv2667-haptics", .of_match_table = of_match_ptr(drv2667_of_match), diff --git a/drivers/input/misc/ibm-panel.c b/drivers/input/misc/ibm-panel.c index 3969ffc1bc8d3b1be35f5a48206c9b62f1b513e9..867ac7aa10d2c16df6c4f2ea9876449ac615411c 100644 --- a/drivers/input/misc/ibm-panel.c +++ b/drivers/input/misc/ibm-panel.c @@ -189,7 +189,7 @@ static struct i2c_driver ibm_panel_driver = { .name = DEVICE_NAME, .of_match_table = ibm_panel_match, }, - .probe_new = ibm_panel_probe, + .probe = ibm_panel_probe, .remove = ibm_panel_remove, }; module_i2c_driver(ibm_panel_driver); diff --git a/drivers/input/misc/iqs269a.c b/drivers/input/misc/iqs269a.c index f4c3aff3895bc5f7821a981d0064af64ea2b66e1..1272ef7b579494dab0b15cdc75dad90cfe5df931 100644 --- a/drivers/input/misc/iqs269a.c +++ b/drivers/input/misc/iqs269a.c @@ -1746,7 +1746,7 @@ static struct i2c_driver iqs269_i2c_driver = { .of_match_table = iqs269_of_match, .pm = pm_sleep_ptr(&iqs269_pm), }, - .probe_new = iqs269_probe, + .probe = iqs269_probe, }; module_i2c_driver(iqs269_i2c_driver); diff --git a/drivers/input/misc/iqs626a.c b/drivers/input/misc/iqs626a.c index 90f997a905b53c4453e63338f6bdbbdf0edca8a8..50035c25c3f70aed98ce186bee08a6b9504fe94c 100644 --- a/drivers/input/misc/iqs626a.c +++ b/drivers/input/misc/iqs626a.c @@ -1822,7 +1822,7 @@ static struct i2c_driver iqs626_i2c_driver = { .of_match_table = iqs626_of_match, .pm = pm_sleep_ptr(&iqs626_pm), }, - .probe_new = iqs626_probe, + .probe = iqs626_probe, }; module_i2c_driver(iqs626_i2c_driver); diff --git a/drivers/input/misc/iqs7222.c b/drivers/input/misc/iqs7222.c index e47ab6c1177f554d5ab4a1003b457414097bfbce..096b0925f41bab10819c900e014708c1eca4c990 100644 --- a/drivers/input/misc/iqs7222.c +++ b/drivers/input/misc/iqs7222.c @@ -2593,7 +2593,7 @@ static struct i2c_driver iqs7222_i2c_driver = { .name = "iqs7222", .of_match_table = iqs7222_of_match, }, - .probe_new = iqs7222_probe, + .probe = iqs7222_probe, }; module_i2c_driver(iqs7222_i2c_driver); diff --git a/drivers/input/misc/kxtj9.c b/drivers/input/misc/kxtj9.c index 4e806d56c55d382121e81e960a9630a15ec33ddc..912e614d039d71d53f83c4499ddf6a90ed24e230 100644 --- a/drivers/input/misc/kxtj9.c +++ b/drivers/input/misc/kxtj9.c @@ -538,7 +538,7 @@ static struct i2c_driver kxtj9_driver = { .name = NAME, .pm = pm_sleep_ptr(&kxtj9_pm_ops), }, - .probe_new = kxtj9_probe, + .probe = kxtj9_probe, .id_table = kxtj9_id, }; diff --git a/drivers/input/misc/mma8450.c b/drivers/input/misc/mma8450.c index b12152536976aa608a315de8ca8622f11ac9e367..76a190b2220bd465016071118440b5fc90708116 100644 --- a/drivers/input/misc/mma8450.c +++ b/drivers/input/misc/mma8450.c @@ -202,7 +202,7 @@ static struct i2c_driver mma8450_driver = { .name = MMA8450_DRV_NAME, .of_match_table = mma8450_dt_ids, }, - .probe_new = mma8450_probe, + .probe = mma8450_probe, .id_table = mma8450_id, }; diff --git a/drivers/input/misc/pcf8574_keypad.c b/drivers/input/misc/pcf8574_keypad.c index 6323c3d37ef710c27b35f619090335f7cc27bcd8..536cedeb38e66f0df1ac4c1efed1526a28a1b3c7 100644 --- a/drivers/input/misc/pcf8574_keypad.c +++ b/drivers/input/misc/pcf8574_keypad.c @@ -199,7 +199,7 @@ static struct i2c_driver pcf8574_kp_driver = { .name = DRV_NAME, .pm = pm_sleep_ptr(&pcf8574_kp_pm_ops), }, - .probe_new = pcf8574_kp_probe, + .probe = pcf8574_kp_probe, .remove = pcf8574_kp_remove, .id_table = pcf8574_kp_id, }; diff --git a/drivers/input/misc/pm8941-pwrkey.c b/drivers/input/misc/pm8941-pwrkey.c index b6a27ebae977b369c770319e8dd2eebb632aa0e3..74d77d8aaeff204d3b9cfca4aa531dc4431d78bb 100644 --- a/drivers/input/misc/pm8941-pwrkey.c +++ b/drivers/input/misc/pm8941-pwrkey.c @@ -50,7 +50,10 @@ #define PON_RESIN_PULL_UP BIT(0) #define PON_DBC_CTL 0x71 -#define PON_DBC_DELAY_MASK 0x7 +#define PON_DBC_DELAY_MASK_GEN1 0x7 +#define PON_DBC_DELAY_MASK_GEN2 0xf +#define PON_DBC_SHIFT_GEN1 6 +#define PON_DBC_SHIFT_GEN2 14 struct pm8941_data { unsigned int pull_up_bit; @@ -247,7 +250,7 @@ static int pm8941_pwrkey_probe(struct platform_device *pdev) struct device *parent; struct device_node *regmap_node; const __be32 *addr; - u32 req_delay; + u32 req_delay, mask, delay_shift; int error; if (of_property_read_u32(pdev->dev.of_node, "debounce", &req_delay)) @@ -336,12 +339,20 @@ static int pm8941_pwrkey_probe(struct platform_device *pdev) pwrkey->input->phys = pwrkey->data->phys; if (pwrkey->data->supports_debounce_config) { - req_delay = (req_delay << 6) / USEC_PER_SEC; + if (pwrkey->subtype >= PON_SUBTYPE_GEN2_PRIMARY) { + mask = PON_DBC_DELAY_MASK_GEN2; + delay_shift = PON_DBC_SHIFT_GEN2; + } else { + mask = PON_DBC_DELAY_MASK_GEN1; + delay_shift = PON_DBC_SHIFT_GEN1; + } + + req_delay = (req_delay << delay_shift) / USEC_PER_SEC; req_delay = ilog2(req_delay); error = regmap_update_bits(pwrkey->regmap, pwrkey->baseaddr + PON_DBC_CTL, - PON_DBC_DELAY_MASK, + mask, req_delay); if (error) { dev_err(&pdev->dev, "failed to set debounce: %d\n", diff --git a/drivers/input/misc/pwm-vibra.c b/drivers/input/misc/pwm-vibra.c index d0e58a7cdfa34cc17593661ba5769dd36b55c0e0..2ba035299db879b224010004b6b018e2fecd4b60 100644 --- a/drivers/input/misc/pwm-vibra.c +++ b/drivers/input/misc/pwm-vibra.c @@ -11,6 +11,7 @@ * Copyright (C) 2010, Lars-Peter Clausen */ +#include #include #include #include @@ -23,6 +24,7 @@ struct pwm_vibrator { struct input_dev *input; + struct gpio_desc *enable_gpio; struct pwm_device *pwm; struct pwm_device *pwm_dir; struct regulator *vcc; @@ -42,19 +44,21 @@ static int pwm_vibrator_start(struct pwm_vibrator *vibrator) if (!vibrator->vcc_on) { err = regulator_enable(vibrator->vcc); if (err) { - dev_err(pdev, "failed to enable regulator: %d", err); + dev_err(pdev, "failed to enable regulator: %d\n", err); return err; } vibrator->vcc_on = true; } + gpiod_set_value_cansleep(vibrator->enable_gpio, 1); + pwm_get_state(vibrator->pwm, &state); pwm_set_relative_duty_cycle(&state, vibrator->level, 0xffff); state.enabled = true; err = pwm_apply_state(vibrator->pwm, &state); if (err) { - dev_err(pdev, "failed to apply pwm state: %d", err); + dev_err(pdev, "failed to apply pwm state: %d\n", err); return err; } @@ -65,7 +69,7 @@ static int pwm_vibrator_start(struct pwm_vibrator *vibrator) err = pwm_apply_state(vibrator->pwm_dir, &state); if (err) { - dev_err(pdev, "failed to apply dir-pwm state: %d", err); + dev_err(pdev, "failed to apply dir-pwm state: %d\n", err); pwm_disable(vibrator->pwm); return err; } @@ -80,6 +84,8 @@ static void pwm_vibrator_stop(struct pwm_vibrator *vibrator) pwm_disable(vibrator->pwm_dir); pwm_disable(vibrator->pwm); + gpiod_set_value_cansleep(vibrator->enable_gpio, 0); + if (vibrator->vcc_on) { regulator_disable(vibrator->vcc); vibrator->vcc_on = false; @@ -137,7 +143,17 @@ static int pwm_vibrator_probe(struct platform_device *pdev) err = PTR_ERR_OR_ZERO(vibrator->vcc); if (err) { if (err != -EPROBE_DEFER) - dev_err(&pdev->dev, "Failed to request regulator: %d", + dev_err(&pdev->dev, "Failed to request regulator: %d\n", + err); + return err; + } + + vibrator->enable_gpio = devm_gpiod_get_optional(&pdev->dev, "enable", + GPIOD_OUT_LOW); + err = PTR_ERR_OR_ZERO(vibrator->enable_gpio); + if (err) { + if (err != -EPROBE_DEFER) + dev_err(&pdev->dev, "Failed to request enable gpio: %d\n", err); return err; } @@ -146,7 +162,7 @@ static int pwm_vibrator_probe(struct platform_device *pdev) err = PTR_ERR_OR_ZERO(vibrator->pwm); if (err) { if (err != -EPROBE_DEFER) - dev_err(&pdev->dev, "Failed to request main pwm: %d", + dev_err(&pdev->dev, "Failed to request main pwm: %d\n", err); return err; } @@ -158,7 +174,7 @@ static int pwm_vibrator_probe(struct platform_device *pdev) state.enabled = false; err = pwm_apply_state(vibrator->pwm, &state); if (err) { - dev_err(&pdev->dev, "failed to apply initial PWM state: %d", + dev_err(&pdev->dev, "failed to apply initial PWM state: %d\n", err); return err; } @@ -172,7 +188,7 @@ static int pwm_vibrator_probe(struct platform_device *pdev) state.enabled = false; err = pwm_apply_state(vibrator->pwm_dir, &state); if (err) { - dev_err(&pdev->dev, "failed to apply initial PWM state: %d", + dev_err(&pdev->dev, "failed to apply initial PWM state: %d\n", err); return err; } @@ -189,7 +205,7 @@ static int pwm_vibrator_probe(struct platform_device *pdev) break; default: - dev_err(&pdev->dev, "Failed to request direction pwm: %d", err); + dev_err(&pdev->dev, "Failed to request direction pwm: %d\n", err); fallthrough; case -EPROBE_DEFER: @@ -207,13 +223,13 @@ static int pwm_vibrator_probe(struct platform_device *pdev) err = input_ff_create_memless(vibrator->input, NULL, pwm_vibrator_play_effect); if (err) { - dev_err(&pdev->dev, "Couldn't create FF dev: %d", err); + dev_err(&pdev->dev, "Couldn't create FF dev: %d\n", err); return err; } err = input_register_device(vibrator->input); if (err) { - dev_err(&pdev->dev, "Couldn't register input dev: %d", err); + dev_err(&pdev->dev, "Couldn't register input dev: %d\n", err); return err; } diff --git a/drivers/input/misc/tps65219-pwrbutton.c b/drivers/input/misc/tps65219-pwrbutton.c index 245134bdb59e6ee5cded50b2a136330d085a17b1..eeb9f2334ab461f8619fefbff2088c7b107de7f3 100644 --- a/drivers/input/misc/tps65219-pwrbutton.c +++ b/drivers/input/misc/tps65219-pwrbutton.c @@ -117,14 +117,16 @@ static int tps65219_pb_probe(struct platform_device *pdev) return 0; } -static int tps65219_pb_remove(struct platform_device *pdev) +static void tps65219_pb_remove(struct platform_device *pdev) { struct tps65219 *tps = dev_get_drvdata(pdev->dev.parent); + int ret; /* Disable interrupt for the pushbutton */ - return regmap_update_bits(tps->regmap, TPS65219_REG_MASK_CONFIG, - TPS65219_REG_MASK_INT_FOR_PB_MASK, - TPS65219_REG_MASK_INT_FOR_PB_MASK); + ret = regmap_set_bits(tps->regmap, TPS65219_REG_MASK_CONFIG, + TPS65219_REG_MASK_INT_FOR_PB_MASK); + if (ret) + dev_warn(&pdev->dev, "Failed to disable irq (%pe)\n", ERR_PTR(ret)); } static const struct platform_device_id tps65219_pwrbtn_id_table[] = { @@ -135,7 +137,7 @@ MODULE_DEVICE_TABLE(platform, tps65219_pwrbtn_id_table); static struct platform_driver tps65219_pb_driver = { .probe = tps65219_pb_probe, - .remove = tps65219_pb_remove, + .remove_new = tps65219_pb_remove, .driver = { .name = "tps65219_pwrbutton", }, diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c index f2593133e5247a8fbc6cebfc296a2aedeb0c87ff..d98212d55108c7e394c669d08f6ea86859e1dfe9 100644 --- a/drivers/input/misc/uinput.c +++ b/drivers/input/misc/uinput.c @@ -33,6 +33,7 @@ #define UINPUT_NAME "uinput" #define UINPUT_BUFFER_SIZE 16 #define UINPUT_NUM_REQUESTS 16 +#define UINPUT_TIMESTAMP_ALLOWED_OFFSET_SECS 10 enum uinput_state { UIST_NEW_DEVICE, UIST_SETUP_COMPLETE, UIST_CREATED }; @@ -569,11 +570,40 @@ static int uinput_setup_device_legacy(struct uinput_device *udev, return retval; } +/* + * Returns true if the given timestamp is valid (i.e., if all the following + * conditions are satisfied), false otherwise. + * 1) given timestamp is positive + * 2) it's within the allowed offset before the current time + * 3) it's not in the future + */ +static bool is_valid_timestamp(const ktime_t timestamp) +{ + ktime_t zero_time; + ktime_t current_time; + ktime_t min_time; + ktime_t offset; + + zero_time = ktime_set(0, 0); + if (ktime_compare(zero_time, timestamp) >= 0) + return false; + + current_time = ktime_get(); + offset = ktime_set(UINPUT_TIMESTAMP_ALLOWED_OFFSET_SECS, 0); + min_time = ktime_sub(current_time, offset); + + if (ktime_after(min_time, timestamp) || ktime_after(timestamp, current_time)) + return false; + + return true; +} + static ssize_t uinput_inject_events(struct uinput_device *udev, const char __user *buffer, size_t count) { struct input_event ev; size_t bytes = 0; + ktime_t timestamp; if (count != 0 && count < input_event_size()) return -EINVAL; @@ -588,6 +618,10 @@ static ssize_t uinput_inject_events(struct uinput_device *udev, if (input_event_from_user(buffer + bytes, &ev)) return -EFAULT; + timestamp = ktime_set(ev.input_event_sec, ev.input_event_usec * NSEC_PER_USEC); + if (is_valid_timestamp(timestamp)) + input_set_timestamp(udev->dev, timestamp); + input_event(udev->dev, ev.type, ev.code, ev.value); bytes += input_event_size(); cond_resched(); diff --git a/drivers/input/mouse/cyapa.c b/drivers/input/mouse/cyapa.c index dd7b0d70d7917d131e3d22e186ec101216a776dc..05851bc32541f7c6917ed1ae9e434234baf9e5f0 100644 --- a/drivers/input/mouse/cyapa.c +++ b/drivers/input/mouse/cyapa.c @@ -1489,7 +1489,7 @@ static struct i2c_driver cyapa_driver = { .of_match_table = of_match_ptr(cyapa_of_match), }, - .probe_new = cyapa_probe, + .probe = cyapa_probe, .id_table = cyapa_id_table, }; diff --git a/drivers/input/mouse/elan_i2c_core.c b/drivers/input/mouse/elan_i2c_core.c index 5f0d75a45c8086ace84d19d77959d50f71f11bad..0cff742302a9fca607db01ee4496b88186748d37 100644 --- a/drivers/input/mouse/elan_i2c_core.c +++ b/drivers/input/mouse/elan_i2c_core.c @@ -1424,7 +1424,7 @@ static struct i2c_driver elan_driver = { .probe_type = PROBE_PREFER_ASYNCHRONOUS, .dev_groups = elan_sysfs_groups, }, - .probe_new = elan_probe, + .probe = elan_probe, .id_table = elan_id, }; diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index c9a7e87b273ed2efdad2adbb09ae913989ab228d..a0aac76b1e41dd91327a1cf44d8fdc2525dd18d9 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c @@ -116,6 +116,13 @@ static DEFINE_MUTEX(psmouse_mutex); static struct workqueue_struct *kpsmoused_wq; +struct psmouse *psmouse_from_serio(struct serio *serio) +{ + struct ps2dev *ps2dev = serio_get_drvdata(serio); + + return container_of(ps2dev, struct psmouse, ps2dev); +} + void psmouse_report_standard_buttons(struct input_dev *dev, u8 buttons) { input_report_key(dev, BTN_LEFT, buttons & BIT(0)); @@ -329,17 +336,14 @@ static void psmouse_handle_oob_data(struct psmouse *psmouse, u8 data) } } -/* - * psmouse_interrupt() handles incoming characters, either passing them - * for normal processing or gathering them as command response. - */ -static irqreturn_t psmouse_interrupt(struct serio *serio, - u8 data, unsigned int flags) +static enum ps2_disposition psmouse_pre_receive_byte(struct ps2dev *ps2dev, + u8 data, + unsigned int flags) { - struct psmouse *psmouse = serio_get_drvdata(serio); + struct psmouse *psmouse = container_of(ps2dev, struct psmouse, ps2dev); if (psmouse->state == PSMOUSE_IGNORE) - goto out; + return PS2_IGNORE; if (unlikely((flags & SERIO_TIMEOUT) || ((flags & SERIO_PARITY) && @@ -350,27 +354,25 @@ static irqreturn_t psmouse_interrupt(struct serio *serio, "bad data from KBC -%s%s\n", flags & SERIO_TIMEOUT ? " timeout" : "", flags & SERIO_PARITY ? " bad parity" : ""); - ps2_cmd_aborted(&psmouse->ps2dev); - goto out; + return PS2_ERROR; } if (flags & SERIO_OOB_DATA) { psmouse_handle_oob_data(psmouse, data); - goto out; + return PS2_IGNORE; } - if (unlikely(psmouse->ps2dev.flags & PS2_FLAG_ACK)) - if (ps2_handle_ack(&psmouse->ps2dev, data)) - goto out; + return PS2_PROCESS; +} - if (unlikely(psmouse->ps2dev.flags & PS2_FLAG_CMD)) - if (ps2_handle_response(&psmouse->ps2dev, data)) - goto out; +static void psmouse_receive_byte(struct ps2dev *ps2dev, u8 data) +{ + struct psmouse *psmouse = container_of(ps2dev, struct psmouse, ps2dev); - pm_wakeup_event(&serio->dev, 0); + pm_wakeup_event(&ps2dev->serio->dev, 0); if (psmouse->state <= PSMOUSE_RESYNCING) - goto out; + return; if (psmouse->state == PSMOUSE_ACTIVATED && psmouse->pktcnt && time_after(jiffies, psmouse->last + HZ/2)) { @@ -379,7 +381,7 @@ static irqreturn_t psmouse_interrupt(struct serio *serio, psmouse->badbyte = psmouse->packet[0]; __psmouse_set_state(psmouse, PSMOUSE_RESYNCING); psmouse_queue_work(psmouse, &psmouse->resync_work, 0); - goto out; + return; } psmouse->packet[psmouse->pktcnt++] = data; @@ -388,21 +390,21 @@ static irqreturn_t psmouse_interrupt(struct serio *serio, if (unlikely(psmouse->packet[0] == PSMOUSE_RET_BAT && psmouse->pktcnt <= 2)) { if (psmouse->pktcnt == 1) { psmouse->last = jiffies; - goto out; + return; } if (psmouse->packet[1] == PSMOUSE_RET_ID || (psmouse->protocol->type == PSMOUSE_HGPK && psmouse->packet[1] == PSMOUSE_RET_BAT)) { __psmouse_set_state(psmouse, PSMOUSE_IGNORE); - serio_reconnect(serio); - goto out; + serio_reconnect(ps2dev->serio); + return; } /* Not a new device, try processing first byte normally */ psmouse->pktcnt = 1; if (psmouse_handle_byte(psmouse)) - goto out; + return; psmouse->packet[psmouse->pktcnt++] = data; } @@ -417,14 +419,11 @@ static irqreturn_t psmouse_interrupt(struct serio *serio, psmouse->badbyte = psmouse->packet[0]; __psmouse_set_state(psmouse, PSMOUSE_RESYNCING); psmouse_queue_work(psmouse, &psmouse->resync_work, 0); - goto out; + return; } psmouse->last = jiffies; psmouse_handle_byte(psmouse); - - out: - return IRQ_HANDLED; } /* @@ -1344,7 +1343,7 @@ static void psmouse_resync(struct work_struct *work) goto out; if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) { - parent = serio_get_drvdata(serio->parent); + parent = psmouse_from_serio(serio->parent); psmouse_deactivate(parent); } @@ -1428,13 +1427,13 @@ static void psmouse_resync(struct work_struct *work) */ static void psmouse_cleanup(struct serio *serio) { - struct psmouse *psmouse = serio_get_drvdata(serio); + struct psmouse *psmouse = psmouse_from_serio(serio); struct psmouse *parent = NULL; mutex_lock(&psmouse_mutex); if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) { - parent = serio_get_drvdata(serio->parent); + parent = psmouse_from_serio(serio->parent); psmouse_deactivate(parent); } @@ -1476,7 +1475,7 @@ static void psmouse_cleanup(struct serio *serio) */ static void psmouse_disconnect(struct serio *serio) { - struct psmouse *psmouse = serio_get_drvdata(serio); + struct psmouse *psmouse = psmouse_from_serio(serio); struct psmouse *parent = NULL; mutex_lock(&psmouse_mutex); @@ -1489,7 +1488,7 @@ static void psmouse_disconnect(struct serio *serio) mutex_lock(&psmouse_mutex); if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) { - parent = serio_get_drvdata(serio->parent); + parent = psmouse_from_serio(serio->parent); psmouse_deactivate(parent); } @@ -1588,7 +1587,7 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv) * connected to this port can be successfully identified */ if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) { - parent = serio_get_drvdata(serio->parent); + parent = psmouse_from_serio(serio->parent); psmouse_deactivate(parent); } @@ -1597,15 +1596,14 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv) if (!psmouse || !input_dev) goto err_free; - ps2_init(&psmouse->ps2dev, serio); + ps2_init(&psmouse->ps2dev, serio, + psmouse_pre_receive_byte, psmouse_receive_byte); INIT_DELAYED_WORK(&psmouse->resync_work, psmouse_resync); psmouse->dev = input_dev; snprintf(psmouse->phys, sizeof(psmouse->phys), "%s/input0", serio->phys); psmouse_set_state(psmouse, PSMOUSE_INITIALIZING); - serio_set_drvdata(serio, psmouse); - error = serio_open(serio, drv); if (error) goto err_clear_drvdata; @@ -1676,7 +1674,7 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv) static int __psmouse_reconnect(struct serio *serio, bool fast_reconnect) { - struct psmouse *psmouse = serio_get_drvdata(serio); + struct psmouse *psmouse = psmouse_from_serio(serio); struct psmouse *parent = NULL; int (*reconnect_handler)(struct psmouse *); enum psmouse_type type; @@ -1695,7 +1693,7 @@ static int __psmouse_reconnect(struct serio *serio, bool fast_reconnect) } if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) { - parent = serio_get_drvdata(serio->parent); + parent = psmouse_from_serio(serio->parent); psmouse_deactivate(parent); } @@ -1781,7 +1779,7 @@ static struct serio_driver psmouse_drv = { }, .description = DRIVER_DESC, .id_table = psmouse_serio_ids, - .interrupt = psmouse_interrupt, + .interrupt = ps2_interrupt, .connect = psmouse_connect, .reconnect = psmouse_reconnect, .fast_reconnect = psmouse_fast_reconnect, @@ -1794,7 +1792,7 @@ ssize_t psmouse_attr_show_helper(struct device *dev, struct device_attribute *de { struct serio *serio = to_serio_port(dev); struct psmouse_attribute *attr = to_psmouse_attr(devattr); - struct psmouse *psmouse = serio_get_drvdata(serio); + struct psmouse *psmouse = psmouse_from_serio(serio); if (psmouse->protocol->smbus_companion && devattr != &psmouse_attr_protocol.dattr) @@ -1815,7 +1813,7 @@ ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *dev if (retval) goto out; - psmouse = serio_get_drvdata(serio); + psmouse = psmouse_from_serio(serio); if (psmouse->protocol->smbus_companion && devattr != &psmouse_attr_protocol.dattr) { @@ -1830,7 +1828,7 @@ ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *dev } if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) { - parent = serio_get_drvdata(serio->parent); + parent = psmouse_from_serio(serio->parent); psmouse_deactivate(parent); } @@ -1925,7 +1923,7 @@ static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, void *data, co } if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) { - parent = serio_get_drvdata(serio->parent); + parent = psmouse_from_serio(serio->parent); if (parent->pt_deactivate) parent->pt_deactivate(parent); } diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h index 64c3a5d3fb3e6b92cd8c9b58102f7a29d7acb55d..4d8acfe0d82aa3017413628d5a8ba8f917ec080f 100644 --- a/drivers/input/mouse/psmouse.h +++ b/drivers/input/mouse/psmouse.h @@ -130,6 +130,8 @@ struct psmouse { void (*pt_deactivate)(struct psmouse *psmouse); }; +struct psmouse *psmouse_from_serio(struct serio *serio); + void psmouse_queue_work(struct psmouse *psmouse, struct delayed_work *work, unsigned long delay); int psmouse_reset(struct psmouse *psmouse); diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index fa021af8506e4f8c3309026ca474a1c1d20a7824..ada299ec5bba55ae03a004bf8ebccf10249e58ae 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c @@ -628,7 +628,7 @@ static void synaptics_set_rate(struct psmouse *psmouse, unsigned int rate) ****************************************************************************/ static int synaptics_pt_write(struct serio *serio, u8 c) { - struct psmouse *parent = serio_get_drvdata(serio->parent); + struct psmouse *parent = psmouse_from_serio(serio->parent); u8 rate_param = SYN_PS_CLIENT_CMD; /* indicates that we want pass-through port */ int error; @@ -645,7 +645,7 @@ static int synaptics_pt_write(struct serio *serio, u8 c) static int synaptics_pt_start(struct serio *serio) { - struct psmouse *parent = serio_get_drvdata(serio->parent); + struct psmouse *parent = psmouse_from_serio(serio->parent); struct synaptics_data *priv = parent->private; serio_pause_rx(parent->ps2dev.serio); @@ -657,7 +657,7 @@ static int synaptics_pt_start(struct serio *serio) static void synaptics_pt_stop(struct serio *serio) { - struct psmouse *parent = serio_get_drvdata(serio->parent); + struct psmouse *parent = psmouse_from_serio(serio->parent); struct synaptics_data *priv = parent->private; serio_pause_rx(parent->ps2dev.serio); @@ -672,7 +672,7 @@ static int synaptics_is_pt_packet(u8 *buf) static void synaptics_pass_pt_packet(struct serio *ptport, u8 *packet) { - struct psmouse *child = serio_get_drvdata(ptport); + struct psmouse *child = psmouse_from_serio(ptport); if (child && child->state == PSMOUSE_ACTIVATED) { serio_interrupt(ptport, packet[1], 0); @@ -688,7 +688,7 @@ static void synaptics_pass_pt_packet(struct serio *ptport, u8 *packet) static void synaptics_pt_activate(struct psmouse *psmouse) { struct synaptics_data *priv = psmouse->private; - struct psmouse *child = serio_get_drvdata(priv->pt_port); + struct psmouse *child = psmouse_from_serio(priv->pt_port); /* adjust the touchpad to child's choice of protocol */ if (child) { diff --git a/drivers/input/mouse/synaptics_i2c.c b/drivers/input/mouse/synaptics_i2c.c index 068692a8aba5d3dda300b297f29fd025ba2d0396..af5cc64c622df1336c7ab270dfce8b522c36ccf4 100644 --- a/drivers/input/mouse/synaptics_i2c.c +++ b/drivers/input/mouse/synaptics_i2c.c @@ -650,7 +650,7 @@ static struct i2c_driver synaptics_i2c_driver = { .pm = pm_sleep_ptr(&synaptics_i2c_pm), }, - .probe_new = synaptics_i2c_probe, + .probe = synaptics_i2c_probe, .remove = synaptics_i2c_remove, .id_table = synaptics_i2c_id_table, diff --git a/drivers/input/mouse/trackpoint.c b/drivers/input/mouse/trackpoint.c index 4a86b3e31d3bd3589f536b0861daf46e1ce87a4e..5f6643b69a2cf40598a1cd919822f78ca1a15b16 100644 --- a/drivers/input/mouse/trackpoint.c +++ b/drivers/input/mouse/trackpoint.c @@ -216,7 +216,7 @@ static umode_t trackpoint_is_attr_visible(struct kobject *kobj, { struct device *dev = kobj_to_dev(kobj); struct serio *serio = to_serio_port(dev); - struct psmouse *psmouse = serio_get_drvdata(serio); + struct psmouse *psmouse = psmouse_from_serio(serio); return trackpoint_is_attr_available(psmouse, attr) ? attr->mode : 0; } diff --git a/drivers/input/rmi4/rmi_i2c.c b/drivers/input/rmi4/rmi_i2c.c index d69569ce8d8db635b04c83afd9d411397b464041..091d4e23b6292ade9d42e27b7613f1a8ade52c47 100644 --- a/drivers/input/rmi4/rmi_i2c.c +++ b/drivers/input/rmi4/rmi_i2c.c @@ -377,7 +377,7 @@ static struct i2c_driver rmi_i2c_driver = { .of_match_table = of_match_ptr(rmi_i2c_of_match), }, .id_table = rmi_id, - .probe_new = rmi_i2c_probe, + .probe = rmi_i2c_probe, }; module_i2c_driver(rmi_i2c_driver); diff --git a/drivers/input/rmi4/rmi_smbus.c b/drivers/input/rmi4/rmi_smbus.c index 4bf0e1df6a4aaf4bc8895d9f8cde7594c1cd9fac..7059a2762aebc1f2a4b09908f214d04e6ab54ee8 100644 --- a/drivers/input/rmi4/rmi_smbus.c +++ b/drivers/input/rmi4/rmi_smbus.c @@ -418,7 +418,7 @@ static struct i2c_driver rmi_smb_driver = { .pm = pm_ptr(&rmi_smb_pm), }, .id_table = rmi_id, - .probe_new = rmi_smb_probe, + .probe = rmi_smb_probe, .remove = rmi_smb_remove, }; diff --git a/drivers/input/serio/Kconfig b/drivers/input/serio/Kconfig index f39b7b3f7942153882faae30a4998ed9525cfbe8..17edc1597446f2643b362d9bee123295d336dbb2 100644 --- a/drivers/input/serio/Kconfig +++ b/drivers/input/serio/Kconfig @@ -148,6 +148,7 @@ config HIL_MLC config SERIO_PCIPS2 tristate "PCI PS/2 keyboard and PS/2 mouse controller" depends on PCI + depends on HAS_IOPORT help Say Y here if you have a Mobility Docking station with PS/2 keyboard and mice ports. diff --git a/drivers/input/serio/libps2.c b/drivers/input/serio/libps2.c index 3e19344eda93ce915bf81c88f685cf8837614e92..6d78a1fe00c1bf43c18d750b43f3391f00be4541 100644 --- a/drivers/input/serio/libps2.c +++ b/drivers/input/serio/libps2.c @@ -19,9 +19,26 @@ #define DRIVER_DESC "PS/2 driver library" -MODULE_AUTHOR("Dmitry Torokhov "); -MODULE_DESCRIPTION("PS/2 driver library"); -MODULE_LICENSE("GPL"); +#define PS2_CMD_SETSCALE11 0x00e6 +#define PS2_CMD_SETRES 0x10e8 +#define PS2_CMD_EX_SETLEDS 0x20eb +#define PS2_CMD_SETLEDS 0x10ed +#define PS2_CMD_GETID 0x02f2 +#define PS2_CMD_SETREP 0x10f3 /* Set repeat rate/set report rate */ +#define PS2_CMD_RESET_BAT 0x02ff + +#define PS2_RET_BAT 0xaa +#define PS2_RET_ID 0x00 +#define PS2_RET_ACK 0xfa +#define PS2_RET_NAK 0xfe +#define PS2_RET_ERR 0xfc + +#define PS2_FLAG_ACK BIT(0) /* Waiting for ACK/NAK */ +#define PS2_FLAG_CMD BIT(1) /* Waiting for a command to finish */ +#define PS2_FLAG_CMD1 BIT(2) /* Waiting for the first byte of command response */ +#define PS2_FLAG_WAITID BIT(3) /* Command executing is GET ID */ +#define PS2_FLAG_NAK BIT(4) /* Last transmission was NAKed */ +#define PS2_FLAG_PASS_NOACK BIT(5) /* Pass non-ACK byte to receive handler */ static int ps2_do_sendbyte(struct ps2dev *ps2dev, u8 byte, unsigned int timeout, unsigned int max_attempts) @@ -76,14 +93,17 @@ static int ps2_do_sendbyte(struct ps2dev *ps2dev, u8 byte, return error; } -/* - * ps2_sendbyte() sends a byte to the device and waits for acknowledge. - * It doesn't handle retransmission, the caller is expected to handle +/** + * ps2_sendbyte - sends a byte to the device and wait for acknowledgement + * @ps2dev: a PS/2 device to send the data to + * @byte: data to be sent to the device + * @timeout: timeout for sending the data and receiving an acknowledge + * + * The function doesn't handle retransmission, the caller is expected to handle * it when needed. * * ps2_sendbyte() can only be called from a process context. */ - int ps2_sendbyte(struct ps2dev *ps2dev, u8 byte, unsigned int timeout) { int retval; @@ -99,6 +119,13 @@ int ps2_sendbyte(struct ps2dev *ps2dev, u8 byte, unsigned int timeout) } EXPORT_SYMBOL(ps2_sendbyte); +/** + * ps2_begin_command - mark beginning of execution of a complex command + * @ps2dev: a PS/2 device executing the command + * + * Serializes a complex/compound command. Once command is finished + * ps2_end_command() should be called. + */ void ps2_begin_command(struct ps2dev *ps2dev) { struct mutex *m = ps2dev->serio->ps2_cmd_mutex ?: &ps2dev->cmd_mutex; @@ -107,6 +134,10 @@ void ps2_begin_command(struct ps2dev *ps2dev) } EXPORT_SYMBOL(ps2_begin_command); +/** + * ps2_end_command - mark end of execution of a complex command + * @ps2dev: a PS/2 device executing the command + */ void ps2_end_command(struct ps2dev *ps2dev) { struct mutex *m = ps2dev->serio->ps2_cmd_mutex ?: &ps2dev->cmd_mutex; @@ -115,11 +146,13 @@ void ps2_end_command(struct ps2dev *ps2dev) } EXPORT_SYMBOL(ps2_end_command); -/* - * ps2_drain() waits for device to transmit requested number of bytes - * and discards them. +/** + * ps2_drain - waits for device to transmit requested number of bytes + * and discards them + * @ps2dev: the PS/2 device that should be drained + * @maxbytes: maximum number of bytes to be drained + * @timeout: time to drain the device */ - void ps2_drain(struct ps2dev *ps2dev, size_t maxbytes, unsigned int timeout) { if (maxbytes > sizeof(ps2dev->cmdbuf)) { @@ -142,11 +175,11 @@ void ps2_drain(struct ps2dev *ps2dev, size_t maxbytes, unsigned int timeout) } EXPORT_SYMBOL(ps2_drain); -/* - * ps2_is_keyboard_id() checks received ID byte against the list of - * known keyboard IDs. +/** + * ps2_is_keyboard_id - checks received ID byte against the list of + * known keyboard IDs + * @id_byte: data byte that should be checked */ - bool ps2_is_keyboard_id(u8 id_byte) { static const u8 keyboard_ids[] = { @@ -167,7 +200,6 @@ EXPORT_SYMBOL(ps2_is_keyboard_id); * response and tries to reduce remaining timeout to speed up command * completion. */ - static int ps2_adjust_timeout(struct ps2dev *ps2dev, unsigned int command, unsigned int timeout) { @@ -217,13 +249,19 @@ static int ps2_adjust_timeout(struct ps2dev *ps2dev, return timeout; } -/* - * ps2_command() sends a command and its parameters to the mouse, - * then waits for the response and puts it in the param array. +/** + * __ps2_command - send a command to PS/2 device + * @ps2dev: the PS/2 device that should execute the command + * @param: a buffer containing parameters to be sent along with the command, + * or place where the results of the command execution will be deposited, + * or both + * @command: command word that encodes the command itself, as well as number of + * additional parameter bytes that should be sent to the device and expected + * length of the command response * - * ps2_command() can only be called from a process context + * Not serialized. Callers should use ps2_begin_command() and ps2_end_command() + * to ensure proper serialization for complex commands. */ - int __ps2_command(struct ps2dev *ps2dev, u8 *param, unsigned int command) { unsigned int timeout; @@ -247,17 +285,38 @@ int __ps2_command(struct ps2dev *ps2dev, u8 *param, unsigned int command) serio_pause_rx(ps2dev->serio); - ps2dev->flags = command == PS2_CMD_GETID ? PS2_FLAG_WAITID : 0; ps2dev->cmdcnt = receive; - if (receive && param) - for (i = 0; i < receive; i++) - ps2dev->cmdbuf[(receive - 1) - i] = param[i]; - /* Signal that we are sending the command byte */ - ps2dev->flags |= PS2_FLAG_ACK_CMD; + switch (command) { + case PS2_CMD_GETID: + /* + * Some mice do not ACK the "get ID" command, prepare to + * handle this. + */ + ps2dev->flags = PS2_FLAG_WAITID; + break; + + case PS2_CMD_SETLEDS: + case PS2_CMD_EX_SETLEDS: + case PS2_CMD_SETREP: + ps2dev->flags = PS2_FLAG_PASS_NOACK; + break; + + default: + ps2dev->flags = 0; + break; + } + + if (receive) { + /* Indicate that we expect response to the command. */ + ps2dev->flags |= PS2_FLAG_CMD | PS2_FLAG_CMD1; + if (param) + for (i = 0; i < receive; i++) + ps2dev->cmdbuf[(receive - 1) - i] = param[i]; + } /* - * Some devices (Synaptics) peform the reset before + * Some devices (Synaptics) perform the reset before * ACKing the reset command, and so it can take a long * time before the ACK arrives. */ @@ -267,9 +326,7 @@ int __ps2_command(struct ps2dev *ps2dev, u8 *param, unsigned int command) if (rc) goto out_reset_flags; - /* Now we are sending command parameters, if any */ - ps2dev->flags &= ~PS2_FLAG_ACK_CMD; - + /* Send command parameters, if any. */ for (i = 0; i < send; i++) { rc = ps2_do_sendbyte(ps2dev, param[i], 200, 2); if (rc) @@ -327,6 +384,20 @@ int __ps2_command(struct ps2dev *ps2dev, u8 *param, unsigned int command) } EXPORT_SYMBOL(__ps2_command); +/** + * ps2_command - send a command to PS/2 device + * @ps2dev: the PS/2 device that should execute the command + * @param: a buffer containing parameters to be sent along with the command, + * or place where the results of the command execution will be deposited, + * or both + * @command: command word that encodes the command itself, as well as number of + * additional parameter bytes that should be sent to the device and expected + * length of the command response + * + * Note: ps2_command() serializes the command execution so that only one + * command can be executed at a time for either individual port or the entire + * 8042 controller. + */ int ps2_command(struct ps2dev *ps2dev, u8 *param, unsigned int command) { int rc; @@ -339,14 +410,16 @@ int ps2_command(struct ps2dev *ps2dev, u8 *param, unsigned int command) } EXPORT_SYMBOL(ps2_command); -/* - * ps2_sliced_command() sends an extended PS/2 command to the mouse - * using sliced syntax, understood by advanced devices, such as Logitech - * or Synaptics touchpads. The command is encoded as: +/** + * ps2_sliced_command - sends an extended PS/2 command to a mouse + * @ps2dev: the PS/2 device that should execute the command + * @command: command byte + * + * The command is sent using "sliced" syntax understood by advanced devices, + * such as Logitech or Synaptics touchpads. The command is encoded as: * 0xE6 0xE8 rr 0xE8 ss 0xE8 tt 0xE8 uu where (rr*64)+(ss*16)+(tt*4)+uu * is the command. */ - int ps2_sliced_command(struct ps2dev *ps2dev, u8 command) { int i; @@ -372,25 +445,60 @@ int ps2_sliced_command(struct ps2dev *ps2dev, u8 command) } EXPORT_SYMBOL(ps2_sliced_command); -/* - * ps2_init() initializes ps2dev structure +/** + * ps2_init - initializes ps2dev structure + * @ps2dev: structure to be initialized + * @serio: serio port associated with the PS/2 device + * @pre_receive_handler: validation handler to check basic communication state + * @receive_handler: main protocol handler + * + * Prepares ps2dev structure for use in drivers for PS/2 devices. */ - -void ps2_init(struct ps2dev *ps2dev, struct serio *serio) +void ps2_init(struct ps2dev *ps2dev, struct serio *serio, + ps2_pre_receive_handler_t pre_receive_handler, + ps2_receive_handler_t receive_handler) { + ps2dev->pre_receive_handler = pre_receive_handler; + ps2dev->receive_handler = receive_handler; + mutex_init(&ps2dev->cmd_mutex); lockdep_set_subclass(&ps2dev->cmd_mutex, serio->depth); init_waitqueue_head(&ps2dev->wait); ps2dev->serio = serio; + serio_set_drvdata(serio, ps2dev); } EXPORT_SYMBOL(ps2_init); /* - * ps2_handle_ack() is supposed to be used in interrupt handler - * to properly process ACK/NAK of a command from a PS/2 device. + * ps2_handle_response() stores device's response to a command and notifies + * the process waiting for completion of the command. Note that there is a + * distinction between waiting for the first byte of the response, and + * waiting for subsequent bytes. It is done so that callers could shorten + * timeouts once first byte of response is received. */ +static void ps2_handle_response(struct ps2dev *ps2dev, u8 data) +{ + if (ps2dev->cmdcnt) + ps2dev->cmdbuf[--ps2dev->cmdcnt] = data; + + if (ps2dev->flags & PS2_FLAG_CMD1) { + ps2dev->flags &= ~PS2_FLAG_CMD1; + if (ps2dev->cmdcnt) + wake_up(&ps2dev->wait); + } + + if (!ps2dev->cmdcnt) { + ps2dev->flags &= ~PS2_FLAG_CMD; + wake_up(&ps2dev->wait); + } +} -bool ps2_handle_ack(struct ps2dev *ps2dev, u8 data) +/* + * ps2_handle_ack() processes ACK/NAK of a command from a PS/2 device, + * possibly applying workarounds for mice not acknowledging the "get ID" + * command. + */ +static void ps2_handle_ack(struct ps2dev *ps2dev, u8 data) { switch (data) { case PS2_RET_ACK: @@ -427,68 +535,89 @@ bool ps2_handle_ack(struct ps2dev *ps2dev, u8 data) * Do not signal errors if we get unexpected reply while * waiting for an ACK to the initial (first) command byte: * the device might not be quiesced yet and continue - * delivering data. + * delivering data. For certain commands (such as set leds and + * set repeat rate) that can be used during normal device + * operation, we even pass this data byte to the normal receive + * handler. * Note that we reset PS2_FLAG_WAITID flag, so the workaround * for mice not acknowledging the Get ID command only triggers * on the 1st byte; if device spews data we really want to see * a real ACK from it. */ dev_dbg(&ps2dev->serio->dev, "unexpected %#02x\n", data); - ps2dev->flags &= ~PS2_FLAG_WAITID; - return ps2dev->flags & PS2_FLAG_ACK_CMD; + if (ps2dev->flags & PS2_FLAG_PASS_NOACK) + ps2dev->receive_handler(ps2dev, data); + ps2dev->flags &= ~(PS2_FLAG_WAITID | PS2_FLAG_PASS_NOACK); + return; } - if (!ps2dev->nak) { + if (!ps2dev->nak) ps2dev->flags &= ~PS2_FLAG_NAK; - if (ps2dev->cmdcnt) - ps2dev->flags |= PS2_FLAG_CMD | PS2_FLAG_CMD1; - } ps2dev->flags &= ~PS2_FLAG_ACK; - wake_up(&ps2dev->wait); - if (data != PS2_RET_ACK) + if (!ps2dev->nak && data != PS2_RET_ACK) ps2_handle_response(ps2dev, data); - - return true; + else + wake_up(&ps2dev->wait); } -EXPORT_SYMBOL(ps2_handle_ack); /* - * ps2_handle_response() is supposed to be used in interrupt handler - * to properly store device's response to a command and notify process - * waiting for completion of the command. + * Clears state of PS/2 device after communication error by resetting majority + * of flags and waking up waiters, if any. */ - -bool ps2_handle_response(struct ps2dev *ps2dev, u8 data) +static void ps2_cleanup(struct ps2dev *ps2dev) { - if (ps2dev->cmdcnt) - ps2dev->cmdbuf[--ps2dev->cmdcnt] = data; + unsigned long old_flags = ps2dev->flags; - if (ps2dev->flags & PS2_FLAG_CMD1) { - ps2dev->flags &= ~PS2_FLAG_CMD1; - if (ps2dev->cmdcnt) - wake_up(&ps2dev->wait); - } + /* reset all flags except last nak */ + ps2dev->flags &= PS2_FLAG_NAK; - if (!ps2dev->cmdcnt) { - ps2dev->flags &= ~PS2_FLAG_CMD; - wake_up(&ps2dev->wait); - } + if (old_flags & PS2_FLAG_ACK) + ps2dev->nak = 1; - return true; + if (old_flags & (PS2_FLAG_ACK | PS2_FLAG_CMD)) + wake_up(&ps2dev->wait); } -EXPORT_SYMBOL(ps2_handle_response); -void ps2_cmd_aborted(struct ps2dev *ps2dev) -{ - if (ps2dev->flags & PS2_FLAG_ACK) - ps2dev->nak = 1; +/** + * ps2_interrupt - common interrupt handler for PS/2 devices + * @serio: serio port for the device + * @data: a data byte received from the device + * @flags: flags such as %SERIO_PARITY or %SERIO_TIMEOUT indicating state of + * the data transfer + * + * ps2_interrupt() invokes pre-receive handler, optionally handles command + * acknowledgement and response from the device, and finally passes the data + * to the main protocol handler for future processing. + */ +irqreturn_t ps2_interrupt(struct serio *serio, u8 data, unsigned int flags) { + struct ps2dev *ps2dev = serio_get_drvdata(serio); + enum ps2_disposition rc; + + rc = ps2dev->pre_receive_handler(ps2dev, data, flags); + switch (rc) { + case PS2_ERROR: + ps2_cleanup(ps2dev); + break; - if (ps2dev->flags & (PS2_FLAG_ACK | PS2_FLAG_CMD)) - wake_up(&ps2dev->wait); + case PS2_IGNORE: + break; - /* reset all flags except last nack */ - ps2dev->flags &= PS2_FLAG_NAK; + case PS2_PROCESS: + if (ps2dev->flags & PS2_FLAG_ACK) + ps2_handle_ack(ps2dev, data); + else if (ps2dev->flags & PS2_FLAG_CMD) + ps2_handle_response(ps2dev, data); + else + ps2dev->receive_handler(ps2dev, data); + break; + } + + return IRQ_HANDLED; } -EXPORT_SYMBOL(ps2_cmd_aborted); +EXPORT_SYMBOL(ps2_interrupt); + +MODULE_AUTHOR("Dmitry Torokhov "); +MODULE_DESCRIPTION("PS/2 driver library"); +MODULE_LICENSE("GPL"); diff --git a/drivers/input/tests/input_test.c b/drivers/input/tests/input_test.c index e5a6c1ad2167c103c20fdd289a2df43245a4dae3..2fa5b725ae0a2a86cc8763e2d1d96b37c7f2a7af 100644 --- a/drivers/input/tests/input_test.c +++ b/drivers/input/tests/input_test.c @@ -43,8 +43,8 @@ static void input_test_exit(struct kunit *test) { struct input_dev *input_dev = test->priv; - input_unregister_device(input_dev); - input_free_device(input_dev); + if (input_dev) + input_unregister_device(input_dev); } static void input_test_poll(struct input_dev *input) { } @@ -87,7 +87,7 @@ static void input_test_timestamp(struct kunit *test) static void input_test_match_device_id(struct kunit *test) { struct input_dev *input_dev = test->priv; - struct input_device_id id; + struct input_device_id id = { 0 }; /* * Must match when the input device bus, vendor, product, version @@ -130,10 +130,42 @@ static void input_test_match_device_id(struct kunit *test) KUNIT_ASSERT_FALSE(test, input_match_device_id(input_dev, &id)); } +static void input_test_grab(struct kunit *test) +{ + struct input_dev *input_dev = test->priv; + struct input_handle test_handle; + struct input_handler handler; + struct input_handle handle; + struct input_device_id id; + int res; + + handler.name = "handler"; + handler.id_table = &id; + + handle.dev = input_get_device(input_dev); + handle.name = dev_name(&input_dev->dev); + handle.handler = &handler; + res = input_grab_device(&handle); + KUNIT_ASSERT_TRUE(test, res == 0); + + test_handle.dev = input_get_device(input_dev); + test_handle.name = dev_name(&input_dev->dev); + test_handle.handler = &handler; + res = input_grab_device(&test_handle); + KUNIT_ASSERT_EQ(test, res, -EBUSY); + + input_release_device(&handle); + input_put_device(input_dev); + res = input_grab_device(&test_handle); + KUNIT_ASSERT_TRUE(test, res == 0); + input_put_device(input_dev); +} + static struct kunit_case input_tests[] = { KUNIT_CASE(input_test_polling), KUNIT_CASE(input_test_timestamp), KUNIT_CASE(input_test_match_device_id), + KUNIT_CASE(input_test_grab), { /* sentinel */ } }; diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 143ff43c67ae339ed38e33ac32f8db85afff9744..c2cbd332af1dfabd17ad339a75efd5b76c9c943b 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -700,6 +700,7 @@ config TOUCHSCREEN_INEXIO config TOUCHSCREEN_MK712 tristate "ICS MicroClock MK712 touchscreen" + depends on ISA help Say Y here if you have the ICS MicroClock MK712 touchscreen controller chip in your system. diff --git a/drivers/input/touchscreen/ad7879-i2c.c b/drivers/input/touchscreen/ad7879-i2c.c index dd8f31737bb8258cc3c8c22d8027fce182b3fff5..feaa6f8b01ed67baea5de8c8a9dc853b21e8da1e 100644 --- a/drivers/input/touchscreen/ad7879-i2c.c +++ b/drivers/input/touchscreen/ad7879-i2c.c @@ -62,7 +62,7 @@ static struct i2c_driver ad7879_i2c_driver = { .pm = &ad7879_pm_ops, .of_match_table = of_match_ptr(ad7879_i2c_dt_ids), }, - .probe_new = ad7879_i2c_probe, + .probe = ad7879_i2c_probe, .id_table = ad7879_id, }; diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c index bb1058b1e7fd453f97f835e0d88cc90fa512ce44..faea40dd66d01862f22e6fc50a95e4c044abfbb1 100644 --- a/drivers/input/touchscreen/ads7846.c +++ b/drivers/input/touchscreen/ads7846.c @@ -24,11 +24,8 @@ #include #include #include -#include -#include -#include +#include #include -#include #include #include #include @@ -140,7 +137,7 @@ struct ads7846 { int (*filter)(void *data, int data_idx, int *val); void *filter_data; int (*get_pendown_state)(void); - int gpio_pendown; + struct gpio_desc *gpio_pendown; void (*wait_for_sync)(void); }; @@ -223,7 +220,7 @@ static int get_pendown_state(struct ads7846 *ts) if (ts->get_pendown_state) return ts->get_pendown_state(); - return !gpio_get_value(ts->gpio_pendown); + return gpiod_get_value(ts->gpio_pendown); } static void ads7846_report_pen_up(struct ads7846 *ts) @@ -989,8 +986,6 @@ static int ads7846_setup_pendown(struct spi_device *spi, struct ads7846 *ts, const struct ads7846_platform_data *pdata) { - int err; - /* * REVISIT when the irq can be triggered active-low, or if for some * reason the touchscreen isn't hooked up, we don't need to access @@ -999,25 +994,15 @@ static int ads7846_setup_pendown(struct spi_device *spi, if (pdata->get_pendown_state) { ts->get_pendown_state = pdata->get_pendown_state; - } else if (gpio_is_valid(pdata->gpio_pendown)) { - - err = devm_gpio_request_one(&spi->dev, pdata->gpio_pendown, - GPIOF_IN, "ads7846_pendown"); - if (err) { - dev_err(&spi->dev, - "failed to request/setup pendown GPIO%d: %d\n", - pdata->gpio_pendown, err); - return err; + } else { + ts->gpio_pendown = gpiod_get(&spi->dev, "pendown", GPIOD_IN); + if (IS_ERR(ts->gpio_pendown)) { + dev_err(&spi->dev, "failed to request pendown GPIO\n"); + return PTR_ERR(ts->gpio_pendown); } - - ts->gpio_pendown = pdata->gpio_pendown; - if (pdata->gpio_pendown_debounce) - gpiod_set_debounce(gpio_to_desc(ts->gpio_pendown), + gpiod_set_debounce(ts->gpio_pendown, pdata->gpio_pendown_debounce); - } else { - dev_err(&spi->dev, "no get_pendown_state nor gpio_pendown?\n"); - return -EINVAL; } return 0; @@ -1119,7 +1104,6 @@ static int ads7846_setup_spi_msg(struct ads7846 *ts, return 0; } -#ifdef CONFIG_OF static const struct of_device_id ads7846_dt_ids[] = { { .compatible = "ti,tsc2046", .data = (void *) 7846 }, { .compatible = "ti,ads7843", .data = (void *) 7843 }, @@ -1130,82 +1114,60 @@ static const struct of_device_id ads7846_dt_ids[] = { }; MODULE_DEVICE_TABLE(of, ads7846_dt_ids); -static const struct ads7846_platform_data *ads7846_probe_dt(struct device *dev) +static const struct ads7846_platform_data *ads7846_get_props(struct device *dev) { struct ads7846_platform_data *pdata; - struct device_node *node = dev->of_node; - const struct of_device_id *match; u32 value; - if (!node) { - dev_err(dev, "Device does not have associated DT data\n"); - return ERR_PTR(-EINVAL); - } - - match = of_match_device(ads7846_dt_ids, dev); - if (!match) { - dev_err(dev, "Unknown device model\n"); - return ERR_PTR(-EINVAL); - } - pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); if (!pdata) return ERR_PTR(-ENOMEM); - pdata->model = (unsigned long)match->data; + pdata->model = (uintptr_t)device_get_match_data(dev); - of_property_read_u16(node, "ti,vref-delay-usecs", - &pdata->vref_delay_usecs); - of_property_read_u16(node, "ti,vref-mv", &pdata->vref_mv); - pdata->keep_vref_on = of_property_read_bool(node, "ti,keep-vref-on"); + device_property_read_u16(dev, "ti,vref-delay-usecs", + &pdata->vref_delay_usecs); + device_property_read_u16(dev, "ti,vref-mv", &pdata->vref_mv); + pdata->keep_vref_on = device_property_read_bool(dev, "ti,keep-vref-on"); - pdata->swap_xy = of_property_read_bool(node, "ti,swap-xy"); + pdata->swap_xy = device_property_read_bool(dev, "ti,swap-xy"); - of_property_read_u16(node, "ti,settle-delay-usec", - &pdata->settle_delay_usecs); - of_property_read_u16(node, "ti,penirq-recheck-delay-usecs", - &pdata->penirq_recheck_delay_usecs); + device_property_read_u16(dev, "ti,settle-delay-usec", + &pdata->settle_delay_usecs); + device_property_read_u16(dev, "ti,penirq-recheck-delay-usecs", + &pdata->penirq_recheck_delay_usecs); - of_property_read_u16(node, "ti,x-plate-ohms", &pdata->x_plate_ohms); - of_property_read_u16(node, "ti,y-plate-ohms", &pdata->y_plate_ohms); + device_property_read_u16(dev, "ti,x-plate-ohms", &pdata->x_plate_ohms); + device_property_read_u16(dev, "ti,y-plate-ohms", &pdata->y_plate_ohms); - of_property_read_u16(node, "ti,x-min", &pdata->x_min); - of_property_read_u16(node, "ti,y-min", &pdata->y_min); - of_property_read_u16(node, "ti,x-max", &pdata->x_max); - of_property_read_u16(node, "ti,y-max", &pdata->y_max); + device_property_read_u16(dev, "ti,x-min", &pdata->x_min); + device_property_read_u16(dev, "ti,y-min", &pdata->y_min); + device_property_read_u16(dev, "ti,x-max", &pdata->x_max); + device_property_read_u16(dev, "ti,y-max", &pdata->y_max); /* * touchscreen-max-pressure gets parsed during * touchscreen_parse_properties() */ - of_property_read_u16(node, "ti,pressure-min", &pdata->pressure_min); - if (!of_property_read_u32(node, "touchscreen-min-pressure", &value)) + device_property_read_u16(dev, "ti,pressure-min", &pdata->pressure_min); + if (!device_property_read_u32(dev, "touchscreen-min-pressure", &value)) pdata->pressure_min = (u16) value; - of_property_read_u16(node, "ti,pressure-max", &pdata->pressure_max); + device_property_read_u16(dev, "ti,pressure-max", &pdata->pressure_max); - of_property_read_u16(node, "ti,debounce-max", &pdata->debounce_max); - if (!of_property_read_u32(node, "touchscreen-average-samples", &value)) + device_property_read_u16(dev, "ti,debounce-max", &pdata->debounce_max); + if (!device_property_read_u32(dev, "touchscreen-average-samples", &value)) pdata->debounce_max = (u16) value; - of_property_read_u16(node, "ti,debounce-tol", &pdata->debounce_tol); - of_property_read_u16(node, "ti,debounce-rep", &pdata->debounce_rep); + device_property_read_u16(dev, "ti,debounce-tol", &pdata->debounce_tol); + device_property_read_u16(dev, "ti,debounce-rep", &pdata->debounce_rep); - of_property_read_u32(node, "ti,pendown-gpio-debounce", + device_property_read_u32(dev, "ti,pendown-gpio-debounce", &pdata->gpio_pendown_debounce); - pdata->wakeup = of_property_read_bool(node, "wakeup-source") || - of_property_read_bool(node, "linux,wakeup"); - - pdata->gpio_pendown = of_get_named_gpio(dev->of_node, "pendown-gpio", 0); + pdata->wakeup = device_property_read_bool(dev, "wakeup-source") || + device_property_read_bool(dev, "linux,wakeup"); return pdata; } -#else -static const struct ads7846_platform_data *ads7846_probe_dt(struct device *dev) -{ - dev_err(dev, "no platform data defined\n"); - return ERR_PTR(-EINVAL); -} -#endif static void ads7846_regulator_disable(void *regulator) { @@ -1269,7 +1231,7 @@ static int ads7846_probe(struct spi_device *spi) pdata = dev_get_platdata(dev); if (!pdata) { - pdata = ads7846_probe_dt(dev); + pdata = ads7846_get_props(dev); if (IS_ERR(pdata)) return PTR_ERR(pdata); } @@ -1426,7 +1388,7 @@ static struct spi_driver ads7846_driver = { .driver = { .name = "ads7846", .pm = pm_sleep_ptr(&ads7846_pm), - .of_match_table = of_match_ptr(ads7846_dt_ids), + .of_match_table = ads7846_dt_ids, }, .probe = ads7846_probe, .remove = ads7846_remove, diff --git a/drivers/input/touchscreen/ar1021_i2c.c b/drivers/input/touchscreen/ar1021_i2c.c index 3a5b65cae360ab76f1ac78f980c4c88d23c06aa4..64dfb749386fc861f17993dac564f42f5da13601 100644 --- a/drivers/input/touchscreen/ar1021_i2c.c +++ b/drivers/input/touchscreen/ar1021_i2c.c @@ -182,7 +182,7 @@ static struct i2c_driver ar1021_i2c_driver = { .of_match_table = ar1021_i2c_of_match, }, - .probe_new = ar1021_i2c_probe, + .probe = ar1021_i2c_probe, .id_table = ar1021_i2c_id, }; module_i2c_driver(ar1021_i2c_driver); diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 996bf434e1cbb0811f13ed6d99be7d658c8942b6..20094b9899f093671ed95a1db0a8551449ff3cbb 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -55,6 +55,7 @@ #define MXT_TOUCH_KEYARRAY_T15 15 #define MXT_TOUCH_PROXIMITY_T23 23 #define MXT_TOUCH_PROXKEY_T52 52 +#define MXT_TOUCH_PTC_KEYS_T97 97 #define MXT_PROCI_GRIPFACE_T20 20 #define MXT_PROCG_NOISE_T22 22 #define MXT_PROCI_ONETOUCH_T24 24 @@ -326,9 +327,13 @@ struct mxt_data { u16 T71_address; u8 T9_reportid_min; u8 T9_reportid_max; + u8 T15_reportid_min; + u8 T15_reportid_max; u16 T18_address; u8 T19_reportid; u16 T44_address; + u8 T97_reportid_min; + u8 T97_reportid_max; u8 T100_reportid_min; u8 T100_reportid_max; @@ -344,6 +349,9 @@ struct mxt_data { u32 *t19_keymap; unsigned int t19_num_keys; + u32 *t15_keymap; + unsigned int t15_num_keys; + enum mxt_suspend_mode suspend_mode; u32 wakeup_method; @@ -375,6 +383,7 @@ static bool mxt_object_readable(unsigned int type) case MXT_TOUCH_KEYARRAY_T15: case MXT_TOUCH_PROXIMITY_T23: case MXT_TOUCH_PROXKEY_T52: + case MXT_TOUCH_PTC_KEYS_T97: case MXT_TOUCH_MULTITOUCHSCREEN_T100: case MXT_PROCI_GRIPFACE_T20: case MXT_PROCG_NOISE_T22: @@ -891,6 +900,24 @@ static void mxt_proc_t9_message(struct mxt_data *data, u8 *message) data->update_input = true; } +static void mxt_proc_t15_messages(struct mxt_data *data, u8 *message) +{ + struct input_dev *input_dev = data->input_dev; + unsigned long keystates = get_unaligned_le32(&message[2]); + int key; + + for (key = 0; key < data->t15_num_keys; key++) + input_report_key(input_dev, data->t15_keymap[key], + keystates & BIT(key)); + + data->update_input = true; +} + +static void mxt_proc_t97_messages(struct mxt_data *data, u8 *message) +{ + mxt_proc_t15_messages(data, message); +} + static void mxt_proc_t100_message(struct mxt_data *data, u8 *message) { struct device *dev = &data->client->dev; @@ -1017,6 +1044,12 @@ static int mxt_proc_message(struct mxt_data *data, u8 *message) } else if (report_id >= data->T9_reportid_min && report_id <= data->T9_reportid_max) { mxt_proc_t9_message(data, message); + } else if (report_id >= data->T15_reportid_min && + report_id <= data->T15_reportid_max) { + mxt_proc_t15_messages(data, message); + } else if (report_id >= data->T97_reportid_min && + report_id <= data->T97_reportid_max) { + mxt_proc_t97_messages(data, message); } else if (report_id >= data->T100_reportid_min && report_id <= data->T100_reportid_max) { mxt_proc_t100_message(data, message); @@ -1689,9 +1722,13 @@ static void mxt_free_object_table(struct mxt_data *data) data->T71_address = 0; data->T9_reportid_min = 0; data->T9_reportid_max = 0; + data->T15_reportid_min = 0; + data->T15_reportid_max = 0; data->T18_address = 0; data->T19_reportid = 0; data->T44_address = 0; + data->T97_reportid_min = 0; + data->T97_reportid_max = 0; data->T100_reportid_min = 0; data->T100_reportid_max = 0; data->max_reportid = 0; @@ -1764,6 +1801,10 @@ static int mxt_parse_object_table(struct mxt_data *data, object->num_report_ids - 1; data->num_touchids = object->num_report_ids; break; + case MXT_TOUCH_KEYARRAY_T15: + data->T15_reportid_min = min_id; + data->T15_reportid_max = max_id; + break; case MXT_SPT_COMMSCONFIG_T18: data->T18_address = object->start_address; break; @@ -1773,6 +1814,10 @@ static int mxt_parse_object_table(struct mxt_data *data, case MXT_SPT_GPIOPWM_T19: data->T19_reportid = min_id; break; + case MXT_TOUCH_PTC_KEYS_T97: + data->T97_reportid_min = min_id; + data->T97_reportid_max = max_id; + break; case MXT_TOUCH_MULTITOUCHSCREEN_T100: data->multitouch = MXT_TOUCH_MULTITOUCHSCREEN_T100; data->T100_reportid_min = min_id; @@ -2050,6 +2095,7 @@ static int mxt_initialize_input_device(struct mxt_data *data) int error; unsigned int num_mt_slots; unsigned int mt_flags = 0; + int i; switch (data->multitouch) { case MXT_TOUCH_MULTI_T9: @@ -2095,6 +2141,10 @@ static int mxt_initialize_input_device(struct mxt_data *data) input_dev->open = mxt_input_open; input_dev->close = mxt_input_close; + input_dev->keycode = data->t15_keymap; + input_dev->keycodemax = data->t15_num_keys; + input_dev->keycodesize = sizeof(data->t15_keymap[0]); + input_set_capability(input_dev, EV_KEY, BTN_TOUCH); /* For single touch */ @@ -2162,6 +2212,13 @@ static int mxt_initialize_input_device(struct mxt_data *data) 0, 255, 0, 0); } + /* For T15 and T97 Key Array */ + if (data->T15_reportid_min || data->T97_reportid_min) { + for (i = 0; i < data->t15_num_keys; i++) + input_set_capability(input_dev, + EV_KEY, data->t15_keymap[i]); + } + input_set_drvdata(input_dev, data); error = input_register_device(input_dev); @@ -3080,8 +3137,10 @@ static void mxt_input_close(struct input_dev *dev) static int mxt_parse_device_properties(struct mxt_data *data) { static const char keymap_property[] = "linux,gpio-keymap"; + static const char buttons_property[] = "linux,keycodes"; struct device *dev = &data->client->dev; u32 *keymap; + u32 *buttonmap; int n_keys; int error; @@ -3111,6 +3170,32 @@ static int mxt_parse_device_properties(struct mxt_data *data) data->t19_num_keys = n_keys; } + if (device_property_present(dev, buttons_property)) { + n_keys = device_property_count_u32(dev, buttons_property); + if (n_keys <= 0) { + error = n_keys < 0 ? n_keys : -EINVAL; + dev_err(dev, "invalid/malformed '%s' property: %d\n", + buttons_property, error); + return error; + } + + buttonmap = devm_kmalloc_array(dev, n_keys, sizeof(*buttonmap), + GFP_KERNEL); + if (!buttonmap) + return -ENOMEM; + + error = device_property_read_u32_array(dev, buttons_property, + buttonmap, n_keys); + if (error) { + dev_err(dev, "failed to parse '%s' property: %d\n", + buttons_property, error); + return error; + } + + data->t15_keymap = buttonmap; + data->t15_num_keys = n_keys; + } + return 0; } @@ -3377,7 +3462,7 @@ static struct i2c_driver mxt_driver = { .acpi_match_table = ACPI_PTR(mxt_acpi_id), .pm = pm_sleep_ptr(&mxt_pm_ops), }, - .probe_new = mxt_probe, + .probe = mxt_probe, .remove = mxt_remove, .id_table = mxt_id, }; diff --git a/drivers/input/touchscreen/auo-pixcir-ts.c b/drivers/input/touchscreen/auo-pixcir-ts.c index 5359efc80b2bcaec489213f9a81c05bdddd9126f..90c682e7407f98c8588c85444b370682e47e7b62 100644 --- a/drivers/input/touchscreen/auo-pixcir-ts.c +++ b/drivers/input/touchscreen/auo-pixcir-ts.c @@ -636,7 +636,7 @@ static struct i2c_driver auo_pixcir_driver = { .pm = pm_sleep_ptr(&auo_pixcir_pm_ops), .of_match_table = of_match_ptr(auo_pixcir_ts_dt_idtable), }, - .probe_new = auo_pixcir_probe, + .probe = auo_pixcir_probe, .id_table = auo_pixcir_idtable, }; diff --git a/drivers/input/touchscreen/bu21013_ts.c b/drivers/input/touchscreen/bu21013_ts.c index c994ab6f4e58b5184729e5f80e4d1264eabf434f..85332cfaa29dc92718a90c812ff30e8368e79da2 100644 --- a/drivers/input/touchscreen/bu21013_ts.c +++ b/drivers/input/touchscreen/bu21013_ts.c @@ -617,7 +617,7 @@ static struct i2c_driver bu21013_driver = { .name = DRIVER_TP, .pm = pm_sleep_ptr(&bu21013_dev_pm_ops), }, - .probe_new = bu21013_probe, + .probe = bu21013_probe, .remove = bu21013_remove, .id_table = bu21013_id, }; diff --git a/drivers/input/touchscreen/bu21029_ts.c b/drivers/input/touchscreen/bu21029_ts.c index 8f1442894ff951a22e8fc5d429569396c7cdf647..c8126d2efe95a9c4c6ed8e8d819d516a65e2aa81 100644 --- a/drivers/input/touchscreen/bu21029_ts.c +++ b/drivers/input/touchscreen/bu21029_ts.c @@ -474,7 +474,7 @@ static struct i2c_driver bu21029_driver = { .pm = pm_sleep_ptr(&bu21029_pm_ops), }, .id_table = bu21029_ids, - .probe_new = bu21029_probe, + .probe = bu21029_probe, }; module_i2c_driver(bu21029_driver); diff --git a/drivers/input/touchscreen/chipone_icn8318.c b/drivers/input/touchscreen/chipone_icn8318.c index 32b714a6ed2d5f85061b4acb5a198dbcc12b61bd..9fbeaf17f00b70ea2ae604f18a578459b3220924 100644 --- a/drivers/input/touchscreen/chipone_icn8318.c +++ b/drivers/input/touchscreen/chipone_icn8318.c @@ -264,7 +264,7 @@ static struct i2c_driver icn8318_driver = { .pm = pm_sleep_ptr(&icn8318_pm_ops), .of_match_table = icn8318_of_match, }, - .probe_new = icn8318_probe, + .probe = icn8318_probe, .id_table = icn8318_i2c_id, }; diff --git a/drivers/input/touchscreen/chipone_icn8505.c b/drivers/input/touchscreen/chipone_icn8505.c index 246bee0bee5336859120295556b8e8d90bc3695c..b56954830b3398a25ff7f725460bae57e242cd12 100644 --- a/drivers/input/touchscreen/chipone_icn8505.c +++ b/drivers/input/touchscreen/chipone_icn8505.c @@ -498,7 +498,7 @@ static struct i2c_driver icn8505_driver = { .pm = pm_sleep_ptr(&icn8505_pm_ops), .acpi_match_table = icn8505_acpi_match, }, - .probe_new = icn8505_probe, + .probe = icn8505_probe, }; module_i2c_driver(icn8505_driver); diff --git a/drivers/input/touchscreen/cy8ctma140.c b/drivers/input/touchscreen/cy8ctma140.c index cd86477d971a3dd2795f787df794ce7713a03259..967ecde23e83ff53cc6c17c40baddec88b7be138 100644 --- a/drivers/input/touchscreen/cy8ctma140.c +++ b/drivers/input/touchscreen/cy8ctma140.c @@ -344,7 +344,7 @@ static struct i2c_driver cy8ctma140_driver = { .of_match_table = cy8ctma140_of_match, }, .id_table = cy8ctma140_idtable, - .probe_new = cy8ctma140_probe, + .probe = cy8ctma140_probe, }; module_i2c_driver(cy8ctma140_driver); diff --git a/drivers/input/touchscreen/cy8ctmg110_ts.c b/drivers/input/touchscreen/cy8ctmg110_ts.c index dcf50fbf6dc7e8c6dd3966430f8d26ec88fcfd7c..54d6c4869eb02de179138df50b030d2da4b36c88 100644 --- a/drivers/input/touchscreen/cy8ctmg110_ts.c +++ b/drivers/input/touchscreen/cy8ctmg110_ts.c @@ -279,7 +279,7 @@ static struct i2c_driver cy8ctmg110_driver = { .pm = pm_sleep_ptr(&cy8ctmg110_pm), }, .id_table = cy8ctmg110_idtable, - .probe_new = cy8ctmg110_probe, + .probe = cy8ctmg110_probe, }; module_i2c_driver(cy8ctmg110_driver); diff --git a/drivers/input/touchscreen/cyttsp4_core.c b/drivers/input/touchscreen/cyttsp4_core.c index 0cd6f626adec5d624cd5fb88adec356d2158d85b..7cb26929dc7328930e09be8416ca67aa9c871a7d 100644 --- a/drivers/input/touchscreen/cyttsp4_core.c +++ b/drivers/input/touchscreen/cyttsp4_core.c @@ -1263,9 +1263,8 @@ static void cyttsp4_stop_wd_timer(struct cyttsp4 *cd) * Ensure we wait until the watchdog timer * running on a different CPU finishes */ - del_timer_sync(&cd->watchdog_timer); + timer_shutdown_sync(&cd->watchdog_timer); cancel_work_sync(&cd->watchdog_work); - del_timer_sync(&cd->watchdog_timer); } static void cyttsp4_watchdog_timer(struct timer_list *t) diff --git a/drivers/input/touchscreen/cyttsp4_i2c.c b/drivers/input/touchscreen/cyttsp4_i2c.c index ec7a4779f3fbf8f3c762efe191dcc7190439692f..80a6890cd45a0bc5b1101c864bb35691d1543235 100644 --- a/drivers/input/touchscreen/cyttsp4_i2c.c +++ b/drivers/input/touchscreen/cyttsp4_i2c.c @@ -60,7 +60,7 @@ static struct i2c_driver cyttsp4_i2c_driver = { .name = CYTTSP4_I2C_NAME, .pm = pm_ptr(&cyttsp4_pm_ops), }, - .probe_new = cyttsp4_i2c_probe, + .probe = cyttsp4_i2c_probe, .remove = cyttsp4_i2c_remove, .id_table = cyttsp4_i2c_id, }; diff --git a/drivers/input/touchscreen/cyttsp5.c b/drivers/input/touchscreen/cyttsp5.c index 3c9d07218f48dfc52bb59fe0be008d8e4915f586..b461ded946fc892bbc5c08eac54983d2d5fd8b9e 100644 --- a/drivers/input/touchscreen/cyttsp5.c +++ b/drivers/input/touchscreen/cyttsp5.c @@ -43,6 +43,7 @@ #define HID_DESC_REG 0x1 #define HID_INPUT_REG 0x3 #define HID_OUTPUT_REG 0x4 +#define HID_COMMAND_REG 0x5 #define REPORT_ID_TOUCH 0x1 #define REPORT_ID_BTN 0x3 @@ -68,6 +69,7 @@ #define HID_APP_OUTPUT_REPORT_ID 0x2F #define HID_BL_RESPONSE_REPORT_ID 0x30 #define HID_BL_OUTPUT_REPORT_ID 0x40 +#define HID_RESPONSE_REPORT_ID 0xF0 #define HID_OUTPUT_RESPONSE_REPORT_OFFSET 2 #define HID_OUTPUT_RESPONSE_CMD_OFFSET 4 @@ -78,9 +80,15 @@ #define HID_SYSINFO_BTN_MASK GENMASK(7, 0) #define HID_SYSINFO_MAX_BTN 8 +#define HID_CMD_SET_POWER 0x8 + +#define HID_POWER_ON 0x0 +#define HID_POWER_SLEEP 0x1 + #define CY_HID_OUTPUT_TIMEOUT_MS 200 #define CY_HID_OUTPUT_GET_SYSINFO_TIMEOUT_MS 3000 #define CY_HID_GET_HID_DESCRIPTOR_TIMEOUT_MS 4000 +#define CY_HID_SET_POWER_TIMEOUT 500 /* maximum number of concurrent tracks */ #define TOUCH_REPORT_SIZE 10 @@ -100,6 +108,14 @@ #define TOUCH_REPORT_USAGE_PG_MIN 0xFF010063 #define TOUCH_COL_USAGE_PG 0x000D0022 +#define SET_CMD_LOW(byte, bits) \ + ((byte) = (((byte) & 0xF0) | ((bits) & 0x0F))) +#define SET_CMD_HIGH(byte, bits)\ + ((byte) = (((byte) & 0x0F) | ((bits) & 0xF0))) +#define SET_CMD_OPCODE(byte, opcode) SET_CMD_LOW(byte, opcode) +#define SET_CMD_REPORT_TYPE(byte, type) SET_CMD_HIGH(byte, ((type) << 4)) +#define SET_CMD_REPORT_ID(byte, id) SET_CMD_LOW(byte, id) + /* System Information interface definitions */ struct cyttsp5_sensing_conf_data_dev { u8 electrodes_x; @@ -557,6 +573,40 @@ static int cyttsp5_hid_output_get_sysinfo(struct cyttsp5 *ts) return cyttsp5_get_sysinfo_regs(ts); } +static int cyttsp5_power_control(struct cyttsp5 *ts, bool on) +{ + u8 state = on ? HID_POWER_ON : HID_POWER_SLEEP; + u8 cmd[2] = { 0 }; + int rc; + + SET_CMD_REPORT_TYPE(cmd[0], 0); + SET_CMD_REPORT_ID(cmd[0], HID_POWER_SLEEP); + SET_CMD_OPCODE(cmd[1], HID_CMD_SET_POWER); + + rc = cyttsp5_write(ts, HID_COMMAND_REG, cmd, sizeof(cmd)); + if (rc) { + dev_err(ts->dev, "Failed to write power command %d", rc); + return rc; + } + + rc = wait_for_completion_interruptible_timeout(&ts->cmd_done, + msecs_to_jiffies(CY_HID_SET_POWER_TIMEOUT)); + if (rc <= 0) { + dev_err(ts->dev, "HID power cmd execution timed out\n"); + return -ETIMEDOUT; + } + + if (ts->response_buf[2] != HID_RESPONSE_REPORT_ID || + (ts->response_buf[3] & 0x03) != state || + (ts->response_buf[4] & 0x0f) != HID_CMD_SET_POWER) { + dev_err(ts->dev, "Validation of the %s response failed\n", + on ? "wakeup" : "sleep"); + return -EINVAL; + } + + return 0; +} + static int cyttsp5_hid_output_bl_launch_app(struct cyttsp5 *ts) { int rc; @@ -601,12 +651,7 @@ static int cyttsp5_get_hid_descriptor(struct cyttsp5 *ts, struct cyttsp5_hid_desc *desc) { struct device *dev = ts->dev; - __le16 hid_desc_register = cpu_to_le16(HID_DESC_REG); int rc; - u8 cmd[2]; - - /* Set HID descriptor register */ - memcpy(cmd, &hid_desc_register, sizeof(hid_desc_register)); rc = cyttsp5_write(ts, HID_DESC_REG, NULL, 0); if (rc) { @@ -675,6 +720,10 @@ static irqreturn_t cyttsp5_handle_irq(int irq, void *handle) case HID_BTN_REPORT_ID: cyttsp5_btn_attention(ts->dev); break; + case HID_RESPONSE_REPORT_ID: + memcpy(ts->response_buf, ts->input_buf, size); + complete(&ts->cmd_done); + break; default: /* It is not an input but a command response */ memcpy(ts->response_buf, ts->input_buf, size); @@ -886,12 +935,35 @@ static const struct i2c_device_id cyttsp5_i2c_id[] = { }; MODULE_DEVICE_TABLE(i2c, cyttsp5_i2c_id); +static int __maybe_unused cyttsp5_suspend(struct device *dev) +{ + struct cyttsp5 *ts = dev_get_drvdata(dev); + + if (!device_may_wakeup(dev)) + cyttsp5_power_control(ts, false); + + return 0; +} + +static int __maybe_unused cyttsp5_resume(struct device *dev) +{ + struct cyttsp5 *ts = dev_get_drvdata(dev); + + if (!device_may_wakeup(dev)) + cyttsp5_power_control(ts, true); + + return 0; +} + +static SIMPLE_DEV_PM_OPS(cyttsp5_pm, cyttsp5_suspend, cyttsp5_resume); + static struct i2c_driver cyttsp5_i2c_driver = { .driver = { .name = CYTTSP5_NAME, .of_match_table = cyttsp5_of_match, + .pm = &cyttsp5_pm, }, - .probe_new = cyttsp5_i2c_probe, + .probe = cyttsp5_i2c_probe, .id_table = cyttsp5_i2c_id, }; module_i2c_driver(cyttsp5_i2c_driver); diff --git a/drivers/input/touchscreen/cyttsp_i2c.c b/drivers/input/touchscreen/cyttsp_i2c.c index 3f91cb43ec820f0146cbe94ec2bb7c0333f34a3d..127a8fda1da4abcf0a29ee029270a41066002e59 100644 --- a/drivers/input/touchscreen/cyttsp_i2c.c +++ b/drivers/input/touchscreen/cyttsp_i2c.c @@ -66,7 +66,7 @@ static struct i2c_driver cyttsp_i2c_driver = { .pm = pm_sleep_ptr(&cyttsp_pm_ops), .of_match_table = cyttsp_of_i2c_match, }, - .probe_new = cyttsp_i2c_probe, + .probe = cyttsp_i2c_probe, .id_table = cyttsp_i2c_id, }; diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c index 24ab9e9f5b21e220fae6100aa226c55cf37f3549..795c7dad22bfb04f5fb58ff0c4cf33572ff1f4ad 100644 --- a/drivers/input/touchscreen/edt-ft5x06.c +++ b/drivers/input/touchscreen/edt-ft5x06.c @@ -1241,6 +1241,7 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client) if (tsdata->wake_gpio) { usleep_range(5000, 6000); gpiod_set_value_cansleep(tsdata->wake_gpio, 1); + usleep_range(5000, 6000); } if (tsdata->reset_gpio) { @@ -1510,7 +1511,7 @@ static struct i2c_driver edt_ft5x06_ts_driver = { .probe_type = PROBE_PREFER_ASYNCHRONOUS, }, .id_table = edt_ft5x06_ts_id, - .probe_new = edt_ft5x06_ts_probe, + .probe = edt_ft5x06_ts_probe, .remove = edt_ft5x06_ts_remove, }; diff --git a/drivers/input/touchscreen/eeti_ts.c b/drivers/input/touchscreen/eeti_ts.c index 56fa21688bdb26780ec6819c755d5310a0638f74..5e4167f6c63ef425ea4b4792565e2b96e9591de3 100644 --- a/drivers/input/touchscreen/eeti_ts.c +++ b/drivers/input/touchscreen/eeti_ts.c @@ -291,7 +291,7 @@ static struct i2c_driver eeti_ts_driver = { .pm = pm_sleep_ptr(&eeti_ts_pm), .of_match_table = of_match_ptr(of_eeti_ts_match), }, - .probe_new = eeti_ts_probe, + .probe = eeti_ts_probe, .id_table = eeti_ts_id, }; diff --git a/drivers/input/touchscreen/egalax_ts.c b/drivers/input/touchscreen/egalax_ts.c index 1a9805938e6df808d114fd41433e6e3c474532a7..a7f7e73082673dbb1b85ae6728d1b2e3cc67a922 100644 --- a/drivers/input/touchscreen/egalax_ts.c +++ b/drivers/input/touchscreen/egalax_ts.c @@ -264,7 +264,7 @@ static struct i2c_driver egalax_ts_driver = { .of_match_table = egalax_ts_dt_ids, }, .id_table = egalax_ts_id, - .probe_new = egalax_ts_probe, + .probe = egalax_ts_probe, }; module_i2c_driver(egalax_ts_driver); diff --git a/drivers/input/touchscreen/ektf2127.c b/drivers/input/touchscreen/ektf2127.c index e6f1e46d003df403df6c83240e56d52e84248e62..fd8724a3c19fd3e7eb751b122f0bee8b1643f8b2 100644 --- a/drivers/input/touchscreen/ektf2127.c +++ b/drivers/input/touchscreen/ektf2127.c @@ -351,7 +351,7 @@ static struct i2c_driver ektf2127_driver = { .pm = pm_sleep_ptr(&ektf2127_pm_ops), .of_match_table = of_match_ptr(ektf2127_of_match), }, - .probe_new = ektf2127_probe, + .probe = ektf2127_probe, .id_table = ektf2127_i2c_id, }; module_i2c_driver(ektf2127_driver); diff --git a/drivers/input/touchscreen/elants_i2c.c b/drivers/input/touchscreen/elants_i2c.c index 8a16eb51481f4f1db7e0b095961c9d44d6a1cf1e..2da1db64126d19fc49860598d410dd9af11c52f7 100644 --- a/drivers/input/touchscreen/elants_i2c.c +++ b/drivers/input/touchscreen/elants_i2c.c @@ -1673,7 +1673,7 @@ MODULE_DEVICE_TABLE(of, elants_of_match); #endif static struct i2c_driver elants_i2c_driver = { - .probe_new = elants_i2c_probe, + .probe = elants_i2c_probe, .id_table = elants_i2c_id, .driver = { .name = DEVICE_NAME, diff --git a/drivers/input/touchscreen/exc3000.c b/drivers/input/touchscreen/exc3000.c index 69eae79e2087c70d76cadbe2c053e9afe8cbe5a0..4af4c1e5d0da25458f98439d09306b32bf114abe 100644 --- a/drivers/input/touchscreen/exc3000.c +++ b/drivers/input/touchscreen/exc3000.c @@ -460,7 +460,7 @@ static struct i2c_driver exc3000_driver = { .of_match_table = of_match_ptr(exc3000_of_match), }, .id_table = exc3000_id, - .probe_new = exc3000_probe, + .probe = exc3000_probe, }; module_i2c_driver(exc3000_driver); diff --git a/drivers/input/touchscreen/goodix.c b/drivers/input/touchscreen/goodix.c index d77f116680a0a098ffaa06f8c33666dff092fd4a..f5aa240739f9709dab5640b87a6120d977f47c32 100644 --- a/drivers/input/touchscreen/goodix.c +++ b/drivers/input/touchscreen/goodix.c @@ -1544,7 +1544,7 @@ MODULE_DEVICE_TABLE(of, goodix_of_match); #endif static struct i2c_driver goodix_ts_driver = { - .probe_new = goodix_ts_probe, + .probe = goodix_ts_probe, .remove = goodix_ts_remove, .id_table = goodix_ts_id, .driver = { diff --git a/drivers/input/touchscreen/hideep.c b/drivers/input/touchscreen/hideep.c index 7c7020099b0ff128a6eeaba6a9fcbba9bc166558..404153338df718d2d62874bc02c9b8948396cd2a 100644 --- a/drivers/input/touchscreen/hideep.c +++ b/drivers/input/touchscreen/hideep.c @@ -1136,7 +1136,7 @@ static struct i2c_driver hideep_driver = { .pm = pm_sleep_ptr(&hideep_pm_ops), }, .id_table = hideep_i2c_id, - .probe_new = hideep_probe, + .probe = hideep_probe, }; module_i2c_driver(hideep_driver); diff --git a/drivers/input/touchscreen/himax_hx83112b.c b/drivers/input/touchscreen/himax_hx83112b.c index e96150d80a48f87197fa9f555a7a258d63cf3d11..4f6609dcdef3d443939621d8c7b07f3c72a23773 100644 --- a/drivers/input/touchscreen/himax_hx83112b.c +++ b/drivers/input/touchscreen/himax_hx83112b.c @@ -349,7 +349,7 @@ MODULE_DEVICE_TABLE(of, himax_of_match); #endif static struct i2c_driver himax_ts_driver = { - .probe_new = himax_probe, + .probe = himax_probe, .id_table = himax_ts_id, .driver = { .name = "Himax-hx83112b-TS", diff --git a/drivers/input/touchscreen/hycon-hy46xx.c b/drivers/input/touchscreen/hycon-hy46xx.c index 8f4989aba9a41a78051a0686954ab68551811fe5..2450cfa14de9dfe67657657399588241d4dfc636 100644 --- a/drivers/input/touchscreen/hycon-hy46xx.c +++ b/drivers/input/touchscreen/hycon-hy46xx.c @@ -580,7 +580,7 @@ static struct i2c_driver hycon_hy46xx_driver = { .probe_type = PROBE_PREFER_ASYNCHRONOUS, }, .id_table = hycon_hy46xx_id, - .probe_new = hycon_hy46xx_probe, + .probe = hycon_hy46xx_probe, }; module_i2c_driver(hycon_hy46xx_driver); diff --git a/drivers/input/touchscreen/hynitron_cstxxx.c b/drivers/input/touchscreen/hynitron_cstxxx.c index e86c85addb388ffbd5d6d3271747a6b64e94c7df..05946fee4fd440a6a284e53584cf0b16d8194ab3 100644 --- a/drivers/input/touchscreen/hynitron_cstxxx.c +++ b/drivers/input/touchscreen/hynitron_cstxxx.c @@ -488,7 +488,7 @@ static struct i2c_driver hynitron_i2c_driver = { .probe_type = PROBE_PREFER_ASYNCHRONOUS, }, .id_table = hyn_tpd_id, - .probe_new = hyn_probe, + .probe = hyn_probe, }; module_i2c_driver(hynitron_i2c_driver); diff --git a/drivers/input/touchscreen/ili210x.c b/drivers/input/touchscreen/ili210x.c index 4897fafa4204d04caba5ad307dc132f375e8af1f..f7cd773f7292a1a3d582391a83d0f6a843c63034 100644 --- a/drivers/input/touchscreen/ili210x.c +++ b/drivers/input/touchscreen/ili210x.c @@ -370,22 +370,33 @@ static int ili251x_firmware_update_resolution(struct device *dev) /* The firmware update blob might have changed the resolution. */ error = priv->chip->read_reg(client, REG_PANEL_INFO, &rs, sizeof(rs)); - if (error) - return error; + if (!error) { + resx = le16_to_cpup((__le16 *)rs); + resy = le16_to_cpup((__le16 *)(rs + 2)); - resx = le16_to_cpup((__le16 *)rs); - resy = le16_to_cpup((__le16 *)(rs + 2)); + /* The value reported by the firmware is invalid. */ + if (!resx || resx == 0xffff || !resy || resy == 0xffff) + error = -EINVAL; + } - /* The value reported by the firmware is invalid. */ - if (!resx || resx == 0xffff || !resy || resy == 0xffff) - return -EINVAL; + /* + * In case of error, the firmware might be stuck in bootloader mode, + * e.g. after a failed firmware update. Set maximum resolution, but + * do not fail to probe, so the user can re-trigger the firmware + * update and recover the touch controller. + */ + if (error) { + dev_warn(dev, "Invalid resolution reported by controller.\n"); + resx = 16384; + resy = 16384; + } input_abs_set_max(priv->input, ABS_X, resx - 1); input_abs_set_max(priv->input, ABS_Y, resy - 1); input_abs_set_max(priv->input, ABS_MT_POSITION_X, resx - 1); input_abs_set_max(priv->input, ABS_MT_POSITION_Y, resy - 1); - return 0; + return error; } static ssize_t ili251x_firmware_update_firmware_version(struct device *dev) @@ -977,11 +988,10 @@ static int ili210x_i2c_probe(struct i2c_client *client) if (priv->chip->has_pressure_reg) input_set_abs_params(input, ABS_MT_PRESSURE, 0, 0xa, 0, 0); error = ili251x_firmware_update_cached_state(dev); - if (error) { - dev_err(dev, "Unable to cache firmware information, err: %d\n", - error); - return error; - } + if (error) + dev_warn(dev, "Unable to cache firmware information, err: %d\n", + error); + touchscreen_parse_properties(input, true, &priv->prop); error = input_mt_init_slots(input, priv->chip->max_touches, @@ -1043,7 +1053,7 @@ static struct i2c_driver ili210x_ts_driver = { .of_match_table = ili210x_dt_ids, }, .id_table = ili210x_i2c_id, - .probe_new = ili210x_i2c_probe, + .probe = ili210x_i2c_probe, }; module_i2c_driver(ili210x_ts_driver); diff --git a/drivers/input/touchscreen/ilitek_ts_i2c.c b/drivers/input/touchscreen/ilitek_ts_i2c.c index d69809338498a560dd656316a8b1b237d7b575f8..2f872e95fbbadee2df4304c30120a04613bfada3 100644 --- a/drivers/input/touchscreen/ilitek_ts_i2c.c +++ b/drivers/input/touchscreen/ilitek_ts_i2c.c @@ -679,7 +679,7 @@ static struct i2c_driver ilitek_ts_i2c_driver = { .of_match_table = of_match_ptr(ilitek_ts_i2c_match), .acpi_match_table = ACPI_PTR(ilitekts_acpi_id), }, - .probe_new = ilitek_ts_i2c_probe, + .probe = ilitek_ts_i2c_probe, .id_table = ilitek_ts_i2c_id, }; module_i2c_driver(ilitek_ts_i2c_driver); diff --git a/drivers/input/touchscreen/imagis.c b/drivers/input/touchscreen/imagis.c index de1b16e94bb85affc233f49c5e68f5b1f90077d1..07111ca2445561702980070c2afe0655919bd808 100644 --- a/drivers/input/touchscreen/imagis.c +++ b/drivers/input/touchscreen/imagis.c @@ -357,7 +357,7 @@ static struct i2c_driver imagis_ts_driver = { .pm = pm_sleep_ptr(&imagis_pm_ops), .of_match_table = of_match_ptr(imagis_of_match), }, - .probe_new = imagis_probe, + .probe = imagis_probe, }; module_i2c_driver(imagis_ts_driver); diff --git a/drivers/input/touchscreen/iqs5xx.c b/drivers/input/touchscreen/iqs5xx.c index c73e9c5c0077e78ad518f8bb19488b6a26fb926c..0aa9d6492df8f8584f93a4cf743ee79253aeab17 100644 --- a/drivers/input/touchscreen/iqs5xx.c +++ b/drivers/input/touchscreen/iqs5xx.c @@ -1093,7 +1093,7 @@ static struct i2c_driver iqs5xx_i2c_driver = { .pm = pm_sleep_ptr(&iqs5xx_pm), }, .id_table = iqs5xx_id, - .probe_new = iqs5xx_probe, + .probe = iqs5xx_probe, }; module_i2c_driver(iqs5xx_i2c_driver); diff --git a/drivers/input/touchscreen/max11801_ts.c b/drivers/input/touchscreen/max11801_ts.c index 461023fd6a09adbf300c1779efc3ee241ac3fce6..8be6dade118cb97056a76cbcc5aef5dcd82f1b9c 100644 --- a/drivers/input/touchscreen/max11801_ts.c +++ b/drivers/input/touchscreen/max11801_ts.c @@ -230,7 +230,7 @@ static struct i2c_driver max11801_ts_driver = { .of_match_table = max11801_ts_dt_ids, }, .id_table = max11801_ts_id, - .probe_new = max11801_ts_probe, + .probe = max11801_ts_probe, }; module_i2c_driver(max11801_ts_driver); diff --git a/drivers/input/touchscreen/mcs5000_ts.c b/drivers/input/touchscreen/mcs5000_ts.c index 704e36087ca26f02423e5b0d3e7de2c90930ade5..ac28019ba4c33cf4361b395164ce6b0ed4391d3f 100644 --- a/drivers/input/touchscreen/mcs5000_ts.c +++ b/drivers/input/touchscreen/mcs5000_ts.c @@ -272,7 +272,7 @@ static const struct i2c_device_id mcs5000_ts_id[] = { MODULE_DEVICE_TABLE(i2c, mcs5000_ts_id); static struct i2c_driver mcs5000_ts_driver = { - .probe_new = mcs5000_ts_probe, + .probe = mcs5000_ts_probe, .driver = { .name = "mcs5000_ts", .pm = pm_sleep_ptr(&mcs5000_ts_pm), diff --git a/drivers/input/touchscreen/melfas_mip4.c b/drivers/input/touchscreen/melfas_mip4.c index 89b6020a9a61563f19331ae528a25596dcffaf57..32896e5085bdcfb7090856e1d78f7523b40704d8 100644 --- a/drivers/input/touchscreen/melfas_mip4.c +++ b/drivers/input/touchscreen/melfas_mip4.c @@ -1591,7 +1591,7 @@ MODULE_DEVICE_TABLE(i2c, mip4_i2c_ids); static struct i2c_driver mip4_driver = { .id_table = mip4_i2c_ids, - .probe_new = mip4_probe, + .probe = mip4_probe, .driver = { .name = MIP4_DEVICE_NAME, .of_match_table = of_match_ptr(mip4_of_match), diff --git a/drivers/input/touchscreen/migor_ts.c b/drivers/input/touchscreen/migor_ts.c index 69fcc88d4f805bfdabb2ecd7d555f70f9c199b64..2384ea69a3f8d02af2626f5f3c97f7737cdde07d 100644 --- a/drivers/input/touchscreen/migor_ts.c +++ b/drivers/input/touchscreen/migor_ts.c @@ -221,7 +221,7 @@ static struct i2c_driver migor_ts_driver = { .name = "migor_ts", .pm = pm_sleep_ptr(&migor_ts_pm), }, - .probe_new = migor_ts_probe, + .probe = migor_ts_probe, .remove = migor_ts_remove, .id_table = migor_ts_id, }; diff --git a/drivers/input/touchscreen/mms114.c b/drivers/input/touchscreen/mms114.c index 4dbca1aad89d087db3a3714b65f549c9d5c951ac..ac12494c7930d679af17e3a0c77df03fe107c50e 100644 --- a/drivers/input/touchscreen/mms114.c +++ b/drivers/input/touchscreen/mms114.c @@ -638,7 +638,7 @@ static struct i2c_driver mms114_driver = { .pm = pm_sleep_ptr(&mms114_pm_ops), .of_match_table = of_match_ptr(mms114_dt_match), }, - .probe_new = mms114_probe, + .probe = mms114_probe, .id_table = mms114_id, }; diff --git a/drivers/input/touchscreen/msg2638.c b/drivers/input/touchscreen/msg2638.c index b23db689d9951b0b3a2e4d8c8a0737d020941aa7..a38af3fee34a82913f88a2a1629a08d9006de09a 100644 --- a/drivers/input/touchscreen/msg2638.c +++ b/drivers/input/touchscreen/msg2638.c @@ -492,7 +492,7 @@ static const struct of_device_id msg2638_of_match[] = { MODULE_DEVICE_TABLE(of, msg2638_of_match); static struct i2c_driver msg2638_ts_driver = { - .probe_new = msg2638_ts_probe, + .probe = msg2638_ts_probe, .driver = { .name = "MStar-TS", .pm = pm_sleep_ptr(&msg2638_pm_ops), diff --git a/drivers/input/touchscreen/novatek-nvt-ts.c b/drivers/input/touchscreen/novatek-nvt-ts.c index 3e551f9d31d7d0afdf46b645a3338013a40ff44a..7f7d879aac6d55b6a265bce39faee4b8228c8398 100644 --- a/drivers/input/touchscreen/novatek-nvt-ts.c +++ b/drivers/input/touchscreen/novatek-nvt-ts.c @@ -290,7 +290,7 @@ static struct i2c_driver nvt_ts_driver = { .name = "novatek-nvt-ts", .pm = pm_sleep_ptr(&nvt_ts_pm_ops), }, - .probe_new = nvt_ts_probe, + .probe = nvt_ts_probe, .id_table = nvt_ts_i2c_id, }; diff --git a/drivers/input/touchscreen/pixcir_i2c_ts.c b/drivers/input/touchscreen/pixcir_i2c_ts.c index f09f4831bad41fe1e4590d1fc6274dccb0d095ba..554e179c2e487dbd0709b051e73cea7e32837868 100644 --- a/drivers/input/touchscreen/pixcir_i2c_ts.c +++ b/drivers/input/touchscreen/pixcir_i2c_ts.c @@ -617,7 +617,7 @@ static struct i2c_driver pixcir_i2c_ts_driver = { .pm = pm_sleep_ptr(&pixcir_dev_pm_ops), .of_match_table = of_match_ptr(pixcir_of_match), }, - .probe_new = pixcir_i2c_ts_probe, + .probe = pixcir_i2c_ts_probe, .id_table = pixcir_i2c_ts_id, }; diff --git a/drivers/input/touchscreen/raydium_i2c_ts.c b/drivers/input/touchscreen/raydium_i2c_ts.c index 49a06d3876cf9dd7020a8b561ec214df05abc1f9..76e7d62d587023c682edca7b73225f93de4e8b12 100644 --- a/drivers/input/touchscreen/raydium_i2c_ts.c +++ b/drivers/input/touchscreen/raydium_i2c_ts.c @@ -1273,7 +1273,7 @@ MODULE_DEVICE_TABLE(of, raydium_of_match); #endif static struct i2c_driver raydium_i2c_driver = { - .probe_new = raydium_i2c_probe, + .probe = raydium_i2c_probe, .id_table = raydium_i2c_id, .driver = { .name = "raydium_ts", diff --git a/drivers/input/touchscreen/rohm_bu21023.c b/drivers/input/touchscreen/rohm_bu21023.c index 833422e5fd6d0377ef5b9fdca75bd6148cfb7913..240424f06b98fccea7fa18161d9524d644e042c5 100644 --- a/drivers/input/touchscreen/rohm_bu21023.c +++ b/drivers/input/touchscreen/rohm_bu21023.c @@ -1183,7 +1183,7 @@ static struct i2c_driver rohm_bu21023_i2c_driver = { .driver = { .name = BU21023_NAME, }, - .probe_new = rohm_bu21023_i2c_probe, + .probe = rohm_bu21023_i2c_probe, .id_table = rohm_bu21023_i2c_id, }; module_i2c_driver(rohm_bu21023_i2c_driver); diff --git a/drivers/input/touchscreen/s6sy761.c b/drivers/input/touchscreen/s6sy761.c index 371cf4848ad561931231cc47e9dee0c4387ffaa2..998d99d189111f8e1671a28167b517e8b5157575 100644 --- a/drivers/input/touchscreen/s6sy761.c +++ b/drivers/input/touchscreen/s6sy761.c @@ -538,7 +538,7 @@ static struct i2c_driver s6sy761_driver = { .of_match_table = of_match_ptr(s6sy761_of_match), .pm = pm_ptr(&s6sy761_pm_ops), }, - .probe_new = s6sy761_probe, + .probe = s6sy761_probe, .remove = s6sy761_remove, .id_table = s6sy761_id, }; diff --git a/drivers/input/touchscreen/silead.c b/drivers/input/touchscreen/silead.c index a37fac089010035374eacd6efacda341f9469abc..9e28f962e059d43231a47e7c505a116d0f584e53 100644 --- a/drivers/input/touchscreen/silead.c +++ b/drivers/input/touchscreen/silead.c @@ -826,7 +826,7 @@ MODULE_DEVICE_TABLE(of, silead_ts_of_match); #endif static struct i2c_driver silead_ts_driver = { - .probe_new = silead_ts_probe, + .probe = silead_ts_probe, .id_table = silead_ts_id, .driver = { .name = SILEAD_TS_NAME, diff --git a/drivers/input/touchscreen/sis_i2c.c b/drivers/input/touchscreen/sis_i2c.c index 5a493b15b25d26ec78cc612e9c0a028d0cd74c2b..426564d0fc39aed0b4cc10e5d6649cbc942fa24b 100644 --- a/drivers/input/touchscreen/sis_i2c.c +++ b/drivers/input/touchscreen/sis_i2c.c @@ -393,7 +393,7 @@ static struct i2c_driver sis_ts_driver = { .name = SIS_I2C_NAME, .of_match_table = of_match_ptr(sis_ts_dt_ids), }, - .probe_new = sis_ts_probe, + .probe = sis_ts_probe, .id_table = sis_ts_id, }; module_i2c_driver(sis_ts_driver); diff --git a/drivers/input/touchscreen/st1232.c b/drivers/input/touchscreen/st1232.c index f49566dc96f80ed699e5e20d85b367955abf68f7..6475084aee1bb7d1f9f7901d94bd48b53f5ddfc8 100644 --- a/drivers/input/touchscreen/st1232.c +++ b/drivers/input/touchscreen/st1232.c @@ -384,7 +384,7 @@ static const struct of_device_id st1232_ts_dt_ids[] = { MODULE_DEVICE_TABLE(of, st1232_ts_dt_ids); static struct i2c_driver st1232_ts_driver = { - .probe_new = st1232_ts_probe, + .probe = st1232_ts_probe, .id_table = st1232_ts_id, .driver = { .name = ST1232_TS_NAME, diff --git a/drivers/input/touchscreen/stmfts.c b/drivers/input/touchscreen/stmfts.c index fdbf5e68943c4764dc89b9a5c9811bde2c1951c6..56e371fd88fa1082029cb7432def580dd6a3379b 100644 --- a/drivers/input/touchscreen/stmfts.c +++ b/drivers/input/touchscreen/stmfts.c @@ -808,7 +808,7 @@ static struct i2c_driver stmfts_driver = { .pm = pm_ptr(&stmfts_pm_ops), .probe_type = PROBE_PREFER_ASYNCHRONOUS, }, - .probe_new = stmfts_probe, + .probe = stmfts_probe, .remove = stmfts_remove, .id_table = stmfts_id, }; diff --git a/drivers/input/touchscreen/sun4i-ts.c b/drivers/input/touchscreen/sun4i-ts.c index 577c75c83e25db2e99df88765219e0a230de3b6a..bb3c6072fc82797536da2f5e346f88aed525228b 100644 --- a/drivers/input/touchscreen/sun4i-ts.c +++ b/drivers/input/touchscreen/sun4i-ts.c @@ -22,7 +22,7 @@ * in the kernel). So this driver offers straight forward, reliable single * touch functionality only. * - * s.a. A20 User Manual "1.15 TP" (Documentation/arm/sunxi.rst) + * s.a. A20 User Manual "1.15 TP" (Documentation/arch/arm/sunxi.rst) * (looks like the description in the A20 User Manual v1.3 is better * than the one in the A10 User Manual v.1.5) */ diff --git a/drivers/input/touchscreen/sx8654.c b/drivers/input/touchscreen/sx8654.c index 52ae730358303a60e323f9d01db7f878259d07f9..0293c493bc79f0184111307aa4b8fd44fdc750a4 100644 --- a/drivers/input/touchscreen/sx8654.c +++ b/drivers/input/touchscreen/sx8654.c @@ -470,7 +470,7 @@ static struct i2c_driver sx8654_driver = { .of_match_table = of_match_ptr(sx8654_of_match), }, .id_table = sx8654_id_table, - .probe_new = sx8654_probe, + .probe = sx8654_probe, }; module_i2c_driver(sx8654_driver); diff --git a/drivers/input/touchscreen/tsc2004.c b/drivers/input/touchscreen/tsc2004.c index 45f39eb20638b433aa900bf2981b1e7fc1f38e98..b5e904c5b7c49e8d7e8d2a8ada90950aae58ef39 100644 --- a/drivers/input/touchscreen/tsc2004.c +++ b/drivers/input/touchscreen/tsc2004.c @@ -68,7 +68,7 @@ static struct i2c_driver tsc2004_driver = { .pm = pm_sleep_ptr(&tsc200x_pm_ops), }, .id_table = tsc2004_idtable, - .probe_new = tsc2004_probe, + .probe = tsc2004_probe, .remove = tsc2004_remove, }; module_i2c_driver(tsc2004_driver); diff --git a/drivers/input/touchscreen/tsc2007_core.c b/drivers/input/touchscreen/tsc2007_core.c index 21916a30fb76cd7b69a057969f4adcdfbd25464f..b3655250d4a7b3b4865d2ebc02831918968e5ddf 100644 --- a/drivers/input/touchscreen/tsc2007_core.c +++ b/drivers/input/touchscreen/tsc2007_core.c @@ -418,7 +418,7 @@ static struct i2c_driver tsc2007_driver = { .of_match_table = tsc2007_of_match, }, .id_table = tsc2007_idtable, - .probe_new = tsc2007_probe, + .probe = tsc2007_probe, }; module_i2c_driver(tsc2007_driver); diff --git a/drivers/input/touchscreen/wacom_i2c.c b/drivers/input/touchscreen/wacom_i2c.c index a145b910525534dedd481b4affa998204eaab057..f389f9c004a9d3c2c487d65d07a0afbc66d35c0d 100644 --- a/drivers/input/touchscreen/wacom_i2c.c +++ b/drivers/input/touchscreen/wacom_i2c.c @@ -264,7 +264,7 @@ static struct i2c_driver wacom_i2c_driver = { .pm = pm_sleep_ptr(&wacom_i2c_pm), }, - .probe_new = wacom_i2c_probe, + .probe = wacom_i2c_probe, .id_table = wacom_i2c_id, }; module_i2c_driver(wacom_i2c_driver); diff --git a/drivers/input/touchscreen/wdt87xx_i2c.c b/drivers/input/touchscreen/wdt87xx_i2c.c index 771962af3d0ac218792ccd9a1e7eb7f6b2076d9e..cbc4750c53f9a9bdab1a3abd4b6f706d2de94eb2 100644 --- a/drivers/input/touchscreen/wdt87xx_i2c.c +++ b/drivers/input/touchscreen/wdt87xx_i2c.c @@ -1169,7 +1169,7 @@ static const struct acpi_device_id wdt87xx_acpi_id[] = { MODULE_DEVICE_TABLE(acpi, wdt87xx_acpi_id); static struct i2c_driver wdt87xx_driver = { - .probe_new = wdt87xx_ts_probe, + .probe = wdt87xx_ts_probe, .id_table = wdt87xx_dev_id, .driver = { .name = WDT87XX_NAME, diff --git a/drivers/input/touchscreen/zet6223.c b/drivers/input/touchscreen/zet6223.c index bfa0c637d56938a80647d05bbeaa0b07cf86b9f0..1a034471f10356a237b2442a38077cabde3a7077 100644 --- a/drivers/input/touchscreen/zet6223.c +++ b/drivers/input/touchscreen/zet6223.c @@ -248,7 +248,7 @@ static struct i2c_driver zet6223_driver = { .name = "zet6223", .of_match_table = zet6223_of_match, }, - .probe_new = zet6223_probe, + .probe = zet6223_probe, .id_table = zet6223_id }; module_i2c_driver(zet6223_driver); diff --git a/drivers/input/touchscreen/zforce_ts.c b/drivers/input/touchscreen/zforce_ts.c index 76b194285e1c5b9ea4400d8cf242cb32271f8865..5be5112845e1edf93808bddd3a65fa93347f4997 100644 --- a/drivers/input/touchscreen/zforce_ts.c +++ b/drivers/input/touchscreen/zforce_ts.c @@ -944,7 +944,7 @@ static struct i2c_driver zforce_driver = { .pm = pm_sleep_ptr(&zforce_pm_ops), .of_match_table = of_match_ptr(zforce_dt_idtable), }, - .probe_new = zforce_probe, + .probe = zforce_probe, .id_table = zforce_idtable, }; diff --git a/drivers/input/touchscreen/zinitix.c b/drivers/input/touchscreen/zinitix.c index b6ece47151b8f6c400045d91ef233310c9491134..1b4807ba46242bccc6dd3962bbf4a8fed5f58c4e 100644 --- a/drivers/input/touchscreen/zinitix.c +++ b/drivers/input/touchscreen/zinitix.c @@ -617,7 +617,7 @@ MODULE_DEVICE_TABLE(of, zinitix_of_match); #endif static struct i2c_driver zinitix_ts_driver = { - .probe_new = zinitix_ts_probe, + .probe = zinitix_ts_probe, .driver = { .name = "Zinitix-TS", .pm = pm_sleep_ptr(&zinitix_pm_ops), diff --git a/drivers/interconnect/Kconfig b/drivers/interconnect/Kconfig index d637a89d4695c527ef225c2036a46b045b596e2b..5faa8d2aecff42031c300c62945debbafb7e17e5 100644 --- a/drivers/interconnect/Kconfig +++ b/drivers/interconnect/Kconfig @@ -15,4 +15,10 @@ source "drivers/interconnect/imx/Kconfig" source "drivers/interconnect/qcom/Kconfig" source "drivers/interconnect/samsung/Kconfig" +config INTERCONNECT_CLK + tristate + depends on COMMON_CLK + help + Support for wrapping clocks into the interconnect nodes. + endif diff --git a/drivers/interconnect/Makefile b/drivers/interconnect/Makefile index 97d393fd638d7939e3321ed4984cd325b29e1180..5604ce351a9f3b2376bf7420dfb37b1a493dc0bb 100644 --- a/drivers/interconnect/Makefile +++ b/drivers/interconnect/Makefile @@ -7,3 +7,5 @@ obj-$(CONFIG_INTERCONNECT) += icc-core.o obj-$(CONFIG_INTERCONNECT_IMX) += imx/ obj-$(CONFIG_INTERCONNECT_QCOM) += qcom/ obj-$(CONFIG_INTERCONNECT_SAMSUNG) += samsung/ + +obj-$(CONFIG_INTERCONNECT_CLK) += icc-clk.o diff --git a/drivers/interconnect/core.c b/drivers/interconnect/core.c index ec46bcb16d5efccfe49ca5a465bb3b1ff4407d40..5fac448c28fdadfeed59ca643535431258b1e7c4 100644 --- a/drivers/interconnect/core.c +++ b/drivers/interconnect/core.c @@ -587,7 +587,7 @@ EXPORT_SYMBOL_GPL(icc_set_tag); /** * icc_get_name() - Get name of the icc path - * @path: reference to the path returned by icc_get() + * @path: interconnect path * * This function is used by an interconnect consumer to get the name of the icc * path. @@ -605,7 +605,7 @@ EXPORT_SYMBOL_GPL(icc_get_name); /** * icc_set_bw() - set bandwidth constraints on an interconnect path - * @path: reference to the path returned by icc_get() + * @path: interconnect path * @avg_bw: average bandwidth in kilobytes per second * @peak_bw: peak bandwidth in kilobytes per second * @@ -704,54 +704,6 @@ int icc_disable(struct icc_path *path) } EXPORT_SYMBOL_GPL(icc_disable); -/** - * icc_get() - return a handle for path between two endpoints - * @dev: the device requesting the path - * @src_id: source device port id - * @dst_id: destination device port id - * - * This function will search for a path between two endpoints and return an - * icc_path handle on success. Use icc_put() to release - * constraints when they are not needed anymore. - * If the interconnect API is disabled, NULL is returned and the consumer - * drivers will still build. Drivers are free to handle this specifically, - * but they don't have to. - * - * Return: icc_path pointer on success, ERR_PTR() on error or NULL if the - * interconnect API is disabled. - */ -struct icc_path *icc_get(struct device *dev, const int src_id, const int dst_id) -{ - struct icc_node *src, *dst; - struct icc_path *path = ERR_PTR(-EPROBE_DEFER); - - mutex_lock(&icc_lock); - - src = node_find(src_id); - if (!src) - goto out; - - dst = node_find(dst_id); - if (!dst) - goto out; - - path = path_find(dev, src, dst); - if (IS_ERR(path)) { - dev_err(dev, "%s: invalid path=%ld\n", __func__, PTR_ERR(path)); - goto out; - } - - path->name = kasprintf(GFP_KERNEL, "%s-%s", src->name, dst->name); - if (!path->name) { - kfree(path); - path = ERR_PTR(-ENOMEM); - } -out: - mutex_unlock(&icc_lock); - return path; -} -EXPORT_SYMBOL_GPL(icc_get); - /** * icc_put() - release the reference to the icc_path * @path: interconnect path diff --git a/drivers/interconnect/icc-clk.c b/drivers/interconnect/icc-clk.c new file mode 100644 index 0000000000000000000000000000000000000000..4d43ebff425772e0ad3eeb2e8d25b4dcd5613de7 --- /dev/null +++ b/drivers/interconnect/icc-clk.c @@ -0,0 +1,174 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2023, Linaro Ltd. + */ + +#include +#include +#include +#include + +struct icc_clk_node { + struct clk *clk; + bool enabled; +}; + +struct icc_clk_provider { + struct icc_provider provider; + int num_clocks; + struct icc_clk_node clocks[]; +}; + +#define to_icc_clk_provider(_provider) \ + container_of(_provider, struct icc_clk_provider, provider) + +static int icc_clk_set(struct icc_node *src, struct icc_node *dst) +{ + struct icc_clk_node *qn = src->data; + int ret; + + if (!qn || !qn->clk) + return 0; + + if (!src->peak_bw) { + if (qn->enabled) + clk_disable_unprepare(qn->clk); + qn->enabled = false; + + return 0; + } + + if (!qn->enabled) { + ret = clk_prepare_enable(qn->clk); + if (ret) + return ret; + qn->enabled = true; + } + + return clk_set_rate(qn->clk, icc_units_to_bps(src->peak_bw)); +} + +static int icc_clk_get_bw(struct icc_node *node, u32 *avg, u32 *peak) +{ + struct icc_clk_node *qn = node->data; + + if (!qn || !qn->clk) + *peak = INT_MAX; + else + *peak = Bps_to_icc(clk_get_rate(qn->clk)); + + return 0; +} + +/** + * icc_clk_register() - register a new clk-based interconnect provider + * @dev: device supporting this provider + * @first_id: an ID of the first provider's node + * @num_clocks: number of instances of struct icc_clk_data + * @data: data for the provider + * + * Registers and returns a clk-based interconnect provider. It is a simple + * wrapper around COMMON_CLK framework, allowing other devices to vote on the + * clock rate. + * + * Return: 0 on success, or an error code otherwise + */ +struct icc_provider *icc_clk_register(struct device *dev, + unsigned int first_id, + unsigned int num_clocks, + const struct icc_clk_data *data) +{ + struct icc_clk_provider *qp; + struct icc_provider *provider; + struct icc_onecell_data *onecell; + struct icc_node *node; + int ret, i, j; + + onecell = devm_kzalloc(dev, struct_size(onecell, nodes, 2 * num_clocks), GFP_KERNEL); + if (!onecell) + return ERR_PTR(-ENOMEM); + + qp = devm_kzalloc(dev, struct_size(qp, clocks, num_clocks), GFP_KERNEL); + if (!qp) + return ERR_PTR(-ENOMEM); + + qp->num_clocks = num_clocks; + + provider = &qp->provider; + provider->dev = dev; + provider->get_bw = icc_clk_get_bw; + provider->set = icc_clk_set; + provider->aggregate = icc_std_aggregate; + provider->xlate = of_icc_xlate_onecell; + INIT_LIST_HEAD(&provider->nodes); + provider->data = onecell; + + icc_provider_init(provider); + + for (i = 0, j = 0; i < num_clocks; i++) { + qp->clocks[i].clk = data[i].clk; + + node = icc_node_create(first_id + j); + if (IS_ERR(node)) { + ret = PTR_ERR(node); + goto err; + } + + node->name = devm_kasprintf(dev, GFP_KERNEL, "%s_master", data[i].name); + node->data = &qp->clocks[i]; + icc_node_add(node, provider); + /* link to the next node, slave */ + icc_link_create(node, first_id + j + 1); + onecell->nodes[j++] = node; + + node = icc_node_create(first_id + j); + if (IS_ERR(node)) { + ret = PTR_ERR(node); + goto err; + } + + node->name = devm_kasprintf(dev, GFP_KERNEL, "%s_slave", data[i].name); + /* no data for slave node */ + icc_node_add(node, provider); + onecell->nodes[j++] = node; + } + + onecell->num_nodes = j; + + ret = icc_provider_register(provider); + if (ret) + goto err; + + return provider; + +err: + icc_nodes_remove(provider); + + return ERR_PTR(ret); +} +EXPORT_SYMBOL_GPL(icc_clk_register); + +/** + * icc_clk_unregister() - unregister a previously registered clk interconnect provider + * @provider: provider returned by icc_clk_register() + */ +void icc_clk_unregister(struct icc_provider *provider) +{ + struct icc_clk_provider *qp = container_of(provider, struct icc_clk_provider, provider); + int i; + + icc_provider_deregister(&qp->provider); + icc_nodes_remove(&qp->provider); + + for (i = 0; i < qp->num_clocks; i++) { + struct icc_clk_node *qn = &qp->clocks[i]; + + if (qn->enabled) + clk_disable_unprepare(qn->clk); + } +} +EXPORT_SYMBOL_GPL(icc_clk_unregister); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Interconnect wrapper for clocks"); +MODULE_AUTHOR("Dmitry Baryshkov "); diff --git a/drivers/interconnect/qcom/icc-rpm.c b/drivers/interconnect/qcom/icc-rpm.c index 5341fa169dbf131ba99f7ed95d43e46071a3d2f7..6acc7686ed386d261b3a0c7e554e3646382f1393 100644 --- a/drivers/interconnect/qcom/icc-rpm.c +++ b/drivers/interconnect/qcom/icc-rpm.c @@ -50,7 +50,7 @@ #define NOC_QOS_MODE_FIXED_VAL 0x0 #define NOC_QOS_MODE_BYPASS_VAL 0x2 -static int qcom_icc_set_qnoc_qos(struct icc_node *src, u64 max_bw) +static int qcom_icc_set_qnoc_qos(struct icc_node *src) { struct icc_provider *provider = src->provider; struct qcom_icc_provider *qp = to_qcom_provider(provider); @@ -95,7 +95,7 @@ static int qcom_icc_bimc_set_qos_health(struct qcom_icc_provider *qp, mask, val); } -static int qcom_icc_set_bimc_qos(struct icc_node *src, u64 max_bw) +static int qcom_icc_set_bimc_qos(struct icc_node *src) { struct qcom_icc_provider *qp; struct qcom_icc_node *qn; @@ -150,7 +150,7 @@ static int qcom_icc_noc_set_qos_priority(struct qcom_icc_provider *qp, NOC_QOS_PRIORITY_P0_MASK, qos->prio_level); } -static int qcom_icc_set_noc_qos(struct icc_node *src, u64 max_bw) +static int qcom_icc_set_noc_qos(struct icc_node *src) { struct qcom_icc_provider *qp; struct qcom_icc_node *qn; @@ -187,7 +187,7 @@ static int qcom_icc_set_noc_qos(struct icc_node *src, u64 max_bw) NOC_QOS_MODEn_MASK, mode); } -static int qcom_icc_qos_set(struct icc_node *node, u64 sum_bw) +static int qcom_icc_qos_set(struct icc_node *node) { struct qcom_icc_provider *qp = to_qcom_provider(node->provider); struct qcom_icc_node *qn = node->data; @@ -196,38 +196,41 @@ static int qcom_icc_qos_set(struct icc_node *node, u64 sum_bw) switch (qp->type) { case QCOM_ICC_BIMC: - return qcom_icc_set_bimc_qos(node, sum_bw); + return qcom_icc_set_bimc_qos(node); case QCOM_ICC_QNOC: - return qcom_icc_set_qnoc_qos(node, sum_bw); + return qcom_icc_set_qnoc_qos(node); default: - return qcom_icc_set_noc_qos(node, sum_bw); + return qcom_icc_set_noc_qos(node); } } -static int qcom_icc_rpm_set(int mas_rpm_id, int slv_rpm_id, u64 sum_bw) +static int qcom_icc_rpm_set(struct qcom_icc_node *qn, u64 sum_bw) { int ret = 0; - if (mas_rpm_id != -1) { + if (qn->qos.ap_owned) + return 0; + + if (qn->mas_rpm_id != -1) { ret = qcom_icc_rpm_smd_send(QCOM_SMD_RPM_ACTIVE_STATE, RPM_BUS_MASTER_REQ, - mas_rpm_id, + qn->mas_rpm_id, sum_bw); if (ret) { pr_err("qcom_icc_rpm_smd_send mas %d error %d\n", - mas_rpm_id, ret); + qn->mas_rpm_id, ret); return ret; } } - if (slv_rpm_id != -1) { + if (qn->slv_rpm_id != -1) { ret = qcom_icc_rpm_smd_send(QCOM_SMD_RPM_ACTIVE_STATE, RPM_BUS_SLAVE_REQ, - slv_rpm_id, + qn->slv_rpm_id, sum_bw); if (ret) { pr_err("qcom_icc_rpm_smd_send slv %d error %d\n", - slv_rpm_id, ret); + qn->slv_rpm_id, ret); return ret; } } @@ -235,26 +238,6 @@ static int qcom_icc_rpm_set(int mas_rpm_id, int slv_rpm_id, u64 sum_bw) return ret; } -static int __qcom_icc_set(struct icc_node *n, struct qcom_icc_node *qn, - u64 sum_bw) -{ - int ret; - - if (!qn->qos.ap_owned) { - /* send bandwidth request message to the RPM processor */ - ret = qcom_icc_rpm_set(qn->mas_rpm_id, qn->slv_rpm_id, sum_bw); - if (ret) - return ret; - } else if (qn->qos.qos_mode != NOC_QOS_MODE_INVALID) { - /* set bandwidth directly from the AP */ - ret = qcom_icc_qos_set(n, sum_bw); - if (ret) - return ret; - } - - return 0; -} - /** * qcom_icc_pre_bw_aggregate - cleans up values before re-aggregate requests * @node: icc node to operate on @@ -370,16 +353,17 @@ static int qcom_icc_set(struct icc_node *src, struct icc_node *dst) sum_bw = icc_units_to_bps(max_agg_avg); - ret = __qcom_icc_set(src, src_qn, sum_bw); + ret = qcom_icc_rpm_set(src_qn, sum_bw); if (ret) return ret; + if (dst_qn) { - ret = __qcom_icc_set(dst, dst_qn, sum_bw); + ret = qcom_icc_rpm_set(dst_qn, sum_bw); if (ret) return ret; } - for (i = 0; i < qp->num_clks; i++) { + for (i = 0; i < qp->num_bus_clks; i++) { /* * Use WAKE bucket for active clock, otherwise, use SLEEP bucket * for other clocks. If a platform doesn't set interconnect @@ -425,7 +409,7 @@ int qnoc_probe(struct platform_device *pdev) struct qcom_icc_provider *qp; struct icc_node *node; size_t num_nodes, i; - const char * const *cds; + const char * const *cds = NULL; int cd_num; int ret; @@ -440,21 +424,20 @@ int qnoc_probe(struct platform_device *pdev) qnodes = desc->nodes; num_nodes = desc->num_nodes; - if (desc->num_clocks) { - cds = desc->clocks; - cd_num = desc->num_clocks; + if (desc->num_intf_clocks) { + cds = desc->intf_clocks; + cd_num = desc->num_intf_clocks; } else { - cds = bus_clocks; - cd_num = ARRAY_SIZE(bus_clocks); + /* 0 intf clocks is perfectly fine */ + cd_num = 0; } - qp = devm_kzalloc(dev, struct_size(qp, bus_clks, cd_num), GFP_KERNEL); + qp = devm_kzalloc(dev, sizeof(*qp), GFP_KERNEL); if (!qp) return -ENOMEM; - qp->bus_clk_rate = devm_kcalloc(dev, cd_num, sizeof(*qp->bus_clk_rate), - GFP_KERNEL); - if (!qp->bus_clk_rate) + qp->intf_clks = devm_kcalloc(dev, cd_num, sizeof(*qp->intf_clks), GFP_KERNEL); + if (!qp->intf_clks) return -ENOMEM; data = devm_kzalloc(dev, struct_size(data, nodes, num_nodes), @@ -462,9 +445,13 @@ int qnoc_probe(struct platform_device *pdev) if (!data) return -ENOMEM; + qp->num_intf_clks = cd_num; for (i = 0; i < cd_num; i++) - qp->bus_clks[i].id = cds[i]; - qp->num_clks = cd_num; + qp->intf_clks[i].id = cds[i]; + + qp->num_bus_clks = desc->no_clk_scaling ? 0 : NUM_BUS_CLKS; + for (i = 0; i < qp->num_bus_clks; i++) + qp->bus_clks[i].id = bus_clocks[i]; qp->type = desc->type; qp->qos_offset = desc->qos_offset; @@ -494,11 +481,15 @@ int qnoc_probe(struct platform_device *pdev) } regmap_done: - ret = devm_clk_bulk_get_optional(dev, qp->num_clks, qp->bus_clks); + ret = devm_clk_bulk_get(dev, qp->num_bus_clks, qp->bus_clks); + if (ret) + return ret; + + ret = clk_bulk_prepare_enable(qp->num_bus_clks, qp->bus_clks); if (ret) return ret; - ret = clk_bulk_prepare_enable(qp->num_clks, qp->bus_clks); + ret = devm_clk_bulk_get(dev, qp->num_intf_clks, qp->intf_clks); if (ret) return ret; @@ -512,6 +503,11 @@ int qnoc_probe(struct platform_device *pdev) icc_provider_init(provider); + /* If this fails, bus accesses will crash the platform! */ + ret = clk_bulk_prepare_enable(qp->num_intf_clks, qp->intf_clks); + if (ret) + return ret; + for (i = 0; i < num_nodes; i++) { size_t j; @@ -528,10 +524,20 @@ int qnoc_probe(struct platform_device *pdev) for (j = 0; j < qnodes[i]->num_links; j++) icc_link_create(node, qnodes[i]->links[j]); + /* Set QoS registers (we only need to do it once, generally) */ + if (qnodes[i]->qos.ap_owned && + qnodes[i]->qos.qos_mode != NOC_QOS_MODE_INVALID) { + ret = qcom_icc_qos_set(node); + if (ret) + return ret; + } + data->nodes[i] = node; } data->num_nodes = num_nodes; + clk_bulk_disable_unprepare(qp->num_intf_clks, qp->intf_clks); + ret = icc_provider_register(provider); if (ret) goto err_remove_nodes; @@ -551,7 +557,7 @@ int qnoc_probe(struct platform_device *pdev) icc_provider_deregister(provider); err_remove_nodes: icc_nodes_remove(provider); - clk_bulk_disable_unprepare(qp->num_clks, qp->bus_clks); + clk_bulk_disable_unprepare(qp->num_bus_clks, qp->bus_clks); return ret; } @@ -563,7 +569,7 @@ int qnoc_remove(struct platform_device *pdev) icc_provider_deregister(&qp->provider); icc_nodes_remove(&qp->provider); - clk_bulk_disable_unprepare(qp->num_clks, qp->bus_clks); + clk_bulk_disable_unprepare(qp->num_bus_clks, qp->bus_clks); return 0; } diff --git a/drivers/interconnect/qcom/icc-rpm.h b/drivers/interconnect/qcom/icc-rpm.h index 22bdb1e4bb123aacbf18a6b84ec6dfb29d74975f..ee705edf19dd67bcf9c24bca2884bfd36d3482fe 100644 --- a/drivers/interconnect/qcom/icc-rpm.h +++ b/drivers/interconnect/qcom/icc-rpm.h @@ -20,24 +20,32 @@ enum qcom_icc_type { QCOM_ICC_QNOC, }; +#define NUM_BUS_CLKS 2 + /** * struct qcom_icc_provider - Qualcomm specific interconnect provider * @provider: generic interconnect provider - * @num_clks: the total number of clk_bulk_data entries + * @num_bus_clks: the total number of bus_clks clk_bulk_data entries (0 or 2) + * @num_intf_clks: the total number of intf_clks clk_bulk_data entries * @type: the ICC provider type * @regmap: regmap for QoS registers read/write access * @qos_offset: offset to QoS registers * @bus_clk_rate: bus clock rate in Hz * @bus_clks: the clk_bulk_data table of bus clocks + * @intf_clks: a clk_bulk_data array of interface clocks + * @is_on: whether the bus is powered on */ struct qcom_icc_provider { struct icc_provider provider; - int num_clks; + int num_bus_clks; + int num_intf_clks; enum qcom_icc_type type; struct regmap *regmap; unsigned int qos_offset; - u64 *bus_clk_rate; - struct clk_bulk_data bus_clks[]; + u64 bus_clk_rate[NUM_BUS_CLKS]; + struct clk_bulk_data bus_clks[NUM_BUS_CLKS]; + struct clk_bulk_data *intf_clks; + bool is_on; }; /** @@ -91,8 +99,10 @@ struct qcom_icc_node { struct qcom_icc_desc { struct qcom_icc_node * const *nodes; size_t num_nodes; - const char * const *clocks; - size_t num_clocks; + const char * const *bus_clocks; + const char * const *intf_clocks; + size_t num_intf_clocks; + bool no_clk_scaling; enum qcom_icc_type type; const struct regmap_config *regmap_cfg; unsigned int qos_offset; diff --git a/drivers/interconnect/qcom/msm8996.c b/drivers/interconnect/qcom/msm8996.c index 14efd2761b7ab80cdd3af0c741c1aca8582e885c..20340fb62fe66234ebabb3e1e4663230dc4c2df8 100644 --- a/drivers/interconnect/qcom/msm8996.c +++ b/drivers/interconnect/qcom/msm8996.c @@ -21,21 +21,17 @@ #include "smd-rpm.h" #include "msm8996.h" -static const char * const bus_mm_clocks[] = { - "bus", - "bus_a", +static const char * const mm_intf_clocks[] = { "iface" }; -static const char * const bus_a0noc_clocks[] = { +static const char * const a0noc_intf_clocks[] = { "aggre0_snoc_axi", "aggre0_cnoc_ahb", "aggre0_noc_mpu_cfg" }; -static const char * const bus_a2noc_clocks[] = { - "bus", - "bus_a", +static const char * const a2noc_intf_clocks[] = { "aggre2_ufs_axi", "ufs_axi" }; @@ -1821,8 +1817,9 @@ static const struct qcom_icc_desc msm8996_a0noc = { .type = QCOM_ICC_NOC, .nodes = a0noc_nodes, .num_nodes = ARRAY_SIZE(a0noc_nodes), - .clocks = bus_a0noc_clocks, - .num_clocks = ARRAY_SIZE(bus_a0noc_clocks), + .intf_clocks = a0noc_intf_clocks, + .num_intf_clocks = ARRAY_SIZE(a0noc_intf_clocks), + .no_clk_scaling = true, .regmap_cfg = &msm8996_a0noc_regmap_config }; @@ -1865,8 +1862,8 @@ static const struct qcom_icc_desc msm8996_a2noc = { .type = QCOM_ICC_NOC, .nodes = a2noc_nodes, .num_nodes = ARRAY_SIZE(a2noc_nodes), - .clocks = bus_a2noc_clocks, - .num_clocks = ARRAY_SIZE(bus_a2noc_clocks), + .intf_clocks = a2noc_intf_clocks, + .num_intf_clocks = ARRAY_SIZE(a2noc_intf_clocks), .regmap_cfg = &msm8996_a2noc_regmap_config }; @@ -2004,8 +2001,8 @@ static const struct qcom_icc_desc msm8996_mnoc = { .type = QCOM_ICC_NOC, .nodes = mnoc_nodes, .num_nodes = ARRAY_SIZE(mnoc_nodes), - .clocks = bus_mm_clocks, - .num_clocks = ARRAY_SIZE(bus_mm_clocks), + .intf_clocks = mm_intf_clocks, + .num_intf_clocks = ARRAY_SIZE(mm_intf_clocks), .regmap_cfg = &msm8996_mnoc_regmap_config }; @@ -2111,7 +2108,17 @@ static struct platform_driver qnoc_driver = { .sync_state = icc_sync_state, } }; -module_platform_driver(qnoc_driver); +static int __init qnoc_driver_init(void) +{ + return platform_driver_register(&qnoc_driver); +} +core_initcall(qnoc_driver_init); + +static void __exit qnoc_driver_exit(void) +{ + platform_driver_unregister(&qnoc_driver); +} +module_exit(qnoc_driver_exit); MODULE_AUTHOR("Yassine Oudjana "); MODULE_DESCRIPTION("Qualcomm MSM8996 NoC driver"); diff --git a/drivers/interconnect/qcom/sdm660.c b/drivers/interconnect/qcom/sdm660.c index 8d879b0bcabcfbed7b3be1a4a127d4c99fe58a17..7ffaf70d62d3dad92fe6714f71e24cb37104ac2b 100644 --- a/drivers/interconnect/qcom/sdm660.c +++ b/drivers/interconnect/qcom/sdm660.c @@ -127,15 +127,11 @@ enum { SDM660_SNOC, }; -static const char * const bus_mm_clocks[] = { - "bus", - "bus_a", +static const char * const mm_intf_clocks[] = { "iface", }; -static const char * const bus_a2noc_clocks[] = { - "bus", - "bus_a", +static const char * const a2noc_intf_clocks[] = { "ipa", "ufs_axi", "aggre2_ufs_axi", @@ -1516,8 +1512,8 @@ static const struct qcom_icc_desc sdm660_a2noc = { .type = QCOM_ICC_NOC, .nodes = sdm660_a2noc_nodes, .num_nodes = ARRAY_SIZE(sdm660_a2noc_nodes), - .clocks = bus_a2noc_clocks, - .num_clocks = ARRAY_SIZE(bus_a2noc_clocks), + .intf_clocks = a2noc_intf_clocks, + .num_intf_clocks = ARRAY_SIZE(a2noc_intf_clocks), .regmap_cfg = &sdm660_a2noc_regmap_config, }; @@ -1620,6 +1616,7 @@ static const struct qcom_icc_desc sdm660_gnoc = { .nodes = sdm660_gnoc_nodes, .num_nodes = ARRAY_SIZE(sdm660_gnoc_nodes), .regmap_cfg = &sdm660_gnoc_regmap_config, + .no_clk_scaling = true, }; static struct qcom_icc_node * const sdm660_mnoc_nodes[] = { @@ -1659,8 +1656,8 @@ static const struct qcom_icc_desc sdm660_mnoc = { .type = QCOM_ICC_NOC, .nodes = sdm660_mnoc_nodes, .num_nodes = ARRAY_SIZE(sdm660_mnoc_nodes), - .clocks = bus_mm_clocks, - .num_clocks = ARRAY_SIZE(bus_mm_clocks), + .intf_clocks = mm_intf_clocks, + .num_intf_clocks = ARRAY_SIZE(mm_intf_clocks), .regmap_cfg = &sdm660_mnoc_regmap_config, }; diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig index 4d800601e8ecd6002c462383e4fc6d2cc186cb03..2b12b583ef4b1edb8c296f59e7e6d4dcc4ca095e 100644 --- a/drivers/iommu/Kconfig +++ b/drivers/iommu/Kconfig @@ -152,6 +152,7 @@ config IOMMU_DMA select IOMMU_IOVA select IRQ_MSI_IOMMU select NEED_SG_DMA_LENGTH + select NEED_SG_DMA_FLAGS if SWIOTLB # Shared Virtual Addressing config IOMMU_SVA diff --git a/drivers/iommu/amd/amd_iommu.h b/drivers/iommu/amd/amd_iommu.h index 9beeceb9d825dfeae9e2aa9229e031513680ba09..0c35018239cecfa2308a4e10c737f751289149ce 100644 --- a/drivers/iommu/amd/amd_iommu.h +++ b/drivers/iommu/amd/amd_iommu.h @@ -11,12 +11,15 @@ #include "amd_iommu_types.h" -extern irqreturn_t amd_iommu_int_thread(int irq, void *data); -extern irqreturn_t amd_iommu_int_handler(int irq, void *data); -extern void amd_iommu_apply_erratum_63(struct amd_iommu *iommu, u16 devid); -extern void amd_iommu_restart_event_logging(struct amd_iommu *iommu); -extern void amd_iommu_restart_ga_log(struct amd_iommu *iommu); -extern void amd_iommu_set_rlookup_table(struct amd_iommu *iommu, u16 devid); +irqreturn_t amd_iommu_int_thread(int irq, void *data); +irqreturn_t amd_iommu_int_handler(int irq, void *data); +void amd_iommu_apply_erratum_63(struct amd_iommu *iommu, u16 devid); +void amd_iommu_restart_event_logging(struct amd_iommu *iommu); +void amd_iommu_restart_ga_log(struct amd_iommu *iommu); +int amd_iommu_init_devices(void); +void amd_iommu_uninit_devices(void); +void amd_iommu_init_notifier(void); +void amd_iommu_set_rlookup_table(struct amd_iommu *iommu, u16 devid); #ifdef CONFIG_AMD_IOMMU_DEBUGFS void amd_iommu_debugfs_setup(struct amd_iommu *iommu); @@ -25,11 +28,11 @@ static inline void amd_iommu_debugfs_setup(struct amd_iommu *iommu) {} #endif /* Needed for interrupt remapping */ -extern int amd_iommu_prepare(void); -extern int amd_iommu_enable(void); -extern void amd_iommu_disable(void); -extern int amd_iommu_reenable(int); -extern int amd_iommu_enable_faulting(void); +int amd_iommu_prepare(void); +int amd_iommu_enable(void); +void amd_iommu_disable(void); +int amd_iommu_reenable(int mode); +int amd_iommu_enable_faulting(void); extern int amd_iommu_guest_ir; extern enum io_pgtable_fmt amd_iommu_pgtable; extern int amd_iommu_gpt_level; @@ -37,33 +40,32 @@ extern int amd_iommu_gpt_level; /* IOMMUv2 specific functions */ struct iommu_domain; -extern bool amd_iommu_v2_supported(void); -extern struct amd_iommu *get_amd_iommu(unsigned int idx); -extern u8 amd_iommu_pc_get_max_banks(unsigned int idx); -extern bool amd_iommu_pc_supported(void); -extern u8 amd_iommu_pc_get_max_counters(unsigned int idx); -extern int amd_iommu_pc_get_reg(struct amd_iommu *iommu, u8 bank, u8 cntr, - u8 fxn, u64 *value); -extern int amd_iommu_pc_set_reg(struct amd_iommu *iommu, u8 bank, u8 cntr, - u8 fxn, u64 *value); - -extern int amd_iommu_register_ppr_notifier(struct notifier_block *nb); -extern int amd_iommu_unregister_ppr_notifier(struct notifier_block *nb); -extern void amd_iommu_domain_direct_map(struct iommu_domain *dom); -extern int amd_iommu_domain_enable_v2(struct iommu_domain *dom, int pasids); -extern int amd_iommu_flush_page(struct iommu_domain *dom, u32 pasid, - u64 address); -extern void amd_iommu_update_and_flush_device_table(struct protection_domain *domain); -extern void amd_iommu_domain_update(struct protection_domain *domain); -extern void amd_iommu_domain_flush_complete(struct protection_domain *domain); -extern void amd_iommu_domain_flush_tlb_pde(struct protection_domain *domain); -extern int amd_iommu_flush_tlb(struct iommu_domain *dom, u32 pasid); -extern int amd_iommu_domain_set_gcr3(struct iommu_domain *dom, u32 pasid, - unsigned long cr3); -extern int amd_iommu_domain_clear_gcr3(struct iommu_domain *dom, u32 pasid); +bool amd_iommu_v2_supported(void); +struct amd_iommu *get_amd_iommu(unsigned int idx); +u8 amd_iommu_pc_get_max_banks(unsigned int idx); +bool amd_iommu_pc_supported(void); +u8 amd_iommu_pc_get_max_counters(unsigned int idx); +int amd_iommu_pc_get_reg(struct amd_iommu *iommu, u8 bank, u8 cntr, + u8 fxn, u64 *value); +int amd_iommu_pc_set_reg(struct amd_iommu *iommu, u8 bank, u8 cntr, + u8 fxn, u64 *value); + +int amd_iommu_register_ppr_notifier(struct notifier_block *nb); +int amd_iommu_unregister_ppr_notifier(struct notifier_block *nb); +void amd_iommu_domain_direct_map(struct iommu_domain *dom); +int amd_iommu_domain_enable_v2(struct iommu_domain *dom, int pasids); +int amd_iommu_flush_page(struct iommu_domain *dom, u32 pasid, u64 address); +void amd_iommu_update_and_flush_device_table(struct protection_domain *domain); +void amd_iommu_domain_update(struct protection_domain *domain); +void amd_iommu_domain_flush_complete(struct protection_domain *domain); +void amd_iommu_domain_flush_tlb_pde(struct protection_domain *domain); +int amd_iommu_flush_tlb(struct iommu_domain *dom, u32 pasid); +int amd_iommu_domain_set_gcr3(struct iommu_domain *dom, u32 pasid, + unsigned long cr3); +int amd_iommu_domain_clear_gcr3(struct iommu_domain *dom, u32 pasid); #ifdef CONFIG_IRQ_REMAP -extern int amd_iommu_create_irq_domain(struct amd_iommu *iommu); +int amd_iommu_create_irq_domain(struct amd_iommu *iommu); #else static inline int amd_iommu_create_irq_domain(struct amd_iommu *iommu) { @@ -75,8 +77,8 @@ static inline int amd_iommu_create_irq_domain(struct amd_iommu *iommu) #define PPR_INVALID 0x1 #define PPR_FAILURE 0xf -extern int amd_iommu_complete_ppr(struct pci_dev *pdev, u32 pasid, - int status, int tag); +int amd_iommu_complete_ppr(struct pci_dev *pdev, u32 pasid, + int status, int tag); static inline bool is_rd890_iommu(struct pci_dev *pdev) { @@ -129,10 +131,9 @@ static inline void *alloc_pgtable_page(int nid, gfp_t gfp) return page ? page_address(page) : NULL; } -extern bool translation_pre_enabled(struct amd_iommu *iommu); -extern bool amd_iommu_is_attach_deferred(struct device *dev); -extern int __init add_special_device(u8 type, u8 id, u32 *devid, - bool cmd_line); +bool translation_pre_enabled(struct amd_iommu *iommu); +bool amd_iommu_is_attach_deferred(struct device *dev); +int __init add_special_device(u8 type, u8 id, u32 *devid, bool cmd_line); #ifdef CONFIG_DMI void amd_iommu_apply_ivrs_quirks(void); @@ -140,9 +141,9 @@ void amd_iommu_apply_ivrs_quirks(void); static inline void amd_iommu_apply_ivrs_quirks(void) { } #endif -extern void amd_iommu_domain_set_pgtable(struct protection_domain *domain, - u64 *root, int mode); -extern struct dev_table_entry *get_dev_table(struct amd_iommu *iommu); +void amd_iommu_domain_set_pgtable(struct protection_domain *domain, + u64 *root, int mode); +struct dev_table_entry *get_dev_table(struct amd_iommu *iommu); extern u64 amd_iommu_efr; extern u64 amd_iommu_efr2; diff --git a/drivers/iommu/amd/amd_iommu_types.h b/drivers/iommu/amd/amd_iommu_types.h index 2ddbda3a43746fd1c8c9b7179e67735bc2f0e243..dc1db6167927910939cdf9d5d749fdbeedf9e5bd 100644 --- a/drivers/iommu/amd/amd_iommu_types.h +++ b/drivers/iommu/amd/amd_iommu_types.h @@ -84,21 +84,21 @@ /* Extended Feature Bits */ -#define FEATURE_PREFETCH (1ULL<<0) -#define FEATURE_PPR (1ULL<<1) -#define FEATURE_X2APIC (1ULL<<2) -#define FEATURE_NX (1ULL<<3) -#define FEATURE_GT (1ULL<<4) -#define FEATURE_IA (1ULL<<6) -#define FEATURE_GA (1ULL<<7) -#define FEATURE_HE (1ULL<<8) -#define FEATURE_PC (1ULL<<9) +#define FEATURE_PREFETCH BIT_ULL(0) +#define FEATURE_PPR BIT_ULL(1) +#define FEATURE_X2APIC BIT_ULL(2) +#define FEATURE_NX BIT_ULL(3) +#define FEATURE_GT BIT_ULL(4) +#define FEATURE_IA BIT_ULL(6) +#define FEATURE_GA BIT_ULL(7) +#define FEATURE_HE BIT_ULL(8) +#define FEATURE_PC BIT_ULL(9) #define FEATURE_GATS_SHIFT (12) #define FEATURE_GATS_MASK (3ULL) -#define FEATURE_GAM_VAPIC (1ULL<<21) -#define FEATURE_GIOSUP (1ULL<<48) -#define FEATURE_EPHSUP (1ULL<<50) -#define FEATURE_SNP (1ULL<<63) +#define FEATURE_GAM_VAPIC BIT_ULL(21) +#define FEATURE_GIOSUP BIT_ULL(48) +#define FEATURE_EPHSUP BIT_ULL(50) +#define FEATURE_SNP BIT_ULL(63) #define FEATURE_PASID_SHIFT 32 #define FEATURE_PASID_MASK (0x1fULL << FEATURE_PASID_SHIFT) @@ -120,13 +120,13 @@ #define PASID_MASK 0x0000ffff /* MMIO status bits */ -#define MMIO_STATUS_EVT_OVERFLOW_INT_MASK (1 << 0) -#define MMIO_STATUS_EVT_INT_MASK (1 << 1) -#define MMIO_STATUS_COM_WAIT_INT_MASK (1 << 2) -#define MMIO_STATUS_PPR_INT_MASK (1 << 6) -#define MMIO_STATUS_GALOG_RUN_MASK (1 << 8) -#define MMIO_STATUS_GALOG_OVERFLOW_MASK (1 << 9) -#define MMIO_STATUS_GALOG_INT_MASK (1 << 10) +#define MMIO_STATUS_EVT_OVERFLOW_INT_MASK BIT(0) +#define MMIO_STATUS_EVT_INT_MASK BIT(1) +#define MMIO_STATUS_COM_WAIT_INT_MASK BIT(2) +#define MMIO_STATUS_PPR_INT_MASK BIT(6) +#define MMIO_STATUS_GALOG_RUN_MASK BIT(8) +#define MMIO_STATUS_GALOG_OVERFLOW_MASK BIT(9) +#define MMIO_STATUS_GALOG_INT_MASK BIT(10) /* event logging constants */ #define EVENT_ENTRY_SIZE 0x10 @@ -174,6 +174,7 @@ #define CONTROL_GAINT_EN 29 #define CONTROL_XT_EN 50 #define CONTROL_INTCAPXT_EN 51 +#define CONTROL_IRTCACHEDIS 59 #define CONTROL_SNPAVIC_EN 61 #define CTRL_INV_TO_MASK (7 << CONTROL_INV_TIMEOUT) @@ -283,7 +284,7 @@ #define AMD_IOMMU_PGSIZES_V2 (PAGE_SIZE | (1ULL << 21) | (1ULL << 30)) /* Bit value definition for dte irq remapping fields*/ -#define DTE_IRQ_PHYS_ADDR_MASK (((1ULL << 45)-1) << 6) +#define DTE_IRQ_PHYS_ADDR_MASK GENMASK_ULL(51, 6) #define DTE_IRQ_REMAP_INTCTL_MASK (0x3ULL << 60) #define DTE_IRQ_REMAP_INTCTL (2ULL << 60) #define DTE_IRQ_REMAP_ENABLE 1ULL @@ -369,23 +370,23 @@ /* * Bit value definition for I/O PTE fields */ -#define IOMMU_PTE_PR (1ULL << 0) -#define IOMMU_PTE_U (1ULL << 59) -#define IOMMU_PTE_FC (1ULL << 60) -#define IOMMU_PTE_IR (1ULL << 61) -#define IOMMU_PTE_IW (1ULL << 62) +#define IOMMU_PTE_PR BIT_ULL(0) +#define IOMMU_PTE_U BIT_ULL(59) +#define IOMMU_PTE_FC BIT_ULL(60) +#define IOMMU_PTE_IR BIT_ULL(61) +#define IOMMU_PTE_IW BIT_ULL(62) /* * Bit value definition for DTE fields */ -#define DTE_FLAG_V (1ULL << 0) -#define DTE_FLAG_TV (1ULL << 1) -#define DTE_FLAG_IR (1ULL << 61) -#define DTE_FLAG_IW (1ULL << 62) - -#define DTE_FLAG_IOTLB (1ULL << 32) -#define DTE_FLAG_GIOV (1ULL << 54) -#define DTE_FLAG_GV (1ULL << 55) +#define DTE_FLAG_V BIT_ULL(0) +#define DTE_FLAG_TV BIT_ULL(1) +#define DTE_FLAG_IR BIT_ULL(61) +#define DTE_FLAG_IW BIT_ULL(62) + +#define DTE_FLAG_IOTLB BIT_ULL(32) +#define DTE_FLAG_GIOV BIT_ULL(54) +#define DTE_FLAG_GV BIT_ULL(55) #define DTE_FLAG_MASK (0x3ffULL << 32) #define DTE_GLX_SHIFT (56) #define DTE_GLX_MASK (3) @@ -439,13 +440,13 @@ #define MAX_DOMAIN_ID 65536 /* Protection domain flags */ -#define PD_DMA_OPS_MASK (1UL << 0) /* domain used for dma_ops */ -#define PD_DEFAULT_MASK (1UL << 1) /* domain is a default dma_ops +#define PD_DMA_OPS_MASK BIT(0) /* domain used for dma_ops */ +#define PD_DEFAULT_MASK BIT(1) /* domain is a default dma_ops domain for an IOMMU */ -#define PD_PASSTHROUGH_MASK (1UL << 2) /* domain has no page +#define PD_PASSTHROUGH_MASK BIT(2) /* domain has no page translation */ -#define PD_IOMMUV2_MASK (1UL << 3) /* domain has gcr3 table */ -#define PD_GIOV_MASK (1UL << 4) /* domain enable GIOV support */ +#define PD_IOMMUV2_MASK BIT(3) /* domain has gcr3 table */ +#define PD_GIOV_MASK BIT(4) /* domain enable GIOV support */ extern bool amd_iommu_dump; #define DUMP_printk(format, arg...) \ @@ -716,6 +717,9 @@ struct amd_iommu { /* if one, we need to send a completion wait command */ bool need_sync; + /* true if disable irte caching */ + bool irtcachedis_enabled; + /* Handle for IOMMU core code */ struct iommu_device iommu; @@ -748,7 +752,7 @@ struct amd_iommu { u32 flags; volatile u64 *cmd_sem; - u64 cmd_sem_val; + atomic64_t cmd_sem_val; #ifdef CONFIG_AMD_IOMMU_DEBUGFS /* DebugFS Info */ @@ -882,7 +886,7 @@ extern int amd_iommu_max_glx_val; * This function flushes all internal caches of * the IOMMU used by this driver. */ -extern void iommu_flush_all_caches(struct amd_iommu *iommu); +void iommu_flush_all_caches(struct amd_iommu *iommu); static inline int get_ioapic_devid(int id) { @@ -986,8 +990,13 @@ union irte_ga_hi { }; struct irte_ga { - union irte_ga_lo lo; - union irte_ga_hi hi; + union { + struct { + union irte_ga_lo lo; + union irte_ga_hi hi; + }; + u128 irte; + }; }; struct irq_2_irte { @@ -1001,7 +1010,6 @@ struct amd_ir_data { struct irq_2_irte irq_2_irte; struct msi_msg msi_entry; void *entry; /* Pointer to union irte or struct irte_ga */ - void *ref; /* Pointer to the actual irte */ /** * Store information for activate/de-activate diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c index c2d80a4e5fb066c69cfe0f8cab1856894bfbb2e3..ea0f1ab94178373094f9eff87a4512c7781b3e22 100644 --- a/drivers/iommu/amd/init.c +++ b/drivers/iommu/amd/init.c @@ -162,6 +162,7 @@ static int amd_iommu_xt_mode = IRQ_REMAP_XAPIC_MODE; static bool amd_iommu_detected; static bool amd_iommu_disabled __initdata; static bool amd_iommu_force_enable __initdata; +static bool amd_iommu_irtcachedis; static int amd_iommu_target_ivhd_type; /* Global EFR and EFR2 registers */ @@ -484,6 +485,9 @@ static void iommu_disable(struct amd_iommu *iommu) /* Disable IOMMU hardware itself */ iommu_feature_disable(iommu, CONTROL_IOMMU_EN); + + /* Clear IRTE cache disabling bit */ + iommu_feature_disable(iommu, CONTROL_IRTCACHEDIS); } /* @@ -1753,7 +1757,7 @@ static int __init init_iommu_one(struct amd_iommu *iommu, struct ivhd_header *h, iommu->pci_seg = pci_seg; raw_spin_lock_init(&iommu->lock); - iommu->cmd_sem_val = 0; + atomic64_set(&iommu->cmd_sem_val, 0); /* Add IOMMU to internal data structures */ list_add_tail(&iommu->list, &amd_iommu_list); @@ -2710,6 +2714,33 @@ static void iommu_enable_ga(struct amd_iommu *iommu) #endif } +static void iommu_disable_irtcachedis(struct amd_iommu *iommu) +{ + iommu_feature_disable(iommu, CONTROL_IRTCACHEDIS); +} + +static void iommu_enable_irtcachedis(struct amd_iommu *iommu) +{ + u64 ctrl; + + if (!amd_iommu_irtcachedis) + return; + + /* + * Note: + * The support for IRTCacheDis feature is dertermined by + * checking if the bit is writable. + */ + iommu_feature_enable(iommu, CONTROL_IRTCACHEDIS); + ctrl = readq(iommu->mmio_base + MMIO_CONTROL_OFFSET); + ctrl &= (1ULL << CONTROL_IRTCACHEDIS); + if (ctrl) + iommu->irtcachedis_enabled = true; + pr_info("iommu%d (%#06x) : IRT cache is %s\n", + iommu->index, iommu->devid, + iommu->irtcachedis_enabled ? "disabled" : "enabled"); +} + static void early_enable_iommu(struct amd_iommu *iommu) { iommu_disable(iommu); @@ -2720,6 +2751,7 @@ static void early_enable_iommu(struct amd_iommu *iommu) iommu_set_exclusion_range(iommu); iommu_enable_ga(iommu); iommu_enable_xt(iommu); + iommu_enable_irtcachedis(iommu); iommu_enable(iommu); iommu_flush_all_caches(iommu); } @@ -2770,10 +2802,12 @@ static void early_enable_iommus(void) for_each_iommu(iommu) { iommu_disable_command_buffer(iommu); iommu_disable_event_buffer(iommu); + iommu_disable_irtcachedis(iommu); iommu_enable_command_buffer(iommu); iommu_enable_event_buffer(iommu); iommu_enable_ga(iommu); iommu_enable_xt(iommu); + iommu_enable_irtcachedis(iommu); iommu_set_device_table(iommu); iommu_flush_all_caches(iommu); } @@ -3426,6 +3460,8 @@ static int __init parse_amd_iommu_options(char *str) amd_iommu_pgtable = AMD_IOMMU_V1; } else if (strncmp(str, "pgtbl_v2", 8) == 0) { amd_iommu_pgtable = AMD_IOMMU_V2; + } else if (strncmp(str, "irtcachedis", 11) == 0) { + amd_iommu_irtcachedis = true; } else { pr_notice("Unknown option - '%s'\n", str); } diff --git a/drivers/iommu/amd/io_pgtable.c b/drivers/iommu/amd/io_pgtable.c index 1b67116882bef8e2317b9e5eaa0c6d39b2b35bee..2892aa1b4dc1db1771b9ebe5d418a14da9e5f456 100644 --- a/drivers/iommu/amd/io_pgtable.c +++ b/drivers/iommu/amd/io_pgtable.c @@ -310,8 +310,8 @@ static u64 *fetch_pte(struct amd_io_pgtable *pgtable, return NULL; /* Large PTE */ - if (PM_PTE_LEVEL(*pte) == 7 || - PM_PTE_LEVEL(*pte) == 0) + if (PM_PTE_LEVEL(*pte) == PAGE_MODE_7_LEVEL || + PM_PTE_LEVEL(*pte) == PAGE_MODE_NONE) break; /* No level skipping support yet */ diff --git a/drivers/iommu/amd/io_pgtable_v2.c b/drivers/iommu/amd/io_pgtable_v2.c index 27c3015947e6fdc2fec5da7bc92614014af9d76f..e9ef2e0a62f670096cc317876180f1d888fd6e07 100644 --- a/drivers/iommu/amd/io_pgtable_v2.c +++ b/drivers/iommu/amd/io_pgtable_v2.c @@ -2,7 +2,7 @@ /* * CPU-agnostic AMD IO page table v2 allocator. * - * Copyright (C) 2022 Advanced Micro Devices, Inc. + * Copyright (C) 2022, 2023 Advanced Micro Devices, Inc. * Author: Suravee Suthikulpanit * Author: Vasant Hegde */ diff --git a/drivers/iommu/amd/iommu.c b/drivers/iommu/amd/iommu.c index dc1ec684977542ea5aa1af73a055ff962cdbe3d0..c3b58a8389b9bff28db96b42289ff1af7db64dc6 100644 --- a/drivers/iommu/amd/iommu.c +++ b/drivers/iommu/amd/iommu.c @@ -1182,11 +1182,11 @@ static int iommu_completion_wait(struct amd_iommu *iommu) if (!iommu->need_sync) return 0; - raw_spin_lock_irqsave(&iommu->lock, flags); - - data = ++iommu->cmd_sem_val; + data = atomic64_add_return(1, &iommu->cmd_sem_val); build_completion_wait(&cmd, iommu, data); + raw_spin_lock_irqsave(&iommu->lock, flags); + ret = __iommu_queue_command_sync(iommu, &cmd, false); if (ret) goto out_unlock; @@ -1273,6 +1273,9 @@ static void amd_iommu_flush_irt_all(struct amd_iommu *iommu) u32 devid; u16 last_bdf = iommu->pci_seg->last_bdf; + if (iommu->irtcachedis_enabled) + return; + for (devid = 0; devid <= last_bdf; devid++) iommu_flush_irt(iommu, devid); @@ -2078,10 +2081,6 @@ static struct protection_domain *protection_domain_alloc(unsigned int type) int mode = DEFAULT_PGTABLE_LEVEL; int ret; - domain = kzalloc(sizeof(*domain), GFP_KERNEL); - if (!domain) - return NULL; - /* * Force IOMMU v1 page table when iommu=pt and * when allocating domain for pass-through devices. @@ -2097,6 +2096,10 @@ static struct protection_domain *protection_domain_alloc(unsigned int type) return NULL; } + domain = kzalloc(sizeof(*domain), GFP_KERNEL); + if (!domain) + return NULL; + switch (pgtable) { case AMD_IOMMU_V1: ret = protection_domain_init_v1(domain, mode); @@ -2313,6 +2316,8 @@ static bool amd_iommu_capable(struct device *dev, enum iommu_cap cap) return amdr_ivrs_remap_support; case IOMMU_CAP_ENFORCE_CACHE_COHERENCY: return true; + case IOMMU_CAP_DEFERRED_FLUSH: + return true; default: break; } @@ -2822,6 +2827,32 @@ EXPORT_SYMBOL(amd_iommu_device_info); static struct irq_chip amd_ir_chip; static DEFINE_SPINLOCK(iommu_table_lock); +static void iommu_flush_irt_and_complete(struct amd_iommu *iommu, u16 devid) +{ + int ret; + u64 data; + unsigned long flags; + struct iommu_cmd cmd, cmd2; + + if (iommu->irtcachedis_enabled) + return; + + build_inv_irt(&cmd, devid); + data = atomic64_add_return(1, &iommu->cmd_sem_val); + build_completion_wait(&cmd2, iommu, data); + + raw_spin_lock_irqsave(&iommu->lock, flags); + ret = __iommu_queue_command_sync(iommu, &cmd, true); + if (ret) + goto out; + ret = __iommu_queue_command_sync(iommu, &cmd2, false); + if (ret) + goto out; + wait_on_sem(iommu, data); +out: + raw_spin_unlock_irqrestore(&iommu->lock, flags); +} + static void set_dte_irq_entry(struct amd_iommu *iommu, u16 devid, struct irq_remap_table *table) { @@ -3021,12 +3052,12 @@ static int alloc_irq_index(struct amd_iommu *iommu, u16 devid, int count, } static int modify_irte_ga(struct amd_iommu *iommu, u16 devid, int index, - struct irte_ga *irte, struct amd_ir_data *data) + struct irte_ga *irte) { - bool ret; struct irq_remap_table *table; - unsigned long flags; struct irte_ga *entry; + unsigned long flags; + u128 old; table = get_irq_table(iommu, devid); if (!table) @@ -3037,24 +3068,18 @@ static int modify_irte_ga(struct amd_iommu *iommu, u16 devid, int index, entry = (struct irte_ga *)table->table; entry = &entry[index]; - ret = cmpxchg_double(&entry->lo.val, &entry->hi.val, - entry->lo.val, entry->hi.val, - irte->lo.val, irte->hi.val); /* * We use cmpxchg16 to atomically update the 128-bit IRTE, * and it cannot be updated by the hardware or other processors * behind us, so the return value of cmpxchg16 should be the * same as the old value. */ - WARN_ON(!ret); - - if (data) - data->ref = entry; + old = entry->irte; + WARN_ON(!try_cmpxchg128(&entry->irte, &old, irte->irte)); raw_spin_unlock_irqrestore(&table->lock, flags); - iommu_flush_irt(iommu, devid); - iommu_completion_wait(iommu); + iommu_flush_irt_and_complete(iommu, devid); return 0; } @@ -3073,8 +3098,7 @@ static int modify_irte(struct amd_iommu *iommu, table->table[index] = irte->val; raw_spin_unlock_irqrestore(&table->lock, flags); - iommu_flush_irt(iommu, devid); - iommu_completion_wait(iommu); + iommu_flush_irt_and_complete(iommu, devid); return 0; } @@ -3092,8 +3116,7 @@ static void free_irte(struct amd_iommu *iommu, u16 devid, int index) iommu->irte_ops->clear_allocated(table, index); raw_spin_unlock_irqrestore(&table->lock, flags); - iommu_flush_irt(iommu, devid); - iommu_completion_wait(iommu); + iommu_flush_irt_and_complete(iommu, devid); } static void irte_prepare(void *entry, @@ -3139,7 +3162,7 @@ static void irte_ga_activate(struct amd_iommu *iommu, void *entry, u16 devid, u1 struct irte_ga *irte = (struct irte_ga *) entry; irte->lo.fields_remap.valid = 1; - modify_irte_ga(iommu, devid, index, irte, NULL); + modify_irte_ga(iommu, devid, index, irte); } static void irte_deactivate(struct amd_iommu *iommu, void *entry, u16 devid, u16 index) @@ -3155,7 +3178,7 @@ static void irte_ga_deactivate(struct amd_iommu *iommu, void *entry, u16 devid, struct irte_ga *irte = (struct irte_ga *) entry; irte->lo.fields_remap.valid = 0; - modify_irte_ga(iommu, devid, index, irte, NULL); + modify_irte_ga(iommu, devid, index, irte); } static void irte_set_affinity(struct amd_iommu *iommu, void *entry, u16 devid, u16 index, @@ -3179,7 +3202,7 @@ static void irte_ga_set_affinity(struct amd_iommu *iommu, void *entry, u16 devid APICID_TO_IRTE_DEST_LO(dest_apicid); irte->hi.fields.destination = APICID_TO_IRTE_DEST_HI(dest_apicid); - modify_irte_ga(iommu, devid, index, irte, NULL); + modify_irte_ga(iommu, devid, index, irte); } } @@ -3529,7 +3552,7 @@ int amd_iommu_activate_guest_mode(void *data) entry->lo.fields_vapic.ga_tag = ir_data->ga_tag; return modify_irte_ga(ir_data->iommu, ir_data->irq_2_irte.devid, - ir_data->irq_2_irte.index, entry, ir_data); + ir_data->irq_2_irte.index, entry); } EXPORT_SYMBOL(amd_iommu_activate_guest_mode); @@ -3559,7 +3582,7 @@ int amd_iommu_deactivate_guest_mode(void *data) APICID_TO_IRTE_DEST_HI(cfg->dest_apicid); return modify_irte_ga(ir_data->iommu, ir_data->irq_2_irte.devid, - ir_data->irq_2_irte.index, entry, ir_data); + ir_data->irq_2_irte.index, entry); } EXPORT_SYMBOL(amd_iommu_deactivate_guest_mode); @@ -3721,44 +3744,26 @@ int amd_iommu_create_irq_domain(struct amd_iommu *iommu) int amd_iommu_update_ga(int cpu, bool is_run, void *data) { - unsigned long flags; - struct amd_iommu *iommu; - struct irq_remap_table *table; struct amd_ir_data *ir_data = (struct amd_ir_data *)data; - int devid = ir_data->irq_2_irte.devid; struct irte_ga *entry = (struct irte_ga *) ir_data->entry; - struct irte_ga *ref = (struct irte_ga *) ir_data->ref; if (!AMD_IOMMU_GUEST_IR_VAPIC(amd_iommu_guest_ir) || - !ref || !entry || !entry->lo.fields_vapic.guest_mode) + !entry || !entry->lo.fields_vapic.guest_mode) return 0; - iommu = ir_data->iommu; - if (!iommu) + if (!ir_data->iommu) return -ENODEV; - table = get_irq_table(iommu, devid); - if (!table) - return -ENODEV; - - raw_spin_lock_irqsave(&table->lock, flags); - - if (ref->lo.fields_vapic.guest_mode) { - if (cpu >= 0) { - ref->lo.fields_vapic.destination = - APICID_TO_IRTE_DEST_LO(cpu); - ref->hi.fields.destination = - APICID_TO_IRTE_DEST_HI(cpu); - } - ref->lo.fields_vapic.is_run = is_run; - barrier(); + if (cpu >= 0) { + entry->lo.fields_vapic.destination = + APICID_TO_IRTE_DEST_LO(cpu); + entry->hi.fields.destination = + APICID_TO_IRTE_DEST_HI(cpu); } + entry->lo.fields_vapic.is_run = is_run; - raw_spin_unlock_irqrestore(&table->lock, flags); - - iommu_flush_irt(iommu, devid); - iommu_completion_wait(iommu); - return 0; + return modify_irte_ga(ir_data->iommu, ir_data->irq_2_irte.devid, + ir_data->irq_2_irte.index, entry); } EXPORT_SYMBOL(amd_iommu_update_ga); #endif diff --git a/drivers/iommu/amd/iommu_v2.c b/drivers/iommu/amd/iommu_v2.c index 864e4ffb6aa94ecb154b76c861c4eda3fdd11ec4..261352a2327162aea05f70083ebd9a0eb3767aa3 100644 --- a/drivers/iommu/amd/iommu_v2.c +++ b/drivers/iommu/amd/iommu_v2.c @@ -485,8 +485,8 @@ static void do_fault(struct work_struct *work) flags |= FAULT_FLAG_REMOTE; mmap_read_lock(mm); - vma = find_extend_vma(mm, address); - if (!vma || address < vma->vm_start) + vma = vma_lookup(mm, address); + if (!vma) /* failed to get a vma in the right range */ goto out; diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c index 3fd83fb75722713eaed891db9226ab76061eb898..9b0dc35056019e0fe095efeedbfc9eb7e320fa08 100644 --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c @@ -894,6 +894,12 @@ static void arm_smmu_cmdq_batch_add(struct arm_smmu_device *smmu, { int index; + if (cmds->num == CMDQ_BATCH_ENTRIES - 1 && + (smmu->options & ARM_SMMU_OPT_CMDQ_FORCE_SYNC)) { + arm_smmu_cmdq_issue_cmdlist(smmu, cmds->cmds, cmds->num, true); + cmds->num = 0; + } + if (cmds->num == CMDQ_BATCH_ENTRIES) { arm_smmu_cmdq_issue_cmdlist(smmu, cmds->cmds, cmds->num, false); cmds->num = 0; @@ -1892,8 +1898,13 @@ static void __arm_smmu_tlb_inv_range(struct arm_smmu_cmdq_ent *cmd, /* Convert page size of 12,14,16 (log2) to 1,2,3 */ cmd->tlbi.tg = (tg - 10) / 2; - /* Determine what level the granule is at */ - cmd->tlbi.ttl = 4 - ((ilog2(granule) - 3) / (tg - 3)); + /* + * Determine what level the granule is at. For non-leaf, io-pgtable + * assumes .tlb_flush_walk can invalidate multiple levels at once, + * so ignore the nominal last-level granule and leave TTL=0. + */ + if (cmd->tlbi.leaf) + cmd->tlbi.ttl = 4 - ((ilog2(granule) - 3) / (tg - 3)); num_pages = size >> tg; } @@ -2008,6 +2019,7 @@ static bool arm_smmu_capable(struct device *dev, enum iommu_cap cap) /* Assume that a coherent TCU implies coherent TBUs */ return master->smmu->features & ARM_SMMU_FEAT_COHERENCY; case IOMMU_CAP_NOEXEC: + case IOMMU_CAP_DEFERRED_FLUSH: return true; default: return false; @@ -2023,7 +2035,6 @@ static struct iommu_domain *arm_smmu_domain_alloc(unsigned type) if (type != IOMMU_DOMAIN_UNMANAGED && type != IOMMU_DOMAIN_DMA && - type != IOMMU_DOMAIN_DMA_FQ && type != IOMMU_DOMAIN_IDENTITY) return NULL; @@ -3429,6 +3440,44 @@ static int arm_smmu_device_reset(struct arm_smmu_device *smmu, bool bypass) return 0; } +#define IIDR_IMPLEMENTER_ARM 0x43b +#define IIDR_PRODUCTID_ARM_MMU_600 0x483 +#define IIDR_PRODUCTID_ARM_MMU_700 0x487 + +static void arm_smmu_device_iidr_probe(struct arm_smmu_device *smmu) +{ + u32 reg; + unsigned int implementer, productid, variant, revision; + + reg = readl_relaxed(smmu->base + ARM_SMMU_IIDR); + implementer = FIELD_GET(IIDR_IMPLEMENTER, reg); + productid = FIELD_GET(IIDR_PRODUCTID, reg); + variant = FIELD_GET(IIDR_VARIANT, reg); + revision = FIELD_GET(IIDR_REVISION, reg); + + switch (implementer) { + case IIDR_IMPLEMENTER_ARM: + switch (productid) { + case IIDR_PRODUCTID_ARM_MMU_600: + /* Arm erratum 1076982 */ + if (variant == 0 && revision <= 2) + smmu->features &= ~ARM_SMMU_FEAT_SEV; + /* Arm erratum 1209401 */ + if (variant < 2) + smmu->features &= ~ARM_SMMU_FEAT_NESTING; + break; + case IIDR_PRODUCTID_ARM_MMU_700: + /* Arm erratum 2812531 */ + smmu->features &= ~ARM_SMMU_FEAT_BTM; + smmu->options |= ARM_SMMU_OPT_CMDQ_FORCE_SYNC; + /* Arm errata 2268618, 2812531 */ + smmu->features &= ~ARM_SMMU_FEAT_NESTING; + break; + } + break; + } +} + static int arm_smmu_device_hw_probe(struct arm_smmu_device *smmu) { u32 reg; @@ -3635,6 +3684,12 @@ static int arm_smmu_device_hw_probe(struct arm_smmu_device *smmu) smmu->ias = max(smmu->ias, smmu->oas); + if ((smmu->features & ARM_SMMU_FEAT_TRANS_S1) && + (smmu->features & ARM_SMMU_FEAT_TRANS_S2)) + smmu->features |= ARM_SMMU_FEAT_NESTING; + + arm_smmu_device_iidr_probe(smmu); + if (arm_smmu_sva_supported(smmu)) smmu->features |= ARM_SMMU_FEAT_SVA; diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h index b574c58a3487674147c1f547339e8a1142b78abf..dcab85698a4e257ae0ab07534727769797e1e0c3 100644 --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h @@ -69,6 +69,12 @@ #define IDR5_VAX GENMASK(11, 10) #define IDR5_VAX_52_BIT 1 +#define ARM_SMMU_IIDR 0x18 +#define IIDR_PRODUCTID GENMASK(31, 20) +#define IIDR_VARIANT GENMASK(19, 16) +#define IIDR_REVISION GENMASK(15, 12) +#define IIDR_IMPLEMENTER GENMASK(11, 0) + #define ARM_SMMU_CR0 0x20 #define CR0_ATSCHK (1 << 4) #define CR0_CMDQEN (1 << 3) @@ -639,11 +645,13 @@ struct arm_smmu_device { #define ARM_SMMU_FEAT_BTM (1 << 16) #define ARM_SMMU_FEAT_SVA (1 << 17) #define ARM_SMMU_FEAT_E2H (1 << 18) +#define ARM_SMMU_FEAT_NESTING (1 << 19) u32 features; #define ARM_SMMU_OPT_SKIP_PREFETCH (1 << 0) #define ARM_SMMU_OPT_PAGE0_REGS_ONLY (1 << 1) #define ARM_SMMU_OPT_MSIPOLL (1 << 2) +#define ARM_SMMU_OPT_CMDQ_FORCE_SYNC (1 << 3) u32 options; struct arm_smmu_cmdq cmdq; diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.c b/drivers/iommu/arm/arm-smmu/arm-smmu.c index 6e0813b26fb6980234be6632ed99210203d08a12..a86acd76c1dfb43b3475a11d632011feedadfac4 100644 --- a/drivers/iommu/arm/arm-smmu/arm-smmu.c +++ b/drivers/iommu/arm/arm-smmu/arm-smmu.c @@ -856,8 +856,7 @@ static struct iommu_domain *arm_smmu_domain_alloc(unsigned type) struct arm_smmu_domain *smmu_domain; if (type != IOMMU_DOMAIN_UNMANAGED && type != IOMMU_DOMAIN_IDENTITY) { - if (using_legacy_binding || - (type != IOMMU_DOMAIN_DMA && type != IOMMU_DOMAIN_DMA_FQ)) + if (using_legacy_binding || type != IOMMU_DOMAIN_DMA) return NULL; } /* @@ -1325,6 +1324,7 @@ static bool arm_smmu_capable(struct device *dev, enum iommu_cap cap) return cfg->smmu->features & ARM_SMMU_FEAT_COHERENT_WALK || device_get_dma_attr(dev) == DEV_DMA_COHERENT; case IOMMU_CAP_NOEXEC: + case IOMMU_CAP_DEFERRED_FLUSH: return true; default: return false; diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c index 7a9f0b0bddbda6175ed11ec92edf4eded7877872..e577241638350c2e7fd0f4b3eefedc631a4aeace 100644 --- a/drivers/iommu/dma-iommu.c +++ b/drivers/iommu/dma-iommu.c @@ -520,9 +520,38 @@ static bool dev_is_untrusted(struct device *dev) return dev_is_pci(dev) && to_pci_dev(dev)->untrusted; } -static bool dev_use_swiotlb(struct device *dev) +static bool dev_use_swiotlb(struct device *dev, size_t size, + enum dma_data_direction dir) { - return IS_ENABLED(CONFIG_SWIOTLB) && dev_is_untrusted(dev); + return IS_ENABLED(CONFIG_SWIOTLB) && + (dev_is_untrusted(dev) || + dma_kmalloc_needs_bounce(dev, size, dir)); +} + +static bool dev_use_sg_swiotlb(struct device *dev, struct scatterlist *sg, + int nents, enum dma_data_direction dir) +{ + struct scatterlist *s; + int i; + + if (!IS_ENABLED(CONFIG_SWIOTLB)) + return false; + + if (dev_is_untrusted(dev)) + return true; + + /* + * If kmalloc() buffers are not DMA-safe for this device and + * direction, check the individual lengths in the sg list. If any + * element is deemed unsafe, use the swiotlb for bouncing. + */ + if (!dma_kmalloc_safe(dev, dir)) { + for_each_sg(sg, s, nents, i) + if (!dma_kmalloc_size_aligned(s->length)) + return true; + } + + return false; } /** @@ -586,7 +615,8 @@ static int iommu_dma_init_domain(struct iommu_domain *domain, dma_addr_t base, goto done_unlock; /* If the FQ fails we can simply fall back to strict mode */ - if (domain->type == IOMMU_DOMAIN_DMA_FQ && iommu_dma_init_fq(domain)) + if (domain->type == IOMMU_DOMAIN_DMA_FQ && + (!device_iommu_capable(dev, IOMMU_CAP_DEFERRED_FLUSH) || iommu_dma_init_fq(domain))) domain->type = IOMMU_DOMAIN_DMA; ret = iova_reserve_iommu_regions(dev, domain); @@ -922,7 +952,7 @@ static void iommu_dma_sync_single_for_cpu(struct device *dev, { phys_addr_t phys; - if (dev_is_dma_coherent(dev) && !dev_use_swiotlb(dev)) + if (dev_is_dma_coherent(dev) && !dev_use_swiotlb(dev, size, dir)) return; phys = iommu_iova_to_phys(iommu_get_dma_domain(dev), dma_handle); @@ -938,7 +968,7 @@ static void iommu_dma_sync_single_for_device(struct device *dev, { phys_addr_t phys; - if (dev_is_dma_coherent(dev) && !dev_use_swiotlb(dev)) + if (dev_is_dma_coherent(dev) && !dev_use_swiotlb(dev, size, dir)) return; phys = iommu_iova_to_phys(iommu_get_dma_domain(dev), dma_handle); @@ -956,7 +986,7 @@ static void iommu_dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg; int i; - if (dev_use_swiotlb(dev)) + if (sg_dma_is_swiotlb(sgl)) for_each_sg(sgl, sg, nelems, i) iommu_dma_sync_single_for_cpu(dev, sg_dma_address(sg), sg->length, dir); @@ -972,7 +1002,7 @@ static void iommu_dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg; int i; - if (dev_use_swiotlb(dev)) + if (sg_dma_is_swiotlb(sgl)) for_each_sg(sgl, sg, nelems, i) iommu_dma_sync_single_for_device(dev, sg_dma_address(sg), @@ -998,7 +1028,8 @@ static dma_addr_t iommu_dma_map_page(struct device *dev, struct page *page, * If both the physical buffer start address and size are * page aligned, we don't need to use a bounce page. */ - if (dev_use_swiotlb(dev) && iova_offset(iovad, phys | size)) { + if (dev_use_swiotlb(dev, size, dir) && + iova_offset(iovad, phys | size)) { void *padding_start; size_t padding_size, aligned_size; @@ -1080,7 +1111,7 @@ static int __finalise_sg(struct device *dev, struct scatterlist *sg, int nents, sg_dma_address(s) = DMA_MAPPING_ERROR; sg_dma_len(s) = 0; - if (sg_is_dma_bus_address(s)) { + if (sg_dma_is_bus_address(s)) { if (i > 0) cur = sg_next(cur); @@ -1136,7 +1167,7 @@ static void __invalidate_sg(struct scatterlist *sg, int nents) int i; for_each_sg(sg, s, nents, i) { - if (sg_is_dma_bus_address(s)) { + if (sg_dma_is_bus_address(s)) { sg_dma_unmark_bus_address(s); } else { if (sg_dma_address(s) != DMA_MAPPING_ERROR) @@ -1166,6 +1197,8 @@ static int iommu_dma_map_sg_swiotlb(struct device *dev, struct scatterlist *sg, struct scatterlist *s; int i; + sg_dma_mark_swiotlb(sg); + for_each_sg(sg, s, nents, i) { sg_dma_address(s) = iommu_dma_map_page(dev, sg_page(s), s->offset, s->length, dir, attrs); @@ -1210,7 +1243,7 @@ static int iommu_dma_map_sg(struct device *dev, struct scatterlist *sg, goto out; } - if (dev_use_swiotlb(dev)) + if (dev_use_sg_swiotlb(dev, sg, nents, dir)) return iommu_dma_map_sg_swiotlb(dev, sg, nents, dir, attrs); if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC)) @@ -1315,7 +1348,7 @@ static void iommu_dma_unmap_sg(struct device *dev, struct scatterlist *sg, struct scatterlist *tmp; int i; - if (dev_use_swiotlb(dev)) { + if (sg_dma_is_swiotlb(sg)) { iommu_dma_unmap_sg_swiotlb(dev, sg, nents, dir, attrs); return; } @@ -1329,7 +1362,7 @@ static void iommu_dma_unmap_sg(struct device *dev, struct scatterlist *sg, * just have to be determined. */ for_each_sg(sg, tmp, nents, i) { - if (sg_is_dma_bus_address(tmp)) { + if (sg_dma_is_bus_address(tmp)) { sg_dma_unmark_bus_address(tmp); continue; } @@ -1343,7 +1376,7 @@ static void iommu_dma_unmap_sg(struct device *dev, struct scatterlist *sg, nents -= i; for_each_sg(tmp, tmp, nents, i) { - if (sg_is_dma_bus_address(tmp)) { + if (sg_dma_is_bus_address(tmp)) { sg_dma_unmark_bus_address(tmp); continue; } diff --git a/drivers/iommu/fsl_pamu_domain.c b/drivers/iommu/fsl_pamu_domain.c index bce3722970996550f426bd173c6fab7fd27fe9bb..4ac0e247ec2b51777b2b30d73e8d17fb2c401054 100644 --- a/drivers/iommu/fsl_pamu_domain.c +++ b/drivers/iommu/fsl_pamu_domain.c @@ -334,17 +334,6 @@ int fsl_pamu_configure_l1_stash(struct iommu_domain *domain, u32 cpu) return ret; } -static struct iommu_group *get_device_iommu_group(struct device *dev) -{ - struct iommu_group *group; - - group = iommu_group_get(dev); - if (!group) - group = iommu_group_alloc(); - - return group; -} - static bool check_pci_ctl_endpt_part(struct pci_controller *pci_ctl) { u32 version; @@ -356,94 +345,52 @@ static bool check_pci_ctl_endpt_part(struct pci_controller *pci_ctl) return version >= 0x204; } -/* Get iommu group information from peer devices or devices on the parent bus */ -static struct iommu_group *get_shared_pci_device_group(struct pci_dev *pdev) +static struct iommu_group *fsl_pamu_device_group(struct device *dev) { - struct pci_dev *tmp; struct iommu_group *group; - struct pci_bus *bus = pdev->bus; + struct pci_dev *pdev; /* - * Traverese the pci bus device list to get - * the shared iommu group. + * For platform devices we allocate a separate group for each of the + * devices. */ - while (bus) { - list_for_each_entry(tmp, &bus->devices, bus_list) { - if (tmp == pdev) - continue; - group = iommu_group_get(&tmp->dev); - if (group) - return group; - } + if (!dev_is_pci(dev)) + return generic_device_group(dev); - bus = bus->parent; - } - - return NULL; -} - -static struct iommu_group *get_pci_device_group(struct pci_dev *pdev) -{ - struct pci_controller *pci_ctl; - bool pci_endpt_partitioning; - struct iommu_group *group = NULL; - - pci_ctl = pci_bus_to_host(pdev->bus); - pci_endpt_partitioning = check_pci_ctl_endpt_part(pci_ctl); - /* We can partition PCIe devices so assign device group to the device */ - if (pci_endpt_partitioning) { - group = pci_device_group(&pdev->dev); - - /* - * PCIe controller is not a paritionable entity - * free the controller device iommu_group. - */ - if (pci_ctl->parent->iommu_group) - iommu_group_remove_device(pci_ctl->parent); - } else { - /* - * All devices connected to the controller will share the - * PCI controllers device group. If this is the first - * device to be probed for the pci controller, copy the - * device group information from the PCI controller device - * node and remove the PCI controller iommu group. - * For subsequent devices, the iommu group information can - * be obtained from sibling devices (i.e. from the bus_devices - * link list). - */ - if (pci_ctl->parent->iommu_group) { - group = get_device_iommu_group(pci_ctl->parent); - iommu_group_remove_device(pci_ctl->parent); - } else { - group = get_shared_pci_device_group(pdev); - } - } - - if (!group) - group = ERR_PTR(-ENODEV); + /* + * We can partition PCIe devices so assign device group to the device + */ + pdev = to_pci_dev(dev); + if (check_pci_ctl_endpt_part(pci_bus_to_host(pdev->bus))) + return pci_device_group(&pdev->dev); + /* + * All devices connected to the controller will share the same device + * group. + * + * Due to ordering between fsl_pamu_init() and fsl_pci_init() it is + * guaranteed that the pci_ctl->parent platform_device will have the + * iommu driver bound and will already have a group set. So we just + * re-use this group as the group for every device in the hose. + */ + group = iommu_group_get(pci_bus_to_host(pdev->bus)->parent); + if (WARN_ON(!group)) + return ERR_PTR(-EINVAL); return group; } -static struct iommu_group *fsl_pamu_device_group(struct device *dev) +static struct iommu_device *fsl_pamu_probe_device(struct device *dev) { - struct iommu_group *group = ERR_PTR(-ENODEV); int len; /* - * For platform devices we allocate a separate group for - * each of the devices. + * uboot must fill the fsl,liodn for platform devices to be supported by + * the iommu. */ - if (dev_is_pci(dev)) - group = get_pci_device_group(to_pci_dev(dev)); - else if (of_get_property(dev->of_node, "fsl,liodn", &len)) - group = get_device_iommu_group(dev); - - return group; -} + if (!dev_is_pci(dev) && + !of_get_property(dev->of_node, "fsl,liodn", &len)) + return ERR_PTR(-ENODEV); -static struct iommu_device *fsl_pamu_probe_device(struct device *dev) -{ return &pamu_iommu; } diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c index b871a6afd803211a419b63b2c19b628df70fa24c..5c8c5cdc36cf565a74d49fc94724639414dc279d 100644 --- a/drivers/iommu/intel/iommu.c +++ b/drivers/iommu/intel/iommu.c @@ -1185,7 +1185,7 @@ static int iommu_alloc_root_entry(struct intel_iommu *iommu) { struct root_entry *root; - root = (struct root_entry *)alloc_pgtable_page(iommu->node, GFP_ATOMIC); + root = alloc_pgtable_page(iommu->node, GFP_ATOMIC); if (!root) { pr_err("Allocating root entry for %s failed\n", iommu->name); @@ -1312,15 +1312,7 @@ static void __iommu_flush_iotlb(struct intel_iommu *iommu, u16 did, iommu->name, type); return; } - /* Note: set drain read/write */ -#if 0 - /* - * This is probably to be super secure.. Looks like we can - * ignore it without any impact. - */ - if (cap_read_drain(iommu->cap)) - val |= DMA_TLB_READ_DRAIN; -#endif + if (cap_write_drain(iommu->cap)) val |= DMA_TLB_WRITE_DRAIN; @@ -1897,8 +1889,6 @@ static int domain_context_mapping_one(struct dmar_domain *domain, struct context_entry *context; int ret; - WARN_ON(did == 0); - if (hw_pass_through && domain_type_is_si(domain)) translation = CONTEXT_TT_PASS_THROUGH; @@ -1944,8 +1934,6 @@ static int domain_context_mapping_one(struct dmar_domain *domain, if (sm_supported(iommu)) { unsigned long pds; - WARN_ON(!table); - /* Setup the PASID DIR pointer: */ pds = context_get_sm_pds(table); context->lo = (u64)virt_to_phys(table->table) | @@ -2967,10 +2955,15 @@ static int init_iommu_hw(void) { struct dmar_drhd_unit *drhd; struct intel_iommu *iommu = NULL; + int ret; - for_each_active_iommu(iommu, drhd) - if (iommu->qi) - dmar_reenable_qi(iommu); + for_each_active_iommu(iommu, drhd) { + if (iommu->qi) { + ret = dmar_reenable_qi(iommu); + if (ret) + return ret; + } + } for_each_iommu(iommu, drhd) { if (drhd->ignored) { @@ -4064,7 +4057,6 @@ static struct iommu_domain *intel_iommu_domain_alloc(unsigned type) case IOMMU_DOMAIN_BLOCKED: return &blocking_domain; case IOMMU_DOMAIN_DMA: - case IOMMU_DOMAIN_DMA_FQ: case IOMMU_DOMAIN_UNMANAGED: dmar_domain = alloc_domain(type); if (!dmar_domain) { @@ -4369,6 +4361,7 @@ static bool intel_iommu_capable(struct device *dev, enum iommu_cap cap) switch (cap) { case IOMMU_CAP_CACHE_COHERENCY: + case IOMMU_CAP_DEFERRED_FLUSH: return true; case IOMMU_CAP_PRE_BOOT_PROTECTION: return dmar_platform_optin(); diff --git a/drivers/iommu/intel/irq_remapping.c b/drivers/iommu/intel/irq_remapping.c index a1b987335b31a308149efa6f95936b9ffc39c247..08f56326e2f84814e1d7cf22dc99b6885c0da544 100644 --- a/drivers/iommu/intel/irq_remapping.c +++ b/drivers/iommu/intel/irq_remapping.c @@ -175,18 +175,14 @@ static int modify_irte(struct irq_2_iommu *irq_iommu, irte = &iommu->ir_table->base[index]; if ((irte->pst == 1) || (irte_modified->pst == 1)) { - bool ret; - - ret = cmpxchg_double(&irte->low, &irte->high, - irte->low, irte->high, - irte_modified->low, irte_modified->high); /* * We use cmpxchg16 to atomically update the 128-bit IRTE, * and it cannot be updated by the hardware or other processors * behind us, so the return value of cmpxchg16 should be the * same as the old value. */ - WARN_ON(!ret); + u128 old = irte->irte; + WARN_ON(!try_cmpxchg128(&irte->irte, &old, irte_modified->irte)); } else { WRITE_ONCE(irte->low, irte_modified->low); WRITE_ONCE(irte->high, irte_modified->high); diff --git a/drivers/iommu/iommu-sva.c b/drivers/iommu/iommu-sva.c index 9821bc44f5ac1d4d5e85175f57963081734464fe..05c0fb2acbc447f94ed3209adbdc893d1b334583 100644 --- a/drivers/iommu/iommu-sva.c +++ b/drivers/iommu/iommu-sva.c @@ -34,8 +34,9 @@ static int iommu_sva_alloc_pasid(struct mm_struct *mm, ioasid_t min, ioasid_t ma } ret = ida_alloc_range(&iommu_global_pasid_ida, min, max, GFP_KERNEL); - if (ret < min) + if (ret < 0) goto out; + mm->pasid = ret; ret = 0; out: @@ -175,7 +176,7 @@ iommu_sva_handle_iopf(struct iommu_fault *fault, void *data) mmap_read_lock(mm); - vma = find_extend_vma(mm, prm->addr); + vma = vma_lookup(mm, prm->addr); if (!vma) /* Unmapped area */ goto out_put_mm; diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index f1dcfa3f1a1b48ab8a48bb6976f524e3dc4c29e0..caaf563d38ae090246c602a0b982fbe4d5a9ccf1 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -68,6 +68,10 @@ struct group_device { char *name; }; +/* Iterate over each struct group_device in a struct iommu_group */ +#define for_each_group_device(group, pos) \ + list_for_each_entry(pos, &(group)->devices, list) + struct iommu_group_attribute { struct attribute attr; ssize_t (*show)(struct iommu_group *group, char *buf); @@ -89,17 +93,39 @@ static const char * const iommu_group_resv_type_string[] = { static int iommu_bus_notifier(struct notifier_block *nb, unsigned long action, void *data); static void iommu_release_device(struct device *dev); -static int iommu_alloc_default_domain(struct iommu_group *group, - struct device *dev); static struct iommu_domain *__iommu_domain_alloc(const struct bus_type *bus, unsigned type); static int __iommu_attach_device(struct iommu_domain *domain, struct device *dev); static int __iommu_attach_group(struct iommu_domain *domain, struct iommu_group *group); + +enum { + IOMMU_SET_DOMAIN_MUST_SUCCEED = 1 << 0, +}; + +static int __iommu_device_set_domain(struct iommu_group *group, + struct device *dev, + struct iommu_domain *new_domain, + unsigned int flags); +static int __iommu_group_set_domain_internal(struct iommu_group *group, + struct iommu_domain *new_domain, + unsigned int flags); static int __iommu_group_set_domain(struct iommu_group *group, - struct iommu_domain *new_domain); -static int iommu_create_device_direct_mappings(struct iommu_group *group, + struct iommu_domain *new_domain) +{ + return __iommu_group_set_domain_internal(group, new_domain, 0); +} +static void __iommu_group_set_domain_nofail(struct iommu_group *group, + struct iommu_domain *new_domain) +{ + WARN_ON(__iommu_group_set_domain_internal( + group, new_domain, IOMMU_SET_DOMAIN_MUST_SUCCEED)); +} + +static int iommu_setup_default_domain(struct iommu_group *group, + int target_type); +static int iommu_create_device_direct_mappings(struct iommu_domain *domain, struct device *dev); static struct iommu_group *iommu_group_get_for_dev(struct device *dev); static ssize_t iommu_group_store_type(struct iommu_group *group, @@ -176,16 +202,16 @@ static int __init iommu_subsys_init(void) if (!iommu_default_passthrough() && !iommu_dma_strict) iommu_def_domain_type = IOMMU_DOMAIN_DMA_FQ; - pr_info("Default domain type: %s %s\n", + pr_info("Default domain type: %s%s\n", iommu_domain_type_str(iommu_def_domain_type), (iommu_cmd_line & IOMMU_CMD_LINE_DMA_API) ? - "(set via kernel command line)" : ""); + " (set via kernel command line)" : ""); if (!iommu_default_passthrough()) - pr_info("DMA domain TLB invalidation policy: %s mode %s\n", + pr_info("DMA domain TLB invalidation policy: %s mode%s\n", iommu_dma_strict ? "strict" : "lazy", (iommu_cmd_line & IOMMU_CMD_LINE_STRICT) ? - "(set via kernel command line)" : ""); + " (set via kernel command line)" : ""); nb = kcalloc(ARRAY_SIZE(iommu_buses), sizeof(*nb), GFP_KERNEL); if (!nb) @@ -343,6 +369,8 @@ static int __iommu_probe_device(struct device *dev, struct list_head *group_list dev->iommu->iommu_dev = iommu_dev; dev->iommu->max_pasids = dev_iommu_get_max_pasids(dev); + if (ops->is_attach_deferred) + dev->iommu->attach_deferred = ops->is_attach_deferred(dev); group = iommu_group_get_for_dev(dev); if (IS_ERR(group)) { @@ -377,30 +405,6 @@ static int __iommu_probe_device(struct device *dev, struct list_head *group_list return ret; } -static bool iommu_is_attach_deferred(struct device *dev) -{ - const struct iommu_ops *ops = dev_iommu_ops(dev); - - if (ops->is_attach_deferred) - return ops->is_attach_deferred(dev); - - return false; -} - -static int iommu_group_do_dma_first_attach(struct device *dev, void *data) -{ - struct iommu_domain *domain = data; - - lockdep_assert_held(&dev->iommu_group->mutex); - - if (iommu_is_attach_deferred(dev)) { - dev->iommu->attach_deferred = 1; - return 0; - } - - return __iommu_attach_device(domain, dev); -} - int iommu_probe_device(struct device *dev) { const struct iommu_ops *ops; @@ -417,29 +421,20 @@ int iommu_probe_device(struct device *dev) goto err_release; } - /* - * Try to allocate a default domain - needs support from the - * IOMMU driver. There are still some drivers which don't - * support default domains, so the return value is not yet - * checked. - */ mutex_lock(&group->mutex); - iommu_alloc_default_domain(group, dev); - /* - * If device joined an existing group which has been claimed, don't - * attach the default domain. - */ - if (group->default_domain && !group->owner) { - ret = iommu_group_do_dma_first_attach(dev, group->default_domain); - if (ret) { - mutex_unlock(&group->mutex); - iommu_group_put(group); - goto err_release; - } - } + if (group->default_domain) + iommu_create_device_direct_mappings(group->default_domain, dev); - iommu_create_device_direct_mappings(group, dev); + if (group->domain) { + ret = __iommu_device_set_domain(group, dev, group->domain, 0); + if (ret) + goto err_unlock; + } else if (!group->default_domain) { + ret = iommu_setup_default_domain(group, 0); + if (ret) + goto err_unlock; + } mutex_unlock(&group->mutex); iommu_group_put(group); @@ -450,6 +445,9 @@ int iommu_probe_device(struct device *dev) return 0; +err_unlock: + mutex_unlock(&group->mutex); + iommu_group_put(group); err_release: iommu_release_device(dev); @@ -468,7 +466,7 @@ __iommu_group_remove_device(struct iommu_group *group, struct device *dev) struct group_device *device; lockdep_assert_held(&group->mutex); - list_for_each_entry(device, &group->devices, list) { + for_each_group_device(group, device) { if (device->dev == dev) { list_del(&device->list); return device; @@ -707,7 +705,7 @@ int iommu_get_group_resv_regions(struct iommu_group *group, int ret = 0; mutex_lock(&group->mutex); - list_for_each_entry(device, &group->devices, list) { + for_each_group_device(group, device) { struct list_head dev_resv_regions; /* @@ -953,16 +951,15 @@ int iommu_group_set_name(struct iommu_group *group, const char *name) } EXPORT_SYMBOL_GPL(iommu_group_set_name); -static int iommu_create_device_direct_mappings(struct iommu_group *group, +static int iommu_create_device_direct_mappings(struct iommu_domain *domain, struct device *dev) { - struct iommu_domain *domain = group->default_domain; struct iommu_resv_region *entry; struct list_head mappings; unsigned long pg_size; int ret = 0; - if (!domain || !iommu_is_dma_domain(domain)) + if (!iommu_is_dma_domain(domain)) return 0; BUG_ON(!domain->pgsize_bitmap); @@ -1069,25 +1066,13 @@ int iommu_group_add_device(struct iommu_group *group, struct device *dev) mutex_lock(&group->mutex); list_add_tail(&device->list, &group->devices); - if (group->domain) - ret = iommu_group_do_dma_first_attach(dev, group->domain); mutex_unlock(&group->mutex); - if (ret) - goto err_put_group; - trace_add_device_to_group(group->id, dev); dev_info(dev, "Adding to iommu group %d\n", group->id); return 0; -err_put_group: - mutex_lock(&group->mutex); - list_del(&device->list); - mutex_unlock(&group->mutex); - dev->iommu_group = NULL; - kobject_put(group->devices_kobj); - sysfs_remove_link(group->devices_kobj, device->name); err_free_name: kfree(device->name); err_remove_link: @@ -1125,31 +1110,6 @@ void iommu_group_remove_device(struct device *dev) } EXPORT_SYMBOL_GPL(iommu_group_remove_device); -static int iommu_group_device_count(struct iommu_group *group) -{ - struct group_device *entry; - int ret = 0; - - list_for_each_entry(entry, &group->devices, list) - ret++; - - return ret; -} - -static int __iommu_group_for_each_dev(struct iommu_group *group, void *data, - int (*fn)(struct device *, void *)) -{ - struct group_device *device; - int ret = 0; - - list_for_each_entry(device, &group->devices, list) { - ret = fn(device->dev, data); - if (ret) - break; - } - return ret; -} - /** * iommu_group_for_each_dev - iterate over each device in the group * @group: the group @@ -1164,10 +1124,15 @@ static int __iommu_group_for_each_dev(struct iommu_group *group, void *data, int iommu_group_for_each_dev(struct iommu_group *group, void *data, int (*fn)(struct device *, void *)) { - int ret; + struct group_device *device; + int ret = 0; mutex_lock(&group->mutex); - ret = __iommu_group_for_each_dev(group, data, fn); + for_each_group_device(group, device) { + ret = fn(device->dev, data); + if (ret) + break; + } mutex_unlock(&group->mutex); return ret; @@ -1656,40 +1621,47 @@ static int iommu_get_def_domain_type(struct device *dev) return 0; } -static int iommu_group_alloc_default_domain(const struct bus_type *bus, - struct iommu_group *group, - unsigned int type) +static struct iommu_domain * +__iommu_group_alloc_default_domain(const struct bus_type *bus, + struct iommu_group *group, int req_type) { - struct iommu_domain *dom; - - dom = __iommu_domain_alloc(bus, type); - if (!dom && type != IOMMU_DOMAIN_DMA) { - dom = __iommu_domain_alloc(bus, IOMMU_DOMAIN_DMA); - if (dom) - pr_warn("Failed to allocate default IOMMU domain of type %u for group %s - Falling back to IOMMU_DOMAIN_DMA", - type, group->name); - } - - if (!dom) - return -ENOMEM; - - group->default_domain = dom; - if (!group->domain) - group->domain = dom; - return 0; + if (group->default_domain && group->default_domain->type == req_type) + return group->default_domain; + return __iommu_domain_alloc(bus, req_type); } -static int iommu_alloc_default_domain(struct iommu_group *group, - struct device *dev) +/* + * req_type of 0 means "auto" which means to select a domain based on + * iommu_def_domain_type or what the driver actually supports. + */ +static struct iommu_domain * +iommu_group_alloc_default_domain(struct iommu_group *group, int req_type) { - unsigned int type; + const struct bus_type *bus = + list_first_entry(&group->devices, struct group_device, list) + ->dev->bus; + struct iommu_domain *dom; - if (group->default_domain) - return 0; + lockdep_assert_held(&group->mutex); + + if (req_type) + return __iommu_group_alloc_default_domain(bus, group, req_type); + + /* The driver gave no guidance on what type to use, try the default */ + dom = __iommu_group_alloc_default_domain(bus, group, iommu_def_domain_type); + if (dom) + return dom; - type = iommu_get_def_domain_type(dev) ? : iommu_def_domain_type; + /* Otherwise IDENTITY and DMA_FQ defaults will try DMA */ + if (iommu_def_domain_type == IOMMU_DOMAIN_DMA) + return NULL; + dom = __iommu_group_alloc_default_domain(bus, group, IOMMU_DOMAIN_DMA); + if (!dom) + return NULL; - return iommu_group_alloc_default_domain(dev->bus, group, type); + pr_warn("Failed to allocate default IOMMU domain of type %u for group %s - Falling back to IOMMU_DOMAIN_DMA", + iommu_def_domain_type, group->name); + return dom; } /** @@ -1774,87 +1746,48 @@ static int iommu_bus_notifier(struct notifier_block *nb, return 0; } -struct __group_domain_type { - struct device *dev; - unsigned int type; -}; - -static int probe_get_default_domain_type(struct device *dev, void *data) -{ - struct __group_domain_type *gtype = data; - unsigned int type = iommu_get_def_domain_type(dev); - - if (type) { - if (gtype->type && gtype->type != type) { - dev_warn(dev, "Device needs domain type %s, but device %s in the same iommu group requires type %s - using default\n", - iommu_domain_type_str(type), - dev_name(gtype->dev), - iommu_domain_type_str(gtype->type)); - gtype->type = 0; - } - - if (!gtype->dev) { - gtype->dev = dev; - gtype->type = type; - } - } - - return 0; -} - -static void probe_alloc_default_domain(const struct bus_type *bus, - struct iommu_group *group) +/* A target_type of 0 will select the best domain type and cannot fail */ +static int iommu_get_default_domain_type(struct iommu_group *group, + int target_type) { - struct __group_domain_type gtype; - - memset(>ype, 0, sizeof(gtype)); + int best_type = target_type; + struct group_device *gdev; + struct device *last_dev; - /* Ask for default domain requirements of all devices in the group */ - __iommu_group_for_each_dev(group, >ype, - probe_get_default_domain_type); - - if (!gtype.type) - gtype.type = iommu_def_domain_type; + lockdep_assert_held(&group->mutex); - iommu_group_alloc_default_domain(bus, group, gtype.type); + for_each_group_device(group, gdev) { + unsigned int type = iommu_get_def_domain_type(gdev->dev); -} + if (best_type && type && best_type != type) { + if (target_type) { + dev_err_ratelimited( + gdev->dev, + "Device cannot be in %s domain\n", + iommu_domain_type_str(target_type)); + return -1; + } -static int __iommu_group_dma_first_attach(struct iommu_group *group) -{ - return __iommu_group_for_each_dev(group, group->default_domain, - iommu_group_do_dma_first_attach); + dev_warn( + gdev->dev, + "Device needs domain type %s, but device %s in the same iommu group requires type %s - using default\n", + iommu_domain_type_str(type), dev_name(last_dev), + iommu_domain_type_str(best_type)); + return 0; + } + if (!best_type) + best_type = type; + last_dev = gdev->dev; + } + return best_type; } -static int iommu_group_do_probe_finalize(struct device *dev, void *data) +static void iommu_group_do_probe_finalize(struct device *dev) { const struct iommu_ops *ops = dev_iommu_ops(dev); if (ops->probe_finalize) ops->probe_finalize(dev); - - return 0; -} - -static void __iommu_group_dma_finalize(struct iommu_group *group) -{ - __iommu_group_for_each_dev(group, group->default_domain, - iommu_group_do_probe_finalize); -} - -static int iommu_do_create_direct_mappings(struct device *dev, void *data) -{ - struct iommu_group *group = data; - - iommu_create_device_direct_mappings(group, dev); - - return 0; -} - -static int iommu_group_create_direct_mappings(struct iommu_group *group) -{ - return __iommu_group_for_each_dev(group, group, - iommu_do_create_direct_mappings); } int bus_iommu_probe(const struct bus_type *bus) @@ -1873,32 +1806,31 @@ int bus_iommu_probe(const struct bus_type *bus) return ret; list_for_each_entry_safe(group, next, &group_list, entry) { + struct group_device *gdev; + mutex_lock(&group->mutex); /* Remove item from the list */ list_del_init(&group->entry); - /* Try to allocate default domain */ - probe_alloc_default_domain(bus, group); - - if (!group->default_domain) { + ret = iommu_setup_default_domain(group, 0); + if (ret) { mutex_unlock(&group->mutex); - continue; + return ret; } - - iommu_group_create_direct_mappings(group); - - ret = __iommu_group_dma_first_attach(group); - mutex_unlock(&group->mutex); - if (ret) - break; - - __iommu_group_dma_finalize(group); + /* + * FIXME: Mis-locked because the ops->probe_finalize() call-back + * of some IOMMU drivers calls arm_iommu_attach_device() which + * in-turn might call back into IOMMU core code, where it tries + * to take group->mutex, resulting in a deadlock. + */ + for_each_group_device(group, gdev) + iommu_group_do_probe_finalize(gdev->dev); } - return ret; + return 0; } bool iommu_present(const struct bus_type *bus) @@ -1946,7 +1878,7 @@ bool iommu_group_has_isolated_msi(struct iommu_group *group) bool ret = true; mutex_lock(&group->mutex); - list_for_each_entry(group_dev, &group->devices, list) + for_each_group_device(group, group_dev) ret &= msi_device_has_isolated_msi(group_dev->dev); mutex_unlock(&group->mutex); return ret; @@ -1980,11 +1912,12 @@ static struct iommu_domain *__iommu_domain_alloc(const struct bus_type *bus, unsigned type) { struct iommu_domain *domain; + unsigned int alloc_type = type & IOMMU_DOMAIN_ALLOC_FLAGS; if (bus == NULL || bus->iommu_ops == NULL) return NULL; - domain = bus->iommu_ops->domain_alloc(type); + domain = bus->iommu_ops->domain_alloc(alloc_type); if (!domain) return NULL; @@ -2028,15 +1961,13 @@ EXPORT_SYMBOL_GPL(iommu_domain_free); static void __iommu_group_set_core_domain(struct iommu_group *group) { struct iommu_domain *new_domain; - int ret; if (group->owner) new_domain = group->blocking_domain; else new_domain = group->default_domain; - ret = __iommu_group_set_domain(group, new_domain); - WARN(ret, "iommu driver failed to attach the default/blocking domain"); + __iommu_group_set_domain_nofail(group, new_domain); } static int __iommu_attach_device(struct iommu_domain *domain, @@ -2082,7 +2013,7 @@ int iommu_attach_device(struct iommu_domain *domain, struct device *dev) */ mutex_lock(&group->mutex); ret = -EINVAL; - if (iommu_group_device_count(group) != 1) + if (list_count_nodes(&group->devices) != 1) goto out_unlock; ret = __iommu_attach_group(domain, group); @@ -2113,7 +2044,7 @@ void iommu_detach_device(struct iommu_domain *domain, struct device *dev) mutex_lock(&group->mutex); if (WARN_ON(domain != group->domain) || - WARN_ON(iommu_group_device_count(group) != 1)) + WARN_ON(list_count_nodes(&group->devices) != 1)) goto out_unlock; __iommu_group_set_core_domain(group); @@ -2149,52 +2080,14 @@ struct iommu_domain *iommu_get_dma_domain(struct device *dev) return dev->iommu_group->default_domain; } -/* - * IOMMU groups are really the natural working unit of the IOMMU, but - * the IOMMU API works on domains and devices. Bridge that gap by - * iterating over the devices in a group. Ideally we'd have a single - * device which represents the requestor ID of the group, but we also - * allow IOMMU drivers to create policy defined minimum sets, where - * the physical hardware may be able to distiguish members, but we - * wish to group them at a higher level (ex. untrusted multi-function - * PCI devices). Thus we attach each device. - */ -static int iommu_group_do_attach_device(struct device *dev, void *data) -{ - struct iommu_domain *domain = data; - - return __iommu_attach_device(domain, dev); -} - static int __iommu_attach_group(struct iommu_domain *domain, struct iommu_group *group) { - int ret; - if (group->domain && group->domain != group->default_domain && group->domain != group->blocking_domain) return -EBUSY; - ret = __iommu_group_for_each_dev(group, domain, - iommu_group_do_attach_device); - if (ret == 0) { - group->domain = domain; - } else { - /* - * To recover from the case when certain device within the - * group fails to attach to the new domain, we need force - * attaching all devices back to the old domain. The old - * domain is compatible for all devices in the group, - * hence the iommu driver should always return success. - */ - struct iommu_domain *old_domain = group->domain; - - group->domain = NULL; - WARN(__iommu_group_set_domain(group, old_domain), - "iommu driver failed to attach a compatible domain"); - } - - return ret; + return __iommu_group_set_domain(group, domain); } /** @@ -2221,21 +2114,61 @@ int iommu_attach_group(struct iommu_domain *domain, struct iommu_group *group) } EXPORT_SYMBOL_GPL(iommu_attach_group); -static int iommu_group_do_set_platform_dma(struct device *dev, void *data) +static int __iommu_device_set_domain(struct iommu_group *group, + struct device *dev, + struct iommu_domain *new_domain, + unsigned int flags) { - const struct iommu_ops *ops = dev_iommu_ops(dev); + int ret; - if (!WARN_ON(!ops->set_platform_dma_ops)) - ops->set_platform_dma_ops(dev); + if (dev->iommu->attach_deferred) { + if (new_domain == group->default_domain) + return 0; + dev->iommu->attach_deferred = 0; + } + ret = __iommu_attach_device(new_domain, dev); + if (ret) { + /* + * If we have a blocking domain then try to attach that in hopes + * of avoiding a UAF. Modern drivers should implement blocking + * domains as global statics that cannot fail. + */ + if ((flags & IOMMU_SET_DOMAIN_MUST_SUCCEED) && + group->blocking_domain && + group->blocking_domain != new_domain) + __iommu_attach_device(group->blocking_domain, dev); + return ret; + } return 0; } -static int __iommu_group_set_domain(struct iommu_group *group, - struct iommu_domain *new_domain) +/* + * If 0 is returned the group's domain is new_domain. If an error is returned + * then the group's domain will be set back to the existing domain unless + * IOMMU_SET_DOMAIN_MUST_SUCCEED, otherwise an error is returned and the group's + * domains is left inconsistent. This is a driver bug to fail attach with a + * previously good domain. We try to avoid a kernel UAF because of this. + * + * IOMMU groups are really the natural working unit of the IOMMU, but the IOMMU + * API works on domains and devices. Bridge that gap by iterating over the + * devices in a group. Ideally we'd have a single device which represents the + * requestor ID of the group, but we also allow IOMMU drivers to create policy + * defined minimum sets, where the physical hardware may be able to distiguish + * members, but we wish to group them at a higher level (ex. untrusted + * multi-function PCI devices). Thus we attach each device. + */ +static int __iommu_group_set_domain_internal(struct iommu_group *group, + struct iommu_domain *new_domain, + unsigned int flags) { + struct group_device *last_gdev; + struct group_device *gdev; + int result; int ret; + lockdep_assert_held(&group->mutex); + if (group->domain == new_domain) return 0; @@ -2245,8 +2178,12 @@ static int __iommu_group_set_domain(struct iommu_group *group, * platform specific behavior. */ if (!new_domain) { - __iommu_group_for_each_dev(group, NULL, - iommu_group_do_set_platform_dma); + for_each_group_device(group, gdev) { + const struct iommu_ops *ops = dev_iommu_ops(gdev->dev); + + if (!WARN_ON(!ops->set_platform_dma_ops)) + ops->set_platform_dma_ops(gdev->dev); + } group->domain = NULL; return 0; } @@ -2256,16 +2193,52 @@ static int __iommu_group_set_domain(struct iommu_group *group, * domain. This switch does not have to be atomic and DMA can be * discarded during the transition. DMA must only be able to access * either new_domain or group->domain, never something else. - * - * Note that this is called in error unwind paths, attaching to a - * domain that has already been attached cannot fail. */ - ret = __iommu_group_for_each_dev(group, new_domain, - iommu_group_do_attach_device); - if (ret) - return ret; + result = 0; + for_each_group_device(group, gdev) { + ret = __iommu_device_set_domain(group, gdev->dev, new_domain, + flags); + if (ret) { + result = ret; + /* + * Keep trying the other devices in the group. If a + * driver fails attach to an otherwise good domain, and + * does not support blocking domains, it should at least + * drop its reference on the current domain so we don't + * UAF. + */ + if (flags & IOMMU_SET_DOMAIN_MUST_SUCCEED) + continue; + goto err_revert; + } + } group->domain = new_domain; - return 0; + return result; + +err_revert: + /* + * This is called in error unwind paths. A well behaved driver should + * always allow us to attach to a domain that was already attached. + */ + last_gdev = gdev; + for_each_group_device(group, gdev) { + const struct iommu_ops *ops = dev_iommu_ops(gdev->dev); + + /* + * If set_platform_dma_ops is not present a NULL domain can + * happen only for first probe, in which case we leave + * group->domain as NULL and let release clean everything up. + */ + if (group->domain) + WARN_ON(__iommu_device_set_domain( + group, gdev->dev, group->domain, + IOMMU_SET_DOMAIN_MUST_SUCCEED)); + else if (ops->set_platform_dma_ops) + ops->set_platform_dma_ops(gdev->dev); + if (gdev == last_gdev) + break; + } + return ret; } void iommu_detach_group(struct iommu_domain *domain, struct iommu_group *group) @@ -2567,7 +2540,7 @@ ssize_t iommu_map_sg(struct iommu_domain *domain, unsigned long iova, len = 0; } - if (sg_is_dma_bus_address(sg)) + if (sg_dma_is_bus_address(sg)) goto next; if (len) { @@ -2846,78 +2819,113 @@ int iommu_dev_disable_feature(struct device *dev, enum iommu_dev_features feat) } EXPORT_SYMBOL_GPL(iommu_dev_disable_feature); -/* - * Changes the default domain of an iommu group - * - * @group: The group for which the default domain should be changed - * @dev: The first device in the group - * @type: The type of the new default domain that gets associated with the group - * - * Returns 0 on success and error code on failure +/** + * iommu_setup_default_domain - Set the default_domain for the group + * @group: Group to change + * @target_type: Domain type to set as the default_domain * - * Note: - * 1. Presently, this function is called only when user requests to change the - * group's default domain type through /sys/kernel/iommu_groups//type - * Please take a closer look if intended to use for other purposes. + * Allocate a default domain and set it as the current domain on the group. If + * the group already has a default domain it will be changed to the target_type. + * When target_type is 0 the default domain is selected based on driver and + * system preferences. */ -static int iommu_change_dev_def_domain(struct iommu_group *group, - struct device *dev, int type) +static int iommu_setup_default_domain(struct iommu_group *group, + int target_type) { - struct __group_domain_type gtype = {NULL, 0}; - struct iommu_domain *prev_dom; + struct iommu_domain *old_dom = group->default_domain; + struct group_device *gdev; + struct iommu_domain *dom; + bool direct_failed; + int req_type; int ret; lockdep_assert_held(&group->mutex); - prev_dom = group->default_domain; - __iommu_group_for_each_dev(group, >ype, - probe_get_default_domain_type); - if (!type) { - /* - * If the user hasn't requested any specific type of domain and - * if the device supports both the domains, then default to the - * domain the device was booted with - */ - type = gtype.type ? : iommu_def_domain_type; - } else if (gtype.type && type != gtype.type) { - dev_err_ratelimited(dev, "Device cannot be in %s domain\n", - iommu_domain_type_str(type)); + req_type = iommu_get_default_domain_type(group, target_type); + if (req_type < 0) return -EINVAL; - } /* - * Switch to a new domain only if the requested domain type is different - * from the existing default domain type + * There are still some drivers which don't support default domains, so + * we ignore the failure and leave group->default_domain NULL. + * + * We assume that the iommu driver starts up the device in + * 'set_platform_dma_ops' mode if it does not support default domains. */ - if (prev_dom->type == type) + dom = iommu_group_alloc_default_domain(group, req_type); + if (!dom) { + /* Once in default_domain mode we never leave */ + if (group->default_domain) + return -ENODEV; + group->default_domain = NULL; return 0; + } - group->default_domain = NULL; - group->domain = NULL; - - /* Sets group->default_domain to the newly allocated domain */ - ret = iommu_group_alloc_default_domain(dev->bus, group, type); - if (ret) - goto restore_old_domain; - - ret = iommu_group_create_direct_mappings(group); - if (ret) - goto free_new_domain; + if (group->default_domain == dom) + return 0; - ret = __iommu_attach_group(group->default_domain, group); - if (ret) - goto free_new_domain; + /* + * IOMMU_RESV_DIRECT and IOMMU_RESV_DIRECT_RELAXABLE regions must be + * mapped before their device is attached, in order to guarantee + * continuity with any FW activity + */ + direct_failed = false; + for_each_group_device(group, gdev) { + if (iommu_create_device_direct_mappings(dom, gdev->dev)) { + direct_failed = true; + dev_warn_once( + gdev->dev->iommu->iommu_dev->dev, + "IOMMU driver was not able to establish FW requested direct mapping."); + } + } - iommu_domain_free(prev_dom); + /* We must set default_domain early for __iommu_device_set_domain */ + group->default_domain = dom; + if (!group->domain) { + /* + * Drivers are not allowed to fail the first domain attach. + * The only way to recover from this is to fail attaching the + * iommu driver and call ops->release_device. Put the domain + * in group->default_domain so it is freed after. + */ + ret = __iommu_group_set_domain_internal( + group, dom, IOMMU_SET_DOMAIN_MUST_SUCCEED); + if (WARN_ON(ret)) + goto out_free_old; + } else { + ret = __iommu_group_set_domain(group, dom); + if (ret) + goto err_restore_def_domain; + } - return 0; + /* + * Drivers are supposed to allow mappings to be installed in a domain + * before device attachment, but some don't. Hack around this defect by + * trying again after attaching. If this happens it means the device + * will not continuously have the IOMMU_RESV_DIRECT map. + */ + if (direct_failed) { + for_each_group_device(group, gdev) { + ret = iommu_create_device_direct_mappings(dom, gdev->dev); + if (ret) + goto err_restore_domain; + } + } -free_new_domain: - iommu_domain_free(group->default_domain); -restore_old_domain: - group->default_domain = prev_dom; - group->domain = prev_dom; +out_free_old: + if (old_dom) + iommu_domain_free(old_dom); + return ret; +err_restore_domain: + if (old_dom) + __iommu_group_set_domain_internal( + group, old_dom, IOMMU_SET_DOMAIN_MUST_SUCCEED); +err_restore_def_domain: + if (old_dom) { + iommu_domain_free(dom); + group->default_domain = old_dom; + } return ret; } @@ -2933,8 +2941,7 @@ static int iommu_change_dev_def_domain(struct iommu_group *group, static ssize_t iommu_group_store_type(struct iommu_group *group, const char *buf, size_t count) { - struct group_device *grp_dev; - struct device *dev; + struct group_device *gdev; int ret, req_type; if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO)) @@ -2959,23 +2966,23 @@ static ssize_t iommu_group_store_type(struct iommu_group *group, if (req_type == IOMMU_DOMAIN_DMA_FQ && group->default_domain->type == IOMMU_DOMAIN_DMA) { ret = iommu_dma_init_fq(group->default_domain); - if (!ret) - group->default_domain->type = IOMMU_DOMAIN_DMA_FQ; - mutex_unlock(&group->mutex); + if (ret) + goto out_unlock; - return ret ?: count; + group->default_domain->type = IOMMU_DOMAIN_DMA_FQ; + ret = count; + goto out_unlock; } /* Otherwise, ensure that device exists and no driver is bound. */ if (list_empty(&group->devices) || group->owner_cnt) { - mutex_unlock(&group->mutex); - return -EPERM; + ret = -EPERM; + goto out_unlock; } - grp_dev = list_first_entry(&group->devices, struct group_device, list); - dev = grp_dev->dev; - - ret = iommu_change_dev_def_domain(group, dev, req_type); + ret = iommu_setup_default_domain(group, req_type); + if (ret) + goto out_unlock; /* * Release the mutex here because ops->probe_finalize() call-back of @@ -2986,9 +2993,12 @@ static ssize_t iommu_group_store_type(struct iommu_group *group, mutex_unlock(&group->mutex); /* Make sure dma_ops is appropriatley set */ - if (!ret) - __iommu_group_dma_finalize(group); + for_each_group_device(group, gdev) + iommu_group_do_probe_finalize(gdev->dev); + return count; +out_unlock: + mutex_unlock(&group->mutex); return ret ?: count; } @@ -3182,16 +3192,13 @@ EXPORT_SYMBOL_GPL(iommu_device_claim_dma_owner); static void __iommu_release_dma_ownership(struct iommu_group *group) { - int ret; - if (WARN_ON(!group->owner_cnt || !group->owner || !xa_empty(&group->pasid_array))) return; group->owner_cnt = 0; group->owner = NULL; - ret = __iommu_group_set_domain(group, group->default_domain); - WARN(ret, "iommu driver failed to attach the default domain"); + __iommu_group_set_domain_nofail(group, group->default_domain); } /** @@ -3253,7 +3260,7 @@ static int __iommu_set_group_pasid(struct iommu_domain *domain, struct group_device *device; int ret = 0; - list_for_each_entry(device, &group->devices, list) { + for_each_group_device(group, device) { ret = domain->ops->set_dev_pasid(domain, device->dev, pasid); if (ret) break; @@ -3268,7 +3275,7 @@ static void __iommu_remove_group_pasid(struct iommu_group *group, struct group_device *device; const struct iommu_ops *ops; - list_for_each_entry(device, &group->devices, list) { + for_each_group_device(group, device) { ops = dev_iommu_ops(device->dev); ops->remove_dev_pasid(device->dev, pasid); } diff --git a/drivers/iommu/iommufd/device.c b/drivers/iommu/iommufd/device.c index 4f9b2142274cebca1b4f30ff0144677dd143e12e..29d05663d4d17a553d09023e26360f23d338ad3c 100644 --- a/drivers/iommu/iommufd/device.c +++ b/drivers/iommu/iommufd/device.c @@ -553,8 +553,8 @@ void iommufd_access_unpin_pages(struct iommufd_access *access, iopt_area_iova_to_index( area, min(last_iova, iopt_area_last_iova(area)))); - up_read(&iopt->iova_rwsem); WARN_ON(!iopt_area_contig_done(&iter)); + up_read(&iopt->iova_rwsem); } EXPORT_SYMBOL_NS_GPL(iommufd_access_unpin_pages, IOMMUFD); diff --git a/drivers/iommu/iommufd/io_pagetable.c b/drivers/iommu/iommufd/io_pagetable.c index e0ae72b9e67f86f89ed29ac29c6363f52821c776..724c4c5742417a8c136811e943e93fdaa777b82d 100644 --- a/drivers/iommu/iommufd/io_pagetable.c +++ b/drivers/iommu/iommufd/io_pagetable.c @@ -458,6 +458,7 @@ static int iopt_unmap_iova_range(struct io_pagetable *iopt, unsigned long start, { struct iopt_area *area; unsigned long unmapped_bytes = 0; + unsigned int tries = 0; int rc = -ENOENT; /* @@ -484,19 +485,26 @@ static int iopt_unmap_iova_range(struct io_pagetable *iopt, unsigned long start, goto out_unlock_iova; } + if (area_first != start) + tries = 0; + /* * num_accesses writers must hold the iova_rwsem too, so we can * safely read it under the write side of the iovam_rwsem * without the pages->mutex. */ if (area->num_accesses) { + size_t length = iopt_area_length(area); + start = area_first; area->prevent_access = true; up_write(&iopt->iova_rwsem); up_read(&iopt->domains_rwsem); - iommufd_access_notify_unmap(iopt, area_first, - iopt_area_length(area)); - if (WARN_ON(READ_ONCE(area->num_accesses))) + + iommufd_access_notify_unmap(iopt, area_first, length); + /* Something is not responding to unmap requests. */ + tries++; + if (WARN_ON(tries > 100)) return -EDEADLOCK; goto again; } diff --git a/drivers/iommu/iommufd/pages.c b/drivers/iommu/iommufd/pages.c index 3c47846cc5efe8f49c26b283e10f3ae42c42d641..412ca96be128eacfd053c2c457ae9663f7801c52 100644 --- a/drivers/iommu/iommufd/pages.c +++ b/drivers/iommu/iommufd/pages.c @@ -786,7 +786,7 @@ static int pfn_reader_user_pin(struct pfn_reader_user *user, user->locked = 1; } rc = pin_user_pages_remote(pages->source_mm, uptr, npages, - user->gup_flags, user->upages, NULL, + user->gup_flags, user->upages, &user->locked); } if (rc <= 0) { @@ -1799,7 +1799,7 @@ static int iopt_pages_rw_page(struct iopt_pages *pages, unsigned long index, rc = pin_user_pages_remote( pages->source_mm, (uintptr_t)(pages->uptr + index * PAGE_SIZE), 1, (flags & IOMMUFD_ACCESS_RW_WRITE) ? FOLL_WRITE : 0, &page, - NULL, NULL); + NULL); mmap_read_unlock(pages->source_mm); if (rc != 1) { if (WARN_ON(rc >= 0)) diff --git a/drivers/iommu/iova.c b/drivers/iommu/iova.c index fe452ce466429a702b4df515e3c03298d418f136..10b964600948c7f618c9fc6f2f6911b81ef15408 100644 --- a/drivers/iommu/iova.c +++ b/drivers/iommu/iova.c @@ -647,7 +647,13 @@ struct iova_rcache { static struct iova_magazine *iova_magazine_alloc(gfp_t flags) { - return kzalloc(sizeof(struct iova_magazine), flags); + struct iova_magazine *mag; + + mag = kmalloc(sizeof(*mag), flags); + if (mag) + mag->size = 0; + + return mag; } static void iova_magazine_free(struct iova_magazine *mag) diff --git a/drivers/iommu/virtio-iommu.c b/drivers/iommu/virtio-iommu.c index 5b8fe9bfa9a5b9ce2a78d5f0bfa4bd511b27d07f..3551ed057774e648311f8c3f8ca71fb09f32161b 100644 --- a/drivers/iommu/virtio-iommu.c +++ b/drivers/iommu/virtio-iommu.c @@ -788,6 +788,29 @@ static int viommu_attach_dev(struct iommu_domain *domain, struct device *dev) return 0; } +static void viommu_detach_dev(struct viommu_endpoint *vdev) +{ + int i; + struct virtio_iommu_req_detach req; + struct viommu_domain *vdomain = vdev->vdomain; + struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(vdev->dev); + + if (!vdomain) + return; + + req = (struct virtio_iommu_req_detach) { + .head.type = VIRTIO_IOMMU_T_DETACH, + .domain = cpu_to_le32(vdomain->id), + }; + + for (i = 0; i < fwspec->num_ids; i++) { + req.endpoint = cpu_to_le32(fwspec->ids[i]); + WARN_ON(viommu_send_req_sync(vdev->viommu, &req, sizeof(req))); + } + vdomain->nr_endpoints--; + vdev->vdomain = NULL; +} + static int viommu_map_pages(struct iommu_domain *domain, unsigned long iova, phys_addr_t paddr, size_t pgsize, size_t pgcount, int prot, gfp_t gfp, size_t *mapped) @@ -810,25 +833,26 @@ static int viommu_map_pages(struct iommu_domain *domain, unsigned long iova, if (ret) return ret; - map = (struct virtio_iommu_req_map) { - .head.type = VIRTIO_IOMMU_T_MAP, - .domain = cpu_to_le32(vdomain->id), - .virt_start = cpu_to_le64(iova), - .phys_start = cpu_to_le64(paddr), - .virt_end = cpu_to_le64(end), - .flags = cpu_to_le32(flags), - }; - - if (!vdomain->nr_endpoints) - return 0; + if (vdomain->nr_endpoints) { + map = (struct virtio_iommu_req_map) { + .head.type = VIRTIO_IOMMU_T_MAP, + .domain = cpu_to_le32(vdomain->id), + .virt_start = cpu_to_le64(iova), + .phys_start = cpu_to_le64(paddr), + .virt_end = cpu_to_le64(end), + .flags = cpu_to_le32(flags), + }; - ret = viommu_send_req_sync(vdomain->viommu, &map, sizeof(map)); - if (ret) - viommu_del_mappings(vdomain, iova, end); - else if (mapped) + ret = viommu_send_req_sync(vdomain->viommu, &map, sizeof(map)); + if (ret) { + viommu_del_mappings(vdomain, iova, end); + return ret; + } + } + if (mapped) *mapped = size; - return ret; + return 0; } static size_t viommu_unmap_pages(struct iommu_domain *domain, unsigned long iova, @@ -990,6 +1014,7 @@ static void viommu_release_device(struct device *dev) { struct viommu_endpoint *vdev = dev_iommu_priv_get(dev); + viommu_detach_dev(vdev); iommu_put_resv_regions(dev, &vdev->resv_regions); kfree(vdev); } diff --git a/drivers/irqchip/irq-clps711x.c b/drivers/irqchip/irq-clps711x.c index 77ebe7e47e0e938f7ed5db0b90f374b48fee4d9f..e731e0784f7e3e0207a7608665a9fa4c94753147 100644 --- a/drivers/irqchip/irq-clps711x.c +++ b/drivers/irqchip/irq-clps711x.c @@ -212,12 +212,6 @@ static int __init _clps711x_intc_init(struct device_node *np, return err; } -void __init clps711x_intc_init(phys_addr_t base, resource_size_t size) -{ - BUG_ON(_clps711x_intc_init(NULL, base, size)); -} - -#ifdef CONFIG_IRQCHIP static int __init clps711x_intc_init_dt(struct device_node *np, struct device_node *parent) { @@ -231,4 +225,3 @@ static int __init clps711x_intc_init_dt(struct device_node *np, return _clps711x_intc_init(np, res.start, resource_size(&res)); } IRQCHIP_DECLARE(clps711x, "cirrus,ep7209-intc", clps711x_intc_init_dt); -#endif diff --git a/drivers/irqchip/irq-ftintc010.c b/drivers/irqchip/irq-ftintc010.c index 46a3aa60e50e3212426eced8929238070810230a..359efc1d1be73b0e778c3795c4cd510343a4e209 100644 --- a/drivers/irqchip/irq-ftintc010.c +++ b/drivers/irqchip/irq-ftintc010.c @@ -125,7 +125,7 @@ static struct irq_chip ft010_irq_chip = { /* Local static for the IRQ entry call */ static struct ft010_irq_data firq; -asmlinkage void __exception_irq_entry ft010_irqchip_handle_irq(struct pt_regs *regs) +static asmlinkage void __exception_irq_entry ft010_irqchip_handle_irq(struct pt_regs *regs) { struct ft010_irq_data *f = &firq; int irq; @@ -162,7 +162,7 @@ static const struct irq_domain_ops ft010_irqdomain_ops = { .xlate = irq_domain_xlate_onetwocell, }; -int __init ft010_of_init_irq(struct device_node *node, +static int __init ft010_of_init_irq(struct device_node *node, struct device_node *parent) { struct ft010_irq_data *f = &firq; diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c index 0ec2b1e1df75bc416ee49f8fbec82d1dfb80f142..1994541eaef841cb0ffcdcec01b9692af4918c6e 100644 --- a/drivers/irqchip/irq-gic-v3-its.c +++ b/drivers/irqchip/irq-gic-v3-its.c @@ -3585,6 +3585,7 @@ static int its_irq_domain_alloc(struct irq_domain *domain, unsigned int virq, irqd = irq_get_irq_data(virq + i); irqd_set_single_target(irqd); irqd_set_affinity_on_activate(irqd); + irqd_set_resend_when_in_progress(irqd); pr_debug("ID:%d pID:%d vID:%d\n", (int)(hwirq + i - its_dev->event_map.lpi_base), (int)(hwirq + i), virq + i); @@ -4523,6 +4524,7 @@ static int its_vpe_irq_domain_alloc(struct irq_domain *domain, unsigned int virq irq_domain_set_hwirq_and_chip(domain, virq + i, i, irqchip, vm->vpes[i]); set_bit(i, bitmap); + irqd_set_resend_when_in_progress(irq_get_irq_data(virq + i)); } if (err) { diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c index a605aa79435a4dca64dd1eb012f0f1fe7f394ff3..0c6c1af9a5b7da91d3129c2bb0dce15f9dcad877 100644 --- a/drivers/irqchip/irq-gic-v3.c +++ b/drivers/irqchip/irq-gic-v3.c @@ -40,6 +40,7 @@ #define FLAGS_WORKAROUND_GICR_WAKER_MSM8996 (1ULL << 0) #define FLAGS_WORKAROUND_CAVIUM_ERRATUM_38539 (1ULL << 1) #define FLAGS_WORKAROUND_MTK_GICR_SAVE (1ULL << 2) +#define FLAGS_WORKAROUND_ASR_ERRATUM_8601001 (1ULL << 3) #define GIC_IRQ_TYPE_PARTITION (GIC_IRQ_TYPE_LPI + 1) @@ -656,10 +657,16 @@ static int gic_irq_set_vcpu_affinity(struct irq_data *d, void *vcpu) return 0; } -static u64 gic_mpidr_to_affinity(unsigned long mpidr) +static u64 gic_cpu_to_affinity(int cpu) { + u64 mpidr = cpu_logical_map(cpu); u64 aff; + /* ASR8601 needs to have its affinities shifted down... */ + if (unlikely(gic_data.flags & FLAGS_WORKAROUND_ASR_ERRATUM_8601001)) + mpidr = (MPIDR_AFFINITY_LEVEL(mpidr, 1) | + (MPIDR_AFFINITY_LEVEL(mpidr, 2) << 8)); + aff = ((u64)MPIDR_AFFINITY_LEVEL(mpidr, 3) << 32 | MPIDR_AFFINITY_LEVEL(mpidr, 2) << 16 | MPIDR_AFFINITY_LEVEL(mpidr, 1) << 8 | @@ -914,7 +921,7 @@ static void __init gic_dist_init(void) * Set all global interrupts to the boot CPU only. ARE must be * enabled. */ - affinity = gic_mpidr_to_affinity(cpu_logical_map(smp_processor_id())); + affinity = gic_cpu_to_affinity(smp_processor_id()); for (i = 32; i < GIC_LINE_NR; i++) gic_write_irouter(affinity, base + GICD_IROUTER + i * 8); @@ -963,7 +970,7 @@ static int gic_iterate_rdists(int (*fn)(struct redist_region *, void __iomem *)) static int __gic_populate_rdist(struct redist_region *region, void __iomem *ptr) { - unsigned long mpidr = cpu_logical_map(smp_processor_id()); + unsigned long mpidr; u64 typer; u32 aff; @@ -971,6 +978,8 @@ static int __gic_populate_rdist(struct redist_region *region, void __iomem *ptr) * Convert affinity to a 32bit value that can be matched to * GICR_TYPER bits [63:32]. */ + mpidr = gic_cpu_to_affinity(smp_processor_id()); + aff = (MPIDR_AFFINITY_LEVEL(mpidr, 3) << 24 | MPIDR_AFFINITY_LEVEL(mpidr, 2) << 16 | MPIDR_AFFINITY_LEVEL(mpidr, 1) << 8 | @@ -1084,7 +1093,7 @@ static inline bool gic_dist_security_disabled(void) static void gic_cpu_sys_reg_init(void) { int i, cpu = smp_processor_id(); - u64 mpidr = cpu_logical_map(cpu); + u64 mpidr = gic_cpu_to_affinity(cpu); u64 need_rss = MPIDR_RS(mpidr); bool group0; u32 pribits; @@ -1183,11 +1192,11 @@ static void gic_cpu_sys_reg_init(void) for_each_online_cpu(i) { bool have_rss = per_cpu(has_rss, i) && per_cpu(has_rss, cpu); - need_rss |= MPIDR_RS(cpu_logical_map(i)); + need_rss |= MPIDR_RS(gic_cpu_to_affinity(i)); if (need_rss && (!have_rss)) pr_crit("CPU%d (%lx) can't SGI CPU%d (%lx), no RSS\n", cpu, (unsigned long)mpidr, - i, (unsigned long)cpu_logical_map(i)); + i, (unsigned long)gic_cpu_to_affinity(i)); } /** @@ -1263,9 +1272,11 @@ static u16 gic_compute_target_list(int *base_cpu, const struct cpumask *mask, unsigned long cluster_id) { int next_cpu, cpu = *base_cpu; - unsigned long mpidr = cpu_logical_map(cpu); + unsigned long mpidr; u16 tlist = 0; + mpidr = gic_cpu_to_affinity(cpu); + while (cpu < nr_cpu_ids) { tlist |= 1 << (mpidr & 0xf); @@ -1274,7 +1285,7 @@ static u16 gic_compute_target_list(int *base_cpu, const struct cpumask *mask, goto out; cpu = next_cpu; - mpidr = cpu_logical_map(cpu); + mpidr = gic_cpu_to_affinity(cpu); if (cluster_id != MPIDR_TO_SGI_CLUSTER_ID(mpidr)) { cpu--; @@ -1319,7 +1330,7 @@ static void gic_ipi_send_mask(struct irq_data *d, const struct cpumask *mask) dsb(ishst); for_each_cpu(cpu, mask) { - u64 cluster_id = MPIDR_TO_SGI_CLUSTER_ID(cpu_logical_map(cpu)); + u64 cluster_id = MPIDR_TO_SGI_CLUSTER_ID(gic_cpu_to_affinity(cpu)); u16 tlist; tlist = gic_compute_target_list(&cpu, mask, cluster_id); @@ -1377,7 +1388,7 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val, offset = convert_offset_index(d, GICD_IROUTER, &index); reg = gic_dist_base(d) + offset + (index * 8); - val = gic_mpidr_to_affinity(cpu_logical_map(cpu)); + val = gic_cpu_to_affinity(cpu); gic_write_irouter(val, reg); @@ -1796,12 +1807,26 @@ static bool gic_enable_quirk_nvidia_t241(void *data) return true; } +static bool gic_enable_quirk_asr8601(void *data) +{ + struct gic_chip_data *d = data; + + d->flags |= FLAGS_WORKAROUND_ASR_ERRATUM_8601001; + + return true; +} + static const struct gic_quirk gic_quirks[] = { { .desc = "GICv3: Qualcomm MSM8996 broken firmware", .compatible = "qcom,msm8996-gic-v3", .init = gic_enable_quirk_msm8996, }, + { + .desc = "GICv3: ASR erratum 8601001", + .compatible = "asr,asr8601-gic-v3", + .init = gic_enable_quirk_asr8601, + }, { .desc = "GICv3: Mediatek Chromebook GICR save problem", .property = "mediatek,broken-save-restore-fw", diff --git a/drivers/irqchip/irq-jcore-aic.c b/drivers/irqchip/irq-jcore-aic.c index 5f47d8ee4ae39e04964a461626b3138fadd11d18..b9dcc8e78c75017582f44d3615c7db92465f4465 100644 --- a/drivers/irqchip/irq-jcore-aic.c +++ b/drivers/irqchip/irq-jcore-aic.c @@ -68,6 +68,7 @@ static int __init aic_irq_of_init(struct device_node *node, unsigned min_irq = JCORE_AIC2_MIN_HWIRQ; unsigned dom_sz = JCORE_AIC_MAX_HWIRQ+1; struct irq_domain *domain; + int ret; pr_info("Initializing J-Core AIC\n"); @@ -100,6 +101,12 @@ static int __init aic_irq_of_init(struct device_node *node, jcore_aic.irq_unmask = noop; jcore_aic.name = "AIC"; + ret = irq_alloc_descs(-1, min_irq, dom_sz - min_irq, + of_node_to_nid(node)); + + if (ret < 0) + return ret; + domain = irq_domain_add_legacy(node, dom_sz - min_irq, min_irq, min_irq, &jcore_aic_irqdomain_ops, &jcore_aic); diff --git a/drivers/irqchip/irq-loongson-eiointc.c b/drivers/irqchip/irq-loongson-eiointc.c index 71ef19f77a5a02a3bb5bb130125ec9dfb5c9135c..92d8aa28bdf5487d2ff8908769eedef3a25725d2 100644 --- a/drivers/irqchip/irq-loongson-eiointc.c +++ b/drivers/irqchip/irq-loongson-eiointc.c @@ -36,6 +36,7 @@ static int nr_pics; struct eiointc_priv { u32 node; + u32 vec_count; nodemask_t node_map; cpumask_t cpuspan_map; struct fwnode_handle *domain_handle; @@ -153,18 +154,18 @@ static int eiointc_router_init(unsigned int cpu) if ((cpu_logical_map(cpu) % CORES_PER_EIO_NODE) == 0) { eiointc_enable(); - for (i = 0; i < VEC_COUNT / 32; i++) { + for (i = 0; i < eiointc_priv[0]->vec_count / 32; i++) { data = (((1 << (i * 2 + 1)) << 16) | (1 << (i * 2))); iocsr_write32(data, EIOINTC_REG_NODEMAP + i * 4); } - for (i = 0; i < VEC_COUNT / 32 / 4; i++) { + for (i = 0; i < eiointc_priv[0]->vec_count / 32 / 4; i++) { bit = BIT(1 + index); /* Route to IP[1 + index] */ data = bit | (bit << 8) | (bit << 16) | (bit << 24); iocsr_write32(data, EIOINTC_REG_IPMAP + i * 4); } - for (i = 0; i < VEC_COUNT / 4; i++) { + for (i = 0; i < eiointc_priv[0]->vec_count / 4; i++) { /* Route to Node-0 Core-0 */ if (index == 0) bit = BIT(cpu_logical_map(0)); @@ -175,7 +176,7 @@ static int eiointc_router_init(unsigned int cpu) iocsr_write32(data, EIOINTC_REG_ROUTE + i * 4); } - for (i = 0; i < VEC_COUNT / 32; i++) { + for (i = 0; i < eiointc_priv[0]->vec_count / 32; i++) { data = 0xffffffff; iocsr_write32(data, EIOINTC_REG_ENABLE + i * 4); iocsr_write32(data, EIOINTC_REG_BOUNCE + i * 4); @@ -195,7 +196,7 @@ static void eiointc_irq_dispatch(struct irq_desc *desc) chained_irq_enter(chip, desc); - for (i = 0; i < VEC_REG_COUNT; i++) { + for (i = 0; i < eiointc_priv[0]->vec_count / VEC_COUNT_PER_REG; i++) { pending = iocsr_read64(EIOINTC_REG_ISR + (i << 3)); iocsr_write64(pending, EIOINTC_REG_ISR + (i << 3)); while (pending) { @@ -310,11 +311,11 @@ static void eiointc_resume(void) eiointc_router_init(0); for (i = 0; i < nr_pics; i++) { - for (j = 0; j < VEC_COUNT; j++) { + for (j = 0; j < eiointc_priv[0]->vec_count; j++) { desc = irq_resolve_mapping(eiointc_priv[i]->eiointc_domain, j); if (desc && desc->handle_irq && desc->handle_irq != handle_bad_irq) { raw_spin_lock(&desc->lock); - irq_data = &desc->irq_data; + irq_data = irq_domain_get_irq_data(eiointc_priv[i]->eiointc_domain, irq_desc_get_irq(desc)); eiointc_set_irq_affinity(irq_data, irq_data->common->affinity, 0); raw_spin_unlock(&desc->lock); } @@ -375,11 +376,47 @@ static int __init acpi_cascade_irqdomain_init(void) return 0; } +static int __init eiointc_init(struct eiointc_priv *priv, int parent_irq, + u64 node_map) +{ + int i; + + node_map = node_map ? node_map : -1ULL; + for_each_possible_cpu(i) { + if (node_map & (1ULL << (cpu_to_eio_node(i)))) { + node_set(cpu_to_eio_node(i), priv->node_map); + cpumask_or(&priv->cpuspan_map, &priv->cpuspan_map, + cpumask_of(i)); + } + } + + priv->eiointc_domain = irq_domain_create_linear(priv->domain_handle, + priv->vec_count, + &eiointc_domain_ops, + priv); + if (!priv->eiointc_domain) { + pr_err("loongson-extioi: cannot add IRQ domain\n"); + return -ENOMEM; + } + + eiointc_priv[nr_pics++] = priv; + eiointc_router_init(0); + irq_set_chained_handler_and_data(parent_irq, eiointc_irq_dispatch, priv); + + if (nr_pics == 1) { + register_syscore_ops(&eiointc_syscore_ops); + cpuhp_setup_state_nocalls(CPUHP_AP_IRQ_LOONGARCH_STARTING, + "irqchip/loongarch/intc:starting", + eiointc_router_init, NULL); + } + + return 0; +} + int __init eiointc_acpi_init(struct irq_domain *parent, struct acpi_madt_eio_pic *acpi_eiointc) { - int i, ret, parent_irq; - unsigned long node_map; + int parent_irq, ret; struct eiointc_priv *priv; int node; @@ -394,37 +431,14 @@ int __init eiointc_acpi_init(struct irq_domain *parent, goto out_free_priv; } + priv->vec_count = VEC_COUNT; priv->node = acpi_eiointc->node; - node_map = acpi_eiointc->node_map ? : -1ULL; - - for_each_possible_cpu(i) { - if (node_map & (1ULL << cpu_to_eio_node(i))) { - node_set(cpu_to_eio_node(i), priv->node_map); - cpumask_or(&priv->cpuspan_map, &priv->cpuspan_map, cpumask_of(i)); - } - } - - /* Setup IRQ domain */ - priv->eiointc_domain = irq_domain_create_linear(priv->domain_handle, VEC_COUNT, - &eiointc_domain_ops, priv); - if (!priv->eiointc_domain) { - pr_err("loongson-eiointc: cannot add IRQ domain\n"); - goto out_free_handle; - } - - eiointc_priv[nr_pics++] = priv; - - eiointc_router_init(0); parent_irq = irq_create_mapping(parent, acpi_eiointc->cascade); - irq_set_chained_handler_and_data(parent_irq, eiointc_irq_dispatch, priv); - if (nr_pics == 1) { - register_syscore_ops(&eiointc_syscore_ops); - cpuhp_setup_state_nocalls(CPUHP_AP_IRQ_LOONGARCH_STARTING, - "irqchip/loongarch/intc:starting", - eiointc_router_init, NULL); - } + ret = eiointc_init(priv, parent_irq, acpi_eiointc->node_map); + if (ret < 0) + goto out_free_handle; if (cpu_has_flatmode) node = cpu_to_node(acpi_eiointc->node * CORES_PER_EIO_NODE); @@ -432,7 +446,10 @@ int __init eiointc_acpi_init(struct irq_domain *parent, node = acpi_eiointc->node; acpi_set_vec_parent(node, priv->eiointc_domain, pch_group); acpi_set_vec_parent(node, priv->eiointc_domain, msi_group); + ret = acpi_cascade_irqdomain_init(); + if (ret < 0) + goto out_free_handle; return ret; @@ -444,3 +461,49 @@ int __init eiointc_acpi_init(struct irq_domain *parent, return -ENOMEM; } + +static int __init eiointc_of_init(struct device_node *of_node, + struct device_node *parent) +{ + int parent_irq, ret; + struct eiointc_priv *priv; + + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + parent_irq = irq_of_parse_and_map(of_node, 0); + if (parent_irq <= 0) { + ret = -ENODEV; + goto out_free_priv; + } + + ret = irq_set_handler_data(parent_irq, priv); + if (ret < 0) + goto out_free_priv; + + /* + * In particular, the number of devices supported by the LS2K0500 + * extended I/O interrupt vector is 128. + */ + if (of_device_is_compatible(of_node, "loongson,ls2k0500-eiointc")) + priv->vec_count = 128; + else + priv->vec_count = VEC_COUNT; + + priv->node = 0; + priv->domain_handle = of_node_to_fwnode(of_node); + + ret = eiointc_init(priv, parent_irq, 0); + if (ret < 0) + goto out_free_priv; + + return 0; + +out_free_priv: + kfree(priv); + return ret; +} + +IRQCHIP_DECLARE(loongson_ls2k0500_eiointc, "loongson,ls2k0500-eiointc", eiointc_of_init); +IRQCHIP_DECLARE(loongson_ls2k2000_eiointc, "loongson,ls2k2000-eiointc", eiointc_of_init); diff --git a/drivers/irqchip/irq-loongson-liointc.c b/drivers/irqchip/irq-loongson-liointc.c index 8d00a9ad5b0053b3155538c687dac01a4dda7eac..e4b33aed1c97b3461e8f66f734f1785743a013f4 100644 --- a/drivers/irqchip/irq-loongson-liointc.c +++ b/drivers/irqchip/irq-loongson-liointc.c @@ -32,6 +32,10 @@ #define LIOINTC_REG_INTC_EN_STATUS (LIOINTC_INTC_CHIP_START + 0x04) #define LIOINTC_REG_INTC_ENABLE (LIOINTC_INTC_CHIP_START + 0x08) #define LIOINTC_REG_INTC_DISABLE (LIOINTC_INTC_CHIP_START + 0x0c) +/* + * LIOINTC_REG_INTC_POL register is only valid for Loongson-2K series, and + * Loongson-3 series behave as noops. + */ #define LIOINTC_REG_INTC_POL (LIOINTC_INTC_CHIP_START + 0x10) #define LIOINTC_REG_INTC_EDGE (LIOINTC_INTC_CHIP_START + 0x14) @@ -116,19 +120,19 @@ static int liointc_set_type(struct irq_data *data, unsigned int type) switch (type) { case IRQ_TYPE_LEVEL_HIGH: liointc_set_bit(gc, LIOINTC_REG_INTC_EDGE, mask, false); - liointc_set_bit(gc, LIOINTC_REG_INTC_POL, mask, true); + liointc_set_bit(gc, LIOINTC_REG_INTC_POL, mask, false); break; case IRQ_TYPE_LEVEL_LOW: liointc_set_bit(gc, LIOINTC_REG_INTC_EDGE, mask, false); - liointc_set_bit(gc, LIOINTC_REG_INTC_POL, mask, false); + liointc_set_bit(gc, LIOINTC_REG_INTC_POL, mask, true); break; case IRQ_TYPE_EDGE_RISING: liointc_set_bit(gc, LIOINTC_REG_INTC_EDGE, mask, true); - liointc_set_bit(gc, LIOINTC_REG_INTC_POL, mask, true); + liointc_set_bit(gc, LIOINTC_REG_INTC_POL, mask, false); break; case IRQ_TYPE_EDGE_FALLING: liointc_set_bit(gc, LIOINTC_REG_INTC_EDGE, mask, true); - liointc_set_bit(gc, LIOINTC_REG_INTC_POL, mask, false); + liointc_set_bit(gc, LIOINTC_REG_INTC_POL, mask, true); break; default: irq_gc_unlock_irqrestore(gc, flags); @@ -291,6 +295,7 @@ static int liointc_init(phys_addr_t addr, unsigned long size, int revision, ct->chip.irq_mask = irq_gc_mask_disable_reg; ct->chip.irq_mask_ack = irq_gc_mask_disable_reg; ct->chip.irq_set_type = liointc_set_type; + ct->chip.flags = IRQCHIP_SKIP_SET_WAKE; gc->mask_cache = 0; priv->gc = gc; diff --git a/drivers/irqchip/irq-loongson-pch-pic.c b/drivers/irqchip/irq-loongson-pch-pic.c index e5fe4d50be056ffe00e2ab8f6c53fc5f1e464169..93a71f66efebfab23c0dd2883a0af328bda1f30b 100644 --- a/drivers/irqchip/irq-loongson-pch-pic.c +++ b/drivers/irqchip/irq-loongson-pch-pic.c @@ -164,7 +164,7 @@ static int pch_pic_domain_translate(struct irq_domain *d, if (fwspec->param_count < 2) return -EINVAL; - *hwirq = fwspec->param[0] + priv->ht_vec_base; + *hwirq = fwspec->param[0]; *type = fwspec->param[1] & IRQ_TYPE_SENSE_MASK; } else { if (fwspec->param_count < 1) @@ -196,7 +196,7 @@ static int pch_pic_alloc(struct irq_domain *domain, unsigned int virq, parent_fwspec.fwnode = domain->parent->fwnode; parent_fwspec.param_count = 1; - parent_fwspec.param[0] = hwirq; + parent_fwspec.param[0] = hwirq + priv->ht_vec_base; err = irq_domain_alloc_irqs_parent(domain, virq, 1, &parent_fwspec); if (err) @@ -401,14 +401,12 @@ static int __init acpi_cascade_irqdomain_init(void) int __init pch_pic_acpi_init(struct irq_domain *parent, struct acpi_madt_bio_pic *acpi_pchpic) { - int ret, vec_base; + int ret; struct fwnode_handle *domain_handle; if (find_pch_pic(acpi_pchpic->gsi_base) >= 0) return 0; - vec_base = acpi_pchpic->gsi_base - GSI_MIN_PCH_IRQ; - domain_handle = irq_domain_alloc_fwnode(&acpi_pchpic->address); if (!domain_handle) { pr_err("Unable to allocate domain handle\n"); @@ -416,7 +414,7 @@ int __init pch_pic_acpi_init(struct irq_domain *parent, } ret = pch_pic_init(acpi_pchpic->address, acpi_pchpic->size, - vec_base, parent, domain_handle, acpi_pchpic->gsi_base); + 0, parent, domain_handle, acpi_pchpic->gsi_base); if (ret < 0) { irq_domain_free_fwnode(domain_handle); diff --git a/drivers/irqchip/irq-mmp.c b/drivers/irqchip/irq-mmp.c index 83455ca72439395fcb090133f4f473ed7067ab4e..25cf4f80e767e68fac0ba6dd00f886c6ee819ddb 100644 --- a/drivers/irqchip/irq-mmp.c +++ b/drivers/irqchip/irq-mmp.c @@ -244,132 +244,6 @@ static void __exception_irq_entry mmp2_handle_irq(struct pt_regs *regs) generic_handle_domain_irq(icu_data[0].domain, hwirq); } -/* MMP (ARMv5) */ -void __init icu_init_irq(void) -{ - int irq; - - max_icu_nr = 1; - mmp_icu_base = ioremap(0xd4282000, 0x1000); - icu_data[0].conf_enable = mmp_conf.conf_enable; - icu_data[0].conf_disable = mmp_conf.conf_disable; - icu_data[0].conf_mask = mmp_conf.conf_mask; - icu_data[0].nr_irqs = 64; - icu_data[0].virq_base = 0; - icu_data[0].domain = irq_domain_add_legacy(NULL, 64, 0, 0, - &irq_domain_simple_ops, - &icu_data[0]); - for (irq = 0; irq < 64; irq++) { - icu_mask_irq(irq_get_irq_data(irq)); - irq_set_chip_and_handler(irq, &icu_irq_chip, handle_level_irq); - } - irq_set_default_host(icu_data[0].domain); - set_handle_irq(mmp_handle_irq); -} - -/* MMP2 (ARMv7) */ -void __init mmp2_init_icu(void) -{ - int irq, end; - - max_icu_nr = 8; - mmp_icu_base = ioremap(0xd4282000, 0x1000); - icu_data[0].conf_enable = mmp2_conf.conf_enable; - icu_data[0].conf_disable = mmp2_conf.conf_disable; - icu_data[0].conf_mask = mmp2_conf.conf_mask; - icu_data[0].nr_irqs = 64; - icu_data[0].virq_base = 0; - icu_data[0].domain = irq_domain_add_legacy(NULL, 64, 0, 0, - &irq_domain_simple_ops, - &icu_data[0]); - icu_data[1].reg_status = mmp_icu_base + 0x150; - icu_data[1].reg_mask = mmp_icu_base + 0x168; - icu_data[1].clr_mfp_irq_base = icu_data[0].virq_base + - icu_data[0].nr_irqs; - icu_data[1].clr_mfp_hwirq = 1; /* offset to IRQ_MMP2_PMIC_BASE */ - icu_data[1].nr_irqs = 2; - icu_data[1].cascade_irq = 4; - icu_data[1].virq_base = icu_data[0].virq_base + icu_data[0].nr_irqs; - icu_data[1].domain = irq_domain_add_legacy(NULL, icu_data[1].nr_irqs, - icu_data[1].virq_base, 0, - &irq_domain_simple_ops, - &icu_data[1]); - icu_data[2].reg_status = mmp_icu_base + 0x154; - icu_data[2].reg_mask = mmp_icu_base + 0x16c; - icu_data[2].nr_irqs = 2; - icu_data[2].cascade_irq = 5; - icu_data[2].virq_base = icu_data[1].virq_base + icu_data[1].nr_irqs; - icu_data[2].domain = irq_domain_add_legacy(NULL, icu_data[2].nr_irqs, - icu_data[2].virq_base, 0, - &irq_domain_simple_ops, - &icu_data[2]); - icu_data[3].reg_status = mmp_icu_base + 0x180; - icu_data[3].reg_mask = mmp_icu_base + 0x17c; - icu_data[3].nr_irqs = 3; - icu_data[3].cascade_irq = 9; - icu_data[3].virq_base = icu_data[2].virq_base + icu_data[2].nr_irqs; - icu_data[3].domain = irq_domain_add_legacy(NULL, icu_data[3].nr_irqs, - icu_data[3].virq_base, 0, - &irq_domain_simple_ops, - &icu_data[3]); - icu_data[4].reg_status = mmp_icu_base + 0x158; - icu_data[4].reg_mask = mmp_icu_base + 0x170; - icu_data[4].nr_irqs = 5; - icu_data[4].cascade_irq = 17; - icu_data[4].virq_base = icu_data[3].virq_base + icu_data[3].nr_irqs; - icu_data[4].domain = irq_domain_add_legacy(NULL, icu_data[4].nr_irqs, - icu_data[4].virq_base, 0, - &irq_domain_simple_ops, - &icu_data[4]); - icu_data[5].reg_status = mmp_icu_base + 0x15c; - icu_data[5].reg_mask = mmp_icu_base + 0x174; - icu_data[5].nr_irqs = 15; - icu_data[5].cascade_irq = 35; - icu_data[5].virq_base = icu_data[4].virq_base + icu_data[4].nr_irqs; - icu_data[5].domain = irq_domain_add_legacy(NULL, icu_data[5].nr_irqs, - icu_data[5].virq_base, 0, - &irq_domain_simple_ops, - &icu_data[5]); - icu_data[6].reg_status = mmp_icu_base + 0x160; - icu_data[6].reg_mask = mmp_icu_base + 0x178; - icu_data[6].nr_irqs = 2; - icu_data[6].cascade_irq = 51; - icu_data[6].virq_base = icu_data[5].virq_base + icu_data[5].nr_irqs; - icu_data[6].domain = irq_domain_add_legacy(NULL, icu_data[6].nr_irqs, - icu_data[6].virq_base, 0, - &irq_domain_simple_ops, - &icu_data[6]); - icu_data[7].reg_status = mmp_icu_base + 0x188; - icu_data[7].reg_mask = mmp_icu_base + 0x184; - icu_data[7].nr_irqs = 2; - icu_data[7].cascade_irq = 55; - icu_data[7].virq_base = icu_data[6].virq_base + icu_data[6].nr_irqs; - icu_data[7].domain = irq_domain_add_legacy(NULL, icu_data[7].nr_irqs, - icu_data[7].virq_base, 0, - &irq_domain_simple_ops, - &icu_data[7]); - end = icu_data[7].virq_base + icu_data[7].nr_irqs; - for (irq = 0; irq < end; irq++) { - icu_mask_irq(irq_get_irq_data(irq)); - if (irq == icu_data[1].cascade_irq || - irq == icu_data[2].cascade_irq || - irq == icu_data[3].cascade_irq || - irq == icu_data[4].cascade_irq || - irq == icu_data[5].cascade_irq || - irq == icu_data[6].cascade_irq || - irq == icu_data[7].cascade_irq) { - irq_set_chip(irq, &icu_irq_chip); - irq_set_chained_handler(irq, icu_mux_irq_demux); - } else { - irq_set_chip_and_handler(irq, &icu_irq_chip, - handle_level_irq); - } - } - irq_set_default_host(icu_data[0].domain); - set_handle_irq(mmp2_handle_irq); -} - -#ifdef CONFIG_OF static int __init mmp_init_bases(struct device_node *node) { int ret, nr_irqs, irq, i = 0; @@ -548,4 +422,3 @@ static int __init mmp2_mux_of_init(struct device_node *node, return -EINVAL; } IRQCHIP_DECLARE(mmp2_mux_intc, "mrvl,mmp2-mux-intc", mmp2_mux_of_init); -#endif diff --git a/drivers/irqchip/irq-mxs.c b/drivers/irqchip/irq-mxs.c index 55cb6b5a686e955310bfbc57ed6f5ed02e040211..be96806455458b19ee8f72f3141fa0b866989d00 100644 --- a/drivers/irqchip/irq-mxs.c +++ b/drivers/irqchip/irq-mxs.c @@ -201,6 +201,7 @@ static int __init icoll_of_init(struct device_node *np, stmp_reset_block(icoll_priv.ctrl); icoll_add_domain(np, ICOLL_NUM_IRQS); + set_handle_irq(icoll_handle_irq); return 0; } diff --git a/drivers/irqchip/irq-riscv-intc.c b/drivers/irqchip/irq-riscv-intc.c index f229e3e66387033605c1e02742de4d878599fb1e..4adeee1bc391fb17aed9a3097a0bb70665ecc166 100644 --- a/drivers/irqchip/irq-riscv-intc.c +++ b/drivers/irqchip/irq-riscv-intc.c @@ -6,6 +6,7 @@ */ #define pr_fmt(fmt) "riscv-intc: " fmt +#include #include #include #include @@ -112,6 +113,30 @@ static struct fwnode_handle *riscv_intc_hwnode(void) return intc_domain->fwnode; } +static int __init riscv_intc_init_common(struct fwnode_handle *fn) +{ + int rc; + + intc_domain = irq_domain_create_linear(fn, BITS_PER_LONG, + &riscv_intc_domain_ops, NULL); + if (!intc_domain) { + pr_err("unable to add IRQ domain\n"); + return -ENXIO; + } + + rc = set_handle_irq(&riscv_intc_irq); + if (rc) { + pr_err("failed to set irq handler\n"); + return rc; + } + + riscv_set_intc_hwnode_fn(riscv_intc_hwnode); + + pr_info("%d local interrupts mapped\n", BITS_PER_LONG); + + return 0; +} + static int __init riscv_intc_init(struct device_node *node, struct device_node *parent) { @@ -133,24 +158,39 @@ static int __init riscv_intc_init(struct device_node *node, if (riscv_hartid_to_cpuid(hartid) != smp_processor_id()) return 0; - intc_domain = irq_domain_add_linear(node, BITS_PER_LONG, - &riscv_intc_domain_ops, NULL); - if (!intc_domain) { - pr_err("unable to add IRQ domain\n"); - return -ENXIO; - } + return riscv_intc_init_common(of_node_to_fwnode(node)); +} - rc = set_handle_irq(&riscv_intc_irq); - if (rc) { - pr_err("failed to set irq handler\n"); - return rc; - } +IRQCHIP_DECLARE(riscv, "riscv,cpu-intc", riscv_intc_init); - riscv_set_intc_hwnode_fn(riscv_intc_hwnode); +#ifdef CONFIG_ACPI - pr_info("%d local interrupts mapped\n", BITS_PER_LONG); +static int __init riscv_intc_acpi_init(union acpi_subtable_headers *header, + const unsigned long end) +{ + struct fwnode_handle *fn; + struct acpi_madt_rintc *rintc; - return 0; + rintc = (struct acpi_madt_rintc *)header; + + /* + * The ACPI MADT will have one INTC for each CPU (or HART) + * so riscv_intc_acpi_init() function will be called once + * for each INTC. We only do INTC initialization + * for the INTC belonging to the boot CPU (or boot HART). + */ + if (riscv_hartid_to_cpuid(rintc->hart_id) != smp_processor_id()) + return 0; + + fn = irq_domain_alloc_named_fwnode("RISCV-INTC"); + if (!fn) { + pr_err("unable to allocate INTC FW node\n"); + return -ENOMEM; + } + + return riscv_intc_init_common(fn); } -IRQCHIP_DECLARE(riscv, "riscv,cpu-intc", riscv_intc_init); +IRQCHIP_ACPI_DECLARE(riscv_intc, ACPI_MADT_TYPE_RINTC, NULL, + ACPI_MADT_RINTC_VERSION_V1, riscv_intc_acpi_init); +#endif diff --git a/drivers/irqchip/irq-stm32-exti.c b/drivers/irqchip/irq-stm32-exti.c index 6a3f7498ea8eadacc08807b09d0b1bdbc97cc1d0..b5fa76ce5046a34f7668965e5b32b4f09c153d56 100644 --- a/drivers/irqchip/irq-stm32-exti.c +++ b/drivers/irqchip/irq-stm32-exti.c @@ -173,6 +173,16 @@ static struct irq_chip stm32_exti_h_chip_direct; #define EXTI_INVALID_IRQ U8_MAX #define STM32MP1_DESC_IRQ_SIZE (ARRAY_SIZE(stm32mp1_exti_banks) * IRQS_PER_BANK) +/* + * Use some intentionally tricky logic here to initialize the whole array to + * EXTI_INVALID_IRQ, but then override certain fields, requiring us to indicate + * that we "know" that there are overrides in this structure, and we'll need to + * disable that warning from W=1 builds. + */ +__diag_push(); +__diag_ignore_all("-Woverride-init", + "logic to initialize all and then override some is OK"); + static const u8 stm32mp1_desc_irq[] = { /* default value */ [0 ... (STM32MP1_DESC_IRQ_SIZE - 1)] = EXTI_INVALID_IRQ, @@ -208,6 +218,7 @@ static const u8 stm32mp1_desc_irq[] = { [31] = 53, [32] = 82, [33] = 83, + [46] = 151, [47] = 93, [48] = 138, [50] = 139, @@ -266,6 +277,8 @@ static const u8 stm32mp13_desc_irq[] = { [70] = 98, }; +__diag_pop(); + static const struct stm32_exti_drv_data stm32mp1_drv_data = { .exti_banks = stm32mp1_exti_banks, .bank_nr = ARRAY_SIZE(stm32mp1_exti_banks), diff --git a/drivers/isdn/Kconfig b/drivers/isdn/Kconfig index 2690e2c5a1584103f80bd9aa37c1da49fb838fb9..6fd1b3f84a29191a155da0445529d7784ad78433 100644 --- a/drivers/isdn/Kconfig +++ b/drivers/isdn/Kconfig @@ -6,7 +6,6 @@ menuconfig ISDN bool "ISDN support" depends on NET && NETDEVICES - depends on !S390 && !UML help ISDN ("Integrated Services Digital Network", called RNIS in France) is a fully digital telephone service that can be used for voice and diff --git a/drivers/isdn/hardware/mISDN/Kconfig b/drivers/isdn/hardware/mISDN/Kconfig index 078eeadf707ae7ebd80b365b51b5966ff2fce098..a35bff8a93f5d2f5069a37ad554736f84fe5c2b7 100644 --- a/drivers/isdn/hardware/mISDN/Kconfig +++ b/drivers/isdn/hardware/mISDN/Kconfig @@ -14,7 +14,7 @@ config MISDN_HFCPCI config MISDN_HFCMULTI tristate "Support for HFC multiport cards (HFC-4S/8S/E1)" - depends on PCI || CPM1 + depends on (PCI || CPM1) && HAS_IOPORT depends on MISDN help Enable support for cards with Cologne Chip AG's HFC multiport @@ -43,7 +43,7 @@ config MISDN_HFCUSB config MISDN_AVMFRITZ tristate "Support for AVM FRITZ!CARD PCI" depends on MISDN - depends on PCI + depends on PCI && HAS_IOPORT select MISDN_IPAC help Enable support for AVMs FRITZ!CARD PCI cards @@ -51,7 +51,7 @@ config MISDN_AVMFRITZ config MISDN_SPEEDFAX tristate "Support for Sedlbauer Speedfax+" depends on MISDN - depends on PCI + depends on PCI && HAS_IOPORT select MISDN_IPAC select MISDN_ISAR help @@ -60,7 +60,7 @@ config MISDN_SPEEDFAX config MISDN_INFINEON tristate "Support for cards with Infineon chipset" depends on MISDN - depends on PCI + depends on PCI && HAS_IOPORT select MISDN_IPAC help Enable support for cards with ISAC + HSCX, IPAC or IPAC-SX @@ -69,14 +69,14 @@ config MISDN_INFINEON config MISDN_W6692 tristate "Support for cards with Winbond 6692" depends on MISDN - depends on PCI + depends on PCI && HAS_IOPORT help Enable support for Winbond 6692 PCI chip based cards. config MISDN_NETJET tristate "Support for NETJet cards" depends on MISDN - depends on PCI + depends on PCI && HAS_IOPORT depends on TTY select MISDN_IPAC select MISDN_HDLC diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index 2c5fdf848210014bbcb4e13cd9eacd9fb01e5de7..6046dfeca16fce9087fe6c25ef56669f668fee41 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -94,6 +94,19 @@ config LEDS_ARIEL Say Y to if your machine is a Dell Wyse 3020 thin client. +config LEDS_AW200XX + tristate "LED support for Awinic AW20036/AW20054/AW20072" + depends on LEDS_CLASS + depends on I2C + help + This option enables support for the AW20036/AW20054/AW20072 LED driver. + It is a 3x12/6x9/6x12 matrix LED driver programmed via + an I2C interface, up to 36/54/72 LEDs or 12/18/24 RGBs, + 3 pattern controllers for auto breathing or group dimming control. + + To compile this driver as a module, choose M here: the module + will be called leds-aw200xx. + config LEDS_AW2013 tristate "LED support for Awinic AW2013" depends on LEDS_CLASS && I2C && OF @@ -122,6 +135,17 @@ config LEDS_BCM6358 This option enables support for LEDs connected to the BCM6358 LED HW controller accessed via MMIO registers. +config LEDS_CHT_WCOVE + tristate "LED support for Intel Cherry Trail Whiskey Cove PMIC" + depends on LEDS_CLASS + depends on INTEL_SOC_PMIC_CHTWC + help + This option enables support for charger and general purpose LEDs + connected to the Intel Cherrytrail Whiskey Cove PMIC. + + To compile this driver as a module, choose M here: the module + will be called leds-cht-wcove. + config LEDS_CPCAP tristate "LED Support for Motorola CPCAP" depends on LEDS_CLASS @@ -676,7 +700,7 @@ config LEDS_LM355x config LEDS_OT200 tristate "LED support for the Bachmann OT200" - depends on LEDS_CLASS && HAS_IOMEM && (X86_32 || COMPILE_TEST) + depends on LEDS_CLASS && HAS_IOPORT && (X86_32 || COMPILE_TEST) help This option enables support for the LEDs on the Bachmann OT200. Say Y to enable LEDs on the Bachmann OT200. @@ -807,8 +831,7 @@ config LEDS_SPI_BYTE supported: Ubiquiti airCube ISP microcontroller based LED controller. config LEDS_TI_LMU_COMMON - tristate "LED driver for TI LMU" - depends on LEDS_CLASS + tristate "LED driver for TI LMU" if COMPILE_TEST select REGMAP help Say Y to enable the LED driver for TI LMU devices. @@ -817,16 +840,16 @@ config LEDS_TI_LMU_COMMON config LEDS_LM3697 tristate "LED driver for LM3697" - depends on LEDS_TI_LMU_COMMON - depends on I2C && OF + depends on LEDS_CLASS && I2C && OF + select LEDS_TI_LMU_COMMON help Say Y to enable the LM3697 LED driver for TI LMU devices. This supports the LED device LM3697. config LEDS_LM36274 tristate "LED driver for LM36274" - depends on LEDS_TI_LMU_COMMON - depends on MFD_TI_LMU + depends on LEDS_CLASS && MFD_TI_LMU + select LEDS_TI_LMU_COMMON help Say Y to enable the LM36274 LED driver for TI LMU devices. This supports the LED device LM36274. diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile index c07d1512c745a592941d1b587689160288978a64..d71f1226540c2ea2e1e95968def2426e086e83df 100644 --- a/drivers/leds/Makefile +++ b/drivers/leds/Makefile @@ -14,12 +14,14 @@ obj-$(CONFIG_LEDS_ADP5520) += leds-adp5520.o obj-$(CONFIG_LEDS_AN30259A) += leds-an30259a.o obj-$(CONFIG_LEDS_APU) += leds-apu.o obj-$(CONFIG_LEDS_ARIEL) += leds-ariel.o +obj-$(CONFIG_LEDS_AW200XX) += leds-aw200xx.o obj-$(CONFIG_LEDS_AW2013) += leds-aw2013.o obj-$(CONFIG_LEDS_BCM6328) += leds-bcm6328.o obj-$(CONFIG_LEDS_BCM6358) += leds-bcm6358.o obj-$(CONFIG_LEDS_BD2606MVV) += leds-bd2606mvv.o obj-$(CONFIG_LEDS_BD2802) += leds-bd2802.o obj-$(CONFIG_LEDS_BLINKM) += leds-blinkm.o +obj-$(CONFIG_LEDS_CHT_WCOVE) += leds-cht-wcove.o obj-$(CONFIG_LEDS_CLEVO_MAIL) += leds-clevo-mail.o obj-$(CONFIG_LEDS_COBALT_QUBE) += leds-cobalt-qube.o obj-$(CONFIG_LEDS_COBALT_RAQ) += leds-cobalt-raq.o diff --git a/drivers/leds/flash/leds-aat1290.c b/drivers/leds/flash/leds-aat1290.c index 589484b22c796c81abc91c01dc7f8790dd3aa345..f12ecb2c658031d815e909a20579bbfb4fe07596 100644 --- a/drivers/leds/flash/leds-aat1290.c +++ b/drivers/leds/flash/leds-aat1290.c @@ -425,7 +425,7 @@ static void aat1290_init_v4l2_flash_config(struct aat1290_led *led, struct led_classdev *led_cdev = &led->fled_cdev.led_cdev; struct led_flash_setting *s; - strlcpy(v4l2_sd_cfg->dev_name, led_cdev->dev->kobj.name, + strscpy(v4l2_sd_cfg->dev_name, led_cdev->dev->kobj.name, sizeof(v4l2_sd_cfg->dev_name)); s = &v4l2_sd_cfg->intensity; diff --git a/drivers/leds/flash/leds-as3645a.c b/drivers/leds/flash/leds-as3645a.c index bb2249771acb29612e987903021a39e7a46868e2..12c2609c11372426ad5359e64203a6fb46258bb4 100644 --- a/drivers/leds/flash/leds-as3645a.c +++ b/drivers/leds/flash/leds-as3645a.c @@ -651,8 +651,8 @@ static int as3645a_v4l2_setup(struct as3645a *flash) }, }; - strlcpy(cfg.dev_name, led->dev->kobj.name, sizeof(cfg.dev_name)); - strlcpy(cfgind.dev_name, flash->iled_cdev.dev->kobj.name, + strscpy(cfg.dev_name, led->dev->kobj.name, sizeof(cfg.dev_name)); + strscpy(cfgind.dev_name, flash->iled_cdev.dev->kobj.name, sizeof(cfgind.dev_name)); flash->vf = v4l2_flash_init( @@ -759,7 +759,7 @@ static struct i2c_driver as3645a_i2c_driver = { .of_match_table = as3645a_of_table, .name = AS_NAME, }, - .probe_new = as3645a_probe, + .probe = as3645a_probe, .remove = as3645a_remove, .id_table = as3645a_id_table, }; diff --git a/drivers/leds/flash/leds-lm3601x.c b/drivers/leds/flash/leds-lm3601x.c index 78730e066a733e35b7f63b05ca4582f98f463c1c..b6c524facf498ba944eb3838f324503063cc6f0a 100644 --- a/drivers/leds/flash/leds-lm3601x.c +++ b/drivers/leds/flash/leds-lm3601x.c @@ -471,7 +471,7 @@ static struct i2c_driver lm3601x_i2c_driver = { .name = "lm3601x", .of_match_table = of_lm3601x_leds_match, }, - .probe_new = lm3601x_probe, + .probe = lm3601x_probe, .remove = lm3601x_remove, .id_table = lm3601x_id, }; diff --git a/drivers/leds/flash/leds-qcom-flash.c b/drivers/leds/flash/leds-qcom-flash.c index 90a24fa25a494ef3d692ae2c5c301023c6ac0325..b089ca1a19012eca234e99a9daee90ed32fdbf9a 100644 --- a/drivers/leds/flash/leds-qcom-flash.c +++ b/drivers/leds/flash/leds-qcom-flash.c @@ -18,7 +18,8 @@ #define FLASH_TYPE_VAL 0x18 #define FLASH_SUBTYPE_REG 0x05 -#define FLASH_SUBTYPE_3CH_VAL 0x04 +#define FLASH_SUBTYPE_3CH_PM8150_VAL 0x04 +#define FLASH_SUBTYPE_3CH_PMI8998_VAL 0x03 #define FLASH_SUBTYPE_4CH_VAL 0x07 #define FLASH_STS_3CH_OTST1 BIT(0) @@ -416,6 +417,14 @@ static int qcom_flash_led_brightness_set(struct led_classdev *led_cdev, bool enable = !!brightness; int rc; + rc = set_flash_strobe(led, SW_STROBE, false); + if (rc) + return rc; + + rc = set_flash_module_en(led, false); + if (rc) + return rc; + rc = set_flash_current(led, current_ma, TORCH_MODE); if (rc) return rc; @@ -529,9 +538,9 @@ static int qcom_flash_register_led_device(struct device *dev, struct led_init_data init_data; struct led_classdev_flash *flash = &led->flash; struct led_flash_setting *brightness, *timeout; - u32 count, current_ua, timeout_us; + u32 current_ua, timeout_us; u32 channels[4]; - int i, rc; + int i, rc, count; count = fwnode_property_count_u32(node, "led-sources"); if (count <= 0) { @@ -682,7 +691,7 @@ static int qcom_flash_led_probe(struct platform_device *pdev) return rc; } - if (val == FLASH_SUBTYPE_3CH_VAL) { + if (val == FLASH_SUBTYPE_3CH_PM8150_VAL || val == FLASH_SUBTYPE_3CH_PMI8998_VAL) { flash_data->hw_type = QCOM_MVFLASH_3CH; flash_data->max_channels = 3; regs = mvflash_3ch_regs; diff --git a/drivers/leds/flash/leds-rt4505.c b/drivers/leds/flash/leds-rt4505.c index e404fe8b0314f979d0d74b46144c9add5c5f5828..1ae5b387f4a50de12ceb20c18c25e2dd9741b620 100644 --- a/drivers/leds/flash/leds-rt4505.c +++ b/drivers/leds/flash/leds-rt4505.c @@ -419,7 +419,7 @@ static struct i2c_driver rt4505_driver = { .name = "rt4505", .of_match_table = of_match_ptr(rt4505_leds_match), }, - .probe_new = rt4505_probe, + .probe = rt4505_probe, .remove = rt4505_remove, .shutdown = rt4505_shutdown, }; diff --git a/drivers/leds/flash/leds-sgm3140.c b/drivers/leds/flash/leds-sgm3140.c index d3a30ad94ac463e4f472e675c1918f0d67d8d399..d3f50dca51366097b4e2d57b26759d92122c0855 100644 --- a/drivers/leds/flash/leds-sgm3140.c +++ b/drivers/leds/flash/leds-sgm3140.c @@ -291,6 +291,7 @@ static int sgm3140_remove(struct platform_device *pdev) static const struct of_device_id sgm3140_dt_match[] = { { .compatible = "ocs,ocp8110" }, + { .compatible = "richtek,rt5033-led" }, { .compatible = "sgmicro,sgm3140" }, { /* sentinel */ } }; diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c index 9255bc11f99d843981ff607ff1eaa364fe79aba0..6dae56b914fe3d0007d11cca51fc00e898b83455 100644 --- a/drivers/leds/led-class.c +++ b/drivers/leds/led-class.c @@ -409,7 +409,7 @@ static int led_classdev_next_name(const char *init_name, char *name, int ret = 0; struct device *dev; - strlcpy(name, init_name, len); + strscpy(name, init_name, len); while ((ret < len) && (dev = class_find_device_by_name(leds_class, name))) { diff --git a/drivers/leds/led-core.c b/drivers/leds/led-core.c index 4a97cb7457888c6dd3c265985548163209f8d647..b9b1295833c90a314e22447f6b6d0a4072bd2577 100644 --- a/drivers/leds/led-core.c +++ b/drivers/leds/led-core.c @@ -114,21 +114,14 @@ static void led_timer_function(struct timer_list *t) mod_timer(&led_cdev->blink_timer, jiffies + msecs_to_jiffies(delay)); } -static void set_brightness_delayed(struct work_struct *ws) +static void set_brightness_delayed_set_brightness(struct led_classdev *led_cdev, + unsigned int value) { - struct led_classdev *led_cdev = - container_of(ws, struct led_classdev, set_brightness_work); int ret = 0; - if (test_and_clear_bit(LED_BLINK_DISABLE, &led_cdev->work_flags)) { - led_cdev->delayed_set_value = LED_OFF; - led_stop_software_blink(led_cdev); - } - - ret = __led_set_brightness(led_cdev, led_cdev->delayed_set_value); + ret = __led_set_brightness(led_cdev, value); if (ret == -ENOTSUPP) - ret = __led_set_brightness_blocking(led_cdev, - led_cdev->delayed_set_value); + ret = __led_set_brightness_blocking(led_cdev, value); if (ret < 0 && /* LED HW might have been unplugged, therefore don't warn */ !(ret == -ENODEV && (led_cdev->flags & LED_UNREGISTERING) && @@ -137,6 +130,37 @@ static void set_brightness_delayed(struct work_struct *ws) "Setting an LED's brightness failed (%d)\n", ret); } +static void set_brightness_delayed(struct work_struct *ws) +{ + struct led_classdev *led_cdev = + container_of(ws, struct led_classdev, set_brightness_work); + + if (test_and_clear_bit(LED_BLINK_DISABLE, &led_cdev->work_flags)) { + led_stop_software_blink(led_cdev); + set_bit(LED_SET_BRIGHTNESS_OFF, &led_cdev->work_flags); + } + + /* + * Triggers may call led_set_brightness(LED_OFF), + * led_set_brightness(LED_FULL) in quick succession to disable blinking + * and turn the LED on. Both actions may have been scheduled to run + * before this work item runs once. To make sure this works properly + * handle LED_SET_BRIGHTNESS_OFF first. + */ + if (test_and_clear_bit(LED_SET_BRIGHTNESS_OFF, &led_cdev->work_flags)) + set_brightness_delayed_set_brightness(led_cdev, LED_OFF); + + if (test_and_clear_bit(LED_SET_BRIGHTNESS, &led_cdev->work_flags)) + set_brightness_delayed_set_brightness(led_cdev, led_cdev->delayed_set_value); + + if (test_and_clear_bit(LED_SET_BLINK, &led_cdev->work_flags)) { + unsigned long delay_on = led_cdev->delayed_delay_on; + unsigned long delay_off = led_cdev->delayed_delay_off; + + led_blink_set(led_cdev, &delay_on, &delay_off); + } +} + static void led_set_software_blink(struct led_classdev *led_cdev, unsigned long delay_on, unsigned long delay_off) @@ -229,6 +253,22 @@ void led_blink_set_oneshot(struct led_classdev *led_cdev, } EXPORT_SYMBOL_GPL(led_blink_set_oneshot); +void led_blink_set_nosleep(struct led_classdev *led_cdev, unsigned long delay_on, + unsigned long delay_off) +{ + /* If necessary delegate to a work queue task. */ + if (led_cdev->blink_set && led_cdev->brightness_set_blocking) { + led_cdev->delayed_delay_on = delay_on; + led_cdev->delayed_delay_off = delay_off; + set_bit(LED_SET_BLINK, &led_cdev->work_flags); + schedule_work(&led_cdev->set_brightness_work); + return; + } + + led_blink_set(led_cdev, &delay_on, &delay_off); +} +EXPORT_SYMBOL_GPL(led_blink_set_nosleep); + void led_stop_software_blink(struct led_classdev *led_cdev) { del_timer_sync(&led_cdev->blink_timer); @@ -271,8 +311,23 @@ void led_set_brightness_nopm(struct led_classdev *led_cdev, unsigned int value) if (!__led_set_brightness(led_cdev, value)) return; - /* If brightness setting can sleep, delegate it to a work queue task */ - led_cdev->delayed_set_value = value; + /* + * Brightness setting can sleep, delegate it to a work queue task. + * value 0 / LED_OFF is special, since it also disables hw-blinking + * (sw-blink disable is handled in led_set_brightness()). + * To avoid a hw-blink-disable getting lost when a second brightness + * change is done immediately afterwards (before the work runs), + * it uses a separate work_flag. + */ + if (value) { + led_cdev->delayed_set_value = value; + set_bit(LED_SET_BRIGHTNESS, &led_cdev->work_flags); + } else { + clear_bit(LED_SET_BRIGHTNESS, &led_cdev->work_flags); + clear_bit(LED_SET_BLINK, &led_cdev->work_flags); + set_bit(LED_SET_BRIGHTNESS_OFF, &led_cdev->work_flags); + } + schedule_work(&led_cdev->set_brightness_work); } EXPORT_SYMBOL_GPL(led_set_brightness_nopm); diff --git a/drivers/leds/led-triggers.c b/drivers/leds/led-triggers.c index 072491d3e17b01501c7a96b6593ce1f6ffe9bb9a..6a5e1f41f9a4527e7373de97cf63ee5079d946c1 100644 --- a/drivers/leds/led-triggers.c +++ b/drivers/leds/led-triggers.c @@ -185,6 +185,7 @@ int led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trig) led_cdev->trigger = NULL; led_cdev->trigger_data = NULL; led_cdev->activated = false; + led_cdev->flags &= ~LED_INIT_DEFAULT_TRIGGER; led_set_brightness(led_cdev, LED_OFF); } if (trig) { @@ -393,8 +394,8 @@ void led_trigger_event(struct led_trigger *trig, EXPORT_SYMBOL_GPL(led_trigger_event); static void led_trigger_blink_setup(struct led_trigger *trig, - unsigned long *delay_on, - unsigned long *delay_off, + unsigned long delay_on, + unsigned long delay_off, int oneshot, int invert) { @@ -406,25 +407,25 @@ static void led_trigger_blink_setup(struct led_trigger *trig, rcu_read_lock(); list_for_each_entry_rcu(led_cdev, &trig->led_cdevs, trig_list) { if (oneshot) - led_blink_set_oneshot(led_cdev, delay_on, delay_off, + led_blink_set_oneshot(led_cdev, &delay_on, &delay_off, invert); else - led_blink_set(led_cdev, delay_on, delay_off); + led_blink_set_nosleep(led_cdev, delay_on, delay_off); } rcu_read_unlock(); } void led_trigger_blink(struct led_trigger *trig, - unsigned long *delay_on, - unsigned long *delay_off) + unsigned long delay_on, + unsigned long delay_off) { led_trigger_blink_setup(trig, delay_on, delay_off, 0, 0); } EXPORT_SYMBOL_GPL(led_trigger_blink); void led_trigger_blink_oneshot(struct led_trigger *trig, - unsigned long *delay_on, - unsigned long *delay_off, + unsigned long delay_on, + unsigned long delay_off, int invert) { led_trigger_blink_setup(trig, delay_on, delay_off, 1, invert); diff --git a/drivers/leds/leds-an30259a.c b/drivers/leds/leds-an30259a.c index 89df267853a91e2c2e8c825c7822243f07ba2cdb..24b1041213c27e2563e3ac1c14e41e3b60ce7655 100644 --- a/drivers/leds/leds-an30259a.c +++ b/drivers/leds/leds-an30259a.c @@ -346,7 +346,7 @@ static struct i2c_driver an30259a_driver = { .name = "leds-an30259a", .of_match_table = of_match_ptr(an30259a_match_table), }, - .probe_new = an30259a_probe, + .probe = an30259a_probe, .remove = an30259a_remove, .id_table = an30259a_id, }; diff --git a/drivers/leds/leds-aw200xx.c b/drivers/leds/leds-aw200xx.c new file mode 100644 index 0000000000000000000000000000000000000000..96979b8e09b7d70292f804870cd1435cb74ff752 --- /dev/null +++ b/drivers/leds/leds-aw200xx.c @@ -0,0 +1,594 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Awinic AW20036/AW20054/AW20072 LED driver + * + * Copyright (c) 2023, SberDevices. All Rights Reserved. + * + * Author: Martin Kurbanov + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define AW200XX_DIM_MAX (BIT(6) - 1) +#define AW200XX_FADE_MAX (BIT(8) - 1) +#define AW200XX_IMAX_DEFAULT_uA 60000 +#define AW200XX_IMAX_MAX_uA 160000 +#define AW200XX_IMAX_MIN_uA 3300 + +/* Page 0 */ +#define AW200XX_REG_PAGE0_BASE 0xc000 + +/* Select page register */ +#define AW200XX_REG_PAGE 0xF0 +#define AW200XX_PAGE_MASK (GENMASK(7, 6) | GENMASK(2, 0)) +#define AW200XX_PAGE_SHIFT 0 +#define AW200XX_NUM_PAGES 6 +#define AW200XX_PAGE_SIZE 256 +#define AW200XX_REG(page, reg) \ + (AW200XX_REG_PAGE0_BASE + (page) * AW200XX_PAGE_SIZE + (reg)) +#define AW200XX_REG_MAX \ + AW200XX_REG(AW200XX_NUM_PAGES - 1, AW200XX_PAGE_SIZE - 1) +#define AW200XX_PAGE0 0 +#define AW200XX_PAGE1 1 +#define AW200XX_PAGE2 2 +#define AW200XX_PAGE3 3 +#define AW200XX_PAGE4 4 +#define AW200XX_PAGE5 5 + +/* Chip ID register */ +#define AW200XX_REG_IDR AW200XX_REG(AW200XX_PAGE0, 0x00) +#define AW200XX_IDR_CHIPID 0x18 + +/* Sleep mode register */ +#define AW200XX_REG_SLPCR AW200XX_REG(AW200XX_PAGE0, 0x01) +#define AW200XX_SLPCR_ACTIVE 0x00 + +/* Reset register */ +#define AW200XX_REG_RSTR AW200XX_REG(AW200XX_PAGE0, 0x02) +#define AW200XX_RSTR_RESET 0x01 + +/* Global current configuration register */ +#define AW200XX_REG_GCCR AW200XX_REG(AW200XX_PAGE0, 0x03) +#define AW200XX_GCCR_IMAX_MASK GENMASK(7, 4) +#define AW200XX_GCCR_IMAX(x) ((x) << 4) +#define AW200XX_GCCR_ALLON BIT(3) + +/* Fast clear display control register */ +#define AW200XX_REG_FCD AW200XX_REG(AW200XX_PAGE0, 0x04) +#define AW200XX_FCD_CLEAR 0x01 + +/* Display size configuration */ +#define AW200XX_REG_DSIZE AW200XX_REG(AW200XX_PAGE0, 0x80) +#define AW200XX_DSIZE_COLUMNS_MAX 12 + +#define AW200XX_LED2REG(x, columns) \ + ((x) + (((x) / (columns)) * (AW200XX_DSIZE_COLUMNS_MAX - (columns)))) + +/* + * DIM current configuration register (page 4). + * The even address for current DIM configuration. + * The odd address for current FADE configuration + */ +#define AW200XX_REG_DIM(x, columns) \ + AW200XX_REG(AW200XX_PAGE4, AW200XX_LED2REG(x, columns) * 2) +#define AW200XX_REG_DIM2FADE(x) ((x) + 1) + +/* + * Duty ratio of display scan (see p.15 of datasheet for formula): + * duty = (592us / 600.5us) * (1 / (display_rows + 1)) + * + * Multiply to 1000 (MILLI) to improve the accuracy of calculations. + */ +#define AW200XX_DUTY_RATIO(rows) \ + (((592UL * USEC_PER_SEC) / 600500UL) * (MILLI / (rows)) / MILLI) + +struct aw200xx_chipdef { + u32 channels; + u32 display_size_rows_max; + u32 display_size_columns; +}; + +struct aw200xx_led { + struct led_classdev cdev; + struct aw200xx *chip; + int dim; + u32 num; +}; + +struct aw200xx { + const struct aw200xx_chipdef *cdef; + struct i2c_client *client; + struct regmap *regmap; + struct mutex mutex; + u32 num_leds; + u32 display_rows; + struct aw200xx_led leds[]; +}; + +static ssize_t dim_show(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + struct led_classdev *cdev = dev_get_drvdata(dev); + struct aw200xx_led *led = container_of(cdev, struct aw200xx_led, cdev); + int dim = led->dim; + + if (dim < 0) + return sysfs_emit(buf, "auto\n"); + + return sysfs_emit(buf, "%d\n", dim); +} + +static ssize_t dim_store(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + struct led_classdev *cdev = dev_get_drvdata(dev); + struct aw200xx_led *led = container_of(cdev, struct aw200xx_led, cdev); + struct aw200xx *chip = led->chip; + u32 columns = chip->cdef->display_size_columns; + int dim; + ssize_t ret; + + if (sysfs_streq(buf, "auto")) { + dim = -1; + } else { + ret = kstrtoint(buf, 0, &dim); + if (ret) + return ret; + + if (dim > AW200XX_DIM_MAX) + return -EINVAL; + } + + mutex_lock(&chip->mutex); + + if (dim >= 0) { + ret = regmap_write(chip->regmap, + AW200XX_REG_DIM(led->num, columns), dim); + if (ret) + goto out_unlock; + } + + led->dim = dim; + ret = count; + +out_unlock: + mutex_unlock(&chip->mutex); + return ret; +} +static DEVICE_ATTR_RW(dim); + +static struct attribute *dim_attrs[] = { + &dev_attr_dim.attr, + NULL +}; +ATTRIBUTE_GROUPS(dim); + +static int aw200xx_brightness_set(struct led_classdev *cdev, + enum led_brightness brightness) +{ + struct aw200xx_led *led = container_of(cdev, struct aw200xx_led, cdev); + struct aw200xx *chip = led->chip; + int dim; + u32 reg; + int ret; + + mutex_lock(&chip->mutex); + + reg = AW200XX_REG_DIM(led->num, chip->cdef->display_size_columns); + + dim = led->dim; + if (dim < 0) + dim = max_t(int, + brightness / (AW200XX_FADE_MAX / AW200XX_DIM_MAX), + 1); + + ret = regmap_write(chip->regmap, reg, dim); + if (ret) + goto out_unlock; + + ret = regmap_write(chip->regmap, + AW200XX_REG_DIM2FADE(reg), brightness); + +out_unlock: + mutex_unlock(&chip->mutex); + + return ret; +} + +static u32 aw200xx_imax_from_global(const struct aw200xx *const chip, + u32 global_imax_uA) +{ + u64 led_imax_uA; + + /* + * The output current of each LED (see p.14 of datasheet for formula): + * Iled = Imax * (dim / 63) * ((fade + 1) / 256) * duty + * + * The value of duty is determined by the following formula: + * duty = (592us / 600.5us) * (1 / (display_rows + 1)) + * + * Calculated for the maximum values of fade and dim. + * We divide by 1000 because we earlier multiplied by 1000 to improve + * accuracy when calculating the duty. + */ + led_imax_uA = global_imax_uA * AW200XX_DUTY_RATIO(chip->display_rows); + do_div(led_imax_uA, MILLI); + + return led_imax_uA; +} + +static u32 aw200xx_imax_to_global(const struct aw200xx *const chip, + u32 led_imax_uA) +{ + u32 duty = AW200XX_DUTY_RATIO(chip->display_rows); + + /* The output current of each LED (see p.14 of datasheet for formula) */ + return (led_imax_uA * 1000U) / duty; +} + +#define AW200XX_IMAX_MULTIPLIER1 10000 +#define AW200XX_IMAX_MULTIPLIER2 3333 +#define AW200XX_IMAX_BASE_VAL1 0 +#define AW200XX_IMAX_BASE_VAL2 8 + +/* + * The AW200XX has a 4-bit register (GCCR) to configure the global current, + * which ranges from 3.3mA to 160mA. The following table indicates the values + * of the global current, divided into two parts: + * + * +-----------+-----------------+-----------+-----------------+ + * | reg value | global max (mA) | reg value | global max (mA) | + * +-----------+-----------------+-----------+-----------------+ + * | 0 | 10 | 8 | 3.3 | + * | 1 | 20 | 9 | 6.7 | + * | 2 | 30 | 10 | 10 | + * | 3 | 40 | 11 | 13.3 | + * | 4 | 60 | 12 | 20 | + * | 5 | 80 | 13 | 26.7 | + * | 6 | 120 | 14 | 40 | + * | 7 | 160 | 15 | 53.3 | + * +-----------+-----------------+-----------+-----------------+ + * + * The left part with a multiplier of 10, and the right part with a multiplier + * of 3.3. + * So we have two formulas to calculate the global current: + * for the left part of the table: + * imax = coefficient * 10 + * + * for the right part of the table: + * imax = coefficient * 3.3 + * + * The coefficient table consists of the following values: + * 1, 2, 3, 4, 6, 8, 12, 16. + */ +static int aw200xx_set_imax(const struct aw200xx *const chip, + u32 led_imax_uA) +{ + u32 g_imax_uA = aw200xx_imax_to_global(chip, led_imax_uA); + u32 coeff_table[] = {1, 2, 3, 4, 6, 8, 12, 16}; + u32 gccr_imax = UINT_MAX; + u32 cur_imax = 0; + int i; + + for (i = 0; i < ARRAY_SIZE(coeff_table); i++) { + u32 imax; + + /* select closest ones */ + imax = coeff_table[i] * AW200XX_IMAX_MULTIPLIER1; + if (g_imax_uA >= imax && imax > cur_imax) { + cur_imax = imax; + gccr_imax = i + AW200XX_IMAX_BASE_VAL1; + } + + imax = coeff_table[i] * AW200XX_IMAX_MULTIPLIER2; + imax = DIV_ROUND_CLOSEST(imax, 100) * 100; + if (g_imax_uA >= imax && imax > cur_imax) { + cur_imax = imax; + gccr_imax = i + AW200XX_IMAX_BASE_VAL2; + } + } + + if (gccr_imax == UINT_MAX) + return -EINVAL; + + return regmap_update_bits(chip->regmap, AW200XX_REG_GCCR, + AW200XX_GCCR_IMAX_MASK, + AW200XX_GCCR_IMAX(gccr_imax)); +} + +static int aw200xx_chip_reset(const struct aw200xx *const chip) +{ + int ret; + + ret = regmap_write(chip->regmap, AW200XX_REG_RSTR, AW200XX_RSTR_RESET); + if (ret) + return ret; + + regcache_mark_dirty(chip->regmap); + return regmap_write(chip->regmap, AW200XX_REG_FCD, AW200XX_FCD_CLEAR); +} + +static int aw200xx_chip_init(const struct aw200xx *const chip) +{ + int ret; + + ret = regmap_write(chip->regmap, AW200XX_REG_DSIZE, + chip->display_rows - 1); + if (ret) + return ret; + + ret = regmap_write(chip->regmap, AW200XX_REG_SLPCR, + AW200XX_SLPCR_ACTIVE); + if (ret) + return ret; + + return regmap_update_bits(chip->regmap, AW200XX_REG_GCCR, + AW200XX_GCCR_ALLON, AW200XX_GCCR_ALLON); +} + +static int aw200xx_chip_check(const struct aw200xx *const chip) +{ + struct device *dev = &chip->client->dev; + u32 chipid; + int ret; + + ret = regmap_read(chip->regmap, AW200XX_REG_IDR, &chipid); + if (ret) + return dev_err_probe(dev, ret, "Failed to read chip ID\n"); + + if (chipid != AW200XX_IDR_CHIPID) + return dev_err_probe(dev, -ENODEV, + "Chip reported wrong ID: %x\n", chipid); + + return 0; +} + +static int aw200xx_probe_fw(struct device *dev, struct aw200xx *chip) +{ + struct fwnode_handle *child; + u32 current_min, current_max, min_uA; + int ret; + int i; + + ret = device_property_read_u32(dev, "awinic,display-rows", + &chip->display_rows); + if (ret) + return dev_err_probe(dev, ret, + "Failed to read 'display-rows' property\n"); + + if (!chip->display_rows || + chip->display_rows > chip->cdef->display_size_rows_max) { + return dev_err_probe(dev, ret, + "Invalid leds display size %u\n", + chip->display_rows); + } + + current_max = aw200xx_imax_from_global(chip, AW200XX_IMAX_MAX_uA); + current_min = aw200xx_imax_from_global(chip, AW200XX_IMAX_MIN_uA); + min_uA = UINT_MAX; + i = 0; + + device_for_each_child_node(dev, child) { + struct led_init_data init_data = {}; + struct aw200xx_led *led; + u32 source, imax; + + ret = fwnode_property_read_u32(child, "reg", &source); + if (ret) { + dev_err(dev, "Missing reg property\n"); + chip->num_leds--; + continue; + } + + if (source >= chip->cdef->channels) { + dev_err(dev, "LED reg %u out of range (max %u)\n", + source, chip->cdef->channels); + chip->num_leds--; + continue; + } + + ret = fwnode_property_read_u32(child, "led-max-microamp", + &imax); + if (ret) { + dev_info(&chip->client->dev, + "DT property led-max-microamp is missing\n"); + } else if (imax < current_min || imax > current_max) { + dev_err(dev, "Invalid value %u for led-max-microamp\n", + imax); + chip->num_leds--; + continue; + } else { + min_uA = min(min_uA, imax); + } + + led = &chip->leds[i]; + led->dim = -1; + led->num = source; + led->chip = chip; + led->cdev.brightness_set_blocking = aw200xx_brightness_set; + led->cdev.groups = dim_groups; + init_data.fwnode = child; + + ret = devm_led_classdev_register_ext(dev, &led->cdev, + &init_data); + if (ret) { + fwnode_handle_put(child); + break; + } + + i++; + } + + if (!chip->num_leds) + return -EINVAL; + + if (min_uA == UINT_MAX) { + min_uA = aw200xx_imax_from_global(chip, + AW200XX_IMAX_DEFAULT_uA); + } + + return aw200xx_set_imax(chip, min_uA); +} + +static const struct regmap_range_cfg aw200xx_ranges[] = { + { + .name = "aw200xx", + .range_min = 0, + .range_max = AW200XX_REG_MAX, + .selector_reg = AW200XX_REG_PAGE, + .selector_mask = AW200XX_PAGE_MASK, + .selector_shift = AW200XX_PAGE_SHIFT, + .window_start = 0, + .window_len = AW200XX_PAGE_SIZE, + }, +}; + +static const struct regmap_range aw200xx_writeonly_ranges[] = { + regmap_reg_range(AW200XX_REG(AW200XX_PAGE1, 0x00), AW200XX_REG_MAX), +}; + +static const struct regmap_access_table aw200xx_readable_table = { + .no_ranges = aw200xx_writeonly_ranges, + .n_no_ranges = ARRAY_SIZE(aw200xx_writeonly_ranges), +}; + +static const struct regmap_range aw200xx_readonly_ranges[] = { + regmap_reg_range(AW200XX_REG_IDR, AW200XX_REG_IDR), +}; + +static const struct regmap_access_table aw200xx_writeable_table = { + .no_ranges = aw200xx_readonly_ranges, + .n_no_ranges = ARRAY_SIZE(aw200xx_readonly_ranges), +}; + +static const struct regmap_config aw200xx_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = AW200XX_REG_MAX, + .ranges = aw200xx_ranges, + .num_ranges = ARRAY_SIZE(aw200xx_ranges), + .rd_table = &aw200xx_readable_table, + .wr_table = &aw200xx_writeable_table, + .cache_type = REGCACHE_RBTREE, +}; + +static int aw200xx_probe(struct i2c_client *client) +{ + const struct aw200xx_chipdef *cdef; + struct aw200xx *chip; + int count; + int ret; + + cdef = device_get_match_data(&client->dev); + if (!cdef) + return -ENODEV; + + count = device_get_child_node_count(&client->dev); + if (!count || count > cdef->channels) + return dev_err_probe(&client->dev, -EINVAL, + "Incorrect number of leds (%d)", count); + + chip = devm_kzalloc(&client->dev, struct_size(chip, leds, count), + GFP_KERNEL); + if (!chip) + return -ENOMEM; + + chip->cdef = cdef; + chip->num_leds = count; + chip->client = client; + i2c_set_clientdata(client, chip); + + chip->regmap = devm_regmap_init_i2c(client, &aw200xx_regmap_config); + if (IS_ERR(chip->regmap)) + return PTR_ERR(chip->regmap); + + ret = aw200xx_chip_check(chip); + if (ret) + return ret; + + mutex_init(&chip->mutex); + + /* Need a lock now since after call aw200xx_probe_fw, sysfs nodes created */ + mutex_lock(&chip->mutex); + + ret = aw200xx_chip_reset(chip); + if (ret) + goto out_unlock; + + ret = aw200xx_probe_fw(&client->dev, chip); + if (ret) + goto out_unlock; + + ret = aw200xx_chip_init(chip); + +out_unlock: + mutex_unlock(&chip->mutex); + return ret; +} + +static void aw200xx_remove(struct i2c_client *client) +{ + struct aw200xx *chip = i2c_get_clientdata(client); + + aw200xx_chip_reset(chip); + mutex_destroy(&chip->mutex); +} + +static const struct aw200xx_chipdef aw20036_cdef = { + .channels = 36, + .display_size_rows_max = 3, + .display_size_columns = 12, +}; + +static const struct aw200xx_chipdef aw20054_cdef = { + .channels = 54, + .display_size_rows_max = 6, + .display_size_columns = 9, +}; + +static const struct aw200xx_chipdef aw20072_cdef = { + .channels = 72, + .display_size_rows_max = 6, + .display_size_columns = 12, +}; + +static const struct i2c_device_id aw200xx_id[] = { + { "aw20036" }, + { "aw20054" }, + { "aw20072" }, + {} +}; +MODULE_DEVICE_TABLE(i2c, aw200xx_id); + +static const struct of_device_id aw200xx_match_table[] = { + { .compatible = "awinic,aw20036", .data = &aw20036_cdef, }, + { .compatible = "awinic,aw20054", .data = &aw20054_cdef, }, + { .compatible = "awinic,aw20072", .data = &aw20072_cdef, }, + {} +}; +MODULE_DEVICE_TABLE(of, aw200xx_match_table); + +static struct i2c_driver aw200xx_driver = { + .driver = { + .name = "aw200xx", + .of_match_table = aw200xx_match_table, + }, + .probe_new = aw200xx_probe, + .remove = aw200xx_remove, + .id_table = aw200xx_id, +}; +module_i2c_driver(aw200xx_driver); + +MODULE_AUTHOR("Martin Kurbanov "); +MODULE_DESCRIPTION("AW200XX LED driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/leds/leds-aw2013.c b/drivers/leds/leds-aw2013.c index 0b52fc9097c6e1abcb3459ffb7405bd83c419c3c..59765640b70fe9c68aafd94feaafd5edd19aacb4 100644 --- a/drivers/leds/leds-aw2013.c +++ b/drivers/leds/leds-aw2013.c @@ -422,7 +422,7 @@ static struct i2c_driver aw2013_driver = { .name = "leds-aw2013", .of_match_table = of_match_ptr(aw2013_match_table), }, - .probe_new = aw2013_probe, + .probe = aw2013_probe, .remove = aw2013_remove, }; diff --git a/drivers/leds/leds-bd2606mvv.c b/drivers/leds/leds-bd2606mvv.c index 76f9d4d70f9a66a058926e2261e89a82ca2c14c5..3fda712d2f80955fb8fe1a6d03c864634e683f87 100644 --- a/drivers/leds/leds-bd2606mvv.c +++ b/drivers/leds/leds-bd2606mvv.c @@ -150,7 +150,7 @@ static struct i2c_driver bd2606mvv_driver = { .name = "leds-bd2606mvv", .of_match_table = of_match_ptr(of_bd2606mvv_leds_match), }, - .probe_new = bd2606mvv_probe, + .probe = bd2606mvv_probe, }; module_i2c_driver(bd2606mvv_driver); diff --git a/drivers/leds/leds-bd2802.c b/drivers/leds/leds-bd2802.c index 601185ddabcc28e361b47fd26bcc9b3729f84091..0792ea126cea0d299e7b3401fe20fc2e6a4e750d 100644 --- a/drivers/leds/leds-bd2802.c +++ b/drivers/leds/leds-bd2802.c @@ -786,7 +786,7 @@ static struct i2c_driver bd2802_i2c_driver = { .name = "BD2802", .pm = &bd2802_pm, }, - .probe_new = bd2802_probe, + .probe = bd2802_probe, .remove = bd2802_remove, .id_table = bd2802_id, }; diff --git a/drivers/leds/leds-blinkm.c b/drivers/leds/leds-blinkm.c index 37f2f32ae42d77b9c0cf75943a06dcbbc75cc5c5..2782da1a19307fa18ff73e8ca2cb7f154db7427a 100644 --- a/drivers/leds/leds-blinkm.c +++ b/drivers/leds/leds-blinkm.c @@ -561,7 +561,7 @@ static int blinkm_detect(struct i2c_client *client, struct i2c_board_info *info) return -ENODEV; } - strlcpy(info->type, "blinkm", I2C_NAME_SIZE); + strscpy(info->type, "blinkm", I2C_NAME_SIZE); return 0; } @@ -730,7 +730,7 @@ static struct i2c_driver blinkm_driver = { .driver = { .name = "blinkm", }, - .probe_new = blinkm_probe, + .probe = blinkm_probe, .remove = blinkm_remove, .id_table = blinkm_id, .detect = blinkm_detect, diff --git a/drivers/leds/leds-cht-wcove.c b/drivers/leds/leds-cht-wcove.c new file mode 100644 index 0000000000000000000000000000000000000000..b4998402b8c6f08ac677402c31fef7cafa3e40ce --- /dev/null +++ b/drivers/leds/leds-cht-wcove.c @@ -0,0 +1,476 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Driver for LEDs connected to the Intel Cherry Trail Whiskey Cove PMIC + * + * Copyright 2019 Yauhen Kharuzhy + * Copyright 2023 Hans de Goede + * + * Register info comes from the Lenovo Yoga Book Android opensource code + * available from Lenovo. File lenovo_yb1_x90f_l_osc_201803.7z path in the 7z: + * YB1_source_code/kernel/cht/drivers/misc/charger_gp_led.c + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define CHT_WC_LED1_CTRL 0x5e1f +#define CHT_WC_LED1_FSM 0x5e20 +#define CHT_WC_LED1_PWM 0x5e21 + +#define CHT_WC_LED2_CTRL 0x4fdf +#define CHT_WC_LED2_FSM 0x4fe0 +#define CHT_WC_LED2_PWM 0x4fe1 + +#define CHT_WC_LED1_SWCTL BIT(0) /* HW or SW control of charging led */ +#define CHT_WC_LED1_ON BIT(1) + +#define CHT_WC_LED2_ON BIT(0) +#define CHT_WC_LED_I_MA2_5 (2 << 2) /* LED current limit */ +#define CHT_WC_LED_I_MASK GENMASK(3, 2) /* LED current limit mask */ + +#define CHT_WC_LED_F_1_4_HZ (0 << 4) +#define CHT_WC_LED_F_1_2_HZ (1 << 4) +#define CHT_WC_LED_F_1_HZ (2 << 4) +#define CHT_WC_LED_F_2_HZ (3 << 4) +#define CHT_WC_LED_F_MASK GENMASK(5, 4) + +#define CHT_WC_LED_EFF_OFF (0 << 1) +#define CHT_WC_LED_EFF_ON (1 << 1) +#define CHT_WC_LED_EFF_BLINKING (2 << 1) +#define CHT_WC_LED_EFF_BREATHING (3 << 1) +#define CHT_WC_LED_EFF_MASK GENMASK(2, 1) + +#define CHT_WC_LED_COUNT 2 + +struct cht_wc_led_regs { + /* Register addresses */ + u16 ctrl; + u16 fsm; + u16 pwm; + /* Mask + values for turning the LED on/off */ + u8 on_off_mask; + u8 on_val; + u8 off_val; +}; + +struct cht_wc_led_saved_regs { + unsigned int ctrl; + unsigned int fsm; + unsigned int pwm; +}; + +struct cht_wc_led { + struct led_classdev cdev; + const struct cht_wc_led_regs *regs; + struct regmap *regmap; + struct mutex mutex; + struct cht_wc_led_saved_regs saved_regs; +}; + +struct cht_wc_leds { + struct cht_wc_led leds[CHT_WC_LED_COUNT]; + /* Saved LED1 initial register values */ + struct cht_wc_led_saved_regs led1_initial_regs; +}; + +static const struct cht_wc_led_regs cht_wc_led_regs[CHT_WC_LED_COUNT] = { + { + .ctrl = CHT_WC_LED1_CTRL, + .fsm = CHT_WC_LED1_FSM, + .pwm = CHT_WC_LED1_PWM, + .on_off_mask = CHT_WC_LED1_SWCTL | CHT_WC_LED1_ON, + .on_val = CHT_WC_LED1_SWCTL | CHT_WC_LED1_ON, + .off_val = CHT_WC_LED1_SWCTL, + }, + { + .ctrl = CHT_WC_LED2_CTRL, + .fsm = CHT_WC_LED2_FSM, + .pwm = CHT_WC_LED2_PWM, + .on_off_mask = CHT_WC_LED2_ON, + .on_val = CHT_WC_LED2_ON, + .off_val = 0, + }, +}; + +static const char * const cht_wc_leds_names[CHT_WC_LED_COUNT] = { + "platform::" LED_FUNCTION_CHARGING, + "platform::" LED_FUNCTION_INDICATOR, +}; + +static int cht_wc_leds_brightness_set(struct led_classdev *cdev, + enum led_brightness value) +{ + struct cht_wc_led *led = container_of(cdev, struct cht_wc_led, cdev); + int ret; + + mutex_lock(&led->mutex); + + if (!value) { + ret = regmap_update_bits(led->regmap, led->regs->ctrl, + led->regs->on_off_mask, led->regs->off_val); + if (ret < 0) { + dev_err(cdev->dev, "Failed to turn off: %d\n", ret); + goto out; + } + + /* Disable HW blinking */ + ret = regmap_update_bits(led->regmap, led->regs->fsm, + CHT_WC_LED_EFF_MASK, CHT_WC_LED_EFF_ON); + if (ret < 0) + dev_err(cdev->dev, "Failed to update LED FSM reg: %d\n", ret); + } else { + ret = regmap_write(led->regmap, led->regs->pwm, value); + if (ret < 0) { + dev_err(cdev->dev, "Failed to set brightness: %d\n", ret); + goto out; + } + + ret = regmap_update_bits(led->regmap, led->regs->ctrl, + led->regs->on_off_mask, led->regs->on_val); + if (ret < 0) + dev_err(cdev->dev, "Failed to turn on: %d\n", ret); + } +out: + mutex_unlock(&led->mutex); + return ret; +} + +static enum led_brightness cht_wc_leds_brightness_get(struct led_classdev *cdev) +{ + struct cht_wc_led *led = container_of(cdev, struct cht_wc_led, cdev); + unsigned int val; + int ret; + + mutex_lock(&led->mutex); + + ret = regmap_read(led->regmap, led->regs->ctrl, &val); + if (ret < 0) { + dev_err(cdev->dev, "Failed to read LED CTRL reg: %d\n", ret); + ret = 0; + goto done; + } + + val &= led->regs->on_off_mask; + if (val != led->regs->on_val) { + ret = 0; + goto done; + } + + ret = regmap_read(led->regmap, led->regs->pwm, &val); + if (ret < 0) { + dev_err(cdev->dev, "Failed to read LED PWM reg: %d\n", ret); + ret = 0; + goto done; + } + + ret = val; +done: + mutex_unlock(&led->mutex); + + return ret; +} + +/* Return blinking period for given CTRL reg value */ +static unsigned long cht_wc_leds_get_period(int ctrl) +{ + ctrl &= CHT_WC_LED_F_MASK; + + switch (ctrl) { + case CHT_WC_LED_F_1_4_HZ: + return 1000 * 4; + case CHT_WC_LED_F_1_2_HZ: + return 1000 * 2; + case CHT_WC_LED_F_1_HZ: + return 1000; + case CHT_WC_LED_F_2_HZ: + return 1000 / 2; + } + + return 0; +} + +/* + * Find suitable hardware blink mode for given period. + * period < 750 ms - select 2 HZ + * 750 ms <= period < 1500 ms - select 1 HZ + * 1500 ms <= period < 3000 ms - select 1/2 HZ + * 3000 ms <= period < 5000 ms - select 1/4 HZ + * 5000 ms <= period - return -1 + */ +static int cht_wc_leds_find_freq(unsigned long period) +{ + if (period < 750) + return CHT_WC_LED_F_2_HZ; + else if (period < 1500) + return CHT_WC_LED_F_1_HZ; + else if (period < 3000) + return CHT_WC_LED_F_1_2_HZ; + else if (period < 5000) + return CHT_WC_LED_F_1_4_HZ; + else + return -1; +} + +static int cht_wc_leds_set_effect(struct led_classdev *cdev, + unsigned long *delay_on, + unsigned long *delay_off, + u8 effect) +{ + struct cht_wc_led *led = container_of(cdev, struct cht_wc_led, cdev); + int ctrl, ret; + + mutex_lock(&led->mutex); + + /* Blink with 1 Hz as default if nothing specified */ + if (!*delay_on && !*delay_off) + *delay_on = *delay_off = 500; + + ctrl = cht_wc_leds_find_freq(*delay_on + *delay_off); + if (ctrl < 0) { + /* Disable HW blinking */ + ret = regmap_update_bits(led->regmap, led->regs->fsm, + CHT_WC_LED_EFF_MASK, CHT_WC_LED_EFF_ON); + if (ret < 0) + dev_err(cdev->dev, "Failed to update LED FSM reg: %d\n", ret); + + /* Fallback to software timer */ + *delay_on = *delay_off = 0; + ret = -EINVAL; + goto done; + } + + ret = regmap_update_bits(led->regmap, led->regs->fsm, + CHT_WC_LED_EFF_MASK, effect); + if (ret < 0) + dev_err(cdev->dev, "Failed to update LED FSM reg: %d\n", ret); + + /* Set the frequency and make sure the LED is on */ + ret = regmap_update_bits(led->regmap, led->regs->ctrl, + CHT_WC_LED_F_MASK | led->regs->on_off_mask, + ctrl | led->regs->on_val); + if (ret < 0) + dev_err(cdev->dev, "Failed to update LED CTRL reg: %d\n", ret); + + *delay_off = *delay_on = cht_wc_leds_get_period(ctrl) / 2; + +done: + mutex_unlock(&led->mutex); + + return ret; +} + +static int cht_wc_leds_blink_set(struct led_classdev *cdev, + unsigned long *delay_on, + unsigned long *delay_off) +{ + u8 effect = CHT_WC_LED_EFF_BLINKING; + + /* + * The desired default behavior of LED1 / the charge LED is breathing + * while charging and on/solid when full. Since triggers cannot select + * breathing, blink_set() gets called when charging. Use slow breathing + * when the default "charging-blink-full-solid" trigger is used to + * achieve the desired default behavior. + */ + if (cdev->flags & LED_INIT_DEFAULT_TRIGGER) { + *delay_on = *delay_off = 1000; + effect = CHT_WC_LED_EFF_BREATHING; + } + + return cht_wc_leds_set_effect(cdev, delay_on, delay_off, effect); +} + +static int cht_wc_leds_pattern_set(struct led_classdev *cdev, + struct led_pattern *pattern, + u32 len, int repeat) +{ + unsigned long delay_off, delay_on; + + if (repeat > 0 || len != 2 || + pattern[0].brightness != 0 || pattern[1].brightness != 1 || + pattern[0].delta_t != pattern[1].delta_t || + (pattern[0].delta_t != 250 && pattern[0].delta_t != 500 && + pattern[0].delta_t != 1000 && pattern[0].delta_t != 2000)) + return -EINVAL; + + delay_off = pattern[0].delta_t; + delay_on = pattern[1].delta_t; + + return cht_wc_leds_set_effect(cdev, &delay_on, &delay_off, CHT_WC_LED_EFF_BREATHING); +} + +static int cht_wc_leds_pattern_clear(struct led_classdev *cdev) +{ + return cht_wc_leds_brightness_set(cdev, 0); +} + +static int cht_wc_led_save_regs(struct cht_wc_led *led, + struct cht_wc_led_saved_regs *saved_regs) +{ + int ret; + + ret = regmap_read(led->regmap, led->regs->ctrl, &saved_regs->ctrl); + if (ret < 0) + return ret; + + ret = regmap_read(led->regmap, led->regs->fsm, &saved_regs->fsm); + if (ret < 0) + return ret; + + return regmap_read(led->regmap, led->regs->pwm, &saved_regs->pwm); +} + +static void cht_wc_led_restore_regs(struct cht_wc_led *led, + const struct cht_wc_led_saved_regs *saved_regs) +{ + regmap_write(led->regmap, led->regs->ctrl, saved_regs->ctrl); + regmap_write(led->regmap, led->regs->fsm, saved_regs->fsm); + regmap_write(led->regmap, led->regs->pwm, saved_regs->pwm); +} + +static int cht_wc_leds_probe(struct platform_device *pdev) +{ + struct intel_soc_pmic *pmic = dev_get_drvdata(pdev->dev.parent); + struct cht_wc_leds *leds; + int ret; + int i; + + /* + * On the Lenovo Yoga Tab 3 the LED1 driver output is actually + * connected to a haptic feedback motor rather then a LED. + * So do not register a LED classdev there (LED2 is unused). + */ + if (pmic->cht_wc_model == INTEL_CHT_WC_LENOVO_YT3_X90) + return -ENODEV; + + leds = devm_kzalloc(&pdev->dev, sizeof(*leds), GFP_KERNEL); + if (!leds) + return -ENOMEM; + + /* + * LED1 might be in hw-controlled mode when this driver gets loaded; and + * since the PMIC is always powered by the battery any changes made are + * permanent. Save LED1 regs to restore them on remove() or shutdown(). + */ + leds->leds[0].regs = &cht_wc_led_regs[0]; + leds->leds[0].regmap = pmic->regmap; + ret = cht_wc_led_save_regs(&leds->leds[0], &leds->led1_initial_regs); + if (ret < 0) + return ret; + + /* Set LED1 default trigger based on machine model */ + switch (pmic->cht_wc_model) { + case INTEL_CHT_WC_GPD_WIN_POCKET: + leds->leds[0].cdev.default_trigger = "max170xx_battery-charging-blink-full-solid"; + break; + case INTEL_CHT_WC_XIAOMI_MIPAD2: + leds->leds[0].cdev.default_trigger = "bq27520-0-charging-blink-full-solid"; + break; + case INTEL_CHT_WC_LENOVO_YOGABOOK1: + leds->leds[0].cdev.default_trigger = "bq27542-0-charging-blink-full-solid"; + break; + default: + dev_warn(&pdev->dev, "Unknown model, no default charging trigger\n"); + break; + } + + for (i = 0; i < CHT_WC_LED_COUNT; i++) { + struct cht_wc_led *led = &leds->leds[i]; + + led->regs = &cht_wc_led_regs[i]; + led->regmap = pmic->regmap; + mutex_init(&led->mutex); + led->cdev.name = cht_wc_leds_names[i]; + led->cdev.brightness_set_blocking = cht_wc_leds_brightness_set; + led->cdev.brightness_get = cht_wc_leds_brightness_get; + led->cdev.blink_set = cht_wc_leds_blink_set; + led->cdev.pattern_set = cht_wc_leds_pattern_set; + led->cdev.pattern_clear = cht_wc_leds_pattern_clear; + led->cdev.max_brightness = 255; + + ret = led_classdev_register(&pdev->dev, &led->cdev); + if (ret < 0) + return ret; + } + + platform_set_drvdata(pdev, leds); + return 0; +} + +static void cht_wc_leds_remove(struct platform_device *pdev) +{ + struct cht_wc_leds *leds = platform_get_drvdata(pdev); + int i; + + for (i = 0; i < CHT_WC_LED_COUNT; i++) + led_classdev_unregister(&leds->leds[i].cdev); + + /* Restore LED1 regs if hw-control was active else leave LED1 off */ + if (!(leds->led1_initial_regs.ctrl & CHT_WC_LED1_SWCTL)) + cht_wc_led_restore_regs(&leds->leds[0], &leds->led1_initial_regs); +} + +static void cht_wc_leds_disable(struct platform_device *pdev) +{ + struct cht_wc_leds *leds = platform_get_drvdata(pdev); + int i; + + for (i = 0; i < CHT_WC_LED_COUNT; i++) + cht_wc_leds_brightness_set(&leds->leds[i].cdev, 0); + + /* Restore LED1 regs if hw-control was active else leave LED1 off */ + if (!(leds->led1_initial_regs.ctrl & CHT_WC_LED1_SWCTL)) + cht_wc_led_restore_regs(&leds->leds[0], &leds->led1_initial_regs); +} + +/* On suspend save current settings and turn LEDs off */ +static int cht_wc_leds_suspend(struct device *dev) +{ + struct cht_wc_leds *leds = dev_get_drvdata(dev); + int i, ret; + + for (i = 0; i < CHT_WC_LED_COUNT; i++) { + ret = cht_wc_led_save_regs(&leds->leds[i], &leds->leds[i].saved_regs); + if (ret < 0) + return ret; + } + + cht_wc_leds_disable(to_platform_device(dev)); + return 0; +} + +/* On resume restore the saved settings */ +static int cht_wc_leds_resume(struct device *dev) +{ + struct cht_wc_leds *leds = dev_get_drvdata(dev); + int i; + + for (i = 0; i < CHT_WC_LED_COUNT; i++) + cht_wc_led_restore_regs(&leds->leds[i], &leds->leds[i].saved_regs); + + return 0; +} + +static DEFINE_SIMPLE_DEV_PM_OPS(cht_wc_leds_pm, cht_wc_leds_suspend, cht_wc_leds_resume); + +static struct platform_driver cht_wc_leds_driver = { + .probe = cht_wc_leds_probe, + .remove_new = cht_wc_leds_remove, + .shutdown = cht_wc_leds_disable, + .driver = { + .name = "cht_wcove_leds", + .pm = pm_sleep_ptr(&cht_wc_leds_pm), + }, +}; +module_platform_driver(cht_wc_leds_driver); + +MODULE_ALIAS("platform:cht_wcove_leds"); +MODULE_DESCRIPTION("Intel Cherry Trail Whiskey Cove PMIC LEDs driver"); +MODULE_AUTHOR("Yauhen Kharuzhy "); +MODULE_LICENSE("GPL"); diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c index ce4e79939731d89d69effdb610ac7cbdfd1d28b0..7bfe40a6bfddfa967740e09d2768d6bc3b235497 100644 --- a/drivers/leds/leds-gpio.c +++ b/drivers/leds/leds-gpio.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -77,6 +78,7 @@ static int create_gpio_led(const struct gpio_led *template, struct fwnode_handle *fwnode, gpio_blink_set_t blink_set) { struct led_init_data init_data = {}; + struct pinctrl *pinctrl; int ret, state; led_dat->cdev.default_trigger = template->default_trigger; @@ -119,6 +121,22 @@ static int create_gpio_led(const struct gpio_led *template, &init_data); } + if (ret) + return ret; + + pinctrl = devm_pinctrl_get_select_default(led_dat->cdev.dev); + if (IS_ERR(pinctrl)) { + ret = PTR_ERR(pinctrl); + if (ret != -ENODEV) { + dev_warn(led_dat->cdev.dev, + "Failed to select %pOF pinctrl: %d\n", + to_of_node(fwnode), ret); + } else { + /* pinctrl-%d not present, not an error */ + ret = 0; + } + } + return ret; } diff --git a/drivers/leds/leds-is31fl319x.c b/drivers/leds/leds-is31fl319x.c index 7c908414ac7e0c468a0cb401a7629e5e9948f0a7..66c65741202e902dd2835db97af20b07ba01de72 100644 --- a/drivers/leds/leds-is31fl319x.c +++ b/drivers/leds/leds-is31fl319x.c @@ -602,7 +602,7 @@ static struct i2c_driver is31fl319x_driver = { .name = "leds-is31fl319x", .of_match_table = of_is31fl319x_match, }, - .probe_new = is31fl319x_probe, + .probe = is31fl319x_probe, .id_table = is31fl319x_id, }; diff --git a/drivers/leds/leds-is31fl32xx.c b/drivers/leds/leds-is31fl32xx.c index 799191859ce07add2db903cf821bd83d97efbed1..72cb56d305c433d0540a6ae8212760ed572ddc98 100644 --- a/drivers/leds/leds-is31fl32xx.c +++ b/drivers/leds/leds-is31fl32xx.c @@ -488,7 +488,7 @@ static struct i2c_driver is31fl32xx_driver = { .name = "is31fl32xx", .of_match_table = of_is31fl32xx_match, }, - .probe_new = is31fl32xx_probe, + .probe = is31fl32xx_probe, .remove = is31fl32xx_remove, .id_table = is31fl32xx_id, }; diff --git a/drivers/leds/leds-lm3530.c b/drivers/leds/leds-lm3530.c index a9a2018592ffcc5f39b21196d9c22596e14d6e1a..a2feef8e4ac5ff86364c00dde96b11dc1cf2e85f 100644 --- a/drivers/leds/leds-lm3530.c +++ b/drivers/leds/leds-lm3530.c @@ -484,7 +484,7 @@ static const struct i2c_device_id lm3530_id[] = { MODULE_DEVICE_TABLE(i2c, lm3530_id); static struct i2c_driver lm3530_i2c_driver = { - .probe_new = lm3530_probe, + .probe = lm3530_probe, .remove = lm3530_remove, .id_table = lm3530_id, .driver = { diff --git a/drivers/leds/leds-lm3532.c b/drivers/leds/leds-lm3532.c index a08c09129a68b3c77e5b6b7a67c17b6c7c15c56a..13662a4aa1f2658200fbdeeaa2d8b6118f701a7b 100644 --- a/drivers/leds/leds-lm3532.c +++ b/drivers/leds/leds-lm3532.c @@ -726,7 +726,7 @@ static const struct i2c_device_id lm3532_id[] = { MODULE_DEVICE_TABLE(i2c, lm3532_id); static struct i2c_driver lm3532_i2c_driver = { - .probe_new = lm3532_probe, + .probe = lm3532_probe, .remove = lm3532_remove, .id_table = lm3532_id, .driver = { diff --git a/drivers/leds/leds-lm355x.c b/drivers/leds/leds-lm355x.c index 612873070ca48e3202715dae59db4d76f67f2403..f68771b9eac6bb30eaa2db471e11c5daa599ded2 100644 --- a/drivers/leds/leds-lm355x.c +++ b/drivers/leds/leds-lm355x.c @@ -516,7 +516,7 @@ static struct i2c_driver lm355x_i2c_driver = { .name = LM355x_NAME, .pm = NULL, }, - .probe_new = lm355x_probe, + .probe = lm355x_probe, .remove = lm355x_remove, .id_table = lm355x_id, }; diff --git a/drivers/leds/leds-lm3642.c b/drivers/leds/leds-lm3642.c index b75ee3546c2ec7fa1e5304a95ba501497153caaa..6eee52e211be738897ed8218b1323903f97a1816 100644 --- a/drivers/leds/leds-lm3642.c +++ b/drivers/leds/leds-lm3642.c @@ -401,7 +401,7 @@ static struct i2c_driver lm3642_i2c_driver = { .name = LM3642_NAME, .pm = NULL, }, - .probe_new = lm3642_probe, + .probe = lm3642_probe, .remove = lm3642_remove, .id_table = lm3642_id, }; diff --git a/drivers/leds/leds-lm3692x.c b/drivers/leds/leds-lm3692x.c index 66126d0666f5bfd3b5833cf9ab0f7aab7aa8695c..f8ad61e47a19299b9d456db8583676b5ea03307c 100644 --- a/drivers/leds/leds-lm3692x.c +++ b/drivers/leds/leds-lm3692x.c @@ -518,7 +518,7 @@ static struct i2c_driver lm3692x_driver = { .name = "lm3692x", .of_match_table = of_lm3692x_leds_match, }, - .probe_new = lm3692x_probe, + .probe = lm3692x_probe, .remove = lm3692x_remove, .id_table = lm3692x_id, }; diff --git a/drivers/leds/leds-lm3697.c b/drivers/leds/leds-lm3697.c index 10e904bf40a046e69e6a1f7221d15280b40fc733..cfb8ac220db6da36971d6c4ac9e25427d67b3178 100644 --- a/drivers/leds/leds-lm3697.c +++ b/drivers/leds/leds-lm3697.c @@ -376,7 +376,7 @@ static struct i2c_driver lm3697_driver = { .name = "lm3697", .of_match_table = of_lm3697_leds_match, }, - .probe_new = lm3697_probe, + .probe = lm3697_probe, .remove = lm3697_remove, .id_table = lm3697_id, }; diff --git a/drivers/leds/leds-lp3944.c b/drivers/leds/leds-lp3944.c index be47c66b2e00bd6a44d2889bc1193428521fb88b..8ea746c499d196a9c0a22e2fbbc8c8e831fc82e3 100644 --- a/drivers/leds/leds-lp3944.c +++ b/drivers/leds/leds-lp3944.c @@ -427,7 +427,7 @@ static struct i2c_driver lp3944_driver = { .driver = { .name = "lp3944", }, - .probe_new = lp3944_probe, + .probe = lp3944_probe, .remove = lp3944_remove, .id_table = lp3944_id, }; diff --git a/drivers/leds/leds-lp3952.c b/drivers/leds/leds-lp3952.c index 24b2e0f9080d95b794c4d78547651a4df7d0c9d7..3bd55652a706ce1b14572c18c4c8fc92be0de9e1 100644 --- a/drivers/leds/leds-lp3952.c +++ b/drivers/leds/leds-lp3952.c @@ -273,7 +273,7 @@ static struct i2c_driver lp3952_i2c_driver = { .driver = { .name = LP3952_NAME, }, - .probe_new = lp3952_probe, + .probe = lp3952_probe, .remove = lp3952_remove, .id_table = lp3952_id, }; diff --git a/drivers/leds/leds-lp50xx.c b/drivers/leds/leds-lp50xx.c index 28d6b39fa72dbcb04857d63d51c36e4ef53d5c03..68c4d9967d6831c5bf1a64c7836f328c62c0b1c8 100644 --- a/drivers/leds/leds-lp50xx.c +++ b/drivers/leds/leds-lp50xx.c @@ -608,7 +608,7 @@ static struct i2c_driver lp50xx_driver = { .name = "lp50xx", .of_match_table = of_lp50xx_leds_match, }, - .probe_new = lp50xx_probe, + .probe = lp50xx_probe, .remove = lp50xx_remove, .id_table = lp50xx_id, }; diff --git a/drivers/leds/leds-lp5521.c b/drivers/leds/leds-lp5521.c index a004af8e22c742396b8a227ccb589c0a75a61a1a..030c040fdf6d69e899ef7bca995b058275c57fb5 100644 --- a/drivers/leds/leds-lp5521.c +++ b/drivers/leds/leds-lp5521.c @@ -58,14 +58,11 @@ /* CONFIG register */ #define LP5521_PWM_HF 0x40 /* PWM: 0 = 256Hz, 1 = 558Hz */ #define LP5521_PWRSAVE_EN 0x20 /* 1 = Power save mode */ -#define LP5521_CP_MODE_OFF 0 /* Charge pump (CP) off */ -#define LP5521_CP_MODE_BYPASS 8 /* CP forced to bypass mode */ -#define LP5521_CP_MODE_1X5 0x10 /* CP forced to 1.5x mode */ -#define LP5521_CP_MODE_AUTO 0x18 /* Automatic mode selection */ +#define LP5521_CP_MODE_MASK 0x18 /* Charge pump mode */ +#define LP5521_CP_MODE_SHIFT 3 #define LP5521_R_TO_BATT 0x04 /* R out: 0 = CP, 1 = Vbat */ #define LP5521_CLK_INT 0x01 /* Internal clock */ -#define LP5521_DEFAULT_CFG \ - (LP5521_PWM_HF | LP5521_PWRSAVE_EN | LP5521_CP_MODE_AUTO) +#define LP5521_DEFAULT_CFG (LP5521_PWM_HF | LP5521_PWRSAVE_EN) /* Status */ #define LP5521_EXT_CLK_USED 0x08 @@ -310,6 +307,8 @@ static int lp5521_post_init_device(struct lp55xx_chip *chip) if (!lp55xx_is_extclk_used(chip)) val |= LP5521_CLK_INT; + val |= (chip->pdata->charge_pump_mode << LP5521_CP_MODE_SHIFT) & LP5521_CP_MODE_MASK; + ret = lp55xx_write(chip, LP5521_REG_CONFIG, val); if (ret) return ret; @@ -608,7 +607,7 @@ static struct i2c_driver lp5521_driver = { .name = "lp5521", .of_match_table = of_match_ptr(of_lp5521_leds_match), }, - .probe_new = lp5521_probe, + .probe = lp5521_probe, .remove = lp5521_remove, .id_table = lp5521_id, }; diff --git a/drivers/leds/leds-lp5523.c b/drivers/leds/leds-lp5523.c index 55da914b8e5cac2931a6789c86538b89c5cfa612..daa6a165fba6be5231258c38c2f2ab85c55a7eff 100644 --- a/drivers/leds/leds-lp5523.c +++ b/drivers/leds/leds-lp5523.c @@ -57,8 +57,11 @@ #define LP5523_AUTO_INC 0x40 #define LP5523_PWR_SAVE 0x20 #define LP5523_PWM_PWR_SAVE 0x04 -#define LP5523_CP_AUTO 0x18 +#define LP5523_CP_MODE_MASK 0x18 +#define LP5523_CP_MODE_SHIFT 3 #define LP5523_AUTO_CLK 0x02 +#define LP5523_DEFAULT_CONFIG \ + (LP5523_AUTO_INC | LP5523_PWR_SAVE | LP5523_AUTO_CLK | LP5523_PWM_PWR_SAVE) #define LP5523_EN_LEDTEST 0x80 #define LP5523_LEDTEST_DONE 0x80 @@ -125,6 +128,7 @@ static void lp5523_set_led_current(struct lp55xx_led *led, u8 led_current) static int lp5523_post_init_device(struct lp55xx_chip *chip) { int ret; + int val; ret = lp55xx_write(chip, LP5523_REG_ENABLE, LP5523_ENABLE); if (ret) @@ -133,10 +137,10 @@ static int lp5523_post_init_device(struct lp55xx_chip *chip) /* Chip startup time is 500 us, 1 - 2 ms gives some margin */ usleep_range(1000, 2000); - ret = lp55xx_write(chip, LP5523_REG_CONFIG, - LP5523_AUTO_INC | LP5523_PWR_SAVE | - LP5523_CP_AUTO | LP5523_AUTO_CLK | - LP5523_PWM_PWR_SAVE); + val = LP5523_DEFAULT_CONFIG; + val |= (chip->pdata->charge_pump_mode << LP5523_CP_MODE_SHIFT) & LP5523_CP_MODE_MASK; + + ret = lp55xx_write(chip, LP5523_REG_CONFIG, val); if (ret) return ret; @@ -983,7 +987,7 @@ static struct i2c_driver lp5523_driver = { .name = "lp5523x", .of_match_table = of_match_ptr(of_lp5523_leds_match), }, - .probe_new = lp5523_probe, + .probe = lp5523_probe, .remove = lp5523_remove, .id_table = lp5523_id, }; diff --git a/drivers/leds/leds-lp5562.c b/drivers/leds/leds-lp5562.c index b5d877faf6d731589fe685c8ec3f60d4d8ee9311..4565cc12cea80031da2bf5a9a3da25384f5c76bc 100644 --- a/drivers/leds/leds-lp5562.c +++ b/drivers/leds/leds-lp5562.c @@ -603,7 +603,7 @@ static struct i2c_driver lp5562_driver = { .name = "lp5562", .of_match_table = of_match_ptr(of_lp5562_leds_match), }, - .probe_new = lp5562_probe, + .probe = lp5562_probe, .remove = lp5562_remove, .id_table = lp5562_id, }; diff --git a/drivers/leds/leds-lp55xx-common.c b/drivers/leds/leds-lp55xx-common.c index c1940964067af8c09450a87bdc658b542cbdd0f0..77bb26906ea6e43ac1318f38cac8939c057b567d 100644 --- a/drivers/leds/leds-lp55xx-common.c +++ b/drivers/leds/leds-lp55xx-common.c @@ -18,6 +18,7 @@ #include #include #include +#include #include "leds-lp55xx-common.h" @@ -691,6 +692,14 @@ struct lp55xx_platform_data *lp55xx_of_populate_pdata(struct device *dev, i++; } + if (of_property_read_u32(np, "ti,charge-pump-mode", &pdata->charge_pump_mode)) + pdata->charge_pump_mode = LP55XX_CP_AUTO; + + if (pdata->charge_pump_mode > LP55XX_CP_AUTO) { + dev_err(dev, "invalid charge pump mode %d\n", pdata->charge_pump_mode); + return ERR_PTR(-EINVAL); + } + of_property_read_string(np, "label", &pdata->label); of_property_read_u8(np, "clock-mode", &pdata->clock_mode); diff --git a/drivers/leds/leds-lp8501.c b/drivers/leds/leds-lp8501.c index 165d6423a928d8e8b747aa726fdee96884585d48..f11886aa8965dfa3c8b0ee250ae273604fff4f6a 100644 --- a/drivers/leds/leds-lp8501.c +++ b/drivers/leds/leds-lp8501.c @@ -53,10 +53,10 @@ #define LP8501_PWM_PSAVE BIT(7) #define LP8501_AUTO_INC BIT(6) #define LP8501_PWR_SAVE BIT(5) -#define LP8501_CP_AUTO 0x18 +#define LP8501_CP_MODE_MASK 0x18 +#define LP8501_CP_MODE_SHIFT 3 #define LP8501_INT_CLK BIT(0) -#define LP8501_DEFAULT_CFG \ - (LP8501_PWM_PSAVE | LP8501_AUTO_INC | LP8501_PWR_SAVE | LP8501_CP_AUTO) +#define LP8501_DEFAULT_CFG (LP8501_PWM_PSAVE | LP8501_AUTO_INC | LP8501_PWR_SAVE) #define LP8501_REG_RESET 0x3D #define LP8501_RESET 0xFF @@ -102,6 +102,8 @@ static int lp8501_post_init_device(struct lp55xx_chip *chip) if (chip->pdata->clock_mode != LP55XX_CLOCK_EXT) val |= LP8501_INT_CLK; + val |= (chip->pdata->charge_pump_mode << LP8501_CP_MODE_SHIFT) & LP8501_CP_MODE_MASK; + ret = lp55xx_write(chip, LP8501_REG_CONFIG, val); if (ret) return ret; @@ -392,7 +394,7 @@ static struct i2c_driver lp8501_driver = { .name = "lp8501", .of_match_table = of_match_ptr(of_lp8501_leds_match), }, - .probe_new = lp8501_probe, + .probe = lp8501_probe, .remove = lp8501_remove, .id_table = lp8501_id, }; diff --git a/drivers/leds/leds-lp8860.c b/drivers/leds/leds-lp8860.c index 221b386443bce9eed8bd9f1e5e9d049f5493bb09..19b621012e582fce00c983e3e2b4b2e20f09f14c 100644 --- a/drivers/leds/leds-lp8860.c +++ b/drivers/leds/leds-lp8860.c @@ -475,7 +475,7 @@ static struct i2c_driver lp8860_driver = { .name = "lp8860", .of_match_table = of_lp8860_leds_match, }, - .probe_new = lp8860_probe, + .probe = lp8860_probe, .remove = lp8860_remove, .id_table = lp8860_id, }; diff --git a/drivers/leds/leds-mt6323.c b/drivers/leds/leds-mt6323.c index 17ee88043f5296ca1fb774197c58651d455f70b9..24f35bdb55fbf3cfb533afe90f18f54251373be5 100644 --- a/drivers/leds/leds-mt6323.c +++ b/drivers/leds/leds-mt6323.c @@ -14,61 +14,54 @@ #include /* - * Register field for MT6323_TOP_CKPDN0 to enable + * Register field for TOP_CKPDN0 to enable * 32K clock common for LED device. */ -#define MT6323_RG_DRV_32K_CK_PDN BIT(11) -#define MT6323_RG_DRV_32K_CK_PDN_MASK BIT(11) +#define RG_DRV_32K_CK_PDN BIT(11) +#define RG_DRV_32K_CK_PDN_MASK BIT(11) + +/* 32K/1M/6M clock common for WLED device */ +#define RG_VWLED_1M_CK_PDN BIT(0) +#define RG_VWLED_32K_CK_PDN BIT(12) +#define RG_VWLED_6M_CK_PDN BIT(13) /* - * Register field for MT6323_TOP_CKPDN2 to enable + * Register field for TOP_CKPDN2 to enable * individual clock for LED device. */ -#define MT6323_RG_ISINK_CK_PDN(i) BIT(i) -#define MT6323_RG_ISINK_CK_PDN_MASK(i) BIT(i) +#define RG_ISINK_CK_PDN(i) BIT(i) +#define RG_ISINK_CK_PDN_MASK(i) BIT(i) /* - * Register field for MT6323_TOP_CKCON1 to select + * Register field for TOP_CKCON1 to select * clock source. */ -#define MT6323_RG_ISINK_CK_SEL_MASK(i) (BIT(10) << (i)) +#define RG_ISINK_CK_SEL_MASK(i) (BIT(10) << (i)) -/* - * Register for MT6323_ISINK_CON0 to setup the - * duty cycle of the blink. - */ -#define MT6323_ISINK_CON0(i) (MT6323_ISINK0_CON0 + 0x8 * (i)) -#define MT6323_ISINK_DIM_DUTY_MASK (0x1f << 8) -#define MT6323_ISINK_DIM_DUTY(i) (((i) << 8) & \ - MT6323_ISINK_DIM_DUTY_MASK) - -/* Register to setup the period of the blink. */ -#define MT6323_ISINK_CON1(i) (MT6323_ISINK0_CON1 + 0x8 * (i)) -#define MT6323_ISINK_DIM_FSEL_MASK (0xffff) -#define MT6323_ISINK_DIM_FSEL(i) ((i) & MT6323_ISINK_DIM_FSEL_MASK) - -/* Register to control the brightness. */ -#define MT6323_ISINK_CON2(i) (MT6323_ISINK0_CON2 + 0x8 * (i)) -#define MT6323_ISINK_CH_STEP_SHIFT 12 -#define MT6323_ISINK_CH_STEP_MASK (0x7 << 12) -#define MT6323_ISINK_CH_STEP(i) (((i) << 12) & \ - MT6323_ISINK_CH_STEP_MASK) -#define MT6323_ISINK_SFSTR0_TC_MASK (0x3 << 1) -#define MT6323_ISINK_SFSTR0_TC(i) (((i) << 1) & \ - MT6323_ISINK_SFSTR0_TC_MASK) -#define MT6323_ISINK_SFSTR0_EN_MASK BIT(0) -#define MT6323_ISINK_SFSTR0_EN BIT(0) +#define ISINK_CON(r, i) (r + 0x8 * (i)) + +/* ISINK_CON0: Register to setup the duty cycle of the blink. */ +#define ISINK_DIM_DUTY_MASK (0x1f << 8) +#define ISINK_DIM_DUTY(i) (((i) << 8) & ISINK_DIM_DUTY_MASK) + +/* ISINK_CON1: Register to setup the period of the blink. */ +#define ISINK_DIM_FSEL_MASK (0xffff) +#define ISINK_DIM_FSEL(i) ((i) & ISINK_DIM_FSEL_MASK) + +/* ISINK_CON2: Register to control the brightness. */ +#define ISINK_CH_STEP_SHIFT 12 +#define ISINK_CH_STEP_MASK (0x7 << 12) +#define ISINK_CH_STEP(i) (((i) << 12) & ISINK_CH_STEP_MASK) +#define ISINK_SFSTR0_TC_MASK (0x3 << 1) +#define ISINK_SFSTR0_TC(i) (((i) << 1) & ISINK_SFSTR0_TC_MASK) +#define ISINK_SFSTR0_EN_MASK BIT(0) +#define ISINK_SFSTR0_EN BIT(0) /* Register to LED channel enablement. */ -#define MT6323_ISINK_CH_EN_MASK(i) BIT(i) -#define MT6323_ISINK_CH_EN(i) BIT(i) +#define ISINK_CH_EN_MASK(i) BIT(i) +#define ISINK_CH_EN(i) BIT(i) -#define MT6323_MAX_PERIOD 10000 -#define MT6323_MAX_LEDS 4 -#define MT6323_MAX_BRIGHTNESS 6 -#define MT6323_UNIT_DUTY 3125 -#define MT6323_CAL_HW_DUTY(o, p) DIV_ROUND_CLOSEST((o) * 100000ul,\ - (p) * MT6323_UNIT_DUTY) +#define MAX_SUPPORTED_LEDS 8 struct mt6323_leds; @@ -86,12 +79,63 @@ struct mt6323_led { enum led_brightness current_brightness; }; +/** + * struct mt6323_regs - register spec for the LED device + * @top_ckpdn: Offset to ISINK_CKPDN[0..x] registers + * @num_top_ckpdn: Number of ISINK_CKPDN registers + * @top_ckcon: Offset to ISINK_CKCON[0..x] registers + * @num_top_ckcon: Number of ISINK_CKCON registers + * @isink_con: Offset to ISINKx_CON[0..x] registers + * @num_isink_con: Number of ISINKx_CON registers + * @isink_max_regs: Number of ISINK[0..x] registers + * @isink_en_ctrl: Offset to ISINK_EN_CTRL register + * @iwled_en_ctrl: Offset to IWLED_EN_CTRL register + */ +struct mt6323_regs { + const u16 *top_ckpdn; + u8 num_top_ckpdn; + const u16 *top_ckcon; + u8 num_top_ckcon; + const u16 *isink_con; + u8 num_isink_con; + u8 isink_max_regs; + u16 isink_en_ctrl; + u16 iwled_en_ctrl; +}; + +/** + * struct mt6323_hwspec - hardware specific parameters + * @max_period: Maximum period for all LEDs + * @max_leds: Maximum number of supported LEDs + * @max_wleds: Maximum number of WLEDs + * @max_brightness: Maximum brightness for all LEDs + * @unit_duty: Steps of duty per period + */ +struct mt6323_hwspec { + u16 max_period; + u8 max_leds; + u8 max_wleds; + u16 max_brightness; + u16 unit_duty; +}; + +/** + * struct mt6323_data - device specific data + * @regs: Register spec for this device + * @spec: Hardware specific parameters + */ +struct mt6323_data { + const struct mt6323_regs *regs; + const struct mt6323_hwspec *spec; +}; + /** * struct mt6323_leds - state container for holding LED controller * of the driver * @dev: the device pointer * @hw: the underlying hardware providing shared * bus for the register operations + * @pdata: device specific data * @lock: the lock among process context * @led: the array that contains the state of individual * LED device @@ -99,9 +143,10 @@ struct mt6323_led { struct mt6323_leds { struct device *dev; struct mt6397_chip *hw; + const struct mt6323_data *pdata; /* protect among process context */ struct mutex lock; - struct mt6323_led *led[MT6323_MAX_LEDS]; + struct mt6323_led *led[MAX_SUPPORTED_LEDS]; }; static int mt6323_led_hw_brightness(struct led_classdev *cdev, @@ -109,6 +154,7 @@ static int mt6323_led_hw_brightness(struct led_classdev *cdev, { struct mt6323_led *led = container_of(cdev, struct mt6323_led, cdev); struct mt6323_leds *leds = led->parent; + const struct mt6323_regs *regs = leds->pdata->regs; struct regmap *regmap = leds->hw->regmap; u32 con2_mask = 0, con2_val = 0; int ret; @@ -117,14 +163,14 @@ static int mt6323_led_hw_brightness(struct led_classdev *cdev, * Setup current output for the corresponding * brightness level. */ - con2_mask |= MT6323_ISINK_CH_STEP_MASK | - MT6323_ISINK_SFSTR0_TC_MASK | - MT6323_ISINK_SFSTR0_EN_MASK; - con2_val |= MT6323_ISINK_CH_STEP(brightness - 1) | - MT6323_ISINK_SFSTR0_TC(2) | - MT6323_ISINK_SFSTR0_EN; - - ret = regmap_update_bits(regmap, MT6323_ISINK_CON2(led->id), + con2_mask |= ISINK_CH_STEP_MASK | + ISINK_SFSTR0_TC_MASK | + ISINK_SFSTR0_EN_MASK; + con2_val |= ISINK_CH_STEP(brightness - 1) | + ISINK_SFSTR0_TC(2) | + ISINK_SFSTR0_EN; + + ret = regmap_update_bits(regmap, ISINK_CON(regs->isink_con[2], led->id), con2_mask, con2_val); return ret; } @@ -133,20 +179,21 @@ static int mt6323_led_hw_off(struct led_classdev *cdev) { struct mt6323_led *led = container_of(cdev, struct mt6323_led, cdev); struct mt6323_leds *leds = led->parent; + const struct mt6323_regs *regs = leds->pdata->regs; struct regmap *regmap = leds->hw->regmap; unsigned int status; int ret; - status = MT6323_ISINK_CH_EN(led->id); - ret = regmap_update_bits(regmap, MT6323_ISINK_EN_CTRL, - MT6323_ISINK_CH_EN_MASK(led->id), ~status); + status = ISINK_CH_EN(led->id); + ret = regmap_update_bits(regmap, regs->isink_en_ctrl, + ISINK_CH_EN_MASK(led->id), ~status); if (ret < 0) return ret; usleep_range(100, 300); - ret = regmap_update_bits(regmap, MT6323_TOP_CKPDN2, - MT6323_RG_ISINK_CK_PDN_MASK(led->id), - MT6323_RG_ISINK_CK_PDN(led->id)); + ret = regmap_update_bits(regmap, regs->top_ckpdn[2], + RG_ISINK_CK_PDN_MASK(led->id), + RG_ISINK_CK_PDN(led->id)); if (ret < 0) return ret; @@ -158,30 +205,31 @@ mt6323_get_led_hw_brightness(struct led_classdev *cdev) { struct mt6323_led *led = container_of(cdev, struct mt6323_led, cdev); struct mt6323_leds *leds = led->parent; + const struct mt6323_regs *regs = leds->pdata->regs; struct regmap *regmap = leds->hw->regmap; unsigned int status; int ret; - ret = regmap_read(regmap, MT6323_TOP_CKPDN2, &status); + ret = regmap_read(regmap, regs->top_ckpdn[2], &status); if (ret < 0) return ret; - if (status & MT6323_RG_ISINK_CK_PDN_MASK(led->id)) + if (status & RG_ISINK_CK_PDN_MASK(led->id)) return 0; - ret = regmap_read(regmap, MT6323_ISINK_EN_CTRL, &status); + ret = regmap_read(regmap, regs->isink_en_ctrl, &status); if (ret < 0) return ret; - if (!(status & MT6323_ISINK_CH_EN(led->id))) + if (!(status & ISINK_CH_EN(led->id))) return 0; - ret = regmap_read(regmap, MT6323_ISINK_CON2(led->id), &status); + ret = regmap_read(regmap, ISINK_CON(regs->isink_con[2], led->id), &status); if (ret < 0) return ret; - return ((status & MT6323_ISINK_CH_STEP_MASK) - >> MT6323_ISINK_CH_STEP_SHIFT) + 1; + return ((status & ISINK_CH_STEP_MASK) + >> ISINK_CH_STEP_SHIFT) + 1; } static int mt6323_led_hw_on(struct led_classdev *cdev, @@ -189,6 +237,7 @@ static int mt6323_led_hw_on(struct led_classdev *cdev, { struct mt6323_led *led = container_of(cdev, struct mt6323_led, cdev); struct mt6323_leds *leds = led->parent; + const struct mt6323_regs *regs = leds->pdata->regs; struct regmap *regmap = leds->hw->regmap; unsigned int status; int ret; @@ -198,23 +247,23 @@ static int mt6323_led_hw_on(struct led_classdev *cdev, * clock and channel and let work with continuous blink as * the default. */ - ret = regmap_update_bits(regmap, MT6323_TOP_CKCON1, - MT6323_RG_ISINK_CK_SEL_MASK(led->id), 0); + ret = regmap_update_bits(regmap, regs->top_ckcon[1], + RG_ISINK_CK_SEL_MASK(led->id), 0); if (ret < 0) return ret; - status = MT6323_RG_ISINK_CK_PDN(led->id); - ret = regmap_update_bits(regmap, MT6323_TOP_CKPDN2, - MT6323_RG_ISINK_CK_PDN_MASK(led->id), + status = RG_ISINK_CK_PDN(led->id); + ret = regmap_update_bits(regmap, regs->top_ckpdn[2], + RG_ISINK_CK_PDN_MASK(led->id), ~status); if (ret < 0) return ret; usleep_range(100, 300); - ret = regmap_update_bits(regmap, MT6323_ISINK_EN_CTRL, - MT6323_ISINK_CH_EN_MASK(led->id), - MT6323_ISINK_CH_EN(led->id)); + ret = regmap_update_bits(regmap, regs->isink_en_ctrl, + ISINK_CH_EN_MASK(led->id), + ISINK_CH_EN(led->id)); if (ret < 0) return ret; @@ -222,15 +271,15 @@ static int mt6323_led_hw_on(struct led_classdev *cdev, if (ret < 0) return ret; - ret = regmap_update_bits(regmap, MT6323_ISINK_CON0(led->id), - MT6323_ISINK_DIM_DUTY_MASK, - MT6323_ISINK_DIM_DUTY(31)); + ret = regmap_update_bits(regmap, ISINK_CON(regs->isink_con[0], led->id), + ISINK_DIM_DUTY_MASK, + ISINK_DIM_DUTY(31)); if (ret < 0) return ret; - ret = regmap_update_bits(regmap, MT6323_ISINK_CON1(led->id), - MT6323_ISINK_DIM_FSEL_MASK, - MT6323_ISINK_DIM_FSEL(1000)); + ret = regmap_update_bits(regmap, ISINK_CON(regs->isink_con[1], led->id), + ISINK_DIM_FSEL_MASK, + ISINK_DIM_FSEL(1000)); if (ret < 0) return ret; @@ -243,6 +292,8 @@ static int mt6323_led_set_blink(struct led_classdev *cdev, { struct mt6323_led *led = container_of(cdev, struct mt6323_led, cdev); struct mt6323_leds *leds = led->parent; + const struct mt6323_regs *regs = leds->pdata->regs; + const struct mt6323_hwspec *spec = leds->pdata->spec; struct regmap *regmap = leds->hw->regmap; unsigned long period; u8 duty_hw; @@ -265,14 +316,14 @@ static int mt6323_led_set_blink(struct led_classdev *cdev, */ period = *delay_on + *delay_off; - if (period > MT6323_MAX_PERIOD) + if (period > spec->max_period) return -EINVAL; /* * Calculate duty_hw based on the percentage of period during * which the led is ON. */ - duty_hw = MT6323_CAL_HW_DUTY(*delay_on, period); + duty_hw = DIV_ROUND_CLOSEST(*delay_on * 100000ul, period * spec->unit_duty); /* hardware doesn't support zero duty cycle. */ if (!duty_hw) @@ -290,15 +341,15 @@ static int mt6323_led_set_blink(struct led_classdev *cdev, led->current_brightness = cdev->max_brightness; } - ret = regmap_update_bits(regmap, MT6323_ISINK_CON0(led->id), - MT6323_ISINK_DIM_DUTY_MASK, - MT6323_ISINK_DIM_DUTY(duty_hw - 1)); + ret = regmap_update_bits(regmap, ISINK_CON(regs->isink_con[0], led->id), + ISINK_DIM_DUTY_MASK, + ISINK_DIM_DUTY(duty_hw - 1)); if (ret < 0) goto out; - ret = regmap_update_bits(regmap, MT6323_ISINK_CON1(led->id), - MT6323_ISINK_DIM_FSEL_MASK, - MT6323_ISINK_DIM_FSEL(period - 1)); + ret = regmap_update_bits(regmap, ISINK_CON(regs->isink_con[1], led->id), + ISINK_DIM_FSEL_MASK, + ISINK_DIM_FSEL(period - 1)); out: mutex_unlock(&leds->lock); @@ -335,6 +386,117 @@ static int mt6323_led_set_brightness(struct led_classdev *cdev, return ret; } +static int mtk_wled_hw_on(struct led_classdev *cdev) +{ + struct mt6323_led *led = container_of(cdev, struct mt6323_led, cdev); + struct mt6323_leds *leds = led->parent; + const struct mt6323_regs *regs = leds->pdata->regs; + struct regmap *regmap = leds->hw->regmap; + int ret; + + ret = regmap_clear_bits(regmap, regs->top_ckpdn[0], RG_VWLED_32K_CK_PDN); + if (ret) + return ret; + + ret = regmap_clear_bits(regmap, regs->top_ckpdn[0], RG_VWLED_6M_CK_PDN); + if (ret) + return ret; + + ret = regmap_clear_bits(regmap, regs->top_ckpdn[0], RG_VWLED_1M_CK_PDN); + if (ret) + return ret; + + usleep_range(5000, 6000); + + /* Enable WLED channel pair */ + ret = regmap_set_bits(regmap, regs->iwled_en_ctrl, BIT(led->id)); + if (ret) + return ret; + + ret = regmap_set_bits(regmap, regs->iwled_en_ctrl, BIT(led->id + 1)); + if (ret) + return ret; + + return 0; +} + +static int mtk_wled_hw_off(struct led_classdev *cdev) +{ + struct mt6323_led *led = container_of(cdev, struct mt6323_led, cdev); + struct mt6323_leds *leds = led->parent; + const struct mt6323_regs *regs = leds->pdata->regs; + struct regmap *regmap = leds->hw->regmap; + int ret; + + ret = regmap_clear_bits(regmap, regs->iwled_en_ctrl, BIT(led->id + 1)); + if (ret) + return ret; + + ret = regmap_clear_bits(regmap, regs->iwled_en_ctrl, BIT(led->id)); + if (ret) + return ret; + + ret = regmap_set_bits(regmap, regs->top_ckpdn[0], RG_VWLED_32K_CK_PDN); + if (ret) + return ret; + + ret = regmap_set_bits(regmap, regs->top_ckpdn[0], RG_VWLED_6M_CK_PDN); + if (ret) + return ret; + + ret = regmap_set_bits(regmap, regs->top_ckpdn[0], RG_VWLED_1M_CK_PDN); + if (ret) + return ret; + + return 0; +} + +static enum led_brightness mt6323_get_wled_brightness(struct led_classdev *cdev) +{ + struct mt6323_led *led = container_of(cdev, struct mt6323_led, cdev); + struct mt6323_leds *leds = led->parent; + const struct mt6323_regs *regs = leds->pdata->regs; + struct regmap *regmap = leds->hw->regmap; + unsigned int status; + int ret; + + ret = regmap_read(regmap, regs->iwled_en_ctrl, &status); + if (ret) + return 0; + + /* Always two channels per WLED */ + status &= BIT(led->id) | BIT(led->id + 1); + + return status ? led->current_brightness : 0; +} + +static int mt6323_wled_set_brightness(struct led_classdev *cdev, + enum led_brightness brightness) +{ + struct mt6323_led *led = container_of(cdev, struct mt6323_led, cdev); + struct mt6323_leds *leds = led->parent; + int ret = 0; + + mutex_lock(&leds->lock); + + if (brightness) { + if (!led->current_brightness) + ret = mtk_wled_hw_on(cdev); + if (ret) + goto out; + } else { + ret = mtk_wled_hw_off(cdev); + if (ret) + goto out; + } + + led->current_brightness = brightness; +out: + mutex_unlock(&leds->lock); + + return ret; +} + static int mt6323_led_set_dt_default(struct led_classdev *cdev, struct device_node *np) { @@ -369,9 +531,12 @@ static int mt6323_led_probe(struct platform_device *pdev) struct mt6397_chip *hw = dev_get_drvdata(dev->parent); struct mt6323_leds *leds; struct mt6323_led *led; + const struct mt6323_regs *regs; + const struct mt6323_hwspec *spec; int ret; unsigned int status; u32 reg; + u8 max_leds; leds = devm_kzalloc(dev, sizeof(*leds), GFP_KERNEL); if (!leds) @@ -379,6 +544,10 @@ static int mt6323_led_probe(struct platform_device *pdev) platform_set_drvdata(pdev, leds); leds->dev = dev; + leds->pdata = device_get_match_data(dev); + regs = leds->pdata->regs; + spec = leds->pdata->spec; + max_leds = spec->max_leds + spec->max_wleds; /* * leds->hw points to the underlying bus for the register @@ -387,17 +556,18 @@ static int mt6323_led_probe(struct platform_device *pdev) leds->hw = hw; mutex_init(&leds->lock); - status = MT6323_RG_DRV_32K_CK_PDN; - ret = regmap_update_bits(leds->hw->regmap, MT6323_TOP_CKPDN0, - MT6323_RG_DRV_32K_CK_PDN_MASK, ~status); + status = RG_DRV_32K_CK_PDN; + ret = regmap_update_bits(leds->hw->regmap, regs->top_ckpdn[0], + RG_DRV_32K_CK_PDN_MASK, ~status); if (ret < 0) { dev_err(leds->dev, - "Failed to update MT6323_TOP_CKPDN0 Register\n"); + "Failed to update TOP_CKPDN0 Register\n"); return ret; } for_each_available_child_of_node(np, child) { struct led_init_data init_data = {}; + bool is_wled; ret = of_property_read_u32(child, "reg", ®); if (ret) { @@ -405,7 +575,8 @@ static int mt6323_led_probe(struct platform_device *pdev) goto put_child_node; } - if (reg >= MT6323_MAX_LEDS || leds->led[reg]) { + if (reg >= max_leds || reg >= MAX_SUPPORTED_LEDS || + leds->led[reg]) { dev_err(dev, "Invalid led reg %u\n", reg); ret = -EINVAL; goto put_child_node; @@ -417,14 +588,24 @@ static int mt6323_led_probe(struct platform_device *pdev) goto put_child_node; } + is_wled = of_property_read_bool(child, "mediatek,is-wled"); + leds->led[reg] = led; leds->led[reg]->id = reg; - leds->led[reg]->cdev.max_brightness = MT6323_MAX_BRIGHTNESS; - leds->led[reg]->cdev.brightness_set_blocking = - mt6323_led_set_brightness; - leds->led[reg]->cdev.blink_set = mt6323_led_set_blink; - leds->led[reg]->cdev.brightness_get = - mt6323_get_led_hw_brightness; + leds->led[reg]->cdev.max_brightness = spec->max_brightness; + + if (is_wled) { + leds->led[reg]->cdev.brightness_set_blocking = + mt6323_wled_set_brightness; + leds->led[reg]->cdev.brightness_get = + mt6323_get_wled_brightness; + } else { + leds->led[reg]->cdev.brightness_set_blocking = + mt6323_led_set_brightness; + leds->led[reg]->cdev.blink_set = mt6323_led_set_blink; + leds->led[reg]->cdev.brightness_get = + mt6323_get_led_hw_brightness; + } leds->led[reg]->parent = leds; ret = mt6323_led_set_dt_default(&leds->led[reg]->cdev, child); @@ -454,23 +635,88 @@ static int mt6323_led_probe(struct platform_device *pdev) static int mt6323_led_remove(struct platform_device *pdev) { struct mt6323_leds *leds = platform_get_drvdata(pdev); + const struct mt6323_regs *regs = leds->pdata->regs; int i; /* Turn the LEDs off on driver removal. */ for (i = 0 ; leds->led[i] ; i++) mt6323_led_hw_off(&leds->led[i]->cdev); - regmap_update_bits(leds->hw->regmap, MT6323_TOP_CKPDN0, - MT6323_RG_DRV_32K_CK_PDN_MASK, - MT6323_RG_DRV_32K_CK_PDN); + regmap_update_bits(leds->hw->regmap, regs->top_ckpdn[0], + RG_DRV_32K_CK_PDN_MASK, + RG_DRV_32K_CK_PDN); mutex_destroy(&leds->lock); return 0; } +static const struct mt6323_regs mt6323_registers = { + .top_ckpdn = (const u16[]){ 0x102, 0x106, 0x10e }, + .num_top_ckpdn = 3, + .top_ckcon = (const u16[]){ 0x120, 0x126 }, + .num_top_ckcon = 2, + .isink_con = (const u16[]){ 0x330, 0x332, 0x334 }, + .num_isink_con = 3, + .isink_max_regs = 4, /* ISINK[0..3] */ + .isink_en_ctrl = 0x356, +}; + +static const struct mt6323_regs mt6331_registers = { + .top_ckpdn = (const u16[]){ 0x138, 0x13e, 0x144 }, + .num_top_ckpdn = 3, + .top_ckcon = (const u16[]){ 0x14c, 0x14a }, + .num_top_ckcon = 2, + .isink_con = (const u16[]){ 0x40c, 0x40e, 0x410, 0x412, 0x414 }, + .num_isink_con = 5, + .isink_max_regs = 4, /* ISINK[0..3] */ + .isink_en_ctrl = 0x43a, +}; + +static const struct mt6323_regs mt6332_registers = { + .top_ckpdn = (const u16[]){ 0x8094, 0x809a, 0x80a0 }, + .num_top_ckpdn = 3, + .top_ckcon = (const u16[]){ 0x80a6, 0x80ac }, + .num_top_ckcon = 2, + .isink_con = (const u16[]){ 0x8cd4 }, + .num_isink_con = 1, + .isink_max_regs = 12, /* IWLED[0..2, 3..9] */ + .iwled_en_ctrl = 0x8cda, +}; + +static const struct mt6323_hwspec mt6323_spec = { + .max_period = 10000, + .max_leds = 4, + .max_brightness = 6, + .unit_duty = 3125, +}; + +static const struct mt6323_hwspec mt6332_spec = { + /* There are no LEDs in MT6332. Only WLEDs are present. */ + .max_leds = 0, + .max_wleds = 1, + .max_brightness = 1024, +}; + +static const struct mt6323_data mt6323_pdata = { + .regs = &mt6323_registers, + .spec = &mt6323_spec, +}; + +static const struct mt6323_data mt6331_pdata = { + .regs = &mt6331_registers, + .spec = &mt6323_spec, +}; + +static const struct mt6323_data mt6332_pdata = { + .regs = &mt6332_registers, + .spec = &mt6332_spec, +}; + static const struct of_device_id mt6323_led_dt_match[] = { - { .compatible = "mediatek,mt6323-led" }, + { .compatible = "mediatek,mt6323-led", .data = &mt6323_pdata}, + { .compatible = "mediatek,mt6331-led", .data = &mt6331_pdata }, + { .compatible = "mediatek,mt6332-led", .data = &mt6332_pdata }, {}, }; MODULE_DEVICE_TABLE(of, mt6323_led_dt_match); diff --git a/drivers/leds/leds-pca9532.c b/drivers/leds/leds-pca9532.c index 15b1acfa442e7e4f8bb5b362f3f0e3f7ed6c7b13..8b5c62083e50827ced35ab5e54284ded8e09b29e 100644 --- a/drivers/leds/leds-pca9532.c +++ b/drivers/leds/leds-pca9532.c @@ -102,7 +102,7 @@ static struct i2c_driver pca9532_driver = { .name = "leds-pca953x", .of_match_table = of_match_ptr(of_pca9532_leds_match), }, - .probe_new = pca9532_probe, + .probe = pca9532_probe, .remove = pca9532_remove, .id_table = pca9532_id, }; diff --git a/drivers/leds/leds-pca955x.c b/drivers/leds/leds-pca955x.c index 1edd092e7894792518aeea3de6b484e95eff935a..b10e1ef38db0b558e26fc143fb9318a9cb14a039 100644 --- a/drivers/leds/leds-pca955x.c +++ b/drivers/leds/leds-pca955x.c @@ -668,7 +668,7 @@ static struct i2c_driver pca955x_driver = { .name = "leds-pca955x", .of_match_table = of_pca955x_match, }, - .probe_new = pca955x_probe, + .probe = pca955x_probe, .id_table = pca955x_id, }; diff --git a/drivers/leds/leds-pca963x.c b/drivers/leds/leds-pca963x.c index 9cd476db601f2b7c0c93857528a5d335827fb659..47223c850e4b4dc3bd0155352a3854c0a6e83d7c 100644 --- a/drivers/leds/leds-pca963x.c +++ b/drivers/leds/leds-pca963x.c @@ -431,7 +431,7 @@ static struct i2c_driver pca963x_driver = { .name = "leds-pca963x", .of_match_table = of_pca963x_match, }, - .probe_new = pca963x_probe, + .probe = pca963x_probe, .id_table = pca963x_id, }; diff --git a/drivers/leds/leds-spi-byte.c b/drivers/leds/leds-spi-byte.c index 2bc5c99daf51a8c999d9694336a29cafba41a408..2c7ffc3c78e666ede757bd077ea0c798060d80a7 100644 --- a/drivers/leds/leds-spi-byte.c +++ b/drivers/leds/leds-spi-byte.c @@ -98,7 +98,7 @@ static int spi_byte_probe(struct spi_device *spi) return -ENOMEM; of_property_read_string(child, "label", &name); - strlcpy(led->name, name, sizeof(led->name)); + strscpy(led->name, name, sizeof(led->name)); led->spi = spi; mutex_init(&led->mutex); led->cdef = device_get_match_data(dev); diff --git a/drivers/leds/leds-tca6507.c b/drivers/leds/leds-tca6507.c index 634cabd5bb79658bae33abe57b29289dbcf0cfb9..aab8617712101b28a406008f3d8e7ee66691d715 100644 --- a/drivers/leds/leds-tca6507.c +++ b/drivers/leds/leds-tca6507.c @@ -808,7 +808,7 @@ static struct i2c_driver tca6507_driver = { .name = "leds-tca6507", .of_match_table = of_match_ptr(of_tca6507_leds_match), }, - .probe_new = tca6507_probe, + .probe = tca6507_probe, .remove = tca6507_remove, .id_table = tca6507_id, }; diff --git a/drivers/leds/leds-tlc591xx.c b/drivers/leds/leds-tlc591xx.c index 7e31db50036f05bdd928b0793dac5d1d7f80c4dc..dfc6fb2b3e5224cc8d39154c9561f0133cf731b1 100644 --- a/drivers/leds/leds-tlc591xx.c +++ b/drivers/leds/leds-tlc591xx.c @@ -230,7 +230,7 @@ static struct i2c_driver tlc591xx_driver = { .name = "tlc591xx", .of_match_table = of_match_ptr(of_tlc591xx_leds_match), }, - .probe_new = tlc591xx_probe, + .probe = tlc591xx_probe, .id_table = tlc591xx_id, }; diff --git a/drivers/leds/leds-turris-omnia.c b/drivers/leds/leds-turris-omnia.c index 013f551b32b27c83cf0822b775c0fd4bca22dc94..64b2d7b6d3f315cfdd75dc5be5ee3855ff2b306a 100644 --- a/drivers/leds/leds-turris-omnia.c +++ b/drivers/leds/leds-turris-omnia.c @@ -271,7 +271,7 @@ static const struct i2c_device_id omnia_id[] = { MODULE_DEVICE_TABLE(i2c, omnia_id); static struct i2c_driver omnia_leds_driver = { - .probe_new = omnia_leds_probe, + .probe = omnia_leds_probe, .remove = omnia_leds_remove, .id_table = omnia_id, .driver = { diff --git a/drivers/leds/rgb/leds-qcom-lpg.c b/drivers/leds/rgb/leds-qcom-lpg.c index 1c849814a4917fe5805a3f1aa8bf87831366a759..59581b3e25ca98ff87dc6d749034554153df47a0 100644 --- a/drivers/leds/rgb/leds-qcom-lpg.c +++ b/drivers/leds/rgb/leds-qcom-lpg.c @@ -1173,8 +1173,10 @@ static int lpg_add_led(struct lpg *lpg, struct device_node *np) i = 0; for_each_available_child_of_node(np, child) { ret = lpg_parse_channel(lpg, child, &led->channels[i]); - if (ret < 0) + if (ret < 0) { + of_node_put(child); return ret; + } info[i].color_index = led->channels[i]->color; info[i].intensity = 0; @@ -1352,8 +1354,10 @@ static int lpg_probe(struct platform_device *pdev) for_each_available_child_of_node(pdev->dev.of_node, np) { ret = lpg_add_led(lpg, np); - if (ret) + if (ret) { + of_node_put(np); return ret; + } } for (i = 0; i < lpg->num_channels; i++) @@ -1414,6 +1418,20 @@ static const struct lpg_data pm8994_lpg_data = { }, }; +/* PMI632 uses SDAM instead of LUT for pattern */ +static const struct lpg_data pmi632_lpg_data = { + .triled_base = 0xd000, + + .num_channels = 5, + .channels = (const struct lpg_channel_data[]) { + { .base = 0xb300, .triled_mask = BIT(7) }, + { .base = 0xb400, .triled_mask = BIT(6) }, + { .base = 0xb500, .triled_mask = BIT(5) }, + { .base = 0xb600 }, + { .base = 0xb700 }, + }, +}; + static const struct lpg_data pmi8994_lpg_data = { .lut_base = 0xb000, .lut_size = 24, @@ -1505,6 +1523,7 @@ static const struct of_device_id lpg_of_table[] = { { .compatible = "qcom,pm8916-pwm", .data = &pm8916_pwm_data }, { .compatible = "qcom,pm8941-lpg", .data = &pm8941_lpg_data }, { .compatible = "qcom,pm8994-lpg", .data = &pm8994_lpg_data }, + { .compatible = "qcom,pmi632-lpg", .data = &pmi632_lpg_data }, { .compatible = "qcom,pmi8994-lpg", .data = &pmi8994_lpg_data }, { .compatible = "qcom,pmi8998-lpg", .data = &pmi8998_lpg_data }, { .compatible = "qcom,pmc8180c-lpg", .data = &pm8150l_lpg_data }, diff --git a/drivers/leds/simple/Kconfig b/drivers/leds/simple/Kconfig index fd2b8225d926ab98ade6c2b3475b848724d028a9..44fa0f93cb3b3dbb13621a3bc1a67437cb508dbc 100644 --- a/drivers/leds/simple/Kconfig +++ b/drivers/leds/simple/Kconfig @@ -1,11 +1,36 @@ # SPDX-License-Identifier: GPL-2.0-only config LEDS_SIEMENS_SIMATIC_IPC tristate "LED driver for Siemens Simatic IPCs" - depends on LEDS_GPIO depends on SIEMENS_SIMATIC_IPC help This option enables support for the LEDs of several Industrial PCs from Siemens. - To compile this driver as a module, choose M here: the modules - will be called simatic-ipc-leds and simatic-ipc-leds-gpio. + To compile this driver as a module, choose M here: the module + will be called simatic-ipc-leds. + +config LEDS_SIEMENS_SIMATIC_IPC_APOLLOLAKE + tristate "LED driver for Siemens Simatic IPCs based on Intel Apollo Lake GPIO" + depends on LEDS_GPIO + depends on PINCTRL_BROXTON + depends on SIEMENS_SIMATIC_IPC + default LEDS_SIEMENS_SIMATIC_IPC + help + This option enables support for the LEDs of several Industrial PCs + from Siemens based on Apollo Lake GPIO i.e. IPC127E. + + To compile this driver as a module, choose M here: the module + will be called simatic-ipc-leds-gpio-apollolake. + +config LEDS_SIEMENS_SIMATIC_IPC_F7188X + tristate "LED driver for Siemens Simatic IPCs based on Nuvoton GPIO" + depends on LEDS_GPIO + depends on GPIO_F7188X + depends on SIEMENS_SIMATIC_IPC + default LEDS_SIEMENS_SIMATIC_IPC + help + This option enables support for the LEDs of several Industrial PCs + from Siemens based on Nuvoton GPIO i.e. IPC227G. + + To compile this driver as a module, choose M here: the module + will be called simatic-ipc-leds-gpio-f7188x. diff --git a/drivers/leds/simple/Makefile b/drivers/leds/simple/Makefile index 1c7ef5e1324ba37ba9232ce532178ab52bc5b8cd..e3e840cea275ca8870aaddee09d46670f1025912 100644 --- a/drivers/leds/simple/Makefile +++ b/drivers/leds/simple/Makefile @@ -1,3 +1,4 @@ # SPDX-License-Identifier: GPL-2.0 -obj-$(CONFIG_LEDS_SIEMENS_SIMATIC_IPC) += simatic-ipc-leds.o -obj-$(CONFIG_LEDS_SIEMENS_SIMATIC_IPC) += simatic-ipc-leds-gpio.o +obj-$(CONFIG_LEDS_SIEMENS_SIMATIC_IPC) += simatic-ipc-leds.o +obj-$(CONFIG_LEDS_SIEMENS_SIMATIC_IPC_APOLLOLAKE) += simatic-ipc-leds-gpio-core.o simatic-ipc-leds-gpio-apollolake.o +obj-$(CONFIG_LEDS_SIEMENS_SIMATIC_IPC_F7188X) += simatic-ipc-leds-gpio-core.o simatic-ipc-leds-gpio-f7188x.o diff --git a/drivers/leds/simple/simatic-ipc-leds-gpio-apollolake.c b/drivers/leds/simple/simatic-ipc-leds-gpio-apollolake.c new file mode 100644 index 0000000000000000000000000000000000000000..e1c712729dcf7ed344be5c2c942cca4c0adfe2ac --- /dev/null +++ b/drivers/leds/simple/simatic-ipc-leds-gpio-apollolake.c @@ -0,0 +1,66 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Siemens SIMATIC IPC driver for GPIO based LEDs + * + * Copyright (c) Siemens AG, 2023 + * + * Author: + * Henning Schild + */ + +#include +#include +#include +#include +#include +#include + +#include "simatic-ipc-leds-gpio.h" + +static struct gpiod_lookup_table simatic_ipc_led_gpio_table = { + .dev_id = "leds-gpio", + .table = { + GPIO_LOOKUP_IDX("apollolake-pinctrl.0", 52, NULL, 0, GPIO_ACTIVE_LOW), + GPIO_LOOKUP_IDX("apollolake-pinctrl.0", 53, NULL, 1, GPIO_ACTIVE_LOW), + GPIO_LOOKUP_IDX("apollolake-pinctrl.0", 57, NULL, 2, GPIO_ACTIVE_LOW), + GPIO_LOOKUP_IDX("apollolake-pinctrl.0", 58, NULL, 3, GPIO_ACTIVE_LOW), + GPIO_LOOKUP_IDX("apollolake-pinctrl.0", 60, NULL, 4, GPIO_ACTIVE_LOW), + GPIO_LOOKUP_IDX("apollolake-pinctrl.0", 51, NULL, 5, GPIO_ACTIVE_LOW), + {} /* Terminating entry */ + }, +}; + +static struct gpiod_lookup_table simatic_ipc_led_gpio_table_extra = { + .dev_id = NULL, /* Filled during initialization */ + .table = { + GPIO_LOOKUP_IDX("apollolake-pinctrl.0", 56, NULL, 6, GPIO_ACTIVE_LOW), + GPIO_LOOKUP_IDX("apollolake-pinctrl.0", 59, NULL, 7, GPIO_ACTIVE_HIGH), + {} /* Terminating entry */ + }, +}; + +static int simatic_ipc_leds_gpio_apollolake_probe(struct platform_device *pdev) +{ + return simatic_ipc_leds_gpio_probe(pdev, &simatic_ipc_led_gpio_table, + &simatic_ipc_led_gpio_table_extra); +} + +static int simatic_ipc_leds_gpio_apollolake_remove(struct platform_device *pdev) +{ + return simatic_ipc_leds_gpio_remove(pdev, &simatic_ipc_led_gpio_table, + &simatic_ipc_led_gpio_table_extra); +} + +static struct platform_driver simatic_ipc_led_gpio_apollolake_driver = { + .probe = simatic_ipc_leds_gpio_apollolake_probe, + .remove = simatic_ipc_leds_gpio_apollolake_remove, + .driver = { + .name = KBUILD_MODNAME, + }, +}; +module_platform_driver(simatic_ipc_led_gpio_apollolake_driver); + +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:" KBUILD_MODNAME); +MODULE_SOFTDEP("pre: simatic-ipc-leds-gpio-core platform:apollolake-pinctrl"); +MODULE_AUTHOR("Henning Schild "); diff --git a/drivers/leds/simple/simatic-ipc-leds-gpio-core.c b/drivers/leds/simple/simatic-ipc-leds-gpio-core.c new file mode 100644 index 0000000000000000000000000000000000000000..2a21b663df8746f4c285ea411f837a6a2a84cb1a --- /dev/null +++ b/drivers/leds/simple/simatic-ipc-leds-gpio-core.c @@ -0,0 +1,104 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Siemens SIMATIC IPC driver for GPIO based LEDs + * + * Copyright (c) Siemens AG, 2023 + * + * Author: + * Henning Schild + */ + +#include +#include +#include +#include +#include +#include + +#include "simatic-ipc-leds-gpio.h" + +static struct platform_device *simatic_leds_pdev; + +static const struct gpio_led simatic_ipc_gpio_leds[] = { + { .name = "red:" LED_FUNCTION_STATUS "-1" }, + { .name = "green:" LED_FUNCTION_STATUS "-1" }, + { .name = "red:" LED_FUNCTION_STATUS "-2" }, + { .name = "green:" LED_FUNCTION_STATUS "-2" }, + { .name = "red:" LED_FUNCTION_STATUS "-3" }, + { .name = "green:" LED_FUNCTION_STATUS "-3" }, +}; + +static const struct gpio_led_platform_data simatic_ipc_gpio_leds_pdata = { + .num_leds = ARRAY_SIZE(simatic_ipc_gpio_leds), + .leds = simatic_ipc_gpio_leds, +}; + +int simatic_ipc_leds_gpio_remove(struct platform_device *pdev, + struct gpiod_lookup_table *table, + struct gpiod_lookup_table *table_extra) +{ + gpiod_remove_lookup_table(table); + gpiod_remove_lookup_table(table_extra); + platform_device_unregister(simatic_leds_pdev); + + return 0; +} +EXPORT_SYMBOL_GPL(simatic_ipc_leds_gpio_remove); + +int simatic_ipc_leds_gpio_probe(struct platform_device *pdev, + struct gpiod_lookup_table *table, + struct gpiod_lookup_table *table_extra) +{ + const struct simatic_ipc_platform *plat = pdev->dev.platform_data; + struct device *dev = &pdev->dev; + struct gpio_desc *gpiod; + int err; + + switch (plat->devmode) { + case SIMATIC_IPC_DEVICE_127E: + case SIMATIC_IPC_DEVICE_227G: + break; + default: + return -ENODEV; + } + + gpiod_add_lookup_table(table); + simatic_leds_pdev = platform_device_register_resndata(NULL, + "leds-gpio", PLATFORM_DEVID_NONE, NULL, 0, + &simatic_ipc_gpio_leds_pdata, + sizeof(simatic_ipc_gpio_leds_pdata)); + if (IS_ERR(simatic_leds_pdev)) { + err = PTR_ERR(simatic_leds_pdev); + goto out; + } + + table_extra->dev_id = dev_name(dev); + gpiod_add_lookup_table(table_extra); + + /* PM_BIOS_BOOT_N */ + gpiod = gpiod_get_index(dev, NULL, 6, GPIOD_OUT_LOW); + if (IS_ERR(gpiod)) { + err = PTR_ERR(gpiod); + goto out; + } + gpiod_put(gpiod); + + /* PM_WDT_OUT */ + gpiod = gpiod_get_index(dev, NULL, 7, GPIOD_OUT_LOW); + if (IS_ERR(gpiod)) { + err = PTR_ERR(gpiod); + goto out; + } + gpiod_put(gpiod); + + return 0; +out: + simatic_ipc_leds_gpio_remove(pdev, table, table_extra); + + return err; +} +EXPORT_SYMBOL_GPL(simatic_ipc_leds_gpio_probe); + +MODULE_LICENSE("GPL v2"); +MODULE_SOFTDEP("pre: platform:leds-gpio"); +MODULE_AUTHOR("Henning Schild "); diff --git a/drivers/leds/simple/simatic-ipc-leds-gpio-f7188x.c b/drivers/leds/simple/simatic-ipc-leds-gpio-f7188x.c new file mode 100644 index 0000000000000000000000000000000000000000..583a6b6c7c2226f17cbf308fd8e8a2d795ee33a9 --- /dev/null +++ b/drivers/leds/simple/simatic-ipc-leds-gpio-f7188x.c @@ -0,0 +1,66 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Siemens SIMATIC IPC driver for GPIO based LEDs + * + * Copyright (c) Siemens AG, 2023 + * + * Author: + * Henning Schild + */ + +#include +#include +#include +#include +#include +#include + +#include "simatic-ipc-leds-gpio.h" + +static struct gpiod_lookup_table simatic_ipc_led_gpio_table = { + .dev_id = "leds-gpio", + .table = { + GPIO_LOOKUP_IDX("gpio-f7188x-2", 0, NULL, 0, GPIO_ACTIVE_LOW), + GPIO_LOOKUP_IDX("gpio-f7188x-2", 1, NULL, 1, GPIO_ACTIVE_LOW), + GPIO_LOOKUP_IDX("gpio-f7188x-2", 2, NULL, 2, GPIO_ACTIVE_LOW), + GPIO_LOOKUP_IDX("gpio-f7188x-2", 3, NULL, 3, GPIO_ACTIVE_LOW), + GPIO_LOOKUP_IDX("gpio-f7188x-2", 4, NULL, 4, GPIO_ACTIVE_LOW), + GPIO_LOOKUP_IDX("gpio-f7188x-2", 5, NULL, 5, GPIO_ACTIVE_LOW), + {} /* Terminating entry */ + }, +}; + +static struct gpiod_lookup_table simatic_ipc_led_gpio_table_extra = { + .dev_id = NULL, /* Filled during initialization */ + .table = { + GPIO_LOOKUP_IDX("gpio-f7188x-3", 6, NULL, 6, GPIO_ACTIVE_HIGH), + GPIO_LOOKUP_IDX("gpio-f7188x-3", 7, NULL, 7, GPIO_ACTIVE_HIGH), + {} /* Terminating entry */ + }, +}; + +static int simatic_ipc_leds_gpio_f7188x_probe(struct platform_device *pdev) +{ + return simatic_ipc_leds_gpio_probe(pdev, &simatic_ipc_led_gpio_table, + &simatic_ipc_led_gpio_table_extra); +} + +static int simatic_ipc_leds_gpio_f7188x_remove(struct platform_device *pdev) +{ + return simatic_ipc_leds_gpio_remove(pdev, &simatic_ipc_led_gpio_table, + &simatic_ipc_led_gpio_table_extra); +} + +static struct platform_driver simatic_ipc_led_gpio_driver = { + .probe = simatic_ipc_leds_gpio_f7188x_probe, + .remove = simatic_ipc_leds_gpio_f7188x_remove, + .driver = { + .name = KBUILD_MODNAME, + }, +}; +module_platform_driver(simatic_ipc_led_gpio_driver); + +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:" KBUILD_MODNAME); +MODULE_SOFTDEP("pre: simatic-ipc-leds-gpio-core gpio_f7188x"); +MODULE_AUTHOR("Henning Schild "); diff --git a/drivers/leds/simple/simatic-ipc-leds-gpio.c b/drivers/leds/simple/simatic-ipc-leds-gpio.c deleted file mode 100644 index e8d329b5a68c313704be3f9ffd0644616c8bb254..0000000000000000000000000000000000000000 --- a/drivers/leds/simple/simatic-ipc-leds-gpio.c +++ /dev/null @@ -1,139 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Siemens SIMATIC IPC driver for GPIO based LEDs - * - * Copyright (c) Siemens AG, 2022 - * - * Authors: - * Henning Schild - */ - -#include -#include -#include -#include -#include -#include - -static struct gpiod_lookup_table *simatic_ipc_led_gpio_table; - -static struct gpiod_lookup_table simatic_ipc_led_gpio_table_127e = { - .dev_id = "leds-gpio", - .table = { - GPIO_LOOKUP_IDX("apollolake-pinctrl.0", 52, NULL, 0, GPIO_ACTIVE_LOW), - GPIO_LOOKUP_IDX("apollolake-pinctrl.0", 53, NULL, 1, GPIO_ACTIVE_LOW), - GPIO_LOOKUP_IDX("apollolake-pinctrl.0", 57, NULL, 2, GPIO_ACTIVE_LOW), - GPIO_LOOKUP_IDX("apollolake-pinctrl.0", 58, NULL, 3, GPIO_ACTIVE_LOW), - GPIO_LOOKUP_IDX("apollolake-pinctrl.0", 60, NULL, 4, GPIO_ACTIVE_LOW), - GPIO_LOOKUP_IDX("apollolake-pinctrl.0", 51, NULL, 5, GPIO_ACTIVE_LOW), - GPIO_LOOKUP_IDX("apollolake-pinctrl.0", 56, NULL, 6, GPIO_ACTIVE_LOW), - GPIO_LOOKUP_IDX("apollolake-pinctrl.0", 59, NULL, 7, GPIO_ACTIVE_HIGH), - }, -}; - -static struct gpiod_lookup_table simatic_ipc_led_gpio_table_227g = { - .dev_id = "leds-gpio", - .table = { - GPIO_LOOKUP_IDX("gpio-f7188x-2", 0, NULL, 0, GPIO_ACTIVE_LOW), - GPIO_LOOKUP_IDX("gpio-f7188x-2", 1, NULL, 1, GPIO_ACTIVE_LOW), - GPIO_LOOKUP_IDX("gpio-f7188x-2", 2, NULL, 2, GPIO_ACTIVE_LOW), - GPIO_LOOKUP_IDX("gpio-f7188x-2", 3, NULL, 3, GPIO_ACTIVE_LOW), - GPIO_LOOKUP_IDX("gpio-f7188x-2", 4, NULL, 4, GPIO_ACTIVE_LOW), - GPIO_LOOKUP_IDX("gpio-f7188x-2", 5, NULL, 5, GPIO_ACTIVE_LOW), - GPIO_LOOKUP_IDX("gpio-f7188x-3", 6, NULL, 6, GPIO_ACTIVE_HIGH), - GPIO_LOOKUP_IDX("gpio-f7188x-3", 7, NULL, 7, GPIO_ACTIVE_HIGH), - } -}; - -static const struct gpio_led simatic_ipc_gpio_leds[] = { - { .name = "red:" LED_FUNCTION_STATUS "-1" }, - { .name = "green:" LED_FUNCTION_STATUS "-1" }, - { .name = "red:" LED_FUNCTION_STATUS "-2" }, - { .name = "green:" LED_FUNCTION_STATUS "-2" }, - { .name = "red:" LED_FUNCTION_STATUS "-3" }, - { .name = "green:" LED_FUNCTION_STATUS "-3" }, -}; - -static const struct gpio_led_platform_data simatic_ipc_gpio_leds_pdata = { - .num_leds = ARRAY_SIZE(simatic_ipc_gpio_leds), - .leds = simatic_ipc_gpio_leds, -}; - -static struct platform_device *simatic_leds_pdev; - -static int simatic_ipc_leds_gpio_remove(struct platform_device *pdev) -{ - gpiod_remove_lookup_table(simatic_ipc_led_gpio_table); - platform_device_unregister(simatic_leds_pdev); - - return 0; -} - -static int simatic_ipc_leds_gpio_probe(struct platform_device *pdev) -{ - const struct simatic_ipc_platform *plat = pdev->dev.platform_data; - struct gpio_desc *gpiod; - int err; - - switch (plat->devmode) { - case SIMATIC_IPC_DEVICE_127E: - if (!IS_ENABLED(CONFIG_PINCTRL_BROXTON)) - return -ENODEV; - simatic_ipc_led_gpio_table = &simatic_ipc_led_gpio_table_127e; - break; - case SIMATIC_IPC_DEVICE_227G: - if (!IS_ENABLED(CONFIG_GPIO_F7188X)) - return -ENODEV; - request_module("gpio-f7188x"); - simatic_ipc_led_gpio_table = &simatic_ipc_led_gpio_table_227g; - break; - default: - return -ENODEV; - } - - gpiod_add_lookup_table(simatic_ipc_led_gpio_table); - simatic_leds_pdev = platform_device_register_resndata(NULL, - "leds-gpio", PLATFORM_DEVID_NONE, NULL, 0, - &simatic_ipc_gpio_leds_pdata, - sizeof(simatic_ipc_gpio_leds_pdata)); - if (IS_ERR(simatic_leds_pdev)) { - err = PTR_ERR(simatic_leds_pdev); - goto out; - } - - /* PM_BIOS_BOOT_N */ - gpiod = gpiod_get_index(&simatic_leds_pdev->dev, NULL, 6, GPIOD_OUT_LOW); - if (IS_ERR(gpiod)) { - err = PTR_ERR(gpiod); - goto out; - } - gpiod_put(gpiod); - - /* PM_WDT_OUT */ - gpiod = gpiod_get_index(&simatic_leds_pdev->dev, NULL, 7, GPIOD_OUT_LOW); - if (IS_ERR(gpiod)) { - err = PTR_ERR(gpiod); - goto out; - } - gpiod_put(gpiod); - - return 0; -out: - simatic_ipc_leds_gpio_remove(pdev); - - return err; -} - -static struct platform_driver simatic_ipc_led_gpio_driver = { - .probe = simatic_ipc_leds_gpio_probe, - .remove = simatic_ipc_leds_gpio_remove, - .driver = { - .name = KBUILD_MODNAME, - } -}; -module_platform_driver(simatic_ipc_led_gpio_driver); - -MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("platform:" KBUILD_MODNAME); -MODULE_SOFTDEP("pre: platform:leds-gpio"); -MODULE_AUTHOR("Henning Schild "); diff --git a/drivers/leds/simple/simatic-ipc-leds-gpio.h b/drivers/leds/simple/simatic-ipc-leds-gpio.h new file mode 100644 index 0000000000000000000000000000000000000000..bf258c32f83def04081592b15d374a8abb68cb5e --- /dev/null +++ b/drivers/leds/simple/simatic-ipc-leds-gpio.h @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Siemens SIMATIC IPC driver for GPIO based LEDs + * + * Copyright (c) Siemens AG, 2023 + * + * Author: + * Henning Schild + */ + +#ifndef _SIMATIC_IPC_LEDS_GPIO_H +#define _SIMATIC_IPC_LEDS_GPIO_H + +int simatic_ipc_leds_gpio_probe(struct platform_device *pdev, + struct gpiod_lookup_table *table, + struct gpiod_lookup_table *table_extra); + +int simatic_ipc_leds_gpio_remove(struct platform_device *pdev, + struct gpiod_lookup_table *table, + struct gpiod_lookup_table *table_extra); + +#endif /* _SIMATIC_IPC_LEDS_GPIO_H */ diff --git a/drivers/leds/simple/simatic-ipc-leds.c b/drivers/leds/simple/simatic-ipc-leds.c index 4894c228c165f89dc48f9934b46f4002643e1520..2124f6d09930b2fbafc098b111cd454259c88612 100644 --- a/drivers/leds/simple/simatic-ipc-leds.c +++ b/drivers/leds/simple/simatic-ipc-leds.c @@ -126,7 +126,6 @@ static struct platform_driver simatic_ipc_led_driver = { .name = KBUILD_MODNAME, } }; - module_platform_driver(simatic_ipc_led_driver); MODULE_LICENSE("GPL v2"); diff --git a/drivers/leds/trigger/ledtrig-disk.c b/drivers/leds/trigger/ledtrig-disk.c index 0b7dfbd042733921e88c2c5d2be74199e927078b..e9b87ee944f26ac94f020bd0483a69fc8504eeff 100644 --- a/drivers/leds/trigger/ledtrig-disk.c +++ b/drivers/leds/trigger/ledtrig-disk.c @@ -19,16 +19,13 @@ DEFINE_LED_TRIGGER(ledtrig_disk_write); void ledtrig_disk_activity(bool write) { - unsigned long blink_delay = BLINK_DELAY; - - led_trigger_blink_oneshot(ledtrig_disk, - &blink_delay, &blink_delay, 0); + led_trigger_blink_oneshot(ledtrig_disk, BLINK_DELAY, BLINK_DELAY, 0); if (write) led_trigger_blink_oneshot(ledtrig_disk_write, - &blink_delay, &blink_delay, 0); + BLINK_DELAY, BLINK_DELAY, 0); else led_trigger_blink_oneshot(ledtrig_disk_read, - &blink_delay, &blink_delay, 0); + BLINK_DELAY, BLINK_DELAY, 0); } EXPORT_SYMBOL(ledtrig_disk_activity); diff --git a/drivers/leds/trigger/ledtrig-mtd.c b/drivers/leds/trigger/ledtrig-mtd.c index 8fa763c2269bd35d85aa66b6038c0f7fca716232..bbe6876a249d7dd6c5d01f44d0121412e250b05c 100644 --- a/drivers/leds/trigger/ledtrig-mtd.c +++ b/drivers/leds/trigger/ledtrig-mtd.c @@ -22,12 +22,8 @@ DEFINE_LED_TRIGGER(ledtrig_nand); void ledtrig_mtd_activity(void) { - unsigned long blink_delay = BLINK_DELAY; - - led_trigger_blink_oneshot(ledtrig_mtd, - &blink_delay, &blink_delay, 0); - led_trigger_blink_oneshot(ledtrig_nand, - &blink_delay, &blink_delay, 0); + led_trigger_blink_oneshot(ledtrig_mtd, BLINK_DELAY, BLINK_DELAY, 0); + led_trigger_blink_oneshot(ledtrig_nand, BLINK_DELAY, BLINK_DELAY, 0); } EXPORT_SYMBOL(ledtrig_mtd_activity); diff --git a/drivers/leds/trigger/ledtrig-netdev.c b/drivers/leds/trigger/ledtrig-netdev.c index d5e774d8302158179110d40d5b6aa10ddc68f804..c9bc5a91ec8324bba245de4297227589dd68982b 100644 --- a/drivers/leds/trigger/ledtrig-netdev.c +++ b/drivers/leds/trigger/ledtrig-netdev.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -20,10 +21,13 @@ #include #include #include -#include +#include +#include #include #include "../leds.h" +#define NETDEV_LED_DEFAULT_INTERVAL 50 + /* * Configurable sysfs attributes: * @@ -37,7 +41,7 @@ */ struct led_netdev_data { - spinlock_t lock; + struct mutex lock; struct delayed_work work; struct notifier_block notifier; @@ -50,16 +54,11 @@ struct led_netdev_data { unsigned int last_activity; unsigned long mode; -#define NETDEV_LED_LINK 0 -#define NETDEV_LED_TX 1 -#define NETDEV_LED_RX 2 -#define NETDEV_LED_MODE_LINKUP 3 -}; + int link_speed; + u8 duplex; -enum netdev_led_attr { - NETDEV_ATTR_LINK, - NETDEV_ATTR_TX, - NETDEV_ATTR_RX + bool carrier_link_up; + bool hw_control; }; static void set_baseline_state(struct led_netdev_data *trigger_data) @@ -67,16 +66,48 @@ static void set_baseline_state(struct led_netdev_data *trigger_data) int current_brightness; struct led_classdev *led_cdev = trigger_data->led_cdev; + /* Already validated, hw control is possible with the requested mode */ + if (trigger_data->hw_control) { + led_cdev->hw_control_set(led_cdev, trigger_data->mode); + + return; + } + current_brightness = led_cdev->brightness; if (current_brightness) led_cdev->blink_brightness = current_brightness; if (!led_cdev->blink_brightness) led_cdev->blink_brightness = led_cdev->max_brightness; - if (!test_bit(NETDEV_LED_MODE_LINKUP, &trigger_data->mode)) + if (!trigger_data->carrier_link_up) { led_set_brightness(led_cdev, LED_OFF); - else { - if (test_bit(NETDEV_LED_LINK, &trigger_data->mode)) + } else { + bool blink_on = false; + + if (test_bit(TRIGGER_NETDEV_LINK, &trigger_data->mode)) + blink_on = true; + + if (test_bit(TRIGGER_NETDEV_LINK_10, &trigger_data->mode) && + trigger_data->link_speed == SPEED_10) + blink_on = true; + + if (test_bit(TRIGGER_NETDEV_LINK_100, &trigger_data->mode) && + trigger_data->link_speed == SPEED_100) + blink_on = true; + + if (test_bit(TRIGGER_NETDEV_LINK_1000, &trigger_data->mode) && + trigger_data->link_speed == SPEED_1000) + blink_on = true; + + if (test_bit(TRIGGER_NETDEV_HALF_DUPLEX, &trigger_data->mode) && + trigger_data->duplex == DUPLEX_HALF) + blink_on = true; + + if (test_bit(TRIGGER_NETDEV_FULL_DUPLEX, &trigger_data->mode) && + trigger_data->duplex == DUPLEX_FULL) + blink_on = true; + + if (blink_on) led_set_brightness(led_cdev, led_cdev->blink_brightness); else @@ -85,44 +116,121 @@ static void set_baseline_state(struct led_netdev_data *trigger_data) /* If we are looking for RX/TX start periodically * checking stats */ - if (test_bit(NETDEV_LED_TX, &trigger_data->mode) || - test_bit(NETDEV_LED_RX, &trigger_data->mode)) + if (test_bit(TRIGGER_NETDEV_TX, &trigger_data->mode) || + test_bit(TRIGGER_NETDEV_RX, &trigger_data->mode)) schedule_delayed_work(&trigger_data->work, 0); } } +static bool supports_hw_control(struct led_classdev *led_cdev) +{ + if (!led_cdev->hw_control_get || !led_cdev->hw_control_set || + !led_cdev->hw_control_is_supported) + return false; + + return !strcmp(led_cdev->hw_control_trigger, led_cdev->trigger->name); +} + +/* + * Validate the configured netdev is the same as the one associated with + * the LED driver in hw control. + */ +static bool validate_net_dev(struct led_classdev *led_cdev, + struct net_device *net_dev) +{ + struct device *dev = led_cdev->hw_control_get_device(led_cdev); + struct net_device *ndev; + + if (!dev) + return false; + + ndev = to_net_dev(dev); + + return ndev == net_dev; +} + +static bool can_hw_control(struct led_netdev_data *trigger_data) +{ + unsigned long default_interval = msecs_to_jiffies(NETDEV_LED_DEFAULT_INTERVAL); + unsigned int interval = atomic_read(&trigger_data->interval); + struct led_classdev *led_cdev = trigger_data->led_cdev; + int ret; + + if (!supports_hw_control(led_cdev)) + return false; + + /* + * Interval must be set to the default + * value. Any different value is rejected if in hw + * control. + */ + if (interval != default_interval) + return false; + + /* + * net_dev must be set with hw control, otherwise no + * blinking can be happening and there is nothing to + * offloaded. Additionally, for hw control to be + * valid, the configured netdev must be the same as + * netdev associated to the LED. + */ + if (!validate_net_dev(led_cdev, trigger_data->net_dev)) + return false; + + /* Check if the requested mode is supported */ + ret = led_cdev->hw_control_is_supported(led_cdev, trigger_data->mode); + /* Fall back to software blinking if not supported */ + if (ret == -EOPNOTSUPP) + return false; + if (ret) { + dev_warn(led_cdev->dev, + "Current mode check failed with error %d\n", ret); + return false; + } + + return true; +} + +static void get_device_state(struct led_netdev_data *trigger_data) +{ + struct ethtool_link_ksettings cmd; + + trigger_data->carrier_link_up = netif_carrier_ok(trigger_data->net_dev); + if (!trigger_data->carrier_link_up) + return; + + if (!__ethtool_get_link_ksettings(trigger_data->net_dev, &cmd)) { + trigger_data->link_speed = cmd.base.speed; + trigger_data->duplex = cmd.base.duplex; + } +} + static ssize_t device_name_show(struct device *dev, struct device_attribute *attr, char *buf) { struct led_netdev_data *trigger_data = led_trigger_get_drvdata(dev); ssize_t len; - spin_lock_bh(&trigger_data->lock); + mutex_lock(&trigger_data->lock); len = sprintf(buf, "%s\n", trigger_data->device_name); - spin_unlock_bh(&trigger_data->lock); + mutex_unlock(&trigger_data->lock); return len; } -static ssize_t device_name_store(struct device *dev, - struct device_attribute *attr, const char *buf, - size_t size) +static int set_device_name(struct led_netdev_data *trigger_data, + const char *name, size_t size) { - struct led_netdev_data *trigger_data = led_trigger_get_drvdata(dev); - - if (size >= IFNAMSIZ) - return -EINVAL; - cancel_delayed_work_sync(&trigger_data->work); - spin_lock_bh(&trigger_data->lock); + mutex_lock(&trigger_data->lock); if (trigger_data->net_dev) { dev_put(trigger_data->net_dev); trigger_data->net_dev = NULL; } - memcpy(trigger_data->device_name, buf, size); + memcpy(trigger_data->device_name, name, size); trigger_data->device_name[size] = 0; if (size > 0 && trigger_data->device_name[size - 1] == '\n') trigger_data->device_name[size - 1] = 0; @@ -131,36 +239,58 @@ static ssize_t device_name_store(struct device *dev, trigger_data->net_dev = dev_get_by_name(&init_net, trigger_data->device_name); - clear_bit(NETDEV_LED_MODE_LINKUP, &trigger_data->mode); - if (trigger_data->net_dev != NULL) - if (netif_carrier_ok(trigger_data->net_dev)) - set_bit(NETDEV_LED_MODE_LINKUP, &trigger_data->mode); + trigger_data->carrier_link_up = false; + trigger_data->link_speed = SPEED_UNKNOWN; + trigger_data->duplex = DUPLEX_UNKNOWN; + if (trigger_data->net_dev != NULL) { + rtnl_lock(); + get_device_state(trigger_data); + rtnl_unlock(); + } trigger_data->last_activity = 0; set_baseline_state(trigger_data); - spin_unlock_bh(&trigger_data->lock); + mutex_unlock(&trigger_data->lock); + + return 0; +} + +static ssize_t device_name_store(struct device *dev, + struct device_attribute *attr, const char *buf, + size_t size) +{ + struct led_netdev_data *trigger_data = led_trigger_get_drvdata(dev); + int ret; + if (size >= IFNAMSIZ) + return -EINVAL; + + ret = set_device_name(trigger_data, buf, size); + + if (ret < 0) + return ret; return size; } static DEVICE_ATTR_RW(device_name); static ssize_t netdev_led_attr_show(struct device *dev, char *buf, - enum netdev_led_attr attr) + enum led_trigger_netdev_modes attr) { struct led_netdev_data *trigger_data = led_trigger_get_drvdata(dev); int bit; switch (attr) { - case NETDEV_ATTR_LINK: - bit = NETDEV_LED_LINK; - break; - case NETDEV_ATTR_TX: - bit = NETDEV_LED_TX; - break; - case NETDEV_ATTR_RX: - bit = NETDEV_LED_RX; + case TRIGGER_NETDEV_LINK: + case TRIGGER_NETDEV_LINK_10: + case TRIGGER_NETDEV_LINK_100: + case TRIGGER_NETDEV_LINK_1000: + case TRIGGER_NETDEV_HALF_DUPLEX: + case TRIGGER_NETDEV_FULL_DUPLEX: + case TRIGGER_NETDEV_TX: + case TRIGGER_NETDEV_RX: + bit = attr; break; default: return -EINVAL; @@ -170,10 +300,10 @@ static ssize_t netdev_led_attr_show(struct device *dev, char *buf, } static ssize_t netdev_led_attr_store(struct device *dev, const char *buf, - size_t size, enum netdev_led_attr attr) + size_t size, enum led_trigger_netdev_modes attr) { struct led_netdev_data *trigger_data = led_trigger_get_drvdata(dev); - unsigned long state; + unsigned long state, mode = trigger_data->mode; int ret; int bit; @@ -182,72 +312,62 @@ static ssize_t netdev_led_attr_store(struct device *dev, const char *buf, return ret; switch (attr) { - case NETDEV_ATTR_LINK: - bit = NETDEV_LED_LINK; - break; - case NETDEV_ATTR_TX: - bit = NETDEV_LED_TX; - break; - case NETDEV_ATTR_RX: - bit = NETDEV_LED_RX; + case TRIGGER_NETDEV_LINK: + case TRIGGER_NETDEV_LINK_10: + case TRIGGER_NETDEV_LINK_100: + case TRIGGER_NETDEV_LINK_1000: + case TRIGGER_NETDEV_HALF_DUPLEX: + case TRIGGER_NETDEV_FULL_DUPLEX: + case TRIGGER_NETDEV_TX: + case TRIGGER_NETDEV_RX: + bit = attr; break; default: return -EINVAL; } - cancel_delayed_work_sync(&trigger_data->work); - if (state) - set_bit(bit, &trigger_data->mode); + set_bit(bit, &mode); else - clear_bit(bit, &trigger_data->mode); - - set_baseline_state(trigger_data); - - return size; -} - -static ssize_t link_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return netdev_led_attr_show(dev, buf, NETDEV_ATTR_LINK); -} - -static ssize_t link_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t size) -{ - return netdev_led_attr_store(dev, buf, size, NETDEV_ATTR_LINK); -} + clear_bit(bit, &mode); -static DEVICE_ATTR_RW(link); - -static ssize_t tx_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return netdev_led_attr_show(dev, buf, NETDEV_ATTR_TX); -} + if (test_bit(TRIGGER_NETDEV_LINK, &mode) && + (test_bit(TRIGGER_NETDEV_LINK_10, &mode) || + test_bit(TRIGGER_NETDEV_LINK_100, &mode) || + test_bit(TRIGGER_NETDEV_LINK_1000, &mode))) + return -EINVAL; -static ssize_t tx_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t size) -{ - return netdev_led_attr_store(dev, buf, size, NETDEV_ATTR_TX); -} + cancel_delayed_work_sync(&trigger_data->work); -static DEVICE_ATTR_RW(tx); + trigger_data->mode = mode; + trigger_data->hw_control = can_hw_control(trigger_data); -static ssize_t rx_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return netdev_led_attr_show(dev, buf, NETDEV_ATTR_RX); -} + set_baseline_state(trigger_data); -static ssize_t rx_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t size) -{ - return netdev_led_attr_store(dev, buf, size, NETDEV_ATTR_RX); + return size; } -static DEVICE_ATTR_RW(rx); +#define DEFINE_NETDEV_TRIGGER(trigger_name, trigger) \ + static ssize_t trigger_name##_show(struct device *dev, \ + struct device_attribute *attr, char *buf) \ + { \ + return netdev_led_attr_show(dev, buf, trigger); \ + } \ + static ssize_t trigger_name##_store(struct device *dev, \ + struct device_attribute *attr, const char *buf, size_t size) \ + { \ + return netdev_led_attr_store(dev, buf, size, trigger); \ + } \ + static DEVICE_ATTR_RW(trigger_name) + +DEFINE_NETDEV_TRIGGER(link, TRIGGER_NETDEV_LINK); +DEFINE_NETDEV_TRIGGER(link_10, TRIGGER_NETDEV_LINK_10); +DEFINE_NETDEV_TRIGGER(link_100, TRIGGER_NETDEV_LINK_100); +DEFINE_NETDEV_TRIGGER(link_1000, TRIGGER_NETDEV_LINK_1000); +DEFINE_NETDEV_TRIGGER(half_duplex, TRIGGER_NETDEV_HALF_DUPLEX); +DEFINE_NETDEV_TRIGGER(full_duplex, TRIGGER_NETDEV_FULL_DUPLEX); +DEFINE_NETDEV_TRIGGER(tx, TRIGGER_NETDEV_TX); +DEFINE_NETDEV_TRIGGER(rx, TRIGGER_NETDEV_RX); static ssize_t interval_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -266,6 +386,9 @@ static ssize_t interval_store(struct device *dev, unsigned long value; int ret; + if (trigger_data->hw_control) + return -EINVAL; + ret = kstrtoul(buf, 0, &value); if (ret) return ret; @@ -283,12 +406,28 @@ static ssize_t interval_store(struct device *dev, static DEVICE_ATTR_RW(interval); +static ssize_t hw_control_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct led_netdev_data *trigger_data = led_trigger_get_drvdata(dev); + + return sprintf(buf, "%d\n", trigger_data->hw_control); +} + +static DEVICE_ATTR_RO(hw_control); + static struct attribute *netdev_trig_attrs[] = { &dev_attr_device_name.attr, &dev_attr_link.attr, + &dev_attr_link_10.attr, + &dev_attr_link_100.attr, + &dev_attr_link_1000.attr, + &dev_attr_full_duplex.attr, + &dev_attr_half_duplex.attr, &dev_attr_rx.attr, &dev_attr_tx.attr, &dev_attr_interval.attr, + &dev_attr_hw_control.attr, NULL }; ATTRIBUTE_GROUPS(netdev_trig); @@ -313,14 +452,17 @@ static int netdev_trig_notify(struct notifier_block *nb, cancel_delayed_work_sync(&trigger_data->work); - spin_lock_bh(&trigger_data->lock); + mutex_lock(&trigger_data->lock); - clear_bit(NETDEV_LED_MODE_LINKUP, &trigger_data->mode); + trigger_data->carrier_link_up = false; + trigger_data->link_speed = SPEED_UNKNOWN; + trigger_data->duplex = DUPLEX_UNKNOWN; switch (evt) { case NETDEV_CHANGENAME: + get_device_state(trigger_data); + fallthrough; case NETDEV_REGISTER: - if (trigger_data->net_dev) - dev_put(trigger_data->net_dev); + dev_put(trigger_data->net_dev); dev_hold(dev); trigger_data->net_dev = dev; break; @@ -330,14 +472,13 @@ static int netdev_trig_notify(struct notifier_block *nb, break; case NETDEV_UP: case NETDEV_CHANGE: - if (netif_carrier_ok(dev)) - set_bit(NETDEV_LED_MODE_LINKUP, &trigger_data->mode); + get_device_state(trigger_data); break; } set_baseline_state(trigger_data); - spin_unlock_bh(&trigger_data->lock); + mutex_unlock(&trigger_data->lock); return NOTIFY_DONE; } @@ -360,21 +501,26 @@ static void netdev_trig_work(struct work_struct *work) } /* If we are not looking for RX/TX then return */ - if (!test_bit(NETDEV_LED_TX, &trigger_data->mode) && - !test_bit(NETDEV_LED_RX, &trigger_data->mode)) + if (!test_bit(TRIGGER_NETDEV_TX, &trigger_data->mode) && + !test_bit(TRIGGER_NETDEV_RX, &trigger_data->mode)) return; dev_stats = dev_get_stats(trigger_data->net_dev, &temp); new_activity = - (test_bit(NETDEV_LED_TX, &trigger_data->mode) ? + (test_bit(TRIGGER_NETDEV_TX, &trigger_data->mode) ? dev_stats->tx_packets : 0) + - (test_bit(NETDEV_LED_RX, &trigger_data->mode) ? + (test_bit(TRIGGER_NETDEV_RX, &trigger_data->mode) ? dev_stats->rx_packets : 0); if (trigger_data->last_activity != new_activity) { led_stop_software_blink(trigger_data->led_cdev); - invert = test_bit(NETDEV_LED_LINK, &trigger_data->mode); + invert = test_bit(TRIGGER_NETDEV_LINK, &trigger_data->mode) || + test_bit(TRIGGER_NETDEV_LINK_10, &trigger_data->mode) || + test_bit(TRIGGER_NETDEV_LINK_100, &trigger_data->mode) || + test_bit(TRIGGER_NETDEV_LINK_1000, &trigger_data->mode) || + test_bit(TRIGGER_NETDEV_HALF_DUPLEX, &trigger_data->mode) || + test_bit(TRIGGER_NETDEV_FULL_DUPLEX, &trigger_data->mode); interval = jiffies_to_msecs( atomic_read(&trigger_data->interval)); /* base state is ON (link present) */ @@ -392,13 +538,15 @@ static void netdev_trig_work(struct work_struct *work) static int netdev_trig_activate(struct led_classdev *led_cdev) { struct led_netdev_data *trigger_data; + unsigned long mode = 0; + struct device *dev; int rc; trigger_data = kzalloc(sizeof(struct led_netdev_data), GFP_KERNEL); if (!trigger_data) return -ENOMEM; - spin_lock_init(&trigger_data->lock); + mutex_init(&trigger_data->lock); trigger_data->notifier.notifier_call = netdev_trig_notify; trigger_data->notifier.priority = 10; @@ -410,9 +558,24 @@ static int netdev_trig_activate(struct led_classdev *led_cdev) trigger_data->device_name[0] = 0; trigger_data->mode = 0; - atomic_set(&trigger_data->interval, msecs_to_jiffies(50)); + atomic_set(&trigger_data->interval, msecs_to_jiffies(NETDEV_LED_DEFAULT_INTERVAL)); trigger_data->last_activity = 0; + /* Check if hw control is active by default on the LED. + * Init already enabled mode in hw control. + */ + if (supports_hw_control(led_cdev) && + !led_cdev->hw_control_get(led_cdev, &mode)) { + dev = led_cdev->hw_control_get_device(led_cdev); + if (dev) { + const char *name = dev_name(dev); + + set_device_name(trigger_data, name, strlen(name)); + trigger_data->hw_control = true; + trigger_data->mode = mode; + } + } + led_set_trigger_data(led_cdev, trigger_data); rc = register_netdevice_notifier(&trigger_data->notifier); @@ -430,8 +593,7 @@ static void netdev_trig_deactivate(struct led_classdev *led_cdev) cancel_delayed_work_sync(&trigger_data->work); - if (trigger_data->net_dev) - dev_put(trigger_data->net_dev); + dev_put(trigger_data->net_dev); kfree(trigger_data); } diff --git a/drivers/macintosh/ams/ams-i2c.c b/drivers/macintosh/ams/ams-i2c.c index a4a1035eb412332e55b2caed28dbaca08f03d947..f9bfe84b1c73566cd0d50564e3ce73aaa187d309 100644 --- a/drivers/macintosh/ams/ams-i2c.c +++ b/drivers/macintosh/ams/ams-i2c.c @@ -69,7 +69,7 @@ static struct i2c_driver ams_i2c_driver = { .driver = { .name = "ams", }, - .probe_new = ams_i2c_probe, + .probe = ams_i2c_probe, .remove = ams_i2c_remove, .id_table = ams_id, }; diff --git a/drivers/macintosh/smu.c b/drivers/macintosh/smu.c index b495bfa7789625ad5d7bf9101ae2d45167b843e2..5183a00529f565b20d9bd941122524a2dae4c13a 100644 --- a/drivers/macintosh/smu.c +++ b/drivers/macintosh/smu.c @@ -33,7 +33,8 @@ #include #include #include -#include +#include +#include #include #include #include @@ -470,7 +471,7 @@ EXPORT_SYMBOL(smu_present); int __init smu_init (void) { struct device_node *np; - const u32 *data; + u64 data; int ret = 0; np = of_find_node_by_type(NULL, "smu"); @@ -514,8 +515,7 @@ int __init smu_init (void) ret = -ENXIO; goto fail_bootmem; } - data = of_get_property(smu->db_node, "reg", NULL); - if (data == NULL) { + if (of_property_read_reg(smu->db_node, 0, &data, NULL)) { printk(KERN_ERR "SMU: Can't find doorbell GPIO address !\n"); ret = -ENXIO; goto fail_db_node; @@ -525,7 +525,7 @@ int __init smu_init (void) * and ack. GPIOs are at 0x50, best would be to find that out * in the device-tree though. */ - smu->doorbell = *data; + smu->doorbell = data; if (smu->doorbell < 0x50) smu->doorbell += 0x50; @@ -534,13 +534,12 @@ int __init smu_init (void) smu->msg_node = of_find_node_by_name(NULL, "smu-interrupt"); if (smu->msg_node == NULL) break; - data = of_get_property(smu->msg_node, "reg", NULL); - if (data == NULL) { + if (of_property_read_reg(smu->msg_node, 0, &data, NULL)) { of_node_put(smu->msg_node); smu->msg_node = NULL; break; } - smu->msg = *data; + smu->msg = data; if (smu->msg < 0x50) smu->msg += 0x50; } while(0); diff --git a/drivers/macintosh/therm_adt746x.c b/drivers/macintosh/therm_adt746x.c index 384b87d661e1c507fe1a8bd1144f54aaadbcc105..53ea56b286f91166b4fb368bcac32075a4a050aa 100644 --- a/drivers/macintosh/therm_adt746x.c +++ b/drivers/macintosh/therm_adt746x.c @@ -598,7 +598,7 @@ static struct i2c_driver thermostat_driver = { .driver = { .name = "therm_adt746x", }, - .probe_new = probe_thermostat, + .probe = probe_thermostat, .remove = remove_thermostat, .id_table = therm_adt746x_id, }; diff --git a/drivers/macintosh/therm_windtunnel.c b/drivers/macintosh/therm_windtunnel.c index 22b15efcc0258af874dd267d68556e4fcca812a7..18a98245432103cfaf93a6ba5f897ac43e89f437 100644 --- a/drivers/macintosh/therm_windtunnel.c +++ b/drivers/macintosh/therm_windtunnel.c @@ -442,7 +442,7 @@ static struct i2c_driver g4fan_driver = { .driver = { .name = "therm_windtunnel", }, - .probe_new = do_probe, + .probe = do_probe, .remove = do_remove, .id_table = therm_windtunnel_id, }; diff --git a/drivers/macintosh/via-cuda.c b/drivers/macintosh/via-cuda.c index 5071289063f0395187116b024e78a9e06427f6f5..f8dd1e8315306fbd5ddcf2387b0f57976b29f04d 100644 --- a/drivers/macintosh/via-cuda.c +++ b/drivers/macintosh/via-cuda.c @@ -235,8 +235,7 @@ int __init find_via_cuda(void) int __init find_via_cuda(void) { struct adb_request req; - phys_addr_t taddr; - const u32 *reg; + struct resource res; int err; if (vias) @@ -245,17 +244,12 @@ int __init find_via_cuda(void) if (!vias) return 0; - reg = of_get_property(vias, "reg", NULL); - if (reg == NULL) { - printk(KERN_ERR "via-cuda: No \"reg\" property !\n"); - goto fail; - } - taddr = of_translate_address(vias, reg); - if (taddr == 0) { - printk(KERN_ERR "via-cuda: Can't translate address !\n"); + err = of_address_to_resource(vias, 0, &res); + if (err) { + printk(KERN_ERR "via-cuda: Error getting \"reg\" property !\n"); goto fail; } - via = ioremap(taddr, 0x2000); + via = ioremap(res.start, 0x2000); if (via == NULL) { printk(KERN_ERR "via-cuda: Can't map address !\n"); goto fail; diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c index e0cb8daf4f082743dde0e6ee4108086f0432059e..9d5703b6093759d8abfbd9e7e27be0a7c73bca04 100644 --- a/drivers/macintosh/via-pmu.c +++ b/drivers/macintosh/via-pmu.c @@ -286,8 +286,9 @@ static char *pbook_type[] = { int __init find_via_pmu(void) { #ifdef CONFIG_PPC_PMAC + int err; u64 taddr; - const u32 *reg; + struct resource res; if (pmu_state != uninitialized) return 1; @@ -295,16 +296,12 @@ int __init find_via_pmu(void) if (vias == NULL) return 0; - reg = of_get_property(vias, "reg", NULL); - if (reg == NULL) { - printk(KERN_ERR "via-pmu: No \"reg\" property !\n"); - goto fail; - } - taddr = of_translate_address(vias, reg); - if (taddr == OF_BAD_ADDR) { - printk(KERN_ERR "via-pmu: Can't translate address !\n"); + err = of_address_to_resource(vias, 0, &res); + if (err) { + printk(KERN_ERR "via-pmu: Error getting \"reg\" property !\n"); goto fail; } + taddr = res.start; pmu_has_adb = 1; @@ -324,7 +321,6 @@ int __init find_via_pmu(void) || of_device_is_compatible(vias->parent, "K2-Keylargo")) { struct device_node *gpiop; struct device_node *adbp; - u64 gaddr = OF_BAD_ADDR; pmu_kind = PMU_KEYLARGO_BASED; adbp = of_find_node_by_type(NULL, "adb"); @@ -338,11 +334,8 @@ int __init find_via_pmu(void) gpiop = of_find_node_by_name(NULL, "gpio"); if (gpiop) { - reg = of_get_property(gpiop, "reg", NULL); - if (reg) - gaddr = of_translate_address(gpiop, reg); - if (gaddr != OF_BAD_ADDR) - gpio_reg = ioremap(gaddr, 0x10); + if (!of_address_to_resource(gpiop, 0, &res)) + gpio_reg = ioremap(res.start, 0x10); of_node_put(gpiop); } if (gpio_reg == NULL) { diff --git a/drivers/macintosh/windfarm_ad7417_sensor.c b/drivers/macintosh/windfarm_ad7417_sensor.c index 33b4723d235e45da2076d8b3f847e71f2d335c5f..49ce37fde9300a15c064c5074c5687ca5c741474 100644 --- a/drivers/macintosh/windfarm_ad7417_sensor.c +++ b/drivers/macintosh/windfarm_ad7417_sensor.c @@ -320,7 +320,7 @@ static struct i2c_driver wf_ad7417_driver = { .name = "wf_ad7417", .of_match_table = wf_ad7417_of_id, }, - .probe_new = wf_ad7417_probe, + .probe = wf_ad7417_probe, .remove = wf_ad7417_remove, .id_table = wf_ad7417_id, }; diff --git a/drivers/macintosh/windfarm_fcu_controls.c b/drivers/macintosh/windfarm_fcu_controls.c index e027d889d7e80c070d091782a5ad1d5eeba822f2..603ef6c600ba8848e5358f5c601be03bda0c1732 100644 --- a/drivers/macintosh/windfarm_fcu_controls.c +++ b/drivers/macintosh/windfarm_fcu_controls.c @@ -589,7 +589,7 @@ static struct i2c_driver wf_fcu_driver = { .name = "wf_fcu", .of_match_table = wf_fcu_of_id, }, - .probe_new = wf_fcu_probe, + .probe = wf_fcu_probe, .remove = wf_fcu_remove, .id_table = wf_fcu_id, }; diff --git a/drivers/macintosh/windfarm_lm75_sensor.c b/drivers/macintosh/windfarm_lm75_sensor.c index 9c6febce2376ba84eee18d679d7d7b7d0bad7f3a..48dbdb2bda150a36dc1c0d0b0a9d1adc3e02e6d1 100644 --- a/drivers/macintosh/windfarm_lm75_sensor.c +++ b/drivers/macintosh/windfarm_lm75_sensor.c @@ -177,7 +177,7 @@ static struct i2c_driver wf_lm75_driver = { .name = "wf_lm75", .of_match_table = wf_lm75_of_id, }, - .probe_new = wf_lm75_probe, + .probe = wf_lm75_probe, .remove = wf_lm75_remove, .id_table = wf_lm75_id, }; diff --git a/drivers/macintosh/windfarm_lm87_sensor.c b/drivers/macintosh/windfarm_lm87_sensor.c index f37a32c2070ca010d376a0bf0c1dab5ca3b4bb3e..975361c23a93a8fb4cf257bbe4d09d9f1c2f1c64 100644 --- a/drivers/macintosh/windfarm_lm87_sensor.c +++ b/drivers/macintosh/windfarm_lm87_sensor.c @@ -172,7 +172,7 @@ static struct i2c_driver wf_lm87_driver = { .name = "wf_lm87", .of_match_table = wf_lm87_of_id, }, - .probe_new = wf_lm87_probe, + .probe = wf_lm87_probe, .remove = wf_lm87_remove, .id_table = wf_lm87_id, }; diff --git a/drivers/macintosh/windfarm_max6690_sensor.c b/drivers/macintosh/windfarm_max6690_sensor.c index 6c5ab657b6b39c7cbc061ff90295956ce7cb2a15..02856d1f031376f0e7fd1f90c8095fee5030f58b 100644 --- a/drivers/macintosh/windfarm_max6690_sensor.c +++ b/drivers/macintosh/windfarm_max6690_sensor.c @@ -128,7 +128,7 @@ static struct i2c_driver wf_max6690_driver = { .name = "wf_max6690", .of_match_table = wf_max6690_of_id, }, - .probe_new = wf_max6690_probe, + .probe = wf_max6690_probe, .remove = wf_max6690_remove, .id_table = wf_max6690_id, }; diff --git a/drivers/macintosh/windfarm_smu_sat.c b/drivers/macintosh/windfarm_smu_sat.c index 089f2743a070d163383a577c2e0878ab1c19833e..50baa062c9dfb8021a3cfe9bc0200193cb791201 100644 --- a/drivers/macintosh/windfarm_smu_sat.c +++ b/drivers/macintosh/windfarm_smu_sat.c @@ -349,7 +349,7 @@ static struct i2c_driver wf_sat_driver = { .name = "wf_smu_sat", .of_match_table = wf_sat_of_id, }, - .probe_new = wf_sat_probe, + .probe = wf_sat_probe, .remove = wf_sat_remove, .id_table = wf_sat_id, }; diff --git a/drivers/mailbox/tegra-hsp.c b/drivers/mailbox/tegra-hsp.c index 573481e436f54f949c25368454c6ceaa670e5540..7f98e7436d9448dccb235feff8aac74131516706 100644 --- a/drivers/mailbox/tegra-hsp.c +++ b/drivers/mailbox/tegra-hsp.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2016-2018, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2016-2023, NVIDIA CORPORATION. All rights reserved. */ #include @@ -97,6 +97,7 @@ struct tegra_hsp_soc { const struct tegra_hsp_db_map *map; bool has_per_mb_ie; bool has_128_bit_mb; + unsigned int reg_stride; }; struct tegra_hsp { @@ -279,7 +280,7 @@ tegra_hsp_doorbell_create(struct tegra_hsp *hsp, const char *name, return ERR_PTR(-ENOMEM); offset = (1 + (hsp->num_sm / 2) + hsp->num_ss + hsp->num_as) * SZ_64K; - offset += index * 0x100; + offset += index * hsp->soc->reg_stride; db->channel.regs = hsp->regs + offset; db->channel.hsp = hsp; @@ -916,24 +917,35 @@ static const struct tegra_hsp_soc tegra186_hsp_soc = { .map = tegra186_hsp_db_map, .has_per_mb_ie = false, .has_128_bit_mb = false, + .reg_stride = 0x100, }; static const struct tegra_hsp_soc tegra194_hsp_soc = { .map = tegra186_hsp_db_map, .has_per_mb_ie = true, .has_128_bit_mb = false, + .reg_stride = 0x100, }; static const struct tegra_hsp_soc tegra234_hsp_soc = { .map = tegra186_hsp_db_map, .has_per_mb_ie = false, .has_128_bit_mb = true, + .reg_stride = 0x100, +}; + +static const struct tegra_hsp_soc tegra264_hsp_soc = { + .map = tegra186_hsp_db_map, + .has_per_mb_ie = false, + .has_128_bit_mb = true, + .reg_stride = 0x1000, }; static const struct of_device_id tegra_hsp_match[] = { { .compatible = "nvidia,tegra186-hsp", .data = &tegra186_hsp_soc }, { .compatible = "nvidia,tegra194-hsp", .data = &tegra194_hsp_soc }, { .compatible = "nvidia,tegra234-hsp", .data = &tegra234_hsp_soc }, + { .compatible = "nvidia,tegra264-hsp", .data = &tegra264_hsp_soc }, { } }; diff --git a/drivers/mailbox/ti-msgmgr.c b/drivers/mailbox/ti-msgmgr.c index ddac423ac1a91aa884a9840aafceb8a016b137c4..03048cbda525e47d9b82a14f18649003d63e017b 100644 --- a/drivers/mailbox/ti-msgmgr.c +++ b/drivers/mailbox/ti-msgmgr.c @@ -430,14 +430,20 @@ static int ti_msgmgr_send_data(struct mbox_chan *chan, void *data) /* Ensure all unused data is 0 */ data_trail &= 0xFFFFFFFF >> (8 * (sizeof(u32) - trail_bytes)); writel(data_trail, data_reg); - data_reg++; + data_reg += sizeof(u32); } + /* * 'data_reg' indicates next register to write. If we did not already * write on tx complete reg(last reg), we must do so for transmit + * In addition, we also need to make sure all intermediate data + * registers(if any required), are reset to 0 for TISCI backward + * compatibility to be maintained. */ - if (data_reg <= qinst->queue_buff_end) - writel(0, qinst->queue_buff_end); + while (data_reg <= qinst->queue_buff_end) { + writel(0, data_reg); + data_reg += sizeof(u32); + } /* If we are in polled mode, wait for a response before proceeding */ if (ti_msgmgr_chan_has_polled_queue_rx(message->chan_rx)) diff --git a/drivers/md/bcache/bcache.h b/drivers/md/bcache/bcache.h index aebb7ef10e631a6c6fd5f9f4d11987eca86f99d0..5a79bb3c272f1ba9adfd786699f983ae4505c6a1 100644 --- a/drivers/md/bcache/bcache.h +++ b/drivers/md/bcache/bcache.h @@ -275,7 +275,7 @@ struct bcache_device { int (*cache_miss)(struct btree *b, struct search *s, struct bio *bio, unsigned int sectors); - int (*ioctl)(struct bcache_device *d, fmode_t mode, + int (*ioctl)(struct bcache_device *d, blk_mode_t mode, unsigned int cmd, unsigned long arg); }; @@ -1004,11 +1004,11 @@ extern struct workqueue_struct *bch_flush_wq; extern struct mutex bch_register_lock; extern struct list_head bch_cache_sets; -extern struct kobj_type bch_cached_dev_ktype; -extern struct kobj_type bch_flash_dev_ktype; -extern struct kobj_type bch_cache_set_ktype; -extern struct kobj_type bch_cache_set_internal_ktype; -extern struct kobj_type bch_cache_ktype; +extern const struct kobj_type bch_cached_dev_ktype; +extern const struct kobj_type bch_flash_dev_ktype; +extern const struct kobj_type bch_cache_set_ktype; +extern const struct kobj_type bch_cache_set_internal_ktype; +extern const struct kobj_type bch_cache_ktype; void bch_cached_dev_release(struct kobject *kobj); void bch_flash_dev_release(struct kobject *kobj); diff --git a/drivers/md/bcache/btree.c b/drivers/md/bcache/btree.c index 147c493a989a5e1fcc03039188c302c4321a2d33..fd121a61f17cca47ec0506aaa92dc24c11cc803f 100644 --- a/drivers/md/bcache/btree.c +++ b/drivers/md/bcache/btree.c @@ -559,6 +559,27 @@ static void mca_data_alloc(struct btree *b, struct bkey *k, gfp_t gfp) } } +#define cmp_int(l, r) ((l > r) - (l < r)) + +#ifdef CONFIG_PROVE_LOCKING +static int btree_lock_cmp_fn(const struct lockdep_map *_a, + const struct lockdep_map *_b) +{ + const struct btree *a = container_of(_a, struct btree, lock.dep_map); + const struct btree *b = container_of(_b, struct btree, lock.dep_map); + + return -cmp_int(a->level, b->level) ?: bkey_cmp(&a->key, &b->key); +} + +static void btree_lock_print_fn(const struct lockdep_map *map) +{ + const struct btree *b = container_of(map, struct btree, lock.dep_map); + + printk(KERN_CONT " l=%u %llu:%llu", b->level, + KEY_INODE(&b->key), KEY_OFFSET(&b->key)); +} +#endif + static struct btree *mca_bucket_alloc(struct cache_set *c, struct bkey *k, gfp_t gfp) { @@ -572,7 +593,7 @@ static struct btree *mca_bucket_alloc(struct cache_set *c, return NULL; init_rwsem(&b->lock); - lockdep_set_novalidate_class(&b->lock); + lock_set_cmp_fn(&b->lock, btree_lock_cmp_fn, btree_lock_print_fn); mutex_init(&b->write_lock); lockdep_set_novalidate_class(&b->write_lock); INIT_LIST_HEAD(&b->list); @@ -885,7 +906,7 @@ static struct btree *mca_cannibalize(struct cache_set *c, struct btree_op *op, * cannibalize_bucket() will take. This means every time we unlock the root of * the btree, we need to release this lock if we have it held. */ -static void bch_cannibalize_unlock(struct cache_set *c) +void bch_cannibalize_unlock(struct cache_set *c) { spin_lock(&c->btree_cannibalize_lock); if (c->btree_cache_alloc_lock == current) { @@ -1090,10 +1111,12 @@ struct btree *__bch_btree_node_alloc(struct cache_set *c, struct btree_op *op, struct btree *parent) { BKEY_PADDED(key) k; - struct btree *b = ERR_PTR(-EAGAIN); + struct btree *b; mutex_lock(&c->bucket_lock); retry: + /* return ERR_PTR(-EAGAIN) when it fails */ + b = ERR_PTR(-EAGAIN); if (__bch_bucket_alloc_set(c, RESERVE_BTREE, &k.key, wait)) goto err; @@ -1138,7 +1161,7 @@ static struct btree *btree_node_alloc_replacement(struct btree *b, { struct btree *n = bch_btree_node_alloc(b->c, op, b->level, b->parent); - if (!IS_ERR_OR_NULL(n)) { + if (!IS_ERR(n)) { mutex_lock(&n->write_lock); bch_btree_sort_into(&b->keys, &n->keys, &b->c->sort); bkey_copy_key(&n->key, &b->key); @@ -1340,7 +1363,7 @@ static int btree_gc_coalesce(struct btree *b, struct btree_op *op, memset(new_nodes, 0, sizeof(new_nodes)); closure_init_stack(&cl); - while (nodes < GC_MERGE_NODES && !IS_ERR_OR_NULL(r[nodes].b)) + while (nodes < GC_MERGE_NODES && !IS_ERR(r[nodes].b)) keys += r[nodes++].keys; blocks = btree_default_blocks(b->c) * 2 / 3; @@ -1352,7 +1375,7 @@ static int btree_gc_coalesce(struct btree *b, struct btree_op *op, for (i = 0; i < nodes; i++) { new_nodes[i] = btree_node_alloc_replacement(r[i].b, NULL); - if (IS_ERR_OR_NULL(new_nodes[i])) + if (IS_ERR(new_nodes[i])) goto out_nocoalesce; } @@ -1487,7 +1510,7 @@ static int btree_gc_coalesce(struct btree *b, struct btree_op *op, bch_keylist_free(&keylist); for (i = 0; i < nodes; i++) - if (!IS_ERR_OR_NULL(new_nodes[i])) { + if (!IS_ERR(new_nodes[i])) { btree_node_free(new_nodes[i]); rw_unlock(true, new_nodes[i]); } @@ -1669,7 +1692,7 @@ static int bch_btree_gc_root(struct btree *b, struct btree_op *op, if (should_rewrite) { n = btree_node_alloc_replacement(b, NULL); - if (!IS_ERR_OR_NULL(n)) { + if (!IS_ERR(n)) { bch_btree_node_write_sync(n); bch_btree_set_root(n); @@ -1968,6 +1991,15 @@ static int bch_btree_check_thread(void *arg) c->gc_stats.nodes++; bch_btree_op_init(&op, 0); ret = bcache_btree(check_recurse, p, c->root, &op); + /* + * The op may be added to cache_set's btree_cache_wait + * in mca_cannibalize(), must ensure it is removed from + * the list and release btree_cache_alloc_lock before + * free op memory. + * Otherwise, the btree_cache_wait will be damaged. + */ + bch_cannibalize_unlock(c); + finish_wait(&c->btree_cache_wait, &(&op)->wait); if (ret) goto out; } diff --git a/drivers/md/bcache/btree.h b/drivers/md/bcache/btree.h index 1b5fdbc0d83eba863d4915ee47b3a8c27643694e..45d64b54115a79a6ba0b8314187702460674d65b 100644 --- a/drivers/md/bcache/btree.h +++ b/drivers/md/bcache/btree.h @@ -247,8 +247,8 @@ static inline void bch_btree_op_init(struct btree_op *op, int write_lock_level) static inline void rw_lock(bool w, struct btree *b, int level) { - w ? down_write_nested(&b->lock, level + 1) - : down_read_nested(&b->lock, level + 1); + w ? down_write(&b->lock) + : down_read(&b->lock); if (w) b->seq++; } @@ -282,6 +282,7 @@ void bch_initial_gc_finish(struct cache_set *c); void bch_moving_gc(struct cache_set *c); int bch_btree_check(struct cache_set *c); void bch_initial_mark_key(struct cache_set *c, int level, struct bkey *k); +void bch_cannibalize_unlock(struct cache_set *c); static inline void wake_up_gc(struct cache_set *c) { diff --git a/drivers/md/bcache/request.c b/drivers/md/bcache/request.c index 67a2e29e0b40e08f2961eb3d46caa57e7071daa7..a9b1f3896249b3da67587076cbf816306709a99f 100644 --- a/drivers/md/bcache/request.c +++ b/drivers/md/bcache/request.c @@ -1228,7 +1228,7 @@ void cached_dev_submit_bio(struct bio *bio) detached_dev_do_request(d, bio, orig_bdev, start_time); } -static int cached_dev_ioctl(struct bcache_device *d, fmode_t mode, +static int cached_dev_ioctl(struct bcache_device *d, blk_mode_t mode, unsigned int cmd, unsigned long arg) { struct cached_dev *dc = container_of(d, struct cached_dev, disk); @@ -1318,7 +1318,7 @@ void flash_dev_submit_bio(struct bio *bio) continue_at(cl, search_free, NULL); } -static int flash_dev_ioctl(struct bcache_device *d, fmode_t mode, +static int flash_dev_ioctl(struct bcache_device *d, blk_mode_t mode, unsigned int cmd, unsigned long arg) { return -ENOTTY; diff --git a/drivers/md/bcache/stats.h b/drivers/md/bcache/stats.h index bd3afc856d53452bd96113b623ba6e1706aca153..21b445f8af158a300690d554236b0dc1c6a6ca0c 100644 --- a/drivers/md/bcache/stats.h +++ b/drivers/md/bcache/stats.h @@ -18,7 +18,6 @@ struct cache_stats { unsigned long cache_misses; unsigned long cache_bypass_hits; unsigned long cache_bypass_misses; - unsigned long cache_readaheads; unsigned long cache_miss_collisions; unsigned long sectors_bypassed; diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c index 7e9d19fd21ddd532c1bfcc68a3f0601e943d508f..0ae2b3676293074a1621226ceee76f0cac6b5d63 100644 --- a/drivers/md/bcache/super.c +++ b/drivers/md/bcache/super.c @@ -732,9 +732,9 @@ static int prio_read(struct cache *ca, uint64_t bucket) /* Bcache device */ -static int open_dev(struct block_device *b, fmode_t mode) +static int open_dev(struct gendisk *disk, blk_mode_t mode) { - struct bcache_device *d = b->bd_disk->private_data; + struct bcache_device *d = disk->private_data; if (test_bit(BCACHE_DEV_CLOSING, &d->flags)) return -ENXIO; @@ -743,14 +743,14 @@ static int open_dev(struct block_device *b, fmode_t mode) return 0; } -static void release_dev(struct gendisk *b, fmode_t mode) +static void release_dev(struct gendisk *b) { struct bcache_device *d = b->private_data; closure_put(&d->cl); } -static int ioctl_dev(struct block_device *b, fmode_t mode, +static int ioctl_dev(struct block_device *b, blk_mode_t mode, unsigned int cmd, unsigned long arg) { struct bcache_device *d = b->bd_disk->private_data; @@ -1369,7 +1369,7 @@ static void cached_dev_free(struct closure *cl) put_page(virt_to_page(dc->sb_disk)); if (!IS_ERR_OR_NULL(dc->bdev)) - blkdev_put(dc->bdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL); + blkdev_put(dc->bdev, dc); wake_up(&unregister_wait); @@ -1453,7 +1453,6 @@ static int register_bdev(struct cache_sb *sb, struct cache_sb_disk *sb_disk, memcpy(&dc->sb, sb, sizeof(struct cache_sb)); dc->bdev = bdev; - dc->bdev->bd_holder = dc; dc->sb_disk = sb_disk; if (cached_dev_init(dc, sb->block_size << 9)) @@ -1723,7 +1722,7 @@ static void cache_set_flush(struct closure *cl) if (!IS_ERR_OR_NULL(c->gc_thread)) kthread_stop(c->gc_thread); - if (!IS_ERR_OR_NULL(c->root)) + if (!IS_ERR(c->root)) list_add(&c->root->list, &c->btree_cache); /* @@ -2087,7 +2086,7 @@ static int run_cache_set(struct cache_set *c) err = "cannot allocate new btree root"; c->root = __bch_btree_node_alloc(c, NULL, 0, true, NULL); - if (IS_ERR_OR_NULL(c->root)) + if (IS_ERR(c->root)) goto err; mutex_lock(&c->root->write_lock); @@ -2218,7 +2217,7 @@ void bch_cache_release(struct kobject *kobj) put_page(virt_to_page(ca->sb_disk)); if (!IS_ERR_OR_NULL(ca->bdev)) - blkdev_put(ca->bdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL); + blkdev_put(ca->bdev, ca); kfree(ca); module_put(THIS_MODULE); @@ -2345,7 +2344,6 @@ static int register_cache(struct cache_sb *sb, struct cache_sb_disk *sb_disk, memcpy(&ca->sb, sb, sizeof(struct cache_sb)); ca->bdev = bdev; - ca->bdev->bd_holder = ca; ca->sb_disk = sb_disk; if (bdev_max_discard_sectors((bdev))) @@ -2359,7 +2357,7 @@ static int register_cache(struct cache_sb *sb, struct cache_sb_disk *sb_disk, * call blkdev_put() to bdev in bch_cache_release(). So we * explicitly call blkdev_put() here. */ - blkdev_put(bdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL); + blkdev_put(bdev, ca); if (ret == -ENOMEM) err = "cache_alloc(): -ENOMEM"; else if (ret == -EPERM) @@ -2448,6 +2446,7 @@ struct async_reg_args { struct cache_sb *sb; struct cache_sb_disk *sb_disk; struct block_device *bdev; + void *holder; }; static void register_bdev_worker(struct work_struct *work) @@ -2455,22 +2454,13 @@ static void register_bdev_worker(struct work_struct *work) int fail = false; struct async_reg_args *args = container_of(work, struct async_reg_args, reg_work.work); - struct cached_dev *dc; - - dc = kzalloc(sizeof(*dc), GFP_KERNEL); - if (!dc) { - fail = true; - put_page(virt_to_page(args->sb_disk)); - blkdev_put(args->bdev, FMODE_READ | FMODE_WRITE | FMODE_EXCL); - goto out; - } mutex_lock(&bch_register_lock); - if (register_bdev(args->sb, args->sb_disk, args->bdev, dc) < 0) + if (register_bdev(args->sb, args->sb_disk, args->bdev, args->holder) + < 0) fail = true; mutex_unlock(&bch_register_lock); -out: if (fail) pr_info("error %s: fail to register backing device\n", args->path); @@ -2485,21 +2475,11 @@ static void register_cache_worker(struct work_struct *work) int fail = false; struct async_reg_args *args = container_of(work, struct async_reg_args, reg_work.work); - struct cache *ca; - - ca = kzalloc(sizeof(*ca), GFP_KERNEL); - if (!ca) { - fail = true; - put_page(virt_to_page(args->sb_disk)); - blkdev_put(args->bdev, FMODE_READ | FMODE_WRITE | FMODE_EXCL); - goto out; - } /* blkdev_put() will be called in bch_cache_release() */ - if (register_cache(args->sb, args->sb_disk, args->bdev, ca) != 0) + if (register_cache(args->sb, args->sb_disk, args->bdev, args->holder)) fail = true; -out: if (fail) pr_info("error %s: fail to register cache device\n", args->path); @@ -2520,6 +2500,13 @@ static void register_device_async(struct async_reg_args *args) queue_delayed_work(system_wq, &args->reg_work, 10); } +static void *alloc_holder_object(struct cache_sb *sb) +{ + if (SB_IS_BDEV(sb)) + return kzalloc(sizeof(struct cached_dev), GFP_KERNEL); + return kzalloc(sizeof(struct cache), GFP_KERNEL); +} + static ssize_t register_bcache(struct kobject *k, struct kobj_attribute *attr, const char *buffer, size_t size) { @@ -2527,9 +2514,11 @@ static ssize_t register_bcache(struct kobject *k, struct kobj_attribute *attr, char *path = NULL; struct cache_sb *sb; struct cache_sb_disk *sb_disk; - struct block_device *bdev; + struct block_device *bdev, *bdev2; + void *holder = NULL; ssize_t ret; bool async_registration = false; + bool quiet = false; #ifdef CONFIG_BCACHE_ASYNC_REGISTRATION async_registration = true; @@ -2558,11 +2547,34 @@ static ssize_t register_bcache(struct kobject *k, struct kobj_attribute *attr, ret = -EINVAL; err = "failed to open device"; - bdev = blkdev_get_by_path(strim(path), - FMODE_READ|FMODE_WRITE|FMODE_EXCL, - sb); + bdev = blkdev_get_by_path(strim(path), BLK_OPEN_READ, NULL, NULL); + if (IS_ERR(bdev)) + goto out_free_sb; + + err = "failed to set blocksize"; + if (set_blocksize(bdev, 4096)) + goto out_blkdev_put; + + err = read_super(sb, bdev, &sb_disk); + if (err) + goto out_blkdev_put; + + holder = alloc_holder_object(sb); + if (!holder) { + ret = -ENOMEM; + err = "cannot allocate memory"; + goto out_put_sb_page; + } + + /* Now reopen in exclusive mode with proper holder */ + bdev2 = blkdev_get_by_dev(bdev->bd_dev, BLK_OPEN_READ | BLK_OPEN_WRITE, + holder, NULL); + blkdev_put(bdev, NULL); + bdev = bdev2; if (IS_ERR(bdev)) { - if (bdev == ERR_PTR(-EBUSY)) { + ret = PTR_ERR(bdev); + bdev = NULL; + if (ret == -EBUSY) { dev_t dev; mutex_lock(&bch_register_lock); @@ -2572,20 +2584,14 @@ static ssize_t register_bcache(struct kobject *k, struct kobj_attribute *attr, else err = "device busy"; mutex_unlock(&bch_register_lock); - if (attr == &ksysfs_register_quiet) - goto done; + if (attr == &ksysfs_register_quiet) { + quiet = true; + ret = size; + } } - goto out_free_sb; + goto out_free_holder; } - err = "failed to set blocksize"; - if (set_blocksize(bdev, 4096)) - goto out_blkdev_put; - - err = read_super(sb, bdev, &sb_disk); - if (err) - goto out_blkdev_put; - err = "failed to register device"; if (async_registration) { @@ -2596,59 +2602,46 @@ static ssize_t register_bcache(struct kobject *k, struct kobj_attribute *attr, if (!args) { ret = -ENOMEM; err = "cannot allocate memory"; - goto out_put_sb_page; + goto out_free_holder; } args->path = path; args->sb = sb; args->sb_disk = sb_disk; args->bdev = bdev; + args->holder = holder; register_device_async(args); /* No wait and returns to user space */ goto async_done; } if (SB_IS_BDEV(sb)) { - struct cached_dev *dc = kzalloc(sizeof(*dc), GFP_KERNEL); - - if (!dc) { - ret = -ENOMEM; - err = "cannot allocate memory"; - goto out_put_sb_page; - } - mutex_lock(&bch_register_lock); - ret = register_bdev(sb, sb_disk, bdev, dc); + ret = register_bdev(sb, sb_disk, bdev, holder); mutex_unlock(&bch_register_lock); /* blkdev_put() will be called in cached_dev_free() */ if (ret < 0) goto out_free_sb; } else { - struct cache *ca = kzalloc(sizeof(*ca), GFP_KERNEL); - - if (!ca) { - ret = -ENOMEM; - err = "cannot allocate memory"; - goto out_put_sb_page; - } - /* blkdev_put() will be called in bch_cache_release() */ - ret = register_cache(sb, sb_disk, bdev, ca); + ret = register_cache(sb, sb_disk, bdev, holder); if (ret) goto out_free_sb; } -done: kfree(sb); kfree(path); module_put(THIS_MODULE); async_done: return size; +out_free_holder: + kfree(holder); out_put_sb_page: put_page(virt_to_page(sb_disk)); out_blkdev_put: - blkdev_put(bdev, FMODE_READ | FMODE_WRITE | FMODE_EXCL); + if (bdev) + blkdev_put(bdev, holder); out_free_sb: kfree(sb); out_free_path: @@ -2657,7 +2650,8 @@ static ssize_t register_bcache(struct kobject *k, struct kobj_attribute *attr, out_module_put: module_put(THIS_MODULE); out: - pr_info("error %s: %s\n", path?path:"", err); + if (!quiet) + pr_info("error %s: %s\n", path?path:"", err); return ret; } diff --git a/drivers/md/bcache/sysfs.c b/drivers/md/bcache/sysfs.c index c6f677059214d33b4f1177a0e4ec4b506194d20b..0e2c1880f60b294e59100808145eb33167d7862e 100644 --- a/drivers/md/bcache/sysfs.c +++ b/drivers/md/bcache/sysfs.c @@ -1111,26 +1111,25 @@ SHOW(__bch_cache) vfree(p); - ret = scnprintf(buf, PAGE_SIZE, - "Unused: %zu%%\n" - "Clean: %zu%%\n" - "Dirty: %zu%%\n" - "Metadata: %zu%%\n" - "Average: %llu\n" - "Sectors per Q: %zu\n" - "Quantiles: [", - unused * 100 / (size_t) ca->sb.nbuckets, - available * 100 / (size_t) ca->sb.nbuckets, - dirty * 100 / (size_t) ca->sb.nbuckets, - meta * 100 / (size_t) ca->sb.nbuckets, sum, - n * ca->sb.bucket_size / (ARRAY_SIZE(q) + 1)); + ret = sysfs_emit(buf, + "Unused: %zu%%\n" + "Clean: %zu%%\n" + "Dirty: %zu%%\n" + "Metadata: %zu%%\n" + "Average: %llu\n" + "Sectors per Q: %zu\n" + "Quantiles: [", + unused * 100 / (size_t) ca->sb.nbuckets, + available * 100 / (size_t) ca->sb.nbuckets, + dirty * 100 / (size_t) ca->sb.nbuckets, + meta * 100 / (size_t) ca->sb.nbuckets, sum, + n * ca->sb.bucket_size / (ARRAY_SIZE(q) + 1)); for (i = 0; i < ARRAY_SIZE(q); i++) - ret += scnprintf(buf + ret, PAGE_SIZE - ret, - "%u ", q[i]); + ret += sysfs_emit_at(buf, ret, "%u ", q[i]); ret--; - ret += scnprintf(buf + ret, PAGE_SIZE - ret, "]\n"); + ret += sysfs_emit_at(buf, ret, "]\n"); return ret; } diff --git a/drivers/md/bcache/sysfs.h b/drivers/md/bcache/sysfs.h index a2ff6447b699f595f6b7a1b0e1fe2504972b067c..65b8bd975ab1eb948baf670264ff622845de1eab 100644 --- a/drivers/md/bcache/sysfs.h +++ b/drivers/md/bcache/sysfs.h @@ -3,7 +3,7 @@ #define _BCACHE_SYSFS_H_ #define KTYPE(type) \ -struct kobj_type type ## _ktype = { \ +const struct kobj_type type ## _ktype = { \ .release = type ## _release, \ .sysfs_ops = &((const struct sysfs_ops) { \ .show = type ## _show, \ diff --git a/drivers/md/bcache/writeback.c b/drivers/md/bcache/writeback.c index d4a5fc0650bb2902dbdb674547e2082809da2f2a..24c049067f61ae6ec9e9c0280e948becb2943f88 100644 --- a/drivers/md/bcache/writeback.c +++ b/drivers/md/bcache/writeback.c @@ -890,6 +890,16 @@ static int bch_root_node_dirty_init(struct cache_set *c, if (ret < 0) pr_warn("sectors dirty init failed, ret=%d!\n", ret); + /* + * The op may be added to cache_set's btree_cache_wait + * in mca_cannibalize(), must ensure it is removed from + * the list and release btree_cache_alloc_lock before + * free op memory. + * Otherwise, the btree_cache_wait will be damaged. + */ + bch_cannibalize_unlock(c); + finish_wait(&c->btree_cache_wait, &(&op.op)->wait); + return ret; } diff --git a/drivers/md/dm-bufio.c b/drivers/md/dm-bufio.c index eea977662e8141b7a9a9dfec959436e5ad0bae88..bc309e41d074aeb453825511f2b996d6c5917dae 100644 --- a/drivers/md/dm-bufio.c +++ b/drivers/md/dm-bufio.c @@ -1157,23 +1157,6 @@ static void *alloc_buffer_data(struct dm_bufio_client *c, gfp_t gfp_mask, *data_mode = DATA_MODE_VMALLOC; - /* - * __vmalloc allocates the data pages and auxiliary structures with - * gfp_flags that were specified, but pagetables are always allocated - * with GFP_KERNEL, no matter what was specified as gfp_mask. - * - * Consequently, we must set per-process flag PF_MEMALLOC_NOIO so that - * all allocations done by this process (including pagetables) are done - * as if GFP_NOIO was specified. - */ - if (gfp_mask & __GFP_NORETRY) { - unsigned int noio_flag = memalloc_noio_save(); - void *ptr = __vmalloc(c->block_size, gfp_mask); - - memalloc_noio_restore(noio_flag); - return ptr; - } - return __vmalloc(c->block_size, gfp_mask); } @@ -2592,6 +2575,13 @@ void dm_bufio_client_destroy(struct dm_bufio_client *c) } EXPORT_SYMBOL_GPL(dm_bufio_client_destroy); +void dm_bufio_client_reset(struct dm_bufio_client *c) +{ + drop_buffers(c); + flush_work(&c->shrink_work); +} +EXPORT_SYMBOL_GPL(dm_bufio_client_reset); + void dm_bufio_set_sector_offset(struct dm_bufio_client *c, sector_t start) { c->start = start; diff --git a/drivers/md/dm-cache-metadata.c b/drivers/md/dm-cache-metadata.c index 9e0c69958587209a0fb3af47c42446f4d2b58910..acffed750e3edc8d248a409626e49ba57172e5c6 100644 --- a/drivers/md/dm-cache-metadata.c +++ b/drivers/md/dm-cache-metadata.c @@ -1828,7 +1828,7 @@ int dm_cache_metadata_abort(struct dm_cache_metadata *cmd) * Replacement block manager (new_bm) is created and old_bm destroyed outside of * cmd root_lock to avoid ABBA deadlock that would result (due to life-cycle of * shrinker associated with the block manager's bufio client vs cmd root_lock). - * - must take shrinker_mutex without holding cmd->root_lock + * - must take shrinker_rwsem without holding cmd->root_lock */ new_bm = dm_block_manager_create(cmd->bdev, DM_CACHE_METADATA_BLOCK_SIZE << SECTOR_SHIFT, CACHE_MAX_CONCURRENT_LOCKS); diff --git a/drivers/md/dm-cache-target.c b/drivers/md/dm-cache-target.c index 872896218550c99d80ec9336565431a5fd5e403b..911f73f7ebbaa07b4fe345d4471ba1106a9e2190 100644 --- a/drivers/md/dm-cache-target.c +++ b/drivers/md/dm-cache-target.c @@ -2051,8 +2051,8 @@ static int parse_metadata_dev(struct cache_args *ca, struct dm_arg_set *as, if (!at_least_one_arg(as, error)) return -EINVAL; - r = dm_get_device(ca->ti, dm_shift_arg(as), FMODE_READ | FMODE_WRITE, - &ca->metadata_dev); + r = dm_get_device(ca->ti, dm_shift_arg(as), + BLK_OPEN_READ | BLK_OPEN_WRITE, &ca->metadata_dev); if (r) { *error = "Error opening metadata device"; return r; @@ -2074,8 +2074,8 @@ static int parse_cache_dev(struct cache_args *ca, struct dm_arg_set *as, if (!at_least_one_arg(as, error)) return -EINVAL; - r = dm_get_device(ca->ti, dm_shift_arg(as), FMODE_READ | FMODE_WRITE, - &ca->cache_dev); + r = dm_get_device(ca->ti, dm_shift_arg(as), + BLK_OPEN_READ | BLK_OPEN_WRITE, &ca->cache_dev); if (r) { *error = "Error opening cache device"; return r; @@ -2093,8 +2093,8 @@ static int parse_origin_dev(struct cache_args *ca, struct dm_arg_set *as, if (!at_least_one_arg(as, error)) return -EINVAL; - r = dm_get_device(ca->ti, dm_shift_arg(as), FMODE_READ | FMODE_WRITE, - &ca->origin_dev); + r = dm_get_device(ca->ti, dm_shift_arg(as), + BLK_OPEN_READ | BLK_OPEN_WRITE, &ca->origin_dev); if (r) { *error = "Error opening origin device"; return r; diff --git a/drivers/md/dm-clone-target.c b/drivers/md/dm-clone-target.c index f467cdb5a022377172e33e12b834777e909977dd..94b2fc33f64be3663ef6ee76276b54c7dcfa7d31 100644 --- a/drivers/md/dm-clone-target.c +++ b/drivers/md/dm-clone-target.c @@ -1683,8 +1683,8 @@ static int parse_metadata_dev(struct clone *clone, struct dm_arg_set *as, char * int r; sector_t metadata_dev_size; - r = dm_get_device(clone->ti, dm_shift_arg(as), FMODE_READ | FMODE_WRITE, - &clone->metadata_dev); + r = dm_get_device(clone->ti, dm_shift_arg(as), + BLK_OPEN_READ | BLK_OPEN_WRITE, &clone->metadata_dev); if (r) { *error = "Error opening metadata device"; return r; @@ -1703,8 +1703,8 @@ static int parse_dest_dev(struct clone *clone, struct dm_arg_set *as, char **err int r; sector_t dest_dev_size; - r = dm_get_device(clone->ti, dm_shift_arg(as), FMODE_READ | FMODE_WRITE, - &clone->dest_dev); + r = dm_get_device(clone->ti, dm_shift_arg(as), + BLK_OPEN_READ | BLK_OPEN_WRITE, &clone->dest_dev); if (r) { *error = "Error opening destination device"; return r; @@ -1725,7 +1725,7 @@ static int parse_source_dev(struct clone *clone, struct dm_arg_set *as, char **e int r; sector_t source_dev_size; - r = dm_get_device(clone->ti, dm_shift_arg(as), FMODE_READ, + r = dm_get_device(clone->ti, dm_shift_arg(as), BLK_OPEN_READ, &clone->source_dev); if (r) { *error = "Error opening source device"; diff --git a/drivers/md/dm-core.h b/drivers/md/dm-core.h index aecab0c0720f77ae2a0ab048304ea3d1023f9959..0d93661f88d306e0d0aa3a1ac085880a8b63d9d6 100644 --- a/drivers/md/dm-core.h +++ b/drivers/md/dm-core.h @@ -207,11 +207,10 @@ struct dm_table { unsigned integrity_added:1; /* - * Indicates the rw permissions for the new logical - * device. This should be a combination of FMODE_READ - * and FMODE_WRITE. + * Indicates the rw permissions for the new logical device. This + * should be a combination of BLK_OPEN_READ and BLK_OPEN_WRITE. */ - fmode_t mode; + blk_mode_t mode; /* a list of devices used by this table */ struct list_head devices; @@ -307,7 +306,8 @@ struct dm_io { */ enum { DM_IO_ACCOUNTED, - DM_IO_WAS_SPLIT + DM_IO_WAS_SPLIT, + DM_IO_BLK_STAT }; static inline bool dm_io_flagged(struct dm_io *io, unsigned int bit) diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index 8b47b913ee831c338b1294e31489ad7930225cce..1dc6227d353ec3b7984cd42d6666f39ab832685b 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c @@ -31,10 +31,10 @@ #include #include #include -#include #include #include #include +#include #include /* for struct rtattr and RTA macros only */ #include #include @@ -745,16 +745,23 @@ static int crypt_iv_eboiv_ctr(struct crypt_config *cc, struct dm_target *ti, static int crypt_iv_eboiv_gen(struct crypt_config *cc, u8 *iv, struct dm_crypt_request *dmreq) { - u8 buf[MAX_CIPHER_BLOCKSIZE] __aligned(__alignof__(__le64)); + struct crypto_skcipher *tfm = any_tfm(cc); struct skcipher_request *req; struct scatterlist src, dst; DECLARE_CRYPTO_WAIT(wait); + unsigned int reqsize; int err; + u8 *buf; - req = skcipher_request_alloc(any_tfm(cc), GFP_NOIO); + reqsize = ALIGN(crypto_skcipher_reqsize(tfm), __alignof__(__le64)); + + req = kmalloc(reqsize + cc->iv_size, GFP_NOIO); if (!req) return -ENOMEM; + skcipher_request_set_tfm(req, tfm); + + buf = (u8 *)req + reqsize; memset(buf, 0, cc->iv_size); *(__le64 *)buf = cpu_to_le64(dmreq->iv_sector * cc->sector_size); @@ -763,7 +770,7 @@ static int crypt_iv_eboiv_gen(struct crypt_config *cc, u8 *iv, skcipher_request_set_crypt(req, &src, &dst, cc->iv_size, buf); skcipher_request_set_callback(req, 0, crypto_req_done, &wait); err = crypto_wait_req(crypto_skcipher_encrypt(req), &wait); - skcipher_request_free(req); + kfree_sensitive(req); return err; } @@ -1661,6 +1668,9 @@ static void crypt_free_buffer_pages(struct crypt_config *cc, struct bio *clone); * In order to not degrade performance with excessive locking, we try * non-blocking allocations without a mutex first but on failure we fallback * to blocking allocations with a mutex. + * + * In order to reduce allocation overhead, we try to allocate compound pages in + * the first pass. If they are not available, we fall back to the mempool. */ static struct bio *crypt_alloc_buffer(struct dm_crypt_io *io, unsigned int size) { @@ -1668,8 +1678,8 @@ static struct bio *crypt_alloc_buffer(struct dm_crypt_io *io, unsigned int size) struct bio *clone; unsigned int nr_iovecs = (size + PAGE_SIZE - 1) >> PAGE_SHIFT; gfp_t gfp_mask = GFP_NOWAIT | __GFP_HIGHMEM; - unsigned int i, len, remaining_size; - struct page *page; + unsigned int remaining_size; + unsigned int order = MAX_ORDER - 1; retry: if (unlikely(gfp_mask & __GFP_DIRECT_RECLAIM)) @@ -1682,20 +1692,34 @@ static struct bio *crypt_alloc_buffer(struct dm_crypt_io *io, unsigned int size) remaining_size = size; - for (i = 0; i < nr_iovecs; i++) { - page = mempool_alloc(&cc->page_pool, gfp_mask); - if (!page) { + while (remaining_size) { + struct page *pages; + unsigned size_to_add; + unsigned remaining_order = __fls((remaining_size + PAGE_SIZE - 1) >> PAGE_SHIFT); + order = min(order, remaining_order); + + while (order > 0) { + pages = alloc_pages(gfp_mask + | __GFP_NOMEMALLOC | __GFP_NORETRY | __GFP_NOWARN | __GFP_COMP, + order); + if (likely(pages != NULL)) + goto have_pages; + order--; + } + + pages = mempool_alloc(&cc->page_pool, gfp_mask); + if (!pages) { crypt_free_buffer_pages(cc, clone); bio_put(clone); gfp_mask |= __GFP_DIRECT_RECLAIM; + order = 0; goto retry; } - len = (remaining_size > PAGE_SIZE) ? PAGE_SIZE : remaining_size; - - bio_add_page(clone, page, len, 0); - - remaining_size -= len; +have_pages: + size_to_add = min((unsigned)PAGE_SIZE << order, remaining_size); + __bio_add_page(clone, pages, size_to_add, 0); + remaining_size -= size_to_add; } /* Allocate space for integrity tags */ @@ -1713,12 +1737,15 @@ static struct bio *crypt_alloc_buffer(struct dm_crypt_io *io, unsigned int size) static void crypt_free_buffer_pages(struct crypt_config *cc, struct bio *clone) { - struct bio_vec *bv; - struct bvec_iter_all iter_all; + struct folio_iter fi; - bio_for_each_segment_all(bv, clone, iter_all) { - BUG_ON(!bv->bv_page); - mempool_free(bv->bv_page, &cc->page_pool); + if (clone->bi_vcnt > 0) { /* bio_for_each_folio_all crashes with an empty bio */ + bio_for_each_folio_all(fi, clone) { + if (folio_test_large(fi.folio)) + folio_put(fi.folio); + else + mempool_free(&fi.folio->page, &cc->page_pool); + } } } @@ -2888,7 +2915,7 @@ static int crypt_ctr_cipher_new(struct dm_target *ti, char *cipher_in, char *key ret = crypt_ctr_auth_cipher(cc, cipher_api); if (ret < 0) { ti->error = "Invalid AEAD cipher spec"; - return -ENOMEM; + return ret; } } @@ -3256,7 +3283,7 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv) cc->per_bio_data_size = ti->per_io_data_size = ALIGN(sizeof(struct dm_crypt_io) + cc->dmreq_start + additional_req_size, - ARCH_KMALLOC_MINALIGN); + ARCH_DMA_MINALIGN); ret = mempool_init(&cc->page_pool, BIO_MAX_VECS, crypt_page_alloc, crypt_page_free, cc); if (ret) { diff --git a/drivers/md/dm-era-target.c b/drivers/md/dm-era-target.c index 0d70914217eedcf715330cfa6f89d2469876c34a..6acfa5bf97a400078e2b5c8b3920d95345df0874 100644 --- a/drivers/md/dm-era-target.c +++ b/drivers/md/dm-era-target.c @@ -1482,14 +1482,16 @@ static int era_ctr(struct dm_target *ti, unsigned int argc, char **argv) era->ti = ti; - r = dm_get_device(ti, argv[0], FMODE_READ | FMODE_WRITE, &era->metadata_dev); + r = dm_get_device(ti, argv[0], BLK_OPEN_READ | BLK_OPEN_WRITE, + &era->metadata_dev); if (r) { ti->error = "Error opening metadata device"; era_destroy(era); return -EINVAL; } - r = dm_get_device(ti, argv[1], FMODE_READ | FMODE_WRITE, &era->origin_dev); + r = dm_get_device(ti, argv[1], BLK_OPEN_READ | BLK_OPEN_WRITE, + &era->origin_dev); if (r) { ti->error = "Error opening data device"; era_destroy(era); diff --git a/drivers/md/dm-flakey.c b/drivers/md/dm-flakey.c index bd80bcafbe5010df096cd7ed824e3b62a250bf99..120153e44ae0d374b011407f209968c4788c21d9 100644 --- a/drivers/md/dm-flakey.c +++ b/drivers/md/dm-flakey.c @@ -16,6 +16,8 @@ #define DM_MSG_PREFIX "flakey" +#define PROBABILITY_BASE 1000000000 + #define all_corrupt_bio_flags_match(bio, fc) \ (((bio)->bi_opf & (fc)->corrupt_bio_flags) == (fc)->corrupt_bio_flags) @@ -34,6 +36,8 @@ struct flakey_c { unsigned int corrupt_bio_rw; unsigned int corrupt_bio_value; blk_opf_t corrupt_bio_flags; + unsigned int random_read_corrupt; + unsigned int random_write_corrupt; }; enum feature_flag_bits { @@ -54,10 +58,11 @@ static int parse_features(struct dm_arg_set *as, struct flakey_c *fc, const char *arg_name; static const struct dm_arg _args[] = { - {0, 7, "Invalid number of feature args"}, + {0, 11, "Invalid number of feature args"}, {1, UINT_MAX, "Invalid corrupt bio byte"}, {0, 255, "Invalid corrupt value to write into bio byte (0-255)"}, {0, UINT_MAX, "Invalid corrupt bio flags mask"}, + {0, PROBABILITY_BASE, "Invalid random corrupt argument"}, }; /* No feature arguments supplied. */ @@ -170,6 +175,32 @@ static int parse_features(struct dm_arg_set *as, struct flakey_c *fc, continue; } + if (!strcasecmp(arg_name, "random_read_corrupt")) { + if (!argc) { + ti->error = "Feature random_read_corrupt requires a parameter"; + return -EINVAL; + } + r = dm_read_arg(_args + 4, as, &fc->random_read_corrupt, &ti->error); + if (r) + return r; + argc--; + + continue; + } + + if (!strcasecmp(arg_name, "random_write_corrupt")) { + if (!argc) { + ti->error = "Feature random_write_corrupt requires a parameter"; + return -EINVAL; + } + r = dm_read_arg(_args + 4, as, &fc->random_write_corrupt, &ti->error); + if (r) + return r; + argc--; + + continue; + } + ti->error = "Unrecognised flakey feature requested"; return -EINVAL; } @@ -184,7 +215,8 @@ static int parse_features(struct dm_arg_set *as, struct flakey_c *fc, } if (!fc->corrupt_bio_byte && !test_bit(ERROR_READS, &fc->flags) && - !test_bit(DROP_WRITES, &fc->flags) && !test_bit(ERROR_WRITES, &fc->flags)) { + !test_bit(DROP_WRITES, &fc->flags) && !test_bit(ERROR_WRITES, &fc->flags) && + !fc->random_read_corrupt && !fc->random_write_corrupt) { set_bit(ERROR_WRITES, &fc->flags); set_bit(ERROR_READS, &fc->flags); } @@ -306,40 +338,143 @@ static void flakey_map_bio(struct dm_target *ti, struct bio *bio) bio->bi_iter.bi_sector = flakey_map_sector(ti, bio->bi_iter.bi_sector); } -static void corrupt_bio_data(struct bio *bio, struct flakey_c *fc) +static void corrupt_bio_common(struct bio *bio, unsigned int corrupt_bio_byte, + unsigned char corrupt_bio_value) { - unsigned int corrupt_bio_byte = fc->corrupt_bio_byte - 1; - struct bvec_iter iter; struct bio_vec bvec; - if (!bio_has_data(bio)) - return; - /* * Overwrite the Nth byte of the bio's data, on whichever page * it falls. */ bio_for_each_segment(bvec, bio, iter) { if (bio_iter_len(bio, iter) > corrupt_bio_byte) { - char *segment; - struct page *page = bio_iter_page(bio, iter); - if (unlikely(page == ZERO_PAGE(0))) - break; - segment = bvec_kmap_local(&bvec); - segment[corrupt_bio_byte] = fc->corrupt_bio_value; + unsigned char *segment = bvec_kmap_local(&bvec); + segment[corrupt_bio_byte] = corrupt_bio_value; kunmap_local(segment); DMDEBUG("Corrupting data bio=%p by writing %u to byte %u " "(rw=%c bi_opf=%u bi_sector=%llu size=%u)\n", - bio, fc->corrupt_bio_value, fc->corrupt_bio_byte, + bio, corrupt_bio_value, corrupt_bio_byte, (bio_data_dir(bio) == WRITE) ? 'w' : 'r', bio->bi_opf, - (unsigned long long)bio->bi_iter.bi_sector, bio->bi_iter.bi_size); + (unsigned long long)bio->bi_iter.bi_sector, + bio->bi_iter.bi_size); break; } corrupt_bio_byte -= bio_iter_len(bio, iter); } } +static void corrupt_bio_data(struct bio *bio, struct flakey_c *fc) +{ + unsigned int corrupt_bio_byte = fc->corrupt_bio_byte - 1; + + if (!bio_has_data(bio)) + return; + + corrupt_bio_common(bio, corrupt_bio_byte, fc->corrupt_bio_value); +} + +static void corrupt_bio_random(struct bio *bio) +{ + unsigned int corrupt_byte; + unsigned char corrupt_value; + + if (!bio_has_data(bio)) + return; + + corrupt_byte = get_random_u32() % bio->bi_iter.bi_size; + corrupt_value = get_random_u8(); + + corrupt_bio_common(bio, corrupt_byte, corrupt_value); +} + +static void clone_free(struct bio *clone) +{ + struct folio_iter fi; + + if (clone->bi_vcnt > 0) { /* bio_for_each_folio_all crashes with an empty bio */ + bio_for_each_folio_all(fi, clone) + folio_put(fi.folio); + } + + bio_uninit(clone); + kfree(clone); +} + +static void clone_endio(struct bio *clone) +{ + struct bio *bio = clone->bi_private; + bio->bi_status = clone->bi_status; + clone_free(clone); + bio_endio(bio); +} + +static struct bio *clone_bio(struct dm_target *ti, struct flakey_c *fc, struct bio *bio) +{ + struct bio *clone; + unsigned size, remaining_size, nr_iovecs, order; + struct bvec_iter iter = bio->bi_iter; + + if (unlikely(bio->bi_iter.bi_size > UIO_MAXIOV << PAGE_SHIFT)) + dm_accept_partial_bio(bio, UIO_MAXIOV << PAGE_SHIFT >> SECTOR_SHIFT); + + size = bio->bi_iter.bi_size; + nr_iovecs = (size + PAGE_SIZE - 1) >> PAGE_SHIFT; + + clone = bio_kmalloc(nr_iovecs, GFP_NOIO | __GFP_NORETRY | __GFP_NOWARN); + if (!clone) + return NULL; + + bio_init(clone, fc->dev->bdev, bio->bi_inline_vecs, nr_iovecs, bio->bi_opf); + + clone->bi_iter.bi_sector = flakey_map_sector(ti, bio->bi_iter.bi_sector); + clone->bi_private = bio; + clone->bi_end_io = clone_endio; + + remaining_size = size; + + order = MAX_ORDER - 1; + while (remaining_size) { + struct page *pages; + unsigned size_to_add, to_copy; + unsigned char *virt; + unsigned remaining_order = __fls((remaining_size + PAGE_SIZE - 1) >> PAGE_SHIFT); + order = min(order, remaining_order); + +retry_alloc_pages: + pages = alloc_pages(GFP_NOIO | __GFP_NORETRY | __GFP_NOWARN | __GFP_COMP, order); + if (unlikely(!pages)) { + if (order) { + order--; + goto retry_alloc_pages; + } + clone_free(clone); + return NULL; + } + size_to_add = min((unsigned)PAGE_SIZE << order, remaining_size); + + virt = page_to_virt(pages); + to_copy = size_to_add; + do { + struct bio_vec bvec = bvec_iter_bvec(bio->bi_io_vec, iter); + unsigned this_step = min(bvec.bv_len, to_copy); + void *map = bvec_kmap_local(&bvec); + memcpy(virt, map, this_step); + kunmap_local(map); + + bvec_iter_advance(bio->bi_io_vec, &iter, this_step); + to_copy -= this_step; + virt += this_step; + } while (to_copy); + + __bio_add_page(clone, pages, size_to_add, 0); + remaining_size -= size_to_add; + } + + return clone; +} + static int flakey_map(struct dm_target *ti, struct bio *bio) { struct flakey_c *fc = ti->private; @@ -354,6 +489,7 @@ static int flakey_map(struct dm_target *ti, struct bio *bio) /* Are we alive ? */ elapsed = (jiffies - fc->start_time) / HZ; if (elapsed % (fc->up_interval + fc->down_interval) >= fc->up_interval) { + bool corrupt_fixed, corrupt_random; /* * Flag this bio as submitted while down. */ @@ -383,12 +519,28 @@ static int flakey_map(struct dm_target *ti, struct bio *bio) /* * Corrupt matching writes. */ - if (fc->corrupt_bio_byte) { - if (fc->corrupt_bio_rw == WRITE) { - if (all_corrupt_bio_flags_match(bio, fc)) - corrupt_bio_data(bio, fc); + corrupt_fixed = false; + corrupt_random = false; + if (fc->corrupt_bio_byte && fc->corrupt_bio_rw == WRITE) { + if (all_corrupt_bio_flags_match(bio, fc)) + corrupt_fixed = true; + } + if (fc->random_write_corrupt) { + u64 rnd = get_random_u64(); + u32 rem = do_div(rnd, PROBABILITY_BASE); + if (rem < fc->random_write_corrupt) + corrupt_random = true; + } + if (corrupt_fixed || corrupt_random) { + struct bio *clone = clone_bio(ti, fc, bio); + if (clone) { + if (corrupt_fixed) + corrupt_bio_data(clone, fc); + if (corrupt_random) + corrupt_bio_random(clone); + submit_bio(clone); + return DM_MAPIO_SUBMITTED; } - goto map_bio; } } @@ -417,6 +569,12 @@ static int flakey_end_io(struct dm_target *ti, struct bio *bio, corrupt_bio_data(bio, fc); } } + if (fc->random_read_corrupt) { + u64 rnd = get_random_u64(); + u32 rem = do_div(rnd, PROBABILITY_BASE); + if (rem < fc->random_read_corrupt) + corrupt_bio_random(bio); + } if (test_bit(ERROR_READS, &fc->flags)) { /* * Error read during the down_interval if drop_writes @@ -449,7 +607,10 @@ static void flakey_status(struct dm_target *ti, status_type_t type, error_reads = test_bit(ERROR_READS, &fc->flags); drop_writes = test_bit(DROP_WRITES, &fc->flags); error_writes = test_bit(ERROR_WRITES, &fc->flags); - DMEMIT(" %u", error_reads + drop_writes + error_writes + (fc->corrupt_bio_byte > 0) * 5); + DMEMIT(" %u", error_reads + drop_writes + error_writes + + (fc->corrupt_bio_byte > 0) * 5 + + (fc->random_read_corrupt > 0) * 2 + + (fc->random_write_corrupt > 0) * 2); if (error_reads) DMEMIT(" error_reads"); @@ -464,6 +625,11 @@ static void flakey_status(struct dm_target *ti, status_type_t type, (fc->corrupt_bio_rw == WRITE) ? 'w' : 'r', fc->corrupt_bio_value, fc->corrupt_bio_flags); + if (fc->random_read_corrupt > 0) + DMEMIT(" random_read_corrupt %u", fc->random_read_corrupt); + if (fc->random_write_corrupt > 0) + DMEMIT(" random_write_corrupt %u", fc->random_write_corrupt); + break; case STATUSTYPE_IMA: diff --git a/drivers/md/dm-init.c b/drivers/md/dm-init.c index d369457dbed0ed5b5c6a2be0b995a04ef1b78f16..2a71bcdba92d149ecfc8c92c2b1152bc9a8bf443 100644 --- a/drivers/md/dm-init.c +++ b/drivers/md/dm-init.c @@ -293,8 +293,10 @@ static int __init dm_init_init(void) for (i = 0; i < ARRAY_SIZE(waitfor); i++) { if (waitfor[i]) { + dev_t dev; + DMINFO("waiting for device %s ...", waitfor[i]); - while (!dm_get_dev_t(waitfor[i])) + while (early_lookup_bdev(waitfor[i], &dev)) fsleep(5000); } } diff --git a/drivers/md/dm-integrity.c b/drivers/md/dm-integrity.c index 31838b13ea54343c2c691448b252191dba6caed1..3d5c56e0a0628ca719a2d12b99e28763c0723c3d 100644 --- a/drivers/md/dm-integrity.c +++ b/drivers/md/dm-integrity.c @@ -34,11 +34,11 @@ #define DEFAULT_BUFFER_SECTORS 128 #define DEFAULT_JOURNAL_WATERMARK 50 #define DEFAULT_SYNC_MSEC 10000 -#define DEFAULT_MAX_JOURNAL_SECTORS 131072 +#define DEFAULT_MAX_JOURNAL_SECTORS (IS_ENABLED(CONFIG_64BIT) ? 131072 : 8192) #define MIN_LOG2_INTERLEAVE_SECTORS 3 #define MAX_LOG2_INTERLEAVE_SECTORS 31 #define METADATA_WORKQUEUE_MAX_ACTIVE 16 -#define RECALC_SECTORS 32768 +#define RECALC_SECTORS (IS_ENABLED(CONFIG_64BIT) ? 32768 : 2048) #define RECALC_WRITE_SUPER 16 #define BITMAP_BLOCK_SIZE 4096 /* don't change it */ #define BITMAP_FLUSH_INTERVAL (10 * HZ) @@ -251,8 +251,6 @@ struct dm_integrity_c { struct workqueue_struct *recalc_wq; struct work_struct recalc_work; - u8 *recalc_buffer; - u8 *recalc_tags; struct bio_list flush_bio_list; @@ -342,24 +340,9 @@ static struct kmem_cache *journal_io_cache; #define JOURNAL_IO_MEMPOOL 32 #ifdef DEBUG_PRINT -#define DEBUG_print(x, ...) printk(KERN_DEBUG x, ##__VA_ARGS__) -static void __DEBUG_bytes(__u8 *bytes, size_t len, const char *msg, ...) -{ - va_list args; - - va_start(args, msg); - vprintk(msg, args); - va_end(args); - if (len) - pr_cont(":"); - while (len) { - pr_cont(" %02x", *bytes); - bytes++; - len--; - } - pr_cont("\n"); -} -#define DEBUG_bytes(bytes, len, msg, ...) __DEBUG_bytes(bytes, len, KERN_DEBUG msg, ##__VA_ARGS__) +#define DEBUG_print(x, ...) printk(KERN_DEBUG x, ##__VA_ARGS__) +#define DEBUG_bytes(bytes, len, msg, ...) printk(KERN_DEBUG msg "%s%*ph\n", ##__VA_ARGS__, \ + len ? ": " : "", len, bytes) #else #define DEBUG_print(x, ...) do { } while (0) #define DEBUG_bytes(bytes, len, msg, ...) do { } while (0) @@ -2661,6 +2644,9 @@ static void recalc_write_super(struct dm_integrity_c *ic) static void integrity_recalc(struct work_struct *w) { struct dm_integrity_c *ic = container_of(w, struct dm_integrity_c, recalc_work); + size_t recalc_tags_size; + u8 *recalc_buffer = NULL; + u8 *recalc_tags = NULL; struct dm_integrity_range range; struct dm_io_request io_req; struct dm_io_region io_loc; @@ -2672,6 +2658,26 @@ static void integrity_recalc(struct work_struct *w) unsigned int i; int r; unsigned int super_counter = 0; + unsigned recalc_sectors = RECALC_SECTORS; + +retry: + recalc_buffer = __vmalloc(recalc_sectors << SECTOR_SHIFT, GFP_NOIO); + if (!recalc_buffer) { +oom: + recalc_sectors >>= 1; + if (recalc_sectors >= 1U << ic->sb->log2_sectors_per_block) + goto retry; + DMCRIT("out of memory for recalculate buffer - recalculation disabled"); + goto free_ret; + } + recalc_tags_size = (recalc_sectors >> ic->sb->log2_sectors_per_block) * ic->tag_size; + if (crypto_shash_digestsize(ic->internal_hash) > ic->tag_size) + recalc_tags_size += crypto_shash_digestsize(ic->internal_hash) - ic->tag_size; + recalc_tags = kvmalloc(recalc_tags_size, GFP_NOIO); + if (!recalc_tags) { + vfree(recalc_buffer); + goto oom; + } DEBUG_print("start recalculation... (position %llx)\n", le64_to_cpu(ic->sb->recalc_sector)); @@ -2693,7 +2699,7 @@ static void integrity_recalc(struct work_struct *w) } get_area_and_offset(ic, range.logical_sector, &area, &offset); - range.n_sectors = min((sector_t)RECALC_SECTORS, ic->provided_data_sectors - range.logical_sector); + range.n_sectors = min((sector_t)recalc_sectors, ic->provided_data_sectors - range.logical_sector); if (!ic->meta_dev) range.n_sectors = min(range.n_sectors, ((sector_t)1U << ic->sb->log2_interleave_sectors) - (unsigned int)offset); @@ -2735,7 +2741,7 @@ static void integrity_recalc(struct work_struct *w) io_req.bi_opf = REQ_OP_READ; io_req.mem.type = DM_IO_VMA; - io_req.mem.ptr.addr = ic->recalc_buffer; + io_req.mem.ptr.addr = recalc_buffer; io_req.notify.fn = NULL; io_req.client = ic->io; io_loc.bdev = ic->dev->bdev; @@ -2748,15 +2754,15 @@ static void integrity_recalc(struct work_struct *w) goto err; } - t = ic->recalc_tags; + t = recalc_tags; for (i = 0; i < n_sectors; i += ic->sectors_per_block) { - integrity_sector_checksum(ic, logical_sector + i, ic->recalc_buffer + (i << SECTOR_SHIFT), t); + integrity_sector_checksum(ic, logical_sector + i, recalc_buffer + (i << SECTOR_SHIFT), t); t += ic->tag_size; } metadata_block = get_metadata_sector_and_offset(ic, area, offset, &metadata_offset); - r = dm_integrity_rw_tag(ic, ic->recalc_tags, &metadata_block, &metadata_offset, t - ic->recalc_tags, TAG_WRITE); + r = dm_integrity_rw_tag(ic, recalc_tags, &metadata_block, &metadata_offset, t - recalc_tags, TAG_WRITE); if (unlikely(r)) { dm_integrity_io_error(ic, "writing tags", r); goto err; @@ -2784,12 +2790,16 @@ static void integrity_recalc(struct work_struct *w) err: remove_range(ic, &range); - return; + goto free_ret; unlock_ret: spin_unlock_irq(&ic->endio_wait.lock); recalc_write_super(ic); + +free_ret: + vfree(recalc_buffer); + kvfree(recalc_tags); } static void bitmap_block_work(struct work_struct *w) @@ -4268,10 +4278,10 @@ static int dm_integrity_ctr(struct dm_target *ti, unsigned int argc, char **argv } /* - * If this workqueue were percpu, it would cause bio reordering + * If this workqueue weren't ordered, it would cause bio reordering * and reduced performance. */ - ic->wait_wq = alloc_workqueue("dm-integrity-wait", WQ_MEM_RECLAIM | WQ_UNBOUND, 1); + ic->wait_wq = alloc_ordered_workqueue("dm-integrity-wait", WQ_MEM_RECLAIM); if (!ic->wait_wq) { ti->error = "Cannot allocate workqueue"; r = -ENOMEM; @@ -4454,8 +4464,6 @@ static int dm_integrity_ctr(struct dm_target *ti, unsigned int argc, char **argv } if (ic->internal_hash) { - size_t recalc_tags_size; - ic->recalc_wq = alloc_workqueue("dm-integrity-recalc", WQ_MEM_RECLAIM, 1); if (!ic->recalc_wq) { ti->error = "Cannot allocate workqueue"; @@ -4463,21 +4471,6 @@ static int dm_integrity_ctr(struct dm_target *ti, unsigned int argc, char **argv goto bad; } INIT_WORK(&ic->recalc_work, integrity_recalc); - ic->recalc_buffer = vmalloc(RECALC_SECTORS << SECTOR_SHIFT); - if (!ic->recalc_buffer) { - ti->error = "Cannot allocate buffer for recalculating"; - r = -ENOMEM; - goto bad; - } - recalc_tags_size = (RECALC_SECTORS >> ic->sb->log2_sectors_per_block) * ic->tag_size; - if (crypto_shash_digestsize(ic->internal_hash) > ic->tag_size) - recalc_tags_size += crypto_shash_digestsize(ic->internal_hash) - ic->tag_size; - ic->recalc_tags = kvmalloc(recalc_tags_size, GFP_KERNEL); - if (!ic->recalc_tags) { - ti->error = "Cannot allocate tags for recalculating"; - r = -ENOMEM; - goto bad; - } } else { if (ic->sb->flags & cpu_to_le32(SB_FLAG_RECALCULATING)) { ti->error = "Recalculate can only be specified with internal_hash"; @@ -4621,8 +4614,6 @@ static void dm_integrity_dtr(struct dm_target *ti) destroy_workqueue(ic->writer_wq); if (ic->recalc_wq) destroy_workqueue(ic->recalc_wq); - vfree(ic->recalc_buffer); - kvfree(ic->recalc_tags); kvfree(ic->bbs); if (ic->bufio) dm_bufio_client_destroy(ic->bufio); diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c index 7d5c9c582ed2d639f244ad998836c1e49fbbaad5..f5ed729a8e0cd300cd8acfb6864ae8c289da00ad 100644 --- a/drivers/md/dm-ioctl.c +++ b/drivers/md/dm-ioctl.c @@ -767,7 +767,14 @@ static int get_target_version(struct file *filp, struct dm_ioctl *param, size_t static int check_name(const char *name) { if (strchr(name, '/')) { - DMERR("invalid device name"); + DMERR("device name cannot contain '/'"); + return -EINVAL; + } + + if (strcmp(name, DM_CONTROL_NODE) == 0 || + strcmp(name, ".") == 0 || + strcmp(name, "..") == 0) { + DMERR("device name cannot be \"%s\", \".\", or \"..\"", DM_CONTROL_NODE); return -EINVAL; } @@ -861,7 +868,7 @@ static void __dev_status(struct mapped_device *md, struct dm_ioctl *param) table = dm_get_inactive_table(md, &srcu_idx); if (table) { - if (!(dm_table_get_mode(table) & FMODE_WRITE)) + if (!(dm_table_get_mode(table) & BLK_OPEN_WRITE)) param->flags |= DM_READONLY_FLAG; param->target_count = table->num_targets; } @@ -1189,7 +1196,7 @@ static int do_resume(struct dm_ioctl *param) if (old_size && new_size && old_size != new_size) need_resize_uevent = true; - if (dm_table_get_mode(new_map) & FMODE_WRITE) + if (dm_table_get_mode(new_map) & BLK_OPEN_WRITE) set_disk_ro(dm_disk(md), 0); else set_disk_ro(dm_disk(md), 1); @@ -1378,26 +1385,48 @@ static int dev_arm_poll(struct file *filp, struct dm_ioctl *param, size_t param_ return 0; } -static inline fmode_t get_mode(struct dm_ioctl *param) +static inline blk_mode_t get_mode(struct dm_ioctl *param) { - fmode_t mode = FMODE_READ | FMODE_WRITE; + blk_mode_t mode = BLK_OPEN_READ | BLK_OPEN_WRITE; if (param->flags & DM_READONLY_FLAG) - mode = FMODE_READ; + mode = BLK_OPEN_READ; return mode; } -static int next_target(struct dm_target_spec *last, uint32_t next, void *end, +static int next_target(struct dm_target_spec *last, uint32_t next, const char *end, struct dm_target_spec **spec, char **target_params) { - *spec = (struct dm_target_spec *) ((unsigned char *) last + next); - *target_params = (char *) (*spec + 1); + static_assert(__alignof__(struct dm_target_spec) <= 8, + "struct dm_target_spec must not require more than 8-byte alignment"); + + /* + * Number of bytes remaining, starting with last. This is always + * sizeof(struct dm_target_spec) or more, as otherwise *last was + * out of bounds already. + */ + size_t remaining = end - (char *)last; + + /* + * There must be room for both the next target spec and the + * NUL-terminator of the target itself. + */ + if (remaining - sizeof(struct dm_target_spec) <= next) { + DMERR("Target spec extends beyond end of parameters"); + return -EINVAL; + } - if (*spec < (last + 1)) + if (next % __alignof__(struct dm_target_spec)) { + DMERR("Next dm_target_spec (offset %u) is not %zu-byte aligned", + next, __alignof__(struct dm_target_spec)); return -EINVAL; + } + + *spec = (struct dm_target_spec *) ((unsigned char *) last + next); + *target_params = (char *) (*spec + 1); - return invalid_str(*target_params, end); + return 0; } static int populate_table(struct dm_table *table, @@ -1407,8 +1436,9 @@ static int populate_table(struct dm_table *table, unsigned int i = 0; struct dm_target_spec *spec = (struct dm_target_spec *) param; uint32_t next = param->data_start; - void *end = (void *) param + param_size; + const char *const end = (const char *) param + param_size; char *target_params; + size_t min_size = sizeof(struct dm_ioctl); if (!param->target_count) { DMERR("%s: no targets specified", __func__); @@ -1416,6 +1446,13 @@ static int populate_table(struct dm_table *table, } for (i = 0; i < param->target_count; i++) { + const char *nul_terminator; + + if (next < min_size) { + DMERR("%s: next target spec (offset %u) overlaps %s", + __func__, next, i ? "previous target" : "'struct dm_ioctl'"); + return -EINVAL; + } r = next_target(spec, next, end, &spec, &target_params); if (r) { @@ -1423,6 +1460,15 @@ static int populate_table(struct dm_table *table, return r; } + nul_terminator = memchr(target_params, 0, (size_t)(end - target_params)); + if (nul_terminator == NULL) { + DMERR("%s: target parameters not NUL-terminated", __func__); + return -EINVAL; + } + + /* Add 1 for NUL terminator */ + min_size = (size_t)(nul_terminator - (const char *)spec) + 1; + r = dm_table_add_target(table, spec->target_type, (sector_t) spec->sector_start, (sector_t) spec->length, @@ -1830,30 +1876,36 @@ static ioctl_fn lookup_ioctl(unsigned int cmd, int *ioctl_flags) * As well as checking the version compatibility this always * copies the kernel interface version out. */ -static int check_version(unsigned int cmd, struct dm_ioctl __user *user) +static int check_version(unsigned int cmd, struct dm_ioctl __user *user, + struct dm_ioctl *kernel_params) { - uint32_t version[3]; int r = 0; - if (copy_from_user(version, user->version, sizeof(version))) + /* Make certain version is first member of dm_ioctl struct */ + BUILD_BUG_ON(offsetof(struct dm_ioctl, version) != 0); + + if (copy_from_user(kernel_params->version, user->version, sizeof(kernel_params->version))) return -EFAULT; - if ((version[0] != DM_VERSION_MAJOR) || - (version[1] > DM_VERSION_MINOR)) { + if ((kernel_params->version[0] != DM_VERSION_MAJOR) || + (kernel_params->version[1] > DM_VERSION_MINOR)) { DMERR("ioctl interface mismatch: kernel(%u.%u.%u), user(%u.%u.%u), cmd(%d)", DM_VERSION_MAJOR, DM_VERSION_MINOR, DM_VERSION_PATCHLEVEL, - version[0], version[1], version[2], cmd); + kernel_params->version[0], + kernel_params->version[1], + kernel_params->version[2], + cmd); r = -EINVAL; } /* * Fill in the kernel version. */ - version[0] = DM_VERSION_MAJOR; - version[1] = DM_VERSION_MINOR; - version[2] = DM_VERSION_PATCHLEVEL; - if (copy_to_user(user->version, version, sizeof(version))) + kernel_params->version[0] = DM_VERSION_MAJOR; + kernel_params->version[1] = DM_VERSION_MINOR; + kernel_params->version[2] = DM_VERSION_PATCHLEVEL; + if (copy_to_user(user->version, kernel_params->version, sizeof(kernel_params->version))) return -EFAULT; return r; @@ -1877,9 +1929,11 @@ static int copy_params(struct dm_ioctl __user *user, struct dm_ioctl *param_kern struct dm_ioctl *dmi; int secure_data; const size_t minimum_data_size = offsetof(struct dm_ioctl, data); - unsigned int noio_flag; - if (copy_from_user(param_kernel, user, minimum_data_size)) + /* check_version() already copied version from userspace, avoid TOCTOU */ + if (copy_from_user((char *)param_kernel + sizeof(param_kernel->version), + (char __user *)user + sizeof(param_kernel->version), + minimum_data_size - sizeof(param_kernel->version))) return -EFAULT; if (param_kernel->data_size < minimum_data_size) { @@ -1904,9 +1958,7 @@ static int copy_params(struct dm_ioctl __user *user, struct dm_ioctl *param_kern * Use kmalloc() rather than vmalloc() when we can. */ dmi = NULL; - noio_flag = memalloc_noio_save(); - dmi = kvmalloc(param_kernel->data_size, GFP_KERNEL | __GFP_HIGH); - memalloc_noio_restore(noio_flag); + dmi = kvmalloc(param_kernel->data_size, GFP_NOIO | __GFP_HIGH); if (!dmi) { if (secure_data && clear_user(user, param_kernel->data_size)) @@ -1991,7 +2043,7 @@ static int ctl_ioctl(struct file *file, uint command, struct dm_ioctl __user *us * Check the interface version passed in. This also * writes out the kernel's interface version. */ - r = check_version(cmd, user); + r = check_version(cmd, user, ¶m_kernel); if (r) return r; diff --git a/drivers/md/dm-raid.c b/drivers/md/dm-raid.c index c8821fcb829986a0f32fad6be95c95033b514f53..8846bf510a35e04ec25b804dc82c4392968670af 100644 --- a/drivers/md/dm-raid.c +++ b/drivers/md/dm-raid.c @@ -3750,11 +3750,11 @@ static int raid_message(struct dm_target *ti, unsigned int argc, char **argv, * canceling read-auto mode */ mddev->ro = 0; - if (!mddev->suspended && mddev->sync_thread) + if (!mddev->suspended) md_wakeup_thread(mddev->sync_thread); } set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); - if (!mddev->suspended && mddev->thread) + if (!mddev->suspended) md_wakeup_thread(mddev->thread); return 0; diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c index 9c49f53760d06699e4f5bf1318a408254e914d4a..bf7a574499a34d3aba7d23cc93507abe4fca528d 100644 --- a/drivers/md/dm-snap.c +++ b/drivers/md/dm-snap.c @@ -1241,9 +1241,8 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv) int i; int r = -EINVAL; char *origin_path, *cow_path; - dev_t origin_dev, cow_dev; unsigned int args_used, num_flush_bios = 1; - fmode_t origin_mode = FMODE_READ; + blk_mode_t origin_mode = BLK_OPEN_READ; if (argc < 4) { ti->error = "requires 4 or more arguments"; @@ -1253,7 +1252,7 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv) if (dm_target_is_snapshot_merge(ti)) { num_flush_bios = 2; - origin_mode = FMODE_WRITE; + origin_mode = BLK_OPEN_WRITE; } s = kzalloc(sizeof(*s), GFP_KERNEL); @@ -1279,24 +1278,21 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv) ti->error = "Cannot get origin device"; goto bad_origin; } - origin_dev = s->origin->bdev->bd_dev; cow_path = argv[0]; argv++; argc--; - cow_dev = dm_get_dev_t(cow_path); - if (cow_dev && cow_dev == origin_dev) { - ti->error = "COW device cannot be the same as origin device"; - r = -EINVAL; - goto bad_cow; - } - r = dm_get_device(ti, cow_path, dm_table_get_mode(ti->table), &s->cow); if (r) { ti->error = "Cannot get COW device"; goto bad_cow; } + if (s->cow->bdev && s->cow->bdev == s->origin->bdev) { + ti->error = "COW device cannot be the same as origin device"; + r = -EINVAL; + goto bad_store; + } r = dm_exception_store_create(ti, argc, argv, s, &args_used, &s->store); if (r) { diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c index 1398f1d6e83e7f9da2ca1562c1024e6319ed0d8f..7d208b2b1a192d88eaaec34d5247d8f7ef6273e8 100644 --- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c @@ -126,7 +126,7 @@ static int alloc_targets(struct dm_table *t, unsigned int num) return 0; } -int dm_table_create(struct dm_table **result, fmode_t mode, +int dm_table_create(struct dm_table **result, blk_mode_t mode, unsigned int num_targets, struct mapped_device *md) { struct dm_table *t = kzalloc(sizeof(*t), GFP_KERNEL); @@ -304,7 +304,7 @@ static int device_area_is_invalid(struct dm_target *ti, struct dm_dev *dev, * device and not to touch the existing bdev field in case * it is accessed concurrently. */ -static int upgrade_mode(struct dm_dev_internal *dd, fmode_t new_mode, +static int upgrade_mode(struct dm_dev_internal *dd, blk_mode_t new_mode, struct mapped_device *md) { int r; @@ -323,24 +323,14 @@ static int upgrade_mode(struct dm_dev_internal *dd, fmode_t new_mode, return 0; } -/* - * Convert the path to a device - */ -dev_t dm_get_dev_t(const char *path) -{ - dev_t dev; - - if (lookup_bdev(path, &dev)) - dev = name_to_dev_t(path); - return dev; -} -EXPORT_SYMBOL_GPL(dm_get_dev_t); - /* * Add a device to the list, or just increment the usage count if * it's already present. + * + * Note: the __ref annotation is because this function can call the __init + * marked early_lookup_bdev when called during early boot code from dm-init.c. */ -int dm_get_device(struct dm_target *ti, const char *path, fmode_t mode, +int __ref dm_get_device(struct dm_target *ti, const char *path, blk_mode_t mode, struct dm_dev **result) { int r; @@ -358,9 +348,13 @@ int dm_get_device(struct dm_target *ti, const char *path, fmode_t mode, if (MAJOR(dev) != major || MINOR(dev) != minor) return -EOVERFLOW; } else { - dev = dm_get_dev_t(path); - if (!dev) - return -ENODEV; + r = lookup_bdev(path, &dev); +#ifndef MODULE + if (r && system_state < SYSTEM_RUNNING) + r = early_lookup_bdev(path, &dev); +#endif + if (r) + return r; } if (dev == disk_devt(t->md->disk)) return -EINVAL; @@ -668,7 +662,8 @@ int dm_table_add_target(struct dm_table *t, const char *type, t->singleton = true; } - if (dm_target_always_writeable(ti->type) && !(t->mode & FMODE_WRITE)) { + if (dm_target_always_writeable(ti->type) && + !(t->mode & BLK_OPEN_WRITE)) { ti->error = "target type may not be included in a read-only table"; goto bad; } @@ -2039,7 +2034,7 @@ struct list_head *dm_table_get_devices(struct dm_table *t) return &t->devices; } -fmode_t dm_table_get_mode(struct dm_table *t) +blk_mode_t dm_table_get_mode(struct dm_table *t) { return t->mode; } diff --git a/drivers/md/dm-thin-metadata.c b/drivers/md/dm-thin-metadata.c index b9461faa9f0df1dccef30684c37dff23577dc61f..6022189c13887bbe81c918effb83217c3886fd8c 100644 --- a/drivers/md/dm-thin-metadata.c +++ b/drivers/md/dm-thin-metadata.c @@ -603,6 +603,8 @@ static int __format_metadata(struct dm_pool_metadata *pmd) r = dm_tm_create_with_sm(pmd->bm, THIN_SUPERBLOCK_LOCATION, &pmd->tm, &pmd->metadata_sm); if (r < 0) { + pmd->tm = NULL; + pmd->metadata_sm = NULL; DMERR("tm_create_with_sm failed"); return r; } @@ -611,6 +613,7 @@ static int __format_metadata(struct dm_pool_metadata *pmd) if (IS_ERR(pmd->data_sm)) { DMERR("sm_disk_create failed"); r = PTR_ERR(pmd->data_sm); + pmd->data_sm = NULL; goto bad_cleanup_tm; } @@ -641,11 +644,15 @@ static int __format_metadata(struct dm_pool_metadata *pmd) bad_cleanup_nb_tm: dm_tm_destroy(pmd->nb_tm); + pmd->nb_tm = NULL; bad_cleanup_data_sm: dm_sm_destroy(pmd->data_sm); + pmd->data_sm = NULL; bad_cleanup_tm: dm_tm_destroy(pmd->tm); + pmd->tm = NULL; dm_sm_destroy(pmd->metadata_sm); + pmd->metadata_sm = NULL; return r; } @@ -711,6 +718,8 @@ static int __open_metadata(struct dm_pool_metadata *pmd) sizeof(disk_super->metadata_space_map_root), &pmd->tm, &pmd->metadata_sm); if (r < 0) { + pmd->tm = NULL; + pmd->metadata_sm = NULL; DMERR("tm_open_with_sm failed"); goto bad_unlock_sblock; } @@ -720,6 +729,7 @@ static int __open_metadata(struct dm_pool_metadata *pmd) if (IS_ERR(pmd->data_sm)) { DMERR("sm_disk_open failed"); r = PTR_ERR(pmd->data_sm); + pmd->data_sm = NULL; goto bad_cleanup_tm; } @@ -746,9 +756,12 @@ static int __open_metadata(struct dm_pool_metadata *pmd) bad_cleanup_data_sm: dm_sm_destroy(pmd->data_sm); + pmd->data_sm = NULL; bad_cleanup_tm: dm_tm_destroy(pmd->tm); + pmd->tm = NULL; dm_sm_destroy(pmd->metadata_sm); + pmd->metadata_sm = NULL; bad_unlock_sblock: dm_bm_unlock(sblock); @@ -795,9 +808,13 @@ static void __destroy_persistent_data_objects(struct dm_pool_metadata *pmd, bool destroy_bm) { dm_sm_destroy(pmd->data_sm); + pmd->data_sm = NULL; dm_sm_destroy(pmd->metadata_sm); + pmd->metadata_sm = NULL; dm_tm_destroy(pmd->nb_tm); + pmd->nb_tm = NULL; dm_tm_destroy(pmd->tm); + pmd->tm = NULL; if (destroy_bm) dm_block_manager_destroy(pmd->bm); } @@ -1005,8 +1022,7 @@ int dm_pool_metadata_close(struct dm_pool_metadata *pmd) __func__, r); } pmd_write_unlock(pmd); - if (!pmd->fail_io) - __destroy_persistent_data_objects(pmd, true); + __destroy_persistent_data_objects(pmd, true); kfree(pmd); return 0; @@ -1881,53 +1897,29 @@ static void __set_abort_with_changes_flags(struct dm_pool_metadata *pmd) int dm_pool_abort_metadata(struct dm_pool_metadata *pmd) { int r = -EINVAL; - struct dm_block_manager *old_bm = NULL, *new_bm = NULL; /* fail_io is double-checked with pmd->root_lock held below */ if (unlikely(pmd->fail_io)) return r; - /* - * Replacement block manager (new_bm) is created and old_bm destroyed outside of - * pmd root_lock to avoid ABBA deadlock that would result (due to life-cycle of - * shrinker associated with the block manager's bufio client vs pmd root_lock). - * - must take shrinker_mutex without holding pmd->root_lock - */ - new_bm = dm_block_manager_create(pmd->bdev, THIN_METADATA_BLOCK_SIZE << SECTOR_SHIFT, - THIN_MAX_CONCURRENT_LOCKS); - pmd_write_lock(pmd); if (pmd->fail_io) { pmd_write_unlock(pmd); - goto out; + return r; } - __set_abort_with_changes_flags(pmd); + + /* destroy data_sm/metadata_sm/nb_tm/tm */ __destroy_persistent_data_objects(pmd, false); - old_bm = pmd->bm; - if (IS_ERR(new_bm)) { - DMERR("could not create block manager during abort"); - pmd->bm = NULL; - r = PTR_ERR(new_bm); - goto out_unlock; - } - pmd->bm = new_bm; + /* reset bm */ + dm_block_manager_reset(pmd->bm); + + /* rebuild data_sm/metadata_sm/nb_tm/tm */ r = __open_or_format_metadata(pmd, false); - if (r) { - pmd->bm = NULL; - goto out_unlock; - } - new_bm = NULL; -out_unlock: if (r) pmd->fail_io = true; pmd_write_unlock(pmd); - dm_block_manager_destroy(old_bm); -out: - if (new_bm && !IS_ERR(new_bm)) - dm_block_manager_destroy(new_bm); - return r; } diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c index 39410bf186cf6ecbf4056814b271f4b3ce80330b..07c7f9795b107b9d36d80bc7b933ceb56282c8c2 100644 --- a/drivers/md/dm-thin.c +++ b/drivers/md/dm-thin.c @@ -2527,16 +2527,11 @@ static void noflush_work(struct thin_c *tc, void (*fn)(struct work_struct *)) /*----------------------------------------------------------------*/ -static bool passdown_enabled(struct pool_c *pt) -{ - return pt->adjusted_pf.discard_passdown; -} - static void set_discard_callbacks(struct pool *pool) { struct pool_c *pt = pool->ti->private; - if (passdown_enabled(pt)) { + if (pt->adjusted_pf.discard_passdown) { pool->process_discard_cell = process_discard_cell_passdown; pool->process_prepared_discard = process_prepared_discard_passdown_pt1; pool->process_prepared_discard_pt2 = process_prepared_discard_passdown_pt2; @@ -2845,7 +2840,7 @@ static bool is_factor(sector_t block_size, uint32_t n) * If discard_passdown was enabled verify that the data device * supports discards. Disable discard_passdown if not. */ -static void disable_passdown_if_not_supported(struct pool_c *pt) +static void disable_discard_passdown_if_not_supported(struct pool_c *pt) { struct pool *pool = pt->pool; struct block_device *data_bdev = pt->data_dev->bdev; @@ -3300,7 +3295,7 @@ static int pool_ctr(struct dm_target *ti, unsigned int argc, char **argv) unsigned long block_size; dm_block_t low_water_blocks; struct dm_dev *metadata_dev; - fmode_t metadata_mode; + blk_mode_t metadata_mode; /* * FIXME Remove validation from scope of lock. @@ -3333,7 +3328,8 @@ static int pool_ctr(struct dm_target *ti, unsigned int argc, char **argv) if (r) goto out_unlock; - metadata_mode = FMODE_READ | ((pf.mode == PM_READ_ONLY) ? 0 : FMODE_WRITE); + metadata_mode = BLK_OPEN_READ | + ((pf.mode == PM_READ_ONLY) ? 0 : BLK_OPEN_WRITE); r = dm_get_device(ti, argv[0], metadata_mode, &metadata_dev); if (r) { ti->error = "Error opening metadata block device"; @@ -3341,7 +3337,7 @@ static int pool_ctr(struct dm_target *ti, unsigned int argc, char **argv) } warn_if_metadata_device_too_big(metadata_dev->bdev); - r = dm_get_device(ti, argv[1], FMODE_READ | FMODE_WRITE, &data_dev); + r = dm_get_device(ti, argv[1], BLK_OPEN_READ | BLK_OPEN_WRITE, &data_dev); if (r) { ti->error = "Error getting data device"; goto out_metadata; @@ -3445,7 +3441,6 @@ static int pool_ctr(struct dm_target *ti, unsigned int argc, char **argv) static int pool_map(struct dm_target *ti, struct bio *bio) { - int r; struct pool_c *pt = ti->private; struct pool *pool = pt->pool; @@ -3454,10 +3449,9 @@ static int pool_map(struct dm_target *ti, struct bio *bio) */ spin_lock_irq(&pool->lock); bio_set_dev(bio, pt->data_dev->bdev); - r = DM_MAPIO_REMAPPED; spin_unlock_irq(&pool->lock); - return r; + return DM_MAPIO_REMAPPED; } static int maybe_resize_data_dev(struct dm_target *ti, bool *need_commit) @@ -4098,21 +4092,22 @@ static void pool_io_hints(struct dm_target *ti, struct queue_limits *limits) * They get transferred to the live pool in bind_control_target() * called from pool_preresume(). */ - if (!pt->adjusted_pf.discard_enabled) { + + if (pt->adjusted_pf.discard_enabled) { + disable_discard_passdown_if_not_supported(pt); + if (!pt->adjusted_pf.discard_passdown) + limits->max_discard_sectors = 0; + /* + * The pool uses the same discard limits as the underlying data + * device. DM core has already set this up. + */ + } else { /* * Must explicitly disallow stacking discard limits otherwise the * block layer will stack them if pool's data device has support. */ limits->discard_granularity = 0; - return; } - - disable_passdown_if_not_supported(pt); - - /* - * The pool uses the same discard limits as the underlying data - * device. DM core has already set this up. - */ } static struct target_type pool_target = { @@ -4222,7 +4217,7 @@ static int thin_ctr(struct dm_target *ti, unsigned int argc, char **argv) goto bad_origin_dev; } - r = dm_get_device(ti, argv[2], FMODE_READ, &origin_dev); + r = dm_get_device(ti, argv[2], BLK_OPEN_READ, &origin_dev); if (r) { ti->error = "Error opening origin device"; goto bad_origin_dev; @@ -4496,11 +4491,10 @@ static void thin_io_hints(struct dm_target *ti, struct queue_limits *limits) struct thin_c *tc = ti->private; struct pool *pool = tc->pool; - if (!pool->pf.discard_enabled) - return; - - limits->discard_granularity = pool->sectors_per_block << SECTOR_SHIFT; - limits->max_discard_sectors = pool->sectors_per_block * BIO_PRISON_MAX_RANGE; + if (pool->pf.discard_enabled) { + limits->discard_granularity = pool->sectors_per_block << SECTOR_SHIFT; + limits->max_discard_sectors = pool->sectors_per_block * BIO_PRISON_MAX_RANGE; + } } static struct target_type thin_target = { diff --git a/drivers/md/dm-verity-fec.c b/drivers/md/dm-verity-fec.c index a9ee2faa75a2963f559c0101dd2354b92c4d3cb8..3ef9f018da60ce7f96dc932b028bc03bc0f5eca2 100644 --- a/drivers/md/dm-verity-fec.c +++ b/drivers/md/dm-verity-fec.c @@ -607,7 +607,7 @@ int verity_fec_parse_opt_args(struct dm_arg_set *as, struct dm_verity *v, (*argc)--; if (!strcasecmp(arg_name, DM_VERITY_OPT_FEC_DEV)) { - r = dm_get_device(ti, arg_value, FMODE_READ, &v->fec->dev); + r = dm_get_device(ti, arg_value, BLK_OPEN_READ, &v->fec->dev); if (r) { ti->error = "FEC device lookup failed"; return r; diff --git a/drivers/md/dm-verity-loadpin.c b/drivers/md/dm-verity-loadpin.c index 4f78cc55c2514e6329d9780939d320e53faa743d..0666699b6858166227131e17a0da99e5ae22a4c2 100644 --- a/drivers/md/dm-verity-loadpin.c +++ b/drivers/md/dm-verity-loadpin.c @@ -58,6 +58,9 @@ bool dm_verity_loadpin_is_bdev_trusted(struct block_device *bdev) int srcu_idx; bool trusted = false; + if (bdev == NULL) + return false; + if (list_empty(&dm_verity_loadpin_trusted_root_digests)) return false; diff --git a/drivers/md/dm-verity-target.c b/drivers/md/dm-verity-target.c index e35c16e06d0658a3632ff8ebbf40774027ab0a94..26adcfea030229b9b2b6a91667b56c0c69646d3a 100644 --- a/drivers/md/dm-verity-target.c +++ b/drivers/md/dm-verity-target.c @@ -1196,7 +1196,7 @@ static int verity_ctr(struct dm_target *ti, unsigned int argc, char **argv) if (r) goto bad; - if ((dm_table_get_mode(ti->table) & ~FMODE_READ)) { + if ((dm_table_get_mode(ti->table) & ~BLK_OPEN_READ)) { ti->error = "Device must be readonly"; r = -EINVAL; goto bad; @@ -1225,13 +1225,13 @@ static int verity_ctr(struct dm_target *ti, unsigned int argc, char **argv) } v->version = num; - r = dm_get_device(ti, argv[1], FMODE_READ, &v->data_dev); + r = dm_get_device(ti, argv[1], BLK_OPEN_READ, &v->data_dev); if (r) { ti->error = "Data device lookup failed"; goto bad; } - r = dm_get_device(ti, argv[2], FMODE_READ, &v->hash_dev); + r = dm_get_device(ti, argv[2], BLK_OPEN_READ, &v->hash_dev); if (r) { ti->error = "Hash device lookup failed"; goto bad; diff --git a/drivers/md/dm-zone.c b/drivers/md/dm-zone.c index 4b82b7798ce4ca499acfabcf9ea36fa0478b024f..eb9832b22b14e2a75fa4d547b776e27fb3d3eb64 100644 --- a/drivers/md/dm-zone.c +++ b/drivers/md/dm-zone.c @@ -7,6 +7,7 @@ #include #include #include +#include #include "dm-core.h" @@ -140,9 +141,9 @@ bool dm_is_zone_write(struct mapped_device *md, struct bio *bio) void dm_cleanup_zoned_dev(struct mapped_device *md) { if (md->disk) { - kfree(md->disk->conv_zones_bitmap); + bitmap_free(md->disk->conv_zones_bitmap); md->disk->conv_zones_bitmap = NULL; - kfree(md->disk->seq_zones_wlock); + bitmap_free(md->disk->seq_zones_wlock); md->disk->seq_zones_wlock = NULL; } @@ -182,9 +183,8 @@ static int dm_zone_revalidate_cb(struct blk_zone *zone, unsigned int idx, switch (zone->type) { case BLK_ZONE_TYPE_CONVENTIONAL: if (!disk->conv_zones_bitmap) { - disk->conv_zones_bitmap = - kcalloc(BITS_TO_LONGS(disk->nr_zones), - sizeof(unsigned long), GFP_NOIO); + disk->conv_zones_bitmap = bitmap_zalloc(disk->nr_zones, + GFP_NOIO); if (!disk->conv_zones_bitmap) return -ENOMEM; } @@ -193,9 +193,8 @@ static int dm_zone_revalidate_cb(struct blk_zone *zone, unsigned int idx, case BLK_ZONE_TYPE_SEQWRITE_REQ: case BLK_ZONE_TYPE_SEQWRITE_PREF: if (!disk->seq_zones_wlock) { - disk->seq_zones_wlock = - kcalloc(BITS_TO_LONGS(disk->nr_zones), - sizeof(unsigned long), GFP_NOIO); + disk->seq_zones_wlock = bitmap_zalloc(disk->nr_zones, + GFP_NOIO); if (!disk->seq_zones_wlock) return -ENOMEM; } diff --git a/drivers/md/dm-zoned-metadata.c b/drivers/md/dm-zoned-metadata.c index 8f0896a6990b115c7a0285f8b4d787466a0e9755..9d3cca8e3dc9e11a01c73b2d22036490bc6d003f 100644 --- a/drivers/md/dm-zoned-metadata.c +++ b/drivers/md/dm-zoned-metadata.c @@ -577,7 +577,7 @@ static struct dmz_mblock *dmz_get_mblock_slow(struct dmz_metadata *zmd, bio->bi_iter.bi_sector = dmz_blk2sect(block); bio->bi_private = mblk; bio->bi_end_io = dmz_mblock_bio_end_io; - bio_add_page(bio, mblk->page, DMZ_BLOCK_SIZE, 0); + __bio_add_page(bio, mblk->page, DMZ_BLOCK_SIZE, 0); submit_bio(bio); return mblk; @@ -728,7 +728,7 @@ static int dmz_write_mblock(struct dmz_metadata *zmd, struct dmz_mblock *mblk, bio->bi_iter.bi_sector = dmz_blk2sect(block); bio->bi_private = mblk; bio->bi_end_io = dmz_mblock_bio_end_io; - bio_add_page(bio, mblk->page, DMZ_BLOCK_SIZE, 0); + __bio_add_page(bio, mblk->page, DMZ_BLOCK_SIZE, 0); submit_bio(bio); return 0; @@ -752,7 +752,7 @@ static int dmz_rdwr_block(struct dmz_dev *dev, enum req_op op, bio = bio_alloc(dev->bdev, 1, op | REQ_SYNC | REQ_META | REQ_PRIO, GFP_NOIO); bio->bi_iter.bi_sector = dmz_blk2sect(block); - bio_add_page(bio, page, DMZ_BLOCK_SIZE, 0); + __bio_add_page(bio, page, DMZ_BLOCK_SIZE, 0); ret = submit_bio_wait(bio); bio_put(bio); diff --git a/drivers/md/dm.c b/drivers/md/dm.c index fffb0cbe2ac8a14fe9bc0c9dc442ce6e4a0a02aa..f0f118ab20fa26371c9bd5395d3763fa34c7ff34 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -207,7 +207,7 @@ static int __init local_init(void) if (r) return r; - deferred_remove_workqueue = alloc_workqueue("kdmremove", WQ_UNBOUND, 1); + deferred_remove_workqueue = alloc_ordered_workqueue("kdmremove", 0); if (!deferred_remove_workqueue) { r = -ENOMEM; goto out_uevent_exit; @@ -310,13 +310,13 @@ int dm_deleting_md(struct mapped_device *md) return test_bit(DMF_DELETING, &md->flags); } -static int dm_blk_open(struct block_device *bdev, fmode_t mode) +static int dm_blk_open(struct gendisk *disk, blk_mode_t mode) { struct mapped_device *md; spin_lock(&_minor_lock); - md = bdev->bd_disk->private_data; + md = disk->private_data; if (!md) goto out; @@ -334,7 +334,7 @@ static int dm_blk_open(struct block_device *bdev, fmode_t mode) return md ? 0 : -ENXIO; } -static void dm_blk_close(struct gendisk *disk, fmode_t mode) +static void dm_blk_close(struct gendisk *disk) { struct mapped_device *md; @@ -448,7 +448,7 @@ static void dm_unprepare_ioctl(struct mapped_device *md, int srcu_idx) dm_put_live_table(md, srcu_idx); } -static int dm_blk_ioctl(struct block_device *bdev, fmode_t mode, +static int dm_blk_ioctl(struct block_device *bdev, blk_mode_t mode, unsigned int cmd, unsigned long arg) { struct mapped_device *md = bdev->bd_disk->private_data; @@ -487,48 +487,50 @@ u64 dm_start_time_ns_from_clone(struct bio *bio) } EXPORT_SYMBOL_GPL(dm_start_time_ns_from_clone); -static bool bio_is_flush_with_data(struct bio *bio) +static inline bool bio_is_flush_with_data(struct bio *bio) { return ((bio->bi_opf & REQ_PREFLUSH) && bio->bi_iter.bi_size); } -static void dm_io_acct(struct dm_io *io, bool end) +static inline unsigned int dm_io_sectors(struct dm_io *io, struct bio *bio) { - struct dm_stats_aux *stats_aux = &io->stats_aux; - unsigned long start_time = io->start_time; - struct mapped_device *md = io->md; - struct bio *bio = io->orig_bio; - unsigned int sectors; - /* * If REQ_PREFLUSH set, don't account payload, it will be * submitted (and accounted) after this flush completes. */ if (bio_is_flush_with_data(bio)) - sectors = 0; - else if (likely(!(dm_io_flagged(io, DM_IO_WAS_SPLIT)))) - sectors = bio_sectors(bio); - else - sectors = io->sectors; + return 0; + if (unlikely(dm_io_flagged(io, DM_IO_WAS_SPLIT))) + return io->sectors; + return bio_sectors(bio); +} - if (!end) - bdev_start_io_acct(bio->bi_bdev, bio_op(bio), start_time); - else - bdev_end_io_acct(bio->bi_bdev, bio_op(bio), sectors, - start_time); +static void dm_io_acct(struct dm_io *io, bool end) +{ + struct bio *bio = io->orig_bio; + + if (dm_io_flagged(io, DM_IO_BLK_STAT)) { + if (!end) + bdev_start_io_acct(bio->bi_bdev, bio_op(bio), + io->start_time); + else + bdev_end_io_acct(bio->bi_bdev, bio_op(bio), + dm_io_sectors(io, bio), + io->start_time); + } if (static_branch_unlikely(&stats_enabled) && - unlikely(dm_stats_used(&md->stats))) { + unlikely(dm_stats_used(&io->md->stats))) { sector_t sector; - if (likely(!dm_io_flagged(io, DM_IO_WAS_SPLIT))) - sector = bio->bi_iter.bi_sector; - else + if (unlikely(dm_io_flagged(io, DM_IO_WAS_SPLIT))) sector = bio_end_sector(bio) - io->sector_offset; + else + sector = bio->bi_iter.bi_sector; - dm_stats_account_io(&md->stats, bio_data_dir(bio), - sector, sectors, - end, start_time, stats_aux); + dm_stats_account_io(&io->md->stats, bio_data_dir(bio), + sector, dm_io_sectors(io, bio), + end, io->start_time, &io->stats_aux); } } @@ -592,8 +594,11 @@ static struct dm_io *alloc_io(struct mapped_device *md, struct bio *bio) spin_lock_init(&io->lock); io->start_time = jiffies; io->flags = 0; + if (blk_queue_io_stat(md->queue)) + dm_io_set_flag(io, DM_IO_BLK_STAT); - if (static_branch_unlikely(&stats_enabled)) + if (static_branch_unlikely(&stats_enabled) && + unlikely(dm_stats_used(&md->stats))) dm_stats_record_start(&md->stats, &io->stats_aux); return io; @@ -734,7 +739,7 @@ static char *_dm_claim_ptr = "I belong to device-mapper"; * Open a table device so we can use it as a map destination. */ static struct table_device *open_table_device(struct mapped_device *md, - dev_t dev, fmode_t mode) + dev_t dev, blk_mode_t mode) { struct table_device *td; struct block_device *bdev; @@ -746,7 +751,7 @@ static struct table_device *open_table_device(struct mapped_device *md, return ERR_PTR(-ENOMEM); refcount_set(&td->count, 1); - bdev = blkdev_get_by_dev(dev, mode | FMODE_EXCL, _dm_claim_ptr); + bdev = blkdev_get_by_dev(dev, mode, _dm_claim_ptr, NULL); if (IS_ERR(bdev)) { r = PTR_ERR(bdev); goto out_free_td; @@ -771,7 +776,7 @@ static struct table_device *open_table_device(struct mapped_device *md, return td; out_blkdev_put: - blkdev_put(bdev, mode | FMODE_EXCL); + blkdev_put(bdev, _dm_claim_ptr); out_free_td: kfree(td); return ERR_PTR(r); @@ -784,14 +789,14 @@ static void close_table_device(struct table_device *td, struct mapped_device *md { if (md->disk->slave_dir) bd_unlink_disk_holder(td->dm_dev.bdev, md->disk); - blkdev_put(td->dm_dev.bdev, td->dm_dev.mode | FMODE_EXCL); + blkdev_put(td->dm_dev.bdev, _dm_claim_ptr); put_dax(td->dm_dev.dax_dev); list_del(&td->list); kfree(td); } static struct table_device *find_table_device(struct list_head *l, dev_t dev, - fmode_t mode) + blk_mode_t mode) { struct table_device *td; @@ -802,7 +807,7 @@ static struct table_device *find_table_device(struct list_head *l, dev_t dev, return NULL; } -int dm_get_table_device(struct mapped_device *md, dev_t dev, fmode_t mode, +int dm_get_table_device(struct mapped_device *md, dev_t dev, blk_mode_t mode, struct dm_dev **result) { struct table_device *td; @@ -2348,6 +2353,7 @@ int dm_setup_md_queue(struct mapped_device *md, struct dm_table *t) break; case DM_TYPE_BIO_BASED: case DM_TYPE_DAX_BIO_BASED: + blk_queue_flag_set(QUEUE_FLAG_IO_STAT, md->queue); break; case DM_TYPE_NONE: WARN_ON_ONCE(true); @@ -3143,6 +3149,8 @@ struct dm_pr { bool fail_early; int ret; enum pr_type type; + struct pr_keys *read_keys; + struct pr_held_reservation *rsv; }; static int dm_call_pr(struct block_device *bdev, iterate_devices_callout_fn fn, @@ -3375,12 +3383,79 @@ static int dm_pr_clear(struct block_device *bdev, u64 key) return r; } +static int __dm_pr_read_keys(struct dm_target *ti, struct dm_dev *dev, + sector_t start, sector_t len, void *data) +{ + struct dm_pr *pr = data; + const struct pr_ops *ops = dev->bdev->bd_disk->fops->pr_ops; + + if (!ops || !ops->pr_read_keys) { + pr->ret = -EOPNOTSUPP; + return -1; + } + + pr->ret = ops->pr_read_keys(dev->bdev, pr->read_keys); + if (!pr->ret) + return -1; + + return 0; +} + +static int dm_pr_read_keys(struct block_device *bdev, struct pr_keys *keys) +{ + struct dm_pr pr = { + .read_keys = keys, + }; + int ret; + + ret = dm_call_pr(bdev, __dm_pr_read_keys, &pr); + if (ret) + return ret; + + return pr.ret; +} + +static int __dm_pr_read_reservation(struct dm_target *ti, struct dm_dev *dev, + sector_t start, sector_t len, void *data) +{ + struct dm_pr *pr = data; + const struct pr_ops *ops = dev->bdev->bd_disk->fops->pr_ops; + + if (!ops || !ops->pr_read_reservation) { + pr->ret = -EOPNOTSUPP; + return -1; + } + + pr->ret = ops->pr_read_reservation(dev->bdev, pr->rsv); + if (!pr->ret) + return -1; + + return 0; +} + +static int dm_pr_read_reservation(struct block_device *bdev, + struct pr_held_reservation *rsv) +{ + struct dm_pr pr = { + .rsv = rsv, + }; + int ret; + + ret = dm_call_pr(bdev, __dm_pr_read_reservation, &pr); + if (ret) + return ret; + + return pr.ret; +} + static const struct pr_ops dm_pr_ops = { .pr_register = dm_pr_register, .pr_reserve = dm_pr_reserve, .pr_release = dm_pr_release, .pr_preempt = dm_pr_preempt, .pr_clear = dm_pr_clear, + .pr_read_keys = dm_pr_read_keys, + .pr_read_reservation = dm_pr_read_reservation, }; static const struct block_device_operations dm_blk_dops = { diff --git a/drivers/md/dm.h b/drivers/md/dm.h index a856e0aee73bc936e8cbc4a3c4a12219e6190367..f682295af91f7877174d4c60aeac13d69c4ee675 100644 --- a/drivers/md/dm.h +++ b/drivers/md/dm.h @@ -203,16 +203,13 @@ int dm_open_count(struct mapped_device *md); int dm_lock_for_deletion(struct mapped_device *md, bool mark_deferred, bool only_deferred); int dm_cancel_deferred_remove(struct mapped_device *md); int dm_request_based(struct mapped_device *md); -int dm_get_table_device(struct mapped_device *md, dev_t dev, fmode_t mode, +int dm_get_table_device(struct mapped_device *md, dev_t dev, blk_mode_t mode, struct dm_dev **result); void dm_put_table_device(struct mapped_device *md, struct dm_dev *d); int dm_kobject_uevent(struct mapped_device *md, enum kobject_action action, unsigned int cookie, bool need_resize_uevent); -void dm_internal_suspend(struct mapped_device *md); -void dm_internal_resume(struct mapped_device *md); - int dm_io_init(void); void dm_io_exit(void); diff --git a/drivers/md/md-autodetect.c b/drivers/md/md-autodetect.c index 91836e6de3260f07903e243571f7d889a9899177..6eaa0eab40f962e2490ed5666f4329f9cba0d029 100644 --- a/drivers/md/md-autodetect.c +++ b/drivers/md/md-autodetect.c @@ -147,7 +147,8 @@ static void __init md_setup_drive(struct md_setup_args *args) if (p) *p++ = 0; - dev = name_to_dev_t(devname); + if (early_lookup_bdev(devname, &dev)) + dev = 0; if (strncmp(devname, "/dev/", 5) == 0) devname += 5; snprintf(comp_name, 63, "/dev/%s", devname); diff --git a/drivers/md/md-bitmap.c b/drivers/md/md-bitmap.c index bc8d7565171d44f3027186fbf5a7b05714e49bda..1ff712889a3b369a1783383621a09625d79dcf83 100644 --- a/drivers/md/md-bitmap.c +++ b/drivers/md/md-bitmap.c @@ -54,14 +54,7 @@ __acquires(bitmap->lock) { unsigned char *mappage; - if (page >= bitmap->pages) { - /* This can happen if bitmap_start_sync goes beyond - * End-of-device while looking for a whole page. - * It is harmless. - */ - return -EINVAL; - } - + WARN_ON_ONCE(page >= bitmap->pages); if (bitmap->bp[page].hijacked) /* it's hijacked, don't try to alloc */ return 0; @@ -1023,7 +1016,6 @@ static int md_bitmap_file_test_bit(struct bitmap *bitmap, sector_t block) return set; } - /* this gets called when the md device is ready to unplug its underlying * (slave) device queues -- before we let any writes go down, we need to * sync the dirty pages of the bitmap file to disk */ @@ -1033,8 +1025,7 @@ void md_bitmap_unplug(struct bitmap *bitmap) int dirty, need_write; int writing = 0; - if (!bitmap || !bitmap->storage.filemap || - test_bit(BITMAP_STALE, &bitmap->flags)) + if (!md_bitmap_enabled(bitmap)) return; /* look at each page to see if there are any set bits that need to be @@ -1063,6 +1054,35 @@ void md_bitmap_unplug(struct bitmap *bitmap) } EXPORT_SYMBOL(md_bitmap_unplug); +struct bitmap_unplug_work { + struct work_struct work; + struct bitmap *bitmap; + struct completion *done; +}; + +static void md_bitmap_unplug_fn(struct work_struct *work) +{ + struct bitmap_unplug_work *unplug_work = + container_of(work, struct bitmap_unplug_work, work); + + md_bitmap_unplug(unplug_work->bitmap); + complete(unplug_work->done); +} + +void md_bitmap_unplug_async(struct bitmap *bitmap) +{ + DECLARE_COMPLETION_ONSTACK(done); + struct bitmap_unplug_work unplug_work; + + INIT_WORK_ONSTACK(&unplug_work.work, md_bitmap_unplug_fn); + unplug_work.bitmap = bitmap; + unplug_work.done = &done; + + queue_work(md_bitmap_wq, &unplug_work.work); + wait_for_completion(&done); +} +EXPORT_SYMBOL(md_bitmap_unplug_async); + static void md_bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset, int needed); /* * bitmap_init_from_disk -- called at bitmap_create time to initialize * the in-memory bitmap from the on-disk bitmap -- also, sets up the @@ -1241,11 +1261,28 @@ static bitmap_counter_t *md_bitmap_get_counter(struct bitmap_counts *bitmap, sector_t offset, sector_t *blocks, int create); +static void mddev_set_timeout(struct mddev *mddev, unsigned long timeout, + bool force) +{ + struct md_thread *thread; + + rcu_read_lock(); + thread = rcu_dereference(mddev->thread); + + if (!thread) + goto out; + + if (force || thread->timeout < MAX_SCHEDULE_TIMEOUT) + thread->timeout = timeout; + +out: + rcu_read_unlock(); +} + /* * bitmap daemon -- periodically wakes up to clean bits and flush pages * out to disk */ - void md_bitmap_daemon_work(struct mddev *mddev) { struct bitmap *bitmap; @@ -1269,7 +1306,7 @@ void md_bitmap_daemon_work(struct mddev *mddev) bitmap->daemon_lastrun = jiffies; if (bitmap->allclean) { - mddev->thread->timeout = MAX_SCHEDULE_TIMEOUT; + mddev_set_timeout(mddev, MAX_SCHEDULE_TIMEOUT, true); goto done; } bitmap->allclean = 1; @@ -1366,8 +1403,7 @@ void md_bitmap_daemon_work(struct mddev *mddev) done: if (bitmap->allclean == 0) - mddev->thread->timeout = - mddev->bitmap_info.daemon_sleep; + mddev_set_timeout(mddev, mddev->bitmap_info.daemon_sleep, true); mutex_unlock(&mddev->bitmap_info.mutex); } @@ -1387,6 +1423,14 @@ __acquires(bitmap->lock) sector_t csize; int err; + if (page >= bitmap->pages) { + /* + * This can happen if bitmap_start_sync goes beyond + * End-of-device while looking for a whole page or + * user set a huge number to sysfs bitmap_set_bits. + */ + return NULL; + } err = md_bitmap_checkpage(bitmap, page, create, 0); if (bitmap->bp[page].hijacked || @@ -1820,8 +1864,7 @@ void md_bitmap_destroy(struct mddev *mddev) mddev->bitmap = NULL; /* disconnect from the md device */ spin_unlock(&mddev->lock); mutex_unlock(&mddev->bitmap_info.mutex); - if (mddev->thread) - mddev->thread->timeout = MAX_SCHEDULE_TIMEOUT; + mddev_set_timeout(mddev, MAX_SCHEDULE_TIMEOUT, true); md_bitmap_free(bitmap); } @@ -1964,7 +2007,7 @@ int md_bitmap_load(struct mddev *mddev) /* Kick recovery in case any bits were set */ set_bit(MD_RECOVERY_NEEDED, &bitmap->mddev->recovery); - mddev->thread->timeout = mddev->bitmap_info.daemon_sleep; + mddev_set_timeout(mddev, mddev->bitmap_info.daemon_sleep, true); md_wakeup_thread(mddev->thread); md_bitmap_update_sb(bitmap); @@ -2469,17 +2512,11 @@ timeout_store(struct mddev *mddev, const char *buf, size_t len) timeout = MAX_SCHEDULE_TIMEOUT-1; if (timeout < 1) timeout = 1; + mddev->bitmap_info.daemon_sleep = timeout; - if (mddev->thread) { - /* if thread->timeout is MAX_SCHEDULE_TIMEOUT, then - * the bitmap is all clean and we don't need to - * adjust the timeout right now - */ - if (mddev->thread->timeout < MAX_SCHEDULE_TIMEOUT) { - mddev->thread->timeout = timeout; - md_wakeup_thread(mddev->thread); - } - } + mddev_set_timeout(mddev, timeout, false); + md_wakeup_thread(mddev->thread); + return len; } diff --git a/drivers/md/md-bitmap.h b/drivers/md/md-bitmap.h index cfd7395de8fd36c779092617c23ad6d36fad7bea..8a3788c9bfef854fde3abc8193e74565619e53b3 100644 --- a/drivers/md/md-bitmap.h +++ b/drivers/md/md-bitmap.h @@ -264,6 +264,7 @@ void md_bitmap_sync_with_cluster(struct mddev *mddev, sector_t new_lo, sector_t new_hi); void md_bitmap_unplug(struct bitmap *bitmap); +void md_bitmap_unplug_async(struct bitmap *bitmap); void md_bitmap_daemon_work(struct mddev *mddev); int md_bitmap_resize(struct bitmap *bitmap, sector_t blocks, @@ -273,6 +274,13 @@ int md_bitmap_copy_from_slot(struct mddev *mddev, int slot, sector_t *lo, sector_t *hi, bool clear_bits); void md_bitmap_free(struct bitmap *bitmap); void md_bitmap_wait_behind_writes(struct mddev *mddev); + +static inline bool md_bitmap_enabled(struct bitmap *bitmap) +{ + return bitmap && bitmap->storage.filemap && + !test_bit(BITMAP_STALE, &bitmap->flags); +} + #endif #endif diff --git a/drivers/md/md-cluster.c b/drivers/md/md-cluster.c index 10e0c5381d01b719a621d3ee42e70dd739309586..3d9fd74233dfd2771f392a898bee03f20814735c 100644 --- a/drivers/md/md-cluster.c +++ b/drivers/md/md-cluster.c @@ -75,14 +75,14 @@ struct md_cluster_info { sector_t suspend_hi; int suspend_from; /* the slot which broadcast suspend_lo/hi */ - struct md_thread *recovery_thread; + struct md_thread __rcu *recovery_thread; unsigned long recovery_map; /* communication loc resources */ struct dlm_lock_resource *ack_lockres; struct dlm_lock_resource *message_lockres; struct dlm_lock_resource *token_lockres; struct dlm_lock_resource *no_new_dev_lockres; - struct md_thread *recv_thread; + struct md_thread __rcu *recv_thread; struct completion newdisk_completion; wait_queue_head_t wait; unsigned long state; @@ -362,8 +362,8 @@ static void __recover_slot(struct mddev *mddev, int slot) set_bit(slot, &cinfo->recovery_map); if (!cinfo->recovery_thread) { - cinfo->recovery_thread = md_register_thread(recover_bitmaps, - mddev, "recover"); + rcu_assign_pointer(cinfo->recovery_thread, + md_register_thread(recover_bitmaps, mddev, "recover")); if (!cinfo->recovery_thread) { pr_warn("md-cluster: Could not create recovery thread\n"); return; @@ -526,11 +526,15 @@ static void process_add_new_disk(struct mddev *mddev, struct cluster_msg *cmsg) static void process_metadata_update(struct mddev *mddev, struct cluster_msg *msg) { int got_lock = 0; + struct md_thread *thread; struct md_cluster_info *cinfo = mddev->cluster_info; mddev->good_device_nr = le32_to_cpu(msg->raid_slot); dlm_lock_sync(cinfo->no_new_dev_lockres, DLM_LOCK_CR); - wait_event(mddev->thread->wqueue, + + /* daemaon thread must exist */ + thread = rcu_dereference_protected(mddev->thread, true); + wait_event(thread->wqueue, (got_lock = mddev_trylock(mddev)) || test_bit(MD_CLUSTER_HOLDING_MUTEX_FOR_RECVD, &cinfo->state)); md_reload_sb(mddev, mddev->good_device_nr); @@ -889,7 +893,8 @@ static int join(struct mddev *mddev, int nodes) } /* Initiate the communication resources */ ret = -ENOMEM; - cinfo->recv_thread = md_register_thread(recv_daemon, mddev, "cluster_recv"); + rcu_assign_pointer(cinfo->recv_thread, + md_register_thread(recv_daemon, mddev, "cluster_recv")); if (!cinfo->recv_thread) { pr_err("md-cluster: cannot allocate memory for recv_thread!\n"); goto err; diff --git a/drivers/md/md-multipath.c b/drivers/md/md-multipath.c index 66edf5e72bd60b8f20dcbac06f00b6e138a5c4b7..92c45be203d7e42d6063388d827b9c85c8ee0a80 100644 --- a/drivers/md/md-multipath.c +++ b/drivers/md/md-multipath.c @@ -400,8 +400,8 @@ static int multipath_run (struct mddev *mddev) if (ret) goto out_free_conf; - mddev->thread = md_register_thread(multipathd, mddev, - "multipath"); + rcu_assign_pointer(mddev->thread, + md_register_thread(multipathd, mddev, "multipath")); if (!mddev->thread) goto out_free_conf; diff --git a/drivers/md/md.c b/drivers/md/md.c index 8e344b4b34446f784b8f111d2ec3c34024285b00..2e38ef421d69f927ecc837267cfb174ca6db1f9f 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -70,11 +70,7 @@ #include "md-bitmap.h" #include "md-cluster.h" -/* pers_list is a list of registered personalities protected - * by pers_lock. - * pers_lock does extra service to protect accesses to - * mddev->thread when the mutex cannot be held. - */ +/* pers_list is a list of registered personalities protected by pers_lock. */ static LIST_HEAD(pers_list); static DEFINE_SPINLOCK(pers_lock); @@ -87,23 +83,13 @@ static struct module *md_cluster_mod; static DECLARE_WAIT_QUEUE_HEAD(resync_wait); static struct workqueue_struct *md_wq; static struct workqueue_struct *md_misc_wq; -static struct workqueue_struct *md_rdev_misc_wq; +struct workqueue_struct *md_bitmap_wq; static int remove_and_add_spares(struct mddev *mddev, struct md_rdev *this); static void mddev_detach(struct mddev *mddev); - -enum md_ro_state { - MD_RDWR, - MD_RDONLY, - MD_AUTO_READ, - MD_MAX_STATE -}; - -static bool md_is_rdwr(struct mddev *mddev) -{ - return (mddev->ro == MD_RDWR); -} +static void export_rdev(struct md_rdev *rdev, struct mddev *mddev); +static void md_wakeup_thread_directly(struct md_thread __rcu *thread); /* * Default number of read corrections we'll attempt on an rdev @@ -360,10 +346,6 @@ EXPORT_SYMBOL_GPL(md_new_event); static LIST_HEAD(all_mddevs); static DEFINE_SPINLOCK(all_mddevs_lock); -static bool is_md_suspended(struct mddev *mddev) -{ - return percpu_ref_is_dying(&mddev->active_io); -} /* Rather than calling directly into the personality make_request function, * IO requests come here first so that we can check if the device is * being suspended pending a reconfiguration. @@ -457,13 +439,19 @@ static void md_submit_bio(struct bio *bio) */ void mddev_suspend(struct mddev *mddev) { - WARN_ON_ONCE(mddev->thread && current == mddev->thread->tsk); - lockdep_assert_held(&mddev->reconfig_mutex); + struct md_thread *thread = rcu_dereference_protected(mddev->thread, + lockdep_is_held(&mddev->reconfig_mutex)); + + WARN_ON_ONCE(thread && current == thread->tsk); if (mddev->suspended++) return; wake_up(&mddev->sb_wait); set_bit(MD_ALLOW_SB_UPDATE, &mddev->flags); percpu_ref_kill(&mddev->active_io); + + if (mddev->pers->prepare_suspend) + mddev->pers->prepare_suspend(mddev); + wait_event(mddev->sb_wait, percpu_ref_is_zero(&mddev->active_io)); mddev->pers->quiesce(mddev, 1); clear_bit_unlock(MD_ALLOW_SB_UPDATE, &mddev->flags); @@ -658,6 +646,7 @@ void mddev_init(struct mddev *mddev) mutex_init(&mddev->bitmap_info.mutex); INIT_LIST_HEAD(&mddev->disks); INIT_LIST_HEAD(&mddev->all_mddevs); + INIT_LIST_HEAD(&mddev->deleting); timer_setup(&mddev->safemode_timer, md_safemode_timeout, 0); atomic_set(&mddev->active, 1); atomic_set(&mddev->openers, 0); @@ -761,6 +750,13 @@ static const struct attribute_group md_redundancy_group; void mddev_unlock(struct mddev *mddev) { + struct md_rdev *rdev; + struct md_rdev *tmp; + LIST_HEAD(delete); + + if (!list_empty(&mddev->deleting)) + list_splice_init(&mddev->deleting, &delete); + if (mddev->to_remove) { /* These cannot be removed under reconfig_mutex as * an access to the files will try to take reconfig_mutex @@ -800,13 +796,14 @@ void mddev_unlock(struct mddev *mddev) } else mutex_unlock(&mddev->reconfig_mutex); - /* As we've dropped the mutex we need a spinlock to - * make sure the thread doesn't disappear - */ - spin_lock(&pers_lock); + list_for_each_entry_safe(rdev, tmp, &delete, same_set) { + list_del_init(&rdev->same_set); + kobject_del(&rdev->kobj); + export_rdev(rdev, mddev); + } + md_wakeup_thread(mddev->thread); wake_up(&mddev->sb_wait); - spin_unlock(&pers_lock); } EXPORT_SYMBOL_GPL(mddev_unlock); @@ -938,7 +935,7 @@ void md_super_write(struct mddev *mddev, struct md_rdev *rdev, atomic_inc(&rdev->nr_pending); bio->bi_iter.bi_sector = sector; - bio_add_page(bio, page, size, 0); + __bio_add_page(bio, page, size, 0); bio->bi_private = rdev; bio->bi_end_io = super_written; @@ -979,7 +976,7 @@ int sync_page_io(struct md_rdev *rdev, sector_t sector, int size, bio.bi_iter.bi_sector = sector + rdev->new_data_offset; else bio.bi_iter.bi_sector = sector + rdev->data_offset; - bio_add_page(&bio, page, size, 0); + __bio_add_page(&bio, page, size, 0); submit_bio_wait(&bio); @@ -2440,16 +2437,12 @@ static int bind_rdev_to_array(struct md_rdev *rdev, struct mddev *mddev) return err; } -static void rdev_delayed_delete(struct work_struct *ws) -{ - struct md_rdev *rdev = container_of(ws, struct md_rdev, del_work); - kobject_del(&rdev->kobj); - kobject_put(&rdev->kobj); -} - void md_autodetect_dev(dev_t dev); -static void export_rdev(struct md_rdev *rdev) +/* just for claiming the bdev */ +static struct md_rdev claim_rdev; + +static void export_rdev(struct md_rdev *rdev, struct mddev *mddev) { pr_debug("md: export_rdev(%pg)\n", rdev->bdev); md_rdev_clear(rdev); @@ -2457,13 +2450,15 @@ static void export_rdev(struct md_rdev *rdev) if (test_bit(AutoDetected, &rdev->flags)) md_autodetect_dev(rdev->bdev->bd_dev); #endif - blkdev_put(rdev->bdev, FMODE_READ | FMODE_WRITE | FMODE_EXCL); + blkdev_put(rdev->bdev, mddev->external ? &claim_rdev : rdev); rdev->bdev = NULL; kobject_put(&rdev->kobj); } static void md_kick_rdev_from_array(struct md_rdev *rdev) { + struct mddev *mddev = rdev->mddev; + bd_unlink_disk_holder(rdev->bdev, rdev->mddev->gendisk); list_del_rcu(&rdev->same_set); pr_debug("md: unbind<%pg>\n", rdev->bdev); @@ -2477,15 +2472,15 @@ static void md_kick_rdev_from_array(struct md_rdev *rdev) rdev->sysfs_unack_badblocks = NULL; rdev->sysfs_badblocks = NULL; rdev->badblocks.count = 0; - /* We need to delay this, otherwise we can deadlock when - * writing to 'remove' to "dev/state". We also need - * to delay it due to rcu usage. - */ + synchronize_rcu(); - INIT_WORK(&rdev->del_work, rdev_delayed_delete); - kobject_get(&rdev->kobj); - queue_work(md_rdev_misc_wq, &rdev->del_work); - export_rdev(rdev); + + /* + * kobject_del() will wait for all in progress writers to be done, where + * reconfig_mutex is held, hence it can't be called under + * reconfig_mutex and it's delayed to mddev_unlock(). + */ + list_add(&rdev->same_set, &mddev->deleting); } static void export_array(struct mddev *mddev) @@ -3553,6 +3548,7 @@ rdev_attr_store(struct kobject *kobj, struct attribute *attr, { struct rdev_sysfs_entry *entry = container_of(attr, struct rdev_sysfs_entry, attr); struct md_rdev *rdev = container_of(kobj, struct md_rdev, kobj); + struct kernfs_node *kn = NULL; ssize_t rv; struct mddev *mddev = rdev->mddev; @@ -3560,6 +3556,10 @@ rdev_attr_store(struct kobject *kobj, struct attribute *attr, return -EIO; if (!capable(CAP_SYS_ADMIN)) return -EACCES; + + if (entry->store == state_store && cmd_match(page, "remove")) + kn = sysfs_break_active_protection(kobj, attr); + rv = mddev ? mddev_lock(mddev) : -ENODEV; if (!rv) { if (rdev->mddev == NULL) @@ -3568,6 +3568,10 @@ rdev_attr_store(struct kobject *kobj, struct attribute *attr, rv = entry->store(rdev, page, length); mddev_unlock(mddev); } + + if (kn) + sysfs_unbreak_active_protection(kn); + return rv; } @@ -3612,6 +3616,7 @@ int md_rdev_init(struct md_rdev *rdev) return badblocks_init(&rdev->badblocks, 0); } EXPORT_SYMBOL_GPL(md_rdev_init); + /* * Import a device. If 'super_format' >= 0, then sanity check the superblock * @@ -3624,7 +3629,6 @@ EXPORT_SYMBOL_GPL(md_rdev_init); */ static struct md_rdev *md_import_device(dev_t newdev, int super_format, int super_minor) { - static struct md_rdev claim_rdev; /* just for claiming the bdev */ struct md_rdev *rdev; sector_t size; int err; @@ -3640,9 +3644,8 @@ static struct md_rdev *md_import_device(dev_t newdev, int super_format, int supe if (err) goto out_clear_rdev; - rdev->bdev = blkdev_get_by_dev(newdev, - FMODE_READ | FMODE_WRITE | FMODE_EXCL, - super_format == -2 ? &claim_rdev : rdev); + rdev->bdev = blkdev_get_by_dev(newdev, BLK_OPEN_READ | BLK_OPEN_WRITE, + super_format == -2 ? &claim_rdev : rdev, NULL); if (IS_ERR(rdev->bdev)) { pr_warn("md: could not open device unknown-block(%u,%u).\n", MAJOR(newdev), MINOR(newdev)); @@ -3679,7 +3682,7 @@ static struct md_rdev *md_import_device(dev_t newdev, int super_format, int supe return rdev; out_blkdev_put: - blkdev_put(rdev->bdev, FMODE_READ | FMODE_WRITE | FMODE_EXCL); + blkdev_put(rdev->bdev, super_format == -2 ? &claim_rdev : rdev); out_clear_rdev: md_rdev_clear(rdev); out_free_rdev: @@ -3794,8 +3797,9 @@ int strict_strtoul_scaled(const char *cp, unsigned long *res, int scale) static ssize_t safe_delay_show(struct mddev *mddev, char *page) { - int msec = (mddev->safemode_delay*1000)/HZ; - return sprintf(page, "%d.%03d\n", msec/1000, msec%1000); + unsigned int msec = ((unsigned long)mddev->safemode_delay*1000)/HZ; + + return sprintf(page, "%u.%03u\n", msec/1000, msec%1000); } static ssize_t safe_delay_store(struct mddev *mddev, const char *cbuf, size_t len) @@ -3807,7 +3811,7 @@ safe_delay_store(struct mddev *mddev, const char *cbuf, size_t len) return -EINVAL; } - if (strict_strtoul_scaled(cbuf, &msec, 3) < 0) + if (strict_strtoul_scaled(cbuf, &msec, 3) < 0 || msec > UINT_MAX / HZ) return -EINVAL; if (msec == 0) mddev->safemode_delay = 0; @@ -4477,6 +4481,8 @@ max_corrected_read_errors_store(struct mddev *mddev, const char *buf, size_t len rv = kstrtouint(buf, 10, &n); if (rv < 0) return rv; + if (n > INT_MAX) + return -EINVAL; atomic_set(&mddev->max_corr_read_errors, n); return len; } @@ -4491,20 +4497,6 @@ null_show(struct mddev *mddev, char *page) return -EINVAL; } -/* need to ensure rdev_delayed_delete() has completed */ -static void flush_rdev_wq(struct mddev *mddev) -{ - struct md_rdev *rdev; - - rcu_read_lock(); - rdev_for_each_rcu(rdev, mddev) - if (work_pending(&rdev->del_work)) { - flush_workqueue(md_rdev_misc_wq); - break; - } - rcu_read_unlock(); -} - static ssize_t new_dev_store(struct mddev *mddev, const char *buf, size_t len) { @@ -4532,7 +4524,6 @@ new_dev_store(struct mddev *mddev, const char *buf, size_t len) minor != MINOR(dev)) return -EOVERFLOW; - flush_rdev_wq(mddev); err = mddev_lock(mddev); if (err) return err; @@ -4560,7 +4551,7 @@ new_dev_store(struct mddev *mddev, const char *buf, size_t len) err = bind_rdev_to_array(rdev, mddev); out: if (err) - export_rdev(rdev); + export_rdev(rdev, mddev); mddev_unlock(mddev); if (!err) md_new_event(); @@ -4804,11 +4795,21 @@ action_store(struct mddev *mddev, const char *page, size_t len) return -EINVAL; err = mddev_lock(mddev); if (!err) { - if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery)) + if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery)) { err = -EBUSY; - else { + } else if (mddev->reshape_position == MaxSector || + mddev->pers->check_reshape == NULL || + mddev->pers->check_reshape(mddev)) { clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery); err = mddev->pers->start_reshape(mddev); + } else { + /* + * If reshape is still in progress, and + * md_check_recovery() can continue to reshape, + * don't restart reshape because data can be + * corrupted for raid456. + */ + clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery); } mddev_unlock(mddev); } @@ -5592,7 +5593,6 @@ struct mddev *md_alloc(dev_t dev, char *name) * removed (mddev_delayed_delete). */ flush_workqueue(md_misc_wq); - flush_workqueue(md_rdev_misc_wq); mutex_lock(&disks_mutex); mddev = mddev_alloc(dev); @@ -6130,7 +6130,7 @@ static void md_clean(struct mddev *mddev) mddev->resync_min = 0; mddev->resync_max = MaxSector; mddev->reshape_position = MaxSector; - mddev->external = 0; + /* we still need mddev->external in export_rdev, do not clear it yet */ mddev->persistent = 0; mddev->level = LEVEL_NONE; mddev->clevel[0] = 0; @@ -6269,10 +6269,12 @@ static int md_set_readonly(struct mddev *mddev, struct block_device *bdev) } if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery)) set_bit(MD_RECOVERY_INTR, &mddev->recovery); - if (mddev->sync_thread) - /* Thread might be blocked waiting for metadata update - * which will now never happen */ - wake_up_process(mddev->sync_thread->tsk); + + /* + * Thread might be blocked waiting for metadata update which will now + * never happen + */ + md_wakeup_thread_directly(mddev->sync_thread); if (mddev->external && test_bit(MD_SB_CHANGE_PENDING, &mddev->sb_flags)) return -EBUSY; @@ -6333,10 +6335,12 @@ static int do_md_stop(struct mddev *mddev, int mode, } if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery)) set_bit(MD_RECOVERY_INTR, &mddev->recovery); - if (mddev->sync_thread) - /* Thread might be blocked waiting for metadata update - * which will now never happen */ - wake_up_process(mddev->sync_thread->tsk); + + /* + * Thread might be blocked waiting for metadata update which will now + * never happen + */ + md_wakeup_thread_directly(mddev->sync_thread); mddev_unlock(mddev); wait_event(resync_wait, (mddev->sync_thread == NULL && @@ -6498,7 +6502,7 @@ static void autorun_devices(int part) rdev_for_each_list(rdev, tmp, &candidates) { list_del_init(&rdev->same_set); if (bind_rdev_to_array(rdev, mddev)) - export_rdev(rdev); + export_rdev(rdev, mddev); } autorun_array(mddev); mddev_unlock(mddev); @@ -6508,7 +6512,7 @@ static void autorun_devices(int part) */ rdev_for_each_list(rdev, tmp, &candidates) { list_del_init(&rdev->same_set); - export_rdev(rdev); + export_rdev(rdev, mddev); } mddev_put(mddev); } @@ -6696,13 +6700,13 @@ int md_add_new_disk(struct mddev *mddev, struct mdu_disk_info_s *info) pr_warn("md: %pg has different UUID to %pg\n", rdev->bdev, rdev0->bdev); - export_rdev(rdev); + export_rdev(rdev, mddev); return -EINVAL; } } err = bind_rdev_to_array(rdev, mddev); if (err) - export_rdev(rdev); + export_rdev(rdev, mddev); return err; } @@ -6733,7 +6737,6 @@ int md_add_new_disk(struct mddev *mddev, struct mdu_disk_info_s *info) if (info->state & (1<raid_disk < mddev->raid_disks) { rdev->raid_disk = info->raid_disk; - set_bit(In_sync, &rdev->flags); clear_bit(Bitmap_sync, &rdev->flags); } else rdev->raid_disk = -1; @@ -6746,7 +6749,7 @@ int md_add_new_disk(struct mddev *mddev, struct mdu_disk_info_s *info) /* This was a hot-add request, but events doesn't * match, so reject it. */ - export_rdev(rdev); + export_rdev(rdev, mddev); return -EINVAL; } @@ -6772,7 +6775,7 @@ int md_add_new_disk(struct mddev *mddev, struct mdu_disk_info_s *info) } } if (has_journal || mddev->bitmap) { - export_rdev(rdev); + export_rdev(rdev, mddev); return -EBUSY; } set_bit(Journal, &rdev->flags); @@ -6787,7 +6790,7 @@ int md_add_new_disk(struct mddev *mddev, struct mdu_disk_info_s *info) /* --add initiated by this node */ err = md_cluster_ops->add_new_disk(mddev, rdev); if (err) { - export_rdev(rdev); + export_rdev(rdev, mddev); return err; } } @@ -6797,7 +6800,7 @@ int md_add_new_disk(struct mddev *mddev, struct mdu_disk_info_s *info) err = bind_rdev_to_array(rdev, mddev); if (err) - export_rdev(rdev); + export_rdev(rdev, mddev); if (mddev_is_clustered(mddev)) { if (info->state & (1 << MD_DISK_CANDIDATE)) { @@ -6860,7 +6863,7 @@ int md_add_new_disk(struct mddev *mddev, struct mdu_disk_info_s *info) err = bind_rdev_to_array(rdev, mddev); if (err) { - export_rdev(rdev); + export_rdev(rdev, mddev); return err; } } @@ -6985,7 +6988,7 @@ static int hot_add_disk(struct mddev *mddev, dev_t dev) return 0; abort_export: - export_rdev(rdev); + export_rdev(rdev, mddev); return err; } @@ -7486,7 +7489,7 @@ static int __md_set_array_info(struct mddev *mddev, void __user *argp) return err; } -static int md_ioctl(struct block_device *bdev, fmode_t mode, +static int md_ioctl(struct block_device *bdev, blk_mode_t mode, unsigned int cmd, unsigned long arg) { int err = 0; @@ -7555,9 +7558,6 @@ static int md_ioctl(struct block_device *bdev, fmode_t mode, } - if (cmd == ADD_NEW_DISK || cmd == HOT_ADD_DISK) - flush_rdev_wq(mddev); - if (cmd == HOT_REMOVE_DISK) /* need to ensure recovery thread has run */ wait_event_interruptible_timeout(mddev->sb_wait, @@ -7718,7 +7718,7 @@ static int md_ioctl(struct block_device *bdev, fmode_t mode, return err; } #ifdef CONFIG_COMPAT -static int md_compat_ioctl(struct block_device *bdev, fmode_t mode, +static int md_compat_ioctl(struct block_device *bdev, blk_mode_t mode, unsigned int cmd, unsigned long arg) { switch (cmd) { @@ -7767,13 +7767,13 @@ static int md_set_read_only(struct block_device *bdev, bool ro) return err; } -static int md_open(struct block_device *bdev, fmode_t mode) +static int md_open(struct gendisk *disk, blk_mode_t mode) { struct mddev *mddev; int err; spin_lock(&all_mddevs_lock); - mddev = mddev_get(bdev->bd_disk->private_data); + mddev = mddev_get(disk->private_data); spin_unlock(&all_mddevs_lock); if (!mddev) return -ENODEV; @@ -7789,7 +7789,7 @@ static int md_open(struct block_device *bdev, fmode_t mode) atomic_inc(&mddev->openers); mutex_unlock(&mddev->open_mutex); - bdev_check_media_change(bdev); + disk_check_media_change(disk); return 0; out_unlock: @@ -7799,7 +7799,7 @@ static int md_open(struct block_device *bdev, fmode_t mode) return err; } -static void md_release(struct gendisk *disk, fmode_t mode) +static void md_release(struct gendisk *disk) { struct mddev *mddev = disk->private_data; @@ -7886,13 +7886,29 @@ static int md_thread(void *arg) return 0; } -void md_wakeup_thread(struct md_thread *thread) +static void md_wakeup_thread_directly(struct md_thread __rcu *thread) { - if (thread) { - pr_debug("md: waking up MD thread %s.\n", thread->tsk->comm); - set_bit(THREAD_WAKEUP, &thread->flags); - wake_up(&thread->wqueue); + struct md_thread *t; + + rcu_read_lock(); + t = rcu_dereference(thread); + if (t) + wake_up_process(t->tsk); + rcu_read_unlock(); +} + +void md_wakeup_thread(struct md_thread __rcu *thread) +{ + struct md_thread *t; + + rcu_read_lock(); + t = rcu_dereference(thread); + if (t) { + pr_debug("md: waking up MD thread %s.\n", t->tsk->comm); + set_bit(THREAD_WAKEUP, &t->flags); + wake_up(&t->wqueue); } + rcu_read_unlock(); } EXPORT_SYMBOL(md_wakeup_thread); @@ -7922,22 +7938,15 @@ struct md_thread *md_register_thread(void (*run) (struct md_thread *), } EXPORT_SYMBOL(md_register_thread); -void md_unregister_thread(struct md_thread **threadp) +void md_unregister_thread(struct md_thread __rcu **threadp) { - struct md_thread *thread; + struct md_thread *thread = rcu_dereference_protected(*threadp, true); - /* - * Locking ensures that mddev_unlock does not wake_up a - * non-existent thread - */ - spin_lock(&pers_lock); - thread = *threadp; - if (!thread) { - spin_unlock(&pers_lock); + if (!thread) return; - } - *threadp = NULL; - spin_unlock(&pers_lock); + + rcu_assign_pointer(*threadp, NULL); + synchronize_rcu(); pr_debug("interrupting MD-thread pid %d\n", task_pid_nr(thread->tsk)); kthread_stop(thread->tsk); @@ -9100,6 +9109,7 @@ void md_do_sync(struct md_thread *thread) spin_unlock(&mddev->lock); wake_up(&resync_wait); + wake_up(&mddev->sb_wait); md_wakeup_thread(mddev->thread); return; } @@ -9202,9 +9212,8 @@ static void md_start_sync(struct work_struct *ws) { struct mddev *mddev = container_of(ws, struct mddev, del_work); - mddev->sync_thread = md_register_thread(md_do_sync, - mddev, - "resync"); + rcu_assign_pointer(mddev->sync_thread, + md_register_thread(md_do_sync, mddev, "resync")); if (!mddev->sync_thread) { pr_warn("%s: could not start resync thread...\n", mdname(mddev)); @@ -9619,9 +9628,10 @@ static int __init md_init(void) if (!md_misc_wq) goto err_misc_wq; - md_rdev_misc_wq = alloc_workqueue("md_rdev_misc", 0, 0); - if (!md_rdev_misc_wq) - goto err_rdev_misc_wq; + md_bitmap_wq = alloc_workqueue("md_bitmap", WQ_MEM_RECLAIM | WQ_UNBOUND, + 0); + if (!md_bitmap_wq) + goto err_bitmap_wq; ret = __register_blkdev(MD_MAJOR, "md", md_probe); if (ret < 0) @@ -9641,8 +9651,8 @@ static int __init md_init(void) err_mdp: unregister_blkdev(MD_MAJOR, "md"); err_md: - destroy_workqueue(md_rdev_misc_wq); -err_rdev_misc_wq: + destroy_workqueue(md_bitmap_wq); +err_bitmap_wq: destroy_workqueue(md_misc_wq); err_misc_wq: destroy_workqueue(md_wq); @@ -9938,8 +9948,8 @@ static __exit void md_exit(void) } spin_unlock(&all_mddevs_lock); - destroy_workqueue(md_rdev_misc_wq); destroy_workqueue(md_misc_wq); + destroy_workqueue(md_bitmap_wq); destroy_workqueue(md_wq); } diff --git a/drivers/md/md.h b/drivers/md/md.h index fd8f260ed5f817a00f3c701d88febb6e505d7ffc..1aef86bf3fc3123500a677fa79ec44a31fbeb52a 100644 --- a/drivers/md/md.h +++ b/drivers/md/md.h @@ -122,8 +122,6 @@ struct md_rdev { struct serial_in_rdev *serial; /* used for raid1 io serialization */ - struct work_struct del_work; /* used for delayed sysfs removal */ - struct kernfs_node *sysfs_state; /* handle for 'state' * sysfs entry */ /* handle for 'unacknowledged_bad_blocks' sysfs dentry */ @@ -367,8 +365,8 @@ struct mddev { int new_chunk_sectors; int reshape_backwards; - struct md_thread *thread; /* management thread */ - struct md_thread *sync_thread; /* doing resync or reconstruct */ + struct md_thread __rcu *thread; /* management thread */ + struct md_thread __rcu *sync_thread; /* doing resync or reconstruct */ /* 'last_sync_action' is initialized to "none". It is set when a * sync operation (i.e "data-check", "requested-resync", "resync", @@ -531,6 +529,12 @@ struct mddev { unsigned int good_device_nr; /* good device num within cluster raid */ unsigned int noio_flag; /* for memalloc scope API */ + /* + * Temporarily store rdev that will be finally removed when + * reconfig_mutex is unlocked, protected by reconfig_mutex. + */ + struct list_head deleting; + bool has_superblocks:1; bool fail_last_dev:1; bool serialize_policy:1; @@ -555,6 +559,23 @@ enum recovery_flags { MD_RESYNCING_REMOTE, /* remote node is running resync thread */ }; +enum md_ro_state { + MD_RDWR, + MD_RDONLY, + MD_AUTO_READ, + MD_MAX_STATE +}; + +static inline bool md_is_rdwr(struct mddev *mddev) +{ + return (mddev->ro == MD_RDWR); +} + +static inline bool is_md_suspended(struct mddev *mddev) +{ + return percpu_ref_is_dying(&mddev->active_io); +} + static inline int __must_check mddev_lock(struct mddev *mddev) { return mutex_lock_interruptible(&mddev->reconfig_mutex); @@ -614,6 +635,7 @@ struct md_personality int (*start_reshape) (struct mddev *mddev); void (*finish_reshape) (struct mddev *mddev); void (*update_reshape_pos) (struct mddev *mddev); + void (*prepare_suspend) (struct mddev *mddev); /* quiesce suspends or resumes internal processing. * 1 - stop new actions and wait for action io to complete * 0 - return to normal behaviour @@ -734,8 +756,8 @@ extern struct md_thread *md_register_thread( void (*run)(struct md_thread *thread), struct mddev *mddev, const char *name); -extern void md_unregister_thread(struct md_thread **threadp); -extern void md_wakeup_thread(struct md_thread *thread); +extern void md_unregister_thread(struct md_thread __rcu **threadp); +extern void md_wakeup_thread(struct md_thread __rcu *thread); extern void md_check_recovery(struct mddev *mddev); extern void md_reap_sync_thread(struct mddev *mddev); extern int mddev_init_writes_pending(struct mddev *mddev); @@ -828,6 +850,7 @@ struct mdu_array_info_s; struct mdu_disk_info_s; extern int mdp_major; +extern struct workqueue_struct *md_bitmap_wq; void md_autostart_arrays(int part); int md_set_array_info(struct mddev *mddev, struct mdu_array_info_s *info); int md_add_new_disk(struct mddev *mddev, struct mdu_disk_info_s *info); diff --git a/drivers/md/persistent-data/dm-block-manager.c b/drivers/md/persistent-data/dm-block-manager.c index 7bdfc23f758aeb900facd2789f7cbebc6a126a1c..0e010e1204aa3119233d6c763cc2c408166e4d44 100644 --- a/drivers/md/persistent-data/dm-block-manager.c +++ b/drivers/md/persistent-data/dm-block-manager.c @@ -421,6 +421,12 @@ void dm_block_manager_destroy(struct dm_block_manager *bm) } EXPORT_SYMBOL_GPL(dm_block_manager_destroy); +void dm_block_manager_reset(struct dm_block_manager *bm) +{ + dm_bufio_client_reset(bm->bufio); +} +EXPORT_SYMBOL_GPL(dm_block_manager_reset); + unsigned int dm_bm_block_size(struct dm_block_manager *bm) { return dm_bufio_get_block_size(bm->bufio); diff --git a/drivers/md/persistent-data/dm-block-manager.h b/drivers/md/persistent-data/dm-block-manager.h index 5746b0f82a039f7ced8f30e40eb6a1b1767ea3c8..f706d3de8d5a15ae074ce4aea465d414ed96b29b 100644 --- a/drivers/md/persistent-data/dm-block-manager.h +++ b/drivers/md/persistent-data/dm-block-manager.h @@ -36,6 +36,7 @@ struct dm_block_manager *dm_block_manager_create( struct block_device *bdev, unsigned int block_size, unsigned int max_held_per_thread); void dm_block_manager_destroy(struct dm_block_manager *bm); +void dm_block_manager_reset(struct dm_block_manager *bm); unsigned int dm_bm_block_size(struct dm_block_manager *bm); dm_block_t dm_bm_nr_blocks(struct dm_block_manager *bm); diff --git a/drivers/md/persistent-data/dm-space-map.h b/drivers/md/persistent-data/dm-space-map.h index dab49035378163f81888983d35d184b83cd44053..6bf69922b5ad637e7549ade17ac7683b6c5e7a3b 100644 --- a/drivers/md/persistent-data/dm-space-map.h +++ b/drivers/md/persistent-data/dm-space-map.h @@ -77,7 +77,8 @@ struct dm_space_map { static inline void dm_sm_destroy(struct dm_space_map *sm) { - sm->destroy(sm); + if (sm) + sm->destroy(sm); } static inline int dm_sm_extend(struct dm_space_map *sm, dm_block_t extra_blocks) diff --git a/drivers/md/persistent-data/dm-transaction-manager.c b/drivers/md/persistent-data/dm-transaction-manager.c index 6dc016248baf1627990d369f54f207ff24c39b2c..c88fa62662035a02d488f8a43353404ce2d30422 100644 --- a/drivers/md/persistent-data/dm-transaction-manager.c +++ b/drivers/md/persistent-data/dm-transaction-manager.c @@ -199,6 +199,9 @@ EXPORT_SYMBOL_GPL(dm_tm_create_non_blocking_clone); void dm_tm_destroy(struct dm_transaction_manager *tm) { + if (!tm) + return; + if (!tm->is_clone) wipe_shadow_table(tm); diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c index f8ee9a95e25d5dc9904805dd90d0452d0e008fe6..d1ac73fcd85292756e5c3c110625920d1bcdf76b 100644 --- a/drivers/md/raid0.c +++ b/drivers/md/raid0.c @@ -270,6 +270,18 @@ static int create_strip_zones(struct mddev *mddev, struct r0conf **private_conf) goto abort; } + if (conf->layout == RAID0_ORIG_LAYOUT) { + for (i = 1; i < conf->nr_strip_zones; i++) { + sector_t first_sector = conf->strip_zone[i-1].zone_end; + + sector_div(first_sector, mddev->chunk_sectors); + zone = conf->strip_zone + i; + /* disk_shift is first disk index used in the zone */ + zone->disk_shift = sector_div(first_sector, + zone->nb_dev); + } + } + pr_debug("md/raid0:%s: done.\n", mdname(mddev)); *private_conf = conf; @@ -431,6 +443,20 @@ static int raid0_run(struct mddev *mddev) return ret; } +/* + * Convert disk_index to the disk order in which it is read/written. + * For example, if we have 4 disks, they are numbered 0,1,2,3. If we + * write the disks starting at disk 3, then the read/write order would + * be disk 3, then 0, then 1, and then disk 2 and we want map_disk_shift() + * to map the disks as follows 0,1,2,3 => 1,2,3,0. So disk 0 would map + * to 1, 1 to 2, 2 to 3, and 3 to 0. That way we can compare disks in + * that 'output' space to understand the read/write disk ordering. + */ +static int map_disk_shift(int disk_index, int num_disks, int disk_shift) +{ + return ((disk_index + num_disks - disk_shift) % num_disks); +} + static void raid0_handle_discard(struct mddev *mddev, struct bio *bio) { struct r0conf *conf = mddev->private; @@ -444,7 +470,9 @@ static void raid0_handle_discard(struct mddev *mddev, struct bio *bio) sector_t end_disk_offset; unsigned int end_disk_index; unsigned int disk; + sector_t orig_start, orig_end; + orig_start = start; zone = find_zone(conf, &start); if (bio_end_sector(bio) > zone->zone_end) { @@ -458,6 +486,7 @@ static void raid0_handle_discard(struct mddev *mddev, struct bio *bio) } else end = bio_end_sector(bio); + orig_end = end; if (zone != conf->strip_zone) end = end - zone[-1].zone_end; @@ -469,13 +498,26 @@ static void raid0_handle_discard(struct mddev *mddev, struct bio *bio) last_stripe_index = end; sector_div(last_stripe_index, stripe_size); - start_disk_index = (int)(start - first_stripe_index * stripe_size) / - mddev->chunk_sectors; + /* In the first zone the original and alternate layouts are the same */ + if ((conf->layout == RAID0_ORIG_LAYOUT) && (zone != conf->strip_zone)) { + sector_div(orig_start, mddev->chunk_sectors); + start_disk_index = sector_div(orig_start, zone->nb_dev); + start_disk_index = map_disk_shift(start_disk_index, + zone->nb_dev, + zone->disk_shift); + sector_div(orig_end, mddev->chunk_sectors); + end_disk_index = sector_div(orig_end, zone->nb_dev); + end_disk_index = map_disk_shift(end_disk_index, + zone->nb_dev, zone->disk_shift); + } else { + start_disk_index = (int)(start - first_stripe_index * stripe_size) / + mddev->chunk_sectors; + end_disk_index = (int)(end - last_stripe_index * stripe_size) / + mddev->chunk_sectors; + } start_disk_offset = ((int)(start - first_stripe_index * stripe_size) % mddev->chunk_sectors) + first_stripe_index * mddev->chunk_sectors; - end_disk_index = (int)(end - last_stripe_index * stripe_size) / - mddev->chunk_sectors; end_disk_offset = ((int)(end - last_stripe_index * stripe_size) % mddev->chunk_sectors) + last_stripe_index * mddev->chunk_sectors; @@ -483,18 +525,22 @@ static void raid0_handle_discard(struct mddev *mddev, struct bio *bio) for (disk = 0; disk < zone->nb_dev; disk++) { sector_t dev_start, dev_end; struct md_rdev *rdev; + int compare_disk; + + compare_disk = map_disk_shift(disk, zone->nb_dev, + zone->disk_shift); - if (disk < start_disk_index) + if (compare_disk < start_disk_index) dev_start = (first_stripe_index + 1) * mddev->chunk_sectors; - else if (disk > start_disk_index) + else if (compare_disk > start_disk_index) dev_start = first_stripe_index * mddev->chunk_sectors; else dev_start = start_disk_offset; - if (disk < end_disk_index) + if (compare_disk < end_disk_index) dev_end = (last_stripe_index + 1) * mddev->chunk_sectors; - else if (disk > end_disk_index) + else if (compare_disk > end_disk_index) dev_end = last_stripe_index * mddev->chunk_sectors; else dev_end = end_disk_offset; diff --git a/drivers/md/raid0.h b/drivers/md/raid0.h index 3816e5477db1e743afeaf707c1971f1dbdce1901..8cc761ca7423002d3d1d1e4c84ac5df9a3dcc70f 100644 --- a/drivers/md/raid0.h +++ b/drivers/md/raid0.h @@ -6,6 +6,7 @@ struct strip_zone { sector_t zone_end; /* Start of the next zone (in sectors) */ sector_t dev_start; /* Zone offset in real dev (in sectors) */ int nb_dev; /* # of devices attached to the zone */ + int disk_shift; /* start disk for the original layout */ }; /* Linux 3.14 (20d0189b101) made an unintended change to diff --git a/drivers/md/raid1-10.c b/drivers/md/raid1-10.c index e61f6cad4e08e9bef57faaecfef4305f1a621200..3f22edec70e7845f68697399676038adf879d90f 100644 --- a/drivers/md/raid1-10.c +++ b/drivers/md/raid1-10.c @@ -21,6 +21,7 @@ #define IO_MADE_GOOD ((struct bio *)2) #define BIO_SPECIAL(bio) ((unsigned long)bio <= 2) +#define MAX_PLUG_BIO 32 /* for managing resync I/O pages */ struct resync_pages { @@ -31,6 +32,7 @@ struct resync_pages { struct raid1_plug_cb { struct blk_plug_cb cb; struct bio_list pending; + unsigned int count; }; static void rbio_pool_free(void *rbio, void *data) @@ -101,11 +103,73 @@ static void md_bio_reset_resync_pages(struct bio *bio, struct resync_pages *rp, struct page *page = resync_fetch_page(rp, idx); int len = min_t(int, size, PAGE_SIZE); - /* - * won't fail because the vec table is big - * enough to hold all these pages - */ - bio_add_page(bio, page, len, 0); + if (WARN_ON(!bio_add_page(bio, page, len, 0))) { + bio->bi_status = BLK_STS_RESOURCE; + bio_endio(bio); + return; + } + size -= len; } while (idx++ < RESYNC_PAGES && size > 0); } + + +static inline void raid1_submit_write(struct bio *bio) +{ + struct md_rdev *rdev = (void *)bio->bi_bdev; + + bio->bi_next = NULL; + bio_set_dev(bio, rdev->bdev); + if (test_bit(Faulty, &rdev->flags)) + bio_io_error(bio); + else if (unlikely(bio_op(bio) == REQ_OP_DISCARD && + !bdev_max_discard_sectors(bio->bi_bdev))) + /* Just ignore it */ + bio_endio(bio); + else + submit_bio_noacct(bio); +} + +static inline bool raid1_add_bio_to_plug(struct mddev *mddev, struct bio *bio, + blk_plug_cb_fn unplug, int copies) +{ + struct raid1_plug_cb *plug = NULL; + struct blk_plug_cb *cb; + + /* + * If bitmap is not enabled, it's safe to submit the io directly, and + * this can get optimal performance. + */ + if (!md_bitmap_enabled(mddev->bitmap)) { + raid1_submit_write(bio); + return true; + } + + cb = blk_check_plugged(unplug, mddev, sizeof(*plug)); + if (!cb) + return false; + + plug = container_of(cb, struct raid1_plug_cb, cb); + bio_list_add(&plug->pending, bio); + if (++plug->count / MAX_PLUG_BIO >= copies) { + list_del(&cb->list); + cb->callback(cb, false); + } + + + return true; +} + +/* + * current->bio_list will be set under submit_bio() context, in this case bitmap + * io will be added to the list and wait for current io submission to finish, + * while current io submission must wait for bitmap io to be done. In order to + * avoid such deadlock, submit bitmap io asynchronously. + */ +static inline void raid1_prepare_flush_writes(struct bitmap *bitmap) +{ + if (current->bio_list) + md_bitmap_unplug_async(bitmap); + else + md_bitmap_unplug(bitmap); +} diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index 68a9e2d9985b2f772c3b71459da7b68a74379a42..dd25832eb04527072a25b1bf098a3873a203db6d 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -794,22 +794,13 @@ static int read_balance(struct r1conf *conf, struct r1bio *r1_bio, int *max_sect static void flush_bio_list(struct r1conf *conf, struct bio *bio) { /* flush any pending bitmap writes to disk before proceeding w/ I/O */ - md_bitmap_unplug(conf->mddev->bitmap); + raid1_prepare_flush_writes(conf->mddev->bitmap); wake_up(&conf->wait_barrier); while (bio) { /* submit pending writes */ struct bio *next = bio->bi_next; - struct md_rdev *rdev = (void *)bio->bi_bdev; - bio->bi_next = NULL; - bio_set_dev(bio, rdev->bdev); - if (test_bit(Faulty, &rdev->flags)) { - bio_io_error(bio); - } else if (unlikely((bio_op(bio) == REQ_OP_DISCARD) && - !bdev_max_discard_sectors(bio->bi_bdev))) - /* Just ignore it */ - bio_endio(bio); - else - submit_bio_noacct(bio); + + raid1_submit_write(bio); bio = next; cond_resched(); } @@ -1147,7 +1138,10 @@ static void alloc_behind_master_bio(struct r1bio *r1_bio, if (unlikely(!page)) goto free_pages; - bio_add_page(behind_bio, page, len, 0); + if (!bio_add_page(behind_bio, page, len, 0)) { + put_page(page); + goto free_pages; + } size -= len; i++; @@ -1175,7 +1169,7 @@ static void raid1_unplug(struct blk_plug_cb *cb, bool from_schedule) struct r1conf *conf = mddev->private; struct bio *bio; - if (from_schedule || current->bio_list) { + if (from_schedule) { spin_lock_irq(&conf->device_lock); bio_list_merge(&conf->pending_bio_list, &plug->pending); spin_unlock_irq(&conf->device_lock); @@ -1343,8 +1337,6 @@ static void raid1_write_request(struct mddev *mddev, struct bio *bio, struct bitmap *bitmap = mddev->bitmap; unsigned long flags; struct md_rdev *blocked_rdev; - struct blk_plug_cb *cb; - struct raid1_plug_cb *plug = NULL; int first_clone; int max_sectors; bool write_behind = false; @@ -1573,15 +1565,7 @@ static void raid1_write_request(struct mddev *mddev, struct bio *bio, r1_bio->sector); /* flush_pending_writes() needs access to the rdev so...*/ mbio->bi_bdev = (void *)rdev; - - cb = blk_check_plugged(raid1_unplug, mddev, sizeof(*plug)); - if (cb) - plug = container_of(cb, struct raid1_plug_cb, cb); - else - plug = NULL; - if (plug) { - bio_list_add(&plug->pending, mbio); - } else { + if (!raid1_add_bio_to_plug(mddev, mbio, raid1_unplug, disks)) { spin_lock_irqsave(&conf->device_lock, flags); bio_list_add(&conf->pending_bio_list, mbio); spin_unlock_irqrestore(&conf->device_lock, flags); @@ -2914,7 +2898,7 @@ static sector_t raid1_sync_request(struct mddev *mddev, sector_t sector_nr, * won't fail because the vec table is big * enough to hold all these pages */ - bio_add_page(bio, page, len, 0); + __bio_add_page(bio, page, len, 0); } } nr_sectors += len>>9; @@ -3084,7 +3068,8 @@ static struct r1conf *setup_conf(struct mddev *mddev) } err = -ENOMEM; - conf->thread = md_register_thread(raid1d, mddev, "raid1"); + rcu_assign_pointer(conf->thread, + md_register_thread(raid1d, mddev, "raid1")); if (!conf->thread) goto abort; @@ -3177,8 +3162,8 @@ static int raid1_run(struct mddev *mddev) /* * Ok, everything is just fine now */ - mddev->thread = conf->thread; - conf->thread = NULL; + rcu_assign_pointer(mddev->thread, conf->thread); + rcu_assign_pointer(conf->thread, NULL); mddev->private = conf; set_bit(MD_FAILFAST_SUPPORTED, &mddev->flags); diff --git a/drivers/md/raid1.h b/drivers/md/raid1.h index ebb6788820e796d12528ab119e5068af69fc2b50..468f189da7a05042fcf82f3dde2c6bf621dc1456 100644 --- a/drivers/md/raid1.h +++ b/drivers/md/raid1.h @@ -130,7 +130,7 @@ struct r1conf { /* When taking over an array from a different personality, we store * the new thread here until we fully activate the array. */ - struct md_thread *thread; + struct md_thread __rcu *thread; /* Keep track of cluster resync window to send to other * nodes. diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 4fcfcb350d2b43c3ffa5d2f2cb581d7ee47a5321..5051149e27bbeae8d8661853137e4d2572ee5fef 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -325,7 +325,7 @@ static void raid_end_bio_io(struct r10bio *r10_bio) if (!test_bit(R10BIO_Uptodate, &r10_bio->state)) bio->bi_status = BLK_STS_IOERR; - if (blk_queue_io_stat(bio->bi_bdev->bd_disk->queue)) + if (r10_bio->start_time) bio_end_io_acct(bio, r10_bio->start_time); bio_endio(bio); /* @@ -779,8 +779,16 @@ static struct md_rdev *read_balance(struct r10conf *conf, disk = r10_bio->devs[slot].devnum; rdev = rcu_dereference(conf->mirrors[disk].replacement); if (rdev == NULL || test_bit(Faulty, &rdev->flags) || - r10_bio->devs[slot].addr + sectors > rdev->recovery_offset) + r10_bio->devs[slot].addr + sectors > + rdev->recovery_offset) { + /* + * Read replacement first to prevent reading both rdev + * and replacement as NULL during replacement replace + * rdev. + */ + smp_mb(); rdev = rcu_dereference(conf->mirrors[disk].rdev); + } if (rdev == NULL || test_bit(Faulty, &rdev->flags)) continue; @@ -902,25 +910,15 @@ static void flush_pending_writes(struct r10conf *conf) __set_current_state(TASK_RUNNING); blk_start_plug(&plug); - /* flush any pending bitmap writes to disk - * before proceeding w/ I/O */ - md_bitmap_unplug(conf->mddev->bitmap); + raid1_prepare_flush_writes(conf->mddev->bitmap); wake_up(&conf->wait_barrier); while (bio) { /* submit pending writes */ struct bio *next = bio->bi_next; - struct md_rdev *rdev = (void*)bio->bi_bdev; - bio->bi_next = NULL; - bio_set_dev(bio, rdev->bdev); - if (test_bit(Faulty, &rdev->flags)) { - bio_io_error(bio); - } else if (unlikely((bio_op(bio) == REQ_OP_DISCARD) && - !bdev_max_discard_sectors(bio->bi_bdev))) - /* Just ignore it */ - bio_endio(bio); - else - submit_bio_noacct(bio); + + raid1_submit_write(bio); bio = next; + cond_resched(); } blk_finish_plug(&plug); } else @@ -982,6 +980,7 @@ static void lower_barrier(struct r10conf *conf) static bool stop_waiting_barrier(struct r10conf *conf) { struct bio_list *bio_list = current->bio_list; + struct md_thread *thread; /* barrier is dropped */ if (!conf->barrier) @@ -997,12 +996,14 @@ static bool stop_waiting_barrier(struct r10conf *conf) (!bio_list_empty(&bio_list[0]) || !bio_list_empty(&bio_list[1]))) return true; + /* daemon thread must exist while handling io */ + thread = rcu_dereference_protected(conf->mddev->thread, true); /* * move on if io is issued from raid10d(), nr_pending is not released * from original io(see handle_read_error()). All raise barrier is * blocked until this io is done. */ - if (conf->mddev->thread->tsk == current) { + if (thread->tsk == current) { WARN_ON_ONCE(atomic_read(&conf->nr_pending) == 0); return true; } @@ -1113,11 +1114,11 @@ static void raid10_unplug(struct blk_plug_cb *cb, bool from_schedule) struct r10conf *conf = mddev->private; struct bio *bio; - if (from_schedule || current->bio_list) { + if (from_schedule) { spin_lock_irq(&conf->device_lock); bio_list_merge(&conf->pending_bio_list, &plug->pending); spin_unlock_irq(&conf->device_lock); - wake_up(&conf->wait_barrier); + wake_up_barrier(conf); md_wakeup_thread(mddev->thread); kfree(plug); return; @@ -1125,23 +1126,15 @@ static void raid10_unplug(struct blk_plug_cb *cb, bool from_schedule) /* we aren't scheduling, so we can do the write-out directly. */ bio = bio_list_get(&plug->pending); - md_bitmap_unplug(mddev->bitmap); - wake_up(&conf->wait_barrier); + raid1_prepare_flush_writes(mddev->bitmap); + wake_up_barrier(conf); while (bio) { /* submit pending writes */ struct bio *next = bio->bi_next; - struct md_rdev *rdev = (void*)bio->bi_bdev; - bio->bi_next = NULL; - bio_set_dev(bio, rdev->bdev); - if (test_bit(Faulty, &rdev->flags)) { - bio_io_error(bio); - } else if (unlikely((bio_op(bio) == REQ_OP_DISCARD) && - !bdev_max_discard_sectors(bio->bi_bdev))) - /* Just ignore it */ - bio_endio(bio); - else - submit_bio_noacct(bio); + + raid1_submit_write(bio); bio = next; + cond_resched(); } kfree(plug); } @@ -1282,8 +1275,6 @@ static void raid10_write_one_disk(struct mddev *mddev, struct r10bio *r10_bio, const blk_opf_t do_sync = bio->bi_opf & REQ_SYNC; const blk_opf_t do_fua = bio->bi_opf & REQ_FUA; unsigned long flags; - struct blk_plug_cb *cb; - struct raid1_plug_cb *plug = NULL; struct r10conf *conf = mddev->private; struct md_rdev *rdev; int devnum = r10_bio->devs[n_copy].devnum; @@ -1323,14 +1314,7 @@ static void raid10_write_one_disk(struct mddev *mddev, struct r10bio *r10_bio, atomic_inc(&r10_bio->remaining); - cb = blk_check_plugged(raid10_unplug, mddev, sizeof(*plug)); - if (cb) - plug = container_of(cb, struct raid1_plug_cb, cb); - else - plug = NULL; - if (plug) { - bio_list_add(&plug->pending, mbio); - } else { + if (!raid1_add_bio_to_plug(mddev, mbio, raid10_unplug, conf->copies)) { spin_lock_irqsave(&conf->device_lock, flags); bio_list_add(&conf->pending_bio_list, mbio); spin_unlock_irqrestore(&conf->device_lock, flags); @@ -1479,9 +1463,15 @@ static void raid10_write_request(struct mddev *mddev, struct bio *bio, for (i = 0; i < conf->copies; i++) { int d = r10_bio->devs[i].devnum; - struct md_rdev *rdev = rcu_dereference(conf->mirrors[d].rdev); - struct md_rdev *rrdev = rcu_dereference( - conf->mirrors[d].replacement); + struct md_rdev *rdev, *rrdev; + + rrdev = rcu_dereference(conf->mirrors[d].replacement); + /* + * Read replacement first to prevent reading both rdev and + * replacement as NULL during replacement replace rdev. + */ + smp_mb(); + rdev = rcu_dereference(conf->mirrors[d].rdev); if (rdev == rrdev) rrdev = NULL; if (rdev && (test_bit(Faulty, &rdev->flags))) @@ -2148,9 +2138,10 @@ static int raid10_add_disk(struct mddev *mddev, struct md_rdev *rdev) { struct r10conf *conf = mddev->private; int err = -EEXIST; - int mirror; + int mirror, repl_slot = -1; int first = 0; int last = conf->geo.raid_disks - 1; + struct raid10_info *p; if (mddev->recovery_cp < MaxSector) /* only hot-add to in-sync arrays, as recovery is @@ -2173,23 +2164,14 @@ static int raid10_add_disk(struct mddev *mddev, struct md_rdev *rdev) else mirror = first; for ( ; mirror <= last ; mirror++) { - struct raid10_info *p = &conf->mirrors[mirror]; + p = &conf->mirrors[mirror]; if (p->recovery_disabled == mddev->recovery_disabled) continue; if (p->rdev) { - if (!test_bit(WantReplacement, &p->rdev->flags) || - p->replacement != NULL) - continue; - clear_bit(In_sync, &rdev->flags); - set_bit(Replacement, &rdev->flags); - rdev->raid_disk = mirror; - err = 0; - if (mddev->gendisk) - disk_stack_limits(mddev->gendisk, rdev->bdev, - rdev->data_offset << 9); - conf->fullsync = 1; - rcu_assign_pointer(p->replacement, rdev); - break; + if (test_bit(WantReplacement, &p->rdev->flags) && + p->replacement == NULL && repl_slot < 0) + repl_slot = mirror; + continue; } if (mddev->gendisk) @@ -2206,6 +2188,19 @@ static int raid10_add_disk(struct mddev *mddev, struct md_rdev *rdev) break; } + if (err && repl_slot >= 0) { + p = &conf->mirrors[repl_slot]; + clear_bit(In_sync, &rdev->flags); + set_bit(Replacement, &rdev->flags); + rdev->raid_disk = repl_slot; + err = 0; + if (mddev->gendisk) + disk_stack_limits(mddev->gendisk, rdev->bdev, + rdev->data_offset << 9); + conf->fullsync = 1; + rcu_assign_pointer(p->replacement, rdev); + } + print_conf(conf); return err; } @@ -3303,6 +3298,7 @@ static sector_t raid10_sync_request(struct mddev *mddev, sector_t sector_nr, int chunks_skipped = 0; sector_t chunk_mask = conf->geo.chunk_mask; int page_idx = 0; + int error_disk = -1; /* * Allow skipping a full rebuild for incremental assembly @@ -3386,8 +3382,21 @@ static sector_t raid10_sync_request(struct mddev *mddev, sector_t sector_nr, return reshape_request(mddev, sector_nr, skipped); if (chunks_skipped >= conf->geo.raid_disks) { - /* if there has been nothing to do on any drive, - * then there is nothing to do at all.. + pr_err("md/raid10:%s: %s fails\n", mdname(mddev), + test_bit(MD_RECOVERY_SYNC, &mddev->recovery) ? "resync" : "recovery"); + if (error_disk >= 0 && + !test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) { + /* + * recovery fails, set mirrors.recovery_disabled, + * device shouldn't be added to there. + */ + conf->mirrors[error_disk].recovery_disabled = + mddev->recovery_disabled; + return 0; + } + /* + * if there has been nothing to do on any drive, + * then there is nothing to do at all. */ *skipped = 1; return (max_sector - sector_nr) + sectors_skipped; @@ -3437,8 +3446,6 @@ static sector_t raid10_sync_request(struct mddev *mddev, sector_t sector_nr, sector_t sect; int must_sync; int any_working; - int need_recover = 0; - int need_replace = 0; struct raid10_info *mirror = &conf->mirrors[i]; struct md_rdev *mrdev, *mreplace; @@ -3446,15 +3453,13 @@ static sector_t raid10_sync_request(struct mddev *mddev, sector_t sector_nr, mrdev = rcu_dereference(mirror->rdev); mreplace = rcu_dereference(mirror->replacement); - if (mrdev != NULL && - !test_bit(Faulty, &mrdev->flags) && - !test_bit(In_sync, &mrdev->flags)) - need_recover = 1; - if (mreplace != NULL && - !test_bit(Faulty, &mreplace->flags)) - need_replace = 1; + if (mrdev && (test_bit(Faulty, &mrdev->flags) || + test_bit(In_sync, &mrdev->flags))) + mrdev = NULL; + if (mreplace && test_bit(Faulty, &mreplace->flags)) + mreplace = NULL; - if (!need_recover && !need_replace) { + if (!mrdev && !mreplace) { rcu_read_unlock(); continue; } @@ -3470,8 +3475,6 @@ static sector_t raid10_sync_request(struct mddev *mddev, sector_t sector_nr, rcu_read_unlock(); continue; } - if (mreplace && test_bit(Faulty, &mreplace->flags)) - mreplace = NULL; /* Unless we are doing a full sync, or a replacement * we only need to recover the block if it is set in * the bitmap @@ -3490,7 +3493,8 @@ static sector_t raid10_sync_request(struct mddev *mddev, sector_t sector_nr, rcu_read_unlock(); continue; } - atomic_inc(&mrdev->nr_pending); + if (mrdev) + atomic_inc(&mrdev->nr_pending); if (mreplace) atomic_inc(&mreplace->nr_pending); rcu_read_unlock(); @@ -3577,7 +3581,7 @@ static sector_t raid10_sync_request(struct mddev *mddev, sector_t sector_nr, r10_bio->devs[1].devnum = i; r10_bio->devs[1].addr = to_addr; - if (need_recover) { + if (mrdev) { bio = r10_bio->devs[1].bio; bio->bi_next = biolist; biolist = bio; @@ -3594,11 +3598,11 @@ static sector_t raid10_sync_request(struct mddev *mddev, sector_t sector_nr, bio = r10_bio->devs[1].repl_bio; if (bio) bio->bi_end_io = NULL; - /* Note: if need_replace, then bio + /* Note: if replace is not NULL, then bio * cannot be NULL as r10buf_pool_alloc will * have allocated it. */ - if (!need_replace) + if (!mreplace) break; bio->bi_next = biolist; biolist = bio; @@ -3622,7 +3626,7 @@ static sector_t raid10_sync_request(struct mddev *mddev, sector_t sector_nr, for (k = 0; k < conf->copies; k++) if (r10_bio->devs[k].devnum == i) break; - if (!test_bit(In_sync, + if (mrdev && !test_bit(In_sync, &mrdev->flags) && !rdev_set_badblocks( mrdev, @@ -3643,17 +3647,21 @@ static sector_t raid10_sync_request(struct mddev *mddev, sector_t sector_nr, mdname(mddev)); mirror->recovery_disabled = mddev->recovery_disabled; + } else { + error_disk = i; } put_buf(r10_bio); if (rb2) atomic_dec(&rb2->remaining); r10_bio = rb2; - rdev_dec_pending(mrdev, mddev); + if (mrdev) + rdev_dec_pending(mrdev, mddev); if (mreplace) rdev_dec_pending(mreplace, mddev); break; } - rdev_dec_pending(mrdev, mddev); + if (mrdev) + rdev_dec_pending(mrdev, mddev); if (mreplace) rdev_dec_pending(mreplace, mddev); if (r10_bio->devs[0].bio->bi_opf & MD_FAILFAST) { @@ -3819,11 +3827,11 @@ static sector_t raid10_sync_request(struct mddev *mddev, sector_t sector_nr, for (bio= biolist ; bio ; bio=bio->bi_next) { struct resync_pages *rp = get_resync_pages(bio); page = resync_fetch_page(rp, page_idx); - /* - * won't fail because the vec table is big enough - * to hold all these pages - */ - bio_add_page(bio, page, len, 0); + if (WARN_ON(!bio_add_page(bio, page, len, 0))) { + bio->bi_status = BLK_STS_RESOURCE; + bio_endio(bio); + goto giveup; + } } nr_sectors += len>>9; sector_nr += len>>9; @@ -4107,7 +4115,8 @@ static struct r10conf *setup_conf(struct mddev *mddev) atomic_set(&conf->nr_pending, 0); err = -ENOMEM; - conf->thread = md_register_thread(raid10d, mddev, "raid10"); + rcu_assign_pointer(conf->thread, + md_register_thread(raid10d, mddev, "raid10")); if (!conf->thread) goto out; @@ -4152,8 +4161,8 @@ static int raid10_run(struct mddev *mddev) if (!conf) goto out; - mddev->thread = conf->thread; - conf->thread = NULL; + rcu_assign_pointer(mddev->thread, conf->thread); + rcu_assign_pointer(conf->thread, NULL); if (mddev_is_clustered(conf->mddev)) { int fc, fo; @@ -4296,8 +4305,8 @@ static int raid10_run(struct mddev *mddev) clear_bit(MD_RECOVERY_CHECK, &mddev->recovery); set_bit(MD_RECOVERY_RESHAPE, &mddev->recovery); set_bit(MD_RECOVERY_RUNNING, &mddev->recovery); - mddev->sync_thread = md_register_thread(md_do_sync, mddev, - "reshape"); + rcu_assign_pointer(mddev->sync_thread, + md_register_thread(md_do_sync, mddev, "reshape")); if (!mddev->sync_thread) goto out_free_conf; } @@ -4698,8 +4707,8 @@ static int raid10_start_reshape(struct mddev *mddev) set_bit(MD_RECOVERY_RESHAPE, &mddev->recovery); set_bit(MD_RECOVERY_RUNNING, &mddev->recovery); - mddev->sync_thread = md_register_thread(md_do_sync, mddev, - "reshape"); + rcu_assign_pointer(mddev->sync_thread, + md_register_thread(md_do_sync, mddev, "reshape")); if (!mddev->sync_thread) { ret = -EAGAIN; goto abort; @@ -4997,11 +5006,11 @@ static sector_t reshape_request(struct mddev *mddev, sector_t sector_nr, if (len > PAGE_SIZE) len = PAGE_SIZE; for (bio = blist; bio ; bio = bio->bi_next) { - /* - * won't fail because the vec table is big enough - * to hold all these pages - */ - bio_add_page(bio, page, len, 0); + if (WARN_ON(!bio_add_page(bio, page, len, 0))) { + bio->bi_status = BLK_STS_RESOURCE; + bio_endio(bio); + return sectors_done; + } } sector_nr += len >> 9; nr_sectors += len >> 9; diff --git a/drivers/md/raid10.h b/drivers/md/raid10.h index 8c072ce0bc542038837ed5640afe475db18b51ba..63e48b11b5529c03e3e185aab6279cc6b98ab8e3 100644 --- a/drivers/md/raid10.h +++ b/drivers/md/raid10.h @@ -100,7 +100,7 @@ struct r10conf { /* When taking over an array from a different personality, we store * the new thread here until we fully activate the array. */ - struct md_thread *thread; + struct md_thread __rcu *thread; /* * Keep track of cluster resync window to send to other nodes. diff --git a/drivers/md/raid5-cache.c b/drivers/md/raid5-cache.c index 46182b955aef81ee9938100b00985ed6fc35c510..47ba7d9e81e18ac4acec816abea286a051150b60 100644 --- a/drivers/md/raid5-cache.c +++ b/drivers/md/raid5-cache.c @@ -120,7 +120,7 @@ struct r5l_log { struct bio_set bs; mempool_t meta_pool; - struct md_thread *reclaim_thread; + struct md_thread __rcu *reclaim_thread; unsigned long reclaim_target; /* number of space that need to be * reclaimed. if it's 0, reclaim spaces * used by io_units which are in @@ -792,7 +792,7 @@ static struct r5l_io_unit *r5l_new_meta(struct r5l_log *log) io->current_bio = r5l_bio_alloc(log); io->current_bio->bi_end_io = r5l_log_endio; io->current_bio->bi_private = io; - bio_add_page(io->current_bio, io->meta_page, PAGE_SIZE, 0); + __bio_add_page(io->current_bio, io->meta_page, PAGE_SIZE, 0); r5_reserve_log_entry(log, io); @@ -1576,17 +1576,18 @@ void r5l_wake_reclaim(struct r5l_log *log, sector_t space) void r5l_quiesce(struct r5l_log *log, int quiesce) { - struct mddev *mddev; + struct mddev *mddev = log->rdev->mddev; + struct md_thread *thread = rcu_dereference_protected( + log->reclaim_thread, lockdep_is_held(&mddev->reconfig_mutex)); if (quiesce) { /* make sure r5l_write_super_and_discard_space exits */ - mddev = log->rdev->mddev; wake_up(&mddev->sb_wait); - kthread_park(log->reclaim_thread->tsk); + kthread_park(thread->tsk); r5l_wake_reclaim(log, MaxSector); r5l_do_reclaim(log); } else - kthread_unpark(log->reclaim_thread->tsk); + kthread_unpark(thread->tsk); } bool r5l_log_disk_error(struct r5conf *conf) @@ -3063,6 +3064,7 @@ void r5c_update_on_rdev_error(struct mddev *mddev, struct md_rdev *rdev) int r5l_init_log(struct r5conf *conf, struct md_rdev *rdev) { struct r5l_log *log; + struct md_thread *thread; int ret; pr_debug("md/raid:%s: using device %pg as journal\n", @@ -3121,11 +3123,13 @@ int r5l_init_log(struct r5conf *conf, struct md_rdev *rdev) spin_lock_init(&log->tree_lock); INIT_RADIX_TREE(&log->big_stripe_tree, GFP_NOWAIT | __GFP_NOWARN); - log->reclaim_thread = md_register_thread(r5l_reclaim_thread, - log->rdev->mddev, "reclaim"); - if (!log->reclaim_thread) + thread = md_register_thread(r5l_reclaim_thread, log->rdev->mddev, + "reclaim"); + if (!thread) goto reclaim_thread; - log->reclaim_thread->timeout = R5C_RECLAIM_WAKEUP_INTERVAL; + + thread->timeout = R5C_RECLAIM_WAKEUP_INTERVAL; + rcu_assign_pointer(log->reclaim_thread, thread); init_waitqueue_head(&log->iounit_wait); diff --git a/drivers/md/raid5-ppl.c b/drivers/md/raid5-ppl.c index e495939bb3e0374c7209cb2e8c7648acbecee479..eaea57aee602c0c41a41878704b02efe4e27c1ce 100644 --- a/drivers/md/raid5-ppl.c +++ b/drivers/md/raid5-ppl.c @@ -465,7 +465,7 @@ static void ppl_submit_iounit(struct ppl_io_unit *io) bio->bi_end_io = ppl_log_endio; bio->bi_iter.bi_sector = log->next_io_sector; - bio_add_page(bio, io->header_page, PAGE_SIZE, 0); + __bio_add_page(bio, io->header_page, PAGE_SIZE, 0); pr_debug("%s: log->current_io_sector: %llu\n", __func__, (unsigned long long)log->next_io_sector); @@ -496,7 +496,7 @@ static void ppl_submit_iounit(struct ppl_io_unit *io) prev->bi_opf, GFP_NOIO, &ppl_conf->bs); bio->bi_iter.bi_sector = bio_end_sector(prev); - bio_add_page(bio, sh->ppl_page, PAGE_SIZE, 0); + __bio_add_page(bio, sh->ppl_page, PAGE_SIZE, 0); bio_chain(bio, prev); ppl_submit_iounit_bio(io, prev); diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 9ea285fbc4a654703f363f7d450c903d5e8c6d77..85b3004594e03a2b4e778efea1142c57417a81f3 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -2433,7 +2433,7 @@ static int grow_stripes(struct r5conf *conf, int num) conf->active_name = 0; sc = kmem_cache_create(conf->cache_name[conf->active_name], - sizeof(struct stripe_head)+(devs-1)*sizeof(struct r5dev), + struct_size_t(struct stripe_head, dev, devs), 0, 0, NULL); if (!sc) return 1; @@ -2559,7 +2559,7 @@ static int resize_stripes(struct r5conf *conf, int newsize) /* Step 1 */ sc = kmem_cache_create(conf->cache_name[1-conf->active_name], - sizeof(struct stripe_head)+(newsize-1)*sizeof(struct r5dev), + struct_size_t(struct stripe_head, dev, newsize), 0, 0, NULL); if (!sc) return -ENOMEM; @@ -5966,6 +5966,19 @@ static int add_all_stripe_bios(struct r5conf *conf, return ret; } +static bool reshape_inprogress(struct mddev *mddev) +{ + return test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery) && + test_bit(MD_RECOVERY_RUNNING, &mddev->recovery) && + !test_bit(MD_RECOVERY_DONE, &mddev->recovery) && + !test_bit(MD_RECOVERY_INTR, &mddev->recovery); +} + +static bool reshape_disabled(struct mddev *mddev) +{ + return is_md_suspended(mddev) || !md_is_rdwr(mddev); +} + static enum stripe_result make_stripe_request(struct mddev *mddev, struct r5conf *conf, struct stripe_request_ctx *ctx, sector_t logical_sector, struct bio *bi) @@ -5997,7 +6010,8 @@ static enum stripe_result make_stripe_request(struct mddev *mddev, if (ahead_of_reshape(mddev, logical_sector, conf->reshape_safe)) { spin_unlock_irq(&conf->device_lock); - return STRIPE_SCHEDULE_AND_RETRY; + ret = STRIPE_SCHEDULE_AND_RETRY; + goto out; } } spin_unlock_irq(&conf->device_lock); @@ -6076,6 +6090,15 @@ static enum stripe_result make_stripe_request(struct mddev *mddev, out_release: raid5_release_stripe(sh); +out: + if (ret == STRIPE_SCHEDULE_AND_RETRY && !reshape_inprogress(mddev) && + reshape_disabled(mddev)) { + bi->bi_status = BLK_STS_IOERR; + ret = STRIPE_FAIL; + pr_err("md/raid456:%s: io failed across reshape position while reshape can't make progress.\n", + mdname(mddev)); + } + return ret; } @@ -7708,7 +7731,8 @@ static struct r5conf *setup_conf(struct mddev *mddev) } sprintf(pers_name, "raid%d", mddev->new_level); - conf->thread = md_register_thread(raid5d, mddev, pers_name); + rcu_assign_pointer(conf->thread, + md_register_thread(raid5d, mddev, pers_name)); if (!conf->thread) { pr_warn("md/raid:%s: couldn't allocate thread.\n", mdname(mddev)); @@ -7931,8 +7955,8 @@ static int raid5_run(struct mddev *mddev) } conf->min_offset_diff = min_offset_diff; - mddev->thread = conf->thread; - conf->thread = NULL; + rcu_assign_pointer(mddev->thread, conf->thread); + rcu_assign_pointer(conf->thread, NULL); mddev->private = conf; for (i = 0; i < conf->raid_disks && conf->previous_raid_disks; @@ -8029,8 +8053,8 @@ static int raid5_run(struct mddev *mddev) clear_bit(MD_RECOVERY_CHECK, &mddev->recovery); set_bit(MD_RECOVERY_RESHAPE, &mddev->recovery); set_bit(MD_RECOVERY_RUNNING, &mddev->recovery); - mddev->sync_thread = md_register_thread(md_do_sync, mddev, - "reshape"); + rcu_assign_pointer(mddev->sync_thread, + md_register_thread(md_do_sync, mddev, "reshape")); if (!mddev->sync_thread) goto abort; } @@ -8377,6 +8401,7 @@ static int raid5_add_disk(struct mddev *mddev, struct md_rdev *rdev) p = conf->disks + disk; tmp = rdev_mdlock_deref(mddev, p->rdev); if (test_bit(WantReplacement, &tmp->flags) && + mddev->reshape_position == MaxSector && p->replacement == NULL) { clear_bit(In_sync, &rdev->flags); set_bit(Replacement, &rdev->flags); @@ -8500,6 +8525,7 @@ static int raid5_start_reshape(struct mddev *mddev) struct r5conf *conf = mddev->private; struct md_rdev *rdev; int spares = 0; + int i; unsigned long flags; if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery)) @@ -8511,6 +8537,13 @@ static int raid5_start_reshape(struct mddev *mddev) if (has_failed(conf)) return -EINVAL; + /* raid5 can't handle concurrent reshape and recovery */ + if (mddev->recovery_cp < MaxSector) + return -EBUSY; + for (i = 0; i < conf->raid_disks; i++) + if (rdev_mdlock_deref(mddev, conf->disks[i].replacement)) + return -EBUSY; + rdev_for_each(rdev, mddev) { if (!test_bit(In_sync, &rdev->flags) && !test_bit(Faulty, &rdev->flags)) @@ -8607,8 +8640,8 @@ static int raid5_start_reshape(struct mddev *mddev) clear_bit(MD_RECOVERY_DONE, &mddev->recovery); set_bit(MD_RECOVERY_RESHAPE, &mddev->recovery); set_bit(MD_RECOVERY_RUNNING, &mddev->recovery); - mddev->sync_thread = md_register_thread(md_do_sync, mddev, - "reshape"); + rcu_assign_pointer(mddev->sync_thread, + md_register_thread(md_do_sync, mddev, "reshape")); if (!mddev->sync_thread) { mddev->recovery = 0; spin_lock_irq(&conf->device_lock); @@ -9043,6 +9076,22 @@ static int raid5_start(struct mddev *mddev) return r5l_start(conf->log); } +static void raid5_prepare_suspend(struct mddev *mddev) +{ + struct r5conf *conf = mddev->private; + + wait_event(mddev->sb_wait, !reshape_inprogress(mddev) || + percpu_ref_is_zero(&mddev->active_io)); + if (percpu_ref_is_zero(&mddev->active_io)) + return; + + /* + * Reshape is not in progress, and array is suspended, io that is + * waiting for reshpape can never be done. + */ + wake_up(&conf->wait_for_overlap); +} + static struct md_personality raid6_personality = { .name = "raid6", @@ -9063,6 +9112,7 @@ static struct md_personality raid6_personality = .check_reshape = raid6_check_reshape, .start_reshape = raid5_start_reshape, .finish_reshape = raid5_finish_reshape, + .prepare_suspend = raid5_prepare_suspend, .quiesce = raid5_quiesce, .takeover = raid6_takeover, .change_consistency_policy = raid5_change_consistency_policy, @@ -9087,6 +9137,7 @@ static struct md_personality raid5_personality = .check_reshape = raid5_check_reshape, .start_reshape = raid5_start_reshape, .finish_reshape = raid5_finish_reshape, + .prepare_suspend = raid5_prepare_suspend, .quiesce = raid5_quiesce, .takeover = raid5_takeover, .change_consistency_policy = raid5_change_consistency_policy, @@ -9112,6 +9163,7 @@ static struct md_personality raid4_personality = .check_reshape = raid5_check_reshape, .start_reshape = raid5_start_reshape, .finish_reshape = raid5_finish_reshape, + .prepare_suspend = raid5_prepare_suspend, .quiesce = raid5_quiesce, .takeover = raid4_takeover, .change_consistency_policy = raid5_change_consistency_policy, diff --git a/drivers/md/raid5.h b/drivers/md/raid5.h index e873938a6125d3a834df5e95bc12bd3940ee5e03..97a795979a3502761b156179ebceb724467c1643 100644 --- a/drivers/md/raid5.h +++ b/drivers/md/raid5.h @@ -268,7 +268,7 @@ struct stripe_head { unsigned long flags; u32 log_checksum; unsigned short write_hint; - } dev[1]; /* allocated with extra space depending of RAID geometry */ + } dev[]; /* allocated depending of RAID geometry ("disks" member) */ }; /* stripe_head_state - collects and tracks the dynamic state of a stripe_head @@ -679,7 +679,7 @@ struct r5conf { /* When taking over an array from a different personality, we store * the new thread here until we fully activate the array. */ - struct md_thread *thread; + struct md_thread __rcu *thread; struct list_head temp_inactive_list[NR_STRIPE_HASH_LOCKS]; struct r5worker_group *worker_groups; int group_cnt; diff --git a/drivers/media/cec/i2c/Kconfig b/drivers/media/cec/i2c/Kconfig index 70432a1d6918680232b2bba963ecc6faac32747d..d912d143fb3129c6b3d0133dbfceffdd48bd543d 100644 --- a/drivers/media/cec/i2c/Kconfig +++ b/drivers/media/cec/i2c/Kconfig @@ -5,6 +5,7 @@ config CEC_CH7322 tristate "Chrontel CH7322 CEC controller" depends on I2C + select REGMAP select REGMAP_I2C select CEC_CORE help diff --git a/drivers/media/cec/i2c/ch7322.c b/drivers/media/cec/i2c/ch7322.c index 34fad7123704fb06ecc321a8a113e79311b32666..439c15bc9e4452cdb2d3b3bc3bbc156c3591a6cb 100644 --- a/drivers/media/cec/i2c/ch7322.c +++ b/drivers/media/cec/i2c/ch7322.c @@ -591,7 +591,7 @@ static struct i2c_driver ch7322_i2c_driver = { .name = "ch7322", .of_match_table = of_match_ptr(ch7322_of_match), }, - .probe_new = ch7322_probe, + .probe = ch7322_probe, .remove = ch7322_remove, }; diff --git a/drivers/media/common/saa7146/saa7146_core.c b/drivers/media/common/saa7146/saa7146_core.c index bcb957883044c77138af70e80614dd94687c63a6..27c53eed8fe39ad323f82f6f4a426161a1d1401c 100644 --- a/drivers/media/common/saa7146/saa7146_core.c +++ b/drivers/media/common/saa7146/saa7146_core.c @@ -133,8 +133,8 @@ int saa7146_wait_for_debi_done(struct saa7146_dev *dev, int nobusyloop) ****************************************************************************/ /* this is videobuf_vmalloc_to_sg() from videobuf-dma-sg.c - make sure virt has been allocated with vmalloc_32(), otherwise the BUG() - may be triggered on highmem machines */ + make sure virt has been allocated with vmalloc_32(), otherwise return NULL + on highmem machines */ static struct scatterlist* vmalloc_to_sg(unsigned char *virt, int nr_pages) { struct scatterlist *sglist; @@ -150,7 +150,7 @@ static struct scatterlist* vmalloc_to_sg(unsigned char *virt, int nr_pages) if (NULL == pg) goto err; if (WARN_ON(PageHighMem(pg))) - return NULL; + goto err; sg_set_page(&sglist[i], pg, PAGE_SIZE, 0); } return sglist; diff --git a/drivers/media/dvb-core/dvbdev.c b/drivers/media/dvb-core/dvbdev.c index a4b05e366cccde2fd0c78d3990bf5710b1fb0ac9..305bb21d843c8bbd8cf9e0a3d8ad7635c35cb083 100644 --- a/drivers/media/dvb-core/dvbdev.c +++ b/drivers/media/dvb-core/dvbdev.c @@ -61,21 +61,21 @@ static const char * const dnames[] = { #define DVB_MAX_IDS 4 static const u8 minor_type[] = { - [DVB_DEVICE_VIDEO] = 0, - [DVB_DEVICE_AUDIO] = 1, - [DVB_DEVICE_SEC] = 2, - [DVB_DEVICE_FRONTEND] = 3, - [DVB_DEVICE_DEMUX] = 4, - [DVB_DEVICE_DVR] = 5, - [DVB_DEVICE_CA] = 6, - [DVB_DEVICE_NET] = 7, - [DVB_DEVICE_OSD] = 8, + [DVB_DEVICE_VIDEO] = 0, + [DVB_DEVICE_AUDIO] = 1, + [DVB_DEVICE_SEC] = 2, + [DVB_DEVICE_FRONTEND] = 3, + [DVB_DEVICE_DEMUX] = 4, + [DVB_DEVICE_DVR] = 5, + [DVB_DEVICE_CA] = 6, + [DVB_DEVICE_NET] = 7, + [DVB_DEVICE_OSD] = 8, }; #define nums2minor(num, type, id) \ - (((num) << 6) | ((id) << 4) | minor_type[type]) + (((num) << 6) | ((id) << 4) | minor_type[type]) -#define MAX_DVB_MINORS (DVB_MAX_ADAPTERS*64) +#define MAX_DVB_MINORS (DVB_MAX_ADAPTERS * 64) #endif static struct class *dvb_class; @@ -112,9 +112,7 @@ static int dvb_device_open(struct inode *inode, struct file *file) return -ENODEV; } - -static const struct file_operations dvb_device_fops = -{ +static const struct file_operations dvb_device_fops = { .owner = THIS_MODULE, .open = dvb_device_open, .llseek = noop_llseek, @@ -147,7 +145,6 @@ int dvb_generic_open(struct inode *inode, struct file *file) } EXPORT_SYMBOL(dvb_generic_open); - int dvb_generic_release(struct inode *inode, struct file *file) { struct dvb_device *dvbdev = file->private_data; @@ -155,11 +152,10 @@ int dvb_generic_release(struct inode *inode, struct file *file) if (!dvbdev) return -ENODEV; - if ((file->f_flags & O_ACCMODE) == O_RDONLY) { + if ((file->f_flags & O_ACCMODE) == O_RDONLY) dvbdev->readers++; - } else { + else dvbdev->writers++; - } dvbdev->users++; @@ -169,7 +165,6 @@ int dvb_generic_release(struct inode *inode, struct file *file) } EXPORT_SYMBOL(dvb_generic_release); - long dvb_generic_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { @@ -185,13 +180,13 @@ long dvb_generic_ioctl(struct file *file, } EXPORT_SYMBOL(dvb_generic_ioctl); - -static int dvbdev_get_free_id (struct dvb_adapter *adap, int type) +static int dvbdev_get_free_id(struct dvb_adapter *adap, int type) { u32 id = 0; while (id < DVB_MAX_IDS) { struct dvb_device *dev; + list_for_each_entry(dev, &adap->device_list, list_head) if (dev->type == type && dev->id == id) goto skip; @@ -245,7 +240,7 @@ static void dvb_media_device_free(struct dvb_device *dvbdev) #if defined(CONFIG_MEDIA_CONTROLLER_DVB) static int dvb_create_tsout_entity(struct dvb_device *dvbdev, - const char *name, int npads) + const char *name, int npads) { int i; @@ -387,7 +382,7 @@ static int dvb_create_media_entity(struct dvb_device *dvbdev, static int dvb_register_media_device(struct dvb_device *dvbdev, int type, int minor, - unsigned demux_sink_pads) + unsigned int demux_sink_pads) { #if defined(CONFIG_MEDIA_CONTROLLER_DVB) struct media_link *link; @@ -462,7 +457,8 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev, mutex_lock(&dvbdev_register_lock); - if ((id = dvbdev_get_free_id (adap, type)) < 0) { + id = dvbdev_get_free_id(adap, type); + if (id < 0) { mutex_unlock(&dvbdev_register_lock); *pdvbdev = NULL; pr_err("%s: couldn't find free device id\n", __func__); @@ -470,7 +466,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev, } *pdvbdev = dvbdev = kzalloc(sizeof(*dvbdev), GFP_KERNEL); - if (!dvbdev){ + if (!dvbdev) { mutex_unlock(&dvbdev_register_lock); return -ENOMEM; } @@ -482,14 +478,13 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev, */ list_for_each_entry(node, &dvbdevfops_list, list_head) { if (node->fops->owner == adap->module && - node->type == type && - node->template == template) { + node->type == type && node->template == template) { dvbdevfops = node->fops; break; } } - if (dvbdevfops == NULL) { + if (!dvbdevfops) { dvbdevfops = kmemdup(template->fops, sizeof(*dvbdevfops), GFP_KERNEL); if (!dvbdevfops) { kfree(dvbdev); @@ -497,7 +492,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev, return -ENOMEM; } - new_node = kzalloc(sizeof(struct dvbdevfops_node), GFP_KERNEL); + new_node = kzalloc(sizeof(*new_node), GFP_KERNEL); if (!new_node) { kfree(dvbdevfops); kfree(dvbdev); @@ -508,7 +503,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev, new_node->fops = dvbdevfops; new_node->type = type; new_node->template = template; - list_add_tail (&new_node->list_head, &dvbdevfops_list); + list_add_tail(&new_node->list_head, &dvbdevfops_list); } memcpy(dvbdev, template, sizeof(struct dvb_device)); @@ -518,21 +513,21 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev, dvbdev->adapter = adap; dvbdev->priv = priv; dvbdev->fops = dvbdevfops; - init_waitqueue_head (&dvbdev->wait_queue); + init_waitqueue_head(&dvbdev->wait_queue); dvbdevfops->owner = adap->module; - list_add_tail (&dvbdev->list_head, &adap->device_list); + list_add_tail(&dvbdev->list_head, &adap->device_list); down_write(&minor_rwsem); #ifdef CONFIG_DVB_DYNAMIC_MINORS for (minor = 0; minor < MAX_DVB_MINORS; minor++) - if (dvb_minors[minor] == NULL) + if (!dvb_minors[minor]) break; if (minor == MAX_DVB_MINORS) { if (new_node) { - list_del (&new_node->list_head); + list_del(&new_node->list_head); kfree(dvbdevfops); kfree(new_node); } - list_del (&dvbdev->list_head); + list_del(&dvbdev->list_head); kfree(dvbdev); up_write(&minor_rwsem); mutex_unlock(&dvbdev_register_lock); @@ -547,14 +542,14 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev, ret = dvb_register_media_device(dvbdev, type, minor, demux_sink_pads); if (ret) { pr_err("%s: dvb_register_media_device failed to create the mediagraph\n", - __func__); + __func__); if (new_node) { - list_del (&new_node->list_head); + list_del(&new_node->list_head); kfree(dvbdevfops); kfree(new_node); } dvb_media_device_free(dvbdev); - list_del (&dvbdev->list_head); + list_del(&dvbdev->list_head); kfree(dvbdev); mutex_unlock(&dvbdev_register_lock); return ret; @@ -567,12 +562,12 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev, pr_err("%s: failed to create device dvb%d.%s%d (%ld)\n", __func__, adap->num, dnames[type], id, PTR_ERR(clsdev)); if (new_node) { - list_del (&new_node->list_head); + list_del(&new_node->list_head); kfree(dvbdevfops); kfree(new_node); } dvb_media_device_free(dvbdev); - list_del (&dvbdev->list_head); + list_del(&dvbdev->list_head); kfree(dvbdev); mutex_unlock(&dvbdev_register_lock); return PTR_ERR(clsdev); @@ -586,7 +581,6 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev, } EXPORT_SYMBOL(dvb_register_device); - void dvb_remove_device(struct dvb_device *dvbdev) { if (!dvbdev) @@ -601,19 +595,17 @@ void dvb_remove_device(struct dvb_device *dvbdev) device_destroy(dvb_class, MKDEV(DVB_MAJOR, dvbdev->minor)); - list_del (&dvbdev->list_head); + list_del(&dvbdev->list_head); } EXPORT_SYMBOL(dvb_remove_device); - static void dvb_free_device(struct kref *ref) { struct dvb_device *dvbdev = container_of(ref, struct dvb_device, ref); - kfree (dvbdev); + kfree(dvbdev); } - struct dvb_device *dvb_device_get(struct dvb_device *dvbdev) { kref_get(&dvbdev->ref); @@ -621,14 +613,12 @@ struct dvb_device *dvb_device_get(struct dvb_device *dvbdev) } EXPORT_SYMBOL(dvb_device_get); - void dvb_device_put(struct dvb_device *dvbdev) { if (dvbdev) kref_put(&dvbdev->ref, dvb_free_device); } - void dvb_unregister_device(struct dvb_device *dvbdev) { dvb_remove_device(dvbdev); @@ -636,7 +626,6 @@ void dvb_unregister_device(struct dvb_device *dvbdev) } EXPORT_SYMBOL(dvb_unregister_device); - #ifdef CONFIG_MEDIA_CONTROLLER_DVB static int dvb_create_io_intf_links(struct dvb_adapter *adap, @@ -669,9 +658,9 @@ int dvb_create_media_graph(struct dvb_adapter *adap, struct media_entity *demux = NULL, *ca = NULL; struct media_link *link; struct media_interface *intf; - unsigned demux_pad = 0; - unsigned dvr_pad = 0; - unsigned ntuner = 0, ndemod = 0; + unsigned int demux_pad = 0; + unsigned int dvr_pad = 0; + unsigned int ntuner = 0, ndemod = 0; int ret, pad_source, pad_sink; static const char *connector_name = "Television"; @@ -741,7 +730,7 @@ int dvb_create_media_graph(struct dvb_adapter *adap, MEDIA_LNK_FL_ENABLED, false); } else { - pad_sink = media_get_pad_index(tuner, true, + pad_sink = media_get_pad_index(tuner, MEDIA_PAD_FL_SINK, PAD_SIGNAL_ANALOG); if (pad_sink < 0) return -EINVAL; @@ -759,7 +748,7 @@ int dvb_create_media_graph(struct dvb_adapter *adap, if (ntuner && ndemod) { /* NOTE: first found tuner source pad presumed correct */ - pad_source = media_get_pad_index(tuner, false, + pad_source = media_get_pad_index(tuner, MEDIA_PAD_FL_SOURCE, PAD_SIGNAL_ANALOG); if (pad_source < 0) return -EINVAL; @@ -795,18 +784,18 @@ int dvb_create_media_graph(struct dvb_adapter *adap, media_device_for_each_entity(entity, mdev) { if (entity->function == MEDIA_ENT_F_IO_DTV) { if (!strncmp(entity->name, DVR_TSOUT, - strlen(DVR_TSOUT))) { + strlen(DVR_TSOUT))) { ret = media_create_pad_link(demux, - ++dvr_pad, - entity, 0, 0); + ++dvr_pad, + entity, 0, 0); if (ret) return ret; } if (!strncmp(entity->name, DEMUX_TSOUT, - strlen(DEMUX_TSOUT))) { + strlen(DEMUX_TSOUT))) { ret = media_create_pad_link(demux, - ++demux_pad, - entity, 0, 0); + ++demux_pad, + entity, 0, 0); if (ret) return ret; } @@ -864,8 +853,10 @@ EXPORT_SYMBOL_GPL(dvb_create_media_graph); static int dvbdev_check_free_adapter_num(int num) { struct list_head *entry; + list_for_each(entry, &dvb_adapter_list) { struct dvb_adapter *adap; + adap = list_entry(entry, struct dvb_adapter, list_head); if (adap->num == num) return 0; @@ -873,7 +864,7 @@ static int dvbdev_check_free_adapter_num(int num) return 1; } -static int dvbdev_get_free_adapter_num (void) +static int dvbdev_get_free_adapter_num(void) { int num = 0; @@ -886,7 +877,6 @@ static int dvbdev_get_free_adapter_num (void) return -ENFILE; } - int dvb_register_adapter(struct dvb_adapter *adap, const char *name, struct module *module, struct device *device, short *adapter_nums) @@ -913,8 +903,8 @@ int dvb_register_adapter(struct dvb_adapter *adap, const char *name, return -ENFILE; } - memset (adap, 0, sizeof(struct dvb_adapter)); - INIT_LIST_HEAD (&adap->device_list); + memset(adap, 0, sizeof(struct dvb_adapter)); + INIT_LIST_HEAD(&adap->device_list); pr_info("DVB: registering new adapter (%s)\n", name); @@ -924,13 +914,13 @@ int dvb_register_adapter(struct dvb_adapter *adap, const char *name, adap->device = device; adap->mfe_shared = 0; adap->mfe_dvbdev = NULL; - mutex_init (&adap->mfe_lock); + mutex_init(&adap->mfe_lock); #ifdef CONFIG_MEDIA_CONTROLLER_DVB mutex_init(&adap->mdev_lock); #endif - list_add_tail (&adap->list_head, &dvb_adapter_list); + list_add_tail(&adap->list_head, &dvb_adapter_list); mutex_unlock(&dvbdev_register_lock); @@ -938,25 +928,26 @@ int dvb_register_adapter(struct dvb_adapter *adap, const char *name, } EXPORT_SYMBOL(dvb_register_adapter); - int dvb_unregister_adapter(struct dvb_adapter *adap) { mutex_lock(&dvbdev_register_lock); - list_del (&adap->list_head); + list_del(&adap->list_head); mutex_unlock(&dvbdev_register_lock); return 0; } EXPORT_SYMBOL(dvb_unregister_adapter); -/* if the miracle happens and "generic_usercopy()" is included into - the kernel, then this can vanish. please don't make the mistake and - define this as video_usercopy(). this will introduce a dependency - to the v4l "videodev.o" module, which is unnecessary for some - cards (ie. the budget dvb-cards don't need the v4l module...) */ +/* + * if the miracle happens and "generic_usercopy()" is included into + * the kernel, then this can vanish. please don't make the mistake and + * define this as video_usercopy(). this will introduce a dependency + * to the v4l "videodev.o" module, which is unnecessary for some + * cards (ie. the budget dvb-cards don't need the v4l module...) + */ int dvb_usercopy(struct file *file, - unsigned int cmd, unsigned long arg, - int (*func)(struct file *file, - unsigned int cmd, void *arg)) + unsigned int cmd, unsigned long arg, + int (*func)(struct file *file, + unsigned int cmd, void *arg)) { char sbuf[128]; void *mbuf = NULL; @@ -970,7 +961,7 @@ int dvb_usercopy(struct file *file, * For this command, the pointer is actually an integer * argument. */ - parg = (void *) arg; + parg = (void *)arg; break; case _IOC_READ: /* some v4l ioctls are marked wrong ... */ case _IOC_WRITE: @@ -980,7 +971,7 @@ int dvb_usercopy(struct file *file, } else { /* too big to allocate from stack */ mbuf = kmalloc(_IOC_SIZE(cmd), GFP_KERNEL); - if (NULL == mbuf) + if (!mbuf) return -ENOMEM; parg = mbuf; } @@ -992,15 +983,15 @@ int dvb_usercopy(struct file *file, } /* call driver */ - if ((err = func(file, cmd, parg)) == -ENOIOCTLCMD) + err = func(file, cmd, parg); + if (err == -ENOIOCTLCMD) err = -ENOTTY; if (err < 0) goto out; /* Copy results into user buffer */ - switch (_IOC_DIR(cmd)) - { + switch (_IOC_DIR(cmd)) { case _IOC_READ: case (_IOC_WRITE | _IOC_READ): if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd))) @@ -1080,19 +1071,20 @@ static char *dvb_devnode(const struct device *dev, umode_t *mode) dvbdev->adapter->num, dnames[dvbdev->type], dvbdev->id); } - static int __init init_dvbdev(void) { int retval; dev_t dev = MKDEV(DVB_MAJOR, 0); - if ((retval = register_chrdev_region(dev, MAX_DVB_MINORS, "DVB")) != 0) { + retval = register_chrdev_region(dev, MAX_DVB_MINORS, "DVB"); + if (retval != 0) { pr_err("dvb-core: unable to get major %d\n", DVB_MAJOR); return retval; } cdev_init(&dvb_device_cdev, &dvb_device_fops); - if ((retval = cdev_add(&dvb_device_cdev, dev, MAX_DVB_MINORS)) != 0) { + retval = cdev_add(&dvb_device_cdev, dev, MAX_DVB_MINORS); + if (retval != 0) { pr_err("dvb-core: unable register character device\n"); goto error; } @@ -1112,7 +1104,6 @@ static int __init init_dvbdev(void) return retval; } - static void __exit exit_dvbdev(void) { struct dvbdevfops_node *node, *next; @@ -1122,7 +1113,7 @@ static void __exit exit_dvbdev(void) unregister_chrdev_region(MKDEV(DVB_MAJOR, 0), MAX_DVB_MINORS); list_for_each_entry_safe(node, next, &dvbdevfops_list, list_head) { - list_del (&node->list_head); + list_del(&node->list_head); kfree(node->fops); kfree(node); } diff --git a/drivers/media/dvb-frontends/a8293.c b/drivers/media/dvb-frontends/a8293.c index cca7cbdd4c7c2353f21693496c058a46c4c0d3f1..f39887c04978f44585b43e048017c5cee3295524 100644 --- a/drivers/media/dvb-frontends/a8293.c +++ b/drivers/media/dvb-frontends/a8293.c @@ -266,7 +266,7 @@ static struct i2c_driver a8293_driver = { .name = "a8293", .suppress_bind_attrs = true, }, - .probe_new = a8293_probe, + .probe = a8293_probe, .remove = a8293_remove, .id_table = a8293_id_table, }; diff --git a/drivers/media/dvb-frontends/af9013.c b/drivers/media/dvb-frontends/af9013.c index 206758a73ae2870c3b196fdfec7f048796ff8593..a829c89792a4325e14c1d0012cc3c74b9983c62e 100644 --- a/drivers/media/dvb-frontends/af9013.c +++ b/drivers/media/dvb-frontends/af9013.c @@ -1563,7 +1563,7 @@ static struct i2c_driver af9013_driver = { .name = "af9013", .suppress_bind_attrs = true, }, - .probe_new = af9013_probe, + .probe = af9013_probe, .remove = af9013_remove, .id_table = af9013_id_table, }; diff --git a/drivers/media/dvb-frontends/af9033.c b/drivers/media/dvb-frontends/af9033.c index a30773f62006b4f2fe0379d877f405888ee1de54..49b7b04a78993934ca34c27e91d6f5cdfa1411b9 100644 --- a/drivers/media/dvb-frontends/af9033.c +++ b/drivers/media/dvb-frontends/af9033.c @@ -1183,7 +1183,7 @@ static struct i2c_driver af9033_driver = { .name = "af9033", .suppress_bind_attrs = true, }, - .probe_new = af9033_probe, + .probe = af9033_probe, .remove = af9033_remove, .id_table = af9033_id_table, }; diff --git a/drivers/media/dvb-frontends/au8522_decoder.c b/drivers/media/dvb-frontends/au8522_decoder.c index 0f748cf46089f1dd8ce345120afcfe3ba2075c1d..acc27376c246fdb29341eb2db34c726c687ff27a 100644 --- a/drivers/media/dvb-frontends/au8522_decoder.c +++ b/drivers/media/dvb-frontends/au8522_decoder.c @@ -776,7 +776,7 @@ static struct i2c_driver au8522_driver = { .driver = { .name = "au8522", }, - .probe_new = au8522_probe, + .probe = au8522_probe, .remove = au8522_remove, .id_table = au8522_id, }; diff --git a/drivers/media/dvb-frontends/cxd2099.c b/drivers/media/dvb-frontends/cxd2099.c index c0967ad95220869f4ce204bc888f78d1781c71c0..3f3b8574366682085d4d442e9aad0fcb8e6d48fd 100644 --- a/drivers/media/dvb-frontends/cxd2099.c +++ b/drivers/media/dvb-frontends/cxd2099.c @@ -681,7 +681,7 @@ static struct i2c_driver cxd2099_driver = { .driver = { .name = "cxd2099", }, - .probe_new = cxd2099_probe, + .probe = cxd2099_probe, .remove = cxd2099_remove, .id_table = cxd2099_id, }; diff --git a/drivers/media/dvb-frontends/cxd2820r_core.c b/drivers/media/dvb-frontends/cxd2820r_core.c index 47aa40967171d5dbd19dde7a906084112ebc633f..d7ee294c6833494c2b7c17b8c611a10cf0b842d6 100644 --- a/drivers/media/dvb-frontends/cxd2820r_core.c +++ b/drivers/media/dvb-frontends/cxd2820r_core.c @@ -733,7 +733,7 @@ static struct i2c_driver cxd2820r_driver = { .name = "cxd2820r", .suppress_bind_attrs = true, }, - .probe_new = cxd2820r_probe, + .probe = cxd2820r_probe, .remove = cxd2820r_remove, .id_table = cxd2820r_id_table, }; diff --git a/drivers/media/dvb-frontends/dvb-pll.c b/drivers/media/dvb-frontends/dvb-pll.c index e35e00db7dbb374d5a500bf5d37a1bc04badf641..90cb41eacf98cc6b6c2bc9cd17dcf0a3f16ca0fa 100644 --- a/drivers/media/dvb-frontends/dvb-pll.c +++ b/drivers/media/dvb-frontends/dvb-pll.c @@ -942,7 +942,7 @@ static struct i2c_driver dvb_pll_driver = { .driver = { .name = "dvb_pll", }, - .probe_new = dvb_pll_probe, + .probe = dvb_pll_probe, .remove = dvb_pll_remove, .id_table = dvb_pll_id, }; diff --git a/drivers/media/dvb-frontends/helene.c b/drivers/media/dvb-frontends/helene.c index e4bbf6a51a2bc792e253a775b492f3af12c291ab..68c1a3e0e2ba5b530adad00173757bbd2b2321ff 100644 --- a/drivers/media/dvb-frontends/helene.c +++ b/drivers/media/dvb-frontends/helene.c @@ -1110,7 +1110,7 @@ static struct i2c_driver helene_driver = { .driver = { .name = "helene", }, - .probe_new = helene_probe, + .probe = helene_probe, .id_table = helene_id, }; module_i2c_driver(helene_driver); diff --git a/drivers/media/dvb-frontends/lgdt3306a.c b/drivers/media/dvb-frontends/lgdt3306a.c index 6bf723b5ffad80426ca80c88fa9111221faab375..70258884126b0f0114cf21bc17a5e524c2ce3b92 100644 --- a/drivers/media/dvb-frontends/lgdt3306a.c +++ b/drivers/media/dvb-frontends/lgdt3306a.c @@ -2249,7 +2249,7 @@ static struct i2c_driver lgdt3306a_driver = { .name = "lgdt3306a", .suppress_bind_attrs = true, }, - .probe_new = lgdt3306a_probe, + .probe = lgdt3306a_probe, .remove = lgdt3306a_remove, .id_table = lgdt3306a_id_table, }; diff --git a/drivers/media/dvb-frontends/lgdt330x.c b/drivers/media/dvb-frontends/lgdt330x.c index 1d6932d8e49786ea97fc6672a9a782077cb3bb38..83565209c3b1ee59965896af970953826dd9f036 100644 --- a/drivers/media/dvb-frontends/lgdt330x.c +++ b/drivers/media/dvb-frontends/lgdt330x.c @@ -993,7 +993,7 @@ static struct i2c_driver lgdt330x_driver = { .name = "lgdt330x", .suppress_bind_attrs = true, }, - .probe_new = lgdt330x_probe, + .probe = lgdt330x_probe, .remove = lgdt330x_remove, .id_table = lgdt330x_id_table, }; diff --git a/drivers/media/dvb-frontends/m88ds3103.c b/drivers/media/dvb-frontends/m88ds3103.c index f26508b217ee6f19f5aa730c86e33fd58ebf323a..cf49ac56a37eda5475bfc776deb8dbdcfd7c8b02 100644 --- a/drivers/media/dvb-frontends/m88ds3103.c +++ b/drivers/media/dvb-frontends/m88ds3103.c @@ -1941,7 +1941,7 @@ static struct i2c_driver m88ds3103_driver = { .name = "m88ds3103", .suppress_bind_attrs = true, }, - .probe_new = m88ds3103_probe, + .probe = m88ds3103_probe, .remove = m88ds3103_remove, .id_table = m88ds3103_id_table, }; diff --git a/drivers/media/dvb-frontends/mb86a20s.c b/drivers/media/dvb-frontends/mb86a20s.c index b74b9afed9a2ef3f021f939146b98b50b6633c93..125fed4891ba9710726ac750edaa1679817da87d 100644 --- a/drivers/media/dvb-frontends/mb86a20s.c +++ b/drivers/media/dvb-frontends/mb86a20s.c @@ -1569,7 +1569,7 @@ static int mb86a20s_get_stats(struct dvb_frontend *fe, int status_nr) u32 t_post_bit_error = 0, t_post_bit_count = 0; u32 block_error = 0, block_count = 0; u32 t_block_error = 0, t_block_count = 0; - int active_layers = 0, pre_ber_layers = 0, post_ber_layers = 0; + int pre_ber_layers = 0, post_ber_layers = 0; int per_layers = 0; dev_dbg(&state->i2c->dev, "%s called.\n", __func__); @@ -1589,9 +1589,6 @@ static int mb86a20s_get_stats(struct dvb_frontend *fe, int status_nr) for (layer = 0; layer < NUM_LAYERS; layer++) { if (c->isdbt_layer_enabled & (1 << layer)) { - /* Layer is active and has rc segments */ - active_layers++; - /* Handle BER before vterbi */ rc = mb86a20s_get_pre_ber(fe, layer, &bit_error, &bit_count); diff --git a/drivers/media/dvb-frontends/mn88443x.c b/drivers/media/dvb-frontends/mn88443x.c index 0782f8377eb2f333731fe93de70f0804d95ffcc5..2ce5692bc22c4a364f0d1d50b2ff0b9897886f58 100644 --- a/drivers/media/dvb-frontends/mn88443x.c +++ b/drivers/media/dvb-frontends/mn88443x.c @@ -800,7 +800,7 @@ static struct i2c_driver mn88443x_driver = { .name = "mn88443x", .of_match_table = mn88443x_of_match, }, - .probe_new = mn88443x_probe, + .probe = mn88443x_probe, .remove = mn88443x_remove, .id_table = mn88443x_i2c_id, }; diff --git a/drivers/media/dvb-frontends/mn88472.c b/drivers/media/dvb-frontends/mn88472.c index 4a71f1c6371aa9a1a9cfb46105c12d6fbbe9296f..73d1e52de569edc9f3bd7e736f4ddfb68ffcd96c 100644 --- a/drivers/media/dvb-frontends/mn88472.c +++ b/drivers/media/dvb-frontends/mn88472.c @@ -718,7 +718,7 @@ static struct i2c_driver mn88472_driver = { .name = "mn88472", .suppress_bind_attrs = true, }, - .probe_new = mn88472_probe, + .probe = mn88472_probe, .remove = mn88472_remove, .id_table = mn88472_id_table, }; diff --git a/drivers/media/dvb-frontends/mn88473.c b/drivers/media/dvb-frontends/mn88473.c index 205b14ae584e90b07ac3bd18a415698a05e49765..eb50591c0e7a0fe858d1088d95cc1f81b66d9584 100644 --- a/drivers/media/dvb-frontends/mn88473.c +++ b/drivers/media/dvb-frontends/mn88473.c @@ -753,7 +753,7 @@ static struct i2c_driver mn88473_driver = { .name = "mn88473", .suppress_bind_attrs = true, }, - .probe_new = mn88473_probe, + .probe = mn88473_probe, .remove = mn88473_remove, .id_table = mn88473_id_table, }; diff --git a/drivers/media/dvb-frontends/mxl692.c b/drivers/media/dvb-frontends/mxl692.c index 9858e11943a0839f1a5aec011cffc9fd633c9bdf..2a31bde2630f88b4569bc48cb19258571fe6ed78 100644 --- a/drivers/media/dvb-frontends/mxl692.c +++ b/drivers/media/dvb-frontends/mxl692.c @@ -1355,7 +1355,7 @@ static struct i2c_driver mxl692_driver = { .driver = { .name = "mxl692", }, - .probe_new = mxl692_probe, + .probe = mxl692_probe, .remove = mxl692_remove, .id_table = mxl692_id_table, }; diff --git a/drivers/media/dvb-frontends/rtl2830.c b/drivers/media/dvb-frontends/rtl2830.c index db3254950147c478ba1b3bfd2f0a121850fdbe6d..35c969fd2cb5e6ceabe746388631691793e6081c 100644 --- a/drivers/media/dvb-frontends/rtl2830.c +++ b/drivers/media/dvb-frontends/rtl2830.c @@ -886,7 +886,7 @@ static struct i2c_driver rtl2830_driver = { .name = "rtl2830", .suppress_bind_attrs = true, }, - .probe_new = rtl2830_probe, + .probe = rtl2830_probe, .remove = rtl2830_remove, .id_table = rtl2830_id_table, }; diff --git a/drivers/media/dvb-frontends/rtl2832.c b/drivers/media/dvb-frontends/rtl2832.c index 900d4db8b9221f498bfa5a3fc991c4fd133384ad..601cf45c39358c46b334cd971078e1bab255f03a 100644 --- a/drivers/media/dvb-frontends/rtl2832.c +++ b/drivers/media/dvb-frontends/rtl2832.c @@ -1135,7 +1135,7 @@ static struct i2c_driver rtl2832_driver = { .name = "rtl2832", .suppress_bind_attrs = true, }, - .probe_new = rtl2832_probe, + .probe = rtl2832_probe, .remove = rtl2832_remove, .id_table = rtl2832_id_table, }; diff --git a/drivers/media/dvb-frontends/si2165.c b/drivers/media/dvb-frontends/si2165.c index cc07e965c34c51f7e37a78c5500cd8a82fe3f886..72810efd1a96a1438e36274044226be57fd9c987 100644 --- a/drivers/media/dvb-frontends/si2165.c +++ b/drivers/media/dvb-frontends/si2165.c @@ -1292,7 +1292,7 @@ static struct i2c_driver si2165_driver = { .driver = { .name = "si2165", }, - .probe_new = si2165_probe, + .probe = si2165_probe, .remove = si2165_remove, .id_table = si2165_id_table, }; diff --git a/drivers/media/dvb-frontends/si2168.c b/drivers/media/dvb-frontends/si2168.c index 2a0e108c5eb0c19604621575f49628dbbb64e106..dae1f2153e8be2b7615ef9cc3f8ed79517174a72 100644 --- a/drivers/media/dvb-frontends/si2168.c +++ b/drivers/media/dvb-frontends/si2168.c @@ -798,7 +798,7 @@ static struct i2c_driver si2168_driver = { .name = "si2168", .suppress_bind_attrs = true, }, - .probe_new = si2168_probe, + .probe = si2168_probe, .remove = si2168_remove, .id_table = si2168_id_table, }; diff --git a/drivers/media/dvb-frontends/sp2.c b/drivers/media/dvb-frontends/sp2.c index 3395f6b5b948edae77a225997a856ff3a8781a3a..4d7d0b8b51b452ea7bcb56b416443e4ddbc547ff 100644 --- a/drivers/media/dvb-frontends/sp2.c +++ b/drivers/media/dvb-frontends/sp2.c @@ -416,7 +416,7 @@ static struct i2c_driver sp2_driver = { .driver = { .name = "sp2", }, - .probe_new = sp2_probe, + .probe = sp2_probe, .remove = sp2_remove, .id_table = sp2_id, }; diff --git a/drivers/media/dvb-frontends/stv090x.c b/drivers/media/dvb-frontends/stv090x.c index 9bde0ad6f26eb36128e555349d925465384e0e7f..a07dc5fdeb3d87312c3b6e1c9fa6f391b3658465 100644 --- a/drivers/media/dvb-frontends/stv090x.c +++ b/drivers/media/dvb-frontends/stv090x.c @@ -5084,7 +5084,7 @@ static struct i2c_driver stv090x_driver = { .name = "stv090x", .suppress_bind_attrs = true, }, - .probe_new = stv090x_probe, + .probe = stv090x_probe, .remove = stv090x_remove, .id_table = stv090x_id_table, }; diff --git a/drivers/media/dvb-frontends/stv6110x.c b/drivers/media/dvb-frontends/stv6110x.c index b2f456116c60fc61d02c6e7319557b5009b17740..11653f846c12381bda376db3d4e978ee40954986 100644 --- a/drivers/media/dvb-frontends/stv6110x.c +++ b/drivers/media/dvb-frontends/stv6110x.c @@ -480,7 +480,7 @@ static struct i2c_driver stv6110x_driver = { .name = "stv6110x", .suppress_bind_attrs = true, }, - .probe_new = stv6110x_probe, + .probe = stv6110x_probe, .remove = stv6110x_remove, .id_table = stv6110x_id_table, }; diff --git a/drivers/media/dvb-frontends/tc90522.c b/drivers/media/dvb-frontends/tc90522.c index 77a991bf47135085ddb0c51074bf20b6c02ef27f..879f028f96828974013ad94a81637a57bcf811a5 100644 --- a/drivers/media/dvb-frontends/tc90522.c +++ b/drivers/media/dvb-frontends/tc90522.c @@ -840,7 +840,7 @@ static struct i2c_driver tc90522_driver = { .driver = { .name = "tc90522", }, - .probe_new = tc90522_probe, + .probe = tc90522_probe, .remove = tc90522_remove, .id_table = tc90522_id, }; diff --git a/drivers/media/dvb-frontends/tda10071.c b/drivers/media/dvb-frontends/tda10071.c index c8e5617d08c0b02a746f1c8a7e8564ac98fd9094..6640851d8bbcaec1ea81d3297d42b1517736bf74 100644 --- a/drivers/media/dvb-frontends/tda10071.c +++ b/drivers/media/dvb-frontends/tda10071.c @@ -1240,7 +1240,7 @@ static struct i2c_driver tda10071_driver = { .name = "tda10071", .suppress_bind_attrs = true, }, - .probe_new = tda10071_probe, + .probe = tda10071_probe, .remove = tda10071_remove, .id_table = tda10071_id_table, }; diff --git a/drivers/media/dvb-frontends/ts2020.c b/drivers/media/dvb-frontends/ts2020.c index c28fee7509cddfc010682a18a2c80bbe6b00572d..f5b60f82769748c889bfebc9aadc86d1016820df 100644 --- a/drivers/media/dvb-frontends/ts2020.c +++ b/drivers/media/dvb-frontends/ts2020.c @@ -720,7 +720,7 @@ static struct i2c_driver ts2020_driver = { .driver = { .name = "ts2020", }, - .probe_new = ts2020_probe, + .probe = ts2020_probe, .remove = ts2020_remove, .id_table = ts2020_id_table, }; diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig index 256d55bb2b1da33070e4c04e44778278bea3b096..226454b6a90dd7a25710ecfe1242d1fa5e818ecf 100644 --- a/drivers/media/i2c/Kconfig +++ b/drivers/media/i2c/Kconfig @@ -338,6 +338,19 @@ config VIDEO_OG01A1B To compile this driver as a module, choose M here: the module will be called og01a1b. +config VIDEO_OV01A10 + tristate "OmniVision OV01A10 sensor support" + depends on VIDEO_DEV && I2C + select MEDIA_CONTROLLER + select VIDEO_V4L2_SUBDEV_API + select V4L2_FWNODE + help + This is a Video4Linux2 sensor driver for the OmniVision + OV01A10 camera. + + To compile this driver as a module, choose M here: the + module will be called ov01a10. + config VIDEO_OV02A10 tristate "OmniVision OV02A10 sensor support" depends on VIDEO_DEV && I2C @@ -1292,6 +1305,7 @@ config VIDEO_TC358746 select VIDEO_V4L2_SUBDEV_API select MEDIA_CONTROLLER select V4L2_FWNODE + select GENERIC_PHY select GENERIC_PHY_MIPI_DPHY select REGMAP_I2C help diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile index b44dacf935f44bfa8147d73c795a6c13a4324b2f..c743aeb5d1ad3c82ce7272b093a926ae25275cac 100644 --- a/drivers/media/i2c/Makefile +++ b/drivers/media/i2c/Makefile @@ -67,6 +67,7 @@ obj-$(CONFIG_VIDEO_MT9V011) += mt9v011.o obj-$(CONFIG_VIDEO_MT9V032) += mt9v032.o obj-$(CONFIG_VIDEO_MT9V111) += mt9v111.o obj-$(CONFIG_VIDEO_OG01A1B) += og01a1b.o +obj-$(CONFIG_VIDEO_OV01A10) += ov01a10.o obj-$(CONFIG_VIDEO_OV02A10) += ov02a10.o obj-$(CONFIG_VIDEO_OV08D10) += ov08d10.o obj-$(CONFIG_VIDEO_OV08X40) += ov08x40.o diff --git a/drivers/media/i2c/ad5820.c b/drivers/media/i2c/ad5820.c index 44c26af49071cfa800403551e689c3b38eeab240..5f605b9be3b15626a4e568717e623bf1d0f69dcc 100644 --- a/drivers/media/i2c/ad5820.c +++ b/drivers/media/i2c/ad5820.c @@ -370,7 +370,7 @@ static struct i2c_driver ad5820_i2c_driver = { .pm = &ad5820_pm, .of_match_table = ad5820_of_table, }, - .probe_new = ad5820_probe, + .probe = ad5820_probe, .remove = ad5820_remove, .id_table = ad5820_id_table, }; diff --git a/drivers/media/i2c/adp1653.c b/drivers/media/i2c/adp1653.c index a61a77de6eee3708a9f402ad0bc4caade352a840..98ca417b8004cfb73df8813df65fe8b324e89da3 100644 --- a/drivers/media/i2c/adp1653.c +++ b/drivers/media/i2c/adp1653.c @@ -535,7 +535,7 @@ static struct i2c_driver adp1653_i2c_driver = { .name = ADP1653_NAME, .pm = &adp1653_pm_ops, }, - .probe_new = adp1653_probe, + .probe = adp1653_probe, .remove = adp1653_remove, .id_table = adp1653_id_table, }; diff --git a/drivers/media/i2c/adv7170.c b/drivers/media/i2c/adv7170.c index aa0f80e299b32c86b2339b41674678d18db40e29..4a2b9fd9e2da16b412a1f2e42ebef120e9229c03 100644 --- a/drivers/media/i2c/adv7170.c +++ b/drivers/media/i2c/adv7170.c @@ -387,7 +387,7 @@ static struct i2c_driver adv7170_driver = { .driver = { .name = "adv7170", }, - .probe_new = adv7170_probe, + .probe = adv7170_probe, .remove = adv7170_remove, .id_table = adv7170_id, }; diff --git a/drivers/media/i2c/adv7175.c b/drivers/media/i2c/adv7175.c index d9bea2b9ec3343bdffe4b750cb3c642e8103c191..e454cba4b026374443cd9e9431b8c1b928948fd7 100644 --- a/drivers/media/i2c/adv7175.c +++ b/drivers/media/i2c/adv7175.c @@ -442,7 +442,7 @@ static struct i2c_driver adv7175_driver = { .driver = { .name = "adv7175", }, - .probe_new = adv7175_probe, + .probe = adv7175_probe, .remove = adv7175_remove, .id_table = adv7175_id, }; diff --git a/drivers/media/i2c/adv7180.c b/drivers/media/i2c/adv7180.c index a22402b7acffca0c827dee679b90ec7b75be0a27..99ba925e8ec8e673138b50a7a7da6070f939b8a1 100644 --- a/drivers/media/i2c/adv7180.c +++ b/drivers/media/i2c/adv7180.c @@ -1610,7 +1610,7 @@ static struct i2c_driver adv7180_driver = { .pm = ADV7180_PM_OPS, .of_match_table = of_match_ptr(adv7180_of_id), }, - .probe_new = adv7180_probe, + .probe = adv7180_probe, .remove = adv7180_remove, .id_table = adv7180_id, }; diff --git a/drivers/media/i2c/adv7183.c b/drivers/media/i2c/adv7183.c index 98b63d79d33d45fa49ccfc072aef3157223134a3..3659feafac69c8f22a0fc9a54c50025d047fc6a6 100644 --- a/drivers/media/i2c/adv7183.c +++ b/drivers/media/i2c/adv7183.c @@ -631,7 +631,7 @@ static struct i2c_driver adv7183_driver = { .driver = { .name = "adv7183", }, - .probe_new = adv7183_probe, + .probe = adv7183_probe, .remove = adv7183_remove, .id_table = adv7183_id, }; diff --git a/drivers/media/i2c/adv7343.c b/drivers/media/i2c/adv7343.c index 7e84869d2434946f82451b57646fc21a2df08bf6..ff21cd4744d3d5b383dabe9e63963a83792750f0 100644 --- a/drivers/media/i2c/adv7343.c +++ b/drivers/media/i2c/adv7343.c @@ -521,7 +521,7 @@ static struct i2c_driver adv7343_driver = { .of_match_table = of_match_ptr(adv7343_of_match), .name = "adv7343", }, - .probe_new = adv7343_probe, + .probe = adv7343_probe, .remove = adv7343_remove, .id_table = adv7343_id, }; diff --git a/drivers/media/i2c/adv7393.c b/drivers/media/i2c/adv7393.c index 61e916cbe65180a41f4f01353dddd33658aa3c40..7638af455cefa1a1c219b78f3ddda21222097e4e 100644 --- a/drivers/media/i2c/adv7393.c +++ b/drivers/media/i2c/adv7393.c @@ -455,7 +455,7 @@ static struct i2c_driver adv7393_driver = { .driver = { .name = "adv7393", }, - .probe_new = adv7393_probe, + .probe = adv7393_probe, .remove = adv7393_remove, .id_table = adv7393_id, }; diff --git a/drivers/media/i2c/adv748x/adv748x-core.c b/drivers/media/i2c/adv748x/adv748x-core.c index 4498d78a235701e176f57a274170bc88d29ab298..3eb6d5e8f0826517d5ccecd450aeb040322d6ec1 100644 --- a/drivers/media/i2c/adv748x/adv748x-core.c +++ b/drivers/media/i2c/adv748x/adv748x-core.c @@ -847,7 +847,7 @@ static struct i2c_driver adv748x_driver = { .of_match_table = adv748x_of_table, .pm = &adv748x_pm_ops, }, - .probe_new = adv748x_probe, + .probe = adv748x_probe, .remove = adv748x_remove, }; diff --git a/drivers/media/i2c/adv7511-v4l2.c b/drivers/media/i2c/adv7511-v4l2.c index 3999fa524cab73d236c6b7557e5af65236eb2b90..a9183d9282fd243388b094def5db574bd7d83895 100644 --- a/drivers/media/i2c/adv7511-v4l2.c +++ b/drivers/media/i2c/adv7511-v4l2.c @@ -1957,7 +1957,7 @@ static struct i2c_driver adv7511_driver = { .driver = { .name = "adv7511-v4l2", }, - .probe_new = adv7511_probe, + .probe = adv7511_probe, .remove = adv7511_remove, .id_table = adv7511_id, }; diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c index 3d0898c4175e0dc20e3952ccd1f8be179fd82b2b..b202a85fbeaa049dceef0342d56ff1873524ebff 100644 --- a/drivers/media/i2c/adv7604.c +++ b/drivers/media/i2c/adv7604.c @@ -3689,7 +3689,7 @@ static struct i2c_driver adv76xx_driver = { .name = "adv7604", .of_match_table = of_match_ptr(adv76xx_of_id), }, - .probe_new = adv76xx_probe, + .probe = adv76xx_probe, .remove = adv76xx_remove, .id_table = adv76xx_i2c_id, }; diff --git a/drivers/media/i2c/adv7842.c b/drivers/media/i2c/adv7842.c index cb86555741190511f1df185e01ce06622e5b25c4..c1664a3620c8edeaa341e25bf7e012125cc8f714 100644 --- a/drivers/media/i2c/adv7842.c +++ b/drivers/media/i2c/adv7842.c @@ -3619,7 +3619,7 @@ static struct i2c_driver adv7842_driver = { .driver = { .name = "adv7842", }, - .probe_new = adv7842_probe, + .probe = adv7842_probe, .remove = adv7842_remove, .id_table = adv7842_id, }; diff --git a/drivers/media/i2c/ak7375.c b/drivers/media/i2c/ak7375.c index e7cec45bc271af28f291e1a27b0a7b4323fda6e0..463b51d46320fa267ce0ed5c51b88e421c651207 100644 --- a/drivers/media/i2c/ak7375.c +++ b/drivers/media/i2c/ak7375.c @@ -306,7 +306,7 @@ static struct i2c_driver ak7375_i2c_driver = { .pm = &ak7375_pm_ops, .of_match_table = ak7375_of_table, }, - .probe_new = ak7375_probe, + .probe = ak7375_probe, .remove = ak7375_remove, }; module_i2c_driver(ak7375_i2c_driver); diff --git a/drivers/media/i2c/ak881x.c b/drivers/media/i2c/ak881x.c index 7c9ab76e244808c868373e9120cc1fa121f12db8..ce840adc2aa7fe42ce7dd3f29d5dbe9c6986b68f 100644 --- a/drivers/media/i2c/ak881x.c +++ b/drivers/media/i2c/ak881x.c @@ -314,7 +314,7 @@ static struct i2c_driver ak881x_i2c_driver = { .driver = { .name = "ak881x", }, - .probe_new = ak881x_probe, + .probe = ak881x_probe, .remove = ak881x_remove, .id_table = ak881x_id, }; diff --git a/drivers/media/i2c/ar0521.c b/drivers/media/i2c/ar0521.c index 77f597571167288ec9dfa091c4554897eeac98d8..a4e39871e8f75c558af3f0e244aee985425102c1 100644 --- a/drivers/media/i2c/ar0521.c +++ b/drivers/media/i2c/ar0521.c @@ -1198,7 +1198,7 @@ static struct i2c_driver ar0521_i2c_driver = { .pm = &ar0521_pm_ops, .of_match_table = ar0521_dt_ids, }, - .probe_new = ar0521_probe, + .probe = ar0521_probe, .remove = ar0521_remove, }; diff --git a/drivers/media/i2c/bt819.c b/drivers/media/i2c/bt819.c index 39f8a53611665e3efc0ee4158ed0bce481a723ee..b4a25cc996dc16196e9ebc4c8958740813e742b9 100644 --- a/drivers/media/i2c/bt819.c +++ b/drivers/media/i2c/bt819.c @@ -468,7 +468,7 @@ static struct i2c_driver bt819_driver = { .driver = { .name = "bt819", }, - .probe_new = bt819_probe, + .probe = bt819_probe, .remove = bt819_remove, .id_table = bt819_id, }; diff --git a/drivers/media/i2c/bt856.c b/drivers/media/i2c/bt856.c index d1d397b15b85c9c83208b0ae476e1d477b29ba4d..814acbd6a5a80aa69f9b00dc1ba2d149b1ba6fa3 100644 --- a/drivers/media/i2c/bt856.c +++ b/drivers/media/i2c/bt856.c @@ -239,7 +239,7 @@ static struct i2c_driver bt856_driver = { .driver = { .name = "bt856", }, - .probe_new = bt856_probe, + .probe = bt856_probe, .remove = bt856_remove, .id_table = bt856_id, }; diff --git a/drivers/media/i2c/bt866.c b/drivers/media/i2c/bt866.c index d632d9a07f0499b46511117dc53eadca3ec938d7..dada059cbce42a309fd76c04cac556f51adff851 100644 --- a/drivers/media/i2c/bt866.c +++ b/drivers/media/i2c/bt866.c @@ -206,7 +206,7 @@ static struct i2c_driver bt866_driver = { .driver = { .name = "bt866", }, - .probe_new = bt866_probe, + .probe = bt866_probe, .remove = bt866_remove, .id_table = bt866_id, }; diff --git a/drivers/media/i2c/ccs/ccs-core.c b/drivers/media/i2c/ccs/ccs-core.c index 559a415fd827f4f99688ca5aaf17341a4542eeb3..49e0d9a0953028b0fdc5b00d8b45d14cff7dfd71 100644 --- a/drivers/media/i2c/ccs/ccs-core.c +++ b/drivers/media/i2c/ccs/ccs-core.c @@ -3731,7 +3731,7 @@ static struct i2c_driver ccs_i2c_driver = { .name = CCS_NAME, .pm = &ccs_pm_ops, }, - .probe_new = ccs_probe, + .probe = ccs_probe, .remove = ccs_remove, }; diff --git a/drivers/media/i2c/cs3308.c b/drivers/media/i2c/cs3308.c index a0b66c04fe252834b57044ae3eb74d100c476820..61afa3d799d2545a6ef88f8076192cd07c95a619 100644 --- a/drivers/media/i2c/cs3308.c +++ b/drivers/media/i2c/cs3308.c @@ -118,7 +118,7 @@ static struct i2c_driver cs3308_driver = { .driver = { .name = "cs3308", }, - .probe_new = cs3308_probe, + .probe = cs3308_probe, .remove = cs3308_remove, .id_table = cs3308_id, }; diff --git a/drivers/media/i2c/cs5345.c b/drivers/media/i2c/cs5345.c index ac4b5632fc46150f3ed2b27c03aac3469864cd94..3019a132e07909c51c1ed7375d6a3ba66a77b14e 100644 --- a/drivers/media/i2c/cs5345.c +++ b/drivers/media/i2c/cs5345.c @@ -198,7 +198,7 @@ static struct i2c_driver cs5345_driver = { .driver = { .name = "cs5345", }, - .probe_new = cs5345_probe, + .probe = cs5345_probe, .remove = cs5345_remove, .id_table = cs5345_id, }; diff --git a/drivers/media/i2c/cs53l32a.c b/drivers/media/i2c/cs53l32a.c index 670f89de32d4ee04de442c2d80436eae3d90c74a..82881b79e7300ac7a99405c150dccfb55973c06c 100644 --- a/drivers/media/i2c/cs53l32a.c +++ b/drivers/media/i2c/cs53l32a.c @@ -209,7 +209,7 @@ static struct i2c_driver cs53l32a_driver = { .driver = { .name = "cs53l32a", }, - .probe_new = cs53l32a_probe, + .probe = cs53l32a_probe, .remove = cs53l32a_remove, .id_table = cs53l32a_id, }; diff --git a/drivers/media/i2c/cx25840/cx25840-core.c b/drivers/media/i2c/cx25840/cx25840-core.c index 46cf422270b2dbebcd2bb18a57f774bae15136c1..5aec252890624044242d9a04bc11e2ad2f041c06 100644 --- a/drivers/media/i2c/cx25840/cx25840-core.c +++ b/drivers/media/i2c/cx25840/cx25840-core.c @@ -6045,7 +6045,7 @@ static struct i2c_driver cx25840_driver = { .driver = { .name = "cx25840", }, - .probe_new = cx25840_probe, + .probe = cx25840_probe, .remove = cx25840_remove, .id_table = cx25840_id, }; diff --git a/drivers/media/i2c/dw9714.c b/drivers/media/i2c/dw9714.c index af59687383aa57ae3ffe08dfdc1d3c8952189aa1..cc09b32ede601d2709a48ac855abfb545a883af2 100644 --- a/drivers/media/i2c/dw9714.c +++ b/drivers/media/i2c/dw9714.c @@ -299,7 +299,7 @@ static struct i2c_driver dw9714_i2c_driver = { .pm = &dw9714_pm_ops, .of_match_table = dw9714_of_table, }, - .probe_new = dw9714_probe, + .probe = dw9714_probe, .remove = dw9714_remove, .id_table = dw9714_id_table, }; diff --git a/drivers/media/i2c/dw9768.c b/drivers/media/i2c/dw9768.c index 83a3ee275bbe874da49791338d8d73749d83d6b2..daabbece8c7e903fc93b6bd2eb7ff46b229d3bf8 100644 --- a/drivers/media/i2c/dw9768.c +++ b/drivers/media/i2c/dw9768.c @@ -549,7 +549,7 @@ static struct i2c_driver dw9768_i2c_driver = { .pm = &dw9768_pm_ops, .of_match_table = dw9768_of_table, }, - .probe_new = dw9768_probe, + .probe = dw9768_probe, .remove = dw9768_remove, }; module_i2c_driver(dw9768_i2c_driver); diff --git a/drivers/media/i2c/dw9807-vcm.c b/drivers/media/i2c/dw9807-vcm.c index 3599720db7e9959cb9cecb65c931b96fa85a62a7..4148009e0e0170caeec6d1b820ef13a09842d7bd 100644 --- a/drivers/media/i2c/dw9807-vcm.c +++ b/drivers/media/i2c/dw9807-vcm.c @@ -310,7 +310,7 @@ static struct i2c_driver dw9807_i2c_driver = { .pm = &dw9807_pm_ops, .of_match_table = dw9807_of_table, }, - .probe_new = dw9807_probe, + .probe = dw9807_probe, .remove = dw9807_remove, }; diff --git a/drivers/media/i2c/et8ek8/et8ek8_driver.c b/drivers/media/i2c/et8ek8/et8ek8_driver.c index ff9bb9fc97dd851e459446d65f7ca5db7dcfa272..d6fc843f9368e51de19b67c334dc4b28828d77dd 100644 --- a/drivers/media/i2c/et8ek8/et8ek8_driver.c +++ b/drivers/media/i2c/et8ek8/et8ek8_driver.c @@ -1501,7 +1501,7 @@ static struct i2c_driver et8ek8_i2c_driver = { .pm = &et8ek8_pm_ops, .of_match_table = et8ek8_of_table, }, - .probe_new = et8ek8_probe, + .probe = et8ek8_probe, .remove = __exit_p(et8ek8_remove), .id_table = et8ek8_id_table, }; diff --git a/drivers/media/i2c/hi556.c b/drivers/media/i2c/hi556.c index 7daefab35cf02e45b5cdb73932a111a3c0262b94..50e78f5b058c23622fe979f713b3c8c7c4466174 100644 --- a/drivers/media/i2c/hi556.c +++ b/drivers/media/i2c/hi556.c @@ -1350,7 +1350,7 @@ static struct i2c_driver hi556_i2c_driver = { .pm = &hi556_pm_ops, .acpi_match_table = ACPI_PTR(hi556_acpi_ids), }, - .probe_new = hi556_probe, + .probe = hi556_probe, .remove = hi556_remove, .flags = I2C_DRV_ACPI_WAIVE_D0_PROBE, }; diff --git a/drivers/media/i2c/hi846.c b/drivers/media/i2c/hi846.c index 306dc35e925fd00ad4943f386e15794e30542564..fa0038749a3b98dca98861a37cf5c8c995d6684e 100644 --- a/drivers/media/i2c/hi846.c +++ b/drivers/media/i2c/hi846.c @@ -1353,7 +1353,8 @@ static int hi846_set_ctrl(struct v4l2_ctrl *ctrl) exposure_max); } - if (!pm_runtime_get_if_in_use(&client->dev)) + ret = pm_runtime_get_if_in_use(&client->dev); + if (!ret || ret == -EAGAIN) return 0; switch (ctrl->id) { @@ -2189,7 +2190,7 @@ static struct i2c_driver hi846_i2c_driver = { .pm = &hi846_pm_ops, .of_match_table = hi846_of_match, }, - .probe_new = hi846_probe, + .probe = hi846_probe, .remove = hi846_remove, }; diff --git a/drivers/media/i2c/hi847.c b/drivers/media/i2c/hi847.c index 5a82b15a9513e1e264e2ecb9d13949fa0680a699..7cdce392e13713766d08984cf61060519de0ea73 100644 --- a/drivers/media/i2c/hi847.c +++ b/drivers/media/i2c/hi847.c @@ -2999,7 +2999,7 @@ static struct i2c_driver hi847_i2c_driver = { .pm = &hi847_pm_ops, .acpi_match_table = ACPI_PTR(hi847_acpi_ids), }, - .probe_new = hi847_probe, + .probe = hi847_probe, .remove = hi847_remove, }; diff --git a/drivers/media/i2c/imx208.c b/drivers/media/i2c/imx208.c index 64c70ebf9869c71e02af65b3f25deb4f0e11fcac..3e870fa9ff793ea7f50c1bf9f06b0ec0491a92e7 100644 --- a/drivers/media/i2c/imx208.c +++ b/drivers/media/i2c/imx208.c @@ -1100,7 +1100,7 @@ static struct i2c_driver imx208_i2c_driver = { .pm = &imx208_pm_ops, .acpi_match_table = ACPI_PTR(imx208_acpi_ids), }, - .probe_new = imx208_probe, + .probe = imx208_probe, .remove = imx208_remove, .flags = I2C_DRV_ACPI_WAIVE_D0_PROBE, }; diff --git a/drivers/media/i2c/imx214.c b/drivers/media/i2c/imx214.c index 710c9fb515fd09ffb14a403539de082b43060cb4..2f9c8582f9401a2564688f88ef45f526c1a2a587 100644 --- a/drivers/media/i2c/imx214.c +++ b/drivers/media/i2c/imx214.c @@ -1112,7 +1112,7 @@ static struct i2c_driver imx214_i2c_driver = { .pm = &imx214_pm_ops, .name = "imx214", }, - .probe_new = imx214_probe, + .probe = imx214_probe, .remove = imx214_remove, }; diff --git a/drivers/media/i2c/imx219.c b/drivers/media/i2c/imx219.c index f9471c9e3a746a2f39c788c28b4eb50048db9b53..d737d5e9a4a67f59b209e52b68aaa28449a78121 100644 --- a/drivers/media/i2c/imx219.c +++ b/drivers/media/i2c/imx219.c @@ -1583,7 +1583,7 @@ static struct i2c_driver imx219_i2c_driver = { .of_match_table = imx219_dt_ids, .pm = &imx219_pm_ops, }, - .probe_new = imx219_probe, + .probe = imx219_probe, .remove = imx219_remove, }; diff --git a/drivers/media/i2c/imx258.c b/drivers/media/i2c/imx258.c index 85d73b1861111c1f67ca7a372ca7441333e7ac25..e196565e846e64c9d22defeee5607c9f61347c0e 100644 --- a/drivers/media/i2c/imx258.c +++ b/drivers/media/i2c/imx258.c @@ -1395,7 +1395,7 @@ static struct i2c_driver imx258_i2c_driver = { .acpi_match_table = ACPI_PTR(imx258_acpi_ids), .of_match_table = imx258_dt_ids, }, - .probe_new = imx258_probe, + .probe = imx258_probe, .remove = imx258_remove, }; diff --git a/drivers/media/i2c/imx274.c b/drivers/media/i2c/imx274.c index 9219f3c9594b0c498f3649aa84759fc17d53159b..f33b692e6951ef64d264fa6d0094a3acfdd11f51 100644 --- a/drivers/media/i2c/imx274.c +++ b/drivers/media/i2c/imx274.c @@ -2168,7 +2168,7 @@ static struct i2c_driver imx274_i2c_driver = { .pm = &imx274_pm_ops, .of_match_table = imx274_of_id_table, }, - .probe_new = imx274_probe, + .probe = imx274_probe, .remove = imx274_remove, .id_table = imx274_id, }; diff --git a/drivers/media/i2c/imx290.c b/drivers/media/i2c/imx290.c index 5ea25b7acc55f04e6069a0767569882ceaf96fb0..b3f832e9d7e1620fe99e61bc7c4398aaad279268 100644 --- a/drivers/media/i2c/imx290.c +++ b/drivers/media/i2c/imx290.c @@ -1716,10 +1716,10 @@ static const struct of_device_id imx290_of_match[] = { MODULE_DEVICE_TABLE(of, imx290_of_match); static struct i2c_driver imx290_i2c_driver = { - .probe_new = imx290_probe, + .probe = imx290_probe, .remove = imx290_remove, .driver = { - .name = "imx290", + .name = "imx290", .pm = pm_ptr(&imx290_pm_ops), .of_match_table = imx290_of_match, }, diff --git a/drivers/media/i2c/imx296.c b/drivers/media/i2c/imx296.c index 4f22c0515ef8dcef6131276c5d888e2488dc793e..c0b9a5349668d032b8202b0c9a874d9c77c002ae 100644 --- a/drivers/media/i2c/imx296.c +++ b/drivers/media/i2c/imx296.c @@ -922,10 +922,12 @@ static int imx296_read_temperature(struct imx296 *sensor, int *temp) if (ret < 0) return ret; - tmdout = imx296_read(sensor, IMX296_TMDOUT) & IMX296_TMDOUT_MASK; + tmdout = imx296_read(sensor, IMX296_TMDOUT); if (tmdout < 0) return tmdout; + tmdout &= IMX296_TMDOUT_MASK; + /* T(°C) = 246.312 - 0.304 * TMDOUT */; *temp = 246312 - 304 * tmdout; @@ -1152,7 +1154,7 @@ static struct i2c_driver imx296_i2c_driver = { .name = "imx296", .pm = &imx296_pm_ops }, - .probe_new = imx296_probe, + .probe = imx296_probe, .remove = imx296_remove, }; diff --git a/drivers/media/i2c/imx319.c b/drivers/media/i2c/imx319.c index 45b1b61b2880d94c23254186b4f111982e7759e3..a2140848d0d657de4d6bb7b557bb6cae747ea664 100644 --- a/drivers/media/i2c/imx319.c +++ b/drivers/media/i2c/imx319.c @@ -2558,7 +2558,7 @@ static struct i2c_driver imx319_i2c_driver = { .pm = &imx319_pm_ops, .acpi_match_table = ACPI_PTR(imx319_acpi_ids), }, - .probe_new = imx319_probe, + .probe = imx319_probe, .remove = imx319_remove, .flags = I2C_DRV_ACPI_WAIVE_D0_PROBE, }; diff --git a/drivers/media/i2c/imx334.c b/drivers/media/i2c/imx334.c index 309c706114d2862dc5844c76e7bc2be30d815ff6..d722c9b7cd31d002349d7189436c57d9a4373eef 100644 --- a/drivers/media/i2c/imx334.c +++ b/drivers/media/i2c/imx334.c @@ -49,7 +49,8 @@ #define IMX334_INCLK_RATE 24000000 /* CSI2 HW configuration */ -#define IMX334_LINK_FREQ 891000000 +#define IMX334_LINK_FREQ_891M 891000000 +#define IMX334_LINK_FREQ_445M 445500000 #define IMX334_NUM_DATA_LANES 4 #define IMX334_REG_MIN 0x00 @@ -117,6 +118,7 @@ struct imx334_mode { * @vblank: Vertical blanking in lines * @cur_mode: Pointer to current selected sensor mode * @mutex: Mutex for serializing sensor controls + * @menu_skip_mask: Menu skip mask for link_freq_ctrl * @cur_code: current selected format code * @streaming: Flag indicating streaming state */ @@ -139,12 +141,14 @@ struct imx334 { u32 vblank; const struct imx334_mode *cur_mode; struct mutex mutex; + unsigned long menu_skip_mask; u32 cur_code; bool streaming; }; static const s64 link_freq[] = { - IMX334_LINK_FREQ, + IMX334_LINK_FREQ_891M, + IMX334_LINK_FREQ_445M, }; /* Sensor mode registers for 1920x1080@30fps */ @@ -468,7 +472,7 @@ static const struct imx334_mode supported_modes[] = { .vblank_min = 45, .vblank_max = 132840, .pclk = 297000000, - .link_freq_idx = 0, + .link_freq_idx = 1, .reg_list = { .num_of_regs = ARRAY_SIZE(mode_1920x1080_regs), .regs = mode_1920x1080_regs, @@ -598,13 +602,22 @@ static int imx334_update_controls(struct imx334 *imx334, if (ret) return ret; + ret = __v4l2_ctrl_modify_range(imx334->pclk_ctrl, mode->pclk, + mode->pclk, 1, mode->pclk); + if (ret) + return ret; + ret = __v4l2_ctrl_modify_range(imx334->hblank_ctrl, mode->hblank, mode->hblank, 1, mode->hblank); if (ret) return ret; - return __v4l2_ctrl_modify_range(imx334->vblank_ctrl, mode->vblank_min, + ret = __v4l2_ctrl_modify_range(imx334->vblank_ctrl, mode->vblank_min, mode->vblank_max, 1, mode->vblank); + if (ret) + return ret; + + return __v4l2_ctrl_s_ctrl(imx334->vblank_ctrl, mode->vblank); } /** @@ -698,6 +711,8 @@ static int imx334_set_ctrl(struct v4l2_ctrl *ctrl) pm_runtime_put(imx334->dev); break; + case V4L2_CID_PIXEL_RATE: + case V4L2_CID_LINK_FREQ: case V4L2_CID_HBLANK: ret = 0; break; @@ -885,7 +900,17 @@ static int imx334_init_pad_cfg(struct v4l2_subdev *sd, struct v4l2_subdev_format fmt = { 0 }; fmt.which = sd_state ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE; - imx334_fill_pad_format(imx334, &supported_modes[0], &fmt); + + mutex_lock(&imx334->mutex); + + imx334_fill_pad_format(imx334, imx334->cur_mode, &fmt); + + __v4l2_ctrl_modify_range(imx334->link_freq_ctrl, 0, + __fls(imx334->menu_skip_mask), + ~(imx334->menu_skip_mask), + __ffs(imx334->menu_skip_mask)); + + mutex_unlock(&imx334->mutex); return imx334_set_pad_format(sd, sd_state, &fmt); } @@ -1046,8 +1071,8 @@ static int imx334_parse_hw_config(struct imx334 *imx334) }; struct fwnode_handle *ep; unsigned long rate; + unsigned int i, j; int ret; - int i; if (!fwnode) return -ENXIO; @@ -1097,11 +1122,20 @@ static int imx334_parse_hw_config(struct imx334 *imx334) goto done_endpoint_free; } - for (i = 0; i < bus_cfg.nr_of_link_frequencies; i++) - if (bus_cfg.link_frequencies[i] == IMX334_LINK_FREQ) + for (i = 0; i < bus_cfg.nr_of_link_frequencies; i++) { + for (j = 0; j < ARRAY_SIZE(link_freq); j++) { + if (bus_cfg.link_frequencies[i] == link_freq[j]) { + set_bit(j, &imx334->menu_skip_mask); + break; + } + } + + if (j == ARRAY_SIZE(link_freq)) { + ret = dev_err_probe(imx334->dev, -EINVAL, + "no supported link freq found\n"); goto done_endpoint_free; - - ret = -EINVAL; + } + } done_endpoint_free: v4l2_fwnode_endpoint_free(&bus_cfg); @@ -1232,10 +1266,10 @@ static int imx334_init_controls(struct imx334 *imx334) imx334->link_freq_ctrl = v4l2_ctrl_new_int_menu(ctrl_hdlr, &imx334_ctrl_ops, V4L2_CID_LINK_FREQ, - ARRAY_SIZE(link_freq) - - 1, - mode->link_freq_idx, + __fls(imx334->menu_skip_mask), + __ffs(imx334->menu_skip_mask), link_freq); + if (imx334->link_freq_ctrl) imx334->link_freq_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; @@ -1302,7 +1336,7 @@ static int imx334_probe(struct i2c_client *client) } /* Set default mode to max resolution */ - imx334->cur_mode = &supported_modes[0]; + imx334->cur_mode = &supported_modes[__ffs(imx334->menu_skip_mask)]; imx334->cur_code = imx334_mbus_codes[0]; imx334->vblank = imx334->cur_mode->vblank; @@ -1382,7 +1416,7 @@ static const struct of_device_id imx334_of_match[] = { MODULE_DEVICE_TABLE(of, imx334_of_match); static struct i2c_driver imx334_driver = { - .probe_new = imx334_probe, + .probe = imx334_probe, .remove = imx334_remove, .driver = { .name = "imx334", diff --git a/drivers/media/i2c/imx335.c b/drivers/media/i2c/imx335.c index 078ede2b7a00fdb9886c2742257258ca9f0419d1..482a0b7f040a546d5fc625dab0763bb46c848877 100644 --- a/drivers/media/i2c/imx335.c +++ b/drivers/media/i2c/imx335.c @@ -1112,7 +1112,7 @@ static const struct of_device_id imx335_of_match[] = { MODULE_DEVICE_TABLE(of, imx335_of_match); static struct i2c_driver imx335_driver = { - .probe_new = imx335_probe, + .probe = imx335_probe, .remove = imx335_remove, .driver = { .name = "imx335", diff --git a/drivers/media/i2c/imx355.c b/drivers/media/i2c/imx355.c index 25d4dbb6041eaa1c785371ca608fd6829b2521db..6571a98b1e9eb3d750621c51965b822e10aef80e 100644 --- a/drivers/media/i2c/imx355.c +++ b/drivers/media/i2c/imx355.c @@ -1845,7 +1845,7 @@ static struct i2c_driver imx355_i2c_driver = { .pm = &imx355_pm_ops, .acpi_match_table = ACPI_PTR(imx355_acpi_ids), }, - .probe_new = imx355_probe, + .probe = imx355_probe, .remove = imx355_remove, }; module_i2c_driver(imx355_i2c_driver); diff --git a/drivers/media/i2c/imx412.c b/drivers/media/i2c/imx412.c index e1e986dc8856ee5df19a53ae6d3cb8a73fb30044..c7e862ae4040f58214de303e1373e1f63ed18b7f 100644 --- a/drivers/media/i2c/imx412.c +++ b/drivers/media/i2c/imx412.c @@ -1293,7 +1293,7 @@ static const struct of_device_id imx412_of_match[] = { MODULE_DEVICE_TABLE(of, imx412_of_match); static struct i2c_driver imx412_driver = { - .probe_new = imx412_probe, + .probe = imx412_probe, .remove = imx412_remove, .driver = { .name = "imx412", diff --git a/drivers/media/i2c/imx415.c b/drivers/media/i2c/imx415.c index d90392df98c715705a788d4cac87aa5ef6e4e9ba..4b5d1ee9cc6bf5c21411fbf17883204b74a89cca 100644 --- a/drivers/media/i2c/imx415.c +++ b/drivers/media/i2c/imx415.c @@ -1283,7 +1283,7 @@ static const struct of_device_id imx415_of_match[] = { MODULE_DEVICE_TABLE(of, imx415_of_match); static struct i2c_driver imx415_driver = { - .probe_new = imx415_probe, + .probe = imx415_probe, .remove = imx415_remove, .driver = { .name = "imx415", diff --git a/drivers/media/i2c/ir-kbd-i2c.c b/drivers/media/i2c/ir-kbd-i2c.c index 51921068931db09b643f6f62280a8d9c128d8de2..b37a2aaf8ac0478ba76503386ad3fc3b038f2a33 100644 --- a/drivers/media/i2c/ir-kbd-i2c.c +++ b/drivers/media/i2c/ir-kbd-i2c.c @@ -988,7 +988,7 @@ static struct i2c_driver ir_kbd_driver = { .driver = { .name = "ir-kbd-i2c", }, - .probe_new = ir_probe, + .probe = ir_probe, .remove = ir_remove, .id_table = ir_kbd_id, }; diff --git a/drivers/media/i2c/isl7998x.c b/drivers/media/i2c/isl7998x.c index ae7af2cc94f558d35f55daca99628720a12708e1..92e49d95363de7d39bf587f3441be816e0e553fe 100644 --- a/drivers/media/i2c/isl7998x.c +++ b/drivers/media/i2c/isl7998x.c @@ -1614,7 +1614,7 @@ static struct i2c_driver isl7998x_i2c_driver = { .of_match_table = of_match_ptr(isl7998x_of_match), .pm = &isl7998x_pm_ops, }, - .probe_new = isl7998x_probe, + .probe = isl7998x_probe, .remove = isl7998x_remove, .id_table = isl7998x_id, }; diff --git a/drivers/media/i2c/ks0127.c b/drivers/media/i2c/ks0127.c index 0d86f2db7ad207a022b65807a487d82a72796077..5c583f57e3f37c5c731577ce5b8a3cac2ccb4d3a 100644 --- a/drivers/media/i2c/ks0127.c +++ b/drivers/media/i2c/ks0127.c @@ -696,7 +696,7 @@ static struct i2c_driver ks0127_driver = { .driver = { .name = "ks0127", }, - .probe_new = ks0127_probe, + .probe = ks0127_probe, .remove = ks0127_remove, .id_table = ks0127_id, }; diff --git a/drivers/media/i2c/lm3560.c b/drivers/media/i2c/lm3560.c index 5ef613604be700c99234bb48b279601504ccfd29..05283ac68f2d8edd9585a205d675de9b3835dd2f 100644 --- a/drivers/media/i2c/lm3560.c +++ b/drivers/media/i2c/lm3560.c @@ -467,7 +467,7 @@ static struct i2c_driver lm3560_i2c_driver = { .name = LM3560_NAME, .pm = NULL, }, - .probe_new = lm3560_probe, + .probe = lm3560_probe, .remove = lm3560_remove, .id_table = lm3560_id_table, }; diff --git a/drivers/media/i2c/lm3646.c b/drivers/media/i2c/lm3646.c index 2a0cf74d2bed6ae68ed7786d33af46b8b8cb7ed6..fab3a7e05f922a25827097d54c9e45cfa4576c3b 100644 --- a/drivers/media/i2c/lm3646.c +++ b/drivers/media/i2c/lm3646.c @@ -396,7 +396,7 @@ static struct i2c_driver lm3646_i2c_driver = { .driver = { .name = LM3646_NAME, }, - .probe_new = lm3646_probe, + .probe = lm3646_probe, .remove = lm3646_remove, .id_table = lm3646_id_table, }; diff --git a/drivers/media/i2c/m52790.c b/drivers/media/i2c/m52790.c index 0e6507ab7e083b37822dcdaba284703d7b00d5ba..f8a69142aae9682e19f93b53d73dd5b078a00f3a 100644 --- a/drivers/media/i2c/m52790.c +++ b/drivers/media/i2c/m52790.c @@ -172,7 +172,7 @@ static struct i2c_driver m52790_driver = { .driver = { .name = "m52790", }, - .probe_new = m52790_probe, + .probe = m52790_probe, .remove = m52790_remove, .id_table = m52790_id, }; diff --git a/drivers/media/i2c/max2175.c b/drivers/media/i2c/max2175.c index 1019020f3a37b12ecfbb597a29d1623aec704788..70c2a2948fd4ea2ef2e5be0b0fa1d0c24b8d2986 100644 --- a/drivers/media/i2c/max2175.c +++ b/drivers/media/i2c/max2175.c @@ -1429,7 +1429,7 @@ static struct i2c_driver max2175_driver = { .name = DRIVER_NAME, .of_match_table = max2175_of_ids, }, - .probe_new = max2175_probe, + .probe = max2175_probe, .remove = max2175_remove, .id_table = max2175_id, }; diff --git a/drivers/media/i2c/max9286.c b/drivers/media/i2c/max9286.c index 13a986b885889faf0c3481e03539503fca3ad418..88c58e0c49aab161b8afa2a1e35cdce8b15ae467 100644 --- a/drivers/media/i2c/max9286.c +++ b/drivers/media/i2c/max9286.c @@ -1716,7 +1716,7 @@ static struct i2c_driver max9286_i2c_driver = { .name = "max9286", .of_match_table = of_match_ptr(max9286_dt_ids), }, - .probe_new = max9286_probe, + .probe = max9286_probe, .remove = max9286_remove, }; diff --git a/drivers/media/i2c/ml86v7667.c b/drivers/media/i2c/ml86v7667.c index dbd2f0bd3651875cde030bb6c68cffb537f13f24..5b72d443422467329ad29a53d6e8206134f94222 100644 --- a/drivers/media/i2c/ml86v7667.c +++ b/drivers/media/i2c/ml86v7667.c @@ -433,7 +433,7 @@ static struct i2c_driver ml86v7667_i2c_driver = { .driver = { .name = DRV_NAME, }, - .probe_new = ml86v7667_probe, + .probe = ml86v7667_probe, .remove = ml86v7667_remove, .id_table = ml86v7667_id, }; diff --git a/drivers/media/i2c/msp3400-driver.c b/drivers/media/i2c/msp3400-driver.c index 12032e28b428800e06d751e9b2cff6857f990004..bec76801487abf563086a3ba19de455381794dbc 100644 --- a/drivers/media/i2c/msp3400-driver.c +++ b/drivers/media/i2c/msp3400-driver.c @@ -892,7 +892,7 @@ static struct i2c_driver msp_driver = { .name = "msp3400", .pm = &msp3400_pm_ops, }, - .probe_new = msp_probe, + .probe = msp_probe, .remove = msp_remove, .id_table = msp_id, }; diff --git a/drivers/media/i2c/mt9m001.c b/drivers/media/i2c/mt9m001.c index ebf9cf1e1bce1bfb400e78cb5238201cf1640194..ce9568e8391cddf8eef06afb14f77dd3dcd7db6d 100644 --- a/drivers/media/i2c/mt9m001.c +++ b/drivers/media/i2c/mt9m001.c @@ -877,7 +877,7 @@ static struct i2c_driver mt9m001_i2c_driver = { .pm = &mt9m001_pm_ops, .of_match_table = mt9m001_of_match, }, - .probe_new = mt9m001_probe, + .probe = mt9m001_probe, .remove = mt9m001_remove, .id_table = mt9m001_id, }; diff --git a/drivers/media/i2c/mt9m111.c b/drivers/media/i2c/mt9m111.c index f5fe272d12055d870e4229e3e36243e12ff94ffd..2878d328fc018da997f68b727c6edb173f622e79 100644 --- a/drivers/media/i2c/mt9m111.c +++ b/drivers/media/i2c/mt9m111.c @@ -1384,7 +1384,7 @@ static struct i2c_driver mt9m111_i2c_driver = { .name = "mt9m111", .of_match_table = of_match_ptr(mt9m111_of_match), }, - .probe_new = mt9m111_probe, + .probe = mt9m111_probe, .remove = mt9m111_remove, .id_table = mt9m111_id, }; diff --git a/drivers/media/i2c/mt9p031.c b/drivers/media/i2c/mt9p031.c index 9e023a4b9bd10736b7bbf90cfdd0ab1c85bdae39..348f1e1098fb87542300a728bd0a79dfac42da38 100644 --- a/drivers/media/i2c/mt9p031.c +++ b/drivers/media/i2c/mt9p031.c @@ -1248,7 +1248,7 @@ static struct i2c_driver mt9p031_i2c_driver = { .of_match_table = of_match_ptr(mt9p031_of_match), .name = "mt9p031", }, - .probe_new = mt9p031_probe, + .probe = mt9p031_probe, .remove = mt9p031_remove, .id_table = mt9p031_id, }; diff --git a/drivers/media/i2c/mt9t112.c b/drivers/media/i2c/mt9t112.c index a82f056787b895487739281c46729676d2ed79bd..93f34b767027afbd9c15c11515f4d8023a3b33e6 100644 --- a/drivers/media/i2c/mt9t112.c +++ b/drivers/media/i2c/mt9t112.c @@ -1119,7 +1119,7 @@ static struct i2c_driver mt9t112_i2c_driver = { .driver = { .name = "mt9t112", }, - .probe_new = mt9t112_probe, + .probe = mt9t112_probe, .remove = mt9t112_remove, .id_table = mt9t112_id, }; diff --git a/drivers/media/i2c/mt9v011.c b/drivers/media/i2c/mt9v011.c index c54c7fbf0963753dd70fedcde3a07fc16d1980dd..774861ba7747d5a7cdd32a7fa119acba290272d1 100644 --- a/drivers/media/i2c/mt9v011.c +++ b/drivers/media/i2c/mt9v011.c @@ -585,7 +585,7 @@ static struct i2c_driver mt9v011_driver = { .driver = { .name = "mt9v011", }, - .probe_new = mt9v011_probe, + .probe = mt9v011_probe, .remove = mt9v011_remove, .id_table = mt9v011_id, }; diff --git a/drivers/media/i2c/mt9v032.c b/drivers/media/i2c/mt9v032.c index 7cfd4ebdd2e675e388b88d36751ae9baa97b70f2..00e7bc6e3235c669647ea912f076bf1a8f31a19e 100644 --- a/drivers/media/i2c/mt9v032.c +++ b/drivers/media/i2c/mt9v032.c @@ -1296,7 +1296,7 @@ static struct i2c_driver mt9v032_driver = { .name = "mt9v032", .of_match_table = of_match_ptr(mt9v032_of_match), }, - .probe_new = mt9v032_probe, + .probe = mt9v032_probe, .remove = mt9v032_remove, .id_table = mt9v032_id, }; diff --git a/drivers/media/i2c/mt9v111.c b/drivers/media/i2c/mt9v111.c index 46d91cd0870cdf8706ba86e46d48d6fa302631f5..1f7edc0f5b1abe542ab26024e081521c8b169d67 100644 --- a/drivers/media/i2c/mt9v111.c +++ b/drivers/media/i2c/mt9v111.c @@ -1265,7 +1265,7 @@ static struct i2c_driver mt9v111_driver = { .name = "mt9v111", .of_match_table = mt9v111_of_match, }, - .probe_new = mt9v111_probe, + .probe = mt9v111_probe, .remove = mt9v111_remove, }; diff --git a/drivers/media/i2c/og01a1b.c b/drivers/media/i2c/og01a1b.c index 35663c10fcd9f8ebfd0071b921e49347bcb8f1f9..b5948759342e9e8a975d2655e5f65715cfc0c724 100644 --- a/drivers/media/i2c/og01a1b.c +++ b/drivers/media/i2c/og01a1b.c @@ -1115,7 +1115,7 @@ static struct i2c_driver og01a1b_i2c_driver = { .pm = &og01a1b_pm_ops, .acpi_match_table = ACPI_PTR(og01a1b_acpi_ids), }, - .probe_new = og01a1b_probe, + .probe = og01a1b_probe, .remove = og01a1b_remove, }; diff --git a/drivers/media/i2c/ov01a10.c b/drivers/media/i2c/ov01a10.c new file mode 100644 index 0000000000000000000000000000000000000000..de5bc19e715b1c8ee5709b7a30a66a3474709c24 --- /dev/null +++ b/drivers/media/i2c/ov01a10.c @@ -0,0 +1,1004 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2023 Intel Corporation. + */ + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#define OV01A10_LINK_FREQ_400MHZ 400000000ULL +#define OV01A10_SCLK 40000000LL +#define OV01A10_DATA_LANES 1 + +#define OV01A10_REG_CHIP_ID 0x300a +#define OV01A10_CHIP_ID 0x560141 + +#define OV01A10_REG_MODE_SELECT 0x0100 +#define OV01A10_MODE_STANDBY 0x00 +#define OV01A10_MODE_STREAMING 0x01 + +/* pixel array */ +#define OV01A10_PIXEL_ARRAY_WIDTH 1296 +#define OV01A10_PIXEL_ARRAY_HEIGHT 816 +#define OV01A10_ACITVE_WIDTH 1280 +#define OV01A10_ACITVE_HEIGHT 800 + +/* vertical and horizontal timings */ +#define OV01A10_REG_VTS 0x380e +#define OV01A10_VTS_DEF 0x0380 +#define OV01A10_VTS_MIN 0x0380 +#define OV01A10_VTS_MAX 0xffff +#define OV01A10_HTS_DEF 1488 + +/* exposure controls */ +#define OV01A10_REG_EXPOSURE 0x3501 +#define OV01A10_EXPOSURE_MIN 4 +#define OV01A10_EXPOSURE_MAX_MARGIN 8 +#define OV01A10_EXPOSURE_STEP 1 + +/* analog gain controls */ +#define OV01A10_REG_ANALOG_GAIN 0x3508 +#define OV01A10_ANAL_GAIN_MIN 0x100 +#define OV01A10_ANAL_GAIN_MAX 0xffff +#define OV01A10_ANAL_GAIN_STEP 1 + +/* digital gain controls */ +#define OV01A10_REG_DIGITAL_GAIN_B 0x350a +#define OV01A10_REG_DIGITAL_GAIN_GB 0x3510 +#define OV01A10_REG_DIGITAL_GAIN_GR 0x3513 +#define OV01A10_REG_DIGITAL_GAIN_R 0x3516 +#define OV01A10_DGTL_GAIN_MIN 0 +#define OV01A10_DGTL_GAIN_MAX 0x3ffff +#define OV01A10_DGTL_GAIN_STEP 1 +#define OV01A10_DGTL_GAIN_DEFAULT 1024 + +/* test pattern control */ +#define OV01A10_REG_TEST_PATTERN 0x4503 +#define OV01A10_TEST_PATTERN_ENABLE BIT(7) +#define OV01A10_LINK_FREQ_400MHZ_INDEX 0 + +/* flip and mirror control */ +#define OV01A10_REG_FORMAT1 0x3820 +#define OV01A10_VFLIP_MASK BIT(4) +#define OV01A10_HFLIP_MASK BIT(3) + +/* window offset */ +#define OV01A10_REG_X_WIN 0x3811 +#define OV01A10_REG_Y_WIN 0x3813 + +struct ov01a10_reg { + u16 address; + u8 val; +}; + +struct ov01a10_reg_list { + u32 num_of_regs; + const struct ov01a10_reg *regs; +}; + +struct ov01a10_link_freq_config { + const struct ov01a10_reg_list reg_list; +}; + +struct ov01a10_mode { + u32 width; + u32 height; + u32 hts; + u32 vts_def; + u32 vts_min; + u32 link_freq_index; + + const struct ov01a10_reg_list reg_list; +}; + +static const struct ov01a10_reg mipi_data_rate_720mbps[] = { + {0x0103, 0x01}, + {0x0302, 0x00}, + {0x0303, 0x06}, + {0x0304, 0x01}, + {0x0305, 0xe0}, + {0x0306, 0x00}, + {0x0308, 0x01}, + {0x0309, 0x00}, + {0x030c, 0x01}, + {0x0322, 0x01}, + {0x0323, 0x06}, + {0x0324, 0x01}, + {0x0325, 0x68}, +}; + +static const struct ov01a10_reg sensor_1280x800_setting[] = { + {0x3002, 0xa1}, + {0x301e, 0xf0}, + {0x3022, 0x01}, + {0x3501, 0x03}, + {0x3502, 0x78}, + {0x3504, 0x0c}, + {0x3508, 0x01}, + {0x3509, 0x00}, + {0x3601, 0xc0}, + {0x3603, 0x71}, + {0x3610, 0x68}, + {0x3611, 0x86}, + {0x3640, 0x10}, + {0x3641, 0x80}, + {0x3642, 0xdc}, + {0x3646, 0x55}, + {0x3647, 0x57}, + {0x364b, 0x00}, + {0x3653, 0x10}, + {0x3655, 0x00}, + {0x3656, 0x00}, + {0x365f, 0x0f}, + {0x3661, 0x45}, + {0x3662, 0x24}, + {0x3663, 0x11}, + {0x3664, 0x07}, + {0x3709, 0x34}, + {0x370b, 0x6f}, + {0x3714, 0x22}, + {0x371b, 0x27}, + {0x371c, 0x67}, + {0x371d, 0xa7}, + {0x371e, 0xe7}, + {0x3730, 0x81}, + {0x3733, 0x10}, + {0x3734, 0x40}, + {0x3737, 0x04}, + {0x3739, 0x1c}, + {0x3767, 0x00}, + {0x376c, 0x81}, + {0x3772, 0x14}, + {0x37c2, 0x04}, + {0x37d8, 0x03}, + {0x37d9, 0x0c}, + {0x37e0, 0x00}, + {0x37e1, 0x08}, + {0x37e2, 0x10}, + {0x37e3, 0x04}, + {0x37e4, 0x04}, + {0x37e5, 0x03}, + {0x37e6, 0x04}, + {0x3800, 0x00}, + {0x3801, 0x00}, + {0x3802, 0x00}, + {0x3803, 0x00}, + {0x3804, 0x05}, + {0x3805, 0x0f}, + {0x3806, 0x03}, + {0x3807, 0x2f}, + {0x3808, 0x05}, + {0x3809, 0x00}, + {0x380a, 0x03}, + {0x380b, 0x20}, + {0x380c, 0x02}, + {0x380d, 0xe8}, + {0x380e, 0x03}, + {0x380f, 0x80}, + {0x3810, 0x00}, + {0x3811, 0x08}, + {0x3812, 0x00}, + {0x3813, 0x08}, + {0x3814, 0x01}, + {0x3815, 0x01}, + {0x3816, 0x01}, + {0x3817, 0x01}, + {0x3820, 0xa0}, + {0x3822, 0x13}, + {0x3832, 0x28}, + {0x3833, 0x10}, + {0x3b00, 0x00}, + {0x3c80, 0x00}, + {0x3c88, 0x02}, + {0x3c8c, 0x07}, + {0x3c8d, 0x40}, + {0x3cc7, 0x80}, + {0x4000, 0xc3}, + {0x4001, 0xe0}, + {0x4003, 0x40}, + {0x4008, 0x02}, + {0x4009, 0x19}, + {0x400a, 0x01}, + {0x400b, 0x6c}, + {0x4011, 0x00}, + {0x4041, 0x00}, + {0x4300, 0xff}, + {0x4301, 0x00}, + {0x4302, 0x0f}, + {0x4503, 0x00}, + {0x4601, 0x50}, + {0x4800, 0x64}, + {0x481f, 0x34}, + {0x4825, 0x33}, + {0x4837, 0x11}, + {0x4881, 0x40}, + {0x4883, 0x01}, + {0x4890, 0x00}, + {0x4901, 0x00}, + {0x4902, 0x00}, + {0x4b00, 0x2a}, + {0x4b0d, 0x00}, + {0x450a, 0x04}, + {0x450b, 0x00}, + {0x5000, 0x65}, + {0x5200, 0x18}, + {0x5004, 0x00}, + {0x5080, 0x40}, + {0x0305, 0xf4}, + {0x0325, 0xc2}, +}; + +static const char * const ov01a10_test_pattern_menu[] = { + "Disabled", + "Color Bar", + "Top-Bottom Darker Color Bar", + "Right-Left Darker Color Bar", + "Color Bar type 4", +}; + +static const s64 link_freq_menu_items[] = { + OV01A10_LINK_FREQ_400MHZ, +}; + +static const struct ov01a10_link_freq_config link_freq_configs[] = { + [OV01A10_LINK_FREQ_400MHZ_INDEX] = { + .reg_list = { + .num_of_regs = ARRAY_SIZE(mipi_data_rate_720mbps), + .regs = mipi_data_rate_720mbps, + } + }, +}; + +static const struct ov01a10_mode supported_modes[] = { + { + .width = OV01A10_ACITVE_WIDTH, + .height = OV01A10_ACITVE_HEIGHT, + .hts = OV01A10_HTS_DEF, + .vts_def = OV01A10_VTS_DEF, + .vts_min = OV01A10_VTS_MIN, + .reg_list = { + .num_of_regs = ARRAY_SIZE(sensor_1280x800_setting), + .regs = sensor_1280x800_setting, + }, + .link_freq_index = OV01A10_LINK_FREQ_400MHZ_INDEX, + }, +}; + +struct ov01a10 { + struct v4l2_subdev sd; + struct media_pad pad; + struct v4l2_ctrl_handler ctrl_handler; + + /* v4l2 controls */ + struct v4l2_ctrl *link_freq; + struct v4l2_ctrl *pixel_rate; + struct v4l2_ctrl *vblank; + struct v4l2_ctrl *hblank; + struct v4l2_ctrl *exposure; + + const struct ov01a10_mode *cur_mode; + + /* streaming state */ + bool streaming; +}; + +static inline struct ov01a10 *to_ov01a10(struct v4l2_subdev *subdev) +{ + return container_of(subdev, struct ov01a10, sd); +} + +static int ov01a10_read_reg(struct ov01a10 *ov01a10, u16 reg, u16 len, u32 *val) +{ + struct i2c_client *client = v4l2_get_subdevdata(&ov01a10->sd); + struct i2c_msg msgs[2]; + u8 addr_buf[2]; + u8 data_buf[4] = {0}; + int ret = 0; + + if (len > sizeof(data_buf)) + return -EINVAL; + + put_unaligned_be16(reg, addr_buf); + msgs[0].addr = client->addr; + msgs[0].flags = 0; + msgs[0].len = sizeof(addr_buf); + msgs[0].buf = addr_buf; + msgs[1].addr = client->addr; + msgs[1].flags = I2C_M_RD; + msgs[1].len = len; + msgs[1].buf = &data_buf[sizeof(data_buf) - len]; + + ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); + + if (ret != ARRAY_SIZE(msgs)) + return ret < 0 ? ret : -EIO; + + *val = get_unaligned_be32(data_buf); + + return 0; +} + +static int ov01a10_write_reg(struct ov01a10 *ov01a10, u16 reg, u16 len, u32 val) +{ + struct i2c_client *client = v4l2_get_subdevdata(&ov01a10->sd); + u8 buf[6]; + int ret = 0; + + if (len > 4) + return -EINVAL; + + put_unaligned_be16(reg, buf); + put_unaligned_be32(val << 8 * (4 - len), buf + 2); + + ret = i2c_master_send(client, buf, len + 2); + if (ret != len + 2) + return ret < 0 ? ret : -EIO; + + return 0; +} + +static int ov01a10_write_reg_list(struct ov01a10 *ov01a10, + const struct ov01a10_reg_list *r_list) +{ + struct i2c_client *client = v4l2_get_subdevdata(&ov01a10->sd); + unsigned int i; + int ret = 0; + + for (i = 0; i < r_list->num_of_regs; i++) { + ret = ov01a10_write_reg(ov01a10, r_list->regs[i].address, 1, + r_list->regs[i].val); + if (ret) { + dev_err_ratelimited(&client->dev, + "write reg 0x%4.4x err = %d\n", + r_list->regs[i].address, ret); + return ret; + } + } + + return 0; +} + +static int ov01a10_update_digital_gain(struct ov01a10 *ov01a10, u32 d_gain) +{ + struct i2c_client *client = v4l2_get_subdevdata(&ov01a10->sd); + u32 real = d_gain << 6; + int ret = 0; + + ret = ov01a10_write_reg(ov01a10, OV01A10_REG_DIGITAL_GAIN_B, 3, real); + if (ret) { + dev_err(&client->dev, "failed to set DIGITAL_GAIN_B\n"); + return ret; + } + + ret = ov01a10_write_reg(ov01a10, OV01A10_REG_DIGITAL_GAIN_GB, 3, real); + if (ret) { + dev_err(&client->dev, "failed to set DIGITAL_GAIN_GB\n"); + return ret; + } + + ret = ov01a10_write_reg(ov01a10, OV01A10_REG_DIGITAL_GAIN_GR, 3, real); + if (ret) { + dev_err(&client->dev, "failed to set DIGITAL_GAIN_GR\n"); + return ret; + } + + ret = ov01a10_write_reg(ov01a10, OV01A10_REG_DIGITAL_GAIN_R, 3, real); + if (ret) + dev_err(&client->dev, "failed to set DIGITAL_GAIN_R\n"); + + return ret; +} + +static int ov01a10_test_pattern(struct ov01a10 *ov01a10, u32 pattern) +{ + if (!pattern) + return 0; + + pattern = (pattern - 1) | OV01A10_TEST_PATTERN_ENABLE; + + return ov01a10_write_reg(ov01a10, OV01A10_REG_TEST_PATTERN, 1, pattern); +} + +/* for vflip and hflip, use 0x9 as window offset to keep the bayer */ +static int ov01a10_set_hflip(struct ov01a10 *ov01a10, u32 hflip) +{ + int ret; + u32 val, offset; + + offset = hflip ? 0x9 : 0x8; + ret = ov01a10_write_reg(ov01a10, OV01A10_REG_X_WIN, 1, offset); + if (ret) + return ret; + + ret = ov01a10_read_reg(ov01a10, OV01A10_REG_FORMAT1, 1, &val); + if (ret) + return ret; + + val = hflip ? val | FIELD_PREP(OV01A10_HFLIP_MASK, 0x1) : + val & ~OV01A10_HFLIP_MASK; + + return ov01a10_write_reg(ov01a10, OV01A10_REG_FORMAT1, 1, val); +} + +static int ov01a10_set_vflip(struct ov01a10 *ov01a10, u32 vflip) +{ + int ret; + u32 val, offset; + + offset = vflip ? 0x9 : 0x8; + ret = ov01a10_write_reg(ov01a10, OV01A10_REG_Y_WIN, 1, offset); + if (ret) + return ret; + + ret = ov01a10_read_reg(ov01a10, OV01A10_REG_FORMAT1, 1, &val); + if (ret) + return ret; + + val = vflip ? val | FIELD_PREP(OV01A10_VFLIP_MASK, 0x1) : + val & ~OV01A10_VFLIP_MASK; + + return ov01a10_write_reg(ov01a10, OV01A10_REG_FORMAT1, 1, val); +} + +static int ov01a10_set_ctrl(struct v4l2_ctrl *ctrl) +{ + struct ov01a10 *ov01a10 = container_of(ctrl->handler, + struct ov01a10, ctrl_handler); + struct i2c_client *client = v4l2_get_subdevdata(&ov01a10->sd); + s64 exposure_max; + int ret = 0; + + if (ctrl->id == V4L2_CID_VBLANK) { + exposure_max = ov01a10->cur_mode->height + ctrl->val - + OV01A10_EXPOSURE_MAX_MARGIN; + __v4l2_ctrl_modify_range(ov01a10->exposure, + ov01a10->exposure->minimum, + exposure_max, ov01a10->exposure->step, + exposure_max); + } + + if (!pm_runtime_get_if_in_use(&client->dev)) + return 0; + + switch (ctrl->id) { + case V4L2_CID_ANALOGUE_GAIN: + ret = ov01a10_write_reg(ov01a10, OV01A10_REG_ANALOG_GAIN, 2, + ctrl->val); + break; + + case V4L2_CID_DIGITAL_GAIN: + ret = ov01a10_update_digital_gain(ov01a10, ctrl->val); + break; + + case V4L2_CID_EXPOSURE: + ret = ov01a10_write_reg(ov01a10, OV01A10_REG_EXPOSURE, 2, + ctrl->val); + break; + + case V4L2_CID_VBLANK: + ret = ov01a10_write_reg(ov01a10, OV01A10_REG_VTS, 2, + ov01a10->cur_mode->height + ctrl->val); + break; + + case V4L2_CID_TEST_PATTERN: + ret = ov01a10_test_pattern(ov01a10, ctrl->val); + break; + + case V4L2_CID_HFLIP: + ov01a10_set_hflip(ov01a10, ctrl->val); + break; + + case V4L2_CID_VFLIP: + ov01a10_set_vflip(ov01a10, ctrl->val); + break; + + default: + ret = -EINVAL; + break; + } + + pm_runtime_put(&client->dev); + + return ret; +} + +static const struct v4l2_ctrl_ops ov01a10_ctrl_ops = { + .s_ctrl = ov01a10_set_ctrl, +}; + +static int ov01a10_init_controls(struct ov01a10 *ov01a10) +{ + struct i2c_client *client = v4l2_get_subdevdata(&ov01a10->sd); + struct v4l2_fwnode_device_properties props; + u32 vblank_min, vblank_max, vblank_default; + struct v4l2_ctrl_handler *ctrl_hdlr; + const struct ov01a10_mode *cur_mode; + s64 exposure_max, h_blank; + int ret = 0; + int size; + + ret = v4l2_fwnode_device_parse(&client->dev, &props); + if (ret) + return ret; + + ctrl_hdlr = &ov01a10->ctrl_handler; + ret = v4l2_ctrl_handler_init(ctrl_hdlr, 12); + if (ret) + return ret; + + cur_mode = ov01a10->cur_mode; + size = ARRAY_SIZE(link_freq_menu_items); + + ov01a10->link_freq = v4l2_ctrl_new_int_menu(ctrl_hdlr, + &ov01a10_ctrl_ops, + V4L2_CID_LINK_FREQ, + size - 1, 0, + link_freq_menu_items); + if (ov01a10->link_freq) + ov01a10->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY; + + ov01a10->pixel_rate = v4l2_ctrl_new_std(ctrl_hdlr, &ov01a10_ctrl_ops, + V4L2_CID_PIXEL_RATE, 0, + OV01A10_SCLK, 1, OV01A10_SCLK); + + vblank_min = cur_mode->vts_min - cur_mode->height; + vblank_max = OV01A10_VTS_MAX - cur_mode->height; + vblank_default = cur_mode->vts_def - cur_mode->height; + ov01a10->vblank = v4l2_ctrl_new_std(ctrl_hdlr, &ov01a10_ctrl_ops, + V4L2_CID_VBLANK, vblank_min, + vblank_max, 1, vblank_default); + + h_blank = cur_mode->hts - cur_mode->width; + ov01a10->hblank = v4l2_ctrl_new_std(ctrl_hdlr, &ov01a10_ctrl_ops, + V4L2_CID_HBLANK, h_blank, h_blank, + 1, h_blank); + if (ov01a10->hblank) + ov01a10->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY; + + v4l2_ctrl_new_std(ctrl_hdlr, &ov01a10_ctrl_ops, V4L2_CID_ANALOGUE_GAIN, + OV01A10_ANAL_GAIN_MIN, OV01A10_ANAL_GAIN_MAX, + OV01A10_ANAL_GAIN_STEP, OV01A10_ANAL_GAIN_MIN); + v4l2_ctrl_new_std(ctrl_hdlr, &ov01a10_ctrl_ops, V4L2_CID_DIGITAL_GAIN, + OV01A10_DGTL_GAIN_MIN, OV01A10_DGTL_GAIN_MAX, + OV01A10_DGTL_GAIN_STEP, OV01A10_DGTL_GAIN_DEFAULT); + + exposure_max = cur_mode->vts_def - OV01A10_EXPOSURE_MAX_MARGIN; + ov01a10->exposure = v4l2_ctrl_new_std(ctrl_hdlr, &ov01a10_ctrl_ops, + V4L2_CID_EXPOSURE, + OV01A10_EXPOSURE_MIN, + exposure_max, + OV01A10_EXPOSURE_STEP, + exposure_max); + + v4l2_ctrl_new_std_menu_items(ctrl_hdlr, &ov01a10_ctrl_ops, + V4L2_CID_TEST_PATTERN, + ARRAY_SIZE(ov01a10_test_pattern_menu) - 1, + 0, 0, ov01a10_test_pattern_menu); + + v4l2_ctrl_new_std(ctrl_hdlr, &ov01a10_ctrl_ops, V4L2_CID_HFLIP, + 0, 1, 1, 0); + v4l2_ctrl_new_std(ctrl_hdlr, &ov01a10_ctrl_ops, V4L2_CID_VFLIP, + 0, 1, 1, 0); + + ret = v4l2_ctrl_new_fwnode_properties(ctrl_hdlr, &ov01a10_ctrl_ops, + &props); + if (ret) + goto fail; + + if (ctrl_hdlr->error) { + ret = ctrl_hdlr->error; + goto fail; + } + + ov01a10->sd.ctrl_handler = ctrl_hdlr; + + return 0; +fail: + v4l2_ctrl_handler_free(ctrl_hdlr); + + return ret; +} + +static void ov01a10_update_pad_format(const struct ov01a10_mode *mode, + struct v4l2_mbus_framefmt *fmt) +{ + fmt->width = mode->width; + fmt->height = mode->height; + fmt->code = MEDIA_BUS_FMT_SBGGR10_1X10; + fmt->field = V4L2_FIELD_NONE; + fmt->colorspace = V4L2_COLORSPACE_RAW; +} + +static int ov01a10_start_streaming(struct ov01a10 *ov01a10) +{ + struct i2c_client *client = v4l2_get_subdevdata(&ov01a10->sd); + const struct ov01a10_reg_list *reg_list; + int link_freq_index; + int ret = 0; + + link_freq_index = ov01a10->cur_mode->link_freq_index; + reg_list = &link_freq_configs[link_freq_index].reg_list; + ret = ov01a10_write_reg_list(ov01a10, reg_list); + if (ret) { + dev_err(&client->dev, "failed to set plls\n"); + return ret; + } + + reg_list = &ov01a10->cur_mode->reg_list; + ret = ov01a10_write_reg_list(ov01a10, reg_list); + if (ret) { + dev_err(&client->dev, "failed to set mode\n"); + return ret; + } + + ret = __v4l2_ctrl_handler_setup(ov01a10->sd.ctrl_handler); + if (ret) + return ret; + + ret = ov01a10_write_reg(ov01a10, OV01A10_REG_MODE_SELECT, 1, + OV01A10_MODE_STREAMING); + if (ret) + dev_err(&client->dev, "failed to start streaming\n"); + + return ret; +} + +static void ov01a10_stop_streaming(struct ov01a10 *ov01a10) +{ + struct i2c_client *client = v4l2_get_subdevdata(&ov01a10->sd); + int ret = 0; + + ret = ov01a10_write_reg(ov01a10, OV01A10_REG_MODE_SELECT, 1, + OV01A10_MODE_STANDBY); + if (ret) + dev_err(&client->dev, "failed to stop streaming\n"); +} + +static int ov01a10_set_stream(struct v4l2_subdev *sd, int enable) +{ + struct ov01a10 *ov01a10 = to_ov01a10(sd); + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct v4l2_subdev_state *state; + int ret = 0; + + state = v4l2_subdev_lock_and_get_active_state(sd); + if (ov01a10->streaming == enable) + goto unlock; + + if (enable) { + ret = pm_runtime_resume_and_get(&client->dev); + if (ret < 0) + goto unlock; + + ret = ov01a10_start_streaming(ov01a10); + if (ret) { + pm_runtime_put(&client->dev); + goto unlock; + } + + goto done; + } + + ov01a10_stop_streaming(ov01a10); + pm_runtime_put(&client->dev); +done: + ov01a10->streaming = enable; +unlock: + v4l2_subdev_unlock_state(state); + + return ret; +} + +static int __maybe_unused ov01a10_suspend(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct ov01a10 *ov01a10 = to_ov01a10(sd); + struct v4l2_subdev_state *state; + + state = v4l2_subdev_lock_and_get_active_state(sd); + if (ov01a10->streaming) + ov01a10_stop_streaming(ov01a10); + + v4l2_subdev_unlock_state(state); + + return 0; +} + +static int __maybe_unused ov01a10_resume(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct ov01a10 *ov01a10 = to_ov01a10(sd); + struct v4l2_subdev_state *state; + int ret = 0; + + state = v4l2_subdev_lock_and_get_active_state(sd); + if (!ov01a10->streaming) + goto exit; + + ret = ov01a10_start_streaming(ov01a10); + if (ret) { + ov01a10->streaming = false; + ov01a10_stop_streaming(ov01a10); + } + +exit: + v4l2_subdev_unlock_state(state); + + return ret; +} + +static int ov01a10_set_format(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_format *fmt) +{ + struct ov01a10 *ov01a10 = to_ov01a10(sd); + const struct ov01a10_mode *mode; + struct v4l2_mbus_framefmt *format; + s32 vblank_def, h_blank; + + mode = v4l2_find_nearest_size(supported_modes, + ARRAY_SIZE(supported_modes), width, + height, fmt->format.width, + fmt->format.height); + + ov01a10_update_pad_format(mode, &fmt->format); + + if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) { + ov01a10->cur_mode = mode; + __v4l2_ctrl_s_ctrl(ov01a10->link_freq, mode->link_freq_index); + __v4l2_ctrl_s_ctrl_int64(ov01a10->pixel_rate, OV01A10_SCLK); + + vblank_def = mode->vts_def - mode->height; + __v4l2_ctrl_modify_range(ov01a10->vblank, + mode->vts_min - mode->height, + OV01A10_VTS_MAX - mode->height, 1, + vblank_def); + __v4l2_ctrl_s_ctrl(ov01a10->vblank, vblank_def); + h_blank = mode->hts - mode->width; + __v4l2_ctrl_modify_range(ov01a10->hblank, h_blank, h_blank, 1, + h_blank); + } + + format = v4l2_subdev_get_pad_format(sd, sd_state, fmt->stream); + *format = fmt->format; + + return 0; +} + +static int ov01a10_init_cfg(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state) +{ + struct v4l2_subdev_format fmt = { + .which = V4L2_SUBDEV_FORMAT_TRY, + .format = { + .width = OV01A10_ACITVE_WIDTH, + .height = OV01A10_ACITVE_HEIGHT, + }, + }; + + ov01a10_set_format(sd, state, &fmt); + + return 0; +} + +static int ov01a10_enum_mbus_code(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_mbus_code_enum *code) +{ + if (code->index > 0) + return -EINVAL; + + code->code = MEDIA_BUS_FMT_SBGGR10_1X10; + + return 0; +} + +static int ov01a10_enum_frame_size(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_frame_size_enum *fse) +{ + if (fse->index >= ARRAY_SIZE(supported_modes) || + fse->code != MEDIA_BUS_FMT_SBGGR10_1X10) + return -EINVAL; + + fse->min_width = supported_modes[fse->index].width; + fse->max_width = fse->min_width; + fse->min_height = supported_modes[fse->index].height; + fse->max_height = fse->min_height; + + return 0; +} + +static int ov01a10_get_selection(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state, + struct v4l2_subdev_selection *sel) +{ + if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE) + return -EINVAL; + + switch (sel->target) { + case V4L2_SEL_TGT_NATIVE_SIZE: + case V4L2_SEL_TGT_CROP_BOUNDS: + sel->r.top = 0; + sel->r.left = 0; + sel->r.width = OV01A10_PIXEL_ARRAY_WIDTH; + sel->r.height = OV01A10_PIXEL_ARRAY_HEIGHT; + return 0; + case V4L2_SEL_TGT_CROP: + case V4L2_SEL_TGT_CROP_DEFAULT: + sel->r.top = (OV01A10_PIXEL_ARRAY_HEIGHT - + OV01A10_ACITVE_HEIGHT) / 2; + sel->r.left = (OV01A10_PIXEL_ARRAY_WIDTH - + OV01A10_ACITVE_WIDTH) / 2; + sel->r.width = OV01A10_ACITVE_WIDTH; + sel->r.height = OV01A10_ACITVE_HEIGHT; + return 0; + } + + return -EINVAL; +} + +static const struct v4l2_subdev_core_ops ov01a10_core_ops = { + .log_status = v4l2_ctrl_subdev_log_status, + .subscribe_event = v4l2_ctrl_subdev_subscribe_event, + .unsubscribe_event = v4l2_event_subdev_unsubscribe, +}; + +static const struct v4l2_subdev_video_ops ov01a10_video_ops = { + .s_stream = ov01a10_set_stream, +}; + +static const struct v4l2_subdev_pad_ops ov01a10_pad_ops = { + .init_cfg = ov01a10_init_cfg, + .set_fmt = ov01a10_set_format, + .get_fmt = v4l2_subdev_get_fmt, + .get_selection = ov01a10_get_selection, + .enum_mbus_code = ov01a10_enum_mbus_code, + .enum_frame_size = ov01a10_enum_frame_size, +}; + +static const struct v4l2_subdev_ops ov01a10_subdev_ops = { + .core = &ov01a10_core_ops, + .video = &ov01a10_video_ops, + .pad = &ov01a10_pad_ops, +}; + +static const struct media_entity_operations ov01a10_subdev_entity_ops = { + .link_validate = v4l2_subdev_link_validate, +}; + +static int ov01a10_identify_module(struct ov01a10 *ov01a10) +{ + struct i2c_client *client = v4l2_get_subdevdata(&ov01a10->sd); + int ret; + u32 val; + + ret = ov01a10_read_reg(ov01a10, OV01A10_REG_CHIP_ID, 3, &val); + if (ret) + return ret; + + if (val != OV01A10_CHIP_ID) { + dev_err(&client->dev, "chip id mismatch: %x!=%x\n", + OV01A10_CHIP_ID, val); + return -EIO; + } + + return 0; +} + +static void ov01a10_remove(struct i2c_client *client) +{ + struct v4l2_subdev *sd = i2c_get_clientdata(client); + + v4l2_async_unregister_subdev(sd); + media_entity_cleanup(&sd->entity); + v4l2_ctrl_handler_free(sd->ctrl_handler); + + pm_runtime_disable(&client->dev); +} + +static int ov01a10_probe(struct i2c_client *client) +{ + struct device *dev = &client->dev; + struct ov01a10 *ov01a10; + int ret = 0; + + ov01a10 = devm_kzalloc(dev, sizeof(*ov01a10), GFP_KERNEL); + if (!ov01a10) + return -ENOMEM; + + v4l2_i2c_subdev_init(&ov01a10->sd, client, &ov01a10_subdev_ops); + + ret = ov01a10_identify_module(ov01a10); + if (ret) + return dev_err_probe(dev, ret, + "failed to find sensor\n"); + + ov01a10->cur_mode = &supported_modes[0]; + + ret = ov01a10_init_controls(ov01a10); + if (ret) { + dev_err(dev, "failed to init controls: %d\n", ret); + return ret; + } + + ov01a10->sd.state_lock = ov01a10->ctrl_handler.lock; + ov01a10->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | + V4L2_SUBDEV_FL_HAS_EVENTS; + ov01a10->sd.entity.ops = &ov01a10_subdev_entity_ops; + ov01a10->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR; + ov01a10->pad.flags = MEDIA_PAD_FL_SOURCE; + + ret = media_entity_pads_init(&ov01a10->sd.entity, 1, &ov01a10->pad); + if (ret) { + dev_err(dev, "Failed to init entity pads: %d\n", ret); + goto err_handler_free; + } + + ret = v4l2_subdev_init_finalize(&ov01a10->sd); + if (ret) { + dev_err(dev, "Failed to allocate subdev state: %d\n", ret); + goto err_media_entity_cleanup; + } + + ret = v4l2_async_register_subdev_sensor(&ov01a10->sd); + if (ret < 0) { + dev_err(dev, "Failed to register subdev: %d\n", ret); + goto err_media_entity_cleanup; + } + + pm_runtime_enable(dev); + pm_runtime_idle(dev); + + return 0; + +err_media_entity_cleanup: + media_entity_cleanup(&ov01a10->sd.entity); + +err_handler_free: + v4l2_ctrl_handler_free(ov01a10->sd.ctrl_handler); + + return ret; +} + +static const struct dev_pm_ops ov01a10_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(ov01a10_suspend, ov01a10_resume) +}; + +#ifdef CONFIG_ACPI +static const struct acpi_device_id ov01a10_acpi_ids[] = { + { "OVTI01A0" }, + { } +}; + +MODULE_DEVICE_TABLE(acpi, ov01a10_acpi_ids); +#endif + +static struct i2c_driver ov01a10_i2c_driver = { + .driver = { + .name = "ov01a10", + .pm = &ov01a10_pm_ops, + .acpi_match_table = ACPI_PTR(ov01a10_acpi_ids), + }, + .probe_new = ov01a10_probe, + .remove = ov01a10_remove, +}; + +module_i2c_driver(ov01a10_i2c_driver); + +MODULE_AUTHOR("Bingbu Cao "); +MODULE_AUTHOR("Wang Yating "); +MODULE_DESCRIPTION("OmniVision OV01A10 sensor driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/i2c/ov02a10.c b/drivers/media/i2c/ov02a10.c index 2c1eb724d8e517044fa2d0711c1b5fd17165ecd5..741d977a76f32fd0a1dd259f36dd03eaf8da9771 100644 --- a/drivers/media/i2c/ov02a10.c +++ b/drivers/media/i2c/ov02a10.c @@ -1002,8 +1002,8 @@ static struct i2c_driver ov02a10_i2c_driver = { .pm = &ov02a10_pm_ops, .of_match_table = ov02a10_of_match, }, - .probe_new = &ov02a10_probe, - .remove = &ov02a10_remove, + .probe = ov02a10_probe, + .remove = ov02a10_remove, }; module_i2c_driver(ov02a10_i2c_driver); diff --git a/drivers/media/i2c/ov08d10.c b/drivers/media/i2c/ov08d10.c index a39e086a51c538494a002c4fa46c19638e7c4b9e..7d55d4ca24de188b2233e8787e371ed7b34e4de9 100644 --- a/drivers/media/i2c/ov08d10.c +++ b/drivers/media/i2c/ov08d10.c @@ -1520,7 +1520,7 @@ static struct i2c_driver ov08d10_i2c_driver = { .pm = &ov08d10_pm_ops, .acpi_match_table = ACPI_PTR(ov08d10_acpi_ids), }, - .probe_new = ov08d10_probe, + .probe = ov08d10_probe, .remove = ov08d10_remove, }; diff --git a/drivers/media/i2c/ov08x40.c b/drivers/media/i2c/ov08x40.c index 72ae7fba94eb0e71d6614edd6e9a3a798b0bc5c2..77bcdcd0824c1f61555d7acec449ece504507ee4 100644 --- a/drivers/media/i2c/ov08x40.c +++ b/drivers/media/i2c/ov08x40.c @@ -3313,7 +3313,7 @@ static struct i2c_driver ov08x40_i2c_driver = { .pm = &ov08x40_pm_ops, .acpi_match_table = ACPI_PTR(ov08x40_acpi_ids), }, - .probe_new = ov08x40_probe, + .probe = ov08x40_probe, .remove = ov08x40_remove, }; diff --git a/drivers/media/i2c/ov13858.c b/drivers/media/i2c/ov13858.c index 69a7a2c590dbcf535454533d7e85d7a24aa399af..3db3e64fa3ffa423d79dfb4c482de91e65d5a2a1 100644 --- a/drivers/media/i2c/ov13858.c +++ b/drivers/media/i2c/ov13858.c @@ -1806,7 +1806,7 @@ static struct i2c_driver ov13858_i2c_driver = { .pm = &ov13858_pm_ops, .acpi_match_table = ACPI_PTR(ov13858_acpi_ids), }, - .probe_new = ov13858_probe, + .probe = ov13858_probe, .remove = ov13858_remove, .id_table = ov13858_id_table, }; diff --git a/drivers/media/i2c/ov13b10.c b/drivers/media/i2c/ov13b10.c index c1430044fb1e96ca6a304a493c4d5c2e9e7705ea..6110fb1e6bc68656aea07d9a2e62bd6e9923c880 100644 --- a/drivers/media/i2c/ov13b10.c +++ b/drivers/media/i2c/ov13b10.c @@ -1496,7 +1496,7 @@ static struct i2c_driver ov13b10_i2c_driver = { .pm = &ov13b10_pm_ops, .acpi_match_table = ACPI_PTR(ov13b10_acpi_ids), }, - .probe_new = ov13b10_probe, + .probe = ov13b10_probe, .remove = ov13b10_remove, .flags = I2C_DRV_ACPI_WAIVE_D0_PROBE, }; diff --git a/drivers/media/i2c/ov2640.c b/drivers/media/i2c/ov2640.c index 39d56838a4efcc89d2102a8d14278b6efba6c1f7..ec801a81c2d0ecc72be1285e05d535b6cbbbe9f4 100644 --- a/drivers/media/i2c/ov2640.c +++ b/drivers/media/i2c/ov2640.c @@ -1298,7 +1298,7 @@ static struct i2c_driver ov2640_i2c_driver = { .name = "ov2640", .of_match_table = of_match_ptr(ov2640_of_match), }, - .probe_new = ov2640_probe, + .probe = ov2640_probe, .remove = ov2640_remove, .id_table = ov2640_id, }; diff --git a/drivers/media/i2c/ov2659.c b/drivers/media/i2c/ov2659.c index 42fc64ada08c0582bd0da392502194190a4ace2e..5429bd2eb05318fa70f18054a745f4f655910393 100644 --- a/drivers/media/i2c/ov2659.c +++ b/drivers/media/i2c/ov2659.c @@ -1584,7 +1584,7 @@ static struct i2c_driver ov2659_i2c_driver = { .pm = &ov2659_pm_ops, .of_match_table = of_match_ptr(ov2659_of_match), }, - .probe_new = ov2659_probe, + .probe = ov2659_probe, .remove = ov2659_remove, .id_table = ov2659_id, }; diff --git a/drivers/media/i2c/ov2680.c b/drivers/media/i2c/ov2680.c index 54153bf66bddc045dff145032bd16a6b60077e8e..d06e9fc37f7706f8df2deeb969c392be978e46e4 100644 --- a/drivers/media/i2c/ov2680.c +++ b/drivers/media/i2c/ov2680.c @@ -1158,7 +1158,7 @@ static struct i2c_driver ov2680_i2c_driver = { .pm = &ov2680_pm_ops, .of_match_table = of_match_ptr(ov2680_dt_ids), }, - .probe_new = ov2680_probe, + .probe = ov2680_probe, .remove = ov2680_remove, }; module_i2c_driver(ov2680_i2c_driver); diff --git a/drivers/media/i2c/ov2685.c b/drivers/media/i2c/ov2685.c index f119a93e7c647678e4f8527ef2db65c142ea8237..303793e1f97d647b8ad024e10882a893c12efe0c 100644 --- a/drivers/media/i2c/ov2685.c +++ b/drivers/media/i2c/ov2685.c @@ -903,8 +903,8 @@ static struct i2c_driver ov2685_i2c_driver = { .pm = &ov2685_pm_ops, .of_match_table = of_match_ptr(ov2685_of_match), }, - .probe_new = &ov2685_probe, - .remove = &ov2685_remove, + .probe = ov2685_probe, + .remove = ov2685_remove, }; module_i2c_driver(ov2685_i2c_driver); diff --git a/drivers/media/i2c/ov2740.c b/drivers/media/i2c/ov2740.c index 89d126240c3450ecd179393afb15f5fe9673cc15..158d934733c3e954f704eaffb0c79bc9dfa5c8a0 100644 --- a/drivers/media/i2c/ov2740.c +++ b/drivers/media/i2c/ov2740.c @@ -1215,7 +1215,7 @@ static struct i2c_driver ov2740_i2c_driver = { .pm = pm_sleep_ptr(&ov2740_pm_ops), .acpi_match_table = ov2740_acpi_ids, }, - .probe_new = ov2740_probe, + .probe = ov2740_probe, .remove = ov2740_remove, .flags = I2C_DRV_ACPI_WAIVE_D0_PROBE, }; diff --git a/drivers/media/i2c/ov4689.c b/drivers/media/i2c/ov4689.c index c602e507d42b615e5151883a0f48cccdcbcc132e..fda217d2cb10af78b3680c597fb0b95716269d85 100644 --- a/drivers/media/i2c/ov4689.c +++ b/drivers/media/i2c/ov4689.c @@ -1008,7 +1008,7 @@ static struct i2c_driver ov4689_i2c_driver = { .pm = &ov4689_pm_ops, .of_match_table = ov4689_of_match, }, - .probe_new = ov4689_probe, + .probe = ov4689_probe, .remove = ov4689_remove, }; diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c index 1536649b9e90f4a86fd1accb0e2b6f8f2f03981e..36b509714c8c777d94bc883692b4a0c39de7fe8c 100644 --- a/drivers/media/i2c/ov5640.c +++ b/drivers/media/i2c/ov5640.c @@ -2815,7 +2815,6 @@ static int ov5640_get_fmt(struct v4l2_subdev *sd, static int ov5640_try_fmt_internal(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *fmt, - enum ov5640_frame_rate fr, const struct ov5640_mode_info **new_mode) { struct ov5640_dev *sensor = to_ov5640_dev(sd); @@ -2927,19 +2926,6 @@ static int ov5640_update_pixel_rate(struct ov5640_dev *sensor) hblank, hblank, 1, hblank); vblank = timings->vblank_def; - - if (sensor->current_fr != mode->def_fps) { - /* - * Compute the vertical blanking according to the framerate - * configured with s_frame_interval. - */ - int fie_num = sensor->frame_interval.numerator; - int fie_denom = sensor->frame_interval.denominator; - - vblank = ((fie_num * pixel_rate / fie_denom) / timings->htot) - - mode->height; - } - __v4l2_ctrl_modify_range(sensor->ctrls.vblank, OV5640_MIN_VBLANK, OV5640_MAX_VTS - mode->height, 1, vblank); __v4l2_ctrl_s_ctrl(sensor->ctrls.vblank, vblank); @@ -2975,8 +2961,7 @@ static int ov5640_set_fmt(struct v4l2_subdev *sd, goto out; } - ret = ov5640_try_fmt_internal(sd, mbus_fmt, - sensor->current_fr, &new_mode); + ret = ov5640_try_fmt_internal(sd, mbus_fmt, &new_mode); if (ret) goto out; @@ -3851,7 +3836,7 @@ static int ov5640_probe(struct i2c_client *client) /* * default init sequence initialize sensor to - * YUV422 UYVY VGA@30fps + * YUV422 UYVY VGA(30FPS in parallel mode, 60 in MIPI CSI-2 mode) */ sensor->frame_interval.numerator = 1; sensor->frame_interval.denominator = ov5640_framerates[OV5640_30_FPS]; @@ -4011,7 +3996,7 @@ static struct i2c_driver ov5640_i2c_driver = { .pm = &ov5640_pm_ops, }, .id_table = ov5640_id, - .probe_new = ov5640_probe, + .probe = ov5640_probe, .remove = ov5640_remove, }; diff --git a/drivers/media/i2c/ov5645.c b/drivers/media/i2c/ov5645.c index c8999fc4f26fdb1761eda454941d35efdd5a3402..a70db7e601a495ef0162689287902697b3bc59c3 100644 --- a/drivers/media/i2c/ov5645.c +++ b/drivers/media/i2c/ov5645.c @@ -1286,7 +1286,7 @@ static struct i2c_driver ov5645_i2c_driver = { .name = "ov5645", .pm = &ov5645_pm_ops, }, - .probe_new = ov5645_probe, + .probe = ov5645_probe, .remove = ov5645_remove, .id_table = ov5645_id, }; diff --git a/drivers/media/i2c/ov5647.c b/drivers/media/i2c/ov5647.c index 233576ee95038ae05d9fea9e346f7f3e95468ece..8de398423b7cb9c482f2a246ef5bf8e59e4598e5 100644 --- a/drivers/media/i2c/ov5647.c +++ b/drivers/media/i2c/ov5647.c @@ -1515,7 +1515,7 @@ static struct i2c_driver ov5647_driver = { .name = "ov5647", .pm = &ov5647_pm_ops, }, - .probe_new = ov5647_probe, + .probe = ov5647_probe, .remove = ov5647_remove, .id_table = ov5647_id, }; diff --git a/drivers/media/i2c/ov5648.c b/drivers/media/i2c/ov5648.c index 17465fcf28e335949f070b4961177b207003deda..aa10eb4e3991c59b1d2a4ff2e89918187ae04c48 100644 --- a/drivers/media/i2c/ov5648.c +++ b/drivers/media/i2c/ov5648.c @@ -2616,8 +2616,8 @@ static struct i2c_driver ov5648_driver = { .of_match_table = ov5648_of_match, .pm = &ov5648_pm_ops, }, - .probe_new = ov5648_probe, - .remove = ov5648_remove, + .probe = ov5648_probe, + .remove = ov5648_remove, }; module_i2c_driver(ov5648_driver); diff --git a/drivers/media/i2c/ov5670.c b/drivers/media/i2c/ov5670.c index c026610d0f31fcff99f358ab4988e9e9a0b3c450..d722348b938b4c13fc7845042b40d01ff1aa5ba4 100644 --- a/drivers/media/i2c/ov5670.c +++ b/drivers/media/i2c/ov5670.c @@ -2853,7 +2853,7 @@ static struct i2c_driver ov5670_i2c_driver = { .acpi_match_table = ACPI_PTR(ov5670_acpi_ids), .of_match_table = ov5670_of_ids, }, - .probe_new = ov5670_probe, + .probe = ov5670_probe, .remove = ov5670_remove, .flags = I2C_DRV_ACPI_WAIVE_D0_PROBE, }; diff --git a/drivers/media/i2c/ov5675.c b/drivers/media/i2c/ov5675.c index d55180b3b7aaa55c7353da467982f549bb275d36..700c4b69846f57e895a360ae47950b9a1ee5a59e 100644 --- a/drivers/media/i2c/ov5675.c +++ b/drivers/media/i2c/ov5675.c @@ -1435,7 +1435,7 @@ static struct i2c_driver ov5675_i2c_driver = { .acpi_match_table = ACPI_PTR(ov5675_acpi_ids), .of_match_table = ov5675_of_match, }, - .probe_new = ov5675_probe, + .probe = ov5675_probe, .remove = ov5675_remove, .flags = I2C_DRV_ACPI_WAIVE_D0_PROBE, }; diff --git a/drivers/media/i2c/ov5693.c b/drivers/media/i2c/ov5693.c index e3c3bed69ad66f415caf2a73384da7a70d70fd19..7f9212cce2397b5169560a851063dbbebf2726d7 100644 --- a/drivers/media/i2c/ov5693.c +++ b/drivers/media/i2c/ov5693.c @@ -404,8 +404,8 @@ static int ov5693_read_reg(struct ov5693_device *ov5693, u32 addr, u32 *value) ret = i2c_transfer(client->adapter, msg, 2); if (ret < 0) return dev_err_probe(&client->dev, ret, - "Failed to read register 0x%04x: %d\n", - addr & OV5693_REG_ADDR_MASK, ret); + "Failed to read register 0x%04x\n", + addr & OV5693_REG_ADDR_MASK); *value = 0; for (i = 0; i < len; ++i) { @@ -1554,7 +1554,7 @@ static struct i2c_driver ov5693_driver = { .of_match_table = ov5693_of_match, .pm = &ov5693_pm_ops, }, - .probe_new = ov5693_probe, + .probe = ov5693_probe, .remove = ov5693_remove, }; module_i2c_driver(ov5693_driver); diff --git a/drivers/media/i2c/ov5695.c b/drivers/media/i2c/ov5695.c index b287c28920a687bad19633ce79e0620c3d472820..3023b72541677d0ef7b46341f6d7b5000e318c97 100644 --- a/drivers/media/i2c/ov5695.c +++ b/drivers/media/i2c/ov5695.c @@ -1392,8 +1392,8 @@ static struct i2c_driver ov5695_i2c_driver = { .pm = &ov5695_pm_ops, .of_match_table = of_match_ptr(ov5695_of_match), }, - .probe_new = &ov5695_probe, - .remove = &ov5695_remove, + .probe = ov5695_probe, + .remove = ov5695_remove, }; module_i2c_driver(ov5695_i2c_driver); diff --git a/drivers/media/i2c/ov6650.c b/drivers/media/i2c/ov6650.c index 4c0ea2ae671b33e38e4e84b363c09eba6ba2527c..1ad07935f0465a9919fc5da4bbcfcb6d633f7e66 100644 --- a/drivers/media/i2c/ov6650.c +++ b/drivers/media/i2c/ov6650.c @@ -1113,7 +1113,7 @@ static struct i2c_driver ov6650_i2c_driver = { .driver = { .name = "ov6650", }, - .probe_new = ov6650_probe, + .probe = ov6650_probe, .remove = ov6650_remove, .id_table = ov6650_id, }; diff --git a/drivers/media/i2c/ov7251.c b/drivers/media/i2c/ov7251.c index 88e98743528531c3302c766448f6dd678a03605e..675fb37a6feaec82614028c3bb9428a878d94c64 100644 --- a/drivers/media/i2c/ov7251.c +++ b/drivers/media/i2c/ov7251.c @@ -1806,7 +1806,7 @@ static struct i2c_driver ov7251_i2c_driver = { .name = "ov7251", .pm = &ov7251_pm_ops, }, - .probe_new = ov7251_probe, + .probe = ov7251_probe, .remove = ov7251_remove, }; diff --git a/drivers/media/i2c/ov7640.c b/drivers/media/i2c/ov7640.c index e6751d5cc64bcd862162c8fcd3ca18c69232035d..293f5f4043587dc783b6f62ba256c7e49b98c049 100644 --- a/drivers/media/i2c/ov7640.c +++ b/drivers/media/i2c/ov7640.c @@ -86,7 +86,7 @@ static struct i2c_driver ov7640_driver = { .driver = { .name = "ov7640", }, - .probe_new = ov7640_probe, + .probe = ov7640_probe, .remove = ov7640_remove, .id_table = ov7640_id, }; diff --git a/drivers/media/i2c/ov7670.c b/drivers/media/i2c/ov7670.c index ecbded4f07653e76432dfcfcaa863ffbfa6fdbbf..2f55491ef571f00d71b1e18c8d28ab544ae7ef92 100644 --- a/drivers/media/i2c/ov7670.c +++ b/drivers/media/i2c/ov7670.c @@ -2033,7 +2033,7 @@ static struct i2c_driver ov7670_driver = { .name = "ov7670", .of_match_table = of_match_ptr(ov7670_of_match), }, - .probe_new = ov7670_probe, + .probe = ov7670_probe, .remove = ov7670_remove, .id_table = ov7670_id, }; diff --git a/drivers/media/i2c/ov772x.c b/drivers/media/i2c/ov772x.c index a238e63425f8cdb900c4eb82556fe33a004aa97e..386d69c8e074658cc5063a8fc2bad2e6f559889c 100644 --- a/drivers/media/i2c/ov772x.c +++ b/drivers/media/i2c/ov772x.c @@ -1551,7 +1551,7 @@ static struct i2c_driver ov772x_i2c_driver = { .name = "ov772x", .of_match_table = ov772x_of_match, }, - .probe_new = ov772x_probe, + .probe = ov772x_probe, .remove = ov772x_remove, .id_table = ov772x_id, }; diff --git a/drivers/media/i2c/ov7740.c b/drivers/media/i2c/ov7740.c index c9fd9b0bc54a66dd19a75823ce77c5c14d19c959..10e47c7d4e0c10520c0fe4c3691b16ef978ac651 100644 --- a/drivers/media/i2c/ov7740.c +++ b/drivers/media/i2c/ov7740.c @@ -1212,7 +1212,7 @@ static struct i2c_driver ov7740_i2c_driver = { .pm = &ov7740_pm_ops, .of_match_table = of_match_ptr(ov7740_of_match), }, - .probe_new = ov7740_probe, + .probe = ov7740_probe, .remove = ov7740_remove, .id_table = ov7740_id, }; diff --git a/drivers/media/i2c/ov8856.c b/drivers/media/i2c/ov8856.c index b5c7881383ca7a2f0b4c546911b6418524d6562d..f053c3a7676a09e171830c716088dbef6842c7ad 100644 --- a/drivers/media/i2c/ov8856.c +++ b/drivers/media/i2c/ov8856.c @@ -2527,7 +2527,7 @@ static struct i2c_driver ov8856_i2c_driver = { .acpi_match_table = ACPI_PTR(ov8856_acpi_ids), .of_match_table = ov8856_of_match, }, - .probe_new = ov8856_probe, + .probe = ov8856_probe, .remove = ov8856_remove, .flags = I2C_DRV_ACPI_WAIVE_D0_PROBE, }; diff --git a/drivers/media/i2c/ov8858.c b/drivers/media/i2c/ov8858.c index 9ca8a17bfbb91ad581fcfa8e52a9f0288f182b6a..3af6125a2eee8130417c1ee00ec7d8367d62300f 100644 --- a/drivers/media/i2c/ov8858.c +++ b/drivers/media/i2c/ov8858.c @@ -1998,8 +1998,8 @@ static struct i2c_driver ov8858_i2c_driver = { .pm = &ov8858_pm_ops, .of_match_table = ov8858_of_match, }, - .probe_new = &ov8858_probe, - .remove = &ov8858_remove, + .probe = ov8858_probe, + .remove = ov8858_remove, }; module_i2c_driver(ov8858_i2c_driver); diff --git a/drivers/media/i2c/ov8865.c b/drivers/media/i2c/ov8865.c index cae1866134a03c36da14139d046a3b08e92ae031..f2213c6158d3e463fc2e27c35bcb5392f78f296b 100644 --- a/drivers/media/i2c/ov8865.c +++ b/drivers/media/i2c/ov8865.c @@ -3158,8 +3158,8 @@ static struct i2c_driver ov8865_driver = { .acpi_match_table = ov8865_acpi_match, .pm = &ov8865_pm_ops, }, - .probe_new = ov8865_probe, - .remove = ov8865_remove, + .probe = ov8865_probe, + .remove = ov8865_remove, }; module_i2c_driver(ov8865_driver); diff --git a/drivers/media/i2c/ov9282.c b/drivers/media/i2c/ov9282.c index 7f46cac38aab48b463485878a0b7f544c4bbb946..068c7449f50ed53bc1c96401a8d63fc68526fecc 100644 --- a/drivers/media/i2c/ov9282.c +++ b/drivers/media/i2c/ov9282.c @@ -1512,7 +1512,7 @@ static const struct of_device_id ov9282_of_match[] = { MODULE_DEVICE_TABLE(of, ov9282_of_match); static struct i2c_driver ov9282_driver = { - .probe_new = ov9282_probe, + .probe = ov9282_probe, .remove = ov9282_remove, .driver = { .name = "ov9282", diff --git a/drivers/media/i2c/ov9640.c b/drivers/media/i2c/ov9640.c index a80fa59bf2ae8567226f1be8e0395d9fe06cd860..cbaea049531d24cb74c8f5c2ba25cd70868d7046 100644 --- a/drivers/media/i2c/ov9640.c +++ b/drivers/media/i2c/ov9640.c @@ -762,7 +762,7 @@ static struct i2c_driver ov9640_i2c_driver = { .driver = { .name = "ov9640", }, - .probe_new = ov9640_probe, + .probe = ov9640_probe, .remove = ov9640_remove, .id_table = ov9640_id, }; diff --git a/drivers/media/i2c/ov9650.c b/drivers/media/i2c/ov9650.c index 7e7cb1e4520e07b134809c59047e8e6ee397bb30..da1ab5135eaa1c84ef6f9b1b2bf40c0e4e6e62a0 100644 --- a/drivers/media/i2c/ov9650.c +++ b/drivers/media/i2c/ov9650.c @@ -1571,7 +1571,7 @@ static struct i2c_driver ov965x_i2c_driver = { .name = DRIVER_NAME, .of_match_table = of_match_ptr(ov965x_of_match), }, - .probe_new = ov965x_probe, + .probe = ov965x_probe, .remove = ov965x_remove, .id_table = ov965x_id, }; diff --git a/drivers/media/i2c/ov9734.c b/drivers/media/i2c/ov9734.c index 8b0a158cb297282d18ed1167188e54c49afaa9c5..b6244772bc5933b6c46309cef085fd922f0d65b7 100644 --- a/drivers/media/i2c/ov9734.c +++ b/drivers/media/i2c/ov9734.c @@ -1028,7 +1028,7 @@ static struct i2c_driver ov9734_i2c_driver = { .pm = &ov9734_pm_ops, .acpi_match_table = ov9734_acpi_ids, }, - .probe_new = ov9734_probe, + .probe = ov9734_probe, .remove = ov9734_remove, }; diff --git a/drivers/media/i2c/rdacm20.c b/drivers/media/i2c/rdacm20.c index a2263fa825b5905fc8cc8d23173e8d786acef893..01a2596282f0474bc34a414478367d48d6537225 100644 --- a/drivers/media/i2c/rdacm20.c +++ b/drivers/media/i2c/rdacm20.c @@ -676,7 +676,7 @@ static struct i2c_driver rdacm20_i2c_driver = { .name = "rdacm20", .of_match_table = rdacm20_of_ids, }, - .probe_new = rdacm20_probe, + .probe = rdacm20_probe, .remove = rdacm20_remove, .shutdown = rdacm20_shutdown, }; diff --git a/drivers/media/i2c/rdacm21.c b/drivers/media/i2c/rdacm21.c index 9ccc56c30d3b0acde7a12cdcd9f6a4a60de8882c..043fec778a5e5f935fdcc65ddceb2de82feac6d1 100644 --- a/drivers/media/i2c/rdacm21.c +++ b/drivers/media/i2c/rdacm21.c @@ -635,7 +635,7 @@ static struct i2c_driver rdacm21_i2c_driver = { .name = "rdacm21", .of_match_table = rdacm21_of_ids, }, - .probe_new = rdacm21_probe, + .probe = rdacm21_probe, .remove = rdacm21_remove, }; diff --git a/drivers/media/i2c/rj54n1cb0c.c b/drivers/media/i2c/rj54n1cb0c.c index 9db5473daba0c51f15c8f02154028aa51dcb173f..b430046f9e2a9fcab40132686c75f05325053fbc 100644 --- a/drivers/media/i2c/rj54n1cb0c.c +++ b/drivers/media/i2c/rj54n1cb0c.c @@ -1421,7 +1421,7 @@ static struct i2c_driver rj54n1_i2c_driver = { .driver = { .name = "rj54n1cb0c", }, - .probe_new = rj54n1_probe, + .probe = rj54n1_probe, .remove = rj54n1_remove, .id_table = rj54n1_id, }; diff --git a/drivers/media/i2c/s5c73m3/s5c73m3-core.c b/drivers/media/i2c/s5c73m3/s5c73m3-core.c index 7938a3327d3ee4eeb81ec042d0e00e74fe6b67d4..ed5b10731a14fd2d07e7895088a64d54e822e6fc 100644 --- a/drivers/media/i2c/s5c73m3/s5c73m3-core.c +++ b/drivers/media/i2c/s5c73m3/s5c73m3-core.c @@ -1729,7 +1729,7 @@ static struct i2c_driver s5c73m3_i2c_driver = { .of_match_table = of_match_ptr(s5c73m3_of_match), .name = DRIVER_NAME, }, - .probe_new = s5c73m3_probe, + .probe = s5c73m3_probe, .remove = s5c73m3_remove, .id_table = s5c73m3_id, }; diff --git a/drivers/media/i2c/s5k5baf.c b/drivers/media/i2c/s5k5baf.c index 960fbf6428ead580e422f7e1e7ad15d9fd0b7a71..67da2045f5431f03dd7130724f511e54f5d6c09e 100644 --- a/drivers/media/i2c/s5k5baf.c +++ b/drivers/media/i2c/s5k5baf.c @@ -2021,7 +2021,7 @@ static struct i2c_driver s5k5baf_i2c_driver = { .of_match_table = s5k5baf_of_match, .name = S5K5BAF_DRIVER_NAME }, - .probe_new = s5k5baf_probe, + .probe = s5k5baf_probe, .remove = s5k5baf_remove, .id_table = s5k5baf_id, }; diff --git a/drivers/media/i2c/s5k6a3.c b/drivers/media/i2c/s5k6a3.c index ef6673b1058011f1849ca593200ff242911b1b8a..b3560c8f8b4116504cf1cb58245d6dc2d97307eb 100644 --- a/drivers/media/i2c/s5k6a3.c +++ b/drivers/media/i2c/s5k6a3.c @@ -373,7 +373,7 @@ static struct i2c_driver s5k6a3_driver = { .of_match_table = of_match_ptr(s5k6a3_of_match), .name = S5K6A3_DRV_NAME, }, - .probe_new = s5k6a3_probe, + .probe = s5k6a3_probe, .remove = s5k6a3_remove, .id_table = s5k6a3_ids, }; diff --git a/drivers/media/i2c/saa6588.c b/drivers/media/i2c/saa6588.c index 8752f7cff611fa620ed4e59e7cdf2e7d73dfdeae..dea9fc09356fa5ee238080f75a837bc74cefd23e 100644 --- a/drivers/media/i2c/saa6588.c +++ b/drivers/media/i2c/saa6588.c @@ -505,7 +505,7 @@ static struct i2c_driver saa6588_driver = { .driver = { .name = "saa6588", }, - .probe_new = saa6588_probe, + .probe = saa6588_probe, .remove = saa6588_remove, .id_table = saa6588_id, }; diff --git a/drivers/media/i2c/saa6752hs.c b/drivers/media/i2c/saa6752hs.c index 892d64fe6e818bf04c164043fd3506bbd2ac3dcb..c106e7a7d1f4edeb974b2c382b426591e5e918dc 100644 --- a/drivers/media/i2c/saa6752hs.c +++ b/drivers/media/i2c/saa6752hs.c @@ -781,7 +781,7 @@ static struct i2c_driver saa6752hs_driver = { .driver = { .name = "saa6752hs", }, - .probe_new = saa6752hs_probe, + .probe = saa6752hs_probe, .remove = saa6752hs_remove, .id_table = saa6752hs_id, }; diff --git a/drivers/media/i2c/saa7110.c b/drivers/media/i2c/saa7110.c index b58e71517376ad15a9723ccf8f47c971b98874b7..1520790338ce27dd4650ee3df8522f096c4ab998 100644 --- a/drivers/media/i2c/saa7110.c +++ b/drivers/media/i2c/saa7110.c @@ -448,7 +448,7 @@ static struct i2c_driver saa7110_driver = { .driver = { .name = "saa7110", }, - .probe_new = saa7110_probe, + .probe = saa7110_probe, .remove = saa7110_remove, .id_table = saa7110_id, }; diff --git a/drivers/media/i2c/saa7115.c b/drivers/media/i2c/saa7115.c index efeda3956f81283c4ec0e538f345318e8ab76e65..a1c71187e773ffd74cb0c0cf57247d65352d507f 100644 --- a/drivers/media/i2c/saa7115.c +++ b/drivers/media/i2c/saa7115.c @@ -1951,7 +1951,7 @@ static struct i2c_driver saa711x_driver = { .driver = { .name = "saa7115", }, - .probe_new = saa711x_probe, + .probe = saa711x_probe, .remove = saa711x_remove, .id_table = saa711x_id, }; diff --git a/drivers/media/i2c/saa7127.c b/drivers/media/i2c/saa7127.c index f98f3a1c38a9d95d92d93592910be3e82d604928..818ed19cf37b540895b591f3f59ac94947b8d569 100644 --- a/drivers/media/i2c/saa7127.c +++ b/drivers/media/i2c/saa7127.c @@ -810,7 +810,7 @@ static struct i2c_driver saa7127_driver = { .driver = { .name = "saa7127", }, - .probe_new = saa7127_probe, + .probe = saa7127_probe, .remove = saa7127_remove, .id_table = saa7127_id, }; diff --git a/drivers/media/i2c/saa717x.c b/drivers/media/i2c/saa717x.c index df01059076faf51b1a54bb96f1adee30ac2921ee..933ec0171430c2ecef2725de1ac17065c8f8e753 100644 --- a/drivers/media/i2c/saa717x.c +++ b/drivers/media/i2c/saa717x.c @@ -1343,7 +1343,7 @@ static struct i2c_driver saa717x_driver = { .driver = { .name = "saa717x", }, - .probe_new = saa717x_probe, + .probe = saa717x_probe, .remove = saa717x_remove, .id_table = saa717x_id, }; diff --git a/drivers/media/i2c/saa7185.c b/drivers/media/i2c/saa7185.c index c78f2e95ba37c96419f30bcd172b2359000f3ea9..5535d71f4860cac98f5ccc062637f652c7e91059 100644 --- a/drivers/media/i2c/saa7185.c +++ b/drivers/media/i2c/saa7185.c @@ -343,7 +343,7 @@ static struct i2c_driver saa7185_driver = { .driver = { .name = "saa7185", }, - .probe_new = saa7185_probe, + .probe = saa7185_probe, .remove = saa7185_remove, .id_table = saa7185_id, }; diff --git a/drivers/media/i2c/sony-btf-mpx.c b/drivers/media/i2c/sony-btf-mpx.c index eef6c8a7c9c95020c03ad70d9c6132e0fe82952f..0f53834f3ae4dad19535b959945b58cd990ad9aa 100644 --- a/drivers/media/i2c/sony-btf-mpx.c +++ b/drivers/media/i2c/sony-btf-mpx.c @@ -375,7 +375,7 @@ static struct i2c_driver sony_btf_mpx_driver = { .driver = { .name = "sony-btf-mpx", }, - .probe_new = sony_btf_mpx_probe, + .probe = sony_btf_mpx_probe, .remove = sony_btf_mpx_remove, .id_table = sony_btf_mpx_id, }; diff --git a/drivers/media/i2c/st-mipid02.c b/drivers/media/i2c/st-mipid02.c index 31b89aff0e86a0621ec9fba146f18ed35c147abc..906553a28676df1a28ed1d30bdf958b9cd4a5715 100644 --- a/drivers/media/i2c/st-mipid02.c +++ b/drivers/media/i2c/st-mipid02.c @@ -736,8 +736,13 @@ static void mipid02_set_fmt_source(struct v4l2_subdev *sd, { struct mipid02_dev *bridge = to_mipid02_dev(sd); - /* source pad mirror active sink pad */ - format->format = bridge->fmt; + /* source pad mirror sink pad */ + if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE) + format->format = bridge->fmt; + else + format->format = *v4l2_subdev_get_try_format(sd, sd_state, + MIPID02_SINK_0); + /* but code may need to be converted */ format->format.code = serial_to_parallel_code(format->format.code); @@ -745,7 +750,8 @@ static void mipid02_set_fmt_source(struct v4l2_subdev *sd, if (format->which != V4L2_SUBDEV_FORMAT_TRY) return; - *v4l2_subdev_get_try_format(sd, sd_state, format->pad) = format->format; + *v4l2_subdev_get_try_format(sd, sd_state, MIPID02_SOURCE) = + format->format; } static void mipid02_set_fmt_sink(struct v4l2_subdev *sd, @@ -763,6 +769,9 @@ static void mipid02_set_fmt_sink(struct v4l2_subdev *sd, fmt = &bridge->fmt; *fmt = format->format; + + /* Propagate the format change to the source pad */ + mipid02_set_fmt_source(sd, sd_state, format); } static int mipid02_set_fmt(struct v4l2_subdev *sd, @@ -1091,7 +1100,7 @@ static struct i2c_driver mipid02_i2c_driver = { .name = "st-mipid02", .of_match_table = mipid02_dt_ids, }, - .probe_new = mipid02_probe, + .probe = mipid02_probe, .remove = mipid02_remove, }; diff --git a/drivers/media/i2c/st-vgxy61.c b/drivers/media/i2c/st-vgxy61.c index adbd093ad190fc3ae90b569c092fe48066c91aec..30f82ca344c44657a7549de7f93d17790908382f 100644 --- a/drivers/media/i2c/st-vgxy61.c +++ b/drivers/media/i2c/st-vgxy61.c @@ -1951,7 +1951,7 @@ static struct i2c_driver vgxy61_i2c_driver = { .of_match_table = vgxy61_dt_ids, .pm = &vgxy61_pm_ops, }, - .probe_new = vgxy61_probe, + .probe = vgxy61_probe, .remove = vgxy61_remove, }; diff --git a/drivers/media/i2c/tc358743.c b/drivers/media/i2c/tc358743.c index 9197fa0b1bc2a62d0588651b8476e4834c654aba..15f8163be9bf2970f42e9ce4ac7c57a8ce28e627 100644 --- a/drivers/media/i2c/tc358743.c +++ b/drivers/media/i2c/tc358743.c @@ -2206,7 +2206,7 @@ static struct i2c_driver tc358743_driver = { .name = "tc358743", .of_match_table = of_match_ptr(tc358743_of_match), }, - .probe_new = tc358743_probe, + .probe = tc358743_probe, .remove = tc358743_remove, .id_table = tc358743_id, }; diff --git a/drivers/media/i2c/tc358746.c b/drivers/media/i2c/tc358746.c index ec1a193ba161a3594f098c94faff47437b924743..e9b2d906c1770d61d7339e2aaa90e5f0edbb1570 100644 --- a/drivers/media/i2c/tc358746.c +++ b/drivers/media/i2c/tc358746.c @@ -1686,7 +1686,7 @@ static struct i2c_driver tc358746_driver = { .pm = pm_ptr(&tc358746_pm_ops), .of_match_table = tc358746_of_match, }, - .probe_new = tc358746_probe, + .probe = tc358746_probe, .remove = tc358746_remove, }; diff --git a/drivers/media/i2c/tda1997x.c b/drivers/media/i2c/tda1997x.c index 27f6393dc3277de31b3f0c4b442df5ed4df1a57f..325e99125941642d6a55864354d54049ab699fd5 100644 --- a/drivers/media/i2c/tda1997x.c +++ b/drivers/media/i2c/tda1997x.c @@ -2834,7 +2834,7 @@ static struct i2c_driver tda1997x_i2c_driver = { .name = "tda1997x", .of_match_table = of_match_ptr(tda1997x_of_id), }, - .probe_new = tda1997x_probe, + .probe = tda1997x_probe, .remove = tda1997x_remove, .id_table = tda1997x_i2c_id, }; diff --git a/drivers/media/i2c/tda7432.c b/drivers/media/i2c/tda7432.c index bbceaac8e0b327055da630545379a70ff3296136..6ecdc8e2e0c6600943576f28f188a96a3f891530 100644 --- a/drivers/media/i2c/tda7432.c +++ b/drivers/media/i2c/tda7432.c @@ -409,7 +409,7 @@ static struct i2c_driver tda7432_driver = { .driver = { .name = "tda7432", }, - .probe_new = tda7432_probe, + .probe = tda7432_probe, .remove = tda7432_remove, .id_table = tda7432_id, }; diff --git a/drivers/media/i2c/tda9840.c b/drivers/media/i2c/tda9840.c index 25fbd7e3950ef2150e027a22c084c604deb4aac1..1911ef2126be3639120a028916cb4fd6cb38573e 100644 --- a/drivers/media/i2c/tda9840.c +++ b/drivers/media/i2c/tda9840.c @@ -191,7 +191,7 @@ static struct i2c_driver tda9840_driver = { .driver = { .name = "tda9840", }, - .probe_new = tda9840_probe, + .probe = tda9840_probe, .remove = tda9840_remove, .id_table = tda9840_id, }; diff --git a/drivers/media/i2c/tea6415c.c b/drivers/media/i2c/tea6415c.c index d375d2d243544bad32f693ed7feb9b12ede2f488..3ed6e441d515319f87d90f2ab369e395a3092955 100644 --- a/drivers/media/i2c/tea6415c.c +++ b/drivers/media/i2c/tea6415c.c @@ -150,7 +150,7 @@ static struct i2c_driver tea6415c_driver = { .driver = { .name = "tea6415c", }, - .probe_new = tea6415c_probe, + .probe = tea6415c_probe, .remove = tea6415c_remove, .id_table = tea6415c_id, }; diff --git a/drivers/media/i2c/tea6420.c b/drivers/media/i2c/tea6420.c index 9da1f3b02c578389f3573c410b6bfa1a2f2de909..63f23784bb41da0421a18ce48611ee3a82312918 100644 --- a/drivers/media/i2c/tea6420.c +++ b/drivers/media/i2c/tea6420.c @@ -132,7 +132,7 @@ static struct i2c_driver tea6420_driver = { .driver = { .name = "tea6420", }, - .probe_new = tea6420_probe, + .probe = tea6420_probe, .remove = tea6420_remove, .id_table = tea6420_id, }; diff --git a/drivers/media/i2c/ths7303.c b/drivers/media/i2c/ths7303.c index 67de90cf696ebc43121054fe2a6f03ae6b68b4fc..ea70c1c13872af3f59e183bbeb352f7872c9c31c 100644 --- a/drivers/media/i2c/ths7303.c +++ b/drivers/media/i2c/ths7303.c @@ -376,7 +376,7 @@ static struct i2c_driver ths7303_driver = { .driver = { .name = "ths73x3", }, - .probe_new = ths7303_probe, + .probe = ths7303_probe, .remove = ths7303_remove, .id_table = ths7303_id, }; diff --git a/drivers/media/i2c/ths8200.c b/drivers/media/i2c/ths8200.c index 081ef5a4b950b9206be7fd20ac166384feb27d39..0e0f676cd221630501e61f3db8cbaa19952ace80 100644 --- a/drivers/media/i2c/ths8200.c +++ b/drivers/media/i2c/ths8200.c @@ -499,7 +499,7 @@ static struct i2c_driver ths8200_driver = { .name = "ths8200", .of_match_table = of_match_ptr(ths8200_of_match), }, - .probe_new = ths8200_probe, + .probe = ths8200_probe, .remove = ths8200_remove, .id_table = ths8200_id, }; diff --git a/drivers/media/i2c/tlv320aic23b.c b/drivers/media/i2c/tlv320aic23b.c index 47198e803817baf63b4f662dad98be95618f3642..d800ff8af1ffee87d870e44a8dfc5d18ce6644e8 100644 --- a/drivers/media/i2c/tlv320aic23b.c +++ b/drivers/media/i2c/tlv320aic23b.c @@ -197,7 +197,7 @@ static struct i2c_driver tlv320aic23b_driver = { .driver = { .name = "tlv320aic23b", }, - .probe_new = tlv320aic23b_probe, + .probe = tlv320aic23b_probe, .remove = tlv320aic23b_remove, .id_table = tlv320aic23b_id, }; diff --git a/drivers/media/i2c/tvaudio.c b/drivers/media/i2c/tvaudio.c index a54c76d9e23b98b421f60948895059e66150d62d..ba20f35cafd5c1db7f4cef488232d76a696e87df 100644 --- a/drivers/media/i2c/tvaudio.c +++ b/drivers/media/i2c/tvaudio.c @@ -2095,7 +2095,7 @@ static struct i2c_driver tvaudio_driver = { .driver = { .name = "tvaudio", }, - .probe_new = tvaudio_probe, + .probe = tvaudio_probe, .remove = tvaudio_remove, .id_table = tvaudio_id, }; diff --git a/drivers/media/i2c/tvp514x.c b/drivers/media/i2c/tvp514x.c index f294cae72b01a498d01fa59eda7ccf29de832643..aa6d4b67b6d50be0d1b08083b17498d44b914bb8 100644 --- a/drivers/media/i2c/tvp514x.c +++ b/drivers/media/i2c/tvp514x.c @@ -1208,7 +1208,7 @@ static struct i2c_driver tvp514x_driver = { .of_match_table = of_match_ptr(tvp514x_of_match), .name = TVP514X_MODULE_NAME, }, - .probe_new = tvp514x_probe, + .probe = tvp514x_probe, .remove = tvp514x_remove, .id_table = tvp514x_id, }; diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c index 859f1cb2fa7446b2df255409b37ded90ff8bbabe..c7fb35ee3f9de748c88f69c407930dbbed549949 100644 --- a/drivers/media/i2c/tvp5150.c +++ b/drivers/media/i2c/tvp5150.c @@ -2280,7 +2280,7 @@ static struct i2c_driver tvp5150_driver = { .name = "tvp5150", .pm = &tvp5150_pm_ops, }, - .probe_new = tvp5150_probe, + .probe = tvp5150_probe, .remove = tvp5150_remove, .id_table = tvp5150_id, }; diff --git a/drivers/media/i2c/tvp7002.c b/drivers/media/i2c/tvp7002.c index 4ccd218f5584e37cbca1ce740f470464d40dec7d..a2d7bc79984930b9bb9397980baf79482d05d08c 100644 --- a/drivers/media/i2c/tvp7002.c +++ b/drivers/media/i2c/tvp7002.c @@ -1079,7 +1079,7 @@ static struct i2c_driver tvp7002_driver = { .of_match_table = of_match_ptr(tvp7002_of_match), .name = TVP7002_MODULE_NAME, }, - .probe_new = tvp7002_probe, + .probe = tvp7002_probe, .remove = tvp7002_remove, .id_table = tvp7002_id, }; diff --git a/drivers/media/i2c/tw2804.c b/drivers/media/i2c/tw2804.c index 710790ece11bc91daeaab4bd59646a6daef25b68..6a2521e3a25c2e480af523eb9fecc32c682c9bae 100644 --- a/drivers/media/i2c/tw2804.c +++ b/drivers/media/i2c/tw2804.c @@ -423,7 +423,7 @@ static struct i2c_driver tw2804_driver = { .driver = { .name = "tw2804", }, - .probe_new = tw2804_probe, + .probe = tw2804_probe, .remove = tw2804_remove, .id_table = tw2804_id, }; diff --git a/drivers/media/i2c/tw9903.c b/drivers/media/i2c/tw9903.c index 428ee55787e1858259c678532ed9cd87dc855a20..996be3960af3f80e1b17f5e836f431d2e2208a60 100644 --- a/drivers/media/i2c/tw9903.c +++ b/drivers/media/i2c/tw9903.c @@ -254,7 +254,7 @@ static struct i2c_driver tw9903_driver = { .driver = { .name = "tw9903", }, - .probe_new = tw9903_probe, + .probe = tw9903_probe, .remove = tw9903_remove, .id_table = tw9903_id, }; diff --git a/drivers/media/i2c/tw9906.c b/drivers/media/i2c/tw9906.c index 7824ed9b04ed6c1360135bde5b91a3ed304f35d0..25c625f6d6e488f3c327a68f9e3f72be1d611733 100644 --- a/drivers/media/i2c/tw9906.c +++ b/drivers/media/i2c/tw9906.c @@ -222,7 +222,7 @@ static struct i2c_driver tw9906_driver = { .driver = { .name = "tw9906", }, - .probe_new = tw9906_probe, + .probe = tw9906_probe, .remove = tw9906_remove, .id_table = tw9906_id, }; diff --git a/drivers/media/i2c/tw9910.c b/drivers/media/i2c/tw9910.c index 459fa22f434114d4a6468c31b32ce2dd328c5449..477a64d8f8ab6f81f423c2f797987655ae4bdf17 100644 --- a/drivers/media/i2c/tw9910.c +++ b/drivers/media/i2c/tw9910.c @@ -1012,7 +1012,7 @@ static struct i2c_driver tw9910_i2c_driver = { .driver = { .name = "tw9910", }, - .probe_new = tw9910_probe, + .probe = tw9910_probe, .remove = tw9910_remove, .id_table = tw9910_id, }; diff --git a/drivers/media/i2c/uda1342.c b/drivers/media/i2c/uda1342.c index b6873d8662728403f0a52afd1657877ee54f281e..da7bc4700bed4cdfd5df9c6bb4550d2754b0f7ed 100644 --- a/drivers/media/i2c/uda1342.c +++ b/drivers/media/i2c/uda1342.c @@ -88,7 +88,7 @@ static struct i2c_driver uda1342_driver = { .driver = { .name = "uda1342", }, - .probe_new = uda1342_probe, + .probe = uda1342_probe, .remove = uda1342_remove, .id_table = uda1342_id, }; diff --git a/drivers/media/i2c/upd64031a.c b/drivers/media/i2c/upd64031a.c index 47eed3aab060a595f0868c0e169a00582828d85f..54c2ba0ba375f48bab3e33467e68f74d792051f8 100644 --- a/drivers/media/i2c/upd64031a.c +++ b/drivers/media/i2c/upd64031a.c @@ -228,7 +228,7 @@ static struct i2c_driver upd64031a_driver = { .driver = { .name = "upd64031a", }, - .probe_new = upd64031a_probe, + .probe = upd64031a_probe, .remove = upd64031a_remove, .id_table = upd64031a_id, }; diff --git a/drivers/media/i2c/upd64083.c b/drivers/media/i2c/upd64083.c index 3f5a7d4853a129f29f11957a5bf2376548925ea1..2a820589a4cb54e9187627b6352368202e17ca73 100644 --- a/drivers/media/i2c/upd64083.c +++ b/drivers/media/i2c/upd64083.c @@ -199,7 +199,7 @@ static struct i2c_driver upd64083_driver = { .driver = { .name = "upd64083", }, - .probe_new = upd64083_probe, + .probe = upd64083_probe, .remove = upd64083_remove, .id_table = upd64083_id, }; diff --git a/drivers/media/i2c/video-i2c.c b/drivers/media/i2c/video-i2c.c index dddf9827b3140a832e3276e81a15ad5fb6a8636a..6f98abc7ccc1d5397b1330d8e6557144f80edc73 100644 --- a/drivers/media/i2c/video-i2c.c +++ b/drivers/media/i2c/video-i2c.c @@ -274,7 +274,7 @@ static const struct hwmon_channel_info amg88xx_temp = { .config = amg88xx_temp_config, }; -static const struct hwmon_channel_info *amg88xx_info[] = { +static const struct hwmon_channel_info * const amg88xx_info[] = { &amg88xx_temp, NULL }; @@ -959,7 +959,7 @@ static struct i2c_driver video_i2c_driver = { .of_match_table = video_i2c_of_match, .pm = &video_i2c_pm_ops, }, - .probe_new = video_i2c_probe, + .probe = video_i2c_probe, .remove = video_i2c_remove, .id_table = video_i2c_id_table, }; diff --git a/drivers/media/i2c/vp27smpx.c b/drivers/media/i2c/vp27smpx.c index ed1c58ea8ed33dbb5bab8c4756d9e7aa1a4e0bfb..0ba3c2b6803761730dac433da417f182d8f49ca2 100644 --- a/drivers/media/i2c/vp27smpx.c +++ b/drivers/media/i2c/vp27smpx.c @@ -181,7 +181,7 @@ static struct i2c_driver vp27smpx_driver = { .driver = { .name = "vp27smpx", }, - .probe_new = vp27smpx_probe, + .probe = vp27smpx_probe, .remove = vp27smpx_remove, .id_table = vp27smpx_id, }; diff --git a/drivers/media/i2c/vpx3220.c b/drivers/media/i2c/vpx3220.c index aa73d5dcc3e7325b50667aedfb64bb6c47b4e9ec..1eaae886f217ad8a994e09ef7b231e3a518d792f 100644 --- a/drivers/media/i2c/vpx3220.c +++ b/drivers/media/i2c/vpx3220.c @@ -546,7 +546,7 @@ static struct i2c_driver vpx3220_driver = { .driver = { .name = "vpx3220", }, - .probe_new = vpx3220_probe, + .probe = vpx3220_probe, .remove = vpx3220_remove, .id_table = vpx3220_id, }; diff --git a/drivers/media/i2c/wm8739.c b/drivers/media/i2c/wm8739.c index 8b34a673ffd3e3327b8f5accb9403e34c731dd60..19bf7a00dff9de6e6c20c9afb4471a10b688420a 100644 --- a/drivers/media/i2c/wm8739.c +++ b/drivers/media/i2c/wm8739.c @@ -252,7 +252,7 @@ static struct i2c_driver wm8739_driver = { .driver = { .name = "wm8739", }, - .probe_new = wm8739_probe, + .probe = wm8739_probe, .remove = wm8739_remove, .id_table = wm8739_id, }; diff --git a/drivers/media/i2c/wm8775.c b/drivers/media/i2c/wm8775.c index 56d98518f7eb80a69f894e55475fb193861f7d4c..d1b716fd6f1192c923421ae9776d039eff2a9a6f 100644 --- a/drivers/media/i2c/wm8775.c +++ b/drivers/media/i2c/wm8775.c @@ -298,7 +298,7 @@ static struct i2c_driver wm8775_driver = { .driver = { .name = "wm8775", }, - .probe_new = wm8775_probe, + .probe = wm8775_probe, .remove = wm8775_remove, .id_table = wm8775_id, }; diff --git a/drivers/media/mc/mc-entity.c b/drivers/media/mc/mc-entity.c index e7216a985ba6278525f855f0d6d78ce4cf8c6926..83468d4a440b3546c53ce4da2b3337018af6f7cf 100644 --- a/drivers/media/mc/mc-entity.c +++ b/drivers/media/mc/mc-entity.c @@ -1052,25 +1052,19 @@ static void __media_entity_remove_link(struct media_entity *entity, kfree(link); } -int media_get_pad_index(struct media_entity *entity, bool is_sink, +int media_get_pad_index(struct media_entity *entity, u32 pad_type, enum media_pad_signal_type sig_type) { - int i; - bool pad_is_sink; + unsigned int i; if (!entity) return -EINVAL; for (i = 0; i < entity->num_pads; i++) { - if (entity->pads[i].flags & MEDIA_PAD_FL_SINK) - pad_is_sink = true; - else if (entity->pads[i].flags & MEDIA_PAD_FL_SOURCE) - pad_is_sink = false; - else - continue; /* This is an error! */ - - if (pad_is_sink != is_sink) + if ((entity->pads[i].flags & + (MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_SOURCE)) != pad_type) continue; + if (entity->pads[i].sig_type == sig_type) return i; } @@ -1416,7 +1410,7 @@ struct media_pad *media_pad_remote_pad_unique(const struct media_pad *pad) EXPORT_SYMBOL_GPL(media_pad_remote_pad_unique); int media_entity_get_fwnode_pad(struct media_entity *entity, - struct fwnode_handle *fwnode, + const struct fwnode_handle *fwnode, unsigned long direction_flags) { struct fwnode_endpoint endpoint; diff --git a/drivers/media/pci/bt8xx/dst_ca.c b/drivers/media/pci/bt8xx/dst_ca.c index 85fcdc59f0d182d499d3639bb664e04f64779349..d234a0f404d68a87fdeee5e7530fa7eb81fad904 100644 --- a/drivers/media/pci/bt8xx/dst_ca.c +++ b/drivers/media/pci/bt8xx/dst_ca.c @@ -534,7 +534,7 @@ static long dst_ca_ioctl(struct file *file, unsigned int cmd, unsigned long ioct mutex_lock(&dst_ca_mutex); dvbdev = file->private_data; - state = (struct dst_state *)dvbdev->priv; + state = dvbdev->priv; p_ca_message = kmalloc(sizeof (struct ca_msg), GFP_KERNEL); p_ca_slot_info = kmalloc(sizeof (struct ca_slot_info), GFP_KERNEL); p_ca_caps = kmalloc(sizeof (struct ca_caps), GFP_KERNEL); diff --git a/drivers/media/pci/cx18/cx18-av-vbi.c b/drivers/media/pci/cx18/cx18-av-vbi.c index a0d465924e75e30753f367c0b79ee1086c480e3a..65281d40c681363740e8480749da40e2ee0ec85c 100644 --- a/drivers/media/pci/cx18/cx18-av-vbi.c +++ b/drivers/media/pci/cx18/cx18-av-vbi.c @@ -51,7 +51,7 @@ struct vbi_anc_data { u8 sdid; u8 data_count; u8 idid[2]; - u8 payload[1]; /* data_count of payload */ + u8 payload[]; /* data_count of payload */ /* u8 checksum; */ /* u8 fill[]; Variable number of fill bytes */ }; diff --git a/drivers/media/pci/cx18/cx18-dvb.c b/drivers/media/pci/cx18/cx18-dvb.c index 33e5a5b5fab41e70dea891644183a633d1a9fc5c..cf82360a503d274b12d2b341a32dd4b48073dc23 100644 --- a/drivers/media/pci/cx18/cx18-dvb.c +++ b/drivers/media/pci/cx18/cx18-dvb.c @@ -234,7 +234,7 @@ static int dvb_register(struct cx18_stream *stream); static int cx18_dvb_start_feed(struct dvb_demux_feed *feed) { struct dvb_demux *demux = feed->demux; - struct cx18_stream *stream = (struct cx18_stream *) demux->priv; + struct cx18_stream *stream = demux->priv; struct cx18 *cx; int ret; u32 v; @@ -305,7 +305,7 @@ static int cx18_dvb_start_feed(struct dvb_demux_feed *feed) static int cx18_dvb_stop_feed(struct dvb_demux_feed *feed) { struct dvb_demux *demux = feed->demux; - struct cx18_stream *stream = (struct cx18_stream *)demux->priv; + struct cx18_stream *stream = demux->priv; struct cx18 *cx; int ret = -EINVAL; diff --git a/drivers/media/pci/dm1105/Kconfig b/drivers/media/pci/dm1105/Kconfig index e0e3af67c99c07ad9793ee792ceb5e28590de25b..4498c37f4990fb355952fb31fd619d37bb78c802 100644 --- a/drivers/media/pci/dm1105/Kconfig +++ b/drivers/media/pci/dm1105/Kconfig @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0-only config DVB_DM1105 tristate "SDMC DM1105 based PCI cards" - depends on DVB_CORE && PCI && I2C && I2C_ALGOBIT + depends on DVB_CORE && PCI && I2C && I2C_ALGOBIT && HAS_IOPORT select DVB_PLL if MEDIA_SUBDRV_AUTOSELECT select DVB_STV0299 if MEDIA_SUBDRV_AUTOSELECT select DVB_STV0288 if MEDIA_SUBDRV_AUTOSELECT diff --git a/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c b/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c index 3c84cb12163207a076fff56de7813485ca48fb71..34984a7474ed8b25841d5b2d8984095a6c331b61 100644 --- a/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c +++ b/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c @@ -1375,7 +1375,8 @@ struct sensor_async_subdev { struct csi2_bus_info csi2; }; -#define to_sensor_asd(asd) container_of(asd, struct sensor_async_subdev, asd) +#define to_sensor_asd(__asd) \ + container_of_const(__asd, struct sensor_async_subdev, asd) /* The .bound() notifier callback when a match is found */ static int cio2_notifier_bound(struct v4l2_async_notifier *notifier, @@ -1417,31 +1418,27 @@ static int cio2_notifier_complete(struct v4l2_async_notifier *notifier) struct sensor_async_subdev *s_asd; struct v4l2_async_subdev *asd; struct cio2_queue *q; - unsigned int pad; int ret; list_for_each_entry(asd, &cio2->notifier.asd_list, asd_list) { s_asd = to_sensor_asd(asd); q = &cio2->queue[s_asd->csi2.port]; - for (pad = 0; pad < q->sensor->entity.num_pads; pad++) - if (q->sensor->entity.pads[pad].flags & - MEDIA_PAD_FL_SOURCE) - break; - - if (pad == q->sensor->entity.num_pads) { - dev_err(dev, "failed to find src pad for %s\n", - q->sensor->name); - return -ENXIO; + ret = media_entity_get_fwnode_pad(&q->sensor->entity, + s_asd->asd.match.fwnode, + MEDIA_PAD_FL_SOURCE); + if (ret < 0) { + dev_err(dev, "no pad for endpoint %pfw (%d)\n", + s_asd->asd.match.fwnode, ret); + return ret; } - ret = media_create_pad_link( - &q->sensor->entity, pad, - &q->subdev.entity, CIO2_PAD_SINK, - 0); + ret = media_create_pad_link(&q->sensor->entity, ret, + &q->subdev.entity, CIO2_PAD_SINK, + 0); if (ret) { - dev_err(dev, "failed to create link for %s\n", - q->sensor->name); + dev_err(dev, "failed to create link for %s (endpoint %pfw, error %d)\n", + q->sensor->name, s_asd->asd.match.fwnode, ret); return ret; } } diff --git a/drivers/media/pci/saa7164/saa7164-dvb.c b/drivers/media/pci/saa7164/saa7164-dvb.c index 24421c116b0bdf736b99f9c4d57f8994a7549ee6..3eb749db1ca76163c1b16578ce858a4b54a4e82f 100644 --- a/drivers/media/pci/saa7164/saa7164-dvb.c +++ b/drivers/media/pci/saa7164/saa7164-dvb.c @@ -280,7 +280,7 @@ static int saa7164_dvb_start_port(struct saa7164_port *port) static int saa7164_dvb_start_feed(struct dvb_demux_feed *feed) { struct dvb_demux *demux = feed->demux; - struct saa7164_port *port = (struct saa7164_port *) demux->priv; + struct saa7164_port *port = demux->priv; struct saa7164_dvb *dvb = &port->dvb; struct saa7164_dev *dev = port->dev; int ret = 0; @@ -307,7 +307,7 @@ static int saa7164_dvb_start_feed(struct dvb_demux_feed *feed) static int saa7164_dvb_stop_feed(struct dvb_demux_feed *feed) { struct dvb_demux *demux = feed->demux; - struct saa7164_port *port = (struct saa7164_port *) demux->priv; + struct saa7164_port *port = demux->priv; struct saa7164_dvb *dvb = &port->dvb; struct saa7164_dev *dev = port->dev; int ret = 0; diff --git a/drivers/media/pci/ttpci/budget-core.c b/drivers/media/pci/ttpci/budget-core.c index 5d5796f244695028489df76a3df78ccda5373c33..710595987522b5fd4b1110cd3f1e81d5f8f7b3a8 100644 --- a/drivers/media/pci/ttpci/budget-core.c +++ b/drivers/media/pci/ttpci/budget-core.c @@ -308,7 +308,7 @@ int ttpci_budget_debiwrite(struct budget *budget, u32 config, int addr, static int budget_start_feed(struct dvb_demux_feed *feed) { struct dvb_demux *demux = feed->demux; - struct budget *budget = (struct budget *) demux->priv; + struct budget *budget = demux->priv; int status = 0; dprintk(2, "budget: %p\n", budget); @@ -327,7 +327,7 @@ static int budget_start_feed(struct dvb_demux_feed *feed) static int budget_stop_feed(struct dvb_demux_feed *feed) { struct dvb_demux *demux = feed->demux; - struct budget *budget = (struct budget *) demux->priv; + struct budget *budget = demux->priv; int status = 0; dprintk(2, "budget: %p\n", budget); diff --git a/drivers/media/pci/tw686x/tw686x-audio.c b/drivers/media/pci/tw686x/tw686x-audio.c index 74cba1368cfa5f4e454f505df2701d614b120218..1ae3845b6743e2e54f074a011763ede60c481586 100644 --- a/drivers/media/pci/tw686x/tw686x-audio.c +++ b/drivers/media/pci/tw686x/tw686x-audio.c @@ -59,7 +59,7 @@ void tw686x_audio_irq(struct tw686x_dev *dev, unsigned long requests, } spin_unlock_irqrestore(&ac->lock, flags); - if (!done || !next) + if (!done) continue; /* * Checking for a non-nil dma_desc[pb]->virt buffer is diff --git a/drivers/media/platform/amphion/vdec.c b/drivers/media/platform/amphion/vdec.c index 3fa1a74a2e2047fcc9928bf703385315ee8b7895..6515f3cdb7a74f1446248636894afe2665657a58 100644 --- a/drivers/media/platform/amphion/vdec.c +++ b/drivers/media/platform/amphion/vdec.c @@ -279,6 +279,7 @@ static void vdec_handle_resolution_change(struct vpu_inst *inst) vdec->source_change--; vpu_notify_source_change(inst); + vpu_set_last_buffer_dequeued(inst, false); } static int vdec_update_state(struct vpu_inst *inst, enum vpu_codec_state state, u32 force) @@ -314,7 +315,7 @@ static void vdec_set_last_buffer_dequeued(struct vpu_inst *inst) return; if (vdec->eos_received) { - if (!vpu_set_last_buffer_dequeued(inst)) { + if (!vpu_set_last_buffer_dequeued(inst, true)) { vdec->eos_received--; vdec_update_state(inst, VPU_CODEC_STATE_DRAIN, 0); } @@ -569,7 +570,7 @@ static int vdec_drain(struct vpu_inst *inst) return 0; if (!vdec->params.frame_count) { - vpu_set_last_buffer_dequeued(inst); + vpu_set_last_buffer_dequeued(inst, true); return 0; } @@ -608,7 +609,7 @@ static int vdec_cmd_stop(struct vpu_inst *inst) vpu_trace(inst->dev, "[%d]\n", inst->id); if (inst->state == VPU_CODEC_STATE_DEINIT) { - vpu_set_last_buffer_dequeued(inst); + vpu_set_last_buffer_dequeued(inst, true); } else { vdec->drain = 1; vdec_drain(inst); diff --git a/drivers/media/platform/amphion/venc.c b/drivers/media/platform/amphion/venc.c index e6e8fe45fc7c3e2b7cb5fdaf4f22bd67ef98a0c7..58480e2755ec4923597b955b41286509f7b4cfa7 100644 --- a/drivers/media/platform/amphion/venc.c +++ b/drivers/media/platform/amphion/venc.c @@ -458,7 +458,7 @@ static int venc_encoder_cmd(struct file *file, void *fh, struct v4l2_encoder_cmd vpu_inst_lock(inst); if (cmd->cmd == V4L2_ENC_CMD_STOP) { if (inst->state == VPU_CODEC_STATE_DEINIT) - vpu_set_last_buffer_dequeued(inst); + vpu_set_last_buffer_dequeued(inst, true); else venc_request_eos(inst); } @@ -878,7 +878,7 @@ static void venc_set_last_buffer_dequeued(struct vpu_inst *inst) struct venc_t *venc = inst->priv; if (venc->stopped && list_empty(&venc->frames)) - vpu_set_last_buffer_dequeued(inst); + vpu_set_last_buffer_dequeued(inst, true); } static void venc_stop_done(struct vpu_inst *inst) diff --git a/drivers/media/platform/amphion/vpu_core.c b/drivers/media/platform/amphion/vpu_core.c index de23627a119a0977fc346ecd1a6431651c0379c3..43d85a54268bcb4ef533bff113f17835dc69ec59 100644 --- a/drivers/media/platform/amphion/vpu_core.c +++ b/drivers/media/platform/amphion/vpu_core.c @@ -254,7 +254,7 @@ static int vpu_core_register(struct device *dev, struct vpu_core *core) if (vpu_core_is_exist(vpu, core)) return 0; - core->workqueue = alloc_workqueue("vpu", WQ_UNBOUND | WQ_MEM_RECLAIM, 1); + core->workqueue = alloc_ordered_workqueue("vpu", WQ_MEM_RECLAIM); if (!core->workqueue) { dev_err(core->dev, "fail to alloc workqueue\n"); return -ENOMEM; diff --git a/drivers/media/platform/amphion/vpu_malone.c b/drivers/media/platform/amphion/vpu_malone.c index ef44bff9fbaf633fa3bb6db415388786856bbbe4..c1d6606ad7e57d1cd4c0364dae0488d8e8823e71 100644 --- a/drivers/media/platform/amphion/vpu_malone.c +++ b/drivers/media/platform/amphion/vpu_malone.c @@ -1313,6 +1313,15 @@ static int vpu_malone_insert_scode_pic(struct malone_scode_t *scode, u32 codec_i return sizeof(hdr); } +static int vpu_malone_insert_scode_vc1_g_seq(struct malone_scode_t *scode) +{ + if (!scode->inst->total_input_count) + return 0; + if (vpu_vb_is_codecconfig(to_vb2_v4l2_buffer(scode->vb))) + scode->need_data = 0; + return 0; +} + static int vpu_malone_insert_scode_vc1_g_pic(struct malone_scode_t *scode) { struct vb2_v4l2_buffer *vbuf; @@ -1344,6 +1353,8 @@ static int vpu_malone_insert_scode_vc1_l_seq(struct malone_scode_t *scode) int size = 0; u8 rcv_seqhdr[MALONE_VC1_RCV_SEQ_HEADER_LEN]; + if (vpu_vb_is_codecconfig(to_vb2_v4l2_buffer(scode->vb))) + scode->need_data = 0; if (scode->inst->total_input_count) return 0; scode->need_data = 0; @@ -1458,6 +1469,7 @@ static const struct malone_scode_handler scode_handlers[] = { }, { .pixelformat = V4L2_PIX_FMT_VC1_ANNEX_G, + .insert_scode_seq = vpu_malone_insert_scode_vc1_g_seq, .insert_scode_pic = vpu_malone_insert_scode_vc1_g_pic, }, { diff --git a/drivers/media/platform/amphion/vpu_v4l2.c b/drivers/media/platform/amphion/vpu_v4l2.c index 6773b885597cec691326116a0362c5d91296d8b7..021235e1c14467edc6d28bb50749a2d3a5f97f83 100644 --- a/drivers/media/platform/amphion/vpu_v4l2.c +++ b/drivers/media/platform/amphion/vpu_v4l2.c @@ -100,7 +100,7 @@ int vpu_notify_source_change(struct vpu_inst *inst) return 0; } -int vpu_set_last_buffer_dequeued(struct vpu_inst *inst) +int vpu_set_last_buffer_dequeued(struct vpu_inst *inst, bool eos) { struct vb2_queue *q; @@ -116,7 +116,8 @@ int vpu_set_last_buffer_dequeued(struct vpu_inst *inst) vpu_trace(inst->dev, "last buffer dequeued\n"); q->last_buffer_dequeued = true; wake_up(&q->done_wq); - vpu_notify_eos(inst); + if (eos) + vpu_notify_eos(inst); return 0; } @@ -740,7 +741,7 @@ int vpu_v4l2_open(struct file *file, struct vpu_inst *inst) inst->fh.ctrl_handler = &inst->ctrl_handler; file->private_data = &inst->fh; inst->state = VPU_CODEC_STATE_DEINIT; - inst->workqueue = alloc_workqueue("vpu_inst", WQ_UNBOUND | WQ_MEM_RECLAIM, 1); + inst->workqueue = alloc_ordered_workqueue("vpu_inst", WQ_MEM_RECLAIM); if (inst->workqueue) { INIT_WORK(&inst->msg_work, vpu_inst_run_work); ret = kfifo_init(&inst->msg_fifo, diff --git a/drivers/media/platform/amphion/vpu_v4l2.h b/drivers/media/platform/amphion/vpu_v4l2.h index ef5de6b66e474b69ce9212577c6d24f5d65b21de..60f43056a7a286f7ed20a40a3d7a7000953b6f12 100644 --- a/drivers/media/platform/amphion/vpu_v4l2.h +++ b/drivers/media/platform/amphion/vpu_v4l2.h @@ -27,7 +27,7 @@ struct vb2_v4l2_buffer *vpu_find_buf_by_idx(struct vpu_inst *inst, u32 type, u32 void vpu_v4l2_set_error(struct vpu_inst *inst); int vpu_notify_eos(struct vpu_inst *inst); int vpu_notify_source_change(struct vpu_inst *inst); -int vpu_set_last_buffer_dequeued(struct vpu_inst *inst); +int vpu_set_last_buffer_dequeued(struct vpu_inst *inst, bool eos); void vpu_vb2_buffers_return(struct vpu_inst *inst, unsigned int type, enum vb2_buffer_state state); int vpu_get_num_buffers(struct vpu_inst *inst, u32 type); bool vpu_is_source_empty(struct vpu_inst *inst); diff --git a/drivers/media/platform/chips-media/coda-common.c b/drivers/media/platform/chips-media/coda-common.c index d013ea5d9d3d239195d09e2057236d61685958d6..ac9a642ae76f720cf234d8c2bdbc9fe51ecd0303 100644 --- a/drivers/media/platform/chips-media/coda-common.c +++ b/drivers/media/platform/chips-media/coda-common.c @@ -3268,7 +3268,7 @@ static int coda_probe(struct platform_device *pdev) &dev->iram.blob); } - dev->workqueue = alloc_workqueue("coda", WQ_UNBOUND | WQ_MEM_RECLAIM, 1); + dev->workqueue = alloc_ordered_workqueue("coda", WQ_MEM_RECLAIM); if (!dev->workqueue) { dev_err(&pdev->dev, "unable to alloc workqueue\n"); ret = -ENOMEM; diff --git a/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c b/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c index 0051f372a66cfea26f11f390bb71a8c90a51430d..4768156181c99110191b6e0431a737e6f51186fd 100644 --- a/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c +++ b/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c @@ -28,6 +28,7 @@ #include "mtk_jpeg_core.h" #include "mtk_jpeg_dec_parse.h" +#if defined(CONFIG_OF) static struct mtk_jpeg_fmt mtk_jpeg_enc_formats[] = { { .fourcc = V4L2_PIX_FMT_JPEG, @@ -101,6 +102,7 @@ static struct mtk_jpeg_fmt mtk_jpeg_dec_formats[] = { .flags = MTK_JPEG_FMT_FLAG_CAPTURE, }, }; +#endif #define MTK_JPEG_ENC_NUM_FORMATS ARRAY_SIZE(mtk_jpeg_enc_formats) #define MTK_JPEG_DEC_NUM_FORMATS ARRAY_SIZE(mtk_jpeg_dec_formats) @@ -936,148 +938,6 @@ static int mtk_jpeg_set_dec_dst(struct mtk_jpeg_ctx *ctx, return 0; } -static int mtk_jpegenc_get_hw(struct mtk_jpeg_ctx *ctx) -{ - struct mtk_jpegenc_comp_dev *comp_jpeg; - struct mtk_jpeg_dev *jpeg = ctx->jpeg; - unsigned long flags; - int hw_id = -1; - int i; - - spin_lock_irqsave(&jpeg->hw_lock, flags); - for (i = 0; i < MTK_JPEGENC_HW_MAX; i++) { - comp_jpeg = jpeg->enc_hw_dev[i]; - if (comp_jpeg->hw_state == MTK_JPEG_HW_IDLE) { - hw_id = i; - comp_jpeg->hw_state = MTK_JPEG_HW_BUSY; - break; - } - } - spin_unlock_irqrestore(&jpeg->hw_lock, flags); - - return hw_id; -} - -static int mtk_jpegenc_set_hw_param(struct mtk_jpeg_ctx *ctx, - int hw_id, - struct vb2_v4l2_buffer *src_buf, - struct vb2_v4l2_buffer *dst_buf) -{ - struct mtk_jpegenc_comp_dev *jpeg = ctx->jpeg->enc_hw_dev[hw_id]; - - jpeg->hw_param.curr_ctx = ctx; - jpeg->hw_param.src_buffer = src_buf; - jpeg->hw_param.dst_buffer = dst_buf; - - return 0; -} - -static int mtk_jpegenc_put_hw(struct mtk_jpeg_dev *jpeg, int hw_id) -{ - unsigned long flags; - - spin_lock_irqsave(&jpeg->hw_lock, flags); - jpeg->enc_hw_dev[hw_id]->hw_state = MTK_JPEG_HW_IDLE; - spin_unlock_irqrestore(&jpeg->hw_lock, flags); - - return 0; -} - -static void mtk_jpegenc_worker(struct work_struct *work) -{ - struct mtk_jpegenc_comp_dev *comp_jpeg[MTK_JPEGENC_HW_MAX]; - enum vb2_buffer_state buf_state = VB2_BUF_STATE_ERROR; - struct mtk_jpeg_src_buf *jpeg_dst_buf; - struct vb2_v4l2_buffer *src_buf, *dst_buf; - int ret, i, hw_id = 0; - unsigned long flags; - - struct mtk_jpeg_ctx *ctx = container_of(work, - struct mtk_jpeg_ctx, - jpeg_work); - struct mtk_jpeg_dev *jpeg = ctx->jpeg; - - for (i = 0; i < MTK_JPEGENC_HW_MAX; i++) - comp_jpeg[i] = jpeg->enc_hw_dev[i]; - i = 0; - -retry_select: - hw_id = mtk_jpegenc_get_hw(ctx); - if (hw_id < 0) { - ret = wait_event_interruptible(jpeg->hw_wq, - atomic_read(&jpeg->hw_rdy) > 0); - if (ret != 0 || (i++ > MTK_JPEG_MAX_RETRY_TIME)) { - dev_err(jpeg->dev, "%s : %d, all HW are busy\n", - __func__, __LINE__); - v4l2_m2m_job_finish(jpeg->m2m_dev, ctx->fh.m2m_ctx); - return; - } - - goto retry_select; - } - - atomic_dec(&jpeg->hw_rdy); - src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); - if (!src_buf) - goto getbuf_fail; - - dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); - if (!dst_buf) - goto getbuf_fail; - - v4l2_m2m_buf_copy_metadata(src_buf, dst_buf, true); - - mtk_jpegenc_set_hw_param(ctx, hw_id, src_buf, dst_buf); - ret = pm_runtime_get_sync(comp_jpeg[hw_id]->dev); - if (ret < 0) { - dev_err(jpeg->dev, "%s : %d, pm_runtime_get_sync fail !!!\n", - __func__, __LINE__); - goto enc_end; - } - - ret = clk_prepare_enable(comp_jpeg[hw_id]->venc_clk.clks->clk); - if (ret) { - dev_err(jpeg->dev, "%s : %d, jpegenc clk_prepare_enable fail\n", - __func__, __LINE__); - goto enc_end; - } - - v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); - v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); - - schedule_delayed_work(&comp_jpeg[hw_id]->job_timeout_work, - msecs_to_jiffies(MTK_JPEG_HW_TIMEOUT_MSEC)); - - spin_lock_irqsave(&comp_jpeg[hw_id]->hw_lock, flags); - jpeg_dst_buf = mtk_jpeg_vb2_to_srcbuf(&dst_buf->vb2_buf); - jpeg_dst_buf->curr_ctx = ctx; - jpeg_dst_buf->frame_num = ctx->total_frame_num; - ctx->total_frame_num++; - mtk_jpeg_enc_reset(comp_jpeg[hw_id]->reg_base); - mtk_jpeg_set_enc_dst(ctx, - comp_jpeg[hw_id]->reg_base, - &dst_buf->vb2_buf); - mtk_jpeg_set_enc_src(ctx, - comp_jpeg[hw_id]->reg_base, - &src_buf->vb2_buf); - mtk_jpeg_set_enc_params(ctx, comp_jpeg[hw_id]->reg_base); - mtk_jpeg_enc_start(comp_jpeg[hw_id]->reg_base); - v4l2_m2m_job_finish(jpeg->m2m_dev, ctx->fh.m2m_ctx); - spin_unlock_irqrestore(&comp_jpeg[hw_id]->hw_lock, flags); - - return; - -enc_end: - v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); - v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); - v4l2_m2m_buf_done(src_buf, buf_state); - v4l2_m2m_buf_done(dst_buf, buf_state); -getbuf_fail: - atomic_inc(&jpeg->hw_rdy); - mtk_jpegenc_put_hw(jpeg, hw_id); - v4l2_m2m_job_finish(jpeg->m2m_dev, ctx->fh.m2m_ctx); -} - static void mtk_jpeg_enc_device_run(void *priv) { struct mtk_jpeg_ctx *ctx = priv; @@ -1128,206 +988,39 @@ static void mtk_jpeg_multicore_enc_device_run(void *priv) queue_work(jpeg->workqueue, &ctx->jpeg_work); } -static int mtk_jpegdec_get_hw(struct mtk_jpeg_ctx *ctx) +static void mtk_jpeg_multicore_dec_device_run(void *priv) { - struct mtk_jpegdec_comp_dev *comp_jpeg; + struct mtk_jpeg_ctx *ctx = priv; struct mtk_jpeg_dev *jpeg = ctx->jpeg; - unsigned long flags; - int hw_id = -1; - int i; - - spin_lock_irqsave(&jpeg->hw_lock, flags); - for (i = 0; i < MTK_JPEGDEC_HW_MAX; i++) { - comp_jpeg = jpeg->dec_hw_dev[i]; - if (comp_jpeg->hw_state == MTK_JPEG_HW_IDLE) { - hw_id = i; - comp_jpeg->hw_state = MTK_JPEG_HW_BUSY; - break; - } - } - spin_unlock_irqrestore(&jpeg->hw_lock, flags); - - return hw_id; -} - -static int mtk_jpegdec_put_hw(struct mtk_jpeg_dev *jpeg, int hw_id) -{ - unsigned long flags; - - spin_lock_irqsave(&jpeg->hw_lock, flags); - jpeg->dec_hw_dev[hw_id]->hw_state = - MTK_JPEG_HW_IDLE; - spin_unlock_irqrestore(&jpeg->hw_lock, flags); - - return 0; -} - -static int mtk_jpegdec_set_hw_param(struct mtk_jpeg_ctx *ctx, - int hw_id, - struct vb2_v4l2_buffer *src_buf, - struct vb2_v4l2_buffer *dst_buf) -{ - struct mtk_jpegdec_comp_dev *jpeg = - ctx->jpeg->dec_hw_dev[hw_id]; - - jpeg->hw_param.curr_ctx = ctx; - jpeg->hw_param.src_buffer = src_buf; - jpeg->hw_param.dst_buffer = dst_buf; - return 0; + queue_work(jpeg->workqueue, &ctx->jpeg_work); } -static void mtk_jpegdec_worker(struct work_struct *work) +static void mtk_jpeg_dec_device_run(void *priv) { - struct mtk_jpeg_ctx *ctx = container_of(work, struct mtk_jpeg_ctx, - jpeg_work); - struct mtk_jpegdec_comp_dev *comp_jpeg[MTK_JPEGDEC_HW_MAX]; - enum vb2_buffer_state buf_state = VB2_BUF_STATE_ERROR; - struct mtk_jpeg_src_buf *jpeg_src_buf, *jpeg_dst_buf; - struct vb2_v4l2_buffer *src_buf, *dst_buf; + struct mtk_jpeg_ctx *ctx = priv; struct mtk_jpeg_dev *jpeg = ctx->jpeg; - int ret, i, hw_id = 0; + struct vb2_v4l2_buffer *src_buf, *dst_buf; + enum vb2_buffer_state buf_state = VB2_BUF_STATE_ERROR; + unsigned long flags; + struct mtk_jpeg_src_buf *jpeg_src_buf; struct mtk_jpeg_bs bs; struct mtk_jpeg_fb fb; - unsigned long flags; - - for (i = 0; i < MTK_JPEGDEC_HW_MAX; i++) - comp_jpeg[i] = jpeg->dec_hw_dev[i]; - i = 0; - -retry_select: - hw_id = mtk_jpegdec_get_hw(ctx); - if (hw_id < 0) { - ret = wait_event_interruptible_timeout(jpeg->hw_wq, - atomic_read(&jpeg->hw_rdy) > 0, - MTK_JPEG_HW_TIMEOUT_MSEC); - if (ret != 0 || (i++ > MTK_JPEG_MAX_RETRY_TIME)) { - dev_err(jpeg->dev, "%s : %d, all HW are busy\n", - __func__, __LINE__); - v4l2_m2m_job_finish(jpeg->m2m_dev, ctx->fh.m2m_ctx); - return; - } - - goto retry_select; - } + int ret; - atomic_dec(&jpeg->hw_rdy); src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); - if (!src_buf) - goto getbuf_fail; - dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); - if (!dst_buf) - goto getbuf_fail; - - v4l2_m2m_buf_copy_metadata(src_buf, dst_buf, true); jpeg_src_buf = mtk_jpeg_vb2_to_srcbuf(&src_buf->vb2_buf); - jpeg_dst_buf = mtk_jpeg_vb2_to_srcbuf(&dst_buf->vb2_buf); - if (mtk_jpeg_check_resolution_change(ctx, - &jpeg_src_buf->dec_param)) { + if (mtk_jpeg_check_resolution_change(ctx, &jpeg_src_buf->dec_param)) { mtk_jpeg_queue_src_chg_event(ctx); ctx->state = MTK_JPEG_SOURCE_CHANGE; - goto getbuf_fail; + v4l2_m2m_job_finish(jpeg->m2m_dev, ctx->fh.m2m_ctx); + return; } - jpeg_src_buf->curr_ctx = ctx; - jpeg_src_buf->frame_num = ctx->total_frame_num; - jpeg_dst_buf->curr_ctx = ctx; - jpeg_dst_buf->frame_num = ctx->total_frame_num; - - mtk_jpegdec_set_hw_param(ctx, hw_id, src_buf, dst_buf); - ret = pm_runtime_get_sync(comp_jpeg[hw_id]->dev); - if (ret < 0) { - dev_err(jpeg->dev, "%s : %d, pm_runtime_get_sync fail !!!\n", - __func__, __LINE__); - goto dec_end; - } - - ret = clk_prepare_enable(comp_jpeg[hw_id]->jdec_clk.clks->clk); - if (ret) { - dev_err(jpeg->dev, "%s : %d, jpegdec clk_prepare_enable fail\n", - __func__, __LINE__); - goto clk_end; - } - - v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); - v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); - - schedule_delayed_work(&comp_jpeg[hw_id]->job_timeout_work, - msecs_to_jiffies(MTK_JPEG_HW_TIMEOUT_MSEC)); - - mtk_jpeg_set_dec_src(ctx, &src_buf->vb2_buf, &bs); - if (mtk_jpeg_set_dec_dst(ctx, - &jpeg_src_buf->dec_param, - &dst_buf->vb2_buf, &fb)) { - dev_err(jpeg->dev, "%s : %d, mtk_jpeg_set_dec_dst fail\n", - __func__, __LINE__); - goto setdst_end; - } - - spin_lock_irqsave(&comp_jpeg[hw_id]->hw_lock, flags); - ctx->total_frame_num++; - mtk_jpeg_dec_reset(comp_jpeg[hw_id]->reg_base); - mtk_jpeg_dec_set_config(comp_jpeg[hw_id]->reg_base, - &jpeg_src_buf->dec_param, - jpeg_src_buf->bs_size, - &bs, - &fb); - mtk_jpeg_dec_start(comp_jpeg[hw_id]->reg_base); - v4l2_m2m_job_finish(jpeg->m2m_dev, ctx->fh.m2m_ctx); - spin_unlock_irqrestore(&comp_jpeg[hw_id]->hw_lock, flags); - - return; - -setdst_end: - clk_disable_unprepare(comp_jpeg[hw_id]->jdec_clk.clks->clk); -clk_end: - pm_runtime_put(comp_jpeg[hw_id]->dev); -dec_end: - v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); - v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); - v4l2_m2m_buf_done(src_buf, buf_state); - v4l2_m2m_buf_done(dst_buf, buf_state); -getbuf_fail: - atomic_inc(&jpeg->hw_rdy); - mtk_jpegdec_put_hw(jpeg, hw_id); - v4l2_m2m_job_finish(jpeg->m2m_dev, ctx->fh.m2m_ctx); -} - -static void mtk_jpeg_multicore_dec_device_run(void *priv) -{ - struct mtk_jpeg_ctx *ctx = priv; - struct mtk_jpeg_dev *jpeg = ctx->jpeg; - - queue_work(jpeg->workqueue, &ctx->jpeg_work); -} - -static void mtk_jpeg_dec_device_run(void *priv) -{ - struct mtk_jpeg_ctx *ctx = priv; - struct mtk_jpeg_dev *jpeg = ctx->jpeg; - struct vb2_v4l2_buffer *src_buf, *dst_buf; - enum vb2_buffer_state buf_state = VB2_BUF_STATE_ERROR; - unsigned long flags; - struct mtk_jpeg_src_buf *jpeg_src_buf; - struct mtk_jpeg_bs bs; - struct mtk_jpeg_fb fb; - int ret; - - src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); - dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); - jpeg_src_buf = mtk_jpeg_vb2_to_srcbuf(&src_buf->vb2_buf); - - if (mtk_jpeg_check_resolution_change(ctx, &jpeg_src_buf->dec_param)) { - mtk_jpeg_queue_src_chg_event(ctx); - ctx->state = MTK_JPEG_SOURCE_CHANGE; - v4l2_m2m_job_finish(jpeg->m2m_dev, ctx->fh.m2m_ctx); - return; - } - - ret = pm_runtime_resume_and_get(jpeg->dev); - if (ret < 0) + ret = pm_runtime_resume_and_get(jpeg->dev); + if (ret < 0) goto dec_end; schedule_delayed_work(&jpeg->job_timeout_work, @@ -1430,101 +1123,6 @@ static void mtk_jpeg_clk_off(struct mtk_jpeg_dev *jpeg) jpeg->variant->clks); } -static irqreturn_t mtk_jpeg_enc_done(struct mtk_jpeg_dev *jpeg) -{ - struct mtk_jpeg_ctx *ctx; - struct vb2_v4l2_buffer *src_buf, *dst_buf; - enum vb2_buffer_state buf_state = VB2_BUF_STATE_ERROR; - u32 result_size; - - ctx = v4l2_m2m_get_curr_priv(jpeg->m2m_dev); - if (!ctx) { - v4l2_err(&jpeg->v4l2_dev, "Context is NULL\n"); - return IRQ_HANDLED; - } - - src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); - dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); - - result_size = mtk_jpeg_enc_get_file_size(jpeg->reg_base); - vb2_set_plane_payload(&dst_buf->vb2_buf, 0, result_size); - - buf_state = VB2_BUF_STATE_DONE; - - v4l2_m2m_buf_done(src_buf, buf_state); - v4l2_m2m_buf_done(dst_buf, buf_state); - v4l2_m2m_job_finish(jpeg->m2m_dev, ctx->fh.m2m_ctx); - pm_runtime_put(ctx->jpeg->dev); - return IRQ_HANDLED; -} - -static irqreturn_t mtk_jpeg_enc_irq(int irq, void *priv) -{ - struct mtk_jpeg_dev *jpeg = priv; - u32 irq_status; - irqreturn_t ret = IRQ_NONE; - - cancel_delayed_work(&jpeg->job_timeout_work); - - irq_status = readl(jpeg->reg_base + JPEG_ENC_INT_STS) & - JPEG_ENC_INT_STATUS_MASK_ALLIRQ; - if (irq_status) - writel(0, jpeg->reg_base + JPEG_ENC_INT_STS); - - if (!(irq_status & JPEG_ENC_INT_STATUS_DONE)) - return ret; - - ret = mtk_jpeg_enc_done(jpeg); - return ret; -} - -static irqreturn_t mtk_jpeg_dec_irq(int irq, void *priv) -{ - struct mtk_jpeg_dev *jpeg = priv; - struct mtk_jpeg_ctx *ctx; - struct vb2_v4l2_buffer *src_buf, *dst_buf; - struct mtk_jpeg_src_buf *jpeg_src_buf; - enum vb2_buffer_state buf_state = VB2_BUF_STATE_ERROR; - u32 dec_irq_ret; - u32 dec_ret; - int i; - - cancel_delayed_work(&jpeg->job_timeout_work); - - dec_ret = mtk_jpeg_dec_get_int_status(jpeg->reg_base); - dec_irq_ret = mtk_jpeg_dec_enum_result(dec_ret); - ctx = v4l2_m2m_get_curr_priv(jpeg->m2m_dev); - if (!ctx) { - v4l2_err(&jpeg->v4l2_dev, "Context is NULL\n"); - return IRQ_HANDLED; - } - - src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); - dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); - jpeg_src_buf = mtk_jpeg_vb2_to_srcbuf(&src_buf->vb2_buf); - - if (dec_irq_ret >= MTK_JPEG_DEC_RESULT_UNDERFLOW) - mtk_jpeg_dec_reset(jpeg->reg_base); - - if (dec_irq_ret != MTK_JPEG_DEC_RESULT_EOF_DONE) { - dev_err(jpeg->dev, "decode failed\n"); - goto dec_end; - } - - for (i = 0; i < dst_buf->vb2_buf.num_planes; i++) - vb2_set_plane_payload(&dst_buf->vb2_buf, i, - jpeg_src_buf->dec_param.comp_size[i]); - - buf_state = VB2_BUF_STATE_DONE; - -dec_end: - v4l2_m2m_buf_done(src_buf, buf_state); - v4l2_m2m_buf_done(dst_buf, buf_state); - v4l2_m2m_job_finish(jpeg->m2m_dev, ctx->fh.m2m_ctx); - pm_runtime_put(ctx->jpeg->dev); - return IRQ_HANDLED; -} - static void mtk_jpeg_set_default_params(struct mtk_jpeg_ctx *ctx) { struct mtk_jpeg_q_data *q = &ctx->out_q; @@ -1637,15 +1235,6 @@ static const struct v4l2_file_operations mtk_jpeg_fops = { .mmap = v4l2_m2m_fop_mmap, }; -static struct clk_bulk_data mt8173_jpeg_dec_clocks[] = { - { .id = "jpgdec-smi" }, - { .id = "jpgdec" }, -}; - -static struct clk_bulk_data mtk_jpeg_clocks[] = { - { .id = "jpgenc" }, -}; - static void mtk_jpeg_job_timeout_work(struct work_struct *work) { struct mtk_jpeg_dev *jpeg = container_of(work, struct mtk_jpeg_dev, @@ -1867,6 +1456,419 @@ static const struct dev_pm_ops mtk_jpeg_pm_ops = { }; #if defined(CONFIG_OF) +static int mtk_jpegenc_get_hw(struct mtk_jpeg_ctx *ctx) +{ + struct mtk_jpegenc_comp_dev *comp_jpeg; + struct mtk_jpeg_dev *jpeg = ctx->jpeg; + unsigned long flags; + int hw_id = -1; + int i; + + spin_lock_irqsave(&jpeg->hw_lock, flags); + for (i = 0; i < MTK_JPEGENC_HW_MAX; i++) { + comp_jpeg = jpeg->enc_hw_dev[i]; + if (comp_jpeg->hw_state == MTK_JPEG_HW_IDLE) { + hw_id = i; + comp_jpeg->hw_state = MTK_JPEG_HW_BUSY; + break; + } + } + spin_unlock_irqrestore(&jpeg->hw_lock, flags); + + return hw_id; +} + +static int mtk_jpegenc_set_hw_param(struct mtk_jpeg_ctx *ctx, + int hw_id, + struct vb2_v4l2_buffer *src_buf, + struct vb2_v4l2_buffer *dst_buf) +{ + struct mtk_jpegenc_comp_dev *jpeg = ctx->jpeg->enc_hw_dev[hw_id]; + + jpeg->hw_param.curr_ctx = ctx; + jpeg->hw_param.src_buffer = src_buf; + jpeg->hw_param.dst_buffer = dst_buf; + + return 0; +} + +static int mtk_jpegenc_put_hw(struct mtk_jpeg_dev *jpeg, int hw_id) +{ + unsigned long flags; + + spin_lock_irqsave(&jpeg->hw_lock, flags); + jpeg->enc_hw_dev[hw_id]->hw_state = MTK_JPEG_HW_IDLE; + spin_unlock_irqrestore(&jpeg->hw_lock, flags); + + return 0; +} + +static int mtk_jpegdec_get_hw(struct mtk_jpeg_ctx *ctx) +{ + struct mtk_jpegdec_comp_dev *comp_jpeg; + struct mtk_jpeg_dev *jpeg = ctx->jpeg; + unsigned long flags; + int hw_id = -1; + int i; + + spin_lock_irqsave(&jpeg->hw_lock, flags); + for (i = 0; i < MTK_JPEGDEC_HW_MAX; i++) { + comp_jpeg = jpeg->dec_hw_dev[i]; + if (comp_jpeg->hw_state == MTK_JPEG_HW_IDLE) { + hw_id = i; + comp_jpeg->hw_state = MTK_JPEG_HW_BUSY; + break; + } + } + spin_unlock_irqrestore(&jpeg->hw_lock, flags); + + return hw_id; +} + +static int mtk_jpegdec_put_hw(struct mtk_jpeg_dev *jpeg, int hw_id) +{ + unsigned long flags; + + spin_lock_irqsave(&jpeg->hw_lock, flags); + jpeg->dec_hw_dev[hw_id]->hw_state = + MTK_JPEG_HW_IDLE; + spin_unlock_irqrestore(&jpeg->hw_lock, flags); + + return 0; +} + +static int mtk_jpegdec_set_hw_param(struct mtk_jpeg_ctx *ctx, + int hw_id, + struct vb2_v4l2_buffer *src_buf, + struct vb2_v4l2_buffer *dst_buf) +{ + struct mtk_jpegdec_comp_dev *jpeg = + ctx->jpeg->dec_hw_dev[hw_id]; + + jpeg->hw_param.curr_ctx = ctx; + jpeg->hw_param.src_buffer = src_buf; + jpeg->hw_param.dst_buffer = dst_buf; + + return 0; +} + +static irqreturn_t mtk_jpeg_enc_done(struct mtk_jpeg_dev *jpeg) +{ + struct mtk_jpeg_ctx *ctx; + struct vb2_v4l2_buffer *src_buf, *dst_buf; + enum vb2_buffer_state buf_state = VB2_BUF_STATE_ERROR; + u32 result_size; + + ctx = v4l2_m2m_get_curr_priv(jpeg->m2m_dev); + if (!ctx) { + v4l2_err(&jpeg->v4l2_dev, "Context is NULL\n"); + return IRQ_HANDLED; + } + + src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); + dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); + + result_size = mtk_jpeg_enc_get_file_size(jpeg->reg_base); + vb2_set_plane_payload(&dst_buf->vb2_buf, 0, result_size); + + buf_state = VB2_BUF_STATE_DONE; + + v4l2_m2m_buf_done(src_buf, buf_state); + v4l2_m2m_buf_done(dst_buf, buf_state); + v4l2_m2m_job_finish(jpeg->m2m_dev, ctx->fh.m2m_ctx); + pm_runtime_put(ctx->jpeg->dev); + return IRQ_HANDLED; +} + +static void mtk_jpegenc_worker(struct work_struct *work) +{ + struct mtk_jpegenc_comp_dev *comp_jpeg[MTK_JPEGENC_HW_MAX]; + enum vb2_buffer_state buf_state = VB2_BUF_STATE_ERROR; + struct mtk_jpeg_src_buf *jpeg_dst_buf; + struct vb2_v4l2_buffer *src_buf, *dst_buf; + int ret, i, hw_id = 0; + unsigned long flags; + + struct mtk_jpeg_ctx *ctx = container_of(work, + struct mtk_jpeg_ctx, + jpeg_work); + struct mtk_jpeg_dev *jpeg = ctx->jpeg; + + for (i = 0; i < MTK_JPEGENC_HW_MAX; i++) + comp_jpeg[i] = jpeg->enc_hw_dev[i]; + i = 0; + +retry_select: + hw_id = mtk_jpegenc_get_hw(ctx); + if (hw_id < 0) { + ret = wait_event_interruptible(jpeg->hw_wq, + atomic_read(&jpeg->hw_rdy) > 0); + if (ret != 0 || (i++ > MTK_JPEG_MAX_RETRY_TIME)) { + dev_err(jpeg->dev, "%s : %d, all HW are busy\n", + __func__, __LINE__); + v4l2_m2m_job_finish(jpeg->m2m_dev, ctx->fh.m2m_ctx); + return; + } + + goto retry_select; + } + + atomic_dec(&jpeg->hw_rdy); + src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); + if (!src_buf) + goto getbuf_fail; + + dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); + if (!dst_buf) + goto getbuf_fail; + + v4l2_m2m_buf_copy_metadata(src_buf, dst_buf, true); + + mtk_jpegenc_set_hw_param(ctx, hw_id, src_buf, dst_buf); + ret = pm_runtime_get_sync(comp_jpeg[hw_id]->dev); + if (ret < 0) { + dev_err(jpeg->dev, "%s : %d, pm_runtime_get_sync fail !!!\n", + __func__, __LINE__); + goto enc_end; + } + + ret = clk_prepare_enable(comp_jpeg[hw_id]->venc_clk.clks->clk); + if (ret) { + dev_err(jpeg->dev, "%s : %d, jpegenc clk_prepare_enable fail\n", + __func__, __LINE__); + goto enc_end; + } + + v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); + v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); + + schedule_delayed_work(&comp_jpeg[hw_id]->job_timeout_work, + msecs_to_jiffies(MTK_JPEG_HW_TIMEOUT_MSEC)); + + spin_lock_irqsave(&comp_jpeg[hw_id]->hw_lock, flags); + jpeg_dst_buf = mtk_jpeg_vb2_to_srcbuf(&dst_buf->vb2_buf); + jpeg_dst_buf->curr_ctx = ctx; + jpeg_dst_buf->frame_num = ctx->total_frame_num; + ctx->total_frame_num++; + mtk_jpeg_enc_reset(comp_jpeg[hw_id]->reg_base); + mtk_jpeg_set_enc_dst(ctx, + comp_jpeg[hw_id]->reg_base, + &dst_buf->vb2_buf); + mtk_jpeg_set_enc_src(ctx, + comp_jpeg[hw_id]->reg_base, + &src_buf->vb2_buf); + mtk_jpeg_set_enc_params(ctx, comp_jpeg[hw_id]->reg_base); + mtk_jpeg_enc_start(comp_jpeg[hw_id]->reg_base); + v4l2_m2m_job_finish(jpeg->m2m_dev, ctx->fh.m2m_ctx); + spin_unlock_irqrestore(&comp_jpeg[hw_id]->hw_lock, flags); + + return; + +enc_end: + v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); + v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); + v4l2_m2m_buf_done(src_buf, buf_state); + v4l2_m2m_buf_done(dst_buf, buf_state); +getbuf_fail: + atomic_inc(&jpeg->hw_rdy); + mtk_jpegenc_put_hw(jpeg, hw_id); + v4l2_m2m_job_finish(jpeg->m2m_dev, ctx->fh.m2m_ctx); +} + +static void mtk_jpegdec_worker(struct work_struct *work) +{ + struct mtk_jpeg_ctx *ctx = container_of(work, struct mtk_jpeg_ctx, + jpeg_work); + struct mtk_jpegdec_comp_dev *comp_jpeg[MTK_JPEGDEC_HW_MAX]; + enum vb2_buffer_state buf_state = VB2_BUF_STATE_ERROR; + struct mtk_jpeg_src_buf *jpeg_src_buf, *jpeg_dst_buf; + struct vb2_v4l2_buffer *src_buf, *dst_buf; + struct mtk_jpeg_dev *jpeg = ctx->jpeg; + int ret, i, hw_id = 0; + struct mtk_jpeg_bs bs; + struct mtk_jpeg_fb fb; + unsigned long flags; + + for (i = 0; i < MTK_JPEGDEC_HW_MAX; i++) + comp_jpeg[i] = jpeg->dec_hw_dev[i]; + i = 0; + +retry_select: + hw_id = mtk_jpegdec_get_hw(ctx); + if (hw_id < 0) { + ret = wait_event_interruptible_timeout(jpeg->hw_wq, + atomic_read(&jpeg->hw_rdy) > 0, + MTK_JPEG_HW_TIMEOUT_MSEC); + if (ret != 0 || (i++ > MTK_JPEG_MAX_RETRY_TIME)) { + dev_err(jpeg->dev, "%s : %d, all HW are busy\n", + __func__, __LINE__); + v4l2_m2m_job_finish(jpeg->m2m_dev, ctx->fh.m2m_ctx); + return; + } + + goto retry_select; + } + + atomic_dec(&jpeg->hw_rdy); + src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); + if (!src_buf) + goto getbuf_fail; + + dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); + if (!dst_buf) + goto getbuf_fail; + + v4l2_m2m_buf_copy_metadata(src_buf, dst_buf, true); + jpeg_src_buf = mtk_jpeg_vb2_to_srcbuf(&src_buf->vb2_buf); + jpeg_dst_buf = mtk_jpeg_vb2_to_srcbuf(&dst_buf->vb2_buf); + + if (mtk_jpeg_check_resolution_change(ctx, + &jpeg_src_buf->dec_param)) { + mtk_jpeg_queue_src_chg_event(ctx); + ctx->state = MTK_JPEG_SOURCE_CHANGE; + goto getbuf_fail; + } + + jpeg_src_buf->curr_ctx = ctx; + jpeg_src_buf->frame_num = ctx->total_frame_num; + jpeg_dst_buf->curr_ctx = ctx; + jpeg_dst_buf->frame_num = ctx->total_frame_num; + + mtk_jpegdec_set_hw_param(ctx, hw_id, src_buf, dst_buf); + ret = pm_runtime_get_sync(comp_jpeg[hw_id]->dev); + if (ret < 0) { + dev_err(jpeg->dev, "%s : %d, pm_runtime_get_sync fail !!!\n", + __func__, __LINE__); + goto dec_end; + } + + ret = clk_prepare_enable(comp_jpeg[hw_id]->jdec_clk.clks->clk); + if (ret) { + dev_err(jpeg->dev, "%s : %d, jpegdec clk_prepare_enable fail\n", + __func__, __LINE__); + goto clk_end; + } + + v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); + v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); + + schedule_delayed_work(&comp_jpeg[hw_id]->job_timeout_work, + msecs_to_jiffies(MTK_JPEG_HW_TIMEOUT_MSEC)); + + mtk_jpeg_set_dec_src(ctx, &src_buf->vb2_buf, &bs); + if (mtk_jpeg_set_dec_dst(ctx, + &jpeg_src_buf->dec_param, + &dst_buf->vb2_buf, &fb)) { + dev_err(jpeg->dev, "%s : %d, mtk_jpeg_set_dec_dst fail\n", + __func__, __LINE__); + goto setdst_end; + } + + spin_lock_irqsave(&comp_jpeg[hw_id]->hw_lock, flags); + ctx->total_frame_num++; + mtk_jpeg_dec_reset(comp_jpeg[hw_id]->reg_base); + mtk_jpeg_dec_set_config(comp_jpeg[hw_id]->reg_base, + &jpeg_src_buf->dec_param, + jpeg_src_buf->bs_size, + &bs, + &fb); + mtk_jpeg_dec_start(comp_jpeg[hw_id]->reg_base); + v4l2_m2m_job_finish(jpeg->m2m_dev, ctx->fh.m2m_ctx); + spin_unlock_irqrestore(&comp_jpeg[hw_id]->hw_lock, flags); + + return; + +setdst_end: + clk_disable_unprepare(comp_jpeg[hw_id]->jdec_clk.clks->clk); +clk_end: + pm_runtime_put(comp_jpeg[hw_id]->dev); +dec_end: + v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); + v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); + v4l2_m2m_buf_done(src_buf, buf_state); + v4l2_m2m_buf_done(dst_buf, buf_state); +getbuf_fail: + atomic_inc(&jpeg->hw_rdy); + mtk_jpegdec_put_hw(jpeg, hw_id); + v4l2_m2m_job_finish(jpeg->m2m_dev, ctx->fh.m2m_ctx); +} + +static irqreturn_t mtk_jpeg_enc_irq(int irq, void *priv) +{ + struct mtk_jpeg_dev *jpeg = priv; + u32 irq_status; + irqreturn_t ret = IRQ_NONE; + + cancel_delayed_work(&jpeg->job_timeout_work); + + irq_status = readl(jpeg->reg_base + JPEG_ENC_INT_STS) & + JPEG_ENC_INT_STATUS_MASK_ALLIRQ; + if (irq_status) + writel(0, jpeg->reg_base + JPEG_ENC_INT_STS); + + if (!(irq_status & JPEG_ENC_INT_STATUS_DONE)) + return ret; + + ret = mtk_jpeg_enc_done(jpeg); + return ret; +} + +static irqreturn_t mtk_jpeg_dec_irq(int irq, void *priv) +{ + struct mtk_jpeg_dev *jpeg = priv; + struct mtk_jpeg_ctx *ctx; + struct vb2_v4l2_buffer *src_buf, *dst_buf; + struct mtk_jpeg_src_buf *jpeg_src_buf; + enum vb2_buffer_state buf_state = VB2_BUF_STATE_ERROR; + u32 dec_irq_ret; + u32 dec_ret; + int i; + + cancel_delayed_work(&jpeg->job_timeout_work); + + dec_ret = mtk_jpeg_dec_get_int_status(jpeg->reg_base); + dec_irq_ret = mtk_jpeg_dec_enum_result(dec_ret); + ctx = v4l2_m2m_get_curr_priv(jpeg->m2m_dev); + if (!ctx) { + v4l2_err(&jpeg->v4l2_dev, "Context is NULL\n"); + return IRQ_HANDLED; + } + + src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); + dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); + jpeg_src_buf = mtk_jpeg_vb2_to_srcbuf(&src_buf->vb2_buf); + + if (dec_irq_ret >= MTK_JPEG_DEC_RESULT_UNDERFLOW) + mtk_jpeg_dec_reset(jpeg->reg_base); + + if (dec_irq_ret != MTK_JPEG_DEC_RESULT_EOF_DONE) { + dev_err(jpeg->dev, "decode failed\n"); + goto dec_end; + } + + for (i = 0; i < dst_buf->vb2_buf.num_planes; i++) + vb2_set_plane_payload(&dst_buf->vb2_buf, i, + jpeg_src_buf->dec_param.comp_size[i]); + + buf_state = VB2_BUF_STATE_DONE; + +dec_end: + v4l2_m2m_buf_done(src_buf, buf_state); + v4l2_m2m_buf_done(dst_buf, buf_state); + v4l2_m2m_job_finish(jpeg->m2m_dev, ctx->fh.m2m_ctx); + pm_runtime_put(ctx->jpeg->dev); + return IRQ_HANDLED; +} + +static struct clk_bulk_data mtk_jpeg_clocks[] = { + { .id = "jpgenc" }, +}; + +static struct clk_bulk_data mt8173_jpeg_dec_clocks[] = { + { .id = "jpgdec-smi" }, + { .id = "jpgdec" }, +}; + static const struct mtk_jpeg_variant mt8173_jpeg_drvdata = { .clks = mt8173_jpeg_dec_clocks, .num_clks = ARRAY_SIZE(mt8173_jpeg_dec_clocks), diff --git a/drivers/media/platform/mediatek/jpeg/mtk_jpeg_dec_parse.c b/drivers/media/platform/mediatek/jpeg/mtk_jpeg_dec_parse.c index b95c45791c29edc5a80caba27e2c84ea00f718a3..bb9cdc9e0e90912bfb5f7d3afb0082a08c6045c0 100644 --- a/drivers/media/platform/mediatek/jpeg/mtk_jpeg_dec_parse.c +++ b/drivers/media/platform/mediatek/jpeg/mtk_jpeg_dec_parse.c @@ -7,15 +7,10 @@ #include #include +#include #include "mtk_jpeg_dec_parse.h" -#define TEM 0x01 -#define SOF0 0xc0 -#define RST 0xd0 -#define SOI 0xd8 -#define EOI 0xd9 - struct mtk_jpeg_stream { u8 *addr; u32 size; @@ -83,7 +78,7 @@ static bool mtk_jpeg_do_parse(struct mtk_jpeg_dec_param *param, u8 *src_addr_va, length = 0; switch (byte) { - case SOF0: + case JPEG_MARKER_SOF0: /* length */ if (read_word_be(&stream, &word)) break; @@ -123,10 +118,10 @@ static bool mtk_jpeg_do_parse(struct mtk_jpeg_dec_param *param, u8 *src_addr_va, notfound = !(i == param->comp_num); break; - case RST ... RST + 7: - case SOI: - case EOI: - case TEM: + case JPEG_MARKER_RST ... JPEG_MARKER_RST + 7: + case JPEG_MARKER_SOI: + case JPEG_MARKER_EOI: + case JPEG_MARKER_TEM: break; default: if (read_word_be(&stream, &word)) diff --git a/drivers/media/platform/mediatek/mdp3/mtk-mdp3-comp.c b/drivers/media/platform/mediatek/mdp3/mtk-mdp3-comp.c index 19a4a085f73a1dc540e92da8a08c91f718981cda..a605e80c7dc366b3032793dbb8250d5ec25d00d3 100644 --- a/drivers/media/platform/mediatek/mdp3/mtk-mdp3-comp.c +++ b/drivers/media/platform/mediatek/mdp3/mtk-mdp3-comp.c @@ -1035,6 +1035,7 @@ static int mdp_comp_sub_create(struct mdp_dev *mdp) { struct device *dev = &mdp->pdev->dev; struct device_node *node, *parent; + int ret = 0; parent = dev->of_node->parent; @@ -1060,16 +1061,22 @@ static int mdp_comp_sub_create(struct mdp_dev *mdp) dev_err(dev, "Fail to get sub comp. id: type %d alias %d\n", type, alias_id); - return -EINVAL; + ret = -EINVAL; + goto err_free_node; } mdp_comp_alias_id[type]++; comp = mdp_comp_create(mdp, node, id); - if (IS_ERR(comp)) - return PTR_ERR(comp); + if (IS_ERR(comp)) { + ret = PTR_ERR(comp); + goto err_free_node; + } } + return ret; - return 0; +err_free_node: + of_node_put(node); + return ret; } void mdp_comp_destroy(struct mdp_dev *mdp) diff --git a/drivers/media/platform/mediatek/vcodec/Makefile b/drivers/media/platform/mediatek/vcodec/Makefile index 93e7a343b5b0eaf487d9037516b2c0c4ee95efca..5f4c30fec85a6a390867830a7f102906aa2d932e 100644 --- a/drivers/media/platform/mediatek/vcodec/Makefile +++ b/drivers/media/platform/mediatek/vcodec/Makefile @@ -10,9 +10,11 @@ mtk-vcodec-dec-y := vdec/vdec_h264_if.o \ vdec/vdec_vp8_req_if.o \ vdec/vdec_vp9_if.o \ vdec/vdec_vp9_req_lat_if.o \ + vdec/vdec_av1_req_lat_if.o \ vdec/vdec_h264_req_if.o \ vdec/vdec_h264_req_common.o \ vdec/vdec_h264_req_multi_if.o \ + vdec/vdec_hevc_req_multi_if.o \ mtk_vcodec_dec_drv.o \ vdec_drv_if.o \ vdec_vpu_if.o \ @@ -44,3 +46,9 @@ endif ifneq ($(CONFIG_VIDEO_MEDIATEK_VCODEC_SCP),) mtk-vcodec-common-y += mtk_vcodec_fw_scp.o endif + +ifneq ($(CONFIG_DEBUG_FS),) +obj-$(CONFIG_VIDEO_MEDIATEK_VCODEC) += mtk-vcodec-dbgfs.o + +mtk-vcodec-dbgfs-y := mtk_vcodec_dbgfs.o +endif \ No newline at end of file diff --git a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dbgfs.c b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dbgfs.c new file mode 100644 index 0000000000000000000000000000000000000000..b5cdbbfcc388dbe63aea12e70065df47226b09cb --- /dev/null +++ b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dbgfs.c @@ -0,0 +1,215 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2023 MediaTek Inc. + * Author: Yunfei Dong + */ + +#include + +#include "mtk_vcodec_dbgfs.h" +#include "mtk_vcodec_drv.h" +#include "mtk_vcodec_util.h" + +static void mtk_vdec_dbgfs_get_format_type(struct mtk_vcodec_ctx *ctx, char *buf, + int *used, int total) +{ + int curr_len; + + switch (ctx->current_codec) { + case V4L2_PIX_FMT_H264_SLICE: + curr_len = snprintf(buf + *used, total - *used, + "\toutput format: h264 slice\n"); + break; + case V4L2_PIX_FMT_VP8_FRAME: + curr_len = snprintf(buf + *used, total - *used, + "\toutput format: vp8 slice\n"); + break; + case V4L2_PIX_FMT_VP9_FRAME: + curr_len = snprintf(buf + *used, total - *used, + "\toutput format: vp9 slice\n"); + break; + default: + curr_len = snprintf(buf + *used, total - *used, + "\tunsupported output format: 0x%x\n", + ctx->current_codec); + } + *used += curr_len; + + switch (ctx->capture_fourcc) { + case V4L2_PIX_FMT_MM21: + curr_len = snprintf(buf + *used, total - *used, + "\tcapture format: MM21\n"); + break; + case V4L2_PIX_FMT_MT21C: + curr_len = snprintf(buf + *used, total - *used, + "\tcapture format: MT21C\n"); + break; + default: + curr_len = snprintf(buf + *used, total - *used, + "\tunsupported capture format: 0x%x\n", + ctx->capture_fourcc); + } + *used += curr_len; +} + +static void mtk_vdec_dbgfs_get_help(char *buf, int *used, int total) +{ + int curr_len; + + curr_len = snprintf(buf + *used, total - *used, + "help: (1: echo -'info' > vdec 2: cat vdec)\n"); + *used += curr_len; + + curr_len = snprintf(buf + *used, total - *used, + "\t-picinfo: get resolution\n"); + *used += curr_len; + + curr_len = snprintf(buf + *used, total - *used, + "\t-format: get output & capture queue format\n"); + *used += curr_len; +} + +static ssize_t mtk_vdec_dbgfs_write(struct file *filp, const char __user *ubuf, + size_t count, loff_t *ppos) +{ + struct mtk_vcodec_dev *vcodec_dev = filp->private_data; + struct mtk_vcodec_dbgfs *dbgfs = &vcodec_dev->dbgfs; + + mutex_lock(&dbgfs->dbgfs_lock); + dbgfs->buf_size = simple_write_to_buffer(dbgfs->dbgfs_buf, sizeof(dbgfs->dbgfs_buf), + ppos, ubuf, count); + mutex_unlock(&dbgfs->dbgfs_lock); + if (dbgfs->buf_size > 0) + return count; + + return dbgfs->buf_size; +} + +static ssize_t mtk_vdec_dbgfs_read(struct file *filp, char __user *ubuf, + size_t count, loff_t *ppos) +{ + struct mtk_vcodec_dev *vcodec_dev = filp->private_data; + struct mtk_vcodec_dbgfs *dbgfs = &vcodec_dev->dbgfs; + struct mtk_vcodec_dbgfs_inst *dbgfs_inst; + struct mtk_vcodec_ctx *ctx; + int total_len = 200 * (dbgfs->inst_count == 0 ? 1 : dbgfs->inst_count); + int used_len = 0, curr_len, ret; + bool dbgfs_index[MTK_VDEC_DBGFS_MAX] = {0}; + char *buf = kmalloc(total_len, GFP_KERNEL); + + if (!buf) + return -ENOMEM; + + if (strstr(dbgfs->dbgfs_buf, "-help") || dbgfs->buf_size == 1) { + mtk_vdec_dbgfs_get_help(buf, &used_len, total_len); + goto read_buffer; + } + + if (strstr(dbgfs->dbgfs_buf, "-picinfo")) + dbgfs_index[MTK_VDEC_DBGFS_PICINFO] = true; + + if (strstr(dbgfs->dbgfs_buf, "-format")) + dbgfs_index[MTK_VDEC_DBGFS_FORMAT] = true; + + mutex_lock(&dbgfs->dbgfs_lock); + list_for_each_entry(dbgfs_inst, &dbgfs->dbgfs_head, node) { + ctx = dbgfs_inst->vcodec_ctx; + + curr_len = snprintf(buf + used_len, total_len - used_len, + "inst[%d]:\n ", ctx->id); + used_len += curr_len; + + if (dbgfs_index[MTK_VDEC_DBGFS_PICINFO]) { + curr_len = snprintf(buf + used_len, total_len - used_len, + "\treal(%dx%d)=>align(%dx%d)\n", + ctx->picinfo.pic_w, ctx->picinfo.pic_h, + ctx->picinfo.buf_w, ctx->picinfo.buf_h); + used_len += curr_len; + } + + if (dbgfs_index[MTK_VDEC_DBGFS_FORMAT]) + mtk_vdec_dbgfs_get_format_type(ctx, buf, &used_len, total_len); + } + mutex_unlock(&dbgfs->dbgfs_lock); +read_buffer: + ret = simple_read_from_buffer(ubuf, count, ppos, buf, used_len); + kfree(buf); + return ret; +} + +static const struct file_operations vdec_fops = { + .open = simple_open, + .write = mtk_vdec_dbgfs_write, + .read = mtk_vdec_dbgfs_read, +}; + +void mtk_vcodec_dbgfs_create(struct mtk_vcodec_ctx *ctx) +{ + struct mtk_vcodec_dbgfs_inst *dbgfs_inst; + struct mtk_vcodec_dev *vcodec_dev = ctx->dev; + + dbgfs_inst = kzalloc(sizeof(*dbgfs_inst), GFP_KERNEL); + if (!dbgfs_inst) + return; + + list_add_tail(&dbgfs_inst->node, &vcodec_dev->dbgfs.dbgfs_head); + + vcodec_dev->dbgfs.inst_count++; + + dbgfs_inst->inst_id = ctx->id; + dbgfs_inst->vcodec_ctx = ctx; +} +EXPORT_SYMBOL_GPL(mtk_vcodec_dbgfs_create); + +void mtk_vcodec_dbgfs_remove(struct mtk_vcodec_dev *vcodec_dev, int ctx_id) +{ + struct mtk_vcodec_dbgfs_inst *dbgfs_inst; + + list_for_each_entry(dbgfs_inst, &vcodec_dev->dbgfs.dbgfs_head, node) { + if (dbgfs_inst->inst_id == ctx_id) { + vcodec_dev->dbgfs.inst_count--; + break; + } + } + + if (dbgfs_inst) { + list_del(&dbgfs_inst->node); + kfree(dbgfs_inst); + } +} +EXPORT_SYMBOL_GPL(mtk_vcodec_dbgfs_remove); + +void mtk_vcodec_dbgfs_init(struct mtk_vcodec_dev *vcodec_dev, bool is_encode) +{ + struct dentry *vcodec_root; + + if (is_encode) + vcodec_dev->dbgfs.vcodec_root = debugfs_create_dir("vcodec-enc", NULL); + else + vcodec_dev->dbgfs.vcodec_root = debugfs_create_dir("vcodec-dec", NULL); + if (IS_ERR(vcodec_dev->dbgfs.vcodec_root)) + dev_err(&vcodec_dev->plat_dev->dev, "create vcodec dir err:%d\n", + IS_ERR(vcodec_dev->dbgfs.vcodec_root)); + + vcodec_root = vcodec_dev->dbgfs.vcodec_root; + debugfs_create_x32("mtk_v4l2_dbg_level", 0644, vcodec_root, &mtk_v4l2_dbg_level); + debugfs_create_x32("mtk_vcodec_dbg", 0644, vcodec_root, &mtk_vcodec_dbg); + + vcodec_dev->dbgfs.inst_count = 0; + if (is_encode) + return; + + INIT_LIST_HEAD(&vcodec_dev->dbgfs.dbgfs_head); + debugfs_create_file("vdec", 0200, vcodec_root, vcodec_dev, &vdec_fops); + mutex_init(&vcodec_dev->dbgfs.dbgfs_lock); +} +EXPORT_SYMBOL_GPL(mtk_vcodec_dbgfs_init); + +void mtk_vcodec_dbgfs_deinit(struct mtk_vcodec_dev *vcodec_dev) +{ + debugfs_remove_recursive(vcodec_dev->dbgfs.vcodec_root); +} +EXPORT_SYMBOL_GPL(mtk_vcodec_dbgfs_deinit); + +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("Mediatek video codec driver"); diff --git a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dbgfs.h b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dbgfs.h new file mode 100644 index 0000000000000000000000000000000000000000..241ff8197e73069b20a2a67f3206924741002f9d --- /dev/null +++ b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dbgfs.h @@ -0,0 +1,74 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2023 MediaTek Inc. + * Author: Yunfei Dong + */ + +#ifndef __MTK_VCODEC_DBGFS_H__ +#define __MTK_VCODEC_DBGFS_H__ + +struct mtk_vcodec_dev; +struct mtk_vcodec_ctx; + +/* + * enum mtk_vdec_dbgfs_log_index - used to get different debug information + */ +enum mtk_vdec_dbgfs_log_index { + MTK_VDEC_DBGFS_PICINFO, + MTK_VDEC_DBGFS_FORMAT, + MTK_VDEC_DBGFS_MAX, +}; + +/** + * struct mtk_vcodec_dbgfs_inst - debugfs information for each inst + * @node: list node for each inst + * @vcodec_ctx: struct mtk_vcodec_ctx + * @inst_id: index of the context that the same with ctx->id + */ +struct mtk_vcodec_dbgfs_inst { + struct list_head node; + struct mtk_vcodec_ctx *vcodec_ctx; + int inst_id; +}; + +/** + * struct mtk_vcodec_dbgfs - dbgfs information + * @dbgfs_head: list head used to link each instance + * @vcodec_root: vcodec dbgfs entry + * @dbgfs_lock: dbgfs lock used to protect dbgfs_buf + * @dbgfs_buf: dbgfs buf used to store dbgfs cmd + * @buf_size: buffer size of dbgfs + * @inst_count: the count of total instance + */ +struct mtk_vcodec_dbgfs { + struct list_head dbgfs_head; + struct dentry *vcodec_root; + struct mutex dbgfs_lock; + char dbgfs_buf[1024]; + int buf_size; + int inst_count; +}; + +#if defined(CONFIG_DEBUG_FS) +void mtk_vcodec_dbgfs_create(struct mtk_vcodec_ctx *ctx); +void mtk_vcodec_dbgfs_remove(struct mtk_vcodec_dev *vcodec_dev, int ctx_id); +void mtk_vcodec_dbgfs_init(struct mtk_vcodec_dev *vcodec_dev, bool is_encode); +void mtk_vcodec_dbgfs_deinit(struct mtk_vcodec_dev *vcodec_dev); +#else +static inline void mtk_vcodec_dbgfs_create(struct mtk_vcodec_ctx *ctx) +{ +} + +static inline void mtk_vcodec_dbgfs_remove(struct mtk_vcodec_dev *vcodec_dev, int ctx_id) +{ +} + +static inline void mtk_vcodec_dbgfs_init(struct mtk_vcodec_dev *vcodec_dev, bool is_encode) +{ +} + +static inline void mtk_vcodec_dbgfs_deinit(struct mtk_vcodec_dev *vcodec_dev) +{ +} +#endif +#endif diff --git a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_drv.c b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_drv.c index 9c652beb3f193bc2226ae0678a92eff1df68e2bc..d41f2121b94fbde397e389d58d25ee2271da82d7 100644 --- a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_drv.c +++ b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_drv.c @@ -215,6 +215,7 @@ static int fops_vcodec_open(struct file *file) ctx->dev->vdec_pdata->init_vdec_params(ctx); list_add(&ctx->list, &dev->ctx_list); + mtk_vcodec_dbgfs_create(ctx); mutex_unlock(&dev->dev_mutex); mtk_v4l2_debug(0, "%s decoder [%d]", dev_name(&dev->plat_dev->dev), @@ -256,6 +257,7 @@ static int fops_vcodec_release(struct file *file) v4l2_fh_exit(&ctx->fh); v4l2_ctrl_handler_free(&ctx->ctrl_hdl); + mtk_vcodec_dbgfs_remove(dev, ctx->id); list_del_init(&ctx->list); kfree(ctx); mutex_unlock(&dev->dev_mutex); @@ -310,7 +312,6 @@ static int mtk_vcodec_probe(struct platform_device *pdev) } if (IS_VDEC_LAT_ARCH(dev->vdec_pdata->hw_arch)) { - vdec_msg_queue_init_ctx(&dev->msg_queue_core_ctx, MTK_VDEC_CORE); dev->core_workqueue = alloc_ordered_workqueue("core-decoder", WQ_MEM_RECLAIM | WQ_FREEZABLE); @@ -423,6 +424,7 @@ static int mtk_vcodec_probe(struct platform_device *pdev) mtk_v4l2_debug(0, "media registered as /dev/media%d", vfd_dec->minor); } + mtk_vcodec_dbgfs_init(dev, false); mtk_v4l2_debug(0, "decoder registered as /dev/video%d", vfd_dec->minor); return 0; @@ -498,6 +500,7 @@ static void mtk_vcodec_dec_remove(struct platform_device *pdev) if (dev->vfd_dec) video_unregister_device(dev->vfd_dec); + mtk_vcodec_dbgfs_deinit(dev); v4l2_device_unregister(&dev->v4l2_dev); if (!dev->vdec_pdata->is_subdev_supported) pm_runtime_disable(dev->pm.dev); diff --git a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_hw.c b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_hw.c index b753bf54ebd90854aba8d39ca71047afa0636eb2..e1cb2f8dca33075307de2c448faa43c36a77fca7 100644 --- a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_hw.c +++ b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_hw.c @@ -148,20 +148,21 @@ static int mtk_vdec_hw_probe(struct platform_device *pdev) ret = mtk_vcodec_init_dec_clk(pdev, &subdev_dev->pm); if (ret) return ret; - pm_runtime_enable(&pdev->dev); + + ret = devm_pm_runtime_enable(&pdev->dev); + if (ret) + return ret; of_id = of_match_device(mtk_vdec_hw_match, dev); if (!of_id) { dev_err(dev, "Can't get vdec subdev id.\n"); - ret = -EINVAL; - goto err; + return -EINVAL; } hw_idx = (enum mtk_vdec_hw_id)(uintptr_t)of_id->data; if (hw_idx >= MTK_VDEC_HW_MAX) { dev_err(dev, "Hardware index %d not correct.\n", hw_idx); - ret = -EINVAL; - goto err; + return -EINVAL; } main_dev->subdev_dev[hw_idx] = subdev_dev; @@ -173,36 +174,25 @@ static int mtk_vdec_hw_probe(struct platform_device *pdev) if (IS_SUPPORT_VDEC_HW_IRQ(hw_idx)) { ret = mtk_vdec_hw_init_irq(subdev_dev); if (ret) - goto err; + return ret; } subdev_dev->reg_base[VDEC_HW_MISC] = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR((__force void *)subdev_dev->reg_base[VDEC_HW_MISC])) { ret = PTR_ERR((__force void *)subdev_dev->reg_base[VDEC_HW_MISC]); - goto err; + return ret; } if (!main_dev->subdev_prob_done) main_dev->subdev_prob_done = mtk_vdec_hw_prob_done; platform_set_drvdata(pdev, subdev_dev); - return 0; -err: - pm_runtime_disable(subdev_dev->pm.dev); - return ret; -} - -static int mtk_vdec_hw_remove(struct platform_device *pdev) -{ - pm_runtime_disable(&pdev->dev); - return 0; } static struct platform_driver mtk_vdec_driver = { .probe = mtk_vdec_hw_probe, - .remove = mtk_vdec_hw_remove, .driver = { .name = "mtk-vdec-comp", .of_match_table = mtk_vdec_hw_match, diff --git a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_stateless.c b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_stateless.c index 3000db975e5f5fa2b6831ccae60b205809186cd8..db1e14a1bd6c100cc07899c420ada2271ba4388a 100644 --- a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_stateless.c +++ b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_stateless.c @@ -107,11 +107,103 @@ static const struct mtk_stateless_control mtk_stateless_controls[] = { }, .codec_type = V4L2_PIX_FMT_VP9_FRAME, }, + { + .cfg = { + .id = V4L2_CID_STATELESS_HEVC_SPS, + }, + .codec_type = V4L2_PIX_FMT_HEVC_SLICE, + }, + { + .cfg = { + .id = V4L2_CID_STATELESS_HEVC_PPS, + }, + .codec_type = V4L2_PIX_FMT_HEVC_SLICE, + }, + { + .cfg = { + .id = V4L2_CID_STATELESS_HEVC_SCALING_MATRIX, + }, + .codec_type = V4L2_PIX_FMT_HEVC_SLICE, + }, + { + .cfg = { + .id = V4L2_CID_STATELESS_HEVC_DECODE_PARAMS, + }, + .codec_type = V4L2_PIX_FMT_HEVC_SLICE, + }, + { + .cfg = { + .id = V4L2_CID_MPEG_VIDEO_HEVC_PROFILE, + .def = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN, + .max = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10, + .menu_skip_mask = + BIT(V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_STILL_PICTURE), + }, + .codec_type = V4L2_PIX_FMT_HEVC_SLICE, + }, + { + .cfg = { + .id = V4L2_CID_STATELESS_HEVC_DECODE_MODE, + .min = V4L2_STATELESS_HEVC_DECODE_MODE_FRAME_BASED, + .def = V4L2_STATELESS_HEVC_DECODE_MODE_FRAME_BASED, + .max = V4L2_STATELESS_HEVC_DECODE_MODE_FRAME_BASED, + }, + .codec_type = V4L2_PIX_FMT_HEVC_SLICE, + }, + { + .cfg = { + .id = V4L2_CID_STATELESS_HEVC_START_CODE, + .min = V4L2_STATELESS_HEVC_START_CODE_ANNEX_B, + .def = V4L2_STATELESS_HEVC_START_CODE_ANNEX_B, + .max = V4L2_STATELESS_HEVC_START_CODE_ANNEX_B, + }, + .codec_type = V4L2_PIX_FMT_HEVC_SLICE, + }, + { + .cfg = { + .id = V4L2_CID_STATELESS_AV1_SEQUENCE, + + }, + .codec_type = V4L2_PIX_FMT_AV1_FRAME, + }, + { + .cfg = { + .id = V4L2_CID_STATELESS_AV1_FRAME, + + }, + .codec_type = V4L2_PIX_FMT_AV1_FRAME, + }, + { + .cfg = { + .id = V4L2_CID_STATELESS_AV1_TILE_GROUP_ENTRY, + .dims = { V4L2_AV1_MAX_TILE_COUNT }, + + }, + .codec_type = V4L2_PIX_FMT_AV1_FRAME, + }, + { + .cfg = { + .id = V4L2_CID_MPEG_VIDEO_AV1_PROFILE, + .min = V4L2_MPEG_VIDEO_AV1_PROFILE_MAIN, + .def = V4L2_MPEG_VIDEO_AV1_PROFILE_MAIN, + .max = V4L2_MPEG_VIDEO_AV1_PROFILE_MAIN, + }, + .codec_type = V4L2_PIX_FMT_AV1_FRAME, + }, + { + .cfg = { + .id = V4L2_CID_MPEG_VIDEO_AV1_LEVEL, + .min = V4L2_MPEG_VIDEO_AV1_LEVEL_2_0, + .def = V4L2_MPEG_VIDEO_AV1_LEVEL_4_0, + .max = V4L2_MPEG_VIDEO_AV1_LEVEL_5_1, + }, + .codec_type = V4L2_PIX_FMT_AV1_FRAME, + }, }; #define NUM_CTRLS ARRAY_SIZE(mtk_stateless_controls) -static struct mtk_video_fmt mtk_video_formats[5]; +static struct mtk_video_fmt mtk_video_formats[7]; static struct mtk_video_fmt default_out_format; static struct mtk_video_fmt default_cap_format; @@ -240,7 +332,7 @@ static void mtk_vdec_worker(struct work_struct *work) mtk_v4l2_err("vb2 buffer media request is NULL"); ret = vdec_if_decode(ctx, bs_src, NULL, &res_chg); - if (ret) { + if (ret && ret != -EAGAIN) { mtk_v4l2_err(" <===[%d], src_buf[%d] sz=0x%zx pts=%llu vdec_if_decode() ret=%d res_chg=%d===>", ctx->id, vb2_src->index, bs_src->size, vb2_src->timestamp, ret, res_chg); @@ -356,6 +448,8 @@ static void mtk_vcodec_add_formats(unsigned int fourcc, case V4L2_PIX_FMT_H264_SLICE: case V4L2_PIX_FMT_VP8_FRAME: case V4L2_PIX_FMT_VP9_FRAME: + case V4L2_PIX_FMT_HEVC_SLICE: + case V4L2_PIX_FMT_AV1_FRAME: mtk_video_formats[count_formats].fourcc = fourcc; mtk_video_formats[count_formats].type = MTK_FMT_DEC; mtk_video_formats[count_formats].num_planes = 1; @@ -412,6 +506,14 @@ static void mtk_vcodec_get_supported_formats(struct mtk_vcodec_ctx *ctx) mtk_vcodec_add_formats(V4L2_PIX_FMT_VP9_FRAME, ctx); out_format_count++; } + if (ctx->dev->dec_capability & MTK_VDEC_FORMAT_HEVC_FRAME) { + mtk_vcodec_add_formats(V4L2_PIX_FMT_HEVC_SLICE, ctx); + out_format_count++; + } + if (ctx->dev->dec_capability & MTK_VDEC_FORMAT_AV1_FRAME) { + mtk_vcodec_add_formats(V4L2_PIX_FMT_AV1_FRAME, ctx); + out_format_count++; + } if (cap_format_count) default_cap_format = mtk_video_formats[cap_format_count - 1]; diff --git a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_drv.h b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_drv.h index 9acab54fd65017cc48d840593a8ad416be83e085..f17d67e781c9381b9eca2fb6c07fba4d2c0c2b19 100644 --- a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_drv.h +++ b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_drv.h @@ -16,6 +16,7 @@ #include #include +#include "mtk_vcodec_dbgfs.h" #include "mtk_vcodec_util.h" #include "vdec_msg_queue.h" @@ -347,6 +348,8 @@ enum mtk_vdec_format_types { MTK_VDEC_FORMAT_H264_SLICE = 0x100, MTK_VDEC_FORMAT_VP8_FRAME = 0x200, MTK_VDEC_FORMAT_VP9_FRAME = 0x400, + MTK_VDEC_FORMAT_AV1_FRAME = 0x800, + MTK_VDEC_FORMAT_HEVC_FRAME = 0x1000, MTK_VCODEC_INNER_RACING = 0x20000, }; @@ -461,7 +464,6 @@ struct mtk_vcodec_enc_pdata { * @enc_capability: used to identify encode capability * * @core_workqueue: queue used for core hardware decode - * @msg_queue_core_ctx: msg queue context used for core workqueue * * @subdev_dev: subdev hardware device * @subdev_prob_done: check whether all used hw device is prob done @@ -470,6 +472,7 @@ struct mtk_vcodec_enc_pdata { * @dec_active_cnt: used to mark whether need to record register value * @vdec_racing_info: record register value * @dec_racing_info_mutex: mutex lock used for inner racing mode + * @dbgfs: debug log related information */ struct mtk_vcodec_dev { struct v4l2_device v4l2_dev; @@ -510,7 +513,6 @@ struct mtk_vcodec_dev { unsigned int enc_capability; struct workqueue_struct *core_workqueue; - struct vdec_msg_queue_ctx msg_queue_core_ctx; void *subdev_dev[MTK_VDEC_HW_MAX]; int (*subdev_prob_done)(struct mtk_vcodec_dev *vdec_dev); @@ -520,6 +522,8 @@ struct mtk_vcodec_dev { u32 vdec_racing_info[132]; /* Protects access to vdec_racing_info data */ struct mutex dec_racing_info_mutex; + + struct mtk_vcodec_dbgfs dbgfs; }; static inline struct mtk_vcodec_ctx *fh_to_ctx(struct v4l2_fh *fh) diff --git a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_enc.c b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_enc.c index db65e77bd37339fd37b5b6478f87a4c415418618..9ff439a50f534662876ae2630ad2303450d681b5 100644 --- a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_enc.c +++ b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_enc.c @@ -505,13 +505,13 @@ static int vidioc_venc_s_fmt_out(struct file *file, void *priv, f->fmt.pix.pixelformat = fmt->fourcc; } - q_data->visible_width = f->fmt.pix_mp.width; - q_data->visible_height = f->fmt.pix_mp.height; - q_data->fmt = fmt; - ret = vidioc_try_fmt_out(ctx, f, q_data->fmt); + ret = vidioc_try_fmt_out(ctx, f, fmt); if (ret) return ret; + q_data->fmt = fmt; + q_data->visible_width = f->fmt.pix_mp.width; + q_data->visible_height = f->fmt.pix_mp.height; q_data->coded_width = f->fmt.pix_mp.width; q_data->coded_height = f->fmt.pix_mp.height; diff --git a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_enc_drv.c b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_enc_drv.c index 168004a08888ff12c27cbd8b0c6be9fd526bb085..5df0a22ff3b52c106708f389461258be33e91b00 100644 --- a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_enc_drv.c +++ b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_enc_drv.c @@ -358,6 +358,7 @@ static int mtk_vcodec_probe(struct platform_device *pdev) goto err_enc_reg; } + mtk_vcodec_dbgfs_init(dev, true); mtk_v4l2_debug(0, "encoder %d registered as /dev/video%d", dev->venc_pdata->core_id, vfd_enc->num); @@ -468,6 +469,7 @@ static void mtk_vcodec_enc_remove(struct platform_device *pdev) if (dev->vfd_enc) video_unregister_device(dev->vfd_enc); + mtk_vcodec_dbgfs_deinit(dev); v4l2_device_unregister(&dev->v4l2_dev); pm_runtime_disable(dev->pm.dev); mtk_vcodec_fw_release(dev->fw_handler); diff --git a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_util.c b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_util.c index ace78c4b5b9eabfb4c38af667006401275cfdf64..f214e6f67005df48f317b1802230c27a57fe841a 100644 --- a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_util.c +++ b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_util.c @@ -13,6 +13,14 @@ #include "mtk_vcodec_drv.h" #include "mtk_vcodec_util.h" +#if defined(CONFIG_DEBUG_FS) +int mtk_vcodec_dbg; +EXPORT_SYMBOL(mtk_vcodec_dbg); + +int mtk_v4l2_dbg_level; +EXPORT_SYMBOL(mtk_v4l2_dbg_level); +#endif + void __iomem *mtk_vcodec_get_reg_addr(struct mtk_vcodec_ctx *data, unsigned int reg_idx) { diff --git a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_util.h b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_util.h index 71956627a0e2ba7c2e82a5a96264d4ec8bda7b69..88d389b65f13f94f769d78916620f9c296a3d34b 100644 --- a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_util.h +++ b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_util.h @@ -35,15 +35,35 @@ struct mtk_vcodec_dev; pr_err("[MTK_VCODEC][ERROR][%d]: " fmt "\n", \ ((struct mtk_vcodec_ctx *)(h)->ctx)->id, ##args) +#if defined(CONFIG_DEBUG_FS) +extern int mtk_v4l2_dbg_level; +extern int mtk_vcodec_dbg; -#define mtk_v4l2_debug(level, fmt, args...) pr_debug(fmt, ##args) +#define mtk_v4l2_debug(level, fmt, args...) \ + do { \ + if (mtk_v4l2_dbg_level >= (level)) \ + pr_debug("[MTK_V4L2] %s, %d: " fmt "\n", \ + __func__, __LINE__, ##args); \ + } while (0) -#define mtk_v4l2_debug_enter() mtk_v4l2_debug(3, "+") -#define mtk_v4l2_debug_leave() mtk_v4l2_debug(3, "-") +#define mtk_vcodec_debug(h, fmt, args...) \ + do { \ + if (mtk_vcodec_dbg) \ + dev_dbg(&(((struct mtk_vcodec_ctx *)(h)->ctx)->dev->plat_dev->dev), \ + "[MTK_VCODEC][%d]: %s, %d " fmt "\n", \ + ((struct mtk_vcodec_ctx *)(h)->ctx)->id, \ + __func__, __LINE__, ##args); \ + } while (0) +#else +#define mtk_v4l2_debug(level, fmt, args...) pr_debug(fmt, ##args) #define mtk_vcodec_debug(h, fmt, args...) \ pr_debug("[MTK_VCODEC][%d]: " fmt "\n", \ ((struct mtk_vcodec_ctx *)(h)->ctx)->id, ##args) +#endif + +#define mtk_v4l2_debug_enter() mtk_v4l2_debug(3, "+") +#define mtk_v4l2_debug_leave() mtk_v4l2_debug(3, "-") #define mtk_vcodec_debug_enter(h) mtk_vcodec_debug(h, "+") #define mtk_vcodec_debug_leave(h) mtk_vcodec_debug(h, "-") diff --git a/drivers/media/platform/mediatek/vcodec/vdec/vdec_av1_req_lat_if.c b/drivers/media/platform/mediatek/vcodec/vdec/vdec_av1_req_lat_if.c new file mode 100644 index 0000000000000000000000000000000000000000..404a1a23fd402298c3e9245ab83ff4604d07418a --- /dev/null +++ b/drivers/media/platform/mediatek/vcodec/vdec/vdec_av1_req_lat_if.c @@ -0,0 +1,2207 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2023 MediaTek Inc. + * Author: Xiaoyong Lu + */ + +#include +#include +#include + +#include "../mtk_vcodec_util.h" +#include "../mtk_vcodec_dec.h" +#include "../mtk_vcodec_intr.h" +#include "../vdec_drv_base.h" +#include "../vdec_drv_if.h" +#include "../vdec_vpu_if.h" + +#define AV1_MAX_FRAME_BUF_COUNT (V4L2_AV1_TOTAL_REFS_PER_FRAME + 1) +#define AV1_TILE_BUF_SIZE 64 +#define AV1_SCALE_SUBPEL_BITS 10 +#define AV1_REF_SCALE_SHIFT 14 +#define AV1_REF_NO_SCALE BIT(AV1_REF_SCALE_SHIFT) +#define AV1_REF_INVALID_SCALE -1 +#define AV1_CDF_TABLE_BUFFER_SIZE 16384 +#define AV1_PRIMARY_REF_NONE 7 + +#define AV1_INVALID_IDX -1 + +#define AV1_DIV_ROUND_UP_POW2(value, n) \ +({ \ + typeof(n) _n = n; \ + typeof(value) _value = value; \ + (_value + (BIT(_n) >> 1)) >> _n; \ +}) + +#define AV1_DIV_ROUND_UP_POW2_SIGNED(value, n) \ +({ \ + typeof(n) _n_ = n; \ + typeof(value) _value_ = value; \ + (((_value_) < 0) ? -AV1_DIV_ROUND_UP_POW2(-(_value_), (_n_)) \ + : AV1_DIV_ROUND_UP_POW2((_value_), (_n_))); \ +}) + +#define BIT_FLAG(x, bit) (!!((x)->flags & (bit))) +#define SEGMENTATION_FLAG(x, name) (!!((x)->flags & V4L2_AV1_SEGMENTATION_FLAG_##name)) +#define QUANT_FLAG(x, name) (!!((x)->flags & V4L2_AV1_QUANTIZATION_FLAG_##name)) +#define SEQUENCE_FLAG(x, name) (!!((x)->flags & V4L2_AV1_SEQUENCE_FLAG_##name)) +#define FH_FLAG(x, name) (!!((x)->flags & V4L2_AV1_FRAME_FLAG_##name)) + +#define MINQ 0 +#define MAXQ 255 + +#define DIV_LUT_PREC_BITS 14 +#define DIV_LUT_BITS 8 +#define DIV_LUT_NUM BIT(DIV_LUT_BITS) +#define WARP_PARAM_REDUCE_BITS 6 +#define WARPEDMODEL_PREC_BITS 16 + +#define SEG_LVL_ALT_Q 0 +#define SECONDARY_FILTER_STRENGTH_NUM_BITS 2 + +static const short div_lut[DIV_LUT_NUM + 1] = { + 16384, 16320, 16257, 16194, 16132, 16070, 16009, 15948, 15888, 15828, 15768, + 15709, 15650, 15592, 15534, 15477, 15420, 15364, 15308, 15252, 15197, 15142, + 15087, 15033, 14980, 14926, 14873, 14821, 14769, 14717, 14665, 14614, 14564, + 14513, 14463, 14413, 14364, 14315, 14266, 14218, 14170, 14122, 14075, 14028, + 13981, 13935, 13888, 13843, 13797, 13752, 13707, 13662, 13618, 13574, 13530, + 13487, 13443, 13400, 13358, 13315, 13273, 13231, 13190, 13148, 13107, 13066, + 13026, 12985, 12945, 12906, 12866, 12827, 12788, 12749, 12710, 12672, 12633, + 12596, 12558, 12520, 12483, 12446, 12409, 12373, 12336, 12300, 12264, 12228, + 12193, 12157, 12122, 12087, 12053, 12018, 11984, 11950, 11916, 11882, 11848, + 11815, 11782, 11749, 11716, 11683, 11651, 11619, 11586, 11555, 11523, 11491, + 11460, 11429, 11398, 11367, 11336, 11305, 11275, 11245, 11215, 11185, 11155, + 11125, 11096, 11067, 11038, 11009, 10980, 10951, 10923, 10894, 10866, 10838, + 10810, 10782, 10755, 10727, 10700, 10673, 10645, 10618, 10592, 10565, 10538, + 10512, 10486, 10460, 10434, 10408, 10382, 10356, 10331, 10305, 10280, 10255, + 10230, 10205, 10180, 10156, 10131, 10107, 10082, 10058, 10034, 10010, 9986, + 9963, 9939, 9916, 9892, 9869, 9846, 9823, 9800, 9777, 9754, 9732, + 9709, 9687, 9664, 9642, 9620, 9598, 9576, 9554, 9533, 9511, 9489, + 9468, 9447, 9425, 9404, 9383, 9362, 9341, 9321, 9300, 9279, 9259, + 9239, 9218, 9198, 9178, 9158, 9138, 9118, 9098, 9079, 9059, 9039, + 9020, 9001, 8981, 8962, 8943, 8924, 8905, 8886, 8867, 8849, 8830, + 8812, 8793, 8775, 8756, 8738, 8720, 8702, 8684, 8666, 8648, 8630, + 8613, 8595, 8577, 8560, 8542, 8525, 8508, 8490, 8473, 8456, 8439, + 8422, 8405, 8389, 8372, 8355, 8339, 8322, 8306, 8289, 8273, 8257, + 8240, 8224, 8208, 8192, +}; + +/** + * struct vdec_av1_slice_init_vsi - VSI used to initialize instance + * @architecture: architecture type + * @reserved: reserved + * @core_vsi: for core vsi + * @cdf_table_addr: cdf table addr + * @cdf_table_size: cdf table size + * @iq_table_addr: iq table addr + * @iq_table_size: iq table size + * @vsi_size: share vsi structure size + */ +struct vdec_av1_slice_init_vsi { + u32 architecture; + u32 reserved; + u64 core_vsi; + u64 cdf_table_addr; + u32 cdf_table_size; + u64 iq_table_addr; + u32 iq_table_size; + u32 vsi_size; +}; + +/** + * struct vdec_av1_slice_mem - memory address and size + * @buf: dma_addr padding + * @dma_addr: buffer address + * @size: buffer size + * @dma_addr_end: buffer end address + * @padding: for padding + */ +struct vdec_av1_slice_mem { + union { + u64 buf; + dma_addr_t dma_addr; + }; + union { + size_t size; + dma_addr_t dma_addr_end; + u64 padding; + }; +}; + +/** + * struct vdec_av1_slice_state - decoding state + * @err : err type for decode + * @full : transcoded buffer is full or not + * @timeout : decode timeout or not + * @perf : performance enable + * @crc : hw checksum + * @out_size : hw output size + */ +struct vdec_av1_slice_state { + int err; + u32 full; + u32 timeout; + u32 perf; + u32 crc[16]; + u32 out_size; +}; + +/* + * enum vdec_av1_slice_resolution_level - resolution level + */ +enum vdec_av1_slice_resolution_level { + AV1_RES_NONE, + AV1_RES_FHD, + AV1_RES_4K, + AV1_RES_8K, +}; + +/* + * enum vdec_av1_slice_frame_type - av1 frame type + */ +enum vdec_av1_slice_frame_type { + AV1_KEY_FRAME = 0, + AV1_INTER_FRAME, + AV1_INTRA_ONLY_FRAME, + AV1_SWITCH_FRAME, + AV1_FRAME_TYPES, +}; + +/* + * enum vdec_av1_slice_reference_mode - reference mode type + */ +enum vdec_av1_slice_reference_mode { + AV1_SINGLE_REFERENCE = 0, + AV1_COMPOUND_REFERENCE, + AV1_REFERENCE_MODE_SELECT, + AV1_REFERENCE_MODES, +}; + +/** + * struct vdec_av1_slice_tile_group - info for each tile + * @num_tiles: tile number + * @tile_size: input size for each tile + * @tile_start_offset: tile offset to input buffer + */ +struct vdec_av1_slice_tile_group { + u32 num_tiles; + u32 tile_size[V4L2_AV1_MAX_TILE_COUNT]; + u32 tile_start_offset[V4L2_AV1_MAX_TILE_COUNT]; +}; + +/** + * struct vdec_av1_slice_scale_factors - scale info for each ref frame + * @is_scaled: frame is scaled or not + * @x_scale: frame width scale coefficient + * @y_scale: frame height scale coefficient + * @x_step: width step for x_scale + * @y_step: height step for y_scale + */ +struct vdec_av1_slice_scale_factors { + u8 is_scaled; + int x_scale; + int y_scale; + int x_step; + int y_step; +}; + +/** + * struct vdec_av1_slice_frame_refs - ref frame info + * @ref_fb_idx: ref slot index + * @ref_map_idx: ref frame index + * @scale_factors: scale factors for each ref frame + */ +struct vdec_av1_slice_frame_refs { + int ref_fb_idx; + int ref_map_idx; + struct vdec_av1_slice_scale_factors scale_factors; +}; + +/** + * struct vdec_av1_slice_gm - AV1 Global Motion parameters + * @wmtype: The type of global motion transform used + * @wmmat: gm_params + * @alpha: alpha info + * @beta: beta info + * @gamma: gamma info + * @delta: delta info + * @invalid: is invalid or not + */ +struct vdec_av1_slice_gm { + int wmtype; + int wmmat[8]; + short alpha; + short beta; + short gamma; + short delta; + char invalid; +}; + +/** + * struct vdec_av1_slice_sm - AV1 Skip Mode parameters + * @skip_mode_allowed: Skip Mode is allowed or not + * @skip_mode_present: specified that the skip_mode will be present or not + * @skip_mode_frame: specifies the frames to use for compound prediction + */ +struct vdec_av1_slice_sm { + u8 skip_mode_allowed; + u8 skip_mode_present; + int skip_mode_frame[2]; +}; + +/** + * struct vdec_av1_slice_seg - AV1 Segmentation params + * @segmentation_enabled: this frame makes use of the segmentation tool or not + * @segmentation_update_map: segmentation map are updated during the decoding frame + * @segmentation_temporal_update:segmentation map are coded relative the existing segmentaion map + * @segmentation_update_data: new parameters are about to be specified for each segment + * @feature_data: specifies the feature data for a segment feature + * @feature_enabled_mask: the corresponding feature value is coded or not. + * @segid_preskip: segment id will be read before the skip syntax element. + * @last_active_segid: the highest numbered segment id that has some enabled feature + */ +struct vdec_av1_slice_seg { + u8 segmentation_enabled; + u8 segmentation_update_map; + u8 segmentation_temporal_update; + u8 segmentation_update_data; + int feature_data[V4L2_AV1_MAX_SEGMENTS][V4L2_AV1_SEG_LVL_MAX]; + u16 feature_enabled_mask[V4L2_AV1_MAX_SEGMENTS]; + int segid_preskip; + int last_active_segid; +}; + +/** + * struct vdec_av1_slice_delta_q_lf - AV1 Loop Filter delta parameters + * @delta_q_present: specified whether quantizer index delta values are present + * @delta_q_res: specifies the left shift which should be applied to decoded quantizer index + * @delta_lf_present: specifies whether loop filter delta values are present + * @delta_lf_res: specifies the left shift which should be applied to decoded + * loop filter delta values + * @delta_lf_multi: specifies that separate loop filter deltas are sent for horizontal + * luma edges,vertical luma edges,the u edges, and the v edges. + */ +struct vdec_av1_slice_delta_q_lf { + u8 delta_q_present; + u8 delta_q_res; + u8 delta_lf_present; + u8 delta_lf_res; + u8 delta_lf_multi; +}; + +/** + * struct vdec_av1_slice_quantization - AV1 Quantization params + * @base_q_idx: indicates the base frame qindex. This is used for Y AC + * coefficients and as the base value for the other quantizers. + * @qindex: qindex + * @delta_qydc: indicates the Y DC quantizer relative to base_q_idx + * @delta_qudc: indicates the U DC quantizer relative to base_q_idx. + * @delta_quac: indicates the U AC quantizer relative to base_q_idx + * @delta_qvdc: indicates the V DC quantizer relative to base_q_idx + * @delta_qvac: indicates the V AC quantizer relative to base_q_idx + * @using_qmatrix: specifies that the quantizer matrix will be used to + * compute quantizers + * @qm_y: specifies the level in the quantizer matrix that should + * be used for luma plane decoding + * @qm_u: specifies the level in the quantizer matrix that should + * be used for chroma U plane decoding. + * @qm_v: specifies the level in the quantizer matrix that should be + * used for chroma V plane decoding + */ +struct vdec_av1_slice_quantization { + int base_q_idx; + int qindex[V4L2_AV1_MAX_SEGMENTS]; + int delta_qydc; + int delta_qudc; + int delta_quac; + int delta_qvdc; + int delta_qvac; + u8 using_qmatrix; + u8 qm_y; + u8 qm_u; + u8 qm_v; +}; + +/** + * struct vdec_av1_slice_lr - AV1 Loop Restauration parameters + * @use_lr: whether to use loop restoration + * @use_chroma_lr: whether to use chroma loop restoration + * @frame_restoration_type: specifies the type of restoration used for each plane + * @loop_restoration_size: pecifies the size of loop restoration units in units + * of samples in the current plane + */ +struct vdec_av1_slice_lr { + u8 use_lr; + u8 use_chroma_lr; + u8 frame_restoration_type[V4L2_AV1_NUM_PLANES_MAX]; + u32 loop_restoration_size[V4L2_AV1_NUM_PLANES_MAX]; +}; + +/** + * struct vdec_av1_slice_loop_filter - AV1 Loop filter parameters + * @loop_filter_level: an array containing loop filter strength values. + * @loop_filter_ref_deltas: contains the adjustment needed for the filter + * level based on the chosen reference frame + * @loop_filter_mode_deltas: contains the adjustment needed for the filter + * level based on the chosen mode + * @loop_filter_sharpness: indicates the sharpness level. The loop_filter_level + * and loop_filter_sharpness together determine when + * a block edge is filtered, and by how much the + * filtering can change the sample values + * @loop_filter_delta_enabled: filetr level depends on the mode and reference + * frame used to predict a block + */ +struct vdec_av1_slice_loop_filter { + u8 loop_filter_level[4]; + int loop_filter_ref_deltas[V4L2_AV1_TOTAL_REFS_PER_FRAME]; + int loop_filter_mode_deltas[2]; + u8 loop_filter_sharpness; + u8 loop_filter_delta_enabled; +}; + +/** + * struct vdec_av1_slice_cdef - AV1 CDEF parameters + * @cdef_damping: controls the amount of damping in the deringing filter + * @cdef_y_strength: specifies the strength of the primary filter and secondary filter + * @cdef_uv_strength: specifies the strength of the primary filter and secondary filter + * @cdef_bits: specifies the number of bits needed to specify which + * CDEF filter to apply + */ +struct vdec_av1_slice_cdef { + u8 cdef_damping; + u8 cdef_y_strength[8]; + u8 cdef_uv_strength[8]; + u8 cdef_bits; +}; + +/** + * struct vdec_av1_slice_mfmv - AV1 mfmv parameters + * @mfmv_valid_ref: mfmv_valid_ref + * @mfmv_dir: mfmv_dir + * @mfmv_ref_to_cur: mfmv_ref_to_cur + * @mfmv_ref_frame_idx: mfmv_ref_frame_idx + * @mfmv_count: mfmv_count + */ +struct vdec_av1_slice_mfmv { + u32 mfmv_valid_ref[3]; + u32 mfmv_dir[3]; + int mfmv_ref_to_cur[3]; + int mfmv_ref_frame_idx[3]; + int mfmv_count; +}; + +/** + * struct vdec_av1_slice_tile - AV1 Tile info + * @tile_cols: specifies the number of tiles across the frame + * @tile_rows: pecifies the number of tiles down the frame + * @mi_col_starts: an array specifying the start column + * @mi_row_starts: an array specifying the start row + * @context_update_tile_id: specifies which tile to use for the CDF update + * @uniform_tile_spacing_flag: tiles are uniformly spaced across the frame + * or the tile sizes are coded + */ +struct vdec_av1_slice_tile { + u8 tile_cols; + u8 tile_rows; + int mi_col_starts[V4L2_AV1_MAX_TILE_COLS + 1]; + int mi_row_starts[V4L2_AV1_MAX_TILE_ROWS + 1]; + u8 context_update_tile_id; + u8 uniform_tile_spacing_flag; +}; + +/** + * struct vdec_av1_slice_uncompressed_header - Represents an AV1 Frame Header OBU + * @use_ref_frame_mvs: use_ref_frame_mvs flag + * @order_hint: specifies OrderHintBits least significant bits of the expected + * @gm: global motion param + * @upscaled_width: the upscaled width + * @frame_width: frame's width + * @frame_height: frame's height + * @reduced_tx_set: frame is restricted to a reduced subset of the full + * set of transform types + * @tx_mode: specifies how the transform size is determined + * @uniform_tile_spacing_flag: tiles are uniformly spaced across the frame + * or the tile sizes are coded + * @interpolation_filter: specifies the filter selection used for performing inter prediction + * @allow_warped_motion: motion_mode may be present or not + * @is_motion_mode_switchable : euqlt to 0 specifies that only the SIMPLE motion mode will be used + * @reference_mode : frame reference mode selected + * @allow_high_precision_mv: specifies that motion vectors are specified to + * quarter pel precision or to eighth pel precision + * @allow_intra_bc: ubducates that intra block copy may be used in this frame + * @force_integer_mv: specifies motion vectors will always be integers or + * can contain fractional bits + * @allow_screen_content_tools: intra blocks may use palette encoding + * @error_resilient_mode: error resislent mode is enable/disable + * @frame_type: specifies the AV1 frame type + * @primary_ref_frame: specifies which reference frame contains the CDF values + * and other state that should be loaded at the start of the frame + * slots will be updated with the current frame after it is decoded + * @disable_frame_end_update_cdf:indicates the end of frame CDF update is disable or enable + * @disable_cdf_update: specified whether the CDF update in the symbol + * decoding process should be disables + * @skip_mode: av1 skip mode parameters + * @seg: av1 segmentaon parameters + * @delta_q_lf: av1 delta loop fileter + * @quant: av1 Quantization params + * @lr: av1 Loop Restauration parameters + * @superres_denom: the denominator for the upscaling ratio + * @loop_filter: av1 Loop filter parameters + * @cdef: av1 CDEF parameters + * @mfmv: av1 mfmv parameters + * @tile: av1 Tile info + * @frame_is_intra: intra frame + * @loss_less_array: loss less array + * @coded_loss_less: coded lsss less + * @mi_rows: size of mi unit in rows + * @mi_cols: size of mi unit in cols + */ +struct vdec_av1_slice_uncompressed_header { + u8 use_ref_frame_mvs; + int order_hint; + struct vdec_av1_slice_gm gm[V4L2_AV1_TOTAL_REFS_PER_FRAME]; + u32 upscaled_width; + u32 frame_width; + u32 frame_height; + u8 reduced_tx_set; + u8 tx_mode; + u8 uniform_tile_spacing_flag; + u8 interpolation_filter; + u8 allow_warped_motion; + u8 is_motion_mode_switchable; + u8 reference_mode; + u8 allow_high_precision_mv; + u8 allow_intra_bc; + u8 force_integer_mv; + u8 allow_screen_content_tools; + u8 error_resilient_mode; + u8 frame_type; + u8 primary_ref_frame; + u8 disable_frame_end_update_cdf; + u32 disable_cdf_update; + struct vdec_av1_slice_sm skip_mode; + struct vdec_av1_slice_seg seg; + struct vdec_av1_slice_delta_q_lf delta_q_lf; + struct vdec_av1_slice_quantization quant; + struct vdec_av1_slice_lr lr; + u32 superres_denom; + struct vdec_av1_slice_loop_filter loop_filter; + struct vdec_av1_slice_cdef cdef; + struct vdec_av1_slice_mfmv mfmv; + struct vdec_av1_slice_tile tile; + u8 frame_is_intra; + u8 loss_less_array[V4L2_AV1_MAX_SEGMENTS]; + u8 coded_loss_less; + u32 mi_rows; + u32 mi_cols; +}; + +/** + * struct vdec_av1_slice_seq_header - Represents an AV1 Sequence OBU + * @bitdepth: the bitdepth to use for the sequence + * @enable_superres: specifies whether the use_superres syntax element may be present + * @enable_filter_intra: specifies the use_filter_intra syntax element may be present + * @enable_intra_edge_filter: whether the intra edge filtering process should be enabled + * @enable_interintra_compound: specifies the mode info fo rinter blocks may + * contain the syntax element interintra + * @enable_masked_compound: specifies the mode info fo rinter blocks may + * contain the syntax element compound_type + * @enable_dual_filter: the inter prediction filter type may be specified independently + * @enable_jnt_comp: distance weights process may be used for inter prediction + * @mono_chrome: indicates the video does not contain U and V color planes + * @enable_order_hint: tools based on the values of order hints may be used + * @order_hint_bits: the number of bits used for the order_hint field at each frame + * @use_128x128_superblock: indicates superblocks contain 128*128 luma samples + * @subsampling_x: the chroma subsamling format + * @subsampling_y: the chroma subsamling format + * @max_frame_width: the maximum frame width for the frames represented by sequence + * @max_frame_height: the maximum frame height for the frames represented by sequence + */ +struct vdec_av1_slice_seq_header { + u8 bitdepth; + u8 enable_superres; + u8 enable_filter_intra; + u8 enable_intra_edge_filter; + u8 enable_interintra_compound; + u8 enable_masked_compound; + u8 enable_dual_filter; + u8 enable_jnt_comp; + u8 mono_chrome; + u8 enable_order_hint; + u8 order_hint_bits; + u8 use_128x128_superblock; + u8 subsampling_x; + u8 subsampling_y; + u32 max_frame_width; + u32 max_frame_height; +}; + +/** + * struct vdec_av1_slice_frame - Represents current Frame info + * @uh: uncompressed header info + * @seq: sequence header info + * @large_scale_tile: is large scale mode + * @cur_ts: current frame timestamp + * @prev_fb_idx: prev slot id + * @ref_frame_sign_bias: arrays for ref_frame sign bias + * @order_hints: arrays for ref_frame order hint + * @ref_frame_valid: arrays for valid ref_frame + * @ref_frame_map: map to slot frame info + * @frame_refs: ref_frame info + */ +struct vdec_av1_slice_frame { + struct vdec_av1_slice_uncompressed_header uh; + struct vdec_av1_slice_seq_header seq; + u8 large_scale_tile; + u64 cur_ts; + int prev_fb_idx; + u8 ref_frame_sign_bias[V4L2_AV1_TOTAL_REFS_PER_FRAME]; + u32 order_hints[V4L2_AV1_REFS_PER_FRAME]; + u32 ref_frame_valid[V4L2_AV1_REFS_PER_FRAME]; + int ref_frame_map[V4L2_AV1_TOTAL_REFS_PER_FRAME]; + struct vdec_av1_slice_frame_refs frame_refs[V4L2_AV1_REFS_PER_FRAME]; +}; + +/** + * struct vdec_av1_slice_work_buffer - work buffer for lat + * @mv_addr: mv buffer memory info + * @cdf_addr: cdf buffer memory info + * @segid_addr: segid buffer memory info + */ +struct vdec_av1_slice_work_buffer { + struct vdec_av1_slice_mem mv_addr; + struct vdec_av1_slice_mem cdf_addr; + struct vdec_av1_slice_mem segid_addr; +}; + +/** + * struct vdec_av1_slice_frame_info - frame info for each slot + * @frame_type: frame type + * @frame_is_intra: is intra frame + * @order_hint: order hint + * @order_hints: referece frame order hint + * @upscaled_width: upscale width + * @pic_pitch: buffer pitch + * @frame_width: frane width + * @frame_height: frame height + * @mi_rows: rows in mode info + * @mi_cols: cols in mode info + * @ref_count: mark to reference frame counts + */ +struct vdec_av1_slice_frame_info { + u8 frame_type; + u8 frame_is_intra; + int order_hint; + u32 order_hints[V4L2_AV1_REFS_PER_FRAME]; + u32 upscaled_width; + u32 pic_pitch; + u32 frame_width; + u32 frame_height; + u32 mi_rows; + u32 mi_cols; + int ref_count; +}; + +/** + * struct vdec_av1_slice_slot - slot info that needs to be saved in the global instance + * @frame_info: frame info for each slot + * @timestamp: time stamp info + */ +struct vdec_av1_slice_slot { + struct vdec_av1_slice_frame_info frame_info[AV1_MAX_FRAME_BUF_COUNT]; + u64 timestamp[AV1_MAX_FRAME_BUF_COUNT]; +}; + +/** + * struct vdec_av1_slice_fb - frame buffer for decoding + * @y: current y buffer address info + * @c: current c buffer address info + */ +struct vdec_av1_slice_fb { + struct vdec_av1_slice_mem y; + struct vdec_av1_slice_mem c; +}; + +/** + * struct vdec_av1_slice_vsi - exchange frame information between Main CPU and MicroP + * @bs: input buffer info + * @work_buffer: working buffe for hw + * @cdf_table: cdf_table buffer + * @cdf_tmp: cdf temp buffer + * @rd_mv: mv buffer for lat output , core input + * @ube: ube buffer + * @trans: transcoded buffer + * @err_map: err map buffer + * @row_info: row info buffer + * @fb: current y/c buffer + * @ref: ref y/c buffer + * @iq_table: iq table buffer + * @tile: tile buffer + * @slots: slots info for each frame + * @slot_id: current frame slot id + * @frame: current frame info + * @state: status after decode done + * @cur_lst_tile_id: tile id for large scale + */ +struct vdec_av1_slice_vsi { + /* lat */ + struct vdec_av1_slice_mem bs; + struct vdec_av1_slice_work_buffer work_buffer[AV1_MAX_FRAME_BUF_COUNT]; + struct vdec_av1_slice_mem cdf_table; + struct vdec_av1_slice_mem cdf_tmp; + /* LAT stage's output, Core stage's input */ + struct vdec_av1_slice_mem rd_mv; + struct vdec_av1_slice_mem ube; + struct vdec_av1_slice_mem trans; + struct vdec_av1_slice_mem err_map; + struct vdec_av1_slice_mem row_info; + /* core */ + struct vdec_av1_slice_fb fb; + struct vdec_av1_slice_fb ref[V4L2_AV1_REFS_PER_FRAME]; + struct vdec_av1_slice_mem iq_table; + /* lat and core share*/ + struct vdec_av1_slice_mem tile; + struct vdec_av1_slice_slot slots; + s8 slot_id; + struct vdec_av1_slice_frame frame; + struct vdec_av1_slice_state state; + u32 cur_lst_tile_id; +}; + +/** + * struct vdec_av1_slice_pfc - per-frame context that contains a local vsi. + * pass it from lat to core + * @vsi: local vsi. copy to/from remote vsi before/after decoding + * @ref_idx: reference buffer timestamp + * @seq: picture sequence + */ +struct vdec_av1_slice_pfc { + struct vdec_av1_slice_vsi vsi; + u64 ref_idx[V4L2_AV1_REFS_PER_FRAME]; + int seq; +}; + +/** + * struct vdec_av1_slice_instance - represent one av1 instance + * @ctx: pointer to codec's context + * @vpu: VPU instance + * @iq_table: iq table buffer + * @cdf_table: cdf table buffer + * @mv: mv working buffer + * @cdf: cdf working buffer + * @seg: segmentation working buffer + * @cdf_temp: cdf temp buffer + * @tile: tile buffer + * @slots: slots info + * @tile_group: tile_group entry + * @level: level of current resolution + * @width: width of last picture + * @height: height of last picture + * @frame_type: frame_type of last picture + * @irq_enabled: irq to Main CPU or MicroP + * @inneracing_mode: is inneracing mode + * @init_vsi: vsi used for initialized AV1 instance + * @vsi: vsi used for decoding/flush ... + * @core_vsi: vsi used for Core stage + * @seq: global picture sequence + */ +struct vdec_av1_slice_instance { + struct mtk_vcodec_ctx *ctx; + struct vdec_vpu_inst vpu; + + struct mtk_vcodec_mem iq_table; + struct mtk_vcodec_mem cdf_table; + + struct mtk_vcodec_mem mv[AV1_MAX_FRAME_BUF_COUNT]; + struct mtk_vcodec_mem cdf[AV1_MAX_FRAME_BUF_COUNT]; + struct mtk_vcodec_mem seg[AV1_MAX_FRAME_BUF_COUNT]; + struct mtk_vcodec_mem cdf_temp; + struct mtk_vcodec_mem tile; + struct vdec_av1_slice_slot slots; + struct vdec_av1_slice_tile_group tile_group; + + /* for resolution change and get_pic_info */ + enum vdec_av1_slice_resolution_level level; + u32 width; + u32 height; + + u32 frame_type; + u32 irq_enabled; + u32 inneracing_mode; + + /* MicroP vsi */ + union { + struct vdec_av1_slice_init_vsi *init_vsi; + struct vdec_av1_slice_vsi *vsi; + }; + struct vdec_av1_slice_vsi *core_vsi; + int seq; +}; + +static int vdec_av1_slice_core_decode(struct vdec_lat_buf *lat_buf); + +static inline int vdec_av1_slice_get_msb(u32 n) +{ + if (n == 0) + return 0; + return 31 ^ __builtin_clz(n); +} + +static inline bool vdec_av1_slice_need_scale(u32 ref_width, u32 ref_height, + u32 this_width, u32 this_height) +{ + return ((this_width << 1) >= ref_width) && + ((this_height << 1) >= ref_height) && + (this_width <= (ref_width << 4)) && + (this_height <= (ref_height << 4)); +} + +static void *vdec_av1_get_ctrl_ptr(struct mtk_vcodec_ctx *ctx, int id) +{ + struct v4l2_ctrl *ctrl = v4l2_ctrl_find(&ctx->ctrl_hdl, id); + + if (!ctrl) + return ERR_PTR(-EINVAL); + + return ctrl->p_cur.p; +} + +static int vdec_av1_slice_init_cdf_table(struct vdec_av1_slice_instance *instance) +{ + u8 *remote_cdf_table; + struct mtk_vcodec_ctx *ctx; + struct vdec_av1_slice_init_vsi *vsi; + int ret; + + ctx = instance->ctx; + vsi = instance->vpu.vsi; + remote_cdf_table = mtk_vcodec_fw_map_dm_addr(ctx->dev->fw_handler, + (u32)vsi->cdf_table_addr); + if (IS_ERR(remote_cdf_table)) { + mtk_vcodec_err(instance, "failed to map cdf table\n"); + return PTR_ERR(remote_cdf_table); + } + + mtk_vcodec_debug(instance, "map cdf table to 0x%p\n", + remote_cdf_table); + + if (instance->cdf_table.va) + mtk_vcodec_mem_free(ctx, &instance->cdf_table); + instance->cdf_table.size = vsi->cdf_table_size; + + ret = mtk_vcodec_mem_alloc(ctx, &instance->cdf_table); + if (ret) + return ret; + + memcpy(instance->cdf_table.va, remote_cdf_table, vsi->cdf_table_size); + + return 0; +} + +static int vdec_av1_slice_init_iq_table(struct vdec_av1_slice_instance *instance) +{ + u8 *remote_iq_table; + struct mtk_vcodec_ctx *ctx; + struct vdec_av1_slice_init_vsi *vsi; + int ret; + + ctx = instance->ctx; + vsi = instance->vpu.vsi; + remote_iq_table = mtk_vcodec_fw_map_dm_addr(ctx->dev->fw_handler, + (u32)vsi->iq_table_addr); + if (IS_ERR(remote_iq_table)) { + mtk_vcodec_err(instance, "failed to map iq table\n"); + return PTR_ERR(remote_iq_table); + } + + mtk_vcodec_debug(instance, "map iq table to 0x%p\n", remote_iq_table); + + if (instance->iq_table.va) + mtk_vcodec_mem_free(ctx, &instance->iq_table); + instance->iq_table.size = vsi->iq_table_size; + + ret = mtk_vcodec_mem_alloc(ctx, &instance->iq_table); + if (ret) + return ret; + + memcpy(instance->iq_table.va, remote_iq_table, vsi->iq_table_size); + + return 0; +} + +static int vdec_av1_slice_get_new_slot(struct vdec_av1_slice_vsi *vsi) +{ + struct vdec_av1_slice_slot *slots = &vsi->slots; + int new_slot_idx = AV1_INVALID_IDX; + int i; + + for (i = 0; i < AV1_MAX_FRAME_BUF_COUNT; i++) { + if (slots->frame_info[i].ref_count == 0) { + new_slot_idx = i; + break; + } + } + + if (new_slot_idx != AV1_INVALID_IDX) { + slots->frame_info[new_slot_idx].ref_count++; + slots->timestamp[new_slot_idx] = vsi->frame.cur_ts; + } + + return new_slot_idx; +} + +static inline void vdec_av1_slice_clear_fb(struct vdec_av1_slice_frame_info *frame_info) +{ + memset((void *)frame_info, 0, sizeof(struct vdec_av1_slice_frame_info)); +} + +static void vdec_av1_slice_decrease_ref_count(struct vdec_av1_slice_slot *slots, int fb_idx) +{ + struct vdec_av1_slice_frame_info *frame_info = slots->frame_info; + + frame_info[fb_idx].ref_count--; + if (frame_info[fb_idx].ref_count < 0) { + frame_info[fb_idx].ref_count = 0; + mtk_v4l2_err("av1_error: %s() fb_idx %d decrease ref_count error\n", + __func__, fb_idx); + } + + vdec_av1_slice_clear_fb(&frame_info[fb_idx]); +} + +static void vdec_av1_slice_cleanup_slots(struct vdec_av1_slice_slot *slots, + struct vdec_av1_slice_frame *frame, + struct v4l2_ctrl_av1_frame *ctrl_fh) +{ + int slot_id, ref_id; + + for (ref_id = 0; ref_id < V4L2_AV1_TOTAL_REFS_PER_FRAME; ref_id++) + frame->ref_frame_map[ref_id] = AV1_INVALID_IDX; + + for (slot_id = 0; slot_id < AV1_MAX_FRAME_BUF_COUNT; slot_id++) { + u64 timestamp = slots->timestamp[slot_id]; + bool ref_used = false; + + /* ignored unused slots */ + if (slots->frame_info[slot_id].ref_count == 0) + continue; + + for (ref_id = 0; ref_id < V4L2_AV1_TOTAL_REFS_PER_FRAME; ref_id++) { + if (ctrl_fh->reference_frame_ts[ref_id] == timestamp) { + frame->ref_frame_map[ref_id] = slot_id; + ref_used = true; + } + } + + if (!ref_used) + vdec_av1_slice_decrease_ref_count(slots, slot_id); + } +} + +static void vdec_av1_slice_setup_slot(struct vdec_av1_slice_instance *instance, + struct vdec_av1_slice_vsi *vsi, + struct v4l2_ctrl_av1_frame *ctrl_fh) +{ + struct vdec_av1_slice_frame_info *cur_frame_info; + struct vdec_av1_slice_uncompressed_header *uh = &vsi->frame.uh; + int ref_id; + + memcpy(&vsi->slots, &instance->slots, sizeof(instance->slots)); + vdec_av1_slice_cleanup_slots(&vsi->slots, &vsi->frame, ctrl_fh); + vsi->slot_id = vdec_av1_slice_get_new_slot(vsi); + + if (vsi->slot_id == AV1_INVALID_IDX) { + mtk_v4l2_err("warning:av1 get invalid index slot\n"); + vsi->slot_id = 0; + } + cur_frame_info = &vsi->slots.frame_info[vsi->slot_id]; + cur_frame_info->frame_type = uh->frame_type; + cur_frame_info->frame_is_intra = ((uh->frame_type == AV1_INTRA_ONLY_FRAME) || + (uh->frame_type == AV1_KEY_FRAME)); + cur_frame_info->order_hint = uh->order_hint; + cur_frame_info->upscaled_width = uh->upscaled_width; + cur_frame_info->pic_pitch = 0; + cur_frame_info->frame_width = uh->frame_width; + cur_frame_info->frame_height = uh->frame_height; + cur_frame_info->mi_cols = ((uh->frame_width + 7) >> 3) << 1; + cur_frame_info->mi_rows = ((uh->frame_height + 7) >> 3) << 1; + + /* ensure current frame is properly mapped if referenced */ + for (ref_id = 0; ref_id < V4L2_AV1_TOTAL_REFS_PER_FRAME; ref_id++) { + u64 timestamp = vsi->slots.timestamp[vsi->slot_id]; + + if (ctrl_fh->reference_frame_ts[ref_id] == timestamp) + vsi->frame.ref_frame_map[ref_id] = vsi->slot_id; + } +} + +static int vdec_av1_slice_alloc_working_buffer(struct vdec_av1_slice_instance *instance, + struct vdec_av1_slice_vsi *vsi) +{ + struct mtk_vcodec_ctx *ctx = instance->ctx; + enum vdec_av1_slice_resolution_level level; + u32 max_sb_w, max_sb_h, max_w, max_h, w, h; + int i, ret; + + w = vsi->frame.uh.frame_width; + h = vsi->frame.uh.frame_height; + + if (w > VCODEC_DEC_4K_CODED_WIDTH || h > VCODEC_DEC_4K_CODED_HEIGHT) + /* 8K */ + return -EINVAL; + + if (w > MTK_VDEC_MAX_W || h > MTK_VDEC_MAX_H) { + /* 4K */ + level = AV1_RES_4K; + max_w = VCODEC_DEC_4K_CODED_WIDTH; + max_h = VCODEC_DEC_4K_CODED_HEIGHT; + } else { + /* FHD */ + level = AV1_RES_FHD; + max_w = MTK_VDEC_MAX_W; + max_h = MTK_VDEC_MAX_H; + } + + if (level == instance->level) + return 0; + + mtk_vcodec_debug(instance, "resolution level changed from %u to %u, %ux%u", + instance->level, level, w, h); + + max_sb_w = DIV_ROUND_UP(max_w, 128); + max_sb_h = DIV_ROUND_UP(max_h, 128); + + for (i = 0; i < AV1_MAX_FRAME_BUF_COUNT; i++) { + if (instance->mv[i].va) + mtk_vcodec_mem_free(ctx, &instance->mv[i]); + instance->mv[i].size = max_sb_w * max_sb_h * SZ_1K; + ret = mtk_vcodec_mem_alloc(ctx, &instance->mv[i]); + if (ret) + goto err; + + if (instance->seg[i].va) + mtk_vcodec_mem_free(ctx, &instance->seg[i]); + instance->seg[i].size = max_sb_w * max_sb_h * 512; + ret = mtk_vcodec_mem_alloc(ctx, &instance->seg[i]); + if (ret) + goto err; + + if (instance->cdf[i].va) + mtk_vcodec_mem_free(ctx, &instance->cdf[i]); + instance->cdf[i].size = AV1_CDF_TABLE_BUFFER_SIZE; + ret = mtk_vcodec_mem_alloc(ctx, &instance->cdf[i]); + if (ret) + goto err; + } + + if (!instance->cdf_temp.va) { + instance->cdf_temp.size = (SZ_1K * 16 * 100); + ret = mtk_vcodec_mem_alloc(ctx, &instance->cdf_temp); + if (ret) + goto err; + vsi->cdf_tmp.buf = instance->cdf_temp.dma_addr; + vsi->cdf_tmp.size = instance->cdf_temp.size; + } + + if (instance->tile.va) + mtk_vcodec_mem_free(ctx, &instance->tile); + + instance->tile.size = AV1_TILE_BUF_SIZE * V4L2_AV1_MAX_TILE_COUNT; + ret = mtk_vcodec_mem_alloc(ctx, &instance->tile); + if (ret) + goto err; + + instance->level = level; + return 0; + +err: + instance->level = AV1_RES_NONE; + return ret; +} + +static void vdec_av1_slice_free_working_buffer(struct vdec_av1_slice_instance *instance) +{ + struct mtk_vcodec_ctx *ctx = instance->ctx; + int i; + + for (i = 0; i < ARRAY_SIZE(instance->mv); i++) + mtk_vcodec_mem_free(ctx, &instance->mv[i]); + + for (i = 0; i < ARRAY_SIZE(instance->seg); i++) + mtk_vcodec_mem_free(ctx, &instance->seg[i]); + + for (i = 0; i < ARRAY_SIZE(instance->cdf); i++) + mtk_vcodec_mem_free(ctx, &instance->cdf[i]); + + mtk_vcodec_mem_free(ctx, &instance->tile); + mtk_vcodec_mem_free(ctx, &instance->cdf_temp); + mtk_vcodec_mem_free(ctx, &instance->cdf_table); + mtk_vcodec_mem_free(ctx, &instance->iq_table); + + instance->level = AV1_RES_NONE; +} + +static inline void vdec_av1_slice_vsi_from_remote(struct vdec_av1_slice_vsi *vsi, + struct vdec_av1_slice_vsi *remote_vsi) +{ + memcpy(&vsi->trans, &remote_vsi->trans, sizeof(vsi->trans)); + memcpy(&vsi->state, &remote_vsi->state, sizeof(vsi->state)); +} + +static inline void vdec_av1_slice_vsi_to_remote(struct vdec_av1_slice_vsi *vsi, + struct vdec_av1_slice_vsi *remote_vsi) +{ + memcpy(remote_vsi, vsi, sizeof(*vsi)); +} + +static int vdec_av1_slice_setup_lat_from_src_buf(struct vdec_av1_slice_instance *instance, + struct vdec_av1_slice_vsi *vsi, + struct vdec_lat_buf *lat_buf) +{ + struct vb2_v4l2_buffer *src; + struct vb2_v4l2_buffer *dst; + + src = v4l2_m2m_next_src_buf(instance->ctx->m2m_ctx); + if (!src) + return -EINVAL; + + lat_buf->src_buf_req = src->vb2_buf.req_obj.req; + dst = &lat_buf->ts_info; + v4l2_m2m_buf_copy_metadata(src, dst, true); + vsi->frame.cur_ts = dst->vb2_buf.timestamp; + + return 0; +} + +static short vdec_av1_slice_resolve_divisor_32(u32 D, short *shift) +{ + int f; + int e; + + *shift = vdec_av1_slice_get_msb(D); + /* e is obtained from D after resetting the most significant 1 bit. */ + e = D - ((u32)1 << *shift); + /* Get the most significant DIV_LUT_BITS (8) bits of e into f */ + if (*shift > DIV_LUT_BITS) + f = AV1_DIV_ROUND_UP_POW2(e, *shift - DIV_LUT_BITS); + else + f = e << (DIV_LUT_BITS - *shift); + if (f > DIV_LUT_NUM) + return -1; + *shift += DIV_LUT_PREC_BITS; + /* Use f as lookup into the precomputed table of multipliers */ + return div_lut[f]; +} + +static void vdec_av1_slice_get_shear_params(struct vdec_av1_slice_gm *gm_params) +{ + const int *mat = gm_params->wmmat; + short shift; + short y; + long long gv, dv; + + if (gm_params->wmmat[2] <= 0) + return; + + gm_params->alpha = clamp_val(mat[2] - (1 << WARPEDMODEL_PREC_BITS), S16_MIN, S16_MAX); + gm_params->beta = clamp_val(mat[3], S16_MIN, S16_MAX); + + y = vdec_av1_slice_resolve_divisor_32(abs(mat[2]), &shift) * (mat[2] < 0 ? -1 : 1); + + gv = ((long long)mat[4] * (1 << WARPEDMODEL_PREC_BITS)) * y; + gm_params->gamma = clamp_val((int)AV1_DIV_ROUND_UP_POW2_SIGNED(gv, shift), + S16_MIN, S16_MAX); + + dv = ((long long)mat[3] * mat[4]) * y; + gm_params->delta = clamp_val(mat[5] - (int)AV1_DIV_ROUND_UP_POW2_SIGNED(dv, shift) - + (1 << WARPEDMODEL_PREC_BITS), S16_MIN, S16_MAX); + + gm_params->alpha = AV1_DIV_ROUND_UP_POW2_SIGNED(gm_params->alpha, WARP_PARAM_REDUCE_BITS) * + (1 << WARP_PARAM_REDUCE_BITS); + gm_params->beta = AV1_DIV_ROUND_UP_POW2_SIGNED(gm_params->beta, WARP_PARAM_REDUCE_BITS) * + (1 << WARP_PARAM_REDUCE_BITS); + gm_params->gamma = AV1_DIV_ROUND_UP_POW2_SIGNED(gm_params->gamma, WARP_PARAM_REDUCE_BITS) * + (1 << WARP_PARAM_REDUCE_BITS); + gm_params->delta = AV1_DIV_ROUND_UP_POW2_SIGNED(gm_params->delta, WARP_PARAM_REDUCE_BITS) * + (1 << WARP_PARAM_REDUCE_BITS); +} + +static void vdec_av1_slice_setup_gm(struct vdec_av1_slice_gm *gm, + struct v4l2_av1_global_motion *ctrl_gm) +{ + u32 i, j; + + for (i = 0; i < V4L2_AV1_TOTAL_REFS_PER_FRAME; i++) { + gm[i].wmtype = ctrl_gm->type[i]; + for (j = 0; j < 6; j++) + gm[i].wmmat[j] = ctrl_gm->params[i][j]; + + gm[i].invalid = !!(ctrl_gm->invalid & BIT(i)); + gm[i].alpha = 0; + gm[i].beta = 0; + gm[i].gamma = 0; + gm[i].delta = 0; + if (gm[i].wmtype <= V4L2_AV1_WARP_MODEL_AFFINE) + vdec_av1_slice_get_shear_params(&gm[i]); + } +} + +static void vdec_av1_slice_setup_seg(struct vdec_av1_slice_seg *seg, + struct v4l2_av1_segmentation *ctrl_seg) +{ + u32 i, j; + + seg->segmentation_enabled = SEGMENTATION_FLAG(ctrl_seg, ENABLED); + seg->segmentation_update_map = SEGMENTATION_FLAG(ctrl_seg, UPDATE_MAP); + seg->segmentation_temporal_update = SEGMENTATION_FLAG(ctrl_seg, TEMPORAL_UPDATE); + seg->segmentation_update_data = SEGMENTATION_FLAG(ctrl_seg, UPDATE_DATA); + seg->segid_preskip = SEGMENTATION_FLAG(ctrl_seg, SEG_ID_PRE_SKIP); + seg->last_active_segid = ctrl_seg->last_active_seg_id; + + for (i = 0; i < V4L2_AV1_MAX_SEGMENTS; i++) { + seg->feature_enabled_mask[i] = ctrl_seg->feature_enabled[i]; + for (j = 0; j < V4L2_AV1_SEG_LVL_MAX; j++) + seg->feature_data[i][j] = ctrl_seg->feature_data[i][j]; + } +} + +static void vdec_av1_slice_setup_quant(struct vdec_av1_slice_quantization *quant, + struct v4l2_av1_quantization *ctrl_quant) +{ + quant->base_q_idx = ctrl_quant->base_q_idx; + quant->delta_qydc = ctrl_quant->delta_q_y_dc; + quant->delta_qudc = ctrl_quant->delta_q_u_dc; + quant->delta_quac = ctrl_quant->delta_q_u_ac; + quant->delta_qvdc = ctrl_quant->delta_q_v_dc; + quant->delta_qvac = ctrl_quant->delta_q_v_ac; + quant->qm_y = ctrl_quant->qm_y; + quant->qm_u = ctrl_quant->qm_u; + quant->qm_v = ctrl_quant->qm_v; + quant->using_qmatrix = QUANT_FLAG(ctrl_quant, USING_QMATRIX); +} + +static int vdec_av1_slice_get_qindex(struct vdec_av1_slice_uncompressed_header *uh, + int segmentation_id) +{ + struct vdec_av1_slice_seg *seg = &uh->seg; + struct vdec_av1_slice_quantization *quant = &uh->quant; + int data = 0, qindex = 0; + + if (seg->segmentation_enabled && + (seg->feature_enabled_mask[segmentation_id] & BIT(SEG_LVL_ALT_Q))) { + data = seg->feature_data[segmentation_id][SEG_LVL_ALT_Q]; + qindex = quant->base_q_idx + data; + return clamp_val(qindex, 0, MAXQ); + } + + return quant->base_q_idx; +} + +static void vdec_av1_slice_setup_lr(struct vdec_av1_slice_lr *lr, + struct v4l2_av1_loop_restoration *ctrl_lr) +{ + int i; + + lr->use_lr = 0; + lr->use_chroma_lr = 0; + for (i = 0; i < V4L2_AV1_NUM_PLANES_MAX; i++) { + lr->frame_restoration_type[i] = ctrl_lr->frame_restoration_type[i]; + lr->loop_restoration_size[i] = ctrl_lr->loop_restoration_size[i]; + if (lr->frame_restoration_type[i]) { + lr->use_lr = 1; + if (i > 0) + lr->use_chroma_lr = 1; + } + } +} + +static void vdec_av1_slice_setup_lf(struct vdec_av1_slice_loop_filter *lf, + struct v4l2_av1_loop_filter *ctrl_lf) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(lf->loop_filter_level); i++) + lf->loop_filter_level[i] = ctrl_lf->level[i]; + + for (i = 0; i < V4L2_AV1_TOTAL_REFS_PER_FRAME; i++) + lf->loop_filter_ref_deltas[i] = ctrl_lf->ref_deltas[i]; + + for (i = 0; i < ARRAY_SIZE(lf->loop_filter_mode_deltas); i++) + lf->loop_filter_mode_deltas[i] = ctrl_lf->mode_deltas[i]; + + lf->loop_filter_sharpness = ctrl_lf->sharpness; + lf->loop_filter_delta_enabled = + BIT_FLAG(ctrl_lf, V4L2_AV1_LOOP_FILTER_FLAG_DELTA_ENABLED); +} + +static void vdec_av1_slice_setup_cdef(struct vdec_av1_slice_cdef *cdef, + struct v4l2_av1_cdef *ctrl_cdef) +{ + int i; + + cdef->cdef_damping = ctrl_cdef->damping_minus_3 + 3; + cdef->cdef_bits = ctrl_cdef->bits; + + for (i = 0; i < V4L2_AV1_CDEF_MAX; i++) { + if (ctrl_cdef->y_sec_strength[i] == 4) + ctrl_cdef->y_sec_strength[i] -= 1; + + if (ctrl_cdef->uv_sec_strength[i] == 4) + ctrl_cdef->uv_sec_strength[i] -= 1; + + cdef->cdef_y_strength[i] = + ctrl_cdef->y_pri_strength[i] << SECONDARY_FILTER_STRENGTH_NUM_BITS | + ctrl_cdef->y_sec_strength[i]; + cdef->cdef_uv_strength[i] = + ctrl_cdef->uv_pri_strength[i] << SECONDARY_FILTER_STRENGTH_NUM_BITS | + ctrl_cdef->uv_sec_strength[i]; + } +} + +static void vdec_av1_slice_setup_seq(struct vdec_av1_slice_seq_header *seq, + struct v4l2_ctrl_av1_sequence *ctrl_seq) +{ + seq->bitdepth = ctrl_seq->bit_depth; + seq->max_frame_width = ctrl_seq->max_frame_width_minus_1 + 1; + seq->max_frame_height = ctrl_seq->max_frame_height_minus_1 + 1; + seq->enable_superres = SEQUENCE_FLAG(ctrl_seq, ENABLE_SUPERRES); + seq->enable_filter_intra = SEQUENCE_FLAG(ctrl_seq, ENABLE_FILTER_INTRA); + seq->enable_intra_edge_filter = SEQUENCE_FLAG(ctrl_seq, ENABLE_INTRA_EDGE_FILTER); + seq->enable_interintra_compound = SEQUENCE_FLAG(ctrl_seq, ENABLE_INTERINTRA_COMPOUND); + seq->enable_masked_compound = SEQUENCE_FLAG(ctrl_seq, ENABLE_MASKED_COMPOUND); + seq->enable_dual_filter = SEQUENCE_FLAG(ctrl_seq, ENABLE_DUAL_FILTER); + seq->enable_jnt_comp = SEQUENCE_FLAG(ctrl_seq, ENABLE_JNT_COMP); + seq->mono_chrome = SEQUENCE_FLAG(ctrl_seq, MONO_CHROME); + seq->enable_order_hint = SEQUENCE_FLAG(ctrl_seq, ENABLE_ORDER_HINT); + seq->order_hint_bits = ctrl_seq->order_hint_bits; + seq->use_128x128_superblock = SEQUENCE_FLAG(ctrl_seq, USE_128X128_SUPERBLOCK); + seq->subsampling_x = SEQUENCE_FLAG(ctrl_seq, SUBSAMPLING_X); + seq->subsampling_y = SEQUENCE_FLAG(ctrl_seq, SUBSAMPLING_Y); +} + +static void vdec_av1_slice_setup_tile(struct vdec_av1_slice_frame *frame, + struct v4l2_av1_tile_info *ctrl_tile) +{ + struct vdec_av1_slice_seq_header *seq = &frame->seq; + struct vdec_av1_slice_tile *tile = &frame->uh.tile; + u32 mib_size_log2 = seq->use_128x128_superblock ? 5 : 4; + int i; + + tile->tile_cols = ctrl_tile->tile_cols; + tile->tile_rows = ctrl_tile->tile_rows; + tile->context_update_tile_id = ctrl_tile->context_update_tile_id; + tile->uniform_tile_spacing_flag = + BIT_FLAG(ctrl_tile, V4L2_AV1_TILE_INFO_FLAG_UNIFORM_TILE_SPACING); + + for (i = 0; i < tile->tile_cols + 1; i++) + tile->mi_col_starts[i] = + ALIGN(ctrl_tile->mi_col_starts[i], BIT(mib_size_log2)) >> mib_size_log2; + + for (i = 0; i < tile->tile_rows + 1; i++) + tile->mi_row_starts[i] = + ALIGN(ctrl_tile->mi_row_starts[i], BIT(mib_size_log2)) >> mib_size_log2; +} + +static void vdec_av1_slice_setup_uh(struct vdec_av1_slice_instance *instance, + struct vdec_av1_slice_frame *frame, + struct v4l2_ctrl_av1_frame *ctrl_fh) +{ + struct vdec_av1_slice_uncompressed_header *uh = &frame->uh; + int i; + + uh->use_ref_frame_mvs = FH_FLAG(ctrl_fh, USE_REF_FRAME_MVS); + uh->order_hint = ctrl_fh->order_hint; + vdec_av1_slice_setup_gm(uh->gm, &ctrl_fh->global_motion); + uh->upscaled_width = ctrl_fh->upscaled_width; + uh->frame_width = ctrl_fh->frame_width_minus_1 + 1; + uh->frame_height = ctrl_fh->frame_height_minus_1 + 1; + uh->mi_cols = ((uh->frame_width + 7) >> 3) << 1; + uh->mi_rows = ((uh->frame_height + 7) >> 3) << 1; + uh->reduced_tx_set = FH_FLAG(ctrl_fh, REDUCED_TX_SET); + uh->tx_mode = ctrl_fh->tx_mode; + uh->uniform_tile_spacing_flag = + BIT_FLAG(&ctrl_fh->tile_info, V4L2_AV1_TILE_INFO_FLAG_UNIFORM_TILE_SPACING); + uh->interpolation_filter = ctrl_fh->interpolation_filter; + uh->allow_warped_motion = FH_FLAG(ctrl_fh, ALLOW_WARPED_MOTION); + uh->is_motion_mode_switchable = FH_FLAG(ctrl_fh, IS_MOTION_MODE_SWITCHABLE); + uh->frame_type = ctrl_fh->frame_type; + uh->frame_is_intra = (uh->frame_type == V4L2_AV1_INTRA_ONLY_FRAME || + uh->frame_type == V4L2_AV1_KEY_FRAME); + + if (!uh->frame_is_intra && FH_FLAG(ctrl_fh, REFERENCE_SELECT)) + uh->reference_mode = AV1_REFERENCE_MODE_SELECT; + else + uh->reference_mode = AV1_SINGLE_REFERENCE; + + uh->allow_high_precision_mv = FH_FLAG(ctrl_fh, ALLOW_HIGH_PRECISION_MV); + uh->allow_intra_bc = FH_FLAG(ctrl_fh, ALLOW_INTRABC); + uh->force_integer_mv = FH_FLAG(ctrl_fh, FORCE_INTEGER_MV); + uh->allow_screen_content_tools = FH_FLAG(ctrl_fh, ALLOW_SCREEN_CONTENT_TOOLS); + uh->error_resilient_mode = FH_FLAG(ctrl_fh, ERROR_RESILIENT_MODE); + uh->primary_ref_frame = ctrl_fh->primary_ref_frame; + uh->disable_frame_end_update_cdf = + FH_FLAG(ctrl_fh, DISABLE_FRAME_END_UPDATE_CDF); + uh->disable_cdf_update = FH_FLAG(ctrl_fh, DISABLE_CDF_UPDATE); + uh->skip_mode.skip_mode_present = FH_FLAG(ctrl_fh, SKIP_MODE_PRESENT); + uh->skip_mode.skip_mode_frame[0] = + ctrl_fh->skip_mode_frame[0] - V4L2_AV1_REF_LAST_FRAME; + uh->skip_mode.skip_mode_frame[1] = + ctrl_fh->skip_mode_frame[1] - V4L2_AV1_REF_LAST_FRAME; + uh->skip_mode.skip_mode_allowed = ctrl_fh->skip_mode_frame[0] ? 1 : 0; + + vdec_av1_slice_setup_seg(&uh->seg, &ctrl_fh->segmentation); + uh->delta_q_lf.delta_q_present = QUANT_FLAG(&ctrl_fh->quantization, DELTA_Q_PRESENT); + uh->delta_q_lf.delta_q_res = 1 << ctrl_fh->quantization.delta_q_res; + uh->delta_q_lf.delta_lf_present = + BIT_FLAG(&ctrl_fh->loop_filter, V4L2_AV1_LOOP_FILTER_FLAG_DELTA_LF_PRESENT); + uh->delta_q_lf.delta_lf_res = ctrl_fh->loop_filter.delta_lf_res; + uh->delta_q_lf.delta_lf_multi = + BIT_FLAG(&ctrl_fh->loop_filter, V4L2_AV1_LOOP_FILTER_FLAG_DELTA_LF_MULTI); + vdec_av1_slice_setup_quant(&uh->quant, &ctrl_fh->quantization); + + uh->coded_loss_less = 1; + for (i = 0; i < V4L2_AV1_MAX_SEGMENTS; i++) { + uh->quant.qindex[i] = vdec_av1_slice_get_qindex(uh, i); + uh->loss_less_array[i] = + (uh->quant.qindex[i] == 0 && uh->quant.delta_qydc == 0 && + uh->quant.delta_quac == 0 && uh->quant.delta_qudc == 0 && + uh->quant.delta_qvac == 0 && uh->quant.delta_qvdc == 0); + + if (!uh->loss_less_array[i]) + uh->coded_loss_less = 0; + } + + vdec_av1_slice_setup_lr(&uh->lr, &ctrl_fh->loop_restoration); + uh->superres_denom = ctrl_fh->superres_denom; + vdec_av1_slice_setup_lf(&uh->loop_filter, &ctrl_fh->loop_filter); + vdec_av1_slice_setup_cdef(&uh->cdef, &ctrl_fh->cdef); + vdec_av1_slice_setup_tile(frame, &ctrl_fh->tile_info); +} + +static int vdec_av1_slice_setup_tile_group(struct vdec_av1_slice_instance *instance, + struct vdec_av1_slice_vsi *vsi) +{ + struct v4l2_ctrl_av1_tile_group_entry *ctrl_tge; + struct vdec_av1_slice_tile_group *tile_group = &instance->tile_group; + struct vdec_av1_slice_uncompressed_header *uh = &vsi->frame.uh; + struct vdec_av1_slice_tile *tile = &uh->tile; + struct v4l2_ctrl *ctrl; + u32 tge_size; + int i; + + ctrl = v4l2_ctrl_find(&instance->ctx->ctrl_hdl, V4L2_CID_STATELESS_AV1_TILE_GROUP_ENTRY); + if (!ctrl) + return -EINVAL; + + tge_size = ctrl->elems; + ctrl_tge = (struct v4l2_ctrl_av1_tile_group_entry *)ctrl->p_cur.p; + + tile_group->num_tiles = tile->tile_cols * tile->tile_rows; + + if (tile_group->num_tiles != tge_size || + tile_group->num_tiles > V4L2_AV1_MAX_TILE_COUNT) { + mtk_vcodec_err(instance, "invalid tge_size %d, tile_num:%d\n", + tge_size, tile_group->num_tiles); + return -EINVAL; + } + + for (i = 0; i < tge_size; i++) { + if (i != ctrl_tge[i].tile_row * vsi->frame.uh.tile.tile_cols + + ctrl_tge[i].tile_col) { + mtk_vcodec_err(instance, "invalid tge info %d, %d %d %d\n", + i, ctrl_tge[i].tile_row, ctrl_tge[i].tile_col, + vsi->frame.uh.tile.tile_rows); + return -EINVAL; + } + tile_group->tile_size[i] = ctrl_tge[i].tile_size; + tile_group->tile_start_offset[i] = ctrl_tge[i].tile_offset; + } + + return 0; +} + +static inline void vdec_av1_slice_setup_state(struct vdec_av1_slice_vsi *vsi) +{ + memset(&vsi->state, 0, sizeof(vsi->state)); +} + +static void vdec_av1_slice_setup_scale_factors(struct vdec_av1_slice_frame_refs *frame_ref, + struct vdec_av1_slice_frame_info *ref_frame_info, + struct vdec_av1_slice_uncompressed_header *uh) +{ + struct vdec_av1_slice_scale_factors *scale_factors = &frame_ref->scale_factors; + u32 ref_upscaled_width = ref_frame_info->upscaled_width; + u32 ref_frame_height = ref_frame_info->frame_height; + u32 frame_width = uh->frame_width; + u32 frame_height = uh->frame_height; + + if (!vdec_av1_slice_need_scale(ref_upscaled_width, ref_frame_height, + frame_width, frame_height)) { + scale_factors->x_scale = -1; + scale_factors->y_scale = -1; + scale_factors->is_scaled = 0; + return; + } + + scale_factors->x_scale = + ((ref_upscaled_width << AV1_REF_SCALE_SHIFT) + (frame_width >> 1)) / frame_width; + scale_factors->y_scale = + ((ref_frame_height << AV1_REF_SCALE_SHIFT) + (frame_height >> 1)) / frame_height; + scale_factors->is_scaled = + (scale_factors->x_scale != AV1_REF_INVALID_SCALE) && + (scale_factors->y_scale != AV1_REF_INVALID_SCALE) && + (scale_factors->x_scale != AV1_REF_NO_SCALE || + scale_factors->y_scale != AV1_REF_NO_SCALE); + scale_factors->x_step = + AV1_DIV_ROUND_UP_POW2(scale_factors->x_scale, + AV1_REF_SCALE_SHIFT - AV1_SCALE_SUBPEL_BITS); + scale_factors->y_step = + AV1_DIV_ROUND_UP_POW2(scale_factors->y_scale, + AV1_REF_SCALE_SHIFT - AV1_SCALE_SUBPEL_BITS); +} + +static unsigned char vdec_av1_slice_get_sign_bias(int a, + int b, + u8 enable_order_hint, + u8 order_hint_bits) +{ + int diff = 0; + int m = 0; + unsigned char result = 0; + + if (!enable_order_hint) + return 0; + + diff = a - b; + m = 1 << (order_hint_bits - 1); + diff = (diff & (m - 1)) - (diff & m); + + if (diff > 0) + result = 1; + + return result; +} + +static void vdec_av1_slice_setup_ref(struct vdec_av1_slice_pfc *pfc, + struct v4l2_ctrl_av1_frame *ctrl_fh) +{ + struct vdec_av1_slice_vsi *vsi = &pfc->vsi; + struct vdec_av1_slice_frame *frame = &vsi->frame; + struct vdec_av1_slice_slot *slots = &vsi->slots; + struct vdec_av1_slice_uncompressed_header *uh = &frame->uh; + struct vdec_av1_slice_seq_header *seq = &frame->seq; + struct vdec_av1_slice_frame_info *cur_frame_info = + &slots->frame_info[vsi->slot_id]; + struct vdec_av1_slice_frame_info *frame_info; + int i, slot_id; + + if (uh->frame_is_intra) + return; + + for (i = 0; i < V4L2_AV1_REFS_PER_FRAME; i++) { + int ref_idx = ctrl_fh->ref_frame_idx[i]; + + pfc->ref_idx[i] = ctrl_fh->reference_frame_ts[ref_idx]; + slot_id = frame->ref_frame_map[ref_idx]; + frame_info = &slots->frame_info[slot_id]; + if (slot_id == AV1_INVALID_IDX) { + mtk_v4l2_err("cannot match reference[%d] 0x%llx\n", i, + ctrl_fh->reference_frame_ts[ref_idx]); + frame->order_hints[i] = 0; + frame->ref_frame_valid[i] = 0; + continue; + } + + frame->frame_refs[i].ref_fb_idx = slot_id; + vdec_av1_slice_setup_scale_factors(&frame->frame_refs[i], + frame_info, uh); + if (!seq->enable_order_hint) + frame->ref_frame_sign_bias[i + 1] = 0; + else + frame->ref_frame_sign_bias[i + 1] = + vdec_av1_slice_get_sign_bias(frame_info->order_hint, + uh->order_hint, + seq->enable_order_hint, + seq->order_hint_bits); + + frame->order_hints[i] = ctrl_fh->order_hints[i + 1]; + cur_frame_info->order_hints[i] = frame->order_hints[i]; + frame->ref_frame_valid[i] = 1; + } +} + +static void vdec_av1_slice_get_previous(struct vdec_av1_slice_vsi *vsi) +{ + struct vdec_av1_slice_frame *frame = &vsi->frame; + + if (frame->uh.primary_ref_frame == AV1_PRIMARY_REF_NONE) + frame->prev_fb_idx = AV1_INVALID_IDX; + else + frame->prev_fb_idx = frame->frame_refs[frame->uh.primary_ref_frame].ref_fb_idx; +} + +static inline void vdec_av1_slice_setup_operating_mode(struct vdec_av1_slice_instance *instance, + struct vdec_av1_slice_frame *frame) +{ + frame->large_scale_tile = 0; +} + +static int vdec_av1_slice_setup_pfc(struct vdec_av1_slice_instance *instance, + struct vdec_av1_slice_pfc *pfc) +{ + struct v4l2_ctrl_av1_frame *ctrl_fh; + struct v4l2_ctrl_av1_sequence *ctrl_seq; + struct vdec_av1_slice_vsi *vsi = &pfc->vsi; + int ret = 0; + + /* frame header */ + ctrl_fh = (struct v4l2_ctrl_av1_frame *) + vdec_av1_get_ctrl_ptr(instance->ctx, + V4L2_CID_STATELESS_AV1_FRAME); + if (IS_ERR(ctrl_fh)) + return PTR_ERR(ctrl_fh); + + ctrl_seq = (struct v4l2_ctrl_av1_sequence *) + vdec_av1_get_ctrl_ptr(instance->ctx, + V4L2_CID_STATELESS_AV1_SEQUENCE); + if (IS_ERR(ctrl_seq)) + return PTR_ERR(ctrl_seq); + + /* setup vsi information */ + vdec_av1_slice_setup_seq(&vsi->frame.seq, ctrl_seq); + vdec_av1_slice_setup_uh(instance, &vsi->frame, ctrl_fh); + vdec_av1_slice_setup_operating_mode(instance, &vsi->frame); + + vdec_av1_slice_setup_state(vsi); + vdec_av1_slice_setup_slot(instance, vsi, ctrl_fh); + vdec_av1_slice_setup_ref(pfc, ctrl_fh); + vdec_av1_slice_get_previous(vsi); + + pfc->seq = instance->seq; + instance->seq++; + + return ret; +} + +static void vdec_av1_slice_setup_lat_buffer(struct vdec_av1_slice_instance *instance, + struct vdec_av1_slice_vsi *vsi, + struct mtk_vcodec_mem *bs, + struct vdec_lat_buf *lat_buf) +{ + struct vdec_av1_slice_work_buffer *work_buffer; + int i; + + vsi->bs.dma_addr = bs->dma_addr; + vsi->bs.size = bs->size; + + vsi->ube.dma_addr = lat_buf->ctx->msg_queue.wdma_addr.dma_addr; + vsi->ube.size = lat_buf->ctx->msg_queue.wdma_addr.size; + vsi->trans.dma_addr = lat_buf->ctx->msg_queue.wdma_wptr_addr; + /* used to store trans end */ + vsi->trans.dma_addr_end = lat_buf->ctx->msg_queue.wdma_rptr_addr; + vsi->err_map.dma_addr = lat_buf->wdma_err_addr.dma_addr; + vsi->err_map.size = lat_buf->wdma_err_addr.size; + vsi->rd_mv.dma_addr = lat_buf->rd_mv_addr.dma_addr; + vsi->rd_mv.size = lat_buf->rd_mv_addr.size; + + vsi->row_info.buf = 0; + vsi->row_info.size = 0; + + work_buffer = vsi->work_buffer; + + for (i = 0; i < AV1_MAX_FRAME_BUF_COUNT; i++) { + work_buffer[i].mv_addr.buf = instance->mv[i].dma_addr; + work_buffer[i].mv_addr.size = instance->mv[i].size; + work_buffer[i].segid_addr.buf = instance->seg[i].dma_addr; + work_buffer[i].segid_addr.size = instance->seg[i].size; + work_buffer[i].cdf_addr.buf = instance->cdf[i].dma_addr; + work_buffer[i].cdf_addr.size = instance->cdf[i].size; + } + + vsi->cdf_tmp.buf = instance->cdf_temp.dma_addr; + vsi->cdf_tmp.size = instance->cdf_temp.size; + + vsi->tile.buf = instance->tile.dma_addr; + vsi->tile.size = instance->tile.size; + memcpy(lat_buf->tile_addr.va, instance->tile.va, 64 * instance->tile_group.num_tiles); + + vsi->cdf_table.buf = instance->cdf_table.dma_addr; + vsi->cdf_table.size = instance->cdf_table.size; + vsi->iq_table.buf = instance->iq_table.dma_addr; + vsi->iq_table.size = instance->iq_table.size; +} + +static void vdec_av1_slice_setup_seg_buffer(struct vdec_av1_slice_instance *instance, + struct vdec_av1_slice_vsi *vsi) +{ + struct vdec_av1_slice_uncompressed_header *uh = &vsi->frame.uh; + struct mtk_vcodec_mem *buf; + + /* reset segment buffer */ + if (uh->primary_ref_frame == AV1_PRIMARY_REF_NONE || !uh->seg.segmentation_enabled) { + mtk_vcodec_debug(instance, "reset seg %d\n", vsi->slot_id); + if (vsi->slot_id != AV1_INVALID_IDX) { + buf = &instance->seg[vsi->slot_id]; + memset(buf->va, 0, buf->size); + } + } +} + +static void vdec_av1_slice_setup_tile_buffer(struct vdec_av1_slice_instance *instance, + struct vdec_av1_slice_vsi *vsi, + struct mtk_vcodec_mem *bs) +{ + struct vdec_av1_slice_tile_group *tile_group = &instance->tile_group; + struct vdec_av1_slice_uncompressed_header *uh = &vsi->frame.uh; + struct vdec_av1_slice_tile *tile = &uh->tile; + u32 tile_num, tile_row, tile_col; + u32 allow_update_cdf = 0; + u32 sb_boundary_x_m1 = 0, sb_boundary_y_m1 = 0; + int tile_info_base; + u32 tile_buf_pa; + u32 *tile_info_buf = instance->tile.va; + u32 pa = (u32)bs->dma_addr; + + if (uh->disable_cdf_update == 0) + allow_update_cdf = 1; + + for (tile_num = 0; tile_num < tile_group->num_tiles; tile_num++) { + /* each uint32 takes place of 4 bytes */ + tile_info_base = (AV1_TILE_BUF_SIZE * tile_num) >> 2; + tile_row = tile_num / tile->tile_cols; + tile_col = tile_num % tile->tile_cols; + tile_info_buf[tile_info_base + 0] = (tile_group->tile_size[tile_num] << 3); + tile_buf_pa = pa + tile_group->tile_start_offset[tile_num]; + + tile_info_buf[tile_info_base + 1] = (tile_buf_pa >> 4) << 4; + tile_info_buf[tile_info_base + 2] = (tile_buf_pa % 16) << 3; + + sb_boundary_x_m1 = + (tile->mi_col_starts[tile_col + 1] - tile->mi_col_starts[tile_col] - 1) & + 0x3f; + sb_boundary_y_m1 = + (tile->mi_row_starts[tile_row + 1] - tile->mi_row_starts[tile_row] - 1) & + 0x1ff; + + tile_info_buf[tile_info_base + 3] = (sb_boundary_y_m1 << 7) | sb_boundary_x_m1; + tile_info_buf[tile_info_base + 4] = ((allow_update_cdf << 18) | (1 << 16)); + + if (tile_num == tile->context_update_tile_id && + uh->disable_frame_end_update_cdf == 0) + tile_info_buf[tile_info_base + 4] |= (1 << 17); + + mtk_vcodec_debug(instance, "// tile buf %d pos(%dx%d) offset 0x%x\n", + tile_num, tile_row, tile_col, tile_info_base); + mtk_vcodec_debug(instance, "// %08x %08x %08x %08x\n", + tile_info_buf[tile_info_base + 0], + tile_info_buf[tile_info_base + 1], + tile_info_buf[tile_info_base + 2], + tile_info_buf[tile_info_base + 3]); + mtk_vcodec_debug(instance, "// %08x %08x %08x %08x\n", + tile_info_buf[tile_info_base + 4], + tile_info_buf[tile_info_base + 5], + tile_info_buf[tile_info_base + 6], + tile_info_buf[tile_info_base + 7]); + } +} + +static int vdec_av1_slice_setup_lat(struct vdec_av1_slice_instance *instance, + struct mtk_vcodec_mem *bs, + struct vdec_lat_buf *lat_buf, + struct vdec_av1_slice_pfc *pfc) +{ + struct vdec_av1_slice_vsi *vsi = &pfc->vsi; + int ret; + + ret = vdec_av1_slice_setup_lat_from_src_buf(instance, vsi, lat_buf); + if (ret) + return ret; + + ret = vdec_av1_slice_setup_pfc(instance, pfc); + if (ret) + return ret; + + ret = vdec_av1_slice_setup_tile_group(instance, vsi); + if (ret) + return ret; + + ret = vdec_av1_slice_alloc_working_buffer(instance, vsi); + if (ret) + return ret; + + vdec_av1_slice_setup_seg_buffer(instance, vsi); + vdec_av1_slice_setup_tile_buffer(instance, vsi, bs); + vdec_av1_slice_setup_lat_buffer(instance, vsi, bs, lat_buf); + + return 0; +} + +static int vdec_av1_slice_update_lat(struct vdec_av1_slice_instance *instance, + struct vdec_lat_buf *lat_buf, + struct vdec_av1_slice_pfc *pfc) +{ + struct vdec_av1_slice_vsi *vsi; + + vsi = &pfc->vsi; + mtk_vcodec_debug(instance, "frame %u LAT CRC 0x%08x, output size is %d\n", + pfc->seq, vsi->state.crc[0], vsi->state.out_size); + + /* buffer full, need to re-decode */ + if (vsi->state.full) { + /* buffer not enough */ + if (vsi->trans.dma_addr_end - vsi->trans.dma_addr == vsi->ube.size) + return -ENOMEM; + return -EAGAIN; + } + + instance->width = vsi->frame.uh.upscaled_width; + instance->height = vsi->frame.uh.frame_height; + instance->frame_type = vsi->frame.uh.frame_type; + + return 0; +} + +static int vdec_av1_slice_setup_core_to_dst_buf(struct vdec_av1_slice_instance *instance, + struct vdec_lat_buf *lat_buf) +{ + struct vb2_v4l2_buffer *dst; + + dst = v4l2_m2m_next_dst_buf(instance->ctx->m2m_ctx); + if (!dst) + return -EINVAL; + + v4l2_m2m_buf_copy_metadata(&lat_buf->ts_info, dst, true); + + return 0; +} + +static int vdec_av1_slice_setup_core_buffer(struct vdec_av1_slice_instance *instance, + struct vdec_av1_slice_pfc *pfc, + struct vdec_av1_slice_vsi *vsi, + struct vdec_fb *fb, + struct vdec_lat_buf *lat_buf) +{ + struct vb2_buffer *vb; + struct vb2_queue *vq; + int w, h, plane, size; + int i; + + plane = instance->ctx->q_data[MTK_Q_DATA_DST].fmt->num_planes; + w = vsi->frame.uh.upscaled_width; + h = vsi->frame.uh.frame_height; + size = ALIGN(w, VCODEC_DEC_ALIGNED_64) * ALIGN(h, VCODEC_DEC_ALIGNED_64); + + /* frame buffer */ + vsi->fb.y.dma_addr = fb->base_y.dma_addr; + if (plane == 1) + vsi->fb.c.dma_addr = fb->base_y.dma_addr + size; + else + vsi->fb.c.dma_addr = fb->base_c.dma_addr; + + /* reference buffers */ + vq = v4l2_m2m_get_vq(instance->ctx->m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); + if (!vq) + return -EINVAL; + + /* get current output buffer */ + vb = &v4l2_m2m_next_dst_buf(instance->ctx->m2m_ctx)->vb2_buf; + if (!vb) + return -EINVAL; + + /* get buffer address from vb2buf */ + for (i = 0; i < V4L2_AV1_REFS_PER_FRAME; i++) { + struct vdec_av1_slice_fb *vref = &vsi->ref[i]; + + vb = vb2_find_buffer(vq, pfc->ref_idx[i]); + if (!vb) { + memset(vref, 0, sizeof(*vref)); + continue; + } + + vref->y.dma_addr = vb2_dma_contig_plane_dma_addr(vb, 0); + if (plane == 1) + vref->c.dma_addr = vref->y.dma_addr + size; + else + vref->c.dma_addr = vb2_dma_contig_plane_dma_addr(vb, 1); + } + vsi->tile.dma_addr = lat_buf->tile_addr.dma_addr; + vsi->tile.size = lat_buf->tile_addr.size; + + return 0; +} + +static int vdec_av1_slice_setup_core(struct vdec_av1_slice_instance *instance, + struct vdec_fb *fb, + struct vdec_lat_buf *lat_buf, + struct vdec_av1_slice_pfc *pfc) +{ + struct vdec_av1_slice_vsi *vsi = &pfc->vsi; + int ret; + + ret = vdec_av1_slice_setup_core_to_dst_buf(instance, lat_buf); + if (ret) + return ret; + + ret = vdec_av1_slice_setup_core_buffer(instance, pfc, vsi, fb, lat_buf); + if (ret) + return ret; + + return 0; +} + +static int vdec_av1_slice_update_core(struct vdec_av1_slice_instance *instance, + struct vdec_lat_buf *lat_buf, + struct vdec_av1_slice_pfc *pfc) +{ + struct vdec_av1_slice_vsi *vsi = instance->core_vsi; + + mtk_vcodec_debug(instance, "frame %u Y_CRC %08x %08x %08x %08x\n", + pfc->seq, vsi->state.crc[0], vsi->state.crc[1], + vsi->state.crc[2], vsi->state.crc[3]); + mtk_vcodec_debug(instance, "frame %u C_CRC %08x %08x %08x %08x\n", + pfc->seq, vsi->state.crc[8], vsi->state.crc[9], + vsi->state.crc[10], vsi->state.crc[11]); + + return 0; +} + +static int vdec_av1_slice_init(struct mtk_vcodec_ctx *ctx) +{ + struct vdec_av1_slice_instance *instance; + struct vdec_av1_slice_init_vsi *vsi; + int ret; + + instance = kzalloc(sizeof(*instance), GFP_KERNEL); + if (!instance) + return -ENOMEM; + + instance->ctx = ctx; + instance->vpu.id = SCP_IPI_VDEC_LAT; + instance->vpu.core_id = SCP_IPI_VDEC_CORE; + instance->vpu.ctx = ctx; + instance->vpu.codec_type = ctx->current_codec; + + ret = vpu_dec_init(&instance->vpu); + if (ret) { + mtk_vcodec_err(instance, "failed to init vpu dec, ret %d\n", ret); + goto error_vpu_init; + } + + /* init vsi and global flags */ + vsi = instance->vpu.vsi; + if (!vsi) { + mtk_vcodec_err(instance, "failed to get AV1 vsi\n"); + ret = -EINVAL; + goto error_vsi; + } + instance->init_vsi = vsi; + instance->core_vsi = mtk_vcodec_fw_map_dm_addr(ctx->dev->fw_handler, (u32)vsi->core_vsi); + + if (!instance->core_vsi) { + mtk_vcodec_err(instance, "failed to get AV1 core vsi\n"); + ret = -EINVAL; + goto error_vsi; + } + + if (vsi->vsi_size != sizeof(struct vdec_av1_slice_vsi)) + mtk_vcodec_err(instance, "remote vsi size 0x%x mismatch! expected: 0x%zx\n", + vsi->vsi_size, sizeof(struct vdec_av1_slice_vsi)); + + instance->irq_enabled = 1; + instance->inneracing_mode = IS_VDEC_INNER_RACING(instance->ctx->dev->dec_capability); + + mtk_vcodec_debug(instance, "vsi 0x%p core_vsi 0x%llx 0x%p, inneracing_mode %d\n", + vsi, vsi->core_vsi, instance->core_vsi, instance->inneracing_mode); + + ret = vdec_av1_slice_init_cdf_table(instance); + if (ret) + goto error_vsi; + + ret = vdec_av1_slice_init_iq_table(instance); + if (ret) + goto error_vsi; + + ctx->drv_handle = instance; + + return 0; +error_vsi: + vpu_dec_deinit(&instance->vpu); +error_vpu_init: + kfree(instance); + + return ret; +} + +static void vdec_av1_slice_deinit(void *h_vdec) +{ + struct vdec_av1_slice_instance *instance = h_vdec; + + if (!instance) + return; + mtk_vcodec_debug(instance, "h_vdec 0x%p\n", h_vdec); + vpu_dec_deinit(&instance->vpu); + vdec_av1_slice_free_working_buffer(instance); + vdec_msg_queue_deinit(&instance->ctx->msg_queue, instance->ctx); + kfree(instance); +} + +static int vdec_av1_slice_flush(void *h_vdec, struct mtk_vcodec_mem *bs, + struct vdec_fb *fb, bool *res_chg) +{ + struct vdec_av1_slice_instance *instance = h_vdec; + int i; + + mtk_vcodec_debug(instance, "flush ...\n"); + + vdec_msg_queue_wait_lat_buf_full(&instance->ctx->msg_queue); + + for (i = 0; i < AV1_MAX_FRAME_BUF_COUNT; i++) + vdec_av1_slice_clear_fb(&instance->slots.frame_info[i]); + + return vpu_dec_reset(&instance->vpu); +} + +static void vdec_av1_slice_get_pic_info(struct vdec_av1_slice_instance *instance) +{ + struct mtk_vcodec_ctx *ctx = instance->ctx; + u32 data[3]; + + mtk_vcodec_debug(instance, "w %u h %u\n", ctx->picinfo.pic_w, ctx->picinfo.pic_h); + + data[0] = ctx->picinfo.pic_w; + data[1] = ctx->picinfo.pic_h; + data[2] = ctx->capture_fourcc; + vpu_dec_get_param(&instance->vpu, data, 3, GET_PARAM_PIC_INFO); + + ctx->picinfo.buf_w = ALIGN(ctx->picinfo.pic_w, VCODEC_DEC_ALIGNED_64); + ctx->picinfo.buf_h = ALIGN(ctx->picinfo.pic_h, VCODEC_DEC_ALIGNED_64); + ctx->picinfo.fb_sz[0] = instance->vpu.fb_sz[0]; + ctx->picinfo.fb_sz[1] = instance->vpu.fb_sz[1]; +} + +static inline void vdec_av1_slice_get_dpb_size(struct vdec_av1_slice_instance *instance, + u32 *dpb_sz) +{ + /* refer av1 specification */ + *dpb_sz = V4L2_AV1_TOTAL_REFS_PER_FRAME + 1; +} + +static void vdec_av1_slice_get_crop_info(struct vdec_av1_slice_instance *instance, + struct v4l2_rect *cr) +{ + struct mtk_vcodec_ctx *ctx = instance->ctx; + + cr->left = 0; + cr->top = 0; + cr->width = ctx->picinfo.pic_w; + cr->height = ctx->picinfo.pic_h; + + mtk_vcodec_debug(instance, "l=%d, t=%d, w=%d, h=%d\n", + cr->left, cr->top, cr->width, cr->height); +} + +static int vdec_av1_slice_get_param(void *h_vdec, enum vdec_get_param_type type, void *out) +{ + struct vdec_av1_slice_instance *instance = h_vdec; + + switch (type) { + case GET_PARAM_PIC_INFO: + vdec_av1_slice_get_pic_info(instance); + break; + case GET_PARAM_DPB_SIZE: + vdec_av1_slice_get_dpb_size(instance, out); + break; + case GET_PARAM_CROP_INFO: + vdec_av1_slice_get_crop_info(instance, out); + break; + default: + mtk_vcodec_err(instance, "invalid get parameter type=%d\n", type); + return -EINVAL; + } + + return 0; +} + +static int vdec_av1_slice_lat_decode(void *h_vdec, struct mtk_vcodec_mem *bs, + struct vdec_fb *fb, bool *res_chg) +{ + struct vdec_av1_slice_instance *instance = h_vdec; + struct vdec_lat_buf *lat_buf; + struct vdec_av1_slice_pfc *pfc; + struct vdec_av1_slice_vsi *vsi; + struct mtk_vcodec_ctx *ctx; + int ret; + + if (!instance || !instance->ctx) + return -EINVAL; + + ctx = instance->ctx; + /* init msgQ for the first time */ + if (vdec_msg_queue_init(&ctx->msg_queue, ctx, + vdec_av1_slice_core_decode, sizeof(*pfc))) { + mtk_vcodec_err(instance, "failed to init AV1 msg queue\n"); + return -ENOMEM; + } + + /* bs NULL means flush decoder */ + if (!bs) + return vdec_av1_slice_flush(h_vdec, bs, fb, res_chg); + + lat_buf = vdec_msg_queue_dqbuf(&ctx->msg_queue.lat_ctx); + if (!lat_buf) { + mtk_vcodec_err(instance, "failed to get AV1 lat buf\n"); + return -EAGAIN; + } + pfc = (struct vdec_av1_slice_pfc *)lat_buf->private_data; + if (!pfc) { + ret = -EINVAL; + goto err_free_fb_out; + } + vsi = &pfc->vsi; + + ret = vdec_av1_slice_setup_lat(instance, bs, lat_buf, pfc); + if (ret) { + mtk_vcodec_err(instance, "failed to setup AV1 lat ret %d\n", ret); + goto err_free_fb_out; + } + + vdec_av1_slice_vsi_to_remote(vsi, instance->vsi); + ret = vpu_dec_start(&instance->vpu, NULL, 0); + if (ret) { + mtk_vcodec_err(instance, "failed to dec AV1 ret %d\n", ret); + goto err_free_fb_out; + } + if (instance->inneracing_mode) + vdec_msg_queue_qbuf(&ctx->msg_queue.core_ctx, lat_buf); + + if (instance->irq_enabled) { + ret = mtk_vcodec_wait_for_done_ctx(ctx, MTK_INST_IRQ_RECEIVED, + WAIT_INTR_TIMEOUT_MS, + MTK_VDEC_LAT0); + /* update remote vsi if decode timeout */ + if (ret) { + mtk_vcodec_err(instance, "AV1 Frame %d decode timeout %d\n", pfc->seq, ret); + WRITE_ONCE(instance->vsi->state.timeout, 1); + } + vpu_dec_end(&instance->vpu); + } + + vdec_av1_slice_vsi_from_remote(vsi, instance->vsi); + ret = vdec_av1_slice_update_lat(instance, lat_buf, pfc); + + /* LAT trans full, re-decode */ + if (ret == -EAGAIN) { + mtk_vcodec_err(instance, "AV1 Frame %d trans full\n", pfc->seq); + if (!instance->inneracing_mode) + vdec_msg_queue_qbuf(&ctx->msg_queue.lat_ctx, lat_buf); + return 0; + } + + /* LAT trans full, no more UBE or decode timeout */ + if (ret == -ENOMEM || vsi->state.timeout) { + mtk_vcodec_err(instance, "AV1 Frame %d insufficient buffer or timeout\n", pfc->seq); + if (!instance->inneracing_mode) + vdec_msg_queue_qbuf(&ctx->msg_queue.lat_ctx, lat_buf); + return -EBUSY; + } + vsi->trans.dma_addr_end += ctx->msg_queue.wdma_addr.dma_addr; + mtk_vcodec_debug(instance, "lat dma 1 0x%pad 0x%pad\n", + &pfc->vsi.trans.dma_addr, &pfc->vsi.trans.dma_addr_end); + + vdec_msg_queue_update_ube_wptr(&ctx->msg_queue, vsi->trans.dma_addr_end); + + if (!instance->inneracing_mode) + vdec_msg_queue_qbuf(&ctx->msg_queue.core_ctx, lat_buf); + memcpy(&instance->slots, &vsi->slots, sizeof(instance->slots)); + + return 0; + +err_free_fb_out: + vdec_msg_queue_qbuf(&ctx->msg_queue.lat_ctx, lat_buf); + + if (pfc) + mtk_vcodec_err(instance, "slice dec number: %d err: %d", pfc->seq, ret); + + return ret; +} + +static int vdec_av1_slice_core_decode(struct vdec_lat_buf *lat_buf) +{ + struct vdec_av1_slice_instance *instance; + struct vdec_av1_slice_pfc *pfc; + struct mtk_vcodec_ctx *ctx = NULL; + struct vdec_fb *fb = NULL; + int ret = -EINVAL; + + if (!lat_buf) + return -EINVAL; + + pfc = lat_buf->private_data; + ctx = lat_buf->ctx; + if (!pfc || !ctx) + return -EINVAL; + + instance = ctx->drv_handle; + if (!instance) + goto err; + + fb = ctx->dev->vdec_pdata->get_cap_buffer(ctx); + if (!fb) { + ret = -EBUSY; + goto err; + } + + ret = vdec_av1_slice_setup_core(instance, fb, lat_buf, pfc); + if (ret) { + mtk_vcodec_err(instance, "vdec_av1_slice_setup_core\n"); + goto err; + } + vdec_av1_slice_vsi_to_remote(&pfc->vsi, instance->core_vsi); + ret = vpu_dec_core(&instance->vpu); + if (ret) { + mtk_vcodec_err(instance, "vpu_dec_core\n"); + goto err; + } + + if (instance->irq_enabled) { + ret = mtk_vcodec_wait_for_done_ctx(ctx, MTK_INST_IRQ_RECEIVED, + WAIT_INTR_TIMEOUT_MS, + MTK_VDEC_CORE); + /* update remote vsi if decode timeout */ + if (ret) { + mtk_vcodec_err(instance, "AV1 frame %d core timeout\n", pfc->seq); + WRITE_ONCE(instance->vsi->state.timeout, 1); + } + vpu_dec_core_end(&instance->vpu); + } + + ret = vdec_av1_slice_update_core(instance, lat_buf, pfc); + if (ret) { + mtk_vcodec_err(instance, "vdec_av1_slice_update_core\n"); + goto err; + } + + mtk_vcodec_debug(instance, "core dma_addr_end 0x%pad\n", + &instance->core_vsi->trans.dma_addr_end); + vdec_msg_queue_update_ube_rptr(&ctx->msg_queue, instance->core_vsi->trans.dma_addr_end); + + ctx->dev->vdec_pdata->cap_to_disp(ctx, 0, lat_buf->src_buf_req); + + return 0; + +err: + /* always update read pointer */ + vdec_msg_queue_update_ube_rptr(&ctx->msg_queue, pfc->vsi.trans.dma_addr_end); + + if (fb) + ctx->dev->vdec_pdata->cap_to_disp(ctx, 1, lat_buf->src_buf_req); + + return ret; +} + +const struct vdec_common_if vdec_av1_slice_lat_if = { + .init = vdec_av1_slice_init, + .decode = vdec_av1_slice_lat_decode, + .get_param = vdec_av1_slice_get_param, + .deinit = vdec_av1_slice_deinit, +}; diff --git a/drivers/media/platform/mediatek/vcodec/vdec/vdec_h264_req_multi_if.c b/drivers/media/platform/mediatek/vcodec/vdec/vdec_h264_req_multi_if.c index 999ce7ee5fdc2027662ea06abfc09eb1a6280c15..a7e8e3257b7fcca23383a4191ee136937c84c302 100644 --- a/drivers/media/platform/mediatek/vcodec/vdec/vdec_h264_req_multi_if.c +++ b/drivers/media/platform/mediatek/vcodec/vdec/vdec_h264_req_multi_if.c @@ -596,7 +596,7 @@ static int vdec_h264_slice_lat_decode(void *h_vdec, struct mtk_vcodec_mem *bs, lat_buf = vdec_msg_queue_dqbuf(&inst->ctx->msg_queue.lat_ctx); if (!lat_buf) { - mtk_vcodec_err(inst, "failed to get lat buffer"); + mtk_vcodec_debug(inst, "failed to get lat buffer"); return -EAGAIN; } share_info = lat_buf->private_data; @@ -672,7 +672,7 @@ static int vdec_h264_slice_lat_decode(void *h_vdec, struct mtk_vcodec_mem *bs, if (IS_VDEC_INNER_RACING(inst->ctx->dev->dec_capability)) { memcpy(&share_info->h264_slice_params, &inst->vsi->h264_slice_params, sizeof(share_info->h264_slice_params)); - vdec_msg_queue_qbuf(&inst->ctx->dev->msg_queue_core_ctx, lat_buf); + vdec_msg_queue_qbuf(&inst->ctx->msg_queue.core_ctx, lat_buf); } /* wait decoder done interrupt */ @@ -698,7 +698,7 @@ static int vdec_h264_slice_lat_decode(void *h_vdec, struct mtk_vcodec_mem *bs, if (!IS_VDEC_INNER_RACING(inst->ctx->dev->dec_capability)) { memcpy(&share_info->h264_slice_params, &inst->vsi->h264_slice_params, sizeof(share_info->h264_slice_params)); - vdec_msg_queue_qbuf(&inst->ctx->dev->msg_queue_core_ctx, lat_buf); + vdec_msg_queue_qbuf(&inst->ctx->msg_queue.core_ctx, lat_buf); } mtk_vcodec_debug(inst, "dec num: %d lat crc: 0x%x 0x%x 0x%x", inst->slice_dec_num, inst->vsi->dec.crc[0], inst->vsi->dec.crc[1], inst->vsi->dec.crc[2]); diff --git a/drivers/media/platform/mediatek/vcodec/vdec/vdec_hevc_req_multi_if.c b/drivers/media/platform/mediatek/vcodec/vdec/vdec_hevc_req_multi_if.c new file mode 100644 index 0000000000000000000000000000000000000000..1e6ab138b0bbe247d971db8d59475267a9e4b5c2 --- /dev/null +++ b/drivers/media/platform/mediatek/vcodec/vdec/vdec_hevc_req_multi_if.c @@ -0,0 +1,1097 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2023 MediaTek Inc. + * Author: Yunfei Dong + */ + +#include +#include +#include + +#include "../mtk_vcodec_util.h" +#include "../mtk_vcodec_dec.h" +#include "../mtk_vcodec_intr.h" +#include "../vdec_drv_base.h" +#include "../vdec_drv_if.h" +#include "../vdec_vpu_if.h" + +/* the size used to store hevc wrap information */ +#define VDEC_HEVC_WRAP_SZ (532 * SZ_1K) + +#define HEVC_MAX_MV_NUM 32 + +/* get used parameters for sps/pps */ +#define GET_HEVC_VDEC_FLAG(cond, flag) \ + { dst_param->cond = ((src_param->flags & (flag)) ? (1) : (0)); } +#define GET_HEVC_VDEC_PARAM(param) \ + { dst_param->param = src_param->param; } + +/** + * enum vdec_hevc_core_dec_err_type - core decode error type + * + * @TRANS_BUFFER_FULL: trans buffer is full + * @SLICE_HEADER_FULL: slice header buffer is full + */ +enum vdec_hevc_core_dec_err_type { + TRANS_BUFFER_FULL = 1, + SLICE_HEADER_FULL, +}; + +/** + * struct mtk_hevc_dpb_info - hevc dpb information + * + * @y_dma_addr: Y plane physical address + * @c_dma_addr: CbCr plane physical address + * @reference_flag: reference picture flag (short/long term reference picture) + * @field: field picture flag + */ +struct mtk_hevc_dpb_info { + dma_addr_t y_dma_addr; + dma_addr_t c_dma_addr; + int reference_flag; + int field; +}; + +/* + * struct mtk_hevc_sps_param - parameters for sps + */ +struct mtk_hevc_sps_param { + unsigned char video_parameter_set_id; + unsigned char seq_parameter_set_id; + unsigned short pic_width_in_luma_samples; + unsigned short pic_height_in_luma_samples; + unsigned char bit_depth_luma_minus8; + unsigned char bit_depth_chroma_minus8; + unsigned char log2_max_pic_order_cnt_lsb_minus4; + unsigned char sps_max_dec_pic_buffering_minus1; + unsigned char sps_max_num_reorder_pics; + unsigned char sps_max_latency_increase_plus1; + unsigned char log2_min_luma_coding_block_size_minus3; + unsigned char log2_diff_max_min_luma_coding_block_size; + unsigned char log2_min_luma_transform_block_size_minus2; + unsigned char log2_diff_max_min_luma_transform_block_size; + unsigned char max_transform_hierarchy_depth_inter; + unsigned char max_transform_hierarchy_depth_intra; + unsigned char pcm_sample_bit_depth_luma_minus1; + unsigned char pcm_sample_bit_depth_chroma_minus1; + unsigned char log2_min_pcm_luma_coding_block_size_minus3; + unsigned char log2_diff_max_min_pcm_luma_coding_block_size; + unsigned char num_short_term_ref_pic_sets; + unsigned char num_long_term_ref_pics_sps; + unsigned char chroma_format_idc; + unsigned char sps_max_sub_layers_minus1; + unsigned char separate_colour_plane; + unsigned char scaling_list_enabled; + unsigned char amp_enabled; + unsigned char sample_adaptive_offset; + unsigned char pcm_enabled; + unsigned char pcm_loop_filter_disabled; + unsigned char long_term_ref_pics_enabled; + unsigned char sps_temporal_mvp_enabled; + unsigned char strong_intra_smoothing_enabled; + unsigned char reserved[5]; +}; + +/* + * struct mtk_hevc_pps_param - parameters for pps + */ +struct mtk_hevc_pps_param { + unsigned char pic_parameter_set_id; + unsigned char num_extra_slice_header_bits; + unsigned char num_ref_idx_l0_default_active_minus1; + unsigned char num_ref_idx_l1_default_active_minus1; + char init_qp_minus26; + unsigned char diff_cu_qp_delta_depth; + char pps_cb_qp_offset; + char pps_cr_qp_offset; + unsigned char num_tile_columns_minus1; + unsigned char num_tile_rows_minus1; + unsigned char column_width_minus1[20]; + unsigned char row_height_minus1[22]; + char pps_beta_offset_div2; + char pps_tc_offset_div2; + unsigned char log2_parallel_merge_level_minus2; + char dependent_slice_segment_enabled; + char output_flag_present; + char sign_data_hiding_enabled; + char cabac_init_present; + char constrained_intra_pred; + char transform_skip_enabled; + char cu_qp_delta_enabled; + char pps_slice_chroma_qp_offsets_present; + char weighted_pred; + char weighted_bipred; + char transquant_bypass_enabled; + char pps_flag_tiles_enabled; + char entropy_coding_sync_enabled; + char loop_filter_across_tiles_enabled; + char pps_loop_filter_across_slices_enabled; + char deblocking_filter_override_enabled; + char pps_disable_deflocking_filter; + char lists_modification_present; + char slice_segment_header_extersion_present; + char deblocking_filter_control_present; + char uniform_spacing; + char reserved[6]; +}; + +/* + * struct mtk_hevc_slice_header_param - parameters for slice header + */ +struct mtk_hevc_slice_header_param { + unsigned int slice_type; + unsigned int num_active_ref_layer_pics; + int slice_qp; + int slice_qp_delta_cb; + int slice_qp_delta_cr; + int num_ref_idx[3]; + unsigned int col_ref_idx; + unsigned int five_minus_max_num_merge_cand; + int slice_deblocking_filter_beta_offset_div2; + int slice_deblocking_filter_tc_offset_div2; + unsigned char sao_enable_flag; + unsigned char sao_enable_flag_chroma; + unsigned char cabac_init_flag; + unsigned char slice_tmvp_flags_present; + unsigned char col_from_l0_flag; + unsigned char mvd_l1_zero_flag; + unsigned char slice_loop_filter_across_slices_enabled_flag; + unsigned char deblocking_filter_disable_flag; + unsigned int slice_reg0; + unsigned int slice_reg1; + unsigned int slice_reg2; + unsigned int num_rps_curr_temp_list; + unsigned int ref_list_mode; + int str_num_delta_pocs; + int str_num_negtive_pos_pics; + int num_long_term; + int num_long_term_sps; + unsigned int max_cu_width; + unsigned int max_cu_height; + unsigned int num_entry_point_offsets; + unsigned int last_lcu_x_in_tile[17]; + unsigned int last_lcu_y_in_tile[17]; + unsigned char nal_unit_type; +}; + +/* + * struct slice_api_hevc_scaling_matrix - parameters for scaling list + */ +struct slice_api_hevc_scaling_matrix { + unsigned char scaling_list_4x4[6][16]; + unsigned char scaling_list_8x8[6][64]; + unsigned char scaling_list_16x16[6][64]; + unsigned char scaling_list_32x32[2][64]; + unsigned char scaling_list_dc_coef_16x16[6]; + unsigned char scaling_list_dc_coef_32x32[2]; +}; + +/* + * struct slice_hevc_dpb_entry - each dpb information + */ +struct slice_hevc_dpb_entry { + u64 timestamp; + unsigned char flags; + unsigned char field_pic; + int pic_order_cnt_val; +}; + +/* + * struct slice_api_hevc_decode_param - parameters for decode. + */ +struct slice_api_hevc_decode_param { + struct slice_hevc_dpb_entry dpb[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; + int pic_order_cnt_val; + unsigned short short_term_ref_pic_set_size; + unsigned short long_term_ref_pic_set_size; + unsigned char num_active_dpb_entries; + unsigned char num_poc_st_curr_before; + unsigned char num_poc_st_curr_after; + unsigned char num_poc_lt_curr; + unsigned char poc_st_curr_before[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; + unsigned char poc_st_curr_after[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; + unsigned char poc_lt_curr[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; + unsigned char num_delta_pocs_of_ref_rps_idx; + int flags; +}; + +/** + * struct hevc_fb - hevc decode frame buffer information + * + * @vdec_fb_va: virtual address of struct vdec_fb + * @y_fb_dma: dma address of Y frame buffer (luma) + * @c_fb_dma: dma address of C frame buffer (chroma) + * @poc: picture order count of frame buffer + * @reserved: for 8 bytes alignment + */ +struct hevc_fb { + u64 vdec_fb_va; + u64 y_fb_dma; + u64 c_fb_dma; + s32 poc; + u32 reserved; +}; + +/** + * struct vdec_hevc_slice_lat_dec_param - parameters for decode current frame + * + * @sps: hevc sps syntax parameters + * @pps: hevc pps syntax parameters + * @slice_header: hevc slice header syntax parameters + * @scaling_matrix: hevc scaling list parameters + * @decode_params: decoder parameters of each frame used for hardware decode + * @hevc_dpb_info: dpb reference list + */ +struct vdec_hevc_slice_lat_dec_param { + struct mtk_hevc_sps_param sps; + struct mtk_hevc_pps_param pps; + struct mtk_hevc_slice_header_param slice_header; + struct slice_api_hevc_scaling_matrix scaling_matrix; + struct slice_api_hevc_decode_param decode_params; + struct mtk_hevc_dpb_info hevc_dpb_info[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; +}; + +/** + * struct vdec_hevc_slice_info - decode information + * + * @wdma_end_addr_offset: wdma end address offset + * @timeout: Decode timeout: 1 timeout, 0 no timeount + * @vdec_fb_va: VDEC frame buffer struct virtual address + * @crc: Used to check whether hardware's status is right + */ +struct vdec_hevc_slice_info { + u64 wdma_end_addr_offset; + u64 timeout; + u64 vdec_fb_va; + u32 crc[8]; +}; + +/* + * struct vdec_hevc_slice_mem - memory address and size + */ +struct vdec_hevc_slice_mem { + union { + u64 buf; + dma_addr_t dma_addr; + }; + union { + size_t size; + dma_addr_t dma_addr_end; + u64 padding; + }; +}; + +/** + * struct vdec_hevc_slice_fb - frame buffer for decoding + * @y: current y buffer address info + * @c: current c buffer address info + */ +struct vdec_hevc_slice_fb { + struct vdec_hevc_slice_mem y; + struct vdec_hevc_slice_mem c; +}; + +/** + * struct vdec_hevc_slice_vsi - shared memory for decode information exchange + * between SCP and Host. + * + * @bs: input buffer info + * + * @ube: ube buffer + * @trans: transcoded buffer + * @err_map: err map buffer + * @slice_bc: slice bc buffer + * @wrap: temp buffer + * + * @fb: current y/c buffer + * @mv_buf_dma: HW working motion vector buffer + * @dec: decode information (AP-R, VPU-W) + * @hevc_slice_params: decode parameters for hw used + */ +struct vdec_hevc_slice_vsi { + /* used in LAT stage */ + struct vdec_hevc_slice_mem bs; + + struct vdec_hevc_slice_mem ube; + struct vdec_hevc_slice_mem trans; + struct vdec_hevc_slice_mem err_map; + struct vdec_hevc_slice_mem slice_bc; + struct vdec_hevc_slice_mem wrap; + + struct vdec_hevc_slice_fb fb; + struct vdec_hevc_slice_mem mv_buf_dma[HEVC_MAX_MV_NUM]; + struct vdec_hevc_slice_info dec; + struct vdec_hevc_slice_lat_dec_param hevc_slice_params; +}; + +/** + * struct vdec_hevc_slice_share_info - shared information used to exchange + * message between lat and core + * + * @sps: sequence header information from user space + * @dec_params: decoder params from user space + * @hevc_slice_params: decoder params used for hardware + * @trans: trans buffer dma address + */ +struct vdec_hevc_slice_share_info { + struct v4l2_ctrl_hevc_sps sps; + struct v4l2_ctrl_hevc_decode_params dec_params; + struct vdec_hevc_slice_lat_dec_param hevc_slice_params; + struct vdec_hevc_slice_mem trans; +}; + +/** + * struct vdec_hevc_slice_inst - hevc decoder instance + * + * @slice_dec_num: how many picture be decoded + * @ctx: point to mtk_vcodec_ctx + * @mv_buf: HW working motion vector buffer + * @vpu: VPU instance + * @vsi: vsi used for lat + * @vsi_core: vsi used for core + * @wrap_addr: wrap address used for hevc + * + * @hevc_slice_param: the parameters that hardware use to decode + * + * @resolution_changed: resolution changed + * @realloc_mv_buf: reallocate mv buffer + * @cap_num_planes: number of capture queue plane + */ +struct vdec_hevc_slice_inst { + unsigned int slice_dec_num; + struct mtk_vcodec_ctx *ctx; + struct mtk_vcodec_mem mv_buf[HEVC_MAX_MV_NUM]; + struct vdec_vpu_inst vpu; + struct vdec_hevc_slice_vsi *vsi; + struct vdec_hevc_slice_vsi *vsi_core; + struct mtk_vcodec_mem wrap_addr; + + struct vdec_hevc_slice_lat_dec_param hevc_slice_param; + + unsigned int resolution_changed; + unsigned int realloc_mv_buf; + unsigned int cap_num_planes; +}; + +static unsigned int vdec_hevc_get_mv_buf_size(unsigned int width, unsigned int height) +{ + const unsigned int unit_size = (width / 16) * (height / 16) + 8; + + return 64 * unit_size; +} + +static void *vdec_hevc_get_ctrl_ptr(struct mtk_vcodec_ctx *ctx, int id) +{ + struct v4l2_ctrl *ctrl = v4l2_ctrl_find(&ctx->ctrl_hdl, id); + + if (!ctrl) + return ERR_PTR(-EINVAL); + + return ctrl->p_cur.p; +} + +static void vdec_hevc_fill_dpb_info(struct mtk_vcodec_ctx *ctx, + struct slice_api_hevc_decode_param *decode_params, + struct mtk_hevc_dpb_info *hevc_dpb_info) +{ + const struct slice_hevc_dpb_entry *dpb; + struct vb2_queue *vq; + struct vb2_buffer *vb; + int index; + + vq = v4l2_m2m_get_vq(ctx->m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); + for (index = 0; index < V4L2_HEVC_DPB_ENTRIES_NUM_MAX; index++) { + dpb = &decode_params->dpb[index]; + if (index >= decode_params->num_active_dpb_entries) + continue; + + vb = vb2_find_buffer(vq, dpb->timestamp); + if (!vb) { + dev_err(&ctx->dev->plat_dev->dev, + "Reference invalid: dpb_index(%d) timestamp(%lld)", + index, dpb->timestamp); + continue; + } + + hevc_dpb_info[index].field = dpb->field_pic; + + hevc_dpb_info[index].y_dma_addr = vb2_dma_contig_plane_dma_addr(vb, 0); + if (ctx->q_data[MTK_Q_DATA_DST].fmt->num_planes == 2) + hevc_dpb_info[index].c_dma_addr = vb2_dma_contig_plane_dma_addr(vb, 1); + else + hevc_dpb_info[index].c_dma_addr = + hevc_dpb_info[index].y_dma_addr + ctx->picinfo.fb_sz[0]; + } +} + +static void vdec_hevc_copy_sps_params(struct mtk_hevc_sps_param *dst_param, + const struct v4l2_ctrl_hevc_sps *src_param) +{ + GET_HEVC_VDEC_PARAM(video_parameter_set_id); + GET_HEVC_VDEC_PARAM(seq_parameter_set_id); + GET_HEVC_VDEC_PARAM(pic_width_in_luma_samples); + GET_HEVC_VDEC_PARAM(pic_height_in_luma_samples); + GET_HEVC_VDEC_PARAM(bit_depth_luma_minus8); + GET_HEVC_VDEC_PARAM(bit_depth_chroma_minus8); + GET_HEVC_VDEC_PARAM(log2_max_pic_order_cnt_lsb_minus4); + GET_HEVC_VDEC_PARAM(sps_max_dec_pic_buffering_minus1); + GET_HEVC_VDEC_PARAM(sps_max_num_reorder_pics); + GET_HEVC_VDEC_PARAM(sps_max_latency_increase_plus1); + GET_HEVC_VDEC_PARAM(log2_min_luma_coding_block_size_minus3); + GET_HEVC_VDEC_PARAM(log2_diff_max_min_luma_coding_block_size); + GET_HEVC_VDEC_PARAM(log2_min_luma_transform_block_size_minus2); + GET_HEVC_VDEC_PARAM(log2_diff_max_min_luma_transform_block_size); + GET_HEVC_VDEC_PARAM(max_transform_hierarchy_depth_inter); + GET_HEVC_VDEC_PARAM(max_transform_hierarchy_depth_intra); + GET_HEVC_VDEC_PARAM(pcm_sample_bit_depth_luma_minus1); + GET_HEVC_VDEC_PARAM(pcm_sample_bit_depth_chroma_minus1); + GET_HEVC_VDEC_PARAM(log2_min_pcm_luma_coding_block_size_minus3); + GET_HEVC_VDEC_PARAM(log2_diff_max_min_pcm_luma_coding_block_size); + GET_HEVC_VDEC_PARAM(num_short_term_ref_pic_sets); + GET_HEVC_VDEC_PARAM(num_long_term_ref_pics_sps); + GET_HEVC_VDEC_PARAM(chroma_format_idc); + GET_HEVC_VDEC_PARAM(sps_max_sub_layers_minus1); + + GET_HEVC_VDEC_FLAG(separate_colour_plane, + V4L2_HEVC_SPS_FLAG_SEPARATE_COLOUR_PLANE); + GET_HEVC_VDEC_FLAG(scaling_list_enabled, + V4L2_HEVC_SPS_FLAG_SCALING_LIST_ENABLED); + GET_HEVC_VDEC_FLAG(amp_enabled, + V4L2_HEVC_SPS_FLAG_AMP_ENABLED); + GET_HEVC_VDEC_FLAG(sample_adaptive_offset, + V4L2_HEVC_SPS_FLAG_SAMPLE_ADAPTIVE_OFFSET); + GET_HEVC_VDEC_FLAG(pcm_enabled, + V4L2_HEVC_SPS_FLAG_PCM_ENABLED); + GET_HEVC_VDEC_FLAG(pcm_loop_filter_disabled, + V4L2_HEVC_SPS_FLAG_PCM_LOOP_FILTER_DISABLED); + GET_HEVC_VDEC_FLAG(long_term_ref_pics_enabled, + V4L2_HEVC_SPS_FLAG_LONG_TERM_REF_PICS_PRESENT); + GET_HEVC_VDEC_FLAG(sps_temporal_mvp_enabled, + V4L2_HEVC_SPS_FLAG_SPS_TEMPORAL_MVP_ENABLED); + GET_HEVC_VDEC_FLAG(strong_intra_smoothing_enabled, + V4L2_HEVC_SPS_FLAG_STRONG_INTRA_SMOOTHING_ENABLED); +} + +static void vdec_hevc_copy_pps_params(struct mtk_hevc_pps_param *dst_param, + const struct v4l2_ctrl_hevc_pps *src_param) +{ + int i; + + GET_HEVC_VDEC_PARAM(pic_parameter_set_id); + GET_HEVC_VDEC_PARAM(num_extra_slice_header_bits); + GET_HEVC_VDEC_PARAM(num_ref_idx_l0_default_active_minus1); + GET_HEVC_VDEC_PARAM(num_ref_idx_l1_default_active_minus1); + GET_HEVC_VDEC_PARAM(init_qp_minus26); + GET_HEVC_VDEC_PARAM(diff_cu_qp_delta_depth); + GET_HEVC_VDEC_PARAM(pps_cb_qp_offset); + GET_HEVC_VDEC_PARAM(pps_cr_qp_offset); + GET_HEVC_VDEC_PARAM(num_tile_columns_minus1); + GET_HEVC_VDEC_PARAM(num_tile_rows_minus1); + GET_HEVC_VDEC_PARAM(init_qp_minus26); + GET_HEVC_VDEC_PARAM(diff_cu_qp_delta_depth); + GET_HEVC_VDEC_PARAM(pic_parameter_set_id); + GET_HEVC_VDEC_PARAM(num_extra_slice_header_bits); + GET_HEVC_VDEC_PARAM(num_ref_idx_l0_default_active_minus1); + GET_HEVC_VDEC_PARAM(num_ref_idx_l1_default_active_minus1); + GET_HEVC_VDEC_PARAM(pps_beta_offset_div2); + GET_HEVC_VDEC_PARAM(pps_tc_offset_div2); + GET_HEVC_VDEC_PARAM(log2_parallel_merge_level_minus2); + + for (i = 0; i < ARRAY_SIZE(src_param->column_width_minus1); i++) + GET_HEVC_VDEC_PARAM(column_width_minus1[i]); + for (i = 0; i < ARRAY_SIZE(src_param->row_height_minus1); i++) + GET_HEVC_VDEC_PARAM(row_height_minus1[i]); + + GET_HEVC_VDEC_FLAG(dependent_slice_segment_enabled, + V4L2_HEVC_PPS_FLAG_DEPENDENT_SLICE_SEGMENT_ENABLED); + GET_HEVC_VDEC_FLAG(output_flag_present, + V4L2_HEVC_PPS_FLAG_OUTPUT_FLAG_PRESENT); + GET_HEVC_VDEC_FLAG(sign_data_hiding_enabled, + V4L2_HEVC_PPS_FLAG_SIGN_DATA_HIDING_ENABLED); + GET_HEVC_VDEC_FLAG(cabac_init_present, + V4L2_HEVC_PPS_FLAG_CABAC_INIT_PRESENT); + GET_HEVC_VDEC_FLAG(constrained_intra_pred, + V4L2_HEVC_PPS_FLAG_CONSTRAINED_INTRA_PRED); + GET_HEVC_VDEC_FLAG(transform_skip_enabled, + V4L2_HEVC_PPS_FLAG_TRANSFORM_SKIP_ENABLED); + GET_HEVC_VDEC_FLAG(cu_qp_delta_enabled, + V4L2_HEVC_PPS_FLAG_CU_QP_DELTA_ENABLED); + GET_HEVC_VDEC_FLAG(pps_slice_chroma_qp_offsets_present, + V4L2_HEVC_PPS_FLAG_PPS_SLICE_CHROMA_QP_OFFSETS_PRESENT); + GET_HEVC_VDEC_FLAG(weighted_pred, + V4L2_HEVC_PPS_FLAG_WEIGHTED_PRED); + GET_HEVC_VDEC_FLAG(weighted_bipred, + V4L2_HEVC_PPS_FLAG_WEIGHTED_BIPRED); + GET_HEVC_VDEC_FLAG(transquant_bypass_enabled, + V4L2_HEVC_PPS_FLAG_TRANSQUANT_BYPASS_ENABLED); + GET_HEVC_VDEC_FLAG(pps_flag_tiles_enabled, + V4L2_HEVC_PPS_FLAG_TILES_ENABLED); + GET_HEVC_VDEC_FLAG(entropy_coding_sync_enabled, + V4L2_HEVC_PPS_FLAG_ENTROPY_CODING_SYNC_ENABLED); + GET_HEVC_VDEC_FLAG(loop_filter_across_tiles_enabled, + V4L2_HEVC_PPS_FLAG_LOOP_FILTER_ACROSS_TILES_ENABLED); + GET_HEVC_VDEC_FLAG(pps_loop_filter_across_slices_enabled, + V4L2_HEVC_PPS_FLAG_PPS_LOOP_FILTER_ACROSS_SLICES_ENABLED); + GET_HEVC_VDEC_FLAG(deblocking_filter_override_enabled, + V4L2_HEVC_PPS_FLAG_DEBLOCKING_FILTER_OVERRIDE_ENABLED); + GET_HEVC_VDEC_FLAG(pps_disable_deflocking_filter, + V4L2_HEVC_PPS_FLAG_PPS_DISABLE_DEBLOCKING_FILTER); + GET_HEVC_VDEC_FLAG(lists_modification_present, + V4L2_HEVC_PPS_FLAG_LISTS_MODIFICATION_PRESENT); + GET_HEVC_VDEC_FLAG(slice_segment_header_extersion_present, + V4L2_HEVC_PPS_FLAG_SLICE_SEGMENT_HEADER_EXTENSION_PRESENT); + GET_HEVC_VDEC_FLAG(deblocking_filter_control_present, + V4L2_HEVC_PPS_FLAG_DEBLOCKING_FILTER_CONTROL_PRESENT); + GET_HEVC_VDEC_FLAG(uniform_spacing, + V4L2_HEVC_PPS_FLAG_UNIFORM_SPACING); +} + +static void vdec_hevc_copy_scaling_matrix(struct slice_api_hevc_scaling_matrix *dst_matrix, + const struct v4l2_ctrl_hevc_scaling_matrix *src_matrix) +{ + memcpy(dst_matrix, src_matrix, sizeof(*src_matrix)); +} + +static void +vdec_hevc_copy_decode_params(struct slice_api_hevc_decode_param *dst_param, + const struct v4l2_ctrl_hevc_decode_params *src_param, + const struct v4l2_hevc_dpb_entry dpb[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]) +{ + struct slice_hevc_dpb_entry *dst_entry; + const struct v4l2_hevc_dpb_entry *src_entry; + int i; + + for (i = 0; i < ARRAY_SIZE(dst_param->dpb); i++) { + dst_entry = &dst_param->dpb[i]; + src_entry = &dpb[i]; + + dst_entry->timestamp = src_entry->timestamp; + dst_entry->flags = src_entry->flags; + dst_entry->field_pic = src_entry->field_pic; + dst_entry->pic_order_cnt_val = src_entry->pic_order_cnt_val; + + GET_HEVC_VDEC_PARAM(poc_st_curr_before[i]); + GET_HEVC_VDEC_PARAM(poc_st_curr_after[i]); + GET_HEVC_VDEC_PARAM(poc_lt_curr[i]); + } + + GET_HEVC_VDEC_PARAM(pic_order_cnt_val); + GET_HEVC_VDEC_PARAM(short_term_ref_pic_set_size); + GET_HEVC_VDEC_PARAM(long_term_ref_pic_set_size); + GET_HEVC_VDEC_PARAM(num_active_dpb_entries); + GET_HEVC_VDEC_PARAM(num_poc_st_curr_before); + GET_HEVC_VDEC_PARAM(num_poc_st_curr_after); + GET_HEVC_VDEC_PARAM(num_delta_pocs_of_ref_rps_idx); + GET_HEVC_VDEC_PARAM(num_poc_lt_curr); + GET_HEVC_VDEC_PARAM(flags); +} + +static int vdec_hevc_slice_fill_decode_parameters(struct vdec_hevc_slice_inst *inst, + struct vdec_hevc_slice_share_info *share_info) +{ + struct vdec_hevc_slice_lat_dec_param *slice_param = &inst->vsi->hevc_slice_params; + const struct v4l2_ctrl_hevc_decode_params *dec_params; + const struct v4l2_ctrl_hevc_scaling_matrix *src_matrix; + const struct v4l2_ctrl_hevc_sps *sps; + const struct v4l2_ctrl_hevc_pps *pps; + + dec_params = + vdec_hevc_get_ctrl_ptr(inst->ctx, V4L2_CID_STATELESS_HEVC_DECODE_PARAMS); + if (IS_ERR(dec_params)) + return PTR_ERR(dec_params); + + src_matrix = + vdec_hevc_get_ctrl_ptr(inst->ctx, V4L2_CID_STATELESS_HEVC_SCALING_MATRIX); + if (IS_ERR(src_matrix)) + return PTR_ERR(src_matrix); + + sps = vdec_hevc_get_ctrl_ptr(inst->ctx, V4L2_CID_STATELESS_HEVC_SPS); + if (IS_ERR(sps)) + return PTR_ERR(sps); + + pps = vdec_hevc_get_ctrl_ptr(inst->ctx, V4L2_CID_STATELESS_HEVC_PPS); + if (IS_ERR(pps)) + return PTR_ERR(pps); + + vdec_hevc_copy_sps_params(&slice_param->sps, sps); + vdec_hevc_copy_pps_params(&slice_param->pps, pps); + vdec_hevc_copy_scaling_matrix(&slice_param->scaling_matrix, src_matrix); + + memcpy(&share_info->sps, sps, sizeof(*sps)); + memcpy(&share_info->dec_params, dec_params, sizeof(*dec_params)); + + slice_param->decode_params.num_poc_st_curr_before = dec_params->num_poc_st_curr_before; + slice_param->decode_params.num_poc_st_curr_after = dec_params->num_poc_st_curr_after; + slice_param->decode_params.num_poc_lt_curr = dec_params->num_poc_lt_curr; + slice_param->decode_params.num_delta_pocs_of_ref_rps_idx = + dec_params->num_delta_pocs_of_ref_rps_idx; + + return 0; +} + +static void vdec_hevc_slice_fill_decode_reflist(struct vdec_hevc_slice_inst *inst, + struct vdec_hevc_slice_lat_dec_param *slice_param, + struct vdec_hevc_slice_share_info *share_info) +{ + struct v4l2_ctrl_hevc_decode_params *dec_params = &share_info->dec_params; + + vdec_hevc_copy_decode_params(&slice_param->decode_params, dec_params, + share_info->dec_params.dpb); + + vdec_hevc_fill_dpb_info(inst->ctx, &slice_param->decode_params, + slice_param->hevc_dpb_info); +} + +static int vdec_hevc_slice_alloc_mv_buf(struct vdec_hevc_slice_inst *inst, + struct vdec_pic_info *pic) +{ + unsigned int buf_sz = vdec_hevc_get_mv_buf_size(pic->buf_w, pic->buf_h); + struct mtk_vcodec_mem *mem; + int i, err; + + mtk_v4l2_debug(3, "allocate mv buffer size = 0x%x", buf_sz); + for (i = 0; i < HEVC_MAX_MV_NUM; i++) { + mem = &inst->mv_buf[i]; + if (mem->va) + mtk_vcodec_mem_free(inst->ctx, mem); + mem->size = buf_sz; + err = mtk_vcodec_mem_alloc(inst->ctx, mem); + if (err) { + mtk_vcodec_err(inst, "failed to allocate mv buf"); + return err; + } + } + + return 0; +} + +static void vdec_hevc_slice_free_mv_buf(struct vdec_hevc_slice_inst *inst) +{ + int i; + struct mtk_vcodec_mem *mem; + + for (i = 0; i < HEVC_MAX_MV_NUM; i++) { + mem = &inst->mv_buf[i]; + if (mem->va) + mtk_vcodec_mem_free(inst->ctx, mem); + } +} + +static void vdec_hevc_slice_get_pic_info(struct vdec_hevc_slice_inst *inst) +{ + struct mtk_vcodec_ctx *ctx = inst->ctx; + u32 data[3]; + + data[0] = ctx->picinfo.pic_w; + data[1] = ctx->picinfo.pic_h; + data[2] = ctx->capture_fourcc; + vpu_dec_get_param(&inst->vpu, data, 3, GET_PARAM_PIC_INFO); + + ctx->picinfo.buf_w = ALIGN(ctx->picinfo.pic_w, VCODEC_DEC_ALIGNED_64); + ctx->picinfo.buf_h = ALIGN(ctx->picinfo.pic_h, VCODEC_DEC_ALIGNED_64); + ctx->picinfo.fb_sz[0] = inst->vpu.fb_sz[0]; + ctx->picinfo.fb_sz[1] = inst->vpu.fb_sz[1]; + inst->cap_num_planes = + ctx->q_data[MTK_Q_DATA_DST].fmt->num_planes; + + mtk_vcodec_debug(inst, "pic(%d, %d), buf(%d, %d)", + ctx->picinfo.pic_w, ctx->picinfo.pic_h, + ctx->picinfo.buf_w, ctx->picinfo.buf_h); + mtk_vcodec_debug(inst, "Y/C(%d, %d)", ctx->picinfo.fb_sz[0], + ctx->picinfo.fb_sz[1]); + + if (ctx->last_decoded_picinfo.pic_w != ctx->picinfo.pic_w || + ctx->last_decoded_picinfo.pic_h != ctx->picinfo.pic_h) { + inst->resolution_changed = true; + if (ctx->last_decoded_picinfo.buf_w != ctx->picinfo.buf_w || + ctx->last_decoded_picinfo.buf_h != ctx->picinfo.buf_h) + inst->realloc_mv_buf = true; + + mtk_v4l2_debug(1, "resChg: (%d %d) : old(%d, %d) -> new(%d, %d)", + inst->resolution_changed, + inst->realloc_mv_buf, + ctx->last_decoded_picinfo.pic_w, + ctx->last_decoded_picinfo.pic_h, + ctx->picinfo.pic_w, ctx->picinfo.pic_h); + } +} + +static void vdec_hevc_slice_get_crop_info(struct vdec_hevc_slice_inst *inst, + struct v4l2_rect *cr) +{ + cr->left = 0; + cr->top = 0; + cr->width = inst->ctx->picinfo.pic_w; + cr->height = inst->ctx->picinfo.pic_h; + + mtk_vcodec_debug(inst, "l=%d, t=%d, w=%d, h=%d", + cr->left, cr->top, cr->width, cr->height); +} + +static int vdec_hevc_slice_setup_lat_buffer(struct vdec_hevc_slice_inst *inst, + struct mtk_vcodec_mem *bs, + struct vdec_lat_buf *lat_buf, + bool *res_chg) +{ + struct mtk_vcodec_mem *mem; + struct mtk_video_dec_buf *src_buf_info; + struct vdec_hevc_slice_share_info *share_info; + int i, err; + + inst->vsi->bs.dma_addr = (u64)bs->dma_addr; + inst->vsi->bs.size = bs->size; + + src_buf_info = container_of(bs, struct mtk_video_dec_buf, bs_buffer); + lat_buf->src_buf_req = src_buf_info->m2m_buf.vb.vb2_buf.req_obj.req; + v4l2_m2m_buf_copy_metadata(&src_buf_info->m2m_buf.vb, &lat_buf->ts_info, true); + + *res_chg = inst->resolution_changed; + if (inst->resolution_changed) { + mtk_vcodec_debug(inst, "- resolution changed -"); + if (inst->realloc_mv_buf) { + err = vdec_hevc_slice_alloc_mv_buf(inst, &inst->ctx->picinfo); + inst->realloc_mv_buf = false; + if (err) + return err; + } + inst->resolution_changed = false; + } + + for (i = 0; i < HEVC_MAX_MV_NUM; i++) { + mem = &inst->mv_buf[i]; + inst->vsi->mv_buf_dma[i].dma_addr = mem->dma_addr; + inst->vsi->mv_buf_dma[i].size = mem->size; + } + + inst->vsi->ube.dma_addr = lat_buf->ctx->msg_queue.wdma_addr.dma_addr; + inst->vsi->ube.size = lat_buf->ctx->msg_queue.wdma_addr.size; + + inst->vsi->err_map.dma_addr = lat_buf->wdma_err_addr.dma_addr; + inst->vsi->err_map.size = lat_buf->wdma_err_addr.size; + + inst->vsi->slice_bc.dma_addr = lat_buf->slice_bc_addr.dma_addr; + inst->vsi->slice_bc.size = lat_buf->slice_bc_addr.size; + + inst->vsi->trans.dma_addr_end = inst->ctx->msg_queue.wdma_rptr_addr; + inst->vsi->trans.dma_addr = inst->ctx->msg_queue.wdma_wptr_addr; + + share_info = lat_buf->private_data; + share_info->trans.dma_addr = inst->vsi->trans.dma_addr; + share_info->trans.dma_addr_end = inst->vsi->trans.dma_addr_end; + + mtk_vcodec_debug(inst, "lat: ube addr/size(0x%llx 0x%llx) err:0x%llx", + inst->vsi->ube.buf, + inst->vsi->ube.padding, + inst->vsi->err_map.buf); + + mtk_vcodec_debug(inst, "slice addr/size(0x%llx 0x%llx) trans start/end((0x%llx 0x%llx))", + inst->vsi->slice_bc.buf, + inst->vsi->slice_bc.padding, + inst->vsi->trans.buf, + inst->vsi->trans.padding); + + return 0; +} + +static int vdec_hevc_slice_setup_core_buffer(struct vdec_hevc_slice_inst *inst, + struct vdec_hevc_slice_share_info *share_info, + struct vdec_lat_buf *lat_buf) +{ + struct mtk_vcodec_mem *mem; + struct mtk_vcodec_ctx *ctx = inst->ctx; + struct vb2_v4l2_buffer *vb2_v4l2; + struct vdec_fb *fb; + u64 y_fb_dma, c_fb_dma; + int i; + + fb = ctx->dev->vdec_pdata->get_cap_buffer(ctx); + if (!fb) { + mtk_vcodec_err(inst, "fb buffer is NULL"); + return -EBUSY; + } + + y_fb_dma = (u64)fb->base_y.dma_addr; + if (ctx->q_data[MTK_Q_DATA_DST].fmt->num_planes == 1) + c_fb_dma = + y_fb_dma + inst->ctx->picinfo.buf_w * inst->ctx->picinfo.buf_h; + else + c_fb_dma = (u64)fb->base_c.dma_addr; + + mtk_vcodec_debug(inst, "[hevc-core] y/c addr = 0x%llx 0x%llx", y_fb_dma, + c_fb_dma); + + inst->vsi_core->fb.y.dma_addr = y_fb_dma; + inst->vsi_core->fb.y.size = ctx->picinfo.fb_sz[0]; + inst->vsi_core->fb.c.dma_addr = c_fb_dma; + inst->vsi_core->fb.y.size = ctx->picinfo.fb_sz[1]; + + inst->vsi_core->dec.vdec_fb_va = (unsigned long)fb; + + inst->vsi_core->ube.dma_addr = lat_buf->ctx->msg_queue.wdma_addr.dma_addr; + inst->vsi_core->ube.size = lat_buf->ctx->msg_queue.wdma_addr.size; + + inst->vsi_core->err_map.dma_addr = lat_buf->wdma_err_addr.dma_addr; + inst->vsi_core->err_map.size = lat_buf->wdma_err_addr.size; + + inst->vsi_core->slice_bc.dma_addr = lat_buf->slice_bc_addr.dma_addr; + inst->vsi_core->slice_bc.size = lat_buf->slice_bc_addr.size; + + inst->vsi_core->trans.dma_addr = share_info->trans.dma_addr; + inst->vsi_core->trans.dma_addr_end = share_info->trans.dma_addr_end; + + inst->vsi_core->wrap.dma_addr = inst->wrap_addr.dma_addr; + inst->vsi_core->wrap.size = inst->wrap_addr.size; + + for (i = 0; i < HEVC_MAX_MV_NUM; i++) { + mem = &inst->mv_buf[i]; + inst->vsi_core->mv_buf_dma[i].dma_addr = mem->dma_addr; + inst->vsi_core->mv_buf_dma[i].size = mem->size; + } + + vb2_v4l2 = v4l2_m2m_next_dst_buf(ctx->m2m_ctx); + v4l2_m2m_buf_copy_metadata(&lat_buf->ts_info, vb2_v4l2, true); + + return 0; +} + +static int vdec_hevc_slice_init(struct mtk_vcodec_ctx *ctx) +{ + struct vdec_hevc_slice_inst *inst; + int err, vsi_size; + + inst = kzalloc(sizeof(*inst), GFP_KERNEL); + if (!inst) + return -ENOMEM; + + inst->ctx = ctx; + + inst->vpu.id = SCP_IPI_VDEC_LAT; + inst->vpu.core_id = SCP_IPI_VDEC_CORE; + inst->vpu.ctx = ctx; + inst->vpu.codec_type = ctx->current_codec; + inst->vpu.capture_type = ctx->capture_fourcc; + + ctx->drv_handle = inst; + err = vpu_dec_init(&inst->vpu); + if (err) { + mtk_vcodec_err(inst, "vdec_hevc init err=%d", err); + goto error_free_inst; + } + + vsi_size = round_up(sizeof(struct vdec_hevc_slice_vsi), VCODEC_DEC_ALIGNED_64); + inst->vsi = inst->vpu.vsi; + inst->vsi_core = + (struct vdec_hevc_slice_vsi *)(((char *)inst->vpu.vsi) + vsi_size); + + inst->resolution_changed = true; + inst->realloc_mv_buf = true; + + inst->wrap_addr.size = VDEC_HEVC_WRAP_SZ; + err = mtk_vcodec_mem_alloc(ctx, &inst->wrap_addr); + if (err) + goto error_free_inst; + + mtk_vcodec_debug(inst, "lat struct size = %d,%d,%d,%d vsi: %d\n", + (int)sizeof(struct mtk_hevc_sps_param), + (int)sizeof(struct mtk_hevc_pps_param), + (int)sizeof(struct vdec_hevc_slice_lat_dec_param), + (int)sizeof(struct mtk_hevc_dpb_info), + vsi_size); + mtk_vcodec_debug(inst, "lat hevc instance >> %p, codec_type = 0x%x", + inst, inst->vpu.codec_type); + + return 0; +error_free_inst: + kfree(inst); + return err; +} + +static void vdec_hevc_slice_deinit(void *h_vdec) +{ + struct vdec_hevc_slice_inst *inst = h_vdec; + struct mtk_vcodec_mem *mem; + + mtk_vcodec_debug_enter(inst); + + vpu_dec_deinit(&inst->vpu); + vdec_hevc_slice_free_mv_buf(inst); + + mem = &inst->wrap_addr; + if (mem->va) + mtk_vcodec_mem_free(inst->ctx, mem); + + vdec_msg_queue_deinit(&inst->ctx->msg_queue, inst->ctx); + kfree(inst); +} + +static int vdec_hevc_slice_core_decode(struct vdec_lat_buf *lat_buf) +{ + int err, timeout; + struct mtk_vcodec_ctx *ctx = lat_buf->ctx; + struct vdec_hevc_slice_inst *inst = ctx->drv_handle; + struct vdec_hevc_slice_share_info *share_info = lat_buf->private_data; + struct vdec_vpu_inst *vpu = &inst->vpu; + + mtk_vcodec_debug(inst, "[hevc-core] vdec_hevc core decode"); + memcpy(&inst->vsi_core->hevc_slice_params, &share_info->hevc_slice_params, + sizeof(share_info->hevc_slice_params)); + + err = vdec_hevc_slice_setup_core_buffer(inst, share_info, lat_buf); + if (err) + goto vdec_dec_end; + + vdec_hevc_slice_fill_decode_reflist(inst, &inst->vsi_core->hevc_slice_params, + share_info); + err = vpu_dec_core(vpu); + if (err) { + mtk_vcodec_err(inst, "core decode err=%d", err); + goto vdec_dec_end; + } + + /* wait decoder done interrupt */ + timeout = mtk_vcodec_wait_for_done_ctx(inst->ctx, MTK_INST_IRQ_RECEIVED, + WAIT_INTR_TIMEOUT_MS, MTK_VDEC_CORE); + if (timeout) + mtk_vcodec_err(inst, "core decode timeout: pic_%d", + ctx->decoded_frame_cnt); + inst->vsi_core->dec.timeout = !!timeout; + + vpu_dec_core_end(vpu); + mtk_vcodec_debug(inst, "pic[%d] crc: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x", + ctx->decoded_frame_cnt, + inst->vsi_core->dec.crc[0], inst->vsi_core->dec.crc[1], + inst->vsi_core->dec.crc[2], inst->vsi_core->dec.crc[3], + inst->vsi_core->dec.crc[4], inst->vsi_core->dec.crc[5], + inst->vsi_core->dec.crc[6], inst->vsi_core->dec.crc[7]); + +vdec_dec_end: + vdec_msg_queue_update_ube_rptr(&lat_buf->ctx->msg_queue, share_info->trans.dma_addr_end); + ctx->dev->vdec_pdata->cap_to_disp(ctx, !!err, lat_buf->src_buf_req); + mtk_vcodec_debug(inst, "core decode done err=%d", err); + ctx->decoded_frame_cnt++; + return 0; +} + +static int vdec_hevc_slice_lat_decode(void *h_vdec, struct mtk_vcodec_mem *bs, + struct vdec_fb *fb, bool *res_chg) +{ + struct vdec_hevc_slice_inst *inst = h_vdec; + struct vdec_vpu_inst *vpu = &inst->vpu; + int err, timeout = 0; + unsigned int data[2]; + struct vdec_lat_buf *lat_buf; + struct vdec_hevc_slice_share_info *share_info; + + if (vdec_msg_queue_init(&inst->ctx->msg_queue, inst->ctx, + vdec_hevc_slice_core_decode, + sizeof(*share_info))) + return -ENOMEM; + + /* bs NULL means flush decoder */ + if (!bs) { + vdec_msg_queue_wait_lat_buf_full(&inst->ctx->msg_queue); + return vpu_dec_reset(vpu); + } + + lat_buf = vdec_msg_queue_dqbuf(&inst->ctx->msg_queue.lat_ctx); + if (!lat_buf) { + mtk_vcodec_debug(inst, "failed to get lat buffer"); + return -EAGAIN; + } + + share_info = lat_buf->private_data; + err = vdec_hevc_slice_fill_decode_parameters(inst, share_info); + if (err) + goto err_free_fb_out; + + err = vdec_hevc_slice_setup_lat_buffer(inst, bs, lat_buf, res_chg); + if (err) + goto err_free_fb_out; + + err = vpu_dec_start(vpu, data, 2); + if (err) { + mtk_vcodec_debug(inst, "lat decode err: %d", err); + goto err_free_fb_out; + } + + if (IS_VDEC_INNER_RACING(inst->ctx->dev->dec_capability)) { + memcpy(&share_info->hevc_slice_params, &inst->vsi->hevc_slice_params, + sizeof(share_info->hevc_slice_params)); + vdec_msg_queue_qbuf(&inst->ctx->msg_queue.core_ctx, lat_buf); + } + + /* wait decoder done interrupt */ + timeout = mtk_vcodec_wait_for_done_ctx(inst->ctx, MTK_INST_IRQ_RECEIVED, + WAIT_INTR_TIMEOUT_MS, MTK_VDEC_LAT0); + if (timeout) + mtk_vcodec_err(inst, "lat decode timeout: pic_%d", inst->slice_dec_num); + inst->vsi->dec.timeout = !!timeout; + + err = vpu_dec_end(vpu); + if (err == SLICE_HEADER_FULL || err == TRANS_BUFFER_FULL) { + if (!IS_VDEC_INNER_RACING(inst->ctx->dev->dec_capability)) + vdec_msg_queue_qbuf(&inst->ctx->msg_queue.lat_ctx, lat_buf); + inst->slice_dec_num++; + mtk_vcodec_err(inst, "lat dec fail: pic_%d err:%d", inst->slice_dec_num, err); + return -EINVAL; + } + + share_info->trans.dma_addr_end = inst->ctx->msg_queue.wdma_addr.dma_addr + + inst->vsi->dec.wdma_end_addr_offset; + vdec_msg_queue_update_ube_wptr(&lat_buf->ctx->msg_queue, share_info->trans.dma_addr_end); + + if (!IS_VDEC_INNER_RACING(inst->ctx->dev->dec_capability)) { + memcpy(&share_info->hevc_slice_params, &inst->vsi->hevc_slice_params, + sizeof(share_info->hevc_slice_params)); + vdec_msg_queue_qbuf(&inst->ctx->msg_queue.core_ctx, lat_buf); + } + mtk_vcodec_debug(inst, "dec num: %d lat crc: 0x%x 0x%x 0x%x", inst->slice_dec_num, + inst->vsi->dec.crc[0], inst->vsi->dec.crc[1], inst->vsi->dec.crc[2]); + + inst->slice_dec_num++; + return 0; +err_free_fb_out: + vdec_msg_queue_qbuf(&inst->ctx->msg_queue.lat_ctx, lat_buf); + mtk_vcodec_err(inst, "slice dec number: %d err: %d", inst->slice_dec_num, err); + return err; +} + +static int vdec_hevc_slice_decode(void *h_vdec, struct mtk_vcodec_mem *bs, + struct vdec_fb *unused, bool *res_chg) +{ + struct vdec_hevc_slice_inst *inst = h_vdec; + + if (!h_vdec || inst->ctx->dev->vdec_pdata->hw_arch == MTK_VDEC_PURE_SINGLE_CORE) + return -EINVAL; + + return vdec_hevc_slice_lat_decode(h_vdec, bs, unused, res_chg); +} + +static int vdec_hevc_slice_get_param(void *h_vdec, enum vdec_get_param_type type, + void *out) +{ + struct vdec_hevc_slice_inst *inst = h_vdec; + + switch (type) { + case GET_PARAM_PIC_INFO: + vdec_hevc_slice_get_pic_info(inst); + break; + case GET_PARAM_DPB_SIZE: + *(unsigned int *)out = 6; + break; + case GET_PARAM_CROP_INFO: + vdec_hevc_slice_get_crop_info(inst, out); + break; + default: + mtk_vcodec_err(inst, "invalid get parameter type=%d", type); + return -EINVAL; + } + return 0; +} + +const struct vdec_common_if vdec_hevc_slice_multi_if = { + .init = vdec_hevc_slice_init, + .decode = vdec_hevc_slice_decode, + .get_param = vdec_hevc_slice_get_param, + .deinit = vdec_hevc_slice_deinit, +}; diff --git a/drivers/media/platform/mediatek/vcodec/vdec/vdec_vp9_req_lat_if.c b/drivers/media/platform/mediatek/vcodec/vdec/vdec_vp9_req_lat_if.c index cf16cf2807f0728ba46cdaa943a75715f194cbee..c2f90848f4984e5534b56bc0cc564974842418de 100644 --- a/drivers/media/platform/mediatek/vcodec/vdec/vdec_vp9_req_lat_if.c +++ b/drivers/media/platform/mediatek/vcodec/vdec/vdec_vp9_req_lat_if.c @@ -2069,7 +2069,7 @@ static int vdec_vp9_slice_lat_decode(void *h_vdec, struct mtk_vcodec_mem *bs, lat_buf = vdec_msg_queue_dqbuf(&instance->ctx->msg_queue.lat_ctx); if (!lat_buf) { - mtk_vcodec_err(instance, "Failed to get VP9 lat buf\n"); + mtk_vcodec_debug(instance, "Failed to get VP9 lat buf\n"); return -EAGAIN; } pfc = (struct vdec_vp9_slice_pfc *)lat_buf->private_data; @@ -2119,7 +2119,7 @@ static int vdec_vp9_slice_lat_decode(void *h_vdec, struct mtk_vcodec_mem *bs, vdec_msg_queue_update_ube_wptr(&ctx->msg_queue, vsi->trans.dma_addr_end + ctx->msg_queue.wdma_addr.dma_addr); - vdec_msg_queue_qbuf(&ctx->dev->msg_queue_core_ctx, lat_buf); + vdec_msg_queue_qbuf(&ctx->msg_queue.core_ctx, lat_buf); return 0; err_free_fb_out: diff --git a/drivers/media/platform/mediatek/vcodec/vdec_drv_if.c b/drivers/media/platform/mediatek/vcodec/vdec_drv_if.c index f3807f03d8806441b3eeb3309d0aa2851d5e4a6e..06d393174cc26fe76460624acf0b84c3b944641c 100644 --- a/drivers/media/platform/mediatek/vcodec/vdec_drv_if.c +++ b/drivers/media/platform/mediatek/vcodec/vdec_drv_if.c @@ -49,6 +49,14 @@ int vdec_if_init(struct mtk_vcodec_ctx *ctx, unsigned int fourcc) ctx->dec_if = &vdec_vp9_slice_lat_if; ctx->hw_id = IS_VDEC_LAT_ARCH(hw_arch) ? MTK_VDEC_LAT0 : MTK_VDEC_CORE; break; + case V4L2_PIX_FMT_HEVC_SLICE: + ctx->dec_if = &vdec_hevc_slice_multi_if; + ctx->hw_id = MTK_VDEC_LAT0; + break; + case V4L2_PIX_FMT_AV1_FRAME: + ctx->dec_if = &vdec_av1_slice_lat_if; + ctx->hw_id = MTK_VDEC_LAT0; + break; default: return -EINVAL; } diff --git a/drivers/media/platform/mediatek/vcodec/vdec_drv_if.h b/drivers/media/platform/mediatek/vcodec/vdec_drv_if.h index 076306ff2dd492c78b67a497dde51c1e58d7ac13..a8da6a59a6a5b68b4ad5cb0396ffc2efada89254 100644 --- a/drivers/media/platform/mediatek/vcodec/vdec_drv_if.h +++ b/drivers/media/platform/mediatek/vcodec/vdec_drv_if.h @@ -61,6 +61,8 @@ extern const struct vdec_common_if vdec_vp8_if; extern const struct vdec_common_if vdec_vp8_slice_if; extern const struct vdec_common_if vdec_vp9_if; extern const struct vdec_common_if vdec_vp9_slice_lat_if; +extern const struct vdec_common_if vdec_hevc_slice_multi_if; +extern const struct vdec_common_if vdec_av1_slice_lat_if; /** * vdec_if_init() - initialize decode driver diff --git a/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.c b/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.c index f3073d1e7f420001f305ce6d94d6d3549e017858..f555341ae7087ad8191fc155c0a0fa4adc1c93ec 100644 --- a/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.c +++ b/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.c @@ -20,6 +20,9 @@ /* the size used to store avc error information */ #define VDEC_ERR_MAP_SZ_AVC (17 * SZ_1K) +#define VDEC_RD_MV_BUFFER_SZ (((SZ_4K * 2304 >> 4) + SZ_1K) << 1) +#define VDEC_LAT_TILE_SZ (64 * V4L2_AV1_MAX_TILE_COUNT) + /* core will read the trans buffer which decoded by lat to decode again. * The trans buffer size of FHD and 4K bitstreams are different. */ @@ -71,7 +74,6 @@ static void vdec_msg_queue_dec(struct vdec_msg_queue *msg_queue, int hardware_in int vdec_msg_queue_qbuf(struct vdec_msg_queue_ctx *msg_ctx, struct vdec_lat_buf *buf) { struct list_head *head; - int status; head = vdec_get_buf_list(msg_ctx->hardware_index, buf); if (!head) { @@ -87,12 +89,9 @@ int vdec_msg_queue_qbuf(struct vdec_msg_queue_ctx *msg_ctx, struct vdec_lat_buf if (msg_ctx->hardware_index != MTK_VDEC_CORE) { wake_up_all(&msg_ctx->ready_to_use); } else { - if (buf->ctx->msg_queue.core_work_cnt < - atomic_read(&buf->ctx->msg_queue.core_list_cnt)) { - status = queue_work(buf->ctx->dev->core_workqueue, - &buf->ctx->msg_queue.core_work); - if (status) - buf->ctx->msg_queue.core_work_cnt++; + if (!(buf->ctx->msg_queue.status & CONTEXT_LIST_QUEUED)) { + queue_work(buf->ctx->dev->core_workqueue, &buf->ctx->msg_queue.core_work); + buf->ctx->msg_queue.status |= CONTEXT_LIST_QUEUED; } } @@ -181,49 +180,23 @@ void vdec_msg_queue_update_ube_wptr(struct vdec_msg_queue *msg_queue, uint64_t u bool vdec_msg_queue_wait_lat_buf_full(struct vdec_msg_queue *msg_queue) { - struct vdec_lat_buf *buf, *tmp; - struct list_head *list_core[3]; - struct vdec_msg_queue_ctx *core_ctx; - int ret, i, in_core_count = 0, count = 0; - long timeout_jiff; - - core_ctx = &msg_queue->ctx->dev->msg_queue_core_ctx; - spin_lock(&core_ctx->ready_lock); - list_for_each_entry_safe(buf, tmp, &core_ctx->ready_queue, core_list) { - if (buf && buf->ctx == msg_queue->ctx) { - list_core[in_core_count++] = &buf->core_list; - list_del(&buf->core_list); - } - } - - for (i = 0; i < in_core_count; i++) { - list_add(list_core[in_core_count - (1 + i)], &core_ctx->ready_queue); - queue_work(msg_queue->ctx->dev->core_workqueue, &msg_queue->core_work); - } - spin_unlock(&core_ctx->ready_lock); - - timeout_jiff = msecs_to_jiffies(1000 * (NUM_BUFFER_COUNT + 2)); - ret = wait_event_timeout(msg_queue->ctx->msg_queue.core_dec_done, - msg_queue->lat_ctx.ready_num == NUM_BUFFER_COUNT, - timeout_jiff); - if (ret) { - mtk_v4l2_debug(3, "success to get lat buf: %d", - msg_queue->lat_ctx.ready_num); + if (atomic_read(&msg_queue->lat_list_cnt) == NUM_BUFFER_COUNT) { + mtk_v4l2_debug(3, "wait buf full: list(%d %d) ready_num:%d status:%d", + atomic_read(&msg_queue->lat_list_cnt), + atomic_read(&msg_queue->core_list_cnt), + msg_queue->lat_ctx.ready_num, + msg_queue->status); return true; } - spin_lock(&core_ctx->ready_lock); - list_for_each_entry_safe(buf, tmp, &core_ctx->ready_queue, core_list) { - if (buf && buf->ctx == msg_queue->ctx) { - count++; - list_del(&buf->core_list); - } - } - spin_unlock(&core_ctx->ready_lock); + msg_queue->flush_done = false; + vdec_msg_queue_qbuf(&msg_queue->core_ctx, &msg_queue->empty_lat_buf); + wait_event(msg_queue->core_dec_done, msg_queue->flush_done); - mtk_v4l2_err("failed with lat buf isn't full: list(%d %d) count:%d", - atomic_read(&msg_queue->lat_list_cnt), - atomic_read(&msg_queue->core_list_cnt), count); + mtk_v4l2_debug(3, "flush done => ready_num:%d status:%d list(%d %d)", + msg_queue->lat_ctx.ready_num, msg_queue->status, + atomic_read(&msg_queue->lat_list_cnt), + atomic_read(&msg_queue->core_list_cnt)); return false; } @@ -249,8 +222,18 @@ void vdec_msg_queue_deinit(struct vdec_msg_queue *msg_queue, if (mem->va) mtk_vcodec_mem_free(ctx, mem); + mem = &lat_buf->rd_mv_addr; + if (mem->va) + mtk_vcodec_mem_free(ctx, mem); + + mem = &lat_buf->tile_addr; + if (mem->va) + mtk_vcodec_mem_free(ctx, mem); + kfree(lat_buf->private_data); } + + cancel_work_sync(&msg_queue->core_work); } static void vdec_msg_queue_core_work(struct work_struct *work) @@ -261,12 +244,23 @@ static void vdec_msg_queue_core_work(struct work_struct *work) container_of(msg_queue, struct mtk_vcodec_ctx, msg_queue); struct mtk_vcodec_dev *dev = ctx->dev; struct vdec_lat_buf *lat_buf; - int status; - lat_buf = vdec_msg_queue_dqbuf(&dev->msg_queue_core_ctx); + spin_lock(&msg_queue->core_ctx.ready_lock); + ctx->msg_queue.status &= ~CONTEXT_LIST_QUEUED; + spin_unlock(&msg_queue->core_ctx.ready_lock); + + lat_buf = vdec_msg_queue_dqbuf(&msg_queue->core_ctx); if (!lat_buf) return; + if (lat_buf->is_last_frame) { + ctx->msg_queue.status = CONTEXT_LIST_DEC_DONE; + msg_queue->flush_done = true; + wake_up(&ctx->msg_queue.core_dec_done); + + return; + } + ctx = lat_buf->ctx; mtk_vcodec_dec_enable_hardware(ctx, MTK_VDEC_CORE); mtk_vcodec_set_curr_ctx(dev, ctx, MTK_VDEC_CORE); @@ -277,18 +271,13 @@ static void vdec_msg_queue_core_work(struct work_struct *work) mtk_vcodec_dec_disable_hardware(ctx, MTK_VDEC_CORE); vdec_msg_queue_qbuf(&ctx->msg_queue.lat_ctx, lat_buf); - wake_up_all(&ctx->msg_queue.core_dec_done); - spin_lock(&dev->msg_queue_core_ctx.ready_lock); - lat_buf->ctx->msg_queue.core_work_cnt--; - - if (lat_buf->ctx->msg_queue.core_work_cnt < - atomic_read(&lat_buf->ctx->msg_queue.core_list_cnt)) { - status = queue_work(lat_buf->ctx->dev->core_workqueue, - &lat_buf->ctx->msg_queue.core_work); - if (status) - lat_buf->ctx->msg_queue.core_work_cnt++; + if (!(ctx->msg_queue.status & CONTEXT_LIST_QUEUED) && + atomic_read(&msg_queue->core_list_cnt)) { + spin_lock(&msg_queue->core_ctx.ready_lock); + ctx->msg_queue.status |= CONTEXT_LIST_QUEUED; + spin_unlock(&msg_queue->core_ctx.ready_lock); + queue_work(ctx->dev->core_workqueue, &msg_queue->core_work); } - spin_unlock(&dev->msg_queue_core_ctx.ready_lock); } int vdec_msg_queue_init(struct vdec_msg_queue *msg_queue, @@ -302,14 +291,14 @@ int vdec_msg_queue_init(struct vdec_msg_queue *msg_queue, if (msg_queue->wdma_addr.size) return 0; - msg_queue->ctx = ctx; - msg_queue->core_work_cnt = 0; vdec_msg_queue_init_ctx(&msg_queue->lat_ctx, MTK_VDEC_LAT0); + vdec_msg_queue_init_ctx(&msg_queue->core_ctx, MTK_VDEC_CORE); INIT_WORK(&msg_queue->core_work, vdec_msg_queue_core_work); atomic_set(&msg_queue->lat_list_cnt, 0); atomic_set(&msg_queue->core_list_cnt, 0); init_waitqueue_head(&msg_queue->core_dec_done); + msg_queue->status = CONTEXT_LIST_EMPTY; msg_queue->wdma_addr.size = vde_msg_queue_get_trans_size(ctx->picinfo.buf_w, @@ -322,6 +311,10 @@ int vdec_msg_queue_init(struct vdec_msg_queue *msg_queue, msg_queue->wdma_rptr_addr = msg_queue->wdma_addr.dma_addr; msg_queue->wdma_wptr_addr = msg_queue->wdma_addr.dma_addr; + msg_queue->empty_lat_buf.ctx = ctx; + msg_queue->empty_lat_buf.core_decode = NULL; + msg_queue->empty_lat_buf.is_last_frame = true; + for (i = 0; i < NUM_BUFFER_COUNT; i++) { lat_buf = &msg_queue->lat_buf[i]; @@ -339,6 +332,22 @@ int vdec_msg_queue_init(struct vdec_msg_queue *msg_queue, goto mem_alloc_err; } + if (ctx->current_codec == V4L2_PIX_FMT_AV1_FRAME) { + lat_buf->rd_mv_addr.size = VDEC_RD_MV_BUFFER_SZ; + err = mtk_vcodec_mem_alloc(ctx, &lat_buf->rd_mv_addr); + if (err) { + mtk_v4l2_err("failed to allocate rd_mv_addr buf[%d]", i); + return -ENOMEM; + } + + lat_buf->tile_addr.size = VDEC_LAT_TILE_SZ; + err = mtk_vcodec_mem_alloc(ctx, &lat_buf->tile_addr); + if (err) { + mtk_v4l2_err("failed to allocate tile_addr buf[%d]", i); + return -ENOMEM; + } + } + lat_buf->private_data = kzalloc(private_size, GFP_KERNEL); if (!lat_buf->private_data) { err = -ENOMEM; @@ -347,6 +356,7 @@ int vdec_msg_queue_init(struct vdec_msg_queue *msg_queue, lat_buf->ctx = ctx; lat_buf->core_decode = core_decode; + lat_buf->is_last_frame = false; err = vdec_msg_queue_qbuf(&msg_queue->lat_ctx, lat_buf); if (err) { mtk_v4l2_err("failed to qbuf buf[%d]", i); diff --git a/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.h b/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.h index a5d44bc97c16b9b6f527f47f447f78b09bbb0bbd..2a745e902ad1264828326f34a743e052da207ce9 100644 --- a/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.h +++ b/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.h @@ -21,6 +21,18 @@ struct mtk_vcodec_ctx; struct mtk_vcodec_dev; typedef int (*core_decode_cb_t)(struct vdec_lat_buf *lat_buf); +/** + * enum core_ctx_status - Context decode status for core hardwre. + * @CONTEXT_LIST_EMPTY: No buffer queued on core hardware(must always be 0) + * @CONTEXT_LIST_QUEUED: Buffer queued to core work list + * @CONTEXT_LIST_DEC_DONE: context decode done + */ +enum core_ctx_status { + CONTEXT_LIST_EMPTY = 0, + CONTEXT_LIST_QUEUED, + CONTEXT_LIST_DEC_DONE, +}; + /** * struct vdec_msg_queue_ctx - represents a queue for buffers ready to be processed * @ready_to_use: ready used queue used to signalize when get a job queue @@ -42,6 +54,8 @@ struct vdec_msg_queue_ctx { * struct vdec_lat_buf - lat buffer message used to store lat info for core decode * @wdma_err_addr: wdma error address used for lat hardware * @slice_bc_addr: slice bc address used for lat hardware + * @rd_mv_addr: mv addr for av1 lat hardware output, core hardware input + * @tile_addr: tile buffer for av1 core input * @ts_info: need to set timestamp from output to capture * @src_buf_req: output buffer media request object * @@ -50,10 +64,14 @@ struct vdec_msg_queue_ctx { * @core_decode: different codec use different decode callback function * @lat_list: add lat buffer to lat head list * @core_list: add lat buffer to core head list + * + * @is_last_frame: meaning this buffer is the last frame */ struct vdec_lat_buf { struct mtk_vcodec_mem wdma_err_addr; struct mtk_vcodec_mem slice_bc_addr; + struct mtk_vcodec_mem rd_mv_addr; + struct mtk_vcodec_mem tile_addr; struct vb2_v4l2_buffer ts_info; struct media_request *src_buf_req; @@ -62,6 +80,8 @@ struct vdec_lat_buf { core_decode_cb_t core_decode; struct list_head lat_list; struct list_head core_list; + + bool is_last_frame; }; /** @@ -72,12 +92,14 @@ struct vdec_lat_buf { * @wdma_wptr_addr: ube write point * @core_work: core hardware work * @lat_ctx: used to store lat buffer list - * @ctx: point to mtk_vcodec_ctx + * @core_ctx: used to store core buffer list * * @lat_list_cnt: used to record each instance lat list count * @core_list_cnt: used to record each instance core list count + * @flush_done: core flush done status + * @empty_lat_buf: the last lat buf used to flush decode * @core_dec_done: core work queue decode done event - * @core_work_cnt: the number of core work in work queue + * @status: current context decode status for core hardware */ struct vdec_msg_queue { struct vdec_lat_buf lat_buf[NUM_BUFFER_COUNT]; @@ -88,12 +110,14 @@ struct vdec_msg_queue { struct work_struct core_work; struct vdec_msg_queue_ctx lat_ctx; - struct mtk_vcodec_ctx *ctx; + struct vdec_msg_queue_ctx core_ctx; atomic_t lat_list_cnt; atomic_t core_list_cnt; + bool flush_done; + struct vdec_lat_buf empty_lat_buf; wait_queue_head_t core_dec_done; - int core_work_cnt; + int status; }; /** diff --git a/drivers/media/platform/mediatek/vpu/mtk_vpu.c b/drivers/media/platform/mediatek/vpu/mtk_vpu.c index 5e2bc286f168ea030c7a266dc5cca2450718bc5e..4c8f5296d120eecaa24d570896c06910a66fb10e 100644 --- a/drivers/media/platform/mediatek/vpu/mtk_vpu.c +++ b/drivers/media/platform/mediatek/vpu/mtk_vpu.c @@ -562,15 +562,17 @@ static int load_requested_vpu(struct mtk_vpu *vpu, int vpu_load_firmware(struct platform_device *pdev) { struct mtk_vpu *vpu; - struct device *dev = &pdev->dev; + struct device *dev; struct vpu_run *run; int ret; if (!pdev) { - dev_err(dev, "VPU platform device is invalid\n"); + pr_err("VPU platform device is invalid\n"); return -EINVAL; } + dev = &pdev->dev; + vpu = platform_get_drvdata(pdev); run = &vpu->run; @@ -1016,6 +1018,7 @@ static int mtk_vpu_resume(struct device *dev) clk_prepare(vpu->clk); ret = vpu_clock_enable(vpu); if (ret) { + clk_unprepare(vpu->clk); dev_err(dev, "failed to enable vpu clock\n"); return ret; } diff --git a/drivers/media/platform/nxp/imx7-media-csi.c b/drivers/media/platform/nxp/imx7-media-csi.c index b701e823436a88ae0f5e1ed904eec5e278f3d96d..0bd2613b9320f41b696ae91cd970dc2cb8d668a1 100644 --- a/drivers/media/platform/nxp/imx7-media-csi.c +++ b/drivers/media/platform/nxp/imx7-media-csi.c @@ -1014,39 +1014,6 @@ static int imx7_csi_enum_mbus_formats(u32 *code, u32 index) return -EINVAL; } -static int imx7_csi_mbus_fmt_to_pix_fmt(struct v4l2_pix_format *pix, - const struct v4l2_mbus_framefmt *mbus, - const struct imx7_csi_pixfmt *cc) -{ - u32 width; - u32 stride; - - if (!cc) { - cc = imx7_csi_find_mbus_format(mbus->code); - if (!cc) - return -EINVAL; - } - - /* Round up width for minimum burst size */ - width = round_up(mbus->width, 8); - - /* Round up stride for IDMAC line start address alignment */ - stride = round_up((width * cc->bpp) >> 3, 8); - - pix->width = width; - pix->height = mbus->height; - pix->pixelformat = cc->fourcc; - pix->colorspace = mbus->colorspace; - pix->xfer_func = mbus->xfer_func; - pix->ycbcr_enc = mbus->ycbcr_enc; - pix->quantization = mbus->quantization; - pix->field = mbus->field; - pix->bytesperline = stride; - pix->sizeimage = stride * pix->height; - - return 0; -} - /* ----------------------------------------------------------------------------- * Video Capture Device - IOCTLs */ @@ -1145,8 +1112,13 @@ static const struct imx7_csi_pixfmt * __imx7_csi_video_try_fmt(struct v4l2_pix_format *pixfmt, struct v4l2_rect *compose) { - struct v4l2_mbus_framefmt fmt_src; const struct imx7_csi_pixfmt *cc; + u32 walign; + + if (compose) { + compose->width = pixfmt->width; + compose->height = pixfmt->height; + } /* * Find the pixel format, default to the first supported format if not @@ -1158,27 +1130,19 @@ __imx7_csi_video_try_fmt(struct v4l2_pix_format *pixfmt, cc = imx7_csi_find_pixel_format(pixfmt->pixelformat); } - /* Allow IDMAC interweave but enforce field order from source. */ - if (V4L2_FIELD_IS_INTERLACED(pixfmt->field)) { - switch (pixfmt->field) { - case V4L2_FIELD_SEQ_TB: - pixfmt->field = V4L2_FIELD_INTERLACED_TB; - break; - case V4L2_FIELD_SEQ_BT: - pixfmt->field = V4L2_FIELD_INTERLACED_BT; - break; - default: - break; - } - } + /* + * The width alignment is 8 bytes as indicated by the + * CSI_IMAG_PARA.IMAGE_WIDTH documentation. Convert it to pixels. + * + * TODO: Implement configurable stride support. + */ + walign = 8 * 8 / cc->bpp; + v4l_bound_align_image(&pixfmt->width, 1, 0xffff, walign, + &pixfmt->height, 1, 0xffff, 1, 0); - v4l2_fill_mbus_format(&fmt_src, pixfmt, 0); - imx7_csi_mbus_fmt_to_pix_fmt(pixfmt, &fmt_src, cc); - - if (compose) { - compose->width = fmt_src.width; - compose->height = fmt_src.height; - } + pixfmt->bytesperline = pixfmt->width * cc->bpp / 8; + pixfmt->sizeimage = pixfmt->bytesperline * pixfmt->height; + pixfmt->field = V4L2_FIELD_NONE; return cc; } @@ -1606,22 +1570,14 @@ static struct imx7_csi_vb2_buffer *imx7_csi_video_next_buf(struct imx7_csi *csi) return buf; } -static int imx7_csi_video_init_format(struct imx7_csi *csi) +static void imx7_csi_video_init_format(struct imx7_csi *csi) { - struct v4l2_mbus_framefmt format = { }; - - format.code = IMX7_CSI_DEF_MBUS_CODE; - format.width = IMX7_CSI_DEF_PIX_WIDTH; - format.height = IMX7_CSI_DEF_PIX_HEIGHT; - format.field = V4L2_FIELD_NONE; - - imx7_csi_mbus_fmt_to_pix_fmt(&csi->vdev_fmt, &format, NULL); - csi->vdev_compose.width = format.width; - csi->vdev_compose.height = format.height; + struct v4l2_pix_format *pixfmt = &csi->vdev_fmt; - csi->vdev_cc = imx7_csi_find_pixel_format(csi->vdev_fmt.pixelformat); + pixfmt->width = IMX7_CSI_DEF_PIX_WIDTH; + pixfmt->height = IMX7_CSI_DEF_PIX_HEIGHT; - return 0; + csi->vdev_cc = __imx7_csi_video_try_fmt(pixfmt, &csi->vdev_compose); } static int imx7_csi_video_register(struct imx7_csi *csi) @@ -1634,9 +1590,7 @@ static int imx7_csi_video_register(struct imx7_csi *csi) vdev->v4l2_dev = v4l2_dev; /* Initialize the default format and compose rectangle. */ - ret = imx7_csi_video_init_format(csi); - if (ret < 0) - return ret; + imx7_csi_video_init_format(csi); /* Register the video device. */ ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1); diff --git a/drivers/media/platform/nxp/imx8-isi/imx8-isi-crossbar.c b/drivers/media/platform/nxp/imx8-isi/imx8-isi-crossbar.c index b5ffde46f31b61fd9675e022a60fa27ecef92f51..f7447b2f4d7779016acf543055be08452373dbf5 100644 --- a/drivers/media/platform/nxp/imx8-isi/imx8-isi-crossbar.c +++ b/drivers/media/platform/nxp/imx8-isi/imx8-isi-crossbar.c @@ -223,7 +223,7 @@ static int mxc_isi_crossbar_init_cfg(struct v4l2_subdev *sd, route->sink_pad = i; route->source_pad = i + xbar->num_sinks; route->flags = V4L2_SUBDEV_ROUTE_FL_ACTIVE; - }; + } routing.num_routes = xbar->num_sources; routing.routes = routes; diff --git a/drivers/media/platform/qcom/camss/camss-vfe.c b/drivers/media/platform/qcom/camss/camss-vfe.c index e0832f3f4f25c046049e51b9fdfde932ad30d0db..06c95568e5af4ee3eacdcb938719c02b9a7f1f13 100644 --- a/drivers/media/platform/qcom/camss/camss-vfe.c +++ b/drivers/media/platform/qcom/camss/camss-vfe.c @@ -1541,7 +1541,11 @@ int msm_vfe_register_entities(struct vfe_device *vfe, } video_out->ops = &vfe->video_ops; - video_out->bpl_alignment = 8; + if (vfe->camss->version == CAMSS_845 || + vfe->camss->version == CAMSS_8250) + video_out->bpl_alignment = 16; + else + video_out->bpl_alignment = 8; video_out->line_based = 0; if (i == VFE_LINE_PIX) { video_out->bpl_alignment = 16; diff --git a/drivers/media/platform/qcom/venus/core.h b/drivers/media/platform/qcom/venus/core.h index 4f81669986ba7f3ff0a6a09079f619311629ae20..320bde0f83cb6e1f5e000427dcf1fb2491459e81 100644 --- a/drivers/media/platform/qcom/venus/core.h +++ b/drivers/media/platform/qcom/venus/core.h @@ -83,6 +83,23 @@ struct venus_resources { const char *fwname; }; +enum venus_fmt { + VENUS_FMT_NV12 = 0, + VENUS_FMT_QC08C = 1, + VENUS_FMT_QC10C = 2, + VENUS_FMT_P010 = 3, + VENUS_FMT_H264 = 4, + VENUS_FMT_VP8 = 5, + VENUS_FMT_VP9 = 6, + VENUS_FMT_HEVC = 7, + VENUS_FMT_VC1_ANNEX_G = 8, + VENUS_FMT_VC1_ANNEX_L = 9, + VENUS_FMT_MPEG4 = 10, + VENUS_FMT_MPEG2 = 11, + VENUS_FMT_H263 = 12, + VENUS_FMT_XVID = 13, +}; + struct venus_format { u32 pixfmt; unsigned int num_planes; @@ -201,6 +218,11 @@ struct venus_core { unsigned int core0_usage_count; unsigned int core1_usage_count; struct dentry *root; + struct venus_img_version { + u32 major; + u32 minor; + u32 rev; + } venus_ver; }; struct vdec_controls { @@ -389,6 +411,7 @@ enum venus_inst_modes { * @sequence_out: a sequence counter for output queue * @m2m_dev: a reference to m2m device structure * @m2m_ctx: a reference to m2m context structure + * @ctx_q_lock: a lock to serialize video device ioctl calls * @state: current state of the instance * @done: a completion for sync HFI operation * @error: an error returned during last HFI sync operation @@ -460,6 +483,7 @@ struct venus_inst { u32 sequence_out; struct v4l2_m2m_dev *m2m_dev; struct v4l2_m2m_ctx *m2m_ctx; + struct mutex ctx_q_lock; unsigned int state; struct completion done; unsigned int error; @@ -508,4 +532,19 @@ venus_caps_by_codec(struct venus_core *core, u32 codec, u32 domain) return NULL; } +static inline bool +is_fw_rev_or_newer(struct venus_core *core, u32 vmajor, u32 vminor, u32 vrev) +{ + return ((core)->venus_ver.major == vmajor && + (core)->venus_ver.minor == vminor && + (core)->venus_ver.rev >= vrev); +} + +static inline bool +is_fw_rev_or_older(struct venus_core *core, u32 vmajor, u32 vminor, u32 vrev) +{ + return ((core)->venus_ver.major == vmajor && + (core)->venus_ver.minor == vminor && + (core)->venus_ver.rev <= vrev); +} #endif diff --git a/drivers/media/platform/qcom/venus/helpers.c b/drivers/media/platform/qcom/venus/helpers.c index a2ceab7f9ddbfc8f076b75d6cdaa2da790b0797b..1822e85ab6bf829990504c196555c26e482f02fd 100644 --- a/drivers/media/platform/qcom/venus/helpers.c +++ b/drivers/media/platform/qcom/venus/helpers.c @@ -502,7 +502,6 @@ session_process_buf(struct venus_inst *inst, struct vb2_v4l2_buffer *vbuf) struct vb2_buffer *vb = &vbuf->vb2_buf; unsigned int type = vb->type; struct hfi_frame_data fdata; - int ret; memset(&fdata, 0, sizeof(fdata)); fdata.alloc_len = buf->size; @@ -533,11 +532,7 @@ session_process_buf(struct venus_inst *inst, struct vb2_v4l2_buffer *vbuf) fdata.offset = 0; } - ret = hfi_session_process_buf(inst, &fdata); - if (ret) - return ret; - - return 0; + return hfi_session_process_buf(inst, &fdata); } static bool is_dynamic_bufmode(struct venus_inst *inst) @@ -612,6 +607,8 @@ static u32 to_hfi_raw_fmt(u32 v4l2_fmt) return HFI_COLOR_FORMAT_NV12_UBWC; case V4L2_PIX_FMT_QC10C: return HFI_COLOR_FORMAT_YUV420_TP10_UBWC; + case V4L2_PIX_FMT_P010: + return HFI_COLOR_FORMAT_P010; default: break; } @@ -639,12 +636,16 @@ static int platform_get_bufreq(struct venus_inst *inst, u32 buftype, if (is_dec) { params.width = inst->width; params.height = inst->height; + params.out_width = inst->out_width; + params.out_height = inst->out_height; params.codec = inst->fmt_out->pixfmt; params.hfi_color_fmt = to_hfi_raw_fmt(inst->fmt_cap->pixfmt); params.dec.max_mbs_per_frame = mbs_per_frame_max(inst); params.dec.buffer_size_limit = 0; params.dec.is_secondary_output = inst->opb_buftype == HFI_BUFFER_OUTPUT2; + if (params.dec.is_secondary_output) + params.hfi_dpb_color_fmt = inst->dpb_fmt; params.dec.is_interlaced = inst->pic_struct != HFI_INTERLACE_FRAME_PROGRESSIVE; } else { @@ -1036,8 +1037,8 @@ static u32 get_framesize_raw_yuv420_tp10_ubwc(u32 width, u32 height) u32 extradata = SZ_16K; u32 size; - y_stride = ALIGN(ALIGN(width, 192) * 4 / 3, 256); - uv_stride = ALIGN(ALIGN(width, 192) * 4 / 3, 256); + y_stride = ALIGN(width * 4 / 3, 256); + uv_stride = ALIGN(width * 4 / 3, 256); y_sclines = ALIGN(height, 16); uv_sclines = ALIGN((height + 1) >> 1, 16); @@ -1764,6 +1765,22 @@ int venus_helper_get_out_fmts(struct venus_inst *inst, u32 v4l2_fmt, if (!caps) return -EINVAL; + if (inst->bit_depth == VIDC_BITDEPTH_10 && inst->session_type == VIDC_SESSION_TYPE_DEC) { + found_ubwc = find_fmt_from_caps(caps, HFI_BUFFER_OUTPUT, + HFI_COLOR_FORMAT_YUV420_TP10_UBWC); + found = find_fmt_from_caps(caps, HFI_BUFFER_OUTPUT2, fmt); + if (found_ubwc && found) { + /* + * Hard-code DPB buffers to be 10bit UBWC + * until V4L2 is able to expose compressed/tiled + * formats to applications. + */ + *out_fmt = HFI_COLOR_FORMAT_YUV420_TP10_UBWC; + *out2_fmt = fmt; + return 0; + } + } + if (ubwc) { ubwc_fmt = fmt | HFI_COLOR_FORMAT_UBWC_BASE; found_ubwc = find_fmt_from_caps(caps, HFI_BUFFER_OUTPUT, diff --git a/drivers/media/platform/qcom/venus/hfi_cmds.c b/drivers/media/platform/qcom/venus/hfi_cmds.c index bc3f8ff058403ca3d7ac1df1bcf86b85faa88a74..7f0802a5518c35fe21c1f2f683d23f137d6432ac 100644 --- a/drivers/media/platform/qcom/venus/hfi_cmds.c +++ b/drivers/media/platform/qcom/venus/hfi_cmds.c @@ -83,7 +83,7 @@ int pkt_sys_set_resource(struct hfi_sys_set_resource_pkt *pkt, u32 id, u32 size, res->size = size; res->mem = addr; pkt->resource_type = HFI_RESOURCE_OCMEM; - pkt->hdr.size += sizeof(*res) - sizeof(u32); + pkt->hdr.size += sizeof(*res); break; } case VIDC_RESOURCE_NONE: @@ -200,8 +200,8 @@ int pkt_session_set_buffers(struct hfi_session_set_buffers_pkt *pkt, struct hfi_buffer_info *bi; pkt->extradata_size = bd->extradata_size; - pkt->shdr.hdr.size = sizeof(*pkt) - sizeof(u32) + - (bd->num_buffers * sizeof(*bi)); + pkt->shdr.hdr.size = sizeof(*pkt) + + bd->num_buffers * sizeof(*bi); bi = (struct hfi_buffer_info *)pkt->buffer_info; for (i = 0; i < pkt->num_buffers; i++) { bi->buffer_addr = bd->device_addr; @@ -209,8 +209,8 @@ int pkt_session_set_buffers(struct hfi_session_set_buffers_pkt *pkt, } } else { pkt->extradata_size = 0; - pkt->shdr.hdr.size = sizeof(*pkt) + - ((bd->num_buffers - 1) * sizeof(u32)); + pkt->shdr.hdr.size = struct_size(pkt, buffer_info, + bd->num_buffers); for (i = 0; i < pkt->num_buffers; i++) pkt->buffer_info[i] = bd->device_addr; } @@ -243,16 +243,16 @@ int pkt_session_unset_buffers(struct hfi_session_release_buffer_pkt *pkt, bi->extradata_addr = bd->extradata_addr; } pkt->shdr.hdr.size = - sizeof(struct hfi_session_set_buffers_pkt) - - sizeof(u32) + (bd->num_buffers * sizeof(*bi)); + sizeof(struct hfi_session_set_buffers_pkt) + + bd->num_buffers * sizeof(*bi); } else { for (i = 0; i < pkt->num_buffers; i++) pkt->buffer_info[i] = bd->device_addr; pkt->extradata_size = 0; pkt->shdr.hdr.size = - sizeof(struct hfi_session_set_buffers_pkt) + - ((bd->num_buffers - 1) * sizeof(u32)); + struct_size((struct hfi_session_set_buffers_pkt *)0, + buffer_info, bd->num_buffers); } pkt->response_req = bd->response_required; @@ -521,6 +521,7 @@ static int pkt_session_set_property_1x(struct hfi_session_set_property_pkt *pkt, pkt->shdr.hdr.size += sizeof(u32) + sizeof(*en); break; } + case HFI_PROPERTY_PARAM_VDEC_ENABLE_SUFFICIENT_SEQCHANGE_EVENT: case HFI_PROPERTY_CONFIG_VDEC_POST_LOOP_DEBLOCKER: { struct hfi_enable *in = pdata; struct hfi_enable *en = prop_data; diff --git a/drivers/media/platform/qcom/venus/hfi_cmds.h b/drivers/media/platform/qcom/venus/hfi_cmds.h index 99bc0b6db67c3f24d4fb9fa16a77adcc213ad917..dd9c5066442db1186e20885921053f9fc0783e89 100644 --- a/drivers/media/platform/qcom/venus/hfi_cmds.h +++ b/drivers/media/platform/qcom/venus/hfi_cmds.h @@ -56,7 +56,7 @@ struct hfi_sys_set_resource_pkt { struct hfi_pkt_hdr hdr; u32 resource_handle; u32 resource_type; - u32 resource_data[1]; + u32 resource_data[]; }; struct hfi_sys_release_resource_pkt { @@ -117,7 +117,7 @@ struct hfi_session_set_buffers_pkt { u32 extradata_size; u32 min_buffer_size; u32 num_buffers; - u32 buffer_info[1]; + u32 buffer_info[]; }; struct hfi_session_get_sequence_header_pkt { diff --git a/drivers/media/platform/qcom/venus/hfi_helper.h b/drivers/media/platform/qcom/venus/hfi_helper.h index 105792a680609a0ffe9f7c6ec6a9258da07355a4..0abbc50c586424d8bc381efb49fd03bdc8f83302 100644 --- a/drivers/media/platform/qcom/venus/hfi_helper.h +++ b/drivers/media/platform/qcom/venus/hfi_helper.h @@ -469,6 +469,8 @@ #define HFI_PROPERTY_PARAM_VDEC_PIXEL_BITDEPTH 0x1003007 #define HFI_PROPERTY_PARAM_VDEC_PIC_STRUCT 0x1003009 #define HFI_PROPERTY_PARAM_VDEC_COLOUR_SPACE 0x100300a +#define HFI_PROPERTY_PARAM_VDEC_ENABLE_SUFFICIENT_SEQCHANGE_EVENT \ + 0x100300b /* * HFI_PROPERTY_CONFIG_VDEC_COMMON_START diff --git a/drivers/media/platform/qcom/venus/hfi_msgs.c b/drivers/media/platform/qcom/venus/hfi_msgs.c index df96db3761a721da8b883e54115417b7caed94f9..3d5dadfa19009ee8dffbd49e93f6d2912314f600 100644 --- a/drivers/media/platform/qcom/venus/hfi_msgs.c +++ b/drivers/media/platform/qcom/venus/hfi_msgs.c @@ -233,7 +233,7 @@ static void hfi_sys_init_done(struct venus_core *core, struct venus_inst *inst, goto done; } - rem_bytes = pkt->hdr.size - sizeof(*pkt) + sizeof(u32); + rem_bytes = pkt->hdr.size - sizeof(*pkt); if (rem_bytes <= 0) { /* missing property data */ error = HFI_ERR_SYS_INSUFFICIENT_RESOURCES; @@ -248,13 +248,15 @@ static void hfi_sys_init_done(struct venus_core *core, struct venus_inst *inst, } static void -sys_get_prop_image_version(struct device *dev, +sys_get_prop_image_version(struct venus_core *core, struct hfi_msg_sys_property_info_pkt *pkt) { + struct device *dev = core->dev; u8 *smem_tbl_ptr; u8 *img_ver; int req_bytes; size_t smem_blk_sz; + int ret; req_bytes = pkt->hdr.size - sizeof(*pkt); @@ -263,8 +265,30 @@ sys_get_prop_image_version(struct device *dev, return; img_ver = pkt->data; + if (!img_ver) + return; + + ret = sscanf(img_ver, "14:video-firmware.%u.%u-%u", + &core->venus_ver.major, &core->venus_ver.minor, &core->venus_ver.rev); + if (ret) + goto done; + + ret = sscanf(img_ver, "14:VIDEO.VPU.%u.%u-%u", + &core->venus_ver.major, &core->venus_ver.minor, &core->venus_ver.rev); + if (ret) + goto done; + + ret = sscanf(img_ver, "14:VIDEO.VE.%u.%u-%u", + &core->venus_ver.major, &core->venus_ver.minor, &core->venus_ver.rev); + if (ret) + goto done; - dev_dbg(dev, VDBGL "F/W version: %s\n", img_ver); + dev_err(dev, VDBGL "error reading F/W version\n"); + return; + +done: + dev_dbg(dev, VDBGL "F/W version: %s, major %u, minor %u, revision %u\n", + img_ver, core->venus_ver.major, core->venus_ver.minor, core->venus_ver.rev); smem_tbl_ptr = qcom_smem_get(QCOM_SMEM_HOST_ANY, SMEM_IMG_VER_TBL, &smem_blk_sz); @@ -286,7 +310,7 @@ static void hfi_sys_property_info(struct venus_core *core, switch (pkt->property) { case HFI_PROPERTY_SYS_IMAGE_VERSION: - sys_get_prop_image_version(dev, pkt); + sys_get_prop_image_version(core, pkt); break; default: dev_dbg(dev, VDBGL "unknown property data\n"); @@ -434,7 +458,7 @@ static void hfi_session_init_done(struct venus_core *core, if (!IS_V1(core)) goto done; - rem_bytes = pkt->shdr.hdr.size - sizeof(*pkt) + sizeof(u32); + rem_bytes = pkt->shdr.hdr.size - sizeof(*pkt); if (rem_bytes <= 0) { error = HFI_ERR_SESSION_INSUFFICIENT_RESOURCES; goto done; diff --git a/drivers/media/platform/qcom/venus/hfi_msgs.h b/drivers/media/platform/qcom/venus/hfi_msgs.h index 510513697335bed3c98de10e71832f88c484c7ec..8c2e17b0d36f092071d9c8c72123ba3704c712fb 100644 --- a/drivers/media/platform/qcom/venus/hfi_msgs.h +++ b/drivers/media/platform/qcom/venus/hfi_msgs.h @@ -50,7 +50,7 @@ struct hfi_msg_event_notify_pkt { u32 event_id; u32 event_data1; u32 event_data2; - u32 ext_event_data[1]; + u32 ext_event_data[]; }; struct hfi_msg_event_release_buffer_ref_pkt { @@ -63,7 +63,7 @@ struct hfi_msg_sys_init_done_pkt { struct hfi_pkt_hdr hdr; u32 error_type; u32 num_properties; - u32 data[1]; + u32 data[]; }; struct hfi_msg_sys_pc_prep_done_pkt { @@ -81,7 +81,7 @@ struct hfi_msg_session_init_done_pkt { struct hfi_session_hdr_pkt shdr; u32 error_type; u32 num_properties; - u32 data[1]; + u32 data[]; }; struct hfi_msg_session_end_done_pkt { @@ -228,7 +228,7 @@ struct hfi_msg_session_parse_sequence_header_done_pkt { struct hfi_session_hdr_pkt shdr; u32 error_type; u32 num_properties; - u32 data[1]; + u32 data[]; }; struct hfi_msg_session_property_info_pkt { @@ -247,7 +247,7 @@ struct hfi_msg_session_release_buffers_done_pkt { struct hfi_session_hdr_pkt shdr; u32 error_type; u32 num_buffers; - u32 buffer_info[1]; + u32 buffer_info[]; }; struct hfi_msg_sys_debug_pkt { @@ -256,7 +256,7 @@ struct hfi_msg_sys_debug_pkt { u32 msg_size; u32 time_stamp_hi; u32 time_stamp_lo; - u8 msg_data[1]; + u8 msg_data[]; }; struct hfi_msg_sys_coverage_pkt { @@ -264,7 +264,7 @@ struct hfi_msg_sys_coverage_pkt { u32 msg_size; u32 time_stamp_hi; u32 time_stamp_lo; - u8 msg_data[1]; + u8 msg_data[]; }; struct venus_core; diff --git a/drivers/media/platform/qcom/venus/hfi_plat_bufs.h b/drivers/media/platform/qcom/venus/hfi_plat_bufs.h index 52a51a3b964a7e5349a529c775467524aa077ad4..25e607452096a143dec521d93616812c28e6f779 100644 --- a/drivers/media/platform/qcom/venus/hfi_plat_bufs.h +++ b/drivers/media/platform/qcom/venus/hfi_plat_bufs.h @@ -12,8 +12,11 @@ struct hfi_plat_buffers_params { u32 width; u32 height; + u32 out_width; + u32 out_height; u32 codec; u32 hfi_color_fmt; + u32 hfi_dpb_color_fmt; enum hfi_version version; u32 num_vpp_pipes; union { diff --git a/drivers/media/platform/qcom/venus/hfi_plat_bufs_v6.c b/drivers/media/platform/qcom/venus/hfi_plat_bufs_v6.c index a9be31ec6927038336ff504718bd95c92f523ac9..e97ff8cf6d64a994e076232a3cd5db22928347a9 100644 --- a/drivers/media/platform/qcom/venus/hfi_plat_bufs_v6.c +++ b/drivers/media/platform/qcom/venus/hfi_plat_bufs_v6.c @@ -1185,6 +1185,7 @@ static int bufreq_dec(struct hfi_plat_buffers_params *params, u32 buftype, enum hfi_version version = params->version; u32 codec = params->codec; u32 width = params->width, height = params->height, out_min_count; + u32 out_width = params->out_width, out_height = params->out_height; struct dec_bufsize_ops *dec_ops; bool is_secondary_output = params->dec.is_secondary_output; bool is_interlaced = params->dec.is_interlaced; @@ -1230,12 +1231,16 @@ static int bufreq_dec(struct hfi_plat_buffers_params *params, u32 buftype, calculate_dec_input_frame_size(width, height, codec, max_mbs_per_frame, buffer_size_limit); - } else if (buftype == HFI_BUFFER_OUTPUT || - buftype == HFI_BUFFER_OUTPUT2) { + } else if (buftype == HFI_BUFFER_OUTPUT || buftype == HFI_BUFFER_OUTPUT2) { bufreq->count_min = out_min_count; bufreq->size = venus_helper_get_framesz_raw(params->hfi_color_fmt, - width, height); + out_width, out_height); + if (buftype == HFI_BUFFER_OUTPUT && + params->dec.is_secondary_output) + bufreq->size = + venus_helper_get_framesz_raw(params->hfi_dpb_color_fmt, + out_width, out_height); } else if (buftype == HFI_BUFFER_INTERNAL_SCRATCH(version)) { bufreq->size = dec_ops->scratch(width, height, is_interlaced); } else if (buftype == HFI_BUFFER_INTERNAL_SCRATCH_1(version)) { diff --git a/drivers/media/platform/qcom/venus/hfi_venus.c b/drivers/media/platform/qcom/venus/hfi_venus.c index 2ad40b3945b0b315c60b12a9a504289001555809..f0b46389e8d569c8e3e2dfd56ee55d10f45c8f6b 100644 --- a/drivers/media/platform/qcom/venus/hfi_venus.c +++ b/drivers/media/platform/qcom/venus/hfi_venus.c @@ -835,34 +835,24 @@ static int venus_sys_set_debug(struct venus_hfi_device *hdev, u32 debug) { struct hfi_sys_set_property_pkt *pkt; u8 packet[IFACEQ_VAR_SMALL_PKT_SIZE]; - int ret; pkt = (struct hfi_sys_set_property_pkt *)packet; pkt_sys_debug_config(pkt, HFI_DEBUG_MODE_QUEUE, debug); - ret = venus_iface_cmdq_write(hdev, pkt, false); - if (ret) - return ret; - - return 0; + return venus_iface_cmdq_write(hdev, pkt, false); } static int venus_sys_set_coverage(struct venus_hfi_device *hdev, u32 mode) { struct hfi_sys_set_property_pkt *pkt; u8 packet[IFACEQ_VAR_SMALL_PKT_SIZE]; - int ret; pkt = (struct hfi_sys_set_property_pkt *)packet; pkt_sys_coverage_config(pkt, mode); - ret = venus_iface_cmdq_write(hdev, pkt, false); - if (ret) - return ret; - - return 0; + return venus_iface_cmdq_write(hdev, pkt, false); } static int venus_sys_set_idle_message(struct venus_hfi_device *hdev, @@ -870,7 +860,6 @@ static int venus_sys_set_idle_message(struct venus_hfi_device *hdev, { struct hfi_sys_set_property_pkt *pkt; u8 packet[IFACEQ_VAR_SMALL_PKT_SIZE]; - int ret; if (!enable) return 0; @@ -879,11 +868,7 @@ static int venus_sys_set_idle_message(struct venus_hfi_device *hdev, pkt_sys_idle_indicator(pkt, enable); - ret = venus_iface_cmdq_write(hdev, pkt, false); - if (ret) - return ret; - - return 0; + return venus_iface_cmdq_write(hdev, pkt, false); } static int venus_sys_set_power_control(struct venus_hfi_device *hdev, @@ -891,17 +876,12 @@ static int venus_sys_set_power_control(struct venus_hfi_device *hdev, { struct hfi_sys_set_property_pkt *pkt; u8 packet[IFACEQ_VAR_SMALL_PKT_SIZE]; - int ret; pkt = (struct hfi_sys_set_property_pkt *)packet; pkt_sys_power_control(pkt, enable); - ret = venus_iface_cmdq_write(hdev, pkt, false); - if (ret) - return ret; - - return 0; + return venus_iface_cmdq_write(hdev, pkt, false); } static int venus_sys_set_ubwc_config(struct venus_hfi_device *hdev) diff --git a/drivers/media/platform/qcom/venus/vdec.c b/drivers/media/platform/qcom/venus/vdec.c index 51a53bf82bd39effbf8d9802eaf266e86b5fba66..f5676440dd36cf9d6357956ba7b6f6e83b305338 100644 --- a/drivers/media/platform/qcom/venus/vdec.c +++ b/drivers/media/platform/qcom/venus/vdec.c @@ -30,69 +30,87 @@ * - future firmware versions could add support for >1 planes */ static const struct venus_format vdec_formats[] = { - { + [VENUS_FMT_NV12] = { .pixfmt = V4L2_PIX_FMT_NV12, .num_planes = 1, .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, - }, { + }, + [VENUS_FMT_QC08C] = { .pixfmt = V4L2_PIX_FMT_QC08C, .num_planes = 1, .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, - }, { + }, + [VENUS_FMT_QC10C] = { .pixfmt = V4L2_PIX_FMT_QC10C, .num_planes = 1, .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, - }, { - .pixfmt = V4L2_PIX_FMT_MPEG4, + }, + [VENUS_FMT_P010] = { + .pixfmt = V4L2_PIX_FMT_P010, + .num_planes = 1, + .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, + }, + [VENUS_FMT_H264] = { + .pixfmt = V4L2_PIX_FMT_H264, .num_planes = 1, .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, .flags = V4L2_FMT_FLAG_DYN_RESOLUTION, - }, { - .pixfmt = V4L2_PIX_FMT_MPEG2, + }, + [VENUS_FMT_VP8] = { + .pixfmt = V4L2_PIX_FMT_VP8, .num_planes = 1, .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, .flags = V4L2_FMT_FLAG_DYN_RESOLUTION, - }, { - .pixfmt = V4L2_PIX_FMT_H263, + }, + [VENUS_FMT_VP9] = { + .pixfmt = V4L2_PIX_FMT_VP9, .num_planes = 1, .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, .flags = V4L2_FMT_FLAG_DYN_RESOLUTION, - }, { - .pixfmt = V4L2_PIX_FMT_VC1_ANNEX_G, + }, + [VENUS_FMT_HEVC] = { + .pixfmt = V4L2_PIX_FMT_HEVC, .num_planes = 1, .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, .flags = V4L2_FMT_FLAG_DYN_RESOLUTION, - }, { - .pixfmt = V4L2_PIX_FMT_VC1_ANNEX_L, + }, + [VENUS_FMT_VC1_ANNEX_G] = { + .pixfmt = V4L2_PIX_FMT_VC1_ANNEX_G, .num_planes = 1, .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, .flags = V4L2_FMT_FLAG_DYN_RESOLUTION, - }, { - .pixfmt = V4L2_PIX_FMT_H264, + }, + [VENUS_FMT_VC1_ANNEX_L] = { + .pixfmt = V4L2_PIX_FMT_VC1_ANNEX_L, .num_planes = 1, .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, .flags = V4L2_FMT_FLAG_DYN_RESOLUTION, - }, { - .pixfmt = V4L2_PIX_FMT_VP8, + }, + [VENUS_FMT_MPEG4] = { + .pixfmt = V4L2_PIX_FMT_MPEG4, .num_planes = 1, .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, .flags = V4L2_FMT_FLAG_DYN_RESOLUTION, - }, { - .pixfmt = V4L2_PIX_FMT_VP9, + }, + [VENUS_FMT_MPEG2] = { + .pixfmt = V4L2_PIX_FMT_MPEG2, .num_planes = 1, .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, .flags = V4L2_FMT_FLAG_DYN_RESOLUTION, - }, { - .pixfmt = V4L2_PIX_FMT_XVID, + }, + [VENUS_FMT_H263] = { + .pixfmt = V4L2_PIX_FMT_H263, .num_planes = 1, .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, .flags = V4L2_FMT_FLAG_DYN_RESOLUTION, - }, { - .pixfmt = V4L2_PIX_FMT_HEVC, + }, + [VENUS_FMT_XVID] = { + .pixfmt = V4L2_PIX_FMT_XVID, .num_planes = 1, .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, .flags = V4L2_FMT_FLAG_DYN_RESOLUTION, }, + }; static const struct venus_format * @@ -551,7 +569,7 @@ vdec_decoder_cmd(struct file *file, void *fh, struct v4l2_decoder_cmd *cmd) fdata.buffer_type = HFI_BUFFER_INPUT; fdata.flags |= HFI_BUFFERFLAG_EOS; - if (IS_V6(inst->core)) + if (IS_V6(inst->core) && is_fw_rev_or_older(inst->core, 1, 0, 87)) fdata.device_addr = 0; else fdata.device_addr = 0xdeadb000; @@ -684,6 +702,14 @@ static int vdec_set_properties(struct venus_inst *inst) return ret; } + /* Enabling sufficient sequence change support for VP9 */ + if (is_fw_rev_or_newer(inst->core, 5, 4, 51)) { + ptype = HFI_PROPERTY_PARAM_VDEC_ENABLE_SUFFICIENT_SEQCHANGE_EVENT; + ret = hfi_session_set_property(inst, ptype, &en); + if (ret) + return ret; + } + ptype = HFI_PROPERTY_PARAM_VDEC_CONCEAL_COLOR; conceal = ctr->conceal_color & 0xffff; conceal |= ((ctr->conceal_color >> 16) & 0xffff) << 10; @@ -710,6 +736,9 @@ static int vdec_set_work_route(struct venus_inst *inst) } #define is_ubwc_fmt(fmt) (!!((fmt) & HFI_COLOR_FORMAT_UBWC_BASE)) +#define is_10bit_ubwc_fmt(fmt) (!!((fmt) & HFI_COLOR_FORMAT_10_BIT_BASE & \ + HFI_COLOR_FORMAT_UBWC_BASE)) + static int vdec_output_conf(struct venus_inst *inst) { @@ -757,7 +786,7 @@ static int vdec_output_conf(struct venus_inst *inst) inst->opb_fmt = out2_fmt; inst->dpb_buftype = HFI_BUFFER_OUTPUT; inst->dpb_fmt = out_fmt; - } else if (is_ubwc_fmt(out2_fmt)) { + } else if (is_ubwc_fmt(out2_fmt) || is_10bit_ubwc_fmt(out_fmt)) { inst->opb_buftype = HFI_BUFFER_OUTPUT; inst->opb_fmt = out_fmt; inst->dpb_buftype = HFI_BUFFER_OUTPUT2; @@ -1474,8 +1503,13 @@ static void vdec_event_change(struct venus_inst *inst, inst->out_width = ev_data->width; inst->out_height = ev_data->height; - if (inst->bit_depth != ev_data->bit_depth) + if (inst->bit_depth != ev_data->bit_depth) { inst->bit_depth = ev_data->bit_depth; + if (inst->bit_depth == VIDC_BITDEPTH_10) + inst->fmt_cap = &vdec_formats[VENUS_FMT_P010]; + else + inst->fmt_cap = &vdec_formats[VENUS_FMT_NV12]; + } if (inst->pic_struct != ev_data->pic_struct) inst->pic_struct = ev_data->pic_struct; @@ -1567,8 +1601,8 @@ static const struct hfi_inst_ops vdec_hfi_ops = { static void vdec_inst_init(struct venus_inst *inst) { inst->hfi_codec = HFI_VIDEO_CODEC_H264; - inst->fmt_out = &vdec_formats[8]; - inst->fmt_cap = &vdec_formats[0]; + inst->fmt_out = &vdec_formats[VENUS_FMT_H264]; + inst->fmt_cap = &vdec_formats[VENUS_FMT_NV12]; inst->width = frame_width_min(inst); inst->height = ALIGN(frame_height_min(inst), 32); inst->crop.left = 0; @@ -1609,6 +1643,7 @@ static int m2m_queue_init(void *priv, struct vb2_queue *src_vq, src_vq->allow_zero_bytesused = 1; src_vq->min_buffers_needed = 0; src_vq->dev = inst->core->dev; + src_vq->lock = &inst->ctx_q_lock; ret = vb2_queue_init(src_vq); if (ret) return ret; @@ -1623,6 +1658,7 @@ static int m2m_queue_init(void *priv, struct vb2_queue *src_vq, dst_vq->allow_zero_bytesused = 1; dst_vq->min_buffers_needed = 0; dst_vq->dev = inst->core->dev; + dst_vq->lock = &inst->ctx_q_lock; return vb2_queue_init(dst_vq); } @@ -1641,6 +1677,7 @@ static int vdec_open(struct file *file) INIT_LIST_HEAD(&inst->internalbufs); INIT_LIST_HEAD(&inst->list); mutex_init(&inst->lock); + mutex_init(&inst->ctx_q_lock); inst->core = core; inst->session_type = VIDC_SESSION_TYPE_DEC; @@ -1716,6 +1753,7 @@ static int vdec_close(struct file *file) ida_destroy(&inst->dpb_ids); hfi_session_destroy(inst); mutex_destroy(&inst->lock); + mutex_destroy(&inst->ctx_q_lock); v4l2_fh_del(&inst->fh); v4l2_fh_exit(&inst->fh); diff --git a/drivers/media/platform/qcom/venus/venc.c b/drivers/media/platform/qcom/venus/venc.c index 4666f42feea3d60c6c0f856d124e8b62184e99a8..6d773b000e8a7eef8d213d58099f81f1fc3bb4be 100644 --- a/drivers/media/platform/qcom/venus/venc.c +++ b/drivers/media/platform/qcom/venus/venc.c @@ -32,28 +32,33 @@ * - future firmware versions could add support for >1 planes */ static const struct venus_format venc_formats[] = { - { + [VENUS_FMT_NV12] = { .pixfmt = V4L2_PIX_FMT_NV12, .num_planes = 1, .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, - }, { - .pixfmt = V4L2_PIX_FMT_MPEG4, + }, + [VENUS_FMT_H264] = { + .pixfmt = V4L2_PIX_FMT_H264, .num_planes = 1, .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, - }, { - .pixfmt = V4L2_PIX_FMT_H263, + }, + [VENUS_FMT_VP8] = { + .pixfmt = V4L2_PIX_FMT_VP8, .num_planes = 1, .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, - }, { - .pixfmt = V4L2_PIX_FMT_H264, + }, + [VENUS_FMT_HEVC] = { + .pixfmt = V4L2_PIX_FMT_HEVC, .num_planes = 1, .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, - }, { - .pixfmt = V4L2_PIX_FMT_VP8, + }, + [VENUS_FMT_MPEG4] = { + .pixfmt = V4L2_PIX_FMT_MPEG4, .num_planes = 1, .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, - }, { - .pixfmt = V4L2_PIX_FMT_HEVC, + }, + [VENUS_FMT_H263] = { + .pixfmt = V4L2_PIX_FMT_H263, .num_planes = 1, .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, }, @@ -1395,6 +1400,7 @@ static int m2m_queue_init(void *priv, struct vb2_queue *src_vq, src_vq->allow_zero_bytesused = 1; src_vq->min_buffers_needed = 1; src_vq->dev = inst->core->dev; + src_vq->lock = &inst->ctx_q_lock; if (inst->core->res->hfi_version == HFI_VERSION_1XX) src_vq->bidirectional = 1; ret = vb2_queue_init(src_vq); @@ -1411,13 +1417,14 @@ static int m2m_queue_init(void *priv, struct vb2_queue *src_vq, dst_vq->allow_zero_bytesused = 1; dst_vq->min_buffers_needed = 1; dst_vq->dev = inst->core->dev; + dst_vq->lock = &inst->ctx_q_lock; return vb2_queue_init(dst_vq); } static void venc_inst_init(struct venus_inst *inst) { - inst->fmt_cap = &venc_formats[3]; - inst->fmt_out = &venc_formats[0]; + inst->fmt_cap = &venc_formats[VENUS_FMT_H264]; + inst->fmt_out = &venc_formats[VENUS_FMT_NV12]; inst->width = 1280; inst->height = ALIGN(720, 32); inst->out_width = 1280; @@ -1443,6 +1450,7 @@ static int venc_open(struct file *file) INIT_LIST_HEAD(&inst->internalbufs); INIT_LIST_HEAD(&inst->list); mutex_init(&inst->lock); + mutex_init(&inst->ctx_q_lock); inst->core = core; inst->session_type = VIDC_SESSION_TYPE_ENC; @@ -1512,6 +1520,7 @@ static int venc_close(struct file *file) venc_ctrl_deinit(inst); hfi_session_destroy(inst); mutex_destroy(&inst->lock); + mutex_destroy(&inst->ctx_q_lock); v4l2_fh_del(&inst->fh); v4l2_fh_exit(&inst->fh); diff --git a/drivers/media/platform/renesas/rcar-isp.c b/drivers/media/platform/renesas/rcar-isp.c index f666b621338d08b8dd098e6de1ca9109a9b75ec0..fee1a066f56b7e158626fc5e89611ec31058c428 100644 --- a/drivers/media/platform/renesas/rcar-isp.c +++ b/drivers/media/platform/renesas/rcar-isp.c @@ -430,6 +430,7 @@ static int risp_probe_resources(struct rcar_isp *isp, static const struct of_device_id risp_of_id_table[] = { { .compatible = "renesas,r8a779a0-isp" }, + { .compatible = "renesas,r8a779g0-isp" }, { /* sentinel */ }, }; MODULE_DEVICE_TABLE(of, risp_of_id_table); diff --git a/drivers/media/platform/renesas/rcar-vin/rcar-core.c b/drivers/media/platform/renesas/rcar-vin/rcar-core.c index ff4bde9cc0e30dd1f6aa47cf7e2a5150408eae1a..3c4f5eb93be18791a5c18e1ae84b8ccb257f862e 100644 --- a/drivers/media/platform/renesas/rcar-vin/rcar-core.c +++ b/drivers/media/platform/renesas/rcar-vin/rcar-core.c @@ -1284,6 +1284,15 @@ static const struct rvin_info rcar_info_r8a779a0 = { .max_height = 4096, }; +static const struct rvin_info rcar_info_r8a779g0 = { + .model = RCAR_GEN3, + .use_mc = true, + .use_isp = true, + .nv12 = true, + .max_width = 4096, + .max_height = 4096, +}; + static const struct of_device_id rvin_of_id_table[] = { { .compatible = "renesas,vin-r8a774a1", @@ -1349,6 +1358,10 @@ static const struct of_device_id rvin_of_id_table[] = { .compatible = "renesas,vin-r8a779a0", .data = &rcar_info_r8a779a0, }, + { + .compatible = "renesas,vin-r8a779g0", + .data = &rcar_info_r8a779g0, + }, { /* Sentinel */ }, }; MODULE_DEVICE_TABLE(of, rvin_of_id_table); diff --git a/drivers/media/platform/renesas/rcar-vin/rcar-csi2.c b/drivers/media/platform/renesas/rcar-vin/rcar-csi2.c index e34060c2b039567cf318fbb65814a2a4bac7de11..7a134c0eff571b0238b5835051766b01bdced037 100644 --- a/drivers/media/platform/renesas/rcar-vin/rcar-csi2.c +++ b/drivers/media/platform/renesas/rcar-vin/rcar-csi2.c @@ -483,11 +483,15 @@ enum rcar_csi2_pads { struct rcar_csi2_info { int (*init_phtw)(struct rcar_csi2 *priv, unsigned int mbps); int (*phy_post_init)(struct rcar_csi2 *priv); + int (*start_receiver)(struct rcar_csi2 *priv); + void (*enter_standby)(struct rcar_csi2 *priv); const struct rcsi2_mbps_reg *hsfreqrange; unsigned int csi0clkfreqrange; unsigned int num_channels; bool clear_ulps; bool use_isp; + bool support_dphy; + bool support_cphy; }; struct rcar_csi2 { @@ -509,6 +513,7 @@ struct rcar_csi2 { struct v4l2_mbus_framefmt mf; int stream_count; + bool cphy; unsigned short lanes; unsigned char lane_swap[4]; }; @@ -533,10 +538,17 @@ static void rcsi2_write(struct rcar_csi2 *priv, unsigned int reg, u32 data) iowrite32(data, priv->base + reg); } -static void rcsi2_enter_standby(struct rcar_csi2 *priv) +static void rcsi2_enter_standby_gen3(struct rcar_csi2 *priv) { rcsi2_write(priv, PHYCNT_REG, 0); rcsi2_write(priv, PHTC_REG, PHTC_TESTCLR); +} + +static void rcsi2_enter_standby(struct rcar_csi2 *priv) +{ + if (priv->info->enter_standby) + priv->info->enter_standby(priv); + reset_control_assert(priv->rstc); usleep_range(100, 150); pm_runtime_put(priv->dev); @@ -656,7 +668,16 @@ static int rcsi2_get_active_lanes(struct rcar_csi2 *priv, return ret; } - if (mbus_config.type != V4L2_MBUS_CSI2_DPHY) { + switch (mbus_config.type) { + case V4L2_MBUS_CSI2_CPHY: + if (!priv->cphy) + return -EINVAL; + break; + case V4L2_MBUS_CSI2_DPHY: + if (priv->cphy) + return -EINVAL; + break; + default: dev_err(priv->dev, "Unsupported media bus type %u\n", mbus_config.type); return -EINVAL; @@ -674,7 +695,7 @@ static int rcsi2_get_active_lanes(struct rcar_csi2 *priv, return 0; } -static int rcsi2_start_receiver(struct rcar_csi2 *priv) +static int rcsi2_start_receiver_gen3(struct rcar_csi2 *priv) { const struct rcar_csi2_format *format; u32 phycnt, vcdt = 0, vcdt2 = 0, fld = 0; @@ -821,7 +842,7 @@ static int rcsi2_start(struct rcar_csi2 *priv) if (ret < 0) return ret; - ret = rcsi2_start_receiver(priv); + ret = priv->info->start_receiver(priv); if (ret) { rcsi2_enter_standby(priv); return ret; @@ -1016,15 +1037,41 @@ static int rcsi2_parse_v4l2(struct rcar_csi2 *priv, if (vep->base.port || vep->base.id) return -ENOTCONN; - if (vep->bus_type != V4L2_MBUS_CSI2_DPHY) { - dev_err(priv->dev, "Unsupported bus: %u\n", vep->bus_type); - return -EINVAL; - } - priv->lanes = vep->bus.mipi_csi2.num_data_lanes; - if (priv->lanes != 1 && priv->lanes != 2 && priv->lanes != 4) { - dev_err(priv->dev, "Unsupported number of data-lanes: %u\n", - priv->lanes); + + switch (vep->bus_type) { + case V4L2_MBUS_CSI2_DPHY: + if (!priv->info->support_dphy) { + dev_err(priv->dev, "D-PHY not supported\n"); + return -EINVAL; + } + + if (priv->lanes != 1 && priv->lanes != 2 && priv->lanes != 4) { + dev_err(priv->dev, + "Unsupported number of data-lanes for D-PHY: %u\n", + priv->lanes); + return -EINVAL; + } + + priv->cphy = false; + break; + case V4L2_MBUS_CSI2_CPHY: + if (!priv->info->support_cphy) { + dev_err(priv->dev, "C-PHY not supported\n"); + return -EINVAL; + } + + if (priv->lanes != 3) { + dev_err(priv->dev, + "Unsupported number of data-lanes for C-PHY: %u\n", + priv->lanes); + return -EINVAL; + } + + priv->cphy = true; + break; + default: + dev_err(priv->dev, "Unsupported bus: %u\n", vep->bus_type); return -EINVAL; } @@ -1048,7 +1095,7 @@ static int rcsi2_parse_dt(struct rcar_csi2 *priv) struct fwnode_handle *fwnode; struct fwnode_handle *ep; struct v4l2_fwnode_endpoint v4l2_ep = { - .bus_type = V4L2_MBUS_CSI2_DPHY + .bus_type = V4L2_MBUS_UNKNOWN, }; int ret; @@ -1363,63 +1410,90 @@ static int rcsi2_probe_resources(struct rcar_csi2 *priv, static const struct rcar_csi2_info rcar_csi2_info_r8a7795 = { .init_phtw = rcsi2_init_phtw_h3_v3h_m3n, + .start_receiver = rcsi2_start_receiver_gen3, + .enter_standby = rcsi2_enter_standby_gen3, .hsfreqrange = hsfreqrange_h3_v3h_m3n, .csi0clkfreqrange = 0x20, .num_channels = 4, .clear_ulps = true, + .support_dphy = true, }; static const struct rcar_csi2_info rcar_csi2_info_r8a7795es2 = { .init_phtw = rcsi2_init_phtw_h3es2, + .start_receiver = rcsi2_start_receiver_gen3, + .enter_standby = rcsi2_enter_standby_gen3, .hsfreqrange = hsfreqrange_h3_v3h_m3n, .csi0clkfreqrange = 0x20, .num_channels = 4, .clear_ulps = true, + .support_dphy = true, }; static const struct rcar_csi2_info rcar_csi2_info_r8a7796 = { + .start_receiver = rcsi2_start_receiver_gen3, + .enter_standby = rcsi2_enter_standby_gen3, .hsfreqrange = hsfreqrange_m3w, .num_channels = 4, + .support_dphy = true, }; static const struct rcar_csi2_info rcar_csi2_info_r8a77961 = { + .start_receiver = rcsi2_start_receiver_gen3, + .enter_standby = rcsi2_enter_standby_gen3, .hsfreqrange = hsfreqrange_m3w, .num_channels = 4, + .support_dphy = true, }; static const struct rcar_csi2_info rcar_csi2_info_r8a77965 = { .init_phtw = rcsi2_init_phtw_h3_v3h_m3n, + .start_receiver = rcsi2_start_receiver_gen3, + .enter_standby = rcsi2_enter_standby_gen3, .hsfreqrange = hsfreqrange_h3_v3h_m3n, .csi0clkfreqrange = 0x20, .num_channels = 4, .clear_ulps = true, + .support_dphy = true, }; static const struct rcar_csi2_info rcar_csi2_info_r8a77970 = { .init_phtw = rcsi2_init_phtw_v3m_e3, .phy_post_init = rcsi2_phy_post_init_v3m_e3, + .start_receiver = rcsi2_start_receiver_gen3, + .enter_standby = rcsi2_enter_standby_gen3, .num_channels = 4, + .support_dphy = true, }; static const struct rcar_csi2_info rcar_csi2_info_r8a77980 = { .init_phtw = rcsi2_init_phtw_h3_v3h_m3n, + .start_receiver = rcsi2_start_receiver_gen3, + .enter_standby = rcsi2_enter_standby_gen3, .hsfreqrange = hsfreqrange_h3_v3h_m3n, .csi0clkfreqrange = 0x20, .clear_ulps = true, + .support_dphy = true, }; static const struct rcar_csi2_info rcar_csi2_info_r8a77990 = { .init_phtw = rcsi2_init_phtw_v3m_e3, .phy_post_init = rcsi2_phy_post_init_v3m_e3, + .start_receiver = rcsi2_start_receiver_gen3, + .enter_standby = rcsi2_enter_standby_gen3, .num_channels = 2, + .support_dphy = true, }; static const struct rcar_csi2_info rcar_csi2_info_r8a779a0 = { .init_phtw = rcsi2_init_phtw_v3u, + .start_receiver = rcsi2_start_receiver_gen3, + .enter_standby = rcsi2_enter_standby_gen3, .hsfreqrange = hsfreqrange_v3u, .csi0clkfreqrange = 0x20, .clear_ulps = true, .use_isp = true, + .support_dphy = true, }; static const struct of_device_id rcar_csi2_of_table[] = { diff --git a/drivers/media/platform/renesas/rcar_fdp1.c b/drivers/media/platform/renesas/rcar_fdp1.c index f43e458590b8cadaa1a821010b1dddef1ae89aed..ab39cd2201c85d84b9fe1e7d67cf46b6a37471c9 100644 --- a/drivers/media/platform/renesas/rcar_fdp1.c +++ b/drivers/media/platform/renesas/rcar_fdp1.c @@ -254,6 +254,8 @@ MODULE_PARM_DESC(debug, "activate debug info"); /* Internal Data (HW Version) */ #define FD1_IP_INTDATA 0x0800 +/* R-Car Gen2 HW manual says zero, but actual value matches R-Car H3 ES1.x */ +#define FD1_IP_GEN2 0x02010101 #define FD1_IP_M3W 0x02010202 #define FD1_IP_H3 0x02010203 #define FD1_IP_M3N 0x02010204 @@ -2360,6 +2362,9 @@ static int fdp1_probe(struct platform_device *pdev) hw_version = fdp1_read(fdp1, FD1_IP_INTDATA); switch (hw_version) { + case FD1_IP_GEN2: + dprintk(fdp1, "FDP1 Version R-Car Gen2\n"); + break; case FD1_IP_M3W: dprintk(fdp1, "FDP1 Version R-Car M3-W\n"); break; diff --git a/drivers/media/platform/renesas/rcar_jpu.c b/drivers/media/platform/renesas/rcar_jpu.c index e7f60480782538fade47feca0eb6da689c5abd23..2b8cb50f54de5f53a6122bd48f6a0915224f4499 100644 --- a/drivers/media/platform/renesas/rcar_jpu.c +++ b/drivers/media/platform/renesas/rcar_jpu.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -71,19 +72,6 @@ #define JPU_JPEG_DEFAULT_422_PIX_FMT V4L2_PIX_FMT_NV16M #define JPU_JPEG_DEFAULT_420_PIX_FMT V4L2_PIX_FMT_NV12M -/* JPEG markers */ -#define TEM 0x01 -#define SOF0 0xc0 -#define RST 0xd0 -#define SOI 0xd8 -#define EOI 0xd9 -#define DHP 0xde -#define DHT 0xc4 -#define COM 0xfe -#define DQT 0xdb -#define DRI 0xdd -#define APP0 0xe0 - #define JPU_RESET_TIMEOUT 100 /* ms */ #define JPU_JOB_TIMEOUT 300 /* ms */ #define JPU_MAX_QUALITY 4 @@ -330,26 +318,32 @@ static const u8 zigzag[] = { * Huffman tables; Padding with 0xff (33.3.27 R01UH0501EJ0100 Rev.1.00) */ #define JPU_JPEG_HDR_BLOB { \ - 0xff, SOI, 0xff, DQT, 0x00, JPU_JPEG_QTBL_SIZE + 0x3, JPU_JPEG_LUM, \ - [JPU_JPEG_QTBL_LUM_OFFSET ... \ + 0xff, JPEG_MARKER_SOI, 0xff, JPEG_MARKER_DQT, 0x00, \ + JPU_JPEG_QTBL_SIZE + 0x3, JPU_JPEG_LUM, \ + [JPU_JPEG_QTBL_LUM_OFFSET ... \ JPU_JPEG_QTBL_LUM_OFFSET + JPU_JPEG_QTBL_SIZE - 1] = 0x00, \ - 0xff, DQT, 0x00, JPU_JPEG_QTBL_SIZE + 0x3, JPU_JPEG_CHR, \ + 0xff, JPEG_MARKER_DQT, 0x00, JPU_JPEG_QTBL_SIZE + 0x3, JPU_JPEG_CHR, \ [JPU_JPEG_QTBL_CHR_OFFSET ... JPU_JPEG_QTBL_CHR_OFFSET + \ - JPU_JPEG_QTBL_SIZE - 1] = 0x00, 0xff, SOF0, 0x00, 0x11, 0x08, \ + JPU_JPEG_QTBL_SIZE - 1] = 0x00, \ + 0xff, JPEG_MARKER_SOF0, 0x00, 0x11, 0x08, \ [JPU_JPEG_HEIGHT_OFFSET ... JPU_JPEG_HEIGHT_OFFSET + 1] = 0x00, \ [JPU_JPEG_WIDTH_OFFSET ... JPU_JPEG_WIDTH_OFFSET + 1] = 0x00, \ 0x03, 0x01, [JPU_JPEG_SUBS_OFFSET] = 0x00, JPU_JPEG_LUM, \ 0x02, 0x11, JPU_JPEG_CHR, 0x03, 0x11, JPU_JPEG_CHR, \ - 0xff, DHT, 0x00, JPU_JPEG_HDCTBL_SIZE + 0x3, JPU_JPEG_LUM|JPU_JPEG_DC, \ + 0xff, JPEG_MARKER_DHT, 0x00, JPU_JPEG_HDCTBL_SIZE + 0x3, \ + JPU_JPEG_LUM | JPU_JPEG_DC, \ [JPU_JPEG_HDCTBL_LUM_OFFSET ... \ JPU_JPEG_HDCTBL_LUM_OFFSET + JPU_JPEG_HDCTBL_SIZE - 1] = 0x00, \ - 0xff, DHT, 0x00, JPU_JPEG_HACTBL_SIZE + 0x3, JPU_JPEG_LUM|JPU_JPEG_AC, \ + 0xff, JPEG_MARKER_DHT, 0x00, JPU_JPEG_HACTBL_SIZE + 0x3, \ + JPU_JPEG_LUM | JPU_JPEG_AC, \ [JPU_JPEG_HACTBL_LUM_OFFSET ... \ JPU_JPEG_HACTBL_LUM_OFFSET + JPU_JPEG_HACTBL_SIZE - 1] = 0x00, \ - 0xff, DHT, 0x00, JPU_JPEG_HDCTBL_SIZE + 0x3, JPU_JPEG_CHR|JPU_JPEG_DC, \ + 0xff, JPEG_MARKER_DHT, 0x00, JPU_JPEG_HDCTBL_SIZE + 0x3, \ + JPU_JPEG_CHR | JPU_JPEG_DC, \ [JPU_JPEG_HDCTBL_CHR_OFFSET ... \ JPU_JPEG_HDCTBL_CHR_OFFSET + JPU_JPEG_HDCTBL_SIZE - 1] = 0x00, \ - 0xff, DHT, 0x00, JPU_JPEG_HACTBL_SIZE + 0x3, JPU_JPEG_CHR|JPU_JPEG_AC, \ + 0xff, JPEG_MARKER_DHT, 0x00, JPU_JPEG_HACTBL_SIZE + 0x3, \ + JPU_JPEG_CHR | JPU_JPEG_AC, \ [JPU_JPEG_HACTBL_CHR_OFFSET ... \ JPU_JPEG_HACTBL_CHR_OFFSET + JPU_JPEG_HACTBL_SIZE - 1] = 0x00, \ [JPU_JPEG_PADDING_OFFSET ... JPU_JPEG_HDR_SIZE - 1] = 0xff \ @@ -613,7 +607,8 @@ static u8 jpu_parse_hdr(void *buffer, unsigned long size, unsigned int *width, * basic size check and EOI - we don't want to let JPU cross * buffer bounds in any case. Hope it's stopping by EOI. */ - if (size < JPU_JPEG_MIN_SIZE || *(u8 *)(buffer + size - 1) != EOI) + if (size < JPU_JPEG_MIN_SIZE || + *(u8 *)(buffer + size - 1) != JPEG_MARKER_EOI) return 0; for (;;) { @@ -624,14 +619,14 @@ static u8 jpu_parse_hdr(void *buffer, unsigned long size, unsigned int *width, c = get_byte(&jpeg_buffer); while (c == 0xff || c == 0); - if (!soi && c == SOI) { + if (!soi && c == JPEG_MARKER_SOI) { soi = true; continue; - } else if (soi != (c != SOI)) + } else if (soi != (c != JPEG_MARKER_SOI)) return 0; switch (c) { - case SOF0: /* SOF0: baseline JPEG */ + case JPEG_MARKER_SOF0: /* SOF0: baseline JPEG */ skip(&jpeg_buffer, 3); /* segment length and bpp */ if (get_word_be(&jpeg_buffer, height) || get_word_be(&jpeg_buffer, width) || @@ -640,11 +635,11 @@ static u8 jpu_parse_hdr(void *buffer, unsigned long size, unsigned int *width, skip(&jpeg_buffer, 1); return get_byte(&jpeg_buffer); - case DHT: - case DQT: - case COM: - case DRI: - case APP0 ... APP0 + 0x0f: + case JPEG_MARKER_DHT: + case JPEG_MARKER_DQT: + case JPEG_MARKER_COM: + case JPEG_MARKER_DRI: + case JPEG_MARKER_APP0 ... JPEG_MARKER_APP0 + 0x0f: if (get_word_be(&jpeg_buffer, &word)) return 0; skip(&jpeg_buffer, (long)word - 2); diff --git a/drivers/media/platform/renesas/renesas-ceu.c b/drivers/media/platform/renesas/renesas-ceu.c index 56b9c59cfda8246aa9b4c4f23e104ac5765cf5d5..5c9e27f8c94b744ddb23facef8ba3fb0d15ee555 100644 --- a/drivers/media/platform/renesas/renesas-ceu.c +++ b/drivers/media/platform/renesas/renesas-ceu.c @@ -702,12 +702,6 @@ static int ceu_start_streaming(struct vb2_queue *vq, unsigned int count) /* Grab the first available buffer and trigger the first capture. */ buf = list_first_entry(&ceudev->capture, struct ceu_buffer, queue); - if (!buf) { - spin_unlock_irqrestore(&ceudev->lock, irqflags); - dev_dbg(ceudev->dev, - "No buffer available for capture.\n"); - goto error_stop_sensor; - } list_del(&buf->queue); ceudev->active = &buf->vb; @@ -722,9 +716,6 @@ static int ceu_start_streaming(struct vb2_queue *vq, unsigned int count) return 0; -error_stop_sensor: - v4l2_subdev_call(v4l2_sd, video, s_stream, 0); - error_return_bufs: spin_lock_irqsave(&ceudev->lock, irqflags); list_for_each_entry(buf, &ceudev->capture, queue) diff --git a/drivers/media/platform/renesas/rzg2l-cru/rzg2l-csi2.c b/drivers/media/platform/renesas/rzg2l-cru/rzg2l-csi2.c index 30dad7383654c36c301158d690c79ceb5182bf92..d6489c62b08125fa6989eaa2cb2efc98bb942ef5 100644 --- a/drivers/media/platform/renesas/rzg2l-cru/rzg2l-csi2.c +++ b/drivers/media/platform/renesas/rzg2l-cru/rzg2l-csi2.c @@ -81,10 +81,10 @@ #define CSIDPHYSKW0_UTIL_DL1_SKW_ADJ(x) (((x) & 0x3) << 4) #define CSIDPHYSKW0_UTIL_DL2_SKW_ADJ(x) (((x) & 0x3) << 8) #define CSIDPHYSKW0_UTIL_DL3_SKW_ADJ(x) (((x) & 0x3) << 12) -#define CSIDPHYSKW0_DEFAULT_SKW CSIDPHYSKW0_UTIL_DL0_SKW_ADJ(1) | \ - CSIDPHYSKW0_UTIL_DL1_SKW_ADJ(1) | \ - CSIDPHYSKW0_UTIL_DL2_SKW_ADJ(1) | \ - CSIDPHYSKW0_UTIL_DL3_SKW_ADJ(1) +#define CSIDPHYSKW0_DEFAULT_SKW (CSIDPHYSKW0_UTIL_DL0_SKW_ADJ(1) | \ + CSIDPHYSKW0_UTIL_DL1_SKW_ADJ(1) | \ + CSIDPHYSKW0_UTIL_DL2_SKW_ADJ(1) | \ + CSIDPHYSKW0_UTIL_DL3_SKW_ADJ(1)) #define VSRSTS_RETRIES 20 diff --git a/drivers/media/platform/rockchip/rga/rga.c b/drivers/media/platform/rockchip/rga/rga.c index 67dcf22e5ba3101ed41d84242e51148cbe08274e..f1c532a5802ac29673904522eeeb92fa1341bb7a 100644 --- a/drivers/media/platform/rockchip/rga/rga.c +++ b/drivers/media/platform/rockchip/rga/rga.c @@ -76,10 +76,7 @@ static irqreturn_t rga_isr(int irq, void *prv) WARN_ON(!src); WARN_ON(!dst); - dst->timecode = src->timecode; - dst->vb2_buf.timestamp = src->vb2_buf.timestamp; - dst->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK; - dst->flags |= src->flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK; + v4l2_m2m_buf_copy_metadata(src, dst, true); v4l2_m2m_buf_done(src, VB2_BUF_STATE_DONE); v4l2_m2m_buf_done(dst, VB2_BUF_STATE_DONE); @@ -726,10 +723,10 @@ static int rga_enable_clocks(struct rockchip_rga *rga) return 0; -err_disable_sclk: - clk_disable_unprepare(rga->sclk); err_disable_aclk: clk_disable_unprepare(rga->aclk); +err_disable_sclk: + clk_disable_unprepare(rga->sclk); return ret; } diff --git a/drivers/media/platform/samsung/exynos4-is/Kconfig b/drivers/media/platform/samsung/exynos4-is/Kconfig index da33faa7132e8597069d2183b37d57e4450bfdc2..7f9ba053dd8ebf6bcd28651fd457402147dfc400 100644 --- a/drivers/media/platform/samsung/exynos4-is/Kconfig +++ b/drivers/media/platform/samsung/exynos4-is/Kconfig @@ -47,7 +47,7 @@ config VIDEO_S5P_MIPI_CSIS config VIDEO_EXYNOS_FIMC_LITE tristate "EXYNOS FIMC-LITE camera interface driver" depends on I2C - depends on SOC_EXYNOS4412 || SOC_EXYNOS5250 || COMPILE_TEST + depends on SOC_EXYNOS4212 || SOC_EXYNOS4412 || SOC_EXYNOS5250 || COMPILE_TEST depends on HAS_DMA select VIDEOBUF2_DMA_CONTIG select VIDEO_EXYNOS4_IS_COMMON diff --git a/drivers/media/platform/samsung/exynos4-is/fimc-core.c b/drivers/media/platform/samsung/exynos4-is/fimc-core.c index a2034ade8b9e23390a598f5706898281b97217e8..976b4f747ad45d346b4e5af60a4b6b563df5c59e 100644 --- a/drivers/media/platform/samsung/exynos4-is/fimc-core.c +++ b/drivers/media/platform/samsung/exynos4-is/fimc-core.c @@ -1128,7 +1128,7 @@ static const struct fimc_drvdata fimc_drvdata_exynos4210 = { .out_buf_count = 32, }; -/* EXYNOS4412 */ +/* EXYNOS4212, EXYNOS4412 */ static const struct fimc_drvdata fimc_drvdata_exynos4x12 = { .num_entities = 4, .lclk_frequency = 166000000UL, diff --git a/drivers/media/platform/samsung/exynos4-is/fimc-lite.c b/drivers/media/platform/samsung/exynos4-is/fimc-lite.c index 24b3dda26714b97f7492b81a3dfcbc1bcd19ade5..c3146ae084476c8bd6d885c3a84d1c0a08709ce9 100644 --- a/drivers/media/platform/samsung/exynos4-is/fimc-lite.c +++ b/drivers/media/platform/samsung/exynos4-is/fimc-lite.c @@ -1621,7 +1621,7 @@ static const struct dev_pm_ops fimc_lite_pm_ops = { NULL) }; -/* EXYNOS4412 */ +/* EXYNOS4212, EXYNOS4412 */ static struct flite_drvdata fimc_lite_drvdata_exynos4 = { .max_width = 8192, .max_height = 8192, diff --git a/drivers/media/platform/samsung/s5p-jpeg/jpeg-core.h b/drivers/media/platform/samsung/s5p-jpeg/jpeg-core.h index 5570c79f122f5a09d10a93d901aa28d4ea730ffb..4b665a3b630f8bf9e972b5a49c3bbb728d9d362d 100644 --- a/drivers/media/platform/samsung/s5p-jpeg/jpeg-core.h +++ b/drivers/media/platform/samsung/s5p-jpeg/jpeg-core.h @@ -11,6 +11,7 @@ #define JPEG_CORE_H_ #include +#include #include #include #include @@ -36,17 +37,6 @@ #define EXYNOS3250_IRQ_TIMEOUT 0x10000000 -/* a selection of JPEG markers */ -#define JPEG_MARKER_TEM 0x01 -#define JPEG_MARKER_SOF0 0xc0 -#define JPEG_MARKER_DHT 0xc4 -#define JPEG_MARKER_RST 0xd0 -#define JPEG_MARKER_SOI 0xd8 -#define JPEG_MARKER_EOI 0xd9 -#define JPEG_MARKER_SOS 0xda -#define JPEG_MARKER_DQT 0xdb -#define JPEG_MARKER_DHP 0xde - /* Flags that indicate a format can be used for capture/output */ #define SJPEG_FMT_FLAG_ENC_CAPTURE (1 << 0) #define SJPEG_FMT_FLAG_ENC_OUTPUT (1 << 1) diff --git a/drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.c b/drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.c index 45ade7210d26fccbccb29aa38152ff01e052d201..5dc1f908b49bd6d07fecb4fa13d3caa5cbfd5c6c 100644 --- a/drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.c +++ b/drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.c @@ -16,8 +16,10 @@ #include #include #include +#include #include #include +#include #include #include #include @@ -135,7 +137,7 @@ static void channel_swdemux_tsklet(struct tasklet_struct *t) static int c8sectpfe_start_feed(struct dvb_demux_feed *dvbdmxfeed) { struct dvb_demux *demux = dvbdmxfeed->demux; - struct stdemux *stdemux = (struct stdemux *)demux->priv; + struct stdemux *stdemux = demux->priv; struct c8sectpfei *fei = stdemux->c8sectpfei; struct channel_info *channel; u32 tmp; @@ -256,7 +258,7 @@ static int c8sectpfe_stop_feed(struct dvb_demux_feed *dvbdmxfeed) { struct dvb_demux *demux = dvbdmxfeed->demux; - struct stdemux *stdemux = (struct stdemux *)demux->priv; + struct stdemux *stdemux = demux->priv; struct c8sectpfei *fei = stdemux->c8sectpfei; struct channel_info *channel; int idlereq; @@ -812,30 +814,23 @@ static int c8sectpfe_probe(struct platform_device *pdev) } of_node_put(i2c_bus); - tsin->rst_gpio = of_get_named_gpio(child, "reset-gpios", 0); - - ret = gpio_is_valid(tsin->rst_gpio); - if (!ret) { - dev_err(dev, - "reset gpio for tsin%d not valid (gpio=%d)\n", - tsin->tsin_id, tsin->rst_gpio); - ret = -EINVAL; - goto err_node_put; - } - - ret = devm_gpio_request_one(dev, tsin->rst_gpio, - GPIOF_OUT_INIT_LOW, "NIM reset"); + /* Acquire reset GPIO and activate it */ + tsin->rst_gpio = devm_fwnode_gpiod_get(dev, + of_fwnode_handle(child), + "reset", GPIOD_OUT_HIGH, + "NIM reset"); + ret = PTR_ERR_OR_ZERO(tsin->rst_gpio); if (ret && ret != -EBUSY) { - dev_err(dev, "Can't request tsin%d reset gpio\n" - , fei->channel_data[index]->tsin_id); + dev_err(dev, "Can't request tsin%d reset gpio\n", + fei->channel_data[index]->tsin_id); goto err_node_put; } if (!ret) { - /* toggle reset lines */ - gpio_direction_output(tsin->rst_gpio, 0); + /* wait for the chip to reset */ usleep_range(3500, 5000); - gpio_direction_output(tsin->rst_gpio, 1); + /* release the reset line */ + gpiod_set_value_cansleep(tsin->rst_gpio, 0); usleep_range(3000, 5000); } @@ -1173,7 +1168,7 @@ MODULE_DEVICE_TABLE(of, c8sectpfe_match); static struct platform_driver c8sectpfe_driver = { .driver = { .name = "c8sectpfe", - .of_match_table = of_match_ptr(c8sectpfe_match), + .of_match_table = c8sectpfe_match, }, .probe = c8sectpfe_probe, .remove_new = c8sectpfe_remove, diff --git a/drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.h b/drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.h index c9d6021904cd7ec9c70d294324b6f13a8e53a7d5..bf377cc82225d9e923f54edde43cb0cc4462a90f 100644 --- a/drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.h +++ b/drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.h @@ -16,6 +16,8 @@ #define C8SECTPFE_MAX_TSIN_CHAN 8 +struct gpio_desc; + struct channel_info { int tsin_id; @@ -25,7 +27,7 @@ struct channel_info { int i2c; int dvb_card; - int rst_gpio; + struct gpio_desc *rst_gpio; struct i2c_adapter *i2c_adapter; struct i2c_adapter *tuner_i2c; diff --git a/drivers/media/platform/st/sti/hva/hva-h264.c b/drivers/media/platform/st/sti/hva/hva-h264.c index 98cb00d2d868cd1716a461201d9b3f59669435f9..196e631fa4b81faae4b657c4cb81f9ed92d6772b 100644 --- a/drivers/media/platform/st/sti/hva/hva-h264.c +++ b/drivers/media/platform/st/sti/hva/hva-h264.c @@ -591,7 +591,7 @@ static int hva_h264_prepare_task(struct hva_ctx *pctx, { struct hva_dev *hva = ctx_to_hdev(pctx); struct device *dev = ctx_to_dev(pctx); - struct hva_h264_ctx *ctx = (struct hva_h264_ctx *)pctx->priv; + struct hva_h264_ctx *ctx = pctx->priv; struct hva_buffer *seq_info = ctx->seq_info; struct hva_buffer *fwd_ref_frame = ctx->ref_frame; struct hva_buffer *loc_rec_frame = ctx->rec_frame; @@ -984,7 +984,7 @@ static int hva_h264_open(struct hva_ctx *pctx) static int hva_h264_close(struct hva_ctx *pctx) { - struct hva_h264_ctx *ctx = (struct hva_h264_ctx *)pctx->priv; + struct hva_h264_ctx *ctx = pctx->priv; struct device *dev = ctx_to_dev(pctx); if (ctx->seq_info) @@ -1007,8 +1007,8 @@ static int hva_h264_close(struct hva_ctx *pctx) static int hva_h264_encode(struct hva_ctx *pctx, struct hva_frame *frame, struct hva_stream *stream) { - struct hva_h264_ctx *ctx = (struct hva_h264_ctx *)pctx->priv; - struct hva_h264_task *task = (struct hva_h264_task *)ctx->task->vaddr; + struct hva_h264_ctx *ctx = pctx->priv; + struct hva_h264_task *task = ctx->task->vaddr; u32 stuffing_bytes = 0; int ret = 0; diff --git a/drivers/media/platform/verisilicon/Makefile b/drivers/media/platform/verisilicon/Makefile index ebd5ede7bef756c129d0c24a0e515224b3fc79fc..6ad2ef885920be35450d24d209d719de2eb8ac09 100644 --- a/drivers/media/platform/verisilicon/Makefile +++ b/drivers/media/platform/verisilicon/Makefile @@ -18,6 +18,9 @@ hantro-vpu-y += \ rockchip_vpu2_hw_h264_dec.o \ rockchip_vpu2_hw_mpeg2_dec.o \ rockchip_vpu2_hw_vp8_dec.o \ + rockchip_vpu981_hw_av1_dec.o \ + rockchip_av1_filmgrain.o \ + rockchip_av1_entropymode.o \ hantro_jpeg.o \ hantro_h264.o \ hantro_hevc.o \ diff --git a/drivers/media/platform/verisilicon/hantro.h b/drivers/media/platform/verisilicon/hantro.h index 2989ebc631cc06b798e61bc606764254ba142a54..6523ffb7488124f821c6f6c52c707f36fd9e09a2 100644 --- a/drivers/media/platform/verisilicon/hantro.h +++ b/drivers/media/platform/verisilicon/hantro.h @@ -38,6 +38,7 @@ struct hantro_postproc_ops; #define HANTRO_H264_DECODER BIT(18) #define HANTRO_HEVC_DECODER BIT(19) #define HANTRO_VP9_DECODER BIT(20) +#define HANTRO_AV1_DECODER BIT(21) #define HANTRO_DECODERS 0xffff0000 /** @@ -111,6 +112,7 @@ struct hantro_variant { * @HANTRO_MODE_VP8_DEC: VP8 decoder. * @HANTRO_MODE_HEVC_DEC: HEVC decoder. * @HANTRO_MODE_VP9_DEC: VP9 decoder. + * @HANTRO_MODE_AV1_DEC: AV1 decoder */ enum hantro_codec_mode { HANTRO_MODE_NONE = -1, @@ -120,6 +122,7 @@ enum hantro_codec_mode { HANTRO_MODE_VP8_DEC, HANTRO_MODE_HEVC_DEC, HANTRO_MODE_VP9_DEC, + HANTRO_MODE_AV1_DEC, }; /* @@ -228,6 +231,8 @@ struct hantro_dev { * @ctrl_handler: Control handler used to register controls. * @jpeg_quality: User-specified JPEG compression quality. * @bit_depth: Bit depth of current frame + * @need_postproc: Set to true if the bitstream features require to + * use the post-processor. * * @codec_ops: Set of operations related to codec mode. * @postproc: Post-processing context. @@ -237,6 +242,7 @@ struct hantro_dev { * @vp8_dec: VP8-decoding context. * @hevc_dec: HEVC-decoding context. * @vp9_dec: VP9-decoding context. + * @av1_dec: AV1-decoding context. */ struct hantro_ctx { struct hantro_dev *dev; @@ -257,6 +263,7 @@ struct hantro_ctx { const struct hantro_codec_ops *codec_ops; struct hantro_postproc_ctx postproc; + bool need_postproc; /* Specific for particular codec modes. */ union { @@ -265,6 +272,7 @@ struct hantro_ctx { struct hantro_vp8_dec_hw_ctx vp8_dec; struct hantro_hevc_dec_hw_ctx hevc_dec; struct hantro_vp9_dec_hw_ctx vp9_dec; + struct hantro_av1_dec_hw_ctx av1_dec; }; }; diff --git a/drivers/media/platform/verisilicon/hantro_drv.c b/drivers/media/platform/verisilicon/hantro_drv.c index 09c74a573ddb50e72e826b982eb167fd1b963fc6..c0a368bacf8803d9f2dac8b541c8634d48a1ab03 100644 --- a/drivers/media/platform/verisilicon/hantro_drv.c +++ b/drivers/media/platform/verisilicon/hantro_drv.c @@ -275,7 +275,13 @@ static int hantro_try_ctrl(struct v4l2_ctrl *ctrl) /* We only support profile 0 */ if (dec_params->profile != 0) return -EINVAL; + } else if (ctrl->id == V4L2_CID_STATELESS_AV1_SEQUENCE) { + const struct v4l2_ctrl_av1_sequence *sequence = ctrl->p_new.p_av1_sequence; + + if (sequence->bit_depth != 8 && sequence->bit_depth != 10) + return -EINVAL; } + return 0; } @@ -313,7 +319,7 @@ static int hantro_vp9_s_ctrl(struct v4l2_ctrl *ctrl) if (ctx->bit_depth == bit_depth) return 0; - return hantro_reset_raw_fmt(ctx, bit_depth); + return hantro_reset_raw_fmt(ctx, bit_depth, HANTRO_AUTO_POSTPROC); } default: return -EINVAL; @@ -337,7 +343,37 @@ static int hantro_hevc_s_ctrl(struct v4l2_ctrl *ctrl) if (ctx->bit_depth == bit_depth) return 0; - return hantro_reset_raw_fmt(ctx, bit_depth); + return hantro_reset_raw_fmt(ctx, bit_depth, HANTRO_AUTO_POSTPROC); + } + default: + return -EINVAL; + } + + return 0; +} + +static int hantro_av1_s_ctrl(struct v4l2_ctrl *ctrl) +{ + struct hantro_ctx *ctx; + + ctx = container_of(ctrl->handler, + struct hantro_ctx, ctrl_handler); + + switch (ctrl->id) { + case V4L2_CID_STATELESS_AV1_SEQUENCE: + { + int bit_depth = ctrl->p_new.p_av1_sequence->bit_depth; + bool need_postproc = HANTRO_AUTO_POSTPROC; + + if (ctrl->p_new.p_av1_sequence->flags + & V4L2_AV1_SEQUENCE_FLAG_FILM_GRAIN_PARAMS_PRESENT) + need_postproc = HANTRO_FORCE_POSTPROC; + + if (ctx->bit_depth == bit_depth && + ctx->need_postproc == need_postproc) + return 0; + + return hantro_reset_raw_fmt(ctx, bit_depth, need_postproc); } default: return -EINVAL; @@ -363,6 +399,11 @@ static const struct v4l2_ctrl_ops hantro_hevc_ctrl_ops = { .s_ctrl = hantro_hevc_s_ctrl, }; +static const struct v4l2_ctrl_ops hantro_av1_ctrl_ops = { + .try_ctrl = hantro_try_ctrl, + .s_ctrl = hantro_av1_s_ctrl, +}; + #define HANTRO_JPEG_ACTIVE_MARKERS (V4L2_JPEG_ACTIVE_MARKER_APP0 | \ V4L2_JPEG_ACTIVE_MARKER_COM | \ V4L2_JPEG_ACTIVE_MARKER_DQT | \ @@ -525,6 +566,28 @@ static const struct hantro_ctrl controls[] = { .cfg = { .id = V4L2_CID_STATELESS_VP9_COMPRESSED_HDR, }, + }, { + .codec = HANTRO_AV1_DECODER, + .cfg = { + .id = V4L2_CID_STATELESS_AV1_FRAME, + }, + }, { + .codec = HANTRO_AV1_DECODER, + .cfg = { + .id = V4L2_CID_STATELESS_AV1_TILE_GROUP_ENTRY, + .dims = { V4L2_AV1_MAX_TILE_COUNT }, + }, + }, { + .codec = HANTRO_AV1_DECODER, + .cfg = { + .id = V4L2_CID_STATELESS_AV1_SEQUENCE, + .ops = &hantro_av1_ctrl_ops, + }, + }, { + .codec = HANTRO_AV1_DECODER, + .cfg = { + .id = V4L2_CID_STATELESS_AV1_FILM_GRAIN, + }, }, }; @@ -656,6 +719,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-av1-vpu", .data = &rk3588_vpu981_variant, }, #endif #ifdef CONFIG_VIDEO_HANTRO_IMX8M { .compatible = "nxp,imx8mm-vpu-g1", .data = &imx8mm_vpu_g1_variant, }, diff --git a/drivers/media/platform/verisilicon/hantro_hevc.c b/drivers/media/platform/verisilicon/hantro_hevc.c index 9383fb7081f6c2cf3f5be2bfe401c352a7cc2613..2c14330bc5621e9886ae4cef4ff36e3ec0e5d147 100644 --- a/drivers/media/platform/verisilicon/hantro_hevc.c +++ b/drivers/media/platform/verisilicon/hantro_hevc.c @@ -109,7 +109,7 @@ static int tile_buffer_reallocate(struct hantro_ctx *ctx) &hevc_dec->tile_filter.dma, GFP_KERNEL); if (!hevc_dec->tile_filter.cpu) - goto err_free_tile_buffers; + return -ENOMEM; hevc_dec->tile_filter.size = size; size = (VERT_SAO_RAM_SIZE * height64 * (num_tile_cols - 1) * ctx->bit_depth) / 8; @@ -125,31 +125,26 @@ static int tile_buffer_reallocate(struct hantro_ctx *ctx) &hevc_dec->tile_bsd.dma, GFP_KERNEL); if (!hevc_dec->tile_bsd.cpu) - goto err_free_tile_buffers; + goto err_free_sao_buffers; hevc_dec->tile_bsd.size = size; hevc_dec->num_tile_cols_allocated = num_tile_cols; return 0; -err_free_tile_buffers: - if (hevc_dec->tile_filter.cpu) - dma_free_coherent(vpu->dev, hevc_dec->tile_filter.size, - hevc_dec->tile_filter.cpu, - hevc_dec->tile_filter.dma); - hevc_dec->tile_filter.cpu = NULL; - +err_free_sao_buffers: if (hevc_dec->tile_sao.cpu) dma_free_coherent(vpu->dev, hevc_dec->tile_sao.size, hevc_dec->tile_sao.cpu, hevc_dec->tile_sao.dma); hevc_dec->tile_sao.cpu = NULL; - if (hevc_dec->tile_bsd.cpu) - dma_free_coherent(vpu->dev, hevc_dec->tile_bsd.size, - hevc_dec->tile_bsd.cpu, - hevc_dec->tile_bsd.dma); - hevc_dec->tile_bsd.cpu = NULL; +err_free_tile_buffers: + if (hevc_dec->tile_filter.cpu) + dma_free_coherent(vpu->dev, hevc_dec->tile_filter.size, + hevc_dec->tile_filter.cpu, + hevc_dec->tile_filter.dma); + hevc_dec->tile_filter.cpu = NULL; return -ENOMEM; } diff --git a/drivers/media/platform/verisilicon/hantro_hw.h b/drivers/media/platform/verisilicon/hantro_hw.h index e83f0c523a302c88734df76877abf2572960a9da..7f33f7b07ce49b44aaac84aa12c66ff664e99570 100644 --- a/drivers/media/platform/verisilicon/hantro_hw.h +++ b/drivers/media/platform/verisilicon/hantro_hw.h @@ -15,6 +15,9 @@ #include #include +#include "rockchip_av1_entropymode.h" +#include "rockchip_av1_filmgrain.h" + #define DEC_8190_ALIGN_MASK 0x07U #define MB_DIM 16 @@ -35,6 +38,8 @@ #define NUM_REF_PICTURES (V4L2_HEVC_DPB_ENTRIES_NUM_MAX + 1) +#define AV1_MAX_FRAME_BUF_COUNT (V4L2_AV1_TOTAL_REFS_PER_FRAME + 1) + struct hantro_dev; struct hantro_ctx; struct hantro_buf; @@ -247,6 +252,84 @@ struct hantro_vp9_dec_hw_ctx { s16 feature_data[8][4]; }; +/** + * struct hantro_av1_dec_ctrls + * @sequence: AV1 Sequence + * @tile_group_entry: AV1 Tile Group entry + * @frame: AV1 Frame Header OBU + * @film_grain: AV1 Film Grain + */ +struct hantro_av1_dec_ctrls { + const struct v4l2_ctrl_av1_sequence *sequence; + const struct v4l2_ctrl_av1_tile_group_entry *tile_group_entry; + const struct v4l2_ctrl_av1_frame *frame; + const struct v4l2_ctrl_av1_film_grain *film_grain; +}; + +struct hantro_av1_frame_ref { + int width; + int height; + int mi_cols; + int mi_rows; + u64 timestamp; + enum v4l2_av1_frame_type frame_type; + bool used; + u32 order_hint; + u32 order_hints[V4L2_AV1_TOTAL_REFS_PER_FRAME]; + struct vb2_v4l2_buffer *vb2_ref; +}; + +/** + * struct hantro_av1_dec_hw_ctx + * @db_data_col: db tile col data buffer + * @db_ctrl_col: db tile col ctrl buffer + * @cdef_col: cdef tile col buffer + * @sr_col: sr tile col buffer + * @lr_col: lr tile col buffer + * @global_model: global model buffer + * @tile_info: tile info buffer + * @segment: segmentation info buffer + * @film_grain: film grain buffer + * @prob_tbl: probability table + * @prob_tbl_out: probability table output + * @tile_buf: tile buffer + * @ctrls: V4L2 controls attached to a run + * @frame_refs: reference frames info slots + * @ref_frame_sign_bias: array of sign bias + * @num_tile_cols_allocated: number of allocated tiles + * @cdfs: current probabilities structure + * @cdfs_ndvc: current mv probabilities structure + * @default_cdfs: default probabilities structure + * @default_cdfs_ndvc: default mv probabilties structure + * @cdfs_last: stored probabilities structures + * @cdfs_last_ndvc: stored mv probabilities structures + * @current_frame_index: index of the current in frame_refs array + */ +struct hantro_av1_dec_hw_ctx { + struct hantro_aux_buf db_data_col; + struct hantro_aux_buf db_ctrl_col; + struct hantro_aux_buf cdef_col; + struct hantro_aux_buf sr_col; + struct hantro_aux_buf lr_col; + struct hantro_aux_buf global_model; + struct hantro_aux_buf tile_info; + struct hantro_aux_buf segment; + struct hantro_aux_buf film_grain; + struct hantro_aux_buf prob_tbl; + struct hantro_aux_buf prob_tbl_out; + struct hantro_aux_buf tile_buf; + struct hantro_av1_dec_ctrls ctrls; + struct hantro_av1_frame_ref frame_refs[AV1_MAX_FRAME_BUF_COUNT]; + u32 ref_frame_sign_bias[V4L2_AV1_TOTAL_REFS_PER_FRAME]; + unsigned int num_tile_cols_allocated; + struct av1cdfs *cdfs; + struct mvcdfs *cdfs_ndvc; + struct av1cdfs default_cdfs; + struct mvcdfs default_cdfs_ndvc; + struct av1cdfs cdfs_last[NUM_REF_FRAMES]; + struct mvcdfs cdfs_last_ndvc[NUM_REF_FRAMES]; + int current_frame_index; +}; /** * struct hantro_postproc_ctx * @@ -320,11 +403,13 @@ extern const struct hantro_variant rk3328_vpu_variant; extern const struct hantro_variant rk3399_vpu_variant; extern const struct hantro_variant rk3568_vepu_variant; extern const struct hantro_variant rk3568_vpu_variant; +extern const struct hantro_variant rk3588_vpu981_variant; extern const struct hantro_variant sama5d4_vdec_variant; extern const struct hantro_variant sunxi_vpu_variant; extern const struct hantro_postproc_ops hantro_g1_postproc_ops; extern const struct hantro_postproc_ops hantro_g2_postproc_ops; +extern const struct hantro_postproc_ops rockchip_vpu981_postproc_ops; extern const u32 hantro_vp8_dec_mc_filter[8][6]; @@ -361,6 +446,10 @@ void hantro_hevc_ref_init(struct hantro_ctx *ctx); dma_addr_t hantro_hevc_get_ref_buf(struct hantro_ctx *ctx, s32 poc); int hantro_hevc_add_ref_buf(struct hantro_ctx *ctx, int poc, dma_addr_t addr); +int rockchip_vpu981_av1_dec_init(struct hantro_ctx *ctx); +void rockchip_vpu981_av1_dec_exit(struct hantro_ctx *ctx); +int rockchip_vpu981_av1_dec_run(struct hantro_ctx *ctx); +void rockchip_vpu981_av1_dec_done(struct hantro_ctx *ctx); static inline unsigned short hantro_vp9_num_sbs(unsigned short dimension) { @@ -417,6 +506,19 @@ hantro_hevc_mv_size(unsigned int width, unsigned int height) return width * height / 16; } +static inline unsigned short hantro_av1_num_sbs(unsigned short dimension) +{ + return DIV_ROUND_UP(dimension, 64); +} + +static inline size_t +hantro_av1_mv_size(unsigned int width, unsigned int height) +{ + size_t num_sbs = hantro_av1_num_sbs(width) * hantro_av1_num_sbs(height); + + return ALIGN(num_sbs * 384, 16) * 2 + 512; +} + int hantro_g1_mpeg2_dec_run(struct hantro_ctx *ctx); int rockchip_vpu2_mpeg2_dec_run(struct hantro_ctx *ctx); void hantro_mpeg2_dec_copy_qtable(u8 *qtable, diff --git a/drivers/media/platform/verisilicon/hantro_postproc.c b/drivers/media/platform/verisilicon/hantro_postproc.c index 6437423ccf3a9e973d0adf51729351e72029bd4c..c977d64105b183fa48850283ee576e3df61bed63 100644 --- a/drivers/media/platform/verisilicon/hantro_postproc.c +++ b/drivers/media/platform/verisilicon/hantro_postproc.c @@ -57,6 +57,10 @@ bool hantro_needs_postproc(const struct hantro_ctx *ctx, { if (ctx->is_encoder) return false; + + if (ctx->need_postproc) + return true; + return fmt->postprocessed; } @@ -197,7 +201,7 @@ int hantro_postproc_alloc(struct hantro_ctx *ctx) unsigned int i, buf_size; /* this should always pick native format */ - fmt = hantro_get_default_fmt(ctx, false, ctx->bit_depth); + fmt = hantro_get_default_fmt(ctx, false, ctx->bit_depth, HANTRO_AUTO_POSTPROC); if (!fmt) return -EINVAL; v4l2_fill_pixfmt_mp(&pix_mp, fmt->fourcc, ctx->src_fmt.width, @@ -213,6 +217,9 @@ int hantro_postproc_alloc(struct hantro_ctx *ctx) else if (ctx->vpu_src_fmt->fourcc == V4L2_PIX_FMT_HEVC_SLICE) buf_size += hantro_hevc_mv_size(pix_mp.width, pix_mp.height); + else if (ctx->vpu_src_fmt->fourcc == V4L2_PIX_FMT_AV1_FRAME) + buf_size += hantro_av1_mv_size(pix_mp.width, + pix_mp.height); for (i = 0; i < num_buffers; ++i) { struct hantro_aux_buf *priv = &ctx->postproc.dec_q[i]; diff --git a/drivers/media/platform/verisilicon/hantro_v4l2.c b/drivers/media/platform/verisilicon/hantro_v4l2.c index 61cfaaf4e927b35a81e55ccae6e2d4b8b2f13dd5..e871c078dd59eea7c77a96bcc2f4bdc151a5940c 100644 --- a/drivers/media/platform/verisilicon/hantro_v4l2.c +++ b/drivers/media/platform/verisilicon/hantro_v4l2.c @@ -31,15 +31,21 @@ #define HANTRO_DEFAULT_BIT_DEPTH 8 static int hantro_set_fmt_out(struct hantro_ctx *ctx, - struct v4l2_pix_format_mplane *pix_mp); + struct v4l2_pix_format_mplane *pix_mp, + bool need_postproc); static int hantro_set_fmt_cap(struct hantro_ctx *ctx, struct v4l2_pix_format_mplane *pix_mp); static const struct hantro_fmt * -hantro_get_formats(const struct hantro_ctx *ctx, unsigned int *num_fmts) +hantro_get_formats(const struct hantro_ctx *ctx, unsigned int *num_fmts, bool need_postproc) { const struct hantro_fmt *formats; + if (need_postproc) { + *num_fmts = 0; + return NULL; + } + if (ctx->is_encoder) { formats = ctx->dev->variant->enc_fmts; *num_fmts = ctx->dev->variant->num_enc_fmts; @@ -71,6 +77,7 @@ int hantro_get_format_depth(u32 fourcc) switch (fourcc) { case V4L2_PIX_FMT_P010: case V4L2_PIX_FMT_P010_4L4: + case V4L2_PIX_FMT_NV15_4L4: return 10; default: return 8; @@ -85,6 +92,10 @@ hantro_check_depth_match(const struct hantro_fmt *fmt, int bit_depth) if (!fmt->match_depth && !fmt->postprocessed) return true; + /* 0 means default depth, which is 8 */ + if (!bit_depth) + bit_depth = HANTRO_DEFAULT_BIT_DEPTH; + fmt_depth = hantro_get_format_depth(fmt->fourcc); /* @@ -103,7 +114,7 @@ hantro_find_format(const struct hantro_ctx *ctx, u32 fourcc) const struct hantro_fmt *formats; unsigned int i, num_fmts; - formats = hantro_get_formats(ctx, &num_fmts); + formats = hantro_get_formats(ctx, &num_fmts, HANTRO_AUTO_POSTPROC); for (i = 0; i < num_fmts; i++) if (formats[i].fourcc == fourcc) return &formats[i]; @@ -116,18 +127,28 @@ hantro_find_format(const struct hantro_ctx *ctx, u32 fourcc) } const struct hantro_fmt * -hantro_get_default_fmt(const struct hantro_ctx *ctx, bool bitstream, int bit_depth) +hantro_get_default_fmt(const struct hantro_ctx *ctx, bool bitstream, + int bit_depth, bool need_postproc) { const struct hantro_fmt *formats; unsigned int i, num_fmts; - formats = hantro_get_formats(ctx, &num_fmts); + formats = hantro_get_formats(ctx, &num_fmts, need_postproc); + for (i = 0; i < num_fmts; i++) { + if (bitstream == (formats[i].codec_mode != + HANTRO_MODE_NONE) && + hantro_check_depth_match(&formats[i], bit_depth)) + return &formats[i]; + } + + formats = hantro_get_postproc_formats(ctx, &num_fmts); for (i = 0; i < num_fmts; i++) { if (bitstream == (formats[i].codec_mode != HANTRO_MODE_NONE) && hantro_check_depth_match(&formats[i], bit_depth)) return &formats[i]; } + return NULL; } @@ -194,7 +215,7 @@ static int vidioc_enum_fmt(struct file *file, void *priv, */ skip_mode_none = capture == ctx->is_encoder; - formats = hantro_get_formats(ctx, &num_fmts); + formats = hantro_get_formats(ctx, &num_fmts, HANTRO_AUTO_POSTPROC); for (i = 0; i < num_fmts; i++) { bool mode_none = formats[i].codec_mode == HANTRO_MODE_NONE; fmt = &formats[i]; @@ -289,7 +310,7 @@ static int hantro_try_fmt(const struct hantro_ctx *ctx, fmt = hantro_find_format(ctx, pix_mp->pixelformat); if (!fmt) { - fmt = hantro_get_default_fmt(ctx, coded, HANTRO_DEFAULT_BIT_DEPTH); + fmt = hantro_get_default_fmt(ctx, coded, HANTRO_DEFAULT_BIT_DEPTH, HANTRO_AUTO_POSTPROC); pix_mp->pixelformat = fmt->fourcc; } @@ -328,6 +349,11 @@ static int hantro_try_fmt(const struct hantro_ctx *ctx, pix_mp->plane_fmt[0].sizeimage += hantro_hevc_mv_size(pix_mp->width, pix_mp->height); + else if (ctx->vpu_src_fmt->fourcc == V4L2_PIX_FMT_AV1_FRAME && + !hantro_needs_postproc(ctx, fmt)) + pix_mp->plane_fmt[0].sizeimage += + hantro_av1_mv_size(pix_mp->width, + pix_mp->height); } else if (!pix_mp->plane_fmt[0].sizeimage) { /* * For coded formats the application can specify @@ -373,7 +399,7 @@ hantro_reset_encoded_fmt(struct hantro_ctx *ctx) const struct hantro_fmt *vpu_fmt; struct v4l2_pix_format_mplane fmt; - vpu_fmt = hantro_get_default_fmt(ctx, true, HANTRO_DEFAULT_BIT_DEPTH); + vpu_fmt = hantro_get_default_fmt(ctx, true, HANTRO_DEFAULT_BIT_DEPTH, HANTRO_AUTO_POSTPROC); if (!vpu_fmt) return; @@ -383,17 +409,17 @@ hantro_reset_encoded_fmt(struct hantro_ctx *ctx) if (ctx->is_encoder) hantro_set_fmt_cap(ctx, &fmt); else - hantro_set_fmt_out(ctx, &fmt); + hantro_set_fmt_out(ctx, &fmt, HANTRO_AUTO_POSTPROC); } int -hantro_reset_raw_fmt(struct hantro_ctx *ctx, int bit_depth) +hantro_reset_raw_fmt(struct hantro_ctx *ctx, int bit_depth, bool need_postproc) { const struct hantro_fmt *raw_vpu_fmt; struct v4l2_pix_format_mplane raw_fmt, *encoded_fmt; int ret; - raw_vpu_fmt = hantro_get_default_fmt(ctx, false, bit_depth); + raw_vpu_fmt = hantro_get_default_fmt(ctx, false, bit_depth, need_postproc); if (!raw_vpu_fmt) return -EINVAL; @@ -408,12 +434,14 @@ hantro_reset_raw_fmt(struct hantro_ctx *ctx, int bit_depth) raw_fmt.width = encoded_fmt->width; raw_fmt.height = encoded_fmt->height; if (ctx->is_encoder) - ret = hantro_set_fmt_out(ctx, &raw_fmt); + ret = hantro_set_fmt_out(ctx, &raw_fmt, need_postproc); else ret = hantro_set_fmt_cap(ctx, &raw_fmt); - if (!ret) + if (!ret) { ctx->bit_depth = bit_depth; + ctx->need_postproc = need_postproc; + } return ret; } @@ -421,7 +449,7 @@ hantro_reset_raw_fmt(struct hantro_ctx *ctx, int bit_depth) void hantro_reset_fmts(struct hantro_ctx *ctx) { hantro_reset_encoded_fmt(ctx); - hantro_reset_raw_fmt(ctx, HANTRO_DEFAULT_BIT_DEPTH); + hantro_reset_raw_fmt(ctx, HANTRO_DEFAULT_BIT_DEPTH, HANTRO_AUTO_POSTPROC); } static void @@ -468,7 +496,8 @@ hantro_update_requires_hold_capture_buf(struct hantro_ctx *ctx, u32 fourcc) } static int hantro_set_fmt_out(struct hantro_ctx *ctx, - struct v4l2_pix_format_mplane *pix_mp) + struct v4l2_pix_format_mplane *pix_mp, + bool need_postproc) { struct vb2_queue *vq; int ret; @@ -521,7 +550,9 @@ static int hantro_set_fmt_out(struct hantro_ctx *ctx, * changes to the raw format. */ if (!ctx->is_encoder) - hantro_reset_raw_fmt(ctx, hantro_get_format_depth(pix_mp->pixelformat)); + hantro_reset_raw_fmt(ctx, + hantro_get_format_depth(pix_mp->pixelformat), + need_postproc); /* Colorimetry information are always propagated. */ ctx->dst_fmt.colorspace = pix_mp->colorspace; @@ -584,7 +615,7 @@ static int hantro_set_fmt_cap(struct hantro_ctx *ctx, * changes to the raw format. */ if (ctx->is_encoder) - hantro_reset_raw_fmt(ctx, HANTRO_DEFAULT_BIT_DEPTH); + hantro_reset_raw_fmt(ctx, HANTRO_DEFAULT_BIT_DEPTH, HANTRO_AUTO_POSTPROC); /* Colorimetry information are always propagated. */ ctx->src_fmt.colorspace = pix_mp->colorspace; @@ -604,7 +635,7 @@ static int hantro_set_fmt_cap(struct hantro_ctx *ctx, static int vidioc_s_fmt_out_mplane(struct file *file, void *priv, struct v4l2_format *f) { - return hantro_set_fmt_out(fh_to_ctx(priv), &f->fmt.pix_mp); + return hantro_set_fmt_out(fh_to_ctx(priv), &f->fmt.pix_mp, HANTRO_AUTO_POSTPROC); } static int diff --git a/drivers/media/platform/verisilicon/hantro_v4l2.h b/drivers/media/platform/verisilicon/hantro_v4l2.h index 9ea2fef57dcd99ede930428339bd373d1aa27062..fca7e3a690e55f7a1232d4e97d695298bdf0de54 100644 --- a/drivers/media/platform/verisilicon/hantro_v4l2.h +++ b/drivers/media/platform/verisilicon/hantro_v4l2.h @@ -18,13 +18,17 @@ #include "hantro.h" +#define HANTRO_FORCE_POSTPROC true +#define HANTRO_AUTO_POSTPROC false + extern const struct v4l2_ioctl_ops hantro_ioctl_ops; extern const struct vb2_ops hantro_queue_ops; -int hantro_reset_raw_fmt(struct hantro_ctx *ctx, int bit_depth); +int hantro_reset_raw_fmt(struct hantro_ctx *ctx, int bit_depth, bool need_postproc); void hantro_reset_fmts(struct hantro_ctx *ctx); int hantro_get_format_depth(u32 fourcc); const struct hantro_fmt * -hantro_get_default_fmt(const struct hantro_ctx *ctx, bool bitstream, int bit_depth); +hantro_get_default_fmt(const struct hantro_ctx *ctx, bool bitstream, + int bit_depth, bool need_postproc); #endif /* HANTRO_V4L2_H_ */ diff --git a/drivers/media/platform/verisilicon/rockchip_av1_entropymode.c b/drivers/media/platform/verisilicon/rockchip_av1_entropymode.c new file mode 100644 index 0000000000000000000000000000000000000000..b1ae72ad675e6159951a278f0eb588a5cd479299 --- /dev/null +++ b/drivers/media/platform/verisilicon/rockchip_av1_entropymode.c @@ -0,0 +1,4424 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2016, Alliance for Open Media. All rights reserved + * + * This source code is subject to the terms of the BSD 2 Clause License and + * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License + * was not distributed with this source code in the LICENSE file, you can + * obtain it at www.aomedia.org/license/software. If the Alliance for Open + * Media Patent License 1.0 was not distributed with this source code in the + * PATENTS file, you can obtain it at www.aomedia.org/license/patent. + */ + +#include "hantro.h" +#include "rockchip_av1_entropymode.h" + +#define AOM_ICDF ICDF +#define AOM_CDF2(a0) AOM_ICDF(a0) +#define AOM_CDF3(a0, a1) \ + AOM_ICDF(a0), AOM_ICDF(a1) +#define AOM_CDF4(a0, a1, a2) \ + AOM_ICDF(a0), AOM_ICDF(a1), AOM_ICDF(a2) +#define AOM_CDF5(a0, a1, a2, a3) \ + AOM_ICDF(a0), AOM_ICDF(a1), AOM_ICDF(a2), AOM_ICDF(a3) +#define AOM_CDF6(a0, a1, a2, a3, a4) \ + AOM_ICDF(a0), AOM_ICDF(a1), AOM_ICDF(a2), AOM_ICDF(a3), AOM_ICDF(a4) +#define AOM_CDF7(a0, a1, a2, a3, a4, a5) \ + AOM_ICDF(a0), AOM_ICDF(a1), AOM_ICDF(a2), \ + AOM_ICDF(a3), AOM_ICDF(a4), AOM_ICDF(a5) +#define AOM_CDF8(a0, a1, a2, a3, a4, a5, a6) \ + AOM_ICDF(a0), AOM_ICDF(a1), AOM_ICDF(a2), \ + AOM_ICDF(a3), AOM_ICDF(a4), AOM_ICDF(a5), AOM_ICDF(a6) +#define AOM_CDF9(a0, a1, a2, a3, a4, a5, a6, a7) \ + AOM_ICDF(a0), AOM_ICDF(a1), AOM_ICDF(a2), AOM_ICDF(a3), \ + AOM_ICDF(a4), AOM_ICDF(a5), AOM_ICDF(a6), AOM_ICDF(a7) +#define AOM_CDF10(a0, a1, a2, a3, a4, a5, a6, a7, a8) \ + AOM_ICDF(a0), AOM_ICDF(a1), AOM_ICDF(a2), AOM_ICDF(a3), \ + AOM_ICDF(a4), AOM_ICDF(a5), AOM_ICDF(a6), AOM_ICDF(a7), AOM_ICDF(a8) +#define AOM_CDF11(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9) \ + AOM_ICDF(a0), AOM_ICDF(a1), AOM_ICDF(a2), AOM_ICDF(a3), AOM_ICDF(a4), \ + AOM_ICDF(a5), AOM_ICDF(a6), AOM_ICDF(a7), AOM_ICDF(a8), AOM_ICDF(a9) +#define AOM_CDF12(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) \ + AOM_ICDF(a0), AOM_ICDF(a1), AOM_ICDF(a2), AOM_ICDF(a3), AOM_ICDF(a4), AOM_ICDF(a5), \ + AOM_ICDF(a6), AOM_ICDF(a7), AOM_ICDF(a8), AOM_ICDF(a9), AOM_ICDF(a10) +#define AOM_CDF13(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11) \ + AOM_ICDF(a0), AOM_ICDF(a1), AOM_ICDF(a2), AOM_ICDF(a3), AOM_ICDF(a4), AOM_ICDF(a5), \ + AOM_ICDF(a6), AOM_ICDF(a7), AOM_ICDF(a8), AOM_ICDF(a9), AOM_ICDF(a10), AOM_ICDF(a11) +#define AOM_CDF14(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12) \ + AOM_ICDF(a0), AOM_ICDF(a1), AOM_ICDF(a2), AOM_ICDF(a3), AOM_ICDF(a4), \ + AOM_ICDF(a5), AOM_ICDF(a6), AOM_ICDF(a7), AOM_ICDF(a8), AOM_ICDF(a9), \ + AOM_ICDF(a10), AOM_ICDF(a11), AOM_ICDF(a12) +#define AOM_CDF15(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13) \ + AOM_ICDF(a0), AOM_ICDF(a1), AOM_ICDF(a2), AOM_ICDF(a3), AOM_ICDF(a4), \ + AOM_ICDF(a5), AOM_ICDF(a6), AOM_ICDF(a7), AOM_ICDF(a8), AOM_ICDF(a9), \ + AOM_ICDF(a10), AOM_ICDF(a11), AOM_ICDF(a12), AOM_ICDF(a13) +#define AOM_CDF16(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14) \ + AOM_ICDF(a0), AOM_ICDF(a1), AOM_ICDF(a2), AOM_ICDF(a3), AOM_ICDF(a4), \ + AOM_ICDF(a5), AOM_ICDF(a6), AOM_ICDF(a7), AOM_ICDF(a8), AOM_ICDF(a9), \ + AOM_ICDF(a10), AOM_ICDF(a11), AOM_ICDF(a12), AOM_ICDF(a13), AOM_ICDF(a14) + +static const u16 default_kf_y_mode_cdf + [KF_MODE_CONTEXTS][KF_MODE_CONTEXTS][CDF_SIZE(AV1_INTRA_MODES)] = { + { + { + AOM_CDF13(15588, 17027, 19338, 20218, 20682, 21110, + 21825, 23244, 24189, 28165, 29093, 30466) + }, + { + AOM_CDF13(12016, 18066, 19516, 20303, 20719, 21444, + 21888, 23032, 24434, 28658, 30172, 31409) + }, + { + AOM_CDF13(10052, 10771, 22296, 22788, 23055, 23239, + 24133, 25620, 26160, 29336, 29929, 31567) + }, + { + AOM_CDF13(14091, 15406, 16442, 18808, 19136, 19546, + 19998, 22096, 24746, 29585, 30958, 32462) + }, + { + AOM_CDF13(12122, 13265, 15603, 16501, 18609, 20033, + 22391, 25583, 26437, 30261, 31073, 32475) + } + }, + { + { + AOM_CDF13(10023, 19585, 20848, 21440, 21832, 22760, + 23089, 24023, 25381, 29014, 30482, 31436) + }, + { + AOM_CDF13(5983, 24099, 24560, 24886, 25066, 25795, + 25913, 26423, 27610, 29905, 31276, 31794) + }, + { + AOM_CDF13(7444, 12781, 20177, 20728, 21077, 21607, + 22170, 23405, 24469, 27915, 29090, 30492) + }, + { + AOM_CDF13(8537, 14689, 15432, 17087, 17408, 18172, + 18408, 19825, 24649, 29153, 31096, 32210) + }, + { + AOM_CDF13(7543, 14231, 15496, 16195, 17905, 20717, + 21984, 24516, 26001, 29675, 30981, 31994) + } + }, + { + { + AOM_CDF13(12613, 13591, 21383, 22004, 22312, 22577, + 23401, 25055, 25729, 29538, 30305, 32077) + }, + { + AOM_CDF13(9687, 13470, 18506, 19230, 19604, 20147, + 20695, 22062, 23219, 27743, 29211, 30907) + }, + { + AOM_CDF13(6183, 6505, 26024, 26252, 26366, 26434, + 27082, 28354, 28555, 30467, 30794, 32086) + }, + { + AOM_CDF13(10718, 11734, 14954, 17224, 17565, 17924, + 18561, 21523, 23878, 28975, 30287, 32252) + }, + { + AOM_CDF13(9194, 9858, 16501, 17263, 18424, 19171, + 21563, 25961, 26561, 30072, 30737, 32463) + } + }, + { + { + AOM_CDF13(12602, 14399, 15488, 18381, 18778, 19315, + 19724, 21419, 25060, 29696, 30917, 32409) + }, + { + AOM_CDF13(8203, 13821, 14524, 17105, 17439, 18131, + 18404, 19468, 25225, 29485, 31158, 32342) + }, + { + AOM_CDF13(8451, 9731, 15004, 17643, 18012, 18425, + 19070, 21538, 24605, 29118, 30078, 32018) + }, + { + AOM_CDF13(7714, 9048, 9516, 16667, 16817, 16994, + 17153, 18767, 26743, 30389, 31536, 32528) + }, + { + AOM_CDF13(8843, 10280, 11496, 15317, 16652, 17943, + 19108, 22718, 25769, 29953, 30983, 32485) + } + }, + { + { + AOM_CDF13(12578, 13671, 15979, 16834, 19075, 20913, + 22989, 25449, 26219, 30214, 31150, 32477) + }, + { + AOM_CDF13(9563, 13626, 15080, 15892, 17756, 20863, + 22207, 24236, 25380, 29653, 31143, 32277) + }, + { + AOM_CDF13(8356, 8901, 17616, 18256, 19350, 20106, + 22598, 25947, 26466, 29900, 30523, 32261) + }, + { + AOM_CDF13(10835, 11815, 13124, 16042, 17018, 18039, + 18947, 22753, 24615, 29489, 30883, 32482) + }, + { + AOM_CDF13(7618, 8288, 9859, 10509, 15386, 18657, + 22903, 28776, 29180, 31355, 31802, 32593) + } + } +}; + +static const u16 default_angle_delta_cdf[DIRECTIONAL_MODES] + [CDF_SIZE(2 * MAX_ANGLE_DELTA + 1)] = { + { AOM_CDF7(2180, 5032, 7567, 22776, 26989, 30217) }, + { AOM_CDF7(2301, 5608, 8801, 23487, 26974, 30330) }, + { AOM_CDF7(3780, 11018, 13699, 19354, 23083, 31286) }, + { AOM_CDF7(4581, 11226, 15147, 17138, 21834, 28397) }, + { AOM_CDF7(1737, 10927, 14509, 19588, 22745, 28823) }, + { AOM_CDF7(2664, 10176, 12485, 17650, 21600, 30495) }, + { AOM_CDF7(2240, 11096, 15453, 20341, 22561, 28917) }, + { AOM_CDF7(3605, 10428, 12459, 17676, 21244, 30655) } +}; + +static const u16 default_if_y_mode_cdf[BLOCK_SIZE_GROUPS][CDF_SIZE(AV1_INTRA_MODES)] = { + { + AOM_CDF13(22801, 23489, 24293, 24756, 25601, 26123, + 26606, 27418, 27945, 29228, 29685, 30349) + }, + { + AOM_CDF13(18673, 19845, 22631, 23318, 23950, 24649, + 25527, 27364, 28152, 29701, 29984, 30852) + }, + { + AOM_CDF13(19770, 20979, 23396, 23939, 24241, 24654, + 25136, 27073, 27830, 29360, 29730, 30659) + }, + { + AOM_CDF13(20155, 21301, 22838, 23178, 23261, 23533, + 23703, 24804, 25352, 26575, 27016, 28049) + } +}; + +static const u16 default_uv_mode_cdf[CFL_ALLOWED_TYPES] + [AV1_INTRA_MODES][CDF_SIZE(UV_INTRA_MODES)] = { + { + { + AOM_CDF13(22631, 24152, 25378, 25661, 25986, 26520, + 27055, 27923, 28244, 30059, 30941, 31961) + }, + { + AOM_CDF13(9513, 26881, 26973, 27046, 27118, 27664, + 27739, 27824, 28359, 29505, 29800, 31796) + }, + { + AOM_CDF13(9845, 9915, 28663, 28704, 28757, 28780, + 29198, 29822, 29854, 30764, 31777, 32029) + }, + { + AOM_CDF13(13639, 13897, 14171, 25331, 25606, 25727, + 25953, 27148, 28577, 30612, 31355, 32493) + }, + { + AOM_CDF13(9764, 9835, 9930, 9954, 25386, 27053, + 27958, 28148, 28243, 31101, 31744, 32363) + }, + { + AOM_CDF13(11825, 13589, 13677, 13720, 15048, 29213, + 29301, 29458, 29711, 31161, 31441, 32550) + }, + { + AOM_CDF13(14175, 14399, 16608, 16821, 17718, 17775, + 28551, 30200, 30245, 31837, 32342, 32667) + }, + { + AOM_CDF13(12885, 13038, 14978, 15590, 15673, 15748, + 16176, 29128, 29267, 30643, 31961, 32461) + }, + { + AOM_CDF13(12026, 13661, 13874, 15305, 15490, 15726, + 15995, 16273, 28443, 30388, 30767, 32416) + }, + { + AOM_CDF13(19052, 19840, 20579, 20916, 21150, 21467, + 21885, 22719, 23174, 28861, 30379, 32175) + }, + { + AOM_CDF13(18627, 19649, 20974, 21219, 21492, 21816, + 22199, 23119, 23527, 27053, 31397, 32148) + }, + { + AOM_CDF13(17026, 19004, 19997, 20339, 20586, 21103, + 21349, 21907, 22482, 25896, 26541, 31819) + }, + { + AOM_CDF13(12124, 13759, 14959, 14992, 15007, 15051, + 15078, 15166, 15255, 15753, 16039, 16606) + } + }, + { + { + AOM_CDF14(10407, 11208, 12900, 13181, 13823, 14175, + 14899, 15656, 15986, 20086, 20995, 22455, + 24212) + }, + { + AOM_CDF14(4532, 19780, 20057, 20215, 20428, 21071, + 21199, 21451, 22099, 24228, 24693, 27032, + 29472) + }, + { + AOM_CDF14(5273, 5379, 20177, 20270, 20385, 20439, + 20949, 21695, 21774, 23138, 24256, 24703, + 26679) + }, + { + AOM_CDF14(6740, 7167, 7662, 14152, 14536, 14785, + 15034, 16741, 18371, 21520, 22206, 23389, + 24182) + }, + { + AOM_CDF14(4987, 5368, 5928, 6068, 19114, 20315, 21857, + 22253, 22411, 24911, 25380, 26027, 26376) + }, + { + AOM_CDF14(5370, 6889, 7247, 7393, 9498, 21114, 21402, + 21753, 21981, 24780, 25386, 26517, 27176) + }, + { + AOM_CDF14(4816, 4961, 7204, 7326, 8765, 8930, 20169, + 20682, 20803, 23188, 23763, 24455, 24940) + }, + { + AOM_CDF14(6608, 6740, 8529, 9049, 9257, 9356, 9735, + 18827, 19059, 22336, 23204, 23964, 24793) + }, + { + AOM_CDF14(5998, 7419, 7781, 8933, 9255, 9549, 9753, + 10417, 18898, 22494, 23139, 24764, 25989) + }, + { + AOM_CDF14(10660, 11298, 12550, 12957, 13322, 13624, + 14040, 15004, 15534, 20714, 21789, 23443, + 24861) + }, + { + AOM_CDF14(10522, 11530, 12552, 12963, 13378, 13779, + 14245, 15235, 15902, 20102, 22696, 23774, + 25838) + }, + { + AOM_CDF14(10099, 10691, 12639, 13049, 13386, 13665, + 14125, 15163, 15636, 19676, 20474, 23519, + 25208) + }, + { + AOM_CDF14(3144, 5087, 7382, 7504, 7593, 7690, 7801, + 8064, 8232, 9248, 9875, 10521, 29048) + } + } +}; + +static const u16 default_partition_cdf[13][16] = { + { + AOM_CDF4(19132, 25510, 30392), AOM_CDF4(13928, 19855, 28540), + AOM_CDF4(12522, 23679, 28629), AOM_CDF4(9896, 18783, 25853), + AOM_CDF2(11570), AOM_CDF2(16855), AOM_CDF3(9413, 22581) + }, + { + AOM_CDF10(15597, 20929, 24571, 26706, 27664, 28821, 29601, 30571, 31902) + }, + { + AOM_CDF10(7925, 11043, 16785, 22470, 23971, 25043, 26651, 28701, 29834) + }, + { + AOM_CDF10(5414, 13269, 15111, 20488, 22360, 24500, 25537, 26336, 32117) + }, + { + AOM_CDF10(2662, 6362, 8614, 20860, 23053, 24778, 26436, 27829, 31171) + }, + { + AOM_CDF10(18462, 20920, 23124, 27647, 28227, 29049, 29519, 30178, 31544) + }, + { + AOM_CDF10(7689, 9060, 12056, 24992, 25660, 26182, 26951, 28041, 29052) + }, + { + AOM_CDF10(6015, 9009, 10062, 24544, 25409, 26545, 27071, 27526, 32047) + }, + { + AOM_CDF10(1394, 2208, 2796, 28614, 29061, 29466, 29840, 30185, 31899) + }, + { + AOM_CDF10(20137, 21547, 23078, 29566, 29837, 30261, 30524, 30892, 31724), + AOM_CDF8(27899, 28219, 28529, 32484, 32539, 32619, 32639) + }, + { + AOM_CDF10(6732, 7490, 9497, 27944, 28250, 28515, 28969, 29630, 30104), + AOM_CDF8(6607, 6990, 8268, 32060, 32219, 32338, 32371) + }, + { + AOM_CDF10(5945, 7663, 8348, 28683, 29117, 29749, 30064, 30298, 32238), + AOM_CDF8(5429, 6676, 7122, 32027, 32227, 32531, 32582) + }, + { + AOM_CDF10(870, 1212, 1487, 31198, 31394, 31574, 31743, 31881, 32332), + AOM_CDF8(711, 966, 1172, 32448, 32538, 32617, 32664) + }, +}; + +static const u16 default_intra_ext_tx0_cdf[EXTTX_SIZES][AV1_INTRA_MODES][8] = { + { + { AOM_CDF7(1535, 8035, 9461, 12751, 23467, 27825)}, + { AOM_CDF7(564, 3335, 9709, 10870, 18143, 28094)}, + { AOM_CDF7(672, 3247, 3676, 11982, 19415, 23127)}, + { AOM_CDF7(5279, 13885, 15487, 18044, 23527, 30252)}, + { AOM_CDF7(4423, 6074, 7985, 10416, 25693, 29298)}, + { AOM_CDF7(1486, 4241, 9460, 10662, 16456, 27694)}, + { AOM_CDF7(439, 2838, 3522, 6737, 18058, 23754)}, + { AOM_CDF7(1190, 4233, 4855, 11670, 20281, 24377)}, + { AOM_CDF7(1045, 4312, 8647, 10159, 18644, 29335)}, + { AOM_CDF7(202, 3734, 4747, 7298, 17127, 24016)}, + { AOM_CDF7(447, 4312, 6819, 8884, 16010, 23858)}, + { AOM_CDF7(277, 4369, 5255, 8905, 16465, 22271)}, + { AOM_CDF7(3409, 5436, 10599, 15599, 19687, 24040)}, + }, + { + { AOM_CDF7(1870, 13742, 14530, 16498, 23770, 27698)}, + { AOM_CDF7(326, 8796, 14632, 15079, 19272, 27486)}, + { AOM_CDF7(484, 7576, 7712, 14443, 19159, 22591)}, + { AOM_CDF7(1126, 15340, 15895, 17023, 20896, 30279)}, + { AOM_CDF7(655, 4854, 5249, 5913, 22099, 27138)}, + { AOM_CDF7(1299, 6458, 8885, 9290, 14851, 25497)}, + { AOM_CDF7(311, 5295, 5552, 6885, 16107, 22672)}, + { AOM_CDF7(883, 8059, 8270, 11258, 17289, 21549)}, + { AOM_CDF7(741, 7580, 9318, 10345, 16688, 29046)}, + { AOM_CDF7(110, 7406, 7915, 9195, 16041, 23329)}, + { AOM_CDF7(363, 7974, 9357, 10673, 15629, 24474)}, + { AOM_CDF7(153, 7647, 8112, 9936, 15307, 19996)}, + { AOM_CDF7(3511, 6332, 11165, 15335, 19323, 23594)}, + }, + { + { AOM_CDF7(4681, 9362, 14043, 18725, 23406, 28087)}, + { AOM_CDF7(4681, 9362, 14043, 18725, 23406, 28087)}, + { AOM_CDF7(4681, 9362, 14043, 18725, 23406, 28087)}, + { AOM_CDF7(4681, 9362, 14043, 18725, 23406, 28087)}, + { AOM_CDF7(4681, 9362, 14043, 18725, 23406, 28087)}, + { AOM_CDF7(4681, 9362, 14043, 18725, 23406, 28087)}, + { AOM_CDF7(4681, 9362, 14043, 18725, 23406, 28087)}, + { AOM_CDF7(4681, 9362, 14043, 18725, 23406, 28087)}, + { AOM_CDF7(4681, 9362, 14043, 18725, 23406, 28087)}, + { AOM_CDF7(4681, 9362, 14043, 18725, 23406, 28087)}, + { AOM_CDF7(4681, 9362, 14043, 18725, 23406, 28087)}, + { AOM_CDF7(4681, 9362, 14043, 18725, 23406, 28087)}, + { AOM_CDF7(4681, 9362, 14043, 18725, 23406, 28087)}, + }, + { + { AOM_CDF7(4681, 9362, 14043, 18725, 23406, 28087)}, + { AOM_CDF7(4681, 9362, 14043, 18725, 23406, 28087)}, + { AOM_CDF7(4681, 9362, 14043, 18725, 23406, 28087)}, + { AOM_CDF7(4681, 9362, 14043, 18725, 23406, 28087)}, + { AOM_CDF7(4681, 9362, 14043, 18725, 23406, 28087)}, + { AOM_CDF7(4681, 9362, 14043, 18725, 23406, 28087)}, + { AOM_CDF7(4681, 9362, 14043, 18725, 23406, 28087)}, + { AOM_CDF7(4681, 9362, 14043, 18725, 23406, 28087)}, + { AOM_CDF7(4681, 9362, 14043, 18725, 23406, 28087)}, + { AOM_CDF7(4681, 9362, 14043, 18725, 23406, 28087)}, + { AOM_CDF7(4681, 9362, 14043, 18725, 23406, 28087)}, + { AOM_CDF7(4681, 9362, 14043, 18725, 23406, 28087)}, + { AOM_CDF7(4681, 9362, 14043, 18725, 23406, 28087)}, + }, +}; + +static const u16 default_intra_ext_tx1_cdf[EXTTX_SIZES][AV1_INTRA_MODES][4] = { + { + { AOM_CDF5(6554, 13107, 19661, 26214)}, + { AOM_CDF5(6554, 13107, 19661, 26214)}, + { AOM_CDF5(6554, 13107, 19661, 26214)}, + { AOM_CDF5(6554, 13107, 19661, 26214)}, + { AOM_CDF5(6554, 13107, 19661, 26214)}, + { AOM_CDF5(6554, 13107, 19661, 26214)}, + { AOM_CDF5(6554, 13107, 19661, 26214)}, + { AOM_CDF5(6554, 13107, 19661, 26214)}, + { AOM_CDF5(6554, 13107, 19661, 26214)}, + { AOM_CDF5(6554, 13107, 19661, 26214)}, + { AOM_CDF5(6554, 13107, 19661, 26214)}, + { AOM_CDF5(6554, 13107, 19661, 26214)}, + { AOM_CDF5(6554, 13107, 19661, 26214)}, + }, + { + { AOM_CDF5(6554, 13107, 19661, 26214)}, + { AOM_CDF5(6554, 13107, 19661, 26214)}, + { AOM_CDF5(6554, 13107, 19661, 26214)}, + { AOM_CDF5(6554, 13107, 19661, 26214)}, + { AOM_CDF5(6554, 13107, 19661, 26214)}, + { AOM_CDF5(6554, 13107, 19661, 26214)}, + { AOM_CDF5(6554, 13107, 19661, 26214)}, + { AOM_CDF5(6554, 13107, 19661, 26214)}, + { AOM_CDF5(6554, 13107, 19661, 26214)}, + { AOM_CDF5(6554, 13107, 19661, 26214)}, + { AOM_CDF5(6554, 13107, 19661, 26214)}, + { AOM_CDF5(6554, 13107, 19661, 26214)}, + { AOM_CDF5(6554, 13107, 19661, 26214)}, + }, + { + { AOM_CDF5(1127, 12814, 22772, 27483)}, + { AOM_CDF5(145, 6761, 11980, 26667)}, + { AOM_CDF5(362, 5887, 11678, 16725)}, + { AOM_CDF5(385, 15213, 18587, 30693)}, + { AOM_CDF5(25, 2914, 23134, 27903)}, + { AOM_CDF5(60, 4470, 11749, 23991)}, + { AOM_CDF5(37, 3332, 14511, 21448)}, + { AOM_CDF5(157, 6320, 13036, 17439)}, + { AOM_CDF5(119, 6719, 12906, 29396)}, + { AOM_CDF5(47, 5537, 12576, 21499)}, + { AOM_CDF5(269, 6076, 11258, 23115)}, + { AOM_CDF5(83, 5615, 12001, 17228)}, + { AOM_CDF5(1968, 5556, 12023, 18547)}, + }, + { + { AOM_CDF5(6554, 13107, 19661, 26214)}, + { AOM_CDF5(6554, 13107, 19661, 26214)}, + { AOM_CDF5(6554, 13107, 19661, 26214)}, + { AOM_CDF5(6554, 13107, 19661, 26214)}, + { AOM_CDF5(6554, 13107, 19661, 26214)}, + { AOM_CDF5(6554, 13107, 19661, 26214)}, + { AOM_CDF5(6554, 13107, 19661, 26214)}, + { AOM_CDF5(6554, 13107, 19661, 26214)}, + { AOM_CDF5(6554, 13107, 19661, 26214)}, + { AOM_CDF5(6554, 13107, 19661, 26214)}, + { AOM_CDF5(6554, 13107, 19661, 26214)}, + { AOM_CDF5(6554, 13107, 19661, 26214)}, + { AOM_CDF5(6554, 13107, 19661, 26214)}, + }, +}; + +static const u16 default_inter_ext_tx_cdf[2][EXTTX_SIZES][EXT_TX_TYPES] = { + { + { + AOM_CDF16(4458, 5560, 7695, 9709, 13330, 14789, 17537, 20266, + 21504, 22848, 23934, 25474, 27727, 28915, 30631) + }, + { + AOM_CDF16(1645, 2573, 4778, 5711, 7807, 8622, 10522, 15357, 17674, + 20408, 22517, 25010, 27116, 28856, 30749) + }, + { + AOM_CDF16(2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384, + 18432, 20480, 22528, 24576, 26624, 28672, 30720) + }, + { + AOM_CDF16(2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384, + 18432, 20480, 22528, 24576, 26624, 28672, 30720) + }, + }, + { + { + AOM_CDF12(2731, 5461, 8192, 10923, 13653, 16384, 19115, 21845, + 24576, 27307, 30037), + AOM_CDF2(16384) + }, + { + AOM_CDF12(2731, 5461, 8192, 10923, 13653, 16384, 19115, 21845, + 24576, 27307, 30037), + AOM_CDF2(4167) + }, + { + AOM_CDF12(770, 2421, 5225, 12907, 15819, 18927, 21561, 24089, + 26595, 28526, 30529), + AOM_CDF2(1998) + }, + { + AOM_CDF12(2731, 5461, 8192, 10923, 13653, 16384, 19115, 21845, + 24576, 27307, 30037), + AOM_CDF2(748) + }, + } +}; + +static const u16 default_cfl_sign_cdf[CDF_SIZE(CFL_JOINT_SIGNS)] = { + AOM_CDF8(1418, 2123, 13340, 18405, 26972, 28343, 32294) +}; + +static const u16 default_cfl_alpha_cdf[CFL_ALPHA_CONTEXTS][CDF_SIZE(CFL_ALPHABET_SIZE)] = { + { + AOM_CDF16(7637, 20719, 31401, 32481, 32657, 32688, 32692, 32696, 32700, + 32704, 32708, 32712, 32716, 32720, 32724) + }, + { + AOM_CDF16(14365, 23603, 28135, 31168, 32167, 32395, 32487, 32573, + 32620, 32647, 32668, 32672, 32676, 32680, 32684) + }, + { + AOM_CDF16(11532, 22380, 28445, 31360, 32349, 32523, 32584, 32649, + 32673, 32677, 32681, 32685, 32689, 32693, 32697) + }, + { + AOM_CDF16(26990, 31402, 32282, 32571, 32692, 32696, 32700, 32704, + 32708, 32712, 32716, 32720, 32724, 32728, 32732) + }, + { + AOM_CDF16(17248, 26058, 28904, 30608, 31305, 31877, 32126, 32321, + 32394, 32464, 32516, 32560, 32576, 32593, 32622) + }, + { + AOM_CDF16(14738, 21678, 25779, 27901, 29024, 30302, 30980, 31843, + 32144, 32413, 32520, 32594, 32622, 32656, 32660) + } +}; + +static const u16 default_switchable_interp_cdf[SWITCHABLE_FILTER_CONTEXTS] + [CDF_SIZE(AV1_SWITCHABLE_FILTERS)] = { + { AOM_CDF3(31935, 32720) }, { AOM_CDF3(5568, 32719) }, + { AOM_CDF3(422, 2938) }, { AOM_CDF3(28244, 32608) }, + { AOM_CDF3(31206, 31953) }, { AOM_CDF3(4862, 32121) }, + { AOM_CDF3(770, 1152) }, { AOM_CDF3(20889, 25637) }, + { AOM_CDF3(31910, 32724) }, { AOM_CDF3(4120, 32712) }, + { AOM_CDF3(305, 2247) }, { AOM_CDF3(27403, 32636) }, + { AOM_CDF3(31022, 32009) }, { AOM_CDF3(2963, 32093) }, + { AOM_CDF3(601, 943) }, { AOM_CDF3(14969, 21398) } +}; + +static const u16 default_newmv_cdf[NEWMV_MODE_CONTEXTS][CDF_SIZE(2)] = { + { AOM_CDF2(24035) }, { AOM_CDF2(16630) }, { AOM_CDF2(15339) }, + { AOM_CDF2(8386) }, { AOM_CDF2(12222) }, { AOM_CDF2(4676) } +}; + +static const u16 default_zeromv_cdf[GLOBALMV_MODE_CONTEXTS][CDF_SIZE(2)] = { + { AOM_CDF2(2175) }, { AOM_CDF2(1054) } +}; + +static const u16 default_refmv_cdf[REFMV_MODE_CONTEXTS][CDF_SIZE(2)] = { + { AOM_CDF2(23974) }, { AOM_CDF2(24188) }, { AOM_CDF2(17848) }, + { AOM_CDF2(28622) }, { AOM_CDF2(24312) }, { AOM_CDF2(19923) } +}; + +static const u16 default_drl_cdf[DRL_MODE_CONTEXTS][CDF_SIZE(2)] = { + { AOM_CDF2(13104) }, { AOM_CDF2(24560) }, { AOM_CDF2(18945) } +}; + +static const u16 default_inter_compound_mode_cdf[AV1_INTER_MODE_CONTEXTS] + [CDF_SIZE(INTER_COMPOUND_MODES)] = { + { AOM_CDF8(7760, 13823, 15808, 17641, 19156, 20666, 26891) }, + { AOM_CDF8(10730, 19452, 21145, 22749, 24039, 25131, 28724) }, + { AOM_CDF8(10664, 20221, 21588, 22906, 24295, 25387, 28436) }, + { AOM_CDF8(13298, 16984, 20471, 24182, 25067, 25736, 26422) }, + { AOM_CDF8(18904, 23325, 25242, 27432, 27898, 28258, 30758) }, + { AOM_CDF8(10725, 17454, 20124, 22820, 24195, 25168, 26046) }, + { AOM_CDF8(17125, 24273, 25814, 27492, 28214, 28704, 30592) }, + { AOM_CDF8(13046, 23214, 24505, 25942, 27435, 28442, 29330) } +}; + +static const u16 default_interintra_cdf[BLOCK_SIZE_GROUPS][CDF_SIZE(2)] = { + { AOM_CDF2(16384) }, { AOM_CDF2(26887) }, { AOM_CDF2(27597) }, + { AOM_CDF2(30237) } +}; + +static const u16 default_interintra_mode_cdf[BLOCK_SIZE_GROUPS][CDF_SIZE(INTERINTRA_MODES)] = { + { AOM_CDF4(8192, 16384, 24576) }, + { AOM_CDF4(1875, 11082, 27332) }, + { AOM_CDF4(2473, 9996, 26388) }, + { AOM_CDF4(4238, 11537, 25926) } +}; + +static const u16 default_wedge_interintra_cdf[BLOCK_SIZES_ALL][CDF_SIZE(2)] = { + { AOM_CDF2(16384) }, { AOM_CDF2(16384) }, { AOM_CDF2(16384) }, + { AOM_CDF2(20036) }, { AOM_CDF2(24957) }, { AOM_CDF2(26704) }, + { AOM_CDF2(27530) }, { AOM_CDF2(29564) }, { AOM_CDF2(29444) }, + { AOM_CDF2(26872) }, { AOM_CDF2(16384) }, { AOM_CDF2(16384) }, + { AOM_CDF2(16384) }, { AOM_CDF2(16384) }, { AOM_CDF2(16384) }, + { AOM_CDF2(16384) }, { AOM_CDF2(16384) }, { AOM_CDF2(16384) }, + { AOM_CDF2(16384) }, { AOM_CDF2(16384) }, { AOM_CDF2(16384) }, + { AOM_CDF2(16384) } +}; + +static const u16 default_compound_type_cdf[BLOCK_SIZES_ALL][CDF_SIZE(COMPOUND_TYPES - 1)] = { + { AOM_CDF2(16384) }, { AOM_CDF2(16384) }, { AOM_CDF2(16384) }, + { AOM_CDF2(23431) }, + { AOM_CDF2(13171) }, { AOM_CDF2(11470) }, { AOM_CDF2(9770) }, + { AOM_CDF2(9100) }, + { AOM_CDF2(8233) }, { AOM_CDF2(6172) }, { AOM_CDF2(16384) }, + { AOM_CDF2(16384) }, + { AOM_CDF2(16384) }, { AOM_CDF2(16384) }, { AOM_CDF2(16384) }, + { AOM_CDF2(16384) }, + { AOM_CDF2(16384) }, { AOM_CDF2(16384) }, { AOM_CDF2(11820) }, + { AOM_CDF2(7701) }, + { AOM_CDF2(16384) }, { AOM_CDF2(16384) } +}; + +static const u16 default_wedge_idx_cdf[BLOCK_SIZES_ALL][CDF_SIZE(16)] = { + { + AOM_CDF16(2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384, + 18432, 20480, 22528, 24576, 26624, 28672, 30720) + }, + { + AOM_CDF16(2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384, + 18432, 20480, 22528, 24576, 26624, 28672, 30720) + }, + { + AOM_CDF16(2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384, + 18432, 20480, 22528, 24576, 26624, 28672, 30720) + }, + { + AOM_CDF16(2438, 4440, 6599, 8663, 11005, 12874, 15751, 18094, + 20359, 22362, 24127, 25702, 27752, 29450, 31171) + }, + { + AOM_CDF16(806, 3266, 6005, 6738, 7218, 7367, 7771, 14588, 16323, + 17367, 18452, 19422, 22839, 26127, 29629) + }, + { + AOM_CDF16(2779, 3738, 4683, 7213, 7775, 8017, 8655, 14357, 17939, + 21332, 24520, 27470, 29456, 30529, 31656) + }, + { + AOM_CDF16(1684, 3625, 5675, 7108, 9302, 11274, 14429, 17144, 19163, + 20961, 22884, 24471, 26719, 28714, 30877) + }, + { + AOM_CDF16(1142, 3491, 6277, 7314, 8089, 8355, 9023, 13624, 15369, + 16730, 18114, 19313, 22521, 26012, 29550) + }, + { + AOM_CDF16(2742, 4195, 5727, 8035, 8980, 9336, 10146, 14124, 17270, + 20533, 23434, 25972, 27944, 29570, 31416) + }, + { + AOM_CDF16(1727, 3948, 6101, 7796, 9841, 12344, 15766, 18944, 20638, + 22038, 23963, 25311, 26988, 28766, 31012) + }, + { + AOM_CDF16(2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384, 18432, + 20480, 22528, 24576, 26624, 28672, 30720) + }, + { + AOM_CDF16(2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384, 18432, + 20480, 22528, 24576, 26624, 28672, 30720) + }, + { + AOM_CDF16(2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384, 18432, + 20480, 22528, 24576, 26624, 28672, 30720) + }, + { + AOM_CDF16(2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384, 18432, + 20480, 22528, 24576, 26624, 28672, 30720) + }, + { + AOM_CDF16(2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384, 18432, + 20480, 22528, 24576, 26624, 28672, 30720) + }, + { + AOM_CDF16(2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384, 18432, + 20480, 22528, 24576, 26624, 28672, 30720) + }, + { + AOM_CDF16(2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384, 18432, + 20480, 22528, 24576, 26624, 28672, 30720) + }, + { + AOM_CDF16(2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384, 18432, + 20480, 22528, 24576, 26624, 28672, 30720) + }, + { + AOM_CDF16(154, 987, 1925, 2051, 2088, 2111, 2151, 23033, 23703, 24284, + 24985, 25684, 27259, 28883, 30911) + }, + { + AOM_CDF16(1135, 1322, 1493, 2635, 2696, 2737, 2770, 21016, 22935, + 25057, 27251, 29173, 30089, 30960, 31933) + }, + { + AOM_CDF16(2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384, 18432, + 20480, 22528, 24576, 26624, 28672, 30720) + }, + { + AOM_CDF16(2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384, 18432, + 20480, 22528, 24576, 26624, 28672, 30720) + } +}; + +static const u16 default_motion_mode_cdf[BLOCK_SIZES_ALL][CDF_SIZE(MOTION_MODES)] = { + { AOM_CDF3(10923, 21845) }, { AOM_CDF3(10923, 21845) }, + { AOM_CDF3(10923, 21845) }, { AOM_CDF3(7651, 24760) }, + { AOM_CDF3(4738, 24765) }, { AOM_CDF3(5391, 25528) }, + { AOM_CDF3(19419, 26810) }, { AOM_CDF3(5123, 23606) }, + { AOM_CDF3(11606, 24308) }, { AOM_CDF3(26260, 29116) }, + { AOM_CDF3(20360, 28062) }, { AOM_CDF3(21679, 26830) }, + { AOM_CDF3(29516, 30701) }, { AOM_CDF3(28898, 30397) }, + { AOM_CDF3(30878, 31335) }, { AOM_CDF3(32507, 32558) }, + { AOM_CDF3(10923, 21845) }, { AOM_CDF3(10923, 21845) }, + { AOM_CDF3(28799, 31390) }, { AOM_CDF3(26431, 30774) }, + { AOM_CDF3(28973, 31594) }, { AOM_CDF3(29742, 31203) } +}; + +static const u16 default_obmc_cdf[BLOCK_SIZES_ALL][CDF_SIZE(2)] = { + { AOM_CDF2(16384) }, { AOM_CDF2(16384) }, { AOM_CDF2(16384) }, + { AOM_CDF2(10437) }, + { AOM_CDF2(9371) }, { AOM_CDF2(9301) }, { AOM_CDF2(17432) }, + { AOM_CDF2(14423) }, + { AOM_CDF2(15142) }, { AOM_CDF2(25817) }, { AOM_CDF2(22823) }, + { AOM_CDF2(22083) }, + { AOM_CDF2(30128) }, { AOM_CDF2(31014) }, { AOM_CDF2(31560) }, + { AOM_CDF2(32638) }, + { AOM_CDF2(16384) }, { AOM_CDF2(16384) }, { AOM_CDF2(23664) }, + { AOM_CDF2(20901) }, + { AOM_CDF2(24008) }, { AOM_CDF2(26879) } +}; + +static const u16 default_intra_inter_cdf[INTRA_INTER_CONTEXTS][CDF_SIZE(2)] = { + { AOM_CDF2(806) }, + { AOM_CDF2(16662) }, + { AOM_CDF2(20186) }, + { AOM_CDF2(26538) } +}; + +static const u16 default_comp_inter_cdf[COMP_INTER_CONTEXTS][CDF_SIZE(2)] = { + { AOM_CDF2(26828) }, + { AOM_CDF2(24035) }, + { AOM_CDF2(12031) }, + { AOM_CDF2(10640) }, + { AOM_CDF2(2901) } +}; + +static const u16 default_comp_ref_type_cdf[COMP_REF_TYPE_CONTEXTS][CDF_SIZE(2)] = { + { AOM_CDF2(1198) }, + { AOM_CDF2(2070) }, + { AOM_CDF2(9166) }, + { AOM_CDF2(7499) }, + { AOM_CDF2(22475) } +}; + +static const u16 default_uni_comp_ref_cdf[UNI_COMP_REF_CONTEXTS] + [UNIDIR_COMP_REFS - 1][CDF_SIZE(2)] = { + { { AOM_CDF2(5284)}, { AOM_CDF2(3865)}, { AOM_CDF2(3128)} }, + { { AOM_CDF2(23152)}, { AOM_CDF2(14173)}, { AOM_CDF2(15270)} }, + { { AOM_CDF2(31774)}, { AOM_CDF2(25120)}, { AOM_CDF2(26710)} } +}; + +static const u16 default_single_ref_cdf[REF_CONTEXTS][SINGLE_REFS - 1][CDF_SIZE(2)] = { + { + { AOM_CDF2(4897)}, + { AOM_CDF2(1555)}, + { AOM_CDF2(4236)}, + { AOM_CDF2(8650)}, + { AOM_CDF2(904)}, + { AOM_CDF2(1444)} + }, + { + { AOM_CDF2(16973)}, + { AOM_CDF2(16751)}, + { AOM_CDF2(19647)}, + { AOM_CDF2(24773)}, + { AOM_CDF2(11014)}, + { AOM_CDF2(15087)} + }, + { + { AOM_CDF2(29744)}, + { AOM_CDF2(30279)}, + { AOM_CDF2(31194)}, + { AOM_CDF2(31895)}, + { AOM_CDF2(26875)}, + { AOM_CDF2(30304)} + } +}; + +static const u16 default_comp_ref_cdf[REF_CONTEXTS][FWD_REFS - 1][CDF_SIZE(2)] = { + { { AOM_CDF2(4946)}, { AOM_CDF2(9468)}, { AOM_CDF2(1503)} }, + { { AOM_CDF2(19891)}, { AOM_CDF2(22441)}, { AOM_CDF2(15160)} }, + { { AOM_CDF2(30731)}, { AOM_CDF2(31059)}, { AOM_CDF2(27544)} } +}; + +static const u16 default_comp_bwdref_cdf[REF_CONTEXTS][BWD_REFS - 1][CDF_SIZE(2)] = { + { { AOM_CDF2(2235)}, { AOM_CDF2(1423)} }, + { { AOM_CDF2(17182)}, { AOM_CDF2(15175)} }, + { { AOM_CDF2(30606)}, { AOM_CDF2(30489)} } +}; + +static const u16 default_palette_y_size_cdf[PALETTE_BLOCK_SIZES][CDF_SIZE(PALETTE_SIZES)] = { + { AOM_CDF7(7952, 13000, 18149, 21478, 25527, 29241) }, + { AOM_CDF7(7139, 11421, 16195, 19544, 23666, 28073) }, + { AOM_CDF7(7788, 12741, 17325, 20500, 24315, 28530) }, + { AOM_CDF7(8271, 14064, 18246, 21564, 25071, 28533) }, + { AOM_CDF7(12725, 19180, 21863, 24839, 27535, 30120) }, + { AOM_CDF7(9711, 14888, 16923, 21052, 25661, 27875) }, + { AOM_CDF7(14940, 20797, 21678, 24186, 27033, 28999) } +}; + +static const u16 default_palette_uv_size_cdf[PALETTE_BLOCK_SIZES][CDF_SIZE(PALETTE_SIZES)] = { + { AOM_CDF7(8713, 19979, 27128, 29609, 31331, 32272) }, + { AOM_CDF7(5839, 15573, 23581, 26947, 29848, 31700) }, + { AOM_CDF7(4426, 11260, 17999, 21483, 25863, 29430) }, + { AOM_CDF7(3228, 9464, 14993, 18089, 22523, 27420) }, + { AOM_CDF7(3768, 8886, 13091, 17852, 22495, 27207) }, + { AOM_CDF7(2464, 8451, 12861, 21632, 25525, 28555) }, + { AOM_CDF7(1269, 5435, 10433, 18963, 21700, 25865) } +}; + +static const u16 default_palette_y_mode_cdf[PALETTE_BLOCK_SIZES] + [PALETTE_Y_MODE_CONTEXTS][CDF_SIZE(2)] = { + { { AOM_CDF2(31676)}, { AOM_CDF2(3419)}, { AOM_CDF2(1261)} }, + { { AOM_CDF2(31912)}, { AOM_CDF2(2859)}, { AOM_CDF2(980)} }, + { { AOM_CDF2(31823)}, { AOM_CDF2(3400)}, { AOM_CDF2(781)} }, + { { AOM_CDF2(32030)}, { AOM_CDF2(3561)}, { AOM_CDF2(904)} }, + { { AOM_CDF2(32309)}, { AOM_CDF2(7337)}, { AOM_CDF2(1462)} }, + { { AOM_CDF2(32265)}, { AOM_CDF2(4015)}, { AOM_CDF2(1521)} }, + { { AOM_CDF2(32450)}, { AOM_CDF2(7946)}, { AOM_CDF2(129)} } +}; + +static const u16 default_palette_uv_mode_cdf[PALETTE_UV_MODE_CONTEXTS][CDF_SIZE(2)] = { + { AOM_CDF2(32461) }, { AOM_CDF2(21488) } +}; + +static const u16 default_palette_y_color_index_cdf[PALETTE_IDX_CONTEXTS][8] = { + // Palette sizes 2 & 8 + { + AOM_CDF2(28710), + AOM_CDF8(21689, 23883, 25163, 26352, 27506, 28827, 30195) + }, + { + AOM_CDF2(16384), + AOM_CDF8(6892, 15385, 17840, 21606, 24287, 26753, 29204) + }, + { + AOM_CDF2(10553), + AOM_CDF8(5651, 23182, 25042, 26518, 27982, 29392, 30900) + }, + { + AOM_CDF2(27036), + AOM_CDF8(19349, 22578, 24418, 25994, 27524, 29031, 30448) + }, + { + AOM_CDF2(31603), + AOM_CDF8(31028, 31270, 31504, 31705, 31927, 32153, 32392) + }, + // Palette sizes 3 & 7 + { + AOM_CDF3(27877, 30490), + AOM_CDF7(23105, 25199, 26464, 27684, 28931, 30318) + }, + { + AOM_CDF3(11532, 25697), + AOM_CDF7(6950, 15447, 18952, 22681, 25567, 28563) + }, + { + AOM_CDF3(6544, 30234), + AOM_CDF7(7560, 23474, 25490, 27203, 28921, 30708) + }, + { + AOM_CDF3(23018, 28072), + AOM_CDF7(18544, 22373, 24457, 26195, 28119, 30045) + }, + { + AOM_CDF3(31915, 32385), + AOM_CDF7(31198, 31451, 31670, 31882, 32123, 32391) + }, + // Palette sizes 4 & 6 + { + AOM_CDF4(25572, 28046, 30045), + AOM_CDF6(23132, 25407, 26970, 28435, 30073) + }, + { + AOM_CDF4(9478, 21590, 27256), + AOM_CDF6(7443, 17242, 20717, 24762, 27982) + }, + { + AOM_CDF4(7248, 26837, 29824), + AOM_CDF6(6300, 24862, 26944, 28784, 30671) + }, + { + AOM_CDF4(19167, 24486, 28349), + AOM_CDF6(18916, 22895, 25267, 27435, 29652) + }, + { + AOM_CDF4(31400, 31825, 32250), + AOM_CDF6(31270, 31550, 31808, 32059, 32353) + }, + // Palette size 5 + { + AOM_CDF5(24779, 26955, 28576, 30282), + AOM_CDF5(8669, 20364, 24073, 28093) + }, + { + AOM_CDF5(4255, 27565, 29377, 31067), + AOM_CDF5(19864, 23674, 26716, 29530) + }, + { + AOM_CDF5(31646, 31893, 32147, 32426), + 0, 0, 0, 0 + } +}; + +static const u16 default_palette_uv_color_index_cdf[PALETTE_IDX_CONTEXTS][8] = { + // Palette sizes 2 & 8 + { + AOM_CDF2(29089), + AOM_CDF8(21442, 23288, 24758, 26246, 27649, 28980, 30563) + }, + { + AOM_CDF2(16384), + AOM_CDF8(5863, 14933, 17552, 20668, 23683, 26411, 29273) + }, + { + AOM_CDF2(8713), + AOM_CDF8(3415, 25810, 26877, 27990, 29223, 30394, 31618) + }, + { + AOM_CDF2(29257), + AOM_CDF8(17965, 20084, 22232, 23974, 26274, 28402, 30390) + }, + { + AOM_CDF2(31610), + AOM_CDF8(31190, 31329, 31516, 31679, 31825, 32026, 32322) + }, + // Palette sizes 3 & 7 + { + AOM_CDF3(25257, 29145), + AOM_CDF7(21239, 23168, 25044, 26962, 28705, 30506) + }, + { + AOM_CDF3(12287, 27293), + AOM_CDF7(6545, 15012, 18004, 21817, 25503, 28701) + }, + { + AOM_CDF3(7033, 27960), + AOM_CDF7(3448, 26295, 27437, 28704, 30126, 31442) + }, + { + AOM_CDF3(20145, 25405), + AOM_CDF7(15889, 18323, 21704, 24698, 26976, 29690) + }, + { + AOM_CDF3(30608, 31639), + AOM_CDF7(30988, 31204, 31479, 31734, 31983, 32325) + }, + // Palette sizes 4 & 6 + { + AOM_CDF4(24210, 27175, 29903), + AOM_CDF6(22217, 24567, 26637, 28683, 30548) + }, + { + AOM_CDF4(9888, 22386, 27214), + AOM_CDF6(7307, 16406, 19636, 24632, 28424) + }, + { + AOM_CDF4(5901, 26053, 29293), + AOM_CDF6(4441, 25064, 26879, 28942, 30919) + }, + { + AOM_CDF4(18318, 22152, 28333), + AOM_CDF6(17210, 20528, 23319, 26750, 29582) + }, + { + AOM_CDF4(30459, 31136, 31926), + AOM_CDF6(30674, 30953, 31396, 31735, 32207) + }, + // Palette size 5 + { + AOM_CDF5(22980, 25479, 27781, 29986), + AOM_CDF5(8413, 21408, 24859, 28874) + }, + { + AOM_CDF5(2257, 29449, 30594, 31598), + AOM_CDF5(19189, 21202, 25915, 28620) + }, + { + AOM_CDF5(31844, 32044, 32281, 32518), + 0, 0, 0, 0 + } +}; + +static const u16 default_txfm_partition_cdf[TXFM_PARTITION_CONTEXTS][CDF_SIZE(2)] = { + { AOM_CDF2(28581) }, { AOM_CDF2(23846) }, { AOM_CDF2(20847) }, + { AOM_CDF2(24315) }, { AOM_CDF2(18196) }, { AOM_CDF2(12133) }, + { AOM_CDF2(18791) }, { AOM_CDF2(10887) }, { AOM_CDF2(11005) }, + { AOM_CDF2(27179) }, { AOM_CDF2(20004) }, { AOM_CDF2(11281) }, + { AOM_CDF2(26549) }, { AOM_CDF2(19308) }, { AOM_CDF2(14224) }, + { AOM_CDF2(28015) }, { AOM_CDF2(21546) }, { AOM_CDF2(14400) }, + { AOM_CDF2(28165) }, { AOM_CDF2(22401) }, { AOM_CDF2(16088) } +}; + +static const u16 default_skip_cdfs[SKIP_CONTEXTS][CDF_SIZE(2)] = { + { AOM_CDF2(31671) }, { AOM_CDF2(16515) }, { AOM_CDF2(4576) } +}; + +static const u16 default_skip_mode_cdfs[SKIP_MODE_CONTEXTS][CDF_SIZE(2)] = { + { AOM_CDF2(32621) }, { AOM_CDF2(20708) }, { AOM_CDF2(8127) } +}; + +static const u16 default_compound_idx_cdfs[COMP_INDEX_CONTEXTS][CDF_SIZE(2)] = { + { AOM_CDF2(18244) }, { AOM_CDF2(12865) }, { AOM_CDF2(7053) }, + { AOM_CDF2(13259) }, { AOM_CDF2(9334) }, { AOM_CDF2(4644) } +}; + +static const u16 default_comp_group_idx_cdfs[COMP_GROUP_IDX_CONTEXTS][CDF_SIZE(2)] = { + { AOM_CDF2(26607) }, { AOM_CDF2(22891) }, { AOM_CDF2(18840) }, + { AOM_CDF2(24594) }, { AOM_CDF2(19934) }, { AOM_CDF2(22674) } +}; + +static const u16 default_intrabc_cdf[CDF_SIZE(2)] = { AOM_CDF2(30531) }; + +static const u16 default_filter_intra_mode_cdf[CDF_SIZE(FILTER_INTRA_MODES)] = { + AOM_CDF5(8949, 12776, 17211, 29558) +}; + +static const u16 default_filter_intra_cdfs[BLOCK_SIZES_ALL][CDF_SIZE(2)] = { + { AOM_CDF2(4621) }, { AOM_CDF2(6743) }, { AOM_CDF2(5893) }, { AOM_CDF2(7866) }, + { AOM_CDF2(12551) }, { AOM_CDF2(9394) }, { AOM_CDF2(12408) }, { AOM_CDF2(14301) }, + { AOM_CDF2(12756) }, { AOM_CDF2(22343) }, { AOM_CDF2(16384) }, { AOM_CDF2(16384) }, + { AOM_CDF2(16384) }, { AOM_CDF2(16384) }, { AOM_CDF2(16384) }, { AOM_CDF2(16384) }, + { AOM_CDF2(12770) }, { AOM_CDF2(10368) }, { AOM_CDF2(20229) }, { AOM_CDF2(18101) }, + { AOM_CDF2(16384) }, { AOM_CDF2(16384) } +}; + +static const u16 default_delta_q_cdf[CDF_SIZE(DELTA_Q_PROBS + 1)] = { + AOM_CDF4(28160, 32120, 32677) +}; + +static const u16 default_delta_lf_multi_cdf[FRAME_LF_COUNT][CDF_SIZE(DELTA_LF_PROBS + 1)] = { + { AOM_CDF4(28160, 32120, 32677) }, + { AOM_CDF4(28160, 32120, 32677) }, + { AOM_CDF4(28160, 32120, 32677) }, + { AOM_CDF4(28160, 32120, 32677) } +}; + +static const u16 default_delta_lf_cdf[CDF_SIZE(DELTA_LF_PROBS + 1)] = { + AOM_CDF4(28160, 32120, 32677) +}; + +static const u16 default_segment_pred_cdf[SEG_TEMPORAL_PRED_CTXS][CDF_SIZE(2)] = { + { AOM_CDF2(128 * 128) }, + { AOM_CDF2(128 * 128) }, + { AOM_CDF2(128 * 128) } +}; + +static const u16 default_spatial_pred_seg_tree_cdf[SPATIAL_PREDICTION_PROBS] + [CDF_SIZE(MAX_SEGMENTS)] = { + { + AOM_CDF8(5622, 7893, 16093, 18233, 27809, 28373, 32533), + }, + { + AOM_CDF8(14274, 18230, 22557, 24935, 29980, 30851, 32344), + }, + { + AOM_CDF8(27527, 28487, 28723, 28890, 32397, 32647, 32679), + }, +}; + +static const u16 default_tx_size_cdf[MAX_TX_CATS] + [AV1_TX_SIZE_CONTEXTS][CDF_SIZE(MAX_TX_DEPTH + 1)] = { + { + { AOM_CDF2(19968)}, + { AOM_CDF2(19968)}, + { AOM_CDF2(24320)} + }, + { + { AOM_CDF3(12272, 30172)}, + { AOM_CDF3(12272, 30172)}, + { AOM_CDF3(18677, 30848)} + }, + { + { AOM_CDF3(12986, 15180)}, + { AOM_CDF3(12986, 15180)}, + { AOM_CDF3(24302, 25602)} + }, + { + { AOM_CDF3(5782, 11475)}, + { AOM_CDF3(5782, 11475)}, + { AOM_CDF3(16803, 22759)} + }, +}; + +static const u16 av1_default_dc_sign_cdfs[TOKEN_CDF_Q_CTXS] + [PLANE_TYPES][DC_SIGN_CONTEXTS][CDF_SIZE(2)] = { + { + { + { AOM_CDF2(128 * 125)}, + { AOM_CDF2(128 * 102)}, + { AOM_CDF2(128 * 147)}, + }, + { + { AOM_CDF2(128 * 119)}, + { AOM_CDF2(128 * 101)}, + { AOM_CDF2(128 * 135)}, + } + }, + { + { + { AOM_CDF2(128 * 125)}, + { AOM_CDF2(128 * 102)}, + { AOM_CDF2(128 * 147)}, + }, + { + { AOM_CDF2(128 * 119)}, + { AOM_CDF2(128 * 101)}, + { AOM_CDF2(128 * 135)}, + } + }, + { + { + { AOM_CDF2(128 * 125)}, + { AOM_CDF2(128 * 102)}, + { AOM_CDF2(128 * 147)}, + }, + { + { AOM_CDF2(128 * 119)}, + { AOM_CDF2(128 * 101)}, + { AOM_CDF2(128 * 135)}, + } + }, + { + { + { AOM_CDF2(128 * 125)}, + { AOM_CDF2(128 * 102)}, + { AOM_CDF2(128 * 147)}, + }, + { + { AOM_CDF2(128 * 119)}, + { AOM_CDF2(128 * 101)}, + { AOM_CDF2(128 * 135)}, + } + }, +}; + +static const u16 av1_default_txb_skip_cdfs[TOKEN_CDF_Q_CTXS] + [TX_SIZES][TXB_SKIP_CONTEXTS][CDF_SIZE(2)] = { + { + { + { AOM_CDF2(31849)}, + { AOM_CDF2(5892)}, + { AOM_CDF2(12112)}, + { AOM_CDF2(21935)}, + { AOM_CDF2(20289)}, + { AOM_CDF2(27473)}, + { AOM_CDF2(32487)}, + { AOM_CDF2(7654)}, + { AOM_CDF2(19473)}, + { AOM_CDF2(29984)}, + { AOM_CDF2(9961)}, + { AOM_CDF2(30242)}, + { AOM_CDF2(32117)} + }, + { + { AOM_CDF2(31548)}, + { AOM_CDF2(1549)}, + { AOM_CDF2(10130)}, + { AOM_CDF2(16656)}, + { AOM_CDF2(18591)}, + { AOM_CDF2(26308)}, + { AOM_CDF2(32537)}, + { AOM_CDF2(5403)}, + { AOM_CDF2(18096)}, + { AOM_CDF2(30003)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)} + }, + { + { AOM_CDF2(29957)}, + { AOM_CDF2(5391)}, + { AOM_CDF2(18039)}, + { AOM_CDF2(23566)}, + { AOM_CDF2(22431)}, + { AOM_CDF2(25822)}, + { AOM_CDF2(32197)}, + { AOM_CDF2(3778)}, + { AOM_CDF2(15336)}, + { AOM_CDF2(28981)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)} + }, + { + { AOM_CDF2(17920)}, + { AOM_CDF2(1818)}, + { AOM_CDF2(7282)}, + { AOM_CDF2(25273)}, + { AOM_CDF2(10923)}, + { AOM_CDF2(31554)}, + { AOM_CDF2(32624)}, + { AOM_CDF2(1366)}, + { AOM_CDF2(15628)}, + { AOM_CDF2(30462)}, + { AOM_CDF2(146)}, + { AOM_CDF2(5132)}, + { AOM_CDF2(31657)} + }, + { + { AOM_CDF2(6308)}, + { AOM_CDF2(117)}, + { AOM_CDF2(1638)}, + { AOM_CDF2(2161)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(10923)}, + { AOM_CDF2(30247)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)} + } + }, + { + { + { AOM_CDF2(30371)}, + { AOM_CDF2(7570)}, + { AOM_CDF2(13155)}, + { AOM_CDF2(20751)}, + { AOM_CDF2(20969)}, + { AOM_CDF2(27067)}, + { AOM_CDF2(32013)}, + { AOM_CDF2(5495)}, + { AOM_CDF2(17942)}, + { AOM_CDF2(28280)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)} + }, + { + { AOM_CDF2(31782)}, + { AOM_CDF2(1836)}, + { AOM_CDF2(10689)}, + { AOM_CDF2(17604)}, + { AOM_CDF2(21622)}, + { AOM_CDF2(27518)}, + { AOM_CDF2(32399)}, + { AOM_CDF2(4419)}, + { AOM_CDF2(16294)}, + { AOM_CDF2(28345)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)} + }, + { + { AOM_CDF2(31901)}, + { AOM_CDF2(10311)}, + { AOM_CDF2(18047)}, + { AOM_CDF2(24806)}, + { AOM_CDF2(23288)}, + { AOM_CDF2(27914)}, + { AOM_CDF2(32296)}, + { AOM_CDF2(4215)}, + { AOM_CDF2(15756)}, + { AOM_CDF2(28341)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)} + }, + { + { AOM_CDF2(26726)}, + { AOM_CDF2(1045)}, + { AOM_CDF2(11703)}, + { AOM_CDF2(20590)}, + { AOM_CDF2(18554)}, + { AOM_CDF2(25970)}, + { AOM_CDF2(31938)}, + { AOM_CDF2(5583)}, + { AOM_CDF2(21313)}, + { AOM_CDF2(29390)}, + { AOM_CDF2(641)}, + { AOM_CDF2(22265)}, + { AOM_CDF2(31452)} + }, + { + { AOM_CDF2(26584)}, + { AOM_CDF2(188)}, + { AOM_CDF2(8847)}, + { AOM_CDF2(24519)}, + { AOM_CDF2(22938)}, + { AOM_CDF2(30583)}, + { AOM_CDF2(32608)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)} + } + }, + { + { + { AOM_CDF2(29614)}, + { AOM_CDF2(9068)}, + { AOM_CDF2(12924)}, + { AOM_CDF2(19538)}, + { AOM_CDF2(17737)}, + { AOM_CDF2(24619)}, + { AOM_CDF2(30642)}, + { AOM_CDF2(4119)}, + { AOM_CDF2(16026)}, + { AOM_CDF2(25657)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)} + }, + { + { AOM_CDF2(31957)}, + { AOM_CDF2(3230)}, + { AOM_CDF2(11153)}, + { AOM_CDF2(18123)}, + { AOM_CDF2(20143)}, + { AOM_CDF2(26536)}, + { AOM_CDF2(31986)}, + { AOM_CDF2(3050)}, + { AOM_CDF2(14603)}, + { AOM_CDF2(25155)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)} + }, + { + { AOM_CDF2(32363)}, + { AOM_CDF2(10692)}, + { AOM_CDF2(19090)}, + { AOM_CDF2(24357)}, + { AOM_CDF2(24442)}, + { AOM_CDF2(28312)}, + { AOM_CDF2(32169)}, + { AOM_CDF2(3648)}, + { AOM_CDF2(15690)}, + { AOM_CDF2(26815)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)} + }, + { + { AOM_CDF2(30669)}, + { AOM_CDF2(3832)}, + { AOM_CDF2(11663)}, + { AOM_CDF2(18889)}, + { AOM_CDF2(19782)}, + { AOM_CDF2(23313)}, + { AOM_CDF2(31330)}, + { AOM_CDF2(5124)}, + { AOM_CDF2(18719)}, + { AOM_CDF2(28468)}, + { AOM_CDF2(3082)}, + { AOM_CDF2(20982)}, + { AOM_CDF2(29443)} + }, + { + { AOM_CDF2(28573)}, + { AOM_CDF2(3183)}, + { AOM_CDF2(17802)}, + { AOM_CDF2(25977)}, + { AOM_CDF2(26677)}, + { AOM_CDF2(27832)}, + { AOM_CDF2(32387)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)} + } + }, + { + { + { AOM_CDF2(26887)}, + { AOM_CDF2(6729)}, + { AOM_CDF2(10361)}, + { AOM_CDF2(17442)}, + { AOM_CDF2(15045)}, + { AOM_CDF2(22478)}, + { AOM_CDF2(29072)}, + { AOM_CDF2(2713)}, + { AOM_CDF2(11861)}, + { AOM_CDF2(20773)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)} + }, + { + { AOM_CDF2(31903)}, + { AOM_CDF2(2044)}, + { AOM_CDF2(7528)}, + { AOM_CDF2(14618)}, + { AOM_CDF2(16182)}, + { AOM_CDF2(24168)}, + { AOM_CDF2(31037)}, + { AOM_CDF2(2786)}, + { AOM_CDF2(11194)}, + { AOM_CDF2(20155)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)} + }, + { + { AOM_CDF2(32510)}, + { AOM_CDF2(8430)}, + { AOM_CDF2(17318)}, + { AOM_CDF2(24154)}, + { AOM_CDF2(23674)}, + { AOM_CDF2(28789)}, + { AOM_CDF2(32139)}, + { AOM_CDF2(3440)}, + { AOM_CDF2(13117)}, + { AOM_CDF2(22702)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)} + }, + { + { AOM_CDF2(31671)}, + { AOM_CDF2(2056)}, + { AOM_CDF2(11746)}, + { AOM_CDF2(16852)}, + { AOM_CDF2(18635)}, + { AOM_CDF2(24715)}, + { AOM_CDF2(31484)}, + { AOM_CDF2(4656)}, + { AOM_CDF2(16074)}, + { AOM_CDF2(24704)}, + { AOM_CDF2(1806)}, + { AOM_CDF2(14645)}, + { AOM_CDF2(25336)} + }, + { + { AOM_CDF2(31539)}, + { AOM_CDF2(8433)}, + { AOM_CDF2(20576)}, + { AOM_CDF2(27904)}, + { AOM_CDF2(27852)}, + { AOM_CDF2(30026)}, + { AOM_CDF2(32441)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)} + } + } +}; + +static const u16 av1_default_eob_extra_cdfs[TOKEN_CDF_Q_CTXS][TX_SIZES][PLANE_TYPES] + [EOB_COEF_CONTEXTS][CDF_SIZE(2)] = { + { + { + { + { AOM_CDF2(16961)}, + { AOM_CDF2(17223)}, + { AOM_CDF2(7621)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + }, + { + { AOM_CDF2(19069)}, + { AOM_CDF2(22525)}, + { AOM_CDF2(13377)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + } + }, + { + { + { AOM_CDF2(20401)}, + { AOM_CDF2(17025)}, + { AOM_CDF2(12845)}, + { AOM_CDF2(12873)}, + { AOM_CDF2(14094)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + }, + { + { AOM_CDF2(20681)}, + { AOM_CDF2(20701)}, + { AOM_CDF2(15250)}, + { AOM_CDF2(15017)}, + { AOM_CDF2(14928)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + } + }, + { + { + { AOM_CDF2(23905)}, + { AOM_CDF2(17194)}, + { AOM_CDF2(16170)}, + { AOM_CDF2(17695)}, + { AOM_CDF2(13826)}, + { AOM_CDF2(15810)}, + { AOM_CDF2(12036)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + }, + { + { AOM_CDF2(23959)}, + { AOM_CDF2(20799)}, + { AOM_CDF2(19021)}, + { AOM_CDF2(16203)}, + { AOM_CDF2(17886)}, + { AOM_CDF2(14144)}, + { AOM_CDF2(12010)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + } + }, + { + { + { AOM_CDF2(27399)}, + { AOM_CDF2(16327)}, + { AOM_CDF2(18071)}, + { AOM_CDF2(19584)}, + { AOM_CDF2(20721)}, + { AOM_CDF2(18432)}, + { AOM_CDF2(19560)}, + { AOM_CDF2(10150)}, + { AOM_CDF2(8805)}, + }, + { + { AOM_CDF2(24932)}, + { AOM_CDF2(20833)}, + { AOM_CDF2(12027)}, + { AOM_CDF2(16670)}, + { AOM_CDF2(19914)}, + { AOM_CDF2(15106)}, + { AOM_CDF2(17662)}, + { AOM_CDF2(13783)}, + { AOM_CDF2(28756)}, + } + }, + { + { + { AOM_CDF2(23406)}, + { AOM_CDF2(21845)}, + { AOM_CDF2(18432)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(17096)}, + { AOM_CDF2(12561)}, + { AOM_CDF2(17320)}, + { AOM_CDF2(22395)}, + { AOM_CDF2(21370)}, + }, + { + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + } + } + }, + { + { + { + { AOM_CDF2(17471)}, + { AOM_CDF2(20223)}, + { AOM_CDF2(11357)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + }, + { + { AOM_CDF2(20335)}, + { AOM_CDF2(21667)}, + { AOM_CDF2(14818)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + } + }, + { + { + { AOM_CDF2(20430)}, + { AOM_CDF2(20662)}, + { AOM_CDF2(15367)}, + { AOM_CDF2(16970)}, + { AOM_CDF2(14657)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + }, + { + { AOM_CDF2(22117)}, + { AOM_CDF2(22028)}, + { AOM_CDF2(18650)}, + { AOM_CDF2(16042)}, + { AOM_CDF2(15885)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + } + }, + { + { + { AOM_CDF2(22409)}, + { AOM_CDF2(21012)}, + { AOM_CDF2(15650)}, + { AOM_CDF2(17395)}, + { AOM_CDF2(15469)}, + { AOM_CDF2(20205)}, + { AOM_CDF2(19511)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + }, + { + { AOM_CDF2(24220)}, + { AOM_CDF2(22480)}, + { AOM_CDF2(17737)}, + { AOM_CDF2(18916)}, + { AOM_CDF2(19268)}, + { AOM_CDF2(18412)}, + { AOM_CDF2(18844)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + } + }, + { + { + { AOM_CDF2(25991)}, + { AOM_CDF2(20314)}, + { AOM_CDF2(17731)}, + { AOM_CDF2(19678)}, + { AOM_CDF2(18649)}, + { AOM_CDF2(17307)}, + { AOM_CDF2(21798)}, + { AOM_CDF2(17549)}, + { AOM_CDF2(15630)}, + }, + { + { AOM_CDF2(26585)}, + { AOM_CDF2(21469)}, + { AOM_CDF2(20432)}, + { AOM_CDF2(17735)}, + { AOM_CDF2(19280)}, + { AOM_CDF2(15235)}, + { AOM_CDF2(20297)}, + { AOM_CDF2(22471)}, + { AOM_CDF2(28997)}, + } + }, + { + { + { AOM_CDF2(26605)}, + { AOM_CDF2(11304)}, + { AOM_CDF2(16726)}, + { AOM_CDF2(16560)}, + { AOM_CDF2(20866)}, + { AOM_CDF2(23524)}, + { AOM_CDF2(19878)}, + { AOM_CDF2(13469)}, + { AOM_CDF2(23084)}, + }, + { + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + } + } + }, + { + { + { + { AOM_CDF2(18983)}, + { AOM_CDF2(20512)}, + { AOM_CDF2(14885)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + }, + { + { AOM_CDF2(20090)}, + { AOM_CDF2(19444)}, + { AOM_CDF2(17286)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + } + }, + { + { + { AOM_CDF2(19139)}, + { AOM_CDF2(21487)}, + { AOM_CDF2(18959)}, + { AOM_CDF2(20910)}, + { AOM_CDF2(19089)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + }, + { + { AOM_CDF2(20536)}, + { AOM_CDF2(20664)}, + { AOM_CDF2(20625)}, + { AOM_CDF2(19123)}, + { AOM_CDF2(14862)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + } + }, + { + { + { AOM_CDF2(19833)}, + { AOM_CDF2(21502)}, + { AOM_CDF2(17485)}, + { AOM_CDF2(20267)}, + { AOM_CDF2(18353)}, + { AOM_CDF2(23329)}, + { AOM_CDF2(21478)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + }, + { + { AOM_CDF2(22041)}, + { AOM_CDF2(23434)}, + { AOM_CDF2(20001)}, + { AOM_CDF2(20554)}, + { AOM_CDF2(20951)}, + { AOM_CDF2(20145)}, + { AOM_CDF2(15562)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + } + }, + { + { + { AOM_CDF2(23312)}, + { AOM_CDF2(21607)}, + { AOM_CDF2(16526)}, + { AOM_CDF2(18957)}, + { AOM_CDF2(18034)}, + { AOM_CDF2(18934)}, + { AOM_CDF2(24247)}, + { AOM_CDF2(16921)}, + { AOM_CDF2(17080)}, + }, + { + { AOM_CDF2(26579)}, + { AOM_CDF2(24910)}, + { AOM_CDF2(18637)}, + { AOM_CDF2(19800)}, + { AOM_CDF2(20388)}, + { AOM_CDF2(9887)}, + { AOM_CDF2(15642)}, + { AOM_CDF2(30198)}, + { AOM_CDF2(24721)}, + } + }, + { + { + { AOM_CDF2(26998)}, + { AOM_CDF2(16737)}, + { AOM_CDF2(17838)}, + { AOM_CDF2(18922)}, + { AOM_CDF2(19515)}, + { AOM_CDF2(18636)}, + { AOM_CDF2(17333)}, + { AOM_CDF2(15776)}, + { AOM_CDF2(22658)}, + }, + { + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + } + } + }, + { + { + { + { AOM_CDF2(20177)}, + { AOM_CDF2(20789)}, + { AOM_CDF2(20262)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + }, + { + { AOM_CDF2(21416)}, + { AOM_CDF2(20855)}, + { AOM_CDF2(23410)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + } + }, + { + { + { AOM_CDF2(20238)}, + { AOM_CDF2(21057)}, + { AOM_CDF2(19159)}, + { AOM_CDF2(22337)}, + { AOM_CDF2(20159)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + }, + { + { AOM_CDF2(20125)}, + { AOM_CDF2(20559)}, + { AOM_CDF2(21707)}, + { AOM_CDF2(22296)}, + { AOM_CDF2(17333)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + } + }, + { + { + { AOM_CDF2(19941)}, + { AOM_CDF2(20527)}, + { AOM_CDF2(21470)}, + { AOM_CDF2(22487)}, + { AOM_CDF2(19558)}, + { AOM_CDF2(22354)}, + { AOM_CDF2(20331)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + }, + { + { AOM_CDF2(22752)}, + { AOM_CDF2(25006)}, + { AOM_CDF2(22075)}, + { AOM_CDF2(21576)}, + { AOM_CDF2(17740)}, + { AOM_CDF2(21690)}, + { AOM_CDF2(19211)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + } + }, + { + { + { AOM_CDF2(21442)}, + { AOM_CDF2(22358)}, + { AOM_CDF2(18503)}, + { AOM_CDF2(20291)}, + { AOM_CDF2(19945)}, + { AOM_CDF2(21294)}, + { AOM_CDF2(21178)}, + { AOM_CDF2(19400)}, + { AOM_CDF2(10556)}, + }, + { + { AOM_CDF2(24648)}, + { AOM_CDF2(24949)}, + { AOM_CDF2(20708)}, + { AOM_CDF2(23905)}, + { AOM_CDF2(20501)}, + { AOM_CDF2(9558)}, + { AOM_CDF2(9423)}, + { AOM_CDF2(30365)}, + { AOM_CDF2(19253)}, + } + }, + { + { + { AOM_CDF2(26064)}, + { AOM_CDF2(22098)}, + { AOM_CDF2(19613)}, + { AOM_CDF2(20525)}, + { AOM_CDF2(17595)}, + { AOM_CDF2(16618)}, + { AOM_CDF2(20497)}, + { AOM_CDF2(18989)}, + { AOM_CDF2(15513)}, + }, + { + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + } + } + } +}; + +static const u16 av1_default_eob_multi16_cdfs[TOKEN_CDF_Q_CTXS][PLANE_TYPES][2][4] = { + { + { + { AOM_CDF5(840, 1039, 1980, 4895)}, + { AOM_CDF5(370, 671, 1883, 4471)} + }, + { + { AOM_CDF5(3247, 4950, 9688, 14563)}, + { AOM_CDF5(1904, 3354, 7763, 14647)} + } + }, + { + { + { AOM_CDF5(2125, 2551, 5165, 8946)}, + { AOM_CDF5(513, 765, 1859, 6339)} + }, + { + { AOM_CDF5(7637, 9498, 14259, 19108)}, + { AOM_CDF5(2497, 4096, 8866, 16993)} + } + }, + { + { + { AOM_CDF5(4016, 4897, 8881, 14968)}, + { AOM_CDF5(716, 1105, 2646, 10056)} + }, + { + { AOM_CDF5(11139, 13270, 18241, 23566)}, + { AOM_CDF5(3192, 5032, 10297, 19755)} + } + }, + { + { + { AOM_CDF5(6708, 8958, 14746, 22133)}, + { AOM_CDF5(1222, 2074, 4783, 15410)} + }, + { + { AOM_CDF5(19575, 21766, 26044, 29709)}, + { AOM_CDF5(7297, 10767, 19273, 28194)} + } + } +}; + +static const u16 av1_default_eob_multi32_cdfs[TOKEN_CDF_Q_CTXS][PLANE_TYPES][2][8] = { + { + { + { AOM_CDF6(400, 520, 977, 2102, 6542)}, + { AOM_CDF6(210, 405, 1315, 3326, 7537)} + }, + { + { AOM_CDF6(2636, 4273, 7588, 11794, 20401)}, + { AOM_CDF6(1786, 3179, 6902, 11357, 19054)} + } + }, + { + { + { AOM_CDF6(989, 1249, 2019, 4151, 10785)}, + { AOM_CDF6(313, 441, 1099, 2917, 8562)} + }, + { + { AOM_CDF6(8394, 10352, 13932, 18855, 26014)}, + { AOM_CDF6(2578, 4124, 8181, 13670, 24234)} + } + }, + { + { + { AOM_CDF6(2515, 3003, 4452, 8162, 16041)}, + { AOM_CDF6(574, 821, 1836, 5089, 13128)} + }, + { + { AOM_CDF6(13468, 16303, 20361, 25105, 29281)}, + { AOM_CDF6(3542, 5502, 10415, 16760, 25644)} + } + }, + { + { + { AOM_CDF6(4617, 5709, 8446, 13584, 23135)}, + { AOM_CDF6(1156, 1702, 3675, 9274, 20539)} + }, + { + { AOM_CDF6(22086, 24282, 27010, 29770, 31743)}, + { AOM_CDF6(7699, 10897, 20891, 26926, 31628)} + } + } +}; + +static const u16 av1_default_eob_multi64_cdfs[TOKEN_CDF_Q_CTXS][PLANE_TYPES][2][8] = { + { + { + { AOM_CDF7(329, 498, 1101, 1784, 3265, 7758)}, + { AOM_CDF7(335, 730, 1459, 5494, 8755, 12997)} + }, + { + { AOM_CDF7(3505, 5304, 10086, 13814, 17684, 23370)}, + { AOM_CDF7(1563, 2700, 4876, 10911, 14706, 22480)} + } + }, + { + { + { AOM_CDF7(1260, 1446, 2253, 3712, 6652, 13369)}, + { AOM_CDF7(401, 605, 1029, 2563, 5845, 12626)} + }, + { + { AOM_CDF7(8609, 10612, 14624, 18714, 22614, 29024)}, + { AOM_CDF7(1923, 3127, 5867, 9703, 14277, 27100)} + } + }, + { + { + { AOM_CDF7(2374, 2772, 4583, 7276, 12288, 19706)}, + { AOM_CDF7(497, 810, 1315, 3000, 7004, 15641)} + }, + { + { AOM_CDF7(15050, 17126, 21410, 24886, 28156, 30726)}, + { AOM_CDF7(4034, 6290, 10235, 14982, 21214, 28491)} + } + }, + { + { + { AOM_CDF7(6307, 7541, 12060, 16358, 22553, 27865)}, + { AOM_CDF7(1289, 2320, 3971, 7926, 14153, 24291)} + }, + { + { AOM_CDF7(24212, 25708, 28268, 30035, 31307, 32049)}, + { AOM_CDF7(8726, 12378, 19409, 26450, 30038, 32462)} + } + } +}; + +static const u16 av1_default_eob_multi128_cdfs[TOKEN_CDF_Q_CTXS][PLANE_TYPES][2][8] = { + { + { + { AOM_CDF8(219, 482, 1140, 2091, 3680, 6028, 12586)}, + { AOM_CDF8(371, 699, 1254, 4830, 9479, 12562, 17497)} + }, + { + { AOM_CDF8(5245, 7456, 12880, 15852, 20033, 23932, 27608)}, + { AOM_CDF8(2054, 3472, 5869, 14232, 18242, 20590, 26752)} + } + }, + { + { + { AOM_CDF8(685, 933, 1488, 2714, 4766, 8562, 19254)}, + { AOM_CDF8(217, 352, 618, 2303, 5261, 9969, 17472)} + }, + { + { AOM_CDF8(8045, 11200, 15497, 19595, 23948, 27408, 30938)}, + { AOM_CDF8(2310, 4160, 7471, 14997, 17931, 20768, 30240)} + } + }, + { + { + { AOM_CDF8(1366, 1738, 2527, 5016, 9355, 15797, 24643)}, + { AOM_CDF8(354, 558, 944, 2760, 7287, 14037, 21779)} + }, + { + { AOM_CDF8(13627, 16246, 20173, 24429, 27948, 30415, 31863)}, + { AOM_CDF8(6275, 9889, 14769, 23164, 27988, 30493, 32272)} + } + }, + { + { + { AOM_CDF8(3472, 4885, 7489, 12481, 18517, 24536, 29635)}, + { AOM_CDF8(886, 1731, 3271, 8469, 15569, 22126, 28383)} + }, + { + { AOM_CDF8(24313, 26062, 28385, 30107, 31217, 31898, 32345)}, + { AOM_CDF8(9165, 13282, 21150, 30286, 31894, 32571, 32712)} + } + } +}; + +static const u16 av1_default_eob_multi256_cdfs[TOKEN_CDF_Q_CTXS][PLANE_TYPES][2][8] = { + { + { + { AOM_CDF9(310, 584, 1887, 3589, 6168, 8611, 11352, 15652)}, + { AOM_CDF9(998, 1850, 2998, 5604, 17341, 19888, 22899, 25583)} + }, + { + { AOM_CDF9(2520, 3240, 5952, 8870, 12577, 17558, 19954, 24168)}, + { AOM_CDF9(2203, 4130, 7435, 10739, 20652, 23681, 25609, 27261)} + } + }, + { + { + { AOM_CDF9(1448, 2109, 4151, 6263, 9329, 13260, 17944, 23300)}, + { AOM_CDF9(399, 1019, 1749, 3038, 10444, 15546, 22739, 27294)} + }, + { + { AOM_CDF9(6402, 8148, 12623, 15072, 18728, 22847, 26447, 29377)}, + { AOM_CDF9(1674, 3252, 5734, 10159, 22397, 23802, 24821, 30940)} + } + }, + { + { + { AOM_CDF9(3089, 3920, 6038, 9460, 14266, 19881, 25766, 29176)}, + { AOM_CDF9(1084, 2358, 3488, 5122, 11483, 18103, 26023, 29799)} + }, + { + { AOM_CDF9(11514, 13794, 17480, 20754, 24361, 27378, 29492, 31277)}, + { AOM_CDF9(6571, 9610, 15516, 21826, 29092, 30829, 31842, 32708)} + } + }, + { + { + { AOM_CDF9(5348, 7113, 11820, 15924, 22106, 26777, 30334, 31757)}, + { AOM_CDF9(2453, 4474, 6307, 8777, 16474, 22975, 29000, 31547)} + }, + { + { AOM_CDF9(23110, 24597, 27140, 28894, 30167, 30927, 31392, 32094)}, + { AOM_CDF9(9998, 17661, 25178, 28097, 31308, 32038, 32403, 32695)} + } + } +}; + +static const u16 av1_default_eob_multi512_cdfs[TOKEN_CDF_Q_CTXS][PLANE_TYPES][2][16] = { + { + { + { AOM_CDF10(641, 983, 3707, 5430, 10234, 14958, 18788, 23412, 26061)}, + { AOM_CDF10(3277, 6554, 9830, 13107, 16384, 19661, 22938, 26214, 29491)} + }, + { + { AOM_CDF10(5095, 6446, 9996, 13354, 16017, 17986, 20919, 26129, 29140)}, + { AOM_CDF10(3277, 6554, 9830, 13107, 16384, 19661, 22938, 26214, 29491)} + } + }, + { + { + { AOM_CDF10(1230, 2278, 5035, 7776, 11871, 15346, 19590, 24584, 28749)}, + { AOM_CDF10(3277, 6554, 9830, 13107, 16384, 19661, 22938, 26214, 29491)} + }, + { + { AOM_CDF10(7265, 9979, 15819, 19250, 21780, 23846, 26478, 28396, 31811)}, + { AOM_CDF10(3277, 6554, 9830, 13107, 16384, 19661, 22938, 26214, 29491)} + } + }, + { + { + { AOM_CDF10(2624, 3936, 6480, 9686, 13979, 17726, 23267, 28410, 31078)}, + { AOM_CDF10(3277, 6554, 9830, 13107, 16384, 19661, 22938, 26214, 29491)} + }, + { + { AOM_CDF10(12015, 14769, 19588, 22052, 24222, 25812, 27300, 29219, 32114)}, + { AOM_CDF10(3277, 6554, 9830, 13107, 16384, 19661, 22938, 26214, 29491)} + } + }, + { + { + { AOM_CDF10(5927, 7809, 10923, 14597, 19439, 24135, 28456, 31142, 32060)}, + { AOM_CDF10(3277, 6554, 9830, 13107, 16384, 19661, 22938, 26214, 29491)} + }, + { + { AOM_CDF10(21093, 23043, 25742, 27658, 29097, 29716, 30073, 30820, 31956)}, + { AOM_CDF10(3277, 6554, 9830, 13107, 16384, 19661, 22938, 26214, 29491)} + } + } +}; + +static const u16 av1_default_eob_multi1024_cdfs[TOKEN_CDF_Q_CTXS][PLANE_TYPES][2][16] = { + { + { + { AOM_CDF11(393, 421, 751, 1623, 3160, + 6352, 13345, 18047, 22571, 25830)}, + { AOM_CDF11(2979, 5958, 8937, 11916, 14895, + 17873, 20852, 23831, 26810, 29789)} + }, + { + { AOM_CDF11(1865, 1988, 2930, 4242, 10533, + 16538, 21354, 27255, 28546, 31784)}, + { AOM_CDF11(2979, 5958, 8937, 11916, 14895, + 17873, 20852, 23831, 26810, 29789)} + } + }, + { + { + { AOM_CDF11(696, 948, 3145, 5702, 9706, + 13217, 17851, 21856, 25692, 28034)}, + { AOM_CDF11(2979, 5958, 8937, 11916, 14895, + 17873, 20852, 23831, 26810, 29789)} + }, + { + { AOM_CDF11(2672, 3591, 9330, 17084, 22725, + 24284, 26527, 28027, 28377, 30876)}, + { AOM_CDF11(2979, 5958, 8937, 11916, 14895, + 17873, 20852, 23831, 26810, 29789)} + } + }, + { + { + { AOM_CDF11(2784, 3831, 7041, 10521, 14847, + 18844, 23155, 26682, 29229, 31045)}, + { AOM_CDF11(2979, 5958, 8937, 11916, 14895, + 17873, 20852, 23831, 26810, 29789)} + }, + { + { AOM_CDF11(9577, 12466, 17739, 20750, 22061, + 23215, 24601, 25483, 25843, 32056)}, + { AOM_CDF11(2979, 5958, 8937, 11916, 14895, + 17873, 20852, 23831, 26810, 29789)} + } + }, + { + { + { AOM_CDF11(6698, 8334, 11961, 15762, 20186, + 23862, 27434, 29326, 31082, 32050)}, + { AOM_CDF11(2979, 5958, 8937, 11916, 14895, + 17873, 20852, 23831, 26810, 29789)} + }, + { + { AOM_CDF11(20569, 22426, 25569, 26859, 28053, + 28913, 29486, 29724, 29807, 32570)}, + { AOM_CDF11(2979, 5958, 8937, 11916, 14895, + 17873, 20852, 23831, 26810, 29789)} + } + } +}; + +static const u16 av1_default_coeff_lps_multi_cdfs[TOKEN_CDF_Q_CTXS] + [TX_SIZES][PLANE_TYPES][LEVEL_CONTEXTS][CDF_SIZE(BR_CDF_SIZE) + 1] = { + { + { + { + { AOM_CDF4(14298, 20718, 24174)}, { AOM_CDF4(12536, 19601, 23789)}, + { AOM_CDF4(8712, 15051, 19503)}, { AOM_CDF4(6170, 11327, 15434)}, + { AOM_CDF4(4742, 8926, 12538)}, { AOM_CDF4(3803, 7317, 10546)}, + { AOM_CDF4(1696, 3317, 4871)}, { AOM_CDF4(14392, 19951, 22756)}, + { AOM_CDF4(15978, 23218, 26818)}, { AOM_CDF4(12187, 19474, 23889)}, + { AOM_CDF4(9176, 15640, 20259)}, { AOM_CDF4(7068, 12655, 17028)}, + { AOM_CDF4(5656, 10442, 14472)}, { AOM_CDF4(2580, 4992, 7244)}, + { AOM_CDF4(12136, 18049, 21426)}, { AOM_CDF4(13784, 20721, 24481)}, + { AOM_CDF4(10836, 17621, 21900)}, { AOM_CDF4(8372, 14444, 18847)}, + { AOM_CDF4(6523, 11779, 16000)}, { AOM_CDF4(5337, 9898, 13760)}, + { AOM_CDF4(3034, 5860, 8462)} + }, + { + { AOM_CDF4(15967, 22905, 26286)}, { AOM_CDF4(13534, 20654, 24579)}, + { AOM_CDF4(9504, 16092, 20535)}, { AOM_CDF4(6975, 12568, 16903)}, + { AOM_CDF4(5364, 10091, 14020)}, { AOM_CDF4(4357, 8370, 11857)}, + { AOM_CDF4(2506, 4934, 7218)}, { AOM_CDF4(23032, 28815, 30936)}, + { AOM_CDF4(19540, 26704, 29719)}, { AOM_CDF4(15158, 22969, 27097)}, + { AOM_CDF4(11408, 18865, 23650)}, { AOM_CDF4(8885, 15448, 20250)}, + { AOM_CDF4(7108, 12853, 17416)}, { AOM_CDF4(4231, 8041, 11480)}, + { AOM_CDF4(19823, 26490, 29156)}, { AOM_CDF4(18890, 25929, 28932)}, + { AOM_CDF4(15660, 23491, 27433)}, { AOM_CDF4(12147, 19776, 24488)}, + { AOM_CDF4(9728, 16774, 21649)}, { AOM_CDF4(7919, 14277, 19066)}, + { AOM_CDF4(5440, 10170, 14185)} + } + }, + { + { + { AOM_CDF4(14406, 20862, 24414)}, { AOM_CDF4(11824, 18907, 23109)}, + { AOM_CDF4(8257, 14393, 18803)}, { AOM_CDF4(5860, 10747, 14778)}, + { AOM_CDF4(4475, 8486, 11984)}, { AOM_CDF4(3606, 6954, 10043)}, + { AOM_CDF4(1736, 3410, 5048)}, { AOM_CDF4(14430, 20046, 22882)}, + { AOM_CDF4(15593, 22899, 26709)}, { AOM_CDF4(12102, 19368, 23811)}, + { AOM_CDF4(9059, 15584, 20262)}, { AOM_CDF4(6999, 12603, 17048)}, + { AOM_CDF4(5684, 10497, 14553)}, { AOM_CDF4(2822, 5438, 7862)}, + { AOM_CDF4(15785, 21585, 24359)}, { AOM_CDF4(18347, 25229, 28266)}, + { AOM_CDF4(14974, 22487, 26389)}, { AOM_CDF4(11423, 18681, 23271)}, + { AOM_CDF4(8863, 15350, 20008)}, { AOM_CDF4(7153, 12852, 17278)}, + { AOM_CDF4(3707, 7036, 9982)} + }, + { + { AOM_CDF4(15460, 21696, 25469)}, { AOM_CDF4(12170, 19249, 23191)}, + { AOM_CDF4(8723, 15027, 19332)}, { AOM_CDF4(6428, 11704, 15874)}, + { AOM_CDF4(4922, 9292, 13052)}, { AOM_CDF4(4139, 7695, 11010)}, + { AOM_CDF4(2291, 4508, 6598)}, { AOM_CDF4(19856, 26920, 29828)}, + { AOM_CDF4(17923, 25289, 28792)}, { AOM_CDF4(14278, 21968, 26297)}, + { AOM_CDF4(10910, 18136, 22950)}, { AOM_CDF4(8423, 14815, 19627)}, + { AOM_CDF4(6771, 12283, 16774)}, { AOM_CDF4(4074, 7750, 11081)}, + { AOM_CDF4(19852, 26074, 28672)}, { AOM_CDF4(19371, 26110, 28989)}, + { AOM_CDF4(16265, 23873, 27663)}, { AOM_CDF4(12758, 20378, 24952)}, + { AOM_CDF4(10095, 17098, 21961)}, { AOM_CDF4(8250, 14628, 19451)}, + { AOM_CDF4(5205, 9745, 13622)} + } + }, + { + { + { AOM_CDF4(10563, 16233, 19763)}, { AOM_CDF4(9794, 16022, 19804)}, + { AOM_CDF4(6750, 11945, 15759)}, { AOM_CDF4(4963, 9186, 12752)}, + { AOM_CDF4(3845, 7435, 10627)}, { AOM_CDF4(3051, 6085, 8834)}, + { AOM_CDF4(1311, 2596, 3830)}, { AOM_CDF4(11246, 16404, 19689)}, + { AOM_CDF4(12315, 18911, 22731)}, { AOM_CDF4(10557, 17095, 21289)}, + { AOM_CDF4(8136, 14006, 18249)}, { AOM_CDF4(6348, 11474, 15565)}, + { AOM_CDF4(5196, 9655, 13400)}, { AOM_CDF4(2349, 4526, 6587)}, + { AOM_CDF4(13337, 18730, 21569)}, { AOM_CDF4(19306, 26071, 28882)}, + { AOM_CDF4(15952, 23540, 27254)}, { AOM_CDF4(12409, 19934, 24430)}, + { AOM_CDF4(9760, 16706, 21389)}, { AOM_CDF4(8004, 14220, 18818)}, + { AOM_CDF4(4138, 7794, 10961)} + }, + { + { AOM_CDF4(10870, 16684, 20949)}, { AOM_CDF4(9664, 15230, 18680)}, + { AOM_CDF4(6886, 12109, 15408)}, { AOM_CDF4(4825, 8900, 12305)}, + { AOM_CDF4(3630, 7162, 10314)}, { AOM_CDF4(3036, 6429, 9387)}, + { AOM_CDF4(1671, 3296, 4940)}, { AOM_CDF4(13819, 19159, 23026)}, + { AOM_CDF4(11984, 19108, 23120)}, { AOM_CDF4(10690, 17210, 21663)}, + { AOM_CDF4(7984, 14154, 18333)}, { AOM_CDF4(6868, 12294, 16124)}, + { AOM_CDF4(5274, 8994, 12868)}, { AOM_CDF4(2988, 5771, 8424)}, + { AOM_CDF4(19736, 26647, 29141)}, { AOM_CDF4(18933, 26070, 28984)}, + { AOM_CDF4(15779, 23048, 27200)}, { AOM_CDF4(12638, 20061, 24532)}, + { AOM_CDF4(10692, 17545, 22220)}, { AOM_CDF4(9217, 15251, 20054)}, + { AOM_CDF4(5078, 9284, 12594)} + } + }, + { + { + { AOM_CDF4(2331, 3662, 5244)}, { AOM_CDF4(2891, 4771, 6145)}, + { AOM_CDF4(4598, 7623, 9729)}, { AOM_CDF4(3520, 6845, 9199)}, + { AOM_CDF4(3417, 6119, 9324)}, { AOM_CDF4(2601, 5412, 7385)}, + { AOM_CDF4(600, 1173, 1744)}, { AOM_CDF4(7672, 13286, 17469)}, + { AOM_CDF4(4232, 7792, 10793)}, { AOM_CDF4(2915, 5317, 7397)}, + { AOM_CDF4(2318, 4356, 6152)}, { AOM_CDF4(2127, 4000, 5554)}, + { AOM_CDF4(1850, 3478, 5275)}, { AOM_CDF4(977, 1933, 2843)}, + { AOM_CDF4(18280, 24387, 27989)}, { AOM_CDF4(15852, 22671, 26185)}, + { AOM_CDF4(13845, 20951, 24789)}, { AOM_CDF4(11055, 17966, 22129)}, + { AOM_CDF4(9138, 15422, 19801)}, { AOM_CDF4(7454, 13145, 17456)}, + { AOM_CDF4(3370, 6393, 9013)} + }, + { + { AOM_CDF4(5842, 9229, 10838)}, { AOM_CDF4(2313, 3491, 4276)}, + { AOM_CDF4(2998, 6104, 7496)}, { AOM_CDF4(2420, 7447, 9868)}, + { AOM_CDF4(3034, 8495, 10923)}, { AOM_CDF4(4076, 8937, 10975)}, + { AOM_CDF4(1086, 2370, 3299)}, { AOM_CDF4(9714, 17254, 20444)}, + { AOM_CDF4(8543, 13698, 17123)}, { AOM_CDF4(4918, 9007, 11910)}, + { AOM_CDF4(4129, 7532, 10553)}, { AOM_CDF4(2364, 5533, 8058)}, + { AOM_CDF4(1834, 3546, 5563)}, { AOM_CDF4(1473, 2908, 4133)}, + { AOM_CDF4(15405, 21193, 25619)}, { AOM_CDF4(15691, 21952, 26561)}, + { AOM_CDF4(12962, 19194, 24165)}, { AOM_CDF4(10272, 17855, 22129)}, + { AOM_CDF4(8588, 15270, 20718)}, { AOM_CDF4(8682, 14669, 19500)}, + { AOM_CDF4(4870, 9636, 13205)} + } + }, + { + { + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)} + }, + { + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)} + } + } + }, + { + { + { + { AOM_CDF4(14995, 21341, 24749)}, { AOM_CDF4(13158, 20289, 24601)}, + { AOM_CDF4(8941, 15326, 19876)}, { AOM_CDF4(6297, 11541, 15807)}, + { AOM_CDF4(4817, 9029, 12776)}, { AOM_CDF4(3731, 7273, 10627)}, + { AOM_CDF4(1847, 3617, 5354)}, { AOM_CDF4(14472, 19659, 22343)}, + { AOM_CDF4(16806, 24162, 27533)}, { AOM_CDF4(12900, 20404, 24713)}, + { AOM_CDF4(9411, 16112, 20797)}, { AOM_CDF4(7056, 12697, 17148)}, + { AOM_CDF4(5544, 10339, 14460)}, { AOM_CDF4(2954, 5704, 8319)}, + { AOM_CDF4(12464, 18071, 21354)}, { AOM_CDF4(15482, 22528, 26034)}, + { AOM_CDF4(12070, 19269, 23624)}, { AOM_CDF4(8953, 15406, 20106)}, + { AOM_CDF4(7027, 12730, 17220)}, { AOM_CDF4(5887, 10913, 15140)}, + { AOM_CDF4(3793, 7278, 10447)} + }, + { + { AOM_CDF4(15571, 22232, 25749)}, { AOM_CDF4(14506, 21575, 25374)}, + { AOM_CDF4(10189, 17089, 21569)}, { AOM_CDF4(7316, 13301, 17915)}, + { AOM_CDF4(5783, 10912, 15190)}, { AOM_CDF4(4760, 9155, 13088)}, + { AOM_CDF4(2993, 5966, 8774)}, { AOM_CDF4(23424, 28903, 30778)}, + { AOM_CDF4(20775, 27666, 30290)}, { AOM_CDF4(16474, 24410, 28299)}, + { AOM_CDF4(12471, 20180, 24987)}, { AOM_CDF4(9410, 16487, 21439)}, + { AOM_CDF4(7536, 13614, 18529)}, { AOM_CDF4(5048, 9586, 13549)}, + { AOM_CDF4(21090, 27290, 29756)}, { AOM_CDF4(20796, 27402, 30026)}, + { AOM_CDF4(17819, 25485, 28969)}, { AOM_CDF4(13860, 21909, 26462)}, + { AOM_CDF4(11002, 18494, 23529)}, { AOM_CDF4(8953, 15929, 20897)}, + { AOM_CDF4(6448, 11918, 16454)} + } + }, + { + { + { AOM_CDF4(15999, 22208, 25449)}, { AOM_CDF4(13050, 19988, 24122)}, + { AOM_CDF4(8594, 14864, 19378)}, { AOM_CDF4(6033, 11079, 15238)}, + { AOM_CDF4(4554, 8683, 12347)}, { AOM_CDF4(3672, 7139, 10337)}, + { AOM_CDF4(1900, 3771, 5576)}, { AOM_CDF4(15788, 21340, 23949)}, + { AOM_CDF4(16825, 24235, 27758)}, { AOM_CDF4(12873, 20402, 24810)}, + { AOM_CDF4(9590, 16363, 21094)}, { AOM_CDF4(7352, 13209, 17733)}, + { AOM_CDF4(5960, 10989, 15184)}, { AOM_CDF4(3232, 6234, 9007)}, + { AOM_CDF4(15761, 20716, 23224)}, { AOM_CDF4(19318, 25989, 28759)}, + { AOM_CDF4(15529, 23094, 26929)}, { AOM_CDF4(11662, 18989, 23641)}, + { AOM_CDF4(8955, 15568, 20366)}, { AOM_CDF4(7281, 13106, 17708)}, + { AOM_CDF4(4248, 8059, 11440)} + }, + { + { AOM_CDF4(14899, 21217, 24503)}, { AOM_CDF4(13519, 20283, 24047)}, + { AOM_CDF4(9429, 15966, 20365)}, { AOM_CDF4(6700, 12355, 16652)}, + { AOM_CDF4(5088, 9704, 13716)}, { AOM_CDF4(4243, 8154, 11731)}, + { AOM_CDF4(2702, 5364, 7861)}, { AOM_CDF4(22745, 28388, 30454)}, + { AOM_CDF4(20235, 27146, 29922)}, { AOM_CDF4(15896, 23715, 27637)}, + { AOM_CDF4(11840, 19350, 24131)}, { AOM_CDF4(9122, 15932, 20880)}, + { AOM_CDF4(7488, 13581, 18362)}, { AOM_CDF4(5114, 9568, 13370)}, + { AOM_CDF4(20845, 26553, 28932)}, { AOM_CDF4(20981, 27372, 29884)}, + { AOM_CDF4(17781, 25335, 28785)}, { AOM_CDF4(13760, 21708, 26297)}, + { AOM_CDF4(10975, 18415, 23365)}, { AOM_CDF4(9045, 15789, 20686)}, + { AOM_CDF4(6130, 11199, 15423)} + } + }, + { + { + { AOM_CDF4(13549, 19724, 23158)}, { AOM_CDF4(11844, 18382, 22246)}, + { AOM_CDF4(7919, 13619, 17773)}, { AOM_CDF4(5486, 10143, 13946)}, + { AOM_CDF4(4166, 7983, 11324)}, { AOM_CDF4(3364, 6506, 9427)}, + { AOM_CDF4(1598, 3160, 4674)}, { AOM_CDF4(15281, 20979, 23781)}, + { AOM_CDF4(14939, 22119, 25952)}, { AOM_CDF4(11363, 18407, 22812)}, + { AOM_CDF4(8609, 14857, 19370)}, { AOM_CDF4(6737, 12184, 16480)}, + { AOM_CDF4(5506, 10263, 14262)}, { AOM_CDF4(2990, 5786, 8380)}, + { AOM_CDF4(20249, 25253, 27417)}, { AOM_CDF4(21070, 27518, 30001)}, + { AOM_CDF4(16854, 24469, 28074)}, { AOM_CDF4(12864, 20486, 25000)}, + { AOM_CDF4(9962, 16978, 21778)}, { AOM_CDF4(8074, 14338, 19048)}, + { AOM_CDF4(4494, 8479, 11906)} + }, + { + { AOM_CDF4(13960, 19617, 22829)}, { AOM_CDF4(11150, 17341, 21228)}, + { AOM_CDF4(7150, 12964, 17190)}, { AOM_CDF4(5331, 10002, 13867)}, + { AOM_CDF4(4167, 7744, 11057)}, { AOM_CDF4(3480, 6629, 9646)}, + { AOM_CDF4(1883, 3784, 5686)}, { AOM_CDF4(18752, 25660, 28912)}, + { AOM_CDF4(16968, 24586, 28030)}, { AOM_CDF4(13520, 21055, 25313)}, + { AOM_CDF4(10453, 17626, 22280)}, { AOM_CDF4(8386, 14505, 19116)}, + { AOM_CDF4(6742, 12595, 17008)}, { AOM_CDF4(4273, 8140, 11499)}, + { AOM_CDF4(22120, 27827, 30233)}, { AOM_CDF4(20563, 27358, 29895)}, + { AOM_CDF4(17076, 24644, 28153)}, { AOM_CDF4(13362, 20942, 25309)}, + { AOM_CDF4(10794, 17965, 22695)}, { AOM_CDF4(9014, 15652, 20319)}, + { AOM_CDF4(5708, 10512, 14497)} + } + }, + { + { + { AOM_CDF4(5705, 10930, 15725)}, { AOM_CDF4(7946, 12765, 16115)}, + { AOM_CDF4(6801, 12123, 16226)}, { AOM_CDF4(5462, 10135, 14200)}, + { AOM_CDF4(4189, 8011, 11507)}, { AOM_CDF4(3191, 6229, 9408)}, + { AOM_CDF4(1057, 2137, 3212)}, { AOM_CDF4(10018, 17067, 21491)}, + { AOM_CDF4(7380, 12582, 16453)}, { AOM_CDF4(6068, 10845, 14339)}, + { AOM_CDF4(5098, 9198, 12555)}, { AOM_CDF4(4312, 8010, 11119)}, + { AOM_CDF4(3700, 6966, 9781)}, { AOM_CDF4(1693, 3326, 4887)}, + { AOM_CDF4(18757, 24930, 27774)}, { AOM_CDF4(17648, 24596, 27817)}, + { AOM_CDF4(14707, 22052, 26026)}, { AOM_CDF4(11720, 18852, 23292)}, + { AOM_CDF4(9357, 15952, 20525)}, { AOM_CDF4(7810, 13753, 18210)}, + { AOM_CDF4(3879, 7333, 10328)} + }, + { + { AOM_CDF4(8278, 13242, 15922)}, { AOM_CDF4(10547, 15867, 18919)}, + { AOM_CDF4(9106, 15842, 20609)}, { AOM_CDF4(6833, 13007, 17218)}, + { AOM_CDF4(4811, 9712, 13923)}, { AOM_CDF4(3985, 7352, 11128)}, + { AOM_CDF4(1688, 3458, 5262)}, { AOM_CDF4(12951, 21861, 26510)}, + { AOM_CDF4(9788, 16044, 20276)}, { AOM_CDF4(6309, 11244, 14870)}, + { AOM_CDF4(5183, 9349, 12566)}, { AOM_CDF4(4389, 8229, 11492)}, + { AOM_CDF4(3633, 6945, 10620)}, { AOM_CDF4(3600, 6847, 9907)}, + { AOM_CDF4(21748, 28137, 30255)}, { AOM_CDF4(19436, 26581, 29560)}, + { AOM_CDF4(16359, 24201, 27953)}, { AOM_CDF4(13961, 21693, 25871)}, + { AOM_CDF4(11544, 18686, 23322)}, { AOM_CDF4(9372, 16462, 20952)}, + { AOM_CDF4(6138, 11210, 15390)} + } + }, + { + { + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)} + }, + { + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)} + } + } + }, + { + { + { + { AOM_CDF4(16138, 22223, 25509)}, { AOM_CDF4(15347, 22430, 26332)}, + { AOM_CDF4(9614, 16736, 21332)}, { AOM_CDF4(6600, 12275, 16907)}, + { AOM_CDF4(4811, 9424, 13547)}, { AOM_CDF4(3748, 7809, 11420)}, + { AOM_CDF4(2254, 4587, 6890)}, { AOM_CDF4(15196, 20284, 23177)}, + { AOM_CDF4(18317, 25469, 28451)}, { AOM_CDF4(13918, 21651, 25842)}, + { AOM_CDF4(10052, 17150, 21995)}, { AOM_CDF4(7499, 13630, 18587)}, + { AOM_CDF4(6158, 11417, 16003)}, { AOM_CDF4(4014, 7785, 11252)}, + { AOM_CDF4(15048, 21067, 24384)}, { AOM_CDF4(18202, 25346, 28553)}, + { AOM_CDF4(14302, 22019, 26356)}, { AOM_CDF4(10839, 18139, 23166)}, + { AOM_CDF4(8715, 15744, 20806)}, { AOM_CDF4(7536, 13576, 18544)}, + { AOM_CDF4(5413, 10335, 14498)} + }, + { + { AOM_CDF4(17394, 24501, 27895)}, { AOM_CDF4(15889, 23420, 27185)}, + { AOM_CDF4(11561, 19133, 23870)}, { AOM_CDF4(8285, 14812, 19844)}, + { AOM_CDF4(6496, 12043, 16550)}, { AOM_CDF4(4771, 9574, 13677)}, + { AOM_CDF4(3603, 6830, 10144)}, { AOM_CDF4(21656, 27704, 30200)}, + { AOM_CDF4(21324, 27915, 30511)}, { AOM_CDF4(17327, 25336, 28997)}, + { AOM_CDF4(13417, 21381, 26033)}, { AOM_CDF4(10132, 17425, 22338)}, + { AOM_CDF4(8580, 15016, 19633)}, { AOM_CDF4(5694, 11477, 16411)}, + { AOM_CDF4(24116, 29780, 31450)}, { AOM_CDF4(23853, 29695, 31591)}, + { AOM_CDF4(20085, 27614, 30428)}, { AOM_CDF4(15326, 24335, 28575)}, + { AOM_CDF4(11814, 19472, 24810)}, { AOM_CDF4(10221, 18611, 24767)}, + { AOM_CDF4(7689, 14558, 20321)} + } + }, + { + { + { AOM_CDF4(16214, 22380, 25770)}, { AOM_CDF4(14213, 21304, 25295)}, + { AOM_CDF4(9213, 15823, 20455)}, { AOM_CDF4(6395, 11758, 16139)}, + { AOM_CDF4(4779, 9187, 13066)}, { AOM_CDF4(3821, 7501, 10953)}, + { AOM_CDF4(2293, 4567, 6795)}, { AOM_CDF4(15859, 21283, 23820)}, + { AOM_CDF4(18404, 25602, 28726)}, { AOM_CDF4(14325, 21980, 26206)}, + { AOM_CDF4(10669, 17937, 22720)}, { AOM_CDF4(8297, 14642, 19447)}, + { AOM_CDF4(6746, 12389, 16893)}, { AOM_CDF4(4324, 8251, 11770)}, + { AOM_CDF4(16532, 21631, 24475)}, { AOM_CDF4(20667, 27150, 29668)}, + { AOM_CDF4(16728, 24510, 28175)}, { AOM_CDF4(12861, 20645, 25332)}, + { AOM_CDF4(10076, 17361, 22417)}, { AOM_CDF4(8395, 14940, 19963)}, + { AOM_CDF4(5731, 10683, 14912)} + }, + { + { AOM_CDF4(14433, 21155, 24938)}, { AOM_CDF4(14658, 21716, 25545)}, + { AOM_CDF4(9923, 16824, 21557)}, { AOM_CDF4(6982, 13052, 17721)}, + { AOM_CDF4(5419, 10503, 15050)}, { AOM_CDF4(4852, 9162, 13014)}, + { AOM_CDF4(3271, 6395, 9630)}, { AOM_CDF4(22210, 27833, 30109)}, + { AOM_CDF4(20750, 27368, 29821)}, { AOM_CDF4(16894, 24828, 28573)}, + { AOM_CDF4(13247, 21276, 25757)}, { AOM_CDF4(10038, 17265, 22563)}, + { AOM_CDF4(8587, 14947, 20327)}, { AOM_CDF4(5645, 11371, 15252)}, + { AOM_CDF4(22027, 27526, 29714)}, { AOM_CDF4(23098, 29146, 31221)}, + { AOM_CDF4(19886, 27341, 30272)}, { AOM_CDF4(15609, 23747, 28046)}, + { AOM_CDF4(11993, 20065, 24939)}, { AOM_CDF4(9637, 18267, 23671)}, + { AOM_CDF4(7625, 13801, 19144)} + } + }, + { + { + { AOM_CDF4(14438, 20798, 24089)}, { AOM_CDF4(12621, 19203, 23097)}, + { AOM_CDF4(8177, 14125, 18402)}, { AOM_CDF4(5674, 10501, 14456)}, + { AOM_CDF4(4236, 8239, 11733)}, { AOM_CDF4(3447, 6750, 9806)}, + { AOM_CDF4(1986, 3950, 5864)}, { AOM_CDF4(16208, 22099, 24930)}, + { AOM_CDF4(16537, 24025, 27585)}, { AOM_CDF4(12780, 20381, 24867)}, + { AOM_CDF4(9767, 16612, 21416)}, { AOM_CDF4(7686, 13738, 18398)}, + { AOM_CDF4(6333, 11614, 15964)}, { AOM_CDF4(3941, 7571, 10836)}, + { AOM_CDF4(22819, 27422, 29202)}, { AOM_CDF4(22224, 28514, 30721)}, + { AOM_CDF4(17660, 25433, 28913)}, { AOM_CDF4(13574, 21482, 26002)}, + { AOM_CDF4(10629, 17977, 22938)}, { AOM_CDF4(8612, 15298, 20265)}, + { AOM_CDF4(5607, 10491, 14596)} + }, + { + { AOM_CDF4(13569, 19800, 23206)}, { AOM_CDF4(13128, 19924, 23869)}, + { AOM_CDF4(8329, 14841, 19403)}, { AOM_CDF4(6130, 10976, 15057)}, + { AOM_CDF4(4682, 8839, 12518)}, { AOM_CDF4(3656, 7409, 10588)}, + { AOM_CDF4(2577, 5099, 7412)}, { AOM_CDF4(22427, 28684, 30585)}, + { AOM_CDF4(20913, 27750, 30139)}, { AOM_CDF4(15840, 24109, 27834)}, + { AOM_CDF4(12308, 20029, 24569)}, { AOM_CDF4(10216, 16785, 21458)}, + { AOM_CDF4(8309, 14203, 19113)}, { AOM_CDF4(6043, 11168, 15307)}, + { AOM_CDF4(23166, 28901, 30998)}, { AOM_CDF4(21899, 28405, 30751)}, + { AOM_CDF4(18413, 26091, 29443)}, { AOM_CDF4(15233, 23114, 27352)}, + { AOM_CDF4(12683, 20472, 25288)}, { AOM_CDF4(10702, 18259, 23409)}, + { AOM_CDF4(8125, 14464, 19226)} + } + }, + { + { + { AOM_CDF4(9040, 14786, 18360)}, { AOM_CDF4(9979, 15718, 19415)}, + { AOM_CDF4(7913, 13918, 18311)}, { AOM_CDF4(5859, 10889, 15184)}, + { AOM_CDF4(4593, 8677, 12510)}, { AOM_CDF4(3820, 7396, 10791)}, + { AOM_CDF4(1730, 3471, 5192)}, { AOM_CDF4(11803, 18365, 22709)}, + { AOM_CDF4(11419, 18058, 22225)}, { AOM_CDF4(9418, 15774, 20243)}, + { AOM_CDF4(7539, 13325, 17657)}, { AOM_CDF4(6233, 11317, 15384)}, + { AOM_CDF4(5137, 9656, 13545)}, { AOM_CDF4(2977, 5774, 8349)}, + { AOM_CDF4(21207, 27246, 29640)}, { AOM_CDF4(19547, 26578, 29497)}, + { AOM_CDF4(16169, 23871, 27690)}, { AOM_CDF4(12820, 20458, 25018)}, + { AOM_CDF4(10224, 17332, 22214)}, { AOM_CDF4(8526, 15048, 19884)}, + { AOM_CDF4(5037, 9410, 13118)} + }, + { + { AOM_CDF4(12339, 17329, 20140)}, { AOM_CDF4(13505, 19895, 23225)}, + { AOM_CDF4(9847, 16944, 21564)}, { AOM_CDF4(7280, 13256, 18348)}, + { AOM_CDF4(4712, 10009, 14454)}, { AOM_CDF4(4361, 7914, 12477)}, + { AOM_CDF4(2870, 5628, 7995)}, { AOM_CDF4(20061, 25504, 28526)}, + { AOM_CDF4(15235, 22878, 26145)}, { AOM_CDF4(12985, 19958, 24155)}, + { AOM_CDF4(9782, 16641, 21403)}, { AOM_CDF4(9456, 16360, 20760)}, + { AOM_CDF4(6855, 12940, 18557)}, { AOM_CDF4(5661, 10564, 15002)}, + { AOM_CDF4(25656, 30602, 31894)}, { AOM_CDF4(22570, 29107, 31092)}, + { AOM_CDF4(18917, 26423, 29541)}, { AOM_CDF4(15940, 23649, 27754)}, + { AOM_CDF4(12803, 20581, 25219)}, { AOM_CDF4(11082, 18695, 23376)}, + { AOM_CDF4(7939, 14373, 19005)} + } + }, + { + { + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)} + }, + { + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)} + } + } + }, + { + { + { + { AOM_CDF4(18315, 24289, 27551)}, { AOM_CDF4(16854, 24068, 27835)}, + { AOM_CDF4(10140, 17927, 23173)}, { AOM_CDF4(6722, 12982, 18267)}, + { AOM_CDF4(4661, 9826, 14706)}, { AOM_CDF4(3832, 8165, 12294)}, + { AOM_CDF4(2795, 6098, 9245)}, { AOM_CDF4(17145, 23326, 26672)}, + { AOM_CDF4(20733, 27680, 30308)}, { AOM_CDF4(16032, 24461, 28546)}, + { AOM_CDF4(11653, 20093, 25081)}, { AOM_CDF4(9290, 16429, 22086)}, + { AOM_CDF4(7796, 14598, 19982)}, { AOM_CDF4(6502, 12378, 17441)}, + { AOM_CDF4(21681, 27732, 30320)}, { AOM_CDF4(22389, 29044, 31261)}, + { AOM_CDF4(19027, 26731, 30087)}, { AOM_CDF4(14739, 23755, 28624)}, + { AOM_CDF4(11358, 20778, 25511)}, { AOM_CDF4(10995, 18073, 24190)}, + { AOM_CDF4(9162, 14990, 20617)} + }, + { + { AOM_CDF4(21425, 27952, 30388)}, { AOM_CDF4(18062, 25838, 29034)}, + { AOM_CDF4(11956, 19881, 24808)}, { AOM_CDF4(7718, 15000, 20980)}, + { AOM_CDF4(5702, 11254, 16143)}, { AOM_CDF4(4898, 9088, 16864)}, + { AOM_CDF4(3679, 6776, 11907)}, { AOM_CDF4(23294, 30160, 31663)}, + { AOM_CDF4(24397, 29896, 31836)}, { AOM_CDF4(19245, 27128, 30593)}, + { AOM_CDF4(13202, 19825, 26404)}, { AOM_CDF4(11578, 19297, 23957)}, + { AOM_CDF4(8073, 13297, 21370)}, { AOM_CDF4(5461, 10923, 19745)}, + { AOM_CDF4(27367, 30521, 31934)}, { AOM_CDF4(24904, 30671, 31940)}, + { AOM_CDF4(23075, 28460, 31299)}, { AOM_CDF4(14400, 23658, 30417)}, + { AOM_CDF4(13885, 23882, 28325)}, { AOM_CDF4(14746, 22938, 27853)}, + { AOM_CDF4(5461, 16384, 27307)} + } + }, + { + { + { AOM_CDF4(18274, 24813, 27890)}, { AOM_CDF4(15537, 23149, 27003)}, + { AOM_CDF4(9449, 16740, 21827)}, { AOM_CDF4(6700, 12498, 17261)}, + { AOM_CDF4(4988, 9866, 14198)}, { AOM_CDF4(4236, 8147, 11902)}, + { AOM_CDF4(2867, 5860, 8654)}, { AOM_CDF4(17124, 23171, 26101)}, + { AOM_CDF4(20396, 27477, 30148)}, { AOM_CDF4(16573, 24629, 28492)}, + { AOM_CDF4(12749, 20846, 25674)}, { AOM_CDF4(10233, 17878, 22818)}, + { AOM_CDF4(8525, 15332, 20363)}, { AOM_CDF4(6283, 11632, 16255)}, + { AOM_CDF4(20466, 26511, 29286)}, { AOM_CDF4(23059, 29174, 31191)}, + { AOM_CDF4(19481, 27263, 30241)}, { AOM_CDF4(15458, 23631, 28137)}, + { AOM_CDF4(12416, 20608, 25693)}, { AOM_CDF4(10261, 18011, 23261)}, + { AOM_CDF4(8016, 14655, 19666)} + }, + { + { AOM_CDF4(17616, 24586, 28112)}, { AOM_CDF4(15809, 23299, 27155)}, + { AOM_CDF4(10767, 18890, 23793)}, { AOM_CDF4(7727, 14255, 18865)}, + { AOM_CDF4(6129, 11926, 16882)}, { AOM_CDF4(4482, 9704, 14861)}, + { AOM_CDF4(3277, 7452, 11522)}, { AOM_CDF4(22956, 28551, 30730)}, + { AOM_CDF4(22724, 28937, 30961)}, { AOM_CDF4(18467, 26324, 29580)}, + { AOM_CDF4(13234, 20713, 25649)}, { AOM_CDF4(11181, 17592, 22481)}, + { AOM_CDF4(8291, 18358, 24576)}, { AOM_CDF4(7568, 11881, 14984)}, + { AOM_CDF4(24948, 29001, 31147)}, { AOM_CDF4(25674, 30619, 32151)}, + { AOM_CDF4(20841, 26793, 29603)}, { AOM_CDF4(14669, 24356, 28666)}, + { AOM_CDF4(11334, 23593, 28219)}, { AOM_CDF4(8922, 14762, 22873)}, + { AOM_CDF4(8301, 13544, 20535)} + } + }, + { + { + { AOM_CDF4(17113, 23733, 27081)}, { AOM_CDF4(14139, 21406, 25452)}, + { AOM_CDF4(8552, 15002, 19776)}, { AOM_CDF4(5871, 11120, 15378)}, + { AOM_CDF4(4455, 8616, 12253)}, { AOM_CDF4(3469, 6910, 10386)}, + { AOM_CDF4(2255, 4553, 6782)}, { AOM_CDF4(18224, 24376, 27053)}, + { AOM_CDF4(19290, 26710, 29614)}, { AOM_CDF4(14936, 22991, 27184)}, + { AOM_CDF4(11238, 18951, 23762)}, { AOM_CDF4(8786, 15617, 20588)}, + { AOM_CDF4(7317, 13228, 18003)}, { AOM_CDF4(5101, 9512, 13493)}, + { AOM_CDF4(22639, 28222, 30210)}, { AOM_CDF4(23216, 29331, 31307)}, + { AOM_CDF4(19075, 26762, 29895)}, { AOM_CDF4(15014, 23113, 27457)}, + { AOM_CDF4(11938, 19857, 24752)}, { AOM_CDF4(9942, 17280, 22282)}, + { AOM_CDF4(7167, 13144, 17752)} + }, + { + { AOM_CDF4(15820, 22738, 26488)}, { AOM_CDF4(13530, 20885, 25216)}, + { AOM_CDF4(8395, 15530, 20452)}, { AOM_CDF4(6574, 12321, 16380)}, + { AOM_CDF4(5353, 10419, 14568)}, { AOM_CDF4(4613, 8446, 12381)}, + { AOM_CDF4(3440, 7158, 9903)}, { AOM_CDF4(24247, 29051, 31224)}, + { AOM_CDF4(22118, 28058, 30369)}, { AOM_CDF4(16498, 24768, 28389)}, + { AOM_CDF4(12920, 21175, 26137)}, { AOM_CDF4(10730, 18619, 25352)}, + { AOM_CDF4(10187, 16279, 22791)}, { AOM_CDF4(9310, 14631, 22127)}, + { AOM_CDF4(24970, 30558, 32057)}, { AOM_CDF4(24801, 29942, 31698)}, + { AOM_CDF4(22432, 28453, 30855)}, { AOM_CDF4(19054, 25680, 29580)}, + { AOM_CDF4(14392, 23036, 28109)}, { AOM_CDF4(12495, 20947, 26650)}, + { AOM_CDF4(12442, 20326, 26214)} + } + }, + { + { + { AOM_CDF4(12162, 18785, 22648)}, { AOM_CDF4(12749, 19697, 23806)}, + { AOM_CDF4(8580, 15297, 20346)}, { AOM_CDF4(6169, 11749, 16543)}, + { AOM_CDF4(4836, 9391, 13448)}, { AOM_CDF4(3821, 7711, 11613)}, + { AOM_CDF4(2228, 4601, 7070)}, { AOM_CDF4(16319, 24725, 28280)}, + { AOM_CDF4(15698, 23277, 27168)}, { AOM_CDF4(12726, 20368, 25047)}, + { AOM_CDF4(9912, 17015, 21976)}, { AOM_CDF4(7888, 14220, 19179)}, + { AOM_CDF4(6777, 12284, 17018)}, { AOM_CDF4(4492, 8590, 12252)}, + { AOM_CDF4(23249, 28904, 30947)}, { AOM_CDF4(21050, 27908, 30512)}, + { AOM_CDF4(17440, 25340, 28949)}, { AOM_CDF4(14059, 22018, 26541)}, + { AOM_CDF4(11288, 18903, 23898)}, { AOM_CDF4(9411, 16342, 21428)}, + { AOM_CDF4(6278, 11588, 15944)} + }, + { + { AOM_CDF4(13981, 20067, 23226)}, { AOM_CDF4(16922, 23580, 26783)}, + { AOM_CDF4(11005, 19039, 24487)}, { AOM_CDF4(7389, 14218, 19798)}, + { AOM_CDF4(5598, 11505, 17206)}, { AOM_CDF4(6090, 11213, 15659)}, + { AOM_CDF4(3820, 7371, 10119)}, { AOM_CDF4(21082, 26925, 29675)}, + { AOM_CDF4(21262, 28627, 31128)}, { AOM_CDF4(18392, 26454, 30437)}, + { AOM_CDF4(14870, 22910, 27096)}, { AOM_CDF4(12620, 19484, 24908)}, + { AOM_CDF4(9290, 16553, 22802)}, { AOM_CDF4(6668, 14288, 20004)}, + { AOM_CDF4(27704, 31055, 31949)}, { AOM_CDF4(24709, 29978, 31788)}, + { AOM_CDF4(21668, 29264, 31657)}, { AOM_CDF4(18295, 26968, 30074)}, + { AOM_CDF4(16399, 24422, 29313)}, { AOM_CDF4(14347, 23026, 28104)}, + { AOM_CDF4(12370, 19806, 24477)} + } + }, + { + { + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)} + }, + { + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)} + } + } + } +}; + +static const u16 av1_default_coeff_base_multi_cdfs + [TOKEN_CDF_Q_CTXS][TX_SIZES][PLANE_TYPES] + [SIG_COEF_CONTEXTS][CDF_SIZE(NUM_BASE_LEVELS + 2) + 1] = { + { + { + { + { AOM_CDF4(4034, 8930, 12727)}, { AOM_CDF4(18082, 29741, 31877)}, + { AOM_CDF4(12596, 26124, 30493)}, { AOM_CDF4(9446, 21118, 27005)}, + { AOM_CDF4(6308, 15141, 21279)}, { AOM_CDF4(2463, 6357, 9783)}, + { AOM_CDF4(20667, 30546, 31929)}, { AOM_CDF4(13043, 26123, 30134)}, + { AOM_CDF4(8151, 18757, 24778)}, { AOM_CDF4(5255, 12839, 18632)}, + { AOM_CDF4(2820, 7206, 11161)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(15736, 27553, 30604)}, + { AOM_CDF4(11210, 23794, 28787)}, { AOM_CDF4(5947, 13874, 19701)}, + { AOM_CDF4(4215, 9323, 13891)}, { AOM_CDF4(2833, 6462, 10059)}, + { AOM_CDF4(19605, 30393, 31582)}, { AOM_CDF4(13523, 26252, 30248)}, + { AOM_CDF4(8446, 18622, 24512)}, { AOM_CDF4(3818, 10343, 15974)}, + { AOM_CDF4(1481, 4117, 6796)}, { AOM_CDF4(22649, 31302, 32190)}, + { AOM_CDF4(14829, 27127, 30449)}, { AOM_CDF4(8313, 17702, 23304)}, + { AOM_CDF4(3022, 8301, 12786)}, { AOM_CDF4(1536, 4412, 7184)}, + { AOM_CDF4(22354, 29774, 31372)}, { AOM_CDF4(14723, 25472, 29214)}, + { AOM_CDF4(6673, 13745, 18662)}, { AOM_CDF4(2068, 5766, 9322)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)} + }, + { + { AOM_CDF4(6302, 16444, 21761)}, { AOM_CDF4(23040, 31538, 32475)}, + { AOM_CDF4(15196, 28452, 31496)}, { AOM_CDF4(10020, 22946, 28514)}, + { AOM_CDF4(6533, 16862, 23501)}, { AOM_CDF4(3538, 9816, 15076)}, + { AOM_CDF4(24444, 31875, 32525)}, { AOM_CDF4(15881, 28924, 31635)}, + { AOM_CDF4(9922, 22873, 28466)}, { AOM_CDF4(6527, 16966, 23691)}, + { AOM_CDF4(4114, 11303, 17220)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(20201, 30770, 32209)}, + { AOM_CDF4(14754, 28071, 31258)}, { AOM_CDF4(8378, 20186, 26517)}, + { AOM_CDF4(5916, 15299, 21978)}, { AOM_CDF4(4268, 11583, 17901)}, + { AOM_CDF4(24361, 32025, 32581)}, { AOM_CDF4(18673, 30105, 31943)}, + { AOM_CDF4(10196, 22244, 27576)}, { AOM_CDF4(5495, 14349, 20417)}, + { AOM_CDF4(2676, 7415, 11498)}, { AOM_CDF4(24678, 31958, 32585)}, + { AOM_CDF4(18629, 29906, 31831)}, { AOM_CDF4(9364, 20724, 26315)}, + { AOM_CDF4(4641, 12318, 18094)}, { AOM_CDF4(2758, 7387, 11579)}, + { AOM_CDF4(25433, 31842, 32469)}, { AOM_CDF4(18795, 29289, 31411)}, + { AOM_CDF4(7644, 17584, 23592)}, { AOM_CDF4(3408, 9014, 15047)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)} + } + }, + { + { + { AOM_CDF4(4536, 10072, 14001)}, { AOM_CDF4(25459, 31416, 32206)}, + { AOM_CDF4(16605, 28048, 30818)}, { AOM_CDF4(11008, 22857, 27719)}, + { AOM_CDF4(6915, 16268, 22315)}, { AOM_CDF4(2625, 6812, 10537)}, + { AOM_CDF4(24257, 31788, 32499)}, { AOM_CDF4(16880, 29454, 31879)}, + { AOM_CDF4(11958, 25054, 29778)}, { AOM_CDF4(7916, 18718, 25084)}, + { AOM_CDF4(3383, 8777, 13446)}, { AOM_CDF4(22720, 31603, 32393)}, + { AOM_CDF4(14960, 28125, 31335)}, { AOM_CDF4(9731, 22210, 27928)}, + { AOM_CDF4(6304, 15832, 22277)}, { AOM_CDF4(2910, 7818, 12166)}, + { AOM_CDF4(20375, 30627, 32131)}, { AOM_CDF4(13904, 27284, 30887)}, + { AOM_CDF4(9368, 21558, 27144)}, { AOM_CDF4(5937, 14966, 21119)}, + { AOM_CDF4(2667, 7225, 11319)}, { AOM_CDF4(23970, 31470, 32378)}, + { AOM_CDF4(17173, 29734, 32018)}, { AOM_CDF4(12795, 25441, 29965)}, + { AOM_CDF4(8981, 19680, 25893)}, { AOM_CDF4(4728, 11372, 16902)}, + { AOM_CDF4(24287, 31797, 32439)}, { AOM_CDF4(16703, 29145, 31696)}, + { AOM_CDF4(10833, 23554, 28725)}, { AOM_CDF4(6468, 16566, 23057)}, + { AOM_CDF4(2415, 6562, 10278)}, { AOM_CDF4(26610, 32395, 32659)}, + { AOM_CDF4(18590, 30498, 32117)}, { AOM_CDF4(12420, 25756, 29950)}, + { AOM_CDF4(7639, 18746, 24710)}, { AOM_CDF4(3001, 8086, 12347)}, + { AOM_CDF4(25076, 32064, 32580)}, { AOM_CDF4(17946, 30128, 32028)}, + { AOM_CDF4(12024, 24985, 29378)}, { AOM_CDF4(7517, 18390, 24304)}, + { AOM_CDF4(3243, 8781, 13331)}, { AOM_CDF4(8192, 16384, 24576)} + }, + { + { AOM_CDF4(6037, 16771, 21957)}, { AOM_CDF4(24774, 31704, 32426)}, + { AOM_CDF4(16830, 28589, 31056)}, { AOM_CDF4(10602, 22828, 27760)}, + { AOM_CDF4(6733, 16829, 23071)}, { AOM_CDF4(3250, 8914, 13556)}, + { AOM_CDF4(25582, 32220, 32668)}, { AOM_CDF4(18659, 30342, 32223)}, + { AOM_CDF4(12546, 26149, 30515)}, { AOM_CDF4(8420, 20451, 26801)}, + { AOM_CDF4(4636, 12420, 18344)}, { AOM_CDF4(27581, 32362, 32639)}, + { AOM_CDF4(18987, 30083, 31978)}, { AOM_CDF4(11327, 24248, 29084)}, + { AOM_CDF4(7264, 17719, 24120)}, { AOM_CDF4(3995, 10768, 16169)}, + { AOM_CDF4(25893, 31831, 32487)}, { AOM_CDF4(16577, 28587, 31379)}, + { AOM_CDF4(10189, 22748, 28182)}, { AOM_CDF4(6832, 17094, 23556)}, + { AOM_CDF4(3708, 10110, 15334)}, { AOM_CDF4(25904, 32282, 32656)}, + { AOM_CDF4(19721, 30792, 32276)}, { AOM_CDF4(12819, 26243, 30411)}, + { AOM_CDF4(8572, 20614, 26891)}, { AOM_CDF4(5364, 14059, 20467)}, + { AOM_CDF4(26580, 32438, 32677)}, { AOM_CDF4(20852, 31225, 32340)}, + { AOM_CDF4(12435, 25700, 29967)}, { AOM_CDF4(8691, 20825, 26976)}, + { AOM_CDF4(4446, 12209, 17269)}, { AOM_CDF4(27350, 32429, 32696)}, + { AOM_CDF4(21372, 30977, 32272)}, { AOM_CDF4(12673, 25270, 29853)}, + { AOM_CDF4(9208, 20925, 26640)}, { AOM_CDF4(5018, 13351, 18732)}, + { AOM_CDF4(27351, 32479, 32713)}, { AOM_CDF4(21398, 31209, 32387)}, + { AOM_CDF4(12162, 25047, 29842)}, { AOM_CDF4(7896, 18691, 25319)}, + { AOM_CDF4(4670, 12882, 18881)}, { AOM_CDF4(8192, 16384, 24576)} + } + }, + { + { + { AOM_CDF4(5487, 10460, 13708)}, { AOM_CDF4(21597, 28303, 30674)}, + { AOM_CDF4(11037, 21953, 26476)}, { AOM_CDF4(8147, 17962, 22952)}, + { AOM_CDF4(5242, 13061, 18532)}, { AOM_CDF4(1889, 5208, 8182)}, + { AOM_CDF4(26774, 32133, 32590)}, { AOM_CDF4(17844, 29564, 31767)}, + { AOM_CDF4(11690, 24438, 29171)}, { AOM_CDF4(7542, 18215, 24459)}, + { AOM_CDF4(2993, 8050, 12319)}, { AOM_CDF4(28023, 32328, 32591)}, + { AOM_CDF4(18651, 30126, 31954)}, { AOM_CDF4(12164, 25146, 29589)}, + { AOM_CDF4(7762, 18530, 24771)}, { AOM_CDF4(3492, 9183, 13920)}, + { AOM_CDF4(27591, 32008, 32491)}, { AOM_CDF4(17149, 28853, 31510)}, + { AOM_CDF4(11485, 24003, 28860)}, { AOM_CDF4(7697, 18086, 24210)}, + { AOM_CDF4(3075, 7999, 12218)}, { AOM_CDF4(28268, 32482, 32654)}, + { AOM_CDF4(19631, 31051, 32404)}, { AOM_CDF4(13860, 27260, 31020)}, + { AOM_CDF4(9605, 21613, 27594)}, { AOM_CDF4(4876, 12162, 17908)}, + { AOM_CDF4(27248, 32316, 32576)}, { AOM_CDF4(18955, 30457, 32075)}, + { AOM_CDF4(11824, 23997, 28795)}, { AOM_CDF4(7346, 18196, 24647)}, + { AOM_CDF4(3403, 9247, 14111)}, { AOM_CDF4(29711, 32655, 32735)}, + { AOM_CDF4(21169, 31394, 32417)}, { AOM_CDF4(13487, 27198, 30957)}, + { AOM_CDF4(8828, 21683, 27614)}, { AOM_CDF4(4270, 11451, 17038)}, + { AOM_CDF4(28708, 32578, 32731)}, { AOM_CDF4(20120, 31241, 32482)}, + { AOM_CDF4(13692, 27550, 31321)}, { AOM_CDF4(9418, 22514, 28439)}, + { AOM_CDF4(4999, 13283, 19462)}, { AOM_CDF4(8192, 16384, 24576)} + }, + { + { AOM_CDF4(5673, 14302, 19711)}, { AOM_CDF4(26251, 30701, 31834)}, + { AOM_CDF4(12782, 23783, 27803)}, { AOM_CDF4(9127, 20657, 25808)}, + { AOM_CDF4(6368, 16208, 21462)}, { AOM_CDF4(2465, 7177, 10822)}, + { AOM_CDF4(29961, 32563, 32719)}, { AOM_CDF4(18318, 29891, 31949)}, + { AOM_CDF4(11361, 24514, 29357)}, { AOM_CDF4(7900, 19603, 25607)}, + { AOM_CDF4(4002, 10590, 15546)}, { AOM_CDF4(29637, 32310, 32595)}, + { AOM_CDF4(18296, 29913, 31809)}, { AOM_CDF4(10144, 21515, 26871)}, + { AOM_CDF4(5358, 14322, 20394)}, { AOM_CDF4(3067, 8362, 13346)}, + { AOM_CDF4(28652, 32470, 32676)}, { AOM_CDF4(17538, 30771, 32209)}, + { AOM_CDF4(13924, 26882, 30494)}, { AOM_CDF4(10496, 22837, 27869)}, + { AOM_CDF4(7236, 16396, 21621)}, { AOM_CDF4(30743, 32687, 32746)}, + { AOM_CDF4(23006, 31676, 32489)}, { AOM_CDF4(14494, 27828, 31120)}, + { AOM_CDF4(10174, 22801, 28352)}, { AOM_CDF4(6242, 15281, 21043)}, + { AOM_CDF4(25817, 32243, 32720)}, { AOM_CDF4(18618, 31367, 32325)}, + { AOM_CDF4(13997, 28318, 31878)}, { AOM_CDF4(12255, 26534, 31383)}, + { AOM_CDF4(9561, 21588, 28450)}, { AOM_CDF4(28188, 32635, 32724)}, + { AOM_CDF4(22060, 32365, 32728)}, { AOM_CDF4(18102, 30690, 32528)}, + { AOM_CDF4(14196, 28864, 31999)}, { AOM_CDF4(12262, 25792, 30865)}, + { AOM_CDF4(24176, 32109, 32628)}, { AOM_CDF4(18280, 29681, 31963)}, + { AOM_CDF4(10205, 23703, 29664)}, { AOM_CDF4(7889, 20025, 27676)}, + { AOM_CDF4(6060, 16743, 23970)}, { AOM_CDF4(8192, 16384, 24576)} + } + }, + { + { + { AOM_CDF4(5141, 7096, 8260)}, { AOM_CDF4(27186, 29022, 29789)}, + { AOM_CDF4(6668, 12568, 15682)}, { AOM_CDF4(2172, 6181, 8638)}, + { AOM_CDF4(1126, 3379, 4531)}, { AOM_CDF4(443, 1361, 2254)}, + { AOM_CDF4(26083, 31153, 32436)}, { AOM_CDF4(13486, 24603, 28483)}, + { AOM_CDF4(6508, 14840, 19910)}, { AOM_CDF4(3386, 8800, 13286)}, + { AOM_CDF4(1530, 4322, 7054)}, { AOM_CDF4(29639, 32080, 32548)}, + { AOM_CDF4(15897, 27552, 30290)}, { AOM_CDF4(8588, 20047, 25383)}, + { AOM_CDF4(4889, 13339, 19269)}, { AOM_CDF4(2240, 6871, 10498)}, + { AOM_CDF4(28165, 32197, 32517)}, { AOM_CDF4(20735, 30427, 31568)}, + { AOM_CDF4(14325, 24671, 27692)}, { AOM_CDF4(5119, 12554, 17805)}, + { AOM_CDF4(1810, 5441, 8261)}, { AOM_CDF4(31212, 32724, 32748)}, + { AOM_CDF4(23352, 31766, 32545)}, { AOM_CDF4(14669, 27570, 31059)}, + { AOM_CDF4(8492, 20894, 27272)}, { AOM_CDF4(3644, 10194, 15204)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)} + }, + { + { AOM_CDF4(2461, 7013, 9371)}, { AOM_CDF4(24749, 29600, 30986)}, + { AOM_CDF4(9466, 19037, 22417)}, { AOM_CDF4(3584, 9280, 14400)}, + { AOM_CDF4(1505, 3929, 5433)}, { AOM_CDF4(677, 1500, 2736)}, + { AOM_CDF4(23987, 30702, 32117)}, { AOM_CDF4(13554, 24571, 29263)}, + { AOM_CDF4(6211, 14556, 21155)}, { AOM_CDF4(3135, 10972, 15625)}, + { AOM_CDF4(2435, 7127, 11427)}, { AOM_CDF4(31300, 32532, 32550)}, + { AOM_CDF4(14757, 30365, 31954)}, { AOM_CDF4(4405, 11612, 18553)}, + { AOM_CDF4(580, 4132, 7322)}, { AOM_CDF4(1695, 10169, 14124)}, + { AOM_CDF4(30008, 32282, 32591)}, { AOM_CDF4(19244, 30108, 31748)}, + { AOM_CDF4(11180, 24158, 29555)}, { AOM_CDF4(5650, 14972, 19209)}, + { AOM_CDF4(2114, 5109, 8456)}, { AOM_CDF4(31856, 32716, 32748)}, + { AOM_CDF4(23012, 31664, 32572)}, { AOM_CDF4(13694, 26656, 30636)}, + { AOM_CDF4(8142, 19508, 26093)}, { AOM_CDF4(4253, 10955, 16724)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)} + } + }, + { + { + { AOM_CDF4(601, 983, 1311)}, { AOM_CDF4(18725, 23406, 28087)}, + { AOM_CDF4(5461, 8192, 10923)}, { AOM_CDF4(3781, 15124, 21425)}, + { AOM_CDF4(2587, 7761, 12072)}, { AOM_CDF4(106, 458, 810)}, + { AOM_CDF4(22282, 29710, 31894)}, { AOM_CDF4(8508, 20926, 25984)}, + { AOM_CDF4(3726, 12713, 18083)}, { AOM_CDF4(1620, 7112, 10893)}, + { AOM_CDF4(729, 2236, 3495)}, { AOM_CDF4(30163, 32474, 32684)}, + { AOM_CDF4(18304, 30464, 32000)}, { AOM_CDF4(11443, 26526, 29647)}, + { AOM_CDF4(6007, 15292, 21299)}, { AOM_CDF4(2234, 6703, 8937)}, + { AOM_CDF4(30954, 32177, 32571)}, { AOM_CDF4(17363, 29562, 31076)}, + { AOM_CDF4(9686, 22464, 27410)}, { AOM_CDF4(8192, 16384, 21390)}, + { AOM_CDF4(1755, 8046, 11264)}, { AOM_CDF4(31168, 32734, 32748)}, + { AOM_CDF4(22486, 31441, 32471)}, { AOM_CDF4(12833, 25627, 29738)}, + { AOM_CDF4(6980, 17379, 23122)}, { AOM_CDF4(3111, 8887, 13479)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)} + }, + { + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)} + } + } + }, + { + { + { + { AOM_CDF4(6041, 11854, 15927)}, { AOM_CDF4(20326, 30905, 32251)}, + { AOM_CDF4(14164, 26831, 30725)}, { AOM_CDF4(9760, 20647, 26585)}, + { AOM_CDF4(6416, 14953, 21219)}, { AOM_CDF4(2966, 7151, 10891)}, + { AOM_CDF4(23567, 31374, 32254)}, { AOM_CDF4(14978, 27416, 30946)}, + { AOM_CDF4(9434, 20225, 26254)}, { AOM_CDF4(6658, 14558, 20535)}, + { AOM_CDF4(3916, 8677, 12989)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(18088, 29545, 31587)}, + { AOM_CDF4(13062, 25843, 30073)}, { AOM_CDF4(8940, 16827, 22251)}, + { AOM_CDF4(7654, 13220, 17973)}, { AOM_CDF4(5733, 10316, 14456)}, + { AOM_CDF4(22879, 31388, 32114)}, { AOM_CDF4(15215, 27993, 30955)}, + { AOM_CDF4(9397, 19445, 24978)}, { AOM_CDF4(3442, 9813, 15344)}, + { AOM_CDF4(1368, 3936, 6532)}, { AOM_CDF4(25494, 32033, 32406)}, + { AOM_CDF4(16772, 27963, 30718)}, { AOM_CDF4(9419, 18165, 23260)}, + { AOM_CDF4(2677, 7501, 11797)}, { AOM_CDF4(1516, 4344, 7170)}, + { AOM_CDF4(26556, 31454, 32101)}, { AOM_CDF4(17128, 27035, 30108)}, + { AOM_CDF4(8324, 15344, 20249)}, { AOM_CDF4(1903, 5696, 9469)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)} + }, + { + { AOM_CDF4(8455, 19003, 24368)}, { AOM_CDF4(23563, 32021, 32604)}, + { AOM_CDF4(16237, 29446, 31935)}, { AOM_CDF4(10724, 23999, 29358)}, + { AOM_CDF4(6725, 17528, 24416)}, { AOM_CDF4(3927, 10927, 16825)}, + { AOM_CDF4(26313, 32288, 32634)}, { AOM_CDF4(17430, 30095, 32095)}, + { AOM_CDF4(11116, 24606, 29679)}, { AOM_CDF4(7195, 18384, 25269)}, + { AOM_CDF4(4726, 12852, 19315)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(22822, 31648, 32483)}, + { AOM_CDF4(16724, 29633, 31929)}, { AOM_CDF4(10261, 23033, 28725)}, + { AOM_CDF4(7029, 17840, 24528)}, { AOM_CDF4(4867, 13886, 21502)}, + { AOM_CDF4(25298, 31892, 32491)}, { AOM_CDF4(17809, 29330, 31512)}, + { AOM_CDF4(9668, 21329, 26579)}, { AOM_CDF4(4774, 12956, 18976)}, + { AOM_CDF4(2322, 7030, 11540)}, { AOM_CDF4(25472, 31920, 32543)}, + { AOM_CDF4(17957, 29387, 31632)}, { AOM_CDF4(9196, 20593, 26400)}, + { AOM_CDF4(4680, 12705, 19202)}, { AOM_CDF4(2917, 8456, 13436)}, + { AOM_CDF4(26471, 32059, 32574)}, { AOM_CDF4(18458, 29783, 31909)}, + { AOM_CDF4(8400, 19464, 25956)}, { AOM_CDF4(3812, 10973, 17206)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)} + } + }, + { + { + { AOM_CDF4(6779, 13743, 17678)}, { AOM_CDF4(24806, 31797, 32457)}, + { AOM_CDF4(17616, 29047, 31372)}, { AOM_CDF4(11063, 23175, 28003)}, + { AOM_CDF4(6521, 16110, 22324)}, { AOM_CDF4(2764, 7504, 11654)}, + { AOM_CDF4(25266, 32367, 32637)}, { AOM_CDF4(19054, 30553, 32175)}, + { AOM_CDF4(12139, 25212, 29807)}, { AOM_CDF4(7311, 18162, 24704)}, + { AOM_CDF4(3397, 9164, 14074)}, { AOM_CDF4(25988, 32208, 32522)}, + { AOM_CDF4(16253, 28912, 31526)}, { AOM_CDF4(9151, 21387, 27372)}, + { AOM_CDF4(5688, 14915, 21496)}, { AOM_CDF4(2717, 7627, 12004)}, + { AOM_CDF4(23144, 31855, 32443)}, { AOM_CDF4(16070, 28491, 31325)}, + { AOM_CDF4(8702, 20467, 26517)}, { AOM_CDF4(5243, 13956, 20367)}, + { AOM_CDF4(2621, 7335, 11567)}, { AOM_CDF4(26636, 32340, 32630)}, + { AOM_CDF4(19990, 31050, 32341)}, { AOM_CDF4(13243, 26105, 30315)}, + { AOM_CDF4(8588, 19521, 25918)}, { AOM_CDF4(4717, 11585, 17304)}, + { AOM_CDF4(25844, 32292, 32582)}, { AOM_CDF4(19090, 30635, 32097)}, + { AOM_CDF4(11963, 24546, 28939)}, { AOM_CDF4(6218, 16087, 22354)}, + { AOM_CDF4(2340, 6608, 10426)}, { AOM_CDF4(28046, 32576, 32694)}, + { AOM_CDF4(21178, 31313, 32296)}, { AOM_CDF4(13486, 26184, 29870)}, + { AOM_CDF4(7149, 17871, 23723)}, { AOM_CDF4(2833, 7958, 12259)}, + { AOM_CDF4(27710, 32528, 32686)}, { AOM_CDF4(20674, 31076, 32268)}, + { AOM_CDF4(12413, 24955, 29243)}, { AOM_CDF4(6676, 16927, 23097)}, + { AOM_CDF4(2966, 8333, 12919)}, { AOM_CDF4(8192, 16384, 24576)} + }, + { + { AOM_CDF4(8639, 19339, 24429)}, { AOM_CDF4(24404, 31837, 32525)}, + { AOM_CDF4(16997, 29425, 31784)}, { AOM_CDF4(11253, 24234, 29149)}, + { AOM_CDF4(6751, 17394, 24028)}, { AOM_CDF4(3490, 9830, 15191)}, + { AOM_CDF4(26283, 32471, 32714)}, { AOM_CDF4(19599, 31168, 32442)}, + { AOM_CDF4(13146, 26954, 30893)}, { AOM_CDF4(8214, 20588, 26890)}, + { AOM_CDF4(4699, 13081, 19300)}, { AOM_CDF4(28212, 32458, 32669)}, + { AOM_CDF4(18594, 30316, 32100)}, { AOM_CDF4(11219, 24408, 29234)}, + { AOM_CDF4(6865, 17656, 24149)}, { AOM_CDF4(3678, 10362, 16006)}, + { AOM_CDF4(25825, 32136, 32616)}, { AOM_CDF4(17313, 29853, 32021)}, + { AOM_CDF4(11197, 24471, 29472)}, { AOM_CDF4(6947, 17781, 24405)}, + { AOM_CDF4(3768, 10660, 16261)}, { AOM_CDF4(27352, 32500, 32706)}, + { AOM_CDF4(20850, 31468, 32469)}, { AOM_CDF4(14021, 27707, 31133)}, + { AOM_CDF4(8964, 21748, 27838)}, { AOM_CDF4(5437, 14665, 21187)}, + { AOM_CDF4(26304, 32492, 32698)}, { AOM_CDF4(20409, 31380, 32385)}, + { AOM_CDF4(13682, 27222, 30632)}, { AOM_CDF4(8974, 21236, 26685)}, + { AOM_CDF4(4234, 11665, 16934)}, { AOM_CDF4(26273, 32357, 32711)}, + { AOM_CDF4(20672, 31242, 32441)}, { AOM_CDF4(14172, 27254, 30902)}, + { AOM_CDF4(9870, 21898, 27275)}, { AOM_CDF4(5164, 13506, 19270)}, + { AOM_CDF4(26725, 32459, 32728)}, { AOM_CDF4(20991, 31442, 32527)}, + { AOM_CDF4(13071, 26434, 30811)}, { AOM_CDF4(8184, 20090, 26742)}, + { AOM_CDF4(4803, 13255, 19895)}, { AOM_CDF4(8192, 16384, 24576)} + } + }, + { + { + { AOM_CDF4(7555, 14942, 18501)}, { AOM_CDF4(24410, 31178, 32287)}, + { AOM_CDF4(14394, 26738, 30253)}, { AOM_CDF4(8413, 19554, 25195)}, + { AOM_CDF4(4766, 12924, 18785)}, { AOM_CDF4(2029, 5806, 9207)}, + { AOM_CDF4(26776, 32364, 32663)}, { AOM_CDF4(18732, 29967, 31931)}, + { AOM_CDF4(11005, 23786, 28852)}, { AOM_CDF4(6466, 16909, 23510)}, + { AOM_CDF4(3044, 8638, 13419)}, { AOM_CDF4(29208, 32582, 32704)}, + { AOM_CDF4(20068, 30857, 32208)}, { AOM_CDF4(12003, 25085, 29595)}, + { AOM_CDF4(6947, 17750, 24189)}, { AOM_CDF4(3245, 9103, 14007)}, + { AOM_CDF4(27359, 32465, 32669)}, { AOM_CDF4(19421, 30614, 32174)}, + { AOM_CDF4(11915, 25010, 29579)}, { AOM_CDF4(6950, 17676, 24074)}, + { AOM_CDF4(3007, 8473, 13096)}, { AOM_CDF4(29002, 32676, 32735)}, + { AOM_CDF4(22102, 31849, 32576)}, { AOM_CDF4(14408, 28009, 31405)}, + { AOM_CDF4(9027, 21679, 27931)}, { AOM_CDF4(4694, 12678, 18748)}, + { AOM_CDF4(28216, 32528, 32682)}, { AOM_CDF4(20849, 31264, 32318)}, + { AOM_CDF4(12756, 25815, 29751)}, { AOM_CDF4(7565, 18801, 24923)}, + { AOM_CDF4(3509, 9533, 14477)}, { AOM_CDF4(30133, 32687, 32739)}, + { AOM_CDF4(23063, 31910, 32515)}, { AOM_CDF4(14588, 28051, 31132)}, + { AOM_CDF4(9085, 21649, 27457)}, { AOM_CDF4(4261, 11654, 17264)}, + { AOM_CDF4(29518, 32691, 32748)}, { AOM_CDF4(22451, 31959, 32613)}, + { AOM_CDF4(14864, 28722, 31700)}, { AOM_CDF4(9695, 22964, 28716)}, + { AOM_CDF4(4932, 13358, 19502)}, { AOM_CDF4(8192, 16384, 24576)} + }, + { + { AOM_CDF4(6465, 16958, 21688)}, { AOM_CDF4(25199, 31514, 32360)}, + { AOM_CDF4(14774, 27149, 30607)}, { AOM_CDF4(9257, 21438, 26972)}, + { AOM_CDF4(5723, 15183, 21882)}, { AOM_CDF4(3150, 8879, 13731)}, + { AOM_CDF4(26989, 32262, 32682)}, { AOM_CDF4(17396, 29937, 32085)}, + { AOM_CDF4(11387, 24901, 29784)}, { AOM_CDF4(7289, 18821, 25548)}, + { AOM_CDF4(3734, 10577, 16086)}, { AOM_CDF4(29728, 32501, 32695)}, + { AOM_CDF4(17431, 29701, 31903)}, { AOM_CDF4(9921, 22826, 28300)}, + { AOM_CDF4(5896, 15434, 22068)}, { AOM_CDF4(3430, 9646, 14757)}, + { AOM_CDF4(28614, 32511, 32705)}, { AOM_CDF4(19364, 30638, 32263)}, + { AOM_CDF4(13129, 26254, 30402)}, { AOM_CDF4(8754, 20484, 26440)}, + { AOM_CDF4(4378, 11607, 17110)}, { AOM_CDF4(30292, 32671, 32744)}, + { AOM_CDF4(21780, 31603, 32501)}, { AOM_CDF4(14314, 27829, 31291)}, + { AOM_CDF4(9611, 22327, 28263)}, { AOM_CDF4(4890, 13087, 19065)}, + { AOM_CDF4(25862, 32567, 32733)}, { AOM_CDF4(20794, 32050, 32567)}, + { AOM_CDF4(17243, 30625, 32254)}, { AOM_CDF4(13283, 27628, 31474)}, + { AOM_CDF4(9669, 22532, 28918)}, { AOM_CDF4(27435, 32697, 32748)}, + { AOM_CDF4(24922, 32390, 32714)}, { AOM_CDF4(21449, 31504, 32536)}, + { AOM_CDF4(16392, 29729, 31832)}, { AOM_CDF4(11692, 24884, 29076)}, + { AOM_CDF4(24193, 32290, 32735)}, { AOM_CDF4(18909, 31104, 32563)}, + { AOM_CDF4(12236, 26841, 31403)}, { AOM_CDF4(8171, 21840, 29082)}, + { AOM_CDF4(7224, 17280, 25275)}, { AOM_CDF4(8192, 16384, 24576)} + } + }, + { + { + { AOM_CDF4(3078, 6839, 9890)}, { AOM_CDF4(13837, 20450, 24479)}, + { AOM_CDF4(5914, 14222, 19328)}, { AOM_CDF4(3866, 10267, 14762)}, + { AOM_CDF4(2612, 7208, 11042)}, { AOM_CDF4(1067, 2991, 4776)}, + { AOM_CDF4(25817, 31646, 32529)}, { AOM_CDF4(13708, 26338, 30385)}, + { AOM_CDF4(7328, 18585, 24870)}, { AOM_CDF4(4691, 13080, 19276)}, + { AOM_CDF4(1825, 5253, 8352)}, { AOM_CDF4(29386, 32315, 32624)}, + { AOM_CDF4(17160, 29001, 31360)}, { AOM_CDF4(9602, 21862, 27396)}, + { AOM_CDF4(5915, 15772, 22148)}, { AOM_CDF4(2786, 7779, 12047)}, + { AOM_CDF4(29246, 32450, 32663)}, { AOM_CDF4(18696, 29929, 31818)}, + { AOM_CDF4(10510, 23369, 28560)}, { AOM_CDF4(6229, 16499, 23125)}, + { AOM_CDF4(2608, 7448, 11705)}, { AOM_CDF4(30753, 32710, 32748)}, + { AOM_CDF4(21638, 31487, 32503)}, { AOM_CDF4(12937, 26854, 30870)}, + { AOM_CDF4(8182, 20596, 26970)}, { AOM_CDF4(3637, 10269, 15497)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)} + }, + { + { AOM_CDF4(5244, 12150, 16906)}, { AOM_CDF4(20486, 26858, 29701)}, + { AOM_CDF4(7756, 18317, 23735)}, { AOM_CDF4(3452, 9256, 13146)}, + { AOM_CDF4(2020, 5206, 8229)}, { AOM_CDF4(1801, 4993, 7903)}, + { AOM_CDF4(27051, 31858, 32531)}, { AOM_CDF4(15988, 27531, 30619)}, + { AOM_CDF4(9188, 21484, 26719)}, { AOM_CDF4(6273, 17186, 23800)}, + { AOM_CDF4(3108, 9355, 14764)}, { AOM_CDF4(31076, 32520, 32680)}, + { AOM_CDF4(18119, 30037, 31850)}, { AOM_CDF4(10244, 22969, 27472)}, + { AOM_CDF4(4692, 14077, 19273)}, { AOM_CDF4(3694, 11677, 17556)}, + { AOM_CDF4(30060, 32581, 32720)}, { AOM_CDF4(21011, 30775, 32120)}, + { AOM_CDF4(11931, 24820, 29289)}, { AOM_CDF4(7119, 17662, 24356)}, + { AOM_CDF4(3833, 10706, 16304)}, { AOM_CDF4(31954, 32731, 32748)}, + { AOM_CDF4(23913, 31724, 32489)}, { AOM_CDF4(15520, 28060, 31286)}, + { AOM_CDF4(11517, 23008, 28571)}, { AOM_CDF4(6193, 14508, 20629)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)} + } + }, + { + { + { AOM_CDF4(1035, 2807, 4156)}, { AOM_CDF4(13162, 18138, 20939)}, + { AOM_CDF4(2696, 6633, 8755)}, { AOM_CDF4(1373, 4161, 6853)}, + { AOM_CDF4(1099, 2746, 4716)}, { AOM_CDF4(340, 1021, 1599)}, + { AOM_CDF4(22826, 30419, 32135)}, { AOM_CDF4(10395, 21762, 26942)}, + { AOM_CDF4(4726, 12407, 17361)}, { AOM_CDF4(2447, 7080, 10593)}, + { AOM_CDF4(1227, 3717, 6011)}, { AOM_CDF4(28156, 31424, 31934)}, + { AOM_CDF4(16915, 27754, 30373)}, { AOM_CDF4(9148, 20990, 26431)}, + { AOM_CDF4(5950, 15515, 21148)}, { AOM_CDF4(2492, 7327, 11526)}, + { AOM_CDF4(30602, 32477, 32670)}, { AOM_CDF4(20026, 29955, 31568)}, + { AOM_CDF4(11220, 23628, 28105)}, { AOM_CDF4(6652, 17019, 22973)}, + { AOM_CDF4(3064, 8536, 13043)}, { AOM_CDF4(31769, 32724, 32748)}, + { AOM_CDF4(22230, 30887, 32373)}, { AOM_CDF4(12234, 25079, 29731)}, + { AOM_CDF4(7326, 18816, 25353)}, { AOM_CDF4(3933, 10907, 16616)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)} + }, + { + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)} + } + } + }, + { + { + { + { AOM_CDF4(8896, 16227, 20630)}, { AOM_CDF4(23629, 31782, 32527)}, + { AOM_CDF4(15173, 27755, 31321)}, { AOM_CDF4(10158, 21233, 27382)}, + { AOM_CDF4(6420, 14857, 21558)}, { AOM_CDF4(3269, 8155, 12646)}, + { AOM_CDF4(24835, 32009, 32496)}, { AOM_CDF4(16509, 28421, 31579)}, + { AOM_CDF4(10957, 21514, 27418)}, { AOM_CDF4(7881, 15930, 22096)}, + { AOM_CDF4(5388, 10960, 15918)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(20745, 30773, 32093)}, + { AOM_CDF4(15200, 27221, 30861)}, { AOM_CDF4(13032, 20873, 25667)}, + { AOM_CDF4(12285, 18663, 23494)}, { AOM_CDF4(11563, 17481, 21489)}, + { AOM_CDF4(26260, 31982, 32320)}, { AOM_CDF4(15397, 28083, 31100)}, + { AOM_CDF4(9742, 19217, 24824)}, { AOM_CDF4(3261, 9629, 15362)}, + { AOM_CDF4(1480, 4322, 7499)}, { AOM_CDF4(27599, 32256, 32460)}, + { AOM_CDF4(16857, 27659, 30774)}, { AOM_CDF4(9551, 18290, 23748)}, + { AOM_CDF4(3052, 8933, 14103)}, { AOM_CDF4(2021, 5910, 9787)}, + { AOM_CDF4(29005, 32015, 32392)}, { AOM_CDF4(17677, 27694, 30863)}, + { AOM_CDF4(9204, 17356, 23219)}, { AOM_CDF4(2403, 7516, 12814)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)} + }, + { + { AOM_CDF4(10808, 22056, 26896)}, { AOM_CDF4(25739, 32313, 32676)}, + { AOM_CDF4(17288, 30203, 32221)}, { AOM_CDF4(11359, 24878, 29896)}, + { AOM_CDF4(6949, 17767, 24893)}, { AOM_CDF4(4287, 11796, 18071)}, + { AOM_CDF4(27880, 32521, 32705)}, { AOM_CDF4(19038, 31004, 32414)}, + { AOM_CDF4(12564, 26345, 30768)}, { AOM_CDF4(8269, 19947, 26779)}, + { AOM_CDF4(5674, 14657, 21674)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(25742, 32319, 32671)}, + { AOM_CDF4(19557, 31164, 32454)}, { AOM_CDF4(13381, 26381, 30755)}, + { AOM_CDF4(10101, 21466, 26722)}, { AOM_CDF4(9209, 19650, 26825)}, + { AOM_CDF4(27107, 31917, 32432)}, { AOM_CDF4(18056, 28893, 31203)}, + { AOM_CDF4(10200, 21434, 26764)}, { AOM_CDF4(4660, 12913, 19502)}, + { AOM_CDF4(2368, 6930, 12504)}, { AOM_CDF4(26960, 32158, 32613)}, + { AOM_CDF4(18628, 30005, 32031)}, { AOM_CDF4(10233, 22442, 28232)}, + { AOM_CDF4(5471, 14630, 21516)}, { AOM_CDF4(3235, 10767, 17109)}, + { AOM_CDF4(27696, 32440, 32692)}, { AOM_CDF4(20032, 31167, 32438)}, + { AOM_CDF4(8700, 21341, 28442)}, { AOM_CDF4(5662, 14831, 21795)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)} + } + }, + { + { + { AOM_CDF4(9704, 17294, 21132)}, { AOM_CDF4(26762, 32278, 32633)}, + { AOM_CDF4(18382, 29620, 31819)}, { AOM_CDF4(10891, 23475, 28723)}, + { AOM_CDF4(6358, 16583, 23309)}, { AOM_CDF4(3248, 9118, 14141)}, + { AOM_CDF4(27204, 32573, 32699)}, { AOM_CDF4(19818, 30824, 32329)}, + { AOM_CDF4(11772, 25120, 30041)}, { AOM_CDF4(6995, 18033, 25039)}, + { AOM_CDF4(3752, 10442, 16098)}, { AOM_CDF4(27222, 32256, 32559)}, + { AOM_CDF4(15356, 28399, 31475)}, { AOM_CDF4(8821, 20635, 27057)}, + { AOM_CDF4(5511, 14404, 21239)}, { AOM_CDF4(2935, 8222, 13051)}, + { AOM_CDF4(24875, 32120, 32529)}, { AOM_CDF4(15233, 28265, 31445)}, + { AOM_CDF4(8605, 20570, 26932)}, { AOM_CDF4(5431, 14413, 21196)}, + { AOM_CDF4(2994, 8341, 13223)}, { AOM_CDF4(28201, 32604, 32700)}, + { AOM_CDF4(21041, 31446, 32456)}, { AOM_CDF4(13221, 26213, 30475)}, + { AOM_CDF4(8255, 19385, 26037)}, { AOM_CDF4(4930, 12585, 18830)}, + { AOM_CDF4(28768, 32448, 32627)}, { AOM_CDF4(19705, 30561, 32021)}, + { AOM_CDF4(11572, 23589, 28220)}, { AOM_CDF4(5532, 15034, 21446)}, + { AOM_CDF4(2460, 7150, 11456)}, { AOM_CDF4(29874, 32619, 32699)}, + { AOM_CDF4(21621, 31071, 32201)}, { AOM_CDF4(12511, 24747, 28992)}, + { AOM_CDF4(6281, 16395, 22748)}, { AOM_CDF4(3246, 9278, 14497)}, + { AOM_CDF4(29715, 32625, 32712)}, { AOM_CDF4(20958, 31011, 32283)}, + { AOM_CDF4(11233, 23671, 28806)}, { AOM_CDF4(6012, 16128, 22868)}, + { AOM_CDF4(3427, 9851, 15414)}, { AOM_CDF4(8192, 16384, 24576)} + }, + { + { AOM_CDF4(11016, 22111, 26794)}, { AOM_CDF4(25946, 32357, 32677)}, + { AOM_CDF4(17890, 30452, 32252)}, { AOM_CDF4(11678, 25142, 29816)}, + { AOM_CDF4(6720, 17534, 24584)}, { AOM_CDF4(4230, 11665, 17820)}, + { AOM_CDF4(28400, 32623, 32747)}, { AOM_CDF4(21164, 31668, 32575)}, + { AOM_CDF4(13572, 27388, 31182)}, { AOM_CDF4(8234, 20750, 27358)}, + { AOM_CDF4(5065, 14055, 20897)}, { AOM_CDF4(28981, 32547, 32705)}, + { AOM_CDF4(18681, 30543, 32239)}, { AOM_CDF4(10919, 24075, 29286)}, + { AOM_CDF4(6431, 17199, 24077)}, { AOM_CDF4(3819, 10464, 16618)}, + { AOM_CDF4(26870, 32467, 32693)}, { AOM_CDF4(19041, 30831, 32347)}, + { AOM_CDF4(11794, 25211, 30016)}, { AOM_CDF4(6888, 18019, 24970)}, + { AOM_CDF4(4370, 12363, 18992)}, { AOM_CDF4(29578, 32670, 32744)}, + { AOM_CDF4(23159, 32007, 32613)}, { AOM_CDF4(15315, 28669, 31676)}, + { AOM_CDF4(9298, 22607, 28782)}, { AOM_CDF4(6144, 15913, 22968)}, + { AOM_CDF4(28110, 32499, 32669)}, { AOM_CDF4(21574, 30937, 32015)}, + { AOM_CDF4(12759, 24818, 28727)}, { AOM_CDF4(6545, 16761, 23042)}, + { AOM_CDF4(3649, 10597, 16833)}, { AOM_CDF4(28163, 32552, 32728)}, + { AOM_CDF4(22101, 31469, 32464)}, { AOM_CDF4(13160, 25472, 30143)}, + { AOM_CDF4(7303, 18684, 25468)}, { AOM_CDF4(5241, 13975, 20955)}, + { AOM_CDF4(28400, 32631, 32744)}, { AOM_CDF4(22104, 31793, 32603)}, + { AOM_CDF4(13557, 26571, 30846)}, { AOM_CDF4(7749, 19861, 26675)}, + { AOM_CDF4(4873, 14030, 21234)}, { AOM_CDF4(8192, 16384, 24576)} + } + }, + { + { + { AOM_CDF4(9800, 17635, 21073)}, { AOM_CDF4(26153, 31885, 32527)}, + { AOM_CDF4(15038, 27852, 31006)}, { AOM_CDF4(8718, 20564, 26486)}, + { AOM_CDF4(5128, 14076, 20514)}, { AOM_CDF4(2636, 7566, 11925)}, + { AOM_CDF4(27551, 32504, 32701)}, { AOM_CDF4(18310, 30054, 32100)}, + { AOM_CDF4(10211, 23420, 29082)}, { AOM_CDF4(6222, 16876, 23916)}, + { AOM_CDF4(3462, 9954, 15498)}, { AOM_CDF4(29991, 32633, 32721)}, + { AOM_CDF4(19883, 30751, 32201)}, { AOM_CDF4(11141, 24184, 29285)}, + { AOM_CDF4(6420, 16940, 23774)}, { AOM_CDF4(3392, 9753, 15118)}, + { AOM_CDF4(28465, 32616, 32712)}, { AOM_CDF4(19850, 30702, 32244)}, + { AOM_CDF4(10983, 24024, 29223)}, { AOM_CDF4(6294, 16770, 23582)}, + { AOM_CDF4(3244, 9283, 14509)}, { AOM_CDF4(30023, 32717, 32748)}, + { AOM_CDF4(22940, 32032, 32626)}, { AOM_CDF4(14282, 27928, 31473)}, + { AOM_CDF4(8562, 21327, 27914)}, { AOM_CDF4(4846, 13393, 19919)}, + { AOM_CDF4(29981, 32590, 32695)}, { AOM_CDF4(20465, 30963, 32166)}, + { AOM_CDF4(11479, 23579, 28195)}, { AOM_CDF4(5916, 15648, 22073)}, + { AOM_CDF4(3031, 8605, 13398)}, { AOM_CDF4(31146, 32691, 32739)}, + { AOM_CDF4(23106, 31724, 32444)}, { AOM_CDF4(13783, 26738, 30439)}, + { AOM_CDF4(7852, 19468, 25807)}, { AOM_CDF4(3860, 11124, 16853)}, + { AOM_CDF4(31014, 32724, 32748)}, { AOM_CDF4(23629, 32109, 32628)}, + { AOM_CDF4(14747, 28115, 31403)}, { AOM_CDF4(8545, 21242, 27478)}, + { AOM_CDF4(4574, 12781, 19067)}, { AOM_CDF4(8192, 16384, 24576)} + }, + { + { AOM_CDF4(9185, 19694, 24688)}, { AOM_CDF4(26081, 31985, 32621)}, + { AOM_CDF4(16015, 29000, 31787)}, { AOM_CDF4(10542, 23690, 29206)}, + { AOM_CDF4(6732, 17945, 24677)}, { AOM_CDF4(3916, 11039, 16722)}, + { AOM_CDF4(28224, 32566, 32744)}, { AOM_CDF4(19100, 31138, 32485)}, + { AOM_CDF4(12528, 26620, 30879)}, { AOM_CDF4(7741, 20277, 26885)}, + { AOM_CDF4(4566, 12845, 18990)}, { AOM_CDF4(29933, 32593, 32718)}, + { AOM_CDF4(17670, 30333, 32155)}, { AOM_CDF4(10385, 23600, 28909)}, + { AOM_CDF4(6243, 16236, 22407)}, { AOM_CDF4(3976, 10389, 16017)}, + { AOM_CDF4(28377, 32561, 32738)}, { AOM_CDF4(19366, 31175, 32482)}, + { AOM_CDF4(13327, 27175, 31094)}, { AOM_CDF4(8258, 20769, 27143)}, + { AOM_CDF4(4703, 13198, 19527)}, { AOM_CDF4(31086, 32706, 32748)}, + { AOM_CDF4(22853, 31902, 32583)}, { AOM_CDF4(14759, 28186, 31419)}, + { AOM_CDF4(9284, 22382, 28348)}, { AOM_CDF4(5585, 15192, 21868)}, + { AOM_CDF4(28291, 32652, 32746)}, { AOM_CDF4(19849, 32107, 32571)}, + { AOM_CDF4(14834, 26818, 29214)}, { AOM_CDF4(10306, 22594, 28672)}, + { AOM_CDF4(6615, 17384, 23384)}, { AOM_CDF4(28947, 32604, 32745)}, + { AOM_CDF4(25625, 32289, 32646)}, { AOM_CDF4(18758, 28672, 31403)}, + { AOM_CDF4(10017, 23430, 28523)}, { AOM_CDF4(6862, 15269, 22131)}, + { AOM_CDF4(23933, 32509, 32739)}, { AOM_CDF4(19927, 31495, 32631)}, + { AOM_CDF4(11903, 26023, 30621)}, { AOM_CDF4(7026, 20094, 27252)}, + { AOM_CDF4(5998, 18106, 24437)}, { AOM_CDF4(8192, 16384, 24576)} + } + }, + { + { + { AOM_CDF4(4456, 11274, 15533)}, { AOM_CDF4(21219, 29079, 31616)}, + { AOM_CDF4(11173, 23774, 28567)}, { AOM_CDF4(7282, 18293, 24263)}, + { AOM_CDF4(4890, 13286, 19115)}, { AOM_CDF4(1890, 5508, 8659)}, + { AOM_CDF4(26651, 32136, 32647)}, { AOM_CDF4(14630, 28254, 31455)}, + { AOM_CDF4(8716, 21287, 27395)}, { AOM_CDF4(5615, 15331, 22008)}, + { AOM_CDF4(2675, 7700, 12150)}, { AOM_CDF4(29954, 32526, 32690)}, + { AOM_CDF4(16126, 28982, 31633)}, { AOM_CDF4(9030, 21361, 27352)}, + { AOM_CDF4(5411, 14793, 21271)}, { AOM_CDF4(2943, 8422, 13163)}, + { AOM_CDF4(29539, 32601, 32730)}, { AOM_CDF4(18125, 30385, 32201)}, + { AOM_CDF4(10422, 24090, 29468)}, { AOM_CDF4(6468, 17487, 24438)}, + { AOM_CDF4(2970, 8653, 13531)}, { AOM_CDF4(30912, 32715, 32748)}, + { AOM_CDF4(20666, 31373, 32497)}, { AOM_CDF4(12509, 26640, 30917)}, + { AOM_CDF4(8058, 20629, 27290)}, { AOM_CDF4(4231, 12006, 18052)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)} + }, + { + { AOM_CDF4(10202, 20633, 25484)}, { AOM_CDF4(27336, 31445, 32352)}, + { AOM_CDF4(12420, 24384, 28552)}, { AOM_CDF4(7648, 18115, 23856)}, + { AOM_CDF4(5662, 14341, 19902)}, { AOM_CDF4(3611, 10328, 15390)}, + { AOM_CDF4(30945, 32616, 32736)}, { AOM_CDF4(18682, 30505, 32253)}, + { AOM_CDF4(11513, 25336, 30203)}, { AOM_CDF4(7449, 19452, 26148)}, + { AOM_CDF4(4482, 13051, 18886)}, { AOM_CDF4(32022, 32690, 32747)}, + { AOM_CDF4(18578, 30501, 32146)}, { AOM_CDF4(11249, 23368, 28631)}, + { AOM_CDF4(5645, 16958, 22158)}, { AOM_CDF4(5009, 11444, 16637)}, + { AOM_CDF4(31357, 32710, 32748)}, { AOM_CDF4(21552, 31494, 32504)}, + { AOM_CDF4(13891, 27677, 31340)}, { AOM_CDF4(9051, 22098, 28172)}, + { AOM_CDF4(5190, 13377, 19486)}, { AOM_CDF4(32364, 32740, 32748)}, + { AOM_CDF4(24839, 31907, 32551)}, { AOM_CDF4(17160, 28779, 31696)}, + { AOM_CDF4(12452, 24137, 29602)}, { AOM_CDF4(6165, 15389, 22477)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)} + } + }, + { + { + { AOM_CDF4(2575, 7281, 11077)}, { AOM_CDF4(14002, 20866, 25402)}, + { AOM_CDF4(6343, 15056, 19658)}, { AOM_CDF4(4474, 11858, 17041)}, + { AOM_CDF4(2865, 8299, 12534)}, { AOM_CDF4(1344, 3949, 6391)}, + { AOM_CDF4(24720, 31239, 32459)}, { AOM_CDF4(12585, 25356, 29968)}, + { AOM_CDF4(7181, 18246, 24444)}, { AOM_CDF4(5025, 13667, 19885)}, + { AOM_CDF4(2521, 7304, 11605)}, { AOM_CDF4(29908, 32252, 32584)}, + { AOM_CDF4(17421, 29156, 31575)}, { AOM_CDF4(9889, 22188, 27782)}, + { AOM_CDF4(5878, 15647, 22123)}, { AOM_CDF4(2814, 8665, 13323)}, + { AOM_CDF4(30183, 32568, 32713)}, { AOM_CDF4(18528, 30195, 32049)}, + { AOM_CDF4(10982, 24606, 29657)}, { AOM_CDF4(6957, 18165, 25231)}, + { AOM_CDF4(3508, 10118, 15468)}, { AOM_CDF4(31761, 32736, 32748)}, + { AOM_CDF4(21041, 31328, 32546)}, { AOM_CDF4(12568, 26732, 31166)}, + { AOM_CDF4(8052, 20720, 27733)}, { AOM_CDF4(4336, 12192, 18396)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)} + }, + { + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)} + } + } + }, + { + { + { + { AOM_CDF4(7062, 16472, 22319)}, { AOM_CDF4(24538, 32261, 32674)}, + { AOM_CDF4(13675, 28041, 31779)}, { AOM_CDF4(8590, 20674, 27631)}, + { AOM_CDF4(5685, 14675, 22013)}, { AOM_CDF4(3655, 9898, 15731)}, + { AOM_CDF4(26493, 32418, 32658)}, { AOM_CDF4(16376, 29342, 32090)}, + { AOM_CDF4(10594, 22649, 28970)}, { AOM_CDF4(8176, 17170, 24303)}, + { AOM_CDF4(5605, 12694, 19139)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(23888, 31902, 32542)}, + { AOM_CDF4(18612, 29687, 31987)}, { AOM_CDF4(16245, 24852, 29249)}, + { AOM_CDF4(15765, 22608, 27559)}, { AOM_CDF4(19895, 24699, 27510)}, + { AOM_CDF4(28401, 32212, 32457)}, { AOM_CDF4(15274, 27825, 30980)}, + { AOM_CDF4(9364, 18128, 24332)}, { AOM_CDF4(2283, 8193, 15082)}, + { AOM_CDF4(1228, 3972, 7881)}, { AOM_CDF4(29455, 32469, 32620)}, + { AOM_CDF4(17981, 28245, 31388)}, { AOM_CDF4(10921, 20098, 26240)}, + { AOM_CDF4(3743, 11829, 18657)}, { AOM_CDF4(2374, 9593, 15715)}, + { AOM_CDF4(31068, 32466, 32635)}, { AOM_CDF4(20321, 29572, 31971)}, + { AOM_CDF4(10771, 20255, 27119)}, { AOM_CDF4(2795, 10410, 17361)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)} + }, + { + { AOM_CDF4(9320, 22102, 27840)}, { AOM_CDF4(27057, 32464, 32724)}, + { AOM_CDF4(16331, 30268, 32309)}, { AOM_CDF4(10319, 23935, 29720)}, + { AOM_CDF4(6189, 16448, 24106)}, { AOM_CDF4(3589, 10884, 18808)}, + { AOM_CDF4(29026, 32624, 32748)}, { AOM_CDF4(19226, 31507, 32587)}, + { AOM_CDF4(12692, 26921, 31203)}, { AOM_CDF4(7049, 19532, 27635)}, + { AOM_CDF4(7727, 15669, 23252)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(28056, 32625, 32748)}, + { AOM_CDF4(22383, 32075, 32669)}, { AOM_CDF4(15417, 27098, 31749)}, + { AOM_CDF4(18127, 26493, 27190)}, { AOM_CDF4(5461, 16384, 21845)}, + { AOM_CDF4(27982, 32091, 32584)}, { AOM_CDF4(19045, 29868, 31972)}, + { AOM_CDF4(10397, 22266, 27932)}, { AOM_CDF4(5990, 13697, 21500)}, + { AOM_CDF4(1792, 6912, 15104)}, { AOM_CDF4(28198, 32501, 32718)}, + { AOM_CDF4(21534, 31521, 32569)}, { AOM_CDF4(11109, 25217, 30017)}, + { AOM_CDF4(5671, 15124, 26151)}, { AOM_CDF4(4681, 14043, 18725)}, + { AOM_CDF4(28688, 32580, 32741)}, { AOM_CDF4(22576, 32079, 32661)}, + { AOM_CDF4(10627, 22141, 28340)}, { AOM_CDF4(9362, 14043, 28087)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)} + } + }, + { + { + { AOM_CDF4(7754, 16948, 22142)}, { AOM_CDF4(25670, 32330, 32691)}, + { AOM_CDF4(15663, 29225, 31994)}, { AOM_CDF4(9878, 23288, 29158)}, + { AOM_CDF4(6419, 17088, 24336)}, { AOM_CDF4(3859, 11003, 17039)}, + { AOM_CDF4(27562, 32595, 32725)}, { AOM_CDF4(17575, 30588, 32399)}, + { AOM_CDF4(10819, 24838, 30309)}, { AOM_CDF4(7124, 18686, 25916)}, + { AOM_CDF4(4479, 12688, 19340)}, { AOM_CDF4(28385, 32476, 32673)}, + { AOM_CDF4(15306, 29005, 31938)}, { AOM_CDF4(8937, 21615, 28322)}, + { AOM_CDF4(5982, 15603, 22786)}, { AOM_CDF4(3620, 10267, 16136)}, + { AOM_CDF4(27280, 32464, 32667)}, { AOM_CDF4(15607, 29160, 32004)}, + { AOM_CDF4(9091, 22135, 28740)}, { AOM_CDF4(6232, 16632, 24020)}, + { AOM_CDF4(4047, 11377, 17672)}, { AOM_CDF4(29220, 32630, 32718)}, + { AOM_CDF4(19650, 31220, 32462)}, { AOM_CDF4(13050, 26312, 30827)}, + { AOM_CDF4(9228, 20870, 27468)}, { AOM_CDF4(6146, 15149, 21971)}, + { AOM_CDF4(30169, 32481, 32623)}, { AOM_CDF4(17212, 29311, 31554)}, + { AOM_CDF4(9911, 21311, 26882)}, { AOM_CDF4(4487, 13314, 20372)}, + { AOM_CDF4(2570, 7772, 12889)}, { AOM_CDF4(30924, 32613, 32708)}, + { AOM_CDF4(19490, 30206, 32107)}, { AOM_CDF4(11232, 23998, 29276)}, + { AOM_CDF4(6769, 17955, 25035)}, { AOM_CDF4(4398, 12623, 19214)}, + { AOM_CDF4(30609, 32627, 32722)}, { AOM_CDF4(19370, 30582, 32287)}, + { AOM_CDF4(10457, 23619, 29409)}, { AOM_CDF4(6443, 17637, 24834)}, + { AOM_CDF4(4645, 13236, 20106)}, { AOM_CDF4(8192, 16384, 24576)} + }, + { + { AOM_CDF4(8626, 20271, 26216)}, { AOM_CDF4(26707, 32406, 32711)}, + { AOM_CDF4(16999, 30329, 32286)}, { AOM_CDF4(11445, 25123, 30286)}, + { AOM_CDF4(6411, 18828, 25601)}, { AOM_CDF4(6801, 12458, 20248)}, + { AOM_CDF4(29918, 32682, 32748)}, { AOM_CDF4(20649, 31739, 32618)}, + { AOM_CDF4(12879, 27773, 31581)}, { AOM_CDF4(7896, 21751, 28244)}, + { AOM_CDF4(5260, 14870, 23698)}, { AOM_CDF4(29252, 32593, 32731)}, + { AOM_CDF4(17072, 30460, 32294)}, { AOM_CDF4(10653, 24143, 29365)}, + { AOM_CDF4(6536, 17490, 23983)}, { AOM_CDF4(4929, 13170, 20085)}, + { AOM_CDF4(28137, 32518, 32715)}, { AOM_CDF4(18171, 30784, 32407)}, + { AOM_CDF4(11437, 25436, 30459)}, { AOM_CDF4(7252, 18534, 26176)}, + { AOM_CDF4(4126, 13353, 20978)}, { AOM_CDF4(31162, 32726, 32748)}, + { AOM_CDF4(23017, 32222, 32701)}, { AOM_CDF4(15629, 29233, 32046)}, + { AOM_CDF4(9387, 22621, 29480)}, { AOM_CDF4(6922, 17616, 25010)}, + { AOM_CDF4(28838, 32265, 32614)}, { AOM_CDF4(19701, 30206, 31920)}, + { AOM_CDF4(11214, 22410, 27933)}, { AOM_CDF4(5320, 14177, 23034)}, + { AOM_CDF4(5049, 12881, 17827)}, { AOM_CDF4(27484, 32471, 32734)}, + { AOM_CDF4(21076, 31526, 32561)}, { AOM_CDF4(12707, 26303, 31211)}, + { AOM_CDF4(8169, 21722, 28219)}, { AOM_CDF4(6045, 19406, 27042)}, + { AOM_CDF4(27753, 32572, 32745)}, { AOM_CDF4(20832, 31878, 32653)}, + { AOM_CDF4(13250, 27356, 31674)}, { AOM_CDF4(7718, 21508, 29858)}, + { AOM_CDF4(7209, 18350, 25559)}, { AOM_CDF4(8192, 16384, 24576)} + } + }, + { + { + { AOM_CDF4(7876, 16901, 21741)}, { AOM_CDF4(24001, 31898, 32625)}, + { AOM_CDF4(14529, 27959, 31451)}, { AOM_CDF4(8273, 20818, 27258)}, + { AOM_CDF4(5278, 14673, 21510)}, { AOM_CDF4(2983, 8843, 14039)}, + { AOM_CDF4(28016, 32574, 32732)}, { AOM_CDF4(17471, 30306, 32301)}, + { AOM_CDF4(10224, 24063, 29728)}, { AOM_CDF4(6602, 17954, 25052)}, + { AOM_CDF4(4002, 11585, 17759)}, { AOM_CDF4(30190, 32634, 32739)}, + { AOM_CDF4(17497, 30282, 32270)}, { AOM_CDF4(10229, 23729, 29538)}, + { AOM_CDF4(6344, 17211, 24440)}, { AOM_CDF4(3849, 11189, 17108)}, + { AOM_CDF4(28570, 32583, 32726)}, { AOM_CDF4(17521, 30161, 32238)}, + { AOM_CDF4(10153, 23565, 29378)}, { AOM_CDF4(6455, 17341, 24443)}, + { AOM_CDF4(3907, 11042, 17024)}, { AOM_CDF4(30689, 32715, 32748)}, + { AOM_CDF4(21546, 31840, 32610)}, { AOM_CDF4(13547, 27581, 31459)}, + { AOM_CDF4(8912, 21757, 28309)}, { AOM_CDF4(5548, 15080, 22046)}, + { AOM_CDF4(30783, 32540, 32685)}, { AOM_CDF4(17540, 29528, 31668)}, + { AOM_CDF4(10160, 21468, 26783)}, { AOM_CDF4(4724, 13393, 20054)}, + { AOM_CDF4(2702, 8174, 13102)}, { AOM_CDF4(31648, 32686, 32742)}, + { AOM_CDF4(20954, 31094, 32337)}, { AOM_CDF4(12420, 25698, 30179)}, + { AOM_CDF4(7304, 19320, 26248)}, { AOM_CDF4(4366, 12261, 18864)}, + { AOM_CDF4(31581, 32723, 32748)}, { AOM_CDF4(21373, 31586, 32525)}, + { AOM_CDF4(12744, 26625, 30885)}, { AOM_CDF4(7431, 20322, 26950)}, + { AOM_CDF4(4692, 13323, 20111)}, { AOM_CDF4(8192, 16384, 24576)} + }, + { + { AOM_CDF4(7833, 18369, 24095)}, { AOM_CDF4(26650, 32273, 32702)}, + { AOM_CDF4(16371, 29961, 32191)}, { AOM_CDF4(11055, 24082, 29629)}, + { AOM_CDF4(6892, 18644, 25400)}, { AOM_CDF4(5006, 13057, 19240)}, + { AOM_CDF4(29834, 32666, 32748)}, { AOM_CDF4(19577, 31335, 32570)}, + { AOM_CDF4(12253, 26509, 31122)}, { AOM_CDF4(7991, 20772, 27711)}, + { AOM_CDF4(5677, 15910, 23059)}, { AOM_CDF4(30109, 32532, 32720)}, + { AOM_CDF4(16747, 30166, 32252)}, { AOM_CDF4(10134, 23542, 29184)}, + { AOM_CDF4(5791, 16176, 23556)}, { AOM_CDF4(4362, 10414, 17284)}, + { AOM_CDF4(29492, 32626, 32748)}, { AOM_CDF4(19894, 31402, 32525)}, + { AOM_CDF4(12942, 27071, 30869)}, { AOM_CDF4(8346, 21216, 27405)}, + { AOM_CDF4(6572, 17087, 23859)}, { AOM_CDF4(32035, 32735, 32748)}, + { AOM_CDF4(22957, 31838, 32618)}, { AOM_CDF4(14724, 28572, 31772)}, + { AOM_CDF4(10364, 23999, 29553)}, { AOM_CDF4(7004, 18433, 25655)}, + { AOM_CDF4(27528, 32277, 32681)}, { AOM_CDF4(16959, 31171, 32096)}, + { AOM_CDF4(10486, 23593, 27962)}, { AOM_CDF4(8192, 16384, 23211)}, + { AOM_CDF4(8937, 17873, 20852)}, { AOM_CDF4(27715, 32002, 32615)}, + { AOM_CDF4(15073, 29491, 31676)}, { AOM_CDF4(11264, 24576, 28672)}, + { AOM_CDF4(2341, 18725, 23406)}, { AOM_CDF4(7282, 18204, 25486)}, + { AOM_CDF4(28547, 32213, 32657)}, { AOM_CDF4(20788, 29773, 32239)}, + { AOM_CDF4(6780, 21469, 30508)}, { AOM_CDF4(5958, 14895, 23831)}, + { AOM_CDF4(16384, 21845, 27307)}, { AOM_CDF4(8192, 16384, 24576)} + } + }, + { + { + { AOM_CDF4(5992, 14304, 19765)}, { AOM_CDF4(22612, 31238, 32456)}, + { AOM_CDF4(13456, 27162, 31087)}, { AOM_CDF4(8001, 20062, 26504)}, + { AOM_CDF4(5168, 14105, 20764)}, { AOM_CDF4(2632, 7771, 12385)}, + { AOM_CDF4(27034, 32344, 32709)}, { AOM_CDF4(15850, 29415, 31997)}, + { AOM_CDF4(9494, 22776, 28841)}, { AOM_CDF4(6151, 16830, 23969)}, + { AOM_CDF4(3461, 10039, 15722)}, { AOM_CDF4(30134, 32569, 32731)}, + { AOM_CDF4(15638, 29422, 31945)}, { AOM_CDF4(9150, 21865, 28218)}, + { AOM_CDF4(5647, 15719, 22676)}, { AOM_CDF4(3402, 9772, 15477)}, + { AOM_CDF4(28530, 32586, 32735)}, { AOM_CDF4(17139, 30298, 32292)}, + { AOM_CDF4(10200, 24039, 29685)}, { AOM_CDF4(6419, 17674, 24786)}, + { AOM_CDF4(3544, 10225, 15824)}, { AOM_CDF4(31333, 32726, 32748)}, + { AOM_CDF4(20618, 31487, 32544)}, { AOM_CDF4(12901, 27217, 31232)}, + { AOM_CDF4(8624, 21734, 28171)}, { AOM_CDF4(5104, 14191, 20748)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)} + }, + { + { AOM_CDF4(11206, 21090, 26561)}, { AOM_CDF4(28759, 32279, 32671)}, + { AOM_CDF4(14171, 27952, 31569)}, { AOM_CDF4(9743, 22907, 29141)}, + { AOM_CDF4(6871, 17886, 24868)}, { AOM_CDF4(4960, 13152, 19315)}, + { AOM_CDF4(31077, 32661, 32748)}, { AOM_CDF4(19400, 31195, 32515)}, + { AOM_CDF4(12752, 26858, 31040)}, { AOM_CDF4(8370, 22098, 28591)}, + { AOM_CDF4(5457, 15373, 22298)}, { AOM_CDF4(31697, 32706, 32748)}, + { AOM_CDF4(17860, 30657, 32333)}, { AOM_CDF4(12510, 24812, 29261)}, + { AOM_CDF4(6180, 19124, 24722)}, { AOM_CDF4(5041, 13548, 17959)}, + { AOM_CDF4(31552, 32716, 32748)}, { AOM_CDF4(21908, 31769, 32623)}, + { AOM_CDF4(14470, 28201, 31565)}, { AOM_CDF4(9493, 22982, 28608)}, + { AOM_CDF4(6858, 17240, 24137)}, { AOM_CDF4(32543, 32752, 32756)}, + { AOM_CDF4(24286, 32097, 32666)}, { AOM_CDF4(15958, 29217, 32024)}, + { AOM_CDF4(10207, 24234, 29958)}, { AOM_CDF4(6929, 18305, 25652)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)} + } + }, + { + { + { AOM_CDF4(4137, 10847, 15682)}, { AOM_CDF4(17824, 27001, 30058)}, + { AOM_CDF4(10204, 22796, 28291)}, { AOM_CDF4(6076, 15935, 22125)}, + { AOM_CDF4(3852, 10937, 16816)}, { AOM_CDF4(2252, 6324, 10131)}, + { AOM_CDF4(25840, 32016, 32662)}, { AOM_CDF4(15109, 28268, 31531)}, + { AOM_CDF4(9385, 22231, 28340)}, { AOM_CDF4(6082, 16672, 23479)}, + { AOM_CDF4(3318, 9427, 14681)}, { AOM_CDF4(30594, 32574, 32718)}, + { AOM_CDF4(16836, 29552, 31859)}, { AOM_CDF4(9556, 22542, 28356)}, + { AOM_CDF4(6305, 16725, 23540)}, { AOM_CDF4(3376, 9895, 15184)}, + { AOM_CDF4(29383, 32617, 32745)}, { AOM_CDF4(18891, 30809, 32401)}, + { AOM_CDF4(11688, 25942, 30687)}, { AOM_CDF4(7468, 19469, 26651)}, + { AOM_CDF4(3909, 11358, 17012)}, { AOM_CDF4(31564, 32736, 32748)}, + { AOM_CDF4(20906, 31611, 32600)}, { AOM_CDF4(13191, 27621, 31537)}, + { AOM_CDF4(8768, 22029, 28676)}, { AOM_CDF4(5079, 14109, 20906)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)} + }, + { + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)} + } + } + } +}; + +static const u16 av1_default_coeff_base_eob_multi_cdfs[TOKEN_CDF_Q_CTXS][TX_SIZES] + [PLANE_TYPES][SIG_COEF_CONTEXTS_EOB][CDF_SIZE(NUM_BASE_LEVELS + 1)] = { + { + { + { + { AOM_CDF3(17837, 29055)}, + { AOM_CDF3(29600, 31446)}, + { AOM_CDF3(30844, 31878)}, + { AOM_CDF3(24926, 28948)} + }, + { + { AOM_CDF3(21365, 30026)}, + { AOM_CDF3(30512, 32423)}, + { AOM_CDF3(31658, 32621)}, + { AOM_CDF3(29630, 31881)} + } + }, + { + { + { AOM_CDF3(5717, 26477)}, + { AOM_CDF3(30491, 31703)}, + { AOM_CDF3(31550, 32158)}, + { AOM_CDF3(29648, 31491)} + }, + { + { AOM_CDF3(12608, 27820)}, + { AOM_CDF3(30680, 32225)}, + { AOM_CDF3(30809, 32335)}, + { AOM_CDF3(31299, 32423)} + } + }, + { + { + { AOM_CDF3(1786, 12612)}, + { AOM_CDF3(30663, 31625)}, + { AOM_CDF3(32339, 32468)}, + { AOM_CDF3(31148, 31833)} + }, + { + { AOM_CDF3(18857, 23865)}, + { AOM_CDF3(31428, 32428)}, + { AOM_CDF3(31744, 32373)}, + { AOM_CDF3(31775, 32526)} + } + }, + { + { + { AOM_CDF3(1787, 2532)}, + { AOM_CDF3(30832, 31662)}, + { AOM_CDF3(31824, 32682)}, + { AOM_CDF3(32133, 32569)} + }, + { + { AOM_CDF3(13751, 22235)}, + { AOM_CDF3(32089, 32409)}, + { AOM_CDF3(27084, 27920)}, + { AOM_CDF3(29291, 32594)} + } + }, + { + { + { AOM_CDF3(1725, 3449)}, + { AOM_CDF3(31102, 31935)}, + { AOM_CDF3(32457, 32613)}, + { AOM_CDF3(32412, 32649)} + }, + { + { AOM_CDF3(10923, 21845)}, + { AOM_CDF3(10923, 21845)}, + { AOM_CDF3(10923, 21845)}, + { AOM_CDF3(10923, 21845)} + } + } + }, + { + { + { + { AOM_CDF3(17560, 29888)}, + { AOM_CDF3(29671, 31549)}, + { AOM_CDF3(31007, 32056)}, + { AOM_CDF3(27286, 30006)} + }, + { + { AOM_CDF3(26594, 31212)}, + { AOM_CDF3(31208, 32582)}, + { AOM_CDF3(31835, 32637)}, + { AOM_CDF3(30595, 32206)} + } + }, + { + { + { AOM_CDF3(15239, 29932)}, + { AOM_CDF3(31315, 32095)}, + { AOM_CDF3(32130, 32434)}, + { AOM_CDF3(30864, 31996)} + }, + { + { AOM_CDF3(26279, 30968)}, + { AOM_CDF3(31142, 32495)}, + { AOM_CDF3(31713, 32540)}, + { AOM_CDF3(31929, 32594)} + } + }, + { + { + { AOM_CDF3(2644, 25198)}, + { AOM_CDF3(32038, 32451)}, + { AOM_CDF3(32639, 32695)}, + { AOM_CDF3(32166, 32518)} + }, + { + { AOM_CDF3(17187, 27668)}, + { AOM_CDF3(31714, 32550)}, + { AOM_CDF3(32283, 32678)}, + { AOM_CDF3(31930, 32563)} + } + }, + { + { + { AOM_CDF3(1044, 2257)}, + { AOM_CDF3(30755, 31923)}, + { AOM_CDF3(32208, 32693)}, + { AOM_CDF3(32244, 32615)} + }, + { + { AOM_CDF3(21317, 26207)}, + { AOM_CDF3(29133, 30868)}, + { AOM_CDF3(29311, 31231)}, + { AOM_CDF3(29657, 31087)} + } + }, + { + { + { AOM_CDF3(478, 1834)}, + { AOM_CDF3(31005, 31987)}, + { AOM_CDF3(32317, 32724)}, + { AOM_CDF3(30865, 32648)} + }, + { + { AOM_CDF3(10923, 21845)}, + { AOM_CDF3(10923, 21845)}, + { AOM_CDF3(10923, 21845)}, + { AOM_CDF3(10923, 21845)} + } + } + }, + { + { + { + { AOM_CDF3(20092, 30774)}, + { AOM_CDF3(30695, 32020)}, + { AOM_CDF3(31131, 32103)}, + { AOM_CDF3(28666, 30870)} + }, + { + { AOM_CDF3(27258, 31095)}, + { AOM_CDF3(31804, 32623)}, + { AOM_CDF3(31763, 32528)}, + { AOM_CDF3(31438, 32506)} + } + }, + { + { + { AOM_CDF3(18049, 30489)}, + { AOM_CDF3(31706, 32286)}, + { AOM_CDF3(32163, 32473)}, + { AOM_CDF3(31550, 32184)} + }, + { + { AOM_CDF3(27116, 30842)}, + { AOM_CDF3(31971, 32598)}, + { AOM_CDF3(32088, 32576)}, + { AOM_CDF3(32067, 32664)} + } + }, + { + { + { AOM_CDF3(12854, 29093)}, + { AOM_CDF3(32272, 32558)}, + { AOM_CDF3(32667, 32729)}, + { AOM_CDF3(32306, 32585)} + }, + { + { AOM_CDF3(25476, 30366)}, + { AOM_CDF3(32169, 32687)}, + { AOM_CDF3(32479, 32689)}, + { AOM_CDF3(31673, 32634)} + } + }, + { + { + { AOM_CDF3(2809, 19301)}, + { AOM_CDF3(32205, 32622)}, + { AOM_CDF3(32338, 32730)}, + { AOM_CDF3(31786, 32616)} + }, + { + { AOM_CDF3(22737, 29105)}, + { AOM_CDF3(30810, 32362)}, + { AOM_CDF3(30014, 32627)}, + { AOM_CDF3(30528, 32574)} + } + }, + { + { + { AOM_CDF3(935, 3382)}, + { AOM_CDF3(30789, 31909)}, + { AOM_CDF3(32466, 32756)}, + { AOM_CDF3(30860, 32513)} + }, + { + { AOM_CDF3(10923, 21845)}, + { AOM_CDF3(10923, 21845)}, + { AOM_CDF3(10923, 21845)}, + { AOM_CDF3(10923, 21845)} + } + } + }, + { + { + { + { AOM_CDF3(22497, 31198)}, + { AOM_CDF3(31715, 32495)}, + { AOM_CDF3(31606, 32337)}, + { AOM_CDF3(30388, 31990)} + }, + { + { AOM_CDF3(27877, 31584)}, + { AOM_CDF3(32170, 32728)}, + { AOM_CDF3(32155, 32688)}, + { AOM_CDF3(32219, 32702)} + } + }, + { + { + { AOM_CDF3(21457, 31043)}, + { AOM_CDF3(31951, 32483)}, + { AOM_CDF3(32153, 32562)}, + { AOM_CDF3(31473, 32215)} + }, + { + { AOM_CDF3(27558, 31151)}, + { AOM_CDF3(32020, 32640)}, + { AOM_CDF3(32097, 32575)}, + { AOM_CDF3(32242, 32719)} + } + }, + { + { + { AOM_CDF3(19980, 30591)}, + { AOM_CDF3(32219, 32597)}, + { AOM_CDF3(32581, 32706)}, + { AOM_CDF3(31803, 32287)} + }, + { + { AOM_CDF3(26473, 30507)}, + { AOM_CDF3(32431, 32723)}, + { AOM_CDF3(32196, 32611)}, + { AOM_CDF3(31588, 32528)} + } + }, + { + { + { AOM_CDF3(24647, 30463)}, + { AOM_CDF3(32412, 32695)}, + { AOM_CDF3(32468, 32720)}, + { AOM_CDF3(31269, 32523)} + }, + { + { AOM_CDF3(28482, 31505)}, + { AOM_CDF3(32152, 32701)}, + { AOM_CDF3(31732, 32598)}, + { AOM_CDF3(31767, 32712)} + } + }, + { + { + { AOM_CDF3(12358, 24977)}, + { AOM_CDF3(31331, 32385)}, + { AOM_CDF3(32634, 32756)}, + { AOM_CDF3(30411, 32548)} + }, + { + { AOM_CDF3(10923, 21845)}, + { AOM_CDF3(10923, 21845)}, + { AOM_CDF3(10923, 21845)}, + { AOM_CDF3(10923, 21845)} + } + } + } +}; + +static const u16 default_joint_cdf[] = { ICDF(4096), ICDF(11264), ICDF(19328)}; +static const u16 default_clsss_cdf[][10] = { + // Vertical component + { + ICDF(28672), ICDF(30976), ICDF(31858), ICDF(32320), ICDF(32551), + ICDF(32656), ICDF(32740), ICDF(32757), ICDF(32762), ICDF(32767) + }, + // Horizontal component + { + ICDF(28672), ICDF(30976), ICDF(31858), ICDF(32320), ICDF(32551), + ICDF(32656), ICDF(32740), ICDF(32757), ICDF(32762), ICDF(32767) + } +}; + +static const u16 default_clsss0_fp_cdf[][2][3] = { + // Vertical component + { + { ICDF(16384), ICDF(24576), ICDF(26624)}, + { ICDF(12288), ICDF(21248), ICDF(24128)} + }, + // Horizontal component + { + { ICDF(16384), ICDF(24576), ICDF(26624)}, + { ICDF(12288), ICDF(21248), ICDF(24128)} + } +}; + +static const u16 default_fp_cdf[][3] = { + // Vertical component + { + ICDF(8192), ICDF(17408), ICDF(21248) + }, + // Horizontal component + { + ICDF(8192), ICDF(17408), ICDF(21248) + } +}; + +static const u16 default_sign_cdf[] = { ICDF(128 * 128), ICDF(128 * 128)}; +static const u16 default_class0_hp_cdf[] = { ICDF(160 * 128), ICDF(160 * 128)}; +static const u16 default_hp_cdf[] = { ICDF(128 * 128), ICDF(128 * 128)}; +static const u16 default_class0_cdf[] = { ICDF(216 * 128), ICDF(216 * 128)}; +static const u16 default_bits_cdf[][10] = { + { + ICDF(128 * 136), ICDF(128 * 140), ICDF(128 * 148), ICDF(128 * 160), + ICDF(128 * 176), ICDF(128 * 192), ICDF(128 * 224), ICDF(128 * 234), + ICDF(128 * 234), ICDF(128 * 240) + }, + { + ICDF(128 * 136), ICDF(128 * 140), ICDF(128 * 148), ICDF(128 * 160), + ICDF(128 * 176), ICDF(128 * 192), ICDF(128 * 224), ICDF(128 * 234), + ICDF(128 * 234), ICDF(128 * 240) + } +}; + +static int rockchip_av1_get_q_ctx(int q) +{ + if (q <= 20) + return 0; + if (q <= 60) + return 1; + if (q <= 120) + return 2; + return 3; +} + +void rockchip_av1_default_coeff_probs(u32 base_qindex, void *ptr) +{ + struct av1cdfs *cdfs = (struct av1cdfs *)ptr; + const int index = rockchip_av1_get_q_ctx(base_qindex); + + memcpy(cdfs->txb_skip_cdf, av1_default_txb_skip_cdfs[index], + sizeof(av1_default_txb_skip_cdfs[0])); + memcpy(cdfs->eob_extra_cdf, av1_default_eob_extra_cdfs[index], + sizeof(av1_default_eob_extra_cdfs[0])); + memcpy(cdfs->dc_sign_cdf, av1_default_dc_sign_cdfs[index], + sizeof(av1_default_dc_sign_cdfs[0])); + memcpy(cdfs->coeff_br_cdf, av1_default_coeff_lps_multi_cdfs[index], + sizeof(av1_default_coeff_lps_multi_cdfs[0])); + memcpy(cdfs->coeff_base_cdf, av1_default_coeff_base_multi_cdfs[index], + sizeof(av1_default_coeff_base_multi_cdfs[0])); + memcpy(cdfs->coeff_base_eob_cdf, + av1_default_coeff_base_eob_multi_cdfs[index], + sizeof(av1_default_coeff_base_eob_multi_cdfs[0])); + memcpy(cdfs->eob_flag_cdf16, av1_default_eob_multi16_cdfs[index], + sizeof(av1_default_eob_multi16_cdfs[0])); + memcpy(cdfs->eob_flag_cdf32, av1_default_eob_multi32_cdfs[index], + sizeof(av1_default_eob_multi32_cdfs[0])); + memcpy(cdfs->eob_flag_cdf64, av1_default_eob_multi64_cdfs[index], + sizeof(av1_default_eob_multi64_cdfs[0])); + memcpy(cdfs->eob_flag_cdf128, av1_default_eob_multi128_cdfs[index], + sizeof(av1_default_eob_multi128_cdfs[0])); + memcpy(cdfs->eob_flag_cdf256, av1_default_eob_multi256_cdfs[index], + sizeof(av1_default_eob_multi256_cdfs[0])); + memcpy(cdfs->eob_flag_cdf512, av1_default_eob_multi512_cdfs[index], + sizeof(av1_default_eob_multi512_cdfs[0])); + memcpy(cdfs->eob_flag_cdf1024, av1_default_eob_multi1024_cdfs[index], + sizeof(av1_default_eob_multi1024_cdfs[0])); +} + +void rockchip_av1_set_default_cdfs(struct av1cdfs *cdfs, + struct mvcdfs *cdfs_ndvc) +{ + memcpy(cdfs->partition_cdf, default_partition_cdf, + sizeof(cdfs->partition_cdf)); + + memcpy(cdfs->tx_type_intra0_cdf, default_intra_ext_tx0_cdf, + sizeof(cdfs->tx_type_intra0_cdf)); + memcpy(cdfs->tx_type_intra1_cdf, default_intra_ext_tx1_cdf, + sizeof(cdfs->tx_type_intra1_cdf)); + memcpy(cdfs->tx_type_inter_cdf, default_inter_ext_tx_cdf, + sizeof(cdfs->tx_type_inter_cdf)); + + memcpy(cdfs->vartx_part_cdf, default_txfm_partition_cdf, + sizeof(cdfs->vartx_part_cdf)); + memcpy(cdfs->mbskip_cdf, default_skip_cdfs, sizeof(cdfs->mbskip_cdf)); + memcpy(cdfs->delta_q_cdf, default_delta_q_cdf, + sizeof(cdfs->delta_q_cdf)); + memcpy(cdfs->delta_lf_multi_cdf, default_delta_lf_multi_cdf, + sizeof(cdfs->delta_lf_multi_cdf)); + memcpy(cdfs->delta_lf_cdf, default_delta_lf_cdf, + sizeof(cdfs->delta_lf_cdf)); + + memcpy(cdfs->segment_pred_cdf, default_segment_pred_cdf, + sizeof(cdfs->segment_pred_cdf)); + + memcpy(cdfs->spatial_pred_seg_tree_cdf, + default_spatial_pred_seg_tree_cdf, + sizeof(cdfs->spatial_pred_seg_tree_cdf)); + + memcpy(cdfs->skip_mode_cdf, default_skip_mode_cdfs, + sizeof(cdfs->skip_mode_cdf)); + + memcpy(cdfs->tx_size_cdf, default_tx_size_cdf, + sizeof(cdfs->tx_size_cdf)); + + memcpy(cdfs->kf_ymode_cdf, default_kf_y_mode_cdf, + sizeof(cdfs->kf_ymode_cdf)); + memcpy(cdfs->uv_mode_cdf, default_uv_mode_cdf, + sizeof(cdfs->uv_mode_cdf)); + memcpy(cdfs->if_ymode_cdf, default_if_y_mode_cdf, + sizeof(cdfs->if_ymode_cdf)); + + memcpy(cdfs->intra_inter_cdf, default_intra_inter_cdf, + sizeof(cdfs->intra_inter_cdf)); + + memcpy(cdfs->comp_ref_cdf, default_comp_ref_cdf, + sizeof(cdfs->comp_ref_cdf)); + memcpy(cdfs->comp_bwdref_cdf, default_comp_bwdref_cdf, + sizeof(cdfs->comp_bwdref_cdf)); + + memcpy(cdfs->comp_inter_cdf, default_comp_inter_cdf, + sizeof(cdfs->comp_inter_cdf)); + + memcpy(cdfs->single_ref_cdf, default_single_ref_cdf, + sizeof(cdfs->single_ref_cdf)); + memcpy(cdfs->comp_ref_type_cdf, default_comp_ref_type_cdf, + sizeof(cdfs->comp_ref_type_cdf)); + memcpy(cdfs->uni_comp_ref_cdf, default_uni_comp_ref_cdf, + sizeof(cdfs->uni_comp_ref_cdf)); + + memcpy(cdfs->newmv_cdf, default_newmv_cdf, sizeof(cdfs->newmv_cdf)); + memcpy(cdfs->zeromv_cdf, default_zeromv_cdf, sizeof(cdfs->zeromv_cdf)); + memcpy(cdfs->refmv_cdf, default_refmv_cdf, sizeof(cdfs->refmv_cdf)); + memcpy(cdfs->drl_cdf, default_drl_cdf, sizeof(cdfs->drl_cdf)); + + memcpy(cdfs->interp_filter_cdf, default_switchable_interp_cdf, + sizeof(cdfs->interp_filter_cdf)); + + // Regular MV cdfs + memcpy(cdfs->mv_cdf.joint_cdf, default_joint_cdf, + sizeof(cdfs->mv_cdf.joint_cdf)); + memcpy(cdfs->mv_cdf.sign_cdf, default_sign_cdf, + sizeof(cdfs->mv_cdf.sign_cdf)); + memcpy(cdfs->mv_cdf.clsss_cdf, default_clsss_cdf, + sizeof(cdfs->mv_cdf.clsss_cdf)); + memcpy(cdfs->mv_cdf.clsss0_fp_cdf, default_clsss0_fp_cdf, + sizeof(cdfs->mv_cdf.clsss0_fp_cdf)); + memcpy(cdfs->mv_cdf.fp_cdf, default_fp_cdf, + sizeof(cdfs->mv_cdf.fp_cdf)); + memcpy(cdfs->mv_cdf.class0_hp_cdf, default_class0_hp_cdf, + sizeof(cdfs->mv_cdf.class0_hp_cdf)); + memcpy(cdfs->mv_cdf.hp_cdf, default_hp_cdf, + sizeof(cdfs->mv_cdf.hp_cdf)); + memcpy(cdfs->mv_cdf.class0_cdf, default_class0_cdf, + sizeof(cdfs->mv_cdf.class0_cdf)); + memcpy(cdfs->mv_cdf.bits_cdf, default_bits_cdf, + sizeof(cdfs->mv_cdf.bits_cdf)); + + // Intrabc cdfs + memcpy(cdfs_ndvc->joint_cdf, default_joint_cdf, + sizeof(cdfs_ndvc->joint_cdf)); + memcpy(cdfs_ndvc->sign_cdf, default_sign_cdf, + sizeof(cdfs_ndvc->sign_cdf)); + memcpy(cdfs_ndvc->clsss_cdf, default_clsss_cdf, + sizeof(cdfs_ndvc->clsss_cdf)); + memcpy(cdfs_ndvc->clsss0_fp_cdf, default_clsss0_fp_cdf, + sizeof(cdfs_ndvc->clsss0_fp_cdf)); + memcpy(cdfs_ndvc->fp_cdf, default_fp_cdf, sizeof(cdfs_ndvc->fp_cdf)); + memcpy(cdfs_ndvc->class0_hp_cdf, default_class0_hp_cdf, + sizeof(cdfs_ndvc->class0_hp_cdf)); + memcpy(cdfs_ndvc->hp_cdf, default_hp_cdf, sizeof(cdfs_ndvc->hp_cdf)); + memcpy(cdfs_ndvc->class0_cdf, default_class0_cdf, + sizeof(cdfs_ndvc->class0_cdf)); + memcpy(cdfs_ndvc->bits_cdf, default_bits_cdf, + sizeof(cdfs_ndvc->bits_cdf)); + + memcpy(cdfs->obmc_cdf, default_obmc_cdf, sizeof(cdfs->obmc_cdf)); + memcpy(cdfs->motion_mode_cdf, default_motion_mode_cdf, + sizeof(cdfs->motion_mode_cdf)); + + memcpy(cdfs->inter_compound_mode_cdf, default_inter_compound_mode_cdf, + sizeof(cdfs->inter_compound_mode_cdf)); + memcpy(cdfs->compound_type_cdf, default_compound_type_cdf, + sizeof(cdfs->compound_type_cdf)); + memcpy(cdfs->interintra_cdf, default_interintra_cdf, + sizeof(cdfs->interintra_cdf)); + memcpy(cdfs->interintra_mode_cdf, default_interintra_mode_cdf, + sizeof(cdfs->interintra_mode_cdf)); + memcpy(cdfs->wedge_interintra_cdf, default_wedge_interintra_cdf, + sizeof(cdfs->wedge_interintra_cdf)); + memcpy(cdfs->wedge_idx_cdf, default_wedge_idx_cdf, + sizeof(cdfs->wedge_idx_cdf)); + + memcpy(cdfs->palette_y_mode_cdf, default_palette_y_mode_cdf, + sizeof(cdfs->palette_y_mode_cdf)); + memcpy(cdfs->palette_uv_mode_cdf, default_palette_uv_mode_cdf, + sizeof(cdfs->palette_uv_mode_cdf)); + memcpy(cdfs->palette_y_size_cdf, default_palette_y_size_cdf, + sizeof(cdfs->palette_y_size_cdf)); + memcpy(cdfs->palette_uv_size_cdf, default_palette_uv_size_cdf, + sizeof(cdfs->palette_uv_size_cdf)); + memcpy(cdfs->palette_y_color_index_cdf, + default_palette_y_color_index_cdf, + sizeof(cdfs->palette_y_color_index_cdf)); + memcpy(cdfs->palette_uv_color_index_cdf, + default_palette_uv_color_index_cdf, + sizeof(cdfs->palette_uv_color_index_cdf)); + + memcpy(cdfs->cfl_sign_cdf, default_cfl_sign_cdf, + sizeof(cdfs->cfl_sign_cdf)); + memcpy(cdfs->cfl_alpha_cdf, default_cfl_alpha_cdf, + sizeof(cdfs->cfl_alpha_cdf)); + + memcpy(cdfs->intrabc_cdf, default_intrabc_cdf, + sizeof(cdfs->intrabc_cdf)); + memcpy(cdfs->angle_delta_cdf, default_angle_delta_cdf, + sizeof(cdfs->angle_delta_cdf)); + memcpy(cdfs->filter_intra_mode_cdf, default_filter_intra_mode_cdf, + sizeof(cdfs->filter_intra_mode_cdf)); + memcpy(cdfs->filter_intra_cdf, default_filter_intra_cdfs, + sizeof(cdfs->filter_intra_cdf)); + memcpy(cdfs->comp_group_idx_cdf, default_comp_group_idx_cdfs, + sizeof(cdfs->comp_group_idx_cdf)); + memcpy(cdfs->compound_idx_cdf, default_compound_idx_cdfs, + sizeof(cdfs->compound_idx_cdf)); +} + +void rockchip_av1_get_cdfs(struct hantro_ctx *ctx, u32 ref_idx) +{ + struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec; + + av1_dec->cdfs = &av1_dec->cdfs_last[ref_idx]; + av1_dec->cdfs_ndvc = &av1_dec->cdfs_last_ndvc[ref_idx]; +} + +void rockchip_av1_store_cdfs(struct hantro_ctx *ctx, + u32 refresh_frame_flags) +{ + struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec; + int i; + + for (i = 0; i < NUM_REF_FRAMES; i++) { + if (refresh_frame_flags & (1 << i)) { + if (&av1_dec->cdfs_last[i] != av1_dec->cdfs) { + av1_dec->cdfs_last[i] = *av1_dec->cdfs; + av1_dec->cdfs_last_ndvc[i] = + *av1_dec->cdfs_ndvc; + } + } + } +} diff --git a/drivers/media/platform/verisilicon/rockchip_av1_entropymode.h b/drivers/media/platform/verisilicon/rockchip_av1_entropymode.h new file mode 100644 index 0000000000000000000000000000000000000000..bbf8424c7d2cd1864532578769e238f346174aa1 --- /dev/null +++ b/drivers/media/platform/verisilicon/rockchip_av1_entropymode.h @@ -0,0 +1,272 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef _ROCKCHIP_AV1_ENTROPYMODE_H_ +#define _ROCKCHIP_AV1_ENTROPYMODE_H_ + +#include + +struct hantro_ctx; + +#define AV1_INTER_MODE_CONTEXTS 15 +#define AV1_INTRA_MODES 13 +#define AV1_REF_CONTEXTS 3 +#define AV1_SWITCHABLE_FILTERS 3 /* number of switchable filters */ +#define AV1_TX_SIZE_CONTEXTS 3 +#define BLOCK_SIZE_GROUPS 4 +#define BR_CDF_SIZE 4 +#define BWD_REFS 3 +#define CFL_ALLOWED_TYPES 2 +#define CFL_ALPHA_CONTEXTS 6 +#define CFL_ALPHABET_SIZE 16 +#define CFL_JOINT_SIGNS 8 +#define CDF_SIZE(x) ((x) - 1) +#define COMP_GROUP_IDX_CONTEXTS 7 +#define COMP_INDEX_CONTEXTS 6 +#define COMP_INTER_CONTEXTS 5 +#define COMP_REF_TYPE_CONTEXTS 5 +#define COMPOUND_TYPES 3 +#define DC_SIGN_CONTEXTS 3 +#define DELTA_LF_PROBS 3 +#define DELTA_Q_PROBS 3 +#define DIRECTIONAL_MODES 8 +#define DRL_MODE_CONTEXTS 3 +#define EOB_COEF_CONTEXTS 9 +#define EXT_TX_SIZES 3 +#define EXT_TX_TYPES 16 +#define EXTTX_SIZES 4 +#define FRAME_LF_COUNT 4 +#define FWD_REFS 4 +#define GLOBALMV_MODE_CONTEXTS 2 +#define ICDF(x) (32768U - (x)) +#define INTER_COMPOUND_MODES 8 +#define INTERINTRA_MODES 4 +#define INTRA_INTER_CONTEXTS 4 +#define KF_MODE_CONTEXTS 5 +#define LEVEL_CONTEXTS 21 +#define MAX_ANGLE_DELTA 3 +#define MAX_MB_SEGMENTS 8 +#define MAX_SEGMENTS 8 +#define MAX_TX_CATS 4 +#define MAX_TX_DEPTH 2 +#define MBSKIP_CONTEXTS 3 +#define MOTION_MODES 3 +#define MOTION_MODE_CONTEXTS 10 +#define NEWMV_MODE_CONTEXTS 6 +#define NUM_BASE_LEVELS 2 +#define NUM_REF_FRAMES 8 +#define PALETTE_BLOCK_SIZES 7 +#define PALETTE_IDX_CONTEXTS 18 +#define PALETTE_SIZES 7 +#define PALETTE_UV_MODE_CONTEXTS 2 +#define PALETTE_Y_MODE_CONTEXTS 3 +#define PARTITION_PLOFFSET 4 +#define NUM_PARTITION_CONTEXTS (4 * PARTITION_PLOFFSET) +#define PLANE_TYPES 2 +#define PREDICTION_PROBS 3 +#define REF_CONTEXTS 5 +#define REFMV_MODE_CONTEXTS 9 +#define SEG_TEMPORAL_PRED_CTXS 3 +#define SIG_COEF_CONTEXTS 42 +#define SIG_COEF_CONTEXTS_EOB 4 +#define SINGLE_REFS 7 +#define SKIP_CONTEXTS 3 +#define SKIP_MODE_CONTEXTS 3 +#define SPATIAL_PREDICTION_PROBS 3 +#define SWITCHABLE_FILTER_CONTEXTS ((AV1_SWITCHABLE_FILTERS + 1) * 4) +#define TOKEN_CDF_Q_CTXS 4 +#define TX_SIZES 5 +#define TX_SIZE_CONTEXTS 2 +#define TX_TYPES 4 +#define TXB_SKIP_CONTEXTS 13 +#define TXFM_PARTITION_CONTEXTS 22 +#define UNI_COMP_REF_CONTEXTS 3 +#define UNIDIR_COMP_REFS 4 +#define UV_INTRA_MODES 14 +#define VARTX_PART_CONTEXTS 22 +#define ZEROMV_MODE_CONTEXTS 2 + +enum blocksizetype { + BLOCK_SIZE_AB4X4, + BLOCK_SIZE_SB4X8, + BLOCK_SIZE_SB8X4, + BLOCK_SIZE_SB8X8, + BLOCK_SIZE_SB8X16, + BLOCK_SIZE_SB16X8, + BLOCK_SIZE_MB16X16, + BLOCK_SIZE_SB16X32, + BLOCK_SIZE_SB32X16, + BLOCK_SIZE_SB32X32, + BLOCK_SIZE_SB32X64, + BLOCK_SIZE_SB64X32, + BLOCK_SIZE_SB64X64, + BLOCK_SIZE_SB64X128, + BLOCK_SIZE_SB128X64, + BLOCK_SIZE_SB128X128, + BLOCK_SIZE_SB4X16, + BLOCK_SIZE_SB16X4, + BLOCK_SIZE_SB8X32, + BLOCK_SIZE_SB32X8, + BLOCK_SIZE_SB16X64, + BLOCK_SIZE_SB64X16, + BLOCK_SIZE_TYPES, + BLOCK_SIZES_ALL = BLOCK_SIZE_TYPES +}; + +enum filterintramodetype { + FILTER_DC_PRED, + FILTER_V_PRED, + FILTER_H_PRED, + FILTER_D153_PRED, + FILTER_PAETH_PRED, + FILTER_INTRA_MODES, + FILTER_INTRA_UNUSED = 7 +}; + +enum frametype { + KEY_FRAME = 0, + INTER_FRAME = 1, + NUM_FRAME_TYPES, +}; + +enum txsize { + TX_4X4 = 0, + TX_8X8 = 1, + TX_16X16 = 2, + TX_32X32 = 3, + TX_SIZE_MAX_SB, +}; + +enum { SIMPLE_TRANSLATION, OBMC_CAUSAL, MOTION_MODE_COUNT }; + +enum mb_prediction_mode { + DC_PRED, /* average of above and left pixels */ + V_PRED, /* vertical prediction */ + H_PRED, /* horizontal prediction */ + D45_PRED, /* Directional 45 deg prediction [anti-clockwise from 0 deg hor] */ + D135_PRED, /* Directional 135 deg prediction [anti-clockwise from 0 deg hor] */ + D117_PRED, /* Directional 112 deg prediction [anti-clockwise from 0 deg hor] */ + D153_PRED, /* Directional 157 deg prediction [anti-clockwise from 0 deg hor] */ + D27_PRED, /* Directional 22 deg prediction [anti-clockwise from 0 deg hor] */ + D63_PRED, /* Directional 67 deg prediction [anti-clockwise from 0 deg hor] */ + SMOOTH_PRED, + TM_PRED_AV1 = SMOOTH_PRED, + SMOOTH_V_PRED, // Vertical interpolation + SMOOTH_H_PRED, // Horizontal interpolation + TM_PRED, /* Truemotion prediction */ + PAETH_PRED = TM_PRED, + NEARESTMV, + NEARMV, + ZEROMV, + NEWMV, + NEAREST_NEARESTMV, + NEAR_NEARMV, + NEAREST_NEWMV, + NEW_NEARESTMV, + NEAR_NEWMV, + NEW_NEARMV, + ZERO_ZEROMV, + NEW_NEWMV, + SPLITMV, + MB_MODE_COUNT +}; + +enum partitiontype { + PARTITION_NONE, + PARTITION_HORZ, + PARTITION_VERT, + PARTITION_SPLIT, + PARTITION_TYPES +}; + +struct mvcdfs { + u16 joint_cdf[3]; + u16 sign_cdf[2]; + u16 clsss_cdf[2][10]; + u16 clsss0_fp_cdf[2][2][3]; + u16 fp_cdf[2][3]; + u16 class0_hp_cdf[2]; + u16 hp_cdf[2]; + u16 class0_cdf[2]; + u16 bits_cdf[2][10]; +}; + +struct av1cdfs { + u16 partition_cdf[13][16]; + u16 kf_ymode_cdf[KF_MODE_CONTEXTS][KF_MODE_CONTEXTS][AV1_INTRA_MODES - 1]; + u16 segment_pred_cdf[PREDICTION_PROBS]; + u16 spatial_pred_seg_tree_cdf[SPATIAL_PREDICTION_PROBS][MAX_MB_SEGMENTS - 1]; + u16 mbskip_cdf[MBSKIP_CONTEXTS]; + u16 delta_q_cdf[DELTA_Q_PROBS]; + u16 delta_lf_multi_cdf[FRAME_LF_COUNT][DELTA_LF_PROBS]; + u16 delta_lf_cdf[DELTA_LF_PROBS]; + u16 skip_mode_cdf[SKIP_MODE_CONTEXTS]; + u16 vartx_part_cdf[VARTX_PART_CONTEXTS][1]; + u16 tx_size_cdf[MAX_TX_CATS][AV1_TX_SIZE_CONTEXTS][MAX_TX_DEPTH]; + u16 if_ymode_cdf[BLOCK_SIZE_GROUPS][AV1_INTRA_MODES - 1]; + u16 uv_mode_cdf[2][AV1_INTRA_MODES][AV1_INTRA_MODES - 1 + 1]; + u16 intra_inter_cdf[INTRA_INTER_CONTEXTS]; + u16 comp_inter_cdf[COMP_INTER_CONTEXTS]; + u16 single_ref_cdf[AV1_REF_CONTEXTS][SINGLE_REFS - 1]; + u16 comp_ref_type_cdf[COMP_REF_TYPE_CONTEXTS][1]; + u16 uni_comp_ref_cdf[UNI_COMP_REF_CONTEXTS][UNIDIR_COMP_REFS - 1][1]; + u16 comp_ref_cdf[AV1_REF_CONTEXTS][FWD_REFS - 1]; + u16 comp_bwdref_cdf[AV1_REF_CONTEXTS][BWD_REFS - 1]; + u16 newmv_cdf[NEWMV_MODE_CONTEXTS]; + u16 zeromv_cdf[ZEROMV_MODE_CONTEXTS]; + u16 refmv_cdf[REFMV_MODE_CONTEXTS]; + u16 drl_cdf[DRL_MODE_CONTEXTS]; + u16 interp_filter_cdf[SWITCHABLE_FILTER_CONTEXTS][AV1_SWITCHABLE_FILTERS - 1]; + struct mvcdfs mv_cdf; + u16 obmc_cdf[BLOCK_SIZE_TYPES]; + u16 motion_mode_cdf[BLOCK_SIZE_TYPES][2]; + u16 inter_compound_mode_cdf[AV1_INTER_MODE_CONTEXTS][INTER_COMPOUND_MODES - 1]; + u16 compound_type_cdf[BLOCK_SIZE_TYPES][CDF_SIZE(COMPOUND_TYPES - 1)]; + u16 interintra_cdf[BLOCK_SIZE_GROUPS]; + u16 interintra_mode_cdf[BLOCK_SIZE_GROUPS][INTERINTRA_MODES - 1]; + u16 wedge_interintra_cdf[BLOCK_SIZE_TYPES]; + u16 wedge_idx_cdf[BLOCK_SIZE_TYPES][CDF_SIZE(16)]; + u16 palette_y_mode_cdf[PALETTE_BLOCK_SIZES][PALETTE_Y_MODE_CONTEXTS][1]; + u16 palette_uv_mode_cdf[PALETTE_UV_MODE_CONTEXTS][1]; + u16 palette_y_size_cdf[PALETTE_BLOCK_SIZES][PALETTE_SIZES - 1]; + u16 palette_uv_size_cdf[PALETTE_BLOCK_SIZES][PALETTE_SIZES - 1]; + u16 cfl_sign_cdf[CFL_JOINT_SIGNS - 1]; + u16 cfl_alpha_cdf[CFL_ALPHA_CONTEXTS][CFL_ALPHABET_SIZE - 1]; + u16 intrabc_cdf[1]; + u16 angle_delta_cdf[DIRECTIONAL_MODES][6]; + u16 filter_intra_mode_cdf[FILTER_INTRA_MODES - 1]; + u16 filter_intra_cdf[BLOCK_SIZES_ALL]; + u16 comp_group_idx_cdf[COMP_GROUP_IDX_CONTEXTS][CDF_SIZE(2)]; + u16 compound_idx_cdf[COMP_INDEX_CONTEXTS][CDF_SIZE(2)]; + u16 dummy0[14]; + // Palette index contexts; sizes 1/7, 2/6, 3/5 packed together + u16 palette_y_color_index_cdf[PALETTE_IDX_CONTEXTS][8]; + u16 palette_uv_color_index_cdf[PALETTE_IDX_CONTEXTS][8]; + u16 tx_type_intra0_cdf[EXTTX_SIZES][AV1_INTRA_MODES][8]; + u16 tx_type_intra1_cdf[EXTTX_SIZES][AV1_INTRA_MODES][4]; + u16 tx_type_inter_cdf[2][EXTTX_SIZES][EXT_TX_TYPES]; + u16 txb_skip_cdf[TX_SIZES][TXB_SKIP_CONTEXTS][CDF_SIZE(2)]; + u16 eob_extra_cdf[TX_SIZES][PLANE_TYPES][EOB_COEF_CONTEXTS][CDF_SIZE(2)]; + u16 dummy1[5]; + u16 eob_flag_cdf16[PLANE_TYPES][2][4]; + u16 eob_flag_cdf32[PLANE_TYPES][2][8]; + u16 eob_flag_cdf64[PLANE_TYPES][2][8]; + u16 eob_flag_cdf128[PLANE_TYPES][2][8]; + u16 eob_flag_cdf256[PLANE_TYPES][2][8]; + u16 eob_flag_cdf512[PLANE_TYPES][2][16]; + u16 eob_flag_cdf1024[PLANE_TYPES][2][16]; + u16 coeff_base_eob_cdf[TX_SIZES][PLANE_TYPES][SIG_COEF_CONTEXTS_EOB][CDF_SIZE(3)]; + u16 coeff_base_cdf[TX_SIZES][PLANE_TYPES][SIG_COEF_CONTEXTS][CDF_SIZE(4) + 1]; + u16 dc_sign_cdf[PLANE_TYPES][DC_SIGN_CONTEXTS][CDF_SIZE(2)]; + u16 dummy2[2]; + u16 coeff_br_cdf[TX_SIZES][PLANE_TYPES][LEVEL_CONTEXTS][CDF_SIZE(BR_CDF_SIZE) + 1]; + u16 dummy3[16]; +}; + +void rockchip_av1_store_cdfs(struct hantro_ctx *ctx, + u32 refresh_frame_flags); +void rockchip_av1_get_cdfs(struct hantro_ctx *ctx, u32 ref_idx); +void rockchip_av1_set_default_cdfs(struct av1cdfs *cdfs, + struct mvcdfs *cdfs_ndvc); +void rockchip_av1_default_coeff_probs(u32 base_qindex, void *ptr); + +#endif /* _ROCKCHIP_AV1_ENTROPYMODE_H_ */ diff --git a/drivers/media/platform/verisilicon/rockchip_av1_filmgrain.c b/drivers/media/platform/verisilicon/rockchip_av1_filmgrain.c new file mode 100644 index 0000000000000000000000000000000000000000..f2ae84f0b4368e9636eb272f5dfab9d78c3bd9a7 --- /dev/null +++ b/drivers/media/platform/verisilicon/rockchip_av1_filmgrain.c @@ -0,0 +1,401 @@ +// SPDX-License-Identifier: GPL-2.0-only or Apache-2.0 + +#include "rockchip_av1_filmgrain.h" + +static const s32 gaussian_sequence[2048] = { + 56, 568, -180, 172, 124, -84, 172, -64, -900, 24, 820, + 224, 1248, 996, 272, -8, -916, -388, -732, -104, -188, 800, + 112, -652, -320, -376, 140, -252, 492, -168, 44, -788, 588, + -584, 500, -228, 12, 680, 272, -476, 972, -100, 652, 368, + 432, -196, -720, -192, 1000, -332, 652, -136, -552, -604, -4, + 192, -220, -136, 1000, -52, 372, -96, -624, 124, -24, 396, + 540, -12, -104, 640, 464, 244, -208, -84, 368, -528, -740, + 248, -968, -848, 608, 376, -60, -292, -40, -156, 252, -292, + 248, 224, -280, 400, -244, 244, -60, 76, -80, 212, 532, + 340, 128, -36, 824, -352, -60, -264, -96, -612, 416, -704, + 220, -204, 640, -160, 1220, -408, 900, 336, 20, -336, -96, + -792, 304, 48, -28, -1232, -1172, -448, 104, -292, -520, 244, + 60, -948, 0, -708, 268, 108, 356, -548, 488, -344, -136, + 488, -196, -224, 656, -236, -1128, 60, 4, 140, 276, -676, + -376, 168, -108, 464, 8, 564, 64, 240, 308, -300, -400, + -456, -136, 56, 120, -408, -116, 436, 504, -232, 328, 844, + -164, -84, 784, -168, 232, -224, 348, -376, 128, 568, 96, + -1244, -288, 276, 848, 832, -360, 656, 464, -384, -332, -356, + 728, -388, 160, -192, 468, 296, 224, 140, -776, -100, 280, + 4, 196, 44, -36, -648, 932, 16, 1428, 28, 528, 808, + 772, 20, 268, 88, -332, -284, 124, -384, -448, 208, -228, + -1044, -328, 660, 380, -148, -300, 588, 240, 540, 28, 136, + -88, -436, 256, 296, -1000, 1400, 0, -48, 1056, -136, 264, + -528, -1108, 632, -484, -592, -344, 796, 124, -668, -768, 388, + 1296, -232, -188, -200, -288, -4, 308, 100, -168, 256, -500, + 204, -508, 648, -136, 372, -272, -120, -1004, -552, -548, -384, + 548, -296, 428, -108, -8, -912, -324, -224, -88, -112, -220, + -100, 996, -796, 548, 360, -216, 180, 428, -200, -212, 148, + 96, 148, 284, 216, -412, -320, 120, -300, -384, -604, -572, + -332, -8, -180, -176, 696, 116, -88, 628, 76, 44, -516, + 240, -208, -40, 100, -592, 344, -308, -452, -228, 20, 916, + -1752, -136, -340, -804, 140, 40, 512, 340, 248, 184, -492, + 896, -156, 932, -628, 328, -688, -448, -616, -752, -100, 560, + -1020, 180, -800, -64, 76, 576, 1068, 396, 660, 552, -108, + -28, 320, -628, 312, -92, -92, -472, 268, 16, 560, 516, + -672, -52, 492, -100, 260, 384, 284, 292, 304, -148, 88, + -152, 1012, 1064, -228, 164, -376, -684, 592, -392, 156, 196, + -524, -64, -884, 160, -176, 636, 648, 404, -396, -436, 864, + 424, -728, 988, -604, 904, -592, 296, -224, 536, -176, -920, + 436, -48, 1176, -884, 416, -776, -824, -884, 524, -548, -564, + -68, -164, -96, 692, 364, -692, -1012, -68, 260, -480, 876, + -1116, 452, -332, -352, 892, -1088, 1220, -676, 12, -292, 244, + 496, 372, -32, 280, 200, 112, -440, -96, 24, -644, -184, + 56, -432, 224, -980, 272, -260, 144, -436, 420, 356, 364, + -528, 76, 172, -744, -368, 404, -752, -416, 684, -688, 72, + 540, 416, 92, 444, 480, -72, -1416, 164, -1172, -68, 24, + 424, 264, 1040, 128, -912, -524, -356, 64, 876, -12, 4, + -88, 532, 272, -524, 320, 276, -508, 940, 24, -400, -120, + 756, 60, 236, -412, 100, 376, -484, 400, -100, -740, -108, + -260, 328, -268, 224, -200, -416, 184, -604, -564, -20, 296, + 60, 892, -888, 60, 164, 68, -760, 216, -296, 904, -336, + -28, 404, -356, -568, -208, -1480, -512, 296, 328, -360, -164, + -1560, -776, 1156, -428, 164, -504, -112, 120, -216, -148, -264, + 308, 32, 64, -72, 72, 116, 176, -64, -272, 460, -536, + -784, -280, 348, 108, -752, -132, 524, -540, -776, 116, -296, + -1196, -288, -560, 1040, -472, 116, -848, -1116, 116, 636, 696, + 284, -176, 1016, 204, -864, -648, -248, 356, 972, -584, -204, + 264, 880, 528, -24, -184, 116, 448, -144, 828, 524, 212, + -212, 52, 12, 200, 268, -488, -404, -880, 824, -672, -40, + 908, -248, 500, 716, -576, 492, -576, 16, 720, -108, 384, + 124, 344, 280, 576, -500, 252, 104, -308, 196, -188, -8, + 1268, 296, 1032, -1196, 436, 316, 372, -432, -200, -660, 704, + -224, 596, -132, 268, 32, -452, 884, 104, -1008, 424, -1348, + -280, 4, -1168, 368, 476, 696, 300, -8, 24, 180, -592, + -196, 388, 304, 500, 724, -160, 244, -84, 272, -256, -420, + 320, 208, -144, -156, 156, 364, 452, 28, 540, 316, 220, + -644, -248, 464, 72, 360, 32, -388, 496, -680, -48, 208, + -116, -408, 60, -604, -392, 548, -840, 784, -460, 656, -544, + -388, -264, 908, -800, -628, -612, -568, 572, -220, 164, 288, + -16, -308, 308, -112, -636, -760, 280, -668, 432, 364, 240, + -196, 604, 340, 384, 196, 592, -44, -500, 432, -580, -132, + 636, -76, 392, 4, -412, 540, 508, 328, -356, -36, 16, + -220, -64, -248, -60, 24, -192, 368, 1040, 92, -24, -1044, + -32, 40, 104, 148, 192, -136, -520, 56, -816, -224, 732, + 392, 356, 212, -80, -424, -1008, -324, 588, -1496, 576, 460, + -816, -848, 56, -580, -92, -1372, -112, -496, 200, 364, 52, + -140, 48, -48, -60, 84, 72, 40, 132, -356, -268, -104, + -284, -404, 732, -520, 164, -304, -540, 120, 328, -76, -460, + 756, 388, 588, 236, -436, -72, -176, -404, -316, -148, 716, + -604, 404, -72, -88, -888, -68, 944, 88, -220, -344, 960, + 472, 460, -232, 704, 120, 832, -228, 692, -508, 132, -476, + 844, -748, -364, -44, 1116, -1104, -1056, 76, 428, 552, -692, + 60, 356, 96, -384, -188, -612, -576, 736, 508, 892, 352, + -1132, 504, -24, -352, 324, 332, -600, -312, 292, 508, -144, + -8, 484, 48, 284, -260, -240, 256, -100, -292, -204, -44, + 472, -204, 908, -188, -1000, -256, 92, 1164, -392, 564, 356, + 652, -28, -884, 256, 484, -192, 760, -176, 376, -524, -452, + -436, 860, -736, 212, 124, 504, -476, 468, 76, -472, 552, + -692, -944, -620, 740, -240, 400, 132, 20, 192, -196, 264, + -668, -1012, -60, 296, -316, -828, 76, -156, 284, -768, -448, + -832, 148, 248, 652, 616, 1236, 288, -328, -400, -124, 588, + 220, 520, -696, 1032, 768, -740, -92, -272, 296, 448, -464, + 412, -200, 392, 440, -200, 264, -152, -260, 320, 1032, 216, + 320, -8, -64, 156, -1016, 1084, 1172, 536, 484, -432, 132, + 372, -52, -256, 84, 116, -352, 48, 116, 304, -384, 412, + 924, -300, 528, 628, 180, 648, 44, -980, -220, 1320, 48, + 332, 748, 524, -268, -720, 540, -276, 564, -344, -208, -196, + 436, 896, 88, -392, 132, 80, -964, -288, 568, 56, -48, + -456, 888, 8, 552, -156, -292, 948, 288, 128, -716, -292, + 1192, -152, 876, 352, -600, -260, -812, -468, -28, -120, -32, + -44, 1284, 496, 192, 464, 312, -76, -516, -380, -456, -1012, + -48, 308, -156, 36, 492, -156, -808, 188, 1652, 68, -120, + -116, 316, 160, -140, 352, 808, -416, 592, 316, -480, 56, + 528, -204, -568, 372, -232, 752, -344, 744, -4, 324, -416, + -600, 768, 268, -248, -88, -132, -420, -432, 80, -288, 404, + -316, -1216, -588, 520, -108, 92, -320, 368, -480, -216, -92, + 1688, -300, 180, 1020, -176, 820, -68, -228, -260, 436, -904, + 20, 40, -508, 440, -736, 312, 332, 204, 760, -372, 728, + 96, -20, -632, -520, -560, 336, 1076, -64, -532, 776, 584, + 192, 396, -728, -520, 276, -188, 80, -52, -612, -252, -48, + 648, 212, -688, 228, -52, -260, 428, -412, -272, -404, 180, + 816, -796, 48, 152, 484, -88, -216, 988, 696, 188, -528, + 648, -116, -180, 316, 476, 12, -564, 96, 476, -252, -364, + -376, -392, 556, -256, -576, 260, -352, 120, -16, -136, -260, + -492, 72, 556, 660, 580, 616, 772, 436, 424, -32, -324, + -1268, 416, -324, -80, 920, 160, 228, 724, 32, -516, 64, + 384, 68, -128, 136, 240, 248, -204, -68, 252, -932, -120, + -480, -628, -84, 192, 852, -404, -288, -132, 204, 100, 168, + -68, -196, -868, 460, 1080, 380, -80, 244, 0, 484, -888, + 64, 184, 352, 600, 460, 164, 604, -196, 320, -64, 588, + -184, 228, 12, 372, 48, -848, -344, 224, 208, -200, 484, + 128, -20, 272, -468, -840, 384, 256, -720, -520, -464, -580, + 112, -120, 644, -356, -208, -608, -528, 704, 560, -424, 392, + 828, 40, 84, 200, -152, 0, -144, 584, 280, -120, 80, + -556, -972, -196, -472, 724, 80, 168, -32, 88, 160, -688, + 0, 160, 356, 372, -776, 740, -128, 676, -248, -480, 4, + -364, 96, 544, 232, -1032, 956, 236, 356, 20, -40, 300, + 24, -676, -596, 132, 1120, -104, 532, -1096, 568, 648, 444, + 508, 380, 188, -376, -604, 1488, 424, 24, 756, -220, -192, + 716, 120, 920, 688, 168, 44, -460, 568, 284, 1144, 1160, + 600, 424, 888, 656, -356, -320, 220, 316, -176, -724, -188, + -816, -628, -348, -228, -380, 1012, -452, -660, 736, 928, 404, + -696, -72, -268, -892, 128, 184, -344, -780, 360, 336, 400, + 344, 428, 548, -112, 136, -228, -216, -820, -516, 340, 92, + -136, 116, -300, 376, -244, 100, -316, -520, -284, -12, 824, + 164, -548, -180, -128, 116, -924, -828, 268, -368, -580, 620, + 192, 160, 0, -1676, 1068, 424, -56, -360, 468, -156, 720, + 288, -528, 556, -364, 548, -148, 504, 316, 152, -648, -620, + -684, -24, -376, -384, -108, -920, -1032, 768, 180, -264, -508, + -1268, -260, -60, 300, -240, 988, 724, -376, -576, -212, -736, + 556, 192, 1092, -620, -880, 376, -56, -4, -216, -32, 836, + 268, 396, 1332, 864, -600, 100, 56, -412, -92, 356, 180, + 884, -468, -436, 292, -388, -804, -704, -840, 368, -348, 140, + -724, 1536, 940, 372, 112, -372, 436, -480, 1136, 296, -32, + -228, 132, -48, -220, 868, -1016, -60, -1044, -464, 328, 916, + 244, 12, -736, -296, 360, 468, -376, -108, -92, 788, 368, + -56, 544, 400, -672, -420, 728, 16, 320, 44, -284, -380, + -796, 488, 132, 204, -596, -372, 88, -152, -908, -636, -572, + -624, -116, -692, -200, -56, 276, -88, 484, -324, 948, 864, + 1000, -456, -184, -276, 292, -296, 156, 676, 320, 160, 908, + -84, -1236, -288, -116, 260, -372, -644, 732, -756, -96, 84, + 344, -520, 348, -688, 240, -84, 216, -1044, -136, -676, -396, + -1500, 960, -40, 176, 168, 1516, 420, -504, -344, -364, -360, + 1216, -940, -380, -212, 252, -660, -708, 484, -444, -152, 928, + -120, 1112, 476, -260, 560, -148, -344, 108, -196, 228, -288, + 504, 560, -328, -88, 288, -1008, 460, -228, 468, -836, -196, + 76, 388, 232, 412, -1168, -716, -644, 756, -172, -356, -504, + 116, 432, 528, 48, 476, -168, -608, 448, 160, -532, -272, + 28, -676, -12, 828, 980, 456, 520, 104, -104, 256, -344, + -4, -28, -368, -52, -524, -572, -556, -200, 768, 1124, -208, + -512, 176, 232, 248, -148, -888, 604, -600, -304, 804, -156, + -212, 488, -192, -804, -256, 368, -360, -916, -328, 228, -240, + -448, -472, 856, -556, -364, 572, -12, -156, -368, -340, 432, + 252, -752, -152, 288, 268, -580, -848, -592, 108, -76, 244, + 312, -716, 592, -80, 436, 360, 4, -248, 160, 516, 584, + 732, 44, -468, -280, -292, -156, -588, 28, 308, 912, 24, + 124, 156, 180, -252, 944, -924, -772, -520, -428, -624, 300, + -212, -1144, 32, -724, 800, -1128, -212, -1288, -848, 180, -416, + 440, 192, -576, -792, -76, -1080, 80, -532, -352, -132, 380, + -820, 148, 1112, 128, 164, 456, 700, -924, 144, -668, -384, + 648, -832, 508, 552, -52, -100, -656, 208, -568, 748, -88, + 680, 232, 300, 192, -408, -1012, -152, -252, -268, 272, -876, + -664, -648, -332, -136, 16, 12, 1152, -28, 332, -536, 320, + -672, -460, -316, 532, -260, 228, -40, 1052, -816, 180, 88, + -496, -556, -672, -368, 428, 92, 356, 404, -408, 252, 196, + -176, -556, 792, 268, 32, 372, 40, 96, -332, 328, 120, + 372, -900, -40, 472, -264, -592, 952, 128, 656, 112, 664, + -232, 420, 4, -344, -464, 556, 244, -416, -32, 252, 0, + -412, 188, -696, 508, -476, 324, -1096, 656, -312, 560, 264, + -136, 304, 160, -64, -580, 248, 336, -720, 560, -348, -288, + -276, -196, -500, 852, -544, -236, -1128, -992, -776, 116, 56, + 52, 860, 884, 212, -12, 168, 1020, 512, -552, 924, -148, + 716, 188, 164, -340, -520, -184, 880, -152, -680, -208, -1156, + -300, -528, -472, 364, 100, -744, -1056, -32, 540, 280, 144, + -676, -32, -232, -280, -224, 96, 568, -76, 172, 148, 148, + 104, 32, -296, -32, 788, -80, 32, -16, 280, 288, 944, + 428, -484 +}; + +static inline s32 clamp(s32 value, s32 low, s32 high) +{ + return value < low ? low : (value > high ? high : value); +} + +static inline s32 round_power_of_two(const s32 val, s32 n) +{ + const s32 a = (s32)1 << (n - 1); + + return (val + a) >> n; +} + +static void rockchip_av1_init_random_generator(u8 luma_num, u16 seed, + u16 *random_register) +{ + u16 random_reg = seed; + + random_reg ^= ((luma_num * 37 + 178) & 255) << 8; + random_reg ^= ((luma_num * 173 + 105) & 255); + *random_register = random_reg; +} + +static inline void rockchip_av1_update_random_register(u16 *random_register) +{ + u16 bit; + u16 random_reg = *random_register; + + bit = ((random_reg >> 0) ^ (random_reg >> 1) ^ (random_reg >> 3) ^ + (random_reg >> 12)) & 1; + *random_register = (random_reg >> 1) | (bit << 15); +} + +static inline s32 rockchip_av1_get_random_number(u16 random_register) +{ + return (random_register >> 5) & ((1 << 11) - 1); +} + +void rockchip_av1_generate_luma_grain_block(s32 (*luma_grain_block)[73][82], + s32 bitdepth, + u8 num_y_points, + s32 grain_scale_shift, + s32 ar_coeff_lag, + s32 (*ar_coeffs_y)[24], + s32 ar_coeff_shift, + s32 grain_min, + s32 grain_max, + u16 random_seed) +{ + s32 gauss_sec_shift = 12 - bitdepth + grain_scale_shift; + u16 grain_random_register = random_seed; + s32 i, j; + + for (i = 0; i < 73; i++) { + for (j = 0; j < 82; j++) { + if (num_y_points > 0) { + rockchip_av1_update_random_register + (&grain_random_register); + (*luma_grain_block)[i][j] = + round_power_of_two(gaussian_sequence + [rockchip_av1_get_random_number + (grain_random_register)], + gauss_sec_shift); + } else { + (*luma_grain_block)[i][j] = 0; + } + } + } + + for (i = 3; i < 73; i++) + for (j = 3; j < 82 - 3; j++) { + s32 pos = 0; + s32 wsum = 0; + s32 deltarow, deltacol; + + for (deltarow = -ar_coeff_lag; deltarow <= 0; + deltarow++) { + for (deltacol = -ar_coeff_lag; + deltacol <= ar_coeff_lag; deltacol++) { + if (deltarow == 0 && deltacol == 0) + break; + wsum = wsum + (*ar_coeffs_y)[pos] * + (*luma_grain_block)[i + deltarow][j + deltacol]; + ++pos; + } + } + (*luma_grain_block)[i][j] = + clamp((*luma_grain_block)[i][j] + + round_power_of_two(wsum, ar_coeff_shift), + grain_min, grain_max); + } +} + +// Calculate chroma grain noise once per frame +void rockchip_av1_generate_chroma_grain_block(s32 (*luma_grain_block)[73][82], + s32 (*cb_grain_block)[38][44], + s32 (*cr_grain_block)[38][44], + s32 bitdepth, + u8 num_y_points, + u8 num_cb_points, + u8 num_cr_points, + s32 grain_scale_shift, + s32 ar_coeff_lag, + s32 (*ar_coeffs_cb)[25], + s32 (*ar_coeffs_cr)[25], + s32 ar_coeff_shift, + s32 grain_min, + s32 grain_max, + u8 chroma_scaling_from_luma, + u16 random_seed) +{ + s32 gauss_sec_shift = 12 - bitdepth + grain_scale_shift; + u16 grain_random_register = 0; + s32 i, j; + + rockchip_av1_init_random_generator(7, random_seed, + &grain_random_register); + for (i = 0; i < 38; i++) { + for (j = 0; j < 44; j++) { + if (num_cb_points || chroma_scaling_from_luma) { + rockchip_av1_update_random_register + (&grain_random_register); + (*cb_grain_block)[i][j] = + round_power_of_two(gaussian_sequence + [rockchip_av1_get_random_number + (grain_random_register)], + gauss_sec_shift); + } else { + (*cb_grain_block)[i][j] = 0; + } + } + } + + rockchip_av1_init_random_generator(11, random_seed, + &grain_random_register); + for (i = 0; i < 38; i++) { + for (j = 0; j < 44; j++) { + if (num_cr_points || chroma_scaling_from_luma) { + rockchip_av1_update_random_register + (&grain_random_register); + (*cr_grain_block)[i][j] = + round_power_of_two(gaussian_sequence + [rockchip_av1_get_random_number + (grain_random_register)], + gauss_sec_shift); + } else { + (*cr_grain_block)[i][j] = 0; + } + } + } + + for (i = 3; i < 38; i++) { + for (j = 3; j < 44 - 3; j++) { + s32 wsum_cb = 0; + s32 wsum_cr = 0; + s32 pos = 0; + s32 deltarow, deltacol; + + for (deltarow = -ar_coeff_lag; deltarow <= 0; + deltarow++) { + for (deltacol = -ar_coeff_lag; + deltacol <= ar_coeff_lag; deltacol++) { + if (deltarow == 0 && deltacol == 0) + break; + wsum_cb = wsum_cb + (*ar_coeffs_cb)[pos] * + (*cb_grain_block)[i + deltarow][j + deltacol]; + wsum_cr = + wsum_cr + + (*ar_coeffs_cr)[pos] * + (*cr_grain_block)[i + deltarow][j + deltacol]; + ++pos; + } + } + + if (num_y_points > 0) { + s32 av_luma = 0; + s32 luma_coord_y = (i << 1) - 3; + s32 luma_coord_x = (j << 1) - 3; + + av_luma += + (*luma_grain_block)[luma_coord_y][luma_coord_x]; + av_luma += + (*luma_grain_block)[luma_coord_y][luma_coord_x + 1]; + av_luma += + (*luma_grain_block)[luma_coord_y + 1][luma_coord_x]; + av_luma += + (*luma_grain_block)[(luma_coord_y + 1)][luma_coord_x + 1]; + av_luma = round_power_of_two(av_luma, 2); + + wsum_cb = wsum_cb + (*ar_coeffs_cb)[pos] * av_luma; + wsum_cr = wsum_cr + (*ar_coeffs_cr)[pos] * av_luma; + } + + if (num_cb_points || chroma_scaling_from_luma) { + (*cb_grain_block)[i][j] = + clamp((*cb_grain_block)[i][j] + + round_power_of_two(wsum_cb, ar_coeff_shift), + grain_min, grain_max); + } + if (num_cr_points || chroma_scaling_from_luma) { + (*cr_grain_block)[i][j] = + clamp((*cr_grain_block)[i][j] + + round_power_of_two(wsum_cr, ar_coeff_shift), + grain_min, grain_max); + } + } + } +} diff --git a/drivers/media/platform/verisilicon/rockchip_av1_filmgrain.h b/drivers/media/platform/verisilicon/rockchip_av1_filmgrain.h new file mode 100644 index 0000000000000000000000000000000000000000..31a8b7920c31bbd11464441e48309696bbc80990 --- /dev/null +++ b/drivers/media/platform/verisilicon/rockchip_av1_filmgrain.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef _ROCKCHIP_AV1_FILMGRAIN_H_ +#define _ROCKCHIP_AV1_FILMGRAIN_H_ + +#include + +void rockchip_av1_generate_luma_grain_block(s32 (*luma_grain_block)[73][82], + s32 bitdepth, + u8 num_y_points, + s32 grain_scale_shift, + s32 ar_coeff_lag, + s32 (*ar_coeffs_y)[24], + s32 ar_coeff_shift, + s32 grain_min, + s32 grain_max, + u16 random_seed); + +void rockchip_av1_generate_chroma_grain_block(s32 (*luma_grain_block)[73][82], + s32 (*cb_grain_block)[38][44], + s32 (*cr_grain_block)[38][44], + s32 bitdepth, + u8 num_y_points, + u8 num_cb_points, + u8 num_cr_points, + s32 grain_scale_shift, + s32 ar_coeff_lag, + s32 (*ar_coeffs_cb)[25], + s32 (*ar_coeffs_cr)[25], + s32 ar_coeff_shift, + s32 grain_min, + s32 grain_max, + u8 chroma_scaling_from_luma, + u16 random_seed); + +#endif diff --git a/drivers/media/platform/verisilicon/rockchip_vpu981_hw_av1_dec.c b/drivers/media/platform/verisilicon/rockchip_vpu981_hw_av1_dec.c new file mode 100644 index 0000000000000000000000000000000000000000..cc4483857489c50257b75cb3dd99a09c2a3bbef8 --- /dev/null +++ b/drivers/media/platform/verisilicon/rockchip_vpu981_hw_av1_dec.c @@ -0,0 +1,2232 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2023, Collabora + * + * Author: Benjamin Gaignard + */ + +#include +#include "hantro.h" +#include "hantro_v4l2.h" +#include "rockchip_vpu981_regs.h" + +#define AV1_DEC_MODE 17 +#define GM_GLOBAL_MODELS_PER_FRAME 7 +#define GLOBAL_MODEL_TOTAL_SIZE (6 * 4 + 4 * 2) +#define GLOBAL_MODEL_SIZE ALIGN(GM_GLOBAL_MODELS_PER_FRAME * GLOBAL_MODEL_TOTAL_SIZE, 2048) +#define AV1_MAX_TILES 128 +#define AV1_TILE_INFO_SIZE (AV1_MAX_TILES * 16) +#define AV1DEC_MAX_PIC_BUFFERS 24 +#define AV1_REF_SCALE_SHIFT 14 +#define AV1_INVALID_IDX -1 +#define MAX_FRAME_DISTANCE 31 +#define AV1_PRIMARY_REF_NONE 7 +#define AV1_TILE_SIZE ALIGN(32 * 128, 4096) +/* + * These 3 values aren't defined enum v4l2_av1_segment_feature because + * they are not part of the specification + */ +#define V4L2_AV1_SEG_LVL_ALT_LF_Y_H 2 +#define V4L2_AV1_SEG_LVL_ALT_LF_U 3 +#define V4L2_AV1_SEG_LVL_ALT_LF_V 4 + +#define SUPERRES_SCALE_BITS 3 +#define SCALE_NUMERATOR 8 +#define SUPERRES_SCALE_DENOMINATOR_MIN (SCALE_NUMERATOR + 1) + +#define RS_SUBPEL_BITS 6 +#define RS_SUBPEL_MASK ((1 << RS_SUBPEL_BITS) - 1) +#define RS_SCALE_SUBPEL_BITS 14 +#define RS_SCALE_SUBPEL_MASK ((1 << RS_SCALE_SUBPEL_BITS) - 1) +#define RS_SCALE_EXTRA_BITS (RS_SCALE_SUBPEL_BITS - RS_SUBPEL_BITS) +#define RS_SCALE_EXTRA_OFF (1 << (RS_SCALE_EXTRA_BITS - 1)) + +#define IS_INTRA(type) ((type == V4L2_AV1_KEY_FRAME) || (type == V4L2_AV1_INTRA_ONLY_FRAME)) + +#define LST_BUF_IDX (V4L2_AV1_REF_LAST_FRAME - V4L2_AV1_REF_LAST_FRAME) +#define LST2_BUF_IDX (V4L2_AV1_REF_LAST2_FRAME - V4L2_AV1_REF_LAST_FRAME) +#define LST3_BUF_IDX (V4L2_AV1_REF_LAST3_FRAME - V4L2_AV1_REF_LAST_FRAME) +#define GLD_BUF_IDX (V4L2_AV1_REF_GOLDEN_FRAME - V4L2_AV1_REF_LAST_FRAME) +#define BWD_BUF_IDX (V4L2_AV1_REF_BWDREF_FRAME - V4L2_AV1_REF_LAST_FRAME) +#define ALT2_BUF_IDX (V4L2_AV1_REF_ALTREF2_FRAME - V4L2_AV1_REF_LAST_FRAME) +#define ALT_BUF_IDX (V4L2_AV1_REF_ALTREF_FRAME - V4L2_AV1_REF_LAST_FRAME) + +#define DIV_LUT_PREC_BITS 14 +#define DIV_LUT_BITS 8 +#define DIV_LUT_NUM BIT(DIV_LUT_BITS) +#define WARP_PARAM_REDUCE_BITS 6 +#define WARPEDMODEL_PREC_BITS 16 + +#define AV1_DIV_ROUND_UP_POW2(value, n) \ +({ \ + typeof(n) _n = n; \ + typeof(value) _value = value; \ + (_value + (BIT(_n) >> 1)) >> _n; \ +}) + +#define AV1_DIV_ROUND_UP_POW2_SIGNED(value, n) \ +({ \ + typeof(n) _n_ = n; \ + typeof(value) _value_ = value; \ + (((_value_) < 0) ? -AV1_DIV_ROUND_UP_POW2(-(_value_), (_n_)) \ + : AV1_DIV_ROUND_UP_POW2((_value_), (_n_))); \ +}) + +struct rockchip_av1_film_grain { + u8 scaling_lut_y[256]; + u8 scaling_lut_cb[256]; + u8 scaling_lut_cr[256]; + s16 cropped_luma_grain_block[4096]; + s16 cropped_chroma_grain_block[1024 * 2]; +}; + +static const short div_lut[DIV_LUT_NUM + 1] = { + 16384, 16320, 16257, 16194, 16132, 16070, 16009, 15948, 15888, 15828, 15768, + 15709, 15650, 15592, 15534, 15477, 15420, 15364, 15308, 15252, 15197, 15142, + 15087, 15033, 14980, 14926, 14873, 14821, 14769, 14717, 14665, 14614, 14564, + 14513, 14463, 14413, 14364, 14315, 14266, 14218, 14170, 14122, 14075, 14028, + 13981, 13935, 13888, 13843, 13797, 13752, 13707, 13662, 13618, 13574, 13530, + 13487, 13443, 13400, 13358, 13315, 13273, 13231, 13190, 13148, 13107, 13066, + 13026, 12985, 12945, 12906, 12866, 12827, 12788, 12749, 12710, 12672, 12633, + 12596, 12558, 12520, 12483, 12446, 12409, 12373, 12336, 12300, 12264, 12228, + 12193, 12157, 12122, 12087, 12053, 12018, 11984, 11950, 11916, 11882, 11848, + 11815, 11782, 11749, 11716, 11683, 11651, 11619, 11586, 11555, 11523, 11491, + 11460, 11429, 11398, 11367, 11336, 11305, 11275, 11245, 11215, 11185, 11155, + 11125, 11096, 11067, 11038, 11009, 10980, 10951, 10923, 10894, 10866, 10838, + 10810, 10782, 10755, 10727, 10700, 10673, 10645, 10618, 10592, 10565, 10538, + 10512, 10486, 10460, 10434, 10408, 10382, 10356, 10331, 10305, 10280, 10255, + 10230, 10205, 10180, 10156, 10131, 10107, 10082, 10058, 10034, 10010, 9986, + 9963, 9939, 9916, 9892, 9869, 9846, 9823, 9800, 9777, 9754, 9732, + 9709, 9687, 9664, 9642, 9620, 9598, 9576, 9554, 9533, 9511, 9489, + 9468, 9447, 9425, 9404, 9383, 9362, 9341, 9321, 9300, 9279, 9259, + 9239, 9218, 9198, 9178, 9158, 9138, 9118, 9098, 9079, 9059, 9039, + 9020, 9001, 8981, 8962, 8943, 8924, 8905, 8886, 8867, 8849, 8830, + 8812, 8793, 8775, 8756, 8738, 8720, 8702, 8684, 8666, 8648, 8630, + 8613, 8595, 8577, 8560, 8542, 8525, 8508, 8490, 8473, 8456, 8439, + 8422, 8405, 8389, 8372, 8355, 8339, 8322, 8306, 8289, 8273, 8257, + 8240, 8224, 8208, 8192, +}; + +static int rockchip_vpu981_get_frame_index(struct hantro_ctx *ctx, int ref) +{ + struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec; + struct hantro_av1_dec_ctrls *ctrls = &av1_dec->ctrls; + const struct v4l2_ctrl_av1_frame *frame = ctrls->frame; + u64 timestamp; + int i, idx = frame->ref_frame_idx[ref]; + + if (idx >= V4L2_AV1_TOTAL_REFS_PER_FRAME || idx < 0) + return AV1_INVALID_IDX; + + timestamp = frame->reference_frame_ts[idx]; + for (i = 0; i < AV1_MAX_FRAME_BUF_COUNT; i++) { + if (!av1_dec->frame_refs[i].used) + continue; + if (av1_dec->frame_refs[i].timestamp == timestamp) + return i; + } + + return AV1_INVALID_IDX; +} + +static int rockchip_vpu981_get_order_hint(struct hantro_ctx *ctx, int ref) +{ + struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec; + int idx = rockchip_vpu981_get_frame_index(ctx, ref); + + if (idx != AV1_INVALID_IDX) + return av1_dec->frame_refs[idx].order_hint; + + return 0; +} + +static int rockchip_vpu981_av1_dec_frame_ref(struct hantro_ctx *ctx, + u64 timestamp) +{ + struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec; + struct hantro_av1_dec_ctrls *ctrls = &av1_dec->ctrls; + const struct v4l2_ctrl_av1_frame *frame = ctrls->frame; + int i; + + for (i = 0; i < AV1_MAX_FRAME_BUF_COUNT; i++) { + int j; + + if (av1_dec->frame_refs[i].used) + continue; + + av1_dec->frame_refs[i].width = frame->frame_width_minus_1 + 1; + av1_dec->frame_refs[i].height = frame->frame_height_minus_1 + 1; + av1_dec->frame_refs[i].mi_cols = DIV_ROUND_UP(frame->frame_width_minus_1 + 1, 8); + av1_dec->frame_refs[i].mi_rows = DIV_ROUND_UP(frame->frame_height_minus_1 + 1, 8); + av1_dec->frame_refs[i].timestamp = timestamp; + av1_dec->frame_refs[i].frame_type = frame->frame_type; + av1_dec->frame_refs[i].order_hint = frame->order_hint; + if (!av1_dec->frame_refs[i].vb2_ref) + av1_dec->frame_refs[i].vb2_ref = hantro_get_dst_buf(ctx); + + for (j = 0; j < V4L2_AV1_TOTAL_REFS_PER_FRAME; j++) + av1_dec->frame_refs[i].order_hints[j] = frame->order_hints[j]; + av1_dec->frame_refs[i].used = true; + av1_dec->current_frame_index = i; + + return i; + } + + return AV1_INVALID_IDX; +} + +static void rockchip_vpu981_av1_dec_frame_unref(struct hantro_ctx *ctx, int idx) +{ + struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec; + + if (idx >= 0) + av1_dec->frame_refs[idx].used = false; +} + +static void rockchip_vpu981_av1_dec_clean_refs(struct hantro_ctx *ctx) +{ + struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec; + struct hantro_av1_dec_ctrls *ctrls = &av1_dec->ctrls; + + int ref, idx; + + for (idx = 0; idx < AV1_MAX_FRAME_BUF_COUNT; idx++) { + u64 timestamp = av1_dec->frame_refs[idx].timestamp; + bool used = false; + + if (!av1_dec->frame_refs[idx].used) + continue; + + for (ref = 0; ref < V4L2_AV1_TOTAL_REFS_PER_FRAME; ref++) { + if (ctrls->frame->reference_frame_ts[ref] == timestamp) + used = true; + } + + if (!used) + rockchip_vpu981_av1_dec_frame_unref(ctx, idx); + } +} + +static size_t rockchip_vpu981_av1_dec_luma_size(struct hantro_ctx *ctx) +{ + return ctx->dst_fmt.width * ctx->dst_fmt.height * ctx->bit_depth / 8; +} + +static size_t rockchip_vpu981_av1_dec_chroma_size(struct hantro_ctx *ctx) +{ + size_t cr_offset = rockchip_vpu981_av1_dec_luma_size(ctx); + + return ALIGN((cr_offset * 3) / 2, 64); +} + +static void rockchip_vpu981_av1_dec_tiles_free(struct hantro_ctx *ctx) +{ + struct hantro_dev *vpu = ctx->dev; + struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec; + + if (av1_dec->db_data_col.cpu) + dma_free_coherent(vpu->dev, av1_dec->db_data_col.size, + av1_dec->db_data_col.cpu, + av1_dec->db_data_col.dma); + av1_dec->db_data_col.cpu = NULL; + + if (av1_dec->db_ctrl_col.cpu) + dma_free_coherent(vpu->dev, av1_dec->db_ctrl_col.size, + av1_dec->db_ctrl_col.cpu, + av1_dec->db_ctrl_col.dma); + av1_dec->db_ctrl_col.cpu = NULL; + + if (av1_dec->cdef_col.cpu) + dma_free_coherent(vpu->dev, av1_dec->cdef_col.size, + av1_dec->cdef_col.cpu, av1_dec->cdef_col.dma); + av1_dec->cdef_col.cpu = NULL; + + if (av1_dec->sr_col.cpu) + dma_free_coherent(vpu->dev, av1_dec->sr_col.size, + av1_dec->sr_col.cpu, av1_dec->sr_col.dma); + av1_dec->sr_col.cpu = NULL; + + if (av1_dec->lr_col.cpu) + dma_free_coherent(vpu->dev, av1_dec->lr_col.size, + av1_dec->lr_col.cpu, av1_dec->lr_col.dma); + av1_dec->lr_col.cpu = NULL; +} + +static int rockchip_vpu981_av1_dec_tiles_reallocate(struct hantro_ctx *ctx) +{ + struct hantro_dev *vpu = ctx->dev; + struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec; + struct hantro_av1_dec_ctrls *ctrls = &av1_dec->ctrls; + unsigned int num_tile_cols = 1 << ctrls->tile_group_entry->tile_col; + unsigned int height = ALIGN(ctrls->frame->frame_height_minus_1 + 1, 64); + unsigned int height_in_sb = height / 64; + unsigned int stripe_num = ((height + 8) + 63) / 64; + size_t size; + + if (av1_dec->db_data_col.size >= + ALIGN(height * 12 * ctx->bit_depth / 8, 128) * num_tile_cols) + return 0; + + rockchip_vpu981_av1_dec_tiles_free(ctx); + + size = ALIGN(height * 12 * ctx->bit_depth / 8, 128) * num_tile_cols; + av1_dec->db_data_col.cpu = dma_alloc_coherent(vpu->dev, size, + &av1_dec->db_data_col.dma, + GFP_KERNEL); + if (!av1_dec->db_data_col.cpu) + goto buffer_allocation_error; + av1_dec->db_data_col.size = size; + + size = ALIGN(height * 2 * 16 / 4, 128) * num_tile_cols; + av1_dec->db_ctrl_col.cpu = dma_alloc_coherent(vpu->dev, size, + &av1_dec->db_ctrl_col.dma, + GFP_KERNEL); + if (!av1_dec->db_ctrl_col.cpu) + goto buffer_allocation_error; + av1_dec->db_ctrl_col.size = size; + + size = ALIGN(height_in_sb * 44 * ctx->bit_depth * 16 / 8, 128) * num_tile_cols; + av1_dec->cdef_col.cpu = dma_alloc_coherent(vpu->dev, size, + &av1_dec->cdef_col.dma, + GFP_KERNEL); + if (!av1_dec->cdef_col.cpu) + goto buffer_allocation_error; + av1_dec->cdef_col.size = size; + + size = ALIGN(height_in_sb * (3040 + 1280), 128) * num_tile_cols; + av1_dec->sr_col.cpu = dma_alloc_coherent(vpu->dev, size, + &av1_dec->sr_col.dma, + GFP_KERNEL); + if (!av1_dec->sr_col.cpu) + goto buffer_allocation_error; + av1_dec->sr_col.size = size; + + size = ALIGN(stripe_num * 1536 * ctx->bit_depth / 8, 128) * num_tile_cols; + av1_dec->lr_col.cpu = dma_alloc_coherent(vpu->dev, size, + &av1_dec->lr_col.dma, + GFP_KERNEL); + if (!av1_dec->lr_col.cpu) + goto buffer_allocation_error; + av1_dec->lr_col.size = size; + + av1_dec->num_tile_cols_allocated = num_tile_cols; + return 0; + +buffer_allocation_error: + rockchip_vpu981_av1_dec_tiles_free(ctx); + return -ENOMEM; +} + +void rockchip_vpu981_av1_dec_exit(struct hantro_ctx *ctx) +{ + struct hantro_dev *vpu = ctx->dev; + struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec; + + if (av1_dec->global_model.cpu) + dma_free_coherent(vpu->dev, av1_dec->global_model.size, + av1_dec->global_model.cpu, + av1_dec->global_model.dma); + av1_dec->global_model.cpu = NULL; + + if (av1_dec->tile_info.cpu) + dma_free_coherent(vpu->dev, av1_dec->tile_info.size, + av1_dec->tile_info.cpu, + av1_dec->tile_info.dma); + av1_dec->tile_info.cpu = NULL; + + if (av1_dec->film_grain.cpu) + dma_free_coherent(vpu->dev, av1_dec->film_grain.size, + av1_dec->film_grain.cpu, + av1_dec->film_grain.dma); + av1_dec->film_grain.cpu = NULL; + + if (av1_dec->prob_tbl.cpu) + dma_free_coherent(vpu->dev, av1_dec->prob_tbl.size, + av1_dec->prob_tbl.cpu, av1_dec->prob_tbl.dma); + av1_dec->prob_tbl.cpu = NULL; + + if (av1_dec->prob_tbl_out.cpu) + dma_free_coherent(vpu->dev, av1_dec->prob_tbl_out.size, + av1_dec->prob_tbl_out.cpu, + av1_dec->prob_tbl_out.dma); + av1_dec->prob_tbl_out.cpu = NULL; + + if (av1_dec->tile_buf.cpu) + dma_free_coherent(vpu->dev, av1_dec->tile_buf.size, + av1_dec->tile_buf.cpu, av1_dec->tile_buf.dma); + av1_dec->tile_buf.cpu = NULL; + + rockchip_vpu981_av1_dec_tiles_free(ctx); +} + +int rockchip_vpu981_av1_dec_init(struct hantro_ctx *ctx) +{ + struct hantro_dev *vpu = ctx->dev; + struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec; + + memset(av1_dec, 0, sizeof(*av1_dec)); + + av1_dec->global_model.cpu = dma_alloc_coherent(vpu->dev, GLOBAL_MODEL_SIZE, + &av1_dec->global_model.dma, + GFP_KERNEL); + if (!av1_dec->global_model.cpu) + return -ENOMEM; + av1_dec->global_model.size = GLOBAL_MODEL_SIZE; + + av1_dec->tile_info.cpu = dma_alloc_coherent(vpu->dev, AV1_MAX_TILES, + &av1_dec->tile_info.dma, + GFP_KERNEL); + if (!av1_dec->tile_info.cpu) + return -ENOMEM; + av1_dec->tile_info.size = AV1_MAX_TILES; + + av1_dec->film_grain.cpu = dma_alloc_coherent(vpu->dev, + ALIGN(sizeof(struct rockchip_av1_film_grain), 2048), + &av1_dec->film_grain.dma, + GFP_KERNEL); + if (!av1_dec->film_grain.cpu) + return -ENOMEM; + av1_dec->film_grain.size = ALIGN(sizeof(struct rockchip_av1_film_grain), 2048); + + av1_dec->prob_tbl.cpu = dma_alloc_coherent(vpu->dev, + ALIGN(sizeof(struct av1cdfs), 2048), + &av1_dec->prob_tbl.dma, + GFP_KERNEL); + if (!av1_dec->prob_tbl.cpu) + return -ENOMEM; + av1_dec->prob_tbl.size = ALIGN(sizeof(struct av1cdfs), 2048); + + av1_dec->prob_tbl_out.cpu = dma_alloc_coherent(vpu->dev, + ALIGN(sizeof(struct av1cdfs), 2048), + &av1_dec->prob_tbl_out.dma, + GFP_KERNEL); + if (!av1_dec->prob_tbl_out.cpu) + return -ENOMEM; + av1_dec->prob_tbl_out.size = ALIGN(sizeof(struct av1cdfs), 2048); + av1_dec->cdfs = &av1_dec->default_cdfs; + av1_dec->cdfs_ndvc = &av1_dec->default_cdfs_ndvc; + + rockchip_av1_set_default_cdfs(av1_dec->cdfs, av1_dec->cdfs_ndvc); + + av1_dec->tile_buf.cpu = dma_alloc_coherent(vpu->dev, + AV1_TILE_SIZE, + &av1_dec->tile_buf.dma, + GFP_KERNEL); + if (!av1_dec->tile_buf.cpu) + return -ENOMEM; + av1_dec->tile_buf.size = AV1_TILE_SIZE; + + return 0; +} + +static int rockchip_vpu981_av1_dec_prepare_run(struct hantro_ctx *ctx) +{ + struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec; + struct hantro_av1_dec_ctrls *ctrls = &av1_dec->ctrls; + + ctrls->sequence = hantro_get_ctrl(ctx, V4L2_CID_STATELESS_AV1_SEQUENCE); + if (WARN_ON(!ctrls->sequence)) + return -EINVAL; + + ctrls->tile_group_entry = + hantro_get_ctrl(ctx, V4L2_CID_STATELESS_AV1_TILE_GROUP_ENTRY); + if (WARN_ON(!ctrls->tile_group_entry)) + return -EINVAL; + + ctrls->frame = hantro_get_ctrl(ctx, V4L2_CID_STATELESS_AV1_FRAME); + if (WARN_ON(!ctrls->frame)) + return -EINVAL; + + ctrls->film_grain = + hantro_get_ctrl(ctx, V4L2_CID_STATELESS_AV1_FILM_GRAIN); + + return rockchip_vpu981_av1_dec_tiles_reallocate(ctx); +} + +static inline int rockchip_vpu981_av1_dec_get_msb(u32 n) +{ + if (n == 0) + return 0; + return 31 ^ __builtin_clz(n); +} + +static short rockchip_vpu981_av1_dec_resolve_divisor_32(u32 d, short *shift) +{ + int f; + u64 e; + + *shift = rockchip_vpu981_av1_dec_get_msb(d); + /* e is obtained from D after resetting the most significant 1 bit. */ + e = d - ((u32)1 << *shift); + /* Get the most significant DIV_LUT_BITS (8) bits of e into f */ + if (*shift > DIV_LUT_BITS) + f = AV1_DIV_ROUND_UP_POW2(e, *shift - DIV_LUT_BITS); + else + f = e << (DIV_LUT_BITS - *shift); + if (f > DIV_LUT_NUM) + return -1; + *shift += DIV_LUT_PREC_BITS; + /* Use f as lookup into the precomputed table of multipliers */ + return div_lut[f]; +} + +static void +rockchip_vpu981_av1_dec_get_shear_params(const u32 *params, s64 *alpha, + s64 *beta, s64 *gamma, s64 *delta) +{ + const int *mat = params; + short shift; + short y; + long long gv, dv; + + if (mat[2] <= 0) + return; + + *alpha = clamp_val(mat[2] - (1 << WARPEDMODEL_PREC_BITS), S16_MIN, S16_MAX); + *beta = clamp_val(mat[3], S16_MIN, S16_MAX); + + y = rockchip_vpu981_av1_dec_resolve_divisor_32(abs(mat[2]), &shift) * (mat[2] < 0 ? -1 : 1); + + gv = ((long long)mat[4] * (1 << WARPEDMODEL_PREC_BITS)) * y; + + *gamma = clamp_val((int)AV1_DIV_ROUND_UP_POW2_SIGNED(gv, shift), S16_MIN, S16_MAX); + + dv = ((long long)mat[3] * mat[4]) * y; + *delta = clamp_val(mat[5] - + (int)AV1_DIV_ROUND_UP_POW2_SIGNED(dv, shift) - (1 << WARPEDMODEL_PREC_BITS), + S16_MIN, S16_MAX); + + *alpha = AV1_DIV_ROUND_UP_POW2_SIGNED(*alpha, WARP_PARAM_REDUCE_BITS) + * (1 << WARP_PARAM_REDUCE_BITS); + *beta = AV1_DIV_ROUND_UP_POW2_SIGNED(*beta, WARP_PARAM_REDUCE_BITS) + * (1 << WARP_PARAM_REDUCE_BITS); + *gamma = AV1_DIV_ROUND_UP_POW2_SIGNED(*gamma, WARP_PARAM_REDUCE_BITS) + * (1 << WARP_PARAM_REDUCE_BITS); + *delta = AV1_DIV_ROUND_UP_POW2_SIGNED(*delta, WARP_PARAM_REDUCE_BITS) + * (1 << WARP_PARAM_REDUCE_BITS); +} + +static void rockchip_vpu981_av1_dec_set_global_model(struct hantro_ctx *ctx) +{ + struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec; + struct hantro_av1_dec_ctrls *ctrls = &av1_dec->ctrls; + const struct v4l2_ctrl_av1_frame *frame = ctrls->frame; + const struct v4l2_av1_global_motion *gm = &frame->global_motion; + u8 *dst = av1_dec->global_model.cpu; + struct hantro_dev *vpu = ctx->dev; + int ref_frame, i; + + memset(dst, 0, GLOBAL_MODEL_SIZE); + for (ref_frame = 0; ref_frame < V4L2_AV1_REFS_PER_FRAME; ++ref_frame) { + s64 alpha = 0, beta = 0, gamma = 0, delta = 0; + + for (i = 0; i < 6; ++i) { + if (i == 2) + *(s32 *)dst = + gm->params[V4L2_AV1_REF_LAST_FRAME + ref_frame][3]; + else if (i == 3) + *(s32 *)dst = + gm->params[V4L2_AV1_REF_LAST_FRAME + ref_frame][2]; + else + *(s32 *)dst = + gm->params[V4L2_AV1_REF_LAST_FRAME + ref_frame][i]; + dst += 4; + } + + if (gm->type[V4L2_AV1_REF_LAST_FRAME + ref_frame] <= V4L2_AV1_WARP_MODEL_AFFINE) + rockchip_vpu981_av1_dec_get_shear_params(&gm->params[V4L2_AV1_REF_LAST_FRAME + ref_frame][0], + &alpha, &beta, &gamma, &delta); + + *(s16 *)dst = alpha; + dst += 2; + *(s16 *)dst = beta; + dst += 2; + *(s16 *)dst = gamma; + dst += 2; + *(s16 *)dst = delta; + dst += 2; + } + + hantro_write_addr(vpu, AV1_GLOBAL_MODEL, av1_dec->global_model.dma); +} + +static int rockchip_vpu981_av1_tile_log2(int target) +{ + int k; + + /* + * returns the smallest value for k such that 1 << k is greater + * than or equal to target + */ + for (k = 0; (1 << k) < target; k++); + + return k; +} + +static void rockchip_vpu981_av1_dec_set_tile_info(struct hantro_ctx *ctx) +{ + struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec; + struct hantro_av1_dec_ctrls *ctrls = &av1_dec->ctrls; + const struct v4l2_av1_tile_info *tile_info = &ctrls->frame->tile_info; + const struct v4l2_ctrl_av1_tile_group_entry *group_entry = + ctrls->tile_group_entry; + int context_update_y = + tile_info->context_update_tile_id / tile_info->tile_cols; + int context_update_x = + tile_info->context_update_tile_id % tile_info->tile_cols; + int context_update_tile_id = + context_update_x * tile_info->tile_rows + context_update_y; + u8 *dst = av1_dec->tile_info.cpu; + struct hantro_dev *vpu = ctx->dev; + int tile0, tile1; + + memset(dst, 0, av1_dec->tile_info.size); + + for (tile0 = 0; tile0 < tile_info->tile_cols; tile0++) { + for (tile1 = 0; tile1 < tile_info->tile_rows; tile1++) { + int tile_id = tile1 * tile_info->tile_cols + tile0; + u32 start, end; + u32 y0 = + tile_info->height_in_sbs_minus_1[tile1] + 1; + u32 x0 = tile_info->width_in_sbs_minus_1[tile0] + 1; + + /* tile size in SB units (width,height) */ + *dst++ = x0; + *dst++ = 0; + *dst++ = 0; + *dst++ = 0; + *dst++ = y0; + *dst++ = 0; + *dst++ = 0; + *dst++ = 0; + + /* tile start position */ + start = group_entry[tile_id].tile_offset - group_entry[0].tile_offset; + *dst++ = start & 255; + *dst++ = (start >> 8) & 255; + *dst++ = (start >> 16) & 255; + *dst++ = (start >> 24) & 255; + + /* number of bytes in tile data */ + end = start + group_entry[tile_id].tile_size; + *dst++ = end & 255; + *dst++ = (end >> 8) & 255; + *dst++ = (end >> 16) & 255; + *dst++ = (end >> 24) & 255; + } + } + + hantro_reg_write(vpu, &av1_multicore_expect_context_update, !!(context_update_x == 0)); + hantro_reg_write(vpu, &av1_tile_enable, + !!((tile_info->tile_cols > 1) || (tile_info->tile_rows > 1))); + hantro_reg_write(vpu, &av1_num_tile_cols_8k, tile_info->tile_cols); + hantro_reg_write(vpu, &av1_num_tile_rows_8k, tile_info->tile_rows); + hantro_reg_write(vpu, &av1_context_update_tile_id, context_update_tile_id); + hantro_reg_write(vpu, &av1_tile_transpose, 1); + if (rockchip_vpu981_av1_tile_log2(tile_info->tile_cols) || + rockchip_vpu981_av1_tile_log2(tile_info->tile_rows)) + hantro_reg_write(vpu, &av1_dec_tile_size_mag, tile_info->tile_size_bytes - 1); + else + hantro_reg_write(vpu, &av1_dec_tile_size_mag, 3); + + hantro_write_addr(vpu, AV1_TILE_BASE, av1_dec->tile_info.dma); +} + +static int rockchip_vpu981_av1_dec_get_dist(struct hantro_ctx *ctx, + int a, int b) +{ + struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec; + struct hantro_av1_dec_ctrls *ctrls = &av1_dec->ctrls; + int bits = ctrls->sequence->order_hint_bits - 1; + int diff, m; + + if (!ctrls->sequence->order_hint_bits) + return 0; + + diff = a - b; + m = 1 << bits; + diff = (diff & (m - 1)) - (diff & m); + + return diff; +} + +static void rockchip_vpu981_av1_dec_set_frame_sign_bias(struct hantro_ctx *ctx) +{ + struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec; + struct hantro_av1_dec_ctrls *ctrls = &av1_dec->ctrls; + const struct v4l2_ctrl_av1_frame *frame = ctrls->frame; + const struct v4l2_ctrl_av1_sequence *sequence = ctrls->sequence; + int i; + + if (!sequence->order_hint_bits || IS_INTRA(frame->frame_type)) { + for (i = 0; i < V4L2_AV1_TOTAL_REFS_PER_FRAME; i++) + av1_dec->ref_frame_sign_bias[i] = 0; + + return; + } + // Identify the nearest forward and backward references. + for (i = 0; i < V4L2_AV1_TOTAL_REFS_PER_FRAME - 1; i++) { + if (rockchip_vpu981_get_frame_index(ctx, i) >= 0) { + int rel_off = + rockchip_vpu981_av1_dec_get_dist(ctx, + rockchip_vpu981_get_order_hint(ctx, i), + frame->order_hint); + av1_dec->ref_frame_sign_bias[i + 1] = (rel_off <= 0) ? 0 : 1; + } + } +} + +static bool +rockchip_vpu981_av1_dec_set_ref(struct hantro_ctx *ctx, int ref, int idx, + int width, int height) +{ + struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec; + struct hantro_av1_dec_ctrls *ctrls = &av1_dec->ctrls; + const struct v4l2_ctrl_av1_frame *frame = ctrls->frame; + struct hantro_dev *vpu = ctx->dev; + struct hantro_decoded_buffer *dst; + dma_addr_t luma_addr, chroma_addr, mv_addr = 0; + size_t cr_offset = rockchip_vpu981_av1_dec_luma_size(ctx); + size_t mv_offset = rockchip_vpu981_av1_dec_chroma_size(ctx); + int cur_width = frame->frame_width_minus_1 + 1; + int cur_height = frame->frame_height_minus_1 + 1; + int scale_width = + ((width << AV1_REF_SCALE_SHIFT) + cur_width / 2) / cur_width; + int scale_height = + ((height << AV1_REF_SCALE_SHIFT) + cur_height / 2) / cur_height; + + switch (ref) { + case 0: + hantro_reg_write(vpu, &av1_ref0_height, height); + hantro_reg_write(vpu, &av1_ref0_width, width); + hantro_reg_write(vpu, &av1_ref0_ver_scale, scale_width); + hantro_reg_write(vpu, &av1_ref0_hor_scale, scale_height); + break; + case 1: + hantro_reg_write(vpu, &av1_ref1_height, height); + hantro_reg_write(vpu, &av1_ref1_width, width); + hantro_reg_write(vpu, &av1_ref1_ver_scale, scale_width); + hantro_reg_write(vpu, &av1_ref1_hor_scale, scale_height); + break; + case 2: + hantro_reg_write(vpu, &av1_ref2_height, height); + hantro_reg_write(vpu, &av1_ref2_width, width); + hantro_reg_write(vpu, &av1_ref2_ver_scale, scale_width); + hantro_reg_write(vpu, &av1_ref2_hor_scale, scale_height); + break; + case 3: + hantro_reg_write(vpu, &av1_ref3_height, height); + hantro_reg_write(vpu, &av1_ref3_width, width); + hantro_reg_write(vpu, &av1_ref3_ver_scale, scale_width); + hantro_reg_write(vpu, &av1_ref3_hor_scale, scale_height); + break; + case 4: + hantro_reg_write(vpu, &av1_ref4_height, height); + hantro_reg_write(vpu, &av1_ref4_width, width); + hantro_reg_write(vpu, &av1_ref4_ver_scale, scale_width); + hantro_reg_write(vpu, &av1_ref4_hor_scale, scale_height); + break; + case 5: + hantro_reg_write(vpu, &av1_ref5_height, height); + hantro_reg_write(vpu, &av1_ref5_width, width); + hantro_reg_write(vpu, &av1_ref5_ver_scale, scale_width); + hantro_reg_write(vpu, &av1_ref5_hor_scale, scale_height); + break; + case 6: + hantro_reg_write(vpu, &av1_ref6_height, height); + hantro_reg_write(vpu, &av1_ref6_width, width); + hantro_reg_write(vpu, &av1_ref6_ver_scale, scale_width); + hantro_reg_write(vpu, &av1_ref6_hor_scale, scale_height); + break; + default: + pr_warn("AV1 invalid reference frame index\n"); + } + + dst = vb2_to_hantro_decoded_buf(&av1_dec->frame_refs[idx].vb2_ref->vb2_buf); + luma_addr = hantro_get_dec_buf_addr(ctx, &dst->base.vb.vb2_buf); + chroma_addr = luma_addr + cr_offset; + mv_addr = luma_addr + mv_offset; + + hantro_write_addr(vpu, AV1_REFERENCE_Y(ref), luma_addr); + hantro_write_addr(vpu, AV1_REFERENCE_CB(ref), chroma_addr); + hantro_write_addr(vpu, AV1_REFERENCE_MV(ref), mv_addr); + + return (scale_width != (1 << AV1_REF_SCALE_SHIFT)) || + (scale_height != (1 << AV1_REF_SCALE_SHIFT)); +} + +static void rockchip_vpu981_av1_dec_set_sign_bias(struct hantro_ctx *ctx, + int ref, int val) +{ + struct hantro_dev *vpu = ctx->dev; + + switch (ref) { + case 0: + hantro_reg_write(vpu, &av1_ref0_sign_bias, val); + break; + case 1: + hantro_reg_write(vpu, &av1_ref1_sign_bias, val); + break; + case 2: + hantro_reg_write(vpu, &av1_ref2_sign_bias, val); + break; + case 3: + hantro_reg_write(vpu, &av1_ref3_sign_bias, val); + break; + case 4: + hantro_reg_write(vpu, &av1_ref4_sign_bias, val); + break; + case 5: + hantro_reg_write(vpu, &av1_ref5_sign_bias, val); + break; + case 6: + hantro_reg_write(vpu, &av1_ref6_sign_bias, val); + break; + default: + pr_warn("AV1 invalid sign bias index\n"); + break; + } +} + +static void rockchip_vpu981_av1_dec_set_segmentation(struct hantro_ctx *ctx) +{ + struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec; + struct hantro_av1_dec_ctrls *ctrls = &av1_dec->ctrls; + const struct v4l2_ctrl_av1_frame *frame = ctrls->frame; + const struct v4l2_av1_segmentation *seg = &frame->segmentation; + u32 segval[V4L2_AV1_MAX_SEGMENTS][V4L2_AV1_SEG_LVL_MAX] = { 0 }; + struct hantro_dev *vpu = ctx->dev; + u8 segsign = 0, preskip_segid = 0, last_active_seg = 0, i, j; + + if (!!(seg->flags & V4L2_AV1_SEGMENTATION_FLAG_ENABLED) && + frame->primary_ref_frame < V4L2_AV1_REFS_PER_FRAME) { + int idx = rockchip_vpu981_get_frame_index(ctx, frame->primary_ref_frame); + + if (idx >= 0) { + dma_addr_t luma_addr, mv_addr = 0; + struct hantro_decoded_buffer *seg; + size_t mv_offset = rockchip_vpu981_av1_dec_chroma_size(ctx); + + seg = vb2_to_hantro_decoded_buf(&av1_dec->frame_refs[idx].vb2_ref->vb2_buf); + luma_addr = hantro_get_dec_buf_addr(ctx, &seg->base.vb.vb2_buf); + mv_addr = luma_addr + mv_offset; + + hantro_write_addr(vpu, AV1_SEGMENTATION, mv_addr); + hantro_reg_write(vpu, &av1_use_temporal3_mvs, 1); + } + } + + hantro_reg_write(vpu, &av1_segment_temp_upd_e, + !!(seg->flags & V4L2_AV1_SEGMENTATION_FLAG_TEMPORAL_UPDATE)); + hantro_reg_write(vpu, &av1_segment_upd_e, + !!(seg->flags & V4L2_AV1_SEGMENTATION_FLAG_UPDATE_MAP)); + hantro_reg_write(vpu, &av1_segment_e, + !!(seg->flags & V4L2_AV1_SEGMENTATION_FLAG_ENABLED)); + + hantro_reg_write(vpu, &av1_error_resilient, + !!(frame->flags & V4L2_AV1_FRAME_FLAG_ERROR_RESILIENT_MODE)); + + if (IS_INTRA(frame->frame_type) || + !!(frame->flags & V4L2_AV1_FRAME_FLAG_ERROR_RESILIENT_MODE)) { + hantro_reg_write(vpu, &av1_use_temporal3_mvs, 0); + } + + if (seg->flags & V4L2_AV1_SEGMENTATION_FLAG_ENABLED) { + int s; + + for (s = 0; s < V4L2_AV1_MAX_SEGMENTS; s++) { + if (seg->feature_enabled[s] & + V4L2_AV1_SEGMENT_FEATURE_ENABLED(V4L2_AV1_SEG_LVL_ALT_Q)) { + segval[s][V4L2_AV1_SEG_LVL_ALT_Q] = + clamp(abs(seg->feature_data[s][V4L2_AV1_SEG_LVL_ALT_Q]), + 0, 255); + segsign |= + (seg->feature_data[s][V4L2_AV1_SEG_LVL_ALT_Q] < 0) << s; + } + + if (seg->feature_enabled[s] & + V4L2_AV1_SEGMENT_FEATURE_ENABLED(V4L2_AV1_SEG_LVL_ALT_LF_Y_V)) + segval[s][V4L2_AV1_SEG_LVL_ALT_LF_Y_V] = + clamp(abs(seg->feature_data[s][V4L2_AV1_SEG_LVL_ALT_LF_Y_V]), + -63, 63); + + if (seg->feature_enabled[s] & + V4L2_AV1_SEGMENT_FEATURE_ENABLED(V4L2_AV1_SEG_LVL_ALT_LF_Y_H)) + segval[s][V4L2_AV1_SEG_LVL_ALT_LF_Y_H] = + clamp(abs(seg->feature_data[s][V4L2_AV1_SEG_LVL_ALT_LF_Y_H]), + -63, 63); + + if (seg->feature_enabled[s] & + V4L2_AV1_SEGMENT_FEATURE_ENABLED(V4L2_AV1_SEG_LVL_ALT_LF_U)) + segval[s][V4L2_AV1_SEG_LVL_ALT_LF_U] = + clamp(abs(seg->feature_data[s][V4L2_AV1_SEG_LVL_ALT_LF_U]), + -63, 63); + + if (seg->feature_enabled[s] & + V4L2_AV1_SEGMENT_FEATURE_ENABLED(V4L2_AV1_SEG_LVL_ALT_LF_V)) + segval[s][V4L2_AV1_SEG_LVL_ALT_LF_V] = + clamp(abs(seg->feature_data[s][V4L2_AV1_SEG_LVL_ALT_LF_V]), + -63, 63); + + if (frame->frame_type && seg->feature_enabled[s] & + V4L2_AV1_SEGMENT_FEATURE_ENABLED(V4L2_AV1_SEG_LVL_REF_FRAME)) + segval[s][V4L2_AV1_SEG_LVL_REF_FRAME]++; + + if (seg->feature_enabled[s] & + V4L2_AV1_SEGMENT_FEATURE_ENABLED(V4L2_AV1_SEG_LVL_REF_SKIP)) + segval[s][V4L2_AV1_SEG_LVL_REF_SKIP] = 1; + + if (seg->feature_enabled[s] & + V4L2_AV1_SEGMENT_FEATURE_ENABLED(V4L2_AV1_SEG_LVL_REF_GLOBALMV)) + segval[s][V4L2_AV1_SEG_LVL_REF_GLOBALMV] = 1; + } + } + + for (i = 0; i < V4L2_AV1_MAX_SEGMENTS; i++) { + for (j = 0; j < V4L2_AV1_SEG_LVL_MAX; j++) { + if (seg->feature_enabled[i] + & V4L2_AV1_SEGMENT_FEATURE_ENABLED(j)) { + preskip_segid |= (j >= V4L2_AV1_SEG_LVL_REF_FRAME); + last_active_seg = max(i, last_active_seg); + } + } + } + + hantro_reg_write(vpu, &av1_last_active_seg, last_active_seg); + hantro_reg_write(vpu, &av1_preskip_segid, preskip_segid); + + hantro_reg_write(vpu, &av1_seg_quant_sign, segsign); + + /* Write QP, filter level, ref frame and skip for every segment */ + hantro_reg_write(vpu, &av1_quant_seg0, + segval[0][V4L2_AV1_SEG_LVL_ALT_Q]); + hantro_reg_write(vpu, &av1_filt_level_delta0_seg0, + segval[0][V4L2_AV1_SEG_LVL_ALT_LF_Y_V]); + hantro_reg_write(vpu, &av1_filt_level_delta1_seg0, + segval[0][V4L2_AV1_SEG_LVL_ALT_LF_Y_H]); + hantro_reg_write(vpu, &av1_filt_level_delta2_seg0, + segval[0][V4L2_AV1_SEG_LVL_ALT_LF_U]); + hantro_reg_write(vpu, &av1_filt_level_delta3_seg0, + segval[0][V4L2_AV1_SEG_LVL_ALT_LF_V]); + hantro_reg_write(vpu, &av1_refpic_seg0, + segval[0][V4L2_AV1_SEG_LVL_REF_FRAME]); + hantro_reg_write(vpu, &av1_skip_seg0, + segval[0][V4L2_AV1_SEG_LVL_REF_SKIP]); + hantro_reg_write(vpu, &av1_global_mv_seg0, + segval[0][V4L2_AV1_SEG_LVL_REF_GLOBALMV]); + + hantro_reg_write(vpu, &av1_quant_seg1, + segval[1][V4L2_AV1_SEG_LVL_ALT_Q]); + hantro_reg_write(vpu, &av1_filt_level_delta0_seg1, + segval[1][V4L2_AV1_SEG_LVL_ALT_LF_Y_V]); + hantro_reg_write(vpu, &av1_filt_level_delta1_seg1, + segval[1][V4L2_AV1_SEG_LVL_ALT_LF_Y_H]); + hantro_reg_write(vpu, &av1_filt_level_delta2_seg1, + segval[1][V4L2_AV1_SEG_LVL_ALT_LF_U]); + hantro_reg_write(vpu, &av1_filt_level_delta3_seg1, + segval[1][V4L2_AV1_SEG_LVL_ALT_LF_V]); + hantro_reg_write(vpu, &av1_refpic_seg1, + segval[1][V4L2_AV1_SEG_LVL_REF_FRAME]); + hantro_reg_write(vpu, &av1_skip_seg1, + segval[1][V4L2_AV1_SEG_LVL_REF_SKIP]); + hantro_reg_write(vpu, &av1_global_mv_seg1, + segval[1][V4L2_AV1_SEG_LVL_REF_GLOBALMV]); + + hantro_reg_write(vpu, &av1_quant_seg2, + segval[2][V4L2_AV1_SEG_LVL_ALT_Q]); + hantro_reg_write(vpu, &av1_filt_level_delta0_seg2, + segval[2][V4L2_AV1_SEG_LVL_ALT_LF_Y_V]); + hantro_reg_write(vpu, &av1_filt_level_delta1_seg2, + segval[2][V4L2_AV1_SEG_LVL_ALT_LF_Y_H]); + hantro_reg_write(vpu, &av1_filt_level_delta2_seg2, + segval[2][V4L2_AV1_SEG_LVL_ALT_LF_U]); + hantro_reg_write(vpu, &av1_filt_level_delta3_seg2, + segval[2][V4L2_AV1_SEG_LVL_ALT_LF_V]); + hantro_reg_write(vpu, &av1_refpic_seg2, + segval[2][V4L2_AV1_SEG_LVL_REF_FRAME]); + hantro_reg_write(vpu, &av1_skip_seg2, + segval[2][V4L2_AV1_SEG_LVL_REF_SKIP]); + hantro_reg_write(vpu, &av1_global_mv_seg2, + segval[2][V4L2_AV1_SEG_LVL_REF_GLOBALMV]); + + hantro_reg_write(vpu, &av1_quant_seg3, + segval[3][V4L2_AV1_SEG_LVL_ALT_Q]); + hantro_reg_write(vpu, &av1_filt_level_delta0_seg3, + segval[3][V4L2_AV1_SEG_LVL_ALT_LF_Y_V]); + hantro_reg_write(vpu, &av1_filt_level_delta1_seg3, + segval[3][V4L2_AV1_SEG_LVL_ALT_LF_Y_H]); + hantro_reg_write(vpu, &av1_filt_level_delta2_seg3, + segval[3][V4L2_AV1_SEG_LVL_ALT_LF_U]); + hantro_reg_write(vpu, &av1_filt_level_delta3_seg3, + segval[3][V4L2_AV1_SEG_LVL_ALT_LF_V]); + hantro_reg_write(vpu, &av1_refpic_seg3, + segval[3][V4L2_AV1_SEG_LVL_REF_FRAME]); + hantro_reg_write(vpu, &av1_skip_seg3, + segval[3][V4L2_AV1_SEG_LVL_REF_SKIP]); + hantro_reg_write(vpu, &av1_global_mv_seg3, + segval[3][V4L2_AV1_SEG_LVL_REF_GLOBALMV]); + + hantro_reg_write(vpu, &av1_quant_seg4, + segval[4][V4L2_AV1_SEG_LVL_ALT_Q]); + hantro_reg_write(vpu, &av1_filt_level_delta0_seg4, + segval[4][V4L2_AV1_SEG_LVL_ALT_LF_Y_V]); + hantro_reg_write(vpu, &av1_filt_level_delta1_seg4, + segval[4][V4L2_AV1_SEG_LVL_ALT_LF_Y_H]); + hantro_reg_write(vpu, &av1_filt_level_delta2_seg4, + segval[4][V4L2_AV1_SEG_LVL_ALT_LF_U]); + hantro_reg_write(vpu, &av1_filt_level_delta3_seg4, + segval[4][V4L2_AV1_SEG_LVL_ALT_LF_V]); + hantro_reg_write(vpu, &av1_refpic_seg4, + segval[4][V4L2_AV1_SEG_LVL_REF_FRAME]); + hantro_reg_write(vpu, &av1_skip_seg4, + segval[4][V4L2_AV1_SEG_LVL_REF_SKIP]); + hantro_reg_write(vpu, &av1_global_mv_seg4, + segval[4][V4L2_AV1_SEG_LVL_REF_GLOBALMV]); + + hantro_reg_write(vpu, &av1_quant_seg5, + segval[5][V4L2_AV1_SEG_LVL_ALT_Q]); + hantro_reg_write(vpu, &av1_filt_level_delta0_seg5, + segval[5][V4L2_AV1_SEG_LVL_ALT_LF_Y_V]); + hantro_reg_write(vpu, &av1_filt_level_delta1_seg5, + segval[5][V4L2_AV1_SEG_LVL_ALT_LF_Y_H]); + hantro_reg_write(vpu, &av1_filt_level_delta2_seg5, + segval[5][V4L2_AV1_SEG_LVL_ALT_LF_U]); + hantro_reg_write(vpu, &av1_filt_level_delta3_seg5, + segval[5][V4L2_AV1_SEG_LVL_ALT_LF_V]); + hantro_reg_write(vpu, &av1_refpic_seg5, + segval[5][V4L2_AV1_SEG_LVL_REF_FRAME]); + hantro_reg_write(vpu, &av1_skip_seg5, + segval[5][V4L2_AV1_SEG_LVL_REF_SKIP]); + hantro_reg_write(vpu, &av1_global_mv_seg5, + segval[5][V4L2_AV1_SEG_LVL_REF_GLOBALMV]); + + hantro_reg_write(vpu, &av1_quant_seg6, + segval[6][V4L2_AV1_SEG_LVL_ALT_Q]); + hantro_reg_write(vpu, &av1_filt_level_delta0_seg6, + segval[6][V4L2_AV1_SEG_LVL_ALT_LF_Y_V]); + hantro_reg_write(vpu, &av1_filt_level_delta1_seg6, + segval[6][V4L2_AV1_SEG_LVL_ALT_LF_Y_H]); + hantro_reg_write(vpu, &av1_filt_level_delta2_seg6, + segval[6][V4L2_AV1_SEG_LVL_ALT_LF_U]); + hantro_reg_write(vpu, &av1_filt_level_delta3_seg6, + segval[6][V4L2_AV1_SEG_LVL_ALT_LF_V]); + hantro_reg_write(vpu, &av1_refpic_seg6, + segval[6][V4L2_AV1_SEG_LVL_REF_FRAME]); + hantro_reg_write(vpu, &av1_skip_seg6, + segval[6][V4L2_AV1_SEG_LVL_REF_SKIP]); + hantro_reg_write(vpu, &av1_global_mv_seg6, + segval[6][V4L2_AV1_SEG_LVL_REF_GLOBALMV]); + + hantro_reg_write(vpu, &av1_quant_seg7, + segval[7][V4L2_AV1_SEG_LVL_ALT_Q]); + hantro_reg_write(vpu, &av1_filt_level_delta0_seg7, + segval[7][V4L2_AV1_SEG_LVL_ALT_LF_Y_V]); + hantro_reg_write(vpu, &av1_filt_level_delta1_seg7, + segval[7][V4L2_AV1_SEG_LVL_ALT_LF_Y_H]); + hantro_reg_write(vpu, &av1_filt_level_delta2_seg7, + segval[7][V4L2_AV1_SEG_LVL_ALT_LF_U]); + hantro_reg_write(vpu, &av1_filt_level_delta3_seg7, + segval[7][V4L2_AV1_SEG_LVL_ALT_LF_V]); + hantro_reg_write(vpu, &av1_refpic_seg7, + segval[7][V4L2_AV1_SEG_LVL_REF_FRAME]); + hantro_reg_write(vpu, &av1_skip_seg7, + segval[7][V4L2_AV1_SEG_LVL_REF_SKIP]); + hantro_reg_write(vpu, &av1_global_mv_seg7, + segval[7][V4L2_AV1_SEG_LVL_REF_GLOBALMV]); +} + +static bool rockchip_vpu981_av1_dec_is_lossless(struct hantro_ctx *ctx) +{ + struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec; + struct hantro_av1_dec_ctrls *ctrls = &av1_dec->ctrls; + const struct v4l2_ctrl_av1_frame *frame = ctrls->frame; + const struct v4l2_av1_segmentation *segmentation = &frame->segmentation; + const struct v4l2_av1_quantization *quantization = &frame->quantization; + int i; + + for (i = 0; i < V4L2_AV1_MAX_SEGMENTS; i++) { + int qindex = quantization->base_q_idx; + + if (segmentation->feature_enabled[i] & + V4L2_AV1_SEGMENT_FEATURE_ENABLED(V4L2_AV1_SEG_LVL_ALT_Q)) { + qindex += segmentation->feature_data[i][V4L2_AV1_SEG_LVL_ALT_Q]; + } + qindex = clamp(qindex, 0, 255); + + if (qindex || + quantization->delta_q_y_dc || + quantization->delta_q_u_dc || + quantization->delta_q_u_ac || + quantization->delta_q_v_dc || + quantization->delta_q_v_ac) + return false; + } + return true; +} + +static void rockchip_vpu981_av1_dec_set_loopfilter(struct hantro_ctx *ctx) +{ + struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec; + struct hantro_av1_dec_ctrls *ctrls = &av1_dec->ctrls; + const struct v4l2_ctrl_av1_frame *frame = ctrls->frame; + const struct v4l2_av1_loop_filter *loop_filter = &frame->loop_filter; + bool filtering_dis = (loop_filter->level[0] == 0) && (loop_filter->level[1] == 0); + struct hantro_dev *vpu = ctx->dev; + + hantro_reg_write(vpu, &av1_filtering_dis, filtering_dis); + hantro_reg_write(vpu, &av1_filt_level_base_gt32, loop_filter->level[0] > 32); + hantro_reg_write(vpu, &av1_filt_sharpness, loop_filter->sharpness); + + hantro_reg_write(vpu, &av1_filt_level0, loop_filter->level[0]); + hantro_reg_write(vpu, &av1_filt_level1, loop_filter->level[1]); + hantro_reg_write(vpu, &av1_filt_level2, loop_filter->level[2]); + hantro_reg_write(vpu, &av1_filt_level3, loop_filter->level[3]); + + if (loop_filter->flags & V4L2_AV1_LOOP_FILTER_FLAG_DELTA_ENABLED && + !rockchip_vpu981_av1_dec_is_lossless(ctx) && + !(frame->flags & V4L2_AV1_FRAME_FLAG_ALLOW_INTRABC)) { + hantro_reg_write(vpu, &av1_filt_ref_adj_0, + loop_filter->ref_deltas[0]); + hantro_reg_write(vpu, &av1_filt_ref_adj_1, + loop_filter->ref_deltas[1]); + hantro_reg_write(vpu, &av1_filt_ref_adj_2, + loop_filter->ref_deltas[2]); + hantro_reg_write(vpu, &av1_filt_ref_adj_3, + loop_filter->ref_deltas[3]); + hantro_reg_write(vpu, &av1_filt_ref_adj_4, + loop_filter->ref_deltas[4]); + hantro_reg_write(vpu, &av1_filt_ref_adj_5, + loop_filter->ref_deltas[5]); + hantro_reg_write(vpu, &av1_filt_ref_adj_6, + loop_filter->ref_deltas[6]); + hantro_reg_write(vpu, &av1_filt_ref_adj_7, + loop_filter->ref_deltas[7]); + hantro_reg_write(vpu, &av1_filt_mb_adj_0, + loop_filter->mode_deltas[0]); + hantro_reg_write(vpu, &av1_filt_mb_adj_1, + loop_filter->mode_deltas[1]); + } else { + hantro_reg_write(vpu, &av1_filt_ref_adj_0, 0); + hantro_reg_write(vpu, &av1_filt_ref_adj_1, 0); + hantro_reg_write(vpu, &av1_filt_ref_adj_2, 0); + hantro_reg_write(vpu, &av1_filt_ref_adj_3, 0); + hantro_reg_write(vpu, &av1_filt_ref_adj_4, 0); + hantro_reg_write(vpu, &av1_filt_ref_adj_5, 0); + hantro_reg_write(vpu, &av1_filt_ref_adj_6, 0); + hantro_reg_write(vpu, &av1_filt_ref_adj_7, 0); + hantro_reg_write(vpu, &av1_filt_mb_adj_0, 0); + hantro_reg_write(vpu, &av1_filt_mb_adj_1, 0); + } + + hantro_write_addr(vpu, AV1_DB_DATA_COL, av1_dec->db_data_col.dma); + hantro_write_addr(vpu, AV1_DB_CTRL_COL, av1_dec->db_ctrl_col.dma); +} + +static void rockchip_vpu981_av1_dec_update_prob(struct hantro_ctx *ctx) +{ + struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec; + struct hantro_av1_dec_ctrls *ctrls = &av1_dec->ctrls; + const struct v4l2_ctrl_av1_frame *frame = ctrls->frame; + bool frame_is_intra = IS_INTRA(frame->frame_type); + struct av1cdfs *out_cdfs = (struct av1cdfs *)av1_dec->prob_tbl_out.cpu; + int i; + + if (frame->flags & V4L2_AV1_FRAME_FLAG_DISABLE_FRAME_END_UPDATE_CDF) + return; + + for (i = 0; i < NUM_REF_FRAMES; i++) { + if (frame->refresh_frame_flags & BIT(i)) { + struct mvcdfs stored_mv_cdf; + + rockchip_av1_get_cdfs(ctx, i); + stored_mv_cdf = av1_dec->cdfs->mv_cdf; + *av1_dec->cdfs = *out_cdfs; + if (frame_is_intra) { + av1_dec->cdfs->mv_cdf = stored_mv_cdf; + *av1_dec->cdfs_ndvc = out_cdfs->mv_cdf; + } + rockchip_av1_store_cdfs(ctx, + frame->refresh_frame_flags); + break; + } + } +} + +void rockchip_vpu981_av1_dec_done(struct hantro_ctx *ctx) +{ + rockchip_vpu981_av1_dec_update_prob(ctx); +} + +static void rockchip_vpu981_av1_dec_set_prob(struct hantro_ctx *ctx) +{ + struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec; + struct hantro_av1_dec_ctrls *ctrls = &av1_dec->ctrls; + const struct v4l2_ctrl_av1_frame *frame = ctrls->frame; + const struct v4l2_av1_quantization *quantization = &frame->quantization; + struct hantro_dev *vpu = ctx->dev; + bool error_resilient_mode = + !!(frame->flags & V4L2_AV1_FRAME_FLAG_ERROR_RESILIENT_MODE); + bool frame_is_intra = IS_INTRA(frame->frame_type); + + if (error_resilient_mode || frame_is_intra || + frame->primary_ref_frame == AV1_PRIMARY_REF_NONE) { + av1_dec->cdfs = &av1_dec->default_cdfs; + av1_dec->cdfs_ndvc = &av1_dec->default_cdfs_ndvc; + rockchip_av1_default_coeff_probs(quantization->base_q_idx, + av1_dec->cdfs); + } else { + rockchip_av1_get_cdfs(ctx, frame->ref_frame_idx[frame->primary_ref_frame]); + } + rockchip_av1_store_cdfs(ctx, frame->refresh_frame_flags); + + memcpy(av1_dec->prob_tbl.cpu, av1_dec->cdfs, sizeof(struct av1cdfs)); + + if (frame_is_intra) { + int mv_offset = offsetof(struct av1cdfs, mv_cdf); + /* Overwrite MV context area with intrabc MV context */ + memcpy(av1_dec->prob_tbl.cpu + mv_offset, av1_dec->cdfs_ndvc, + sizeof(struct mvcdfs)); + } + + hantro_write_addr(vpu, AV1_PROP_TABLE_OUT, av1_dec->prob_tbl_out.dma); + hantro_write_addr(vpu, AV1_PROP_TABLE, av1_dec->prob_tbl.dma); +} + +static void +rockchip_vpu981_av1_dec_init_scaling_function(const u8 *values, const u8 *scaling, + u8 num_points, u8 *scaling_lut) +{ + int i, point; + + if (num_points == 0) { + memset(scaling_lut, 0, 256); + return; + } + + for (point = 0; point < num_points - 1; point++) { + int x; + s32 delta_y = scaling[point + 1] - scaling[point]; + s32 delta_x = values[point + 1] - values[point]; + s64 delta = + delta_x ? delta_y * ((65536 + (delta_x >> 1)) / + delta_x) : 0; + + for (x = 0; x < delta_x; x++) { + scaling_lut[values[point] + x] = + scaling[point] + + (s32)((x * delta + 32768) >> 16); + } + } + + for (i = values[num_points - 1]; i < 256; i++) + scaling_lut[i] = scaling[num_points - 1]; +} + +static void rockchip_vpu981_av1_dec_set_fgs(struct hantro_ctx *ctx) +{ + struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec; + struct hantro_av1_dec_ctrls *ctrls = &av1_dec->ctrls; + const struct v4l2_ctrl_av1_film_grain *film_grain = ctrls->film_grain; + struct rockchip_av1_film_grain *fgmem = av1_dec->film_grain.cpu; + struct hantro_dev *vpu = ctx->dev; + bool scaling_from_luma = + !!(film_grain->flags & V4L2_AV1_FILM_GRAIN_FLAG_CHROMA_SCALING_FROM_LUMA); + s32 (*ar_coeffs_y)[24]; + s32 (*ar_coeffs_cb)[25]; + s32 (*ar_coeffs_cr)[25]; + s32 (*luma_grain_block)[73][82]; + s32 (*cb_grain_block)[38][44]; + s32 (*cr_grain_block)[38][44]; + s32 ar_coeff_lag, ar_coeff_shift; + s32 grain_scale_shift, bitdepth; + s32 grain_center, grain_min, grain_max; + int i, j; + + hantro_reg_write(vpu, &av1_apply_grain, 0); + + if (!(film_grain->flags & V4L2_AV1_FILM_GRAIN_FLAG_APPLY_GRAIN)) { + hantro_reg_write(vpu, &av1_num_y_points_b, 0); + hantro_reg_write(vpu, &av1_num_cb_points_b, 0); + hantro_reg_write(vpu, &av1_num_cr_points_b, 0); + hantro_reg_write(vpu, &av1_scaling_shift, 0); + hantro_reg_write(vpu, &av1_cb_mult, 0); + hantro_reg_write(vpu, &av1_cb_luma_mult, 0); + hantro_reg_write(vpu, &av1_cb_offset, 0); + hantro_reg_write(vpu, &av1_cr_mult, 0); + hantro_reg_write(vpu, &av1_cr_luma_mult, 0); + hantro_reg_write(vpu, &av1_cr_offset, 0); + hantro_reg_write(vpu, &av1_overlap_flag, 0); + hantro_reg_write(vpu, &av1_clip_to_restricted_range, 0); + hantro_reg_write(vpu, &av1_chroma_scaling_from_luma, 0); + hantro_reg_write(vpu, &av1_random_seed, 0); + hantro_write_addr(vpu, AV1_FILM_GRAIN, 0); + return; + } + + ar_coeffs_y = kzalloc(sizeof(int32_t) * 24, GFP_KERNEL); + ar_coeffs_cb = kzalloc(sizeof(int32_t) * 25, GFP_KERNEL); + ar_coeffs_cr = kzalloc(sizeof(int32_t) * 25, GFP_KERNEL); + luma_grain_block = kzalloc(sizeof(int32_t) * 73 * 82, GFP_KERNEL); + cb_grain_block = kzalloc(sizeof(int32_t) * 38 * 44, GFP_KERNEL); + cr_grain_block = kzalloc(sizeof(int32_t) * 38 * 44, GFP_KERNEL); + + if (!ar_coeffs_y || !ar_coeffs_cb || !ar_coeffs_cr || + !luma_grain_block || !cb_grain_block || !cr_grain_block) { + pr_warn("Fail allocating memory for film grain parameters\n"); + goto alloc_fail; + } + + hantro_reg_write(vpu, &av1_apply_grain, 1); + + hantro_reg_write(vpu, &av1_num_y_points_b, + film_grain->num_y_points > 0); + hantro_reg_write(vpu, &av1_num_cb_points_b, + film_grain->num_cb_points > 0); + hantro_reg_write(vpu, &av1_num_cr_points_b, + film_grain->num_cr_points > 0); + hantro_reg_write(vpu, &av1_scaling_shift, + film_grain->grain_scaling_minus_8 + 8); + + if (!scaling_from_luma) { + hantro_reg_write(vpu, &av1_cb_mult, film_grain->cb_mult - 128); + hantro_reg_write(vpu, &av1_cb_luma_mult, film_grain->cb_luma_mult - 128); + hantro_reg_write(vpu, &av1_cb_offset, film_grain->cb_offset - 256); + hantro_reg_write(vpu, &av1_cr_mult, film_grain->cr_mult - 128); + hantro_reg_write(vpu, &av1_cr_luma_mult, film_grain->cr_luma_mult - 128); + hantro_reg_write(vpu, &av1_cr_offset, film_grain->cr_offset - 256); + } else { + hantro_reg_write(vpu, &av1_cb_mult, 0); + hantro_reg_write(vpu, &av1_cb_luma_mult, 0); + hantro_reg_write(vpu, &av1_cb_offset, 0); + hantro_reg_write(vpu, &av1_cr_mult, 0); + hantro_reg_write(vpu, &av1_cr_luma_mult, 0); + hantro_reg_write(vpu, &av1_cr_offset, 0); + } + + hantro_reg_write(vpu, &av1_overlap_flag, + !!(film_grain->flags & V4L2_AV1_FILM_GRAIN_FLAG_OVERLAP)); + hantro_reg_write(vpu, &av1_clip_to_restricted_range, + !!(film_grain->flags & V4L2_AV1_FILM_GRAIN_FLAG_CLIP_TO_RESTRICTED_RANGE)); + hantro_reg_write(vpu, &av1_chroma_scaling_from_luma, scaling_from_luma); + hantro_reg_write(vpu, &av1_random_seed, film_grain->grain_seed); + + rockchip_vpu981_av1_dec_init_scaling_function(film_grain->point_y_value, + film_grain->point_y_scaling, + film_grain->num_y_points, + fgmem->scaling_lut_y); + + if (film_grain->flags & + V4L2_AV1_FILM_GRAIN_FLAG_CHROMA_SCALING_FROM_LUMA) { + memcpy(fgmem->scaling_lut_cb, fgmem->scaling_lut_y, + sizeof(*fgmem->scaling_lut_y) * 256); + memcpy(fgmem->scaling_lut_cr, fgmem->scaling_lut_y, + sizeof(*fgmem->scaling_lut_y) * 256); + } else { + rockchip_vpu981_av1_dec_init_scaling_function + (film_grain->point_cb_value, film_grain->point_cb_scaling, + film_grain->num_cb_points, fgmem->scaling_lut_cb); + rockchip_vpu981_av1_dec_init_scaling_function + (film_grain->point_cr_value, film_grain->point_cr_scaling, + film_grain->num_cr_points, fgmem->scaling_lut_cr); + } + + for (i = 0; i < V4L2_AV1_AR_COEFFS_SIZE; i++) { + if (i < 24) + (*ar_coeffs_y)[i] = film_grain->ar_coeffs_y_plus_128[i] - 128; + (*ar_coeffs_cb)[i] = film_grain->ar_coeffs_cb_plus_128[i] - 128; + (*ar_coeffs_cr)[i] = film_grain->ar_coeffs_cr_plus_128[i] - 128; + } + + ar_coeff_lag = film_grain->ar_coeff_lag; + ar_coeff_shift = film_grain->ar_coeff_shift_minus_6 + 6; + grain_scale_shift = film_grain->grain_scale_shift; + bitdepth = ctx->bit_depth; + grain_center = 128 << (bitdepth - 8); + grain_min = 0 - grain_center; + grain_max = (256 << (bitdepth - 8)) - 1 - grain_center; + + rockchip_av1_generate_luma_grain_block(luma_grain_block, bitdepth, + film_grain->num_y_points, grain_scale_shift, + ar_coeff_lag, ar_coeffs_y, ar_coeff_shift, + grain_min, grain_max, film_grain->grain_seed); + + rockchip_av1_generate_chroma_grain_block(luma_grain_block, cb_grain_block, + cr_grain_block, bitdepth, + film_grain->num_y_points, + film_grain->num_cb_points, + film_grain->num_cr_points, + grain_scale_shift, ar_coeff_lag, ar_coeffs_cb, + ar_coeffs_cr, ar_coeff_shift, grain_min, + grain_max, + scaling_from_luma, + film_grain->grain_seed); + + for (i = 0; i < 64; i++) { + for (j = 0; j < 64; j++) + fgmem->cropped_luma_grain_block[i * 64 + j] = + (*luma_grain_block)[i + 9][j + 9]; + } + + for (i = 0; i < 32; i++) { + for (j = 0; j < 32; j++) { + fgmem->cropped_chroma_grain_block[i * 64 + 2 * j] = + (*cb_grain_block)[i + 6][j + 6]; + fgmem->cropped_chroma_grain_block[i * 64 + 2 * j + 1] = + (*cr_grain_block)[i + 6][j + 6]; + } + } + + hantro_write_addr(vpu, AV1_FILM_GRAIN, av1_dec->film_grain.dma); + +alloc_fail: + kfree(ar_coeffs_y); + kfree(ar_coeffs_cb); + kfree(ar_coeffs_cr); + kfree(luma_grain_block); + kfree(cb_grain_block); + kfree(cr_grain_block); +} + +static void rockchip_vpu981_av1_dec_set_cdef(struct hantro_ctx *ctx) +{ + struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec; + struct hantro_av1_dec_ctrls *ctrls = &av1_dec->ctrls; + const struct v4l2_ctrl_av1_frame *frame = ctrls->frame; + const struct v4l2_av1_cdef *cdef = &frame->cdef; + struct hantro_dev *vpu = ctx->dev; + u32 luma_pri_strength = 0; + u16 luma_sec_strength = 0; + u32 chroma_pri_strength = 0; + u16 chroma_sec_strength = 0; + int i; + + hantro_reg_write(vpu, &av1_cdef_bits, cdef->bits); + hantro_reg_write(vpu, &av1_cdef_damping, cdef->damping_minus_3); + + for (i = 0; i < BIT(cdef->bits); i++) { + luma_pri_strength |= cdef->y_pri_strength[i] << (i * 4); + if (cdef->y_sec_strength[i] == 4) + luma_sec_strength |= 3 << (i * 2); + else + luma_sec_strength |= cdef->y_sec_strength[i] << (i * 2); + + chroma_pri_strength |= cdef->uv_pri_strength[i] << (i * 4); + if (cdef->uv_sec_strength[i] == 4) + chroma_sec_strength |= 3 << (i * 2); + else + chroma_sec_strength |= cdef->uv_sec_strength[i] << (i * 2); + } + + hantro_reg_write(vpu, &av1_cdef_luma_primary_strength, + luma_pri_strength); + hantro_reg_write(vpu, &av1_cdef_luma_secondary_strength, + luma_sec_strength); + hantro_reg_write(vpu, &av1_cdef_chroma_primary_strength, + chroma_pri_strength); + hantro_reg_write(vpu, &av1_cdef_chroma_secondary_strength, + chroma_sec_strength); + + hantro_write_addr(vpu, AV1_CDEF_COL, av1_dec->cdef_col.dma); +} + +static void rockchip_vpu981_av1_dec_set_lr(struct hantro_ctx *ctx) +{ + struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec; + struct hantro_av1_dec_ctrls *ctrls = &av1_dec->ctrls; + const struct v4l2_ctrl_av1_frame *frame = ctrls->frame; + const struct v4l2_av1_loop_restoration *loop_restoration = + &frame->loop_restoration; + struct hantro_dev *vpu = ctx->dev; + u16 lr_type = 0, lr_unit_size = 0; + u8 restoration_unit_size[V4L2_AV1_NUM_PLANES_MAX] = { 3, 3, 3 }; + int i; + + if (loop_restoration->flags & V4L2_AV1_LOOP_RESTORATION_FLAG_USES_LR) { + restoration_unit_size[0] = 1 + loop_restoration->lr_unit_shift; + restoration_unit_size[1] = + 1 + loop_restoration->lr_unit_shift - loop_restoration->lr_uv_shift; + restoration_unit_size[2] = + 1 + loop_restoration->lr_unit_shift - loop_restoration->lr_uv_shift; + } + + for (i = 0; i < V4L2_AV1_NUM_PLANES_MAX; i++) { + lr_type |= + loop_restoration->frame_restoration_type[i] << (i * 2); + lr_unit_size |= restoration_unit_size[i] << (i * 2); + } + + hantro_reg_write(vpu, &av1_lr_type, lr_type); + hantro_reg_write(vpu, &av1_lr_unit_size, lr_unit_size); + hantro_write_addr(vpu, AV1_LR_COL, av1_dec->lr_col.dma); +} + +static void rockchip_vpu981_av1_dec_set_superres_params(struct hantro_ctx *ctx) +{ + struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec; + struct hantro_av1_dec_ctrls *ctrls = &av1_dec->ctrls; + const struct v4l2_ctrl_av1_frame *frame = ctrls->frame; + struct hantro_dev *vpu = ctx->dev; + u8 superres_scale_denominator = SCALE_NUMERATOR; + int superres_luma_step = RS_SCALE_SUBPEL_BITS; + int superres_chroma_step = RS_SCALE_SUBPEL_BITS; + int superres_luma_step_invra = RS_SCALE_SUBPEL_BITS; + int superres_chroma_step_invra = RS_SCALE_SUBPEL_BITS; + int superres_init_luma_subpel_x = 0; + int superres_init_chroma_subpel_x = 0; + int superres_is_scaled = 0; + int min_w = min_t(uint32_t, 16, frame->upscaled_width); + int upscaled_luma, downscaled_luma; + int downscaled_chroma, upscaled_chroma; + int step_luma, step_chroma; + int err_luma, err_chroma; + int initial_luma, initial_chroma; + int width = 0; + + if (frame->flags & V4L2_AV1_FRAME_FLAG_USE_SUPERRES) + superres_scale_denominator = frame->superres_denom; + + if (superres_scale_denominator <= SCALE_NUMERATOR) + goto set_regs; + + width = (frame->upscaled_width * SCALE_NUMERATOR + + (superres_scale_denominator / 2)) / superres_scale_denominator; + + if (width < min_w) + width = min_w; + + if (width == frame->upscaled_width) + goto set_regs; + + superres_is_scaled = 1; + upscaled_luma = frame->upscaled_width; + downscaled_luma = width; + downscaled_chroma = (downscaled_luma + 1) >> 1; + upscaled_chroma = (upscaled_luma + 1) >> 1; + step_luma = + ((downscaled_luma << RS_SCALE_SUBPEL_BITS) + + (upscaled_luma / 2)) / upscaled_luma; + step_chroma = + ((downscaled_chroma << RS_SCALE_SUBPEL_BITS) + + (upscaled_chroma / 2)) / upscaled_chroma; + err_luma = + (upscaled_luma * step_luma) + - (downscaled_luma << RS_SCALE_SUBPEL_BITS); + err_chroma = + (upscaled_chroma * step_chroma) + - (downscaled_chroma << RS_SCALE_SUBPEL_BITS); + initial_luma = + ((-((upscaled_luma - downscaled_luma) << (RS_SCALE_SUBPEL_BITS - 1)) + + upscaled_luma / 2) + / upscaled_luma + (1 << (RS_SCALE_EXTRA_BITS - 1)) - err_luma / 2) + & RS_SCALE_SUBPEL_MASK; + initial_chroma = + ((-((upscaled_chroma - downscaled_chroma) << (RS_SCALE_SUBPEL_BITS - 1)) + + upscaled_chroma / 2) + / upscaled_chroma + (1 << (RS_SCALE_EXTRA_BITS - 1)) - err_chroma / 2) + & RS_SCALE_SUBPEL_MASK; + superres_luma_step = step_luma; + superres_chroma_step = step_chroma; + superres_luma_step_invra = + ((upscaled_luma << RS_SCALE_SUBPEL_BITS) + (downscaled_luma / 2)) + / downscaled_luma; + superres_chroma_step_invra = + ((upscaled_chroma << RS_SCALE_SUBPEL_BITS) + (downscaled_chroma / 2)) + / downscaled_chroma; + superres_init_luma_subpel_x = initial_luma; + superres_init_chroma_subpel_x = initial_chroma; + +set_regs: + hantro_reg_write(vpu, &av1_superres_pic_width, frame->upscaled_width); + + if (frame->flags & V4L2_AV1_FRAME_FLAG_USE_SUPERRES) + hantro_reg_write(vpu, &av1_scale_denom_minus9, + frame->superres_denom - SUPERRES_SCALE_DENOMINATOR_MIN); + else + hantro_reg_write(vpu, &av1_scale_denom_minus9, frame->superres_denom); + + hantro_reg_write(vpu, &av1_superres_luma_step, superres_luma_step); + hantro_reg_write(vpu, &av1_superres_chroma_step, superres_chroma_step); + hantro_reg_write(vpu, &av1_superres_luma_step_invra, + superres_luma_step_invra); + hantro_reg_write(vpu, &av1_superres_chroma_step_invra, + superres_chroma_step_invra); + hantro_reg_write(vpu, &av1_superres_init_luma_subpel_x, + superres_init_luma_subpel_x); + hantro_reg_write(vpu, &av1_superres_init_chroma_subpel_x, + superres_init_chroma_subpel_x); + hantro_reg_write(vpu, &av1_superres_is_scaled, superres_is_scaled); + + hantro_write_addr(vpu, AV1_SR_COL, av1_dec->sr_col.dma); +} + +static void rockchip_vpu981_av1_dec_set_picture_dimensions(struct hantro_ctx *ctx) +{ + struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec; + struct hantro_av1_dec_ctrls *ctrls = &av1_dec->ctrls; + const struct v4l2_ctrl_av1_frame *frame = ctrls->frame; + struct hantro_dev *vpu = ctx->dev; + int pic_width_in_cbs = DIV_ROUND_UP(frame->frame_width_minus_1 + 1, 8); + int pic_height_in_cbs = DIV_ROUND_UP(frame->frame_height_minus_1 + 1, 8); + int pic_width_pad = ALIGN(frame->frame_width_minus_1 + 1, 8) + - (frame->frame_width_minus_1 + 1); + int pic_height_pad = ALIGN(frame->frame_height_minus_1 + 1, 8) + - (frame->frame_height_minus_1 + 1); + + hantro_reg_write(vpu, &av1_pic_width_in_cbs, pic_width_in_cbs); + hantro_reg_write(vpu, &av1_pic_height_in_cbs, pic_height_in_cbs); + hantro_reg_write(vpu, &av1_pic_width_pad, pic_width_pad); + hantro_reg_write(vpu, &av1_pic_height_pad, pic_height_pad); + + rockchip_vpu981_av1_dec_set_superres_params(ctx); +} + +static void rockchip_vpu981_av1_dec_set_other_frames(struct hantro_ctx *ctx) +{ + struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec; + struct hantro_av1_dec_ctrls *ctrls = &av1_dec->ctrls; + const struct v4l2_ctrl_av1_frame *frame = ctrls->frame; + struct hantro_dev *vpu = ctx->dev; + bool use_ref_frame_mvs = + !!(ctrls->frame->flags & V4L2_AV1_FRAME_FLAG_USE_REF_FRAME_MVS); + int cur_frame_offset = frame->order_hint; + int alt_frame_offset = 0; + int gld_frame_offset = 0; + int bwd_frame_offset = 0; + int alt2_frame_offset = 0; + int refs_selected[3] = { 0, 0, 0 }; + int cur_mi_cols = DIV_ROUND_UP(frame->frame_width_minus_1 + 1, 8); + int cur_mi_rows = DIV_ROUND_UP(frame->frame_height_minus_1 + 1, 8); + int cur_offset[V4L2_AV1_TOTAL_REFS_PER_FRAME - 1]; + int cur_roffset[V4L2_AV1_TOTAL_REFS_PER_FRAME - 1]; + int mf_types[3] = { 0, 0, 0 }; + int ref_stamp = 2; + int ref_ind = 0; + int rf, idx; + + alt_frame_offset = rockchip_vpu981_get_order_hint(ctx, ALT_BUF_IDX); + gld_frame_offset = rockchip_vpu981_get_order_hint(ctx, GLD_BUF_IDX); + bwd_frame_offset = rockchip_vpu981_get_order_hint(ctx, BWD_BUF_IDX); + alt2_frame_offset = rockchip_vpu981_get_order_hint(ctx, ALT2_BUF_IDX); + + idx = rockchip_vpu981_get_frame_index(ctx, LST_BUF_IDX); + if (idx >= 0) { + int alt_frame_offset_in_lst = + av1_dec->frame_refs[idx].order_hints[V4L2_AV1_REF_ALTREF_FRAME]; + bool is_lst_overlay = + (alt_frame_offset_in_lst == gld_frame_offset); + + if (!is_lst_overlay) { + int lst_mi_cols = av1_dec->frame_refs[idx].mi_cols; + int lst_mi_rows = av1_dec->frame_refs[idx].mi_rows; + bool lst_intra_only = + IS_INTRA(av1_dec->frame_refs[idx].frame_type); + + if (lst_mi_cols == cur_mi_cols && + lst_mi_rows == cur_mi_rows && !lst_intra_only) { + mf_types[ref_ind] = V4L2_AV1_REF_LAST_FRAME; + refs_selected[ref_ind++] = LST_BUF_IDX; + } + } + ref_stamp--; + } + + idx = rockchip_vpu981_get_frame_index(ctx, BWD_BUF_IDX); + if (rockchip_vpu981_av1_dec_get_dist(ctx, bwd_frame_offset, cur_frame_offset) > 0) { + int bwd_mi_cols = av1_dec->frame_refs[idx].mi_cols; + int bwd_mi_rows = av1_dec->frame_refs[idx].mi_rows; + bool bwd_intra_only = + IS_INTRA(av1_dec->frame_refs[idx].frame_type); + + if (bwd_mi_cols == cur_mi_cols && bwd_mi_rows == cur_mi_rows && + !bwd_intra_only) { + mf_types[ref_ind] = V4L2_AV1_REF_BWDREF_FRAME; + refs_selected[ref_ind++] = BWD_BUF_IDX; + ref_stamp--; + } + } + + idx = rockchip_vpu981_get_frame_index(ctx, ALT2_BUF_IDX); + if (rockchip_vpu981_av1_dec_get_dist(ctx, alt2_frame_offset, cur_frame_offset) > 0) { + int alt2_mi_cols = av1_dec->frame_refs[idx].mi_cols; + int alt2_mi_rows = av1_dec->frame_refs[idx].mi_rows; + bool alt2_intra_only = + IS_INTRA(av1_dec->frame_refs[idx].frame_type); + + if (alt2_mi_cols == cur_mi_cols && alt2_mi_rows == cur_mi_rows && + !alt2_intra_only) { + mf_types[ref_ind] = V4L2_AV1_REF_ALTREF2_FRAME; + refs_selected[ref_ind++] = ALT2_BUF_IDX; + ref_stamp--; + } + } + + idx = rockchip_vpu981_get_frame_index(ctx, ALT_BUF_IDX); + if (rockchip_vpu981_av1_dec_get_dist(ctx, alt_frame_offset, cur_frame_offset) > 0 && + ref_stamp >= 0) { + int alt_mi_cols = av1_dec->frame_refs[idx].mi_cols; + int alt_mi_rows = av1_dec->frame_refs[idx].mi_rows; + bool alt_intra_only = + IS_INTRA(av1_dec->frame_refs[idx].frame_type); + + if (alt_mi_cols == cur_mi_cols && alt_mi_rows == cur_mi_rows && + !alt_intra_only) { + mf_types[ref_ind] = V4L2_AV1_REF_ALTREF_FRAME; + refs_selected[ref_ind++] = ALT_BUF_IDX; + ref_stamp--; + } + } + + idx = rockchip_vpu981_get_frame_index(ctx, LST2_BUF_IDX); + if (idx >= 0 && ref_stamp >= 0) { + int lst2_mi_cols = av1_dec->frame_refs[idx].mi_cols; + int lst2_mi_rows = av1_dec->frame_refs[idx].mi_rows; + bool lst2_intra_only = + IS_INTRA(av1_dec->frame_refs[idx].frame_type); + + if (lst2_mi_cols == cur_mi_cols && lst2_mi_rows == cur_mi_rows && + !lst2_intra_only) { + mf_types[ref_ind] = V4L2_AV1_REF_LAST2_FRAME; + refs_selected[ref_ind++] = LST2_BUF_IDX; + ref_stamp--; + } + } + + for (rf = 0; rf < V4L2_AV1_TOTAL_REFS_PER_FRAME - 1; ++rf) { + idx = rockchip_vpu981_get_frame_index(ctx, rf); + if (idx >= 0) { + int rf_order_hint = rockchip_vpu981_get_order_hint(ctx, rf); + + cur_offset[rf] = + rockchip_vpu981_av1_dec_get_dist(ctx, cur_frame_offset, rf_order_hint); + cur_roffset[rf] = + rockchip_vpu981_av1_dec_get_dist(ctx, rf_order_hint, cur_frame_offset); + } else { + cur_offset[rf] = 0; + cur_roffset[rf] = 0; + } + } + + hantro_reg_write(vpu, &av1_use_temporal0_mvs, 0); + hantro_reg_write(vpu, &av1_use_temporal1_mvs, 0); + hantro_reg_write(vpu, &av1_use_temporal2_mvs, 0); + hantro_reg_write(vpu, &av1_use_temporal3_mvs, 0); + + hantro_reg_write(vpu, &av1_mf1_last_offset, 0); + hantro_reg_write(vpu, &av1_mf1_last2_offset, 0); + hantro_reg_write(vpu, &av1_mf1_last3_offset, 0); + hantro_reg_write(vpu, &av1_mf1_golden_offset, 0); + hantro_reg_write(vpu, &av1_mf1_bwdref_offset, 0); + hantro_reg_write(vpu, &av1_mf1_altref2_offset, 0); + hantro_reg_write(vpu, &av1_mf1_altref_offset, 0); + + if (use_ref_frame_mvs && ref_ind > 0 && + cur_offset[mf_types[0] - V4L2_AV1_REF_LAST_FRAME] <= MAX_FRAME_DISTANCE && + cur_offset[mf_types[0] - V4L2_AV1_REF_LAST_FRAME] >= -MAX_FRAME_DISTANCE) { + int rf = rockchip_vpu981_get_order_hint(ctx, refs_selected[0]); + int idx = rockchip_vpu981_get_frame_index(ctx, refs_selected[0]); + u32 *oh = av1_dec->frame_refs[idx].order_hints; + int val; + + hantro_reg_write(vpu, &av1_use_temporal0_mvs, 1); + + val = rockchip_vpu981_av1_dec_get_dist(ctx, rf, oh[V4L2_AV1_REF_LAST_FRAME]); + hantro_reg_write(vpu, &av1_mf1_last_offset, val); + + val = rockchip_vpu981_av1_dec_get_dist(ctx, rf, oh[V4L2_AV1_REF_LAST2_FRAME]); + hantro_reg_write(vpu, &av1_mf1_last2_offset, val); + + val = rockchip_vpu981_av1_dec_get_dist(ctx, rf, oh[V4L2_AV1_REF_LAST3_FRAME]); + hantro_reg_write(vpu, &av1_mf1_last3_offset, val); + + val = rockchip_vpu981_av1_dec_get_dist(ctx, rf, oh[V4L2_AV1_REF_GOLDEN_FRAME]); + hantro_reg_write(vpu, &av1_mf1_golden_offset, val); + + val = rockchip_vpu981_av1_dec_get_dist(ctx, rf, oh[V4L2_AV1_REF_BWDREF_FRAME]); + hantro_reg_write(vpu, &av1_mf1_bwdref_offset, val); + + val = rockchip_vpu981_av1_dec_get_dist(ctx, rf, oh[V4L2_AV1_REF_ALTREF2_FRAME]); + hantro_reg_write(vpu, &av1_mf1_altref2_offset, val); + + val = rockchip_vpu981_av1_dec_get_dist(ctx, rf, oh[V4L2_AV1_REF_ALTREF_FRAME]); + hantro_reg_write(vpu, &av1_mf1_altref_offset, val); + } + + hantro_reg_write(vpu, &av1_mf2_last_offset, 0); + hantro_reg_write(vpu, &av1_mf2_last2_offset, 0); + hantro_reg_write(vpu, &av1_mf2_last3_offset, 0); + hantro_reg_write(vpu, &av1_mf2_golden_offset, 0); + hantro_reg_write(vpu, &av1_mf2_bwdref_offset, 0); + hantro_reg_write(vpu, &av1_mf2_altref2_offset, 0); + hantro_reg_write(vpu, &av1_mf2_altref_offset, 0); + + if (use_ref_frame_mvs && ref_ind > 1 && + cur_offset[mf_types[1] - V4L2_AV1_REF_LAST_FRAME] <= MAX_FRAME_DISTANCE && + cur_offset[mf_types[1] - V4L2_AV1_REF_LAST_FRAME] >= -MAX_FRAME_DISTANCE) { + int rf = rockchip_vpu981_get_order_hint(ctx, refs_selected[1]); + int idx = rockchip_vpu981_get_frame_index(ctx, refs_selected[1]); + u32 *oh = av1_dec->frame_refs[idx].order_hints; + int val; + + hantro_reg_write(vpu, &av1_use_temporal1_mvs, 1); + + val = rockchip_vpu981_av1_dec_get_dist(ctx, rf, oh[V4L2_AV1_REF_LAST_FRAME]); + hantro_reg_write(vpu, &av1_mf2_last_offset, val); + + val = rockchip_vpu981_av1_dec_get_dist(ctx, rf, oh[V4L2_AV1_REF_LAST2_FRAME]); + hantro_reg_write(vpu, &av1_mf2_last2_offset, val); + + val = rockchip_vpu981_av1_dec_get_dist(ctx, rf, oh[V4L2_AV1_REF_LAST3_FRAME]); + hantro_reg_write(vpu, &av1_mf2_last3_offset, val); + + val = rockchip_vpu981_av1_dec_get_dist(ctx, rf, oh[V4L2_AV1_REF_GOLDEN_FRAME]); + hantro_reg_write(vpu, &av1_mf2_golden_offset, val); + + val = rockchip_vpu981_av1_dec_get_dist(ctx, rf, oh[V4L2_AV1_REF_BWDREF_FRAME]); + hantro_reg_write(vpu, &av1_mf2_bwdref_offset, val); + + val = rockchip_vpu981_av1_dec_get_dist(ctx, rf, oh[V4L2_AV1_REF_ALTREF2_FRAME]); + hantro_reg_write(vpu, &av1_mf2_altref2_offset, val); + + val = rockchip_vpu981_av1_dec_get_dist(ctx, rf, oh[V4L2_AV1_REF_ALTREF_FRAME]); + hantro_reg_write(vpu, &av1_mf2_altref_offset, val); + } + + hantro_reg_write(vpu, &av1_mf3_last_offset, 0); + hantro_reg_write(vpu, &av1_mf3_last2_offset, 0); + hantro_reg_write(vpu, &av1_mf3_last3_offset, 0); + hantro_reg_write(vpu, &av1_mf3_golden_offset, 0); + hantro_reg_write(vpu, &av1_mf3_bwdref_offset, 0); + hantro_reg_write(vpu, &av1_mf3_altref2_offset, 0); + hantro_reg_write(vpu, &av1_mf3_altref_offset, 0); + + if (use_ref_frame_mvs && ref_ind > 2 && + cur_offset[mf_types[2] - V4L2_AV1_REF_LAST_FRAME] <= MAX_FRAME_DISTANCE && + cur_offset[mf_types[2] - V4L2_AV1_REF_LAST_FRAME] >= -MAX_FRAME_DISTANCE) { + int rf = rockchip_vpu981_get_order_hint(ctx, refs_selected[2]); + int idx = rockchip_vpu981_get_frame_index(ctx, refs_selected[2]); + u32 *oh = av1_dec->frame_refs[idx].order_hints; + int val; + + hantro_reg_write(vpu, &av1_use_temporal2_mvs, 1); + + val = rockchip_vpu981_av1_dec_get_dist(ctx, rf, oh[V4L2_AV1_REF_LAST_FRAME]); + hantro_reg_write(vpu, &av1_mf3_last_offset, val); + + val = rockchip_vpu981_av1_dec_get_dist(ctx, rf, oh[V4L2_AV1_REF_LAST2_FRAME]); + hantro_reg_write(vpu, &av1_mf3_last2_offset, val); + + val = rockchip_vpu981_av1_dec_get_dist(ctx, rf, oh[V4L2_AV1_REF_LAST3_FRAME]); + hantro_reg_write(vpu, &av1_mf3_last3_offset, val); + + val = rockchip_vpu981_av1_dec_get_dist(ctx, rf, oh[V4L2_AV1_REF_GOLDEN_FRAME]); + hantro_reg_write(vpu, &av1_mf3_golden_offset, val); + + val = rockchip_vpu981_av1_dec_get_dist(ctx, rf, oh[V4L2_AV1_REF_BWDREF_FRAME]); + hantro_reg_write(vpu, &av1_mf3_bwdref_offset, val); + + val = rockchip_vpu981_av1_dec_get_dist(ctx, rf, oh[V4L2_AV1_REF_ALTREF2_FRAME]); + hantro_reg_write(vpu, &av1_mf3_altref2_offset, val); + + val = rockchip_vpu981_av1_dec_get_dist(ctx, rf, oh[V4L2_AV1_REF_ALTREF_FRAME]); + hantro_reg_write(vpu, &av1_mf3_altref_offset, val); + } + + hantro_reg_write(vpu, &av1_cur_last_offset, cur_offset[0]); + hantro_reg_write(vpu, &av1_cur_last2_offset, cur_offset[1]); + hantro_reg_write(vpu, &av1_cur_last3_offset, cur_offset[2]); + hantro_reg_write(vpu, &av1_cur_golden_offset, cur_offset[3]); + hantro_reg_write(vpu, &av1_cur_bwdref_offset, cur_offset[4]); + hantro_reg_write(vpu, &av1_cur_altref2_offset, cur_offset[5]); + hantro_reg_write(vpu, &av1_cur_altref_offset, cur_offset[6]); + + hantro_reg_write(vpu, &av1_cur_last_roffset, cur_roffset[0]); + hantro_reg_write(vpu, &av1_cur_last2_roffset, cur_roffset[1]); + hantro_reg_write(vpu, &av1_cur_last3_roffset, cur_roffset[2]); + hantro_reg_write(vpu, &av1_cur_golden_roffset, cur_roffset[3]); + hantro_reg_write(vpu, &av1_cur_bwdref_roffset, cur_roffset[4]); + hantro_reg_write(vpu, &av1_cur_altref2_roffset, cur_roffset[5]); + hantro_reg_write(vpu, &av1_cur_altref_roffset, cur_roffset[6]); + + hantro_reg_write(vpu, &av1_mf1_type, mf_types[0] - V4L2_AV1_REF_LAST_FRAME); + hantro_reg_write(vpu, &av1_mf2_type, mf_types[1] - V4L2_AV1_REF_LAST_FRAME); + hantro_reg_write(vpu, &av1_mf3_type, mf_types[2] - V4L2_AV1_REF_LAST_FRAME); +} + +static void rockchip_vpu981_av1_dec_set_reference_frames(struct hantro_ctx *ctx) +{ + struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec; + struct hantro_av1_dec_ctrls *ctrls = &av1_dec->ctrls; + const struct v4l2_ctrl_av1_frame *frame = ctrls->frame; + int frame_type = frame->frame_type; + bool allow_intrabc = !!(ctrls->frame->flags & V4L2_AV1_FRAME_FLAG_ALLOW_INTRABC); + int ref_count[AV1DEC_MAX_PIC_BUFFERS] = { 0 }; + struct hantro_dev *vpu = ctx->dev; + int i, ref_frames = 0; + bool scale_enable = false; + + if (IS_INTRA(frame_type) && !allow_intrabc) + return; + + if (!allow_intrabc) { + for (i = 0; i < V4L2_AV1_REFS_PER_FRAME; i++) { + int idx = rockchip_vpu981_get_frame_index(ctx, i); + + if (idx >= 0) + ref_count[idx]++; + } + + for (i = 0; i < AV1DEC_MAX_PIC_BUFFERS; i++) { + if (ref_count[i]) + ref_frames++; + } + } else { + ref_frames = 1; + } + hantro_reg_write(vpu, &av1_ref_frames, ref_frames); + + rockchip_vpu981_av1_dec_set_frame_sign_bias(ctx); + + for (i = V4L2_AV1_REF_LAST_FRAME; i < V4L2_AV1_TOTAL_REFS_PER_FRAME; i++) { + u32 ref = i - 1; + int idx = 0; + int width, height; + + if (allow_intrabc) { + idx = av1_dec->current_frame_index; + width = frame->frame_width_minus_1 + 1; + height = frame->frame_height_minus_1 + 1; + } else { + if (rockchip_vpu981_get_frame_index(ctx, ref) > 0) + idx = rockchip_vpu981_get_frame_index(ctx, ref); + width = av1_dec->frame_refs[idx].width; + height = av1_dec->frame_refs[idx].height; + } + + scale_enable |= + rockchip_vpu981_av1_dec_set_ref(ctx, ref, idx, width, + height); + + rockchip_vpu981_av1_dec_set_sign_bias(ctx, ref, + av1_dec->ref_frame_sign_bias[i]); + } + hantro_reg_write(vpu, &av1_ref_scaling_enable, scale_enable); + + hantro_reg_write(vpu, &av1_ref0_gm_mode, + frame->global_motion.type[V4L2_AV1_REF_LAST_FRAME]); + hantro_reg_write(vpu, &av1_ref1_gm_mode, + frame->global_motion.type[V4L2_AV1_REF_LAST2_FRAME]); + hantro_reg_write(vpu, &av1_ref2_gm_mode, + frame->global_motion.type[V4L2_AV1_REF_LAST3_FRAME]); + hantro_reg_write(vpu, &av1_ref3_gm_mode, + frame->global_motion.type[V4L2_AV1_REF_GOLDEN_FRAME]); + hantro_reg_write(vpu, &av1_ref4_gm_mode, + frame->global_motion.type[V4L2_AV1_REF_BWDREF_FRAME]); + hantro_reg_write(vpu, &av1_ref5_gm_mode, + frame->global_motion.type[V4L2_AV1_REF_ALTREF2_FRAME]); + hantro_reg_write(vpu, &av1_ref6_gm_mode, + frame->global_motion.type[V4L2_AV1_REF_ALTREF_FRAME]); + + rockchip_vpu981_av1_dec_set_other_frames(ctx); +} + +static void rockchip_vpu981_av1_dec_set_parameters(struct hantro_ctx *ctx) +{ + struct hantro_dev *vpu = ctx->dev; + struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec; + struct hantro_av1_dec_ctrls *ctrls = &av1_dec->ctrls; + + hantro_reg_write(vpu, &av1_skip_mode, + !!(ctrls->frame->flags & V4L2_AV1_FRAME_FLAG_SKIP_MODE_PRESENT)); + hantro_reg_write(vpu, &av1_tempor_mvp_e, + !!(ctrls->frame->flags & V4L2_AV1_FRAME_FLAG_USE_REF_FRAME_MVS)); + hantro_reg_write(vpu, &av1_delta_lf_res_log, + ctrls->frame->loop_filter.delta_lf_res); + hantro_reg_write(vpu, &av1_delta_lf_multi, + !!(ctrls->frame->loop_filter.flags + & V4L2_AV1_LOOP_FILTER_FLAG_DELTA_LF_MULTI)); + hantro_reg_write(vpu, &av1_delta_lf_present, + !!(ctrls->frame->loop_filter.flags + & V4L2_AV1_LOOP_FILTER_FLAG_DELTA_LF_PRESENT)); + hantro_reg_write(vpu, &av1_disable_cdf_update, + !!(ctrls->frame->flags & V4L2_AV1_FRAME_FLAG_DISABLE_CDF_UPDATE)); + hantro_reg_write(vpu, &av1_allow_warp, + !!(ctrls->frame->flags & V4L2_AV1_FRAME_FLAG_ALLOW_WARPED_MOTION)); + hantro_reg_write(vpu, &av1_show_frame, + !!(ctrls->frame->flags & V4L2_AV1_FRAME_FLAG_SHOW_FRAME)); + hantro_reg_write(vpu, &av1_switchable_motion_mode, + !!(ctrls->frame->flags & V4L2_AV1_FRAME_FLAG_IS_MOTION_MODE_SWITCHABLE)); + hantro_reg_write(vpu, &av1_enable_cdef, + !!(ctrls->sequence->flags & V4L2_AV1_SEQUENCE_FLAG_ENABLE_CDEF)); + hantro_reg_write(vpu, &av1_allow_masked_compound, + !!(ctrls->sequence->flags + & V4L2_AV1_SEQUENCE_FLAG_ENABLE_MASKED_COMPOUND)); + hantro_reg_write(vpu, &av1_allow_interintra, + !!(ctrls->sequence->flags + & V4L2_AV1_SEQUENCE_FLAG_ENABLE_INTERINTRA_COMPOUND)); + hantro_reg_write(vpu, &av1_enable_intra_edge_filter, + !!(ctrls->sequence->flags + & V4L2_AV1_SEQUENCE_FLAG_ENABLE_INTRA_EDGE_FILTER)); + hantro_reg_write(vpu, &av1_allow_filter_intra, + !!(ctrls->sequence->flags & V4L2_AV1_SEQUENCE_FLAG_ENABLE_FILTER_INTRA)); + hantro_reg_write(vpu, &av1_enable_jnt_comp, + !!(ctrls->sequence->flags & V4L2_AV1_SEQUENCE_FLAG_ENABLE_JNT_COMP)); + hantro_reg_write(vpu, &av1_enable_dual_filter, + !!(ctrls->sequence->flags & V4L2_AV1_SEQUENCE_FLAG_ENABLE_DUAL_FILTER)); + hantro_reg_write(vpu, &av1_reduced_tx_set_used, + !!(ctrls->frame->flags & V4L2_AV1_FRAME_FLAG_REDUCED_TX_SET)); + hantro_reg_write(vpu, &av1_allow_screen_content_tools, + !!(ctrls->frame->flags & V4L2_AV1_FRAME_FLAG_ALLOW_SCREEN_CONTENT_TOOLS)); + hantro_reg_write(vpu, &av1_allow_intrabc, + !!(ctrls->frame->flags & V4L2_AV1_FRAME_FLAG_ALLOW_INTRABC)); + + if (!(ctrls->frame->flags & V4L2_AV1_FRAME_FLAG_ALLOW_SCREEN_CONTENT_TOOLS)) + hantro_reg_write(vpu, &av1_force_interger_mv, 0); + else + hantro_reg_write(vpu, &av1_force_interger_mv, + !!(ctrls->frame->flags & V4L2_AV1_FRAME_FLAG_FORCE_INTEGER_MV)); + + hantro_reg_write(vpu, &av1_blackwhite_e, 0); + hantro_reg_write(vpu, &av1_delta_q_res_log, ctrls->frame->quantization.delta_q_res); + hantro_reg_write(vpu, &av1_delta_q_present, + !!(ctrls->frame->quantization.flags + & V4L2_AV1_QUANTIZATION_FLAG_DELTA_Q_PRESENT)); + + hantro_reg_write(vpu, &av1_idr_pic_e, !ctrls->frame->frame_type); + hantro_reg_write(vpu, &av1_quant_base_qindex, ctrls->frame->quantization.base_q_idx); + hantro_reg_write(vpu, &av1_bit_depth_y_minus8, ctx->bit_depth - 8); + hantro_reg_write(vpu, &av1_bit_depth_c_minus8, ctx->bit_depth - 8); + + hantro_reg_write(vpu, &av1_mcomp_filt_type, ctrls->frame->interpolation_filter); + hantro_reg_write(vpu, &av1_high_prec_mv_e, + !!(ctrls->frame->flags & V4L2_AV1_FRAME_FLAG_ALLOW_HIGH_PRECISION_MV)); + hantro_reg_write(vpu, &av1_comp_pred_mode, + (ctrls->frame->flags & V4L2_AV1_FRAME_FLAG_REFERENCE_SELECT) ? 2 : 0); + hantro_reg_write(vpu, &av1_transform_mode, (ctrls->frame->tx_mode == 1) ? 3 : 4); + hantro_reg_write(vpu, &av1_max_cb_size, + (ctrls->sequence->flags + & V4L2_AV1_SEQUENCE_FLAG_USE_128X128_SUPERBLOCK) ? 7 : 6); + hantro_reg_write(vpu, &av1_min_cb_size, 3); + + hantro_reg_write(vpu, &av1_comp_pred_fixed_ref, 0); + hantro_reg_write(vpu, &av1_comp_pred_var_ref0_av1, 0); + hantro_reg_write(vpu, &av1_comp_pred_var_ref1_av1, 0); + hantro_reg_write(vpu, &av1_filt_level_seg0, 0); + hantro_reg_write(vpu, &av1_filt_level_seg1, 0); + hantro_reg_write(vpu, &av1_filt_level_seg2, 0); + hantro_reg_write(vpu, &av1_filt_level_seg3, 0); + hantro_reg_write(vpu, &av1_filt_level_seg4, 0); + hantro_reg_write(vpu, &av1_filt_level_seg5, 0); + hantro_reg_write(vpu, &av1_filt_level_seg6, 0); + hantro_reg_write(vpu, &av1_filt_level_seg7, 0); + + hantro_reg_write(vpu, &av1_qp_delta_y_dc_av1, ctrls->frame->quantization.delta_q_y_dc); + hantro_reg_write(vpu, &av1_qp_delta_ch_dc_av1, ctrls->frame->quantization.delta_q_u_dc); + hantro_reg_write(vpu, &av1_qp_delta_ch_ac_av1, ctrls->frame->quantization.delta_q_u_ac); + if (ctrls->frame->quantization.flags & V4L2_AV1_QUANTIZATION_FLAG_USING_QMATRIX) { + hantro_reg_write(vpu, &av1_qmlevel_y, ctrls->frame->quantization.qm_y); + hantro_reg_write(vpu, &av1_qmlevel_u, ctrls->frame->quantization.qm_u); + hantro_reg_write(vpu, &av1_qmlevel_v, ctrls->frame->quantization.qm_v); + } else { + hantro_reg_write(vpu, &av1_qmlevel_y, 0xff); + hantro_reg_write(vpu, &av1_qmlevel_u, 0xff); + hantro_reg_write(vpu, &av1_qmlevel_v, 0xff); + } + + hantro_reg_write(vpu, &av1_lossless_e, rockchip_vpu981_av1_dec_is_lossless(ctx)); + hantro_reg_write(vpu, &av1_quant_delta_v_dc, ctrls->frame->quantization.delta_q_v_dc); + hantro_reg_write(vpu, &av1_quant_delta_v_ac, ctrls->frame->quantization.delta_q_v_ac); + + hantro_reg_write(vpu, &av1_skip_ref0, + (ctrls->frame->skip_mode_frame[0]) ? ctrls->frame->skip_mode_frame[0] : 1); + hantro_reg_write(vpu, &av1_skip_ref1, + (ctrls->frame->skip_mode_frame[1]) ? ctrls->frame->skip_mode_frame[1] : 1); + + hantro_write_addr(vpu, AV1_MC_SYNC_CURR, av1_dec->tile_buf.dma); + hantro_write_addr(vpu, AV1_MC_SYNC_LEFT, av1_dec->tile_buf.dma); +} + +static void +rockchip_vpu981_av1_dec_set_input_buffer(struct hantro_ctx *ctx, + struct vb2_v4l2_buffer *vb2_src) +{ + struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec; + struct hantro_av1_dec_ctrls *ctrls = &av1_dec->ctrls; + const struct v4l2_ctrl_av1_tile_group_entry *group_entry = + ctrls->tile_group_entry; + struct hantro_dev *vpu = ctx->dev; + dma_addr_t src_dma; + u32 src_len, src_buf_len; + int start_bit, offset; + + src_dma = vb2_dma_contig_plane_dma_addr(&vb2_src->vb2_buf, 0); + src_len = vb2_get_plane_payload(&vb2_src->vb2_buf, 0); + src_buf_len = vb2_plane_size(&vb2_src->vb2_buf, 0); + + start_bit = (group_entry[0].tile_offset & 0xf) * 8; + offset = group_entry[0].tile_offset & ~0xf; + + hantro_reg_write(vpu, &av1_strm_buffer_len, src_buf_len); + hantro_reg_write(vpu, &av1_strm_start_bit, start_bit); + hantro_reg_write(vpu, &av1_stream_len, src_len); + hantro_reg_write(vpu, &av1_strm_start_offset, 0); + hantro_write_addr(vpu, AV1_INPUT_STREAM, src_dma + offset); +} + +static void +rockchip_vpu981_av1_dec_set_output_buffer(struct hantro_ctx *ctx) +{ + struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec; + struct hantro_dev *vpu = ctx->dev; + struct hantro_decoded_buffer *dst; + struct vb2_v4l2_buffer *vb2_dst; + dma_addr_t luma_addr, chroma_addr, mv_addr = 0; + size_t cr_offset = rockchip_vpu981_av1_dec_luma_size(ctx); + size_t mv_offset = rockchip_vpu981_av1_dec_chroma_size(ctx); + + vb2_dst = av1_dec->frame_refs[av1_dec->current_frame_index].vb2_ref; + dst = vb2_to_hantro_decoded_buf(&vb2_dst->vb2_buf); + luma_addr = hantro_get_dec_buf_addr(ctx, &dst->base.vb.vb2_buf); + chroma_addr = luma_addr + cr_offset; + mv_addr = luma_addr + mv_offset; + + hantro_write_addr(vpu, AV1_TILE_OUT_LU, luma_addr); + hantro_write_addr(vpu, AV1_TILE_OUT_CH, chroma_addr); + hantro_write_addr(vpu, AV1_TILE_OUT_MV, mv_addr); +} + +int rockchip_vpu981_av1_dec_run(struct hantro_ctx *ctx) +{ + struct hantro_dev *vpu = ctx->dev; + struct vb2_v4l2_buffer *vb2_src; + int ret; + + hantro_start_prepare_run(ctx); + + ret = rockchip_vpu981_av1_dec_prepare_run(ctx); + if (ret) + goto prepare_error; + + vb2_src = hantro_get_src_buf(ctx); + if (!vb2_src) { + ret = -EINVAL; + goto prepare_error; + } + + rockchip_vpu981_av1_dec_clean_refs(ctx); + rockchip_vpu981_av1_dec_frame_ref(ctx, vb2_src->vb2_buf.timestamp); + + rockchip_vpu981_av1_dec_set_parameters(ctx); + rockchip_vpu981_av1_dec_set_global_model(ctx); + rockchip_vpu981_av1_dec_set_tile_info(ctx); + rockchip_vpu981_av1_dec_set_reference_frames(ctx); + rockchip_vpu981_av1_dec_set_segmentation(ctx); + rockchip_vpu981_av1_dec_set_loopfilter(ctx); + rockchip_vpu981_av1_dec_set_picture_dimensions(ctx); + rockchip_vpu981_av1_dec_set_cdef(ctx); + rockchip_vpu981_av1_dec_set_lr(ctx); + rockchip_vpu981_av1_dec_set_fgs(ctx); + rockchip_vpu981_av1_dec_set_prob(ctx); + + hantro_reg_write(vpu, &av1_dec_mode, AV1_DEC_MODE); + hantro_reg_write(vpu, &av1_dec_out_ec_byte_word, 0); + hantro_reg_write(vpu, &av1_write_mvs_e, 1); + hantro_reg_write(vpu, &av1_dec_out_ec_bypass, 1); + hantro_reg_write(vpu, &av1_dec_clk_gate_e, 1); + + hantro_reg_write(vpu, &av1_dec_abort_e, 0); + hantro_reg_write(vpu, &av1_dec_tile_int_e, 0); + + hantro_reg_write(vpu, &av1_dec_alignment, 64); + hantro_reg_write(vpu, &av1_apf_disable, 0); + hantro_reg_write(vpu, &av1_apf_threshold, 8); + hantro_reg_write(vpu, &av1_dec_buswidth, 2); + hantro_reg_write(vpu, &av1_dec_max_burst, 16); + hantro_reg_write(vpu, &av1_error_conceal_e, 0); + hantro_reg_write(vpu, &av1_axi_rd_ostd_threshold, 64); + hantro_reg_write(vpu, &av1_axi_wr_ostd_threshold, 64); + + hantro_reg_write(vpu, &av1_ext_timeout_cycles, 0xfffffff); + hantro_reg_write(vpu, &av1_ext_timeout_override_e, 1); + hantro_reg_write(vpu, &av1_timeout_cycles, 0xfffffff); + hantro_reg_write(vpu, &av1_timeout_override_e, 1); + + rockchip_vpu981_av1_dec_set_output_buffer(ctx); + rockchip_vpu981_av1_dec_set_input_buffer(ctx, vb2_src); + + hantro_end_prepare_run(ctx); + + hantro_reg_write(vpu, &av1_dec_e, 1); + + return 0; + +prepare_error: + hantro_end_prepare_run(ctx); + hantro_irq_done(vpu, VB2_BUF_STATE_ERROR); + return ret; +} + +static void rockchip_vpu981_postproc_enable(struct hantro_ctx *ctx) +{ + struct hantro_dev *vpu = ctx->dev; + int width = ctx->dst_fmt.width; + int height = ctx->dst_fmt.height; + struct vb2_v4l2_buffer *vb2_dst; + size_t chroma_offset; + dma_addr_t dst_dma; + + vb2_dst = hantro_get_dst_buf(ctx); + + dst_dma = vb2_dma_contig_plane_dma_addr(&vb2_dst->vb2_buf, 0); + chroma_offset = ctx->dst_fmt.plane_fmt[0].bytesperline * + ctx->dst_fmt.height; + + /* enable post processor */ + hantro_reg_write(vpu, &av1_pp_out_e, 1); + hantro_reg_write(vpu, &av1_pp_in_format, 0); + hantro_reg_write(vpu, &av1_pp0_dup_hor, 1); + hantro_reg_write(vpu, &av1_pp0_dup_ver, 1); + + hantro_reg_write(vpu, &av1_pp_in_height, height / 2); + hantro_reg_write(vpu, &av1_pp_in_width, width / 2); + hantro_reg_write(vpu, &av1_pp_out_height, height); + hantro_reg_write(vpu, &av1_pp_out_width, width); + hantro_reg_write(vpu, &av1_pp_out_y_stride, + ctx->dst_fmt.plane_fmt[0].bytesperline); + hantro_reg_write(vpu, &av1_pp_out_c_stride, + ctx->dst_fmt.plane_fmt[0].bytesperline); + switch (ctx->dst_fmt.pixelformat) { + case V4L2_PIX_FMT_P010: + hantro_reg_write(vpu, &av1_pp_out_format, 1); + break; + case V4L2_PIX_FMT_NV12: + hantro_reg_write(vpu, &av1_pp_out_format, 3); + break; + default: + hantro_reg_write(vpu, &av1_pp_out_format, 0); + } + + hantro_reg_write(vpu, &av1_ppd_blend_exist, 0); + hantro_reg_write(vpu, &av1_ppd_dith_exist, 0); + hantro_reg_write(vpu, &av1_ablend_crop_e, 0); + hantro_reg_write(vpu, &av1_pp_format_customer1_e, 0); + hantro_reg_write(vpu, &av1_pp_crop_exist, 0); + hantro_reg_write(vpu, &av1_pp_up_level, 0); + hantro_reg_write(vpu, &av1_pp_down_level, 0); + hantro_reg_write(vpu, &av1_pp_exist, 0); + + hantro_write_addr(vpu, AV1_PP_OUT_LU, dst_dma); + hantro_write_addr(vpu, AV1_PP_OUT_CH, dst_dma + chroma_offset); +} + +static void rockchip_vpu981_postproc_disable(struct hantro_ctx *ctx) +{ + struct hantro_dev *vpu = ctx->dev; + + /* disable post processor */ + hantro_reg_write(vpu, &av1_pp_out_e, 0); +} + +const struct hantro_postproc_ops rockchip_vpu981_postproc_ops = { + .enable = rockchip_vpu981_postproc_enable, + .disable = rockchip_vpu981_postproc_disable, +}; diff --git a/drivers/media/platform/verisilicon/rockchip_vpu981_regs.h b/drivers/media/platform/verisilicon/rockchip_vpu981_regs.h new file mode 100644 index 0000000000000000000000000000000000000000..182e6c830ff696d06b97431371750b4eedb413ff --- /dev/null +++ b/drivers/media/platform/verisilicon/rockchip_vpu981_regs.h @@ -0,0 +1,477 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2022, Collabora + * + * Author: Benjamin Gaignard + */ + +#ifndef _ROCKCHIP_VPU981_REGS_H_ +#define _ROCKCHIP_VPU981_REGS_H_ + +#include "hantro.h" + +#define AV1_SWREG(nr) ((nr) * 4) + +#define AV1_DEC_REG(b, s, m) \ + ((const struct hantro_reg) { \ + .base = AV1_SWREG(b), \ + .shift = s, \ + .mask = m, \ + }) + +#define AV1_REG_INTERRUPT AV1_SWREG(1) +#define AV1_REG_INTERRUPT_DEC_RDY_INT BIT(12) + +#define AV1_REG_CONFIG AV1_SWREG(2) +#define AV1_REG_CONFIG_DEC_CLK_GATE_E BIT(10) + +#define av1_dec_e AV1_DEC_REG(1, 0, 0x1) +#define av1_dec_abort_e AV1_DEC_REG(1, 5, 0x1) +#define av1_dec_tile_int_e AV1_DEC_REG(1, 7, 0x1) + +#define av1_dec_clk_gate_e AV1_DEC_REG(2, 10, 0x1) + +#define av1_dec_out_ec_bypass AV1_DEC_REG(3, 8, 0x1) +#define av1_write_mvs_e AV1_DEC_REG(3, 12, 0x1) +#define av1_filtering_dis AV1_DEC_REG(3, 14, 0x1) +#define av1_dec_out_dis AV1_DEC_REG(3, 15, 0x1) +#define av1_dec_out_ec_byte_word AV1_DEC_REG(3, 16, 0x1) +#define av1_skip_mode AV1_DEC_REG(3, 26, 0x1) +#define av1_dec_mode AV1_DEC_REG(3, 27, 0x1f) + +#define av1_ref_frames AV1_DEC_REG(4, 0, 0xf) +#define av1_pic_height_in_cbs AV1_DEC_REG(4, 6, 0x1fff) +#define av1_pic_width_in_cbs AV1_DEC_REG(4, 19, 0x1fff) + +#define av1_ref_scaling_enable AV1_DEC_REG(5, 0, 0x1) +#define av1_filt_level_base_gt32 AV1_DEC_REG(5, 1, 0x1) +#define av1_error_resilient AV1_DEC_REG(5, 2, 0x1) +#define av1_force_interger_mv AV1_DEC_REG(5, 3, 0x1) +#define av1_allow_intrabc AV1_DEC_REG(5, 4, 0x1) +#define av1_allow_screen_content_tools AV1_DEC_REG(5, 5, 0x1) +#define av1_reduced_tx_set_used AV1_DEC_REG(5, 6, 0x1) +#define av1_enable_dual_filter AV1_DEC_REG(5, 7, 0x1) +#define av1_enable_jnt_comp AV1_DEC_REG(5, 8, 0x1) +#define av1_allow_filter_intra AV1_DEC_REG(5, 9, 0x1) +#define av1_enable_intra_edge_filter AV1_DEC_REG(5, 10, 0x1) +#define av1_tempor_mvp_e AV1_DEC_REG(5, 11, 0x1) +#define av1_allow_interintra AV1_DEC_REG(5, 12, 0x1) +#define av1_allow_masked_compound AV1_DEC_REG(5, 13, 0x1) +#define av1_enable_cdef AV1_DEC_REG(5, 14, 0x1) +#define av1_switchable_motion_mode AV1_DEC_REG(5, 15, 0x1) +#define av1_show_frame AV1_DEC_REG(5, 16, 0x1) +#define av1_superres_is_scaled AV1_DEC_REG(5, 17, 0x1) +#define av1_allow_warp AV1_DEC_REG(5, 18, 0x1) +#define av1_disable_cdf_update AV1_DEC_REG(5, 19, 0x1) +#define av1_preskip_segid AV1_DEC_REG(5, 20, 0x1) +#define av1_delta_lf_present AV1_DEC_REG(5, 21, 0x1) +#define av1_delta_lf_multi AV1_DEC_REG(5, 22, 0x1) +#define av1_delta_lf_res_log AV1_DEC_REG(5, 23, 0x3) +#define av1_strm_start_bit AV1_DEC_REG(5, 25, 0x7f) + +#define av1_stream_len AV1_DEC_REG(6, 0, 0xffffffff) + +#define av1_delta_q_present AV1_DEC_REG(7, 0, 0x1) +#define av1_delta_q_res_log AV1_DEC_REG(7, 1, 0x3) +#define av1_cdef_damping AV1_DEC_REG(7, 3, 0x3) +#define av1_cdef_bits AV1_DEC_REG(7, 5, 0x3) +#define av1_apply_grain AV1_DEC_REG(7, 7, 0x1) +#define av1_num_y_points_b AV1_DEC_REG(7, 8, 0x1) +#define av1_num_cb_points_b AV1_DEC_REG(7, 9, 0x1) +#define av1_num_cr_points_b AV1_DEC_REG(7, 10, 0x1) +#define av1_overlap_flag AV1_DEC_REG(7, 11, 0x1) +#define av1_clip_to_restricted_range AV1_DEC_REG(7, 12, 0x1) +#define av1_chroma_scaling_from_luma AV1_DEC_REG(7, 13, 0x1) +#define av1_random_seed AV1_DEC_REG(7, 14, 0xffff) +#define av1_blackwhite_e AV1_DEC_REG(7, 30, 0x1) + +#define av1_scaling_shift AV1_DEC_REG(8, 0, 0xf) +#define av1_bit_depth_c_minus8 AV1_DEC_REG(8, 4, 0x3) +#define av1_bit_depth_y_minus8 AV1_DEC_REG(8, 6, 0x3) +#define av1_quant_base_qindex AV1_DEC_REG(8, 8, 0xff) +#define av1_idr_pic_e AV1_DEC_REG(8, 16, 0x1) +#define av1_superres_pic_width AV1_DEC_REG(8, 17, 0x7fff) + +#define av1_ref4_sign_bias AV1_DEC_REG(9, 2, 0x1) +#define av1_ref5_sign_bias AV1_DEC_REG(9, 3, 0x1) +#define av1_ref6_sign_bias AV1_DEC_REG(9, 4, 0x1) +#define av1_mf1_type AV1_DEC_REG(9, 5, 0x7) +#define av1_mf2_type AV1_DEC_REG(9, 8, 0x7) +#define av1_mf3_type AV1_DEC_REG(9, 11, 0x7) +#define av1_scale_denom_minus9 AV1_DEC_REG(9, 14, 0x7) +#define av1_last_active_seg AV1_DEC_REG(9, 17, 0x7) +#define av1_context_update_tile_id AV1_DEC_REG(9, 20, 0xfff) + +#define av1_tile_transpose AV1_DEC_REG(10, 0, 0x1) +#define av1_tile_enable AV1_DEC_REG(10, 1, 0x1) +#define av1_multicore_full_width AV1_DEC_REG(10, 2, 0xff) +#define av1_num_tile_rows_8k AV1_DEC_REG(10, 10, 0x7f) +#define av1_num_tile_cols_8k AV1_DEC_REG(10, 17, 0x7f) +#define av1_multicore_tile_start_x AV1_DEC_REG(10, 24, 0xff) + +#define av1_use_temporal3_mvs AV1_DEC_REG(11, 0, 0x1) +#define av1_use_temporal2_mvs AV1_DEC_REG(11, 1, 0x1) +#define av1_use_temporal1_mvs AV1_DEC_REG(11, 2, 0x1) +#define av1_use_temporal0_mvs AV1_DEC_REG(11, 3, 0x1) +#define av1_comp_pred_mode AV1_DEC_REG(11, 4, 0x3) +#define av1_high_prec_mv_e AV1_DEC_REG(11, 7, 0x1) +#define av1_mcomp_filt_type AV1_DEC_REG(11, 8, 0x7) +#define av1_multicore_expect_context_update AV1_DEC_REG(11, 11, 0x1) +#define av1_multicore_sbx_offset AV1_DEC_REG(11, 12, 0x7f) +#define av1_ulticore_tile_col AV1_DEC_REG(11, 19, 0x7f) +#define av1_transform_mode AV1_DEC_REG(11, 27, 0x7) +#define av1_dec_tile_size_mag AV1_DEC_REG(11, 30, 0x3) + +#define av1_seg_quant_sign AV1_DEC_REG(12, 2, 0xff) +#define av1_max_cb_size AV1_DEC_REG(12, 10, 0x7) +#define av1_min_cb_size AV1_DEC_REG(12, 13, 0x7) +#define av1_comp_pred_fixed_ref AV1_DEC_REG(12, 16, 0x7) +#define av1_multicore_tile_width AV1_DEC_REG(12, 19, 0x7f) +#define av1_pic_height_pad AV1_DEC_REG(12, 26, 0x7) +#define av1_pic_width_pad AV1_DEC_REG(12, 29, 0x7) + +#define av1_segment_e AV1_DEC_REG(13, 0, 0x1) +#define av1_segment_upd_e AV1_DEC_REG(13, 1, 0x1) +#define av1_segment_temp_upd_e AV1_DEC_REG(13, 2, 0x1) +#define av1_comp_pred_var_ref0_av1 AV1_DEC_REG(13, 3, 0x7) +#define av1_comp_pred_var_ref1_av1 AV1_DEC_REG(13, 6, 0x7) +#define av1_lossless_e AV1_DEC_REG(13, 9, 0x1) +#define av1_qp_delta_ch_ac_av1 AV1_DEC_REG(13, 11, 0x7f) +#define av1_qp_delta_ch_dc_av1 AV1_DEC_REG(13, 18, 0x7f) +#define av1_qp_delta_y_dc_av1 AV1_DEC_REG(13, 25, 0x7f) + +#define av1_quant_seg0 AV1_DEC_REG(14, 0, 0xff) +#define av1_filt_level_seg0 AV1_DEC_REG(14, 8, 0x3f) +#define av1_skip_seg0 AV1_DEC_REG(14, 14, 0x1) +#define av1_refpic_seg0 AV1_DEC_REG(14, 15, 0xf) +#define av1_filt_level_delta0_seg0 AV1_DEC_REG(14, 19, 0x7f) +#define av1_filt_level0 AV1_DEC_REG(14, 26, 0x3f) + +#define av1_quant_seg1 AV1_DEC_REG(15, 0, 0xff) +#define av1_filt_level_seg1 AV1_DEC_REG(15, 8, 0x3f) +#define av1_skip_seg1 AV1_DEC_REG(15, 14, 0x1) +#define av1_refpic_seg1 AV1_DEC_REG(15, 15, 0xf) +#define av1_filt_level_delta0_seg1 AV1_DEC_REG(15, 19, 0x7f) +#define av1_filt_level1 AV1_DEC_REG(15, 26, 0x3f) + +#define av1_quant_seg2 AV1_DEC_REG(16, 0, 0xff) +#define av1_filt_level_seg2 AV1_DEC_REG(16, 8, 0x3f) +#define av1_skip_seg2 AV1_DEC_REG(16, 14, 0x1) +#define av1_refpic_seg2 AV1_DEC_REG(16, 15, 0xf) +#define av1_filt_level_delta0_seg2 AV1_DEC_REG(16, 19, 0x7f) +#define av1_filt_level2 AV1_DEC_REG(16, 26, 0x3f) + +#define av1_quant_seg3 AV1_DEC_REG(17, 0, 0xff) +#define av1_filt_level_seg3 AV1_DEC_REG(17, 8, 0x3f) +#define av1_skip_seg3 AV1_DEC_REG(17, 14, 0x1) +#define av1_refpic_seg3 AV1_DEC_REG(17, 15, 0xf) +#define av1_filt_level_delta0_seg3 AV1_DEC_REG(17, 19, 0x7f) +#define av1_filt_level3 AV1_DEC_REG(17, 26, 0x3f) + +#define av1_quant_seg4 AV1_DEC_REG(18, 0, 0xff) +#define av1_filt_level_seg4 AV1_DEC_REG(18, 8, 0x3f) +#define av1_skip_seg4 AV1_DEC_REG(18, 14, 0x1) +#define av1_refpic_seg4 AV1_DEC_REG(18, 15, 0xf) +#define av1_filt_level_delta0_seg4 AV1_DEC_REG(18, 19, 0x7f) +#define av1_lr_type AV1_DEC_REG(18, 26, 0x3f) + +#define av1_quant_seg5 AV1_DEC_REG(19, 0, 0xff) +#define av1_filt_level_seg5 AV1_DEC_REG(19, 8, 0x3f) +#define av1_skip_seg5 AV1_DEC_REG(19, 14, 0x1) +#define av1_refpic_seg5 AV1_DEC_REG(19, 15, 0xf) +#define av1_filt_level_delta0_seg5 AV1_DEC_REG(19, 19, 0x7f) +#define av1_lr_unit_size AV1_DEC_REG(19, 26, 0x3f) + +#define av1_filt_level_delta1_seg0 AV1_DEC_REG(20, 0, 0x7f) +#define av1_filt_level_delta2_seg0 AV1_DEC_REG(20, 7, 0x7f) +#define av1_filt_level_delta3_seg0 AV1_DEC_REG(20, 14, 0x7f) +#define av1_global_mv_seg0 AV1_DEC_REG(20, 21, 0x1) +#define av1_mf1_last_offset AV1_DEC_REG(20, 22, 0x1ff) + +#define av1_filt_level_delta1_seg1 AV1_DEC_REG(21, 0, 0x7f) +#define av1_filt_level_delta2_seg1 AV1_DEC_REG(21, 7, 0x7f) +#define av1_filt_level_delta3_seg1 AV1_DEC_REG(21, 14, 0x7f) +#define av1_global_mv_seg1 AV1_DEC_REG(21, 21, 0x1) +#define av1_mf1_last2_offset AV1_DEC_REG(21, 22, 0x1ff) + +#define av1_filt_level_delta1_seg2 AV1_DEC_REG(22, 0, 0x7f) +#define av1_filt_level_delta2_seg2 AV1_DEC_REG(22, 7, 0x7f) +#define av1_filt_level_delta3_seg2 AV1_DEC_REG(22, 14, 0x7f) +#define av1_global_mv_seg2 AV1_DEC_REG(22, 21, 0x1) +#define av1_mf1_last3_offset AV1_DEC_REG(22, 22, 0x1ff) + +#define av1_filt_level_delta1_seg3 AV1_DEC_REG(23, 0, 0x7f) +#define av1_filt_level_delta2_seg3 AV1_DEC_REG(23, 7, 0x7f) +#define av1_filt_level_delta3_seg3 AV1_DEC_REG(23, 14, 0x7f) +#define av1_global_mv_seg3 AV1_DEC_REG(23, 21, 0x1) +#define av1_mf1_golden_offset AV1_DEC_REG(23, 22, 0x1ff) + +#define av1_filt_level_delta1_seg4 AV1_DEC_REG(24, 0, 0x7f) +#define av1_filt_level_delta2_seg4 AV1_DEC_REG(24, 7, 0x7f) +#define av1_filt_level_delta3_seg4 AV1_DEC_REG(24, 14, 0x7f) +#define av1_global_mv_seg4 AV1_DEC_REG(24, 21, 0x1) +#define av1_mf1_bwdref_offset AV1_DEC_REG(24, 22, 0x1ff) + +#define av1_filt_level_delta1_seg5 AV1_DEC_REG(25, 0, 0x7f) +#define av1_filt_level_delta2_seg5 AV1_DEC_REG(25, 7, 0x7f) +#define av1_filt_level_delta3_seg5 AV1_DEC_REG(25, 14, 0x7f) +#define av1_global_mv_seg5 AV1_DEC_REG(25, 21, 0x1) +#define av1_mf1_altref2_offset AV1_DEC_REG(25, 22, 0x1ff) + +#define av1_filt_level_delta1_seg6 AV1_DEC_REG(26, 0, 0x7f) +#define av1_filt_level_delta2_seg6 AV1_DEC_REG(26, 7, 0x7f) +#define av1_filt_level_delta3_seg6 AV1_DEC_REG(26, 14, 0x7f) +#define av1_global_mv_seg6 AV1_DEC_REG(26, 21, 0x1) +#define av1_mf1_altref_offset AV1_DEC_REG(26, 22, 0x1ff) + +#define av1_filt_level_delta1_seg7 AV1_DEC_REG(27, 0, 0x7f) +#define av1_filt_level_delta2_seg7 AV1_DEC_REG(27, 7, 0x7f) +#define av1_filt_level_delta3_seg7 AV1_DEC_REG(27, 14, 0x7f) +#define av1_global_mv_seg7 AV1_DEC_REG(27, 21, 0x1) +#define av1_mf2_last_offset AV1_DEC_REG(27, 22, 0x1ff) + +#define av1_cb_offset AV1_DEC_REG(28, 0, 0x1ff) +#define av1_cb_luma_mult AV1_DEC_REG(28, 9, 0xff) +#define av1_cb_mult AV1_DEC_REG(28, 17, 0xff) +#define av1_quant_delta_v_dc AV1_DEC_REG(28, 25, 0x7f) + +#define av1_cr_offset AV1_DEC_REG(29, 0, 0x1ff) +#define av1_cr_luma_mult AV1_DEC_REG(29, 9, 0xff) +#define av1_cr_mult AV1_DEC_REG(29, 17, 0xff) +#define av1_quant_delta_v_ac AV1_DEC_REG(29, 25, 0x7f) + +#define av1_filt_ref_adj_5 AV1_DEC_REG(30, 0, 0x7f) +#define av1_filt_ref_adj_4 AV1_DEC_REG(30, 7, 0x7f) +#define av1_filt_mb_adj_1 AV1_DEC_REG(30, 14, 0x7f) +#define av1_filt_mb_adj_0 AV1_DEC_REG(30, 21, 0x7f) +#define av1_filt_sharpness AV1_DEC_REG(30, 28, 0x7) + +#define av1_quant_seg6 AV1_DEC_REG(31, 0, 0xff) +#define av1_filt_level_seg6 AV1_DEC_REG(31, 8, 0x3f) +#define av1_skip_seg6 AV1_DEC_REG(31, 14, 0x1) +#define av1_refpic_seg6 AV1_DEC_REG(31, 15, 0xf) +#define av1_filt_level_delta0_seg6 AV1_DEC_REG(31, 19, 0x7f) +#define av1_skip_ref0 AV1_DEC_REG(31, 26, 0xf) + +#define av1_quant_seg7 AV1_DEC_REG(32, 0, 0xff) +#define av1_filt_level_seg7 AV1_DEC_REG(32, 8, 0x3f) +#define av1_skip_seg7 AV1_DEC_REG(32, 14, 0x1) +#define av1_refpic_seg7 AV1_DEC_REG(32, 15, 0xf) +#define av1_filt_level_delta0_seg7 AV1_DEC_REG(32, 19, 0x7f) +#define av1_skip_ref1 AV1_DEC_REG(32, 26, 0xf) + +#define av1_ref0_height AV1_DEC_REG(33, 0, 0xffff) +#define av1_ref0_width AV1_DEC_REG(33, 16, 0xffff) + +#define av1_ref1_height AV1_DEC_REG(34, 0, 0xffff) +#define av1_ref1_width AV1_DEC_REG(34, 16, 0xffff) + +#define av1_ref2_height AV1_DEC_REG(35, 0, 0xffff) +#define av1_ref2_width AV1_DEC_REG(35, 16, 0xffff) + +#define av1_ref0_ver_scale AV1_DEC_REG(36, 0, 0xffff) +#define av1_ref0_hor_scale AV1_DEC_REG(36, 16, 0xffff) + +#define av1_ref1_ver_scale AV1_DEC_REG(37, 0, 0xffff) +#define av1_ref1_hor_scale AV1_DEC_REG(37, 16, 0xffff) + +#define av1_ref2_ver_scale AV1_DEC_REG(38, 0, 0xffff) +#define av1_ref2_hor_scale AV1_DEC_REG(38, 16, 0xffff) + +#define av1_ref3_ver_scale AV1_DEC_REG(39, 0, 0xffff) +#define av1_ref3_hor_scale AV1_DEC_REG(39, 16, 0xffff) + +#define av1_ref4_ver_scale AV1_DEC_REG(40, 0, 0xffff) +#define av1_ref4_hor_scale AV1_DEC_REG(40, 16, 0xffff) + +#define av1_ref5_ver_scale AV1_DEC_REG(41, 0, 0xffff) +#define av1_ref5_hor_scale AV1_DEC_REG(41, 16, 0xffff) + +#define av1_ref6_ver_scale AV1_DEC_REG(42, 0, 0xffff) +#define av1_ref6_hor_scale AV1_DEC_REG(42, 16, 0xffff) + +#define av1_ref3_height AV1_DEC_REG(43, 0, 0xffff) +#define av1_ref3_width AV1_DEC_REG(43, 16, 0xffff) + +#define av1_ref4_height AV1_DEC_REG(44, 0, 0xffff) +#define av1_ref4_width AV1_DEC_REG(44, 16, 0xffff) + +#define av1_ref5_height AV1_DEC_REG(45, 0, 0xffff) +#define av1_ref5_width AV1_DEC_REG(45, 16, 0xffff) + +#define av1_ref6_height AV1_DEC_REG(46, 0, 0xffff) +#define av1_ref6_width AV1_DEC_REG(46, 16, 0xffff) + +#define av1_mf2_last2_offset AV1_DEC_REG(47, 0, 0x1ff) +#define av1_mf2_last3_offset AV1_DEC_REG(47, 9, 0x1ff) +#define av1_mf2_golden_offset AV1_DEC_REG(47, 18, 0x1ff) +#define av1_qmlevel_y AV1_DEC_REG(47, 27, 0xf) + +#define av1_mf2_bwdref_offset AV1_DEC_REG(48, 0, 0x1ff) +#define av1_mf2_altref2_offset AV1_DEC_REG(48, 9, 0x1ff) +#define av1_mf2_altref_offset AV1_DEC_REG(48, 18, 0x1ff) +#define av1_qmlevel_u AV1_DEC_REG(48, 27, 0xf) + +#define av1_filt_ref_adj_6 AV1_DEC_REG(49, 0, 0x7f) +#define av1_filt_ref_adj_7 AV1_DEC_REG(49, 7, 0x7f) +#define av1_qmlevel_v AV1_DEC_REG(49, 14, 0xf) + +#define av1_superres_chroma_step AV1_DEC_REG(51, 0, 0x3fff) +#define av1_superres_luma_step AV1_DEC_REG(51, 14, 0x3fff) + +#define av1_superres_init_chroma_subpel_x AV1_DEC_REG(52, 0, 0x3fff) +#define av1_superres_init_luma_subpel_x AV1_DEC_REG(52, 14, 0x3fff) + +#define av1_cdef_chroma_secondary_strength AV1_DEC_REG(53, 0, 0xffff) +#define av1_cdef_luma_secondary_strength AV1_DEC_REG(53, 16, 0xffff) + +#define av1_apf_threshold AV1_DEC_REG(55, 0, 0xffff) +#define av1_apf_single_pu_mode AV1_DEC_REG(55, 30, 0x1) +#define av1_apf_disable AV1_DEC_REG(55, 30, 0x1) + +#define av1_dec_max_burst AV1_DEC_REG(58, 0, 0xff) +#define av1_dec_buswidth AV1_DEC_REG(58, 8, 0x7) +#define av1_dec_multicore_mode AV1_DEC_REG(58, 11, 0x3) +#define av1_dec_axi_wd_id_e AV1_DEC_REG(58, 13, 0x1) +#define av1_dec_axi_rd_id_e AV1_DEC_REG(58, 14, 0x1) +#define av1_dec_mc_polltime AV1_DEC_REG(58, 17, 0x3ff) +#define av1_dec_mc_pollmode AV1_DEC_REG(58, 27, 0x3) + +#define av1_filt_ref_adj_3 AV1_DEC_REG(59, 0, 0x3f) +#define av1_filt_ref_adj_2 AV1_DEC_REG(59, 7, 0x3f) +#define av1_filt_ref_adj_1 AV1_DEC_REG(59, 14, 0x3f) +#define av1_filt_ref_adj_0 AV1_DEC_REG(59, 21, 0x3f) +#define av1_ref0_sign_bias AV1_DEC_REG(59, 28, 0x1) +#define av1_ref1_sign_bias AV1_DEC_REG(59, 29, 0x1) +#define av1_ref2_sign_bias AV1_DEC_REG(59, 30, 0x1) +#define av1_ref3_sign_bias AV1_DEC_REG(59, 31, 0x1) + +#define av1_cur_last_roffset AV1_DEC_REG(184, 0, 0x1ff) +#define av1_cur_last_offset AV1_DEC_REG(184, 9, 0x1ff) +#define av1_mf3_last_offset AV1_DEC_REG(184, 18, 0x1ff) +#define av1_ref0_gm_mode AV1_DEC_REG(184, 27, 0x3) + +#define av1_cur_last2_roffset AV1_DEC_REG(185, 0, 0x1ff) +#define av1_cur_last2_offset AV1_DEC_REG(185, 9, 0x1ff) +#define av1_mf3_last2_offset AV1_DEC_REG(185, 18, 0x1ff) +#define av1_ref1_gm_mode AV1_DEC_REG(185, 27, 0x3) + +#define av1_cur_last3_roffset AV1_DEC_REG(186, 0, 0x1ff) +#define av1_cur_last3_offset AV1_DEC_REG(186, 9, 0x1ff) +#define av1_mf3_last3_offset AV1_DEC_REG(186, 18, 0x1ff) +#define av1_ref2_gm_mode AV1_DEC_REG(186, 27, 0x3) + +#define av1_cur_golden_roffset AV1_DEC_REG(187, 0, 0x1ff) +#define av1_cur_golden_offset AV1_DEC_REG(187, 9, 0x1ff) +#define av1_mf3_golden_offset AV1_DEC_REG(187, 18, 0x1ff) +#define av1_ref3_gm_mode AV1_DEC_REG(187, 27, 0x3) + +#define av1_cur_bwdref_roffset AV1_DEC_REG(188, 0, 0x1ff) +#define av1_cur_bwdref_offset AV1_DEC_REG(188, 9, 0x1ff) +#define av1_mf3_bwdref_offset AV1_DEC_REG(188, 18, 0x1ff) +#define av1_ref4_gm_mode AV1_DEC_REG(188, 27, 0x3) + +#define av1_cur_altref2_roffset AV1_DEC_REG(257, 0, 0x1ff) +#define av1_cur_altref2_offset AV1_DEC_REG(257, 9, 0x1ff) +#define av1_mf3_altref2_offset AV1_DEC_REG(257, 18, 0x1ff) +#define av1_ref5_gm_mode AV1_DEC_REG(257, 27, 0x3) + +#define av1_strm_buffer_len AV1_DEC_REG(258, 0, 0xffffffff) + +#define av1_strm_start_offset AV1_DEC_REG(259, 0, 0xffffffff) + +#define av1_ppd_blend_exist AV1_DEC_REG(260, 21, 0x1) +#define av1_ppd_dith_exist AV1_DEC_REG(260, 23, 0x1) +#define av1_ablend_crop_e AV1_DEC_REG(260, 24, 0x1) +#define av1_pp_format_p010_e AV1_DEC_REG(260, 25, 0x1) +#define av1_pp_format_customer1_e AV1_DEC_REG(260, 26, 0x1) +#define av1_pp_crop_exist AV1_DEC_REG(260, 27, 0x1) +#define av1_pp_up_level AV1_DEC_REG(260, 28, 0x1) +#define av1_pp_down_level AV1_DEC_REG(260, 29, 0x3) +#define av1_pp_exist AV1_DEC_REG(260, 31, 0x1) + +#define av1_cur_altref_roffset AV1_DEC_REG(262, 0, 0x1ff) +#define av1_cur_altref_offset AV1_DEC_REG(262, 9, 0x1ff) +#define av1_mf3_altref_offset AV1_DEC_REG(262, 18, 0x1ff) +#define av1_ref6_gm_mode AV1_DEC_REG(262, 27, 0x3) + +#define av1_cdef_luma_primary_strength AV1_DEC_REG(263, 0, 0xffffffff) + +#define av1_cdef_chroma_primary_strength AV1_DEC_REG(264, 0, 0xffffffff) + +#define av1_axi_arqos AV1_DEC_REG(265, 0, 0xf) +#define av1_axi_awqos AV1_DEC_REG(265, 4, 0xf) +#define av1_axi_wr_ostd_threshold AV1_DEC_REG(265, 8, 0x3ff) +#define av1_axi_rd_ostd_threshold AV1_DEC_REG(265, 18, 0x3ff) +#define av1_axi_wr_4k_dis AV1_DEC_REG(265, 31, 0x1) + +#define av1_128bit_mode AV1_DEC_REG(266, 5, 0x1) +#define av1_wr_shaper_bypass AV1_DEC_REG(266, 10, 0x1) +#define av1_error_conceal_e AV1_DEC_REG(266, 30, 0x1) + +#define av1_superres_chroma_step_invra AV1_DEC_REG(298, 0, 0xffff) +#define av1_superres_luma_step_invra AV1_DEC_REG(298, 16, 0xffff) + +#define av1_dec_alignment AV1_DEC_REG(314, 0, 0xffff) + +#define av1_ext_timeout_cycles AV1_DEC_REG(318, 0, 0x7fffffff) +#define av1_ext_timeout_override_e AV1_DEC_REG(318, 31, 0x1) + +#define av1_timeout_cycles AV1_DEC_REG(319, 0, 0x7fffffff) +#define av1_timeout_override_e AV1_DEC_REG(319, 31, 0x1) + +#define av1_pp_out_e AV1_DEC_REG(320, 0, 0x1) +#define av1_pp_cr_first AV1_DEC_REG(320, 1, 0x1) +#define av1_pp_out_mode AV1_DEC_REG(320, 2, 0x1) +#define av1_pp_out_tile_e AV1_DEC_REG(320, 3, 0x1) +#define av1_pp_status AV1_DEC_REG(320, 4, 0xf) +#define av1_pp_in_blk_size AV1_DEC_REG(320, 8, 0x7) +#define av1_pp_out_p010_fmt AV1_DEC_REG(320, 11, 0x3) +#define av1_pp_out_rgb_fmt AV1_DEC_REG(320, 13, 0x1f) +#define av1_rgb_range_max AV1_DEC_REG(320, 18, 0xfff) +#define av1_pp_rgb_planar AV1_DEC_REG(320, 30, 0x1) + +#define av1_scale_hratio AV1_DEC_REG(322, 0, 0x3ffff) +#define av1_pp_out_format AV1_DEC_REG(322, 18, 0x1f) +#define av1_ver_scale_mode AV1_DEC_REG(322, 23, 0x3) +#define av1_hor_scale_mode AV1_DEC_REG(322, 25, 0x3) +#define av1_pp_in_format AV1_DEC_REG(322, 27, 0x1f) + +#define av1_pp_out_c_stride AV1_DEC_REG(329, 0, 0xffff) +#define av1_pp_out_y_stride AV1_DEC_REG(329, 16, 0xffff) + +#define av1_pp_in_height AV1_DEC_REG(331, 0, 0xffff) +#define av1_pp_in_width AV1_DEC_REG(331, 16, 0xffff) + +#define av1_pp_out_height AV1_DEC_REG(332, 0, 0xffff) +#define av1_pp_out_width AV1_DEC_REG(332, 16, 0xffff) + +#define av1_pp1_dup_ver AV1_DEC_REG(394, 0, 0xff) +#define av1_pp1_dup_hor AV1_DEC_REG(394, 8, 0xff) +#define av1_pp0_dup_ver AV1_DEC_REG(394, 16, 0xff) +#define av1_pp0_dup_hor AV1_DEC_REG(394, 24, 0xff) + +#define AV1_TILE_OUT_LU (AV1_SWREG(65)) +#define AV1_REFERENCE_Y(i) (AV1_SWREG(67) + ((i) * 0x8)) +#define AV1_SEGMENTATION (AV1_SWREG(81)) +#define AV1_GLOBAL_MODEL (AV1_SWREG(83)) +#define AV1_CDEF_COL (AV1_SWREG(85)) +#define AV1_SR_COL (AV1_SWREG(89)) +#define AV1_LR_COL (AV1_SWREG(91)) +#define AV1_FILM_GRAIN (AV1_SWREG(95)) +#define AV1_TILE_OUT_CH (AV1_SWREG(99)) +#define AV1_REFERENCE_CB(i) (AV1_SWREG(101) + ((i) * 0x8)) +#define AV1_TILE_OUT_MV (AV1_SWREG(133)) +#define AV1_REFERENCE_MV(i) (AV1_SWREG(135) + ((i) * 0x8)) +#define AV1_TILE_BASE (AV1_SWREG(167)) +#define AV1_INPUT_STREAM (AV1_SWREG(169)) +#define AV1_PROP_TABLE_OUT (AV1_SWREG(171)) +#define AV1_PROP_TABLE (AV1_SWREG(173)) +#define AV1_MC_SYNC_CURR (AV1_SWREG(175)) +#define AV1_MC_SYNC_LEFT (AV1_SWREG(177)) +#define AV1_DB_DATA_COL (AV1_SWREG(179)) +#define AV1_DB_CTRL_COL (AV1_SWREG(183)) +#define AV1_PP_OUT_LU (AV1_SWREG(326)) +#define AV1_PP_OUT_CH (AV1_SWREG(328)) + +#endif /* _ROCKCHIP_VPU981_REGS_H_ */ diff --git a/drivers/media/platform/verisilicon/rockchip_vpu_hw.c b/drivers/media/platform/verisilicon/rockchip_vpu_hw.c index 8de6fd2e8eefa72227789d26f8c8d28aec1cb414..816ffa905a4bb4e690f9b56217e312768a63c70c 100644 --- a/drivers/media/platform/verisilicon/rockchip_vpu_hw.c +++ b/drivers/media/platform/verisilicon/rockchip_vpu_hw.c @@ -13,9 +13,13 @@ #include "hantro_g1_regs.h" #include "hantro_h1_regs.h" #include "rockchip_vpu2_regs.h" +#include "rockchip_vpu981_regs.h" #define RK3066_ACLK_MAX_FREQ (300 * 1000 * 1000) #define RK3288_ACLK_MAX_FREQ (400 * 1000 * 1000) +#define RK3588_ACLK_MAX_FREQ (300 * 1000 * 1000) + +#define ROCKCHIP_VPU981_MIN_SIZE 64 /* * Supported formats. @@ -74,6 +78,37 @@ static const struct hantro_fmt rockchip_vpu1_postproc_fmts[] = { }, }; +static const struct hantro_fmt rockchip_vpu981_postproc_fmts[] = { + { + .fourcc = V4L2_PIX_FMT_NV12, + .codec_mode = HANTRO_MODE_NONE, + .match_depth = true, + .postprocessed = true, + .frmsize = { + .min_width = ROCKCHIP_VPU981_MIN_SIZE, + .max_width = FMT_UHD_WIDTH, + .step_width = MB_DIM, + .min_height = ROCKCHIP_VPU981_MIN_SIZE, + .max_height = FMT_UHD_HEIGHT, + .step_height = MB_DIM, + }, + }, + { + .fourcc = V4L2_PIX_FMT_P010, + .codec_mode = HANTRO_MODE_NONE, + .match_depth = true, + .postprocessed = true, + .frmsize = { + .min_width = ROCKCHIP_VPU981_MIN_SIZE, + .max_width = FMT_UHD_WIDTH, + .step_width = MB_DIM, + .min_height = ROCKCHIP_VPU981_MIN_SIZE, + .max_height = FMT_UHD_HEIGHT, + .step_height = MB_DIM, + }, + }, +}; + static const struct hantro_fmt rk3066_vpu_dec_fmts[] = { { .fourcc = V4L2_PIX_FMT_NV12, @@ -277,6 +312,48 @@ static const struct hantro_fmt rk3399_vpu_dec_fmts[] = { }, }; +static const struct hantro_fmt rockchip_vpu981_dec_fmts[] = { + { + .fourcc = V4L2_PIX_FMT_NV12_4L4, + .codec_mode = HANTRO_MODE_NONE, + .match_depth = true, + .frmsize = { + .min_width = ROCKCHIP_VPU981_MIN_SIZE, + .max_width = FMT_UHD_WIDTH, + .step_width = MB_DIM, + .min_height = ROCKCHIP_VPU981_MIN_SIZE, + .max_height = FMT_UHD_HEIGHT, + .step_height = MB_DIM, + }, + }, + { + .fourcc = V4L2_PIX_FMT_NV15_4L4, + .codec_mode = HANTRO_MODE_NONE, + .match_depth = true, + .frmsize = { + .min_width = ROCKCHIP_VPU981_MIN_SIZE, + .max_width = FMT_UHD_WIDTH, + .step_width = MB_DIM, + .min_height = ROCKCHIP_VPU981_MIN_SIZE, + .max_height = FMT_UHD_HEIGHT, + .step_height = MB_DIM, + }, + }, + { + .fourcc = V4L2_PIX_FMT_AV1_FRAME, + .codec_mode = HANTRO_MODE_AV1_DEC, + .max_depth = 2, + .frmsize = { + .min_width = ROCKCHIP_VPU981_MIN_SIZE, + .max_width = FMT_UHD_WIDTH, + .step_width = MB_DIM, + .min_height = ROCKCHIP_VPU981_MIN_SIZE, + .max_height = FMT_UHD_HEIGHT, + .step_height = MB_DIM, + }, + }, +}; + static irqreturn_t rockchip_vpu1_vepu_irq(int irq, void *dev_id) { struct hantro_dev *vpu = dev_id; @@ -331,6 +408,24 @@ static irqreturn_t rockchip_vpu2_vepu_irq(int irq, void *dev_id) return IRQ_HANDLED; } +static irqreturn_t rk3588_vpu981_irq(int irq, void *dev_id) +{ + struct hantro_dev *vpu = dev_id; + enum vb2_buffer_state state; + u32 status; + + status = vdpu_read(vpu, AV1_REG_INTERRUPT); + state = (status & AV1_REG_INTERRUPT_DEC_RDY_INT) ? + VB2_BUF_STATE_DONE : VB2_BUF_STATE_ERROR; + + vdpu_write(vpu, 0, AV1_REG_INTERRUPT); + vdpu_write(vpu, AV1_REG_CONFIG_DEC_CLK_GATE_E, AV1_REG_CONFIG); + + hantro_irq_done(vpu, state); + + return IRQ_HANDLED; +} + static int rk3036_vpu_hw_init(struct hantro_dev *vpu) { /* Bump ACLK to max. possible freq. to improve performance. */ @@ -346,6 +441,13 @@ static int rk3066_vpu_hw_init(struct hantro_dev *vpu) return 0; } +static int rk3588_vpu981_hw_init(struct hantro_dev *vpu) +{ + /* Bump ACLKs to max. possible freq. to improve performance. */ + clk_set_rate(vpu->clocks[0].clk, RK3588_ACLK_MAX_FREQ); + return 0; +} + static int rockchip_vpu_hw_init(struct hantro_dev *vpu) { /* Bump ACLK to max. possible freq. to improve performance. */ @@ -498,6 +600,14 @@ static const struct hantro_codec_ops rk3568_vepu_codec_ops[] = { }, }; +static const struct hantro_codec_ops rk3588_vpu981_codec_ops[] = { + [HANTRO_MODE_AV1_DEC] = { + .run = rockchip_vpu981_av1_dec_run, + .init = rockchip_vpu981_av1_dec_init, + .exit = rockchip_vpu981_av1_dec_exit, + .done = rockchip_vpu981_av1_dec_done, + }, +}; /* * VPU variant. */ @@ -529,10 +639,18 @@ static const char * const rk3066_vpu_clk_names[] = { "aclk_vepu", "hclk_vepu" }; +static const struct hantro_irq rk3588_vpu981_irqs[] = { + { "vdpu", rk3588_vpu981_irq }, +}; + static const char * const rockchip_vpu_clk_names[] = { "aclk", "hclk" }; +static const char * const rk3588_vpu981_vpu_clk_names[] = { + "aclk", "hclk", "aclk_vdpu_root", "hclk_vdpu_root" +}; + /* VDPU1/VEPU1 */ const struct hantro_variant rk3036_vpu_variant = { @@ -678,3 +796,19 @@ const struct hantro_variant px30_vpu_variant = { .clk_names = rockchip_vpu_clk_names, .num_clocks = ARRAY_SIZE(rockchip_vpu_clk_names) }; + +const struct hantro_variant rk3588_vpu981_variant = { + .dec_offset = 0x0, + .dec_fmts = rockchip_vpu981_dec_fmts, + .num_dec_fmts = ARRAY_SIZE(rockchip_vpu981_dec_fmts), + .postproc_fmts = rockchip_vpu981_postproc_fmts, + .num_postproc_fmts = ARRAY_SIZE(rockchip_vpu981_postproc_fmts), + .postproc_ops = &rockchip_vpu981_postproc_ops, + .codec = HANTRO_AV1_DECODER, + .codec_ops = rk3588_vpu981_codec_ops, + .irqs = rk3588_vpu981_irqs, + .num_irqs = ARRAY_SIZE(rk3588_vpu981_irqs), + .init = rk3588_vpu981_hw_init, + .clk_names = rk3588_vpu981_vpu_clk_names, + .num_clocks = ARRAY_SIZE(rk3588_vpu981_vpu_clk_names) +}; diff --git a/drivers/media/platform/via/via-camera.c b/drivers/media/platform/via/via-camera.c index 450254403fa8914a80c244b897fdd1ab7ca22ed5..4cb8f29e2f14aa4c6009e752110a58f979ab316f 100644 --- a/drivers/media/platform/via/via-camera.c +++ b/drivers/media/platform/via/via-camera.c @@ -11,7 +11,7 @@ #include #include #include -#include +#include #include #include #include @@ -26,7 +26,6 @@ #include #include #include -#include #include #ifdef CONFIG_X86 @@ -71,8 +70,8 @@ struct via_camera { /* * GPIO info for power/reset management */ - int power_gpio; - int reset_gpio; + struct gpio_desc *power_gpio; + struct gpio_desc *reset_gpio; /* * I/O memory stuff. */ @@ -180,27 +179,19 @@ static struct via_format *via_find_format(u32 pixelformat) */ static int via_sensor_power_setup(struct via_camera *cam) { - int ret; + struct device *dev = &cam->platdev->dev; + + cam->power_gpio = devm_gpiod_get(dev, "VGPIO3", GPIOD_OUT_LOW); + if (IS_ERR(cam->power_gpio)) + return dev_err_probe(dev, PTR_ERR(cam->power_gpio), + "failed to get power GPIO"); + + /* Request the reset line asserted */ + cam->reset_gpio = devm_gpiod_get(dev, "VGPIO2", GPIOD_OUT_HIGH); + if (IS_ERR(cam->reset_gpio)) + return dev_err_probe(dev, PTR_ERR(cam->reset_gpio), + "failed to get reset GPIO"); - cam->power_gpio = viafb_gpio_lookup("VGPIO3"); - cam->reset_gpio = viafb_gpio_lookup("VGPIO2"); - if (!gpio_is_valid(cam->power_gpio) || !gpio_is_valid(cam->reset_gpio)) { - dev_err(&cam->platdev->dev, "Unable to find GPIO lines\n"); - return -EINVAL; - } - ret = gpio_request(cam->power_gpio, "viafb-camera"); - if (ret) { - dev_err(&cam->platdev->dev, "Unable to request power GPIO\n"); - return ret; - } - ret = gpio_request(cam->reset_gpio, "viafb-camera"); - if (ret) { - dev_err(&cam->platdev->dev, "Unable to request reset GPIO\n"); - gpio_free(cam->power_gpio); - return ret; - } - gpio_direction_output(cam->power_gpio, 0); - gpio_direction_output(cam->reset_gpio, 0); return 0; } @@ -209,25 +200,23 @@ static int via_sensor_power_setup(struct via_camera *cam) */ static void via_sensor_power_up(struct via_camera *cam) { - gpio_set_value(cam->power_gpio, 1); - gpio_set_value(cam->reset_gpio, 0); + gpiod_set_value(cam->power_gpio, 1); + gpiod_set_value(cam->reset_gpio, 1); msleep(20); /* Probably excessive */ - gpio_set_value(cam->reset_gpio, 1); + gpiod_set_value(cam->reset_gpio, 0); msleep(20); } static void via_sensor_power_down(struct via_camera *cam) { - gpio_set_value(cam->power_gpio, 0); - gpio_set_value(cam->reset_gpio, 0); + gpiod_set_value(cam->power_gpio, 0); + gpiod_set_value(cam->reset_gpio, 1); } static void via_sensor_power_release(struct via_camera *cam) { via_sensor_power_down(cam); - gpio_free(cam->power_gpio); - gpio_free(cam->reset_gpio); } /* --------------------------------------------------------------------------*/ diff --git a/drivers/media/platform/video-mux.c b/drivers/media/platform/video-mux.c index 1d9f32e5a91716a10bbbd470e9d49e0608f89c18..6d273abfe16cf5d3fd0c13f55e927add202091d0 100644 --- a/drivers/media/platform/video-mux.c +++ b/drivers/media/platform/video-mux.c @@ -24,7 +24,6 @@ struct video_mux { struct v4l2_subdev subdev; struct v4l2_async_notifier notifier; struct media_pad *pads; - struct v4l2_mbus_framefmt *format_mbus; struct mux_control *mux; struct mutex lock; int active; @@ -71,6 +70,9 @@ static int video_mux_link_setup(struct media_entity *entity, mutex_lock(&vmux->lock); if (flags & MEDIA_LNK_FL_ENABLED) { + struct v4l2_subdev_state *sd_state; + struct v4l2_mbus_framefmt *source_mbusformat; + if (vmux->active == local->index) goto out; @@ -86,7 +88,12 @@ static int video_mux_link_setup(struct media_entity *entity, vmux->active = local->index; /* Propagate the active format to the source */ - vmux->format_mbus[source_pad] = vmux->format_mbus[vmux->active]; + sd_state = v4l2_subdev_lock_and_get_active_state(sd); + source_mbusformat = v4l2_subdev_get_pad_format(sd, sd_state, + source_pad); + *source_mbusformat = *v4l2_subdev_get_pad_format(sd, sd_state, + vmux->active); + v4l2_subdev_unlock_state(sd_state); } else { if (vmux->active != local->index) goto out; @@ -138,40 +145,6 @@ static const struct v4l2_subdev_video_ops video_mux_subdev_video_ops = { .s_stream = video_mux_s_stream, }; -static struct v4l2_mbus_framefmt * -__video_mux_get_pad_format(struct v4l2_subdev *sd, - struct v4l2_subdev_state *sd_state, - unsigned int pad, u32 which) -{ - struct video_mux *vmux = v4l2_subdev_to_video_mux(sd); - - switch (which) { - case V4L2_SUBDEV_FORMAT_TRY: - return v4l2_subdev_get_try_format(sd, sd_state, pad); - case V4L2_SUBDEV_FORMAT_ACTIVE: - return &vmux->format_mbus[pad]; - default: - return NULL; - } -} - -static int video_mux_get_format(struct v4l2_subdev *sd, - struct v4l2_subdev_state *sd_state, - struct v4l2_subdev_format *sdformat) -{ - struct video_mux *vmux = v4l2_subdev_to_video_mux(sd); - - mutex_lock(&vmux->lock); - - sdformat->format = *__video_mux_get_pad_format(sd, sd_state, - sdformat->pad, - sdformat->which); - - mutex_unlock(&vmux->lock); - - return 0; -} - static int video_mux_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_state *sd_state, struct v4l2_subdev_format *sdformat) @@ -181,14 +154,11 @@ static int video_mux_set_format(struct v4l2_subdev *sd, struct media_pad *pad = &vmux->pads[sdformat->pad]; u16 source_pad = sd->entity.num_pads - 1; - mbusformat = __video_mux_get_pad_format(sd, sd_state, sdformat->pad, - sdformat->which); + mbusformat = v4l2_subdev_get_pad_format(sd, sd_state, sdformat->pad); if (!mbusformat) return -EINVAL; - source_mbusformat = __video_mux_get_pad_format(sd, sd_state, - source_pad, - sdformat->which); + source_mbusformat = v4l2_subdev_get_pad_format(sd, sd_state, source_pad); if (!source_mbusformat) return -EINVAL; @@ -298,7 +268,8 @@ static int video_mux_set_format(struct v4l2_subdev *sd, /* Source pad mirrors active sink pad, no limitations on sink pads */ if ((pad->flags & MEDIA_PAD_FL_SOURCE) && vmux->active >= 0) - sdformat->format = vmux->format_mbus[vmux->active]; + sdformat->format = *v4l2_subdev_get_pad_format(sd, sd_state, + vmux->active); *mbusformat = sdformat->format; @@ -321,7 +292,7 @@ static int video_mux_init_cfg(struct v4l2_subdev *sd, mutex_lock(&vmux->lock); for (i = 0; i < sd->entity.num_pads; i++) { - mbusformat = v4l2_subdev_get_try_format(sd, sd_state, i); + mbusformat = v4l2_subdev_get_pad_format(sd, sd_state, i); *mbusformat = video_mux_format_mbus_default; } @@ -332,7 +303,7 @@ static int video_mux_init_cfg(struct v4l2_subdev *sd, static const struct v4l2_subdev_pad_ops video_mux_pad_ops = { .init_cfg = video_mux_init_cfg, - .get_fmt = video_mux_get_format, + .get_fmt = v4l2_subdev_get_fmt, .set_fmt = video_mux_set_format, }; @@ -389,7 +360,7 @@ static int video_mux_async_register(struct video_mux *vmux, ret = PTR_ERR(asd); /* OK if asd already exists */ if (ret != -EEXIST) - return ret; + goto err_nf_cleanup; } } @@ -397,9 +368,19 @@ static int video_mux_async_register(struct video_mux *vmux, ret = v4l2_async_subdev_nf_register(&vmux->subdev, &vmux->notifier); if (ret) - return ret; + goto err_nf_cleanup; + + ret = v4l2_async_register_subdev(&vmux->subdev); + if (ret) + goto err_nf_unregister; - return v4l2_async_register_subdev(&vmux->subdev); + return 0; + +err_nf_unregister: + v4l2_async_nf_unregister(&vmux->notifier); +err_nf_cleanup: + v4l2_async_nf_cleanup(&vmux->notifier); + return ret; } static int video_mux_probe(struct platform_device *pdev) @@ -452,17 +433,9 @@ static int video_mux_probe(struct platform_device *pdev) if (!vmux->pads) return -ENOMEM; - vmux->format_mbus = devm_kcalloc(dev, num_pads, - sizeof(*vmux->format_mbus), - GFP_KERNEL); - if (!vmux->format_mbus) - return -ENOMEM; - - for (i = 0; i < num_pads; i++) { + for (i = 0; i < num_pads; i++) vmux->pads[i].flags = (i < num_pads - 1) ? MEDIA_PAD_FL_SINK : MEDIA_PAD_FL_SOURCE; - vmux->format_mbus[i] = video_mux_format_mbus_default; - } vmux->subdev.entity.function = MEDIA_ENT_F_VID_MUX; ret = media_entity_pads_init(&vmux->subdev.entity, num_pads, @@ -472,12 +445,20 @@ static int video_mux_probe(struct platform_device *pdev) vmux->subdev.entity.ops = &video_mux_ops; + ret = v4l2_subdev_init_finalize(&vmux->subdev); + if (ret < 0) + goto err_entity_cleanup; + ret = video_mux_async_register(vmux, num_pads - 1); - if (ret) { - v4l2_async_nf_unregister(&vmux->notifier); - v4l2_async_nf_cleanup(&vmux->notifier); - } + if (ret) + goto err_subdev_cleanup; + + return 0; +err_subdev_cleanup: + v4l2_subdev_cleanup(&vmux->subdev); +err_entity_cleanup: + media_entity_cleanup(&vmux->subdev.entity); return ret; } @@ -489,6 +470,7 @@ static void video_mux_remove(struct platform_device *pdev) v4l2_async_nf_unregister(&vmux->notifier); v4l2_async_nf_cleanup(&vmux->notifier); v4l2_async_unregister_subdev(sd); + v4l2_subdev_cleanup(sd); media_entity_cleanup(&sd->entity); } diff --git a/drivers/media/radio/Kconfig b/drivers/media/radio/Kconfig index 616a38feb641e5ac34aafca21c9c5748b8cac6eb..d52eccdc7eb9d39151b32e1bca26bc082fcddffd 100644 --- a/drivers/media/radio/Kconfig +++ b/drivers/media/radio/Kconfig @@ -15,7 +15,7 @@ if RADIO_ADAPTERS config RADIO_MAXIRADIO tristate "Guillemot MAXI Radio FM 2000 radio" - depends on PCI + depends on PCI && HAS_IOPORT select RADIO_TEA575X help Choose Y here if you have this radio card. This card may also be @@ -232,6 +232,7 @@ source "drivers/media/radio/wl128x/Kconfig" menuconfig V4L_RADIO_ISA_DRIVERS bool "ISA radio devices" depends on ISA || COMPILE_TEST + depends on HAS_IOPORT help Say Y here to enable support for these ISA drivers. @@ -240,6 +241,7 @@ if V4L_RADIO_ISA_DRIVERS config RADIO_AZTECH tristate "Aztech/Packard Bell Radio" depends on ISA || COMPILE_TEST + depends on HAS_IOPORT select RADIO_ISA help Choose Y here if you have one of these FM radio cards, and then fill @@ -260,6 +262,7 @@ config RADIO_AZTECH_PORT config RADIO_CADET tristate "ADS Cadet AM/FM Tuner" depends on ISA || COMPILE_TEST + depends on HAS_IOPORT help Choose Y here if you have one of these AM/FM radio cards, and then fill in the port address below. @@ -270,6 +273,7 @@ config RADIO_CADET config RADIO_GEMTEK tristate "GemTek Radio card (or compatible) support" depends on ISA || COMPILE_TEST + depends on HAS_IOPORT select RADIO_ISA help Choose Y here if you have this FM radio card, and then fill in the @@ -309,6 +313,7 @@ config RADIO_GEMTEK_PROBE config RADIO_ISA depends on ISA || COMPILE_TEST + depends on HAS_IOPORT tristate config RADIO_MIROPCM20 @@ -329,6 +334,7 @@ config RADIO_MIROPCM20 config RADIO_RTRACK tristate "AIMSlab RadioTrack (aka RadioReveal) support" depends on ISA || COMPILE_TEST + depends on HAS_IOPORT select RADIO_ISA help Choose Y here if you have one of these FM radio cards, and then fill @@ -383,6 +389,7 @@ config RADIO_RTRACK_PORT config RADIO_SF16FMI tristate "SF16-FMI/SF16-FMP/SF16-FMD Radio" depends on ISA || COMPILE_TEST + depends on HAS_IOPORT help Choose Y here if you have one of these FM radio cards. @@ -392,6 +399,7 @@ config RADIO_SF16FMI config RADIO_SF16FMR2 tristate "SF16-FMR2/SF16-FMD2 Radio" depends on ISA || COMPILE_TEST + depends on HAS_IOPORT select RADIO_TEA575X help Choose Y here if you have one of these FM radio cards. @@ -402,6 +410,7 @@ config RADIO_SF16FMR2 config RADIO_TERRATEC tristate "TerraTec ActiveRadio ISA Standalone" depends on ISA || COMPILE_TEST + depends on HAS_IOPORT select RADIO_ISA help Choose Y here if you have this FM radio card. @@ -416,6 +425,7 @@ config RADIO_TERRATEC config RADIO_TRUST tristate "Trust FM radio card" depends on ISA || COMPILE_TEST + depends on HAS_IOPORT select RADIO_ISA help This is a driver for the Trust FM radio cards. Say Y if you have @@ -439,6 +449,7 @@ config RADIO_TRUST_PORT config RADIO_TYPHOON tristate "Typhoon Radio (a.k.a. EcoRadio)" depends on ISA || COMPILE_TEST + depends on HAS_IOPORT select RADIO_ISA help Choose Y here if you have one of these FM radio cards, and then fill @@ -473,6 +484,7 @@ config RADIO_TYPHOON_PORT config RADIO_ZOLTRIX tristate "Zoltrix Radio" depends on ISA || COMPILE_TEST + depends on HAS_IOPORT select RADIO_ISA help Choose Y here if you have one of these FM radio cards, and then fill diff --git a/drivers/media/radio/radio-tea5764.c b/drivers/media/radio/radio-tea5764.c index 2cb74afba49c1524c0562f91785a6430593b7fbf..14e7dd3889ff004ec41757066df8a62c9420e8c6 100644 --- a/drivers/media/radio/radio-tea5764.c +++ b/drivers/media/radio/radio-tea5764.c @@ -511,7 +511,7 @@ static struct i2c_driver tea5764_i2c_driver = { .driver = { .name = "radio-tea5764", }, - .probe_new = tea5764_i2c_probe, + .probe = tea5764_i2c_probe, .remove = tea5764_i2c_remove, .id_table = tea5764_id, }; diff --git a/drivers/media/radio/saa7706h.c b/drivers/media/radio/saa7706h.c index 3c758a98334450c37942be4123d6b50f33a82c8d..91345198bbf10b7a55ec81f28f3fb0f2f8f43147 100644 --- a/drivers/media/radio/saa7706h.c +++ b/drivers/media/radio/saa7706h.c @@ -405,7 +405,7 @@ static struct i2c_driver saa7706h_driver = { .driver = { .name = DRIVER_NAME, }, - .probe_new = saa7706h_probe, + .probe = saa7706h_probe, .remove = saa7706h_remove, .id_table = saa7706h_id, }; diff --git a/drivers/media/radio/si470x/radio-si470x-i2c.c b/drivers/media/radio/si470x/radio-si470x-i2c.c index a6ad926c2b4e87e53d7589d3612e90459e1ce5b0..fd449e42c191301a51b9a2e047b551124b804758 100644 --- a/drivers/media/radio/si470x/radio-si470x-i2c.c +++ b/drivers/media/radio/si470x/radio-si470x-i2c.c @@ -532,7 +532,7 @@ static struct i2c_driver si470x_i2c_driver = { .pm = &si470x_i2c_pm, #endif }, - .probe_new = si470x_i2c_probe, + .probe = si470x_i2c_probe, .remove = si470x_i2c_remove, .id_table = si470x_i2c_id, }; diff --git a/drivers/media/radio/si4713/si4713.c b/drivers/media/radio/si4713/si4713.c index 93d847c294e8156265a37b20eeda7de3ec6736ba..ddaf7a60b7d019ab8ff23e80df6064460ff56874 100644 --- a/drivers/media/radio/si4713/si4713.c +++ b/drivers/media/radio/si4713/si4713.c @@ -1657,7 +1657,7 @@ static struct i2c_driver si4713_i2c_driver = { .name = "si4713", .of_match_table = of_match_ptr(si4713_of_match), }, - .probe_new = si4713_probe, + .probe = si4713_probe, .remove = si4713_remove, .id_table = si4713_id, }; diff --git a/drivers/media/radio/tef6862.c b/drivers/media/radio/tef6862.c index d14c97d79e8346effae253d88832c0a3957453c9..215168aa1588eff2a10bfa34c15b37e353c345d7 100644 --- a/drivers/media/radio/tef6862.c +++ b/drivers/media/radio/tef6862.c @@ -183,7 +183,7 @@ static struct i2c_driver tef6862_driver = { .driver = { .name = DRIVER_NAME, }, - .probe_new = tef6862_probe, + .probe = tef6862_probe, .remove = tef6862_remove, .id_table = tef6862_id, }; diff --git a/drivers/media/radio/wl128x/fmdrv_common.c b/drivers/media/radio/wl128x/fmdrv_common.c index cbd49dff6d74c9fe2d7323472b39d5927a5025e0..b31b7ed60bbebae8f929d4c4772e2b49bbb98683 100644 --- a/drivers/media/radio/wl128x/fmdrv_common.c +++ b/drivers/media/radio/wl128x/fmdrv_common.c @@ -1234,9 +1234,8 @@ static int fm_download_firmware(struct fmdev *fmdev, const u8 *fw_name) struct bts_action *action; struct bts_action_delay *delay; u8 *fw_data; - int ret, fw_len, cmd_cnt; + int ret, fw_len; - cmd_cnt = 0; set_bit(FM_FW_DW_INPROGRESS, &fmdev->flag); ret = request_firmware(&fw_entry, fw_name, @@ -1272,7 +1271,6 @@ static int fm_download_firmware(struct fmdev *fmdev, const u8 *fw_name) if (ret) goto rel_fw; - cmd_cnt++; break; case ACTION_DELAY: /* Delay */ @@ -1284,7 +1282,7 @@ static int fm_download_firmware(struct fmdev *fmdev, const u8 *fw_name) fw_data += (sizeof(struct bts_action) + (action->size)); fw_len -= (sizeof(struct bts_action) + (action->size)); } - fmdbg("Firmware commands(%d) loaded to chip\n", cmd_cnt); + fmdbg("Transfered only %d of %d bytes of the firmware to chip\n", fw_entry->size - fw_len, fw_entry->size); rel_fw: release_firmware(fw_entry); clear_bit(FM_FW_DW_INPROGRESS, &fmdev->flag); diff --git a/drivers/media/rc/Kconfig b/drivers/media/rc/Kconfig index ac4172feb6f9411c476d120ef5e738e2dedbf75d..922c790b577efc4b605164a415cae8e66c1255bf 100644 --- a/drivers/media/rc/Kconfig +++ b/drivers/media/rc/Kconfig @@ -148,6 +148,7 @@ if RC_DEVICES config IR_ENE tristate "ENE eHome Receiver/Transceiver (pnp id: ENE0100/ENE02xxx)" depends on PNP || COMPILE_TEST + depends on HAS_IOPORT help Say Y here to enable support for integrated infrared receiver /transceiver made by ENE. @@ -161,6 +162,7 @@ config IR_ENE config IR_FINTEK tristate "Fintek Consumer Infrared Transceiver" depends on PNP || COMPILE_TEST + depends on HAS_IOPORT help Say Y here to enable support for integrated infrared receiver /transceiver made by Fintek. This chip is found on assorted @@ -249,6 +251,7 @@ config IR_IMON_RAW config IR_ITE_CIR tristate "ITE Tech Inc. IT8712/IT8512 Consumer Infrared Transceiver" depends on PNP || COMPILE_TEST + depends on HAS_IOPORT help Say Y here to enable support for integrated infrared receivers /transceivers made by ITE Tech Inc. These are found in @@ -301,6 +304,7 @@ config IR_MTK config IR_NUVOTON tristate "Nuvoton w836x7hg Consumer Infrared Transceiver" depends on PNP || COMPILE_TEST + depends on HAS_IOPORT help Say Y here to enable support for integrated infrared receiver /transceiver made by Nuvoton (formerly Winbond). This chip is @@ -345,6 +349,7 @@ config IR_RX51 config IR_SERIAL tristate "Homebrew Serial Port Receiver" + depends on HAS_IOPORT help Say Y if you want to use Homebrew Serial Port Receivers and Transceivers. @@ -412,6 +417,7 @@ config IR_TTUSBIR config IR_WINBOND_CIR tristate "Winbond IR remote control" depends on (X86 && PNP) || COMPILE_TEST + depends on HAS_IOPORT select NEW_LEDS select LEDS_CLASS select BITREVERSE diff --git a/drivers/media/test-drivers/vidtv/vidtv_demod.c b/drivers/media/test-drivers/vidtv/vidtv_demod.c index b878db7986862630fb73cf1595875b4d2bcaab72..7a0cd9601917ff27f30f0b9319e486074a2a2d8c 100644 --- a/drivers/media/test-drivers/vidtv/vidtv_demod.c +++ b/drivers/media/test-drivers/vidtv/vidtv_demod.c @@ -449,7 +449,7 @@ static struct i2c_driver vidtv_demod_i2c_driver = { .name = "dvb_vidtv_demod", .suppress_bind_attrs = true, }, - .probe_new = vidtv_demod_i2c_probe, + .probe = vidtv_demod_i2c_probe, .remove = vidtv_demod_i2c_remove, .id_table = vidtv_demod_i2c_id_table, }; diff --git a/drivers/media/test-drivers/vidtv/vidtv_tuner.c b/drivers/media/test-drivers/vidtv/vidtv_tuner.c index 55a4387f3854e017cca6a46223cefa64bfdfb161..a748737d47f3b0a4d64a00c3ce12ed5d427910d0 100644 --- a/drivers/media/test-drivers/vidtv/vidtv_tuner.c +++ b/drivers/media/test-drivers/vidtv/vidtv_tuner.c @@ -425,7 +425,7 @@ static struct i2c_driver vidtv_tuner_i2c_driver = { .name = "dvb_vidtv_tuner", .suppress_bind_attrs = true, }, - .probe_new = vidtv_tuner_i2c_probe, + .probe = vidtv_tuner_i2c_probe, .remove = vidtv_tuner_i2c_remove, .id_table = vidtv_tuner_i2c_id_table, }; diff --git a/drivers/media/test-drivers/vivid/vivid-vid-cap.c b/drivers/media/test-drivers/vivid/vivid-vid-cap.c index 801286dc1448032b963ed5b1548fefab1f7b52fa..3a06df35a2d7ceeffb081ebd543efd2cd7abfbb9 100644 --- a/drivers/media/test-drivers/vivid/vivid-vid-cap.c +++ b/drivers/media/test-drivers/vivid/vivid-vid-cap.c @@ -21,13 +21,8 @@ #include "vivid-kthread-cap.h" #include "vivid-vid-cap.h" -/* The number of discrete webcam framesizes */ -#define VIVID_WEBCAM_SIZES 6 -/* The number of discrete webcam frameintervals */ -#define VIVID_WEBCAM_IVALS (VIVID_WEBCAM_SIZES * 2) - /* Sizes must be in increasing order */ -static const struct v4l2_frmsize_discrete webcam_sizes[VIVID_WEBCAM_SIZES] = { +static const struct v4l2_frmsize_discrete webcam_sizes[] = { { 320, 180 }, { 640, 360 }, { 640, 480 }, @@ -40,21 +35,43 @@ static const struct v4l2_frmsize_discrete webcam_sizes[VIVID_WEBCAM_SIZES] = { * Intervals must be in increasing order and there must be twice as many * elements in this array as there are in webcam_sizes. */ -static const struct v4l2_fract webcam_intervals[VIVID_WEBCAM_IVALS] = { +static const struct v4l2_fract webcam_intervals[] = { { 1, 1 }, { 1, 2 }, { 1, 4 }, { 1, 5 }, { 1, 10 }, { 2, 25 }, - { 1, 15 }, + { 1, 15 }, /* 7 - maximum for 2160p */ { 1, 25 }, - { 1, 30 }, + { 1, 30 }, /* 9 - maximum for 1080p */ { 1, 40 }, { 1, 50 }, - { 1, 60 }, + { 1, 60 }, /* 12 - maximum for 720p */ + { 1, 120 }, }; +/* Limit maximum FPS rates for high resolutions */ +#define IVAL_COUNT_720P 12 /* 720p and up is limited to 60 fps */ +#define IVAL_COUNT_1080P 9 /* 1080p and up is limited to 30 fps */ +#define IVAL_COUNT_2160P 7 /* 2160p and up is limited to 15 fps */ + +static inline unsigned int webcam_ival_count(const struct vivid_dev *dev, + unsigned int frmsize_idx) +{ + if (webcam_sizes[frmsize_idx].height >= 2160) + return IVAL_COUNT_2160P; + + if (webcam_sizes[frmsize_idx].height >= 1080) + return IVAL_COUNT_1080P; + + if (webcam_sizes[frmsize_idx].height >= 720) + return IVAL_COUNT_720P; + + /* For low resolutions, allow all FPS rates */ + return ARRAY_SIZE(webcam_intervals); +} + static int vid_cap_queue_setup(struct vb2_queue *vq, unsigned *nbuffers, unsigned *nplanes, unsigned sizes[], struct device *alloc_devs[]) @@ -560,7 +577,7 @@ int vivid_try_fmt_vid_cap(struct file *file, void *priv, if (vivid_is_webcam(dev)) { const struct v4l2_frmsize_discrete *sz = v4l2_find_nearest_size(webcam_sizes, - VIVID_WEBCAM_SIZES, width, + ARRAY_SIZE(webcam_sizes), width, height, mp->width, mp->height); w = sz->width; @@ -736,14 +753,16 @@ int vivid_s_fmt_vid_cap(struct file *file, void *priv, compose->height /= factor; } } else if (vivid_is_webcam(dev)) { + unsigned int ival_sz = webcam_ival_count(dev, dev->webcam_size_idx); + /* Guaranteed to be a match */ for (i = 0; i < ARRAY_SIZE(webcam_sizes); i++) if (webcam_sizes[i].width == mp->width && webcam_sizes[i].height == mp->height) break; dev->webcam_size_idx = i; - if (dev->webcam_ival_idx >= 2 * (VIVID_WEBCAM_SIZES - i)) - dev->webcam_ival_idx = 2 * (VIVID_WEBCAM_SIZES - i) - 1; + if (dev->webcam_ival_idx >= ival_sz) + dev->webcam_ival_idx = ival_sz - 1; vivid_update_format_cap(dev, false); } else { struct v4l2_rect r = { 0, 0, mp->width, mp->height }; @@ -1636,7 +1655,7 @@ int vidioc_enum_frameintervals(struct file *file, void *priv, break; if (i == ARRAY_SIZE(webcam_sizes)) return -EINVAL; - if (fival->index >= 2 * (VIVID_WEBCAM_SIZES - i)) + if (fival->index >= webcam_ival_count(dev, i)) return -EINVAL; fival->type = V4L2_FRMIVAL_TYPE_DISCRETE; fival->discrete = webcam_intervals[fival->index]; @@ -1663,7 +1682,7 @@ int vivid_vid_cap_s_parm(struct file *file, void *priv, struct v4l2_streamparm *parm) { struct vivid_dev *dev = video_drvdata(file); - unsigned ival_sz = 2 * (VIVID_WEBCAM_SIZES - dev->webcam_size_idx); + unsigned int ival_sz = webcam_ival_count(dev, dev->webcam_size_idx); struct v4l2_fract tpf; unsigned i; diff --git a/drivers/media/tuners/e4000.c b/drivers/media/tuners/e4000.c index 7c269f3159ef0a26a3b4b669bd7f821cf9b20f4e..3893a00c18ce1dc1785cdb2ba297e9962d0e9530 100644 --- a/drivers/media/tuners/e4000.c +++ b/drivers/media/tuners/e4000.c @@ -729,7 +729,7 @@ static struct i2c_driver e4000_driver = { .name = "e4000", .suppress_bind_attrs = true, }, - .probe_new = e4000_probe, + .probe = e4000_probe, .remove = e4000_remove, .id_table = e4000_id_table, }; diff --git a/drivers/media/tuners/fc2580.c b/drivers/media/tuners/fc2580.c index 3cd8279f4f2e0a4529ab47ce1346cea4835a5777..f6613dcf40a39f0a246b5f75dccac6acdf6257ac 100644 --- a/drivers/media/tuners/fc2580.c +++ b/drivers/media/tuners/fc2580.c @@ -610,7 +610,7 @@ static struct i2c_driver fc2580_driver = { .name = "fc2580", .suppress_bind_attrs = true, }, - .probe_new = fc2580_probe, + .probe = fc2580_probe, .remove = fc2580_remove, .id_table = fc2580_id_table, }; diff --git a/drivers/media/tuners/m88rs6000t.c b/drivers/media/tuners/m88rs6000t.c index 7d172a5a66d9bce8e478232e2056a5f0b213a675..2cd7f0e0c70d5d90e3d1f6d41e1e3f3e999fd623 100644 --- a/drivers/media/tuners/m88rs6000t.c +++ b/drivers/media/tuners/m88rs6000t.c @@ -718,7 +718,7 @@ static struct i2c_driver m88rs6000t_driver = { .driver = { .name = "m88rs6000t", }, - .probe_new = m88rs6000t_probe, + .probe = m88rs6000t_probe, .remove = m88rs6000t_remove, .id_table = m88rs6000t_id, }; diff --git a/drivers/media/tuners/mt2060.c b/drivers/media/tuners/mt2060.c index e5d86874adb34eaf2ebb34573328b28afb9b3c48..0278a9f0aeefacebe8f6029ecdca836e49703b45 100644 --- a/drivers/media/tuners/mt2060.c +++ b/drivers/media/tuners/mt2060.c @@ -524,7 +524,7 @@ static struct i2c_driver mt2060_driver = { .name = "mt2060", .suppress_bind_attrs = true, }, - .probe_new = mt2060_probe, + .probe = mt2060_probe, .remove = mt2060_remove, .id_table = mt2060_id_table, }; diff --git a/drivers/media/tuners/mxl301rf.c b/drivers/media/tuners/mxl301rf.c index c35442a77ae5157b2a23a390c0f049babfc61062..9b2b237745ae3932ab33ab5b964fa553dfa0c4a7 100644 --- a/drivers/media/tuners/mxl301rf.c +++ b/drivers/media/tuners/mxl301rf.c @@ -326,7 +326,7 @@ static struct i2c_driver mxl301rf_driver = { .driver = { .name = "mxl301rf", }, - .probe_new = mxl301rf_probe, + .probe = mxl301rf_probe, .remove = mxl301rf_remove, .id_table = mxl301rf_id, }; diff --git a/drivers/media/tuners/qm1d1b0004.c b/drivers/media/tuners/qm1d1b0004.c index 0b6f750c54add47565ff7ea9c69b8495df9bfc37..af2d3618b9d5b0a8130817aa3106c054fc279a22 100644 --- a/drivers/media/tuners/qm1d1b0004.c +++ b/drivers/media/tuners/qm1d1b0004.c @@ -253,7 +253,7 @@ static struct i2c_driver qm1d1b0004_driver = { .driver = { .name = "qm1d1b0004", }, - .probe_new = qm1d1b0004_probe, + .probe = qm1d1b0004_probe, .remove = qm1d1b0004_remove, .id_table = qm1d1b0004_id, }; diff --git a/drivers/media/tuners/qm1d1c0042.c b/drivers/media/tuners/qm1d1c0042.c index f9be7a721d2c549eeba7fad2672db26a31321870..ce7223315b0cf4dd7b86d5f2e112966adfdc674b 100644 --- a/drivers/media/tuners/qm1d1c0042.c +++ b/drivers/media/tuners/qm1d1c0042.c @@ -443,7 +443,7 @@ static struct i2c_driver qm1d1c0042_driver = { .driver = { .name = "qm1d1c0042", }, - .probe_new = qm1d1c0042_probe, + .probe = qm1d1c0042_probe, .remove = qm1d1c0042_remove, .id_table = qm1d1c0042_id, }; diff --git a/drivers/media/tuners/si2157.c b/drivers/media/tuners/si2157.c index 3fa3dcda917ad1fa23c4a70fc1205bbee0bc2342..def06c262ea2e673cb78ba77f48af441f7aca6bf 100644 --- a/drivers/media/tuners/si2157.c +++ b/drivers/media/tuners/si2157.c @@ -990,7 +990,7 @@ static struct i2c_driver si2157_driver = { .name = "si2157", .suppress_bind_attrs = true, }, - .probe_new = si2157_probe, + .probe = si2157_probe, .remove = si2157_remove, .id_table = si2157_id_table, }; diff --git a/drivers/media/tuners/tda18212.c b/drivers/media/tuners/tda18212.c index 5fdf05a974154f493ebca0d3f1569e0d6b7757c0..8d742bd61df0948859e5d45d11abda30df78a573 100644 --- a/drivers/media/tuners/tda18212.c +++ b/drivers/media/tuners/tda18212.c @@ -263,7 +263,7 @@ static struct i2c_driver tda18212_driver = { .driver = { .name = "tda18212", }, - .probe_new = tda18212_probe, + .probe = tda18212_probe, .remove = tda18212_remove, .id_table = tda18212_id, }; diff --git a/drivers/media/tuners/tda18250.c b/drivers/media/tuners/tda18250.c index 66ff2d035de705791a3343d300ac278e554120a3..32ea473f3f496a53b00f639ef3fb198c5f87ae64 100644 --- a/drivers/media/tuners/tda18250.c +++ b/drivers/media/tuners/tda18250.c @@ -877,7 +877,7 @@ static struct i2c_driver tda18250_driver = { .driver = { .name = "tda18250", }, - .probe_new = tda18250_probe, + .probe = tda18250_probe, .remove = tda18250_remove, .id_table = tda18250_id_table, }; diff --git a/drivers/media/tuners/tua9001.c b/drivers/media/tuners/tua9001.c index ac38afd3441a03b4981a4f2d75fec694cf277899..03a3a022b0a887464ebf006949024821303c8a6d 100644 --- a/drivers/media/tuners/tua9001.c +++ b/drivers/media/tuners/tua9001.c @@ -255,7 +255,7 @@ static struct i2c_driver tua9001_driver = { .name = "tua9001", .suppress_bind_attrs = true, }, - .probe_new = tua9001_probe, + .probe = tua9001_probe, .remove = tua9001_remove, .id_table = tua9001_id_table, }; diff --git a/drivers/media/usb/as102/as102_usb_drv.c b/drivers/media/usb/as102/as102_usb_drv.c index 50419e8ae56c57fac7e0f0b331d6b22946c4ef91..6b380144d6c287859d81aab25a0b68974437a672 100644 --- a/drivers/media/usb/as102/as102_usb_drv.c +++ b/drivers/media/usb/as102/as102_usb_drv.c @@ -303,10 +303,8 @@ static void as102_usb_release(struct kref *kref) struct as102_dev_t *as102_dev; as102_dev = container_of(kref, struct as102_dev_t, kref); - if (as102_dev != NULL) { - usb_put_dev(as102_dev->bus_adap.usb_dev); - kfree(as102_dev); - } + usb_put_dev(as102_dev->bus_adap.usb_dev); + kfree(as102_dev); } static void as102_usb_disconnect(struct usb_interface *intf) diff --git a/drivers/media/usb/au0828/au0828-core.c b/drivers/media/usb/au0828/au0828-core.c index b3a09d3ac7d24068fad97af44ebf4e6cdd9aa093..1e246b47766dd5675aa5d368aee2dbddb794589f 100644 --- a/drivers/media/usb/au0828/au0828-core.c +++ b/drivers/media/usb/au0828/au0828-core.c @@ -250,7 +250,7 @@ static void au0828_media_graph_notify(struct media_entity *new, create_link: if (decoder && mixer) { - ret = media_get_pad_index(decoder, false, + ret = media_get_pad_index(decoder, MEDIA_PAD_FL_SOURCE, PAD_SIGNAL_AUDIO); if (ret >= 0) ret = media_create_pad_link(decoder, ret, diff --git a/drivers/media/usb/dvb-usb-v2/az6007.c b/drivers/media/usb/dvb-usb-v2/az6007.c index 62ee09f28a0bc115b2eadd5ec0596d2216018cb6..2dcbb49d66dab2eabcc7d595df76d3532d438163 100644 --- a/drivers/media/usb/dvb-usb-v2/az6007.c +++ b/drivers/media/usb/dvb-usb-v2/az6007.c @@ -202,7 +202,8 @@ static int az6007_rc_query(struct dvb_usb_device *d) unsigned code; enum rc_proto proto; - az6007_read(d, AZ6007_READ_IR, 0, 0, st->data, 10); + if (az6007_read(d, AZ6007_READ_IR, 0, 0, st->data, 10) < 0) + return -EIO; if (st->data[1] == 0x44) return 0; @@ -248,7 +249,7 @@ static int az6007_ci_read_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address) { - struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; + struct dvb_usb_device *d = ca->data; struct az6007_device_state *state = d_to_priv(d); int ret; @@ -290,7 +291,7 @@ static int az6007_ci_write_attribute_mem(struct dvb_ca_en50221 *ca, int address, u8 value) { - struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; + struct dvb_usb_device *d = ca->data; struct az6007_device_state *state = d_to_priv(d); int ret; @@ -321,7 +322,7 @@ static int az6007_ci_read_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address) { - struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; + struct dvb_usb_device *d = ca->data; struct az6007_device_state *state = d_to_priv(d); int ret; @@ -367,7 +368,7 @@ static int az6007_ci_write_cam_control(struct dvb_ca_en50221 *ca, u8 address, u8 value) { - struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; + struct dvb_usb_device *d = ca->data; struct az6007_device_state *state = d_to_priv(d); int ret; @@ -398,7 +399,7 @@ static int az6007_ci_write_cam_control(struct dvb_ca_en50221 *ca, static int CI_CamReady(struct dvb_ca_en50221 *ca, int slot) { - struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; + struct dvb_usb_device *d = ca->data; int ret; u8 req; @@ -429,7 +430,7 @@ static int CI_CamReady(struct dvb_ca_en50221 *ca, int slot) static int az6007_ci_slot_reset(struct dvb_ca_en50221 *ca, int slot) { - struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; + struct dvb_usb_device *d = ca->data; struct az6007_device_state *state = d_to_priv(d); int ret, i; @@ -485,7 +486,7 @@ static int az6007_ci_slot_shutdown(struct dvb_ca_en50221 *ca, int slot) static int az6007_ci_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot) { - struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; + struct dvb_usb_device *d = ca->data; struct az6007_device_state *state = d_to_priv(d); int ret; @@ -514,7 +515,7 @@ static int az6007_ci_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot) static int az6007_ci_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open) { - struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; + struct dvb_usb_device *d = ca->data; struct az6007_device_state *state = d_to_priv(d); int ret; u8 req; diff --git a/drivers/media/usb/dvb-usb/af9005-fe.c b/drivers/media/usb/dvb-usb/af9005-fe.c index 9d6fa0556d7b5b1c20ce51928fa984a2915af2ac..404e56b32145f1e629b08809ed866371b6efb0fa 100644 --- a/drivers/media/usb/dvb-usb/af9005-fe.c +++ b/drivers/media/usb/dvb-usb/af9005-fe.c @@ -1412,8 +1412,7 @@ static int af9005_fe_get_frontend(struct dvb_frontend *fe, static void af9005_fe_release(struct dvb_frontend *fe) { - struct af9005_fe_state *state = - (struct af9005_fe_state *)fe->demodulator_priv; + struct af9005_fe_state *state = fe->demodulator_priv; kfree(state); } diff --git a/drivers/media/usb/dvb-usb/az6027.c b/drivers/media/usb/dvb-usb/az6027.c index a31c6f82f4e90fbcd08bc600ada4948180a9970f..2bc27710427d5c21b5d4d8247559a759aa62dd57 100644 --- a/drivers/media/usb/dvb-usb/az6027.c +++ b/drivers/media/usb/dvb-usb/az6027.c @@ -407,8 +407,8 @@ static int az6027_ci_read_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address) { - struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; - struct az6027_device_state *state = (struct az6027_device_state *)d->priv; + struct dvb_usb_device *d = ca->data; + struct az6027_device_state *state = d->priv; int ret; u8 req; @@ -449,8 +449,8 @@ static int az6027_ci_write_attribute_mem(struct dvb_ca_en50221 *ca, int address, u8 value) { - struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; - struct az6027_device_state *state = (struct az6027_device_state *)d->priv; + struct dvb_usb_device *d = ca->data; + struct az6027_device_state *state = d->priv; int ret; u8 req; @@ -480,8 +480,8 @@ static int az6027_ci_read_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address) { - struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; - struct az6027_device_state *state = (struct az6027_device_state *)d->priv; + struct dvb_usb_device *d = ca->data; + struct az6027_device_state *state = d->priv; int ret; u8 req; @@ -526,8 +526,8 @@ static int az6027_ci_write_cam_control(struct dvb_ca_en50221 *ca, u8 address, u8 value) { - struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; - struct az6027_device_state *state = (struct az6027_device_state *)d->priv; + struct dvb_usb_device *d = ca->data; + struct az6027_device_state *state = d->priv; int ret; u8 req; @@ -557,7 +557,7 @@ static int az6027_ci_write_cam_control(struct dvb_ca_en50221 *ca, static int CI_CamReady(struct dvb_ca_en50221 *ca, int slot) { - struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; + struct dvb_usb_device *d = ca->data; int ret; u8 req; @@ -588,8 +588,8 @@ static int CI_CamReady(struct dvb_ca_en50221 *ca, int slot) static int az6027_ci_slot_reset(struct dvb_ca_en50221 *ca, int slot) { - struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; - struct az6027_device_state *state = (struct az6027_device_state *)d->priv; + struct dvb_usb_device *d = ca->data; + struct az6027_device_state *state = d->priv; int ret, i; u8 req; @@ -644,8 +644,8 @@ static int az6027_ci_slot_shutdown(struct dvb_ca_en50221 *ca, int slot) static int az6027_ci_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot) { - struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; - struct az6027_device_state *state = (struct az6027_device_state *)d->priv; + struct dvb_usb_device *d = ca->data; + struct az6027_device_state *state = d->priv; int ret; u8 req; @@ -673,8 +673,8 @@ static int az6027_ci_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot) static int az6027_ci_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open) { - struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; - struct az6027_device_state *state = (struct az6027_device_state *)d->priv; + struct dvb_usb_device *d = ca->data; + struct az6027_device_state *state = d->priv; int ret; u8 req; u16 value; @@ -719,7 +719,7 @@ static void az6027_ci_uninit(struct dvb_usb_device *d) if (NULL == d) return; - state = (struct az6027_device_state *)d->priv; + state = d->priv; if (NULL == state) return; @@ -735,7 +735,7 @@ static void az6027_ci_uninit(struct dvb_usb_device *d) static int az6027_ci_init(struct dvb_usb_adapter *a) { struct dvb_usb_device *d = a->dev; - struct az6027_device_state *state = (struct az6027_device_state *)d->priv; + struct az6027_device_state *state = d->priv; int ret; deb_info("%s", __func__); diff --git a/drivers/media/usb/dvb-usb/dtt200u-fe.c b/drivers/media/usb/dvb-usb/dtt200u-fe.c index 9f83560ba63d357925e552a0e64d06b58e4ed3c5..586afe22d81773a12dfe9e2be1f2ac9c7450f8ba 100644 --- a/drivers/media/usb/dvb-usb/dtt200u-fe.c +++ b/drivers/media/usb/dvb-usb/dtt200u-fe.c @@ -195,7 +195,7 @@ static int dtt200u_fe_get_frontend(struct dvb_frontend* fe, static void dtt200u_fe_release(struct dvb_frontend* fe) { - struct dtt200u_fe_state *state = (struct dtt200u_fe_state*) fe->demodulator_priv; + struct dtt200u_fe_state *state = fe->demodulator_priv; kfree(state); } diff --git a/drivers/media/usb/dvb-usb/dw2102.c b/drivers/media/usb/dvb-usb/dw2102.c index 8747960e614611a71f2d5ec78ecac77f633207f9..970b84c3f0b5a12bf29066af78a9e9e21b26bc98 100644 --- a/drivers/media/usb/dvb-usb/dw2102.c +++ b/drivers/media/usb/dvb-usb/dw2102.c @@ -830,7 +830,7 @@ static int dw210x_read_mac_address(struct dvb_usb_device *d, u8 mac[6]) for (i = 0; i < 256; i++) { if (dw210x_op_rw(d->udev, 0xb6, 0xa0 , i, ibuf, 2, DW210X_READ_MSG) < 0) { err("read eeprom failed."); - return -1; + return -EIO; } else { eepromline[i%16] = ibuf[0]; eeprom[i] = ibuf[0]; @@ -869,7 +869,7 @@ static int s6x0_read_mac_address(struct dvb_usb_device *d, u8 mac[6]) ret = s6x0_i2c_transfer(&d->i2c_adap, msg, 2); if (ret != 2) { err("read eeprom failed."); - return -1; + return -EIO; } else { eepromline[i % 16] = ibuf[0]; eeprom[i] = ibuf[0]; @@ -903,7 +903,7 @@ static int su3000_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) static int su3000_power_ctrl(struct dvb_usb_device *d, int i) { - struct dw2102_state *state = (struct dw2102_state *)d->priv; + struct dw2102_state *state = d->priv; int ret = 0; info("%s: %d, initialized %d", __func__, i, state->initialized); @@ -946,7 +946,7 @@ static int su3000_read_mac_address(struct dvb_usb_device *d, u8 mac[6]) for (i = 0; i < 6; i++) { obuf[1] = 0xf0 + i; if (i2c_transfer(&d->i2c_adap, msg, 2) != 2) - return -1; + return -EIO; else mac[i] = ibuf[0]; } @@ -978,8 +978,7 @@ static int dw210x_set_voltage(struct dvb_frontend *fe, .len = 2, }; - struct dvb_usb_adapter *udev_adap = - (struct dvb_usb_adapter *)(fe->dvb->priv); + struct dvb_usb_adapter *udev_adap = fe->dvb->priv; if (voltage == SEC_VOLTAGE_18) msg.buf = command_18v; else if (voltage == SEC_VOLTAGE_13) @@ -993,9 +992,8 @@ static int dw210x_set_voltage(struct dvb_frontend *fe, static int s660_set_voltage(struct dvb_frontend *fe, enum fe_sec_voltage voltage) { - struct dvb_usb_adapter *d = - (struct dvb_usb_adapter *)(fe->dvb->priv); - struct dw2102_state *st = (struct dw2102_state *)d->dev->priv; + struct dvb_usb_adapter *d = fe->dvb->priv; + struct dw2102_state *st = d->dev->priv; dw210x_set_voltage(fe, voltage); if (st->old_set_voltage) @@ -1014,8 +1012,7 @@ static void dw210x_led_ctrl(struct dvb_frontend *fe, int offon) .buf = led_off, .len = 1 }; - struct dvb_usb_adapter *udev_adap = - (struct dvb_usb_adapter *)(fe->dvb->priv); + struct dvb_usb_adapter *udev_adap = fe->dvb->priv; if (offon) msg.buf = led_on; @@ -1025,9 +1022,8 @@ static void dw210x_led_ctrl(struct dvb_frontend *fe, int offon) static int tt_s2_4600_read_status(struct dvb_frontend *fe, enum fe_status *status) { - struct dvb_usb_adapter *d = - (struct dvb_usb_adapter *)(fe->dvb->priv); - struct dw2102_state *st = (struct dw2102_state *)d->dev->priv; + struct dvb_usb_adapter *d = fe->dvb->priv; + struct dw2102_state *st = d->dev->priv; int ret; ret = st->fe_read_status(fe, status); @@ -2576,7 +2572,7 @@ static int dw2102_probe(struct usb_interface *intf, static void dw2102_disconnect(struct usb_interface *intf) { struct dvb_usb_device *d = usb_get_intfdata(intf); - struct dw2102_state *st = (struct dw2102_state *)d->priv; + struct dw2102_state *st = d->priv; struct i2c_client *client; /* remove I2C client for tuner */ diff --git a/drivers/media/usb/dvb-usb/opera1.c b/drivers/media/usb/dvb-usb/opera1.c index 0da86f58aff6984d8f84256141bfe5b0a592a307..98b2177667d27bf228a11e15abd1216474c3d34e 100644 --- a/drivers/media/usb/dvb-usb/opera1.c +++ b/drivers/media/usb/dvb-usb/opera1.c @@ -172,8 +172,7 @@ static int opera1_set_voltage(struct dvb_frontend *fe, struct i2c_msg msg[] = { {.addr = ADDR_B600_VOLTAGE_13V,.flags = 0,.buf = command_13v,.len = 1}, }; - struct dvb_usb_adapter *udev_adap = - (struct dvb_usb_adapter *)(fe->dvb->priv); + struct dvb_usb_adapter *udev_adap = fe->dvb->priv; if (voltage == SEC_VOLTAGE_18) { msg[0].addr = ADDR_B601_VOLTAGE_18V; msg[0].buf = command_18v; diff --git a/drivers/media/usb/dvb-usb/pctv452e.c b/drivers/media/usb/dvb-usb/pctv452e.c index da42c989e0719ee72d3c2388dd741db0cf922ddf..2aab49003493ceccd9d2dcbcc01f329e9d2efb74 100644 --- a/drivers/media/usb/dvb-usb/pctv452e.c +++ b/drivers/media/usb/dvb-usb/pctv452e.c @@ -108,7 +108,7 @@ struct pctv452e_state { static int tt3650_ci_msg(struct dvb_usb_device *d, u8 cmd, u8 *data, unsigned int write_len, unsigned int read_len) { - struct pctv452e_state *state = (struct pctv452e_state *)d->priv; + struct pctv452e_state *state = d->priv; u8 *buf; u8 id; unsigned int rlen; @@ -159,8 +159,8 @@ static int tt3650_ci_msg_locked(struct dvb_ca_en50221 *ca, u8 cmd, u8 *data, unsigned int write_len, unsigned int read_len) { - struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; - struct pctv452e_state *state = (struct pctv452e_state *)d->priv; + struct dvb_usb_device *d = ca->data; + struct pctv452e_state *state = d->priv; int ret; mutex_lock(&state->ca_mutex); @@ -292,8 +292,8 @@ static int tt3650_ci_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot) static int tt3650_ci_slot_reset(struct dvb_ca_en50221 *ca, int slot) { - struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; - struct pctv452e_state *state = (struct pctv452e_state *)d->priv; + struct dvb_usb_device *d = ca->data; + struct pctv452e_state *state = d->priv; u8 buf[1]; int ret; @@ -361,7 +361,7 @@ static void tt3650_ci_uninit(struct dvb_usb_device *d) if (NULL == d) return; - state = (struct pctv452e_state *)d->priv; + state = d->priv; if (NULL == state) return; @@ -379,7 +379,7 @@ static void tt3650_ci_uninit(struct dvb_usb_device *d) static int tt3650_ci_init(struct dvb_usb_adapter *a) { struct dvb_usb_device *d = a->dev; - struct pctv452e_state *state = (struct pctv452e_state *)d->priv; + struct pctv452e_state *state = d->priv; int ret; ci_dbg("%s", __func__); @@ -417,7 +417,7 @@ static int pctv452e_i2c_msg(struct dvb_usb_device *d, u8 addr, const u8 *snd_buf, u8 snd_len, u8 *rcv_buf, u8 rcv_len) { - struct pctv452e_state *state = (struct pctv452e_state *)d->priv; + struct pctv452e_state *state = d->priv; u8 *buf; u8 id; int ret; @@ -516,7 +516,7 @@ static u32 pctv452e_i2c_func(struct i2c_adapter *adapter) static int pctv452e_power_ctrl(struct dvb_usb_device *d, int i) { - struct pctv452e_state *state = (struct pctv452e_state *)d->priv; + struct pctv452e_state *state = d->priv; u8 *b0, *rx; int ret; @@ -567,7 +567,7 @@ static int pctv452e_power_ctrl(struct dvb_usb_device *d, int i) static int pctv452e_rc_query(struct dvb_usb_device *d) { - struct pctv452e_state *state = (struct pctv452e_state *)d->priv; + struct pctv452e_state *state = d->priv; u8 *b, *rx; int ret, i; u8 id; diff --git a/drivers/media/usb/go7007/s2250-board.c b/drivers/media/usb/go7007/s2250-board.c index 29dfcc6d0b0aa4e9b6551401dde3bae661a6719b..db1fab96d5293459075d829691b88fb7793f6e68 100644 --- a/drivers/media/usb/go7007/s2250-board.c +++ b/drivers/media/usb/go7007/s2250-board.c @@ -620,7 +620,7 @@ static struct i2c_driver s2250_driver = { .driver = { .name = "s2250", }, - .probe_new = s2250_probe, + .probe = s2250_probe, .remove = s2250_remove, .id_table = s2250_id, }; diff --git a/drivers/media/usb/siano/smsusb.c b/drivers/media/usb/siano/smsusb.c index 6f443c542c6da646d823a8aaa1ce3c2f72cae087..640737d3b8aeb266dfc0db514cac9b3c3a85a419 100644 --- a/drivers/media/usb/siano/smsusb.c +++ b/drivers/media/usb/siano/smsusb.c @@ -179,7 +179,8 @@ static void smsusb_stop_streaming(struct smsusb_device_t *dev) for (i = 0; i < MAX_URBS; i++) { usb_kill_urb(&dev->surbs[i].urb); - cancel_work_sync(&dev->surbs[i].wq); + if (dev->surbs[i].wq.func) + cancel_work_sync(&dev->surbs[i].wq); if (dev->surbs[i].cb) { smscore_putbuffer(dev->coredev, dev->surbs[i].cb); diff --git a/drivers/media/usb/stk1160/Kconfig b/drivers/media/usb/stk1160/Kconfig index 4f50fb7db7b9c07341252fe9e2c9482e660e5314..bf7c16baa9f8e16e26f27d3c8912e6dac9cf2ec7 100644 --- a/drivers/media/usb/stk1160/Kconfig +++ b/drivers/media/usb/stk1160/Kconfig @@ -1,8 +1,9 @@ # SPDX-License-Identifier: GPL-2.0-only -config VIDEO_STK1160_COMMON +config VIDEO_STK1160 tristate "STK1160 USB video capture support" depends on VIDEO_DEV && I2C - + select VIDEOBUF2_VMALLOC + select VIDEO_SAA711X help This is a video4linux driver for STK1160 based video capture devices. @@ -12,10 +13,3 @@ config VIDEO_STK1160_COMMON This driver only provides support for video capture. For audio capture, you need to select the snd-usb-audio driver (i.e. CONFIG_SND_USB_AUDIO). - -config VIDEO_STK1160 - tristate - depends on VIDEO_STK1160_COMMON - default y - select VIDEOBUF2_VMALLOC - select VIDEO_SAA711X diff --git a/drivers/media/usb/ttusb-dec/ttusb_dec.c b/drivers/media/usb/ttusb-dec/ttusb_dec.c index c4474d4c44e28adc84a26265ac45dd619bef3df2..79faa256061333bb01456b7833fd1f37719dee6b 100644 --- a/drivers/media/usb/ttusb-dec/ttusb_dec.c +++ b/drivers/media/usb/ttusb-dec/ttusb_dec.c @@ -1128,7 +1128,7 @@ static int ttusb_dec_stop_sec_feed(struct dvb_demux_feed *dvbdmxfeed) { struct ttusb_dec *dec = dvbdmxfeed->demux->priv; u8 b0[] = { 0x00, 0x00 }; - struct filter_info *finfo = (struct filter_info *)dvbdmxfeed->priv; + struct filter_info *finfo = dvbdmxfeed->priv; unsigned long flags; b0[1] = finfo->stream_id; diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c index d631ce4f9f7bb298d2b4c309d0bf242cdbd61a93..08fcd2ffa727b248d7857031a7790341aef5f1a0 100644 --- a/drivers/media/usb/uvc/uvc_driver.c +++ b/drivers/media/usb/uvc/uvc_driver.c @@ -184,7 +184,7 @@ static void uvc_stream_delete(struct uvc_streaming *stream) usb_put_intf(stream->intf); - kfree(stream->format); + kfree(stream->formats); kfree(stream->header.bmaControls); kfree(stream); } @@ -221,7 +221,8 @@ static struct uvc_streaming *uvc_stream_new(struct uvc_device *dev, static int uvc_parse_format(struct uvc_device *dev, struct uvc_streaming *streaming, struct uvc_format *format, - u32 **intervals, unsigned char *buffer, int buflen) + struct uvc_frame *frames, u32 **intervals, const unsigned char *buffer, + int buflen) { struct usb_interface *intf = streaming->intf; struct usb_host_interface *alts = intf->cur_altsetting; @@ -235,6 +236,7 @@ static int uvc_parse_format(struct uvc_device *dev, format->type = buffer[2]; format->index = buffer[3]; + format->frames = frames; switch (buffer[2]) { case UVC_VS_FORMAT_UNCOMPRESSED: @@ -339,8 +341,8 @@ static int uvc_parse_format(struct uvc_device *dev, ftype = 0; /* Create a dummy frame descriptor. */ - frame = &format->frame[0]; - memset(&format->frame[0], 0, sizeof(format->frame[0])); + frame = &frames[0]; + memset(frame, 0, sizeof(*frame)); frame->bFrameIntervalType = 1; frame->dwDefaultFrameInterval = 1; frame->dwFrameInterval = *intervals; @@ -370,7 +372,9 @@ static int uvc_parse_format(struct uvc_device *dev, */ while (buflen > 2 && buffer[1] == USB_DT_CS_INTERFACE && buffer[2] == ftype) { - frame = &format->frame[format->nframes]; + unsigned int maxIntervalIndex; + + frame = &frames[format->nframes]; if (ftype != UVC_VS_FRAME_FRAME_BASED) n = buflen > 25 ? buffer[25] : 0; else @@ -405,8 +409,27 @@ static int uvc_parse_format(struct uvc_device *dev, get_unaligned_le32(&buffer[17]); frame->bFrameIntervalType = buffer[21]; } + + /* + * Copy the frame intervals. + * + * Some bogus devices report dwMinFrameInterval equal to + * dwMaxFrameInterval and have dwFrameIntervalStep set to + * zero. Setting all null intervals to 1 fixes the problem and + * some other divisions by zero that could happen. + */ frame->dwFrameInterval = *intervals; + for (i = 0; i < n; ++i) { + interval = get_unaligned_le32(&buffer[26+4*i]); + (*intervals)[i] = interval ? interval : 1; + } + + /* + * Apply more fixes, quirks and workarounds to handle incorrect + * or broken descriptors. + */ + /* * Several UVC chipsets screw up dwMaxVideoFrameBufferSize * completely. Observed behaviours range from setting the @@ -421,30 +444,25 @@ static int uvc_parse_format(struct uvc_device *dev, * frame->wWidth * frame->wHeight / 8; /* - * Some bogus devices report dwMinFrameInterval equal to - * dwMaxFrameInterval and have dwFrameIntervalStep set to - * zero. Setting all null intervals to 1 fixes the problem and - * some other divisions by zero that could happen. + * Clamp the default frame interval to the boundaries. A zero + * bFrameIntervalType value indicates a continuous frame + * interval range, with dwFrameInterval[0] storing the minimum + * value and dwFrameInterval[1] storing the maximum value. */ - for (i = 0; i < n; ++i) { - interval = get_unaligned_le32(&buffer[26+4*i]); - *(*intervals)++ = interval ? interval : 1; - } + maxIntervalIndex = frame->bFrameIntervalType ? n - 1 : 1; + frame->dwDefaultFrameInterval = + clamp(frame->dwDefaultFrameInterval, + frame->dwFrameInterval[0], + frame->dwFrameInterval[maxIntervalIndex]); /* - * Make sure that the default frame interval stays between - * the boundaries. + * Some devices report frame intervals that are not functional. + * If the corresponding quirk is set, restrict operation to the + * first interval only. */ - n -= frame->bFrameIntervalType ? 1 : 2; - frame->dwDefaultFrameInterval = - min(frame->dwFrameInterval[n], - max(frame->dwFrameInterval[0], - frame->dwDefaultFrameInterval)); - if (dev->quirks & UVC_QUIRK_RESTRICT_FRAME_RATE) { frame->bFrameIntervalType = 1; - frame->dwFrameInterval[0] = - frame->dwDefaultFrameInterval; + (*intervals)[0] = frame->dwDefaultFrameInterval; } uvc_dbg(dev, DESCR, "- %ux%u (%u.%u fps)\n", @@ -453,6 +471,8 @@ static int uvc_parse_format(struct uvc_device *dev, (100000000 / frame->dwDefaultFrameInterval) % 10); format->nframes++; + *intervals += n; + buflen -= buffer[0]; buffer += buffer[0]; } @@ -493,7 +513,7 @@ static int uvc_parse_streaming(struct uvc_device *dev, struct uvc_format *format; struct uvc_frame *frame; struct usb_host_interface *alts = &intf->altsetting[0]; - unsigned char *_buffer, *buffer = alts->extra; + const unsigned char *_buffer, *buffer = alts->extra; int _buflen, buflen = alts->extralen; unsigned int nformats = 0, nframes = 0, nintervals = 0; unsigned int size, i, n, p; @@ -677,7 +697,7 @@ static int uvc_parse_streaming(struct uvc_device *dev, frame = (struct uvc_frame *)&format[nformats]; interval = (u32 *)&frame[nframes]; - streaming->format = format; + streaming->formats = format; streaming->nformats = 0; /* Parse the format descriptors. */ @@ -687,8 +707,7 @@ static int uvc_parse_streaming(struct uvc_device *dev, case UVC_VS_FORMAT_MJPEG: case UVC_VS_FORMAT_DV: case UVC_VS_FORMAT_FRAME_BASED: - format->frame = frame; - ret = uvc_parse_format(dev, streaming, format, + ret = uvc_parse_format(dev, streaming, format, frame, &interval, buffer, buflen); if (ret < 0) goto error; @@ -1147,7 +1166,7 @@ static int uvc_parse_standard_control(struct uvc_device *dev, static int uvc_parse_control(struct uvc_device *dev) { struct usb_host_interface *alts = dev->intf->cur_altsetting; - unsigned char *buffer = alts->extra; + const unsigned char *buffer = alts->extra; int buflen = alts->extralen; int ret; @@ -3011,15 +3030,33 @@ static const struct usb_device_id uvc_ids[] = { .bInterfaceSubClass = 1, .bInterfaceProtocol = 0, .driver_info = (kernel_ulong_t)&uvc_ctrl_power_line_limited }, - /* Acer EasyCamera */ + /* Intel D410/ASR depth camera */ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = 0x5986, - .idProduct = 0x1180, + .idVendor = 0x8086, + .idProduct = 0x0ad2, .bInterfaceClass = USB_CLASS_VIDEO, .bInterfaceSubClass = 1, .bInterfaceProtocol = 0, - .driver_info = (kernel_ulong_t)&uvc_ctrl_power_line_limited }, + .driver_info = UVC_INFO_META(V4L2_META_FMT_D4XX) }, + /* Intel D415/ASRC depth camera */ + { .match_flags = USB_DEVICE_ID_MATCH_DEVICE + | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x8086, + .idProduct = 0x0ad3, + .bInterfaceClass = USB_CLASS_VIDEO, + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 0, + .driver_info = UVC_INFO_META(V4L2_META_FMT_D4XX) }, + /* Intel D430/AWG depth camera */ + { .match_flags = USB_DEVICE_ID_MATCH_DEVICE + | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x8086, + .idProduct = 0x0ad4, + .bInterfaceClass = USB_CLASS_VIDEO, + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 0, + .driver_info = UVC_INFO_META(V4L2_META_FMT_D4XX) }, /* Intel RealSense D4M */ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, @@ -3029,6 +3066,42 @@ static const struct usb_device_id uvc_ids[] = { .bInterfaceSubClass = 1, .bInterfaceProtocol = 0, .driver_info = UVC_INFO_META(V4L2_META_FMT_D4XX) }, + /* Intel D435/AWGC depth camera */ + { .match_flags = USB_DEVICE_ID_MATCH_DEVICE + | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x8086, + .idProduct = 0x0b07, + .bInterfaceClass = USB_CLASS_VIDEO, + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 0, + .driver_info = UVC_INFO_META(V4L2_META_FMT_D4XX) }, + /* Intel D435i depth camera */ + { .match_flags = USB_DEVICE_ID_MATCH_DEVICE + | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x8086, + .idProduct = 0x0b3a, + .bInterfaceClass = USB_CLASS_VIDEO, + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 0, + .driver_info = UVC_INFO_META(V4L2_META_FMT_D4XX) }, + /* Intel D405 Depth Camera */ + { .match_flags = USB_DEVICE_ID_MATCH_DEVICE + | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x8086, + .idProduct = 0x0b5b, + .bInterfaceClass = USB_CLASS_VIDEO, + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 0, + .driver_info = UVC_INFO_META(V4L2_META_FMT_D4XX) }, + /* Intel D455 Depth Camera */ + { .match_flags = USB_DEVICE_ID_MATCH_DEVICE + | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x8086, + .idProduct = 0x0b5c, + .bInterfaceClass = USB_CLASS_VIDEO, + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 0, + .driver_info = UVC_INFO_META(V4L2_META_FMT_D4XX) }, /* Generic USB Video Class */ { USB_INTERFACE_INFO(USB_CLASS_VIDEO, 1, UVC_PC_PROTOCOL_UNDEFINED) }, { USB_INTERFACE_INFO(USB_CLASS_VIDEO, 1, UVC_PC_PROTOCOL_15) }, diff --git a/drivers/media/usb/uvc/uvc_v4l2.c b/drivers/media/usb/uvc/uvc_v4l2.c index 35453f81c1d97a59a9c869af8bfbe590302711b3..5ac2a424b13df6c8e5e86264812094f399e35859 100644 --- a/drivers/media/usb/uvc/uvc_v4l2.c +++ b/drivers/media/usb/uvc/uvc_v4l2.c @@ -161,7 +161,7 @@ static int uvc_ioctl_xu_ctrl_map(struct uvc_video_chain *chain, * the Video Probe and Commit negotiation, but some hardware don't implement * that feature. */ -static u32 uvc_try_frame_interval(struct uvc_frame *frame, u32 interval) +static u32 uvc_try_frame_interval(const struct uvc_frame *frame, u32 interval) { unsigned int i; @@ -210,10 +210,11 @@ static u32 uvc_v4l2_get_bytesperline(const struct uvc_format *format, static int uvc_v4l2_try_format(struct uvc_streaming *stream, struct v4l2_format *fmt, struct uvc_streaming_control *probe, - struct uvc_format **uvc_format, struct uvc_frame **uvc_frame) + const struct uvc_format **uvc_format, + const struct uvc_frame **uvc_frame) { - struct uvc_format *format = NULL; - struct uvc_frame *frame = NULL; + const struct uvc_format *format = NULL; + const struct uvc_frame *frame = NULL; u16 rw, rh; unsigned int d, maxd; unsigned int i; @@ -235,7 +236,7 @@ static int uvc_v4l2_try_format(struct uvc_streaming *stream, * format otherwise. */ for (i = 0; i < stream->nformats; ++i) { - format = &stream->format[i]; + format = &stream->formats[i]; if (format->fcc == fmt->fmt.pix.pixelformat) break; } @@ -255,14 +256,14 @@ static int uvc_v4l2_try_format(struct uvc_streaming *stream, maxd = (unsigned int)-1; for (i = 0; i < format->nframes; ++i) { - u16 w = format->frame[i].wWidth; - u16 h = format->frame[i].wHeight; + u16 w = format->frames[i].wWidth; + u16 h = format->frames[i].wHeight; d = min(w, rw) * min(h, rh); d = w*h + rw*rh - 2*d; if (d < maxd) { maxd = d; - frame = &format->frame[i]; + frame = &format->frames[i]; } if (maxd == 0) @@ -319,8 +320,8 @@ static int uvc_v4l2_try_format(struct uvc_streaming *stream, * accepted the requested format as-is. */ for (i = 0; i < stream->nformats; ++i) { - if (probe->bFormatIndex == stream->format[i].index) { - format = &stream->format[i]; + if (probe->bFormatIndex == stream->formats[i].index) { + format = &stream->formats[i]; break; } } @@ -331,8 +332,8 @@ static int uvc_v4l2_try_format(struct uvc_streaming *stream, probe->bFormatIndex); for (i = 0; i < format->nframes; ++i) { - if (probe->bFrameIndex == format->frame[i].bFrameIndex) { - frame = &format->frame[i]; + if (probe->bFrameIndex == format->frames[i].bFrameIndex) { + frame = &format->frames[i]; break; } } @@ -363,8 +364,8 @@ static int uvc_v4l2_try_format(struct uvc_streaming *stream, static int uvc_v4l2_get_format(struct uvc_streaming *stream, struct v4l2_format *fmt) { - struct uvc_format *format; - struct uvc_frame *frame; + const struct uvc_format *format; + const struct uvc_frame *frame; int ret = 0; if (fmt->type != stream->type) @@ -398,8 +399,8 @@ static int uvc_v4l2_set_format(struct uvc_streaming *stream, struct v4l2_format *fmt) { struct uvc_streaming_control probe; - struct uvc_format *format; - struct uvc_frame *frame; + const struct uvc_format *format; + const struct uvc_frame *frame; int ret; if (fmt->type != stream->type) @@ -465,8 +466,8 @@ static int uvc_v4l2_set_streamparm(struct uvc_streaming *stream, { struct uvc_streaming_control probe; struct v4l2_fract timeperframe; - struct uvc_format *format; - struct uvc_frame *frame; + const struct uvc_format *format; + const struct uvc_frame *frame; u32 interval, maxd; unsigned int i; int ret; @@ -501,19 +502,19 @@ static int uvc_v4l2_set_streamparm(struct uvc_streaming *stream, for (i = 0; i < format->nframes && maxd != 0; i++) { u32 d, ival; - if (&format->frame[i] == stream->cur_frame) + if (&format->frames[i] == stream->cur_frame) continue; - if (format->frame[i].wWidth != stream->cur_frame->wWidth || - format->frame[i].wHeight != stream->cur_frame->wHeight) + if (format->frames[i].wWidth != stream->cur_frame->wWidth || + format->frames[i].wHeight != stream->cur_frame->wHeight) continue; - ival = uvc_try_frame_interval(&format->frame[i], interval); + ival = uvc_try_frame_interval(&format->frames[i], interval); d = abs((s32)ival - interval); if (d >= maxd) continue; - frame = &format->frame[i]; + frame = &format->frames[i]; probe.bFrameIndex = frame->bFrameIndex; probe.dwFrameInterval = ival; maxd = d; @@ -697,7 +698,7 @@ static int uvc_ioctl_querycap(struct file *file, void *fh, static int uvc_ioctl_enum_fmt(struct uvc_streaming *stream, struct v4l2_fmtdesc *fmt) { - struct uvc_format *format; + const struct uvc_format *format; enum v4l2_buf_type type = fmt->type; u32 index = fmt->index; @@ -708,7 +709,7 @@ static int uvc_ioctl_enum_fmt(struct uvc_streaming *stream, fmt->index = index; fmt->type = type; - format = &stream->format[fmt->index]; + format = &stream->formats[fmt->index]; fmt->flags = 0; if (format->flags & UVC_FMT_FLAG_COMPRESSED) fmt->flags |= V4L2_FMT_FLAG_COMPRESSED; @@ -1249,15 +1250,15 @@ static int uvc_ioctl_enum_framesizes(struct file *file, void *fh, { struct uvc_fh *handle = fh; struct uvc_streaming *stream = handle->stream; - struct uvc_format *format = NULL; - struct uvc_frame *frame = NULL; + const struct uvc_format *format = NULL; + const struct uvc_frame *frame = NULL; unsigned int index; unsigned int i; /* Look for the given pixel format */ for (i = 0; i < stream->nformats; i++) { - if (stream->format[i].fcc == fsize->pixel_format) { - format = &stream->format[i]; + if (stream->formats[i].fcc == fsize->pixel_format) { + format = &stream->formats[i]; break; } } @@ -1266,10 +1267,10 @@ static int uvc_ioctl_enum_framesizes(struct file *file, void *fh, /* Skip duplicate frame sizes */ for (i = 0, index = 0; i < format->nframes; i++) { - if (frame && frame->wWidth == format->frame[i].wWidth && - frame->wHeight == format->frame[i].wHeight) + if (frame && frame->wWidth == format->frames[i].wWidth && + frame->wHeight == format->frames[i].wHeight) continue; - frame = &format->frame[i]; + frame = &format->frames[i]; if (index == fsize->index) break; index++; @@ -1289,16 +1290,16 @@ static int uvc_ioctl_enum_frameintervals(struct file *file, void *fh, { struct uvc_fh *handle = fh; struct uvc_streaming *stream = handle->stream; - struct uvc_format *format = NULL; - struct uvc_frame *frame = NULL; + const struct uvc_format *format = NULL; + const struct uvc_frame *frame = NULL; unsigned int nintervals; unsigned int index; unsigned int i; /* Look for the given pixel format and frame size */ for (i = 0; i < stream->nformats; i++) { - if (stream->format[i].fcc == fival->pixel_format) { - format = &stream->format[i]; + if (stream->formats[i].fcc == fival->pixel_format) { + format = &stream->formats[i]; break; } } @@ -1307,9 +1308,9 @@ static int uvc_ioctl_enum_frameintervals(struct file *file, void *fh, index = fival->index; for (i = 0; i < format->nframes; i++) { - if (format->frame[i].wWidth == fival->width && - format->frame[i].wHeight == fival->height) { - frame = &format->frame[i]; + if (format->frames[i].wWidth == fival->width && + format->frames[i].wHeight == fival->height) { + frame = &format->frames[i]; nintervals = frame->bFrameIntervalType ?: 1; if (index < nintervals) break; diff --git a/drivers/media/usb/uvc/uvc_video.c b/drivers/media/usb/uvc/uvc_video.c index d4b023d4de7c3b37bc0287dce16301e49f4e5bf4..28dde08ec6c5d9d595ceb559437617637fb3e86b 100644 --- a/drivers/media/usb/uvc/uvc_video.c +++ b/drivers/media/usb/uvc/uvc_video.c @@ -137,8 +137,8 @@ static const struct usb_device_id elgato_cam_link_4k = { static void uvc_fixup_video_ctrl(struct uvc_streaming *stream, struct uvc_streaming_control *ctrl) { - struct uvc_format *format = NULL; - struct uvc_frame *frame = NULL; + const struct uvc_format *format = NULL; + const struct uvc_frame *frame = NULL; unsigned int i; /* @@ -166,8 +166,8 @@ static void uvc_fixup_video_ctrl(struct uvc_streaming *stream, } for (i = 0; i < stream->nformats; ++i) { - if (stream->format[i].index == ctrl->bFormatIndex) { - format = &stream->format[i]; + if (stream->formats[i].index == ctrl->bFormatIndex) { + format = &stream->formats[i]; break; } } @@ -176,8 +176,8 @@ static void uvc_fixup_video_ctrl(struct uvc_streaming *stream, return; for (i = 0; i < format->nframes; ++i) { - if (format->frame[i].bFrameIndex == ctrl->bFrameIndex) { - frame = &format->frame[i]; + if (format->frames[i].bFrameIndex == ctrl->bFrameIndex) { + frame = &format->frames[i]; break; } } @@ -2100,8 +2100,8 @@ int uvc_video_resume(struct uvc_streaming *stream, int reset) int uvc_video_init(struct uvc_streaming *stream) { struct uvc_streaming_control *probe = &stream->ctrl; - struct uvc_format *format = NULL; - struct uvc_frame *frame = NULL; + const struct uvc_format *format = NULL; + const struct uvc_frame *frame = NULL; struct uvc_urb *uvc_urb; unsigned int i; int ret; @@ -2161,7 +2161,7 @@ int uvc_video_init(struct uvc_streaming *stream) * available format otherwise. */ for (i = stream->nformats; i > 0; --i) { - format = &stream->format[i-1]; + format = &stream->formats[i-1]; if (format->index == probe->bFormatIndex) break; } @@ -2179,7 +2179,7 @@ int uvc_video_init(struct uvc_streaming *stream) * descriptor is not found, use the first available frame. */ for (i = format->nframes; i > 0; --i) { - frame = &format->frame[i-1]; + frame = &format->frames[i-1]; if (frame->bFrameIndex == probe->bFrameIndex) break; } diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h index 9a596c8d894a823b8b851c5d7618be7d770c3a2e..6fb0a78b1b0097129ef723f7826013c85aa3c2cb 100644 --- a/drivers/media/usb/uvc/uvcvideo.h +++ b/drivers/media/usb/uvc/uvcvideo.h @@ -251,7 +251,7 @@ struct uvc_frame { u32 dwMaxVideoFrameBufferSize; u8 bFrameIntervalType; u32 dwDefaultFrameInterval; - u32 *dwFrameInterval; + const u32 *dwFrameInterval; }; struct uvc_format { @@ -265,7 +265,7 @@ struct uvc_format { u32 flags; unsigned int nframes; - struct uvc_frame *frame; + const struct uvc_frame *frames; }; struct uvc_streaming_header { @@ -438,12 +438,12 @@ struct uvc_streaming { enum v4l2_buf_type type; unsigned int nformats; - struct uvc_format *format; + const struct uvc_format *formats; struct uvc_streaming_control ctrl; - struct uvc_format *def_format; - struct uvc_format *cur_format; - struct uvc_frame *cur_frame; + const struct uvc_format *def_format; + const struct uvc_format *cur_format; + const struct uvc_frame *cur_frame; /* * Protect access to ctrl, cur_format, cur_frame and hardware video diff --git a/drivers/media/v4l2-core/tuner-core.c b/drivers/media/v4l2-core/tuner-core.c index 1c0d23c5220376eb0fa6e6d80c71089d927e1645..5687089bea6eaf4546dd8eff3ef606423dc4d830 100644 --- a/drivers/media/v4l2-core/tuner-core.c +++ b/drivers/media/v4l2-core/tuner-core.c @@ -1411,7 +1411,7 @@ static struct i2c_driver tuner_driver = { .name = "tuner", .pm = &tuner_pm_ops, }, - .probe_new = tuner_probe, + .probe = tuner_probe, .remove = tuner_remove, .command = tuner_command, .id_table = tuner_id, diff --git a/drivers/media/v4l2-core/v4l2-common.c b/drivers/media/v4l2-core/v4l2-common.c index 3c5ab5ecd67895d3fa7b1c2e766394843ff757c8..bee1535b04d3910d22fae2398c4f8a5ef8933208 100644 --- a/drivers/media/v4l2-core/v4l2-common.c +++ b/drivers/media/v4l2-core/v4l2-common.c @@ -235,91 +235,93 @@ const struct v4l2_format_info *v4l2_format_info(u32 format) { static const struct v4l2_format_info formats[] = { /* RGB formats */ - { .format = V4L2_PIX_FMT_BGR24, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 3, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_RGB24, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 3, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_HSV24, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 3, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_BGR32, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_XBGR32, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_BGRX32, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_RGB32, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_XRGB32, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_RGBX32, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_HSV32, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_ARGB32, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_RGBA32, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_ABGR32, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_BGRA32, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_RGB565, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_RGB555, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_BGR666, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_BGR48_12, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 6, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_ABGR64_12, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 8, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_BGR24, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 3, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_RGB24, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 3, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_HSV24, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 3, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_BGR32, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_XBGR32, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_BGRX32, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_RGB32, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_XRGB32, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_RGBX32, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_HSV32, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_ARGB32, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_RGBA32, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_ABGR32, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_BGRA32, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_RGB565, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_RGB555, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_BGR666, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_BGR48_12, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 6, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_ABGR64_12, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 8, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, /* YUV packed formats */ - { .format = V4L2_PIX_FMT_YUYV, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 2, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_YVYU, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 2, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_UYVY, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 2, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_VYUY, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 2, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_Y212, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 2, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_YUV48_12, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 1, .bpp = { 6, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_YUYV, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_YVYU, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_UYVY, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_VYUY, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_Y212, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_YUV48_12, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 1, .bpp = { 6, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, /* YUV planar formats */ - { .format = V4L2_PIX_FMT_NV12, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 2, .vdiv = 2 }, - { .format = V4L2_PIX_FMT_NV21, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 2, .vdiv = 2 }, - { .format = V4L2_PIX_FMT_NV16, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 2, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_NV61, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 2, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_NV24, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 1, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_NV42, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 1, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_P010, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 2, 2, 0, 0 }, .hdiv = 2, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_P012, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 2, 4, 0, 0 }, .hdiv = 2, .vdiv = 2 }, - - { .format = V4L2_PIX_FMT_YUV410, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 4, .vdiv = 4 }, - { .format = V4L2_PIX_FMT_YVU410, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 4, .vdiv = 4 }, - { .format = V4L2_PIX_FMT_YUV411P, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 4, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_YUV420, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 2, .vdiv = 2 }, - { .format = V4L2_PIX_FMT_YVU420, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 2, .vdiv = 2 }, - { .format = V4L2_PIX_FMT_YUV422P, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 2, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_GREY, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_NV12, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 2 }, + { .format = V4L2_PIX_FMT_NV21, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 2 }, + { .format = V4L2_PIX_FMT_NV16, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_NV61, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_NV24, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_NV42, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_P010, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 2, 2, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_P012, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 2, 4, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 2 }, + + { .format = V4L2_PIX_FMT_YUV410, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 4, .vdiv = 4 }, + { .format = V4L2_PIX_FMT_YVU410, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 4, .vdiv = 4 }, + { .format = V4L2_PIX_FMT_YUV411P, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 4, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_YUV420, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 2 }, + { .format = V4L2_PIX_FMT_YVU420, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 2 }, + { .format = V4L2_PIX_FMT_YUV422P, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_GREY, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, /* Tiled YUV formats */ - { .format = V4L2_PIX_FMT_NV12_4L4, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 2, .vdiv = 2 }, - { .format = V4L2_PIX_FMT_P010_4L4, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 2, 4, 0, 0 }, .hdiv = 2, .vdiv = 2 }, + { .format = V4L2_PIX_FMT_NV12_4L4, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 2 }, + { .format = V4L2_PIX_FMT_NV15_4L4, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 5, 10, 0, 0 }, .bpp_div = { 4, 4, 1, 1 }, .hdiv = 2, .vdiv = 2, + .block_w = { 4, 2, 0, 0 }, .block_h = { 1, 1, 0, 0 }}, + { .format = V4L2_PIX_FMT_P010_4L4, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 2, 4, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 2 }, /* YUV planar formats, non contiguous variant */ - { .format = V4L2_PIX_FMT_YUV420M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 3, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 2, .vdiv = 2 }, - { .format = V4L2_PIX_FMT_YVU420M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 3, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 2, .vdiv = 2 }, - { .format = V4L2_PIX_FMT_YUV422M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 3, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 2, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_YVU422M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 3, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 2, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_YUV444M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 3, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 1, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_YVU444M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 3, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 1, .vdiv = 1 }, - - { .format = V4L2_PIX_FMT_NV12M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 2, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 2, .vdiv = 2 }, - { .format = V4L2_PIX_FMT_NV21M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 2, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 2, .vdiv = 2 }, - { .format = V4L2_PIX_FMT_NV16M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 2, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 2, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_NV61M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 2, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 2, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_P012M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 2, .comp_planes = 2, .bpp = { 2, 4, 0, 0 }, .hdiv = 2, .vdiv = 2 }, + { .format = V4L2_PIX_FMT_YUV420M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 3, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 2 }, + { .format = V4L2_PIX_FMT_YVU420M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 3, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 2 }, + { .format = V4L2_PIX_FMT_YUV422M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 3, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_YVU422M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 3, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_YUV444M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 3, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_YVU444M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 3, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, + + { .format = V4L2_PIX_FMT_NV12M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 2, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 2 }, + { .format = V4L2_PIX_FMT_NV21M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 2, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 2 }, + { .format = V4L2_PIX_FMT_NV16M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 2, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_NV61M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 2, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_P012M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 2, .comp_planes = 2, .bpp = { 2, 4, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 2 }, /* Bayer RGB formats */ - { .format = V4L2_PIX_FMT_SBGGR8, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_SGBRG8, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_SGRBG8, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_SRGGB8, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_SBGGR10, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_SGBRG10, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_SGRBG10, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_SRGGB10, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_SBGGR10ALAW8, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_SGBRG10ALAW8, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_SGRBG10ALAW8, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_SRGGB10ALAW8, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_SBGGR10DPCM8, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_SGBRG10DPCM8, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_SGRBG10DPCM8, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_SRGGB10DPCM8, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_SBGGR12, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_SGBRG12, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_SGRBG12, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_SRGGB12, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_SBGGR8, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_SGBRG8, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_SGRBG8, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_SRGGB8, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_SBGGR10, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_SGBRG10, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_SGRBG10, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_SRGGB10, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_SBGGR10ALAW8, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_SGBRG10ALAW8, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_SGRBG10ALAW8, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_SRGGB10ALAW8, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_SBGGR10DPCM8, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_SGBRG10DPCM8, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_SGRBG10DPCM8, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_SRGGB10DPCM8, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_SBGGR12, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_SGBRG12, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_SGRBG12, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_SRGGB12, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, }; unsigned int i; @@ -379,7 +381,7 @@ int v4l2_fill_pixfmt_mp(struct v4l2_pix_format_mplane *pixfmt, if (info->mem_planes == 1) { plane = &pixfmt->plane_fmt[0]; - plane->bytesperline = ALIGN(width, v4l2_format_block_width(info, 0)) * info->bpp[0]; + plane->bytesperline = ALIGN(width, v4l2_format_block_width(info, 0)) * info->bpp[0] / info->bpp_div[0]; plane->sizeimage = 0; for (i = 0; i < info->comp_planes; i++) { @@ -393,7 +395,7 @@ int v4l2_fill_pixfmt_mp(struct v4l2_pix_format_mplane *pixfmt, plane->sizeimage += info->bpp[i] * DIV_ROUND_UP(aligned_width, hdiv) * - DIV_ROUND_UP(aligned_height, vdiv); + DIV_ROUND_UP(aligned_height, vdiv) / info->bpp_div[i]; } } else { for (i = 0; i < info->comp_planes; i++) { @@ -407,7 +409,7 @@ int v4l2_fill_pixfmt_mp(struct v4l2_pix_format_mplane *pixfmt, plane = &pixfmt->plane_fmt[i]; plane->bytesperline = - info->bpp[i] * DIV_ROUND_UP(aligned_width, hdiv); + info->bpp[i] * DIV_ROUND_UP(aligned_width, hdiv) / info->bpp_div[i]; plane->sizeimage = plane->bytesperline * DIV_ROUND_UP(aligned_height, vdiv); } @@ -433,7 +435,7 @@ int v4l2_fill_pixfmt(struct v4l2_pix_format *pixfmt, u32 pixelformat, pixfmt->width = width; pixfmt->height = height; pixfmt->pixelformat = pixelformat; - pixfmt->bytesperline = ALIGN(width, v4l2_format_block_width(info, 0)) * info->bpp[0]; + pixfmt->bytesperline = ALIGN(width, v4l2_format_block_width(info, 0)) * info->bpp[0] / info->bpp_div[0]; pixfmt->sizeimage = 0; for (i = 0; i < info->comp_planes; i++) { @@ -447,7 +449,7 @@ int v4l2_fill_pixfmt(struct v4l2_pix_format *pixfmt, u32 pixelformat, pixfmt->sizeimage += info->bpp[i] * DIV_ROUND_UP(aligned_width, hdiv) * - DIV_ROUND_UP(aligned_height, vdiv); + DIV_ROUND_UP(aligned_height, vdiv) / info->bpp_div[i]; } return 0; } diff --git a/drivers/media/v4l2-core/v4l2-ctrls-core.c b/drivers/media/v4l2-core/v4l2-ctrls-core.c index 29169170880a69ab388582ad879e08d52ab76bbf..a662fb60f73f42166b53c983a6468a948f6b4d3e 100644 --- a/drivers/media/v4l2-core/v4l2-ctrls-core.c +++ b/drivers/media/v4l2-core/v4l2-ctrls-core.c @@ -111,6 +111,7 @@ static void std_init_compound(const struct v4l2_ctrl *ctrl, u32 idx, struct v4l2_ctrl_vp9_frame *p_vp9_frame; struct v4l2_ctrl_fwht_params *p_fwht_params; struct v4l2_ctrl_h264_scaling_matrix *p_h264_scaling_matrix; + struct v4l2_ctrl_av1_sequence *p_av1_sequence; void *p = ptr.p + idx * ctrl->elem_size; if (ctrl->p_def.p_const) @@ -157,6 +158,10 @@ static void std_init_compound(const struct v4l2_ctrl *ctrl, u32 idx, p_vp9_frame->flags |= V4L2_VP9_FRAME_FLAG_X_SUBSAMPLING | V4L2_VP9_FRAME_FLAG_Y_SUBSAMPLING; break; + case V4L2_CTRL_TYPE_AV1_SEQUENCE: + p_av1_sequence = p; + p_av1_sequence->bit_depth = 8; + break; case V4L2_CTRL_TYPE_FWHT_PARAMS: p_fwht_params = p; p_fwht_params->version = V4L2_FWHT_VERSION; @@ -350,6 +355,19 @@ void v4l2_ctrl_type_op_log(const struct v4l2_ctrl *ctrl) case V4L2_CTRL_TYPE_HEVC_DECODE_PARAMS: pr_cont("HEVC_DECODE_PARAMS"); break; + case V4L2_CTRL_TYPE_AV1_SEQUENCE: + pr_cont("AV1_SEQUENCE"); + break; + case V4L2_CTRL_TYPE_AV1_TILE_GROUP_ENTRY: + pr_cont("AV1_TILE_GROUP_ENTRY"); + break; + case V4L2_CTRL_TYPE_AV1_FRAME: + pr_cont("AV1_FRAME"); + break; + case V4L2_CTRL_TYPE_AV1_FILM_GRAIN: + pr_cont("AV1_FILM_GRAIN"); + break; + default: pr_cont("unknown type %d", ctrl->type); break; @@ -547,6 +565,231 @@ validate_vp9_frame(struct v4l2_ctrl_vp9_frame *frame) return 0; } +static int validate_av1_quantization(struct v4l2_av1_quantization *q) +{ + if (q->flags > GENMASK(2, 0)) + return -EINVAL; + + if (q->delta_q_y_dc < -64 || q->delta_q_y_dc > 63 || + q->delta_q_u_dc < -64 || q->delta_q_u_dc > 63 || + q->delta_q_v_dc < -64 || q->delta_q_v_dc > 63 || + q->delta_q_u_ac < -64 || q->delta_q_u_ac > 63 || + q->delta_q_v_ac < -64 || q->delta_q_v_ac > 63 || + q->delta_q_res > GENMASK(1, 0)) + return -EINVAL; + + if (q->qm_y > GENMASK(3, 0) || + q->qm_u > GENMASK(3, 0) || + q->qm_v > GENMASK(3, 0)) + return -EINVAL; + + return 0; +} + +static int validate_av1_segmentation(struct v4l2_av1_segmentation *s) +{ + u32 i; + u32 j; + + if (s->flags > GENMASK(4, 0)) + return -EINVAL; + + for (i = 0; i < ARRAY_SIZE(s->feature_data); i++) { + static const int segmentation_feature_signed[] = { 1, 1, 1, 1, 1, 0, 0, 0 }; + static const int segmentation_feature_max[] = { 255, 63, 63, 63, 63, 7, 0, 0}; + + for (j = 0; j < ARRAY_SIZE(s->feature_data[j]); j++) { + s32 limit = segmentation_feature_max[j]; + + if (segmentation_feature_signed[j]) { + if (s->feature_data[i][j] < -limit || + s->feature_data[i][j] > limit) + return -EINVAL; + } else { + if (s->feature_data[i][j] < 0 || s->feature_data[i][j] > limit) + return -EINVAL; + } + } + } + + return 0; +} + +static int validate_av1_loop_filter(struct v4l2_av1_loop_filter *lf) +{ + u32 i; + + if (lf->flags > GENMASK(3, 0)) + return -EINVAL; + + for (i = 0; i < ARRAY_SIZE(lf->level); i++) { + if (lf->level[i] > GENMASK(5, 0)) + return -EINVAL; + } + + if (lf->sharpness > GENMASK(2, 0)) + return -EINVAL; + + for (i = 0; i < ARRAY_SIZE(lf->ref_deltas); i++) { + if (lf->ref_deltas[i] < -64 || lf->ref_deltas[i] > 63) + return -EINVAL; + } + + for (i = 0; i < ARRAY_SIZE(lf->mode_deltas); i++) { + if (lf->mode_deltas[i] < -64 || lf->mode_deltas[i] > 63) + return -EINVAL; + } + + return 0; +} + +static int validate_av1_cdef(struct v4l2_av1_cdef *cdef) +{ + u32 i; + + if (cdef->damping_minus_3 > GENMASK(1, 0) || + cdef->bits > GENMASK(1, 0)) + return -EINVAL; + + for (i = 0; i < 1 << cdef->bits; i++) { + if (cdef->y_pri_strength[i] > GENMASK(3, 0) || + cdef->y_sec_strength[i] > 4 || + cdef->uv_pri_strength[i] > GENMASK(3, 0) || + cdef->uv_sec_strength[i] > 4) + return -EINVAL; + } + + return 0; +} + +static int validate_av1_loop_restauration(struct v4l2_av1_loop_restoration *lr) +{ + if (lr->lr_unit_shift > 3 || lr->lr_uv_shift > 1) + return -EINVAL; + + return 0; +} + +static int validate_av1_film_grain(struct v4l2_ctrl_av1_film_grain *fg) +{ + u32 i; + + if (fg->flags > GENMASK(4, 0)) + return -EINVAL; + + if (fg->film_grain_params_ref_idx > GENMASK(2, 0) || + fg->num_y_points > 14 || + fg->num_cb_points > 10 || + fg->num_cr_points > GENMASK(3, 0) || + fg->grain_scaling_minus_8 > GENMASK(1, 0) || + fg->ar_coeff_lag > GENMASK(1, 0) || + fg->ar_coeff_shift_minus_6 > GENMASK(1, 0) || + fg->grain_scale_shift > GENMASK(1, 0)) + return -EINVAL; + + if (!(fg->flags & V4L2_AV1_FILM_GRAIN_FLAG_APPLY_GRAIN)) + return 0; + + for (i = 1; i < fg->num_y_points; i++) + if (fg->point_y_value[i] <= fg->point_y_value[i - 1]) + return -EINVAL; + + for (i = 1; i < fg->num_cb_points; i++) + if (fg->point_cb_value[i] <= fg->point_cb_value[i - 1]) + return -EINVAL; + + for (i = 1; i < fg->num_cr_points; i++) + if (fg->point_cr_value[i] <= fg->point_cr_value[i - 1]) + return -EINVAL; + + return 0; +} + +static int validate_av1_frame(struct v4l2_ctrl_av1_frame *f) +{ + int ret = 0; + + ret = validate_av1_quantization(&f->quantization); + if (ret) + return ret; + ret = validate_av1_segmentation(&f->segmentation); + if (ret) + return ret; + ret = validate_av1_loop_filter(&f->loop_filter); + if (ret) + return ret; + ret = validate_av1_cdef(&f->cdef); + if (ret) + return ret; + ret = validate_av1_loop_restauration(&f->loop_restoration); + if (ret) + return ret; + + if (f->flags & + ~(V4L2_AV1_FRAME_FLAG_SHOW_FRAME | + V4L2_AV1_FRAME_FLAG_SHOWABLE_FRAME | + V4L2_AV1_FRAME_FLAG_ERROR_RESILIENT_MODE | + V4L2_AV1_FRAME_FLAG_DISABLE_CDF_UPDATE | + V4L2_AV1_FRAME_FLAG_ALLOW_SCREEN_CONTENT_TOOLS | + V4L2_AV1_FRAME_FLAG_FORCE_INTEGER_MV | + V4L2_AV1_FRAME_FLAG_ALLOW_INTRABC | + V4L2_AV1_FRAME_FLAG_USE_SUPERRES | + V4L2_AV1_FRAME_FLAG_ALLOW_HIGH_PRECISION_MV | + V4L2_AV1_FRAME_FLAG_IS_MOTION_MODE_SWITCHABLE | + V4L2_AV1_FRAME_FLAG_USE_REF_FRAME_MVS | + V4L2_AV1_FRAME_FLAG_DISABLE_FRAME_END_UPDATE_CDF | + V4L2_AV1_FRAME_FLAG_ALLOW_WARPED_MOTION | + V4L2_AV1_FRAME_FLAG_REFERENCE_SELECT | + V4L2_AV1_FRAME_FLAG_REDUCED_TX_SET | + V4L2_AV1_FRAME_FLAG_SKIP_MODE_ALLOWED | + V4L2_AV1_FRAME_FLAG_SKIP_MODE_PRESENT | + V4L2_AV1_FRAME_FLAG_FRAME_SIZE_OVERRIDE | + V4L2_AV1_FRAME_FLAG_BUFFER_REMOVAL_TIME_PRESENT | + V4L2_AV1_FRAME_FLAG_FRAME_REFS_SHORT_SIGNALING)) + return -EINVAL; + + if (f->superres_denom > GENMASK(2, 0) + 9) + return -EINVAL; + + return 0; +} + +static int validate_av1_sequence(struct v4l2_ctrl_av1_sequence *s) +{ + if (s->flags & + ~(V4L2_AV1_SEQUENCE_FLAG_STILL_PICTURE | + V4L2_AV1_SEQUENCE_FLAG_USE_128X128_SUPERBLOCK | + V4L2_AV1_SEQUENCE_FLAG_ENABLE_FILTER_INTRA | + V4L2_AV1_SEQUENCE_FLAG_ENABLE_INTRA_EDGE_FILTER | + V4L2_AV1_SEQUENCE_FLAG_ENABLE_INTERINTRA_COMPOUND | + V4L2_AV1_SEQUENCE_FLAG_ENABLE_MASKED_COMPOUND | + V4L2_AV1_SEQUENCE_FLAG_ENABLE_WARPED_MOTION | + V4L2_AV1_SEQUENCE_FLAG_ENABLE_DUAL_FILTER | + V4L2_AV1_SEQUENCE_FLAG_ENABLE_ORDER_HINT | + V4L2_AV1_SEQUENCE_FLAG_ENABLE_JNT_COMP | + V4L2_AV1_SEQUENCE_FLAG_ENABLE_REF_FRAME_MVS | + V4L2_AV1_SEQUENCE_FLAG_ENABLE_SUPERRES | + V4L2_AV1_SEQUENCE_FLAG_ENABLE_CDEF | + V4L2_AV1_SEQUENCE_FLAG_ENABLE_RESTORATION | + V4L2_AV1_SEQUENCE_FLAG_MONO_CHROME | + V4L2_AV1_SEQUENCE_FLAG_COLOR_RANGE | + V4L2_AV1_SEQUENCE_FLAG_SUBSAMPLING_X | + V4L2_AV1_SEQUENCE_FLAG_SUBSAMPLING_Y | + V4L2_AV1_SEQUENCE_FLAG_FILM_GRAIN_PARAMS_PRESENT | + V4L2_AV1_SEQUENCE_FLAG_SEPARATE_UV_DELTA_Q)) + return -EINVAL; + + if (s->seq_profile == 1 && s->flags & V4L2_AV1_SEQUENCE_FLAG_MONO_CHROME) + return -EINVAL; + + /* reserved */ + if (s->seq_profile > 2) + return -EINVAL; + + /* TODO: PROFILES */ + return 0; +} + /* * Compound controls validation requires setting unused fields/flags to zero * in order to properly detect unchanged controls with v4l2_ctrl_type_op_equal's @@ -911,6 +1154,14 @@ static int std_validate_compound(const struct v4l2_ctrl *ctrl, u32 idx, case V4L2_CTRL_TYPE_VP9_FRAME: return validate_vp9_frame(p); + case V4L2_CTRL_TYPE_AV1_FRAME: + return validate_av1_frame(p); + case V4L2_CTRL_TYPE_AV1_SEQUENCE: + return validate_av1_sequence(p); + case V4L2_CTRL_TYPE_AV1_TILE_GROUP_ENTRY: + break; + case V4L2_CTRL_TYPE_AV1_FILM_GRAIN: + return validate_av1_film_grain(p); case V4L2_CTRL_TYPE_AREA: area = p; @@ -1602,6 +1853,18 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl, case V4L2_CTRL_TYPE_VP9_FRAME: elem_size = sizeof(struct v4l2_ctrl_vp9_frame); break; + case V4L2_CTRL_TYPE_AV1_SEQUENCE: + elem_size = sizeof(struct v4l2_ctrl_av1_sequence); + break; + case V4L2_CTRL_TYPE_AV1_TILE_GROUP_ENTRY: + elem_size = sizeof(struct v4l2_ctrl_av1_tile_group_entry); + break; + case V4L2_CTRL_TYPE_AV1_FRAME: + elem_size = sizeof(struct v4l2_ctrl_av1_frame); + break; + case V4L2_CTRL_TYPE_AV1_FILM_GRAIN: + elem_size = sizeof(struct v4l2_ctrl_av1_film_grain); + break; case V4L2_CTRL_TYPE_AREA: elem_size = sizeof(struct v4l2_area); break; diff --git a/drivers/media/v4l2-core/v4l2-ctrls-defs.c b/drivers/media/v4l2-core/v4l2-ctrls-defs.c index 564fedee2c88ed3ad5d9480df05f1bc1d09f78f4..8696eb1cdd6191fc34fecf02921a5a67052889e7 100644 --- a/drivers/media/v4l2-core/v4l2-ctrls-defs.c +++ b/drivers/media/v4l2-core/v4l2-ctrls-defs.c @@ -499,6 +499,40 @@ const char * const *v4l2_ctrl_get_menu(u32 id) NULL, }; + static const char * const av1_profile[] = { + "Main", + "High", + "Professional", + NULL, + }; + static const char * const av1_level[] = { + "2.0", + "2.1", + "2.2", + "2.3", + "3.0", + "3.1", + "3.2", + "3.3", + "4.0", + "4.1", + "4.2", + "4.3", + "5.0", + "5.1", + "5.2", + "5.3", + "6.0", + "6.1", + "6.2", + "6.3", + "7.0", + "7.1", + "7.2", + "7.3", + NULL, + }; + static const char * const hevc_profile[] = { "Main", "Main Still Picture", @@ -704,6 +738,10 @@ const char * const *v4l2_ctrl_get_menu(u32 id) return hevc_tier; case V4L2_CID_MPEG_VIDEO_HEVC_LOOP_FILTER_MODE: return hevc_loop_filter_mode; + case V4L2_CID_MPEG_VIDEO_AV1_PROFILE: + return av1_profile; + case V4L2_CID_MPEG_VIDEO_AV1_LEVEL: + return av1_level; case V4L2_CID_STATELESS_HEVC_DECODE_MODE: return hevc_decode_mode; case V4L2_CID_STATELESS_HEVC_START_CODE: @@ -1004,6 +1042,10 @@ const char *v4l2_ctrl_get_name(u32 id) case V4L2_CID_MPEG_VIDEO_REF_NUMBER_FOR_PFRAMES: return "Reference Frames for a P-Frame"; case V4L2_CID_MPEG_VIDEO_PREPEND_SPSPPS_TO_IDR: return "Prepend SPS and PPS to IDR"; + /* AV1 controls */ + case V4L2_CID_MPEG_VIDEO_AV1_PROFILE: return "AV1 Profile"; + case V4L2_CID_MPEG_VIDEO_AV1_LEVEL: return "AV1 Level"; + /* CAMERA controls */ /* Keep the order of the 'case's the same as in v4l2-controls.h! */ case V4L2_CID_CAMERA_CLASS: return "Camera Controls"; @@ -1190,6 +1232,10 @@ const char *v4l2_ctrl_get_name(u32 id) case V4L2_CID_STATELESS_HEVC_DECODE_MODE: return "HEVC Decode Mode"; case V4L2_CID_STATELESS_HEVC_START_CODE: return "HEVC Start Code"; case V4L2_CID_STATELESS_HEVC_ENTRY_POINT_OFFSETS: return "HEVC Entry Point Offsets"; + case V4L2_CID_STATELESS_AV1_SEQUENCE: return "AV1 Sequence Parameters"; + case V4L2_CID_STATELESS_AV1_TILE_GROUP_ENTRY: return "AV1 Tile Group Entry"; + case V4L2_CID_STATELESS_AV1_FRAME: return "AV1 Frame Parameters"; + case V4L2_CID_STATELESS_AV1_FILM_GRAIN: return "AV1 Film Grain"; /* Colorimetry controls */ /* Keep the order of the 'case's the same as in v4l2-controls.h! */ @@ -1365,6 +1411,8 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type, case V4L2_CID_MPEG_VIDEO_HEVC_SIZE_OF_LENGTH_FIELD: case V4L2_CID_MPEG_VIDEO_HEVC_TIER: case V4L2_CID_MPEG_VIDEO_HEVC_LOOP_FILTER_MODE: + case V4L2_CID_MPEG_VIDEO_AV1_PROFILE: + case V4L2_CID_MPEG_VIDEO_AV1_LEVEL: case V4L2_CID_STATELESS_HEVC_DECODE_MODE: case V4L2_CID_STATELESS_HEVC_START_CODE: case V4L2_CID_STATELESS_H264_DECODE_MODE: @@ -1531,6 +1579,19 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type, case V4L2_CID_STATELESS_VP9_FRAME: *type = V4L2_CTRL_TYPE_VP9_FRAME; break; + case V4L2_CID_STATELESS_AV1_SEQUENCE: + *type = V4L2_CTRL_TYPE_AV1_SEQUENCE; + break; + case V4L2_CID_STATELESS_AV1_TILE_GROUP_ENTRY: + *type = V4L2_CTRL_TYPE_AV1_TILE_GROUP_ENTRY; + *flags |= V4L2_CTRL_FLAG_DYNAMIC_ARRAY; + break; + case V4L2_CID_STATELESS_AV1_FRAME: + *type = V4L2_CTRL_TYPE_AV1_FRAME; + break; + case V4L2_CID_STATELESS_AV1_FILM_GRAIN: + *type = V4L2_CTRL_TYPE_AV1_FILM_GRAIN; + break; case V4L2_CID_UNIT_CELL_SIZE: *type = V4L2_CTRL_TYPE_AREA; *flags |= V4L2_CTRL_FLAG_READ_ONLY; diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c index a858acea65477d7003f26bec8d2c2713912bb560..01ba27f2ef873e7f63829aedb2c538a2db64541d 100644 --- a/drivers/media/v4l2-core/v4l2-ioctl.c +++ b/drivers/media/v4l2-core/v4l2-ioctl.c @@ -1356,6 +1356,7 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt) case V4L2_PIX_FMT_NV12_4L4: descr = "Y/UV 4:2:0 (4x4 Linear)"; break; case V4L2_PIX_FMT_NV12_16L16: descr = "Y/UV 4:2:0 (16x16 Linear)"; break; case V4L2_PIX_FMT_NV12_32L32: descr = "Y/UV 4:2:0 (32x32 Linear)"; break; + case V4L2_PIX_FMT_NV15_4L4: descr = "10-bit Y/UV 4:2:0 (4x4 Linear)"; break; case V4L2_PIX_FMT_P010_4L4: descr = "10-bit Y/UV 4:2:0 (4x4 Linear)"; break; case V4L2_PIX_FMT_NV12M: descr = "Y/UV 4:2:0 (N-C)"; break; case V4L2_PIX_FMT_NV21M: descr = "Y/VU 4:2:0 (N-C)"; break; @@ -1506,6 +1507,7 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt) case V4L2_PIX_FMT_QC08C: descr = "QCOM Compressed 8-bit Format"; break; case V4L2_PIX_FMT_QC10C: descr = "QCOM Compressed 10-bit Format"; break; case V4L2_PIX_FMT_AJPG: descr = "Aspeed JPEG"; break; + case V4L2_PIX_FMT_AV1_FRAME: descr = "AV1 Frame"; break; default: if (fmt->description[0]) return; diff --git a/drivers/media/v4l2-core/v4l2-mc.c b/drivers/media/v4l2-core/v4l2-mc.c index 22fe08fce0a9abe8a3fb359a014b2471acab2ac3..52d349e72b8ca52217d0f67d1071020a1f0b29d0 100644 --- a/drivers/media/v4l2-core/v4l2-mc.c +++ b/drivers/media/v4l2-core/v4l2-mc.c @@ -105,9 +105,11 @@ int v4l2_mc_create_media_graph(struct media_device *mdev) /* Link the tuner and IF video output pads */ if (tuner) { if (if_vid) { - pad_source = media_get_pad_index(tuner, false, + pad_source = media_get_pad_index(tuner, + MEDIA_PAD_FL_SOURCE, PAD_SIGNAL_ANALOG); - pad_sink = media_get_pad_index(if_vid, true, + pad_sink = media_get_pad_index(if_vid, + MEDIA_PAD_FL_SINK, PAD_SIGNAL_ANALOG); if (pad_source < 0 || pad_sink < 0) { dev_warn(mdev->dev, "Couldn't get tuner and/or PLL pad(s): (%d, %d)\n", @@ -122,9 +124,11 @@ int v4l2_mc_create_media_graph(struct media_device *mdev) return ret; } - pad_source = media_get_pad_index(if_vid, false, + pad_source = media_get_pad_index(if_vid, + MEDIA_PAD_FL_SOURCE, PAD_SIGNAL_ANALOG); - pad_sink = media_get_pad_index(decoder, true, + pad_sink = media_get_pad_index(decoder, + MEDIA_PAD_FL_SINK, PAD_SIGNAL_ANALOG); if (pad_source < 0 || pad_sink < 0) { dev_warn(mdev->dev, "get decoder and/or PLL pad(s): (%d, %d)\n", @@ -139,9 +143,11 @@ int v4l2_mc_create_media_graph(struct media_device *mdev) return ret; } } else { - pad_source = media_get_pad_index(tuner, false, + pad_source = media_get_pad_index(tuner, + MEDIA_PAD_FL_SOURCE, PAD_SIGNAL_ANALOG); - pad_sink = media_get_pad_index(decoder, true, + pad_sink = media_get_pad_index(decoder, + MEDIA_PAD_FL_SINK, PAD_SIGNAL_ANALOG); if (pad_source < 0 || pad_sink < 0) { dev_warn(mdev->dev, "couldn't get tuner and/or decoder pad(s): (%d, %d)\n", @@ -156,9 +162,11 @@ int v4l2_mc_create_media_graph(struct media_device *mdev) } if (if_aud) { - pad_source = media_get_pad_index(tuner, false, + pad_source = media_get_pad_index(tuner, + MEDIA_PAD_FL_SOURCE, PAD_SIGNAL_AUDIO); - pad_sink = media_get_pad_index(if_aud, true, + pad_sink = media_get_pad_index(if_aud, + MEDIA_PAD_FL_SINK, PAD_SIGNAL_AUDIO); if (pad_source < 0 || pad_sink < 0) { dev_warn(mdev->dev, "couldn't get tuner and/or decoder pad(s) for audio: (%d, %d)\n", @@ -180,7 +188,8 @@ int v4l2_mc_create_media_graph(struct media_device *mdev) /* Create demod to V4L, VBI and SDR radio links */ if (io_v4l) { - pad_source = media_get_pad_index(decoder, false, PAD_SIGNAL_DV); + pad_source = media_get_pad_index(decoder, MEDIA_PAD_FL_SOURCE, + PAD_SIGNAL_DV); if (pad_source < 0) { dev_warn(mdev->dev, "couldn't get decoder output pad for V4L I/O\n"); return -EINVAL; @@ -195,7 +204,8 @@ int v4l2_mc_create_media_graph(struct media_device *mdev) } if (io_swradio) { - pad_source = media_get_pad_index(decoder, false, PAD_SIGNAL_DV); + pad_source = media_get_pad_index(decoder, MEDIA_PAD_FL_SOURCE, + PAD_SIGNAL_DV); if (pad_source < 0) { dev_warn(mdev->dev, "couldn't get decoder output pad for SDR\n"); return -EINVAL; @@ -210,7 +220,8 @@ int v4l2_mc_create_media_graph(struct media_device *mdev) } if (io_vbi) { - pad_source = media_get_pad_index(decoder, false, PAD_SIGNAL_DV); + pad_source = media_get_pad_index(decoder, MEDIA_PAD_FL_SOURCE, + PAD_SIGNAL_DV); if (pad_source < 0) { dev_warn(mdev->dev, "couldn't get decoder output pad for VBI\n"); return -EINVAL; @@ -231,7 +242,7 @@ int v4l2_mc_create_media_graph(struct media_device *mdev) case MEDIA_ENT_F_CONN_RF: if (!tuner) continue; - pad_sink = media_get_pad_index(tuner, true, + pad_sink = media_get_pad_index(tuner, MEDIA_PAD_FL_SINK, PAD_SIGNAL_ANALOG); if (pad_sink < 0) { dev_warn(mdev->dev, "couldn't get tuner analog pad sink\n"); @@ -243,7 +254,8 @@ int v4l2_mc_create_media_graph(struct media_device *mdev) break; case MEDIA_ENT_F_CONN_SVIDEO: case MEDIA_ENT_F_CONN_COMPOSITE: - pad_sink = media_get_pad_index(decoder, true, + pad_sink = media_get_pad_index(decoder, + MEDIA_PAD_FL_SINK, PAD_SIGNAL_ANALOG); if (pad_sink < 0) { dev_warn(mdev->dev, "couldn't get decoder analog pad sink\n"); diff --git a/drivers/media/v4l2-core/videobuf-dma-sg.c b/drivers/media/v4l2-core/videobuf-dma-sg.c index 53001532e8e30726446d3c636f61bfdd5ac862b6..405b89ea1054d6a8f2a25fa84cb6aaf83ee4dd64 100644 --- a/drivers/media/v4l2-core/videobuf-dma-sg.c +++ b/drivers/media/v4l2-core/videobuf-dma-sg.c @@ -180,7 +180,7 @@ static int videobuf_dma_init_user_locked(struct videobuf_dmabuf *dma, data, size, dma->nr_pages); err = pin_user_pages(data & PAGE_MASK, dma->nr_pages, gup_flags, - dma->pages, NULL); + dma->pages); if (err != dma->nr_pages) { dma->nr_pages = (err >= 0) ? err : 0; diff --git a/drivers/memory/Kconfig b/drivers/memory/Kconfig index 91774e6ee6240e3718c4a657c8ac35471caa56e4..8efdd1f9713950766fa04eac0c215988fbdb1b60 100644 --- a/drivers/memory/Kconfig +++ b/drivers/memory/Kconfig @@ -30,17 +30,6 @@ config ARM_PL172_MPMC If you have an embedded system with an AMBA bus and a PL172 controller, say Y or M here. -config ATMEL_SDRAMC - bool "Atmel (Multi-port DDR-)SDRAM Controller" - default y if ARCH_AT91 - depends on ARCH_AT91 || COMPILE_TEST - depends on OF - help - This driver is for Atmel SDRAM Controller or Atmel Multi-port - DDR-SDRAM Controller available on Atmel AT91SAM9 and SAMA5 SoCs. - Starting with the at91sam9g45, this controller supports SDR, DDR and - LP-DDR memories. - config ATMEL_EBI bool "Atmel EBI driver" default y if ARCH_AT91 diff --git a/drivers/memory/Makefile b/drivers/memory/Makefile index ae14ded464a840bd94e75bbf2a97841a42130144..d2e6ca9abbe0231c14284e3818ce734c618f83d0 100644 --- a/drivers/memory/Makefile +++ b/drivers/memory/Makefile @@ -8,7 +8,6 @@ ifeq ($(CONFIG_DDR),y) obj-$(CONFIG_OF) += of_memory.o endif obj-$(CONFIG_ARM_PL172_MPMC) += pl172.o -obj-$(CONFIG_ATMEL_SDRAMC) += atmel-sdramc.o obj-$(CONFIG_ATMEL_EBI) += atmel-ebi.o obj-$(CONFIG_BRCMSTB_DPFE) += brcmstb_dpfe.o obj-$(CONFIG_BRCMSTB_MEMC) += brcmstb_memc.o diff --git a/drivers/memory/atmel-sdramc.c b/drivers/memory/atmel-sdramc.c deleted file mode 100644 index ea6e9e1eaf04687cd6a9cec822a72467782cbe4e..0000000000000000000000000000000000000000 --- a/drivers/memory/atmel-sdramc.c +++ /dev/null @@ -1,74 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Atmel (Multi-port DDR-)SDRAM Controller driver - * - * Author: Alexandre Belloni - * - * Copyright (C) 2014 Atmel - */ - -#include -#include -#include -#include -#include -#include - -struct at91_ramc_caps { - bool has_ddrck; - bool has_mpddr_clk; -}; - -static const struct at91_ramc_caps at91rm9200_caps = { }; - -static const struct at91_ramc_caps at91sam9g45_caps = { - .has_ddrck = 1, - .has_mpddr_clk = 0, -}; - -static const struct at91_ramc_caps sama5d3_caps = { - .has_ddrck = 1, - .has_mpddr_clk = 1, -}; - -static const struct of_device_id atmel_ramc_of_match[] = { - { .compatible = "atmel,at91rm9200-sdramc", .data = &at91rm9200_caps, }, - { .compatible = "atmel,at91sam9260-sdramc", .data = &at91rm9200_caps, }, - { .compatible = "atmel,at91sam9g45-ddramc", .data = &at91sam9g45_caps, }, - { .compatible = "atmel,sama5d3-ddramc", .data = &sama5d3_caps, }, - {}, -}; - -static int atmel_ramc_probe(struct platform_device *pdev) -{ - const struct at91_ramc_caps *caps; - struct clk *clk; - - caps = of_device_get_match_data(&pdev->dev); - - if (caps->has_ddrck) { - clk = devm_clk_get_enabled(&pdev->dev, "ddrck"); - if (IS_ERR(clk)) - return PTR_ERR(clk); - } - - if (caps->has_mpddr_clk) { - clk = devm_clk_get_enabled(&pdev->dev, "mpddr"); - if (IS_ERR(clk)) { - pr_err("AT91 RAMC: couldn't get mpddr clock\n"); - return PTR_ERR(clk); - } - } - - return 0; -} - -static struct platform_driver atmel_ramc_driver = { - .probe = atmel_ramc_probe, - .driver = { - .name = "atmel-ramc", - .of_match_table = atmel_ramc_of_match, - }, -}; - -builtin_platform_driver(atmel_ramc_driver); diff --git a/drivers/memory/brcmstb_dpfe.c b/drivers/memory/brcmstb_dpfe.c index 76c82e9c8fcebd36139b21bbcf97a08496ec55f5..9339f80b21c50fbd7e362cadf68f7bc6b9d94308 100644 --- a/drivers/memory/brcmstb_dpfe.c +++ b/drivers/memory/brcmstb_dpfe.c @@ -434,15 +434,17 @@ static void __finalize_command(struct brcmstb_dpfe_priv *priv) static int __send_command(struct brcmstb_dpfe_priv *priv, unsigned int cmd, u32 result[]) { - const u32 *msg = priv->dpfe_api->command[cmd]; void __iomem *regs = priv->regs; unsigned int i, chksum, chksum_idx; + const u32 *msg; int ret = 0; u32 resp; if (cmd >= DPFE_CMD_MAX) return -1; + msg = priv->dpfe_api->command[cmd]; + mutex_lock(&priv->lock); /* Wait for DCPU to become ready */ diff --git a/drivers/memory/renesas-rpc-if.c b/drivers/memory/renesas-rpc-if.c index 025bb628aaf3381523e403ae4659b016b117a1a3..75fcba45ec1bae67f6f206441b4d01d28152d78f 100644 --- a/drivers/memory/renesas-rpc-if.c +++ b/drivers/memory/renesas-rpc-if.c @@ -7,6 +7,7 @@ * Copyright (C) 2019-2020 Cogent Embedded, Inc. */ +#include #include #include #include @@ -163,6 +164,11 @@ static const struct regmap_access_table rpcif_volatile_table = { .n_yes_ranges = ARRAY_SIZE(rpcif_volatile_ranges), }; +struct rpcif_info { + enum rpcif_type type; + u8 strtim; +}; + struct rpcif_priv { struct device *dev; void __iomem *base; @@ -171,7 +177,7 @@ struct rpcif_priv { struct reset_control *rstc; struct platform_device *vdev; size_t size; - enum rpcif_type type; + const struct rpcif_info *info; enum rpcif_data_dir dir; u8 bus_size; u8 xfer_size; @@ -186,6 +192,26 @@ struct rpcif_priv { u32 ddr; /* DRDRENR or SMDRENR */ }; +static const struct rpcif_info rpcif_info_r8a7796 = { + .type = RPCIF_RCAR_GEN3, + .strtim = 6, +}; + +static const struct rpcif_info rpcif_info_gen3 = { + .type = RPCIF_RCAR_GEN3, + .strtim = 7, +}; + +static const struct rpcif_info rpcif_info_rz_g2l = { + .type = RPCIF_RZ_G2L, + .strtim = 7, +}; + +static const struct rpcif_info rpcif_info_gen4 = { + .type = RPCIF_RCAR_GEN4, + .strtim = 15, +}; + /* * Custom accessor functions to ensure SM[RW]DR[01] are always accessed with * proper width. Requires rpcif_priv.xfer_size to be correctly set before! @@ -310,7 +336,7 @@ int rpcif_hw_init(struct device *dev, bool hyperflash) if (ret) return ret; - if (rpc->type == RPCIF_RZ_G2L) { + if (rpc->info->type == RPCIF_RZ_G2L) { ret = reset_control_reset(rpc->rstc); if (ret) return ret; @@ -324,12 +350,10 @@ int rpcif_hw_init(struct device *dev, bool hyperflash) /* DMA Transfer is not supported */ regmap_update_bits(rpc->regmap, RPCIF_PHYCNT, RPCIF_PHYCNT_HS, 0); - if (rpc->type == RPCIF_RCAR_GEN3) - regmap_update_bits(rpc->regmap, RPCIF_PHYCNT, - RPCIF_PHYCNT_STRTIM(7), RPCIF_PHYCNT_STRTIM(7)); - else if (rpc->type == RPCIF_RCAR_GEN4) - regmap_update_bits(rpc->regmap, RPCIF_PHYCNT, - RPCIF_PHYCNT_STRTIM(15), RPCIF_PHYCNT_STRTIM(15)); + regmap_update_bits(rpc->regmap, RPCIF_PHYCNT, + /* create mask with all affected bits set */ + RPCIF_PHYCNT_STRTIM(BIT(fls(rpc->info->strtim)) - 1), + RPCIF_PHYCNT_STRTIM(rpc->info->strtim)); regmap_update_bits(rpc->regmap, RPCIF_PHYOFFSET1, RPCIF_PHYOFFSET1_DDRTMG(3), RPCIF_PHYOFFSET1_DDRTMG(3)); @@ -340,7 +364,7 @@ int rpcif_hw_init(struct device *dev, bool hyperflash) regmap_update_bits(rpc->regmap, RPCIF_PHYINT, RPCIF_PHYINT_WPVAL, 0); - if (rpc->type == RPCIF_RZ_G2L) + if (rpc->info->type == RPCIF_RZ_G2L) regmap_update_bits(rpc->regmap, RPCIF_CMNCR, RPCIF_CMNCR_MOIIO(3) | RPCIF_CMNCR_IOFV(3) | RPCIF_CMNCR_BSZ(3), @@ -729,9 +753,9 @@ static int rpcif_probe(struct platform_device *pdev) rpc->dirmap = devm_ioremap_resource(dev, res); if (IS_ERR(rpc->dirmap)) return PTR_ERR(rpc->dirmap); - rpc->size = resource_size(res); - rpc->type = (uintptr_t)of_device_get_match_data(dev); + rpc->size = resource_size(res); + rpc->info = of_device_get_match_data(dev); rpc->rstc = devm_reset_control_get_exclusive(dev, NULL); if (IS_ERR(rpc->rstc)) return PTR_ERR(rpc->rstc); @@ -764,9 +788,10 @@ static int rpcif_remove(struct platform_device *pdev) } static const struct of_device_id rpcif_of_match[] = { - { .compatible = "renesas,rcar-gen3-rpc-if", .data = (void *)RPCIF_RCAR_GEN3 }, - { .compatible = "renesas,rcar-gen4-rpc-if", .data = (void *)RPCIF_RCAR_GEN4 }, - { .compatible = "renesas,rzg2l-rpc-if", .data = (void *)RPCIF_RZ_G2L }, + { .compatible = "renesas,r8a7796-rpc-if", .data = &rpcif_info_r8a7796 }, + { .compatible = "renesas,rcar-gen3-rpc-if", .data = &rpcif_info_gen3 }, + { .compatible = "renesas,rcar-gen4-rpc-if", .data = &rpcif_info_gen4 }, + { .compatible = "renesas,rzg2l-rpc-if", .data = &rpcif_info_rz_g2l }, {}, }; MODULE_DEVICE_TABLE(of, rpcif_of_match); diff --git a/drivers/memory/tegra/mc.c b/drivers/memory/tegra/mc.c index 9082b6c3763dcc16b11dcd418c9b95bd94fa0547..4a750da1c12aaee09a1e17ea0108b01ac55aa52d 100644 --- a/drivers/memory/tegra/mc.c +++ b/drivers/memory/tegra/mc.c @@ -15,6 +15,7 @@ #include #include #include +#include #include @@ -792,6 +793,8 @@ static int tegra_mc_interconnect_setup(struct tegra_mc *mc) mc->provider.data = &mc->provider; mc->provider.set = mc->soc->icc_ops->set; mc->provider.aggregate = mc->soc->icc_ops->aggregate; + mc->provider.get_bw = mc->soc->icc_ops->get_bw; + mc->provider.xlate = mc->soc->icc_ops->xlate; mc->provider.xlate_extended = mc->soc->icc_ops->xlate_extended; icc_provider_init(&mc->provider); @@ -824,6 +827,8 @@ static int tegra_mc_interconnect_setup(struct tegra_mc *mc) err = icc_link_create(node, TEGRA_ICC_MC); if (err) goto remove_nodes; + + node->data = (struct tegra_mc_client *)&(mc->soc->clients[i]); } err = icc_provider_register(&mc->provider); @@ -838,6 +843,23 @@ static int tegra_mc_interconnect_setup(struct tegra_mc *mc) return err; } +static void tegra_mc_num_channel_enabled(struct tegra_mc *mc) +{ + unsigned int i; + u32 value; + + value = mc_ch_readl(mc, 0, MC_EMEM_ADR_CFG_CHANNEL_ENABLE); + if (value <= 0) { + mc->num_channels = mc->soc->num_channels; + return; + } + + for (i = 0; i < 32; i++) { + if (value & BIT(i)) + mc->num_channels++; + } +} + static int tegra_mc_probe(struct platform_device *pdev) { struct tegra_mc *mc; @@ -876,6 +898,8 @@ static int tegra_mc_probe(struct platform_device *pdev) return err; } + tegra_mc_num_channel_enabled(mc); + if (mc->soc->ops && mc->soc->ops->handle_irq) { mc->irq = platform_get_irq(pdev, 0); if (mc->irq < 0) diff --git a/drivers/memory/tegra/mc.h b/drivers/memory/tegra/mc.h index bc01586b65602cc2259a6ef7dfe52477605cac2d..c3f6655bec60e8cc40aeb1caf29b4c9d7b86f48d 100644 --- a/drivers/memory/tegra/mc.h +++ b/drivers/memory/tegra/mc.h @@ -53,6 +53,7 @@ #define MC_ERR_ROUTE_SANITY_ADR 0x9c4 #define MC_ERR_GENERALIZED_CARVEOUT_STATUS 0xc00 #define MC_ERR_GENERALIZED_CARVEOUT_ADR 0xc04 +#define MC_EMEM_ADR_CFG_CHANNEL_ENABLE 0xdf8 #define MC_GLOBAL_INTSTATUS 0xf24 #define MC_ERR_ADR_HI 0x11fc diff --git a/drivers/memory/tegra/tegra186-emc.c b/drivers/memory/tegra/tegra186-emc.c index e935ad4e95b68729bd42e53de80e6a1e41154d3f..6ad8a4023dd730e181127dde2464ad7535ff231f 100644 --- a/drivers/memory/tegra/tegra186-emc.c +++ b/drivers/memory/tegra/tegra186-emc.c @@ -7,9 +7,11 @@ #include #include #include +#include #include #include +#include "mc.h" struct tegra186_emc_dvfs { unsigned long latency; @@ -29,8 +31,15 @@ struct tegra186_emc { unsigned long min_rate; unsigned long max_rate; } debugfs; + + struct icc_provider provider; }; +static inline struct tegra186_emc *to_tegra186_emc(struct icc_provider *provider) +{ + return container_of(provider, struct tegra186_emc, provider); +} + /* * debugfs interface * @@ -146,8 +155,102 @@ DEFINE_DEBUGFS_ATTRIBUTE(tegra186_emc_debug_max_rate_fops, tegra186_emc_debug_max_rate_get, tegra186_emc_debug_max_rate_set, "%llu\n"); +/* + * tegra_emc_icc_set_bw() - Set BW api for EMC provider + * @src: ICC node for External Memory Controller (EMC) + * @dst: ICC node for External Memory (DRAM) + * + * Do nothing here as info to BPMP-FW is now passed in the BW set function + * of the MC driver. BPMP-FW sets the final Freq based on the passed values. + */ +static int tegra_emc_icc_set_bw(struct icc_node *src, struct icc_node *dst) +{ + return 0; +} + +static struct icc_node * +tegra_emc_of_icc_xlate(struct of_phandle_args *spec, void *data) +{ + struct icc_provider *provider = data; + struct icc_node *node; + + /* External Memory is the only possible ICC route */ + list_for_each_entry(node, &provider->nodes, node_list) { + if (node->id != TEGRA_ICC_EMEM) + continue; + + return node; + } + + return ERR_PTR(-EPROBE_DEFER); +} + +static int tegra_emc_icc_get_init_bw(struct icc_node *node, u32 *avg, u32 *peak) +{ + *avg = 0; + *peak = 0; + + return 0; +} + +static int tegra_emc_interconnect_init(struct tegra186_emc *emc) +{ + struct tegra_mc *mc = dev_get_drvdata(emc->dev->parent); + const struct tegra_mc_soc *soc = mc->soc; + struct icc_node *node; + int err; + + emc->provider.dev = emc->dev; + emc->provider.set = tegra_emc_icc_set_bw; + emc->provider.data = &emc->provider; + emc->provider.aggregate = soc->icc_ops->aggregate; + emc->provider.xlate = tegra_emc_of_icc_xlate; + emc->provider.get_bw = tegra_emc_icc_get_init_bw; + + icc_provider_init(&emc->provider); + + /* create External Memory Controller node */ + node = icc_node_create(TEGRA_ICC_EMC); + if (IS_ERR(node)) { + err = PTR_ERR(node); + goto err_msg; + } + + node->name = "External Memory Controller"; + icc_node_add(node, &emc->provider); + + /* link External Memory Controller to External Memory (DRAM) */ + err = icc_link_create(node, TEGRA_ICC_EMEM); + if (err) + goto remove_nodes; + + /* create External Memory node */ + node = icc_node_create(TEGRA_ICC_EMEM); + if (IS_ERR(node)) { + err = PTR_ERR(node); + goto remove_nodes; + } + + node->name = "External Memory (DRAM)"; + icc_node_add(node, &emc->provider); + + err = icc_provider_register(&emc->provider); + if (err) + goto remove_nodes; + + return 0; + +remove_nodes: + icc_nodes_remove(&emc->provider); +err_msg: + dev_err(emc->dev, "failed to initialize ICC: %d\n", err); + + return err; +} + static int tegra186_emc_probe(struct platform_device *pdev) { + struct tegra_mc *mc = dev_get_drvdata(pdev->dev.parent); struct mrq_emc_dvfs_latency_response response; struct tegra_bpmp_message msg; struct tegra186_emc *emc; @@ -236,6 +339,32 @@ static int tegra186_emc_probe(struct platform_device *pdev) debugfs_create_file("max_rate", S_IRUGO | S_IWUSR, emc->debugfs.root, emc, &tegra186_emc_debug_max_rate_fops); + if (mc && mc->soc->icc_ops) { + if (tegra_bpmp_mrq_is_supported(emc->bpmp, MRQ_BWMGR_INT)) { + mc->bwmgr_mrq_supported = true; + + /* + * MC driver probe can't get BPMP reference as it gets probed + * earlier than BPMP. So, save the BPMP ref got from the EMC + * DT node in the mc->bpmp and use it in MC's icc_set hook. + */ + mc->bpmp = emc->bpmp; + barrier(); + } + + /* + * Initialize the ICC even if BPMP-FW doesn't support 'MRQ_BWMGR_INT'. + * Use the flag 'mc->bwmgr_mrq_supported' within MC driver and return + * EINVAL instead of passing the request to BPMP-FW later when the BW + * request is made by client with 'icc_set_bw()' call. + */ + err = tegra_emc_interconnect_init(emc); + if (err) { + mc->bpmp = NULL; + goto put_bpmp; + } + } + return 0; put_bpmp: @@ -245,9 +374,12 @@ static int tegra186_emc_probe(struct platform_device *pdev) static int tegra186_emc_remove(struct platform_device *pdev) { + struct tegra_mc *mc = dev_get_drvdata(pdev->dev.parent); struct tegra186_emc *emc = platform_get_drvdata(pdev); debugfs_remove_recursive(emc->debugfs.root); + + mc->bpmp = NULL; tegra_bpmp_put(emc->bpmp); return 0; @@ -272,6 +404,7 @@ static struct platform_driver tegra186_emc_driver = { .name = "tegra186-emc", .of_match_table = tegra186_emc_of_match, .suppress_bind_attrs = true, + .sync_state = icc_sync_state, }, .probe = tegra186_emc_probe, .remove = tegra186_emc_remove, diff --git a/drivers/memory/tegra/tegra234.c b/drivers/memory/tegra/tegra234.c index 02dcc5748bba2d16cfb9fd3fdd240078055231e7..8e873a7bc34f29b98fc762e22b801037d58bffec 100644 --- a/drivers/memory/tegra/tegra234.c +++ b/drivers/memory/tegra/tegra234.c @@ -1,18 +1,47 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (C) 2021-2022, NVIDIA CORPORATION. All rights reserved. + * Copyright (C) 2022-2023, NVIDIA CORPORATION. All rights reserved. */ #include #include +#include +#include +#include #include "mc.h" static const struct tegra_mc_client tegra234_mc_clients[] = { { + .id = TEGRA234_MEMORY_CLIENT_HDAR, + .name = "hdar", + .bpmp_id = TEGRA_ICC_BPMP_HDA, + .type = TEGRA_ICC_ISO_AUDIO, + .sid = TEGRA234_SID_HDA, + .regs = { + .sid = { + .override = 0xa8, + .security = 0xac, + }, + }, + }, { + .id = TEGRA234_MEMORY_CLIENT_HDAW, + .name = "hdaw", + .bpmp_id = TEGRA_ICC_BPMP_HDA, + .type = TEGRA_ICC_ISO_AUDIO, + .sid = TEGRA234_SID_HDA, + .regs = { + .sid = { + .override = 0x1a8, + .security = 0x1ac, + }, + }, + }, { .id = TEGRA234_MEMORY_CLIENT_MGBEARD, .name = "mgbeard", + .bpmp_id = TEGRA_ICC_BPMP_EQOS, + .type = TEGRA_ICC_NISO, .sid = TEGRA234_SID_MGBE, .regs = { .sid = { @@ -23,6 +52,8 @@ static const struct tegra_mc_client tegra234_mc_clients[] = { }, { .id = TEGRA234_MEMORY_CLIENT_MGBEBRD, .name = "mgbebrd", + .bpmp_id = TEGRA_ICC_BPMP_EQOS, + .type = TEGRA_ICC_NISO, .sid = TEGRA234_SID_MGBE_VF1, .regs = { .sid = { @@ -33,6 +64,8 @@ static const struct tegra_mc_client tegra234_mc_clients[] = { }, { .id = TEGRA234_MEMORY_CLIENT_MGBECRD, .name = "mgbecrd", + .bpmp_id = TEGRA_ICC_BPMP_EQOS, + .type = TEGRA_ICC_NISO, .sid = TEGRA234_SID_MGBE_VF2, .regs = { .sid = { @@ -43,6 +76,8 @@ static const struct tegra_mc_client tegra234_mc_clients[] = { }, { .id = TEGRA234_MEMORY_CLIENT_MGBEDRD, .name = "mgbedrd", + .bpmp_id = TEGRA_ICC_BPMP_EQOS, + .type = TEGRA_ICC_NISO, .sid = TEGRA234_SID_MGBE_VF3, .regs = { .sid = { @@ -52,6 +87,8 @@ static const struct tegra_mc_client tegra234_mc_clients[] = { }, }, { .id = TEGRA234_MEMORY_CLIENT_MGBEAWR, + .bpmp_id = TEGRA_ICC_BPMP_EQOS, + .type = TEGRA_ICC_NISO, .name = "mgbeawr", .sid = TEGRA234_SID_MGBE, .regs = { @@ -63,6 +100,8 @@ static const struct tegra_mc_client tegra234_mc_clients[] = { }, { .id = TEGRA234_MEMORY_CLIENT_MGBEBWR, .name = "mgbebwr", + .bpmp_id = TEGRA_ICC_BPMP_EQOS, + .type = TEGRA_ICC_NISO, .sid = TEGRA234_SID_MGBE_VF1, .regs = { .sid = { @@ -73,6 +112,8 @@ static const struct tegra_mc_client tegra234_mc_clients[] = { }, { .id = TEGRA234_MEMORY_CLIENT_MGBECWR, .name = "mgbecwr", + .bpmp_id = TEGRA_ICC_BPMP_EQOS, + .type = TEGRA_ICC_NISO, .sid = TEGRA234_SID_MGBE_VF2, .regs = { .sid = { @@ -83,6 +124,8 @@ static const struct tegra_mc_client tegra234_mc_clients[] = { }, { .id = TEGRA234_MEMORY_CLIENT_SDMMCRAB, .name = "sdmmcrab", + .bpmp_id = TEGRA_ICC_BPMP_SDMMC_4, + .type = TEGRA_ICC_NISO, .sid = TEGRA234_SID_SDMMC4, .regs = { .sid = { @@ -93,6 +136,8 @@ static const struct tegra_mc_client tegra234_mc_clients[] = { }, { .id = TEGRA234_MEMORY_CLIENT_MGBEDWR, .name = "mgbedwr", + .bpmp_id = TEGRA_ICC_BPMP_EQOS, + .type = TEGRA_ICC_NISO, .sid = TEGRA234_SID_MGBE_VF3, .regs = { .sid = { @@ -103,6 +148,8 @@ static const struct tegra_mc_client tegra234_mc_clients[] = { }, { .id = TEGRA234_MEMORY_CLIENT_SDMMCWAB, .name = "sdmmcwab", + .bpmp_id = TEGRA_ICC_BPMP_SDMMC_4, + .type = TEGRA_ICC_NISO, .sid = TEGRA234_SID_SDMMC4, .regs = { .sid = { @@ -110,6 +157,90 @@ static const struct tegra_mc_client tegra234_mc_clients[] = { .security = 0x33c, }, }, + }, { + .id = TEGRA234_MEMORY_CLIENT_VI2W, + .name = "vi2w", + .bpmp_id = TEGRA_ICC_BPMP_VI2, + .type = TEGRA_ICC_ISO_VI, + .sid = TEGRA234_SID_ISO_VI2, + .regs = { + .sid = { + .override = 0x380, + .security = 0x384, + }, + }, + }, { + .id = TEGRA234_MEMORY_CLIENT_VI2FALR, + .name = "vi2falr", + .bpmp_id = TEGRA_ICC_BPMP_VI2FAL, + .type = TEGRA_ICC_ISO_VIFAL, + .sid = TEGRA234_SID_ISO_VI2FALC, + .regs = { + .sid = { + .override = 0x388, + .security = 0x38c, + }, + }, + }, { + .id = TEGRA234_MEMORY_CLIENT_VI2FALW, + .name = "vi2falw", + .bpmp_id = TEGRA_ICC_BPMP_VI2FAL, + .type = TEGRA_ICC_ISO_VIFAL, + .sid = TEGRA234_SID_ISO_VI2FALC, + .regs = { + .sid = { + .override = 0x3e0, + .security = 0x3e4, + }, + }, + }, { + .id = TEGRA234_MEMORY_CLIENT_APER, + .name = "aper", + .bpmp_id = TEGRA_ICC_BPMP_APE, + .type = TEGRA_ICC_ISO_AUDIO, + .sid = TEGRA234_SID_APE, + .regs = { + .sid = { + .override = 0x3d0, + .security = 0x3d4, + }, + }, + }, { + .id = TEGRA234_MEMORY_CLIENT_APEW, + .name = "apew", + .bpmp_id = TEGRA_ICC_BPMP_APE, + .type = TEGRA_ICC_ISO_AUDIO, + .sid = TEGRA234_SID_APE, + .regs = { + .sid = { + .override = 0x3d8, + .security = 0x3dc, + }, + }, + }, { + .id = TEGRA234_MEMORY_CLIENT_NVDISPLAYR, + .name = "nvdisplayr", + .bpmp_id = TEGRA_ICC_BPMP_DISPLAY, + .type = TEGRA_ICC_ISO_DISPLAY, + .sid = TEGRA234_SID_ISO_NVDISPLAY, + .regs = { + .sid = { + .override = 0x490, + .security = 0x494, + }, + }, + }, { + .id = TEGRA234_MEMORY_CLIENT_NVDISPLAYR1, + .name = "nvdisplayr1", + .bpmp_id = TEGRA_ICC_BPMP_DISPLAY, + .type = TEGRA_ICC_ISO_DISPLAY, + .sid = TEGRA234_SID_ISO_NVDISPLAY, + .regs = { + .sid = { + .override = 0x508, + .security = 0x50c, + }, + }, }, { .id = TEGRA234_MEMORY_CLIENT_BPMPR, .name = "bpmpr", @@ -153,6 +284,8 @@ static const struct tegra_mc_client tegra234_mc_clients[] = { }, { .id = TEGRA234_MEMORY_CLIENT_APEDMAR, .name = "apedmar", + .bpmp_id = TEGRA_ICC_BPMP_APEDMA, + .type = TEGRA_ICC_ISO_AUDIO, .sid = TEGRA234_SID_APE, .regs = { .sid = { @@ -163,6 +296,8 @@ static const struct tegra_mc_client tegra234_mc_clients[] = { }, { .id = TEGRA234_MEMORY_CLIENT_APEDMAW, .name = "apedmaw", + .bpmp_id = TEGRA_ICC_BPMP_APEDMA, + .type = TEGRA_ICC_ISO_AUDIO, .sid = TEGRA234_SID_APE, .regs = { .sid = { @@ -330,9 +465,466 @@ static const struct tegra_mc_client tegra234_mc_clients[] = { .security = 0x37c, }, }, + }, { + .id = TEGRA234_MEMORY_CLIENT_PCIE0R, + .name = "pcie0r", + .bpmp_id = TEGRA_ICC_BPMP_PCIE_0, + .type = TEGRA_ICC_NISO, + .sid = TEGRA234_SID_PCIE0, + .regs = { + .sid = { + .override = 0x6c0, + .security = 0x6c4, + }, + }, + }, { + .id = TEGRA234_MEMORY_CLIENT_PCIE0W, + .name = "pcie0w", + .bpmp_id = TEGRA_ICC_BPMP_PCIE_0, + .type = TEGRA_ICC_NISO, + .sid = TEGRA234_SID_PCIE0, + .regs = { + .sid = { + .override = 0x6c8, + .security = 0x6cc, + }, + }, + }, { + .id = TEGRA234_MEMORY_CLIENT_PCIE1R, + .name = "pcie1r", + .bpmp_id = TEGRA_ICC_BPMP_PCIE_1, + .type = TEGRA_ICC_NISO, + .sid = TEGRA234_SID_PCIE1, + .regs = { + .sid = { + .override = 0x6d0, + .security = 0x6d4, + }, + }, + }, { + .id = TEGRA234_MEMORY_CLIENT_PCIE1W, + .name = "pcie1w", + .bpmp_id = TEGRA_ICC_BPMP_PCIE_1, + .type = TEGRA_ICC_NISO, + .sid = TEGRA234_SID_PCIE1, + .regs = { + .sid = { + .override = 0x6d8, + .security = 0x6dc, + }, + }, + }, { + .id = TEGRA234_MEMORY_CLIENT_PCIE2AR, + .name = "pcie2ar", + .bpmp_id = TEGRA_ICC_BPMP_PCIE_2, + .type = TEGRA_ICC_NISO, + .sid = TEGRA234_SID_PCIE2, + .regs = { + .sid = { + .override = 0x6e0, + .security = 0x6e4, + }, + }, + }, { + .id = TEGRA234_MEMORY_CLIENT_PCIE2AW, + .name = "pcie2aw", + .bpmp_id = TEGRA_ICC_BPMP_PCIE_2, + .type = TEGRA_ICC_NISO, + .sid = TEGRA234_SID_PCIE2, + .regs = { + .sid = { + .override = 0x6e8, + .security = 0x6ec, + }, + }, + }, { + .id = TEGRA234_MEMORY_CLIENT_PCIE3R, + .name = "pcie3r", + .bpmp_id = TEGRA_ICC_BPMP_PCIE_3, + .type = TEGRA_ICC_NISO, + .sid = TEGRA234_SID_PCIE3, + .regs = { + .sid = { + .override = 0x6f0, + .security = 0x6f4, + }, + }, + }, { + .id = TEGRA234_MEMORY_CLIENT_PCIE3W, + .name = "pcie3w", + .bpmp_id = TEGRA_ICC_BPMP_PCIE_3, + .type = TEGRA_ICC_NISO, + .sid = TEGRA234_SID_PCIE3, + .regs = { + .sid = { + .override = 0x6f8, + .security = 0x6fc, + }, + }, + }, { + .id = TEGRA234_MEMORY_CLIENT_PCIE4R, + .name = "pcie4r", + .bpmp_id = TEGRA_ICC_BPMP_PCIE_4, + .type = TEGRA_ICC_NISO, + .sid = TEGRA234_SID_PCIE4, + .regs = { + .sid = { + .override = 0x700, + .security = 0x704, + }, + }, + }, { + .id = TEGRA234_MEMORY_CLIENT_PCIE4W, + .name = "pcie4w", + .bpmp_id = TEGRA_ICC_BPMP_PCIE_4, + .type = TEGRA_ICC_NISO, + .sid = TEGRA234_SID_PCIE4, + .regs = { + .sid = { + .override = 0x708, + .security = 0x70c, + }, + }, + }, { + .id = TEGRA234_MEMORY_CLIENT_PCIE5R, + .name = "pcie5r", + .bpmp_id = TEGRA_ICC_BPMP_PCIE_5, + .type = TEGRA_ICC_NISO, + .sid = TEGRA234_SID_PCIE5, + .regs = { + .sid = { + .override = 0x710, + .security = 0x714, + }, + }, + }, { + .id = TEGRA234_MEMORY_CLIENT_PCIE5W, + .name = "pcie5w", + .bpmp_id = TEGRA_ICC_BPMP_PCIE_5, + .type = TEGRA_ICC_NISO, + .sid = TEGRA234_SID_PCIE5, + .regs = { + .sid = { + .override = 0x718, + .security = 0x71c, + }, + }, + }, { + .id = TEGRA234_MEMORY_CLIENT_PCIE5R1, + .name = "pcie5r1", + .bpmp_id = TEGRA_ICC_BPMP_PCIE_5, + .type = TEGRA_ICC_NISO, + .sid = TEGRA234_SID_PCIE5, + .regs = { + .sid = { + .override = 0x778, + .security = 0x77c, + }, + }, + }, { + .id = TEGRA234_MEMORY_CLIENT_PCIE6AR, + .name = "pcie6ar", + .bpmp_id = TEGRA_ICC_BPMP_PCIE_6, + .type = TEGRA_ICC_NISO, + .sid = TEGRA234_SID_PCIE6, + .regs = { + .sid = { + .override = 0x140, + .security = 0x144, + }, + }, + }, { + .id = TEGRA234_MEMORY_CLIENT_PCIE6AW, + .name = "pcie6aw", + .bpmp_id = TEGRA_ICC_BPMP_PCIE_6, + .type = TEGRA_ICC_NISO, + .sid = TEGRA234_SID_PCIE6, + .regs = { + .sid = { + .override = 0x148, + .security = 0x14c, + }, + }, + }, { + .id = TEGRA234_MEMORY_CLIENT_PCIE6AR1, + .name = "pcie6ar1", + .bpmp_id = TEGRA_ICC_BPMP_PCIE_6, + .type = TEGRA_ICC_NISO, + .sid = TEGRA234_SID_PCIE6, + .regs = { + .sid = { + .override = 0x1e8, + .security = 0x1ec, + }, + }, + }, { + .id = TEGRA234_MEMORY_CLIENT_PCIE7AR, + .name = "pcie7ar", + .bpmp_id = TEGRA_ICC_BPMP_PCIE_7, + .type = TEGRA_ICC_NISO, + .sid = TEGRA234_SID_PCIE7, + .regs = { + .sid = { + .override = 0x150, + .security = 0x154, + }, + }, + }, { + .id = TEGRA234_MEMORY_CLIENT_PCIE7AW, + .name = "pcie7aw", + .bpmp_id = TEGRA_ICC_BPMP_PCIE_7, + .type = TEGRA_ICC_NISO, + .sid = TEGRA234_SID_PCIE7, + .regs = { + .sid = { + .override = 0x180, + .security = 0x184, + }, + }, + }, { + .id = TEGRA234_MEMORY_CLIENT_PCIE7AR1, + .name = "pcie7ar1", + .bpmp_id = TEGRA_ICC_BPMP_PCIE_7, + .type = TEGRA_ICC_NISO, + .sid = TEGRA234_SID_PCIE7, + .regs = { + .sid = { + .override = 0x248, + .security = 0x24c, + }, + }, + }, { + .id = TEGRA234_MEMORY_CLIENT_PCIE8AR, + .name = "pcie8ar", + .bpmp_id = TEGRA_ICC_BPMP_PCIE_8, + .type = TEGRA_ICC_NISO, + .sid = TEGRA234_SID_PCIE8, + .regs = { + .sid = { + .override = 0x190, + .security = 0x194, + }, + }, + }, { + .id = TEGRA234_MEMORY_CLIENT_PCIE8AW, + .name = "pcie8aw", + .bpmp_id = TEGRA_ICC_BPMP_PCIE_8, + .type = TEGRA_ICC_NISO, + .sid = TEGRA234_SID_PCIE8, + .regs = { + .sid = { + .override = 0x1d8, + .security = 0x1dc, + }, + }, + }, { + .id = TEGRA234_MEMORY_CLIENT_PCIE9AR, + .name = "pcie9ar", + .bpmp_id = TEGRA_ICC_BPMP_PCIE_9, + .type = TEGRA_ICC_NISO, + .sid = TEGRA234_SID_PCIE9, + .regs = { + .sid = { + .override = 0x1e0, + .security = 0x1e4, + }, + }, + }, { + .id = TEGRA234_MEMORY_CLIENT_PCIE9AW, + .name = "pcie9aw", + .bpmp_id = TEGRA_ICC_BPMP_PCIE_9, + .type = TEGRA_ICC_NISO, + .sid = TEGRA234_SID_PCIE9, + .regs = { + .sid = { + .override = 0x1f0, + .security = 0x1f4, + }, + }, + }, { + .id = TEGRA234_MEMORY_CLIENT_PCIE10AR, + .name = "pcie10ar", + .bpmp_id = TEGRA_ICC_BPMP_PCIE_10, + .type = TEGRA_ICC_NISO, + .sid = TEGRA234_SID_PCIE10, + .regs = { + .sid = { + .override = 0x1f8, + .security = 0x1fc, + }, + }, + }, { + .id = TEGRA234_MEMORY_CLIENT_PCIE10AW, + .name = "pcie10aw", + .bpmp_id = TEGRA_ICC_BPMP_PCIE_10, + .type = TEGRA_ICC_NISO, + .sid = TEGRA234_SID_PCIE10, + .regs = { + .sid = { + .override = 0x200, + .security = 0x204, + }, + }, + }, { + .id = TEGRA234_MEMORY_CLIENT_PCIE10AR1, + .name = "pcie10ar1", + .bpmp_id = TEGRA_ICC_BPMP_PCIE_10, + .type = TEGRA_ICC_NISO, + .sid = TEGRA234_SID_PCIE10, + .regs = { + .sid = { + .override = 0x240, + .security = 0x244, + }, + }, + }, { + .id = TEGRA_ICC_MC_CPU_CLUSTER0, + .name = "sw_cluster0", + .bpmp_id = TEGRA_ICC_BPMP_CPU_CLUSTER0, + .type = TEGRA_ICC_NISO, + }, { + .id = TEGRA_ICC_MC_CPU_CLUSTER1, + .name = "sw_cluster1", + .bpmp_id = TEGRA_ICC_BPMP_CPU_CLUSTER1, + .type = TEGRA_ICC_NISO, + }, { + .id = TEGRA_ICC_MC_CPU_CLUSTER2, + .name = "sw_cluster2", + .bpmp_id = TEGRA_ICC_BPMP_CPU_CLUSTER2, + .type = TEGRA_ICC_NISO, }, }; +/* + * tegra234_mc_icc_set() - Pass MC client info to the BPMP-FW + * @src: ICC node for Memory Controller's (MC) Client + * @dst: ICC node for Memory Controller (MC) + * + * Passing the current request info from the MC to the BPMP-FW where + * LA and PTSA registers are accessed and the final EMC freq is set + * based on client_id, type, latency and bandwidth. + * icc_set_bw() makes set_bw calls for both MC and EMC providers in + * sequence. Both the calls are protected by 'mutex_lock(&icc_lock)'. + * So, the data passed won't be updated by concurrent set calls from + * other clients. + */ +static int tegra234_mc_icc_set(struct icc_node *src, struct icc_node *dst) +{ + struct tegra_mc *mc = icc_provider_to_tegra_mc(dst->provider); + struct mrq_bwmgr_int_request bwmgr_req = { 0 }; + struct mrq_bwmgr_int_response bwmgr_resp = { 0 }; + const struct tegra_mc_client *pclient = src->data; + struct tegra_bpmp_message msg; + int ret; + + /* + * Same Src and Dst node will happen during boot from icc_node_add(). + * This can be used to pre-initialize and set bandwidth for all clients + * before their drivers are loaded. We are skipping this case as for us, + * the pre-initialization already happened in Bootloader(MB2) and BPMP-FW. + */ + if (src->id == dst->id) + return 0; + + if (!mc->bwmgr_mrq_supported) + return -EINVAL; + + if (!mc->bpmp) { + dev_err(mc->dev, "BPMP reference NULL\n"); + return -ENOENT; + } + + if (pclient->type == TEGRA_ICC_NISO) + bwmgr_req.bwmgr_calc_set_req.niso_bw = src->avg_bw; + else + bwmgr_req.bwmgr_calc_set_req.iso_bw = src->avg_bw; + + bwmgr_req.bwmgr_calc_set_req.client_id = pclient->bpmp_id; + + bwmgr_req.cmd = CMD_BWMGR_INT_CALC_AND_SET; + bwmgr_req.bwmgr_calc_set_req.mc_floor = src->peak_bw; + bwmgr_req.bwmgr_calc_set_req.floor_unit = BWMGR_INT_UNIT_KBPS; + + memset(&msg, 0, sizeof(msg)); + msg.mrq = MRQ_BWMGR_INT; + msg.tx.data = &bwmgr_req; + msg.tx.size = sizeof(bwmgr_req); + msg.rx.data = &bwmgr_resp; + msg.rx.size = sizeof(bwmgr_resp); + + ret = tegra_bpmp_transfer(mc->bpmp, &msg); + if (ret < 0) { + dev_err(mc->dev, "BPMP transfer failed: %d\n", ret); + goto error; + } + if (msg.rx.ret < 0) { + pr_err("failed to set bandwidth for %u: %d\n", + bwmgr_req.bwmgr_calc_set_req.client_id, msg.rx.ret); + ret = -EINVAL; + } + +error: + return ret; +} + +static int tegra234_mc_icc_aggregate(struct icc_node *node, u32 tag, u32 avg_bw, + u32 peak_bw, u32 *agg_avg, u32 *agg_peak) +{ + struct icc_provider *p = node->provider; + struct tegra_mc *mc = icc_provider_to_tegra_mc(p); + + if (!mc->bwmgr_mrq_supported) + return -EINVAL; + + if (node->id == TEGRA_ICC_MC_CPU_CLUSTER0 || + node->id == TEGRA_ICC_MC_CPU_CLUSTER1 || + node->id == TEGRA_ICC_MC_CPU_CLUSTER2) { + if (mc) + peak_bw = peak_bw * mc->num_channels; + } + + *agg_avg += avg_bw; + *agg_peak = max(*agg_peak, peak_bw); + + return 0; +} + +static struct icc_node* +tegra234_mc_of_icc_xlate(struct of_phandle_args *spec, void *data) +{ + struct tegra_mc *mc = icc_provider_to_tegra_mc(data); + unsigned int cl_id = spec->args[0]; + struct icc_node *node; + + list_for_each_entry(node, &mc->provider.nodes, node_list) { + if (node->id != cl_id) + continue; + + return node; + } + + /* + * If a client driver calls devm_of_icc_get() before the MC driver + * is probed, then return EPROBE_DEFER to the client driver. + */ + return ERR_PTR(-EPROBE_DEFER); +} + +static int tegra234_mc_icc_get_init_bw(struct icc_node *node, u32 *avg, u32 *peak) +{ + *avg = 0; + *peak = 0; + + return 0; +} + +static const struct tegra_mc_icc_ops tegra234_mc_icc_ops = { + .xlate = tegra234_mc_of_icc_xlate, + .aggregate = tegra234_mc_icc_aggregate, + .get_bw = tegra234_mc_icc_get_init_bw, + .set = tegra234_mc_icc_set, +}; + const struct tegra_mc_soc tegra234_mc_soc = { .num_clients = ARRAY_SIZE(tegra234_mc_clients), .clients = tegra234_mc_clients, @@ -345,6 +937,7 @@ const struct tegra_mc_soc tegra234_mc_soc = { MC_INT_SECURITY_VIOLATION | MC_INT_DECERR_EMEM, .has_addr_hi_reg = true, .ops = &tegra186_mc_ops, + .icc_ops = &tegra234_mc_icc_ops, .ch_intmask = 0x0000ff00, .global_intstatus_channel_shift = 8, /* diff --git a/drivers/memory/ti-emif-sram-pm.S b/drivers/memory/ti-emif-sram-pm.S index d60a8cfd63f35b13ffe775a367abd648a050fe4e..7756b397124428e66184bc5466dc1107ac0b3c3c 100644 --- a/drivers/memory/ti-emif-sram-pm.S +++ b/drivers/memory/ti-emif-sram-pm.S @@ -8,7 +8,7 @@ #include #include -#include +#include #include "emif.h" #include "ti-emif-asm-offsets.h" diff --git a/drivers/memstick/host/r592.c b/drivers/memstick/host/r592.c index 42bfc46842b8271d5db351a01bde13fd5306c4dd..461f5ffd02bc1242597959bfa90d70c025913f0b 100644 --- a/drivers/memstick/host/r592.c +++ b/drivers/memstick/host/r592.c @@ -44,12 +44,10 @@ static const char *tpc_names[] = { * memstick_debug_get_tpc_name - debug helper that returns string for * a TPC number */ -const char *memstick_debug_get_tpc_name(int tpc) +static __maybe_unused const char *memstick_debug_get_tpc_name(int tpc) { return tpc_names[tpc-1]; } -EXPORT_SYMBOL(memstick_debug_get_tpc_name); - /* Read a register*/ static inline u32 r592_read_reg(struct r592_device *dev, int address) diff --git a/drivers/message/fusion/Kconfig b/drivers/message/fusion/Kconfig index a3d0288fd0e2b3c32707c11fab7e377a61be3a8f..88a6e506a9422487b17d33a06d42da5426f062d9 100644 --- a/drivers/message/fusion/Kconfig +++ b/drivers/message/fusion/Kconfig @@ -2,7 +2,7 @@ menuconfig FUSION bool "Fusion MPT device support" - depends on PCI + depends on PCI && HAS_IOPORT help Say Y here to get to see options for Fusion Message Passing Technology (MPT) drivers. diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index 4f0afce8428da45f2dac29310cf2e2de89d32a5a..4bf669c5564932616a69056598765969a138c08e 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c @@ -712,7 +712,7 @@ mpt_register(MPT_CALLBACK cbfunc, MPT_DRIVER_CLASS dclass, char *func_name) MptDriverClass[cb_idx] = dclass; MptEvHandlers[cb_idx] = NULL; last_drv_idx = cb_idx; - strlcpy(MptCallbacksName[cb_idx], func_name, + strscpy(MptCallbacksName[cb_idx], func_name, MPT_MAX_CALLBACKNAME_LEN+1); break; } @@ -7666,7 +7666,7 @@ mpt_display_event_info(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply) break; } if (ds) - strlcpy(evStr, ds, EVENT_DESCR_STR_SZ); + strscpy(evStr, ds, EVENT_DESCR_STR_SZ); devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c index 1decd09a08d8166c448fc403660addb8e6d437f9..dd028df4b283d55c24e25fa086bd400f5653c5be 100644 --- a/drivers/message/fusion/mptctl.c +++ b/drivers/message/fusion/mptctl.c @@ -2408,7 +2408,7 @@ mptctl_hp_hostinfo(MPT_ADAPTER *ioc, unsigned long arg, unsigned int data_size) if (mpt_config(ioc, &cfg) == 0) { ManufacturingPage0_t *pdata = (ManufacturingPage0_t *) pbuf; if (strlen(pdata->BoardTracerNumber) > 1) { - strlcpy(karg.serial_number, + strscpy(karg.serial_number, pdata->BoardTracerNumber, 24); } } diff --git a/drivers/mfd/88pm800.c b/drivers/mfd/88pm800.c index 4d9b61b927544f2850ac85ffe2e9975c8528b53f..300caa0673352e8777f7fde183bc916c49fc13b7 100644 --- a/drivers/mfd/88pm800.c +++ b/drivers/mfd/88pm800.c @@ -597,7 +597,7 @@ static struct i2c_driver pm800_driver = { .name = "88PM800", .pm = pm_sleep_ptr(&pm80x_pm_ops), }, - .probe_new = pm800_probe, + .probe = pm800_probe, .remove = pm800_remove, .id_table = pm80x_id_table, }; diff --git a/drivers/mfd/88pm805.c b/drivers/mfd/88pm805.c index 352f13cb14811b80ad1249e555eabf6225140cc8..68417c3c4f5ae4a78ae1d3702c91c49821efee48 100644 --- a/drivers/mfd/88pm805.c +++ b/drivers/mfd/88pm805.c @@ -253,7 +253,7 @@ static struct i2c_driver pm805_driver = { .name = "88PM805", .pm = pm_sleep_ptr(&pm80x_pm_ops), }, - .probe_new = pm805_probe, + .probe = pm805_probe, .remove = pm805_remove, .id_table = pm80x_id_table, }; diff --git a/drivers/mfd/88pm80x.c b/drivers/mfd/88pm80x.c index ac4f08565f29021ebd98f78bd4feae1de97565dc..bbc1a87f0c8f9915e0563a7da8771722215ab015 100644 --- a/drivers/mfd/88pm80x.c +++ b/drivers/mfd/88pm80x.c @@ -74,7 +74,6 @@ int pm80x_init(struct i2c_client *client) chip->irq = client->irq; chip->dev = &client->dev; - dev_set_drvdata(chip->dev, chip); i2c_set_clientdata(chip->client, chip); ret = regmap_read(chip->regmap, PM80X_CHIP_ID, &val); diff --git a/drivers/mfd/88pm860x-core.c b/drivers/mfd/88pm860x-core.c index aabac37c35025688993fc4886a88164a122f7b14..151bf03e772d161d80f62f9981573a1b3c8a49dd 100644 --- a/drivers/mfd/88pm860x-core.c +++ b/drivers/mfd/88pm860x-core.c @@ -1166,7 +1166,6 @@ static int pm860x_probe(struct i2c_client *client) chip->client = client; i2c_set_clientdata(client, chip); chip->dev = &client->dev; - dev_set_drvdata(chip->dev, chip); /* * Both client and companion client shares same platform driver. @@ -1251,7 +1250,7 @@ static struct i2c_driver pm860x_driver = { .pm = pm_sleep_ptr(&pm860x_pm_ops), .of_match_table = pm860x_dt_ids, }, - .probe_new = pm860x_probe, + .probe = pm860x_probe, .remove = pm860x_remove, .id_table = pm860x_id_table, }; diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index e90463c4441ce325e17d8cf11f2b34d88c59149d..6f5b259a6d6a0b9ddc3c4ba555e4695b03b87987 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -266,8 +266,8 @@ config MFD_MADERA_SPI Support for the Cirrus Logic Madera platform audio SoC core functionality controlled via SPI. -config MFD_MAX597X - tristate "Maxim 597x power switch and monitor" +config MFD_MAX5970 + tristate "Maxim 5970/5978 power switch and monitor" depends on (I2C && OF) select MFD_SIMPLE_MFD_I2C help @@ -784,6 +784,19 @@ config MFD_MAX14577 additional drivers must be enabled in order to use the functionality of the device. +config MFD_MAX77541 + tristate "Analog Devices MAX77541/77540 PMIC Support" + depends on I2C=y + select MFD_CORE + select REGMAP_I2C + select REGMAP_IRQ + help + Say yes here to add support for Analog Devices MAX77541 and + MAX77540 Power Management ICs. This driver provides + common support for accessing the device; additional drivers + must be enabled in order to use the functionality of the device. + There are regulators and adc. + config MFD_MAX77620 bool "Maxim Semiconductor MAX77620 and MAX20024 PMIC Support" depends on I2C=y @@ -1183,12 +1196,17 @@ config MFD_RC5T583 Additional drivers must be enabled in order to use the different functionality of the device. -config MFD_RK808 +config MFD_RK8XX + bool + select MFD_CORE + +config MFD_RK8XX_I2C tristate "Rockchip RK805/RK808/RK809/RK817/RK818 Power Management Chip" depends on I2C && OF select MFD_CORE select REGMAP_I2C select REGMAP_IRQ + select MFD_RK8XX help If you say yes here you get support for the RK805, RK808, RK809, RK817 and RK818 Power Management chips. @@ -1196,6 +1214,20 @@ config MFD_RK808 through I2C interface. The device supports multiple sub-devices including interrupts, RTC, LDO & DCDC regulators, and onkey. +config MFD_RK8XX_SPI + tristate "Rockchip RK806 Power Management Chip" + depends on SPI && OF + select MFD_CORE + select REGMAP_SPI + select REGMAP_IRQ + select MFD_RK8XX + help + If you say yes here you get support for the RK806 Power Management + chip. + This driver provides common support for accessing the device + through an SPI interface. The device supports multiple sub-devices + including interrupts, LDO & DCDC regulators, and power on-key. + config MFD_RN5T618 tristate "Ricoh RN5T567/618 PMIC" depends on I2C @@ -1679,6 +1711,38 @@ config MFD_TPS65912_SPI If you say yes here you get support for the TPS65912 series of PM chips with SPI interface. +config MFD_TPS6594 + tristate + select MFD_CORE + select REGMAP + select REGMAP_IRQ + +config MFD_TPS6594_I2C + tristate "TI TPS6594 Power Management chip with I2C" + select MFD_TPS6594 + select REGMAP_I2C + select CRC8 + depends on I2C + help + If you say yes here you get support for the TPS6594 series of + PM chips with I2C interface. + + This driver can also be built as a module. If so, the module + will be called tps6594-i2c. + +config MFD_TPS6594_SPI + tristate "TI TPS6594 Power Management chip with SPI" + select MFD_TPS6594 + select REGMAP_SPI + select CRC8 + depends on SPI_MASTER + help + If you say yes here you get support for the TPS6594 series of + PM chips with SPI interface. + + This driver can also be built as a module. If so, the module + will be called tps6594-spi. + config TWL4030_CORE bool "TI TWL4030/TWL5030/TWL6030/TPS659x0 Support" depends on I2C=y diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 1d2392f06f78a84ad5ed919ee9b0c063a58935ca..f3d1f1dc73b5b6bad09e44f29ff44b8a450b2120 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -96,6 +96,9 @@ obj-$(CONFIG_MFD_TPS65910) += tps65910.o obj-$(CONFIG_MFD_TPS65912) += tps65912-core.o obj-$(CONFIG_MFD_TPS65912_I2C) += tps65912-i2c.o obj-$(CONFIG_MFD_TPS65912_SPI) += tps65912-spi.o +obj-$(CONFIG_MFD_TPS6594) += tps6594-core.o +obj-$(CONFIG_MFD_TPS6594_I2C) += tps6594-i2c.o +obj-$(CONFIG_MFD_TPS6594_SPI) += tps6594-spi.o obj-$(CONFIG_MENELAUS) += menelaus.o obj-$(CONFIG_TWL4030_CORE) += twl-core.o twl4030-irq.o twl6030-irq.o @@ -151,6 +154,7 @@ obj-$(CONFIG_MFD_DA9063) += da9063.o obj-$(CONFIG_MFD_DA9150) += da9150-core.o obj-$(CONFIG_MFD_MAX14577) += max14577.o +obj-$(CONFIG_MFD_MAX77541) += max77541.o obj-$(CONFIG_MFD_MAX77620) += max77620.o obj-$(CONFIG_MFD_MAX77650) += max77650.o obj-$(CONFIG_MFD_MAX77686) += max77686.o @@ -214,7 +218,9 @@ obj-$(CONFIG_MFD_PALMAS) += palmas.o obj-$(CONFIG_MFD_VIPERBOARD) += viperboard.o obj-$(CONFIG_MFD_NTXEC) += ntxec.o obj-$(CONFIG_MFD_RC5T583) += rc5t583.o rc5t583-irq.o -obj-$(CONFIG_MFD_RK808) += rk808.o +obj-$(CONFIG_MFD_RK8XX) += rk8xx-core.o +obj-$(CONFIG_MFD_RK8XX_I2C) += rk8xx-i2c.o +obj-$(CONFIG_MFD_RK8XX_SPI) += rk8xx-spi.o obj-$(CONFIG_MFD_RN5T618) += rn5t618.o obj-$(CONFIG_MFD_SEC_CORE) += sec-core.o sec-irq.o obj-$(CONFIG_MFD_SYSCON) += syscon.o diff --git a/drivers/mfd/aat2870-core.c b/drivers/mfd/aat2870-core.c index f253da5b246becccc2f7c89d061cab2a2f695687..2fee62f1016c800701c09ab49b67ce7cdbb33b63 100644 --- a/drivers/mfd/aat2870-core.c +++ b/drivers/mfd/aat2870-core.c @@ -345,8 +345,6 @@ static int aat2870_i2c_probe(struct i2c_client *client) return -ENOMEM; aat2870->dev = &client->dev; - dev_set_drvdata(aat2870->dev, aat2870); - aat2870->client = client; i2c_set_clientdata(client, aat2870); @@ -451,7 +449,7 @@ static struct i2c_driver aat2870_i2c_driver = { .pm = pm_sleep_ptr(&aat2870_pm_ops), .suppress_bind_attrs = true, }, - .probe_new = aat2870_i2c_probe, + .probe = aat2870_i2c_probe, .id_table = aat2870_i2c_id_table, }; diff --git a/drivers/mfd/acer-ec-a500.c b/drivers/mfd/acer-ec-a500.c index 7fd8b998807586c72f1b76f4119a5c8193f6d61e..feb757e90dc3f3be1ca74bf12b21c5d20801f7c3 100644 --- a/drivers/mfd/acer-ec-a500.c +++ b/drivers/mfd/acer-ec-a500.c @@ -190,7 +190,7 @@ static struct i2c_driver a500_ec_driver = { .name = "acer-a500-embedded-controller", .of_match_table = a500_ec_match, }, - .probe_new = a500_ec_probe, + .probe = a500_ec_probe, .remove = a500_ec_remove, }; module_i2c_driver(a500_ec_driver); diff --git a/drivers/mfd/act8945a.c b/drivers/mfd/act8945a.c index bcf0fda15f0c32b005ee450338c638fc33342aec..2406fcdff5f9cc3546580e695974ade16087f727 100644 --- a/drivers/mfd/act8945a.c +++ b/drivers/mfd/act8945a.c @@ -70,7 +70,7 @@ static struct i2c_driver act8945a_i2c_driver = { .name = "act8945a", .of_match_table = of_match_ptr(act8945a_of_match), }, - .probe_new = act8945a_i2c_probe, + .probe = act8945a_i2c_probe, .id_table = act8945a_i2c_id, }; diff --git a/drivers/mfd/adp5520.c b/drivers/mfd/adp5520.c index cb168efdbafe8bd4c39839bcdd2f81545f243410..bd6f4965ebc8269d40f38e34e0092af5139fae21 100644 --- a/drivers/mfd/adp5520.c +++ b/drivers/mfd/adp5520.c @@ -340,7 +340,7 @@ static struct i2c_driver adp5520_driver = { .pm = pm_sleep_ptr(&adp5520_pm), .suppress_bind_attrs = true, }, - .probe_new = adp5520_probe, + .probe = adp5520_probe, .id_table = adp5520_id, }; builtin_i2c_driver(adp5520_driver); diff --git a/drivers/mfd/arizona-i2c.c b/drivers/mfd/arizona-i2c.c index 43e393c8608df2fe23aa74cbcb4d2c922efe6167..9b7183ffc92809306fb6c38153c2e5af20cccfa1 100644 --- a/drivers/mfd/arizona-i2c.c +++ b/drivers/mfd/arizona-i2c.c @@ -121,7 +121,7 @@ static struct i2c_driver arizona_i2c_driver = { .pm = pm_ptr(&arizona_pm_ops), .of_match_table = of_match_ptr(arizona_i2c_of_match), }, - .probe_new = arizona_i2c_probe, + .probe = arizona_i2c_probe, .remove = arizona_i2c_remove, .id_table = arizona_i2c_id, }; diff --git a/drivers/mfd/as3711.c b/drivers/mfd/as3711.c index 3facfdd28e81fd00c392c041bab3d3bf9b80e0ae..c7e85ff38013273d4e7f415186bf4d165d41f087 100644 --- a/drivers/mfd/as3711.c +++ b/drivers/mfd/as3711.c @@ -201,7 +201,7 @@ static struct i2c_driver as3711_i2c_driver = { .name = "as3711", .of_match_table = of_match_ptr(as3711_of_match), }, - .probe_new = as3711_i2c_probe, + .probe = as3711_i2c_probe, .id_table = as3711_i2c_id, }; diff --git a/drivers/mfd/as3722.c b/drivers/mfd/as3722.c index b6dda0eb86456a104c5bdf9ddf5012421c415c4d..a2bf68afc131d3d09f3c41cce2d8da4a50826812 100644 --- a/drivers/mfd/as3722.c +++ b/drivers/mfd/as3722.c @@ -445,7 +445,7 @@ static struct i2c_driver as3722_i2c_driver = { .of_match_table = as3722_of_match, .pm = &as3722_pm_ops, }, - .probe_new = as3722_i2c_probe, + .probe = as3722_i2c_probe, .id_table = as3722_i2c_id, }; diff --git a/drivers/mfd/atc260x-i2c.c b/drivers/mfd/atc260x-i2c.c index 8e1491167160b51486f1e20d90f1e1404de72a03..fb53b0432a317a8b05022d4535bbfb0444fb7ea8 100644 --- a/drivers/mfd/atc260x-i2c.c +++ b/drivers/mfd/atc260x-i2c.c @@ -53,7 +53,7 @@ static struct i2c_driver atc260x_i2c_driver = { .name = "atc260x", .of_match_table = atc260x_i2c_of_match, }, - .probe_new = atc260x_i2c_probe, + .probe = atc260x_i2c_probe, }; module_i2c_driver(atc260x_i2c_driver); diff --git a/drivers/mfd/axp20x-i2c.c b/drivers/mfd/axp20x-i2c.c index b4f5cb457117eef57ee3ede5a32a5b2f74e2cb60..68d3560cfe4a0ec8076d42723daa53a200713fb4 100644 --- a/drivers/mfd/axp20x-i2c.c +++ b/drivers/mfd/axp20x-i2c.c @@ -59,10 +59,12 @@ static void axp20x_i2c_remove(struct i2c_client *i2c) #ifdef CONFIG_OF static const struct of_device_id axp20x_i2c_of_match[] = { { .compatible = "x-powers,axp152", .data = (void *)AXP152_ID }, + { .compatible = "x-powers,axp192", .data = (void *)AXP192_ID }, { .compatible = "x-powers,axp202", .data = (void *)AXP202_ID }, { .compatible = "x-powers,axp209", .data = (void *)AXP209_ID }, { .compatible = "x-powers,axp221", .data = (void *)AXP221_ID }, { .compatible = "x-powers,axp223", .data = (void *)AXP223_ID }, + { .compatible = "x-powers,axp313a", .data = (void *)AXP313A_ID }, { .compatible = "x-powers,axp803", .data = (void *)AXP803_ID }, { .compatible = "x-powers,axp806", .data = (void *)AXP806_ID }, { .compatible = "x-powers,axp15060", .data = (void *)AXP15060_ID }, @@ -73,10 +75,12 @@ MODULE_DEVICE_TABLE(of, axp20x_i2c_of_match); static const struct i2c_device_id axp20x_i2c_id[] = { { "axp152", 0 }, + { "axp192", 0 }, { "axp202", 0 }, { "axp209", 0 }, { "axp221", 0 }, { "axp223", 0 }, + { "axp313a", 0 }, { "axp803", 0 }, { "axp806", 0 }, { "axp15060", 0 }, @@ -101,7 +105,7 @@ static struct i2c_driver axp20x_i2c_driver = { .of_match_table = of_match_ptr(axp20x_i2c_of_match), .acpi_match_table = ACPI_PTR(axp20x_i2c_acpi_match), }, - .probe_new = axp20x_i2c_probe, + .probe = axp20x_i2c_probe, .remove = axp20x_i2c_remove, .id_table = axp20x_i2c_id, }; diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c index 72b87aae60cc02d06594f6e28faa686dc3ac0fef..c03bc5cda080a9c1d79ab7211d39ed7afd3dd60c 100644 --- a/drivers/mfd/axp20x.c +++ b/drivers/mfd/axp20x.c @@ -34,11 +34,13 @@ static const char * const axp20x_model_names[] = { "AXP152", + "AXP192", "AXP202", "AXP209", "AXP221", "AXP223", "AXP288", + "AXP313a", "AXP803", "AXP806", "AXP809", @@ -93,6 +95,35 @@ static const struct regmap_access_table axp20x_volatile_table = { .n_yes_ranges = ARRAY_SIZE(axp20x_volatile_ranges), }; +static const struct regmap_range axp192_writeable_ranges[] = { + regmap_reg_range(AXP192_DATACACHE(0), AXP192_DATACACHE(5)), + regmap_reg_range(AXP192_PWR_OUT_CTRL, AXP192_IRQ5_STATE), + regmap_reg_range(AXP20X_DCDC_MODE, AXP192_N_RSTO_CTRL), + regmap_reg_range(AXP20X_CC_CTRL, AXP20X_CC_CTRL), +}; + +static const struct regmap_range axp192_volatile_ranges[] = { + regmap_reg_range(AXP20X_PWR_INPUT_STATUS, AXP192_USB_OTG_STATUS), + regmap_reg_range(AXP192_IRQ1_STATE, AXP192_IRQ4_STATE), + regmap_reg_range(AXP192_IRQ5_STATE, AXP192_IRQ5_STATE), + regmap_reg_range(AXP20X_ACIN_V_ADC_H, AXP20X_IPSOUT_V_HIGH_L), + regmap_reg_range(AXP20X_TIMER_CTRL, AXP20X_TIMER_CTRL), + regmap_reg_range(AXP192_GPIO2_0_STATE, AXP192_GPIO2_0_STATE), + regmap_reg_range(AXP192_GPIO4_3_STATE, AXP192_GPIO4_3_STATE), + regmap_reg_range(AXP192_N_RSTO_CTRL, AXP192_N_RSTO_CTRL), + regmap_reg_range(AXP20X_CHRG_CC_31_24, AXP20X_CC_CTRL), +}; + +static const struct regmap_access_table axp192_writeable_table = { + .yes_ranges = axp192_writeable_ranges, + .n_yes_ranges = ARRAY_SIZE(axp192_writeable_ranges), +}; + +static const struct regmap_access_table axp192_volatile_table = { + .yes_ranges = axp192_volatile_ranges, + .n_yes_ranges = ARRAY_SIZE(axp192_volatile_ranges), +}; + /* AXP22x ranges are shared with the AXP809, as they cover the same range */ static const struct regmap_range axp22x_writeable_ranges[] = { regmap_reg_range(AXP20X_DATACACHE(0), AXP20X_IRQ5_STATE), @@ -156,6 +187,25 @@ static const struct regmap_range axp806_writeable_ranges[] = { regmap_reg_range(AXP806_REG_ADDR_EXT, AXP806_REG_ADDR_EXT), }; +static const struct regmap_range axp313a_writeable_ranges[] = { + regmap_reg_range(AXP313A_ON_INDICATE, AXP313A_IRQ_STATE), +}; + +static const struct regmap_range axp313a_volatile_ranges[] = { + regmap_reg_range(AXP313A_SHUTDOWN_CTRL, AXP313A_SHUTDOWN_CTRL), + regmap_reg_range(AXP313A_IRQ_STATE, AXP313A_IRQ_STATE), +}; + +static const struct regmap_access_table axp313a_writeable_table = { + .yes_ranges = axp313a_writeable_ranges, + .n_yes_ranges = ARRAY_SIZE(axp313a_writeable_ranges), +}; + +static const struct regmap_access_table axp313a_volatile_table = { + .yes_ranges = axp313a_volatile_ranges, + .n_yes_ranges = ARRAY_SIZE(axp313a_volatile_ranges), +}; + static const struct regmap_range axp806_volatile_ranges[] = { regmap_reg_range(AXP20X_IRQ1_STATE, AXP20X_IRQ2_STATE), }; @@ -200,6 +250,19 @@ static const struct resource axp152_pek_resources[] = { DEFINE_RES_IRQ_NAMED(AXP152_IRQ_PEK_FAL_EDGE, "PEK_DBF"), }; +static const struct resource axp192_ac_power_supply_resources[] = { + DEFINE_RES_IRQ_NAMED(AXP192_IRQ_ACIN_PLUGIN, "ACIN_PLUGIN"), + DEFINE_RES_IRQ_NAMED(AXP192_IRQ_ACIN_REMOVAL, "ACIN_REMOVAL"), + DEFINE_RES_IRQ_NAMED(AXP192_IRQ_ACIN_OVER_V, "ACIN_OVER_V"), +}; + +static const struct resource axp192_usb_power_supply_resources[] = { + DEFINE_RES_IRQ_NAMED(AXP192_IRQ_VBUS_PLUGIN, "VBUS_PLUGIN"), + DEFINE_RES_IRQ_NAMED(AXP192_IRQ_VBUS_REMOVAL, "VBUS_REMOVAL"), + DEFINE_RES_IRQ_NAMED(AXP192_IRQ_VBUS_VALID, "VBUS_VALID"), + DEFINE_RES_IRQ_NAMED(AXP192_IRQ_VBUS_NOT_VALID, "VBUS_NOT_VALID"), +}; + static const struct resource axp20x_ac_power_supply_resources[] = { DEFINE_RES_IRQ_NAMED(AXP20X_IRQ_ACIN_PLUGIN, "ACIN_PLUGIN"), DEFINE_RES_IRQ_NAMED(AXP20X_IRQ_ACIN_REMOVAL, "ACIN_REMOVAL"), @@ -248,6 +311,11 @@ static const struct resource axp288_fuel_gauge_resources[] = { DEFINE_RES_IRQ(AXP288_IRQ_WL1), }; +static const struct resource axp313a_pek_resources[] = { + DEFINE_RES_IRQ_NAMED(AXP313A_IRQ_PEK_RIS_EDGE, "PEK_DBR"), + DEFINE_RES_IRQ_NAMED(AXP313A_IRQ_PEK_FAL_EDGE, "PEK_DBF"), +}; + static const struct resource axp803_pek_resources[] = { DEFINE_RES_IRQ_NAMED(AXP803_IRQ_PEK_RIS_EDGE, "PEK_DBR"), DEFINE_RES_IRQ_NAMED(AXP803_IRQ_PEK_FAL_EDGE, "PEK_DBF"), @@ -277,6 +345,15 @@ static const struct regmap_config axp152_regmap_config = { .cache_type = REGCACHE_RBTREE, }; +static const struct regmap_config axp192_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .wr_table = &axp192_writeable_table, + .volatile_table = &axp192_volatile_table, + .max_register = AXP20X_CC_CTRL, + .cache_type = REGCACHE_RBTREE, +}; + static const struct regmap_config axp20x_regmap_config = { .reg_bits = 8, .val_bits = 8, @@ -304,6 +381,15 @@ static const struct regmap_config axp288_regmap_config = { .cache_type = REGCACHE_RBTREE, }; +static const struct regmap_config axp313a_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .wr_table = &axp313a_writeable_table, + .volatile_table = &axp313a_volatile_table, + .max_register = AXP313A_IRQ_STATE, + .cache_type = REGCACHE_RBTREE, +}; + static const struct regmap_config axp806_regmap_config = { .reg_bits = 8, .val_bits = 8, @@ -345,6 +431,42 @@ static const struct regmap_irq axp152_regmap_irqs[] = { INIT_REGMAP_IRQ(AXP152, GPIO0_INPUT, 2, 0), }; +static const struct regmap_irq axp192_regmap_irqs[] = { + INIT_REGMAP_IRQ(AXP192, ACIN_OVER_V, 0, 7), + INIT_REGMAP_IRQ(AXP192, ACIN_PLUGIN, 0, 6), + INIT_REGMAP_IRQ(AXP192, ACIN_REMOVAL, 0, 5), + INIT_REGMAP_IRQ(AXP192, VBUS_OVER_V, 0, 4), + INIT_REGMAP_IRQ(AXP192, VBUS_PLUGIN, 0, 3), + INIT_REGMAP_IRQ(AXP192, VBUS_REMOVAL, 0, 2), + INIT_REGMAP_IRQ(AXP192, VBUS_V_LOW, 0, 1), + INIT_REGMAP_IRQ(AXP192, BATT_PLUGIN, 1, 7), + INIT_REGMAP_IRQ(AXP192, BATT_REMOVAL, 1, 6), + INIT_REGMAP_IRQ(AXP192, BATT_ENT_ACT_MODE, 1, 5), + INIT_REGMAP_IRQ(AXP192, BATT_EXIT_ACT_MODE, 1, 4), + INIT_REGMAP_IRQ(AXP192, CHARG, 1, 3), + INIT_REGMAP_IRQ(AXP192, CHARG_DONE, 1, 2), + INIT_REGMAP_IRQ(AXP192, BATT_TEMP_HIGH, 1, 1), + INIT_REGMAP_IRQ(AXP192, BATT_TEMP_LOW, 1, 0), + INIT_REGMAP_IRQ(AXP192, DIE_TEMP_HIGH, 2, 7), + INIT_REGMAP_IRQ(AXP192, CHARG_I_LOW, 2, 6), + INIT_REGMAP_IRQ(AXP192, DCDC1_V_LONG, 2, 5), + INIT_REGMAP_IRQ(AXP192, DCDC2_V_LONG, 2, 4), + INIT_REGMAP_IRQ(AXP192, DCDC3_V_LONG, 2, 3), + INIT_REGMAP_IRQ(AXP192, PEK_SHORT, 2, 1), + INIT_REGMAP_IRQ(AXP192, PEK_LONG, 2, 0), + INIT_REGMAP_IRQ(AXP192, N_OE_PWR_ON, 3, 7), + INIT_REGMAP_IRQ(AXP192, N_OE_PWR_OFF, 3, 6), + INIT_REGMAP_IRQ(AXP192, VBUS_VALID, 3, 5), + INIT_REGMAP_IRQ(AXP192, VBUS_NOT_VALID, 3, 4), + INIT_REGMAP_IRQ(AXP192, VBUS_SESS_VALID, 3, 3), + INIT_REGMAP_IRQ(AXP192, VBUS_SESS_END, 3, 2), + INIT_REGMAP_IRQ(AXP192, LOW_PWR_LVL, 3, 0), + INIT_REGMAP_IRQ(AXP192, TIMER, 4, 7), + INIT_REGMAP_IRQ(AXP192, GPIO2_INPUT, 4, 2), + INIT_REGMAP_IRQ(AXP192, GPIO1_INPUT, 4, 1), + INIT_REGMAP_IRQ(AXP192, GPIO0_INPUT, 4, 0), +}; + static const struct regmap_irq axp20x_regmap_irqs[] = { INIT_REGMAP_IRQ(AXP20X, ACIN_OVER_V, 0, 7), INIT_REGMAP_IRQ(AXP20X, ACIN_PLUGIN, 0, 6), @@ -456,6 +578,16 @@ static const struct regmap_irq axp288_regmap_irqs[] = { INIT_REGMAP_IRQ(AXP288, BC_USB_CHNG, 5, 1), }; +static const struct regmap_irq axp313a_regmap_irqs[] = { + INIT_REGMAP_IRQ(AXP313A, PEK_RIS_EDGE, 0, 7), + INIT_REGMAP_IRQ(AXP313A, PEK_FAL_EDGE, 0, 6), + INIT_REGMAP_IRQ(AXP313A, PEK_SHORT, 0, 5), + INIT_REGMAP_IRQ(AXP313A, PEK_LONG, 0, 4), + INIT_REGMAP_IRQ(AXP313A, DCDC3_V_LOW, 0, 3), + INIT_REGMAP_IRQ(AXP313A, DCDC2_V_LOW, 0, 2), + INIT_REGMAP_IRQ(AXP313A, DIE_TEMP_HIGH, 0, 0), +}; + static const struct regmap_irq axp803_regmap_irqs[] = { INIT_REGMAP_IRQ(AXP803, ACIN_OVER_V, 0, 7), INIT_REGMAP_IRQ(AXP803, ACIN_PLUGIN, 0, 6), @@ -571,6 +703,32 @@ static const struct regmap_irq_chip axp152_regmap_irq_chip = { .num_regs = 3, }; +static unsigned int axp192_get_irq_reg(struct regmap_irq_chip_data *data, + unsigned int base, int index) +{ + /* linear mapping for IRQ1 to IRQ4 */ + if (index < 4) + return base + index; + + /* handle IRQ5 separately */ + if (base == AXP192_IRQ1_EN) + return AXP192_IRQ5_EN; + + return AXP192_IRQ5_STATE; +} + +static const struct regmap_irq_chip axp192_regmap_irq_chip = { + .name = "axp192_irq_chip", + .status_base = AXP192_IRQ1_STATE, + .ack_base = AXP192_IRQ1_STATE, + .unmask_base = AXP192_IRQ1_EN, + .init_ack_masked = true, + .irqs = axp192_regmap_irqs, + .num_irqs = ARRAY_SIZE(axp192_regmap_irqs), + .num_regs = 5, + .get_irq_reg = axp192_get_irq_reg, +}; + static const struct regmap_irq_chip axp20x_regmap_irq_chip = { .name = "axp20x_irq_chip", .status_base = AXP20X_IRQ1_STATE, @@ -606,6 +764,17 @@ static const struct regmap_irq_chip axp288_regmap_irq_chip = { }; +static const struct regmap_irq_chip axp313a_regmap_irq_chip = { + .name = "axp313a_irq_chip", + .status_base = AXP313A_IRQ_STATE, + .ack_base = AXP313A_IRQ_STATE, + .unmask_base = AXP313A_IRQ_EN, + .init_ack_masked = true, + .irqs = axp313a_regmap_irqs, + .num_irqs = ARRAY_SIZE(axp313a_regmap_irqs), + .num_regs = 1, +}; + static const struct regmap_irq_chip axp803_regmap_irq_chip = { .name = "axp803", .status_base = AXP20X_IRQ1_STATE, @@ -650,6 +819,27 @@ static const struct regmap_irq_chip axp15060_regmap_irq_chip = { .num_regs = 2, }; +static const struct mfd_cell axp192_cells[] = { + { + .name = "axp192-adc", + .of_compatible = "x-powers,axp192-adc", + }, { + .name = "axp20x-battery-power-supply", + .of_compatible = "x-powers,axp192-battery-power-supply", + }, { + .name = "axp20x-ac-power-supply", + .of_compatible = "x-powers,axp202-ac-power-supply", + .num_resources = ARRAY_SIZE(axp192_ac_power_supply_resources), + .resources = axp192_ac_power_supply_resources, + }, { + .name = "axp20x-usb-power-supply", + .of_compatible = "x-powers,axp192-usb-power-supply", + .num_resources = ARRAY_SIZE(axp192_usb_power_supply_resources), + .resources = axp192_usb_power_supply_resources, + }, + { .name = "axp20x-regulator" }, +}; + static const struct mfd_cell axp20x_cells[] = { { .name = "axp20x-gpio", @@ -745,6 +935,11 @@ static const struct mfd_cell axp152_cells[] = { }, }; +static struct mfd_cell axp313a_cells[] = { + MFD_CELL_NAME("axp20x-regulator"), + MFD_CELL_RES("axp313a-pek", axp313a_pek_resources), +}; + static const struct resource axp288_adc_resources[] = { DEFINE_RES_IRQ_NAMED(AXP288_IRQ_GPADC, "GPADC"), }; @@ -914,8 +1109,18 @@ static const struct mfd_cell axp_regulator_only_cells[] = { static int axp20x_power_off(struct sys_off_data *data) { struct axp20x_dev *axp20x = data->cb_data; + unsigned int shutdown_reg; - regmap_write(axp20x->regmap, AXP20X_OFF_CTRL, AXP20X_OFF); + switch (axp20x->variant) { + case AXP313A_ID: + shutdown_reg = AXP313A_SHUTDOWN_CTRL; + break; + default: + shutdown_reg = AXP20X_OFF_CTRL; + break; + } + + regmap_write(axp20x->regmap, shutdown_reg, AXP20X_OFF); /* Give capacitors etc. time to drain to avoid kernel panic msg. */ mdelay(500); @@ -952,6 +1157,12 @@ int axp20x_match_device(struct axp20x_dev *axp20x) axp20x->regmap_cfg = &axp152_regmap_config; axp20x->regmap_irq_chip = &axp152_regmap_irq_chip; break; + case AXP192_ID: + axp20x->nr_cells = ARRAY_SIZE(axp192_cells); + axp20x->cells = axp192_cells; + axp20x->regmap_cfg = &axp192_regmap_config; + axp20x->regmap_irq_chip = &axp192_regmap_irq_chip; + break; case AXP202_ID: case AXP209_ID: axp20x->nr_cells = ARRAY_SIZE(axp20x_cells); @@ -978,6 +1189,12 @@ int axp20x_match_device(struct axp20x_dev *axp20x) axp20x->regmap_irq_chip = &axp288_regmap_irq_chip; axp20x->irq_flags = IRQF_TRIGGER_LOW; break; + case AXP313A_ID: + axp20x->nr_cells = ARRAY_SIZE(axp313a_cells); + axp20x->cells = axp313a_cells; + axp20x->regmap_cfg = &axp313a_regmap_config; + axp20x->regmap_irq_chip = &axp313a_regmap_irq_chip; + break; case AXP803_ID: axp20x->nr_cells = ARRAY_SIZE(axp803_cells); axp20x->cells = axp803_cells; diff --git a/drivers/mfd/bcm590xx.c b/drivers/mfd/bcm590xx.c index 251d515478d55fbb9854dc544443cf45024afda4..9f39b46b87f4457b1b00445e7baeb58cb32f6de4 100644 --- a/drivers/mfd/bcm590xx.c +++ b/drivers/mfd/bcm590xx.c @@ -108,7 +108,7 @@ static struct i2c_driver bcm590xx_i2c_driver = { .name = "bcm590xx", .of_match_table = bcm590xx_of_match, }, - .probe_new = bcm590xx_i2c_probe, + .probe = bcm590xx_i2c_probe, .id_table = bcm590xx_i2c_id, }; module_i2c_driver(bcm590xx_i2c_driver); diff --git a/drivers/mfd/bd9571mwv.c b/drivers/mfd/bd9571mwv.c index 60dc858c8117a8075955aaced93db782a6456390..819d09e4d10077f9367cf7d6ebc2a7944bb25675 100644 --- a/drivers/mfd/bd9571mwv.c +++ b/drivers/mfd/bd9571mwv.c @@ -278,7 +278,7 @@ static struct i2c_driver bd9571mwv_driver = { .name = "bd9571mwv", .of_match_table = bd9571mwv_of_match_table, }, - .probe_new = bd9571mwv_probe, + .probe = bd9571mwv_probe, .id_table = bd9571mwv_id_table, }; module_i2c_driver(bd9571mwv_driver); diff --git a/drivers/mfd/da903x.c b/drivers/mfd/da903x.c index 6570b33a5a77bd60c51af9e5a3708353909824dc..e86b39de3303a2cdda6a83e47608aa6d822713a7 100644 --- a/drivers/mfd/da903x.c +++ b/drivers/mfd/da903x.c @@ -543,7 +543,7 @@ static struct i2c_driver da903x_driver = { .driver = { .name = "da903x", }, - .probe_new = da903x_probe, + .probe = da903x_probe, .remove = da903x_remove, .id_table = da903x_id_table, }; diff --git a/drivers/mfd/da9052-i2c.c b/drivers/mfd/da9052-i2c.c index 03db7a2ccf7a0353a399ade10960390563a9be33..541e2d47677eb9c2dc8b574a9836b4f35a63070b 100644 --- a/drivers/mfd/da9052-i2c.c +++ b/drivers/mfd/da9052-i2c.c @@ -176,7 +176,7 @@ static void da9052_i2c_remove(struct i2c_client *client) } static struct i2c_driver da9052_i2c_driver = { - .probe_new = da9052_i2c_probe, + .probe = da9052_i2c_probe, .remove = da9052_i2c_remove, .id_table = da9052_i2c_id, .driver = { diff --git a/drivers/mfd/da9055-i2c.c b/drivers/mfd/da9055-i2c.c index 537fd5de3e6d46b71bf49186084607e29c677626..bbaf4f07f2743851c0430e67baca5ae3d18d86a4 100644 --- a/drivers/mfd/da9055-i2c.c +++ b/drivers/mfd/da9055-i2c.c @@ -66,7 +66,7 @@ static const struct of_device_id da9055_of_match[] = { }; static struct i2c_driver da9055_i2c_driver = { - .probe_new = da9055_i2c_probe, + .probe = da9055_i2c_probe, .remove = da9055_i2c_remove, .id_table = da9055_i2c_id, .driver = { diff --git a/drivers/mfd/da9062-core.c b/drivers/mfd/da9062-core.c index d073d5f106ecc415aeddecf52fd6763928b93ef2..48f58b6f5629384d28c722f2e0defaa0815d8731 100644 --- a/drivers/mfd/da9062-core.c +++ b/drivers/mfd/da9062-core.c @@ -726,7 +726,7 @@ static struct i2c_driver da9062_i2c_driver = { .name = "da9062", .of_match_table = da9062_dt_ids, }, - .probe_new = da9062_i2c_probe, + .probe = da9062_i2c_probe, .remove = da9062_i2c_remove, .id_table = da9062_i2c_id, }; diff --git a/drivers/mfd/da9063-i2c.c b/drivers/mfd/da9063-i2c.c index 03f8f95a1d62c20450211f648a5b570ecee2c310..d715cf9a9e688333de5c67ab1c9e9ff637c8dbe6 100644 --- a/drivers/mfd/da9063-i2c.c +++ b/drivers/mfd/da9063-i2c.c @@ -469,7 +469,7 @@ static struct i2c_driver da9063_i2c_driver = { .name = "da9063", .of_match_table = da9063_dt_ids, }, - .probe_new = da9063_i2c_probe, + .probe = da9063_i2c_probe, .id_table = da9063_i2c_id, }; diff --git a/drivers/mfd/da9150-core.c b/drivers/mfd/da9150-core.c index d2c954103b2f5432eb984df6c7dd0b1ed7f1b40c..94d621e20635ddcb7720e24a581941f6a4388b9e 100644 --- a/drivers/mfd/da9150-core.c +++ b/drivers/mfd/da9150-core.c @@ -510,7 +510,7 @@ static struct i2c_driver da9150_driver = { .name = "da9150", .of_match_table = da9150_of_match, }, - .probe_new = da9150_probe, + .probe = da9150_probe, .remove = da9150_remove, .shutdown = da9150_shutdown, .id_table = da9150_i2c_id, diff --git a/drivers/mfd/dln2.c b/drivers/mfd/dln2.c index c3149729cec2e3a3fc153d5e6c08ac05cb653062..c7510434380a4376efb5b71b036b4bf8ae9d835e 100644 --- a/drivers/mfd/dln2.c +++ b/drivers/mfd/dln2.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/mfd/ene-kb3930.c b/drivers/mfd/ene-kb3930.c index 3eff98e26bea9a33c6c2299291f91e4f84b73fb7..fa0ad2f14a396189a2df066072096ff90456ae7c 100644 --- a/drivers/mfd/ene-kb3930.c +++ b/drivers/mfd/ene-kb3930.c @@ -196,7 +196,7 @@ static const struct of_device_id kb3930_dt_ids[] = { MODULE_DEVICE_TABLE(of, kb3930_dt_ids); static struct i2c_driver kb3930_driver = { - .probe_new = kb3930_probe, + .probe = kb3930_probe, .remove = kb3930_remove, .driver = { .name = "ene-kb3930", diff --git a/drivers/mfd/gateworks-gsc.c b/drivers/mfd/gateworks-gsc.c index c954ed265de81c925a1e58ec790dc851256cfe84..b02bfdc871e9ec3e92f07a3ac5185f2fdf325c0f 100644 --- a/drivers/mfd/gateworks-gsc.c +++ b/drivers/mfd/gateworks-gsc.c @@ -264,7 +264,7 @@ static struct i2c_driver gsc_driver = { .name = "gateworks-gsc", .of_match_table = gsc_of_match, }, - .probe_new = gsc_probe, + .probe = gsc_probe, .remove = gsc_remove, }; module_i2c_driver(gsc_driver); diff --git a/drivers/mfd/intel-lpss-acpi.c b/drivers/mfd/intel-lpss-acpi.c index a143c8dca2d93b4cb7cb88d0651abb8270e054e8..212818aef93e20859227209b8143af55b1dec412 100644 --- a/drivers/mfd/intel-lpss-acpi.c +++ b/drivers/mfd/intel-lpss-acpi.c @@ -183,6 +183,9 @@ static int intel_lpss_acpi_probe(struct platform_device *pdev) return -ENOMEM; info->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!info->mem) + return -ENODEV; + info->irq = platform_get_irq(pdev, 0); ret = intel_lpss_probe(&pdev->dev, info); diff --git a/drivers/mfd/intel-lpss.c b/drivers/mfd/intel-lpss.c index cfbee2cfba6b0103e1da409e931ea155763fdb59..9591b354072ad140dca799a622ac94f9e49a3c17 100644 --- a/drivers/mfd/intel-lpss.c +++ b/drivers/mfd/intel-lpss.c @@ -460,6 +460,7 @@ void intel_lpss_remove(struct device *dev) } EXPORT_SYMBOL_GPL(intel_lpss_remove); +#ifdef CONFIG_PM static int resume_lpss_device(struct device *dev, void *data) { if (!dev_pm_test_driver_flags(dev, DPM_FLAG_SMART_SUSPEND)) @@ -514,6 +515,7 @@ int intel_lpss_resume(struct device *dev) return 0; } EXPORT_SYMBOL_GPL(intel_lpss_resume); +#endif static int __init intel_lpss_init(void) { diff --git a/drivers/mfd/intel-m10-bmc-core.c b/drivers/mfd/intel-m10-bmc-core.c index dac9cf7bcb4a3493bd63a202eeacb50cc8958fa2..8ad5b382158419883ee3c82d61b7b1fa311e140c 100644 --- a/drivers/mfd/intel-m10-bmc-core.c +++ b/drivers/mfd/intel-m10-bmc-core.c @@ -12,6 +12,91 @@ #include #include +void m10bmc_fw_state_set(struct intel_m10bmc *m10bmc, enum m10bmc_fw_state new_state) +{ + /* bmcfw_state is only needed if handshake_sys_reg_nranges > 0 */ + if (!m10bmc->info->handshake_sys_reg_nranges) + return; + + down_write(&m10bmc->bmcfw_lock); + m10bmc->bmcfw_state = new_state; + up_write(&m10bmc->bmcfw_lock); +} +EXPORT_SYMBOL_NS_GPL(m10bmc_fw_state_set, INTEL_M10_BMC_CORE); + +/* + * For some Intel FPGA devices, the BMC firmware is not available to service + * handshake registers during a secure update. + */ +static bool m10bmc_reg_always_available(struct intel_m10bmc *m10bmc, unsigned int offset) +{ + if (!m10bmc->info->handshake_sys_reg_nranges) + return true; + + return !regmap_reg_in_ranges(offset, m10bmc->info->handshake_sys_reg_ranges, + m10bmc->info->handshake_sys_reg_nranges); +} + +/* + * m10bmc_handshake_reg_unavailable - Checks if reg access collides with secure update state + * @m10bmc: M10 BMC structure + * + * For some Intel FPGA devices, the BMC firmware is not available to service + * handshake registers during a secure update erase and write phases. + * + * Context: @m10bmc->bmcfw_lock must be held. + */ +static bool m10bmc_handshake_reg_unavailable(struct intel_m10bmc *m10bmc) +{ + return m10bmc->bmcfw_state == M10BMC_FW_STATE_SEC_UPDATE_PREPARE || + m10bmc->bmcfw_state == M10BMC_FW_STATE_SEC_UPDATE_WRITE; +} + +/* + * This function helps to simplify the accessing of the system registers. + * + * The base of the system registers is configured through the struct + * csr_map. + */ +int m10bmc_sys_read(struct intel_m10bmc *m10bmc, unsigned int offset, unsigned int *val) +{ + const struct m10bmc_csr_map *csr_map = m10bmc->info->csr_map; + int ret; + + if (m10bmc_reg_always_available(m10bmc, offset)) + return m10bmc_raw_read(m10bmc, csr_map->base + offset, val); + + down_read(&m10bmc->bmcfw_lock); + if (m10bmc_handshake_reg_unavailable(m10bmc)) + ret = -EBUSY; /* Reg not available during secure update */ + else + ret = m10bmc_raw_read(m10bmc, csr_map->base + offset, val); + up_read(&m10bmc->bmcfw_lock); + + return ret; +} +EXPORT_SYMBOL_NS_GPL(m10bmc_sys_read, INTEL_M10_BMC_CORE); + +int m10bmc_sys_update_bits(struct intel_m10bmc *m10bmc, unsigned int offset, + unsigned int msk, unsigned int val) +{ + const struct m10bmc_csr_map *csr_map = m10bmc->info->csr_map; + int ret; + + if (m10bmc_reg_always_available(m10bmc, offset)) + return regmap_update_bits(m10bmc->regmap, csr_map->base + offset, msk, val); + + down_read(&m10bmc->bmcfw_lock); + if (m10bmc_handshake_reg_unavailable(m10bmc)) + ret = -EBUSY; /* Reg not available during secure update */ + else + ret = regmap_update_bits(m10bmc->regmap, csr_map->base + offset, msk, val); + up_read(&m10bmc->bmcfw_lock); + + return ret; +} +EXPORT_SYMBOL_NS_GPL(m10bmc_sys_update_bits, INTEL_M10_BMC_CORE); + static ssize_t bmc_version_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -98,7 +183,7 @@ const struct attribute_group *m10bmc_dev_groups[] = { &m10bmc_group, NULL, }; -EXPORT_SYMBOL_GPL(m10bmc_dev_groups); +EXPORT_SYMBOL_NS_GPL(m10bmc_dev_groups, INTEL_M10_BMC_CORE); int m10bmc_dev_init(struct intel_m10bmc *m10bmc, const struct intel_m10bmc_platform_info *info) { @@ -106,6 +191,7 @@ int m10bmc_dev_init(struct intel_m10bmc *m10bmc, const struct intel_m10bmc_platf m10bmc->info = info; dev_set_drvdata(m10bmc->dev, m10bmc); + init_rwsem(&m10bmc->bmcfw_lock); ret = devm_mfd_add_devices(m10bmc->dev, PLATFORM_DEVID_AUTO, info->cells, info->n_cells, @@ -115,7 +201,7 @@ int m10bmc_dev_init(struct intel_m10bmc *m10bmc, const struct intel_m10bmc_platf return ret; } -EXPORT_SYMBOL_GPL(m10bmc_dev_init); +EXPORT_SYMBOL_NS_GPL(m10bmc_dev_init, INTEL_M10_BMC_CORE); MODULE_DESCRIPTION("Intel MAX 10 BMC core driver"); MODULE_AUTHOR("Intel Corporation"); diff --git a/drivers/mfd/intel-m10-bmc-pmci.c b/drivers/mfd/intel-m10-bmc-pmci.c index 8821f1876dd6f6d8d620b9886367760fe48196f6..0392ef8b57d860bd2913844cd0edc4c0df46725e 100644 --- a/drivers/mfd/intel-m10-bmc-pmci.c +++ b/drivers/mfd/intel-m10-bmc-pmci.c @@ -453,3 +453,4 @@ module_dfl_driver(m10bmc_pmci_driver); MODULE_DESCRIPTION("MAX10 BMC PMCI-based interface"); MODULE_AUTHOR("Intel Corporation"); MODULE_LICENSE("GPL"); +MODULE_IMPORT_NS(INTEL_M10_BMC_CORE); diff --git a/drivers/mfd/intel-m10-bmc-spi.c b/drivers/mfd/intel-m10-bmc-spi.c index 957200e17fed19c04b40f6223a20d51dc208a0bb..cbeb7de9e04160935a83796c95f5d27ed2d4e337 100644 --- a/drivers/mfd/intel-m10-bmc-spi.c +++ b/drivers/mfd/intel-m10-bmc-spi.c @@ -116,12 +116,20 @@ static struct mfd_cell m10bmc_d5005_subdevs[] = { { .name = "d5005bmc-sec-update" }, }; +static const struct regmap_range m10bmc_d5005_fw_handshake_regs[] = { + regmap_reg_range(M10BMC_N3000_TELEM_START, M10BMC_D5005_TELEM_END), +}; + static struct mfd_cell m10bmc_pacn3000_subdevs[] = { { .name = "n3000bmc-hwmon" }, { .name = "n3000bmc-retimer" }, { .name = "n3000bmc-sec-update" }, }; +static const struct regmap_range m10bmc_n3000_fw_handshake_regs[] = { + regmap_reg_range(M10BMC_N3000_TELEM_START, M10BMC_N3000_TELEM_END), +}; + static struct mfd_cell m10bmc_n5010_subdevs[] = { { .name = "n5010bmc-hwmon" }, }; @@ -129,18 +137,24 @@ static struct mfd_cell m10bmc_n5010_subdevs[] = { static const struct intel_m10bmc_platform_info m10bmc_spi_n3000 = { .cells = m10bmc_pacn3000_subdevs, .n_cells = ARRAY_SIZE(m10bmc_pacn3000_subdevs), + .handshake_sys_reg_ranges = m10bmc_n3000_fw_handshake_regs, + .handshake_sys_reg_nranges = ARRAY_SIZE(m10bmc_n3000_fw_handshake_regs), .csr_map = &m10bmc_n3000_csr_map, }; static const struct intel_m10bmc_platform_info m10bmc_spi_d5005 = { .cells = m10bmc_d5005_subdevs, .n_cells = ARRAY_SIZE(m10bmc_d5005_subdevs), + .handshake_sys_reg_ranges = m10bmc_d5005_fw_handshake_regs, + .handshake_sys_reg_nranges = ARRAY_SIZE(m10bmc_d5005_fw_handshake_regs), .csr_map = &m10bmc_n3000_csr_map, }; static const struct intel_m10bmc_platform_info m10bmc_spi_n5010 = { .cells = m10bmc_n5010_subdevs, .n_cells = ARRAY_SIZE(m10bmc_n5010_subdevs), + .handshake_sys_reg_ranges = m10bmc_n3000_fw_handshake_regs, + .handshake_sys_reg_nranges = ARRAY_SIZE(m10bmc_n3000_fw_handshake_regs), .csr_map = &m10bmc_n3000_csr_map, }; @@ -166,3 +180,4 @@ MODULE_DESCRIPTION("Intel MAX 10 BMC SPI bus interface"); MODULE_AUTHOR("Intel Corporation"); MODULE_LICENSE("GPL v2"); MODULE_ALIAS("spi:intel-m10-bmc"); +MODULE_IMPORT_NS(INTEL_M10_BMC_CORE); diff --git a/drivers/mfd/intel_soc_pmic_chtdc_ti.c b/drivers/mfd/intel_soc_pmic_chtdc_ti.c index 282b8fd08009bebac591edca0ed7b8fab6bf00d5..992855bfda3e47b68576e85071016efc471cad3d 100644 --- a/drivers/mfd/intel_soc_pmic_chtdc_ti.c +++ b/drivers/mfd/intel_soc_pmic_chtdc_ti.c @@ -172,7 +172,7 @@ static struct i2c_driver chtdc_ti_i2c_driver = { .pm = pm_sleep_ptr(&chtdc_ti_pm_ops), .acpi_match_table = chtdc_ti_acpi_ids, }, - .probe_new = chtdc_ti_probe, + .probe = chtdc_ti_probe, .shutdown = chtdc_ti_shutdown, }; module_i2c_driver(chtdc_ti_i2c_driver); diff --git a/drivers/mfd/intel_soc_pmic_chtwc.c b/drivers/mfd/intel_soc_pmic_chtwc.c index 871776d511e31c232e398fcc3f263bc3396b8d65..7fce3ef7ab453df45046034e42a4afd603b392b4 100644 --- a/drivers/mfd/intel_soc_pmic_chtwc.c +++ b/drivers/mfd/intel_soc_pmic_chtwc.c @@ -272,7 +272,7 @@ static struct i2c_driver cht_wc_driver = { .pm = pm_sleep_ptr(&cht_wc_pm_ops), .acpi_match_table = cht_wc_acpi_ids, }, - .probe_new = cht_wc_probe, + .probe = cht_wc_probe, .shutdown = cht_wc_shutdown, .id_table = cht_wc_i2c_id, }; diff --git a/drivers/mfd/intel_soc_pmic_crc.c b/drivers/mfd/intel_soc_pmic_crc.c index b745ace46e5b6792bbda404f049f3e0fdd9783b9..581f81cbaa24bd08738bbf413768ffee6844a561 100644 --- a/drivers/mfd/intel_soc_pmic_crc.c +++ b/drivers/mfd/intel_soc_pmic_crc.c @@ -263,7 +263,7 @@ static struct i2c_driver crystal_cove_i2c_driver = { .pm = pm_sleep_ptr(&crystal_cove_pm_ops), .acpi_match_table = crystal_cove_acpi_match, }, - .probe_new = crystal_cove_i2c_probe, + .probe = crystal_cove_i2c_probe, .remove = crystal_cove_i2c_remove, .shutdown = crystal_cove_shutdown, }; diff --git a/drivers/mfd/iqs62x.c b/drivers/mfd/iqs62x.c index 1895fce25b060b1845506133fb6e49cb4432b64e..dfe9cb79e6a14b732bb3d49779cd15d574f845a1 100644 --- a/drivers/mfd/iqs62x.c +++ b/drivers/mfd/iqs62x.c @@ -1069,7 +1069,7 @@ static struct i2c_driver iqs62x_i2c_driver = { .of_match_table = iqs62x_of_match, .pm = &iqs62x_pm, }, - .probe_new = iqs62x_probe, + .probe = iqs62x_probe, .remove = iqs62x_remove, }; module_i2c_driver(iqs62x_i2c_driver); diff --git a/drivers/mfd/khadas-mcu.c b/drivers/mfd/khadas-mcu.c index 1c807c0e6d25a2c52fa4bf57158a4c8d7ac6a35a..61396d824f16df67cfde41c1fe27310da1ca95be 100644 --- a/drivers/mfd/khadas-mcu.c +++ b/drivers/mfd/khadas-mcu.c @@ -134,7 +134,7 @@ static struct i2c_driver khadas_mcu_driver = { .name = "khadas-mcu-core", .of_match_table = of_match_ptr(khadas_mcu_of_match), }, - .probe_new = khadas_mcu_probe, + .probe = khadas_mcu_probe, }; module_i2c_driver(khadas_mcu_driver); diff --git a/drivers/mfd/lm3533-core.c b/drivers/mfd/lm3533-core.c index 946f94f3a3c3090b4835b09d0a40b842582b8c71..c211183cecb242ea9243c30b261a7c0eb5906586 100644 --- a/drivers/mfd/lm3533-core.c +++ b/drivers/mfd/lm3533-core.c @@ -485,8 +485,6 @@ static int lm3533_device_init(struct lm3533 *lm3533) lm3533->gpio_hwen = pdata->gpio_hwen; - dev_set_drvdata(lm3533->dev, lm3533); - if (gpio_is_valid(lm3533->gpio_hwen)) { ret = devm_gpio_request_one(lm3533->dev, lm3533->gpio_hwen, GPIOF_OUT_INIT_LOW, "lm3533-hwen"); @@ -626,7 +624,7 @@ static struct i2c_driver lm3533_i2c_driver = { .name = "lm3533", }, .id_table = lm3533_i2c_ids, - .probe_new = lm3533_i2c_probe, + .probe = lm3533_i2c_probe, .remove = lm3533_i2c_remove, }; diff --git a/drivers/mfd/lochnagar-i2c.c b/drivers/mfd/lochnagar-i2c.c index 3a65d9938902351f496e3baddb78cdd54b5537ea..3c8843117080ccc8a3185d9cf60cedadd0a95c9e 100644 --- a/drivers/mfd/lochnagar-i2c.c +++ b/drivers/mfd/lochnagar-i2c.c @@ -382,7 +382,7 @@ static struct i2c_driver lochnagar_i2c_driver = { .of_match_table = of_match_ptr(lochnagar_of_match), .suppress_bind_attrs = true, }, - .probe_new = lochnagar_i2c_probe, + .probe = lochnagar_i2c_probe, }; static int __init lochnagar_i2c_init(void) diff --git a/drivers/mfd/lp3943.c b/drivers/mfd/lp3943.c index f9f39b53d03008595f645d7285515863fced4b61..7f749a23dca84f4567c401d74e3bea46f5ad05ce 100644 --- a/drivers/mfd/lp3943.c +++ b/drivers/mfd/lp3943.c @@ -140,7 +140,7 @@ MODULE_DEVICE_TABLE(of, lp3943_of_match); #endif static struct i2c_driver lp3943_driver = { - .probe_new = lp3943_probe, + .probe = lp3943_probe, .driver = { .name = "lp3943", .of_match_table = of_match_ptr(lp3943_of_match), diff --git a/drivers/mfd/lp873x.c b/drivers/mfd/lp873x.c index c81c5c9ad7489a363d8e59216d09278883fc602a..6639f0fad4ea98495633680cc009a932d1433f81 100644 --- a/drivers/mfd/lp873x.c +++ b/drivers/mfd/lp873x.c @@ -78,7 +78,7 @@ static struct i2c_driver lp873x_driver = { .name = "lp873x", .of_match_table = of_lp873x_match_table, }, - .probe_new = lp873x_probe, + .probe = lp873x_probe, .id_table = lp873x_id_table, }; module_i2c_driver(lp873x_driver); diff --git a/drivers/mfd/lp87565.c b/drivers/mfd/lp87565.c index 568f0f01ea0d2e0925fd840ecd64e8f56bed2bcc..88ce4d7c50a71c4007a407c340bb0b50aa6a2485 100644 --- a/drivers/mfd/lp87565.c +++ b/drivers/mfd/lp87565.c @@ -119,7 +119,7 @@ static struct i2c_driver lp87565_driver = { .name = "lp87565", .of_match_table = of_lp87565_match_table, }, - .probe_new = lp87565_probe, + .probe = lp87565_probe, .shutdown = lp87565_shutdown, .id_table = lp87565_id_table, }; diff --git a/drivers/mfd/lp8788.c b/drivers/mfd/lp8788.c index 18583addaae289498436ba9858c90fce7ba3423e..f371eeb042e031ea699a12261ec1504ca60af8eb 100644 --- a/drivers/mfd/lp8788.c +++ b/drivers/mfd/lp8788.c @@ -225,7 +225,7 @@ static struct i2c_driver lp8788_driver = { .driver = { .name = "lp8788", }, - .probe_new = lp8788_probe, + .probe = lp8788_probe, .remove = lp8788_remove, .id_table = lp8788_ids, }; diff --git a/drivers/mfd/madera-i2c.c b/drivers/mfd/madera-i2c.c index 47e65d88feb0ebad6bc300bff826cfa554461833..0968aa9733ac0f0b2f03682d037e8f01f6e1d274 100644 --- a/drivers/mfd/madera-i2c.c +++ b/drivers/mfd/madera-i2c.c @@ -139,7 +139,7 @@ static struct i2c_driver madera_i2c_driver = { .pm = &madera_pm_ops, .of_match_table = of_match_ptr(madera_of_match), }, - .probe_new = madera_i2c_probe, + .probe = madera_i2c_probe, .remove = madera_i2c_remove, .id_table = madera_i2c_id, }; diff --git a/drivers/mfd/max14577.c b/drivers/mfd/max14577.c index 0e3731e9e9b59793e61c26bcd00f426932e735d7..25ed8846b7fbb01d9c753cc13b678e27d9203161 100644 --- a/drivers/mfd/max14577.c +++ b/drivers/mfd/max14577.c @@ -518,7 +518,7 @@ static struct i2c_driver max14577_i2c_driver = { .pm = pm_sleep_ptr(&max14577_pm), .of_match_table = max14577_dt_match, }, - .probe_new = max14577_i2c_probe, + .probe = max14577_i2c_probe, .remove = max14577_i2c_remove, .id_table = max14577_i2c_id, }; diff --git a/drivers/mfd/max77541.c b/drivers/mfd/max77541.c new file mode 100644 index 0000000000000000000000000000000000000000..e147e949c2b31a1b053905923e53946327dc0ac4 --- /dev/null +++ b/drivers/mfd/max77541.c @@ -0,0 +1,224 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2022 Analog Devices, Inc. + * Driver for the MAX77540 and MAX77541 + */ + +#include +#include +#include +#include +#include +#include + +static const struct regmap_config max77541_regmap_config = { + .reg_bits = 8, + .val_bits = 8, +}; + +static const struct regmap_irq max77541_src_irqs[] = { + { .mask = MAX77541_BIT_INT_SRC_TOPSYS }, + { .mask = MAX77541_BIT_INT_SRC_BUCK }, +}; + +static const struct regmap_irq_chip max77541_src_irq_chip = { + .name = "max77541-src", + .status_base = MAX77541_REG_INT_SRC, + .mask_base = MAX77541_REG_INT_SRC_M, + .num_regs = 1, + .irqs = max77541_src_irqs, + .num_irqs = ARRAY_SIZE(max77541_src_irqs), +}; + +static const struct regmap_irq max77541_topsys_irqs[] = { + { .mask = MAX77541_BIT_TOPSYS_INT_TJ_120C }, + { .mask = MAX77541_BIT_TOPSYS_INT_TJ_140C }, + { .mask = MAX77541_BIT_TOPSYS_INT_TSHDN }, + { .mask = MAX77541_BIT_TOPSYS_INT_UVLO }, + { .mask = MAX77541_BIT_TOPSYS_INT_ALT_SWO }, + { .mask = MAX77541_BIT_TOPSYS_INT_EXT_FREQ_DET }, +}; + +static const struct regmap_irq_chip max77541_topsys_irq_chip = { + .name = "max77541-topsys", + .status_base = MAX77541_REG_TOPSYS_INT, + .mask_base = MAX77541_REG_TOPSYS_INT_M, + .num_regs = 1, + .irqs = max77541_topsys_irqs, + .num_irqs = ARRAY_SIZE(max77541_topsys_irqs), +}; + +static const struct regmap_irq max77541_buck_irqs[] = { + { .mask = MAX77541_BIT_BUCK_INT_M1_POK_FLT }, + { .mask = MAX77541_BIT_BUCK_INT_M2_POK_FLT }, + { .mask = MAX77541_BIT_BUCK_INT_M1_SCFLT }, + { .mask = MAX77541_BIT_BUCK_INT_M2_SCFLT }, +}; + +static const struct regmap_irq_chip max77541_buck_irq_chip = { + .name = "max77541-buck", + .status_base = MAX77541_REG_BUCK_INT, + .mask_base = MAX77541_REG_BUCK_INT_M, + .num_regs = 1, + .irqs = max77541_buck_irqs, + .num_irqs = ARRAY_SIZE(max77541_buck_irqs), +}; + +static const struct regmap_irq max77541_adc_irqs[] = { + { .mask = MAX77541_BIT_ADC_INT_CH1_I }, + { .mask = MAX77541_BIT_ADC_INT_CH2_I }, + { .mask = MAX77541_BIT_ADC_INT_CH3_I }, + { .mask = MAX77541_BIT_ADC_INT_CH6_I }, +}; + +static const struct regmap_irq_chip max77541_adc_irq_chip = { + .name = "max77541-adc", + .status_base = MAX77541_REG_ADC_INT, + .mask_base = MAX77541_REG_ADC_INT_M, + .num_regs = 1, + .irqs = max77541_adc_irqs, + .num_irqs = ARRAY_SIZE(max77541_adc_irqs), +}; + +static const struct mfd_cell max77540_devs[] = { + MFD_CELL_OF("max77540-regulator", NULL, NULL, 0, 0, NULL), +}; + +static const struct mfd_cell max77541_devs[] = { + MFD_CELL_OF("max77541-regulator", NULL, NULL, 0, 0, NULL), + MFD_CELL_OF("max77541-adc", NULL, NULL, 0, 0, NULL), +}; + +static int max77541_pmic_irq_init(struct device *dev) +{ + struct max77541 *max77541 = dev_get_drvdata(dev); + int irq = max77541->i2c->irq; + int ret; + + ret = devm_regmap_add_irq_chip(dev, max77541->regmap, irq, + IRQF_ONESHOT | IRQF_SHARED, 0, + &max77541_src_irq_chip, + &max77541->irq_data); + if (ret) + return ret; + + ret = devm_regmap_add_irq_chip(dev, max77541->regmap, irq, + IRQF_ONESHOT | IRQF_SHARED, 0, + &max77541_topsys_irq_chip, + &max77541->irq_topsys); + if (ret) + return ret; + + ret = devm_regmap_add_irq_chip(dev, max77541->regmap, irq, + IRQF_ONESHOT | IRQF_SHARED, 0, + &max77541_buck_irq_chip, + &max77541->irq_buck); + if (ret) + return ret; + + if (max77541->id == MAX77541) { + ret = devm_regmap_add_irq_chip(dev, max77541->regmap, irq, + IRQF_ONESHOT | IRQF_SHARED, 0, + &max77541_adc_irq_chip, + &max77541->irq_adc); + if (ret) + return ret; + } + + return 0; +} + +static int max77541_pmic_setup(struct device *dev) +{ + struct max77541 *max77541 = dev_get_drvdata(dev); + const struct mfd_cell *cells; + int n_devs; + int ret; + + switch (max77541->id) { + case MAX77540: + cells = max77540_devs; + n_devs = ARRAY_SIZE(max77540_devs); + break; + case MAX77541: + cells = max77541_devs; + n_devs = ARRAY_SIZE(max77541_devs); + break; + default: + return -EINVAL; + } + + ret = max77541_pmic_irq_init(dev); + if (ret) + return dev_err_probe(dev, ret, "Failed to initialize IRQ\n"); + + ret = device_init_wakeup(dev, true); + if (ret) + return dev_err_probe(dev, ret, "Unable to init wakeup\n"); + + return devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE, + cells, n_devs, NULL, 0, NULL); +} + +static int max77541_probe(struct i2c_client *client) +{ + const struct i2c_device_id *id = i2c_client_get_device_id(client); + struct device *dev = &client->dev; + struct max77541 *max77541; + + max77541 = devm_kzalloc(dev, sizeof(*max77541), GFP_KERNEL); + if (!max77541) + return -ENOMEM; + + i2c_set_clientdata(client, max77541); + max77541->i2c = client; + + max77541->id = (enum max7754x_ids)device_get_match_data(dev); + if (!max77541->id) + max77541->id = (enum max7754x_ids)id->driver_data; + + if (!max77541->id) + return -EINVAL; + + max77541->regmap = devm_regmap_init_i2c(client, + &max77541_regmap_config); + if (IS_ERR(max77541->regmap)) + return dev_err_probe(dev, PTR_ERR(max77541->regmap), + "Failed to allocate register map\n"); + + return max77541_pmic_setup(dev); +} + +static const struct of_device_id max77541_of_id[] = { + { + .compatible = "adi,max77540", + .data = (void *)MAX77540, + }, + { + .compatible = "adi,max77541", + .data = (void *)MAX77541, + }, + { } +}; +MODULE_DEVICE_TABLE(of, max77541_of_id); + +static const struct i2c_device_id max77541_id[] = { + { "max77540", MAX77540 }, + { "max77541", MAX77541 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, max77541_id); + +static struct i2c_driver max77541_driver = { + .driver = { + .name = "max77541", + .of_match_table = max77541_of_id, + }, + .probe = max77541_probe, + .id_table = max77541_id, +}; +module_i2c_driver(max77541_driver); + +MODULE_DESCRIPTION("MAX7740/MAX7741 Driver"); +MODULE_AUTHOR("Okan Sahin "); +MODULE_LICENSE("GPL"); diff --git a/drivers/mfd/max77620.c b/drivers/mfd/max77620.c index cbd2297126f041756b3e04235c6067fa13837b18..5811ed8f484033b967199a871a766acce4a4524f 100644 --- a/drivers/mfd/max77620.c +++ b/drivers/mfd/max77620.c @@ -698,7 +698,7 @@ static struct i2c_driver max77620_driver = { .name = "max77620", .pm = pm_sleep_ptr(&max77620_pm_ops), }, - .probe_new = max77620_probe, + .probe = max77620_probe, .id_table = max77620_id, }; builtin_i2c_driver(max77620_driver); diff --git a/drivers/mfd/max77650.c b/drivers/mfd/max77650.c index 3c07fcdd9d076a29f94c39fe77c93459b25393e0..75b5dc44e38cee0e0c733d7d59c3bd7477d1deed 100644 --- a/drivers/mfd/max77650.c +++ b/drivers/mfd/max77650.c @@ -222,7 +222,7 @@ static struct i2c_driver max77650_i2c_driver = { .name = "max77650", .of_match_table = max77650_of_match, }, - .probe_new = max77650_i2c_probe, + .probe = max77650_i2c_probe, }; module_i2c_driver(max77650_i2c_driver); diff --git a/drivers/mfd/max77686.c b/drivers/mfd/max77686.c index f8e863f3fc95812b330e1bf3a151a7e302f113aa..01833086ca7dec476295a520113ffe691cdae5a1 100644 --- a/drivers/mfd/max77686.c +++ b/drivers/mfd/max77686.c @@ -269,7 +269,7 @@ static struct i2c_driver max77686_i2c_driver = { .pm = pm_sleep_ptr(&max77686_pm), .of_match_table = max77686_pmic_dt_match, }, - .probe_new = max77686_i2c_probe, + .probe = max77686_i2c_probe, }; module_i2c_driver(max77686_i2c_driver); diff --git a/drivers/mfd/max77693.c b/drivers/mfd/max77693.c index 3995e8769f491340c499404b19de1d97f50e4f86..1c485a4c3dcf8672d9cf07c254dbc2ffdf07a003 100644 --- a/drivers/mfd/max77693.c +++ b/drivers/mfd/max77693.c @@ -356,7 +356,7 @@ static struct i2c_driver max77693_i2c_driver = { .pm = &max77693_pm, .of_match_table = of_match_ptr(max77693_dt_match), }, - .probe_new = max77693_i2c_probe, + .probe = max77693_i2c_probe, .remove = max77693_i2c_remove, .id_table = max77693_i2c_id, }; diff --git a/drivers/mfd/max77714.c b/drivers/mfd/max77714.c index 143a432ea343676b81a07fbdc3c9e1d92355e253..c618605a3fb29dc6f41609e691f3354dc67f5f62 100644 --- a/drivers/mfd/max77714.c +++ b/drivers/mfd/max77714.c @@ -143,7 +143,7 @@ static struct i2c_driver max77714_driver = { .name = "max77714", .of_match_table = max77714_dt_match, }, - .probe_new = max77714_probe, + .probe = max77714_probe, }; module_i2c_driver(max77714_driver); diff --git a/drivers/mfd/max77843.c b/drivers/mfd/max77843.c index 8ff0723808c8e66a76e0fa0a9a6c20daf9bfabbb..b3689c13a14db6d73ff71b20bf3676836491ec18 100644 --- a/drivers/mfd/max77843.c +++ b/drivers/mfd/max77843.c @@ -207,7 +207,7 @@ static struct i2c_driver max77843_i2c_driver = { .of_match_table = max77843_dt_match, .suppress_bind_attrs = true, }, - .probe_new = max77843_probe, + .probe = max77843_probe, .id_table = max77843_id, }; diff --git a/drivers/mfd/max8907.c b/drivers/mfd/max8907.c index a69b865c6eacf3b3a0355d284e61328ce77fda27..78b5ee688decc6bcae51025cdf61f6f566938872 100644 --- a/drivers/mfd/max8907.c +++ b/drivers/mfd/max8907.c @@ -201,8 +201,6 @@ static int max8907_i2c_probe(struct i2c_client *i2c) } max8907->dev = &i2c->dev; - dev_set_drvdata(max8907->dev, max8907); - max8907->i2c_gen = i2c; i2c_set_clientdata(i2c, max8907); max8907->regmap_gen = devm_regmap_init_i2c(i2c, @@ -313,7 +311,7 @@ static struct i2c_driver max8907_i2c_driver = { .name = "max8907", .of_match_table = of_match_ptr(max8907_of_match), }, - .probe_new = max8907_i2c_probe, + .probe = max8907_i2c_probe, .remove = max8907_i2c_remove, .id_table = max8907_i2c_id, }; diff --git a/drivers/mfd/max8925-i2c.c b/drivers/mfd/max8925-i2c.c index 4057fd15c29e74dcc39952d67a1d017bb959d657..7608000488f950529e7876e514d8478474b4bca6 100644 --- a/drivers/mfd/max8925-i2c.c +++ b/drivers/mfd/max8925-i2c.c @@ -172,7 +172,6 @@ static int max8925_probe(struct i2c_client *client) chip->i2c = client; chip->dev = &client->dev; i2c_set_clientdata(client, chip); - dev_set_drvdata(chip->dev, chip); mutex_init(&chip->io_lock); chip->rtc = i2c_new_dummy_device(chip->i2c->adapter, RTC_I2C_ADDR); @@ -240,7 +239,7 @@ static struct i2c_driver max8925_driver = { .pm = pm_sleep_ptr(&max8925_pm_ops), .of_match_table = max8925_dt_ids, }, - .probe_new = max8925_probe, + .probe = max8925_probe, .remove = max8925_remove, .id_table = max8925_id_table, }; diff --git a/drivers/mfd/max8997.c b/drivers/mfd/max8997.c index 79d551b86150f69af3f6f0faf781e3abea04f1e4..94c09a5eab32c3336e5a99f791f3e90a9757404e 100644 --- a/drivers/mfd/max8997.c +++ b/drivers/mfd/max8997.c @@ -478,7 +478,7 @@ static struct i2c_driver max8997_i2c_driver = { .suppress_bind_attrs = true, .of_match_table = of_match_ptr(max8997_pmic_dt_match), }, - .probe_new = max8997_i2c_probe, + .probe = max8997_i2c_probe, .id_table = max8997_i2c_id, }; diff --git a/drivers/mfd/max8998.c b/drivers/mfd/max8998.c index 122f7b931f5a22ff00234846f9f9f764ea03ea81..33a3ec5464fb6459e431cfcc5e64af332f3600f0 100644 --- a/drivers/mfd/max8998.c +++ b/drivers/mfd/max8998.c @@ -348,7 +348,7 @@ static struct i2c_driver max8998_i2c_driver = { .suppress_bind_attrs = true, .of_match_table = of_match_ptr(max8998_dt_match), }, - .probe_new = max8998_i2c_probe, + .probe = max8998_i2c_probe, .id_table = max8998_i2c_id, }; diff --git a/drivers/mfd/mc13xxx-i2c.c b/drivers/mfd/mc13xxx-i2c.c index 633b973a5ba77c0427b2a76f6204dab1caf5fb61..de59b498c925e2f19c6df473235f3616b601f7fe 100644 --- a/drivers/mfd/mc13xxx-i2c.c +++ b/drivers/mfd/mc13xxx-i2c.c @@ -95,7 +95,7 @@ static struct i2c_driver mc13xxx_i2c_driver = { .name = "mc13xxx", .of_match_table = mc13xxx_dt_ids, }, - .probe_new = mc13xxx_i2c_probe, + .probe = mc13xxx_i2c_probe, .remove = mc13xxx_i2c_remove, }; diff --git a/drivers/mfd/menelaus.c b/drivers/mfd/menelaus.c index c2866a11c1d22ac1de692a229906243fd51cf1e3..662604ea97f222237886cd9f53d16093f9fdfd15 100644 --- a/drivers/mfd/menelaus.c +++ b/drivers/mfd/menelaus.c @@ -1240,7 +1240,7 @@ static struct i2c_driver menelaus_i2c_driver = { .driver = { .name = DRIVER_NAME, }, - .probe_new = menelaus_probe, + .probe = menelaus_probe, .remove = menelaus_remove, .id_table = menelaus_id, }; diff --git a/drivers/mfd/menf21bmc.c b/drivers/mfd/menf21bmc.c index 9092fac46e35980d79854320cad050f09319a38d..1d36095155e047446bbb95f21828bfa442247748 100644 --- a/drivers/mfd/menf21bmc.c +++ b/drivers/mfd/menf21bmc.c @@ -111,7 +111,7 @@ MODULE_DEVICE_TABLE(i2c, menf21bmc_id_table); static struct i2c_driver menf21bmc_driver = { .driver.name = "menf21bmc", .id_table = menf21bmc_id_table, - .probe_new = menf21bmc_probe, + .probe = menf21bmc_probe, }; module_i2c_driver(menf21bmc_driver); diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c index 695d50b3bac67a81a7e5fac709c98737c3c6a38f..0ed7c0d7784e1bf18b619fd3e7b6d909a1d26c52 100644 --- a/drivers/mfd/mfd-core.c +++ b/drivers/mfd/mfd-core.c @@ -102,7 +102,6 @@ static int mfd_match_of_node_to_dev(struct platform_device *pdev, { #if IS_ENABLED(CONFIG_OF) struct mfd_of_node_entry *of_entry; - const __be32 *reg; u64 of_node_addr; /* Skip if OF node has previously been allocated to a device */ @@ -115,13 +114,10 @@ static int mfd_match_of_node_to_dev(struct platform_device *pdev, goto allocate_of_node; /* We only care about each node's first defined address */ - reg = of_get_address(np, 0, NULL, NULL); - if (!reg) + if (of_property_read_reg(np, 0, &of_node_addr, NULL)) /* OF node does not contatin a 'reg' property to match to */ return -EAGAIN; - of_node_addr = of_read_number(reg, of_n_addr_cells(np)); - if (cell->of_reg != of_node_addr) /* No match */ return -EAGAIN; diff --git a/drivers/mfd/mp2629.c b/drivers/mfd/mp2629.c index 16840ec5fd1cde407e1748fc88a1d474c786c925..717b704c3c6b7ba1e2bdc61eb4a7adac42dddac9 100644 --- a/drivers/mfd/mp2629.c +++ b/drivers/mfd/mp2629.c @@ -70,7 +70,7 @@ static struct i2c_driver mp2629_driver = { .name = "mp2629", .of_match_table = mp2629_of_match, }, - .probe_new = mp2629_probe, + .probe = mp2629_probe, }; module_i2c_driver(mp2629_driver); diff --git a/drivers/mfd/mt6360-core.c b/drivers/mfd/mt6360-core.c index d3b32eb79837755a7d31cfd73b3d813e44f40fd2..2685efa5c9e2d374a885a066c49f89acd0eca67c 100644 --- a/drivers/mfd/mt6360-core.c +++ b/drivers/mfd/mt6360-core.c @@ -623,7 +623,7 @@ static struct i2c_driver mt6360_driver = { .pm = &mt6360_pm_ops, .of_match_table = of_match_ptr(mt6360_of_id), }, - .probe_new = mt6360_probe, + .probe = mt6360_probe, }; module_i2c_driver(mt6360_driver); diff --git a/drivers/mfd/mt6370.c b/drivers/mfd/mt6370.c index cf19cce2fdc0bc16684bb958c7b96a598d07f066..c126ccb25d668d2ada522bdacce62a07bed2238d 100644 --- a/drivers/mfd/mt6370.c +++ b/drivers/mfd/mt6370.c @@ -303,7 +303,7 @@ static struct i2c_driver mt6370_driver = { .name = "mt6370", .of_match_table = mt6370_match_table, }, - .probe_new = mt6370_probe, + .probe = mt6370_probe, }; module_i2c_driver(mt6370_driver); diff --git a/drivers/mfd/ntxec.c b/drivers/mfd/ntxec.c index b02785b10d48470d486dc80a23022608a6bfb3ab..4416cd37e539bf8be80ed47954491020de09728c 100644 --- a/drivers/mfd/ntxec.c +++ b/drivers/mfd/ntxec.c @@ -260,7 +260,7 @@ static struct i2c_driver ntxec_driver = { .name = "ntxec", .of_match_table = of_ntxec_match_table, }, - .probe_new = ntxec_probe, + .probe = ntxec_probe, .remove = ntxec_remove, }; module_i2c_driver(ntxec_driver); diff --git a/drivers/mfd/palmas.c b/drivers/mfd/palmas.c index b8383c6cba3ff9842f4382c4755dc259a06e35e3..a36f12402987cc6550a785f8b9cc075cc925c059 100644 --- a/drivers/mfd/palmas.c +++ b/drivers/mfd/palmas.c @@ -725,7 +725,7 @@ static struct i2c_driver palmas_i2c_driver = { .name = "palmas", .of_match_table = of_palmas_match_tbl, }, - .probe_new = palmas_i2c_probe, + .probe = palmas_i2c_probe, .remove = palmas_i2c_remove, .id_table = palmas_i2c_id, }; diff --git a/drivers/mfd/pcf50633-core.c b/drivers/mfd/pcf50633-core.c index 0e4fc99e9f492d7ec57a91701d044a06ce2ff18a..014a68711b18a3b5d2a1f71a9b2cc13ece18e390 100644 --- a/drivers/mfd/pcf50633-core.c +++ b/drivers/mfd/pcf50633-core.c @@ -282,7 +282,7 @@ static struct i2c_driver pcf50633_driver = { .pm = pm_sleep_ptr(&pcf50633_pm), }, .id_table = pcf50633_id_table, - .probe_new = pcf50633_probe, + .probe = pcf50633_probe, .remove = pcf50633_remove, }; diff --git a/drivers/mfd/qcom-pm8008.c b/drivers/mfd/qcom-pm8008.c index 837246aab4ace94af65aef2d23a39c32de05fd25..94a8cca1d9551165c7fb572965c475c6d6d46d15 100644 --- a/drivers/mfd/qcom-pm8008.c +++ b/drivers/mfd/qcom-pm8008.c @@ -199,15 +199,15 @@ static const struct of_device_id pm8008_match[] = { { .compatible = "qcom,pm8008", }, { }, }; +MODULE_DEVICE_TABLE(of, pm8008_match); static struct i2c_driver pm8008_mfd_driver = { .driver = { .name = "pm8008", .of_match_table = pm8008_match, }, - .probe_new = pm8008_probe, + .probe = pm8008_probe, }; module_i2c_driver(pm8008_mfd_driver); MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("i2c:qcom-pm8008"); diff --git a/drivers/mfd/rc5t583-irq.c b/drivers/mfd/rc5t583-irq.c index 621ea61fa7c62983560c4ddca451f5ddbec3c5ad..97f52b671520bc1cc3a39131de4b1c59be9e0b10 100644 --- a/drivers/mfd/rc5t583-irq.c +++ b/drivers/mfd/rc5t583-irq.c @@ -8,9 +8,9 @@ * based on code * Copyright (C) 2011 RICOH COMPANY,LTD */ +#include #include #include -#include #include enum int_type { diff --git a/drivers/mfd/rc5t583.c b/drivers/mfd/rc5t583.c index df83cc39931514a8f3f67f0f9763bef6752403fe..5e81f011363ffd7108bddce3a65bf3e525906f15 100644 --- a/drivers/mfd/rc5t583.c +++ b/drivers/mfd/rc5t583.c @@ -288,7 +288,7 @@ static struct i2c_driver rc5t583_i2c_driver = { .driver = { .name = "rc5t583", }, - .probe_new = rc5t583_i2c_probe, + .probe = rc5t583_i2c_probe, .id_table = rc5t583_i2c_id, }; diff --git a/drivers/mfd/retu-mfd.c b/drivers/mfd/retu-mfd.c index d71483859e2ef51225a269ba5159dff6a76777e8..b50cfa7f4b8f4d7caedbe5fb53e1cd247c6e19f2 100644 --- a/drivers/mfd/retu-mfd.c +++ b/drivers/mfd/retu-mfd.c @@ -318,7 +318,7 @@ static struct i2c_driver retu_driver = { .name = "retu-mfd", .of_match_table = retu_of_match, }, - .probe_new = retu_probe, + .probe = retu_probe, .remove = retu_remove, .id_table = retu_id, }; diff --git a/drivers/mfd/rk808.c b/drivers/mfd/rk8xx-core.c similarity index 71% rename from drivers/mfd/rk808.c rename to drivers/mfd/rk8xx-core.c index 0f22ef61e8170dd594777597bc2d7e34daa99cd1..e8fc9e2ab1d0d2e27a4d05029a14fa02082f3cd1 100644 --- a/drivers/mfd/rk808.c +++ b/drivers/mfd/rk8xx-core.c @@ -1,18 +1,15 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * MFD core driver for Rockchip RK808/RK818 + * MFD core driver for Rockchip RK8XX * * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd + * Copyright (C) 2016 PHYTEC Messtechnik GmbH * * Author: Chris Zhong * Author: Zhang Qing - * - * Copyright (C) 2016 PHYTEC Messtechnik GmbH - * * Author: Wadim Egorov */ -#include #include #include #include @@ -27,92 +24,6 @@ struct rk808_reg_data { int value; }; -static bool rk808_is_volatile_reg(struct device *dev, unsigned int reg) -{ - /* - * Notes: - * - Technically the ROUND_30s bit makes RTC_CTRL_REG volatile, but - * we don't use that feature. It's better to cache. - * - It's unlikely we care that RK808_DEVCTRL_REG is volatile since - * bits are cleared in case when we shutoff anyway, but better safe. - */ - - switch (reg) { - case RK808_SECONDS_REG ... RK808_WEEKS_REG: - case RK808_RTC_STATUS_REG: - case RK808_VB_MON_REG: - case RK808_THERMAL_REG: - case RK808_DCDC_UV_STS_REG: - case RK808_LDO_UV_STS_REG: - case RK808_DCDC_PG_REG: - case RK808_LDO_PG_REG: - case RK808_DEVCTRL_REG: - case RK808_INT_STS_REG1: - case RK808_INT_STS_REG2: - return true; - } - - return false; -} - -static bool rk817_is_volatile_reg(struct device *dev, unsigned int reg) -{ - /* - * Notes: - * - Technically the ROUND_30s bit makes RTC_CTRL_REG volatile, but - * we don't use that feature. It's better to cache. - */ - - switch (reg) { - case RK817_SECONDS_REG ... RK817_WEEKS_REG: - case RK817_RTC_STATUS_REG: - case RK817_CODEC_DTOP_LPT_SRST: - case RK817_GAS_GAUGE_ADC_CONFIG0 ... RK817_GAS_GAUGE_CUR_ADC_K0: - case RK817_PMIC_CHRG_STS: - case RK817_PMIC_CHRG_OUT: - case RK817_PMIC_CHRG_IN: - case RK817_INT_STS_REG0: - case RK817_INT_STS_REG1: - case RK817_INT_STS_REG2: - case RK817_SYS_STS: - return true; - } - - return false; -} - -static const struct regmap_config rk818_regmap_config = { - .reg_bits = 8, - .val_bits = 8, - .max_register = RK818_USB_CTRL_REG, - .cache_type = REGCACHE_RBTREE, - .volatile_reg = rk808_is_volatile_reg, -}; - -static const struct regmap_config rk805_regmap_config = { - .reg_bits = 8, - .val_bits = 8, - .max_register = RK805_OFF_SOURCE_REG, - .cache_type = REGCACHE_RBTREE, - .volatile_reg = rk808_is_volatile_reg, -}; - -static const struct regmap_config rk808_regmap_config = { - .reg_bits = 8, - .val_bits = 8, - .max_register = RK808_IO_POL_REG, - .cache_type = REGCACHE_RBTREE, - .volatile_reg = rk808_is_volatile_reg, -}; - -static const struct regmap_config rk817_regmap_config = { - .reg_bits = 8, - .val_bits = 8, - .max_register = RK817_GPIO_INT_CFG, - .cache_type = REGCACHE_NONE, - .volatile_reg = rk817_is_volatile_reg, -}; - static const struct resource rtc_resources[] = { DEFINE_RES_IRQ(RK808_IRQ_RTC_ALARM), }; @@ -126,6 +37,11 @@ static const struct resource rk805_key_resources[] = { DEFINE_RES_IRQ(RK805_IRQ_PWRON_FALL), }; +static struct resource rk806_pwrkey_resources[] = { + DEFINE_RES_IRQ(RK806_IRQ_PWRON_FALL), + DEFINE_RES_IRQ(RK806_IRQ_PWRON_RISE), +}; + static const struct resource rk817_pwrkey_resources[] = { DEFINE_RES_IRQ(RK817_IRQ_PWRON_RISE), DEFINE_RES_IRQ(RK817_IRQ_PWRON_FALL), @@ -153,6 +69,17 @@ static const struct mfd_cell rk805s[] = { }, }; +static const struct mfd_cell rk806s[] = { + { .name = "rk805-pinctrl", .id = PLATFORM_DEVID_AUTO, }, + { .name = "rk808-regulator", .id = PLATFORM_DEVID_AUTO, }, + { + .name = "rk805-pwrkey", + .resources = rk806_pwrkey_resources, + .num_resources = ARRAY_SIZE(rk806_pwrkey_resources), + .id = PLATFORM_DEVID_AUTO, + }, +}; + static const struct mfd_cell rk808s[] = { { .name = "rk808-clkout", .id = PLATFORM_DEVID_NONE, }, { .name = "rk808-regulator", .id = PLATFORM_DEVID_NONE, }, @@ -212,6 +139,12 @@ static const struct rk808_reg_data rk805_pre_init_reg[] = { {RK805_THERMAL_REG, TEMP_HOTDIE_MSK, TEMP115C}, }; +static const struct rk808_reg_data rk806_pre_init_reg[] = { + { RK806_GPIO_INT_CONFIG, RK806_INT_POL_MSK, RK806_INT_POL_L }, + { RK806_SYS_CFG3, RK806_SLAVE_RESTART_FUN_MSK, RK806_SLAVE_RESTART_FUN_EN }, + { RK806_SYS_OPTION, RK806_SYS_ENB2_2M_MSK, RK806_SYS_ENB2_2M_EN }, +}; + static const struct rk808_reg_data rk808_pre_init_reg[] = { { RK808_BUCK3_CONFIG_REG, BUCK_ILMIN_MASK, BUCK_ILMIN_150MA }, { RK808_BUCK4_CONFIG_REG, BUCK_ILMIN_MASK, BUCK_ILMIN_200MA }, @@ -362,6 +295,27 @@ static const struct regmap_irq rk805_irqs[] = { }, }; +static const struct regmap_irq rk806_irqs[] = { + /* INT_STS0 IRQs */ + REGMAP_IRQ_REG(RK806_IRQ_PWRON_FALL, 0, RK806_INT_STS_PWRON_FALL), + REGMAP_IRQ_REG(RK806_IRQ_PWRON_RISE, 0, RK806_INT_STS_PWRON_RISE), + REGMAP_IRQ_REG(RK806_IRQ_PWRON, 0, RK806_INT_STS_PWRON), + REGMAP_IRQ_REG(RK806_IRQ_PWRON_LP, 0, RK806_INT_STS_PWRON_LP), + REGMAP_IRQ_REG(RK806_IRQ_HOTDIE, 0, RK806_INT_STS_HOTDIE), + REGMAP_IRQ_REG(RK806_IRQ_VDC_RISE, 0, RK806_INT_STS_VDC_RISE), + REGMAP_IRQ_REG(RK806_IRQ_VDC_FALL, 0, RK806_INT_STS_VDC_FALL), + REGMAP_IRQ_REG(RK806_IRQ_VB_LO, 0, RK806_INT_STS_VB_LO), + /* INT_STS1 IRQs */ + REGMAP_IRQ_REG(RK806_IRQ_REV0, 1, RK806_INT_STS_REV0), + REGMAP_IRQ_REG(RK806_IRQ_REV1, 1, RK806_INT_STS_REV1), + REGMAP_IRQ_REG(RK806_IRQ_REV2, 1, RK806_INT_STS_REV2), + REGMAP_IRQ_REG(RK806_IRQ_CRC_ERROR, 1, RK806_INT_STS_CRC_ERROR), + REGMAP_IRQ_REG(RK806_IRQ_SLP3_GPIO, 1, RK806_INT_STS_SLP3_GPIO), + REGMAP_IRQ_REG(RK806_IRQ_SLP2_GPIO, 1, RK806_INT_STS_SLP2_GPIO), + REGMAP_IRQ_REG(RK806_IRQ_SLP1_GPIO, 1, RK806_INT_STS_SLP1_GPIO), + REGMAP_IRQ_REG(RK806_IRQ_WDT, 1, RK806_INT_STS_WDT), +}; + static const struct regmap_irq rk808_irqs[] = { /* INT_STS */ [RK808_IRQ_VOUT_LO] = { @@ -512,6 +466,18 @@ static struct regmap_irq_chip rk805_irq_chip = { .init_ack_masked = true, }; +static struct regmap_irq_chip rk806_irq_chip = { + .name = "rk806", + .irqs = rk806_irqs, + .num_irqs = ARRAY_SIZE(rk806_irqs), + .num_regs = 2, + .irq_reg_stride = 2, + .mask_base = RK806_INT_MSK0, + .status_base = RK806_INT_STS0, + .ack_base = RK806_INT_STS0, + .init_ack_masked = true, +}; + static const struct regmap_irq_chip rk808_irq_chip = { .name = "rk808", .irqs = rk808_irqs, @@ -548,13 +514,11 @@ static const struct regmap_irq_chip rk818_irq_chip = { .init_ack_masked = true, }; -static struct i2c_client *rk808_i2c_client; - -static void rk808_pm_power_off(void) +static int rk808_power_off(struct sys_off_data *data) { + struct rk808 *rk808 = data->cb_data; int ret; unsigned int reg, bit; - struct rk808 *rk808 = i2c_get_clientdata(rk808_i2c_client); switch (rk808->variant) { case RK805_ID: @@ -575,16 +539,18 @@ static void rk808_pm_power_off(void) bit = DEV_OFF; break; default: - return; + return NOTIFY_DONE; } ret = regmap_update_bits(rk808->regmap, reg, bit, bit); if (ret) - dev_err(&rk808_i2c_client->dev, "Failed to shutdown device!\n"); + dev_err(rk808->dev, "Failed to shutdown device!\n"); + + return NOTIFY_DONE; } -static int rk808_restart_notify(struct notifier_block *this, unsigned long mode, void *cmd) +static int rk808_restart(struct sys_off_data *data) { - struct rk808 *rk808 = i2c_get_clientdata(rk808_i2c_client); + struct rk808 *rk808 = data->cb_data; unsigned int reg, bit; int ret; @@ -600,19 +566,14 @@ static int rk808_restart_notify(struct notifier_block *this, unsigned long mode, } ret = regmap_update_bits(rk808->regmap, reg, bit, bit); if (ret) - dev_err(&rk808_i2c_client->dev, "Failed to restart device!\n"); + dev_err(rk808->dev, "Failed to restart device!\n"); return NOTIFY_DONE; } -static struct notifier_block rk808_restart_handler = { - .notifier_call = rk808_restart_notify, - .priority = 192, -}; - -static void rk8xx_shutdown(struct i2c_client *client) +void rk8xx_shutdown(struct device *dev) { - struct rk808 *rk808 = i2c_get_clientdata(client); + struct rk808 *rk808 = dev_get_drvdata(dev); int ret; switch (rk808->variant) { @@ -633,75 +594,47 @@ static void rk8xx_shutdown(struct i2c_client *client) return; } if (ret) - dev_warn(&client->dev, + dev_warn(dev, "Cannot switch to power down function\n"); } +EXPORT_SYMBOL_GPL(rk8xx_shutdown); -static const struct of_device_id rk808_of_match[] = { - { .compatible = "rockchip,rk805" }, - { .compatible = "rockchip,rk808" }, - { .compatible = "rockchip,rk809" }, - { .compatible = "rockchip,rk817" }, - { .compatible = "rockchip,rk818" }, - { }, -}; -MODULE_DEVICE_TABLE(of, rk808_of_match); - -static int rk808_probe(struct i2c_client *client) +int rk8xx_probe(struct device *dev, int variant, unsigned int irq, struct regmap *regmap) { - struct device_node *np = client->dev.of_node; struct rk808 *rk808; const struct rk808_reg_data *pre_init_reg; const struct mfd_cell *cells; + int dual_support = 0; int nr_pre_init_regs; int nr_cells; - int msb, lsb; - unsigned char pmic_id_msb, pmic_id_lsb; int ret; int i; - rk808 = devm_kzalloc(&client->dev, sizeof(*rk808), GFP_KERNEL); + rk808 = devm_kzalloc(dev, sizeof(*rk808), GFP_KERNEL); if (!rk808) return -ENOMEM; - - if (of_device_is_compatible(np, "rockchip,rk817") || - of_device_is_compatible(np, "rockchip,rk809")) { - pmic_id_msb = RK817_ID_MSB; - pmic_id_lsb = RK817_ID_LSB; - } else { - pmic_id_msb = RK808_ID_MSB; - pmic_id_lsb = RK808_ID_LSB; - } - - /* Read chip variant */ - msb = i2c_smbus_read_byte_data(client, pmic_id_msb); - if (msb < 0) { - dev_err(&client->dev, "failed to read the chip id at 0x%x\n", - RK808_ID_MSB); - return msb; - } - - lsb = i2c_smbus_read_byte_data(client, pmic_id_lsb); - if (lsb < 0) { - dev_err(&client->dev, "failed to read the chip id at 0x%x\n", - RK808_ID_LSB); - return lsb; - } - - rk808->variant = ((msb << 8) | lsb) & RK8XX_ID_MSK; - dev_info(&client->dev, "chip id: 0x%x\n", (unsigned int)rk808->variant); + rk808->dev = dev; + rk808->variant = variant; + rk808->regmap = regmap; + dev_set_drvdata(dev, rk808); switch (rk808->variant) { case RK805_ID: - rk808->regmap_cfg = &rk805_regmap_config; rk808->regmap_irq_chip = &rk805_irq_chip; pre_init_reg = rk805_pre_init_reg; nr_pre_init_regs = ARRAY_SIZE(rk805_pre_init_reg); cells = rk805s; nr_cells = ARRAY_SIZE(rk805s); break; + case RK806_ID: + rk808->regmap_irq_chip = &rk806_irq_chip; + pre_init_reg = rk806_pre_init_reg; + nr_pre_init_regs = ARRAY_SIZE(rk806_pre_init_reg); + cells = rk806s; + nr_cells = ARRAY_SIZE(rk806s); + dual_support = IRQF_SHARED; + break; case RK808_ID: - rk808->regmap_cfg = &rk808_regmap_config; rk808->regmap_irq_chip = &rk808_irq_chip; pre_init_reg = rk808_pre_init_reg; nr_pre_init_regs = ARRAY_SIZE(rk808_pre_init_reg); @@ -709,7 +642,6 @@ static int rk808_probe(struct i2c_client *client) nr_cells = ARRAY_SIZE(rk808s); break; case RK818_ID: - rk808->regmap_cfg = &rk818_regmap_config; rk808->regmap_irq_chip = &rk818_irq_chip; pre_init_reg = rk818_pre_init_reg; nr_pre_init_regs = ARRAY_SIZE(rk818_pre_init_reg); @@ -718,7 +650,6 @@ static int rk808_probe(struct i2c_client *client) break; case RK809_ID: case RK817_ID: - rk808->regmap_cfg = &rk817_regmap_config; rk808->regmap_irq_chip = &rk817_irq_chip; pre_init_reg = rk817_pre_init_reg; nr_pre_init_regs = ARRAY_SIZE(rk817_pre_init_reg); @@ -726,97 +657,64 @@ static int rk808_probe(struct i2c_client *client) nr_cells = ARRAY_SIZE(rk817s); break; default: - dev_err(&client->dev, "Unsupported RK8XX ID %lu\n", - rk808->variant); + dev_err(dev, "Unsupported RK8XX ID %lu\n", rk808->variant); return -EINVAL; } - rk808->i2c = client; - i2c_set_clientdata(client, rk808); - - rk808->regmap = devm_regmap_init_i2c(client, rk808->regmap_cfg); - if (IS_ERR(rk808->regmap)) { - dev_err(&client->dev, "regmap initialization failed\n"); - return PTR_ERR(rk808->regmap); - } - - if (!client->irq) { - dev_err(&client->dev, "No interrupt support, no core IRQ\n"); - return -EINVAL; - } + if (!irq) + return dev_err_probe(dev, -EINVAL, "No interrupt support, no core IRQ\n"); - ret = regmap_add_irq_chip(rk808->regmap, client->irq, - IRQF_ONESHOT, -1, - rk808->regmap_irq_chip, &rk808->irq_data); - if (ret) { - dev_err(&client->dev, "Failed to add irq_chip %d\n", ret); - return ret; - } + ret = devm_regmap_add_irq_chip(dev, rk808->regmap, irq, + IRQF_ONESHOT | dual_support, -1, + rk808->regmap_irq_chip, &rk808->irq_data); + if (ret) + return dev_err_probe(dev, ret, "Failed to add irq_chip\n"); for (i = 0; i < nr_pre_init_regs; i++) { ret = regmap_update_bits(rk808->regmap, pre_init_reg[i].addr, pre_init_reg[i].mask, pre_init_reg[i].value); - if (ret) { - dev_err(&client->dev, - "0x%x write err\n", - pre_init_reg[i].addr); - return ret; - } + if (ret) + return dev_err_probe(dev, ret, "0x%x write err\n", + pre_init_reg[i].addr); } - ret = devm_mfd_add_devices(&client->dev, PLATFORM_DEVID_NONE, - cells, nr_cells, NULL, 0, + ret = devm_mfd_add_devices(dev, 0, cells, nr_cells, NULL, 0, regmap_irq_get_domain(rk808->irq_data)); - if (ret) { - dev_err(&client->dev, "failed to add MFD devices %d\n", ret); - goto err_irq; - } + if (ret) + return dev_err_probe(dev, ret, "failed to add MFD devices\n"); - if (of_property_read_bool(np, "rockchip,system-power-controller")) { - rk808_i2c_client = client; - pm_power_off = rk808_pm_power_off; + if (device_property_read_bool(dev, "rockchip,system-power-controller")) { + ret = devm_register_sys_off_handler(dev, + SYS_OFF_MODE_POWER_OFF_PREPARE, SYS_OFF_PRIO_HIGH, + &rk808_power_off, rk808); + if (ret) + return dev_err_probe(dev, ret, + "failed to register poweroff handler\n"); switch (rk808->variant) { case RK809_ID: case RK817_ID: - ret = register_restart_handler(&rk808_restart_handler); + ret = devm_register_sys_off_handler(dev, + SYS_OFF_MODE_RESTART, SYS_OFF_PRIO_HIGH, + &rk808_restart, rk808); if (ret) - dev_warn(&client->dev, "failed to register rst handler, %d\n", ret); + dev_warn(dev, "failed to register rst handler, %d\n", ret); break; default: - dev_dbg(&client->dev, "pmic controlled board reset not supported\n"); + dev_dbg(dev, "pmic controlled board reset not supported\n"); break; } } return 0; - -err_irq: - regmap_del_irq_chip(client->irq, rk808->irq_data); - return ret; } +EXPORT_SYMBOL_GPL(rk8xx_probe); -static void rk808_remove(struct i2c_client *client) +int rk8xx_suspend(struct device *dev) { - struct rk808 *rk808 = i2c_get_clientdata(client); - - regmap_del_irq_chip(client->irq, rk808->irq_data); - - /** - * pm_power_off may points to a function from another module. - * Check if the pointer is set by us and only then overwrite it. - */ - if (pm_power_off == rk808_pm_power_off) - pm_power_off = NULL; - - unregister_restart_handler(&rk808_restart_handler); -} - -static int __maybe_unused rk8xx_suspend(struct device *dev) -{ - struct rk808 *rk808 = i2c_get_clientdata(to_i2c_client(dev)); + struct rk808 *rk808 = dev_get_drvdata(dev); int ret = 0; switch (rk808->variant) { @@ -839,10 +737,11 @@ static int __maybe_unused rk8xx_suspend(struct device *dev) return ret; } +EXPORT_SYMBOL_GPL(rk8xx_suspend); -static int __maybe_unused rk8xx_resume(struct device *dev) +int rk8xx_resume(struct device *dev) { - struct rk808 *rk808 = i2c_get_clientdata(to_i2c_client(dev)); + struct rk808 *rk808 = dev_get_drvdata(dev); int ret = 0; switch (rk808->variant) { @@ -859,23 +758,10 @@ static int __maybe_unused rk8xx_resume(struct device *dev) return ret; } -static SIMPLE_DEV_PM_OPS(rk8xx_pm_ops, rk8xx_suspend, rk8xx_resume); - -static struct i2c_driver rk808_i2c_driver = { - .driver = { - .name = "rk808", - .of_match_table = rk808_of_match, - .pm = &rk8xx_pm_ops, - }, - .probe_new = rk808_probe, - .remove = rk808_remove, - .shutdown = rk8xx_shutdown, -}; - -module_i2c_driver(rk808_i2c_driver); +EXPORT_SYMBOL_GPL(rk8xx_resume); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Chris Zhong "); MODULE_AUTHOR("Zhang Qing "); MODULE_AUTHOR("Wadim Egorov "); -MODULE_DESCRIPTION("RK808/RK818 PMIC driver"); +MODULE_DESCRIPTION("RK8xx PMIC core"); diff --git a/drivers/mfd/rk8xx-i2c.c b/drivers/mfd/rk8xx-i2c.c new file mode 100644 index 0000000000000000000000000000000000000000..1a98feea97e2c5bc8301623323852ca6ef5b71de --- /dev/null +++ b/drivers/mfd/rk8xx-i2c.c @@ -0,0 +1,185 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Rockchip RK808/RK818 Core (I2C) driver + * + * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd + * Copyright (C) 2016 PHYTEC Messtechnik GmbH + * + * Author: Chris Zhong + * Author: Zhang Qing + * Author: Wadim Egorov + */ + +#include +#include +#include +#include +#include + +struct rk8xx_i2c_platform_data { + const struct regmap_config *regmap_cfg; + int variant; +}; + +static bool rk808_is_volatile_reg(struct device *dev, unsigned int reg) +{ + /* + * Notes: + * - Technically the ROUND_30s bit makes RTC_CTRL_REG volatile, but + * we don't use that feature. It's better to cache. + * - It's unlikely we care that RK808_DEVCTRL_REG is volatile since + * bits are cleared in case when we shutoff anyway, but better safe. + */ + + switch (reg) { + case RK808_SECONDS_REG ... RK808_WEEKS_REG: + case RK808_RTC_STATUS_REG: + case RK808_VB_MON_REG: + case RK808_THERMAL_REG: + case RK808_DCDC_UV_STS_REG: + case RK808_LDO_UV_STS_REG: + case RK808_DCDC_PG_REG: + case RK808_LDO_PG_REG: + case RK808_DEVCTRL_REG: + case RK808_INT_STS_REG1: + case RK808_INT_STS_REG2: + return true; + } + + return false; +} + +static bool rk817_is_volatile_reg(struct device *dev, unsigned int reg) +{ + /* + * Notes: + * - Technically the ROUND_30s bit makes RTC_CTRL_REG volatile, but + * we don't use that feature. It's better to cache. + */ + + switch (reg) { + case RK817_SECONDS_REG ... RK817_WEEKS_REG: + case RK817_RTC_STATUS_REG: + case RK817_CODEC_DTOP_LPT_SRST: + case RK817_GAS_GAUGE_ADC_CONFIG0 ... RK817_GAS_GAUGE_CUR_ADC_K0: + case RK817_PMIC_CHRG_STS: + case RK817_PMIC_CHRG_OUT: + case RK817_PMIC_CHRG_IN: + case RK817_INT_STS_REG0: + case RK817_INT_STS_REG1: + case RK817_INT_STS_REG2: + case RK817_SYS_STS: + return true; + } + + return false; +} + + +static const struct regmap_config rk818_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = RK818_USB_CTRL_REG, + .cache_type = REGCACHE_RBTREE, + .volatile_reg = rk808_is_volatile_reg, +}; + +static const struct regmap_config rk805_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = RK805_OFF_SOURCE_REG, + .cache_type = REGCACHE_RBTREE, + .volatile_reg = rk808_is_volatile_reg, +}; + +static const struct regmap_config rk808_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = RK808_IO_POL_REG, + .cache_type = REGCACHE_RBTREE, + .volatile_reg = rk808_is_volatile_reg, +}; + +static const struct regmap_config rk817_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = RK817_GPIO_INT_CFG, + .cache_type = REGCACHE_NONE, + .volatile_reg = rk817_is_volatile_reg, +}; + +static const struct rk8xx_i2c_platform_data rk805_data = { + .regmap_cfg = &rk805_regmap_config, + .variant = RK805_ID, +}; + +static const struct rk8xx_i2c_platform_data rk808_data = { + .regmap_cfg = &rk808_regmap_config, + .variant = RK808_ID, +}; + +static const struct rk8xx_i2c_platform_data rk809_data = { + .regmap_cfg = &rk817_regmap_config, + .variant = RK809_ID, +}; + +static const struct rk8xx_i2c_platform_data rk817_data = { + .regmap_cfg = &rk817_regmap_config, + .variant = RK817_ID, +}; + +static const struct rk8xx_i2c_platform_data rk818_data = { + .regmap_cfg = &rk818_regmap_config, + .variant = RK818_ID, +}; + +static int rk8xx_i2c_probe(struct i2c_client *client) +{ + const struct rk8xx_i2c_platform_data *data; + struct regmap *regmap; + + data = device_get_match_data(&client->dev); + if (!data) + return -ENODEV; + + regmap = devm_regmap_init_i2c(client, data->regmap_cfg); + if (IS_ERR(regmap)) + return dev_err_probe(&client->dev, PTR_ERR(regmap), + "regmap initialization failed\n"); + + return rk8xx_probe(&client->dev, data->variant, client->irq, regmap); +} + +static void rk8xx_i2c_shutdown(struct i2c_client *client) +{ + rk8xx_shutdown(&client->dev); +} + +static SIMPLE_DEV_PM_OPS(rk8xx_i2c_pm_ops, rk8xx_suspend, rk8xx_resume); + +static const struct of_device_id rk8xx_i2c_of_match[] = { + { .compatible = "rockchip,rk805", .data = &rk805_data }, + { .compatible = "rockchip,rk808", .data = &rk808_data }, + { .compatible = "rockchip,rk809", .data = &rk809_data }, + { .compatible = "rockchip,rk817", .data = &rk817_data }, + { .compatible = "rockchip,rk818", .data = &rk818_data }, + { }, +}; +MODULE_DEVICE_TABLE(of, rk8xx_i2c_of_match); + +static struct i2c_driver rk8xx_i2c_driver = { + .driver = { + .name = "rk8xx-i2c", + .of_match_table = rk8xx_i2c_of_match, + .pm = &rk8xx_i2c_pm_ops, + }, + .probe = rk8xx_i2c_probe, + .shutdown = rk8xx_i2c_shutdown, +}; +module_i2c_driver(rk8xx_i2c_driver); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Chris Zhong "); +MODULE_AUTHOR("Zhang Qing "); +MODULE_AUTHOR("Wadim Egorov "); +MODULE_DESCRIPTION("RK8xx I2C PMIC driver"); diff --git a/drivers/mfd/rk8xx-spi.c b/drivers/mfd/rk8xx-spi.c new file mode 100644 index 0000000000000000000000000000000000000000..fd137f38c2c4a74a6693a54859f74d01a0e2ddee --- /dev/null +++ b/drivers/mfd/rk8xx-spi.c @@ -0,0 +1,124 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Rockchip RK806 Core (SPI) driver + * + * Copyright (c) 2021 Rockchip Electronics Co., Ltd. + * Copyright (c) 2023 Collabora Ltd. + * + * Author: Xu Shengfei + * Author: Sebastian Reichel + */ + +#include +#include +#include +#include +#include +#include + +#define RK806_ADDR_SIZE 2 +#define RK806_CMD_WITH_SIZE(CMD, VALUE_BYTES) \ + (RK806_CMD_##CMD | RK806_CMD_CRC_DIS | (VALUE_BYTES - 1)) + +static const struct regmap_range rk806_volatile_ranges[] = { + regmap_reg_range(RK806_POWER_EN0, RK806_POWER_EN5), + regmap_reg_range(RK806_DVS_START_CTRL, RK806_INT_MSK1), +}; + +static const struct regmap_access_table rk806_volatile_table = { + .yes_ranges = rk806_volatile_ranges, + .n_yes_ranges = ARRAY_SIZE(rk806_volatile_ranges), +}; + +static const struct regmap_config rk806_regmap_config_spi = { + .reg_bits = 16, + .val_bits = 8, + .max_register = RK806_BUCK_RSERVE_REG5, + .cache_type = REGCACHE_RBTREE, + .volatile_table = &rk806_volatile_table, +}; + +static int rk806_spi_bus_write(void *context, const void *vdata, size_t count) +{ + struct device *dev = context; + struct spi_device *spi = to_spi_device(dev); + struct spi_transfer xfer[2] = { 0 }; + /* data and thus count includes the register address */ + size_t val_size = count - RK806_ADDR_SIZE; + char cmd; + + if (val_size < 1 || val_size > (RK806_CMD_LEN_MSK + 1)) + return -EINVAL; + + cmd = RK806_CMD_WITH_SIZE(WRITE, val_size); + + xfer[0].tx_buf = &cmd; + xfer[0].len = sizeof(cmd); + xfer[1].tx_buf = vdata; + xfer[1].len = count; + + return spi_sync_transfer(spi, xfer, ARRAY_SIZE(xfer)); +} + +static int rk806_spi_bus_read(void *context, const void *vreg, size_t reg_size, + void *val, size_t val_size) +{ + struct device *dev = context; + struct spi_device *spi = to_spi_device(dev); + char txbuf[3] = { 0 }; + + if (reg_size != RK806_ADDR_SIZE || + val_size < 1 || val_size > (RK806_CMD_LEN_MSK + 1)) + return -EINVAL; + + /* TX buffer contains command byte followed by two address bytes */ + txbuf[0] = RK806_CMD_WITH_SIZE(READ, val_size); + memcpy(txbuf+1, vreg, reg_size); + + return spi_write_then_read(spi, txbuf, sizeof(txbuf), val, val_size); +} + +static const struct regmap_bus rk806_regmap_bus_spi = { + .write = rk806_spi_bus_write, + .read = rk806_spi_bus_read, + .reg_format_endian_default = REGMAP_ENDIAN_LITTLE, +}; + +static int rk8xx_spi_probe(struct spi_device *spi) +{ + struct regmap *regmap; + + regmap = devm_regmap_init(&spi->dev, &rk806_regmap_bus_spi, + &spi->dev, &rk806_regmap_config_spi); + if (IS_ERR(regmap)) + return dev_err_probe(&spi->dev, PTR_ERR(regmap), + "Failed to init regmap\n"); + + return rk8xx_probe(&spi->dev, RK806_ID, spi->irq, regmap); +} + +static const struct of_device_id rk8xx_spi_of_match[] = { + { .compatible = "rockchip,rk806", }, + { } +}; +MODULE_DEVICE_TABLE(of, rk8xx_spi_of_match); + +static const struct spi_device_id rk8xx_spi_id_table[] = { + { "rk806", 0 }, + { } +}; +MODULE_DEVICE_TABLE(spi, rk8xx_spi_id_table); + +static struct spi_driver rk8xx_spi_driver = { + .driver = { + .name = "rk8xx-spi", + .of_match_table = rk8xx_spi_of_match, + }, + .probe = rk8xx_spi_probe, + .id_table = rk8xx_spi_id_table, +}; +module_spi_driver(rk8xx_spi_driver); + +MODULE_AUTHOR("Xu Shengfei "); +MODULE_DESCRIPTION("RK8xx SPI PMIC driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/mfd/rn5t618.c b/drivers/mfd/rn5t618.c index 2f59230749cd944534ef466c64cd5efd9ae72f7a..333fef8729a54468d2f62ccd1af3a4eefd058fff 100644 --- a/drivers/mfd/rn5t618.c +++ b/drivers/mfd/rn5t618.c @@ -280,7 +280,7 @@ static struct i2c_driver rn5t618_i2c_driver = { .of_match_table = of_match_ptr(rn5t618_of_match), .pm = &rn5t618_i2c_dev_pm_ops, }, - .probe_new = rn5t618_i2c_probe, + .probe = rn5t618_i2c_probe, .remove = rn5t618_i2c_remove, }; diff --git a/drivers/mfd/rohm-bd71828.c b/drivers/mfd/rohm-bd71828.c index 7eb920633ee964991f163013748b0cb25eb84b7b..93d80a79b90112e9316e0354ca0f137e3ffce8f0 100644 --- a/drivers/mfd/rohm-bd71828.c +++ b/drivers/mfd/rohm-bd71828.c @@ -564,7 +564,7 @@ static struct i2c_driver bd71828_drv = { .name = "rohm-bd71828", .of_match_table = bd71828_of_match, }, - .probe_new = &bd71828_i2c_probe, + .probe = bd71828_i2c_probe, }; module_i2c_driver(bd71828_drv); diff --git a/drivers/mfd/rohm-bd718x7.c b/drivers/mfd/rohm-bd718x7.c index 378eb1a692e419e4ecbeb5ed3e5acf1f0a9933f4..0b58ecc7833405e75a3ad1a2929c5118053558c9 100644 --- a/drivers/mfd/rohm-bd718x7.c +++ b/drivers/mfd/rohm-bd718x7.c @@ -208,7 +208,7 @@ static struct i2c_driver bd718xx_i2c_driver = { .name = "rohm-bd718x7", .of_match_table = bd718xx_of_match, }, - .probe_new = bd718xx_i2c_probe, + .probe = bd718xx_i2c_probe, }; static int __init bd718xx_i2c_init(void) diff --git a/drivers/mfd/rohm-bd9576.c b/drivers/mfd/rohm-bd9576.c index 6491e385d980c4d5d6a56d46bfe6067216ff0772..645673322ec0e62c4ec9cfef0bd31baed7d2827a 100644 --- a/drivers/mfd/rohm-bd9576.c +++ b/drivers/mfd/rohm-bd9576.c @@ -178,7 +178,7 @@ static struct i2c_driver bd957x_drv = { .name = "rohm-bd957x", .of_match_table = bd957x_of_match, }, - .probe_new = &bd957x_i2c_probe, + .probe = bd957x_i2c_probe, }; module_i2c_driver(bd957x_drv); diff --git a/drivers/mfd/rsmu_i2c.c b/drivers/mfd/rsmu_i2c.c index 807c321014607196c7093c31ad18f8e2c45c1e8b..26972a5aff4543bcb77b59a981605990864236b0 100644 --- a/drivers/mfd/rsmu_i2c.c +++ b/drivers/mfd/rsmu_i2c.c @@ -279,7 +279,7 @@ static struct i2c_driver rsmu_i2c_driver = { .name = "rsmu-i2c", .of_match_table = of_match_ptr(rsmu_i2c_of_match), }, - .probe_new = rsmu_i2c_probe, + .probe = rsmu_i2c_probe, .remove = rsmu_i2c_remove, .id_table = rsmu_i2c_id, }; diff --git a/drivers/mfd/rt4831.c b/drivers/mfd/rt4831.c index c6d34dc2b5206d9e2235ea04b1877cc6291dbc6e..f8d6dc55b5588317be37b2b09509e02ceb9c7434 100644 --- a/drivers/mfd/rt4831.c +++ b/drivers/mfd/rt4831.c @@ -109,7 +109,7 @@ static struct i2c_driver rt4831_driver = { .name = "rt4831", .of_match_table = rt4831_of_match, }, - .probe_new = rt4831_probe, + .probe = rt4831_probe, .remove = rt4831_remove, }; module_i2c_driver(rt4831_driver); diff --git a/drivers/mfd/rt5033.c b/drivers/mfd/rt5033.c index a5e520fe50a143d0e55a1d8d4aa46af48922d199..67b0a228db249b4728a87f045b2ea0560cc99789 100644 --- a/drivers/mfd/rt5033.c +++ b/drivers/mfd/rt5033.c @@ -40,9 +40,6 @@ static const struct mfd_cell rt5033_devs[] = { { .name = "rt5033-charger", .of_compatible = "richtek,rt5033-charger", - }, { - .name = "rt5033-battery", - .of_compatible = "richtek,rt5033-battery", }, { .name = "rt5033-led", .of_compatible = "richtek,rt5033-led", @@ -58,7 +55,7 @@ static const struct regmap_config rt5033_regmap_config = { static int rt5033_i2c_probe(struct i2c_client *i2c) { struct rt5033_dev *rt5033; - unsigned int dev_id; + unsigned int dev_id, chip_rev; int ret; rt5033 = devm_kzalloc(&i2c->dev, sizeof(*rt5033), GFP_KERNEL); @@ -81,7 +78,8 @@ static int rt5033_i2c_probe(struct i2c_client *i2c) dev_err(&i2c->dev, "Device not found\n"); return -ENODEV; } - dev_info(&i2c->dev, "Device found Device ID: %04x\n", dev_id); + chip_rev = dev_id & RT5033_CHIP_REV_MASK; + dev_info(&i2c->dev, "Device found (rev. %d)\n", chip_rev); ret = regmap_add_irq_chip(rt5033->regmap, rt5033->irq, IRQF_TRIGGER_FALLING | IRQF_ONESHOT, @@ -122,7 +120,7 @@ static struct i2c_driver rt5033_driver = { .name = "rt5033", .of_match_table = rt5033_dt_match, }, - .probe_new = rt5033_i2c_probe, + .probe = rt5033_i2c_probe, .id_table = rt5033_i2c_id, }; module_i2c_driver(rt5033_driver); diff --git a/drivers/mfd/rt5120.c b/drivers/mfd/rt5120.c index 829b7a0a0781c3ef89df475abd97a13625a39f35..58d9a124d79548790c72ae0accb460950dc88dba 100644 --- a/drivers/mfd/rt5120.c +++ b/drivers/mfd/rt5120.c @@ -114,7 +114,7 @@ static struct i2c_driver rt5120_driver = { .name = "rt5120", .of_match_table = rt5120_device_match_table, }, - .probe_new = rt5120_probe, + .probe = rt5120_probe, }; module_i2c_driver(rt5120_driver); diff --git a/drivers/mfd/sec-core.c b/drivers/mfd/sec-core.c index c2d0ed4969596069d847d5684e3c12d3c558f247..d2f631901886915bddf3496a80a25633b71d684a 100644 --- a/drivers/mfd/sec-core.c +++ b/drivers/mfd/sec-core.c @@ -450,7 +450,7 @@ static struct i2c_driver sec_pmic_driver = { .pm = pm_sleep_ptr(&sec_pmic_pm_ops), .of_match_table = sec_dt_match, }, - .probe_new = sec_pmic_probe, + .probe = sec_pmic_probe, .shutdown = sec_pmic_shutdown, }; module_i2c_driver(sec_pmic_driver); diff --git a/drivers/mfd/si476x-i2c.c b/drivers/mfd/si476x-i2c.c index 22131cf85e3f9a5ad4744d47b524715bcd87eae4..899c0b5ea3aabb87246a0b387929db58d7b70d7b 100644 --- a/drivers/mfd/si476x-i2c.c +++ b/drivers/mfd/si476x-i2c.c @@ -866,7 +866,7 @@ static struct i2c_driver si476x_core_driver = { .driver = { .name = "si476x-core", }, - .probe_new = si476x_core_probe, + .probe = si476x_core_probe, .remove = si476x_core_remove, .id_table = si476x_id, }; diff --git a/drivers/mfd/simple-mfd-i2c.c b/drivers/mfd/simple-mfd-i2c.c index 20782b4dd17240c2a569c78dae912ff3ede26bde..6eda79533208a349e9f49ddcb0f2f8fedb1d8b79 100644 --- a/drivers/mfd/simple-mfd-i2c.c +++ b/drivers/mfd/simple-mfd-i2c.c @@ -72,28 +72,28 @@ static const struct simple_mfd_data silergy_sy7636a = { .mfd_cell_size = ARRAY_SIZE(sy7636a_cells), }; -static const struct mfd_cell max597x_cells[] = { - { .name = "max597x-regulator", }, - { .name = "max597x-iio", }, - { .name = "max597x-led", }, +static const struct mfd_cell max5970_cells[] = { + { .name = "max5970-regulator", }, + { .name = "max5970-iio", }, + { .name = "max5970-led", }, }; -static const struct simple_mfd_data maxim_max597x = { - .mfd_cell = max597x_cells, - .mfd_cell_size = ARRAY_SIZE(max597x_cells), +static const struct simple_mfd_data maxim_max5970 = { + .mfd_cell = max5970_cells, + .mfd_cell_size = ARRAY_SIZE(max5970_cells), }; static const struct of_device_id simple_mfd_i2c_of_match[] = { { .compatible = "kontron,sl28cpld" }, { .compatible = "silergy,sy7636a", .data = &silergy_sy7636a}, - { .compatible = "maxim,max5970", .data = &maxim_max597x}, - { .compatible = "maxim,max5978", .data = &maxim_max597x}, + { .compatible = "maxim,max5970", .data = &maxim_max5970}, + { .compatible = "maxim,max5978", .data = &maxim_max5970}, {} }; MODULE_DEVICE_TABLE(of, simple_mfd_i2c_of_match); static struct i2c_driver simple_mfd_i2c_driver = { - .probe_new = simple_mfd_i2c_probe, + .probe = simple_mfd_i2c_probe, .driver = { .name = "simple-mfd-i2c", .of_match_table = simple_mfd_i2c_of_match, diff --git a/drivers/mfd/sky81452.c b/drivers/mfd/sky81452.c index 2515ecae1d3fe9620223c240a6a8ee64a95860ca..771b62a5c70f4a27afb729d35f9e9c086db46557 100644 --- a/drivers/mfd/sky81452.c +++ b/drivers/mfd/sky81452.c @@ -77,7 +77,7 @@ static struct i2c_driver sky81452_driver = { .name = "sky81452", .of_match_table = of_match_ptr(sky81452_of_match), }, - .probe_new = sky81452_probe, + .probe = sky81452_probe, .id_table = sky81452_ids, }; diff --git a/drivers/mfd/smpro-core.c b/drivers/mfd/smpro-core.c index d7729cf70378217f703ab1e86125bc80d03f48fb..59d31590c69b741540e84935c28864e6ce405b03 100644 --- a/drivers/mfd/smpro-core.c +++ b/drivers/mfd/smpro-core.c @@ -125,7 +125,7 @@ static const struct of_device_id smpro_core_of_match[] = { MODULE_DEVICE_TABLE(of, smpro_core_of_match); static struct i2c_driver smpro_core_driver = { - .probe_new = smpro_core_probe, + .probe = smpro_core_probe, .driver = { .name = "smpro-core", .of_match_table = smpro_core_of_match, diff --git a/drivers/mfd/stmfx.c b/drivers/mfd/stmfx.c index e281971ba54ed6e9b0bbe5659467a9da19db3ca0..c02cbd9c2f5d798b01dc56e382a278bdc770506f 100644 --- a/drivers/mfd/stmfx.c +++ b/drivers/mfd/stmfx.c @@ -330,9 +330,8 @@ static int stmfx_chip_init(struct i2c_client *client) stmfx->vdd = devm_regulator_get_optional(&client->dev, "vdd"); ret = PTR_ERR_OR_ZERO(stmfx->vdd); if (ret) { - if (ret == -ENODEV) - stmfx->vdd = NULL; - else + stmfx->vdd = NULL; + if (ret != -ENODEV) return dev_err_probe(&client->dev, ret, "Failed to get VDD regulator\n"); } @@ -387,7 +386,7 @@ static int stmfx_chip_init(struct i2c_client *client) err: if (stmfx->vdd) - return regulator_disable(stmfx->vdd); + regulator_disable(stmfx->vdd); return ret; } @@ -553,7 +552,7 @@ static struct i2c_driver stmfx_driver = { .of_match_table = stmfx_of_match, .pm = pm_sleep_ptr(&stmfx_dev_pm_ops), }, - .probe_new = stmfx_probe, + .probe = stmfx_probe, .remove = stmfx_remove, }; module_i2c_driver(stmfx_driver); diff --git a/drivers/mfd/stmpe-i2c.c b/drivers/mfd/stmpe-i2c.c index 7998e0db1e158bf9ca353bdf588831f2f3378c6f..1d7b401776d1c314d82f953036ee0a0a56b93094 100644 --- a/drivers/mfd/stmpe-i2c.c +++ b/drivers/mfd/stmpe-i2c.c @@ -118,7 +118,7 @@ static struct i2c_driver stmpe_i2c_driver = { .pm = pm_sleep_ptr(&stmpe_dev_pm_ops), .of_match_table = stmpe_of_match, }, - .probe_new = stmpe_i2c_probe, + .probe = stmpe_i2c_probe, .remove = stmpe_i2c_remove, .id_table = stmpe_i2c_id, }; diff --git a/drivers/mfd/stmpe.c b/drivers/mfd/stmpe.c index a92301dfc71268805eb040de20a1930430b1c2b7..9c3cf58457a7db69fc479cdb7e19192f762de81e 100644 --- a/drivers/mfd/stmpe.c +++ b/drivers/mfd/stmpe.c @@ -1485,9 +1485,9 @@ int stmpe_probe(struct stmpe_client_info *ci, enum stmpe_partnum partnum) void stmpe_remove(struct stmpe *stmpe) { - if (!IS_ERR(stmpe->vio)) + if (!IS_ERR(stmpe->vio) && regulator_is_enabled(stmpe->vio)) regulator_disable(stmpe->vio); - if (!IS_ERR(stmpe->vcc)) + if (!IS_ERR(stmpe->vcc) && regulator_is_enabled(stmpe->vcc)) regulator_disable(stmpe->vcc); __stmpe_disable(stmpe, STMPE_BLOCK_ADC); diff --git a/drivers/mfd/stpmic1.c b/drivers/mfd/stpmic1.c index 8db1530d9bacb80d498022d6e015203fbd943a3d..3cc7492f828ff9646b97d2d885978c0d371bcb7c 100644 --- a/drivers/mfd/stpmic1.c +++ b/drivers/mfd/stpmic1.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -19,7 +20,7 @@ static const struct regmap_range stpmic1_readable_ranges[] = { regmap_reg_range(TURN_ON_SR, VERSION_SR), - regmap_reg_range(SWOFF_PWRCTRL_CR, LDO6_STDBY_CR), + regmap_reg_range(MAIN_CR, LDO6_STDBY_CR), regmap_reg_range(BST_SW_CR, BST_SW_CR), regmap_reg_range(INT_PENDING_R1, INT_PENDING_R4), regmap_reg_range(INT_CLEAR_R1, INT_CLEAR_R4), @@ -30,7 +31,7 @@ static const struct regmap_range stpmic1_readable_ranges[] = { }; static const struct regmap_range stpmic1_writeable_ranges[] = { - regmap_reg_range(SWOFF_PWRCTRL_CR, LDO6_STDBY_CR), + regmap_reg_range(MAIN_CR, LDO6_STDBY_CR), regmap_reg_range(BST_SW_CR, BST_SW_CR), regmap_reg_range(INT_CLEAR_R1, INT_CLEAR_R4), regmap_reg_range(INT_SET_MASK_R1, INT_SET_MASK_R4), @@ -117,6 +118,16 @@ static const struct regmap_irq_chip stpmic1_regmap_irq_chip = { .num_irqs = ARRAY_SIZE(stpmic1_irqs), }; +static int stpmic1_power_off(struct sys_off_data *data) +{ + struct stpmic1 *ddata = data->cb_data; + + regmap_update_bits(ddata->regmap, MAIN_CR, + SOFTWARE_SWITCH_OFF, SOFTWARE_SWITCH_OFF); + + return NOTIFY_DONE; +} + static int stpmic1_probe(struct i2c_client *i2c) { struct stpmic1 *ddata; @@ -159,6 +170,16 @@ static int stpmic1_probe(struct i2c_client *i2c) return ret; } + ret = devm_register_sys_off_handler(ddata->dev, + SYS_OFF_MODE_POWER_OFF, + SYS_OFF_PRIO_DEFAULT, + stpmic1_power_off, + ddata); + if (ret) { + dev_err(ddata->dev, "failed to register sys-off handler: %d\n", ret); + return ret; + } + return devm_of_platform_populate(dev); } @@ -201,7 +222,7 @@ static struct i2c_driver stpmic1_driver = { .of_match_table = of_match_ptr(stpmic1_of_match), .pm = pm_sleep_ptr(&stpmic1_pm), }, - .probe_new = stpmic1_probe, + .probe = stpmic1_probe, }; module_i2c_driver(stpmic1_driver); diff --git a/drivers/mfd/stw481x.c b/drivers/mfd/stw481x.c index 2a8fc9d1c80635f695cb9f0153189af3c1876f37..f35c3af680ddc1a6b605d9e90e2ff3e5bafca17e 100644 --- a/drivers/mfd/stw481x.c +++ b/drivers/mfd/stw481x.c @@ -239,7 +239,7 @@ static struct i2c_driver stw481x_driver = { .name = "stw481x", .of_match_table = stw481x_match, }, - .probe_new = stw481x_probe, + .probe = stw481x_probe, .id_table = stw481x_id, }; diff --git a/drivers/mfd/tc3589x.c b/drivers/mfd/tc3589x.c index cbfe19d1b1459d61f91d043587303192668c113e..16df64e3c0bec0d82818c82d2d41647b4dc1852d 100644 --- a/drivers/mfd/tc3589x.c +++ b/drivers/mfd/tc3589x.c @@ -485,7 +485,7 @@ static struct i2c_driver tc3589x_driver = { .pm = pm_sleep_ptr(&tc3589x_dev_pm_ops), .of_match_table = of_match_ptr(tc3589x_match), }, - .probe_new = tc3589x_probe, + .probe = tc3589x_probe, .remove = tc3589x_remove, .id_table = tc3589x_id, }; diff --git a/drivers/mfd/ti-lmu.c b/drivers/mfd/ti-lmu.c index 9921320be2557ad3beb877617cfeb881937d995b..4f06adad7b5ef5b8001684a3b9ea2835a0660114 100644 --- a/drivers/mfd/ti-lmu.c +++ b/drivers/mfd/ti-lmu.c @@ -217,7 +217,7 @@ static const struct i2c_device_id ti_lmu_ids[] = { MODULE_DEVICE_TABLE(i2c, ti_lmu_ids); static struct i2c_driver ti_lmu_driver = { - .probe_new = ti_lmu_probe, + .probe = ti_lmu_probe, .driver = { .name = "ti-lmu", .of_match_table = ti_lmu_of_match, diff --git a/drivers/mfd/tps6105x.c b/drivers/mfd/tps6105x.c index a66cb911998d7bed4b6e4b137b22d05b61180d95..5601f6d0d874c8f4c7eec52b21a1ca5555f4add3 100644 --- a/drivers/mfd/tps6105x.c +++ b/drivers/mfd/tps6105x.c @@ -209,7 +209,7 @@ static struct i2c_driver tps6105x_driver = { .name = "tps6105x", .of_match_table = tps6105x_of_match, }, - .probe_new = tps6105x_probe, + .probe = tps6105x_probe, .remove = tps6105x_remove, .id_table = tps6105x_id, }; diff --git a/drivers/mfd/tps65010.c b/drivers/mfd/tps65010.c index fb733288cca3b2502ec59d825f5dfbb04132b77e..2b9105295f3012fd281f86b920f945e72adbe2e4 100644 --- a/drivers/mfd/tps65010.c +++ b/drivers/mfd/tps65010.c @@ -506,12 +506,8 @@ static void tps65010_remove(struct i2c_client *client) struct tps65010 *tps = i2c_get_clientdata(client); struct tps65010_board *board = dev_get_platdata(&client->dev); - if (board && board->teardown) { - int status = board->teardown(client, board->context); - if (status < 0) - dev_dbg(&client->dev, "board %s %s err %d\n", - "teardown", client->name, status); - } + if (board && board->teardown) + board->teardown(client, &tps->chip); if (client->irq > 0) free_irq(client->irq, tps); cancel_delayed_work_sync(&tps->work); @@ -619,7 +615,7 @@ static int tps65010_probe(struct i2c_client *client) tps, DEBUG_FOPS); /* optionally register GPIOs */ - if (board && board->base != 0) { + if (board) { tps->outmask = board->outmask; tps->chip.label = client->name; @@ -632,7 +628,7 @@ static int tps65010_probe(struct i2c_client *client) /* NOTE: only partial support for inputs; nyet IRQs */ tps->chip.get = tps65010_gpio_get; - tps->chip.base = board->base; + tps->chip.base = -1; tps->chip.ngpio = 7; tps->chip.can_sleep = 1; @@ -641,7 +637,7 @@ static int tps65010_probe(struct i2c_client *client) dev_err(&client->dev, "can't add gpiochip, err %d\n", status); else if (board->setup) { - status = board->setup(client, board->context); + status = board->setup(client, &tps->chip); if (status < 0) { dev_dbg(&client->dev, "board %s %s err %d\n", @@ -668,7 +664,7 @@ static struct i2c_driver tps65010_driver = { .driver = { .name = "tps65010", }, - .probe_new = tps65010_probe, + .probe = tps65010_probe, .remove = tps65010_remove, .id_table = tps65010_id, }; diff --git a/drivers/mfd/tps6507x.c b/drivers/mfd/tps6507x.c index 500b594de31656db8935b2e4b377b4bf18ee4256..9716bf703c7aaaeaa53a0b133f423695b118718d 100644 --- a/drivers/mfd/tps6507x.c +++ b/drivers/mfd/tps6507x.c @@ -122,7 +122,7 @@ static struct i2c_driver tps6507x_i2c_driver = { .name = "tps6507x", .of_match_table = of_match_ptr(tps6507x_of_match), }, - .probe_new = tps6507x_i2c_probe, + .probe = tps6507x_i2c_probe, .id_table = tps6507x_i2c_id, }; diff --git a/drivers/mfd/tps65086.c b/drivers/mfd/tps65086.c index 9494c1d71b866c8316f4d4ffc6e6903ba22ead9a..6a21000aad4ace747c543316ffe8cf466c0f90ed 100644 --- a/drivers/mfd/tps65086.c +++ b/drivers/mfd/tps65086.c @@ -129,7 +129,7 @@ static struct i2c_driver tps65086_driver = { .name = "tps65086", .of_match_table = tps65086_of_match_table, }, - .probe_new = tps65086_probe, + .probe = tps65086_probe, .remove = tps65086_remove, .id_table = tps65086_id_table, }; diff --git a/drivers/mfd/tps65090.c b/drivers/mfd/tps65090.c index af718a9c58b333c7c4948086b989925871bc6ece..a35ad70755fb648f01c2485b16be2aee37decda7 100644 --- a/drivers/mfd/tps65090.c +++ b/drivers/mfd/tps65090.c @@ -236,7 +236,7 @@ static struct i2c_driver tps65090_driver = { .suppress_bind_attrs = true, .of_match_table = of_match_ptr(tps65090_of_match), }, - .probe_new = tps65090_i2c_probe, + .probe = tps65090_i2c_probe, .id_table = tps65090_id_table, }; diff --git a/drivers/mfd/tps65217.c b/drivers/mfd/tps65217.c index eebd60601b01ddc4b00f861e98813c9686998d2d..60599291b3154b0ae4abcc84a07224e07c73e033 100644 --- a/drivers/mfd/tps65217.c +++ b/drivers/mfd/tps65217.c @@ -402,7 +402,7 @@ static struct i2c_driver tps65217_driver = { .of_match_table = tps65217_of_match, }, .id_table = tps65217_id_table, - .probe_new = tps65217_probe, + .probe = tps65217_probe, .remove = tps65217_remove, }; diff --git a/drivers/mfd/tps65218.c b/drivers/mfd/tps65218.c index ea69dcef91ecc532e99f6cb31e56659a4d803731..619bf7adb20cad532c172bfad3915629054b5ef0 100644 --- a/drivers/mfd/tps65218.c +++ b/drivers/mfd/tps65218.c @@ -347,7 +347,7 @@ static struct i2c_driver tps65218_driver = { .name = "tps65218", .of_match_table = of_tps65218_match_table, }, - .probe_new = tps65218_probe, + .probe = tps65218_probe, .id_table = tps65218_id_table, }; diff --git a/drivers/mfd/tps65219.c b/drivers/mfd/tps65219.c index 0e402fda206bd2a5b6204d8389a54104fd9d04ef..0e0c42e4fdfc755fbf484dc8c9bdf31def01fab0 100644 --- a/drivers/mfd/tps65219.c +++ b/drivers/mfd/tps65219.c @@ -25,13 +25,21 @@ static int tps65219_cold_reset(struct tps65219 *tps) TPS65219_MFP_COLD_RESET_I2C_CTRL_MASK); } -static int tps65219_restart(struct notifier_block *this, - unsigned long reboot_mode, void *cmd) +static int tps65219_soft_shutdown(struct tps65219 *tps) { - struct tps65219 *tps; + return regmap_update_bits(tps->regmap, TPS65219_REG_MFP_CTRL, + TPS65219_MFP_I2C_OFF_REQ_MASK, + TPS65219_MFP_I2C_OFF_REQ_MASK); +} - tps = container_of(this, struct tps65219, nb); +static int tps65219_power_off_handler(struct sys_off_data *data) +{ + tps65219_soft_shutdown(data->cb_data); + return NOTIFY_DONE; +} +static int tps65219_restart(struct tps65219 *tps, unsigned long reboot_mode) +{ if (reboot_mode == REBOOT_WARM) tps65219_warm_reset(tps); else @@ -40,10 +48,11 @@ static int tps65219_restart(struct notifier_block *this, return NOTIFY_DONE; } -static struct notifier_block pmic_rst_restart_nb = { - .notifier_call = tps65219_restart, - .priority = 200, -}; +static int tps65219_restart_handler(struct sys_off_data *data) +{ + tps65219_restart(data->cb_data, data->mode); + return NOTIFY_DONE; +} static const struct resource tps65219_pwrbutton_resources[] = { DEFINE_RES_IRQ_NAMED(TPS65219_INT_PB_FALLING_EDGE_DETECT, "falling"), @@ -106,7 +115,7 @@ static const struct mfd_cell tps65219_cells[] = { .resources = tps65219_regulator_resources, .num_resources = ARRAY_SIZE(tps65219_regulator_resources), }, - { .name = "tps65219-gpios", }, + { .name = "tps65219-gpio", }, }; static const struct mfd_cell tps65219_pwrbutton_cell = { @@ -269,13 +278,22 @@ static int tps65219_probe(struct i2c_client *client) } } - tps->nb = pmic_rst_restart_nb; - ret = register_restart_handler(&tps->nb); + ret = devm_register_restart_handler(tps->dev, + tps65219_restart_handler, + tps); + if (ret) { dev_err(tps->dev, "cannot register restart handler, %d\n", ret); return ret; } + ret = devm_register_power_off_handler(tps->dev, + tps65219_power_off_handler, + tps); + if (ret) { + dev_err(tps->dev, "failed to register power-off handler: %d\n", ret); + return ret; + } return 0; } @@ -290,7 +308,7 @@ static struct i2c_driver tps65219_driver = { .name = "tps65219", .of_match_table = of_tps65219_match_table, }, - .probe_new = tps65219_probe, + .probe = tps65219_probe, }; module_i2c_driver(tps65219_driver); diff --git a/drivers/mfd/tps6586x.c b/drivers/mfd/tps6586x.c index 90e23232b6b0e6e907eed51c42659372621c8c49..55675ceedcd3b315598d5db29a6abd2046228c85 100644 --- a/drivers/mfd/tps6586x.c +++ b/drivers/mfd/tps6586x.c @@ -619,7 +619,7 @@ static struct i2c_driver tps6586x_driver = { .of_match_table = of_match_ptr(tps6586x_of_match), .pm = &tps6586x_pm_ops, }, - .probe_new = tps6586x_i2c_probe, + .probe = tps6586x_i2c_probe, .remove = tps6586x_i2c_remove, .id_table = tps6586x_id_table, }; diff --git a/drivers/mfd/tps65910.c b/drivers/mfd/tps65910.c index 821c0277a2edc22af15f01c2099324ce0a29f040..41408df1712f08fdb43b812e6bd16e6fbad09d53 100644 --- a/drivers/mfd/tps65910.c +++ b/drivers/mfd/tps65910.c @@ -535,7 +535,7 @@ static struct i2c_driver tps65910_i2c_driver = { .name = "tps65910", .of_match_table = of_match_ptr(tps65910_of_match), }, - .probe_new = tps65910_i2c_probe, + .probe = tps65910_i2c_probe, .id_table = tps65910_i2c_id, }; diff --git a/drivers/mfd/tps65912-i2c.c b/drivers/mfd/tps65912-i2c.c index 1bf945966bf7abf4afe3d361d17da807c6ef4944..3c5ac781b6c16d68151ea6020bebd64b71601a1c 100644 --- a/drivers/mfd/tps65912-i2c.c +++ b/drivers/mfd/tps65912-i2c.c @@ -60,7 +60,7 @@ static struct i2c_driver tps65912_i2c_driver = { .name = "tps65912", .of_match_table = tps65912_i2c_of_match_table, }, - .probe_new = tps65912_i2c_probe, + .probe = tps65912_i2c_probe, .remove = tps65912_i2c_remove, .id_table = tps65912_i2c_id_table, }; diff --git a/drivers/mfd/tps6594-core.c b/drivers/mfd/tps6594-core.c new file mode 100644 index 0000000000000000000000000000000000000000..15f314833207c4e2c3dfac45ba911801d6bd7e33 --- /dev/null +++ b/drivers/mfd/tps6594-core.c @@ -0,0 +1,462 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Core functions for TI TPS6594/TPS6593/LP8764 PMICs + * + * Copyright (C) 2023 BayLibre Incorporated - https://www.baylibre.com/ + */ + +#include +#include +#include +#include +#include + +#include +#include + +#define TPS6594_CRC_SYNC_TIMEOUT_MS 150 + +/* Completion to synchronize CRC feature enabling on all PMICs */ +static DECLARE_COMPLETION(tps6594_crc_comp); + +static const struct resource tps6594_regulator_resources[] = { + DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_BUCK1_OV, TPS6594_IRQ_NAME_BUCK1_OV), + DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_BUCK1_UV, TPS6594_IRQ_NAME_BUCK1_UV), + DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_BUCK1_SC, TPS6594_IRQ_NAME_BUCK1_SC), + DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_BUCK1_ILIM, TPS6594_IRQ_NAME_BUCK1_ILIM), + DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_BUCK2_OV, TPS6594_IRQ_NAME_BUCK2_OV), + DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_BUCK2_UV, TPS6594_IRQ_NAME_BUCK2_UV), + DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_BUCK2_SC, TPS6594_IRQ_NAME_BUCK2_SC), + DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_BUCK2_ILIM, TPS6594_IRQ_NAME_BUCK2_ILIM), + DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_BUCK3_OV, TPS6594_IRQ_NAME_BUCK3_OV), + DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_BUCK3_UV, TPS6594_IRQ_NAME_BUCK3_UV), + DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_BUCK3_SC, TPS6594_IRQ_NAME_BUCK3_SC), + DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_BUCK3_ILIM, TPS6594_IRQ_NAME_BUCK3_ILIM), + DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_BUCK4_OV, TPS6594_IRQ_NAME_BUCK4_OV), + DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_BUCK4_UV, TPS6594_IRQ_NAME_BUCK4_UV), + DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_BUCK4_SC, TPS6594_IRQ_NAME_BUCK4_SC), + DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_BUCK4_ILIM, TPS6594_IRQ_NAME_BUCK4_ILIM), + DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_BUCK5_OV, TPS6594_IRQ_NAME_BUCK5_OV), + DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_BUCK5_UV, TPS6594_IRQ_NAME_BUCK5_UV), + DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_BUCK5_SC, TPS6594_IRQ_NAME_BUCK5_SC), + DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_BUCK5_ILIM, TPS6594_IRQ_NAME_BUCK5_ILIM), + DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_LDO1_OV, TPS6594_IRQ_NAME_LDO1_OV), + DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_LDO1_UV, TPS6594_IRQ_NAME_LDO1_UV), + DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_LDO1_SC, TPS6594_IRQ_NAME_LDO1_SC), + DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_LDO1_ILIM, TPS6594_IRQ_NAME_LDO1_ILIM), + DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_LDO2_OV, TPS6594_IRQ_NAME_LDO2_OV), + DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_LDO2_UV, TPS6594_IRQ_NAME_LDO2_UV), + DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_LDO2_SC, TPS6594_IRQ_NAME_LDO2_SC), + DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_LDO2_ILIM, TPS6594_IRQ_NAME_LDO2_ILIM), + DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_LDO3_OV, TPS6594_IRQ_NAME_LDO3_OV), + DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_LDO3_UV, TPS6594_IRQ_NAME_LDO3_UV), + DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_LDO3_SC, TPS6594_IRQ_NAME_LDO3_SC), + DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_LDO3_ILIM, TPS6594_IRQ_NAME_LDO3_ILIM), + DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_LDO4_OV, TPS6594_IRQ_NAME_LDO4_OV), + DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_LDO4_UV, TPS6594_IRQ_NAME_LDO4_UV), + DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_LDO4_SC, TPS6594_IRQ_NAME_LDO4_SC), + DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_LDO4_ILIM, TPS6594_IRQ_NAME_LDO4_ILIM), + DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_VCCA_OV, TPS6594_IRQ_NAME_VCCA_OV), + DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_VCCA_UV, TPS6594_IRQ_NAME_VCCA_UV), + DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_VMON1_OV, TPS6594_IRQ_NAME_VMON1_OV), + DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_VMON1_UV, TPS6594_IRQ_NAME_VMON1_UV), + DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_VMON1_RV, TPS6594_IRQ_NAME_VMON1_RV), + DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_VMON2_OV, TPS6594_IRQ_NAME_VMON2_OV), + DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_VMON2_UV, TPS6594_IRQ_NAME_VMON2_UV), + DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_VMON2_RV, TPS6594_IRQ_NAME_VMON2_RV), +}; + +static const struct resource tps6594_pinctrl_resources[] = { + DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_GPIO9, TPS6594_IRQ_NAME_GPIO9), + DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_GPIO10, TPS6594_IRQ_NAME_GPIO10), + DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_GPIO11, TPS6594_IRQ_NAME_GPIO11), + DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_GPIO1, TPS6594_IRQ_NAME_GPIO1), + DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_GPIO2, TPS6594_IRQ_NAME_GPIO2), + DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_GPIO3, TPS6594_IRQ_NAME_GPIO3), + DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_GPIO4, TPS6594_IRQ_NAME_GPIO4), + DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_GPIO5, TPS6594_IRQ_NAME_GPIO5), + DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_GPIO6, TPS6594_IRQ_NAME_GPIO6), + DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_GPIO7, TPS6594_IRQ_NAME_GPIO7), + DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_GPIO8, TPS6594_IRQ_NAME_GPIO8), +}; + +static const struct resource tps6594_pfsm_resources[] = { + DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_NPWRON_START, TPS6594_IRQ_NAME_NPWRON_START), + DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_ENABLE, TPS6594_IRQ_NAME_ENABLE), + DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_FSD, TPS6594_IRQ_NAME_FSD), + DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_SOFT_REBOOT, TPS6594_IRQ_NAME_SOFT_REBOOT), + DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_BIST_PASS, TPS6594_IRQ_NAME_BIST_PASS), + DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_EXT_CLK, TPS6594_IRQ_NAME_EXT_CLK), + DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_TWARN, TPS6594_IRQ_NAME_TWARN), + DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_TSD_ORD, TPS6594_IRQ_NAME_TSD_ORD), + DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_BIST_FAIL, TPS6594_IRQ_NAME_BIST_FAIL), + DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_REG_CRC_ERR, TPS6594_IRQ_NAME_REG_CRC_ERR), + DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_RECOV_CNT, TPS6594_IRQ_NAME_RECOV_CNT), + DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_SPMI_ERR, TPS6594_IRQ_NAME_SPMI_ERR), + DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_NPWRON_LONG, TPS6594_IRQ_NAME_NPWRON_LONG), + DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_NINT_READBACK, TPS6594_IRQ_NAME_NINT_READBACK), + DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_NRSTOUT_READBACK, TPS6594_IRQ_NAME_NRSTOUT_READBACK), + DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_TSD_IMM, TPS6594_IRQ_NAME_TSD_IMM), + DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_VCCA_OVP, TPS6594_IRQ_NAME_VCCA_OVP), + DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_PFSM_ERR, TPS6594_IRQ_NAME_PFSM_ERR), + DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_IMM_SHUTDOWN, TPS6594_IRQ_NAME_IMM_SHUTDOWN), + DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_ORD_SHUTDOWN, TPS6594_IRQ_NAME_ORD_SHUTDOWN), + DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_MCU_PWR_ERR, TPS6594_IRQ_NAME_MCU_PWR_ERR), + DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_SOC_PWR_ERR, TPS6594_IRQ_NAME_SOC_PWR_ERR), + DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_COMM_FRM_ERR, TPS6594_IRQ_NAME_COMM_FRM_ERR), + DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_COMM_CRC_ERR, TPS6594_IRQ_NAME_COMM_CRC_ERR), + DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_COMM_ADR_ERR, TPS6594_IRQ_NAME_COMM_ADR_ERR), + DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_EN_DRV_READBACK, TPS6594_IRQ_NAME_EN_DRV_READBACK), + DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_NRSTOUT_SOC_READBACK, + TPS6594_IRQ_NAME_NRSTOUT_SOC_READBACK), +}; + +static const struct resource tps6594_esm_resources[] = { + DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_ESM_SOC_PIN, TPS6594_IRQ_NAME_ESM_SOC_PIN), + DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_ESM_SOC_FAIL, TPS6594_IRQ_NAME_ESM_SOC_FAIL), + DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_ESM_SOC_RST, TPS6594_IRQ_NAME_ESM_SOC_RST), +}; + +static const struct resource tps6594_rtc_resources[] = { + DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_TIMER, TPS6594_IRQ_NAME_TIMER), + DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_ALARM, TPS6594_IRQ_NAME_ALARM), + DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_POWER_UP, TPS6594_IRQ_NAME_POWERUP), +}; + +static const struct mfd_cell tps6594_common_cells[] = { + MFD_CELL_RES("tps6594-regulator", tps6594_regulator_resources), + MFD_CELL_RES("tps6594-pinctrl", tps6594_pinctrl_resources), + MFD_CELL_RES("tps6594-pfsm", tps6594_pfsm_resources), + MFD_CELL_RES("tps6594-esm", tps6594_esm_resources), +}; + +static const struct mfd_cell tps6594_rtc_cells[] = { + MFD_CELL_RES("tps6594-rtc", tps6594_rtc_resources), +}; + +static const struct regmap_irq tps6594_irqs[] = { + /* INT_BUCK1_2 register */ + REGMAP_IRQ_REG(TPS6594_IRQ_BUCK1_OV, 0, TPS6594_BIT_BUCKX_OV_INT(0)), + REGMAP_IRQ_REG(TPS6594_IRQ_BUCK1_UV, 0, TPS6594_BIT_BUCKX_UV_INT(0)), + REGMAP_IRQ_REG(TPS6594_IRQ_BUCK1_SC, 0, TPS6594_BIT_BUCKX_SC_INT(0)), + REGMAP_IRQ_REG(TPS6594_IRQ_BUCK1_ILIM, 0, TPS6594_BIT_BUCKX_ILIM_INT(0)), + REGMAP_IRQ_REG(TPS6594_IRQ_BUCK2_OV, 0, TPS6594_BIT_BUCKX_OV_INT(1)), + REGMAP_IRQ_REG(TPS6594_IRQ_BUCK2_UV, 0, TPS6594_BIT_BUCKX_UV_INT(1)), + REGMAP_IRQ_REG(TPS6594_IRQ_BUCK2_SC, 0, TPS6594_BIT_BUCKX_SC_INT(1)), + REGMAP_IRQ_REG(TPS6594_IRQ_BUCK2_ILIM, 0, TPS6594_BIT_BUCKX_ILIM_INT(1)), + + /* INT_BUCK3_4 register */ + REGMAP_IRQ_REG(TPS6594_IRQ_BUCK3_OV, 1, TPS6594_BIT_BUCKX_OV_INT(2)), + REGMAP_IRQ_REG(TPS6594_IRQ_BUCK3_UV, 1, TPS6594_BIT_BUCKX_UV_INT(2)), + REGMAP_IRQ_REG(TPS6594_IRQ_BUCK3_SC, 1, TPS6594_BIT_BUCKX_SC_INT(2)), + REGMAP_IRQ_REG(TPS6594_IRQ_BUCK3_ILIM, 1, TPS6594_BIT_BUCKX_ILIM_INT(2)), + REGMAP_IRQ_REG(TPS6594_IRQ_BUCK4_OV, 1, TPS6594_BIT_BUCKX_OV_INT(3)), + REGMAP_IRQ_REG(TPS6594_IRQ_BUCK4_UV, 1, TPS6594_BIT_BUCKX_UV_INT(3)), + REGMAP_IRQ_REG(TPS6594_IRQ_BUCK4_SC, 1, TPS6594_BIT_BUCKX_SC_INT(3)), + REGMAP_IRQ_REG(TPS6594_IRQ_BUCK4_ILIM, 1, TPS6594_BIT_BUCKX_ILIM_INT(3)), + + /* INT_BUCK5 register */ + REGMAP_IRQ_REG(TPS6594_IRQ_BUCK5_OV, 2, TPS6594_BIT_BUCKX_OV_INT(4)), + REGMAP_IRQ_REG(TPS6594_IRQ_BUCK5_UV, 2, TPS6594_BIT_BUCKX_UV_INT(4)), + REGMAP_IRQ_REG(TPS6594_IRQ_BUCK5_SC, 2, TPS6594_BIT_BUCKX_SC_INT(4)), + REGMAP_IRQ_REG(TPS6594_IRQ_BUCK5_ILIM, 2, TPS6594_BIT_BUCKX_ILIM_INT(4)), + + /* INT_LDO1_2 register */ + REGMAP_IRQ_REG(TPS6594_IRQ_LDO1_OV, 3, TPS6594_BIT_LDOX_OV_INT(0)), + REGMAP_IRQ_REG(TPS6594_IRQ_LDO1_UV, 3, TPS6594_BIT_LDOX_UV_INT(0)), + REGMAP_IRQ_REG(TPS6594_IRQ_LDO1_SC, 3, TPS6594_BIT_LDOX_SC_INT(0)), + REGMAP_IRQ_REG(TPS6594_IRQ_LDO1_ILIM, 3, TPS6594_BIT_LDOX_ILIM_INT(0)), + REGMAP_IRQ_REG(TPS6594_IRQ_LDO2_OV, 3, TPS6594_BIT_LDOX_OV_INT(1)), + REGMAP_IRQ_REG(TPS6594_IRQ_LDO2_UV, 3, TPS6594_BIT_LDOX_UV_INT(1)), + REGMAP_IRQ_REG(TPS6594_IRQ_LDO2_SC, 3, TPS6594_BIT_LDOX_SC_INT(1)), + REGMAP_IRQ_REG(TPS6594_IRQ_LDO2_ILIM, 3, TPS6594_BIT_LDOX_ILIM_INT(1)), + + /* INT_LDO3_4 register */ + REGMAP_IRQ_REG(TPS6594_IRQ_LDO3_OV, 4, TPS6594_BIT_LDOX_OV_INT(2)), + REGMAP_IRQ_REG(TPS6594_IRQ_LDO3_UV, 4, TPS6594_BIT_LDOX_UV_INT(2)), + REGMAP_IRQ_REG(TPS6594_IRQ_LDO3_SC, 4, TPS6594_BIT_LDOX_SC_INT(2)), + REGMAP_IRQ_REG(TPS6594_IRQ_LDO3_ILIM, 4, TPS6594_BIT_LDOX_ILIM_INT(2)), + REGMAP_IRQ_REG(TPS6594_IRQ_LDO4_OV, 4, TPS6594_BIT_LDOX_OV_INT(3)), + REGMAP_IRQ_REG(TPS6594_IRQ_LDO4_UV, 4, TPS6594_BIT_LDOX_UV_INT(3)), + REGMAP_IRQ_REG(TPS6594_IRQ_LDO4_SC, 4, TPS6594_BIT_LDOX_SC_INT(3)), + REGMAP_IRQ_REG(TPS6594_IRQ_LDO4_ILIM, 4, TPS6594_BIT_LDOX_ILIM_INT(3)), + + /* INT_VMON register */ + REGMAP_IRQ_REG(TPS6594_IRQ_VCCA_OV, 5, TPS6594_BIT_VCCA_OV_INT), + REGMAP_IRQ_REG(TPS6594_IRQ_VCCA_UV, 5, TPS6594_BIT_VCCA_UV_INT), + REGMAP_IRQ_REG(TPS6594_IRQ_VMON1_OV, 5, TPS6594_BIT_VMON1_OV_INT), + REGMAP_IRQ_REG(TPS6594_IRQ_VMON1_UV, 5, TPS6594_BIT_VMON1_UV_INT), + REGMAP_IRQ_REG(TPS6594_IRQ_VMON1_RV, 5, TPS6594_BIT_VMON1_RV_INT), + REGMAP_IRQ_REG(TPS6594_IRQ_VMON2_OV, 5, TPS6594_BIT_VMON2_OV_INT), + REGMAP_IRQ_REG(TPS6594_IRQ_VMON2_UV, 5, TPS6594_BIT_VMON2_UV_INT), + REGMAP_IRQ_REG(TPS6594_IRQ_VMON2_RV, 5, TPS6594_BIT_VMON2_RV_INT), + + /* INT_GPIO register */ + REGMAP_IRQ_REG(TPS6594_IRQ_GPIO9, 6, TPS6594_BIT_GPIO9_INT), + REGMAP_IRQ_REG(TPS6594_IRQ_GPIO10, 6, TPS6594_BIT_GPIO10_INT), + REGMAP_IRQ_REG(TPS6594_IRQ_GPIO11, 6, TPS6594_BIT_GPIO11_INT), + + /* INT_GPIO1_8 register */ + REGMAP_IRQ_REG(TPS6594_IRQ_GPIO1, 7, TPS6594_BIT_GPIOX_INT(0)), + REGMAP_IRQ_REG(TPS6594_IRQ_GPIO2, 7, TPS6594_BIT_GPIOX_INT(1)), + REGMAP_IRQ_REG(TPS6594_IRQ_GPIO3, 7, TPS6594_BIT_GPIOX_INT(2)), + REGMAP_IRQ_REG(TPS6594_IRQ_GPIO4, 7, TPS6594_BIT_GPIOX_INT(3)), + REGMAP_IRQ_REG(TPS6594_IRQ_GPIO5, 7, TPS6594_BIT_GPIOX_INT(4)), + REGMAP_IRQ_REG(TPS6594_IRQ_GPIO6, 7, TPS6594_BIT_GPIOX_INT(5)), + REGMAP_IRQ_REG(TPS6594_IRQ_GPIO7, 7, TPS6594_BIT_GPIOX_INT(6)), + REGMAP_IRQ_REG(TPS6594_IRQ_GPIO8, 7, TPS6594_BIT_GPIOX_INT(7)), + + /* INT_STARTUP register */ + REGMAP_IRQ_REG(TPS6594_IRQ_NPWRON_START, 8, TPS6594_BIT_NPWRON_START_INT), + REGMAP_IRQ_REG(TPS6594_IRQ_ENABLE, 8, TPS6594_BIT_ENABLE_INT), + REGMAP_IRQ_REG(TPS6594_IRQ_FSD, 8, TPS6594_BIT_FSD_INT), + REGMAP_IRQ_REG(TPS6594_IRQ_SOFT_REBOOT, 8, TPS6594_BIT_SOFT_REBOOT_INT), + + /* INT_MISC register */ + REGMAP_IRQ_REG(TPS6594_IRQ_BIST_PASS, 9, TPS6594_BIT_BIST_PASS_INT), + REGMAP_IRQ_REG(TPS6594_IRQ_EXT_CLK, 9, TPS6594_BIT_EXT_CLK_INT), + REGMAP_IRQ_REG(TPS6594_IRQ_TWARN, 9, TPS6594_BIT_TWARN_INT), + + /* INT_MODERATE_ERR register */ + REGMAP_IRQ_REG(TPS6594_IRQ_TSD_ORD, 10, TPS6594_BIT_TSD_ORD_INT), + REGMAP_IRQ_REG(TPS6594_IRQ_BIST_FAIL, 10, TPS6594_BIT_BIST_FAIL_INT), + REGMAP_IRQ_REG(TPS6594_IRQ_REG_CRC_ERR, 10, TPS6594_BIT_REG_CRC_ERR_INT), + REGMAP_IRQ_REG(TPS6594_IRQ_RECOV_CNT, 10, TPS6594_BIT_RECOV_CNT_INT), + REGMAP_IRQ_REG(TPS6594_IRQ_SPMI_ERR, 10, TPS6594_BIT_SPMI_ERR_INT), + REGMAP_IRQ_REG(TPS6594_IRQ_NPWRON_LONG, 10, TPS6594_BIT_NPWRON_LONG_INT), + REGMAP_IRQ_REG(TPS6594_IRQ_NINT_READBACK, 10, TPS6594_BIT_NINT_READBACK_INT), + REGMAP_IRQ_REG(TPS6594_IRQ_NRSTOUT_READBACK, 10, TPS6594_BIT_NRSTOUT_READBACK_INT), + + /* INT_SEVERE_ERR register */ + REGMAP_IRQ_REG(TPS6594_IRQ_TSD_IMM, 11, TPS6594_BIT_TSD_IMM_INT), + REGMAP_IRQ_REG(TPS6594_IRQ_VCCA_OVP, 11, TPS6594_BIT_VCCA_OVP_INT), + REGMAP_IRQ_REG(TPS6594_IRQ_PFSM_ERR, 11, TPS6594_BIT_PFSM_ERR_INT), + + /* INT_FSM_ERR register */ + REGMAP_IRQ_REG(TPS6594_IRQ_IMM_SHUTDOWN, 12, TPS6594_BIT_IMM_SHUTDOWN_INT), + REGMAP_IRQ_REG(TPS6594_IRQ_ORD_SHUTDOWN, 12, TPS6594_BIT_ORD_SHUTDOWN_INT), + REGMAP_IRQ_REG(TPS6594_IRQ_MCU_PWR_ERR, 12, TPS6594_BIT_MCU_PWR_ERR_INT), + REGMAP_IRQ_REG(TPS6594_IRQ_SOC_PWR_ERR, 12, TPS6594_BIT_SOC_PWR_ERR_INT), + + /* INT_COMM_ERR register */ + REGMAP_IRQ_REG(TPS6594_IRQ_COMM_FRM_ERR, 13, TPS6594_BIT_COMM_FRM_ERR_INT), + REGMAP_IRQ_REG(TPS6594_IRQ_COMM_CRC_ERR, 13, TPS6594_BIT_COMM_CRC_ERR_INT), + REGMAP_IRQ_REG(TPS6594_IRQ_COMM_ADR_ERR, 13, TPS6594_BIT_COMM_ADR_ERR_INT), + + /* INT_READBACK_ERR register */ + REGMAP_IRQ_REG(TPS6594_IRQ_EN_DRV_READBACK, 14, TPS6594_BIT_EN_DRV_READBACK_INT), + REGMAP_IRQ_REG(TPS6594_IRQ_NRSTOUT_SOC_READBACK, 14, TPS6594_BIT_NRSTOUT_SOC_READBACK_INT), + + /* INT_ESM register */ + REGMAP_IRQ_REG(TPS6594_IRQ_ESM_SOC_PIN, 15, TPS6594_BIT_ESM_SOC_PIN_INT), + REGMAP_IRQ_REG(TPS6594_IRQ_ESM_SOC_FAIL, 15, TPS6594_BIT_ESM_SOC_FAIL_INT), + REGMAP_IRQ_REG(TPS6594_IRQ_ESM_SOC_RST, 15, TPS6594_BIT_ESM_SOC_RST_INT), + + /* RTC_STATUS register */ + REGMAP_IRQ_REG(TPS6594_IRQ_TIMER, 16, TPS6594_BIT_TIMER), + REGMAP_IRQ_REG(TPS6594_IRQ_ALARM, 16, TPS6594_BIT_ALARM), + REGMAP_IRQ_REG(TPS6594_IRQ_POWER_UP, 16, TPS6594_BIT_POWER_UP), +}; + +static const unsigned int tps6594_irq_reg[] = { + TPS6594_REG_INT_BUCK1_2, + TPS6594_REG_INT_BUCK3_4, + TPS6594_REG_INT_BUCK5, + TPS6594_REG_INT_LDO1_2, + TPS6594_REG_INT_LDO3_4, + TPS6594_REG_INT_VMON, + TPS6594_REG_INT_GPIO, + TPS6594_REG_INT_GPIO1_8, + TPS6594_REG_INT_STARTUP, + TPS6594_REG_INT_MISC, + TPS6594_REG_INT_MODERATE_ERR, + TPS6594_REG_INT_SEVERE_ERR, + TPS6594_REG_INT_FSM_ERR, + TPS6594_REG_INT_COMM_ERR, + TPS6594_REG_INT_READBACK_ERR, + TPS6594_REG_INT_ESM, + TPS6594_REG_RTC_STATUS, +}; + +static inline unsigned int tps6594_get_irq_reg(struct regmap_irq_chip_data *data, + unsigned int base, int index) +{ + return tps6594_irq_reg[index]; +}; + +static int tps6594_handle_post_irq(void *irq_drv_data) +{ + struct tps6594 *tps = irq_drv_data; + int ret = 0; + + /* + * When CRC is enabled, writing to a read-only bit triggers an error, + * and COMM_ADR_ERR_INT bit is set. Besides, bits indicating interrupts + * (that must be cleared) and read-only bits are sometimes grouped in + * the same register. + * Since regmap clears interrupts by doing a write per register, clearing + * an interrupt bit in a register containing also a read-only bit makes + * COMM_ADR_ERR_INT bit set. Clear immediately this bit to avoid raising + * a new interrupt. + */ + if (tps->use_crc) + ret = regmap_write_bits(tps->regmap, TPS6594_REG_INT_COMM_ERR, + TPS6594_BIT_COMM_ADR_ERR_INT, + TPS6594_BIT_COMM_ADR_ERR_INT); + + return ret; +}; + +static struct regmap_irq_chip tps6594_irq_chip = { + .ack_base = TPS6594_REG_INT_BUCK1_2, + .ack_invert = 1, + .clear_ack = 1, + .init_ack_masked = 1, + .num_regs = ARRAY_SIZE(tps6594_irq_reg), + .irqs = tps6594_irqs, + .num_irqs = ARRAY_SIZE(tps6594_irqs), + .get_irq_reg = tps6594_get_irq_reg, + .handle_post_irq = tps6594_handle_post_irq, +}; + +bool tps6594_is_volatile_reg(struct device *dev, unsigned int reg) +{ + return (reg >= TPS6594_REG_INT_TOP && reg <= TPS6594_REG_STAT_READBACK_ERR) || + reg == TPS6594_REG_RTC_STATUS; +} +EXPORT_SYMBOL_GPL(tps6594_is_volatile_reg); + +static int tps6594_check_crc_mode(struct tps6594 *tps, bool primary_pmic) +{ + int ret; + + /* + * Check if CRC is enabled. + * Once CRC is enabled, it can't be disabled until next power cycle. + */ + tps->use_crc = true; + ret = regmap_test_bits(tps->regmap, TPS6594_REG_SERIAL_IF_CONFIG, + TPS6594_BIT_I2C1_SPI_CRC_EN); + if (ret == 0) { + ret = -EIO; + } else if (ret > 0) { + dev_info(tps->dev, "CRC feature enabled on %s PMIC", + primary_pmic ? "primary" : "secondary"); + ret = 0; + } + + return ret; +} + +static int tps6594_set_crc_feature(struct tps6594 *tps) +{ + int ret; + + ret = tps6594_check_crc_mode(tps, true); + if (ret) { + /* + * If CRC is not already enabled, force PFSM I2C_2 trigger to enable it + * on primary PMIC. + */ + tps->use_crc = false; + ret = regmap_write_bits(tps->regmap, TPS6594_REG_FSM_I2C_TRIGGERS, + TPS6594_BIT_TRIGGER_I2C(2), TPS6594_BIT_TRIGGER_I2C(2)); + if (ret) + return ret; + + /* + * Wait for PFSM to process trigger. + * The datasheet indicates 2 ms, and clock specification is +/-5%. + * 4 ms should provide sufficient margin. + */ + usleep_range(4000, 5000); + + ret = tps6594_check_crc_mode(tps, true); + } + + return ret; +} + +static int tps6594_enable_crc(struct tps6594 *tps) +{ + struct device *dev = tps->dev; + unsigned int is_primary; + unsigned long timeout = msecs_to_jiffies(TPS6594_CRC_SYNC_TIMEOUT_MS); + int ret; + + /* + * CRC mode can be used with I2C or SPI protocols. + * If this mode is specified for primary PMIC, it will also be applied to secondary PMICs + * through SPMI serial interface. + * In this multi-PMIC synchronization scheme, the primary PMIC is the controller device + * on the SPMI bus, and the secondary PMICs are the target devices on the SPMI bus. + */ + is_primary = of_property_read_bool(dev->of_node, "ti,primary-pmic"); + if (is_primary) { + /* Enable CRC feature on primary PMIC */ + ret = tps6594_set_crc_feature(tps); + if (ret) + return ret; + + /* Notify secondary PMICs that CRC feature is enabled */ + complete_all(&tps6594_crc_comp); + } else { + /* Wait for CRC feature enabling event from primary PMIC */ + ret = wait_for_completion_interruptible_timeout(&tps6594_crc_comp, timeout); + if (ret == 0) + ret = -ETIMEDOUT; + else if (ret > 0) + ret = tps6594_check_crc_mode(tps, false); + } + + return ret; +} + +int tps6594_device_init(struct tps6594 *tps, bool enable_crc) +{ + struct device *dev = tps->dev; + int ret; + + if (enable_crc) { + ret = tps6594_enable_crc(tps); + if (ret) + return dev_err_probe(dev, ret, "Failed to enable CRC\n"); + } + + /* Keep PMIC in ACTIVE state */ + ret = regmap_set_bits(tps->regmap, TPS6594_REG_FSM_NSLEEP_TRIGGERS, + TPS6594_BIT_NSLEEP1B | TPS6594_BIT_NSLEEP2B); + if (ret) + return dev_err_probe(dev, ret, "Failed to set PMIC state\n"); + + tps6594_irq_chip.irq_drv_data = tps; + tps6594_irq_chip.name = devm_kasprintf(dev, GFP_KERNEL, "%s-%ld-0x%02x", + dev->driver->name, tps->chip_id, tps->reg); + + ret = devm_regmap_add_irq_chip(dev, tps->regmap, tps->irq, IRQF_SHARED | IRQF_ONESHOT, + 0, &tps6594_irq_chip, &tps->irq_data); + if (ret) + return dev_err_probe(dev, ret, "Failed to add regmap IRQ\n"); + + ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_AUTO, tps6594_common_cells, + ARRAY_SIZE(tps6594_common_cells), NULL, 0, + regmap_irq_get_domain(tps->irq_data)); + if (ret) + return dev_err_probe(dev, ret, "Failed to add common child devices\n"); + + /* No RTC for LP8764 */ + if (tps->chip_id != LP8764) { + ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_AUTO, tps6594_rtc_cells, + ARRAY_SIZE(tps6594_rtc_cells), NULL, 0, + regmap_irq_get_domain(tps->irq_data)); + if (ret) + return dev_err_probe(dev, ret, "Failed to add RTC child device\n"); + } + + return 0; +} +EXPORT_SYMBOL_GPL(tps6594_device_init); + +MODULE_AUTHOR("Julien Panis "); +MODULE_DESCRIPTION("TPS6594 Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/mfd/tps6594-i2c.c b/drivers/mfd/tps6594-i2c.c new file mode 100644 index 0000000000000000000000000000000000000000..899c88c0fe7744464796e7c0d67265a2628c2985 --- /dev/null +++ b/drivers/mfd/tps6594-i2c.c @@ -0,0 +1,244 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * I2C access driver for TI TPS6594/TPS6593/LP8764 PMICs + * + * Copyright (C) 2023 BayLibre Incorporated - https://www.baylibre.com/ + */ + +#include +#include +#include +#include +#include +#include + +#include + +static bool enable_crc; +module_param(enable_crc, bool, 0444); +MODULE_PARM_DESC(enable_crc, "Enable CRC feature for I2C interface"); + +DECLARE_CRC8_TABLE(tps6594_i2c_crc_table); + +static int tps6594_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) +{ + int ret = i2c_transfer(adap, msgs, num); + + if (ret == num) + return 0; + else if (ret < 0) + return ret; + else + return -EIO; +} + +static int tps6594_i2c_reg_read_with_crc(struct i2c_client *client, u8 page, u8 reg, u8 *val) +{ + struct i2c_msg msgs[2]; + u8 buf_rx[] = { 0, 0 }; + /* I2C address = I2C base address + Page index */ + const u8 addr = client->addr + page; + /* + * CRC is calculated from every bit included in the protocol + * except the ACK bits from the target. Byte stream is: + * - B0: (I2C_addr_7bits << 1) | WR_bit, with WR_bit = 0 + * - B1: reg + * - B2: (I2C_addr_7bits << 1) | RD_bit, with RD_bit = 1 + * - B3: val + * - B4: CRC from B0-B1-B2-B3 + */ + u8 crc_data[] = { addr << 1, reg, addr << 1 | 1, 0 }; + int ret; + + /* Write register */ + msgs[0].addr = addr; + msgs[0].flags = 0; + msgs[0].len = 1; + msgs[0].buf = ® + + /* Read data and CRC */ + msgs[1].addr = msgs[0].addr; + msgs[1].flags = I2C_M_RD; + msgs[1].len = 2; + msgs[1].buf = buf_rx; + + ret = tps6594_i2c_transfer(client->adapter, msgs, 2); + if (ret < 0) + return ret; + + crc_data[sizeof(crc_data) - 1] = *val = buf_rx[0]; + if (buf_rx[1] != crc8(tps6594_i2c_crc_table, crc_data, sizeof(crc_data), CRC8_INIT_VALUE)) + return -EIO; + + return ret; +} + +static int tps6594_i2c_reg_write_with_crc(struct i2c_client *client, u8 page, u8 reg, u8 val) +{ + struct i2c_msg msg; + u8 buf[] = { reg, val, 0 }; + /* I2C address = I2C base address + Page index */ + const u8 addr = client->addr + page; + /* + * CRC is calculated from every bit included in the protocol + * except the ACK bits from the target. Byte stream is: + * - B0: (I2C_addr_7bits << 1) | WR_bit, with WR_bit = 0 + * - B1: reg + * - B2: val + * - B3: CRC from B0-B1-B2 + */ + const u8 crc_data[] = { addr << 1, reg, val }; + + /* Write register, data and CRC */ + msg.addr = addr; + msg.flags = client->flags & I2C_M_TEN; + msg.len = sizeof(buf); + msg.buf = buf; + + buf[msg.len - 1] = crc8(tps6594_i2c_crc_table, crc_data, sizeof(crc_data), CRC8_INIT_VALUE); + + return tps6594_i2c_transfer(client->adapter, &msg, 1); +} + +static int tps6594_i2c_read(void *context, const void *reg_buf, size_t reg_size, + void *val_buf, size_t val_size) +{ + struct i2c_client *client = context; + struct tps6594 *tps = i2c_get_clientdata(client); + struct i2c_msg msgs[2]; + const u8 *reg_bytes = reg_buf; + u8 *val_bytes = val_buf; + const u8 page = reg_bytes[1]; + u8 reg = reg_bytes[0]; + int ret = 0; + int i; + + if (tps->use_crc) { + /* + * Auto-increment feature does not support CRC protocol. + * Converts the bulk read operation into a series of single read operations. + */ + for (i = 0 ; ret == 0 && i < val_size ; i++) + ret = tps6594_i2c_reg_read_with_crc(client, page, reg + i, val_bytes + i); + + return ret; + } + + /* Write register: I2C address = I2C base address + Page index */ + msgs[0].addr = client->addr + page; + msgs[0].flags = 0; + msgs[0].len = 1; + msgs[0].buf = ® + + /* Read data */ + msgs[1].addr = msgs[0].addr; + msgs[1].flags = I2C_M_RD; + msgs[1].len = val_size; + msgs[1].buf = val_bytes; + + return tps6594_i2c_transfer(client->adapter, msgs, 2); +} + +static int tps6594_i2c_write(void *context, const void *data, size_t count) +{ + struct i2c_client *client = context; + struct tps6594 *tps = i2c_get_clientdata(client); + struct i2c_msg msg; + const u8 *bytes = data; + u8 *buf; + const u8 page = bytes[1]; + const u8 reg = bytes[0]; + int ret = 0; + int i; + + if (tps->use_crc) { + /* + * Auto-increment feature does not support CRC protocol. + * Converts the bulk write operation into a series of single write operations. + */ + for (i = 0 ; ret == 0 && i < count - 2 ; i++) + ret = tps6594_i2c_reg_write_with_crc(client, page, reg + i, bytes[i + 2]); + + return ret; + } + + /* Setup buffer: page byte is not sent */ + buf = kzalloc(--count, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + buf[0] = reg; + for (i = 0 ; i < count - 1 ; i++) + buf[i + 1] = bytes[i + 2]; + + /* Write register and data: I2C address = I2C base address + Page index */ + msg.addr = client->addr + page; + msg.flags = client->flags & I2C_M_TEN; + msg.len = count; + msg.buf = buf; + + ret = tps6594_i2c_transfer(client->adapter, &msg, 1); + + kfree(buf); + return ret; +} + +static const struct regmap_config tps6594_i2c_regmap_config = { + .reg_bits = 16, + .val_bits = 8, + .max_register = TPS6594_REG_DWD_FAIL_CNT_REG, + .volatile_reg = tps6594_is_volatile_reg, + .read = tps6594_i2c_read, + .write = tps6594_i2c_write, +}; + +static const struct of_device_id tps6594_i2c_of_match_table[] = { + { .compatible = "ti,tps6594-q1", .data = (void *)TPS6594, }, + { .compatible = "ti,tps6593-q1", .data = (void *)TPS6593, }, + { .compatible = "ti,lp8764-q1", .data = (void *)LP8764, }, + {} +}; +MODULE_DEVICE_TABLE(of, tps6594_i2c_of_match_table); + +static int tps6594_i2c_probe(struct i2c_client *client) +{ + struct device *dev = &client->dev; + struct tps6594 *tps; + const struct of_device_id *match; + + tps = devm_kzalloc(dev, sizeof(*tps), GFP_KERNEL); + if (!tps) + return -ENOMEM; + + i2c_set_clientdata(client, tps); + + tps->dev = dev; + tps->reg = client->addr; + tps->irq = client->irq; + + tps->regmap = devm_regmap_init(dev, NULL, client, &tps6594_i2c_regmap_config); + if (IS_ERR(tps->regmap)) + return dev_err_probe(dev, PTR_ERR(tps->regmap), "Failed to init regmap\n"); + + match = of_match_device(tps6594_i2c_of_match_table, dev); + if (!match) + return dev_err_probe(dev, -EINVAL, "Failed to find matching chip ID\n"); + tps->chip_id = (unsigned long)match->data; + + crc8_populate_msb(tps6594_i2c_crc_table, TPS6594_CRC8_POLYNOMIAL); + + return tps6594_device_init(tps, enable_crc); +} + +static struct i2c_driver tps6594_i2c_driver = { + .driver = { + .name = "tps6594", + .of_match_table = tps6594_i2c_of_match_table, + }, + .probe = tps6594_i2c_probe, +}; +module_i2c_driver(tps6594_i2c_driver); + +MODULE_AUTHOR("Julien Panis "); +MODULE_DESCRIPTION("TPS6594 I2C Interface Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/mfd/tps6594-spi.c b/drivers/mfd/tps6594-spi.c new file mode 100644 index 0000000000000000000000000000000000000000..f4b4f37f957f3e647802cff0f7775c822f613cfb --- /dev/null +++ b/drivers/mfd/tps6594-spi.c @@ -0,0 +1,129 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * SPI access driver for TI TPS6594/TPS6593/LP8764 PMICs + * + * Copyright (C) 2023 BayLibre Incorporated - https://www.baylibre.com/ + */ + +#include +#include +#include +#include +#include +#include + +#include + +#define TPS6594_SPI_PAGE_SHIFT 5 +#define TPS6594_SPI_READ_BIT BIT(4) + +static bool enable_crc; +module_param(enable_crc, bool, 0444); +MODULE_PARM_DESC(enable_crc, "Enable CRC feature for SPI interface"); + +DECLARE_CRC8_TABLE(tps6594_spi_crc_table); + +static int tps6594_spi_reg_read(void *context, unsigned int reg, unsigned int *val) +{ + struct spi_device *spi = context; + struct tps6594 *tps = spi_get_drvdata(spi); + u8 buf[4] = { 0 }; + size_t count_rx = 1; + int ret; + + buf[0] = reg; + buf[1] = TPS6594_REG_TO_PAGE(reg) << TPS6594_SPI_PAGE_SHIFT | TPS6594_SPI_READ_BIT; + + if (tps->use_crc) + count_rx++; + + ret = spi_write_then_read(spi, buf, 2, buf + 2, count_rx); + if (ret < 0) + return ret; + + if (tps->use_crc && buf[3] != crc8(tps6594_spi_crc_table, buf, 3, CRC8_INIT_VALUE)) + return -EIO; + + *val = buf[2]; + + return 0; +} + +static int tps6594_spi_reg_write(void *context, unsigned int reg, unsigned int val) +{ + struct spi_device *spi = context; + struct tps6594 *tps = spi_get_drvdata(spi); + u8 buf[4] = { 0 }; + size_t count = 3; + + buf[0] = reg; + buf[1] = TPS6594_REG_TO_PAGE(reg) << TPS6594_SPI_PAGE_SHIFT; + buf[2] = val; + + if (tps->use_crc) + buf[3] = crc8(tps6594_spi_crc_table, buf, count++, CRC8_INIT_VALUE); + + return spi_write(spi, buf, count); +} + +static const struct regmap_config tps6594_spi_regmap_config = { + .reg_bits = 16, + .val_bits = 8, + .max_register = TPS6594_REG_DWD_FAIL_CNT_REG, + .volatile_reg = tps6594_is_volatile_reg, + .reg_read = tps6594_spi_reg_read, + .reg_write = tps6594_spi_reg_write, + .use_single_read = true, + .use_single_write = true, +}; + +static const struct of_device_id tps6594_spi_of_match_table[] = { + { .compatible = "ti,tps6594-q1", .data = (void *)TPS6594, }, + { .compatible = "ti,tps6593-q1", .data = (void *)TPS6593, }, + { .compatible = "ti,lp8764-q1", .data = (void *)LP8764, }, + {} +}; +MODULE_DEVICE_TABLE(of, tps6594_spi_of_match_table); + +static int tps6594_spi_probe(struct spi_device *spi) +{ + struct device *dev = &spi->dev; + struct tps6594 *tps; + const struct of_device_id *match; + + tps = devm_kzalloc(dev, sizeof(*tps), GFP_KERNEL); + if (!tps) + return -ENOMEM; + + spi_set_drvdata(spi, tps); + + tps->dev = dev; + tps->reg = spi->chip_select; + tps->irq = spi->irq; + + tps->regmap = devm_regmap_init(dev, NULL, spi, &tps6594_spi_regmap_config); + if (IS_ERR(tps->regmap)) + return dev_err_probe(dev, PTR_ERR(tps->regmap), "Failed to init regmap\n"); + + match = of_match_device(tps6594_spi_of_match_table, dev); + if (!match) + return dev_err_probe(dev, -EINVAL, "Failed to find matching chip ID\n"); + tps->chip_id = (unsigned long)match->data; + + crc8_populate_msb(tps6594_spi_crc_table, TPS6594_CRC8_POLYNOMIAL); + + return tps6594_device_init(tps, enable_crc); +} + +static struct spi_driver tps6594_spi_driver = { + .driver = { + .name = "tps6594", + .of_match_table = tps6594_spi_of_match_table, + }, + .probe = tps6594_spi_probe, +}; +module_spi_driver(tps6594_spi_driver); + +MODULE_AUTHOR("Julien Panis "); +MODULE_DESCRIPTION("TPS6594 SPI Interface Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c index e801b7ce010f30ab56c9e9f78c95371dbaa7847e..ce01a87f8dc399ddf3ed31cca0ee0b1cd4abef94 100644 --- a/drivers/mfd/twl-core.c +++ b/drivers/mfd/twl-core.c @@ -890,7 +890,7 @@ static struct i2c_driver twl_driver = { .driver.name = DRIVER_NAME, .driver.pm = &twl_dev_pm_ops, .id_table = twl_ids, - .probe_new = twl_probe, + .probe = twl_probe, .remove = twl_remove, }; builtin_i2c_driver(twl_driver); diff --git a/drivers/mfd/twl6040.c b/drivers/mfd/twl6040.c index e982119bbefa576a1cd3dd960f4d7e1a3c71e323..d85675a4d9a81254b34f802396f957318b313c86 100644 --- a/drivers/mfd/twl6040.c +++ b/drivers/mfd/twl6040.c @@ -608,7 +608,7 @@ static const struct regmap_config twl6040_regmap_config = { .volatile_reg = twl6040_volatile_reg, .writeable_reg = twl6040_writeable_reg, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, .use_single_read = true, .use_single_write = true, }; @@ -829,7 +829,7 @@ static struct i2c_driver twl6040_driver = { .driver = { .name = "twl6040", }, - .probe_new = twl6040_probe, + .probe = twl6040_probe, .remove = twl6040_remove, .id_table = twl6040_i2c_id, }; diff --git a/drivers/mfd/wcd934x.c b/drivers/mfd/wcd934x.c index 07e884087f2c7d37cd8e6f2bfa3409014b25546c..6b942d5270c165aef076f4e9ba7827642b26dc10 100644 --- a/drivers/mfd/wcd934x.c +++ b/drivers/mfd/wcd934x.c @@ -227,10 +227,9 @@ static int wcd934x_slim_probe(struct slim_device *sdev) "Failed to get IRQ\n"); ddata->extclk = devm_clk_get(dev, "extclk"); - if (IS_ERR(ddata->extclk)) { - dev_err(dev, "Failed to get extclk"); - return PTR_ERR(ddata->extclk); - } + if (IS_ERR(ddata->extclk)) + return dev_err_probe(dev, PTR_ERR(ddata->extclk), + "Failed to get extclk"); ddata->supplies[0].supply = "vdd-buck"; ddata->supplies[1].supply = "vdd-buck-sido"; @@ -239,16 +238,12 @@ static int wcd934x_slim_probe(struct slim_device *sdev) ddata->supplies[4].supply = "vdd-io"; ret = regulator_bulk_get(dev, WCD934X_MAX_SUPPLY, ddata->supplies); - if (ret) { - dev_err(dev, "Failed to get supplies: err = %d\n", ret); - return ret; - } + if (ret) + return dev_err_probe(dev, ret, "Failed to get supplies\n"); ret = regulator_bulk_enable(WCD934X_MAX_SUPPLY, ddata->supplies); - if (ret) { - dev_err(dev, "Failed to enable supplies: err = %d\n", ret); - return ret; - } + if (ret) + return dev_err_probe(dev, ret, "Failed to enable supplies\n"); /* * For WCD934X, it takes about 600us for the Vout_A and @@ -258,8 +253,9 @@ static int wcd934x_slim_probe(struct slim_device *sdev) usleep_range(600, 650); reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW); if (IS_ERR(reset_gpio)) { - return dev_err_probe(dev, PTR_ERR(reset_gpio), - "Failed to get reset gpio: err = %ld\n", PTR_ERR(reset_gpio)); + ret = dev_err_probe(dev, PTR_ERR(reset_gpio), + "Failed to get reset gpio\n"); + goto err_disable_regulators; } msleep(20); gpiod_set_value(reset_gpio, 1); @@ -269,6 +265,10 @@ static int wcd934x_slim_probe(struct slim_device *sdev) dev_set_drvdata(dev, ddata); return 0; + +err_disable_regulators: + regulator_bulk_disable(WCD934X_MAX_SUPPLY, ddata->supplies); + return ret; } static void wcd934x_slim_remove(struct slim_device *sdev) diff --git a/drivers/mfd/wl1273-core.c b/drivers/mfd/wl1273-core.c index a5d6128fc67d43533947c0a8c20a0ea3bda45d09..e2a7fccaed016bb5b248a801f4f8e6e86c2574a8 100644 --- a/drivers/mfd/wl1273-core.c +++ b/drivers/mfd/wl1273-core.c @@ -232,7 +232,7 @@ static struct i2c_driver wl1273_core_driver = { .driver = { .name = WL1273_FM_DRIVER_NAME, }, - .probe_new = wl1273_core_probe, + .probe = wl1273_core_probe, .id_table = wl1273_driver_id_table, }; diff --git a/drivers/mfd/wm831x-core.c b/drivers/mfd/wm831x-core.c index d2f444d2ae78f3e9f7cba8da19bce866b0f60d5a..e86b6a4896a68d70f9bea9b3fd957e382730033c 100644 --- a/drivers/mfd/wm831x-core.c +++ b/drivers/mfd/wm831x-core.c @@ -1430,7 +1430,7 @@ struct regmap_config wm831x_regmap_config = { .reg_bits = 16, .val_bits = 16, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, .max_register = WM831X_DBE_CHECK_DATA, .readable_reg = wm831x_reg_readable, diff --git a/drivers/mfd/wm831x-i2c.c b/drivers/mfd/wm831x-i2c.c index 9dbe96e2d46a02c91053e12c4aa3172f810137d4..997837f13180603ae0109b67b8b7b551e74d91b6 100644 --- a/drivers/mfd/wm831x-i2c.c +++ b/drivers/mfd/wm831x-i2c.c @@ -102,7 +102,7 @@ static struct i2c_driver wm831x_i2c_driver = { .of_match_table = of_match_ptr(wm831x_of_match), .suppress_bind_attrs = true, }, - .probe_new = wm831x_i2c_probe, + .probe = wm831x_i2c_probe, .id_table = wm831x_i2c_id, }; diff --git a/drivers/mfd/wm8350-i2c.c b/drivers/mfd/wm8350-i2c.c index 1fa1dfbc9e315c87c7abaffccaadedb47d4ec0c8..c2a7d7069975272bb9965f84a2d013985033557a 100644 --- a/drivers/mfd/wm8350-i2c.c +++ b/drivers/mfd/wm8350-i2c.c @@ -52,7 +52,7 @@ static struct i2c_driver wm8350_i2c_driver = { .name = "wm8350", .suppress_bind_attrs = true, }, - .probe_new = wm8350_i2c_probe, + .probe = wm8350_i2c_probe, .id_table = wm8350_i2c_id, }; diff --git a/drivers/mfd/wm8400-core.c b/drivers/mfd/wm8400-core.c index 5e1599ac9abc3b7575bb776aad43c2bbaa302675..75483c9be0c4da1be5d467c8ebdd7c2601bbd681 100644 --- a/drivers/mfd/wm8400-core.c +++ b/drivers/mfd/wm8400-core.c @@ -54,8 +54,6 @@ static int wm8400_init(struct wm8400 *wm8400, unsigned int reg; int ret; - dev_set_drvdata(wm8400->dev, wm8400); - /* Check that this is actually a WM8400 */ ret = regmap_read(wm8400->regmap, WM8400_RESET_ID, ®); if (ret != 0) { @@ -145,7 +143,7 @@ static struct i2c_driver wm8400_i2c_driver = { .driver = { .name = "WM8400", }, - .probe_new = wm8400_i2c_probe, + .probe = wm8400_i2c_probe, .id_table = wm8400_i2c_id, }; #endif diff --git a/drivers/mfd/wm8994-core.c b/drivers/mfd/wm8994-core.c index c419ab0c0eae75e9e4105b609d9ce82c7a7b313f..1e4f1694f065721b43dbb09fc3f577e54c9c91df 100644 --- a/drivers/mfd/wm8994-core.c +++ b/drivers/mfd/wm8994-core.c @@ -320,8 +320,6 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq) if (ret != 0) return ret; - dev_set_drvdata(wm8994->dev, wm8994); - /* Add the on-chip regulators first for bootstrapping */ ret = mfd_add_devices(wm8994->dev, 0, wm8994_regulator_devs, @@ -672,7 +670,7 @@ static struct i2c_driver wm8994_i2c_driver = { .pm = pm_ptr(&wm8994_pm_ops), .of_match_table = wm8994_of_match, }, - .probe_new = wm8994_i2c_probe, + .probe = wm8994_i2c_probe, .remove = wm8994_i2c_remove, .id_table = wm8994_i2c_id, }; diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 433aa41977852af6ca1aabeb62de68783d8dece7..75e427f124b286e40d89d6e863b950a7634798af 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -538,6 +538,29 @@ config TMR_INJECT Say N here unless you know what you are doing. +config TPS6594_ESM + tristate "TI TPS6594 Error Signal Monitor support" + depends on MFD_TPS6594 + default MFD_TPS6594 + help + Support ESM (Error Signal Monitor) on TPS6594 PMIC devices. + ESM is used typically to reboot the board in error condition. + + This driver can also be built as a module. If so, the module + will be called tps6594-esm. + +config TPS6594_PFSM + tristate "TI TPS6594 Pre-configurable Finite State Machine support" + depends on MFD_TPS6594 + default MFD_TPS6594 + help + Support PFSM (Pre-configurable Finite State Machine) on TPS6594 PMIC devices. + These devices integrate a finite state machine engine, which manages the state + of the device during operating state transition. + + This driver can also be built as a module. If so, the module + will be called tps6594-pfsm. + source "drivers/misc/c2port/Kconfig" source "drivers/misc/eeprom/Kconfig" source "drivers/misc/cb710/Kconfig" diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 56de43943cd512694194901dff57e5b751e852a8..f2a4d1ff65d46a2a014b6e40ed737d26a68a25d0 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -65,3 +65,5 @@ obj-$(CONFIG_GP_PCI1XXXX) += mchp_pci1xxxx/ obj-$(CONFIG_VCPU_STALL_DETECTOR) += vcpu_stall_detector.o obj-$(CONFIG_TMR_MANAGER) += xilinx_tmr_manager.o obj-$(CONFIG_TMR_INJECT) += xilinx_tmr_inject.o +obj-$(CONFIG_TPS6594_ESM) += tps6594-esm.o +obj-$(CONFIG_TPS6594_PFSM) += tps6594-pfsm.o diff --git a/drivers/misc/ad525x_dpot-i2c.c b/drivers/misc/ad525x_dpot-i2c.c index 3856d5c04c5fdca66df37d175e785b7a7208afe1..469478f7a1d3313333e0ca20c9c5c793957b5bc0 100644 --- a/drivers/misc/ad525x_dpot-i2c.c +++ b/drivers/misc/ad525x_dpot-i2c.c @@ -106,7 +106,7 @@ static struct i2c_driver ad_dpot_i2c_driver = { .driver = { .name = "ad_dpot", }, - .probe_new = ad_dpot_i2c_probe, + .probe = ad_dpot_i2c_probe, .remove = ad_dpot_i2c_remove, .id_table = ad_dpot_id, }; diff --git a/drivers/misc/altera-stapl/Makefile b/drivers/misc/altera-stapl/Makefile index dd0f8189666bef7e57e9e5f35c65d1b246b3b100..90f18e7bf9b0d90023acd64504897b0fce20e36b 100644 --- a/drivers/misc/altera-stapl/Makefile +++ b/drivers/misc/altera-stapl/Makefile @@ -1,4 +1,5 @@ # SPDX-License-Identifier: GPL-2.0-only -altera-stapl-objs = altera-lpt.o altera-jtag.o altera-comp.o altera.o +altera-stapl-y = altera-jtag.o altera-comp.o altera.o +altera-stapl-$(CONFIG_HAS_IOPORT) += altera-lpt.o obj-$(CONFIG_ALTERA_STAPL) += altera-stapl.o diff --git a/drivers/misc/altera-stapl/altera.c b/drivers/misc/altera-stapl/altera.c index a58b7cb81d98148d4f99713719f70e8bc374bba5..587427b73914c5da285958b5b5753edbaeccc2b1 100644 --- a/drivers/misc/altera-stapl/altera.c +++ b/drivers/misc/altera-stapl/altera.c @@ -2407,6 +2407,10 @@ int altera_init(struct altera_config *config, const struct firmware *fw) astate->config = config; if (!astate->config->jtag_io) { + if (!IS_ENABLED(CONFIG_HAS_IOPORT)) { + retval = -ENODEV; + goto free_state; + } dprintk("%s: using byteblaster!\n", __func__); astate->config->jtag_io = netup_jtag_io_lpt; } @@ -2481,7 +2485,7 @@ int altera_init(struct altera_config *config, const struct firmware *fw) } else if (exec_result) printk(KERN_ERR "%s: error %d\n", __func__, exec_result); - +free_state: kfree(astate); free_value: kfree(value); diff --git a/drivers/misc/apds9802als.c b/drivers/misc/apds9802als.c index 0526c55d5cd5cb9f817c658a29c8e9171e9da772..693f0e539f37a55d6ca12fa397c389c3a34a9e26 100644 --- a/drivers/misc/apds9802als.c +++ b/drivers/misc/apds9802als.c @@ -296,7 +296,7 @@ static struct i2c_driver apds9802als_driver = { .name = DRIVER_NAME, .pm = APDS9802ALS_PM_OPS, }, - .probe_new = apds9802als_probe, + .probe = apds9802als_probe, .remove = apds9802als_remove, .id_table = apds9802als_id, }; diff --git a/drivers/misc/apds990x.c b/drivers/misc/apds990x.c index 0024503ea6dbbfd6ce5e64a8ddaa3f8b994c6746..92b92be91d6021a621220ebcd0681365633e17aa 100644 --- a/drivers/misc/apds990x.c +++ b/drivers/misc/apds990x.c @@ -1267,11 +1267,11 @@ static const struct dev_pm_ops apds990x_pm_ops = { }; static struct i2c_driver apds990x_driver = { - .driver = { + .driver = { .name = "apds990x", .pm = &apds990x_pm_ops, }, - .probe_new = apds990x_probe, + .probe = apds990x_probe, .remove = apds990x_remove, .id_table = apds990x_id, }; diff --git a/drivers/misc/bh1770glc.c b/drivers/misc/bh1770glc.c index bedbe0efb330e7cfb16eba071c602ee6777cedbd..1629b62fd0524a9a5df25721f52cb9fd633c7b59 100644 --- a/drivers/misc/bh1770glc.c +++ b/drivers/misc/bh1770glc.c @@ -1374,11 +1374,11 @@ static const struct dev_pm_ops bh1770_pm_ops = { }; static struct i2c_driver bh1770_driver = { - .driver = { + .driver = { .name = "bh1770glc", .pm = &bh1770_pm_ops, }, - .probe_new = bh1770_probe, + .probe = bh1770_probe, .remove = bh1770_remove, .id_table = bh1770_id, }; diff --git a/drivers/misc/ds1682.c b/drivers/misc/ds1682.c index d517eed32971c42495ea23b29ccf4e5c52892190..21fc5bc85c5c8cc198c86135484ab802fc94eb68 100644 --- a/drivers/misc/ds1682.c +++ b/drivers/misc/ds1682.c @@ -250,7 +250,7 @@ static struct i2c_driver ds1682_driver = { .name = "ds1682", .of_match_table = ds1682_of_match, }, - .probe_new = ds1682_probe, + .probe = ds1682_probe, .remove = ds1682_remove, .id_table = ds1682_id, }; diff --git a/drivers/misc/eeprom/at24.c b/drivers/misc/eeprom/at24.c index 938c4f41b98c7a2eaacb88ab5fc287c99df07f56..dbbf7db4ff2f49b885bd113b0d232cbf6715e3de 100644 --- a/drivers/misc/eeprom/at24.c +++ b/drivers/misc/eeprom/at24.c @@ -761,7 +761,8 @@ static int at24_probe(struct i2c_client *client) pm_runtime_disable(dev); if (!pm_runtime_status_suspended(dev)) regulator_disable(at24->vcc_reg); - return PTR_ERR(at24->nvmem); + return dev_err_probe(dev, PTR_ERR(at24->nvmem), + "failed to register nvmem\n"); } /* @@ -832,7 +833,7 @@ static struct i2c_driver at24_driver = { .of_match_table = at24_of_match, .acpi_match_table = ACPI_PTR(at24_acpi_ids), }, - .probe_new = at24_probe, + .probe = at24_probe, .remove = at24_remove, .id_table = at24_ids, .flags = I2C_DRV_ACPI_WAIVE_D0_PROBE, diff --git a/drivers/misc/eeprom/ee1004.c b/drivers/misc/eeprom/ee1004.c index c8c6deb7ed8943dbcb7e97c559e75c0985088f91..a1acd77130f26de8217efbcdb45b16abd58aaabf 100644 --- a/drivers/misc/eeprom/ee1004.c +++ b/drivers/misc/eeprom/ee1004.c @@ -234,7 +234,7 @@ static struct i2c_driver ee1004_driver = { .name = "ee1004", .dev_groups = ee1004_groups, }, - .probe_new = ee1004_probe, + .probe = ee1004_probe, .remove = ee1004_remove, .id_table = ee1004_ids, }; diff --git a/drivers/misc/eeprom/eeprom.c b/drivers/misc/eeprom/eeprom.c index 32611100d5cd332380dafe34f0ee0657f712ce2a..ccb7c2f7ee2fbfdc125222b1ab7705e5ba058a11 100644 --- a/drivers/misc/eeprom/eeprom.c +++ b/drivers/misc/eeprom/eeprom.c @@ -196,7 +196,7 @@ static struct i2c_driver eeprom_driver = { .driver = { .name = "eeprom", }, - .probe_new = eeprom_probe, + .probe = eeprom_probe, .remove = eeprom_remove, .id_table = eeprom_id, diff --git a/drivers/misc/eeprom/idt_89hpesx.c b/drivers/misc/eeprom/idt_89hpesx.c index 7075d0b378811bb1329e86d204078878f35dbbf9..740c06382b8347f898a9e6424b9ce32e0438074f 100644 --- a/drivers/misc/eeprom/idt_89hpesx.c +++ b/drivers/misc/eeprom/idt_89hpesx.c @@ -1556,7 +1556,7 @@ static struct i2c_driver idt_driver = { .name = IDT_NAME, .of_match_table = idt_of_match, }, - .probe_new = idt_probe, + .probe = idt_probe, .remove = idt_remove, .id_table = idt_ids, }; diff --git a/drivers/misc/eeprom/max6875.c b/drivers/misc/eeprom/max6875.c index 79cf8afcef2e81150771e371c7fc489bd89d4477..cb6b1efeafe0fe86416be16bd57bdc8424d3b7de 100644 --- a/drivers/misc/eeprom/max6875.c +++ b/drivers/misc/eeprom/max6875.c @@ -192,7 +192,7 @@ static struct i2c_driver max6875_driver = { .driver = { .name = "max6875", }, - .probe_new = max6875_probe, + .probe = max6875_probe, .remove = max6875_remove, .id_table = max6875_id, }; diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c index 30d4d0476248ffdfeec0f5c2c2c7a71840e26d20..9666d28037e1806ce6022840d383ef7e4b429f68 100644 --- a/drivers/misc/fastrpc.c +++ b/drivers/misc/fastrpc.c @@ -1437,7 +1437,7 @@ static int fastrpc_init_create_process(struct fastrpc_user *fl, sc = FASTRPC_SCALARS(FASTRPC_RMID_INIT_CREATE, 4, 0); if (init.attrs) - sc = FASTRPC_SCALARS(FASTRPC_RMID_INIT_CREATE_ATTR, 6, 0); + sc = FASTRPC_SCALARS(FASTRPC_RMID_INIT_CREATE_ATTR, 4, 0); err = fastrpc_internal_invoke(fl, true, FASTRPC_INIT_HANDLE, sc, args); @@ -2225,6 +2225,9 @@ static int fastrpc_device_register(struct device *dev, struct fastrpc_channel_ct fdev->miscdev.fops = &fastrpc_fops; fdev->miscdev.name = devm_kasprintf(dev, GFP_KERNEL, "fastrpc-%s%s", domain, is_secured ? "-secure" : ""); + if (!fdev->miscdev.name) + return -ENOMEM; + err = misc_register(&fdev->miscdev); if (!err) { if (is_secured) diff --git a/drivers/misc/hmc6352.c b/drivers/misc/hmc6352.c index 8967940ecd1e8ae9bc6def638b909498372618de..759eaeb64307cd38b4cb4d869a02356ea14f4220 100644 --- a/drivers/misc/hmc6352.c +++ b/drivers/misc/hmc6352.c @@ -131,7 +131,7 @@ static struct i2c_driver hmc6352_driver = { .driver = { .name = "hmc6352", }, - .probe_new = hmc6352_probe, + .probe = hmc6352_probe, .remove = hmc6352_remove, .id_table = hmc6352_id, }; diff --git a/drivers/misc/ics932s401.c b/drivers/misc/ics932s401.c index 12108a7b9b40df7c4b879644d90e8dfe44192621..ee6296b9807823727db7a8d63608718481c8cb72 100644 --- a/drivers/misc/ics932s401.c +++ b/drivers/misc/ics932s401.c @@ -105,7 +105,7 @@ static struct i2c_driver ics932s401_driver = { .driver = { .name = "ics932s401", }, - .probe_new = ics932s401_probe, + .probe = ics932s401_probe, .remove = ics932s401_remove, .id_table = ics932s401_id, .detect = ics932s401_detect, diff --git a/drivers/misc/isl29003.c b/drivers/misc/isl29003.c index 147b58f7968da8fca5b9ed2ed47eacaebf19c1bc..ebf0635aee64a8d856ff496373d99c277cc7dd2a 100644 --- a/drivers/misc/isl29003.c +++ b/drivers/misc/isl29003.c @@ -459,7 +459,7 @@ static struct i2c_driver isl29003_driver = { .name = ISL29003_DRV_NAME, .pm = ISL29003_PM_OPS, }, - .probe_new = isl29003_probe, + .probe = isl29003_probe, .remove = isl29003_remove, .id_table = isl29003_id, }; diff --git a/drivers/misc/isl29020.c b/drivers/misc/isl29020.c index 3be02093368cf951e5eec2f7bda77d9097f563bc..c5976fa8c825053b8d01a1fde81c9503f9e9713c 100644 --- a/drivers/misc/isl29020.c +++ b/drivers/misc/isl29020.c @@ -214,7 +214,7 @@ static struct i2c_driver isl29020_driver = { .name = "isl29020", .pm = ISL29020_PM_OPS, }, - .probe_new = isl29020_probe, + .probe = isl29020_probe, .remove = isl29020_remove, .id_table = isl29020_id, }; diff --git a/drivers/misc/lis3lv02d/lis3lv02d_i2c.c b/drivers/misc/lis3lv02d/lis3lv02d_i2c.c index 7071412d6bf63ea1eb7196cdef52f01ccbe8e5e9..3882e97e96a70f580a599f940d6a400a42469c8c 100644 --- a/drivers/misc/lis3lv02d/lis3lv02d_i2c.c +++ b/drivers/misc/lis3lv02d/lis3lv02d_i2c.c @@ -262,7 +262,7 @@ static struct i2c_driver lis3lv02d_i2c_driver = { .pm = &lis3_pm_ops, .of_match_table = of_match_ptr(lis3lv02d_i2c_dt_ids), }, - .probe_new = lis3lv02d_i2c_probe, + .probe = lis3lv02d_i2c_probe, .remove = lis3lv02d_i2c_remove, .id_table = lis3lv02d_id, }; diff --git a/drivers/misc/lkdtm/bugs.c b/drivers/misc/lkdtm/bugs.c index 48821f4c2b21a88c083f5a36310106c0103f92e7..3c95600ab2f71bdd0c3ea62399204b555f279c12 100644 --- a/drivers/misc/lkdtm/bugs.c +++ b/drivers/misc/lkdtm/bugs.c @@ -309,7 +309,7 @@ static void lkdtm_OVERFLOW_UNSIGNED(void) struct array_bounds_flex_array { int one; int two; - char data[1]; + char data[]; }; struct array_bounds { @@ -341,7 +341,7 @@ static void lkdtm_ARRAY_BOUNDS(void) * For the uninstrumented flex array member, also touch 1 byte * beyond to verify it is correctly uninstrumented. */ - for (i = 0; i < sizeof(not_checked->data) + 1; i++) + for (i = 0; i < 2; i++) not_checked->data[i] = 'A'; pr_info("Array access beyond bounds ...\n"); @@ -487,6 +487,7 @@ static void lkdtm_UNSET_SMEP(void) * the cr4 writing instruction. */ insn = (unsigned char *)native_write_cr4; + OPTIMIZER_HIDE_VAR(insn); for (i = 0; i < MOV_CR4_DEPTH; i++) { /* mov %rdi, %cr4 */ if (insn[i] == 0x0f && insn[i+1] == 0x22 && insn[i+2] == 0xe7) diff --git a/drivers/misc/lkdtm/core.c b/drivers/misc/lkdtm/core.c index b4712ff196b4e59bf76347f01213ac43344d98b5..0772e4a4757e9f47a32abb6a76dc613261b2a642 100644 --- a/drivers/misc/lkdtm/core.c +++ b/drivers/misc/lkdtm/core.c @@ -79,7 +79,7 @@ static struct crashpoint crashpoints[] = { CRASHPOINT("INT_HARDWARE_ENTRY", "do_IRQ"), CRASHPOINT("INT_HW_IRQ_EN", "handle_irq_event"), CRASHPOINT("INT_TASKLET_ENTRY", "tasklet_action"), - CRASHPOINT("FS_DEVRW", "ll_rw_block"), + CRASHPOINT("FS_SUBMIT_BH", "submit_bh"), CRASHPOINT("MEM_SWAPOUT", "shrink_inactive_list"), CRASHPOINT("TIMERADD", "hrtimer_start"), CRASHPOINT("SCSI_QUEUE_RQ", "scsi_queue_rq"), diff --git a/drivers/misc/mei/bus-fixup.c b/drivers/misc/mei/bus-fixup.c index 31e3c74ca1f1e4a377592fb8e76b2ce327684063..b8b716faf1921914fad9fcc7228b8a07c6d545e3 100644 --- a/drivers/misc/mei/bus-fixup.c +++ b/drivers/misc/mei/bus-fixup.c @@ -108,7 +108,7 @@ struct mkhi_fw_ver { static int mei_osver(struct mei_cl_device *cldev) { const size_t size = MKHI_OSVER_BUF_LEN; - char buf[MKHI_OSVER_BUF_LEN]; + u8 buf[MKHI_OSVER_BUF_LEN]; struct mkhi_msg *req; struct mkhi_fwcaps *fwcaps; struct mei_os_ver *os_ver; @@ -137,7 +137,7 @@ static int mei_osver(struct mei_cl_device *cldev) sizeof(struct mkhi_fw_ver_block) * (__num)) static int mei_fwver(struct mei_cl_device *cldev) { - char buf[MKHI_FWVER_BUF_LEN]; + u8 buf[MKHI_FWVER_BUF_LEN]; struct mkhi_msg req; struct mkhi_msg *rsp; struct mkhi_fw_ver *fwver; diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c index 5d7a68674d9b20b32c415fe8c132ea3c558f03e0..33ec6424dfee25aacd862fd00b2b2f806fbd426c 100644 --- a/drivers/misc/mei/bus.c +++ b/drivers/misc/mei/bus.c @@ -1046,9 +1046,6 @@ static int mei_cl_device_match(struct device *dev, struct device_driver *drv) const struct mei_cl_driver *cldrv = to_mei_cl_driver(drv); const struct mei_cl_device_id *found_id; - if (!cldev) - return 0; - if (!cldev->do_match) return 0; @@ -1079,9 +1076,6 @@ static int mei_cl_device_probe(struct device *dev) cldev = to_mei_cl_device(dev); cldrv = to_mei_cl_driver(dev->driver); - if (!cldev) - return 0; - if (!cldrv || !cldrv->probe) return -ENODEV; @@ -1276,9 +1270,6 @@ static void mei_cl_bus_dev_release(struct device *dev) { struct mei_cl_device *cldev = to_mei_cl_device(dev); - if (!cldev) - return; - mei_cl_flush_queues(cldev->cl, NULL); mei_me_cl_put(cldev->me_cl); mei_dev_bus_put(cldev->bus); diff --git a/drivers/misc/pci_endpoint_test.c b/drivers/misc/pci_endpoint_test.c index a7244de081ec9c28c95a9d7b36e89943558d87e9..ed4d0ef5e5c3193b22cd65f1377ca7a922459e17 100644 --- a/drivers/misc/pci_endpoint_test.c +++ b/drivers/misc/pci_endpoint_test.c @@ -159,10 +159,7 @@ static irqreturn_t pci_endpoint_test_irqhandler(int irq, void *dev_id) if (reg & STATUS_IRQ_RAISED) { test->last_irq = irq; complete(&test->irq_raised); - reg &= ~STATUS_IRQ_RAISED; } - pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_STATUS, - reg); return IRQ_HANDLED; } @@ -316,21 +313,17 @@ static bool pci_endpoint_test_msi_irq(struct pci_endpoint_test *test, struct pci_dev *pdev = test->pdev; pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_IRQ_TYPE, - msix == false ? IRQ_TYPE_MSI : - IRQ_TYPE_MSIX); + msix ? IRQ_TYPE_MSIX : IRQ_TYPE_MSI); pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_IRQ_NUMBER, msi_num); pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_COMMAND, - msix == false ? COMMAND_RAISE_MSI_IRQ : - COMMAND_RAISE_MSIX_IRQ); + msix ? COMMAND_RAISE_MSIX_IRQ : + COMMAND_RAISE_MSI_IRQ); val = wait_for_completion_timeout(&test->irq_raised, msecs_to_jiffies(1000)); if (!val) return false; - if (pci_irq_vector(pdev, msi_num - 1) == test->last_irq) - return true; - - return false; + return pci_irq_vector(pdev, msi_num - 1) == test->last_irq; } static int pci_endpoint_test_validate_xfer_params(struct device *dev, @@ -729,6 +722,10 @@ static long pci_endpoint_test_ioctl(struct file *file, unsigned int cmd, struct pci_dev *pdev = test->pdev; mutex_lock(&test->mutex); + + reinit_completion(&test->irq_raised); + test->last_irq = -ENODATA; + switch (cmd) { case PCITEST_BAR: bar = arg; @@ -938,6 +935,9 @@ static void pci_endpoint_test_remove(struct pci_dev *pdev) if (id < 0) return; + pci_endpoint_test_release_irq(test); + pci_endpoint_test_free_irq_vectors(test); + misc_deregister(&test->miscdev); kfree(misc_device->name); kfree(test->name); @@ -947,9 +947,6 @@ static void pci_endpoint_test_remove(struct pci_dev *pdev) pci_iounmap(pdev, test->bar[bar]); } - pci_endpoint_test_release_irq(test); - pci_endpoint_test_free_irq_vectors(test); - pci_release_regions(pdev); pci_disable_device(pdev); } diff --git a/drivers/misc/sgi-gru/grufault.c b/drivers/misc/sgi-gru/grufault.c index b836936e97471715bf0da41de745e80f449d22c1..629edb6486deaef514ba15a52176b84fc17465e7 100644 --- a/drivers/misc/sgi-gru/grufault.c +++ b/drivers/misc/sgi-gru/grufault.c @@ -185,7 +185,7 @@ static int non_atomic_pte_lookup(struct vm_area_struct *vma, #else *pageshift = PAGE_SHIFT; #endif - if (get_user_pages(vaddr, 1, write ? FOLL_WRITE : 0, &page, NULL) <= 0) + if (get_user_pages(vaddr, 1, write ? FOLL_WRITE : 0, &page) <= 0) return -EFAULT; *paddr = page_to_phys(page); put_page(page); @@ -228,7 +228,7 @@ static int atomic_pte_lookup(struct vm_area_struct *vma, unsigned long vaddr, goto err; #ifdef CONFIG_X86_64 if (unlikely(pmd_large(*pmdp))) - pte = *(pte_t *) pmdp; + pte = ptep_get((pte_t *)pmdp); else #endif pte = *pte_offset_kernel(pmdp, vaddr); diff --git a/drivers/misc/smpro-errmon.c b/drivers/misc/smpro-errmon.c index a1f0b2c77fac34299fe7a8984fd32caa8cd0cb4e..c12035a465854ddd5077340b8c7bedbf6f1cd993 100644 --- a/drivers/misc/smpro-errmon.c +++ b/drivers/misc/smpro-errmon.c @@ -6,7 +6,6 @@ * */ -#include #include #include #include diff --git a/drivers/misc/sram.c b/drivers/misc/sram.c index 99413310956bbee8a86fbc7396c7b0fff9451a07..5757adf418b1de0f0aeee60edaed035b2d241d01 100644 --- a/drivers/misc/sram.c +++ b/drivers/misc/sram.c @@ -235,10 +235,11 @@ static int sram_reserve_regions(struct sram_dev *sram, struct resource *res) goto err_chunks; } if (!label) - label = child->name; - - block->label = devm_kstrdup(sram->dev, - label, GFP_KERNEL); + block->label = devm_kasprintf(sram->dev, GFP_KERNEL, + "%s", dev_name(sram->dev)); + else + block->label = devm_kstrdup(sram->dev, + label, GFP_KERNEL); if (!block->label) { ret = -ENOMEM; goto err_chunks; diff --git a/drivers/misc/tps6594-esm.c b/drivers/misc/tps6594-esm.c new file mode 100644 index 0000000000000000000000000000000000000000..b488f704f104eb81a0108d1c29fbed09a62f79d8 --- /dev/null +++ b/drivers/misc/tps6594-esm.c @@ -0,0 +1,132 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * ESM (Error Signal Monitor) driver for TI TPS6594/TPS6593/LP8764 PMICs + * + * Copyright (C) 2023 BayLibre Incorporated - https://www.baylibre.com/ + */ + +#include +#include +#include +#include +#include + +#include + +static irqreturn_t tps6594_esm_isr(int irq, void *dev_id) +{ + struct platform_device *pdev = dev_id; + int i; + + for (i = 0 ; i < pdev->num_resources ; i++) { + if (irq == platform_get_irq_byname(pdev, pdev->resource[i].name)) { + dev_err(pdev->dev.parent, "%s error detected\n", pdev->resource[i].name); + return IRQ_HANDLED; + } + } + + return IRQ_NONE; +} + +static int tps6594_esm_probe(struct platform_device *pdev) +{ + struct tps6594 *tps = dev_get_drvdata(pdev->dev.parent); + struct device *dev = &pdev->dev; + int irq; + int ret; + int i; + + for (i = 0 ; i < pdev->num_resources ; i++) { + irq = platform_get_irq_byname(pdev, pdev->resource[i].name); + if (irq < 0) + return dev_err_probe(dev, irq, "Failed to get %s irq\n", + pdev->resource[i].name); + + ret = devm_request_threaded_irq(dev, irq, NULL, + tps6594_esm_isr, IRQF_ONESHOT, + pdev->resource[i].name, pdev); + if (ret) + return dev_err_probe(dev, ret, "Failed to request irq\n"); + } + + ret = regmap_set_bits(tps->regmap, TPS6594_REG_ESM_SOC_MODE_CFG, + TPS6594_BIT_ESM_SOC_EN | TPS6594_BIT_ESM_SOC_ENDRV); + if (ret) + return dev_err_probe(dev, ret, "Failed to configure ESM\n"); + + ret = regmap_set_bits(tps->regmap, TPS6594_REG_ESM_SOC_START_REG, + TPS6594_BIT_ESM_SOC_START); + if (ret) + return dev_err_probe(dev, ret, "Failed to start ESM\n"); + + pm_runtime_enable(dev); + pm_runtime_get_sync(dev); + + return 0; +} + +static int tps6594_esm_remove(struct platform_device *pdev) +{ + struct tps6594 *tps = dev_get_drvdata(pdev->dev.parent); + struct device *dev = &pdev->dev; + int ret; + + ret = regmap_clear_bits(tps->regmap, TPS6594_REG_ESM_SOC_START_REG, + TPS6594_BIT_ESM_SOC_START); + if (ret) { + dev_err(dev, "Failed to stop ESM\n"); + goto out; + } + + ret = regmap_clear_bits(tps->regmap, TPS6594_REG_ESM_SOC_MODE_CFG, + TPS6594_BIT_ESM_SOC_EN | TPS6594_BIT_ESM_SOC_ENDRV); + if (ret) + dev_err(dev, "Failed to unconfigure ESM\n"); + +out: + pm_runtime_put_sync(dev); + pm_runtime_disable(dev); + + return ret; +} + +static int tps6594_esm_suspend(struct device *dev) +{ + struct tps6594 *tps = dev_get_drvdata(dev->parent); + int ret; + + ret = regmap_clear_bits(tps->regmap, TPS6594_REG_ESM_SOC_START_REG, + TPS6594_BIT_ESM_SOC_START); + + pm_runtime_put_sync(dev); + + return ret; +} + +static int tps6594_esm_resume(struct device *dev) +{ + struct tps6594 *tps = dev_get_drvdata(dev->parent); + + pm_runtime_get_sync(dev); + + return regmap_set_bits(tps->regmap, TPS6594_REG_ESM_SOC_START_REG, + TPS6594_BIT_ESM_SOC_START); +} + +static DEFINE_SIMPLE_DEV_PM_OPS(tps6594_esm_pm_ops, tps6594_esm_suspend, tps6594_esm_resume); + +static struct platform_driver tps6594_esm_driver = { + .driver = { + .name = "tps6594-esm", + .pm = pm_sleep_ptr(&tps6594_esm_pm_ops), + }, + .probe = tps6594_esm_probe, + .remove = tps6594_esm_remove, +}; + +module_platform_driver(tps6594_esm_driver); + +MODULE_ALIAS("platform:tps6594-esm"); +MODULE_AUTHOR("Julien Panis "); +MODULE_DESCRIPTION("TPS6594 Error Signal Monitor Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/misc/tps6594-pfsm.c b/drivers/misc/tps6594-pfsm.c new file mode 100644 index 0000000000000000000000000000000000000000..5223d1580807e906628950354c15ad02c1df2f4c --- /dev/null +++ b/drivers/misc/tps6594-pfsm.c @@ -0,0 +1,306 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * PFSM (Pre-configurable Finite State Machine) driver for TI TPS6594/TPS6593/LP8764 PMICs + * + * Copyright (C) 2023 BayLibre Incorporated - https://www.baylibre.com/ + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#define TPS6594_STARTUP_DEST_MCU_ONLY_VAL 2 +#define TPS6594_STARTUP_DEST_ACTIVE_VAL 3 +#define TPS6594_STARTUP_DEST_SHIFT 5 +#define TPS6594_STARTUP_DEST_MCU_ONLY (TPS6594_STARTUP_DEST_MCU_ONLY_VAL \ + << TPS6594_STARTUP_DEST_SHIFT) +#define TPS6594_STARTUP_DEST_ACTIVE (TPS6594_STARTUP_DEST_ACTIVE_VAL \ + << TPS6594_STARTUP_DEST_SHIFT) + +/* + * To update the PMIC firmware, the user must be able to access + * page 0 (user registers) and page 1 (NVM control and configuration). + */ +#define TPS6594_PMIC_MAX_POS 0x200 + +#define TPS6594_FILE_TO_PFSM(f) container_of((f)->private_data, struct tps6594_pfsm, miscdev) + +/** + * struct tps6594_pfsm - device private data structure + * + * @miscdev: misc device infos + * @regmap: regmap for accessing the device registers + */ +struct tps6594_pfsm { + struct miscdevice miscdev; + struct regmap *regmap; +}; + +static ssize_t tps6594_pfsm_read(struct file *f, char __user *buf, + size_t count, loff_t *ppos) +{ + struct tps6594_pfsm *pfsm = TPS6594_FILE_TO_PFSM(f); + loff_t pos = *ppos; + unsigned int val; + int ret; + int i; + + if (pos < 0) + return -EINVAL; + if (pos >= TPS6594_PMIC_MAX_POS) + return 0; + if (count > TPS6594_PMIC_MAX_POS - pos) + count = TPS6594_PMIC_MAX_POS - pos; + + for (i = 0 ; i < count ; i++) { + ret = regmap_read(pfsm->regmap, pos + i, &val); + if (ret) + return ret; + + if (put_user(val, buf + i)) + return -EFAULT; + } + + *ppos = pos + count; + + return count; +} + +static ssize_t tps6594_pfsm_write(struct file *f, const char __user *buf, + size_t count, loff_t *ppos) +{ + struct tps6594_pfsm *pfsm = TPS6594_FILE_TO_PFSM(f); + loff_t pos = *ppos; + char val; + int ret; + int i; + + if (pos < 0) + return -EINVAL; + if (pos >= TPS6594_PMIC_MAX_POS || !count) + return 0; + if (count > TPS6594_PMIC_MAX_POS - pos) + count = TPS6594_PMIC_MAX_POS - pos; + + for (i = 0 ; i < count ; i++) { + if (get_user(val, buf + i)) + return -EFAULT; + + ret = regmap_write(pfsm->regmap, pos + i, val); + if (ret) + return ret; + } + + *ppos = pos + count; + + return count; +} + +static int tps6594_pfsm_configure_ret_trig(struct regmap *regmap, u8 gpio_ret, u8 ddr_ret) +{ + int ret; + + if (gpio_ret) + ret = regmap_set_bits(regmap, TPS6594_REG_FSM_I2C_TRIGGERS, + TPS6594_BIT_TRIGGER_I2C(5) | TPS6594_BIT_TRIGGER_I2C(6)); + else + ret = regmap_clear_bits(regmap, TPS6594_REG_FSM_I2C_TRIGGERS, + TPS6594_BIT_TRIGGER_I2C(5) | TPS6594_BIT_TRIGGER_I2C(6)); + if (ret) + return ret; + + if (ddr_ret) + ret = regmap_set_bits(regmap, TPS6594_REG_FSM_I2C_TRIGGERS, + TPS6594_BIT_TRIGGER_I2C(7)); + else + ret = regmap_clear_bits(regmap, TPS6594_REG_FSM_I2C_TRIGGERS, + TPS6594_BIT_TRIGGER_I2C(7)); + + return ret; +} + +static long tps6594_pfsm_ioctl(struct file *f, unsigned int cmd, unsigned long arg) +{ + struct tps6594_pfsm *pfsm = TPS6594_FILE_TO_PFSM(f); + struct pmic_state_opt state_opt; + void __user *argp = (void __user *)arg; + int ret = -ENOIOCTLCMD; + + switch (cmd) { + case PMIC_GOTO_STANDBY: + /* Disable LP mode */ + ret = regmap_clear_bits(pfsm->regmap, TPS6594_REG_RTC_CTRL_2, + TPS6594_BIT_LP_STANDBY_SEL); + if (ret) + return ret; + + /* Force trigger */ + ret = regmap_write_bits(pfsm->regmap, TPS6594_REG_FSM_I2C_TRIGGERS, + TPS6594_BIT_TRIGGER_I2C(0), TPS6594_BIT_TRIGGER_I2C(0)); + break; + case PMIC_GOTO_LP_STANDBY: + /* Enable LP mode */ + ret = regmap_set_bits(pfsm->regmap, TPS6594_REG_RTC_CTRL_2, + TPS6594_BIT_LP_STANDBY_SEL); + if (ret) + return ret; + + /* Force trigger */ + ret = regmap_write_bits(pfsm->regmap, TPS6594_REG_FSM_I2C_TRIGGERS, + TPS6594_BIT_TRIGGER_I2C(0), TPS6594_BIT_TRIGGER_I2C(0)); + break; + case PMIC_UPDATE_PGM: + /* Force trigger */ + ret = regmap_write_bits(pfsm->regmap, TPS6594_REG_FSM_I2C_TRIGGERS, + TPS6594_BIT_TRIGGER_I2C(3), TPS6594_BIT_TRIGGER_I2C(3)); + break; + case PMIC_SET_ACTIVE_STATE: + /* Modify NSLEEP1-2 bits */ + ret = regmap_set_bits(pfsm->regmap, TPS6594_REG_FSM_NSLEEP_TRIGGERS, + TPS6594_BIT_NSLEEP1B | TPS6594_BIT_NSLEEP2B); + break; + case PMIC_SET_MCU_ONLY_STATE: + if (copy_from_user(&state_opt, argp, sizeof(state_opt))) + return -EFAULT; + + /* Configure retention triggers */ + ret = tps6594_pfsm_configure_ret_trig(pfsm->regmap, state_opt.gpio_retention, + state_opt.ddr_retention); + if (ret) + return ret; + + /* Modify NSLEEP1-2 bits */ + ret = regmap_clear_bits(pfsm->regmap, TPS6594_REG_FSM_NSLEEP_TRIGGERS, + TPS6594_BIT_NSLEEP1B); + if (ret) + return ret; + + ret = regmap_set_bits(pfsm->regmap, TPS6594_REG_FSM_NSLEEP_TRIGGERS, + TPS6594_BIT_NSLEEP2B); + break; + case PMIC_SET_RETENTION_STATE: + if (copy_from_user(&state_opt, argp, sizeof(state_opt))) + return -EFAULT; + + /* Configure wake-up destination */ + if (state_opt.mcu_only_startup_dest) + ret = regmap_write_bits(pfsm->regmap, TPS6594_REG_RTC_CTRL_2, + TPS6594_MASK_STARTUP_DEST, + TPS6594_STARTUP_DEST_MCU_ONLY); + else + ret = regmap_write_bits(pfsm->regmap, TPS6594_REG_RTC_CTRL_2, + TPS6594_MASK_STARTUP_DEST, + TPS6594_STARTUP_DEST_ACTIVE); + if (ret) + return ret; + + /* Configure retention triggers */ + ret = tps6594_pfsm_configure_ret_trig(pfsm->regmap, state_opt.gpio_retention, + state_opt.ddr_retention); + if (ret) + return ret; + + /* Modify NSLEEP1-2 bits */ + ret = regmap_clear_bits(pfsm->regmap, TPS6594_REG_FSM_NSLEEP_TRIGGERS, + TPS6594_BIT_NSLEEP2B); + break; + } + + return ret; +} + +static const struct file_operations tps6594_pfsm_fops = { + .owner = THIS_MODULE, + .llseek = generic_file_llseek, + .read = tps6594_pfsm_read, + .write = tps6594_pfsm_write, + .unlocked_ioctl = tps6594_pfsm_ioctl, + .compat_ioctl = compat_ptr_ioctl, +}; + +static irqreturn_t tps6594_pfsm_isr(int irq, void *dev_id) +{ + struct platform_device *pdev = dev_id; + int i; + + for (i = 0 ; i < pdev->num_resources ; i++) { + if (irq == platform_get_irq_byname(pdev, pdev->resource[i].name)) { + dev_err(pdev->dev.parent, "%s event detected\n", pdev->resource[i].name); + return IRQ_HANDLED; + } + } + + return IRQ_NONE; +} + +static int tps6594_pfsm_probe(struct platform_device *pdev) +{ + struct tps6594_pfsm *pfsm; + struct tps6594 *tps = dev_get_drvdata(pdev->dev.parent); + struct device *dev = &pdev->dev; + int irq; + int ret; + int i; + + pfsm = devm_kzalloc(dev, sizeof(struct tps6594_pfsm), GFP_KERNEL); + if (!pfsm) + return -ENOMEM; + + pfsm->regmap = tps->regmap; + + pfsm->miscdev.minor = MISC_DYNAMIC_MINOR; + pfsm->miscdev.name = devm_kasprintf(dev, GFP_KERNEL, "pfsm-%ld-0x%02x", + tps->chip_id, tps->reg); + pfsm->miscdev.fops = &tps6594_pfsm_fops; + pfsm->miscdev.parent = dev->parent; + + for (i = 0 ; i < pdev->num_resources ; i++) { + irq = platform_get_irq_byname(pdev, pdev->resource[i].name); + if (irq < 0) + return dev_err_probe(dev, irq, "Failed to get %s irq\n", + pdev->resource[i].name); + + ret = devm_request_threaded_irq(dev, irq, NULL, + tps6594_pfsm_isr, IRQF_ONESHOT, + pdev->resource[i].name, pdev); + if (ret) + return dev_err_probe(dev, ret, "Failed to request irq\n"); + } + + platform_set_drvdata(pdev, pfsm); + + return misc_register(&pfsm->miscdev); +} + +static int tps6594_pfsm_remove(struct platform_device *pdev) +{ + struct tps6594_pfsm *pfsm = platform_get_drvdata(pdev); + + misc_deregister(&pfsm->miscdev); + + return 0; +} + +static struct platform_driver tps6594_pfsm_driver = { + .driver = { + .name = "tps6594-pfsm", + }, + .probe = tps6594_pfsm_probe, + .remove = tps6594_pfsm_remove, +}; + +module_platform_driver(tps6594_pfsm_driver); + +MODULE_ALIAS("platform:tps6594-pfsm"); +MODULE_AUTHOR("Julien Panis "); +MODULE_DESCRIPTION("TPS6594 Pre-configurable Finite State Machine Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/misc/tsl2550.c b/drivers/misc/tsl2550.c index 6c62b94e0acdb3c79d461ac445363fb6f92e84e5..a3bc2823143ebc23e949eb32790580c1d87ae0c7 100644 --- a/drivers/misc/tsl2550.c +++ b/drivers/misc/tsl2550.c @@ -437,7 +437,7 @@ static struct i2c_driver tsl2550_driver = { .of_match_table = tsl2550_of_match, .pm = TSL2550_PM_OPS, }, - .probe_new = tsl2550_probe, + .probe = tsl2550_probe, .remove = tsl2550_remove, .id_table = tsl2550_id, }; diff --git a/drivers/misc/uacce/uacce.c b/drivers/misc/uacce/uacce.c index 346bd7cf2e94f5a1fbcde7d1ab7f68983cf07801..930c252753a073ac13b8a8d09899f60d37c46b47 100644 --- a/drivers/misc/uacce/uacce.c +++ b/drivers/misc/uacce/uacce.c @@ -166,8 +166,8 @@ static int uacce_fops_open(struct inode *inode, struct file *filep) init_waitqueue_head(&q->wait); filep->private_data = q; - uacce->inode = inode; q->state = UACCE_Q_INIT; + q->mapping = filep->f_mapping; mutex_init(&q->mutex); list_add(&q->list, &uacce->queues); mutex_unlock(&uacce->mutex); @@ -200,12 +200,15 @@ static int uacce_fops_release(struct inode *inode, struct file *filep) static void uacce_vma_close(struct vm_area_struct *vma) { struct uacce_queue *q = vma->vm_private_data; - struct uacce_qfile_region *qfr = NULL; - if (vma->vm_pgoff < UACCE_MAX_REGION) - qfr = q->qfrs[vma->vm_pgoff]; + if (vma->vm_pgoff < UACCE_MAX_REGION) { + struct uacce_qfile_region *qfr = q->qfrs[vma->vm_pgoff]; - kfree(qfr); + mutex_lock(&q->mutex); + q->qfrs[vma->vm_pgoff] = NULL; + mutex_unlock(&q->mutex); + kfree(qfr); + } } static const struct vm_operations_struct uacce_vm_ops = { @@ -574,12 +577,6 @@ void uacce_remove(struct uacce_device *uacce) if (!uacce) return; - /* - * unmap remaining mapping from user space, preventing user still - * access the mmaped area while parent device is already removed - */ - if (uacce->inode) - unmap_mapping_range(uacce->inode->i_mapping, 0, 0, 1); /* * uacce_fops_open() may be running concurrently, even after we remove @@ -597,6 +594,12 @@ void uacce_remove(struct uacce_device *uacce) uacce_put_queue(q); mutex_unlock(&q->mutex); uacce_unbind_queue(q); + + /* + * unmap remaining mapping from user space, preventing user still + * access the mmaped area while parent device is already removed + */ + unmap_mapping_range(q->mapping, 0, 0, 1); } /* disable sva now since no opened queues */ diff --git a/drivers/misc/xilinx_sdfec.c b/drivers/misc/xilinx_sdfec.c index cb9506f9cbd07077756625a9621580a6ec6269b9..270ff4c5971a1ab186d5500a8631fe1d80fe199f 100644 --- a/drivers/misc/xilinx_sdfec.c +++ b/drivers/misc/xilinx_sdfec.c @@ -855,16 +855,6 @@ static int xsdfec_cfg_axi_streams(struct xsdfec_dev *xsdfec) return 0; } -static int xsdfec_dev_open(struct inode *iptr, struct file *fptr) -{ - return 0; -} - -static int xsdfec_dev_release(struct inode *iptr, struct file *fptr) -{ - return 0; -} - static int xsdfec_start(struct xsdfec_dev *xsdfec) { u32 regread; @@ -1030,8 +1020,6 @@ static __poll_t xsdfec_poll(struct file *file, poll_table *wait) static const struct file_operations xsdfec_fops = { .owner = THIS_MODULE, - .open = xsdfec_dev_open, - .release = xsdfec_dev_release, .unlocked_ioctl = xsdfec_dev_ioctl, .poll = xsdfec_poll, .compat_ioctl = compat_ptr_ioctl, diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c index d920c417838930214b7d9c77fc4208d66c177e6e..f701efb1fa785518ada2f2ef8f1f504cc7e4f726 100644 --- a/drivers/mmc/core/block.c +++ b/drivers/mmc/core/block.c @@ -178,6 +178,7 @@ static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq, int recovery_mode, struct mmc_queue *mq); static void mmc_blk_hsq_req_done(struct mmc_request *mrq); +static int mmc_spi_err_check(struct mmc_card *card); static struct mmc_blk_data *mmc_blk_get(struct gendisk *disk) { @@ -358,15 +359,15 @@ static const struct attribute_group *mmc_disk_attr_groups[] = { NULL, }; -static int mmc_blk_open(struct block_device *bdev, fmode_t mode) +static int mmc_blk_open(struct gendisk *disk, blk_mode_t mode) { - struct mmc_blk_data *md = mmc_blk_get(bdev->bd_disk); + struct mmc_blk_data *md = mmc_blk_get(disk); int ret = -ENXIO; mutex_lock(&block_mutex); if (md) { ret = 0; - if ((mode & FMODE_WRITE) && md->read_only) { + if ((mode & BLK_OPEN_WRITE) && md->read_only) { mmc_blk_put(md); ret = -EROFS; } @@ -376,7 +377,7 @@ static int mmc_blk_open(struct block_device *bdev, fmode_t mode) return ret; } -static void mmc_blk_release(struct gendisk *disk, fmode_t mode) +static void mmc_blk_release(struct gendisk *disk) { struct mmc_blk_data *md = disk->private_data; @@ -608,6 +609,11 @@ static int __mmc_blk_ioctl_cmd(struct mmc_card *card, struct mmc_blk_data *md, if ((card->host->caps & MMC_CAP_WAIT_WHILE_BUSY) && use_r1b_resp) return 0; + if (mmc_host_is_spi(card->host)) { + if (idata->ic.write_flag || r1b_resp || cmd.flags & MMC_RSP_SPI_BUSY) + return mmc_spi_err_check(card); + return err; + } /* Ensure RPMB/R1B command has completed by polling with CMD13. */ if (idata->rpmb || r1b_resp) err = mmc_poll_for_busy(card, busy_timeout_ms, false, @@ -757,7 +763,7 @@ static int mmc_blk_check_blkdev(struct block_device *bdev) return 0; } -static int mmc_blk_ioctl(struct block_device *bdev, fmode_t mode, +static int mmc_blk_ioctl(struct block_device *bdev, blk_mode_t mode, unsigned int cmd, unsigned long arg) { struct mmc_blk_data *md; @@ -794,7 +800,7 @@ static int mmc_blk_ioctl(struct block_device *bdev, fmode_t mode, } #ifdef CONFIG_COMPAT -static int mmc_blk_compat_ioctl(struct block_device *bdev, fmode_t mode, +static int mmc_blk_compat_ioctl(struct block_device *bdev, blk_mode_t mode, unsigned int cmd, unsigned long arg) { return mmc_blk_ioctl(bdev, mode, cmd, (unsigned long) compat_ptr(arg)); @@ -2505,9 +2511,9 @@ static struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card, string_get_size((u64)size, 512, STRING_UNITS_2, cap_str, sizeof(cap_str)); - pr_info("%s: %s %s %s %s\n", + pr_info("%s: %s %s %s%s\n", md->disk->disk_name, mmc_card_id(card), mmc_card_name(card), - cap_str, md->read_only ? "(ro)" : ""); + cap_str, md->read_only ? " (ro)" : ""); /* used in ->open, must be set before add_disk: */ if (area_type == MMC_BLK_DATA_AREA_MAIN) @@ -2899,12 +2905,12 @@ static const struct file_operations mmc_dbg_ext_csd_fops = { .llseek = default_llseek, }; -static int mmc_blk_add_debugfs(struct mmc_card *card, struct mmc_blk_data *md) +static void mmc_blk_add_debugfs(struct mmc_card *card, struct mmc_blk_data *md) { struct dentry *root; if (!card->debugfs_root) - return 0; + return; root = card->debugfs_root; @@ -2913,19 +2919,13 @@ static int mmc_blk_add_debugfs(struct mmc_card *card, struct mmc_blk_data *md) debugfs_create_file_unsafe("status", 0400, root, card, &mmc_dbg_card_status_fops); - if (!md->status_dentry) - return -EIO; } if (mmc_card_mmc(card)) { md->ext_csd_dentry = debugfs_create_file("ext_csd", S_IRUSR, root, card, &mmc_dbg_ext_csd_fops); - if (!md->ext_csd_dentry) - return -EIO; } - - return 0; } static void mmc_blk_remove_debugfs(struct mmc_card *card, @@ -2934,22 +2934,17 @@ static void mmc_blk_remove_debugfs(struct mmc_card *card, if (!card->debugfs_root) return; - if (!IS_ERR_OR_NULL(md->status_dentry)) { - debugfs_remove(md->status_dentry); - md->status_dentry = NULL; - } + debugfs_remove(md->status_dentry); + md->status_dentry = NULL; - if (!IS_ERR_OR_NULL(md->ext_csd_dentry)) { - debugfs_remove(md->ext_csd_dentry); - md->ext_csd_dentry = NULL; - } + debugfs_remove(md->ext_csd_dentry); + md->ext_csd_dentry = NULL; } #else -static int mmc_blk_add_debugfs(struct mmc_card *card, struct mmc_blk_data *md) +static void mmc_blk_add_debugfs(struct mmc_card *card, struct mmc_blk_data *md) { - return 0; } static void mmc_blk_remove_debugfs(struct mmc_card *card, diff --git a/drivers/mmc/core/card.h b/drivers/mmc/core/card.h index cfdd1ff40b865e4a4a8b4be002170106f4fc3e57..4edf9057fa79d320ef24dd47f066f1eb32c47600 100644 --- a/drivers/mmc/core/card.h +++ b/drivers/mmc/core/card.h @@ -53,6 +53,10 @@ struct mmc_fixup { unsigned int manfid; unsigned short oemid; + /* Manufacturing date */ + unsigned short year; + unsigned char month; + /* SDIO-specific fields. You can use SDIO_ANY_ID here of course */ u16 cis_vendor, cis_device; @@ -68,6 +72,8 @@ struct mmc_fixup { #define CID_MANFID_ANY (-1u) #define CID_OEMID_ANY ((unsigned short) -1) +#define CID_YEAR_ANY ((unsigned short) -1) +#define CID_MONTH_ANY ((unsigned char) -1) #define CID_NAME_ANY (NULL) #define EXT_CSD_REV_ANY (-1u) @@ -81,17 +87,21 @@ struct mmc_fixup { #define CID_MANFID_APACER 0x27 #define CID_MANFID_KINGSTON 0x70 #define CID_MANFID_HYNIX 0x90 +#define CID_MANFID_KINGSTON_SD 0x9F #define CID_MANFID_NUMONYX 0xFE #define END_FIXUP { NULL } -#define _FIXUP_EXT(_name, _manfid, _oemid, _rev_start, _rev_end, \ - _cis_vendor, _cis_device, \ - _fixup, _data, _ext_csd_rev) \ +#define _FIXUP_EXT(_name, _manfid, _oemid, _year, _month, \ + _rev_start, _rev_end, \ + _cis_vendor, _cis_device, \ + _fixup, _data, _ext_csd_rev) \ { \ .name = (_name), \ .manfid = (_manfid), \ .oemid = (_oemid), \ + .year = (_year), \ + .month = (_month), \ .rev_start = (_rev_start), \ .rev_end = (_rev_end), \ .cis_vendor = (_cis_vendor), \ @@ -103,8 +113,8 @@ struct mmc_fixup { #define MMC_FIXUP_REV(_name, _manfid, _oemid, _rev_start, _rev_end, \ _fixup, _data, _ext_csd_rev) \ - _FIXUP_EXT(_name, _manfid, \ - _oemid, _rev_start, _rev_end, \ + _FIXUP_EXT(_name, _manfid, _oemid, CID_YEAR_ANY, CID_MONTH_ANY, \ + _rev_start, _rev_end, \ SDIO_ANY_ID, SDIO_ANY_ID, \ _fixup, _data, _ext_csd_rev) \ @@ -118,8 +128,9 @@ struct mmc_fixup { _ext_csd_rev) #define SDIO_FIXUP(_vendor, _device, _fixup, _data) \ - _FIXUP_EXT(CID_NAME_ANY, CID_MANFID_ANY, \ - CID_OEMID_ANY, 0, -1ull, \ + _FIXUP_EXT(CID_NAME_ANY, CID_MANFID_ANY, CID_OEMID_ANY, \ + CID_YEAR_ANY, CID_MONTH_ANY, \ + 0, -1ull, \ _vendor, _device, \ _fixup, _data, EXT_CSD_REV_ANY) \ @@ -264,4 +275,9 @@ static inline int mmc_card_broken_sd_discard(const struct mmc_card *c) return c->quirks & MMC_QUIRK_BROKEN_SD_DISCARD; } +static inline int mmc_card_broken_sd_cache(const struct mmc_card *c) +{ + return c->quirks & MMC_QUIRK_BROKEN_SD_CACHE; +} + #endif diff --git a/drivers/mmc/core/quirks.h b/drivers/mmc/core/quirks.h index 29b9497936df99d73e293babf7117d4ca53da2ce..32b64b564fb1fd774b1546d0f21c918647e71159 100644 --- a/drivers/mmc/core/quirks.h +++ b/drivers/mmc/core/quirks.h @@ -53,6 +53,15 @@ static const struct mmc_fixup __maybe_unused mmc_blk_fixups[] = { MMC_FIXUP("MMC32G", CID_MANFID_TOSHIBA, CID_OEMID_ANY, add_quirk_mmc, MMC_QUIRK_BLK_NO_CMD23), + /* + * Kingston Canvas Go! Plus microSD cards never finish SD cache flush. + * This has so far only been observed on cards from 11/2019, while new + * cards from 2023/05 do not exhibit this behavior. + */ + _FIXUP_EXT("SD64G", CID_MANFID_KINGSTON_SD, 0x5449, 2019, 11, + 0, -1ull, SDIO_ANY_ID, SDIO_ANY_ID, add_quirk_sd, + MMC_QUIRK_BROKEN_SD_CACHE, EXT_CSD_REV_ANY), + /* * Some SD cards lockup while using CMD23 multiblock transfers. */ @@ -100,6 +109,20 @@ static const struct mmc_fixup __maybe_unused mmc_blk_fixups[] = { MMC_FIXUP("V10016", CID_MANFID_KINGSTON, CID_OEMID_ANY, add_quirk_mmc, MMC_QUIRK_TRIM_BROKEN), + /* + * Micron MTFC4GACAJCN-1M advertises TRIM but it does not seems to + * support being used to offload WRITE_ZEROES. + */ + MMC_FIXUP("Q2J54A", CID_MANFID_MICRON, 0x014e, add_quirk_mmc, + MMC_QUIRK_TRIM_BROKEN), + + /* + * Kingston EMMC04G-M627 advertises TRIM but it does not seems to + * support being used to offload WRITE_ZEROES. + */ + MMC_FIXUP("M62704", CID_MANFID_KINGSTON, 0x0100, add_quirk_mmc, + MMC_QUIRK_TRIM_BROKEN), + /* * Some SD cards reports discard support while they don't */ @@ -209,6 +232,10 @@ static inline void mmc_fixup_device(struct mmc_card *card, if (f->of_compatible && !mmc_fixup_of_compatible_match(card, f->of_compatible)) continue; + if (f->year != CID_YEAR_ANY && f->year != card->cid.year) + continue; + if (f->month != CID_MONTH_ANY && f->month != card->cid.month) + continue; dev_dbg(&card->dev, "calling %ps\n", f->vendor_fixup); f->vendor_fixup(card, f->data); diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index 72b664ed90cf6b7f5cc2c978eb7501d428427389..246ce027ae0aac41fe09ad6ec2db2b2b07ba8867 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c @@ -1170,7 +1170,7 @@ static int sd_parse_ext_reg_perf(struct mmc_card *card, u8 fno, u8 page, card->ext_perf.feature_support |= SD_EXT_PERF_HOST_MAINT; /* Cache support at bit 0. */ - if (reg_buf[4] & BIT(0)) + if ((reg_buf[4] & BIT(0)) && !mmc_card_broken_sd_cache(card)) card->ext_perf.feature_support |= SD_EXT_PERF_CACHE; /* Command queue support indicated via queue depth bits (0 to 4). */ diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index 9f793892123c2c835de3acb2e85066fe08acaf1b..159a3e9490aed858206d265278460c0bbee0c057 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig @@ -550,7 +550,7 @@ config MMC_SDHCI_MSM depends on MMC_SDHCI_PLTFM select MMC_SDHCI_IO_ACCESSORS select MMC_CQHCI - select QCOM_SCM if MMC_CRYPTO + select QCOM_INLINE_CRYPTO_ENGINE if MMC_CRYPTO help This selects the Secure Digital Host Controller Interface (SDHCI) support present in Qualcomm SOCs. The controller supports diff --git a/drivers/mmc/host/bcm2835.c b/drivers/mmc/host/bcm2835.c index 8648f7e63ca1a6554ea40071c244778f1d9fb8de..eea208856ce0d0de6b5cc3cfd8c50474d4e9f317 100644 --- a/drivers/mmc/host/bcm2835.c +++ b/drivers/mmc/host/bcm2835.c @@ -1403,8 +1403,8 @@ static int bcm2835_probe(struct platform_device *pdev) host->max_clk = clk_get_rate(clk); host->irq = platform_get_irq(pdev, 0); - if (host->irq <= 0) { - ret = -EINVAL; + if (host->irq < 0) { + ret = host->irq; goto err; } diff --git a/drivers/mmc/host/cqhci.h b/drivers/mmc/host/cqhci.h index ba9387ed90eb6fc4f40ea07efd1e70913da38091..1a12e40a02e670a3704a20226fac3b9598decb7a 100644 --- a/drivers/mmc/host/cqhci.h +++ b/drivers/mmc/host/cqhci.h @@ -5,6 +5,7 @@ #define LINUX_MMC_CQHCI_H #include +#include #include #include #include @@ -23,6 +24,8 @@ /* capabilities */ #define CQHCI_CAP 0x04 #define CQHCI_CAP_CS 0x10000000 /* Crypto Support */ +#define CQHCI_CAP_ITCFMUL GENMASK(15, 12) +#define CQHCI_ITCFMUL(x) FIELD_GET(CQHCI_CAP_ITCFMUL, (x)) /* configuration */ #define CQHCI_CFG 0x08 diff --git a/drivers/mmc/host/dw_mmc-bluefield.c b/drivers/mmc/host/dw_mmc-bluefield.c index 10baf122bc15e4b1dddadc2d37c707e11d39c5f0..4747e5698f488a361b1334543b4d08b5b7145e2d 100644 --- a/drivers/mmc/host/dw_mmc-bluefield.c +++ b/drivers/mmc/host/dw_mmc-bluefield.c @@ -52,7 +52,7 @@ static int dw_mci_bluefield_probe(struct platform_device *pdev) static struct platform_driver dw_mci_bluefield_pltfm_driver = { .probe = dw_mci_bluefield_probe, - .remove = dw_mci_pltfm_remove, + .remove_new = dw_mci_pltfm_remove, .driver = { .name = "dwmmc_bluefield", .probe_type = PROBE_PREFER_ASYNCHRONOUS, diff --git a/drivers/mmc/host/dw_mmc-k3.c b/drivers/mmc/host/dw_mmc-k3.c index 0311a37dd4abfafdecc5030b992637d550a20b5e..e8ee7c43f60b28bff0f7e66036312c52c0c4302e 100644 --- a/drivers/mmc/host/dw_mmc-k3.c +++ b/drivers/mmc/host/dw_mmc-k3.c @@ -470,7 +470,7 @@ static const struct dev_pm_ops dw_mci_k3_dev_pm_ops = { static struct platform_driver dw_mci_k3_pltfm_driver = { .probe = dw_mci_k3_probe, - .remove = dw_mci_pltfm_remove, + .remove_new = dw_mci_pltfm_remove, .driver = { .name = "dwmmc_k3", .probe_type = PROBE_PREFER_ASYNCHRONOUS, diff --git a/drivers/mmc/host/dw_mmc-pltfm.c b/drivers/mmc/host/dw_mmc-pltfm.c index 48b7da2b86b3b9e0141644a02c3840094c1759d4..2353fadceda1181fe0592e5e03dfd005ebe79016 100644 --- a/drivers/mmc/host/dw_mmc-pltfm.c +++ b/drivers/mmc/host/dw_mmc-pltfm.c @@ -121,18 +121,17 @@ static int dw_mci_pltfm_probe(struct platform_device *pdev) return dw_mci_pltfm_register(pdev, drv_data); } -int dw_mci_pltfm_remove(struct platform_device *pdev) +void dw_mci_pltfm_remove(struct platform_device *pdev) { struct dw_mci *host = platform_get_drvdata(pdev); dw_mci_remove(host); - return 0; } EXPORT_SYMBOL_GPL(dw_mci_pltfm_remove); static struct platform_driver dw_mci_pltfm_driver = { .probe = dw_mci_pltfm_probe, - .remove = dw_mci_pltfm_remove, + .remove_new = dw_mci_pltfm_remove, .driver = { .name = "dw_mmc", .probe_type = PROBE_PREFER_ASYNCHRONOUS, diff --git a/drivers/mmc/host/dw_mmc-pltfm.h b/drivers/mmc/host/dw_mmc-pltfm.h index 2d50d7da2e3687a4968d7ac7e57f2c0c1926e732..64cf7522a3d49f2febc71daba0c9bb4b28eface3 100644 --- a/drivers/mmc/host/dw_mmc-pltfm.h +++ b/drivers/mmc/host/dw_mmc-pltfm.h @@ -10,7 +10,7 @@ extern int dw_mci_pltfm_register(struct platform_device *pdev, const struct dw_mci_drv_data *drv_data); -extern int dw_mci_pltfm_remove(struct platform_device *pdev); +extern void dw_mci_pltfm_remove(struct platform_device *pdev); extern const struct dev_pm_ops dw_mci_pltfm_pmops; #endif /* _DW_MMC_PLTFM_H_ */ diff --git a/drivers/mmc/host/dw_mmc-starfive.c b/drivers/mmc/host/dw_mmc-starfive.c index dab1508bf83c67ea8cbcf3d07d6f3a207930735a..fd05a648a8bb7c9e30c68120f787b09a53902f47 100644 --- a/drivers/mmc/host/dw_mmc-starfive.c +++ b/drivers/mmc/host/dw_mmc-starfive.c @@ -172,7 +172,7 @@ static int dw_mci_starfive_probe(struct platform_device *pdev) static struct platform_driver dw_mci_starfive_driver = { .probe = dw_mci_starfive_probe, - .remove = dw_mci_pltfm_remove, + .remove_new = dw_mci_pltfm_remove, .driver = { .name = "dwmmc_starfive", .probe_type = PROBE_PREFER_ASYNCHRONOUS, diff --git a/drivers/mmc/host/litex_mmc.c b/drivers/mmc/host/litex_mmc.c index 39c6707fdfdbcdb160902abcc377794d471bd3bf..9af6b0902efe1462080ee492ba9b12ff998eec64 100644 --- a/drivers/mmc/host/litex_mmc.c +++ b/drivers/mmc/host/litex_mmc.c @@ -649,6 +649,7 @@ static struct platform_driver litex_mmc_driver = { .driver = { .name = "litex-mmc", .of_match_table = litex_match, + .probe_type = PROBE_PREFER_ASYNCHRONOUS, }, }; module_platform_driver(litex_mmc_driver); diff --git a/drivers/mmc/host/meson-gx-mmc.c b/drivers/mmc/host/meson-gx-mmc.c index b8514d9d5e736d6ed1a3805940722957cb8fb56c..ee9a25b900aec98f5c008b74adb42a7b2e80d6f0 100644 --- a/drivers/mmc/host/meson-gx-mmc.c +++ b/drivers/mmc/host/meson-gx-mmc.c @@ -991,11 +991,8 @@ static irqreturn_t meson_mmc_irq(int irq, void *dev_id) if (data && !cmd->error) data->bytes_xfered = data->blksz * data->blocks; - if (meson_mmc_bounce_buf_read(data) || - meson_mmc_get_next_command(cmd)) - ret = IRQ_WAKE_THREAD; - else - ret = IRQ_HANDLED; + + return IRQ_WAKE_THREAD; } out: @@ -1007,9 +1004,6 @@ static irqreturn_t meson_mmc_irq(int irq, void *dev_id) writel(start, host->regs + SD_EMMC_START); } - if (ret == IRQ_HANDLED) - meson_mmc_request_done(host->mmc, cmd->mrq); - return ret; } @@ -1192,8 +1186,8 @@ static int meson_mmc_probe(struct platform_device *pdev) return PTR_ERR(host->regs); host->irq = platform_get_irq(pdev, 0); - if (host->irq <= 0) - return -EINVAL; + if (host->irq < 0) + return host->irq; cd_irq = platform_get_irq_optional(pdev, 1); mmc_gpio_set_cd_irq(mmc, cd_irq); diff --git a/drivers/mmc/host/meson-mx-sdhc-mmc.c b/drivers/mmc/host/meson-mx-sdhc-mmc.c index da85c2f2acb83f3072091f416f0a8c2277ed0c92..97168cdfa8e982c10ebf332af1533bbb3fe40821 100644 --- a/drivers/mmc/host/meson-mx-sdhc-mmc.c +++ b/drivers/mmc/host/meson-mx-sdhc-mmc.c @@ -776,6 +776,11 @@ static void meson_mx_sdhc_init_hw(struct mmc_host *mmc) regmap_write(host->regmap, MESON_SDHC_ISTA, MESON_SDHC_ISTA_ALL_IRQS); } +static void meason_mx_mmc_free_host(void *data) +{ + mmc_free_host(data); +} + static int meson_mx_sdhc_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -788,8 +793,7 @@ static int meson_mx_sdhc_probe(struct platform_device *pdev) if (!mmc) return -ENOMEM; - ret = devm_add_action_or_reset(dev, (void(*)(void *))mmc_free_host, - mmc); + ret = devm_add_action_or_reset(dev, meason_mx_mmc_free_host, mmc); if (ret) { dev_err(dev, "Failed to register mmc_free_host action\n"); return ret; diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c index f2b2e8b0574e8a8c02bcce349e9b0e7d307f3ee1..769b34afa835dce21006a64f1982f0e9cd18e7c8 100644 --- a/drivers/mmc/host/mmci.c +++ b/drivers/mmc/host/mmci.c @@ -37,6 +37,7 @@ #include #include #include +#include #include #include @@ -270,6 +271,7 @@ static struct variant_data variant_stm32_sdmmc = { .datactrl_any_blocksz = true, .datactrl_mask_sdio = MCI_DPSM_ST_SDIOEN, .stm32_idmabsize_mask = GENMASK(12, 5), + .stm32_idmabsize_align = BIT(5), .busy_timeout = true, .busy_detect = true, .busy_detect_flag = MCI_STM32_BUSYD0, @@ -296,6 +298,35 @@ static struct variant_data variant_stm32_sdmmcv2 = { .datactrl_any_blocksz = true, .datactrl_mask_sdio = MCI_DPSM_ST_SDIOEN, .stm32_idmabsize_mask = GENMASK(16, 5), + .stm32_idmabsize_align = BIT(5), + .dma_lli = true, + .busy_timeout = true, + .busy_detect = true, + .busy_detect_flag = MCI_STM32_BUSYD0, + .busy_detect_mask = MCI_STM32_BUSYD0ENDMASK, + .init = sdmmc_variant_init, +}; + +static struct variant_data variant_stm32_sdmmcv3 = { + .fifosize = 256 * 4, + .fifohalfsize = 128 * 4, + .f_max = 267000000, + .stm32_clkdiv = true, + .cmdreg_cpsm_enable = MCI_CPSM_STM32_ENABLE, + .cmdreg_lrsp_crc = MCI_CPSM_STM32_LRSP_CRC, + .cmdreg_srsp_crc = MCI_CPSM_STM32_SRSP_CRC, + .cmdreg_srsp = MCI_CPSM_STM32_SRSP, + .cmdreg_stop = MCI_CPSM_STM32_CMDSTOP, + .data_cmd_enable = MCI_CPSM_STM32_CMDTRANS, + .irq_pio_mask = MCI_IRQ_PIO_STM32_MASK, + .datactrl_first = true, + .datacnt_useless = true, + .datalength_bits = 25, + .datactrl_blocksz = 14, + .datactrl_any_blocksz = true, + .datactrl_mask_sdio = MCI_DPSM_ST_SDIOEN, + .stm32_idmabsize_mask = GENMASK(16, 6), + .stm32_idmabsize_align = BIT(6), .dma_lli = true, .busy_timeout = true, .busy_detect = true, @@ -654,10 +685,52 @@ static u32 ux500v2_get_dctrl_cfg(struct mmci_host *host) return MCI_DPSM_ENABLE | (host->data->blksz << 16); } -static bool ux500_busy_complete(struct mmci_host *host, u32 status, u32 err_msk) +static void ux500_busy_clear_mask_done(struct mmci_host *host) { void __iomem *base = host->base; + writel(host->variant->busy_detect_mask, base + MMCICLEAR); + writel(readl(base + MMCIMASK0) & + ~host->variant->busy_detect_mask, base + MMCIMASK0); + host->busy_state = MMCI_BUSY_DONE; + host->busy_status = 0; +} + +/* + * ux500_busy_complete() - this will wait until the busy status + * goes off, saving any status that occur in the meantime into + * host->busy_status until we know the card is not busy any more. + * The function returns true when the busy detection is ended + * and we should continue processing the command. + * + * The Ux500 typically fires two IRQs over a busy cycle like this: + * + * DAT0 busy +-----------------+ + * | | + * DAT0 not busy ----+ +-------- + * + * ^ ^ + * | | + * IRQ1 IRQ2 + */ +static bool ux500_busy_complete(struct mmci_host *host, struct mmc_command *cmd, + u32 status, u32 err_msk) +{ + void __iomem *base = host->base; + int retries = 10; + + if (status & err_msk) { + /* Stop any ongoing busy detection if an error occurs */ + ux500_busy_clear_mask_done(host); + goto out_ret_state; + } + + /* + * The state transitions are encoded in a state machine crossing + * the edges in this switch statement. + */ + switch (host->busy_state) { + /* * Before unmasking for the busy end IRQ, confirm that the * command was sent successfully. To keep track of having a @@ -667,19 +740,33 @@ static bool ux500_busy_complete(struct mmci_host *host, u32 status, u32 err_msk) * Note that, the card may need a couple of clock cycles before * it starts signaling busy on DAT0, hence re-read the * MMCISTATUS register here, to allow the busy bit to be set. - * Potentially we may even need to poll the register for a - * while, to allow it to be set, but tests indicates that it - * isn't needed. */ - if (!host->busy_status && !(status & err_msk) && - (readl(base + MMCISTATUS) & host->variant->busy_detect_flag)) { - writel(readl(base + MMCIMASK0) | - host->variant->busy_detect_mask, - base + MMCIMASK0); - + case MMCI_BUSY_DONE: + /* + * Save the first status register read to be sure to catch + * all bits that may be lost will retrying. If the command + * is still busy this will result in assigning 0 to + * host->busy_status, which is what it should be in IDLE. + */ host->busy_status = status & (MCI_CMDSENT | MCI_CMDRESPEND); - return false; - } + while (retries) { + status = readl(base + MMCISTATUS); + /* Keep accumulating status bits */ + host->busy_status |= status & (MCI_CMDSENT | MCI_CMDRESPEND); + if (status & host->variant->busy_detect_flag) { + writel(readl(base + MMCIMASK0) | + host->variant->busy_detect_mask, + base + MMCIMASK0); + host->busy_state = MMCI_BUSY_WAITING_FOR_START_IRQ; + schedule_delayed_work(&host->ux500_busy_timeout_work, + msecs_to_jiffies(cmd->busy_timeout)); + goto out_ret_state; + } + retries--; + } + dev_dbg(mmc_dev(host->mmc), "no busy signalling in time\n"); + ux500_busy_clear_mask_done(host); + break; /* * If there is a command in-progress that has been successfully @@ -692,27 +779,39 @@ static bool ux500_busy_complete(struct mmci_host *host, u32 status, u32 err_msk) * both the start and the end interrupts needs to be cleared, * one after the other. So, clear the busy start IRQ here. */ - if (host->busy_status && - (status & host->variant->busy_detect_flag)) { - writel(host->variant->busy_detect_mask, base + MMCICLEAR); - return false; - } + case MMCI_BUSY_WAITING_FOR_START_IRQ: + if (status & host->variant->busy_detect_flag) { + host->busy_status |= status & (MCI_CMDSENT | MCI_CMDRESPEND); + writel(host->variant->busy_detect_mask, base + MMCICLEAR); + host->busy_state = MMCI_BUSY_WAITING_FOR_END_IRQ; + } else { + dev_dbg(mmc_dev(host->mmc), + "lost busy status when waiting for busy start IRQ\n"); + cancel_delayed_work(&host->ux500_busy_timeout_work); + ux500_busy_clear_mask_done(host); + } + break; - /* - * If there is a command in-progress that has been successfully - * sent and the busy bit isn't set, it means we have received - * the busy end IRQ. Clear and mask the IRQ, then continue to - * process the command. - */ - if (host->busy_status) { - writel(host->variant->busy_detect_mask, base + MMCICLEAR); + case MMCI_BUSY_WAITING_FOR_END_IRQ: + if (!(status & host->variant->busy_detect_flag)) { + host->busy_status |= status & (MCI_CMDSENT | MCI_CMDRESPEND); + writel(host->variant->busy_detect_mask, base + MMCICLEAR); + cancel_delayed_work(&host->ux500_busy_timeout_work); + ux500_busy_clear_mask_done(host); + } else { + dev_dbg(mmc_dev(host->mmc), + "busy status still asserted when handling busy end IRQ - will keep waiting\n"); + } + break; - writel(readl(base + MMCIMASK0) & - ~host->variant->busy_detect_mask, base + MMCIMASK0); - host->busy_status = 0; + default: + dev_dbg(mmc_dev(host->mmc), "fell through on state %d\n", + host->busy_state); + break; } - return true; +out_ret_state: + return (host->busy_state == MMCI_BUSY_DONE); } /* @@ -1214,6 +1313,7 @@ static void mmci_start_command(struct mmci_host *host, struct mmc_command *cmd, u32 c) { void __iomem *base = host->base; + bool busy_resp = cmd->flags & MMC_RSP_BUSY; unsigned long long clks; dev_dbg(mmc_dev(host->mmc), "op %02x arg %08x flags %08x\n", @@ -1238,10 +1338,14 @@ mmci_start_command(struct mmci_host *host, struct mmc_command *cmd, u32 c) c |= host->variant->cmdreg_srsp; } - if (host->variant->busy_timeout && cmd->flags & MMC_RSP_BUSY) { - if (!cmd->busy_timeout) - cmd->busy_timeout = 10 * MSEC_PER_SEC; + host->busy_status = 0; + host->busy_state = MMCI_BUSY_DONE; + /* Assign a default timeout if the core does not provide one */ + if (busy_resp && !cmd->busy_timeout) + cmd->busy_timeout = 10 * MSEC_PER_SEC; + + if (busy_resp && host->variant->busy_timeout) { if (cmd->busy_timeout > host->mmc->max_busy_timeout) clks = (unsigned long long)host->mmc->max_busy_timeout * host->cclk; else @@ -1382,7 +1486,7 @@ mmci_cmd_irq(struct mmci_host *host, struct mmc_command *cmd, /* Handle busy detection on DAT0 if the variant supports it. */ if (busy_resp && host->variant->busy_detect) - if (!host->ops->busy_complete(host, status, err_msk)) + if (!host->ops->busy_complete(host, cmd, status, err_msk)) return; host->cmd = NULL; @@ -1429,6 +1533,34 @@ mmci_cmd_irq(struct mmci_host *host, struct mmc_command *cmd, } } +/* + * This busy timeout worker is used to "kick" the command IRQ if a + * busy detect IRQ fails to appear in reasonable time. Only used on + * variants with busy detection IRQ delivery. + */ +static void ux500_busy_timeout_work(struct work_struct *work) +{ + struct mmci_host *host = container_of(work, struct mmci_host, + ux500_busy_timeout_work.work); + unsigned long flags; + u32 status; + + spin_lock_irqsave(&host->lock, flags); + + if (host->cmd) { + dev_dbg(mmc_dev(host->mmc), "timeout waiting for busy IRQ\n"); + + /* If we are still busy let's tag on a cmd-timeout error. */ + status = readl(host->base + MMCISTATUS); + if (status & host->variant->busy_detect_flag) + status |= MCI_CMDTIMEOUT; + + mmci_cmd_irq(host, host->cmd, status); + } + + spin_unlock_irqrestore(&host->lock, flags); +} + static int mmci_get_rx_fifocnt(struct mmci_host *host, u32 status, int remain) { return remain - (readl(host->base + MMCIFIFOCNT) << 2); @@ -1735,7 +1867,8 @@ static void mmci_set_max_busy_timeout(struct mmc_host *mmc) return; if (host->variant->busy_timeout && mmc->actual_clock) - max_busy_timeout = ~0UL / (mmc->actual_clock / MSEC_PER_SEC); + max_busy_timeout = U32_MAX / DIV_ROUND_UP(mmc->actual_clock, + MSEC_PER_SEC); mmc->max_busy_timeout = max_busy_timeout; } @@ -2242,6 +2375,10 @@ static int mmci_probe(struct amba_device *dev, goto clk_disable; } + if (host->variant->busy_detect) + INIT_DELAYED_WORK(&host->ux500_busy_timeout_work, + ux500_busy_timeout_work); + writel(MCI_IRQENABLE | variant->start_err, host->base + MMCIMASK0); amba_set_drvdata(dev, mmc); @@ -2440,6 +2577,11 @@ static const struct amba_id mmci_ids[] = { .mask = 0xf0ffffff, .data = &variant_stm32_sdmmcv2, }, + { + .id = 0x00353180, + .mask = 0xf0ffffff, + .data = &variant_stm32_sdmmcv3, + }, /* Qualcomm variants */ { .id = 0x00051180, @@ -2455,6 +2597,7 @@ static struct amba_driver mmci_driver = { .drv = { .name = DRIVER_NAME, .pm = &mmci_dev_pm_ops, + .probe_type = PROBE_PREFER_ASYNCHRONOUS, }, .probe = mmci_probe, .remove = mmci_remove, diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h index e1a9b96a3396f03d149d08791bab6aab20855175..253197f132fca786e6099ad927ce8d7a307b9dc7 100644 --- a/drivers/mmc/host/mmci.h +++ b/drivers/mmc/host/mmci.h @@ -218,6 +218,11 @@ #define MCI_STM32_BUSYD0ENDMASK BIT(21) #define MMCIMASK1 0x040 + +/* STM32 sdmmc data FIFO threshold register */ +#define MMCI_STM32_FIFOTHRR 0x044 +#define MMCI_STM32_THR_MASK GENMASK(3, 0) + #define MMCIFIFOCNT 0x048 #define MMCIFIFO 0x080 /* to 0x0bc */ @@ -227,8 +232,6 @@ #define MMCI_STM32_IDMALLIEN BIT(1) #define MMCI_STM32_IDMABSIZER 0x054 -#define MMCI_STM32_IDMABNDT_SHIFT 5 -#define MMCI_STM32_IDMABNDT_MASK GENMASK(12, 5) #define MMCI_STM32_IDMABASE0R 0x058 @@ -261,6 +264,19 @@ struct clk; struct dma_chan; struct mmci_host; +/** + * enum mmci_busy_state - enumerate the busy detect wait states + * + * This is used for the state machine waiting for different busy detect + * interrupts on hardware that fire a single IRQ for start and end of + * the busy detect phase on DAT0. + */ +enum mmci_busy_state { + MMCI_BUSY_WAITING_FOR_START_IRQ, + MMCI_BUSY_WAITING_FOR_END_IRQ, + MMCI_BUSY_DONE, +}; + /** * struct variant_data - MMCI variant-specific quirks * @clkreg: default value for MCICLOCK register @@ -361,6 +377,7 @@ struct variant_data { u32 opendrain; u8 dma_lli:1; u32 stm32_idmabsize_mask; + u32 stm32_idmabsize_align; void (*init)(struct mmci_host *host); }; @@ -380,7 +397,7 @@ struct mmci_host_ops { void (*dma_error)(struct mmci_host *host); void (*set_clkreg)(struct mmci_host *host, unsigned int desired); void (*set_pwrreg)(struct mmci_host *host, unsigned int pwr); - bool (*busy_complete)(struct mmci_host *host, u32 status, u32 err_msk); + bool (*busy_complete)(struct mmci_host *host, struct mmc_command *cmd, u32 status, u32 err_msk); void (*pre_sig_volt_switch)(struct mmci_host *host); int (*post_sig_volt_switch)(struct mmci_host *host, struct mmc_ios *ios); }; @@ -409,6 +426,7 @@ struct mmci_host { u32 clk_reg; u32 clk_reg_add; u32 datactrl_reg; + enum mmci_busy_state busy_state; u32 busy_status; u32 mask1_reg; u8 vqmmc_enabled:1; @@ -437,6 +455,7 @@ struct mmci_host { void *dma_priv; s32 next_cookie; + struct delayed_work ux500_busy_timeout_work; }; #define dma_inprogress(host) ((host)->dma_in_progress) diff --git a/drivers/mmc/host/mmci_stm32_sdmmc.c b/drivers/mmc/host/mmci_stm32_sdmmc.c index 60bca78a72b19f7ccea58c09e87c10c909eac0a6..35067e1e6cd8017b1bb37683f9dda6169af5cbf1 100644 --- a/drivers/mmc/host/mmci_stm32_sdmmc.c +++ b/drivers/mmc/host/mmci_stm32_sdmmc.c @@ -15,7 +15,6 @@ #include "mmci.h" #define SDMMC_LLI_BUF_LEN PAGE_SIZE -#define SDMMC_IDMA_BURST BIT(MMCI_STM32_IDMABNDT_SHIFT) #define DLYB_CR 0x0 #define DLYB_CR_DEN BIT(0) @@ -34,6 +33,20 @@ #define DLYB_LNG_TIMEOUT_US 1000 #define SDMMC_VSWEND_TIMEOUT_US 10000 +#define SYSCFG_DLYBSD_CR 0x0 +#define DLYBSD_CR_EN BIT(0) +#define DLYBSD_CR_RXTAPSEL_MASK GENMASK(6, 1) +#define DLYBSD_TAPSEL_NB 32 +#define DLYBSD_BYP_EN BIT(16) +#define DLYBSD_BYP_CMD GENMASK(21, 17) +#define DLYBSD_ANTIGLITCH_EN BIT(22) + +#define SYSCFG_DLYBSD_SR 0x4 +#define DLYBSD_SR_LOCK BIT(0) +#define DLYBSD_SR_RXTAPSEL_ACK BIT(1) + +#define DLYBSD_TIMEOUT_1S_IN_US 1000000 + struct sdmmc_lli_desc { u32 idmalar; u32 idmabase; @@ -48,10 +61,21 @@ struct sdmmc_idma { bool use_bounce_buffer; }; +struct sdmmc_dlyb; + +struct sdmmc_tuning_ops { + int (*dlyb_enable)(struct sdmmc_dlyb *dlyb); + void (*set_input_ck)(struct sdmmc_dlyb *dlyb); + int (*tuning_prepare)(struct mmci_host *host); + int (*set_cfg)(struct sdmmc_dlyb *dlyb, int unit __maybe_unused, + int phase, bool sampler __maybe_unused); +}; + struct sdmmc_dlyb { void __iomem *base; u32 unit; u32 max; + struct sdmmc_tuning_ops *ops; }; static int sdmmc_idma_validate_data(struct mmci_host *host, @@ -69,7 +93,8 @@ static int sdmmc_idma_validate_data(struct mmci_host *host, idma->use_bounce_buffer = false; for_each_sg(data->sg, sg, data->sg_len - 1, i) { if (!IS_ALIGNED(sg->offset, sizeof(u32)) || - !IS_ALIGNED(sg->length, SDMMC_IDMA_BURST)) { + !IS_ALIGNED(sg->length, + host->variant->stm32_idmabsize_align)) { dev_dbg(mmc_dev(host->mmc), "unaligned scatterlist: ofst:%x length:%d\n", data->sg->offset, data->sg->length); @@ -293,23 +318,13 @@ static void mmci_sdmmc_set_clkreg(struct mmci_host *host, unsigned int desired) clk |= host->clk_reg_add; clk |= ddr; - /* - * SDMMC_FBCK is selected when an external Delay Block is needed - * with SDR104 or HS200. - */ - if (host->mmc->ios.timing >= MMC_TIMING_UHS_SDR50) { + if (host->mmc->ios.timing >= MMC_TIMING_UHS_SDR50) clk |= MCI_STM32_CLK_BUSSPEED; - if (host->mmc->ios.timing == MMC_TIMING_UHS_SDR104 || - host->mmc->ios.timing == MMC_TIMING_MMC_HS200) { - clk &= ~MCI_STM32_CLK_SEL_MSK; - clk |= MCI_STM32_CLK_SELFBCK; - } - } mmci_write_clkreg(host, clk); } -static void sdmmc_dlyb_input_ck(struct sdmmc_dlyb *dlyb) +static void sdmmc_dlyb_mp15_input_ck(struct sdmmc_dlyb *dlyb) { if (!dlyb || !dlyb->base) return; @@ -326,7 +341,8 @@ static void mmci_sdmmc_set_pwrreg(struct mmci_host *host, unsigned int pwr) /* adds OF options */ pwr = host->pwr_reg_add; - sdmmc_dlyb_input_ck(dlyb); + if (dlyb && dlyb->ops->set_input_ck) + dlyb->ops->set_input_ck(dlyb); if (ios.power_mode == MMC_POWER_OFF) { /* Only a reset could power-off sdmmc */ @@ -371,6 +387,19 @@ static u32 sdmmc_get_dctrl_cfg(struct mmci_host *host) datactrl = mmci_dctrl_blksz(host); + if (host->hw_revision >= 3) { + u32 thr = 0; + + if (host->mmc->ios.timing == MMC_TIMING_UHS_SDR104 || + host->mmc->ios.timing == MMC_TIMING_MMC_HS200) { + thr = ffs(min_t(unsigned int, host->data->blksz, + host->variant->fifosize)); + thr = min_t(u32, thr, MMCI_STM32_THR_MASK); + } + + writel_relaxed(thr, host->base + MMCI_STM32_FIFOTHRR); + } + if (host->mmc->card && mmc_card_sdio(host->mmc->card) && host->data->blocks == 1) datactrl |= MCI_DPSM_STM32_MODE_SDIO; @@ -382,7 +411,8 @@ static u32 sdmmc_get_dctrl_cfg(struct mmci_host *host) return datactrl; } -static bool sdmmc_busy_complete(struct mmci_host *host, u32 status, u32 err_msk) +static bool sdmmc_busy_complete(struct mmci_host *host, struct mmc_command *cmd, + u32 status, u32 err_msk) { void __iomem *base = host->base; u32 busy_d0, busy_d0end, mask, sdmmc_status; @@ -423,8 +453,15 @@ static bool sdmmc_busy_complete(struct mmci_host *host, u32 status, u32 err_msk) return true; } -static void sdmmc_dlyb_set_cfgr(struct sdmmc_dlyb *dlyb, - int unit, int phase, bool sampler) +static int sdmmc_dlyb_mp15_enable(struct sdmmc_dlyb *dlyb) +{ + writel_relaxed(DLYB_CR_DEN, dlyb->base + DLYB_CR); + + return 0; +} + +static int sdmmc_dlyb_mp15_set_cfg(struct sdmmc_dlyb *dlyb, + int unit, int phase, bool sampler) { u32 cfgr; @@ -436,16 +473,18 @@ static void sdmmc_dlyb_set_cfgr(struct sdmmc_dlyb *dlyb, if (!sampler) writel_relaxed(DLYB_CR_DEN, dlyb->base + DLYB_CR); + + return 0; } -static int sdmmc_dlyb_lng_tuning(struct mmci_host *host) +static int sdmmc_dlyb_mp15_prepare(struct mmci_host *host) { struct sdmmc_dlyb *dlyb = host->variant_priv; u32 cfgr; int i, lng, ret; for (i = 0; i <= DLYB_CFGR_UNIT_MAX; i++) { - sdmmc_dlyb_set_cfgr(dlyb, i, DLYB_CFGR_SEL_MAX, true); + dlyb->ops->set_cfg(dlyb, i, DLYB_CFGR_SEL_MAX, true); ret = readl_relaxed_poll_timeout(dlyb->base + DLYB_CFGR, cfgr, (cfgr & DLYB_CFGR_LNGF), @@ -471,14 +510,58 @@ static int sdmmc_dlyb_lng_tuning(struct mmci_host *host) return 0; } +static int sdmmc_dlyb_mp25_enable(struct sdmmc_dlyb *dlyb) +{ + u32 cr, sr; + + cr = readl_relaxed(dlyb->base + SYSCFG_DLYBSD_CR); + cr |= DLYBSD_CR_EN; + + writel_relaxed(cr, dlyb->base + SYSCFG_DLYBSD_CR); + + return readl_relaxed_poll_timeout(dlyb->base + SYSCFG_DLYBSD_SR, + sr, sr & DLYBSD_SR_LOCK, 1, + DLYBSD_TIMEOUT_1S_IN_US); +} + +static int sdmmc_dlyb_mp25_set_cfg(struct sdmmc_dlyb *dlyb, + int unit __maybe_unused, int phase, + bool sampler __maybe_unused) +{ + u32 cr, sr; + + cr = readl_relaxed(dlyb->base + SYSCFG_DLYBSD_CR); + cr &= ~DLYBSD_CR_RXTAPSEL_MASK; + cr |= FIELD_PREP(DLYBSD_CR_RXTAPSEL_MASK, phase); + + writel_relaxed(cr, dlyb->base + SYSCFG_DLYBSD_CR); + + return readl_relaxed_poll_timeout(dlyb->base + SYSCFG_DLYBSD_SR, + sr, sr & DLYBSD_SR_RXTAPSEL_ACK, 1, + DLYBSD_TIMEOUT_1S_IN_US); +} + +static int sdmmc_dlyb_mp25_prepare(struct mmci_host *host) +{ + struct sdmmc_dlyb *dlyb = host->variant_priv; + + dlyb->max = DLYBSD_TAPSEL_NB; + + return 0; +} + static int sdmmc_dlyb_phase_tuning(struct mmci_host *host, u32 opcode) { struct sdmmc_dlyb *dlyb = host->variant_priv; int cur_len = 0, max_len = 0, end_of_len = 0; - int phase; + int phase, ret; for (phase = 0; phase <= dlyb->max; phase++) { - sdmmc_dlyb_set_cfgr(dlyb, dlyb->unit, phase, false); + ret = dlyb->ops->set_cfg(dlyb, dlyb->unit, phase, false); + if (ret) { + dev_err(mmc_dev(host->mmc), "tuning config failed\n"); + return ret; + } if (mmc_send_tuning(host->mmc, opcode, NULL)) { cur_len = 0; @@ -496,10 +579,15 @@ static int sdmmc_dlyb_phase_tuning(struct mmci_host *host, u32 opcode) return -EINVAL; } - writel_relaxed(0, dlyb->base + DLYB_CR); + if (dlyb->ops->set_input_ck) + dlyb->ops->set_input_ck(dlyb); phase = end_of_len - max_len / 2; - sdmmc_dlyb_set_cfgr(dlyb, dlyb->unit, phase, false); + ret = dlyb->ops->set_cfg(dlyb, dlyb->unit, phase, false); + if (ret) { + dev_err(mmc_dev(host->mmc), "tuning reconfig failed\n"); + return ret; + } dev_dbg(mmc_dev(host->mmc), "unit:%d max_dly:%d phase:%d\n", dlyb->unit, dlyb->max, phase); @@ -511,12 +599,33 @@ static int sdmmc_execute_tuning(struct mmc_host *mmc, u32 opcode) { struct mmci_host *host = mmc_priv(mmc); struct sdmmc_dlyb *dlyb = host->variant_priv; + u32 clk; + int ret; + + if ((host->mmc->ios.timing != MMC_TIMING_UHS_SDR104 && + host->mmc->ios.timing != MMC_TIMING_MMC_HS200) || + host->mmc->actual_clock <= 50000000) + return 0; if (!dlyb || !dlyb->base) return -EINVAL; - if (sdmmc_dlyb_lng_tuning(host)) - return -EINVAL; + ret = dlyb->ops->dlyb_enable(dlyb); + if (ret) + return ret; + + /* + * SDMMC_FBCK is selected when an external Delay Block is needed + * with SDR104 or HS200. + */ + clk = host->clk_reg; + clk &= ~MCI_STM32_CLK_SEL_MSK; + clk |= MCI_STM32_CLK_SELFBCK; + mmci_write_clkreg(host, clk); + + ret = dlyb->ops->tuning_prepare(host); + if (ret) + return ret; return sdmmc_dlyb_phase_tuning(host, opcode); } @@ -574,6 +683,19 @@ static struct mmci_host_ops sdmmc_variant_ops = { .post_sig_volt_switch = sdmmc_post_sig_volt_switch, }; +static struct sdmmc_tuning_ops dlyb_tuning_mp15_ops = { + .dlyb_enable = sdmmc_dlyb_mp15_enable, + .set_input_ck = sdmmc_dlyb_mp15_input_ck, + .tuning_prepare = sdmmc_dlyb_mp15_prepare, + .set_cfg = sdmmc_dlyb_mp15_set_cfg, +}; + +static struct sdmmc_tuning_ops dlyb_tuning_mp25_ops = { + .dlyb_enable = sdmmc_dlyb_mp25_enable, + .tuning_prepare = sdmmc_dlyb_mp25_prepare, + .set_cfg = sdmmc_dlyb_mp25_set_cfg, +}; + void sdmmc_variant_init(struct mmci_host *host) { struct device_node *np = host->mmc->parent->of_node; @@ -592,6 +714,11 @@ void sdmmc_variant_init(struct mmci_host *host) return; dlyb->base = base_dlyb; + if (of_device_is_compatible(np, "st,stm32mp25-sdmmc2")) + dlyb->ops = &dlyb_tuning_mp25_ops; + else + dlyb->ops = &dlyb_tuning_mp15_ops; + host->variant_priv = dlyb; host->mmc_ops->execute_tuning = sdmmc_execute_tuning; } diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c index edade0e54a0c284c70ffc2056483779a2764c8a9..02403ff99e0d48e3aa9e3266efd6b9e0779a5ca2 100644 --- a/drivers/mmc/host/mtk-sd.c +++ b/drivers/mmc/host/mtk-sd.c @@ -473,6 +473,7 @@ struct msdc_host { struct msdc_tune_para def_tune_para; /* default tune setting */ struct msdc_tune_para saved_tune_para; /* tune result of CMD21/CMD19 */ struct cqhci_host *cq_host; + u32 cq_ssc1_time; }; static const struct mtk_mmc_compatible mt2701_compat = { @@ -2450,9 +2451,49 @@ static void msdc_hs400_enhanced_strobe(struct mmc_host *mmc, } } +static void msdc_cqe_cit_cal(struct msdc_host *host, u64 timer_ns) +{ + struct mmc_host *mmc = mmc_from_priv(host); + struct cqhci_host *cq_host = mmc->cqe_private; + u8 itcfmul; + u64 hclk_freq, value; + + /* + * On MediaTek SoCs the MSDC controller's CQE uses msdc_hclk as ITCFVAL + * so we multiply/divide the HCLK frequency by ITCFMUL to calculate the + * Send Status Command Idle Timer (CIT) value. + */ + hclk_freq = (u64)clk_get_rate(host->h_clk); + itcfmul = CQHCI_ITCFMUL(cqhci_readl(cq_host, CQHCI_CAP)); + switch (itcfmul) { + case 0x0: + do_div(hclk_freq, 1000); + break; + case 0x1: + do_div(hclk_freq, 100); + break; + case 0x2: + do_div(hclk_freq, 10); + break; + case 0x3: + break; + case 0x4: + hclk_freq = hclk_freq * 10; + break; + default: + host->cq_ssc1_time = 0x40; + return; + } + + value = hclk_freq * timer_ns; + do_div(value, 1000000000); + host->cq_ssc1_time = value; +} + static void msdc_cqe_enable(struct mmc_host *mmc) { struct msdc_host *host = mmc_priv(mmc); + struct cqhci_host *cq_host = mmc->cqe_private; /* enable cmdq irq */ writel(MSDC_INT_CMDQ, host->base + MSDC_INTEN); @@ -2462,6 +2503,9 @@ static void msdc_cqe_enable(struct mmc_host *mmc) msdc_set_busy_timeout(host, 20 * 1000000000ULL, 0); /* default read data timeout 1s */ msdc_set_timeout(host, 1000000000ULL, 0); + + /* Set the send status command idle timer */ + cqhci_writel(cq_host, host->cq_ssc1_time, CQHCI_SSC1); } static void msdc_cqe_disable(struct mmc_host *mmc, bool recovery) @@ -2680,7 +2724,7 @@ static int msdc_drv_probe(struct platform_device *pdev) host->irq = platform_get_irq(pdev, 0); if (host->irq < 0) { - ret = -EINVAL; + ret = host->irq; goto host_free; } @@ -2707,7 +2751,7 @@ static int msdc_drv_probe(struct platform_device *pdev) /* Support for SDIO eint irq ? */ if ((mmc->pm_caps & MMC_PM_WAKE_SDIO_IRQ) && (mmc->pm_caps & MMC_PM_KEEP_POWER)) { - host->eint_irq = platform_get_irq_byname(pdev, "sdio_wakeup"); + host->eint_irq = platform_get_irq_byname_optional(pdev, "sdio_wakeup"); if (host->eint_irq > 0) { host->pins_eint = pinctrl_lookup_state(host->pinctrl, "state_eint"); if (IS_ERR(host->pins_eint)) { @@ -2803,6 +2847,8 @@ static int msdc_drv_probe(struct platform_device *pdev) /* cqhci 16bit length */ /* 0 size, means 65536 so we don't have to -1 here */ mmc->max_seg_size = 64 * 1024; + /* Reduce CIT to 0x40 that corresponds to 2.35us */ + msdc_cqe_cit_cal(host, 2350); } ret = devm_request_irq(&pdev->dev, host->irq, msdc_irq, diff --git a/drivers/mmc/host/mvsdio.c b/drivers/mmc/host/mvsdio.c index 629efbe639c4f6e52548bfad9e2af52a291a6bc3..b4f6a0a2fcb51c540bd735fbdf80235ac7568b6e 100644 --- a/drivers/mmc/host/mvsdio.c +++ b/drivers/mmc/host/mvsdio.c @@ -704,7 +704,7 @@ static int mvsd_probe(struct platform_device *pdev) } irq = platform_get_irq(pdev, 0); if (irq < 0) - return -ENXIO; + return irq; mmc = mmc_alloc_host(sizeof(struct mvsd_host), &pdev->dev); if (!mmc) { diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c index ce78edfb402b2cacc41a10931ff62e433f44c216..6a259563690d6391c717b9d15f8cc95e37ab7fc4 100644 --- a/drivers/mmc/host/omap.c +++ b/drivers/mmc/host/omap.c @@ -26,6 +26,7 @@ #include #include #include +#include #include @@ -111,6 +112,9 @@ struct mmc_omap_slot { struct mmc_request *mrq; struct mmc_omap_host *host; struct mmc_host *mmc; + struct gpio_desc *vsd; + struct gpio_desc *vio; + struct gpio_desc *cover; struct omap_mmc_slot_data *pdata; }; @@ -133,6 +137,7 @@ struct mmc_omap_host { int irq; unsigned char bus_mode; unsigned int reg_shift; + struct gpio_desc *slot_switch; struct work_struct cmd_abort_work; unsigned abort:1; @@ -216,8 +221,13 @@ static void mmc_omap_select_slot(struct mmc_omap_slot *slot, int claimed) if (host->current_slot != slot) { OMAP_MMC_WRITE(host, CON, slot->saved_con & 0xFC00); - if (host->pdata->switch_slot != NULL) - host->pdata->switch_slot(mmc_dev(slot->mmc), slot->id); + if (host->slot_switch) + /* + * With two slots and a simple GPIO switch, setting + * the GPIO to 0 selects slot ID 0, setting it to 1 + * selects slot ID 1. + */ + gpiod_set_value(host->slot_switch, slot->id); host->current_slot = slot; } @@ -297,6 +307,9 @@ static void mmc_omap_release_slot(struct mmc_omap_slot *slot, int clk_enabled) static inline int mmc_omap_cover_is_open(struct mmc_omap_slot *slot) { + /* If we have a GPIO then use that */ + if (slot->cover) + return gpiod_get_value(slot->cover); if (slot->pdata->get_cover_state) return slot->pdata->get_cover_state(mmc_dev(slot->mmc), slot->id); @@ -1106,6 +1119,11 @@ static void mmc_omap_set_power(struct mmc_omap_slot *slot, int power_on, host = slot->host; + if (slot->vsd) + gpiod_set_value(slot->vsd, power_on); + if (slot->vio) + gpiod_set_value(slot->vio, power_on); + if (slot->pdata->set_power != NULL) slot->pdata->set_power(mmc_dev(slot->mmc), slot->id, power_on, vdd); @@ -1240,6 +1258,23 @@ static int mmc_omap_new_slot(struct mmc_omap_host *host, int id) slot->power_mode = MMC_POWER_UNDEFINED; slot->pdata = &host->pdata->slots[id]; + /* Check for some optional GPIO controls */ + slot->vsd = gpiod_get_index_optional(host->dev, "vsd", + id, GPIOD_OUT_LOW); + if (IS_ERR(slot->vsd)) + return dev_err_probe(host->dev, PTR_ERR(slot->vsd), + "error looking up VSD GPIO\n"); + slot->vio = gpiod_get_index_optional(host->dev, "vio", + id, GPIOD_OUT_LOW); + if (IS_ERR(slot->vio)) + return dev_err_probe(host->dev, PTR_ERR(slot->vio), + "error looking up VIO GPIO\n"); + slot->cover = gpiod_get_index_optional(host->dev, "cover", + id, GPIOD_IN); + if (IS_ERR(slot->cover)) + return dev_err_probe(host->dev, PTR_ERR(slot->cover), + "error looking up cover switch GPIO\n"); + host->slots[id] = slot; mmc->caps = 0; @@ -1343,12 +1378,19 @@ static int mmc_omap_probe(struct platform_device *pdev) irq = platform_get_irq(pdev, 0); if (irq < 0) - return -ENXIO; + return irq; host->virt_base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); if (IS_ERR(host->virt_base)) return PTR_ERR(host->virt_base); + host->slot_switch = gpiod_get_optional(host->dev, "switch", + GPIOD_OUT_LOW); + if (IS_ERR(host->slot_switch)) + return dev_err_probe(host->dev, PTR_ERR(host->slot_switch), + "error looking up slot switch GPIO\n"); + + INIT_WORK(&host->slot_release_work, mmc_omap_slot_release_work); INIT_WORK(&host->send_stop_work, mmc_omap_send_stop_work); diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 517dde777413409a0300dcc138cff55e0ad1acdc..1e0f2d7774bd10c467cef1897f14c79874d55e5b 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -1791,9 +1791,11 @@ static int omap_hsmmc_probe(struct platform_device *pdev) } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - irq = platform_get_irq(pdev, 0); - if (res == NULL || irq < 0) + if (!res) return -ENXIO; + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return irq; base = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(base)) diff --git a/drivers/mmc/host/owl-mmc.c b/drivers/mmc/host/owl-mmc.c index 6f9d31a886ba1a306afe3a30af24b07c71ff58fe..1bf22b08b373d2dd7541b63dbd10b9e9c73dc692 100644 --- a/drivers/mmc/host/owl-mmc.c +++ b/drivers/mmc/host/owl-mmc.c @@ -637,7 +637,7 @@ static int owl_mmc_probe(struct platform_device *pdev) owl_host->irq = platform_get_irq(pdev, 0); if (owl_host->irq < 0) { - ret = -EINVAL; + ret = owl_host->irq; goto err_release_channel; } diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c index 8f0e639236b15c4cbb725f52196c52a00483b1d6..edf2e6c14dc6f09970d5583f6369faf05a33153c 100644 --- a/drivers/mmc/host/sdhci-acpi.c +++ b/drivers/mmc/host/sdhci-acpi.c @@ -829,7 +829,7 @@ static int sdhci_acpi_probe(struct platform_device *pdev) host->ops = &sdhci_acpi_ops_dflt; host->irq = platform_get_irq(pdev, 0); if (host->irq < 0) { - err = -EINVAL; + err = host->irq; goto err_free; } diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c index 8ac81d57a3dfe5ceffb767cdab0449a5998ac5d1..1c935b5bafe1e2088116e0a12e3857e2a9cc4e47 100644 --- a/drivers/mmc/host/sdhci-msm.c +++ b/drivers/mmc/host/sdhci-msm.c @@ -13,12 +13,13 @@ #include #include #include -#include #include #include #include #include +#include + #include "sdhci-cqhci.h" #include "sdhci-pltfm.h" #include "cqhci.h" @@ -258,12 +259,14 @@ struct sdhci_msm_variant_info { struct sdhci_msm_host { struct platform_device *pdev; void __iomem *core_mem; /* MSM SDCC mapped address */ - void __iomem *ice_mem; /* MSM ICE mapped address (if available) */ int pwr_irq; /* power irq */ struct clk *bus_clk; /* SDHC bus voter clock */ struct clk *xo_clk; /* TCXO clk needed for FLL feature of cm_dll*/ - /* core, iface, cal, sleep, and ice clocks */ - struct clk_bulk_data bulk_clks[5]; + /* core, iface, cal and sleep clocks */ + struct clk_bulk_data bulk_clks[4]; +#ifdef CONFIG_MMC_CRYPTO + struct qcom_ice *ice; +#endif unsigned long clk_rate; struct mmc_host *mmc; bool use_14lpp_dll_reset; @@ -1804,164 +1807,51 @@ static void sdhci_msm_set_clock(struct sdhci_host *host, unsigned int clock) #ifdef CONFIG_MMC_CRYPTO -#define AES_256_XTS_KEY_SIZE 64 - -/* QCOM ICE registers */ - -#define QCOM_ICE_REG_VERSION 0x0008 - -#define QCOM_ICE_REG_FUSE_SETTING 0x0010 -#define QCOM_ICE_FUSE_SETTING_MASK 0x1 -#define QCOM_ICE_FORCE_HW_KEY0_SETTING_MASK 0x2 -#define QCOM_ICE_FORCE_HW_KEY1_SETTING_MASK 0x4 - -#define QCOM_ICE_REG_BIST_STATUS 0x0070 -#define QCOM_ICE_BIST_STATUS_MASK 0xF0000000 - -#define QCOM_ICE_REG_ADVANCED_CONTROL 0x1000 - -#define sdhci_msm_ice_writel(host, val, reg) \ - writel((val), (host)->ice_mem + (reg)) -#define sdhci_msm_ice_readl(host, reg) \ - readl((host)->ice_mem + (reg)) - -static bool sdhci_msm_ice_supported(struct sdhci_msm_host *msm_host) -{ - struct device *dev = mmc_dev(msm_host->mmc); - u32 regval = sdhci_msm_ice_readl(msm_host, QCOM_ICE_REG_VERSION); - int major = regval >> 24; - int minor = (regval >> 16) & 0xFF; - int step = regval & 0xFFFF; - - /* For now this driver only supports ICE version 3. */ - if (major != 3) { - dev_warn(dev, "Unsupported ICE version: v%d.%d.%d\n", - major, minor, step); - return false; - } - - dev_info(dev, "Found QC Inline Crypto Engine (ICE) v%d.%d.%d\n", - major, minor, step); - - /* If fuses are blown, ICE might not work in the standard way. */ - regval = sdhci_msm_ice_readl(msm_host, QCOM_ICE_REG_FUSE_SETTING); - if (regval & (QCOM_ICE_FUSE_SETTING_MASK | - QCOM_ICE_FORCE_HW_KEY0_SETTING_MASK | - QCOM_ICE_FORCE_HW_KEY1_SETTING_MASK)) { - dev_warn(dev, "Fuses are blown; ICE is unusable!\n"); - return false; - } - return true; -} - -static inline struct clk *sdhci_msm_ice_get_clk(struct device *dev) -{ - return devm_clk_get(dev, "ice"); -} - static int sdhci_msm_ice_init(struct sdhci_msm_host *msm_host, struct cqhci_host *cq_host) { struct mmc_host *mmc = msm_host->mmc; struct device *dev = mmc_dev(mmc); - struct resource *res; + struct qcom_ice *ice; if (!(cqhci_readl(cq_host, CQHCI_CAP) & CQHCI_CAP_CS)) return 0; - res = platform_get_resource_byname(msm_host->pdev, IORESOURCE_MEM, - "ice"); - if (!res) { - dev_warn(dev, "ICE registers not found\n"); - goto disable; - } - - if (!qcom_scm_ice_available()) { - dev_warn(dev, "ICE SCM interface not found\n"); - goto disable; + ice = of_qcom_ice_get(dev); + if (ice == ERR_PTR(-EOPNOTSUPP)) { + dev_warn(dev, "Disabling inline encryption support\n"); + ice = NULL; } - msm_host->ice_mem = devm_ioremap_resource(dev, res); - if (IS_ERR(msm_host->ice_mem)) - return PTR_ERR(msm_host->ice_mem); - - if (!sdhci_msm_ice_supported(msm_host)) - goto disable; + if (IS_ERR_OR_NULL(ice)) + return PTR_ERR_OR_ZERO(ice); + msm_host->ice = ice; mmc->caps2 |= MMC_CAP2_CRYPTO; - return 0; -disable: - dev_warn(dev, "Disabling inline encryption support\n"); return 0; } -static void sdhci_msm_ice_low_power_mode_enable(struct sdhci_msm_host *msm_host) -{ - u32 regval; - - regval = sdhci_msm_ice_readl(msm_host, QCOM_ICE_REG_ADVANCED_CONTROL); - /* - * Enable low power mode sequence - * [0]-0, [1]-0, [2]-0, [3]-E, [4]-0, [5]-0, [6]-0, [7]-0 - */ - regval |= 0x7000; - sdhci_msm_ice_writel(msm_host, regval, QCOM_ICE_REG_ADVANCED_CONTROL); -} - -static void sdhci_msm_ice_optimization_enable(struct sdhci_msm_host *msm_host) +static void sdhci_msm_ice_enable(struct sdhci_msm_host *msm_host) { - u32 regval; - - /* ICE Optimizations Enable Sequence */ - regval = sdhci_msm_ice_readl(msm_host, QCOM_ICE_REG_ADVANCED_CONTROL); - regval |= 0xD807100; - /* ICE HPG requires delay before writing */ - udelay(5); - sdhci_msm_ice_writel(msm_host, regval, QCOM_ICE_REG_ADVANCED_CONTROL); - udelay(5); + if (msm_host->mmc->caps2 & MMC_CAP2_CRYPTO) + qcom_ice_enable(msm_host->ice); } -/* - * Wait until the ICE BIST (built-in self-test) has completed. - * - * This may be necessary before ICE can be used. - * - * Note that we don't really care whether the BIST passed or failed; we really - * just want to make sure that it isn't still running. This is because (a) the - * BIST is a FIPS compliance thing that never fails in practice, (b) ICE is - * documented to reject crypto requests if the BIST fails, so we needn't do it - * in software too, and (c) properly testing storage encryption requires testing - * the full storage stack anyway, and not relying on hardware-level self-tests. - */ -static int sdhci_msm_ice_wait_bist_status(struct sdhci_msm_host *msm_host) +static __maybe_unused int sdhci_msm_ice_resume(struct sdhci_msm_host *msm_host) { - u32 regval; - int err; + if (msm_host->mmc->caps2 & MMC_CAP2_CRYPTO) + return qcom_ice_resume(msm_host->ice); - err = readl_poll_timeout(msm_host->ice_mem + QCOM_ICE_REG_BIST_STATUS, - regval, !(regval & QCOM_ICE_BIST_STATUS_MASK), - 50, 5000); - if (err) - dev_err(mmc_dev(msm_host->mmc), - "Timed out waiting for ICE self-test to complete\n"); - return err; + return 0; } -static void sdhci_msm_ice_enable(struct sdhci_msm_host *msm_host) +static __maybe_unused int sdhci_msm_ice_suspend(struct sdhci_msm_host *msm_host) { - if (!(msm_host->mmc->caps2 & MMC_CAP2_CRYPTO)) - return; - sdhci_msm_ice_low_power_mode_enable(msm_host); - sdhci_msm_ice_optimization_enable(msm_host); - sdhci_msm_ice_wait_bist_status(msm_host); -} + if (msm_host->mmc->caps2 & MMC_CAP2_CRYPTO) + return qcom_ice_suspend(msm_host->ice); -static int __maybe_unused sdhci_msm_ice_resume(struct sdhci_msm_host *msm_host) -{ - if (!(msm_host->mmc->caps2 & MMC_CAP2_CRYPTO)) - return 0; - return sdhci_msm_ice_wait_bist_status(msm_host); + return 0; } /* @@ -1972,48 +1862,28 @@ static int sdhci_msm_program_key(struct cqhci_host *cq_host, const union cqhci_crypto_cfg_entry *cfg, int slot) { - struct device *dev = mmc_dev(cq_host->mmc); + struct sdhci_host *host = mmc_priv(cq_host->mmc); + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host); union cqhci_crypto_cap_entry cap; - union { - u8 bytes[AES_256_XTS_KEY_SIZE]; - u32 words[AES_256_XTS_KEY_SIZE / sizeof(u32)]; - } key; - int i; - int err; - - if (!(cfg->config_enable & CQHCI_CRYPTO_CONFIGURATION_ENABLE)) - return qcom_scm_ice_invalidate_key(slot); /* Only AES-256-XTS has been tested so far. */ cap = cq_host->crypto_cap_array[cfg->crypto_cap_idx]; if (cap.algorithm_id != CQHCI_CRYPTO_ALG_AES_XTS || - cap.key_size != CQHCI_CRYPTO_KEY_SIZE_256) { - dev_err_ratelimited(dev, - "Unhandled crypto capability; algorithm_id=%d, key_size=%d\n", - cap.algorithm_id, cap.key_size); + cap.key_size != CQHCI_CRYPTO_KEY_SIZE_256) return -EINVAL; - } - memcpy(key.bytes, cfg->crypto_key, AES_256_XTS_KEY_SIZE); - - /* - * The SCM call byte-swaps the 32-bit words of the key. So we have to - * do the same, in order for the final key be correct. - */ - for (i = 0; i < ARRAY_SIZE(key.words); i++) - __cpu_to_be32s(&key.words[i]); - - err = qcom_scm_ice_set_key(slot, key.bytes, AES_256_XTS_KEY_SIZE, - QCOM_SCM_ICE_CIPHER_AES_256_XTS, - cfg->data_unit_size); - memzero_explicit(&key, sizeof(key)); - return err; + if (cfg->config_enable & CQHCI_CRYPTO_CONFIGURATION_ENABLE) + return qcom_ice_program_key(msm_host->ice, + QCOM_ICE_CRYPTO_ALG_AES_XTS, + QCOM_ICE_CRYPTO_KEY_SIZE_256, + cfg->crypto_key, + cfg->data_unit_size, slot); + else + return qcom_ice_evict_key(msm_host->ice, slot); } + #else /* CONFIG_MMC_CRYPTO */ -static inline struct clk *sdhci_msm_ice_get_clk(struct device *dev) -{ - return NULL; -} static inline int sdhci_msm_ice_init(struct sdhci_msm_host *msm_host, struct cqhci_host *cq_host) @@ -2025,11 +1895,17 @@ static inline void sdhci_msm_ice_enable(struct sdhci_msm_host *msm_host) { } -static inline int __maybe_unused +static inline __maybe_unused int sdhci_msm_ice_resume(struct sdhci_msm_host *msm_host) { return 0; } + +static inline __maybe_unused int +sdhci_msm_ice_suspend(struct sdhci_msm_host *msm_host) +{ + return 0; +} #endif /* !CONFIG_MMC_CRYPTO */ /*****************************************************************************\ @@ -2479,6 +2355,9 @@ static inline void sdhci_msm_get_of_property(struct platform_device *pdev, msm_host->ddr_config = DDR_CONFIG_POR_VAL; of_property_read_u32(node, "qcom,dll-config", &msm_host->dll_config); + + if (of_device_is_compatible(node, "qcom,msm8916-sdhci")) + host->quirks2 |= SDHCI_QUIRK2_BROKEN_64_BIT_DMA; } static int sdhci_msm_gcc_reset(struct device *dev, struct sdhci_host *host) @@ -2630,11 +2509,6 @@ static int sdhci_msm_probe(struct platform_device *pdev) clk = NULL; msm_host->bulk_clks[3].clk = clk; - clk = sdhci_msm_ice_get_clk(&pdev->dev); - if (IS_ERR(clk)) - clk = NULL; - msm_host->bulk_clks[4].clk = clk; - ret = clk_bulk_prepare_enable(ARRAY_SIZE(msm_host->bulk_clks), msm_host->bulk_clks); if (ret) @@ -2827,7 +2701,7 @@ static __maybe_unused int sdhci_msm_runtime_suspend(struct device *dev) clk_bulk_disable_unprepare(ARRAY_SIZE(msm_host->bulk_clks), msm_host->bulk_clks); - return 0; + return sdhci_msm_ice_suspend(msm_host); } static __maybe_unused int sdhci_msm_runtime_resume(struct device *dev) diff --git a/drivers/mmc/host/sdhci-pci-core.c b/drivers/mmc/host/sdhci-pci-core.c index 01975d145200663777df2093b522e646f52dade1..1c2572c0f012d2265719c4f572a8bcf1a7de62d6 100644 --- a/drivers/mmc/host/sdhci-pci-core.c +++ b/drivers/mmc/host/sdhci-pci-core.c @@ -1903,6 +1903,7 @@ static const struct pci_device_id pci_ids[] = { SDHCI_PCI_DEVICE(GLI, 9750, gl9750), SDHCI_PCI_DEVICE(GLI, 9755, gl9755), SDHCI_PCI_DEVICE(GLI, 9763E, gl9763e), + SDHCI_PCI_DEVICE(GLI, 9767, gl9767), SDHCI_PCI_DEVICE_CLASS(AMD, SYSTEM_SDHCI, PCI_CLASS_MASK, amd), /* Generic SD host controller */ {PCI_DEVICE_CLASS(SYSTEM_SDHCI, PCI_CLASS_MASK)}, diff --git a/drivers/mmc/host/sdhci-pci-gli.c b/drivers/mmc/host/sdhci-pci-gli.c index 633a8ee8f8c5bcf2a1b7f6022873991f6d16a668..ae8c307b7aa7b7f0781a246674d0646b3a5b973e 100644 --- a/drivers/mmc/host/sdhci-pci-gli.c +++ b/drivers/mmc/host/sdhci-pci-gli.c @@ -149,6 +149,72 @@ #define PCI_GLI_9755_PM_CTRL 0xFC #define PCI_GLI_9755_PM_STATE GENMASK(1, 0) +#define SDHCI_GLI_9767_GM_BURST_SIZE 0x510 +#define SDHCI_GLI_9767_GM_BURST_SIZE_AXI_ALWAYS_SET BIT(8) + +#define PCIE_GLI_9767_VHS 0x884 +#define GLI_9767_VHS_REV GENMASK(19, 16) +#define GLI_9767_VHS_REV_R 0x0 +#define GLI_9767_VHS_REV_M 0x1 +#define GLI_9767_VHS_REV_W 0x2 + +#define PCIE_GLI_9767_COM_MAILBOX 0x888 +#define PCIE_GLI_9767_COM_MAILBOX_SSC_EN BIT(1) + +#define PCIE_GLI_9767_CFG 0x8A0 +#define PCIE_GLI_9767_CFG_LOW_PWR_OFF BIT(12) + +#define PCIE_GLI_9767_COMBO_MUX_CTL 0x8C8 +#define PCIE_GLI_9767_COMBO_MUX_CTL_RST_EN BIT(6) +#define PCIE_GLI_9767_COMBO_MUX_CTL_WAIT_PERST_EN BIT(10) + +#define PCIE_GLI_9767_PWR_MACRO_CTL 0x8D0 +#define PCIE_GLI_9767_PWR_MACRO_CTL_LOW_VOLTAGE GENMASK(3, 0) +#define PCIE_GLI_9767_PWR_MACRO_CTL_LD0_LOW_OUTPUT_VOLTAGE GENMASK(15, 12) +#define PCIE_GLI_9767_PWR_MACRO_CTL_LD0_LOW_OUTPUT_VOLTAGE_VALUE 0x7 +#define PCIE_GLI_9767_PWR_MACRO_CTL_RCLK_AMPLITUDE_CTL GENMASK(29, 28) +#define PCIE_GLI_9767_PWR_MACRO_CTL_RCLK_AMPLITUDE_CTL_VALUE 0x3 + +#define PCIE_GLI_9767_SCR 0x8E0 +#define PCIE_GLI_9767_SCR_AUTO_AXI_W_BURST BIT(6) +#define PCIE_GLI_9767_SCR_AUTO_AXI_R_BURST BIT(7) +#define PCIE_GLI_9767_SCR_AXI_REQ BIT(9) +#define PCIE_GLI_9767_SCR_CARD_DET_PWR_SAVING_EN BIT(10) +#define PCIE_GLI_9767_SCR_SYSTEM_CLK_SELECT_MODE0 BIT(16) +#define PCIE_GLI_9767_SCR_SYSTEM_CLK_SELECT_MODE1 BIT(17) +#define PCIE_GLI_9767_SCR_CORE_PWR_D3_OFF BIT(21) +#define PCIE_GLI_9767_SCR_CFG_RST_DATA_LINK_DOWN BIT(30) + +#define PCIE_GLI_9767_SDHC_CAP 0x91C +#define PCIE_GLI_9767_SDHC_CAP_SDEI_RESULT BIT(5) + +#define PCIE_GLI_9767_SD_PLL_CTL 0x938 +#define PCIE_GLI_9767_SD_PLL_CTL_PLL_LDIV GENMASK(9, 0) +#define PCIE_GLI_9767_SD_PLL_CTL_PLL_PDIV GENMASK(15, 12) +#define PCIE_GLI_9767_SD_PLL_CTL_PLL_DIR_EN BIT(16) +#define PCIE_GLI_9767_SD_PLL_CTL_SSC_EN BIT(19) +#define PCIE_GLI_9767_SD_PLL_CTL_SSC_STEP_SETTING GENMASK(28, 24) + +#define PCIE_GLI_9767_SD_PLL_CTL2 0x93C +#define PCIE_GLI_9767_SD_PLL_CTL2_PLLSSC_PPM GENMASK(31, 16) + +#define PCIE_GLI_9767_SD_EXPRESS_CTL 0x940 +#define PCIE_GLI_9767_SD_EXPRESS_CTL_SDEI_EXE BIT(0) +#define PCIE_GLI_9767_SD_EXPRESS_CTL_SD_EXPRESS_MODE BIT(1) + +#define PCIE_GLI_9767_SD_DATA_MULTI_CTL 0x944 +#define PCIE_GLI_9767_SD_DATA_MULTI_CTL_DISCONNECT_TIME GENMASK(23, 16) +#define PCIE_GLI_9767_SD_DATA_MULTI_CTL_DISCONNECT_TIME_VALUE 0x64 + +#define PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_REG2 0x950 +#define PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_REG2_SDEI_COMPLETE BIT(0) + +#define PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_EN_REG2 0x954 +#define PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_EN_REG2_SDEI_COMPLETE_STATUS_EN BIT(0) + +#define PCIE_GLI_9767_NORMAL_ERR_INT_SIGNAL_EN_REG2 0x958 +#define PCIE_GLI_9767_NORMAL_ERR_INT_SIGNAL_EN_REG2_SDEI_COMPLETE_SIGNAL_EN BIT(0) + #define GLI_MAX_TUNING_LOOP 40 /* Genesys Logic chipset */ @@ -693,6 +759,293 @@ static void gl9755_hw_setting(struct sdhci_pci_slot *slot) gl9755_wt_off(pdev); } +static inline void gl9767_vhs_read(struct pci_dev *pdev) +{ + u32 vhs_enable; + u32 vhs_value; + + pci_read_config_dword(pdev, PCIE_GLI_9767_VHS, &vhs_value); + vhs_enable = FIELD_GET(GLI_9767_VHS_REV, vhs_value); + + if (vhs_enable == GLI_9767_VHS_REV_R) + return; + + vhs_value &= ~GLI_9767_VHS_REV; + vhs_value |= FIELD_PREP(GLI_9767_VHS_REV, GLI_9767_VHS_REV_R); + + pci_write_config_dword(pdev, PCIE_GLI_9767_VHS, vhs_value); +} + +static inline void gl9767_vhs_write(struct pci_dev *pdev) +{ + u32 vhs_enable; + u32 vhs_value; + + pci_read_config_dword(pdev, PCIE_GLI_9767_VHS, &vhs_value); + vhs_enable = FIELD_GET(GLI_9767_VHS_REV, vhs_value); + + if (vhs_enable == GLI_9767_VHS_REV_W) + return; + + vhs_value &= ~GLI_9767_VHS_REV; + vhs_value |= FIELD_PREP(GLI_9767_VHS_REV, GLI_9767_VHS_REV_W); + + pci_write_config_dword(pdev, PCIE_GLI_9767_VHS, vhs_value); +} + +static bool gl9767_ssc_enable(struct pci_dev *pdev) +{ + u32 value; + u8 enable; + + gl9767_vhs_write(pdev); + + pci_read_config_dword(pdev, PCIE_GLI_9767_COM_MAILBOX, &value); + enable = FIELD_GET(PCIE_GLI_9767_COM_MAILBOX_SSC_EN, value); + + gl9767_vhs_read(pdev); + + return enable; +} + +static void gl9767_set_ssc(struct pci_dev *pdev, u8 enable, u8 step, u16 ppm) +{ + u32 pll; + u32 ssc; + + gl9767_vhs_write(pdev); + + pci_read_config_dword(pdev, PCIE_GLI_9767_SD_PLL_CTL, &pll); + pci_read_config_dword(pdev, PCIE_GLI_9767_SD_PLL_CTL2, &ssc); + pll &= ~(PCIE_GLI_9767_SD_PLL_CTL_SSC_STEP_SETTING | + PCIE_GLI_9767_SD_PLL_CTL_SSC_EN); + ssc &= ~PCIE_GLI_9767_SD_PLL_CTL2_PLLSSC_PPM; + pll |= FIELD_PREP(PCIE_GLI_9767_SD_PLL_CTL_SSC_STEP_SETTING, step) | + FIELD_PREP(PCIE_GLI_9767_SD_PLL_CTL_SSC_EN, enable); + ssc |= FIELD_PREP(PCIE_GLI_9767_SD_PLL_CTL2_PLLSSC_PPM, ppm); + pci_write_config_dword(pdev, PCIE_GLI_9767_SD_PLL_CTL2, ssc); + pci_write_config_dword(pdev, PCIE_GLI_9767_SD_PLL_CTL, pll); + + gl9767_vhs_read(pdev); +} + +static void gl9767_set_pll(struct pci_dev *pdev, u8 dir, u16 ldiv, u8 pdiv) +{ + u32 pll; + + gl9767_vhs_write(pdev); + + pci_read_config_dword(pdev, PCIE_GLI_9767_SD_PLL_CTL, &pll); + pll &= ~(PCIE_GLI_9767_SD_PLL_CTL_PLL_LDIV | + PCIE_GLI_9767_SD_PLL_CTL_PLL_PDIV | + PCIE_GLI_9767_SD_PLL_CTL_PLL_DIR_EN); + pll |= FIELD_PREP(PCIE_GLI_9767_SD_PLL_CTL_PLL_LDIV, ldiv) | + FIELD_PREP(PCIE_GLI_9767_SD_PLL_CTL_PLL_PDIV, pdiv) | + FIELD_PREP(PCIE_GLI_9767_SD_PLL_CTL_PLL_DIR_EN, dir); + pci_write_config_dword(pdev, PCIE_GLI_9767_SD_PLL_CTL, pll); + + gl9767_vhs_read(pdev); + + /* wait for pll stable */ + usleep_range(1000, 1100); +} + +static void gl9767_set_ssc_pll_205mhz(struct pci_dev *pdev) +{ + bool enable = gl9767_ssc_enable(pdev); + + /* set pll to 205MHz and ssc */ + gl9767_set_ssc(pdev, enable, 0x1F, 0xF5C3); + gl9767_set_pll(pdev, 0x1, 0x246, 0x0); +} + +static void gl9767_disable_ssc_pll(struct pci_dev *pdev) +{ + u32 pll; + + gl9767_vhs_write(pdev); + + pci_read_config_dword(pdev, PCIE_GLI_9767_SD_PLL_CTL, &pll); + pll &= ~(PCIE_GLI_9767_SD_PLL_CTL_PLL_DIR_EN | PCIE_GLI_9767_SD_PLL_CTL_SSC_EN); + pci_write_config_dword(pdev, PCIE_GLI_9767_SD_PLL_CTL, pll); + + gl9767_vhs_read(pdev); +} + +static void sdhci_gl9767_set_clock(struct sdhci_host *host, unsigned int clock) +{ + struct sdhci_pci_slot *slot = sdhci_priv(host); + struct mmc_ios *ios = &host->mmc->ios; + struct pci_dev *pdev; + u32 value; + u16 clk; + + pdev = slot->chip->pdev; + host->mmc->actual_clock = 0; + + gl9767_vhs_write(pdev); + + pci_read_config_dword(pdev, PCIE_GLI_9767_CFG, &value); + value |= PCIE_GLI_9767_CFG_LOW_PWR_OFF; + pci_write_config_dword(pdev, PCIE_GLI_9767_CFG, value); + + gl9767_disable_ssc_pll(pdev); + sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL); + + if (clock == 0) + return; + + clk = sdhci_calc_clk(host, clock, &host->mmc->actual_clock); + if (clock == 200000000 && ios->timing == MMC_TIMING_UHS_SDR104) { + host->mmc->actual_clock = 205000000; + gl9767_set_ssc_pll_205mhz(pdev); + } + + sdhci_enable_clk(host, clk); + + pci_read_config_dword(pdev, PCIE_GLI_9767_CFG, &value); + value &= ~PCIE_GLI_9767_CFG_LOW_PWR_OFF; + pci_write_config_dword(pdev, PCIE_GLI_9767_CFG, value); + + gl9767_vhs_read(pdev); +} + +static void gli_set_9767(struct sdhci_host *host) +{ + u32 value; + + value = sdhci_readl(host, SDHCI_GLI_9767_GM_BURST_SIZE); + value &= ~SDHCI_GLI_9767_GM_BURST_SIZE_AXI_ALWAYS_SET; + sdhci_writel(host, value, SDHCI_GLI_9767_GM_BURST_SIZE); +} + +static void gl9767_hw_setting(struct sdhci_pci_slot *slot) +{ + struct pci_dev *pdev = slot->chip->pdev; + u32 value; + + gl9767_vhs_write(pdev); + + pci_read_config_dword(pdev, PCIE_GLI_9767_PWR_MACRO_CTL, &value); + value &= ~(PCIE_GLI_9767_PWR_MACRO_CTL_LOW_VOLTAGE | + PCIE_GLI_9767_PWR_MACRO_CTL_LD0_LOW_OUTPUT_VOLTAGE | + PCIE_GLI_9767_PWR_MACRO_CTL_RCLK_AMPLITUDE_CTL); + + value |= PCIE_GLI_9767_PWR_MACRO_CTL_LOW_VOLTAGE | + FIELD_PREP(PCIE_GLI_9767_PWR_MACRO_CTL_LD0_LOW_OUTPUT_VOLTAGE, + PCIE_GLI_9767_PWR_MACRO_CTL_LD0_LOW_OUTPUT_VOLTAGE_VALUE) | + FIELD_PREP(PCIE_GLI_9767_PWR_MACRO_CTL_RCLK_AMPLITUDE_CTL, + PCIE_GLI_9767_PWR_MACRO_CTL_RCLK_AMPLITUDE_CTL_VALUE); + pci_write_config_dword(pdev, PCIE_GLI_9767_PWR_MACRO_CTL, value); + + pci_read_config_dword(pdev, PCIE_GLI_9767_SCR, &value); + value &= ~(PCIE_GLI_9767_SCR_SYSTEM_CLK_SELECT_MODE0 | + PCIE_GLI_9767_SCR_SYSTEM_CLK_SELECT_MODE1 | + PCIE_GLI_9767_SCR_CFG_RST_DATA_LINK_DOWN); + + value |= PCIE_GLI_9767_SCR_AUTO_AXI_W_BURST | + PCIE_GLI_9767_SCR_AUTO_AXI_R_BURST | + PCIE_GLI_9767_SCR_AXI_REQ | + PCIE_GLI_9767_SCR_CARD_DET_PWR_SAVING_EN | + PCIE_GLI_9767_SCR_CORE_PWR_D3_OFF; + pci_write_config_dword(pdev, PCIE_GLI_9767_SCR, value); + + gl9767_vhs_read(pdev); +} + +static void sdhci_gl9767_reset(struct sdhci_host *host, u8 mask) +{ + sdhci_reset(host, mask); + gli_set_9767(host); +} + +static int gl9767_init_sd_express(struct mmc_host *mmc, struct mmc_ios *ios) +{ + struct sdhci_host *host = mmc_priv(mmc); + struct sdhci_pci_slot *slot = sdhci_priv(host); + struct pci_dev *pdev; + u32 value; + int i; + + pdev = slot->chip->pdev; + + if (mmc->ops->get_ro(mmc)) { + mmc->ios.timing &= ~(MMC_TIMING_SD_EXP | MMC_TIMING_SD_EXP_1_2V); + return 0; + } + + gl9767_vhs_write(pdev); + + pci_read_config_dword(pdev, PCIE_GLI_9767_COMBO_MUX_CTL, &value); + value &= ~(PCIE_GLI_9767_COMBO_MUX_CTL_RST_EN | PCIE_GLI_9767_COMBO_MUX_CTL_WAIT_PERST_EN); + pci_write_config_dword(pdev, PCIE_GLI_9767_COMBO_MUX_CTL, value); + + pci_read_config_dword(pdev, PCIE_GLI_9767_SD_DATA_MULTI_CTL, &value); + value &= ~PCIE_GLI_9767_SD_DATA_MULTI_CTL_DISCONNECT_TIME; + value |= FIELD_PREP(PCIE_GLI_9767_SD_DATA_MULTI_CTL_DISCONNECT_TIME, + PCIE_GLI_9767_SD_DATA_MULTI_CTL_DISCONNECT_TIME_VALUE); + pci_write_config_dword(pdev, PCIE_GLI_9767_SD_DATA_MULTI_CTL, value); + + pci_read_config_dword(pdev, PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_REG2, &value); + value |= PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_REG2_SDEI_COMPLETE; + pci_write_config_dword(pdev, PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_REG2, value); + + pci_read_config_dword(pdev, PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_EN_REG2, &value); + value |= PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_EN_REG2_SDEI_COMPLETE_STATUS_EN; + pci_write_config_dword(pdev, PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_EN_REG2, value); + + pci_read_config_dword(pdev, PCIE_GLI_9767_NORMAL_ERR_INT_SIGNAL_EN_REG2, &value); + value |= PCIE_GLI_9767_NORMAL_ERR_INT_SIGNAL_EN_REG2_SDEI_COMPLETE_SIGNAL_EN; + pci_write_config_dword(pdev, PCIE_GLI_9767_NORMAL_ERR_INT_SIGNAL_EN_REG2, value); + + pci_read_config_dword(pdev, PCIE_GLI_9767_CFG, &value); + value |= PCIE_GLI_9767_CFG_LOW_PWR_OFF; + pci_write_config_dword(pdev, PCIE_GLI_9767_CFG, value); + + value = sdhci_readw(host, SDHCI_CLOCK_CONTROL); + value &= ~(SDHCI_CLOCK_CARD_EN | SDHCI_CLOCK_PLL_EN); + sdhci_writew(host, value, SDHCI_CLOCK_CONTROL); + + value = sdhci_readb(host, SDHCI_POWER_CONTROL); + value |= (SDHCI_VDD2_POWER_180 | SDHCI_VDD2_POWER_ON); + sdhci_writeb(host, value, SDHCI_POWER_CONTROL); + + pci_read_config_dword(pdev, PCIE_GLI_9767_SD_EXPRESS_CTL, &value); + value |= PCIE_GLI_9767_SD_EXPRESS_CTL_SDEI_EXE; + pci_write_config_dword(pdev, PCIE_GLI_9767_SD_EXPRESS_CTL, value); + + for (i = 0; i < 2; i++) { + usleep_range(10000, 10100); + pci_read_config_dword(pdev, PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_REG2, &value); + if (value & PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_REG2_SDEI_COMPLETE) { + pci_write_config_dword(pdev, PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_REG2, + value); + break; + } + } + + pci_read_config_dword(pdev, PCIE_GLI_9767_SDHC_CAP, &value); + if (value & PCIE_GLI_9767_SDHC_CAP_SDEI_RESULT) { + pci_read_config_dword(pdev, PCIE_GLI_9767_SD_EXPRESS_CTL, &value); + value |= PCIE_GLI_9767_SD_EXPRESS_CTL_SD_EXPRESS_MODE; + pci_write_config_dword(pdev, PCIE_GLI_9767_SD_EXPRESS_CTL, value); + } else { + mmc->ios.timing &= ~(MMC_TIMING_SD_EXP | MMC_TIMING_SD_EXP_1_2V); + + value = sdhci_readb(host, SDHCI_POWER_CONTROL); + value &= ~(SDHCI_VDD2_POWER_180 | SDHCI_VDD2_POWER_ON); + sdhci_writeb(host, value, SDHCI_POWER_CONTROL); + + value = sdhci_readw(host, SDHCI_CLOCK_CONTROL); + value |= (SDHCI_CLOCK_CARD_EN | SDHCI_CLOCK_PLL_EN); + sdhci_writew(host, value, SDHCI_CLOCK_CONTROL); + } + + gl9767_vhs_read(pdev); + + return 0; +} + static int gli_probe_slot_gl9750(struct sdhci_pci_slot *slot) { struct sdhci_host *host = slot->host; @@ -717,6 +1070,21 @@ static int gli_probe_slot_gl9755(struct sdhci_pci_slot *slot) return 0; } +static int gli_probe_slot_gl9767(struct sdhci_pci_slot *slot) +{ + struct sdhci_host *host = slot->host; + + gli_set_9767(host); + gl9767_hw_setting(slot); + gli_pcie_enable_msi(slot); + slot->host->mmc->caps2 |= MMC_CAP2_NO_SDIO; + host->mmc->caps2 |= MMC_CAP2_SD_EXP; + host->mmc_host_ops.init_sd_express = gl9767_init_sd_express; + sdhci_enable_v4_mode(host); + + return 0; +} + static void sdhci_gli_voltage_switch(struct sdhci_host *host) { /* @@ -740,6 +1108,25 @@ static void sdhci_gli_voltage_switch(struct sdhci_host *host) usleep_range(100000, 110000); } +static void sdhci_gl9767_voltage_switch(struct sdhci_host *host) +{ + /* + * According to Section 3.6.1 signal voltage switch procedure in + * SD Host Controller Simplified Spec. 4.20, steps 6~8 are as + * follows: + * (6) Set 1.8V Signal Enable in the Host Control 2 register. + * (7) Wait 5ms. 1.8V voltage regulator shall be stable within this + * period. + * (8) If 1.8V Signal Enable is cleared by Host Controller, go to + * step (12). + * + * Wait 5ms after set 1.8V signal enable in Host Control 2 register + * to ensure 1.8V signal enable bit is set by GL9767. + * + */ + usleep_range(5000, 5500); +} + static void sdhci_gl9750_reset(struct sdhci_host *host, u8 mask) { sdhci_reset(host, mask); @@ -1150,3 +1537,22 @@ const struct sdhci_pci_fixes sdhci_gl9763e = { #endif .add_host = gl9763e_add_host, }; + +static const struct sdhci_ops sdhci_gl9767_ops = { + .set_clock = sdhci_gl9767_set_clock, + .enable_dma = sdhci_pci_enable_dma, + .set_bus_width = sdhci_set_bus_width, + .reset = sdhci_gl9767_reset, + .set_uhs_signaling = sdhci_set_uhs_signaling, + .voltage_switch = sdhci_gl9767_voltage_switch, +}; + +const struct sdhci_pci_fixes sdhci_gl9767 = { + .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, + .quirks2 = SDHCI_QUIRK2_BROKEN_DDR50, + .probe_slot = gli_probe_slot_gl9767, + .ops = &sdhci_gl9767_ops, +#ifdef CONFIG_PM_SLEEP + .resume = sdhci_pci_gli_resume, +#endif +}; diff --git a/drivers/mmc/host/sdhci-pci.h b/drivers/mmc/host/sdhci-pci.h index 3661a224fb04a115d48fa00dcfe814e43c01c671..9c8863956381554128f2481958eebf93d5039ec2 100644 --- a/drivers/mmc/host/sdhci-pci.h +++ b/drivers/mmc/host/sdhci-pci.h @@ -76,6 +76,7 @@ #define PCI_DEVICE_ID_GLI_9755 0x9755 #define PCI_DEVICE_ID_GLI_9750 0x9750 #define PCI_DEVICE_ID_GLI_9763E 0xe763 +#define PCI_DEVICE_ID_GLI_9767 0x9767 /* * PCI device class and mask @@ -195,5 +196,6 @@ extern const struct sdhci_pci_fixes sdhci_o2; extern const struct sdhci_pci_fixes sdhci_gl9750; extern const struct sdhci_pci_fixes sdhci_gl9755; extern const struct sdhci_pci_fixes sdhci_gl9763e; +extern const struct sdhci_pci_fixes sdhci_gl9767; #endif /* __SDHCI_PCI_H */ diff --git a/drivers/mmc/host/sdhci-spear.c b/drivers/mmc/host/sdhci-spear.c index d463e2fd5b1a8bfe38bd09f825f135dde485fb8c..c79035727b20b36b7d49a5088e2356d01c805746 100644 --- a/drivers/mmc/host/sdhci-spear.c +++ b/drivers/mmc/host/sdhci-spear.c @@ -65,8 +65,8 @@ static int sdhci_probe(struct platform_device *pdev) host->hw_name = "sdhci"; host->ops = &sdhci_pltfm_ops; host->irq = platform_get_irq(pdev, 0); - if (host->irq <= 0) { - ret = -EINVAL; + if (host->irq < 0) { + ret = host->irq; goto err_host; } host->quirks = SDHCI_QUIRK_BROKEN_ADMA; diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 3241916141d7dc98140d4dcabfb5c07412a43b1d..ff41aa56564eaac0bada1efdb687731d7bf69474 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -1167,6 +1167,8 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd) } } + sdhci_config_dma(host); + if (host->flags & SDHCI_REQ_USE_DMA) { int sg_cnt = sdhci_pre_dma_transfer(host, data, COOKIE_MAPPED); @@ -1186,8 +1188,6 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd) } } - sdhci_config_dma(host); - if (!(host->flags & SDHCI_REQ_USE_DMA)) { int flags; diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index f4f2085c274c9d28dbb626cf7eb63da8760e6df9..f219bdea8f280d6ffb647ff4ac8523a13c6214c3 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h @@ -99,6 +99,13 @@ #define SDHCI_POWER_180 0x0A #define SDHCI_POWER_300 0x0C #define SDHCI_POWER_330 0x0E +/* + * VDD2 - UHS2 or PCIe/NVMe + * VDD2 power on/off and voltage select + */ +#define SDHCI_VDD2_POWER_ON 0x10 +#define SDHCI_VDD2_POWER_120 0x80 +#define SDHCI_VDD2_POWER_180 0xA0 #define SDHCI_BLOCK_GAP_CONTROL 0x2A diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c index 0fd4c9d644dd5149357cf40c3d110d1b0e417fae..5cf53348372a4a1b8a2d2c49545d6ab545436330 100644 --- a/drivers/mmc/host/sh_mmcif.c +++ b/drivers/mmc/host/sh_mmcif.c @@ -1400,7 +1400,7 @@ static int sh_mmcif_probe(struct platform_device *pdev) irq[0] = platform_get_irq(pdev, 0); irq[1] = platform_get_irq_optional(pdev, 1); if (irq[0] < 0) - return -ENXIO; + return irq[0]; reg = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(reg)) diff --git a/drivers/mmc/host/sunxi-mmc.c b/drivers/mmc/host/sunxi-mmc.c index 3db9f32d6a7b9fcd51672ed299e7456c0ac079d7..69dcb8805e05fef0b48f161e8d5aaa4a81b5f6f3 100644 --- a/drivers/mmc/host/sunxi-mmc.c +++ b/drivers/mmc/host/sunxi-mmc.c @@ -1350,8 +1350,8 @@ static int sunxi_mmc_resource_request(struct sunxi_mmc_host *host, return ret; host->irq = platform_get_irq(pdev, 0); - if (host->irq <= 0) { - ret = -EINVAL; + if (host->irq < 0) { + ret = host->irq; goto error_disable_mmc; } diff --git a/drivers/mmc/host/usdhi6rol0.c b/drivers/mmc/host/usdhi6rol0.c index 2f59917b105eb44e025d77a75a7292ca93050fd5..2e17903658fc8347cfbc3a99aaa5bf1d3ee27c6c 100644 --- a/drivers/mmc/host/usdhi6rol0.c +++ b/drivers/mmc/host/usdhi6rol0.c @@ -1757,8 +1757,10 @@ static int usdhi6_probe(struct platform_device *pdev) irq_cd = platform_get_irq_byname(pdev, "card detect"); irq_sd = platform_get_irq_byname(pdev, "data"); irq_sdio = platform_get_irq_byname(pdev, "SDIO"); - if (irq_sd < 0 || irq_sdio < 0) - return -ENODEV; + if (irq_sd < 0) + return irq_sd; + if (irq_sdio < 0) + return irq_sdio; mmc = mmc_alloc_host(sizeof(struct usdhi6_host), dev); if (!mmc) diff --git a/drivers/most/configfs.c b/drivers/most/configfs.c index 27b0c923597f232a1c9ab5408336daa24b60e5ca..36d8c917f65f22754bc34575cfcb52c0fedd2814 100644 --- a/drivers/most/configfs.c +++ b/drivers/most/configfs.c @@ -204,7 +204,7 @@ static ssize_t mdev_link_device_store(struct config_item *item, { struct mdev_link *mdev_link = to_mdev_link(item); - strlcpy(mdev_link->device, page, sizeof(mdev_link->device)); + strscpy(mdev_link->device, page, sizeof(mdev_link->device)); strim(mdev_link->device); return count; } @@ -219,7 +219,7 @@ static ssize_t mdev_link_channel_store(struct config_item *item, { struct mdev_link *mdev_link = to_mdev_link(item); - strlcpy(mdev_link->channel, page, sizeof(mdev_link->channel)); + strscpy(mdev_link->channel, page, sizeof(mdev_link->channel)); strim(mdev_link->channel); return count; } @@ -234,7 +234,7 @@ static ssize_t mdev_link_comp_store(struct config_item *item, { struct mdev_link *mdev_link = to_mdev_link(item); - strlcpy(mdev_link->comp, page, sizeof(mdev_link->comp)); + strscpy(mdev_link->comp, page, sizeof(mdev_link->comp)); strim(mdev_link->comp); return count; } @@ -250,7 +250,7 @@ static ssize_t mdev_link_comp_params_store(struct config_item *item, { struct mdev_link *mdev_link = to_mdev_link(item); - strlcpy(mdev_link->comp_params, page, sizeof(mdev_link->comp_params)); + strscpy(mdev_link->comp_params, page, sizeof(mdev_link->comp_params)); strim(mdev_link->comp_params); return count; } diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c index 54f92d09d9cf430c3bd3a63f3dd4634cbbab0400..11b06fefaa0e297ef82e88401bedd48a1c95e657 100644 --- a/drivers/mtd/chips/cfi_cmdset_0001.c +++ b/drivers/mtd/chips/cfi_cmdset_0001.c @@ -1,8 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Common Flash Interface support: * Intel Extended Vendor Command Set (ID 0x0001) * - * (C) 2000 Red Hat. GPL'd + * (C) 2000 Red Hat. * * * 10/10/2000 Nicolas Pitre diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c index 67453f59c69cbb4902576ff5ecc9c9655a688b3b..153fb8d0008ed9643f7bcb32c1e3c83afc02c4ec 100644 --- a/drivers/mtd/chips/cfi_cmdset_0002.c +++ b/drivers/mtd/chips/cfi_cmdset_0002.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Common Flash Interface support: * AMD & Fujitsu Standard Vendor Command Set (ID 0x0002) @@ -16,8 +17,6 @@ * 25/09/2008 Christopher Moore: TopBottom fixup for many Macronix with CFI V1.0 * * Occasionally maintained by Thayne Harbaugh tharbaugh at lnxi dot com - * - * This code is GPL */ #include diff --git a/drivers/mtd/chips/cfi_cmdset_0020.c b/drivers/mtd/chips/cfi_cmdset_0020.c index d35df526e0a69afde9f40c4b33b1144c780989cc..60c7f6f751c747d81e5aafaf9d4b4af1f40385a7 100644 --- a/drivers/mtd/chips/cfi_cmdset_0020.c +++ b/drivers/mtd/chips/cfi_cmdset_0020.c @@ -1,8 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Common Flash Interface support: * ST Advanced Architecture Command Set (ID 0x0020) * - * (C) 2000 Red Hat. GPL'd + * (C) 2000 Red Hat. * * 10/10/2000 Nicolas Pitre * - completely revamped method functions so they are aware and diff --git a/drivers/mtd/chips/cfi_probe.c b/drivers/mtd/chips/cfi_probe.c index cf426956454cfb5717a48fbb9ed637f598bfd438..a04b6174181c4579b803744868fc6a14f5f704d3 100644 --- a/drivers/mtd/chips/cfi_probe.c +++ b/drivers/mtd/chips/cfi_probe.c @@ -1,6 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0 /* Common Flash Interface probe code. - (C) 2000 Red Hat. GPL'd. + (C) 2000 Red Hat. */ #include diff --git a/drivers/mtd/chips/cfi_util.c b/drivers/mtd/chips/cfi_util.c index 6a6a2a21d2edc167c6ff5f40df18c7b3b589545a..140c69a67e8268f2e0ca59563c8a0bf0a936f4d4 100644 --- a/drivers/mtd/chips/cfi_util.c +++ b/drivers/mtd/chips/cfi_util.c @@ -1,11 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Common Flash Interface support: * Generic utility functions not dependent on command set * * Copyright (C) 2002 Red Hat * Copyright (C) 2003 STMicroelectronics Limited - * - * This code is covered by the GPL. */ #include diff --git a/drivers/mtd/chips/gen_probe.c b/drivers/mtd/chips/gen_probe.c index 4d4f978410161e63ed3a72e448fce6959d799ddf..9e53fcd7600d276c5382a67181745e4cd626171a 100644 --- a/drivers/mtd/chips/gen_probe.c +++ b/drivers/mtd/chips/gen_probe.c @@ -1,7 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Routines common to all CFI-type probes. * (C) 2001-2003 Red Hat, Inc. - * GPL'd */ #include diff --git a/drivers/mtd/chips/jedec_probe.c b/drivers/mtd/chips/jedec_probe.c index 6f7e7e1b3fe5fc69ac9e868d2fdc84e135a717ce..23c32fe584b70a89328107bee1875594fefe2d6c 100644 --- a/drivers/mtd/chips/jedec_probe.c +++ b/drivers/mtd/chips/jedec_probe.c @@ -1,6 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0 /* Common Flash Interface probe code. - (C) 2000 Red Hat. GPL'd. + (C) 2000 Red Hat. See JEDEC (http://www.jedec.org/) standard JESD21C (section 3.5) for the standard this probe goes back to. diff --git a/drivers/mtd/chips/map_ram.c b/drivers/mtd/chips/map_ram.c index c37fce92686407bbad54c0c4a8b4d6d78ffd4079..e8dd6496927ef659d2fc1dc65006e62705910f12 100644 --- a/drivers/mtd/chips/map_ram.c +++ b/drivers/mtd/chips/map_ram.c @@ -1,6 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Common code to handle map devices which are simple RAM - * (C) 2000 Red Hat. GPL'd. + * (C) 2000 Red Hat. */ #include diff --git a/drivers/mtd/chips/map_rom.c b/drivers/mtd/chips/map_rom.c index 20e3604b4d7169fef2c65daeba87dbe74b502baf..0823b15aaadbe371da40745ab655b40129102ff5 100644 --- a/drivers/mtd/chips/map_rom.c +++ b/drivers/mtd/chips/map_rom.c @@ -1,6 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Common code to handle map devices which are simple ROM - * (C) 2000 Red Hat. GPL'd. + * (C) 2000 Red Hat. */ #include diff --git a/drivers/mtd/devices/block2mtd.c b/drivers/mtd/devices/block2mtd.c index 4cd37ec45762b6f92add0557923ff445a92f1f01..be106dc20ff3cf664152ec723528c77b97ad30a2 100644 --- a/drivers/mtd/devices/block2mtd.c +++ b/drivers/mtd/devices/block2mtd.c @@ -209,40 +209,34 @@ static void block2mtd_free_device(struct block2mtd_dev *dev) if (dev->blkdev) { invalidate_mapping_pages(dev->blkdev->bd_inode->i_mapping, 0, -1); - blkdev_put(dev->blkdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL); + blkdev_put(dev->blkdev, NULL); } kfree(dev); } - -static struct block2mtd_dev *add_device(char *devname, int erase_size, - char *label, int timeout) +/* + * This function is marked __ref because it calls the __init marked + * early_lookup_bdev when called from the early boot code. + */ +static struct block_device __ref *mdtblock_early_get_bdev(const char *devname, + blk_mode_t mode, int timeout, struct block2mtd_dev *dev) { + struct block_device *bdev = ERR_PTR(-ENODEV); #ifndef MODULE int i; -#endif - const fmode_t mode = FMODE_READ | FMODE_WRITE | FMODE_EXCL; - struct block_device *bdev; - struct block2mtd_dev *dev; - char *name; - if (!devname) - return NULL; - - dev = kzalloc(sizeof(struct block2mtd_dev), GFP_KERNEL); - if (!dev) - return NULL; - - /* Get a handle on the device */ - bdev = blkdev_get_by_path(devname, mode, dev); + /* + * We can't use early_lookup_bdev from a running system. + */ + if (system_state >= SYSTEM_RUNNING) + return bdev; -#ifndef MODULE /* * We might not have the root device mounted at this point. * Try to resolve the device name by other means. */ - for (i = 0; IS_ERR(bdev) && i <= timeout; i++) { + for (i = 0; i <= timeout; i++) { dev_t devt; if (i) @@ -254,13 +248,35 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size, msleep(1000); wait_for_device_probe(); - devt = name_to_dev_t(devname); - if (!devt) - continue; - bdev = blkdev_get_by_dev(devt, mode, dev); + if (!early_lookup_bdev(devname, &devt)) { + bdev = blkdev_get_by_dev(devt, mode, dev, NULL); + if (!IS_ERR(bdev)) + break; + } } #endif + return bdev; +} +static struct block2mtd_dev *add_device(char *devname, int erase_size, + char *label, int timeout) +{ + const blk_mode_t mode = BLK_OPEN_READ | BLK_OPEN_WRITE; + struct block_device *bdev; + struct block2mtd_dev *dev; + char *name; + + if (!devname) + return NULL; + + dev = kzalloc(sizeof(struct block2mtd_dev), GFP_KERNEL); + if (!dev) + return NULL; + + /* Get a handle on the device */ + bdev = blkdev_get_by_path(devname, mode, dev, NULL); + if (IS_ERR(bdev)) + bdev = mdtblock_early_get_bdev(devname, mode, timeout, dev); if (IS_ERR(bdev)) { pr_err("error: cannot open device %s\n", devname); goto err_free_block2mtd; diff --git a/drivers/mtd/devices/st_spi_fsm.c b/drivers/mtd/devices/st_spi_fsm.c index 54861d889c3096a8f74ff1c828ececd5d2bb6e95..3dbb1aa80bfa7b5c719c76b6630db9b0fadd9461 100644 --- a/drivers/mtd/devices/st_spi_fsm.c +++ b/drivers/mtd/devices/st_spi_fsm.c @@ -2046,34 +2046,26 @@ static int stfsm_probe(struct platform_device *pdev) return PTR_ERR(fsm->base); } - fsm->clk = devm_clk_get(&pdev->dev, NULL); + fsm->clk = devm_clk_get_enabled(&pdev->dev, NULL); if (IS_ERR(fsm->clk)) { dev_err(fsm->dev, "Couldn't find EMI clock.\n"); return PTR_ERR(fsm->clk); } - ret = clk_prepare_enable(fsm->clk); - if (ret) { - dev_err(fsm->dev, "Failed to enable EMI clock.\n"); - return ret; - } - mutex_init(&fsm->lock); ret = stfsm_init(fsm); if (ret) { dev_err(&pdev->dev, "Failed to initialise FSM Controller\n"); - goto err_clk_unprepare; + return ret; } stfsm_fetch_platform_configs(pdev); /* Detect SPI FLASH device */ info = stfsm_jedec_probe(fsm); - if (!info) { - ret = -ENODEV; - goto err_clk_unprepare; - } + if (!info) + return -ENODEV; fsm->info = info; /* Use device size to determine address width */ @@ -2089,7 +2081,7 @@ static int stfsm_probe(struct platform_device *pdev) else ret = stfsm_prepare_rwe_seqs_default(fsm); if (ret) - goto err_clk_unprepare; + return ret; fsm->mtd.name = info->name; fsm->mtd.dev.parent = &pdev->dev; @@ -2112,13 +2104,7 @@ static int stfsm_probe(struct platform_device *pdev) (long long)fsm->mtd.size, (long long)(fsm->mtd.size >> 20), fsm->mtd.erasesize, (fsm->mtd.erasesize >> 10)); - ret = mtd_device_register(&fsm->mtd, NULL, 0); - if (ret) { -err_clk_unprepare: - clk_disable_unprepare(fsm->clk); - } - - return ret; + return mtd_device_register(&fsm->mtd, NULL, 0); } static int stfsm_remove(struct platform_device *pdev) @@ -2127,8 +2113,6 @@ static int stfsm_remove(struct platform_device *pdev) WARN_ON(mtd_device_unregister(&fsm->mtd)); - clk_disable_unprepare(fsm->clk); - return 0; } diff --git a/drivers/mtd/maps/pismo.c b/drivers/mtd/maps/pismo.c index 3e0fff3f129e7cbc6bc18963b046824e7ce2caaa..ecf68922da73e552f34dd88a19f64a62982f057a 100644 --- a/drivers/mtd/maps/pismo.c +++ b/drivers/mtd/maps/pismo.c @@ -259,7 +259,7 @@ static struct i2c_driver pismo_driver = { .driver = { .name = "pismo", }, - .probe_new = pismo_probe, + .probe = pismo_probe, .remove = pismo_remove, .id_table = pismo_id, }; diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c index 60b222799871e8fcd89e3e1c5bd569b34ecf51b1..ff18636e08897391d48950b0338c408b438727d9 100644 --- a/drivers/mtd/mtd_blkdevs.c +++ b/drivers/mtd/mtd_blkdevs.c @@ -182,9 +182,9 @@ static blk_status_t mtd_queue_rq(struct blk_mq_hw_ctx *hctx, return BLK_STS_OK; } -static int blktrans_open(struct block_device *bdev, fmode_t mode) +static int blktrans_open(struct gendisk *disk, blk_mode_t mode) { - struct mtd_blktrans_dev *dev = bdev->bd_disk->private_data; + struct mtd_blktrans_dev *dev = disk->private_data; int ret = 0; kref_get(&dev->ref); @@ -208,7 +208,7 @@ static int blktrans_open(struct block_device *bdev, fmode_t mode) ret = __get_mtd_device(dev->mtd); if (ret) goto error_release; - dev->file_mode = mode; + dev->writable = mode & BLK_OPEN_WRITE; unlock: dev->open++; @@ -225,7 +225,7 @@ static int blktrans_open(struct block_device *bdev, fmode_t mode) return ret; } -static void blktrans_release(struct gendisk *disk, fmode_t mode) +static void blktrans_release(struct gendisk *disk) { struct mtd_blktrans_dev *dev = disk->private_data; diff --git a/drivers/mtd/mtdblock.c b/drivers/mtd/mtdblock.c index a0a1194dc1d902579f79b7befdad1d61b4a671a4..fa476fb4dffb6c9289f8b5678ff4f49c06a2a4a9 100644 --- a/drivers/mtd/mtdblock.c +++ b/drivers/mtd/mtdblock.c @@ -294,7 +294,7 @@ static void mtdblock_release(struct mtd_blktrans_dev *mbd) * It was the last usage. Free the cache, but only sync if * opened for writing. */ - if (mbd->file_mode & FMODE_WRITE) + if (mbd->writable) mtd_sync(mbd->mtd); vfree(mtdblk->cache_data); } diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c index 60670b2f70b9f988f8add4fa590b5c11a32a6a86..e00b12aa5ec91c32802177128f9b13be251c64c8 100644 --- a/drivers/mtd/mtdcore.c +++ b/drivers/mtd/mtdcore.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -966,6 +967,26 @@ static int mtd_otp_nvmem_add(struct mtd_info *mtd) } if (size > 0) { + /* + * The factory OTP contains thing such as a unique serial + * number and is small, so let's read it out and put it + * into the entropy pool. + */ + void *otp; + + otp = kmalloc(size, GFP_KERNEL); + if (!otp) { + err = -ENOMEM; + goto err; + } + err = mtd_nvmem_fact_otp_reg_read(mtd, 0, otp, size); + if (err < 0) { + kfree(otp); + goto err; + } + add_device_randomness(otp, err); + kfree(otp); + nvmem = mtd_otp_nvmem_register(mtd, "factory-otp", size, mtd_nvmem_fact_otp_reg_read); if (IS_ERR(nvmem)) { diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c index 85f5ee6f06fc6344715d6c8bedc1a79bc4d68ea2..a46affbb037d23ba879d583a2cf9d9fd4b13fab6 100644 --- a/drivers/mtd/mtdpart.c +++ b/drivers/mtd/mtdpart.c @@ -326,7 +326,6 @@ static int __mtd_del_partition(struct mtd_info *mtd) static int __del_mtd_partitions(struct mtd_info *mtd) { struct mtd_info *child, *next; - LIST_HEAD(tmp_list); int ret, err = 0; list_for_each_entry_safe(child, next, &mtd->partitions, part.node) { diff --git a/drivers/mtd/nand/raw/Makefile b/drivers/mtd/nand/raw/Makefile index 917cdfb815b9f19f16e0a8d58529ec2b5da91107..d93e861d8ba7aead6e87820484dd2bfe791f7a12 100644 --- a/drivers/mtd/nand/raw/Makefile +++ b/drivers/mtd/nand/raw/Makefile @@ -67,5 +67,6 @@ nand-objs += nand_esmt.o nand-objs += nand_hynix.o nand-objs += nand_macronix.o nand-objs += nand_micron.o +nand-objs += nand_sandisk.o nand-objs += nand_samsung.o nand-objs += nand_toshiba.o diff --git a/drivers/mtd/nand/raw/arasan-nand-controller.c b/drivers/mtd/nand/raw/arasan-nand-controller.c index d513d2db3549ead2808749e49e5e55c2b407b932..906eef70cb6d9c5b26a0ffca95148e071a596bb8 100644 --- a/drivers/mtd/nand/raw/arasan-nand-controller.c +++ b/drivers/mtd/nand/raw/arasan-nand-controller.c @@ -973,21 +973,6 @@ static int anfc_setup_interface(struct nand_chip *chip, int target, nvddr = nand_get_nvddr_timings(conf); if (IS_ERR(nvddr)) return PTR_ERR(nvddr); - - /* - * The controller only supports data payload requests which are - * a multiple of 4. In practice, most data accesses are 4-byte - * aligned and this is not an issue. However, rounding up will - * simply be refused by the controller if we reached the end of - * the device *and* we are using the NV-DDR interface(!). In - * this situation, unaligned data requests ending at the device - * boundary will confuse the controller and cannot be performed. - * - * This is something that happens in nand_read_subpage() when - * selecting software ECC support and must be avoided. - */ - if (chip->ecc.engine_type == NAND_ECC_ENGINE_TYPE_SOFT) - return -ENOTSUPP; } else { sdr = nand_get_sdr_timings(conf); if (IS_ERR(sdr)) diff --git a/drivers/mtd/nand/raw/internals.h b/drivers/mtd/nand/raw/internals.h index 7016e0f38398e201f4b489ad541934876f5debbe..e9932da18bdd56939d03f0c09418d60f9dbcedf6 100644 --- a/drivers/mtd/nand/raw/internals.h +++ b/drivers/mtd/nand/raw/internals.h @@ -73,6 +73,7 @@ extern const struct nand_manufacturer_ops hynix_nand_manuf_ops; extern const struct nand_manufacturer_ops macronix_nand_manuf_ops; extern const struct nand_manufacturer_ops micron_nand_manuf_ops; extern const struct nand_manufacturer_ops samsung_nand_manuf_ops; +extern const struct nand_manufacturer_ops sandisk_nand_manuf_ops; extern const struct nand_manufacturer_ops toshiba_nand_manuf_ops; /* MLC pairing schemes */ diff --git a/drivers/mtd/nand/raw/meson_nand.c b/drivers/mtd/nand/raw/meson_nand.c index 1feea7d822520495f41a3971213cb7eabb243407..d3faf80866314622aefbfb9d927124a3ebd72736 100644 --- a/drivers/mtd/nand/raw/meson_nand.c +++ b/drivers/mtd/nand/raw/meson_nand.c @@ -38,6 +38,7 @@ #define NFC_CMD_SCRAMBLER_DISABLE 0 #define NFC_CMD_SHORTMODE_DISABLE 0 #define NFC_CMD_RB_INT BIT(14) +#define NFC_CMD_RB_INT_NO_PIN ((0xb << 10) | BIT(18) | BIT(16)) #define NFC_CMD_GET_SIZE(x) (((x) >> 22) & GENMASK(4, 0)) @@ -76,6 +77,7 @@ #define GENCMDIADDRH(aih, addr) ((aih) | (((addr) >> 16) & 0xffff)) #define DMA_DIR(dir) ((dir) ? NFC_CMD_N2M : NFC_CMD_M2N) +#define DMA_ADDR_ALIGN 8 #define ECC_CHECK_RETURN_FF (-1) @@ -108,6 +110,11 @@ #define PER_INFO_BYTE 8 +#define NFC_CMD_RAW_LEN GENMASK(13, 0) + +#define NFC_COLUMN_ADDR_0 0 +#define NFC_COLUMN_ADDR_1 0 + struct meson_nfc_nand_chip { struct list_head node; struct nand_chip nand; @@ -179,6 +186,7 @@ struct meson_nfc { u32 info_bytes; unsigned long assigned_cs; + bool no_rb_pin; }; enum { @@ -280,7 +288,7 @@ static void meson_nfc_cmd_access(struct nand_chip *nand, int raw, bool dir, if (raw) { len = mtd->writesize + mtd->oobsize; - cmd = (len & GENMASK(13, 0)) | scrambler | DMA_DIR(dir); + cmd = len | scrambler | DMA_DIR(dir); writel(cmd, nfc->reg_base + NFC_REG_CMD); return; } @@ -392,7 +400,42 @@ static void meson_nfc_set_data_oob(struct nand_chip *nand, } } -static int meson_nfc_queue_rb(struct meson_nfc *nfc, int timeout_ms) +static int meson_nfc_wait_no_rb_pin(struct meson_nfc *nfc, int timeout_ms, + bool need_cmd_read0) +{ + u32 cmd, cfg; + + meson_nfc_cmd_idle(nfc, nfc->timing.twb); + meson_nfc_drain_cmd(nfc); + meson_nfc_wait_cmd_finish(nfc, CMD_FIFO_EMPTY_TIMEOUT); + + cfg = readl(nfc->reg_base + NFC_REG_CFG); + cfg |= NFC_RB_IRQ_EN; + writel(cfg, nfc->reg_base + NFC_REG_CFG); + + reinit_completion(&nfc->completion); + cmd = nfc->param.chip_select | NFC_CMD_CLE | NAND_CMD_STATUS; + writel(cmd, nfc->reg_base + NFC_REG_CMD); + + /* use the max erase time as the maximum clock for waiting R/B */ + cmd = NFC_CMD_RB | NFC_CMD_RB_INT_NO_PIN | nfc->timing.tbers_max; + writel(cmd, nfc->reg_base + NFC_REG_CMD); + + if (!wait_for_completion_timeout(&nfc->completion, + msecs_to_jiffies(timeout_ms))) + return -ETIMEDOUT; + + if (need_cmd_read0) { + cmd = nfc->param.chip_select | NFC_CMD_CLE | NAND_CMD_READ0; + writel(cmd, nfc->reg_base + NFC_REG_CMD); + meson_nfc_drain_cmd(nfc); + meson_nfc_wait_cmd_finish(nfc, CMD_FIFO_EMPTY_TIMEOUT); + } + + return 0; +} + +static int meson_nfc_wait_rb_pin(struct meson_nfc *nfc, int timeout_ms) { u32 cmd, cfg; int ret = 0; @@ -420,6 +463,27 @@ static int meson_nfc_queue_rb(struct meson_nfc *nfc, int timeout_ms) return ret; } +static int meson_nfc_queue_rb(struct meson_nfc *nfc, int timeout_ms, + bool need_cmd_read0) +{ + if (nfc->no_rb_pin) { + /* This mode is used when there is no wired R/B pin. + * It works like 'nand_soft_waitrdy()', but instead of + * polling NAND_CMD_STATUS bit in the software loop, + * it will wait for interrupt - controllers checks IO + * bus and when it detects NAND_CMD_STATUS on it, it + * raises interrupt. After interrupt, NAND_CMD_READ0 is + * sent as terminator of the ready waiting procedure if + * needed (for all cases except page programming - this + * is reason of 'need_cmd_read0' flag). + */ + return meson_nfc_wait_no_rb_pin(nfc, timeout_ms, + need_cmd_read0); + } else { + return meson_nfc_wait_rb_pin(nfc, timeout_ms); + } +} + static void meson_nfc_set_user_byte(struct nand_chip *nand, u8 *oob_buf) { struct meson_nfc_nand_chip *meson_chip = to_meson_nand(nand); @@ -544,7 +608,7 @@ static int meson_nfc_read_buf(struct nand_chip *nand, u8 *buf, int len) if (ret) goto out; - cmd = NFC_CMD_N2M | (len & GENMASK(13, 0)); + cmd = NFC_CMD_N2M | len; writel(cmd, nfc->reg_base + NFC_REG_CMD); meson_nfc_drain_cmd(nfc); @@ -568,7 +632,7 @@ static int meson_nfc_write_buf(struct nand_chip *nand, u8 *buf, int len) if (ret) return ret; - cmd = NFC_CMD_M2N | (len & GENMASK(13, 0)); + cmd = NFC_CMD_M2N | len; writel(cmd, nfc->reg_base + NFC_REG_CMD); meson_nfc_drain_cmd(nfc); @@ -595,12 +659,12 @@ static int meson_nfc_rw_cmd_prepare_and_execute(struct nand_chip *nand, cmd0 = in ? NAND_CMD_READ0 : NAND_CMD_SEQIN; nfc->cmdfifo.rw.cmd0 = cs | NFC_CMD_CLE | cmd0; - addrs[0] = cs | NFC_CMD_ALE | 0; + addrs[0] = cs | NFC_CMD_ALE | NFC_COLUMN_ADDR_0; if (mtd->writesize <= 512) { cmd_num--; row_start = 1; } else { - addrs[1] = cs | NFC_CMD_ALE | 0; + addrs[1] = cs | NFC_CMD_ALE | NFC_COLUMN_ADDR_1; row_start = 2; } @@ -623,7 +687,7 @@ static int meson_nfc_rw_cmd_prepare_and_execute(struct nand_chip *nand, if (in) { nfc->cmdfifo.rw.cmd1 = cs | NFC_CMD_CLE | NAND_CMD_READSTART; writel(nfc->cmdfifo.rw.cmd1, nfc->reg_base + NFC_REG_CMD); - meson_nfc_queue_rb(nfc, PSEC_TO_MSEC(sdr->tR_max)); + meson_nfc_queue_rb(nfc, PSEC_TO_MSEC(sdr->tR_max), true); } else { meson_nfc_cmd_idle(nfc, nfc->timing.tadl); } @@ -669,7 +733,7 @@ static int meson_nfc_write_page_sub(struct nand_chip *nand, cmd = nfc->param.chip_select | NFC_CMD_CLE | NAND_CMD_PAGEPROG; writel(cmd, nfc->reg_base + NFC_REG_CMD); - meson_nfc_queue_rb(nfc, PSEC_TO_MSEC(sdr->tPROG_max)); + meson_nfc_queue_rb(nfc, PSEC_TO_MSEC(sdr->tPROG_max), false); meson_nfc_dma_buffer_release(nand, data_len, info_len, DMA_TO_DEVICE); @@ -842,6 +906,9 @@ static int meson_nfc_read_oob(struct nand_chip *nand, int page) static bool meson_nfc_is_buffer_dma_safe(const void *buffer) { + if ((uintptr_t)buffer % DMA_ADDR_ALIGN) + return false; + if (virt_addr_valid(buffer) && (!object_is_on_stack(buffer))) return true; return false; @@ -899,6 +966,31 @@ meson_nand_op_put_dma_safe_output_buf(const struct nand_op_instr *instr, kfree(buf); } +static int meson_nfc_check_op(struct nand_chip *chip, + const struct nand_operation *op) +{ + int op_id; + + for (op_id = 0; op_id < op->ninstrs; op_id++) { + const struct nand_op_instr *instr; + + instr = &op->instrs[op_id]; + + switch (instr->type) { + case NAND_OP_DATA_IN_INSTR: + case NAND_OP_DATA_OUT_INSTR: + if (instr->ctx.data.len > NFC_CMD_RAW_LEN) + return -ENOTSUPP; + + break; + default: + break; + } + } + + return 0; +} + static int meson_nfc_exec_op(struct nand_chip *nand, const struct nand_operation *op, bool check_only) { @@ -907,8 +999,13 @@ static int meson_nfc_exec_op(struct nand_chip *nand, const struct nand_op_instr *instr = NULL; void *buf; u32 op_id, delay_idle, cmd; + int err; int i; + err = meson_nfc_check_op(nand, op); + if (err) + return err; + if (check_only) return 0; @@ -952,7 +1049,8 @@ static int meson_nfc_exec_op(struct nand_chip *nand, break; case NAND_OP_WAITRDY_INSTR: - meson_nfc_queue_rb(nfc, instr->ctx.waitrdy.timeout_ms); + meson_nfc_queue_rb(nfc, instr->ctx.waitrdy.timeout_ms, + true); if (instr->delay_ns) meson_nfc_cmd_idle(nfc, delay_idle); break; @@ -1181,6 +1279,7 @@ static int meson_nand_attach_chip(struct nand_chip *nand) struct meson_nfc_nand_chip *meson_chip = to_meson_nand(nand); struct mtd_info *mtd = nand_to_mtd(nand); int nsectors = mtd->writesize / 1024; + int raw_writesize; int ret; if (!mtd->name) { @@ -1192,6 +1291,13 @@ static int meson_nand_attach_chip(struct nand_chip *nand) return -ENOMEM; } + raw_writesize = mtd->writesize + mtd->oobsize; + if (raw_writesize > NFC_CMD_RAW_LEN) { + dev_err(nfc->dev, "too big write size in raw mode: %d > %ld\n", + raw_writesize, NFC_CMD_RAW_LEN); + return -EINVAL; + } + if (nand->bbt_options & NAND_BBT_USE_FLASH) nand->bbt_options |= NAND_BBT_NO_OOB; @@ -1248,6 +1354,7 @@ meson_nfc_nand_chip_init(struct device *dev, struct mtd_info *mtd; int ret, i; u32 tmp, nsels; + u32 nand_rb_val = 0; nsels = of_property_count_elems_of_size(np, "reg", sizeof(u32)); if (!nsels || nsels > MAX_CE_NUM) { @@ -1287,6 +1394,15 @@ meson_nfc_nand_chip_init(struct device *dev, mtd->owner = THIS_MODULE; mtd->dev.parent = dev; + ret = of_property_read_u32(np, "nand-rb", &nand_rb_val); + if (ret == -EINVAL) + nfc->no_rb_pin = true; + else if (ret) + return ret; + + if (nand_rb_val) + return -EINVAL; + ret = nand_scan(nand, nsels); if (ret) return ret; diff --git a/drivers/mtd/nand/raw/nand_ids.c b/drivers/mtd/nand/raw/nand_ids.c index dacc5529b3df9f48e570449fc100dfbdc670bec2..650351c62af636bb0da069889a540cba1966871c 100644 --- a/drivers/mtd/nand/raw/nand_ids.c +++ b/drivers/mtd/nand/raw/nand_ids.c @@ -44,6 +44,9 @@ struct nand_flash_dev nand_flash_ids[] = { {"TC58NVG6D2 64G 3.3V 8-bit", { .id = {0x98, 0xde, 0x94, 0x82, 0x76, 0x56, 0x04, 0x20} }, SZ_8K, SZ_8K, SZ_2M, 0, 8, 640, NAND_ECC_INFO(40, SZ_1K) }, + {"SDTNQGAMA 64G 3.3V 8-bit", + { .id = {0x45, 0xde, 0x94, 0x93, 0x76, 0x57} }, + SZ_16K, SZ_8K, SZ_4M, 0, 6, 1280, NAND_ECC_INFO(40, SZ_1K) }, {"SDTNRGAMA 64G 3.3V 8-bit", { .id = {0x45, 0xde, 0x94, 0x93, 0x76, 0x50} }, SZ_16K, SZ_8K, SZ_4M, 0, 6, 1280, NAND_ECC_INFO(40, SZ_1K) }, @@ -188,7 +191,7 @@ static const struct nand_manufacturer_desc nand_manufacturer_descs[] = { {NAND_MFR_NATIONAL, "National"}, {NAND_MFR_RENESAS, "Renesas"}, {NAND_MFR_SAMSUNG, "Samsung", &samsung_nand_manuf_ops}, - {NAND_MFR_SANDISK, "SanDisk"}, + {NAND_MFR_SANDISK, "SanDisk", &sandisk_nand_manuf_ops}, {NAND_MFR_STMICRO, "ST Micro"}, {NAND_MFR_TOSHIBA, "Toshiba", &toshiba_nand_manuf_ops}, {NAND_MFR_WINBOND, "Winbond"}, diff --git a/drivers/mtd/nand/raw/nand_macronix.c b/drivers/mtd/nand/raw/nand_macronix.c index 385957eb676211a058a9c482d1b47ecdab3a9f72..e229de32ff5000c77280a037bcf73b52965f2ea0 100644 --- a/drivers/mtd/nand/raw/nand_macronix.c +++ b/drivers/mtd/nand/raw/nand_macronix.c @@ -6,6 +6,7 @@ * Author: Boris Brezillon */ +#include #include "linux/delay.h" #include "internals.h" @@ -31,6 +32,16 @@ #define MXIC_CMD_POWER_DOWN 0xB9 +#define ONFI_FEATURE_ADDR_30LFXG18AC_OTP 0x90 +#define MACRONIX_30LFXG18AC_OTP_START_PAGE 2 +#define MACRONIX_30LFXG18AC_OTP_PAGES 30 +#define MACRONIX_30LFXG18AC_OTP_PAGE_SIZE 2112 +#define MACRONIX_30LFXG18AC_OTP_SIZE_BYTES \ + (MACRONIX_30LFXG18AC_OTP_PAGES * \ + MACRONIX_30LFXG18AC_OTP_PAGE_SIZE) + +#define MACRONIX_30LFXG18AC_OTP_EN BIT(0) + struct nand_onfi_vendor_macronix { u8 reserved; u8 reliability_func; @@ -315,6 +326,161 @@ static void macronix_nand_deep_power_down_support(struct nand_chip *chip) chip->ops.resume = mxic_nand_resume; } +static int macronix_30lfxg18ac_get_otp_info(struct mtd_info *mtd, size_t len, + size_t *retlen, + struct otp_info *buf) +{ + if (len < sizeof(*buf)) + return -EINVAL; + + /* Always report that OTP is unlocked. Reason is that this + * type of flash chip doesn't provide way to check that OTP + * is locked or not: subfeature parameter is implemented as + * volatile register. Technically OTP region could be locked + * and become readonly, but as there is no way to check it, + * don't allow to lock it ('_lock_user_prot_reg' callback + * always returns -EOPNOTSUPP) and thus we report that OTP + * is unlocked. + */ + buf->locked = 0; + buf->start = 0; + buf->length = MACRONIX_30LFXG18AC_OTP_SIZE_BYTES; + + *retlen = sizeof(*buf); + + return 0; +} + +static int macronix_30lfxg18ac_otp_enable(struct nand_chip *nand) +{ + u8 feature_buf[ONFI_SUBFEATURE_PARAM_LEN] = { 0 }; + + feature_buf[0] = MACRONIX_30LFXG18AC_OTP_EN; + return nand_set_features(nand, ONFI_FEATURE_ADDR_30LFXG18AC_OTP, + feature_buf); +} + +static int macronix_30lfxg18ac_otp_disable(struct nand_chip *nand) +{ + u8 feature_buf[ONFI_SUBFEATURE_PARAM_LEN] = { 0 }; + + return nand_set_features(nand, ONFI_FEATURE_ADDR_30LFXG18AC_OTP, + feature_buf); +} + +static int __macronix_30lfxg18ac_rw_otp(struct mtd_info *mtd, + loff_t offs_in_flash, + size_t len, size_t *retlen, + u_char *buf, bool write) +{ + struct nand_chip *nand; + size_t bytes_handled; + off_t offs_in_page; + u64 page; + int ret; + + nand = mtd_to_nand(mtd); + nand_select_target(nand, 0); + + ret = macronix_30lfxg18ac_otp_enable(nand); + if (ret) + goto out_otp; + + page = offs_in_flash; + /* 'page' will be result of division. */ + offs_in_page = do_div(page, MACRONIX_30LFXG18AC_OTP_PAGE_SIZE); + bytes_handled = 0; + + while (bytes_handled < len && + page < MACRONIX_30LFXG18AC_OTP_PAGES) { + size_t bytes_to_handle; + u64 phys_page = page + MACRONIX_30LFXG18AC_OTP_START_PAGE; + + bytes_to_handle = min_t(size_t, len - bytes_handled, + MACRONIX_30LFXG18AC_OTP_PAGE_SIZE - + offs_in_page); + + if (write) + ret = nand_prog_page_op(nand, phys_page, offs_in_page, + &buf[bytes_handled], bytes_to_handle); + else + ret = nand_read_page_op(nand, phys_page, offs_in_page, + &buf[bytes_handled], bytes_to_handle); + if (ret) + goto out_otp; + + bytes_handled += bytes_to_handle; + offs_in_page = 0; + page++; + } + + *retlen = bytes_handled; + +out_otp: + if (ret) + dev_err(&mtd->dev, "failed to perform OTP IO: %i\n", ret); + + ret = macronix_30lfxg18ac_otp_disable(nand); + if (ret) + dev_err(&mtd->dev, "failed to leave OTP mode after %s\n", + write ? "write" : "read"); + + nand_deselect_target(nand); + + return ret; +} + +static int macronix_30lfxg18ac_write_otp(struct mtd_info *mtd, loff_t to, + size_t len, size_t *rlen, + const u_char *buf) +{ + return __macronix_30lfxg18ac_rw_otp(mtd, to, len, rlen, (u_char *)buf, + true); +} + +static int macronix_30lfxg18ac_read_otp(struct mtd_info *mtd, loff_t from, + size_t len, size_t *rlen, + u_char *buf) +{ + return __macronix_30lfxg18ac_rw_otp(mtd, from, len, rlen, buf, false); +} + +static int macronix_30lfxg18ac_lock_otp(struct mtd_info *mtd, loff_t from, + size_t len) +{ + /* See comment in 'macronix_30lfxg18ac_get_otp_info()'. */ + return -EOPNOTSUPP; +} + +static void macronix_nand_setup_otp(struct nand_chip *chip) +{ + static const char * const supported_otp_models[] = { + "MX30LF1G18AC", + "MX30LF2G18AC", + "MX30LF4G18AC", + }; + struct mtd_info *mtd; + + if (match_string(supported_otp_models, + ARRAY_SIZE(supported_otp_models), + chip->parameters.model) < 0) + return; + + if (!chip->parameters.supports_set_get_features) + return; + + bitmap_set(chip->parameters.get_feature_list, + ONFI_FEATURE_ADDR_30LFXG18AC_OTP, 1); + bitmap_set(chip->parameters.set_feature_list, + ONFI_FEATURE_ADDR_30LFXG18AC_OTP, 1); + + mtd = nand_to_mtd(chip); + mtd->_get_user_prot_info = macronix_30lfxg18ac_get_otp_info; + mtd->_read_user_prot_reg = macronix_30lfxg18ac_read_otp; + mtd->_write_user_prot_reg = macronix_30lfxg18ac_write_otp; + mtd->_lock_user_prot_reg = macronix_30lfxg18ac_lock_otp; +} + static int macronix_nand_init(struct nand_chip *chip) { if (nand_is_slc(chip)) @@ -324,6 +490,7 @@ static int macronix_nand_init(struct nand_chip *chip) macronix_nand_onfi_init(chip); macronix_nand_block_protection_support(chip); macronix_nand_deep_power_down_support(chip); + macronix_nand_setup_otp(chip); return 0; } diff --git a/drivers/mtd/nand/raw/nand_sandisk.c b/drivers/mtd/nand/raw/nand_sandisk.c new file mode 100644 index 0000000000000000000000000000000000000000..7c66e4187dc77893d4ef50cdc1600d0c2dd1f9e3 --- /dev/null +++ b/drivers/mtd/nand/raw/nand_sandisk.c @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "internals.h" + +static int +sdtnqgama_choose_interface_config(struct nand_chip *chip, + struct nand_interface_config *iface) +{ + onfi_fill_interface_config(chip, iface, NAND_SDR_IFACE, 0); + + return nand_choose_best_sdr_timings(chip, iface, NULL); +} + +static int sandisk_nand_init(struct nand_chip *chip) +{ + if (!strncmp("SDTNQGAMA", chip->parameters.model, + sizeof("SDTNQGAMA") - 1)) + chip->ops.choose_interface_config = + &sdtnqgama_choose_interface_config; + + return 0; +} + +const struct nand_manufacturer_ops sandisk_nand_manuf_ops = { + .init = sandisk_nand_init, +}; diff --git a/drivers/mtd/nand/spi/gigadevice.c b/drivers/mtd/nand/spi/gigadevice.c index 6b043e24855fb1b557d44a01ceb5b163d115b78d..cfd7c3b26dc45a4cbd9f2f93b490225450258fba 100644 --- a/drivers/mtd/nand/spi/gigadevice.c +++ b/drivers/mtd/nand/spi/gigadevice.c @@ -501,6 +501,16 @@ static const struct spinand_info gigadevice_spinand_table[] = { SPINAND_HAS_QE_BIT, SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout, gd5fxgq4uexxg_ecc_get_status)), + SPINAND_INFO("GD5F2GQ5xExxH", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x22), + NAND_MEMORG(1, 2048, 64, 64, 2048, 40, 1, 1, 1), + NAND_ECCREQ(4, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants_2gq5, + &write_cache_variants, + &update_cache_variants), + SPINAND_HAS_QE_BIT, + SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout, + gd5fxgq4uexxg_ecc_get_status)), }; static const struct spinand_manufacturer_ops gigadevice_spinand_manuf_ops = { diff --git a/drivers/mtd/nand/spi/macronix.c b/drivers/mtd/nand/spi/macronix.c index 722a9738ba370f1ff70922e710cbf8375adf5e4e..3dfc7e1e52410272753436074053cae2383f08fe 100644 --- a/drivers/mtd/nand/spi/macronix.c +++ b/drivers/mtd/nand/spi/macronix.c @@ -299,6 +299,26 @@ static const struct spinand_info macronix_spinand_table[] = { SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, mx35lf1ge4ab_ecc_get_status)), + SPINAND_INFO("MX31LF2GE4BC", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x2e), + NAND_MEMORG(1, 2048, 64, 64, 2048, 40, 1, 1, 1), + NAND_ECCREQ(8, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, + &write_cache_variants, + &update_cache_variants), + SPINAND_HAS_QE_BIT, + SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, + mx35lf1ge4ab_ecc_get_status)), + SPINAND_INFO("MX3UF2GE4BC", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xae), + NAND_MEMORG(1, 2048, 64, 64, 2048, 40, 1, 1, 1), + NAND_ECCREQ(8, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, + &write_cache_variants, + &update_cache_variants), + SPINAND_HAS_QE_BIT, + SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, + mx35lf1ge4ab_ecc_get_status)), }; static const struct spinand_manufacturer_ops macronix_spinand_manuf_ops = { diff --git a/drivers/mtd/sm_ftl.c b/drivers/mtd/sm_ftl.c index 4cfec3b7b4461d585381a5037ac8c81e807bba10..b5b3c4c44a94c410a2c4dee725d58dccb6ce6842 100644 --- a/drivers/mtd/sm_ftl.c +++ b/drivers/mtd/sm_ftl.c @@ -981,7 +981,7 @@ static int sm_cache_flush(struct sm_ftl *ftl) /* Update the FTL table */ zone->lba_to_phys_table[ftl->cache_block] = write_sector; - /* Write succesfull, so erase and free the old block */ + /* Write successful, so erase and free the old block */ if (block_num > 0) sm_erase_block(ftl, zone_num, block_num, 1); diff --git a/drivers/mtd/ubi/block.c b/drivers/mtd/ubi/block.c index 3711d7f746003d3902a3b7b41865f81aea0c97b3..437c5b83ffe51347b40841edbc7409ef91c0bd83 100644 --- a/drivers/mtd/ubi/block.c +++ b/drivers/mtd/ubi/block.c @@ -227,9 +227,9 @@ static blk_status_t ubiblock_read(struct request *req) return BLK_STS_OK; } -static int ubiblock_open(struct block_device *bdev, fmode_t mode) +static int ubiblock_open(struct gendisk *disk, blk_mode_t mode) { - struct ubiblock *dev = bdev->bd_disk->private_data; + struct ubiblock *dev = disk->private_data; int ret; mutex_lock(&dev->dev_mutex); @@ -246,11 +246,10 @@ static int ubiblock_open(struct block_device *bdev, fmode_t mode) * It's just a paranoid check, as write requests will get rejected * in any case. */ - if (mode & FMODE_WRITE) { + if (mode & BLK_OPEN_WRITE) { ret = -EROFS; goto out_unlock; } - dev->desc = ubi_open_volume(dev->ubi_num, dev->vol_id, UBI_READONLY); if (IS_ERR(dev->desc)) { dev_err(disk_to_dev(dev->gd), "failed to open ubi volume %d_%d", @@ -270,7 +269,7 @@ static int ubiblock_open(struct block_device *bdev, fmode_t mode) return ret; } -static void ubiblock_release(struct gendisk *gd, fmode_t mode) +static void ubiblock_release(struct gendisk *gd) { struct ubiblock *dev = gd->private_data; diff --git a/drivers/mux/Kconfig b/drivers/mux/Kconfig index e5c571fd232cc2f220d84e72339443c5176b272e..80f015cf6e54f635bdae45b791c0c51a73222bfc 100644 --- a/drivers/mux/Kconfig +++ b/drivers/mux/Kconfig @@ -47,7 +47,7 @@ config MUX_GPIO config MUX_MMIO tristate "MMIO/Regmap register bitfield-controlled Multiplexer" - depends on OF || COMPILE_TEST + depends on OF help MMIO/Regmap register bitfield-controlled Multiplexer controller. diff --git a/drivers/mux/adg792a.c b/drivers/mux/adg792a.c index e8fc2fc1ab090da7995fa93b74b47cfb833fef14..4da5aecb9fc62bc38c4ab67e839a8f86fa7be5e2 100644 --- a/drivers/mux/adg792a.c +++ b/drivers/mux/adg792a.c @@ -143,7 +143,7 @@ static struct i2c_driver adg792a_driver = { .name = "adg792a", .of_match_table = of_match_ptr(adg792a_of_match), }, - .probe_new = adg792a_probe, + .probe = adg792a_probe, .id_table = adg792a_id, }; module_i2c_driver(adg792a_driver); diff --git a/drivers/mux/mmio.c b/drivers/mux/mmio.c index 44a7a0e885b8dc0ab5b436ea6366a7a87a8ef59b..245bc07eee4ba12d2956024e6fcfb4741a3531af 100644 --- a/drivers/mux/mmio.c +++ b/drivers/mux/mmio.c @@ -131,7 +131,7 @@ static int mux_mmio_probe(struct platform_device *pdev) static struct platform_driver mux_mmio_driver = { .driver = { .name = "mmio-mux", - .of_match_table = of_match_ptr(mux_mmio_dt_ids), + .of_match_table = mux_mmio_dt_ids, }, .probe = mux_mmio_probe, }; diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index d0a1ed216d154d0627683cd2e8320ecd08da1c9c..368c6f5b327e8a645ef1e440989b6ad172e88e9b 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -403,7 +403,6 @@ config TUN_VNET_CROSS_LE config VETH tristate "Virtual ethernet pair device" select PAGE_POOL - select PAGE_POOL_STATS help This device is a local ethernet tunnel. Devices are created in pairs. When one end receives the packet it appears on its pair and vice diff --git a/drivers/net/arcnet/arcnet.c b/drivers/net/arcnet/arcnet.c index 1bad1866ae462d9067b300778846b23dceb873af..99265667538c3c87ab0c9a84fe8544145b8dcb19 100644 --- a/drivers/net/arcnet/arcnet.c +++ b/drivers/net/arcnet/arcnet.c @@ -196,13 +196,10 @@ static void arcnet_dump_packet(struct net_device *dev, int bufnum, void arcnet_led_event(struct net_device *dev, enum arcnet_led_event event) { struct arcnet_local *lp = netdev_priv(dev); - unsigned long led_delay = 350; - unsigned long tx_delay = 50; switch (event) { case ARCNET_LED_EVENT_RECON: - led_trigger_blink_oneshot(lp->recon_led_trig, - &led_delay, &led_delay, 0); + led_trigger_blink_oneshot(lp->recon_led_trig, 350, 350, 0); break; case ARCNET_LED_EVENT_OPEN: led_trigger_event(lp->tx_led_trig, LED_OFF); @@ -213,8 +210,7 @@ void arcnet_led_event(struct net_device *dev, enum arcnet_led_event event) led_trigger_event(lp->recon_led_trig, LED_OFF); break; case ARCNET_LED_EVENT_TX: - led_trigger_blink_oneshot(lp->tx_led_trig, - &tx_delay, &tx_delay, 0); + led_trigger_blink_oneshot(lp->tx_led_trig, 50, 50, 0); break; } } diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index edbaa1444f8ecd9bf344a50f6f599d7eaaf4ff3e..7a0f25301f7ec25f471cb74b856342dfdbefd21d 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -1,8 +1,9 @@ +// SPDX-License-Identifier: GPL-1.0+ /* * originally based on the dummy device. * * Copyright 1999, Thomas Davis, tadavis@lbl.gov. - * Licensed under the GPL. Based on dummy.c, and eql.c devices. + * Based on dummy.c, and eql.c devices. * * bonding.c: an Ethernet Bonding driver * @@ -2871,6 +2872,8 @@ static bool bond_has_this_ip(struct bonding *bond, __be32 ip) return ret; } +#define BOND_VLAN_PROTO_NONE cpu_to_be16(0xffff) + static bool bond_handle_vlan(struct slave *slave, struct bond_vlan_tag *tags, struct sk_buff *skb) { @@ -2878,13 +2881,13 @@ static bool bond_handle_vlan(struct slave *slave, struct bond_vlan_tag *tags, struct net_device *slave_dev = slave->dev; struct bond_vlan_tag *outer_tag = tags; - if (!tags || tags->vlan_proto == VLAN_N_VID) + if (!tags || tags->vlan_proto == BOND_VLAN_PROTO_NONE) return true; tags++; /* Go through all the tags backwards and add them to the packet */ - while (tags->vlan_proto != VLAN_N_VID) { + while (tags->vlan_proto != BOND_VLAN_PROTO_NONE) { if (!tags->vlan_id) { tags++; continue; @@ -2960,7 +2963,7 @@ struct bond_vlan_tag *bond_verify_device_path(struct net_device *start_dev, tags = kcalloc(level + 1, sizeof(*tags), GFP_ATOMIC); if (!tags) return ERR_PTR(-ENOMEM); - tags[level].vlan_proto = VLAN_N_VID; + tags[level].vlan_proto = BOND_VLAN_PROTO_NONE; return tags; } @@ -4197,7 +4200,7 @@ u32 bond_xmit_hash(struct bonding *bond, struct sk_buff *skb) return skb->hash; return __bond_xmit_hash(bond, skb, skb->data, skb->protocol, - skb_mac_offset(skb), skb_network_offset(skb), + 0, skb_network_offset(skb), skb_headlen(skb)); } @@ -5439,7 +5442,7 @@ static netdev_tx_t bond_tls_device_xmit(struct bonding *bond, struct sk_buff *sk { struct net_device *tls_netdev = rcu_dereference(tls_get_ctx(skb->sk)->netdev); - /* tls_netdev might become NULL, even if tls_is_sk_tx_device_offloaded + /* tls_netdev might become NULL, even if tls_is_skb_tx_device_offloaded * was true, if tls_device_down is running in parallel, but it's OK, * because bond_get_slave_by_dev has a NULL check. */ @@ -5458,7 +5461,7 @@ static netdev_tx_t __bond_start_xmit(struct sk_buff *skb, struct net_device *dev return NETDEV_TX_OK; #if IS_ENABLED(CONFIG_TLS_DEVICE) - if (skb->sk && tls_is_sk_tx_device_offloaded(skb->sk)) + if (tls_is_skb_tx_device_offloaded(skb)) return bond_tls_device_xmit(bond, skb, dev); #endif diff --git a/drivers/net/bonding/bonding_priv.h b/drivers/net/bonding/bonding_priv.h index 48cdf3a49a7d745ff50dc9ad1e7ca90ebd3c8afc..fef6288c6944fb6f88046e9846c234352492c7f5 100644 --- a/drivers/net/bonding/bonding_priv.h +++ b/drivers/net/bonding/bonding_priv.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-1.0+ */ /* * Bond several ethernet interfaces into a Cisco, running 'Etherchannel'. * @@ -7,9 +8,6 @@ * BUT, I'm the one who modified it for ethernet, so: * (c) Copyright 1999, Thomas Davis, tadavis@lbl.gov * - * This software may be used and distributed according to the terms - * of the GNU Public License, incorporated herein by reference. - * */ #ifndef _BONDING_PRIV_H diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig index b190007c01bec5f4e3b6bf11a60026560e09f333..a5c5036dfb943888958e9299780a56a11b41c89e 100644 --- a/drivers/net/can/Kconfig +++ b/drivers/net/can/Kconfig @@ -153,8 +153,7 @@ config CAN_JANZ_ICAN3 config CAN_KVASER_PCIEFD depends on PCI tristate "Kvaser PCIe FD cards" - select CRC32 - help + help This is a driver for the Kvaser PCI Express CAN FD family. Supported devices: diff --git a/drivers/net/can/at91_can.c b/drivers/net/can/at91_can.c index 199cb200f2bdd246068830de3d00ceeb4cae4047..4621266851ed42a9e18aae2ece6ee434bc9f7a39 100644 --- a/drivers/net/can/at91_can.c +++ b/drivers/net/can/at91_can.c @@ -1346,7 +1346,7 @@ static int at91_can_probe(struct platform_device *pdev) return err; } -static int at91_can_remove(struct platform_device *pdev) +static void at91_can_remove(struct platform_device *pdev) { struct net_device *dev = platform_get_drvdata(pdev); struct at91_priv *priv = netdev_priv(dev); @@ -1362,8 +1362,6 @@ static int at91_can_remove(struct platform_device *pdev) clk_put(priv->clk); free_candev(dev); - - return 0; } static const struct platform_device_id at91_can_id_table[] = { @@ -1381,7 +1379,7 @@ MODULE_DEVICE_TABLE(platform, at91_can_id_table); static struct platform_driver at91_can_driver = { .probe = at91_can_probe, - .remove = at91_can_remove, + .remove_new = at91_can_remove, .driver = { .name = KBUILD_MODNAME, .of_match_table = of_match_ptr(at91_can_dt_ids), diff --git a/drivers/net/can/bxcan.c b/drivers/net/can/bxcan.c index 027a8a162fe49fb3457dd943b8d84cd55e4f319e..39de7164bc4e102bed26822a22882f0095e4cfb9 100644 --- a/drivers/net/can/bxcan.c +++ b/drivers/net/can/bxcan.c @@ -966,22 +966,16 @@ static int bxcan_probe(struct platform_device *pdev) } rx_irq = platform_get_irq_byname(pdev, "rx0"); - if (rx_irq < 0) { - dev_err(dev, "failed to get rx0 irq\n"); + if (rx_irq < 0) return rx_irq; - } tx_irq = platform_get_irq_byname(pdev, "tx"); - if (tx_irq < 0) { - dev_err(dev, "failed to get tx irq\n"); + if (tx_irq < 0) return tx_irq; - } sce_irq = platform_get_irq_byname(pdev, "sce"); - if (sce_irq < 0) { - dev_err(dev, "failed to get sce irq\n"); + if (sce_irq < 0) return sce_irq; - } ndev = alloc_candev(sizeof(struct bxcan_priv), BXCAN_TX_MB_NUM); if (!ndev) { @@ -1039,7 +1033,7 @@ static int bxcan_probe(struct platform_device *pdev) return err; } -static int bxcan_remove(struct platform_device *pdev) +static void bxcan_remove(struct platform_device *pdev) { struct net_device *ndev = platform_get_drvdata(pdev); struct bxcan_priv *priv = netdev_priv(ndev); @@ -1048,7 +1042,6 @@ static int bxcan_remove(struct platform_device *pdev) clk_disable_unprepare(priv->clk); can_rx_offload_del(&priv->offload); free_candev(ndev); - return 0; } static int __maybe_unused bxcan_suspend(struct device *dev) @@ -1100,7 +1093,7 @@ static struct platform_driver bxcan_driver = { .of_match_table = bxcan_of_match, }, .probe = bxcan_probe, - .remove = bxcan_remove, + .remove_new = bxcan_remove, }; module_platform_driver(bxcan_driver); diff --git a/drivers/net/can/c_can/c_can_platform.c b/drivers/net/can/c_can/c_can_platform.c index 03ccb7cfacaf8e1b4862d8cb70ac5dcaa31d038a..925930b6c4ca5f020cd70197d77486d391233c6b 100644 --- a/drivers/net/can/c_can/c_can_platform.c +++ b/drivers/net/can/c_can/c_can_platform.c @@ -410,7 +410,7 @@ static int c_can_plat_probe(struct platform_device *pdev) return ret; } -static int c_can_plat_remove(struct platform_device *pdev) +static void c_can_plat_remove(struct platform_device *pdev) { struct net_device *dev = platform_get_drvdata(pdev); struct c_can_priv *priv = netdev_priv(dev); @@ -418,8 +418,6 @@ static int c_can_plat_remove(struct platform_device *pdev) unregister_c_can_dev(dev); pm_runtime_disable(priv->device); free_c_can_dev(dev); - - return 0; } #ifdef CONFIG_PM @@ -487,7 +485,7 @@ static struct platform_driver c_can_plat_driver = { .of_match_table = c_can_of_table, }, .probe = c_can_plat_probe, - .remove = c_can_plat_remove, + .remove_new = c_can_plat_remove, .suspend = c_can_suspend, .resume = c_can_resume, .id_table = c_can_id_table, diff --git a/drivers/net/can/cc770/cc770_isa.c b/drivers/net/can/cc770/cc770_isa.c index 8f6dccd5a58792fc143cb462e176c9a2fdd4c69b..22009440a983ee3d602a99882603ea423b63a54e 100644 --- a/drivers/net/can/cc770/cc770_isa.c +++ b/drivers/net/can/cc770/cc770_isa.c @@ -285,7 +285,7 @@ static int cc770_isa_probe(struct platform_device *pdev) return err; } -static int cc770_isa_remove(struct platform_device *pdev) +static void cc770_isa_remove(struct platform_device *pdev) { struct net_device *dev = platform_get_drvdata(pdev); struct cc770_priv *priv = netdev_priv(dev); @@ -303,13 +303,11 @@ static int cc770_isa_remove(struct platform_device *pdev) release_region(port[idx], CC770_IOSIZE); } free_cc770dev(dev); - - return 0; } static struct platform_driver cc770_isa_driver = { .probe = cc770_isa_probe, - .remove = cc770_isa_remove, + .remove_new = cc770_isa_remove, .driver = { .name = KBUILD_MODNAME, }, diff --git a/drivers/net/can/cc770/cc770_platform.c b/drivers/net/can/cc770/cc770_platform.c index 8dcc32e4e30efac4f655cf9f28d856758d97252a..13bcfba05f18ff57f733e1b6c8c99d99a2218ac4 100644 --- a/drivers/net/can/cc770/cc770_platform.c +++ b/drivers/net/can/cc770/cc770_platform.c @@ -230,7 +230,7 @@ static int cc770_platform_probe(struct platform_device *pdev) return err; } -static int cc770_platform_remove(struct platform_device *pdev) +static void cc770_platform_remove(struct platform_device *pdev) { struct net_device *dev = platform_get_drvdata(pdev); struct cc770_priv *priv = netdev_priv(dev); @@ -242,8 +242,6 @@ static int cc770_platform_remove(struct platform_device *pdev) mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); release_mem_region(mem->start, resource_size(mem)); - - return 0; } static const struct of_device_id cc770_platform_table[] = { @@ -259,7 +257,7 @@ static struct platform_driver cc770_platform_driver = { .of_match_table = cc770_platform_table, }, .probe = cc770_platform_probe, - .remove = cc770_platform_remove, + .remove_new = cc770_platform_remove, }; module_platform_driver(cc770_platform_driver); diff --git a/drivers/net/can/ctucanfd/ctucanfd_platform.c b/drivers/net/can/ctucanfd/ctucanfd_platform.c index a17561d971929840349ae4f469aeb883eedc1c7f..55bb10b157b498107dc4722c3754be8479a731e6 100644 --- a/drivers/net/can/ctucanfd/ctucanfd_platform.c +++ b/drivers/net/can/ctucanfd/ctucanfd_platform.c @@ -86,7 +86,7 @@ static int ctucan_platform_probe(struct platform_device *pdev) * This function frees all the resources allocated to the device. * Return: 0 always */ -static int ctucan_platform_remove(struct platform_device *pdev) +static void ctucan_platform_remove(struct platform_device *pdev) { struct net_device *ndev = platform_get_drvdata(pdev); struct ctucan_priv *priv = netdev_priv(ndev); @@ -97,8 +97,6 @@ static int ctucan_platform_remove(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); netif_napi_del(&priv->napi); free_candev(ndev); - - return 0; } static SIMPLE_DEV_PM_OPS(ctucan_platform_pm_ops, ctucan_suspend, ctucan_resume); @@ -113,7 +111,7 @@ MODULE_DEVICE_TABLE(of, ctucan_of_match); static struct platform_driver ctucanfd_driver = { .probe = ctucan_platform_probe, - .remove = ctucan_platform_remove, + .remove_new = ctucan_platform_remove, .driver = { .name = DRV_NAME, .pm = &ctucan_platform_pm_ops, diff --git a/drivers/net/can/dev/length.c b/drivers/net/can/dev/length.c index b48140b1102ea0ef8040c790578f9595df78e398..b7f4d76dd444fc99539dccfdede621867cd11037 100644 --- a/drivers/net/can/dev/length.c +++ b/drivers/net/can/dev/length.c @@ -78,18 +78,7 @@ unsigned int can_skb_get_frame_len(const struct sk_buff *skb) else len = cf->len; - if (can_is_canfd_skb(skb)) { - if (cf->can_id & CAN_EFF_FLAG) - len += CANFD_FRAME_OVERHEAD_EFF; - else - len += CANFD_FRAME_OVERHEAD_SFF; - } else { - if (cf->can_id & CAN_EFF_FLAG) - len += CAN_FRAME_OVERHEAD_EFF; - else - len += CAN_FRAME_OVERHEAD_SFF; - } - - return len; + return can_frame_bytes(can_is_canfd_skb(skb), cf->can_id & CAN_EFF_FLAG, + false, len); } EXPORT_SYMBOL_GPL(can_skb_get_frame_len); diff --git a/drivers/net/can/dev/rx-offload.c b/drivers/net/can/dev/rx-offload.c index 81ebf0562c89d24ec4008d0d69e0256bcc099cb3..161e45a7e8c1135700165b553704c4256baef63f 100644 --- a/drivers/net/can/dev/rx-offload.c +++ b/drivers/net/can/dev/rx-offload.c @@ -220,7 +220,7 @@ int can_rx_offload_irq_offload_fifo(struct can_rx_offload *offload) EXPORT_SYMBOL_GPL(can_rx_offload_irq_offload_fifo); int can_rx_offload_queue_timestamp(struct can_rx_offload *offload, - struct sk_buff *skb, u32 timestamp) + struct sk_buff *skb, u32 timestamp) { struct can_rx_offload_cb *cb; diff --git a/drivers/net/can/flexcan/flexcan-core.c b/drivers/net/can/flexcan/flexcan-core.c index 6d638c93977bc7744c2c44b89dd82d3d2d967f4e..ff0fc18baf133c86596da9d6c7d630870b5c0cfc 100644 --- a/drivers/net/can/flexcan/flexcan-core.c +++ b/drivers/net/can/flexcan/flexcan-core.c @@ -2218,7 +2218,7 @@ static int flexcan_probe(struct platform_device *pdev) return err; } -static int flexcan_remove(struct platform_device *pdev) +static void flexcan_remove(struct platform_device *pdev) { struct net_device *dev = platform_get_drvdata(pdev); @@ -2227,8 +2227,6 @@ static int flexcan_remove(struct platform_device *pdev) unregister_flexcandev(dev); pm_runtime_disable(&pdev->dev); free_candev(dev); - - return 0; } static int __maybe_unused flexcan_suspend(struct device *device) @@ -2379,7 +2377,7 @@ static struct platform_driver flexcan_driver = { .of_match_table = flexcan_of_match, }, .probe = flexcan_probe, - .remove = flexcan_remove, + .remove_new = flexcan_remove, .id_table = flexcan_id_table, }; diff --git a/drivers/net/can/grcan.c b/drivers/net/can/grcan.c index 4bedcc3eea0d6726a821e2772ad45424a3be2872..3174efdae271af8ce820984da9aaad617f927e31 100644 --- a/drivers/net/can/grcan.c +++ b/drivers/net/can/grcan.c @@ -1696,7 +1696,7 @@ static int grcan_probe(struct platform_device *ofdev) return err; } -static int grcan_remove(struct platform_device *ofdev) +static void grcan_remove(struct platform_device *ofdev) { struct net_device *dev = platform_get_drvdata(ofdev); struct grcan_priv *priv = netdev_priv(dev); @@ -1706,8 +1706,6 @@ static int grcan_remove(struct platform_device *ofdev) irq_dispose_mapping(dev->irq); netif_napi_del(&priv->napi); free_candev(dev); - - return 0; } static const struct of_device_id grcan_match[] = { @@ -1726,7 +1724,7 @@ static struct platform_driver grcan_driver = { .of_match_table = grcan_match, }, .probe = grcan_probe, - .remove = grcan_remove, + .remove_new = grcan_remove, }; module_platform_driver(grcan_driver); diff --git a/drivers/net/can/ifi_canfd/ifi_canfd.c b/drivers/net/can/ifi_canfd/ifi_canfd.c index 07eaf724a57273c78f230442d865e7ab0b2d8046..1d6642c94f2f5851b051ef91ae0426c86749f182 100644 --- a/drivers/net/can/ifi_canfd/ifi_canfd.c +++ b/drivers/net/can/ifi_canfd/ifi_canfd.c @@ -1013,15 +1013,13 @@ static int ifi_canfd_plat_probe(struct platform_device *pdev) return ret; } -static int ifi_canfd_plat_remove(struct platform_device *pdev) +static void ifi_canfd_plat_remove(struct platform_device *pdev) { struct net_device *ndev = platform_get_drvdata(pdev); unregister_candev(ndev); platform_set_drvdata(pdev, NULL); free_candev(ndev); - - return 0; } static const struct of_device_id ifi_canfd_of_table[] = { @@ -1036,7 +1034,7 @@ static struct platform_driver ifi_canfd_plat_driver = { .of_match_table = ifi_canfd_of_table, }, .probe = ifi_canfd_plat_probe, - .remove = ifi_canfd_plat_remove, + .remove_new = ifi_canfd_plat_remove, }; module_platform_driver(ifi_canfd_plat_driver); diff --git a/drivers/net/can/janz-ican3.c b/drivers/net/can/janz-ican3.c index 0732a509214182943972ec6cbf8241d7404ea067..d048ea565b89252e859b8f4be70016b8369caf7f 100644 --- a/drivers/net/can/janz-ican3.c +++ b/drivers/net/can/janz-ican3.c @@ -2023,7 +2023,7 @@ static int ican3_probe(struct platform_device *pdev) return ret; } -static int ican3_remove(struct platform_device *pdev) +static void ican3_remove(struct platform_device *pdev) { struct net_device *ndev = platform_get_drvdata(pdev); struct ican3_dev *mod = netdev_priv(ndev); @@ -2042,8 +2042,6 @@ static int ican3_remove(struct platform_device *pdev) iounmap(mod->dpm); free_candev(ndev); - - return 0; } static struct platform_driver ican3_driver = { @@ -2051,7 +2049,7 @@ static struct platform_driver ican3_driver = { .name = DRV_NAME, }, .probe = ican3_probe, - .remove = ican3_remove, + .remove_new = ican3_remove, }; module_platform_driver(ican3_driver); diff --git a/drivers/net/can/kvaser_pciefd.c b/drivers/net/can/kvaser_pciefd.c index be189edb256ceb13590b170e3294ef72264a5092..db6256f2b1b36084ee455f52379465de8e341fbe 100644 --- a/drivers/net/can/kvaser_pciefd.c +++ b/drivers/net/can/kvaser_pciefd.c @@ -3,19 +3,19 @@ * Parts of this driver are based on the following: * - Kvaser linux pciefd driver (version 5.25) * - PEAK linux canfd driver - * - Altera Avalon EPCS flash controller driver */ -#include -#include +#include +#include #include #include +#include +#include +#include +#include +#include #include -#include #include -#include -#include -#include MODULE_LICENSE("Dual BSD/GPL"); MODULE_AUTHOR("Kvaser AB "); @@ -25,42 +25,25 @@ MODULE_DESCRIPTION("CAN driver for Kvaser CAN/PCIe devices"); #define KVASER_PCIEFD_WAIT_TIMEOUT msecs_to_jiffies(1000) #define KVASER_PCIEFD_BEC_POLL_FREQ (jiffies + msecs_to_jiffies(200)) -#define KVASER_PCIEFD_MAX_ERR_REP 256 -#define KVASER_PCIEFD_CAN_TX_MAX_COUNT 17 -#define KVASER_PCIEFD_MAX_CAN_CHANNELS 4 -#define KVASER_PCIEFD_DMA_COUNT 2 +#define KVASER_PCIEFD_MAX_ERR_REP 256U +#define KVASER_PCIEFD_CAN_TX_MAX_COUNT 17U +#define KVASER_PCIEFD_MAX_CAN_CHANNELS 4UL +#define KVASER_PCIEFD_DMA_COUNT 2U -#define KVASER_PCIEFD_DMA_SIZE (4 * 1024) -#define KVASER_PCIEFD_64BIT_DMA_BIT BIT(0) +#define KVASER_PCIEFD_DMA_SIZE (4U * 1024U) #define KVASER_PCIEFD_VENDOR 0x1a07 -#define KVASER_PCIEFD_4HS_ID 0x0d -#define KVASER_PCIEFD_2HS_ID 0x0e -#define KVASER_PCIEFD_HS_ID 0x0f -#define KVASER_PCIEFD_MINIPCIE_HS_ID 0x10 -#define KVASER_PCIEFD_MINIPCIE_2HS_ID 0x11 +#define KVASER_PCIEFD_4HS_DEVICE_ID 0x000d +#define KVASER_PCIEFD_2HS_V2_DEVICE_ID 0x000e +#define KVASER_PCIEFD_HS_V2_DEVICE_ID 0x000f +#define KVASER_PCIEFD_MINIPCIE_HS_V2_DEVICE_ID 0x0010 +#define KVASER_PCIEFD_MINIPCIE_2HS_V2_DEVICE_ID 0x0011 /* PCIe IRQ registers */ #define KVASER_PCIEFD_IRQ_REG 0x40 #define KVASER_PCIEFD_IEN_REG 0x50 -/* DMA map */ +/* DMA address translation map register base */ #define KVASER_PCIEFD_DMA_MAP_BASE 0x1000 -/* Kvaser KCAN CAN controller registers */ -#define KVASER_PCIEFD_KCAN0_BASE 0x10000 -#define KVASER_PCIEFD_KCAN_BASE_OFFSET 0x1000 -#define KVASER_PCIEFD_KCAN_FIFO_REG 0x100 -#define KVASER_PCIEFD_KCAN_FIFO_LAST_REG 0x180 -#define KVASER_PCIEFD_KCAN_CTRL_REG 0x2c0 -#define KVASER_PCIEFD_KCAN_CMD_REG 0x400 -#define KVASER_PCIEFD_KCAN_IEN_REG 0x408 -#define KVASER_PCIEFD_KCAN_IRQ_REG 0x410 -#define KVASER_PCIEFD_KCAN_TX_NPACKETS_REG 0x414 -#define KVASER_PCIEFD_KCAN_STAT_REG 0x418 -#define KVASER_PCIEFD_KCAN_MODE_REG 0x41c -#define KVASER_PCIEFD_KCAN_BTRN_REG 0x420 -#define KVASER_PCIEFD_KCAN_BUS_LOAD_REG 0x424 -#define KVASER_PCIEFD_KCAN_BTRD_REG 0x428 -#define KVASER_PCIEFD_KCAN_PWM_REG 0x430 /* Loopback control register */ #define KVASER_PCIEFD_LOOP_REG 0x1f000 /* System identification and information registers */ @@ -78,183 +61,196 @@ MODULE_DESCRIPTION("CAN driver for Kvaser CAN/PCIe devices"); #define KVASER_PCIEFD_SRB_STAT_REG (KVASER_PCIEFD_SRB_BASE + 0x210) #define KVASER_PCIEFD_SRB_RX_NR_PACKETS_REG (KVASER_PCIEFD_SRB_BASE + 0x214) #define KVASER_PCIEFD_SRB_CTRL_REG (KVASER_PCIEFD_SRB_BASE + 0x218) -/* EPCS flash controller registers */ -#define KVASER_PCIEFD_SPI_BASE 0x1fc00 -#define KVASER_PCIEFD_SPI_RX_REG KVASER_PCIEFD_SPI_BASE -#define KVASER_PCIEFD_SPI_TX_REG (KVASER_PCIEFD_SPI_BASE + 0x4) -#define KVASER_PCIEFD_SPI_STATUS_REG (KVASER_PCIEFD_SPI_BASE + 0x8) -#define KVASER_PCIEFD_SPI_CTRL_REG (KVASER_PCIEFD_SPI_BASE + 0xc) -#define KVASER_PCIEFD_SPI_SSEL_REG (KVASER_PCIEFD_SPI_BASE + 0x14) - -#define KVASER_PCIEFD_IRQ_ALL_MSK 0x1f +/* Kvaser KCAN CAN controller registers */ +#define KVASER_PCIEFD_KCAN0_BASE 0x10000 +#define KVASER_PCIEFD_KCAN_BASE_OFFSET 0x1000 +#define KVASER_PCIEFD_KCAN_FIFO_REG 0x100 +#define KVASER_PCIEFD_KCAN_FIFO_LAST_REG 0x180 +#define KVASER_PCIEFD_KCAN_CTRL_REG 0x2c0 +#define KVASER_PCIEFD_KCAN_CMD_REG 0x400 +#define KVASER_PCIEFD_KCAN_IEN_REG 0x408 +#define KVASER_PCIEFD_KCAN_IRQ_REG 0x410 +#define KVASER_PCIEFD_KCAN_TX_NR_PACKETS_REG 0x414 +#define KVASER_PCIEFD_KCAN_STAT_REG 0x418 +#define KVASER_PCIEFD_KCAN_MODE_REG 0x41c +#define KVASER_PCIEFD_KCAN_BTRN_REG 0x420 +#define KVASER_PCIEFD_KCAN_BUS_LOAD_REG 0x424 +#define KVASER_PCIEFD_KCAN_BTRD_REG 0x428 +#define KVASER_PCIEFD_KCAN_PWM_REG 0x430 + +/* PCI interrupt fields */ #define KVASER_PCIEFD_IRQ_SRB BIT(4) +#define KVASER_PCIEFD_IRQ_ALL_MASK GENMASK(4, 0) -#define KVASER_PCIEFD_SYSID_NRCHAN_SHIFT 24 -#define KVASER_PCIEFD_SYSID_MAJOR_VER_SHIFT 16 -#define KVASER_PCIEFD_SYSID_BUILD_VER_SHIFT 1 +/* Enable 64-bit DMA address translation */ +#define KVASER_PCIEFD_64BIT_DMA_BIT BIT(0) + +/* System build information fields */ +#define KVASER_PCIEFD_SYSID_VERSION_NR_CHAN_MASK GENMASK(31, 24) +#define KVASER_PCIEFD_SYSID_VERSION_MAJOR_MASK GENMASK(23, 16) +#define KVASER_PCIEFD_SYSID_VERSION_MINOR_MASK GENMASK(7, 0) +#define KVASER_PCIEFD_SYSID_BUILD_SEQ_MASK GENMASK(15, 1) /* Reset DMA buffer 0, 1 and FIFO offset */ -#define KVASER_PCIEFD_SRB_CMD_RDB0 BIT(4) #define KVASER_PCIEFD_SRB_CMD_RDB1 BIT(5) +#define KVASER_PCIEFD_SRB_CMD_RDB0 BIT(4) #define KVASER_PCIEFD_SRB_CMD_FOR BIT(0) -/* DMA packet done, buffer 0 and 1 */ -#define KVASER_PCIEFD_SRB_IRQ_DPD0 BIT(8) -#define KVASER_PCIEFD_SRB_IRQ_DPD1 BIT(9) -/* DMA overflow, buffer 0 and 1 */ -#define KVASER_PCIEFD_SRB_IRQ_DOF0 BIT(10) -#define KVASER_PCIEFD_SRB_IRQ_DOF1 BIT(11) /* DMA underflow, buffer 0 and 1 */ -#define KVASER_PCIEFD_SRB_IRQ_DUF0 BIT(12) #define KVASER_PCIEFD_SRB_IRQ_DUF1 BIT(13) +#define KVASER_PCIEFD_SRB_IRQ_DUF0 BIT(12) +/* DMA overflow, buffer 0 and 1 */ +#define KVASER_PCIEFD_SRB_IRQ_DOF1 BIT(11) +#define KVASER_PCIEFD_SRB_IRQ_DOF0 BIT(10) +/* DMA packet done, buffer 0 and 1 */ +#define KVASER_PCIEFD_SRB_IRQ_DPD1 BIT(9) +#define KVASER_PCIEFD_SRB_IRQ_DPD0 BIT(8) +/* Got DMA support */ +#define KVASER_PCIEFD_SRB_STAT_DMA BIT(24) /* DMA idle */ #define KVASER_PCIEFD_SRB_STAT_DI BIT(15) -/* DMA support */ -#define KVASER_PCIEFD_SRB_STAT_DMA BIT(24) /* SRB current packet level */ -#define KVASER_PCIEFD_SRB_RX_NR_PACKETS_MASK 0xff +#define KVASER_PCIEFD_SRB_RX_NR_PACKETS_MASK GENMASK(7, 0) /* DMA Enable */ #define KVASER_PCIEFD_SRB_CTRL_DMA_ENABLE BIT(0) -/* EPCS flash controller definitions */ -#define KVASER_PCIEFD_CFG_IMG_SZ (64 * 1024) -#define KVASER_PCIEFD_CFG_IMG_OFFSET (31 * 65536L) -#define KVASER_PCIEFD_CFG_MAX_PARAMS 256 -#define KVASER_PCIEFD_CFG_MAGIC 0xcafef00d -#define KVASER_PCIEFD_CFG_PARAM_MAX_SZ 24 -#define KVASER_PCIEFD_CFG_SYS_VER 1 -#define KVASER_PCIEFD_CFG_PARAM_NR_CHAN 130 -#define KVASER_PCIEFD_SPI_TMT BIT(5) -#define KVASER_PCIEFD_SPI_TRDY BIT(6) -#define KVASER_PCIEFD_SPI_RRDY BIT(7) -#define KVASER_PCIEFD_FLASH_ID_EPCS16 0x14 -/* Commands for controlling the onboard flash */ -#define KVASER_PCIEFD_FLASH_RES_CMD 0xab -#define KVASER_PCIEFD_FLASH_READ_CMD 0x3 -#define KVASER_PCIEFD_FLASH_STATUS_CMD 0x5 - -/* Kvaser KCAN definitions */ -#define KVASER_PCIEFD_KCAN_CTRL_EFLUSH (4 << 29) -#define KVASER_PCIEFD_KCAN_CTRL_EFRAME (5 << 29) - -#define KVASER_PCIEFD_KCAN_CMD_SEQ_SHIFT 16 -/* Request status packet */ -#define KVASER_PCIEFD_KCAN_CMD_SRQ BIT(0) +/* KCAN CTRL packet types */ +#define KVASER_PCIEFD_KCAN_CTRL_TYPE_MASK GENMASK(31, 29) +#define KVASER_PCIEFD_KCAN_CTRL_TYPE_EFLUSH 0x4 +#define KVASER_PCIEFD_KCAN_CTRL_TYPE_EFRAME 0x5 + +/* Command sequence number */ +#define KVASER_PCIEFD_KCAN_CMD_SEQ_MASK GENMASK(23, 16) +/* Command bits */ +#define KVASER_PCIEFD_KCAN_CMD_MASK GENMASK(5, 0) /* Abort, flush and reset */ #define KVASER_PCIEFD_KCAN_CMD_AT BIT(1) +/* Request status packet */ +#define KVASER_PCIEFD_KCAN_CMD_SRQ BIT(0) -/* Tx FIFO unaligned read */ -#define KVASER_PCIEFD_KCAN_IRQ_TAR BIT(0) -/* Tx FIFO unaligned end */ -#define KVASER_PCIEFD_KCAN_IRQ_TAE BIT(1) -/* Bus parameter protection error */ -#define KVASER_PCIEFD_KCAN_IRQ_BPP BIT(2) -/* FDF bit when controller is in classic mode */ -#define KVASER_PCIEFD_KCAN_IRQ_FDIC BIT(3) -/* Rx FIFO overflow */ -#define KVASER_PCIEFD_KCAN_IRQ_ROF BIT(5) -/* Abort done */ -#define KVASER_PCIEFD_KCAN_IRQ_ABD BIT(13) -/* Tx buffer flush done */ -#define KVASER_PCIEFD_KCAN_IRQ_TFD BIT(14) -/* Tx FIFO overflow */ -#define KVASER_PCIEFD_KCAN_IRQ_TOF BIT(15) -/* Tx FIFO empty */ -#define KVASER_PCIEFD_KCAN_IRQ_TE BIT(16) /* Transmitter unaligned */ #define KVASER_PCIEFD_KCAN_IRQ_TAL BIT(17) +/* Tx FIFO empty */ +#define KVASER_PCIEFD_KCAN_IRQ_TE BIT(16) +/* Tx FIFO overflow */ +#define KVASER_PCIEFD_KCAN_IRQ_TOF BIT(15) +/* Tx buffer flush done */ +#define KVASER_PCIEFD_KCAN_IRQ_TFD BIT(14) +/* Abort done */ +#define KVASER_PCIEFD_KCAN_IRQ_ABD BIT(13) +/* Rx FIFO overflow */ +#define KVASER_PCIEFD_KCAN_IRQ_ROF BIT(5) +/* FDF bit when controller is in classic CAN mode */ +#define KVASER_PCIEFD_KCAN_IRQ_FDIC BIT(3) +/* Bus parameter protection error */ +#define KVASER_PCIEFD_KCAN_IRQ_BPP BIT(2) +/* Tx FIFO unaligned end */ +#define KVASER_PCIEFD_KCAN_IRQ_TAE BIT(1) +/* Tx FIFO unaligned read */ +#define KVASER_PCIEFD_KCAN_IRQ_TAR BIT(0) -#define KVASER_PCIEFD_KCAN_TX_NPACKETS_MAX_SHIFT 16 +/* Tx FIFO size */ +#define KVASER_PCIEFD_KCAN_TX_NR_PACKETS_MAX_MASK GENMASK(23, 16) +/* Tx FIFO current packet level */ +#define KVASER_PCIEFD_KCAN_TX_NR_PACKETS_CURRENT_MASK GENMASK(7, 0) -#define KVASER_PCIEFD_KCAN_STAT_SEQNO_SHIFT 24 -/* Abort request */ -#define KVASER_PCIEFD_KCAN_STAT_AR BIT(7) -/* Idle state. Controller in reset mode and no abort or flush pending */ -#define KVASER_PCIEFD_KCAN_STAT_IDLE BIT(10) -/* Bus off */ -#define KVASER_PCIEFD_KCAN_STAT_BOFF BIT(11) -/* Reset mode request */ -#define KVASER_PCIEFD_KCAN_STAT_RMR BIT(14) -/* Controller in reset mode */ -#define KVASER_PCIEFD_KCAN_STAT_IRM BIT(15) -/* Controller got one-shot capability */ -#define KVASER_PCIEFD_KCAN_STAT_CAP BIT(16) +/* Current status packet sequence number */ +#define KVASER_PCIEFD_KCAN_STAT_SEQNO_MASK GENMASK(31, 24) /* Controller got CAN FD capability */ #define KVASER_PCIEFD_KCAN_STAT_FD BIT(19) -#define KVASER_PCIEFD_KCAN_STAT_BUS_OFF_MSK (KVASER_PCIEFD_KCAN_STAT_AR | \ - KVASER_PCIEFD_KCAN_STAT_BOFF | KVASER_PCIEFD_KCAN_STAT_RMR | \ - KVASER_PCIEFD_KCAN_STAT_IRM) +/* Controller got one-shot capability */ +#define KVASER_PCIEFD_KCAN_STAT_CAP BIT(16) +/* Controller in reset mode */ +#define KVASER_PCIEFD_KCAN_STAT_IRM BIT(15) +/* Reset mode request */ +#define KVASER_PCIEFD_KCAN_STAT_RMR BIT(14) +/* Bus off */ +#define KVASER_PCIEFD_KCAN_STAT_BOFF BIT(11) +/* Idle state. Controller in reset mode and no abort or flush pending */ +#define KVASER_PCIEFD_KCAN_STAT_IDLE BIT(10) +/* Abort request */ +#define KVASER_PCIEFD_KCAN_STAT_AR BIT(7) +/* Controller is bus off */ +#define KVASER_PCIEFD_KCAN_STAT_BUS_OFF_MASK \ + (KVASER_PCIEFD_KCAN_STAT_AR | KVASER_PCIEFD_KCAN_STAT_BOFF | \ + KVASER_PCIEFD_KCAN_STAT_RMR | KVASER_PCIEFD_KCAN_STAT_IRM) -/* Reset mode */ -#define KVASER_PCIEFD_KCAN_MODE_RM BIT(8) -/* Listen only mode */ -#define KVASER_PCIEFD_KCAN_MODE_LOM BIT(9) -/* Error packet enable */ -#define KVASER_PCIEFD_KCAN_MODE_EPEN BIT(12) -/* CAN FD non-ISO */ -#define KVASER_PCIEFD_KCAN_MODE_NIFDEN BIT(15) -/* Acknowledgment packet type */ -#define KVASER_PCIEFD_KCAN_MODE_APT BIT(20) -/* Active error flag enable. Clear to force error passive */ -#define KVASER_PCIEFD_KCAN_MODE_EEN BIT(23) /* Classic CAN mode */ #define KVASER_PCIEFD_KCAN_MODE_CCM BIT(31) +/* Active error flag enable. Clear to force error passive */ +#define KVASER_PCIEFD_KCAN_MODE_EEN BIT(23) +/* Acknowledgment packet type */ +#define KVASER_PCIEFD_KCAN_MODE_APT BIT(20) +/* CAN FD non-ISO */ +#define KVASER_PCIEFD_KCAN_MODE_NIFDEN BIT(15) +/* Error packet enable */ +#define KVASER_PCIEFD_KCAN_MODE_EPEN BIT(12) +/* Listen only mode */ +#define KVASER_PCIEFD_KCAN_MODE_LOM BIT(9) +/* Reset mode */ +#define KVASER_PCIEFD_KCAN_MODE_RM BIT(8) -#define KVASER_PCIEFD_KCAN_BTRN_SJW_SHIFT 13 -#define KVASER_PCIEFD_KCAN_BTRN_TSEG1_SHIFT 17 -#define KVASER_PCIEFD_KCAN_BTRN_TSEG2_SHIFT 26 - -#define KVASER_PCIEFD_KCAN_PWM_TOP_SHIFT 16 - -/* Kvaser KCAN packet types */ -#define KVASER_PCIEFD_PACK_TYPE_DATA 0 -#define KVASER_PCIEFD_PACK_TYPE_ACK 1 -#define KVASER_PCIEFD_PACK_TYPE_TXRQ 2 -#define KVASER_PCIEFD_PACK_TYPE_ERROR 3 -#define KVASER_PCIEFD_PACK_TYPE_EFLUSH_ACK 4 -#define KVASER_PCIEFD_PACK_TYPE_EFRAME_ACK 5 -#define KVASER_PCIEFD_PACK_TYPE_ACK_DATA 6 -#define KVASER_PCIEFD_PACK_TYPE_STATUS 8 -#define KVASER_PCIEFD_PACK_TYPE_BUS_LOAD 9 - -/* Kvaser KCAN packet common definitions */ -#define KVASER_PCIEFD_PACKET_SEQ_MSK 0xff -#define KVASER_PCIEFD_PACKET_CHID_SHIFT 25 -#define KVASER_PCIEFD_PACKET_TYPE_SHIFT 28 - -/* Kvaser KCAN TDATA and RDATA first word */ +/* BTRN and BTRD fields */ +#define KVASER_PCIEFD_KCAN_BTRN_TSEG2_MASK GENMASK(30, 26) +#define KVASER_PCIEFD_KCAN_BTRN_TSEG1_MASK GENMASK(25, 17) +#define KVASER_PCIEFD_KCAN_BTRN_SJW_MASK GENMASK(16, 13) +#define KVASER_PCIEFD_KCAN_BTRN_BRP_MASK GENMASK(12, 0) + +/* PWM Control fields */ +#define KVASER_PCIEFD_KCAN_PWM_TOP_MASK GENMASK(23, 16) +#define KVASER_PCIEFD_KCAN_PWM_TRIGGER_MASK GENMASK(7, 0) + +/* KCAN packet type IDs */ +#define KVASER_PCIEFD_PACK_TYPE_DATA 0x0 +#define KVASER_PCIEFD_PACK_TYPE_ACK 0x1 +#define KVASER_PCIEFD_PACK_TYPE_TXRQ 0x2 +#define KVASER_PCIEFD_PACK_TYPE_ERROR 0x3 +#define KVASER_PCIEFD_PACK_TYPE_EFLUSH_ACK 0x4 +#define KVASER_PCIEFD_PACK_TYPE_EFRAME_ACK 0x5 +#define KVASER_PCIEFD_PACK_TYPE_ACK_DATA 0x6 +#define KVASER_PCIEFD_PACK_TYPE_STATUS 0x8 +#define KVASER_PCIEFD_PACK_TYPE_BUS_LOAD 0x9 + +/* Common KCAN packet definitions, second word */ +#define KVASER_PCIEFD_PACKET_TYPE_MASK GENMASK(31, 28) +#define KVASER_PCIEFD_PACKET_CHID_MASK GENMASK(27, 25) +#define KVASER_PCIEFD_PACKET_SEQ_MASK GENMASK(7, 0) + +/* KCAN Transmit/Receive data packet, first word */ #define KVASER_PCIEFD_RPACKET_IDE BIT(30) #define KVASER_PCIEFD_RPACKET_RTR BIT(29) -/* Kvaser KCAN TDATA and RDATA second word */ -#define KVASER_PCIEFD_RPACKET_ESI BIT(13) -#define KVASER_PCIEFD_RPACKET_BRS BIT(14) -#define KVASER_PCIEFD_RPACKET_FDF BIT(15) -#define KVASER_PCIEFD_RPACKET_DLC_SHIFT 8 -/* Kvaser KCAN TDATA second word */ -#define KVASER_PCIEFD_TPACKET_SMS BIT(16) +#define KVASER_PCIEFD_RPACKET_ID_MASK GENMASK(28, 0) +/* KCAN Transmit data packet, second word */ #define KVASER_PCIEFD_TPACKET_AREQ BIT(31) +#define KVASER_PCIEFD_TPACKET_SMS BIT(16) +/* KCAN Transmit/Receive data packet, second word */ +#define KVASER_PCIEFD_RPACKET_FDF BIT(15) +#define KVASER_PCIEFD_RPACKET_BRS BIT(14) +#define KVASER_PCIEFD_RPACKET_ESI BIT(13) +#define KVASER_PCIEFD_RPACKET_DLC_MASK GENMASK(11, 8) -/* Kvaser KCAN APACKET */ -#define KVASER_PCIEFD_APACKET_FLU BIT(8) -#define KVASER_PCIEFD_APACKET_CT BIT(9) -#define KVASER_PCIEFD_APACKET_ABL BIT(10) +/* KCAN Transmit acknowledge packet, first word */ #define KVASER_PCIEFD_APACKET_NACK BIT(11) +#define KVASER_PCIEFD_APACKET_ABL BIT(10) +#define KVASER_PCIEFD_APACKET_CT BIT(9) +#define KVASER_PCIEFD_APACKET_FLU BIT(8) -/* Kvaser KCAN SPACK first word */ -#define KVASER_PCIEFD_SPACK_RXERR_SHIFT 8 -#define KVASER_PCIEFD_SPACK_BOFF BIT(16) -#define KVASER_PCIEFD_SPACK_IDET BIT(20) -#define KVASER_PCIEFD_SPACK_IRM BIT(21) +/* KCAN Status packet, first word */ #define KVASER_PCIEFD_SPACK_RMCD BIT(22) -/* Kvaser KCAN SPACK second word */ -#define KVASER_PCIEFD_SPACK_AUTO BIT(21) -#define KVASER_PCIEFD_SPACK_EWLR BIT(23) +#define KVASER_PCIEFD_SPACK_IRM BIT(21) +#define KVASER_PCIEFD_SPACK_IDET BIT(20) +#define KVASER_PCIEFD_SPACK_BOFF BIT(16) +#define KVASER_PCIEFD_SPACK_RXERR_MASK GENMASK(15, 8) +#define KVASER_PCIEFD_SPACK_TXERR_MASK GENMASK(7, 0) +/* KCAN Status packet, second word */ #define KVASER_PCIEFD_SPACK_EPLR BIT(24) +#define KVASER_PCIEFD_SPACK_EWLR BIT(23) +#define KVASER_PCIEFD_SPACK_AUTO BIT(21) -/* Kvaser KCAN_EPACK second word */ +/* KCAN Error detected packet, second word */ #define KVASER_PCIEFD_EPACK_DIR_TX BIT(0) struct kvaser_pciefd; @@ -306,195 +302,43 @@ static const struct can_bittiming_const kvaser_pciefd_bittiming_const = { .brp_inc = 1, }; -struct kvaser_pciefd_cfg_param { - __le32 magic; - __le32 nr; - __le32 len; - u8 data[KVASER_PCIEFD_CFG_PARAM_MAX_SZ]; -}; - -struct kvaser_pciefd_cfg_img { - __le32 version; - __le32 magic; - __le32 crc; - struct kvaser_pciefd_cfg_param params[KVASER_PCIEFD_CFG_MAX_PARAMS]; -}; - static struct pci_device_id kvaser_pciefd_id_table[] = { - { PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_4HS_ID), }, - { PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_2HS_ID), }, - { PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_HS_ID), }, - { PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_MINIPCIE_HS_ID), }, - { PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_MINIPCIE_2HS_ID), }, - { 0,}, + { + PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_4HS_DEVICE_ID), + }, + { + PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_2HS_V2_DEVICE_ID), + }, + { + PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_HS_V2_DEVICE_ID), + }, + { + PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_MINIPCIE_HS_V2_DEVICE_ID), + }, + { + PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_MINIPCIE_2HS_V2_DEVICE_ID), + }, + { + 0, + }, }; MODULE_DEVICE_TABLE(pci, kvaser_pciefd_id_table); -/* Onboard flash memory functions */ -static int kvaser_pciefd_spi_wait_loop(struct kvaser_pciefd *pcie, int msk) -{ - u32 res; - - return readl_poll_timeout(pcie->reg_base + KVASER_PCIEFD_SPI_STATUS_REG, - res, res & msk, 0, 10); -} - -static int kvaser_pciefd_spi_cmd(struct kvaser_pciefd *pcie, const u8 *tx, - u32 tx_len, u8 *rx, u32 rx_len) -{ - int c; - - iowrite32(BIT(0), pcie->reg_base + KVASER_PCIEFD_SPI_SSEL_REG); - iowrite32(BIT(10), pcie->reg_base + KVASER_PCIEFD_SPI_CTRL_REG); - ioread32(pcie->reg_base + KVASER_PCIEFD_SPI_RX_REG); - - c = tx_len; - while (c--) { - if (kvaser_pciefd_spi_wait_loop(pcie, KVASER_PCIEFD_SPI_TRDY)) - return -EIO; - - iowrite32(*tx++, pcie->reg_base + KVASER_PCIEFD_SPI_TX_REG); - - if (kvaser_pciefd_spi_wait_loop(pcie, KVASER_PCIEFD_SPI_RRDY)) - return -EIO; - - ioread32(pcie->reg_base + KVASER_PCIEFD_SPI_RX_REG); - } - - c = rx_len; - while (c-- > 0) { - if (kvaser_pciefd_spi_wait_loop(pcie, KVASER_PCIEFD_SPI_TRDY)) - return -EIO; - - iowrite32(0, pcie->reg_base + KVASER_PCIEFD_SPI_TX_REG); - - if (kvaser_pciefd_spi_wait_loop(pcie, KVASER_PCIEFD_SPI_RRDY)) - return -EIO; - - *rx++ = ioread32(pcie->reg_base + KVASER_PCIEFD_SPI_RX_REG); - } - - if (kvaser_pciefd_spi_wait_loop(pcie, KVASER_PCIEFD_SPI_TMT)) - return -EIO; - - iowrite32(0, pcie->reg_base + KVASER_PCIEFD_SPI_CTRL_REG); - - if (c != -1) { - dev_err(&pcie->pci->dev, "Flash SPI transfer failed\n"); - return -EIO; - } - - return 0; -} - -static int kvaser_pciefd_cfg_read_and_verify(struct kvaser_pciefd *pcie, - struct kvaser_pciefd_cfg_img *img) -{ - int offset = KVASER_PCIEFD_CFG_IMG_OFFSET; - int res, crc; - u8 *crc_buff; - - u8 cmd[] = { - KVASER_PCIEFD_FLASH_READ_CMD, - (u8)((offset >> 16) & 0xff), - (u8)((offset >> 8) & 0xff), - (u8)(offset & 0xff) - }; - - res = kvaser_pciefd_spi_cmd(pcie, cmd, ARRAY_SIZE(cmd), (u8 *)img, - KVASER_PCIEFD_CFG_IMG_SZ); - if (res) - return res; - - crc_buff = (u8 *)img->params; - - if (le32_to_cpu(img->version) != KVASER_PCIEFD_CFG_SYS_VER) { - dev_err(&pcie->pci->dev, - "Config flash corrupted, version number is wrong\n"); - return -ENODEV; - } - - if (le32_to_cpu(img->magic) != KVASER_PCIEFD_CFG_MAGIC) { - dev_err(&pcie->pci->dev, - "Config flash corrupted, magic number is wrong\n"); - return -ENODEV; - } - - crc = ~crc32_be(0xffffffff, crc_buff, sizeof(img->params)); - if (le32_to_cpu(img->crc) != crc) { - dev_err(&pcie->pci->dev, - "Stored CRC does not match flash image contents\n"); - return -EIO; - } - - return 0; -} - -static void kvaser_pciefd_cfg_read_params(struct kvaser_pciefd *pcie, - struct kvaser_pciefd_cfg_img *img) +static inline void kvaser_pciefd_send_kcan_cmd(struct kvaser_pciefd_can *can, u32 cmd) { - struct kvaser_pciefd_cfg_param *param; - - param = &img->params[KVASER_PCIEFD_CFG_PARAM_NR_CHAN]; - memcpy(&pcie->nr_channels, param->data, le32_to_cpu(param->len)); + iowrite32(FIELD_PREP(KVASER_PCIEFD_KCAN_CMD_MASK, cmd) | + FIELD_PREP(KVASER_PCIEFD_KCAN_CMD_SEQ_MASK, ++can->cmd_seq), + can->reg_base + KVASER_PCIEFD_KCAN_CMD_REG); } -static int kvaser_pciefd_read_cfg(struct kvaser_pciefd *pcie) +static inline void kvaser_pciefd_request_status(struct kvaser_pciefd_can *can) { - int res; - struct kvaser_pciefd_cfg_img *img; - - /* Read electronic signature */ - u8 cmd[] = {KVASER_PCIEFD_FLASH_RES_CMD, 0, 0, 0}; - - res = kvaser_pciefd_spi_cmd(pcie, cmd, ARRAY_SIZE(cmd), cmd, 1); - if (res) - return -EIO; - - img = kmalloc(KVASER_PCIEFD_CFG_IMG_SZ, GFP_KERNEL); - if (!img) - return -ENOMEM; - - if (cmd[0] != KVASER_PCIEFD_FLASH_ID_EPCS16) { - dev_err(&pcie->pci->dev, - "Flash id is 0x%x instead of expected EPCS16 (0x%x)\n", - cmd[0], KVASER_PCIEFD_FLASH_ID_EPCS16); - - res = -ENODEV; - goto image_free; - } - - cmd[0] = KVASER_PCIEFD_FLASH_STATUS_CMD; - res = kvaser_pciefd_spi_cmd(pcie, cmd, 1, cmd, 1); - if (res) { - goto image_free; - } else if (cmd[0] & 1) { - res = -EIO; - /* No write is ever done, the WIP should never be set */ - dev_err(&pcie->pci->dev, "Unexpected WIP bit set in flash\n"); - goto image_free; - } - - res = kvaser_pciefd_cfg_read_and_verify(pcie, img); - if (res) { - res = -EIO; - goto image_free; - } - - kvaser_pciefd_cfg_read_params(pcie, img); - -image_free: - kfree(img); - return res; + kvaser_pciefd_send_kcan_cmd(can, KVASER_PCIEFD_KCAN_CMD_SRQ); } -static void kvaser_pciefd_request_status(struct kvaser_pciefd_can *can) +static inline void kvaser_pciefd_abort_flush_reset(struct kvaser_pciefd_can *can) { - u32 cmd; - - cmd = KVASER_PCIEFD_KCAN_CMD_SRQ; - cmd |= ++can->cmd_seq << KVASER_PCIEFD_KCAN_CMD_SEQ_SHIFT; - iowrite32(cmd, can->reg_base + KVASER_PCIEFD_KCAN_CMD_REG); + kvaser_pciefd_send_kcan_cmd(can, KVASER_PCIEFD_KCAN_CMD_AT); } static void kvaser_pciefd_enable_err_gen(struct kvaser_pciefd_can *can) @@ -523,7 +367,7 @@ static void kvaser_pciefd_disable_err_gen(struct kvaser_pciefd_can *can) spin_unlock_irqrestore(&can->lock, irq); } -static int kvaser_pciefd_set_tx_irq(struct kvaser_pciefd_can *can) +static void kvaser_pciefd_set_tx_irq(struct kvaser_pciefd_can *can) { u32 msk; @@ -534,8 +378,13 @@ static int kvaser_pciefd_set_tx_irq(struct kvaser_pciefd_can *can) KVASER_PCIEFD_KCAN_IRQ_TAR; iowrite32(msk, can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG); +} - return 0; +static inline void kvaser_pciefd_set_skb_timestamp(const struct kvaser_pciefd *pcie, + struct sk_buff *skb, u64 timestamp) +{ + skb_hwtstamps(skb)->hwtstamp = + ns_to_ktime(div_u64(timestamp * 1000, pcie->freq_to_ticks_div)); } static void kvaser_pciefd_setup_controller(struct kvaser_pciefd_can *can) @@ -544,7 +393,6 @@ static void kvaser_pciefd_setup_controller(struct kvaser_pciefd_can *can) unsigned long irq; spin_lock_irqsave(&can->lock, irq); - mode = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG); if (can->can.ctrlmode & CAN_CTRLMODE_FD) { mode &= ~KVASER_PCIEFD_KCAN_MODE_CCM; @@ -561,7 +409,6 @@ static void kvaser_pciefd_setup_controller(struct kvaser_pciefd_can *can) mode |= KVASER_PCIEFD_KCAN_MODE_LOM; else mode &= ~KVASER_PCIEFD_KCAN_MODE_LOM; - mode |= KVASER_PCIEFD_KCAN_MODE_EEN; mode |= KVASER_PCIEFD_KCAN_MODE_EPEN; /* Use ACK packet type */ @@ -578,18 +425,13 @@ static void kvaser_pciefd_start_controller_flush(struct kvaser_pciefd_can *can) unsigned long irq; spin_lock_irqsave(&can->lock, irq); - iowrite32(-1, can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG); + iowrite32(GENMASK(31, 0), can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG); iowrite32(KVASER_PCIEFD_KCAN_IRQ_ABD, can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG); - status = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_STAT_REG); if (status & KVASER_PCIEFD_KCAN_STAT_IDLE) { - u32 cmd; - /* If controller is already idle, run abort, flush and reset */ - cmd = KVASER_PCIEFD_KCAN_CMD_AT; - cmd |= ++can->cmd_seq << KVASER_PCIEFD_KCAN_CMD_SEQ_SHIFT; - iowrite32(cmd, can->reg_base + KVASER_PCIEFD_KCAN_CMD_REG); + kvaser_pciefd_abort_flush_reset(can); } else if (!(status & KVASER_PCIEFD_KCAN_STAT_RMR)) { u32 mode; @@ -598,7 +440,6 @@ static void kvaser_pciefd_start_controller_flush(struct kvaser_pciefd_can *can) mode |= KVASER_PCIEFD_KCAN_MODE_RM; iowrite32(mode, can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG); } - spin_unlock_irqrestore(&can->lock, irq); } @@ -608,7 +449,6 @@ static int kvaser_pciefd_bus_on(struct kvaser_pciefd_can *can) unsigned long irq; del_timer(&can->bec_poll_timer); - if (!completion_done(&can->flush_comp)) kvaser_pciefd_start_controller_flush(can); @@ -620,11 +460,9 @@ static int kvaser_pciefd_bus_on(struct kvaser_pciefd_can *can) spin_lock_irqsave(&can->lock, irq); iowrite32(0, can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG); - iowrite32(-1, can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG); - + iowrite32(GENMASK(31, 0), can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG); iowrite32(KVASER_PCIEFD_KCAN_IRQ_ABD, can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG); - mode = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG); mode &= ~KVASER_PCIEFD_KCAN_MODE_RM; iowrite32(mode, can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG); @@ -637,11 +475,10 @@ static int kvaser_pciefd_bus_on(struct kvaser_pciefd_can *can) } /* Reset interrupt handling */ iowrite32(0, can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG); - iowrite32(-1, can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG); + iowrite32(GENMASK(31, 0), can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG); kvaser_pciefd_set_tx_irq(can); kvaser_pciefd_setup_controller(can); - can->can.state = CAN_STATE_ERROR_ACTIVE; netif_wake_queue(can->can.dev); can->bec.txerr = 0; @@ -659,10 +496,9 @@ static void kvaser_pciefd_pwm_stop(struct kvaser_pciefd_can *can) spin_lock_irqsave(&can->lock, irq); pwm_ctrl = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_PWM_REG); - top = (pwm_ctrl >> KVASER_PCIEFD_KCAN_PWM_TOP_SHIFT) & 0xff; - + top = FIELD_GET(KVASER_PCIEFD_KCAN_PWM_TOP_MASK, pwm_ctrl); /* Set duty cycle to zero */ - pwm_ctrl |= top; + pwm_ctrl |= FIELD_PREP(KVASER_PCIEFD_KCAN_PWM_TRIGGER_MASK, top); iowrite32(pwm_ctrl, can->reg_base + KVASER_PCIEFD_KCAN_PWM_REG); spin_unlock_irqrestore(&can->lock, irq); } @@ -675,18 +511,17 @@ static void kvaser_pciefd_pwm_start(struct kvaser_pciefd_can *can) kvaser_pciefd_pwm_stop(can); spin_lock_irqsave(&can->lock, irq); - - /* Set frequency to 500 KHz*/ + /* Set frequency to 500 KHz */ top = can->kv_pcie->bus_freq / (2 * 500000) - 1; - pwm_ctrl = top & 0xff; - pwm_ctrl |= (top & 0xff) << KVASER_PCIEFD_KCAN_PWM_TOP_SHIFT; + pwm_ctrl = FIELD_PREP(KVASER_PCIEFD_KCAN_PWM_TRIGGER_MASK, top); + pwm_ctrl |= FIELD_PREP(KVASER_PCIEFD_KCAN_PWM_TOP_MASK, top); iowrite32(pwm_ctrl, can->reg_base + KVASER_PCIEFD_KCAN_PWM_REG); /* Set duty cycle to 95 */ trigger = (100 * top - 95 * (top + 1) + 50) / 100; - pwm_ctrl = trigger & 0xff; - pwm_ctrl |= (top & 0xff) << KVASER_PCIEFD_KCAN_PWM_TOP_SHIFT; + pwm_ctrl = FIELD_PREP(KVASER_PCIEFD_KCAN_PWM_TRIGGER_MASK, trigger); + pwm_ctrl |= FIELD_PREP(KVASER_PCIEFD_KCAN_PWM_TOP_MASK, top); iowrite32(pwm_ctrl, can->reg_base + KVASER_PCIEFD_KCAN_PWM_REG); spin_unlock_irqrestore(&can->lock, irq); } @@ -741,7 +576,6 @@ static int kvaser_pciefd_prepare_tx_packet(struct kvaser_pciefd_tx_packet *p, int seq = can->echo_idx; memset(p, 0, sizeof(*p)); - if (can->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT) p->header[1] |= KVASER_PCIEFD_TPACKET_SMS; @@ -751,19 +585,24 @@ static int kvaser_pciefd_prepare_tx_packet(struct kvaser_pciefd_tx_packet *p, if (cf->can_id & CAN_EFF_FLAG) p->header[0] |= KVASER_PCIEFD_RPACKET_IDE; - p->header[0] |= cf->can_id & CAN_EFF_MASK; - p->header[1] |= can_fd_len2dlc(cf->len) << KVASER_PCIEFD_RPACKET_DLC_SHIFT; + p->header[0] |= FIELD_PREP(KVASER_PCIEFD_RPACKET_ID_MASK, cf->can_id); p->header[1] |= KVASER_PCIEFD_TPACKET_AREQ; if (can_is_canfd_skb(skb)) { + p->header[1] |= FIELD_PREP(KVASER_PCIEFD_RPACKET_DLC_MASK, + can_fd_len2dlc(cf->len)); p->header[1] |= KVASER_PCIEFD_RPACKET_FDF; if (cf->flags & CANFD_BRS) p->header[1] |= KVASER_PCIEFD_RPACKET_BRS; if (cf->flags & CANFD_ESI) p->header[1] |= KVASER_PCIEFD_RPACKET_ESI; + } else { + p->header[1] |= + FIELD_PREP(KVASER_PCIEFD_RPACKET_DLC_MASK, + can_get_cc_dlc((struct can_frame *)cf, can->can.ctrlmode)); } - p->header[1] |= seq & KVASER_PCIEFD_PACKET_SEQ_MSK; + p->header[1] |= FIELD_PREP(KVASER_PCIEFD_PACKET_SEQ_MASK, seq); packet_size = cf->len; memcpy(p->data, cf->data, packet_size); @@ -777,16 +616,15 @@ static netdev_tx_t kvaser_pciefd_start_xmit(struct sk_buff *skb, struct kvaser_pciefd_can *can = netdev_priv(netdev); unsigned long irq_flags; struct kvaser_pciefd_tx_packet packet; - int nwords; + int nr_words; u8 count; if (can_dev_dropped_skb(netdev, skb)) return NETDEV_TX_OK; - nwords = kvaser_pciefd_prepare_tx_packet(&packet, can, skb); + nr_words = kvaser_pciefd_prepare_tx_packet(&packet, can, skb); spin_lock_irqsave(&can->echo_lock, irq_flags); - /* Prepare and save echo skb in internal slot */ can_put_echo_skb(skb, netdev, can->echo_idx, 0); @@ -799,13 +637,13 @@ static netdev_tx_t kvaser_pciefd_start_xmit(struct sk_buff *skb, iowrite32(packet.header[1], can->reg_base + KVASER_PCIEFD_KCAN_FIFO_REG); - if (nwords) { - u32 data_last = ((u32 *)packet.data)[nwords - 1]; + if (nr_words) { + u32 data_last = ((u32 *)packet.data)[nr_words - 1]; /* Write data to fifo, except last word */ iowrite32_rep(can->reg_base + KVASER_PCIEFD_KCAN_FIFO_REG, packet.data, - nwords - 1); + nr_words - 1); /* Write last word to end of fifo */ __raw_writel(data_last, can->reg_base + KVASER_PCIEFD_KCAN_FIFO_LAST_REG); @@ -815,14 +653,13 @@ static netdev_tx_t kvaser_pciefd_start_xmit(struct sk_buff *skb, KVASER_PCIEFD_KCAN_FIFO_LAST_REG); } - count = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_TX_NPACKETS_REG); + count = FIELD_GET(KVASER_PCIEFD_KCAN_TX_NR_PACKETS_CURRENT_MASK, + ioread32(can->reg_base + KVASER_PCIEFD_KCAN_TX_NR_PACKETS_REG)); /* No room for a new message, stop the queue until at least one * successful transmit */ - if (count >= KVASER_PCIEFD_CAN_TX_MAX_COUNT || - can->can.echo_skb[can->echo_idx]) + if (count >= can->can.echo_skb_max || can->can.echo_skb[can->echo_idx]) netif_stop_queue(netdev); - spin_unlock_irqrestore(&can->echo_lock, irq_flags); return NETDEV_TX_OK; @@ -840,25 +677,20 @@ static int kvaser_pciefd_set_bittiming(struct kvaser_pciefd_can *can, bool data) else bt = &can->can.bittiming; - btrn = ((bt->phase_seg2 - 1) & 0x1f) << - KVASER_PCIEFD_KCAN_BTRN_TSEG2_SHIFT | - (((bt->prop_seg + bt->phase_seg1) - 1) & 0x1ff) << - KVASER_PCIEFD_KCAN_BTRN_TSEG1_SHIFT | - ((bt->sjw - 1) & 0xf) << KVASER_PCIEFD_KCAN_BTRN_SJW_SHIFT | - ((bt->brp - 1) & 0x1fff); + btrn = FIELD_PREP(KVASER_PCIEFD_KCAN_BTRN_TSEG2_MASK, bt->phase_seg2 - 1) | + FIELD_PREP(KVASER_PCIEFD_KCAN_BTRN_TSEG1_MASK, bt->prop_seg + bt->phase_seg1 - 1) | + FIELD_PREP(KVASER_PCIEFD_KCAN_BTRN_SJW_MASK, bt->sjw - 1) | + FIELD_PREP(KVASER_PCIEFD_KCAN_BTRN_BRP_MASK, bt->brp - 1); spin_lock_irqsave(&can->lock, irq_flags); mode = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG); - /* Put the circuit in reset mode */ iowrite32(mode | KVASER_PCIEFD_KCAN_MODE_RM, can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG); /* Can only set bittiming if in reset mode */ ret = readl_poll_timeout(can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG, - test, test & KVASER_PCIEFD_KCAN_MODE_RM, - 0, 10); - + test, test & KVASER_PCIEFD_KCAN_MODE_RM, 0, 10); if (ret) { spin_unlock_irqrestore(&can->lock, irq_flags); return -EBUSY; @@ -868,11 +700,10 @@ static int kvaser_pciefd_set_bittiming(struct kvaser_pciefd_can *can, bool data) iowrite32(btrn, can->reg_base + KVASER_PCIEFD_KCAN_BTRD_REG); else iowrite32(btrn, can->reg_base + KVASER_PCIEFD_KCAN_BTRN_REG); - /* Restore previous reset mode status */ iowrite32(mode, can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG); - spin_unlock_irqrestore(&can->lock, irq_flags); + return 0; } @@ -910,6 +741,7 @@ static int kvaser_pciefd_get_berr_counter(const struct net_device *ndev, bec->rxerr = can->bec.rxerr; bec->txerr = can->bec.txerr; + return 0; } @@ -941,7 +773,7 @@ static int kvaser_pciefd_setup_can_ctrls(struct kvaser_pciefd *pcie) for (i = 0; i < pcie->nr_channels; i++) { struct net_device *netdev; struct kvaser_pciefd_can *can; - u32 status, tx_npackets; + u32 status, tx_nr_packets_max; netdev = alloc_candev(sizeof(struct kvaser_pciefd_can), KVASER_PCIEFD_CAN_TX_MAX_COUNT); @@ -953,7 +785,6 @@ static int kvaser_pciefd_setup_can_ctrls(struct kvaser_pciefd *pcie) netdev->ethtool_ops = &kvaser_pciefd_ethtool_ops; can->reg_base = pcie->reg_base + KVASER_PCIEFD_KCAN0_BASE + i * KVASER_PCIEFD_KCAN_BASE_OFFSET; - can->kv_pcie = pcie; can->cmd_seq = 0; can->err_rep_cnt = 0; @@ -962,41 +793,31 @@ static int kvaser_pciefd_setup_can_ctrls(struct kvaser_pciefd *pcie) init_completion(&can->start_comp); init_completion(&can->flush_comp); - timer_setup(&can->bec_poll_timer, kvaser_pciefd_bec_poll_timer, - 0); + timer_setup(&can->bec_poll_timer, kvaser_pciefd_bec_poll_timer, 0); /* Disable Bus load reporting */ iowrite32(0, can->reg_base + KVASER_PCIEFD_KCAN_BUS_LOAD_REG); - tx_npackets = ioread32(can->reg_base + - KVASER_PCIEFD_KCAN_TX_NPACKETS_REG); - if (((tx_npackets >> KVASER_PCIEFD_KCAN_TX_NPACKETS_MAX_SHIFT) & - 0xff) < KVASER_PCIEFD_CAN_TX_MAX_COUNT) { - dev_err(&pcie->pci->dev, - "Max Tx count is smaller than expected\n"); - - free_candev(netdev); - return -ENODEV; - } + tx_nr_packets_max = + FIELD_GET(KVASER_PCIEFD_KCAN_TX_NR_PACKETS_MAX_MASK, + ioread32(can->reg_base + KVASER_PCIEFD_KCAN_TX_NR_PACKETS_REG)); can->can.clock.freq = pcie->freq; - can->can.echo_skb_max = KVASER_PCIEFD_CAN_TX_MAX_COUNT; + can->can.echo_skb_max = min(KVASER_PCIEFD_CAN_TX_MAX_COUNT, tx_nr_packets_max - 1); can->echo_idx = 0; spin_lock_init(&can->echo_lock); spin_lock_init(&can->lock); + can->can.bittiming_const = &kvaser_pciefd_bittiming_const; can->can.data_bittiming_const = &kvaser_pciefd_bittiming_const; - can->can.do_set_bittiming = kvaser_pciefd_set_nominal_bittiming; - can->can.do_set_data_bittiming = - kvaser_pciefd_set_data_bittiming; - + can->can.do_set_data_bittiming = kvaser_pciefd_set_data_bittiming; can->can.do_set_mode = kvaser_pciefd_set_mode; can->can.do_get_berr_counter = kvaser_pciefd_get_berr_counter; - can->can.ctrlmode_supported = CAN_CTRLMODE_LISTENONLY | CAN_CTRLMODE_FD | - CAN_CTRLMODE_FD_NON_ISO; + CAN_CTRLMODE_FD_NON_ISO | + CAN_CTRLMODE_CC_LEN8_DLC; status = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_STAT_REG); if (!(status & KVASER_PCIEFD_KCAN_STAT_FD)) { @@ -1011,10 +832,9 @@ static int kvaser_pciefd_setup_can_ctrls(struct kvaser_pciefd *pcie) can->can.ctrlmode_supported |= CAN_CTRLMODE_ONE_SHOT; netdev->flags |= IFF_ECHO; - SET_NETDEV_DEV(netdev, &pcie->pci->dev); - iowrite32(-1, can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG); + iowrite32(GENMASK(31, 0), can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG); iowrite32(KVASER_PCIEFD_KCAN_IRQ_ABD, can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG); @@ -1073,18 +893,16 @@ static int kvaser_pciefd_setup_dma(struct kvaser_pciefd *pcie) for (i = 0; i < KVASER_PCIEFD_DMA_COUNT; i++) { unsigned int offset = KVASER_PCIEFD_DMA_MAP_BASE + 8 * i; - pcie->dma_data[i] = - dmam_alloc_coherent(&pcie->pci->dev, - KVASER_PCIEFD_DMA_SIZE, - &dma_addr[i], - GFP_KERNEL); + pcie->dma_data[i] = dmam_alloc_coherent(&pcie->pci->dev, + KVASER_PCIEFD_DMA_SIZE, + &dma_addr[i], + GFP_KERNEL); if (!pcie->dma_data[i] || !dma_addr[i]) { dev_err(&pcie->pci->dev, "Rx dma_alloc(%u) failure\n", KVASER_PCIEFD_DMA_SIZE); return -ENOMEM; } - kvaser_pciefd_write_dma_map(pcie, dma_addr[i], offset); } @@ -1092,10 +910,10 @@ static int kvaser_pciefd_setup_dma(struct kvaser_pciefd *pcie) iowrite32(KVASER_PCIEFD_SRB_CMD_FOR | KVASER_PCIEFD_SRB_CMD_RDB0 | KVASER_PCIEFD_SRB_CMD_RDB1, pcie->reg_base + KVASER_PCIEFD_SRB_CMD_REG); - /* Empty Rx FIFO */ - srb_packet_count = ioread32(pcie->reg_base + KVASER_PCIEFD_SRB_RX_NR_PACKETS_REG) & - KVASER_PCIEFD_SRB_RX_NR_PACKETS_MASK; + srb_packet_count = + FIELD_GET(KVASER_PCIEFD_SRB_RX_NR_PACKETS_MASK, + ioread32(pcie->reg_base + KVASER_PCIEFD_SRB_RX_NR_PACKETS_REG)); while (srb_packet_count) { /* Drop current packet in FIFO */ ioread32(pcie->reg_base + KVASER_PCIEFD_SRB_FIFO_LAST_REG); @@ -1117,37 +935,21 @@ static int kvaser_pciefd_setup_dma(struct kvaser_pciefd *pcie) static int kvaser_pciefd_setup_board(struct kvaser_pciefd *pcie) { - u32 sysid, srb_status, build; - u8 sysid_nr_chan; - int ret; - - ret = kvaser_pciefd_read_cfg(pcie); - if (ret) - return ret; - - sysid = ioread32(pcie->reg_base + KVASER_PCIEFD_SYSID_VERSION_REG); - sysid_nr_chan = (sysid >> KVASER_PCIEFD_SYSID_NRCHAN_SHIFT) & 0xff; - if (pcie->nr_channels != sysid_nr_chan) { - dev_err(&pcie->pci->dev, - "Number of channels does not match: %u vs %u\n", - pcie->nr_channels, - sysid_nr_chan); - return -ENODEV; - } + u32 version, srb_status, build; - if (pcie->nr_channels > KVASER_PCIEFD_MAX_CAN_CHANNELS) - pcie->nr_channels = KVASER_PCIEFD_MAX_CAN_CHANNELS; + version = ioread32(pcie->reg_base + KVASER_PCIEFD_SYSID_VERSION_REG); + pcie->nr_channels = min(KVASER_PCIEFD_MAX_CAN_CHANNELS, + FIELD_GET(KVASER_PCIEFD_SYSID_VERSION_NR_CHAN_MASK, version)); build = ioread32(pcie->reg_base + KVASER_PCIEFD_SYSID_BUILD_REG); - dev_dbg(&pcie->pci->dev, "Version %u.%u.%u\n", - (sysid >> KVASER_PCIEFD_SYSID_MAJOR_VER_SHIFT) & 0xff, - sysid & 0xff, - (build >> KVASER_PCIEFD_SYSID_BUILD_VER_SHIFT) & 0x7fff); + dev_dbg(&pcie->pci->dev, "Version %lu.%lu.%lu\n", + FIELD_GET(KVASER_PCIEFD_SYSID_VERSION_MAJOR_MASK, version), + FIELD_GET(KVASER_PCIEFD_SYSID_VERSION_MINOR_MASK, version), + FIELD_GET(KVASER_PCIEFD_SYSID_BUILD_SEQ_MASK, build)); srb_status = ioread32(pcie->reg_base + KVASER_PCIEFD_SRB_STAT_REG); if (!(srb_status & KVASER_PCIEFD_SRB_STAT_DMA)) { - dev_err(&pcie->pci->dev, - "Hardware without DMA is not supported\n"); + dev_err(&pcie->pci->dev, "Hardware without DMA is not supported\n"); return -ENODEV; } @@ -1157,10 +959,10 @@ static int kvaser_pciefd_setup_board(struct kvaser_pciefd *pcie) pcie->freq_to_ticks_div = pcie->freq / 1000000; if (pcie->freq_to_ticks_div == 0) pcie->freq_to_ticks_div = 1; - /* Turn off all loopback functionality */ iowrite32(0, pcie->reg_base + KVASER_PCIEFD_LOOP_REG); - return ret; + + return 0; } static int kvaser_pciefd_handle_data_packet(struct kvaser_pciefd *pcie, @@ -1170,56 +972,48 @@ static int kvaser_pciefd_handle_data_packet(struct kvaser_pciefd *pcie, struct sk_buff *skb; struct canfd_frame *cf; struct can_priv *priv; - struct net_device_stats *stats; - struct skb_shared_hwtstamps *shhwtstamps; - u8 ch_id = (p->header[1] >> KVASER_PCIEFD_PACKET_CHID_SHIFT) & 0x7; + u8 ch_id = FIELD_GET(KVASER_PCIEFD_PACKET_CHID_MASK, p->header[1]); + u8 dlc; if (ch_id >= pcie->nr_channels) return -EIO; priv = &pcie->can[ch_id]->can; - stats = &priv->dev->stats; + dlc = FIELD_GET(KVASER_PCIEFD_RPACKET_DLC_MASK, p->header[1]); if (p->header[1] & KVASER_PCIEFD_RPACKET_FDF) { skb = alloc_canfd_skb(priv->dev, &cf); if (!skb) { - stats->rx_dropped++; + priv->dev->stats.rx_dropped++; return -ENOMEM; } + cf->len = can_fd_dlc2len(dlc); if (p->header[1] & KVASER_PCIEFD_RPACKET_BRS) cf->flags |= CANFD_BRS; - if (p->header[1] & KVASER_PCIEFD_RPACKET_ESI) cf->flags |= CANFD_ESI; } else { skb = alloc_can_skb(priv->dev, (struct can_frame **)&cf); if (!skb) { - stats->rx_dropped++; + priv->dev->stats.rx_dropped++; return -ENOMEM; } + can_frame_set_cc_len((struct can_frame *)cf, dlc, priv->ctrlmode); } - cf->can_id = p->header[0] & CAN_EFF_MASK; + cf->can_id = FIELD_GET(KVASER_PCIEFD_RPACKET_ID_MASK, p->header[0]); if (p->header[0] & KVASER_PCIEFD_RPACKET_IDE) cf->can_id |= CAN_EFF_FLAG; - cf->len = can_fd_dlc2len(p->header[1] >> KVASER_PCIEFD_RPACKET_DLC_SHIFT); - if (p->header[0] & KVASER_PCIEFD_RPACKET_RTR) { cf->can_id |= CAN_RTR_FLAG; } else { memcpy(cf->data, data, cf->len); - - stats->rx_bytes += cf->len; + priv->dev->stats.rx_bytes += cf->len; } - stats->rx_packets++; - - shhwtstamps = skb_hwtstamps(skb); - - shhwtstamps->hwtstamp = - ns_to_ktime(div_u64(p->timestamp * 1000, - pcie->freq_to_ticks_div)); + priv->dev->stats.rx_packets++; + kvaser_pciefd_set_skb_timestamp(pcie, skb, p->timestamp); return netif_rx(skb); } @@ -1239,7 +1033,6 @@ static void kvaser_pciefd_change_state(struct kvaser_pciefd_can *can, spin_lock_irqsave(&can->lock, irq_flags); netif_stop_queue(can->can.dev); spin_unlock_irqrestore(&can->lock, irq_flags); - /* Prevent CAN controller from auto recover from bus off */ if (!can->can.restart_ms) { kvaser_pciefd_start_controller_flush(can); @@ -1257,7 +1050,7 @@ static void kvaser_pciefd_packet_to_state(struct kvaser_pciefd_rx_packet *p, if (p->header[0] & KVASER_PCIEFD_SPACK_BOFF || p->header[0] & KVASER_PCIEFD_SPACK_IRM) *new_state = CAN_STATE_BUS_OFF; - else if (bec->txerr >= 255 || bec->rxerr >= 255) + else if (bec->txerr >= 255 || bec->rxerr >= 255) *new_state = CAN_STATE_BUS_OFF; else if (p->header[1] & KVASER_PCIEFD_SPACK_EPLR) *new_state = CAN_STATE_ERROR_PASSIVE; @@ -1282,23 +1075,16 @@ static int kvaser_pciefd_rx_error_frame(struct kvaser_pciefd_can *can, struct net_device *ndev = can->can.dev; struct sk_buff *skb; struct can_frame *cf = NULL; - struct skb_shared_hwtstamps *shhwtstamps; - struct net_device_stats *stats = &ndev->stats; old_state = can->can.state; - bec.txerr = p->header[0] & 0xff; - bec.rxerr = (p->header[0] >> KVASER_PCIEFD_SPACK_RXERR_SHIFT) & 0xff; - - kvaser_pciefd_packet_to_state(p, &bec, &new_state, &tx_state, - &rx_state); + bec.txerr = FIELD_GET(KVASER_PCIEFD_SPACK_TXERR_MASK, p->header[0]); + bec.rxerr = FIELD_GET(KVASER_PCIEFD_SPACK_RXERR_MASK, p->header[0]); + kvaser_pciefd_packet_to_state(p, &bec, &new_state, &tx_state, &rx_state); skb = alloc_can_err_skb(ndev, &cf); - if (new_state != old_state) { - kvaser_pciefd_change_state(can, cf, new_state, tx_state, - rx_state); - + kvaser_pciefd_change_state(can, cf, new_state, tx_state, rx_state); if (old_state == CAN_STATE_BUS_OFF && new_state == CAN_STATE_ERROR_ACTIVE && can->can.restart_ms) { @@ -1311,28 +1097,25 @@ static int kvaser_pciefd_rx_error_frame(struct kvaser_pciefd_can *can, can->err_rep_cnt++; can->can.can_stats.bus_error++; if (p->header[1] & KVASER_PCIEFD_EPACK_DIR_TX) - stats->tx_errors++; + ndev->stats.tx_errors++; else - stats->rx_errors++; + ndev->stats.rx_errors++; can->bec.txerr = bec.txerr; can->bec.rxerr = bec.rxerr; if (!skb) { - stats->rx_dropped++; + ndev->stats.rx_dropped++; return -ENOMEM; } - shhwtstamps = skb_hwtstamps(skb); - shhwtstamps->hwtstamp = - ns_to_ktime(div_u64(p->timestamp * 1000, - can->kv_pcie->freq_to_ticks_div)); + kvaser_pciefd_set_skb_timestamp(can->kv_pcie, skb, p->timestamp); cf->can_id |= CAN_ERR_BUSERROR | CAN_ERR_CNT; - cf->data[6] = bec.txerr; cf->data[7] = bec.rxerr; netif_rx(skb); + return 0; } @@ -1340,19 +1123,19 @@ static int kvaser_pciefd_handle_error_packet(struct kvaser_pciefd *pcie, struct kvaser_pciefd_rx_packet *p) { struct kvaser_pciefd_can *can; - u8 ch_id = (p->header[1] >> KVASER_PCIEFD_PACKET_CHID_SHIFT) & 0x7; + u8 ch_id = FIELD_GET(KVASER_PCIEFD_PACKET_CHID_MASK, p->header[1]); if (ch_id >= pcie->nr_channels) return -EIO; can = pcie->can[ch_id]; - kvaser_pciefd_rx_error_frame(can, p); if (can->err_rep_cnt >= KVASER_PCIEFD_MAX_ERR_REP) /* Do not report more errors, until bec_poll_timer expires */ kvaser_pciefd_disable_err_gen(can); /* Start polling the error counters */ mod_timer(&can->bec_poll_timer, KVASER_PCIEFD_BEC_POLL_FREQ); + return 0; } @@ -1364,29 +1147,22 @@ static int kvaser_pciefd_handle_status_resp(struct kvaser_pciefd_can *can, old_state = can->can.state; - bec.txerr = p->header[0] & 0xff; - bec.rxerr = (p->header[0] >> KVASER_PCIEFD_SPACK_RXERR_SHIFT) & 0xff; - - kvaser_pciefd_packet_to_state(p, &bec, &new_state, &tx_state, - &rx_state); + bec.txerr = FIELD_GET(KVASER_PCIEFD_SPACK_TXERR_MASK, p->header[0]); + bec.rxerr = FIELD_GET(KVASER_PCIEFD_SPACK_RXERR_MASK, p->header[0]); + kvaser_pciefd_packet_to_state(p, &bec, &new_state, &tx_state, &rx_state); if (new_state != old_state) { struct net_device *ndev = can->can.dev; struct sk_buff *skb; struct can_frame *cf; - struct skb_shared_hwtstamps *shhwtstamps; skb = alloc_can_err_skb(ndev, &cf); if (!skb) { - struct net_device_stats *stats = &ndev->stats; - - stats->rx_dropped++; + ndev->stats.rx_dropped++; return -ENOMEM; } - kvaser_pciefd_change_state(can, cf, new_state, tx_state, - rx_state); - + kvaser_pciefd_change_state(can, cf, new_state, tx_state, rx_state); if (old_state == CAN_STATE_BUS_OFF && new_state == CAN_STATE_ERROR_ACTIVE && can->can.restart_ms) { @@ -1394,10 +1170,7 @@ static int kvaser_pciefd_handle_status_resp(struct kvaser_pciefd_can *can, cf->can_id |= CAN_ERR_RESTARTED; } - shhwtstamps = skb_hwtstamps(skb); - shhwtstamps->hwtstamp = - ns_to_ktime(div_u64(p->timestamp * 1000, - can->kv_pcie->freq_to_ticks_div)); + kvaser_pciefd_set_skb_timestamp(can->kv_pcie, skb, p->timestamp); cf->data[6] = bec.txerr; cf->data[7] = bec.rxerr; @@ -1419,7 +1192,7 @@ static int kvaser_pciefd_handle_status_packet(struct kvaser_pciefd *pcie, struct kvaser_pciefd_can *can; u8 cmdseq; u32 status; - u8 ch_id = (p->header[1] >> KVASER_PCIEFD_PACKET_CHID_SHIFT) & 0x7; + u8 ch_id = FIELD_GET(KVASER_PCIEFD_PACKET_CHID_MASK, p->header[1]); if (ch_id >= pcie->nr_channels) return -EIO; @@ -1427,43 +1200,40 @@ static int kvaser_pciefd_handle_status_packet(struct kvaser_pciefd *pcie, can = pcie->can[ch_id]; status = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_STAT_REG); - cmdseq = (status >> KVASER_PCIEFD_KCAN_STAT_SEQNO_SHIFT) & 0xff; + cmdseq = FIELD_GET(KVASER_PCIEFD_KCAN_STAT_SEQNO_MASK, status); /* Reset done, start abort and flush */ if (p->header[0] & KVASER_PCIEFD_SPACK_IRM && p->header[0] & KVASER_PCIEFD_SPACK_RMCD && p->header[1] & KVASER_PCIEFD_SPACK_AUTO && - cmdseq == (p->header[1] & KVASER_PCIEFD_PACKET_SEQ_MSK) && + cmdseq == FIELD_GET(KVASER_PCIEFD_PACKET_SEQ_MASK, p->header[1]) && status & KVASER_PCIEFD_KCAN_STAT_IDLE) { - u32 cmd; - iowrite32(KVASER_PCIEFD_KCAN_IRQ_ABD, can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG); - cmd = KVASER_PCIEFD_KCAN_CMD_AT; - cmd |= ++can->cmd_seq << KVASER_PCIEFD_KCAN_CMD_SEQ_SHIFT; - iowrite32(cmd, can->reg_base + KVASER_PCIEFD_KCAN_CMD_REG); + kvaser_pciefd_abort_flush_reset(can); } else if (p->header[0] & KVASER_PCIEFD_SPACK_IDET && p->header[0] & KVASER_PCIEFD_SPACK_IRM && - cmdseq == (p->header[1] & KVASER_PCIEFD_PACKET_SEQ_MSK) && + cmdseq == FIELD_GET(KVASER_PCIEFD_PACKET_SEQ_MASK, p->header[1]) && status & KVASER_PCIEFD_KCAN_STAT_IDLE) { /* Reset detected, send end of flush if no packet are in FIFO */ - u8 count = ioread32(can->reg_base + - KVASER_PCIEFD_KCAN_TX_NPACKETS_REG) & 0xff; + u8 count; + count = FIELD_GET(KVASER_PCIEFD_KCAN_TX_NR_PACKETS_CURRENT_MASK, + ioread32(can->reg_base + KVASER_PCIEFD_KCAN_TX_NR_PACKETS_REG)); if (!count) - iowrite32(KVASER_PCIEFD_KCAN_CTRL_EFLUSH, + iowrite32(FIELD_PREP(KVASER_PCIEFD_KCAN_CTRL_TYPE_MASK, + KVASER_PCIEFD_KCAN_CTRL_TYPE_EFLUSH), can->reg_base + KVASER_PCIEFD_KCAN_CTRL_REG); } else if (!(p->header[1] & KVASER_PCIEFD_SPACK_AUTO) && - cmdseq == (p->header[1] & KVASER_PCIEFD_PACKET_SEQ_MSK)) { + cmdseq == FIELD_GET(KVASER_PCIEFD_PACKET_SEQ_MASK, p->header[1])) { /* Response to status request received */ kvaser_pciefd_handle_status_resp(can, p); if (can->can.state != CAN_STATE_BUS_OFF && can->can.state != CAN_STATE_ERROR_ACTIVE) { - mod_timer(&can->bec_poll_timer, - KVASER_PCIEFD_BEC_POLL_FREQ); + mod_timer(&can->bec_poll_timer, KVASER_PCIEFD_BEC_POLL_FREQ); } } else if (p->header[0] & KVASER_PCIEFD_SPACK_RMCD && - !(status & KVASER_PCIEFD_KCAN_STAT_BUS_OFF_MSK)) { + !(status & KVASER_PCIEFD_KCAN_STAT_BUS_OFF_MASK)) { /* Reset to bus on detected */ if (!completion_done(&can->start_comp)) complete(&can->start_comp); @@ -1472,50 +1242,14 @@ static int kvaser_pciefd_handle_status_packet(struct kvaser_pciefd *pcie, return 0; } -static int kvaser_pciefd_handle_eack_packet(struct kvaser_pciefd *pcie, - struct kvaser_pciefd_rx_packet *p) -{ - struct kvaser_pciefd_can *can; - u8 ch_id = (p->header[1] >> KVASER_PCIEFD_PACKET_CHID_SHIFT) & 0x7; - - if (ch_id >= pcie->nr_channels) - return -EIO; - - can = pcie->can[ch_id]; - - /* If this is the last flushed packet, send end of flush */ - if (p->header[0] & KVASER_PCIEFD_APACKET_FLU) { - u8 count = ioread32(can->reg_base + - KVASER_PCIEFD_KCAN_TX_NPACKETS_REG) & 0xff; - - if (count == 0) - iowrite32(KVASER_PCIEFD_KCAN_CTRL_EFLUSH, - can->reg_base + KVASER_PCIEFD_KCAN_CTRL_REG); - } else { - int echo_idx = p->header[0] & KVASER_PCIEFD_PACKET_SEQ_MSK; - int dlc = can_get_echo_skb(can->can.dev, echo_idx, NULL); - struct net_device_stats *stats = &can->can.dev->stats; - - stats->tx_bytes += dlc; - stats->tx_packets++; - - if (netif_queue_stopped(can->can.dev)) - netif_wake_queue(can->can.dev); - } - - return 0; -} - static void kvaser_pciefd_handle_nack_packet(struct kvaser_pciefd_can *can, struct kvaser_pciefd_rx_packet *p) { struct sk_buff *skb; - struct net_device_stats *stats = &can->can.dev->stats; struct can_frame *cf; skb = alloc_can_err_skb(can->can.dev, &cf); - - stats->tx_errors++; + can->can.dev->stats.tx_errors++; if (p->header[0] & KVASER_PCIEFD_APACKET_ABL) { if (skb) cf->can_id |= CAN_ERR_LOSTARB; @@ -1526,9 +1260,10 @@ static void kvaser_pciefd_handle_nack_packet(struct kvaser_pciefd_can *can, if (skb) { cf->can_id |= CAN_ERR_BUSERROR; + kvaser_pciefd_set_skb_timestamp(can->kv_pcie, skb, p->timestamp); netif_rx(skb); } else { - stats->rx_dropped++; + can->can.dev->stats.rx_dropped++; netdev_warn(can->can.dev, "No memory left for err_skb\n"); } } @@ -1538,7 +1273,7 @@ static int kvaser_pciefd_handle_ack_packet(struct kvaser_pciefd *pcie, { struct kvaser_pciefd_can *can; bool one_shot_fail = false; - u8 ch_id = (p->header[1] >> KVASER_PCIEFD_PACKET_CHID_SHIFT) & 0x7; + u8 ch_id = FIELD_GET(KVASER_PCIEFD_PACKET_CHID_MASK, p->header[1]); if (ch_id >= pcie->nr_channels) return -EIO; @@ -1556,20 +1291,24 @@ static int kvaser_pciefd_handle_ack_packet(struct kvaser_pciefd *pcie, if (p->header[0] & KVASER_PCIEFD_APACKET_FLU) { netdev_dbg(can->can.dev, "Packet was flushed\n"); } else { - int echo_idx = p->header[0] & KVASER_PCIEFD_PACKET_SEQ_MSK; - int dlc = can_get_echo_skb(can->can.dev, echo_idx, NULL); - u8 count = ioread32(can->reg_base + - KVASER_PCIEFD_KCAN_TX_NPACKETS_REG) & 0xff; + int echo_idx = FIELD_GET(KVASER_PCIEFD_PACKET_SEQ_MASK, p->header[0]); + int len; + u8 count; + struct sk_buff *skb; - if (count < KVASER_PCIEFD_CAN_TX_MAX_COUNT && - netif_queue_stopped(can->can.dev)) + skb = can->can.echo_skb[echo_idx]; + if (skb) + kvaser_pciefd_set_skb_timestamp(pcie, skb, p->timestamp); + len = can_get_echo_skb(can->can.dev, echo_idx, NULL); + count = FIELD_GET(KVASER_PCIEFD_KCAN_TX_NR_PACKETS_CURRENT_MASK, + ioread32(can->reg_base + KVASER_PCIEFD_KCAN_TX_NR_PACKETS_REG)); + + if (count < can->can.echo_skb_max && netif_queue_stopped(can->can.dev)) netif_wake_queue(can->can.dev); if (!one_shot_fail) { - struct net_device_stats *stats = &can->can.dev->stats; - - stats->tx_bytes += dlc; - stats->tx_packets++; + can->can.dev->stats.tx_bytes += len; + can->can.dev->stats.tx_packets++; } } @@ -1580,7 +1319,7 @@ static int kvaser_pciefd_handle_eflush_packet(struct kvaser_pciefd *pcie, struct kvaser_pciefd_rx_packet *p) { struct kvaser_pciefd_can *can; - u8 ch_id = (p->header[1] >> KVASER_PCIEFD_PACKET_CHID_SHIFT) & 0x7; + u8 ch_id = FIELD_GET(KVASER_PCIEFD_PACKET_CHID_MASK, p->header[1]); if (ch_id >= pcie->nr_channels) return -EIO; @@ -1619,15 +1358,15 @@ static int kvaser_pciefd_read_packet(struct kvaser_pciefd *pcie, int *start_pos, pos += 2; p->timestamp = le64_to_cpu(timestamp); - type = (p->header[1] >> KVASER_PCIEFD_PACKET_TYPE_SHIFT) & 0xf; + type = FIELD_GET(KVASER_PCIEFD_PACKET_TYPE_MASK, p->header[1]); switch (type) { case KVASER_PCIEFD_PACK_TYPE_DATA: ret = kvaser_pciefd_handle_data_packet(pcie, p, &buffer[pos]); if (!(p->header[0] & KVASER_PCIEFD_RPACKET_RTR)) { u8 data_len; - data_len = can_fd_dlc2len(p->header[1] >> - KVASER_PCIEFD_RPACKET_DLC_SHIFT); + data_len = can_fd_dlc2len(FIELD_GET(KVASER_PCIEFD_RPACKET_DLC_MASK, + p->header[1])); pos += DIV_ROUND_UP(data_len, 4); } break; @@ -1644,16 +1383,13 @@ static int kvaser_pciefd_read_packet(struct kvaser_pciefd *pcie, int *start_pos, ret = kvaser_pciefd_handle_error_packet(pcie, p); break; - case KVASER_PCIEFD_PACK_TYPE_EFRAME_ACK: - ret = kvaser_pciefd_handle_eack_packet(pcie, p); - break; - case KVASER_PCIEFD_PACK_TYPE_EFLUSH_ACK: ret = kvaser_pciefd_handle_eflush_packet(pcie, p); break; case KVASER_PCIEFD_PACK_TYPE_ACK_DATA: case KVASER_PCIEFD_PACK_TYPE_BUS_LOAD: + case KVASER_PCIEFD_PACK_TYPE_EFRAME_ACK: case KVASER_PCIEFD_PACK_TYPE_TXRQ: dev_info(&pcie->pci->dev, "Received unexpected packet type 0x%08X\n", type); @@ -1692,7 +1428,7 @@ static int kvaser_pciefd_read_buffer(struct kvaser_pciefd *pcie, int dma_buf) return res; } -static int kvaser_pciefd_receive_irq(struct kvaser_pciefd *pcie) +static void kvaser_pciefd_receive_irq(struct kvaser_pciefd *pcie) { u32 irq; @@ -1718,10 +1454,9 @@ static int kvaser_pciefd_receive_irq(struct kvaser_pciefd *pcie) dev_err(&pcie->pci->dev, "DMA IRQ error 0x%08X\n", irq); iowrite32(irq, pcie->reg_base + KVASER_PCIEFD_SRB_IRQ_REG); - return 0; } -static int kvaser_pciefd_transmit_irq(struct kvaser_pciefd_can *can) +static void kvaser_pciefd_transmit_irq(struct kvaser_pciefd_can *can) { u32 irq = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG); @@ -1739,7 +1474,6 @@ static int kvaser_pciefd_transmit_irq(struct kvaser_pciefd_can *can) netdev_err(can->can.dev, "Rx FIFO overflow\n"); iowrite32(irq, can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG); - return 0; } static irqreturn_t kvaser_pciefd_irq_handler(int irq, void *dev) @@ -1750,7 +1484,7 @@ static irqreturn_t kvaser_pciefd_irq_handler(int irq, void *dev) board_irq = ioread32(pcie->reg_base + KVASER_PCIEFD_IRQ_REG); - if (!(board_irq & KVASER_PCIEFD_IRQ_ALL_MSK)) + if (!(board_irq & KVASER_PCIEFD_IRQ_ALL_MASK)) return IRQ_NONE; if (board_irq & KVASER_PCIEFD_IRQ_SRB) @@ -1768,20 +1502,18 @@ static irqreturn_t kvaser_pciefd_irq_handler(int irq, void *dev) kvaser_pciefd_transmit_irq(pcie->can[i]); } - iowrite32(board_irq, pcie->reg_base + KVASER_PCIEFD_IRQ_REG); return IRQ_HANDLED; } static void kvaser_pciefd_teardown_can_ctrls(struct kvaser_pciefd *pcie) { int i; - struct kvaser_pciefd_can *can; for (i = 0; i < pcie->nr_channels; i++) { - can = pcie->can[i]; + struct kvaser_pciefd_can *can = pcie->can[i]; + if (can) { - iowrite32(0, - can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG); + iowrite32(0, can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG); kvaser_pciefd_pwm_stop(can); free_candev(can->can.dev); } @@ -1842,10 +1574,8 @@ static int kvaser_pciefd_probe(struct pci_dev *pdev, KVASER_PCIEFD_SRB_IRQ_DUF0 | KVASER_PCIEFD_SRB_IRQ_DUF1, pcie->reg_base + KVASER_PCIEFD_SRB_IEN_REG); - /* Reset IRQ handling, expected to be off before */ - iowrite32(KVASER_PCIEFD_IRQ_ALL_MSK, - pcie->reg_base + KVASER_PCIEFD_IRQ_REG); - iowrite32(KVASER_PCIEFD_IRQ_ALL_MSK, + /* Enable PCI interrupts */ + iowrite32(KVASER_PCIEFD_IRQ_ALL_MASK, pcie->reg_base + KVASER_PCIEFD_IEN_REG); /* Ready the DMA buffers */ @@ -1884,14 +1614,13 @@ static int kvaser_pciefd_probe(struct pci_dev *pdev, static void kvaser_pciefd_remove_all_ctrls(struct kvaser_pciefd *pcie) { - struct kvaser_pciefd_can *can; int i; for (i = 0; i < pcie->nr_channels; i++) { - can = pcie->can[i]; + struct kvaser_pciefd_can *can = pcie->can[i]; + if (can) { - iowrite32(0, - can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG); + iowrite32(0, can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG); unregister_candev(can->can.dev); del_timer(&can->bec_poll_timer); kvaser_pciefd_pwm_stop(can); @@ -1906,10 +1635,8 @@ static void kvaser_pciefd_remove(struct pci_dev *pdev) kvaser_pciefd_remove_all_ctrls(pcie); - /* Turn off IRQ generation */ + /* Disable interrupts */ iowrite32(0, pcie->reg_base + KVASER_PCIEFD_SRB_CTRL_REG); - iowrite32(KVASER_PCIEFD_IRQ_ALL_MSK, - pcie->reg_base + KVASER_PCIEFD_IRQ_REG); iowrite32(0, pcie->reg_base + KVASER_PCIEFD_IEN_REG); free_irq(pcie->pci->irq, pcie); diff --git a/drivers/net/can/m_can/m_can.c b/drivers/net/can/m_can/m_can.c index a5003435802b18819cac46b49e5a35c13a280ae4..c5af92bcc9c98afdf2eb0d477baead63d03f0987 100644 --- a/drivers/net/can/m_can/m_can.c +++ b/drivers/net/can/m_can/m_can.c @@ -469,7 +469,7 @@ static void m_can_receive_skb(struct m_can_classdev *cdev, int err; err = can_rx_offload_queue_timestamp(&cdev->offload, skb, - timestamp); + timestamp); if (err) stats->rx_fifo_errors++; } else { @@ -895,7 +895,7 @@ static int m_can_handle_bus_errors(struct net_device *dev, u32 irqstatus, netdev_dbg(dev, "Arbitration phase error detected\n"); work_done += m_can_handle_lec_err(dev, lec); } - + if (is_lec_err(dlec)) { netdev_dbg(dev, "Data phase error detected\n"); work_done += m_can_handle_lec_err(dev, dlec); diff --git a/drivers/net/can/m_can/m_can_platform.c b/drivers/net/can/m_can/m_can_platform.c index 9c1dcf838006dcd5f2e964fc526abd195a7ef3c4..94dc82644113617d7740bf77c06da35037230b03 100644 --- a/drivers/net/can/m_can/m_can_platform.c +++ b/drivers/net/can/m_can/m_can_platform.c @@ -164,7 +164,7 @@ static __maybe_unused int m_can_resume(struct device *dev) return m_can_class_resume(dev); } -static int m_can_plat_remove(struct platform_device *pdev) +static void m_can_plat_remove(struct platform_device *pdev) { struct m_can_plat_priv *priv = platform_get_drvdata(pdev); struct m_can_classdev *mcan_class = &priv->cdev; @@ -172,8 +172,6 @@ static int m_can_plat_remove(struct platform_device *pdev) m_can_class_unregister(mcan_class); m_can_class_free_dev(mcan_class->net); - - return 0; } static int __maybe_unused m_can_runtime_suspend(struct device *dev) @@ -223,7 +221,7 @@ static struct platform_driver m_can_plat_driver = { .pm = &m_can_pmops, }, .probe = m_can_plat_probe, - .remove = m_can_plat_remove, + .remove_new = m_can_plat_remove, }; module_platform_driver(m_can_plat_driver); diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c index b0ed798ae70febdf32e80b419b1c2e8d17cd6c4a..4837df6efa92685fbb632986dbb51bab67590de5 100644 --- a/drivers/net/can/mscan/mpc5xxx_can.c +++ b/drivers/net/can/mscan/mpc5xxx_can.c @@ -349,7 +349,7 @@ static int mpc5xxx_can_probe(struct platform_device *ofdev) return err; } -static int mpc5xxx_can_remove(struct platform_device *ofdev) +static void mpc5xxx_can_remove(struct platform_device *ofdev) { const struct of_device_id *match; const struct mpc5xxx_can_data *data; @@ -365,8 +365,6 @@ static int mpc5xxx_can_remove(struct platform_device *ofdev) iounmap(priv->reg_base); irq_dispose_mapping(dev->irq); free_candev(dev); - - return 0; } #ifdef CONFIG_PM @@ -437,7 +435,7 @@ static struct platform_driver mpc5xxx_can_driver = { .of_match_table = mpc5xxx_can_table, }, .probe = mpc5xxx_can_probe, - .remove = mpc5xxx_can_remove, + .remove_new = mpc5xxx_can_remove, #ifdef CONFIG_PM .suspend = mpc5xxx_can_suspend, .resume = mpc5xxx_can_resume, diff --git a/drivers/net/can/rcar/rcar_can.c b/drivers/net/can/rcar/rcar_can.c index cc43c9c5e38c58ac69a9826075cf578177ac5ede..f5aa5dbacaf21fc6ebcb71b1ac73599374b3ef3b 100644 --- a/drivers/net/can/rcar/rcar_can.c +++ b/drivers/net/can/rcar/rcar_can.c @@ -824,7 +824,7 @@ static int rcar_can_probe(struct platform_device *pdev) return err; } -static int rcar_can_remove(struct platform_device *pdev) +static void rcar_can_remove(struct platform_device *pdev) { struct net_device *ndev = platform_get_drvdata(pdev); struct rcar_can_priv *priv = netdev_priv(ndev); @@ -832,7 +832,6 @@ static int rcar_can_remove(struct platform_device *pdev) unregister_candev(ndev); netif_napi_del(&priv->napi); free_candev(ndev); - return 0; } static int __maybe_unused rcar_can_suspend(struct device *dev) @@ -908,7 +907,7 @@ static struct platform_driver rcar_can_driver = { .pm = &rcar_can_pm_ops, }, .probe = rcar_can_probe, - .remove = rcar_can_remove, + .remove_new = rcar_can_remove, }; module_platform_driver(rcar_can_driver); diff --git a/drivers/net/can/rcar/rcar_canfd.c b/drivers/net/can/rcar/rcar_canfd.c index 963c42f4375595ae3555744217fe8c9d00e1015d..e4d7489134399538090bb1fc38f36f99e1ea2af9 100644 --- a/drivers/net/can/rcar/rcar_canfd.c +++ b/drivers/net/can/rcar/rcar_canfd.c @@ -2078,7 +2078,7 @@ static int rcar_canfd_probe(struct platform_device *pdev) return err; } -static int rcar_canfd_remove(struct platform_device *pdev) +static void rcar_canfd_remove(struct platform_device *pdev) { struct rcar_canfd_global *gpriv = platform_get_drvdata(pdev); u32 ch; @@ -2096,8 +2096,6 @@ static int rcar_canfd_remove(struct platform_device *pdev) clk_disable_unprepare(gpriv->clkp); reset_control_assert(gpriv->rstc1); reset_control_assert(gpriv->rstc2); - - return 0; } static int __maybe_unused rcar_canfd_suspend(struct device *dev) @@ -2130,7 +2128,7 @@ static struct platform_driver rcar_canfd_driver = { .pm = &rcar_canfd_pm_ops, }, .probe = rcar_canfd_probe, - .remove = rcar_canfd_remove, + .remove_new = rcar_canfd_remove, }; module_platform_driver(rcar_canfd_driver); diff --git a/drivers/net/can/sja1000/sja1000.c b/drivers/net/can/sja1000/sja1000.c index aac5956e4a532092a0e67a0b57937ac10c8b4597..0ada0e160e93605828db9d6e879c51e65c0e6f32 100644 --- a/drivers/net/can/sja1000/sja1000.c +++ b/drivers/net/can/sja1000/sja1000.c @@ -387,6 +387,16 @@ static void sja1000_rx(struct net_device *dev) netif_rx(skb); } +static irqreturn_t sja1000_reset_interrupt(int irq, void *dev_id) +{ + struct net_device *dev = (struct net_device *)dev_id; + + netdev_dbg(dev, "performing a soft reset upon overrun\n"); + sja1000_start(dev); + + return IRQ_HANDLED; +} + static int sja1000_err(struct net_device *dev, uint8_t isrc, uint8_t status) { struct sja1000_priv *priv = netdev_priv(dev); @@ -397,6 +407,7 @@ static int sja1000_err(struct net_device *dev, uint8_t isrc, uint8_t status) enum can_state rx_state, tx_state; unsigned int rxerr, txerr; uint8_t ecc, alc; + int ret = 0; skb = alloc_can_err_skb(dev, &cf); if (skb == NULL) @@ -413,6 +424,15 @@ static int sja1000_err(struct net_device *dev, uint8_t isrc, uint8_t status) stats->rx_over_errors++; stats->rx_errors++; sja1000_write_cmdreg(priv, CMD_CDO); /* clear bit */ + + /* Some controllers needs additional handling upon overrun + * condition: the controller may sometimes be totally confused + * and refuse any new frame while its buffer is empty. The only + * way to re-sync the read vs. write buffer offsets is to + * stop any current handling and perform a reset. + */ + if (priv->flags & SJA1000_QUIRK_RESET_ON_OVERRUN) + ret = IRQ_WAKE_THREAD; } if (isrc & IRQ_EI) { @@ -492,7 +512,7 @@ static int sja1000_err(struct net_device *dev, uint8_t isrc, uint8_t status) netif_rx(skb); - return 0; + return ret; } irqreturn_t sja1000_interrupt(int irq, void *dev_id) @@ -501,7 +521,8 @@ irqreturn_t sja1000_interrupt(int irq, void *dev_id) struct sja1000_priv *priv = netdev_priv(dev); struct net_device_stats *stats = &dev->stats; uint8_t isrc, status; - int n = 0; + irqreturn_t ret = 0; + int n = 0, err; if (priv->pre_irq) priv->pre_irq(priv); @@ -546,19 +567,25 @@ irqreturn_t sja1000_interrupt(int irq, void *dev_id) } if (isrc & (IRQ_DOI | IRQ_EI | IRQ_BEI | IRQ_EPI | IRQ_ALI)) { /* error interrupt */ - if (sja1000_err(dev, isrc, status)) + err = sja1000_err(dev, isrc, status); + if (err == IRQ_WAKE_THREAD) + ret = err; + if (err) break; } n++; } out: + if (!ret) + ret = (n) ? IRQ_HANDLED : IRQ_NONE; + if (priv->post_irq) priv->post_irq(priv); if (n >= SJA1000_MAX_IRQ) netdev_dbg(dev, "%d messages handled in ISR", n); - return (n) ? IRQ_HANDLED : IRQ_NONE; + return ret; } EXPORT_SYMBOL_GPL(sja1000_interrupt); @@ -577,8 +604,9 @@ static int sja1000_open(struct net_device *dev) /* register interrupt handler, if not done by the device driver */ if (!(priv->flags & SJA1000_CUSTOM_IRQ_HANDLER)) { - err = request_irq(dev->irq, sja1000_interrupt, priv->irq_flags, - dev->name, (void *)dev); + err = request_threaded_irq(dev->irq, sja1000_interrupt, + sja1000_reset_interrupt, + priv->irq_flags, dev->name, (void *)dev); if (err) { close_candev(dev); return -EAGAIN; diff --git a/drivers/net/can/sja1000/sja1000.h b/drivers/net/can/sja1000/sja1000.h index 7f736f1df5474b7246911b9ae15c555c170275ed..f015e39e2224f2c31217a982599b10bb605ad6ae 100644 --- a/drivers/net/can/sja1000/sja1000.h +++ b/drivers/net/can/sja1000/sja1000.h @@ -147,6 +147,7 @@ */ #define SJA1000_CUSTOM_IRQ_HANDLER BIT(0) #define SJA1000_QUIRK_NO_CDR_REG BIT(1) +#define SJA1000_QUIRK_RESET_ON_OVERRUN BIT(2) /* * SJA1000 private data structure diff --git a/drivers/net/can/sja1000/sja1000_isa.c b/drivers/net/can/sja1000/sja1000_isa.c index db3e767d5320fd1a309d4323246c32c41abcabe2..fca5a9a1d85792a6aad1610d7c81ac8d25a40851 100644 --- a/drivers/net/can/sja1000/sja1000_isa.c +++ b/drivers/net/can/sja1000/sja1000_isa.c @@ -223,7 +223,7 @@ static int sja1000_isa_probe(struct platform_device *pdev) return err; } -static int sja1000_isa_remove(struct platform_device *pdev) +static void sja1000_isa_remove(struct platform_device *pdev) { struct net_device *dev = platform_get_drvdata(pdev); struct sja1000_priv *priv = netdev_priv(dev); @@ -241,13 +241,11 @@ static int sja1000_isa_remove(struct platform_device *pdev) release_region(port[idx], SJA1000_IOSIZE); } free_sja1000dev(dev); - - return 0; } static struct platform_driver sja1000_isa_driver = { .probe = sja1000_isa_probe, - .remove = sja1000_isa_remove, + .remove_new = sja1000_isa_remove, .driver = { .name = DRV_NAME, }, diff --git a/drivers/net/can/sja1000/sja1000_platform.c b/drivers/net/can/sja1000/sja1000_platform.c index 6779d5357069f6df903160b19008fabc849333db..4e59952c66d49ecc7a770797e9c373ddcc4d2c66 100644 --- a/drivers/net/can/sja1000/sja1000_platform.c +++ b/drivers/net/can/sja1000/sja1000_platform.c @@ -106,7 +106,7 @@ static void sp_technologic_init(struct sja1000_priv *priv, struct device_node *o static void sp_rzn1_init(struct sja1000_priv *priv, struct device_node *of) { - priv->flags = SJA1000_QUIRK_NO_CDR_REG; + priv->flags = SJA1000_QUIRK_NO_CDR_REG | SJA1000_QUIRK_RESET_ON_OVERRUN; } static void sp_populate(struct sja1000_priv *priv, @@ -277,6 +277,9 @@ static int sp_probe(struct platform_device *pdev) priv->irq_flags = IRQF_SHARED; } + if (priv->flags & SJA1000_QUIRK_RESET_ON_OVERRUN) + priv->irq_flags |= IRQF_ONESHOT; + dev->irq = irq; priv->reg_base = addr; @@ -317,19 +320,17 @@ static int sp_probe(struct platform_device *pdev) return err; } -static int sp_remove(struct platform_device *pdev) +static void sp_remove(struct platform_device *pdev) { struct net_device *dev = platform_get_drvdata(pdev); unregister_sja1000dev(dev); free_sja1000dev(dev); - - return 0; } static struct platform_driver sp_driver = { .probe = sp_probe, - .remove = sp_remove, + .remove_new = sp_remove, .driver = { .name = DRV_NAME, .of_match_table = sp_of_table, diff --git a/drivers/net/can/softing/softing_main.c b/drivers/net/can/softing/softing_main.c index c72f505d29feec565f0fff43d3a7f51240800405..bd25137062c5e60d3b3bb27191abd437bc2d8312 100644 --- a/drivers/net/can/softing/softing_main.c +++ b/drivers/net/can/softing/softing_main.c @@ -729,7 +729,7 @@ static const struct attribute_group softing_pdev_group = { /* * platform driver */ -static int softing_pdev_remove(struct platform_device *pdev) +static void softing_pdev_remove(struct platform_device *pdev) { struct softing *card = platform_get_drvdata(pdev); int j; @@ -747,7 +747,6 @@ static int softing_pdev_remove(struct platform_device *pdev) iounmap(card->dpram); kfree(card); - return 0; } static int softing_pdev_probe(struct platform_device *pdev) @@ -855,7 +854,7 @@ static struct platform_driver softing_driver = { .name = KBUILD_MODNAME, }, .probe = softing_pdev_probe, - .remove = softing_pdev_remove, + .remove_new = softing_pdev_remove, }; module_platform_driver(softing_driver); diff --git a/drivers/net/can/sun4i_can.c b/drivers/net/can/sun4i_can.c index 2b78f9197681b739d6b09693e714bc6bdd203b05..0827830bbf28cd024ff51bb2334e6c98ad56eea3 100644 --- a/drivers/net/can/sun4i_can.c +++ b/drivers/net/can/sun4i_can.c @@ -791,14 +791,12 @@ static const struct of_device_id sun4ican_of_match[] = { MODULE_DEVICE_TABLE(of, sun4ican_of_match); -static int sun4ican_remove(struct platform_device *pdev) +static void sun4ican_remove(struct platform_device *pdev) { struct net_device *dev = platform_get_drvdata(pdev); unregister_netdev(dev); free_candev(dev); - - return 0; } static int sun4ican_probe(struct platform_device *pdev) @@ -901,7 +899,7 @@ static struct platform_driver sun4i_can_driver = { .of_match_table = sun4ican_of_match, }, .probe = sun4ican_probe, - .remove = sun4ican_remove, + .remove_new = sun4ican_remove, }; module_platform_driver(sun4i_can_driver); diff --git a/drivers/net/can/ti_hecc.c b/drivers/net/can/ti_hecc.c index 27700f72eac259458deaf23542dac43ab358f472..54284661992eb333cf615a924bb17eb3f08693f5 100644 --- a/drivers/net/can/ti_hecc.c +++ b/drivers/net/can/ti_hecc.c @@ -625,7 +625,7 @@ static int ti_hecc_error(struct net_device *ndev, int int_status, timestamp = hecc_read(priv, HECC_CANLNT); err = can_rx_offload_queue_timestamp(&priv->offload, skb, - timestamp); + timestamp); if (err) ndev->stats.rx_fifo_errors++; } @@ -963,7 +963,7 @@ static int ti_hecc_probe(struct platform_device *pdev) return err; } -static int ti_hecc_remove(struct platform_device *pdev) +static void ti_hecc_remove(struct platform_device *pdev) { struct net_device *ndev = platform_get_drvdata(pdev); struct ti_hecc_priv *priv = netdev_priv(ndev); @@ -973,8 +973,6 @@ static int ti_hecc_remove(struct platform_device *pdev) clk_put(priv->clk); can_rx_offload_del(&priv->offload); free_candev(ndev); - - return 0; } #ifdef CONFIG_PM @@ -1028,7 +1026,7 @@ static struct platform_driver ti_hecc_driver = { .of_match_table = ti_hecc_dt_ids, }, .probe = ti_hecc_probe, - .remove = ti_hecc_remove, + .remove_new = ti_hecc_remove, .suspend = ti_hecc_suspend, .resume = ti_hecc_resume, }; diff --git a/drivers/net/can/usb/Kconfig b/drivers/net/can/usb/Kconfig index 445504ababcedd381616f4315476b53c25488069..58fcd2b348207cb2410ba830aeec010d124053f2 100644 --- a/drivers/net/can/usb/Kconfig +++ b/drivers/net/can/usb/Kconfig @@ -38,6 +38,18 @@ config CAN_ETAS_ES58X To compile this driver as a module, choose M here: the module will be called etas_es58x. +config CAN_F81604 + tristate "Fintek F81604 USB to 2CAN interface" + help + This driver supports the Fintek F81604 USB to 2CAN interface. + The device can support CAN2.0A/B protocol and also support + 2 output pins to control external terminator (optional). + + To compile this driver as a module, choose M here: the module will + be called f81604. + + (see also https://www.fintek.com.tw). + config CAN_GS_USB tristate "Geschwister Schneider UG and candleLight compatible interfaces" help diff --git a/drivers/net/can/usb/Makefile b/drivers/net/can/usb/Makefile index 1ea16be5743b4abddda5d8a91257ec0faeee42b9..8b11088e9a5956c2a63a3476d898b12788cbf581 100644 --- a/drivers/net/can/usb/Makefile +++ b/drivers/net/can/usb/Makefile @@ -7,6 +7,7 @@ obj-$(CONFIG_CAN_8DEV_USB) += usb_8dev.o obj-$(CONFIG_CAN_EMS_USB) += ems_usb.o obj-$(CONFIG_CAN_ESD_USB) += esd_usb.o obj-$(CONFIG_CAN_ETAS_ES58X) += etas_es58x/ +obj-$(CONFIG_CAN_F81604) += f81604.o obj-$(CONFIG_CAN_GS_USB) += gs_usb.o obj-$(CONFIG_CAN_KVASER_USB) += kvaser_usb/ obj-$(CONFIG_CAN_MCBA_USB) += mcba_usb.o diff --git a/drivers/net/can/usb/esd_usb.c b/drivers/net/can/usb/esd_usb.c index d33bac3a6c10630eca2b55e285c269144a477080..6201637ac0ff2056ca08f9803bbc826947858bfa 100644 --- a/drivers/net/can/usb/esd_usb.c +++ b/drivers/net/can/usb/esd_usb.c @@ -3,18 +3,19 @@ * CAN driver for esd electronics gmbh CAN-USB/2 and CAN-USB/Micro * * Copyright (C) 2010-2012 esd electronic system design gmbh, Matthias Fuchs - * Copyright (C) 2022 esd electronics gmbh, Frank Jungclaus + * Copyright (C) 2022-2023 esd electronics gmbh, Frank Jungclaus */ -#include -#include -#include -#include -#include -#include #include #include #include +#include +#include +#include +#include +#include +#include +#include MODULE_AUTHOR("Matthias Fuchs "); MODULE_AUTHOR("Frank Jungclaus "); @@ -22,95 +23,87 @@ MODULE_DESCRIPTION("CAN driver for esd electronics gmbh CAN-USB/2 and CAN-USB/Mi MODULE_LICENSE("GPL v2"); /* USB vendor and product ID */ -#define USB_ESDGMBH_VENDOR_ID 0x0ab4 -#define USB_CANUSB2_PRODUCT_ID 0x0010 -#define USB_CANUSBM_PRODUCT_ID 0x0011 +#define ESD_USB_ESDGMBH_VENDOR_ID 0x0ab4 +#define ESD_USB_CANUSB2_PRODUCT_ID 0x0010 +#define ESD_USB_CANUSBM_PRODUCT_ID 0x0011 /* CAN controller clock frequencies */ -#define ESD_USB2_CAN_CLOCK 60000000 -#define ESD_USBM_CAN_CLOCK 36000000 +#define ESD_USB_2_CAN_CLOCK (60 * MEGA) /* Hz */ +#define ESD_USB_M_CAN_CLOCK (36 * MEGA) /* Hz */ /* Maximum number of CAN nets */ #define ESD_USB_MAX_NETS 2 /* USB commands */ -#define CMD_VERSION 1 /* also used for VERSION_REPLY */ -#define CMD_CAN_RX 2 /* device to host only */ -#define CMD_CAN_TX 3 /* also used for TX_DONE */ -#define CMD_SETBAUD 4 /* also used for SETBAUD_REPLY */ -#define CMD_TS 5 /* also used for TS_REPLY */ -#define CMD_IDADD 6 /* also used for IDADD_REPLY */ +#define ESD_USB_CMD_VERSION 1 /* also used for VERSION_REPLY */ +#define ESD_USB_CMD_CAN_RX 2 /* device to host only */ +#define ESD_USB_CMD_CAN_TX 3 /* also used for TX_DONE */ +#define ESD_USB_CMD_SETBAUD 4 /* also used for SETBAUD_REPLY */ +#define ESD_USB_CMD_TS 5 /* also used for TS_REPLY */ +#define ESD_USB_CMD_IDADD 6 /* also used for IDADD_REPLY */ /* esd CAN message flags - dlc field */ -#define ESD_RTR 0x10 +#define ESD_USB_RTR BIT(4) /* esd CAN message flags - id field */ -#define ESD_EXTID 0x20000000 -#define ESD_EVENT 0x40000000 -#define ESD_IDMASK 0x1fffffff +#define ESD_USB_EXTID BIT(29) +#define ESD_USB_EVENT BIT(30) +#define ESD_USB_IDMASK GENMASK(28, 0) /* esd CAN event ids */ -#define ESD_EV_CAN_ERROR_EXT 2 /* CAN controller specific diagnostic data */ +#define ESD_USB_EV_CAN_ERROR_EXT 2 /* CAN controller specific diagnostic data */ /* baudrate message flags */ -#define ESD_USB_UBR 0x80000000 -#define ESD_USB_LOM 0x40000000 -#define ESD_USB_NO_BAUDRATE 0x7fffffff - -/* bit timing CAN-USB/2 */ -#define ESD_USB2_TSEG1_MIN 1 -#define ESD_USB2_TSEG1_MAX 16 -#define ESD_USB2_TSEG1_SHIFT 16 -#define ESD_USB2_TSEG2_MIN 1 -#define ESD_USB2_TSEG2_MAX 8 -#define ESD_USB2_TSEG2_SHIFT 20 -#define ESD_USB2_SJW_MAX 4 -#define ESD_USB2_SJW_SHIFT 14 -#define ESD_USBM_SJW_SHIFT 24 -#define ESD_USB2_BRP_MIN 1 -#define ESD_USB2_BRP_MAX 1024 -#define ESD_USB2_BRP_INC 1 -#define ESD_USB2_3_SAMPLES 0x00800000 +#define ESD_USB_LOM BIT(30) /* Listen Only Mode */ +#define ESD_USB_UBR BIT(31) /* User Bit Rate (controller BTR) in bits 0..27 */ +#define ESD_USB_NO_BAUDRATE GENMASK(30, 0) /* bit rate unconfigured */ + +/* bit timing esd CAN-USB */ +#define ESD_USB_2_TSEG1_SHIFT 16 +#define ESD_USB_2_TSEG2_SHIFT 20 +#define ESD_USB_2_SJW_SHIFT 14 +#define ESD_USB_M_SJW_SHIFT 24 +#define ESD_USB_TRIPLE_SAMPLES BIT(23) /* esd IDADD message */ -#define ESD_ID_ENABLE 0x80 -#define ESD_MAX_ID_SEGMENT 64 +#define ESD_USB_ID_ENABLE BIT(7) +#define ESD_USB_MAX_ID_SEGMENT 64 /* SJA1000 ECC register (emulated by usb firmware) */ -#define SJA1000_ECC_SEG 0x1F -#define SJA1000_ECC_DIR 0x20 -#define SJA1000_ECC_ERR 0x06 -#define SJA1000_ECC_BIT 0x00 -#define SJA1000_ECC_FORM 0x40 -#define SJA1000_ECC_STUFF 0x80 -#define SJA1000_ECC_MASK 0xc0 +#define ESD_USB_SJA1000_ECC_SEG GENMASK(4, 0) +#define ESD_USB_SJA1000_ECC_DIR BIT(5) +#define ESD_USB_SJA1000_ECC_ERR BIT(2, 1) +#define ESD_USB_SJA1000_ECC_BIT 0x00 +#define ESD_USB_SJA1000_ECC_FORM BIT(6) +#define ESD_USB_SJA1000_ECC_STUFF BIT(7) +#define ESD_USB_SJA1000_ECC_MASK GENMASK(7, 6) /* esd bus state event codes */ -#define ESD_BUSSTATE_MASK 0xc0 -#define ESD_BUSSTATE_WARN 0x40 -#define ESD_BUSSTATE_ERRPASSIVE 0x80 -#define ESD_BUSSTATE_BUSOFF 0xc0 +#define ESD_USB_BUSSTATE_MASK GENMASK(7, 6) +#define ESD_USB_BUSSTATE_WARN BIT(6) +#define ESD_USB_BUSSTATE_ERRPASSIVE BIT(7) +#define ESD_USB_BUSSTATE_BUSOFF GENMASK(7, 6) -#define RX_BUFFER_SIZE 1024 -#define MAX_RX_URBS 4 -#define MAX_TX_URBS 16 /* must be power of 2 */ +#define ESD_USB_RX_BUFFER_SIZE 1024 +#define ESD_USB_MAX_RX_URBS 4 +#define ESD_USB_MAX_TX_URBS 16 /* must be power of 2 */ -struct header_msg { - u8 len; /* len is always the total message length in 32bit words */ +struct esd_usb_header_msg { + u8 len; /* total message length in 32bit words */ u8 cmd; u8 rsvd[2]; }; -struct version_msg { - u8 len; +struct esd_usb_version_msg { + u8 len; /* total message length in 32bit words */ u8 cmd; u8 rsvd; u8 flags; __le32 drv_version; }; -struct version_reply_msg { - u8 len; +struct esd_usb_version_reply_msg { + u8 len; /* total message length in 32bit words */ u8 cmd; u8 nets; u8 features; @@ -120,15 +113,15 @@ struct version_reply_msg { __le32 ts; }; -struct rx_msg { - u8 len; +struct esd_usb_rx_msg { + u8 len; /* total message length in 32bit words */ u8 cmd; u8 net; u8 dlc; __le32 ts; __le32 id; /* upper 3 bits contain flags */ union { - u8 data[8]; + u8 data[CAN_MAX_DLEN]; struct { u8 status; /* CAN Controller Status */ u8 ecc; /* Error Capture Register */ @@ -138,18 +131,18 @@ struct rx_msg { }; }; -struct tx_msg { - u8 len; +struct esd_usb_tx_msg { + u8 len; /* total message length in 32bit words */ u8 cmd; u8 net; u8 dlc; u32 hnd; /* opaque handle, not used by device */ __le32 id; /* upper 3 bits contain flags */ - u8 data[8]; + u8 data[CAN_MAX_DLEN]; }; -struct tx_done_msg { - u8 len; +struct esd_usb_tx_done_msg { + u8 len; /* total message length in 32bit words */ u8 cmd; u8 net; u8 status; @@ -157,16 +150,16 @@ struct tx_done_msg { __le32 ts; }; -struct id_filter_msg { - u8 len; +struct esd_usb_id_filter_msg { + u8 len; /* total message length in 32bit words */ u8 cmd; u8 net; u8 option; - __le32 mask[ESD_MAX_ID_SEGMENT + 1]; + __le32 mask[ESD_USB_MAX_ID_SEGMENT + 1]; /* +1 for 29bit extended IDs */ }; -struct set_baudrate_msg { - u8 len; +struct esd_usb_set_baudrate_msg { + u8 len; /* total message length in 32bit words */ u8 cmd; u8 net; u8 rsvd; @@ -175,19 +168,19 @@ struct set_baudrate_msg { /* Main message type used between library and application */ union __packed esd_usb_msg { - struct header_msg hdr; - struct version_msg version; - struct version_reply_msg version_reply; - struct rx_msg rx; - struct tx_msg tx; - struct tx_done_msg txdone; - struct set_baudrate_msg setbaud; - struct id_filter_msg filter; + struct esd_usb_header_msg hdr; + struct esd_usb_version_msg version; + struct esd_usb_version_reply_msg version_reply; + struct esd_usb_rx_msg rx; + struct esd_usb_tx_msg tx; + struct esd_usb_tx_done_msg txdone; + struct esd_usb_set_baudrate_msg setbaud; + struct esd_usb_id_filter_msg filter; }; static struct usb_device_id esd_usb_table[] = { - {USB_DEVICE(USB_ESDGMBH_VENDOR_ID, USB_CANUSB2_PRODUCT_ID)}, - {USB_DEVICE(USB_ESDGMBH_VENDOR_ID, USB_CANUSBM_PRODUCT_ID)}, + {USB_DEVICE(ESD_USB_ESDGMBH_VENDOR_ID, ESD_USB_CANUSB2_PRODUCT_ID)}, + {USB_DEVICE(ESD_USB_ESDGMBH_VENDOR_ID, ESD_USB_CANUSBM_PRODUCT_ID)}, {} }; MODULE_DEVICE_TABLE(usb, esd_usb_table); @@ -208,8 +201,8 @@ struct esd_usb { int net_count; u32 version; int rxinitdone; - void *rxbuf[MAX_RX_URBS]; - dma_addr_t rxbuf_dma[MAX_RX_URBS]; + void *rxbuf[ESD_USB_MAX_RX_URBS]; + dma_addr_t rxbuf_dma[ESD_USB_MAX_RX_URBS]; }; struct esd_usb_net_priv { @@ -217,7 +210,7 @@ struct esd_usb_net_priv { atomic_t active_tx_jobs; struct usb_anchor tx_submitted; - struct esd_tx_urb_context tx_contexts[MAX_TX_URBS]; + struct esd_tx_urb_context tx_contexts[ESD_USB_MAX_TX_URBS]; struct esd_usb *usb; struct net_device *netdev; @@ -232,9 +225,9 @@ static void esd_usb_rx_event(struct esd_usb_net_priv *priv, struct net_device_stats *stats = &priv->netdev->stats; struct can_frame *cf; struct sk_buff *skb; - u32 id = le32_to_cpu(msg->rx.id) & ESD_IDMASK; + u32 id = le32_to_cpu(msg->rx.id) & ESD_USB_IDMASK; - if (id == ESD_EV_CAN_ERROR_EXT) { + if (id == ESD_USB_EV_CAN_ERROR_EXT) { u8 state = msg->rx.ev_can_err_ext.status; u8 ecc = msg->rx.ev_can_err_ext.ecc; @@ -261,15 +254,15 @@ static void esd_usb_rx_event(struct esd_usb_net_priv *priv, priv->old_state = state; - switch (state & ESD_BUSSTATE_MASK) { - case ESD_BUSSTATE_BUSOFF: + switch (state & ESD_USB_BUSSTATE_MASK) { + case ESD_USB_BUSSTATE_BUSOFF: new_state = CAN_STATE_BUS_OFF; can_bus_off(priv->netdev); break; - case ESD_BUSSTATE_WARN: + case ESD_USB_BUSSTATE_WARN: new_state = CAN_STATE_ERROR_WARNING; break; - case ESD_BUSSTATE_ERRPASSIVE: + case ESD_USB_BUSSTATE_ERRPASSIVE: new_state = CAN_STATE_ERROR_PASSIVE; break; default: @@ -291,14 +284,14 @@ static void esd_usb_rx_event(struct esd_usb_net_priv *priv, cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR; - switch (ecc & SJA1000_ECC_MASK) { - case SJA1000_ECC_BIT: + switch (ecc & ESD_USB_SJA1000_ECC_MASK) { + case ESD_USB_SJA1000_ECC_BIT: cf->data[2] |= CAN_ERR_PROT_BIT; break; - case SJA1000_ECC_FORM: + case ESD_USB_SJA1000_ECC_FORM: cf->data[2] |= CAN_ERR_PROT_FORM; break; - case SJA1000_ECC_STUFF: + case ESD_USB_SJA1000_ECC_STUFF: cf->data[2] |= CAN_ERR_PROT_STUFF; break; default: @@ -306,11 +299,11 @@ static void esd_usb_rx_event(struct esd_usb_net_priv *priv, } /* Error occurred during transmission? */ - if (!(ecc & SJA1000_ECC_DIR)) + if (!(ecc & ESD_USB_SJA1000_ECC_DIR)) cf->data[2] |= CAN_ERR_PROT_TX; /* Bit stream position in CAN frame as the error was detected */ - cf->data[3] = ecc & SJA1000_ECC_SEG; + cf->data[3] = ecc & ESD_USB_SJA1000_ECC_SEG; } if (skb) { @@ -337,7 +330,7 @@ static void esd_usb_rx_can_msg(struct esd_usb_net_priv *priv, id = le32_to_cpu(msg->rx.id); - if (id & ESD_EVENT) { + if (id & ESD_USB_EVENT) { esd_usb_rx_event(priv, msg); } else { skb = alloc_can_skb(priv->netdev, &cf); @@ -346,14 +339,14 @@ static void esd_usb_rx_can_msg(struct esd_usb_net_priv *priv, return; } - cf->can_id = id & ESD_IDMASK; - can_frame_set_cc_len(cf, msg->rx.dlc & ~ESD_RTR, + cf->can_id = id & ESD_USB_IDMASK; + can_frame_set_cc_len(cf, msg->rx.dlc & ~ESD_USB_RTR, priv->can.ctrlmode); - if (id & ESD_EXTID) + if (id & ESD_USB_EXTID) cf->can_id |= CAN_EFF_FLAG; - if (msg->rx.dlc & ESD_RTR) { + if (msg->rx.dlc & ESD_USB_RTR) { cf->can_id |= CAN_RTR_FLAG; } else { for (i = 0; i < cf->len; i++) @@ -377,7 +370,7 @@ static void esd_usb_tx_done_msg(struct esd_usb_net_priv *priv, if (!netif_device_present(netdev)) return; - context = &priv->tx_contexts[msg->txdone.hnd & (MAX_TX_URBS - 1)]; + context = &priv->tx_contexts[msg->txdone.hnd & (ESD_USB_MAX_TX_URBS - 1)]; if (!msg->txdone.status) { stats->tx_packets++; @@ -389,7 +382,7 @@ static void esd_usb_tx_done_msg(struct esd_usb_net_priv *priv, } /* Release context */ - context->echo_index = MAX_TX_URBS; + context->echo_index = ESD_USB_MAX_TX_URBS; atomic_dec(&priv->active_tx_jobs); netif_wake_queue(netdev); @@ -424,7 +417,7 @@ static void esd_usb_read_bulk_callback(struct urb *urb) msg = (union esd_usb_msg *)(urb->transfer_buffer + pos); switch (msg->hdr.cmd) { - case CMD_CAN_RX: + case ESD_USB_CMD_CAN_RX: if (msg->rx.net >= dev->net_count) { dev_err(dev->udev->dev.parent, "format error\n"); break; @@ -433,7 +426,7 @@ static void esd_usb_read_bulk_callback(struct urb *urb) esd_usb_rx_can_msg(dev->nets[msg->rx.net], msg); break; - case CMD_CAN_TX: + case ESD_USB_CMD_CAN_TX: if (msg->txdone.net >= dev->net_count) { dev_err(dev->udev->dev.parent, "format error\n"); break; @@ -444,7 +437,7 @@ static void esd_usb_read_bulk_callback(struct urb *urb) break; } - pos += msg->hdr.len << 2; + pos += msg->hdr.len * sizeof(u32); /* convert to # of bytes */ if (pos > urb->actual_length) { dev_err(dev->udev->dev.parent, "format error\n"); @@ -454,7 +447,7 @@ static void esd_usb_read_bulk_callback(struct urb *urb) resubmit_urb: usb_fill_bulk_urb(urb, dev->udev, usb_rcvbulkpipe(dev->udev, 1), - urb->transfer_buffer, RX_BUFFER_SIZE, + urb->transfer_buffer, ESD_USB_RX_BUFFER_SIZE, esd_usb_read_bulk_callback, dev); retval = usb_submit_urb(urb, GFP_ATOMIC); @@ -538,7 +531,7 @@ static int esd_usb_send_msg(struct esd_usb *dev, union esd_usb_msg *msg) return usb_bulk_msg(dev->udev, usb_sndbulkpipe(dev->udev, 2), msg, - msg->hdr.len << 2, + msg->hdr.len * sizeof(u32), /* convert to # of bytes */ &actual_length, 1000); } @@ -563,7 +556,7 @@ static int esd_usb_setup_rx_urbs(struct esd_usb *dev) if (dev->rxinitdone) return 0; - for (i = 0; i < MAX_RX_URBS; i++) { + for (i = 0; i < ESD_USB_MAX_RX_URBS; i++) { struct urb *urb = NULL; u8 *buf = NULL; dma_addr_t buf_dma; @@ -575,7 +568,7 @@ static int esd_usb_setup_rx_urbs(struct esd_usb *dev) break; } - buf = usb_alloc_coherent(dev->udev, RX_BUFFER_SIZE, GFP_KERNEL, + buf = usb_alloc_coherent(dev->udev, ESD_USB_RX_BUFFER_SIZE, GFP_KERNEL, &buf_dma); if (!buf) { dev_warn(dev->udev->dev.parent, @@ -588,7 +581,7 @@ static int esd_usb_setup_rx_urbs(struct esd_usb *dev) usb_fill_bulk_urb(urb, dev->udev, usb_rcvbulkpipe(dev->udev, 1), - buf, RX_BUFFER_SIZE, + buf, ESD_USB_RX_BUFFER_SIZE, esd_usb_read_bulk_callback, dev); urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; usb_anchor_urb(urb, &dev->rx_submitted); @@ -596,7 +589,7 @@ static int esd_usb_setup_rx_urbs(struct esd_usb *dev) err = usb_submit_urb(urb, GFP_KERNEL); if (err) { usb_unanchor_urb(urb); - usb_free_coherent(dev->udev, RX_BUFFER_SIZE, buf, + usb_free_coherent(dev->udev, ESD_USB_RX_BUFFER_SIZE, buf, urb->transfer_dma); goto freeurb; } @@ -618,7 +611,7 @@ static int esd_usb_setup_rx_urbs(struct esd_usb *dev) } /* Warn if we've couldn't transmit all the URBs */ - if (i < MAX_RX_URBS) { + if (i < ESD_USB_MAX_RX_URBS) { dev_warn(dev->udev->dev.parent, "rx performance may be slow\n"); } @@ -653,14 +646,14 @@ static int esd_usb_start(struct esd_usb_net_priv *priv) * the number of the starting bitmask (0..64) to the filter.option * field followed by only some bitmasks. */ - msg->hdr.cmd = CMD_IDADD; - msg->hdr.len = 2 + ESD_MAX_ID_SEGMENT; + msg->hdr.cmd = ESD_USB_CMD_IDADD; + msg->hdr.len = sizeof(struct esd_usb_id_filter_msg) / sizeof(u32); /* # of 32bit words */ msg->filter.net = priv->index; - msg->filter.option = ESD_ID_ENABLE; /* start with segment 0 */ - for (i = 0; i < ESD_MAX_ID_SEGMENT; i++) - msg->filter.mask[i] = cpu_to_le32(0xffffffff); + msg->filter.option = ESD_USB_ID_ENABLE; /* start with segment 0 */ + for (i = 0; i < ESD_USB_MAX_ID_SEGMENT; i++) + msg->filter.mask[i] = cpu_to_le32(GENMASK(31, 0)); /* enable 29bit extended IDs */ - msg->filter.mask[ESD_MAX_ID_SEGMENT] = cpu_to_le32(0x00000001); + msg->filter.mask[ESD_USB_MAX_ID_SEGMENT] = cpu_to_le32(BIT(0)); err = esd_usb_send_msg(dev, msg); if (err) @@ -689,8 +682,8 @@ static void unlink_all_urbs(struct esd_usb *dev) usb_kill_anchored_urbs(&dev->rx_submitted); - for (i = 0; i < MAX_RX_URBS; ++i) - usb_free_coherent(dev->udev, RX_BUFFER_SIZE, + for (i = 0; i < ESD_USB_MAX_RX_URBS; ++i) + usb_free_coherent(dev->udev, ESD_USB_RX_BUFFER_SIZE, dev->rxbuf[i], dev->rxbuf_dma[i]); for (i = 0; i < dev->net_count; i++) { @@ -699,8 +692,8 @@ static void unlink_all_urbs(struct esd_usb *dev) usb_kill_anchored_urbs(&priv->tx_submitted); atomic_set(&priv->active_tx_jobs, 0); - for (j = 0; j < MAX_TX_URBS; j++) - priv->tx_contexts[j].echo_index = MAX_TX_URBS; + for (j = 0; j < ESD_USB_MAX_TX_URBS; j++) + priv->tx_contexts[j].echo_index = ESD_USB_MAX_TX_URBS; } } } @@ -765,25 +758,27 @@ static netdev_tx_t esd_usb_start_xmit(struct sk_buff *skb, msg = (union esd_usb_msg *)buf; - msg->hdr.len = 3; /* minimal length */ - msg->hdr.cmd = CMD_CAN_TX; + /* minimal length as # of 32bit words */ + msg->hdr.len = offsetof(struct esd_usb_tx_msg, data) / sizeof(u32); + msg->hdr.cmd = ESD_USB_CMD_CAN_TX; msg->tx.net = priv->index; msg->tx.dlc = can_get_cc_dlc(cf, priv->can.ctrlmode); msg->tx.id = cpu_to_le32(cf->can_id & CAN_ERR_MASK); if (cf->can_id & CAN_RTR_FLAG) - msg->tx.dlc |= ESD_RTR; + msg->tx.dlc |= ESD_USB_RTR; if (cf->can_id & CAN_EFF_FLAG) - msg->tx.id |= cpu_to_le32(ESD_EXTID); + msg->tx.id |= cpu_to_le32(ESD_USB_EXTID); for (i = 0; i < cf->len; i++) msg->tx.data[i] = cf->data[i]; - msg->hdr.len += (cf->len + 3) >> 2; + /* round up, then divide by 4 to add the payload length as # of 32bit words */ + msg->hdr.len += DIV_ROUND_UP(cf->len, sizeof(u32)); - for (i = 0; i < MAX_TX_URBS; i++) { - if (priv->tx_contexts[i].echo_index == MAX_TX_URBS) { + for (i = 0; i < ESD_USB_MAX_TX_URBS; i++) { + if (priv->tx_contexts[i].echo_index == ESD_USB_MAX_TX_URBS) { context = &priv->tx_contexts[i]; break; } @@ -800,10 +795,10 @@ static netdev_tx_t esd_usb_start_xmit(struct sk_buff *skb, context->echo_index = i; /* hnd must not be 0 - MSB is stripped in txdone handling */ - msg->tx.hnd = 0x80000000 | i; /* returned in TX done message */ + msg->tx.hnd = BIT(31) | i; /* returned in TX done message */ usb_fill_bulk_urb(urb, dev->udev, usb_sndbulkpipe(dev->udev, 2), buf, - msg->hdr.len << 2, + msg->hdr.len * sizeof(u32), /* convert to # of bytes */ esd_usb_write_bulk_callback, context); urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; @@ -815,7 +810,7 @@ static netdev_tx_t esd_usb_start_xmit(struct sk_buff *skb, atomic_inc(&priv->active_tx_jobs); /* Slow down tx path */ - if (atomic_read(&priv->active_tx_jobs) >= MAX_TX_URBS) + if (atomic_read(&priv->active_tx_jobs) >= ESD_USB_MAX_TX_URBS) netif_stop_queue(netdev); err = usb_submit_urb(urb, GFP_ATOMIC); @@ -865,18 +860,18 @@ static int esd_usb_close(struct net_device *netdev) return -ENOMEM; /* Disable all IDs (see esd_usb_start()) */ - msg->hdr.cmd = CMD_IDADD; - msg->hdr.len = 2 + ESD_MAX_ID_SEGMENT; + msg->hdr.cmd = ESD_USB_CMD_IDADD; + msg->hdr.len = sizeof(struct esd_usb_id_filter_msg) / sizeof(u32);/* # of 32bit words */ msg->filter.net = priv->index; - msg->filter.option = ESD_ID_ENABLE; /* start with segment 0 */ - for (i = 0; i <= ESD_MAX_ID_SEGMENT; i++) + msg->filter.option = ESD_USB_ID_ENABLE; /* start with segment 0 */ + for (i = 0; i <= ESD_USB_MAX_ID_SEGMENT; i++) msg->filter.mask[i] = 0; if (esd_usb_send_msg(priv->usb, msg) < 0) netdev_err(netdev, "sending idadd message failed\n"); /* set CAN controller to reset mode */ - msg->hdr.len = 2; - msg->hdr.cmd = CMD_SETBAUD; + msg->hdr.len = sizeof(struct esd_usb_set_baudrate_msg) / sizeof(u32); /* # of 32bit words */ + msg->hdr.cmd = ESD_USB_CMD_SETBAUD; msg->setbaud.net = priv->index; msg->setbaud.rsvd = 0; msg->setbaud.baud = cpu_to_le32(ESD_USB_NO_BAUDRATE); @@ -905,20 +900,21 @@ static const struct ethtool_ops esd_usb_ethtool_ops = { .get_ts_info = ethtool_op_get_ts_info, }; -static const struct can_bittiming_const esd_usb2_bittiming_const = { - .name = "esd_usb2", - .tseg1_min = ESD_USB2_TSEG1_MIN, - .tseg1_max = ESD_USB2_TSEG1_MAX, - .tseg2_min = ESD_USB2_TSEG2_MIN, - .tseg2_max = ESD_USB2_TSEG2_MAX, - .sjw_max = ESD_USB2_SJW_MAX, - .brp_min = ESD_USB2_BRP_MIN, - .brp_max = ESD_USB2_BRP_MAX, - .brp_inc = ESD_USB2_BRP_INC, +static const struct can_bittiming_const esd_usb_2_bittiming_const = { + .name = "esd_usb_2", + .tseg1_min = 1, + .tseg1_max = 16, + .tseg2_min = 1, + .tseg2_max = 8, + .sjw_max = 4, + .brp_min = 1, + .brp_max = 1024, + .brp_inc = 1, }; -static int esd_usb2_set_bittiming(struct net_device *netdev) +static int esd_usb_2_set_bittiming(struct net_device *netdev) { + const struct can_bittiming_const *btc = &esd_usb_2_bittiming_const; struct esd_usb_net_priv *priv = netdev_priv(netdev); struct can_bittiming *bt = &priv->can.bittiming; union esd_usb_msg *msg; @@ -930,35 +926,35 @@ static int esd_usb2_set_bittiming(struct net_device *netdev) if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) canbtr |= ESD_USB_LOM; - canbtr |= (bt->brp - 1) & (ESD_USB2_BRP_MAX - 1); + canbtr |= (bt->brp - 1) & (btc->brp_max - 1); if (le16_to_cpu(priv->usb->udev->descriptor.idProduct) == - USB_CANUSBM_PRODUCT_ID) - sjw_shift = ESD_USBM_SJW_SHIFT; + ESD_USB_CANUSBM_PRODUCT_ID) + sjw_shift = ESD_USB_M_SJW_SHIFT; else - sjw_shift = ESD_USB2_SJW_SHIFT; + sjw_shift = ESD_USB_2_SJW_SHIFT; - canbtr |= ((bt->sjw - 1) & (ESD_USB2_SJW_MAX - 1)) + canbtr |= ((bt->sjw - 1) & (btc->sjw_max - 1)) << sjw_shift; canbtr |= ((bt->prop_seg + bt->phase_seg1 - 1) - & (ESD_USB2_TSEG1_MAX - 1)) - << ESD_USB2_TSEG1_SHIFT; - canbtr |= ((bt->phase_seg2 - 1) & (ESD_USB2_TSEG2_MAX - 1)) - << ESD_USB2_TSEG2_SHIFT; + & (btc->tseg1_max - 1)) + << ESD_USB_2_TSEG1_SHIFT; + canbtr |= ((bt->phase_seg2 - 1) & (btc->tseg2_max - 1)) + << ESD_USB_2_TSEG2_SHIFT; if (priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES) - canbtr |= ESD_USB2_3_SAMPLES; + canbtr |= ESD_USB_TRIPLE_SAMPLES; msg = kmalloc(sizeof(*msg), GFP_KERNEL); if (!msg) return -ENOMEM; - msg->hdr.len = 2; - msg->hdr.cmd = CMD_SETBAUD; + msg->hdr.len = sizeof(struct esd_usb_set_baudrate_msg) / sizeof(u32); /* # of 32bit words */ + msg->hdr.cmd = ESD_USB_CMD_SETBAUD; msg->setbaud.net = priv->index; msg->setbaud.rsvd = 0; msg->setbaud.baud = cpu_to_le32(canbtr); - netdev_info(netdev, "setting BTR=%#x\n", canbtr); + netdev_dbg(netdev, "setting BTR=%#x\n", canbtr); err = esd_usb_send_msg(priv->usb, msg); @@ -999,7 +995,7 @@ static int esd_usb_probe_one_net(struct usb_interface *intf, int index) int err = 0; int i; - netdev = alloc_candev(sizeof(*priv), MAX_TX_URBS); + netdev = alloc_candev(sizeof(*priv), ESD_USB_MAX_TX_URBS); if (!netdev) { dev_err(&intf->dev, "couldn't alloc candev\n"); err = -ENOMEM; @@ -1011,8 +1007,8 @@ static int esd_usb_probe_one_net(struct usb_interface *intf, int index) init_usb_anchor(&priv->tx_submitted); atomic_set(&priv->active_tx_jobs, 0); - for (i = 0; i < MAX_TX_URBS; i++) - priv->tx_contexts[i].echo_index = MAX_TX_URBS; + for (i = 0; i < ESD_USB_MAX_TX_URBS; i++) + priv->tx_contexts[i].echo_index = ESD_USB_MAX_TX_URBS; priv->usb = dev; priv->netdev = netdev; @@ -1024,15 +1020,15 @@ static int esd_usb_probe_one_net(struct usb_interface *intf, int index) CAN_CTRLMODE_BERR_REPORTING; if (le16_to_cpu(dev->udev->descriptor.idProduct) == - USB_CANUSBM_PRODUCT_ID) - priv->can.clock.freq = ESD_USBM_CAN_CLOCK; + ESD_USB_CANUSBM_PRODUCT_ID) + priv->can.clock.freq = ESD_USB_M_CAN_CLOCK; else { - priv->can.clock.freq = ESD_USB2_CAN_CLOCK; + priv->can.clock.freq = ESD_USB_2_CAN_CLOCK; priv->can.ctrlmode_supported |= CAN_CTRLMODE_3_SAMPLES; } - priv->can.bittiming_const = &esd_usb2_bittiming_const; - priv->can.do_set_bittiming = esd_usb2_set_bittiming; + priv->can.bittiming_const = &esd_usb_2_bittiming_const; + priv->can.do_set_bittiming = esd_usb_2_set_bittiming; priv->can.do_set_mode = esd_usb_set_mode; priv->can.do_get_berr_counter = esd_usb_get_berr_counter; @@ -1090,8 +1086,8 @@ static int esd_usb_probe(struct usb_interface *intf, } /* query number of CAN interfaces (nets) */ - msg->hdr.cmd = CMD_VERSION; - msg->hdr.len = 2; + msg->hdr.cmd = ESD_USB_CMD_VERSION; + msg->hdr.len = sizeof(struct esd_usb_version_msg) / sizeof(u32); /* # of 32bit words */ msg->version.rsvd = 0; msg->version.flags = 0; msg->version.drv_version = 0; diff --git a/drivers/net/can/usb/f81604.c b/drivers/net/can/usb/f81604.c new file mode 100644 index 0000000000000000000000000000000000000000..ec8cef7fd2d535b39fe914ecd0ca161cf96ba573 --- /dev/null +++ b/drivers/net/can/usb/f81604.c @@ -0,0 +1,1201 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Fintek F81604 USB-to-2CAN controller driver. + * + * Copyright (C) 2023 Ji-Ze Hong (Peter Hong) + */ +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +/* vendor and product id */ +#define F81604_VENDOR_ID 0x2c42 +#define F81604_PRODUCT_ID 0x1709 +#define F81604_CAN_CLOCK (12 * MEGA) +#define F81604_MAX_DEV 2 +#define F81604_SET_DEVICE_RETRY 10 + +#define F81604_USB_TIMEOUT 2000 +#define F81604_SET_GET_REGISTER 0xA0 +#define F81604_PORT_OFFSET 0x1000 +#define F81604_MAX_RX_URBS 4 + +#define F81604_CMD_DATA 0x00 + +#define F81604_DLC_LEN_MASK GENMASK(3, 0) +#define F81604_DLC_EFF_BIT BIT(7) +#define F81604_DLC_RTR_BIT BIT(6) + +#define F81604_SFF_SHIFT 5 +#define F81604_EFF_SHIFT 3 + +#define F81604_BRP_MASK GENMASK(5, 0) +#define F81604_SJW_MASK GENMASK(7, 6) + +#define F81604_SEG1_MASK GENMASK(3, 0) +#define F81604_SEG2_MASK GENMASK(6, 4) + +#define F81604_CLEAR_ALC 0 +#define F81604_CLEAR_ECC 1 +#define F81604_CLEAR_OVERRUN 2 + +/* device setting */ +#define F81604_CTRL_MODE_REG 0x80 +#define F81604_TX_ONESHOT (0x03 << 3) +#define F81604_TX_NORMAL (0x01 << 3) +#define F81604_RX_AUTO_RELEASE_BUF BIT(1) +#define F81604_INT_WHEN_CHANGE BIT(0) + +#define F81604_TERMINATOR_REG 0x105 +#define F81604_CAN0_TERM BIT(2) +#define F81604_CAN1_TERM BIT(3) + +#define F81604_TERMINATION_DISABLED CAN_TERMINATION_DISABLED +#define F81604_TERMINATION_ENABLED 120 + +/* SJA1000 registers - manual section 6.4 (Pelican Mode) */ +#define F81604_SJA1000_MOD 0x00 +#define F81604_SJA1000_CMR 0x01 +#define F81604_SJA1000_IR 0x03 +#define F81604_SJA1000_IER 0x04 +#define F81604_SJA1000_ALC 0x0B +#define F81604_SJA1000_ECC 0x0C +#define F81604_SJA1000_RXERR 0x0E +#define F81604_SJA1000_TXERR 0x0F +#define F81604_SJA1000_ACCC0 0x10 +#define F81604_SJA1000_ACCM0 0x14 +#define F81604_MAX_FILTER_CNT 4 + +/* Common registers - manual section 6.5 */ +#define F81604_SJA1000_BTR0 0x06 +#define F81604_SJA1000_BTR1 0x07 +#define F81604_SJA1000_BTR1_SAMPLE_TRIPLE BIT(7) +#define F81604_SJA1000_OCR 0x08 +#define F81604_SJA1000_CDR 0x1F + +/* mode register */ +#define F81604_SJA1000_MOD_RM 0x01 +#define F81604_SJA1000_MOD_LOM 0x02 +#define F81604_SJA1000_MOD_STM 0x04 + +/* commands */ +#define F81604_SJA1000_CMD_CDO 0x08 + +/* interrupt sources */ +#define F81604_SJA1000_IRQ_BEI 0x80 +#define F81604_SJA1000_IRQ_ALI 0x40 +#define F81604_SJA1000_IRQ_EPI 0x20 +#define F81604_SJA1000_IRQ_DOI 0x08 +#define F81604_SJA1000_IRQ_EI 0x04 +#define F81604_SJA1000_IRQ_TI 0x02 +#define F81604_SJA1000_IRQ_RI 0x01 +#define F81604_SJA1000_IRQ_ALL 0xFF +#define F81604_SJA1000_IRQ_OFF 0x00 + +/* status register content */ +#define F81604_SJA1000_SR_BS 0x80 +#define F81604_SJA1000_SR_ES 0x40 +#define F81604_SJA1000_SR_TCS 0x08 + +/* ECC register */ +#define F81604_SJA1000_ECC_SEG 0x1F +#define F81604_SJA1000_ECC_DIR 0x20 +#define F81604_SJA1000_ECC_BIT 0x00 +#define F81604_SJA1000_ECC_FORM 0x40 +#define F81604_SJA1000_ECC_STUFF 0x80 +#define F81604_SJA1000_ECC_MASK 0xc0 + +/* ALC register */ +#define F81604_SJA1000_ALC_MASK 0x1f + +/* table of devices that work with this driver */ +static const struct usb_device_id f81604_table[] = { + { USB_DEVICE(F81604_VENDOR_ID, F81604_PRODUCT_ID) }, + {} /* Terminating entry */ +}; + +MODULE_DEVICE_TABLE(usb, f81604_table); + +static const struct ethtool_ops f81604_ethtool_ops = { + .get_ts_info = ethtool_op_get_ts_info, +}; + +static const u16 f81604_termination[] = { F81604_TERMINATION_DISABLED, + F81604_TERMINATION_ENABLED }; + +struct f81604_priv { + struct net_device *netdev[F81604_MAX_DEV]; +}; + +struct f81604_port_priv { + struct can_priv can; + struct net_device *netdev; + struct sk_buff *echo_skb; + + unsigned long clear_flags; + struct work_struct clear_reg_work; + + struct usb_device *dev; + struct usb_interface *intf; + + struct usb_anchor urbs_anchor; +}; + +/* Interrupt endpoint data format: + * Byte 0: Status register. + * Byte 1: Interrupt register. + * Byte 2: Interrupt enable register. + * Byte 3: Arbitration lost capture(ALC) register. + * Byte 4: Error code capture(ECC) register. + * Byte 5: Error warning limit register. + * Byte 6: RX error counter register. + * Byte 7: TX error counter register. + * Byte 8: Reserved. + */ +struct f81604_int_data { + u8 sr; + u8 isrc; + u8 ier; + u8 alc; + u8 ecc; + u8 ewlr; + u8 rxerr; + u8 txerr; + u8 val; +} __packed __aligned(4); + +struct f81604_sff { + __be16 id; + u8 data[CAN_MAX_DLEN]; +} __packed __aligned(2); + +struct f81604_eff { + __be32 id; + u8 data[CAN_MAX_DLEN]; +} __packed __aligned(2); + +struct f81604_can_frame { + u8 cmd; + + /* According for F81604 DLC define: + * bit 3~0: data length (0~8) + * bit6: is RTR flag. + * bit7: is EFF frame. + */ + u8 dlc; + + union { + struct f81604_sff sff; + struct f81604_eff eff; + }; +} __packed __aligned(2); + +static const u8 bulk_in_addr[F81604_MAX_DEV] = { 2, 4 }; +static const u8 bulk_out_addr[F81604_MAX_DEV] = { 1, 3 }; +static const u8 int_in_addr[F81604_MAX_DEV] = { 1, 3 }; + +static int f81604_write(struct usb_device *dev, u16 reg, u8 data) +{ + int ret; + + ret = usb_control_msg_send(dev, 0, F81604_SET_GET_REGISTER, + USB_TYPE_VENDOR | USB_DIR_OUT, 0, reg, + &data, sizeof(data), F81604_USB_TIMEOUT, + GFP_KERNEL); + if (ret) + dev_err(&dev->dev, "%s: reg: %x data: %x failed: %pe\n", + __func__, reg, data, ERR_PTR(ret)); + + return ret; +} + +static int f81604_read(struct usb_device *dev, u16 reg, u8 *data) +{ + int ret; + + ret = usb_control_msg_recv(dev, 0, F81604_SET_GET_REGISTER, + USB_TYPE_VENDOR | USB_DIR_IN, 0, reg, data, + sizeof(*data), F81604_USB_TIMEOUT, + GFP_KERNEL); + + if (ret < 0) + dev_err(&dev->dev, "%s: reg: %x failed: %pe\n", __func__, reg, + ERR_PTR(ret)); + + return ret; +} + +static int f81604_update_bits(struct usb_device *dev, u16 reg, u8 mask, + u8 data) +{ + int ret; + u8 tmp; + + ret = f81604_read(dev, reg, &tmp); + if (ret) + return ret; + + tmp &= ~mask; + tmp |= (mask & data); + + return f81604_write(dev, reg, tmp); +} + +static int f81604_sja1000_write(struct f81604_port_priv *priv, u16 reg, + u8 data) +{ + int port = priv->netdev->dev_port; + int real_reg; + + real_reg = reg + F81604_PORT_OFFSET * port + F81604_PORT_OFFSET; + return f81604_write(priv->dev, real_reg, data); +} + +static int f81604_sja1000_read(struct f81604_port_priv *priv, u16 reg, + u8 *data) +{ + int port = priv->netdev->dev_port; + int real_reg; + + real_reg = reg + F81604_PORT_OFFSET * port + F81604_PORT_OFFSET; + return f81604_read(priv->dev, real_reg, data); +} + +static int f81604_set_reset_mode(struct f81604_port_priv *priv) +{ + int ret, i; + u8 tmp; + + /* disable interrupts */ + ret = f81604_sja1000_write(priv, F81604_SJA1000_IER, + F81604_SJA1000_IRQ_OFF); + if (ret) + return ret; + + for (i = 0; i < F81604_SET_DEVICE_RETRY; i++) { + ret = f81604_sja1000_read(priv, F81604_SJA1000_MOD, &tmp); + if (ret) + return ret; + + /* check reset bit */ + if (tmp & F81604_SJA1000_MOD_RM) { + priv->can.state = CAN_STATE_STOPPED; + return 0; + } + + /* reset chip */ + ret = f81604_sja1000_write(priv, F81604_SJA1000_MOD, + F81604_SJA1000_MOD_RM); + if (ret) + return ret; + } + + return -EPERM; +} + +static int f81604_set_normal_mode(struct f81604_port_priv *priv) +{ + u8 tmp, ier = 0; + u8 mod_reg = 0; + int ret, i; + + for (i = 0; i < F81604_SET_DEVICE_RETRY; i++) { + ret = f81604_sja1000_read(priv, F81604_SJA1000_MOD, &tmp); + if (ret) + return ret; + + /* check reset bit */ + if ((tmp & F81604_SJA1000_MOD_RM) == 0) { + priv->can.state = CAN_STATE_ERROR_ACTIVE; + /* enable interrupts, RI handled by bulk-in */ + ier = F81604_SJA1000_IRQ_ALL & ~F81604_SJA1000_IRQ_RI; + if (!(priv->can.ctrlmode & + CAN_CTRLMODE_BERR_REPORTING)) + ier &= ~F81604_SJA1000_IRQ_BEI; + + return f81604_sja1000_write(priv, F81604_SJA1000_IER, + ier); + } + + /* set chip to normal mode */ + if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) + mod_reg |= F81604_SJA1000_MOD_LOM; + if (priv->can.ctrlmode & CAN_CTRLMODE_PRESUME_ACK) + mod_reg |= F81604_SJA1000_MOD_STM; + + ret = f81604_sja1000_write(priv, F81604_SJA1000_MOD, mod_reg); + if (ret) + return ret; + } + + return -EPERM; +} + +static int f81604_chipset_init(struct f81604_port_priv *priv) +{ + int i, ret; + + /* set clock divider and output control register */ + ret = f81604_sja1000_write(priv, F81604_SJA1000_CDR, + CDR_CBP | CDR_PELICAN); + if (ret) + return ret; + + /* set acceptance filter (accept all) */ + for (i = 0; i < F81604_MAX_FILTER_CNT; ++i) { + ret = f81604_sja1000_write(priv, F81604_SJA1000_ACCC0 + i, 0); + if (ret) + return ret; + } + + for (i = 0; i < F81604_MAX_FILTER_CNT; ++i) { + ret = f81604_sja1000_write(priv, F81604_SJA1000_ACCM0 + i, + 0xFF); + if (ret) + return ret; + } + + return f81604_sja1000_write(priv, F81604_SJA1000_OCR, + OCR_TX0_PUSHPULL | OCR_TX1_PUSHPULL | + OCR_MODE_NORMAL); +} + +static void f81604_process_rx_packet(struct net_device *netdev, + struct f81604_can_frame *frame) +{ + struct net_device_stats *stats = &netdev->stats; + struct can_frame *cf; + struct sk_buff *skb; + + if (frame->cmd != F81604_CMD_DATA) + return; + + skb = alloc_can_skb(netdev, &cf); + if (!skb) { + stats->rx_dropped++; + return; + } + + cf->len = can_cc_dlc2len(frame->dlc & F81604_DLC_LEN_MASK); + + if (frame->dlc & F81604_DLC_EFF_BIT) { + cf->can_id = get_unaligned_be32(&frame->eff.id) >> + F81604_EFF_SHIFT; + cf->can_id |= CAN_EFF_FLAG; + + if (!(frame->dlc & F81604_DLC_RTR_BIT)) + memcpy(cf->data, frame->eff.data, cf->len); + } else { + cf->can_id = get_unaligned_be16(&frame->sff.id) >> + F81604_SFF_SHIFT; + + if (!(frame->dlc & F81604_DLC_RTR_BIT)) + memcpy(cf->data, frame->sff.data, cf->len); + } + + if (frame->dlc & F81604_DLC_RTR_BIT) + cf->can_id |= CAN_RTR_FLAG; + else + stats->rx_bytes += cf->len; + + stats->rx_packets++; + netif_rx(skb); +} + +static void f81604_read_bulk_callback(struct urb *urb) +{ + struct f81604_can_frame *frame = urb->transfer_buffer; + struct net_device *netdev = urb->context; + int ret; + + if (!netif_device_present(netdev)) + return; + + if (urb->status) + netdev_info(netdev, "%s: URB aborted %pe\n", __func__, + ERR_PTR(urb->status)); + + switch (urb->status) { + case 0: /* success */ + break; + + case -ENOENT: + case -EPIPE: + case -EPROTO: + case -ESHUTDOWN: + return; + + default: + goto resubmit_urb; + } + + if (urb->actual_length != sizeof(*frame)) { + netdev_warn(netdev, "URB length %u not equal to %zu\n", + urb->actual_length, sizeof(*frame)); + goto resubmit_urb; + } + + f81604_process_rx_packet(netdev, frame); + +resubmit_urb: + ret = usb_submit_urb(urb, GFP_ATOMIC); + if (ret == -ENODEV) + netif_device_detach(netdev); + else if (ret) + netdev_err(netdev, + "%s: failed to resubmit read bulk urb: %pe\n", + __func__, ERR_PTR(ret)); +} + +static void f81604_handle_tx(struct f81604_port_priv *priv, + struct f81604_int_data *data) +{ + struct net_device *netdev = priv->netdev; + struct net_device_stats *stats = &netdev->stats; + + /* transmission buffer released */ + if (priv->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT && + !(data->sr & F81604_SJA1000_SR_TCS)) { + stats->tx_errors++; + can_free_echo_skb(netdev, 0, NULL); + } else { + /* transmission complete */ + stats->tx_bytes += can_get_echo_skb(netdev, 0, NULL); + stats->tx_packets++; + } + + netif_wake_queue(netdev); +} + +static void f81604_handle_can_bus_errors(struct f81604_port_priv *priv, + struct f81604_int_data *data) +{ + enum can_state can_state = priv->can.state; + struct net_device *netdev = priv->netdev; + struct net_device_stats *stats = &netdev->stats; + struct can_frame *cf; + struct sk_buff *skb; + + /* Note: ALC/ECC will not auto clear by read here, must be cleared by + * read register (via clear_reg_work). + */ + + skb = alloc_can_err_skb(netdev, &cf); + if (skb) { + cf->can_id |= CAN_ERR_CNT; + cf->data[6] = data->txerr; + cf->data[7] = data->rxerr; + } + + if (data->isrc & F81604_SJA1000_IRQ_DOI) { + /* data overrun interrupt */ + netdev_dbg(netdev, "data overrun interrupt\n"); + + if (skb) { + cf->can_id |= CAN_ERR_CRTL; + cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW; + } + + stats->rx_over_errors++; + stats->rx_errors++; + + set_bit(F81604_CLEAR_OVERRUN, &priv->clear_flags); + } + + if (data->isrc & F81604_SJA1000_IRQ_EI) { + /* error warning interrupt */ + netdev_dbg(netdev, "error warning interrupt\n"); + + if (data->sr & F81604_SJA1000_SR_BS) + can_state = CAN_STATE_BUS_OFF; + else if (data->sr & F81604_SJA1000_SR_ES) + can_state = CAN_STATE_ERROR_WARNING; + else + can_state = CAN_STATE_ERROR_ACTIVE; + } + + if (data->isrc & F81604_SJA1000_IRQ_BEI) { + /* bus error interrupt */ + netdev_dbg(netdev, "bus error interrupt\n"); + + priv->can.can_stats.bus_error++; + stats->rx_errors++; + + if (skb) { + cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR; + + /* set error type */ + switch (data->ecc & F81604_SJA1000_ECC_MASK) { + case F81604_SJA1000_ECC_BIT: + cf->data[2] |= CAN_ERR_PROT_BIT; + break; + case F81604_SJA1000_ECC_FORM: + cf->data[2] |= CAN_ERR_PROT_FORM; + break; + case F81604_SJA1000_ECC_STUFF: + cf->data[2] |= CAN_ERR_PROT_STUFF; + break; + default: + break; + } + + /* set error location */ + cf->data[3] = data->ecc & F81604_SJA1000_ECC_SEG; + + /* Error occurred during transmission? */ + if ((data->ecc & F81604_SJA1000_ECC_DIR) == 0) + cf->data[2] |= CAN_ERR_PROT_TX; + } + + set_bit(F81604_CLEAR_ECC, &priv->clear_flags); + } + + if (data->isrc & F81604_SJA1000_IRQ_EPI) { + if (can_state == CAN_STATE_ERROR_PASSIVE) + can_state = CAN_STATE_ERROR_WARNING; + else + can_state = CAN_STATE_ERROR_PASSIVE; + + /* error passive interrupt */ + netdev_dbg(netdev, "error passive interrupt: %d\n", can_state); + } + + if (data->isrc & F81604_SJA1000_IRQ_ALI) { + /* arbitration lost interrupt */ + netdev_dbg(netdev, "arbitration lost interrupt\n"); + + priv->can.can_stats.arbitration_lost++; + + if (skb) { + cf->can_id |= CAN_ERR_LOSTARB; + cf->data[0] = data->alc & F81604_SJA1000_ALC_MASK; + } + + set_bit(F81604_CLEAR_ALC, &priv->clear_flags); + } + + if (can_state != priv->can.state) { + enum can_state tx_state, rx_state; + + tx_state = data->txerr >= data->rxerr ? can_state : 0; + rx_state = data->txerr <= data->rxerr ? can_state : 0; + + can_change_state(netdev, cf, tx_state, rx_state); + + if (can_state == CAN_STATE_BUS_OFF) + can_bus_off(netdev); + } + + if (priv->clear_flags) + schedule_work(&priv->clear_reg_work); + + if (skb) + netif_rx(skb); +} + +static void f81604_read_int_callback(struct urb *urb) +{ + struct f81604_int_data *data = urb->transfer_buffer; + struct net_device *netdev = urb->context; + struct f81604_port_priv *priv; + int ret; + + priv = netdev_priv(netdev); + + if (!netif_device_present(netdev)) + return; + + if (urb->status) + netdev_info(netdev, "%s: Int URB aborted: %pe\n", __func__, + ERR_PTR(urb->status)); + + switch (urb->status) { + case 0: /* success */ + break; + + case -ENOENT: + case -EPIPE: + case -EPROTO: + case -ESHUTDOWN: + return; + + default: + goto resubmit_urb; + } + + /* handle Errors */ + if (data->isrc & (F81604_SJA1000_IRQ_DOI | F81604_SJA1000_IRQ_EI | + F81604_SJA1000_IRQ_BEI | F81604_SJA1000_IRQ_EPI | + F81604_SJA1000_IRQ_ALI)) + f81604_handle_can_bus_errors(priv, data); + + /* handle TX */ + if (priv->can.state != CAN_STATE_BUS_OFF && + (data->isrc & F81604_SJA1000_IRQ_TI)) + f81604_handle_tx(priv, data); + +resubmit_urb: + ret = usb_submit_urb(urb, GFP_ATOMIC); + if (ret == -ENODEV) + netif_device_detach(netdev); + else if (ret) + netdev_err(netdev, "%s: failed to resubmit int urb: %pe\n", + __func__, ERR_PTR(ret)); +} + +static void f81604_unregister_urbs(struct f81604_port_priv *priv) +{ + usb_kill_anchored_urbs(&priv->urbs_anchor); +} + +static int f81604_register_urbs(struct f81604_port_priv *priv) +{ + struct net_device *netdev = priv->netdev; + struct f81604_int_data *int_data; + int id = netdev->dev_port; + struct urb *int_urb; + int rx_urb_cnt; + int ret; + + for (rx_urb_cnt = 0; rx_urb_cnt < F81604_MAX_RX_URBS; ++rx_urb_cnt) { + struct f81604_can_frame *frame; + struct urb *rx_urb; + + rx_urb = usb_alloc_urb(0, GFP_KERNEL); + if (!rx_urb) { + ret = -ENOMEM; + break; + } + + frame = kmalloc(sizeof(*frame), GFP_KERNEL); + if (!frame) { + usb_free_urb(rx_urb); + ret = -ENOMEM; + break; + } + + usb_fill_bulk_urb(rx_urb, priv->dev, + usb_rcvbulkpipe(priv->dev, bulk_in_addr[id]), + frame, sizeof(*frame), + f81604_read_bulk_callback, netdev); + + rx_urb->transfer_flags |= URB_FREE_BUFFER; + usb_anchor_urb(rx_urb, &priv->urbs_anchor); + + ret = usb_submit_urb(rx_urb, GFP_KERNEL); + if (ret) { + usb_unanchor_urb(rx_urb); + usb_free_urb(rx_urb); + break; + } + + /* Drop reference, USB core will take care of freeing it */ + usb_free_urb(rx_urb); + } + + if (rx_urb_cnt == 0) { + netdev_warn(netdev, "%s: submit rx urb failed: %pe\n", + __func__, ERR_PTR(ret)); + + goto error; + } + + int_urb = usb_alloc_urb(0, GFP_KERNEL); + if (!int_urb) { + ret = -ENOMEM; + goto error; + } + + int_data = kmalloc(sizeof(*int_data), GFP_KERNEL); + if (!int_data) { + usb_free_urb(int_urb); + ret = -ENOMEM; + goto error; + } + + usb_fill_int_urb(int_urb, priv->dev, + usb_rcvintpipe(priv->dev, int_in_addr[id]), int_data, + sizeof(*int_data), f81604_read_int_callback, netdev, + 1); + + int_urb->transfer_flags |= URB_FREE_BUFFER; + usb_anchor_urb(int_urb, &priv->urbs_anchor); + + ret = usb_submit_urb(int_urb, GFP_KERNEL); + if (ret) { + usb_unanchor_urb(int_urb); + usb_free_urb(int_urb); + + netdev_warn(netdev, "%s: submit int urb failed: %pe\n", + __func__, ERR_PTR(ret)); + goto error; + } + + /* Drop reference, USB core will take care of freeing it */ + usb_free_urb(int_urb); + + return 0; + +error: + f81604_unregister_urbs(priv); + return ret; +} + +static int f81604_start(struct net_device *netdev) +{ + struct f81604_port_priv *priv = netdev_priv(netdev); + int ret; + u8 mode; + u8 tmp; + + mode = F81604_RX_AUTO_RELEASE_BUF | F81604_INT_WHEN_CHANGE; + + /* Set TR/AT mode */ + if (priv->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT) + mode |= F81604_TX_ONESHOT; + else + mode |= F81604_TX_NORMAL; + + ret = f81604_sja1000_write(priv, F81604_CTRL_MODE_REG, mode); + if (ret) + return ret; + + /* set reset mode */ + ret = f81604_set_reset_mode(priv); + if (ret) + return ret; + + ret = f81604_chipset_init(priv); + if (ret) + return ret; + + /* Clear error counters and error code capture */ + ret = f81604_sja1000_write(priv, F81604_SJA1000_TXERR, 0); + if (ret) + return ret; + + ret = f81604_sja1000_write(priv, F81604_SJA1000_RXERR, 0); + if (ret) + return ret; + + /* Read clear for ECC/ALC/IR register */ + ret = f81604_sja1000_read(priv, F81604_SJA1000_ECC, &tmp); + if (ret) + return ret; + + ret = f81604_sja1000_read(priv, F81604_SJA1000_ALC, &tmp); + if (ret) + return ret; + + ret = f81604_sja1000_read(priv, F81604_SJA1000_IR, &tmp); + if (ret) + return ret; + + ret = f81604_register_urbs(priv); + if (ret) + return ret; + + ret = f81604_set_normal_mode(priv); + if (ret) { + f81604_unregister_urbs(priv); + return ret; + } + + return 0; +} + +static int f81604_set_bittiming(struct net_device *dev) +{ + struct f81604_port_priv *priv = netdev_priv(dev); + struct can_bittiming *bt = &priv->can.bittiming; + u8 btr0, btr1; + int ret; + + btr0 = FIELD_PREP(F81604_BRP_MASK, bt->brp - 1) | + FIELD_PREP(F81604_SJW_MASK, bt->sjw - 1); + + btr1 = FIELD_PREP(F81604_SEG1_MASK, + bt->prop_seg + bt->phase_seg1 - 1) | + FIELD_PREP(F81604_SEG2_MASK, bt->phase_seg2 - 1); + + if (priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES) + btr1 |= F81604_SJA1000_BTR1_SAMPLE_TRIPLE; + + ret = f81604_sja1000_write(priv, F81604_SJA1000_BTR0, btr0); + if (ret) { + netdev_warn(dev, "%s: Set BTR0 failed: %pe\n", __func__, + ERR_PTR(ret)); + return ret; + } + + ret = f81604_sja1000_write(priv, F81604_SJA1000_BTR1, btr1); + if (ret) { + netdev_warn(dev, "%s: Set BTR1 failed: %pe\n", __func__, + ERR_PTR(ret)); + return ret; + } + + return 0; +} + +static int f81604_set_mode(struct net_device *netdev, enum can_mode mode) +{ + int ret; + + switch (mode) { + case CAN_MODE_START: + ret = f81604_start(netdev); + if (!ret && netif_queue_stopped(netdev)) + netif_wake_queue(netdev); + break; + + default: + ret = -EOPNOTSUPP; + } + + return ret; +} + +static void f81604_write_bulk_callback(struct urb *urb) +{ + struct net_device *netdev = urb->context; + + if (!netif_device_present(netdev)) + return; + + if (urb->status) + netdev_info(netdev, "%s: Tx URB error: %pe\n", __func__, + ERR_PTR(urb->status)); +} + +static void f81604_clear_reg_work(struct work_struct *work) +{ + struct f81604_port_priv *priv; + u8 tmp; + + priv = container_of(work, struct f81604_port_priv, clear_reg_work); + + /* dummy read for clear Arbitration lost capture(ALC) register. */ + if (test_and_clear_bit(F81604_CLEAR_ALC, &priv->clear_flags)) + f81604_sja1000_read(priv, F81604_SJA1000_ALC, &tmp); + + /* dummy read for clear Error code capture(ECC) register. */ + if (test_and_clear_bit(F81604_CLEAR_ECC, &priv->clear_flags)) + f81604_sja1000_read(priv, F81604_SJA1000_ECC, &tmp); + + /* dummy write for clear data overrun flag. */ + if (test_and_clear_bit(F81604_CLEAR_OVERRUN, &priv->clear_flags)) + f81604_sja1000_write(priv, F81604_SJA1000_CMR, + F81604_SJA1000_CMD_CDO); +} + +static netdev_tx_t f81604_start_xmit(struct sk_buff *skb, + struct net_device *netdev) +{ + struct can_frame *cf = (struct can_frame *)skb->data; + struct f81604_port_priv *priv = netdev_priv(netdev); + struct net_device_stats *stats = &netdev->stats; + struct f81604_can_frame *frame; + struct urb *write_urb; + int ret; + + if (can_dev_dropped_skb(netdev, skb)) + return NETDEV_TX_OK; + + netif_stop_queue(netdev); + + write_urb = usb_alloc_urb(0, GFP_ATOMIC); + if (!write_urb) + goto nomem_urb; + + frame = kzalloc(sizeof(*frame), GFP_ATOMIC); + if (!frame) + goto nomem_buf; + + usb_fill_bulk_urb(write_urb, priv->dev, + usb_sndbulkpipe(priv->dev, + bulk_out_addr[netdev->dev_port]), + frame, sizeof(*frame), f81604_write_bulk_callback, + priv->netdev); + + write_urb->transfer_flags |= URB_FREE_BUFFER; + + frame->cmd = F81604_CMD_DATA; + frame->dlc = cf->len; + + if (cf->can_id & CAN_RTR_FLAG) + frame->dlc |= F81604_DLC_RTR_BIT; + + if (cf->can_id & CAN_EFF_FLAG) { + u32 id = (cf->can_id & CAN_EFF_MASK) << F81604_EFF_SHIFT; + + put_unaligned_be32(id, &frame->eff.id); + + frame->dlc |= F81604_DLC_EFF_BIT; + + if (!(cf->can_id & CAN_RTR_FLAG)) + memcpy(&frame->eff.data, cf->data, cf->len); + } else { + u32 id = (cf->can_id & CAN_SFF_MASK) << F81604_SFF_SHIFT; + + put_unaligned_be16(id, &frame->sff.id); + + if (!(cf->can_id & CAN_RTR_FLAG)) + memcpy(&frame->sff.data, cf->data, cf->len); + } + + can_put_echo_skb(skb, netdev, 0, 0); + + ret = usb_submit_urb(write_urb, GFP_ATOMIC); + if (ret) { + netdev_err(netdev, "%s: failed to resubmit tx bulk urb: %pe\n", + __func__, ERR_PTR(ret)); + + can_free_echo_skb(netdev, 0, NULL); + stats->tx_dropped++; + stats->tx_errors++; + + if (ret == -ENODEV) + netif_device_detach(netdev); + else + netif_wake_queue(netdev); + } + + /* let usb core take care of this urb */ + usb_free_urb(write_urb); + + return NETDEV_TX_OK; + +nomem_buf: + usb_free_urb(write_urb); + +nomem_urb: + dev_kfree_skb(skb); + stats->tx_dropped++; + stats->tx_errors++; + netif_wake_queue(netdev); + + return NETDEV_TX_OK; +} + +static int f81604_get_berr_counter(const struct net_device *netdev, + struct can_berr_counter *bec) +{ + struct f81604_port_priv *priv = netdev_priv(netdev); + u8 txerr, rxerr; + int ret; + + ret = f81604_sja1000_read(priv, F81604_SJA1000_TXERR, &txerr); + if (ret) + return ret; + + ret = f81604_sja1000_read(priv, F81604_SJA1000_RXERR, &rxerr); + if (ret) + return ret; + + bec->txerr = txerr; + bec->rxerr = rxerr; + + return 0; +} + +/* Open USB device */ +static int f81604_open(struct net_device *netdev) +{ + int ret; + + ret = open_candev(netdev); + if (ret) + return ret; + + ret = f81604_start(netdev); + if (ret) { + if (ret == -ENODEV) + netif_device_detach(netdev); + + close_candev(netdev); + return ret; + } + + netif_start_queue(netdev); + return 0; +} + +/* Close USB device */ +static int f81604_close(struct net_device *netdev) +{ + struct f81604_port_priv *priv = netdev_priv(netdev); + + f81604_set_reset_mode(priv); + + netif_stop_queue(netdev); + cancel_work_sync(&priv->clear_reg_work); + close_candev(netdev); + + f81604_unregister_urbs(priv); + + return 0; +} + +static const struct net_device_ops f81604_netdev_ops = { + .ndo_open = f81604_open, + .ndo_stop = f81604_close, + .ndo_start_xmit = f81604_start_xmit, + .ndo_change_mtu = can_change_mtu, +}; + +static const struct can_bittiming_const f81604_bittiming_const = { + .name = KBUILD_MODNAME, + .tseg1_min = 1, + .tseg1_max = 16, + .tseg2_min = 1, + .tseg2_max = 8, + .sjw_max = 4, + .brp_min = 1, + .brp_max = 64, + .brp_inc = 1, +}; + +/* Called by the usb core when driver is unloaded or device is removed */ +static void f81604_disconnect(struct usb_interface *intf) +{ + struct f81604_priv *priv = usb_get_intfdata(intf); + int i; + + for (i = 0; i < ARRAY_SIZE(priv->netdev); ++i) { + if (!priv->netdev[i]) + continue; + + unregister_netdev(priv->netdev[i]); + free_candev(priv->netdev[i]); + } +} + +static int __f81604_set_termination(struct usb_device *dev, int idx, u16 term) +{ + u8 mask, data = 0; + + if (idx == 0) + mask = F81604_CAN0_TERM; + else + mask = F81604_CAN1_TERM; + + if (term) + data = mask; + + return f81604_update_bits(dev, F81604_TERMINATOR_REG, mask, data); +} + +static int f81604_set_termination(struct net_device *netdev, u16 term) +{ + struct f81604_port_priv *port_priv = netdev_priv(netdev); + + ASSERT_RTNL(); + + return __f81604_set_termination(port_priv->dev, netdev->dev_port, + term); +} + +static int f81604_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + struct usb_device *dev = interface_to_usbdev(intf); + struct net_device *netdev; + struct f81604_priv *priv; + int i, ret; + + priv = devm_kzalloc(&intf->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + usb_set_intfdata(intf, priv); + + for (i = 0; i < ARRAY_SIZE(priv->netdev); ++i) { + ret = __f81604_set_termination(dev, i, 0); + if (ret) { + dev_err(&intf->dev, + "Setting termination of CH#%d failed: %pe\n", + i, ERR_PTR(ret)); + return ret; + } + } + + for (i = 0; i < ARRAY_SIZE(priv->netdev); ++i) { + struct f81604_port_priv *port_priv; + + netdev = alloc_candev(sizeof(*port_priv), 1); + if (!netdev) { + dev_err(&intf->dev, "Couldn't alloc candev: %d\n", i); + ret = -ENOMEM; + + goto failure_cleanup; + } + + port_priv = netdev_priv(netdev); + + INIT_WORK(&port_priv->clear_reg_work, f81604_clear_reg_work); + init_usb_anchor(&port_priv->urbs_anchor); + + port_priv->intf = intf; + port_priv->dev = dev; + port_priv->netdev = netdev; + port_priv->can.clock.freq = F81604_CAN_CLOCK; + + port_priv->can.termination_const = f81604_termination; + port_priv->can.termination_const_cnt = + ARRAY_SIZE(f81604_termination); + port_priv->can.bittiming_const = &f81604_bittiming_const; + port_priv->can.do_set_bittiming = f81604_set_bittiming; + port_priv->can.do_set_mode = f81604_set_mode; + port_priv->can.do_set_termination = f81604_set_termination; + port_priv->can.do_get_berr_counter = f81604_get_berr_counter; + port_priv->can.ctrlmode_supported = + CAN_CTRLMODE_LISTENONLY | CAN_CTRLMODE_3_SAMPLES | + CAN_CTRLMODE_ONE_SHOT | CAN_CTRLMODE_BERR_REPORTING | + CAN_CTRLMODE_PRESUME_ACK; + + netdev->ethtool_ops = &f81604_ethtool_ops; + netdev->netdev_ops = &f81604_netdev_ops; + netdev->flags |= IFF_ECHO; + netdev->dev_port = i; + + SET_NETDEV_DEV(netdev, &intf->dev); + + ret = register_candev(netdev); + if (ret) { + netdev_err(netdev, "register CAN device failed: %pe\n", + ERR_PTR(ret)); + free_candev(netdev); + + goto failure_cleanup; + } + + priv->netdev[i] = netdev; + } + + return 0; + +failure_cleanup: + f81604_disconnect(intf); + return ret; +} + +static struct usb_driver f81604_driver = { + .name = KBUILD_MODNAME, + .probe = f81604_probe, + .disconnect = f81604_disconnect, + .id_table = f81604_table, +}; + +module_usb_driver(f81604_driver); + +MODULE_AUTHOR("Ji-Ze Hong (Peter Hong) "); +MODULE_DESCRIPTION("Fintek F81604 USB to 2xCANBUS"); +MODULE_LICENSE("GPL"); diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c b/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c index 7135ec851341b088a09adafcbb684d9f3a1b53e9..71ef4db5c09f68897483df25f969db81c27e5159 100644 --- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c +++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c @@ -816,7 +816,7 @@ static int kvaser_usb_init_one(struct kvaser_usb *dev, int channel) init_completion(&priv->stop_comp); init_completion(&priv->flush_comp); init_completion(&priv->get_busparams_comp); - priv->can.ctrlmode_supported = 0; + priv->can.ctrlmode_supported = CAN_CTRLMODE_CC_LEN8_DLC; priv->dev = dev; priv->netdev = netdev; diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c b/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c index ef341c4254fc8b14dd3f81b0d1909100b3cde393..c7ba768dfe173d42981d77c7a17ba83557b31cbb 100644 --- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c +++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c @@ -1263,7 +1263,7 @@ static void kvaser_usb_hydra_rx_msg_std(const struct kvaser_usb *dev, if (flags & KVASER_USB_HYDRA_CF_FLAG_OVERRUN) kvaser_usb_can_rx_over_error(priv->netdev); - cf->len = can_cc_dlc2len(cmd->rx_can.dlc); + can_frame_set_cc_len((struct can_frame *)cf, cmd->rx_can.dlc, priv->can.ctrlmode); if (flags & KVASER_USB_HYDRA_CF_FLAG_REMOTE_FRAME) { cf->can_id |= CAN_RTR_FLAG; @@ -1342,7 +1342,7 @@ static void kvaser_usb_hydra_rx_msg_ext(const struct kvaser_usb *dev, if (flags & KVASER_USB_HYDRA_CF_FLAG_ESI) cf->flags |= CANFD_ESI; } else { - cf->len = can_cc_dlc2len(dlc); + can_frame_set_cc_len((struct can_frame *)cf, dlc, priv->can.ctrlmode); } if (flags & KVASER_USB_HYDRA_CF_FLAG_REMOTE_FRAME) { @@ -1442,7 +1442,7 @@ kvaser_usb_hydra_frame_to_cmd_ext(const struct kvaser_usb_net_priv *priv, struct kvaser_usb *dev = priv->dev; struct kvaser_cmd_ext *cmd; struct canfd_frame *cf = (struct canfd_frame *)skb->data; - u8 dlc = can_fd_len2dlc(cf->len); + u8 dlc; u8 nbr_of_bytes = cf->len; u32 flags; u32 id; @@ -1467,6 +1467,11 @@ kvaser_usb_hydra_frame_to_cmd_ext(const struct kvaser_usb_net_priv *priv, cmd->len = cpu_to_le16(*cmd_len); + if (can_is_canfd_skb(skb)) + dlc = can_fd_len2dlc(cf->len); + else + dlc = can_get_cc_dlc((struct can_frame *)cf, priv->can.ctrlmode); + cmd->tx_can.databytes = nbr_of_bytes; cmd->tx_can.dlc = dlc; @@ -1542,7 +1547,7 @@ kvaser_usb_hydra_frame_to_cmd_std(const struct kvaser_usb_net_priv *priv, id = cf->can_id & CAN_SFF_MASK; } - cmd->tx_can.dlc = cf->len; + cmd->tx_can.dlc = can_get_cc_dlc(cf, priv->can.ctrlmode); flags = (cf->can_id & CAN_EFF_FLAG ? KVASER_USB_HYDRA_CF_FLAG_EXTENDED_ID : 0); diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c b/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c index 1c2f99ce4c6c72832ec5f60b60bb490c2adf7f78..23bd7574b1c7e1483a1bcf7b7a5fc14234e9c7de 100644 --- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c +++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c @@ -573,7 +573,7 @@ kvaser_usb_leaf_frame_to_cmd(const struct kvaser_usb_net_priv *priv, cmd->u.tx_can.data[1] = cf->can_id & 0x3f; } - cmd->u.tx_can.data[5] = cf->len; + cmd->u.tx_can.data[5] = can_get_cc_dlc(cf, priv->can.ctrlmode); memcpy(&cmd->u.tx_can.data[6], cf->data, cf->len); if (cf->can_id & CAN_RTR_FLAG) @@ -1349,7 +1349,7 @@ static void kvaser_usb_leaf_rx_can_msg(const struct kvaser_usb *dev, else cf->can_id &= CAN_SFF_MASK; - cf->len = can_cc_dlc2len(cmd->u.leaf.log_message.dlc); + can_frame_set_cc_len(cf, cmd->u.leaf.log_message.dlc & 0xF, priv->can.ctrlmode); if (cmd->u.leaf.log_message.flags & MSG_FLAG_REMOTE_FRAME) cf->can_id |= CAN_RTR_FLAG; @@ -1367,7 +1367,7 @@ static void kvaser_usb_leaf_rx_can_msg(const struct kvaser_usb *dev, cf->can_id |= CAN_EFF_FLAG; } - cf->len = can_cc_dlc2len(rx_data[5]); + can_frame_set_cc_len(cf, rx_data[5] & 0xF, priv->can.ctrlmode); if (cmd->u.rx_can_header.flag & MSG_FLAG_REMOTE_FRAME) cf->can_id |= CAN_RTR_FLAG; diff --git a/drivers/net/can/xilinx_can.c b/drivers/net/can/xilinx_can.c index 43c812ea1de02320c7e8da79fdd194864d8a45d8..4d3283db3a1311fb7877dc70010efa282e895843 100644 --- a/drivers/net/can/xilinx_can.c +++ b/drivers/net/can/xilinx_can.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #define DRIVER_NAME "xilinx_can" @@ -198,6 +199,7 @@ struct xcan_devtype_data { * @bus_clk: Pointer to struct clk * @can_clk: Pointer to struct clk * @devtype: Device type specific constants + * @transceiver: Optional pointer to associated CAN transceiver */ struct xcan_priv { struct can_priv can; @@ -215,6 +217,7 @@ struct xcan_priv { struct clk *bus_clk; struct clk *can_clk; struct xcan_devtype_data devtype; + struct phy *transceiver; }; /* CAN Bittiming constants as per Xilinx CAN specs */ @@ -1419,6 +1422,10 @@ static int xcan_open(struct net_device *ndev) struct xcan_priv *priv = netdev_priv(ndev); int ret; + ret = phy_power_on(priv->transceiver); + if (ret) + return ret; + ret = pm_runtime_get_sync(priv->dev); if (ret < 0) { netdev_err(ndev, "%s: pm_runtime_get failed(%d)\n", @@ -1462,6 +1469,7 @@ static int xcan_open(struct net_device *ndev) free_irq(ndev->irq, ndev); err: pm_runtime_put(priv->dev); + phy_power_off(priv->transceiver); return ret; } @@ -1483,6 +1491,7 @@ static int xcan_close(struct net_device *ndev) close_candev(ndev); pm_runtime_put(priv->dev); + phy_power_off(priv->transceiver); return 0; } @@ -1713,6 +1722,7 @@ static int xcan_probe(struct platform_device *pdev) { struct net_device *ndev; struct xcan_priv *priv; + struct phy *transceiver; const struct of_device_id *of_id; const struct xcan_devtype_data *devtype = &xcan_axi_data; void __iomem *addr; @@ -1843,6 +1853,14 @@ static int xcan_probe(struct platform_device *pdev) goto err_free; } + transceiver = devm_phy_optional_get(&pdev->dev, NULL); + if (IS_ERR(transceiver)) { + ret = PTR_ERR(transceiver); + dev_err_probe(&pdev->dev, ret, "failed to get phy\n"); + goto err_free; + } + priv->transceiver = transceiver; + priv->write_reg = xcan_write_reg_le; priv->read_reg = xcan_read_reg_le; @@ -1869,6 +1887,7 @@ static int xcan_probe(struct platform_device *pdev) goto err_disableclks; } + of_can_transceiver(ndev); pm_runtime_put(&pdev->dev); if (priv->devtype.flags & XCAN_FLAG_CANFD_2) { @@ -1898,20 +1917,18 @@ static int xcan_probe(struct platform_device *pdev) * This function frees all the resources allocated to the device. * Return: 0 always */ -static int xcan_remove(struct platform_device *pdev) +static void xcan_remove(struct platform_device *pdev) { struct net_device *ndev = platform_get_drvdata(pdev); unregister_candev(ndev); pm_runtime_disable(&pdev->dev); free_candev(ndev); - - return 0; } static struct platform_driver xcan_driver = { .probe = xcan_probe, - .remove = xcan_remove, + .remove_new = xcan_remove, .driver = { .name = DRIVER_NAME, .pm = &xcan_dev_pm_ops, diff --git a/drivers/net/dsa/b53/b53_serdes.c b/drivers/net/dsa/b53/b53_serdes.c index 0690210770ffec1d26a4366236c6d1bf50636e1e..b0ccebcd3ffa5b2fe1994f832f6d1dd8d9d9b0fa 100644 --- a/drivers/net/dsa/b53/b53_serdes.c +++ b/drivers/net/dsa/b53/b53_serdes.c @@ -65,7 +65,7 @@ static u16 b53_serdes_read(struct b53_device *dev, u8 lane, return b53_serdes_read_blk(dev, offset, block); } -static int b53_serdes_config(struct phylink_pcs *pcs, unsigned int mode, +static int b53_serdes_config(struct phylink_pcs *pcs, unsigned int neg_mode, phy_interface_t interface, const unsigned long *advertising, bool permit_pause_to_mac) @@ -239,6 +239,7 @@ int b53_serdes_init(struct b53_device *dev, int port) pcs->dev = dev; pcs->lane = lane; pcs->pcs.ops = &b53_pcs_ops; + pcs->pcs.neg_mode = true; return 0; } diff --git a/drivers/net/dsa/hirschmann/hellcreek.c b/drivers/net/dsa/hirschmann/hellcreek.c index 595a548bb0a80323a6adc24a27e9e2cf26c8c57a..af50001ccdd4e63e58d639bdf6941fbaedd5ac64 100644 --- a/drivers/net/dsa/hirschmann/hellcreek.c +++ b/drivers/net/dsa/hirschmann/hellcreek.c @@ -1885,13 +1885,17 @@ static int hellcreek_port_setup_tc(struct dsa_switch *ds, int port, case TC_SETUP_QDISC_TAPRIO: { struct tc_taprio_qopt_offload *taprio = type_data; - if (!hellcreek_validate_schedule(hellcreek, taprio)) - return -EOPNOTSUPP; + switch (taprio->cmd) { + case TAPRIO_CMD_REPLACE: + if (!hellcreek_validate_schedule(hellcreek, taprio)) + return -EOPNOTSUPP; - if (taprio->enable) return hellcreek_port_set_schedule(ds, port, taprio); - - return hellcreek_port_del_schedule(ds, port); + case TAPRIO_CMD_DESTROY: + return hellcreek_port_del_schedule(ds, port); + default: + return -EOPNOTSUPP; + } } default: return -EOPNOTSUPP; diff --git a/drivers/net/dsa/lan9303-core.c b/drivers/net/dsa/lan9303-core.c index c0215a8770f49d71c9847853fe38492a8a01d80e..ff76444057d24289c8810d53c790ce330ff83f96 100644 --- a/drivers/net/dsa/lan9303-core.c +++ b/drivers/net/dsa/lan9303-core.c @@ -1458,7 +1458,6 @@ int lan9303_remove(struct lan9303 *chip) /* assert reset to the whole device to prevent it from doing anything */ gpiod_set_value_cansleep(chip->reset_gpio, 1); - gpiod_unexport(chip->reset_gpio); return 0; } diff --git a/drivers/net/dsa/lan9303_i2c.c b/drivers/net/dsa/lan9303_i2c.c index e8844820c3a93a42e7a1235088b293bfef570adc..bbbec322bc4fbbc52ef5e66c5a862fb349000afb 100644 --- a/drivers/net/dsa/lan9303_i2c.c +++ b/drivers/net/dsa/lan9303_i2c.c @@ -105,7 +105,7 @@ static struct i2c_driver lan9303_i2c_driver = { .name = "LAN9303_I2C", .of_match_table = lan9303_i2c_of_match, }, - .probe_new = lan9303_i2c_probe, + .probe = lan9303_i2c_probe, .remove = lan9303_i2c_remove, .shutdown = lan9303_i2c_shutdown, .id_table = lan9303_i2c_id, diff --git a/drivers/net/dsa/microchip/ksz8795.c b/drivers/net/dsa/microchip/ksz8795.c index f56fca1b1a222a9f229daac6ad80bf1b5954644e..84d502589f8e3316e38e972ccf839278354b90dd 100644 --- a/drivers/net/dsa/microchip/ksz8795.c +++ b/drivers/net/dsa/microchip/ksz8795.c @@ -28,13 +28,13 @@ static void ksz_cfg(struct ksz_device *dev, u32 addr, u8 bits, bool set) { - regmap_update_bits(dev->regmap[0], addr, bits, set ? bits : 0); + regmap_update_bits(ksz_regmap_8(dev), addr, bits, set ? bits : 0); } static void ksz_port_cfg(struct ksz_device *dev, int port, int offset, u8 bits, bool set) { - regmap_update_bits(dev->regmap[0], PORT_CTRL_ADDR(port, offset), + regmap_update_bits(ksz_regmap_8(dev), PORT_CTRL_ADDR(port, offset), bits, set ? bits : 0); } @@ -941,7 +941,6 @@ void ksz8_flush_dyn_mac_table(struct ksz_device *dev, int port) { u8 learn[DSA_MAX_PORTS]; int first, index, cnt; - struct ksz_port *p; const u16 *regs; regs = dev->info->regs; @@ -955,9 +954,6 @@ void ksz8_flush_dyn_mac_table(struct ksz_device *dev, int port) cnt = dev->info->port_cnt; } for (index = first; index < cnt; index++) { - p = &dev->ports[index]; - if (!p->on) - continue; ksz_pread8(dev, index, regs[P_STP_CTRL], &learn[index]); if (!(learn[index] & PORT_LEARN_DISABLE)) ksz_pwrite8(dev, index, regs[P_STP_CTRL], @@ -965,9 +961,6 @@ void ksz8_flush_dyn_mac_table(struct ksz_device *dev, int port) } ksz_cfg(dev, S_FLUSH_TABLE_CTRL, SW_FLUSH_DYN_MAC_TABLE, true); for (index = first; index < cnt; index++) { - p = &dev->ports[index]; - if (!p->on) - continue; if (!(learn[index] & PORT_LEARN_DISABLE)) ksz_pwrite8(dev, index, regs[P_STP_CTRL], learn[index]); } @@ -1338,25 +1331,14 @@ void ksz8_config_cpu_port(struct dsa_switch *ds) ksz_cfg(dev, regs[S_TAIL_TAG_CTRL], masks[SW_TAIL_TAG_ENABLE], true); - p = &dev->ports[dev->cpu_port]; - p->on = 1; - ksz8_port_setup(dev, dev->cpu_port, true); for (i = 0; i < dev->phy_port_cnt; i++) { - p = &dev->ports[i]; - ksz_port_stp_state_set(ds, i, BR_STATE_DISABLED); - - /* Last port may be disabled. */ - if (i == dev->phy_port_cnt) - break; - p->on = 1; } for (i = 0; i < dev->phy_port_cnt; i++) { p = &dev->ports[i]; - if (!p->on) - continue; + if (!ksz_is_ksz88x3(dev)) { ksz_pread8(dev, i, regs[P_REMOTE_STATUS], &remote); if (remote & KSZ8_PORT_FIBER_MODE) @@ -1425,14 +1407,14 @@ int ksz8_setup(struct dsa_switch *ds) ksz_cfg(dev, S_LINK_AGING_CTRL, SW_LINK_AUTO_AGING, true); /* Enable aggressive back off algorithm in half duplex mode. */ - regmap_update_bits(dev->regmap[0], REG_SW_CTRL_1, + regmap_update_bits(ksz_regmap_8(dev), REG_SW_CTRL_1, SW_AGGR_BACKOFF, SW_AGGR_BACKOFF); /* * Make sure unicast VLAN boundary is set as default and * enable no excessive collision drop. */ - regmap_update_bits(dev->regmap[0], REG_SW_CTRL_2, + regmap_update_bits(ksz_regmap_8(dev), REG_SW_CTRL_2, UNICAST_VLAN_BOUNDARY | NO_EXC_COLLISION_DROP, UNICAST_VLAN_BOUNDARY | NO_EXC_COLLISION_DROP); diff --git a/drivers/net/dsa/microchip/ksz8863_smi.c b/drivers/net/dsa/microchip/ksz8863_smi.c index 3698112138b78b33a1205690b3d9a35e5ab6c557..fd6e2e69a42ae796bb07574e7f0a1854606b5ab2 100644 --- a/drivers/net/dsa/microchip/ksz8863_smi.c +++ b/drivers/net/dsa/microchip/ksz8863_smi.c @@ -104,6 +104,7 @@ static const struct regmap_config ksz8863_regmap_config[] = { .cache_type = REGCACHE_NONE, .lock = ksz_regmap_lock, .unlock = ksz_regmap_unlock, + .max_register = U8_MAX, }, { .name = "#16", @@ -113,6 +114,7 @@ static const struct regmap_config ksz8863_regmap_config[] = { .cache_type = REGCACHE_NONE, .lock = ksz_regmap_lock, .unlock = ksz_regmap_unlock, + .max_register = U8_MAX, }, { .name = "#32", @@ -122,11 +124,14 @@ static const struct regmap_config ksz8863_regmap_config[] = { .cache_type = REGCACHE_NONE, .lock = ksz_regmap_lock, .unlock = ksz_regmap_unlock, + .max_register = U8_MAX, } }; static int ksz8863_smi_probe(struct mdio_device *mdiodev) { + struct device *ddev = &mdiodev->dev; + const struct ksz_chip_data *chip; struct regmap_config rc; struct ksz_device *dev; int ret; @@ -136,9 +141,15 @@ static int ksz8863_smi_probe(struct mdio_device *mdiodev) if (!dev) return -ENOMEM; - for (i = 0; i < ARRAY_SIZE(ksz8863_regmap_config); i++) { + chip = device_get_match_data(ddev); + if (!chip) + return -EINVAL; + + for (i = 0; i < __KSZ_NUM_REGMAPS; i++) { rc = ksz8863_regmap_config[i]; rc.lock_arg = &dev->regmap_mutex; + rc.wr_table = chip->wr_table; + rc.rd_table = chip->rd_table; dev->regmap[i] = devm_regmap_init(&mdiodev->dev, ®map_smi[i], dev, &rc); diff --git a/drivers/net/dsa/microchip/ksz9477.c b/drivers/net/dsa/microchip/ksz9477.c index bf13d47c26cf70bf9ac6242cc58fb53bb00d361a..83b7f2d5c1ea6d76f07011d651c85998fce290aa 100644 --- a/drivers/net/dsa/microchip/ksz9477.c +++ b/drivers/net/dsa/microchip/ksz9477.c @@ -21,25 +21,25 @@ static void ksz_cfg(struct ksz_device *dev, u32 addr, u8 bits, bool set) { - regmap_update_bits(dev->regmap[0], addr, bits, set ? bits : 0); + regmap_update_bits(ksz_regmap_8(dev), addr, bits, set ? bits : 0); } static void ksz_port_cfg(struct ksz_device *dev, int port, int offset, u8 bits, bool set) { - regmap_update_bits(dev->regmap[0], PORT_CTRL_ADDR(port, offset), + regmap_update_bits(ksz_regmap_8(dev), PORT_CTRL_ADDR(port, offset), bits, set ? bits : 0); } static void ksz9477_cfg32(struct ksz_device *dev, u32 addr, u32 bits, bool set) { - regmap_update_bits(dev->regmap[2], addr, bits, set ? bits : 0); + regmap_update_bits(ksz_regmap_32(dev), addr, bits, set ? bits : 0); } static void ksz9477_port_cfg32(struct ksz_device *dev, int port, int offset, u32 bits, bool set) { - regmap_update_bits(dev->regmap[2], PORT_CTRL_ADDR(port, offset), + regmap_update_bits(ksz_regmap_32(dev), PORT_CTRL_ADDR(port, offset), bits, set ? bits : 0); } @@ -52,7 +52,7 @@ int ksz9477_change_mtu(struct ksz_device *dev, int port, int mtu) frame_size = mtu + VLAN_ETH_HLEN + ETH_FCS_LEN; - return regmap_update_bits(dev->regmap[1], REG_SW_MTU__2, + return regmap_update_bits(ksz_regmap_16(dev), REG_SW_MTU__2, REG_SW_MTU_MASK, frame_size); } @@ -60,7 +60,7 @@ static int ksz9477_wait_vlan_ctrl_ready(struct ksz_device *dev) { unsigned int val; - return regmap_read_poll_timeout(dev->regmap[0], REG_SW_VLAN_CTRL, + return regmap_read_poll_timeout(ksz_regmap_8(dev), REG_SW_VLAN_CTRL, val, !(val & VLAN_START), 10, 1000); } @@ -147,7 +147,7 @@ static int ksz9477_wait_alu_ready(struct ksz_device *dev) { unsigned int val; - return regmap_read_poll_timeout(dev->regmap[2], REG_SW_ALU_CTRL__4, + return regmap_read_poll_timeout(ksz_regmap_32(dev), REG_SW_ALU_CTRL__4, val, !(val & ALU_START), 10, 1000); } @@ -155,7 +155,7 @@ static int ksz9477_wait_alu_sta_ready(struct ksz_device *dev) { unsigned int val; - return regmap_read_poll_timeout(dev->regmap[2], + return regmap_read_poll_timeout(ksz_regmap_32(dev), REG_SW_ALU_STAT_CTRL__4, val, !(val & ALU_STAT_START), 10, 1000); @@ -170,7 +170,7 @@ int ksz9477_reset_switch(struct ksz_device *dev) ksz_cfg(dev, REG_SW_OPERATION, SW_RESET, true); /* turn off SPI DO Edge select */ - regmap_update_bits(dev->regmap[0], REG_SW_GLOBAL_SERIAL_CTRL_0, + regmap_update_bits(ksz_regmap_8(dev), REG_SW_GLOBAL_SERIAL_CTRL_0, SPI_AUTO_EDGE_DETECTION, 0); /* default configuration */ @@ -213,7 +213,7 @@ void ksz9477_r_mib_cnt(struct ksz_device *dev, int port, u16 addr, u64 *cnt) data |= (addr << MIB_COUNTER_INDEX_S); ksz_pwrite32(dev, port, REG_PORT_MIB_CTRL_STAT__4, data); - ret = regmap_read_poll_timeout(dev->regmap[2], + ret = regmap_read_poll_timeout(ksz_regmap_32(dev), PORT_CTRL_ADDR(port, REG_PORT_MIB_CTRL_STAT__4), val, !(val & MIB_COUNTER_READ), 10, 1000); /* failed to read MIB. get out of loop */ @@ -329,11 +329,27 @@ int ksz9477_r_phy(struct ksz_device *dev, u16 addr, u16 reg, u16 *data) int ksz9477_w_phy(struct ksz_device *dev, u16 addr, u16 reg, u16 val) { + u32 mask, val32; + /* No real PHY after this. */ if (!dev->info->internal_phy[addr]) return 0; - return ksz_pwrite16(dev, addr, 0x100 + (reg << 1), val); + if (reg < 0x10) + return ksz_pwrite16(dev, addr, 0x100 + (reg << 1), val); + + /* Errata: When using SPI, I2C, or in-band register access, + * writes to certain PHY registers should be performed as + * 32-bit writes instead of 16-bit writes. + */ + val32 = val; + mask = 0xffff; + if ((reg & 1) == 0) { + val32 <<= 16; + mask <<= 16; + } + reg &= ~1; + return ksz_prmw32(dev, addr, 0x100 + (reg << 1), mask, val32); } void ksz9477_cfg_port_member(struct ksz_device *dev, int port, u8 member) @@ -346,7 +362,7 @@ void ksz9477_flush_dyn_mac_table(struct ksz_device *dev, int port) const u16 *regs = dev->info->regs; u8 data; - regmap_update_bits(dev->regmap[0], REG_SW_LUE_CTRL_2, + regmap_update_bits(ksz_regmap_8(dev), REG_SW_LUE_CTRL_2, SW_FLUSH_OPTION_M << SW_FLUSH_OPTION_S, SW_FLUSH_OPTION_DYN_MAC << SW_FLUSH_OPTION_S); @@ -889,62 +905,6 @@ static phy_interface_t ksz9477_get_interface(struct ksz_device *dev, int port) return interface; } -static void ksz9477_port_mmd_write(struct ksz_device *dev, int port, - u8 dev_addr, u16 reg_addr, u16 val) -{ - ksz_pwrite16(dev, port, REG_PORT_PHY_MMD_SETUP, - MMD_SETUP(PORT_MMD_OP_INDEX, dev_addr)); - ksz_pwrite16(dev, port, REG_PORT_PHY_MMD_INDEX_DATA, reg_addr); - ksz_pwrite16(dev, port, REG_PORT_PHY_MMD_SETUP, - MMD_SETUP(PORT_MMD_OP_DATA_NO_INCR, dev_addr)); - ksz_pwrite16(dev, port, REG_PORT_PHY_MMD_INDEX_DATA, val); -} - -static void ksz9477_phy_errata_setup(struct ksz_device *dev, int port) -{ - /* Apply PHY settings to address errata listed in - * KSZ9477, KSZ9897, KSZ9896, KSZ9567, KSZ8565 - * Silicon Errata and Data Sheet Clarification documents: - * - * Register settings are needed to improve PHY receive performance - */ - ksz9477_port_mmd_write(dev, port, 0x01, 0x6f, 0xdd0b); - ksz9477_port_mmd_write(dev, port, 0x01, 0x8f, 0x6032); - ksz9477_port_mmd_write(dev, port, 0x01, 0x9d, 0x248c); - ksz9477_port_mmd_write(dev, port, 0x01, 0x75, 0x0060); - ksz9477_port_mmd_write(dev, port, 0x01, 0xd3, 0x7777); - ksz9477_port_mmd_write(dev, port, 0x1c, 0x06, 0x3008); - ksz9477_port_mmd_write(dev, port, 0x1c, 0x08, 0x2001); - - /* Transmit waveform amplitude can be improved - * (1000BASE-T, 100BASE-TX, 10BASE-Te) - */ - ksz9477_port_mmd_write(dev, port, 0x1c, 0x04, 0x00d0); - - /* Energy Efficient Ethernet (EEE) feature select must - * be manually disabled (except on KSZ8565 which is 100Mbit) - */ - if (dev->info->gbit_capable[port]) - ksz9477_port_mmd_write(dev, port, 0x07, 0x3c, 0x0000); - - /* Register settings are required to meet data sheet - * supply current specifications - */ - ksz9477_port_mmd_write(dev, port, 0x1c, 0x13, 0x6eff); - ksz9477_port_mmd_write(dev, port, 0x1c, 0x14, 0xe6ff); - ksz9477_port_mmd_write(dev, port, 0x1c, 0x15, 0x6eff); - ksz9477_port_mmd_write(dev, port, 0x1c, 0x16, 0xe6ff); - ksz9477_port_mmd_write(dev, port, 0x1c, 0x17, 0x00ff); - ksz9477_port_mmd_write(dev, port, 0x1c, 0x18, 0x43ff); - ksz9477_port_mmd_write(dev, port, 0x1c, 0x19, 0xc3ff); - ksz9477_port_mmd_write(dev, port, 0x1c, 0x1a, 0x6fff); - ksz9477_port_mmd_write(dev, port, 0x1c, 0x1b, 0x07ff); - ksz9477_port_mmd_write(dev, port, 0x1c, 0x1c, 0x0fff); - ksz9477_port_mmd_write(dev, port, 0x1c, 0x1d, 0xe7ff); - ksz9477_port_mmd_write(dev, port, 0x1c, 0x1e, 0xefff); - ksz9477_port_mmd_write(dev, port, 0x1c, 0x20, 0xeeee); -} - void ksz9477_get_caps(struct ksz_device *dev, int port, struct phylink_config *config) { @@ -1029,20 +989,10 @@ void ksz9477_port_setup(struct ksz_device *dev, int port, bool cpu_port) /* enable 802.1p priority */ ksz_port_cfg(dev, port, P_PRIO_CTRL, PORT_802_1P_PRIO_ENABLE, true); - if (dev->info->internal_phy[port]) { - /* do not force flow control */ - ksz_port_cfg(dev, port, REG_PORT_CTRL_0, - PORT_FORCE_TX_FLOW_CTRL | PORT_FORCE_RX_FLOW_CTRL, - false); - - if (dev->info->phy_errata_9477) - ksz9477_phy_errata_setup(dev, port); - } else { - /* force flow control */ - ksz_port_cfg(dev, port, REG_PORT_CTRL_0, - PORT_FORCE_TX_FLOW_CTRL | PORT_FORCE_RX_FLOW_CTRL, - true); - } + /* force flow control for non-PHY ports only */ + ksz_port_cfg(dev, port, REG_PORT_CTRL_0, + PORT_FORCE_TX_FLOW_CTRL | PORT_FORCE_RX_FLOW_CTRL, + !dev->info->internal_phy[port]); if (cpu_port) member = dsa_user_ports(ds); @@ -1165,7 +1115,7 @@ int ksz9477_setup(struct dsa_switch *ds) ksz_cfg(dev, REG_SW_MAC_CTRL_1, SW_JUMBO_PACKET, true); /* Now we can configure default MTU value */ - ret = regmap_update_bits(dev->regmap[1], REG_SW_MTU__2, REG_SW_MTU_MASK, + ret = regmap_update_bits(ksz_regmap_16(dev), REG_SW_MTU__2, REG_SW_MTU_MASK, VLAN_ETH_FRAME_LEN + ETH_FCS_LEN); if (ret) return ret; diff --git a/drivers/net/dsa/microchip/ksz9477_i2c.c b/drivers/net/dsa/microchip/ksz9477_i2c.c index 97a317263a2f44e0363ad2e57626b2afa3b1ad06..2710afad4f3aff838c4ea30f6db5d79d69c992b3 100644 --- a/drivers/net/dsa/microchip/ksz9477_i2c.c +++ b/drivers/net/dsa/microchip/ksz9477_i2c.c @@ -24,7 +24,7 @@ static int ksz9477_i2c_probe(struct i2c_client *i2c) if (!dev) return -ENOMEM; - for (i = 0; i < ARRAY_SIZE(ksz9477_regmap_config); i++) { + for (i = 0; i < __KSZ_NUM_REGMAPS; i++) { rc = ksz9477_regmap_config[i]; rc.lock_arg = &dev->regmap_mutex; dev->regmap[i] = devm_regmap_init_i2c(i2c, &rc); @@ -119,7 +119,7 @@ static struct i2c_driver ksz9477_i2c_driver = { .name = "ksz9477-switch", .of_match_table = ksz9477_dt_ids, }, - .probe_new = ksz9477_i2c_probe, + .probe = ksz9477_i2c_probe, .remove = ksz9477_i2c_remove, .shutdown = ksz9477_i2c_shutdown, .id_table = ksz9477_i2c_id, diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c index a4428be5f483ca1587229f8e4c36d6a6dd276892..813b91a816bbee9c33bb0005b3de424bc04aec29 100644 --- a/drivers/net/dsa/microchip/ksz_common.c +++ b/drivers/net/dsa/microchip/ksz_common.c @@ -1075,6 +1075,45 @@ static const struct regmap_access_table ksz9896_register_set = { .n_yes_ranges = ARRAY_SIZE(ksz9896_valid_regs), }; +static const struct regmap_range ksz8873_valid_regs[] = { + regmap_reg_range(0x00, 0x01), + /* global control register */ + regmap_reg_range(0x02, 0x0f), + + /* port registers */ + regmap_reg_range(0x10, 0x1d), + regmap_reg_range(0x1e, 0x1f), + regmap_reg_range(0x20, 0x2d), + regmap_reg_range(0x2e, 0x2f), + regmap_reg_range(0x30, 0x39), + regmap_reg_range(0x3f, 0x3f), + + /* advanced control registers */ + regmap_reg_range(0x60, 0x6f), + regmap_reg_range(0x70, 0x75), + regmap_reg_range(0x76, 0x78), + regmap_reg_range(0x79, 0x7a), + regmap_reg_range(0x7b, 0x83), + regmap_reg_range(0x8e, 0x99), + regmap_reg_range(0x9a, 0xa5), + regmap_reg_range(0xa6, 0xa6), + regmap_reg_range(0xa7, 0xaa), + regmap_reg_range(0xab, 0xae), + regmap_reg_range(0xaf, 0xba), + regmap_reg_range(0xbb, 0xbc), + regmap_reg_range(0xbd, 0xbd), + regmap_reg_range(0xc0, 0xc0), + regmap_reg_range(0xc2, 0xc2), + regmap_reg_range(0xc3, 0xc3), + regmap_reg_range(0xc4, 0xc4), + regmap_reg_range(0xc6, 0xc6), +}; + +static const struct regmap_access_table ksz8873_register_set = { + .yes_ranges = ksz8873_valid_regs, + .n_yes_ranges = ARRAY_SIZE(ksz8873_valid_regs), +}; + const struct ksz_chip_data ksz_switch_chips[] = { [KSZ8563] = { .chip_id = KSZ8563_CHIP_ID, @@ -1214,6 +1253,8 @@ const struct ksz_chip_data ksz_switch_chips[] = { .supports_mii = {false, false, true}, .supports_rmii = {false, false, true}, .internal_phy = {true, true, false}, + .wr_table = &ksz8873_register_set, + .rd_table = &ksz8873_register_set, }, [KSZ9477] = { @@ -1229,7 +1270,6 @@ const struct ksz_chip_data ksz_switch_chips[] = { .tc_cbs_supported = true, .tc_ets_supported = true, .ops = &ksz9477_dev_ops, - .phy_errata_9477 = true, .mib_names = ksz9477_mib_names, .mib_cnt = ARRAY_SIZE(ksz9477_mib_names), .reg_mib_cnt = MIB_COUNTER_NUM, @@ -1262,7 +1302,6 @@ const struct ksz_chip_data ksz_switch_chips[] = { .port_nirqs = 2, .num_tx_queues = 4, .ops = &ksz9477_dev_ops, - .phy_errata_9477 = true, .mib_names = ksz9477_mib_names, .mib_cnt = ARRAY_SIZE(ksz9477_mib_names), .reg_mib_cnt = MIB_COUNTER_NUM, @@ -1295,7 +1334,6 @@ const struct ksz_chip_data ksz_switch_chips[] = { .port_nirqs = 2, .num_tx_queues = 4, .ops = &ksz9477_dev_ops, - .phy_errata_9477 = true, .mib_names = ksz9477_mib_names, .mib_cnt = ARRAY_SIZE(ksz9477_mib_names), .reg_mib_cnt = MIB_COUNTER_NUM, @@ -1382,7 +1420,6 @@ const struct ksz_chip_data ksz_switch_chips[] = { .tc_cbs_supported = true, .tc_ets_supported = true, .ops = &ksz9477_dev_ops, - .phy_errata_9477 = true, .mib_names = ksz9477_mib_names, .mib_cnt = ARRAY_SIZE(ksz9477_mib_names), .reg_mib_cnt = MIB_COUNTER_NUM, @@ -2095,7 +2132,7 @@ static int ksz_setup(struct dsa_switch *ds) } /* set broadcast storm protection 10% rate */ - regmap_update_bits(dev->regmap[1], regs[S_BROADCAST_CTRL], + regmap_update_bits(ksz_regmap_16(dev), regs[S_BROADCAST_CTRL], BROADCAST_STORM_RATE, (BROADCAST_STORM_VALUE * BROADCAST_STORM_PROT_RATE) / 100); @@ -2106,7 +2143,7 @@ static int ksz_setup(struct dsa_switch *ds) ds->num_tx_queues = dev->info->num_tx_queues; - regmap_update_bits(dev->regmap[0], regs[S_MULTICAST_CTRL], + regmap_update_bits(ksz_regmap_8(dev), regs[S_MULTICAST_CTRL], MULTICAST_STORM_DISABLE, MULTICAST_STORM_DISABLE); ksz_init_mib_timer(dev); @@ -2156,7 +2193,7 @@ static int ksz_setup(struct dsa_switch *ds) } /* start switch */ - regmap_update_bits(dev->regmap[0], regs[S_START_CTRL], + regmap_update_bits(ksz_regmap_8(dev), regs[S_START_CTRL], SW_START, SW_START); return 0; diff --git a/drivers/net/dsa/microchip/ksz_common.h b/drivers/net/dsa/microchip/ksz_common.h index 8abecaf6089ef4ce1fd1f733a9af699941fe6ac3..28444e5924f95422e4d26581b1f596122eda7615 100644 --- a/drivers/net/dsa/microchip/ksz_common.h +++ b/drivers/net/dsa/microchip/ksz_common.h @@ -22,6 +22,13 @@ struct ksz_device; struct ksz_port; +enum ksz_regmap_width { + KSZ_REGMAP_8, + KSZ_REGMAP_16, + KSZ_REGMAP_32, + __KSZ_NUM_REGMAPS, +}; + struct vlan_table { u32 table[3]; }; @@ -53,7 +60,6 @@ struct ksz_chip_data { bool tc_cbs_supported; bool tc_ets_supported; const struct ksz_dev_ops *ops; - bool phy_errata_9477; bool ksz87xx_eee_link_erratum; const struct ksz_mib_names *mib_names; int mib_cnt; @@ -101,7 +107,6 @@ struct ksz_port { int stp_state; struct phy_device phydev; - u32 on:1; /* port is not disabled by hardware */ u32 fiber:1; /* port is fiber */ u32 force:1; u32 read:1; /* read MIB counters in background */ @@ -137,7 +142,7 @@ struct ksz_device { const struct ksz_dev_ops *dev_ops; struct device *dev; - struct regmap *regmap[3]; + struct regmap *regmap[__KSZ_NUM_REGMAPS]; void *priv; int irq; @@ -377,11 +382,25 @@ phy_interface_t ksz_get_xmii(struct ksz_device *dev, int port, bool gbit); extern const struct ksz_chip_data ksz_switch_chips[]; /* Common register access functions */ +static inline struct regmap *ksz_regmap_8(struct ksz_device *dev) +{ + return dev->regmap[KSZ_REGMAP_8]; +} + +static inline struct regmap *ksz_regmap_16(struct ksz_device *dev) +{ + return dev->regmap[KSZ_REGMAP_16]; +} + +static inline struct regmap *ksz_regmap_32(struct ksz_device *dev) +{ + return dev->regmap[KSZ_REGMAP_32]; +} static inline int ksz_read8(struct ksz_device *dev, u32 reg, u8 *val) { unsigned int value; - int ret = regmap_read(dev->regmap[0], reg, &value); + int ret = regmap_read(ksz_regmap_8(dev), reg, &value); if (ret) dev_err(dev->dev, "can't read 8bit reg: 0x%x %pe\n", reg, @@ -394,7 +413,7 @@ static inline int ksz_read8(struct ksz_device *dev, u32 reg, u8 *val) static inline int ksz_read16(struct ksz_device *dev, u32 reg, u16 *val) { unsigned int value; - int ret = regmap_read(dev->regmap[1], reg, &value); + int ret = regmap_read(ksz_regmap_16(dev), reg, &value); if (ret) dev_err(dev->dev, "can't read 16bit reg: 0x%x %pe\n", reg, @@ -407,7 +426,7 @@ static inline int ksz_read16(struct ksz_device *dev, u32 reg, u16 *val) static inline int ksz_read32(struct ksz_device *dev, u32 reg, u32 *val) { unsigned int value; - int ret = regmap_read(dev->regmap[2], reg, &value); + int ret = regmap_read(ksz_regmap_32(dev), reg, &value); if (ret) dev_err(dev->dev, "can't read 32bit reg: 0x%x %pe\n", reg, @@ -422,7 +441,7 @@ static inline int ksz_read64(struct ksz_device *dev, u32 reg, u64 *val) u32 value[2]; int ret; - ret = regmap_bulk_read(dev->regmap[2], reg, value, 2); + ret = regmap_bulk_read(ksz_regmap_32(dev), reg, value, 2); if (ret) dev_err(dev->dev, "can't read 64bit reg: 0x%x %pe\n", reg, ERR_PTR(ret)); @@ -436,7 +455,7 @@ static inline int ksz_write8(struct ksz_device *dev, u32 reg, u8 value) { int ret; - ret = regmap_write(dev->regmap[0], reg, value); + ret = regmap_write(ksz_regmap_8(dev), reg, value); if (ret) dev_err(dev->dev, "can't write 8bit reg: 0x%x %pe\n", reg, ERR_PTR(ret)); @@ -448,7 +467,7 @@ static inline int ksz_write16(struct ksz_device *dev, u32 reg, u16 value) { int ret; - ret = regmap_write(dev->regmap[1], reg, value); + ret = regmap_write(ksz_regmap_16(dev), reg, value); if (ret) dev_err(dev->dev, "can't write 16bit reg: 0x%x %pe\n", reg, ERR_PTR(ret)); @@ -460,7 +479,7 @@ static inline int ksz_write32(struct ksz_device *dev, u32 reg, u32 value) { int ret; - ret = regmap_write(dev->regmap[2], reg, value); + ret = regmap_write(ksz_regmap_32(dev), reg, value); if (ret) dev_err(dev->dev, "can't write 32bit reg: 0x%x %pe\n", reg, ERR_PTR(ret)); @@ -473,7 +492,7 @@ static inline int ksz_rmw16(struct ksz_device *dev, u32 reg, u16 mask, { int ret; - ret = regmap_update_bits(dev->regmap[1], reg, mask, value); + ret = regmap_update_bits(ksz_regmap_16(dev), reg, mask, value); if (ret) dev_err(dev->dev, "can't rmw 16bit reg 0x%x: %pe\n", reg, ERR_PTR(ret)); @@ -486,7 +505,7 @@ static inline int ksz_rmw32(struct ksz_device *dev, u32 reg, u32 mask, { int ret; - ret = regmap_update_bits(dev->regmap[2], reg, mask, value); + ret = regmap_update_bits(ksz_regmap_32(dev), reg, mask, value); if (ret) dev_err(dev->dev, "can't rmw 32bit reg 0x%x: %pe\n", reg, ERR_PTR(ret)); @@ -503,12 +522,19 @@ static inline int ksz_write64(struct ksz_device *dev, u32 reg, u64 value) val[0] = swab32(value & 0xffffffffULL); val[1] = swab32(value >> 32ULL); - return regmap_bulk_write(dev->regmap[2], reg, val, 2); + return regmap_bulk_write(ksz_regmap_32(dev), reg, val, 2); } static inline int ksz_rmw8(struct ksz_device *dev, int offset, u8 mask, u8 val) { - return regmap_update_bits(dev->regmap[0], offset, mask, val); + int ret; + + ret = regmap_update_bits(ksz_regmap_8(dev), offset, mask, val); + if (ret) + dev_err(dev->dev, "can't rmw 8bit reg 0x%x: %pe\n", offset, + ERR_PTR(ret)); + + return ret; } static inline int ksz_pread8(struct ksz_device *dev, int port, int offset, @@ -549,12 +575,18 @@ static inline int ksz_pwrite32(struct ksz_device *dev, int port, int offset, data); } -static inline void ksz_prmw8(struct ksz_device *dev, int port, int offset, - u8 mask, u8 val) +static inline int ksz_prmw8(struct ksz_device *dev, int port, int offset, + u8 mask, u8 val) +{ + return ksz_rmw8(dev, dev->dev_ops->get_port_addr(port, offset), + mask, val); +} + +static inline int ksz_prmw32(struct ksz_device *dev, int port, int offset, + u32 mask, u32 val) { - regmap_update_bits(dev->regmap[0], - dev->dev_ops->get_port_addr(port, offset), - mask, val); + return ksz_rmw32(dev, dev->dev_ops->get_port_addr(port, offset), + mask, val); } static inline void ksz_regmap_lock(void *__mtx) @@ -709,9 +741,9 @@ static inline int is_lan937x(struct ksz_device *dev) #define KSZ_REGMAP_TABLE(ksz, swp, regbits, regpad, regalign) \ static const struct regmap_config ksz##_regmap_config[] = { \ - KSZ_REGMAP_ENTRY(8, swp, (regbits), (regpad), (regalign)), \ - KSZ_REGMAP_ENTRY(16, swp, (regbits), (regpad), (regalign)), \ - KSZ_REGMAP_ENTRY(32, swp, (regbits), (regpad), (regalign)), \ + [KSZ_REGMAP_8] = KSZ_REGMAP_ENTRY(8, swp, (regbits), (regpad), (regalign)), \ + [KSZ_REGMAP_16] = KSZ_REGMAP_ENTRY(16, swp, (regbits), (regpad), (regalign)), \ + [KSZ_REGMAP_32] = KSZ_REGMAP_ENTRY(32, swp, (regbits), (regpad), (regalign)), \ } #endif diff --git a/drivers/net/dsa/microchip/ksz_spi.c b/drivers/net/dsa/microchip/ksz_spi.c index 96c52e8fb51b6c858e413ffac870337a07c1ded9..279338451621b1834c92dda25bbe2d7209da2f8d 100644 --- a/drivers/net/dsa/microchip/ksz_spi.c +++ b/drivers/net/dsa/microchip/ksz_spi.c @@ -63,7 +63,7 @@ static int ksz_spi_probe(struct spi_device *spi) else regmap_config = ksz9477_regmap_config; - for (i = 0; i < ARRAY_SIZE(ksz8795_regmap_config); i++) { + for (i = 0; i < __KSZ_NUM_REGMAPS; i++) { rc = regmap_config[i]; rc.lock_arg = &dev->regmap_mutex; rc.wr_table = chip->wr_table; diff --git a/drivers/net/dsa/microchip/lan937x_main.c b/drivers/net/dsa/microchip/lan937x_main.c index 399a3905e6cad10bced50b33e26002d0fb84446b..b479a628b1ae5610990b2bc56f06656ee2ee798c 100644 --- a/drivers/net/dsa/microchip/lan937x_main.c +++ b/drivers/net/dsa/microchip/lan937x_main.c @@ -20,13 +20,13 @@ static int lan937x_cfg(struct ksz_device *dev, u32 addr, u8 bits, bool set) { - return regmap_update_bits(dev->regmap[0], addr, bits, set ? bits : 0); + return regmap_update_bits(ksz_regmap_8(dev), addr, bits, set ? bits : 0); } static int lan937x_port_cfg(struct ksz_device *dev, int port, int offset, u8 bits, bool set) { - return regmap_update_bits(dev->regmap[0], PORT_CTRL_ADDR(port, offset), + return regmap_update_bits(ksz_regmap_8(dev), PORT_CTRL_ADDR(port, offset), bits, set ? bits : 0); } @@ -86,7 +86,7 @@ static int lan937x_internal_phy_write(struct ksz_device *dev, int addr, int reg, if (ret < 0) return ret; - ret = regmap_read_poll_timeout(dev->regmap[1], REG_VPHY_IND_CTRL__2, + ret = regmap_read_poll_timeout(ksz_regmap_16(dev), REG_VPHY_IND_CTRL__2, value, !(value & VPHY_IND_BUSY), 10, 1000); if (ret < 0) { @@ -116,7 +116,7 @@ static int lan937x_internal_phy_read(struct ksz_device *dev, int addr, int reg, if (ret < 0) return ret; - ret = regmap_read_poll_timeout(dev->regmap[1], REG_VPHY_IND_CTRL__2, + ret = regmap_read_poll_timeout(ksz_regmap_16(dev), REG_VPHY_IND_CTRL__2, value, !(value & VPHY_IND_BUSY), 10, 1000); if (ret < 0) { diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c index 9bc54e1348cb9bb8164f74a54bc76f345c90411a..38b3c6dda386ad6855255fa29c1e0bc400ebe1d6 100644 --- a/drivers/net/dsa/mt7530.c +++ b/drivers/net/dsa/mt7530.c @@ -399,6 +399,20 @@ static void mt7530_pll_setup(struct mt7530_priv *priv) core_set(priv, CORE_TRGMII_GSW_CLK_CG, REG_GSWCK_EN); } +/* If port 6 is available as a CPU port, always prefer that as the default, + * otherwise don't care. + */ +static struct dsa_port * +mt753x_preferred_default_local_cpu_port(struct dsa_switch *ds) +{ + struct dsa_port *cpu_dp = dsa_to_port(ds, 6); + + if (dsa_port_is_cpu(cpu_dp)) + return cpu_dp; + + return NULL; +} + /* Setup port 6 interface mode and TRGMII TX circuit */ static int mt7530_pad_clk_setup(struct dsa_switch *ds, phy_interface_t interface) @@ -985,6 +999,18 @@ static void mt7530_setup_port5(struct dsa_switch *ds, phy_interface_t interface) mutex_unlock(&priv->reg_mutex); } +static void +mt753x_trap_frames(struct mt7530_priv *priv) +{ + /* Trap BPDUs to the CPU port(s) */ + mt7530_rmw(priv, MT753X_BPC, MT753X_BPDU_PORT_FW_MASK, + MT753X_BPDU_CPU_ONLY); + + /* Trap LLDP frames with :0E MAC DA to the CPU port(s) */ + mt7530_rmw(priv, MT753X_RGAC2, MT753X_R0E_PORT_FW_MASK, + MT753X_R0E_PORT_FW(MT753X_BPDU_CPU_ONLY)); +} + static int mt753x_cpu_port_enable(struct dsa_switch *ds, int port) { @@ -1007,9 +1033,16 @@ mt753x_cpu_port_enable(struct dsa_switch *ds, int port) UNU_FFP(BIT(port))); /* Set CPU port number */ - if (priv->id == ID_MT7621) + if (priv->id == ID_MT7530 || priv->id == ID_MT7621) mt7530_rmw(priv, MT7530_MFC, CPU_MASK, CPU_EN | CPU_PORT(port)); + /* Add the CPU port to the CPU port bitmap for MT7531 and the switch on + * the MT7988 SoC. Trapped frames will be forwarded to the CPU port that + * is affine to the inbound user port. + */ + if (priv->id == ID_MT7531 || priv->id == ID_MT7988) + mt7530_set(priv, MT7531_CFC, MT7531_CPU_PMAP(BIT(port))); + /* CPU port gets connected to all user ports of * the switch. */ @@ -2255,6 +2288,8 @@ mt7530_setup(struct dsa_switch *ds) priv->p6_interface = PHY_INTERFACE_MODE_NA; + mt753x_trap_frames(priv); + /* Enable and reset MIB counters */ mt7530_mib_reset(ds); @@ -2352,17 +2387,9 @@ static int mt7531_setup_common(struct dsa_switch *ds) { struct mt7530_priv *priv = ds->priv; - struct dsa_port *cpu_dp; int ret, i; - /* BPDU to CPU port */ - dsa_switch_for_each_cpu_port(cpu_dp, ds) { - mt7530_rmw(priv, MT7531_CFC, MT7531_CPU_PMAP_MASK, - BIT(cpu_dp->index)); - break; - } - mt7530_rmw(priv, MT753X_BPC, MT753X_BPDU_PORT_FW_MASK, - MT753X_BPDU_CPU_ONLY); + mt753x_trap_frames(priv); /* Enable and reset MIB counters */ mt7530_mib_reset(ds); @@ -2978,7 +3005,7 @@ static void mt7530_pcs_get_state(struct phylink_pcs *pcs, state->pause |= MLO_PAUSE_TX; } -static int mt753x_pcs_config(struct phylink_pcs *pcs, unsigned int mode, +static int mt753x_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode, phy_interface_t interface, const unsigned long *advertising, bool permit_pause_to_mac) @@ -3006,6 +3033,7 @@ mt753x_setup(struct dsa_switch *ds) /* Initialise the PCS devices */ for (i = 0; i < priv->ds->num_ports; i++) { priv->pcs[i].pcs.ops = priv->info->pcs_ops; + priv->pcs[i].pcs.neg_mode = true; priv->pcs[i].priv = priv; priv->pcs[i].port = i; } @@ -3085,6 +3113,7 @@ static int mt7988_setup(struct dsa_switch *ds) const struct dsa_switch_ops mt7530_switch_ops = { .get_tag_protocol = mtk_get_tag_protocol, .setup = mt753x_setup, + .preferred_default_local_cpu_port = mt753x_preferred_default_local_cpu_port, .get_strings = mt7530_get_strings, .get_ethtool_stats = mt7530_get_ethtool_stats, .get_sset_count = mt7530_get_sset_count, diff --git a/drivers/net/dsa/mt7530.h b/drivers/net/dsa/mt7530.h index 5084f48a886913821cff0ba2e14fbba802e54bdf..08045b035e6ab02cd0396cca9e6d7aaa9d294fb4 100644 --- a/drivers/net/dsa/mt7530.h +++ b/drivers/net/dsa/mt7530.h @@ -54,6 +54,7 @@ enum mt753x_id { #define MT7531_MIRROR_PORT_GET(x) (((x) >> 16) & MIRROR_MASK) #define MT7531_MIRROR_PORT_SET(x) (((x) & MIRROR_MASK) << 16) #define MT7531_CPU_PMAP_MASK GENMASK(7, 0) +#define MT7531_CPU_PMAP(x) FIELD_PREP(MT7531_CPU_PMAP_MASK, x) #define MT753X_MIRROR_REG(id) ((((id) == ID_MT7531) || ((id) == ID_MT7988)) ? \ MT7531_CFC : MT7530_MFC) @@ -66,6 +67,11 @@ enum mt753x_id { #define MT753X_BPC 0x24 #define MT753X_BPDU_PORT_FW_MASK GENMASK(2, 0) +/* Register for :03 and :0E MAC DA frame control */ +#define MT753X_RGAC2 0x2c +#define MT753X_R0E_PORT_FW_MASK GENMASK(18, 16) +#define MT753X_R0E_PORT_FW(x) FIELD_PREP(MT753X_R0E_PORT_FW_MASK, x) + enum mt753x_bpdu_port_fw { MT753X_BPDU_FOLLOW_MFC, MT753X_BPDU_CPU_EXCLUDE = 4, diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 08a46ffd53af99524dc751dd05f2dbece4a6d71f..8b51756bd80544c5a5a0a2b0fac532a5b7928540 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -463,11 +463,11 @@ static int mv88e6xxx_port_setup_mac(struct mv88e6xxx_chip *chip, int port, return err; } -static int mv88e6xxx_phy_is_internal(struct dsa_switch *ds, int port) +static int mv88e6xxx_phy_is_internal(struct mv88e6xxx_chip *chip, int port) { - struct mv88e6xxx_chip *chip = ds->priv; - - return port < chip->info->num_internal_phys; + return port >= chip->info->internal_phys_offset && + port < chip->info->num_internal_phys + + chip->info->internal_phys_offset; } static int mv88e6xxx_port_ppu_updates(struct mv88e6xxx_chip *chip, int port) @@ -479,7 +479,7 @@ static int mv88e6xxx_port_ppu_updates(struct mv88e6xxx_chip *chip, int port) * report whether the port is internal. */ if (chip->info->family == MV88E6XXX_FAMILY_6250) - return port < chip->info->num_internal_phys; + return mv88e6xxx_phy_is_internal(chip, port); err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_STS, ®); if (err) { @@ -584,7 +584,7 @@ static void mv88e6095_phylink_get_caps(struct mv88e6xxx_chip *chip, int port, config->mac_capabilities = MAC_SYM_PAUSE | MAC_10 | MAC_100; - if (mv88e6xxx_phy_is_internal(chip->ds, port)) { + if (mv88e6xxx_phy_is_internal(chip, port)) { __set_bit(PHY_INTERFACE_MODE_MII, config->supported_interfaces); } else { if (cmode < ARRAY_SIZE(mv88e6185_phy_interface_modes) && @@ -790,6 +790,8 @@ static void mv88e6393x_phylink_get_caps(struct mv88e6xxx_chip *chip, int port, unsigned long *supported = config->supported_interfaces; bool is_6191x = chip->info->prod_num == MV88E6XXX_PORT_SWITCH_ID_PROD_6191X; + bool is_6361 = + chip->info->prod_num == MV88E6XXX_PORT_SWITCH_ID_PROD_6361; mv88e6xxx_translate_cmode(chip->ports[port].cmode, supported); @@ -804,13 +806,16 @@ static void mv88e6393x_phylink_get_caps(struct mv88e6xxx_chip *chip, int port, /* 6191X supports >1G modes only on port 10 */ if (!is_6191x || port == 10) { __set_bit(PHY_INTERFACE_MODE_2500BASEX, supported); - __set_bit(PHY_INTERFACE_MODE_5GBASER, supported); - __set_bit(PHY_INTERFACE_MODE_10GBASER, supported); - /* FIXME: USXGMII is not supported yet */ - /* __set_bit(PHY_INTERFACE_MODE_USXGMII, supported); */ - - config->mac_capabilities |= MAC_2500FD | MAC_5000FD | - MAC_10000FD; + config->mac_capabilities |= MAC_2500FD; + + /* 6361 only supports up to 2500BaseX */ + if (!is_6361) { + __set_bit(PHY_INTERFACE_MODE_5GBASER, supported); + __set_bit(PHY_INTERFACE_MODE_10GBASER, supported); + __set_bit(PHY_INTERFACE_MODE_USXGMII, supported); + config->mac_capabilities |= MAC_5000FD | + MAC_10000FD; + } } } @@ -832,7 +837,7 @@ static void mv88e6xxx_get_caps(struct dsa_switch *ds, int port, chip->info->ops->phylink_get_caps(chip, port, config); mv88e6xxx_reg_unlock(chip); - if (mv88e6xxx_phy_is_internal(ds, port)) { + if (mv88e6xxx_phy_is_internal(chip, port)) { __set_bit(PHY_INTERFACE_MODE_INTERNAL, config->supported_interfaces); /* Internal ports with no phy-mode need GMII for PHYLIB */ @@ -841,29 +846,38 @@ static void mv88e6xxx_get_caps(struct dsa_switch *ds, int port, } } +static int mv88e6xxx_mac_prepare(struct dsa_switch *ds, int port, + unsigned int mode, phy_interface_t interface) +{ + struct mv88e6xxx_chip *chip = ds->priv; + int err = 0; + + /* In inband mode, the link may come up at any time while the link + * is not forced down. Force the link down while we reconfigure the + * interface mode. + */ + if (mode == MLO_AN_INBAND && + chip->ports[port].interface != interface && + chip->info->ops->port_set_link) { + mv88e6xxx_reg_lock(chip); + err = chip->info->ops->port_set_link(chip, port, + LINK_FORCED_DOWN); + mv88e6xxx_reg_unlock(chip); + } + + return err; +} + static void mv88e6xxx_mac_config(struct dsa_switch *ds, int port, unsigned int mode, const struct phylink_link_state *state) { struct mv88e6xxx_chip *chip = ds->priv; - struct mv88e6xxx_port *p; int err = 0; - p = &chip->ports[port]; - mv88e6xxx_reg_lock(chip); - if (mode != MLO_AN_PHY || !mv88e6xxx_phy_is_internal(ds, port)) { - /* In inband mode, the link may come up at any time while the - * link is not forced down. Force the link down while we - * reconfigure the interface mode. - */ - if (mode == MLO_AN_INBAND && - p->interface != state->interface && - chip->info->ops->port_set_link) - chip->info->ops->port_set_link(chip, port, - LINK_FORCED_DOWN); - + if (mode != MLO_AN_PHY || !mv88e6xxx_phy_is_internal(chip, port)) { err = mv88e6xxx_port_config_interface(chip, port, state->interface); if (err && err != -EOPNOTSUPP) @@ -880,24 +894,38 @@ static void mv88e6xxx_mac_config(struct dsa_switch *ds, int port, err = 0; } +err_unlock: + mv88e6xxx_reg_unlock(chip); + + if (err && err != -EOPNOTSUPP) + dev_err(ds->dev, "p%d: failed to configure MAC/PCS\n", port); +} + +static int mv88e6xxx_mac_finish(struct dsa_switch *ds, int port, + unsigned int mode, phy_interface_t interface) +{ + struct mv88e6xxx_chip *chip = ds->priv; + int err = 0; + /* Undo the forced down state above after completing configuration * irrespective of its state on entry, which allows the link to come * up in the in-band case where there is no separate SERDES. Also * ensure that the link can come up if the PPU is in use and we are * in PHY mode (we treat the PPU as an effective in-band mechanism.) */ + mv88e6xxx_reg_lock(chip); + if (chip->info->ops->port_set_link && - ((mode == MLO_AN_INBAND && p->interface != state->interface) || + ((mode == MLO_AN_INBAND && + chip->ports[port].interface != interface) || (mode == MLO_AN_PHY && mv88e6xxx_port_ppu_updates(chip, port)))) - chip->info->ops->port_set_link(chip, port, LINK_UNFORCED); - - p->interface = state->interface; + err = chip->info->ops->port_set_link(chip, port, LINK_UNFORCED); -err_unlock: mv88e6xxx_reg_unlock(chip); - if (err && err != -EOPNOTSUPP) - dev_err(ds->dev, "p%d: failed to configure MAC/PCS\n", port); + chip->ports[port].interface = interface; + + return err; } static void mv88e6xxx_mac_link_down(struct dsa_switch *ds, int port, @@ -3311,7 +3339,7 @@ static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port) caps = pl_config.mac_capabilities; if (chip->info->ops->port_max_speed_mode) - mode = chip->info->ops->port_max_speed_mode(port); + mode = chip->info->ops->port_max_speed_mode(chip, port); else mode = PHY_INTERFACE_MODE_NA; @@ -5043,6 +5071,7 @@ static const struct mv88e6xxx_ops mv88e6250_ops = { .avb_ops = &mv88e6352_avb_ops, .ptp_ops = &mv88e6250_ptp_ops, .phylink_get_caps = mv88e6250_phylink_get_caps, + .set_max_frame_size = mv88e6185_g1_set_max_frame_size, }; static const struct mv88e6xxx_ops mv88e6290_ops = { @@ -5642,6 +5671,46 @@ static const struct mv88e6xxx_ops mv88e6393x_ops = { }; static const struct mv88e6xxx_info mv88e6xxx_table[] = { + [MV88E6020] = { + .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6020, + .family = MV88E6XXX_FAMILY_6250, + .name = "Marvell 88E6020", + .num_databases = 64, + .num_ports = 4, + .num_internal_phys = 2, + .max_vid = 4095, + .port_base_addr = 0x8, + .phy_base_addr = 0x0, + .global1_addr = 0xf, + .global2_addr = 0x7, + .age_time_coeff = 15000, + .g1_irqs = 9, + .g2_irqs = 5, + .atu_move_port_mask = 0xf, + .dual_chip = true, + .ops = &mv88e6250_ops, + }, + + [MV88E6071] = { + .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6071, + .family = MV88E6XXX_FAMILY_6250, + .name = "Marvell 88E6071", + .num_databases = 64, + .num_ports = 7, + .num_internal_phys = 5, + .max_vid = 4095, + .port_base_addr = 0x08, + .phy_base_addr = 0x00, + .global1_addr = 0x0f, + .global2_addr = 0x07, + .age_time_coeff = 15000, + .g1_irqs = 9, + .g2_irqs = 5, + .atu_move_port_mask = 0xf, + .dual_chip = true, + .ops = &mv88e6250_ops, + }, + [MV88E6085] = { .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6085, .family = MV88E6XXX_FAMILY_6097, @@ -6024,7 +6093,8 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { .name = "Marvell 88E6191X", .num_databases = 4096, .num_ports = 11, /* 10 + Z80 */ - .num_internal_phys = 9, + .num_internal_phys = 8, + .internal_phys_offset = 1, .max_vid = 8191, .max_sid = 63, .port_base_addr = 0x0, @@ -6047,7 +6117,8 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { .name = "Marvell 88E6193X", .num_databases = 4096, .num_ports = 11, /* 10 + Z80 */ - .num_internal_phys = 9, + .num_internal_phys = 8, + .internal_phys_offset = 1, .max_vid = 8191, .max_sid = 63, .port_base_addr = 0x0, @@ -6309,6 +6380,32 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { .ptp_support = true, .ops = &mv88e6352_ops, }, + [MV88E6361] = { + .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6361, + .family = MV88E6XXX_FAMILY_6393, + .name = "Marvell 88E6361", + .num_databases = 4096, + .num_macs = 16384, + .num_ports = 11, + /* Ports 1, 2 and 8 are not routed */ + .invalid_port_mask = BIT(1) | BIT(2) | BIT(8), + .num_internal_phys = 5, + .internal_phys_offset = 3, + .max_vid = 4095, + .max_sid = 63, + .port_base_addr = 0x0, + .phy_base_addr = 0x0, + .global1_addr = 0x1b, + .global2_addr = 0x1c, + .age_time_coeff = 3750, + .g1_irqs = 10, + .g2_irqs = 14, + .atu_move_port_mask = 0x1f, + .pvt = true, + .multi_chip = true, + .ptp_support = true, + .ops = &mv88e6393x_ops, + }, [MV88E6390] = { .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6390, .family = MV88E6XXX_FAMILY_6390, @@ -6366,7 +6463,8 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { .name = "Marvell 88E6393X", .num_databases = 4096, .num_ports = 11, /* 10 + Z80 */ - .num_internal_phys = 9, + .num_internal_phys = 8, + .internal_phys_offset = 1, .max_vid = 8191, .max_sid = 63, .port_base_addr = 0x0, @@ -7002,7 +7100,9 @@ static const struct dsa_switch_ops mv88e6xxx_switch_ops = { .port_teardown = mv88e6xxx_port_teardown, .phylink_get_caps = mv88e6xxx_get_caps, .phylink_mac_link_state = mv88e6xxx_serdes_pcs_get_state, + .phylink_mac_prepare = mv88e6xxx_mac_prepare, .phylink_mac_config = mv88e6xxx_mac_config, + .phylink_mac_finish = mv88e6xxx_mac_finish, .phylink_mac_an_restart = mv88e6xxx_serdes_pcs_an_restart, .phylink_mac_link_down = mv88e6xxx_mac_link_down, .phylink_mac_link_up = mv88e6xxx_mac_link_up, diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/chip.h index da6e1339f809fc98924c06227bfc9fdf1b562c9a..0ad34b2d89137fb0d134e412063c0a59a84f8c60 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.h +++ b/drivers/net/dsa/mv88e6xxx/chip.h @@ -54,6 +54,8 @@ enum mv88e6xxx_frame_mode { /* List of supported models */ enum mv88e6xxx_model { + MV88E6020, + MV88E6071, MV88E6085, MV88E6095, MV88E6097, @@ -82,6 +84,7 @@ enum mv88e6xxx_model { MV88E6350, MV88E6351, MV88E6352, + MV88E6361, MV88E6390, MV88E6390X, MV88E6393X, @@ -94,13 +97,13 @@ enum mv88e6xxx_family { MV88E6XXX_FAMILY_6097, /* 6046 6085 6096 6097 */ MV88E6XXX_FAMILY_6165, /* 6123 6161 6165 */ MV88E6XXX_FAMILY_6185, /* 6108 6121 6122 6131 6152 6155 6182 6185 */ - MV88E6XXX_FAMILY_6250, /* 6220 6250 */ + MV88E6XXX_FAMILY_6250, /* 6220 6250 6020 6071 */ MV88E6XXX_FAMILY_6320, /* 6320 6321 */ MV88E6XXX_FAMILY_6341, /* 6141 6341 */ MV88E6XXX_FAMILY_6351, /* 6171 6175 6350 6351 */ MV88E6XXX_FAMILY_6352, /* 6172 6176 6240 6352 */ MV88E6XXX_FAMILY_6390, /* 6190 6190X 6191 6290 6390 6390X */ - MV88E6XXX_FAMILY_6393, /* 6191X 6193X 6393X */ + MV88E6XXX_FAMILY_6393, /* 6191X 6193X 6361 6393X */ }; /** @@ -167,6 +170,11 @@ struct mv88e6xxx_info { /* Supports PTP */ bool ptp_support; + + /* Internal PHY start index. 0 means that internal PHYs range starts at + * port 0, 1 means internal PHYs range starts at port 1, etc + */ + unsigned int internal_phys_offset; }; struct mv88e6xxx_atu_entry { @@ -513,7 +521,8 @@ struct mv88e6xxx_ops { int speed, int duplex); /* What interface mode should be used for maximum speed? */ - phy_interface_t (*port_max_speed_mode)(int port); + phy_interface_t (*port_max_speed_mode)(struct mv88e6xxx_chip *chip, + int port); int (*port_tag_remap)(struct mv88e6xxx_chip *chip, int port); diff --git a/drivers/net/dsa/mv88e6xxx/global2.c b/drivers/net/dsa/mv88e6xxx/global2.c index 61589689307682c6bf59bef040c3d438088228a8..937a01f2ba75ebe0e89e419da93a0b937352cb68 100644 --- a/drivers/net/dsa/mv88e6xxx/global2.c +++ b/drivers/net/dsa/mv88e6xxx/global2.c @@ -1196,9 +1196,12 @@ int mv88e6xxx_g2_irq_setup(struct mv88e6xxx_chip *chip) int mv88e6xxx_g2_irq_mdio_setup(struct mv88e6xxx_chip *chip, struct mii_bus *bus) { + int phy_start = chip->info->internal_phys_offset; + int phy_end = chip->info->internal_phys_offset + + chip->info->num_internal_phys; int phy, irq; - for (phy = 0; phy < chip->info->num_internal_phys; phy++) { + for (phy = phy_start; phy < phy_end; phy++) { irq = irq_find_mapping(chip->g2_irq.domain, phy); if (irq < 0) return irq; diff --git a/drivers/net/dsa/mv88e6xxx/port.c b/drivers/net/dsa/mv88e6xxx/port.c index f79cf716c541f0b63d09fa77256a205e6f45a0d1..dd66ec902d4cb512df969471535c0d4d68d250c3 100644 --- a/drivers/net/dsa/mv88e6xxx/port.c +++ b/drivers/net/dsa/mv88e6xxx/port.c @@ -342,7 +342,8 @@ int mv88e6341_port_set_speed_duplex(struct mv88e6xxx_chip *chip, int port, duplex); } -phy_interface_t mv88e6341_port_max_speed_mode(int port) +phy_interface_t mv88e6341_port_max_speed_mode(struct mv88e6xxx_chip *chip, + int port) { if (port == 5) return PHY_INTERFACE_MODE_2500BASEX; @@ -381,7 +382,8 @@ int mv88e6390_port_set_speed_duplex(struct mv88e6xxx_chip *chip, int port, duplex); } -phy_interface_t mv88e6390_port_max_speed_mode(int port) +phy_interface_t mv88e6390_port_max_speed_mode(struct mv88e6xxx_chip *chip, + int port) { if (port == 9 || port == 10) return PHY_INTERFACE_MODE_2500BASEX; @@ -403,7 +405,8 @@ int mv88e6390x_port_set_speed_duplex(struct mv88e6xxx_chip *chip, int port, duplex); } -phy_interface_t mv88e6390x_port_max_speed_mode(int port) +phy_interface_t mv88e6390x_port_max_speed_mode(struct mv88e6xxx_chip *chip, + int port) { if (port == 9 || port == 10) return PHY_INTERFACE_MODE_XAUI; @@ -421,6 +424,10 @@ int mv88e6393x_port_set_speed_duplex(struct mv88e6xxx_chip *chip, int port, u16 reg, ctrl; int err; + if (chip->info->prod_num == MV88E6XXX_PORT_SWITCH_ID_PROD_6361 && + speed > 2500) + return -EOPNOTSUPP; + if (speed == 200 && port != 0) return -EOPNOTSUPP; @@ -500,12 +507,17 @@ int mv88e6393x_port_set_speed_duplex(struct mv88e6xxx_chip *chip, int port, return 0; } -phy_interface_t mv88e6393x_port_max_speed_mode(int port) +phy_interface_t mv88e6393x_port_max_speed_mode(struct mv88e6xxx_chip *chip, + int port) { - if (port == 0 || port == 9 || port == 10) - return PHY_INTERFACE_MODE_10GBASER; - return PHY_INTERFACE_MODE_NA; + if (port != 0 && port != 9 && port != 10) + return PHY_INTERFACE_MODE_NA; + + if (chip->info->prod_num == MV88E6XXX_PORT_SWITCH_ID_PROD_6361) + return PHY_INTERFACE_MODE_2500BASEX; + + return PHY_INTERFACE_MODE_10GBASER; } static int mv88e6xxx_port_set_cmode(struct mv88e6xxx_chip *chip, int port, @@ -554,6 +566,9 @@ static int mv88e6xxx_port_set_cmode(struct mv88e6xxx_chip *chip, int port, case PHY_INTERFACE_MODE_10GBASER: cmode = MV88E6393X_PORT_STS_CMODE_10GBASER; break; + case PHY_INTERFACE_MODE_USXGMII: + cmode = MV88E6393X_PORT_STS_CMODE_USXGMII; + break; default: cmode = 0; } diff --git a/drivers/net/dsa/mv88e6xxx/port.h b/drivers/net/dsa/mv88e6xxx/port.h index d19b6303b91f0aafc6924d6098a93f93fc07213c..86deeb347cbc1d82526f362f719c57ac17039bf0 100644 --- a/drivers/net/dsa/mv88e6xxx/port.h +++ b/drivers/net/dsa/mv88e6xxx/port.h @@ -111,6 +111,8 @@ /* Offset 0x03: Switch Identifier Register */ #define MV88E6XXX_PORT_SWITCH_ID 0x03 #define MV88E6XXX_PORT_SWITCH_ID_PROD_MASK 0xfff0 +#define MV88E6XXX_PORT_SWITCH_ID_PROD_6020 0x0200 +#define MV88E6XXX_PORT_SWITCH_ID_PROD_6071 0x0710 #define MV88E6XXX_PORT_SWITCH_ID_PROD_6085 0x04a0 #define MV88E6XXX_PORT_SWITCH_ID_PROD_6095 0x0950 #define MV88E6XXX_PORT_SWITCH_ID_PROD_6097 0x0990 @@ -133,6 +135,7 @@ #define MV88E6XXX_PORT_SWITCH_ID_PROD_6220 0x2200 #define MV88E6XXX_PORT_SWITCH_ID_PROD_6240 0x2400 #define MV88E6XXX_PORT_SWITCH_ID_PROD_6250 0x2500 +#define MV88E6XXX_PORT_SWITCH_ID_PROD_6361 0x2610 #define MV88E6XXX_PORT_SWITCH_ID_PROD_6290 0x2900 #define MV88E6XXX_PORT_SWITCH_ID_PROD_6321 0x3100 #define MV88E6XXX_PORT_SWITCH_ID_PROD_6141 0x3400 @@ -359,10 +362,14 @@ int mv88e6390x_port_set_speed_duplex(struct mv88e6xxx_chip *chip, int port, int mv88e6393x_port_set_speed_duplex(struct mv88e6xxx_chip *chip, int port, int speed, int duplex); -phy_interface_t mv88e6341_port_max_speed_mode(int port); -phy_interface_t mv88e6390_port_max_speed_mode(int port); -phy_interface_t mv88e6390x_port_max_speed_mode(int port); -phy_interface_t mv88e6393x_port_max_speed_mode(int port); +phy_interface_t mv88e6341_port_max_speed_mode(struct mv88e6xxx_chip *chip, + int port); +phy_interface_t mv88e6390_port_max_speed_mode(struct mv88e6xxx_chip *chip, + int port); +phy_interface_t mv88e6390x_port_max_speed_mode(struct mv88e6xxx_chip *chip, + int port); +phy_interface_t mv88e6393x_port_max_speed_mode(struct mv88e6xxx_chip *chip, + int port); int mv88e6xxx_port_set_state(struct mv88e6xxx_chip *chip, int port, u8 state); diff --git a/drivers/net/dsa/mv88e6xxx/serdes.c b/drivers/net/dsa/mv88e6xxx/serdes.c index 72faec8f44dcaee9abe666fbc3ae23e15671114c..80167d53212f8b226994456bbdbd5b8db34c62df 100644 --- a/drivers/net/dsa/mv88e6xxx/serdes.c +++ b/drivers/net/dsa/mv88e6xxx/serdes.c @@ -683,7 +683,8 @@ int mv88e6393x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port) cmode == MV88E6XXX_PORT_STS_CMODE_SGMII || cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX || cmode == MV88E6393X_PORT_STS_CMODE_5GBASER || - cmode == MV88E6393X_PORT_STS_CMODE_10GBASER) + cmode == MV88E6393X_PORT_STS_CMODE_10GBASER || + cmode == MV88E6393X_PORT_STS_CMODE_USXGMII) lane = port; return lane; @@ -984,7 +985,42 @@ static int mv88e6393x_serdes_pcs_get_state_10g(struct mv88e6xxx_chip *chip, state->speed = SPEED_10000; state->duplex = DUPLEX_FULL; } + return 0; +} + +/* USXGMII registers for Marvell switch 88e639x are undocumented and this function is based + * on some educated guesses. It appears that there are no status bits related to + * autonegotiation complete or flow control. + */ +static int mv88e639x_serdes_pcs_get_state_usxgmii(struct mv88e6xxx_chip *chip, + int port, int lane, + struct phylink_link_state *state) +{ + u16 status, lp_status; + int err; + err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, + MV88E6390_USXGMII_PHY_STATUS, &status); + if (err) { + dev_err(chip->dev, "can't read Serdes USXGMII PHY status: %d\n", err); + return err; + } + dev_dbg(chip->dev, "USXGMII PHY status: 0x%x\n", status); + + state->link = !!(status & MDIO_USXGMII_LINK); + state->an_complete = state->link; + + if (state->link) { + err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, + MV88E6390_USXGMII_LP_STATUS, &lp_status); + if (err) { + dev_err(chip->dev, "can't read Serdes USXGMII LP status: %d\n", err); + return err; + } + dev_dbg(chip->dev, "USXGMII LP status: 0x%x\n", lp_status); + /* lp_status appears to include the "link" bit as per USXGMII spec. */ + phylink_decode_usxgmii_word(state, lp_status); + } return 0; } @@ -1020,6 +1056,9 @@ int mv88e6393x_serdes_pcs_get_state(struct mv88e6xxx_chip *chip, int port, case PHY_INTERFACE_MODE_10GBASER: return mv88e6393x_serdes_pcs_get_state_10g(chip, port, lane, state); + case PHY_INTERFACE_MODE_USXGMII: + return mv88e639x_serdes_pcs_get_state_usxgmii(chip, port, lane, + state); default: return -EOPNOTSUPP; @@ -1173,6 +1212,7 @@ int mv88e6393x_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port, return mv88e6390_serdes_irq_enable_sgmii(chip, lane, enable); case MV88E6393X_PORT_STS_CMODE_5GBASER: case MV88E6393X_PORT_STS_CMODE_10GBASER: + case MV88E6393X_PORT_STS_CMODE_USXGMII: return mv88e6393x_serdes_irq_enable_10g(chip, lane, enable); } @@ -1213,6 +1253,7 @@ irqreturn_t mv88e6393x_serdes_irq_status(struct mv88e6xxx_chip *chip, int port, break; case MV88E6393X_PORT_STS_CMODE_5GBASER: case MV88E6393X_PORT_STS_CMODE_10GBASER: + case MV88E6393X_PORT_STS_CMODE_USXGMII: err = mv88e6393x_serdes_irq_status_10g(chip, lane, &status); if (err) return err; @@ -1477,7 +1518,8 @@ static int mv88e6393x_serdes_erratum_5_2(struct mv88e6xxx_chip *chip, int lane, * to SERDES operating in 10G mode. These registers only apply to 10G * operation and have no effect on other speeds. */ - if (cmode != MV88E6393X_PORT_STS_CMODE_10GBASER) + if (cmode != MV88E6393X_PORT_STS_CMODE_10GBASER && + cmode != MV88E6393X_PORT_STS_CMODE_USXGMII) return 0; for (i = 0; i < ARRAY_SIZE(fixes); ++i) { @@ -1582,6 +1624,7 @@ int mv88e6393x_serdes_power(struct mv88e6xxx_chip *chip, int port, int lane, break; case MV88E6393X_PORT_STS_CMODE_5GBASER: case MV88E6393X_PORT_STS_CMODE_10GBASER: + case MV88E6393X_PORT_STS_CMODE_USXGMII: err = mv88e6390_serdes_power_10g(chip, lane, on); break; default: diff --git a/drivers/net/dsa/mv88e6xxx/serdes.h b/drivers/net/dsa/mv88e6xxx/serdes.h index 29bb4e91e2f6be1715e0a2f47b15c099a7cc329a..e245687ddb1d0a919cc442eecf6575983cd2981a 100644 --- a/drivers/net/dsa/mv88e6xxx/serdes.h +++ b/drivers/net/dsa/mv88e6xxx/serdes.h @@ -48,6 +48,10 @@ #define MV88E6393X_10G_INT_LINK_CHANGE BIT(2) #define MV88E6393X_10G_INT_STATUS 0x9001 +/* USXGMII */ +#define MV88E6390_USXGMII_LP_STATUS 0xf0a2 +#define MV88E6390_USXGMII_PHY_STATUS 0xf0a6 + /* 1000BASE-X and SGMII */ #define MV88E6390_SGMII_BMCR (0x2000 + MII_BMCR) #define MV88E6390_SGMII_BMSR (0x2000 + MII_BMSR) diff --git a/drivers/net/dsa/ocelot/felix.c b/drivers/net/dsa/ocelot/felix.c index 80861ac090ae3c419a126eac08a8d8d371ee422a..8da46d284e35649a7b68a4148593e2a03aa5d8c7 100644 --- a/drivers/net/dsa/ocelot/felix.c +++ b/drivers/net/dsa/ocelot/felix.c @@ -1286,7 +1286,6 @@ static int felix_parse_ports_node(struct felix *felix, if (err < 0) { dev_info(dev, "Unsupported PHY mode %s on port %d\n", phy_modes(phy_mode), port); - of_node_put(child); /* Leave port_phy_modes[port] = 0, which is also * PHY_INTERFACE_MODE_NA. This will perform a @@ -1725,6 +1724,18 @@ static bool felix_rxtstamp(struct dsa_switch *ds, int port, u32 tstamp_hi; u64 tstamp; + switch (type & PTP_CLASS_PMASK) { + case PTP_CLASS_L2: + if (!(ocelot->ports[port]->trap_proto & OCELOT_PROTO_PTP_L2)) + return false; + break; + case PTP_CLASS_IPV4: + case PTP_CLASS_IPV6: + if (!(ocelot->ports[port]->trap_proto & OCELOT_PROTO_PTP_L4)) + return false; + break; + } + /* If the "no XTR IRQ" workaround is in use, tell DSA to defer this skb * for RX timestamping. Then free it, and poll for its copy through * MMIO in the CPU port module, and inject that into the stack from @@ -1774,16 +1785,15 @@ static int felix_change_mtu(struct dsa_switch *ds, int port, int new_mtu) { struct ocelot *ocelot = ds->priv; struct ocelot_port *ocelot_port = ocelot->ports[port]; - struct felix *felix = ocelot_to_felix(ocelot); ocelot_port_set_maxlen(ocelot, port, new_mtu); - mutex_lock(&ocelot->tas_lock); + mutex_lock(&ocelot->fwd_domain_lock); - if (ocelot_port->taprio && felix->info->tas_guard_bands_update) - felix->info->tas_guard_bands_update(ocelot, port); + if (ocelot_port->taprio && ocelot->ops->tas_guard_bands_update) + ocelot->ops->tas_guard_bands_update(ocelot, port); - mutex_unlock(&ocelot->tas_lock); + mutex_unlock(&ocelot->fwd_domain_lock); return 0; } diff --git a/drivers/net/dsa/ocelot/felix.h b/drivers/net/dsa/ocelot/felix.h index 96008c046da5361578b33f6a080769a9769a36ad..1d4befe7cfe8e06044d401f715f34b95edbdca0c 100644 --- a/drivers/net/dsa/ocelot/felix.h +++ b/drivers/net/dsa/ocelot/felix.h @@ -57,7 +57,6 @@ struct felix_info { void (*mdio_bus_free)(struct ocelot *ocelot); int (*port_setup_tc)(struct dsa_switch *ds, int port, enum tc_setup_type type, void *type_data); - void (*tas_guard_bands_update)(struct ocelot *ocelot, int port); void (*port_sched_speed_set)(struct ocelot *ocelot, int port, u32 speed); void (*phylink_mac_config)(struct ocelot *ocelot, int port, diff --git a/drivers/net/dsa/ocelot/felix_vsc9959.c b/drivers/net/dsa/ocelot/felix_vsc9959.c index d172a3e9736c426516e687e6f99ae1302c2c73d6..1c113957fcf45f44a8d4ba38e762e88e10c63712 100644 --- a/drivers/net/dsa/ocelot/felix_vsc9959.c +++ b/drivers/net/dsa/ocelot/felix_vsc9959.c @@ -1021,7 +1021,6 @@ static int vsc9959_mdio_bus_alloc(struct ocelot *ocelot) for (port = 0; port < felix->info->num_ports; port++) { struct ocelot_port *ocelot_port = ocelot->ports[port]; struct phylink_pcs *phylink_pcs; - struct mdio_device *mdio_device; if (dsa_is_unused_port(felix->ds, port)) continue; @@ -1029,16 +1028,10 @@ static int vsc9959_mdio_bus_alloc(struct ocelot *ocelot) if (ocelot_port->phy_mode == PHY_INTERFACE_MODE_INTERNAL) continue; - mdio_device = mdio_device_create(felix->imdio, port); - if (IS_ERR(mdio_device)) + phylink_pcs = lynx_pcs_create_mdiodev(felix->imdio, port); + if (IS_ERR(phylink_pcs)) continue; - phylink_pcs = lynx_pcs_create(mdio_device); - if (!phylink_pcs) { - mdio_device_free(mdio_device); - continue; - } - felix->pcs[port] = phylink_pcs; dev_info(dev, "Found PCS at internal MDIO address %d\n", port); @@ -1054,14 +1047,9 @@ static void vsc9959_mdio_bus_free(struct ocelot *ocelot) for (port = 0; port < ocelot->num_phys_ports; port++) { struct phylink_pcs *phylink_pcs = felix->pcs[port]; - struct mdio_device *mdio_device; - - if (!phylink_pcs) - continue; - mdio_device = lynx_get_mdio_device(phylink_pcs); - mdio_device_free(mdio_device); - lynx_pcs_destroy(phylink_pcs); + if (phylink_pcs) + lynx_pcs_destroy(phylink_pcs); } mdiobus_unregister(felix->imdio); mdiobus_free(felix->imdio); @@ -1221,15 +1209,17 @@ static u32 vsc9959_tas_tc_max_sdu(struct tc_taprio_qopt_offload *taprio, int tc) static void vsc9959_tas_guard_bands_update(struct ocelot *ocelot, int port) { struct ocelot_port *ocelot_port = ocelot->ports[port]; + struct ocelot_mm_state *mm = &ocelot->mm[port]; struct tc_taprio_qopt_offload *taprio; u64 min_gate_len[OCELOT_NUM_TC]; + u32 val, maxlen, add_frag_size; + u64 needed_min_frag_time_ps; int speed, picos_per_byte; u64 needed_bit_time_ps; - u32 val, maxlen; u8 tas_speed; int tc; - lockdep_assert_held(&ocelot->tas_lock); + lockdep_assert_held(&ocelot->fwd_domain_lock); taprio = ocelot_port->taprio; @@ -1265,14 +1255,21 @@ static void vsc9959_tas_guard_bands_update(struct ocelot *ocelot, int port) */ needed_bit_time_ps = (u64)(maxlen + 24) * picos_per_byte; + /* Preemptible TCs don't need to pass a full MTU, the port will + * automatically emit a HOLD request when a preemptible TC gate closes + */ + val = ocelot_read_rix(ocelot, QSYS_PREEMPTION_CFG, port); + add_frag_size = QSYS_PREEMPTION_CFG_MM_ADD_FRAG_SIZE_X(val); + needed_min_frag_time_ps = picos_per_byte * + (u64)(24 + 2 * ethtool_mm_frag_size_add_to_min(add_frag_size)); + dev_dbg(ocelot->dev, - "port %d: max frame size %d needs %llu ps at speed %d\n", - port, maxlen, needed_bit_time_ps, speed); + "port %d: max frame size %d needs %llu ps, %llu ps for mPackets at speed %d\n", + port, maxlen, needed_bit_time_ps, needed_min_frag_time_ps, + speed); vsc9959_tas_min_gate_lengths(taprio, min_gate_len); - mutex_lock(&ocelot->fwd_domain_lock); - for (tc = 0; tc < OCELOT_NUM_TC; tc++) { u32 requested_max_sdu = vsc9959_tas_tc_max_sdu(taprio, tc); u64 remaining_gate_len_ps; @@ -1281,7 +1278,9 @@ static void vsc9959_tas_guard_bands_update(struct ocelot *ocelot, int port) remaining_gate_len_ps = vsc9959_tas_remaining_gate_len_ps(min_gate_len[tc]); - if (remaining_gate_len_ps > needed_bit_time_ps) { + if ((mm->active_preemptible_tcs & BIT(tc)) ? + remaining_gate_len_ps > needed_min_frag_time_ps : + remaining_gate_len_ps > needed_bit_time_ps) { /* Setting QMAXSDU_CFG to 0 disables oversized frame * dropping. */ @@ -1335,8 +1334,6 @@ static void vsc9959_tas_guard_bands_update(struct ocelot *ocelot, int port) ocelot_write_rix(ocelot, maxlen, QSYS_PORT_MAX_SDU, port); ocelot->ops->cut_through_fwd(ocelot); - - mutex_unlock(&ocelot->fwd_domain_lock); } static void vsc9959_sched_speed_set(struct ocelot *ocelot, int port, @@ -1363,7 +1360,7 @@ static void vsc9959_sched_speed_set(struct ocelot *ocelot, int port, break; } - mutex_lock(&ocelot->tas_lock); + mutex_lock(&ocelot->fwd_domain_lock); ocelot_rmw_rix(ocelot, QSYS_TAG_CONFIG_LINK_SPEED(tas_speed), @@ -1373,7 +1370,7 @@ static void vsc9959_sched_speed_set(struct ocelot *ocelot, int port, if (ocelot_port->taprio) vsc9959_tas_guard_bands_update(ocelot, port); - mutex_unlock(&ocelot->tas_lock); + mutex_unlock(&ocelot->fwd_domain_lock); } static void vsc9959_new_base_time(struct ocelot *ocelot, ktime_t base_time, @@ -1421,9 +1418,9 @@ static int vsc9959_qos_port_tas_set(struct ocelot *ocelot, int port, int ret, i; u32 val; - mutex_lock(&ocelot->tas_lock); + mutex_lock(&ocelot->fwd_domain_lock); - if (!taprio->enable) { + if (taprio->cmd == TAPRIO_CMD_DESTROY) { ocelot_port_mqprio(ocelot, port, &taprio->mqprio); ocelot_rmw_rix(ocelot, 0, QSYS_TAG_CONFIG_ENABLE, QSYS_TAG_CONFIG, port); @@ -1433,8 +1430,11 @@ static int vsc9959_qos_port_tas_set(struct ocelot *ocelot, int port, vsc9959_tas_guard_bands_update(ocelot, port); - mutex_unlock(&ocelot->tas_lock); + mutex_unlock(&ocelot->fwd_domain_lock); return 0; + } else if (taprio->cmd != TAPRIO_CMD_REPLACE) { + ret = -EOPNOTSUPP; + goto err_unlock; } ret = ocelot_port_mqprio(ocelot, port, &taprio->mqprio); @@ -1513,7 +1513,7 @@ static int vsc9959_qos_port_tas_set(struct ocelot *ocelot, int port, ocelot_port->taprio = taprio_offload_get(taprio); vsc9959_tas_guard_bands_update(ocelot, port); - mutex_unlock(&ocelot->tas_lock); + mutex_unlock(&ocelot->fwd_domain_lock); return 0; @@ -1521,7 +1521,7 @@ static int vsc9959_qos_port_tas_set(struct ocelot *ocelot, int port, taprio->mqprio.qopt.num_tc = 0; ocelot_port_mqprio(ocelot, port, &taprio->mqprio); err_unlock: - mutex_unlock(&ocelot->tas_lock); + mutex_unlock(&ocelot->fwd_domain_lock); return ret; } @@ -1534,7 +1534,7 @@ static void vsc9959_tas_clock_adjust(struct ocelot *ocelot) int port; u32 val; - mutex_lock(&ocelot->tas_lock); + mutex_lock(&ocelot->fwd_domain_lock); for (port = 0; port < ocelot->num_phys_ports; port++) { ocelot_port = ocelot->ports[port]; @@ -1572,7 +1572,7 @@ static void vsc9959_tas_clock_adjust(struct ocelot *ocelot) QSYS_TAG_CONFIG_ENABLE, QSYS_TAG_CONFIG, port); } - mutex_unlock(&ocelot->tas_lock); + mutex_unlock(&ocelot->fwd_domain_lock); } static int vsc9959_qos_port_cbs_set(struct dsa_switch *ds, int port, @@ -1643,6 +1643,18 @@ static int vsc9959_qos_query_caps(struct tc_query_caps_base *base) } } +static int vsc9959_qos_port_mqprio(struct ocelot *ocelot, int port, + struct tc_mqprio_qopt_offload *mqprio) +{ + int ret; + + mutex_lock(&ocelot->fwd_domain_lock); + ret = ocelot_port_mqprio(ocelot, port, mqprio); + mutex_unlock(&ocelot->fwd_domain_lock); + + return ret; +} + static int vsc9959_port_setup_tc(struct dsa_switch *ds, int port, enum tc_setup_type type, void *type_data) @@ -1655,7 +1667,7 @@ static int vsc9959_port_setup_tc(struct dsa_switch *ds, int port, case TC_SETUP_QDISC_TAPRIO: return vsc9959_qos_port_tas_set(ocelot, port, type_data); case TC_SETUP_QDISC_MQPRIO: - return ocelot_port_mqprio(ocelot, port, type_data); + return vsc9959_qos_port_mqprio(ocelot, port, type_data); case TC_SETUP_QDISC_CBS: return vsc9959_qos_port_cbs_set(ds, port, type_data); default: @@ -2600,6 +2612,7 @@ static const struct ocelot_ops vsc9959_ops = { .cut_through_fwd = vsc9959_cut_through_fwd, .tas_clock_adjust = vsc9959_tas_clock_adjust, .update_stats = vsc9959_update_stats, + .tas_guard_bands_update = vsc9959_tas_guard_bands_update, }; static const struct felix_info felix_info_vsc9959 = { @@ -2625,7 +2638,6 @@ static const struct felix_info felix_info_vsc9959 = { .port_modes = vsc9959_port_modes, .port_setup_tc = vsc9959_port_setup_tc, .port_sched_speed_set = vsc9959_sched_speed_set, - .tas_guard_bands_update = vsc9959_tas_guard_bands_update, }; /* The INTB interrupt is shared between for PTP TX timestamp availability diff --git a/drivers/net/dsa/ocelot/seville_vsc9953.c b/drivers/net/dsa/ocelot/seville_vsc9953.c index 96d4972a62f0f8085c10292c59bdebe3ea415f78..15003b2af264d1448ea4880fb09e5501756fd590 100644 --- a/drivers/net/dsa/ocelot/seville_vsc9953.c +++ b/drivers/net/dsa/ocelot/seville_vsc9953.c @@ -912,7 +912,6 @@ static int vsc9953_mdio_bus_alloc(struct ocelot *ocelot) for (port = 0; port < felix->info->num_ports; port++) { struct ocelot_port *ocelot_port = ocelot->ports[port]; struct phylink_pcs *phylink_pcs; - struct mdio_device *mdio_device; int addr = port + 4; if (dsa_is_unused_port(felix->ds, port)) @@ -921,16 +920,10 @@ static int vsc9953_mdio_bus_alloc(struct ocelot *ocelot) if (ocelot_port->phy_mode == PHY_INTERFACE_MODE_INTERNAL) continue; - mdio_device = mdio_device_create(felix->imdio, addr); - if (IS_ERR(mdio_device)) + phylink_pcs = lynx_pcs_create_mdiodev(felix->imdio, addr); + if (IS_ERR(phylink_pcs)) continue; - phylink_pcs = lynx_pcs_create(mdio_device); - if (!phylink_pcs) { - mdio_device_free(mdio_device); - continue; - } - felix->pcs[port] = phylink_pcs; dev_info(dev, "Found PCS at internal MDIO address %d\n", addr); @@ -946,14 +939,9 @@ static void vsc9953_mdio_bus_free(struct ocelot *ocelot) for (port = 0; port < ocelot->num_phys_ports; port++) { struct phylink_pcs *phylink_pcs = felix->pcs[port]; - struct mdio_device *mdio_device; - - if (!phylink_pcs) - continue; - mdio_device = lynx_get_mdio_device(phylink_pcs); - mdio_device_free(mdio_device); - lynx_pcs_destroy(phylink_pcs); + if (phylink_pcs) + lynx_pcs_destroy(phylink_pcs); } /* mdiobus_unregister and mdiobus_free handled by devres */ diff --git a/drivers/net/dsa/qca/ar9331.c b/drivers/net/dsa/qca/ar9331.c index e7b98b864fa1690e2cb58c17d60cfca0fa835544..b2bf78ac485ebdd425571bd1ecc5c82d574a6bb6 100644 --- a/drivers/net/dsa/qca/ar9331.c +++ b/drivers/net/dsa/qca/ar9331.c @@ -391,7 +391,7 @@ static int ar9331_sw_mbus_init(struct ar9331_sw_priv *priv) static int ar9331_sw_setup_port(struct dsa_switch *ds, int port) { - struct ar9331_sw_priv *priv = (struct ar9331_sw_priv *)ds->priv; + struct ar9331_sw_priv *priv = ds->priv; struct regmap *regmap = priv->regmap; u32 port_mask, port_ctrl, val; int ret; @@ -439,7 +439,7 @@ static int ar9331_sw_setup_port(struct dsa_switch *ds, int port) static int ar9331_sw_setup(struct dsa_switch *ds) { - struct ar9331_sw_priv *priv = (struct ar9331_sw_priv *)ds->priv; + struct ar9331_sw_priv *priv = ds->priv; struct regmap *regmap = priv->regmap; int ret, i; @@ -484,7 +484,7 @@ static int ar9331_sw_setup(struct dsa_switch *ds) static void ar9331_sw_port_disable(struct dsa_switch *ds, int port) { - struct ar9331_sw_priv *priv = (struct ar9331_sw_priv *)ds->priv; + struct ar9331_sw_priv *priv = ds->priv; struct regmap *regmap = priv->regmap; int ret; @@ -527,7 +527,7 @@ static void ar9331_sw_phylink_mac_config(struct dsa_switch *ds, int port, unsigned int mode, const struct phylink_link_state *state) { - struct ar9331_sw_priv *priv = (struct ar9331_sw_priv *)ds->priv; + struct ar9331_sw_priv *priv = ds->priv; struct regmap *regmap = priv->regmap; int ret; @@ -542,7 +542,7 @@ static void ar9331_sw_phylink_mac_link_down(struct dsa_switch *ds, int port, unsigned int mode, phy_interface_t interface) { - struct ar9331_sw_priv *priv = (struct ar9331_sw_priv *)ds->priv; + struct ar9331_sw_priv *priv = ds->priv; struct ar9331_sw_port *p = &priv->port[port]; struct regmap *regmap = priv->regmap; int ret; @@ -562,7 +562,7 @@ static void ar9331_sw_phylink_mac_link_up(struct dsa_switch *ds, int port, int speed, int duplex, bool tx_pause, bool rx_pause) { - struct ar9331_sw_priv *priv = (struct ar9331_sw_priv *)ds->priv; + struct ar9331_sw_priv *priv = ds->priv; struct ar9331_sw_port *p = &priv->port[port]; struct regmap *regmap = priv->regmap; u32 val; @@ -665,7 +665,7 @@ static void ar9331_do_stats_poll(struct work_struct *work) static void ar9331_get_stats64(struct dsa_switch *ds, int port, struct rtnl_link_stats64 *s) { - struct ar9331_sw_priv *priv = (struct ar9331_sw_priv *)ds->priv; + struct ar9331_sw_priv *priv = ds->priv; struct ar9331_sw_port *p = &priv->port[port]; spin_lock(&p->stats_lock); @@ -676,7 +676,7 @@ static void ar9331_get_stats64(struct dsa_switch *ds, int port, static void ar9331_get_pause_stats(struct dsa_switch *ds, int port, struct ethtool_pause_stats *pause_stats) { - struct ar9331_sw_priv *priv = (struct ar9331_sw_priv *)ds->priv; + struct ar9331_sw_priv *priv = ds->priv; struct ar9331_sw_port *p = &priv->port[port]; spin_lock(&p->stats_lock); diff --git a/drivers/net/dsa/qca/qca8k-8xxx.c b/drivers/net/dsa/qca/qca8k-8xxx.c index 6d5ac7588a69170d80782081ac2ff5c4227ce270..09b80644c11bd679557ee626f0c78eb5f24297ed 100644 --- a/drivers/net/dsa/qca/qca8k-8xxx.c +++ b/drivers/net/dsa/qca/qca8k-8xxx.c @@ -588,6 +588,9 @@ qca8k_phy_eth_busy_wait(struct qca8k_mgmt_eth_data *mgmt_eth_data, bool ack; int ret; + if (!skb) + return -ENOMEM; + reinit_completion(&mgmt_eth_data->rw_done); /* Increment seq_num and set it in the copy pkt */ @@ -1493,7 +1496,7 @@ static void qca8k_pcs_get_state(struct phylink_pcs *pcs, state->pause |= MLO_PAUSE_TX; } -static int qca8k_pcs_config(struct phylink_pcs *pcs, unsigned int mode, +static int qca8k_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode, phy_interface_t interface, const unsigned long *advertising, bool permit_pause_to_mac) @@ -1520,14 +1523,12 @@ static int qca8k_pcs_config(struct phylink_pcs *pcs, unsigned int mode, } /* Enable/disable SerDes auto-negotiation as necessary */ - ret = qca8k_read(priv, QCA8K_REG_PWS, &val); + val = neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED ? + 0 : QCA8K_PWS_SERDES_AEN_DIS; + + ret = qca8k_rmw(priv, QCA8K_REG_PWS, QCA8K_PWS_SERDES_AEN_DIS, val); if (ret) return ret; - if (phylink_autoneg_inband(mode)) - val &= ~QCA8K_PWS_SERDES_AEN_DIS; - else - val |= QCA8K_PWS_SERDES_AEN_DIS; - qca8k_write(priv, QCA8K_REG_PWS, val); /* Configure the SGMII parameters */ ret = qca8k_read(priv, QCA8K_REG_SGMII_CTRL, &val); @@ -1598,6 +1599,7 @@ static void qca8k_setup_pcs(struct qca8k_priv *priv, struct qca8k_pcs *qpcs, int port) { qpcs->pcs.ops = &qca8k_pcs_ops; + qpcs->pcs.neg_mode = true; /* We don't have interrupts for link changes, so we need to poll */ qpcs->pcs.poll = true; @@ -1756,7 +1758,7 @@ static int qca8k_connect_tag_protocol(struct dsa_switch *ds, static int qca8k_setup(struct dsa_switch *ds) { - struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv; + struct qca8k_priv *priv = ds->priv; int cpu_port, ret, i; u32 mask; diff --git a/drivers/net/dsa/qca/qca8k-common.c b/drivers/net/dsa/qca/qca8k-common.c index 96773e4325582c8565ce1453ad33785e60cb5db3..8c2dc0e48ff4b9765c48fdb199c8394efb817246 100644 --- a/drivers/net/dsa/qca/qca8k-common.c +++ b/drivers/net/dsa/qca/qca8k-common.c @@ -760,7 +760,7 @@ int qca8k_port_fdb_add(struct dsa_switch *ds, int port, const unsigned char *addr, u16 vid, struct dsa_db db) { - struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv; + struct qca8k_priv *priv = ds->priv; u16 port_mask = BIT(port); return qca8k_port_fdb_insert(priv, addr, port_mask, vid); @@ -770,7 +770,7 @@ int qca8k_port_fdb_del(struct dsa_switch *ds, int port, const unsigned char *addr, u16 vid, struct dsa_db db) { - struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv; + struct qca8k_priv *priv = ds->priv; u16 port_mask = BIT(port); if (!vid) @@ -782,7 +782,7 @@ int qca8k_port_fdb_del(struct dsa_switch *ds, int port, int qca8k_port_fdb_dump(struct dsa_switch *ds, int port, dsa_fdb_dump_cb_t *cb, void *data) { - struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv; + struct qca8k_priv *priv = ds->priv; struct qca8k_fdb _fdb = { 0 }; int cnt = QCA8K_NUM_FDB_RECORDS; bool is_static; diff --git a/drivers/net/dsa/qca/qca8k-leds.c b/drivers/net/dsa/qca/qca8k-leds.c index b883692b7d86114e00524c13a0d5ecf39844ebff..1261e0bb21efed27355f0f9fe9719849796a4adc 100644 --- a/drivers/net/dsa/qca/qca8k-leds.c +++ b/drivers/net/dsa/qca/qca8k-leds.c @@ -5,6 +5,18 @@ #include "qca8k.h" #include "qca8k_leds.h" +static u32 qca8k_phy_to_port(int phy) +{ + /* Internal PHY 0 has port at index 1. + * Internal PHY 1 has port at index 2. + * Internal PHY 2 has port at index 3. + * Internal PHY 3 has port at index 4. + * Internal PHY 4 has port at index 5. + */ + + return phy + 1; +} + static int qca8k_get_enable_led_reg(int port_num, int led_num, struct qca8k_led_pattern_en *reg_info) { @@ -31,6 +43,53 @@ qca8k_get_enable_led_reg(int port_num, int led_num, struct qca8k_led_pattern_en return 0; } +static int +qca8k_get_control_led_reg(int port_num, int led_num, struct qca8k_led_pattern_en *reg_info) +{ + reg_info->reg = QCA8K_LED_CTRL_REG(led_num); + + /* 6 total control rule: + * 3 control rules for phy0-3 that applies to all their leds + * 3 control rules for phy4 + */ + if (port_num == 4) + reg_info->shift = QCA8K_LED_PHY4_CONTROL_RULE_SHIFT; + else + reg_info->shift = QCA8K_LED_PHY0123_CONTROL_RULE_SHIFT; + + return 0; +} + +static int +qca8k_parse_netdev(unsigned long rules, u32 *offload_trigger) +{ + /* Parsing specific to netdev trigger */ + if (test_bit(TRIGGER_NETDEV_TX, &rules)) + *offload_trigger |= QCA8K_LED_TX_BLINK_MASK; + if (test_bit(TRIGGER_NETDEV_RX, &rules)) + *offload_trigger |= QCA8K_LED_RX_BLINK_MASK; + if (test_bit(TRIGGER_NETDEV_LINK_10, &rules)) + *offload_trigger |= QCA8K_LED_LINK_10M_EN_MASK; + if (test_bit(TRIGGER_NETDEV_LINK_100, &rules)) + *offload_trigger |= QCA8K_LED_LINK_100M_EN_MASK; + if (test_bit(TRIGGER_NETDEV_LINK_1000, &rules)) + *offload_trigger |= QCA8K_LED_LINK_1000M_EN_MASK; + if (test_bit(TRIGGER_NETDEV_HALF_DUPLEX, &rules)) + *offload_trigger |= QCA8K_LED_HALF_DUPLEX_MASK; + if (test_bit(TRIGGER_NETDEV_FULL_DUPLEX, &rules)) + *offload_trigger |= QCA8K_LED_FULL_DUPLEX_MASK; + + if (rules && !*offload_trigger) + return -EOPNOTSUPP; + + /* Enable some default rule by default to the requested mode: + * - Blink at 4Hz by default + */ + *offload_trigger |= QCA8K_LED_BLINK_4HZ; + + return 0; +} + static int qca8k_led_brightness_set(struct qca8k_led *led, enum led_brightness brightness) @@ -164,6 +223,143 @@ qca8k_cled_blink_set(struct led_classdev *ldev, return 0; } +static int +qca8k_cled_trigger_offload(struct led_classdev *ldev, bool enable) +{ + struct qca8k_led *led = container_of(ldev, struct qca8k_led, cdev); + + struct qca8k_led_pattern_en reg_info; + struct qca8k_priv *priv = led->priv; + u32 mask, val = QCA8K_LED_ALWAYS_OFF; + + qca8k_get_enable_led_reg(led->port_num, led->led_num, ®_info); + + if (enable) + val = QCA8K_LED_RULE_CONTROLLED; + + if (led->port_num == 0 || led->port_num == 4) { + mask = QCA8K_LED_PATTERN_EN_MASK; + val <<= QCA8K_LED_PATTERN_EN_SHIFT; + } else { + mask = QCA8K_LED_PHY123_PATTERN_EN_MASK; + } + + return regmap_update_bits(priv->regmap, reg_info.reg, mask << reg_info.shift, + val << reg_info.shift); +} + +static bool +qca8k_cled_hw_control_status(struct led_classdev *ldev) +{ + struct qca8k_led *led = container_of(ldev, struct qca8k_led, cdev); + + struct qca8k_led_pattern_en reg_info; + struct qca8k_priv *priv = led->priv; + u32 val; + + qca8k_get_enable_led_reg(led->port_num, led->led_num, ®_info); + + regmap_read(priv->regmap, reg_info.reg, &val); + + val >>= reg_info.shift; + + if (led->port_num == 0 || led->port_num == 4) { + val &= QCA8K_LED_PATTERN_EN_MASK; + val >>= QCA8K_LED_PATTERN_EN_SHIFT; + } else { + val &= QCA8K_LED_PHY123_PATTERN_EN_MASK; + } + + return val == QCA8K_LED_RULE_CONTROLLED; +} + +static int +qca8k_cled_hw_control_is_supported(struct led_classdev *ldev, unsigned long rules) +{ + u32 offload_trigger = 0; + + return qca8k_parse_netdev(rules, &offload_trigger); +} + +static int +qca8k_cled_hw_control_set(struct led_classdev *ldev, unsigned long rules) +{ + struct qca8k_led *led = container_of(ldev, struct qca8k_led, cdev); + struct qca8k_led_pattern_en reg_info; + struct qca8k_priv *priv = led->priv; + u32 offload_trigger = 0; + int ret; + + ret = qca8k_parse_netdev(rules, &offload_trigger); + if (ret) + return ret; + + ret = qca8k_cled_trigger_offload(ldev, true); + if (ret) + return ret; + + qca8k_get_control_led_reg(led->port_num, led->led_num, ®_info); + + return regmap_update_bits(priv->regmap, reg_info.reg, + QCA8K_LED_RULE_MASK << reg_info.shift, + offload_trigger << reg_info.shift); +} + +static int +qca8k_cled_hw_control_get(struct led_classdev *ldev, unsigned long *rules) +{ + struct qca8k_led *led = container_of(ldev, struct qca8k_led, cdev); + struct qca8k_led_pattern_en reg_info; + struct qca8k_priv *priv = led->priv; + u32 val; + int ret; + + /* With hw control not active return err */ + if (!qca8k_cled_hw_control_status(ldev)) + return -EINVAL; + + qca8k_get_control_led_reg(led->port_num, led->led_num, ®_info); + + ret = regmap_read(priv->regmap, reg_info.reg, &val); + if (ret) + return ret; + + val >>= reg_info.shift; + val &= QCA8K_LED_RULE_MASK; + + /* Parsing specific to netdev trigger */ + if (val & QCA8K_LED_TX_BLINK_MASK) + set_bit(TRIGGER_NETDEV_TX, rules); + if (val & QCA8K_LED_RX_BLINK_MASK) + set_bit(TRIGGER_NETDEV_RX, rules); + if (val & QCA8K_LED_LINK_10M_EN_MASK) + set_bit(TRIGGER_NETDEV_LINK_10, rules); + if (val & QCA8K_LED_LINK_100M_EN_MASK) + set_bit(TRIGGER_NETDEV_LINK_100, rules); + if (val & QCA8K_LED_LINK_1000M_EN_MASK) + set_bit(TRIGGER_NETDEV_LINK_1000, rules); + if (val & QCA8K_LED_HALF_DUPLEX_MASK) + set_bit(TRIGGER_NETDEV_HALF_DUPLEX, rules); + if (val & QCA8K_LED_FULL_DUPLEX_MASK) + set_bit(TRIGGER_NETDEV_FULL_DUPLEX, rules); + + return 0; +} + +static struct device *qca8k_cled_hw_control_get_device(struct led_classdev *ldev) +{ + struct qca8k_led *led = container_of(ldev, struct qca8k_led, cdev); + struct qca8k_priv *priv = led->priv; + struct dsa_port *dp; + + dp = dsa_to_port(priv->ds, qca8k_phy_to_port(led->port_num)); + if (!dp) + return NULL; + if (dp->slave) + return &dp->slave->dev; + return NULL; +} + static int qca8k_parse_port_leds(struct qca8k_priv *priv, struct fwnode_handle *port, int port_num) { @@ -224,6 +420,11 @@ qca8k_parse_port_leds(struct qca8k_priv *priv, struct fwnode_handle *port, int p port_led->cdev.max_brightness = 1; port_led->cdev.brightness_set_blocking = qca8k_cled_brightness_set_blocking; port_led->cdev.blink_set = qca8k_cled_blink_set; + port_led->cdev.hw_control_is_supported = qca8k_cled_hw_control_is_supported; + port_led->cdev.hw_control_set = qca8k_cled_hw_control_set; + port_led->cdev.hw_control_get = qca8k_cled_hw_control_get; + port_led->cdev.hw_control_get_device = qca8k_cled_hw_control_get_device; + port_led->cdev.hw_control_trigger = "netdev"; init_data.default_label = ":port"; init_data.fwnode = led; init_data.devname_mandatory = true; diff --git a/drivers/net/dsa/sja1105/sja1105.h b/drivers/net/dsa/sja1105/sja1105.h index fb1549a5fe3216fea6503bb4f97ec765e34e6766..dee35ba924ad2f5fe97be4865be825393f42bc58 100644 --- a/drivers/net/dsa/sja1105/sja1105.h +++ b/drivers/net/dsa/sja1105/sja1105.h @@ -252,6 +252,7 @@ struct sja1105_private { unsigned long ucast_egress_floods; unsigned long bcast_egress_floods; unsigned long hwts_tx_en; + unsigned long hwts_rx_en; const struct sja1105_info *info; size_t max_xfer_len; struct spi_device *spidev; @@ -289,7 +290,6 @@ struct sja1105_spi_message { /* From sja1105_main.c */ enum sja1105_reset_reason { SJA1105_VLAN_FILTERING = 0, - SJA1105_RX_HWTSTAMPING, SJA1105_AGEING_TIME, SJA1105_SCHEDULING, SJA1105_BEST_EFFORT_POLICING, diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja1105/sja1105_main.c index b70dcf32a26dcbf62f443c62d17f33dfe90abf76..3529a565b4aafe4e0f9546577eb61673355fb1d7 100644 --- a/drivers/net/dsa/sja1105/sja1105_main.c +++ b/drivers/net/dsa/sja1105/sja1105_main.c @@ -866,12 +866,12 @@ static int sja1105_init_general_params(struct sja1105_private *priv) .hostprio = 7, .mac_fltres1 = SJA1105_LINKLOCAL_FILTER_A, .mac_flt1 = SJA1105_LINKLOCAL_FILTER_A_MASK, - .incl_srcpt1 = false, - .send_meta1 = false, + .incl_srcpt1 = true, + .send_meta1 = true, .mac_fltres0 = SJA1105_LINKLOCAL_FILTER_B, .mac_flt0 = SJA1105_LINKLOCAL_FILTER_B_MASK, - .incl_srcpt0 = false, - .send_meta0 = false, + .incl_srcpt0 = true, + .send_meta0 = true, /* Default to an invalid value */ .mirr_port = priv->ds->num_ports, /* No TTEthernet */ @@ -2215,7 +2215,6 @@ static int sja1105_reload_cbs(struct sja1105_private *priv) static const char * const sja1105_reset_reasons[] = { [SJA1105_VLAN_FILTERING] = "VLAN filtering", - [SJA1105_RX_HWTSTAMPING] = "RX timestamping", [SJA1105_AGEING_TIME] = "Ageing time", [SJA1105_SCHEDULING] = "Time-aware scheduling", [SJA1105_BEST_EFFORT_POLICING] = "Best-effort policing", @@ -2314,7 +2313,7 @@ int sja1105_static_config_reload(struct sja1105_private *priv, for (i = 0; i < ds->num_ports; i++) { struct dw_xpcs *xpcs = priv->xpcs[i]; - unsigned int mode; + unsigned int neg_mode; rc = sja1105_adjust_port_config(priv, i, speed_mbps[i]); if (rc < 0) @@ -2324,17 +2323,15 @@ int sja1105_static_config_reload(struct sja1105_private *priv, continue; if (bmcr[i] & BMCR_ANENABLE) - mode = MLO_AN_INBAND; - else if (priv->fixed_link[i]) - mode = MLO_AN_FIXED; + neg_mode = PHYLINK_PCS_NEG_INBAND_ENABLED; else - mode = MLO_AN_PHY; + neg_mode = PHYLINK_PCS_NEG_OUTBAND; - rc = xpcs_do_config(xpcs, priv->phy_mode[i], mode, NULL); + rc = xpcs_do_config(xpcs, priv->phy_mode[i], NULL, neg_mode); if (rc < 0) goto out; - if (!phylink_autoneg_inband(mode)) { + if (neg_mode == PHYLINK_PCS_NEG_OUTBAND) { int speed = SPEED_UNKNOWN; if (priv->phy_mode[i] == PHY_INTERFACE_MODE_2500BASEX) @@ -2346,7 +2343,7 @@ int sja1105_static_config_reload(struct sja1105_private *priv, else speed = SPEED_10; - xpcs_link_up(&xpcs->pcs, mode, priv->phy_mode[i], + xpcs_link_up(&xpcs->pcs, neg_mode, priv->phy_mode[i], speed, DUPLEX_FULL); } } @@ -2407,11 +2404,6 @@ int sja1105_vlan_filtering(struct dsa_switch *ds, int port, bool enabled, general_params->tpid = tpid; /* EtherType used to identify outer tagged (S-tag) VLAN traffic */ general_params->tpid2 = tpid2; - /* When VLAN filtering is on, we need to at least be able to - * decode management traffic through the "backup plan". - */ - general_params->incl_srcpt1 = enabled; - general_params->incl_srcpt0 = enabled; for (port = 0; port < ds->num_ports; port++) { if (dsa_is_unused_port(ds, port)) diff --git a/drivers/net/dsa/sja1105/sja1105_mdio.c b/drivers/net/dsa/sja1105/sja1105_mdio.c index 01f1cb71904226a2521233c0b9b9d7b29292a5e6..833e55e4b961296901d08def7fd2ff98caa7afb3 100644 --- a/drivers/net/dsa/sja1105/sja1105_mdio.c +++ b/drivers/net/dsa/sja1105/sja1105_mdio.c @@ -400,7 +400,6 @@ static int sja1105_mdiobus_pcs_register(struct sja1105_private *priv) } for (port = 0; port < ds->num_ports; port++) { - struct mdio_device *mdiodev; struct dw_xpcs *xpcs; if (dsa_is_unused_port(ds, port)) @@ -410,13 +409,7 @@ static int sja1105_mdiobus_pcs_register(struct sja1105_private *priv) priv->phy_mode[port] != PHY_INTERFACE_MODE_2500BASEX) continue; - mdiodev = mdio_device_create(bus, port); - if (IS_ERR(mdiodev)) { - rc = PTR_ERR(mdiodev); - goto out_pcs_free; - } - - xpcs = xpcs_create(mdiodev, priv->phy_mode[port]); + xpcs = xpcs_create_mdiodev(bus, port, priv->phy_mode[port]); if (IS_ERR(xpcs)) { rc = PTR_ERR(xpcs); goto out_pcs_free; @@ -434,7 +427,6 @@ static int sja1105_mdiobus_pcs_register(struct sja1105_private *priv) if (!priv->xpcs[port]) continue; - mdio_device_free(priv->xpcs[port]->mdiodev); xpcs_destroy(priv->xpcs[port]); priv->xpcs[port] = NULL; } @@ -457,7 +449,6 @@ static void sja1105_mdiobus_pcs_unregister(struct sja1105_private *priv) if (!priv->xpcs[port]) continue; - mdio_device_free(priv->xpcs[port]->mdiodev); xpcs_destroy(priv->xpcs[port]); priv->xpcs[port] = NULL; } diff --git a/drivers/net/dsa/sja1105/sja1105_ptp.c b/drivers/net/dsa/sja1105/sja1105_ptp.c index 30fb2cc40164b120c2bdf47608837136b084cd47..a7d41e7813982e35ed23c79df5e560eb3b660d80 100644 --- a/drivers/net/dsa/sja1105/sja1105_ptp.c +++ b/drivers/net/dsa/sja1105/sja1105_ptp.c @@ -58,35 +58,10 @@ enum sja1105_ptp_clk_mode { #define ptp_data_to_sja1105(d) \ container_of((d), struct sja1105_private, ptp_data) -/* Must be called only while the RX timestamping state of the tagger - * is turned off - */ -static int sja1105_change_rxtstamping(struct sja1105_private *priv, - bool on) -{ - struct sja1105_ptp_data *ptp_data = &priv->ptp_data; - struct sja1105_general_params_entry *general_params; - struct sja1105_table *table; - - table = &priv->static_config.tables[BLK_IDX_GENERAL_PARAMS]; - general_params = table->entries; - general_params->send_meta1 = on; - general_params->send_meta0 = on; - - ptp_cancel_worker_sync(ptp_data->clock); - skb_queue_purge(&ptp_data->skb_txtstamp_queue); - skb_queue_purge(&ptp_data->skb_rxtstamp_queue); - - return sja1105_static_config_reload(priv, SJA1105_RX_HWTSTAMPING); -} - int sja1105_hwtstamp_set(struct dsa_switch *ds, int port, struct ifreq *ifr) { - struct sja1105_tagger_data *tagger_data = sja1105_tagger_data(ds); struct sja1105_private *priv = ds->priv; struct hwtstamp_config config; - bool rx_on; - int rc; if (copy_from_user(&config, ifr->ifr_data, sizeof(config))) return -EFAULT; @@ -104,26 +79,13 @@ int sja1105_hwtstamp_set(struct dsa_switch *ds, int port, struct ifreq *ifr) switch (config.rx_filter) { case HWTSTAMP_FILTER_NONE: - rx_on = false; + priv->hwts_rx_en &= ~BIT(port); break; default: - rx_on = true; + priv->hwts_rx_en |= BIT(port); break; } - if (rx_on != tagger_data->rxtstamp_get_state(ds)) { - tagger_data->rxtstamp_set_state(ds, false); - - rc = sja1105_change_rxtstamping(priv, rx_on); - if (rc < 0) { - dev_err(ds->dev, - "Failed to change RX timestamping: %d\n", rc); - return rc; - } - if (rx_on) - tagger_data->rxtstamp_set_state(ds, true); - } - if (copy_to_user(ifr->ifr_data, &config, sizeof(config))) return -EFAULT; return 0; @@ -131,7 +93,6 @@ int sja1105_hwtstamp_set(struct dsa_switch *ds, int port, struct ifreq *ifr) int sja1105_hwtstamp_get(struct dsa_switch *ds, int port, struct ifreq *ifr) { - struct sja1105_tagger_data *tagger_data = sja1105_tagger_data(ds); struct sja1105_private *priv = ds->priv; struct hwtstamp_config config; @@ -140,7 +101,7 @@ int sja1105_hwtstamp_get(struct dsa_switch *ds, int port, struct ifreq *ifr) config.tx_type = HWTSTAMP_TX_ON; else config.tx_type = HWTSTAMP_TX_OFF; - if (tagger_data->rxtstamp_get_state(ds)) + if (priv->hwts_rx_en & BIT(port)) config.rx_filter = HWTSTAMP_FILTER_PTP_V2_L2_EVENT; else config.rx_filter = HWTSTAMP_FILTER_NONE; @@ -413,11 +374,10 @@ static long sja1105_rxtstamp_work(struct ptp_clock_info *ptp) bool sja1105_rxtstamp(struct dsa_switch *ds, int port, struct sk_buff *skb) { - struct sja1105_tagger_data *tagger_data = sja1105_tagger_data(ds); struct sja1105_private *priv = ds->priv; struct sja1105_ptp_data *ptp_data = &priv->ptp_data; - if (!tagger_data->rxtstamp_get_state(ds)) + if (!(priv->hwts_rx_en & BIT(port))) return false; /* We need to read the full PTP clock to reconstruct the Rx diff --git a/drivers/net/dsa/sja1105/sja1105_tas.c b/drivers/net/dsa/sja1105/sja1105_tas.c index e6153848a9509401d91ca9d48fa46616c0561d25..d7818710bc02832fb1c70f115c8e50dbb99f4547 100644 --- a/drivers/net/dsa/sja1105/sja1105_tas.c +++ b/drivers/net/dsa/sja1105/sja1105_tas.c @@ -516,10 +516,11 @@ int sja1105_setup_tc_taprio(struct dsa_switch *ds, int port, /* Can't change an already configured port (must delete qdisc first). * Can't delete the qdisc from an unconfigured port. */ - if (!!tas_data->offload[port] == admin->enable) + if ((!!tas_data->offload[port] && admin->cmd == TAPRIO_CMD_REPLACE) || + (!tas_data->offload[port] && admin->cmd == TAPRIO_CMD_DESTROY)) return -EINVAL; - if (!admin->enable) { + if (admin->cmd == TAPRIO_CMD_DESTROY) { taprio_offload_free(tas_data->offload[port]); tas_data->offload[port] = NULL; @@ -528,6 +529,8 @@ int sja1105_setup_tc_taprio(struct dsa_switch *ds, int port, return rc; return sja1105_static_config_reload(priv, SJA1105_SCHEDULING); + } else if (admin->cmd != TAPRIO_CMD_REPLACE) { + return -EOPNOTSUPP; } /* The cycle time extension is the amount of time the last cycle from diff --git a/drivers/net/dsa/vitesse-vsc73xx-core.c b/drivers/net/dsa/vitesse-vsc73xx-core.c index ae55167ce0a6f5fa6f9fa0556d77a41a8b114614..ef1a4a7c47b23150ac833867a35a004e46cd5361 100644 --- a/drivers/net/dsa/vitesse-vsc73xx-core.c +++ b/drivers/net/dsa/vitesse-vsc73xx-core.c @@ -1025,17 +1025,17 @@ static int vsc73xx_change_mtu(struct dsa_switch *ds, int port, int new_mtu) struct vsc73xx *vsc = ds->priv; return vsc73xx_write(vsc, VSC73XX_BLOCK_MAC, port, - VSC73XX_MAXLEN, new_mtu); + VSC73XX_MAXLEN, new_mtu + ETH_HLEN + ETH_FCS_LEN); } /* According to application not "VSC7398 Jumbo Frames" setting - * up the MTU to 9.6 KB does not affect the performance on standard + * up the frame size to 9.6 KB does not affect the performance on standard * frames. It is clear from the application note that * "9.6 kilobytes" == 9600 bytes. */ static int vsc73xx_get_max_mtu(struct dsa_switch *ds, int port) { - return 9600; + return 9600 - ETH_HLEN - ETH_FCS_LEN; } static const struct dsa_switch_ops vsc73xx_ds_ops = { diff --git a/drivers/net/dsa/xrs700x/xrs700x_i2c.c b/drivers/net/dsa/xrs700x/xrs700x_i2c.c index 14ff6887a225dc1095cd1da19dfd7e5f463b6a24..c1179d7311f7e4f48e897dd338279eed031932ed 100644 --- a/drivers/net/dsa/xrs700x/xrs700x_i2c.c +++ b/drivers/net/dsa/xrs700x/xrs700x_i2c.c @@ -147,7 +147,7 @@ static struct i2c_driver xrs700x_i2c_driver = { .name = "xrs700x-i2c", .of_match_table = of_match_ptr(xrs700x_i2c_dt_ids), }, - .probe_new = xrs700x_i2c_probe, + .probe = xrs700x_i2c_probe, .remove = xrs700x_i2c_remove, .shutdown = xrs700x_i2c_shutdown, .id_table = xrs700x_i2c_id, diff --git a/drivers/net/ethernet/8390/8390.h b/drivers/net/ethernet/8390/8390.h index e5226446599884dae1118660e1c55b79ca681789..f784a6e2ab0ed35671a0744c42fd75389e75866d 100644 --- a/drivers/net/ethernet/8390/8390.h +++ b/drivers/net/ethernet/8390/8390.h @@ -1,3 +1,5 @@ +/* SPDX-License-Identifier: GPL-1.0+ */ + /* Generic NS8390 register definitions. */ /* This file is part of Donald Becker's 8390 drivers, and is distributed diff --git a/drivers/net/ethernet/8390/apne.c b/drivers/net/ethernet/8390/apne.c index 991ad953aa79067b253e02fa0b037a3c5191ba8d..a09f383dd249f1e1782d20de475bdac76a90c54d 100644 --- a/drivers/net/ethernet/8390/apne.c +++ b/drivers/net/ethernet/8390/apne.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Amiga Linux/68k 8390 based PCMCIA Ethernet Driver for the Amiga 1200 * @@ -19,12 +20,6 @@ * * ---------------------------------------------------------------------------- * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of the Linux - * distribution for more details. - * - * ---------------------------------------------------------------------------- - * */ diff --git a/drivers/net/ethernet/8390/axnet_cs.c b/drivers/net/ethernet/8390/axnet_cs.c index 78f985885547eacd48a8cec4387976874a41b941..fea489af72fb0b80665b9e6c2464f2d1283c89af 100644 --- a/drivers/net/ethernet/8390/axnet_cs.c +++ b/drivers/net/ethernet/8390/axnet_cs.c @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: GPL-1.0+ + /*====================================================================== A PCMCIA ethernet driver for Asix AX88190-based cards @@ -17,9 +19,7 @@ Written 1992,1993 by Donald Becker. Copyright 1993 United States Government as represented by the - Director, National Security Agency. This software may be used and - distributed according to the terms of the GNU General Public License, - incorporated herein by reference. + Director, National Security Agency. Donald Becker may be reached at becker@scyld.com ======================================================================*/ diff --git a/drivers/net/ethernet/8390/hydra.c b/drivers/net/ethernet/8390/hydra.c index 1df7601af86a4008ce24e2ecf235932502bcf1fa..24f49a8ff903ff3ae8496074c19df0235b7965cf 100644 --- a/drivers/net/ethernet/8390/hydra.c +++ b/drivers/net/ethernet/8390/hydra.c @@ -1,10 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0-only + /* New Hydra driver using generic 8390 core */ /* Based on old hydra driver by Topi Kanerva (topi@susanna.oulu.fi) */ -/* This file is subject to the terms and conditions of the GNU General */ -/* Public License. See the file COPYING in the main directory of the */ -/* Linux distribution for more details. */ - /* Peter De Schrijver (p2@mind.be) */ /* Oldenburg 2000 */ diff --git a/drivers/net/ethernet/8390/lib8390.c b/drivers/net/ethernet/8390/lib8390.c index e84021282edf30eaee5e8f1ead2ae0bc526193a8..84aeb8054304f9cb041cddfb1d4e0cc38b692ee9 100644 --- a/drivers/net/ethernet/8390/lib8390.c +++ b/drivers/net/ethernet/8390/lib8390.c @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: GPL-1.0+ + /* 8390.c: A general NS8390 ethernet driver core for linux. */ /* Written 1992-94 by Donald Becker. @@ -5,9 +7,6 @@ Copyright 1993 United States Government as represented by the Director, National Security Agency. - This software may be used and distributed according to the terms - of the GNU General Public License, incorporated herein by reference. - The author may be reached as becker@scyld.com, or C/O Scyld Computing Corporation 410 Severn Ave., Suite 210 diff --git a/drivers/net/ethernet/8390/mac8390.c b/drivers/net/ethernet/8390/mac8390.c index 7fb819b9b89a5bacef527fb29a05c0948ad77d5e..4a0a095a1a8a0a6269ec595f4ea03e32a514908e 100644 --- a/drivers/net/ethernet/8390/mac8390.c +++ b/drivers/net/ethernet/8390/mac8390.c @@ -1,11 +1,9 @@ +// SPDX-License-Identifier: GPL-1.0+ /* mac8390.c: New driver for 8390-based Nubus (or Nubus-alike) Ethernet cards on Linux */ /* Based on the former daynaport.c driver, by Alan Cox. Some code taken from or inspired by skeleton.c by Donald Becker, acenic.c by - Jes Sorensen, and ne2k-pci.c by Donald Becker and Paul Gortmaker. - - This software may be used and distributed according to the terms of - the GNU Public License, incorporated herein by reference. */ + Jes Sorensen, and ne2k-pci.c by Donald Becker and Paul Gortmaker. */ /* 2000-02-28: support added for Dayna and Kinetics cards by A.G.deWijn@phys.uu.nl */ diff --git a/drivers/net/ethernet/8390/mcf8390.c b/drivers/net/ethernet/8390/mcf8390.c index 8a7918d33419652c1ebe6474adcd43634858db99..217838b282202577ea91cad53e73a75f4c14447f 100644 --- a/drivers/net/ethernet/8390/mcf8390.c +++ b/drivers/net/ethernet/8390/mcf8390.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Support for ColdFire CPU based boards using a NS8390 Ethernet device. * @@ -5,9 +6,6 @@ * * (C) Copyright 2012, Greg Ungerer * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of the Linux - * distribution for more details. */ #include diff --git a/drivers/net/ethernet/8390/ne.c b/drivers/net/ethernet/8390/ne.c index bc9c81dc00fd20c37311da008e9d6bc04dc8f864..7d89ec1cf273daea97936c5384d12170f5a0d494 100644 --- a/drivers/net/ethernet/8390/ne.c +++ b/drivers/net/ethernet/8390/ne.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-1.0+ /* ne.c: A general non-shared-memory NS8390 ethernet driver for linux. */ /* Written 1992-94 by Donald Becker. @@ -5,9 +6,6 @@ Copyright 1993 United States Government as represented by the Director, National Security Agency. - This software may be used and distributed according to the terms - of the GNU General Public License, incorporated herein by reference. - The author may be reached as becker@scyld.com, or C/O Scyld Computing Corporation, 410 Severn Ave., Suite 210, Annapolis MD 21403 diff --git a/drivers/net/ethernet/8390/ne2k-pci.c b/drivers/net/ethernet/8390/ne2k-pci.c index 6a0a2039600a0ae2f648b00a85ac6f88ccb2e300..2c6bd36d2f313be32c367c08fe4e2a0601d2285d 100644 --- a/drivers/net/ethernet/8390/ne2k-pci.c +++ b/drivers/net/ethernet/8390/ne2k-pci.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-1.0+ /* A Linux device driver for PCI NE2000 clones. * * Authors and other copyright holders: diff --git a/drivers/net/ethernet/8390/pcnet_cs.c b/drivers/net/ethernet/8390/pcnet_cs.c index 0f07fe03da98c8642961a67669db387b6e0954f0..9bd5e991f1e52be30a5285196779d725ae9b481e 100644 --- a/drivers/net/ethernet/8390/pcnet_cs.c +++ b/drivers/net/ethernet/8390/pcnet_cs.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-1.0+ /*====================================================================== A PCMCIA ethernet driver for NS8390-based cards @@ -17,9 +18,7 @@ Written 1992,1993 by Donald Becker. Copyright 1993 United States Government as represented by the - Director, National Security Agency. This software may be used and - distributed according to the terms of the GNU General Public License, - incorporated herein by reference. + Director, National Security Agency. Donald Becker may be reached at becker@scyld.com Based also on Keith Moore's changes to Don Becker's code, for IBM diff --git a/drivers/net/ethernet/8390/smc-ultra.c b/drivers/net/ethernet/8390/smc-ultra.c index 7465650c80780594203516d5a4915a9122d04448..22ca804b2e95d4134145ac73e30a2692756812c1 100644 --- a/drivers/net/ethernet/8390/smc-ultra.c +++ b/drivers/net/ethernet/8390/smc-ultra.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-1.0+ /* smc-ultra.c: A SMC Ultra ethernet driver for linux. */ /* This is a driver for the SMC Ultra and SMC EtherEZ ISA ethercards. @@ -7,9 +8,6 @@ Copyright 1993 United States Government as represented by the Director, National Security Agency. - This software may be used and distributed according to the terms - of the GNU General Public License, incorporated herein by reference. - The author may be reached as becker@scyld.com, or C/O Scyld Computing Corporation 410 Severn Ave., Suite 210 diff --git a/drivers/net/ethernet/8390/stnic.c b/drivers/net/ethernet/8390/stnic.c index bd89ca8a92dfbcbca3dd16c2be51f3763f2a00a9..265976e3b64ab227c55924bd8e0581b24b506d42 100644 --- a/drivers/net/ethernet/8390/stnic.c +++ b/drivers/net/ethernet/8390/stnic.c @@ -1,8 +1,5 @@ +// SPDX-License-Identifier: GPL-2.0-only /* stnic.c : A SH7750 specific part of driver for NS DP83902A ST-NIC. - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. * * Copyright (C) 1999 kaz Kojima */ diff --git a/drivers/net/ethernet/8390/wd.c b/drivers/net/ethernet/8390/wd.c index 119021d41451e88726af07852b587b4d33673efd..ffd639477dfcb9dc550a1d0f07fd3766a9f9edad 100644 --- a/drivers/net/ethernet/8390/wd.c +++ b/drivers/net/ethernet/8390/wd.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-1.0+ /* wd.c: A WD80x3 ethernet driver for linux. */ /* Written 1993-94 by Donald Becker. @@ -5,9 +6,6 @@ Copyright 1993 United States Government as represented by the Director, National Security Agency. - This software may be used and distributed according to the terms - of the GNU General Public License, incorporated herein by reference. - The author may be reached as becker@scyld.com, or C/O Scyld Computing Corporation 410 Severn Ave., Suite 210 diff --git a/drivers/net/ethernet/8390/zorro8390.c b/drivers/net/ethernet/8390/zorro8390.c index e8b4fe813a0828527941cb52d5f4aead54ab21cb..d70390e9d03d9bfe421554ef9e50ce78123bddfe 100644 --- a/drivers/net/ethernet/8390/zorro8390.c +++ b/drivers/net/ethernet/8390/zorro8390.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Amiga Linux/m68k and Linux/PPC Zorro NS8390 Ethernet Driver * @@ -9,12 +10,6 @@ * * --------------------------------------------------------------------------- * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of the Linux - * distribution for more details. - * - * --------------------------------------------------------------------------- - * * The Ariadne II and X-Surf are Zorro-II boards containing Realtek RTL8019AS * Ethernet Controllers. */ diff --git a/drivers/net/ethernet/altera/Kconfig b/drivers/net/ethernet/altera/Kconfig index dd7fd41ccde5bfd087f3850923bbdf3416037678..17985319088c1d3b9a926ec4d6e142afc78a6ad1 100644 --- a/drivers/net/ethernet/altera/Kconfig +++ b/drivers/net/ethernet/altera/Kconfig @@ -4,7 +4,9 @@ config ALTERA_TSE depends on HAS_DMA select PHYLIB select PHYLINK - select PCS_ALTERA_TSE + select PCS_LYNX + select MDIO_REGMAP + select REGMAP_MMIO help This driver supports the Altera Triple-Speed (TSE) Ethernet MAC. diff --git a/drivers/net/ethernet/altera/altera_tse_main.c b/drivers/net/ethernet/altera/altera_tse_main.c index 66e3af73ec41ac9623b6d8be957b6f6fdc88742b..2e15800e53102fefa22880ed7131c93de09f5b17 100644 --- a/drivers/net/ethernet/altera/altera_tse_main.c +++ b/drivers/net/ethernet/altera/altera_tse_main.c @@ -27,14 +27,16 @@ #include #include #include +#include #include #include #include #include #include -#include +#include #include #include +#include #include #include @@ -1036,10 +1038,6 @@ static struct net_device_ops altera_tse_netdev_ops = { .ndo_validate_addr = eth_validate_addr, }; -static void alt_tse_mac_an_restart(struct phylink_config *config) -{ -} - static void alt_tse_mac_config(struct phylink_config *config, unsigned int mode, const struct phylink_link_state *state) { @@ -1096,7 +1094,6 @@ static struct phylink_pcs *alt_tse_select_pcs(struct phylink_config *config, } static const struct phylink_mac_ops alt_tse_phylink_ops = { - .mac_an_restart = alt_tse_mac_an_restart, .mac_config = alt_tse_mac_config, .mac_link_down = alt_tse_mac_link_down, .mac_link_up = alt_tse_mac_link_up, @@ -1137,13 +1134,16 @@ static int request_and_map(struct platform_device *pdev, const char *name, static int altera_tse_probe(struct platform_device *pdev) { const struct of_device_id *of_id = NULL; + struct regmap_config pcs_regmap_cfg; struct altera_tse_private *priv; + struct mdio_regmap_config mrc; struct resource *control_port; + struct regmap *pcs_regmap; struct resource *dma_res; struct resource *pcs_res; + struct mii_bus *pcs_bus; struct net_device *ndev; void __iomem *descmap; - int pcs_reg_width = 2; int ret = -ENODEV; ndev = alloc_etherdev(sizeof(struct altera_tse_private)); @@ -1255,18 +1255,41 @@ static int altera_tse_probe(struct platform_device *pdev) if (ret) goto err_free_netdev; + memset(&pcs_regmap_cfg, 0, sizeof(pcs_regmap_cfg)); + memset(&mrc, 0, sizeof(mrc)); /* SGMII PCS address space. The location can vary depending on how the * IP is integrated. We can have a resource dedicated to it at a specific * address space, but if it's not the case, we fallback to the mdiophy0 * from the MAC's address space */ - ret = request_and_map(pdev, "pcs", &pcs_res, - &priv->pcs_base); + ret = request_and_map(pdev, "pcs", &pcs_res, &priv->pcs_base); if (ret) { + /* If we can't find a dedicated resource for the PCS, fallback + * to the internal PCS, that has a different address stride + */ priv->pcs_base = priv->mac_dev + tse_csroffs(mdio_phy0); - pcs_reg_width = 4; + pcs_regmap_cfg.reg_bits = 32; + /* Values are MDIO-like values, on 16 bits */ + pcs_regmap_cfg.val_bits = 16; + pcs_regmap_cfg.reg_shift = REGMAP_UPSHIFT(2); + } else { + pcs_regmap_cfg.reg_bits = 16; + pcs_regmap_cfg.val_bits = 16; + pcs_regmap_cfg.reg_shift = REGMAP_UPSHIFT(1); } + /* Create a regmap for the PCS so that it can be used by the PCS driver */ + pcs_regmap = devm_regmap_init_mmio(&pdev->dev, priv->pcs_base, + &pcs_regmap_cfg); + if (IS_ERR(pcs_regmap)) { + ret = PTR_ERR(pcs_regmap); + goto err_free_netdev; + } + mrc.regmap = pcs_regmap; + mrc.parent = &pdev->dev; + mrc.valid_addr = 0x0; + mrc.autoscan = false; + /* Rx IRQ */ priv->rx_irq = platform_get_irq_byname(pdev, "rx_irq"); if (priv->rx_irq == -ENXIO) { @@ -1389,7 +1412,18 @@ static int altera_tse_probe(struct platform_device *pdev) (unsigned long) control_port->start, priv->rx_irq, priv->tx_irq); - priv->pcs = alt_tse_pcs_create(ndev, priv->pcs_base, pcs_reg_width); + snprintf(mrc.name, MII_BUS_ID_SIZE, "%s-pcs-mii", ndev->name); + pcs_bus = devm_mdio_regmap_register(&pdev->dev, &mrc); + if (IS_ERR(pcs_bus)) { + ret = PTR_ERR(pcs_bus); + goto err_init_pcs; + } + + priv->pcs = lynx_pcs_create_mdiodev(pcs_bus, 0); + if (IS_ERR(priv->pcs)) { + ret = PTR_ERR(priv->pcs); + goto err_init_pcs; + } priv->phylink_config.dev = &ndev->dev; priv->phylink_config.type = PHYLINK_NETDEV; @@ -1412,12 +1446,13 @@ static int altera_tse_probe(struct platform_device *pdev) if (IS_ERR(priv->phylink)) { dev_err(&pdev->dev, "failed to create phylink\n"); ret = PTR_ERR(priv->phylink); - goto err_init_phy; + goto err_init_phylink; } return 0; - -err_init_phy: +err_init_phylink: + lynx_pcs_destroy(priv->pcs); +err_init_pcs: unregister_netdev(ndev); err_register_netdev: netif_napi_del(&priv->napi); @@ -1438,6 +1473,8 @@ static int altera_tse_remove(struct platform_device *pdev) altera_tse_mdio_destroy(ndev); unregister_netdev(ndev); phylink_destroy(priv->phylink); + lynx_pcs_destroy(priv->pcs); + free_netdev(ndev); return 0; diff --git a/drivers/net/ethernet/amazon/ena/ena_admin_defs.h b/drivers/net/ethernet/amazon/ena/ena_admin_defs.h index 466ad9470d1f44b3b663c866a8d170fab26a381d..6de0d590be34fe2a42ba7a57141ae6076ecf5485 100644 --- a/drivers/net/ethernet/amazon/ena/ena_admin_defs.h +++ b/drivers/net/ethernet/amazon/ena/ena_admin_defs.h @@ -869,7 +869,9 @@ struct ena_admin_host_info { * 2 : interrupt_moderation * 3 : rx_buf_mirroring * 4 : rss_configurable_function_key - * 31:5 : reserved + * 5 : reserved + * 6 : rx_page_reuse + * 31:7 : reserved */ u32 driver_supported_features; }; @@ -1184,6 +1186,8 @@ struct ena_admin_ena_mmio_req_read_less_resp { #define ENA_ADMIN_HOST_INFO_RX_BUF_MIRRORING_MASK BIT(3) #define ENA_ADMIN_HOST_INFO_RSS_CONFIGURABLE_FUNCTION_KEY_SHIFT 4 #define ENA_ADMIN_HOST_INFO_RSS_CONFIGURABLE_FUNCTION_KEY_MASK BIT(4) +#define ENA_ADMIN_HOST_INFO_RX_PAGE_REUSE_SHIFT 6 +#define ENA_ADMIN_HOST_INFO_RX_PAGE_REUSE_MASK BIT(6) /* aenq_common_desc */ #define ENA_ADMIN_AENQ_COMMON_DESC_PHASE_MASK BIT(0) diff --git a/drivers/net/ethernet/amazon/ena/ena_com.c b/drivers/net/ethernet/amazon/ena/ena_com.c index 451c3a1b62553794e736e2d1eb7b981072def1c6..633b321d7fdd97c9090ee6d7f6452d952dbc1fd8 100644 --- a/drivers/net/ethernet/amazon/ena/ena_com.c +++ b/drivers/net/ethernet/amazon/ena/ena_com.c @@ -35,6 +35,8 @@ #define ENA_REGS_ADMIN_INTR_MASK 1 +#define ENA_MAX_BACKOFF_DELAY_EXP 16U + #define ENA_MIN_ADMIN_POLL_US 100 #define ENA_MAX_ADMIN_POLL_US 5000 @@ -536,6 +538,7 @@ static int ena_com_comp_status_to_errno(struct ena_com_admin_queue *admin_queue, static void ena_delay_exponential_backoff_us(u32 exp, u32 delay_us) { + exp = min_t(u32, exp, ENA_MAX_BACKOFF_DELAY_EXP); delay_us = max_t(u32, ENA_MIN_ADMIN_POLL_US, delay_us); delay_us = min_t(u32, delay_us * (1U << exp), ENA_MAX_ADMIN_POLL_US); usleep_range(delay_us, 2 * delay_us); diff --git a/drivers/net/ethernet/amazon/ena/ena_netdev.c b/drivers/net/ethernet/amazon/ena/ena_netdev.c index e6a6efaeb87c24c3ee42e7d5ba5775bf3310641a..d19593fae226575d1a9d070aef5d5c84e6f312dc 100644 --- a/drivers/net/ethernet/amazon/ena/ena_netdev.c +++ b/drivers/net/ethernet/amazon/ena/ena_netdev.c @@ -1023,7 +1023,7 @@ static int ena_alloc_rx_buffer(struct ena_ring *rx_ring, int tailroom; /* restore page offset value in case it has been changed by device */ - rx_info->page_offset = headroom; + rx_info->buf_offset = headroom; /* if previous allocated page is not used */ if (unlikely(rx_info->page)) @@ -1040,6 +1040,8 @@ static int ena_alloc_rx_buffer(struct ena_ring *rx_ring, tailroom = SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); rx_info->page = page; + rx_info->dma_addr = dma; + rx_info->page_offset = 0; ena_buf = &rx_info->ena_buf; ena_buf->paddr = dma + headroom; ena_buf->len = ENA_PAGE_SIZE - headroom - tailroom; @@ -1047,14 +1049,12 @@ static int ena_alloc_rx_buffer(struct ena_ring *rx_ring, return 0; } -static void ena_unmap_rx_buff(struct ena_ring *rx_ring, - struct ena_rx_buffer *rx_info) +static void ena_unmap_rx_buff_attrs(struct ena_ring *rx_ring, + struct ena_rx_buffer *rx_info, + unsigned long attrs) { - struct ena_com_buf *ena_buf = &rx_info->ena_buf; - - dma_unmap_page(rx_ring->dev, ena_buf->paddr - rx_ring->rx_headroom, - ENA_PAGE_SIZE, - DMA_BIDIRECTIONAL); + dma_unmap_page_attrs(rx_ring->dev, rx_info->dma_addr, ENA_PAGE_SIZE, + DMA_BIDIRECTIONAL, attrs); } static void ena_free_rx_page(struct ena_ring *rx_ring, @@ -1068,7 +1068,7 @@ static void ena_free_rx_page(struct ena_ring *rx_ring, return; } - ena_unmap_rx_buff(rx_ring, rx_info); + ena_unmap_rx_buff_attrs(rx_ring, rx_info, 0); __free_page(page); rx_info->page = NULL; @@ -1406,14 +1406,14 @@ static int ena_clean_tx_irq(struct ena_ring *tx_ring, u32 budget) return tx_pkts; } -static struct sk_buff *ena_alloc_skb(struct ena_ring *rx_ring, void *first_frag) +static struct sk_buff *ena_alloc_skb(struct ena_ring *rx_ring, void *first_frag, u16 len) { struct sk_buff *skb; if (!first_frag) - skb = napi_alloc_skb(rx_ring->napi, rx_ring->rx_copybreak); + skb = napi_alloc_skb(rx_ring->napi, len); else - skb = napi_build_skb(first_frag, ENA_PAGE_SIZE); + skb = napi_build_skb(first_frag, len); if (unlikely(!skb)) { ena_increase_stat(&rx_ring->rx_stats.skb_alloc_fail, 1, @@ -1422,24 +1422,47 @@ static struct sk_buff *ena_alloc_skb(struct ena_ring *rx_ring, void *first_frag) netif_dbg(rx_ring->adapter, rx_err, rx_ring->netdev, "Failed to allocate skb. first_frag %s\n", first_frag ? "provided" : "not provided"); - return NULL; } return skb; } +static bool ena_try_rx_buf_page_reuse(struct ena_rx_buffer *rx_info, u16 buf_len, + u16 len, int pkt_offset) +{ + struct ena_com_buf *ena_buf = &rx_info->ena_buf; + + /* More than ENA_MIN_RX_BUF_SIZE left in the reused buffer + * for data + headroom + tailroom. + */ + if (SKB_DATA_ALIGN(len + pkt_offset) + ENA_MIN_RX_BUF_SIZE <= ena_buf->len) { + page_ref_inc(rx_info->page); + rx_info->page_offset += buf_len; + ena_buf->paddr += buf_len; + ena_buf->len -= buf_len; + return true; + } + + return false; +} + static struct sk_buff *ena_rx_skb(struct ena_ring *rx_ring, struct ena_com_rx_buf_info *ena_bufs, u32 descs, u16 *next_to_clean) { + int tailroom = SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); + bool is_xdp_loaded = ena_xdp_present_ring(rx_ring); struct ena_rx_buffer *rx_info; struct ena_adapter *adapter; + int page_offset, pkt_offset; + dma_addr_t pre_reuse_paddr; u16 len, req_id, buf = 0; + bool reuse_rx_buf_page; struct sk_buff *skb; - void *page_addr; - u32 page_offset; - void *data_addr; + void *buf_addr; + int buf_offset; + u16 buf_len; len = ena_bufs[buf].len; req_id = ena_bufs[buf].req_id; @@ -1459,34 +1482,30 @@ static struct sk_buff *ena_rx_skb(struct ena_ring *rx_ring, "rx_info %p page %p\n", rx_info, rx_info->page); - /* save virt address of first buffer */ - page_addr = page_address(rx_info->page); + buf_offset = rx_info->buf_offset; + pkt_offset = buf_offset - rx_ring->rx_headroom; page_offset = rx_info->page_offset; - data_addr = page_addr + page_offset; - - prefetch(data_addr); + buf_addr = page_address(rx_info->page) + page_offset; if (len <= rx_ring->rx_copybreak) { - skb = ena_alloc_skb(rx_ring, NULL); + skb = ena_alloc_skb(rx_ring, NULL, len); if (unlikely(!skb)) return NULL; - netif_dbg(rx_ring->adapter, rx_status, rx_ring->netdev, - "RX allocated small packet. len %d. data_len %d\n", - skb->len, skb->data_len); - /* sync this buffer for CPU use */ dma_sync_single_for_cpu(rx_ring->dev, - dma_unmap_addr(&rx_info->ena_buf, paddr), + dma_unmap_addr(&rx_info->ena_buf, paddr) + pkt_offset, len, DMA_FROM_DEVICE); - skb_copy_to_linear_data(skb, data_addr, len); + skb_copy_to_linear_data(skb, buf_addr + buf_offset, len); dma_sync_single_for_device(rx_ring->dev, - dma_unmap_addr(&rx_info->ena_buf, paddr), + dma_unmap_addr(&rx_info->ena_buf, paddr) + pkt_offset, len, DMA_FROM_DEVICE); skb_put(skb, len); + netif_dbg(rx_ring->adapter, rx_status, rx_ring->netdev, + "RX allocated small packet. len %d.\n", skb->len); skb->protocol = eth_type_trans(skb, rx_ring->netdev); rx_ring->free_ids[*next_to_clean] = req_id; *next_to_clean = ENA_RX_RING_IDX_ADD(*next_to_clean, descs, @@ -1494,14 +1513,28 @@ static struct sk_buff *ena_rx_skb(struct ena_ring *rx_ring, return skb; } - ena_unmap_rx_buff(rx_ring, rx_info); + buf_len = SKB_DATA_ALIGN(len + buf_offset + tailroom); + + pre_reuse_paddr = dma_unmap_addr(&rx_info->ena_buf, paddr); + + /* If XDP isn't loaded try to reuse part of the RX buffer */ + reuse_rx_buf_page = !is_xdp_loaded && + ena_try_rx_buf_page_reuse(rx_info, buf_len, len, pkt_offset); - skb = ena_alloc_skb(rx_ring, page_addr); + dma_sync_single_for_cpu(rx_ring->dev, + pre_reuse_paddr + pkt_offset, + len, + DMA_FROM_DEVICE); + + if (!reuse_rx_buf_page) + ena_unmap_rx_buff_attrs(rx_ring, rx_info, DMA_ATTR_SKIP_CPU_SYNC); + + skb = ena_alloc_skb(rx_ring, buf_addr, buf_len); if (unlikely(!skb)) return NULL; /* Populate skb's linear part */ - skb_reserve(skb, page_offset); + skb_reserve(skb, buf_offset); skb_put(skb, len); skb->protocol = eth_type_trans(skb, rx_ring->netdev); @@ -1510,7 +1543,8 @@ static struct sk_buff *ena_rx_skb(struct ena_ring *rx_ring, "RX skb updated. len %d. data_len %d\n", skb->len, skb->data_len); - rx_info->page = NULL; + if (!reuse_rx_buf_page) + rx_info->page = NULL; rx_ring->free_ids[*next_to_clean] = req_id; *next_to_clean = @@ -1525,10 +1559,28 @@ static struct sk_buff *ena_rx_skb(struct ena_ring *rx_ring, rx_info = &rx_ring->rx_buffer_info[req_id]; - ena_unmap_rx_buff(rx_ring, rx_info); + /* rx_info->buf_offset includes rx_ring->rx_headroom */ + buf_offset = rx_info->buf_offset; + pkt_offset = buf_offset - rx_ring->rx_headroom; + buf_len = SKB_DATA_ALIGN(len + buf_offset + tailroom); + page_offset = rx_info->page_offset; + + pre_reuse_paddr = dma_unmap_addr(&rx_info->ena_buf, paddr); + + reuse_rx_buf_page = !is_xdp_loaded && + ena_try_rx_buf_page_reuse(rx_info, buf_len, len, pkt_offset); + + dma_sync_single_for_cpu(rx_ring->dev, + pre_reuse_paddr + pkt_offset, + len, + DMA_FROM_DEVICE); + + if (!reuse_rx_buf_page) + ena_unmap_rx_buff_attrs(rx_ring, rx_info, + DMA_ATTR_SKIP_CPU_SYNC); skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, rx_info->page, - rx_info->page_offset, len, ENA_PAGE_SIZE); + page_offset + buf_offset, len, buf_len); } while (1); @@ -1626,7 +1678,7 @@ static int ena_xdp_handle_buff(struct ena_ring *rx_ring, struct xdp_buff *xdp) rx_info = &rx_ring->rx_buffer_info[rx_ring->ena_bufs[0].req_id]; xdp_prepare_buff(xdp, page_address(rx_info->page), - rx_info->page_offset, + rx_info->buf_offset, rx_ring->ena_bufs[0].len, false); /* If for some reason we received a bigger packet than * we expect, then we simply drop it @@ -1638,7 +1690,7 @@ static int ena_xdp_handle_buff(struct ena_ring *rx_ring, struct xdp_buff *xdp) /* The xdp program might expand the headers */ if (ret == ENA_XDP_PASS) { - rx_info->page_offset = xdp->data - xdp->data_hard_start; + rx_info->buf_offset = xdp->data - xdp->data_hard_start; rx_ring->ena_bufs[0].len = xdp->data_end - xdp->data; } @@ -1693,7 +1745,7 @@ static int ena_clean_rx_irq(struct ena_ring *rx_ring, struct napi_struct *napi, /* First descriptor might have an offset set by the device */ rx_info = &rx_ring->rx_buffer_info[rx_ring->ena_bufs[0].req_id]; - rx_info->page_offset += ena_rx_ctx.pkt_offset; + rx_info->buf_offset += ena_rx_ctx.pkt_offset; netif_dbg(rx_ring->adapter, rx_status, rx_ring->netdev, "rx_poll: q %d got packet from ena. descs #: %d l3 proto %d l4 proto %d hash: %x\n", @@ -1723,8 +1775,9 @@ static int ena_clean_rx_irq(struct ena_ring *rx_ring, struct napi_struct *napi, * from RX side. */ if (xdp_verdict & ENA_XDP_FORWARDED) { - ena_unmap_rx_buff(rx_ring, - &rx_ring->rx_buffer_info[req_id]); + ena_unmap_rx_buff_attrs(rx_ring, + &rx_ring->rx_buffer_info[req_id], + 0); rx_ring->rx_buffer_info[req_id].page = NULL; } } @@ -3233,7 +3286,8 @@ static void ena_config_host_info(struct ena_com_dev *ena_dev, struct pci_dev *pd ENA_ADMIN_HOST_INFO_RX_OFFSET_MASK | ENA_ADMIN_HOST_INFO_INTERRUPT_MODERATION_MASK | ENA_ADMIN_HOST_INFO_RX_BUF_MIRRORING_MASK | - ENA_ADMIN_HOST_INFO_RSS_CONFIGURABLE_FUNCTION_KEY_MASK; + ENA_ADMIN_HOST_INFO_RSS_CONFIGURABLE_FUNCTION_KEY_MASK | + ENA_ADMIN_HOST_INFO_RX_PAGE_REUSE_MASK; rc = ena_com_set_host_attributes(ena_dev); if (rc) { diff --git a/drivers/net/ethernet/amazon/ena/ena_netdev.h b/drivers/net/ethernet/amazon/ena/ena_netdev.h index 5a0d4ee761727f5570bc789d9e738a4f07cf5f44..248b715b4d68d57acf15139ef2325ebfd119a5c4 100644 --- a/drivers/net/ethernet/amazon/ena/ena_netdev.h +++ b/drivers/net/ethernet/amazon/ena/ena_netdev.h @@ -51,6 +51,8 @@ #define ENA_DEFAULT_RING_SIZE (1024) #define ENA_MIN_RING_SIZE (256) +#define ENA_MIN_RX_BUF_SIZE (2048) + #define ENA_MIN_NUM_IO_QUEUES (1) #define ENA_TX_WAKEUP_THRESH (MAX_SKB_FRAGS + 2) @@ -175,7 +177,9 @@ struct ena_tx_buffer { struct ena_rx_buffer { struct sk_buff *skb; struct page *page; + dma_addr_t dma_addr; u32 page_offset; + u32 buf_offset; struct ena_com_buf ena_buf; } ____cacheline_aligned; diff --git a/drivers/net/ethernet/amd/pds_core/core.c b/drivers/net/ethernet/amd/pds_core/core.c index 483a070d96fa9c23f8a2986f9a4597b92b0a9eac..f2c79456d74525e3dc8ca47fa620161ba5a1ce1a 100644 --- a/drivers/net/ethernet/amd/pds_core/core.c +++ b/drivers/net/ethernet/amd/pds_core/core.c @@ -196,7 +196,7 @@ int pdsc_qcq_alloc(struct pdsc *pdsc, unsigned int type, unsigned int index, dma_addr_t q_base_pa; int err; - qcq->q.info = vzalloc(num_descs * sizeof(*qcq->q.info)); + qcq->q.info = vcalloc(num_descs, sizeof(*qcq->q.info)); if (!qcq->q.info) { err = -ENOMEM; goto err_out; @@ -219,7 +219,7 @@ int pdsc_qcq_alloc(struct pdsc *pdsc, unsigned int type, unsigned int index, if (err) goto err_out_free_q_info; - qcq->cq.info = vzalloc(num_descs * sizeof(*qcq->cq.info)); + qcq->cq.info = vcalloc(num_descs, sizeof(*qcq->cq.info)); if (!qcq->cq.info) { err = -ENOMEM; goto err_out_free_irq; diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c index 16e7fb2c0daee69605cfabce44e57a885f41bb2a..6a716337f48be17f2a711cbda5144515fc8803d5 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c @@ -2782,9 +2782,9 @@ static bool xgbe_phy_valid_speed_baset_mode(struct xgbe_prv_data *pdata, switch (speed) { case SPEED_10: - /* Supported in ver >= 30H */ + /* Supported in ver 21H and ver >= 30H */ ver = XGMAC_GET_BITS(pdata->hw_feat.version, MAC_VR, SNPSVER); - return (ver >= 0x30) ? true : false; + return (ver == 0x21 || ver >= 0x30); case SPEED_100: case SPEED_1000: return true; @@ -2806,9 +2806,10 @@ static bool xgbe_phy_valid_speed_sfp_mode(struct xgbe_prv_data *pdata, switch (speed) { case SPEED_10: - /* Supported in ver >= 30H */ + /* Supported in ver 21H and ver >= 30H */ ver = XGMAC_GET_BITS(pdata->hw_feat.version, MAC_VR, SNPSVER); - return (ver >= 0x30) && (phy_data->sfp_speed == XGBE_SFP_SPEED_100_1000); + return ((ver == 0x21 || ver >= 0x30) && + (phy_data->sfp_speed == XGBE_SFP_SPEED_100_1000)); case SPEED_100: return (phy_data->sfp_speed == XGBE_SFP_SPEED_100_1000); case SPEED_1000: @@ -3158,9 +3159,9 @@ static bool xgbe_phy_port_mode_mismatch(struct xgbe_prv_data *pdata) struct xgbe_phy_data *phy_data = pdata->phy_data; unsigned int ver; - /* 10 Mbps speed is not supported in ver < 30H */ + /* 10 Mbps speed is supported in ver 21H and ver >= 30H */ ver = XGMAC_GET_BITS(pdata->hw_feat.version, MAC_VR, SNPSVER); - if (ver < 0x30 && (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_10)) + if ((ver < 0x30 && ver != 0x21) && (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_10)) return true; switch (phy_data->port_mode) { diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_macsec.c b/drivers/net/ethernet/aquantia/atlantic/aq_macsec.c index 7eb5851eb95dc3f8a948dc2783489aca6dd45530..6afff8af5e86c54def78b181959f5191a8f7690c 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_macsec.c +++ b/drivers/net/ethernet/aquantia/atlantic/aq_macsec.c @@ -289,7 +289,7 @@ static int aq_get_txsc_stats(struct aq_hw_s *hw, const int sc_idx, static int aq_mdo_dev_open(struct macsec_context *ctx) { - struct aq_nic_s *nic = netdev_priv(ctx->netdev); + struct aq_nic_s *nic = macsec_netdev_priv(ctx->netdev); int ret = 0; if (netif_carrier_ok(nic->ndev)) @@ -300,7 +300,7 @@ static int aq_mdo_dev_open(struct macsec_context *ctx) static int aq_mdo_dev_stop(struct macsec_context *ctx) { - struct aq_nic_s *nic = netdev_priv(ctx->netdev); + struct aq_nic_s *nic = macsec_netdev_priv(ctx->netdev); int i; for (i = 0; i < AQ_MACSEC_MAX_SC; i++) { @@ -439,7 +439,7 @@ static enum aq_macsec_sc_sa sc_sa_from_num_an(const int num_an) static int aq_mdo_add_secy(struct macsec_context *ctx) { - struct aq_nic_s *nic = netdev_priv(ctx->netdev); + struct aq_nic_s *nic = macsec_netdev_priv(ctx->netdev); struct aq_macsec_cfg *cfg = nic->macsec_cfg; const struct macsec_secy *secy = ctx->secy; enum aq_macsec_sc_sa sc_sa; @@ -474,7 +474,7 @@ static int aq_mdo_add_secy(struct macsec_context *ctx) static int aq_mdo_upd_secy(struct macsec_context *ctx) { - struct aq_nic_s *nic = netdev_priv(ctx->netdev); + struct aq_nic_s *nic = macsec_netdev_priv(ctx->netdev); const struct macsec_secy *secy = ctx->secy; int txsc_idx; int ret = 0; @@ -528,7 +528,7 @@ static int aq_clear_txsc(struct aq_nic_s *nic, const int txsc_idx, static int aq_mdo_del_secy(struct macsec_context *ctx) { - struct aq_nic_s *nic = netdev_priv(ctx->netdev); + struct aq_nic_s *nic = macsec_netdev_priv(ctx->netdev); int ret = 0; if (!nic->macsec_cfg) @@ -576,7 +576,7 @@ static int aq_update_txsa(struct aq_nic_s *nic, const unsigned int sc_idx, static int aq_mdo_add_txsa(struct macsec_context *ctx) { - struct aq_nic_s *nic = netdev_priv(ctx->netdev); + struct aq_nic_s *nic = macsec_netdev_priv(ctx->netdev); struct aq_macsec_cfg *cfg = nic->macsec_cfg; const struct macsec_secy *secy = ctx->secy; struct aq_macsec_txsc *aq_txsc; @@ -603,7 +603,7 @@ static int aq_mdo_add_txsa(struct macsec_context *ctx) static int aq_mdo_upd_txsa(struct macsec_context *ctx) { - struct aq_nic_s *nic = netdev_priv(ctx->netdev); + struct aq_nic_s *nic = macsec_netdev_priv(ctx->netdev); struct aq_macsec_cfg *cfg = nic->macsec_cfg; const struct macsec_secy *secy = ctx->secy; struct aq_macsec_txsc *aq_txsc; @@ -652,7 +652,7 @@ static int aq_clear_txsa(struct aq_nic_s *nic, struct aq_macsec_txsc *aq_txsc, static int aq_mdo_del_txsa(struct macsec_context *ctx) { - struct aq_nic_s *nic = netdev_priv(ctx->netdev); + struct aq_nic_s *nic = macsec_netdev_priv(ctx->netdev); struct aq_macsec_cfg *cfg = nic->macsec_cfg; int txsc_idx; int ret = 0; @@ -744,7 +744,7 @@ static int aq_set_rxsc(struct aq_nic_s *nic, const u32 rxsc_idx) static int aq_mdo_add_rxsc(struct macsec_context *ctx) { - struct aq_nic_s *nic = netdev_priv(ctx->netdev); + struct aq_nic_s *nic = macsec_netdev_priv(ctx->netdev); struct aq_macsec_cfg *cfg = nic->macsec_cfg; const u32 rxsc_idx_max = aq_sc_idx_max(cfg->sc_sa); u32 rxsc_idx; @@ -775,7 +775,7 @@ static int aq_mdo_add_rxsc(struct macsec_context *ctx) static int aq_mdo_upd_rxsc(struct macsec_context *ctx) { - struct aq_nic_s *nic = netdev_priv(ctx->netdev); + struct aq_nic_s *nic = macsec_netdev_priv(ctx->netdev); int rxsc_idx; int ret = 0; @@ -838,7 +838,7 @@ static int aq_clear_rxsc(struct aq_nic_s *nic, const int rxsc_idx, static int aq_mdo_del_rxsc(struct macsec_context *ctx) { - struct aq_nic_s *nic = netdev_priv(ctx->netdev); + struct aq_nic_s *nic = macsec_netdev_priv(ctx->netdev); enum aq_clear_type clear_type = AQ_CLEAR_SW; int rxsc_idx; int ret = 0; @@ -906,8 +906,8 @@ static int aq_update_rxsa(struct aq_nic_s *nic, const unsigned int sc_idx, static int aq_mdo_add_rxsa(struct macsec_context *ctx) { + struct aq_nic_s *nic = macsec_netdev_priv(ctx->netdev); const struct macsec_rx_sc *rx_sc = ctx->sa.rx_sa->sc; - struct aq_nic_s *nic = netdev_priv(ctx->netdev); const struct macsec_secy *secy = ctx->secy; struct aq_macsec_rxsc *aq_rxsc; int rxsc_idx; @@ -933,8 +933,8 @@ static int aq_mdo_add_rxsa(struct macsec_context *ctx) static int aq_mdo_upd_rxsa(struct macsec_context *ctx) { + struct aq_nic_s *nic = macsec_netdev_priv(ctx->netdev); const struct macsec_rx_sc *rx_sc = ctx->sa.rx_sa->sc; - struct aq_nic_s *nic = netdev_priv(ctx->netdev); struct aq_macsec_cfg *cfg = nic->macsec_cfg; const struct macsec_secy *secy = ctx->secy; int rxsc_idx; @@ -982,8 +982,8 @@ static int aq_clear_rxsa(struct aq_nic_s *nic, struct aq_macsec_rxsc *aq_rxsc, static int aq_mdo_del_rxsa(struct macsec_context *ctx) { + struct aq_nic_s *nic = macsec_netdev_priv(ctx->netdev); const struct macsec_rx_sc *rx_sc = ctx->sa.rx_sa->sc; - struct aq_nic_s *nic = netdev_priv(ctx->netdev); struct aq_macsec_cfg *cfg = nic->macsec_cfg; int rxsc_idx; int ret = 0; @@ -1000,7 +1000,7 @@ static int aq_mdo_del_rxsa(struct macsec_context *ctx) static int aq_mdo_get_dev_stats(struct macsec_context *ctx) { - struct aq_nic_s *nic = netdev_priv(ctx->netdev); + struct aq_nic_s *nic = macsec_netdev_priv(ctx->netdev); struct aq_macsec_common_stats *stats = &nic->macsec_cfg->stats; struct aq_hw_s *hw = nic->aq_hw; @@ -1020,7 +1020,7 @@ static int aq_mdo_get_dev_stats(struct macsec_context *ctx) static int aq_mdo_get_tx_sc_stats(struct macsec_context *ctx) { - struct aq_nic_s *nic = netdev_priv(ctx->netdev); + struct aq_nic_s *nic = macsec_netdev_priv(ctx->netdev); struct aq_macsec_tx_sc_stats *stats; struct aq_hw_s *hw = nic->aq_hw; struct aq_macsec_txsc *aq_txsc; @@ -1044,7 +1044,7 @@ static int aq_mdo_get_tx_sc_stats(struct macsec_context *ctx) static int aq_mdo_get_tx_sa_stats(struct macsec_context *ctx) { - struct aq_nic_s *nic = netdev_priv(ctx->netdev); + struct aq_nic_s *nic = macsec_netdev_priv(ctx->netdev); struct aq_macsec_cfg *cfg = nic->macsec_cfg; struct aq_macsec_tx_sa_stats *stats; struct aq_hw_s *hw = nic->aq_hw; @@ -1084,7 +1084,7 @@ static int aq_mdo_get_tx_sa_stats(struct macsec_context *ctx) static int aq_mdo_get_rx_sc_stats(struct macsec_context *ctx) { - struct aq_nic_s *nic = netdev_priv(ctx->netdev); + struct aq_nic_s *nic = macsec_netdev_priv(ctx->netdev); struct aq_macsec_cfg *cfg = nic->macsec_cfg; struct aq_macsec_rx_sa_stats *stats; struct aq_hw_s *hw = nic->aq_hw; @@ -1129,7 +1129,7 @@ static int aq_mdo_get_rx_sc_stats(struct macsec_context *ctx) static int aq_mdo_get_rx_sa_stats(struct macsec_context *ctx) { - struct aq_nic_s *nic = netdev_priv(ctx->netdev); + struct aq_nic_s *nic = macsec_netdev_priv(ctx->netdev); struct aq_macsec_cfg *cfg = nic->macsec_cfg; struct aq_macsec_rx_sa_stats *stats; struct aq_hw_s *hw = nic->aq_hw; @@ -1399,7 +1399,7 @@ static void aq_check_txsa_expiration(struct aq_nic_s *nic) #define AQ_LOCKED_MDO_DEF(mdo) \ static int aq_locked_mdo_##mdo(struct macsec_context *ctx) \ { \ - struct aq_nic_s *nic = netdev_priv(ctx->netdev); \ + struct aq_nic_s *nic = macsec_netdev_priv(ctx->netdev); \ int ret; \ mutex_lock(&nic->macsec_mutex); \ ret = aq_mdo_##mdo(ctx); \ diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c index 7f933175cbdac9aa643246190a0f6b297af19414..4de22eed099a8443fb8ac9fb88199baeae36bbb7 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c +++ b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c @@ -532,10 +532,10 @@ static bool aq_add_rx_fragment(struct device *dev, buff_->rxdata.pg_off, buff_->len, DMA_FROM_DEVICE); - skb_frag_off_set(frag, buff_->rxdata.pg_off); - skb_frag_size_set(frag, buff_->len); sinfo->xdp_frags_size += buff_->len; - __skb_frag_set_page(frag, buff_->rxdata.page); + skb_frag_fill_page_desc(frag, buff_->rxdata.page, + buff_->rxdata.pg_off, + buff_->len); buff_->is_cleaned = 1; diff --git a/drivers/net/ethernet/arc/emac.h b/drivers/net/ethernet/arc/emac.h index d820ae03a9660df1672ba6b51aa538cfd8265210..0e244f0e25fd36c757ba80999a84a1249dee31cf 100644 --- a/drivers/net/ethernet/arc/emac.h +++ b/drivers/net/ethernet/arc/emac.h @@ -220,6 +220,6 @@ static inline void arc_reg_clr(struct arc_emac_priv *priv, int reg, int mask) int arc_mdio_probe(struct arc_emac_priv *priv); int arc_mdio_remove(struct arc_emac_priv *priv); int arc_emac_probe(struct net_device *ndev, int interface); -int arc_emac_remove(struct net_device *ndev); +void arc_emac_remove(struct net_device *ndev); #endif /* ARC_EMAC_H */ diff --git a/drivers/net/ethernet/arc/emac_arc.c b/drivers/net/ethernet/arc/emac_arc.c index 800620b8f10d41e2094fb5c28d25bab24302a30d..ce3147e886a10ddb3c50b3df7b260a8e8ffa210b 100644 --- a/drivers/net/ethernet/arc/emac_arc.c +++ b/drivers/net/ethernet/arc/emac_arc.c @@ -61,11 +61,11 @@ static int emac_arc_probe(struct platform_device *pdev) static int emac_arc_remove(struct platform_device *pdev) { struct net_device *ndev = platform_get_drvdata(pdev); - int err; - err = arc_emac_remove(ndev); + arc_emac_remove(ndev); free_netdev(ndev); - return err; + + return 0; } static const struct of_device_id emac_arc_dt_ids[] = { diff --git a/drivers/net/ethernet/arc/emac_main.c b/drivers/net/ethernet/arc/emac_main.c index ba0646b3b122e9a79b05d7c72fb4c441f23a432b..2b427d8a18315215344838bebccf7d9ff3e91226 100644 --- a/drivers/net/ethernet/arc/emac_main.c +++ b/drivers/net/ethernet/arc/emac_main.c @@ -1008,7 +1008,7 @@ int arc_emac_probe(struct net_device *ndev, int interface) } EXPORT_SYMBOL_GPL(arc_emac_probe); -int arc_emac_remove(struct net_device *ndev) +void arc_emac_remove(struct net_device *ndev) { struct arc_emac_priv *priv = netdev_priv(ndev); @@ -1019,8 +1019,6 @@ int arc_emac_remove(struct net_device *ndev) if (!IS_ERR(priv->clk)) clk_disable_unprepare(priv->clk); - - return 0; } EXPORT_SYMBOL_GPL(arc_emac_remove); diff --git a/drivers/net/ethernet/arc/emac_rockchip.c b/drivers/net/ethernet/arc/emac_rockchip.c index 1c9ca3bcb87147d49811ca5cb2bcfafd1c5bda34..509101112279d7618e0d3fa631a3ca9920eff866 100644 --- a/drivers/net/ethernet/arc/emac_rockchip.c +++ b/drivers/net/ethernet/arc/emac_rockchip.c @@ -248,9 +248,8 @@ static int emac_rockchip_remove(struct platform_device *pdev) { struct net_device *ndev = platform_get_drvdata(pdev); struct rockchip_priv_data *priv = netdev_priv(ndev); - int err; - err = arc_emac_remove(ndev); + arc_emac_remove(ndev); clk_disable_unprepare(priv->refclk); @@ -261,7 +260,7 @@ static int emac_rockchip_remove(struct platform_device *pdev) clk_disable_unprepare(priv->macclk); free_netdev(ndev); - return err; + return 0; } static struct platform_driver emac_rockchip_driver = { diff --git a/drivers/net/ethernet/broadcom/bgmac.c b/drivers/net/ethernet/broadcom/bgmac.c index 1761df8fb7f96888017e0a4f7cad0c22aad67c77..10c7c232cc4ecce0d719435c8f3b14060de0dc58 100644 --- a/drivers/net/ethernet/broadcom/bgmac.c +++ b/drivers/net/ethernet/broadcom/bgmac.c @@ -1492,8 +1492,6 @@ int bgmac_enet_probe(struct bgmac *bgmac) bgmac->in_init = true; - bgmac_chip_intrs_off(bgmac); - net_dev->irq = bgmac->irq; SET_NETDEV_DEV(net_dev, bgmac->dev); dev_set_drvdata(bgmac->dev, bgmac); @@ -1511,6 +1509,8 @@ int bgmac_enet_probe(struct bgmac *bgmac) */ bgmac_clk_enable(bgmac, 0); + bgmac_chip_intrs_off(bgmac); + /* This seems to be fixing IRQ by assigning OOB #6 to the core */ if (!(bgmac->feature_flags & BGMAC_FEAT_IDM_MASK)) { if (bgmac->feature_flags & BGMAC_FEAT_IRQ_ID_OOB_6) diff --git a/drivers/net/ethernet/broadcom/bnx2.c b/drivers/net/ethernet/broadcom/bnx2.c index 466e1d62bcf6ea0bebeb40652987c1734a710da3..0d917a9699c586809ed6529bc01366a0bee17f29 100644 --- a/drivers/net/ethernet/broadcom/bnx2.c +++ b/drivers/net/ethernet/broadcom/bnx2.c @@ -2955,7 +2955,6 @@ bnx2_reuse_rx_skb_pages(struct bnx2 *bp, struct bnx2_rx_ring_info *rxr, shinfo = skb_shinfo(skb); shinfo->nr_frags--; page = skb_frag_page(&shinfo->frags[shinfo->nr_frags]); - __skb_frag_set_page(&shinfo->frags[shinfo->nr_frags], NULL); cons_rx_pg->page = page; dev_kfree_skb(skb); diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index b499bc9c4e06701c3d5bc02e0898d5c79ee1b267..e5b54e6025bece04206b69ba9556908aaa53e46e 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -1085,9 +1085,8 @@ static u32 __bnxt_rx_agg_pages(struct bnxt *bp, RX_AGG_CMP_LEN) >> RX_AGG_CMP_LEN_SHIFT; cons_rx_buf = &rxr->rx_agg_ring[cons]; - skb_frag_off_set(frag, cons_rx_buf->offset); - skb_frag_size_set(frag, frag_len); - __skb_frag_set_page(frag, cons_rx_buf->page); + skb_frag_fill_page_desc(frag, cons_rx_buf->page, + cons_rx_buf->offset, frag_len); shinfo->nr_frags = i + 1; __clear_bit(cons, rxr->rx_agg_bmap); @@ -1103,10 +1102,7 @@ static u32 __bnxt_rx_agg_pages(struct bnxt *bp, xdp_buff_set_frag_pfmemalloc(xdp); if (bnxt_alloc_rx_page(bp, rxr, prod, GFP_ATOMIC) != 0) { - unsigned int nr_frags; - - nr_frags = --shinfo->nr_frags; - __skb_frag_set_page(&shinfo->frags[nr_frags], NULL); + --shinfo->nr_frags; cons_rx_buf->page = page; /* Update prod since possibly some pages have been diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c index 2f1a1f2d2157f252504a67dbd3959c19a24f0950..1467b94a6427fc6ce1af71cce971a203f5d6484a 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c @@ -468,6 +468,7 @@ static void bnxt_vf_rep_netdev_init(struct bnxt *bp, struct bnxt_vf_rep *vf_rep, struct net_device *pf_dev = bp->dev; u16 max_mtu; + SET_NETDEV_DEV(dev, &bp->pdev->dev); dev->netdev_ops = &bnxt_vf_rep_netdev_ops; dev->ethtool_ops = &bnxt_vf_rep_ethtool_ops; /* Just inherit all the featues of the parent PF as the VF-R diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet_wol.c b/drivers/net/ethernet/broadcom/genet/bcmgenet_wol.c index 3a4b6cb7b7b95b6dabfec545aaedec86b55c38c9..7a41cad5788f4edd6691552901f4b2eb8fdebc36 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmgenet_wol.c +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet_wol.c @@ -42,6 +42,12 @@ void bcmgenet_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) struct bcmgenet_priv *priv = netdev_priv(dev); struct device *kdev = &priv->pdev->dev; + if (dev->phydev) { + phy_ethtool_get_wol(dev->phydev, wol); + if (wol->supported) + return; + } + if (!device_can_wakeup(kdev)) { wol->supported = 0; wol->wolopts = 0; @@ -63,6 +69,14 @@ int bcmgenet_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) { struct bcmgenet_priv *priv = netdev_priv(dev); struct device *kdev = &priv->pdev->dev; + int ret; + + /* Try Wake-on-LAN from the PHY first */ + if (dev->phydev) { + ret = phy_ethtool_set_wol(dev->phydev, wol); + if (ret != -EOPNOTSUPP) + return ret; + } if (!device_can_wakeup(kdev)) return -ENOTSUPP; diff --git a/drivers/net/ethernet/broadcom/genet/bcmmii.c b/drivers/net/ethernet/broadcom/genet/bcmmii.c index c15ed0acdb777deef01816683e4024dcc27e5277..0092e46c46f83c668bff5833a0d1b3e89c6b63bf 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmmii.c +++ b/drivers/net/ethernet/broadcom/genet/bcmmii.c @@ -673,5 +673,7 @@ void bcmgenet_mii_exit(struct net_device *dev) if (of_phy_is_fixed_link(dn)) of_phy_deregister_fixed_link(dn); of_node_put(priv->phy_dn); + clk_prepare_enable(priv->clk); platform_device_unregister(priv->mii_pdev); + clk_disable_unprepare(priv->clk); } diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index 58747292521d8199a85173cad8f2d8afc4473a99..5ef073a79ce94bc7f83f88c9391b882a6ed36cc5 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -57,6 +57,7 @@ #include #include +#include #include #include @@ -224,6 +225,7 @@ MODULE_AUTHOR("David S. Miller (davem@redhat.com) and Jeff Garzik (jgarzik@pobox MODULE_DESCRIPTION("Broadcom Tigon3 ethernet driver"); MODULE_LICENSE("GPL"); MODULE_FIRMWARE(FIRMWARE_TG3); +MODULE_FIRMWARE(FIRMWARE_TG357766); MODULE_FIRMWARE(FIRMWARE_TG3TSO); MODULE_FIRMWARE(FIRMWARE_TG3TSO5); diff --git a/drivers/net/ethernet/cadence/macb.h b/drivers/net/ethernet/cadence/macb.h index cfbdd00227649d05a0d8ec51e5a786678a94609d..78c972bb1d962368ed0c62b5f3d28e47047f1b34 100644 --- a/drivers/net/ethernet/cadence/macb.h +++ b/drivers/net/ethernet/cadence/macb.h @@ -82,6 +82,7 @@ #define GEM_NCFGR 0x0004 /* Network Config */ #define GEM_USRIO 0x000c /* User IO */ #define GEM_DMACFG 0x0010 /* DMA Configuration */ +#define GEM_PBUFRXCUT 0x0044 /* RX Partial Store and Forward */ #define GEM_JML 0x0048 /* Jumbo Max Length */ #define GEM_HS_MAC_CONFIG 0x0050 /* GEM high speed config */ #define GEM_HRB 0x0080 /* Hash Bottom */ @@ -347,6 +348,10 @@ #define GEM_ADDR64_SIZE 1 +/* Bitfields in PBUFRXCUT */ +#define GEM_ENCUTTHRU_OFFSET 31 /* Enable RX partial store and forward */ +#define GEM_ENCUTTHRU_SIZE 1 + /* Bitfields in NSR */ #define MACB_NSR_LINK_OFFSET 0 /* pcs_link_state */ #define MACB_NSR_LINK_SIZE 1 @@ -513,6 +518,8 @@ #define GEM_TX_PKT_BUFF_OFFSET 21 #define GEM_TX_PKT_BUFF_SIZE 1 +#define GEM_RX_PBUF_ADDR_OFFSET 22 +#define GEM_RX_PBUF_ADDR_SIZE 4 /* Bitfields in DCFG5. */ #define GEM_TSU_OFFSET 8 @@ -521,6 +528,8 @@ /* Bitfields in DCFG6. */ #define GEM_PBUF_LSO_OFFSET 27 #define GEM_PBUF_LSO_SIZE 1 +#define GEM_PBUF_CUTTHRU_OFFSET 25 +#define GEM_PBUF_CUTTHRU_SIZE 1 #define GEM_DAW64_OFFSET 23 #define GEM_DAW64_SIZE 1 @@ -1181,6 +1190,7 @@ struct macb_config { struct clk **hclk, struct clk **tx_clk, struct clk **rx_clk, struct clk **tsu_clk); int (*init)(struct platform_device *pdev); + unsigned int max_tx_length; int jumbo_max_len; const struct macb_usrio_config *usrio; }; @@ -1289,6 +1299,9 @@ struct macb { u32 wol; + /* holds value of rx watermark value for pbuf_rxcutthru register */ + u32 rx_watermark; + struct macb_ptp_info *ptp_info; /* macb-ptp interface */ struct phy *sgmii_phy; /* for ZynqMP SGMII mode */ diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c index 29a1199dad146952ac63a21e196e6c29a89b7d1b..f6a0f12a6d520f7c20eae01b6c39cc64faf22553 100644 --- a/drivers/net/ethernet/cadence/macb_main.c +++ b/drivers/net/ethernet/cadence/macb_main.c @@ -563,7 +563,7 @@ static void macb_set_tx_clk(struct macb *bp, int speed) netdev_err(bp->dev, "adjusting tx_clk failed.\n"); } -static void macb_usx_pcs_link_up(struct phylink_pcs *pcs, unsigned int mode, +static void macb_usx_pcs_link_up(struct phylink_pcs *pcs, unsigned int neg_mode, phy_interface_t interface, int speed, int duplex) { @@ -596,7 +596,7 @@ static void macb_usx_pcs_get_state(struct phylink_pcs *pcs, } static int macb_usx_pcs_config(struct phylink_pcs *pcs, - unsigned int mode, + unsigned int neg_mode, phy_interface_t interface, const unsigned long *advertising, bool permit_pause_to_mac) @@ -621,7 +621,7 @@ static void macb_pcs_an_restart(struct phylink_pcs *pcs) } static int macb_pcs_config(struct phylink_pcs *pcs, - unsigned int mode, + unsigned int neg_mode, phy_interface_t interface, const unsigned long *advertising, bool permit_pause_to_mac) @@ -862,7 +862,9 @@ static int macb_mii_probe(struct net_device *dev) struct macb *bp = netdev_priv(dev); bp->phylink_sgmii_pcs.ops = &macb_phylink_pcs_ops; + bp->phylink_sgmii_pcs.neg_mode = true; bp->phylink_usx_pcs.ops = &macb_phylink_usx_pcs_ops; + bp->phylink_usx_pcs.neg_mode = true; bp->phylink_config.dev = &dev->dev; bp->phylink_config.type = PHYLINK_NETDEV; @@ -2635,6 +2637,9 @@ static void macb_reset_hw(struct macb *bp) macb_writel(bp, TSR, -1); macb_writel(bp, RSR, -1); + /* Disable RX partial store and forward and reset watermark value */ + gem_writel(bp, PBUFRXCUT, 0); + /* Disable all interrupts */ for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) { queue_writel(queue, IDR, -1); @@ -2792,6 +2797,10 @@ static void macb_init_hw(struct macb *bp) bp->rx_frm_len_mask = MACB_RX_JFRMLEN_MASK; macb_configure_dma(bp); + + /* Enable RX partial store and forward and set watermark */ + if (bp->rx_watermark) + gem_writel(bp, PBUFRXCUT, (bp->rx_watermark | GEM_BIT(ENCUTTHRU))); } /* The hash address register is 64 bits long and takes up two @@ -4117,14 +4126,12 @@ static int macb_init(struct platform_device *pdev) /* setup appropriated routines according to adapter type */ if (macb_is_gem(bp)) { - bp->max_tx_length = GEM_MAX_TX_LEN; bp->macbgem_ops.mog_alloc_rx_buffers = gem_alloc_rx_buffers; bp->macbgem_ops.mog_free_rx_buffers = gem_free_rx_buffers; bp->macbgem_ops.mog_init_rings = gem_init_rings; bp->macbgem_ops.mog_rx = gem_rx; dev->ethtool_ops = &gem_ethtool_ops; } else { - bp->max_tx_length = MACB_MAX_TX_LEN; bp->macbgem_ops.mog_alloc_rx_buffers = macb_alloc_rx_buffers; bp->macbgem_ops.mog_free_rx_buffers = macb_free_rx_buffers; bp->macbgem_ops.mog_init_rings = macb_init_rings; @@ -4861,7 +4868,8 @@ static const struct macb_config mpfs_config = { .clk_init = macb_clk_init, .init = init_reset_optional, .usrio = &macb_default_usrio, - .jumbo_max_len = 10240, + .max_tx_length = 4040, /* Cadence Erratum 1686 */ + .jumbo_max_len = 4040, }; static const struct macb_config sama7g5_gem_config = { @@ -4947,6 +4955,7 @@ static int macb_probe(struct platform_device *pdev) phy_interface_t interface; struct net_device *dev; struct resource *regs; + u32 wtrmrk_rst_val; void __iomem *mem; struct macb *bp; int err, val; @@ -5012,6 +5021,13 @@ static int macb_probe(struct platform_device *pdev) if (macb_config) bp->jumbo_max_len = macb_config->jumbo_max_len; + if (!hw_is_gem(bp->regs, bp->native_io)) + bp->max_tx_length = MACB_MAX_TX_LEN; + else if (macb_config->max_tx_length) + bp->max_tx_length = macb_config->max_tx_length; + else + bp->max_tx_length = GEM_MAX_TX_LEN; + bp->wol = 0; if (of_property_read_bool(np, "magic-packet")) bp->wol |= MACB_WOL_HAS_MAGIC_PACKET; @@ -5019,6 +5035,25 @@ static int macb_probe(struct platform_device *pdev) bp->usrio = macb_config->usrio; + /* By default we set to partial store and forward mode for zynqmp. + * Disable if not set in devicetree. + */ + if (GEM_BFEXT(PBUF_CUTTHRU, gem_readl(bp, DCFG6))) { + err = of_property_read_u32(bp->pdev->dev.of_node, + "cdns,rx-watermark", + &bp->rx_watermark); + + if (!err) { + /* Disable partial store and forward in case of error or + * invalid watermark value + */ + wtrmrk_rst_val = (1 << (GEM_BFEXT(RX_PBUF_ADDR, gem_readl(bp, DCFG2)))) - 1; + if (bp->rx_watermark > wtrmrk_rst_val || !bp->rx_watermark) { + dev_info(&bp->pdev->dev, "Invalid watermark value\n"); + bp->rx_watermark = 0; + } + } + } spin_lock_init(&bp->lock); /* setup capabilities */ diff --git a/drivers/net/ethernet/cavium/Kconfig b/drivers/net/ethernet/cavium/Kconfig index 1c76c95b0b275f88110b9995f78dd270ffc87a1d..ca742cc146d798aea9145f15ebfc0c485d6c2487 100644 --- a/drivers/net/ethernet/cavium/Kconfig +++ b/drivers/net/ethernet/cavium/Kconfig @@ -62,6 +62,9 @@ config CAVIUM_PTP Precision Time Protocol or other purposes. Timestamps can be used in BGX, TNS, GTI, and NIC blocks. +config LIQUIDIO_CORE + tristate + config LIQUIDIO tristate "Cavium LiquidIO support" depends on 64BIT && PCI @@ -69,6 +72,7 @@ config LIQUIDIO depends on PTP_1588_CLOCK_OPTIONAL select FW_LOADER select LIBCRC32C + select LIQUIDIO_CORE select NET_DEVLINK help This driver supports Cavium LiquidIO Intelligent Server Adapters @@ -92,6 +96,7 @@ config LIQUIDIO_VF tristate "Cavium LiquidIO VF support" depends on 64BIT && PCI_MSI depends on PTP_1588_CLOCK_OPTIONAL + select LIQUIDIO_CORE help This driver supports Cavium LiquidIO Intelligent Server Adapter based on CN23XX chips. diff --git a/drivers/net/ethernet/cavium/liquidio/Makefile b/drivers/net/ethernet/cavium/liquidio/Makefile index bc99375020431c2722f39d4a351341d934e5214b..4ee80af88e79eeb7b2e762adf15e1f33ca2f9225 100644 --- a/drivers/net/ethernet/cavium/liquidio/Makefile +++ b/drivers/net/ethernet/cavium/liquidio/Makefile @@ -3,7 +3,9 @@ # Cavium Liquidio ethernet device driver # -common-objs := lio_ethtool.o \ +obj-$(CONFIG_LIQUIDIO_CORE) += liquidio-core.o +liquidio-core-y := \ + lio_ethtool.o \ lio_core.o \ request_manager.o \ response_manager.o \ @@ -18,7 +20,7 @@ common-objs := lio_ethtool.o \ octeon_nic.o obj-$(CONFIG_LIQUIDIO) += liquidio.o -liquidio-y := lio_main.o octeon_console.o lio_vf_rep.o $(common-objs) +liquidio-y := lio_main.o octeon_console.o lio_vf_rep.o obj-$(CONFIG_LIQUIDIO_VF) += liquidio_vf.o -liquidio_vf-y := lio_vf_main.o $(common-objs) +liquidio_vf-y := lio_vf_main.o diff --git a/drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.c b/drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.c index 9ed3d1ab2ca58020c7bef7469b4fd8d110aa09f7..068ed52b66c94dfd75d038c2578740d3c8664732 100644 --- a/drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.c +++ b/drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.c @@ -719,12 +719,10 @@ static int cn23xx_setup_pf_mbox(struct octeon_device *oct) for (i = 0; i < oct->sriov_info.max_vfs; i++) { q_no = i * oct->sriov_info.rings_per_vf; - mbox = vmalloc(sizeof(*mbox)); + mbox = vzalloc(sizeof(*mbox)); if (!mbox) goto free_mbox; - memset(mbox, 0, sizeof(struct octeon_mbox)); - spin_lock_init(&mbox->lock); mbox->oct_dev = oct; @@ -1377,6 +1375,7 @@ int setup_cn23xx_octeon_pf_device(struct octeon_device *oct) return 0; } +EXPORT_SYMBOL_GPL(setup_cn23xx_octeon_pf_device); int validate_cn23xx_pf_config_info(struct octeon_device *oct, struct octeon_config *conf23xx) @@ -1435,6 +1434,7 @@ int cn23xx_fw_loaded(struct octeon_device *oct) val = octeon_read_csr64(oct, CN23XX_SLI_SCRATCH2); return (val >> SCR2_BIT_FW_LOADED) & 1ULL; } +EXPORT_SYMBOL_GPL(cn23xx_fw_loaded); void cn23xx_tell_vf_its_macaddr_changed(struct octeon_device *oct, int vfidx, u8 *mac) @@ -1456,6 +1456,7 @@ void cn23xx_tell_vf_its_macaddr_changed(struct octeon_device *oct, int vfidx, octeon_mbox_write(oct, &mbox_cmd); } } +EXPORT_SYMBOL_GPL(cn23xx_tell_vf_its_macaddr_changed); static void cn23xx_get_vf_stats_callback(struct octeon_device *oct, @@ -1510,3 +1511,4 @@ int cn23xx_get_vf_stats(struct octeon_device *oct, int vfidx, return 0; } +EXPORT_SYMBOL_GPL(cn23xx_get_vf_stats); diff --git a/drivers/net/ethernet/cavium/liquidio/cn23xx_vf_device.c b/drivers/net/ethernet/cavium/liquidio/cn23xx_vf_device.c index fda49404968c330cf2e9065e54bd720bd2f42e9c..dd5d80fee24f0f8175fd08488e19d5a752f7c9ea 100644 --- a/drivers/net/ethernet/cavium/liquidio/cn23xx_vf_device.c +++ b/drivers/net/ethernet/cavium/liquidio/cn23xx_vf_device.c @@ -279,12 +279,10 @@ static int cn23xx_setup_vf_mbox(struct octeon_device *oct) { struct octeon_mbox *mbox = NULL; - mbox = vmalloc(sizeof(*mbox)); + mbox = vzalloc(sizeof(*mbox)); if (!mbox) return 1; - memset(mbox, 0, sizeof(struct octeon_mbox)); - spin_lock_init(&mbox->lock); mbox->oct_dev = oct; @@ -386,6 +384,7 @@ void cn23xx_vf_ask_pf_to_do_flr(struct octeon_device *oct) octeon_mbox_write(oct, &mbox_cmd); } +EXPORT_SYMBOL_GPL(cn23xx_vf_ask_pf_to_do_flr); static void octeon_pfvf_hs_callback(struct octeon_device *oct, struct octeon_mbox_cmd *cmd, @@ -468,6 +467,7 @@ int cn23xx_octeon_pfvf_handshake(struct octeon_device *oct) return 0; } +EXPORT_SYMBOL_GPL(cn23xx_octeon_pfvf_handshake); static void cn23xx_handle_vf_mbox_intr(struct octeon_ioq_vector *ioq_vector) { @@ -680,3 +680,4 @@ int cn23xx_setup_octeon_vf_device(struct octeon_device *oct) return 0; } +EXPORT_SYMBOL_GPL(cn23xx_setup_octeon_vf_device); diff --git a/drivers/net/ethernet/cavium/liquidio/cn66xx_device.c b/drivers/net/ethernet/cavium/liquidio/cn66xx_device.c index 39643be8c30a9753cd0b6c07d8aa99af7d1ecae0..93fccfec288d47305b9f17e4ef6c8cbb3dc4d5e8 100644 --- a/drivers/net/ethernet/cavium/liquidio/cn66xx_device.c +++ b/drivers/net/ethernet/cavium/liquidio/cn66xx_device.c @@ -697,6 +697,7 @@ int lio_setup_cn66xx_octeon_device(struct octeon_device *oct) return 0; } +EXPORT_SYMBOL_GPL(lio_setup_cn66xx_octeon_device); int lio_validate_cn6xxx_config_info(struct octeon_device *oct, struct octeon_config *conf6xxx) diff --git a/drivers/net/ethernet/cavium/liquidio/cn68xx_device.c b/drivers/net/ethernet/cavium/liquidio/cn68xx_device.c index 30254e4cf70f7682c5a9f57f610a8baaaa042ed7..b5103def37613c88015c343e3ca2612727337e7e 100644 --- a/drivers/net/ethernet/cavium/liquidio/cn68xx_device.c +++ b/drivers/net/ethernet/cavium/liquidio/cn68xx_device.c @@ -181,3 +181,4 @@ int lio_setup_cn68xx_octeon_device(struct octeon_device *oct) return 0; } +EXPORT_SYMBOL_GPL(lio_setup_cn68xx_octeon_device); diff --git a/drivers/net/ethernet/cavium/liquidio/lio_core.c b/drivers/net/ethernet/cavium/liquidio/lio_core.c index 882b2be06ea0e0ac7c9031f95e7757364e12e532..9cc6303c82ffb7f2680d3a01e4ca4c7fb227574c 100644 --- a/drivers/net/ethernet/cavium/liquidio/lio_core.c +++ b/drivers/net/ethernet/cavium/liquidio/lio_core.c @@ -26,6 +26,9 @@ #include "octeon_main.h" #include "octeon_network.h" +MODULE_AUTHOR("Cavium Networks, "); +MODULE_LICENSE("GPL"); + /* OOM task polling interval */ #define LIO_OOM_POLL_INTERVAL_MS 250 @@ -71,6 +74,7 @@ void lio_delete_glists(struct lio *lio) kfree(lio->glist); lio->glist = NULL; } +EXPORT_SYMBOL_GPL(lio_delete_glists); /** * lio_setup_glists - Setup gather lists @@ -154,6 +158,7 @@ int lio_setup_glists(struct octeon_device *oct, struct lio *lio, int num_iqs) return 0; } +EXPORT_SYMBOL_GPL(lio_setup_glists); int liquidio_set_feature(struct net_device *netdev, int cmd, u16 param1) { @@ -180,6 +185,7 @@ int liquidio_set_feature(struct net_device *netdev, int cmd, u16 param1) } return ret; } +EXPORT_SYMBOL_GPL(liquidio_set_feature); void octeon_report_tx_completion_to_bql(void *txq, unsigned int pkts_compl, unsigned int bytes_compl) @@ -395,6 +401,7 @@ void liquidio_link_ctrl_cmd_completion(void *nctrl_ptr) nctrl->ncmd.s.cmd); } } +EXPORT_SYMBOL_GPL(liquidio_link_ctrl_cmd_completion); void octeon_pf_changed_vf_macaddr(struct octeon_device *oct, u8 *mac) { @@ -478,6 +485,7 @@ int setup_rx_oom_poll_fn(struct net_device *netdev) return 0; } +EXPORT_SYMBOL_GPL(setup_rx_oom_poll_fn); void cleanup_rx_oom_poll_fn(struct net_device *netdev) { @@ -495,6 +503,7 @@ void cleanup_rx_oom_poll_fn(struct net_device *netdev) } } } +EXPORT_SYMBOL_GPL(cleanup_rx_oom_poll_fn); /* Runs in interrupt context. */ static void lio_update_txq_status(struct octeon_device *oct, int iq_num) @@ -899,6 +908,7 @@ int liquidio_setup_io_queues(struct octeon_device *octeon_dev, int ifidx, return 0; } +EXPORT_SYMBOL_GPL(liquidio_setup_io_queues); static int liquidio_schedule_msix_droq_pkt_handler(struct octeon_droq *droq, u64 ret) @@ -1194,6 +1204,7 @@ int octeon_setup_interrupt(struct octeon_device *oct, u32 num_ioqs) } return 0; } +EXPORT_SYMBOL_GPL(octeon_setup_interrupt); /** * liquidio_change_mtu - Net device change_mtu @@ -1256,6 +1267,7 @@ int liquidio_change_mtu(struct net_device *netdev, int new_mtu) WRITE_ONCE(sc->caller_is_done, true); return 0; } +EXPORT_SYMBOL_GPL(liquidio_change_mtu); int lio_wait_for_clean_oq(struct octeon_device *oct) { @@ -1279,6 +1291,7 @@ int lio_wait_for_clean_oq(struct octeon_device *oct) return pending_pkts; } +EXPORT_SYMBOL_GPL(lio_wait_for_clean_oq); static void octnet_nic_stats_callback(struct octeon_device *oct_dev, @@ -1509,6 +1522,7 @@ void lio_fetch_stats(struct work_struct *work) return; } +EXPORT_SYMBOL_GPL(lio_fetch_stats); int liquidio_set_speed(struct lio *lio, int speed) { @@ -1659,6 +1673,7 @@ int liquidio_get_speed(struct lio *lio) return retval; } +EXPORT_SYMBOL_GPL(liquidio_get_speed); int liquidio_set_fec(struct lio *lio, int on_off) { @@ -1812,3 +1827,4 @@ int liquidio_get_fec(struct lio *lio) return retval; } +EXPORT_SYMBOL_GPL(liquidio_get_fec); diff --git a/drivers/net/ethernet/cavium/liquidio/lio_ethtool.c b/drivers/net/ethernet/cavium/liquidio/lio_ethtool.c index 2c10ae3f7fc143f3e3fe048f5395fe6ebbdbe135..9d56181a301f12263e9e74f64c71b9c2d55e1986 100644 --- a/drivers/net/ethernet/cavium/liquidio/lio_ethtool.c +++ b/drivers/net/ethernet/cavium/liquidio/lio_ethtool.c @@ -3180,3 +3180,4 @@ void liquidio_set_ethtool_ops(struct net_device *netdev) else netdev->ethtool_ops = &lio_ethtool_ops; } +EXPORT_SYMBOL_GPL(liquidio_set_ethtool_ops); diff --git a/drivers/net/ethernet/cavium/liquidio/lio_main.c b/drivers/net/ethernet/cavium/liquidio/lio_main.c index 9bd1d2d7027dd7cfa5d08975029e8f233cfe8a8a..100daadbea2a66ff648250abef332ff6c4c94228 100644 --- a/drivers/net/ethernet/cavium/liquidio/lio_main.c +++ b/drivers/net/ethernet/cavium/liquidio/lio_main.c @@ -191,8 +191,7 @@ static void octeon_droq_bh(struct tasklet_struct *t) static int lio_wait_for_oq_pkts(struct octeon_device *oct) { - struct octeon_device_priv *oct_priv = - (struct octeon_device_priv *)oct->priv; + struct octeon_device_priv *oct_priv = oct->priv; int retry = 100, pkt_cnt = 0, pending_pkts = 0; int i; @@ -950,8 +949,7 @@ static void octeon_destroy_resources(struct octeon_device *oct) { int i, refcount; struct msix_entry *msix_entries; - struct octeon_device_priv *oct_priv = - (struct octeon_device_priv *)oct->priv; + struct octeon_device_priv *oct_priv = oct->priv; struct handshake *hs; @@ -1211,8 +1209,7 @@ static int send_rx_ctrl_cmd(struct lio *lio, int start_stop) static void liquidio_destroy_nic_device(struct octeon_device *oct, int ifidx) { struct net_device *netdev = oct->props[ifidx].netdev; - struct octeon_device_priv *oct_priv = - (struct octeon_device_priv *)oct->priv; + struct octeon_device_priv *oct_priv = oct->priv; struct napi_struct *napi, *n; struct lio *lio; @@ -1774,8 +1771,7 @@ static int liquidio_open(struct net_device *netdev) { struct lio *lio = GET_LIO(netdev); struct octeon_device *oct = lio->oct_dev; - struct octeon_device_priv *oct_priv = - (struct octeon_device_priv *)oct->priv; + struct octeon_device_priv *oct_priv = oct->priv; struct napi_struct *napi, *n; int ret = 0; @@ -1855,8 +1851,7 @@ static int liquidio_stop(struct net_device *netdev) { struct lio *lio = GET_LIO(netdev); struct octeon_device *oct = lio->oct_dev; - struct octeon_device_priv *oct_priv = - (struct octeon_device_priv *)oct->priv; + struct octeon_device_priv *oct_priv = oct->priv; struct napi_struct *napi, *n; int ret = 0; @@ -4057,8 +4052,7 @@ static int octeon_device_init(struct octeon_device *octeon_dev) char bootcmd[] = "\n"; char *dbg_enb = NULL; enum lio_fw_state fw_state; - struct octeon_device_priv *oct_priv = - (struct octeon_device_priv *)octeon_dev->priv; + struct octeon_device_priv *oct_priv = octeon_dev->priv; atomic_set(&octeon_dev->status, OCT_DEV_BEGIN_STATE); /* Enable access to the octeon device and make its DMA capability diff --git a/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c b/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c index e2921aec3da082513ae76f1863f83a0a13530a23..62c2eadc33e35a0f99630f6cd0e7c1a3ff39472c 100644 --- a/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c +++ b/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c @@ -72,8 +72,7 @@ static int liquidio_stop(struct net_device *netdev); static int lio_wait_for_oq_pkts(struct octeon_device *oct) { - struct octeon_device_priv *oct_priv = - (struct octeon_device_priv *)oct->priv; + struct octeon_device_priv *oct_priv = oct->priv; int retry = MAX_IO_PENDING_PKT_COUNT; int pkt_cnt = 0, pending_pkts; int i; @@ -442,8 +441,7 @@ static void octeon_pci_flr(struct octeon_device *oct) */ static void octeon_destroy_resources(struct octeon_device *oct) { - struct octeon_device_priv *oct_priv = - (struct octeon_device_priv *)oct->priv; + struct octeon_device_priv *oct_priv = oct->priv; struct msix_entry *msix_entries; int i; @@ -659,8 +657,7 @@ static int send_rx_ctrl_cmd(struct lio *lio, int start_stop) static void liquidio_destroy_nic_device(struct octeon_device *oct, int ifidx) { struct net_device *netdev = oct->props[ifidx].netdev; - struct octeon_device_priv *oct_priv = - (struct octeon_device_priv *)oct->priv; + struct octeon_device_priv *oct_priv = oct->priv; struct napi_struct *napi, *n; struct lio *lio; @@ -909,8 +906,7 @@ static int liquidio_open(struct net_device *netdev) { struct lio *lio = GET_LIO(netdev); struct octeon_device *oct = lio->oct_dev; - struct octeon_device_priv *oct_priv = - (struct octeon_device_priv *)oct->priv; + struct octeon_device_priv *oct_priv = oct->priv; struct napi_struct *napi, *n; int ret = 0; @@ -956,8 +952,7 @@ static int liquidio_stop(struct net_device *netdev) { struct lio *lio = GET_LIO(netdev); struct octeon_device *oct = lio->oct_dev; - struct octeon_device_priv *oct_priv = - (struct octeon_device_priv *)oct->priv; + struct octeon_device_priv *oct_priv = oct->priv; struct napi_struct *napi, *n; int ret = 0; diff --git a/drivers/net/ethernet/cavium/liquidio/octeon_device.c b/drivers/net/ethernet/cavium/liquidio/octeon_device.c index e159194d0aef65c648ccba435c486d7f06bc10e3..364f4f912dc20a416c0786261a1ce1c9ae0048cd 100644 --- a/drivers/net/ethernet/cavium/liquidio/octeon_device.c +++ b/drivers/net/ethernet/cavium/liquidio/octeon_device.c @@ -564,6 +564,7 @@ void octeon_init_device_list(int conf_type) for (i = 0; i < MAX_OCTEON_DEVICES; i++) oct_set_config_info(i, conf_type); } +EXPORT_SYMBOL_GPL(octeon_init_device_list); static void *__retrieve_octeon_config_info(struct octeon_device *oct, u16 card_type) @@ -633,6 +634,7 @@ char *lio_get_state_string(atomic_t *state_ptr) return oct_dev_state_str[OCT_DEV_STATE_INVALID]; return oct_dev_state_str[istate]; } +EXPORT_SYMBOL_GPL(lio_get_state_string); static char *get_oct_app_string(u32 app_mode) { @@ -661,6 +663,7 @@ void octeon_free_device_mem(struct octeon_device *oct) octeon_device[i] = NULL; octeon_device_count--; } +EXPORT_SYMBOL_GPL(octeon_free_device_mem); static struct octeon_device *octeon_allocate_device_mem(u32 pci_id, u32 priv_size) @@ -747,6 +750,7 @@ struct octeon_device *octeon_allocate_device(u32 pci_id, return oct; } +EXPORT_SYMBOL_GPL(octeon_allocate_device); /** Register a device's bus location at initialization time. * @param octeon_dev - pointer to the octeon device structure. @@ -804,6 +808,7 @@ int octeon_register_device(struct octeon_device *oct, return refcount; } +EXPORT_SYMBOL_GPL(octeon_register_device); /** Deregister a device at de-initialization time. * @param octeon_dev - pointer to the octeon device structure. @@ -821,6 +826,7 @@ int octeon_deregister_device(struct octeon_device *oct) return refcount; } +EXPORT_SYMBOL_GPL(octeon_deregister_device); int octeon_allocate_ioq_vector(struct octeon_device *oct, u32 num_ioqs) @@ -853,12 +859,14 @@ octeon_allocate_ioq_vector(struct octeon_device *oct, u32 num_ioqs) return 0; } +EXPORT_SYMBOL_GPL(octeon_allocate_ioq_vector); void octeon_free_ioq_vector(struct octeon_device *oct) { vfree(oct->ioq_vector); } +EXPORT_SYMBOL_GPL(octeon_free_ioq_vector); /* this function is only for setting up the first queue */ int octeon_setup_instr_queues(struct octeon_device *oct) @@ -904,6 +912,7 @@ int octeon_setup_instr_queues(struct octeon_device *oct) oct->num_iqs++; return 0; } +EXPORT_SYMBOL_GPL(octeon_setup_instr_queues); int octeon_setup_output_queues(struct octeon_device *oct) { @@ -940,6 +949,7 @@ int octeon_setup_output_queues(struct octeon_device *oct) return 0; } +EXPORT_SYMBOL_GPL(octeon_setup_output_queues); int octeon_set_io_queues_off(struct octeon_device *oct) { @@ -989,6 +999,7 @@ int octeon_set_io_queues_off(struct octeon_device *oct) } return 0; } +EXPORT_SYMBOL_GPL(octeon_set_io_queues_off); void octeon_set_droq_pkt_op(struct octeon_device *oct, u32 q_no, @@ -1027,6 +1038,7 @@ int octeon_init_dispatch_list(struct octeon_device *oct) return 0; } +EXPORT_SYMBOL_GPL(octeon_init_dispatch_list); void octeon_delete_dispatch_list(struct octeon_device *oct) { @@ -1058,6 +1070,7 @@ void octeon_delete_dispatch_list(struct octeon_device *oct) kfree(temp); } } +EXPORT_SYMBOL_GPL(octeon_delete_dispatch_list); octeon_dispatch_fn_t octeon_get_dispatch(struct octeon_device *octeon_dev, u16 opcode, @@ -1180,6 +1193,7 @@ octeon_register_dispatch_fn(struct octeon_device *oct, return 0; } +EXPORT_SYMBOL_GPL(octeon_register_dispatch_fn); int octeon_core_drv_init(struct octeon_recv_info *recv_info, void *buf) { @@ -1262,6 +1276,7 @@ int octeon_core_drv_init(struct octeon_recv_info *recv_info, void *buf) octeon_free_recv_info(recv_info); return 0; } +EXPORT_SYMBOL_GPL(octeon_core_drv_init); int octeon_get_tx_qsize(struct octeon_device *oct, u32 q_no) @@ -1272,6 +1287,7 @@ int octeon_get_tx_qsize(struct octeon_device *oct, u32 q_no) return -1; } +EXPORT_SYMBOL_GPL(octeon_get_tx_qsize); int octeon_get_rx_qsize(struct octeon_device *oct, u32 q_no) { @@ -1280,6 +1296,7 @@ int octeon_get_rx_qsize(struct octeon_device *oct, u32 q_no) return oct->droq[q_no]->max_count; return -1; } +EXPORT_SYMBOL_GPL(octeon_get_rx_qsize); /* Retruns the host firmware handshake OCTEON specific configuration */ struct octeon_config *octeon_get_conf(struct octeon_device *oct) @@ -1302,6 +1319,7 @@ struct octeon_config *octeon_get_conf(struct octeon_device *oct) } return default_oct_conf; } +EXPORT_SYMBOL_GPL(octeon_get_conf); /* scratch register address is same in all the OCT-II and CN70XX models */ #define CNXX_SLI_SCRATCH1 0x3C0 @@ -1318,6 +1336,7 @@ struct octeon_device *lio_get_device(u32 octeon_id) else return octeon_device[octeon_id]; } +EXPORT_SYMBOL_GPL(lio_get_device); u64 lio_pci_readq(struct octeon_device *oct, u64 addr) { @@ -1349,6 +1368,7 @@ u64 lio_pci_readq(struct octeon_device *oct, u64 addr) return val64; } +EXPORT_SYMBOL_GPL(lio_pci_readq); void lio_pci_writeq(struct octeon_device *oct, u64 val, @@ -1369,6 +1389,7 @@ void lio_pci_writeq(struct octeon_device *oct, spin_unlock_irqrestore(&oct->pci_win_lock, flags); } +EXPORT_SYMBOL_GPL(lio_pci_writeq); int octeon_mem_access_ok(struct octeon_device *oct) { @@ -1388,6 +1409,7 @@ int octeon_mem_access_ok(struct octeon_device *oct) return access_okay ? 0 : 1; } +EXPORT_SYMBOL_GPL(octeon_mem_access_ok); int octeon_wait_for_ddr_init(struct octeon_device *oct, u32 *timeout) { @@ -1408,6 +1430,7 @@ int octeon_wait_for_ddr_init(struct octeon_device *oct, u32 *timeout) return ret; } +EXPORT_SYMBOL_GPL(octeon_wait_for_ddr_init); /* Get the octeon id assigned to the octeon device passed as argument. * This function is exported to other modules. @@ -1462,3 +1485,4 @@ void lio_enable_irq(struct octeon_droq *droq, struct octeon_instr_queue *iq) } } } +EXPORT_SYMBOL_GPL(lio_enable_irq); diff --git a/drivers/net/ethernet/cavium/liquidio/octeon_droq.c b/drivers/net/ethernet/cavium/liquidio/octeon_droq.c index d4080bddcb6ba7770ab1b076ac2d4fe097710b16..0d6ee30affb9137327208b53f4579c6e0e384820 100644 --- a/drivers/net/ethernet/cavium/liquidio/octeon_droq.c +++ b/drivers/net/ethernet/cavium/liquidio/octeon_droq.c @@ -107,6 +107,7 @@ u32 octeon_droq_check_hw_for_pkts(struct octeon_droq *droq) return last_count; } +EXPORT_SYMBOL_GPL(octeon_droq_check_hw_for_pkts); static void octeon_droq_compute_max_packet_bufs(struct octeon_droq *droq) { @@ -216,6 +217,7 @@ int octeon_delete_droq(struct octeon_device *oct, u32 q_no) return 0; } +EXPORT_SYMBOL_GPL(octeon_delete_droq); int octeon_init_droq(struct octeon_device *oct, u32 q_no, @@ -773,6 +775,7 @@ octeon_droq_process_packets(struct octeon_device *oct, return 0; } +EXPORT_SYMBOL_GPL(octeon_droq_process_packets); /* * Utility function to poll for packets. check_hw_for_packets must be @@ -921,6 +924,7 @@ int octeon_unregister_droq_ops(struct octeon_device *oct, u32 q_no) return 0; } +EXPORT_SYMBOL_GPL(octeon_unregister_droq_ops); int octeon_create_droq(struct octeon_device *oct, u32 q_no, u32 num_descs, diff --git a/drivers/net/ethernet/cavium/liquidio/octeon_mem_ops.c b/drivers/net/ethernet/cavium/liquidio/octeon_mem_ops.c index 7ccab36143c1710bb8213db48c78d00e73a20059..d70132437af3405ace8b58f5f6b54da096468cfa 100644 --- a/drivers/net/ethernet/cavium/liquidio/octeon_mem_ops.c +++ b/drivers/net/ethernet/cavium/liquidio/octeon_mem_ops.c @@ -164,6 +164,7 @@ octeon_pci_read_core_mem(struct octeon_device *oct, { __octeon_pci_rw_core_mem(oct, coreaddr, buf, len, 1); } +EXPORT_SYMBOL_GPL(octeon_pci_read_core_mem); void octeon_pci_write_core_mem(struct octeon_device *oct, @@ -173,6 +174,7 @@ octeon_pci_write_core_mem(struct octeon_device *oct, { __octeon_pci_rw_core_mem(oct, coreaddr, (u8 *)buf, len, 0); } +EXPORT_SYMBOL_GPL(octeon_pci_write_core_mem); u64 octeon_read_device_mem64(struct octeon_device *oct, u64 coreaddr) { @@ -182,6 +184,7 @@ u64 octeon_read_device_mem64(struct octeon_device *oct, u64 coreaddr) return be64_to_cpu(ret); } +EXPORT_SYMBOL_GPL(octeon_read_device_mem64); u32 octeon_read_device_mem32(struct octeon_device *oct, u64 coreaddr) { @@ -191,6 +194,7 @@ u32 octeon_read_device_mem32(struct octeon_device *oct, u64 coreaddr) return be32_to_cpu(ret); } +EXPORT_SYMBOL_GPL(octeon_read_device_mem32); void octeon_write_device_mem32(struct octeon_device *oct, u64 coreaddr, u32 val) @@ -199,3 +203,4 @@ void octeon_write_device_mem32(struct octeon_device *oct, u64 coreaddr, __octeon_pci_rw_core_mem(oct, coreaddr, (u8 *)&t, 4, 0); } +EXPORT_SYMBOL_GPL(octeon_write_device_mem32); diff --git a/drivers/net/ethernet/cavium/liquidio/octeon_nic.c b/drivers/net/ethernet/cavium/liquidio/octeon_nic.c index 1a706f81bbb0d9e21e3e5f6d6e53e8ee25c31690..dee56ea740e7c9207678b8a37460d68ddc45a701 100644 --- a/drivers/net/ethernet/cavium/liquidio/octeon_nic.c +++ b/drivers/net/ethernet/cavium/liquidio/octeon_nic.c @@ -79,6 +79,7 @@ octeon_alloc_soft_command_resp(struct octeon_device *oct, return sc; } +EXPORT_SYMBOL_GPL(octeon_alloc_soft_command_resp); int octnet_send_nic_data_pkt(struct octeon_device *oct, struct octnic_data_pkt *ndata, @@ -90,6 +91,7 @@ int octnet_send_nic_data_pkt(struct octeon_device *oct, ndata->buf, ndata->datasize, ndata->reqtype); } +EXPORT_SYMBOL_GPL(octnet_send_nic_data_pkt); static inline struct octeon_soft_command *octnic_alloc_ctrl_pkt_sc(struct octeon_device *oct, @@ -196,3 +198,4 @@ octnet_send_nic_ctrl_pkt(struct octeon_device *oct, return retval; } +EXPORT_SYMBOL_GPL(octnet_send_nic_ctrl_pkt); diff --git a/drivers/net/ethernet/cavium/liquidio/request_manager.c b/drivers/net/ethernet/cavium/liquidio/request_manager.c index 32f854c0cd79bb440a5807eaf358ffbd880895f0..de8a6ce86ad7e2ba399d62064d5d9549b85afa76 100644 --- a/drivers/net/ethernet/cavium/liquidio/request_manager.c +++ b/drivers/net/ethernet/cavium/liquidio/request_manager.c @@ -185,6 +185,7 @@ int octeon_delete_instr_queue(struct octeon_device *oct, u32 iq_no) } return 1; } +EXPORT_SYMBOL_GPL(octeon_delete_instr_queue); /* Return 0 on success, 1 on failure */ int octeon_setup_iq(struct octeon_device *oct, @@ -258,6 +259,7 @@ int lio_wait_for_instr_fetch(struct octeon_device *oct) return instr_cnt; } +EXPORT_SYMBOL_GPL(lio_wait_for_instr_fetch); static inline void ring_doorbell(struct octeon_device *oct, struct octeon_instr_queue *iq) @@ -282,6 +284,7 @@ octeon_ring_doorbell_locked(struct octeon_device *oct, u32 iq_no) ring_doorbell(oct, iq); spin_unlock(&iq->post_lock); } +EXPORT_SYMBOL_GPL(octeon_ring_doorbell_locked); static inline void __copy_cmd_into_iq(struct octeon_instr_queue *iq, u8 *cmd) @@ -345,6 +348,7 @@ octeon_register_reqtype_free_fn(struct octeon_device *oct, int reqtype, return 0; } +EXPORT_SYMBOL_GPL(octeon_register_reqtype_free_fn); static inline void __add_to_request_list(struct octeon_instr_queue *iq, @@ -430,6 +434,7 @@ lio_process_iq_request_list(struct octeon_device *oct, return inst_count; } +EXPORT_SYMBOL_GPL(lio_process_iq_request_list); /* Can only be called from process context */ int @@ -566,6 +571,7 @@ octeon_send_command(struct octeon_device *oct, u32 iq_no, return st.status; } +EXPORT_SYMBOL_GPL(octeon_send_command); void octeon_prepare_soft_command(struct octeon_device *oct, @@ -673,6 +679,7 @@ octeon_prepare_soft_command(struct octeon_device *oct, } } } +EXPORT_SYMBOL_GPL(octeon_prepare_soft_command); int octeon_send_soft_command(struct octeon_device *oct, struct octeon_soft_command *sc) @@ -726,6 +733,7 @@ int octeon_send_soft_command(struct octeon_device *oct, return (octeon_send_command(oct, sc->iq_no, 1, &sc->cmd, sc, len, REQTYPE_SOFT_COMMAND)); } +EXPORT_SYMBOL_GPL(octeon_send_soft_command); int octeon_setup_sc_buffer_pool(struct octeon_device *oct) { @@ -755,6 +763,7 @@ int octeon_setup_sc_buffer_pool(struct octeon_device *oct) return 0; } +EXPORT_SYMBOL_GPL(octeon_setup_sc_buffer_pool); int octeon_free_sc_done_list(struct octeon_device *oct) { @@ -794,6 +803,7 @@ int octeon_free_sc_done_list(struct octeon_device *oct) return 0; } +EXPORT_SYMBOL_GPL(octeon_free_sc_done_list); int octeon_free_sc_zombie_list(struct octeon_device *oct) { @@ -818,6 +828,7 @@ int octeon_free_sc_zombie_list(struct octeon_device *oct) return 0; } +EXPORT_SYMBOL_GPL(octeon_free_sc_zombie_list); int octeon_free_sc_buffer_pool(struct octeon_device *oct) { @@ -842,6 +853,7 @@ int octeon_free_sc_buffer_pool(struct octeon_device *oct) return 0; } +EXPORT_SYMBOL_GPL(octeon_free_sc_buffer_pool); struct octeon_soft_command *octeon_alloc_soft_command(struct octeon_device *oct, u32 datasize, @@ -913,6 +925,7 @@ struct octeon_soft_command *octeon_alloc_soft_command(struct octeon_device *oct, return sc; } +EXPORT_SYMBOL_GPL(octeon_alloc_soft_command); void octeon_free_soft_command(struct octeon_device *oct, struct octeon_soft_command *sc) @@ -925,3 +938,4 @@ void octeon_free_soft_command(struct octeon_device *oct, spin_unlock_bh(&oct->sc_buf_pool.lock); } +EXPORT_SYMBOL_GPL(octeon_free_soft_command); diff --git a/drivers/net/ethernet/cavium/liquidio/response_manager.c b/drivers/net/ethernet/cavium/liquidio/response_manager.c index ac7747ccf56a03a338c5a87ab4e92de770a3e6e2..861050966e180749feab9342a018377be269606d 100644 --- a/drivers/net/ethernet/cavium/liquidio/response_manager.c +++ b/drivers/net/ethernet/cavium/liquidio/response_manager.c @@ -52,12 +52,14 @@ int octeon_setup_response_list(struct octeon_device *oct) return ret; } +EXPORT_SYMBOL_GPL(octeon_setup_response_list); void octeon_delete_response_list(struct octeon_device *oct) { cancel_delayed_work_sync(&oct->dma_comp_wq.wk.work); destroy_workqueue(oct->dma_comp_wq.wq); } +EXPORT_SYMBOL_GPL(octeon_delete_response_list); int lio_process_ordered_list(struct octeon_device *octeon_dev, u32 force_quit) @@ -219,6 +221,7 @@ int lio_process_ordered_list(struct octeon_device *octeon_dev, return 0; } +EXPORT_SYMBOL_GPL(lio_process_ordered_list); static void oct_poll_req_completion(struct work_struct *work) { diff --git a/drivers/net/ethernet/cavium/thunder/thunder_bgx.c b/drivers/net/ethernet/cavium/thunder/thunder_bgx.c index 7eb2ddbe9bad6b3f5586704be0a0ff8474346c20..a317feb8decb64c9263f64245b8dfeeb4efea40f 100644 --- a/drivers/net/ethernet/cavium/thunder/thunder_bgx.c +++ b/drivers/net/ethernet/cavium/thunder/thunder_bgx.c @@ -1126,8 +1126,7 @@ static int bgx_lmac_enable(struct bgx *bgx, u8 lmacid) } poll: - lmac->check_link = alloc_workqueue("check_link", WQ_UNBOUND | - WQ_MEM_RECLAIM, 1); + lmac->check_link = alloc_ordered_workqueue("check_link", WQ_MEM_RECLAIM); if (!lmac->check_link) return -ENOMEM; INIT_DELAYED_WORK(&lmac->dwork, bgx_poll_for_link); diff --git a/drivers/net/ethernet/chelsio/cxgb3/sge.c b/drivers/net/ethernet/chelsio/cxgb3/sge.c index efa7f401529ec255be65813bd306c67d5a0eb65e..2e9a74fe0970df333226b80af8716f30865c01b7 100644 --- a/drivers/net/ethernet/chelsio/cxgb3/sge.c +++ b/drivers/net/ethernet/chelsio/cxgb3/sge.c @@ -2184,9 +2184,8 @@ static void lro_add_page(struct adapter *adap, struct sge_qset *qs, len -= offset; rx_frag += nr_frags; - __skb_frag_set_page(rx_frag, sd->pg_chunk.page); - skb_frag_off_set(rx_frag, sd->pg_chunk.offset + offset); - skb_frag_size_set(rx_frag, len); + skb_frag_fill_page_desc(rx_frag, sd->pg_chunk.page, + sd->pg_chunk.offset + offset, len); skb->len += len; skb->data_len += len; diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c index f0bc7396ce2b12c86951e83d92e581147deb84ff..2eb33a727bba3b6e6db281c4db508f5b46df4a9c 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c @@ -1175,7 +1175,7 @@ static u16 cxgb_select_queue(struct net_device *dev, struct sk_buff *skb, txq = netdev_pick_tx(dev, skb, sb_dev); if (xfrm_offload(skb) || is_ptp_enabled(skb, dev) || skb->encapsulation || - cxgb4_is_ktls_skb(skb) || + tls_is_skb_tx_device_offloaded(skb) || (proto != IPPROTO_TCP && proto != IPPROTO_UDP)) txq = txq % pi->nqsets; diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h index 34546f5312eee59f1453262aab41624d12f27992..a9599ba26975764b7848a7bb12601bb44559f764 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h @@ -497,11 +497,6 @@ struct cxgb4_uld_info { #endif }; -static inline bool cxgb4_is_ktls_skb(struct sk_buff *skb) -{ - return skb->sk && tls_is_sk_tx_device_offloaded(skb->sk); -} - void cxgb4_uld_enable(struct adapter *adap); void cxgb4_register_uld(enum cxgb4_uld type, const struct cxgb4_uld_info *p); int cxgb4_unregister_uld(enum cxgb4_uld type); diff --git a/drivers/net/ethernet/chelsio/cxgb4/sge.c b/drivers/net/ethernet/chelsio/cxgb4/sge.c index 46809e2d94ee08bf619398791daf034beb4f8405..98dd78551d89a656544f2d6be753ef0ceb159232 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/sge.c +++ b/drivers/net/ethernet/chelsio/cxgb4/sge.c @@ -1530,7 +1530,7 @@ static netdev_tx_t cxgb4_eth_xmit(struct sk_buff *skb, struct net_device *dev) #endif /* CHELSIO_IPSEC_INLINE */ #if IS_ENABLED(CONFIG_CHELSIO_TLS_DEVICE) - if (cxgb4_is_ktls_skb(skb) && + if (tls_is_skb_tx_device_offloaded(skb) && (skb->len - skb_tcp_all_headers(skb))) return adap->uld[CXGB4_ULD_KTLS].tx_handler(skb, dev); #endif /* CHELSIO_TLS_DEVICE */ diff --git a/drivers/net/ethernet/chelsio/inline_crypto/ch_ktls/chcr_ktls.c b/drivers/net/ethernet/chelsio/inline_crypto/ch_ktls/chcr_ktls.c index 1a5fdd755e9e30124d80cbb385d8efad1d41530a..bcdc7fc2f4276ace76c6fd3a35a93fd918fed792 100644 --- a/drivers/net/ethernet/chelsio/inline_crypto/ch_ktls/chcr_ktls.c +++ b/drivers/net/ethernet/chelsio/inline_crypto/ch_ktls/chcr_ktls.c @@ -1946,7 +1946,7 @@ static int chcr_ktls_xmit(struct sk_buff *skb, struct net_device *dev) tls_ctx = tls_get_ctx(skb->sk); tls_netdev = rcu_dereference_bh(tls_ctx->netdev); /* Don't quit on NULL: if tls_device_down is running in parallel, - * netdev might become NULL, even if tls_is_sk_tx_device_offloaded was + * netdev might become NULL, even if tls_is_skb_tx_device_offloaded was * true. Rather continue processing this packet. */ if (unlikely(tls_netdev && tls_netdev != dev)) diff --git a/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls.h b/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls.h index 41714203ace8986790d08d4334045351007ab99f..68562a82d03681131d983d89b0f0ef549235442b 100644 --- a/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls.h +++ b/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls.h @@ -568,8 +568,7 @@ void chtls_destroy_sock(struct sock *sk); int chtls_sendmsg(struct sock *sk, struct msghdr *msg, size_t size); int chtls_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int flags, int *addr_len); -int chtls_sendpage(struct sock *sk, struct page *page, - int offset, size_t size, int flags); +void chtls_splice_eof(struct socket *sock); int send_tx_flowc_wr(struct sock *sk, int compl, u32 snd_nxt, u32 rcv_nxt); void chtls_tcp_push(struct sock *sk, int flags); diff --git a/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_io.c b/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_io.c index ae6b17b96bf12256ecbb15f7109a224009edad5a..5fc64e47568a9c55acaabb62eeb30cfa7524f876 100644 --- a/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_io.c +++ b/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_io.c @@ -1092,7 +1092,17 @@ int chtls_sendmsg(struct sock *sk, struct msghdr *msg, size_t size) if (copy > size) copy = size; - if (skb_tailroom(skb) > 0) { + if (msg->msg_flags & MSG_SPLICE_PAGES) { + err = skb_splice_from_iter(skb, &msg->msg_iter, copy, + sk->sk_allocation); + if (err < 0) { + if (err == -EMSGSIZE) + goto new_buf; + goto do_fault; + } + copy = err; + sk_wmem_queued_add(sk, copy); + } else if (skb_tailroom(skb) > 0) { copy = min(copy, skb_tailroom(skb)); if (is_tls_tx(csk)) copy = min_t(int, copy, csk->tlshws.txleft); @@ -1227,113 +1237,13 @@ int chtls_sendmsg(struct sock *sk, struct msghdr *msg, size_t size) goto done; } -int chtls_sendpage(struct sock *sk, struct page *page, - int offset, size_t size, int flags) +void chtls_splice_eof(struct socket *sock) { - struct chtls_sock *csk; - struct chtls_dev *cdev; - int mss, err, copied; - struct tcp_sock *tp; - long timeo; + struct sock *sk = sock->sk; - tp = tcp_sk(sk); - copied = 0; - csk = rcu_dereference_sk_user_data(sk); - cdev = csk->cdev; lock_sock(sk); - timeo = sock_sndtimeo(sk, flags & MSG_DONTWAIT); - - err = sk_stream_wait_connect(sk, &timeo); - if (!sk_in_state(sk, TCPF_ESTABLISHED | TCPF_CLOSE_WAIT) && - err != 0) - goto out_err; - - mss = csk->mss; - csk_set_flag(csk, CSK_TX_MORE_DATA); - - while (size > 0) { - struct sk_buff *skb = skb_peek_tail(&csk->txq); - int copy, i; - - if (!skb || (ULP_SKB_CB(skb)->flags & ULPCB_FLAG_NO_APPEND) || - (copy = mss - skb->len) <= 0) { -new_buf: - if (!csk_mem_free(cdev, sk)) - goto wait_for_sndbuf; - - if (is_tls_tx(csk)) { - skb = get_record_skb(sk, - select_size(sk, size, - flags, - TX_TLSHDR_LEN), - true); - } else { - skb = get_tx_skb(sk, 0); - } - if (!skb) - goto wait_for_memory; - copy = mss; - } - if (copy > size) - copy = size; - - i = skb_shinfo(skb)->nr_frags; - if (skb_can_coalesce(skb, i, page, offset)) { - skb_frag_size_add(&skb_shinfo(skb)->frags[i - 1], copy); - } else if (i < MAX_SKB_FRAGS) { - get_page(page); - skb_fill_page_desc(skb, i, page, offset, copy); - } else { - tx_skb_finalize(skb); - push_frames_if_head(sk); - goto new_buf; - } - - skb->len += copy; - if (skb->len == mss) - tx_skb_finalize(skb); - skb->data_len += copy; - skb->truesize += copy; - sk->sk_wmem_queued += copy; - tp->write_seq += copy; - copied += copy; - offset += copy; - size -= copy; - - if (corked(tp, flags) && - (sk_stream_wspace(sk) < sk_stream_min_wspace(sk))) - ULP_SKB_CB(skb)->flags |= ULPCB_FLAG_NO_APPEND; - - if (!size) - break; - - if (unlikely(ULP_SKB_CB(skb)->flags & ULPCB_FLAG_NO_APPEND)) - push_frames_if_head(sk); - continue; -wait_for_sndbuf: - set_bit(SOCK_NOSPACE, &sk->sk_socket->flags); -wait_for_memory: - err = csk_wait_memory(cdev, sk, &timeo); - if (err) - goto do_error; - } -out: - csk_reset_flag(csk, CSK_TX_MORE_DATA); - if (copied) - chtls_tcp_push(sk, flags); -done: + chtls_tcp_push(sk, 0); release_sock(sk); - return copied; - -do_error: - if (copied) - goto out; - -out_err: - if (csk_conn_inline(csk)) - csk_reset_flag(csk, CSK_TX_MORE_DATA); - copied = sk_stream_error(sk, flags, err); - goto done; } static void chtls_select_window(struct sock *sk) diff --git a/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_main.c b/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_main.c index 1e55b12fee5168fefb091c39085d5d954d5eefb8..455a54708be4405ae6be05b8f3e70fd88f57c729 100644 --- a/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_main.c +++ b/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_main.c @@ -606,7 +606,7 @@ static void __init chtls_init_ulp_ops(void) chtls_cpl_prot.destroy = chtls_destroy_sock; chtls_cpl_prot.shutdown = chtls_shutdown; chtls_cpl_prot.sendmsg = chtls_sendmsg; - chtls_cpl_prot.sendpage = chtls_sendpage; + chtls_cpl_prot.splice_eof = chtls_splice_eof; chtls_cpl_prot.recvmsg = chtls_recvmsg; chtls_cpl_prot.setsockopt = chtls_setsockopt; chtls_cpl_prot.getsockopt = chtls_getsockopt; diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index 7e408bcc88deda638a53102401773d49af8a63d5..18c2fc880d093dcbe2718ee079774e3ef5f4269f 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c @@ -1135,8 +1135,8 @@ static struct sk_buff *be_lancer_xmit_workarounds(struct be_adapter *adapter, eth_hdr_len = ntohs(skb->protocol) == ETH_P_8021Q ? VLAN_ETH_HLEN : ETH_HLEN; if (skb->len <= 60 && - (lancer_chip(adapter) || skb_vlan_tag_present(skb)) && - is_ipv4_pkt(skb)) { + (lancer_chip(adapter) || BE3_chip(adapter) || + skb_vlan_tag_present(skb)) && is_ipv4_pkt(skb)) { ip = (struct iphdr *)ip_hdr(skb); pskb_trim(skb, eth_hdr_len + ntohs(ip->tot_len)); } @@ -2343,11 +2343,10 @@ static void skb_fill_rx_data(struct be_rx_obj *rxo, struct sk_buff *skb, hdr_len = ETH_HLEN; memcpy(skb->data, start, hdr_len); skb_shinfo(skb)->nr_frags = 1; - skb_frag_set_page(skb, 0, page_info->page); - skb_frag_off_set(&skb_shinfo(skb)->frags[0], - page_info->page_offset + hdr_len); - skb_frag_size_set(&skb_shinfo(skb)->frags[0], - curr_frag_len - hdr_len); + skb_frag_fill_page_desc(&skb_shinfo(skb)->frags[0], + page_info->page, + page_info->page_offset + hdr_len, + curr_frag_len - hdr_len); skb->data_len = curr_frag_len - hdr_len; skb->truesize += rx_frag_size; skb->tail += hdr_len; @@ -2369,16 +2368,17 @@ static void skb_fill_rx_data(struct be_rx_obj *rxo, struct sk_buff *skb, if (page_info->page_offset == 0) { /* Fresh page */ j++; - skb_frag_set_page(skb, j, page_info->page); - skb_frag_off_set(&skb_shinfo(skb)->frags[j], - page_info->page_offset); - skb_frag_size_set(&skb_shinfo(skb)->frags[j], 0); + skb_frag_fill_page_desc(&skb_shinfo(skb)->frags[j], + page_info->page, + page_info->page_offset, + curr_frag_len); skb_shinfo(skb)->nr_frags++; } else { put_page(page_info->page); + skb_frag_size_add(&skb_shinfo(skb)->frags[j], + curr_frag_len); } - skb_frag_size_add(&skb_shinfo(skb)->frags[j], curr_frag_len); skb->len += curr_frag_len; skb->data_len += curr_frag_len; skb->truesize += rx_frag_size; @@ -2451,14 +2451,16 @@ static void be_rx_compl_process_gro(struct be_rx_obj *rxo, if (i == 0 || page_info->page_offset == 0) { /* First frag or Fresh page */ j++; - skb_frag_set_page(skb, j, page_info->page); - skb_frag_off_set(&skb_shinfo(skb)->frags[j], - page_info->page_offset); - skb_frag_size_set(&skb_shinfo(skb)->frags[j], 0); + skb_frag_fill_page_desc(&skb_shinfo(skb)->frags[j], + page_info->page, + page_info->page_offset, + curr_frag_len); } else { put_page(page_info->page); + skb_frag_size_add(&skb_shinfo(skb)->frags[j], + curr_frag_len); } - skb_frag_size_add(&skb_shinfo(skb)->frags[j], curr_frag_len); + skb->truesize += rx_frag_size; remaining -= curr_frag_len; memset(page_info, 0, sizeof(*page_info)); diff --git a/drivers/net/ethernet/engleder/tsnep_selftests.c b/drivers/net/ethernet/engleder/tsnep_selftests.c index 1581d6b2223207d69dcd946b7033d46cafc4be33..8a9145f93147c635559c64a05db05a1e73a84edf 100644 --- a/drivers/net/ethernet/engleder/tsnep_selftests.c +++ b/drivers/net/ethernet/engleder/tsnep_selftests.c @@ -329,7 +329,7 @@ static bool disable_taprio(struct tsnep_adapter *adapter) int retval; memset(&qopt, 0, sizeof(qopt)); - qopt.enable = 0; + qopt.cmd = TAPRIO_CMD_DESTROY; retval = tsnep_tc_setup(adapter->netdev, TC_SETUP_QDISC_TAPRIO, &qopt); if (retval) return false; @@ -360,7 +360,7 @@ static bool tsnep_test_taprio(struct tsnep_adapter *adapter) for (i = 0; i < 255; i++) qopt->entries[i].command = TC_TAPRIO_CMD_SET_GATES; - qopt->enable = 1; + qopt->cmd = TAPRIO_CMD_REPLACE; qopt->base_time = ktime_set(0, 0); qopt->cycle_time = 1500000; qopt->cycle_time_extension = 0; @@ -382,7 +382,7 @@ static bool tsnep_test_taprio(struct tsnep_adapter *adapter) if (!run_taprio(adapter, qopt, 100)) goto failed; - qopt->enable = 1; + qopt->cmd = TAPRIO_CMD_REPLACE; qopt->base_time = ktime_set(0, 0); qopt->cycle_time = 411854; qopt->cycle_time_extension = 0; @@ -406,7 +406,7 @@ static bool tsnep_test_taprio(struct tsnep_adapter *adapter) if (!run_taprio(adapter, qopt, 100)) goto failed; - qopt->enable = 1; + qopt->cmd = TAPRIO_CMD_REPLACE; qopt->base_time = ktime_set(0, 0); delay_base_time(adapter, qopt, 12); qopt->cycle_time = 125000; @@ -457,7 +457,7 @@ static bool tsnep_test_taprio_change(struct tsnep_adapter *adapter) for (i = 0; i < 255; i++) qopt->entries[i].command = TC_TAPRIO_CMD_SET_GATES; - qopt->enable = 1; + qopt->cmd = TAPRIO_CMD_REPLACE; qopt->base_time = ktime_set(0, 0); qopt->cycle_time = 100000; qopt->cycle_time_extension = 0; @@ -610,7 +610,7 @@ static bool tsnep_test_taprio_extension(struct tsnep_adapter *adapter) for (i = 0; i < 255; i++) qopt->entries[i].command = TC_TAPRIO_CMD_SET_GATES; - qopt->enable = 1; + qopt->cmd = TAPRIO_CMD_REPLACE; qopt->base_time = ktime_set(0, 0); qopt->cycle_time = 100000; qopt->cycle_time_extension = 50000; diff --git a/drivers/net/ethernet/engleder/tsnep_tc.c b/drivers/net/ethernet/engleder/tsnep_tc.c index d083e6684f12084ba4499ab3f7b2ef82684901a5..745b191a55402272640777516d2c3d60a1ee53cc 100644 --- a/drivers/net/ethernet/engleder/tsnep_tc.c +++ b/drivers/net/ethernet/engleder/tsnep_tc.c @@ -325,7 +325,7 @@ static int tsnep_taprio(struct tsnep_adapter *adapter, if (!adapter->gate_control) return -EOPNOTSUPP; - if (!qopt->enable) { + if (qopt->cmd == TAPRIO_CMD_DESTROY) { /* disable gate control if active */ mutex_lock(&adapter->gate_control_lock); @@ -337,6 +337,8 @@ static int tsnep_taprio(struct tsnep_adapter *adapter, mutex_unlock(&adapter->gate_control_lock); return 0; + } else if (qopt->cmd != TAPRIO_CMD_REPLACE) { + return -EOPNOTSUPP; } retval = tsnep_validate_gcl(qopt); diff --git a/drivers/net/ethernet/freescale/Kconfig b/drivers/net/ethernet/freescale/Kconfig index 1c78f66a89da954f06cf38b33eaed6da180eab5f..75401d2a5fb493411517ebda3456064d60ce6663 100644 --- a/drivers/net/ethernet/freescale/Kconfig +++ b/drivers/net/ethernet/freescale/Kconfig @@ -29,7 +29,7 @@ config FEC select CRC32 select PHYLIB select PAGE_POOL - select PAGE_POOL_STATS + imply PAGE_POOL_STATS imply NET_SELFTESTS help Say Y here if you want to use the built-in 10/100 Fast ethernet diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c index a62cffaf6ff115629f9d24db67b4ded092584273..a9676d0dece8edac2cae1d19e0d205a295efbaea 100644 --- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c +++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c @@ -5025,7 +5025,7 @@ static int dpaa2_eth_probe(struct fsl_mc_device *dpni_dev) return err; } -static int dpaa2_eth_remove(struct fsl_mc_device *ls_dev) +static void dpaa2_eth_remove(struct fsl_mc_device *ls_dev) { struct device *dev; struct net_device *net_dev; @@ -5073,8 +5073,6 @@ static int dpaa2_eth_remove(struct fsl_mc_device *ls_dev) dev_dbg(net_dev->dev.parent, "Removed interface %s\n", net_dev->name); free_netdev(net_dev); - - return 0; } static const struct fsl_mc_device_id dpaa2_eth_match_id_table[] = { diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c index b1871e6c4006946995718dc4290281b01a11d45c..a69bb22c37eaba5248ab5789a32f1db9e2b41351 100644 --- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c +++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c @@ -54,6 +54,9 @@ static int phy_mode(enum dpmac_eth_if eth_if, phy_interface_t *if_mode) case DPMAC_ETH_IF_XFI: *if_mode = PHY_INTERFACE_MODE_10GBASER; break; + case DPMAC_ETH_IF_CAUI: + *if_mode = PHY_INTERFACE_MODE_25GBASER; + break; default: return -EINVAL; } @@ -79,6 +82,8 @@ static enum dpmac_eth_if dpmac_eth_if_mode(phy_interface_t if_mode) return DPMAC_ETH_IF_XFI; case PHY_INTERFACE_MODE_1000BASEX: return DPMAC_ETH_IF_1000BASEX; + case PHY_INTERFACE_MODE_25GBASER: + return DPMAC_ETH_IF_CAUI; default: return DPMAC_ETH_IF_MII; } @@ -247,8 +252,8 @@ static int dpaa2_pcs_create(struct dpaa2_mac *mac, struct fwnode_handle *dpmac_node, int id) { - struct mdio_device *mdiodev; struct fwnode_handle *node; + struct phylink_pcs *pcs; node = fwnode_find_reference(dpmac_node, "pcs-handle", 0); if (IS_ERR(node)) { @@ -257,26 +262,27 @@ static int dpaa2_pcs_create(struct dpaa2_mac *mac, return 0; } - if (!fwnode_device_is_available(node)) { - netdev_err(mac->net_dev, "pcs-handle node not available\n"); - fwnode_handle_put(node); - return -ENODEV; - } - - mdiodev = fwnode_mdio_find_device(node); + pcs = lynx_pcs_create_fwnode(node); fwnode_handle_put(node); - if (!mdiodev) { + + if (pcs == ERR_PTR(-EPROBE_DEFER)) { netdev_dbg(mac->net_dev, "missing PCS device\n"); return -EPROBE_DEFER; } - mac->pcs = lynx_pcs_create(mdiodev); - if (!mac->pcs) { - netdev_err(mac->net_dev, "lynx_pcs_create() failed\n"); - put_device(&mdiodev->dev); - return -ENOMEM; + if (pcs == ERR_PTR(-ENODEV)) { + netdev_err(mac->net_dev, "pcs-handle node not available\n"); + return PTR_ERR(pcs); + } + + if (IS_ERR(pcs)) { + netdev_err(mac->net_dev, + "lynx_pcs_create_fwnode() failed: %pe\n", pcs); + return PTR_ERR(pcs); } + mac->pcs = pcs; + return 0; } @@ -285,11 +291,7 @@ static void dpaa2_pcs_destroy(struct dpaa2_mac *mac) struct phylink_pcs *phylink_pcs = mac->pcs; if (phylink_pcs) { - struct mdio_device *mdio = lynx_get_mdio_device(phylink_pcs); - struct device *dev = &mdio->dev; - lynx_pcs_destroy(phylink_pcs); - put_device(dev); mac->pcs = NULL; } } @@ -418,7 +420,7 @@ int dpaa2_mac_connect(struct dpaa2_mac *mac) mac->phylink_config.mac_capabilities = MAC_SYM_PAUSE | MAC_ASYM_PAUSE | MAC_10FD | MAC_100FD | MAC_1000FD | MAC_2500FD | MAC_5000FD | - MAC_10000FD; + MAC_10000FD | MAC_25000FD; dpaa2_mac_set_supported_interfaces(mac); diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-ptp.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-ptp.c index 90d23ab1ce9d9eb3268553d65267920c102da8b2..4497e3c0456d1828afd4e8a067cafefa40dab622 100644 --- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-ptp.c +++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-ptp.c @@ -219,7 +219,7 @@ static int dpaa2_ptp_probe(struct fsl_mc_device *mc_dev) return err; } -static int dpaa2_ptp_remove(struct fsl_mc_device *mc_dev) +static void dpaa2_ptp_remove(struct fsl_mc_device *mc_dev) { struct device *dev = &mc_dev->dev; struct ptp_qoriq *ptp_qoriq; @@ -232,8 +232,6 @@ static int dpaa2_ptp_remove(struct fsl_mc_device *mc_dev) fsl_mc_free_irqs(mc_dev); dprtc_close(mc_dev->mc_io, 0, mc_dev->mc_handle); fsl_mc_portal_free(mc_dev->mc_io); - - return 0; } static const struct fsl_mc_device_id dpaa2_ptp_match_id_table[] = { diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c index f4ae4289c41ae674c1fc84318ef71b316fd178b5..21cc4e52425a976b6741c2f00e219bf6cd965a58 100644 --- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c +++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c @@ -3221,7 +3221,7 @@ static void dpaa2_switch_teardown(struct fsl_mc_device *sw_dev) dev_warn(dev, "dpsw_close err %d\n", err); } -static int dpaa2_switch_remove(struct fsl_mc_device *sw_dev) +static void dpaa2_switch_remove(struct fsl_mc_device *sw_dev) { struct ethsw_port_priv *port_priv; struct ethsw_core *ethsw; @@ -3252,8 +3252,6 @@ static int dpaa2_switch_remove(struct fsl_mc_device *sw_dev) kfree(ethsw); dev_set_drvdata(dev, NULL); - - return 0; } static int dpaa2_switch_probe_port(struct ethsw_core *ethsw, diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c b/drivers/net/ethernet/freescale/enetc/enetc.c index 9e1b2536e9a916f5541fbe3f9fbfd51109767e2c..35461165de0d2aba0ac3a48988af55ac87586402 100644 --- a/drivers/net/ethernet/freescale/enetc/enetc.c +++ b/drivers/net/ethernet/freescale/enetc/enetc.c @@ -1451,9 +1451,8 @@ static void enetc_add_rx_buff_to_xdp(struct enetc_bdr *rx_ring, int i, xdp_buff_set_frag_pfmemalloc(xdp_buff); frag = &shinfo->frags[shinfo->nr_frags]; - skb_frag_off_set(frag, rx_swbd->page_offset); - skb_frag_size_set(frag, size); - __skb_frag_set_page(frag, rx_swbd->page); + skb_frag_fill_page_desc(frag, rx_swbd->page, rx_swbd->page_offset, + size); shinfo->nr_frags++; } @@ -1790,7 +1789,7 @@ static int enetc_alloc_tx_resource(struct enetc_bdr_resource *res, res->bd_count = bd_count; res->bd_size = sizeof(union enetc_tx_bd); - res->tx_swbd = vzalloc(bd_count * sizeof(*res->tx_swbd)); + res->tx_swbd = vcalloc(bd_count, sizeof(*res->tx_swbd)); if (!res->tx_swbd) return -ENOMEM; @@ -1878,7 +1877,7 @@ static int enetc_alloc_rx_resource(struct enetc_bdr_resource *res, if (extended) res->bd_size *= 2; - res->rx_swbd = vzalloc(bd_count * sizeof(struct enetc_rx_swbd)); + res->rx_swbd = vcalloc(bd_count, sizeof(struct enetc_rx_swbd)); if (!res->rx_swbd) return -ENOMEM; @@ -2639,7 +2638,7 @@ static void enetc_debug_tx_ring_prios(struct enetc_ndev_priv *priv) priv->tx_ring[i]->prio); } -static void enetc_reset_tc_mqprio(struct net_device *ndev) +void enetc_reset_tc_mqprio(struct net_device *ndev) { struct enetc_ndev_priv *priv = netdev_priv(ndev); struct enetc_hw *hw = &priv->si->hw; @@ -2664,6 +2663,7 @@ static void enetc_reset_tc_mqprio(struct net_device *ndev) enetc_change_preemptible_tcs(priv, 0); } +EXPORT_SYMBOL_GPL(enetc_reset_tc_mqprio); int enetc_setup_tc_mqprio(struct net_device *ndev, void *type_data) { diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h b/drivers/net/ethernet/freescale/enetc/enetc.h index c97a8e3d7a7fe4c9f41e182727671431edef8a50..8577cf7699a042d9b4937439bf0104e91b1fcd14 100644 --- a/drivers/net/ethernet/freescale/enetc/enetc.h +++ b/drivers/net/ethernet/freescale/enetc/enetc.h @@ -429,6 +429,7 @@ struct net_device_stats *enetc_get_stats(struct net_device *ndev); void enetc_set_features(struct net_device *ndev, netdev_features_t features); int enetc_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd); int enetc_setup_tc_mqprio(struct net_device *ndev, void *type_data); +void enetc_reset_tc_mqprio(struct net_device *ndev); int enetc_setup_bpf(struct net_device *ndev, struct netdev_bpf *bpf); int enetc_xdp_xmit(struct net_device *ndev, int num_frames, struct xdp_frame **frames, u32 flags); diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.c b/drivers/net/ethernet/freescale/enetc/enetc_pf.c index 7cd22d370caa3a1d33f7e02f33e8abdc0ceaafa6..1416262d42967aea34ad5e0213505f21c9f0227a 100644 --- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c +++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c @@ -863,7 +863,6 @@ static int enetc_imdio_create(struct enetc_pf *pf) struct device *dev = &pf->si->pdev->dev; struct enetc_mdio_priv *mdio_priv; struct phylink_pcs *phylink_pcs; - struct mdio_device *mdio_device; struct mii_bus *bus; int err; @@ -889,17 +888,9 @@ static int enetc_imdio_create(struct enetc_pf *pf) goto free_mdio_bus; } - mdio_device = mdio_device_create(bus, 0); - if (IS_ERR(mdio_device)) { - err = PTR_ERR(mdio_device); - dev_err(dev, "cannot create mdio device (%d)\n", err); - goto unregister_mdiobus; - } - - phylink_pcs = lynx_pcs_create(mdio_device); - if (!phylink_pcs) { - mdio_device_free(mdio_device); - err = -ENOMEM; + phylink_pcs = lynx_pcs_create_mdiodev(bus, 0); + if (IS_ERR(phylink_pcs)) { + err = PTR_ERR(phylink_pcs); dev_err(dev, "cannot create lynx pcs (%d)\n", err); goto unregister_mdiobus; } @@ -918,13 +909,8 @@ static int enetc_imdio_create(struct enetc_pf *pf) static void enetc_imdio_remove(struct enetc_pf *pf) { - struct mdio_device *mdio_device; - - if (pf->pcs) { - mdio_device = lynx_get_mdio_device(pf->pcs); - mdio_device_free(mdio_device); + if (pf->pcs) lynx_pcs_destroy(pf->pcs); - } if (pf->imdio) { mdiobus_unregister(pf->imdio); mdiobus_free(pf->imdio); diff --git a/drivers/net/ethernet/freescale/enetc/enetc_qos.c b/drivers/net/ethernet/freescale/enetc/enetc_qos.c index 126007ab70f619f3497e0d1ad76e2317fb78a71c..270cbd5e8684c3157281c2589fd4d58bda770713 100644 --- a/drivers/net/ethernet/freescale/enetc/enetc_qos.c +++ b/drivers/net/ethernet/freescale/enetc/enetc_qos.c @@ -43,10 +43,9 @@ void enetc_sched_speed_set(struct enetc_ndev_priv *priv, int speed) enetc_port_wr(hw, ENETC_PMR, (tmp & ~ENETC_PMR_PSPEED_MASK) | pspeed); } -static int enetc_setup_taprio(struct net_device *ndev, +static int enetc_setup_taprio(struct enetc_ndev_priv *priv, struct tc_taprio_qopt_offload *admin_conf) { - struct enetc_ndev_priv *priv = netdev_priv(ndev); struct enetc_hw *hw = &priv->si->hw; struct enetc_cbd cbd = {.cmd = 0}; struct tgs_gcl_conf *gcl_config; @@ -60,19 +59,13 @@ static int enetc_setup_taprio(struct net_device *ndev, int err; int i; + /* TSD and Qbv are mutually exclusive in hardware */ + for (i = 0; i < priv->num_tx_rings; i++) + if (priv->tx_ring[i]->tsd_enable) + return -EBUSY; + if (admin_conf->num_entries > enetc_get_max_gcl_len(hw)) return -EINVAL; - gcl_len = admin_conf->num_entries; - - tge = enetc_rd(hw, ENETC_PTGCR); - if (!admin_conf->enable) { - enetc_wr(hw, ENETC_PTGCR, tge & ~ENETC_PTGCR_TGE); - enetc_reset_ptcmsdur(hw); - - priv->active_offloads &= ~ENETC_F_QBV; - - return 0; - } if (admin_conf->cycle_time > U32_MAX || admin_conf->cycle_time_extension > U32_MAX) @@ -82,6 +75,7 @@ static int enetc_setup_taprio(struct net_device *ndev, * control BD descriptor. */ gcl_config = &cbd.gcl_conf; + gcl_len = admin_conf->num_entries; data_size = struct_size(gcl_data, entry, gcl_len); tmp = enetc_cbd_alloc_data_mem(priv->si, &cbd, data_size, @@ -115,6 +109,7 @@ static int enetc_setup_taprio(struct net_device *ndev, cbd.cls = BDCR_CMD_PORT_GCL; cbd.status_flags = 0; + tge = enetc_rd(hw, ENETC_PTGCR); enetc_wr(hw, ENETC_PTGCR, tge | ENETC_PTGCR_TGE); err = enetc_send_cmd(priv->si, &cbd); @@ -132,25 +127,95 @@ static int enetc_setup_taprio(struct net_device *ndev, return 0; } -int enetc_setup_tc_taprio(struct net_device *ndev, void *type_data) +static void enetc_reset_taprio_stats(struct enetc_ndev_priv *priv) +{ + int i; + + for (i = 0; i < priv->num_tx_rings; i++) + priv->tx_ring[i]->stats.win_drop = 0; +} + +static void enetc_reset_taprio(struct enetc_ndev_priv *priv) +{ + struct enetc_hw *hw = &priv->si->hw; + u32 val; + + val = enetc_rd(hw, ENETC_PTGCR); + enetc_wr(hw, ENETC_PTGCR, val & ~ENETC_PTGCR_TGE); + enetc_reset_ptcmsdur(hw); + + priv->active_offloads &= ~ENETC_F_QBV; +} + +static void enetc_taprio_destroy(struct net_device *ndev) { - struct tc_taprio_qopt_offload *taprio = type_data; struct enetc_ndev_priv *priv = netdev_priv(ndev); - int err, i; - /* TSD and Qbv are mutually exclusive in hardware */ + enetc_reset_taprio(priv); + enetc_reset_tc_mqprio(ndev); + enetc_reset_taprio_stats(priv); +} + +static void enetc_taprio_stats(struct net_device *ndev, + struct tc_taprio_qopt_stats *stats) +{ + struct enetc_ndev_priv *priv = netdev_priv(ndev); + u64 window_drops = 0; + int i; + for (i = 0; i < priv->num_tx_rings; i++) - if (priv->tx_ring[i]->tsd_enable) - return -EBUSY; + window_drops += priv->tx_ring[i]->stats.win_drop; + + stats->window_drops = window_drops; +} + +static void enetc_taprio_queue_stats(struct net_device *ndev, + struct tc_taprio_qopt_queue_stats *queue_stats) +{ + struct tc_taprio_qopt_stats *stats = &queue_stats->stats; + struct enetc_ndev_priv *priv = netdev_priv(ndev); + int queue = queue_stats->queue; - err = enetc_setup_tc_mqprio(ndev, &taprio->mqprio); + stats->window_drops = priv->tx_ring[queue]->stats.win_drop; +} + +static int enetc_taprio_replace(struct net_device *ndev, + struct tc_taprio_qopt_offload *offload) +{ + struct enetc_ndev_priv *priv = netdev_priv(ndev); + int err; + + err = enetc_setup_tc_mqprio(ndev, &offload->mqprio); if (err) return err; - err = enetc_setup_taprio(ndev, taprio); - if (err) { - taprio->mqprio.qopt.num_tc = 0; - enetc_setup_tc_mqprio(ndev, &taprio->mqprio); + err = enetc_setup_taprio(priv, offload); + if (err) + enetc_reset_tc_mqprio(ndev); + + return err; +} + +int enetc_setup_tc_taprio(struct net_device *ndev, void *type_data) +{ + struct tc_taprio_qopt_offload *offload = type_data; + int err = 0; + + switch (offload->cmd) { + case TAPRIO_CMD_REPLACE: + err = enetc_taprio_replace(ndev, offload); + break; + case TAPRIO_CMD_DESTROY: + enetc_taprio_destroy(ndev); + break; + case TAPRIO_CMD_STATS: + enetc_taprio_stats(ndev, &offload->stats); + break; + case TAPRIO_CMD_QUEUE_STATS: + enetc_taprio_queue_stats(ndev, &offload->queue_stats); + break; + default: + err = -EOPNOTSUPP; } return err; diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h index 9939ccafb556609f8b6931ef42bb49f267aadea8..63a053dea819d09807942adf30a6795f49d31cd6 100644 --- a/drivers/net/ethernet/freescale/fec.h +++ b/drivers/net/ethernet/freescale/fec.h @@ -355,7 +355,7 @@ struct bufdesc_ex { #define RX_RING_SIZE (FEC_ENET_RX_FRPPG * FEC_ENET_RX_PAGES) #define FEC_ENET_TX_FRSIZE 2048 #define FEC_ENET_TX_FRPPG (PAGE_SIZE / FEC_ENET_TX_FRSIZE) -#define TX_RING_SIZE 512 /* Must be power of two */ +#define TX_RING_SIZE 1024 /* Must be power of two */ #define TX_RING_MOD_MASK 511 /* for this to work */ #define BD_ENET_RX_INT 0x00800000 @@ -544,10 +544,23 @@ enum { XDP_STATS_TOTAL, }; +enum fec_txbuf_type { + FEC_TXBUF_T_SKB, + FEC_TXBUF_T_XDP_NDO, +}; + +struct fec_tx_buffer { + union { + struct sk_buff *skb; + struct xdp_frame *xdp; + }; + enum fec_txbuf_type type; +}; + struct fec_enet_priv_tx_q { struct bufdesc_prop bd; unsigned char *tx_bounce[TX_RING_SIZE]; - struct sk_buff *tx_skbuff[TX_RING_SIZE]; + struct fec_tx_buffer tx_buf[TX_RING_SIZE]; unsigned short tx_stop_threshold; unsigned short tx_wake_threshold; diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index 38e5b5abe067cf6ce8a2bf8144c9dd7245ae2e8c..ec9e4bdb0c06be7eaa2e6aa0d2957ee70c57100f 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -397,7 +397,7 @@ static void fec_dump(struct net_device *ndev) fec16_to_cpu(bdp->cbd_sc), fec32_to_cpu(bdp->cbd_bufaddr), fec16_to_cpu(bdp->cbd_datlen), - txq->tx_skbuff[index]); + txq->tx_buf[index].skb); bdp = fec_enet_get_nextdesc(bdp, &txq->bd); index++; } while (bdp != txq->bd.base); @@ -654,7 +654,7 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq, index = fec_enet_get_bd_index(last_bdp, &txq->bd); /* Save skb pointer */ - txq->tx_skbuff[index] = skb; + txq->tx_buf[index].skb = skb; /* Make sure the updates to rest of the descriptor are performed before * transferring ownership. @@ -672,9 +672,7 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq, skb_tx_timestamp(skb); - /* Make sure the update to bdp and tx_skbuff are performed before - * txq->bd.cur. - */ + /* Make sure the update to bdp is performed before txq->bd.cur. */ wmb(); txq->bd.cur = bdp; @@ -862,7 +860,7 @@ static int fec_enet_txq_submit_tso(struct fec_enet_priv_tx_q *txq, } /* Save skb pointer */ - txq->tx_skbuff[index] = skb; + txq->tx_buf[index].skb = skb; skb_tx_timestamp(skb); txq->bd.cur = bdp; @@ -952,16 +950,33 @@ static void fec_enet_bd_init(struct net_device *dev) for (i = 0; i < txq->bd.ring_size; i++) { /* Initialize the BD for every fragment in the page. */ bdp->cbd_sc = cpu_to_fec16(0); - if (bdp->cbd_bufaddr && - !IS_TSO_HEADER(txq, fec32_to_cpu(bdp->cbd_bufaddr))) - dma_unmap_single(&fep->pdev->dev, - fec32_to_cpu(bdp->cbd_bufaddr), - fec16_to_cpu(bdp->cbd_datlen), - DMA_TO_DEVICE); - if (txq->tx_skbuff[i]) { - dev_kfree_skb_any(txq->tx_skbuff[i]); - txq->tx_skbuff[i] = NULL; + if (txq->tx_buf[i].type == FEC_TXBUF_T_SKB) { + if (bdp->cbd_bufaddr && + !IS_TSO_HEADER(txq, fec32_to_cpu(bdp->cbd_bufaddr))) + dma_unmap_single(&fep->pdev->dev, + fec32_to_cpu(bdp->cbd_bufaddr), + fec16_to_cpu(bdp->cbd_datlen), + DMA_TO_DEVICE); + if (txq->tx_buf[i].skb) { + dev_kfree_skb_any(txq->tx_buf[i].skb); + txq->tx_buf[i].skb = NULL; + } + } else { + if (bdp->cbd_bufaddr) + dma_unmap_single(&fep->pdev->dev, + fec32_to_cpu(bdp->cbd_bufaddr), + fec16_to_cpu(bdp->cbd_datlen), + DMA_TO_DEVICE); + + if (txq->tx_buf[i].xdp) { + xdp_return_frame(txq->tx_buf[i].xdp); + txq->tx_buf[i].xdp = NULL; + } + + /* restore default tx buffer type: FEC_TXBUF_T_SKB */ + txq->tx_buf[i].type = FEC_TXBUF_T_SKB; } + bdp->cbd_bufaddr = cpu_to_fec32(0); bdp = fec_enet_get_nextdesc(bdp, &txq->bd); } @@ -1011,24 +1026,6 @@ static void fec_enet_enable_ring(struct net_device *ndev) } } -static void fec_enet_reset_skb(struct net_device *ndev) -{ - struct fec_enet_private *fep = netdev_priv(ndev); - struct fec_enet_priv_tx_q *txq; - int i, j; - - for (i = 0; i < fep->num_tx_queues; i++) { - txq = fep->tx_queue[i]; - - for (j = 0; j < txq->bd.ring_size; j++) { - if (txq->tx_skbuff[j]) { - dev_kfree_skb_any(txq->tx_skbuff[j]); - txq->tx_skbuff[j] = NULL; - } - } - } -} - /* * This function is called to start or restart the FEC during a link * change, transmit timeout, or to reconfigure the FEC. The network @@ -1071,9 +1068,6 @@ fec_restart(struct net_device *ndev) fec_enet_enable_ring(ndev); - /* Reset tx SKB buffers. */ - fec_enet_reset_skb(ndev); - /* Enable MII mode */ if (fep->full_duplex == DUPLEX_FULL) { /* FD enable */ @@ -1381,6 +1375,7 @@ static void fec_enet_tx_queue(struct net_device *ndev, u16 queue_id) { struct fec_enet_private *fep; + struct xdp_frame *xdpf; struct bufdesc *bdp; unsigned short status; struct sk_buff *skb; @@ -1408,16 +1403,31 @@ fec_enet_tx_queue(struct net_device *ndev, u16 queue_id) index = fec_enet_get_bd_index(bdp, &txq->bd); - skb = txq->tx_skbuff[index]; - txq->tx_skbuff[index] = NULL; - if (!IS_TSO_HEADER(txq, fec32_to_cpu(bdp->cbd_bufaddr))) - dma_unmap_single(&fep->pdev->dev, - fec32_to_cpu(bdp->cbd_bufaddr), - fec16_to_cpu(bdp->cbd_datlen), - DMA_TO_DEVICE); - bdp->cbd_bufaddr = cpu_to_fec32(0); - if (!skb) - goto skb_done; + if (txq->tx_buf[index].type == FEC_TXBUF_T_SKB) { + skb = txq->tx_buf[index].skb; + txq->tx_buf[index].skb = NULL; + if (bdp->cbd_bufaddr && + !IS_TSO_HEADER(txq, fec32_to_cpu(bdp->cbd_bufaddr))) + dma_unmap_single(&fep->pdev->dev, + fec32_to_cpu(bdp->cbd_bufaddr), + fec16_to_cpu(bdp->cbd_datlen), + DMA_TO_DEVICE); + bdp->cbd_bufaddr = cpu_to_fec32(0); + if (!skb) + goto tx_buf_done; + } else { + xdpf = txq->tx_buf[index].xdp; + if (bdp->cbd_bufaddr) + dma_unmap_single(&fep->pdev->dev, + fec32_to_cpu(bdp->cbd_bufaddr), + fec16_to_cpu(bdp->cbd_datlen), + DMA_TO_DEVICE); + bdp->cbd_bufaddr = cpu_to_fec32(0); + if (!xdpf) { + txq->tx_buf[index].type = FEC_TXBUF_T_SKB; + goto tx_buf_done; + } + } /* Check for errors. */ if (status & (BD_ENET_TX_HB | BD_ENET_TX_LC | @@ -1436,21 +1446,11 @@ fec_enet_tx_queue(struct net_device *ndev, u16 queue_id) ndev->stats.tx_carrier_errors++; } else { ndev->stats.tx_packets++; - ndev->stats.tx_bytes += skb->len; - } - - /* NOTE: SKBTX_IN_PROGRESS being set does not imply it's we who - * are to time stamp the packet, so we still need to check time - * stamping enabled flag. - */ - if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS && - fep->hwts_tx_en) && - fep->bufdesc_ex) { - struct skb_shared_hwtstamps shhwtstamps; - struct bufdesc_ex *ebdp = (struct bufdesc_ex *)bdp; - fec_enet_hwtstamp(fep, fec32_to_cpu(ebdp->ts), &shhwtstamps); - skb_tstamp_tx(skb, &shhwtstamps); + if (txq->tx_buf[index].type == FEC_TXBUF_T_SKB) + ndev->stats.tx_bytes += skb->len; + else + ndev->stats.tx_bytes += xdpf->len; } /* Deferred means some collisions occurred during transmit, @@ -1459,10 +1459,32 @@ fec_enet_tx_queue(struct net_device *ndev, u16 queue_id) if (status & BD_ENET_TX_DEF) ndev->stats.collisions++; - /* Free the sk buffer associated with this last transmit */ - dev_kfree_skb_any(skb); -skb_done: - /* Make sure the update to bdp and tx_skbuff are performed + if (txq->tx_buf[index].type == FEC_TXBUF_T_SKB) { + /* NOTE: SKBTX_IN_PROGRESS being set does not imply it's we who + * are to time stamp the packet, so we still need to check time + * stamping enabled flag. + */ + if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS && + fep->hwts_tx_en) && fep->bufdesc_ex) { + struct skb_shared_hwtstamps shhwtstamps; + struct bufdesc_ex *ebdp = (struct bufdesc_ex *)bdp; + + fec_enet_hwtstamp(fep, fec32_to_cpu(ebdp->ts), &shhwtstamps); + skb_tstamp_tx(skb, &shhwtstamps); + } + + /* Free the sk buffer associated with this last transmit */ + dev_kfree_skb_any(skb); + } else { + xdp_return_frame(xdpf); + + txq->tx_buf[index].xdp = NULL; + /* restore default tx buffer type: FEC_TXBUF_T_SKB */ + txq->tx_buf[index].type = FEC_TXBUF_T_SKB; + } + +tx_buf_done: + /* Make sure the update to bdp and tx_buf are performed * before dirty_tx */ wmb(); @@ -2810,6 +2832,7 @@ static void fec_enet_get_xdp_stats(struct fec_enet_private *fep, u64 *data) static void fec_enet_page_pool_stats(struct fec_enet_private *fep, u64 *data) { +#ifdef CONFIG_PAGE_POOL_STATS struct page_pool_stats stats = {}; struct fec_enet_priv_rx_q *rxq; int i; @@ -2824,6 +2847,7 @@ static void fec_enet_page_pool_stats(struct fec_enet_private *fep, u64 *data) } page_pool_ethtool_stats_get(data, &stats); +#endif } static void fec_enet_get_ethtool_stats(struct net_device *dev, @@ -3268,9 +3292,19 @@ static void fec_enet_free_buffers(struct net_device *ndev) for (i = 0; i < txq->bd.ring_size; i++) { kfree(txq->tx_bounce[i]); txq->tx_bounce[i] = NULL; - skb = txq->tx_skbuff[i]; - txq->tx_skbuff[i] = NULL; - dev_kfree_skb(skb); + + if (txq->tx_buf[i].type == FEC_TXBUF_T_SKB) { + skb = txq->tx_buf[i].skb; + txq->tx_buf[i].skb = NULL; + dev_kfree_skb(skb); + } else { + if (txq->tx_buf[i].xdp) { + xdp_return_frame(txq->tx_buf[i].xdp); + txq->tx_buf[i].xdp = NULL; + } + + txq->tx_buf[i].type = FEC_TXBUF_T_SKB; + } } } } @@ -3315,8 +3349,7 @@ static int fec_enet_alloc_queue(struct net_device *ndev) fep->total_tx_ring_size += fep->tx_queue[i]->bd.ring_size; txq->tx_stop_threshold = FEC_MAX_SKB_DESCS; - txq->tx_wake_threshold = - (txq->bd.ring_size - txq->tx_stop_threshold) / 2; + txq->tx_wake_threshold = FEC_MAX_SKB_DESCS + 2 * MAX_SKB_FRAGS; txq->tso_hdrs = dma_alloc_coherent(&fep->pdev->dev, txq->bd.ring_size * TSO_HEADER_SIZE, @@ -3751,12 +3784,18 @@ static int fec_enet_bpf(struct net_device *dev, struct netdev_bpf *bpf) if (fep->quirks & FEC_QUIRK_SWAP_FRAME) return -EOPNOTSUPP; + if (!bpf->prog) + xdp_features_clear_redirect_target(dev); + if (is_run) { napi_disable(&fep->napi); netif_tx_disable(dev); } old_prog = xchg(&fep->xdp_prog, bpf->prog); + if (old_prog) + bpf_prog_put(old_prog); + fec_restart(dev); if (is_run) { @@ -3764,8 +3803,8 @@ static int fec_enet_bpf(struct net_device *dev, struct netdev_bpf *bpf) netif_tx_start_all_queues(dev); } - if (old_prog) - bpf_prog_put(old_prog); + if (bpf->prog) + xdp_features_set_redirect_target(dev, false); return 0; @@ -3791,19 +3830,18 @@ static int fec_enet_txq_xmit_frame(struct fec_enet_private *fep, struct xdp_frame *frame) { unsigned int index, status, estatus; - struct bufdesc *bdp, *last_bdp; + struct bufdesc *bdp; dma_addr_t dma_addr; int entries_free; entries_free = fec_enet_get_free_txdesc_num(txq); if (entries_free < MAX_SKB_FRAGS + 1) { - netdev_err(fep->netdev, "NOT enough BD for SG!\n"); - return NETDEV_TX_BUSY; + netdev_err_once(fep->netdev, "NOT enough BD for SG!\n"); + return -EBUSY; } /* Fill in a Tx ring entry */ bdp = txq->bd.cur; - last_bdp = bdp; status = fec16_to_cpu(bdp->cbd_sc); status &= ~BD_ENET_TX_STATS; @@ -3812,7 +3850,7 @@ static int fec_enet_txq_xmit_frame(struct fec_enet_private *fep, dma_addr = dma_map_single(&fep->pdev->dev, frame->data, frame->len, DMA_TO_DEVICE); if (dma_mapping_error(&fep->pdev->dev, dma_addr)) - return FEC_ENET_XDP_CONSUMED; + return -ENOMEM; status |= (BD_ENET_TX_INTR | BD_ENET_TX_LAST); if (fep->bufdesc_ex) @@ -3831,8 +3869,8 @@ static int fec_enet_txq_xmit_frame(struct fec_enet_private *fep, ebdp->cbd_esc = cpu_to_fec32(estatus); } - index = fec_enet_get_bd_index(last_bdp, &txq->bd); - txq->tx_skbuff[index] = NULL; + txq->tx_buf[index].type = FEC_TXBUF_T_XDP_NDO; + txq->tx_buf[index].xdp = frame; /* Make sure the updates to rest of the descriptor are performed before * transferring ownership. @@ -3846,7 +3884,7 @@ static int fec_enet_txq_xmit_frame(struct fec_enet_private *fep, bdp->cbd_sc = cpu_to_fec16(status); /* If this was the last BD in the ring, start at the beginning again. */ - bdp = fec_enet_get_nextdesc(last_bdp, &txq->bd); + bdp = fec_enet_get_nextdesc(bdp, &txq->bd); /* Make sure the update to bdp are performed before txq->bd.cur. */ dma_wmb(); @@ -3879,7 +3917,7 @@ static int fec_enet_xdp_xmit(struct net_device *dev, __netif_tx_lock(nq, cpu); for (i = 0; i < num_frames; i++) { - if (fec_enet_txq_xmit_frame(fep, txq, frames[i]) != 0) + if (fec_enet_txq_xmit_frame(fep, txq, frames[i]) < 0) break; sent_frames++; } @@ -4035,6 +4073,10 @@ static int fec_enet_init(struct net_device *ndev) ndev->hw_features = ndev->features; + if (!(fep->quirks & FEC_QUIRK_SWAP_FRAME)) + ndev->xdp_features = NETDEV_XDP_ACT_BASIC | + NETDEV_XDP_ACT_REDIRECT; + fec_restart(ndev); if (fep->quirks & FEC_QUIRK_MIB_CLEAR) diff --git a/drivers/net/ethernet/freescale/fman/fman_dtsec.c b/drivers/net/ethernet/freescale/fman/fman_dtsec.c index d528ca681b6f4616de32dd9da7d0339509f8f707..3088da7adf0f846744079107f7f72fea74114f4a 100644 --- a/drivers/net/ethernet/freescale/fman/fman_dtsec.c +++ b/drivers/net/ethernet/freescale/fman/fman_dtsec.c @@ -763,15 +763,15 @@ static void dtsec_pcs_get_state(struct phylink_pcs *pcs, phylink_mii_c22_pcs_get_state(dtsec->tbidev, state); } -static int dtsec_pcs_config(struct phylink_pcs *pcs, unsigned int mode, +static int dtsec_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode, phy_interface_t interface, const unsigned long *advertising, bool permit_pause_to_mac) { struct fman_mac *dtsec = pcs_to_dtsec(pcs); - return phylink_mii_c22_pcs_config(dtsec->tbidev, mode, interface, - advertising); + return phylink_mii_c22_pcs_config(dtsec->tbidev, interface, + advertising, neg_mode); } static void dtsec_pcs_an_restart(struct phylink_pcs *pcs) @@ -1447,6 +1447,7 @@ int dtsec_initialization(struct mac_device *mac_dev, goto _return_fm_mac_free; } dtsec->pcs.ops = &dtsec_pcs_ops; + dtsec->pcs.neg_mode = true; dtsec->pcs.poll = true; supported = mac_dev->phylink_config.supported_interfaces; diff --git a/drivers/net/ethernet/freescale/fman/fman_memac.c b/drivers/net/ethernet/freescale/fman/fman_memac.c index 625c79d5636fbd0c4ad54c7a1e0fadfa77ed776a..3b75cc543be93f058323deda9f97964ed3da724b 100644 --- a/drivers/net/ethernet/freescale/fman/fman_memac.c +++ b/drivers/net/ethernet/freescale/fman/fman_memac.c @@ -976,14 +976,10 @@ static int memac_init(struct fman_mac *memac) static void pcs_put(struct phylink_pcs *pcs) { - struct mdio_device *mdiodev; - if (IS_ERR_OR_NULL(pcs)) return; - mdiodev = lynx_get_mdio_device(pcs); lynx_pcs_destroy(pcs); - mdio_device_free(mdiodev); } static int memac_free(struct fman_mac *memac) @@ -1043,20 +1039,14 @@ static struct phylink_pcs *memac_pcs_create(struct device_node *mac_node, int index) { struct device_node *node; - struct mdio_device *mdiodev = NULL; struct phylink_pcs *pcs; node = of_parse_phandle(mac_node, "pcsphy-handle", index); - if (node && of_device_is_available(node)) - mdiodev = of_mdio_find_device(node); - of_node_put(node); + if (!node) + return ERR_PTR(-ENODEV); - if (!mdiodev) - return ERR_PTR(-EPROBE_DEFER); - - pcs = lynx_pcs_create(mdiodev); - if (!pcs) - mdio_device_free(mdiodev); + pcs = lynx_pcs_create_fwnode(of_fwnode_handle(node)); + of_node_put(node); return pcs; } diff --git a/drivers/net/ethernet/freescale/fs_enet/mii-fec.c b/drivers/net/ethernet/freescale/fs_enet/mii-fec.c index d37d7a19a75978ed9f47ba71062b20bd9489c7ab..59a8f0bd0f5c077c51365ed7698a62d27385a3a3 100644 --- a/drivers/net/ethernet/freescale/fs_enet/mii-fec.c +++ b/drivers/net/ethernet/freescale/fs_enet/mii-fec.c @@ -127,7 +127,7 @@ static int fs_enet_mdio_probe(struct platform_device *ofdev) if (ret) goto out_res; - snprintf(new_bus->id, MII_BUS_ID_SIZE, "%x", res.start); + snprintf(new_bus->id, MII_BUS_ID_SIZE, "%pap", &res.start); fec->fecp = ioremap(res.start, resource_size(&res)); if (!fec->fecp) { diff --git a/drivers/net/ethernet/fungible/funeth/funeth_rx.c b/drivers/net/ethernet/fungible/funeth/funeth_rx.c index 29a6c2ede43a6991af695e63659d5f477d3d2d4b..7e2584895de39ba5f6aee946a1a0c887210670fe 100644 --- a/drivers/net/ethernet/fungible/funeth/funeth_rx.c +++ b/drivers/net/ethernet/fungible/funeth/funeth_rx.c @@ -323,9 +323,8 @@ static int fun_gather_pkt(struct funeth_rxq *q, unsigned int tot_len, if (ref_ok) ref_ok |= buf->node; - __skb_frag_set_page(frags, buf->page); - skb_frag_off_set(frags, q->buf_offset); - skb_frag_size_set(frags++, frag_len); + skb_frag_fill_page_desc(frags++, buf->page, q->buf_offset, + frag_len); tot_len -= frag_len; if (!tot_len) diff --git a/drivers/net/ethernet/fungible/funeth/funeth_tx.c b/drivers/net/ethernet/fungible/funeth/funeth_tx.c index 706d81e39a54d3b1902e3ec0aafe8f29a75dff52..8ddefd3ec15b64ad0ede28dd58cbddf07af82dab 100644 --- a/drivers/net/ethernet/fungible/funeth/funeth_tx.c +++ b/drivers/net/ethernet/fungible/funeth/funeth_tx.c @@ -348,8 +348,7 @@ netdev_tx_t fun_start_xmit(struct sk_buff *skb, struct net_device *netdev) unsigned int tls_len = 0; unsigned int ndesc; - if (IS_ENABLED(CONFIG_TLS_DEVICE) && skb->sk && - tls_is_sk_tx_device_offloaded(skb->sk)) { + if (tls_is_skb_tx_device_offloaded(skb)) { skb = fun_tls_tx(skb, q, &tls_len); if (unlikely(!skb)) goto dropped; diff --git a/drivers/net/ethernet/google/gve/gve.h b/drivers/net/ethernet/google/gve/gve.h index 98eb78d98e9f43c6e8541946d5398e9d7824005e..4b425bf71ede13711fbc3d3a81abd8447d5d4193 100644 --- a/drivers/net/ethernet/google/gve/gve.h +++ b/drivers/net/ethernet/google/gve/gve.h @@ -964,5 +964,6 @@ void gve_handle_report_stats(struct gve_priv *priv); /* exported by ethtool.c */ extern const struct ethtool_ops gve_ethtool_ops; /* needed by ethtool */ +extern char gve_driver_name[]; extern const char gve_version_str[]; #endif /* _GVE_H_ */ diff --git a/drivers/net/ethernet/google/gve/gve_ethtool.c b/drivers/net/ethernet/google/gve/gve_ethtool.c index cfd4b8d284d12eaaf1b7fef612c3db47fbf0bc8d..233e5946905e7dfa4bb7f0bf2955cd316b352b21 100644 --- a/drivers/net/ethernet/google/gve/gve_ethtool.c +++ b/drivers/net/ethernet/google/gve/gve_ethtool.c @@ -15,7 +15,7 @@ static void gve_get_drvinfo(struct net_device *netdev, { struct gve_priv *priv = netdev_priv(netdev); - strscpy(info->driver, "gve", sizeof(info->driver)); + strscpy(info->driver, gve_driver_name, sizeof(info->driver)); strscpy(info->version, gve_version_str, sizeof(info->version)); strscpy(info->bus_info, pci_name(priv->pdev), sizeof(info->bus_info)); } @@ -590,6 +590,9 @@ static int gve_get_link_ksettings(struct net_device *netdev, err = gve_adminq_report_link_speed(priv); cmd->base.speed = priv->link_speed; + + cmd->base.duplex = DUPLEX_FULL; + return err; } diff --git a/drivers/net/ethernet/google/gve/gve_main.c b/drivers/net/ethernet/google/gve/gve_main.c index caa00c72aeebaac083b22e11fb8b4094e8e62eab..e6f1711d9be04f5ccdc1ed9ed4fd8b83027e16ed 100644 --- a/drivers/net/ethernet/google/gve/gve_main.c +++ b/drivers/net/ethernet/google/gve/gve_main.c @@ -31,7 +31,9 @@ // Minimum amount of time between queue kicks in msec (10 seconds) #define MIN_TX_TIMEOUT_GAP (1000 * 10) +#define DQO_TX_MAX 0x3FFFF +char gve_driver_name[] = "gve"; const char gve_version_str[] = GVE_VERSION; static const char gve_version_prefix[] = GVE_VERSION_PREFIX; @@ -2047,6 +2049,10 @@ static int gve_init_priv(struct gve_priv *priv, bool skip_describe_device) goto err; } + /* Big TCP is only supported on DQ*/ + if (!gve_is_gqi(priv)) + netif_set_tso_max_size(priv->dev, DQO_TX_MAX); + priv->num_registered_pages = 0; priv->rx_copybreak = GVE_DEFAULT_RX_COPYBREAK; /* gvnic has one Notification Block per MSI-x vector, except for the @@ -2195,7 +2201,7 @@ static int gve_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if (err) return err; - err = pci_request_regions(pdev, "gvnic-cfg"); + err = pci_request_regions(pdev, gve_driver_name); if (err) goto abort_with_enabled; @@ -2388,8 +2394,8 @@ static const struct pci_device_id gve_id_table[] = { { } }; -static struct pci_driver gvnic_driver = { - .name = "gvnic", +static struct pci_driver gve_driver = { + .name = gve_driver_name, .id_table = gve_id_table, .probe = gve_probe, .remove = gve_remove, @@ -2400,10 +2406,10 @@ static struct pci_driver gvnic_driver = { #endif }; -module_pci_driver(gvnic_driver); +module_pci_driver(gve_driver); MODULE_DEVICE_TABLE(pci, gve_id_table); MODULE_AUTHOR("Google, Inc."); -MODULE_DESCRIPTION("gVNIC Driver"); +MODULE_DESCRIPTION("Google Virtual NIC Driver"); MODULE_LICENSE("Dual MIT/GPL"); MODULE_VERSION(GVE_VERSION); diff --git a/drivers/net/ethernet/google/gve/gve_tx.c b/drivers/net/ethernet/google/gve/gve_tx.c index 813da572abca2d198cc91eec85e740504b40d5a0..6957a865cff37c86a96e4929b986915907781415 100644 --- a/drivers/net/ethernet/google/gve/gve_tx.c +++ b/drivers/net/ethernet/google/gve/gve_tx.c @@ -248,7 +248,7 @@ static int gve_tx_alloc_ring(struct gve_priv *priv, int idx) tx->mask = slots - 1; /* alloc metadata */ - tx->info = vzalloc(sizeof(*tx->info) * slots); + tx->info = vcalloc(slots, sizeof(*tx->info)); if (!tx->info) return -ENOMEM; diff --git a/drivers/net/ethernet/google/gve/gve_tx_dqo.c b/drivers/net/ethernet/google/gve/gve_tx_dqo.c index b76143bfd594793bbdd4a5eae4aa9a7fc4632e91..3c09e66ba1ab1107b26d467df72a6f8035d47b11 100644 --- a/drivers/net/ethernet/google/gve/gve_tx_dqo.c +++ b/drivers/net/ethernet/google/gve/gve_tx_dqo.c @@ -8,6 +8,7 @@ #include "gve_adminq.h" #include "gve_utils.h" #include "gve_dqo.h" +#include #include #include #include @@ -646,6 +647,9 @@ static int gve_try_tx_skb(struct gve_priv *priv, struct gve_tx_ring *tx, goto drop; } + if (unlikely(ipv6_hopopt_jumbo_remove(skb))) + goto drop; + num_buffer_descs = gve_num_buffer_descs_needed(skb); } else { num_buffer_descs = gve_num_buffer_descs_needed(skb); diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h index 9c9c72dc57e00d886fa5f83aaaebb0ce7e25681d..b99d75260d594747acda60864f0c7e1c15174a81 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h +++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h @@ -647,8 +647,7 @@ struct hnae3_ae_ops { int (*rm_mc_addr)(struct hnae3_handle *handle, const unsigned char *addr); void (*set_tso_stats)(struct hnae3_handle *handle, int enable); - void (*update_stats)(struct hnae3_handle *handle, - struct net_device_stats *net_stats); + void (*update_stats)(struct hnae3_handle *handle); void (*get_stats)(struct hnae3_handle *handle, u64 *data); void (*get_mac_stats)(struct hnae3_handle *handle, struct hns3_mac_stats *mac_stats); diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_rss.c b/drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_rss.c index ae2736549526b1511d9ad73aa6a5376274a025f3..b4ae2160aff4f3fb7aef8ee4056e752bc46662ae 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_rss.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_rss.c @@ -305,8 +305,7 @@ int hclge_comm_set_rss_indir_table(struct hnae3_ae_dev *ae_dev, return 0; } -int hclge_comm_set_rss_input_tuple(struct hnae3_handle *nic, - struct hclge_comm_hw *hw, bool is_pf, +int hclge_comm_set_rss_input_tuple(struct hclge_comm_hw *hw, struct hclge_comm_rss_cfg *rss_cfg) { struct hclge_comm_rss_input_tuple_cmd *req; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_rss.h b/drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_rss.h index 92af3d2980d3cb7145bc44a6d517c435b3d2ff93..cdafa63fe38bc13efff38d282a9f88067096e48a 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_rss.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_rss.h @@ -112,8 +112,7 @@ int hclge_comm_init_rss_tuple_cmd(struct hclge_comm_rss_cfg *rss_cfg, struct hnae3_ae_dev *ae_dev, struct hclge_comm_rss_input_tuple_cmd *req); u64 hclge_comm_convert_rss_tuple(u8 tuple_sets); -int hclge_comm_set_rss_input_tuple(struct hnae3_handle *nic, - struct hclge_comm_hw *hw, bool is_pf, +int hclge_comm_set_rss_input_tuple(struct hclge_comm_hw *hw, struct hclge_comm_rss_cfg *rss_cfg); int hclge_comm_set_rss_indir_table(struct hnae3_ae_dev *ae_dev, struct hclge_comm_hw *hw, const u16 *indir); diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c index d385ffc21876601d94022104c545fa95be60ddcb..6546cfe7f7cc71a67fdd650597d616e1134cddcb 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c @@ -438,19 +438,36 @@ static void hns3_dbg_fill_content(char *content, u16 len, const struct hns3_dbg_item *items, const char **result, u16 size) { +#define HNS3_DBG_LINE_END_LEN 2 char *pos = content; + u16 item_len; u16 i; + if (!len) { + return; + } else if (len <= HNS3_DBG_LINE_END_LEN) { + *pos++ = '\0'; + return; + } + memset(content, ' ', len); - for (i = 0; i < size; i++) { - if (result) - strncpy(pos, result[i], strlen(result[i])); - else - strncpy(pos, items[i].name, strlen(items[i].name)); + len -= HNS3_DBG_LINE_END_LEN; - pos += strlen(items[i].name) + items[i].interval; + for (i = 0; i < size; i++) { + item_len = strlen(items[i].name) + items[i].interval; + if (len < item_len) + break; + + if (result) { + if (item_len < strlen(result[i])) + break; + strscpy(pos, result[i], strlen(result[i])); + } else { + strscpy(pos, items[i].name, strlen(items[i].name)); + } + pos += item_len; + len -= item_len; } - *pos++ = '\n'; *pos++ = '\0'; } @@ -941,8 +958,7 @@ static const struct hns3_dbg_item tx_bd_info_items[] = { { "MSS_HW_CSUM", 0 }, }; -static void hns3_dump_tx_bd_info(struct hns3_nic_priv *priv, - struct hns3_desc *desc, char **result, int idx) +static void hns3_dump_tx_bd_info(struct hns3_desc *desc, char **result, int idx) { unsigned int j = 0; @@ -991,7 +1007,7 @@ static int hns3_dbg_tx_bd_info(struct hns3_dbg_data *d, char *buf, int len) for (i = 0; i < ring->desc_num; i++) { desc = &ring->desc[i]; - hns3_dump_tx_bd_info(priv, desc, result, i); + hns3_dump_tx_bd_info(desc, result, i); hns3_dbg_fill_content(content, sizeof(content), tx_bd_info_items, (const char **)result, ARRAY_SIZE(tx_bd_info_items)); diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index b676496ec6d7ce5b7c28454eab5e442603a64d9a..9f6890059666e50bde32445c801369417c882796 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -2538,7 +2538,7 @@ static void hns3_nic_get_stats64(struct net_device *netdev, if (test_bit(HNS3_NIC_STATE_DOWN, &priv->state)) return; - handle->ae_algo->ops->update_stats(handle, &netdev->stats); + handle->ae_algo->ops->update_stats(handle); memset(&ring_total_stats, 0, sizeof(ring_total_stats)); for (idx = 0; idx < queue_num; idx++) { diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c index 51d1278b18f6637d1e7bd13bc04970d6843d41b3..407d30ee55d2e449f787e080b1b9b16864eda6a0 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c @@ -228,7 +228,7 @@ static u32 hns3_lb_check_rx_ring(struct hns3_nic_priv *priv, u32 budget) } static void hns3_lb_clear_tx_ring(struct hns3_nic_priv *priv, u32 start_ringid, - u32 end_ringid, u32 budget) + u32 end_ringid) { u32 i; @@ -295,8 +295,7 @@ static int hns3_lp_run_test(struct net_device *ndev, enum hnae3_loop mode) out: hns3_lb_clear_tx_ring(priv, HNS3_NIC_LB_TEST_RING_ID, - HNS3_NIC_LB_TEST_RING_ID, - HNS3_NIC_LB_TEST_PKT_NUM); + HNS3_NIC_LB_TEST_RING_ID); kfree_skb(skb); return ret_val; @@ -618,7 +617,7 @@ static void hns3_get_stats(struct net_device *netdev, return; } - h->ae_algo->ops->update_stats(h, &netdev->stats); + h->ae_algo->ops->update_stats(h); /* get per-queue stats */ p = hns3_get_stats_tqps(h, p); diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c index a0b46e7d863ebc665c8176481e959b583e8a3e44..233c132dc513e056a80ff1735bd8e93b1436ea03 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c @@ -88,16 +88,35 @@ static void hclge_dbg_fill_content(char *content, u16 len, const struct hclge_dbg_item *items, const char **result, u16 size) { +#define HCLGE_DBG_LINE_END_LEN 2 char *pos = content; + u16 item_len; u16 i; + if (!len) { + return; + } else if (len <= HCLGE_DBG_LINE_END_LEN) { + *pos++ = '\0'; + return; + } + memset(content, ' ', len); + len -= HCLGE_DBG_LINE_END_LEN; + for (i = 0; i < size; i++) { - if (result) - strncpy(pos, result[i], strlen(result[i])); - else - strncpy(pos, items[i].name, strlen(items[i].name)); - pos += strlen(items[i].name) + items[i].interval; + item_len = strlen(items[i].name) + items[i].interval; + if (len < item_len) + break; + + if (result) { + if (item_len < strlen(result[i])) + break; + strscpy(pos, result[i], strlen(result[i])); + } else { + strscpy(pos, items[i].name, strlen(items[i].name)); + } + pos += item_len; + len -= item_len; } *pos++ = '\n'; *pos++ = '\0'; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 2689b108f7df7b4e94efdeec45135b8b297a15d7..bf675c15fbb9c9093dfc20b6046f268a32f12055 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -689,8 +689,7 @@ static void hclge_update_stats_for_all(struct hclge_dev *hdev) "Update MAC stats fail, status = %d.\n", status); } -static void hclge_update_stats(struct hnae3_handle *handle, - struct net_device_stats *net_stats) +static void hclge_update_stats(struct hnae3_handle *handle) { struct hclge_vport *vport = hclge_get_vport(handle); struct hclge_dev *hdev = vport->back; @@ -824,7 +823,7 @@ static void hclge_get_mac_stat(struct hnae3_handle *handle, struct hclge_vport *vport = hclge_get_vport(handle); struct hclge_dev *hdev = vport->back; - hclge_update_stats(handle, NULL); + hclge_update_stats(handle); mac_stats->tx_pause_cnt = hdev->mac_stats.mac_tx_mac_pause_num; mac_stats->rx_pause_cnt = hdev->mac_stats.mac_rx_mac_pause_num; @@ -4965,9 +4964,7 @@ int hclge_rss_init_hw(struct hclge_dev *hdev) if (ret) return ret; - ret = hclge_comm_set_rss_input_tuple(&hdev->vport[0].nic, - &hdev->hw.hw, true, - &hdev->rss_cfg); + ret = hclge_comm_set_rss_input_tuple(&hdev->hw.hw, &hdev->rss_cfg); if (ret) return ret; @@ -6243,8 +6240,7 @@ static int hclge_fd_check_spec(struct hclge_dev *hdev, return hclge_fd_check_ext_tuple(hdev, fs, unused_tuple); } -static void hclge_fd_get_tcpip4_tuple(struct hclge_dev *hdev, - struct ethtool_rx_flow_spec *fs, +static void hclge_fd_get_tcpip4_tuple(struct ethtool_rx_flow_spec *fs, struct hclge_fd_rule *rule, u8 ip_proto) { rule->tuples.src_ip[IPV4_INDEX] = @@ -6273,8 +6269,7 @@ static void hclge_fd_get_tcpip4_tuple(struct hclge_dev *hdev, rule->tuples_mask.ip_proto = 0xFF; } -static void hclge_fd_get_ip4_tuple(struct hclge_dev *hdev, - struct ethtool_rx_flow_spec *fs, +static void hclge_fd_get_ip4_tuple(struct ethtool_rx_flow_spec *fs, struct hclge_fd_rule *rule) { rule->tuples.src_ip[IPV4_INDEX] = @@ -6297,8 +6292,7 @@ static void hclge_fd_get_ip4_tuple(struct hclge_dev *hdev, rule->tuples_mask.ether_proto = 0xFFFF; } -static void hclge_fd_get_tcpip6_tuple(struct hclge_dev *hdev, - struct ethtool_rx_flow_spec *fs, +static void hclge_fd_get_tcpip6_tuple(struct ethtool_rx_flow_spec *fs, struct hclge_fd_rule *rule, u8 ip_proto) { be32_to_cpu_array(rule->tuples.src_ip, fs->h_u.tcp_ip6_spec.ip6src, @@ -6327,8 +6321,7 @@ static void hclge_fd_get_tcpip6_tuple(struct hclge_dev *hdev, rule->tuples_mask.ip_proto = 0xFF; } -static void hclge_fd_get_ip6_tuple(struct hclge_dev *hdev, - struct ethtool_rx_flow_spec *fs, +static void hclge_fd_get_ip6_tuple(struct ethtool_rx_flow_spec *fs, struct hclge_fd_rule *rule) { be32_to_cpu_array(rule->tuples.src_ip, fs->h_u.usr_ip6_spec.ip6src, @@ -6351,8 +6344,7 @@ static void hclge_fd_get_ip6_tuple(struct hclge_dev *hdev, rule->tuples_mask.ether_proto = 0xFFFF; } -static void hclge_fd_get_ether_tuple(struct hclge_dev *hdev, - struct ethtool_rx_flow_spec *fs, +static void hclge_fd_get_ether_tuple(struct ethtool_rx_flow_spec *fs, struct hclge_fd_rule *rule) { ether_addr_copy(rule->tuples.src_mac, fs->h_u.ether_spec.h_source); @@ -6388,8 +6380,7 @@ static void hclge_fd_get_user_def_tuple(struct hclge_fd_user_def_info *info, rule->ep.user_def = *info; } -static int hclge_fd_get_tuple(struct hclge_dev *hdev, - struct ethtool_rx_flow_spec *fs, +static int hclge_fd_get_tuple(struct ethtool_rx_flow_spec *fs, struct hclge_fd_rule *rule, struct hclge_fd_user_def_info *info) { @@ -6397,31 +6388,31 @@ static int hclge_fd_get_tuple(struct hclge_dev *hdev, switch (flow_type) { case SCTP_V4_FLOW: - hclge_fd_get_tcpip4_tuple(hdev, fs, rule, IPPROTO_SCTP); + hclge_fd_get_tcpip4_tuple(fs, rule, IPPROTO_SCTP); break; case TCP_V4_FLOW: - hclge_fd_get_tcpip4_tuple(hdev, fs, rule, IPPROTO_TCP); + hclge_fd_get_tcpip4_tuple(fs, rule, IPPROTO_TCP); break; case UDP_V4_FLOW: - hclge_fd_get_tcpip4_tuple(hdev, fs, rule, IPPROTO_UDP); + hclge_fd_get_tcpip4_tuple(fs, rule, IPPROTO_UDP); break; case IP_USER_FLOW: - hclge_fd_get_ip4_tuple(hdev, fs, rule); + hclge_fd_get_ip4_tuple(fs, rule); break; case SCTP_V6_FLOW: - hclge_fd_get_tcpip6_tuple(hdev, fs, rule, IPPROTO_SCTP); + hclge_fd_get_tcpip6_tuple(fs, rule, IPPROTO_SCTP); break; case TCP_V6_FLOW: - hclge_fd_get_tcpip6_tuple(hdev, fs, rule, IPPROTO_TCP); + hclge_fd_get_tcpip6_tuple(fs, rule, IPPROTO_TCP); break; case UDP_V6_FLOW: - hclge_fd_get_tcpip6_tuple(hdev, fs, rule, IPPROTO_UDP); + hclge_fd_get_tcpip6_tuple(fs, rule, IPPROTO_UDP); break; case IPV6_USER_FLOW: - hclge_fd_get_ip6_tuple(hdev, fs, rule); + hclge_fd_get_ip6_tuple(fs, rule); break; case ETHER_FLOW: - hclge_fd_get_ether_tuple(hdev, fs, rule); + hclge_fd_get_ether_tuple(fs, rule); break; default: return -EOPNOTSUPP; @@ -6578,7 +6569,7 @@ static int hclge_add_fd_entry(struct hnae3_handle *handle, if (!rule) return -ENOMEM; - ret = hclge_fd_get_tuple(hdev, fs, rule, &info); + ret = hclge_fd_get_tuple(fs, rule, &info); if (ret) { kfree(rule); return ret; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h index 81aa6b0facf5a422a2b197c26b7f8fdda52a5d24..6a43d1515585f23be6396a8c2d0456b9811b1872 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h @@ -835,15 +835,10 @@ struct hclge_vf_vlan_cfg { * Then for input key(k) and mask(v), we can calculate the value by * the formulae: * x = (~k) & v - * y = (k ^ ~v) & k + * y = k & v */ -#define calc_x(x, k, v) (x = ~(k) & (v)) -#define calc_y(y, k, v) \ - do { \ - const typeof(k) _k_ = (k); \ - const typeof(v) _v_ = (v); \ - (y) = (_k_ ^ ~_v_) & (_k_); \ - } while (0) +#define calc_x(x, k, v) ((x) = ~(k) & (v)) +#define calc_y(y, k, v) ((y) = (k) & (v)) #define HCLGE_MAC_STATS_FIELD_OFF(f) (offsetof(struct hclge_mac_stats, f)) #define HCLGE_STATS_READ(p, offset) (*(u64 *)((u8 *)(p) + (offset))) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c index dd08989a4c7c1d122955c8b2839f07b32ff2283d..34f02ca8d1d2d01e50e17222ca2fe26d298639ff 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c @@ -121,8 +121,7 @@ static struct hclgevf_dev *hclgevf_ae_get_hdev(struct hnae3_handle *handle) return container_of(handle, struct hclgevf_dev, nic); } -static void hclgevf_update_stats(struct hnae3_handle *handle, - struct net_device_stats *net_stats) +static void hclgevf_update_stats(struct hnae3_handle *handle) { struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle); int status; @@ -1645,8 +1644,7 @@ static void hclgevf_reset(struct hclgevf_dev *hdev) hclgevf_reset_err_handle(hdev); } -static enum hnae3_reset_type hclgevf_get_reset_level(struct hclgevf_dev *hdev, - unsigned long *addr) +static enum hnae3_reset_type hclgevf_get_reset_level(unsigned long *addr) { enum hnae3_reset_type rst_level = HNAE3_NONE_RESET; @@ -1685,8 +1683,7 @@ static void hclgevf_reset_event(struct pci_dev *pdev, if (hdev->default_reset_request) hdev->reset_level = - hclgevf_get_reset_level(hdev, - &hdev->default_reset_request); + hclgevf_get_reset_level(&hdev->default_reset_request); else hdev->reset_level = HNAE3_VF_FUNC_RESET; @@ -1828,7 +1825,7 @@ static void hclgevf_reset_service_task(struct hclgevf_dev *hdev) hdev->last_reset_time = jiffies; hdev->reset_type = - hclgevf_get_reset_level(hdev, &hdev->reset_pending); + hclgevf_get_reset_level(&hdev->reset_pending); if (hdev->reset_type != HNAE3_NONE_RESET) hclgevf_reset(hdev); } else if (test_and_clear_bit(HCLGEVF_RESET_REQUESTED, @@ -2160,8 +2157,7 @@ static int hclgevf_rss_init_hw(struct hclgevf_dev *hdev) if (ret) return ret; - ret = hclge_comm_set_rss_input_tuple(&hdev->nic, &hdev->hw.hw, - false, rss_cfg); + ret = hclge_comm_set_rss_input_tuple(&hdev->hw.hw, rss_cfg); if (ret) return ret; } diff --git a/drivers/net/ethernet/i825xx/82596.c b/drivers/net/ethernet/i825xx/82596.c index 3ee89ae496d0ca6f16f13527531d02758a5f2164..773d7aa29ef5fc0784d875fe4578120a8238b03d 100644 --- a/drivers/net/ethernet/i825xx/82596.c +++ b/drivers/net/ethernet/i825xx/82596.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-1.0+ /* 82596.c: A generic 82596 ethernet driver for linux. */ /* Based on Apricot.c @@ -31,9 +32,7 @@ Driver skeleton Written 1993 by Donald Becker. Copyright 1993 United States Government as represented by the Director, - National Security Agency. This software may only be used and distributed - according to the terms of the GNU General Public License as modified by SRC, - incorporated herein by reference. + National Security Agency. The author may be reached as becker@scyld.com, or C/O Scyld Computing Corporation, 410 Severn Ave., Suite 210, Annapolis MD 21403 diff --git a/drivers/net/ethernet/i825xx/lasi_82596.c b/drivers/net/ethernet/i825xx/lasi_82596.c index 0af70094aba3414cf4b90ffc4a7ac2f3177e738c..3e53e0c243ba04fcf445488a76b45d3428ba78dc 100644 --- a/drivers/net/ethernet/i825xx/lasi_82596.c +++ b/drivers/net/ethernet/i825xx/lasi_82596.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-1.0+ /* lasi_82596.c -- driver for the intel 82596 ethernet controller, as munged into HPPA boxen . @@ -59,9 +60,7 @@ Driver skeleton Written 1993 by Donald Becker. Copyright 1993 United States Government as represented by the Director, - National Security Agency. This software may only be used and distributed - according to the terms of the GNU General Public License as modified by SRC, - incorporated herein by reference. + National Security Agency. The author may be reached as becker@scyld.com, or C/O Scyld Computing Corporation, 410 Severn Ave., Suite 210, Annapolis MD 21403 diff --git a/drivers/net/ethernet/i825xx/lib82596.c b/drivers/net/ethernet/i825xx/lib82596.c index ca2fb303fcc6f69afab536ba8852ed07f9579a34..67d248a7a6f49e8ed866d3a6e9f3b7dadf32184f 100644 --- a/drivers/net/ethernet/i825xx/lib82596.c +++ b/drivers/net/ethernet/i825xx/lib82596.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-1.0+ /* lasi_82596.c -- driver for the intel 82596 ethernet controller, as munged into HPPA boxen . @@ -59,9 +60,7 @@ Driver skeleton Written 1993 by Donald Becker. Copyright 1993 United States Government as represented by the Director, - National Security Agency. This software may only be used and distributed - according to the terms of the GNU General Public License as modified by SRC, - incorporated herein by reference. + National Security Agency. The author may be reached as becker@scyld.com, or C/O Scyld Computing Corporation, 410 Severn Ave., Suite 210, Annapolis MD 21403 diff --git a/drivers/net/ethernet/i825xx/sun3_82586.c b/drivers/net/ethernet/i825xx/sun3_82586.c index 3909c6a0af89f990062be21409abd2404555ecf6..5e27470c6b1ef32baae89ba8e20a5f3a5d9d5f8c 100644 --- a/drivers/net/ethernet/i825xx/sun3_82586.c +++ b/drivers/net/ethernet/i825xx/sun3_82586.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Sun3 i82586 Ethernet driver * diff --git a/drivers/net/ethernet/i825xx/sun3_82586.h b/drivers/net/ethernet/i825xx/sun3_82586.h index d82eca563266a13df8ab916adb2322d8782d63d3..d8e249d704a76e675500101c5add71033fe80501 100644 --- a/drivers/net/ethernet/i825xx/sun3_82586.h +++ b/drivers/net/ethernet/i825xx/sun3_82586.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ /* * Intel i82586 Ethernet definitions * diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c index c63d3ec9d32847f049b41c82b4ac02544463e95d..763d613adbcc0ecbcd5bc6a183f89b9671d3a2d8 100644 --- a/drivers/net/ethernet/ibm/ibmvnic.c +++ b/drivers/net/ethernet/ibm/ibmvnic.c @@ -1816,7 +1816,14 @@ static int __ibmvnic_open(struct net_device *netdev) if (prev_state == VNIC_CLOSED) enable_irq(adapter->tx_scrq[i]->irq); enable_scrq_irq(adapter, adapter->tx_scrq[i]); - netdev_tx_reset_queue(netdev_get_tx_queue(netdev, i)); + /* netdev_tx_reset_queue will reset dql stats. During NON_FATAL + * resets, don't reset the stats because there could be batched + * skb's waiting to be sent. If we reset dql stats, we risk + * num_completed being greater than num_queued. This will cause + * a BUG_ON in dql_completed(). + */ + if (adapter->reset_reason != VNIC_RESET_NON_FATAL) + netdev_tx_reset_queue(netdev_get_tx_queue(netdev, i)); } rc = set_link_state(adapter, IBMVNIC_LOGICAL_LNK_UP); diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c index bd7ef59b1f2e74ecb66f6ac0290d9c6b3a2a290a..771a3c909c459e573e12cd58eaa6eb6fd91ffd21 100644 --- a/drivers/net/ethernet/intel/e1000e/netdev.c +++ b/drivers/net/ethernet/intel/e1000e/netdev.c @@ -4198,7 +4198,7 @@ void e1000e_reset(struct e1000_adapter *adapter) /** * e1000e_trigger_lsc - trigger an LSC interrupt - * @adapter: + * @adapter: board private structure * * Fire a link status change interrupt to start the watchdog. **/ diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index b847bd105b16e7260383245375b3015cc2633492..29ad1797adcea167c4c9eaf7f3c2ce6cc0f9bd48 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -1788,12 +1788,6 @@ static int i40e_set_mac(struct net_device *netdev, void *p) if (!is_valid_ether_addr(addr->sa_data)) return -EADDRNOTAVAIL; - if (ether_addr_equal(netdev->dev_addr, addr->sa_data)) { - netdev_info(netdev, "already using mac address %pM\n", - addr->sa_data); - return 0; - } - if (test_bit(__I40E_DOWN, pf->state) || test_bit(__I40E_RESET_RECOVERY_PENDING, pf->state)) return -EADDRNOTAVAIL; diff --git a/drivers/net/ethernet/intel/i40e/i40e_xsk.c b/drivers/net/ethernet/intel/i40e/i40e_xsk.c index cd7b52fb6b46c3f29b8df9870d3785960fc192f0..05ec1181471ea390ab5d659df352729628c4d13e 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_xsk.c +++ b/drivers/net/ethernet/intel/i40e/i40e_xsk.c @@ -582,7 +582,7 @@ static void i40e_clean_xdp_tx_buffer(struct i40e_ring *tx_ring, * @vsi: Current VSI * @tx_ring: XDP Tx ring * - * Returns true if cleanup/tranmission is done. + * Returns true if cleanup/transmission is done. **/ bool i40e_clean_xdp_tx_irq(struct i40e_vsi *vsi, struct i40e_ring *tx_ring) { diff --git a/drivers/net/ethernet/intel/iavf/iavf.h b/drivers/net/ethernet/intel/iavf/iavf.h index 39d0fe76a38ff80e7ce895a48473d0f676dc6a35..f80f2735e6886fb8dc3df1dadcf27defe0a8b3c9 100644 --- a/drivers/net/ethernet/intel/iavf/iavf.h +++ b/drivers/net/ethernet/intel/iavf/iavf.h @@ -523,9 +523,6 @@ void iavf_schedule_request_stats(struct iavf_adapter *adapter); void iavf_reset(struct iavf_adapter *adapter); void iavf_set_ethtool_ops(struct net_device *netdev); void iavf_update_stats(struct iavf_adapter *adapter); -void iavf_reset_interrupt_capability(struct iavf_adapter *adapter); -int iavf_init_interrupt_scheme(struct iavf_adapter *adapter); -void iavf_irq_enable_queues(struct iavf_adapter *adapter); void iavf_free_all_tx_resources(struct iavf_adapter *adapter); void iavf_free_all_rx_resources(struct iavf_adapter *adapter); @@ -579,17 +576,10 @@ void iavf_enable_vlan_stripping_v2(struct iavf_adapter *adapter, u16 tpid); void iavf_disable_vlan_stripping_v2(struct iavf_adapter *adapter, u16 tpid); void iavf_enable_vlan_insertion_v2(struct iavf_adapter *adapter, u16 tpid); void iavf_disable_vlan_insertion_v2(struct iavf_adapter *adapter, u16 tpid); -int iavf_replace_primary_mac(struct iavf_adapter *adapter, - const u8 *new_mac); -void -iavf_set_vlan_offload_features(struct iavf_adapter *adapter, - netdev_features_t prev_features, - netdev_features_t features); void iavf_add_fdir_filter(struct iavf_adapter *adapter); void iavf_del_fdir_filter(struct iavf_adapter *adapter); void iavf_add_adv_rss_cfg(struct iavf_adapter *adapter); void iavf_del_adv_rss_cfg(struct iavf_adapter *adapter); struct iavf_mac_filter *iavf_add_filter(struct iavf_adapter *adapter, const u8 *macaddr); -int iavf_lock_timeout(struct mutex *lock, unsigned int msecs); #endif /* _IAVF_H_ */ diff --git a/drivers/net/ethernet/intel/iavf/iavf_alloc.h b/drivers/net/ethernet/intel/iavf/iavf_alloc.h index 2711573c14ecdc0a52b6efc02ac6dc0ecc9a1072..162ea70685a63ef50a69c39927c172199980a189 100644 --- a/drivers/net/ethernet/intel/iavf/iavf_alloc.h +++ b/drivers/net/ethernet/intel/iavf/iavf_alloc.h @@ -28,7 +28,6 @@ enum iavf_status iavf_free_dma_mem(struct iavf_hw *hw, struct iavf_dma_mem *mem); enum iavf_status iavf_allocate_virt_mem(struct iavf_hw *hw, struct iavf_virt_mem *mem, u32 size); -enum iavf_status iavf_free_virt_mem(struct iavf_hw *hw, - struct iavf_virt_mem *mem); +void iavf_free_virt_mem(struct iavf_hw *hw, struct iavf_virt_mem *mem); #endif /* _IAVF_ALLOC_H_ */ diff --git a/drivers/net/ethernet/intel/iavf/iavf_common.c b/drivers/net/ethernet/intel/iavf/iavf_common.c index dd11dbbd5551a2c1d9f8a431d972655d9cabe79c..1afd761d8052080942ce796e560fa7478bbf3a1b 100644 --- a/drivers/net/ethernet/intel/iavf/iavf_common.c +++ b/drivers/net/ethernet/intel/iavf/iavf_common.c @@ -35,7 +35,6 @@ enum iavf_status iavf_set_mac_type(struct iavf_hw *hw) status = IAVF_ERR_DEVICE_NOT_SUPPORTED; } - hw_dbg(hw, "found mac: %d, returns: %d\n", hw->mac.type, status); return status; } @@ -397,23 +396,6 @@ static enum iavf_status iavf_aq_get_set_rss_lut(struct iavf_hw *hw, return status; } -/** - * iavf_aq_get_rss_lut - * @hw: pointer to the hardware structure - * @vsi_id: vsi fw index - * @pf_lut: for PF table set true, for VSI table set false - * @lut: pointer to the lut buffer provided by the caller - * @lut_size: size of the lut buffer - * - * get the RSS lookup table, PF or VSI type - **/ -enum iavf_status iavf_aq_get_rss_lut(struct iavf_hw *hw, u16 vsi_id, - bool pf_lut, u8 *lut, u16 lut_size) -{ - return iavf_aq_get_set_rss_lut(hw, vsi_id, pf_lut, lut, lut_size, - false); -} - /** * iavf_aq_set_rss_lut * @hw: pointer to the hardware structure @@ -472,19 +454,6 @@ iavf_status iavf_aq_get_set_rss_key(struct iavf_hw *hw, u16 vsi_id, return status; } -/** - * iavf_aq_get_rss_key - * @hw: pointer to the hw struct - * @vsi_id: vsi fw index - * @key: pointer to key info struct - * - **/ -enum iavf_status iavf_aq_get_rss_key(struct iavf_hw *hw, u16 vsi_id, - struct iavf_aqc_get_set_rss_key_data *key) -{ - return iavf_aq_get_set_rss_key(hw, vsi_id, key, false); -} - /** * iavf_aq_set_rss_key * @hw: pointer to the hw struct @@ -828,17 +797,3 @@ void iavf_vf_parse_hw_config(struct iavf_hw *hw, vsi_res++; } } - -/** - * iavf_vf_reset - * @hw: pointer to the hardware structure - * - * Send a VF_RESET message to the PF. Does not wait for response from PF - * as none will be forthcoming. Immediately after calling this function, - * the admin queue should be shut down and (optionally) reinitialized. - **/ -enum iavf_status iavf_vf_reset(struct iavf_hw *hw) -{ - return iavf_aq_send_msg_to_pf(hw, VIRTCHNL_OP_RESET_VF, - 0, NULL, 0, NULL); -} diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c b/drivers/net/ethernet/intel/iavf/iavf_main.c index 4a66873882d12a70b6d79eedd40684d3f5a77b11..a483eb185c99cb4ff7a394b91ef695190a285504 100644 --- a/drivers/net/ethernet/intel/iavf/iavf_main.c +++ b/drivers/net/ethernet/intel/iavf/iavf_main.c @@ -192,12 +192,11 @@ enum iavf_status iavf_allocate_dma_mem_d(struct iavf_hw *hw, } /** - * iavf_free_dma_mem_d - OS specific memory free for shared code + * iavf_free_dma_mem - wrapper for DMA memory freeing * @hw: pointer to the HW structure * @mem: ptr to mem struct to free **/ -enum iavf_status iavf_free_dma_mem_d(struct iavf_hw *hw, - struct iavf_dma_mem *mem) +enum iavf_status iavf_free_dma_mem(struct iavf_hw *hw, struct iavf_dma_mem *mem) { struct iavf_adapter *adapter = (struct iavf_adapter *)hw->back; @@ -209,13 +208,13 @@ enum iavf_status iavf_free_dma_mem_d(struct iavf_hw *hw, } /** - * iavf_allocate_virt_mem_d - OS specific memory alloc for shared code + * iavf_allocate_virt_mem - virt memory alloc wrapper * @hw: pointer to the HW structure * @mem: ptr to mem struct to fill out * @size: size of memory requested **/ -enum iavf_status iavf_allocate_virt_mem_d(struct iavf_hw *hw, - struct iavf_virt_mem *mem, u32 size) +enum iavf_status iavf_allocate_virt_mem(struct iavf_hw *hw, + struct iavf_virt_mem *mem, u32 size) { if (!mem) return IAVF_ERR_PARAM; @@ -230,20 +229,13 @@ enum iavf_status iavf_allocate_virt_mem_d(struct iavf_hw *hw, } /** - * iavf_free_virt_mem_d - OS specific memory free for shared code + * iavf_free_virt_mem - virt memory free wrapper * @hw: pointer to the HW structure * @mem: ptr to mem struct to free **/ -enum iavf_status iavf_free_virt_mem_d(struct iavf_hw *hw, - struct iavf_virt_mem *mem) +void iavf_free_virt_mem(struct iavf_hw *hw, struct iavf_virt_mem *mem) { - if (!mem) - return IAVF_ERR_PARAM; - - /* it's ok to kfree a NULL pointer */ kfree(mem->va); - - return 0; } /** @@ -253,7 +245,7 @@ enum iavf_status iavf_free_virt_mem_d(struct iavf_hw *hw, * * Returns 0 on success, negative on failure **/ -int iavf_lock_timeout(struct mutex *lock, unsigned int msecs) +static int iavf_lock_timeout(struct mutex *lock, unsigned int msecs) { unsigned int wait, delay = 10; @@ -362,7 +354,7 @@ static void iavf_irq_disable(struct iavf_adapter *adapter) * iavf_irq_enable_queues - Enable interrupt for all queues * @adapter: board private structure **/ -void iavf_irq_enable_queues(struct iavf_adapter *adapter) +static void iavf_irq_enable_queues(struct iavf_adapter *adapter) { struct iavf_hw *hw = &adapter->hw; int i; @@ -1003,44 +995,40 @@ struct iavf_mac_filter *iavf_add_filter(struct iavf_adapter *adapter, * * Do not call this with mac_vlan_list_lock! **/ -int iavf_replace_primary_mac(struct iavf_adapter *adapter, - const u8 *new_mac) +static int iavf_replace_primary_mac(struct iavf_adapter *adapter, + const u8 *new_mac) { struct iavf_hw *hw = &adapter->hw; - struct iavf_mac_filter *f; + struct iavf_mac_filter *new_f; + struct iavf_mac_filter *old_f; spin_lock_bh(&adapter->mac_vlan_list_lock); - list_for_each_entry(f, &adapter->mac_filter_list, list) { - f->is_primary = false; + new_f = iavf_add_filter(adapter, new_mac); + if (!new_f) { + spin_unlock_bh(&adapter->mac_vlan_list_lock); + return -ENOMEM; } - f = iavf_find_filter(adapter, hw->mac.addr); - if (f) { - f->remove = true; + old_f = iavf_find_filter(adapter, hw->mac.addr); + if (old_f) { + old_f->is_primary = false; + old_f->remove = true; adapter->aq_required |= IAVF_FLAG_AQ_DEL_MAC_FILTER; } - - f = iavf_add_filter(adapter, new_mac); - - if (f) { - /* Always send the request to add if changing primary MAC - * even if filter is already present on the list - */ - f->is_primary = true; - f->add = true; - adapter->aq_required |= IAVF_FLAG_AQ_ADD_MAC_FILTER; - ether_addr_copy(hw->mac.addr, new_mac); - } + /* Always send the request to add if changing primary MAC, + * even if filter is already present on the list + */ + new_f->is_primary = true; + new_f->add = true; + adapter->aq_required |= IAVF_FLAG_AQ_ADD_MAC_FILTER; + ether_addr_copy(hw->mac.addr, new_mac); spin_unlock_bh(&adapter->mac_vlan_list_lock); /* schedule the watchdog task to immediately process the request */ - if (f) { - mod_delayed_work(adapter->wq, &adapter->watchdog_task, 0); - return 0; - } - return -ENOMEM; + mod_delayed_work(adapter->wq, &adapter->watchdog_task, 0); + return 0; } /** @@ -1863,7 +1851,7 @@ static void iavf_free_q_vectors(struct iavf_adapter *adapter) * @adapter: board private structure * **/ -void iavf_reset_interrupt_capability(struct iavf_adapter *adapter) +static void iavf_reset_interrupt_capability(struct iavf_adapter *adapter) { if (!adapter->msix_entries) return; @@ -1878,7 +1866,7 @@ void iavf_reset_interrupt_capability(struct iavf_adapter *adapter) * @adapter: board private structure to initialize * **/ -int iavf_init_interrupt_scheme(struct iavf_adapter *adapter) +static int iavf_init_interrupt_scheme(struct iavf_adapter *adapter) { int err; @@ -2176,7 +2164,7 @@ static int iavf_process_aq_command(struct iavf_adapter *adapter) * the watchdog if any changes are requested to expedite the request via * virtchnl. **/ -void +static void iavf_set_vlan_offload_features(struct iavf_adapter *adapter, netdev_features_t prev_features, netdev_features_t features) diff --git a/drivers/net/ethernet/intel/iavf/iavf_osdep.h b/drivers/net/ethernet/intel/iavf/iavf_osdep.h index a452ce90679a9dc625942bf8033664e9829f67cd..77d33deaabb55695ed7081a3d24db7243eba0785 100644 --- a/drivers/net/ethernet/intel/iavf/iavf_osdep.h +++ b/drivers/net/ethernet/intel/iavf/iavf_osdep.h @@ -13,12 +13,6 @@ /* get readq/writeq support for 32 bit kernels, use the low-first version */ #include -/* File to be the magic between shared code and - * actual OS primitives - */ - -#define hw_dbg(hw, S, A...) do {} while (0) - #define wr32(a, reg, value) writel((value), ((a)->hw_addr + (reg))) #define rd32(a, reg) readl((a)->hw_addr + (reg)) @@ -35,14 +29,11 @@ struct iavf_dma_mem { #define iavf_allocate_dma_mem(h, m, unused, s, a) \ iavf_allocate_dma_mem_d(h, m, s, a) -#define iavf_free_dma_mem(h, m) iavf_free_dma_mem_d(h, m) struct iavf_virt_mem { void *va; u32 size; }; -#define iavf_allocate_virt_mem(h, m, s) iavf_allocate_virt_mem_d(h, m, s) -#define iavf_free_virt_mem(h, m) iavf_free_virt_mem_d(h, m) #define iavf_debug(h, m, s, ...) \ do { \ diff --git a/drivers/net/ethernet/intel/iavf/iavf_prototype.h b/drivers/net/ethernet/intel/iavf/iavf_prototype.h index edebfbbcffdc2e390b846332ebf257da9e1bb2a4..940cb4203fbe8370929e12b9b8540a776190f960 100644 --- a/drivers/net/ethernet/intel/iavf/iavf_prototype.h +++ b/drivers/net/ethernet/intel/iavf/iavf_prototype.h @@ -40,12 +40,8 @@ enum iavf_status iavf_aq_queue_shutdown(struct iavf_hw *hw, bool unloading); const char *iavf_aq_str(struct iavf_hw *hw, enum iavf_admin_queue_err aq_err); const char *iavf_stat_str(struct iavf_hw *hw, enum iavf_status stat_err); -enum iavf_status iavf_aq_get_rss_lut(struct iavf_hw *hw, u16 seid, - bool pf_lut, u8 *lut, u16 lut_size); enum iavf_status iavf_aq_set_rss_lut(struct iavf_hw *hw, u16 seid, bool pf_lut, u8 *lut, u16 lut_size); -enum iavf_status iavf_aq_get_rss_key(struct iavf_hw *hw, u16 seid, - struct iavf_aqc_get_set_rss_key_data *key); enum iavf_status iavf_aq_set_rss_key(struct iavf_hw *hw, u16 seid, struct iavf_aqc_get_set_rss_key_data *key); @@ -60,7 +56,6 @@ static inline struct iavf_rx_ptype_decoded decode_rx_desc_ptype(u8 ptype) void iavf_vf_parse_hw_config(struct iavf_hw *hw, struct virtchnl_vf_resource *msg); -enum iavf_status iavf_vf_reset(struct iavf_hw *hw); enum iavf_status iavf_aq_send_msg_to_pf(struct iavf_hw *hw, enum virtchnl_ops v_opcode, enum iavf_status v_retval, diff --git a/drivers/net/ethernet/intel/iavf/iavf_txrx.c b/drivers/net/ethernet/intel/iavf/iavf_txrx.c index e989feda133c1e63447f005437f09ba248084fdb..8c5f6096b0022c32953a93429df857edf33c765a 100644 --- a/drivers/net/ethernet/intel/iavf/iavf_txrx.c +++ b/drivers/net/ethernet/intel/iavf/iavf_txrx.c @@ -54,7 +54,7 @@ static void iavf_unmap_and_free_tx_resource(struct iavf_ring *ring, * iavf_clean_tx_ring - Free any empty Tx buffers * @tx_ring: ring to be cleaned **/ -void iavf_clean_tx_ring(struct iavf_ring *tx_ring) +static void iavf_clean_tx_ring(struct iavf_ring *tx_ring) { unsigned long bi_size; u16 i; @@ -110,7 +110,7 @@ void iavf_free_tx_resources(struct iavf_ring *tx_ring) * Since there is no access to the ring head register * in XL710, we need to use our local copies **/ -u32 iavf_get_tx_pending(struct iavf_ring *ring, bool in_sw) +static u32 iavf_get_tx_pending(struct iavf_ring *ring, bool in_sw) { u32 head, tail; @@ -127,6 +127,24 @@ u32 iavf_get_tx_pending(struct iavf_ring *ring, bool in_sw) return 0; } +/** + * iavf_force_wb - Issue SW Interrupt so HW does a wb + * @vsi: the VSI we care about + * @q_vector: the vector on which to force writeback + **/ +static void iavf_force_wb(struct iavf_vsi *vsi, struct iavf_q_vector *q_vector) +{ + u32 val = IAVF_VFINT_DYN_CTLN1_INTENA_MASK | + IAVF_VFINT_DYN_CTLN1_ITR_INDX_MASK | /* set noitr */ + IAVF_VFINT_DYN_CTLN1_SWINT_TRIG_MASK | + IAVF_VFINT_DYN_CTLN1_SW_ITR_INDX_ENA_MASK + /* allow 00 to be written to the index */; + + wr32(&vsi->back->hw, + IAVF_VFINT_DYN_CTLN1(q_vector->reg_idx), + val); +} + /** * iavf_detect_recover_hung - Function to detect and recover hung_queues * @vsi: pointer to vsi struct with tx queues @@ -352,25 +370,6 @@ static void iavf_enable_wb_on_itr(struct iavf_vsi *vsi, q_vector->arm_wb_state = true; } -/** - * iavf_force_wb - Issue SW Interrupt so HW does a wb - * @vsi: the VSI we care about - * @q_vector: the vector on which to force writeback - * - **/ -void iavf_force_wb(struct iavf_vsi *vsi, struct iavf_q_vector *q_vector) -{ - u32 val = IAVF_VFINT_DYN_CTLN1_INTENA_MASK | - IAVF_VFINT_DYN_CTLN1_ITR_INDX_MASK | /* set noitr */ - IAVF_VFINT_DYN_CTLN1_SWINT_TRIG_MASK | - IAVF_VFINT_DYN_CTLN1_SW_ITR_INDX_ENA_MASK - /* allow 00 to be written to the index */; - - wr32(&vsi->back->hw, - IAVF_VFINT_DYN_CTLN1(q_vector->reg_idx), - val); -} - static inline bool iavf_container_is_rx(struct iavf_q_vector *q_vector, struct iavf_ring_container *rc) { @@ -687,7 +686,7 @@ int iavf_setup_tx_descriptors(struct iavf_ring *tx_ring) * iavf_clean_rx_ring - Free Rx buffers * @rx_ring: ring to be cleaned **/ -void iavf_clean_rx_ring(struct iavf_ring *rx_ring) +static void iavf_clean_rx_ring(struct iavf_ring *rx_ring) { unsigned long bi_size; u16 i; diff --git a/drivers/net/ethernet/intel/iavf/iavf_txrx.h b/drivers/net/ethernet/intel/iavf/iavf_txrx.h index 2624bf6d009e362de2b31c8858d07a89313879c8..7e6ee32d19b696dcd04cbbbc7e72526ad9adf1f0 100644 --- a/drivers/net/ethernet/intel/iavf/iavf_txrx.h +++ b/drivers/net/ethernet/intel/iavf/iavf_txrx.h @@ -442,15 +442,11 @@ static inline unsigned int iavf_rx_pg_order(struct iavf_ring *ring) bool iavf_alloc_rx_buffers(struct iavf_ring *rxr, u16 cleaned_count); netdev_tx_t iavf_xmit_frame(struct sk_buff *skb, struct net_device *netdev); -void iavf_clean_tx_ring(struct iavf_ring *tx_ring); -void iavf_clean_rx_ring(struct iavf_ring *rx_ring); int iavf_setup_tx_descriptors(struct iavf_ring *tx_ring); int iavf_setup_rx_descriptors(struct iavf_ring *rx_ring); void iavf_free_tx_resources(struct iavf_ring *tx_ring); void iavf_free_rx_resources(struct iavf_ring *rx_ring); int iavf_napi_poll(struct napi_struct *napi, int budget); -void iavf_force_wb(struct iavf_vsi *vsi, struct iavf_q_vector *q_vector); -u32 iavf_get_tx_pending(struct iavf_ring *ring, bool in_sw); void iavf_detect_recover_hung(struct iavf_vsi *vsi); int __iavf_maybe_stop_tx(struct iavf_ring *tx_ring, int size); bool __iavf_chk_linearize(struct sk_buff *skb); diff --git a/drivers/net/ethernet/intel/ice/Makefile b/drivers/net/ethernet/intel/ice/Makefile index 5d89392f969bfe5df947e95c671c1dce3e3ae5fe..817977e3039d54540b702295de3d7554cfb95969 100644 --- a/drivers/net/ethernet/intel/ice/Makefile +++ b/drivers/net/ethernet/intel/ice/Makefile @@ -18,6 +18,7 @@ ice-y := ice_main.o \ ice_txrx_lib.o \ ice_txrx.o \ ice_fltr.o \ + ice_irq.o \ ice_pf_vsi_vlan_ops.o \ ice_vsi_vlan_ops.o \ ice_vsi_vlan_lib.o \ diff --git a/drivers/net/ethernet/intel/ice/ice.h b/drivers/net/ethernet/intel/ice/ice.h index aa32111afd6edcf88778879c164af4e0c45c8287..4ba3d99439a0ab56e4afa1fd35430247b5fb3892 100644 --- a/drivers/net/ethernet/intel/ice/ice.h +++ b/drivers/net/ethernet/intel/ice/ice.h @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -74,6 +75,7 @@ #include "ice_lag.h" #include "ice_vsi_vlan_ops.h" #include "ice_gnss.h" +#include "ice_irq.h" #define ICE_BAR0 0 #define ICE_REQ_DESC_MULTIPLE 32 @@ -103,11 +105,6 @@ #define ICE_Q_WAIT_RETRY_LIMIT 10 #define ICE_Q_WAIT_MAX_RETRY (5 * ICE_Q_WAIT_RETRY_LIMIT) #define ICE_MAX_LG_RSS_QS 256 -#define ICE_RES_VALID_BIT 0x8000 -#define ICE_RES_MISC_VEC_ID (ICE_RES_VALID_BIT - 1) -#define ICE_RES_RDMA_VEC_ID (ICE_RES_MISC_VEC_ID - 1) -/* All VF control VSIs share the same IRQ, so assign a unique ID for them */ -#define ICE_RES_VF_CTRL_VEC_ID (ICE_RES_RDMA_VEC_ID - 1) #define ICE_INVAL_Q_INDEX 0xffff #define ICE_MAX_RXQS_PER_TC 256 /* Used when setting VSI context per TC Rx queues */ @@ -245,12 +242,6 @@ struct ice_tc_cfg { struct ice_tc_info tc_info[ICE_MAX_TRAFFIC_CLASS]; }; -struct ice_res_tracker { - u16 num_entries; - u16 end; - u16 list[]; -}; - struct ice_qs_cfg { struct mutex *qs_mutex; /* will be assigned to &pf->avail_q_mutex */ unsigned long *pf_map; @@ -348,7 +339,9 @@ struct ice_vsi { u32 rx_buf_failed; u32 rx_page_failed; u16 num_q_vectors; - u16 base_vector; /* IRQ base for OS reserved vectors */ + /* tell if only dynamic irq allocation is allowed */ + bool irq_dyn_alloc; + enum ice_vsi_type type; u16 vsi_num; /* HW (absolute) index of this VSI */ u16 idx; /* software index in pf->vsi[] */ @@ -479,6 +472,7 @@ struct ice_q_vector { char name[ICE_INT_NAME_STR_LEN]; u16 total_events; /* net_dim(): number of interrupts processed */ + struct msi_map irq; } ____cacheline_internodealigned_in_smp; enum ice_pf_flags { @@ -514,6 +508,12 @@ enum ice_pf_flags { ICE_PF_FLAGS_NBITS /* must be last */ }; +enum ice_misc_thread_tasks { + ICE_MISC_THREAD_EXTTS_EVENT, + ICE_MISC_THREAD_TX_TSTAMP, + ICE_MISC_THREAD_NBITS /* must be last */ +}; + struct ice_switchdev_info { struct ice_vsi *control_vsi; struct ice_vsi *uplink_vsi; @@ -539,7 +539,7 @@ struct ice_pf { /* OS reserved IRQ details */ struct msix_entry *msix_entries; - struct ice_res_tracker *irq_tracker; + struct ice_irq_tracker irq_tracker; /* First MSIX vector used by SR-IOV VFs. Calculated by subtracting the * number of MSIX vectors needed for all SR-IOV VFs from the number of * MSIX vectors allowed on this PF. @@ -556,6 +556,7 @@ struct ice_pf { DECLARE_BITMAP(features, ICE_F_MAX); DECLARE_BITMAP(state, ICE_STATE_NBITS); DECLARE_BITMAP(flags, ICE_PF_FLAGS_NBITS); + DECLARE_BITMAP(misc_thread, ICE_MISC_THREAD_NBITS); unsigned long *avail_txqs; /* bitmap to track PF Tx queue usage */ unsigned long *avail_rxqs; /* bitmap to track PF Rx queue usage */ unsigned long serv_tmr_period; @@ -583,8 +584,7 @@ struct ice_pf { u32 hw_csum_rx_error; u32 oicr_err_reg; - u16 oicr_idx; /* Other interrupt cause MSIX vector index */ - u16 num_avail_sw_msix; /* remaining MSIX SW vectors left unclaimed */ + struct msi_map oicr_irq; /* Other interrupt cause MSIX vector */ u16 max_pf_txqs; /* Total Tx queues PF wide */ u16 max_pf_rxqs; /* Total Rx queues PF wide */ u16 num_lan_msix; /* Total MSIX vectors for base driver */ @@ -670,7 +670,7 @@ ice_irq_dynamic_ena(struct ice_hw *hw, struct ice_vsi *vsi, struct ice_q_vector *q_vector) { u32 vector = (vsi && q_vector) ? q_vector->reg_idx : - ((struct ice_pf *)hw->back)->oicr_idx; + ((struct ice_pf *)hw->back)->oicr_irq.index; int itr = ICE_ITR_NONE; u32 val; @@ -821,25 +821,6 @@ static inline bool ice_is_switchdev_running(struct ice_pf *pf) return pf->switchdev.is_running; } -/** - * ice_set_sriov_cap - enable SRIOV in PF flags - * @pf: PF struct - */ -static inline void ice_set_sriov_cap(struct ice_pf *pf) -{ - if (pf->hw.func_caps.common_cap.sr_iov_1_1) - set_bit(ICE_FLAG_SRIOV_CAPABLE, pf->flags); -} - -/** - * ice_clear_sriov_cap - disable SRIOV in PF flags - * @pf: PF struct - */ -static inline void ice_clear_sriov_cap(struct ice_pf *pf) -{ - clear_bit(ICE_FLAG_SRIOV_CAPABLE, pf->flags); -} - #define ICE_FD_STAT_CTR_BLOCK_COUNT 256 #define ICE_FD_STAT_PF_IDX(base_idx) \ ((base_idx) * ICE_FD_STAT_CTR_BLOCK_COUNT) diff --git a/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h index 838d9b274d6854f0df659b36010e55604a5602ea..63d3e1dcbba55ef05239f1bba2d6c0340c94b12f 100644 --- a/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h +++ b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h @@ -1087,7 +1087,7 @@ struct ice_aqc_get_phy_caps { #define ICE_PHY_TYPE_HIGH_100G_CAUI2 BIT_ULL(2) #define ICE_PHY_TYPE_HIGH_100G_AUI2_AOC_ACC BIT_ULL(3) #define ICE_PHY_TYPE_HIGH_100G_AUI2 BIT_ULL(4) -#define ICE_PHY_TYPE_HIGH_MAX_INDEX 5 +#define ICE_PHY_TYPE_HIGH_MAX_INDEX 4 struct ice_aqc_get_phy_caps_data { __le64 phy_type_low; /* Use values from ICE_PHY_TYPE_LOW_* */ diff --git a/drivers/net/ethernet/intel/ice/ice_arfs.c b/drivers/net/ethernet/intel/ice/ice_arfs.c index fba178e0760097f70acbcb5288a9d6be38fe4e7d..cca0e753f38ff92be24f8e8fc8963e2bf2416cfa 100644 --- a/drivers/net/ethernet/intel/ice/ice_arfs.c +++ b/drivers/net/ethernet/intel/ice/ice_arfs.c @@ -596,7 +596,7 @@ int ice_set_cpu_rx_rmap(struct ice_vsi *vsi) { struct net_device *netdev; struct ice_pf *pf; - int base_idx, i; + int i; if (!vsi || vsi->type != ICE_VSI_PF) return 0; @@ -613,10 +613,9 @@ int ice_set_cpu_rx_rmap(struct ice_vsi *vsi) if (unlikely(!netdev->rx_cpu_rmap)) return -EINVAL; - base_idx = vsi->base_vector; ice_for_each_q_vector(vsi, i) if (irq_cpu_rmap_add(netdev->rx_cpu_rmap, - pf->msix_entries[base_idx + i].vector)) { + vsi->q_vectors[i]->irq.virq)) { ice_free_cpu_rx_rmap(vsi); return -EINVAL; } diff --git a/drivers/net/ethernet/intel/ice/ice_base.c b/drivers/net/ethernet/intel/ice/ice_base.c index 1911d644dfa8ddd77c41cd1268ad6d0dbe9f3143..4a12316f7b464aaddaae4407136e93c4a6356539 100644 --- a/drivers/net/ethernet/intel/ice/ice_base.c +++ b/drivers/net/ethernet/intel/ice/ice_base.c @@ -103,10 +103,10 @@ static int ice_vsi_alloc_q_vector(struct ice_vsi *vsi, u16 v_idx) { struct ice_pf *pf = vsi->back; struct ice_q_vector *q_vector; + int err; /* allocate q_vector */ - q_vector = devm_kzalloc(ice_pf_to_dev(pf), sizeof(*q_vector), - GFP_KERNEL); + q_vector = kzalloc(sizeof(*q_vector), GFP_KERNEL); if (!q_vector) return -ENOMEM; @@ -118,9 +118,34 @@ static int ice_vsi_alloc_q_vector(struct ice_vsi *vsi, u16 v_idx) q_vector->rx.itr_mode = ITR_DYNAMIC; q_vector->tx.type = ICE_TX_CONTAINER; q_vector->rx.type = ICE_RX_CONTAINER; + q_vector->irq.index = -ENOENT; - if (vsi->type == ICE_VSI_VF) + if (vsi->type == ICE_VSI_VF) { + q_vector->reg_idx = ice_calc_vf_reg_idx(vsi->vf, q_vector); goto out; + } else if (vsi->type == ICE_VSI_CTRL && vsi->vf) { + struct ice_vsi *ctrl_vsi = ice_get_vf_ctrl_vsi(pf, vsi); + + if (ctrl_vsi) { + if (unlikely(!ctrl_vsi->q_vectors)) { + err = -ENOENT; + goto err_free_q_vector; + } + + q_vector->irq = ctrl_vsi->q_vectors[0]->irq; + goto skip_alloc; + } + } + + q_vector->irq = ice_alloc_irq(pf, vsi->irq_dyn_alloc); + if (q_vector->irq.index < 0) { + err = -ENOMEM; + goto err_free_q_vector; + } + +skip_alloc: + q_vector->reg_idx = q_vector->irq.index; + /* only set affinity_mask if the CPU is online */ if (cpu_online(v_idx)) cpumask_set_cpu(v_idx, &q_vector->affinity_mask); @@ -137,6 +162,11 @@ static int ice_vsi_alloc_q_vector(struct ice_vsi *vsi, u16 v_idx) vsi->q_vectors[v_idx] = q_vector; return 0; + +err_free_q_vector: + kfree(q_vector); + + return err; } /** @@ -168,7 +198,19 @@ static void ice_free_q_vector(struct ice_vsi *vsi, int v_idx) if (vsi->netdev) netif_napi_del(&q_vector->napi); - devm_kfree(dev, q_vector); + /* release MSIX interrupt if q_vector had interrupt allocated */ + if (q_vector->irq.index < 0) + goto free_q_vector; + + /* only free last VF ctrl vsi interrupt */ + if (vsi->type == ICE_VSI_CTRL && vsi->vf && + ice_get_vf_ctrl_vsi(pf, vsi)) + goto free_q_vector; + + ice_free_irq(pf, q_vector->irq); + +free_q_vector: + kfree(q_vector); vsi->q_vectors[v_idx] = NULL; } diff --git a/drivers/net/ethernet/intel/ice/ice_common.c b/drivers/net/ethernet/intel/ice/ice_common.c index eb2dc09837769ce33a7d5d1efdfae4a23fcf7a0c..e16d4c83ed5f9fdad7fdc20b193a9ca2d732b0da 100644 --- a/drivers/net/ethernet/intel/ice/ice_common.c +++ b/drivers/net/ethernet/intel/ice/ice_common.c @@ -814,8 +814,7 @@ static void ice_cleanup_fltr_mgmt_struct(struct ice_hw *hw) devm_kfree(ice_hw_to_dev(hw), lst_itr); } } - if (recps[i].root_buf) - devm_kfree(ice_hw_to_dev(hw), recps[i].root_buf); + devm_kfree(ice_hw_to_dev(hw), recps[i].root_buf); } ice_rm_all_sw_replay_rule_info(hw); devm_kfree(ice_hw_to_dev(hw), sw->recp_list); @@ -834,7 +833,7 @@ static int ice_get_fw_log_cfg(struct ice_hw *hw) u16 size; size = sizeof(*config) * ICE_AQC_FW_LOG_ID_MAX; - config = devm_kzalloc(ice_hw_to_dev(hw), size, GFP_KERNEL); + config = kzalloc(size, GFP_KERNEL); if (!config) return -ENOMEM; @@ -857,7 +856,7 @@ static int ice_get_fw_log_cfg(struct ice_hw *hw) } } - devm_kfree(ice_hw_to_dev(hw), config); + kfree(config); return status; } @@ -1011,8 +1010,7 @@ static int ice_cfg_fw_log(struct ice_hw *hw, bool enable) } out: - if (data) - devm_kfree(ice_hw_to_dev(hw), data); + devm_kfree(ice_hw_to_dev(hw), data); return status; } diff --git a/drivers/net/ethernet/intel/ice/ice_controlq.c b/drivers/net/ethernet/intel/ice/ice_controlq.c index d2faf1baad2f9d14b4d01a30fff2d8fc11a09775..e7d2474c431c5c0f4e7631fe4708513b4773ae31 100644 --- a/drivers/net/ethernet/intel/ice/ice_controlq.c +++ b/drivers/net/ethernet/intel/ice/ice_controlq.c @@ -339,8 +339,7 @@ do { \ } \ } \ /* free the buffer info list */ \ - if ((qi)->ring.cmd_buf) \ - devm_kfree(ice_hw_to_dev(hw), (qi)->ring.cmd_buf); \ + devm_kfree(ice_hw_to_dev(hw), (qi)->ring.cmd_buf); \ /* free DMA head */ \ devm_kfree(ice_hw_to_dev(hw), (qi)->ring.dma_head); \ } while (0) @@ -1056,14 +1055,19 @@ ice_sq_send_cmd(struct ice_hw *hw, struct ice_ctl_q_info *cq, if (cq->sq.next_to_use == cq->sq.count) cq->sq.next_to_use = 0; wr32(hw, cq->sq.tail, cq->sq.next_to_use); + ice_flush(hw); + + /* Wait a short time before initial ice_sq_done() check, to allow + * hardware time for completion. + */ + udelay(5); timeout = jiffies + ICE_CTL_Q_SQ_CMD_TIMEOUT; do { if (ice_sq_done(hw, cq)) break; - usleep_range(ICE_CTL_Q_SQ_CMD_USEC, - ICE_CTL_Q_SQ_CMD_USEC * 3 / 2); + usleep_range(100, 150); } while (time_before(jiffies, timeout)); /* if ready, copy the desc back to temp */ diff --git a/drivers/net/ethernet/intel/ice/ice_controlq.h b/drivers/net/ethernet/intel/ice/ice_controlq.h index 950b7f4a7a053df7f6a098efd8c8790bb3625c28..8f2fd1613a952d22e1bf488cd455febcf0621292 100644 --- a/drivers/net/ethernet/intel/ice/ice_controlq.h +++ b/drivers/net/ethernet/intel/ice/ice_controlq.h @@ -35,7 +35,6 @@ enum ice_ctl_q { /* Control Queue timeout settings - max delay 1s */ #define ICE_CTL_Q_SQ_CMD_TIMEOUT HZ /* Wait max 1s */ -#define ICE_CTL_Q_SQ_CMD_USEC 100 /* Check every 100usec */ #define ICE_CTL_Q_ADMIN_INIT_TIMEOUT 10 /* Count 10 times */ #define ICE_CTL_Q_ADMIN_INIT_MSEC 100 /* Check every 100msec */ diff --git a/drivers/net/ethernet/intel/ice/ice_ddp.h b/drivers/net/ethernet/intel/ice/ice_ddp.h index 37eadb3d27a86271cd6391328af18a717e1d81df..41acfe26df1c6b6f27e4a6ca96f1d162d9188932 100644 --- a/drivers/net/ethernet/intel/ice/ice_ddp.h +++ b/drivers/net/ethernet/intel/ice/ice_ddp.h @@ -185,7 +185,7 @@ struct ice_buf_hdr { #define ICE_MAX_ENTRIES_IN_BUF(hd_sz, ent_sz) \ ((ICE_PKG_BUF_SIZE - \ - struct_size((struct ice_buf_hdr *)0, section_entry, 1) - (hd_sz)) / \ + struct_size_t(struct ice_buf_hdr, section_entry, 1) - (hd_sz)) / \ (ent_sz)) /* ice package section IDs */ @@ -297,7 +297,7 @@ struct ice_label_section { }; #define ICE_MAX_LABELS_IN_BUF \ - ICE_MAX_ENTRIES_IN_BUF(struct_size((struct ice_label_section *)0, \ + ICE_MAX_ENTRIES_IN_BUF(struct_size_t(struct ice_label_section, \ label, 1) - \ sizeof(struct ice_label), \ sizeof(struct ice_label)) @@ -352,7 +352,7 @@ struct ice_boost_tcam_section { }; #define ICE_MAX_BST_TCAMS_IN_BUF \ - ICE_MAX_ENTRIES_IN_BUF(struct_size((struct ice_boost_tcam_section *)0, \ + ICE_MAX_ENTRIES_IN_BUF(struct_size_t(struct ice_boost_tcam_section, \ tcam, 1) - \ sizeof(struct ice_boost_tcam_entry), \ sizeof(struct ice_boost_tcam_entry)) @@ -372,8 +372,7 @@ struct ice_marker_ptype_tcam_section { }; #define ICE_MAX_MARKER_PTYPE_TCAMS_IN_BUF \ - ICE_MAX_ENTRIES_IN_BUF( \ - struct_size((struct ice_marker_ptype_tcam_section *)0, tcam, \ + ICE_MAX_ENTRIES_IN_BUF(struct_size_t(struct ice_marker_ptype_tcam_section, tcam, \ 1) - \ sizeof(struct ice_marker_ptype_tcam_entry), \ sizeof(struct ice_marker_ptype_tcam_entry)) diff --git a/drivers/net/ethernet/intel/ice/ice_devlink.c b/drivers/net/ethernet/intel/ice/ice_devlink.c index bc44cc220818078ea5370a554e78a69adcbb6b2f..80dc5445b50d45fa2f444221aebc18800e261c43 100644 --- a/drivers/net/ethernet/intel/ice/ice_devlink.c +++ b/drivers/net/ethernet/intel/ice/ice_devlink.c @@ -1256,8 +1256,6 @@ static const struct devlink_ops ice_devlink_ops = { BIT(DEVLINK_RELOAD_ACTION_FW_ACTIVATE), .reload_down = ice_devlink_reload_down, .reload_up = ice_devlink_reload_up, - .port_split = ice_devlink_port_split, - .port_unsplit = ice_devlink_port_unsplit, .eswitch_mode_get = ice_eswitch_mode_get, .eswitch_mode_set = ice_eswitch_mode_set, .info_get = ice_devlink_info_get, @@ -1512,6 +1510,11 @@ ice_devlink_set_port_split_options(struct ice_pf *pf, ice_active_port_option = active_idx; } +static const struct devlink_port_ops ice_devlink_port_ops = { + .port_split = ice_devlink_port_split, + .port_unsplit = ice_devlink_port_unsplit, +}; + /** * ice_devlink_create_pf_port - Create a devlink port for this PF * @pf: the PF to create a devlink port for @@ -1551,7 +1554,8 @@ int ice_devlink_create_pf_port(struct ice_pf *pf) devlink_port_attrs_set(devlink_port, &attrs); devlink = priv_to_devlink(pf); - err = devlink_port_register(devlink, devlink_port, vsi->idx); + err = devlink_port_register_with_ops(devlink, devlink_port, vsi->idx, + &ice_devlink_port_ops); if (err) { dev_err(dev, "Failed to create devlink port for PF %d, error %d\n", pf->hw.pf_id, err); diff --git a/drivers/net/ethernet/intel/ice/ice_eswitch.c b/drivers/net/ethernet/intel/ice/ice_eswitch.c index f6dd3f8fd936e0e5bf31786a7de49a59aa0c53c1..ad0a007b739881d3220529b59fbc6171c093c46a 100644 --- a/drivers/net/ethernet/intel/ice/ice_eswitch.c +++ b/drivers/net/ethernet/intel/ice/ice_eswitch.c @@ -10,16 +10,15 @@ #include "ice_tc_lib.h" /** - * ice_eswitch_add_vf_mac_rule - add adv rule with VF's MAC + * ice_eswitch_add_vf_sp_rule - add adv rule with VF's VSI index * @pf: pointer to PF struct * @vf: pointer to VF struct - * @mac: VF's MAC address * * This function adds advanced rule that forwards packets with - * VF's MAC address (src MAC) to the corresponding switchdev ctrl VSI queue. + * VF's VSI index to the corresponding switchdev ctrl VSI queue. */ -int -ice_eswitch_add_vf_mac_rule(struct ice_pf *pf, struct ice_vf *vf, const u8 *mac) +static int +ice_eswitch_add_vf_sp_rule(struct ice_pf *pf, struct ice_vf *vf) { struct ice_vsi *ctrl_vsi = pf->switchdev.control_vsi; struct ice_adv_rule_info rule_info = { 0 }; @@ -32,76 +31,41 @@ ice_eswitch_add_vf_mac_rule(struct ice_pf *pf, struct ice_vf *vf, const u8 *mac) if (!list) return -ENOMEM; - list[0].type = ICE_MAC_OFOS; - ether_addr_copy(list[0].h_u.eth_hdr.src_addr, mac); - eth_broadcast_addr(list[0].m_u.eth_hdr.src_addr); + ice_rule_add_src_vsi_metadata(list); - rule_info.sw_act.flag |= ICE_FLTR_TX; + rule_info.sw_act.flag = ICE_FLTR_TX; rule_info.sw_act.vsi_handle = ctrl_vsi->idx; rule_info.sw_act.fltr_act = ICE_FWD_TO_Q; - rule_info.rx = false; rule_info.sw_act.fwd_id.q_id = hw->func_caps.common_cap.rxq_first_id + ctrl_vsi->rxq_map[vf->vf_id]; rule_info.flags_info.act |= ICE_SINGLE_ACT_LB_ENABLE; rule_info.flags_info.act_valid = true; rule_info.tun_type = ICE_SW_TUN_AND_NON_TUN; + rule_info.src_vsi = vf->lan_vsi_idx; err = ice_add_adv_rule(hw, list, lkups_cnt, &rule_info, - vf->repr->mac_rule); + &vf->repr->sp_rule); if (err) - dev_err(ice_pf_to_dev(pf), "Unable to add VF mac rule in switchdev mode for VF %d", + dev_err(ice_pf_to_dev(pf), "Unable to add VF slow-path rule in switchdev mode for VF %d", vf->vf_id); - else - vf->repr->rule_added = true; kfree(list); return err; } /** - * ice_eswitch_replay_vf_mac_rule - replay adv rule with VF's MAC - * @vf: pointer to vF struct - * - * This function replays VF's MAC rule after reset. - */ -void ice_eswitch_replay_vf_mac_rule(struct ice_vf *vf) -{ - int err; - - if (!ice_is_switchdev_running(vf->pf)) - return; - - if (is_valid_ether_addr(vf->hw_lan_addr)) { - err = ice_eswitch_add_vf_mac_rule(vf->pf, vf, - vf->hw_lan_addr); - if (err) { - dev_err(ice_pf_to_dev(vf->pf), "Failed to add MAC %pM for VF %d\n, error %d\n", - vf->hw_lan_addr, vf->vf_id, err); - return; - } - vf->num_mac++; - - ether_addr_copy(vf->dev_lan_addr, vf->hw_lan_addr); - } -} - -/** - * ice_eswitch_del_vf_mac_rule - delete adv rule with VF's MAC + * ice_eswitch_del_vf_sp_rule - delete adv rule with VF's VSI index * @vf: pointer to the VF struct * - * Delete the advanced rule that was used to forward packets with the VF's MAC - * address (src MAC) to the corresponding switchdev ctrl VSI queue. + * Delete the advanced rule that was used to forward packets with the VF's VSI + * index to the corresponding switchdev ctrl VSI queue. */ -void ice_eswitch_del_vf_mac_rule(struct ice_vf *vf) +static void ice_eswitch_del_vf_sp_rule(struct ice_vf *vf) { - if (!ice_is_switchdev_running(vf->pf)) - return; - - if (!vf->repr->rule_added) + if (!vf->repr) return; - ice_rem_adv_rule_by_id(&vf->pf->hw, vf->repr->mac_rule); - vf->repr->rule_added = false; + ice_rem_adv_rule_by_id(&vf->pf->hw, &vf->repr->sp_rule); } /** @@ -237,6 +201,7 @@ ice_eswitch_release_reprs(struct ice_pf *pf, struct ice_vsi *ctrl_vsi) ice_vsi_update_security(vsi, ice_vsi_ctx_set_antispoof); metadata_dst_free(vf->repr->dst); vf->repr->dst = NULL; + ice_eswitch_del_vf_sp_rule(vf); ice_fltr_add_mac_and_broadcast(vsi, vf->hw_lan_addr, ICE_FWD_TO_VSI); @@ -264,25 +229,30 @@ static int ice_eswitch_setup_reprs(struct ice_pf *pf) vf->repr->dst = metadata_dst_alloc(0, METADATA_HW_PORT_MUX, GFP_KERNEL); if (!vf->repr->dst) { - ice_fltr_add_mac_and_broadcast(vsi, - vf->hw_lan_addr, + ice_fltr_add_mac_and_broadcast(vsi, vf->hw_lan_addr, + ICE_FWD_TO_VSI); + goto err; + } + + if (ice_eswitch_add_vf_sp_rule(pf, vf)) { + ice_fltr_add_mac_and_broadcast(vsi, vf->hw_lan_addr, ICE_FWD_TO_VSI); goto err; } if (ice_vsi_update_security(vsi, ice_vsi_ctx_clear_antispoof)) { - ice_fltr_add_mac_and_broadcast(vsi, - vf->hw_lan_addr, + ice_fltr_add_mac_and_broadcast(vsi, vf->hw_lan_addr, ICE_FWD_TO_VSI); + ice_eswitch_del_vf_sp_rule(vf); metadata_dst_free(vf->repr->dst); vf->repr->dst = NULL; goto err; } if (ice_vsi_add_vlan_zero(vsi)) { - ice_fltr_add_mac_and_broadcast(vsi, - vf->hw_lan_addr, + ice_fltr_add_mac_and_broadcast(vsi, vf->hw_lan_addr, ICE_FWD_TO_VSI); + ice_eswitch_del_vf_sp_rule(vf); metadata_dst_free(vf->repr->dst); vf->repr->dst = NULL; ice_vsi_update_security(vsi, ice_vsi_ctx_set_antispoof); diff --git a/drivers/net/ethernet/intel/ice/ice_eswitch.h b/drivers/net/ethernet/intel/ice/ice_eswitch.h index 6a413331572b6a95e663d5820416e390e0c91539..b18bf83a2f5b29a7aa0a4a651f03a4a213dc55d0 100644 --- a/drivers/net/ethernet/intel/ice/ice_eswitch.h +++ b/drivers/net/ethernet/intel/ice/ice_eswitch.h @@ -20,11 +20,6 @@ bool ice_is_eswitch_mode_switchdev(struct ice_pf *pf); void ice_eswitch_update_repr(struct ice_vsi *vsi); void ice_eswitch_stop_all_tx_queues(struct ice_pf *pf); -int -ice_eswitch_add_vf_mac_rule(struct ice_pf *pf, struct ice_vf *vf, - const u8 *mac); -void ice_eswitch_replay_vf_mac_rule(struct ice_vf *vf); -void ice_eswitch_del_vf_mac_rule(struct ice_vf *vf); void ice_eswitch_set_target_vsi(struct sk_buff *skb, struct ice_tx_offload_params *off); @@ -34,15 +29,6 @@ ice_eswitch_port_start_xmit(struct sk_buff *skb, struct net_device *netdev); static inline void ice_eswitch_release(struct ice_pf *pf) { } static inline void ice_eswitch_stop_all_tx_queues(struct ice_pf *pf) { } -static inline void ice_eswitch_replay_vf_mac_rule(struct ice_vf *vf) { } -static inline void ice_eswitch_del_vf_mac_rule(struct ice_vf *vf) { } - -static inline int -ice_eswitch_add_vf_mac_rule(struct ice_pf *pf, struct ice_vf *vf, - const u8 *mac) -{ - return -EOPNOTSUPP; -} static inline void ice_eswitch_set_target_vsi(struct sk_buff *skb, diff --git a/drivers/net/ethernet/intel/ice/ice_ethtool.c b/drivers/net/ethernet/intel/ice/ice_ethtool.c index f86e814354a311b1fb70fe339aa96d153d222508..8d5cbbd0b3d5abcb71a609cb5bf1bd1f8c443ef0 100644 --- a/drivers/net/ethernet/intel/ice/ice_ethtool.c +++ b/drivers/net/ethernet/intel/ice/ice_ethtool.c @@ -4,6 +4,7 @@ /* ethtool support for ice */ #include "ice.h" +#include "ice_ethtool.h" #include "ice_flow.h" #include "ice_fltr.h" #include "ice_lib.h" @@ -956,7 +957,7 @@ static u64 ice_intr_test(struct net_device *netdev) netdev_info(netdev, "interrupt test\n"); - wr32(&pf->hw, GLINT_DYN_CTL(pf->oicr_idx), + wr32(&pf->hw, GLINT_DYN_CTL(pf->oicr_irq.index), GLINT_DYN_CTL_SW_ITR_INDX_M | GLINT_DYN_CTL_INTENA_MSK_M | GLINT_DYN_CTL_SWINT_TRIG_M); @@ -1658,15 +1659,26 @@ ice_mask_min_supported_speeds(struct ice_hw *hw, *phy_types_low &= ~ICE_PHY_TYPE_LOW_MASK_MIN_1G; } -#define ice_ethtool_advertise_link_mode(aq_link_speed, ethtool_link_mode) \ - do { \ - if (req_speeds & (aq_link_speed) || \ - (!req_speeds && \ - (advert_phy_type_lo & phy_type_mask_lo || \ - advert_phy_type_hi & phy_type_mask_hi))) \ - ethtool_link_ksettings_add_link_mode(ks, advertising,\ - ethtool_link_mode); \ - } while (0) +/** + * ice_linkmode_set_bit - set link mode bit + * @phy_to_ethtool: PHY type to ethtool link mode struct to set + * @ks: ethtool link ksettings struct to fill out + * @req_speeds: speed requested by user + * @advert_phy_type: advertised PHY type + * @phy_type: PHY type + */ +static void +ice_linkmode_set_bit(const struct ice_phy_type_to_ethtool *phy_to_ethtool, + struct ethtool_link_ksettings *ks, u32 req_speeds, + u64 advert_phy_type, u32 phy_type) +{ + linkmode_set_bit(phy_to_ethtool->link_mode, ks->link_modes.supported); + + if (req_speeds & phy_to_ethtool->aq_link_speed || + (!req_speeds && advert_phy_type & BIT(phy_type))) + linkmode_set_bit(phy_to_ethtool->link_mode, + ks->link_modes.advertising); +} /** * ice_phy_type_to_ethtool - convert the phy_types to ethtool link modes @@ -1682,11 +1694,10 @@ ice_phy_type_to_ethtool(struct net_device *netdev, struct ice_pf *pf = vsi->back; u64 advert_phy_type_lo = 0; u64 advert_phy_type_hi = 0; - u64 phy_type_mask_lo = 0; - u64 phy_type_mask_hi = 0; u64 phy_types_high = 0; u64 phy_types_low = 0; - u16 req_speeds; + u32 req_speeds; + u32 i; req_speeds = vsi->port_info->phy.link_info.req_speeds; @@ -1743,272 +1754,22 @@ ice_phy_type_to_ethtool(struct net_device *netdev, advert_phy_type_hi = vsi->port_info->phy.phy_type_high; } - ethtool_link_ksettings_zero_link_mode(ks, supported); - ethtool_link_ksettings_zero_link_mode(ks, advertising); - - phy_type_mask_lo = ICE_PHY_TYPE_LOW_100BASE_TX | - ICE_PHY_TYPE_LOW_100M_SGMII; - if (phy_types_low & phy_type_mask_lo) { - ethtool_link_ksettings_add_link_mode(ks, supported, - 100baseT_Full); - - ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_100MB, - 100baseT_Full); - } - - phy_type_mask_lo = ICE_PHY_TYPE_LOW_1000BASE_T | - ICE_PHY_TYPE_LOW_1G_SGMII; - if (phy_types_low & phy_type_mask_lo) { - ethtool_link_ksettings_add_link_mode(ks, supported, - 1000baseT_Full); - ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_1000MB, - 1000baseT_Full); - } - - phy_type_mask_lo = ICE_PHY_TYPE_LOW_1000BASE_KX; - if (phy_types_low & phy_type_mask_lo) { - ethtool_link_ksettings_add_link_mode(ks, supported, - 1000baseKX_Full); - ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_1000MB, - 1000baseKX_Full); - } - - phy_type_mask_lo = ICE_PHY_TYPE_LOW_1000BASE_SX | - ICE_PHY_TYPE_LOW_1000BASE_LX; - if (phy_types_low & phy_type_mask_lo) { - ethtool_link_ksettings_add_link_mode(ks, supported, - 1000baseX_Full); - ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_1000MB, - 1000baseX_Full); - } - - phy_type_mask_lo = ICE_PHY_TYPE_LOW_2500BASE_T; - if (phy_types_low & phy_type_mask_lo) { - ethtool_link_ksettings_add_link_mode(ks, supported, - 2500baseT_Full); - ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_2500MB, - 2500baseT_Full); - } - - phy_type_mask_lo = ICE_PHY_TYPE_LOW_2500BASE_X | - ICE_PHY_TYPE_LOW_2500BASE_KX; - if (phy_types_low & phy_type_mask_lo) { - ethtool_link_ksettings_add_link_mode(ks, supported, - 2500baseX_Full); - ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_2500MB, - 2500baseX_Full); - } - - phy_type_mask_lo = ICE_PHY_TYPE_LOW_5GBASE_T | - ICE_PHY_TYPE_LOW_5GBASE_KR; - if (phy_types_low & phy_type_mask_lo) { - ethtool_link_ksettings_add_link_mode(ks, supported, - 5000baseT_Full); - ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_5GB, - 5000baseT_Full); - } - - phy_type_mask_lo = ICE_PHY_TYPE_LOW_10GBASE_T | - ICE_PHY_TYPE_LOW_10G_SFI_DA | - ICE_PHY_TYPE_LOW_10G_SFI_AOC_ACC | - ICE_PHY_TYPE_LOW_10G_SFI_C2C; - if (phy_types_low & phy_type_mask_lo) { - ethtool_link_ksettings_add_link_mode(ks, supported, - 10000baseT_Full); - ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_10GB, - 10000baseT_Full); - } - - phy_type_mask_lo = ICE_PHY_TYPE_LOW_10GBASE_KR_CR1; - if (phy_types_low & phy_type_mask_lo) { - ethtool_link_ksettings_add_link_mode(ks, supported, - 10000baseKR_Full); - ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_10GB, - 10000baseKR_Full); - } - - phy_type_mask_lo = ICE_PHY_TYPE_LOW_10GBASE_SR; - if (phy_types_low & phy_type_mask_lo) { - ethtool_link_ksettings_add_link_mode(ks, supported, - 10000baseSR_Full); - ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_10GB, - 10000baseSR_Full); - } - - phy_type_mask_lo = ICE_PHY_TYPE_LOW_10GBASE_LR; - if (phy_types_low & phy_type_mask_lo) { - ethtool_link_ksettings_add_link_mode(ks, supported, - 10000baseLR_Full); - ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_10GB, - 10000baseLR_Full); - } - - phy_type_mask_lo = ICE_PHY_TYPE_LOW_25GBASE_T | - ICE_PHY_TYPE_LOW_25GBASE_CR | - ICE_PHY_TYPE_LOW_25GBASE_CR_S | - ICE_PHY_TYPE_LOW_25GBASE_CR1 | - ICE_PHY_TYPE_LOW_25G_AUI_AOC_ACC | - ICE_PHY_TYPE_LOW_25G_AUI_C2C; - if (phy_types_low & phy_type_mask_lo) { - ethtool_link_ksettings_add_link_mode(ks, supported, - 25000baseCR_Full); - ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_25GB, - 25000baseCR_Full); - } - - phy_type_mask_lo = ICE_PHY_TYPE_LOW_25GBASE_SR | - ICE_PHY_TYPE_LOW_25GBASE_LR; - if (phy_types_low & phy_type_mask_lo) { - ethtool_link_ksettings_add_link_mode(ks, supported, - 25000baseSR_Full); - ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_25GB, - 25000baseSR_Full); - } - - phy_type_mask_lo = ICE_PHY_TYPE_LOW_25GBASE_KR | - ICE_PHY_TYPE_LOW_25GBASE_KR_S | - ICE_PHY_TYPE_LOW_25GBASE_KR1; - if (phy_types_low & phy_type_mask_lo) { - ethtool_link_ksettings_add_link_mode(ks, supported, - 25000baseKR_Full); - ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_25GB, - 25000baseKR_Full); - } - - phy_type_mask_lo = ICE_PHY_TYPE_LOW_40GBASE_KR4; - if (phy_types_low & phy_type_mask_lo) { - ethtool_link_ksettings_add_link_mode(ks, supported, - 40000baseKR4_Full); - ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_40GB, - 40000baseKR4_Full); - } - - phy_type_mask_lo = ICE_PHY_TYPE_LOW_40GBASE_CR4 | - ICE_PHY_TYPE_LOW_40G_XLAUI_AOC_ACC | - ICE_PHY_TYPE_LOW_40G_XLAUI; - if (phy_types_low & phy_type_mask_lo) { - ethtool_link_ksettings_add_link_mode(ks, supported, - 40000baseCR4_Full); - ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_40GB, - 40000baseCR4_Full); - } - - phy_type_mask_lo = ICE_PHY_TYPE_LOW_40GBASE_SR4; - if (phy_types_low & phy_type_mask_lo) { - ethtool_link_ksettings_add_link_mode(ks, supported, - 40000baseSR4_Full); - ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_40GB, - 40000baseSR4_Full); - } - - phy_type_mask_lo = ICE_PHY_TYPE_LOW_40GBASE_LR4; - if (phy_types_low & phy_type_mask_lo) { - ethtool_link_ksettings_add_link_mode(ks, supported, - 40000baseLR4_Full); - ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_40GB, - 40000baseLR4_Full); - } - - phy_type_mask_lo = ICE_PHY_TYPE_LOW_50GBASE_CR2 | - ICE_PHY_TYPE_LOW_50G_LAUI2_AOC_ACC | - ICE_PHY_TYPE_LOW_50G_LAUI2 | - ICE_PHY_TYPE_LOW_50G_AUI2_AOC_ACC | - ICE_PHY_TYPE_LOW_50G_AUI2 | - ICE_PHY_TYPE_LOW_50GBASE_CP | - ICE_PHY_TYPE_LOW_50GBASE_SR | - ICE_PHY_TYPE_LOW_50G_AUI1_AOC_ACC | - ICE_PHY_TYPE_LOW_50G_AUI1; - if (phy_types_low & phy_type_mask_lo) { - ethtool_link_ksettings_add_link_mode(ks, supported, - 50000baseCR2_Full); - ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_50GB, - 50000baseCR2_Full); - } - - phy_type_mask_lo = ICE_PHY_TYPE_LOW_50GBASE_KR2 | - ICE_PHY_TYPE_LOW_50GBASE_KR_PAM4; - if (phy_types_low & phy_type_mask_lo) { - ethtool_link_ksettings_add_link_mode(ks, supported, - 50000baseKR2_Full); - ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_50GB, - 50000baseKR2_Full); - } - - phy_type_mask_lo = ICE_PHY_TYPE_LOW_50GBASE_SR2 | - ICE_PHY_TYPE_LOW_50GBASE_LR2 | - ICE_PHY_TYPE_LOW_50GBASE_FR | - ICE_PHY_TYPE_LOW_50GBASE_LR; - if (phy_types_low & phy_type_mask_lo) { - ethtool_link_ksettings_add_link_mode(ks, supported, - 50000baseSR2_Full); - ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_50GB, - 50000baseSR2_Full); - } - - phy_type_mask_lo = ICE_PHY_TYPE_LOW_100GBASE_CR4 | - ICE_PHY_TYPE_LOW_100G_CAUI4_AOC_ACC | - ICE_PHY_TYPE_LOW_100G_CAUI4 | - ICE_PHY_TYPE_LOW_100G_AUI4_AOC_ACC | - ICE_PHY_TYPE_LOW_100G_AUI4 | - ICE_PHY_TYPE_LOW_100GBASE_CR_PAM4; - phy_type_mask_hi = ICE_PHY_TYPE_HIGH_100G_CAUI2_AOC_ACC | - ICE_PHY_TYPE_HIGH_100G_CAUI2 | - ICE_PHY_TYPE_HIGH_100G_AUI2_AOC_ACC | - ICE_PHY_TYPE_HIGH_100G_AUI2; - if (phy_types_low & phy_type_mask_lo || - phy_types_high & phy_type_mask_hi) { - ethtool_link_ksettings_add_link_mode(ks, supported, - 100000baseCR4_Full); - ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_100GB, - 100000baseCR4_Full); - } - - if (phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_CP2) { - ethtool_link_ksettings_add_link_mode(ks, supported, - 100000baseCR2_Full); - ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_100GB, - 100000baseCR2_Full); - } - - if (phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_SR4) { - ethtool_link_ksettings_add_link_mode(ks, supported, - 100000baseSR4_Full); - ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_100GB, - 100000baseSR4_Full); - } - - if (phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_SR2) { - ethtool_link_ksettings_add_link_mode(ks, supported, - 100000baseSR2_Full); - ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_100GB, - 100000baseSR2_Full); - } - - phy_type_mask_lo = ICE_PHY_TYPE_LOW_100GBASE_LR4 | - ICE_PHY_TYPE_LOW_100GBASE_DR; - if (phy_types_low & phy_type_mask_lo) { - ethtool_link_ksettings_add_link_mode(ks, supported, - 100000baseLR4_ER4_Full); - ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_100GB, - 100000baseLR4_ER4_Full); - } + linkmode_zero(ks->link_modes.supported); + linkmode_zero(ks->link_modes.advertising); - phy_type_mask_lo = ICE_PHY_TYPE_LOW_100GBASE_KR4 | - ICE_PHY_TYPE_LOW_100GBASE_KR_PAM4; - if (phy_types_low & phy_type_mask_lo) { - ethtool_link_ksettings_add_link_mode(ks, supported, - 100000baseKR4_Full); - ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_100GB, - 100000baseKR4_Full); + for (i = 0; i < BITS_PER_TYPE(u64); i++) { + if (phy_types_low & BIT_ULL(i)) + ice_linkmode_set_bit(&phy_type_low_lkup[i], ks, + req_speeds, advert_phy_type_lo, + i); } - if (phy_types_high & ICE_PHY_TYPE_HIGH_100GBASE_KR2_PAM4) { - ethtool_link_ksettings_add_link_mode(ks, supported, - 100000baseKR2_Full); - ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_100GB, - 100000baseKR2_Full); + for (i = 0; i < BITS_PER_TYPE(u64); i++) { + if (phy_types_high & BIT_ULL(i)) + ice_linkmode_set_bit(&phy_type_high_lkup[i], ks, + req_speeds, advert_phy_type_hi, + i); } - } #define TEST_SET_BITS_TIMEOUT 50 diff --git a/drivers/net/ethernet/intel/ice/ice_ethtool.h b/drivers/net/ethernet/intel/ice/ice_ethtool.h new file mode 100644 index 0000000000000000000000000000000000000000..b403ee79cd5e47482b86b5fde24c55c7f972e4bb --- /dev/null +++ b/drivers/net/ethernet/intel/ice/ice_ethtool.h @@ -0,0 +1,105 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* Copyright (C) 2023 Intel Corporation */ + +#ifndef _ICE_ETHTOOL_H_ +#define _ICE_ETHTOOL_H_ + +struct ice_phy_type_to_ethtool { + u64 aq_link_speed; + u8 link_mode; +}; + +/* Macro to make PHY type to Ethtool link mode table entry. + * The index is the PHY type. + */ +#define ICE_PHY_TYPE(LINK_SPEED, ETHTOOL_LINK_MODE) {\ + .aq_link_speed = ICE_AQ_LINK_SPEED_##LINK_SPEED, \ + .link_mode = ETHTOOL_LINK_MODE_##ETHTOOL_LINK_MODE##_BIT, \ +} + +/* Lookup table mapping PHY type low to link speed and Ethtool link modes. + * Array index corresponds to HW PHY type bit, see + * ice_adminq_cmd.h:ICE_PHY_TYPE_LOW_*. + */ +static const struct ice_phy_type_to_ethtool +phy_type_low_lkup[] = { + [0] = ICE_PHY_TYPE(100MB, 100baseT_Full), + [1] = ICE_PHY_TYPE(100MB, 100baseT_Full), + [2] = ICE_PHY_TYPE(1000MB, 1000baseT_Full), + [3] = ICE_PHY_TYPE(1000MB, 1000baseX_Full), + [4] = ICE_PHY_TYPE(1000MB, 1000baseX_Full), + [5] = ICE_PHY_TYPE(1000MB, 1000baseKX_Full), + [6] = ICE_PHY_TYPE(1000MB, 1000baseT_Full), + [7] = ICE_PHY_TYPE(2500MB, 2500baseT_Full), + [8] = ICE_PHY_TYPE(2500MB, 2500baseX_Full), + [9] = ICE_PHY_TYPE(2500MB, 2500baseX_Full), + [10] = ICE_PHY_TYPE(5GB, 5000baseT_Full), + [11] = ICE_PHY_TYPE(5GB, 5000baseT_Full), + [12] = ICE_PHY_TYPE(10GB, 10000baseT_Full), + [13] = ICE_PHY_TYPE(10GB, 10000baseCR_Full), + [14] = ICE_PHY_TYPE(10GB, 10000baseSR_Full), + [15] = ICE_PHY_TYPE(10GB, 10000baseLR_Full), + [16] = ICE_PHY_TYPE(10GB, 10000baseKR_Full), + [17] = ICE_PHY_TYPE(10GB, 10000baseCR_Full), + [18] = ICE_PHY_TYPE(10GB, 10000baseKR_Full), + [19] = ICE_PHY_TYPE(25GB, 25000baseCR_Full), + [20] = ICE_PHY_TYPE(25GB, 25000baseCR_Full), + [21] = ICE_PHY_TYPE(25GB, 25000baseCR_Full), + [22] = ICE_PHY_TYPE(25GB, 25000baseCR_Full), + [23] = ICE_PHY_TYPE(25GB, 25000baseSR_Full), + [24] = ICE_PHY_TYPE(25GB, 25000baseSR_Full), + [25] = ICE_PHY_TYPE(25GB, 25000baseKR_Full), + [26] = ICE_PHY_TYPE(25GB, 25000baseKR_Full), + [27] = ICE_PHY_TYPE(25GB, 25000baseKR_Full), + [28] = ICE_PHY_TYPE(25GB, 25000baseSR_Full), + [29] = ICE_PHY_TYPE(25GB, 25000baseCR_Full), + [30] = ICE_PHY_TYPE(40GB, 40000baseCR4_Full), + [31] = ICE_PHY_TYPE(40GB, 40000baseSR4_Full), + [32] = ICE_PHY_TYPE(40GB, 40000baseLR4_Full), + [33] = ICE_PHY_TYPE(40GB, 40000baseKR4_Full), + [34] = ICE_PHY_TYPE(40GB, 40000baseSR4_Full), + [35] = ICE_PHY_TYPE(40GB, 40000baseCR4_Full), + [36] = ICE_PHY_TYPE(50GB, 50000baseCR2_Full), + [37] = ICE_PHY_TYPE(50GB, 50000baseSR2_Full), + [38] = ICE_PHY_TYPE(50GB, 50000baseSR2_Full), + [39] = ICE_PHY_TYPE(50GB, 50000baseKR2_Full), + [40] = ICE_PHY_TYPE(50GB, 50000baseSR2_Full), + [41] = ICE_PHY_TYPE(50GB, 50000baseCR2_Full), + [42] = ICE_PHY_TYPE(50GB, 50000baseSR2_Full), + [43] = ICE_PHY_TYPE(50GB, 50000baseCR2_Full), + [44] = ICE_PHY_TYPE(50GB, 50000baseCR_Full), + [45] = ICE_PHY_TYPE(50GB, 50000baseSR_Full), + [46] = ICE_PHY_TYPE(50GB, 50000baseLR_ER_FR_Full), + [47] = ICE_PHY_TYPE(50GB, 50000baseLR_ER_FR_Full), + [48] = ICE_PHY_TYPE(50GB, 50000baseKR_Full), + [49] = ICE_PHY_TYPE(50GB, 50000baseSR_Full), + [50] = ICE_PHY_TYPE(50GB, 50000baseCR_Full), + [51] = ICE_PHY_TYPE(100GB, 100000baseCR4_Full), + [52] = ICE_PHY_TYPE(100GB, 100000baseSR4_Full), + [53] = ICE_PHY_TYPE(100GB, 100000baseLR4_ER4_Full), + [54] = ICE_PHY_TYPE(100GB, 100000baseKR4_Full), + [55] = ICE_PHY_TYPE(100GB, 100000baseCR4_Full), + [56] = ICE_PHY_TYPE(100GB, 100000baseCR4_Full), + [57] = ICE_PHY_TYPE(100GB, 100000baseSR4_Full), + [58] = ICE_PHY_TYPE(100GB, 100000baseCR4_Full), + [59] = ICE_PHY_TYPE(100GB, 100000baseCR4_Full), + [60] = ICE_PHY_TYPE(100GB, 100000baseKR4_Full), + [61] = ICE_PHY_TYPE(100GB, 100000baseCR2_Full), + [62] = ICE_PHY_TYPE(100GB, 100000baseSR2_Full), + [63] = ICE_PHY_TYPE(100GB, 100000baseLR4_ER4_Full), +}; + +/* Lookup table mapping PHY type high to link speed and Ethtool link modes. + * Array index corresponds to HW PHY type bit, see + * ice_adminq_cmd.h:ICE_PHY_TYPE_HIGH_* + */ +static const struct ice_phy_type_to_ethtool +phy_type_high_lkup[] = { + [0] = ICE_PHY_TYPE(100GB, 100000baseKR2_Full), + [1] = ICE_PHY_TYPE(100GB, 100000baseSR2_Full), + [2] = ICE_PHY_TYPE(100GB, 100000baseCR2_Full), + [3] = ICE_PHY_TYPE(100GB, 100000baseSR2_Full), + [4] = ICE_PHY_TYPE(100GB, 100000baseCR2_Full), +}; + +#endif /* !_ICE_ETHTOOL_H_ */ diff --git a/drivers/net/ethernet/intel/ice/ice_flow.c b/drivers/net/ethernet/intel/ice/ice_flow.c index ef103e47a8dc20bbc38c47fba3b46b245b4a7a32..85cca572c22a54d953cf0c2d323e4de00b8c8e3a 100644 --- a/drivers/net/ethernet/intel/ice/ice_flow.c +++ b/drivers/net/ethernet/intel/ice/ice_flow.c @@ -1303,23 +1303,6 @@ ice_flow_find_prof_id(struct ice_hw *hw, enum ice_block blk, u64 prof_id) return NULL; } -/** - * ice_dealloc_flow_entry - Deallocate flow entry memory - * @hw: pointer to the HW struct - * @entry: flow entry to be removed - */ -static void -ice_dealloc_flow_entry(struct ice_hw *hw, struct ice_flow_entry *entry) -{ - if (!entry) - return; - - if (entry->entry) - devm_kfree(ice_hw_to_dev(hw), entry->entry); - - devm_kfree(ice_hw_to_dev(hw), entry); -} - /** * ice_flow_rem_entry_sync - Remove a flow entry * @hw: pointer to the HW struct @@ -1335,7 +1318,8 @@ ice_flow_rem_entry_sync(struct ice_hw *hw, enum ice_block __always_unused blk, list_del(&entry->l_entry); - ice_dealloc_flow_entry(hw, entry); + devm_kfree(ice_hw_to_dev(hw), entry->entry); + devm_kfree(ice_hw_to_dev(hw), entry); return 0; } @@ -1662,8 +1646,7 @@ ice_flow_add_entry(struct ice_hw *hw, enum ice_block blk, u64 prof_id, out: if (status && e) { - if (e->entry) - devm_kfree(ice_hw_to_dev(hw), e->entry); + devm_kfree(ice_hw_to_dev(hw), e->entry); devm_kfree(ice_hw_to_dev(hw), e); } diff --git a/drivers/net/ethernet/intel/ice/ice_idc.c b/drivers/net/ethernet/intel/ice/ice_idc.c index e6bc2285071e2762c1851d8cadd9a18589895a28..145b27f2a4ce80a8fcb2a31dbee2c843ea6ca89b 100644 --- a/drivers/net/ethernet/intel/ice/ice_idc.c +++ b/drivers/net/ethernet/intel/ice/ice_idc.c @@ -229,20 +229,34 @@ void ice_get_qos_params(struct ice_pf *pf, struct iidc_qos_params *qos) EXPORT_SYMBOL_GPL(ice_get_qos_params); /** - * ice_reserve_rdma_qvector - Reserve vector resources for RDMA driver + * ice_alloc_rdma_qvectors - Allocate vector resources for RDMA driver * @pf: board private structure to initialize */ -static int ice_reserve_rdma_qvector(struct ice_pf *pf) +static int ice_alloc_rdma_qvectors(struct ice_pf *pf) { if (ice_is_rdma_ena(pf)) { - int index; - - index = ice_get_res(pf, pf->irq_tracker, pf->num_rdma_msix, - ICE_RES_RDMA_VEC_ID); - if (index < 0) - return index; - pf->num_avail_sw_msix -= pf->num_rdma_msix; - pf->rdma_base_vector = (u16)index; + int i; + + pf->msix_entries = kcalloc(pf->num_rdma_msix, + sizeof(*pf->msix_entries), + GFP_KERNEL); + if (!pf->msix_entries) + return -ENOMEM; + + /* RDMA is the only user of pf->msix_entries array */ + pf->rdma_base_vector = 0; + + for (i = 0; i < pf->num_rdma_msix; i++) { + struct msix_entry *entry = &pf->msix_entries[i]; + struct msi_map map; + + map = ice_alloc_irq(pf, false); + if (map.index < 0) + break; + + entry->entry = map.index; + entry->vector = map.virq; + } } return 0; } @@ -253,9 +267,21 @@ static int ice_reserve_rdma_qvector(struct ice_pf *pf) */ static void ice_free_rdma_qvector(struct ice_pf *pf) { - pf->num_avail_sw_msix -= pf->num_rdma_msix; - ice_free_res(pf->irq_tracker, pf->rdma_base_vector, - ICE_RES_RDMA_VEC_ID); + int i; + + if (!pf->msix_entries) + return; + + for (i = 0; i < pf->num_rdma_msix; i++) { + struct msi_map map; + + map.index = pf->msix_entries[i].entry; + map.virq = pf->msix_entries[i].vector; + ice_free_irq(pf, map); + } + + kfree(pf->msix_entries); + pf->msix_entries = NULL; } /** @@ -357,7 +383,7 @@ int ice_init_rdma(struct ice_pf *pf) } /* Reserve vector resources */ - ret = ice_reserve_rdma_qvector(pf); + ret = ice_alloc_rdma_qvectors(pf); if (ret < 0) { dev_err(dev, "failed to reserve vectors for RDMA\n"); goto err_reserve_rdma_qvector; diff --git a/drivers/net/ethernet/intel/ice/ice_irq.c b/drivers/net/ethernet/intel/ice/ice_irq.c new file mode 100644 index 0000000000000000000000000000000000000000..ad82ff7d199570fe219fb95669a2488517d7ce7c --- /dev/null +++ b/drivers/net/ethernet/intel/ice/ice_irq.c @@ -0,0 +1,378 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (C) 2023, Intel Corporation. */ + +#include "ice.h" +#include "ice_lib.h" +#include "ice_irq.h" + +/** + * ice_init_irq_tracker - initialize interrupt tracker + * @pf: board private structure + * @max_vectors: maximum number of vectors that tracker can hold + * @num_static: number of preallocated interrupts + */ +static void +ice_init_irq_tracker(struct ice_pf *pf, unsigned int max_vectors, + unsigned int num_static) +{ + pf->irq_tracker.num_entries = max_vectors; + pf->irq_tracker.num_static = num_static; + xa_init_flags(&pf->irq_tracker.entries, XA_FLAGS_ALLOC); +} + +/** + * ice_deinit_irq_tracker - free xarray tracker + * @pf: board private structure + */ +static void ice_deinit_irq_tracker(struct ice_pf *pf) +{ + xa_destroy(&pf->irq_tracker.entries); +} + +/** + * ice_free_irq_res - free a block of resources + * @pf: board private structure + * @index: starting index previously returned by ice_get_res + */ +static void ice_free_irq_res(struct ice_pf *pf, u16 index) +{ + struct ice_irq_entry *entry; + + entry = xa_erase(&pf->irq_tracker.entries, index); + kfree(entry); +} + +/** + * ice_get_irq_res - get an interrupt resource + * @pf: board private structure + * @dyn_only: force entry to be dynamically allocated + * + * Allocate new irq entry in the free slot of the tracker. Since xarray + * is used, always allocate new entry at the lowest possible index. Set + * proper allocation limit for maximum tracker entries. + * + * Returns allocated irq entry or NULL on failure. + */ +static struct ice_irq_entry *ice_get_irq_res(struct ice_pf *pf, bool dyn_only) +{ + struct xa_limit limit = { .max = pf->irq_tracker.num_entries, + .min = 0 }; + unsigned int num_static = pf->irq_tracker.num_static; + struct ice_irq_entry *entry; + unsigned int index; + int ret; + + entry = kzalloc(sizeof(*entry), GFP_KERNEL); + if (!entry) + return NULL; + + /* skip preallocated entries if the caller says so */ + if (dyn_only) + limit.min = num_static; + + ret = xa_alloc(&pf->irq_tracker.entries, &index, entry, limit, + GFP_KERNEL); + + if (ret) { + kfree(entry); + entry = NULL; + } else { + entry->index = index; + entry->dynamic = index >= num_static; + } + + return entry; +} + +/** + * ice_reduce_msix_usage - Reduce usage of MSI-X vectors + * @pf: board private structure + * @v_remain: number of remaining MSI-X vectors to be distributed + * + * Reduce the usage of MSI-X vectors when entire request cannot be fulfilled. + * pf->num_lan_msix and pf->num_rdma_msix values are set based on number of + * remaining vectors. + */ +static void ice_reduce_msix_usage(struct ice_pf *pf, int v_remain) +{ + int v_rdma; + + if (!ice_is_rdma_ena(pf)) { + pf->num_lan_msix = v_remain; + return; + } + + /* RDMA needs at least 1 interrupt in addition to AEQ MSIX */ + v_rdma = ICE_RDMA_NUM_AEQ_MSIX + 1; + + if (v_remain < ICE_MIN_LAN_TXRX_MSIX + ICE_MIN_RDMA_MSIX) { + dev_warn(ice_pf_to_dev(pf), "Not enough MSI-X vectors to support RDMA.\n"); + clear_bit(ICE_FLAG_RDMA_ENA, pf->flags); + + pf->num_rdma_msix = 0; + pf->num_lan_msix = ICE_MIN_LAN_TXRX_MSIX; + } else if ((v_remain < ICE_MIN_LAN_TXRX_MSIX + v_rdma) || + (v_remain - v_rdma < v_rdma)) { + /* Support minimum RDMA and give remaining vectors to LAN MSIX + */ + pf->num_rdma_msix = ICE_MIN_RDMA_MSIX; + pf->num_lan_msix = v_remain - ICE_MIN_RDMA_MSIX; + } else { + /* Split remaining MSIX with RDMA after accounting for AEQ MSIX + */ + pf->num_rdma_msix = (v_remain - ICE_RDMA_NUM_AEQ_MSIX) / 2 + + ICE_RDMA_NUM_AEQ_MSIX; + pf->num_lan_msix = v_remain - pf->num_rdma_msix; + } +} + +/** + * ice_ena_msix_range - Request a range of MSIX vectors from the OS + * @pf: board private structure + * + * Compute the number of MSIX vectors wanted and request from the OS. Adjust + * device usage if there are not enough vectors. Return the number of vectors + * reserved or negative on failure. + */ +static int ice_ena_msix_range(struct ice_pf *pf) +{ + int num_cpus, hw_num_msix, v_other, v_wanted, v_actual; + struct device *dev = ice_pf_to_dev(pf); + int err; + + hw_num_msix = pf->hw.func_caps.common_cap.num_msix_vectors; + num_cpus = num_online_cpus(); + + /* LAN miscellaneous handler */ + v_other = ICE_MIN_LAN_OICR_MSIX; + + /* Flow Director */ + if (test_bit(ICE_FLAG_FD_ENA, pf->flags)) + v_other += ICE_FDIR_MSIX; + + /* switchdev */ + v_other += ICE_ESWITCH_MSIX; + + v_wanted = v_other; + + /* LAN traffic */ + pf->num_lan_msix = num_cpus; + v_wanted += pf->num_lan_msix; + + /* RDMA auxiliary driver */ + if (ice_is_rdma_ena(pf)) { + pf->num_rdma_msix = num_cpus + ICE_RDMA_NUM_AEQ_MSIX; + v_wanted += pf->num_rdma_msix; + } + + if (v_wanted > hw_num_msix) { + int v_remain; + + dev_warn(dev, "not enough device MSI-X vectors. wanted = %d, available = %d\n", + v_wanted, hw_num_msix); + + if (hw_num_msix < ICE_MIN_MSIX) { + err = -ERANGE; + goto exit_err; + } + + v_remain = hw_num_msix - v_other; + if (v_remain < ICE_MIN_LAN_TXRX_MSIX) { + v_other = ICE_MIN_MSIX - ICE_MIN_LAN_TXRX_MSIX; + v_remain = ICE_MIN_LAN_TXRX_MSIX; + } + + ice_reduce_msix_usage(pf, v_remain); + v_wanted = pf->num_lan_msix + pf->num_rdma_msix + v_other; + + dev_notice(dev, "Reducing request to %d MSI-X vectors for LAN traffic.\n", + pf->num_lan_msix); + if (ice_is_rdma_ena(pf)) + dev_notice(dev, "Reducing request to %d MSI-X vectors for RDMA.\n", + pf->num_rdma_msix); + } + + /* actually reserve the vectors */ + v_actual = pci_alloc_irq_vectors(pf->pdev, ICE_MIN_MSIX, v_wanted, + PCI_IRQ_MSIX); + if (v_actual < 0) { + dev_err(dev, "unable to reserve MSI-X vectors\n"); + err = v_actual; + goto exit_err; + } + + if (v_actual < v_wanted) { + dev_warn(dev, "not enough OS MSI-X vectors. requested = %d, obtained = %d\n", + v_wanted, v_actual); + + if (v_actual < ICE_MIN_MSIX) { + /* error if we can't get minimum vectors */ + pci_free_irq_vectors(pf->pdev); + err = -ERANGE; + goto exit_err; + } else { + int v_remain = v_actual - v_other; + + if (v_remain < ICE_MIN_LAN_TXRX_MSIX) + v_remain = ICE_MIN_LAN_TXRX_MSIX; + + ice_reduce_msix_usage(pf, v_remain); + + dev_notice(dev, "Enabled %d MSI-X vectors for LAN traffic.\n", + pf->num_lan_msix); + + if (ice_is_rdma_ena(pf)) + dev_notice(dev, "Enabled %d MSI-X vectors for RDMA.\n", + pf->num_rdma_msix); + } + } + + return v_actual; + +exit_err: + pf->num_rdma_msix = 0; + pf->num_lan_msix = 0; + return err; +} + +/** + * ice_clear_interrupt_scheme - Undo things done by ice_init_interrupt_scheme + * @pf: board private structure + */ +void ice_clear_interrupt_scheme(struct ice_pf *pf) +{ + pci_free_irq_vectors(pf->pdev); + ice_deinit_irq_tracker(pf); +} + +/** + * ice_init_interrupt_scheme - Determine proper interrupt scheme + * @pf: board private structure to initialize + */ +int ice_init_interrupt_scheme(struct ice_pf *pf) +{ + int total_vectors = pf->hw.func_caps.common_cap.num_msix_vectors; + int vectors, max_vectors; + + vectors = ice_ena_msix_range(pf); + + if (vectors < 0) + return -ENOMEM; + + if (pci_msix_can_alloc_dyn(pf->pdev)) + max_vectors = total_vectors; + else + max_vectors = vectors; + + ice_init_irq_tracker(pf, max_vectors, vectors); + + return 0; +} + +/** + * ice_alloc_irq - Allocate new interrupt vector + * @pf: board private structure + * @dyn_only: force dynamic allocation of the interrupt + * + * Allocate new interrupt vector for a given owner id. + * return struct msi_map with interrupt details and track + * allocated interrupt appropriately. + * + * This function reserves new irq entry from the irq_tracker. + * if according to the tracker information all interrupts that + * were allocated with ice_pci_alloc_irq_vectors are already used + * and dynamically allocated interrupts are supported then new + * interrupt will be allocated with pci_msix_alloc_irq_at. + * + * Some callers may only support dynamically allocated interrupts. + * This is indicated with dyn_only flag. + * + * On failure, return map with negative .index. The caller + * is expected to check returned map index. + * + */ +struct msi_map ice_alloc_irq(struct ice_pf *pf, bool dyn_only) +{ + int sriov_base_vector = pf->sriov_base_vector; + struct msi_map map = { .index = -ENOENT }; + struct device *dev = ice_pf_to_dev(pf); + struct ice_irq_entry *entry; + + entry = ice_get_irq_res(pf, dyn_only); + if (!entry) + return map; + + /* fail if we're about to violate SRIOV vectors space */ + if (sriov_base_vector && entry->index >= sriov_base_vector) + goto exit_free_res; + + if (pci_msix_can_alloc_dyn(pf->pdev) && entry->dynamic) { + map = pci_msix_alloc_irq_at(pf->pdev, entry->index, NULL); + if (map.index < 0) + goto exit_free_res; + dev_dbg(dev, "allocated new irq at index %d\n", map.index); + } else { + map.index = entry->index; + map.virq = pci_irq_vector(pf->pdev, map.index); + } + + return map; + +exit_free_res: + dev_err(dev, "Could not allocate irq at idx %d\n", entry->index); + ice_free_irq_res(pf, entry->index); + return map; +} + +/** + * ice_free_irq - Free interrupt vector + * @pf: board private structure + * @map: map with interrupt details + * + * Remove allocated interrupt from the interrupt tracker. If interrupt was + * allocated dynamically, free respective interrupt vector. + */ +void ice_free_irq(struct ice_pf *pf, struct msi_map map) +{ + struct ice_irq_entry *entry; + + entry = xa_load(&pf->irq_tracker.entries, map.index); + + if (!entry) { + dev_err(ice_pf_to_dev(pf), "Failed to get MSIX interrupt entry at index %d", + map.index); + return; + } + + dev_dbg(ice_pf_to_dev(pf), "Free irq at index %d\n", map.index); + + if (entry->dynamic) + pci_msix_free_irq(pf->pdev, map); + + ice_free_irq_res(pf, map.index); +} + +/** + * ice_get_max_used_msix_vector - Get the max used interrupt vector + * @pf: board private structure + * + * Return index of maximum used interrupt vectors with respect to the + * beginning of the MSIX table. Take into account that some interrupts + * may have been dynamically allocated after MSIX was initially enabled. + */ +int ice_get_max_used_msix_vector(struct ice_pf *pf) +{ + unsigned long start, index, max_idx; + void *entry; + + /* Treat all preallocated interrupts as used */ + start = pf->irq_tracker.num_static; + max_idx = start - 1; + + xa_for_each_start(&pf->irq_tracker.entries, index, entry, start) { + if (index > max_idx) + max_idx = index; + } + + return max_idx; +} diff --git a/drivers/net/ethernet/intel/ice/ice_irq.h b/drivers/net/ethernet/intel/ice/ice_irq.h new file mode 100644 index 0000000000000000000000000000000000000000..f35efc08575efeeb1a3b7b8915ed876eb5721a3a --- /dev/null +++ b/drivers/net/ethernet/intel/ice/ice_irq.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (C) 2023, Intel Corporation. */ + +#ifndef _ICE_IRQ_H_ +#define _ICE_IRQ_H_ + +struct ice_irq_entry { + unsigned int index; + bool dynamic; /* allocation type flag */ +}; + +struct ice_irq_tracker { + struct xarray entries; + u16 num_entries; /* total vectors available */ + u16 num_static; /* preallocated entries */ +}; + +int ice_init_interrupt_scheme(struct ice_pf *pf); +void ice_clear_interrupt_scheme(struct ice_pf *pf); + +struct msi_map ice_alloc_irq(struct ice_pf *pf, bool dyn_only); +void ice_free_irq(struct ice_pf *pf, struct msi_map map); +int ice_get_max_used_msix_vector(struct ice_pf *pf); + +#endif diff --git a/drivers/net/ethernet/intel/ice/ice_lag.c b/drivers/net/ethernet/intel/ice/ice_lag.c index ee5b36941ba35868c260f36ae430061bea55223f..5a7753bda32457ec7aaee441984648a8dc69e968 100644 --- a/drivers/net/ethernet/intel/ice/ice_lag.c +++ b/drivers/net/ethernet/intel/ice/ice_lag.c @@ -6,15 +6,6 @@ #include "ice.h" #include "ice_lag.h" -/** - * ice_lag_nop_handler - no-op Rx handler to disable LAG - * @pskb: pointer to skb pointer - */ -rx_handler_result_t ice_lag_nop_handler(struct sk_buff __always_unused **pskb) -{ - return RX_HANDLER_PASS; -} - /** * ice_lag_set_primary - set PF LAG state as Primary * @lag: LAG info struct @@ -158,7 +149,6 @@ ice_lag_link(struct ice_lag *lag, struct netdev_notifier_changeupper_info *info) lag->upper_netdev = upper; } - ice_clear_sriov_cap(pf); ice_clear_rdma_cap(pf); lag->bonded = true; @@ -205,7 +195,6 @@ ice_lag_unlink(struct ice_lag *lag, } lag->peer_netdev = NULL; - ice_set_sriov_cap(pf); ice_set_rdma_cap(pf); lag->bonded = false; lag->role = ICE_LAG_NONE; @@ -229,7 +218,6 @@ static void ice_lag_unregister(struct ice_lag *lag, struct net_device *netdev) if (lag->upper_netdev) { dev_put(lag->upper_netdev); lag->upper_netdev = NULL; - ice_set_sriov_cap(pf); ice_set_rdma_cap(pf); } /* perform some cleanup in case we come back */ diff --git a/drivers/net/ethernet/intel/ice/ice_lag.h b/drivers/net/ethernet/intel/ice/ice_lag.h index 51b5cf467ce24dba543b6e8ac171f072573df55c..2c373676c42f297e98530b0efa18102f1daf63bf 100644 --- a/drivers/net/ethernet/intel/ice/ice_lag.h +++ b/drivers/net/ethernet/intel/ice/ice_lag.h @@ -25,63 +25,9 @@ struct ice_lag { struct notifier_block notif_block; u8 bonded:1; /* currently bonded */ u8 primary:1; /* this is primary */ - u8 handler:1; /* did we register a rx_netdev_handler */ - /* each thing blocking bonding will increment this value by one. - * If this value is zero, then bonding is allowed. - */ - u16 dis_lag; u8 role; }; int ice_init_lag(struct ice_pf *pf); void ice_deinit_lag(struct ice_pf *pf); -rx_handler_result_t ice_lag_nop_handler(struct sk_buff **pskb); - -/** - * ice_disable_lag - increment LAG disable count - * @lag: LAG struct - */ -static inline void ice_disable_lag(struct ice_lag *lag) -{ - /* If LAG this PF is not already disabled, disable it */ - rtnl_lock(); - if (!netdev_is_rx_handler_busy(lag->netdev)) { - if (!netdev_rx_handler_register(lag->netdev, - ice_lag_nop_handler, - NULL)) - lag->handler = true; - } - rtnl_unlock(); - lag->dis_lag++; -} - -/** - * ice_enable_lag - decrement disable count for a PF - * @lag: LAG struct - * - * Decrement the disable counter for a port, and if that count reaches - * zero, then remove the no-op Rx handler from that netdev - */ -static inline void ice_enable_lag(struct ice_lag *lag) -{ - if (lag->dis_lag) - lag->dis_lag--; - if (!lag->dis_lag && lag->handler) { - rtnl_lock(); - netdev_rx_handler_unregister(lag->netdev); - rtnl_unlock(); - lag->handler = false; - } -} - -/** - * ice_is_lag_dis - is LAG disabled - * @lag: LAG struct - * - * Return true if bonding is disabled - */ -static inline bool ice_is_lag_dis(struct ice_lag *lag) -{ - return !!(lag->dis_lag); -} #endif /* _ICE_LAG_H_ */ diff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c index 11ae0e41f518a13b1c77c56a15404338495b746a..00e3afd507a4084c5cc170cd23d230a9275fdc72 100644 --- a/drivers/net/ethernet/intel/ice/ice_lib.c +++ b/drivers/net/ethernet/intel/ice/ice_lib.c @@ -321,31 +321,19 @@ static void ice_vsi_free_arrays(struct ice_vsi *vsi) dev = ice_pf_to_dev(pf); - if (vsi->af_xdp_zc_qps) { - bitmap_free(vsi->af_xdp_zc_qps); - vsi->af_xdp_zc_qps = NULL; - } + bitmap_free(vsi->af_xdp_zc_qps); + vsi->af_xdp_zc_qps = NULL; /* free the ring and vector containers */ - if (vsi->q_vectors) { - devm_kfree(dev, vsi->q_vectors); - vsi->q_vectors = NULL; - } - if (vsi->tx_rings) { - devm_kfree(dev, vsi->tx_rings); - vsi->tx_rings = NULL; - } - if (vsi->rx_rings) { - devm_kfree(dev, vsi->rx_rings); - vsi->rx_rings = NULL; - } - if (vsi->txq_map) { - devm_kfree(dev, vsi->txq_map); - vsi->txq_map = NULL; - } - if (vsi->rxq_map) { - devm_kfree(dev, vsi->rxq_map); - vsi->rxq_map = NULL; - } + devm_kfree(dev, vsi->q_vectors); + vsi->q_vectors = NULL; + devm_kfree(dev, vsi->tx_rings); + vsi->tx_rings = NULL; + devm_kfree(dev, vsi->rx_rings); + vsi->rx_rings = NULL; + devm_kfree(dev, vsi->txq_map); + vsi->txq_map = NULL; + devm_kfree(dev, vsi->rxq_map); + vsi->rxq_map = NULL; } /** @@ -902,10 +890,8 @@ static void ice_rss_clean(struct ice_vsi *vsi) dev = ice_pf_to_dev(pf); - if (vsi->rss_hkey_user) - devm_kfree(dev, vsi->rss_hkey_user); - if (vsi->rss_lut_user) - devm_kfree(dev, vsi->rss_lut_user); + devm_kfree(dev, vsi->rss_hkey_user); + devm_kfree(dev, vsi->rss_lut_user); ice_vsi_clean_rss_flow_fld(vsi); /* remove RSS replay list */ @@ -1370,190 +1356,6 @@ static int ice_vsi_init(struct ice_vsi *vsi, u32 vsi_flags) return ret; } -/** - * ice_free_res - free a block of resources - * @res: pointer to the resource - * @index: starting index previously returned by ice_get_res - * @id: identifier to track owner - * - * Returns number of resources freed - */ -int ice_free_res(struct ice_res_tracker *res, u16 index, u16 id) -{ - int count = 0; - int i; - - if (!res || index >= res->end) - return -EINVAL; - - id |= ICE_RES_VALID_BIT; - for (i = index; i < res->end && res->list[i] == id; i++) { - res->list[i] = 0; - count++; - } - - return count; -} - -/** - * ice_search_res - Search the tracker for a block of resources - * @res: pointer to the resource - * @needed: size of the block needed - * @id: identifier to track owner - * - * Returns the base item index of the block, or -ENOMEM for error - */ -static int ice_search_res(struct ice_res_tracker *res, u16 needed, u16 id) -{ - u16 start = 0, end = 0; - - if (needed > res->end) - return -ENOMEM; - - id |= ICE_RES_VALID_BIT; - - do { - /* skip already allocated entries */ - if (res->list[end++] & ICE_RES_VALID_BIT) { - start = end; - if ((start + needed) > res->end) - break; - } - - if (end == (start + needed)) { - int i = start; - - /* there was enough, so assign it to the requestor */ - while (i != end) - res->list[i++] = id; - - return start; - } - } while (end < res->end); - - return -ENOMEM; -} - -/** - * ice_get_free_res_count - Get free count from a resource tracker - * @res: Resource tracker instance - */ -static u16 ice_get_free_res_count(struct ice_res_tracker *res) -{ - u16 i, count = 0; - - for (i = 0; i < res->end; i++) - if (!(res->list[i] & ICE_RES_VALID_BIT)) - count++; - - return count; -} - -/** - * ice_get_res - get a block of resources - * @pf: board private structure - * @res: pointer to the resource - * @needed: size of the block needed - * @id: identifier to track owner - * - * Returns the base item index of the block, or negative for error - */ -int -ice_get_res(struct ice_pf *pf, struct ice_res_tracker *res, u16 needed, u16 id) -{ - if (!res || !pf) - return -EINVAL; - - if (!needed || needed > res->num_entries || id >= ICE_RES_VALID_BIT) { - dev_err(ice_pf_to_dev(pf), "param err: needed=%d, num_entries = %d id=0x%04x\n", - needed, res->num_entries, id); - return -EINVAL; - } - - return ice_search_res(res, needed, id); -} - -/** - * ice_get_vf_ctrl_res - Get VF control VSI resource - * @pf: pointer to the PF structure - * @vsi: the VSI to allocate a resource for - * - * Look up whether another VF has already allocated the control VSI resource. - * If so, re-use this resource so that we share it among all VFs. - * - * Otherwise, allocate the resource and return it. - */ -static int ice_get_vf_ctrl_res(struct ice_pf *pf, struct ice_vsi *vsi) -{ - struct ice_vf *vf; - unsigned int bkt; - int base; - - rcu_read_lock(); - ice_for_each_vf_rcu(pf, bkt, vf) { - if (vf != vsi->vf && vf->ctrl_vsi_idx != ICE_NO_VSI) { - base = pf->vsi[vf->ctrl_vsi_idx]->base_vector; - rcu_read_unlock(); - return base; - } - } - rcu_read_unlock(); - - return ice_get_res(pf, pf->irq_tracker, vsi->num_q_vectors, - ICE_RES_VF_CTRL_VEC_ID); -} - -/** - * ice_vsi_setup_vector_base - Set up the base vector for the given VSI - * @vsi: ptr to the VSI - * - * This should only be called after ice_vsi_alloc_def() which allocates the - * corresponding SW VSI structure and initializes num_queue_pairs for the - * newly allocated VSI. - * - * Returns 0 on success or negative on failure - */ -static int ice_vsi_setup_vector_base(struct ice_vsi *vsi) -{ - struct ice_pf *pf = vsi->back; - struct device *dev; - u16 num_q_vectors; - int base; - - dev = ice_pf_to_dev(pf); - /* SRIOV doesn't grab irq_tracker entries for each VSI */ - if (vsi->type == ICE_VSI_VF) - return 0; - if (vsi->type == ICE_VSI_CHNL) - return 0; - - if (vsi->base_vector) { - dev_dbg(dev, "VSI %d has non-zero base vector %d\n", - vsi->vsi_num, vsi->base_vector); - return -EEXIST; - } - - num_q_vectors = vsi->num_q_vectors; - /* reserve slots from OS requested IRQs */ - if (vsi->type == ICE_VSI_CTRL && vsi->vf) { - base = ice_get_vf_ctrl_res(pf, vsi); - } else { - base = ice_get_res(pf, pf->irq_tracker, num_q_vectors, - vsi->idx); - } - - if (base < 0) { - dev_err(dev, "%d MSI-X interrupts available. %s %d failed to get %d MSI-X vectors\n", - ice_get_free_res_count(pf->irq_tracker), - ice_vsi_type_str(vsi->type), vsi->idx, num_q_vectors); - return -ENOENT; - } - vsi->base_vector = (u16)base; - pf->num_avail_sw_msix -= num_q_vectors; - - return 0; -} - /** * ice_vsi_clear_rings - Deallocates the Tx and Rx rings for VSI * @vsi: the VSI having rings deallocated @@ -2409,50 +2211,6 @@ static void ice_vsi_set_tc_cfg(struct ice_vsi *vsi) ice_vsi_set_dcb_tc_cfg(vsi); } -/** - * ice_vsi_set_q_vectors_reg_idx - set the HW register index for all q_vectors - * @vsi: VSI to set the q_vectors register index on - */ -static int -ice_vsi_set_q_vectors_reg_idx(struct ice_vsi *vsi) -{ - u16 i; - - if (!vsi || !vsi->q_vectors) - return -EINVAL; - - ice_for_each_q_vector(vsi, i) { - struct ice_q_vector *q_vector = vsi->q_vectors[i]; - - if (!q_vector) { - dev_err(ice_pf_to_dev(vsi->back), "Failed to set reg_idx on q_vector %d VSI %d\n", - i, vsi->vsi_num); - goto clear_reg_idx; - } - - if (vsi->type == ICE_VSI_VF) { - struct ice_vf *vf = vsi->vf; - - q_vector->reg_idx = ice_calc_vf_reg_idx(vf, q_vector); - } else { - q_vector->reg_idx = - q_vector->v_idx + vsi->base_vector; - } - } - - return 0; - -clear_reg_idx: - ice_for_each_q_vector(vsi, i) { - struct ice_q_vector *q_vector = vsi->q_vectors[i]; - - if (q_vector) - q_vector->reg_idx = 0; - } - - return -EINVAL; -} - /** * ice_cfg_sw_lldp - Config switch rules for LLDP packet handling * @vsi: the VSI being configured @@ -2611,37 +2369,6 @@ static void ice_set_agg_vsi(struct ice_vsi *vsi) vsi->agg_node->num_vsis); } -/** - * ice_free_vf_ctrl_res - Free the VF control VSI resource - * @pf: pointer to PF structure - * @vsi: the VSI to free resources for - * - * Check if the VF control VSI resource is still in use. If no VF is using it - * any more, release the VSI resource. Otherwise, leave it to be cleaned up - * once no other VF uses it. - */ -static void ice_free_vf_ctrl_res(struct ice_pf *pf, struct ice_vsi *vsi) -{ - struct ice_vf *vf; - unsigned int bkt; - - rcu_read_lock(); - ice_for_each_vf_rcu(pf, bkt, vf) { - if (vf != vsi->vf && vf->ctrl_vsi_idx != ICE_NO_VSI) { - rcu_read_unlock(); - return; - } - } - rcu_read_unlock(); - - /* No other VFs left that have control VSI. It is now safe to reclaim - * SW interrupts back to the common pool. - */ - ice_free_res(pf->irq_tracker, vsi->base_vector, - ICE_RES_VF_CTRL_VEC_ID); - pf->num_avail_sw_msix += vsi->num_q_vectors; -} - static int ice_vsi_cfg_tc_lan(struct ice_pf *pf, struct ice_vsi *vsi) { u16 max_txqs[ICE_MAX_TRAFFIC_CLASS] = { 0 }; @@ -2728,14 +2455,6 @@ ice_vsi_cfg_def(struct ice_vsi *vsi, struct ice_vsi_cfg_params *params) if (ret) goto unroll_vsi_init; - ret = ice_vsi_setup_vector_base(vsi); - if (ret) - goto unroll_alloc_q_vector; - - ret = ice_vsi_set_q_vectors_reg_idx(vsi); - if (ret) - goto unroll_vector_base; - ret = ice_vsi_alloc_rings(vsi); if (ret) goto unroll_vector_base; @@ -2788,10 +2507,6 @@ ice_vsi_cfg_def(struct ice_vsi *vsi, struct ice_vsi_cfg_params *params) if (ret) goto unroll_alloc_q_vector; - ret = ice_vsi_set_q_vectors_reg_idx(vsi); - if (ret) - goto unroll_vector_base; - ret = ice_vsi_alloc_ring_stats(vsi); if (ret) goto unroll_vector_base; @@ -2827,8 +2542,6 @@ ice_vsi_cfg_def(struct ice_vsi *vsi, struct ice_vsi_cfg_params *params) unroll_vector_base: /* reclaim SW interrupts back to the common pool */ - ice_free_res(pf->irq_tracker, vsi->base_vector, vsi->idx); - pf->num_avail_sw_msix += vsi->num_q_vectors; unroll_alloc_q_vector: ice_vsi_free_q_vectors(vsi); unroll_vsi_init: @@ -2920,14 +2633,6 @@ void ice_vsi_decfg(struct ice_vsi *vsi) * many interrupts each VF needs. SR-IOV MSIX resources are also * cleared in the same manner. */ - if (vsi->type == ICE_VSI_CTRL && vsi->vf) { - ice_free_vf_ctrl_res(pf, vsi); - } else if (vsi->type != ICE_VSI_VF) { - /* reclaim SW interrupts back to the common pool */ - ice_free_res(pf->irq_tracker, vsi->base_vector, vsi->idx); - pf->num_avail_sw_msix += vsi->num_q_vectors; - vsi->base_vector = 0; - } if (vsi->type == ICE_VSI_VF && vsi->agg_node && vsi->agg_node->valid) @@ -2993,8 +2698,6 @@ ice_vsi_setup(struct ice_pf *pf, struct ice_vsi_cfg_params *params) return vsi; err_vsi_cfg: - if (params->type == ICE_VSI_VF) - ice_enable_lag(pf->lag); ice_vsi_free(vsi); return NULL; @@ -3044,7 +2747,6 @@ static void ice_vsi_release_msix(struct ice_vsi *vsi) void ice_vsi_free_irq(struct ice_vsi *vsi) { struct ice_pf *pf = vsi->back; - int base = vsi->base_vector; int i; if (!vsi->q_vectors || !vsi->irqs_ready) @@ -3058,10 +2760,9 @@ void ice_vsi_free_irq(struct ice_vsi *vsi) ice_free_cpu_rx_rmap(vsi); ice_for_each_q_vector(vsi, i) { - u16 vector = i + base; int irq_num; - irq_num = pf->msix_entries[vector].vector; + irq_num = vsi->q_vectors[i]->irq.virq; /* free only the irqs that were actually requested */ if (!vsi->q_vectors[i] || @@ -3193,7 +2894,6 @@ void ice_dis_vsi(struct ice_vsi *vsi, bool locked) */ void ice_vsi_dis_irq(struct ice_vsi *vsi) { - int base = vsi->base_vector; struct ice_pf *pf = vsi->back; struct ice_hw *hw = &pf->hw; u32 val; @@ -3240,7 +2940,7 @@ void ice_vsi_dis_irq(struct ice_vsi *vsi) return; ice_for_each_q_vector(vsi, i) - synchronize_irq(pf->msix_entries[i + base].vector); + synchronize_irq(vsi->q_vectors[i]->irq.virq); } /** diff --git a/drivers/net/ethernet/intel/ice/ice_lib.h b/drivers/net/ethernet/intel/ice/ice_lib.h index 75221478f2dc04a670d3e02e48106f5bf088c42c..e985766e6bb5fcedb0c6edd2beda7623996c97a4 100644 --- a/drivers/net/ethernet/intel/ice/ice_lib.h +++ b/drivers/net/ethernet/intel/ice/ice_lib.h @@ -104,11 +104,6 @@ int ice_ena_vsi(struct ice_vsi *vsi, bool locked); void ice_vsi_decfg(struct ice_vsi *vsi); void ice_dis_vsi(struct ice_vsi *vsi, bool locked); -int ice_free_res(struct ice_res_tracker *res, u16 index, u16 id); - -int -ice_get_res(struct ice_pf *pf, struct ice_res_tracker *res, u16 needed, u16 id); - int ice_vsi_rebuild(struct ice_vsi *vsi, u32 vsi_flags); int ice_vsi_cfg(struct ice_vsi *vsi, struct ice_vsi_cfg_params *params); diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c index 42c318ceff61837495c33fa4e19ecc3db0e9bf63..19a5e7f3a075ee3c1a4462b1a826f63c33eb3db4 100644 --- a/drivers/net/ethernet/intel/ice/ice_main.c +++ b/drivers/net/ethernet/intel/ice/ice_main.c @@ -2490,7 +2490,6 @@ static int ice_vsi_req_irq_msix(struct ice_vsi *vsi, char *basename) { int q_vectors = vsi->num_q_vectors; struct ice_pf *pf = vsi->back; - int base = vsi->base_vector; struct device *dev; int rx_int_idx = 0; int tx_int_idx = 0; @@ -2501,7 +2500,7 @@ static int ice_vsi_req_irq_msix(struct ice_vsi *vsi, char *basename) for (vector = 0; vector < q_vectors; vector++) { struct ice_q_vector *q_vector = vsi->q_vectors[vector]; - irq_num = pf->msix_entries[base + vector].vector; + irq_num = q_vector->irq.virq; if (q_vector->tx.tx_ring && q_vector->rx.rx_ring) { snprintf(q_vector->name, sizeof(q_vector->name) - 1, @@ -2555,9 +2554,8 @@ static int ice_vsi_req_irq_msix(struct ice_vsi *vsi, char *basename) return 0; free_q_irqs: - while (vector) { - vector--; - irq_num = pf->msix_entries[base + vector].vector; + while (vector--) { + irq_num = vsi->q_vectors[vector]->irq.virq; if (!IS_ENABLED(CONFIG_RFS_ACCEL)) irq_set_affinity_notifier(irq_num, NULL); irq_set_affinity_hint(irq_num, NULL); @@ -2635,11 +2633,11 @@ static void ice_vsi_assign_bpf_prog(struct ice_vsi *vsi, struct bpf_prog *prog) int i; old_prog = xchg(&vsi->xdp_prog, prog); - if (old_prog) - bpf_prog_put(old_prog); - ice_for_each_rxq(vsi, i) WRITE_ONCE(vsi->rx_rings[i]->xdp_prog, vsi->xdp_prog); + + if (old_prog) + bpf_prog_put(old_prog); } /** @@ -2924,6 +2922,12 @@ ice_xdp_setup_prog(struct ice_vsi *vsi, struct bpf_prog *prog, } } + /* hot swap progs and avoid toggling link */ + if (ice_is_xdp_ena_vsi(vsi) == !!prog) { + ice_vsi_assign_bpf_prog(vsi, prog); + return 0; + } + /* need to stop netdev while setting up the program for Rx rings */ if (if_running && !test_and_set_bit(ICE_VSI_DOWN, vsi->state)) { ret = ice_down(vsi); @@ -2956,13 +2960,6 @@ ice_xdp_setup_prog(struct ice_vsi *vsi, struct bpf_prog *prog, xdp_ring_err = ice_realloc_zc_buf(vsi, false); if (xdp_ring_err) NL_SET_ERR_MSG_MOD(extack, "Freeing XDP Rx resources failed"); - } else { - /* safe to call even when prog == vsi->xdp_prog as - * dev_xdp_install in net/core/dev.c incremented prog's - * refcount so corresponding bpf_prog_put won't cause - * underflow - */ - ice_vsi_assign_bpf_prog(vsi, prog); } if (if_running) @@ -3047,7 +3044,7 @@ static void ice_ena_misc_vector(struct ice_pf *pf) wr32(hw, PFINT_OICR_ENA, val); /* SW_ITR_IDX = 0, but don't change INTENA */ - wr32(hw, GLINT_DYN_CTL(pf->oicr_idx), + wr32(hw, GLINT_DYN_CTL(pf->oicr_irq.index), GLINT_DYN_CTL_SW_ITR_INDX_M | GLINT_DYN_CTL_INTENA_MSK_M); } @@ -3060,7 +3057,6 @@ static irqreturn_t ice_misc_intr(int __always_unused irq, void *data) { struct ice_pf *pf = (struct ice_pf *)data; struct ice_hw *hw = &pf->hw; - irqreturn_t ret = IRQ_NONE; struct device *dev; u32 oicr, ena_mask; @@ -3142,19 +3138,24 @@ static irqreturn_t ice_misc_intr(int __always_unused irq, void *data) if (oicr & PFINT_OICR_TSYN_TX_M) { ena_mask &= ~PFINT_OICR_TSYN_TX_M; if (!hw->reset_ongoing) - ret = IRQ_WAKE_THREAD; + set_bit(ICE_MISC_THREAD_TX_TSTAMP, pf->misc_thread); } if (oicr & PFINT_OICR_TSYN_EVNT_M) { u8 tmr_idx = hw->func_caps.ts_func_info.tmr_index_owned; u32 gltsyn_stat = rd32(hw, GLTSYN_STAT(tmr_idx)); - /* Save EVENTs from GTSYN register */ - pf->ptp.ext_ts_irq |= gltsyn_stat & (GLTSYN_STAT_EVENT0_M | - GLTSYN_STAT_EVENT1_M | - GLTSYN_STAT_EVENT2_M); ena_mask &= ~PFINT_OICR_TSYN_EVNT_M; - kthread_queue_work(pf->ptp.kworker, &pf->ptp.extts_work); + + if (hw->func_caps.ts_func_info.src_tmr_owned) { + /* Save EVENTs from GLTSYN register */ + pf->ptp.ext_ts_irq |= gltsyn_stat & + (GLTSYN_STAT_EVENT0_M | + GLTSYN_STAT_EVENT1_M | + GLTSYN_STAT_EVENT2_M); + + set_bit(ICE_MISC_THREAD_EXTTS_EVENT, pf->misc_thread); + } } #define ICE_AUX_CRIT_ERR (PFINT_OICR_PE_CRITERR_M | PFINT_OICR_HMC_ERR_M | PFINT_OICR_PE_PUSH_M) @@ -3174,16 +3175,10 @@ static irqreturn_t ice_misc_intr(int __always_unused irq, void *data) if (oicr & (PFINT_OICR_PCI_EXCEPTION_M | PFINT_OICR_ECC_ERR_M)) { set_bit(ICE_PFR_REQ, pf->state); - ice_service_task_schedule(pf); } } - if (!ret) - ret = IRQ_HANDLED; - - ice_service_task_schedule(pf); - ice_irq_dynamic_ena(hw, NULL, NULL); - return ret; + return IRQ_WAKE_THREAD; } /** @@ -3194,12 +3189,29 @@ static irqreturn_t ice_misc_intr(int __always_unused irq, void *data) static irqreturn_t ice_misc_intr_thread_fn(int __always_unused irq, void *data) { struct ice_pf *pf = data; + struct ice_hw *hw; + + hw = &pf->hw; if (ice_is_reset_in_progress(pf->state)) return IRQ_HANDLED; - while (!ice_ptp_process_ts(pf)) - usleep_range(50, 100); + ice_service_task_schedule(pf); + + if (test_and_clear_bit(ICE_MISC_THREAD_EXTTS_EVENT, pf->misc_thread)) + ice_ptp_extts_event(pf); + + if (test_and_clear_bit(ICE_MISC_THREAD_TX_TSTAMP, pf->misc_thread)) { + /* Process outstanding Tx timestamps. If there is more work, + * re-arm the interrupt to trigger again. + */ + if (ice_ptp_process_ts(pf) == ICE_TX_TSTAMP_WORK_PENDING) { + wr32(hw, PFINT_OICR, PFINT_OICR_TSYN_TX_M); + ice_flush(hw); + } + } + + ice_irq_dynamic_ena(hw, NULL, NULL); return IRQ_HANDLED; } @@ -3234,6 +3246,7 @@ static void ice_dis_ctrlq_interrupts(struct ice_hw *hw) */ static void ice_free_irq_msix_misc(struct ice_pf *pf) { + int misc_irq_num = pf->oicr_irq.virq; struct ice_hw *hw = &pf->hw; ice_dis_ctrlq_interrupts(hw); @@ -3242,14 +3255,10 @@ static void ice_free_irq_msix_misc(struct ice_pf *pf) wr32(hw, PFINT_OICR_ENA, 0); ice_flush(hw); - if (pf->msix_entries) { - synchronize_irq(pf->msix_entries[pf->oicr_idx].vector); - devm_free_irq(ice_pf_to_dev(pf), - pf->msix_entries[pf->oicr_idx].vector, pf); - } + synchronize_irq(misc_irq_num); + devm_free_irq(ice_pf_to_dev(pf), misc_irq_num, pf); - pf->num_avail_sw_msix += 1; - ice_free_res(pf->irq_tracker, pf->oicr_idx, ICE_RES_MISC_VEC_ID); + ice_free_irq(pf, pf->oicr_irq); } /** @@ -3295,7 +3304,8 @@ static int ice_req_irq_msix_misc(struct ice_pf *pf) { struct device *dev = ice_pf_to_dev(pf); struct ice_hw *hw = &pf->hw; - int oicr_idx, err = 0; + struct msi_map oicr_irq; + int err = 0; if (!pf->int_name[0]) snprintf(pf->int_name, sizeof(pf->int_name) - 1, "%s-%s:misc", @@ -3309,30 +3319,26 @@ static int ice_req_irq_msix_misc(struct ice_pf *pf) goto skip_req_irq; /* reserve one vector in irq_tracker for misc interrupts */ - oicr_idx = ice_get_res(pf, pf->irq_tracker, 1, ICE_RES_MISC_VEC_ID); - if (oicr_idx < 0) - return oicr_idx; - - pf->num_avail_sw_msix -= 1; - pf->oicr_idx = (u16)oicr_idx; - - err = devm_request_threaded_irq(dev, - pf->msix_entries[pf->oicr_idx].vector, - ice_misc_intr, ice_misc_intr_thread_fn, - 0, pf->int_name, pf); + oicr_irq = ice_alloc_irq(pf, false); + if (oicr_irq.index < 0) + return oicr_irq.index; + + pf->oicr_irq = oicr_irq; + err = devm_request_threaded_irq(dev, pf->oicr_irq.virq, ice_misc_intr, + ice_misc_intr_thread_fn, 0, + pf->int_name, pf); if (err) { dev_err(dev, "devm_request_threaded_irq for %s failed: %d\n", pf->int_name, err); - ice_free_res(pf->irq_tracker, 1, ICE_RES_MISC_VEC_ID); - pf->num_avail_sw_msix += 1; + ice_free_irq(pf, pf->oicr_irq); return err; } skip_req_irq: ice_ena_misc_vector(pf); - ice_ena_ctrlq_interrupts(hw, pf->oicr_idx); - wr32(hw, GLINT_ITR(ICE_RX_ITR, pf->oicr_idx), + ice_ena_ctrlq_interrupts(hw, pf->oicr_irq.index); + wr32(hw, GLINT_ITR(ICE_RX_ITR, pf->oicr_irq.index), ITR_REG_ALIGN(ICE_ITR_8K) >> ICE_ITR_GRAN_S); ice_flush(hw); @@ -3900,224 +3906,6 @@ static int ice_init_pf(struct ice_pf *pf) return 0; } -/** - * ice_reduce_msix_usage - Reduce usage of MSI-X vectors - * @pf: board private structure - * @v_remain: number of remaining MSI-X vectors to be distributed - * - * Reduce the usage of MSI-X vectors when entire request cannot be fulfilled. - * pf->num_lan_msix and pf->num_rdma_msix values are set based on number of - * remaining vectors. - */ -static void ice_reduce_msix_usage(struct ice_pf *pf, int v_remain) -{ - int v_rdma; - - if (!ice_is_rdma_ena(pf)) { - pf->num_lan_msix = v_remain; - return; - } - - /* RDMA needs at least 1 interrupt in addition to AEQ MSIX */ - v_rdma = ICE_RDMA_NUM_AEQ_MSIX + 1; - - if (v_remain < ICE_MIN_LAN_TXRX_MSIX + ICE_MIN_RDMA_MSIX) { - dev_warn(ice_pf_to_dev(pf), "Not enough MSI-X vectors to support RDMA.\n"); - clear_bit(ICE_FLAG_RDMA_ENA, pf->flags); - - pf->num_rdma_msix = 0; - pf->num_lan_msix = ICE_MIN_LAN_TXRX_MSIX; - } else if ((v_remain < ICE_MIN_LAN_TXRX_MSIX + v_rdma) || - (v_remain - v_rdma < v_rdma)) { - /* Support minimum RDMA and give remaining vectors to LAN MSIX */ - pf->num_rdma_msix = ICE_MIN_RDMA_MSIX; - pf->num_lan_msix = v_remain - ICE_MIN_RDMA_MSIX; - } else { - /* Split remaining MSIX with RDMA after accounting for AEQ MSIX - */ - pf->num_rdma_msix = (v_remain - ICE_RDMA_NUM_AEQ_MSIX) / 2 + - ICE_RDMA_NUM_AEQ_MSIX; - pf->num_lan_msix = v_remain - pf->num_rdma_msix; - } -} - -/** - * ice_ena_msix_range - Request a range of MSIX vectors from the OS - * @pf: board private structure - * - * Compute the number of MSIX vectors wanted and request from the OS. Adjust - * device usage if there are not enough vectors. Return the number of vectors - * reserved or negative on failure. - */ -static int ice_ena_msix_range(struct ice_pf *pf) -{ - int num_cpus, hw_num_msix, v_other, v_wanted, v_actual; - struct device *dev = ice_pf_to_dev(pf); - int err, i; - - hw_num_msix = pf->hw.func_caps.common_cap.num_msix_vectors; - num_cpus = num_online_cpus(); - - /* LAN miscellaneous handler */ - v_other = ICE_MIN_LAN_OICR_MSIX; - - /* Flow Director */ - if (test_bit(ICE_FLAG_FD_ENA, pf->flags)) - v_other += ICE_FDIR_MSIX; - - /* switchdev */ - v_other += ICE_ESWITCH_MSIX; - - v_wanted = v_other; - - /* LAN traffic */ - pf->num_lan_msix = num_cpus; - v_wanted += pf->num_lan_msix; - - /* RDMA auxiliary driver */ - if (ice_is_rdma_ena(pf)) { - pf->num_rdma_msix = num_cpus + ICE_RDMA_NUM_AEQ_MSIX; - v_wanted += pf->num_rdma_msix; - } - - if (v_wanted > hw_num_msix) { - int v_remain; - - dev_warn(dev, "not enough device MSI-X vectors. wanted = %d, available = %d\n", - v_wanted, hw_num_msix); - - if (hw_num_msix < ICE_MIN_MSIX) { - err = -ERANGE; - goto exit_err; - } - - v_remain = hw_num_msix - v_other; - if (v_remain < ICE_MIN_LAN_TXRX_MSIX) { - v_other = ICE_MIN_MSIX - ICE_MIN_LAN_TXRX_MSIX; - v_remain = ICE_MIN_LAN_TXRX_MSIX; - } - - ice_reduce_msix_usage(pf, v_remain); - v_wanted = pf->num_lan_msix + pf->num_rdma_msix + v_other; - - dev_notice(dev, "Reducing request to %d MSI-X vectors for LAN traffic.\n", - pf->num_lan_msix); - if (ice_is_rdma_ena(pf)) - dev_notice(dev, "Reducing request to %d MSI-X vectors for RDMA.\n", - pf->num_rdma_msix); - } - - pf->msix_entries = devm_kcalloc(dev, v_wanted, - sizeof(*pf->msix_entries), GFP_KERNEL); - if (!pf->msix_entries) { - err = -ENOMEM; - goto exit_err; - } - - for (i = 0; i < v_wanted; i++) - pf->msix_entries[i].entry = i; - - /* actually reserve the vectors */ - v_actual = pci_enable_msix_range(pf->pdev, pf->msix_entries, - ICE_MIN_MSIX, v_wanted); - if (v_actual < 0) { - dev_err(dev, "unable to reserve MSI-X vectors\n"); - err = v_actual; - goto msix_err; - } - - if (v_actual < v_wanted) { - dev_warn(dev, "not enough OS MSI-X vectors. requested = %d, obtained = %d\n", - v_wanted, v_actual); - - if (v_actual < ICE_MIN_MSIX) { - /* error if we can't get minimum vectors */ - pci_disable_msix(pf->pdev); - err = -ERANGE; - goto msix_err; - } else { - int v_remain = v_actual - v_other; - - if (v_remain < ICE_MIN_LAN_TXRX_MSIX) - v_remain = ICE_MIN_LAN_TXRX_MSIX; - - ice_reduce_msix_usage(pf, v_remain); - - dev_notice(dev, "Enabled %d MSI-X vectors for LAN traffic.\n", - pf->num_lan_msix); - - if (ice_is_rdma_ena(pf)) - dev_notice(dev, "Enabled %d MSI-X vectors for RDMA.\n", - pf->num_rdma_msix); - } - } - - return v_actual; - -msix_err: - devm_kfree(dev, pf->msix_entries); - -exit_err: - pf->num_rdma_msix = 0; - pf->num_lan_msix = 0; - return err; -} - -/** - * ice_dis_msix - Disable MSI-X interrupt setup in OS - * @pf: board private structure - */ -static void ice_dis_msix(struct ice_pf *pf) -{ - pci_disable_msix(pf->pdev); - devm_kfree(ice_pf_to_dev(pf), pf->msix_entries); - pf->msix_entries = NULL; -} - -/** - * ice_clear_interrupt_scheme - Undo things done by ice_init_interrupt_scheme - * @pf: board private structure - */ -static void ice_clear_interrupt_scheme(struct ice_pf *pf) -{ - ice_dis_msix(pf); - - if (pf->irq_tracker) { - devm_kfree(ice_pf_to_dev(pf), pf->irq_tracker); - pf->irq_tracker = NULL; - } -} - -/** - * ice_init_interrupt_scheme - Determine proper interrupt scheme - * @pf: board private structure to initialize - */ -static int ice_init_interrupt_scheme(struct ice_pf *pf) -{ - int vectors; - - vectors = ice_ena_msix_range(pf); - - if (vectors < 0) - return vectors; - - /* set up vector assignment tracking */ - pf->irq_tracker = devm_kzalloc(ice_pf_to_dev(pf), - struct_size(pf->irq_tracker, list, vectors), - GFP_KERNEL); - if (!pf->irq_tracker) { - ice_dis_msix(pf); - return -ENOMEM; - } - - /* populate SW interrupts pool with number of OS granted IRQs. */ - pf->num_avail_sw_msix = (u16)vectors; - pf->irq_tracker->num_entries = (u16)vectors; - pf->irq_tracker->end = pf->irq_tracker->num_entries; - - return 0; -} - /** * ice_is_wol_supported - check if WoL is supported * @hw: pointer to hardware info @@ -5835,11 +5623,6 @@ static int ice_set_mac_address(struct net_device *netdev, void *pi) if (!is_valid_ether_addr(mac)) return -EADDRNOTAVAIL; - if (ether_addr_equal(netdev->dev_addr, mac)) { - netdev_dbg(netdev, "already using mac %pM\n", mac); - return 0; - } - if (test_bit(ICE_DOWN, pf->state) || ice_is_reset_in_progress(pf->state)) { netdev_err(netdev, "can't set mac %pM. device not ready\n", @@ -5956,6 +5739,13 @@ ice_set_tx_maxrate(struct net_device *netdev, int queue_index, u32 maxrate) q_handle = vsi->tx_rings[queue_index]->q_handle; tc = ice_dcb_get_tc(vsi, queue_index); + vsi = ice_locate_vsi_using_queue(vsi, queue_index); + if (!vsi) { + netdev_err(netdev, "Invalid VSI for given queue %d\n", + queue_index); + return -EINVAL; + } + /* Set BW back to default, when user set maxrate to 0 */ if (!maxrate) status = ice_cfg_q_bw_dflt_lmt(vsi->port_info, vsi->idx, tc, @@ -7629,21 +7419,9 @@ static int ice_change_mtu(struct net_device *netdev, int new_mtu) } netdev->mtu = (unsigned int)new_mtu; - - /* if VSI is up, bring it down and then back up */ - if (!test_and_set_bit(ICE_VSI_DOWN, vsi->state)) { - err = ice_down(vsi); - if (err) { - netdev_err(netdev, "change MTU if_down err %d\n", err); - return err; - } - - err = ice_up(vsi); - if (err) { - netdev_err(netdev, "change MTU if_up err %d\n", err); - return err; - } - } + err = ice_down_up(vsi); + if (err) + return err; netdev_dbg(netdev, "changed MTU to %d\n", new_mtu); set_bit(ICE_FLAG_MTU_CHANGED, pf->flags); @@ -8101,10 +7879,10 @@ static int ice_validate_mqprio_qopt(struct ice_vsi *vsi, struct tc_mqprio_qopt_offload *mqprio_qopt) { - u64 sum_max_rate = 0, sum_min_rate = 0; int non_power_of_2_qcount = 0; struct ice_pf *pf = vsi->back; int max_rss_q_cnt = 0; + u64 sum_min_rate = 0; struct device *dev; int i, speed; u8 num_tc; @@ -8120,6 +7898,7 @@ ice_validate_mqprio_qopt(struct ice_vsi *vsi, dev = ice_pf_to_dev(pf); vsi->ch_rss_size = 0; num_tc = mqprio_qopt->qopt.num_tc; + speed = ice_get_link_speed_kbps(vsi); for (i = 0; num_tc; i++) { int qcount = mqprio_qopt->qopt.count[i]; @@ -8160,7 +7939,6 @@ ice_validate_mqprio_qopt(struct ice_vsi *vsi, */ max_rate = mqprio_qopt->max_rate[i]; max_rate = div_u64(max_rate, ICE_BW_KBPS_DIVISOR); - sum_max_rate += max_rate; /* min_rate is minimum guaranteed rate and it can't be zero */ min_rate = mqprio_qopt->min_rate[i]; @@ -8173,6 +7951,12 @@ ice_validate_mqprio_qopt(struct ice_vsi *vsi, return -EINVAL; } + if (max_rate && max_rate > speed) { + dev_err(dev, "TC%d: max_rate(%llu Kbps) > link speed of %u Kbps\n", + i, max_rate, speed); + return -EINVAL; + } + iter_div_u64_rem(min_rate, ICE_MIN_BW_LIMIT, &rem); if (rem) { dev_err(dev, "TC%d: Min Rate not multiple of %u Kbps", @@ -8210,12 +7994,6 @@ ice_validate_mqprio_qopt(struct ice_vsi *vsi, (mqprio_qopt->qopt.offset[i] + mqprio_qopt->qopt.count[i])) return -EINVAL; - speed = ice_get_link_speed_kbps(vsi); - if (sum_max_rate && sum_max_rate > (u64)speed) { - dev_err(dev, "Invalid max Tx rate(%llu) Kbps > speed(%u) Kbps specified\n", - sum_max_rate, speed); - return -EINVAL; - } if (sum_min_rate && sum_min_rate > (u64)speed) { dev_err(dev, "Invalid min Tx rate(%llu) Kbps > speed (%u) Kbps specified\n", sum_min_rate, speed); diff --git a/drivers/net/ethernet/intel/ice/ice_protocol_type.h b/drivers/net/ethernet/intel/ice/ice_protocol_type.h index 02a4e1cf624e9ab80f9b0119cf160eede1b1232c..6a9364761165d28186e8873ba7c156352c760696 100644 --- a/drivers/net/ethernet/intel/ice/ice_protocol_type.h +++ b/drivers/net/ethernet/intel/ice/ice_protocol_type.h @@ -47,6 +47,7 @@ enum ice_protocol_type { ICE_L2TPV3, ICE_VLAN_EX, ICE_VLAN_IN, + ICE_HW_METADATA, ICE_VXLAN_GPE, ICE_SCTP_IL, ICE_PROTOCOL_LAST @@ -115,17 +116,7 @@ enum ice_prot_id { #define ICE_L2TPV3_HW 104 #define ICE_UDP_OF_HW 52 /* UDP Tunnels */ -#define ICE_META_DATA_ID_HW 255 /* this is used for tunnel and VLAN type */ -#define ICE_MDID_SIZE 2 - -#define ICE_TUN_FLAG_MDID 21 -#define ICE_TUN_FLAG_MDID_OFF (ICE_MDID_SIZE * ICE_TUN_FLAG_MDID) -#define ICE_TUN_FLAG_MASK 0xFF - -#define ICE_VLAN_FLAG_MDID 20 -#define ICE_VLAN_FLAG_MDID_OFF (ICE_MDID_SIZE * ICE_VLAN_FLAG_MDID) -#define ICE_PKT_FLAGS_0_TO_15_VLAN_FLAGS_MASK 0xD000 #define ICE_TUN_FLAG_FV_IND 2 @@ -230,6 +221,191 @@ struct ice_nvgre_hdr { __be32 tni_flow; }; +/* Metadata information + * + * Not all MDIDs can be used by switch block. It depends on package version. + * + * MDID 16 (Rx offset) + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | A | B | Reserved | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * A = Source port where the transaction came from (3b). + * + * B = Destination TC of the packet. The TC is relative to a port (5b). + * + * MDID 17 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | PTYPE | Reserved | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * PTYPE = Encodes the packet type (10b). + * + * MDID 18 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Packet length | R | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * Packet length = Length of the packet in bytes + * (packet always carriers CRC) (14b). + * R = Reserved (2b). + * + * MDID 19 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Source VSI | Reserved | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * Source VSI = Source VSI of packet loopbacked in switch (for egress) (10b). + */ +#define ICE_MDID_SOURCE_VSI_MASK GENMASK(9, 0) + +/* + * MDID 20 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |A|B|C|D|E|F|R|R|G|H|I|J|K|L|M|N| + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * A = DSI - set for DSI RX pkts. + * B = ipsec_decrypted - invalid on NIC. + * C = marker - this is a marker packet. + * D = from_network - for TX sets to 0 + * for RX: + * * 1 - packet is from external link + * * 0 - packet source is from internal + * E = source_interface_is_rx - reflect the physical interface from where the + * packet was received: + * * 1 - Rx + * * 0 - Tx + * F = from_mng - The bit signals that the packet's origin is the management. + * G = ucast - Outer L2 MAC address is unicast. + * H = mcast - Outer L2 MAC address is multicast. + * I = bcast - Outer L2 MAC address is broadcast. + * J = second_outer_mac_present - 2 outer MAC headers are present in the packet. + * K = STAG or BVLAN - Outer L2 header has STAG (ethernet type 0x88a8) or + * BVLAN (ethernet type 0x88a8). + * L = ITAG - Outer L2 header has ITAG *ethernet type 0x88e7) + * M = EVLAN (0x8100) - Outer L2 header has EVLAN (ethernet type 0x8100) + * N = EVLAN (0x9100) - Outer L2 header has EVLAN (ethernet type 0x9100) + */ +#define ICE_PKT_VLAN_STAG BIT(12) +#define ICE_PKT_VLAN_ITAG BIT(13) +#define ICE_PKT_VLAN_EVLAN (BIT(14) | BIT(15)) +#define ICE_PKT_VLAN_MASK (ICE_PKT_VLAN_STAG | ICE_PKT_VLAN_ITAG | \ + ICE_PKT_VLAN_EVLAN) +/* MDID 21 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |A|B|C|D|E|F|G|H|I|J|R|R|K|L|M|N| + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * A = VLAN (0x8100) - Outer L2 header has VLAN (ethernet type 0x8100) + * B = NSHoE - Outer L2 header has NSH (ethernet type 0x894f) + * C = MPLS (0x8847) - There is at least 1 MPLS tag in the outer header + * (ethernet type 0x8847) + * D = MPLS (0x8848) - There is at least 1 MPLS tag in the outer header + * (ethernet type 0x8848) + * E = multi MPLS - There is more than a single MPLS tag in the outer header + * F = inner MPLS - There is inner MPLS tag in the packet + * G = tunneled MAC - Set if the packet includes a tunneled MAC + * H = tunneled VLAN - Same as VLAN, but for a tunneled header + * I = pkt_is_frag - Packet is fragmented (ipv4 or ipv6) + * J = ipv6_ext - The packet has routing or destination ipv6 extension in inner + * or outer ipv6 headers + * K = RoCE - UDP packet detected as RoCEv2 + * L = UDP_XSUM_0 - Set to 1 if L4 checksum is 0 in a UDP packet + * M = ESP - This is a ESP packet + * N = NAT_ESP - This is a ESP packet encapsulated in UDP NAT + */ +#define ICE_PKT_TUNNEL_MAC BIT(6) +#define ICE_PKT_TUNNEL_VLAN BIT(7) +#define ICE_PKT_TUNNEL_MASK (ICE_PKT_TUNNEL_MAC | ICE_PKT_TUNNEL_VLAN) + +/* MDID 22 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |A|B|C|D|E|F| G |H|I|J| K |L|M| + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * A = fin - fin flag in tcp header + * B = sync - sync flag in tcp header + * C = rst - rst flag in tcp header + * D = psh - psh flag in tcp header + * E = ack - ack flag in tcp header + * F = urg - urg flag in tcp header + * G = tunnel type (3b) - Flags used to decode tunnel type: + * * b000 - not a VXLAN/Geneve/GRE tunnel + * * b001 - VXLAN-GPE + * * b010 - VXLAN (non-GPE) + * * b011 - Geneve + * * b100 - GRE (no key, no xsum) + * * b101 - GREK (key, no xsum) + * * b110 - GREC (no key, xsum) + * * b111 - GREKC (key, xsum) + * H = UDP_GRE - Packet is UDP (VXLAN or VLAN_GPE or Geneve or MPLSoUDP or GRE) + * tunnel + * I = OAM - VXLAN/Geneve/tunneled NSH packet with the OAM bit set + * J = tunneled NSH - Packet has NSHoGRE or NSHoUDP + * K = switch (2b) - Direction on switch + * * b00 - normal + * * b01 - TX force only LAN + * * b10 - TX disable LAN + * * b11 - direct to VSI + * L = swpe - Represents SWPE bit in TX command + * M = sw_cmd - Switch command + * + * MDID 23 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |A|B|C|D| R |E|F|R| + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * A = MAC error - Produced by MAC according to L2 error conditions + * B = PPRS no offload - FIFO overflow in PPRS or any problematic condition in + * PPRS ANA + * C = abort - Set when malicious packet is detected + * D = partial analysis - ANA's analysing got cut in the middle + * (header > 504B etc.) + * E = FLM - Flow director hit indication + * F = FDLONG - Flow direector long bucket indication + * + */ +#define ICE_MDID_SIZE 2 +#define ICE_META_DATA_ID_HW 255 + +enum ice_hw_metadata_id { + ICE_SOURCE_PORT_MDID = 16, + ICE_PTYPE_MDID = 17, + ICE_PACKET_LENGTH_MDID = 18, + ICE_SOURCE_VSI_MDID = 19, + ICE_PKT_VLAN_MDID = 20, + ICE_PKT_TUNNEL_MDID = 21, + ICE_PKT_TCP_MDID = 22, + ICE_PKT_ERROR_MDID = 23, +}; + +enum ice_hw_metadata_offset { + ICE_SOURCE_PORT_MDID_OFFSET = ICE_MDID_SIZE * ICE_SOURCE_PORT_MDID, + ICE_PTYPE_MDID_OFFSET = ICE_MDID_SIZE * ICE_PTYPE_MDID, + ICE_PACKET_LENGTH_MDID_OFFSET = ICE_MDID_SIZE * ICE_PACKET_LENGTH_MDID, + ICE_SOURCE_VSI_MDID_OFFSET = ICE_MDID_SIZE * ICE_SOURCE_VSI_MDID, + ICE_PKT_VLAN_MDID_OFFSET = ICE_MDID_SIZE * ICE_PKT_VLAN_MDID, + ICE_PKT_TUNNEL_MDID_OFFSET = ICE_MDID_SIZE * ICE_PKT_TUNNEL_MDID, + ICE_PKT_TCP_MDID_OFFSET = ICE_MDID_SIZE * ICE_PKT_TCP_MDID, + ICE_PKT_ERROR_MDID_OFFSET = ICE_MDID_SIZE * ICE_PKT_ERROR_MDID, +}; + +enum ice_pkt_flags { + ICE_PKT_FLAGS_VLAN = 0, + ICE_PKT_FLAGS_TUNNEL = 1, + ICE_PKT_FLAGS_TCP = 2, + ICE_PKT_FLAGS_ERROR = 3, +}; + +struct ice_hw_metadata { + __be16 source_port; + __be16 ptype; + __be16 packet_length; + __be16 source_vsi; + __be16 flags[4]; +}; + union ice_prot_hdr { struct ice_ether_hdr eth_hdr; struct ice_ethtype_hdr ethertype; @@ -243,6 +419,7 @@ union ice_prot_hdr { struct ice_udp_gtp_hdr gtp_hdr; struct ice_pppoe_hdr pppoe_hdr; struct ice_l2tpv3_sess_hdr l2tpv3_sess_hdr; + struct ice_hw_metadata metadata; }; /* This is mapping table entry that maps every word within a given protocol diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c b/drivers/net/ethernet/intel/ice/ice_ptp.c index ac6f06f9a2ed06149a1180db22d8a5c42d21dd29..81d96a40d5a74306372b594128eb39c7a049bba6 100644 --- a/drivers/net/ethernet/intel/ice/ice_ptp.c +++ b/drivers/net/ethernet/intel/ice/ice_ptp.c @@ -617,7 +617,7 @@ ice_ptp_is_tx_tracker_up(struct ice_ptp_tx *tx) } /** - * ice_ptp_tx_tstamp - Process Tx timestamps for a port + * ice_ptp_process_tx_tstamp - Process Tx timestamps for a port * @tx: the PTP Tx timestamp tracker * * Process timestamps captured by the PHY associated with this port. To do @@ -633,15 +633,6 @@ ice_ptp_is_tx_tracker_up(struct ice_ptp_tx *tx) * 6) extend the 40 bit timestamp value to get a 64 bit timestamp value * 7) send this 64 bit timestamp to the stack * - * Returns true if all timestamps were handled, and false if any slots remain - * without a timestamp. - * - * After looping, if we still have waiting SKBs, return false. This may cause - * us effectively poll even when not strictly necessary. We do this because - * it's possible a new timestamp was requested around the same time as the - * interrupt. In some cases hardware might not interrupt us again when the - * timestamp is captured. - * * Note that we do not hold the tracking lock while reading the Tx timestamp. * This is because reading the timestamp requires taking a mutex that might * sleep. @@ -673,10 +664,9 @@ ice_ptp_is_tx_tracker_up(struct ice_ptp_tx *tx) * the packet will never be sent by hardware and discard it without reading * the timestamp register. */ -static bool ice_ptp_tx_tstamp(struct ice_ptp_tx *tx) +static void ice_ptp_process_tx_tstamp(struct ice_ptp_tx *tx) { struct ice_ptp_port *ptp_port; - bool more_timestamps; struct ice_pf *pf; struct ice_hw *hw; u64 tstamp_ready; @@ -685,7 +675,7 @@ static bool ice_ptp_tx_tstamp(struct ice_ptp_tx *tx) u8 idx; if (!tx->init) - return true; + return; ptp_port = container_of(tx, struct ice_ptp_port, tx); pf = ptp_port_to_pf(ptp_port); @@ -694,7 +684,7 @@ static bool ice_ptp_tx_tstamp(struct ice_ptp_tx *tx) /* Read the Tx ready status first */ err = ice_get_phy_tx_tstamp_ready(hw, tx->block, &tstamp_ready); if (err) - return false; + return; /* Drop packets if the link went down */ link_up = ptp_port->link_up; @@ -782,15 +772,34 @@ static bool ice_ptp_tx_tstamp(struct ice_ptp_tx *tx) skb_tstamp_tx(skb, &shhwtstamps); dev_kfree_skb_any(skb); } +} - /* Check if we still have work to do. If so, re-queue this task to - * poll for remaining timestamps. - */ +/** + * ice_ptp_tx_tstamp - Process Tx timestamps for this function. + * @tx: Tx tracking structure to initialize + * + * Returns: ICE_TX_TSTAMP_WORK_PENDING if there are any outstanding incomplete + * Tx timestamps, or ICE_TX_TSTAMP_WORK_DONE otherwise. + */ +static enum ice_tx_tstamp_work ice_ptp_tx_tstamp(struct ice_ptp_tx *tx) +{ + bool more_timestamps; + + if (!tx->init) + return ICE_TX_TSTAMP_WORK_DONE; + + /* Process the Tx timestamp tracker */ + ice_ptp_process_tx_tstamp(tx); + + /* Check if there are outstanding Tx timestamps */ spin_lock(&tx->lock); more_timestamps = tx->init && !bitmap_empty(tx->in_use, tx->len); spin_unlock(&tx->lock); - return !more_timestamps; + if (more_timestamps) + return ICE_TX_TSTAMP_WORK_PENDING; + + return ICE_TX_TSTAMP_WORK_DONE; } /** @@ -911,7 +920,7 @@ ice_ptp_release_tx_tracker(struct ice_pf *pf, struct ice_ptp_tx *tx) spin_unlock(&tx->lock); /* wait for potentially outstanding interrupt to complete */ - synchronize_irq(pf->msix_entries[pf->oicr_idx].vector); + synchronize_irq(pf->oicr_irq.virq); ice_ptp_flush_tx_tracker(pf, tx); @@ -1458,15 +1467,11 @@ static int ice_ptp_adjfine(struct ptp_clock_info *info, long scaled_ppm) } /** - * ice_ptp_extts_work - Workqueue task function - * @work: external timestamp work structure - * - * Service for PTP external clock event + * ice_ptp_extts_event - Process PTP external clock event + * @pf: Board private structure */ -static void ice_ptp_extts_work(struct kthread_work *work) +void ice_ptp_extts_event(struct ice_pf *pf) { - struct ice_ptp *ptp = container_of(work, struct ice_ptp, extts_work); - struct ice_pf *pf = container_of(ptp, struct ice_pf, ptp); struct ptp_clock_event event; struct ice_hw *hw = &pf->hw; u8 chan, tmr_idx; @@ -2430,9 +2435,10 @@ s8 ice_ptp_request_ts(struct ice_ptp_tx *tx, struct sk_buff *skb) * ice_ptp_process_ts - Process the PTP Tx timestamps * @pf: Board private structure * - * Returns true if timestamps are processed. + * Returns: ICE_TX_TSTAMP_WORK_PENDING if there are any outstanding Tx + * timestamps that need processing, and ICE_TX_TSTAMP_WORK_DONE otherwise. */ -bool ice_ptp_process_ts(struct ice_pf *pf) +enum ice_tx_tstamp_work ice_ptp_process_ts(struct ice_pf *pf) { return ice_ptp_tx_tstamp(&pf->ptp.port.tx); } @@ -2558,7 +2564,6 @@ void ice_ptp_prepare_for_reset(struct ice_pf *pf) ice_ptp_cfg_timestamp(pf, false); kthread_cancel_delayed_work_sync(&ptp->work); - kthread_cancel_work_sync(&ptp->extts_work); if (test_bit(ICE_PFR_REQ, pf->state)) return; @@ -2656,7 +2661,6 @@ static int ice_ptp_init_work(struct ice_pf *pf, struct ice_ptp *ptp) /* Initialize work functions */ kthread_init_delayed_work(&ptp->work, ice_ptp_periodic_work); - kthread_init_work(&ptp->extts_work, ice_ptp_extts_work); /* Allocate a kworker for handling work required for the ports * connected to the PTP hardware clock. diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.h b/drivers/net/ethernet/intel/ice/ice_ptp.h index 9cda2f43e0e562c89291d803d4f43859c67a7394..995a57019ba767ce9349c182a51019308d3afb84 100644 --- a/drivers/net/ethernet/intel/ice/ice_ptp.h +++ b/drivers/net/ethernet/intel/ice/ice_ptp.h @@ -108,6 +108,16 @@ struct ice_tx_tstamp { u64 cached_tstamp; }; +/** + * enum ice_tx_tstamp_work - Status of Tx timestamp work function + * @ICE_TX_TSTAMP_WORK_DONE: Tx timestamp processing is complete + * @ICE_TX_TSTAMP_WORK_PENDING: More Tx timestamps are pending + */ +enum ice_tx_tstamp_work { + ICE_TX_TSTAMP_WORK_DONE = 0, + ICE_TX_TSTAMP_WORK_PENDING, +}; + /** * struct ice_ptp_tx - Tracking structure for all Tx timestamp requests on a port * @lock: lock to prevent concurrent access to fields of this struct @@ -169,7 +179,6 @@ struct ice_ptp_port { * struct ice_ptp - data used for integrating with CONFIG_PTP_1588_CLOCK * @port: data for the PHY port initialization procedure * @work: delayed work function for periodic tasks - * @extts_work: work function for handling external Tx timestamps * @cached_phc_time: a cached copy of the PHC time for timestamp extension * @cached_phc_jiffies: jiffies when cached_phc_time was last updated * @ext_ts_chan: the external timestamp channel in use @@ -190,7 +199,6 @@ struct ice_ptp_port { struct ice_ptp { struct ice_ptp_port port; struct kthread_delayed_work work; - struct kthread_work extts_work; u64 cached_phc_time; unsigned long cached_phc_jiffies; u8 ext_ts_chan; @@ -256,8 +264,9 @@ int ice_ptp_get_ts_config(struct ice_pf *pf, struct ifreq *ifr); void ice_ptp_cfg_timestamp(struct ice_pf *pf, bool ena); int ice_get_ptp_clock_index(struct ice_pf *pf); +void ice_ptp_extts_event(struct ice_pf *pf); s8 ice_ptp_request_ts(struct ice_ptp_tx *tx, struct sk_buff *skb); -bool ice_ptp_process_ts(struct ice_pf *pf); +enum ice_tx_tstamp_work ice_ptp_process_ts(struct ice_pf *pf); void ice_ptp_rx_hwtstamp(struct ice_rx_ring *rx_ring, @@ -284,6 +293,7 @@ static inline int ice_get_ptp_clock_index(struct ice_pf *pf) return -1; } +static inline void ice_ptp_extts_event(struct ice_pf *pf) { } static inline s8 ice_ptp_request_ts(struct ice_ptp_tx *tx, struct sk_buff *skb) { diff --git a/drivers/net/ethernet/intel/ice/ice_repr.c b/drivers/net/ethernet/intel/ice/ice_repr.c index fd1f8b0ad0ab45796fd3af7eec43b1b8b6b4db0f..e30e12321abd4553da6587c39f60e6dd272038f3 100644 --- a/drivers/net/ethernet/intel/ice/ice_repr.c +++ b/drivers/net/ethernet/intel/ice/ice_repr.c @@ -298,14 +298,6 @@ static int ice_repr_add(struct ice_vf *vf) if (!repr) return -ENOMEM; -#ifdef CONFIG_ICE_SWITCHDEV - repr->mac_rule = kzalloc(sizeof(*repr->mac_rule), GFP_KERNEL); - if (!repr->mac_rule) { - err = -ENOMEM; - goto err_alloc_rule; - } -#endif - repr->netdev = alloc_etherdev(sizeof(struct ice_netdev_priv)); if (!repr->netdev) { err = -ENOMEM; @@ -351,11 +343,6 @@ static int ice_repr_add(struct ice_vf *vf) free_netdev(repr->netdev); repr->netdev = NULL; err_alloc: -#ifdef CONFIG_ICE_SWITCHDEV - kfree(repr->mac_rule); - repr->mac_rule = NULL; -err_alloc_rule: -#endif kfree(repr); vf->repr = NULL; return err; @@ -376,10 +363,6 @@ static void ice_repr_rem(struct ice_vf *vf) ice_devlink_destroy_vf_port(vf); free_netdev(vf->repr->netdev); vf->repr->netdev = NULL; -#ifdef CONFIG_ICE_SWITCHDEV - kfree(vf->repr->mac_rule); - vf->repr->mac_rule = NULL; -#endif kfree(vf->repr); vf->repr = NULL; diff --git a/drivers/net/ethernet/intel/ice/ice_repr.h b/drivers/net/ethernet/intel/ice/ice_repr.h index 378a45bfa25646f966f2f4421b260c9bd2eba4f1..9c2a6f496b3b9750adcaaa35613ed025361cffa4 100644 --- a/drivers/net/ethernet/intel/ice/ice_repr.h +++ b/drivers/net/ethernet/intel/ice/ice_repr.h @@ -13,9 +13,8 @@ struct ice_repr { struct net_device *netdev; struct metadata_dst *dst; #ifdef CONFIG_ICE_SWITCHDEV - /* info about slow path MAC rule */ - struct ice_rule_query_data *mac_rule; - u8 rule_added; + /* info about slow path rule */ + struct ice_rule_query_data sp_rule; #endif }; diff --git a/drivers/net/ethernet/intel/ice/ice_sched.c b/drivers/net/ethernet/intel/ice/ice_sched.c index b7682de0ae0578c19ac16b9bb373d8d4004f9d9e..b664d60fd037e33171cf7bbc28aef5309e44f9ce 100644 --- a/drivers/net/ethernet/intel/ice/ice_sched.c +++ b/drivers/net/ethernet/intel/ice/ice_sched.c @@ -358,10 +358,7 @@ void ice_free_sched_node(struct ice_port_info *pi, struct ice_sched_node *node) node->sibling; } - /* leaf nodes have no children */ - if (node->children) - devm_kfree(ice_hw_to_dev(hw), node->children); - + devm_kfree(ice_hw_to_dev(hw), node->children); kfree(node->name); xa_erase(&pi->sched_node_ids, node->id); devm_kfree(ice_hw_to_dev(hw), node); @@ -859,10 +856,8 @@ void ice_sched_cleanup_all(struct ice_hw *hw) if (!hw) return; - if (hw->layer_info) { - devm_kfree(ice_hw_to_dev(hw), hw->layer_info); - hw->layer_info = NULL; - } + devm_kfree(ice_hw_to_dev(hw), hw->layer_info); + hw->layer_info = NULL; ice_sched_clear_port(hw->port_info); diff --git a/drivers/net/ethernet/intel/ice/ice_sriov.c b/drivers/net/ethernet/intel/ice/ice_sriov.c index 588ad8696756defb6154022fe4fc9b7c75eed366..1f66914c7a202a3c7825307935c6b4968fd1ed1d 100644 --- a/drivers/net/ethernet/intel/ice/ice_sriov.c +++ b/drivers/net/ethernet/intel/ice/ice_sriov.c @@ -135,18 +135,9 @@ static void ice_dis_vf_mappings(struct ice_vf *vf) */ static int ice_sriov_free_msix_res(struct ice_pf *pf) { - struct ice_res_tracker *res; - if (!pf) return -EINVAL; - res = pf->irq_tracker; - if (!res) - return -EINVAL; - - /* give back irq_tracker resources used */ - WARN_ON(pf->sriov_base_vector < res->num_entries); - pf->sriov_base_vector = 0; return 0; @@ -409,29 +400,6 @@ int ice_calc_vf_reg_idx(struct ice_vf *vf, struct ice_q_vector *q_vector) q_vector->v_idx + 1; } -/** - * ice_get_max_valid_res_idx - Get the max valid resource index - * @res: pointer to the resource to find the max valid index for - * - * Start from the end of the ice_res_tracker and return right when we find the - * first res->list entry with the ICE_RES_VALID_BIT set. This function is only - * valid for SR-IOV because it is the only consumer that manipulates the - * res->end and this is always called when res->end is set to res->num_entries. - */ -static int ice_get_max_valid_res_idx(struct ice_res_tracker *res) -{ - int i; - - if (!res) - return -EINVAL; - - for (i = res->num_entries - 1; i >= 0; i--) - if (res->list[i] & ICE_RES_VALID_BIT) - return i; - - return 0; -} - /** * ice_sriov_set_msix_res - Set any used MSIX resources * @pf: pointer to PF structure @@ -450,7 +418,7 @@ static int ice_get_max_valid_res_idx(struct ice_res_tracker *res) static int ice_sriov_set_msix_res(struct ice_pf *pf, u16 num_msix_needed) { u16 total_vectors = pf->hw.func_caps.common_cap.num_msix_vectors; - int vectors_used = pf->irq_tracker->num_entries; + int vectors_used = ice_get_max_used_msix_vector(pf); int sriov_base_vector; sriov_base_vector = total_vectors - num_msix_needed; @@ -490,7 +458,7 @@ static int ice_sriov_set_msix_res(struct ice_pf *pf, u16 num_msix_needed) */ static int ice_set_per_vf_res(struct ice_pf *pf, u16 num_vfs) { - int max_valid_res_idx = ice_get_max_valid_res_idx(pf->irq_tracker); + int vectors_used = ice_get_max_used_msix_vector(pf); u16 num_msix_per_vf, num_txq, num_rxq, avail_qs; int msix_avail_per_vf, msix_avail_for_sriov; struct device *dev = ice_pf_to_dev(pf); @@ -501,12 +469,9 @@ static int ice_set_per_vf_res(struct ice_pf *pf, u16 num_vfs) if (!num_vfs) return -EINVAL; - if (max_valid_res_idx < 0) - return -ENOSPC; - /* determine MSI-X resources per VF */ msix_avail_for_sriov = pf->hw.func_caps.common_cap.num_msix_vectors - - pf->irq_tracker->num_entries; + vectors_used; msix_avail_per_vf = msix_avail_for_sriov / num_vfs; if (msix_avail_per_vf >= ICE_NUM_VF_MSIX_MED) { num_msix_per_vf = ICE_NUM_VF_MSIX_MED; @@ -871,7 +836,7 @@ static int ice_ena_vfs(struct ice_pf *pf, u16 num_vfs) int ret; /* Disable global interrupt 0 so we don't try to handle the VFLR. */ - wr32(hw, GLINT_DYN_CTL(pf->oicr_idx), + wr32(hw, GLINT_DYN_CTL(pf->oicr_irq.index), ICE_ITR_NONE << GLINT_DYN_CTL_ITR_INDX_S); set_bit(ICE_OICR_INTR_DIS, pf->state); ice_flush(hw); @@ -940,14 +905,13 @@ static int ice_ena_vfs(struct ice_pf *pf, u16 num_vfs) */ static int ice_pci_sriov_ena(struct ice_pf *pf, int num_vfs) { - int pre_existing_vfs = pci_num_vf(pf->pdev); struct device *dev = ice_pf_to_dev(pf); int err; - if (pre_existing_vfs && pre_existing_vfs != num_vfs) + if (!num_vfs) { ice_free_vfs(pf); - else if (pre_existing_vfs && pre_existing_vfs == num_vfs) return 0; + } if (num_vfs > pf->vfs.num_supported) { dev_err(dev, "Can't enable %d VFs, max VFs supported is %d\n", @@ -1014,8 +978,6 @@ int ice_sriov_configure(struct pci_dev *pdev, int num_vfs) if (!num_vfs) { if (!pci_vfs_assigned(pdev)) { ice_free_vfs(pf); - if (pf->lag) - ice_enable_lag(pf->lag); return 0; } @@ -1027,8 +989,6 @@ int ice_sriov_configure(struct pci_dev *pdev, int num_vfs) if (err) return err; - if (pf->lag) - ice_disable_lag(pf->lag); return num_vfs; } diff --git a/drivers/net/ethernet/intel/ice/ice_switch.c b/drivers/net/ethernet/intel/ice/ice_switch.c index 46b36851af460e2f39e0685f3d7043cda0eec351..6db4ca7978cbb67d86beaf6d38f2dd30f5f21f99 100644 --- a/drivers/net/ethernet/intel/ice/ice_switch.c +++ b/drivers/net/ethernet/intel/ice/ice_switch.c @@ -1636,21 +1636,16 @@ ice_save_vsi_ctx(struct ice_hw *hw, u16 vsi_handle, struct ice_vsi_ctx *vsi) */ static void ice_clear_vsi_q_ctx(struct ice_hw *hw, u16 vsi_handle) { - struct ice_vsi_ctx *vsi; + struct ice_vsi_ctx *vsi = ice_get_vsi_ctx(hw, vsi_handle); u8 i; - vsi = ice_get_vsi_ctx(hw, vsi_handle); if (!vsi) return; ice_for_each_traffic_class(i) { - if (vsi->lan_q_ctx[i]) { - devm_kfree(ice_hw_to_dev(hw), vsi->lan_q_ctx[i]); - vsi->lan_q_ctx[i] = NULL; - } - if (vsi->rdma_q_ctx[i]) { - devm_kfree(ice_hw_to_dev(hw), vsi->rdma_q_ctx[i]); - vsi->rdma_q_ctx[i] = NULL; - } + devm_kfree(ice_hw_to_dev(hw), vsi->lan_q_ctx[i]); + vsi->lan_q_ctx[i] = NULL; + devm_kfree(ice_hw_to_dev(hw), vsi->rdma_q_ctx[i]); + vsi->rdma_q_ctx[i] = NULL; } } @@ -4540,6 +4535,11 @@ ice_free_res_cntr(struct ice_hw *hw, u8 type, u8 alloc_shared, u16 num_items, return status; } +#define ICE_PROTOCOL_ENTRY(id, ...) { \ + .prot_type = id, \ + .offs = {__VA_ARGS__}, \ +} + /* This is mapping table entry that maps every word within a given protocol * structure to the real byte offset as per the specification of that * protocol header. @@ -4550,29 +4550,38 @@ ice_free_res_cntr(struct ice_hw *hw, u8 type, u8 alloc_shared, u16 num_items, * structure is added to that union. */ static const struct ice_prot_ext_tbl_entry ice_prot_ext[ICE_PROTOCOL_LAST] = { - { ICE_MAC_OFOS, { 0, 2, 4, 6, 8, 10, 12 } }, - { ICE_MAC_IL, { 0, 2, 4, 6, 8, 10, 12 } }, - { ICE_ETYPE_OL, { 0 } }, - { ICE_ETYPE_IL, { 0 } }, - { ICE_VLAN_OFOS, { 2, 0 } }, - { ICE_IPV4_OFOS, { 0, 2, 4, 6, 8, 10, 12, 14, 16, 18 } }, - { ICE_IPV4_IL, { 0, 2, 4, 6, 8, 10, 12, 14, 16, 18 } }, - { ICE_IPV6_OFOS, { 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, - 26, 28, 30, 32, 34, 36, 38 } }, - { ICE_IPV6_IL, { 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, - 26, 28, 30, 32, 34, 36, 38 } }, - { ICE_TCP_IL, { 0, 2 } }, - { ICE_UDP_OF, { 0, 2 } }, - { ICE_UDP_ILOS, { 0, 2 } }, - { ICE_VXLAN, { 8, 10, 12, 14 } }, - { ICE_GENEVE, { 8, 10, 12, 14 } }, - { ICE_NVGRE, { 0, 2, 4, 6 } }, - { ICE_GTP, { 8, 10, 12, 14, 16, 18, 20, 22 } }, - { ICE_GTP_NO_PAY, { 8, 10, 12, 14 } }, - { ICE_PPPOE, { 0, 2, 4, 6 } }, - { ICE_L2TPV3, { 0, 2, 4, 6, 8, 10 } }, - { ICE_VLAN_EX, { 2, 0 } }, - { ICE_VLAN_IN, { 2, 0 } }, + ICE_PROTOCOL_ENTRY(ICE_MAC_OFOS, 0, 2, 4, 6, 8, 10, 12), + ICE_PROTOCOL_ENTRY(ICE_MAC_IL, 0, 2, 4, 6, 8, 10, 12), + ICE_PROTOCOL_ENTRY(ICE_ETYPE_OL, 0), + ICE_PROTOCOL_ENTRY(ICE_ETYPE_IL, 0), + ICE_PROTOCOL_ENTRY(ICE_VLAN_OFOS, 2, 0), + ICE_PROTOCOL_ENTRY(ICE_IPV4_OFOS, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18), + ICE_PROTOCOL_ENTRY(ICE_IPV4_IL, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18), + ICE_PROTOCOL_ENTRY(ICE_IPV6_OFOS, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, + 20, 22, 24, 26, 28, 30, 32, 34, 36, 38), + ICE_PROTOCOL_ENTRY(ICE_IPV6_IL, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, + 22, 24, 26, 28, 30, 32, 34, 36, 38), + ICE_PROTOCOL_ENTRY(ICE_TCP_IL, 0, 2), + ICE_PROTOCOL_ENTRY(ICE_UDP_OF, 0, 2), + ICE_PROTOCOL_ENTRY(ICE_UDP_ILOS, 0, 2), + ICE_PROTOCOL_ENTRY(ICE_VXLAN, 8, 10, 12, 14), + ICE_PROTOCOL_ENTRY(ICE_GENEVE, 8, 10, 12, 14), + ICE_PROTOCOL_ENTRY(ICE_NVGRE, 0, 2, 4, 6), + ICE_PROTOCOL_ENTRY(ICE_GTP, 8, 10, 12, 14, 16, 18, 20, 22), + ICE_PROTOCOL_ENTRY(ICE_GTP_NO_PAY, 8, 10, 12, 14), + ICE_PROTOCOL_ENTRY(ICE_PPPOE, 0, 2, 4, 6), + ICE_PROTOCOL_ENTRY(ICE_L2TPV3, 0, 2, 4, 6, 8, 10), + ICE_PROTOCOL_ENTRY(ICE_VLAN_EX, 2, 0), + ICE_PROTOCOL_ENTRY(ICE_VLAN_IN, 2, 0), + ICE_PROTOCOL_ENTRY(ICE_HW_METADATA, + ICE_SOURCE_PORT_MDID_OFFSET, + ICE_PTYPE_MDID_OFFSET, + ICE_PACKET_LENGTH_MDID_OFFSET, + ICE_SOURCE_VSI_MDID_OFFSET, + ICE_PKT_VLAN_MDID_OFFSET, + ICE_PKT_TUNNEL_MDID_OFFSET, + ICE_PKT_TCP_MDID_OFFSET, + ICE_PKT_ERROR_MDID_OFFSET), }; static struct ice_protocol_entry ice_prot_id_tbl[ICE_PROTOCOL_LAST] = { @@ -4597,6 +4606,7 @@ static struct ice_protocol_entry ice_prot_id_tbl[ICE_PROTOCOL_LAST] = { { ICE_L2TPV3, ICE_L2TPV3_HW }, { ICE_VLAN_EX, ICE_VLAN_OF_HW }, { ICE_VLAN_IN, ICE_VLAN_OL_HW }, + { ICE_HW_METADATA, ICE_META_DATA_ID_HW }, }; /** @@ -5255,71 +5265,6 @@ ice_create_recipe_group(struct ice_hw *hw, struct ice_sw_recipe *rm, return status; } -/** - * ice_tun_type_match_word - determine if tun type needs a match mask - * @tun_type: tunnel type - * @mask: mask to be used for the tunnel - */ -static bool ice_tun_type_match_word(enum ice_sw_tunnel_type tun_type, u16 *mask) -{ - switch (tun_type) { - case ICE_SW_TUN_GENEVE: - case ICE_SW_TUN_VXLAN: - case ICE_SW_TUN_NVGRE: - case ICE_SW_TUN_GTPU: - case ICE_SW_TUN_GTPC: - *mask = ICE_TUN_FLAG_MASK; - return true; - - default: - *mask = 0; - return false; - } -} - -/** - * ice_add_special_words - Add words that are not protocols, such as metadata - * @rinfo: other information regarding the rule e.g. priority and action info - * @lkup_exts: lookup word structure - * @dvm_ena: is double VLAN mode enabled - */ -static int -ice_add_special_words(struct ice_adv_rule_info *rinfo, - struct ice_prot_lkup_ext *lkup_exts, bool dvm_ena) -{ - u16 mask; - - /* If this is a tunneled packet, then add recipe index to match the - * tunnel bit in the packet metadata flags. - */ - if (ice_tun_type_match_word(rinfo->tun_type, &mask)) { - if (lkup_exts->n_val_words < ICE_MAX_CHAIN_WORDS) { - u8 word = lkup_exts->n_val_words++; - - lkup_exts->fv_words[word].prot_id = ICE_META_DATA_ID_HW; - lkup_exts->fv_words[word].off = ICE_TUN_FLAG_MDID_OFF; - lkup_exts->field_mask[word] = mask; - } else { - return -ENOSPC; - } - } - - if (rinfo->vlan_type != 0 && dvm_ena) { - if (lkup_exts->n_val_words < ICE_MAX_CHAIN_WORDS) { - u8 word = lkup_exts->n_val_words++; - - lkup_exts->fv_words[word].prot_id = ICE_META_DATA_ID_HW; - lkup_exts->fv_words[word].off = ICE_VLAN_FLAG_MDID_OFF; - lkup_exts->field_mask[word] = - ICE_PKT_FLAGS_0_TO_15_VLAN_FLAGS_MASK; - } else { - return -ENOSPC; - } - } - - return 0; -} - /* ice_get_compat_fv_bitmap - Get compatible field vector bitmap for rule * @hw: pointer to hardware structure * @rinfo: other information regarding the rule e.g. priority and action info @@ -5433,13 +5378,6 @@ ice_add_adv_recipe(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups, if (status) goto err_unroll; - /* Create any special protocol/offset pairs, such as looking at tunnel - * bits by extracting metadata - */ - status = ice_add_special_words(rinfo, lkup_exts, ice_is_dvm_ena(hw)); - if (status) - goto err_unroll; - /* Group match words into recipes using preferred recipe grouping * criteria. */ @@ -5525,9 +5463,7 @@ ice_add_adv_recipe(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups, devm_kfree(ice_hw_to_dev(hw), fvit); } - if (rm->root_buf) - devm_kfree(ice_hw_to_dev(hw), rm->root_buf); - + devm_kfree(ice_hw_to_dev(hw), rm->root_buf); kfree(rm); err_free_lkup_exts: @@ -5725,6 +5661,10 @@ ice_fill_adv_dummy_packet(struct ice_adv_lkup_elem *lkups, u16 lkups_cnt, * was already checked when search for the dummy packet */ type = lkups[i].type; + /* metadata isn't present in the packet */ + if (type == ICE_HW_METADATA) + continue; + for (j = 0; offsets[j].type != ICE_PROTOCOL_LAST; j++) { if (type == offsets[j].type) { offset = offsets[j].offset; @@ -5860,16 +5800,21 @@ ice_fill_adv_packet_tun(struct ice_hw *hw, enum ice_sw_tunnel_type tun_type, /** * ice_fill_adv_packet_vlan - fill dummy packet with VLAN tag type + * @hw: pointer to hw structure * @vlan_type: VLAN tag type * @pkt: dummy packet to fill in * @offsets: offset info for the dummy packet */ static int -ice_fill_adv_packet_vlan(u16 vlan_type, u8 *pkt, +ice_fill_adv_packet_vlan(struct ice_hw *hw, u16 vlan_type, u8 *pkt, const struct ice_dummy_pkt_offsets *offsets) { u16 i; + /* Check if there is something to do */ + if (!vlan_type || !ice_is_dvm_ena(hw)) + return 0; + /* Find VLAN header and insert VLAN TPID */ for (i = 0; offsets[i].type != ICE_PROTOCOL_LAST; i++) { if (offsets[i].type == ICE_VLAN_OFOS || @@ -5888,6 +5833,15 @@ ice_fill_adv_packet_vlan(u16 vlan_type, u8 *pkt, return -EIO; } +static bool ice_rules_equal(const struct ice_adv_rule_info *first, + const struct ice_adv_rule_info *second) +{ + return first->sw_act.flag == second->sw_act.flag && + first->tun_type == second->tun_type && + first->vlan_type == second->vlan_type && + first->src_vsi == second->src_vsi; +} + /** * ice_find_adv_rule_entry - Search a rule entry * @hw: pointer to the hardware structure @@ -5921,9 +5875,7 @@ ice_find_adv_rule_entry(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups, lkups_matched = false; break; } - if (rinfo->sw_act.flag == list_itr->rule_info.sw_act.flag && - rinfo->tun_type == list_itr->rule_info.tun_type && - rinfo->vlan_type == list_itr->rule_info.vlan_type && + if (ice_rules_equal(rinfo, &list_itr->rule_info) && lkups_matched) return list_itr; } @@ -6039,6 +5991,26 @@ ice_adv_add_update_vsi_list(struct ice_hw *hw, return status; } +void ice_rule_add_tunnel_metadata(struct ice_adv_lkup_elem *lkup) +{ + lkup->type = ICE_HW_METADATA; + lkup->m_u.metadata.flags[ICE_PKT_FLAGS_TUNNEL] = + cpu_to_be16(ICE_PKT_TUNNEL_MASK); +} + +void ice_rule_add_vlan_metadata(struct ice_adv_lkup_elem *lkup) +{ + lkup->type = ICE_HW_METADATA; + lkup->m_u.metadata.flags[ICE_PKT_FLAGS_VLAN] = + cpu_to_be16(ICE_PKT_VLAN_MASK); +} + +void ice_rule_add_src_vsi_metadata(struct ice_adv_lkup_elem *lkup) +{ + lkup->type = ICE_HW_METADATA; + lkup->m_u.metadata.source_vsi = cpu_to_be16(ICE_MDID_SOURCE_VSI_MASK); +} + /** * ice_add_adv_rule - helper function to create an advanced switch rule * @hw: pointer to the hardware structure @@ -6120,7 +6092,10 @@ ice_add_adv_rule(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups, if (rinfo->sw_act.fltr_act == ICE_FWD_TO_VSI) rinfo->sw_act.fwd_id.hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle); - if (rinfo->sw_act.flag & ICE_FLTR_TX) + + if (rinfo->src_vsi) + rinfo->sw_act.src = ice_get_hw_vsi_num(hw, rinfo->src_vsi); + else rinfo->sw_act.src = ice_get_hw_vsi_num(hw, vsi_handle); status = ice_add_adv_recipe(hw, lkups, lkups_cnt, rinfo, &rid); @@ -6189,19 +6164,20 @@ ice_add_adv_rule(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups, goto err_ice_add_adv_rule; } - /* set the rule LOOKUP type based on caller specified 'Rx' - * instead of hardcoding it to be either LOOKUP_TX/RX + /* If there is no matching criteria for direction there + * is only one difference between Rx and Tx: + * - get switch id base on VSI number from source field (Tx) + * - get switch id base on port number (Rx) * - * for 'Rx' set the source to be the port number - * for 'Tx' set the source to be the source HW VSI number (determined - * by caller) + * If matching on direction metadata is chose rule direction is + * extracted from type value set here. */ - if (rinfo->rx) { - s_rule->hdr.type = cpu_to_le16(ICE_AQC_SW_RULES_T_LKUP_RX); - s_rule->src = cpu_to_le16(hw->port_info->lport); - } else { + if (rinfo->sw_act.flag & ICE_FLTR_TX) { s_rule->hdr.type = cpu_to_le16(ICE_AQC_SW_RULES_T_LKUP_TX); s_rule->src = cpu_to_le16(rinfo->sw_act.src); + } else { + s_rule->hdr.type = cpu_to_le16(ICE_AQC_SW_RULES_T_LKUP_RX); + s_rule->src = cpu_to_le16(hw->port_info->lport); } s_rule->recipe_id = cpu_to_le16(rid); @@ -6211,22 +6187,16 @@ ice_add_adv_rule(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups, if (status) goto err_ice_add_adv_rule; - if (rinfo->tun_type != ICE_NON_TUN && - rinfo->tun_type != ICE_SW_TUN_AND_NON_TUN) { - status = ice_fill_adv_packet_tun(hw, rinfo->tun_type, - s_rule->hdr_data, - profile->offsets); - if (status) - goto err_ice_add_adv_rule; - } + status = ice_fill_adv_packet_tun(hw, rinfo->tun_type, s_rule->hdr_data, + profile->offsets); + if (status) + goto err_ice_add_adv_rule; - if (rinfo->vlan_type != 0 && ice_is_dvm_ena(hw)) { - status = ice_fill_adv_packet_vlan(rinfo->vlan_type, - s_rule->hdr_data, - profile->offsets); - if (status) - goto err_ice_add_adv_rule; - } + status = ice_fill_adv_packet_vlan(hw, rinfo->vlan_type, + s_rule->hdr_data, + profile->offsets); + if (status) + goto err_ice_add_adv_rule; status = ice_aq_sw_rules(hw, (struct ice_aqc_sw_rules *)s_rule, rule_buf_sz, 1, ice_aqc_opc_add_sw_rules, @@ -6469,13 +6439,6 @@ ice_rem_adv_rule(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups, return -EIO; } - /* Create any special protocol/offset pairs, such as looking at tunnel - * bits by extracting metadata - */ - status = ice_add_special_words(rinfo, &lkup_exts, ice_is_dvm_ena(hw)); - if (status) - return status; - rid = ice_find_recp(hw, &lkup_exts, rinfo->tun_type); /* If did not find a recipe that match the existing criteria */ if (rid == ICE_MAX_NUM_RECIPES) diff --git a/drivers/net/ethernet/intel/ice/ice_switch.h b/drivers/net/ethernet/intel/ice/ice_switch.h index 68d8e8a6a1896de25941b2aaa911ca809c3811ad..c84b56fe84a5e089a45cf124b739d881cee1a72b 100644 --- a/drivers/net/ethernet/intel/ice/ice_switch.h +++ b/drivers/net/ethernet/intel/ice/ice_switch.h @@ -10,7 +10,6 @@ #define ICE_DFLT_VSI_INVAL 0xff #define ICE_FLTR_RX BIT(0) #define ICE_FLTR_TX BIT(1) -#define ICE_FLTR_TX_RX (ICE_FLTR_RX | ICE_FLTR_TX) #define ICE_VSI_INVAL_ID 0xffff #define ICE_INVAL_Q_HANDLE 0xFFFF @@ -187,12 +186,13 @@ struct ice_adv_rule_flags_info { }; struct ice_adv_rule_info { + /* Store metadata values in rule info */ enum ice_sw_tunnel_type tun_type; - struct ice_sw_act_ctrl sw_act; - u32 priority; - u8 rx; /* true means LOOKUP_RX otherwise LOOKUP_TX */ - u16 fltr_rule_id; u16 vlan_type; + u16 fltr_rule_id; + u32 priority; + u16 src_vsi; + struct ice_sw_act_ctrl sw_act; struct ice_adv_rule_flags_info flags_info; }; @@ -342,6 +342,9 @@ ice_free_res_cntr(struct ice_hw *hw, u8 type, u8 alloc_shared, u16 num_items, u16 counter_id); /* Switch/bridge related commands */ +void ice_rule_add_tunnel_metadata(struct ice_adv_lkup_elem *lkup); +void ice_rule_add_vlan_metadata(struct ice_adv_lkup_elem *lkup); +void ice_rule_add_src_vsi_metadata(struct ice_adv_lkup_elem *lkup); int ice_add_adv_rule(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups, u16 lkups_cnt, struct ice_adv_rule_info *rinfo, diff --git a/drivers/net/ethernet/intel/ice/ice_tc_lib.c b/drivers/net/ethernet/intel/ice/ice_tc_lib.c index d1a31f236d26adcf1cca3e18a81332a926357eec..4a34ef5f58d36bd5600b9449cd41e8d26ecbcfa8 100644 --- a/drivers/net/ethernet/intel/ice/ice_tc_lib.c +++ b/drivers/net/ethernet/intel/ice/ice_tc_lib.c @@ -54,6 +54,10 @@ ice_tc_count_lkups(u32 flags, struct ice_tc_flower_lyr_2_4_hdrs *headers, if (flags & (ICE_TC_FLWR_FIELD_VLAN | ICE_TC_FLWR_FIELD_VLAN_PRIO)) lkups_cnt++; + /* is VLAN TPID specified */ + if (flags & ICE_TC_FLWR_FIELD_VLAN_TPID) + lkups_cnt++; + /* is CVLAN specified? */ if (flags & (ICE_TC_FLWR_FIELD_CVLAN | ICE_TC_FLWR_FIELD_CVLAN_PRIO)) lkups_cnt++; @@ -80,6 +84,10 @@ ice_tc_count_lkups(u32 flags, struct ice_tc_flower_lyr_2_4_hdrs *headers, ICE_TC_FLWR_FIELD_SRC_L4_PORT)) lkups_cnt++; + /* matching for tunneled packets in metadata */ + if (fltr->tunnel_type != TNL_LAST) + lkups_cnt++; + return lkups_cnt; } @@ -320,6 +328,10 @@ ice_tc_fill_tunnel_outer(u32 flags, struct ice_tc_flower_fltr *fltr, i++; } + /* always fill matching on tunneled packets in metadata */ + ice_rule_add_tunnel_metadata(&list[i]); + i++; + return i; } @@ -390,10 +402,6 @@ ice_tc_fill_rules(struct ice_hw *hw, u32 flags, /* copy VLAN info */ if (flags & (ICE_TC_FLWR_FIELD_VLAN | ICE_TC_FLWR_FIELD_VLAN_PRIO)) { - vlan_tpid = be16_to_cpu(headers->vlan_hdr.vlan_tpid); - rule_info->vlan_type = - ice_check_supported_vlan_tpid(vlan_tpid); - if (flags & ICE_TC_FLWR_FIELD_CVLAN) list[i].type = ICE_VLAN_EX; else @@ -418,6 +426,15 @@ ice_tc_fill_rules(struct ice_hw *hw, u32 flags, i++; } + if (flags & ICE_TC_FLWR_FIELD_VLAN_TPID) { + vlan_tpid = be16_to_cpu(headers->vlan_hdr.vlan_tpid); + rule_info->vlan_type = + ice_check_supported_vlan_tpid(vlan_tpid); + + ice_rule_add_vlan_metadata(&list[i]); + i++; + } + if (flags & (ICE_TC_FLWR_FIELD_CVLAN | ICE_TC_FLWR_FIELD_CVLAN_PRIO)) { list[i].type = ICE_VLAN_IN; @@ -698,12 +715,10 @@ ice_eswitch_add_tc_fltr(struct ice_vsi *vsi, struct ice_tc_flower_fltr *fltr) if (fltr->direction == ICE_ESWITCH_FLTR_INGRESS) { rule_info.sw_act.flag |= ICE_FLTR_RX; rule_info.sw_act.src = hw->pf_id; - rule_info.rx = true; rule_info.flags_info.act = ICE_SINGLE_ACT_LB_ENABLE; } else { rule_info.sw_act.flag |= ICE_FLTR_TX; rule_info.sw_act.src = vsi->idx; - rule_info.rx = false; rule_info.flags_info.act = ICE_SINGLE_ACT_LAN_ENABLE; } @@ -735,17 +750,16 @@ ice_eswitch_add_tc_fltr(struct ice_vsi *vsi, struct ice_tc_flower_fltr *fltr) /** * ice_locate_vsi_using_queue - locate VSI using queue (forward to queue action) * @vsi: Pointer to VSI - * @tc_fltr: Pointer to tc_flower_filter + * @queue: Queue index * - * Locate the VSI using specified queue. When ADQ is not enabled, always - * return input VSI, otherwise locate corresponding VSI based on per channel - * offset and qcount + * Locate the VSI using specified "queue". When ADQ is not enabled, + * always return input VSI, otherwise locate corresponding + * VSI based on per channel "offset" and "qcount" */ -static struct ice_vsi * -ice_locate_vsi_using_queue(struct ice_vsi *vsi, - struct ice_tc_flower_fltr *tc_fltr) +struct ice_vsi * +ice_locate_vsi_using_queue(struct ice_vsi *vsi, int queue) { - int num_tc, tc, queue; + int num_tc, tc; /* if ADQ is not active, passed VSI is the candidate VSI */ if (!ice_is_adq_active(vsi->back)) @@ -755,7 +769,6 @@ ice_locate_vsi_using_queue(struct ice_vsi *vsi, * upon queue number) */ num_tc = vsi->mqprio_qopt.qopt.num_tc; - queue = tc_fltr->action.fwd.q.queue; for (tc = 0; tc < num_tc; tc++) { int qcount = vsi->mqprio_qopt.qopt.count[tc]; @@ -797,6 +810,7 @@ ice_tc_forward_action(struct ice_vsi *vsi, struct ice_tc_flower_fltr *tc_fltr) struct ice_pf *pf = vsi->back; struct device *dev; u32 tc_class; + int q; dev = ice_pf_to_dev(pf); @@ -825,7 +839,8 @@ ice_tc_forward_action(struct ice_vsi *vsi, struct ice_tc_flower_fltr *tc_fltr) /* Determine destination VSI even though the action is * FWD_TO_QUEUE, because QUEUE is associated with VSI */ - dest_vsi = tc_fltr->dest_vsi; + q = tc_fltr->action.fwd.q.queue; + dest_vsi = ice_locate_vsi_using_queue(vsi, q); break; default: dev_err(dev, @@ -910,7 +925,6 @@ ice_add_tc_flower_adv_fltr(struct ice_vsi *vsi, rule_info.sw_act.vsi_handle = dest_vsi->idx; rule_info.priority = ICE_SWITCH_FLTR_PRIO_VSI; rule_info.sw_act.src = hw->pf_id; - rule_info.rx = true; dev_dbg(dev, "add switch rule for TC:%u vsi_idx:%u, lkups_cnt:%u\n", tc_fltr->action.fwd.tc.tc_class, rule_info.sw_act.vsi_handle, lkups_cnt); @@ -921,7 +935,6 @@ ice_add_tc_flower_adv_fltr(struct ice_vsi *vsi, rule_info.sw_act.vsi_handle = dest_vsi->idx; rule_info.priority = ICE_SWITCH_FLTR_PRIO_QUEUE; rule_info.sw_act.src = hw->pf_id; - rule_info.rx = true; dev_dbg(dev, "add switch rule action to forward to queue:%u (HW queue %u), lkups_cnt:%u\n", tc_fltr->action.fwd.q.queue, tc_fltr->action.fwd.q.hw_queue, lkups_cnt); @@ -929,7 +942,6 @@ ice_add_tc_flower_adv_fltr(struct ice_vsi *vsi, case ICE_DROP_PACKET: rule_info.sw_act.flag |= ICE_FLTR_RX; rule_info.sw_act.src = hw->pf_id; - rule_info.rx = true; rule_info.priority = ICE_SWITCH_FLTR_PRIO_VSI; break; default: @@ -1460,8 +1472,10 @@ ice_parse_cls_flower(struct net_device *filter_dev, struct ice_vsi *vsi, VLAN_PRIO_MASK); } - if (match.mask->vlan_tpid) + if (match.mask->vlan_tpid) { headers->vlan_hdr.vlan_tpid = match.key->vlan_tpid; + fltr->flags |= ICE_TC_FLWR_FIELD_VLAN_TPID; + } } if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_CVLAN)) { @@ -1702,7 +1716,7 @@ ice_tc_forward_to_queue(struct ice_vsi *vsi, struct ice_tc_flower_fltr *fltr, /* If ADQ is configured, and the queue belongs to ADQ VSI, then prepare * ADQ switch filter */ - ch_vsi = ice_locate_vsi_using_queue(vsi, fltr); + ch_vsi = ice_locate_vsi_using_queue(vsi, fltr->action.fwd.q.queue); if (!ch_vsi) return -EINVAL; fltr->dest_vsi = ch_vsi; diff --git a/drivers/net/ethernet/intel/ice/ice_tc_lib.h b/drivers/net/ethernet/intel/ice/ice_tc_lib.h index 8d5e22ac7023cadbea534f83f87cd1cc2c7e0d5e..65d387163a46baa34763b5291faf95d9198f6404 100644 --- a/drivers/net/ethernet/intel/ice/ice_tc_lib.h +++ b/drivers/net/ethernet/intel/ice/ice_tc_lib.h @@ -33,6 +33,7 @@ #define ICE_TC_FLWR_FIELD_L2TPV3_SESSID BIT(26) #define ICE_TC_FLWR_FIELD_VLAN_PRIO BIT(27) #define ICE_TC_FLWR_FIELD_CVLAN_PRIO BIT(28) +#define ICE_TC_FLWR_FIELD_VLAN_TPID BIT(29) #define ICE_TC_FLOWER_MASK_32 0xFFFFFFFF @@ -203,6 +204,7 @@ static inline int ice_chnl_dmac_fltr_cnt(struct ice_pf *pf) return pf->num_dmac_chnl_fltrs; } +struct ice_vsi *ice_locate_vsi_using_queue(struct ice_vsi *vsi, int queue); int ice_add_cls_flower(struct net_device *netdev, struct ice_vsi *vsi, struct flow_cls_offload *cls_flower); diff --git a/drivers/net/ethernet/intel/ice/ice_vf_lib.c b/drivers/net/ethernet/intel/ice/ice_vf_lib.c index bf74a2f3a4f8c3d8ebf5a1492782ec06c79b3ddd..b26ce4425f4559321b4f853d1b47a107a5501456 100644 --- a/drivers/net/ethernet/intel/ice/ice_vf_lib.c +++ b/drivers/net/ethernet/intel/ice/ice_vf_lib.c @@ -689,8 +689,6 @@ int ice_reset_vf(struct ice_vf *vf, u32 flags) */ ice_vf_clear_all_promisc_modes(vf, vsi); - ice_eswitch_del_vf_mac_rule(vf); - ice_vf_fdir_exit(vf); ice_vf_fdir_init(vf); /* clean VF control VSI when resetting VF since it should be setup @@ -716,7 +714,6 @@ int ice_reset_vf(struct ice_vf *vf, u32 flags) } ice_eswitch_update_repr(vsi); - ice_eswitch_replay_vf_mac_rule(vf); /* if the VF has been reset allow it to come up again */ ice_mbx_clear_malvf(&vf->mbx_info); @@ -1329,3 +1326,35 @@ void ice_vf_set_initialized(struct ice_vf *vf) set_bit(ICE_VF_STATE_INIT, vf->vf_states); memset(&vf->vlan_v2_caps, 0, sizeof(vf->vlan_v2_caps)); } + +/** + * ice_get_vf_ctrl_vsi - Get first VF control VSI pointer + * @pf: the PF private structure + * @vsi: pointer to the VSI + * + * Return first found VF control VSI other than the vsi + * passed by parameter. This function is used to determine + * whether new resources have to be allocated for control VSI + * or they can be shared with existing one. + * + * Return found VF control VSI pointer other itself. Return + * NULL Otherwise. + * + */ +struct ice_vsi *ice_get_vf_ctrl_vsi(struct ice_pf *pf, struct ice_vsi *vsi) +{ + struct ice_vsi *ctrl_vsi = NULL; + struct ice_vf *vf; + unsigned int bkt; + + rcu_read_lock(); + ice_for_each_vf_rcu(pf, bkt, vf) { + if (vf != vsi->vf && vf->ctrl_vsi_idx != ICE_NO_VSI) { + ctrl_vsi = pf->vsi[vf->ctrl_vsi_idx]; + break; + } + } + + rcu_read_unlock(); + return ctrl_vsi; +} diff --git a/drivers/net/ethernet/intel/ice/ice_vf_lib.h b/drivers/net/ethernet/intel/ice/ice_vf_lib.h index a38ef00a367942b52f45c8b9d87abe4d95f52fef..67172fdd9bc27ff66ee5fff37e829941a464154b 100644 --- a/drivers/net/ethernet/intel/ice/ice_vf_lib.h +++ b/drivers/net/ethernet/intel/ice/ice_vf_lib.h @@ -227,6 +227,7 @@ int ice_vf_clear_vsi_promisc(struct ice_vf *vf, struct ice_vsi *vsi, u8 promisc_m); int ice_reset_vf(struct ice_vf *vf, u32 flags); void ice_reset_all_vfs(struct ice_pf *pf); +struct ice_vsi *ice_get_vf_ctrl_vsi(struct ice_pf *pf, struct ice_vsi *vsi); #else /* CONFIG_PCI_IOV */ static inline struct ice_vf *ice_get_vf_by_id(struct ice_pf *pf, u16 vf_id) { @@ -291,6 +292,12 @@ static inline int ice_reset_vf(struct ice_vf *vf, u32 flags) static inline void ice_reset_all_vfs(struct ice_pf *pf) { } + +static inline struct ice_vsi * +ice_get_vf_ctrl_vsi(struct ice_pf *pf, struct ice_vsi *vsi) +{ + return NULL; +} #endif /* !CONFIG_PCI_IOV */ #endif /* _ICE_VF_LIB_H_ */ diff --git a/drivers/net/ethernet/intel/ice/ice_virtchnl.c b/drivers/net/ethernet/intel/ice/ice_virtchnl.c index f4a524f80b110f1dc3d60d706eedb31a20740000..efbc2968a7bf6a7e9d74d992fb6f576874ffac24 100644 --- a/drivers/net/ethernet/intel/ice/ice_virtchnl.c +++ b/drivers/net/ethernet/intel/ice/ice_virtchnl.c @@ -3730,7 +3730,6 @@ static int ice_vc_repr_add_mac(struct ice_vf *vf, u8 *msg) for (i = 0; i < al->num_elements; i++) { u8 *mac_addr = al->list[i].addr; - int result; if (!is_unicast_ether_addr(mac_addr) || ether_addr_equal(mac_addr, vf->hw_lan_addr)) @@ -3742,13 +3741,6 @@ static int ice_vc_repr_add_mac(struct ice_vf *vf, u8 *msg) goto handle_mac_exit; } - result = ice_eswitch_add_vf_mac_rule(pf, vf, mac_addr); - if (result) { - dev_err(ice_pf_to_dev(pf), "Failed to add MAC %pM for VF %d\n, error %d\n", - mac_addr, vf->vf_id, result); - goto handle_mac_exit; - } - ice_vfhw_mac_add(vf, &al->list[i]); vf->num_mac++; break; diff --git a/drivers/net/ethernet/intel/ice/ice_vlan_mode.c b/drivers/net/ethernet/intel/ice/ice_vlan_mode.c index bcda2e0048073ddf00e23eea82f3d827b78b45e0..1279c1ffe31c3976065178b69da74614b914b2b3 100644 --- a/drivers/net/ethernet/intel/ice/ice_vlan_mode.c +++ b/drivers/net/ethernet/intel/ice/ice_vlan_mode.c @@ -219,7 +219,7 @@ static struct ice_update_recipe_lkup_idx_params ice_dvm_dflt_recipes[] = { .rid = ICE_SW_LKUP_VLAN, .fv_idx = ICE_PKT_FLAGS_0_TO_15_FV_IDX, .ignore_valid = false, - .mask = ICE_PKT_FLAGS_0_TO_15_VLAN_FLAGS_MASK, + .mask = ICE_PKT_VLAN_MASK, .mask_valid = true, .lkup_idx = ICE_SW_LKUP_VLAN_PKT_FLAGS_LKUP_IDX, }, diff --git a/drivers/net/ethernet/intel/ice/ice_xsk.c b/drivers/net/ethernet/intel/ice/ice_xsk.c index d1e489da7363f26ecfb723fcc75423a8faa1efdd..a7fe2b4ce6552fb284b879a5fca9b483a3a7059e 100644 --- a/drivers/net/ethernet/intel/ice/ice_xsk.c +++ b/drivers/net/ethernet/intel/ice/ice_xsk.c @@ -90,7 +90,6 @@ ice_qvec_dis_irq(struct ice_vsi *vsi, struct ice_rx_ring *rx_ring, { struct ice_pf *pf = vsi->back; struct ice_hw *hw = &pf->hw; - int base = vsi->base_vector; u16 reg; u32 val; @@ -103,11 +102,9 @@ ice_qvec_dis_irq(struct ice_vsi *vsi, struct ice_rx_ring *rx_ring, wr32(hw, QINT_RQCTL(reg), val); if (q_vector) { - u16 v_idx = q_vector->v_idx; - wr32(hw, GLINT_DYN_CTL(q_vector->reg_idx), 0); ice_flush(hw); - synchronize_irq(pf->msix_entries[v_idx + base].vector); + synchronize_irq(q_vector->irq.virq); } } diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index bb3db387d49cf6de899fec0acbcb1882a5f2452e..9a2561409b06f15fd3a742e1ab154a4c559510c7 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c @@ -183,11 +183,13 @@ static int igb_resume(struct device *); static int igb_runtime_suspend(struct device *dev); static int igb_runtime_resume(struct device *dev); static int igb_runtime_idle(struct device *dev); +#ifdef CONFIG_PM static const struct dev_pm_ops igb_pm_ops = { SET_SYSTEM_SLEEP_PM_OPS(igb_suspend, igb_resume) SET_RUNTIME_PM_OPS(igb_runtime_suspend, igb_runtime_resume, igb_runtime_idle) }; +#endif static void igb_shutdown(struct pci_dev *); static int igb_pci_sriov_configure(struct pci_dev *dev, int num_vfs); #ifdef CONFIG_IGB_DCA @@ -9585,6 +9587,11 @@ static pci_ers_result_t igb_io_error_detected(struct pci_dev *pdev, struct net_device *netdev = pci_get_drvdata(pdev); struct igb_adapter *adapter = netdev_priv(netdev); + if (state == pci_channel_io_normal) { + dev_warn(&pdev->dev, "Non-correctable non-fatal error reported.\n"); + return PCI_ERS_RESULT_CAN_RECOVER; + } + netif_device_detach(netdev); if (state == pci_channel_io_perm_failure) diff --git a/drivers/net/ethernet/intel/igc/igc.h b/drivers/net/ethernet/intel/igc/igc.h index 34aebf00a5123893fd7097e97e260a9c1c23354c..9db384f66a8ee7245a02e2fae24ad4421c9a5605 100644 --- a/drivers/net/ethernet/intel/igc/igc.h +++ b/drivers/net/ethernet/intel/igc/igc.h @@ -13,6 +13,8 @@ #include #include #include +#include +#include #include "igc_hw.h" @@ -100,6 +102,8 @@ struct igc_ring { u32 start_time; u32 end_time; u32 max_sdu; + bool oper_gate_closed; /* Operating gate. True if the TX Queue is closed */ + bool admin_gate_closed; /* Future gate. True if the TX Queue will be closed */ /* CBS parameters */ bool cbs_enable; /* indicates if CBS is enabled */ @@ -159,6 +163,7 @@ struct igc_adapter { struct timer_list watchdog_timer; struct timer_list dma_err_timer; struct timer_list phy_info_timer; + struct hrtimer hrtimer; u32 wol; u32 en_mng_pt; @@ -183,10 +188,13 @@ struct igc_adapter { u32 max_frame_size; u32 min_frame_size; + int tc_setup_type; ktime_t base_time; ktime_t cycle_time; - bool qbv_enable; + bool taprio_offload_enable; u32 qbv_config_change_errors; + bool qbv_transition; + unsigned int qbv_count; /* OS defined structs */ struct pci_dev *pdev; @@ -228,7 +236,10 @@ struct igc_adapter { struct ptp_clock *ptp_clock; struct ptp_clock_info ptp_caps; - struct work_struct ptp_tx_work; + /* Access to ptp_tx_skb and ptp_tx_start are protected by the + * ptp_tx_lock. + */ + spinlock_t ptp_tx_lock; struct sk_buff *ptp_tx_skb; struct hwtstamp_config tstamp_config; unsigned long ptp_tx_start; @@ -311,6 +322,33 @@ extern char igc_driver_name[]; #define IGC_MRQC_RSS_FIELD_IPV4_UDP 0x00400000 #define IGC_MRQC_RSS_FIELD_IPV6_UDP 0x00800000 +/* RX-desc Write-Back format RSS Type's */ +enum igc_rss_type_num { + IGC_RSS_TYPE_NO_HASH = 0, + IGC_RSS_TYPE_HASH_TCP_IPV4 = 1, + IGC_RSS_TYPE_HASH_IPV4 = 2, + IGC_RSS_TYPE_HASH_TCP_IPV6 = 3, + IGC_RSS_TYPE_HASH_IPV6_EX = 4, + IGC_RSS_TYPE_HASH_IPV6 = 5, + IGC_RSS_TYPE_HASH_TCP_IPV6_EX = 6, + IGC_RSS_TYPE_HASH_UDP_IPV4 = 7, + IGC_RSS_TYPE_HASH_UDP_IPV6 = 8, + IGC_RSS_TYPE_HASH_UDP_IPV6_EX = 9, + IGC_RSS_TYPE_MAX = 10, +}; +#define IGC_RSS_TYPE_MAX_TABLE 16 +#define IGC_RSS_TYPE_MASK GENMASK(3,0) /* 4-bits (3:0) = mask 0x0F */ + +/* igc_rss_type - Rx descriptor RSS type field */ +static inline u32 igc_rss_type(const union igc_adv_rx_desc *rx_desc) +{ + /* RSS Type 4-bits (3:0) number: 0-9 (above 9 is reserved) + * Accessing the same bits via u16 (wb.lower.lo_dword.hs_rss.pkt_info) + * is slightly slower than via u32 (wb.lower.lo_dword.data) + */ + return le32_get_bits(rx_desc->wb.lower.lo_dword.data, IGC_RSS_TYPE_MASK); +} + /* Interrupt defines */ #define IGC_START_ITR 648 /* ~6000 ints/sec */ #define IGC_4K_ITR 980 @@ -401,7 +439,6 @@ enum igc_state_t { __IGC_TESTING, __IGC_RESETTING, __IGC_DOWN, - __IGC_PTP_TX_IN_PROGRESS, }; enum igc_tx_flags { @@ -471,6 +508,13 @@ struct igc_rx_buffer { }; }; +/* context wrapper around xdp_buff to provide access to descriptor metadata */ +struct igc_xdp_buff { + struct xdp_buff xdp; + union igc_adv_rx_desc *rx_desc; + ktime_t rx_ts; /* data indication bit IGC_RXDADV_STAT_TSIP */ +}; + struct igc_q_vector { struct igc_adapter *adapter; /* backlink */ void __iomem *itr_register; @@ -578,6 +622,7 @@ enum igc_ring_flags_t { IGC_RING_FLAG_TX_CTX_IDX, IGC_RING_FLAG_TX_DETECT_HANG, IGC_RING_FLAG_AF_XDP_ZC, + IGC_RING_FLAG_TX_HWTSTAMP, }; #define ring_uses_large_buffer(ring) \ @@ -634,6 +679,7 @@ int igc_ptp_set_ts_config(struct net_device *netdev, struct ifreq *ifr); int igc_ptp_get_ts_config(struct net_device *netdev, struct ifreq *ifr); void igc_ptp_tx_hang(struct igc_adapter *adapter); void igc_ptp_read(struct igc_adapter *adapter, struct timespec64 *ts); +void igc_ptp_tx_tstamp_event(struct igc_adapter *adapter); #define igc_rx_pg_size(_ring) (PAGE_SIZE << igc_rx_pg_order(_ring)) diff --git a/drivers/net/ethernet/intel/igc/igc_ethtool.c b/drivers/net/ethernet/intel/igc/igc_ethtool.c index 0e2cb00622d1a3904d0f0afe38c63a1b72f59f85..93bce729be76a69c562ee5523bd521466356168b 100644 --- a/drivers/net/ethernet/intel/igc/igc_ethtool.c +++ b/drivers/net/ethernet/intel/igc/igc_ethtool.c @@ -1708,6 +1708,8 @@ static int igc_ethtool_get_link_ksettings(struct net_device *netdev, /* twisted pair */ cmd->base.port = PORT_TP; cmd->base.phy_address = hw->phy.addr; + ethtool_link_ksettings_add_link_mode(cmd, supported, TP); + ethtool_link_ksettings_add_link_mode(cmd, advertising, TP); /* advertising link modes */ if (hw->phy.autoneg_advertised & ADVERTISE_10_HALF) diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c index fa764190f27050a28dc0778e426eec18467c9389..9f93f0f4f752010b91036cc233516fa9d5fa5574 100644 --- a/drivers/net/ethernet/intel/igc/igc_main.c +++ b/drivers/net/ethernet/intel/igc/igc_main.c @@ -711,7 +711,6 @@ static void igc_configure_tx_ring(struct igc_adapter *adapter, /* disable the queue */ wr32(IGC_TXDCTL(reg_idx), 0); wrfl(); - mdelay(10); wr32(IGC_TDLEN(reg_idx), ring->count * sizeof(union igc_adv_tx_desc)); @@ -1017,7 +1016,7 @@ static __le32 igc_tx_launchtime(struct igc_ring *ring, ktime_t txtime, ktime_t base_time = adapter->base_time; ktime_t now = ktime_get_clocktai(); ktime_t baset_est, end_of_cycle; - u32 launchtime; + s32 launchtime; s64 n; n = div64_s64(ktime_sub_ns(now, base_time), cycle_time); @@ -1030,7 +1029,7 @@ static __le32 igc_tx_launchtime(struct igc_ring *ring, ktime_t txtime, *first_flag = true; ring->last_ff_cycle = baset_est; - if (ktime_compare(txtime, ring->last_tx_cycle) > 0) + if (ktime_compare(end_of_cycle, ring->last_tx_cycle) > 0) *insert_empty = true; } } @@ -1573,26 +1572,24 @@ static netdev_tx_t igc_xmit_frame_ring(struct sk_buff *skb, first->bytecount = skb->len; first->gso_segs = 1; - if (tx_ring->max_sdu > 0) { - u32 max_sdu = 0; - - max_sdu = tx_ring->max_sdu + - (skb_vlan_tagged(first->skb) ? VLAN_HLEN : 0); + if (adapter->qbv_transition || tx_ring->oper_gate_closed) + goto out_drop; - if (first->bytecount > max_sdu) { - adapter->stats.txdrop++; - goto out_drop; - } + if (tx_ring->max_sdu > 0 && first->bytecount > tx_ring->max_sdu) { + adapter->stats.txdrop++; + goto out_drop; } - if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) { + if (unlikely(test_bit(IGC_RING_FLAG_TX_HWTSTAMP, &tx_ring->flags) && + skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) { /* FIXME: add support for retrieving timestamps from * the other timer registers before skipping the * timestamping request. */ - if (adapter->tstamp_config.tx_type == HWTSTAMP_TX_ON && - !test_and_set_bit_lock(__IGC_PTP_TX_IN_PROGRESS, - &adapter->state)) { + unsigned long flags; + + spin_lock_irqsave(&adapter->ptp_tx_lock, flags); + if (!adapter->ptp_tx_skb) { skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; tx_flags |= IGC_TX_FLAGS_TSTAMP; @@ -1601,6 +1598,8 @@ static netdev_tx_t igc_xmit_frame_ring(struct sk_buff *skb, } else { adapter->tx_hwtstamp_skipped++; } + + spin_unlock_irqrestore(&adapter->ptp_tx_lock, flags); } if (skb_vlan_tag_present(skb)) { @@ -1697,14 +1696,36 @@ static void igc_rx_checksum(struct igc_ring *ring, le32_to_cpu(rx_desc->wb.upper.status_error)); } +/* Mapping HW RSS Type to enum pkt_hash_types */ +static const enum pkt_hash_types igc_rss_type_table[IGC_RSS_TYPE_MAX_TABLE] = { + [IGC_RSS_TYPE_NO_HASH] = PKT_HASH_TYPE_L2, + [IGC_RSS_TYPE_HASH_TCP_IPV4] = PKT_HASH_TYPE_L4, + [IGC_RSS_TYPE_HASH_IPV4] = PKT_HASH_TYPE_L3, + [IGC_RSS_TYPE_HASH_TCP_IPV6] = PKT_HASH_TYPE_L4, + [IGC_RSS_TYPE_HASH_IPV6_EX] = PKT_HASH_TYPE_L3, + [IGC_RSS_TYPE_HASH_IPV6] = PKT_HASH_TYPE_L3, + [IGC_RSS_TYPE_HASH_TCP_IPV6_EX] = PKT_HASH_TYPE_L4, + [IGC_RSS_TYPE_HASH_UDP_IPV4] = PKT_HASH_TYPE_L4, + [IGC_RSS_TYPE_HASH_UDP_IPV6] = PKT_HASH_TYPE_L4, + [IGC_RSS_TYPE_HASH_UDP_IPV6_EX] = PKT_HASH_TYPE_L4, + [10] = PKT_HASH_TYPE_NONE, /* RSS Type above 9 "Reserved" by HW */ + [11] = PKT_HASH_TYPE_NONE, /* keep array sized for SW bit-mask */ + [12] = PKT_HASH_TYPE_NONE, /* to handle future HW revisons */ + [13] = PKT_HASH_TYPE_NONE, + [14] = PKT_HASH_TYPE_NONE, + [15] = PKT_HASH_TYPE_NONE, +}; + static inline void igc_rx_hash(struct igc_ring *ring, union igc_adv_rx_desc *rx_desc, struct sk_buff *skb) { - if (ring->netdev->features & NETIF_F_RXHASH) - skb_set_hash(skb, - le32_to_cpu(rx_desc->wb.lower.hi_dword.rss), - PKT_HASH_TYPE_L3); + if (ring->netdev->features & NETIF_F_RXHASH) { + u32 rss_hash = le32_to_cpu(rx_desc->wb.lower.hi_dword.rss); + u32 rss_type = igc_rss_type(rx_desc); + + skb_set_hash(skb, rss_hash, igc_rss_type_table[rss_type]); + } } static void igc_rx_vlan(struct igc_ring *rx_ring, @@ -2221,6 +2242,8 @@ static bool igc_alloc_rx_buffers_zc(struct igc_ring *ring, u16 count) if (!count) return ok; + XSK_CHECK_PRIV_TYPE(struct igc_xdp_buff); + desc = IGC_RX_DESC(ring, i); bi = &ring->rx_buffer_info[i]; i -= ring->count; @@ -2394,6 +2417,8 @@ static int igc_xdp_xmit_back(struct igc_adapter *adapter, struct xdp_buff *xdp) nq = txring_txq(ring); __netif_tx_lock(nq, cpu); + /* Avoid transmit queue timeout since we share it with the slow path */ + txq_trans_cond_update(nq); res = igc_xdp_init_tx_descriptor(ring, xdpf); __netif_tx_unlock(nq); return res; @@ -2505,8 +2530,8 @@ static int igc_clean_rx_irq(struct igc_q_vector *q_vector, const int budget) union igc_adv_rx_desc *rx_desc; struct igc_rx_buffer *rx_buffer; unsigned int size, truesize; + struct igc_xdp_buff ctx; ktime_t timestamp = 0; - struct xdp_buff xdp; int pkt_offset = 0; void *pktbuf; @@ -2535,18 +2560,20 @@ static int igc_clean_rx_irq(struct igc_q_vector *q_vector, const int budget) if (igc_test_staterr(rx_desc, IGC_RXDADV_STAT_TSIP)) { timestamp = igc_ptp_rx_pktstamp(q_vector->adapter, pktbuf); + ctx.rx_ts = timestamp; pkt_offset = IGC_TS_HDR_LEN; size -= IGC_TS_HDR_LEN; } if (!skb) { - xdp_init_buff(&xdp, truesize, &rx_ring->xdp_rxq); - xdp_prepare_buff(&xdp, pktbuf - igc_rx_offset(rx_ring), + xdp_init_buff(&ctx.xdp, truesize, &rx_ring->xdp_rxq); + xdp_prepare_buff(&ctx.xdp, pktbuf - igc_rx_offset(rx_ring), igc_rx_offset(rx_ring) + pkt_offset, size, true); - xdp_buff_clear_frags_flag(&xdp); + xdp_buff_clear_frags_flag(&ctx.xdp); + ctx.rx_desc = rx_desc; - skb = igc_xdp_run_prog(adapter, &xdp); + skb = igc_xdp_run_prog(adapter, &ctx.xdp); } if (IS_ERR(skb)) { @@ -2568,9 +2595,9 @@ static int igc_clean_rx_irq(struct igc_q_vector *q_vector, const int budget) } else if (skb) igc_add_rx_frag(rx_ring, rx_buffer, skb, size); else if (ring_uses_build_skb(rx_ring)) - skb = igc_build_skb(rx_ring, rx_buffer, &xdp); + skb = igc_build_skb(rx_ring, rx_buffer, &ctx.xdp); else - skb = igc_construct_skb(rx_ring, rx_buffer, &xdp, + skb = igc_construct_skb(rx_ring, rx_buffer, &ctx.xdp, timestamp); /* exit if we failed to retrieve a buffer */ @@ -2671,6 +2698,15 @@ static void igc_dispatch_skb_zc(struct igc_q_vector *q_vector, napi_gro_receive(&q_vector->napi, skb); } +static struct igc_xdp_buff *xsk_buff_to_igc_ctx(struct xdp_buff *xdp) +{ + /* xdp_buff pointer used by ZC code path is alloc as xdp_buff_xsk. The + * igc_xdp_buff shares its layout with xdp_buff_xsk and private + * igc_xdp_buff fields fall into xdp_buff_xsk->cb + */ + return (struct igc_xdp_buff *)xdp; +} + static int igc_clean_rx_irq_zc(struct igc_q_vector *q_vector, const int budget) { struct igc_adapter *adapter = q_vector->adapter; @@ -2689,6 +2725,7 @@ static int igc_clean_rx_irq_zc(struct igc_q_vector *q_vector, const int budget) while (likely(total_packets < budget)) { union igc_adv_rx_desc *desc; struct igc_rx_buffer *bi; + struct igc_xdp_buff *ctx; ktime_t timestamp = 0; unsigned int size; int res; @@ -2706,9 +2743,13 @@ static int igc_clean_rx_irq_zc(struct igc_q_vector *q_vector, const int budget) bi = &ring->rx_buffer_info[ntc]; + ctx = xsk_buff_to_igc_ctx(bi->xdp); + ctx->rx_desc = desc; + if (igc_test_staterr(desc, IGC_RXDADV_STAT_TSIP)) { timestamp = igc_ptp_rx_pktstamp(q_vector->adapter, bi->xdp->data); + ctx->rx_ts = timestamp; bi->xdp->data += IGC_TS_HDR_LEN; @@ -2796,6 +2837,9 @@ static void igc_xdp_xmit_zc(struct igc_ring *ring) __netif_tx_lock(nq, cpu); + /* Avoid transmit queue timeout since we share it with the slow path */ + txq_trans_cond_update(nq); + budget = igc_desc_unused(ring); while (xsk_tx_peek_desc(pool, &xdp_desc) && budget--) { @@ -2963,8 +3007,8 @@ static bool igc_clean_tx_irq(struct igc_q_vector *q_vector, int napi_budget) time_after(jiffies, tx_buffer->time_stamp + (adapter->tx_timeout_factor * HZ)) && !(rd32(IGC_STATUS) & IGC_STATUS_TXOFF) && - (rd32(IGC_TDH(tx_ring->reg_idx)) != - readl(tx_ring->tail))) { + (rd32(IGC_TDH(tx_ring->reg_idx)) != readl(tx_ring->tail)) && + !tx_ring->oper_gate_closed) { /* detected Tx unit hang */ netdev_err(tx_ring->netdev, "Detected Tx Unit Hang\n" @@ -5219,7 +5263,7 @@ static void igc_tsync_interrupt(struct igc_adapter *adapter) if (tsicr & IGC_TSICR_TXTS) { /* retrieve hardware timestamp */ - schedule_work(&adapter->ptp_tx_work); + igc_ptp_tx_tstamp_event(adapter); ack |= IGC_TSICR_TXTS; } @@ -6053,7 +6097,10 @@ static int igc_tsn_clear_schedule(struct igc_adapter *adapter) adapter->base_time = 0; adapter->cycle_time = NSEC_PER_SEC; + adapter->taprio_offload_enable = false; adapter->qbv_config_change_errors = 0; + adapter->qbv_transition = false; + adapter->qbv_count = 0; for (i = 0; i < adapter->num_tx_queues; i++) { struct igc_ring *ring = adapter->tx_ring[i]; @@ -6061,6 +6108,8 @@ static int igc_tsn_clear_schedule(struct igc_adapter *adapter) ring->start_time = 0; ring->end_time = NSEC_PER_SEC; ring->max_sdu = 0; + ring->oper_gate_closed = false; + ring->admin_gate_closed = false; } return 0; @@ -6072,18 +6121,20 @@ static int igc_save_qbv_schedule(struct igc_adapter *adapter, bool queue_configured[IGC_MAX_TX_QUEUES] = { }; struct igc_hw *hw = &adapter->hw; u32 start_time = 0, end_time = 0; + struct timespec64 now; size_t n; int i; - adapter->qbv_enable = qopt->enable; - - if (!qopt->enable) + if (qopt->cmd == TAPRIO_CMD_DESTROY) return igc_tsn_clear_schedule(adapter); + if (qopt->cmd != TAPRIO_CMD_REPLACE) + return -EOPNOTSUPP; + if (qopt->base_time < 0) return -ERANGE; - if (igc_is_device_id_i225(hw) && adapter->base_time) + if (igc_is_device_id_i225(hw) && adapter->taprio_offload_enable) return -EALREADY; if (!validate_schedule(adapter, qopt)) @@ -6091,6 +6142,9 @@ static int igc_save_qbv_schedule(struct igc_adapter *adapter, adapter->cycle_time = qopt->cycle_time; adapter->base_time = qopt->base_time; + adapter->taprio_offload_enable = true; + + igc_ptp_read(adapter, &now); for (n = 0; n < qopt->num_entries; n++) { struct tc_taprio_sched_entry *e = &qopt->entries[n]; @@ -6126,7 +6180,10 @@ static int igc_save_qbv_schedule(struct igc_adapter *adapter, ring->start_time = start_time; ring->end_time = end_time; - queue_configured[i] = true; + if (ring->start_time >= adapter->cycle_time) + queue_configured[i] = false; + else + queue_configured[i] = true; } start_time += e->interval; @@ -6136,8 +6193,20 @@ static int igc_save_qbv_schedule(struct igc_adapter *adapter, * If not, set the start and end time to be end time. */ for (i = 0; i < adapter->num_tx_queues; i++) { + struct igc_ring *ring = adapter->tx_ring[i]; + + if (!is_base_time_past(qopt->base_time, &now)) { + ring->admin_gate_closed = false; + } else { + ring->oper_gate_closed = false; + ring->admin_gate_closed = false; + } + if (!queue_configured[i]) { - struct igc_ring *ring = adapter->tx_ring[i]; + if (!is_base_time_past(qopt->base_time, &now)) + ring->admin_gate_closed = true; + else + ring->oper_gate_closed = true; ring->start_time = end_time; ring->end_time = end_time; @@ -6149,7 +6218,7 @@ static int igc_save_qbv_schedule(struct igc_adapter *adapter, struct net_device *dev = adapter->netdev; if (qopt->max_sdu[i]) - ring->max_sdu = qopt->max_sdu[i] + dev->hard_header_len; + ring->max_sdu = qopt->max_sdu[i] + dev->hard_header_len - ETH_TLEN; else ring->max_sdu = 0; } @@ -6269,6 +6338,8 @@ static int igc_setup_tc(struct net_device *dev, enum tc_setup_type type, { struct igc_adapter *adapter = netdev_priv(dev); + adapter->tc_setup_type = type; + switch (type) { case TC_QUERY_CAPS: return igc_tc_query_caps(adapter, type_data); @@ -6321,6 +6392,9 @@ static int igc_xdp_xmit(struct net_device *dev, int num_frames, __netif_tx_lock(nq, cpu); + /* Avoid transmit queue timeout since we share it with the slow path */ + txq_trans_cond_update(nq); + drops = 0; for (i = 0; i < num_frames; i++) { int err; @@ -6461,6 +6535,79 @@ u32 igc_rd32(struct igc_hw *hw, u32 reg) return value; } +/* Mapping HW RSS Type to enum xdp_rss_hash_type */ +static enum xdp_rss_hash_type igc_xdp_rss_type[IGC_RSS_TYPE_MAX_TABLE] = { + [IGC_RSS_TYPE_NO_HASH] = XDP_RSS_TYPE_L2, + [IGC_RSS_TYPE_HASH_TCP_IPV4] = XDP_RSS_TYPE_L4_IPV4_TCP, + [IGC_RSS_TYPE_HASH_IPV4] = XDP_RSS_TYPE_L3_IPV4, + [IGC_RSS_TYPE_HASH_TCP_IPV6] = XDP_RSS_TYPE_L4_IPV6_TCP, + [IGC_RSS_TYPE_HASH_IPV6_EX] = XDP_RSS_TYPE_L3_IPV6_EX, + [IGC_RSS_TYPE_HASH_IPV6] = XDP_RSS_TYPE_L3_IPV6, + [IGC_RSS_TYPE_HASH_TCP_IPV6_EX] = XDP_RSS_TYPE_L4_IPV6_TCP_EX, + [IGC_RSS_TYPE_HASH_UDP_IPV4] = XDP_RSS_TYPE_L4_IPV4_UDP, + [IGC_RSS_TYPE_HASH_UDP_IPV6] = XDP_RSS_TYPE_L4_IPV6_UDP, + [IGC_RSS_TYPE_HASH_UDP_IPV6_EX] = XDP_RSS_TYPE_L4_IPV6_UDP_EX, + [10] = XDP_RSS_TYPE_NONE, /* RSS Type above 9 "Reserved" by HW */ + [11] = XDP_RSS_TYPE_NONE, /* keep array sized for SW bit-mask */ + [12] = XDP_RSS_TYPE_NONE, /* to handle future HW revisons */ + [13] = XDP_RSS_TYPE_NONE, + [14] = XDP_RSS_TYPE_NONE, + [15] = XDP_RSS_TYPE_NONE, +}; + +static int igc_xdp_rx_hash(const struct xdp_md *_ctx, u32 *hash, + enum xdp_rss_hash_type *rss_type) +{ + const struct igc_xdp_buff *ctx = (void *)_ctx; + + if (!(ctx->xdp.rxq->dev->features & NETIF_F_RXHASH)) + return -ENODATA; + + *hash = le32_to_cpu(ctx->rx_desc->wb.lower.hi_dword.rss); + *rss_type = igc_xdp_rss_type[igc_rss_type(ctx->rx_desc)]; + + return 0; +} + +static int igc_xdp_rx_timestamp(const struct xdp_md *_ctx, u64 *timestamp) +{ + const struct igc_xdp_buff *ctx = (void *)_ctx; + + if (igc_test_staterr(ctx->rx_desc, IGC_RXDADV_STAT_TSIP)) { + *timestamp = ctx->rx_ts; + + return 0; + } + + return -ENODATA; +} + +static const struct xdp_metadata_ops igc_xdp_metadata_ops = { + .xmo_rx_hash = igc_xdp_rx_hash, + .xmo_rx_timestamp = igc_xdp_rx_timestamp, +}; + +static enum hrtimer_restart igc_qbv_scheduling_timer(struct hrtimer *timer) +{ + struct igc_adapter *adapter = container_of(timer, struct igc_adapter, + hrtimer); + unsigned int i; + + adapter->qbv_transition = true; + for (i = 0; i < adapter->num_tx_queues; i++) { + struct igc_ring *tx_ring = adapter->tx_ring[i]; + + if (tx_ring->admin_gate_closed) { + tx_ring->admin_gate_closed = false; + tx_ring->oper_gate_closed = true; + } else { + tx_ring->oper_gate_closed = false; + } + } + adapter->qbv_transition = false; + return HRTIMER_NORESTART; +} + /** * igc_probe - Device Initialization Routine * @pdev: PCI device information struct @@ -6534,6 +6681,7 @@ static int igc_probe(struct pci_dev *pdev, hw->hw_addr = adapter->io_addr; netdev->netdev_ops = &igc_netdev_ops; + netdev->xdp_metadata_ops = &igc_xdp_metadata_ops; igc_ethtool_set_ops(netdev); netdev->watchdog_timeo = 5 * HZ; @@ -6561,6 +6709,7 @@ static int igc_probe(struct pci_dev *pdev, netdev->features |= NETIF_F_TSO; netdev->features |= NETIF_F_TSO6; netdev->features |= NETIF_F_TSO_ECN; + netdev->features |= NETIF_F_RXHASH; netdev->features |= NETIF_F_RXCSUM; netdev->features |= NETIF_F_HW_CSUM; netdev->features |= NETIF_F_SCTP_CRC; @@ -6637,6 +6786,9 @@ static int igc_probe(struct pci_dev *pdev, INIT_WORK(&adapter->reset_task, igc_reset_task); INIT_WORK(&adapter->watchdog_task, igc_watchdog_task); + hrtimer_init(&adapter->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + adapter->hrtimer.function = &igc_qbv_scheduling_timer; + /* Initialize link properties that are user-changeable */ adapter->fc_autoneg = true; hw->mac.autoneg = true; @@ -6740,6 +6892,7 @@ static void igc_remove(struct pci_dev *pdev) cancel_work_sync(&adapter->reset_task); cancel_work_sync(&adapter->watchdog_task); + hrtimer_cancel(&adapter->hrtimer); /* Release control of h/w to f/w. If f/w is AMT enabled, this * would have already happened in close and is redundant. diff --git a/drivers/net/ethernet/intel/igc/igc_ptp.c b/drivers/net/ethernet/intel/igc/igc_ptp.c index 4e10ced736dbb5855d0389b8c4636c22c52c06a2..f0b979a7065521e67e07365bdeaa358909437253 100644 --- a/drivers/net/ethernet/intel/igc/igc_ptp.c +++ b/drivers/net/ethernet/intel/igc/igc_ptp.c @@ -356,16 +356,35 @@ static int igc_ptp_feature_enable_i225(struct ptp_clock_info *ptp, tsim &= ~IGC_TSICR_TT0; } if (on) { + struct timespec64 safe_start; int i = rq->perout.index; igc_pin_perout(igc, i, pin, use_freq); - igc->perout[i].start.tv_sec = rq->perout.start.sec; + igc_ptp_read(igc, &safe_start); + + /* PPS output start time is triggered by Target time(TT) + * register. Programming any past time value into TT + * register will cause PPS to never start. Need to make + * sure we program the TT register a time ahead in + * future. There isn't a stringent need to fire PPS out + * right away. Adding +2 seconds should take care of + * corner cases. Let's say if the SYSTIML is close to + * wrap up and the timer keeps ticking as we program the + * register, adding +2seconds is safe bet. + */ + safe_start.tv_sec += 2; + + if (rq->perout.start.sec < safe_start.tv_sec) + igc->perout[i].start.tv_sec = safe_start.tv_sec; + else + igc->perout[i].start.tv_sec = rq->perout.start.sec; igc->perout[i].start.tv_nsec = rq->perout.start.nsec; igc->perout[i].period.tv_sec = ts.tv_sec; igc->perout[i].period.tv_nsec = ts.tv_nsec; - wr32(trgttimh, rq->perout.start.sec); + wr32(trgttimh, (u32)igc->perout[i].start.tv_sec); /* For now, always select timer 0 as source. */ - wr32(trgttiml, rq->perout.start.nsec | IGC_TT_IO_TIMER_SEL_SYSTIM0); + wr32(trgttiml, (u32)(igc->perout[i].start.tv_nsec | + IGC_TT_IO_TIMER_SEL_SYSTIM0)); if (use_freq) wr32(freqout, ns); tsauxc |= tsauxc_mask; @@ -536,9 +555,34 @@ static void igc_ptp_enable_rx_timestamp(struct igc_adapter *adapter) wr32(IGC_TSYNCRXCTL, val); } +static void igc_ptp_clear_tx_tstamp(struct igc_adapter *adapter) +{ + unsigned long flags; + + spin_lock_irqsave(&adapter->ptp_tx_lock, flags); + + dev_kfree_skb_any(adapter->ptp_tx_skb); + adapter->ptp_tx_skb = NULL; + + spin_unlock_irqrestore(&adapter->ptp_tx_lock, flags); +} + static void igc_ptp_disable_tx_timestamp(struct igc_adapter *adapter) { struct igc_hw *hw = &adapter->hw; + int i; + + /* Clear the flags first to avoid new packets to be enqueued + * for TX timestamping. + */ + for (i = 0; i < adapter->num_tx_queues; i++) { + struct igc_ring *tx_ring = adapter->tx_ring[i]; + + clear_bit(IGC_RING_FLAG_TX_HWTSTAMP, &tx_ring->flags); + } + + /* Now we can clean the pending TX timestamp requests. */ + igc_ptp_clear_tx_tstamp(adapter); wr32(IGC_TSYNCTXCTL, 0); } @@ -546,12 +590,23 @@ static void igc_ptp_disable_tx_timestamp(struct igc_adapter *adapter) static void igc_ptp_enable_tx_timestamp(struct igc_adapter *adapter) { struct igc_hw *hw = &adapter->hw; + int i; wr32(IGC_TSYNCTXCTL, IGC_TSYNCTXCTL_ENABLED | IGC_TSYNCTXCTL_TXSYNSIG); /* Read TXSTMP registers to discard any timestamp previously stored. */ rd32(IGC_TXSTMPL); rd32(IGC_TXSTMPH); + + /* The hardware is ready to accept TX timestamp requests, + * notify the transmit path. + */ + for (i = 0; i < adapter->num_tx_queues; i++) { + struct igc_ring *tx_ring = adapter->tx_ring[i]; + + set_bit(IGC_RING_FLAG_TX_HWTSTAMP, &tx_ring->flags); + } + } /** @@ -603,6 +658,7 @@ static int igc_ptp_set_timestamp_mode(struct igc_adapter *adapter, return 0; } +/* Requires adapter->ptp_tx_lock held by caller. */ static void igc_ptp_tx_timeout(struct igc_adapter *adapter) { struct igc_hw *hw = &adapter->hw; @@ -610,7 +666,6 @@ static void igc_ptp_tx_timeout(struct igc_adapter *adapter) dev_kfree_skb_any(adapter->ptp_tx_skb); adapter->ptp_tx_skb = NULL; adapter->tx_hwtstamp_timeouts++; - clear_bit_unlock(__IGC_PTP_TX_IN_PROGRESS, &adapter->state); /* Clear the tx valid bit in TSYNCTXCTL register to enable interrupt. */ rd32(IGC_TXSTMPH); netdev_warn(adapter->netdev, "Tx timestamp timeout\n"); @@ -618,20 +673,20 @@ static void igc_ptp_tx_timeout(struct igc_adapter *adapter) void igc_ptp_tx_hang(struct igc_adapter *adapter) { - bool timeout = time_is_before_jiffies(adapter->ptp_tx_start + - IGC_PTP_TX_TIMEOUT); + unsigned long flags; - if (!test_bit(__IGC_PTP_TX_IN_PROGRESS, &adapter->state)) - return; + spin_lock_irqsave(&adapter->ptp_tx_lock, flags); - /* If we haven't received a timestamp within the timeout, it is - * reasonable to assume that it will never occur, so we can unlock the - * timestamp bit when this occurs. - */ - if (timeout) { - cancel_work_sync(&adapter->ptp_tx_work); - igc_ptp_tx_timeout(adapter); - } + if (!adapter->ptp_tx_skb) + goto unlock; + + if (time_is_after_jiffies(adapter->ptp_tx_start + IGC_PTP_TX_TIMEOUT)) + goto unlock; + + igc_ptp_tx_timeout(adapter); + +unlock: + spin_unlock_irqrestore(&adapter->ptp_tx_lock, flags); } /** @@ -641,20 +696,57 @@ void igc_ptp_tx_hang(struct igc_adapter *adapter) * If we were asked to do hardware stamping and such a time stamp is * available, then it must have been for this skb here because we only * allow only one such packet into the queue. + * + * Context: Expects adapter->ptp_tx_lock to be held by caller. */ static void igc_ptp_tx_hwtstamp(struct igc_adapter *adapter) { struct sk_buff *skb = adapter->ptp_tx_skb; struct skb_shared_hwtstamps shhwtstamps; struct igc_hw *hw = &adapter->hw; + u32 tsynctxctl; int adjust = 0; u64 regval; if (WARN_ON_ONCE(!skb)) return; - regval = rd32(IGC_TXSTMPL); - regval |= (u64)rd32(IGC_TXSTMPH) << 32; + tsynctxctl = rd32(IGC_TSYNCTXCTL); + tsynctxctl &= IGC_TSYNCTXCTL_TXTT_0; + if (tsynctxctl) { + regval = rd32(IGC_TXSTMPL); + regval |= (u64)rd32(IGC_TXSTMPH) << 32; + } else { + /* There's a bug in the hardware that could cause + * missing interrupts for TX timestamping. The issue + * is that for new interrupts to be triggered, the + * IGC_TXSTMPH_0 register must be read. + * + * To avoid discarding a valid timestamp that just + * happened at the "wrong" time, we need to confirm + * that there was no timestamp captured, we do that by + * assuming that no two timestamps in sequence have + * the same nanosecond value. + * + * So, we read the "low" register, read the "high" + * register (to latch a new timestamp) and read the + * "low" register again, if "old" and "new" versions + * of the "low" register are different, a valid + * timestamp was captured, we can read the "high" + * register again. + */ + u32 txstmpl_old, txstmpl_new; + + txstmpl_old = rd32(IGC_TXSTMPL); + rd32(IGC_TXSTMPH); + txstmpl_new = rd32(IGC_TXSTMPL); + + if (txstmpl_old == txstmpl_new) + return; + + regval = txstmpl_new; + regval |= (u64)rd32(IGC_TXSTMPH) << 32; + } if (igc_ptp_systim_to_hwtstamp(adapter, &shhwtstamps, regval)) return; @@ -676,13 +768,7 @@ static void igc_ptp_tx_hwtstamp(struct igc_adapter *adapter) shhwtstamps.hwtstamp = ktime_add_ns(shhwtstamps.hwtstamp, adjust); - /* Clear the lock early before calling skb_tstamp_tx so that - * applications are not woken up before the lock bit is clear. We use - * a copy of the skb pointer to ensure other threads can't change it - * while we're notifying the stack. - */ adapter->ptp_tx_skb = NULL; - clear_bit_unlock(__IGC_PTP_TX_IN_PROGRESS, &adapter->state); /* Notify the stack and free the skb after we've unlocked */ skb_tstamp_tx(skb, &shhwtstamps); @@ -690,27 +776,25 @@ static void igc_ptp_tx_hwtstamp(struct igc_adapter *adapter) } /** - * igc_ptp_tx_work - * @work: pointer to work struct + * igc_ptp_tx_tstamp_event + * @adapter: board private structure * - * This work function polls the TSYNCTXCTL valid bit to determine when a - * timestamp has been taken for the current stored skb. + * Called when a TX timestamp interrupt happens to retrieve the + * timestamp and send it up to the socket. */ -static void igc_ptp_tx_work(struct work_struct *work) +void igc_ptp_tx_tstamp_event(struct igc_adapter *adapter) { - struct igc_adapter *adapter = container_of(work, struct igc_adapter, - ptp_tx_work); - struct igc_hw *hw = &adapter->hw; - u32 tsynctxctl; + unsigned long flags; - if (!test_bit(__IGC_PTP_TX_IN_PROGRESS, &adapter->state)) - return; + spin_lock_irqsave(&adapter->ptp_tx_lock, flags); - tsynctxctl = rd32(IGC_TSYNCTXCTL); - if (WARN_ON_ONCE(!(tsynctxctl & IGC_TSYNCTXCTL_TXTT_0))) - return; + if (!adapter->ptp_tx_skb) + goto unlock; igc_ptp_tx_hwtstamp(adapter); + +unlock: + spin_unlock_irqrestore(&adapter->ptp_tx_lock, flags); } /** @@ -959,8 +1043,8 @@ void igc_ptp_init(struct igc_adapter *adapter) return; } + spin_lock_init(&adapter->ptp_tx_lock); spin_lock_init(&adapter->tmreg_lock); - INIT_WORK(&adapter->ptp_tx_work, igc_ptp_tx_work); adapter->tstamp_config.rx_filter = HWTSTAMP_FILTER_NONE; adapter->tstamp_config.tx_type = HWTSTAMP_TX_OFF; @@ -1020,10 +1104,7 @@ void igc_ptp_suspend(struct igc_adapter *adapter) if (!(adapter->ptp_flags & IGC_PTP_ENABLED)) return; - cancel_work_sync(&adapter->ptp_tx_work); - dev_kfree_skb_any(adapter->ptp_tx_skb); - adapter->ptp_tx_skb = NULL; - clear_bit_unlock(__IGC_PTP_TX_IN_PROGRESS, &adapter->state); + igc_ptp_clear_tx_tstamp(adapter); if (pci_device_is_present(adapter->pdev)) { igc_ptp_time_save(adapter); diff --git a/drivers/net/ethernet/intel/igc/igc_tsn.c b/drivers/net/ethernet/intel/igc/igc_tsn.c index 94a2b0dfb54d40b7fd00dfac8b47a8a95a96b90d..a9c08321aca901c20f1178088f4764413a40d2ea 100644 --- a/drivers/net/ethernet/intel/igc/igc_tsn.c +++ b/drivers/net/ethernet/intel/igc/igc_tsn.c @@ -37,7 +37,7 @@ static unsigned int igc_tsn_new_flags(struct igc_adapter *adapter) { unsigned int new_flags = adapter->flags & ~IGC_FLAG_TSN_ANY_ENABLED; - if (adapter->qbv_enable) + if (adapter->taprio_offload_enable) new_flags |= IGC_FLAG_TSN_QBV_ENABLED; if (is_any_launchtime(adapter)) @@ -114,7 +114,6 @@ static int igc_tsn_disable_offload(struct igc_adapter *adapter) static int igc_tsn_enable_offload(struct igc_adapter *adapter) { struct igc_hw *hw = &adapter->hw; - bool tsn_mode_reconfig = false; u32 tqavctrl, baset_l, baset_h; u32 sec, nsec, cycle; ktime_t base_time, systim; @@ -133,8 +132,28 @@ static int igc_tsn_enable_offload(struct igc_adapter *adapter) wr32(IGC_STQT(i), ring->start_time); wr32(IGC_ENDQT(i), ring->end_time); - txqctl |= IGC_TXQCTL_STRICT_CYCLE | - IGC_TXQCTL_STRICT_END; + if (adapter->taprio_offload_enable) { + /* If taprio_offload_enable is set we are in "taprio" + * mode and we need to be strict about the + * cycles: only transmit a packet if it can be + * completed during that cycle. + * + * If taprio_offload_enable is NOT true when + * enabling TSN offload, the cycle should have + * no external effects, but is only used internally + * to adapt the base time register after a second + * has passed. + * + * Enabling strict mode in this case would + * unnecessarily prevent the transmission of + * certain packets (i.e. at the boundary of a + * second) and thus interfere with the launchtime + * feature that promises transmission at a + * certain point in time. + */ + txqctl |= IGC_TXQCTL_STRICT_CYCLE | + IGC_TXQCTL_STRICT_END; + } if (ring->launchtime_enable) txqctl |= IGC_TXQCTL_QUEUE_MODE_LAUNCHT; @@ -228,11 +247,10 @@ static int igc_tsn_enable_offload(struct igc_adapter *adapter) tqavctrl = rd32(IGC_TQAVCTRL) & ~IGC_TQAVCTRL_FUTSCDDIS; - if (tqavctrl & IGC_TQAVCTRL_TRANSMIT_MODE_TSN) - tsn_mode_reconfig = true; - tqavctrl |= IGC_TQAVCTRL_TRANSMIT_MODE_TSN | IGC_TQAVCTRL_ENHANCED_QAV; + adapter->qbv_count++; + cycle = adapter->cycle_time; base_time = adapter->base_time; @@ -249,17 +267,29 @@ static int igc_tsn_enable_offload(struct igc_adapter *adapter) * Gate Control List (GCL) is running. */ if ((rd32(IGC_BASET_H) || rd32(IGC_BASET_L)) && - tsn_mode_reconfig) + (adapter->tc_setup_type == TC_SETUP_QDISC_TAPRIO) && + (adapter->qbv_count > 1)) adapter->qbv_config_change_errors++; } else { - /* According to datasheet section 7.5.2.9.3.3, FutScdDis bit - * has to be configured before the cycle time and base time. - * Tx won't hang if there is a GCL is already running, - * so in this case we don't need to set FutScdDis. - */ - if (igc_is_device_id_i226(hw) && - !(rd32(IGC_BASET_H) || rd32(IGC_BASET_L))) - tqavctrl |= IGC_TQAVCTRL_FUTSCDDIS; + if (igc_is_device_id_i226(hw)) { + ktime_t adjust_time, expires_time; + + /* According to datasheet section 7.5.2.9.3.3, FutScdDis bit + * has to be configured before the cycle time and base time. + * Tx won't hang if a GCL is already running, + * so in this case we don't need to set FutScdDis. + */ + if (!(rd32(IGC_BASET_H) || rd32(IGC_BASET_L))) + tqavctrl |= IGC_TQAVCTRL_FUTSCDDIS; + + nsec = rd32(IGC_SYSTIML); + sec = rd32(IGC_SYSTIMH); + systim = ktime_set(sec, nsec); + + adjust_time = adapter->base_time; + expires_time = ktime_sub_ns(adjust_time, systim); + hrtimer_start(&adapter->hrtimer, expires_time, HRTIMER_MODE_REL); + } } wr32(IGC_TQAVCTRL, tqavctrl); @@ -305,7 +335,11 @@ int igc_tsn_offload_apply(struct igc_adapter *adapter) { struct igc_hw *hw = &adapter->hw; - if (netif_running(adapter->netdev) && igc_is_device_id_i225(hw)) { + /* Per I225/6 HW Design Section 7.5.2.1, transmit mode + * cannot be changed dynamically. Require reset the adapter. + */ + if (netif_running(adapter->netdev) && + (igc_is_device_id_i225(hw) || !adapter->qbv_count)) { schedule_work(&adapter->reset_task); return 0; } diff --git a/drivers/net/ethernet/litex/litex_liteeth.c b/drivers/net/ethernet/litex/litex_liteeth.c index 35f24e0f0934932fd8feaa53223dbbb5c081f2ee..ffa96059079c6abd5ff7dd4db41284d4cd8c2a04 100644 --- a/drivers/net/ethernet/litex/litex_liteeth.c +++ b/drivers/net/ethernet/litex/litex_liteeth.c @@ -78,8 +78,7 @@ static int liteeth_rx(struct net_device *netdev) memcpy_fromio(data, priv->rx_base + rx_slot * priv->slot_size, len); skb->protocol = eth_type_trans(skb, netdev); - netdev->stats.rx_packets++; - netdev->stats.rx_bytes += len; + dev_sw_netstats_rx_add(netdev, len); return netif_rx(skb); @@ -185,8 +184,7 @@ static netdev_tx_t liteeth_start_xmit(struct sk_buff *skb, litex_write16(priv->base + LITEETH_READER_LENGTH, skb->len); litex_write8(priv->base + LITEETH_READER_START, 1); - netdev->stats.tx_bytes += skb->len; - netdev->stats.tx_packets++; + dev_sw_netstats_tx_add(netdev, 1, skb->len); priv->tx_slot = (priv->tx_slot + 1) % priv->num_tx_slots; dev_kfree_skb_any(skb); @@ -194,9 +192,17 @@ static netdev_tx_t liteeth_start_xmit(struct sk_buff *skb, return NETDEV_TX_OK; } +static void +liteeth_get_stats64(struct net_device *netdev, struct rtnl_link_stats64 *stats) +{ + netdev_stats_to_stats64(stats, &netdev->stats); + dev_fetch_sw_netstats(stats, netdev->tstats); +} + static const struct net_device_ops liteeth_netdev_ops = { .ndo_open = liteeth_open, .ndo_stop = liteeth_stop, + .ndo_get_stats64 = liteeth_get_stats64, .ndo_start_xmit = liteeth_start_xmit, }; @@ -242,6 +248,11 @@ static int liteeth_probe(struct platform_device *pdev) priv->netdev = netdev; priv->dev = &pdev->dev; + netdev->tstats = devm_netdev_alloc_pcpu_stats(&pdev->dev, + struct pcpu_sw_netstats); + if (!netdev->tstats) + return -ENOMEM; + irq = platform_get_irq(pdev, 0); if (irq < 0) return irq; diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c index 2cad76d0a50ef6fab802bb929948f1136451084d..acf4f6ba73a6f97b74b3c2a4e6b2581146d0f651 100644 --- a/drivers/net/ethernet/marvell/mvneta.c +++ b/drivers/net/ethernet/marvell/mvneta.c @@ -344,6 +344,15 @@ #define MVNETA_MAX_SKB_DESCS (MVNETA_MAX_TSO_SEGS * 2 + MAX_SKB_FRAGS) +/* The size of a TSO header page */ +#define MVNETA_TSO_PAGE_SIZE (2 * PAGE_SIZE) + +/* Number of TSO headers per page. This should be a power of 2 */ +#define MVNETA_TSO_PER_PAGE (MVNETA_TSO_PAGE_SIZE / TSO_HEADER_SIZE) + +/* Maximum number of TSO header pages */ +#define MVNETA_MAX_TSO_PAGES (MVNETA_MAX_TXD / MVNETA_TSO_PER_PAGE) + /* descriptor aligned size */ #define MVNETA_DESC_ALIGNED_SIZE 32 @@ -364,10 +373,6 @@ MVNETA_SKB_HEADROOM)) #define MVNETA_MAX_RX_BUF_SIZE (PAGE_SIZE - MVNETA_SKB_PAD) -#define IS_TSO_HEADER(txq, addr) \ - ((addr >= txq->tso_hdrs_phys) && \ - (addr < txq->tso_hdrs_phys + txq->size * TSO_HEADER_SIZE)) - #define MVNETA_RX_GET_BM_POOL_ID(rxd) \ (((rxd)->status & MVNETA_RXD_BM_POOL_MASK) >> MVNETA_RXD_BM_POOL_SHIFT) @@ -638,6 +643,7 @@ struct mvneta_rx_desc { #endif enum mvneta_tx_buf_type { + MVNETA_TYPE_TSO, MVNETA_TYPE_SKB, MVNETA_TYPE_XDP_TX, MVNETA_TYPE_XDP_NDO, @@ -690,10 +696,10 @@ struct mvneta_tx_queue { int next_desc_to_proc; /* DMA buffers for TSO headers */ - char *tso_hdrs; + char *tso_hdrs[MVNETA_MAX_TSO_PAGES]; /* DMA address of TSO headers */ - dma_addr_t tso_hdrs_phys; + dma_addr_t tso_hdrs_phys[MVNETA_MAX_TSO_PAGES]; /* Affinity mask for CPUs*/ cpumask_t affinity_mask; @@ -1505,7 +1511,7 @@ static void mvneta_defaults_set(struct mvneta_port *pp) */ if (txq_number == 1) txq_map = (cpu == pp->rxq_def) ? - MVNETA_CPU_TXQ_ACCESS(1) : 0; + MVNETA_CPU_TXQ_ACCESS(0) : 0; } else { txq_map = MVNETA_CPU_TXQ_ACCESS_ALL_MASK; @@ -1878,12 +1884,13 @@ static void mvneta_txq_bufs_free(struct mvneta_port *pp, mvneta_txq_inc_get(txq); - if (!IS_TSO_HEADER(txq, tx_desc->buf_phys_addr) && - buf->type != MVNETA_TYPE_XDP_TX) + if (buf->type == MVNETA_TYPE_XDP_NDO || + buf->type == MVNETA_TYPE_SKB) dma_unmap_single(pp->dev->dev.parent, tx_desc->buf_phys_addr, tx_desc->data_size, DMA_TO_DEVICE); - if (buf->type == MVNETA_TYPE_SKB && buf->skb) { + if ((buf->type == MVNETA_TYPE_TSO || + buf->type == MVNETA_TYPE_SKB) && buf->skb) { bytes_compl += buf->skb->len; pkts_compl++; dev_kfree_skb_any(buf->skb); @@ -2369,9 +2376,8 @@ mvneta_swbm_add_rx_fragment(struct mvneta_port *pp, if (data_len > 0 && sinfo->nr_frags < MAX_SKB_FRAGS) { skb_frag_t *frag = &sinfo->frags[sinfo->nr_frags++]; - skb_frag_off_set(frag, pp->rx_offset_correction); - skb_frag_size_set(frag, data_len); - __skb_frag_set_page(frag, page); + skb_frag_fill_page_desc(frag, page, + pp->rx_offset_correction, data_len); if (!xdp_buff_has_frags(xdp)) { sinfo->xdp_frags_size = *size; @@ -2661,20 +2667,72 @@ static int mvneta_rx_hwbm(struct napi_struct *napi, return rx_done; } -static inline void -mvneta_tso_put_hdr(struct sk_buff *skb, struct mvneta_tx_queue *txq) +static void mvneta_free_tso_hdrs(struct mvneta_port *pp, + struct mvneta_tx_queue *txq) +{ + struct device *dev = pp->dev->dev.parent; + int i; + + for (i = 0; i < MVNETA_MAX_TSO_PAGES; i++) { + if (txq->tso_hdrs[i]) { + dma_free_coherent(dev, MVNETA_TSO_PAGE_SIZE, + txq->tso_hdrs[i], + txq->tso_hdrs_phys[i]); + txq->tso_hdrs[i] = NULL; + } + } +} + +static int mvneta_alloc_tso_hdrs(struct mvneta_port *pp, + struct mvneta_tx_queue *txq) +{ + struct device *dev = pp->dev->dev.parent; + int i, num; + + num = DIV_ROUND_UP(txq->size, MVNETA_TSO_PER_PAGE); + for (i = 0; i < num; i++) { + txq->tso_hdrs[i] = dma_alloc_coherent(dev, MVNETA_TSO_PAGE_SIZE, + &txq->tso_hdrs_phys[i], + GFP_KERNEL); + if (!txq->tso_hdrs[i]) { + mvneta_free_tso_hdrs(pp, txq); + return -ENOMEM; + } + } + + return 0; +} + +static char *mvneta_get_tso_hdr(struct mvneta_tx_queue *txq, dma_addr_t *dma) +{ + int index, offset; + + index = txq->txq_put_index / MVNETA_TSO_PER_PAGE; + offset = (txq->txq_put_index % MVNETA_TSO_PER_PAGE) * TSO_HEADER_SIZE; + + *dma = txq->tso_hdrs_phys[index] + offset; + + return txq->tso_hdrs[index] + offset; +} + +static void mvneta_tso_put_hdr(struct sk_buff *skb, struct mvneta_tx_queue *txq, + struct tso_t *tso, int size, bool is_last) { struct mvneta_tx_buf *buf = &txq->buf[txq->txq_put_index]; int hdr_len = skb_tcp_all_headers(skb); struct mvneta_tx_desc *tx_desc; + dma_addr_t hdr_phys; + char *hdr; + + hdr = mvneta_get_tso_hdr(txq, &hdr_phys); + tso_build_hdr(skb, hdr, tso, size, is_last); tx_desc = mvneta_txq_next_desc_get(txq); tx_desc->data_size = hdr_len; tx_desc->command = mvneta_skb_tx_csum(skb); tx_desc->command |= MVNETA_TXD_F_DESC; - tx_desc->buf_phys_addr = txq->tso_hdrs_phys + - txq->txq_put_index * TSO_HEADER_SIZE; - buf->type = MVNETA_TYPE_SKB; + tx_desc->buf_phys_addr = hdr_phys; + buf->type = MVNETA_TYPE_TSO; buf->skb = NULL; mvneta_txq_inc_put(txq); @@ -2714,14 +2772,41 @@ mvneta_tso_put_data(struct net_device *dev, struct mvneta_tx_queue *txq, return 0; } +static void mvneta_release_descs(struct mvneta_port *pp, + struct mvneta_tx_queue *txq, + int first, int num) +{ + int desc_idx, i; + + desc_idx = first + num; + if (desc_idx >= txq->size) + desc_idx -= txq->size; + + for (i = num; i >= 0; i--) { + struct mvneta_tx_desc *tx_desc = txq->descs + desc_idx; + struct mvneta_tx_buf *buf = &txq->buf[desc_idx]; + + if (buf->type == MVNETA_TYPE_SKB) + dma_unmap_single(pp->dev->dev.parent, + tx_desc->buf_phys_addr, + tx_desc->data_size, + DMA_TO_DEVICE); + + mvneta_txq_desc_put(txq); + + if (desc_idx == 0) + desc_idx = txq->size; + desc_idx -= 1; + } +} + static int mvneta_tx_tso(struct sk_buff *skb, struct net_device *dev, struct mvneta_tx_queue *txq) { int hdr_len, total_len, data_left; - int desc_count = 0; + int first_desc, desc_count = 0; struct mvneta_port *pp = netdev_priv(dev); struct tso_t tso; - int i; /* Count needed descriptors */ if ((txq->count + tso_count_descs(skb)) >= txq->size) @@ -2732,22 +2817,19 @@ static int mvneta_tx_tso(struct sk_buff *skb, struct net_device *dev, return 0; } + first_desc = txq->txq_put_index; + /* Initialize the TSO handler, and prepare the first payload */ hdr_len = tso_start(skb, &tso); total_len = skb->len - hdr_len; while (total_len > 0) { - char *hdr; - data_left = min_t(int, skb_shinfo(skb)->gso_size, total_len); total_len -= data_left; desc_count++; /* prepare packet headers: MAC + IP + TCP */ - hdr = txq->tso_hdrs + txq->txq_put_index * TSO_HEADER_SIZE; - tso_build_hdr(skb, hdr, &tso, data_left, total_len == 0); - - mvneta_tso_put_hdr(skb, txq); + mvneta_tso_put_hdr(skb, txq, &tso, data_left, total_len == 0); while (data_left > 0) { int size; @@ -2772,15 +2854,7 @@ static int mvneta_tx_tso(struct sk_buff *skb, struct net_device *dev, /* Release all used data descriptors; header descriptors must not * be DMA-unmapped. */ - for (i = desc_count - 1; i >= 0; i--) { - struct mvneta_tx_desc *tx_desc = txq->descs + i; - if (!IS_TSO_HEADER(txq, tx_desc->buf_phys_addr)) - dma_unmap_single(pp->dev->dev.parent, - tx_desc->buf_phys_addr, - tx_desc->data_size, - DMA_TO_DEVICE); - mvneta_txq_desc_put(txq); - } + mvneta_release_descs(pp, txq, first_desc, desc_count - 1); return 0; } @@ -2790,6 +2864,7 @@ static int mvneta_tx_frag_process(struct mvneta_port *pp, struct sk_buff *skb, { struct mvneta_tx_desc *tx_desc; int i, nr_frags = skb_shinfo(skb)->nr_frags; + int first_desc = txq->txq_put_index; for (i = 0; i < nr_frags; i++) { struct mvneta_tx_buf *buf = &txq->buf[txq->txq_put_index]; @@ -2828,15 +2903,7 @@ static int mvneta_tx_frag_process(struct mvneta_port *pp, struct sk_buff *skb, /* Release all descriptors that were used to map fragments of * this packet, as well as the corresponding DMA mappings */ - for (i = i - 1; i >= 0; i--) { - tx_desc = txq->descs + i; - dma_unmap_single(pp->dev->dev.parent, - tx_desc->buf_phys_addr, - tx_desc->data_size, - DMA_TO_DEVICE); - mvneta_txq_desc_put(txq); - } - + mvneta_release_descs(pp, txq, first_desc, i - 1); return -ENOMEM; } @@ -3457,7 +3524,7 @@ static void mvneta_rxq_deinit(struct mvneta_port *pp, static int mvneta_txq_sw_init(struct mvneta_port *pp, struct mvneta_tx_queue *txq) { - int cpu; + int cpu, err; txq->size = pp->tx_ring_size; @@ -3482,11 +3549,9 @@ static int mvneta_txq_sw_init(struct mvneta_port *pp, return -ENOMEM; /* Allocate DMA buffers for TSO MAC/IP/TCP headers */ - txq->tso_hdrs = dma_alloc_coherent(pp->dev->dev.parent, - txq->size * TSO_HEADER_SIZE, - &txq->tso_hdrs_phys, GFP_KERNEL); - if (!txq->tso_hdrs) - return -ENOMEM; + err = mvneta_alloc_tso_hdrs(pp, txq); + if (err) + return err; /* Setup XPS mapping */ if (pp->neta_armada3700) @@ -3538,10 +3603,7 @@ static void mvneta_txq_sw_deinit(struct mvneta_port *pp, kfree(txq->buf); - if (txq->tso_hdrs) - dma_free_coherent(pp->dev->dev.parent, - txq->size * TSO_HEADER_SIZE, - txq->tso_hdrs, txq->tso_hdrs_phys); + mvneta_free_tso_hdrs(pp, txq); if (txq->descs) dma_free_coherent(pp->dev->dev.parent, txq->size * MVNETA_DESC_ALIGNED_SIZE, @@ -3550,7 +3612,6 @@ static void mvneta_txq_sw_deinit(struct mvneta_port *pp, netdev_tx_reset_queue(nq); txq->buf = NULL; - txq->tso_hdrs = NULL; txq->descs = NULL; txq->last_desc = 0; txq->next_desc_to_proc = 0; @@ -3941,8 +4002,8 @@ static void mvneta_pcs_get_state(struct phylink_pcs *pcs, state->pause |= MLO_PAUSE_TX; } -static int mvneta_pcs_config(struct phylink_pcs *pcs, - unsigned int mode, phy_interface_t interface, +static int mvneta_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode, + phy_interface_t interface, const unsigned long *advertising, bool permit_pause_to_mac) { @@ -3955,7 +4016,7 @@ static int mvneta_pcs_config(struct phylink_pcs *pcs, MVNETA_GMAC_AN_FLOW_CTRL_EN | MVNETA_GMAC_AN_DUPLEX_EN; - if (phylink_autoneg_inband(mode)) { + if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED) { mask |= MVNETA_GMAC_CONFIG_MII_SPEED | MVNETA_GMAC_CONFIG_GMII_SPEED | MVNETA_GMAC_CONFIG_FULL_DUPLEX; @@ -4295,7 +4356,7 @@ static void mvneta_percpu_elect(struct mvneta_port *pp) */ if (txq_number == 1) txq_map = (cpu == elected_cpu) ? - MVNETA_CPU_TXQ_ACCESS(1) : 0; + MVNETA_CPU_TXQ_ACCESS(0) : 0; else txq_map = mvreg_read(pp, MVNETA_CPU_MAP(cpu)) & MVNETA_CPU_TXQ_ACCESS_ALL_MASK; @@ -5457,6 +5518,7 @@ static int mvneta_probe(struct platform_device *pdev) clk_prepare_enable(pp->clk_bus); pp->phylink_pcs.ops = &mvneta_phylink_pcs_ops; + pp->phylink_pcs.neg_mode = true; pp->phylink_config.dev = &dev->dev; pp->phylink_config.type = PHYLINK_NETDEV; @@ -5821,6 +5883,8 @@ static int __init mvneta_driver_init(void) { int ret; + BUILD_BUG_ON_NOT_POWER_OF_2(MVNETA_TSO_PER_PAGE); + ret = cpuhp_setup_state_multi(CPUHP_AP_ONLINE_DYN, "net/mvneta:online", mvneta_cpu_online, mvneta_cpu_down_prepare); diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c index adc9536119135744de095d316e585e16385561ea..1fec84b4c068dc2a909a31a2131ebf9a10518b6d 100644 --- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c +++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c @@ -6168,8 +6168,7 @@ static void mvpp2_xlg_pcs_get_state(struct phylink_pcs *pcs, state->pause |= MLO_PAUSE_RX; } -static int mvpp2_xlg_pcs_config(struct phylink_pcs *pcs, - unsigned int mode, +static int mvpp2_xlg_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode, phy_interface_t interface, const unsigned long *advertising, bool permit_pause_to_mac) @@ -6232,7 +6231,7 @@ static void mvpp2_gmac_pcs_get_state(struct phylink_pcs *pcs, state->pause |= MLO_PAUSE_TX; } -static int mvpp2_gmac_pcs_config(struct phylink_pcs *pcs, unsigned int mode, +static int mvpp2_gmac_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode, phy_interface_t interface, const unsigned long *advertising, bool permit_pause_to_mac) @@ -6246,7 +6245,7 @@ static int mvpp2_gmac_pcs_config(struct phylink_pcs *pcs, unsigned int mode, MVPP2_GMAC_FLOW_CTRL_AUTONEG | MVPP2_GMAC_AN_DUPLEX_EN; - if (phylink_autoneg_inband(mode)) { + if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED) { mask |= MVPP2_GMAC_CONFIG_MII_SPEED | MVPP2_GMAC_CONFIG_GMII_SPEED | MVPP2_GMAC_CONFIG_FULL_DUPLEX; @@ -6649,8 +6648,9 @@ static void mvpp2_acpi_start(struct mvpp2_port *port) mvpp2_mac_prepare(&port->phylink_config, MLO_AN_INBAND, port->phy_interface); mvpp2_mac_config(&port->phylink_config, MLO_AN_INBAND, &state); - pcs->ops->pcs_config(pcs, MLO_AN_INBAND, port->phy_interface, - state.advertising, false); + pcs->ops->pcs_config(pcs, PHYLINK_PCS_NEG_INBAND_ENABLED, + port->phy_interface, state.advertising, + false); mvpp2_mac_finish(&port->phylink_config, MLO_AN_INBAND, port->phy_interface); mvpp2_mac_link_up(&port->phylink_config, NULL, @@ -6896,7 +6896,9 @@ static int mvpp2_port_probe(struct platform_device *pdev, dev->dev.of_node = port_node; port->pcs_gmac.ops = &mvpp2_phylink_gmac_pcs_ops; + port->pcs_gmac.neg_mode = true; port->pcs_xlg.ops = &mvpp2_phylink_xlg_pcs_ops; + port->pcs_xlg.neg_mode = true; if (!mvpp2_use_acpi_compat_mode(port_fwnode)) { port->phylink_config.dev = &dev->dev; diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_rx.c b/drivers/net/ethernet/marvell/octeon_ep/octep_rx.c index 392d9b0da0d7a8503f3cd9a677c3ddfdb2644e8a..3c43f8078528508e457a9ff789909205704e4099 100644 --- a/drivers/net/ethernet/marvell/octeon_ep/octep_rx.c +++ b/drivers/net/ethernet/marvell/octeon_ep/octep_rx.c @@ -158,7 +158,7 @@ static int octep_setup_oq(struct octep_device *oct, int q_no) goto desc_dma_alloc_err; } - oq->buff_info = vzalloc(oq->max_count * OCTEP_OQ_RECVBUF_SIZE); + oq->buff_info = vcalloc(oq->max_count, OCTEP_OQ_RECVBUF_SIZE); if (unlikely(!oq->buff_info)) { dev_err(&oct->pdev->dev, "Failed to allocate buffer info for OQ-%d\n", q_no); diff --git a/drivers/net/ethernet/marvell/octeontx2/Kconfig b/drivers/net/ethernet/marvell/octeontx2/Kconfig index 993ac180a5db832a8b988acf8533d98d88339723..a32d85d6f599f2cdf95c707a364b404d7434c64f 100644 --- a/drivers/net/ethernet/marvell/octeontx2/Kconfig +++ b/drivers/net/ethernet/marvell/octeontx2/Kconfig @@ -32,6 +32,7 @@ config OCTEONTX2_PF tristate "Marvell OcteonTX2 NIC Physical Function driver" select OCTEONTX2_MBOX select NET_DEVLINK + select PAGE_POOL depends on (64BIT && COMPILE_TEST) || ARM64 select DIMLIB depends on PCI diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cgx.c b/drivers/net/ethernet/marvell/octeontx2/af/cgx.c index bd77152bb8d7c7f1f338e81ecc0d6c53e3999877..592037f4e55b60670723a63ccba48258cf0c83b7 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/cgx.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/cgx.c @@ -169,6 +169,9 @@ void cgx_lmac_write(int cgx_id, int lmac_id, u64 offset, u64 val) { struct cgx *cgx_dev = cgx_get_pdata(cgx_id); + /* Software must not access disabled LMAC registers */ + if (!is_lmac_valid(cgx_dev, lmac_id)) + return; cgx_write(cgx_dev, lmac_id, offset, val); } @@ -176,6 +179,10 @@ u64 cgx_lmac_read(int cgx_id, int lmac_id, u64 offset) { struct cgx *cgx_dev = cgx_get_pdata(cgx_id); + /* Software must not access disabled LMAC registers */ + if (!is_lmac_valid(cgx_dev, lmac_id)) + return 0; + return cgx_read(cgx_dev, lmac_id, offset); } @@ -530,14 +537,15 @@ static u32 cgx_get_lmac_fifo_len(void *cgxd, int lmac_id) int cgx_lmac_internal_loopback(void *cgxd, int lmac_id, bool enable) { struct cgx *cgx = cgxd; - u8 lmac_type; + struct lmac *lmac; u64 cfg; if (!is_lmac_valid(cgx, lmac_id)) return -ENODEV; - lmac_type = cgx->mac_ops->get_lmac_type(cgx, lmac_id); - if (lmac_type == LMAC_MODE_SGMII || lmac_type == LMAC_MODE_QSGMII) { + lmac = lmac_pdata(lmac_id, cgx); + if (lmac->lmac_type == LMAC_MODE_SGMII || + lmac->lmac_type == LMAC_MODE_QSGMII) { cfg = cgx_read(cgx, lmac_id, CGXX_GMP_PCS_MRX_CTL); if (enable) cfg |= CGXX_GMP_PCS_MRX_CTL_LBK; @@ -1556,6 +1564,23 @@ int cgx_lmac_linkup_start(void *cgxd) return 0; } +int cgx_lmac_reset(void *cgxd, int lmac_id, u8 pf_req_flr) +{ + struct cgx *cgx = cgxd; + u64 cfg; + + if (!is_lmac_valid(cgx, lmac_id)) + return -ENODEV; + + /* Resetting PFC related CSRs */ + cfg = 0xff; + cgx_write(cgxd, lmac_id, CGXX_CMRX_RX_LOGL_XON, cfg); + + if (pf_req_flr) + cgx_lmac_internal_loopback(cgxd, lmac_id, false); + return 0; +} + static int cgx_configure_interrupt(struct cgx *cgx, struct lmac *lmac, int cnt, bool req_free) { @@ -1675,6 +1700,7 @@ static int cgx_lmac_init(struct cgx *cgx) cgx->lmac_idmap[lmac->lmac_id] = lmac; set_bit(lmac->lmac_id, &cgx->lmac_bmap); cgx->mac_ops->mac_pause_frm_config(cgx, lmac->lmac_id, true); + lmac->lmac_type = cgx->mac_ops->get_lmac_type(cgx, lmac->lmac_id); } return cgx_lmac_verify_fwi_version(cgx); @@ -1771,6 +1797,7 @@ static struct mac_ops cgx_mac_ops = { .mac_tx_enable = cgx_lmac_tx_enable, .pfc_config = cgx_lmac_pfc_config, .mac_get_pfc_frm_cfg = cgx_lmac_get_pfc_frm_cfg, + .mac_reset = cgx_lmac_reset, }; static int cgx_probe(struct pci_dev *pdev, const struct pci_device_id *id) diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cgx.h b/drivers/net/ethernet/marvell/octeontx2/af/cgx.h index 5a20d93004c7181a37a2c862f57edc8ad10a6957..5741141796880a6068bd8560c6f56cf945906550 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/cgx.h +++ b/drivers/net/ethernet/marvell/octeontx2/af/cgx.h @@ -35,6 +35,7 @@ #define CGXX_CMRX_INT_ENA_W1S 0x058 #define CGXX_CMRX_RX_ID_MAP 0x060 #define CGXX_CMRX_RX_STAT0 0x070 +#define CGXX_CMRX_RX_LOGL_XON 0x100 #define CGXX_CMRX_RX_LMACS 0x128 #define CGXX_CMRX_RX_DMAC_CTL0 (0x1F8 + mac_ops->csr_offset) #define CGX_DMAC_CTL0_CAM_ENABLE BIT_ULL(3) @@ -181,4 +182,5 @@ int cgx_lmac_get_pfc_frm_cfg(void *cgxd, int lmac_id, u8 *tx_pause, u8 *rx_pause); int verify_lmac_fc_cfg(void *cgxd, int lmac_id, u8 tx_pause, u8 rx_pause, int pfvf_idx); +int cgx_lmac_reset(void *cgxd, int lmac_id, u8 pf_req_flr); #endif /* CGX_H */ diff --git a/drivers/net/ethernet/marvell/octeontx2/af/common.h b/drivers/net/ethernet/marvell/octeontx2/af/common.h index 8931864ee110c4d88fa8233d68bce579fb503594..2436c1ff9ba4cfdeefc13446bfe68bfee07509cf 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/common.h +++ b/drivers/net/ethernet/marvell/octeontx2/af/common.h @@ -142,9 +142,16 @@ enum nix_scheduler { #define TXSCH_RR_QTM_MAX ((1 << 24) - 1) #define TXSCH_TL1_DFLT_RR_QTM TXSCH_RR_QTM_MAX -#define TXSCH_TL1_DFLT_RR_PRIO (0x1ull) +#define TXSCH_TL1_DFLT_RR_PRIO (0x7ull) #define CN10K_MAX_DWRR_WEIGHT 16384 /* Weight is 14bit on CN10K */ +/* Don't change the order as on CN10K (except CN10KB) + * SMQX_CFG[SDP] value should be 1 for SDP flows. + */ +#define SMQ_LINK_TYPE_RPM 0 +#define SMQ_LINK_TYPE_SDP 1 +#define SMQ_LINK_TYPE_LBK 2 + /* Min/Max packet sizes, excluding FCS */ #define NIC_HW_MIN_FRS 40 #define NIC_HW_MAX_FRS 9212 diff --git a/drivers/net/ethernet/marvell/octeontx2/af/lmac_common.h b/drivers/net/ethernet/marvell/octeontx2/af/lmac_common.h index 39aaf0e4467dcffddc77f359e59987eb2fefe0b6..0b4cba03f2e8371012af5f71e3b763dc7dcac7c3 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/lmac_common.h +++ b/drivers/net/ethernet/marvell/octeontx2/af/lmac_common.h @@ -24,6 +24,7 @@ * @cgx: parent cgx port * @mcast_filters_count: Number of multicast filters installed * @lmac_id: lmac port id + * @lmac_type: lmac type like SGMII/XAUI * @cmd_pend: flag set before new command is started * flag cleared after command response is received * @name: lmac port name @@ -43,6 +44,7 @@ struct lmac { struct cgx *cgx; u8 mcast_filters_count; u8 lmac_id; + u8 lmac_type; bool cmd_pend; char *name; }; @@ -125,6 +127,7 @@ struct mac_ops { int (*mac_get_pfc_frm_cfg)(void *cgxd, int lmac_id, u8 *tx_pause, u8 *rx_pause); + int (*mac_reset)(void *cgxd, int lmac_id, u8 pf_req_flr); /* FEC stats */ int (*get_fec_stats)(void *cgxd, int lmac_id, diff --git a/drivers/net/ethernet/marvell/octeontx2/af/mbox.h b/drivers/net/ethernet/marvell/octeontx2/af/mbox.h index 6389ed83637dc639dfdd7eefc6bfea7b2a4333d7..eba307eee2b2b97223688a16e06621e8b23e681d 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/mbox.h +++ b/drivers/net/ethernet/marvell/octeontx2/af/mbox.h @@ -1080,6 +1080,8 @@ struct nix_vtag_config_rsp { */ }; +#define NIX_FLOW_KEY_TYPE_L3_L4_MASK (~(0xf << 28)) + struct nix_rss_flowkey_cfg { struct mbox_msghdr hdr; int mcam_index; /* MCAM entry index to modify */ @@ -1105,6 +1107,10 @@ struct nix_rss_flowkey_cfg { #define NIX_FLOW_KEY_TYPE_IPV4_PROTO BIT(21) #define NIX_FLOW_KEY_TYPE_AH BIT(22) #define NIX_FLOW_KEY_TYPE_ESP BIT(23) +#define NIX_FLOW_KEY_TYPE_L4_DST_ONLY BIT(28) +#define NIX_FLOW_KEY_TYPE_L4_SRC_ONLY BIT(29) +#define NIX_FLOW_KEY_TYPE_L3_DST_ONLY BIT(30) +#define NIX_FLOW_KEY_TYPE_L3_SRC_ONLY BIT(31) u32 flowkey_cfg; /* Flowkey types selected */ u8 group; /* RSS context or group */ }; @@ -1151,6 +1157,7 @@ struct nix_rx_cfg { struct mbox_msghdr hdr; #define NIX_RX_OL3_VERIFY BIT(0) #define NIX_RX_OL4_VERIFY BIT(1) +#define NIX_RX_DROP_RE BIT(2) u8 len_verify; /* Outer L3/L4 len check */ #define NIX_RX_CSUM_OL4_VERIFY BIT(0) u8 csum_verify; /* Outer L4 checksum verification */ @@ -1239,7 +1246,9 @@ struct nix_hw_info { u16 min_mtu; u32 rpm_dwrr_mtu; u32 sdp_dwrr_mtu; - u64 rsvd[16]; /* Add reserved fields for future expansion */ + u32 lbk_dwrr_mtu; + u32 rsvd32[1]; + u64 rsvd[15]; /* Add reserved fields for future expansion */ }; struct nix_bandprof_alloc_req { diff --git a/drivers/net/ethernet/marvell/octeontx2/af/ptp.c b/drivers/net/ethernet/marvell/octeontx2/af/ptp.c index 3411e2e47d46b70976c14eff1411c11394539036..0ee420a489fc4980e6356210bcb7b3e0a71a0561 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/ptp.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/ptp.c @@ -208,7 +208,7 @@ struct ptp *ptp_get(void) /* Check driver is bound to PTP block */ if (!ptp) ptp = ERR_PTR(-EPROBE_DEFER); - else + else if (!IS_ERR(ptp)) pci_dev_get(ptp->pdev); return ptp; @@ -388,11 +388,10 @@ static int ptp_extts_on(struct ptp *ptp, int on) static int ptp_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { - struct device *dev = &pdev->dev; struct ptp *ptp; int err; - ptp = devm_kzalloc(dev, sizeof(*ptp), GFP_KERNEL); + ptp = kzalloc(sizeof(*ptp), GFP_KERNEL); if (!ptp) { err = -ENOMEM; goto error; @@ -428,20 +427,19 @@ static int ptp_probe(struct pci_dev *pdev, return 0; error_free: - devm_kfree(dev, ptp); + kfree(ptp); error: /* For `ptp_get()` we need to differentiate between the case * when the core has not tried to probe this device and the case when - * the probe failed. In the later case we pretend that the - * initialization was successful and keep the error in + * the probe failed. In the later case we keep the error in * `dev->driver_data`. */ pci_set_drvdata(pdev, ERR_PTR(err)); if (!first_ptp_block) first_ptp_block = ERR_PTR(err); - return 0; + return err; } static void ptp_remove(struct pci_dev *pdev) @@ -449,16 +447,17 @@ static void ptp_remove(struct pci_dev *pdev) struct ptp *ptp = pci_get_drvdata(pdev); u64 clock_cfg; - if (cn10k_ptp_errata(ptp) && hrtimer_active(&ptp->hrtimer)) - hrtimer_cancel(&ptp->hrtimer); - if (IS_ERR_OR_NULL(ptp)) return; + if (cn10k_ptp_errata(ptp) && hrtimer_active(&ptp->hrtimer)) + hrtimer_cancel(&ptp->hrtimer); + /* Disable PTP clock */ clock_cfg = readq(ptp->reg_base + PTP_CLOCK_CFG); clock_cfg &= ~PTP_CLOCK_CFG_PTP_EN; writeq(clock_cfg, ptp->reg_base + PTP_CLOCK_CFG); + kfree(ptp); } static const struct pci_device_id ptp_id_table[] = { diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rpm.c b/drivers/net/ethernet/marvell/octeontx2/af/rpm.c index de0d88dd10d65c74803e44e330a4cbf78e2eb00d..b4fcb20c3f4fddb5512fcd2cb211fba521dc7b76 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rpm.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rpm.c @@ -37,6 +37,7 @@ static struct mac_ops rpm_mac_ops = { .mac_tx_enable = rpm_lmac_tx_enable, .pfc_config = rpm_lmac_pfc_config, .mac_get_pfc_frm_cfg = rpm_lmac_get_pfc_frm_cfg, + .mac_reset = rpm_lmac_reset, }; static struct mac_ops rpm2_mac_ops = { @@ -47,7 +48,7 @@ static struct mac_ops rpm2_mac_ops = { .int_set_reg = RPM2_CMRX_SW_INT_ENA_W1S, .irq_offset = 1, .int_ena_bit = BIT_ULL(0), - .lmac_fwi = RPM_LMAC_FWI, + .lmac_fwi = RPM2_LMAC_FWI, .non_contiguous_serdes_lane = true, .rx_stats_cnt = 43, .tx_stats_cnt = 34, @@ -68,6 +69,7 @@ static struct mac_ops rpm2_mac_ops = { .mac_tx_enable = rpm_lmac_tx_enable, .pfc_config = rpm_lmac_pfc_config, .mac_get_pfc_frm_cfg = rpm_lmac_get_pfc_frm_cfg, + .mac_reset = rpm_lmac_reset, }; bool is_dev_rpm2(void *rpmd) @@ -537,14 +539,15 @@ u32 rpm2_get_lmac_fifo_len(void *rpmd, int lmac_id) int rpm_lmac_internal_loopback(void *rpmd, int lmac_id, bool enable) { rpm_t *rpm = rpmd; - u8 lmac_type; + struct lmac *lmac; u64 cfg; if (!is_lmac_valid(rpm, lmac_id)) return -ENODEV; - lmac_type = rpm->mac_ops->get_lmac_type(rpm, lmac_id); - if (lmac_type == LMAC_MODE_QSGMII || lmac_type == LMAC_MODE_SGMII) { + lmac = lmac_pdata(lmac_id, rpm); + if (lmac->lmac_type == LMAC_MODE_QSGMII || + lmac->lmac_type == LMAC_MODE_SGMII) { dev_err(&rpm->pdev->dev, "loopback not supported for LPC mode\n"); return 0; } @@ -713,3 +716,24 @@ int rpm_get_fec_stats(void *rpmd, int lmac_id, struct cgx_fec_stats_rsp *rsp) return 0; } + +int rpm_lmac_reset(void *rpmd, int lmac_id, u8 pf_req_flr) +{ + u64 rx_logl_xon, cfg; + rpm_t *rpm = rpmd; + + if (!is_lmac_valid(rpm, lmac_id)) + return -ENODEV; + + /* Resetting PFC related CSRs */ + rx_logl_xon = is_dev_rpm2(rpm) ? RPM2_CMRX_RX_LOGL_XON : + RPMX_CMRX_RX_LOGL_XON; + cfg = 0xff; + + rpm_write(rpm, lmac_id, rx_logl_xon, cfg); + + if (pf_req_flr) + rpm_lmac_internal_loopback(rpm, lmac_id, false); + + return 0; +} diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rpm.h b/drivers/net/ethernet/marvell/octeontx2/af/rpm.h index 22147b4c21370720559837d8f5c1e9b784e883e1..b79cfbc6f87705f38627ae83d55a329cf0c4c922 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rpm.h +++ b/drivers/net/ethernet/marvell/octeontx2/af/rpm.h @@ -74,6 +74,7 @@ #define RPMX_MTI_MAC100X_CL01_PAUSE_QUANTA 0x80A8 #define RPMX_MTI_MAC100X_CL89_PAUSE_QUANTA 0x8108 #define RPM_DEFAULT_PAUSE_TIME 0x7FF +#define RPMX_CMRX_RX_LOGL_XON 0x4100 #define RPMX_MTI_MAC100X_XIF_MODE 0x8100 #define RPMX_ONESTEP_ENABLE BIT_ULL(5) @@ -94,7 +95,8 @@ /* CN10KB CSR Declaration */ #define RPM2_CMRX_SW_INT 0x1b0 -#define RPM2_CMRX_SW_INT_ENA_W1S 0x1b8 +#define RPM2_CMRX_SW_INT_ENA_W1S 0x1c8 +#define RPM2_LMAC_FWI 0x12 #define RPM2_CMR_CHAN_MSK_OR 0x3120 #define RPM2_CMR_RX_OVR_BP_EN BIT_ULL(2) #define RPM2_CMR_RX_OVR_BP_BP BIT_ULL(1) @@ -131,4 +133,5 @@ int rpm_lmac_get_pfc_frm_cfg(void *rpmd, int lmac_id, u8 *tx_pause, int rpm2_get_nr_lmacs(void *rpmd); bool is_dev_rpm2(void *rpmd); int rpm_get_fec_stats(void *cgxd, int lmac_id, struct cgx_fec_stats_rsp *rsp); +int rpm_lmac_reset(void *rpmd, int lmac_id, u8 pf_req_flr); #endif /* RPM_H */ diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu.c index 9f673bda9dbdd5898e8c58b821cd8178e8c3bf55..73df2d564545587ee891221070bce8853f2832b3 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu.c @@ -2629,6 +2629,7 @@ static void __rvu_flr_handler(struct rvu *rvu, u16 pcifunc) * Since LF is detached use LF number as -1. */ rvu_npc_free_mcam_entries(rvu, pcifunc, -1); + rvu_mac_reset(rvu, pcifunc); mutex_unlock(&rvu->flr_lock); } @@ -3044,9 +3045,8 @@ static int rvu_flr_init(struct rvu *rvu) cfg | BIT_ULL(22)); } - rvu->flr_wq = alloc_workqueue("rvu_afpf_flr", - WQ_UNBOUND | WQ_HIGHPRI | WQ_MEM_RECLAIM, - 1); + rvu->flr_wq = alloc_ordered_workqueue("rvu_afpf_flr", + WQ_HIGHPRI | WQ_MEM_RECLAIM); if (!rvu->flr_wq) return -ENOMEM; @@ -3252,7 +3252,7 @@ static int rvu_probe(struct pci_dev *pdev, const struct pci_device_id *id) rvu->ptp = ptp_get(); if (IS_ERR(rvu->ptp)) { err = PTR_ERR(rvu->ptp); - if (err == -EPROBE_DEFER) + if (err) goto err_release_regions; rvu->ptp = NULL; } diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h index d655bf04a483dd3d3513ad7e2d092241d5bdb804..e8e65fd7888dfb283b3b9da41a6b980fd939732a 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h @@ -23,6 +23,7 @@ #define PCI_DEVID_OCTEONTX2_LBK 0xA061 /* Subsystem Device ID */ +#define PCI_SUBSYS_DEVID_98XX 0xB100 #define PCI_SUBSYS_DEVID_96XX 0xB200 #define PCI_SUBSYS_DEVID_CN10K_A 0xB900 #define PCI_SUBSYS_DEVID_CNF10K_B 0xBC00 @@ -285,6 +286,22 @@ struct nix_mark_format { u32 *cfg; }; +/* smq(flush) to tl1 cir/pir info */ +struct nix_smq_tree_ctx { + u64 cir_off; + u64 cir_val; + u64 pir_off; + u64 pir_val; +}; + +/* smq flush context */ +struct nix_smq_flush_ctx { + int smq; + u16 tl1_schq; + u16 tl2_schq; + struct nix_smq_tree_ctx smq_tree_ctx[NIX_TXSCH_LVL_CNT]; +}; + struct npc_pkind { struct rsrc_bmap rsrc; u32 *pfchan_map; @@ -346,6 +363,7 @@ struct hw_cap { bool per_pf_mbox_regs; /* PF mbox specified in per PF registers ? */ bool programmable_chans; /* Channels programmable ? */ bool ipolicer; + bool nix_multiple_dwrr_mtu; /* Multiple DWRR_MTU to choose from */ bool npc_hash_extract; /* Hash extract enabled ? */ bool npc_exact_match_enabled; /* Exact match supported ? */ }; @@ -669,6 +687,16 @@ static inline u16 rvu_nix_chan_cpt(struct rvu *rvu, u8 chan) return rvu->hw->cpt_chan_base + chan; } +static inline bool is_rvu_supports_nix1(struct rvu *rvu) +{ + struct pci_dev *pdev = rvu->pdev; + + if (pdev->subsystem_device == PCI_SUBSYS_DEVID_98XX) + return true; + + return false; +} + /* Function Prototypes * RVU */ @@ -802,8 +830,11 @@ int nix_aq_context_read(struct rvu *rvu, struct nix_hw *nix_hw, struct nix_cn10k_aq_enq_rsp *aq_rsp, u16 pcifunc, u8 ctype, u32 qidx); int rvu_get_nix_blkaddr(struct rvu *rvu, u16 pcifunc); +int nix_get_dwrr_mtu_reg(struct rvu_hwinfo *hw, int smq_link_type); u32 convert_dwrr_mtu_to_bytes(u8 dwrr_mtu); u32 convert_bytes_to_dwrr_mtu(u32 bytes); +void rvu_nix_tx_tl2_cfg(struct rvu *rvu, int blkaddr, u16 pcifunc, + struct nix_txsch *txsch, bool enable); /* NPC APIs */ void rvu_npc_freemem(struct rvu *rvu); @@ -864,6 +895,7 @@ int rvu_cgx_config_tx(void *cgxd, int lmac_id, bool enable); int rvu_cgx_prio_flow_ctrl_cfg(struct rvu *rvu, u16 pcifunc, u8 tx_pause, u8 rx_pause, u16 pfc_en); int rvu_cgx_cfg_pause_frm(struct rvu *rvu, u16 pcifunc, u8 tx_pause, u8 rx_pause); +void rvu_mac_reset(struct rvu *rvu, u16 pcifunc); u32 rvu_cgx_get_lmac_fifolen(struct rvu *rvu, int cgx, int lmac); int npc_get_nixlf_mcam_index(struct npc_mcam *mcam, u16 pcifunc, int nixlf, int type); diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c index 83b342fa8d753cd880ffd6a29bf8e82d1775b9ba..095b2cc4a69994ac8f4ca2a81f874866e5d1fc05 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c @@ -114,7 +114,7 @@ static void rvu_map_cgx_nix_block(struct rvu *rvu, int pf, p2x = cgx_lmac_get_p2x(cgx_id, lmac_id); /* Firmware sets P2X_SELECT as either NIX0 or NIX1 */ pfvf->nix_blkaddr = BLKADDR_NIX0; - if (p2x == CMR_P2X_SEL_NIX1) + if (is_rvu_supports_nix1(rvu) && p2x == CMR_P2X_SEL_NIX1) pfvf->nix_blkaddr = BLKADDR_NIX1; } @@ -763,7 +763,7 @@ static int rvu_cgx_ptp_rx_cfg(struct rvu *rvu, u16 pcifunc, bool enable) cgxd = rvu_cgx_pdata(cgx_id, rvu); mac_ops = get_mac_ops(cgxd); - mac_ops->mac_enadis_ptp_config(cgxd, lmac_id, true); + mac_ops->mac_enadis_ptp_config(cgxd, lmac_id, enable); /* If PTP is enabled then inform NPC that packets to be * parsed by this PF will have their data shifted by 8 bytes * and if PTP is disabled then no shift is required @@ -1250,3 +1250,21 @@ int rvu_mbox_handler_cgx_prio_flow_ctrl_cfg(struct rvu *rvu, mac_ops->mac_get_pfc_frm_cfg(cgxd, lmac_id, &rsp->tx_pause, &rsp->rx_pause); return err; } + +void rvu_mac_reset(struct rvu *rvu, u16 pcifunc) +{ + int pf = rvu_get_pf(pcifunc); + struct mac_ops *mac_ops; + struct cgx *cgxd; + u8 cgx, lmac; + + if (!is_pf_cgxmapped(rvu, pf)) + return; + + rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx, &lmac); + cgxd = rvu_cgx_pdata(cgx, rvu); + mac_ops = get_mac_ops(cgxd); + + if (mac_ops->mac_reset(cgxd, lmac, !is_vf(pcifunc))) + dev_err(rvu->dev, "Failed to reset MAC\n"); +} diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c index 9533b1d929604a097981c5ae703bf895db5bd73d..3b26893efdf8b154e885bc791083249b452072d6 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c @@ -1222,6 +1222,11 @@ static int rvu_dbg_npa_ctx_display(struct seq_file *m, void *unused, int ctype) for (aura = id; aura < max_id; aura++) { aq_req.aura_id = aura; + + /* Skip if queue is uninitialized */ + if (ctype == NPA_AQ_CTYPE_POOL && !test_bit(aura, pfvf->pool_bmap)) + continue; + seq_printf(m, "======%s : %d=======\n", (ctype == NPA_AQ_CTYPE_AURA) ? "AURA" : "POOL", aq_req.aura_id); diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_devlink.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_devlink.c index e4407f09c9d34bb27213d22772161769b9745bc1..41df5ac23f927f1e3e6f1fc478e36d28501fdbe8 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_devlink.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_devlink.c @@ -1413,7 +1413,8 @@ static int rvu_af_dl_dwrr_mtu_set(struct devlink *devlink, u32 id, u64 dwrr_mtu; dwrr_mtu = convert_bytes_to_dwrr_mtu(ctx->val.vu32); - rvu_write64(rvu, BLKADDR_NIX0, NIX_AF_DWRR_RPM_MTU, dwrr_mtu); + rvu_write64(rvu, BLKADDR_NIX0, + nix_get_dwrr_mtu_reg(rvu->hw, SMQ_LINK_TYPE_RPM), dwrr_mtu); return 0; } @@ -1428,7 +1429,8 @@ static int rvu_af_dl_dwrr_mtu_get(struct devlink *devlink, u32 id, if (!rvu->hw->cap.nix_common_dwrr_mtu) return -EOPNOTSUPP; - dwrr_mtu = rvu_read64(rvu, BLKADDR_NIX0, NIX_AF_DWRR_RPM_MTU); + dwrr_mtu = rvu_read64(rvu, BLKADDR_NIX0, + nix_get_dwrr_mtu_reg(rvu->hw, SMQ_LINK_TYPE_RPM)); ctx->val.vu32 = convert_dwrr_mtu_to_bytes(dwrr_mtu); return 0; @@ -1438,6 +1440,7 @@ enum rvu_af_dl_param_id { RVU_AF_DEVLINK_PARAM_ID_BASE = DEVLINK_PARAM_GENERIC_ID_MAX, RVU_AF_DEVLINK_PARAM_ID_DWRR_MTU, RVU_AF_DEVLINK_PARAM_ID_NPC_EXACT_FEATURE_DISABLE, + RVU_AF_DEVLINK_PARAM_ID_NPC_MCAM_ZONE_PERCENT, }; static int rvu_af_npc_exact_feature_get(struct devlink *devlink, u32 id, @@ -1494,6 +1497,67 @@ static int rvu_af_npc_exact_feature_validate(struct devlink *devlink, u32 id, return -EFAULT; } +static int rvu_af_dl_npc_mcam_high_zone_percent_get(struct devlink *devlink, u32 id, + struct devlink_param_gset_ctx *ctx) +{ + struct rvu_devlink *rvu_dl = devlink_priv(devlink); + struct rvu *rvu = rvu_dl->rvu; + struct npc_mcam *mcam; + u32 percent; + + mcam = &rvu->hw->mcam; + percent = (mcam->hprio_count * 100) / mcam->bmap_entries; + ctx->val.vu8 = (u8)percent; + + return 0; +} + +static int rvu_af_dl_npc_mcam_high_zone_percent_set(struct devlink *devlink, u32 id, + struct devlink_param_gset_ctx *ctx) +{ + struct rvu_devlink *rvu_dl = devlink_priv(devlink); + struct rvu *rvu = rvu_dl->rvu; + struct npc_mcam *mcam; + u32 percent; + + percent = ctx->val.vu8; + mcam = &rvu->hw->mcam; + mcam->hprio_count = (mcam->bmap_entries * percent) / 100; + mcam->hprio_end = mcam->hprio_count; + mcam->lprio_count = (mcam->bmap_entries - mcam->hprio_count) / 2; + mcam->lprio_start = mcam->bmap_entries - mcam->lprio_count; + + return 0; +} + +static int rvu_af_dl_npc_mcam_high_zone_percent_validate(struct devlink *devlink, u32 id, + union devlink_param_value val, + struct netlink_ext_ack *extack) +{ + struct rvu_devlink *rvu_dl = devlink_priv(devlink); + struct rvu *rvu = rvu_dl->rvu; + struct npc_mcam *mcam; + + /* The percent of high prio zone must range from 12% to 100% of unreserved mcam space */ + if (val.vu8 < 12 || val.vu8 > 100) { + NL_SET_ERR_MSG_MOD(extack, + "mcam high zone percent must be between 12% to 100%"); + return -EINVAL; + } + + /* Do not allow user to modify the high priority zone entries while mcam entries + * have already been assigned. + */ + mcam = &rvu->hw->mcam; + if (mcam->bmap_fcnt < mcam->bmap_entries) { + NL_SET_ERR_MSG_MOD(extack, + "mcam entries have already been assigned, can't resize"); + return -EPERM; + } + + return 0; +} + static const struct devlink_param rvu_af_dl_params[] = { DEVLINK_PARAM_DRIVER(RVU_AF_DEVLINK_PARAM_ID_DWRR_MTU, "dwrr_mtu", DEVLINK_PARAM_TYPE_U32, @@ -1509,6 +1573,12 @@ static const struct devlink_param rvu_af_dl_param_exact_match[] = { rvu_af_npc_exact_feature_get, rvu_af_npc_exact_feature_disable, rvu_af_npc_exact_feature_validate), + DEVLINK_PARAM_DRIVER(RVU_AF_DEVLINK_PARAM_ID_NPC_MCAM_ZONE_PERCENT, + "npc_mcam_high_zone_percent", DEVLINK_PARAM_TYPE_U8, + BIT(DEVLINK_PARAM_CMODE_RUNTIME), + rvu_af_dl_npc_mcam_high_zone_percent_get, + rvu_af_dl_npc_mcam_high_zone_percent_set, + rvu_af_dl_npc_mcam_high_zone_percent_validate), }; /* Devlink switch mode */ diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c index f01d057ad025ae7f2aca0d06c16238bc2d005227..04b0e885f9d2e572442772dadc63ec8f72d16183 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c @@ -191,6 +191,18 @@ struct nix_hw *get_nix_hw(struct rvu_hwinfo *hw, int blkaddr) return NULL; } +int nix_get_dwrr_mtu_reg(struct rvu_hwinfo *hw, int smq_link_type) +{ + if (hw->cap.nix_multiple_dwrr_mtu) + return NIX_AF_DWRR_MTUX(smq_link_type); + + if (smq_link_type == SMQ_LINK_TYPE_SDP) + return NIX_AF_DWRR_SDP_MTU; + + /* Here it's same reg for RPM and LBK */ + return NIX_AF_DWRR_RPM_MTU; +} + u32 convert_dwrr_mtu_to_bytes(u8 dwrr_mtu) { dwrr_mtu &= 0x1FULL; @@ -1691,6 +1703,42 @@ handle_txschq_shaper_update(struct rvu *rvu, int blkaddr, int nixlf, return true; } +static void nix_reset_tx_schedule(struct rvu *rvu, int blkaddr, + int lvl, int schq) +{ + u64 tlx_parent = 0, tlx_schedule = 0; + + switch (lvl) { + case NIX_TXSCH_LVL_TL2: + tlx_parent = NIX_AF_TL2X_PARENT(schq); + tlx_schedule = NIX_AF_TL2X_SCHEDULE(schq); + break; + case NIX_TXSCH_LVL_TL3: + tlx_parent = NIX_AF_TL3X_PARENT(schq); + tlx_schedule = NIX_AF_TL3X_SCHEDULE(schq); + break; + case NIX_TXSCH_LVL_TL4: + tlx_parent = NIX_AF_TL4X_PARENT(schq); + tlx_schedule = NIX_AF_TL4X_SCHEDULE(schq); + break; + case NIX_TXSCH_LVL_MDQ: + /* no need to reset SMQ_CFG as HW clears this CSR + * on SMQ flush + */ + tlx_parent = NIX_AF_MDQX_PARENT(schq); + tlx_schedule = NIX_AF_MDQX_SCHEDULE(schq); + break; + default: + return; + } + + if (tlx_parent) + rvu_write64(rvu, blkaddr, tlx_parent, 0x0); + + if (tlx_schedule) + rvu_write64(rvu, blkaddr, tlx_schedule, 0x0); +} + /* Disable shaping of pkts by a scheduler queue * at a given scheduler level. */ @@ -2040,6 +2088,7 @@ int rvu_mbox_handler_nix_txsch_alloc(struct rvu *rvu, pfvf_map[schq] = TXSCH_MAP(pcifunc, 0); nix_reset_tx_linkcfg(rvu, blkaddr, lvl, schq); nix_reset_tx_shaping(rvu, blkaddr, nixlf, lvl, schq); + nix_reset_tx_schedule(rvu, blkaddr, lvl, schq); } for (idx = 0; idx < req->schq[lvl]; idx++) { @@ -2049,6 +2098,7 @@ int rvu_mbox_handler_nix_txsch_alloc(struct rvu *rvu, pfvf_map[schq] = TXSCH_MAP(pcifunc, 0); nix_reset_tx_linkcfg(rvu, blkaddr, lvl, schq); nix_reset_tx_shaping(rvu, blkaddr, nixlf, lvl, schq); + nix_reset_tx_schedule(rvu, blkaddr, lvl, schq); } } @@ -2065,9 +2115,121 @@ int rvu_mbox_handler_nix_txsch_alloc(struct rvu *rvu, return rc; } +static void nix_smq_flush_fill_ctx(struct rvu *rvu, int blkaddr, int smq, + struct nix_smq_flush_ctx *smq_flush_ctx) +{ + struct nix_smq_tree_ctx *smq_tree_ctx; + u64 parent_off, regval; + u16 schq; + int lvl; + + smq_flush_ctx->smq = smq; + + schq = smq; + for (lvl = NIX_TXSCH_LVL_SMQ; lvl <= NIX_TXSCH_LVL_TL1; lvl++) { + smq_tree_ctx = &smq_flush_ctx->smq_tree_ctx[lvl]; + if (lvl == NIX_TXSCH_LVL_TL1) { + smq_flush_ctx->tl1_schq = schq; + smq_tree_ctx->cir_off = NIX_AF_TL1X_CIR(schq); + smq_tree_ctx->pir_off = 0; + smq_tree_ctx->pir_val = 0; + parent_off = 0; + } else if (lvl == NIX_TXSCH_LVL_TL2) { + smq_flush_ctx->tl2_schq = schq; + smq_tree_ctx->cir_off = NIX_AF_TL2X_CIR(schq); + smq_tree_ctx->pir_off = NIX_AF_TL2X_PIR(schq); + parent_off = NIX_AF_TL2X_PARENT(schq); + } else if (lvl == NIX_TXSCH_LVL_TL3) { + smq_tree_ctx->cir_off = NIX_AF_TL3X_CIR(schq); + smq_tree_ctx->pir_off = NIX_AF_TL3X_PIR(schq); + parent_off = NIX_AF_TL3X_PARENT(schq); + } else if (lvl == NIX_TXSCH_LVL_TL4) { + smq_tree_ctx->cir_off = NIX_AF_TL4X_CIR(schq); + smq_tree_ctx->pir_off = NIX_AF_TL4X_PIR(schq); + parent_off = NIX_AF_TL4X_PARENT(schq); + } else if (lvl == NIX_TXSCH_LVL_MDQ) { + smq_tree_ctx->cir_off = NIX_AF_MDQX_CIR(schq); + smq_tree_ctx->pir_off = NIX_AF_MDQX_PIR(schq); + parent_off = NIX_AF_MDQX_PARENT(schq); + } + /* save cir/pir register values */ + smq_tree_ctx->cir_val = rvu_read64(rvu, blkaddr, smq_tree_ctx->cir_off); + if (smq_tree_ctx->pir_off) + smq_tree_ctx->pir_val = rvu_read64(rvu, blkaddr, smq_tree_ctx->pir_off); + + /* get parent txsch node */ + if (parent_off) { + regval = rvu_read64(rvu, blkaddr, parent_off); + schq = (regval >> 16) & 0x1FF; + } + } +} + +static void nix_smq_flush_enadis_xoff(struct rvu *rvu, int blkaddr, + struct nix_smq_flush_ctx *smq_flush_ctx, bool enable) +{ + struct nix_txsch *txsch; + struct nix_hw *nix_hw; + u64 regoff; + int tl2; + + nix_hw = get_nix_hw(rvu->hw, blkaddr); + if (!nix_hw) + return; + + /* loop through all TL2s with matching PF_FUNC */ + txsch = &nix_hw->txsch[NIX_TXSCH_LVL_TL2]; + for (tl2 = 0; tl2 < txsch->schq.max; tl2++) { + /* skip the smq(flush) TL2 */ + if (tl2 == smq_flush_ctx->tl2_schq) + continue; + /* skip unused TL2s */ + if (TXSCH_MAP_FLAGS(txsch->pfvf_map[tl2]) & NIX_TXSCHQ_FREE) + continue; + /* skip if PF_FUNC doesn't match */ + if ((TXSCH_MAP_FUNC(txsch->pfvf_map[tl2]) & ~RVU_PFVF_FUNC_MASK) != + (TXSCH_MAP_FUNC(txsch->pfvf_map[smq_flush_ctx->tl2_schq] & + ~RVU_PFVF_FUNC_MASK))) + continue; + /* enable/disable XOFF */ + regoff = NIX_AF_TL2X_SW_XOFF(tl2); + if (enable) + rvu_write64(rvu, blkaddr, regoff, 0x1); + else + rvu_write64(rvu, blkaddr, regoff, 0x0); + } +} + +static void nix_smq_flush_enadis_rate(struct rvu *rvu, int blkaddr, + struct nix_smq_flush_ctx *smq_flush_ctx, bool enable) +{ + u64 cir_off, pir_off, cir_val, pir_val; + struct nix_smq_tree_ctx *smq_tree_ctx; + int lvl; + + for (lvl = NIX_TXSCH_LVL_SMQ; lvl <= NIX_TXSCH_LVL_TL1; lvl++) { + smq_tree_ctx = &smq_flush_ctx->smq_tree_ctx[lvl]; + cir_off = smq_tree_ctx->cir_off; + cir_val = smq_tree_ctx->cir_val; + pir_off = smq_tree_ctx->pir_off; + pir_val = smq_tree_ctx->pir_val; + + if (enable) { + rvu_write64(rvu, blkaddr, cir_off, cir_val); + if (lvl != NIX_TXSCH_LVL_TL1) + rvu_write64(rvu, blkaddr, pir_off, pir_val); + } else { + rvu_write64(rvu, blkaddr, cir_off, 0x0); + if (lvl != NIX_TXSCH_LVL_TL1) + rvu_write64(rvu, blkaddr, pir_off, 0x0); + } + } +} + static int nix_smq_flush(struct rvu *rvu, int blkaddr, int smq, u16 pcifunc, int nixlf) { + struct nix_smq_flush_ctx *smq_flush_ctx; int pf = rvu_get_pf(pcifunc); u8 cgx_id = 0, lmac_id = 0; int err, restore_tx_en = 0; @@ -2087,6 +2249,14 @@ static int nix_smq_flush(struct rvu *rvu, int blkaddr, lmac_id, true); } + /* XOFF all TL2s whose parent TL1 matches SMQ tree TL1 */ + smq_flush_ctx = kzalloc(sizeof(*smq_flush_ctx), GFP_KERNEL); + if (!smq_flush_ctx) + return -ENOMEM; + nix_smq_flush_fill_ctx(rvu, blkaddr, smq, smq_flush_ctx); + nix_smq_flush_enadis_xoff(rvu, blkaddr, smq_flush_ctx, true); + nix_smq_flush_enadis_rate(rvu, blkaddr, smq_flush_ctx, false); + cfg = rvu_read64(rvu, blkaddr, NIX_AF_SMQX_CFG(smq)); /* Do SMQ flush and set enqueue xoff */ cfg |= BIT_ULL(50) | BIT_ULL(49); @@ -2101,8 +2271,14 @@ static int nix_smq_flush(struct rvu *rvu, int blkaddr, err = rvu_poll_reg(rvu, blkaddr, NIX_AF_SMQX_CFG(smq), BIT_ULL(49), true); if (err) - dev_err(rvu->dev, - "NIXLF%d: SMQ%d flush failed\n", nixlf, smq); + dev_info(rvu->dev, + "NIXLF%d: SMQ%d flush failed, txlink might be busy\n", + nixlf, smq); + + /* clear XOFF on TL2s */ + nix_smq_flush_enadis_rate(rvu, blkaddr, smq_flush_ctx, true); + nix_smq_flush_enadis_xoff(rvu, blkaddr, smq_flush_ctx, false); + kfree(smq_flush_ctx); rvu_cgx_enadis_rx_bp(rvu, pf, true); /* restore cgx tx state */ @@ -2144,6 +2320,7 @@ static int nix_txschq_free(struct rvu *rvu, u16 pcifunc) continue; nix_reset_tx_linkcfg(rvu, blkaddr, lvl, schq); nix_clear_tx_xoff(rvu, blkaddr, lvl, schq); + nix_reset_tx_shaping(rvu, blkaddr, nixlf, lvl, schq); } } nix_clear_tx_xoff(rvu, blkaddr, NIX_TXSCH_LVL_TL1, @@ -2182,6 +2359,7 @@ static int nix_txschq_free(struct rvu *rvu, u16 pcifunc) for (schq = 0; schq < txsch->schq.max; schq++) { if (TXSCH_MAP_FUNC(txsch->pfvf_map[schq]) != pcifunc) continue; + nix_reset_tx_schedule(rvu, blkaddr, lvl, schq); rvu_free_rsrc(&txsch->schq, schq); txsch->pfvf_map[schq] = TXSCH_MAP(0, NIX_TXSCHQ_FREE); } @@ -2241,6 +2419,9 @@ static int nix_txschq_free_one(struct rvu *rvu, */ nix_clear_tx_xoff(rvu, blkaddr, lvl, schq); + nix_reset_tx_linkcfg(rvu, blkaddr, lvl, schq); + nix_reset_tx_shaping(rvu, blkaddr, nixlf, lvl, schq); + /* Flush if it is a SMQ. Onus of disabling * TL2/3 queue links before SMQ flush is on user */ @@ -2250,6 +2431,8 @@ static int nix_txschq_free_one(struct rvu *rvu, goto err; } + nix_reset_tx_schedule(rvu, blkaddr, lvl, schq); + /* Free the resource */ rvu_free_rsrc(&txsch->schq, schq); txsch->pfvf_map[schq] = TXSCH_MAP(0, NIX_TXSCHQ_FREE); @@ -2404,17 +2587,19 @@ static int nix_txschq_cfg_read(struct rvu *rvu, struct nix_hw *nix_hw, return 0; } -static void rvu_nix_tx_tl2_cfg(struct rvu *rvu, int blkaddr, - u16 pcifunc, struct nix_txsch *txsch) +void rvu_nix_tx_tl2_cfg(struct rvu *rvu, int blkaddr, u16 pcifunc, + struct nix_txsch *txsch, bool enable) { struct rvu_hwinfo *hw = rvu->hw; int lbk_link_start, lbk_links; u8 pf = rvu_get_pf(pcifunc); int schq; + u64 cfg; if (!is_pf_cgxmapped(rvu, pf)) return; + cfg = enable ? (BIT_ULL(12) | RVU_SWITCH_LBK_CHAN) : 0; lbk_link_start = hw->cgx_links; for (schq = 0; schq < txsch->schq.max; schq++) { @@ -2428,8 +2613,7 @@ static void rvu_nix_tx_tl2_cfg(struct rvu *rvu, int blkaddr, rvu_write64(rvu, blkaddr, NIX_AF_TL3_TL2X_LINKX_CFG(schq, lbk_link_start + - lbk_links), - BIT_ULL(12) | RVU_SWITCH_LBK_CHAN); + lbk_links), cfg); } } @@ -2535,8 +2719,6 @@ int rvu_mbox_handler_nix_txschq_cfg(struct rvu *rvu, rvu_write64(rvu, blkaddr, reg, regval); } - rvu_nix_tx_tl2_cfg(rvu, blkaddr, pcifunc, - &nix_hw->txsch[NIX_TXSCH_LVL_TL2]); return 0; } @@ -3147,10 +3329,16 @@ static int nix_setup_txschq(struct rvu *rvu, struct nix_hw *nix_hw, int blkaddr) } /* Setup a default value of 8192 as DWRR MTU */ - if (rvu->hw->cap.nix_common_dwrr_mtu) { - rvu_write64(rvu, blkaddr, NIX_AF_DWRR_RPM_MTU, + if (rvu->hw->cap.nix_common_dwrr_mtu || + rvu->hw->cap.nix_multiple_dwrr_mtu) { + rvu_write64(rvu, blkaddr, + nix_get_dwrr_mtu_reg(rvu->hw, SMQ_LINK_TYPE_RPM), + convert_bytes_to_dwrr_mtu(8192)); + rvu_write64(rvu, blkaddr, + nix_get_dwrr_mtu_reg(rvu->hw, SMQ_LINK_TYPE_LBK), convert_bytes_to_dwrr_mtu(8192)); - rvu_write64(rvu, blkaddr, NIX_AF_DWRR_SDP_MTU, + rvu_write64(rvu, blkaddr, + nix_get_dwrr_mtu_reg(rvu->hw, SMQ_LINK_TYPE_SDP), convert_bytes_to_dwrr_mtu(8192)); } @@ -3248,19 +3436,28 @@ int rvu_mbox_handler_nix_get_hw_info(struct rvu *rvu, struct msg_req *req, rsp->min_mtu = NIC_HW_MIN_FRS; - if (!rvu->hw->cap.nix_common_dwrr_mtu) { + if (!rvu->hw->cap.nix_common_dwrr_mtu && + !rvu->hw->cap.nix_multiple_dwrr_mtu) { /* Return '1' on OTx2 */ rsp->rpm_dwrr_mtu = 1; rsp->sdp_dwrr_mtu = 1; + rsp->lbk_dwrr_mtu = 1; return 0; } - dwrr_mtu = rvu_read64(rvu, BLKADDR_NIX0, NIX_AF_DWRR_RPM_MTU); + /* Return DWRR_MTU for TLx_SCHEDULE[RR_WEIGHT] config */ + dwrr_mtu = rvu_read64(rvu, blkaddr, + nix_get_dwrr_mtu_reg(rvu->hw, SMQ_LINK_TYPE_RPM)); rsp->rpm_dwrr_mtu = convert_dwrr_mtu_to_bytes(dwrr_mtu); - dwrr_mtu = rvu_read64(rvu, BLKADDR_NIX0, NIX_AF_DWRR_SDP_MTU); + dwrr_mtu = rvu_read64(rvu, blkaddr, + nix_get_dwrr_mtu_reg(rvu->hw, SMQ_LINK_TYPE_SDP)); rsp->sdp_dwrr_mtu = convert_dwrr_mtu_to_bytes(dwrr_mtu); + dwrr_mtu = rvu_read64(rvu, blkaddr, + nix_get_dwrr_mtu_reg(rvu->hw, SMQ_LINK_TYPE_LBK)); + rsp->lbk_dwrr_mtu = convert_dwrr_mtu_to_bytes(dwrr_mtu); + return 0; } @@ -3309,6 +3506,7 @@ static int set_flowkey_fields(struct nix_rx_flowkey_alg *alg, u32 flow_cfg) struct nix_rx_flowkey_alg *field; struct nix_rx_flowkey_alg tmp; u32 key_type, valid_key; + u32 l3_l4_src_dst; int l4_key_offset = 0; if (!alg) @@ -3336,6 +3534,15 @@ static int set_flowkey_fields(struct nix_rx_flowkey_alg *alg, u32 flow_cfg) * group_member - Enabled when protocol is part of a group. */ + /* Last 4 bits (31:28) are reserved to specify SRC, DST + * selection for L3, L4 i.e IPV[4,6]_SRC, IPV[4,6]_DST, + * [TCP,UDP,SCTP]_SRC, [TCP,UDP,SCTP]_DST + * 31 => L3_SRC, 30 => L3_DST, 29 => L4_SRC, 28 => L4_DST + */ + l3_l4_src_dst = flow_cfg; + /* Reset these 4 bits, so that these won't be part of key */ + flow_cfg &= NIX_FLOW_KEY_TYPE_L3_L4_MASK; + keyoff_marker = 0; max_key_off = 0; group_member = 0; nr_field = 0; key_off = 0; field_marker = 1; field = &tmp; max_bit_pos = fls(flow_cfg); @@ -3373,6 +3580,22 @@ static int set_flowkey_fields(struct nix_rx_flowkey_alg *alg, u32 flow_cfg) } field->hdr_offset = 12; /* SIP offset */ field->bytesm1 = 7; /* SIP + DIP, 8 bytes */ + + /* Only SIP */ + if (l3_l4_src_dst & NIX_FLOW_KEY_TYPE_L3_SRC_ONLY) + field->bytesm1 = 3; /* SIP, 4 bytes */ + + if (l3_l4_src_dst & NIX_FLOW_KEY_TYPE_L3_DST_ONLY) { + /* Both SIP + DIP */ + if (field->bytesm1 == 3) { + field->bytesm1 = 7; /* SIP + DIP, 8B */ + } else { + /* Only DIP */ + field->hdr_offset = 16; /* DIP off */ + field->bytesm1 = 3; /* DIP, 4 bytes */ + } + } + field->ltype_mask = 0xF; /* Match only IPv4 */ keyoff_marker = false; break; @@ -3386,6 +3609,22 @@ static int set_flowkey_fields(struct nix_rx_flowkey_alg *alg, u32 flow_cfg) } field->hdr_offset = 8; /* SIP offset */ field->bytesm1 = 31; /* SIP + DIP, 32 bytes */ + + /* Only SIP */ + if (l3_l4_src_dst & NIX_FLOW_KEY_TYPE_L3_SRC_ONLY) + field->bytesm1 = 15; /* SIP, 16 bytes */ + + if (l3_l4_src_dst & NIX_FLOW_KEY_TYPE_L3_DST_ONLY) { + /* Both SIP + DIP */ + if (field->bytesm1 == 15) { + /* SIP + DIP, 32 bytes */ + field->bytesm1 = 31; + } else { + /* Only DIP */ + field->hdr_offset = 24; /* DIP off */ + field->bytesm1 = 15; /* DIP,16 bytes */ + } + } field->ltype_mask = 0xF; /* Match only IPv6 */ break; case NIX_FLOW_KEY_TYPE_TCP: @@ -3401,6 +3640,21 @@ static int set_flowkey_fields(struct nix_rx_flowkey_alg *alg, u32 flow_cfg) field->lid = NPC_LID_LH; field->bytesm1 = 3; /* Sport + Dport, 4 bytes */ + if (l3_l4_src_dst & NIX_FLOW_KEY_TYPE_L4_SRC_ONLY) + field->bytesm1 = 1; /* SRC, 2 bytes */ + + if (l3_l4_src_dst & NIX_FLOW_KEY_TYPE_L4_DST_ONLY) { + /* Both SRC + DST */ + if (field->bytesm1 == 1) { + /* SRC + DST, 4 bytes */ + field->bytesm1 = 3; + } else { + /* Only DIP */ + field->hdr_offset = 2; /* DST off */ + field->bytesm1 = 1; /* DST, 2 bytes */ + } + } + /* Enum values for NPC_LID_LD and NPC_LID_LG are same, * so no need to change the ltype_match, just change * the lid for inner protocols @@ -3815,21 +4069,14 @@ int rvu_mbox_handler_nix_set_rx_mode(struct rvu *rvu, struct nix_rx_mode *req, } /* install/uninstall promisc entry */ - if (promisc) { + if (promisc) rvu_npc_install_promisc_entry(rvu, pcifunc, nixlf, pfvf->rx_chan_base, pfvf->rx_chan_cnt); - - if (rvu_npc_exact_has_match_table(rvu)) - rvu_npc_exact_promisc_enable(rvu, pcifunc); - } else { + else if (!nix_rx_multicast) rvu_npc_enable_promisc_entry(rvu, pcifunc, nixlf, false); - if (rvu_npc_exact_has_match_table(rvu)) - rvu_npc_exact_promisc_disable(rvu, pcifunc); - } - return 0; } @@ -4069,6 +4316,11 @@ int rvu_mbox_handler_nix_set_rx_cfg(struct rvu *rvu, struct nix_rx_cfg *req, else cfg &= ~BIT_ULL(40); + if (req->len_verify & NIX_RX_DROP_RE) + cfg |= BIT_ULL(32); + else + cfg &= ~BIT_ULL(32); + if (req->csum_verify & BIT(0)) cfg |= BIT_ULL(37); else @@ -4266,8 +4518,11 @@ static void rvu_nix_setup_capabilities(struct rvu *rvu, int blkaddr) * Check if HW uses a common MTU for all DWRR quantum configs. * On OcteonTx2 this register field is '0'. */ - if (((hw_const >> 56) & 0x10) == 0x10) + if ((((hw_const >> 56) & 0x10) == 0x10) && !(hw_const & BIT_ULL(61))) hw->cap.nix_common_dwrr_mtu = true; + + if (hw_const & BIT_ULL(61)) + hw->cap.nix_multiple_dwrr_mtu = true; } static int rvu_nix_block_init(struct rvu *rvu, struct nix_hw *nix_hw) diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_hash.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_hash.c index 9f11c1e4073737f3f8d187da7f29497d925e2b8b..6fe67f3a7f6f18ebce2b3e11c7c4ba4a2cdd0ce5 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_hash.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_hash.c @@ -1164,8 +1164,10 @@ static u16 __rvu_npc_exact_cmd_rules_cnt_update(struct rvu *rvu, int drop_mcam_i { struct npc_exact_table *table; u16 *cnt, old_cnt; + bool promisc; table = rvu->hw->table; + promisc = table->promisc_mode[drop_mcam_idx]; cnt = &table->cnt_cmd_rules[drop_mcam_idx]; old_cnt = *cnt; @@ -1177,13 +1179,18 @@ static u16 __rvu_npc_exact_cmd_rules_cnt_update(struct rvu *rvu, int drop_mcam_i *enable_or_disable_cam = false; - /* If all rules are deleted, disable cam */ + if (promisc) + goto done; + + /* If all rules are deleted and not already in promisc mode; + * disable cam + */ if (!*cnt && val < 0) { *enable_or_disable_cam = true; goto done; } - /* If rule got added, enable cam */ + /* If rule got added and not already in promisc mode; enable cam */ if (!old_cnt && val > 0) { *enable_or_disable_cam = true; goto done; @@ -1462,6 +1469,12 @@ int rvu_npc_exact_promisc_disable(struct rvu *rvu, u16 pcifunc) *promisc = false; mutex_unlock(&table->lock); + /* Enable drop rule */ + rvu_npc_enable_mcam_by_entry_index(rvu, drop_mcam_idx, NIX_INTF_RX, + true); + + dev_dbg(rvu->dev, "%s: disabled promisc mode (cgx=%d lmac=%d)\n", + __func__, cgx_id, lmac_id); return 0; } @@ -1503,6 +1516,12 @@ int rvu_npc_exact_promisc_enable(struct rvu *rvu, u16 pcifunc) *promisc = true; mutex_unlock(&table->lock); + /* disable drop rule */ + rvu_npc_enable_mcam_by_entry_index(rvu, drop_mcam_idx, NIX_INTF_RX, + false); + + dev_dbg(rvu->dev, "%s: Enabled promisc mode (cgx=%d lmac=%d)\n", + __func__, cgx_id, lmac_id); return 0; } diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_reg.h b/drivers/net/ethernet/marvell/octeontx2/af/rvu_reg.h index 7007f0b8e6591ab89a8871aff8fe5a49e80c1241..b42e631e52d0fd686144881bb255f1529a80879e 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_reg.h +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_reg.h @@ -272,7 +272,8 @@ #define NIX_AF_DEBUG_NPC_RESP_DATAX(a) (0x680 | (a) << 3) #define NIX_AF_SMQX_CFG(a) (0x700 | (a) << 16) #define NIX_AF_SQM_DBG_CTL_STATUS (0x750) -#define NIX_AF_DWRR_SDP_MTU (0x790) +#define NIX_AF_DWRR_SDP_MTU (0x790) /* All CN10K except CN10KB */ +#define NIX_AF_DWRR_MTUX(a) (0x790 | (a) << 16) /* Only for CN10KB */ #define NIX_AF_DWRR_RPM_MTU (0x7A0) #define NIX_AF_PSE_CHANNEL_LEVEL (0x800) #define NIX_AF_PSE_SHAPER_CFG (0x810) diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_switch.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_switch.c index 3392487f6b47b8f424bfb1a677eecabdaa156793..592b317f46376ec6bb8c2ce89ad6ff150610b7e6 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_switch.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_switch.c @@ -8,6 +8,17 @@ #include #include "rvu.h" +static void rvu_switch_enable_lbk_link(struct rvu *rvu, u16 pcifunc, bool enable) +{ + struct rvu_pfvf *pfvf = rvu_get_pfvf(rvu, pcifunc); + struct nix_hw *nix_hw; + + nix_hw = get_nix_hw(rvu->hw, pfvf->nix_blkaddr); + /* Enable LBK links with channel 63 for TX MCAM rule */ + rvu_nix_tx_tl2_cfg(rvu, pfvf->nix_blkaddr, pcifunc, + &nix_hw->txsch[NIX_TXSCH_LVL_TL2], enable); +} + static int rvu_switch_install_rx_rule(struct rvu *rvu, u16 pcifunc, u16 chan_mask) { @@ -52,6 +63,8 @@ static int rvu_switch_install_tx_rule(struct rvu *rvu, u16 pcifunc, u16 entry) if (!test_bit(NIXLF_INITIALIZED, &pfvf->flags)) return 0; + rvu_switch_enable_lbk_link(rvu, pcifunc, true); + lbkid = pfvf->nix_blkaddr == BLKADDR_NIX0 ? 0 : 1; ether_addr_copy(req.packet.dmac, pfvf->mac_addr); eth_broadcast_addr((u8 *)&req.mask.dmac); @@ -218,6 +231,9 @@ void rvu_switch_disable(struct rvu *rvu) "Reverting RX rule for PF%d failed(%d)\n", pf, err); + /* Disable LBK link */ + rvu_switch_enable_lbk_link(rvu, pcifunc, false); + rvu_get_pf_numvfs(rvu, pf, &numvfs, NULL); for (vf = 0; vf < numvfs; vf++) { pcifunc = pf << 10 | ((vf + 1) & 0x3FF); @@ -226,6 +242,8 @@ void rvu_switch_disable(struct rvu *rvu) dev_err(rvu->dev, "Reverting RX rule for PF%dVF%d failed(%d)\n", pf, vf, err); + + rvu_switch_enable_lbk_link(rvu, pcifunc, false); } } diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/Makefile b/drivers/net/ethernet/marvell/octeontx2/nic/Makefile index 73fdb8798614835a8438b60d561d04d79c4b0926..5664f768cb0cd1711ada99605efc0861957452d9 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/Makefile +++ b/drivers/net/ethernet/marvell/octeontx2/nic/Makefile @@ -8,7 +8,7 @@ obj-$(CONFIG_OCTEONTX2_VF) += rvu_nicvf.o otx2_ptp.o rvu_nicpf-y := otx2_pf.o otx2_common.o otx2_txrx.o otx2_ethtool.o \ otx2_flows.o otx2_tc.o cn10k.o otx2_dmac_flt.o \ - otx2_devlink.o + otx2_devlink.o qos_sq.o qos.o rvu_nicvf-y := otx2_vf.o otx2_devlink.o rvu_nicpf-$(CONFIG_DCB) += otx2_dcbnl.o diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/cn10k_macsec.c b/drivers/net/ethernet/marvell/octeontx2/nic/cn10k_macsec.c index a487a98eac88c2290519dceee59cce61d8d2b093..6e2fb24be8c1e47a63891793843c564f6ce31caf 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/cn10k_macsec.c +++ b/drivers/net/ethernet/marvell/octeontx2/nic/cn10k_macsec.c @@ -6,7 +6,6 @@ #include #include -#include #include "otx2_common.h" #define MCS_TCAM0_MAC_DA_MASK GENMASK_ULL(47, 0) @@ -212,6 +211,7 @@ static int cn10k_mcs_write_rx_secy(struct otx2_nic *pfvf, struct mcs_secy_plcy_write_req *req; struct mbox *mbox = &pfvf->mbox; u64 policy; + u8 cipher; int ret; mutex_lock(&mbox->lock); @@ -227,7 +227,21 @@ static int cn10k_mcs_write_rx_secy(struct otx2_nic *pfvf, policy |= MCS_RX_SECY_PLCY_RP; policy |= MCS_RX_SECY_PLCY_AUTH_ENA; - policy |= FIELD_PREP(MCS_RX_SECY_PLCY_CIP, MCS_GCM_AES_128); + + switch (secy->key_len) { + case 16: + cipher = secy->xpn ? MCS_GCM_AES_XPN_128 : MCS_GCM_AES_128; + break; + case 32: + cipher = secy->xpn ? MCS_GCM_AES_XPN_256 : MCS_GCM_AES_256; + break; + default: + cipher = MCS_GCM_AES_128; + dev_warn(pfvf->dev, "Unsupported key length\n"); + break; + } + + policy |= FIELD_PREP(MCS_RX_SECY_PLCY_CIP, cipher); policy |= FIELD_PREP(MCS_RX_SECY_PLCY_VAL, secy->validate_frames); policy |= MCS_RX_SECY_PLCY_ENA; @@ -323,9 +337,12 @@ static int cn10k_mcs_write_rx_sa_plcy(struct otx2_nic *pfvf, { unsigned char *src = rxsc->sa_key[assoc_num]; struct mcs_sa_plcy_write_req *plcy_req; + u8 *salt_p = rxsc->salt[assoc_num]; struct mcs_rx_sc_sa_map *map_req; struct mbox *mbox = &pfvf->mbox; + u64 ssci_salt_95_64 = 0; u8 reg, key_len; + u64 salt_63_0; int ret; mutex_lock(&mbox->lock); @@ -349,6 +366,15 @@ static int cn10k_mcs_write_rx_sa_plcy(struct otx2_nic *pfvf, reg++; } + if (secy->xpn) { + memcpy((u8 *)&salt_63_0, salt_p, 8); + memcpy((u8 *)&ssci_salt_95_64, salt_p + 8, 4); + ssci_salt_95_64 |= (__force u64)rxsc->ssci[assoc_num] << 32; + + plcy_req->plcy[0][6] = salt_63_0; + plcy_req->plcy[0][7] = ssci_salt_95_64; + } + plcy_req->sa_index[0] = rxsc->hw_sa_id[assoc_num]; plcy_req->sa_cnt = 1; plcy_req->dir = MCS_RX; @@ -400,12 +426,16 @@ static int cn10k_mcs_write_tx_secy(struct otx2_nic *pfvf, struct mcs_secy_plcy_write_req *req; struct mbox *mbox = &pfvf->mbox; struct macsec_tx_sc *sw_tx_sc; - /* Insert SecTag after 12 bytes (DA+SA)*/ - u8 tag_offset = 12; u8 sectag_tci = 0; + u8 tag_offset; u64 policy; + u8 cipher; int ret; + /* Insert SecTag after 12 bytes (DA+SA) or 16 bytes + * if VLAN tag needs to be sent in clear text. + */ + tag_offset = txsc->vlan_dev ? 16 : 12; sw_tx_sc = &secy->tx_sc; mutex_lock(&mbox->lock); @@ -434,7 +464,21 @@ static int cn10k_mcs_write_tx_secy(struct otx2_nic *pfvf, policy |= FIELD_PREP(MCS_TX_SECY_PLCY_ST_OFFSET, tag_offset); policy |= MCS_TX_SECY_PLCY_INS_MODE; policy |= MCS_TX_SECY_PLCY_AUTH_ENA; - policy |= FIELD_PREP(MCS_TX_SECY_PLCY_CIP, MCS_GCM_AES_128); + + switch (secy->key_len) { + case 16: + cipher = secy->xpn ? MCS_GCM_AES_XPN_128 : MCS_GCM_AES_128; + break; + case 32: + cipher = secy->xpn ? MCS_GCM_AES_XPN_256 : MCS_GCM_AES_256; + break; + default: + cipher = MCS_GCM_AES_128; + dev_warn(pfvf->dev, "Unsupported key length\n"); + break; + } + + policy |= FIELD_PREP(MCS_TX_SECY_PLCY_CIP, cipher); if (secy->protect_frames) policy |= MCS_TX_SECY_PLCY_PROTECT; @@ -544,8 +588,11 @@ static int cn10k_mcs_write_tx_sa_plcy(struct otx2_nic *pfvf, { unsigned char *src = txsc->sa_key[assoc_num]; struct mcs_sa_plcy_write_req *plcy_req; + u8 *salt_p = txsc->salt[assoc_num]; struct mbox *mbox = &pfvf->mbox; + u64 ssci_salt_95_64 = 0; u8 reg, key_len; + u64 salt_63_0; int ret; mutex_lock(&mbox->lock); @@ -561,6 +608,15 @@ static int cn10k_mcs_write_tx_sa_plcy(struct otx2_nic *pfvf, reg++; } + if (secy->xpn) { + memcpy((u8 *)&salt_63_0, salt_p, 8); + memcpy((u8 *)&ssci_salt_95_64, salt_p + 8, 4); + ssci_salt_95_64 |= (__force u64)txsc->ssci[assoc_num] << 32; + + plcy_req->plcy[0][6] = salt_63_0; + plcy_req->plcy[0][7] = ssci_salt_95_64; + } + plcy_req->plcy[0][8] = assoc_num; plcy_req->sa_index[0] = txsc->hw_sa_id[assoc_num]; plcy_req->sa_cnt = 1; @@ -922,8 +978,7 @@ static int cn10k_mcs_secy_tx_cfg(struct otx2_nic *pfvf, struct macsec_secy *secy { if (sw_tx_sa) { cn10k_mcs_write_tx_sa_plcy(pfvf, secy, txsc, sa_num); - cn10k_write_tx_sa_pn(pfvf, txsc, sa_num, - sw_tx_sa->next_pn_halves.lower); + cn10k_write_tx_sa_pn(pfvf, txsc, sa_num, sw_tx_sa->next_pn); cn10k_mcs_link_tx_sa2sc(pfvf, secy, txsc, sa_num, sw_tx_sa->active); } @@ -959,7 +1014,7 @@ static int cn10k_mcs_secy_rx_cfg(struct otx2_nic *pfvf, cn10k_mcs_write_rx_sa_plcy(pfvf, secy, mcs_rx_sc, sa_num, sw_rx_sa->active); cn10k_mcs_write_rx_sa_pn(pfvf, mcs_rx_sc, sa_num, - sw_rx_sa->next_pn_halves.lower); + sw_rx_sa->next_pn); } cn10k_mcs_write_rx_flowid(pfvf, mcs_rx_sc, hw_secy_id); @@ -1053,7 +1108,7 @@ static void cn10k_mcs_sync_stats(struct otx2_nic *pfvf, struct macsec_secy *secy static int cn10k_mdo_open(struct macsec_context *ctx) { - struct otx2_nic *pfvf = netdev_priv(ctx->netdev); + struct otx2_nic *pfvf = macsec_netdev_priv(ctx->netdev); struct cn10k_mcs_cfg *cfg = pfvf->macsec_cfg; struct macsec_secy *secy = ctx->secy; struct macsec_tx_sa *sw_tx_sa; @@ -1077,7 +1132,7 @@ static int cn10k_mdo_open(struct macsec_context *ctx) static int cn10k_mdo_stop(struct macsec_context *ctx) { - struct otx2_nic *pfvf = netdev_priv(ctx->netdev); + struct otx2_nic *pfvf = macsec_netdev_priv(ctx->netdev); struct cn10k_mcs_cfg *cfg = pfvf->macsec_cfg; struct cn10k_mcs_txsc *txsc; int err; @@ -1095,7 +1150,7 @@ static int cn10k_mdo_stop(struct macsec_context *ctx) static int cn10k_mdo_add_secy(struct macsec_context *ctx) { - struct otx2_nic *pfvf = netdev_priv(ctx->netdev); + struct otx2_nic *pfvf = macsec_netdev_priv(ctx->netdev); struct cn10k_mcs_cfg *cfg = pfvf->macsec_cfg; struct macsec_secy *secy = ctx->secy; struct cn10k_mcs_txsc *txsc; @@ -1103,13 +1158,6 @@ static int cn10k_mdo_add_secy(struct macsec_context *ctx) if (secy->icv_len != MACSEC_DEFAULT_ICV_LEN) return -EOPNOTSUPP; - /* Stick to 16 bytes key len until XPN support is added */ - if (secy->key_len != 16) - return -EOPNOTSUPP; - - if (secy->xpn) - return -EOPNOTSUPP; - txsc = cn10k_mcs_create_txsc(pfvf); if (IS_ERR(txsc)) return -ENOSPC; @@ -1118,6 +1166,7 @@ static int cn10k_mdo_add_secy(struct macsec_context *ctx) txsc->encoding_sa = secy->tx_sc.encoding_sa; txsc->last_validate_frames = secy->validate_frames; txsc->last_replay_protect = secy->replay_protect; + txsc->vlan_dev = is_vlan_dev(ctx->netdev); list_add(&txsc->entry, &cfg->txsc_list); @@ -1129,7 +1178,7 @@ static int cn10k_mdo_add_secy(struct macsec_context *ctx) static int cn10k_mdo_upd_secy(struct macsec_context *ctx) { - struct otx2_nic *pfvf = netdev_priv(ctx->netdev); + struct otx2_nic *pfvf = macsec_netdev_priv(ctx->netdev); struct cn10k_mcs_cfg *cfg = pfvf->macsec_cfg; struct macsec_secy *secy = ctx->secy; struct macsec_tx_sa *sw_tx_sa; @@ -1164,7 +1213,7 @@ static int cn10k_mdo_upd_secy(struct macsec_context *ctx) static int cn10k_mdo_del_secy(struct macsec_context *ctx) { - struct otx2_nic *pfvf = netdev_priv(ctx->netdev); + struct otx2_nic *pfvf = macsec_netdev_priv(ctx->netdev); struct cn10k_mcs_cfg *cfg = pfvf->macsec_cfg; struct cn10k_mcs_txsc *txsc; @@ -1183,7 +1232,7 @@ static int cn10k_mdo_del_secy(struct macsec_context *ctx) static int cn10k_mdo_add_txsa(struct macsec_context *ctx) { - struct otx2_nic *pfvf = netdev_priv(ctx->netdev); + struct otx2_nic *pfvf = macsec_netdev_priv(ctx->netdev); struct macsec_tx_sa *sw_tx_sa = ctx->sa.tx_sa; struct cn10k_mcs_cfg *cfg = pfvf->macsec_cfg; struct macsec_secy *secy = ctx->secy; @@ -1202,6 +1251,9 @@ static int cn10k_mdo_add_txsa(struct macsec_context *ctx) return -ENOSPC; memcpy(&txsc->sa_key[sa_num], ctx->sa.key, secy->key_len); + memcpy(&txsc->salt[sa_num], sw_tx_sa->key.salt.bytes, MACSEC_SALT_LEN); + txsc->ssci[sa_num] = sw_tx_sa->ssci; + txsc->sa_bmap |= 1 << sa_num; if (netif_running(secy->netdev)) { @@ -1210,7 +1262,7 @@ static int cn10k_mdo_add_txsa(struct macsec_context *ctx) return err; err = cn10k_write_tx_sa_pn(pfvf, txsc, sa_num, - sw_tx_sa->next_pn_halves.lower); + sw_tx_sa->next_pn); if (err) return err; @@ -1225,7 +1277,7 @@ static int cn10k_mdo_add_txsa(struct macsec_context *ctx) static int cn10k_mdo_upd_txsa(struct macsec_context *ctx) { - struct otx2_nic *pfvf = netdev_priv(ctx->netdev); + struct otx2_nic *pfvf = macsec_netdev_priv(ctx->netdev); struct macsec_tx_sa *sw_tx_sa = ctx->sa.tx_sa; struct cn10k_mcs_cfg *cfg = pfvf->macsec_cfg; struct macsec_secy *secy = ctx->secy; @@ -1243,7 +1295,7 @@ static int cn10k_mdo_upd_txsa(struct macsec_context *ctx) if (netif_running(secy->netdev)) { /* Keys cannot be changed after creation */ err = cn10k_write_tx_sa_pn(pfvf, txsc, sa_num, - sw_tx_sa->next_pn_halves.lower); + sw_tx_sa->next_pn); if (err) return err; @@ -1258,7 +1310,7 @@ static int cn10k_mdo_upd_txsa(struct macsec_context *ctx) static int cn10k_mdo_del_txsa(struct macsec_context *ctx) { - struct otx2_nic *pfvf = netdev_priv(ctx->netdev); + struct otx2_nic *pfvf = macsec_netdev_priv(ctx->netdev); struct cn10k_mcs_cfg *cfg = pfvf->macsec_cfg; u8 sa_num = ctx->sa.assoc_num; struct cn10k_mcs_txsc *txsc; @@ -1278,7 +1330,7 @@ static int cn10k_mdo_del_txsa(struct macsec_context *ctx) static int cn10k_mdo_add_rxsc(struct macsec_context *ctx) { - struct otx2_nic *pfvf = netdev_priv(ctx->netdev); + struct otx2_nic *pfvf = macsec_netdev_priv(ctx->netdev); struct cn10k_mcs_cfg *cfg = pfvf->macsec_cfg; struct macsec_secy *secy = ctx->secy; struct cn10k_mcs_rxsc *rxsc; @@ -1312,7 +1364,7 @@ static int cn10k_mdo_add_rxsc(struct macsec_context *ctx) static int cn10k_mdo_upd_rxsc(struct macsec_context *ctx) { - struct otx2_nic *pfvf = netdev_priv(ctx->netdev); + struct otx2_nic *pfvf = macsec_netdev_priv(ctx->netdev); struct cn10k_mcs_cfg *cfg = pfvf->macsec_cfg; struct macsec_secy *secy = ctx->secy; bool enable = ctx->rx_sc->active; @@ -1331,7 +1383,7 @@ static int cn10k_mdo_upd_rxsc(struct macsec_context *ctx) static int cn10k_mdo_del_rxsc(struct macsec_context *ctx) { - struct otx2_nic *pfvf = netdev_priv(ctx->netdev); + struct otx2_nic *pfvf = macsec_netdev_priv(ctx->netdev); struct cn10k_mcs_cfg *cfg = pfvf->macsec_cfg; struct cn10k_mcs_rxsc *rxsc; @@ -1349,11 +1401,10 @@ static int cn10k_mdo_del_rxsc(struct macsec_context *ctx) static int cn10k_mdo_add_rxsa(struct macsec_context *ctx) { + struct otx2_nic *pfvf = macsec_netdev_priv(ctx->netdev); struct macsec_rx_sc *sw_rx_sc = ctx->sa.rx_sa->sc; - struct otx2_nic *pfvf = netdev_priv(ctx->netdev); struct cn10k_mcs_cfg *cfg = pfvf->macsec_cfg; struct macsec_rx_sa *rx_sa = ctx->sa.rx_sa; - u64 next_pn = rx_sa->next_pn_halves.lower; struct macsec_secy *secy = ctx->secy; bool sa_in_use = rx_sa->active; u8 sa_num = ctx->sa.assoc_num; @@ -1371,6 +1422,9 @@ static int cn10k_mdo_add_rxsa(struct macsec_context *ctx) return -ENOSPC; memcpy(&rxsc->sa_key[sa_num], ctx->sa.key, ctx->secy->key_len); + memcpy(&rxsc->salt[sa_num], rx_sa->key.salt.bytes, MACSEC_SALT_LEN); + rxsc->ssci[sa_num] = rx_sa->ssci; + rxsc->sa_bmap |= 1 << sa_num; if (netif_running(secy->netdev)) { @@ -1379,7 +1433,8 @@ static int cn10k_mdo_add_rxsa(struct macsec_context *ctx) if (err) return err; - err = cn10k_mcs_write_rx_sa_pn(pfvf, rxsc, sa_num, next_pn); + err = cn10k_mcs_write_rx_sa_pn(pfvf, rxsc, sa_num, + rx_sa->next_pn); if (err) return err; } @@ -1389,11 +1444,10 @@ static int cn10k_mdo_add_rxsa(struct macsec_context *ctx) static int cn10k_mdo_upd_rxsa(struct macsec_context *ctx) { + struct otx2_nic *pfvf = macsec_netdev_priv(ctx->netdev); struct macsec_rx_sc *sw_rx_sc = ctx->sa.rx_sa->sc; - struct otx2_nic *pfvf = netdev_priv(ctx->netdev); struct cn10k_mcs_cfg *cfg = pfvf->macsec_cfg; struct macsec_rx_sa *rx_sa = ctx->sa.rx_sa; - u64 next_pn = rx_sa->next_pn_halves.lower; struct macsec_secy *secy = ctx->secy; bool sa_in_use = rx_sa->active; u8 sa_num = ctx->sa.assoc_num; @@ -1412,7 +1466,8 @@ static int cn10k_mdo_upd_rxsa(struct macsec_context *ctx) if (err) return err; - err = cn10k_mcs_write_rx_sa_pn(pfvf, rxsc, sa_num, next_pn); + err = cn10k_mcs_write_rx_sa_pn(pfvf, rxsc, sa_num, + rx_sa->next_pn); if (err) return err; } @@ -1422,8 +1477,8 @@ static int cn10k_mdo_upd_rxsa(struct macsec_context *ctx) static int cn10k_mdo_del_rxsa(struct macsec_context *ctx) { + struct otx2_nic *pfvf = macsec_netdev_priv(ctx->netdev); struct macsec_rx_sc *sw_rx_sc = ctx->sa.rx_sa->sc; - struct otx2_nic *pfvf = netdev_priv(ctx->netdev); struct cn10k_mcs_cfg *cfg = pfvf->macsec_cfg; u8 sa_num = ctx->sa.assoc_num; struct cn10k_mcs_rxsc *rxsc; @@ -1445,8 +1500,8 @@ static int cn10k_mdo_del_rxsa(struct macsec_context *ctx) static int cn10k_mdo_get_dev_stats(struct macsec_context *ctx) { + struct otx2_nic *pfvf = macsec_netdev_priv(ctx->netdev); struct mcs_secy_stats tx_rsp = { 0 }, rx_rsp = { 0 }; - struct otx2_nic *pfvf = netdev_priv(ctx->netdev); struct cn10k_mcs_cfg *cfg = pfvf->macsec_cfg; struct macsec_secy *secy = ctx->secy; struct cn10k_mcs_txsc *txsc; @@ -1481,7 +1536,7 @@ static int cn10k_mdo_get_dev_stats(struct macsec_context *ctx) static int cn10k_mdo_get_tx_sc_stats(struct macsec_context *ctx) { - struct otx2_nic *pfvf = netdev_priv(ctx->netdev); + struct otx2_nic *pfvf = macsec_netdev_priv(ctx->netdev); struct cn10k_mcs_cfg *cfg = pfvf->macsec_cfg; struct mcs_sc_stats rsp = { 0 }; struct cn10k_mcs_txsc *txsc; @@ -1502,7 +1557,7 @@ static int cn10k_mdo_get_tx_sc_stats(struct macsec_context *ctx) static int cn10k_mdo_get_tx_sa_stats(struct macsec_context *ctx) { - struct otx2_nic *pfvf = netdev_priv(ctx->netdev); + struct otx2_nic *pfvf = macsec_netdev_priv(ctx->netdev); struct cn10k_mcs_cfg *cfg = pfvf->macsec_cfg; struct mcs_sa_stats rsp = { 0 }; u8 sa_num = ctx->sa.assoc_num; @@ -1525,7 +1580,7 @@ static int cn10k_mdo_get_tx_sa_stats(struct macsec_context *ctx) static int cn10k_mdo_get_rx_sc_stats(struct macsec_context *ctx) { - struct otx2_nic *pfvf = netdev_priv(ctx->netdev); + struct otx2_nic *pfvf = macsec_netdev_priv(ctx->netdev); struct cn10k_mcs_cfg *cfg = pfvf->macsec_cfg; struct macsec_secy *secy = ctx->secy; struct mcs_sc_stats rsp = { 0 }; @@ -1567,8 +1622,8 @@ static int cn10k_mdo_get_rx_sc_stats(struct macsec_context *ctx) static int cn10k_mdo_get_rx_sa_stats(struct macsec_context *ctx) { + struct otx2_nic *pfvf = macsec_netdev_priv(ctx->netdev); struct macsec_rx_sc *sw_rx_sc = ctx->sa.rx_sa->sc; - struct otx2_nic *pfvf = netdev_priv(ctx->netdev); struct cn10k_mcs_cfg *cfg = pfvf->macsec_cfg; struct mcs_sa_stats rsp = { 0 }; u8 sa_num = ctx->sa.assoc_num; diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c index 8a41ad8ca04f115de066a1bbc44f80939bdf73f4..77c8f650f7ac162dac727f8e4ecb8135afb72d7c 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c @@ -8,6 +8,7 @@ #include #include #include +#include #include "otx2_reg.h" #include "otx2_common.h" @@ -89,6 +90,11 @@ int otx2_update_sq_stats(struct otx2_nic *pfvf, int qidx) if (!pfvf->qset.sq) return 0; + if (qidx >= pfvf->hw.non_qos_queues) { + if (!test_bit(qidx - pfvf->hw.non_qos_queues, pfvf->qos.qos_sq_bmap)) + return 0; + } + otx2_nix_sq_op_stats(&sq->stats, pfvf, qidx); return 1; } @@ -513,11 +519,32 @@ void otx2_config_irq_coalescing(struct otx2_nic *pfvf, int qidx) (pfvf->hw.cq_ecount_wait - 1)); } -int __otx2_alloc_rbuf(struct otx2_nic *pfvf, struct otx2_pool *pool, - dma_addr_t *dma) +static int otx2_alloc_pool_buf(struct otx2_nic *pfvf, struct otx2_pool *pool, + dma_addr_t *dma) +{ + unsigned int offset = 0; + struct page *page; + size_t sz; + + sz = SKB_DATA_ALIGN(pool->rbsize); + sz = ALIGN(sz, OTX2_ALIGN); + + page = page_pool_alloc_frag(pool->page_pool, &offset, sz, GFP_ATOMIC); + if (unlikely(!page)) + return -ENOMEM; + + *dma = page_pool_get_dma_addr(page) + offset; + return 0; +} + +static int __otx2_alloc_rbuf(struct otx2_nic *pfvf, struct otx2_pool *pool, + dma_addr_t *dma) { u8 *buf; + if (pool->page_pool) + return otx2_alloc_pool_buf(pfvf, pool, dma); + buf = napi_alloc_frag_align(pool->rbsize, OTX2_ALIGN); if (unlikely(!buf)) return -ENOMEM; @@ -532,8 +559,8 @@ int __otx2_alloc_rbuf(struct otx2_nic *pfvf, struct otx2_pool *pool, return 0; } -static int otx2_alloc_rbuf(struct otx2_nic *pfvf, struct otx2_pool *pool, - dma_addr_t *dma) +int otx2_alloc_rbuf(struct otx2_nic *pfvf, struct otx2_pool *pool, + dma_addr_t *dma) { int ret; @@ -616,6 +643,10 @@ int otx2_txschq_config(struct otx2_nic *pfvf, int lvl, int prio, bool txschq_for req->regval[0] = ((u64)pfvf->tx_max_pktlen << 8) | OTX2_MIN_MTU; req->regval[0] |= (0x20ULL << 51) | (0x80ULL << 39) | (0x2ULL << 36); + /* Set link type for DWRR MTU selection on CN10K silicons */ + if (!is_dev_otx2(pfvf->pdev)) + req->regval[0] |= FIELD_PREP(GENMASK_ULL(58, 57), + (u64)hw->smq_link_type); req->num_regs++; /* MDQ config */ parent = schq_list[NIX_TXSCH_LVL_TL4][prio]; @@ -716,7 +747,8 @@ EXPORT_SYMBOL(otx2_smq_flush); int otx2_txsch_alloc(struct otx2_nic *pfvf) { struct nix_txsch_alloc_req *req; - int lvl; + struct nix_txsch_alloc_rsp *rsp; + int lvl, schq, rc; /* Get memory to put this msg */ req = otx2_mbox_alloc_msg_nix_txsch_alloc(&pfvf->mbox); @@ -726,43 +758,83 @@ int otx2_txsch_alloc(struct otx2_nic *pfvf) /* Request one schq per level */ for (lvl = 0; lvl < NIX_TXSCH_LVL_CNT; lvl++) req->schq[lvl] = 1; + rc = otx2_sync_mbox_msg(&pfvf->mbox); + if (rc) + return rc; - return otx2_sync_mbox_msg(&pfvf->mbox); + rsp = (struct nix_txsch_alloc_rsp *) + otx2_mbox_get_rsp(&pfvf->mbox.mbox, 0, &req->hdr); + if (IS_ERR(rsp)) + return PTR_ERR(rsp); + + /* Setup transmit scheduler list */ + for (lvl = 0; lvl < NIX_TXSCH_LVL_CNT; lvl++) + for (schq = 0; schq < rsp->schq[lvl]; schq++) + pfvf->hw.txschq_list[lvl][schq] = + rsp->schq_list[lvl][schq]; + + pfvf->hw.txschq_link_cfg_lvl = rsp->link_cfg_lvl; + + return 0; } -int otx2_txschq_stop(struct otx2_nic *pfvf) +void otx2_txschq_free_one(struct otx2_nic *pfvf, u16 lvl, u16 schq) { struct nix_txsch_free_req *free_req; - int lvl, schq, err; + int err; mutex_lock(&pfvf->mbox.lock); - /* Free the transmit schedulers */ + free_req = otx2_mbox_alloc_msg_nix_txsch_free(&pfvf->mbox); if (!free_req) { mutex_unlock(&pfvf->mbox.lock); - return -ENOMEM; + netdev_err(pfvf->netdev, + "Failed alloc txschq free req\n"); + return; } - free_req->flags = TXSCHQ_FREE_ALL; + free_req->schq_lvl = lvl; + free_req->schq = schq; + err = otx2_sync_mbox_msg(&pfvf->mbox); + if (err) { + netdev_err(pfvf->netdev, + "Failed stop txschq %d at level %d\n", schq, lvl); + } + mutex_unlock(&pfvf->mbox.lock); +} + +void otx2_txschq_stop(struct otx2_nic *pfvf) +{ + int lvl, schq; + + /* free non QOS TLx nodes */ + for (lvl = 0; lvl < NIX_TXSCH_LVL_CNT; lvl++) + otx2_txschq_free_one(pfvf, lvl, + pfvf->hw.txschq_list[lvl][0]); /* Clear the txschq list */ for (lvl = 0; lvl < NIX_TXSCH_LVL_CNT; lvl++) { for (schq = 0; schq < MAX_TXSCHQ_PER_FUNC; schq++) pfvf->hw.txschq_list[lvl][schq] = 0; } - return err; + } void otx2_sqb_flush(struct otx2_nic *pfvf) { int qidx, sqe_tail, sqe_head; + struct otx2_snd_queue *sq; u64 incr, *ptr, val; int timeout = 1000; ptr = (u64 *)otx2_get_regaddr(pfvf, NIX_LF_SQ_OP_STATUS); - for (qidx = 0; qidx < pfvf->hw.tot_tx_queues; qidx++) { + for (qidx = 0; qidx < otx2_get_total_tx_queues(pfvf); qidx++) { + sq = &pfvf->qset.sq[qidx]; + if (!sq->sqb_ptrs) + continue; + incr = (u64)qidx << 32; while (timeout) { val = otx2_atomic64_add(incr, ptr); @@ -862,7 +934,7 @@ int otx2_sq_aq_init(void *dev, u16 qidx, u16 sqb_aura) return otx2_sync_mbox_msg(&pfvf->mbox); } -static int otx2_sq_init(struct otx2_nic *pfvf, u16 qidx, u16 sqb_aura) +int otx2_sq_init(struct otx2_nic *pfvf, u16 qidx, u16 sqb_aura) { struct otx2_qset *qset = &pfvf->qset; struct otx2_snd_queue *sq; @@ -935,9 +1007,17 @@ static int otx2_cq_init(struct otx2_nic *pfvf, u16 qidx) cq->cint_idx = qidx - pfvf->hw.rx_queues; cq->cqe_cnt = qset->sqe_cnt; } else { - cq->cq_type = CQ_XDP; - cq->cint_idx = qidx - non_xdp_queues; - cq->cqe_cnt = qset->sqe_cnt; + if (pfvf->hw.xdp_queues && + qidx < non_xdp_queues + pfvf->hw.xdp_queues) { + cq->cq_type = CQ_XDP; + cq->cint_idx = qidx - non_xdp_queues; + cq->cqe_cnt = qset->sqe_cnt; + } else { + cq->cq_type = CQ_QOS; + cq->cint_idx = qidx - non_xdp_queues - + pfvf->hw.xdp_queues; + cq->cqe_cnt = qset->sqe_cnt; + } } cq->cqe_size = pfvf->qset.xqe_size; @@ -1048,7 +1128,7 @@ int otx2_config_nix_queues(struct otx2_nic *pfvf) } /* Initialize TX queues */ - for (qidx = 0; qidx < pfvf->hw.tot_tx_queues; qidx++) { + for (qidx = 0; qidx < pfvf->hw.non_qos_queues; qidx++) { u16 sqb_aura = otx2_get_pool_idx(pfvf, AURA_NIX_SQ, qidx); err = otx2_sq_init(pfvf, qidx, sqb_aura); @@ -1095,7 +1175,7 @@ int otx2_config_nix(struct otx2_nic *pfvf) /* Set RQ/SQ/CQ counts */ nixlf->rq_cnt = pfvf->hw.rx_queues; - nixlf->sq_cnt = pfvf->hw.tot_tx_queues; + nixlf->sq_cnt = otx2_get_total_tx_queues(pfvf); nixlf->cq_cnt = pfvf->qset.cq_cnt; nixlf->rss_sz = MAX_RSS_INDIR_TBL_SIZE; nixlf->rss_grps = MAX_RSS_GROUPS; @@ -1133,7 +1213,7 @@ void otx2_sq_free_sqbs(struct otx2_nic *pfvf) int sqb, qidx; u64 iova, pa; - for (qidx = 0; qidx < hw->tot_tx_queues; qidx++) { + for (qidx = 0; qidx < otx2_get_total_tx_queues(pfvf); qidx++) { sq = &qset->sq[qidx]; if (!sq->sqb_ptrs) continue; @@ -1151,10 +1231,31 @@ void otx2_sq_free_sqbs(struct otx2_nic *pfvf) } } +void otx2_free_bufs(struct otx2_nic *pfvf, struct otx2_pool *pool, + u64 iova, int size) +{ + struct page *page; + u64 pa; + + pa = otx2_iova_to_phys(pfvf->iommu_domain, iova); + page = virt_to_head_page(phys_to_virt(pa)); + + if (pool->page_pool) { + page_pool_put_full_page(pool->page_pool, page, true); + } else { + dma_unmap_page_attrs(pfvf->dev, iova, size, + DMA_FROM_DEVICE, + DMA_ATTR_SKIP_CPU_SYNC); + + put_page(page); + } +} + void otx2_free_aura_ptr(struct otx2_nic *pfvf, int type) { int pool_id, pool_start = 0, pool_end = 0, size = 0; - u64 iova, pa; + struct otx2_pool *pool; + u64 iova; if (type == AURA_NIX_SQ) { pool_start = otx2_get_pool_idx(pfvf, type, 0); @@ -1170,15 +1271,13 @@ void otx2_free_aura_ptr(struct otx2_nic *pfvf, int type) /* Free SQB and RQB pointers from the aura pool */ for (pool_id = pool_start; pool_id < pool_end; pool_id++) { iova = otx2_aura_allocptr(pfvf, pool_id); + pool = &pfvf->qset.pool[pool_id]; while (iova) { if (type == AURA_NIX_RQ) iova -= OTX2_HEAD_ROOM; - pa = otx2_iova_to_phys(pfvf->iommu_domain, iova); - dma_unmap_page_attrs(pfvf->dev, iova, size, - DMA_FROM_DEVICE, - DMA_ATTR_SKIP_CPU_SYNC); - put_page(virt_to_page(phys_to_virt(pa))); + otx2_free_bufs(pfvf, pool, iova, size); + iova = otx2_aura_allocptr(pfvf, pool_id); } } @@ -1196,13 +1295,15 @@ void otx2_aura_pool_free(struct otx2_nic *pfvf) pool = &pfvf->qset.pool[pool_id]; qmem_free(pfvf->dev, pool->stack); qmem_free(pfvf->dev, pool->fc_addr); + page_pool_destroy(pool->page_pool); + pool->page_pool = NULL; } devm_kfree(pfvf->dev, pfvf->qset.pool); pfvf->qset.pool = NULL; } -static int otx2_aura_init(struct otx2_nic *pfvf, int aura_id, - int pool_id, int numptrs) +int otx2_aura_init(struct otx2_nic *pfvf, int aura_id, + int pool_id, int numptrs) { struct npa_aq_enq_req *aq; struct otx2_pool *pool; @@ -1278,9 +1379,10 @@ static int otx2_aura_init(struct otx2_nic *pfvf, int aura_id, return 0; } -static int otx2_pool_init(struct otx2_nic *pfvf, u16 pool_id, - int stack_pages, int numptrs, int buf_size) +int otx2_pool_init(struct otx2_nic *pfvf, u16 pool_id, + int stack_pages, int numptrs, int buf_size, int type) { + struct page_pool_params pp_params = { 0 }; struct npa_aq_enq_req *aq; struct otx2_pool *pool; int err; @@ -1324,6 +1426,22 @@ static int otx2_pool_init(struct otx2_nic *pfvf, u16 pool_id, aq->ctype = NPA_AQ_CTYPE_POOL; aq->op = NPA_AQ_INSTOP_INIT; + if (type != AURA_NIX_RQ) { + pool->page_pool = NULL; + return 0; + } + + pp_params.flags = PP_FLAG_PAGE_FRAG | PP_FLAG_DMA_MAP; + pp_params.pool_size = numptrs; + pp_params.nid = NUMA_NO_NODE; + pp_params.dev = pfvf->dev; + pp_params.dma_dir = DMA_FROM_DEVICE; + pool->page_pool = page_pool_create(&pp_params); + if (IS_ERR(pool->page_pool)) { + netdev_err(pfvf->netdev, "Creation of page pool failed\n"); + return PTR_ERR(pool->page_pool); + } + return 0; } @@ -1349,7 +1467,7 @@ int otx2_sq_aura_pool_init(struct otx2_nic *pfvf) stack_pages = (num_sqbs + hw->stack_pg_ptrs - 1) / hw->stack_pg_ptrs; - for (qidx = 0; qidx < hw->tot_tx_queues; qidx++) { + for (qidx = 0; qidx < hw->non_qos_queues; qidx++) { pool_id = otx2_get_pool_idx(pfvf, AURA_NIX_SQ, qidx); /* Initialize aura context */ err = otx2_aura_init(pfvf, pool_id, pool_id, num_sqbs); @@ -1358,7 +1476,7 @@ int otx2_sq_aura_pool_init(struct otx2_nic *pfvf) /* Initialize pool context */ err = otx2_pool_init(pfvf, pool_id, stack_pages, - num_sqbs, hw->sqb_size); + num_sqbs, hw->sqb_size, AURA_NIX_SQ); if (err) goto fail; } @@ -1369,7 +1487,7 @@ int otx2_sq_aura_pool_init(struct otx2_nic *pfvf) goto fail; /* Allocate pointers and free them to aura/pool */ - for (qidx = 0; qidx < hw->tot_tx_queues; qidx++) { + for (qidx = 0; qidx < hw->non_qos_queues; qidx++) { pool_id = otx2_get_pool_idx(pfvf, AURA_NIX_SQ, qidx); pool = &pfvf->qset.pool[pool_id]; @@ -1421,7 +1539,7 @@ int otx2_rq_aura_pool_init(struct otx2_nic *pfvf) } for (pool_id = 0; pool_id < hw->rqpool_cnt; pool_id++) { err = otx2_pool_init(pfvf, pool_id, stack_pages, - num_ptrs, pfvf->rbsize); + num_ptrs, pfvf->rbsize, AURA_NIX_RQ); if (err) goto fail; } @@ -1605,7 +1723,6 @@ int otx2_nix_config_bp(struct otx2_nic *pfvf, bool enable) req->bpid_per_chan = 0; #endif - return otx2_sync_mbox_msg(&pfvf->mbox); } EXPORT_SYMBOL(otx2_nix_config_bp); @@ -1629,21 +1746,6 @@ void mbox_handler_cgx_fec_stats(struct otx2_nic *pfvf, pfvf->hw.cgx_fec_uncorr_blks += rsp->fec_uncorr_blks; } -void mbox_handler_nix_txsch_alloc(struct otx2_nic *pf, - struct nix_txsch_alloc_rsp *rsp) -{ - int lvl, schq; - - /* Setup transmit scheduler list */ - for (lvl = 0; lvl < NIX_TXSCH_LVL_CNT; lvl++) - for (schq = 0; schq < rsp->schq[lvl]; schq++) - pf->hw.txschq_list[lvl][schq] = - rsp->schq_list[lvl][schq]; - - pf->hw.txschq_link_cfg_lvl = rsp->link_cfg_lvl; -} -EXPORT_SYMBOL(mbox_handler_nix_txsch_alloc); - void mbox_handler_npa_lf_alloc(struct otx2_nic *pfvf, struct npa_lf_alloc_rsp *rsp) { @@ -1727,6 +1829,17 @@ void otx2_set_cints_affinity(struct otx2_nic *pfvf) } } +static u32 get_dwrr_mtu(struct otx2_nic *pfvf, struct nix_hw_info *hw) +{ + if (is_otx2_lbkvf(pfvf->pdev)) { + pfvf->hw.smq_link_type = SMQ_LINK_TYPE_LBK; + return hw->lbk_dwrr_mtu; + } + + pfvf->hw.smq_link_type = SMQ_LINK_TYPE_RPM; + return hw->rpm_dwrr_mtu; +} + u16 otx2_get_max_mtu(struct otx2_nic *pfvf) { struct nix_hw_info *rsp; @@ -1756,7 +1869,7 @@ u16 otx2_get_max_mtu(struct otx2_nic *pfvf) max_mtu = rsp->max_mtu - 8 - OTX2_ETH_HLEN; /* Also save DWRR MTU, needed for DWRR weight calculation */ - pfvf->hw.dwrr_mtu = rsp->rpm_dwrr_mtu; + pfvf->hw.dwrr_mtu = get_dwrr_mtu(pfvf, rsp); if (!pfvf->hw.dwrr_mtu) pfvf->hw.dwrr_mtu = 1; } diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h index 0c8fc66ade82da1bb342865cc8db4a51df25968e..ba8091131ec0848aa80251fed904fc88b5b52f9b 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -27,6 +28,7 @@ #include "otx2_txrx.h" #include "otx2_devlink.h" #include +#include "qos.h" /* IPv4 flag more fragment bit */ #define IPV4_FLAG_MORE 0x20 @@ -183,13 +185,29 @@ struct mbox { int up_num_msgs; /* mbox_up number of messages */ }; +/* Egress rate limiting definitions */ +#define MAX_BURST_EXPONENT 0x0FULL +#define MAX_BURST_MANTISSA 0xFFULL +#define MAX_BURST_SIZE 130816ULL +#define MAX_RATE_DIVIDER_EXPONENT 12ULL +#define MAX_RATE_EXPONENT 0x0FULL +#define MAX_RATE_MANTISSA 0xFFULL + +/* Bitfields in NIX_TLX_PIR register */ +#define TLX_RATE_MANTISSA GENMASK_ULL(8, 1) +#define TLX_RATE_EXPONENT GENMASK_ULL(12, 9) +#define TLX_RATE_DIVIDER_EXPONENT GENMASK_ULL(16, 13) +#define TLX_BURST_MANTISSA GENMASK_ULL(36, 29) +#define TLX_BURST_EXPONENT GENMASK_ULL(40, 37) + struct otx2_hw { struct pci_dev *pdev; struct otx2_rss_info rss_info; u16 rx_queues; u16 tx_queues; u16 xdp_queues; - u16 tot_tx_queues; + u16 tc_tx_queues; + u16 non_qos_queues; /* tx queues plus xdp queues */ u16 max_queues; u16 pool_cnt; u16 rqpool_cnt; @@ -209,6 +227,7 @@ struct otx2_hw { u16 txschq_list[NIX_TXSCH_LVL_CNT][MAX_TXSCHQ_PER_FUNC]; u16 matchall_ipolicer; u32 dwrr_mtu; + u8 smq_link_type; /* HW settings, coalescing etc */ u16 rx_chan_base; @@ -250,6 +269,7 @@ struct otx2_hw { #define CN10K_RPM 3 #define CN10K_PTP_ONESTEP 4 #define CN10K_HW_MACSEC 5 +#define QOS_CIR_PIR_SUPPORT 6 unsigned long cap_flag; #define LMT_LINE_SIZE 128 @@ -398,6 +418,9 @@ struct cn10k_mcs_txsc { u8 sa_bmap; u8 sa_key[CN10K_MCS_SA_PER_SC][MACSEC_MAX_KEY_LEN]; u8 encoding_sa; + u8 salt[CN10K_MCS_SA_PER_SC][MACSEC_SALT_LEN]; + ssci_t ssci[CN10K_MCS_SA_PER_SC]; + bool vlan_dev; /* macsec running on VLAN ? */ }; struct cn10k_mcs_rxsc { @@ -410,6 +433,8 @@ struct cn10k_mcs_rxsc { u16 hw_sa_id[CN10K_MCS_SA_PER_SC]; u8 sa_bmap; u8 sa_key[CN10K_MCS_SA_PER_SC][MACSEC_MAX_KEY_LEN]; + u8 salt[CN10K_MCS_SA_PER_SC][MACSEC_SALT_LEN]; + ssci_t ssci[CN10K_MCS_SA_PER_SC]; }; struct cn10k_mcs_cfg { @@ -501,6 +526,8 @@ struct otx2_nic { u16 pfc_schq_list[NIX_TXSCH_LVL_CNT][MAX_TXSCHQ_PER_FUNC]; bool pfc_alloc_status[NIX_PF_PFC_PRIO_MAX]; #endif + /* qos */ + struct otx2_qos qos; /* napi event count. It is needed for adaptive irq coalescing. */ u32 napi_events; @@ -582,6 +609,7 @@ static inline void otx2_setup_dev_hw_settings(struct otx2_nic *pfvf) __set_bit(CN10K_LMTST, &hw->cap_flag); __set_bit(CN10K_RPM, &hw->cap_flag); __set_bit(CN10K_PTP_ONESTEP, &hw->cap_flag); + __set_bit(QOS_CIR_PIR_SUPPORT, &hw->cap_flag); } if (is_dev_cn10kb(pfvf->pdev)) @@ -745,8 +773,7 @@ static inline void cn10k_aura_freeptr(void *dev, int aura, u64 buf) /* Alloc pointer from pool/aura */ static inline u64 otx2_aura_allocptr(struct otx2_nic *pfvf, int aura) { - u64 *ptr = (u64 *)otx2_get_regaddr(pfvf, - NPA_LF_AURA_OP_ALLOCX(0)); + u64 *ptr = (__force u64 *)otx2_get_regaddr(pfvf, NPA_LF_AURA_OP_ALLOCX(0)); u64 incr = (u64)aura | BIT_ULL(63); return otx2_atomic64_add(incr, ptr); @@ -888,12 +915,34 @@ static inline void otx2_dma_unmap_page(struct otx2_nic *pfvf, static inline u16 otx2_get_smq_idx(struct otx2_nic *pfvf, u16 qidx) { + u16 smq; #ifdef CONFIG_DCB if (qidx < NIX_PF_PFC_PRIO_MAX && pfvf->pfc_alloc_status[qidx]) return pfvf->pfc_schq_list[NIX_TXSCH_LVL_SMQ][qidx]; #endif + /* check if qidx falls under QOS queues */ + if (qidx >= pfvf->hw.non_qos_queues) + smq = pfvf->qos.qid_to_sqmap[qidx - pfvf->hw.non_qos_queues]; + else + smq = pfvf->hw.txschq_list[NIX_TXSCH_LVL_SMQ][0]; + + return smq; +} + +static inline u16 otx2_get_total_tx_queues(struct otx2_nic *pfvf) +{ + return pfvf->hw.non_qos_queues + pfvf->hw.tc_tx_queues; +} + +static inline u64 otx2_convert_rate(u64 rate) +{ + u64 converted_rate; + + /* Convert bytes per second to Mbps */ + converted_rate = rate * 8; + converted_rate = max_t(u64, converted_rate / 1000000, 1); - return pfvf->hw.txschq_list[NIX_TXSCH_LVL_SMQ][0]; + return converted_rate; } /* MSI-X APIs */ @@ -920,19 +969,25 @@ int otx2_config_nix(struct otx2_nic *pfvf); int otx2_config_nix_queues(struct otx2_nic *pfvf); int otx2_txschq_config(struct otx2_nic *pfvf, int lvl, int prio, bool pfc_en); int otx2_txsch_alloc(struct otx2_nic *pfvf); -int otx2_txschq_stop(struct otx2_nic *pfvf); +void otx2_txschq_stop(struct otx2_nic *pfvf); +void otx2_txschq_free_one(struct otx2_nic *pfvf, u16 lvl, u16 schq); void otx2_sqb_flush(struct otx2_nic *pfvf); -int __otx2_alloc_rbuf(struct otx2_nic *pfvf, struct otx2_pool *pool, - dma_addr_t *dma); +int otx2_alloc_rbuf(struct otx2_nic *pfvf, struct otx2_pool *pool, + dma_addr_t *dma); int otx2_rxtx_enable(struct otx2_nic *pfvf, bool enable); void otx2_ctx_disable(struct mbox *mbox, int type, bool npa); int otx2_nix_config_bp(struct otx2_nic *pfvf, bool enable); -void otx2_cleanup_rx_cqes(struct otx2_nic *pfvf, struct otx2_cq_queue *cq); +void otx2_cleanup_rx_cqes(struct otx2_nic *pfvf, struct otx2_cq_queue *cq, int qidx); void otx2_cleanup_tx_cqes(struct otx2_nic *pfvf, struct otx2_cq_queue *cq); +int otx2_sq_init(struct otx2_nic *pfvf, u16 qidx, u16 sqb_aura); int otx2_sq_aq_init(void *dev, u16 qidx, u16 sqb_aura); int cn10k_sq_aq_init(void *dev, u16 qidx, u16 sqb_aura); int otx2_alloc_buffer(struct otx2_nic *pfvf, struct otx2_cq_queue *cq, dma_addr_t *dma); +int otx2_pool_init(struct otx2_nic *pfvf, u16 pool_id, + int stack_pages, int numptrs, int buf_size, int type); +int otx2_aura_init(struct otx2_nic *pfvf, int aura_id, + int pool_id, int numptrs); /* RSS configuration APIs*/ int otx2_rss_init(struct otx2_nic *pfvf); @@ -1000,6 +1055,8 @@ u16 otx2_get_max_mtu(struct otx2_nic *pfvf); int otx2_handle_ntuple_tc_features(struct net_device *netdev, netdev_features_t features); int otx2_smq_flush(struct otx2_nic *pfvf, int smq); +void otx2_free_bufs(struct otx2_nic *pfvf, struct otx2_pool *pool, + u64 iova, int size); /* tc support */ int otx2_init_tc(struct otx2_nic *nic); @@ -1040,4 +1097,24 @@ static inline void cn10k_handle_mcs_event(struct otx2_nic *pfvf, {} #endif /* CONFIG_MACSEC */ +/* qos support */ +static inline void otx2_qos_init(struct otx2_nic *pfvf, int qos_txqs) +{ + struct otx2_hw *hw = &pfvf->hw; + + hw->tc_tx_queues = qos_txqs; + INIT_LIST_HEAD(&pfvf->qos.qos_tree); + mutex_init(&pfvf->qos.qos_lock); +} + +static inline void otx2_shutdown_qos(struct otx2_nic *pfvf) +{ + mutex_destroy(&pfvf->qos.qos_lock); +} + +u16 otx2_select_queue(struct net_device *netdev, struct sk_buff *skb, + struct net_device *sb_dev); +int otx2_get_txq_by_classid(struct otx2_nic *pfvf, u16 classid); +void otx2_qos_config_txschq(struct otx2_nic *pfvf); +void otx2_clean_qos_queues(struct otx2_nic *pfvf); #endif /* OTX2_COMMON_H */ diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c index 0f8d1a69139f3f35ed0e089b2f0c1b4ba6b94e3e..c47d91da32dc7012edb908a92976e5f51f203e4b 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c @@ -92,10 +92,16 @@ static void otx2_get_qset_strings(struct otx2_nic *pfvf, u8 **data, int qset) *data += ETH_GSTRING_LEN; } } - for (qidx = 0; qidx < pfvf->hw.tx_queues; qidx++) { + + for (qidx = 0; qidx < otx2_get_total_tx_queues(pfvf); qidx++) { for (stats = 0; stats < otx2_n_queue_stats; stats++) { - sprintf(*data, "txq%d: %s", qidx + start_qidx, - otx2_queue_stats[stats].name); + if (qidx >= pfvf->hw.non_qos_queues) + sprintf(*data, "txq_qos%d: %s", + qidx + start_qidx - pfvf->hw.non_qos_queues, + otx2_queue_stats[stats].name); + else + sprintf(*data, "txq%d: %s", qidx + start_qidx, + otx2_queue_stats[stats].name); *data += ETH_GSTRING_LEN; } } @@ -159,7 +165,7 @@ static void otx2_get_qset_stats(struct otx2_nic *pfvf, [otx2_queue_stats[stat].index]; } - for (qidx = 0; qidx < pfvf->hw.tx_queues; qidx++) { + for (qidx = 0; qidx < otx2_get_total_tx_queues(pfvf); qidx++) { if (!otx2_update_sq_stats(pfvf, qidx)) { for (stat = 0; stat < otx2_n_queue_stats; stat++) *((*data)++) = 0; @@ -254,7 +260,7 @@ static int otx2_get_sset_count(struct net_device *netdev, int sset) return -EINVAL; qstats_count = otx2_n_queue_stats * - (pfvf->hw.rx_queues + pfvf->hw.tx_queues); + (pfvf->hw.rx_queues + otx2_get_total_tx_queues(pfvf)); if (!test_bit(CN10K_RPM, &pfvf->hw.cap_flag)) mac_stats = CGX_RX_STATS_COUNT + CGX_TX_STATS_COUNT; otx2_update_lmac_fec_stats(pfvf); @@ -282,7 +288,7 @@ static int otx2_set_channels(struct net_device *dev, { struct otx2_nic *pfvf = netdev_priv(dev); bool if_up = netif_running(dev); - int err = 0; + int err, qos_txqs; if (!channel->rx_count || !channel->tx_count) return -EINVAL; @@ -296,14 +302,19 @@ static int otx2_set_channels(struct net_device *dev, if (if_up) dev->netdev_ops->ndo_stop(dev); - err = otx2_set_real_num_queues(dev, channel->tx_count, + qos_txqs = bitmap_weight(pfvf->qos.qos_sq_bmap, + OTX2_QOS_MAX_LEAF_NODES); + + err = otx2_set_real_num_queues(dev, channel->tx_count + qos_txqs, channel->rx_count); if (err) return err; pfvf->hw.rx_queues = channel->rx_count; pfvf->hw.tx_queues = channel->tx_count; - pfvf->qset.cq_cnt = pfvf->hw.tx_queues + pfvf->hw.rx_queues; + if (pfvf->xdp_prog) + pfvf->hw.xdp_queues = channel->rx_count; + pfvf->hw.non_qos_queues = pfvf->hw.tx_queues + pfvf->hw.xdp_queues; if (if_up) err = dev->netdev_ops->ndo_open(dev); @@ -1405,7 +1416,7 @@ static int otx2vf_get_sset_count(struct net_device *netdev, int sset) return -EINVAL; qstats_count = otx2_n_queue_stats * - (vf->hw.rx_queues + vf->hw.tx_queues); + (vf->hw.rx_queues + otx2_get_total_tx_queues(vf)); return otx2_n_dev_stats + otx2_n_drv_stats + qstats_count + 1; } diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c index 10e11262d48a0b3ae7a9ba4c74e5b8bfd4e5eae6..2d7713a1a15394e550a2c83b8ae8f5a49b4f9af3 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c @@ -872,6 +872,14 @@ static int otx2_prepare_flow_request(struct ethtool_rx_flow_spec *fsp, return -EINVAL; vlan_etype = be16_to_cpu(fsp->h_ext.vlan_etype); + + /* Drop rule with vlan_etype == 802.1Q + * and vlan_id == 0 is not supported + */ + if (vlan_etype == ETH_P_8021Q && !fsp->m_ext.vlan_tci && + fsp->ring_cookie == RX_CLS_FLOW_DISC) + return -EINVAL; + /* Only ETH_P_8021Q and ETH_P_802AD types supported */ if (vlan_etype != ETH_P_8021Q && vlan_etype != ETH_P_8021AD) diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c index 18284ad751572006d41c5b724aff5f9628d741bc..fe8ea4e531b7e3bc18675cb31ab1dc1889339cb7 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c @@ -23,6 +23,7 @@ #include "otx2_struct.h" #include "otx2_ptp.h" #include "cn10k.h" +#include "qos.h" #include #define DRV_NAME "rvu_nicpf" @@ -271,8 +272,7 @@ static int otx2_pf_flr_init(struct otx2_nic *pf, int num_vfs) { int vf; - pf->flr_wq = alloc_workqueue("otx2_pf_flr_wq", - WQ_UNBOUND | WQ_HIGHPRI, 1); + pf->flr_wq = alloc_ordered_workqueue("otx2_pf_flr_wq", WQ_HIGHPRI); if (!pf->flr_wq) return -ENOMEM; @@ -593,9 +593,8 @@ static int otx2_pfvf_mbox_init(struct otx2_nic *pf, int numvfs) if (!pf->mbox_pfvf) return -ENOMEM; - pf->mbox_pfvf_wq = alloc_workqueue("otx2_pfvf_mailbox", - WQ_UNBOUND | WQ_HIGHPRI | - WQ_MEM_RECLAIM, 1); + pf->mbox_pfvf_wq = alloc_ordered_workqueue("otx2_pfvf_mailbox", + WQ_HIGHPRI | WQ_MEM_RECLAIM); if (!pf->mbox_pfvf_wq) return -ENOMEM; @@ -791,10 +790,6 @@ static void otx2_process_pfaf_mbox_msg(struct otx2_nic *pf, case MBOX_MSG_NIX_LF_ALLOC: mbox_handler_nix_lf_alloc(pf, (struct nix_lf_alloc_rsp *)msg); break; - case MBOX_MSG_NIX_TXSCH_ALLOC: - mbox_handler_nix_txsch_alloc(pf, - (struct nix_txsch_alloc_rsp *)msg); - break; case MBOX_MSG_NIX_BP_ENABLE: mbox_handler_nix_bp_enable(pf, (struct nix_bp_cfg_rsp *)msg); break; @@ -1063,9 +1058,8 @@ static int otx2_pfaf_mbox_init(struct otx2_nic *pf) int err; mbox->pfvf = pf; - pf->mbox_wq = alloc_workqueue("otx2_pfaf_mailbox", - WQ_UNBOUND | WQ_HIGHPRI | - WQ_MEM_RECLAIM, 1); + pf->mbox_wq = alloc_ordered_workqueue("otx2_pfaf_mailbox", + WQ_HIGHPRI | WQ_MEM_RECLAIM); if (!pf->mbox_wq) return -ENOMEM; @@ -1228,6 +1222,7 @@ static char *nix_snd_status_e_str[NIX_SND_STATUS_MAX] = { static irqreturn_t otx2_q_intr_handler(int irq, void *data) { struct otx2_nic *pf = data; + struct otx2_snd_queue *sq; u64 val, *ptr; u64 qidx = 0; @@ -1257,10 +1252,14 @@ static irqreturn_t otx2_q_intr_handler(int irq, void *data) } /* SQ */ - for (qidx = 0; qidx < pf->hw.tot_tx_queues; qidx++) { + for (qidx = 0; qidx < otx2_get_total_tx_queues(pf); qidx++) { u64 sq_op_err_dbg, mnq_err_dbg, snd_err_dbg; u8 sq_op_err_code, mnq_err_code, snd_err_code; + sq = &pf->qset.sq[qidx]; + if (!sq->sqb_ptrs) + continue; + /* Below debug registers captures first errors corresponding to * those registers. We don't have to check against SQ qid as * these are fatal errors. @@ -1383,8 +1382,11 @@ static void otx2_free_sq_res(struct otx2_nic *pf) otx2_ctx_disable(&pf->mbox, NIX_AQ_CTYPE_SQ, false); /* Free SQB pointers */ otx2_sq_free_sqbs(pf); - for (qidx = 0; qidx < pf->hw.tot_tx_queues; qidx++) { + for (qidx = 0; qidx < otx2_get_total_tx_queues(pf); qidx++) { sq = &qset->sq[qidx]; + /* Skip freeing Qos queues if they are not initialized */ + if (!sq->sqe) + continue; qmem_free(pf->dev, sq->sqe); qmem_free(pf->dev, sq->tso_hdrs); kfree(sq->sg); @@ -1433,7 +1435,7 @@ static int otx2_init_hw_resources(struct otx2_nic *pf) * so, aura count = pool count. */ hw->rqpool_cnt = hw->rx_queues; - hw->sqpool_cnt = hw->tot_tx_queues; + hw->sqpool_cnt = otx2_get_total_tx_queues(pf); hw->pool_cnt = hw->rqpool_cnt + hw->sqpool_cnt; /* Maximum hardware supported transmit length */ @@ -1516,8 +1518,7 @@ static int otx2_init_hw_resources(struct otx2_nic *pf) otx2_free_cq_res(pf); otx2_ctx_disable(mbox, NIX_AQ_CTYPE_RQ, false); err_free_txsch: - if (otx2_txschq_stop(pf)) - dev_err(pf->dev, "%s failed to stop TX schedulers\n", __func__); + otx2_txschq_stop(pf); err_free_sq_ptrs: otx2_sq_free_sqbs(pf); err_free_rq_ptrs: @@ -1551,22 +1552,24 @@ static void otx2_free_hw_resources(struct otx2_nic *pf) struct nix_lf_free_req *free_req; struct mbox *mbox = &pf->mbox; struct otx2_cq_queue *cq; + struct otx2_pool *pool; struct msg_req *req; - int qidx, err; + int pool_id; + int qidx; /* Ensure all SQE are processed */ otx2_sqb_flush(pf); /* Stop transmission */ - err = otx2_txschq_stop(pf); - if (err) - dev_err(pf->dev, "RVUPF: Failed to stop/free TX schedulers\n"); + otx2_txschq_stop(pf); #ifdef CONFIG_DCB if (pf->pfc_en) otx2_pfc_txschq_stop(pf); #endif + otx2_clean_qos_queues(pf); + mutex_lock(&mbox->lock); /* Disable backpressure */ if (!(pf->pcifunc & RVU_PFVF_FUNC_MASK)) @@ -1580,7 +1583,7 @@ static void otx2_free_hw_resources(struct otx2_nic *pf) for (qidx = 0; qidx < qset->cq_cnt; qidx++) { cq = &qset->cq[qidx]; if (cq->cq_type == CQ_RX) - otx2_cleanup_rx_cqes(pf, cq); + otx2_cleanup_rx_cqes(pf, cq, qidx); else otx2_cleanup_tx_cqes(pf, cq); } @@ -1590,6 +1593,13 @@ static void otx2_free_hw_resources(struct otx2_nic *pf) /* Free RQ buffer pointers*/ otx2_free_aura_ptr(pf, AURA_NIX_RQ); + for (qidx = 0; qidx < pf->hw.rx_queues; qidx++) { + pool_id = otx2_get_pool_idx(pf, AURA_NIX_RQ, qidx); + pool = &pf->qset.pool[pool_id]; + page_pool_destroy(pool->page_pool); + pool->page_pool = NULL; + } + otx2_free_cq_res(pf); /* Free all ingress bandwidth profiles allocated */ @@ -1688,11 +1698,14 @@ int otx2_open(struct net_device *netdev) netif_carrier_off(netdev); - pf->qset.cq_cnt = pf->hw.rx_queues + pf->hw.tot_tx_queues; /* RQ and SQs are mapped to different CQs, * so find out max CQ IRQs (i.e CINTs) needed. */ - pf->hw.cint_cnt = max(pf->hw.rx_queues, pf->hw.tx_queues); + pf->hw.cint_cnt = max3(pf->hw.rx_queues, pf->hw.tx_queues, + pf->hw.tc_tx_queues); + + pf->qset.cq_cnt = pf->hw.rx_queues + otx2_get_total_tx_queues(pf); + qset->napi = kcalloc(pf->hw.cint_cnt, sizeof(*cq_poll), GFP_KERNEL); if (!qset->napi) return -ENOMEM; @@ -1708,7 +1721,7 @@ int otx2_open(struct net_device *netdev) if (!qset->cq) goto err_free_mem; - qset->sq = kcalloc(pf->hw.tot_tx_queues, + qset->sq = kcalloc(otx2_get_total_tx_queues(pf), sizeof(struct otx2_snd_queue), GFP_KERNEL); if (!qset->sq) goto err_free_mem; @@ -1743,6 +1756,11 @@ int otx2_open(struct net_device *netdev) else cq_poll->cq_ids[CQ_XDP] = CINT_INVALID_CQ; + cq_poll->cq_ids[CQ_QOS] = (qidx < pf->hw.tc_tx_queues) ? + (qidx + pf->hw.rx_queues + + pf->hw.non_qos_queues) : + CINT_INVALID_CQ; + cq_poll->dev = (void *)pf; cq_poll->dim.mode = DIM_CQ_PERIOD_MODE_START_FROM_CQE; INIT_WORK(&cq_poll->dim.work, otx2_dim_work); @@ -1826,6 +1844,9 @@ int otx2_open(struct net_device *netdev) /* 'intf_down' may be checked on any cpu */ smp_wmb(); + /* Enable QoS configuration before starting tx queues */ + otx2_qos_config_txschq(pf); + /* we have already received link status notification */ if (pf->linfo.link_up && !(pf->pcifunc & RVU_PFVF_FUNC_MASK)) otx2_handle_link_event(pf); @@ -1947,6 +1968,12 @@ static netdev_tx_t otx2_xmit(struct sk_buff *skb, struct net_device *netdev) int qidx = skb_get_queue_mapping(skb); struct otx2_snd_queue *sq; struct netdev_queue *txq; + int sq_idx; + + /* XDP SQs are not mapped with TXQs + * advance qid to derive correct sq mapped with QOS + */ + sq_idx = (qidx >= pf->hw.tx_queues) ? (qidx + pf->hw.xdp_queues) : qidx; /* Check for minimum and maximum packet length */ if (skb->len <= ETH_HLEN || @@ -1955,7 +1982,7 @@ static netdev_tx_t otx2_xmit(struct sk_buff *skb, struct net_device *netdev) return NETDEV_TX_OK; } - sq = &pf->qset.sq[qidx]; + sq = &pf->qset.sq[sq_idx]; txq = netdev_get_tx_queue(netdev, qidx); if (!otx2_sq_append_skb(netdev, sq, skb, qidx)) { @@ -1973,14 +2000,48 @@ static netdev_tx_t otx2_xmit(struct sk_buff *skb, struct net_device *netdev) return NETDEV_TX_OK; } -static u16 otx2_select_queue(struct net_device *netdev, struct sk_buff *skb, - struct net_device *sb_dev) +static int otx2_qos_select_htb_queue(struct otx2_nic *pf, struct sk_buff *skb, + u16 htb_maj_id) +{ + u16 classid; + + if ((TC_H_MAJ(skb->priority) >> 16) == htb_maj_id) + classid = TC_H_MIN(skb->priority); + else + classid = READ_ONCE(pf->qos.defcls); + + if (!classid) + return 0; + + return otx2_get_txq_by_classid(pf, classid); +} + +u16 otx2_select_queue(struct net_device *netdev, struct sk_buff *skb, + struct net_device *sb_dev) { -#ifdef CONFIG_DCB struct otx2_nic *pf = netdev_priv(netdev); + bool qos_enabled; +#ifdef CONFIG_DCB u8 vlan_prio; #endif + int txq; + + qos_enabled = (netdev->real_num_tx_queues > pf->hw.tx_queues) ? true : false; + if (unlikely(qos_enabled)) { + /* This smp_load_acquire() pairs with smp_store_release() in + * otx2_qos_root_add() called from htb offload root creation + */ + u16 htb_maj_id = smp_load_acquire(&pf->qos.maj_id); + + if (unlikely(htb_maj_id)) { + txq = otx2_qos_select_htb_queue(pf, skb, htb_maj_id); + if (txq > 0) + return txq; + goto process_pfc; + } + } +process_pfc: #ifdef CONFIG_DCB if (!skb_vlan_tag_present(skb)) goto pick_tx; @@ -1994,8 +2055,13 @@ static u16 otx2_select_queue(struct net_device *netdev, struct sk_buff *skb, pick_tx: #endif - return netdev_pick_tx(netdev, skb, NULL); + txq = netdev_pick_tx(netdev, skb, NULL); + if (unlikely(qos_enabled)) + return txq % pf->hw.tx_queues; + + return txq; } +EXPORT_SYMBOL(otx2_select_queue); static netdev_features_t otx2_fix_features(struct net_device *dev, netdev_features_t features) @@ -2529,7 +2595,7 @@ static int otx2_xdp_setup(struct otx2_nic *pf, struct bpf_prog *prog) xdp_features_clear_redirect_target(dev); } - pf->hw.tot_tx_queues += pf->hw.xdp_queues; + pf->hw.non_qos_queues += pf->hw.xdp_queues; if (if_up) otx2_open(pf->netdev); @@ -2712,10 +2778,10 @@ static void otx2_sriov_vfcfg_cleanup(struct otx2_nic *pf) static int otx2_probe(struct pci_dev *pdev, const struct pci_device_id *id) { struct device *dev = &pdev->dev; + int err, qcount, qos_txqs; struct net_device *netdev; struct otx2_nic *pf; struct otx2_hw *hw; - int err, qcount; int num_vec; err = pcim_enable_device(pdev); @@ -2740,8 +2806,9 @@ static int otx2_probe(struct pci_dev *pdev, const struct pci_device_id *id) /* Set number of queues */ qcount = min_t(int, num_online_cpus(), OTX2_MAX_CQ_CNT); + qos_txqs = min_t(int, qcount, OTX2_QOS_MAX_LEAF_NODES); - netdev = alloc_etherdev_mqs(sizeof(*pf), qcount, qcount); + netdev = alloc_etherdev_mqs(sizeof(*pf), qcount + qos_txqs, qcount); if (!netdev) { err = -ENOMEM; goto err_release_regions; @@ -2760,7 +2827,7 @@ static int otx2_probe(struct pci_dev *pdev, const struct pci_device_id *id) hw->pdev = pdev; hw->rx_queues = qcount; hw->tx_queues = qcount; - hw->tot_tx_queues = qcount; + hw->non_qos_queues = qcount; hw->max_queues = qcount; hw->rbuf_len = OTX2_DEFAULT_RBUF_LEN; /* Use CQE of 128 byte descriptor size by default */ @@ -2929,6 +2996,8 @@ static int otx2_probe(struct pci_dev *pdev, const struct pci_device_id *id) goto err_pf_sriov_init; #endif + otx2_qos_init(pf, qos_txqs); + return 0; err_pf_sriov_init: @@ -3104,6 +3173,7 @@ static void otx2_remove(struct pci_dev *pdev) otx2_ptp_destroy(pf); otx2_mcam_flow_del(pf); otx2_shutdown_tc(pf); + otx2_shutdown_qos(pf); otx2_detach_resources(&pf->mbox); if (pf->hw.lmt_info) free_percpu(pf->hw.lmt_info); diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_reg.h b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_reg.h index 1b967eaf948ba927a7f585d75f5b5d614158e781..45a32e4b49d1cb458e41e8628aea68b0b990a610 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_reg.h +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_reg.h @@ -145,12 +145,25 @@ #define NIX_AF_TL1X_TOPOLOGY(a) (0xC80 | (a) << 16) #define NIX_AF_TL2X_PARENT(a) (0xE88 | (a) << 16) #define NIX_AF_TL2X_SCHEDULE(a) (0xE00 | (a) << 16) +#define NIX_AF_TL2X_TOPOLOGY(a) (0xE80 | (a) << 16) +#define NIX_AF_TL2X_CIR(a) (0xE20 | (a) << 16) +#define NIX_AF_TL2X_PIR(a) (0xE30 | (a) << 16) #define NIX_AF_TL3X_PARENT(a) (0x1088 | (a) << 16) #define NIX_AF_TL3X_SCHEDULE(a) (0x1000 | (a) << 16) +#define NIX_AF_TL3X_SHAPE(a) (0x1010 | (a) << 16) +#define NIX_AF_TL3X_CIR(a) (0x1020 | (a) << 16) +#define NIX_AF_TL3X_PIR(a) (0x1030 | (a) << 16) +#define NIX_AF_TL3X_TOPOLOGY(a) (0x1080 | (a) << 16) #define NIX_AF_TL4X_PARENT(a) (0x1288 | (a) << 16) #define NIX_AF_TL4X_SCHEDULE(a) (0x1200 | (a) << 16) +#define NIX_AF_TL4X_SHAPE(a) (0x1210 | (a) << 16) +#define NIX_AF_TL4X_CIR(a) (0x1220 | (a) << 16) #define NIX_AF_TL4X_PIR(a) (0x1230 | (a) << 16) +#define NIX_AF_TL4X_TOPOLOGY(a) (0x1280 | (a) << 16) #define NIX_AF_MDQX_SCHEDULE(a) (0x1400 | (a) << 16) +#define NIX_AF_MDQX_SHAPE(a) (0x1410 | (a) << 16) +#define NIX_AF_MDQX_CIR(a) (0x1420 | (a) << 16) +#define NIX_AF_MDQX_PIR(a) (0x1430 | (a) << 16) #define NIX_AF_MDQX_PARENT(a) (0x1480 | (a) << 16) #define NIX_AF_TL3_TL2X_LINKX_CFG(a, b) (0x1700 | (a) << 16 | (b) << 3) diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c index 8392f63e433fc4f58bdcf32df2941f2343c463d1..5e56b6c3e60ad825efdbc70fef3dedc606f474d3 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c @@ -19,25 +19,11 @@ #include "cn10k.h" #include "otx2_common.h" - -/* Egress rate limiting definitions */ -#define MAX_BURST_EXPONENT 0x0FULL -#define MAX_BURST_MANTISSA 0xFFULL -#define MAX_BURST_SIZE 130816ULL -#define MAX_RATE_DIVIDER_EXPONENT 12ULL -#define MAX_RATE_EXPONENT 0x0FULL -#define MAX_RATE_MANTISSA 0xFFULL +#include "qos.h" #define CN10K_MAX_BURST_MANTISSA 0x7FFFULL #define CN10K_MAX_BURST_SIZE 8453888ULL -/* Bitfields in NIX_TLX_PIR register */ -#define TLX_RATE_MANTISSA GENMASK_ULL(8, 1) -#define TLX_RATE_EXPONENT GENMASK_ULL(12, 9) -#define TLX_RATE_DIVIDER_EXPONENT GENMASK_ULL(16, 13) -#define TLX_BURST_MANTISSA GENMASK_ULL(36, 29) -#define TLX_BURST_EXPONENT GENMASK_ULL(40, 37) - #define CN10K_TLX_BURST_MANTISSA GENMASK_ULL(43, 29) #define CN10K_TLX_BURST_EXPONENT GENMASK_ULL(47, 44) @@ -147,8 +133,8 @@ static void otx2_get_egress_rate_cfg(u64 maxrate, u32 *exp, } } -static u64 otx2_get_txschq_rate_regval(struct otx2_nic *nic, - u64 maxrate, u32 burst) +u64 otx2_get_txschq_rate_regval(struct otx2_nic *nic, + u64 maxrate, u32 burst) { u32 burst_exp, burst_mantissa; u32 exp, mantissa, div_exp; @@ -264,7 +250,6 @@ static int otx2_tc_egress_matchall_install(struct otx2_nic *nic, struct netlink_ext_ack *extack = cls->common.extack; struct flow_action *actions = &cls->rule->action; struct flow_action_entry *entry; - u64 rate; int err; err = otx2_tc_validate_flow(nic, actions, extack); @@ -288,10 +273,8 @@ static int otx2_tc_egress_matchall_install(struct otx2_nic *nic, NL_SET_ERR_MSG_MOD(extack, "QoS offload not support packets per second"); return -EOPNOTSUPP; } - /* Convert bytes per second to Mbps */ - rate = entry->police.rate_bytes_ps * 8; - rate = max_t(u64, rate / 1000000, 1); - err = otx2_set_matchall_egress_rate(nic, entry->police.burst, rate); + err = otx2_set_matchall_egress_rate(nic, entry->police.burst, + otx2_convert_rate(entry->police.rate_bytes_ps)); if (err) return err; nic->flags |= OTX2_FLAG_TC_MATCHALL_EGRESS_ENABLED; @@ -413,8 +396,12 @@ static int otx2_tc_parse_actions(struct otx2_nic *nic, return -EOPNOTSUPP; } req->vf = priv->pcifunc & RVU_PFVF_FUNC_MASK; - req->op = NIX_RX_ACTION_DEFAULT; - return 0; + + /* if op is already set; avoid overwriting the same */ + if (!req->op) + req->op = NIX_RX_ACTION_DEFAULT; + break; + case FLOW_ACTION_VLAN_POP: req->vtag0_valid = true; /* use RX_VTAG_TYPE7 which is initialized to strip vlan tag */ @@ -450,6 +437,12 @@ static int otx2_tc_parse_actions(struct otx2_nic *nic, case FLOW_ACTION_MARK: mark = act->mark; break; + + case FLOW_ACTION_RX_QUEUE_MAPPING: + req->op = NIX_RX_ACTIONOP_UCAST; + req->index = act->rx_queue; + break; + default: return -EOPNOTSUPP; } @@ -604,6 +597,21 @@ static int otx2_tc_prepare_flow(struct otx2_nic *nic, struct otx2_tc_flow *node, return -EOPNOTSUPP; } + if (!match.mask->vlan_id) { + struct flow_action_entry *act; + int i; + + flow_action_for_each(i, act, &rule->action) { + if (act->id == FLOW_ACTION_DROP) { + netdev_err(nic->netdev, + "vlan tpid 0x%x with vlan_id %d is not supported for DROP rule.\n", + ntohs(match.key->vlan_tpid), + match.key->vlan_id); + return -EOPNOTSUPP; + } + } + } + if (match.mask->vlan_id || match.mask->vlan_dei || match.mask->vlan_priority) { @@ -1127,6 +1135,8 @@ int otx2_setup_tc(struct net_device *netdev, enum tc_setup_type type, switch (type) { case TC_SETUP_BLOCK: return otx2_setup_tc_block(netdev, type_data); + case TC_SETUP_QDISC_HTB: + return otx2_setup_tc_htb(netdev, type_data); default: return -EOPNOTSUPP; } diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c index 7af223b0a37f51e129c5d28d9d500262a4c0b620..e369baf115301df919a2b315e3709d82f931e4a0 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c @@ -217,9 +217,6 @@ static bool otx2_skb_add_frag(struct otx2_nic *pfvf, struct sk_buff *skb, skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, page, va - page_address(page) + off, len - off, pfvf->rbsize); - - otx2_dma_unmap_page(pfvf, iova - OTX2_HEAD_ROOM, - pfvf->rbsize, DMA_FROM_DEVICE); return true; } @@ -382,6 +379,8 @@ static void otx2_rcv_pkt_handler(struct otx2_nic *pfvf, if (pfvf->netdev->features & NETIF_F_RXCSUM) skb->ip_summed = CHECKSUM_UNNECESSARY; + skb_mark_for_recycle(skb); + napi_gro_frags(napi); } @@ -464,12 +463,13 @@ static int otx2_tx_napi_handler(struct otx2_nic *pfvf, break; } - if (cq->cq_type == CQ_XDP) { + qidx = cq->cq_idx - pfvf->hw.rx_queues; + + if (cq->cq_type == CQ_XDP) otx2_xdp_snd_pkt_handler(pfvf, sq, cqe); - } else { - otx2_snd_pkt_handler(pfvf, cq, sq, cqe, budget, - &tx_pkts, &tx_bytes); - } + else + otx2_snd_pkt_handler(pfvf, cq, &pfvf->qset.sq[qidx], + cqe, budget, &tx_pkts, &tx_bytes); cqe->hdr.cqe_type = NIX_XQE_TYPE_INVALID; processed_cqe++; @@ -486,7 +486,11 @@ static int otx2_tx_napi_handler(struct otx2_nic *pfvf, if (likely(tx_pkts)) { struct netdev_queue *txq; - txq = netdev_get_tx_queue(pfvf->netdev, cq->cint_idx); + qidx = cq->cq_idx - pfvf->hw.rx_queues; + + if (qidx >= pfvf->hw.tx_queues) + qidx -= pfvf->hw.xdp_queues; + txq = netdev_get_tx_queue(pfvf->netdev, qidx); netdev_tx_completed_queue(txq, tx_pkts, tx_bytes); /* Check if queue was stopped earlier due to ring full */ smp_mb(); @@ -734,7 +738,8 @@ static void otx2_sqe_add_hdr(struct otx2_nic *pfvf, struct otx2_snd_queue *sq, sqe_hdr->aura = sq->aura_id; /* Post a CQE Tx after pkt transmission */ sqe_hdr->pnc = 1; - sqe_hdr->sq = qidx; + sqe_hdr->sq = (qidx >= pfvf->hw.tx_queues) ? + qidx + pfvf->hw.xdp_queues : qidx; } sqe_hdr->total = skb->len; /* Set SQE identifier which will be used later for freeing SKB */ @@ -1178,11 +1183,13 @@ bool otx2_sq_append_skb(struct net_device *netdev, struct otx2_snd_queue *sq, } EXPORT_SYMBOL(otx2_sq_append_skb); -void otx2_cleanup_rx_cqes(struct otx2_nic *pfvf, struct otx2_cq_queue *cq) +void otx2_cleanup_rx_cqes(struct otx2_nic *pfvf, struct otx2_cq_queue *cq, int qidx) { struct nix_cqe_rx_s *cqe; + struct otx2_pool *pool; int processed_cqe = 0; - u64 iova, pa; + u16 pool_id; + u64 iova; if (pfvf->xdp_prog) xdp_rxq_info_unreg(&cq->xdp_rxq); @@ -1190,6 +1197,9 @@ void otx2_cleanup_rx_cqes(struct otx2_nic *pfvf, struct otx2_cq_queue *cq) if (otx2_nix_cq_op_status(pfvf, cq) || !cq->pend_cqe) return; + pool_id = otx2_get_pool_idx(pfvf, AURA_NIX_RQ, qidx); + pool = &pfvf->qset.pool[pool_id]; + while (cq->pend_cqe) { cqe = (struct nix_cqe_rx_s *)otx2_get_next_cqe(cq); processed_cqe++; @@ -1202,9 +1212,8 @@ void otx2_cleanup_rx_cqes(struct otx2_nic *pfvf, struct otx2_cq_queue *cq) continue; } iova = cqe->sg.seg_addr - OTX2_HEAD_ROOM; - pa = otx2_iova_to_phys(pfvf->iommu_domain, iova); - otx2_dma_unmap_page(pfvf, iova, pfvf->rbsize, DMA_FROM_DEVICE); - put_page(virt_to_page(phys_to_virt(pa))); + + otx2_free_bufs(pfvf, pool, iova, pfvf->rbsize); } /* Free CQEs to HW */ @@ -1219,8 +1228,10 @@ void otx2_cleanup_tx_cqes(struct otx2_nic *pfvf, struct otx2_cq_queue *cq) struct nix_cqe_tx_s *cqe; int processed_cqe = 0; struct sg_list *sg; + int qidx; - sq = &pfvf->qset.sq[cq->cint_idx]; + qidx = cq->cq_idx - pfvf->hw.rx_queues; + sq = &pfvf->qset.sq[qidx]; if (otx2_nix_cq_op_status(pfvf, cq) || !cq->pend_cqe) return; diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.h b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.h index 93cac2c2664c204d72f428c2661f89ab61a124c4..b5d689eeff80b8d331c9509ebf9310b02d3256fa 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.h +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.h @@ -102,7 +102,8 @@ enum cq_type { CQ_RX, CQ_TX, CQ_XDP, - CQS_PER_CINT = 3, /* RQ + SQ + XDP */ + CQ_QOS, + CQS_PER_CINT = 4, /* RQ + SQ + XDP + QOS_SQ */ }; struct otx2_cq_poll { @@ -117,6 +118,7 @@ struct otx2_cq_poll { struct otx2_pool { struct qmem *stack; struct qmem *fc_addr; + struct page_pool *page_pool; u16 rbsize; }; diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c index 53366dbfbf27c3a63e8bfda0531e86a2e711389c..35e06048356f4d545298b4bfc34ae848168734f1 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c @@ -70,10 +70,6 @@ static void otx2vf_process_vfaf_mbox_msg(struct otx2_nic *vf, case MBOX_MSG_NIX_LF_ALLOC: mbox_handler_nix_lf_alloc(vf, (struct nix_lf_alloc_rsp *)msg); break; - case MBOX_MSG_NIX_TXSCH_ALLOC: - mbox_handler_nix_txsch_alloc(vf, - (struct nix_txsch_alloc_rsp *)msg); - break; case MBOX_MSG_NIX_BP_ENABLE: mbox_handler_nix_bp_enable(vf, (struct nix_bp_cfg_rsp *)msg); break; @@ -297,9 +293,8 @@ static int otx2vf_vfaf_mbox_init(struct otx2_nic *vf) int err; mbox->pfvf = vf; - vf->mbox_wq = alloc_workqueue("otx2_vfaf_mailbox", - WQ_UNBOUND | WQ_HIGHPRI | - WQ_MEM_RECLAIM, 1); + vf->mbox_wq = alloc_ordered_workqueue("otx2_vfaf_mailbox", + WQ_HIGHPRI | WQ_MEM_RECLAIM); if (!vf->mbox_wq) return -ENOMEM; @@ -479,6 +474,7 @@ static const struct net_device_ops otx2vf_netdev_ops = { .ndo_open = otx2vf_open, .ndo_stop = otx2vf_stop, .ndo_start_xmit = otx2vf_xmit, + .ndo_select_queue = otx2_select_queue, .ndo_set_rx_mode = otx2vf_set_rx_mode, .ndo_set_mac_address = otx2_set_mac_address, .ndo_change_mtu = otx2vf_change_mtu, @@ -524,10 +520,10 @@ static int otx2vf_probe(struct pci_dev *pdev, const struct pci_device_id *id) { int num_vec = pci_msix_vec_count(pdev); struct device *dev = &pdev->dev; + int err, qcount, qos_txqs; struct net_device *netdev; struct otx2_nic *vf; struct otx2_hw *hw; - int err, qcount; err = pcim_enable_device(pdev); if (err) { @@ -550,7 +546,8 @@ static int otx2vf_probe(struct pci_dev *pdev, const struct pci_device_id *id) pci_set_master(pdev); qcount = num_online_cpus(); - netdev = alloc_etherdev_mqs(sizeof(*vf), qcount, qcount); + qos_txqs = min_t(int, qcount, OTX2_QOS_MAX_LEAF_NODES); + netdev = alloc_etherdev_mqs(sizeof(*vf), qcount + qos_txqs, qcount); if (!netdev) { err = -ENOMEM; goto err_release_regions; @@ -570,7 +567,7 @@ static int otx2vf_probe(struct pci_dev *pdev, const struct pci_device_id *id) hw->rx_queues = qcount; hw->tx_queues = qcount; hw->max_queues = qcount; - hw->tot_tx_queues = qcount; + hw->non_qos_queues = qcount; hw->rbuf_len = OTX2_DEFAULT_RBUF_LEN; /* Use CQE of 128 byte descriptor size by default */ hw->xqe_size = 128; @@ -699,6 +696,7 @@ static int otx2vf_probe(struct pci_dev *pdev, const struct pci_device_id *id) if (err) goto err_shutdown_tc; #endif + otx2_qos_init(vf, qos_txqs); return 0; @@ -761,6 +759,7 @@ static void otx2vf_remove(struct pci_dev *pdev) otx2_ptp_destroy(vf); otx2_mcam_flow_del(vf); otx2_shutdown_tc(vf); + otx2_shutdown_qos(vf); otx2vf_disable_mbox_intr(vf); otx2_detach_resources(&vf->mbox); free_percpu(vf->hw.lmt_info); diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/qos.c b/drivers/net/ethernet/marvell/octeontx2/nic/qos.c new file mode 100644 index 0000000000000000000000000000000000000000..d3a76c5ccda8b79cf0bec8143f9daf056ec0ec56 --- /dev/null +++ b/drivers/net/ethernet/marvell/octeontx2/nic/qos.c @@ -0,0 +1,1363 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Marvell RVU Ethernet driver + * + * Copyright (C) 2023 Marvell. + * + */ +#include +#include +#include +#include + +#include "otx2_common.h" +#include "cn10k.h" +#include "qos.h" + +#define OTX2_QOS_QID_INNER 0xFFFFU +#define OTX2_QOS_QID_NONE 0xFFFEU +#define OTX2_QOS_ROOT_CLASSID 0xFFFFFFFF +#define OTX2_QOS_CLASS_NONE 0 +#define OTX2_QOS_DEFAULT_PRIO 0xF +#define OTX2_QOS_INVALID_SQ 0xFFFF + +static void otx2_qos_update_tx_netdev_queues(struct otx2_nic *pfvf) +{ + struct otx2_hw *hw = &pfvf->hw; + int tx_queues, qos_txqs, err; + + qos_txqs = bitmap_weight(pfvf->qos.qos_sq_bmap, + OTX2_QOS_MAX_LEAF_NODES); + + tx_queues = hw->tx_queues + qos_txqs; + + err = netif_set_real_num_tx_queues(pfvf->netdev, tx_queues); + if (err) { + netdev_err(pfvf->netdev, + "Failed to set no of Tx queues: %d\n", tx_queues); + return; + } +} + +static void otx2_qos_get_regaddr(struct otx2_qos_node *node, + struct nix_txschq_config *cfg, + int index) +{ + if (node->level == NIX_TXSCH_LVL_SMQ) { + cfg->reg[index++] = NIX_AF_MDQX_PARENT(node->schq); + cfg->reg[index++] = NIX_AF_MDQX_SCHEDULE(node->schq); + cfg->reg[index++] = NIX_AF_MDQX_PIR(node->schq); + cfg->reg[index] = NIX_AF_MDQX_CIR(node->schq); + } else if (node->level == NIX_TXSCH_LVL_TL4) { + cfg->reg[index++] = NIX_AF_TL4X_PARENT(node->schq); + cfg->reg[index++] = NIX_AF_TL4X_SCHEDULE(node->schq); + cfg->reg[index++] = NIX_AF_TL4X_PIR(node->schq); + cfg->reg[index] = NIX_AF_TL4X_CIR(node->schq); + } else if (node->level == NIX_TXSCH_LVL_TL3) { + cfg->reg[index++] = NIX_AF_TL3X_PARENT(node->schq); + cfg->reg[index++] = NIX_AF_TL3X_SCHEDULE(node->schq); + cfg->reg[index++] = NIX_AF_TL3X_PIR(node->schq); + cfg->reg[index] = NIX_AF_TL3X_CIR(node->schq); + } else if (node->level == NIX_TXSCH_LVL_TL2) { + cfg->reg[index++] = NIX_AF_TL2X_PARENT(node->schq); + cfg->reg[index++] = NIX_AF_TL2X_SCHEDULE(node->schq); + cfg->reg[index++] = NIX_AF_TL2X_PIR(node->schq); + cfg->reg[index] = NIX_AF_TL2X_CIR(node->schq); + } +} + +static void otx2_config_sched_shaping(struct otx2_nic *pfvf, + struct otx2_qos_node *node, + struct nix_txschq_config *cfg, + int *num_regs) +{ + u64 maxrate; + + otx2_qos_get_regaddr(node, cfg, *num_regs); + + /* configure parent txschq */ + cfg->regval[*num_regs] = node->parent->schq << 16; + (*num_regs)++; + + /* configure prio/quantum */ + if (node->qid == OTX2_QOS_QID_NONE) { + cfg->regval[*num_regs] = node->prio << 24 | + mtu_to_dwrr_weight(pfvf, pfvf->tx_max_pktlen); + (*num_regs)++; + return; + } + + /* configure priority */ + cfg->regval[*num_regs] = (node->schq - node->parent->prio_anchor) << 24; + (*num_regs)++; + + /* configure PIR */ + maxrate = (node->rate > node->ceil) ? node->rate : node->ceil; + + cfg->regval[*num_regs] = + otx2_get_txschq_rate_regval(pfvf, maxrate, 65536); + (*num_regs)++; + + /* Don't configure CIR when both CIR+PIR not supported + * On 96xx, CIR + PIR + RED_ALGO=STALL causes deadlock + */ + if (!test_bit(QOS_CIR_PIR_SUPPORT, &pfvf->hw.cap_flag)) + return; + + cfg->regval[*num_regs] = + otx2_get_txschq_rate_regval(pfvf, node->rate, 65536); + (*num_regs)++; +} + +static void __otx2_qos_txschq_cfg(struct otx2_nic *pfvf, + struct otx2_qos_node *node, + struct nix_txschq_config *cfg) +{ + struct otx2_hw *hw = &pfvf->hw; + int num_regs = 0; + u8 level; + + level = node->level; + + /* program txschq registers */ + if (level == NIX_TXSCH_LVL_SMQ) { + cfg->reg[num_regs] = NIX_AF_SMQX_CFG(node->schq); + cfg->regval[num_regs] = ((u64)pfvf->tx_max_pktlen << 8) | + OTX2_MIN_MTU; + cfg->regval[num_regs] |= (0x20ULL << 51) | (0x80ULL << 39) | + (0x2ULL << 36); + num_regs++; + + otx2_config_sched_shaping(pfvf, node, cfg, &num_regs); + + } else if (level == NIX_TXSCH_LVL_TL4) { + otx2_config_sched_shaping(pfvf, node, cfg, &num_regs); + } else if (level == NIX_TXSCH_LVL_TL3) { + /* configure link cfg */ + if (level == pfvf->qos.link_cfg_lvl) { + cfg->reg[num_regs] = NIX_AF_TL3_TL2X_LINKX_CFG(node->schq, hw->tx_link); + cfg->regval[num_regs] = BIT_ULL(13) | BIT_ULL(12); + num_regs++; + } + + otx2_config_sched_shaping(pfvf, node, cfg, &num_regs); + } else if (level == NIX_TXSCH_LVL_TL2) { + /* configure link cfg */ + if (level == pfvf->qos.link_cfg_lvl) { + cfg->reg[num_regs] = NIX_AF_TL3_TL2X_LINKX_CFG(node->schq, hw->tx_link); + cfg->regval[num_regs] = BIT_ULL(13) | BIT_ULL(12); + num_regs++; + } + + /* check if node is root */ + if (node->qid == OTX2_QOS_QID_INNER && !node->parent) { + cfg->reg[num_regs] = NIX_AF_TL2X_SCHEDULE(node->schq); + cfg->regval[num_regs] = TXSCH_TL1_DFLT_RR_PRIO << 24 | + mtu_to_dwrr_weight(pfvf, + pfvf->tx_max_pktlen); + num_regs++; + goto txschq_cfg_out; + } + + otx2_config_sched_shaping(pfvf, node, cfg, &num_regs); + } + +txschq_cfg_out: + cfg->num_regs = num_regs; +} + +static int otx2_qos_txschq_set_parent_topology(struct otx2_nic *pfvf, + struct otx2_qos_node *parent) +{ + struct mbox *mbox = &pfvf->mbox; + struct nix_txschq_config *cfg; + int rc; + + if (parent->level == NIX_TXSCH_LVL_MDQ) + return 0; + + mutex_lock(&mbox->lock); + + cfg = otx2_mbox_alloc_msg_nix_txschq_cfg(&pfvf->mbox); + if (!cfg) { + mutex_unlock(&mbox->lock); + return -ENOMEM; + } + + cfg->lvl = parent->level; + + if (parent->level == NIX_TXSCH_LVL_TL4) + cfg->reg[0] = NIX_AF_TL4X_TOPOLOGY(parent->schq); + else if (parent->level == NIX_TXSCH_LVL_TL3) + cfg->reg[0] = NIX_AF_TL3X_TOPOLOGY(parent->schq); + else if (parent->level == NIX_TXSCH_LVL_TL2) + cfg->reg[0] = NIX_AF_TL2X_TOPOLOGY(parent->schq); + else if (parent->level == NIX_TXSCH_LVL_TL1) + cfg->reg[0] = NIX_AF_TL1X_TOPOLOGY(parent->schq); + + cfg->regval[0] = (u64)parent->prio_anchor << 32; + if (parent->level == NIX_TXSCH_LVL_TL1) + cfg->regval[0] |= (u64)TXSCH_TL1_DFLT_RR_PRIO << 1; + + cfg->num_regs++; + + rc = otx2_sync_mbox_msg(&pfvf->mbox); + + mutex_unlock(&mbox->lock); + + return rc; +} + +static void otx2_qos_free_hw_node_schq(struct otx2_nic *pfvf, + struct otx2_qos_node *parent) +{ + struct otx2_qos_node *node; + + list_for_each_entry_reverse(node, &parent->child_schq_list, list) + otx2_txschq_free_one(pfvf, node->level, node->schq); +} + +static void otx2_qos_free_hw_node(struct otx2_nic *pfvf, + struct otx2_qos_node *parent) +{ + struct otx2_qos_node *node, *tmp; + + list_for_each_entry_safe(node, tmp, &parent->child_list, list) { + otx2_qos_free_hw_node(pfvf, node); + otx2_qos_free_hw_node_schq(pfvf, node); + otx2_txschq_free_one(pfvf, node->level, node->schq); + } +} + +static void otx2_qos_free_hw_cfg(struct otx2_nic *pfvf, + struct otx2_qos_node *node) +{ + mutex_lock(&pfvf->qos.qos_lock); + + /* free child node hw mappings */ + otx2_qos_free_hw_node(pfvf, node); + otx2_qos_free_hw_node_schq(pfvf, node); + + /* free node hw mappings */ + otx2_txschq_free_one(pfvf, node->level, node->schq); + + mutex_unlock(&pfvf->qos.qos_lock); +} + +static void otx2_qos_sw_node_delete(struct otx2_nic *pfvf, + struct otx2_qos_node *node) +{ + hash_del_rcu(&node->hlist); + + if (node->qid != OTX2_QOS_QID_INNER && node->qid != OTX2_QOS_QID_NONE) { + __clear_bit(node->qid, pfvf->qos.qos_sq_bmap); + otx2_qos_update_tx_netdev_queues(pfvf); + } + + list_del(&node->list); + kfree(node); +} + +static void otx2_qos_free_sw_node_schq(struct otx2_nic *pfvf, + struct otx2_qos_node *parent) +{ + struct otx2_qos_node *node, *tmp; + + list_for_each_entry_safe(node, tmp, &parent->child_schq_list, list) { + list_del(&node->list); + kfree(node); + } +} + +static void __otx2_qos_free_sw_node(struct otx2_nic *pfvf, + struct otx2_qos_node *parent) +{ + struct otx2_qos_node *node, *tmp; + + list_for_each_entry_safe(node, tmp, &parent->child_list, list) { + __otx2_qos_free_sw_node(pfvf, node); + otx2_qos_free_sw_node_schq(pfvf, node); + otx2_qos_sw_node_delete(pfvf, node); + } +} + +static void otx2_qos_free_sw_node(struct otx2_nic *pfvf, + struct otx2_qos_node *node) +{ + mutex_lock(&pfvf->qos.qos_lock); + + __otx2_qos_free_sw_node(pfvf, node); + otx2_qos_free_sw_node_schq(pfvf, node); + otx2_qos_sw_node_delete(pfvf, node); + + mutex_unlock(&pfvf->qos.qos_lock); +} + +static void otx2_qos_destroy_node(struct otx2_nic *pfvf, + struct otx2_qos_node *node) +{ + otx2_qos_free_hw_cfg(pfvf, node); + otx2_qos_free_sw_node(pfvf, node); +} + +static void otx2_qos_fill_cfg_schq(struct otx2_qos_node *parent, + struct otx2_qos_cfg *cfg) +{ + struct otx2_qos_node *node; + + list_for_each_entry(node, &parent->child_schq_list, list) + cfg->schq[node->level]++; +} + +static void otx2_qos_fill_cfg_tl(struct otx2_qos_node *parent, + struct otx2_qos_cfg *cfg) +{ + struct otx2_qos_node *node; + + list_for_each_entry(node, &parent->child_list, list) { + otx2_qos_fill_cfg_tl(node, cfg); + cfg->schq_contig[node->level]++; + otx2_qos_fill_cfg_schq(node, cfg); + } +} + +static void otx2_qos_prepare_txschq_cfg(struct otx2_nic *pfvf, + struct otx2_qos_node *parent, + struct otx2_qos_cfg *cfg) +{ + mutex_lock(&pfvf->qos.qos_lock); + otx2_qos_fill_cfg_tl(parent, cfg); + mutex_unlock(&pfvf->qos.qos_lock); +} + +static void otx2_qos_read_txschq_cfg_schq(struct otx2_qos_node *parent, + struct otx2_qos_cfg *cfg) +{ + struct otx2_qos_node *node; + int cnt; + + list_for_each_entry(node, &parent->child_schq_list, list) { + cnt = cfg->dwrr_node_pos[node->level]; + cfg->schq_list[node->level][cnt] = node->schq; + cfg->schq[node->level]++; + cfg->dwrr_node_pos[node->level]++; + } +} + +static void otx2_qos_read_txschq_cfg_tl(struct otx2_qos_node *parent, + struct otx2_qos_cfg *cfg) +{ + struct otx2_qos_node *node; + int cnt; + + list_for_each_entry(node, &parent->child_list, list) { + otx2_qos_read_txschq_cfg_tl(node, cfg); + cnt = cfg->static_node_pos[node->level]; + cfg->schq_contig_list[node->level][cnt] = node->schq; + cfg->schq_contig[node->level]++; + cfg->static_node_pos[node->level]++; + otx2_qos_read_txschq_cfg_schq(node, cfg); + } +} + +static void otx2_qos_read_txschq_cfg(struct otx2_nic *pfvf, + struct otx2_qos_node *node, + struct otx2_qos_cfg *cfg) +{ + mutex_lock(&pfvf->qos.qos_lock); + otx2_qos_read_txschq_cfg_tl(node, cfg); + mutex_unlock(&pfvf->qos.qos_lock); +} + +static struct otx2_qos_node * +otx2_qos_alloc_root(struct otx2_nic *pfvf) +{ + struct otx2_qos_node *node; + + node = kzalloc(sizeof(*node), GFP_KERNEL); + if (!node) + return ERR_PTR(-ENOMEM); + + node->parent = NULL; + if (!is_otx2_vf(pfvf->pcifunc)) + node->level = NIX_TXSCH_LVL_TL1; + else + node->level = NIX_TXSCH_LVL_TL2; + + WRITE_ONCE(node->qid, OTX2_QOS_QID_INNER); + node->classid = OTX2_QOS_ROOT_CLASSID; + + hash_add_rcu(pfvf->qos.qos_hlist, &node->hlist, node->classid); + list_add_tail(&node->list, &pfvf->qos.qos_tree); + INIT_LIST_HEAD(&node->child_list); + INIT_LIST_HEAD(&node->child_schq_list); + + return node; +} + +static int otx2_qos_add_child_node(struct otx2_qos_node *parent, + struct otx2_qos_node *node) +{ + struct list_head *head = &parent->child_list; + struct otx2_qos_node *tmp_node; + struct list_head *tmp; + + for (tmp = head->next; tmp != head; tmp = tmp->next) { + tmp_node = list_entry(tmp, struct otx2_qos_node, list); + if (tmp_node->prio == node->prio) + return -EEXIST; + if (tmp_node->prio > node->prio) { + list_add_tail(&node->list, tmp); + return 0; + } + } + + list_add_tail(&node->list, head); + return 0; +} + +static int otx2_qos_alloc_txschq_node(struct otx2_nic *pfvf, + struct otx2_qos_node *node) +{ + struct otx2_qos_node *txschq_node, *parent, *tmp; + int lvl; + + parent = node; + for (lvl = node->level - 1; lvl >= NIX_TXSCH_LVL_MDQ; lvl--) { + txschq_node = kzalloc(sizeof(*txschq_node), GFP_KERNEL); + if (!txschq_node) + goto err_out; + + txschq_node->parent = parent; + txschq_node->level = lvl; + txschq_node->classid = OTX2_QOS_CLASS_NONE; + WRITE_ONCE(txschq_node->qid, OTX2_QOS_QID_NONE); + txschq_node->rate = 0; + txschq_node->ceil = 0; + txschq_node->prio = 0; + + mutex_lock(&pfvf->qos.qos_lock); + list_add_tail(&txschq_node->list, &node->child_schq_list); + mutex_unlock(&pfvf->qos.qos_lock); + + INIT_LIST_HEAD(&txschq_node->child_list); + INIT_LIST_HEAD(&txschq_node->child_schq_list); + parent = txschq_node; + } + + return 0; + +err_out: + list_for_each_entry_safe(txschq_node, tmp, &node->child_schq_list, + list) { + list_del(&txschq_node->list); + kfree(txschq_node); + } + return -ENOMEM; +} + +static struct otx2_qos_node * +otx2_qos_sw_create_leaf_node(struct otx2_nic *pfvf, + struct otx2_qos_node *parent, + u16 classid, u32 prio, u64 rate, u64 ceil, + u16 qid) +{ + struct otx2_qos_node *node; + int err; + + node = kzalloc(sizeof(*node), GFP_KERNEL); + if (!node) + return ERR_PTR(-ENOMEM); + + node->parent = parent; + node->level = parent->level - 1; + node->classid = classid; + WRITE_ONCE(node->qid, qid); + + node->rate = otx2_convert_rate(rate); + node->ceil = otx2_convert_rate(ceil); + node->prio = prio; + + __set_bit(qid, pfvf->qos.qos_sq_bmap); + + hash_add_rcu(pfvf->qos.qos_hlist, &node->hlist, classid); + + mutex_lock(&pfvf->qos.qos_lock); + err = otx2_qos_add_child_node(parent, node); + if (err) { + mutex_unlock(&pfvf->qos.qos_lock); + return ERR_PTR(err); + } + mutex_unlock(&pfvf->qos.qos_lock); + + INIT_LIST_HEAD(&node->child_list); + INIT_LIST_HEAD(&node->child_schq_list); + + err = otx2_qos_alloc_txschq_node(pfvf, node); + if (err) { + otx2_qos_sw_node_delete(pfvf, node); + return ERR_PTR(-ENOMEM); + } + + return node; +} + +static struct otx2_qos_node * +otx2_sw_node_find(struct otx2_nic *pfvf, u32 classid) +{ + struct otx2_qos_node *node = NULL; + + hash_for_each_possible(pfvf->qos.qos_hlist, node, hlist, classid) { + if (node->classid == classid) + break; + } + + return node; +} + +static struct otx2_qos_node * +otx2_sw_node_find_rcu(struct otx2_nic *pfvf, u32 classid) +{ + struct otx2_qos_node *node = NULL; + + hash_for_each_possible_rcu(pfvf->qos.qos_hlist, node, hlist, classid) { + if (node->classid == classid) + break; + } + + return node; +} + +int otx2_get_txq_by_classid(struct otx2_nic *pfvf, u16 classid) +{ + struct otx2_qos_node *node; + u16 qid; + int res; + + node = otx2_sw_node_find_rcu(pfvf, classid); + if (!node) { + res = -ENOENT; + goto out; + } + qid = READ_ONCE(node->qid); + if (qid == OTX2_QOS_QID_INNER) { + res = -EINVAL; + goto out; + } + res = pfvf->hw.tx_queues + qid; +out: + return res; +} + +static int +otx2_qos_txschq_config(struct otx2_nic *pfvf, struct otx2_qos_node *node) +{ + struct mbox *mbox = &pfvf->mbox; + struct nix_txschq_config *req; + int rc; + + mutex_lock(&mbox->lock); + + req = otx2_mbox_alloc_msg_nix_txschq_cfg(&pfvf->mbox); + if (!req) { + mutex_unlock(&mbox->lock); + return -ENOMEM; + } + + req->lvl = node->level; + __otx2_qos_txschq_cfg(pfvf, node, req); + + rc = otx2_sync_mbox_msg(&pfvf->mbox); + + mutex_unlock(&mbox->lock); + + return rc; +} + +static int otx2_qos_txschq_alloc(struct otx2_nic *pfvf, + struct otx2_qos_cfg *cfg) +{ + struct nix_txsch_alloc_req *req; + struct nix_txsch_alloc_rsp *rsp; + struct mbox *mbox = &pfvf->mbox; + int lvl, rc, schq; + + mutex_lock(&mbox->lock); + req = otx2_mbox_alloc_msg_nix_txsch_alloc(&pfvf->mbox); + if (!req) { + mutex_unlock(&mbox->lock); + return -ENOMEM; + } + + for (lvl = 0; lvl < NIX_TXSCH_LVL_CNT; lvl++) { + req->schq[lvl] = cfg->schq[lvl]; + req->schq_contig[lvl] = cfg->schq_contig[lvl]; + } + + rc = otx2_sync_mbox_msg(&pfvf->mbox); + if (rc) { + mutex_unlock(&mbox->lock); + return rc; + } + + rsp = (struct nix_txsch_alloc_rsp *) + otx2_mbox_get_rsp(&pfvf->mbox.mbox, 0, &req->hdr); + + if (IS_ERR(rsp)) { + rc = PTR_ERR(rsp); + goto out; + } + + for (lvl = 0; lvl < NIX_TXSCH_LVL_CNT; lvl++) { + for (schq = 0; schq < rsp->schq_contig[lvl]; schq++) { + cfg->schq_contig_list[lvl][schq] = + rsp->schq_contig_list[lvl][schq]; + } + } + + for (lvl = 0; lvl < NIX_TXSCH_LVL_CNT; lvl++) { + for (schq = 0; schq < rsp->schq[lvl]; schq++) { + cfg->schq_list[lvl][schq] = + rsp->schq_list[lvl][schq]; + } + } + + pfvf->qos.link_cfg_lvl = rsp->link_cfg_lvl; + +out: + mutex_unlock(&mbox->lock); + return rc; +} + +static void otx2_qos_txschq_fill_cfg_schq(struct otx2_nic *pfvf, + struct otx2_qos_node *node, + struct otx2_qos_cfg *cfg) +{ + struct otx2_qos_node *tmp; + int cnt; + + list_for_each_entry(tmp, &node->child_schq_list, list) { + cnt = cfg->dwrr_node_pos[tmp->level]; + tmp->schq = cfg->schq_list[tmp->level][cnt]; + cfg->dwrr_node_pos[tmp->level]++; + } +} + +static void otx2_qos_txschq_fill_cfg_tl(struct otx2_nic *pfvf, + struct otx2_qos_node *node, + struct otx2_qos_cfg *cfg) +{ + struct otx2_qos_node *tmp; + int cnt; + + list_for_each_entry(tmp, &node->child_list, list) { + otx2_qos_txschq_fill_cfg_tl(pfvf, tmp, cfg); + cnt = cfg->static_node_pos[tmp->level]; + tmp->schq = cfg->schq_contig_list[tmp->level][cnt]; + if (cnt == 0) + node->prio_anchor = tmp->schq; + cfg->static_node_pos[tmp->level]++; + otx2_qos_txschq_fill_cfg_schq(pfvf, tmp, cfg); + } +} + +static void otx2_qos_txschq_fill_cfg(struct otx2_nic *pfvf, + struct otx2_qos_node *node, + struct otx2_qos_cfg *cfg) +{ + mutex_lock(&pfvf->qos.qos_lock); + otx2_qos_txschq_fill_cfg_tl(pfvf, node, cfg); + otx2_qos_txschq_fill_cfg_schq(pfvf, node, cfg); + mutex_unlock(&pfvf->qos.qos_lock); +} + +static int otx2_qos_txschq_push_cfg_schq(struct otx2_nic *pfvf, + struct otx2_qos_node *node, + struct otx2_qos_cfg *cfg) +{ + struct otx2_qos_node *tmp; + int ret; + + list_for_each_entry(tmp, &node->child_schq_list, list) { + ret = otx2_qos_txschq_config(pfvf, tmp); + if (ret) + return -EIO; + ret = otx2_qos_txschq_set_parent_topology(pfvf, tmp->parent); + if (ret) + return -EIO; + } + + return 0; +} + +static int otx2_qos_txschq_push_cfg_tl(struct otx2_nic *pfvf, + struct otx2_qos_node *node, + struct otx2_qos_cfg *cfg) +{ + struct otx2_qos_node *tmp; + int ret; + + list_for_each_entry(tmp, &node->child_list, list) { + ret = otx2_qos_txschq_push_cfg_tl(pfvf, tmp, cfg); + if (ret) + return -EIO; + ret = otx2_qos_txschq_config(pfvf, tmp); + if (ret) + return -EIO; + ret = otx2_qos_txschq_push_cfg_schq(pfvf, tmp, cfg); + if (ret) + return -EIO; + } + + ret = otx2_qos_txschq_set_parent_topology(pfvf, node); + if (ret) + return -EIO; + + return 0; +} + +static int otx2_qos_txschq_push_cfg(struct otx2_nic *pfvf, + struct otx2_qos_node *node, + struct otx2_qos_cfg *cfg) +{ + int ret; + + mutex_lock(&pfvf->qos.qos_lock); + ret = otx2_qos_txschq_push_cfg_tl(pfvf, node, cfg); + if (ret) + goto out; + ret = otx2_qos_txschq_push_cfg_schq(pfvf, node, cfg); +out: + mutex_unlock(&pfvf->qos.qos_lock); + return ret; +} + +static int otx2_qos_txschq_update_config(struct otx2_nic *pfvf, + struct otx2_qos_node *node, + struct otx2_qos_cfg *cfg) +{ + otx2_qos_txschq_fill_cfg(pfvf, node, cfg); + + return otx2_qos_txschq_push_cfg(pfvf, node, cfg); +} + +static int otx2_qos_txschq_update_root_cfg(struct otx2_nic *pfvf, + struct otx2_qos_node *root, + struct otx2_qos_cfg *cfg) +{ + root->schq = cfg->schq_list[root->level][0]; + return otx2_qos_txschq_config(pfvf, root); +} + +static void otx2_qos_free_cfg(struct otx2_nic *pfvf, struct otx2_qos_cfg *cfg) +{ + int lvl, idx, schq; + + for (lvl = 0; lvl < NIX_TXSCH_LVL_CNT; lvl++) { + for (idx = 0; idx < cfg->schq[lvl]; idx++) { + schq = cfg->schq_list[lvl][idx]; + otx2_txschq_free_one(pfvf, lvl, schq); + } + } + + for (lvl = 0; lvl < NIX_TXSCH_LVL_CNT; lvl++) { + for (idx = 0; idx < cfg->schq_contig[lvl]; idx++) { + schq = cfg->schq_contig_list[lvl][idx]; + otx2_txschq_free_one(pfvf, lvl, schq); + } + } +} + +static void otx2_qos_enadis_sq(struct otx2_nic *pfvf, + struct otx2_qos_node *node, + u16 qid) +{ + if (pfvf->qos.qid_to_sqmap[qid] != OTX2_QOS_INVALID_SQ) + otx2_qos_disable_sq(pfvf, qid); + + pfvf->qos.qid_to_sqmap[qid] = node->schq; + otx2_qos_enable_sq(pfvf, qid); +} + +static void otx2_qos_update_smq_schq(struct otx2_nic *pfvf, + struct otx2_qos_node *node, + bool action) +{ + struct otx2_qos_node *tmp; + + if (node->qid == OTX2_QOS_QID_INNER) + return; + + list_for_each_entry(tmp, &node->child_schq_list, list) { + if (tmp->level == NIX_TXSCH_LVL_MDQ) { + if (action == QOS_SMQ_FLUSH) + otx2_smq_flush(pfvf, tmp->schq); + else + otx2_qos_enadis_sq(pfvf, tmp, node->qid); + } + } +} + +static void __otx2_qos_update_smq(struct otx2_nic *pfvf, + struct otx2_qos_node *node, + bool action) +{ + struct otx2_qos_node *tmp; + + list_for_each_entry(tmp, &node->child_list, list) { + __otx2_qos_update_smq(pfvf, tmp, action); + if (tmp->qid == OTX2_QOS_QID_INNER) + continue; + if (tmp->level == NIX_TXSCH_LVL_MDQ) { + if (action == QOS_SMQ_FLUSH) + otx2_smq_flush(pfvf, tmp->schq); + else + otx2_qos_enadis_sq(pfvf, tmp, tmp->qid); + } else { + otx2_qos_update_smq_schq(pfvf, tmp, action); + } + } +} + +static void otx2_qos_update_smq(struct otx2_nic *pfvf, + struct otx2_qos_node *node, + bool action) +{ + mutex_lock(&pfvf->qos.qos_lock); + __otx2_qos_update_smq(pfvf, node, action); + otx2_qos_update_smq_schq(pfvf, node, action); + mutex_unlock(&pfvf->qos.qos_lock); +} + +static int otx2_qos_push_txschq_cfg(struct otx2_nic *pfvf, + struct otx2_qos_node *node, + struct otx2_qos_cfg *cfg) +{ + int ret; + + ret = otx2_qos_txschq_alloc(pfvf, cfg); + if (ret) + return -ENOSPC; + + if (!(pfvf->netdev->flags & IFF_UP)) { + otx2_qos_txschq_fill_cfg(pfvf, node, cfg); + return 0; + } + + ret = otx2_qos_txschq_update_config(pfvf, node, cfg); + if (ret) { + otx2_qos_free_cfg(pfvf, cfg); + return -EIO; + } + + otx2_qos_update_smq(pfvf, node, QOS_CFG_SQ); + + return 0; +} + +static int otx2_qos_update_tree(struct otx2_nic *pfvf, + struct otx2_qos_node *node, + struct otx2_qos_cfg *cfg) +{ + otx2_qos_prepare_txschq_cfg(pfvf, node->parent, cfg); + return otx2_qos_push_txschq_cfg(pfvf, node->parent, cfg); +} + +static int otx2_qos_root_add(struct otx2_nic *pfvf, u16 htb_maj_id, u16 htb_defcls, + struct netlink_ext_ack *extack) +{ + struct otx2_qos_cfg *new_cfg; + struct otx2_qos_node *root; + int err; + + netdev_dbg(pfvf->netdev, + "TC_HTB_CREATE: handle=0x%x defcls=0x%x\n", + htb_maj_id, htb_defcls); + + root = otx2_qos_alloc_root(pfvf); + if (IS_ERR(root)) { + err = PTR_ERR(root); + return err; + } + + /* allocate txschq queue */ + new_cfg = kzalloc(sizeof(*new_cfg), GFP_KERNEL); + if (!new_cfg) { + NL_SET_ERR_MSG_MOD(extack, "Memory allocation error"); + err = -ENOMEM; + goto free_root_node; + } + /* allocate htb root node */ + new_cfg->schq[root->level] = 1; + err = otx2_qos_txschq_alloc(pfvf, new_cfg); + if (err) { + NL_SET_ERR_MSG_MOD(extack, "Error allocating txschq"); + goto free_root_node; + } + + if (!(pfvf->netdev->flags & IFF_UP) || + root->level == NIX_TXSCH_LVL_TL1) { + root->schq = new_cfg->schq_list[root->level][0]; + goto out; + } + + /* update the txschq configuration in hw */ + err = otx2_qos_txschq_update_root_cfg(pfvf, root, new_cfg); + if (err) { + NL_SET_ERR_MSG_MOD(extack, + "Error updating txschq configuration"); + goto txschq_free; + } + +out: + WRITE_ONCE(pfvf->qos.defcls, htb_defcls); + /* Pairs with smp_load_acquire() in ndo_select_queue */ + smp_store_release(&pfvf->qos.maj_id, htb_maj_id); + kfree(new_cfg); + return 0; + +txschq_free: + otx2_qos_free_cfg(pfvf, new_cfg); +free_root_node: + kfree(new_cfg); + otx2_qos_sw_node_delete(pfvf, root); + return err; +} + +static int otx2_qos_root_destroy(struct otx2_nic *pfvf) +{ + struct otx2_qos_node *root; + + netdev_dbg(pfvf->netdev, "TC_HTB_DESTROY\n"); + + /* find root node */ + root = otx2_sw_node_find(pfvf, OTX2_QOS_ROOT_CLASSID); + if (!root) + return -ENOENT; + + /* free the hw mappings */ + otx2_qos_destroy_node(pfvf, root); + + return 0; +} + +static int otx2_qos_validate_configuration(struct otx2_qos_node *parent, + struct netlink_ext_ack *extack, + struct otx2_nic *pfvf, + u64 prio) +{ + if (test_bit(prio, parent->prio_bmap)) { + NL_SET_ERR_MSG_MOD(extack, + "Static priority child with same priority exists"); + return -EEXIST; + } + + if (prio == TXSCH_TL1_DFLT_RR_PRIO) { + NL_SET_ERR_MSG_MOD(extack, + "Priority is reserved for Round Robin"); + return -EINVAL; + } + + return 0; +} + +static int otx2_qos_leaf_alloc_queue(struct otx2_nic *pfvf, u16 classid, + u32 parent_classid, u64 rate, u64 ceil, + u64 prio, struct netlink_ext_ack *extack) +{ + struct otx2_qos_cfg *old_cfg, *new_cfg; + struct otx2_qos_node *node, *parent; + int qid, ret, err; + + netdev_dbg(pfvf->netdev, + "TC_HTB_LEAF_ALLOC_QUEUE: classid=0x%x parent_classid=0x%x rate=%lld ceil=%lld prio=%lld\n", + classid, parent_classid, rate, ceil, prio); + + if (prio > OTX2_QOS_MAX_PRIO) { + NL_SET_ERR_MSG_MOD(extack, "Valid priority range 0 to 7"); + ret = -EOPNOTSUPP; + goto out; + } + + /* get parent node */ + parent = otx2_sw_node_find(pfvf, parent_classid); + if (!parent) { + NL_SET_ERR_MSG_MOD(extack, "parent node not found"); + ret = -ENOENT; + goto out; + } + if (parent->level == NIX_TXSCH_LVL_MDQ) { + NL_SET_ERR_MSG_MOD(extack, "HTB qos max levels reached"); + ret = -EOPNOTSUPP; + goto out; + } + + ret = otx2_qos_validate_configuration(parent, extack, pfvf, prio); + if (ret) + goto out; + + set_bit(prio, parent->prio_bmap); + + /* read current txschq configuration */ + old_cfg = kzalloc(sizeof(*old_cfg), GFP_KERNEL); + if (!old_cfg) { + NL_SET_ERR_MSG_MOD(extack, "Memory allocation error"); + ret = -ENOMEM; + goto reset_prio; + } + otx2_qos_read_txschq_cfg(pfvf, parent, old_cfg); + + /* allocate a new sq */ + qid = otx2_qos_get_qid(pfvf); + if (qid < 0) { + NL_SET_ERR_MSG_MOD(extack, "Reached max supported QOS SQ's"); + ret = -ENOMEM; + goto free_old_cfg; + } + + /* Actual SQ mapping will be updated after SMQ alloc */ + pfvf->qos.qid_to_sqmap[qid] = OTX2_QOS_INVALID_SQ; + + /* allocate and initialize a new child node */ + node = otx2_qos_sw_create_leaf_node(pfvf, parent, classid, prio, rate, + ceil, qid); + if (IS_ERR(node)) { + NL_SET_ERR_MSG_MOD(extack, "Unable to allocate leaf node"); + ret = PTR_ERR(node); + goto free_old_cfg; + } + + /* push new txschq config to hw */ + new_cfg = kzalloc(sizeof(*new_cfg), GFP_KERNEL); + if (!new_cfg) { + NL_SET_ERR_MSG_MOD(extack, "Memory allocation error"); + ret = -ENOMEM; + goto free_node; + } + ret = otx2_qos_update_tree(pfvf, node, new_cfg); + if (ret) { + NL_SET_ERR_MSG_MOD(extack, "HTB HW configuration error"); + kfree(new_cfg); + otx2_qos_sw_node_delete(pfvf, node); + /* restore the old qos tree */ + err = otx2_qos_txschq_update_config(pfvf, parent, old_cfg); + if (err) { + netdev_err(pfvf->netdev, + "Failed to restore txcshq configuration"); + goto free_old_cfg; + } + + otx2_qos_update_smq(pfvf, parent, QOS_CFG_SQ); + goto free_old_cfg; + } + + /* update tx_real_queues */ + otx2_qos_update_tx_netdev_queues(pfvf); + + /* free new txschq config */ + kfree(new_cfg); + + /* free old txschq config */ + otx2_qos_free_cfg(pfvf, old_cfg); + kfree(old_cfg); + + return pfvf->hw.tx_queues + qid; + +free_node: + otx2_qos_sw_node_delete(pfvf, node); +free_old_cfg: + kfree(old_cfg); +reset_prio: + clear_bit(prio, parent->prio_bmap); +out: + return ret; +} + +static int otx2_qos_leaf_to_inner(struct otx2_nic *pfvf, u16 classid, + u16 child_classid, u64 rate, u64 ceil, u64 prio, + struct netlink_ext_ack *extack) +{ + struct otx2_qos_cfg *old_cfg, *new_cfg; + struct otx2_qos_node *node, *child; + int ret, err; + u16 qid; + + netdev_dbg(pfvf->netdev, + "TC_HTB_LEAF_TO_INNER classid %04x, child %04x, rate %llu, ceil %llu\n", + classid, child_classid, rate, ceil); + + if (prio > OTX2_QOS_MAX_PRIO) { + NL_SET_ERR_MSG_MOD(extack, "Valid priority range 0 to 7"); + ret = -EOPNOTSUPP; + goto out; + } + + /* find node related to classid */ + node = otx2_sw_node_find(pfvf, classid); + if (!node) { + NL_SET_ERR_MSG_MOD(extack, "HTB node not found"); + ret = -ENOENT; + goto out; + } + /* check max qos txschq level */ + if (node->level == NIX_TXSCH_LVL_MDQ) { + NL_SET_ERR_MSG_MOD(extack, "HTB qos level not supported"); + ret = -EOPNOTSUPP; + goto out; + } + + set_bit(prio, node->prio_bmap); + + /* store the qid to assign to leaf node */ + qid = node->qid; + + /* read current txschq configuration */ + old_cfg = kzalloc(sizeof(*old_cfg), GFP_KERNEL); + if (!old_cfg) { + NL_SET_ERR_MSG_MOD(extack, "Memory allocation error"); + ret = -ENOMEM; + goto reset_prio; + } + otx2_qos_read_txschq_cfg(pfvf, node, old_cfg); + + /* delete the txschq nodes allocated for this node */ + otx2_qos_free_sw_node_schq(pfvf, node); + + /* mark this node as htb inner node */ + WRITE_ONCE(node->qid, OTX2_QOS_QID_INNER); + + /* allocate and initialize a new child node */ + child = otx2_qos_sw_create_leaf_node(pfvf, node, child_classid, + prio, rate, ceil, qid); + if (IS_ERR(child)) { + NL_SET_ERR_MSG_MOD(extack, "Unable to allocate leaf node"); + ret = PTR_ERR(child); + goto free_old_cfg; + } + + /* push new txschq config to hw */ + new_cfg = kzalloc(sizeof(*new_cfg), GFP_KERNEL); + if (!new_cfg) { + NL_SET_ERR_MSG_MOD(extack, "Memory allocation error"); + ret = -ENOMEM; + goto free_node; + } + ret = otx2_qos_update_tree(pfvf, child, new_cfg); + if (ret) { + NL_SET_ERR_MSG_MOD(extack, "HTB HW configuration error"); + kfree(new_cfg); + otx2_qos_sw_node_delete(pfvf, child); + /* restore the old qos tree */ + WRITE_ONCE(node->qid, qid); + err = otx2_qos_alloc_txschq_node(pfvf, node); + if (err) { + netdev_err(pfvf->netdev, + "Failed to restore old leaf node"); + goto free_old_cfg; + } + err = otx2_qos_txschq_update_config(pfvf, node, old_cfg); + if (err) { + netdev_err(pfvf->netdev, + "Failed to restore txcshq configuration"); + goto free_old_cfg; + } + otx2_qos_update_smq(pfvf, node, QOS_CFG_SQ); + goto free_old_cfg; + } + + /* free new txschq config */ + kfree(new_cfg); + + /* free old txschq config */ + otx2_qos_free_cfg(pfvf, old_cfg); + kfree(old_cfg); + + return 0; + +free_node: + otx2_qos_sw_node_delete(pfvf, child); +free_old_cfg: + kfree(old_cfg); +reset_prio: + clear_bit(prio, node->prio_bmap); +out: + return ret; +} + +static int otx2_qos_leaf_del(struct otx2_nic *pfvf, u16 *classid, + struct netlink_ext_ack *extack) +{ + struct otx2_qos_node *node, *parent; + u64 prio; + u16 qid; + + netdev_dbg(pfvf->netdev, "TC_HTB_LEAF_DEL classid %04x\n", *classid); + + /* find node related to classid */ + node = otx2_sw_node_find(pfvf, *classid); + if (!node) { + NL_SET_ERR_MSG_MOD(extack, "HTB node not found"); + return -ENOENT; + } + parent = node->parent; + prio = node->prio; + qid = node->qid; + + otx2_qos_disable_sq(pfvf, node->qid); + + otx2_qos_destroy_node(pfvf, node); + pfvf->qos.qid_to_sqmap[qid] = OTX2_QOS_INVALID_SQ; + + clear_bit(prio, parent->prio_bmap); + + return 0; +} + +static int otx2_qos_leaf_del_last(struct otx2_nic *pfvf, u16 classid, bool force, + struct netlink_ext_ack *extack) +{ + struct otx2_qos_node *node, *parent; + struct otx2_qos_cfg *new_cfg; + u64 prio; + int err; + u16 qid; + + netdev_dbg(pfvf->netdev, + "TC_HTB_LEAF_DEL_LAST classid %04x\n", classid); + + /* find node related to classid */ + node = otx2_sw_node_find(pfvf, classid); + if (!node) { + NL_SET_ERR_MSG_MOD(extack, "HTB node not found"); + return -ENOENT; + } + + /* save qid for use by parent */ + qid = node->qid; + prio = node->prio; + + parent = otx2_sw_node_find(pfvf, node->parent->classid); + if (!parent) { + NL_SET_ERR_MSG_MOD(extack, "parent node not found"); + return -ENOENT; + } + + /* destroy the leaf node */ + otx2_qos_destroy_node(pfvf, node); + pfvf->qos.qid_to_sqmap[qid] = OTX2_QOS_INVALID_SQ; + + clear_bit(prio, parent->prio_bmap); + + /* create downstream txschq entries to parent */ + err = otx2_qos_alloc_txschq_node(pfvf, parent); + if (err) { + NL_SET_ERR_MSG_MOD(extack, "HTB failed to create txsch configuration"); + return err; + } + WRITE_ONCE(parent->qid, qid); + __set_bit(qid, pfvf->qos.qos_sq_bmap); + + /* push new txschq config to hw */ + new_cfg = kzalloc(sizeof(*new_cfg), GFP_KERNEL); + if (!new_cfg) { + NL_SET_ERR_MSG_MOD(extack, "Memory allocation error"); + return -ENOMEM; + } + /* fill txschq cfg and push txschq cfg to hw */ + otx2_qos_fill_cfg_schq(parent, new_cfg); + err = otx2_qos_push_txschq_cfg(pfvf, parent, new_cfg); + if (err) { + NL_SET_ERR_MSG_MOD(extack, "HTB HW configuration error"); + kfree(new_cfg); + return err; + } + kfree(new_cfg); + + /* update tx_real_queues */ + otx2_qos_update_tx_netdev_queues(pfvf); + + return 0; +} + +void otx2_clean_qos_queues(struct otx2_nic *pfvf) +{ + struct otx2_qos_node *root; + + root = otx2_sw_node_find(pfvf, OTX2_QOS_ROOT_CLASSID); + if (!root) + return; + + otx2_qos_update_smq(pfvf, root, QOS_SMQ_FLUSH); +} + +void otx2_qos_config_txschq(struct otx2_nic *pfvf) +{ + struct otx2_qos_node *root; + int err; + + root = otx2_sw_node_find(pfvf, OTX2_QOS_ROOT_CLASSID); + if (!root) + return; + + err = otx2_qos_txschq_config(pfvf, root); + if (err) { + netdev_err(pfvf->netdev, "Error update txschq configuration\n"); + goto root_destroy; + } + + err = otx2_qos_txschq_push_cfg_tl(pfvf, root, NULL); + if (err) { + netdev_err(pfvf->netdev, "Error update txschq configuration\n"); + goto root_destroy; + } + + otx2_qos_update_smq(pfvf, root, QOS_CFG_SQ); + return; + +root_destroy: + netdev_err(pfvf->netdev, "Failed to update Scheduler/Shaping config in Hardware\n"); + /* Free resources allocated */ + otx2_qos_root_destroy(pfvf); +} + +int otx2_setup_tc_htb(struct net_device *ndev, struct tc_htb_qopt_offload *htb) +{ + struct otx2_nic *pfvf = netdev_priv(ndev); + int res; + + switch (htb->command) { + case TC_HTB_CREATE: + return otx2_qos_root_add(pfvf, htb->parent_classid, + htb->classid, htb->extack); + case TC_HTB_DESTROY: + return otx2_qos_root_destroy(pfvf); + case TC_HTB_LEAF_ALLOC_QUEUE: + res = otx2_qos_leaf_alloc_queue(pfvf, htb->classid, + htb->parent_classid, + htb->rate, htb->ceil, + htb->prio, htb->extack); + if (res < 0) + return res; + htb->qid = res; + return 0; + case TC_HTB_LEAF_TO_INNER: + return otx2_qos_leaf_to_inner(pfvf, htb->parent_classid, + htb->classid, htb->rate, + htb->ceil, htb->prio, + htb->extack); + case TC_HTB_LEAF_DEL: + return otx2_qos_leaf_del(pfvf, &htb->classid, htb->extack); + case TC_HTB_LEAF_DEL_LAST: + case TC_HTB_LEAF_DEL_LAST_FORCE: + return otx2_qos_leaf_del_last(pfvf, htb->classid, + htb->command == TC_HTB_LEAF_DEL_LAST_FORCE, + htb->extack); + case TC_HTB_LEAF_QUERY_QUEUE: + res = otx2_get_txq_by_classid(pfvf, htb->classid); + htb->qid = res; + return 0; + case TC_HTB_NODE_MODIFY: + fallthrough; + default: + return -EOPNOTSUPP; + } +} diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/qos.h b/drivers/net/ethernet/marvell/octeontx2/nic/qos.h new file mode 100644 index 0000000000000000000000000000000000000000..19773284be27a160876a1e7239c85883135cb23a --- /dev/null +++ b/drivers/net/ethernet/marvell/octeontx2/nic/qos.h @@ -0,0 +1,69 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Marvell RVU Ethernet driver + * + * Copyright (C) 2023 Marvell. + * + */ +#ifndef OTX2_QOS_H +#define OTX2_QOS_H + +#include +#include +#include + +#define OTX2_QOS_MAX_LVL 4 +#define OTX2_QOS_MAX_PRIO 7 +#define OTX2_QOS_MAX_LEAF_NODES 16 + +enum qos_smq_operations { + QOS_CFG_SQ, + QOS_SMQ_FLUSH, +}; + +u64 otx2_get_txschq_rate_regval(struct otx2_nic *nic, u64 maxrate, u32 burst); + +int otx2_setup_tc_htb(struct net_device *ndev, struct tc_htb_qopt_offload *htb); +int otx2_qos_get_qid(struct otx2_nic *pfvf); +void otx2_qos_free_qid(struct otx2_nic *pfvf, int qidx); +int otx2_qos_enable_sq(struct otx2_nic *pfvf, int qidx); +void otx2_qos_disable_sq(struct otx2_nic *pfvf, int qidx); + +struct otx2_qos_cfg { + u16 schq[NIX_TXSCH_LVL_CNT]; + u16 schq_contig[NIX_TXSCH_LVL_CNT]; + int static_node_pos[NIX_TXSCH_LVL_CNT]; + int dwrr_node_pos[NIX_TXSCH_LVL_CNT]; + u16 schq_contig_list[NIX_TXSCH_LVL_CNT][MAX_TXSCHQ_PER_FUNC]; + u16 schq_list[NIX_TXSCH_LVL_CNT][MAX_TXSCHQ_PER_FUNC]; +}; + +struct otx2_qos { + DECLARE_HASHTABLE(qos_hlist, order_base_2(OTX2_QOS_MAX_LEAF_NODES)); + struct mutex qos_lock; /* child list lock */ + u16 qid_to_sqmap[OTX2_QOS_MAX_LEAF_NODES]; + struct list_head qos_tree; + DECLARE_BITMAP(qos_sq_bmap, OTX2_QOS_MAX_LEAF_NODES); + u16 maj_id; + u16 defcls; + u8 link_cfg_lvl; /* LINKX_CFG CSRs mapped to TL3 or TL2's index ? */ +}; + +struct otx2_qos_node { + struct list_head list; /* list management */ + struct list_head child_list; + struct list_head child_schq_list; + struct hlist_node hlist; + DECLARE_BITMAP(prio_bmap, OTX2_QOS_MAX_PRIO + 1); + struct otx2_qos_node *parent; /* parent qos node */ + u64 rate; /* htb params */ + u64 ceil; + u32 classid; + u32 prio; + u16 schq; /* hw txschq */ + u16 qid; + u16 prio_anchor; + u8 level; +}; + + +#endif diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/qos_sq.c b/drivers/net/ethernet/marvell/octeontx2/nic/qos_sq.c new file mode 100644 index 0000000000000000000000000000000000000000..9d887bfc31089cccebc833cb62853ba9e9c79a24 --- /dev/null +++ b/drivers/net/ethernet/marvell/octeontx2/nic/qos_sq.c @@ -0,0 +1,296 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Marvell RVU Physical Function ethernet driver + * + * Copyright (C) 2023 Marvell. + * + */ + +#include +#include + +#include "cn10k.h" +#include "otx2_reg.h" +#include "otx2_common.h" +#include "otx2_txrx.h" +#include "otx2_struct.h" + +#define OTX2_QOS_MAX_LEAF_NODES 16 + +static void otx2_qos_aura_pool_free(struct otx2_nic *pfvf, int pool_id) +{ + struct otx2_pool *pool; + + if (!pfvf->qset.pool) + return; + + pool = &pfvf->qset.pool[pool_id]; + qmem_free(pfvf->dev, pool->stack); + qmem_free(pfvf->dev, pool->fc_addr); + pool->stack = NULL; + pool->fc_addr = NULL; +} + +static int otx2_qos_sq_aura_pool_init(struct otx2_nic *pfvf, int qidx) +{ + struct otx2_qset *qset = &pfvf->qset; + int pool_id, stack_pages, num_sqbs; + struct otx2_hw *hw = &pfvf->hw; + struct otx2_snd_queue *sq; + struct otx2_pool *pool; + dma_addr_t bufptr; + int err, ptr; + u64 iova, pa; + + /* Calculate number of SQBs needed. + * + * For a 128byte SQE, and 4K size SQB, 31 SQEs will fit in one SQB. + * Last SQE is used for pointing to next SQB. + */ + num_sqbs = (hw->sqb_size / 128) - 1; + num_sqbs = (qset->sqe_cnt + num_sqbs) / num_sqbs; + + /* Get no of stack pages needed */ + stack_pages = + (num_sqbs + hw->stack_pg_ptrs - 1) / hw->stack_pg_ptrs; + + pool_id = otx2_get_pool_idx(pfvf, AURA_NIX_SQ, qidx); + pool = &pfvf->qset.pool[pool_id]; + + /* Initialize aura context */ + err = otx2_aura_init(pfvf, pool_id, pool_id, num_sqbs); + if (err) + return err; + + /* Initialize pool context */ + err = otx2_pool_init(pfvf, pool_id, stack_pages, + num_sqbs, hw->sqb_size, AURA_NIX_SQ); + if (err) + goto aura_free; + + /* Flush accumulated messages */ + err = otx2_sync_mbox_msg(&pfvf->mbox); + if (err) + goto pool_free; + + /* Allocate pointers and free them to aura/pool */ + sq = &qset->sq[qidx]; + sq->sqb_count = 0; + sq->sqb_ptrs = kcalloc(num_sqbs, sizeof(*sq->sqb_ptrs), GFP_KERNEL); + if (!sq->sqb_ptrs) { + err = -ENOMEM; + goto pool_free; + } + + for (ptr = 0; ptr < num_sqbs; ptr++) { + err = otx2_alloc_rbuf(pfvf, pool, &bufptr); + if (err) + goto sqb_free; + pfvf->hw_ops->aura_freeptr(pfvf, pool_id, bufptr); + sq->sqb_ptrs[sq->sqb_count++] = (u64)bufptr; + } + + return 0; + +sqb_free: + while (ptr--) { + if (!sq->sqb_ptrs[ptr]) + continue; + iova = sq->sqb_ptrs[ptr]; + pa = otx2_iova_to_phys(pfvf->iommu_domain, iova); + dma_unmap_page_attrs(pfvf->dev, iova, hw->sqb_size, + DMA_FROM_DEVICE, + DMA_ATTR_SKIP_CPU_SYNC); + put_page(virt_to_page(phys_to_virt(pa))); + otx2_aura_allocptr(pfvf, pool_id); + } + sq->sqb_count = 0; + kfree(sq->sqb_ptrs); +pool_free: + qmem_free(pfvf->dev, pool->stack); +aura_free: + qmem_free(pfvf->dev, pool->fc_addr); + otx2_mbox_reset(&pfvf->mbox.mbox, 0); + return err; +} + +static void otx2_qos_sq_free_sqbs(struct otx2_nic *pfvf, int qidx) +{ + struct otx2_qset *qset = &pfvf->qset; + struct otx2_hw *hw = &pfvf->hw; + struct otx2_snd_queue *sq; + u64 iova, pa; + int sqb; + + sq = &qset->sq[qidx]; + if (!sq->sqb_ptrs) + return; + for (sqb = 0; sqb < sq->sqb_count; sqb++) { + if (!sq->sqb_ptrs[sqb]) + continue; + iova = sq->sqb_ptrs[sqb]; + pa = otx2_iova_to_phys(pfvf->iommu_domain, iova); + dma_unmap_page_attrs(pfvf->dev, iova, hw->sqb_size, + DMA_FROM_DEVICE, + DMA_ATTR_SKIP_CPU_SYNC); + put_page(virt_to_page(phys_to_virt(pa))); + } + + sq->sqb_count = 0; + + sq = &qset->sq[qidx]; + qmem_free(pfvf->dev, sq->sqe); + qmem_free(pfvf->dev, sq->tso_hdrs); + kfree(sq->sg); + kfree(sq->sqb_ptrs); + qmem_free(pfvf->dev, sq->timestamps); + + memset((void *)sq, 0, sizeof(*sq)); +} + +/* send queue id */ +static void otx2_qos_sqb_flush(struct otx2_nic *pfvf, int qidx) +{ + int sqe_tail, sqe_head; + u64 incr, *ptr, val; + + ptr = (__force u64 *)otx2_get_regaddr(pfvf, NIX_LF_SQ_OP_STATUS); + incr = (u64)qidx << 32; + val = otx2_atomic64_add(incr, ptr); + sqe_head = (val >> 20) & 0x3F; + sqe_tail = (val >> 28) & 0x3F; + if (sqe_head != sqe_tail) + usleep_range(50, 60); +} + +static int otx2_qos_ctx_disable(struct otx2_nic *pfvf, u16 qidx, int aura_id) +{ + struct nix_cn10k_aq_enq_req *cn10k_sq_aq; + struct npa_aq_enq_req *aura_aq; + struct npa_aq_enq_req *pool_aq; + struct nix_aq_enq_req *sq_aq; + + if (test_bit(CN10K_LMTST, &pfvf->hw.cap_flag)) { + cn10k_sq_aq = otx2_mbox_alloc_msg_nix_cn10k_aq_enq(&pfvf->mbox); + if (!cn10k_sq_aq) + return -ENOMEM; + cn10k_sq_aq->qidx = qidx; + cn10k_sq_aq->sq.ena = 0; + cn10k_sq_aq->sq_mask.ena = 1; + cn10k_sq_aq->ctype = NIX_AQ_CTYPE_SQ; + cn10k_sq_aq->op = NIX_AQ_INSTOP_WRITE; + } else { + sq_aq = otx2_mbox_alloc_msg_nix_aq_enq(&pfvf->mbox); + if (!sq_aq) + return -ENOMEM; + sq_aq->qidx = qidx; + sq_aq->sq.ena = 0; + sq_aq->sq_mask.ena = 1; + sq_aq->ctype = NIX_AQ_CTYPE_SQ; + sq_aq->op = NIX_AQ_INSTOP_WRITE; + } + + aura_aq = otx2_mbox_alloc_msg_npa_aq_enq(&pfvf->mbox); + if (!aura_aq) { + otx2_mbox_reset(&pfvf->mbox.mbox, 0); + return -ENOMEM; + } + + aura_aq->aura_id = aura_id; + aura_aq->aura.ena = 0; + aura_aq->aura_mask.ena = 1; + aura_aq->ctype = NPA_AQ_CTYPE_AURA; + aura_aq->op = NPA_AQ_INSTOP_WRITE; + + pool_aq = otx2_mbox_alloc_msg_npa_aq_enq(&pfvf->mbox); + if (!pool_aq) { + otx2_mbox_reset(&pfvf->mbox.mbox, 0); + return -ENOMEM; + } + + pool_aq->aura_id = aura_id; + pool_aq->pool.ena = 0; + pool_aq->pool_mask.ena = 1; + + pool_aq->ctype = NPA_AQ_CTYPE_POOL; + pool_aq->op = NPA_AQ_INSTOP_WRITE; + + return otx2_sync_mbox_msg(&pfvf->mbox); +} + +int otx2_qos_get_qid(struct otx2_nic *pfvf) +{ + int qidx; + + qidx = find_first_zero_bit(pfvf->qos.qos_sq_bmap, + pfvf->hw.tc_tx_queues); + + return qidx == pfvf->hw.tc_tx_queues ? -ENOSPC : qidx; +} + +void otx2_qos_free_qid(struct otx2_nic *pfvf, int qidx) +{ + clear_bit(qidx, pfvf->qos.qos_sq_bmap); +} + +int otx2_qos_enable_sq(struct otx2_nic *pfvf, int qidx) +{ + struct otx2_hw *hw = &pfvf->hw; + int pool_id, sq_idx, err; + + if (pfvf->flags & OTX2_FLAG_INTF_DOWN) + return -EPERM; + + sq_idx = hw->non_qos_queues + qidx; + + mutex_lock(&pfvf->mbox.lock); + err = otx2_qos_sq_aura_pool_init(pfvf, sq_idx); + if (err) + goto out; + + pool_id = otx2_get_pool_idx(pfvf, AURA_NIX_SQ, sq_idx); + err = otx2_sq_init(pfvf, sq_idx, pool_id); + if (err) + goto out; +out: + mutex_unlock(&pfvf->mbox.lock); + return err; +} + +void otx2_qos_disable_sq(struct otx2_nic *pfvf, int qidx) +{ + struct otx2_qset *qset = &pfvf->qset; + struct otx2_hw *hw = &pfvf->hw; + struct otx2_snd_queue *sq; + struct otx2_cq_queue *cq; + int pool_id, sq_idx; + + sq_idx = hw->non_qos_queues + qidx; + + /* If the DOWN flag is set SQs are already freed */ + if (pfvf->flags & OTX2_FLAG_INTF_DOWN) + return; + + sq = &pfvf->qset.sq[sq_idx]; + if (!sq->sqb_ptrs) + return; + + if (sq_idx < hw->non_qos_queues || + sq_idx >= otx2_get_total_tx_queues(pfvf)) { + netdev_err(pfvf->netdev, "Send Queue is not a QoS queue\n"); + return; + } + + cq = &qset->cq[pfvf->hw.rx_queues + sq_idx]; + pool_id = otx2_get_pool_idx(pfvf, AURA_NIX_SQ, sq_idx); + + otx2_qos_sqb_flush(pfvf, sq_idx); + otx2_smq_flush(pfvf, otx2_get_smq_idx(pfvf, sq_idx)); + otx2_cleanup_tx_cqes(pfvf, cq); + + mutex_lock(&pfvf->mbox.lock); + otx2_qos_ctx_disable(pfvf, sq_idx, pool_id); + mutex_unlock(&pfvf->mbox.lock); + + otx2_qos_sq_free_sqbs(pfvf, sq_idx); + otx2_qos_aura_pool_free(pfvf, pool_id); +} diff --git a/drivers/net/ethernet/marvell/prestera/prestera_flower.c b/drivers/net/ethernet/marvell/prestera/prestera_flower.c index 91a478b75cbf009ff5caa8ccb550e38da1dd7836..3e20e71b0f81a7af79d299d91861468e9399ee20 100644 --- a/drivers/net/ethernet/marvell/prestera/prestera_flower.c +++ b/drivers/net/ethernet/marvell/prestera/prestera_flower.c @@ -148,6 +148,12 @@ static int prestera_flower_parse_meta(struct prestera_acl_rule *rule, __be16 key, mask; flow_rule_match_meta(f_rule, &match); + + if (match.mask->l2_miss) { + NL_SET_ERR_MSG_MOD(f->common.extack, "Can't match on \"l2_miss\""); + return -EOPNOTSUPP; + } + if (match.mask->ingress_ifindex != 0xFFFFFFFF) { NL_SET_ERR_MSG_MOD(f->common.extack, "Unsupported ingress ifindex mask"); diff --git a/drivers/net/ethernet/marvell/prestera/prestera_main.c b/drivers/net/ethernet/marvell/prestera/prestera_main.c index 9d504142e51addfcfd5e68f200f7395fabc4870a..4fb886c57cd77897d7e7c8913b98744b30f05da4 100644 --- a/drivers/net/ethernet/marvell/prestera/prestera_main.c +++ b/drivers/net/ethernet/marvell/prestera/prestera_main.c @@ -300,8 +300,7 @@ static void prestera_pcs_get_state(struct phylink_pcs *pcs, } } -static int prestera_pcs_config(struct phylink_pcs *pcs, - unsigned int mode, +static int prestera_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode, phy_interface_t interface, const unsigned long *advertising, bool permit_pause_to_mac) @@ -316,30 +315,25 @@ static int prestera_pcs_config(struct phylink_pcs *pcs, cfg_mac.admin = true; cfg_mac.fec = PRESTERA_PORT_FEC_OFF; + cfg_mac.inband = neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED; switch (interface) { case PHY_INTERFACE_MODE_10GBASER: cfg_mac.speed = SPEED_10000; - cfg_mac.inband = 0; cfg_mac.mode = PRESTERA_MAC_MODE_SR_LR; break; case PHY_INTERFACE_MODE_2500BASEX: cfg_mac.speed = SPEED_2500; cfg_mac.duplex = DUPLEX_FULL; - cfg_mac.inband = test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, - advertising); cfg_mac.mode = PRESTERA_MAC_MODE_SGMII; break; case PHY_INTERFACE_MODE_SGMII: - cfg_mac.inband = 1; cfg_mac.mode = PRESTERA_MAC_MODE_SGMII; break; case PHY_INTERFACE_MODE_1000BASEX: default: cfg_mac.speed = SPEED_1000; cfg_mac.duplex = DUPLEX_FULL; - cfg_mac.inband = test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, - advertising); cfg_mac.mode = PRESTERA_MAC_MODE_1000BASE_X; break; } @@ -401,6 +395,7 @@ static int prestera_port_sfp_bind(struct prestera_port *port) continue; port->phylink_pcs.ops = &prestera_pcs_ops; + port->phylink_pcs.neg_mode = true; port->phy_config.dev = &port->dev->dev; port->phy_config.type = PHYLINK_NETDEV; diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c index 277738c50c56e946546958a7369622697f686d0b..61286b0d9b0cb619896de03874acca0fbd3a5315 100644 --- a/drivers/net/ethernet/mellanox/mlx4/main.c +++ b/drivers/net/ethernet/mellanox/mlx4/main.c @@ -1374,16 +1374,13 @@ static int mlx4_mf_bond(struct mlx4_dev *dev) int nvfs; struct mlx4_slaves_pport slaves_port1; struct mlx4_slaves_pport slaves_port2; - DECLARE_BITMAP(slaves_port_1_2, MLX4_MFUNC_MAX); slaves_port1 = mlx4_phys_to_slaves_pport(dev, 1); slaves_port2 = mlx4_phys_to_slaves_pport(dev, 2); - bitmap_and(slaves_port_1_2, - slaves_port1.slaves, slaves_port2.slaves, - dev->persist->num_vfs + 1); /* only single port vfs are allowed */ - if (bitmap_weight(slaves_port_1_2, dev->persist->num_vfs + 1) > 1) { + if (bitmap_weight_and(slaves_port1.slaves, slaves_port2.slaves, + dev->persist->num_vfs + 1) > 1) { mlx4_warn(dev, "HA mode unsupported for dual ported VFs\n"); return -EINVAL; } @@ -3027,13 +3024,43 @@ static void mlx4_enable_msi_x(struct mlx4_dev *dev) } } +static int mlx4_devlink_port_type_set(struct devlink_port *devlink_port, + enum devlink_port_type port_type) +{ + struct mlx4_port_info *info = container_of(devlink_port, + struct mlx4_port_info, + devlink_port); + enum mlx4_port_type mlx4_port_type; + + switch (port_type) { + case DEVLINK_PORT_TYPE_AUTO: + mlx4_port_type = MLX4_PORT_TYPE_AUTO; + break; + case DEVLINK_PORT_TYPE_ETH: + mlx4_port_type = MLX4_PORT_TYPE_ETH; + break; + case DEVLINK_PORT_TYPE_IB: + mlx4_port_type = MLX4_PORT_TYPE_IB; + break; + default: + return -EOPNOTSUPP; + } + + return __set_port_type(info, mlx4_port_type); +} + +static const struct devlink_port_ops mlx4_devlink_port_ops = { + .port_type_set = mlx4_devlink_port_type_set, +}; + static int mlx4_init_port_info(struct mlx4_dev *dev, int port) { struct devlink *devlink = priv_to_devlink(mlx4_priv(dev)); struct mlx4_port_info *info = &mlx4_priv(dev)->port[port]; int err; - err = devl_port_register(devlink, &info->devlink_port, port); + err = devl_port_register_with_ops(devlink, &info->devlink_port, port, + &mlx4_devlink_port_ops); if (err) return err; @@ -3877,31 +3904,6 @@ static int __mlx4_init_one(struct pci_dev *pdev, int pci_dev_data, return err; } -static int mlx4_devlink_port_type_set(struct devlink_port *devlink_port, - enum devlink_port_type port_type) -{ - struct mlx4_port_info *info = container_of(devlink_port, - struct mlx4_port_info, - devlink_port); - enum mlx4_port_type mlx4_port_type; - - switch (port_type) { - case DEVLINK_PORT_TYPE_AUTO: - mlx4_port_type = MLX4_PORT_TYPE_AUTO; - break; - case DEVLINK_PORT_TYPE_ETH: - mlx4_port_type = MLX4_PORT_TYPE_ETH; - break; - case DEVLINK_PORT_TYPE_IB: - mlx4_port_type = MLX4_PORT_TYPE_IB; - break; - default: - return -EOPNOTSUPP; - } - - return __set_port_type(info, mlx4_port_type); -} - static void mlx4_devlink_param_load_driverinit_values(struct devlink *devlink) { struct mlx4_priv *priv = devlink_priv(devlink); @@ -3986,7 +3988,6 @@ static int mlx4_devlink_reload_up(struct devlink *devlink, enum devlink_reload_a } static const struct devlink_ops mlx4_devlink_ops = { - .port_type_set = mlx4_devlink_port_type_set, .reload_actions = BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT), .reload_down = mlx4_devlink_reload_down, .reload_up = mlx4_devlink_reload_up, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/Makefile b/drivers/net/ethernet/mellanox/mlx5/core/Makefile index ddf1e352f51dbb41f426142b23a659a231f680c0..35f00700a4d6cacfe7593ed799c7c06888cbe250 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/Makefile +++ b/drivers/net/ethernet/mellanox/mlx5/core/Makefile @@ -75,7 +75,8 @@ mlx5_core-$(CONFIG_MLX5_ESWITCH) += esw/acl/helper.o \ esw/acl/egress_lgcy.o esw/acl/egress_ofld.o \ esw/acl/ingress_lgcy.o esw/acl/ingress_ofld.o -mlx5_core-$(CONFIG_MLX5_BRIDGE) += esw/bridge.o esw/bridge_mcast.o en/rep/bridge.o +mlx5_core-$(CONFIG_MLX5_BRIDGE) += esw/bridge.o esw/bridge_mcast.o esw/bridge_debugfs.o \ + en/rep/bridge.o mlx5_core-$(CONFIG_THERMAL) += thermal.o mlx5_core-$(CONFIG_MLX5_MPFS) += lib/mpfs.o diff --git a/drivers/net/ethernet/mellanox/mlx5/core/debugfs.c b/drivers/net/ethernet/mellanox/mlx5/core/debugfs.c index bb95b40d25eb5d224f1d424f0d111d8ca441d94c..2138f28a293182150421477ddb5523300485bac5 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/debugfs.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/debugfs.c @@ -246,6 +246,7 @@ void mlx5_pages_debugfs_init(struct mlx5_core_dev *dev) debugfs_create_u32("fw_pages_total", 0400, pages, &dev->priv.fw_pages); debugfs_create_u32("fw_pages_vfs", 0400, pages, &dev->priv.page_counters[MLX5_VF]); + debugfs_create_u32("fw_pages_ec_vfs", 0400, pages, &dev->priv.page_counters[MLX5_EC_VF]); debugfs_create_u32("fw_pages_sfs", 0400, pages, &dev->priv.page_counters[MLX5_SF]); debugfs_create_u32("fw_pages_host_pf", 0400, pages, &dev->priv.page_counters[MLX5_HOST_PF]); debugfs_create_u32("fw_pages_alloc_failed", 0400, pages, &dev->priv.fw_pages_alloc_failed); @@ -513,11 +514,11 @@ EXPORT_SYMBOL(mlx5_debug_qp_add); void mlx5_debug_qp_remove(struct mlx5_core_dev *dev, struct mlx5_core_qp *qp) { - if (!mlx5_debugfs_root) + if (!mlx5_debugfs_root || !qp->dbg) return; - if (qp->dbg) - rem_res_tree(qp->dbg); + rem_res_tree(qp->dbg); + qp->dbg = NULL; } EXPORT_SYMBOL(mlx5_debug_qp_remove); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/dev.c b/drivers/net/ethernet/mellanox/mlx5/core/dev.c index 1b33533b15dea966e6e1a32c2042e731cd711ba3..edb06fb9bbc52c6c318603e3e572d1d600525c09 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/dev.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/dev.c @@ -151,12 +151,6 @@ static bool is_ib_rep_supported(struct mlx5_core_dev *dev) if (!is_eth_rep_supported(dev)) return false; - if (!MLX5_ESWITCH_MANAGER(dev)) - return false; - - if (!is_mdev_switchdev_mode(dev)) - return false; - if (mlx5_core_mp_enabled(dev)) return false; @@ -323,6 +317,18 @@ static void del_adev(struct auxiliary_device *adev) auxiliary_device_uninit(adev); } +void mlx5_dev_set_lightweight(struct mlx5_core_dev *dev) +{ + mutex_lock(&mlx5_intf_mutex); + dev->priv.flags |= MLX5_PRIV_FLAGS_DISABLE_ALL_ADEV; + mutex_unlock(&mlx5_intf_mutex); +} + +bool mlx5_dev_is_lightweight(struct mlx5_core_dev *dev) +{ + return dev->priv.flags & MLX5_PRIV_FLAGS_DISABLE_ALL_ADEV; +} + int mlx5_attach_device(struct mlx5_core_dev *dev) { struct mlx5_priv *priv = &dev->priv; @@ -457,6 +463,10 @@ static int add_drivers(struct mlx5_core_dev *dev) if (priv->adev[i]) continue; + if (mlx5_adev_devices[i].is_enabled && + !(mlx5_adev_devices[i].is_enabled(dev))) + continue; + if (mlx5_adev_devices[i].is_supported) is_supported = mlx5_adev_devices[i].is_supported(dev); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/devlink.c b/drivers/net/ethernet/mellanox/mlx5/core/devlink.c index 4b607785d694c549ae3a98407d7e3600c0a89879..3d82ec8906660540e88b50e27e6b104c4a00cc12 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/devlink.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/devlink.c @@ -7,7 +7,6 @@ #include "fw_reset.h" #include "fs_core.h" #include "eswitch.h" -#include "lag/lag.h" #include "esw/qos.h" #include "sf/dev/dev.h" #include "sf/sf.h" @@ -142,6 +141,13 @@ static int mlx5_devlink_reload_down(struct devlink *devlink, bool netns_change, bool sf_dev_allocated; int ret = 0; + if (mlx5_dev_is_lightweight(dev)) { + if (action != DEVLINK_RELOAD_ACTION_DRIVER_REINIT) + return -EOPNOTSUPP; + mlx5_unload_one_light(dev); + return 0; + } + sf_dev_allocated = mlx5_sf_dev_allocated(dev); if (sf_dev_allocated) { /* Reload results in deleting SF device which further results in @@ -162,9 +168,8 @@ static int mlx5_devlink_reload_down(struct devlink *devlink, bool netns_change, return -EOPNOTSUPP; } - if (pci_num_vf(pdev)) { + if (mlx5_core_is_pf(dev) && pci_num_vf(pdev)) NL_SET_ERR_MSG_MOD(extack, "reload while VFs are present is unfavorable"); - } switch (action) { case DEVLINK_RELOAD_ACTION_DRIVER_REINIT: @@ -195,6 +200,10 @@ static int mlx5_devlink_reload_up(struct devlink *devlink, enum devlink_reload_a *actions_performed = BIT(action); switch (action) { case DEVLINK_RELOAD_ACTION_DRIVER_REINIT: + if (mlx5_dev_is_lightweight(dev)) { + mlx5_fw_reporters_create(dev); + return mlx5_init_one_devl_locked(dev); + } ret = mlx5_load_one_devl_locked(dev, false); break; case DEVLINK_RELOAD_ACTION_FW_ACTIVATE: @@ -311,8 +320,6 @@ static const struct devlink_ops mlx5_devlink_ops = { .eswitch_inline_mode_get = mlx5_devlink_eswitch_inline_mode_get, .eswitch_encap_mode_set = mlx5_devlink_eswitch_encap_mode_set, .eswitch_encap_mode_get = mlx5_devlink_eswitch_encap_mode_get, - .port_function_hw_addr_get = mlx5_devlink_port_function_hw_addr_get, - .port_function_hw_addr_set = mlx5_devlink_port_function_hw_addr_set, .rate_leaf_tx_share_set = mlx5_esw_devlink_rate_leaf_tx_share_set, .rate_leaf_tx_max_set = mlx5_esw_devlink_rate_leaf_tx_max_set, .rate_node_tx_share_set = mlx5_esw_devlink_rate_node_tx_share_set, @@ -320,16 +327,9 @@ static const struct devlink_ops mlx5_devlink_ops = { .rate_node_new = mlx5_esw_devlink_rate_node_new, .rate_node_del = mlx5_esw_devlink_rate_node_del, .rate_leaf_parent_set = mlx5_esw_devlink_rate_parent_set, - .port_fn_roce_get = mlx5_devlink_port_fn_roce_get, - .port_fn_roce_set = mlx5_devlink_port_fn_roce_set, - .port_fn_migratable_get = mlx5_devlink_port_fn_migratable_get, - .port_fn_migratable_set = mlx5_devlink_port_fn_migratable_set, #endif #ifdef CONFIG_MLX5_SF_MANAGER .port_new = mlx5_devlink_sf_port_new, - .port_del = mlx5_devlink_sf_port_del, - .port_fn_state_get = mlx5_devlink_sf_port_fn_state_get, - .port_fn_state_set = mlx5_devlink_sf_port_fn_state_set, #endif .flash_update = mlx5_devlink_flash_update, .info_get = mlx5_devlink_info_get, @@ -437,54 +437,6 @@ static int mlx5_devlink_large_group_num_validate(struct devlink *devlink, u32 id return 0; } - -static int mlx5_devlink_esw_multiport_set(struct devlink *devlink, u32 id, - struct devlink_param_gset_ctx *ctx) -{ - struct mlx5_core_dev *dev = devlink_priv(devlink); - - if (!MLX5_ESWITCH_MANAGER(dev)) - return -EOPNOTSUPP; - - if (ctx->val.vbool) - return mlx5_lag_mpesw_enable(dev); - - mlx5_lag_mpesw_disable(dev); - return 0; -} - -static int mlx5_devlink_esw_multiport_get(struct devlink *devlink, u32 id, - struct devlink_param_gset_ctx *ctx) -{ - struct mlx5_core_dev *dev = devlink_priv(devlink); - - if (!MLX5_ESWITCH_MANAGER(dev)) - return -EOPNOTSUPP; - - ctx->val.vbool = mlx5_lag_is_mpesw(dev); - return 0; -} - -static int mlx5_devlink_esw_multiport_validate(struct devlink *devlink, u32 id, - union devlink_param_value val, - struct netlink_ext_ack *extack) -{ - struct mlx5_core_dev *dev = devlink_priv(devlink); - - if (!MLX5_ESWITCH_MANAGER(dev)) { - NL_SET_ERR_MSG_MOD(extack, "E-Switch is unsupported"); - return -EOPNOTSUPP; - } - - if (mlx5_eswitch_mode(dev) != MLX5_ESWITCH_OFFLOADS) { - NL_SET_ERR_MSG_MOD(extack, - "E-Switch must be in switchdev mode"); - return -EBUSY; - } - - return 0; -} - #endif static int mlx5_devlink_eq_depth_validate(struct devlink *devlink, u32 id, @@ -558,12 +510,6 @@ static const struct devlink_param mlx5_devlink_params[] = { BIT(DEVLINK_PARAM_CMODE_DRIVERINIT), NULL, NULL, mlx5_devlink_large_group_num_validate), - DEVLINK_PARAM_DRIVER(MLX5_DEVLINK_PARAM_ID_ESW_MULTIPORT, - "esw_multiport", DEVLINK_PARAM_TYPE_BOOL, - BIT(DEVLINK_PARAM_CMODE_RUNTIME), - mlx5_devlink_esw_multiport_get, - mlx5_devlink_esw_multiport_set, - mlx5_devlink_esw_multiport_validate), #endif DEVLINK_PARAM_GENERIC(IO_EQ_SIZE, BIT(DEVLINK_PARAM_CMODE_DRIVERINIT), NULL, NULL, mlx5_devlink_eq_depth_validate), @@ -576,7 +522,7 @@ static void mlx5_devlink_set_params_init_values(struct devlink *devlink) struct mlx5_core_dev *dev = devlink_priv(devlink); union devlink_param_value value; - value.vbool = MLX5_CAP_GEN(dev, roce); + value.vbool = MLX5_CAP_GEN(dev, roce) && !mlx5_dev_is_lightweight(dev); devl_param_driverinit_value_set(devlink, DEVLINK_PARAM_GENERIC_ID_ENABLE_ROCE, value); @@ -626,7 +572,7 @@ static int mlx5_devlink_eth_params_register(struct devlink *devlink) if (err) return err; - value.vbool = true; + value.vbool = !mlx5_dev_is_lightweight(dev); devl_param_driverinit_value_set(devlink, DEVLINK_PARAM_GENERIC_ID_ENABLE_ETH, value); @@ -666,6 +612,7 @@ static const struct devlink_param mlx5_devlink_rdma_params[] = { static int mlx5_devlink_rdma_params_register(struct devlink *devlink) { + struct mlx5_core_dev *dev = devlink_priv(devlink); union devlink_param_value value; int err; @@ -677,7 +624,7 @@ static int mlx5_devlink_rdma_params_register(struct devlink *devlink) if (err) return err; - value.vbool = true; + value.vbool = !mlx5_dev_is_lightweight(dev); devl_param_driverinit_value_set(devlink, DEVLINK_PARAM_GENERIC_ID_ENABLE_RDMA, value); @@ -712,7 +659,7 @@ static int mlx5_devlink_vnet_params_register(struct devlink *devlink) if (err) return err; - value.vbool = true; + value.vbool = !mlx5_dev_is_lightweight(dev); devl_param_driverinit_value_set(devlink, DEVLINK_PARAM_GENERIC_ID_ENABLE_VNET, value); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/diag/reporter_vnic.c b/drivers/net/ethernet/mellanox/mlx5/core/diag/reporter_vnic.c index 9114661cd967916abd717abda2ecf5fd68b9d027..b0128336ff01a0028a3d6c8ad524d4f071714a00 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/diag/reporter_vnic.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/diag/reporter_vnic.c @@ -76,6 +76,16 @@ int mlx5_reporter_vnic_diagnose_counters(struct mlx5_core_dev *dev, if (err) return err; + err = devlink_fmsg_u64_pair_put(fmsg, "generated_pkt_steering_fail", + VNIC_ENV_GET64(&vnic, generated_pkt_steering_fail)); + if (err) + return err; + + err = devlink_fmsg_u64_pair_put(fmsg, "handled_pkt_steering_fail", + VNIC_ENV_GET64(&vnic, handled_pkt_steering_fail)); + if (err) + return err; + err = devlink_fmsg_obj_nest_end(fmsg); if (err) return err; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h index 8e999f238194812bb44e5b57e1f3b22cf08c67dd..b1807bfb815f1a43f6c5858d1a3aea5120ecb35b 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h @@ -165,15 +165,6 @@ struct page_pool; #define MLX5E_MAX_KLM_PER_WQE(mdev) \ MLX5E_KLM_ENTRIES_PER_WQE(MLX5_SEND_WQE_BB * mlx5e_get_max_sq_aligned_wqebbs(mdev)) -#define MLX5E_MSG_LEVEL NETIF_MSG_LINK - -#define mlx5e_dbg(mlevel, priv, format, ...) \ -do { \ - if (NETIF_MSG_##mlevel & (priv)->msglevel) \ - netdev_warn(priv->netdev, format, \ - ##__VA_ARGS__); \ -} while (0) - #define mlx5e_state_dereference(priv, p) \ rcu_dereference_protected((p), lockdep_is_held(&(priv)->state_lock)) @@ -594,13 +585,6 @@ struct mlx5e_mpw_info { #define MLX5E_MAX_RX_FRAGS 4 -/* a single cache unit is capable to serve one napi call (for non-striding rq) - * or a MPWQE (for striding rq). - */ -#define MLX5E_CACHE_UNIT (MLX5_MPWRQ_MAX_PAGES_PER_WQE > NAPI_POLL_WEIGHT ? \ - MLX5_MPWRQ_MAX_PAGES_PER_WQE : NAPI_POLL_WEIGHT) -#define MLX5E_CACHE_SIZE (4 * roundup_pow_of_two(MLX5E_CACHE_UNIT)) - struct mlx5e_rq; typedef void (*mlx5e_fp_handle_rx_cqe)(struct mlx5e_rq*, struct mlx5_cqe64*); typedef struct sk_buff * @@ -887,7 +871,6 @@ struct mlx5e_priv { #endif /* priv data path fields - end */ - u32 msglevel; unsigned long state; struct mutex state_lock; /* Protects Interface state */ struct mlx5e_rq drop_rq; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/fs_tt_redirect.c b/drivers/net/ethernet/mellanox/mlx5/core/en/fs_tt_redirect.c index 03cb79adf912f70e703007c888a91cc97f611f37..be83ad9db82a474e5fec76d9af4316492017c271 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/fs_tt_redirect.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/fs_tt_redirect.c @@ -594,7 +594,7 @@ int mlx5e_fs_tt_redirect_any_create(struct mlx5e_flow_steering *fs) err = fs_any_create_table(fs); if (err) - return err; + goto err_free_any; err = fs_any_enable(fs); if (err) @@ -606,8 +606,8 @@ int mlx5e_fs_tt_redirect_any_create(struct mlx5e_flow_steering *fs) err_destroy_table: fs_any_destroy_table(fs_any); - - kfree(fs_any); +err_free_any: mlx5e_fs_set_any(fs, NULL); + kfree(fs_any); return err; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/params.c b/drivers/net/ethernet/mellanox/mlx5/core/en/params.c index 9c94807097cb84463ef7a5b6dfc8b3af416f880a..5ce28ff7685fcedd66994c3cc98340eda7eef513 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/params.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/params.c @@ -732,7 +732,8 @@ static void mlx5e_rx_compute_wqe_bulk_params(struct mlx5e_params *params, static int mlx5e_build_rq_frags_info(struct mlx5_core_dev *mdev, struct mlx5e_params *params, struct mlx5e_xsk_param *xsk, - struct mlx5e_rq_frags_info *info) + struct mlx5e_rq_frags_info *info, + u32 *xdp_frag_size) { u32 byte_count = MLX5E_SW2HW_MTU(params, params->sw_mtu); int frag_size_max = DEFAULT_FRAG_SIZE; @@ -845,6 +846,8 @@ static int mlx5e_build_rq_frags_info(struct mlx5_core_dev *mdev, info->log_num_frags = order_base_2(info->num_frags); + *xdp_frag_size = info->num_frags > 1 && params->xdp_prog ? PAGE_SIZE : 0; + return 0; } @@ -989,7 +992,8 @@ int mlx5e_build_rq_param(struct mlx5_core_dev *mdev, } default: /* MLX5_WQ_TYPE_CYCLIC */ MLX5_SET(wq, wq, log_wq_sz, params->log_rq_mtu_frames); - err = mlx5e_build_rq_frags_info(mdev, params, xsk, ¶m->frags_info); + err = mlx5e_build_rq_frags_info(mdev, params, xsk, ¶m->frags_info, + ¶m->xdp_frag_size); if (err) return err; ndsegs = param->frags_info.num_frags; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/params.h b/drivers/net/ethernet/mellanox/mlx5/core/en/params.h index a5d20f6d6d9c703c8828f4c11f4d19be86a688f9..6800949dafbc99b0b530ec9d8dcda89179dd1e1e 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/params.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/params.h @@ -24,6 +24,7 @@ struct mlx5e_rq_param { u32 rqc[MLX5_ST_SZ_DW(rqc)]; struct mlx5_wq_param wq; struct mlx5e_rq_frags_info frags_info; + u32 xdp_frag_size; }; struct mlx5e_sq_param { diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c b/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c index 7e8e96cc5cd083e220e36334dd499220f2ed542a..8e25f4ef5cccee6147db730c8eabf263f0d406de 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c @@ -65,12 +65,13 @@ int mlx5e_port_query_buffer(struct mlx5e_priv *priv, MLX5_GET(bufferx_reg, buffer, xoff_threshold) * port_buff_cell_sz; total_used += port_buffer->buffer[i].size; - mlx5e_dbg(HW, priv, "buffer %d: size=%d, xon=%d, xoff=%d, epsb=%d, lossy=%d\n", i, - port_buffer->buffer[i].size, - port_buffer->buffer[i].xon, - port_buffer->buffer[i].xoff, - port_buffer->buffer[i].epsb, - port_buffer->buffer[i].lossy); + netdev_dbg(priv->netdev, "buffer %d: size=%d, xon=%d, xoff=%d, epsb=%d, lossy=%d\n", + i, + port_buffer->buffer[i].size, + port_buffer->buffer[i].xon, + port_buffer->buffer[i].xoff, + port_buffer->buffer[i].epsb, + port_buffer->buffer[i].lossy); } port_buffer->internal_buffers_size = 0; @@ -87,11 +88,11 @@ int mlx5e_port_query_buffer(struct mlx5e_priv *priv, port_buffer->internal_buffers_size - port_buffer->headroom_size; - mlx5e_dbg(HW, priv, - "total buffer size=%u, headroom buffer size=%u, internal buffers size=%u, spare buffer size=%u\n", - port_buffer->port_buffer_size, port_buffer->headroom_size, - port_buffer->internal_buffers_size, - port_buffer->spare_buffer_size); + netdev_dbg(priv->netdev, + "total buffer size=%u, headroom buffer size=%u, internal buffers size=%u, spare buffer size=%u\n", + port_buffer->port_buffer_size, port_buffer->headroom_size, + port_buffer->internal_buffers_size, + port_buffer->spare_buffer_size); out: kfree(out); return err; @@ -352,7 +353,7 @@ static u32 calculate_xoff(struct mlx5e_priv *priv, unsigned int mtu) xoff = (301 + 216 * priv->dcbx.cable_len / 100) * speed / 1000 + 272 * mtu / 100; - mlx5e_dbg(HW, priv, "%s: xoff=%d\n", __func__, xoff); + netdev_dbg(priv->netdev, "%s: xoff=%d\n", __func__, xoff); return xoff; } @@ -484,6 +485,7 @@ int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv, u8 *prio2buffer) { u16 port_buff_cell_sz = priv->dcbx.port_buff_cell_sz; + struct net_device *netdev = priv->netdev; struct mlx5e_port_buffer port_buffer; u32 xoff = calculate_xoff(priv, mtu); bool update_prio2buffer = false; @@ -495,7 +497,7 @@ int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv, int err; int i; - mlx5e_dbg(HW, priv, "%s: change=%x\n", __func__, change); + netdev_dbg(netdev, "%s: change=%x\n", __func__, change); max_mtu = max_t(unsigned int, priv->netdev->max_mtu, MINIMUM_MAX_MTU); err = mlx5e_port_query_buffer(priv, &port_buffer); @@ -510,8 +512,8 @@ int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv, } if (change & MLX5E_PORT_BUFFER_PFC) { - mlx5e_dbg(HW, priv, "%s: requested PFC per priority bitmask: 0x%x\n", - __func__, pfc->pfc_en); + netdev_dbg(netdev, "%s: requested PFC per priority bitmask: 0x%x\n", + __func__, pfc->pfc_en); err = mlx5e_port_query_priority2buffer(priv->mdev, buffer); if (err) return err; @@ -526,8 +528,8 @@ int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv, if (change & MLX5E_PORT_BUFFER_PRIO2BUFFER) { update_prio2buffer = true; for (i = 0; i < MLX5E_MAX_NETWORK_BUFFER; i++) - mlx5e_dbg(HW, priv, "%s: requested to map prio[%d] to buffer %d\n", - __func__, i, prio2buffer[i]); + netdev_dbg(priv->netdev, "%s: requested to map prio[%d] to buffer %d\n", + __func__, i, prio2buffer[i]); err = fill_pfc_en(priv->mdev, &curr_pfc_en); if (err) @@ -541,10 +543,10 @@ int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv, if (change & MLX5E_PORT_BUFFER_SIZE) { for (i = 0; i < MLX5E_MAX_NETWORK_BUFFER; i++) { - mlx5e_dbg(HW, priv, "%s: buffer[%d]=%d\n", __func__, i, buffer_size[i]); + netdev_dbg(priv->netdev, "%s: buffer[%d]=%d\n", __func__, i, buffer_size[i]); if (!port_buffer.buffer[i].lossy && !buffer_size[i]) { - mlx5e_dbg(HW, priv, "%s: lossless buffer[%d] size cannot be zero\n", - __func__, i); + netdev_dbg(priv->netdev, "%s: lossless buffer[%d] size cannot be zero\n", + __func__, i); return -EINVAL; } @@ -552,7 +554,7 @@ int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv, total_used += buffer_size[i]; } - mlx5e_dbg(HW, priv, "%s: total buffer requested=%d\n", __func__, total_used); + netdev_dbg(priv->netdev, "%s: total buffer requested=%d\n", __func__, total_used); if (total_used > port_buffer.headroom_size && (total_used - port_buffer.headroom_size) > diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/ptp.c b/drivers/net/ethernet/mellanox/mlx5/core/en/ptp.c index 3cbebfba582bdbce79741c4c7d798dd13846af64..b0b429a0321edeb97db2d986b86c5f28c6be1a3e 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/ptp.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/ptp.c @@ -729,8 +729,10 @@ int mlx5e_ptp_open(struct mlx5e_priv *priv, struct mlx5e_params *params, c = kvzalloc_node(sizeof(*c), GFP_KERNEL, dev_to_node(mlx5_core_dma_dev(mdev))); cparams = kvzalloc(sizeof(*cparams), GFP_KERNEL); - if (!c || !cparams) - return -ENOMEM; + if (!c || !cparams) { + err = -ENOMEM; + goto err_free; + } c->priv = priv; c->mdev = priv->mdev; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/qos.c b/drivers/net/ethernet/mellanox/mlx5/core/en/qos.c index 2842195ee548adf5a464c2a1fd7429114360cb4e..1874c2f0587f414cc6450f2b87c341a32005e77d 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/qos.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/qos.c @@ -379,6 +379,12 @@ int mlx5e_htb_setup_tc(struct mlx5e_priv *priv, struct tc_htb_qopt_offload *htb_ if (!htb && htb_qopt->command != TC_HTB_CREATE) return -EINVAL; + if (htb_qopt->prio) { + NL_SET_ERR_MSG_MOD(htb_qopt->extack, + "prio parameter is not supported by device with HTB offload enabled."); + return -EOPNOTSUPP; + } + switch (htb_qopt->command) { case TC_HTB_CREATE: if (!mlx5_qos_is_supported(priv->mdev)) { @@ -515,4 +521,3 @@ int mlx5e_mqprio_rl_get_node_hw_id(struct mlx5e_mqprio_rl *rl, int tc, u32 *hw_i *hw_id = rl->leaves_id[tc]; return 0; } - diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/rep/bridge.c b/drivers/net/ethernet/mellanox/mlx5/core/en/rep/bridge.c index fd191925ab4b0f89dbbe0b9789ac63ce2b92b185..5608002465734d4dfb6da83248f6bae817fd59a4 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/rep/bridge.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/rep/bridge.c @@ -136,7 +136,6 @@ static int mlx5_esw_bridge_port_changeupper(struct notifier_block *nb, void *ptr struct mlx5_eswitch *esw = br_offloads->esw; u16 vport_num, esw_owner_vhca_id; struct netlink_ext_ack *extack; - int ifindex = upper->ifindex; int err = 0; if (!netif_is_bridge_master(upper)) @@ -150,15 +149,15 @@ static int mlx5_esw_bridge_port_changeupper(struct notifier_block *nb, void *ptr if (mlx5_esw_bridge_is_local(dev, rep, esw)) err = info->linking ? - mlx5_esw_bridge_vport_link(ifindex, vport_num, esw_owner_vhca_id, + mlx5_esw_bridge_vport_link(upper, vport_num, esw_owner_vhca_id, br_offloads, extack) : - mlx5_esw_bridge_vport_unlink(ifindex, vport_num, esw_owner_vhca_id, + mlx5_esw_bridge_vport_unlink(upper, vport_num, esw_owner_vhca_id, br_offloads, extack); else if (mlx5_esw_bridge_dev_same_hw(rep, esw)) err = info->linking ? - mlx5_esw_bridge_vport_peer_link(ifindex, vport_num, esw_owner_vhca_id, + mlx5_esw_bridge_vport_peer_link(upper, vport_num, esw_owner_vhca_id, br_offloads, extack) : - mlx5_esw_bridge_vport_peer_unlink(ifindex, vport_num, esw_owner_vhca_id, + mlx5_esw_bridge_vport_peer_unlink(upper, vport_num, esw_owner_vhca_id, br_offloads, extack); return err; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc/act_stats.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc/act_stats.c index 07c1895a2b23414f2a9b5bf5e1454757951624c3..7aa926e542d32a31becaa00c9d94f3c2b74983dc 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc/act_stats.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc/act_stats.c @@ -25,8 +25,8 @@ struct mlx5e_tc_act_stats { static const struct rhashtable_params act_counters_ht_params = { .head_offset = offsetof(struct mlx5e_tc_act_stats, hash), - .key_offset = 0, - .key_len = offsetof(struct mlx5e_tc_act_stats, counter), + .key_offset = offsetof(struct mlx5e_tc_act_stats, tc_act_cookie), + .key_len = sizeof_field(struct mlx5e_tc_act_stats, tc_act_cookie), .automatic_shrinking = true, }; @@ -169,14 +169,11 @@ mlx5e_tc_act_stats_fill_stats(struct mlx5e_tc_act_stats_handle *handle, { struct rhashtable *ht = &handle->ht; struct mlx5e_tc_act_stats *item; - struct mlx5e_tc_act_stats key; u64 pkts, bytes, lastused; int err = 0; - key.tc_act_cookie = fl_act->cookie; - rcu_read_lock(); - item = rhashtable_lookup(ht, &key, act_counters_ht_params); + item = rhashtable_lookup(ht, &fl_act->cookie, act_counters_ht_params); if (!item) { rcu_read_unlock(); err = -ENOENT; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc/post_act.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc/post_act.c index 0290e0dea53903c27c90a240b28746c6f208ffce..4e923a2874aefe089faa454dc4c8f04e4e776b3f 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc/post_act.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc/post_act.c @@ -112,10 +112,8 @@ mlx5e_tc_post_act_add(struct mlx5e_post_act *post_act, struct mlx5_flow_attr *po int err; handle = kzalloc(sizeof(*handle), GFP_KERNEL); - if (!handle) { - kfree(handle); + if (!handle) return ERR_PTR(-ENOMEM); - } post_attr->chain = 0; post_attr->prio = 0; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c index ead38ef6948313dd96366ac70c1d2d1f0c7cf0c3..fadfa8b50bebeb027f96554b37a59add2bef3264 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c @@ -1545,7 +1545,8 @@ mlx5_tc_ct_parse_action(struct mlx5_tc_ct_priv *priv, attr->ct_attr.ct_action |= act->ct.action; /* So we can have clear + ct */ attr->ct_attr.zone = act->ct.zone; - attr->ct_attr.nf_ft = act->ct.flow_table; + if (!(act->ct.action & TCA_CT_ACT_CLEAR)) + attr->ct_attr.nf_ft = act->ct.flow_table; attr->ct_attr.act_miss_cookie = act->miss_cookie; return 0; @@ -1990,6 +1991,9 @@ mlx5_tc_ct_flow_offload(struct mlx5_tc_ct_priv *priv, struct mlx5_flow_attr *att if (!priv) return -EOPNOTSUPP; + if (attr->ct_attr.offloaded) + return 0; + if (attr->ct_attr.ct_action & TCA_CT_ACT_CLEAR) { err = mlx5_tc_ct_entry_set_registers(priv, &attr->parse_attr->mod_hdr_acts, 0, 0, 0, 0); @@ -1999,11 +2003,15 @@ mlx5_tc_ct_flow_offload(struct mlx5_tc_ct_priv *priv, struct mlx5_flow_attr *att attr->action |= MLX5_FLOW_CONTEXT_ACTION_MOD_HDR; } - if (!attr->ct_attr.nf_ft) /* means only ct clear action, and not ct_clear,ct() */ + if (!attr->ct_attr.nf_ft) { /* means only ct clear action, and not ct_clear,ct() */ + attr->ct_attr.offloaded = true; return 0; + } mutex_lock(&priv->control_lock); err = __mlx5_tc_ct_flow_offload(priv, attr); + if (!err) + attr->ct_attr.offloaded = true; mutex_unlock(&priv->control_lock); return err; @@ -2021,6 +2029,8 @@ void mlx5_tc_ct_delete_flow(struct mlx5_tc_ct_priv *priv, struct mlx5_flow_attr *attr) { + if (!attr->ct_attr.offloaded) /* no ct action, return */ + return; if (!attr->ct_attr.nf_ft) /* means only ct clear action, and not ct_clear,ct() */ return; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.h b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.h index 8e9316fa46d4b5413361dc6b66b197bfcb8a30c2..b66c5f98067f716306147d7ba31c8e6c6db894b2 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.h @@ -29,6 +29,7 @@ struct mlx5_ct_attr { u32 ct_labels_id; u32 act_miss_mapping; u64 act_miss_cookie; + bool offloaded; struct mlx5_ct_ft *ft; }; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_priv.h b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_priv.h index ba2b1f24ff14ad7aefb3ca230738418a6e7f08ea..6cc23af66b5be0d9e31c63dcac6e85214a5fe075 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_priv.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_priv.h @@ -94,13 +94,13 @@ struct mlx5e_tc_flow { * destinations. */ struct encap_flow_item encaps[MLX5_MAX_FLOW_FWD_VPORTS]; - struct mlx5e_tc_flow *peer_flow; struct mlx5e_hairpin_entry *hpe; /* attached hairpin instance */ struct list_head hairpin; /* flows sharing the same hairpin */ - struct list_head peer; /* flows with peer flow */ + struct list_head peer[MLX5_MAX_PORTS]; /* flows with peer flow */ struct list_head unready; /* flows not ready to be offloaded (e.g * due to missing route) */ + struct list_head peer_flows; /* flows on peer */ struct net_device *orig_dev; /* netdev adding flow first */ int tmp_entry_index; struct list_head tmp_list; /* temporary flow list used by neigh update */ diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c b/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c index f0e6095809faf1c053b1bd77902407dc24aa78ee..40589cebb773002739746987f3d1089d76de2ffb 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c @@ -662,8 +662,7 @@ static void mlx5e_free_xdpsq_desc(struct mlx5e_xdpsq *sq, /* No need to check ((page->pp_magic & ~0x3UL) == PP_SIGNATURE) * as we know this is a page_pool page. */ - page_pool_put_defragged_page(page->pp, - page, -1, true); + page_pool_recycle_direct(page->pp, page); } while (++n < num); break; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/xsk/setup.c b/drivers/net/ethernet/mellanox/mlx5/core/en/xsk/setup.c index ed279f4509761b5b3acd298d35477e83bd248647..36826b58248478a4150818093ab29b4e04574c01 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/xsk/setup.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/xsk/setup.c @@ -86,7 +86,7 @@ static int mlx5e_init_xsk_rq(struct mlx5e_channel *c, if (err) return err; - return xdp_rxq_info_reg(&rq->xdp_rxq, rq->netdev, rq_xdp_ix, 0); + return xdp_rxq_info_reg(&rq->xdp_rxq, rq->netdev, rq_xdp_ix, c->napi.napi_id); } static int mlx5e_open_xsk_rq(struct mlx5e_channel *c, struct mlx5e_params *params, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/en_accel.h b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/en_accel.h index c964644ee866e765480f2746d5441a8a103a64be..bac4717548c67e9e6ac900929de542e1b19b6bdf 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/en_accel.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/en_accel.h @@ -125,7 +125,7 @@ static inline bool mlx5e_accel_tx_begin(struct net_device *dev, #ifdef CONFIG_MLX5_EN_TLS /* May send WQEs. */ - if (mlx5e_ktls_skb_offloaded(skb)) + if (tls_is_skb_tx_device_offloaded(skb)) if (unlikely(!mlx5e_ktls_handle_tx_skb(dev, sq, skb, &state->tls))) return false; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/fs_tcp.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/fs_tcp.c index 88a5aed9d678100bb8bf10097c7df4504f62358b..c7d191f66ad1bc40c8dcab2eaeda82c230b61027 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/fs_tcp.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/fs_tcp.c @@ -190,6 +190,7 @@ static int accel_fs_tcp_create_groups(struct mlx5e_flow_table *ft, in = kvzalloc(inlen, GFP_KERNEL); if (!in || !ft->g) { kfree(ft->g); + ft->g = NULL; kvfree(in); return -ENOMEM; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c index 55b38544422f3e11365c94d103d83dd321dc4faf..891d39b4bfd4f77fc68357990ce36ecf54cb1ff4 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c @@ -61,16 +61,19 @@ static void mlx5e_ipsec_handle_tx_limit(struct work_struct *_work) struct mlx5e_ipsec_sa_entry *sa_entry = dwork->sa_entry; struct xfrm_state *x = sa_entry->x; - spin_lock(&x->lock); + if (sa_entry->attrs.drop) + return; + + spin_lock_bh(&x->lock); xfrm_state_check_expire(x); if (x->km.state == XFRM_STATE_EXPIRED) { sa_entry->attrs.drop = true; - mlx5e_accel_ipsec_fs_modify(sa_entry); - } - spin_unlock(&x->lock); + spin_unlock_bh(&x->lock); - if (sa_entry->attrs.drop) + mlx5e_accel_ipsec_fs_modify(sa_entry); return; + } + spin_unlock_bh(&x->lock); queue_delayed_work(sa_entry->ipsec->wq, &dwork->dwork, MLX5_IPSEC_RESCHED); @@ -1040,11 +1043,17 @@ static int mlx5e_xfrm_add_policy(struct xfrm_policy *x, return err; } -static void mlx5e_xfrm_free_policy(struct xfrm_policy *x) +static void mlx5e_xfrm_del_policy(struct xfrm_policy *x) { struct mlx5e_ipsec_pol_entry *pol_entry = to_ipsec_pol_entry(x); mlx5e_accel_ipsec_fs_del_pol(pol_entry); +} + +static void mlx5e_xfrm_free_policy(struct xfrm_policy *x) +{ + struct mlx5e_ipsec_pol_entry *pol_entry = to_ipsec_pol_entry(x); + kfree(pol_entry); } @@ -1065,6 +1074,7 @@ static const struct xfrmdev_ops mlx5e_ipsec_packet_xfrmdev_ops = { .xdo_dev_state_update_curlft = mlx5e_xfrm_update_curlft, .xdo_dev_policy_add = mlx5e_xfrm_add_policy, + .xdo_dev_policy_delete = mlx5e_xfrm_del_policy, .xdo_dev_policy_free = mlx5e_xfrm_free_policy, }; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_offload.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_offload.c index df90e19066bcc58085373d58342a83e708a82e8f..a3554bde3e0758deaa7c9a4e03a133fabc9db84e 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_offload.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_offload.c @@ -305,7 +305,17 @@ static void mlx5e_ipsec_update_esn_state(struct mlx5e_ipsec_sa_entry *sa_entry, } mlx5e_ipsec_build_accel_xfrm_attrs(sa_entry, &attrs); + + /* It is safe to execute the modify below unlocked since the only flows + * that could affect this HW object, are create, destroy and this work. + * + * Creation flow can't co-exist with this modify work, the destruction + * flow would cancel this work, and this work is a single entity that + * can't conflict with it self. + */ + spin_unlock_bh(&sa_entry->x->lock); mlx5_accel_esp_modify_xfrm(sa_entry, &attrs); + spin_lock_bh(&sa_entry->x->lock); data.data_offset_condition_operand = MLX5_IPSEC_ASO_REMOVE_FLOW_PKT_CNT_OFFSET; @@ -431,7 +441,7 @@ static void mlx5e_ipsec_handle_event(struct work_struct *_work) aso = sa_entry->ipsec->aso; attrs = &sa_entry->attrs; - spin_lock(&sa_entry->x->lock); + spin_lock_bh(&sa_entry->x->lock); ret = mlx5e_ipsec_aso_query(sa_entry, NULL); if (ret) goto unlock; @@ -447,7 +457,7 @@ static void mlx5e_ipsec_handle_event(struct work_struct *_work) mlx5e_ipsec_handle_limits(sa_entry); unlock: - spin_unlock(&sa_entry->x->lock); + spin_unlock_bh(&sa_entry->x->lock); kfree(work); } @@ -596,7 +606,8 @@ int mlx5e_ipsec_aso_query(struct mlx5e_ipsec_sa_entry *sa_entry, do { ret = mlx5_aso_poll_cq(aso->aso, false); if (ret) - usleep_range(2, 10); + /* We are in atomic context */ + udelay(10); } while (ret && time_is_after_jiffies(expires)); spin_unlock_bh(&aso->lock); return ret; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_tx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_tx.c index 0e4c0a093293a7e8872a7c751bfd8d5373f80935..efb2cf74ad6a3ab2bc853b519175ed76f55fd1e2 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_tx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_tx.c @@ -846,7 +846,7 @@ bool mlx5e_ktls_handle_tx_skb(struct net_device *netdev, struct mlx5e_txqsq *sq, tls_ctx = tls_get_ctx(skb->sk); tls_netdev = rcu_dereference_bh(tls_ctx->netdev); /* Don't WARN on NULL: if tls_device_down is running in parallel, - * netdev might become NULL, even if tls_is_sk_tx_device_offloaded was + * netdev might become NULL, even if tls_is_skb_tx_device_offloaded was * true. Rather continue processing this packet. */ if (WARN_ON_ONCE(tls_netdev && tls_netdev != netdev)) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_txrx.h b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_txrx.h index 2dd78dd4ad65ba0eeb0b683d71d3ebe71f7f7dec..f87b65c560ea68ef764139d1039286c1a350efa1 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_txrx.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_txrx.h @@ -49,11 +49,6 @@ mlx5e_ktls_rx_pending_resync_list(struct mlx5e_channel *c, int budget) return budget && test_bit(MLX5E_SQ_STATE_PENDING_TLS_RX_RESYNC, &c->async_icosq.state); } -static inline bool mlx5e_ktls_skb_offloaded(struct sk_buff *skb) -{ - return skb->sk && tls_is_sk_tx_device_offloaded(skb->sk); -} - static inline void mlx5e_ktls_handle_tx_wqe(struct mlx5_wqe_ctrl_seg *cseg, struct mlx5e_accel_tx_tls_state *state) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c index 6b7b563f844a1f03d7288088b9989a7aa70c113b..592b165530ffa376031f19fa54736b345f9fc612 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c @@ -349,15 +349,6 @@ static void mlx5e_macsec_cleanup_sa(struct mlx5e_macsec *macsec, sa->macsec_rule = NULL; } -static struct mlx5e_priv *macsec_netdev_priv(const struct net_device *dev) -{ -#if IS_ENABLED(CONFIG_VLAN_8021Q) - if (is_vlan_dev(dev)) - return netdev_priv(vlan_dev_priv(dev)->real_dev); -#endif - return netdev_priv(dev); -} - static int mlx5e_macsec_init_sa(struct macsec_context *ctx, struct mlx5e_macsec_sa *sa, bool encrypt, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c b/drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c index bed0c2d043e70b9a58540b69a9c421352b366021..933a7772a7a396728f6eb27790896f69ede981f7 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c @@ -570,10 +570,10 @@ static struct mlx5_flow_handle *arfs_add_rule(struct mlx5e_priv *priv, if (IS_ERR(rule)) { err = PTR_ERR(rule); priv->channel_stats[arfs_rule->rxq]->rq.arfs_err++; - mlx5e_dbg(HW, priv, - "%s: add rule(filter id=%d, rq idx=%d, ip proto=0x%x) failed,err=%d\n", - __func__, arfs_rule->filter_id, arfs_rule->rxq, - tuple->ip_proto, err); + netdev_dbg(priv->netdev, + "%s: add rule(filter id=%d, rq idx=%d, ip proto=0x%x) failed,err=%d\n", + __func__, arfs_rule->filter_id, arfs_rule->rxq, + tuple->ip_proto, err); } out: diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c index ebee52a8361aa7f7102683c4d62dbc4571ed1a71..8705cffc747ffbaeb08186fde904c5f30fbab438 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c @@ -275,10 +275,10 @@ static int mlx5e_dcbnl_ieee_setets_core(struct mlx5e_priv *priv, struct ieee_ets memcpy(priv->dcbx.tc_tsa, ets->tc_tsa, sizeof(ets->tc_tsa)); for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) { - mlx5e_dbg(HW, priv, "%s: prio_%d <=> tc_%d\n", - __func__, i, ets->prio_tc[i]); - mlx5e_dbg(HW, priv, "%s: tc_%d <=> tx_bw_%d%%, group_%d\n", - __func__, i, tc_tx_bw[i], tc_group[i]); + netdev_dbg(priv->netdev, "%s: prio_%d <=> tc_%d\n", + __func__, i, ets->prio_tc[i]); + netdev_dbg(priv->netdev, "%s: tc_%d <=> tx_bw_%d%%, group_%d\n", + __func__, i, tc_tx_bw[i], tc_group[i]); } return err; @@ -399,9 +399,9 @@ static int mlx5e_dcbnl_ieee_setpfc(struct net_device *dev, } if (!ret) { - mlx5e_dbg(HW, priv, - "%s: PFC per priority bit mask: 0x%x\n", - __func__, pfc->pfc_en); + netdev_dbg(dev, + "%s: PFC per priority bit mask: 0x%x\n", + __func__, pfc->pfc_en); } return ret; } @@ -611,8 +611,8 @@ static int mlx5e_dcbnl_ieee_setmaxrate(struct net_device *netdev, } for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) { - mlx5e_dbg(HW, priv, "%s: tc_%d <=> max_bw %d Gbps\n", - __func__, i, max_bw_value[i]); + netdev_dbg(netdev, "%s: tc_%d <=> max_bw %d Gbps\n", + __func__, i, max_bw_value[i]); } return mlx5_modify_port_ets_rate_limit(mdev, max_bw_value, max_bw_unit); @@ -640,10 +640,10 @@ static u8 mlx5e_dcbnl_setall(struct net_device *netdev) ets.tc_rx_bw[i] = cee_cfg->pg_bw_pct[i]; ets.tc_tsa[i] = IEEE_8021QAZ_TSA_ETS; ets.prio_tc[i] = cee_cfg->prio_to_pg_map[i]; - mlx5e_dbg(HW, priv, - "%s: Priority group %d: tx_bw %d, rx_bw %d, prio_tc %d\n", - __func__, i, ets.tc_tx_bw[i], ets.tc_rx_bw[i], - ets.prio_tc[i]); + netdev_dbg(netdev, + "%s: Priority group %d: tx_bw %d, rx_bw %d, prio_tc %d\n", + __func__, i, ets.tc_tx_bw[i], ets.tc_rx_bw[i], + ets.prio_tc[i]); } err = mlx5e_dbcnl_validate_ets(netdev, &ets, true); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c index 1f5a2110d31f59b2844cf79c30885d6a81b3137a..27861b68ced57aa44c25f6bd144f04695a345ada 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c @@ -1689,16 +1689,6 @@ static int mlx5e_set_fecparam(struct net_device *netdev, return 0; } -static u32 mlx5e_get_msglevel(struct net_device *dev) -{ - return ((struct mlx5e_priv *)netdev_priv(dev))->msglevel; -} - -static void mlx5e_set_msglevel(struct net_device *dev, u32 val) -{ - ((struct mlx5e_priv *)netdev_priv(dev))->msglevel = val; -} - static int mlx5e_set_phys_id(struct net_device *dev, enum ethtool_phys_id_state state) { @@ -1952,9 +1942,9 @@ int mlx5e_modify_rx_cqe_compression_locked(struct mlx5e_priv *priv, bool new_val if (err) return err; - mlx5e_dbg(DRV, priv, "MLX5E: RxCqeCmprss was turned %s\n", - MLX5E_GET_PFLAG(&priv->channels.params, - MLX5E_PFLAG_RX_CQE_COMPRESS) ? "ON" : "OFF"); + netdev_dbg(priv->netdev, "MLX5E: RxCqeCmprss was turned %s\n", + MLX5E_GET_PFLAG(&priv->channels.params, + MLX5E_PFLAG_RX_CQE_COMPRESS) ? "ON" : "OFF"); return 0; } @@ -2444,8 +2434,6 @@ const struct ethtool_ops mlx5e_ethtool_ops = { .get_priv_flags = mlx5e_get_priv_flags, .set_priv_flags = mlx5e_set_priv_flags, .self_test = mlx5e_self_test, - .get_msglevel = mlx5e_get_msglevel, - .set_msglevel = mlx5e_set_msglevel, .get_fec_stats = mlx5e_get_fec_stats, .get_fecparam = mlx5e_get_fecparam, .set_fecparam = mlx5e_set_fecparam, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c b/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c index 33bfe4d7338be9f3400e68d73689e560822f56a1..934b0d5ce1b3f524dd715983132ea1cd960301d5 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c @@ -283,7 +283,7 @@ static int __mlx5e_add_vlan_rule(struct mlx5e_flow_steering *fs, if (IS_ERR(*rule_p)) { err = PTR_ERR(*rule_p); *rule_p = NULL; - fs_err(fs, "%s: add rule failed\n", __func__); + fs_err(fs, "add rule failed\n"); } return err; @@ -395,8 +395,7 @@ int mlx5e_add_vlan_trap(struct mlx5e_flow_steering *fs, int trap_id, int tir_num if (IS_ERR(rule)) { err = PTR_ERR(rule); fs->vlan->trap_rule = NULL; - fs_err(fs, "%s: add VLAN trap rule failed, err %d\n", - __func__, err); + fs_err(fs, "add VLAN trap rule failed, err %d\n", err); return err; } fs->vlan->trap_rule = rule; @@ -421,8 +420,7 @@ int mlx5e_add_mac_trap(struct mlx5e_flow_steering *fs, int trap_id, int tir_num) if (IS_ERR(rule)) { err = PTR_ERR(rule); fs->l2.trap_rule = NULL; - fs_err(fs, "%s: add MAC trap rule failed, err %d\n", - __func__, err); + fs_err(fs, "add MAC trap rule failed, err %d\n", err); return err; } fs->l2.trap_rule = rule; @@ -763,7 +761,7 @@ static int mlx5e_add_promisc_rule(struct mlx5e_flow_steering *fs) if (IS_ERR(*rule_p)) { err = PTR_ERR(*rule_p); *rule_p = NULL; - fs_err(fs, "%s: add promiscuous rule failed\n", __func__); + fs_err(fs, "add promiscuous rule failed\n"); } kvfree(spec); return err; @@ -995,7 +993,7 @@ static int mlx5e_add_l2_flow_rule(struct mlx5e_flow_steering *fs, ai->rule = mlx5_add_flow_rules(ft, spec, &flow_act, &dest, 1); if (IS_ERR(ai->rule)) { - fs_err(fs, "%s: add l2 rule(mac:%pM) failed\n", __func__, mv_dmac); + fs_err(fs, "add l2 rule(mac:%pM) failed\n", mv_dmac); err = PTR_ERR(ai->rule); ai->rule = NULL; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index a7c526ee5024748097a39abf2f718c0e9ea28f9d..defb1efccb78fa5ee067eb7ed2ce8cdd2a603040 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -641,7 +641,7 @@ static void mlx5e_free_mpwqe_rq_drop_page(struct mlx5e_rq *rq) } static int mlx5e_init_rxq_rq(struct mlx5e_channel *c, struct mlx5e_params *params, - struct mlx5e_rq *rq) + u32 xdp_frag_size, struct mlx5e_rq *rq) { struct mlx5_core_dev *mdev = c->mdev; int err; @@ -665,7 +665,8 @@ static int mlx5e_init_rxq_rq(struct mlx5e_channel *c, struct mlx5e_params *param if (err) return err; - return xdp_rxq_info_reg(&rq->xdp_rxq, rq->netdev, rq->ix, c->napi.napi_id); + return __xdp_rxq_info_reg(&rq->xdp_rxq, rq->netdev, rq->ix, c->napi.napi_id, + xdp_frag_size); } static int mlx5_rq_shampo_alloc(struct mlx5_core_dev *mdev, @@ -2240,7 +2241,7 @@ static int mlx5e_open_rxq_rq(struct mlx5e_channel *c, struct mlx5e_params *param { int err; - err = mlx5e_init_rxq_rq(c, params, &c->rq); + err = mlx5e_init_rxq_rq(c, params, rq_params->xdp_frag_size, &c->rq); if (err) return err; @@ -2401,7 +2402,7 @@ static int mlx5e_channel_stats_alloc(struct mlx5e_priv *priv, int ix, int cpu) /* Asymmetric dynamic memory allocation. * Freed in mlx5e_priv_arrays_free, not on channel closure. */ - mlx5e_dbg(DRV, priv, "Creating channel stats %d\n", ix); + netdev_dbg(priv->netdev, "Creating channel stats %d\n", ix); priv->channel_stats[ix] = kvzalloc_node(sizeof(**priv->channel_stats), GFP_KERNEL, cpu_to_node(cpu)); if (!priv->channel_stats[ix]) @@ -2779,7 +2780,7 @@ int mlx5e_update_tx_netdev_queues(struct mlx5e_priv *priv) if (MLX5E_GET_PFLAG(&priv->channels.params, MLX5E_PFLAG_TX_PORT_TS)) num_txqs += ntc; - mlx5e_dbg(DRV, priv, "Setting num_txqs %d\n", num_txqs); + netdev_dbg(priv->netdev, "Setting num_txqs %d\n", num_txqs); err = netif_set_real_num_tx_queues(priv->netdev, num_txqs); if (err) netdev_warn(priv->netdev, "netif_set_real_num_tx_queues failed, %d\n", err); @@ -5585,7 +5586,6 @@ int mlx5e_priv_init(struct mlx5e_priv *priv, /* priv init */ priv->mdev = mdev; priv->netdev = netdev; - priv->msglevel = MLX5E_MSG_LEVEL; priv->max_nch = nch; priv->max_opened_tc = 1; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c index 3e7041bd5705e8761258d3513c5bc358a602cf68..152b62138450f9855578489a43e047a351978349 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c @@ -374,7 +374,9 @@ static void mlx5e_sqs2vport_stop(struct mlx5_eswitch *esw, struct mlx5_eswitch_rep *rep) { struct mlx5e_rep_sq *rep_sq, *tmp; + struct mlx5e_rep_sq_peer *sq_peer; struct mlx5e_rep_priv *rpriv; + unsigned long i; if (esw->mode != MLX5_ESWITCH_OFFLOADS) return; @@ -382,31 +384,78 @@ static void mlx5e_sqs2vport_stop(struct mlx5_eswitch *esw, rpriv = mlx5e_rep_to_rep_priv(rep); list_for_each_entry_safe(rep_sq, tmp, &rpriv->vport_sqs_list, list) { mlx5_eswitch_del_send_to_vport_rule(rep_sq->send_to_vport_rule); - if (rep_sq->send_to_vport_rule_peer) - mlx5_eswitch_del_send_to_vport_rule(rep_sq->send_to_vport_rule_peer); + xa_for_each(&rep_sq->sq_peer, i, sq_peer) { + if (sq_peer->rule) + mlx5_eswitch_del_send_to_vport_rule(sq_peer->rule); + + xa_erase(&rep_sq->sq_peer, i); + kfree(sq_peer); + } + + xa_destroy(&rep_sq->sq_peer); list_del(&rep_sq->list); kfree(rep_sq); } } +static int mlx5e_sqs2vport_add_peers_rules(struct mlx5_eswitch *esw, struct mlx5_eswitch_rep *rep, + struct mlx5_devcom *devcom, + struct mlx5e_rep_sq *rep_sq, int i) +{ + struct mlx5_eswitch *peer_esw = NULL; + struct mlx5_flow_handle *flow_rule; + int tmp; + + mlx5_devcom_for_each_peer_entry(devcom, MLX5_DEVCOM_ESW_OFFLOADS, + peer_esw, tmp) { + u16 peer_rule_idx = MLX5_CAP_GEN(peer_esw->dev, vhca_id); + struct mlx5e_rep_sq_peer *sq_peer; + int err; + + sq_peer = kzalloc(sizeof(*sq_peer), GFP_KERNEL); + if (!sq_peer) + return -ENOMEM; + + flow_rule = mlx5_eswitch_add_send_to_vport_rule(peer_esw, esw, + rep, rep_sq->sqn); + if (IS_ERR(flow_rule)) { + kfree(sq_peer); + return PTR_ERR(flow_rule); + } + + sq_peer->rule = flow_rule; + sq_peer->peer = peer_esw; + err = xa_insert(&rep_sq->sq_peer, peer_rule_idx, sq_peer, GFP_KERNEL); + if (err) { + kfree(sq_peer); + mlx5_eswitch_del_send_to_vport_rule(flow_rule); + return err; + } + } + + return 0; +} + static int mlx5e_sqs2vport_start(struct mlx5_eswitch *esw, struct mlx5_eswitch_rep *rep, u32 *sqns_array, int sqns_num) { - struct mlx5_eswitch *peer_esw = NULL; struct mlx5_flow_handle *flow_rule; struct mlx5e_rep_priv *rpriv; struct mlx5e_rep_sq *rep_sq; + struct mlx5_devcom *devcom; + bool devcom_locked = false; int err; int i; if (esw->mode != MLX5_ESWITCH_OFFLOADS) return 0; + devcom = esw->dev->priv.devcom; rpriv = mlx5e_rep_to_rep_priv(rep); - if (mlx5_devcom_is_paired(esw->dev->priv.devcom, MLX5_DEVCOM_ESW_OFFLOADS)) - peer_esw = mlx5_devcom_get_peer_data(esw->dev->priv.devcom, - MLX5_DEVCOM_ESW_OFFLOADS); + if (mlx5_devcom_comp_is_ready(devcom, MLX5_DEVCOM_ESW_OFFLOADS) && + mlx5_devcom_for_each_peer_begin(devcom, MLX5_DEVCOM_ESW_OFFLOADS)) + devcom_locked = true; for (i = 0; i < sqns_num; i++) { rep_sq = kzalloc(sizeof(*rep_sq), GFP_KERNEL); @@ -426,31 +475,30 @@ static int mlx5e_sqs2vport_start(struct mlx5_eswitch *esw, rep_sq->send_to_vport_rule = flow_rule; rep_sq->sqn = sqns_array[i]; - if (peer_esw) { - flow_rule = mlx5_eswitch_add_send_to_vport_rule(peer_esw, esw, - rep, sqns_array[i]); - if (IS_ERR(flow_rule)) { - err = PTR_ERR(flow_rule); + xa_init(&rep_sq->sq_peer); + if (devcom_locked) { + err = mlx5e_sqs2vport_add_peers_rules(esw, rep, devcom, rep_sq, i); + if (err) { mlx5_eswitch_del_send_to_vport_rule(rep_sq->send_to_vport_rule); + xa_destroy(&rep_sq->sq_peer); kfree(rep_sq); goto out_err; } - rep_sq->send_to_vport_rule_peer = flow_rule; } list_add(&rep_sq->list, &rpriv->vport_sqs_list); } - if (peer_esw) - mlx5_devcom_release_peer_data(esw->dev->priv.devcom, MLX5_DEVCOM_ESW_OFFLOADS); + if (devcom_locked) + mlx5_devcom_for_each_peer_end(devcom, MLX5_DEVCOM_ESW_OFFLOADS); return 0; out_err: mlx5e_sqs2vport_stop(esw, rep); - if (peer_esw) - mlx5_devcom_release_peer_data(esw->dev->priv.devcom, MLX5_DEVCOM_ESW_OFFLOADS); + if (devcom_locked) + mlx5_devcom_for_each_peer_end(devcom, MLX5_DEVCOM_ESW_OFFLOADS); return err; } @@ -1530,17 +1578,24 @@ static void *mlx5e_vport_rep_get_proto_dev(struct mlx5_eswitch_rep *rep) return rpriv->netdev; } -static void mlx5e_vport_rep_event_unpair(struct mlx5_eswitch_rep *rep) +static void mlx5e_vport_rep_event_unpair(struct mlx5_eswitch_rep *rep, + struct mlx5_eswitch *peer_esw) { + u16 i = MLX5_CAP_GEN(peer_esw->dev, vhca_id); struct mlx5e_rep_priv *rpriv; struct mlx5e_rep_sq *rep_sq; + WARN_ON_ONCE(!peer_esw); rpriv = mlx5e_rep_to_rep_priv(rep); list_for_each_entry(rep_sq, &rpriv->vport_sqs_list, list) { - if (!rep_sq->send_to_vport_rule_peer) + struct mlx5e_rep_sq_peer *sq_peer = xa_load(&rep_sq->sq_peer, i); + + if (!sq_peer || sq_peer->peer != peer_esw) continue; - mlx5_eswitch_del_send_to_vport_rule(rep_sq->send_to_vport_rule_peer); - rep_sq->send_to_vport_rule_peer = NULL; + + mlx5_eswitch_del_send_to_vport_rule(sq_peer->rule); + xa_erase(&rep_sq->sq_peer, i); + kfree(sq_peer); } } @@ -1548,24 +1603,52 @@ static int mlx5e_vport_rep_event_pair(struct mlx5_eswitch *esw, struct mlx5_eswitch_rep *rep, struct mlx5_eswitch *peer_esw) { + u16 i = MLX5_CAP_GEN(peer_esw->dev, vhca_id); struct mlx5_flow_handle *flow_rule; + struct mlx5e_rep_sq_peer *sq_peer; struct mlx5e_rep_priv *rpriv; struct mlx5e_rep_sq *rep_sq; + int err; rpriv = mlx5e_rep_to_rep_priv(rep); list_for_each_entry(rep_sq, &rpriv->vport_sqs_list, list) { - if (rep_sq->send_to_vport_rule_peer) + sq_peer = xa_load(&rep_sq->sq_peer, i); + + if (sq_peer && sq_peer->peer) continue; - flow_rule = mlx5_eswitch_add_send_to_vport_rule(peer_esw, esw, rep, rep_sq->sqn); - if (IS_ERR(flow_rule)) + + flow_rule = mlx5_eswitch_add_send_to_vport_rule(peer_esw, esw, rep, + rep_sq->sqn); + if (IS_ERR(flow_rule)) { + err = PTR_ERR(flow_rule); goto err_out; - rep_sq->send_to_vport_rule_peer = flow_rule; + } + + if (sq_peer) { + sq_peer->rule = flow_rule; + sq_peer->peer = peer_esw; + continue; + } + sq_peer = kzalloc(sizeof(*sq_peer), GFP_KERNEL); + if (!sq_peer) { + err = -ENOMEM; + goto err_sq_alloc; + } + err = xa_insert(&rep_sq->sq_peer, i, sq_peer, GFP_KERNEL); + if (err) + goto err_xa; + sq_peer->rule = flow_rule; + sq_peer->peer = peer_esw; } return 0; +err_xa: + kfree(sq_peer); +err_sq_alloc: + mlx5_eswitch_del_send_to_vport_rule(flow_rule); err_out: - mlx5e_vport_rep_event_unpair(rep); - return PTR_ERR(flow_rule); + mlx5e_vport_rep_event_unpair(rep, peer_esw); + return err; } static int mlx5e_vport_rep_event(struct mlx5_eswitch *esw, @@ -1578,7 +1661,7 @@ static int mlx5e_vport_rep_event(struct mlx5_eswitch *esw, if (event == MLX5_SWITCHDEV_EVENT_PAIR) err = mlx5e_vport_rep_event_pair(esw, rep, data); else if (event == MLX5_SWITCHDEV_EVENT_UNPAIR) - mlx5e_vport_rep_event_unpair(rep); + mlx5e_vport_rep_event_unpair(rep, data); return err; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.h b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.h index 80b7f5079a5a5488f10070457cf087e47146b8a1..70640fa1ad7bc04c7a0da2075ee23e096ff54cd7 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.h @@ -225,9 +225,14 @@ struct mlx5e_encap_entry { struct rcu_head rcu; }; +struct mlx5e_rep_sq_peer { + struct mlx5_flow_handle *rule; + void *peer; +}; + struct mlx5e_rep_sq { struct mlx5_flow_handle *send_to_vport_rule; - struct mlx5_flow_handle *send_to_vport_rule_peer; + struct xarray sq_peer; u32 sqn; struct list_head list; }; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c index 69634829558e2bc59c91dd485f5f025640277880..41d37159e027b90c77ef724b1e0a821e6560c7d0 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c @@ -390,10 +390,18 @@ static void mlx5e_dealloc_rx_wqe(struct mlx5e_rq *rq, u16 ix) { struct mlx5e_wqe_frag_info *wi = get_frag(rq, ix); - if (rq->xsk_pool) + if (rq->xsk_pool) { mlx5e_xsk_free_rx_wqe(wi); - else + } else { mlx5e_free_rx_wqe(rq, wi); + + /* Avoid a second release of the wqe pages: dealloc is called + * for the same missing wqes on regular RQ flush and on regular + * RQ close. This happens when XSK RQs come into play. + */ + for (int i = 0; i < rq->wqe.info.num_frags; i++, wi++) + wi->flags |= BIT(MLX5E_WQE_FRAG_SKIP_RELEASE); + } } static void mlx5e_xsk_free_rx_wqes(struct mlx5e_rq *rq, u16 ix, int wqe_bulk) @@ -491,9 +499,7 @@ mlx5e_add_skb_shared_info_frag(struct mlx5e_rq *rq, struct skb_shared_info *sinf } frag = &sinfo->frags[sinfo->nr_frags++]; - __skb_frag_set_page(frag, frag_page->page); - skb_frag_off_set(frag, frag_offset); - skb_frag_size_set(frag, len); + skb_frag_fill_page_desc(frag, frag_page->page, frag_offset, len); if (page_is_pfmemalloc(frag_page->page)) xdp_buff_set_frag_pfmemalloc(xdp); @@ -1745,11 +1751,11 @@ mlx5e_skb_from_cqe_nonlinear(struct mlx5e_rq *rq, struct mlx5e_wqe_frag_info *wi prog = rcu_dereference(rq->xdp_prog); if (prog && mlx5e_xdp_handle(rq, prog, &mxbuf)) { - if (test_bit(MLX5E_RQ_FLAG_XDP_XMIT, rq->flags)) { + if (__test_and_clear_bit(MLX5E_RQ_FLAG_XDP_XMIT, rq->flags)) { struct mlx5e_wqe_frag_info *pwi; for (pwi = head_wi; pwi < wi; pwi++) - pwi->flags |= BIT(MLX5E_WQE_FRAG_SKIP_RELEASE); + pwi->frag_page->frags++; } return NULL; /* page/packet was consumed by XDP */ } @@ -1819,12 +1825,8 @@ static void mlx5e_handle_rx_cqe(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe) rq, wi, cqe, cqe_bcnt); if (!skb) { /* probably for XDP */ - if (__test_and_clear_bit(MLX5E_RQ_FLAG_XDP_XMIT, rq->flags)) { - /* do not return page to cache, - * it will be returned on XDP_TX completion. - */ - wi->flags |= BIT(MLX5E_WQE_FRAG_SKIP_RELEASE); - } + if (__test_and_clear_bit(MLX5E_RQ_FLAG_XDP_XMIT, rq->flags)) + wi->frag_page->frags++; goto wq_cyc_pop; } @@ -1870,12 +1872,8 @@ static void mlx5e_handle_rx_cqe_rep(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe) rq, wi, cqe, cqe_bcnt); if (!skb) { /* probably for XDP */ - if (__test_and_clear_bit(MLX5E_RQ_FLAG_XDP_XMIT, rq->flags)) { - /* do not return page to cache, - * it will be returned on XDP_TX completion. - */ - wi->flags |= BIT(MLX5E_WQE_FRAG_SKIP_RELEASE); - } + if (__test_and_clear_bit(MLX5E_RQ_FLAG_XDP_XMIT, rq->flags)) + wi->frag_page->frags++; goto wq_cyc_pop; } @@ -2054,12 +2052,12 @@ mlx5e_skb_from_cqe_mpwrq_nonlinear(struct mlx5e_rq *rq, struct mlx5e_mpw_info *w if (prog) { if (mlx5e_xdp_handle(rq, prog, &mxbuf)) { if (__test_and_clear_bit(MLX5E_RQ_FLAG_XDP_XMIT, rq->flags)) { - int i; + struct mlx5e_frag_page *pfp; + + for (pfp = head_page; pfp < frag_page; pfp++) + pfp->frags++; - for (i = 0; i < sinfo->nr_frags; i++) - /* non-atomic */ - __set_bit(page_idx + i, wi->skip_release_bitmap); - return NULL; + wi->linear_page.frags++; } mlx5e_page_release_fragmented(rq, &wi->linear_page); return NULL; /* page/packet was consumed by XDP */ @@ -2157,7 +2155,7 @@ mlx5e_skb_from_cqe_mpwrq_linear(struct mlx5e_rq *rq, struct mlx5e_mpw_info *wi, cqe_bcnt, &mxbuf); if (mlx5e_xdp_handle(rq, prog, &mxbuf)) { if (__test_and_clear_bit(MLX5E_RQ_FLAG_XDP_XMIT, rq->flags)) - __set_bit(page_idx, wi->skip_release_bitmap); /* non-atomic */ + frag_page->frags++; return NULL; /* page/packet was consumed by XDP */ } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c index f1d9596905c6c8dad60be9e8c454f47c0f24dbd4..4d77055abd4be3659672663e97c6b4269435119c 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c @@ -30,7 +30,7 @@ * SOFTWARE. */ -#include "lib/mlx5.h" +#include "lib/events.h" #include "en.h" #include "en_accel/ktls.h" #include "en_accel/en_accel.h" @@ -748,11 +748,22 @@ static const struct counter_desc vport_stats_desc[] = { VPORT_COUNTER_OFF(transmitted_ib_multicast.octets) }, }; +static const struct counter_desc vport_loopback_stats_desc[] = { + { "vport_loopback_packets", + VPORT_COUNTER_OFF(local_loopback.packets) }, + { "vport_loopback_bytes", + VPORT_COUNTER_OFF(local_loopback.octets) }, +}; + #define NUM_VPORT_COUNTERS ARRAY_SIZE(vport_stats_desc) +#define NUM_VPORT_LOOPBACK_COUNTERS(dev) \ + (MLX5_CAP_GEN(dev, vport_counter_local_loopback) ? \ + ARRAY_SIZE(vport_loopback_stats_desc) : 0) static MLX5E_DECLARE_STATS_GRP_OP_NUM_STATS(vport) { - return NUM_VPORT_COUNTERS; + return NUM_VPORT_COUNTERS + + NUM_VPORT_LOOPBACK_COUNTERS(priv->mdev); } static MLX5E_DECLARE_STATS_GRP_OP_FILL_STRS(vport) @@ -761,6 +772,11 @@ static MLX5E_DECLARE_STATS_GRP_OP_FILL_STRS(vport) for (i = 0; i < NUM_VPORT_COUNTERS; i++) strcpy(data + (idx++) * ETH_GSTRING_LEN, vport_stats_desc[i].format); + + for (i = 0; i < NUM_VPORT_LOOPBACK_COUNTERS(priv->mdev); i++) + strcpy(data + (idx++) * ETH_GSTRING_LEN, + vport_loopback_stats_desc[i].format); + return idx; } @@ -771,6 +787,11 @@ static MLX5E_DECLARE_STATS_GRP_OP_FILL_STATS(vport) for (i = 0; i < NUM_VPORT_COUNTERS; i++) data[idx++] = MLX5E_READ_CTR64_BE(priv->stats.vport.query_vport_out, vport_stats_desc, i); + + for (i = 0; i < NUM_VPORT_LOOPBACK_COUNTERS(priv->mdev); i++) + data[idx++] = MLX5E_READ_CTR64_BE(priv->stats.vport.query_vport_out, + vport_loopback_stats_desc, i); + return idx; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c index 8a5a8703f0a31b0c4b2feadfb39a5cbcdb1d9196..8d0a3f69693e113a2e215166e76020b35b2372f6 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c @@ -1439,6 +1439,7 @@ static void mlx5e_tc_del_nic_flow(struct mlx5e_priv *priv, mlx5e_hairpin_flow_del(priv, flow); free_flow_post_acts(flow); + mlx5_tc_ct_delete_flow(get_ct_priv(flow->priv), attr); kvfree(attr->parse_attr); kfree(flow->attr); @@ -1638,7 +1639,8 @@ static void remove_unready_flow(struct mlx5e_tc_flow *flow) uplink_priv = &rpriv->uplink_priv; mutex_lock(&uplink_priv->unready_flows_lock); - unready_flow_del(flow); + if (flow_flag_test(flow, NOT_READY)) + unready_flow_del(flow); mutex_unlock(&uplink_priv->unready_flows_lock); } @@ -1666,8 +1668,11 @@ int mlx5e_tc_query_route_vport(struct net_device *out_dev, struct net_device *ro { struct mlx5e_priv *out_priv, *route_priv; struct mlx5_core_dev *route_mdev; + struct mlx5_devcom *devcom; struct mlx5_eswitch *esw; u16 vhca_id; + int err; + int i; out_priv = netdev_priv(out_dev); esw = out_priv->mdev->priv.eswitch; @@ -1675,28 +1680,25 @@ int mlx5e_tc_query_route_vport(struct net_device *out_dev, struct net_device *ro route_mdev = route_priv->mdev; vhca_id = MLX5_CAP_GEN(route_mdev, vhca_id); - if (mlx5_lag_is_active(out_priv->mdev)) { - struct mlx5_devcom *devcom; - int err; - - /* In lag case we may get devices from different eswitch instances. - * If we failed to get vport num, it means, mostly, that we on the wrong - * eswitch. - */ - err = mlx5_eswitch_vhca_id_to_vport(esw, vhca_id, vport); - if (err != -ENOENT) - return err; - - rcu_read_lock(); - devcom = out_priv->mdev->priv.devcom; - esw = mlx5_devcom_get_peer_data_rcu(devcom, MLX5_DEVCOM_ESW_OFFLOADS); - err = esw ? mlx5_eswitch_vhca_id_to_vport(esw, vhca_id, vport) : -ENODEV; - rcu_read_unlock(); + err = mlx5_eswitch_vhca_id_to_vport(esw, vhca_id, vport); + if (!err) + return err; + if (!mlx5_lag_is_active(out_priv->mdev)) return err; + + rcu_read_lock(); + devcom = out_priv->mdev->priv.devcom; + err = -ENODEV; + mlx5_devcom_for_each_peer_entry_rcu(devcom, MLX5_DEVCOM_ESW_OFFLOADS, + esw, i) { + err = mlx5_eswitch_vhca_id_to_vport(esw, vhca_id, vport); + if (!err) + break; } + rcu_read_unlock(); - return mlx5_eswitch_vhca_id_to_vport(esw, vhca_id, vport); + return err; } static int @@ -1931,8 +1933,7 @@ static void mlx5e_tc_del_fdb_flow(struct mlx5e_priv *priv, esw_attr = attr->esw_attr; mlx5e_put_flow_tunnel_id(flow); - if (flow_flag_test(flow, NOT_READY)) - remove_unready_flow(flow); + remove_unready_flow(flow); if (mlx5e_is_offloaded_flow(flow)) { if (flow_flag_test(flow, SLOW)) @@ -1986,47 +1987,59 @@ void mlx5e_put_flow_list(struct mlx5e_priv *priv, struct list_head *flow_list) mlx5e_flow_put(priv, flow); } -static void __mlx5e_tc_del_fdb_peer_flow(struct mlx5e_tc_flow *flow) +static void mlx5e_tc_del_fdb_peer_flow(struct mlx5e_tc_flow *flow, + int peer_index) { struct mlx5_eswitch *esw = flow->priv->mdev->priv.eswitch; + struct mlx5e_tc_flow *peer_flow; + struct mlx5e_tc_flow *tmp; if (!flow_flag_test(flow, ESWITCH) || !flow_flag_test(flow, DUP)) return; mutex_lock(&esw->offloads.peer_mutex); - list_del(&flow->peer); + list_del(&flow->peer[peer_index]); mutex_unlock(&esw->offloads.peer_mutex); - flow_flag_clear(flow, DUP); - - if (refcount_dec_and_test(&flow->peer_flow->refcnt)) { - mlx5e_tc_del_fdb_flow(flow->peer_flow->priv, flow->peer_flow); - kfree(flow->peer_flow); + list_for_each_entry_safe(peer_flow, tmp, &flow->peer_flows, peer_flows) { + if (peer_index != mlx5_get_dev_index(peer_flow->priv->mdev)) + continue; + if (refcount_dec_and_test(&peer_flow->refcnt)) { + mlx5e_tc_del_fdb_flow(peer_flow->priv, peer_flow); + list_del(&peer_flow->peer_flows); + kfree(peer_flow); + } } - flow->peer_flow = NULL; + if (list_empty(&flow->peer_flows)) + flow_flag_clear(flow, DUP); } -static void mlx5e_tc_del_fdb_peer_flow(struct mlx5e_tc_flow *flow) +static void mlx5e_tc_del_fdb_peers_flow(struct mlx5e_tc_flow *flow) { - struct mlx5_core_dev *dev = flow->priv->mdev; - struct mlx5_devcom *devcom = dev->priv.devcom; - struct mlx5_eswitch *peer_esw; - - peer_esw = mlx5_devcom_get_peer_data(devcom, MLX5_DEVCOM_ESW_OFFLOADS); - if (!peer_esw) - return; + int i; - __mlx5e_tc_del_fdb_peer_flow(flow); - mlx5_devcom_release_peer_data(devcom, MLX5_DEVCOM_ESW_OFFLOADS); + for (i = 0; i < MLX5_MAX_PORTS; i++) { + if (i == mlx5_get_dev_index(flow->priv->mdev)) + continue; + mlx5e_tc_del_fdb_peer_flow(flow, i); + } } static void mlx5e_tc_del_flow(struct mlx5e_priv *priv, struct mlx5e_tc_flow *flow) { if (mlx5e_is_eswitch_flow(flow)) { - mlx5e_tc_del_fdb_peer_flow(flow); + struct mlx5_devcom *devcom = flow->priv->mdev->priv.devcom; + + if (!mlx5_devcom_for_each_peer_begin(devcom, MLX5_DEVCOM_ESW_OFFLOADS)) { + mlx5e_tc_del_fdb_flow(priv, flow); + return; + } + + mlx5e_tc_del_fdb_peers_flow(flow); + mlx5_devcom_for_each_peer_end(devcom, MLX5_DEVCOM_ESW_OFFLOADS); mlx5e_tc_del_fdb_flow(priv, flow); } else { mlx5e_tc_del_nic_flow(priv, flow); @@ -2502,6 +2515,12 @@ static int mlx5e_flower_parse_meta(struct net_device *filter_dev, return 0; flow_rule_match_meta(rule, &match); + + if (match.mask->l2_miss) { + NL_SET_ERR_MSG_MOD(f->common.extack, "Can't match on \"l2_miss\""); + return -EOPNOTSUPP; + } + if (!match.mask->ingress_ifindex) return 0; @@ -4197,8 +4216,8 @@ static bool is_peer_flow_needed(struct mlx5e_tc_flow *flow) flow_flag_test(flow, INGRESS); bool act_is_encap = !!(attr->action & MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT); - bool esw_paired = mlx5_devcom_is_paired(esw_attr->in_mdev->priv.devcom, - MLX5_DEVCOM_ESW_OFFLOADS); + bool esw_paired = mlx5_devcom_comp_is_ready(esw_attr->in_mdev->priv.devcom, + MLX5_DEVCOM_ESW_OFFLOADS); if (!esw_paired) return false; @@ -4289,6 +4308,7 @@ mlx5e_alloc_flow(struct mlx5e_priv *priv, int attr_size, INIT_LIST_HEAD(&flow->hairpin); INIT_LIST_HEAD(&flow->l3_to_l2_reformat); INIT_LIST_HEAD(&flow->attrs); + INIT_LIST_HEAD(&flow->peer_flows); refcount_set(&flow->refcnt, 1); init_completion(&flow->init_done); init_completion(&flow->del_hw_done); @@ -4397,22 +4417,19 @@ __mlx5e_add_fdb_flow(struct mlx5e_priv *priv, static int mlx5e_tc_add_fdb_peer_flow(struct flow_cls_offload *f, struct mlx5e_tc_flow *flow, - unsigned long flow_flags) + unsigned long flow_flags, + struct mlx5_eswitch *peer_esw) { struct mlx5e_priv *priv = flow->priv, *peer_priv; - struct mlx5_eswitch *esw = priv->mdev->priv.eswitch, *peer_esw; + struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; struct mlx5_esw_flow_attr *attr = flow->attr->esw_attr; - struct mlx5_devcom *devcom = priv->mdev->priv.devcom; struct mlx5e_tc_flow_parse_attr *parse_attr; + int i = mlx5_get_dev_index(peer_esw->dev); struct mlx5e_rep_priv *peer_urpriv; struct mlx5e_tc_flow *peer_flow; struct mlx5_core_dev *in_mdev; int err = 0; - peer_esw = mlx5_devcom_get_peer_data(devcom, MLX5_DEVCOM_ESW_OFFLOADS); - if (!peer_esw) - return -ENODEV; - peer_urpriv = mlx5_eswitch_get_uplink_priv(peer_esw, REP_ETH); peer_priv = netdev_priv(peer_urpriv->netdev); @@ -4437,14 +4454,13 @@ static int mlx5e_tc_add_fdb_peer_flow(struct flow_cls_offload *f, goto out; } - flow->peer_flow = peer_flow; + list_add_tail(&peer_flow->peer_flows, &flow->peer_flows); flow_flag_set(flow, DUP); mutex_lock(&esw->offloads.peer_mutex); - list_add_tail(&flow->peer, &esw->offloads.peer_flows); + list_add_tail(&flow->peer[i], &esw->offloads.peer_flows[i]); mutex_unlock(&esw->offloads.peer_mutex); out: - mlx5_devcom_release_peer_data(devcom, MLX5_DEVCOM_ESW_OFFLOADS); return err; } @@ -4455,30 +4471,48 @@ mlx5e_add_fdb_flow(struct mlx5e_priv *priv, struct net_device *filter_dev, struct mlx5e_tc_flow **__flow) { + struct mlx5_devcom *devcom = priv->mdev->priv.devcom; struct mlx5e_rep_priv *rpriv = priv->ppriv; struct mlx5_eswitch_rep *in_rep = rpriv->rep; struct mlx5_core_dev *in_mdev = priv->mdev; + struct mlx5_eswitch *peer_esw; struct mlx5e_tc_flow *flow; int err; + int i; flow = __mlx5e_add_fdb_flow(priv, f, flow_flags, filter_dev, in_rep, in_mdev); if (IS_ERR(flow)) return PTR_ERR(flow); - if (is_peer_flow_needed(flow)) { - err = mlx5e_tc_add_fdb_peer_flow(f, flow, flow_flags); - if (err) { - mlx5e_tc_del_fdb_flow(priv, flow); - goto out; - } + if (!is_peer_flow_needed(flow)) { + *__flow = flow; + return 0; } - *__flow = flow; + if (!mlx5_devcom_for_each_peer_begin(devcom, MLX5_DEVCOM_ESW_OFFLOADS)) { + err = -ENODEV; + goto clean_flow; + } + mlx5_devcom_for_each_peer_entry(devcom, + MLX5_DEVCOM_ESW_OFFLOADS, + peer_esw, i) { + err = mlx5e_tc_add_fdb_peer_flow(f, flow, flow_flags, peer_esw); + if (err) + goto peer_clean; + } + + mlx5_devcom_for_each_peer_end(devcom, MLX5_DEVCOM_ESW_OFFLOADS); + + *__flow = flow; return 0; -out: +peer_clean: + mlx5e_tc_del_fdb_peers_flow(flow); + mlx5_devcom_for_each_peer_end(devcom, MLX5_DEVCOM_ESW_OFFLOADS); +clean_flow: + mlx5e_tc_del_fdb_flow(priv, flow); return err; } @@ -4696,7 +4730,6 @@ int mlx5e_stats_flower(struct net_device *dev, struct mlx5e_priv *priv, { struct mlx5_devcom *devcom = priv->mdev->priv.devcom; struct rhashtable *tc_ht = get_tc_ht(priv, flags); - struct mlx5_eswitch *peer_esw; struct mlx5e_tc_flow *flow; struct mlx5_fc *counter; u64 lastuse = 0; @@ -4731,23 +4764,29 @@ int mlx5e_stats_flower(struct net_device *dev, struct mlx5e_priv *priv, /* Under multipath it's possible for one rule to be currently * un-offloaded while the other rule is offloaded. */ - peer_esw = mlx5_devcom_get_peer_data(devcom, MLX5_DEVCOM_ESW_OFFLOADS); - if (!peer_esw) + if (!mlx5_devcom_for_each_peer_begin(devcom, MLX5_DEVCOM_ESW_OFFLOADS)) goto out; - if (flow_flag_test(flow, DUP) && - flow_flag_test(flow->peer_flow, OFFLOADED)) { - u64 bytes2; - u64 packets2; - u64 lastuse2; + if (flow_flag_test(flow, DUP)) { + struct mlx5e_tc_flow *peer_flow; - if (flow_flag_test(flow, USE_ACT_STATS)) { - f->use_act_stats = true; - } else { - counter = mlx5e_tc_get_counter(flow->peer_flow); + list_for_each_entry(peer_flow, &flow->peer_flows, peer_flows) { + u64 packets2; + u64 lastuse2; + u64 bytes2; + + if (!flow_flag_test(peer_flow, OFFLOADED)) + continue; + if (flow_flag_test(flow, USE_ACT_STATS)) { + f->use_act_stats = true; + break; + } + + counter = mlx5e_tc_get_counter(peer_flow); if (!counter) goto no_peer_counter; - mlx5_fc_query_cached(counter, &bytes2, &packets2, &lastuse2); + mlx5_fc_query_cached(counter, &bytes2, &packets2, + &lastuse2); bytes += bytes2; packets += packets2; @@ -4756,7 +4795,7 @@ int mlx5e_stats_flower(struct net_device *dev, struct mlx5e_priv *priv, } no_peer_counter: - mlx5_devcom_release_peer_data(devcom, MLX5_DEVCOM_ESW_OFFLOADS); + mlx5_devcom_for_each_peer_end(devcom, MLX5_DEVCOM_ESW_OFFLOADS); out: flow_stats_update(&f->stats, bytes, packets, 0, lastuse, FLOW_ACTION_HW_STATS_DELAYED); @@ -5274,9 +5313,14 @@ int mlx5e_tc_num_filters(struct mlx5e_priv *priv, unsigned long flags) void mlx5e_tc_clean_fdb_peer_flows(struct mlx5_eswitch *esw) { struct mlx5e_tc_flow *flow, *tmp; + int i; - list_for_each_entry_safe(flow, tmp, &esw->offloads.peer_flows, peer) - __mlx5e_tc_del_fdb_peer_flow(flow); + for (i = 0; i < MLX5_MAX_PORTS; i++) { + if (i == mlx5_get_dev_index(esw->dev)) + continue; + list_for_each_entry_safe(flow, tmp, &esw->offloads.peer_flows[i], peer[i]) + mlx5e_tc_del_fdb_peers_flow(flow); + } } void mlx5e_tc_reoffload_flows_work(struct work_struct *work) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_txrx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_txrx.c index fbb2d963fb7e1bc3afce053980f360f2467d1bf1..a7d9b7cb4297fcf486a4dba310d25b856ded1b8f 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_txrx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_txrx.c @@ -207,7 +207,7 @@ int mlx5e_napi_poll(struct napi_struct *napi, int budget) } ch_stats->aff_change++; aff_change = true; - if (budget && work_done == budget) + if (work_done == budget) work_done--; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/egress_ofld.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/egress_ofld.c index 2e504c7461c6574f7c4303886e9a6a002408e365..24b1ca4e4ff8741fba72f425d2f7a79b57478066 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/egress_ofld.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/egress_ofld.c @@ -15,13 +15,27 @@ static void esw_acl_egress_ofld_fwd2vport_destroy(struct mlx5_vport *vport) vport->egress.offloads.fwd_rule = NULL; } -static void esw_acl_egress_ofld_bounce_rule_destroy(struct mlx5_vport *vport) +void esw_acl_egress_ofld_bounce_rule_destroy(struct mlx5_vport *vport, int rule_index) { - if (!vport->egress.offloads.bounce_rule) + struct mlx5_flow_handle *bounce_rule = + xa_load(&vport->egress.offloads.bounce_rules, rule_index); + + if (!bounce_rule) return; - mlx5_del_flow_rules(vport->egress.offloads.bounce_rule); - vport->egress.offloads.bounce_rule = NULL; + mlx5_del_flow_rules(bounce_rule); + xa_erase(&vport->egress.offloads.bounce_rules, rule_index); +} + +static void esw_acl_egress_ofld_bounce_rules_destroy(struct mlx5_vport *vport) +{ + struct mlx5_flow_handle *bounce_rule; + unsigned long i; + + xa_for_each(&vport->egress.offloads.bounce_rules, i, bounce_rule) { + mlx5_del_flow_rules(bounce_rule); + xa_erase(&vport->egress.offloads.bounce_rules, i); + } } static int esw_acl_egress_ofld_fwd2vport_create(struct mlx5_eswitch *esw, @@ -96,7 +110,7 @@ static void esw_acl_egress_ofld_rules_destroy(struct mlx5_vport *vport) { esw_acl_egress_vlan_destroy(vport); esw_acl_egress_ofld_fwd2vport_destroy(vport); - esw_acl_egress_ofld_bounce_rule_destroy(vport); + esw_acl_egress_ofld_bounce_rules_destroy(vport); } static int esw_acl_egress_ofld_groups_create(struct mlx5_eswitch *esw, @@ -194,6 +208,7 @@ int esw_acl_egress_ofld_setup(struct mlx5_eswitch *esw, struct mlx5_vport *vport vport->egress.acl = NULL; return err; } + vport->egress.type = VPORT_EGRESS_ACL_TYPE_DEFAULT; err = esw_acl_egress_ofld_groups_create(esw, vport); if (err) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/helper.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/helper.c index 45b839116212df14ac05958c9254a16a2ebcab46..d599e50af346bef72bd08cb385fe0aca44cdf2c7 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/helper.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/helper.c @@ -35,7 +35,8 @@ esw_acl_table_create(struct mlx5_eswitch *esw, struct mlx5_vport *vport, int ns, } ft_attr.max_fte = size; - ft_attr.flags = MLX5_FLOW_TABLE_OTHER_VPORT; + if (vport_num || mlx5_core_is_ecpf(esw->dev)) + ft_attr.flags = MLX5_FLOW_TABLE_OTHER_VPORT; acl = mlx5_create_vport_flow_table(root_ns, &ft_attr, vport_num); if (IS_ERR(acl)) { err = PTR_ERR(acl); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/ofld.h b/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/ofld.h index c9f8469e9a4740ee15d0a574b2ced8d176decd36..536b04e8361868b1bfb0e585771f953bbedbb0ae 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/ofld.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/ofld.h @@ -10,6 +10,7 @@ /* Eswitch acl egress external APIs */ int esw_acl_egress_ofld_setup(struct mlx5_eswitch *esw, struct mlx5_vport *vport); void esw_acl_egress_ofld_cleanup(struct mlx5_vport *vport); +void esw_acl_egress_ofld_bounce_rule_destroy(struct mlx5_vport *vport, int rule_index); int mlx5_esw_acl_egress_vport_bond(struct mlx5_eswitch *esw, u16 active_vport_num, u16 passive_vport_num); int mlx5_esw_acl_egress_vport_unbond(struct mlx5_eswitch *esw, u16 vport_num); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge.c index 1ba03e219111a7fed56142bfc2a7226e5aa10453..f4fe1daa4afd5dfaca375dc7bc9e380c855873d0 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge.c @@ -647,22 +647,35 @@ mlx5_esw_bridge_ingress_flow_create(u16 vport_num, const unsigned char *addr, } static struct mlx5_flow_handle * -mlx5_esw_bridge_ingress_flow_peer_create(u16 vport_num, const unsigned char *addr, +mlx5_esw_bridge_ingress_flow_peer_create(u16 vport_num, u16 esw_owner_vhca_id, + const unsigned char *addr, struct mlx5_esw_bridge_vlan *vlan, u32 counter_id, struct mlx5_esw_bridge *bridge) { struct mlx5_devcom *devcom = bridge->br_offloads->esw->dev->priv.devcom; + struct mlx5_eswitch *tmp, *peer_esw = NULL; static struct mlx5_flow_handle *handle; - struct mlx5_eswitch *peer_esw; + int i; - peer_esw = mlx5_devcom_get_peer_data(devcom, MLX5_DEVCOM_ESW_OFFLOADS); - if (!peer_esw) + if (!mlx5_devcom_for_each_peer_begin(devcom, MLX5_DEVCOM_ESW_OFFLOADS)) return ERR_PTR(-ENODEV); + mlx5_devcom_for_each_peer_entry(devcom, + MLX5_DEVCOM_ESW_OFFLOADS, + tmp, i) { + if (mlx5_esw_is_owner(tmp, vport_num, esw_owner_vhca_id)) { + peer_esw = tmp; + break; + } + } + if (!peer_esw) { + mlx5_devcom_for_each_peer_end(devcom, MLX5_DEVCOM_ESW_OFFLOADS); + return ERR_PTR(-ENODEV); + } + handle = mlx5_esw_bridge_ingress_flow_with_esw_create(vport_num, addr, vlan, counter_id, bridge, peer_esw); - - mlx5_devcom_release_peer_data(devcom, MLX5_DEVCOM_ESW_OFFLOADS); + mlx5_devcom_for_each_peer_end(devcom, MLX5_DEVCOM_ESW_OFFLOADS); return handle; } @@ -821,7 +834,7 @@ mlx5_esw_bridge_egress_miss_flow_create(struct mlx5_flow_table *egress_ft, return handle; } -static struct mlx5_esw_bridge *mlx5_esw_bridge_create(int ifindex, +static struct mlx5_esw_bridge *mlx5_esw_bridge_create(struct net_device *br_netdev, struct mlx5_esw_bridge_offloads *br_offloads) { struct mlx5_esw_bridge *bridge; @@ -845,11 +858,12 @@ static struct mlx5_esw_bridge *mlx5_esw_bridge_create(int ifindex, goto err_mdb_ht; INIT_LIST_HEAD(&bridge->fdb_list); - bridge->ifindex = ifindex; + bridge->ifindex = br_netdev->ifindex; bridge->refcnt = 1; bridge->ageing_time = clock_t_to_jiffies(BR_DEFAULT_AGEING_TIME); bridge->vlan_proto = ETH_P_8021Q; list_add(&bridge->list, &br_offloads->bridges); + mlx5_esw_bridge_debugfs_init(br_netdev, bridge); return bridge; @@ -873,6 +887,7 @@ static void mlx5_esw_bridge_put(struct mlx5_esw_bridge_offloads *br_offloads, if (--bridge->refcnt) return; + mlx5_esw_bridge_debugfs_cleanup(bridge); mlx5_esw_bridge_egress_table_cleanup(bridge); mlx5_esw_bridge_mcast_disable(bridge); list_del(&bridge->list); @@ -885,14 +900,14 @@ static void mlx5_esw_bridge_put(struct mlx5_esw_bridge_offloads *br_offloads, } static struct mlx5_esw_bridge * -mlx5_esw_bridge_lookup(int ifindex, struct mlx5_esw_bridge_offloads *br_offloads) +mlx5_esw_bridge_lookup(struct net_device *br_netdev, struct mlx5_esw_bridge_offloads *br_offloads) { struct mlx5_esw_bridge *bridge; ASSERT_RTNL(); list_for_each_entry(bridge, &br_offloads->bridges, list) { - if (bridge->ifindex == ifindex) { + if (bridge->ifindex == br_netdev->ifindex) { mlx5_esw_bridge_get(bridge); return bridge; } @@ -905,7 +920,7 @@ mlx5_esw_bridge_lookup(int ifindex, struct mlx5_esw_bridge_offloads *br_offloads return ERR_PTR(err); } - bridge = mlx5_esw_bridge_create(ifindex, br_offloads); + bridge = mlx5_esw_bridge_create(br_netdev, br_offloads); if (IS_ERR(bridge) && list_empty(&br_offloads->bridges)) mlx5_esw_bridge_ingress_table_cleanup(br_offloads); return bridge; @@ -1369,8 +1384,9 @@ mlx5_esw_bridge_fdb_entry_init(struct net_device *dev, u16 vport_num, u16 esw_ow entry->ingress_counter = counter; handle = peer ? - mlx5_esw_bridge_ingress_flow_peer_create(vport_num, addr, vlan, - mlx5_fc_id(counter), bridge) : + mlx5_esw_bridge_ingress_flow_peer_create(vport_num, esw_owner_vhca_id, + addr, vlan, mlx5_fc_id(counter), + bridge) : mlx5_esw_bridge_ingress_flow_create(vport_num, addr, vlan, mlx5_fc_id(counter), bridge); if (IS_ERR(handle)) { @@ -1587,15 +1603,15 @@ static int mlx5_esw_bridge_vport_cleanup(struct mlx5_esw_bridge_offloads *br_off return 0; } -static int mlx5_esw_bridge_vport_link_with_flags(int ifindex, u16 vport_num, u16 esw_owner_vhca_id, - u16 flags, +static int mlx5_esw_bridge_vport_link_with_flags(struct net_device *br_netdev, u16 vport_num, + u16 esw_owner_vhca_id, u16 flags, struct mlx5_esw_bridge_offloads *br_offloads, struct netlink_ext_ack *extack) { struct mlx5_esw_bridge *bridge; int err; - bridge = mlx5_esw_bridge_lookup(ifindex, br_offloads); + bridge = mlx5_esw_bridge_lookup(br_netdev, br_offloads); if (IS_ERR(bridge)) { NL_SET_ERR_MSG_MOD(extack, "Error checking for existing bridge with same ifindex"); return PTR_ERR(bridge); @@ -1613,15 +1629,16 @@ static int mlx5_esw_bridge_vport_link_with_flags(int ifindex, u16 vport_num, u16 return err; } -int mlx5_esw_bridge_vport_link(int ifindex, u16 vport_num, u16 esw_owner_vhca_id, +int mlx5_esw_bridge_vport_link(struct net_device *br_netdev, u16 vport_num, u16 esw_owner_vhca_id, struct mlx5_esw_bridge_offloads *br_offloads, struct netlink_ext_ack *extack) { - return mlx5_esw_bridge_vport_link_with_flags(ifindex, vport_num, esw_owner_vhca_id, 0, + return mlx5_esw_bridge_vport_link_with_flags(br_netdev, vport_num, esw_owner_vhca_id, 0, br_offloads, extack); } -int mlx5_esw_bridge_vport_unlink(int ifindex, u16 vport_num, u16 esw_owner_vhca_id, +int mlx5_esw_bridge_vport_unlink(struct net_device *br_netdev, u16 vport_num, + u16 esw_owner_vhca_id, struct mlx5_esw_bridge_offloads *br_offloads, struct netlink_ext_ack *extack) { @@ -1633,7 +1650,7 @@ int mlx5_esw_bridge_vport_unlink(int ifindex, u16 vport_num, u16 esw_owner_vhca_ NL_SET_ERR_MSG_MOD(extack, "Port is not attached to any bridge"); return -EINVAL; } - if (port->bridge->ifindex != ifindex) { + if (port->bridge->ifindex != br_netdev->ifindex) { NL_SET_ERR_MSG_MOD(extack, "Port is attached to another bridge"); return -EINVAL; } @@ -1644,23 +1661,25 @@ int mlx5_esw_bridge_vport_unlink(int ifindex, u16 vport_num, u16 esw_owner_vhca_ return err; } -int mlx5_esw_bridge_vport_peer_link(int ifindex, u16 vport_num, u16 esw_owner_vhca_id, +int mlx5_esw_bridge_vport_peer_link(struct net_device *br_netdev, u16 vport_num, + u16 esw_owner_vhca_id, struct mlx5_esw_bridge_offloads *br_offloads, struct netlink_ext_ack *extack) { if (!MLX5_CAP_ESW(br_offloads->esw->dev, merged_eswitch)) return 0; - return mlx5_esw_bridge_vport_link_with_flags(ifindex, vport_num, esw_owner_vhca_id, + return mlx5_esw_bridge_vport_link_with_flags(br_netdev, vport_num, esw_owner_vhca_id, MLX5_ESW_BRIDGE_PORT_FLAG_PEER, br_offloads, extack); } -int mlx5_esw_bridge_vport_peer_unlink(int ifindex, u16 vport_num, u16 esw_owner_vhca_id, +int mlx5_esw_bridge_vport_peer_unlink(struct net_device *br_netdev, u16 vport_num, + u16 esw_owner_vhca_id, struct mlx5_esw_bridge_offloads *br_offloads, struct netlink_ext_ack *extack) { - return mlx5_esw_bridge_vport_unlink(ifindex, vport_num, esw_owner_vhca_id, br_offloads, + return mlx5_esw_bridge_vport_unlink(br_netdev, vport_num, esw_owner_vhca_id, br_offloads, extack); } @@ -1887,6 +1906,7 @@ struct mlx5_esw_bridge_offloads *mlx5_esw_bridge_init(struct mlx5_eswitch *esw) xa_init(&br_offloads->ports); br_offloads->esw = esw; esw->br_offloads = br_offloads; + mlx5_esw_bridge_debugfs_offloads_init(br_offloads); return br_offloads; } @@ -1902,6 +1922,7 @@ void mlx5_esw_bridge_cleanup(struct mlx5_eswitch *esw) mlx5_esw_bridge_flush(br_offloads); WARN_ON(!xa_empty(&br_offloads->ports)); + mlx5_esw_bridge_debugfs_offloads_cleanup(br_offloads); esw->br_offloads = NULL; kvfree(br_offloads); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge.h b/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge.h index a9dd18c73d6a5f504cd66d1286af9c6ac7edd139..c2c7c70d99eb70c48d301de06298e231193c0d71 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge.h @@ -10,6 +10,7 @@ #include #include "eswitch.h" +struct dentry; struct mlx5_flow_table; struct mlx5_flow_group; @@ -17,6 +18,7 @@ struct mlx5_esw_bridge_offloads { struct mlx5_eswitch *esw; struct list_head bridges; struct xarray ports; + struct dentry *debugfs_root; struct notifier_block netdev_nb; struct notifier_block nb_blk; @@ -43,16 +45,18 @@ struct mlx5_esw_bridge_offloads { struct mlx5_esw_bridge_offloads *mlx5_esw_bridge_init(struct mlx5_eswitch *esw); void mlx5_esw_bridge_cleanup(struct mlx5_eswitch *esw); -int mlx5_esw_bridge_vport_link(int ifindex, u16 vport_num, u16 esw_owner_vhca_id, +int mlx5_esw_bridge_vport_link(struct net_device *br_netdev, u16 vport_num, u16 esw_owner_vhca_id, struct mlx5_esw_bridge_offloads *br_offloads, struct netlink_ext_ack *extack); -int mlx5_esw_bridge_vport_unlink(int ifindex, u16 vport_num, u16 esw_owner_vhca_id, +int mlx5_esw_bridge_vport_unlink(struct net_device *br_netdev, u16 vport_num, u16 esw_owner_vhca_id, struct mlx5_esw_bridge_offloads *br_offloads, struct netlink_ext_ack *extack); -int mlx5_esw_bridge_vport_peer_link(int ifindex, u16 vport_num, u16 esw_owner_vhca_id, +int mlx5_esw_bridge_vport_peer_link(struct net_device *br_netdev, u16 vport_num, + u16 esw_owner_vhca_id, struct mlx5_esw_bridge_offloads *br_offloads, struct netlink_ext_ack *extack); -int mlx5_esw_bridge_vport_peer_unlink(int ifindex, u16 vport_num, u16 esw_owner_vhca_id, +int mlx5_esw_bridge_vport_peer_unlink(struct net_device *br_netdev, u16 vport_num, + u16 esw_owner_vhca_id, struct mlx5_esw_bridge_offloads *br_offloads, struct netlink_ext_ack *extack); void mlx5_esw_bridge_fdb_update_used(struct net_device *dev, u16 vport_num, u16 esw_owner_vhca_id, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge_debugfs.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge_debugfs.c new file mode 100644 index 0000000000000000000000000000000000000000..b6a45eff28f554be7456be783ad24f4b104ae0b5 --- /dev/null +++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge_debugfs.c @@ -0,0 +1,89 @@ +// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB +/* Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved. */ + +#include +#include "bridge.h" +#include "bridge_priv.h" + +static void *mlx5_esw_bridge_debugfs_start(struct seq_file *seq, loff_t *pos); +static void *mlx5_esw_bridge_debugfs_next(struct seq_file *seq, void *v, loff_t *pos); +static void mlx5_esw_bridge_debugfs_stop(struct seq_file *seq, void *v); +static int mlx5_esw_bridge_debugfs_show(struct seq_file *seq, void *v); + +static const struct seq_operations mlx5_esw_bridge_debugfs_sops = { + .start = mlx5_esw_bridge_debugfs_start, + .next = mlx5_esw_bridge_debugfs_next, + .stop = mlx5_esw_bridge_debugfs_stop, + .show = mlx5_esw_bridge_debugfs_show, +}; +DEFINE_SEQ_ATTRIBUTE(mlx5_esw_bridge_debugfs); + +static void *mlx5_esw_bridge_debugfs_start(struct seq_file *seq, loff_t *pos) +{ + struct mlx5_esw_bridge *bridge = seq->private; + + rtnl_lock(); + return *pos ? seq_list_start(&bridge->fdb_list, *pos - 1) : SEQ_START_TOKEN; +} + +static void *mlx5_esw_bridge_debugfs_next(struct seq_file *seq, void *v, loff_t *pos) +{ + struct mlx5_esw_bridge *bridge = seq->private; + + return seq_list_next(v == SEQ_START_TOKEN ? &bridge->fdb_list : v, &bridge->fdb_list, pos); +} + +static void mlx5_esw_bridge_debugfs_stop(struct seq_file *seq, void *v) +{ + rtnl_unlock(); +} + +static int mlx5_esw_bridge_debugfs_show(struct seq_file *seq, void *v) +{ + struct mlx5_esw_bridge_fdb_entry *entry; + u64 packets, bytes, lastuse; + + if (v == SEQ_START_TOKEN) { + seq_printf(seq, "%-16s %-17s %4s %20s %20s %20s %5s\n", + "DEV", "MAC", "VLAN", "PACKETS", "BYTES", "LASTUSE", "FLAGS"); + return 0; + } + + entry = list_entry(v, struct mlx5_esw_bridge_fdb_entry, list); + mlx5_fc_query_cached_raw(entry->ingress_counter, &bytes, &packets, &lastuse); + seq_printf(seq, "%-16s %-17pM %4d %20llu %20llu %20llu %#5x\n", + entry->dev->name, entry->key.addr, entry->key.vid, packets, bytes, lastuse, + entry->flags); + return 0; +} + +void mlx5_esw_bridge_debugfs_init(struct net_device *br_netdev, struct mlx5_esw_bridge *bridge) +{ + if (!bridge->br_offloads->debugfs_root) + return; + + bridge->debugfs_dir = debugfs_create_dir(br_netdev->name, + bridge->br_offloads->debugfs_root); + debugfs_create_file("fdb", 0444, bridge->debugfs_dir, bridge, + &mlx5_esw_bridge_debugfs_fops); +} + +void mlx5_esw_bridge_debugfs_cleanup(struct mlx5_esw_bridge *bridge) +{ + debugfs_remove_recursive(bridge->debugfs_dir); + bridge->debugfs_dir = NULL; +} + +void mlx5_esw_bridge_debugfs_offloads_init(struct mlx5_esw_bridge_offloads *br_offloads) +{ + if (!br_offloads->esw->debugfs_root) + return; + + br_offloads->debugfs_root = debugfs_create_dir("bridge", br_offloads->esw->debugfs_root); +} + +void mlx5_esw_bridge_debugfs_offloads_cleanup(struct mlx5_esw_bridge_offloads *br_offloads) +{ + debugfs_remove_recursive(br_offloads->debugfs_root); + br_offloads->debugfs_root = NULL; +} diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge_mcast.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge_mcast.c index 2eae594a5e80fd1eced99a474f35e8128ed279a6..2455f8b93c1e504e91fb722fc4c77a357b0aaeec 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge_mcast.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge_mcast.c @@ -540,16 +540,29 @@ static struct mlx5_flow_handle * mlx5_esw_bridge_mcast_filter_flow_peer_create(struct mlx5_esw_bridge_port *port) { struct mlx5_devcom *devcom = port->bridge->br_offloads->esw->dev->priv.devcom; + struct mlx5_eswitch *tmp, *peer_esw = NULL; static struct mlx5_flow_handle *handle; - struct mlx5_eswitch *peer_esw; + int i; - peer_esw = mlx5_devcom_get_peer_data(devcom, MLX5_DEVCOM_ESW_OFFLOADS); - if (!peer_esw) + if (!mlx5_devcom_for_each_peer_begin(devcom, MLX5_DEVCOM_ESW_OFFLOADS)) return ERR_PTR(-ENODEV); + mlx5_devcom_for_each_peer_entry(devcom, + MLX5_DEVCOM_ESW_OFFLOADS, + tmp, i) { + if (mlx5_esw_is_owner(tmp, port->vport_num, port->esw_owner_vhca_id)) { + peer_esw = tmp; + break; + } + } + if (!peer_esw) { + mlx5_devcom_for_each_peer_end(devcom, MLX5_DEVCOM_ESW_OFFLOADS); + return ERR_PTR(-ENODEV); + } + handle = mlx5_esw_bridge_mcast_flow_with_esw_create(port, peer_esw); - mlx5_devcom_release_peer_data(devcom, MLX5_DEVCOM_ESW_OFFLOADS); + mlx5_devcom_for_each_peer_end(devcom, MLX5_DEVCOM_ESW_OFFLOADS); return handle; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge_priv.h b/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge_priv.h index c9595801bdb4787f8b65b2d11aa66d7b53d7fb63..4911cc32161b4267f7c700061afb93f65a05d9e4 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge_priv.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge_priv.h @@ -199,6 +199,7 @@ struct mlx5_esw_bridge { int refcnt; struct list_head list; struct mlx5_esw_bridge_offloads *br_offloads; + struct dentry *debugfs_dir; struct list_head fdb_list; struct rhashtable fdb_ht; @@ -241,4 +242,9 @@ void mlx5_esw_bridge_port_mdb_vlan_flush(struct mlx5_esw_bridge_port *port, struct mlx5_esw_bridge_vlan *vlan); void mlx5_esw_bridge_mdb_flush(struct mlx5_esw_bridge *bridge); +void mlx5_esw_bridge_debugfs_offloads_init(struct mlx5_esw_bridge_offloads *br_offloads); +void mlx5_esw_bridge_debugfs_offloads_cleanup(struct mlx5_esw_bridge_offloads *br_offloads); +void mlx5_esw_bridge_debugfs_init(struct net_device *br_netdev, struct mlx5_esw_bridge *bridge); +void mlx5_esw_bridge_debugfs_cleanup(struct mlx5_esw_bridge *bridge); + #endif /* _MLX5_ESW_BRIDGE_PRIVATE_ */ diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c index 084a910bb4e74045021a67ef7fff18f150a656db..af779c700278ed4f4c5c4c203c231de85ffbe731 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c @@ -18,7 +18,8 @@ static bool mlx5_esw_devlink_port_supported(struct mlx5_eswitch *esw, u16 vport_ { return vport_num == MLX5_VPORT_UPLINK || (mlx5_core_is_ecpf(esw->dev) && vport_num == MLX5_VPORT_PF) || - mlx5_eswitch_is_vf_vport(esw, vport_num); + mlx5_eswitch_is_vf_vport(esw, vport_num) || + mlx5_core_is_ec_vf_vport(esw->dev, vport_num); } static struct devlink_port *mlx5_esw_dl_port_alloc(struct mlx5_eswitch *esw, u16 vport_num) @@ -56,6 +57,11 @@ static struct devlink_port *mlx5_esw_dl_port_alloc(struct mlx5_eswitch *esw, u16 dl_port->attrs.switch_id.id_len = ppid.id_len; devlink_port_attrs_pci_vf_set(dl_port, controller_num, pfnum, vport_num - 1, external); + } else if (mlx5_core_is_ec_vf_vport(esw->dev, vport_num)) { + memcpy(dl_port->attrs.switch_id.id, ppid.id, ppid.id_len); + dl_port->attrs.switch_id.id_len = ppid.id_len; + devlink_port_attrs_pci_vf_set(dl_port, controller_num, pfnum, + vport_num - 1, false); } return dl_port; } @@ -65,6 +71,15 @@ static void mlx5_esw_dl_port_free(struct devlink_port *dl_port) kfree(dl_port); } +static const struct devlink_port_ops mlx5_esw_dl_port_ops = { + .port_fn_hw_addr_get = mlx5_devlink_port_fn_hw_addr_get, + .port_fn_hw_addr_set = mlx5_devlink_port_fn_hw_addr_set, + .port_fn_roce_get = mlx5_devlink_port_fn_roce_get, + .port_fn_roce_set = mlx5_devlink_port_fn_roce_set, + .port_fn_migratable_get = mlx5_devlink_port_fn_migratable_get, + .port_fn_migratable_set = mlx5_devlink_port_fn_migratable_set, +}; + int mlx5_esw_offloads_devlink_port_register(struct mlx5_eswitch *esw, u16 vport_num) { struct mlx5_core_dev *dev = esw->dev; @@ -87,7 +102,8 @@ int mlx5_esw_offloads_devlink_port_register(struct mlx5_eswitch *esw, u16 vport_ devlink = priv_to_devlink(dev); dl_port_index = mlx5_esw_vport_to_devlink_port_index(dev, vport_num); - err = devl_port_register(devlink, dl_port, dl_port_index); + err = devl_port_register_with_ops(devlink, dl_port, dl_port_index, + &mlx5_esw_dl_port_ops); if (err) goto reg_err; @@ -134,6 +150,20 @@ struct devlink_port *mlx5_esw_offloads_devlink_port(struct mlx5_eswitch *esw, u1 return IS_ERR(vport) ? ERR_CAST(vport) : vport->dl_port; } +static const struct devlink_port_ops mlx5_esw_dl_sf_port_ops = { +#ifdef CONFIG_MLX5_SF_MANAGER + .port_del = mlx5_devlink_sf_port_del, +#endif + .port_fn_hw_addr_get = mlx5_devlink_port_fn_hw_addr_get, + .port_fn_hw_addr_set = mlx5_devlink_port_fn_hw_addr_set, + .port_fn_roce_get = mlx5_devlink_port_fn_roce_get, + .port_fn_roce_set = mlx5_devlink_port_fn_roce_set, +#ifdef CONFIG_MLX5_SF_MANAGER + .port_fn_state_get = mlx5_devlink_sf_port_fn_state_get, + .port_fn_state_set = mlx5_devlink_sf_port_fn_state_set, +#endif +}; + int mlx5_esw_devlink_sf_port_register(struct mlx5_eswitch *esw, struct devlink_port *dl_port, u16 vport_num, u32 controller, u32 sfnum) { @@ -156,7 +186,8 @@ int mlx5_esw_devlink_sf_port_register(struct mlx5_eswitch *esw, struct devlink_p devlink_port_attrs_pci_sf_set(dl_port, controller, pfnum, sfnum, !!controller); devlink = priv_to_devlink(dev); dl_port_index = mlx5_esw_vport_to_devlink_port_index(dev, vport_num); - err = devl_port_register(devlink, dl_port, dl_port_index); + err = devl_port_register_with_ops(devlink, dl_port, dl_port_index, + &mlx5_esw_dl_sf_port_ops); if (err) return err; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/legacy.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/legacy.c index fabe49a35a5c963a12dfbd4bd4aabdf8f98b4638..255bc8b749f9a52139d0eb998154c1c4a5aae41e 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/esw/legacy.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/legacy.c @@ -285,9 +285,8 @@ static int _mlx5_eswitch_set_vepa_locked(struct mlx5_eswitch *esw, if (IS_ERR(flow_rule)) { err = PTR_ERR(flow_rule); goto out; - } else { - esw->fdb_table.legacy.vepa_uplink_rule = flow_rule; } + esw->fdb_table.legacy.vepa_uplink_rule = flow_rule; /* Star rule to forward all traffic to uplink vport */ memset(&dest, 0, sizeof(dest)); @@ -299,9 +298,8 @@ static int _mlx5_eswitch_set_vepa_locked(struct mlx5_eswitch *esw, if (IS_ERR(flow_rule)) { err = PTR_ERR(flow_rule); goto out; - } else { - esw->fdb_table.legacy.vepa_star_rule = flow_rule; } + esw->fdb_table.legacy.vepa_star_rule = flow_rule; out: kvfree(spec); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c index 901c53751b0aa2691567f2b78d53e94f9fcaac99..243c455f102979c3d9da7e7bef8bc6fa5ea3978a 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c @@ -31,6 +31,7 @@ */ #include +#include #include #include #include @@ -41,6 +42,7 @@ #include "esw/qos.h" #include "mlx5_core.h" #include "lib/eq.h" +#include "lag/lag.h" #include "eswitch.h" #include "fs_core.h" #include "devlink.h" @@ -92,7 +94,7 @@ mlx5_eswitch_get_vport(struct mlx5_eswitch *esw, u16 vport_num) { struct mlx5_vport *vport; - if (!esw || !MLX5_CAP_GEN(esw->dev, vport_group_manager)) + if (!esw) return ERR_PTR(-EPERM); vport = xa_load(&esw->vports, vport_num); @@ -113,7 +115,8 @@ static int arm_vport_context_events_cmd(struct mlx5_core_dev *dev, u16 vport, opcode, MLX5_CMD_OP_MODIFY_NIC_VPORT_CONTEXT); MLX5_SET(modify_nic_vport_context_in, in, field_select.change_event, 1); MLX5_SET(modify_nic_vport_context_in, in, vport_number, vport); - MLX5_SET(modify_nic_vport_context_in, in, other_vport, 1); + if (vport || mlx5_core_is_ecpf(dev)) + MLX5_SET(modify_nic_vport_context_in, in, other_vport, 1); nic_vport_ctx = MLX5_ADDR_OF(modify_nic_vport_context_in, in, nic_vport_context); @@ -309,11 +312,12 @@ static int esw_add_uc_addr(struct mlx5_eswitch *esw, struct vport_addr *vaddr) fdb_add: /* SRIOV is enabled: Forward UC MAC to vport */ - if (esw->fdb_table.legacy.fdb && esw->mode == MLX5_ESWITCH_LEGACY) + if (esw->fdb_table.legacy.fdb && esw->mode == MLX5_ESWITCH_LEGACY) { vaddr->flow_rule = esw_fdb_set_vport_rule(esw, mac, vport); - esw_debug(esw->dev, "\tADDED UC MAC: vport[%d] %pM fr(%p)\n", - vport, mac, vaddr->flow_rule); + esw_debug(esw->dev, "\tADDED UC MAC: vport[%d] %pM fr(%p)\n", + vport, mac, vaddr->flow_rule); + } return 0; } @@ -710,6 +714,9 @@ void esw_vport_change_handle_locked(struct mlx5_vport *vport) struct mlx5_eswitch *esw = dev->priv.eswitch; u8 mac[ETH_ALEN]; + if (!MLX5_CAP_GEN(dev, log_max_l2_table)) + return; + mlx5_query_nic_vport_mac_address(dev, vport->vport, true, mac); esw_debug(dev, "vport[%d] Context Changed: perm mac: %pM\n", vport->vport, mac); @@ -800,6 +807,9 @@ static int mlx5_esw_vport_caps_get(struct mlx5_eswitch *esw, struct mlx5_vport * hca_caps = MLX5_ADDR_OF(query_hca_cap_out, query_ctx, capability); vport->info.roce_enabled = MLX5_GET(cmd_hca_cap, hca_caps, roce); + if (!MLX5_CAP_GEN_MAX(esw->dev, hca_cap_2)) + goto out_free; + memset(query_ctx, 0, query_out_sz); err = mlx5_vport_get_other_func_cap(esw->dev, vport->vport, query_ctx, MLX5_CAP_GENERAL_2); @@ -946,7 +956,8 @@ void mlx5_esw_vport_disable(struct mlx5_eswitch *esw, u16 vport_num) vport->enabled = false; /* Disable events from this vport */ - arm_vport_context_events_cmd(esw->dev, vport->vport, 0); + if (MLX5_CAP_GEN(esw->dev, log_max_l2_table)) + arm_vport_context_events_cmd(esw->dev, vport->vport, 0); if (!mlx5_esw_is_manager_vport(esw, vport->vport) && MLX5_CAP_GEN(esw->dev, vhca_resource_manager)) @@ -1045,6 +1056,18 @@ static void mlx5_eswitch_clear_vf_vports_info(struct mlx5_eswitch *esw) } } +static void mlx5_eswitch_clear_ec_vf_vports_info(struct mlx5_eswitch *esw) +{ + struct mlx5_vport *vport; + unsigned long i; + + mlx5_esw_for_each_ec_vf_vport(esw, i, vport, esw->esw_funcs.num_ec_vfs) { + memset(&vport->qos, 0, sizeof(vport->qos)); + memset(&vport->info, 0, sizeof(vport->info)); + vport->info.link_state = MLX5_VPORT_ADMIN_STATE_AUTO; + } +} + /* Public E-Switch API */ int mlx5_eswitch_load_vport(struct mlx5_eswitch *esw, u16 vport_num, enum mlx5_eswitch_vport_event enabled_events) @@ -1084,6 +1107,19 @@ void mlx5_eswitch_unload_vf_vports(struct mlx5_eswitch *esw, u16 num_vfs) } } +static void mlx5_eswitch_unload_ec_vf_vports(struct mlx5_eswitch *esw, + u16 num_ec_vfs) +{ + struct mlx5_vport *vport; + unsigned long i; + + mlx5_esw_for_each_ec_vf_vport(esw, i, vport, num_ec_vfs) { + if (!vport->enabled) + continue; + mlx5_eswitch_unload_vport(esw, vport->vport); + } +} + int mlx5_eswitch_load_vf_vports(struct mlx5_eswitch *esw, u16 num_vfs, enum mlx5_eswitch_vport_event enabled_events) { @@ -1104,6 +1140,26 @@ int mlx5_eswitch_load_vf_vports(struct mlx5_eswitch *esw, u16 num_vfs, return err; } +static int mlx5_eswitch_load_ec_vf_vports(struct mlx5_eswitch *esw, u16 num_ec_vfs, + enum mlx5_eswitch_vport_event enabled_events) +{ + struct mlx5_vport *vport; + unsigned long i; + int err; + + mlx5_esw_for_each_ec_vf_vport(esw, i, vport, num_ec_vfs) { + err = mlx5_eswitch_load_vport(esw, vport->vport, enabled_events); + if (err) + goto vf_err; + } + + return 0; + +vf_err: + mlx5_eswitch_unload_ec_vf_vports(esw, num_ec_vfs); + return err; +} + static int host_pf_enable_hca(struct mlx5_core_dev *dev) { if (!mlx5_core_is_ecpf(dev)) @@ -1148,6 +1204,12 @@ mlx5_eswitch_enable_pf_vf_vports(struct mlx5_eswitch *esw, ret = mlx5_eswitch_load_vport(esw, MLX5_VPORT_ECPF, enabled_events); if (ret) goto ecpf_err; + if (mlx5_core_ec_sriov_enabled(esw->dev)) { + ret = mlx5_eswitch_load_ec_vf_vports(esw, esw->esw_funcs.num_ec_vfs, + enabled_events); + if (ret) + goto ec_vf_err; + } } /* Enable VF vports */ @@ -1158,6 +1220,9 @@ mlx5_eswitch_enable_pf_vf_vports(struct mlx5_eswitch *esw, return 0; vf_err: + if (mlx5_core_ec_sriov_enabled(esw->dev)) + mlx5_eswitch_unload_ec_vf_vports(esw, esw->esw_funcs.num_ec_vfs); +ec_vf_err: if (mlx5_ecpf_vport_exists(esw->dev)) mlx5_eswitch_unload_vport(esw, MLX5_VPORT_ECPF); ecpf_err: @@ -1174,8 +1239,11 @@ void mlx5_eswitch_disable_pf_vf_vports(struct mlx5_eswitch *esw) { mlx5_eswitch_unload_vf_vports(esw, esw->esw_funcs.num_vfs); - if (mlx5_ecpf_vport_exists(esw->dev)) + if (mlx5_ecpf_vport_exists(esw->dev)) { + if (mlx5_core_ec_sriov_enabled(esw->dev)) + mlx5_eswitch_unload_ec_vf_vports(esw, esw->esw_funcs.num_vfs); mlx5_eswitch_unload_vport(esw, MLX5_VPORT_ECPF); + } host_pf_disable_hca(esw->dev); mlx5_eswitch_unload_vport(esw, MLX5_VPORT_PF); @@ -1219,6 +1287,9 @@ mlx5_eswitch_update_num_of_vfs(struct mlx5_eswitch *esw, int num_vfs) esw->esw_funcs.num_vfs = MLX5_GET(query_esw_functions_out, out, host_params_context.host_num_of_vfs); + if (mlx5_core_ec_sriov_enabled(esw->dev)) + esw->esw_funcs.num_ec_vfs = num_vfs; + kvfree(out); } @@ -1326,9 +1397,9 @@ int mlx5_eswitch_enable_locked(struct mlx5_eswitch *esw, int num_vfs) mlx5_eswitch_event_handlers_register(esw); - esw_info(esw->dev, "Enable: mode(%s), nvfs(%d), active vports(%d)\n", + esw_info(esw->dev, "Enable: mode(%s), nvfs(%d), necvfs(%d), active vports(%d)\n", esw->mode == MLX5_ESWITCH_LEGACY ? "LEGACY" : "OFFLOADS", - esw->esw_funcs.num_vfs, esw->enabled_vports); + esw->esw_funcs.num_vfs, esw->esw_funcs.num_ec_vfs, esw->enabled_vports); mlx5_esw_mode_change_notify(esw, esw->mode); @@ -1350,7 +1421,7 @@ int mlx5_eswitch_enable_locked(struct mlx5_eswitch *esw, int num_vfs) int mlx5_eswitch_enable(struct mlx5_eswitch *esw, int num_vfs) { bool toggle_lag; - int ret; + int ret = 0; if (!mlx5_esw_allowed(esw)) return 0; @@ -1370,10 +1441,21 @@ int mlx5_eswitch_enable(struct mlx5_eswitch *esw, int num_vfs) vport_events = (esw->mode == MLX5_ESWITCH_LEGACY) ? MLX5_LEGACY_SRIOV_VPORT_EVENTS : MLX5_VPORT_UC_ADDR_CHANGE; - ret = mlx5_eswitch_load_vf_vports(esw, num_vfs, vport_events); - if (!ret) - esw->esw_funcs.num_vfs = num_vfs; + /* If this is the ECPF the number of host VFs is managed via the + * eswitch function change event handler, and any num_vfs provided + * here are intended to be EC VFs. + */ + if (!mlx5_core_is_ecpf(esw->dev)) { + ret = mlx5_eswitch_load_vf_vports(esw, num_vfs, vport_events); + if (!ret) + esw->esw_funcs.num_vfs = num_vfs; + } else if (mlx5_core_ec_sriov_enabled(esw->dev)) { + ret = mlx5_eswitch_load_ec_vf_vports(esw, num_vfs, vport_events); + if (!ret) + esw->esw_funcs.num_ec_vfs = num_vfs; + } } + up_write(&esw->mode_lock); if (toggle_lag) @@ -1393,16 +1475,22 @@ void mlx5_eswitch_disable_sriov(struct mlx5_eswitch *esw, bool clear_vf) /* If driver is unloaded, this function is called twice by remove_one() * and mlx5_unload(). Prevent the second call. */ - if (!esw->esw_funcs.num_vfs && !clear_vf) + if (!esw->esw_funcs.num_vfs && !esw->esw_funcs.num_ec_vfs && !clear_vf) goto unlock; - esw_info(esw->dev, "Unload vfs: mode(%s), nvfs(%d), active vports(%d)\n", + esw_info(esw->dev, "Unload vfs: mode(%s), nvfs(%d), necvfs(%d), active vports(%d)\n", esw->mode == MLX5_ESWITCH_LEGACY ? "LEGACY" : "OFFLOADS", - esw->esw_funcs.num_vfs, esw->enabled_vports); - - mlx5_eswitch_unload_vf_vports(esw, esw->esw_funcs.num_vfs); - if (clear_vf) - mlx5_eswitch_clear_vf_vports_info(esw); + esw->esw_funcs.num_vfs, esw->esw_funcs.num_ec_vfs, esw->enabled_vports); + + if (!mlx5_core_is_ecpf(esw->dev)) { + mlx5_eswitch_unload_vf_vports(esw, esw->esw_funcs.num_vfs); + if (clear_vf) + mlx5_eswitch_clear_vf_vports_info(esw); + } else if (mlx5_core_ec_sriov_enabled(esw->dev)) { + mlx5_eswitch_unload_ec_vf_vports(esw, esw->esw_funcs.num_ec_vfs); + if (clear_vf) + mlx5_eswitch_clear_ec_vf_vports_info(esw); + } if (esw->mode == MLX5_ESWITCH_OFFLOADS) { struct devlink *devlink = priv_to_devlink(esw->dev); @@ -1413,7 +1501,10 @@ void mlx5_eswitch_disable_sriov(struct mlx5_eswitch *esw, bool clear_vf) if (esw->mode == MLX5_ESWITCH_LEGACY) mlx5_eswitch_disable_locked(esw); - esw->esw_funcs.num_vfs = 0; + if (!mlx5_core_is_ecpf(esw->dev)) + esw->esw_funcs.num_vfs = 0; + else + esw->esw_funcs.num_ec_vfs = 0; unlock: up_write(&esw->mode_lock); @@ -1433,9 +1524,9 @@ void mlx5_eswitch_disable_locked(struct mlx5_eswitch *esw) mlx5_eswitch_event_handlers_unregister(esw); - esw_info(esw->dev, "Disable: mode(%s), nvfs(%d), active vports(%d)\n", + esw_info(esw->dev, "Disable: mode(%s), nvfs(%d), necvfs(%d), active vports(%d)\n", esw->mode == MLX5_ESWITCH_LEGACY ? "LEGACY" : "OFFLOADS", - esw->esw_funcs.num_vfs, esw->enabled_vports); + esw->esw_funcs.num_vfs, esw->esw_funcs.num_ec_vfs, esw->enabled_vports); if (esw->fdb_table.flags & MLX5_ESW_FDB_CREATED) { esw->fdb_table.flags &= ~MLX5_ESW_FDB_CREATED; @@ -1595,7 +1686,19 @@ static int mlx5_esw_vports_init(struct mlx5_eswitch *esw) idx++; } - if (mlx5_ecpf_vport_exists(dev)) { + if (mlx5_core_ec_sriov_enabled(esw->dev)) { + int ec_vf_base_num = mlx5_core_ec_vf_vport_base(dev); + + for (i = 0; i < mlx5_core_max_ec_vfs(esw->dev); i++) { + err = mlx5_esw_vport_alloc(esw, idx, ec_vf_base_num + i); + if (err) + goto err; + idx++; + } + } + + if (mlx5_ecpf_vport_exists(dev) || + mlx5_core_is_ecpf_esw_manager(dev)) { err = mlx5_esw_vport_alloc(esw, idx, MLX5_VPORT_ECPF); if (err) goto err; @@ -1611,22 +1714,60 @@ static int mlx5_esw_vports_init(struct mlx5_eswitch *esw) return err; } +static int mlx5_devlink_esw_multiport_set(struct devlink *devlink, u32 id, + struct devlink_param_gset_ctx *ctx) +{ + struct mlx5_core_dev *dev = devlink_priv(devlink); + + if (!MLX5_ESWITCH_MANAGER(dev)) + return -EOPNOTSUPP; + + if (ctx->val.vbool) + return mlx5_lag_mpesw_enable(dev); + + mlx5_lag_mpesw_disable(dev); + return 0; +} + +static int mlx5_devlink_esw_multiport_get(struct devlink *devlink, u32 id, + struct devlink_param_gset_ctx *ctx) +{ + struct mlx5_core_dev *dev = devlink_priv(devlink); + + ctx->val.vbool = mlx5_lag_is_mpesw(dev); + return 0; +} + +static const struct devlink_param mlx5_eswitch_params[] = { + DEVLINK_PARAM_DRIVER(MLX5_DEVLINK_PARAM_ID_ESW_MULTIPORT, + "esw_multiport", DEVLINK_PARAM_TYPE_BOOL, + BIT(DEVLINK_PARAM_CMODE_RUNTIME), + mlx5_devlink_esw_multiport_get, + mlx5_devlink_esw_multiport_set, NULL), +}; + int mlx5_eswitch_init(struct mlx5_core_dev *dev) { struct mlx5_eswitch *esw; int err; - if (!MLX5_VPORT_MANAGER(dev)) + if (!MLX5_VPORT_MANAGER(dev) && !MLX5_ESWITCH_MANAGER(dev)) return 0; esw = kzalloc(sizeof(*esw), GFP_KERNEL); if (!esw) return -ENOMEM; + err = devl_params_register(priv_to_devlink(dev), mlx5_eswitch_params, + ARRAY_SIZE(mlx5_eswitch_params)); + if (err) + goto free_esw; + esw->dev = dev; esw->manager_vport = mlx5_eswitch_manager_vport(dev); esw->first_host_vport = mlx5_eswitch_first_host_vport_num(dev); + esw->debugfs_root = debugfs_create_dir("esw", mlx5_debugfs_get_dev_root(dev)); esw->work_queue = create_singlethread_workqueue("mlx5_esw_wq"); if (!esw->work_queue) { err = -ENOMEM; @@ -1680,13 +1821,17 @@ int mlx5_eswitch_init(struct mlx5_core_dev *dev) abort: if (esw->work_queue) destroy_workqueue(esw->work_queue); + debugfs_remove_recursive(esw->debugfs_root); + devl_params_unregister(priv_to_devlink(dev), mlx5_eswitch_params, + ARRAY_SIZE(mlx5_eswitch_params)); +free_esw: kfree(esw); return err; } void mlx5_eswitch_cleanup(struct mlx5_eswitch *esw) { - if (!esw || !MLX5_VPORT_MANAGER(esw->dev)) + if (!esw) return; esw_info(esw->dev, "cleanup\n"); @@ -1703,6 +1848,9 @@ void mlx5_eswitch_cleanup(struct mlx5_eswitch *esw) mutex_destroy(&esw->offloads.decap_tbl_lock); esw_offloads_cleanup(esw); mlx5_esw_vports_cleanup(esw); + debugfs_remove_recursive(esw->debugfs_root); + devl_params_unregister(priv_to_devlink(esw->dev), mlx5_eswitch_params, + ARRAY_SIZE(mlx5_eswitch_params)); kfree(esw); } @@ -1763,12 +1911,6 @@ int mlx5_eswitch_set_vport_mac(struct mlx5_eswitch *esw, static bool mlx5_esw_check_port_type(struct mlx5_eswitch *esw, u16 vport_num, xa_mark_t mark) { - struct mlx5_vport *vport; - - vport = mlx5_eswitch_get_vport(esw, vport_num); - if (IS_ERR(vport)) - return false; - return xa_get_mark(&esw->vports, vport_num, mark); } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h index add6cfa432a5b7dd2c5cd4830a576d3ec9a00e7e..ae0dc8a3060d735569abf917e3f5993b78d37329 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h @@ -123,8 +123,14 @@ struct vport_ingress { } offloads; }; +enum vport_egress_acl_type { + VPORT_EGRESS_ACL_TYPE_DEFAULT, + VPORT_EGRESS_ACL_TYPE_SHARED_FDB, +}; + struct vport_egress { struct mlx5_flow_table *acl; + enum vport_egress_acl_type type; struct mlx5_flow_handle *allowed_vlan; struct mlx5_flow_group *vlan_grp; union { @@ -136,7 +142,7 @@ struct vport_egress { struct { struct mlx5_flow_group *fwd_grp; struct mlx5_flow_handle *fwd_rule; - struct mlx5_flow_handle *bounce_rule; + struct xarray bounce_rules; struct mlx5_flow_group *bounce_grp; } offloads; }; @@ -218,7 +224,7 @@ struct mlx5_eswitch_fdb { struct mlx5_flow_group *send_to_vport_grp; struct mlx5_flow_group *send_to_vport_meta_grp; struct mlx5_flow_group *peer_miss_grp; - struct mlx5_flow_handle **peer_miss_rules; + struct mlx5_flow_handle **peer_miss_rules[MLX5_MAX_PORTS]; struct mlx5_flow_group *miss_grp; struct mlx5_flow_handle **send_to_vport_meta_rules; struct mlx5_flow_handle *miss_rule_uni; @@ -249,7 +255,7 @@ struct mlx5_esw_offload { struct mlx5_flow_group *vport_rx_drop_group; struct mlx5_flow_handle *vport_rx_drop_rule; struct xarray vport_reps; - struct list_head peer_flows; + struct list_head peer_flows[MLX5_MAX_PORTS]; struct mutex peer_mutex; struct mutex encap_tbl_lock; /* protects encap_tbl */ DECLARE_HASHTABLE(encap_tbl, 8); @@ -283,6 +289,7 @@ struct mlx5_host_work { struct mlx5_esw_functions { struct mlx5_nb nb; u16 num_vfs; + u16 num_ec_vfs; }; enum { @@ -297,6 +304,8 @@ enum { MLX5_ESW_FDB_CREATED = BIT(0), }; +struct dentry; + struct mlx5_eswitch { struct mlx5_core_dev *dev; struct mlx5_nb nb; @@ -305,6 +314,7 @@ struct mlx5_eswitch { struct hlist_head mc_table[MLX5_L2_ADDR_HASH_SIZE]; struct esw_mc_addr mc_promisc; /* end of legacy */ + struct dentry *debugfs_root; struct workqueue_struct *work_queue; struct xarray vports; u32 flags; @@ -337,12 +347,13 @@ struct mlx5_eswitch { int mode; u16 manager_vport; u16 first_host_vport; + u8 num_peers; struct mlx5_esw_functions esw_funcs; struct { u32 large_group_num; } params; struct blocking_notifier_head n_head; - bool paired[MLX5_MAX_PORTS]; + struct xarray paired; }; void esw_offloads_disable(struct mlx5_eswitch *esw); @@ -506,12 +517,12 @@ int mlx5_devlink_eswitch_encap_mode_set(struct devlink *devlink, struct netlink_ext_ack *extack); int mlx5_devlink_eswitch_encap_mode_get(struct devlink *devlink, enum devlink_eswitch_encap_mode *encap); -int mlx5_devlink_port_function_hw_addr_get(struct devlink_port *port, - u8 *hw_addr, int *hw_addr_len, - struct netlink_ext_ack *extack); -int mlx5_devlink_port_function_hw_addr_set(struct devlink_port *port, - const u8 *hw_addr, int hw_addr_len, - struct netlink_ext_ack *extack); +int mlx5_devlink_port_fn_hw_addr_get(struct devlink_port *port, + u8 *hw_addr, int *hw_addr_len, + struct netlink_ext_ack *extack); +int mlx5_devlink_port_fn_hw_addr_set(struct devlink_port *port, + const u8 *hw_addr, int hw_addr_len, + struct netlink_ext_ack *extack); int mlx5_devlink_port_fn_roce_get(struct devlink_port *port, bool *is_enabled, struct netlink_ext_ack *extack); int mlx5_devlink_port_fn_roce_set(struct devlink_port *port, bool enable, @@ -578,6 +589,13 @@ mlx5_esw_is_manager_vport(const struct mlx5_eswitch *esw, u16 vport_num) return esw->manager_vport == vport_num; } +static inline bool mlx5_esw_is_owner(struct mlx5_eswitch *esw, u16 vport_num, + u16 esw_owner_vhca_id) +{ + return esw_owner_vhca_id == MLX5_CAP_GEN(esw->dev, vhca_id) || + (vport_num == MLX5_VPORT_UPLINK && mlx5_lag_is_master(esw->dev)); +} + static inline u16 mlx5_eswitch_first_host_vport_num(struct mlx5_core_dev *dev) { return mlx5_core_is_ecpf_esw_manager(dev) ? @@ -640,6 +658,19 @@ void mlx5e_tc_clean_fdb_peer_flows(struct mlx5_eswitch *esw); #define mlx5_esw_for_each_host_func_vport(esw, index, vport, last) \ mlx5_esw_for_each_vport_marked(esw, index, vport, last, MLX5_ESW_VPT_HOST_FN) +/* This macro should only be used if EC SRIOV is enabled. + * + * Because there were no more marks available on the xarray this uses a + * for_each_range approach. The range is only valid when EC SRIOV is enabled + */ +#define mlx5_esw_for_each_ec_vf_vport(esw, index, vport, last) \ + xa_for_each_range(&((esw)->vports), \ + index, \ + vport, \ + MLX5_CAP_GEN_2((esw->dev), ec_vf_vport_base), \ + MLX5_CAP_GEN_2((esw->dev), ec_vf_vport_base) +\ + (last) - 1) + struct mlx5_eswitch *mlx5_devlink_eswitch_get(struct devlink *devlink); struct mlx5_vport *__must_check mlx5_eswitch_get_vport(struct mlx5_eswitch *esw, u16 vport_num); @@ -686,6 +717,14 @@ mlx5_esw_vporttbl_put(struct mlx5_eswitch *esw, struct mlx5_vport_tbl_attr *attr struct mlx5_flow_handle * esw_add_restore_rule(struct mlx5_eswitch *esw, u32 tag); +void mlx5_esw_set_flow_group_source_port(struct mlx5_eswitch *esw, + u32 *flow_group_in, + int match_params); + +void mlx5_esw_set_spec_source_port(struct mlx5_eswitch *esw, + u16 vport, + struct mlx5_flow_spec *spec); + int esw_offloads_load_rep(struct mlx5_eswitch *esw, u16 vport_num); void esw_offloads_unload_rep(struct mlx5_eswitch *esw, u16 vport_num); @@ -740,9 +779,9 @@ void esw_vport_change_handle_locked(struct mlx5_vport *vport); bool mlx5_esw_offloads_controller_valid(const struct mlx5_eswitch *esw, u32 controller); -int mlx5_eswitch_offloads_config_single_fdb(struct mlx5_eswitch *master_esw, - struct mlx5_eswitch *slave_esw); -void mlx5_eswitch_offloads_destroy_single_fdb(struct mlx5_eswitch *master_esw, +int mlx5_eswitch_offloads_single_fdb_add_one(struct mlx5_eswitch *master_esw, + struct mlx5_eswitch *slave_esw, int max_slaves); +void mlx5_eswitch_offloads_single_fdb_del_one(struct mlx5_eswitch *master_esw, struct mlx5_eswitch *slave_esw); int mlx5_eswitch_reload_reps(struct mlx5_eswitch *esw); @@ -757,6 +796,13 @@ static inline int mlx5_eswitch_num_vfs(struct mlx5_eswitch *esw) return 0; } +static inline int mlx5_eswitch_get_npeers(struct mlx5_eswitch *esw) +{ + if (mlx5_esw_allowed(esw)) + return esw->num_peers; + return 0; +} + static inline struct mlx5_flow_table * mlx5_eswitch_get_slow_fdb(struct mlx5_eswitch *esw) { @@ -794,16 +840,18 @@ mlx5_esw_vport_to_devlink_port_index(const struct mlx5_core_dev *dev, } static inline int -mlx5_eswitch_offloads_config_single_fdb(struct mlx5_eswitch *master_esw, - struct mlx5_eswitch *slave_esw) +mlx5_eswitch_offloads_single_fdb_add_one(struct mlx5_eswitch *master_esw, + struct mlx5_eswitch *slave_esw, int max_slaves) { return 0; } static inline void -mlx5_eswitch_offloads_destroy_single_fdb(struct mlx5_eswitch *master_esw, +mlx5_eswitch_offloads_single_fdb_del_one(struct mlx5_eswitch *master_esw, struct mlx5_eswitch *slave_esw) {} +static inline int mlx5_eswitch_get_npeers(struct mlx5_eswitch *esw) { return 0; } + static inline int mlx5_eswitch_reload_reps(struct mlx5_eswitch *esw) { diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c index 8d19c20d3447e67cb63b4e7b4ead294ba3147b66..bdfe609cc9ec4a4924901ef4c687ad9384a21e02 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c @@ -55,13 +55,6 @@ #define mlx5_esw_for_each_rep(esw, i, rep) \ xa_for_each(&((esw)->offloads.vport_reps), i, rep) -#define mlx5_esw_for_each_sf_rep(esw, i, rep) \ - xa_for_each_marked(&((esw)->offloads.vport_reps), i, rep, MLX5_ESW_VPT_SF) - -#define mlx5_esw_for_each_vf_rep(esw, index, rep) \ - mlx5_esw_for_each_entry_marked(&((esw)->offloads.vport_reps), index, \ - rep, (esw)->esw_funcs.num_vfs, MLX5_ESW_VPT_VF) - /* There are two match-all miss flows, one for unicast dst mac and * one for multicast. */ @@ -838,6 +831,7 @@ mlx5_eswitch_add_send_to_vport_rule(struct mlx5_eswitch *on_esw, struct mlx5_flow_handle *flow_rule; struct mlx5_flow_spec *spec; void *misc; + u16 vport; spec = kvzalloc(sizeof(*spec), GFP_KERNEL); if (!spec) { @@ -847,20 +841,43 @@ mlx5_eswitch_add_send_to_vport_rule(struct mlx5_eswitch *on_esw, misc = MLX5_ADDR_OF(fte_match_param, spec->match_value, misc_parameters); MLX5_SET(fte_match_set_misc, misc, source_sqn, sqn); - /* source vport is the esw manager */ - MLX5_SET(fte_match_set_misc, misc, source_port, from_esw->manager_vport); - if (MLX5_CAP_ESW(on_esw->dev, merged_eswitch)) - MLX5_SET(fte_match_set_misc, misc, source_eswitch_owner_vhca_id, - MLX5_CAP_GEN(from_esw->dev, vhca_id)); misc = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, misc_parameters); MLX5_SET_TO_ONES(fte_match_set_misc, misc, source_sqn); - MLX5_SET_TO_ONES(fte_match_set_misc, misc, source_port); - if (MLX5_CAP_ESW(on_esw->dev, merged_eswitch)) - MLX5_SET_TO_ONES(fte_match_set_misc, misc, - source_eswitch_owner_vhca_id); spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS; + + /* source vport is the esw manager */ + vport = from_esw->manager_vport; + + if (mlx5_eswitch_vport_match_metadata_enabled(on_esw)) { + misc = MLX5_ADDR_OF(fte_match_param, spec->match_value, misc_parameters_2); + MLX5_SET(fte_match_set_misc2, misc, metadata_reg_c_0, + mlx5_eswitch_get_vport_metadata_for_match(from_esw, vport)); + + misc = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, misc_parameters_2); + MLX5_SET(fte_match_set_misc2, misc, metadata_reg_c_0, + mlx5_eswitch_get_vport_metadata_mask()); + + spec->match_criteria_enable |= MLX5_MATCH_MISC_PARAMETERS_2; + } else { + misc = MLX5_ADDR_OF(fte_match_param, spec->match_value, misc_parameters); + MLX5_SET(fte_match_set_misc, misc, source_port, vport); + + if (MLX5_CAP_ESW(on_esw->dev, merged_eswitch)) + MLX5_SET(fte_match_set_misc, misc, source_eswitch_owner_vhca_id, + MLX5_CAP_GEN(from_esw->dev, vhca_id)); + + misc = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, misc_parameters); + MLX5_SET_TO_ONES(fte_match_set_misc, misc, source_port); + + if (MLX5_CAP_ESW(on_esw->dev, merged_eswitch)) + MLX5_SET_TO_ONES(fte_match_set_misc, misc, + source_eswitch_owner_vhca_id); + + spec->match_criteria_enable |= MLX5_MATCH_MISC_PARAMETERS; + } + dest.type = MLX5_FLOW_DESTINATION_TYPE_VPORT; dest.vport.num = rep->vport; dest.vport.vhca_id = MLX5_CAP_GEN(rep->esw->dev, vhca_id); @@ -1052,6 +1069,9 @@ static int esw_add_fdb_peer_miss_rules(struct mlx5_eswitch *esw, void *misc; int err; + if (!MLX5_VPORT_MANAGER(esw->dev) && !mlx5_core_is_ecpf_esw_manager(esw->dev)) + return 0; + spec = kvzalloc(sizeof(*spec), GFP_KERNEL); if (!spec) return -ENOMEM; @@ -1108,11 +1128,32 @@ static int esw_add_fdb_peer_miss_rules(struct mlx5_eswitch *esw, flows[vport->index] = flow; } - esw->fdb_table.offloads.peer_miss_rules = flows; + if (mlx5_core_ec_sriov_enabled(esw->dev)) { + mlx5_esw_for_each_ec_vf_vport(esw, i, vport, mlx5_core_max_ec_vfs(esw->dev)) { + if (i >= mlx5_core_max_ec_vfs(peer_dev)) + break; + esw_set_peer_miss_rule_source_port(esw, peer_dev->priv.eswitch, + spec, vport->vport); + flow = mlx5_add_flow_rules(esw->fdb_table.offloads.slow_fdb, + spec, &flow_act, &dest, 1); + if (IS_ERR(flow)) { + err = PTR_ERR(flow); + goto add_ec_vf_flow_err; + } + flows[vport->index] = flow; + } + } + esw->fdb_table.offloads.peer_miss_rules[mlx5_get_dev_index(peer_dev)] = flows; kvfree(spec); return 0; +add_ec_vf_flow_err: + mlx5_esw_for_each_ec_vf_vport(esw, i, vport, mlx5_core_max_ec_vfs(esw->dev)) { + if (!flows[vport->index]) + continue; + mlx5_del_flow_rules(flows[vport->index]); + } add_vf_flow_err: mlx5_esw_for_each_vf_vport(esw, i, vport, mlx5_core_max_vfs(esw->dev)) { if (!flows[vport->index]) @@ -1136,13 +1177,28 @@ static int esw_add_fdb_peer_miss_rules(struct mlx5_eswitch *esw, return err; } -static void esw_del_fdb_peer_miss_rules(struct mlx5_eswitch *esw) +static void esw_del_fdb_peer_miss_rules(struct mlx5_eswitch *esw, + struct mlx5_core_dev *peer_dev) { + u16 peer_index = mlx5_get_dev_index(peer_dev); struct mlx5_flow_handle **flows; struct mlx5_vport *vport; unsigned long i; - flows = esw->fdb_table.offloads.peer_miss_rules; + flows = esw->fdb_table.offloads.peer_miss_rules[peer_index]; + if (!flows) + return; + + if (mlx5_core_ec_sriov_enabled(esw->dev)) { + mlx5_esw_for_each_ec_vf_vport(esw, i, vport, mlx5_core_max_ec_vfs(esw->dev)) { + /* The flow for a particular vport could be NULL if the other ECPF + * has fewer or no VFs enabled + */ + if (!flows[vport->index]) + continue; + mlx5_del_flow_rules(flows[vport->index]); + } + } mlx5_esw_for_each_vf_vport(esw, i, vport, mlx5_core_max_vfs(esw->dev)) mlx5_del_flow_rules(flows[vport->index]); @@ -1156,7 +1212,9 @@ static void esw_del_fdb_peer_miss_rules(struct mlx5_eswitch *esw) vport = mlx5_eswitch_get_vport(esw, MLX5_VPORT_PF); mlx5_del_flow_rules(flows[vport->index]); } + kvfree(flows); + esw->fdb_table.offloads.peer_miss_rules[peer_index] = NULL; } static int esw_add_fdb_miss_rule(struct mlx5_eswitch *esw) @@ -1269,8 +1327,10 @@ esw_add_restore_rule(struct mlx5_eswitch *esw, u32 tag) #define MAX_PF_SQ 256 #define MAX_SQ_NVPORTS 32 -static void esw_set_flow_group_source_port(struct mlx5_eswitch *esw, - u32 *flow_group_in) +void +mlx5_esw_set_flow_group_source_port(struct mlx5_eswitch *esw, + u32 *flow_group_in, + int match_params) { void *match_criteria = MLX5_ADDR_OF(create_flow_group_in, flow_group_in, @@ -1279,7 +1339,7 @@ static void esw_set_flow_group_source_port(struct mlx5_eswitch *esw, if (mlx5_eswitch_vport_match_metadata_enabled(esw)) { MLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable, - MLX5_MATCH_MISC_PARAMETERS_2); + MLX5_MATCH_MISC_PARAMETERS_2 | match_params); MLX5_SET(fte_match_param, match_criteria, misc_parameters_2.metadata_reg_c_0, @@ -1287,7 +1347,7 @@ static void esw_set_flow_group_source_port(struct mlx5_eswitch *esw, } else { MLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable, - MLX5_MATCH_MISC_PARAMETERS); + MLX5_MATCH_MISC_PARAMETERS | match_params); MLX5_SET_TO_ONES(fte_match_param, match_criteria, misc_parameters.source_port); @@ -1463,14 +1523,13 @@ esw_create_send_to_vport_group(struct mlx5_eswitch *esw, memset(flow_group_in, 0, inlen); - MLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable, - MLX5_MATCH_MISC_PARAMETERS); + mlx5_esw_set_flow_group_source_port(esw, flow_group_in, MLX5_MATCH_MISC_PARAMETERS); match_criteria = MLX5_ADDR_OF(create_flow_group_in, flow_group_in, match_criteria); - MLX5_SET_TO_ONES(fte_match_param, match_criteria, misc_parameters.source_sqn); - MLX5_SET_TO_ONES(fte_match_param, match_criteria, misc_parameters.source_port); - if (MLX5_CAP_ESW(esw->dev, merged_eswitch)) { + + if (!mlx5_eswitch_vport_match_metadata_enabled(esw) && + MLX5_CAP_ESW(esw->dev, merged_eswitch)) { MLX5_SET_TO_ONES(fte_match_param, match_criteria, misc_parameters.source_eswitch_owner_vhca_id); MLX5_SET(create_flow_group_in, flow_group_in, @@ -1548,6 +1607,7 @@ esw_create_peer_esw_miss_group(struct mlx5_eswitch *esw, u32 *flow_group_in, int *ix) { + int max_peer_ports = (esw->total_vports - 1) * (MLX5_MAX_PORTS - 1); int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in); struct mlx5_flow_group *g; void *match_criteria; @@ -1558,7 +1618,7 @@ esw_create_peer_esw_miss_group(struct mlx5_eswitch *esw, memset(flow_group_in, 0, inlen); - esw_set_flow_group_source_port(esw, flow_group_in); + mlx5_esw_set_flow_group_source_port(esw, flow_group_in, 0); if (!mlx5_eswitch_vport_match_metadata_enabled(esw)) { match_criteria = MLX5_ADDR_OF(create_flow_group_in, @@ -1574,8 +1634,8 @@ esw_create_peer_esw_miss_group(struct mlx5_eswitch *esw, MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, *ix); MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, - *ix + esw->total_vports - 1); - *ix += esw->total_vports; + *ix + max_peer_ports); + *ix += max_peer_ports + 1; g = mlx5_create_flow_group(fdb, flow_group_in); if (IS_ERR(g)) { @@ -1677,7 +1737,7 @@ static int esw_create_offloads_fdb_tables(struct mlx5_eswitch *esw) * total vports of the peer (currently is also uses esw->total_vports). */ table_size = MLX5_MAX_PORTS * (esw->total_vports * MAX_SQ_NVPORTS + MAX_PF_SQ) + - esw->total_vports * 2 + MLX5_ESW_MISS_FLOWS; + esw->total_vports * MLX5_MAX_PORTS + MLX5_ESW_MISS_FLOWS; /* create the slow path fdb with encap set, so further table instances * can be created at run time while VFs are probed if the FW allows that. @@ -1844,8 +1904,7 @@ static int esw_create_vport_rx_group(struct mlx5_eswitch *esw) if (!flow_group_in) return -ENOMEM; - /* create vport rx group */ - esw_set_flow_group_source_port(esw, flow_group_in); + mlx5_esw_set_flow_group_source_port(esw, flow_group_in, 0); MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, 0); MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, nvports - 1); @@ -1915,21 +1974,13 @@ static void esw_destroy_vport_rx_drop_group(struct mlx5_eswitch *esw) mlx5_destroy_flow_group(esw->offloads.vport_rx_drop_group); } -struct mlx5_flow_handle * -mlx5_eswitch_create_vport_rx_rule(struct mlx5_eswitch *esw, u16 vport, - struct mlx5_flow_destination *dest) +void +mlx5_esw_set_spec_source_port(struct mlx5_eswitch *esw, + u16 vport, + struct mlx5_flow_spec *spec) { - struct mlx5_flow_act flow_act = {0}; - struct mlx5_flow_handle *flow_rule; - struct mlx5_flow_spec *spec; void *misc; - spec = kvzalloc(sizeof(*spec), GFP_KERNEL); - if (!spec) { - flow_rule = ERR_PTR(-ENOMEM); - goto out; - } - if (mlx5_eswitch_vport_match_metadata_enabled(esw)) { misc = MLX5_ADDR_OF(fte_match_param, spec->match_value, misc_parameters_2); MLX5_SET(fte_match_set_misc2, misc, metadata_reg_c_0, @@ -1949,6 +2000,23 @@ mlx5_eswitch_create_vport_rx_rule(struct mlx5_eswitch *esw, u16 vport, spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS; } +} + +struct mlx5_flow_handle * +mlx5_eswitch_create_vport_rx_rule(struct mlx5_eswitch *esw, u16 vport, + struct mlx5_flow_destination *dest) +{ + struct mlx5_flow_act flow_act = {0}; + struct mlx5_flow_handle *flow_rule; + struct mlx5_flow_spec *spec; + + spec = kvzalloc(sizeof(*spec), GFP_KERNEL); + if (!spec) { + flow_rule = ERR_PTR(-ENOMEM); + goto out; + } + + mlx5_esw_set_spec_source_port(esw, vport, spec); flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST; flow_rule = mlx5_add_flow_rules(esw->offloads.ft_offloads, spec, @@ -2142,6 +2210,7 @@ static int esw_offloads_start(struct mlx5_eswitch *esw, "Failed setting eswitch to offloads"); esw->mode = MLX5_ESWITCH_LEGACY; mlx5_rescan_drivers(esw->dev); + return err; } if (esw->offloads.inline_mode == MLX5_INLINE_MODE_NONE) { if (mlx5_eswitch_inline_mode_get(esw, @@ -2151,19 +2220,7 @@ static int esw_offloads_start(struct mlx5_eswitch *esw, "Inline mode is different between vports"); } } - return err; -} - -static void mlx5_esw_offloads_rep_mark_set(struct mlx5_eswitch *esw, - struct mlx5_eswitch_rep *rep, - xa_mark_t mark) -{ - bool mark_set; - - /* Copy the mark from vport to its rep */ - mark_set = xa_get_mark(&esw->vports, rep->vport, mark); - if (mark_set) - xa_set_mark(&esw->offloads.vport_reps, rep->vport, mark); + return 0; } static int mlx5_esw_offloads_rep_init(struct mlx5_eswitch *esw, const struct mlx5_vport *vport) @@ -2185,9 +2242,6 @@ static int mlx5_esw_offloads_rep_init(struct mlx5_eswitch *esw, const struct mlx if (err) goto insert_err; - mlx5_esw_offloads_rep_mark_set(esw, rep, MLX5_ESW_VPT_HOST_FN); - mlx5_esw_offloads_rep_mark_set(esw, rep, MLX5_ESW_VPT_VF); - mlx5_esw_offloads_rep_mark_set(esw, rep, MLX5_ESW_VPT_SF); return 0; insert_err: @@ -2328,37 +2382,13 @@ static void __esw_offloads_unload_rep(struct mlx5_eswitch *esw, esw->offloads.rep_ops[rep_type]->unload(rep); } -static void __unload_reps_sf_vport(struct mlx5_eswitch *esw, u8 rep_type) -{ - struct mlx5_eswitch_rep *rep; - unsigned long i; - - mlx5_esw_for_each_sf_rep(esw, i, rep) - __esw_offloads_unload_rep(esw, rep, rep_type); -} - static void __unload_reps_all_vport(struct mlx5_eswitch *esw, u8 rep_type) { struct mlx5_eswitch_rep *rep; unsigned long i; - __unload_reps_sf_vport(esw, rep_type); - - mlx5_esw_for_each_vf_rep(esw, i, rep) - __esw_offloads_unload_rep(esw, rep, rep_type); - - if (mlx5_ecpf_vport_exists(esw->dev)) { - rep = mlx5_eswitch_get_rep(esw, MLX5_VPORT_ECPF); - __esw_offloads_unload_rep(esw, rep, rep_type); - } - - if (mlx5_core_is_ecpf_esw_manager(esw->dev)) { - rep = mlx5_eswitch_get_rep(esw, MLX5_VPORT_PF); + mlx5_esw_for_each_rep(esw, i, rep) __esw_offloads_unload_rep(esw, rep, rep_type); - } - - rep = mlx5_eswitch_get_rep(esw, MLX5_VPORT_UPLINK); - __esw_offloads_unload_rep(esw, rep, rep_type); } int mlx5_esw_offloads_rep_load(struct mlx5_eswitch *esw, u16 vport_num) @@ -2476,6 +2506,7 @@ static int __esw_set_master_egress_rule(struct mlx5_core_dev *master, struct mlx5_vport *vport, struct mlx5_flow_table *acl) { + u16 slave_index = MLX5_CAP_GEN(slave, vhca_id); struct mlx5_flow_handle *flow_rule = NULL; struct mlx5_flow_destination dest = {}; struct mlx5_flow_act flow_act = {}; @@ -2491,8 +2522,7 @@ static int __esw_set_master_egress_rule(struct mlx5_core_dev *master, misc = MLX5_ADDR_OF(fte_match_param, spec->match_value, misc_parameters); MLX5_SET(fte_match_set_misc, misc, source_port, MLX5_VPORT_UPLINK); - MLX5_SET(fte_match_set_misc, misc, source_eswitch_owner_vhca_id, - MLX5_CAP_GEN(slave, vhca_id)); + MLX5_SET(fte_match_set_misc, misc, source_eswitch_owner_vhca_id, slave_index); misc = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, misc_parameters); MLX5_SET_TO_ONES(fte_match_set_misc, misc, source_port); @@ -2507,49 +2537,43 @@ static int __esw_set_master_egress_rule(struct mlx5_core_dev *master, flow_rule = mlx5_add_flow_rules(acl, spec, &flow_act, &dest, 1); - if (IS_ERR(flow_rule)) + if (IS_ERR(flow_rule)) { err = PTR_ERR(flow_rule); - else - vport->egress.offloads.bounce_rule = flow_rule; + } else { + err = xa_insert(&vport->egress.offloads.bounce_rules, + slave_index, flow_rule, GFP_KERNEL); + if (err) + mlx5_del_flow_rules(flow_rule); + } kvfree(spec); return err; } -static int esw_set_master_egress_rule(struct mlx5_core_dev *master, - struct mlx5_core_dev *slave) +static int esw_master_egress_create_resources(struct mlx5_eswitch *esw, + struct mlx5_flow_namespace *egress_ns, + struct mlx5_vport *vport, size_t count) { int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in); - struct mlx5_eswitch *esw = master->priv.eswitch; struct mlx5_flow_table_attr ft_attr = { - .max_fte = 1, .prio = 0, .level = 0, - .flags = MLX5_FLOW_TABLE_OTHER_VPORT, + .max_fte = count, .prio = 0, .level = 0, }; - struct mlx5_flow_namespace *egress_ns; struct mlx5_flow_table *acl; struct mlx5_flow_group *g; - struct mlx5_vport *vport; void *match_criteria; u32 *flow_group_in; int err; - vport = mlx5_eswitch_get_vport(esw, esw->manager_vport); - if (IS_ERR(vport)) - return PTR_ERR(vport); - - egress_ns = mlx5_get_flow_vport_acl_namespace(master, - MLX5_FLOW_NAMESPACE_ESW_EGRESS, - vport->index); - if (!egress_ns) - return -EINVAL; - if (vport->egress.acl) - return -EINVAL; + return 0; flow_group_in = kvzalloc(inlen, GFP_KERNEL); if (!flow_group_in) return -ENOMEM; + if (vport->vport || mlx5_core_is_ecpf(esw->dev)) + ft_attr.flags = MLX5_FLOW_TABLE_OTHER_VPORT; + acl = mlx5_create_vport_flow_table(egress_ns, &ft_attr, vport->vport); if (IS_ERR(acl)) { err = PTR_ERR(acl); @@ -2568,7 +2592,7 @@ static int esw_set_master_egress_rule(struct mlx5_core_dev *master, MLX5_SET(create_flow_group_in, flow_group_in, source_eswitch_owner_vhca_id_valid, 1); MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, 0); - MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, 0); + MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, count); g = mlx5_create_flow_group(acl, flow_group_in); if (IS_ERR(g)) { @@ -2576,19 +2600,15 @@ static int esw_set_master_egress_rule(struct mlx5_core_dev *master, goto err_group; } - err = __esw_set_master_egress_rule(master, slave, vport, acl); - if (err) - goto err_rule; - vport->egress.acl = acl; vport->egress.offloads.bounce_grp = g; + vport->egress.type = VPORT_EGRESS_ACL_TYPE_SHARED_FDB; + xa_init_flags(&vport->egress.offloads.bounce_rules, XA_FLAGS_ALLOC); kvfree(flow_group_in); return 0; -err_rule: - mlx5_destroy_flow_group(g); err_group: mlx5_destroy_flow_table(acl); out: @@ -2596,18 +2616,74 @@ static int esw_set_master_egress_rule(struct mlx5_core_dev *master, return err; } -static void esw_unset_master_egress_rule(struct mlx5_core_dev *dev) +static void esw_master_egress_destroy_resources(struct mlx5_vport *vport) +{ + if (!xa_empty(&vport->egress.offloads.bounce_rules)) + return; + mlx5_destroy_flow_group(vport->egress.offloads.bounce_grp); + vport->egress.offloads.bounce_grp = NULL; + mlx5_destroy_flow_table(vport->egress.acl); + vport->egress.acl = NULL; +} + +static int esw_set_master_egress_rule(struct mlx5_core_dev *master, + struct mlx5_core_dev *slave, size_t count) +{ + struct mlx5_eswitch *esw = master->priv.eswitch; + u16 slave_index = MLX5_CAP_GEN(slave, vhca_id); + struct mlx5_flow_namespace *egress_ns; + struct mlx5_vport *vport; + int err; + + vport = mlx5_eswitch_get_vport(esw, esw->manager_vport); + if (IS_ERR(vport)) + return PTR_ERR(vport); + + egress_ns = mlx5_get_flow_vport_acl_namespace(master, + MLX5_FLOW_NAMESPACE_ESW_EGRESS, + vport->index); + if (!egress_ns) + return -EINVAL; + + if (vport->egress.acl && vport->egress.type != VPORT_EGRESS_ACL_TYPE_SHARED_FDB) + return 0; + + err = esw_master_egress_create_resources(esw, egress_ns, vport, count); + if (err) + return err; + + if (xa_load(&vport->egress.offloads.bounce_rules, slave_index)) + return -EINVAL; + + err = __esw_set_master_egress_rule(master, slave, vport, vport->egress.acl); + if (err) + goto err_rule; + + return 0; + +err_rule: + esw_master_egress_destroy_resources(vport); + return err; +} + +static void esw_unset_master_egress_rule(struct mlx5_core_dev *dev, + struct mlx5_core_dev *slave_dev) { struct mlx5_vport *vport; vport = mlx5_eswitch_get_vport(dev->priv.eswitch, dev->priv.eswitch->manager_vport); - esw_acl_egress_ofld_cleanup(vport); + esw_acl_egress_ofld_bounce_rule_destroy(vport, MLX5_CAP_GEN(slave_dev, vhca_id)); + + if (xa_empty(&vport->egress.offloads.bounce_rules)) { + esw_acl_egress_ofld_cleanup(vport); + xa_destroy(&vport->egress.offloads.bounce_rules); + } } -int mlx5_eswitch_offloads_config_single_fdb(struct mlx5_eswitch *master_esw, - struct mlx5_eswitch *slave_esw) +int mlx5_eswitch_offloads_single_fdb_add_one(struct mlx5_eswitch *master_esw, + struct mlx5_eswitch *slave_esw, int max_slaves) { int err; @@ -2617,7 +2693,7 @@ int mlx5_eswitch_offloads_config_single_fdb(struct mlx5_eswitch *master_esw, return err; err = esw_set_master_egress_rule(master_esw->dev, - slave_esw->dev); + slave_esw->dev, max_slaves); if (err) goto err_acl; @@ -2625,21 +2701,21 @@ int mlx5_eswitch_offloads_config_single_fdb(struct mlx5_eswitch *master_esw, err_acl: esw_set_slave_root_fdb(NULL, slave_esw->dev); - return err; } -void mlx5_eswitch_offloads_destroy_single_fdb(struct mlx5_eswitch *master_esw, +void mlx5_eswitch_offloads_single_fdb_del_one(struct mlx5_eswitch *master_esw, struct mlx5_eswitch *slave_esw) { - esw_unset_master_egress_rule(master_esw->dev); esw_set_slave_root_fdb(NULL, slave_esw->dev); + esw_unset_master_egress_rule(master_esw->dev, slave_esw->dev); } #define ESW_OFFLOADS_DEVCOM_PAIR (0) #define ESW_OFFLOADS_DEVCOM_UNPAIR (1) -static void mlx5_esw_offloads_rep_event_unpair(struct mlx5_eswitch *esw) +static void mlx5_esw_offloads_rep_event_unpair(struct mlx5_eswitch *esw, + struct mlx5_eswitch *peer_esw) { const struct mlx5_eswitch_rep_ops *ops; struct mlx5_eswitch_rep *rep; @@ -2652,18 +2728,19 @@ static void mlx5_esw_offloads_rep_event_unpair(struct mlx5_eswitch *esw) ops = esw->offloads.rep_ops[rep_type]; if (atomic_read(&rep->rep_data[rep_type].state) == REP_LOADED && ops->event) - ops->event(esw, rep, MLX5_SWITCHDEV_EVENT_UNPAIR, NULL); + ops->event(esw, rep, MLX5_SWITCHDEV_EVENT_UNPAIR, peer_esw); } } } -static void mlx5_esw_offloads_unpair(struct mlx5_eswitch *esw) +static void mlx5_esw_offloads_unpair(struct mlx5_eswitch *esw, + struct mlx5_eswitch *peer_esw) { #if IS_ENABLED(CONFIG_MLX5_CLS_ACT) mlx5e_tc_clean_fdb_peer_flows(esw); #endif - mlx5_esw_offloads_rep_event_unpair(esw); - esw_del_fdb_peer_miss_rules(esw); + mlx5_esw_offloads_rep_event_unpair(esw, peer_esw); + esw_del_fdb_peer_miss_rules(esw, peer_esw->dev); } static int mlx5_esw_offloads_pair(struct mlx5_eswitch *esw, @@ -2694,7 +2771,7 @@ static int mlx5_esw_offloads_pair(struct mlx5_eswitch *esw, return 0; err_out: - mlx5_esw_offloads_unpair(esw); + mlx5_esw_offloads_unpair(esw, peer_esw); return err; } @@ -2702,7 +2779,9 @@ static int mlx5_esw_offloads_set_ns_peer(struct mlx5_eswitch *esw, struct mlx5_eswitch *peer_esw, bool pair) { + u8 peer_idx = mlx5_get_dev_index(peer_esw->dev); struct mlx5_flow_root_namespace *peer_ns; + u8 idx = mlx5_get_dev_index(esw->dev); struct mlx5_flow_root_namespace *ns; int err; @@ -2710,18 +2789,18 @@ static int mlx5_esw_offloads_set_ns_peer(struct mlx5_eswitch *esw, ns = esw->dev->priv.steering->fdb_root_ns; if (pair) { - err = mlx5_flow_namespace_set_peer(ns, peer_ns); + err = mlx5_flow_namespace_set_peer(ns, peer_ns, peer_idx); if (err) return err; - err = mlx5_flow_namespace_set_peer(peer_ns, ns); + err = mlx5_flow_namespace_set_peer(peer_ns, ns, idx); if (err) { - mlx5_flow_namespace_set_peer(ns, NULL); + mlx5_flow_namespace_set_peer(ns, NULL, peer_idx); return err; } } else { - mlx5_flow_namespace_set_peer(ns, NULL); - mlx5_flow_namespace_set_peer(peer_ns, NULL); + mlx5_flow_namespace_set_peer(ns, NULL, peer_idx); + mlx5_flow_namespace_set_peer(peer_ns, NULL, idx); } return 0; @@ -2734,15 +2813,21 @@ static int mlx5_esw_offloads_devcom_event(int event, struct mlx5_eswitch *esw = my_data; struct mlx5_devcom *devcom = esw->dev->priv.devcom; struct mlx5_eswitch *peer_esw = event_data; + u16 esw_i, peer_esw_i; + bool esw_paired; int err; + peer_esw_i = MLX5_CAP_GEN(peer_esw->dev, vhca_id); + esw_i = MLX5_CAP_GEN(esw->dev, vhca_id); + esw_paired = !!xa_load(&esw->paired, peer_esw_i); + switch (event) { case ESW_OFFLOADS_DEVCOM_PAIR: if (mlx5_eswitch_vport_match_metadata_enabled(esw) != mlx5_eswitch_vport_match_metadata_enabled(peer_esw)) break; - if (esw->paired[mlx5_get_dev_index(peer_esw->dev)]) + if (esw_paired) break; err = mlx5_esw_offloads_set_ns_peer(esw, peer_esw, true); @@ -2756,28 +2841,43 @@ static int mlx5_esw_offloads_devcom_event(int event, if (err) goto err_pair; - esw->paired[mlx5_get_dev_index(peer_esw->dev)] = true; - peer_esw->paired[mlx5_get_dev_index(esw->dev)] = true; - mlx5_devcom_set_paired(devcom, MLX5_DEVCOM_ESW_OFFLOADS, true); + err = xa_insert(&esw->paired, peer_esw_i, peer_esw, GFP_KERNEL); + if (err) + goto err_xa; + + err = xa_insert(&peer_esw->paired, esw_i, esw, GFP_KERNEL); + if (err) + goto err_peer_xa; + + esw->num_peers++; + peer_esw->num_peers++; + mlx5_devcom_comp_set_ready(devcom, MLX5_DEVCOM_ESW_OFFLOADS, true); break; case ESW_OFFLOADS_DEVCOM_UNPAIR: - if (!esw->paired[mlx5_get_dev_index(peer_esw->dev)]) + if (!esw_paired) break; - mlx5_devcom_set_paired(devcom, MLX5_DEVCOM_ESW_OFFLOADS, false); - esw->paired[mlx5_get_dev_index(peer_esw->dev)] = false; - peer_esw->paired[mlx5_get_dev_index(esw->dev)] = false; - mlx5_esw_offloads_unpair(peer_esw); - mlx5_esw_offloads_unpair(esw); + peer_esw->num_peers--; + esw->num_peers--; + if (!esw->num_peers && !peer_esw->num_peers) + mlx5_devcom_comp_set_ready(devcom, MLX5_DEVCOM_ESW_OFFLOADS, false); + xa_erase(&peer_esw->paired, esw_i); + xa_erase(&esw->paired, peer_esw_i); + mlx5_esw_offloads_unpair(peer_esw, esw); + mlx5_esw_offloads_unpair(esw, peer_esw); mlx5_esw_offloads_set_ns_peer(esw, peer_esw, false); break; } return 0; +err_peer_xa: + xa_erase(&esw->paired, peer_esw_i); +err_xa: + mlx5_esw_offloads_unpair(peer_esw, esw); err_pair: - mlx5_esw_offloads_unpair(esw); + mlx5_esw_offloads_unpair(esw, peer_esw); err_peer: mlx5_esw_offloads_set_ns_peer(esw, peer_esw, false); err_out: @@ -2789,24 +2889,29 @@ static int mlx5_esw_offloads_devcom_event(int event, void mlx5_esw_offloads_devcom_init(struct mlx5_eswitch *esw) { struct mlx5_devcom *devcom = esw->dev->priv.devcom; + int i; - INIT_LIST_HEAD(&esw->offloads.peer_flows); + for (i = 0; i < MLX5_MAX_PORTS; i++) + INIT_LIST_HEAD(&esw->offloads.peer_flows[i]); mutex_init(&esw->offloads.peer_mutex); if (!MLX5_CAP_ESW(esw->dev, merged_eswitch)) return; - if (!mlx5_is_lag_supported(esw->dev)) + if (!mlx5_lag_is_supported(esw->dev)) return; + xa_init(&esw->paired); mlx5_devcom_register_component(devcom, MLX5_DEVCOM_ESW_OFFLOADS, mlx5_esw_offloads_devcom_event, esw); + esw->num_peers = 0; mlx5_devcom_send_event(devcom, MLX5_DEVCOM_ESW_OFFLOADS, - ESW_OFFLOADS_DEVCOM_PAIR, esw); + ESW_OFFLOADS_DEVCOM_PAIR, + ESW_OFFLOADS_DEVCOM_UNPAIR, esw); } void mlx5_esw_offloads_devcom_cleanup(struct mlx5_eswitch *esw) @@ -2816,13 +2921,15 @@ void mlx5_esw_offloads_devcom_cleanup(struct mlx5_eswitch *esw) if (!MLX5_CAP_ESW(esw->dev, merged_eswitch)) return; - if (!mlx5_is_lag_supported(esw->dev)) + if (!mlx5_lag_is_supported(esw->dev)) return; mlx5_devcom_send_event(devcom, MLX5_DEVCOM_ESW_OFFLOADS, + ESW_OFFLOADS_DEVCOM_UNPAIR, ESW_OFFLOADS_DEVCOM_UNPAIR, esw); mlx5_devcom_unregister_component(devcom, MLX5_DEVCOM_ESW_OFFLOADS); + xa_destroy(&esw->paired); } bool mlx5_esw_vport_match_metadata_supported(const struct mlx5_eswitch *esw) @@ -2834,9 +2941,6 @@ bool mlx5_esw_vport_match_metadata_supported(const struct mlx5_eswitch *esw) MLX5_FDB_TO_VPORT_REG_C_0)) return false; - if (!MLX5_CAP_ESW_FLOWTABLE(esw->dev, flow_source)) - return false; - return true; } @@ -3247,6 +3351,9 @@ int esw_offloads_enable(struct mlx5_eswitch *esw) /* Representor will control the vport link state */ mlx5_esw_for_each_vf_vport(esw, i, vport, esw->esw_funcs.num_vfs) vport->info.link_state = MLX5_VPORT_ADMIN_STATE_DOWN; + if (mlx5_core_ec_sriov_enabled(esw->dev)) + mlx5_esw_for_each_ec_vf_vport(esw, i, vport, esw->esw_funcs.num_ec_vfs) + vport->info.link_state = MLX5_VPORT_ADMIN_STATE_DOWN; /* Uplink vport rep must load first. */ err = esw_offloads_load_rep(esw, MLX5_VPORT_UPLINK); @@ -3285,7 +3392,7 @@ static int esw_offloads_stop(struct mlx5_eswitch *esw, /* If changing from switchdev to legacy mode without sriov enabled, * no need to create legacy fdb. */ - if (!mlx5_sriov_is_enabled(esw->dev)) + if (!mlx5_core_is_pf(esw->dev) || !mlx5_sriov_is_enabled(esw->dev)) return 0; err = mlx5_eswitch_enable_locked(esw, MLX5_ESWITCH_IGNORE_NUM_VFS); @@ -3484,8 +3591,27 @@ static int mlx5_esw_vports_inline_set(struct mlx5_eswitch *esw, u8 mlx5_mode, goto revert_inline_mode; } } + if (mlx5_core_ec_sriov_enabled(esw->dev)) { + mlx5_esw_for_each_ec_vf_vport(esw, i, vport, esw->esw_funcs.num_ec_vfs) { + err = mlx5_modify_nic_vport_min_inline(dev, vport->vport, mlx5_mode); + if (err) { + err_vport_num = vport->vport; + NL_SET_ERR_MSG_MOD(extack, + "Failed to set min inline on vport"); + goto revert_ec_vf_inline_mode; + } + } + } return 0; +revert_ec_vf_inline_mode: + mlx5_esw_for_each_ec_vf_vport(esw, i, vport, esw->esw_funcs.num_ec_vfs) { + if (vport->vport == err_vport_num) + break; + mlx5_modify_nic_vport_min_inline(dev, + vport->vport, + esw->offloads.inline_mode); + } revert_inline_mode: mlx5_esw_for_each_host_func_vport(esw, i, vport, esw->esw_funcs.num_vfs) { if (vport->vport == err_vport_num) @@ -3835,9 +3961,6 @@ static int mlx5_esw_query_vport_vhca_id(struct mlx5_eswitch *esw, u16 vport_num, int err; *vhca_id = 0; - if (mlx5_esw_is_manager_vport(esw, vport_num) || - !MLX5_CAP_GEN(esw->dev, vhca_resource_manager)) - return -EPERM; query_ctx = kzalloc(query_out_sz, GFP_KERNEL); if (!query_ctx) @@ -3926,9 +4049,9 @@ is_port_function_supported(struct mlx5_eswitch *esw, u16 vport_num) mlx5_esw_is_sf_vport(esw, vport_num); } -int mlx5_devlink_port_function_hw_addr_get(struct devlink_port *port, - u8 *hw_addr, int *hw_addr_len, - struct netlink_ext_ack *extack) +int mlx5_devlink_port_fn_hw_addr_get(struct devlink_port *port, + u8 *hw_addr, int *hw_addr_len, + struct netlink_ext_ack *extack) { struct mlx5_eswitch *esw; struct mlx5_vport *vport; @@ -3955,9 +4078,9 @@ int mlx5_devlink_port_function_hw_addr_get(struct devlink_port *port, return 0; } -int mlx5_devlink_port_function_hw_addr_set(struct devlink_port *port, - const u8 *hw_addr, int hw_addr_len, - struct netlink_ext_ack *extack) +int mlx5_devlink_port_fn_hw_addr_set(struct devlink_port *port, + const u8 *hw_addr, int hw_addr_len, + struct netlink_ext_ack *extack) { struct mlx5_eswitch *esw; u16 vport_num; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/events.c b/drivers/net/ethernet/mellanox/mlx5/core/events.c index 718cf09c28ce4baffb464cc3db5eaf08d3a9b1ac..3ec892d51f57d2b8834ddfd4116ea4031dfac4c8 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/events.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/events.c @@ -5,7 +5,7 @@ #include "mlx5_core.h" #include "lib/eq.h" -#include "lib/mlx5.h" +#include "lib/events.h" struct mlx5_event_nb { struct mlx5_nb nb; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c index 144e59480686447de7c74d60f28b5efa9066dce6..91dcb0dcad101ef640b8113e51409988d9d11a00 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c @@ -139,7 +139,8 @@ static void mlx5_cmd_stub_modify_header_dealloc(struct mlx5_flow_root_namespace } static int mlx5_cmd_stub_set_peer(struct mlx5_flow_root_namespace *ns, - struct mlx5_flow_root_namespace *peer_ns) + struct mlx5_flow_root_namespace *peer_ns, + u8 peer_idx) { return 0; } @@ -243,16 +244,22 @@ static int mlx5_cmd_update_root_ft(struct mlx5_flow_root_namespace *ns, ft->type == FS_FT_FDB && mlx5_lag_is_shared_fdb(dev) && mlx5_lag_is_master(dev)) { - err = mlx5_cmd_set_slave_root_fdb(dev, - mlx5_lag_get_peer_mdev(dev), - !disconnect, (!disconnect) ? - ft->id : 0); - if (err && !disconnect) { - MLX5_SET(set_flow_table_root_in, in, op_mod, 0); - MLX5_SET(set_flow_table_root_in, in, table_id, - ns->root_ft->id); - mlx5_cmd_exec_in(dev, set_flow_table_root, in); + struct mlx5_core_dev *peer_dev; + int i; + + mlx5_lag_for_each_peer_mdev(dev, peer_dev, i) { + err = mlx5_cmd_set_slave_root_fdb(dev, peer_dev, !disconnect, + (!disconnect) ? ft->id : 0); + if (err && !disconnect) { + MLX5_SET(set_flow_table_root_in, in, op_mod, 0); + MLX5_SET(set_flow_table_root_in, in, table_id, + ns->root_ft->id); + mlx5_cmd_exec_in(dev, set_flow_table_root, in); + } + if (err) + break; } + } return err; @@ -511,10 +518,11 @@ static int mlx5_cmd_set_fte(struct mlx5_core_dev *dev, struct mlx5_flow_rule *dst; void *in_flow_context, *vlan; void *in_match_value; + int reformat_id = 0; unsigned int inlen; int dst_cnt_size; + u32 *in, action; void *in_dests; - u32 *in; int err; if (mlx5_set_extended_dest(dev, fte, &extended_dest)) @@ -553,22 +561,42 @@ static int mlx5_cmd_set_fte(struct mlx5_core_dev *dev, MLX5_SET(flow_context, in_flow_context, extended_destination, extended_dest); - if (extended_dest) { - u32 action; - action = fte->action.action & - ~MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT; - MLX5_SET(flow_context, in_flow_context, action, action); - } else { - MLX5_SET(flow_context, in_flow_context, action, - fte->action.action); - if (fte->action.pkt_reformat) - MLX5_SET(flow_context, in_flow_context, packet_reformat_id, - fte->action.pkt_reformat->id); + action = fte->action.action; + if (extended_dest) + action &= ~MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT; + + MLX5_SET(flow_context, in_flow_context, action, action); + + if (!extended_dest && fte->action.pkt_reformat) { + struct mlx5_pkt_reformat *pkt_reformat = fte->action.pkt_reformat; + + if (pkt_reformat->owner == MLX5_FLOW_RESOURCE_OWNER_SW) { + reformat_id = mlx5_fs_dr_action_get_pkt_reformat_id(pkt_reformat); + if (reformat_id < 0) { + mlx5_core_err(dev, + "Unsupported SW-owned pkt_reformat type (%d) in FW-owned table\n", + pkt_reformat->reformat_type); + err = reformat_id; + goto err_out; + } + } else { + reformat_id = fte->action.pkt_reformat->id; + } } - if (fte->action.modify_hdr) + + MLX5_SET(flow_context, in_flow_context, packet_reformat_id, (u32)reformat_id); + + if (fte->action.modify_hdr) { + if (fte->action.modify_hdr->owner == MLX5_FLOW_RESOURCE_OWNER_SW) { + mlx5_core_err(dev, "Can't use SW-owned modify_hdr in FW-owned table\n"); + err = -EOPNOTSUPP; + goto err_out; + } + MLX5_SET(flow_context, in_flow_context, modify_header_id, fte->action.modify_hdr->id); + } MLX5_SET(flow_context, in_flow_context, encrypt_decrypt_type, fte->action.crypto.type); @@ -885,6 +913,8 @@ static int mlx5_cmd_packet_reformat_alloc(struct mlx5_flow_root_namespace *ns, pkt_reformat->id = MLX5_GET(alloc_packet_reformat_context_out, out, packet_reformat_id); + pkt_reformat->owner = MLX5_FLOW_RESOURCE_OWNER_FW; + kfree(in); return err; } @@ -969,6 +999,7 @@ static int mlx5_cmd_modify_header_alloc(struct mlx5_flow_root_namespace *ns, err = mlx5_cmd_exec(dev, in, inlen, out, sizeof(out)); modify_hdr->id = MLX5_GET(alloc_modify_header_context_out, out, modify_header_id); + modify_hdr->owner = MLX5_FLOW_RESOURCE_OWNER_FW; kfree(in); return err; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.h b/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.h index 8ef4254b9ea126e13a9052d6d36c561a33962898..b6b9a5a20591dfe59e8213fd3f92987d1c8d4ebd 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.h @@ -93,7 +93,8 @@ struct mlx5_flow_cmds { struct mlx5_modify_hdr *modify_hdr); int (*set_peer)(struct mlx5_flow_root_namespace *ns, - struct mlx5_flow_root_namespace *peer_ns); + struct mlx5_flow_root_namespace *peer_ns, + u8 peer_idx); int (*create_ns)(struct mlx5_flow_root_namespace *ns); int (*destroy_ns)(struct mlx5_flow_root_namespace *ns); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c index 19da02c41616182ca26f8ca1d28eb3fd3e93d1ee..4ef04aa287719ee469ca8f0e47453b7929719fd1 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c @@ -3620,7 +3620,8 @@ void mlx5_destroy_match_definer(struct mlx5_core_dev *dev, } int mlx5_flow_namespace_set_peer(struct mlx5_flow_root_namespace *ns, - struct mlx5_flow_root_namespace *peer_ns) + struct mlx5_flow_root_namespace *peer_ns, + u8 peer_idx) { if (peer_ns && ns->mode != peer_ns->mode) { mlx5_core_err(ns->dev, @@ -3628,7 +3629,7 @@ int mlx5_flow_namespace_set_peer(struct mlx5_flow_root_namespace *ns, return -EINVAL; } - return ns->cmds->set_peer(ns, peer_ns); + return ns->cmds->set_peer(ns, peer_ns, peer_idx); } /* This function should be called only at init stage of the namespace. diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h index f137a0611b77b41a7c733b60b1321af60b70c0f3..03e64c4c245da3e170eb636fa7049fe792525e76 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h @@ -54,8 +54,14 @@ struct mlx5_flow_definer { u32 id; }; +enum mlx5_flow_resource_owner { + MLX5_FLOW_RESOURCE_OWNER_FW, + MLX5_FLOW_RESOURCE_OWNER_SW, +}; + struct mlx5_modify_hdr { enum mlx5_flow_namespace_type ns_type; + enum mlx5_flow_resource_owner owner; union { struct mlx5_fs_dr_action action; u32 id; @@ -65,6 +71,7 @@ struct mlx5_modify_hdr { struct mlx5_pkt_reformat { enum mlx5_flow_namespace_type ns_type; int reformat_type; /* from mlx5_ifc */ + enum mlx5_flow_resource_owner owner; union { struct mlx5_fs_dr_action action; u32 id; @@ -295,7 +302,8 @@ void mlx5_fc_update_sampling_interval(struct mlx5_core_dev *dev, const struct mlx5_flow_cmds *mlx5_fs_cmd_get_fw_cmds(void); int mlx5_flow_namespace_set_peer(struct mlx5_flow_root_namespace *ns, - struct mlx5_flow_root_namespace *peer_ns); + struct mlx5_flow_root_namespace *peer_ns, + u8 peer_idx); int mlx5_flow_namespace_set_mode(struct mlx5_flow_namespace *ns, enum mlx5_flow_steering_mode mode); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fw.c b/drivers/net/ethernet/mellanox/mlx5/core/fw.c index 7bb7be01225a8a9a183639546610d319f01e2675..fb2035a5ec999247068b2e91c41b685df78ab9c2 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fw.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/fw.c @@ -196,14 +196,11 @@ int mlx5_query_hca_caps(struct mlx5_core_dev *dev) return err; } - if (MLX5_CAP_GEN(dev, vport_group_manager) && - MLX5_ESWITCH_MANAGER(dev)) { + if (MLX5_ESWITCH_MANAGER(dev)) { err = mlx5_core_get_caps(dev, MLX5_CAP_ESWITCH_FLOW_TABLE); if (err) return err; - } - if (MLX5_ESWITCH_MANAGER(dev)) { err = mlx5_core_get_caps(dev, MLX5_CAP_ESWITCH); if (err) return err; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c b/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c index 50022e7565f14303937672f33332677e359dde14..4804990b7f22617ab0f0af9514ff8b48b2517368 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c @@ -21,6 +21,7 @@ struct mlx5_fw_reset { struct workqueue_struct *wq; struct work_struct fw_live_patch_work; struct work_struct reset_request_work; + struct work_struct reset_unload_work; struct work_struct reset_reload_work; struct work_struct reset_now_work; struct work_struct reset_abort_work; @@ -30,6 +31,26 @@ struct mlx5_fw_reset { int ret; }; +enum { + MLX5_FW_RST_STATE_IDLE = 0, + MLX5_FW_RST_STATE_TOGGLE_REQ = 4, +}; + +enum { + MLX5_RST_STATE_BIT_NUM = 12, + MLX5_RST_ACK_BIT_NUM = 22, +}; + +static u8 mlx5_get_fw_rst_state(struct mlx5_core_dev *dev) +{ + return (ioread32be(&dev->iseg->initializing) >> MLX5_RST_STATE_BIT_NUM) & 0xF; +} + +static void mlx5_set_fw_rst_ack(struct mlx5_core_dev *dev) +{ + iowrite32be(BIT(MLX5_RST_ACK_BIT_NUM), &dev->iseg->initializing); +} + static int mlx5_fw_reset_enable_remote_dev_reset_set(struct devlink *devlink, u32 id, struct devlink_param_gset_ctx *ctx) { @@ -155,7 +176,7 @@ int mlx5_fw_reset_set_live_patch(struct mlx5_core_dev *dev) return mlx5_reg_mfrl_set(dev, MLX5_MFRL_REG_RESET_LEVEL0, 0, 0, false); } -static void mlx5_fw_reset_complete_reload(struct mlx5_core_dev *dev) +static void mlx5_fw_reset_complete_reload(struct mlx5_core_dev *dev, bool unloaded) { struct mlx5_fw_reset *fw_reset = dev->priv.fw_reset; @@ -163,7 +184,8 @@ static void mlx5_fw_reset_complete_reload(struct mlx5_core_dev *dev) if (test_bit(MLX5_FW_RESET_FLAGS_PENDING_COMP, &fw_reset->reset_flags)) { complete(&fw_reset->done); } else { - mlx5_unload_one(dev, false); + if (!unloaded) + mlx5_unload_one(dev, false); if (mlx5_health_wait_pci_up(dev)) mlx5_core_err(dev, "reset reload flow aborted, PCI reads still not working\n"); else @@ -204,7 +226,7 @@ static void mlx5_sync_reset_reload_work(struct work_struct *work) mlx5_sync_reset_clear_reset_requested(dev, false); mlx5_enter_error_state(dev, true); - mlx5_fw_reset_complete_reload(dev); + mlx5_fw_reset_complete_reload(dev, false); } #define MLX5_RESET_POLL_INTERVAL (HZ / 10) @@ -276,6 +298,44 @@ static void mlx5_fw_live_patch_event(struct work_struct *work) mlx5_core_err(dev, "Failed to reload FW tracer\n"); } +static int mlx5_check_dev_ids(struct mlx5_core_dev *dev, u16 dev_id) +{ + struct pci_bus *bridge_bus = dev->pdev->bus; + struct pci_dev *sdev; + u16 sdev_id; + int err; + + /* Check that all functions under the pci bridge are PFs of + * this device otherwise fail this function. + */ + list_for_each_entry(sdev, &bridge_bus->devices, bus_list) { + err = pci_read_config_word(sdev, PCI_DEVICE_ID, &sdev_id); + if (err) + return err; + if (sdev_id != dev_id) { + mlx5_core_warn(dev, "unrecognized dev_id (0x%x)\n", sdev_id); + return -EPERM; + } + } + return 0; +} + +static bool mlx5_is_reset_now_capable(struct mlx5_core_dev *dev) +{ + u16 dev_id; + int err; + + if (!MLX5_CAP_GEN(dev, fast_teardown)) { + mlx5_core_warn(dev, "fast teardown is not supported by firmware\n"); + return false; + } + + err = pci_read_config_word(dev->pdev, PCI_DEVICE_ID, &dev_id); + if (err) + return false; + return (!mlx5_check_dev_ids(dev, dev_id)); +} + static void mlx5_sync_reset_request_event(struct work_struct *work) { struct mlx5_fw_reset *fw_reset = container_of(work, struct mlx5_fw_reset, @@ -283,7 +343,8 @@ static void mlx5_sync_reset_request_event(struct work_struct *work) struct mlx5_core_dev *dev = fw_reset->dev; int err; - if (test_bit(MLX5_FW_RESET_FLAGS_NACK_RESET_REQUEST, &fw_reset->reset_flags)) { + if (test_bit(MLX5_FW_RESET_FLAGS_NACK_RESET_REQUEST, &fw_reset->reset_flags) || + !mlx5_is_reset_now_capable(dev)) { err = mlx5_fw_reset_set_reset_sync_nack(dev); mlx5_core_warn(dev, "PCI Sync FW Update Reset Nack %s", err ? "Failed" : "Sent"); @@ -303,26 +364,17 @@ static int mlx5_pci_link_toggle(struct mlx5_core_dev *dev) { struct pci_bus *bridge_bus = dev->pdev->bus; struct pci_dev *bridge = bridge_bus->self; - u16 reg16, dev_id, sdev_id; unsigned long timeout; struct pci_dev *sdev; + u16 reg16, dev_id; int cap, err; - u32 reg32; - /* Check that all functions under the pci bridge are PFs of - * this device otherwise fail this function. - */ err = pci_read_config_word(dev->pdev, PCI_DEVICE_ID, &dev_id); if (err) return err; - list_for_each_entry(sdev, &bridge_bus->devices, bus_list) { - err = pci_read_config_word(sdev, PCI_DEVICE_ID, &sdev_id); - if (err) - return err; - if (sdev_id != dev_id) - return -EPERM; - } - + err = mlx5_check_dev_ids(dev, dev_id); + if (err) + return err; cap = pci_find_capability(bridge, PCI_CAP_ID_EXP); if (!cap) return -EOPNOTSUPP; @@ -346,11 +398,8 @@ static int mlx5_pci_link_toggle(struct mlx5_core_dev *dev) return err; /* Check link */ - err = pci_read_config_dword(bridge, cap + PCI_EXP_LNKCAP, ®32); - if (err) - return err; - if (!(reg32 & PCI_EXP_LNKCAP_DLLLARC)) { - mlx5_core_warn(dev, "No PCI link reporting capability (0x%08x)\n", reg32); + if (!bridge->link_active_reporting) { + mlx5_core_warn(dev, "No PCI link reporting capability\n"); msleep(1000); goto restore; } @@ -427,7 +476,70 @@ static void mlx5_sync_reset_now_event(struct work_struct *work) mlx5_enter_error_state(dev, true); done: fw_reset->ret = err; - mlx5_fw_reset_complete_reload(dev); + mlx5_fw_reset_complete_reload(dev, false); +} + +static void mlx5_sync_reset_unload_event(struct work_struct *work) +{ + struct mlx5_fw_reset *fw_reset; + struct mlx5_core_dev *dev; + unsigned long timeout; + bool reset_action; + u8 rst_state; + int err; + + fw_reset = container_of(work, struct mlx5_fw_reset, reset_unload_work); + dev = fw_reset->dev; + + if (mlx5_sync_reset_clear_reset_requested(dev, false)) + return; + + mlx5_core_warn(dev, "Sync Reset Unload. Function is forced down.\n"); + + err = mlx5_cmd_fast_teardown_hca(dev); + if (err) + mlx5_core_warn(dev, "Fast teardown failed, unloading, err %d\n", err); + else + mlx5_enter_error_state(dev, true); + + if (test_bit(MLX5_FW_RESET_FLAGS_PENDING_COMP, &fw_reset->reset_flags)) + mlx5_unload_one_devl_locked(dev, false); + else + mlx5_unload_one(dev, false); + + mlx5_set_fw_rst_ack(dev); + mlx5_core_warn(dev, "Sync Reset Unload done, device reset expected\n"); + + reset_action = false; + timeout = jiffies + msecs_to_jiffies(mlx5_tout_ms(dev, RESET_UNLOAD)); + do { + rst_state = mlx5_get_fw_rst_state(dev); + if (rst_state == MLX5_FW_RST_STATE_TOGGLE_REQ || + rst_state == MLX5_FW_RST_STATE_IDLE) { + reset_action = true; + break; + } + msleep(20); + } while (!time_after(jiffies, timeout)); + + if (!reset_action) { + mlx5_core_err(dev, "Got timeout waiting for sync reset action, state = %u\n", + rst_state); + fw_reset->ret = -ETIMEDOUT; + goto done; + } + + mlx5_core_warn(dev, "Sync Reset, got reset action. rst_state = %u\n", rst_state); + if (rst_state == MLX5_FW_RST_STATE_TOGGLE_REQ) { + err = mlx5_pci_link_toggle(dev); + if (err) { + mlx5_core_warn(dev, "mlx5_pci_link_toggle failed, err %d\n", err); + fw_reset->ret = err; + } + } + +done: + mlx5_fw_reset_complete_reload(dev, true); } static void mlx5_sync_reset_abort_event(struct work_struct *work) @@ -452,6 +564,9 @@ static void mlx5_sync_reset_events_handle(struct mlx5_fw_reset *fw_reset, struct case MLX5_SYNC_RST_STATE_RESET_REQUEST: queue_work(fw_reset->wq, &fw_reset->reset_request_work); break; + case MLX5_SYNC_RST_STATE_RESET_UNLOAD: + queue_work(fw_reset->wq, &fw_reset->reset_unload_work); + break; case MLX5_SYNC_RST_STATE_RESET_NOW: queue_work(fw_reset->wq, &fw_reset->reset_now_work); break; @@ -486,10 +601,13 @@ static int fw_reset_event_notifier(struct notifier_block *nb, unsigned long acti int mlx5_fw_reset_wait_reset_done(struct mlx5_core_dev *dev) { unsigned long pci_sync_update_timeout = mlx5_tout_ms(dev, PCI_SYNC_UPDATE); - unsigned long timeout = msecs_to_jiffies(pci_sync_update_timeout); struct mlx5_fw_reset *fw_reset = dev->priv.fw_reset; + unsigned long timeout; int err; + if (MLX5_CAP_GEN(dev, pci_sync_for_fw_update_with_driver_unload)) + pci_sync_update_timeout += mlx5_tout_ms(dev, RESET_UNLOAD); + timeout = msecs_to_jiffies(pci_sync_update_timeout); if (!wait_for_completion_timeout(&fw_reset->done, timeout)) { mlx5_core_warn(dev, "FW sync reset timeout after %lu seconds\n", pci_sync_update_timeout / 1000); @@ -526,6 +644,7 @@ void mlx5_drain_fw_reset(struct mlx5_core_dev *dev) set_bit(MLX5_FW_RESET_FLAGS_DROP_NEW_REQUESTS, &fw_reset->reset_flags); cancel_work_sync(&fw_reset->fw_live_patch_work); cancel_work_sync(&fw_reset->reset_request_work); + cancel_work_sync(&fw_reset->reset_unload_work); cancel_work_sync(&fw_reset->reset_reload_work); cancel_work_sync(&fw_reset->reset_now_work); cancel_work_sync(&fw_reset->reset_abort_work); @@ -564,6 +683,7 @@ int mlx5_fw_reset_init(struct mlx5_core_dev *dev) INIT_WORK(&fw_reset->fw_live_patch_work, mlx5_fw_live_patch_event); INIT_WORK(&fw_reset->reset_request_work, mlx5_sync_reset_request_event); + INIT_WORK(&fw_reset->reset_unload_work, mlx5_sync_reset_unload_event); INIT_WORK(&fw_reset->reset_reload_work, mlx5_sync_reset_reload_work); INIT_WORK(&fw_reset->reset_now_work, mlx5_sync_reset_now_event); INIT_WORK(&fw_reset->reset_abort_work, mlx5_sync_reset_abort_event); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/health.c b/drivers/net/ethernet/mellanox/mlx5/core/health.c index 871c32dda66ec54705a4b21963d45620e098c085..187cb2c464f864abf68f98ee5c6354f113d226d4 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/health.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/health.c @@ -39,6 +39,7 @@ #include "mlx5_core.h" #include "lib/eq.h" #include "lib/mlx5.h" +#include "lib/events.h" #include "lib/pci_vsc.h" #include "lib/tout.h" #include "diag/fw_tracer.h" @@ -719,7 +720,7 @@ static const struct devlink_health_reporter_ops mlx5_fw_fatal_reporter_ops = { #define MLX5_FW_REPORTER_VF_GRACEFUL_PERIOD 30000 #define MLX5_FW_REPORTER_DEFAULT_GRACEFUL_PERIOD MLX5_FW_REPORTER_VF_GRACEFUL_PERIOD -static void mlx5_fw_reporters_create(struct mlx5_core_dev *dev) +void mlx5_fw_reporters_create(struct mlx5_core_dev *dev) { struct mlx5_core_health *health = &dev->priv.health; struct devlink *devlink = priv_to_devlink(dev); @@ -735,17 +736,17 @@ static void mlx5_fw_reporters_create(struct mlx5_core_dev *dev) } health->fw_reporter = - devlink_health_reporter_create(devlink, &mlx5_fw_reporter_ops, - 0, dev); + devl_health_reporter_create(devlink, &mlx5_fw_reporter_ops, + 0, dev); if (IS_ERR(health->fw_reporter)) mlx5_core_warn(dev, "Failed to create fw reporter, err = %ld\n", PTR_ERR(health->fw_reporter)); health->fw_fatal_reporter = - devlink_health_reporter_create(devlink, - &mlx5_fw_fatal_reporter_ops, - grace_period, - dev); + devl_health_reporter_create(devlink, + &mlx5_fw_fatal_reporter_ops, + grace_period, + dev); if (IS_ERR(health->fw_fatal_reporter)) mlx5_core_warn(dev, "Failed to create fw fatal reporter, err = %ld\n", PTR_ERR(health->fw_fatal_reporter)); @@ -777,7 +778,8 @@ void mlx5_trigger_health_work(struct mlx5_core_dev *dev) { struct mlx5_core_health *health = &dev->priv.health; - queue_work(health->wq, &health->fatal_report_work); + if (!mlx5_dev_is_lightweight(dev)) + queue_work(health->wq, &health->fatal_report_work); } #define MLX5_MSEC_PER_HOUR (MSEC_PER_SEC * 60 * 60) @@ -905,10 +907,15 @@ void mlx5_health_cleanup(struct mlx5_core_dev *dev) int mlx5_health_init(struct mlx5_core_dev *dev) { + struct devlink *devlink = priv_to_devlink(dev); struct mlx5_core_health *health; char *name; - mlx5_fw_reporters_create(dev); + if (!mlx5_dev_is_lightweight(dev)) { + devl_lock(devlink); + mlx5_fw_reporters_create(dev); + devl_unlock(devlink); + } mlx5_reporter_vnic_create(dev); health = &dev->priv.health; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c index 5d331b940f4d43643bcc1fc4ddba75248f0b6046..f0a074b2fcdf32d8ca634db4f30bc7d787e07c10 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c @@ -512,8 +512,11 @@ static void mlx5_lag_set_port_sel_mode_offloads(struct mlx5_lag *ldev, return; if (MLX5_CAP_PORT_SELECTION(dev0->dev, port_select_flow_table) && - tracker->tx_type == NETDEV_LAG_TX_TYPE_HASH) + tracker->tx_type == NETDEV_LAG_TX_TYPE_HASH) { + if (ldev->ports > 2) + ldev->buckets = MLX5_LAG_MAX_HASH_BUCKETS; set_bit(MLX5_LAG_MODE_FLAG_HASH_BASED, flags); + } } static int mlx5_lag_set_flags(struct mlx5_lag *ldev, enum mlx5_lag_mode mode, @@ -550,6 +553,29 @@ char *mlx5_get_str_port_sel_mode(enum mlx5_lag_mode mode, unsigned long flags) } } +static int mlx5_lag_create_single_fdb(struct mlx5_lag *ldev) +{ + struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev; + struct mlx5_eswitch *master_esw = dev0->priv.eswitch; + int err; + int i; + + for (i = MLX5_LAG_P1 + 1; i < ldev->ports; i++) { + struct mlx5_eswitch *slave_esw = ldev->pf[i].dev->priv.eswitch; + + err = mlx5_eswitch_offloads_single_fdb_add_one(master_esw, + slave_esw, ldev->ports); + if (err) + goto err; + } + return 0; +err: + for (; i > MLX5_LAG_P1; i--) + mlx5_eswitch_offloads_single_fdb_del_one(master_esw, + ldev->pf[i].dev->priv.eswitch); + return err; +} + static int mlx5_create_lag(struct mlx5_lag *ldev, struct lag_tracker *tracker, enum mlx5_lag_mode mode, @@ -557,7 +583,6 @@ static int mlx5_create_lag(struct mlx5_lag *ldev, { bool shared_fdb = test_bit(MLX5_LAG_MODE_FLAG_SHARED_FDB, &flags); struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev; - struct mlx5_core_dev *dev1 = ldev->pf[MLX5_LAG_P2].dev; u32 in[MLX5_ST_SZ_DW(destroy_lag_in)] = {}; int err; @@ -575,8 +600,7 @@ static int mlx5_create_lag(struct mlx5_lag *ldev, } if (shared_fdb) { - err = mlx5_eswitch_offloads_config_single_fdb(dev0->priv.eswitch, - dev1->priv.eswitch); + err = mlx5_lag_create_single_fdb(ldev); if (err) mlx5_core_err(dev0, "Can't enable single FDB mode\n"); else @@ -647,19 +671,21 @@ int mlx5_activate_lag(struct mlx5_lag *ldev, int mlx5_deactivate_lag(struct mlx5_lag *ldev) { struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev; - struct mlx5_core_dev *dev1 = ldev->pf[MLX5_LAG_P2].dev; + struct mlx5_eswitch *master_esw = dev0->priv.eswitch; u32 in[MLX5_ST_SZ_DW(destroy_lag_in)] = {}; bool roce_lag = __mlx5_lag_is_roce(ldev); unsigned long flags = ldev->mode_flags; int err; + int i; ldev->mode = MLX5_LAG_MODE_NONE; ldev->mode_flags = 0; mlx5_lag_mp_reset(ldev); if (test_bit(MLX5_LAG_MODE_FLAG_SHARED_FDB, &flags)) { - mlx5_eswitch_offloads_destroy_single_fdb(dev0->priv.eswitch, - dev1->priv.eswitch); + for (i = MLX5_LAG_P1 + 1; i < ldev->ports; i++) + mlx5_eswitch_offloads_single_fdb_del_one(master_esw, + ldev->pf[i].dev->priv.eswitch); clear_bit(MLX5_LAG_MODE_FLAG_SHARED_FDB, &flags); } @@ -685,7 +711,7 @@ int mlx5_deactivate_lag(struct mlx5_lag *ldev) return 0; } -#define MLX5_LAG_OFFLOADS_SUPPORTED_PORTS 2 +#define MLX5_LAG_OFFLOADS_SUPPORTED_PORTS 4 bool mlx5_lag_check_prereq(struct mlx5_lag *ldev) { #ifdef CONFIG_MLX5_ESWITCH @@ -711,7 +737,7 @@ bool mlx5_lag_check_prereq(struct mlx5_lag *ldev) if (mlx5_eswitch_mode(ldev->pf[i].dev) != mode) return false; - if (mode == MLX5_ESWITCH_OFFLOADS && ldev->ports != MLX5_LAG_OFFLOADS_SUPPORTED_PORTS) + if (mode == MLX5_ESWITCH_OFFLOADS && ldev->ports > MLX5_LAG_OFFLOADS_SUPPORTED_PORTS) return false; #else for (i = 0; i < ldev->ports; i++) @@ -759,7 +785,6 @@ void mlx5_disable_lag(struct mlx5_lag *ldev) { bool shared_fdb = test_bit(MLX5_LAG_MODE_FLAG_SHARED_FDB, &ldev->mode_flags); struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev; - struct mlx5_core_dev *dev1 = ldev->pf[MLX5_LAG_P2].dev; bool roce_lag; int err; int i; @@ -784,28 +809,35 @@ void mlx5_disable_lag(struct mlx5_lag *ldev) if (shared_fdb || roce_lag) mlx5_lag_add_devices(ldev); - if (shared_fdb) { - if (!(dev0->priv.flags & MLX5_PRIV_FLAGS_DISABLE_ALL_ADEV)) - mlx5_eswitch_reload_reps(dev0->priv.eswitch); - if (!(dev1->priv.flags & MLX5_PRIV_FLAGS_DISABLE_ALL_ADEV)) - mlx5_eswitch_reload_reps(dev1->priv.eswitch); - } + if (shared_fdb) + for (i = 0; i < ldev->ports; i++) + if (!(ldev->pf[i].dev->priv.flags & MLX5_PRIV_FLAGS_DISABLE_ALL_ADEV)) + mlx5_eswitch_reload_reps(ldev->pf[i].dev->priv.eswitch); } -bool mlx5_shared_fdb_supported(struct mlx5_lag *ldev) +static bool mlx5_shared_fdb_supported(struct mlx5_lag *ldev) { - struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev; - struct mlx5_core_dev *dev1 = ldev->pf[MLX5_LAG_P2].dev; - - if (is_mdev_switchdev_mode(dev0) && - is_mdev_switchdev_mode(dev1) && - mlx5_eswitch_vport_match_metadata_enabled(dev0->priv.eswitch) && - mlx5_eswitch_vport_match_metadata_enabled(dev1->priv.eswitch) && - mlx5_devcom_is_paired(dev0->priv.devcom, - MLX5_DEVCOM_ESW_OFFLOADS) && - MLX5_CAP_GEN(dev1, lag_native_fdb_selection) && - MLX5_CAP_ESW(dev1, root_ft_on_other_esw) && - MLX5_CAP_ESW(dev0, esw_shared_ingress_acl)) + struct mlx5_core_dev *dev; + int i; + + for (i = MLX5_LAG_P1 + 1; i < ldev->ports; i++) { + dev = ldev->pf[i].dev; + if (is_mdev_switchdev_mode(dev) && + mlx5_eswitch_vport_match_metadata_enabled(dev->priv.eswitch) && + MLX5_CAP_GEN(dev, lag_native_fdb_selection) && + MLX5_CAP_ESW(dev, root_ft_on_other_esw) && + mlx5_eswitch_get_npeers(dev->priv.eswitch) == + MLX5_CAP_GEN(dev, num_lag_ports) - 1) + continue; + return false; + } + + dev = ldev->pf[MLX5_LAG_P1].dev; + if (is_mdev_switchdev_mode(dev) && + mlx5_eswitch_vport_match_metadata_enabled(dev->priv.eswitch) && + mlx5_devcom_comp_is_ready(dev->priv.devcom, MLX5_DEVCOM_ESW_OFFLOADS) && + MLX5_CAP_ESW(dev, esw_shared_ingress_acl) && + mlx5_eswitch_get_npeers(dev->priv.eswitch) == MLX5_CAP_GEN(dev, num_lag_ports) - 1) return true; return false; @@ -842,7 +874,6 @@ static bool mlx5_lag_should_disable_lag(struct mlx5_lag *ldev, bool do_bond) static void mlx5_do_bond(struct mlx5_lag *ldev) { struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev; - struct mlx5_core_dev *dev1 = ldev->pf[MLX5_LAG_P2].dev; struct lag_tracker tracker = { }; bool do_bond, roce_lag; int err; @@ -883,20 +914,24 @@ static void mlx5_do_bond(struct mlx5_lag *ldev) for (i = 1; i < ldev->ports; i++) mlx5_nic_vport_enable_roce(ldev->pf[i].dev); } else if (shared_fdb) { + int i; + dev0->priv.flags &= ~MLX5_PRIV_FLAGS_DISABLE_IB_ADEV; mlx5_rescan_drivers_locked(dev0); - err = mlx5_eswitch_reload_reps(dev0->priv.eswitch); - if (!err) - err = mlx5_eswitch_reload_reps(dev1->priv.eswitch); + for (i = 0; i < ldev->ports; i++) { + err = mlx5_eswitch_reload_reps(ldev->pf[i].dev->priv.eswitch); + if (err) + break; + } if (err) { dev0->priv.flags |= MLX5_PRIV_FLAGS_DISABLE_IB_ADEV; mlx5_rescan_drivers_locked(dev0); mlx5_deactivate_lag(ldev); mlx5_lag_add_devices(ldev); - mlx5_eswitch_reload_reps(dev0->priv.eswitch); - mlx5_eswitch_reload_reps(dev1->priv.eswitch); + for (i = 0; i < ldev->ports; i++) + mlx5_eswitch_reload_reps(ldev->pf[i].dev->priv.eswitch); mlx5_core_err(dev0, "Failed to enable lag\n"); return; } @@ -1233,14 +1268,21 @@ void mlx5_lag_remove_mdev(struct mlx5_core_dev *dev) mlx5_ldev_put(ldev); } +bool mlx5_lag_is_supported(struct mlx5_core_dev *dev) +{ + if (!MLX5_CAP_GEN(dev, vport_group_manager) || + !MLX5_CAP_GEN(dev, lag_master) || + MLX5_CAP_GEN(dev, num_lag_ports) < 2 || + MLX5_CAP_GEN(dev, num_lag_ports) > MLX5_MAX_PORTS) + return false; + return true; +} + void mlx5_lag_add_mdev(struct mlx5_core_dev *dev) { int err; - if (!MLX5_CAP_GEN(dev, vport_group_manager) || - !MLX5_CAP_GEN(dev, lag_master) || - (MLX5_CAP_GEN(dev, num_lag_ports) > MLX5_MAX_PORTS || - MLX5_CAP_GEN(dev, num_lag_ports) <= 1)) + if (!mlx5_lag_is_supported(dev)) return; recheck: @@ -1496,26 +1538,37 @@ u8 mlx5_lag_get_num_ports(struct mlx5_core_dev *dev) } EXPORT_SYMBOL(mlx5_lag_get_num_ports); -struct mlx5_core_dev *mlx5_lag_get_peer_mdev(struct mlx5_core_dev *dev) +struct mlx5_core_dev *mlx5_lag_get_next_peer_mdev(struct mlx5_core_dev *dev, int *i) { struct mlx5_core_dev *peer_dev = NULL; struct mlx5_lag *ldev; unsigned long flags; + int idx; spin_lock_irqsave(&lag_lock, flags); ldev = mlx5_lag_dev(dev); if (!ldev) goto unlock; - peer_dev = ldev->pf[MLX5_LAG_P1].dev == dev ? - ldev->pf[MLX5_LAG_P2].dev : - ldev->pf[MLX5_LAG_P1].dev; + if (*i == ldev->ports) + goto unlock; + for (idx = *i; idx < ldev->ports; idx++) + if (ldev->pf[idx].dev != dev) + break; + + if (idx == ldev->ports) { + *i = idx; + goto unlock; + } + *i = idx + 1; + + peer_dev = ldev->pf[idx].dev; unlock: spin_unlock_irqrestore(&lag_lock, flags); return peer_dev; } -EXPORT_SYMBOL(mlx5_lag_get_peer_mdev); +EXPORT_SYMBOL(mlx5_lag_get_next_peer_mdev); int mlx5_lag_query_cong_counters(struct mlx5_core_dev *dev, u64 *values, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.h b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.h index bc1f1dd3e2834a0bd96bd9b32d435aafdab3789e..a061b1873e27008bdae392693c8c05e956da087a 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.h @@ -74,15 +74,7 @@ struct mlx5_lag { struct lag_mpesw lag_mpesw; }; -static inline bool mlx5_is_lag_supported(struct mlx5_core_dev *dev) -{ - if (!MLX5_CAP_GEN(dev, vport_group_manager) || - !MLX5_CAP_GEN(dev, lag_master) || - MLX5_CAP_GEN(dev, num_lag_ports) < 2 || - MLX5_CAP_GEN(dev, num_lag_ports) > MLX5_MAX_PORTS) - return false; - return true; -} +bool mlx5_lag_is_supported(struct mlx5_core_dev *dev); static inline struct mlx5_lag * mlx5_lag_dev(struct mlx5_core_dev *dev) @@ -111,7 +103,6 @@ int mlx5_activate_lag(struct mlx5_lag *ldev, bool shared_fdb); int mlx5_lag_dev_get_netdev_idx(struct mlx5_lag *ldev, struct net_device *ndev); -bool mlx5_shared_fdb_supported(struct mlx5_lag *ldev); char *mlx5_get_str_port_sel_mode(enum mlx5_lag_mode mode, unsigned long flags); void mlx5_infer_tx_enabled(struct lag_tracker *tracker, u8 num_ports, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag/mp.c b/drivers/net/ethernet/mellanox/mlx5/core/lag/mp.c index d85a8dfc153d6a5a945a7538848fb4d9f3c09d18..b1aa494c76ba88d3d5fd836aa9433b9da9c3760d 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lag/mp.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/lag/mp.c @@ -7,13 +7,14 @@ #include "lag/mp.h" #include "mlx5_core.h" #include "eswitch.h" -#include "lib/mlx5.h" +#include "lib/events.h" static bool __mlx5_lag_is_multipath(struct mlx5_lag *ldev) { return ldev->mode == MLX5_LAG_MODE_MULTIPATH; } +#define MLX5_LAG_MULTIPATH_OFFLOADS_SUPPORTED_PORTS 2 static bool mlx5_lag_multipath_check_prereq(struct mlx5_lag *ldev) { if (!mlx5_lag_is_ready(ldev)) @@ -22,6 +23,9 @@ static bool mlx5_lag_multipath_check_prereq(struct mlx5_lag *ldev) if (__mlx5_lag_is_active(ldev) && !__mlx5_lag_is_multipath(ldev)) return false; + if (ldev->ports > MLX5_LAG_MULTIPATH_OFFLOADS_SUPPORTED_PORTS) + return false; + return mlx5_esw_multipath_prereq(ldev->pf[MLX5_LAG_P1].dev, ldev->pf[MLX5_LAG_P2].dev); } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag/mpesw.c b/drivers/net/ethernet/mellanox/mlx5/core/lag/mpesw.c index 0c0ef600f6437dcc948c26f3f27b4cdfe42c06a7..4bf15391525c590787d7e64d7f7cc6586f1c301b 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lag/mpesw.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/lag/mpesw.c @@ -6,7 +6,7 @@ #include "lag/lag.h" #include "eswitch.h" #include "esw/acl/ofld.h" -#include "lib/mlx5.h" +#include "lib/events.h" static void mlx5_mpesw_metadata_cleanup(struct mlx5_lag *ldev) { @@ -65,6 +65,7 @@ static int mlx5_mpesw_metadata_set(struct mlx5_lag *ldev) return err; } +#define MLX5_LAG_MPESW_OFFLOADS_SUPPORTED_PORTS 2 static int enable_mpesw(struct mlx5_lag *ldev) { struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev; @@ -74,6 +75,9 @@ static int enable_mpesw(struct mlx5_lag *ldev) if (ldev->mode != MLX5_LAG_MODE_NONE) return -EINVAL; + if (ldev->ports > MLX5_LAG_MPESW_OFFLOADS_SUPPORTED_PORTS) + return -EOPNOTSUPP; + if (mlx5_eswitch_mode(dev0) != MLX5_ESWITCH_OFFLOADS || !MLX5_CAP_PORT_SELECTION(dev0, port_select_flow_table) || !MLX5_CAP_GEN(dev0, create_lag_when_not_master_up) || diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c index 932fbc843c6921dd33e564a42f5601c12886f9ea..973babfaff25cd84dc562cfb5491e86a9986c861 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c @@ -93,17 +93,23 @@ static bool mlx5_modify_mtutc_allowed(struct mlx5_core_dev *mdev) return MLX5_CAP_MCAM_FEATURE(mdev, ptpcyc2realtime_modify); } -static bool mlx5_is_mtutc_time_adj_cap(struct mlx5_core_dev *mdev, s64 delta) +static s32 mlx5_ptp_getmaxphase(struct ptp_clock_info *ptp) { - s64 min = MLX5_MTUTC_OPERATION_ADJUST_TIME_MIN; - s64 max = MLX5_MTUTC_OPERATION_ADJUST_TIME_MAX; + struct mlx5_clock *clock = container_of(ptp, struct mlx5_clock, ptp_info); + struct mlx5_core_dev *mdev; - if (MLX5_CAP_MCAM_FEATURE(mdev, mtutc_time_adjustment_extended_range)) { - min = MLX5_MTUTC_OPERATION_ADJUST_TIME_EXTENDED_MIN; - max = MLX5_MTUTC_OPERATION_ADJUST_TIME_EXTENDED_MAX; - } + mdev = container_of(clock, struct mlx5_core_dev, clock); + + return MLX5_CAP_MCAM_FEATURE(mdev, mtutc_time_adjustment_extended_range) ? + MLX5_MTUTC_OPERATION_ADJUST_TIME_EXTENDED_MAX : + MLX5_MTUTC_OPERATION_ADJUST_TIME_MAX; +} + +static bool mlx5_is_mtutc_time_adj_cap(struct mlx5_core_dev *mdev, s64 delta) +{ + s64 max = mlx5_ptp_getmaxphase(&mdev->clock.ptp_info); - if (delta < min || delta > max) + if (delta < -max || delta > max) return false; return true; @@ -351,14 +357,6 @@ static int mlx5_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta) static int mlx5_ptp_adjphase(struct ptp_clock_info *ptp, s32 delta) { - struct mlx5_clock *clock = container_of(ptp, struct mlx5_clock, ptp_info); - struct mlx5_core_dev *mdev; - - mdev = container_of(clock, struct mlx5_core_dev, clock); - - if (!mlx5_is_mtutc_time_adj_cap(mdev, delta)) - return -ERANGE; - return mlx5_ptp_adjtime(ptp, delta); } @@ -734,6 +732,7 @@ static const struct ptp_clock_info mlx5_ptp_clock_info = { .pps = 0, .adjfine = mlx5_ptp_adjfine, .adjphase = mlx5_ptp_adjphase, + .getmaxphase = mlx5_ptp_getmaxphase, .adjtime = mlx5_ptp_adjtime, .gettimex64 = mlx5_ptp_gettimex, .settime64 = mlx5_ptp_settime, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.c index b7d779d08d8371082415d439b547e54cf6f6b8e5..78c94b22bdc09a9b78d1c20107e3b2268855f3f8 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.c @@ -19,7 +19,7 @@ struct mlx5_devcom_component { mlx5_devcom_event_handler_t handler; struct rw_semaphore sem; - bool paired; + bool ready; }; struct mlx5_devcom_list { @@ -75,13 +75,14 @@ struct mlx5_devcom *mlx5_devcom_register_device(struct mlx5_core_dev *dev) if (!mlx5_core_is_pf(dev)) return NULL; - if (MLX5_CAP_GEN(dev, num_lag_ports) != MLX5_DEVCOM_PORTS_SUPPORTED) + if (MLX5_CAP_GEN(dev, num_lag_ports) > MLX5_DEVCOM_PORTS_SUPPORTED) return NULL; mlx5_dev_list_lock(); sguid0 = mlx5_query_nic_system_image_guid(dev); list_for_each_entry(iter, &devcom_list, list) { - struct mlx5_core_dev *tmp_dev = NULL; + /* There is at least one device in iter */ + struct mlx5_core_dev *tmp_dev; idx = -1; for (i = 0; i < MLX5_DEVCOM_PORTS_SUPPORTED; i++) { @@ -193,7 +194,7 @@ void mlx5_devcom_unregister_component(struct mlx5_devcom *devcom, int mlx5_devcom_send_event(struct mlx5_devcom *devcom, enum mlx5_devcom_components id, - int event, + int event, int rollback_event, void *event_data) { struct mlx5_devcom_component *comp; @@ -210,84 +211,134 @@ int mlx5_devcom_send_event(struct mlx5_devcom *devcom, if (i != devcom->idx && data) { err = comp->handler(event, data, event_data); - break; + if (err) + goto rollback; } } + up_write(&comp->sem); + return 0; + +rollback: + while (i--) { + void *data = rcu_dereference_protected(comp->device[i].data, + lockdep_is_held(&comp->sem)); + + if (i != devcom->idx && data) + comp->handler(rollback_event, data, event_data); + } + up_write(&comp->sem); return err; } -void mlx5_devcom_set_paired(struct mlx5_devcom *devcom, - enum mlx5_devcom_components id, - bool paired) +void mlx5_devcom_comp_set_ready(struct mlx5_devcom *devcom, + enum mlx5_devcom_components id, + bool ready) { struct mlx5_devcom_component *comp; comp = &devcom->priv->components[id]; WARN_ON(!rwsem_is_locked(&comp->sem)); - WRITE_ONCE(comp->paired, paired); + WRITE_ONCE(comp->ready, ready); } -bool mlx5_devcom_is_paired(struct mlx5_devcom *devcom, - enum mlx5_devcom_components id) +bool mlx5_devcom_comp_is_ready(struct mlx5_devcom *devcom, + enum mlx5_devcom_components id) { if (IS_ERR_OR_NULL(devcom)) return false; - return READ_ONCE(devcom->priv->components[id].paired); + return READ_ONCE(devcom->priv->components[id].ready); } -void *mlx5_devcom_get_peer_data(struct mlx5_devcom *devcom, - enum mlx5_devcom_components id) +bool mlx5_devcom_for_each_peer_begin(struct mlx5_devcom *devcom, + enum mlx5_devcom_components id) { struct mlx5_devcom_component *comp; - int i; if (IS_ERR_OR_NULL(devcom)) - return NULL; + return false; comp = &devcom->priv->components[id]; down_read(&comp->sem); - if (!READ_ONCE(comp->paired)) { + if (!READ_ONCE(comp->ready)) { up_read(&comp->sem); - return NULL; + return false; } - for (i = 0; i < MLX5_DEVCOM_PORTS_SUPPORTED; i++) - if (i != devcom->idx) - break; + return true; +} + +void mlx5_devcom_for_each_peer_end(struct mlx5_devcom *devcom, + enum mlx5_devcom_components id) +{ + struct mlx5_devcom_component *comp = &devcom->priv->components[id]; - return rcu_dereference_protected(comp->device[i].data, lockdep_is_held(&comp->sem)); + up_read(&comp->sem); } -void *mlx5_devcom_get_peer_data_rcu(struct mlx5_devcom *devcom, enum mlx5_devcom_components id) +void *mlx5_devcom_get_next_peer_data(struct mlx5_devcom *devcom, + enum mlx5_devcom_components id, + int *i) { struct mlx5_devcom_component *comp; - int i; + void *ret; + int idx; - if (IS_ERR_OR_NULL(devcom)) - return NULL; + comp = &devcom->priv->components[id]; - for (i = 0; i < MLX5_DEVCOM_PORTS_SUPPORTED; i++) - if (i != devcom->idx) - break; + if (*i == MLX5_DEVCOM_PORTS_SUPPORTED) + return NULL; + for (idx = *i; idx < MLX5_DEVCOM_PORTS_SUPPORTED; idx++) { + if (idx != devcom->idx) { + ret = rcu_dereference_protected(comp->device[idx].data, + lockdep_is_held(&comp->sem)); + if (ret) + break; + } + } - comp = &devcom->priv->components[id]; - /* This can change concurrently, however 'data' pointer will remain - * valid for the duration of RCU read section. - */ - if (!READ_ONCE(comp->paired)) + if (idx == MLX5_DEVCOM_PORTS_SUPPORTED) { + *i = idx; return NULL; + } + *i = idx + 1; - return rcu_dereference(comp->device[i].data); + return ret; } -void mlx5_devcom_release_peer_data(struct mlx5_devcom *devcom, - enum mlx5_devcom_components id) +void *mlx5_devcom_get_next_peer_data_rcu(struct mlx5_devcom *devcom, + enum mlx5_devcom_components id, + int *i) { - struct mlx5_devcom_component *comp = &devcom->priv->components[id]; + struct mlx5_devcom_component *comp; + void *ret; + int idx; - up_read(&comp->sem); + comp = &devcom->priv->components[id]; + + if (*i == MLX5_DEVCOM_PORTS_SUPPORTED) + return NULL; + for (idx = *i; idx < MLX5_DEVCOM_PORTS_SUPPORTED; idx++) { + if (idx != devcom->idx) { + /* This can change concurrently, however 'data' pointer will remain + * valid for the duration of RCU read section. + */ + if (!READ_ONCE(comp->ready)) + return NULL; + ret = rcu_dereference(comp->device[idx].data); + if (ret) + break; + } + } + + if (idx == MLX5_DEVCOM_PORTS_SUPPORTED) { + *i = idx; + return NULL; + } + *i = idx + 1; + + return ret; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.h b/drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.h index 9a496f4722dadd690388a98c5cba59f0cfa9371b..d953a01b8eaac193bd96b10d3778df430e30999f 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.h @@ -6,7 +6,7 @@ #include -#define MLX5_DEVCOM_PORTS_SUPPORTED 2 +#define MLX5_DEVCOM_PORTS_SUPPORTED 4 enum mlx5_devcom_components { MLX5_DEVCOM_ESW_OFFLOADS, @@ -30,20 +30,33 @@ void mlx5_devcom_unregister_component(struct mlx5_devcom *devcom, int mlx5_devcom_send_event(struct mlx5_devcom *devcom, enum mlx5_devcom_components id, - int event, + int event, int rollback_event, void *event_data); -void mlx5_devcom_set_paired(struct mlx5_devcom *devcom, - enum mlx5_devcom_components id, - bool paired); -bool mlx5_devcom_is_paired(struct mlx5_devcom *devcom, - enum mlx5_devcom_components id); +void mlx5_devcom_comp_set_ready(struct mlx5_devcom *devcom, + enum mlx5_devcom_components id, + bool ready); +bool mlx5_devcom_comp_is_ready(struct mlx5_devcom *devcom, + enum mlx5_devcom_components id); -void *mlx5_devcom_get_peer_data(struct mlx5_devcom *devcom, - enum mlx5_devcom_components id); -void *mlx5_devcom_get_peer_data_rcu(struct mlx5_devcom *devcom, enum mlx5_devcom_components id); -void mlx5_devcom_release_peer_data(struct mlx5_devcom *devcom, +bool mlx5_devcom_for_each_peer_begin(struct mlx5_devcom *devcom, + enum mlx5_devcom_components id); +void mlx5_devcom_for_each_peer_end(struct mlx5_devcom *devcom, enum mlx5_devcom_components id); +void *mlx5_devcom_get_next_peer_data(struct mlx5_devcom *devcom, + enum mlx5_devcom_components id, int *i); -#endif +#define mlx5_devcom_for_each_peer_entry(devcom, id, data, i) \ + for (i = 0, data = mlx5_devcom_get_next_peer_data(devcom, id, &i); \ + data; \ + data = mlx5_devcom_get_next_peer_data(devcom, id, &i)) + +void *mlx5_devcom_get_next_peer_data_rcu(struct mlx5_devcom *devcom, + enum mlx5_devcom_components id, int *i); +#define mlx5_devcom_for_each_peer_entry_rcu(devcom, id, data, i) \ + for (i = 0, data = mlx5_devcom_get_next_peer_data_rcu(devcom, id, &i); \ + data; \ + data = mlx5_devcom_get_next_peer_data_rcu(devcom, id, &i)) + +#endif diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/events.h b/drivers/net/ethernet/mellanox/mlx5/core/lib/events.h new file mode 100644 index 0000000000000000000000000000000000000000..a0f7faea317bc9506ac60e51102e9c89190d8d6e --- /dev/null +++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/events.h @@ -0,0 +1,40 @@ +/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */ +/* Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved. */ + +#ifndef __LIB_EVENTS_H__ +#define __LIB_EVENTS_H__ + +#include "mlx5_core.h" + +#define PORT_MODULE_EVENT_MODULE_STATUS_MASK 0xF +#define PORT_MODULE_EVENT_ERROR_TYPE_MASK 0xF + +enum port_module_event_status_type { + MLX5_MODULE_STATUS_PLUGGED = 0x1, + MLX5_MODULE_STATUS_UNPLUGGED = 0x2, + MLX5_MODULE_STATUS_ERROR = 0x3, + MLX5_MODULE_STATUS_DISABLED = 0x4, + MLX5_MODULE_STATUS_NUM, +}; + +enum port_module_event_error_type { + MLX5_MODULE_EVENT_ERROR_POWER_BUDGET_EXCEEDED = 0x0, + MLX5_MODULE_EVENT_ERROR_LONG_RANGE_FOR_NON_MLNX = 0x1, + MLX5_MODULE_EVENT_ERROR_BUS_STUCK = 0x2, + MLX5_MODULE_EVENT_ERROR_NO_EEPROM_RETRY_TIMEOUT = 0x3, + MLX5_MODULE_EVENT_ERROR_ENFORCE_PART_NUMBER_LIST = 0x4, + MLX5_MODULE_EVENT_ERROR_UNKNOWN_IDENTIFIER = 0x5, + MLX5_MODULE_EVENT_ERROR_HIGH_TEMPERATURE = 0x6, + MLX5_MODULE_EVENT_ERROR_BAD_CABLE = 0x7, + MLX5_MODULE_EVENT_ERROR_PCIE_POWER_SLOT_EXCEEDED = 0xc, + MLX5_MODULE_EVENT_ERROR_NUM, +}; + +struct mlx5_pme_stats { + u64 status_counters[MLX5_MODULE_STATUS_NUM]; + u64 error_counters[MLX5_MODULE_EVENT_ERROR_NUM]; +}; + +void mlx5_get_pme_stats(struct mlx5_core_dev *dev, struct mlx5_pme_stats *stats); +int mlx5_notifier_call_chain(struct mlx5_events *events, unsigned int event, void *data); +#endif diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/mlx5.h b/drivers/net/ethernet/mellanox/mlx5/core/lib/mlx5.h index ccf12f7db6f064e098fd6b9cbe7b075731b88e54..2b5826a785c4f747b02135ab0f7872fa46c904af 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lib/mlx5.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/mlx5.h @@ -45,40 +45,6 @@ int mlx5_crdump_enable(struct mlx5_core_dev *dev); void mlx5_crdump_disable(struct mlx5_core_dev *dev); int mlx5_crdump_collect(struct mlx5_core_dev *dev, u32 *cr_data); -/* TODO move to lib/events.h */ - -#define PORT_MODULE_EVENT_MODULE_STATUS_MASK 0xF -#define PORT_MODULE_EVENT_ERROR_TYPE_MASK 0xF - -enum port_module_event_status_type { - MLX5_MODULE_STATUS_PLUGGED = 0x1, - MLX5_MODULE_STATUS_UNPLUGGED = 0x2, - MLX5_MODULE_STATUS_ERROR = 0x3, - MLX5_MODULE_STATUS_DISABLED = 0x4, - MLX5_MODULE_STATUS_NUM, -}; - -enum port_module_event_error_type { - MLX5_MODULE_EVENT_ERROR_POWER_BUDGET_EXCEEDED = 0x0, - MLX5_MODULE_EVENT_ERROR_LONG_RANGE_FOR_NON_MLNX = 0x1, - MLX5_MODULE_EVENT_ERROR_BUS_STUCK = 0x2, - MLX5_MODULE_EVENT_ERROR_NO_EEPROM_RETRY_TIMEOUT = 0x3, - MLX5_MODULE_EVENT_ERROR_ENFORCE_PART_NUMBER_LIST = 0x4, - MLX5_MODULE_EVENT_ERROR_UNKNOWN_IDENTIFIER = 0x5, - MLX5_MODULE_EVENT_ERROR_HIGH_TEMPERATURE = 0x6, - MLX5_MODULE_EVENT_ERROR_BAD_CABLE = 0x7, - MLX5_MODULE_EVENT_ERROR_PCIE_POWER_SLOT_EXCEEDED = 0xc, - MLX5_MODULE_EVENT_ERROR_NUM, -}; - -struct mlx5_pme_stats { - u64 status_counters[MLX5_MODULE_STATUS_NUM]; - u64 error_counters[MLX5_MODULE_EVENT_ERROR_NUM]; -}; - -void mlx5_get_pme_stats(struct mlx5_core_dev *dev, struct mlx5_pme_stats *stats); -int mlx5_notifier_call_chain(struct mlx5_events *events, unsigned int event, void *data); - static inline struct net *mlx5_core_net(struct mlx5_core_dev *dev) { return devlink_net(priv_to_devlink(dev)); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/mpfs.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/mpfs.c index 8ff16318e32dc922fa318712016deed2cb6e4900..4450091e181a104bd8bc122f845735a470b68aa0 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lib/mpfs.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/mpfs.c @@ -99,7 +99,7 @@ int mlx5_mpfs_init(struct mlx5_core_dev *dev) int l2table_size = 1 << MLX5_CAP_GEN(dev, log_max_l2_table); struct mlx5_mpfs *mpfs; - if (!MLX5_ESWITCH_MANAGER(dev)) + if (!MLX5_ESWITCH_MANAGER(dev) || l2table_size == 1) return 0; mpfs = kzalloc(sizeof(*mpfs), GFP_KERNEL); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/tout.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/tout.c index 696e45e2bd06d476348962227ee5af627ebc0271..e223e0e46433e8fec4a7a4fb375c47654622cd68 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lib/tout.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/tout.c @@ -24,7 +24,8 @@ static const u32 tout_def_sw_val[MAX_TIMEOUT_TYPES] = { [MLX5_TO_TEARDOWN_MS] = 3000, [MLX5_TO_FSM_REACTIVATE_MS] = 5000, [MLX5_TO_RECLAIM_PAGES_MS] = 5000, - [MLX5_TO_RECLAIM_VFS_PAGES_MS] = 120000 + [MLX5_TO_RECLAIM_VFS_PAGES_MS] = 120000, + [MLX5_TO_RESET_UNLOAD_MS] = 300000 }; static void tout_set(struct mlx5_core_dev *dev, u64 val, enum mlx5_timeouts_types type) @@ -118,7 +119,8 @@ u64 _mlx5_tout_ms(struct mlx5_core_dev *dev, enum mlx5_timeouts_types type) #define MLX5_TIMEOUT_FILL(fld, reg_out, dev, to_type, to_extra) \ ({ \ u64 fw_to = MLX5_TIMEOUT_QUERY(fld, reg_out); \ - tout_set(dev, fw_to + (to_extra), to_type); \ + if (fw_to) \ + tout_set(dev, fw_to + (to_extra), to_type); \ fw_to; \ }) @@ -146,6 +148,7 @@ static int tout_query_dtor(struct mlx5_core_dev *dev) MLX5_TIMEOUT_FILL(fsm_reactivate_to, out, dev, MLX5_TO_FSM_REACTIVATE_MS, 0); MLX5_TIMEOUT_FILL(reclaim_pages_to, out, dev, MLX5_TO_RECLAIM_PAGES_MS, 0); MLX5_TIMEOUT_FILL(reclaim_vfs_pages_to, out, dev, MLX5_TO_RECLAIM_VFS_PAGES_MS, 0); + MLX5_TIMEOUT_FILL(reset_unload_to, out, dev, MLX5_TO_RESET_UNLOAD_MS, 0); return 0; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/tout.h b/drivers/net/ethernet/mellanox/mlx5/core/lib/tout.h index bc9e9aeda8478149f29cd8da1c9b311e37574d29..99e0a05526fe4269ef6ff9002992f3af5b89a19f 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lib/tout.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/tout.h @@ -26,6 +26,7 @@ enum mlx5_timeouts_types { MLX5_TO_FSM_REACTIVATE_MS, MLX5_TO_RECLAIM_PAGES_MS, MLX5_TO_RECLAIM_VFS_PAGES_MS, + MLX5_TO_RESET_UNLOAD_MS, MAX_TIMEOUT_TYPES }; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c index d6ee016deae176aa2ac54401304a5e8e1dda4c8f..88dbea6631d507befd6d59a253928bce901912d0 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c @@ -619,6 +619,9 @@ static int handle_hca_cap(struct mlx5_core_dev *dev, void *set_ctx) if (MLX5_CAP_GEN_MAX(dev, pci_sync_for_fw_update_event)) MLX5_SET(cmd_hca_cap, set_hca_cap, pci_sync_for_fw_update_event, 1); + if (MLX5_CAP_GEN_MAX(dev, pci_sync_for_fw_update_with_driver_unload)) + MLX5_SET(cmd_hca_cap, set_hca_cap, + pci_sync_for_fw_update_with_driver_unload, 1); if (MLX5_CAP_GEN_MAX(dev, num_vhca_ports)) MLX5_SET(cmd_hca_cap, @@ -1118,7 +1121,7 @@ static void mlx5_cleanup_once(struct mlx5_core_dev *dev) mlx5_devcom_unregister_device(dev->priv.devcom); } -static int mlx5_function_setup(struct mlx5_core_dev *dev, bool boot, u64 timeout) +static int mlx5_function_enable(struct mlx5_core_dev *dev, bool boot, u64 timeout) { int err; @@ -1183,28 +1186,56 @@ static int mlx5_function_setup(struct mlx5_core_dev *dev, bool boot, u64 timeout goto reclaim_boot_pages; } + return 0; + +reclaim_boot_pages: + mlx5_reclaim_startup_pages(dev); +err_disable_hca: + mlx5_core_disable_hca(dev, 0); +stop_health_poll: + mlx5_stop_health_poll(dev, boot); +err_cmd_cleanup: + mlx5_cmd_set_state(dev, MLX5_CMDIF_STATE_DOWN); + mlx5_cmd_cleanup(dev); + + return err; +} + +static void mlx5_function_disable(struct mlx5_core_dev *dev, bool boot) +{ + mlx5_reclaim_startup_pages(dev); + mlx5_core_disable_hca(dev, 0); + mlx5_stop_health_poll(dev, boot); + mlx5_cmd_set_state(dev, MLX5_CMDIF_STATE_DOWN); + mlx5_cmd_cleanup(dev); +} + +static int mlx5_function_open(struct mlx5_core_dev *dev) +{ + int err; + err = set_hca_ctrl(dev); if (err) { mlx5_core_err(dev, "set_hca_ctrl failed\n"); - goto reclaim_boot_pages; + return err; } err = set_hca_cap(dev); if (err) { mlx5_core_err(dev, "set_hca_cap failed\n"); - goto reclaim_boot_pages; + return err; } err = mlx5_satisfy_startup_pages(dev, 0); if (err) { mlx5_core_err(dev, "failed to allocate init pages\n"); - goto reclaim_boot_pages; + return err; } err = mlx5_cmd_init_hca(dev, sw_owner_id); if (err) { mlx5_core_err(dev, "init hca failed\n"); - goto reclaim_boot_pages; + return err; } mlx5_set_driver_version(dev); @@ -1212,26 +1243,13 @@ static int mlx5_function_setup(struct mlx5_core_dev *dev, bool boot, u64 timeout err = mlx5_query_hca_caps(dev); if (err) { mlx5_core_err(dev, "query hca failed\n"); - goto reclaim_boot_pages; + return err; } mlx5_start_health_fw_log_up(dev); - return 0; - -reclaim_boot_pages: - mlx5_reclaim_startup_pages(dev); -err_disable_hca: - mlx5_core_disable_hca(dev, 0); -stop_health_poll: - mlx5_stop_health_poll(dev, boot); -err_cmd_cleanup: - mlx5_cmd_set_state(dev, MLX5_CMDIF_STATE_DOWN); - mlx5_cmd_cleanup(dev); - - return err; } -static int mlx5_function_teardown(struct mlx5_core_dev *dev, bool boot) +static int mlx5_function_close(struct mlx5_core_dev *dev) { int err; @@ -1240,15 +1258,33 @@ static int mlx5_function_teardown(struct mlx5_core_dev *dev, bool boot) mlx5_core_err(dev, "tear_down_hca failed, skip cleanup\n"); return err; } - mlx5_reclaim_startup_pages(dev); - mlx5_core_disable_hca(dev, 0); - mlx5_stop_health_poll(dev, boot); - mlx5_cmd_set_state(dev, MLX5_CMDIF_STATE_DOWN); - mlx5_cmd_cleanup(dev); return 0; } +static int mlx5_function_setup(struct mlx5_core_dev *dev, bool boot, u64 timeout) +{ + int err; + + err = mlx5_function_enable(dev, boot, timeout); + if (err) + return err; + + err = mlx5_function_open(dev); + if (err) + mlx5_function_disable(dev, boot); + return err; +} + +static int mlx5_function_teardown(struct mlx5_core_dev *dev, bool boot) +{ + int err = mlx5_function_close(dev); + + if (!err) + mlx5_function_disable(dev, boot); + return err; +} + static int mlx5_load(struct mlx5_core_dev *dev) { int err; @@ -1391,12 +1427,11 @@ static void mlx5_unload(struct mlx5_core_dev *dev) mlx5_put_uars_page(dev, dev->priv.uar); } -int mlx5_init_one(struct mlx5_core_dev *dev) +int mlx5_init_one_devl_locked(struct mlx5_core_dev *dev) { - struct devlink *devlink = priv_to_devlink(dev); + bool light_probe = mlx5_dev_is_lightweight(dev); int err = 0; - devl_lock(devlink); mutex_lock(&dev->intf_state_mutex); dev->state = MLX5_DEVICE_STATE_UP; @@ -1410,9 +1445,14 @@ int mlx5_init_one(struct mlx5_core_dev *dev) goto function_teardown; } - err = mlx5_devlink_params_register(priv_to_devlink(dev)); - if (err) - goto err_devlink_params_reg; + /* In case of light_probe, mlx5_devlink is already registered. + * Hence, don't register devlink again. + */ + if (!light_probe) { + err = mlx5_devlink_params_register(priv_to_devlink(dev)); + if (err) + goto err_devlink_params_reg; + } err = mlx5_load(dev); if (err) @@ -1425,14 +1465,14 @@ int mlx5_init_one(struct mlx5_core_dev *dev) goto err_register; mutex_unlock(&dev->intf_state_mutex); - devl_unlock(devlink); return 0; err_register: clear_bit(MLX5_INTERFACE_STATE_UP, &dev->intf_state); mlx5_unload(dev); err_load: - mlx5_devlink_params_unregister(priv_to_devlink(dev)); + if (!light_probe) + mlx5_devlink_params_unregister(priv_to_devlink(dev)); err_devlink_params_reg: mlx5_cleanup_once(dev); function_teardown: @@ -1440,6 +1480,16 @@ int mlx5_init_one(struct mlx5_core_dev *dev) err_function: dev->state = MLX5_DEVICE_STATE_INTERNAL_ERROR; mutex_unlock(&dev->intf_state_mutex); + return err; +} + +int mlx5_init_one(struct mlx5_core_dev *dev) +{ + struct devlink *devlink = priv_to_devlink(dev); + int err; + + devl_lock(devlink); + err = mlx5_init_one_devl_locked(dev); devl_unlock(devlink); return err; } @@ -1557,6 +1607,100 @@ void mlx5_unload_one(struct mlx5_core_dev *dev, bool suspend) devl_unlock(devlink); } +/* In case of light probe, we don't need a full query of hca_caps, but only the bellow caps. + * A full query of hca_caps will be done when the device will reload. + */ +static int mlx5_query_hca_caps_light(struct mlx5_core_dev *dev) +{ + int err; + + err = mlx5_core_get_caps(dev, MLX5_CAP_GENERAL); + if (err) + return err; + + if (MLX5_CAP_GEN(dev, eth_net_offloads)) { + err = mlx5_core_get_caps(dev, MLX5_CAP_ETHERNET_OFFLOADS); + if (err) + return err; + } + + if (MLX5_CAP_GEN(dev, nic_flow_table) || + MLX5_CAP_GEN(dev, ipoib_enhanced_offloads)) { + err = mlx5_core_get_caps(dev, MLX5_CAP_FLOW_TABLE); + if (err) + return err; + } + + if (MLX5_CAP_GEN_64(dev, general_obj_types) & + MLX5_GENERAL_OBJ_TYPES_CAP_VIRTIO_NET_Q) { + err = mlx5_core_get_caps(dev, MLX5_CAP_VDPA_EMULATION); + if (err) + return err; + } + + return 0; +} + +int mlx5_init_one_light(struct mlx5_core_dev *dev) +{ + struct devlink *devlink = priv_to_devlink(dev); + int err; + + dev->state = MLX5_DEVICE_STATE_UP; + err = mlx5_function_enable(dev, true, mlx5_tout_ms(dev, FW_PRE_INIT_TIMEOUT)); + if (err) { + mlx5_core_warn(dev, "mlx5_function_enable err=%d\n", err); + goto out; + } + + err = mlx5_query_hca_caps_light(dev); + if (err) { + mlx5_core_warn(dev, "mlx5_query_hca_caps_light err=%d\n", err); + goto query_hca_caps_err; + } + + devl_lock(devlink); + err = mlx5_devlink_params_register(priv_to_devlink(dev)); + devl_unlock(devlink); + if (err) { + mlx5_core_warn(dev, "mlx5_devlink_param_reg err = %d\n", err); + goto query_hca_caps_err; + } + + return 0; + +query_hca_caps_err: + mlx5_function_disable(dev, true); +out: + dev->state = MLX5_DEVICE_STATE_INTERNAL_ERROR; + return err; +} + +void mlx5_uninit_one_light(struct mlx5_core_dev *dev) +{ + struct devlink *devlink = priv_to_devlink(dev); + + devl_lock(devlink); + mlx5_devlink_params_unregister(priv_to_devlink(dev)); + devl_unlock(devlink); + if (dev->state != MLX5_DEVICE_STATE_UP) + return; + mlx5_function_disable(dev, true); +} + +/* xxx_light() function are used in order to configure the device without full + * init (light init). e.g.: There isn't a point in reload a device to light state. + * Hence, mlx5_load_one_light() isn't needed. + */ + +void mlx5_unload_one_light(struct mlx5_core_dev *dev) +{ + if (dev->state != MLX5_DEVICE_STATE_UP) + return; + mlx5_function_disable(dev, false); + dev->state = MLX5_DEVICE_STATE_INTERNAL_ERROR; +} + static const int types[] = { MLX5_CAP_GENERAL, MLX5_CAP_GENERAL_2, @@ -1809,7 +1953,7 @@ static void remove_one(struct pci_dev *pdev) mlx5_drain_fw_reset(dev); mlx5_drain_health_wq(dev); devlink_unregister(devlink); - mlx5_sriov_disable(pdev); + mlx5_sriov_disable(pdev, false); mlx5_thermal_uninit(dev); mlx5_crdump_disable(dev); mlx5_uninit_one(dev); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h b/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h index 229520405d4ae9d74abc7e844e2bea82184c6bf0..c4be257c043d4fe1702951b6178392b49b6e1ad4 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h @@ -195,7 +195,7 @@ void mlx5_sriov_cleanup(struct mlx5_core_dev *dev); int mlx5_sriov_attach(struct mlx5_core_dev *dev); void mlx5_sriov_detach(struct mlx5_core_dev *dev); int mlx5_core_sriov_configure(struct pci_dev *dev, int num_vfs); -void mlx5_sriov_disable(struct pci_dev *pdev); +void mlx5_sriov_disable(struct pci_dev *pdev, bool num_vf_change); int mlx5_core_sriov_set_msix_vec_count(struct pci_dev *vf, int msix_vec_count); int mlx5_core_enable_hca(struct mlx5_core_dev *dev, u16 func_id); int mlx5_core_disable_hca(struct mlx5_core_dev *dev, u16 func_id); @@ -240,11 +240,14 @@ int mlx5_attach_device(struct mlx5_core_dev *dev); void mlx5_detach_device(struct mlx5_core_dev *dev, bool suspend); int mlx5_register_device(struct mlx5_core_dev *dev); void mlx5_unregister_device(struct mlx5_core_dev *dev); +void mlx5_dev_set_lightweight(struct mlx5_core_dev *dev); +bool mlx5_dev_is_lightweight(struct mlx5_core_dev *dev); struct mlx5_core_dev *mlx5_get_next_phys_dev_lag(struct mlx5_core_dev *dev); void mlx5_dev_list_lock(void); void mlx5_dev_list_unlock(void); int mlx5_dev_list_trylock(void); +void mlx5_fw_reporters_create(struct mlx5_core_dev *dev); int mlx5_query_mtpps(struct mlx5_core_dev *dev, u32 *mtpps, u32 mtpps_size); int mlx5_set_mtpps(struct mlx5_core_dev *mdev, u32 *mtpps, u32 mtpps_size); int mlx5_query_mtppse(struct mlx5_core_dev *mdev, u8 pin, u8 *arm, u8 *mode); @@ -307,16 +310,20 @@ static inline bool mlx5_core_is_sf(const struct mlx5_core_dev *dev) int mlx5_mdev_init(struct mlx5_core_dev *dev, int profile_idx); void mlx5_mdev_uninit(struct mlx5_core_dev *dev); int mlx5_init_one(struct mlx5_core_dev *dev); +int mlx5_init_one_devl_locked(struct mlx5_core_dev *dev); void mlx5_uninit_one(struct mlx5_core_dev *dev); void mlx5_unload_one(struct mlx5_core_dev *dev, bool suspend); void mlx5_unload_one_devl_locked(struct mlx5_core_dev *dev, bool suspend); int mlx5_load_one(struct mlx5_core_dev *dev, bool recovery); int mlx5_load_one_devl_locked(struct mlx5_core_dev *dev, bool recovery); +int mlx5_init_one_light(struct mlx5_core_dev *dev); +void mlx5_uninit_one_light(struct mlx5_core_dev *dev); +void mlx5_unload_one_light(struct mlx5_core_dev *dev); -int mlx5_vport_set_other_func_cap(struct mlx5_core_dev *dev, const void *hca_cap, u16 function_id, +int mlx5_vport_set_other_func_cap(struct mlx5_core_dev *dev, const void *hca_cap, u16 vport, u16 opmod); -#define mlx5_vport_get_other_func_general_cap(dev, fid, out) \ - mlx5_vport_get_other_func_cap(dev, fid, out, MLX5_CAP_GENERAL) +#define mlx5_vport_get_other_func_general_cap(dev, vport, out) \ + mlx5_vport_get_other_func_cap(dev, vport, out, MLX5_CAP_GENERAL) void mlx5_events_work_enqueue(struct mlx5_core_dev *dev, struct work_struct *work); static inline u32 mlx5_sriov_get_vf_total_msix(struct pci_dev *pdev) @@ -331,4 +338,31 @@ bool mlx5_rdma_supported(struct mlx5_core_dev *dev); bool mlx5_vnet_supported(struct mlx5_core_dev *dev); bool mlx5_same_hw_devs(struct mlx5_core_dev *dev, struct mlx5_core_dev *peer_dev); +static inline u16 mlx5_core_ec_vf_vport_base(const struct mlx5_core_dev *dev) +{ + return MLX5_CAP_GEN_2(dev, ec_vf_vport_base); +} + +static inline u16 mlx5_core_ec_sriov_enabled(const struct mlx5_core_dev *dev) +{ + return mlx5_core_is_ecpf(dev) && mlx5_core_ec_vf_vport_base(dev); +} + +static inline bool mlx5_core_is_ec_vf_vport(const struct mlx5_core_dev *dev, u16 vport_num) +{ + int base_vport = mlx5_core_ec_vf_vport_base(dev); + int max_vport = base_vport + mlx5_core_max_ec_vfs(dev); + + if (!mlx5_core_ec_sriov_enabled(dev)) + return false; + + return (vport_num >= base_vport && vport_num < max_vport); +} + +static inline int mlx5_vport_to_func_id(const struct mlx5_core_dev *dev, u16 vport, bool ec_vf_func) +{ + return ec_vf_func ? vport - mlx5_core_ec_vf_vport_base(dev) + : vport; +} + #endif /* __MLX5_CORE_H__ */ diff --git a/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c b/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c index 95dc67fb300157aa8071d40ce667d0e43dd1b7af..dcf58efac159cf7286fd11483330c6750e290a19 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c @@ -79,7 +79,13 @@ static u16 func_id_to_type(struct mlx5_core_dev *dev, u16 func_id, bool ec_funct if (!func_id) return mlx5_core_is_ecpf(dev) && !ec_function ? MLX5_HOST_PF : MLX5_PF; - return func_id <= mlx5_core_max_vfs(dev) ? MLX5_VF : MLX5_SF; + if (func_id <= max(mlx5_core_max_vfs(dev), mlx5_core_max_ec_vfs(dev))) { + if (ec_function) + return MLX5_EC_VF; + else + return MLX5_VF; + } + return MLX5_SF; } static u32 mlx5_get_ec_function(u32 function) @@ -730,6 +736,9 @@ int mlx5_reclaim_startup_pages(struct mlx5_core_dev *dev) WARN(dev->priv.page_counters[MLX5_HOST_PF], "External host PF FW pages counter is %d after reclaiming all pages\n", dev->priv.page_counters[MLX5_HOST_PF]); + WARN(dev->priv.page_counters[MLX5_EC_VF], + "EC VFs FW pages counter is %d after reclaiming all pages\n", + dev->priv.page_counters[MLX5_EC_VF]); return 0; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c b/drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c index 843da89a903501dd8964bf5ba7de7967113fd5aa..cba2a4afb5fdaeeca65e32fa1aa6a7c63cea507e 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c @@ -41,6 +41,15 @@ struct mlx5_irq_table { struct mlx5_irq_pool *sf_comp_pool; }; +static int mlx5_core_func_to_vport(const struct mlx5_core_dev *dev, + int func, + bool ec_vf_func) +{ + if (!ec_vf_func) + return func; + return mlx5_core_ec_vf_vport_base(dev) + func - 1; +} + /** * mlx5_get_default_msix_vec_count - Get the default number of MSI-X vectors * to be ssigned to each VF. @@ -79,6 +88,8 @@ int mlx5_set_msix_vec_count(struct mlx5_core_dev *dev, int function_id, int set_sz = MLX5_ST_SZ_BYTES(set_hca_cap_in); void *hca_cap = NULL, *query_cap = NULL, *cap; int num_vf_msix, min_msix, max_msix; + bool ec_vf_function; + int vport; int ret; num_vf_msix = MLX5_CAP_GEN_MAX(dev, num_total_dynamic_vf_msix); @@ -104,7 +115,9 @@ int mlx5_set_msix_vec_count(struct mlx5_core_dev *dev, int function_id, goto out; } - ret = mlx5_vport_get_other_func_general_cap(dev, function_id, query_cap); + ec_vf_function = mlx5_core_ec_sriov_enabled(dev); + vport = mlx5_core_func_to_vport(dev, function_id, ec_vf_function); + ret = mlx5_vport_get_other_func_general_cap(dev, vport, query_cap); if (ret) goto out; @@ -115,6 +128,7 @@ int mlx5_set_msix_vec_count(struct mlx5_core_dev *dev, int function_id, MLX5_SET(set_hca_cap_in, hca_cap, opcode, MLX5_CMD_OP_SET_HCA_CAP); MLX5_SET(set_hca_cap_in, hca_cap, other_function, 1); + MLX5_SET(set_hca_cap_in, hca_cap, ec_vf_function, ec_vf_function); MLX5_SET(set_hca_cap_in, hca_cap, function_id, function_id); MLX5_SET(set_hca_cap_in, hca_cap, op_mod, @@ -126,14 +140,22 @@ int mlx5_set_msix_vec_count(struct mlx5_core_dev *dev, int function_id, return ret; } -static void irq_release(struct mlx5_irq *irq) +/* mlx5_system_free_irq - Free an IRQ + * @irq: IRQ to free + * + * Free the IRQ and other resources such as rmap from the system. + * BUT doesn't free or remove reference from mlx5. + * This function is very important for the shutdown flow, where we need to + * cleanup system resoruces but keep mlx5 objects alive, + * see mlx5_irq_table_free_irqs(). + */ +static void mlx5_system_free_irq(struct mlx5_irq *irq) { struct mlx5_irq_pool *pool = irq->pool; #ifdef CONFIG_RFS_ACCEL struct cpu_rmap *rmap; #endif - xa_erase(&pool->irqs, irq->pool_index); /* free_irq requires that affinity_hint and rmap will be cleared before * calling it. To satisfy this requirement, we call * irq_cpu_rmap_remove() to remove the notifier @@ -145,10 +167,18 @@ static void irq_release(struct mlx5_irq *irq) irq_cpu_rmap_remove(rmap, irq->map.virq); #endif - free_cpumask_var(irq->mask); free_irq(irq->map.virq, &irq->nh); if (irq->map.index && pci_msix_can_alloc_dyn(pool->dev->pdev)) pci_msix_free_irq(pool->dev->pdev, irq->map); +} + +static void irq_release(struct mlx5_irq *irq) +{ + struct mlx5_irq_pool *pool = irq->pool; + + xa_erase(&pool->irqs, irq->pool_index); + mlx5_system_free_irq(irq); + free_cpumask_var(irq->mask); kfree(irq); } @@ -565,15 +595,21 @@ void mlx5_irqs_release_vectors(struct mlx5_irq **irqs, int nirqs) int mlx5_irqs_request_vectors(struct mlx5_core_dev *dev, u16 *cpus, int nirqs, struct mlx5_irq **irqs, struct cpu_rmap **rmap) { + struct mlx5_irq_table *table = mlx5_irq_table_get(dev); + struct mlx5_irq_pool *pool = table->pcif_pool; struct irq_affinity_desc af_desc; struct mlx5_irq *irq; + int offset = 1; int i; + if (!pool->xa_num_irqs.max) + offset = 0; + af_desc.is_managed = false; for (i = 0; i < nirqs; i++) { cpumask_clear(&af_desc.mask); cpumask_set_cpu(cpus[i], &af_desc.mask); - irq = mlx5_irq_request(dev, i + 1, &af_desc, rmap); + irq = mlx5_irq_request(dev, i + offset, &af_desc, rmap); if (IS_ERR(irq)) break; irqs[i] = irq; @@ -699,7 +735,8 @@ static void mlx5_irq_pool_free_irqs(struct mlx5_irq_pool *pool) unsigned long index; xa_for_each(&pool->irqs, index, irq) - free_irq(irq->map.virq, &irq->nh); + mlx5_system_free_irq(irq); + } static void mlx5_irq_pools_free_irqs(struct mlx5_irq_table *table) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/rdma.c b/drivers/net/ethernet/mellanox/mlx5/core/rdma.c index 540cf05f6373991a2951fdb58988404af67b39e4..a42f6cd99b74482d2ff642795563a18b32e7de33 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/rdma.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/rdma.c @@ -30,9 +30,8 @@ static int mlx5_rdma_enable_roce_steering(struct mlx5_core_dev *dev) struct mlx5_flow_spec *spec; struct mlx5_flow_table *ft; struct mlx5_flow_group *fg; - void *match_criteria; + struct mlx5_eswitch *esw; u32 *flow_group_in; - void *misc; int err; if (!(MLX5_CAP_FLOWTABLE_RDMA_RX(dev, ft_support) && @@ -63,12 +62,8 @@ static int mlx5_rdma_enable_roce_steering(struct mlx5_core_dev *dev) goto free; } - MLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable, - MLX5_MATCH_MISC_PARAMETERS); - match_criteria = MLX5_ADDR_OF(create_flow_group_in, flow_group_in, - match_criteria); - MLX5_SET_TO_ONES(fte_match_param, match_criteria, - misc_parameters.source_port); + esw = dev->priv.eswitch; + mlx5_esw_set_flow_group_source_port(esw, flow_group_in, 0); fg = mlx5_create_flow_group(ft, flow_group_in); if (IS_ERR(fg)) { @@ -77,14 +72,7 @@ static int mlx5_rdma_enable_roce_steering(struct mlx5_core_dev *dev) goto destroy_flow_table; } - spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS; - misc = MLX5_ADDR_OF(fte_match_param, spec->match_value, - misc_parameters); - MLX5_SET(fte_match_set_misc, misc, source_port, - dev->priv.eswitch->manager_vport); - misc = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, - misc_parameters); - MLX5_SET_TO_ONES(fte_match_set_misc, misc, source_port); + mlx5_esw_set_spec_source_port(esw, esw->manager_vport, spec); flow_act.action = MLX5_FLOW_CONTEXT_ACTION_ALLOW; flow_rule = mlx5_add_flow_rules(ft, spec, &flow_act, NULL, 0); @@ -115,7 +103,7 @@ static int mlx5_rdma_enable_roce_steering(struct mlx5_core_dev *dev) static void mlx5_rdma_del_roce_addr(struct mlx5_core_dev *dev) { - mlx5_core_roce_gid_set(dev, 0, 0, 0, + mlx5_core_roce_gid_set(dev, 0, MLX5_ROCE_VERSION_2, 0, NULL, NULL, false, 0, 1); } @@ -135,7 +123,7 @@ static int mlx5_rdma_add_roce_addr(struct mlx5_core_dev *dev) mlx5_rdma_make_default_gid(dev, &gid); return mlx5_core_roce_gid_set(dev, 0, - MLX5_ROCE_VERSION_1, + MLX5_ROCE_VERSION_2, 0, gid.raw, mac, false, 0, 1); } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/driver.c b/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/driver.c index 0692363cf80e4d8f2d31e4133faab797a03abf10..8fe82f1191bb92694f96c1d1742f393405b43904 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/driver.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/driver.c @@ -3,6 +3,7 @@ #include #include +#include #include "mlx5_core.h" #include "dev.h" #include "devlink.h" @@ -28,6 +29,10 @@ static int mlx5_sf_dev_probe(struct auxiliary_device *adev, const struct auxilia mdev->priv.adev_idx = adev->id; sf_dev->mdev = mdev; + /* Only local SFs do light probe */ + if (MLX5_ESWITCH_MANAGER(sf_dev->parent_mdev)) + mlx5_dev_set_lightweight(mdev); + err = mlx5_mdev_init(mdev, MLX5_SF_PROF); if (err) { mlx5_core_warn(mdev, "mlx5_mdev_init on err=%d\n", err); @@ -41,7 +46,10 @@ static int mlx5_sf_dev_probe(struct auxiliary_device *adev, const struct auxilia goto remap_err; } - err = mlx5_init_one(mdev); + if (MLX5_ESWITCH_MANAGER(sf_dev->parent_mdev)) + err = mlx5_init_one_light(mdev); + else + err = mlx5_init_one(mdev); if (err) { mlx5_core_warn(mdev, "mlx5_init_one err=%d\n", err); goto init_one_err; @@ -65,7 +73,10 @@ static void mlx5_sf_dev_remove(struct auxiliary_device *adev) mlx5_drain_health_wq(sf_dev->mdev); devlink_unregister(devlink); - mlx5_uninit_one(sf_dev->mdev); + if (mlx5_dev_is_lightweight(sf_dev->mdev)) + mlx5_uninit_one_light(sf_dev->mdev); + else + mlx5_uninit_one(sf_dev->mdev); iounmap(sf_dev->mdev->iseg); mlx5_mdev_uninit(sf_dev->mdev); mlx5_devlink_free(devlink); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/sf/devlink.c b/drivers/net/ethernet/mellanox/mlx5/core/sf/devlink.c index 7d955a4d9f1452564b42a02121fd418a19ad7aa3..6a3fa30b2bf20eebc55433369bff8d27deb636a2 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/sf/devlink.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/sf/devlink.c @@ -28,7 +28,6 @@ struct mlx5_sf_table { struct mutex sf_state_lock; /* Serializes sf state among user cmds & vhca event handler. */ struct notifier_block esw_nb; struct notifier_block vhca_nb; - u8 ecpu: 1; }; static struct mlx5_sf * @@ -283,7 +282,7 @@ int mlx5_devlink_sf_port_fn_state_set(struct devlink_port *dl_port, static int mlx5_sf_add(struct mlx5_core_dev *dev, struct mlx5_sf_table *table, const struct devlink_port_new_attrs *new_attr, struct netlink_ext_ack *extack, - unsigned int *new_port_index) + struct devlink_port **dl_port) { struct mlx5_eswitch *esw = dev->priv.eswitch; struct mlx5_sf *sf; @@ -297,7 +296,7 @@ static int mlx5_sf_add(struct mlx5_core_dev *dev, struct mlx5_sf_table *table, new_attr->controller, new_attr->sfnum); if (err) goto esw_err; - *new_port_index = sf->port_index; + *dl_port = &sf->dl_port; trace_mlx5_sf_add(dev, sf->port_index, sf->controller, sf->hw_fn_id, new_attr->sfnum); return 0; @@ -339,7 +338,7 @@ mlx5_sf_new_check_attr(struct mlx5_core_dev *dev, const struct devlink_port_new_ int mlx5_devlink_sf_port_new(struct devlink *devlink, const struct devlink_port_new_attrs *new_attr, struct netlink_ext_ack *extack, - unsigned int *new_port_index) + struct devlink_port **dl_port) { struct mlx5_core_dev *dev = devlink_priv(devlink); struct mlx5_sf_table *table; @@ -355,7 +354,7 @@ int mlx5_devlink_sf_port_new(struct devlink *devlink, "Port add is only supported in eswitch switchdev mode or SF ports are disabled."); return -EOPNOTSUPP; } - err = mlx5_sf_add(dev, table, new_attr, extack, new_port_index); + err = mlx5_sf_add(dev, table, new_attr, extack, dl_port); mlx5_sf_table_put(table); return err; } @@ -379,7 +378,8 @@ static void mlx5_sf_dealloc(struct mlx5_sf_table *table, struct mlx5_sf *sf) } } -int mlx5_devlink_sf_port_del(struct devlink *devlink, unsigned int port_index, +int mlx5_devlink_sf_port_del(struct devlink *devlink, + struct devlink_port *dl_port, struct netlink_ext_ack *extack) { struct mlx5_core_dev *dev = devlink_priv(devlink); @@ -394,7 +394,7 @@ int mlx5_devlink_sf_port_del(struct devlink *devlink, unsigned int port_index, "Port del is only supported in eswitch switchdev mode or SF ports are disabled."); return -EOPNOTSUPP; } - sf = mlx5_sf_lookup_by_index(table, port_index); + sf = mlx5_sf_lookup_by_index(table, dl_port->index); if (!sf) { err = -ENODEV; goto sf_err; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/sf/sf.h b/drivers/net/ethernet/mellanox/mlx5/core/sf/sf.h index 3a480e06ecc0172d81e6b816a551f6e82a302269..860f9ddb7107b858bc8b67904826cdd52b7aa4ba 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/sf/sf.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/sf/sf.h @@ -21,8 +21,9 @@ void mlx5_sf_table_cleanup(struct mlx5_core_dev *dev); int mlx5_devlink_sf_port_new(struct devlink *devlink, const struct devlink_port_new_attrs *add_attr, struct netlink_ext_ack *extack, - unsigned int *new_port_index); -int mlx5_devlink_sf_port_del(struct devlink *devlink, unsigned int port_index, + struct devlink_port **dl_port); +int mlx5_devlink_sf_port_del(struct devlink *devlink, + struct devlink_port *dl_port, struct netlink_ext_ack *extack); int mlx5_devlink_sf_port_fn_state_get(struct devlink_port *dl_port, enum devlink_port_fn_state *state, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/sriov.c b/drivers/net/ethernet/mellanox/mlx5/core/sriov.c index 20d7662c10fb6bb96652d4212914befbe03aa551..4e42a3b9b8eecb4f9f0786c19d69c8e459754661 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/sriov.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/sriov.c @@ -37,7 +37,7 @@ #include "mlx5_irq.h" #include "eswitch.h" -static int sriov_restore_guids(struct mlx5_core_dev *dev, int vf) +static int sriov_restore_guids(struct mlx5_core_dev *dev, int vf, u16 func_id) { struct mlx5_core_sriov *sriov = &dev->priv.sriov; struct mlx5_hca_vport_context *in; @@ -59,7 +59,7 @@ static int sriov_restore_guids(struct mlx5_core_dev *dev, int vf) !!(in->node_guid) * MLX5_HCA_VPORT_SEL_NODE_GUID | !!(in->policy) * MLX5_HCA_VPORT_SEL_STATE_POLICY; - err = mlx5_core_modify_hca_vport_context(dev, 1, 1, vf + 1, in); + err = mlx5_core_modify_hca_vport_context(dev, 1, 1, func_id, in); if (err) mlx5_core_warn(dev, "modify vport context failed, unable to restore VF %d settings\n", vf); @@ -73,9 +73,7 @@ static int mlx5_device_enable_sriov(struct mlx5_core_dev *dev, int num_vfs) { struct mlx5_core_sriov *sriov = &dev->priv.sriov; int err, vf, num_msix_count; - - if (!MLX5_ESWITCH_MANAGER(dev)) - goto enable_vfs_hca; + int vport_num; err = mlx5_eswitch_enable(dev->priv.eswitch, num_vfs); if (err) { @@ -84,7 +82,6 @@ static int mlx5_device_enable_sriov(struct mlx5_core_dev *dev, int num_vfs) return err; } -enable_vfs_hca: num_msix_count = mlx5_get_default_msix_vec_count(dev, num_vfs); for (vf = 0; vf < num_vfs; vf++) { /* Notify the VF before its enablement to let it set @@ -108,7 +105,10 @@ static int mlx5_device_enable_sriov(struct mlx5_core_dev *dev, int num_vfs) sriov->vfs_ctx[vf].enabled = 1; if (MLX5_CAP_GEN(dev, port_type) == MLX5_CAP_PORT_TYPE_IB) { - err = sriov_restore_guids(dev, vf); + vport_num = mlx5_core_ec_sriov_enabled(dev) ? + mlx5_core_ec_vf_vport_base(dev) + vf + : vf + 1; + err = sriov_restore_guids(dev, vf, vport_num); if (err) { mlx5_core_warn(dev, "failed to restore VF %d settings, err %d\n", @@ -123,9 +123,11 @@ static int mlx5_device_enable_sriov(struct mlx5_core_dev *dev, int num_vfs) } static void -mlx5_device_disable_sriov(struct mlx5_core_dev *dev, int num_vfs, bool clear_vf) +mlx5_device_disable_sriov(struct mlx5_core_dev *dev, int num_vfs, bool clear_vf, bool num_vf_change) { struct mlx5_core_sriov *sriov = &dev->priv.sriov; + bool wait_for_ec_vf_pages = true; + bool wait_for_vf_pages = true; int err; int vf; @@ -147,11 +149,30 @@ mlx5_device_disable_sriov(struct mlx5_core_dev *dev, int num_vfs, bool clear_vf) mlx5_eswitch_disable_sriov(dev->priv.eswitch, clear_vf); + /* There are a number of scenarios when SRIOV is being disabled: + * 1. VFs or ECVFs had been created, and now set back to 0 (num_vf_change == true). + * - If EC SRIOV is enabled then this flow is happening on the + * embedded platform, wait for only EC VF pages. + * - If EC SRIOV is not enabled this flow is happening on non-embedded + * platform, wait for the VF pages. + * + * 2. The driver is being unloaded. In this case wait for all pages. + */ + if (num_vf_change) { + if (mlx5_core_ec_sriov_enabled(dev)) + wait_for_vf_pages = false; + else + wait_for_ec_vf_pages = false; + } + + if (wait_for_ec_vf_pages && mlx5_wait_for_pages(dev, &dev->priv.page_counters[MLX5_EC_VF])) + mlx5_core_warn(dev, "timeout reclaiming EC VFs pages\n"); + /* For ECPFs, skip waiting for host VF pages until ECPF is destroyed */ if (mlx5_core_is_ecpf(dev)) return; - if (mlx5_wait_for_pages(dev, &dev->priv.page_counters[MLX5_VF])) + if (wait_for_vf_pages && mlx5_wait_for_pages(dev, &dev->priv.page_counters[MLX5_VF])) mlx5_core_warn(dev, "timeout reclaiming VFs pages\n"); } @@ -172,12 +193,12 @@ static int mlx5_sriov_enable(struct pci_dev *pdev, int num_vfs) err = pci_enable_sriov(pdev, num_vfs); if (err) { mlx5_core_warn(dev, "pci_enable_sriov failed : %d\n", err); - mlx5_device_disable_sriov(dev, num_vfs, true); + mlx5_device_disable_sriov(dev, num_vfs, true, true); } return err; } -void mlx5_sriov_disable(struct pci_dev *pdev) +void mlx5_sriov_disable(struct pci_dev *pdev, bool num_vf_change) { struct mlx5_core_dev *dev = pci_get_drvdata(pdev); struct devlink *devlink = priv_to_devlink(dev); @@ -185,7 +206,7 @@ void mlx5_sriov_disable(struct pci_dev *pdev) pci_disable_sriov(pdev); devl_lock(devlink); - mlx5_device_disable_sriov(dev, num_vfs, true); + mlx5_device_disable_sriov(dev, num_vfs, true, num_vf_change); devl_unlock(devlink); } @@ -200,7 +221,7 @@ int mlx5_core_sriov_configure(struct pci_dev *pdev, int num_vfs) if (num_vfs) err = mlx5_sriov_enable(pdev, num_vfs); else - mlx5_sriov_disable(pdev); + mlx5_sriov_disable(pdev, true); if (!err) sriov->num_vfs = num_vfs; @@ -245,7 +266,7 @@ void mlx5_sriov_detach(struct mlx5_core_dev *dev) if (!mlx5_core_is_pf(dev)) return; - mlx5_device_disable_sriov(dev, pci_num_vf(dev->pdev), false); + mlx5_device_disable_sriov(dev, pci_num_vf(dev->pdev), false, false); } static u16 mlx5_get_max_vfs(struct mlx5_core_dev *dev) @@ -284,6 +305,7 @@ int mlx5_sriov_init(struct mlx5_core_dev *dev) total_vfs = pci_sriov_get_totalvfs(pdev); sriov->max_vfs = mlx5_get_max_vfs(dev); sriov->num_vfs = pci_num_vf(pdev); + sriov->max_ec_vfs = mlx5_core_ec_sriov_enabled(dev) ? pci_sriov_get_totalvfs(dev->pdev) : 0; sriov->vfs_ctx = kcalloc(total_vfs, sizeof(*sriov->vfs_ctx), GFP_KERNEL); if (!sriov->vfs_ctx) return -ENOMEM; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_action.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_action.c index 0eb9a8d7f282fc93e99ab4598a52b950d877f6d0..e739ec6cdf901a7686f451d266e3d1470eabd27e 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_action.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_action.c @@ -1421,9 +1421,13 @@ dr_action_create_reformat_action(struct mlx5dr_domain *dmn, } case DR_ACTION_TYP_TNL_L3_TO_L2: { - u8 hw_actions[DR_ACTION_CACHE_LINE_SIZE] = {}; + u8 *hw_actions; int ret; + hw_actions = kzalloc(DR_ACTION_CACHE_LINE_SIZE, GFP_KERNEL); + if (!hw_actions) + return -ENOMEM; + ret = mlx5dr_ste_set_action_decap_l3_list(dmn->ste_ctx, data, data_sz, hw_actions, @@ -1431,6 +1435,7 @@ dr_action_create_reformat_action(struct mlx5dr_domain *dmn, &action->rewrite->num_of_actions); if (ret) { mlx5dr_dbg(dmn, "Failed creating decap l3 action list\n"); + kfree(hw_actions); return ret; } @@ -1440,6 +1445,7 @@ dr_action_create_reformat_action(struct mlx5dr_domain *dmn, ret = mlx5dr_ste_alloc_modify_hdr(action); if (ret) { mlx5dr_dbg(dmn, "Failed preparing reformat data\n"); + kfree(hw_actions); return ret; } return 0; @@ -2071,8 +2077,9 @@ mlx5dr_action_create_dest_vport(struct mlx5dr_domain *dmn, struct mlx5dr_action *action; u8 peer_vport; - peer_vport = vhca_id_valid && (vhca_id != dmn->info.caps.gvmi); - vport_dmn = peer_vport ? dmn->peer_dmn : dmn; + peer_vport = vhca_id_valid && mlx5_core_is_pf(dmn->mdev) && + (vhca_id != dmn->info.caps.gvmi); + vport_dmn = peer_vport ? dmn->peer_dmn[vhca_id] : dmn; if (!vport_dmn) { mlx5dr_dbg(dmn, "No peer vport domain for given vhca_id\n"); return NULL; @@ -2129,6 +2136,11 @@ mlx5dr_action_create_aso(struct mlx5dr_domain *dmn, u32 obj_id, return action; } +u32 mlx5dr_action_get_pkt_reformat_id(struct mlx5dr_action *action) +{ + return action->reformat->id; +} + int mlx5dr_action_destroy(struct mlx5dr_action *action) { if (WARN_ON_ONCE(refcount_read(&action->refcount) > 1)) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_cmd.c index 1aa525e509f109277b03d53c11f51e18886fde95..7491911ebcb50d00f608e046755b3834aa4848b0 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_cmd.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_cmd.c @@ -34,6 +34,7 @@ int mlx5dr_cmd_query_esw_vport_context(struct mlx5_core_dev *mdev, int mlx5dr_cmd_query_gvmi(struct mlx5_core_dev *mdev, bool other_vport, u16 vport_number, u16 *gvmi) { + bool ec_vf_func = other_vport ? mlx5_core_is_ec_vf_vport(mdev, vport_number) : false; u32 in[MLX5_ST_SZ_DW(query_hca_cap_in)] = {}; int out_size; void *out; @@ -46,7 +47,8 @@ int mlx5dr_cmd_query_gvmi(struct mlx5_core_dev *mdev, bool other_vport, MLX5_SET(query_hca_cap_in, in, opcode, MLX5_CMD_OP_QUERY_HCA_CAP); MLX5_SET(query_hca_cap_in, in, other_function, other_vport); - MLX5_SET(query_hca_cap_in, in, function_id, vport_number); + MLX5_SET(query_hca_cap_in, in, function_id, mlx5_vport_to_func_id(mdev, vport_number, ec_vf_func)); + MLX5_SET(query_hca_cap_in, in, ec_vf_function, ec_vf_func); MLX5_SET(query_hca_cap_in, in, op_mod, MLX5_SET_HCA_CAP_OP_MOD_GENERAL_DEVICE << 1 | HCA_CAP_OPMOD_GET_CUR); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_domain.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_domain.c index 9a2dfe6ebe3188941a273afcc1f90dbe1eb85667..75dc85dc24ef212a34aa02e4173fc25b17b53154 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_domain.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_domain.c @@ -555,17 +555,18 @@ int mlx5dr_domain_destroy(struct mlx5dr_domain *dmn) } void mlx5dr_domain_set_peer(struct mlx5dr_domain *dmn, - struct mlx5dr_domain *peer_dmn) + struct mlx5dr_domain *peer_dmn, + u8 peer_idx) { mlx5dr_domain_lock(dmn); - if (dmn->peer_dmn) - refcount_dec(&dmn->peer_dmn->refcount); + if (dmn->peer_dmn[peer_idx]) + refcount_dec(&dmn->peer_dmn[peer_idx]->refcount); - dmn->peer_dmn = peer_dmn; + dmn->peer_dmn[peer_idx] = peer_dmn; - if (dmn->peer_dmn) - refcount_inc(&dmn->peer_dmn->refcount); + if (dmn->peer_dmn[peer_idx]) + refcount_inc(&dmn->peer_dmn[peer_idx]->refcount); mlx5dr_domain_unlock(dmn); } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste_v0.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste_v0.c index 2010d4ac651909e1ff2d5d8a7ca2a485ae13e50c..69d7a8f3c402e31a942eea82bce6e4deb231d5a0 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste_v0.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste_v0.c @@ -1647,6 +1647,7 @@ dr_ste_v0_build_src_gvmi_qpn_tag(struct mlx5dr_match_param *value, u8 *tag) { struct mlx5dr_match_misc *misc = &value->misc; + int id = misc->source_eswitch_owner_vhca_id; struct mlx5dr_cmd_vport_cap *vport_cap; struct mlx5dr_domain *dmn = sb->dmn; struct mlx5dr_domain *vport_dmn; @@ -1657,11 +1658,11 @@ dr_ste_v0_build_src_gvmi_qpn_tag(struct mlx5dr_match_param *value, if (sb->vhca_id_valid) { /* Find port GVMI based on the eswitch_owner_vhca_id */ - if (misc->source_eswitch_owner_vhca_id == dmn->info.caps.gvmi) + if (id == dmn->info.caps.gvmi) vport_dmn = dmn; - else if (dmn->peer_dmn && (misc->source_eswitch_owner_vhca_id == - dmn->peer_dmn->info.caps.gvmi)) - vport_dmn = dmn->peer_dmn; + else if (id < MLX5_MAX_PORTS && dmn->peer_dmn[id] && + (id == dmn->peer_dmn[id]->info.caps.gvmi)) + vport_dmn = dmn->peer_dmn[id]; else return -EINVAL; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste_v1.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste_v1.c index 4c0704ad166b35a2309508fcdf8ecda3c316e5c9..f4ef0b22b991211c83c8a914fab296ace8355996 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste_v1.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste_v1.c @@ -1979,6 +1979,7 @@ static int dr_ste_v1_build_src_gvmi_qpn_tag(struct mlx5dr_match_param *value, u8 *tag) { struct mlx5dr_match_misc *misc = &value->misc; + int id = misc->source_eswitch_owner_vhca_id; struct mlx5dr_cmd_vport_cap *vport_cap; struct mlx5dr_domain *dmn = sb->dmn; struct mlx5dr_domain *vport_dmn; @@ -1988,11 +1989,11 @@ static int dr_ste_v1_build_src_gvmi_qpn_tag(struct mlx5dr_match_param *value, if (sb->vhca_id_valid) { /* Find port GVMI based on the eswitch_owner_vhca_id */ - if (misc->source_eswitch_owner_vhca_id == dmn->info.caps.gvmi) + if (id == dmn->info.caps.gvmi) vport_dmn = dmn; - else if (dmn->peer_dmn && (misc->source_eswitch_owner_vhca_id == - dmn->peer_dmn->info.caps.gvmi)) - vport_dmn = dmn->peer_dmn; + else if (id < MLX5_MAX_PORTS && dmn->peer_dmn[id] && + (id == dmn->peer_dmn[id]->info.caps.gvmi)) + vport_dmn = dmn->peer_dmn[id]; else return -EINVAL; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_types.h b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_types.h index 678a993ab053d490302ed58a9b0bc449273395e3..1622dbbe6b970d2cb66e53de2857485f6bc78a41 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_types.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_types.h @@ -935,7 +935,7 @@ struct mlx5dr_domain_info { }; struct mlx5dr_domain { - struct mlx5dr_domain *peer_dmn; + struct mlx5dr_domain *peer_dmn[MLX5_MAX_PORTS]; struct mlx5_core_dev *mdev; u32 pdn; struct mlx5_uars_page *uar; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/fs_dr.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/fs_dr.c index 984653756779616de63528501cbdab338c025162..6aac5f006bf8b1ae63a78ef681bc08a2a326c761 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/steering/fs_dr.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/fs_dr.c @@ -331,8 +331,16 @@ static int mlx5_cmd_dr_create_fte(struct mlx5_flow_root_namespace *ns, } if (fte->action.action & MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT) { - bool is_decap = fte->action.pkt_reformat->reformat_type == - MLX5_REFORMAT_TYPE_L3_TUNNEL_TO_L2; + bool is_decap; + + if (fte->action.pkt_reformat->owner == MLX5_FLOW_RESOURCE_OWNER_FW) { + err = -EINVAL; + mlx5dr_err(domain, "FW-owned reformat can't be used in SW rule\n"); + goto free_actions; + } + + is_decap = fte->action.pkt_reformat->reformat_type == + MLX5_REFORMAT_TYPE_L3_TUNNEL_TO_L2; if (is_decap) actions[num_actions++] = @@ -661,6 +669,7 @@ static int mlx5_cmd_dr_packet_reformat_alloc(struct mlx5_flow_root_namespace *ns return -EINVAL; } + pkt_reformat->owner = MLX5_FLOW_RESOURCE_OWNER_SW; pkt_reformat->action.dr_action = action; return 0; @@ -691,6 +700,7 @@ static int mlx5_cmd_dr_modify_header_alloc(struct mlx5_flow_root_namespace *ns, return -EINVAL; } + modify_hdr->owner = MLX5_FLOW_RESOURCE_OWNER_SW; modify_hdr->action.dr_action = action; return 0; @@ -770,14 +780,15 @@ static int mlx5_cmd_dr_update_fte(struct mlx5_flow_root_namespace *ns, } static int mlx5_cmd_dr_set_peer(struct mlx5_flow_root_namespace *ns, - struct mlx5_flow_root_namespace *peer_ns) + struct mlx5_flow_root_namespace *peer_ns, + u8 peer_idx) { struct mlx5dr_domain *peer_domain = NULL; if (peer_ns) peer_domain = peer_ns->fs_dr_domain.dr_domain; mlx5dr_domain_set_peer(ns->fs_dr_domain.dr_domain, - peer_domain); + peer_domain, peer_idx); return 0; } @@ -816,6 +827,19 @@ static u32 mlx5_cmd_dr_get_capabilities(struct mlx5_flow_root_namespace *ns, return steering_caps; } +int mlx5_fs_dr_action_get_pkt_reformat_id(struct mlx5_pkt_reformat *pkt_reformat) +{ + switch (pkt_reformat->reformat_type) { + case MLX5_REFORMAT_TYPE_L2_TO_VXLAN: + case MLX5_REFORMAT_TYPE_L2_TO_NVGRE: + case MLX5_REFORMAT_TYPE_L2_TO_L2_TUNNEL: + case MLX5_REFORMAT_TYPE_L2_TO_L3_TUNNEL: + case MLX5_REFORMAT_TYPE_INSERT_HDR: + return mlx5dr_action_get_pkt_reformat_id(pkt_reformat->action.dr_action); + } + return -EOPNOTSUPP; +} + bool mlx5_fs_dr_is_supported(struct mlx5_core_dev *dev) { return mlx5dr_is_supported(dev); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/fs_dr.h b/drivers/net/ethernet/mellanox/mlx5/core/steering/fs_dr.h index d168622063d559d06b69656190c085411f5f8153..99a3b2eff6b8fdd5c946f71dea7944ea11040777 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/steering/fs_dr.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/fs_dr.h @@ -38,6 +38,8 @@ struct mlx5_fs_dr_table { bool mlx5_fs_dr_is_supported(struct mlx5_core_dev *dev); +int mlx5_fs_dr_action_get_pkt_reformat_id(struct mlx5_pkt_reformat *pkt_reformat); + const struct mlx5_flow_cmds *mlx5_fs_cmd_get_dr_cmds(void); #else @@ -47,6 +49,11 @@ static inline const struct mlx5_flow_cmds *mlx5_fs_cmd_get_dr_cmds(void) return NULL; } +static inline u32 mlx5_fs_dr_action_get_pkt_reformat_id(struct mlx5_pkt_reformat *pkt_reformat) +{ + return 0; +} + static inline bool mlx5_fs_dr_is_supported(struct mlx5_core_dev *dev) { return false; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/mlx5dr.h b/drivers/net/ethernet/mellanox/mlx5/core/steering/mlx5dr.h index 9afd268a257381015d347eae469f5407b1132bfd..24cbb33ecd6c99c117992952ce95899dde208d87 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/steering/mlx5dr.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/mlx5dr.h @@ -48,7 +48,8 @@ int mlx5dr_domain_destroy(struct mlx5dr_domain *domain); int mlx5dr_domain_sync(struct mlx5dr_domain *domain, u32 flags); void mlx5dr_domain_set_peer(struct mlx5dr_domain *dmn, - struct mlx5dr_domain *peer_dmn); + struct mlx5dr_domain *peer_dmn, + u8 peer_idx); struct mlx5dr_table * mlx5dr_table_create(struct mlx5dr_domain *domain, u32 level, u32 flags, @@ -150,6 +151,8 @@ mlx5dr_action_create_dest_match_range(struct mlx5dr_domain *dmn, int mlx5dr_action_destroy(struct mlx5dr_action *action); +u32 mlx5dr_action_get_pkt_reformat_id(struct mlx5dr_action *action); + int mlx5dr_definer_get(struct mlx5dr_domain *dmn, u16 format_id, u8 *dw_selectors, u8 *byte_selectors, u8 *match_mask, u32 *definer_id); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/thermal.c b/drivers/net/ethernet/mellanox/mlx5/core/thermal.c index e47fa6fb836f1cc1ed40da6690943d24551eb4c4..52199d39657ed2caf0e363baf70a574d0994c63d 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/thermal.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/thermal.c @@ -45,7 +45,7 @@ static int mlx5_thermal_get_mtmp_temp(struct mlx5_core_dev *mdev, u32 id, int *p static int mlx5_thermal_get_temp(struct thermal_zone_device *tzdev, int *p_temp) { - struct mlx5_thermal *thermal = tzdev->devdata; + struct mlx5_thermal *thermal = thermal_zone_device_priv(tzdev); struct mlx5_core_dev *mdev = thermal->mdev; int err; @@ -68,30 +68,36 @@ static struct thermal_zone_device_ops mlx5_thermal_ops = { int mlx5_thermal_init(struct mlx5_core_dev *mdev) { + char data[THERMAL_NAME_LENGTH]; struct mlx5_thermal *thermal; - struct thermal_zone_device *tzd; - const char *data = "mlx5"; + int err; - tzd = thermal_zone_get_zone_by_name(data); - if (!IS_ERR(tzd)) + if (!mlx5_core_is_pf(mdev) && !mlx5_core_is_ecpf(mdev)) return 0; + err = snprintf(data, sizeof(data), "mlx5_%s", dev_name(mdev->device)); + if (err < 0 || err >= sizeof(data)) { + mlx5_core_err(mdev, "Failed to setup thermal zone name, %d\n", err); + return -EINVAL; + } + thermal = kzalloc(sizeof(*thermal), GFP_KERNEL); if (!thermal) return -ENOMEM; thermal->mdev = mdev; - thermal->tzdev = thermal_zone_device_register(data, - MLX5_THERMAL_NUM_TRIPS, - MLX5_THERMAL_TRIP_MASK, - thermal, - &mlx5_thermal_ops, - NULL, 0, MLX5_THERMAL_POLL_INT_MSEC); + thermal->tzdev = thermal_zone_device_register_with_trips(data, + NULL, + MLX5_THERMAL_NUM_TRIPS, + MLX5_THERMAL_TRIP_MASK, + thermal, + &mlx5_thermal_ops, + NULL, 0, MLX5_THERMAL_POLL_INT_MSEC); if (IS_ERR(thermal->tzdev)) { - dev_err(mdev->device, "Failed to register thermal zone device (%s) %ld\n", - data, PTR_ERR(thermal->tzdev)); + err = PTR_ERR(thermal->tzdev); + mlx5_core_err(mdev, "Failed to register thermal zone device (%s) %d\n", data, err); kfree(thermal); - return -EINVAL; + return err; } mdev->thermal = thermal; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/vport.c b/drivers/net/ethernet/mellanox/mlx5/core/vport.c index ba7e3df2241394e98331481c23fd389d4f684541..5a31fb47ffa58bb23c84013b0a1f7f8983a787d4 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/vport.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/vport.c @@ -288,7 +288,8 @@ int mlx5_query_nic_vport_mac_list(struct mlx5_core_dev *dev, MLX5_CMD_OP_QUERY_NIC_VPORT_CONTEXT); MLX5_SET(query_nic_vport_context_in, in, allowed_list_type, list_type); MLX5_SET(query_nic_vport_context_in, in, vport_number, vport); - MLX5_SET(query_nic_vport_context_in, in, other_vport, 1); + if (vport || mlx5_core_is_ecpf(dev)) + MLX5_SET(query_nic_vport_context_in, in, other_vport, 1); err = mlx5_cmd_exec(dev, in, sizeof(in), out, out_sz); if (err) @@ -1160,23 +1161,26 @@ u64 mlx5_query_nic_system_image_guid(struct mlx5_core_dev *mdev) } EXPORT_SYMBOL_GPL(mlx5_query_nic_system_image_guid); -int mlx5_vport_get_other_func_cap(struct mlx5_core_dev *dev, u16 function_id, void *out, +int mlx5_vport_get_other_func_cap(struct mlx5_core_dev *dev, u16 vport, void *out, u16 opmod) { + bool ec_vf_func = mlx5_core_is_ec_vf_vport(dev, vport); u8 in[MLX5_ST_SZ_BYTES(query_hca_cap_in)] = {}; opmod = (opmod << 1) | (HCA_CAP_OPMOD_GET_MAX & 0x01); MLX5_SET(query_hca_cap_in, in, opcode, MLX5_CMD_OP_QUERY_HCA_CAP); MLX5_SET(query_hca_cap_in, in, op_mod, opmod); - MLX5_SET(query_hca_cap_in, in, function_id, function_id); + MLX5_SET(query_hca_cap_in, in, function_id, mlx5_vport_to_func_id(dev, vport, ec_vf_func)); MLX5_SET(query_hca_cap_in, in, other_function, true); + MLX5_SET(query_hca_cap_in, in, ec_vf_function, ec_vf_func); return mlx5_cmd_exec_inout(dev, query_hca_cap, in, out); } EXPORT_SYMBOL_GPL(mlx5_vport_get_other_func_cap); int mlx5_vport_set_other_func_cap(struct mlx5_core_dev *dev, const void *hca_cap, - u16 function_id, u16 opmod) + u16 vport, u16 opmod) { + bool ec_vf_func = mlx5_core_is_ec_vf_vport(dev, vport); int set_sz = MLX5_ST_SZ_BYTES(set_hca_cap_in); void *set_hca_cap; void *set_ctx; @@ -1190,8 +1194,10 @@ int mlx5_vport_set_other_func_cap(struct mlx5_core_dev *dev, const void *hca_cap MLX5_SET(set_hca_cap_in, set_ctx, op_mod, opmod << 1); set_hca_cap = MLX5_ADDR_OF(set_hca_cap_in, set_ctx, capability); memcpy(set_hca_cap, hca_cap, MLX5_ST_SZ_BYTES(cmd_hca_cap)); - MLX5_SET(set_hca_cap_in, set_ctx, function_id, function_id); + MLX5_SET(set_hca_cap_in, set_ctx, function_id, + mlx5_vport_to_func_id(dev, vport, ec_vf_func)); MLX5_SET(set_hca_cap_in, set_ctx, other_function, true); + MLX5_SET(set_hca_cap_in, set_ctx, ec_vf_function, ec_vf_func); ret = mlx5_cmd_exec_in(dev, set_hca_cap, set_ctx); kfree(set_ctx); diff --git a/drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2_format.h b/drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2_format.h index b001e525809111b09df39e0801c7c488333c4be9..47f6cc0401c398ecd319794a6933fda010881d3f 100644 --- a/drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2_format.h +++ b/drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2_format.h @@ -44,7 +44,7 @@ MLXFW_MFA2_TLV(multi, struct mlxfw_mfa2_tlv_multi, MLXFW_MFA2_TLV_MULTI_PART); struct mlxfw_mfa2_tlv_psid { - u8 psid[0]; + DECLARE_FLEX_ARRAY(u8, psid); } __packed; MLXFW_MFA2_TLV_VARSIZE(psid, struct mlxfw_mfa2_tlv_psid, diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.c b/drivers/net/ethernet/mellanox/mlxsw/core.c index 22db0bb15c4539dba4b77835721cf0dbb892485f..1ccf3b73ed7245701169e1acc55621e533387d79 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core.c @@ -1723,8 +1723,6 @@ static const struct devlink_ops mlxsw_devlink_ops = { BIT(DEVLINK_RELOAD_ACTION_FW_ACTIVATE), .reload_down = mlxsw_devlink_core_bus_device_reload_down, .reload_up = mlxsw_devlink_core_bus_device_reload_up, - .port_split = mlxsw_devlink_port_split, - .port_unsplit = mlxsw_devlink_port_unsplit, .sb_pool_get = mlxsw_devlink_sb_pool_get, .sb_pool_set = mlxsw_devlink_sb_pool_set, .sb_port_pool_get = mlxsw_devlink_sb_port_pool_get, @@ -3116,6 +3114,11 @@ u64 mlxsw_core_res_get(struct mlxsw_core *mlxsw_core, } EXPORT_SYMBOL(mlxsw_core_res_get); +static const struct devlink_port_ops mlxsw_devlink_port_ops = { + .port_split = mlxsw_devlink_port_split, + .port_unsplit = mlxsw_devlink_port_unsplit, +}; + static int __mlxsw_core_port_init(struct mlxsw_core *mlxsw_core, u16 local_port, enum devlink_port_flavour flavour, u8 slot_index, u32 port_number, bool split, @@ -3150,7 +3153,8 @@ static int __mlxsw_core_port_init(struct mlxsw_core *mlxsw_core, u16 local_port, devlink_port_linecard_set(devlink_port, linecard->devlink_linecard); } - err = devl_port_register(devlink, devlink_port, local_port); + err = devl_port_register_with_ops(devlink, devlink_port, local_port, + &mlxsw_devlink_port_ops); if (err) memset(mlxsw_core_port, 0, sizeof(*mlxsw_core_port)); return err; diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.c b/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.c index bd1a51a0a54085c6e6db59203fbb3318208caabd..f0b2963ebac32b569164077464f32c00fec6b4ad 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.c @@ -42,6 +42,7 @@ static const struct mlxsw_afk_element_info mlxsw_afk_element_infos[] = { MLXSW_AFK_ELEMENT_INFO_BUF(DST_IP_64_95, 0x34, 4), MLXSW_AFK_ELEMENT_INFO_BUF(DST_IP_32_63, 0x38, 4), MLXSW_AFK_ELEMENT_INFO_BUF(DST_IP_0_31, 0x3C, 4), + MLXSW_AFK_ELEMENT_INFO_U32(FDB_MISS, 0x40, 0, 1), }; struct mlxsw_afk { diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.h b/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.h index 3a037fe47211ddf44214be0bf146ff87a03f7342..65a4abadc7dbb61426896c850de5b45d2d2116c7 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.h +++ b/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.h @@ -35,6 +35,7 @@ enum mlxsw_afk_element { MLXSW_AFK_ELEMENT_IP_DSCP, MLXSW_AFK_ELEMENT_VIRT_ROUTER_MSB, MLXSW_AFK_ELEMENT_VIRT_ROUTER_LSB, + MLXSW_AFK_ELEMENT_FDB_MISS, MLXSW_AFK_ELEMENT_MAX, }; @@ -69,7 +70,7 @@ struct mlxsw_afk_element_info { MLXSW_AFK_ELEMENT_INFO(MLXSW_AFK_ELEMENT_TYPE_BUF, \ _element, _offset, 0, _size) -#define MLXSW_AFK_ELEMENT_STORAGE_SIZE 0x40 +#define MLXSW_AFK_ELEMENT_STORAGE_SIZE 0x44 struct mlxsw_afk_element_inst { /* element instance in actual block */ enum mlxsw_afk_element element; diff --git a/drivers/net/ethernet/mellanox/mlxsw/i2c.c b/drivers/net/ethernet/mellanox/mlxsw/i2c.c index 2c586c2308aef12eefcee4f0a39a9578ab978546..41298835a11e1673221fdda27dab5fb650ce6cd7 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/i2c.c +++ b/drivers/net/ethernet/mellanox/mlxsw/i2c.c @@ -751,7 +751,7 @@ static void mlxsw_i2c_remove(struct i2c_client *client) int mlxsw_i2c_driver_register(struct i2c_driver *i2c_driver) { - i2c_driver->probe_new = mlxsw_i2c_probe; + i2c_driver->probe = mlxsw_i2c_probe; i2c_driver->remove = mlxsw_i2c_remove; return i2c_add_driver(i2c_driver); } diff --git a/drivers/net/ethernet/mellanox/mlxsw/minimal.c b/drivers/net/ethernet/mellanox/mlxsw/minimal.c index 6b56eadd736e5783343e9cd0b7a2edd71709d38f..6b98c3287b4976f01a4232dbaa3f7382ea89eca5 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/minimal.c +++ b/drivers/net/ethernet/mellanox/mlxsw/minimal.c @@ -417,6 +417,7 @@ static int mlxsw_m_linecards_init(struct mlxsw_m *mlxsw_m) err_kmalloc_array: for (i--; i >= 0; i--) kfree(mlxsw_m->line_cards[i]); + kfree(mlxsw_m->line_cards); err_kcalloc: kfree(mlxsw_m->ports); return err; diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index 02a327744a61b6c84319b7d79804966e612e7dcc..25a01dafde1ba9c43e1371f112a032eb88746366 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -4337,8 +4337,8 @@ static int mlxsw_sp_port_lag_join(struct mlxsw_sp_port *mlxsw_sp_port, mlxsw_sp_port_vlan_router_leave(mlxsw_sp_port->default_vlan); /* Join a router interface configured on the LAG, if exists */ - err = mlxsw_sp_port_vlan_router_join(mlxsw_sp_port->default_vlan, - lag_dev, extack); + err = mlxsw_sp_router_port_join_lag(mlxsw_sp_port, lag_dev, + extack); if (err) goto err_router_join; @@ -5139,14 +5139,6 @@ static int mlxsw_sp_netdevice_event(struct notifier_block *nb, return notifier_from_errno(err); } -static struct notifier_block mlxsw_sp_inetaddr_valid_nb __read_mostly = { - .notifier_call = mlxsw_sp_inetaddr_valid_event, -}; - -static struct notifier_block mlxsw_sp_inet6addr_valid_nb __read_mostly = { - .notifier_call = mlxsw_sp_inet6addr_valid_event, -}; - static const struct pci_device_id mlxsw_sp1_pci_id_table[] = { {PCI_VDEVICE(MELLANOX, PCI_DEVICE_ID_MELLANOX_SPECTRUM), 0}, {0, }, @@ -5191,12 +5183,9 @@ static int __init mlxsw_sp_module_init(void) { int err; - register_inetaddr_validator_notifier(&mlxsw_sp_inetaddr_valid_nb); - register_inet6addr_validator_notifier(&mlxsw_sp_inet6addr_valid_nb); - err = mlxsw_core_driver_register(&mlxsw_sp1_driver); if (err) - goto err_sp1_core_driver_register; + return err; err = mlxsw_core_driver_register(&mlxsw_sp2_driver); if (err) @@ -5242,9 +5231,6 @@ static int __init mlxsw_sp_module_init(void) mlxsw_core_driver_unregister(&mlxsw_sp2_driver); err_sp2_core_driver_register: mlxsw_core_driver_unregister(&mlxsw_sp1_driver); -err_sp1_core_driver_register: - unregister_inet6addr_validator_notifier(&mlxsw_sp_inet6addr_valid_nb); - unregister_inetaddr_validator_notifier(&mlxsw_sp_inetaddr_valid_nb); return err; } @@ -5258,8 +5244,6 @@ static void __exit mlxsw_sp_module_exit(void) mlxsw_core_driver_unregister(&mlxsw_sp3_driver); mlxsw_core_driver_unregister(&mlxsw_sp2_driver); mlxsw_core_driver_unregister(&mlxsw_sp1_driver); - unregister_inet6addr_validator_notifier(&mlxsw_sp_inet6addr_valid_nb); - unregister_inetaddr_validator_notifier(&mlxsw_sp_inetaddr_valid_nb); } module_init(mlxsw_sp_module_init); diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h index 4c22f800451434721d73c9c0dcff9d16c2b1d269..231e364cbb7c38a94c0088656007f69254ac401c 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h @@ -755,14 +755,6 @@ int mlxsw_sp_router_init(struct mlxsw_sp *mlxsw_sp, void mlxsw_sp_router_fini(struct mlxsw_sp *mlxsw_sp); void mlxsw_sp_rif_macvlan_del(struct mlxsw_sp *mlxsw_sp, const struct net_device *macvlan_dev); -int mlxsw_sp_inetaddr_valid_event(struct notifier_block *unused, - unsigned long event, void *ptr); -int mlxsw_sp_inet6addr_valid_event(struct notifier_block *unused, - unsigned long event, void *ptr); -int -mlxsw_sp_port_vlan_router_join(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan, - struct net_device *l3_dev, - struct netlink_ext_ack *extack); void mlxsw_sp_port_vlan_router_leave(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan); void mlxsw_sp_rif_destroy_by_dev(struct mlxsw_sp *mlxsw_sp, diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_flex_keys.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_flex_keys.c index 00c32320f8915506ca5408a907f26a1713f47130..4dea39f2b304b91935adccb68b91ff9d7a5256db 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_flex_keys.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_flex_keys.c @@ -123,10 +123,12 @@ const struct mlxsw_afk_ops mlxsw_sp1_afk_ops = { }; static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_mac_0[] = { + MLXSW_AFK_ELEMENT_INST_U32(FDB_MISS, 0x00, 3, 1), MLXSW_AFK_ELEMENT_INST_BUF(DMAC_0_31, 0x04, 4), }; static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_mac_1[] = { + MLXSW_AFK_ELEMENT_INST_U32(FDB_MISS, 0x00, 3, 1), MLXSW_AFK_ELEMENT_INST_BUF(SMAC_0_31, 0x04, 4), }; diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_dpipe.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_dpipe.c index 5416093c0e35805c80f5d0aeb6032fbf181578d0..c8a356accdf8eff67ab7d99f0d7880721dd70aef 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_dpipe.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_dpipe.c @@ -221,7 +221,7 @@ mlxsw_sp_dpipe_table_erif_entries_dump(void *priv, bool counters_enabled, for (; i < rif_count; i++) { struct mlxsw_sp_rif *rif = mlxsw_sp_rif_by_index(mlxsw_sp, i); - if (!rif || !mlxsw_sp_rif_dev(rif)) + if (!rif || !mlxsw_sp_rif_has_dev(rif)) continue; err = mlxsw_sp_erif_entry_get(mlxsw_sp, &entry, rif, counters_enabled); diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c index 594cdcb90b3d03d7ec0b165aa06f8edb4f8d779a..72917f09e806e95d33a4b4288fd14da84c5d0439 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c @@ -281,39 +281,38 @@ static int mlxsw_sp_flower_parse_actions(struct mlxsw_sp *mlxsw_sp, return 0; } -static int mlxsw_sp_flower_parse_meta(struct mlxsw_sp_acl_rule_info *rulei, - struct flow_cls_offload *f, - struct mlxsw_sp_flow_block *block) +static int +mlxsw_sp_flower_parse_meta_iif(struct mlxsw_sp_acl_rule_info *rulei, + const struct mlxsw_sp_flow_block *block, + const struct flow_match_meta *match, + struct netlink_ext_ack *extack) { - struct flow_rule *rule = flow_cls_offload_flow_rule(f); struct mlxsw_sp_port *mlxsw_sp_port; struct net_device *ingress_dev; - struct flow_match_meta match; - if (!flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_META)) + if (!match->mask->ingress_ifindex) return 0; - flow_rule_match_meta(rule, &match); - if (match.mask->ingress_ifindex != 0xFFFFFFFF) { - NL_SET_ERR_MSG_MOD(f->common.extack, "Unsupported ingress ifindex mask"); + if (match->mask->ingress_ifindex != 0xFFFFFFFF) { + NL_SET_ERR_MSG_MOD(extack, "Unsupported ingress ifindex mask"); return -EINVAL; } ingress_dev = __dev_get_by_index(block->net, - match.key->ingress_ifindex); + match->key->ingress_ifindex); if (!ingress_dev) { - NL_SET_ERR_MSG_MOD(f->common.extack, "Can't find specified ingress port to match on"); + NL_SET_ERR_MSG_MOD(extack, "Can't find specified ingress port to match on"); return -EINVAL; } if (!mlxsw_sp_port_dev_check(ingress_dev)) { - NL_SET_ERR_MSG_MOD(f->common.extack, "Can't match on non-mlxsw ingress port"); + NL_SET_ERR_MSG_MOD(extack, "Can't match on non-mlxsw ingress port"); return -EINVAL; } mlxsw_sp_port = netdev_priv(ingress_dev); if (mlxsw_sp_port->mlxsw_sp != block->mlxsw_sp) { - NL_SET_ERR_MSG_MOD(f->common.extack, "Can't match on a port from different device"); + NL_SET_ERR_MSG_MOD(extack, "Can't match on a port from different device"); return -EINVAL; } @@ -321,9 +320,29 @@ static int mlxsw_sp_flower_parse_meta(struct mlxsw_sp_acl_rule_info *rulei, MLXSW_AFK_ELEMENT_SRC_SYS_PORT, mlxsw_sp_port->local_port, 0xFFFFFFFF); + return 0; } +static int mlxsw_sp_flower_parse_meta(struct mlxsw_sp_acl_rule_info *rulei, + struct flow_cls_offload *f, + struct mlxsw_sp_flow_block *block) +{ + struct flow_rule *rule = flow_cls_offload_flow_rule(f); + struct flow_match_meta match; + + if (!flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_META)) + return 0; + + flow_rule_match_meta(rule, &match); + + mlxsw_sp_acl_rulei_keymask_u32(rulei, MLXSW_AFK_ELEMENT_FDB_MISS, + match.key->l2_miss, match.mask->l2_miss); + + return mlxsw_sp_flower_parse_meta_iif(rulei, block, &match, + f->common.extack); +} + static void mlxsw_sp_flower_parse_ipv4(struct mlxsw_sp_acl_rule_info *rulei, struct flow_cls_offload *f) { diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_mr.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_mr.c index 1f6bc0c7e91ddac1243e80d10ee650575980974a..69cd689dbc83e9b2a1508b8d160f07159081c7cc 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_mr.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_mr.c @@ -704,12 +704,12 @@ void mlxsw_sp_mr_vif_del(struct mlxsw_sp_mr_table *mr_table, vifi_t vif_index) static struct mlxsw_sp_mr_vif * mlxsw_sp_mr_dev_vif_lookup(struct mlxsw_sp_mr_table *mr_table, - const struct net_device *dev) + const struct mlxsw_sp_rif *rif) { vifi_t vif_index; for (vif_index = 0; vif_index < MAXVIFS; vif_index++) - if (mr_table->vifs[vif_index].dev == dev) + if (mlxsw_sp_rif_dev_is(rif, mr_table->vifs[vif_index].dev)) return &mr_table->vifs[vif_index]; return NULL; } @@ -717,13 +717,12 @@ mlxsw_sp_mr_dev_vif_lookup(struct mlxsw_sp_mr_table *mr_table, int mlxsw_sp_mr_rif_add(struct mlxsw_sp_mr_table *mr_table, const struct mlxsw_sp_rif *rif) { - const struct net_device *rif_dev = mlxsw_sp_rif_dev(rif); struct mlxsw_sp_mr_vif *mr_vif; - if (!rif_dev) + if (!mlxsw_sp_rif_has_dev(rif)) return 0; - mr_vif = mlxsw_sp_mr_dev_vif_lookup(mr_table, rif_dev); + mr_vif = mlxsw_sp_mr_dev_vif_lookup(mr_table, rif); if (!mr_vif) return 0; return mlxsw_sp_mr_vif_resolve(mr_table, mr_vif->dev, mr_vif, @@ -733,13 +732,12 @@ int mlxsw_sp_mr_rif_add(struct mlxsw_sp_mr_table *mr_table, void mlxsw_sp_mr_rif_del(struct mlxsw_sp_mr_table *mr_table, const struct mlxsw_sp_rif *rif) { - const struct net_device *rif_dev = mlxsw_sp_rif_dev(rif); struct mlxsw_sp_mr_vif *mr_vif; - if (!rif_dev) + if (!mlxsw_sp_rif_has_dev(rif)) return; - mr_vif = mlxsw_sp_mr_dev_vif_lookup(mr_table, rif_dev); + mr_vif = mlxsw_sp_mr_dev_vif_lookup(mr_table, rif); if (!mr_vif) return; mlxsw_sp_mr_vif_unresolve(mr_table, mr_vif->dev, mr_vif); @@ -748,17 +746,16 @@ void mlxsw_sp_mr_rif_del(struct mlxsw_sp_mr_table *mr_table, void mlxsw_sp_mr_rif_mtu_update(struct mlxsw_sp_mr_table *mr_table, const struct mlxsw_sp_rif *rif, int mtu) { - const struct net_device *rif_dev = mlxsw_sp_rif_dev(rif); struct mlxsw_sp *mlxsw_sp = mr_table->mlxsw_sp; struct mlxsw_sp_mr_route_vif_entry *rve; struct mlxsw_sp_mr *mr = mlxsw_sp->mr; struct mlxsw_sp_mr_vif *mr_vif; - if (!rif_dev) + if (!mlxsw_sp_rif_has_dev(rif)) return; /* Search for a VIF that use that RIF */ - mr_vif = mlxsw_sp_mr_dev_vif_lookup(mr_table, rif_dev); + mr_vif = mlxsw_sp_mr_dev_vif_lookup(mr_table, rif); if (!mr_vif) return; diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve_vxlan.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve_vxlan.c index d309b77a01944c00dc0fbad2ec95906b81a63d1d..bb8eeb86edf751713b14b4a1bbcdd53cf0ac325b 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve_vxlan.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve_vxlan.c @@ -11,10 +11,12 @@ #include "spectrum_nve.h" #define MLXSW_SP_NVE_VXLAN_IPV4_SUPPORTED_FLAGS (VXLAN_F_UDP_ZERO_CSUM_TX | \ - VXLAN_F_LEARN) + VXLAN_F_LEARN | \ + VXLAN_F_LOCALBYPASS) #define MLXSW_SP_NVE_VXLAN_IPV6_SUPPORTED_FLAGS (VXLAN_F_IPV6 | \ VXLAN_F_UDP_ZERO_CSUM6_TX | \ - VXLAN_F_UDP_ZERO_CSUM6_RX) + VXLAN_F_UDP_ZERO_CSUM6_RX | \ + VXLAN_F_LOCALBYPASS) static bool mlxsw_sp_nve_vxlan_ipv4_flags_check(const struct vxlan_config *cfg, struct netlink_ext_ack *extack) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c index 4a73e2fe95ef90422ea4bf7efaf7fd05942bd1ac..b32adf277a2274f9b2fe9a08943d06b1ce5acb72 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c @@ -51,10 +51,27 @@ struct mlxsw_sp_vr; struct mlxsw_sp_lpm_tree; struct mlxsw_sp_rif_ops; -struct mlxsw_sp_rif { +struct mlxsw_sp_crif_key { + struct net_device *dev; +}; + +struct mlxsw_sp_crif { + struct mlxsw_sp_crif_key key; + struct rhash_head ht_node; + bool can_destroy; struct list_head nexthop_list; + struct mlxsw_sp_rif *rif; +}; + +static const struct rhashtable_params mlxsw_sp_crif_ht_params = { + .key_offset = offsetof(struct mlxsw_sp_crif, key), + .key_len = sizeof_field(struct mlxsw_sp_crif, key), + .head_offset = offsetof(struct mlxsw_sp_crif, ht_node), +}; + +struct mlxsw_sp_rif { + struct mlxsw_sp_crif *crif; /* NULL for underlay RIF */ struct list_head neigh_list; - struct net_device *dev; /* NULL for underlay RIF */ struct mlxsw_sp_fid *fid; unsigned char addr[ETH_ALEN]; int mtu; @@ -71,6 +88,13 @@ struct mlxsw_sp_rif { bool counter_egress_valid; }; +static struct net_device *mlxsw_sp_rif_dev(const struct mlxsw_sp_rif *rif) +{ + if (!rif->crif) + return NULL; + return rif->crif->key.dev; +} + struct mlxsw_sp_rif_params { struct net_device *dev; union { @@ -96,8 +120,8 @@ struct mlxsw_sp_rif_subport { struct mlxsw_sp_rif_ipip_lb { struct mlxsw_sp_rif common; struct mlxsw_sp_rif_ipip_lb_config lb_config; - u16 ul_vr_id; /* Reserved for Spectrum-2. */ - u16 ul_rif_id; /* Reserved for Spectrum. */ + u16 ul_vr_id; /* Spectrum-1. */ + u16 ul_rif_id; /* Spectrum-2+. */ }; struct mlxsw_sp_rif_params_ipip_lb { @@ -748,10 +772,11 @@ static bool mlxsw_sp_vr_is_used(const struct mlxsw_sp_vr *vr) static struct mlxsw_sp_vr *mlxsw_sp_vr_find_unused(struct mlxsw_sp *mlxsw_sp) { + int max_vrs = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_VRS); struct mlxsw_sp_vr *vr; int i; - for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_VRS); i++) { + for (i = 0; i < max_vrs; i++) { vr = &mlxsw_sp->router->vrs[i]; if (!mlxsw_sp_vr_is_used(vr)) return vr; @@ -792,12 +817,13 @@ static u32 mlxsw_sp_fix_tb_id(u32 tb_id) static struct mlxsw_sp_vr *mlxsw_sp_vr_find(struct mlxsw_sp *mlxsw_sp, u32 tb_id) { + int max_vrs = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_VRS); struct mlxsw_sp_vr *vr; int i; tb_id = mlxsw_sp_fix_tb_id(tb_id); - for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_VRS); i++) { + for (i = 0; i < max_vrs; i++) { vr = &mlxsw_sp->router->vrs[i]; if (mlxsw_sp_vr_is_used(vr) && vr->tb_id == tb_id) return vr; @@ -959,6 +985,7 @@ static int mlxsw_sp_vrs_lpm_tree_replace(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_fib *fib, struct mlxsw_sp_lpm_tree *new_tree) { + int max_vrs = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_VRS); enum mlxsw_sp_l3proto proto = fib->proto; struct mlxsw_sp_lpm_tree *old_tree; u8 old_id, new_id = new_tree->id; @@ -968,7 +995,7 @@ static int mlxsw_sp_vrs_lpm_tree_replace(struct mlxsw_sp *mlxsw_sp, old_tree = mlxsw_sp->router->lpm.proto_trees[proto]; old_id = old_tree->id; - for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_VRS); i++) { + for (i = 0; i < max_vrs; i++) { vr = &mlxsw_sp->router->vrs[i]; if (!mlxsw_sp_vr_lpm_tree_should_replace(vr, proto, old_id)) continue; @@ -1052,6 +1079,61 @@ u32 mlxsw_sp_ipip_dev_ul_tb_id(const struct net_device *ol_dev) return tb_id; } +static void +mlxsw_sp_crif_init(struct mlxsw_sp_crif *crif, struct net_device *dev) +{ + crif->key.dev = dev; + INIT_LIST_HEAD(&crif->nexthop_list); +} + +static struct mlxsw_sp_crif * +mlxsw_sp_crif_alloc(struct net_device *dev) +{ + struct mlxsw_sp_crif *crif; + + crif = kzalloc(sizeof(*crif), GFP_KERNEL); + if (!crif) + return NULL; + + mlxsw_sp_crif_init(crif, dev); + return crif; +} + +static void mlxsw_sp_crif_free(struct mlxsw_sp_crif *crif) +{ + if (WARN_ON(crif->rif)) + return; + + WARN_ON(!list_empty(&crif->nexthop_list)); + kfree(crif); +} + +static int mlxsw_sp_crif_insert(struct mlxsw_sp_router *router, + struct mlxsw_sp_crif *crif) +{ + return rhashtable_insert_fast(&router->crif_ht, &crif->ht_node, + mlxsw_sp_crif_ht_params); +} + +static void mlxsw_sp_crif_remove(struct mlxsw_sp_router *router, + struct mlxsw_sp_crif *crif) +{ + rhashtable_remove_fast(&router->crif_ht, &crif->ht_node, + mlxsw_sp_crif_ht_params); +} + +static struct mlxsw_sp_crif * +mlxsw_sp_crif_lookup(struct mlxsw_sp_router *router, + const struct net_device *dev) +{ + struct mlxsw_sp_crif_key key = { + .dev = (struct net_device *)dev, + }; + + return rhashtable_lookup_fast(&router->crif_ht, &key, + mlxsw_sp_crif_ht_params); +} + static struct mlxsw_sp_rif * mlxsw_sp_rif_create(struct mlxsw_sp *mlxsw_sp, const struct mlxsw_sp_rif_params *params, @@ -1557,6 +1639,7 @@ mlxsw_sp_rif_ipip_lb_op(struct mlxsw_sp_rif_ipip_lb *lb_rif, u16 ul_vr_id, u16 ul_rif_id, bool enable) { struct mlxsw_sp_rif_ipip_lb_config lb_cf = lb_rif->lb_config; + struct net_device *dev = mlxsw_sp_rif_dev(&lb_rif->common); enum mlxsw_reg_ritr_loopback_ipip_options ipip_options; struct mlxsw_sp_rif *rif = &lb_rif->common; struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp; @@ -1569,7 +1652,7 @@ mlxsw_sp_rif_ipip_lb_op(struct mlxsw_sp_rif_ipip_lb *lb_rif, u16 ul_vr_id, case MLXSW_SP_L3_PROTO_IPV4: saddr4 = be32_to_cpu(lb_cf.saddr.addr4); mlxsw_reg_ritr_pack(ritr_pl, enable, MLXSW_REG_RITR_LOOPBACK_IF, - rif->rif_index, rif->vr_id, rif->dev->mtu); + rif->rif_index, rif->vr_id, dev->mtu); mlxsw_reg_ritr_loopback_ipip4_pack(ritr_pl, lb_cf.lb_ipipt, ipip_options, ul_vr_id, ul_rif_id, saddr4, @@ -1579,7 +1662,7 @@ mlxsw_sp_rif_ipip_lb_op(struct mlxsw_sp_rif_ipip_lb *lb_rif, u16 ul_vr_id, case MLXSW_SP_L3_PROTO_IPV6: saddr6 = &lb_cf.saddr.addr6; mlxsw_reg_ritr_pack(ritr_pl, enable, MLXSW_REG_RITR_LOOPBACK_IF, - rif->rif_index, rif->vr_id, rif->dev->mtu); + rif->rif_index, rif->vr_id, dev->mtu); mlxsw_reg_ritr_loopback_ipip6_pack(ritr_pl, lb_cf.lb_ipipt, ipip_options, ul_vr_id, ul_rif_id, saddr6, @@ -1639,9 +1722,29 @@ static void mlxsw_sp_netdevice_ipip_ol_down_event(struct mlxsw_sp *mlxsw_sp, mlxsw_sp_ipip_entry_ol_down_event(mlxsw_sp, ipip_entry); } -static void mlxsw_sp_nexthop_rif_migrate(struct mlxsw_sp *mlxsw_sp, +static void mlxsw_sp_nexthop_rif_update(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_rif *rif); + +static void mlxsw_sp_rif_migrate_destroy(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_rif *old_rif, - struct mlxsw_sp_rif *new_rif); + struct mlxsw_sp_rif *new_rif, + bool migrate_nhs) +{ + struct mlxsw_sp_crif *crif = old_rif->crif; + struct mlxsw_sp_crif mock_crif = {}; + + if (migrate_nhs) + mlxsw_sp_nexthop_rif_update(mlxsw_sp, new_rif); + + /* Plant a mock CRIF so that destroying the old RIF doesn't unoffload + * our nexthops and IPIP tunnels, and doesn't sever the crif->rif link. + */ + mlxsw_sp_crif_init(&mock_crif, crif->key.dev); + old_rif->crif = &mock_crif; + mock_crif.rif = old_rif; + mlxsw_sp_rif_destroy(old_rif); +} + static int mlxsw_sp_ipip_entry_ol_lb_update(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_ipip_entry *ipip_entry, @@ -1659,18 +1762,11 @@ mlxsw_sp_ipip_entry_ol_lb_update(struct mlxsw_sp *mlxsw_sp, return PTR_ERR(new_lb_rif); ipip_entry->ol_lb = new_lb_rif; - if (keep_encap) - mlxsw_sp_nexthop_rif_migrate(mlxsw_sp, &old_lb_rif->common, - &new_lb_rif->common); - - mlxsw_sp_rif_destroy(&old_lb_rif->common); - + mlxsw_sp_rif_migrate_destroy(mlxsw_sp, &old_lb_rif->common, + &new_lb_rif->common, keep_encap); return 0; } -static void mlxsw_sp_nexthop_rif_update(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_rif *rif); - /** * __mlxsw_sp_ipip_entry_update_tunnel - Update offload related to IPIP entry. * @mlxsw_sp: mlxsw_sp. @@ -2329,7 +2425,7 @@ static void mlxsw_sp_router_neigh_ent_ipv4_process(struct mlxsw_sp *mlxsw_sp, } dipn = htonl(dip); - dev = mlxsw_sp->router->rifs[rif]->dev; + dev = mlxsw_sp_rif_dev(mlxsw_sp->router->rifs[rif]); n = neigh_lookup(&arp_tbl, &dipn, dev); if (!n) return; @@ -2357,7 +2453,7 @@ static void mlxsw_sp_router_neigh_ent_ipv6_process(struct mlxsw_sp *mlxsw_sp, return; } - dev = mlxsw_sp->router->rifs[rif]->dev; + dev = mlxsw_sp_rif_dev(mlxsw_sp->router->rifs[rif]); n = neigh_lookup(&nd_tbl, &dip, dev); if (!n) return; @@ -2745,13 +2841,12 @@ static void mlxsw_sp_router_update_priority_work(struct work_struct *work) } static int mlxsw_sp_router_schedule_work(struct net *net, - struct notifier_block *nb, + struct mlxsw_sp_router *router, + struct neighbour *n, void (*cb)(struct work_struct *)) { struct mlxsw_sp_netevent_work *net_work; - struct mlxsw_sp_router *router; - router = container_of(nb, struct mlxsw_sp_router, netevent_nb); if (!net_eq(net, mlxsw_sp_net(router->mlxsw_sp))) return NOTIFY_DONE; @@ -2761,19 +2856,31 @@ static int mlxsw_sp_router_schedule_work(struct net *net, INIT_WORK(&net_work->work, cb); net_work->mlxsw_sp = router->mlxsw_sp; + net_work->n = n; mlxsw_core_schedule_work(&net_work->work); return NOTIFY_DONE; } +static bool mlxsw_sp_dev_lower_is_port(struct net_device *dev) +{ + struct mlxsw_sp_port *mlxsw_sp_port; + + rcu_read_lock(); + mlxsw_sp_port = mlxsw_sp_port_dev_lower_find_rcu(dev); + rcu_read_unlock(); + return !!mlxsw_sp_port; +} + static int mlxsw_sp_router_netevent_event(struct notifier_block *nb, unsigned long event, void *ptr) { - struct mlxsw_sp_netevent_work *net_work; - struct mlxsw_sp_port *mlxsw_sp_port; - struct mlxsw_sp *mlxsw_sp; + struct mlxsw_sp_router *router; unsigned long interval; struct neigh_parms *p; struct neighbour *n; + struct net *net; + + router = container_of(nb, struct mlxsw_sp_router, netevent_nb); switch (event) { case NETEVENT_DELAY_PROBE_TIME_UPDATE: @@ -2787,51 +2894,37 @@ static int mlxsw_sp_router_netevent_event(struct notifier_block *nb, /* We are in atomic context and can't take RTNL mutex, * so use RCU variant to walk the device chain. */ - mlxsw_sp_port = mlxsw_sp_port_lower_dev_hold(p->dev); - if (!mlxsw_sp_port) + if (!mlxsw_sp_dev_lower_is_port(p->dev)) return NOTIFY_DONE; - mlxsw_sp = mlxsw_sp_port->mlxsw_sp; interval = jiffies_to_msecs(NEIGH_VAR(p, DELAY_PROBE_TIME)); - mlxsw_sp->router->neighs_update.interval = interval; - - mlxsw_sp_port_dev_put(mlxsw_sp_port); + router->neighs_update.interval = interval; break; case NETEVENT_NEIGH_UPDATE: n = ptr; + net = neigh_parms_net(n->parms); if (n->tbl->family != AF_INET && n->tbl->family != AF_INET6) return NOTIFY_DONE; - mlxsw_sp_port = mlxsw_sp_port_lower_dev_hold(n->dev); - if (!mlxsw_sp_port) + if (!mlxsw_sp_dev_lower_is_port(n->dev)) return NOTIFY_DONE; - net_work = kzalloc(sizeof(*net_work), GFP_ATOMIC); - if (!net_work) { - mlxsw_sp_port_dev_put(mlxsw_sp_port); - return NOTIFY_BAD; - } - - INIT_WORK(&net_work->work, mlxsw_sp_router_neigh_event_work); - net_work->mlxsw_sp = mlxsw_sp_port->mlxsw_sp; - net_work->n = n; - /* Take a reference to ensure the neighbour won't be * destructed until we drop the reference in delayed * work. */ neigh_clone(n); - mlxsw_core_schedule_work(&net_work->work); - mlxsw_sp_port_dev_put(mlxsw_sp_port); - break; + return mlxsw_sp_router_schedule_work(net, router, n, + mlxsw_sp_router_neigh_event_work); + case NETEVENT_IPV4_MPATH_HASH_UPDATE: case NETEVENT_IPV6_MPATH_HASH_UPDATE: - return mlxsw_sp_router_schedule_work(ptr, nb, + return mlxsw_sp_router_schedule_work(ptr, router, NULL, mlxsw_sp_router_mp_hash_event_work); case NETEVENT_IPV4_FWD_UPDATE_PRIORITY_UPDATE: - return mlxsw_sp_router_schedule_work(ptr, nb, + return mlxsw_sp_router_schedule_work(ptr, router, NULL, mlxsw_sp_router_update_priority_work); } @@ -2902,7 +2995,7 @@ struct mlxsw_sp_nexthop_key { struct mlxsw_sp_nexthop { struct list_head neigh_list_node; /* member of neigh entry list */ - struct list_head rif_list_node; + struct list_head crif_list_node; struct list_head router_list_node; struct mlxsw_sp_nexthop_group_info *nhgi; /* pointer back to the group * this nexthop belongs to @@ -2915,7 +3008,7 @@ struct mlxsw_sp_nexthop { int nh_weight; int norm_nh_weight; int num_adj_entries; - struct mlxsw_sp_rif *rif; + struct mlxsw_sp_crif *crif; u8 should_offload:1, /* set indicates this nexthop should be written * to the adjacency table. */ @@ -2935,6 +3028,14 @@ struct mlxsw_sp_nexthop { bool counter_valid; }; +static struct net_device * +mlxsw_sp_nexthop_dev(const struct mlxsw_sp_nexthop *nh) +{ + if (!nh->crif) + return NULL; + return nh->crif->key.dev; +} + enum mlxsw_sp_nexthop_group_type { MLXSW_SP_NEXTHOP_GROUP_TYPE_IPV4, MLXSW_SP_NEXTHOP_GROUP_TYPE_IPV6, @@ -2952,9 +3053,18 @@ struct mlxsw_sp_nexthop_group_info { is_resilient:1; struct list_head list; /* member in nh_res_grp_list */ struct mlxsw_sp_nexthop nexthops[]; -#define nh_rif nexthops[0].rif }; +static struct mlxsw_sp_rif * +mlxsw_sp_nhgi_rif(const struct mlxsw_sp_nexthop_group_info *nhgi) +{ + struct mlxsw_sp_crif *crif = nhgi->nexthops[0].crif; + + if (!crif) + return NULL; + return crif->rif; +} + struct mlxsw_sp_nexthop_group_vr_key { u16 vr_id; enum mlxsw_sp_l3proto proto; @@ -3076,7 +3186,9 @@ int mlxsw_sp_nexthop_indexes(struct mlxsw_sp_nexthop *nh, u32 *p_adj_index, struct mlxsw_sp_rif *mlxsw_sp_nexthop_rif(struct mlxsw_sp_nexthop *nh) { - return nh->rif; + if (WARN_ON(!nh->crif)) + return NULL; + return nh->crif->rif; } bool mlxsw_sp_nexthop_group_has_ipip(struct mlxsw_sp_nexthop *nh) @@ -3461,11 +3573,12 @@ static int __mlxsw_sp_nexthop_eth_update(struct mlxsw_sp *mlxsw_sp, bool force, char *ratr_pl) { struct mlxsw_sp_neigh_entry *neigh_entry = nh->neigh_entry; + struct mlxsw_sp_rif *rif = mlxsw_sp_nexthop_rif(nh); enum mlxsw_reg_ratr_op op; u16 rif_index; - rif_index = nh->rif ? nh->rif->rif_index : - mlxsw_sp->router->lb_rif_index; + rif_index = rif ? rif->rif_index : + mlxsw_sp->router->lb_crif->rif->rif_index; op = force ? MLXSW_REG_RATR_OP_WRITE_WRITE_ENTRY : MLXSW_REG_RATR_OP_WRITE_WRITE_ENTRY_ON_ACTIVITY; mlxsw_reg_ratr_pack(ratr_pl, op, true, MLXSW_REG_RATR_TYPE_ETHERNET, @@ -4008,16 +4121,18 @@ mlxsw_sp_nexthop_dead_neigh_replace(struct mlxsw_sp *mlxsw_sp, { struct neighbour *n, *old_n = neigh_entry->key.n; struct mlxsw_sp_nexthop *nh; + struct net_device *dev; bool entry_connected; u8 nud_state, dead; int err; nh = list_first_entry(&neigh_entry->nexthop_list, struct mlxsw_sp_nexthop, neigh_list_node); + dev = mlxsw_sp_nexthop_dev(nh); - n = neigh_lookup(nh->neigh_tbl, &nh->gw_addr, nh->rif->dev); + n = neigh_lookup(nh->neigh_tbl, &nh->gw_addr, dev); if (!n) { - n = neigh_create(nh->neigh_tbl, &nh->gw_addr, nh->rif->dev); + n = neigh_create(nh->neigh_tbl, &nh->gw_addr, dev); if (IS_ERR(n)) return PTR_ERR(n); neigh_event_send(n, NULL); @@ -4081,44 +4196,49 @@ mlxsw_sp_nexthop_neigh_update(struct mlxsw_sp *mlxsw_sp, } } -static void mlxsw_sp_nexthop_rif_init(struct mlxsw_sp_nexthop *nh, - struct mlxsw_sp_rif *rif) +static void mlxsw_sp_nexthop_crif_init(struct mlxsw_sp_nexthop *nh, + struct mlxsw_sp_crif *crif) { - if (nh->rif) + if (nh->crif) return; - nh->rif = rif; - list_add(&nh->rif_list_node, &rif->nexthop_list); + nh->crif = crif; + list_add(&nh->crif_list_node, &crif->nexthop_list); } -static void mlxsw_sp_nexthop_rif_fini(struct mlxsw_sp_nexthop *nh) +static void mlxsw_sp_nexthop_crif_fini(struct mlxsw_sp_nexthop *nh) { - if (!nh->rif) + if (!nh->crif) return; - list_del(&nh->rif_list_node); - nh->rif = NULL; + list_del(&nh->crif_list_node); + nh->crif = NULL; } static int mlxsw_sp_nexthop_neigh_init(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_nexthop *nh) { struct mlxsw_sp_neigh_entry *neigh_entry; + struct net_device *dev; struct neighbour *n; u8 nud_state, dead; int err; + if (WARN_ON(!nh->crif->rif)) + return 0; + if (!nh->nhgi->gateway || nh->neigh_entry) return 0; + dev = mlxsw_sp_nexthop_dev(nh); /* Take a reference of neigh here ensuring that neigh would * not be destructed before the nexthop entry is finished. * The reference is taken either in neigh_lookup() or * in neigh_create() in case n is not found. */ - n = neigh_lookup(nh->neigh_tbl, &nh->gw_addr, nh->rif->dev); + n = neigh_lookup(nh->neigh_tbl, &nh->gw_addr, dev); if (!n) { - n = neigh_create(nh->neigh_tbl, &nh->gw_addr, nh->rif->dev); + n = neigh_create(nh->neigh_tbl, &nh->gw_addr, dev); if (IS_ERR(n)) return PTR_ERR(n); neigh_event_send(n, NULL); @@ -4197,15 +4317,20 @@ static void mlxsw_sp_nexthop_ipip_init(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_nexthop *nh, struct mlxsw_sp_ipip_entry *ipip_entry) { + struct mlxsw_sp_crif *crif; bool removing; if (!nh->nhgi->gateway || nh->ipip_entry) return; + crif = mlxsw_sp_crif_lookup(mlxsw_sp->router, ipip_entry->ol_dev); + if (WARN_ON(!crif)) + return; + nh->ipip_entry = ipip_entry; removing = !mlxsw_sp_ipip_netdev_ul_up(ipip_entry->ol_dev); __mlxsw_sp_nexthop_neigh_update(nh, removing); - mlxsw_sp_nexthop_rif_init(nh, &ipip_entry->ol_lb->common); + mlxsw_sp_nexthop_crif_init(nh, crif); } static void mlxsw_sp_nexthop_ipip_fini(struct mlxsw_sp *mlxsw_sp, @@ -4237,7 +4362,7 @@ static int mlxsw_sp_nexthop_type_init(struct mlxsw_sp *mlxsw_sp, { const struct mlxsw_sp_ipip_ops *ipip_ops; struct mlxsw_sp_ipip_entry *ipip_entry; - struct mlxsw_sp_rif *rif; + struct mlxsw_sp_crif *crif; int err; ipip_entry = mlxsw_sp_ipip_entry_find_by_ol_dev(mlxsw_sp, dev); @@ -4251,11 +4376,15 @@ static int mlxsw_sp_nexthop_type_init(struct mlxsw_sp *mlxsw_sp, } nh->type = MLXSW_SP_NEXTHOP_TYPE_ETH; - rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, dev); - if (!rif) + crif = mlxsw_sp_crif_lookup(mlxsw_sp->router, dev); + if (!crif) + return 0; + + mlxsw_sp_nexthop_crif_init(nh, crif); + + if (!crif->rif) return 0; - mlxsw_sp_nexthop_rif_init(nh, rif); err = mlxsw_sp_nexthop_neigh_init(mlxsw_sp, nh); if (err) goto err_neigh_init; @@ -4263,25 +4392,30 @@ static int mlxsw_sp_nexthop_type_init(struct mlxsw_sp *mlxsw_sp, return 0; err_neigh_init: - mlxsw_sp_nexthop_rif_fini(nh); + mlxsw_sp_nexthop_crif_fini(nh); return err; } -static void mlxsw_sp_nexthop_type_fini(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_nexthop *nh) +static void mlxsw_sp_nexthop_type_rif_gone(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_nexthop *nh) { switch (nh->type) { case MLXSW_SP_NEXTHOP_TYPE_ETH: mlxsw_sp_nexthop_neigh_fini(mlxsw_sp, nh); - mlxsw_sp_nexthop_rif_fini(nh); break; case MLXSW_SP_NEXTHOP_TYPE_IPIP: - mlxsw_sp_nexthop_rif_fini(nh); mlxsw_sp_nexthop_ipip_fini(mlxsw_sp, nh); break; } } +static void mlxsw_sp_nexthop_type_fini(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_nexthop *nh) +{ + mlxsw_sp_nexthop_type_rif_gone(mlxsw_sp, nh); + mlxsw_sp_nexthop_crif_fini(nh); +} + static int mlxsw_sp_nexthop4_init(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_nexthop_group *nh_grp, struct mlxsw_sp_nexthop *nh, @@ -4368,16 +4502,17 @@ static void mlxsw_sp_nexthop4_event(struct mlxsw_sp *mlxsw_sp, static void mlxsw_sp_nexthop_rif_update(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_rif *rif) { + struct net_device *dev = mlxsw_sp_rif_dev(rif); struct mlxsw_sp_nexthop *nh; bool removing; - list_for_each_entry(nh, &rif->nexthop_list, rif_list_node) { + list_for_each_entry(nh, &rif->crif->nexthop_list, crif_list_node) { switch (nh->type) { case MLXSW_SP_NEXTHOP_TYPE_ETH: removing = false; break; case MLXSW_SP_NEXTHOP_TYPE_IPIP: - removing = !mlxsw_sp_ipip_netdev_ul_up(rif->dev); + removing = !mlxsw_sp_ipip_netdev_ul_up(dev); break; default: WARN_ON(1); @@ -4389,25 +4524,14 @@ static void mlxsw_sp_nexthop_rif_update(struct mlxsw_sp *mlxsw_sp, } } -static void mlxsw_sp_nexthop_rif_migrate(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_rif *old_rif, - struct mlxsw_sp_rif *new_rif) -{ - struct mlxsw_sp_nexthop *nh; - - list_splice_init(&old_rif->nexthop_list, &new_rif->nexthop_list); - list_for_each_entry(nh, &new_rif->nexthop_list, rif_list_node) - nh->rif = new_rif; - mlxsw_sp_nexthop_rif_update(mlxsw_sp, new_rif); -} - static void mlxsw_sp_nexthop_rif_gone_sync(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_rif *rif) { struct mlxsw_sp_nexthop *nh, *tmp; - list_for_each_entry_safe(nh, tmp, &rif->nexthop_list, rif_list_node) { - mlxsw_sp_nexthop_type_fini(mlxsw_sp, nh); + list_for_each_entry_safe(nh, tmp, &rif->crif->nexthop_list, + crif_list_node) { + mlxsw_sp_nexthop_type_rif_gone(mlxsw_sp, nh); mlxsw_sp_nexthop_group_refresh(mlxsw_sp, nh->nhgi->nh_grp); } } @@ -4427,7 +4551,7 @@ static int mlxsw_sp_adj_trap_entry_init(struct mlxsw_sp *mlxsw_sp) mlxsw_reg_ratr_pack(ratr_pl, MLXSW_REG_RATR_OP_WRITE_WRITE_ENTRY, true, MLXSW_REG_RATR_TYPE_ETHERNET, mlxsw_sp->router->adj_trap_index, - mlxsw_sp->router->lb_rif_index); + mlxsw_sp->router->lb_crif->rif->rif_index); mlxsw_reg_ratr_trap_action_set(ratr_pl, trap_action); mlxsw_reg_ratr_trap_id_set(ratr_pl, MLXSW_TRAP_ID_RTR_EGRESS0); err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ratr), ratr_pl); @@ -4743,21 +4867,19 @@ static bool mlxsw_sp_nexthop_obj_is_gateway(struct mlxsw_sp *mlxsw_sp, static void mlxsw_sp_nexthop_obj_blackhole_init(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_nexthop *nh) { - u16 lb_rif_index = mlxsw_sp->router->lb_rif_index; - nh->action = MLXSW_SP_NEXTHOP_ACTION_DISCARD; nh->should_offload = 1; /* While nexthops that discard packets do not forward packets * via an egress RIF, they still need to be programmed using a * valid RIF, so use the loopback RIF created during init. */ - nh->rif = mlxsw_sp->router->rifs[lb_rif_index]; + nh->crif = mlxsw_sp->router->lb_crif; } static void mlxsw_sp_nexthop_obj_blackhole_fini(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_nexthop *nh) { - nh->rif = NULL; + nh->crif = NULL; nh->should_offload = 0; } @@ -5491,7 +5613,7 @@ mlxsw_sp_fib_entry_should_offload(const struct mlxsw_sp_fib_entry *fib_entry) case MLXSW_SP_FIB_ENTRY_TYPE_REMOTE: return !!nh_group->nhgi->adj_index_valid; case MLXSW_SP_FIB_ENTRY_TYPE_LOCAL: - return !!nh_group->nhgi->nh_rif; + return !!mlxsw_sp_nhgi_rif(nh_group->nhgi); case MLXSW_SP_FIB_ENTRY_TYPE_BLACKHOLE: case MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP: case MLXSW_SP_FIB_ENTRY_TYPE_NVE_DECAP: @@ -5509,9 +5631,10 @@ mlxsw_sp_rt6_nexthop(struct mlxsw_sp_nexthop_group *nh_grp, for (i = 0; i < nh_grp->nhgi->count; i++) { struct mlxsw_sp_nexthop *nh = &nh_grp->nhgi->nexthops[i]; + struct net_device *dev = mlxsw_sp_nexthop_dev(nh); struct fib6_info *rt = mlxsw_sp_rt6->rt; - if (nh->rif && nh->rif->dev == rt->fib6_nh->fib_nh_dev && + if (dev && dev == rt->fib6_nh->fib_nh_dev && ipv6_addr_equal((const struct in6_addr *) &nh->gw_addr, &rt->fib6_nh->fib_nh_gw6)) return nh; @@ -5752,7 +5875,8 @@ static int mlxsw_sp_fib_entry_op_remote(struct mlxsw_sp *mlxsw_sp, trap_action = MLXSW_REG_RALUE_TRAP_ACTION_NOP; adjacency_index = nhgi->adj_index; ecmp_size = nhgi->ecmp_size; - } else if (!nhgi->adj_index_valid && nhgi->count && nhgi->nh_rif) { + } else if (!nhgi->adj_index_valid && nhgi->count && + mlxsw_sp_nhgi_rif(nhgi)) { trap_action = MLXSW_REG_RALUE_TRAP_ACTION_NOP; adjacency_index = mlxsw_sp->router->adj_trap_index; ecmp_size = 1; @@ -5771,7 +5895,7 @@ static int mlxsw_sp_fib_entry_op_local(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_fib_entry *fib_entry, enum mlxsw_reg_ralue_op op) { - struct mlxsw_sp_rif *rif = fib_entry->nh_group->nhgi->nh_rif; + struct mlxsw_sp_rif *rif = mlxsw_sp_nhgi_rif(fib_entry->nh_group->nhgi); enum mlxsw_reg_ralue_trap_action trap_action; char ralue_pl[MLXSW_REG_RALUE_LEN]; u16 trap_id = 0; @@ -7298,9 +7422,10 @@ static void mlxsw_sp_vr_fib_flush(struct mlxsw_sp *mlxsw_sp, static void mlxsw_sp_router_fib_flush(struct mlxsw_sp *mlxsw_sp) { + int max_vrs = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_VRS); int i, j; - for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_VRS); i++) { + for (i = 0; i < max_vrs; i++) { struct mlxsw_sp_vr *vr = &mlxsw_sp->router->vrs[i]; if (!mlxsw_sp_vr_is_used(vr)) @@ -7699,11 +7824,12 @@ static struct mlxsw_sp_rif * mlxsw_sp_rif_find_by_dev(const struct mlxsw_sp *mlxsw_sp, const struct net_device *dev) { + int max_rifs = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS); int i; - for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS); i++) + for (i = 0; i < max_rifs; i++) if (mlxsw_sp->router->rifs[i] && - mlxsw_sp->router->rifs[i]->dev == dev) + mlxsw_sp_rif_dev_is(mlxsw_sp->router->rifs[i], dev)) return mlxsw_sp->router->rifs[i]; return NULL; @@ -7761,33 +7887,52 @@ static int mlxsw_sp_router_rif_disable(struct mlxsw_sp *mlxsw_sp, u16 rif) static void mlxsw_sp_router_rif_gone_sync(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_rif *rif) { + /* Signal to nexthop cleanup that the RIF is going away. */ + rif->crif->rif = NULL; + mlxsw_sp_router_rif_disable(mlxsw_sp, rif->rif_index); mlxsw_sp_nexthop_rif_gone_sync(mlxsw_sp, rif); mlxsw_sp_neigh_rif_gone_sync(mlxsw_sp, rif); } +static bool __mlxsw_sp_dev_addr_list_empty(const struct net_device *dev) +{ + struct inet6_dev *inet6_dev; + struct in_device *idev; + + idev = __in_dev_get_rcu(dev); + if (idev && idev->ifa_list) + return false; + + inet6_dev = __in6_dev_get(dev); + if (inet6_dev && !list_empty(&inet6_dev->addr_list)) + return false; + + return true; +} + +static bool mlxsw_sp_dev_addr_list_empty(const struct net_device *dev) +{ + bool addr_list_empty; + + rcu_read_lock(); + addr_list_empty = __mlxsw_sp_dev_addr_list_empty(dev); + rcu_read_unlock(); + + return addr_list_empty; +} + static bool mlxsw_sp_rif_should_config(struct mlxsw_sp_rif *rif, struct net_device *dev, unsigned long event) { - struct inet6_dev *inet6_dev; - bool addr_list_empty = true; - struct in_device *idev; + bool addr_list_empty; switch (event) { case NETDEV_UP: return rif == NULL; case NETDEV_DOWN: - rcu_read_lock(); - idev = __in_dev_get_rcu(dev); - if (idev && idev->ifa_list) - addr_list_empty = false; - - inet6_dev = __in6_dev_get(dev); - if (addr_list_empty && inet6_dev && - !list_empty(&inet6_dev->addr_list)) - addr_list_empty = false; - rcu_read_unlock(); + addr_list_empty = mlxsw_sp_dev_addr_list_empty(dev); /* macvlans do not have a RIF, but rather piggy back on the * RIF of their lower device. @@ -7796,7 +7941,7 @@ mlxsw_sp_rif_should_config(struct mlxsw_sp_rif *rif, struct net_device *dev, return true; if (rif && addr_list_empty && - !netif_is_l3_slave(rif->dev)) + !netif_is_l3_slave(mlxsw_sp_rif_dev(rif))) return true; /* It is possible we already removed the RIF ourselves * if it was assigned to a netdev that is now a bridge @@ -7854,27 +7999,39 @@ static void mlxsw_sp_rif_index_free(struct mlxsw_sp *mlxsw_sp, u16 rif_index, static struct mlxsw_sp_rif *mlxsw_sp_rif_alloc(size_t rif_size, u16 rif_index, u16 vr_id, - struct net_device *l3_dev) + struct mlxsw_sp_crif *crif) { + struct net_device *l3_dev = crif ? crif->key.dev : NULL; struct mlxsw_sp_rif *rif; rif = kzalloc(rif_size, GFP_KERNEL); if (!rif) return NULL; - INIT_LIST_HEAD(&rif->nexthop_list); INIT_LIST_HEAD(&rif->neigh_list); if (l3_dev) { ether_addr_copy(rif->addr, l3_dev->dev_addr); rif->mtu = l3_dev->mtu; - rif->dev = l3_dev; } rif->vr_id = vr_id; rif->rif_index = rif_index; + if (crif) { + rif->crif = crif; + crif->rif = rif; + } return rif; } +static void mlxsw_sp_rif_free(struct mlxsw_sp_rif *rif) +{ + WARN_ON(!list_empty(&rif->neigh_list)); + + if (rif->crif) + rif->crif->rif = NULL; + kfree(rif); +} + struct mlxsw_sp_rif *mlxsw_sp_rif_by_index(const struct mlxsw_sp *mlxsw_sp, u16 rif_index) { @@ -7893,7 +8050,8 @@ u16 mlxsw_sp_ipip_lb_rif_index(const struct mlxsw_sp_rif_ipip_lb *lb_rif) u16 mlxsw_sp_ipip_lb_ul_vr_id(const struct mlxsw_sp_rif_ipip_lb *lb_rif) { - u32 ul_tb_id = mlxsw_sp_ipip_dev_ul_tb_id(lb_rif->common.dev); + struct net_device *dev = mlxsw_sp_rif_dev(&lb_rif->common); + u32 ul_tb_id = mlxsw_sp_ipip_dev_ul_tb_id(dev); struct mlxsw_sp_vr *ul_vr; ul_vr = mlxsw_sp_vr_get(lb_rif->common.mlxsw_sp, ul_tb_id, NULL); @@ -8070,12 +8228,18 @@ mlxsw_sp_router_hwstats_notify_schedule(struct net_device *dev) int mlxsw_sp_rif_dev_ifindex(const struct mlxsw_sp_rif *rif) { - return rif->dev->ifindex; + return mlxsw_sp_rif_dev(rif)->ifindex; } -const struct net_device *mlxsw_sp_rif_dev(const struct mlxsw_sp_rif *rif) +bool mlxsw_sp_rif_has_dev(const struct mlxsw_sp_rif *rif) +{ + return !!mlxsw_sp_rif_dev(rif); +} + +bool mlxsw_sp_rif_dev_is(const struct mlxsw_sp_rif *rif, + const struct net_device *dev) { - return rif->dev; + return mlxsw_sp_rif_dev(rif) == dev; } static void mlxsw_sp_rif_push_l3_stats(struct mlxsw_sp_rif *rif) @@ -8083,7 +8247,7 @@ static void mlxsw_sp_rif_push_l3_stats(struct mlxsw_sp_rif *rif) struct rtnl_hw_stats64 stats = {}; if (!mlxsw_sp_router_port_l3_stats_fetch(rif, &stats)) - netdev_offload_xstats_push_delta(rif->dev, + netdev_offload_xstats_push_delta(mlxsw_sp_rif_dev(rif), NETDEV_OFFLOAD_XSTATS_TYPE_L3, &stats); } @@ -8098,6 +8262,7 @@ mlxsw_sp_rif_create(struct mlxsw_sp *mlxsw_sp, const struct mlxsw_sp_rif_ops *ops; struct mlxsw_sp_fid *fid = NULL; enum mlxsw_sp_rif_type type; + struct mlxsw_sp_crif *crif; struct mlxsw_sp_rif *rif; struct mlxsw_sp_vr *vr; u16 rif_index; @@ -8117,12 +8282,18 @@ mlxsw_sp_rif_create(struct mlxsw_sp *mlxsw_sp, goto err_rif_index_alloc; } - rif = mlxsw_sp_rif_alloc(ops->rif_size, rif_index, vr->id, params->dev); + crif = mlxsw_sp_crif_lookup(mlxsw_sp->router, params->dev); + if (WARN_ON(!crif)) { + err = -ENOENT; + goto err_crif_lookup; + } + + rif = mlxsw_sp_rif_alloc(ops->rif_size, rif_index, vr->id, crif); if (!rif) { err = -ENOMEM; goto err_rif_alloc; } - dev_hold(rif->dev); + dev_hold(params->dev); mlxsw_sp->router->rifs[rif_index] = rif; rif->mlxsw_sp = mlxsw_sp; rif->ops = ops; @@ -8150,12 +8321,12 @@ mlxsw_sp_rif_create(struct mlxsw_sp *mlxsw_sp, goto err_mr_rif_add; } - if (netdev_offload_xstats_enabled(rif->dev, + if (netdev_offload_xstats_enabled(params->dev, NETDEV_OFFLOAD_XSTATS_TYPE_L3)) { err = mlxsw_sp_router_port_l3_stats_enable(rif); if (err) goto err_stats_enable; - mlxsw_sp_router_hwstats_notify_schedule(rif->dev); + mlxsw_sp_router_hwstats_notify_schedule(params->dev); } else { mlxsw_sp_rif_counters_alloc(rif); } @@ -8173,9 +8344,10 @@ mlxsw_sp_rif_create(struct mlxsw_sp *mlxsw_sp, mlxsw_sp_fid_put(fid); err_fid_get: mlxsw_sp->router->rifs[rif_index] = NULL; - dev_put(rif->dev); - kfree(rif); + dev_put(params->dev); + mlxsw_sp_rif_free(rif); err_rif_alloc: +err_crif_lookup: mlxsw_sp_rif_index_free(mlxsw_sp, rif_index, rif_entries); err_rif_index_alloc: vr->rif_count--; @@ -8185,8 +8357,10 @@ mlxsw_sp_rif_create(struct mlxsw_sp *mlxsw_sp, static void mlxsw_sp_rif_destroy(struct mlxsw_sp_rif *rif) { + struct net_device *dev = mlxsw_sp_rif_dev(rif); const struct mlxsw_sp_rif_ops *ops = rif->ops; struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp; + struct mlxsw_sp_crif *crif = rif->crif; struct mlxsw_sp_fid *fid = rif->fid; u8 rif_entries = rif->rif_entries; u16 rif_index = rif->rif_index; @@ -8197,11 +8371,10 @@ static void mlxsw_sp_rif_destroy(struct mlxsw_sp_rif *rif) mlxsw_sp_router_rif_gone_sync(mlxsw_sp, rif); vr = &mlxsw_sp->router->vrs[rif->vr_id]; - if (netdev_offload_xstats_enabled(rif->dev, - NETDEV_OFFLOAD_XSTATS_TYPE_L3)) { + if (netdev_offload_xstats_enabled(dev, NETDEV_OFFLOAD_XSTATS_TYPE_L3)) { mlxsw_sp_rif_push_l3_stats(rif); mlxsw_sp_router_port_l3_stats_disable(rif); - mlxsw_sp_router_hwstats_notify_schedule(rif->dev); + mlxsw_sp_router_hwstats_notify_schedule(dev); } else { mlxsw_sp_rif_counters_free(rif); } @@ -8213,11 +8386,14 @@ static void mlxsw_sp_rif_destroy(struct mlxsw_sp_rif *rif) /* Loopback RIFs are not associated with a FID. */ mlxsw_sp_fid_put(fid); mlxsw_sp->router->rifs[rif->rif_index] = NULL; - dev_put(rif->dev); - kfree(rif); + dev_put(dev); + mlxsw_sp_rif_free(rif); mlxsw_sp_rif_index_free(mlxsw_sp, rif_index, rif_entries); vr->rif_count--; mlxsw_sp_vr_put(mlxsw_sp, vr); + + if (crif->can_destroy) + mlxsw_sp_crif_free(crif); } void mlxsw_sp_rif_destroy_by_dev(struct mlxsw_sp *mlxsw_sp, @@ -8549,25 +8725,20 @@ __mlxsw_sp_port_vlan_router_leave(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan) mlxsw_sp_rif_subport_put(rif); } -int -mlxsw_sp_port_vlan_router_join(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan, - struct net_device *l3_dev, - struct netlink_ext_ack *extack) +static int +mlxsw_sp_port_vlan_router_join_existing(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan, + struct net_device *l3_dev, + struct netlink_ext_ack *extack) { struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port_vlan->mlxsw_sp_port->mlxsw_sp; - struct mlxsw_sp_rif *rif; - int err = 0; - mutex_lock(&mlxsw_sp->router->lock); - rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, l3_dev); - if (!rif) - goto out; + lockdep_assert_held(&mlxsw_sp->router->lock); - err = __mlxsw_sp_port_vlan_router_join(mlxsw_sp_port_vlan, l3_dev, - extack); -out: - mutex_unlock(&mlxsw_sp->router->lock); - return err; + if (!mlxsw_sp_rif_find_by_dev(mlxsw_sp, l3_dev)) + return 0; + + return __mlxsw_sp_port_vlan_router_join(mlxsw_sp_port_vlan, l3_dev, + extack); } void @@ -8874,8 +9045,8 @@ static int mlxsw_sp_inetaddr_event(struct notifier_block *nb, return notifier_from_errno(err); } -int mlxsw_sp_inetaddr_valid_event(struct notifier_block *unused, - unsigned long event, void *ptr) +static int mlxsw_sp_inetaddr_valid_event(struct notifier_block *unused, + unsigned long event, void *ptr) { struct in_validator_info *ivi = (struct in_validator_info *) ptr; struct net_device *dev = ivi->ivi_dev->dev; @@ -8957,8 +9128,8 @@ static int mlxsw_sp_inet6addr_event(struct notifier_block *nb, return NOTIFY_DONE; } -int mlxsw_sp_inet6addr_valid_event(struct notifier_block *unused, - unsigned long event, void *ptr) +static int mlxsw_sp_inet6addr_valid_event(struct notifier_block *unused, + unsigned long event, void *ptr) { struct in6_validator_info *i6vi = (struct in6_validator_info *) ptr; struct net_device *dev = i6vi->i6vi_dev->dev; @@ -9004,7 +9175,7 @@ mlxsw_sp_router_port_change_event(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_rif *rif, struct netlink_ext_ack *extack) { - struct net_device *dev = rif->dev; + struct net_device *dev = mlxsw_sp_rif_dev(rif); u8 old_mac_profile; u16 fid_index; int err; @@ -9088,6 +9259,104 @@ static int mlxsw_sp_router_port_pre_changeaddr_event(struct mlxsw_sp_rif *rif, return -ENOBUFS; } +static bool mlxsw_sp_router_netdevice_interesting(struct mlxsw_sp *mlxsw_sp, + struct net_device *dev) +{ + struct vlan_dev_priv *vlan; + + if (netif_is_lag_master(dev) || + netif_is_bridge_master(dev) || + mlxsw_sp_port_dev_check(dev) || + mlxsw_sp_netdev_is_ipip_ol(mlxsw_sp, dev) || + netif_is_l3_master(dev)) + return true; + + if (!is_vlan_dev(dev)) + return false; + + vlan = vlan_dev_priv(dev); + return netif_is_lag_master(vlan->real_dev) || + netif_is_bridge_master(vlan->real_dev) || + mlxsw_sp_port_dev_check(vlan->real_dev); +} + +static struct mlxsw_sp_crif * +mlxsw_sp_crif_register(struct mlxsw_sp_router *router, struct net_device *dev) +{ + struct mlxsw_sp_crif *crif; + int err; + + if (WARN_ON(mlxsw_sp_crif_lookup(router, dev))) + return NULL; + + crif = mlxsw_sp_crif_alloc(dev); + if (!crif) + return ERR_PTR(-ENOMEM); + + err = mlxsw_sp_crif_insert(router, crif); + if (err) + goto err_netdev_insert; + + return crif; + +err_netdev_insert: + mlxsw_sp_crif_free(crif); + return ERR_PTR(err); +} + +static void mlxsw_sp_crif_unregister(struct mlxsw_sp_router *router, + struct mlxsw_sp_crif *crif) +{ + struct mlxsw_sp_nexthop *nh, *tmp; + + mlxsw_sp_crif_remove(router, crif); + + list_for_each_entry_safe(nh, tmp, &crif->nexthop_list, crif_list_node) + mlxsw_sp_nexthop_type_fini(router->mlxsw_sp, nh); + + if (crif->rif) + crif->can_destroy = true; + else + mlxsw_sp_crif_free(crif); +} + +static int mlxsw_sp_netdevice_register(struct mlxsw_sp_router *router, + struct net_device *dev) +{ + struct mlxsw_sp_crif *crif; + + if (!mlxsw_sp_router_netdevice_interesting(router->mlxsw_sp, dev)) + return 0; + + crif = mlxsw_sp_crif_register(router, dev); + return PTR_ERR_OR_ZERO(crif); +} + +static void mlxsw_sp_netdevice_unregister(struct mlxsw_sp_router *router, + struct net_device *dev) +{ + struct mlxsw_sp_crif *crif; + + if (!mlxsw_sp_router_netdevice_interesting(router->mlxsw_sp, dev)) + return; + + /* netdev_run_todo(), by way of netdev_wait_allrefs_any(), rebroadcasts + * the NETDEV_UNREGISTER message, so we can get here twice. If that's + * what happened, the netdevice state is NETREG_UNREGISTERED. In that + * case, we expect to have collected the CRIF already, and warn if it + * still exists. Otherwise we expect the CRIF to exist. + */ + crif = mlxsw_sp_crif_lookup(router, dev); + if (dev->reg_state == NETREG_UNREGISTERED) { + if (!WARN_ON(crif)) + return; + } + if (WARN_ON(!crif)) + return; + + mlxsw_sp_crif_unregister(router, crif); +} + static bool mlxsw_sp_is_offload_xstats_event(unsigned long event) { switch (event) { @@ -9254,6 +9523,46 @@ mlxsw_sp_netdevice_vrf_event(struct net_device *l3_dev, unsigned long event, return err; } +static int +mlxsw_sp_port_vid_router_join_existing(struct mlxsw_sp_port *mlxsw_sp_port, + u16 vid, struct net_device *dev, + struct netlink_ext_ack *extack) +{ + struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan; + + mlxsw_sp_port_vlan = mlxsw_sp_port_vlan_find_by_vid(mlxsw_sp_port, + vid); + if (WARN_ON(!mlxsw_sp_port_vlan)) + return -EINVAL; + + return mlxsw_sp_port_vlan_router_join_existing(mlxsw_sp_port_vlan, + dev, extack); +} + +static int __mlxsw_sp_router_port_join_lag(struct mlxsw_sp_port *mlxsw_sp_port, + struct net_device *lag_dev, + struct netlink_ext_ack *extack) +{ + u16 default_vid = MLXSW_SP_DEFAULT_VID; + + return mlxsw_sp_port_vid_router_join_existing(mlxsw_sp_port, + default_vid, lag_dev, + extack); +} + +int mlxsw_sp_router_port_join_lag(struct mlxsw_sp_port *mlxsw_sp_port, + struct net_device *lag_dev, + struct netlink_ext_ack *extack) +{ + int err; + + mutex_lock(&mlxsw_sp_port->mlxsw_sp->router->lock); + err = __mlxsw_sp_router_port_join_lag(mlxsw_sp_port, lag_dev, extack); + mutex_unlock(&mlxsw_sp_port->mlxsw_sp->router->lock); + + return err; +} + static int mlxsw_sp_router_netdevice_event(struct notifier_block *nb, unsigned long event, void *ptr) { @@ -9267,6 +9576,15 @@ static int mlxsw_sp_router_netdevice_event(struct notifier_block *nb, mutex_lock(&mlxsw_sp->router->lock); + if (event == NETDEV_REGISTER) { + err = mlxsw_sp_netdevice_register(router, dev); + if (err) + /* No need to roll this back, UNREGISTER will collect it + * anyhow. + */ + goto out; + } + if (mlxsw_sp_is_offload_xstats_event(event)) err = mlxsw_sp_netdevice_offload_xstats_cmd(mlxsw_sp, dev, event, ptr); @@ -9281,6 +9599,10 @@ static int mlxsw_sp_router_netdevice_event(struct notifier_block *nb, else if (mlxsw_sp_is_vrf_event(event, ptr)) err = mlxsw_sp_netdevice_vrf_event(dev, event, ptr); + if (event == NETDEV_UNREGISTER) + mlxsw_sp_netdevice_unregister(router, dev); + +out: mutex_unlock(&mlxsw_sp->router->lock); return notifier_from_errno(err); @@ -9300,15 +9622,16 @@ static int __mlxsw_sp_rif_macvlan_flush(struct net_device *dev, static int mlxsw_sp_rif_macvlan_flush(struct mlxsw_sp_rif *rif) { + struct net_device *dev = mlxsw_sp_rif_dev(rif); struct netdev_nested_priv priv = { .data = (void *)rif, }; - if (!netif_is_macvlan_port(rif->dev)) + if (!netif_is_macvlan_port(dev)) return 0; - netdev_warn(rif->dev, "Router interface is deleted. Upper macvlans will not work\n"); - return netdev_walk_all_upper_dev_rcu(rif->dev, + netdev_warn(dev, "Router interface is deleted. Upper macvlans will not work\n"); + return netdev_walk_all_upper_dev_rcu(dev, __mlxsw_sp_rif_macvlan_flush, &priv); } @@ -9329,6 +9652,7 @@ static void mlxsw_sp_rif_subport_setup(struct mlxsw_sp_rif *rif, static int mlxsw_sp_rif_subport_op(struct mlxsw_sp_rif *rif, bool enable) { + struct net_device *dev = mlxsw_sp_rif_dev(rif); struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp; struct mlxsw_sp_rif_subport *rif_subport; char ritr_pl[MLXSW_REG_RITR_LEN]; @@ -9336,8 +9660,8 @@ static int mlxsw_sp_rif_subport_op(struct mlxsw_sp_rif *rif, bool enable) rif_subport = mlxsw_sp_rif_subport_rif(rif); mlxsw_reg_ritr_pack(ritr_pl, enable, MLXSW_REG_RITR_SP_IF, - rif->rif_index, rif->vr_id, rif->dev->mtu); - mlxsw_reg_ritr_mac_pack(ritr_pl, rif->dev->dev_addr); + rif->rif_index, rif->vr_id, dev->mtu); + mlxsw_reg_ritr_mac_pack(ritr_pl, dev->dev_addr); mlxsw_reg_ritr_if_mac_profile_id_set(ritr_pl, rif->mac_profile_id); efid = mlxsw_sp_fid_index(rif->fid); mlxsw_reg_ritr_sp_if_pack(ritr_pl, rif_subport->lag, @@ -9350,6 +9674,7 @@ static int mlxsw_sp_rif_subport_op(struct mlxsw_sp_rif *rif, bool enable) static int mlxsw_sp_rif_subport_configure(struct mlxsw_sp_rif *rif, struct netlink_ext_ack *extack) { + struct net_device *dev = mlxsw_sp_rif_dev(rif); u8 mac_profile; int err; @@ -9363,7 +9688,7 @@ static int mlxsw_sp_rif_subport_configure(struct mlxsw_sp_rif *rif, if (err) goto err_rif_subport_op; - err = mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, rif->dev->dev_addr, + err = mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, dev->dev_addr, mlxsw_sp_fid_index(rif->fid), true); if (err) goto err_rif_fdb_op; @@ -9375,7 +9700,7 @@ static int mlxsw_sp_rif_subport_configure(struct mlxsw_sp_rif *rif, return 0; err_fid_rif_set: - mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, rif->dev->dev_addr, + mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, dev->dev_addr, mlxsw_sp_fid_index(rif->fid), false); err_rif_fdb_op: mlxsw_sp_rif_subport_op(rif, false); @@ -9386,10 +9711,11 @@ static int mlxsw_sp_rif_subport_configure(struct mlxsw_sp_rif *rif, static void mlxsw_sp_rif_subport_deconfigure(struct mlxsw_sp_rif *rif) { + struct net_device *dev = mlxsw_sp_rif_dev(rif); struct mlxsw_sp_fid *fid = rif->fid; mlxsw_sp_fid_rif_unset(fid); - mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, rif->dev->dev_addr, + mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, dev->dev_addr, mlxsw_sp_fid_index(fid), false); mlxsw_sp_rif_macvlan_flush(rif); mlxsw_sp_rif_subport_op(rif, false); @@ -9415,12 +9741,13 @@ static const struct mlxsw_sp_rif_ops mlxsw_sp_rif_subport_ops = { static int mlxsw_sp_rif_fid_op(struct mlxsw_sp_rif *rif, u16 fid, bool enable) { enum mlxsw_reg_ritr_if_type type = MLXSW_REG_RITR_FID_IF; + struct net_device *dev = mlxsw_sp_rif_dev(rif); struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp; char ritr_pl[MLXSW_REG_RITR_LEN]; mlxsw_reg_ritr_pack(ritr_pl, enable, type, rif->rif_index, rif->vr_id, - rif->dev->mtu); - mlxsw_reg_ritr_mac_pack(ritr_pl, rif->dev->dev_addr); + dev->mtu); + mlxsw_reg_ritr_mac_pack(ritr_pl, dev->dev_addr); mlxsw_reg_ritr_if_mac_profile_id_set(ritr_pl, rif->mac_profile_id); mlxsw_reg_ritr_fid_if_fid_set(ritr_pl, fid); @@ -9435,6 +9762,7 @@ u16 mlxsw_sp_router_port(const struct mlxsw_sp *mlxsw_sp) static int mlxsw_sp_rif_fid_configure(struct mlxsw_sp_rif *rif, struct netlink_ext_ack *extack) { + struct net_device *dev = mlxsw_sp_rif_dev(rif); struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp; u16 fid_index = mlxsw_sp_fid_index(rif->fid); u8 mac_profile; @@ -9460,7 +9788,7 @@ static int mlxsw_sp_rif_fid_configure(struct mlxsw_sp_rif *rif, if (err) goto err_fid_bc_flood_set; - err = mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, rif->dev->dev_addr, + err = mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, dev->dev_addr, mlxsw_sp_fid_index(rif->fid), true); if (err) goto err_rif_fdb_op; @@ -9472,7 +9800,7 @@ static int mlxsw_sp_rif_fid_configure(struct mlxsw_sp_rif *rif, return 0; err_fid_rif_set: - mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, rif->dev->dev_addr, + mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, dev->dev_addr, mlxsw_sp_fid_index(rif->fid), false); err_rif_fdb_op: mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_BC, @@ -9489,12 +9817,13 @@ static int mlxsw_sp_rif_fid_configure(struct mlxsw_sp_rif *rif, static void mlxsw_sp_rif_fid_deconfigure(struct mlxsw_sp_rif *rif) { + struct net_device *dev = mlxsw_sp_rif_dev(rif); u16 fid_index = mlxsw_sp_fid_index(rif->fid); struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp; struct mlxsw_sp_fid *fid = rif->fid; mlxsw_sp_fid_rif_unset(fid); - mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, rif->dev->dev_addr, + mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, dev->dev_addr, mlxsw_sp_fid_index(fid), false); mlxsw_sp_rif_macvlan_flush(rif); mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_BC, @@ -9509,7 +9838,9 @@ static struct mlxsw_sp_fid * mlxsw_sp_rif_fid_fid_get(struct mlxsw_sp_rif *rif, struct netlink_ext_ack *extack) { - return mlxsw_sp_fid_8021d_get(rif->mlxsw_sp, rif->dev->ifindex); + int rif_ifindex = mlxsw_sp_rif_dev_ifindex(rif); + + return mlxsw_sp_fid_8021d_get(rif->mlxsw_sp, rif_ifindex); } static void mlxsw_sp_rif_fid_fdb_del(struct mlxsw_sp_rif *rif, const char *mac) @@ -9517,7 +9848,7 @@ static void mlxsw_sp_rif_fid_fdb_del(struct mlxsw_sp_rif *rif, const char *mac) struct switchdev_notifier_fdb_info info = {}; struct net_device *dev; - dev = br_fdb_find_port(rif->dev, mac, 0); + dev = br_fdb_find_port(mlxsw_sp_rif_dev(rif), mac, 0); if (!dev) return; @@ -9540,17 +9871,18 @@ static struct mlxsw_sp_fid * mlxsw_sp_rif_vlan_fid_get(struct mlxsw_sp_rif *rif, struct netlink_ext_ack *extack) { + struct net_device *dev = mlxsw_sp_rif_dev(rif); struct net_device *br_dev; u16 vid; int err; - if (is_vlan_dev(rif->dev)) { - vid = vlan_dev_vlan_id(rif->dev); - br_dev = vlan_dev_real_dev(rif->dev); + if (is_vlan_dev(dev)) { + vid = vlan_dev_vlan_id(dev); + br_dev = vlan_dev_real_dev(dev); if (WARN_ON(!netif_is_bridge_master(br_dev))) return ERR_PTR(-EINVAL); } else { - err = br_vlan_get_pvid(rif->dev, &vid); + err = br_vlan_get_pvid(dev, &vid); if (err < 0 || !vid) { NL_SET_ERR_MSG_MOD(extack, "Couldn't determine bridge PVID"); return ERR_PTR(-EINVAL); @@ -9562,12 +9894,13 @@ mlxsw_sp_rif_vlan_fid_get(struct mlxsw_sp_rif *rif, static void mlxsw_sp_rif_vlan_fdb_del(struct mlxsw_sp_rif *rif, const char *mac) { + struct net_device *rif_dev = mlxsw_sp_rif_dev(rif); struct switchdev_notifier_fdb_info info = {}; u16 vid = mlxsw_sp_fid_8021q_vid(rif->fid); struct net_device *br_dev; struct net_device *dev; - br_dev = is_vlan_dev(rif->dev) ? vlan_dev_real_dev(rif->dev) : rif->dev; + br_dev = is_vlan_dev(rif_dev) ? vlan_dev_real_dev(rif_dev) : rif_dev; dev = br_fdb_find_port(br_dev, mac, vid); if (!dev) return; @@ -9581,11 +9914,12 @@ static void mlxsw_sp_rif_vlan_fdb_del(struct mlxsw_sp_rif *rif, const char *mac) static int mlxsw_sp_rif_vlan_op(struct mlxsw_sp_rif *rif, u16 vid, u16 efid, bool enable) { + struct net_device *dev = mlxsw_sp_rif_dev(rif); struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp; char ritr_pl[MLXSW_REG_RITR_LEN]; mlxsw_reg_ritr_vlan_if_pack(ritr_pl, enable, rif->rif_index, rif->vr_id, - rif->dev->mtu, rif->dev->dev_addr, + dev->mtu, dev->dev_addr, rif->mac_profile_id, vid, efid); return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl); @@ -9594,6 +9928,7 @@ static int mlxsw_sp_rif_vlan_op(struct mlxsw_sp_rif *rif, u16 vid, u16 efid, static int mlxsw_sp_rif_vlan_configure(struct mlxsw_sp_rif *rif, u16 efid, struct netlink_ext_ack *extack) { + struct net_device *dev = mlxsw_sp_rif_dev(rif); u16 vid = mlxsw_sp_fid_8021q_vid(rif->fid); struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp; u8 mac_profile; @@ -9619,7 +9954,7 @@ static int mlxsw_sp_rif_vlan_configure(struct mlxsw_sp_rif *rif, u16 efid, if (err) goto err_fid_bc_flood_set; - err = mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, rif->dev->dev_addr, + err = mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, dev->dev_addr, mlxsw_sp_fid_index(rif->fid), true); if (err) goto err_rif_fdb_op; @@ -9631,7 +9966,7 @@ static int mlxsw_sp_rif_vlan_configure(struct mlxsw_sp_rif *rif, u16 efid, return 0; err_fid_rif_set: - mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, rif->dev->dev_addr, + mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, dev->dev_addr, mlxsw_sp_fid_index(rif->fid), false); err_rif_fdb_op: mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_BC, @@ -9648,11 +9983,12 @@ static int mlxsw_sp_rif_vlan_configure(struct mlxsw_sp_rif *rif, u16 efid, static void mlxsw_sp_rif_vlan_deconfigure(struct mlxsw_sp_rif *rif) { + struct net_device *dev = mlxsw_sp_rif_dev(rif); u16 vid = mlxsw_sp_fid_8021q_vid(rif->fid); struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp; mlxsw_sp_fid_rif_unset(rif->fid); - mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, rif->dev->dev_addr, + mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, dev->dev_addr, mlxsw_sp_fid_index(rif->fid), false); mlxsw_sp_rif_macvlan_flush(rif); mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_BC, @@ -9719,12 +10055,13 @@ mlxsw_sp1_rif_ipip_lb_configure(struct mlxsw_sp_rif *rif, struct netlink_ext_ack *extack) { struct mlxsw_sp_rif_ipip_lb *lb_rif = mlxsw_sp_rif_ipip_lb_rif(rif); - u32 ul_tb_id = mlxsw_sp_ipip_dev_ul_tb_id(rif->dev); + struct net_device *dev = mlxsw_sp_rif_dev(rif); + u32 ul_tb_id = mlxsw_sp_ipip_dev_ul_tb_id(dev); struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp; struct mlxsw_sp_vr *ul_vr; int err; - ul_vr = mlxsw_sp_vr_get(mlxsw_sp, ul_tb_id, NULL); + ul_vr = mlxsw_sp_vr_get(mlxsw_sp, ul_tb_id, extack); if (IS_ERR(ul_vr)) return PTR_ERR(ul_vr); @@ -9786,6 +10123,7 @@ mlxsw_sp_rif_ipip_lb_ul_rif_op(struct mlxsw_sp_rif *ul_rif, bool enable) static struct mlxsw_sp_rif * mlxsw_sp_ul_rif_create(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_vr *vr, + struct mlxsw_sp_crif *ul_crif, struct netlink_ext_ack *extack) { struct mlxsw_sp_rif *ul_rif; @@ -9799,7 +10137,8 @@ mlxsw_sp_ul_rif_create(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_vr *vr, return ERR_PTR(err); } - ul_rif = mlxsw_sp_rif_alloc(sizeof(*ul_rif), rif_index, vr->id, NULL); + ul_rif = mlxsw_sp_rif_alloc(sizeof(*ul_rif), rif_index, vr->id, + ul_crif); if (!ul_rif) { err = -ENOMEM; goto err_rif_alloc; @@ -9817,7 +10156,7 @@ mlxsw_sp_ul_rif_create(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_vr *vr, ul_rif_op_err: mlxsw_sp->router->rifs[rif_index] = NULL; - kfree(ul_rif); + mlxsw_sp_rif_free(ul_rif); err_rif_alloc: mlxsw_sp_rif_index_free(mlxsw_sp, rif_index, rif_entries); return ERR_PTR(err); @@ -9832,12 +10171,13 @@ static void mlxsw_sp_ul_rif_destroy(struct mlxsw_sp_rif *ul_rif) atomic_sub(rif_entries, &mlxsw_sp->router->rifs_count); mlxsw_sp_rif_ipip_lb_ul_rif_op(ul_rif, false); mlxsw_sp->router->rifs[ul_rif->rif_index] = NULL; - kfree(ul_rif); + mlxsw_sp_rif_free(ul_rif); mlxsw_sp_rif_index_free(mlxsw_sp, rif_index, rif_entries); } static struct mlxsw_sp_rif * mlxsw_sp_ul_rif_get(struct mlxsw_sp *mlxsw_sp, u32 tb_id, + struct mlxsw_sp_crif *ul_crif, struct netlink_ext_ack *extack) { struct mlxsw_sp_vr *vr; @@ -9850,7 +10190,7 @@ mlxsw_sp_ul_rif_get(struct mlxsw_sp *mlxsw_sp, u32 tb_id, if (refcount_inc_not_zero(&vr->ul_rif_refcnt)) return vr->ul_rif; - vr->ul_rif = mlxsw_sp_ul_rif_create(mlxsw_sp, vr, extack); + vr->ul_rif = mlxsw_sp_ul_rif_create(mlxsw_sp, vr, ul_crif, extack); if (IS_ERR(vr->ul_rif)) { err = PTR_ERR(vr->ul_rif); goto err_ul_rif_create; @@ -9888,7 +10228,7 @@ int mlxsw_sp_router_ul_rif_get(struct mlxsw_sp *mlxsw_sp, u32 ul_tb_id, int err = 0; mutex_lock(&mlxsw_sp->router->lock); - ul_rif = mlxsw_sp_ul_rif_get(mlxsw_sp, ul_tb_id, NULL); + ul_rif = mlxsw_sp_ul_rif_get(mlxsw_sp, ul_tb_id, NULL, NULL); if (IS_ERR(ul_rif)) { err = PTR_ERR(ul_rif); goto out; @@ -9918,12 +10258,13 @@ mlxsw_sp2_rif_ipip_lb_configure(struct mlxsw_sp_rif *rif, struct netlink_ext_ack *extack) { struct mlxsw_sp_rif_ipip_lb *lb_rif = mlxsw_sp_rif_ipip_lb_rif(rif); - u32 ul_tb_id = mlxsw_sp_ipip_dev_ul_tb_id(rif->dev); + struct net_device *dev = mlxsw_sp_rif_dev(rif); + u32 ul_tb_id = mlxsw_sp_ipip_dev_ul_tb_id(dev); struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp; struct mlxsw_sp_rif *ul_rif; int err; - ul_rif = mlxsw_sp_ul_rif_get(mlxsw_sp, ul_tb_id, NULL); + ul_rif = mlxsw_sp_ul_rif_get(mlxsw_sp, ul_tb_id, NULL, extack); if (IS_ERR(ul_rif)) return PTR_ERR(ul_rif); @@ -10041,11 +10382,12 @@ static int mlxsw_sp_rifs_init(struct mlxsw_sp *mlxsw_sp) static void mlxsw_sp_rifs_fini(struct mlxsw_sp *mlxsw_sp) { + int max_rifs = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS); struct devlink *devlink = priv_to_devlink(mlxsw_sp->core); int i; WARN_ON_ONCE(atomic_read(&mlxsw_sp->router->rifs_count)); - for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS); i++) + for (i = 0; i < max_rifs; i++) WARN_ON_ONCE(mlxsw_sp->router->rifs[i]); devl_resource_occ_get_unregister(devlink, MLXSW_SP_RESOURCE_RIFS); @@ -10444,28 +10786,41 @@ static void __mlxsw_sp_router_fini(struct mlxsw_sp *mlxsw_sp) mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(rgcr), rgcr_pl); } -static int mlxsw_sp_lb_rif_init(struct mlxsw_sp *mlxsw_sp) +static int mlxsw_sp_lb_rif_init(struct mlxsw_sp *mlxsw_sp, + struct netlink_ext_ack *extack) { - u16 lb_rif_index; + struct mlxsw_sp_router *router = mlxsw_sp->router; + struct mlxsw_sp_rif *lb_rif; int err; + router->lb_crif = mlxsw_sp_crif_alloc(NULL); + if (!router->lb_crif) + return -ENOMEM; + /* Create a generic loopback RIF associated with the main table * (default VRF). Any table can be used, but the main table exists - * anyway, so we do not waste resources. + * anyway, so we do not waste resources. Loopback RIFs are usually + * created with a NULL CRIF, but this RIF is used as a fallback RIF + * for blackhole nexthops, and nexthops expect to have a valid CRIF. */ - err = mlxsw_sp_router_ul_rif_get(mlxsw_sp, RT_TABLE_MAIN, - &lb_rif_index); - if (err) - return err; - - mlxsw_sp->router->lb_rif_index = lb_rif_index; + lb_rif = mlxsw_sp_ul_rif_get(mlxsw_sp, RT_TABLE_MAIN, router->lb_crif, + extack); + if (IS_ERR(lb_rif)) { + err = PTR_ERR(lb_rif); + goto err_ul_rif_get; + } return 0; + +err_ul_rif_get: + mlxsw_sp_crif_free(router->lb_crif); + return err; } static void mlxsw_sp_lb_rif_fini(struct mlxsw_sp *mlxsw_sp) { - mlxsw_sp_router_ul_rif_put(mlxsw_sp, mlxsw_sp->router->lb_rif_index); + mlxsw_sp_ul_rif_put(mlxsw_sp->router->lb_crif->rif); + mlxsw_sp_crif_free(mlxsw_sp->router->lb_crif); } static int mlxsw_sp1_router_init(struct mlxsw_sp *mlxsw_sp) @@ -10504,6 +10859,7 @@ int mlxsw_sp_router_init(struct mlxsw_sp *mlxsw_sp, struct netlink_ext_ack *extack) { struct mlxsw_sp_router *router; + struct notifier_block *nb; int err; router = kzalloc(sizeof(*mlxsw_sp->router), GFP_KERNEL); @@ -10525,14 +10881,19 @@ int mlxsw_sp_router_init(struct mlxsw_sp *mlxsw_sp, if (err) goto err_router_init; - err = mlxsw_sp_rifs_init(mlxsw_sp); - if (err) - goto err_rifs_init; - err = mlxsw_sp->router_ops->ipips_init(mlxsw_sp); if (err) goto err_ipips_init; + err = rhashtable_init(&mlxsw_sp->router->crif_ht, + &mlxsw_sp_crif_ht_params); + if (err) + goto err_crif_ht_init; + + err = mlxsw_sp_rifs_init(mlxsw_sp); + if (err) + goto err_rifs_init; + err = rhashtable_init(&mlxsw_sp->router->nexthop_ht, &mlxsw_sp_nexthop_ht_params); if (err) @@ -10556,7 +10917,7 @@ int mlxsw_sp_router_init(struct mlxsw_sp *mlxsw_sp, if (err) goto err_vrs_init; - err = mlxsw_sp_lb_rif_init(mlxsw_sp); + err = mlxsw_sp_lb_rif_init(mlxsw_sp, extack); if (err) goto err_lb_rif_init; @@ -10582,6 +10943,17 @@ int mlxsw_sp_router_init(struct mlxsw_sp *mlxsw_sp, if (err) goto err_register_inet6addr_notifier; + router->inetaddr_valid_nb.notifier_call = mlxsw_sp_inetaddr_valid_event; + err = register_inetaddr_validator_notifier(&router->inetaddr_valid_nb); + if (err) + goto err_register_inetaddr_valid_notifier; + + nb = &router->inet6addr_valid_nb; + nb->notifier_call = mlxsw_sp_inet6addr_valid_event; + err = register_inet6addr_validator_notifier(nb); + if (err) + goto err_register_inet6addr_valid_notifier; + mlxsw_sp->router->netevent_nb.notifier_call = mlxsw_sp_router_netevent_event; err = register_netevent_notifier(&mlxsw_sp->router->netevent_nb); @@ -10621,6 +10993,10 @@ int mlxsw_sp_router_init(struct mlxsw_sp *mlxsw_sp, err_register_nexthop_notifier: unregister_netevent_notifier(&mlxsw_sp->router->netevent_nb); err_register_netevent_notifier: + unregister_inet6addr_validator_notifier(&router->inet6addr_valid_nb); +err_register_inet6addr_valid_notifier: + unregister_inetaddr_validator_notifier(&router->inetaddr_valid_nb); +err_register_inetaddr_valid_notifier: unregister_inet6addr_notifier(&router->inet6addr_nb); err_register_inet6addr_notifier: unregister_inetaddr_notifier(&router->inetaddr_nb); @@ -10643,10 +11019,12 @@ int mlxsw_sp_router_init(struct mlxsw_sp *mlxsw_sp, err_nexthop_group_ht_init: rhashtable_destroy(&mlxsw_sp->router->nexthop_ht); err_nexthop_ht_init: - mlxsw_sp_ipips_fini(mlxsw_sp); -err_ipips_init: mlxsw_sp_rifs_fini(mlxsw_sp); err_rifs_init: + rhashtable_destroy(&mlxsw_sp->router->crif_ht); +err_crif_ht_init: + mlxsw_sp_ipips_fini(mlxsw_sp); +err_ipips_init: __mlxsw_sp_router_fini(mlxsw_sp); err_router_init: cancel_delayed_work_sync(&mlxsw_sp->router->nh_grp_activity_dw); @@ -10658,15 +11036,18 @@ int mlxsw_sp_router_init(struct mlxsw_sp *mlxsw_sp, void mlxsw_sp_router_fini(struct mlxsw_sp *mlxsw_sp) { + struct mlxsw_sp_router *router = mlxsw_sp->router; + unregister_netdevice_notifier_net(mlxsw_sp_net(mlxsw_sp), - &mlxsw_sp->router->netdevice_nb); - unregister_fib_notifier(mlxsw_sp_net(mlxsw_sp), - &mlxsw_sp->router->fib_nb); + &router->netdevice_nb); + unregister_fib_notifier(mlxsw_sp_net(mlxsw_sp), &router->fib_nb); unregister_nexthop_notifier(mlxsw_sp_net(mlxsw_sp), - &mlxsw_sp->router->nexthop_nb); - unregister_netevent_notifier(&mlxsw_sp->router->netevent_nb); - unregister_inet6addr_notifier(&mlxsw_sp->router->inet6addr_nb); - unregister_inetaddr_notifier(&mlxsw_sp->router->inetaddr_nb); + &router->nexthop_nb); + unregister_netevent_notifier(&router->netevent_nb); + unregister_inet6addr_validator_notifier(&router->inet6addr_valid_nb); + unregister_inetaddr_validator_notifier(&router->inetaddr_valid_nb); + unregister_inet6addr_notifier(&router->inet6addr_nb); + unregister_inetaddr_notifier(&router->inetaddr_nb); mlxsw_core_flush_owq(); mlxsw_sp_mp_hash_fini(mlxsw_sp); mlxsw_sp_neigh_fini(mlxsw_sp); @@ -10674,12 +11055,13 @@ void mlxsw_sp_router_fini(struct mlxsw_sp *mlxsw_sp) mlxsw_sp_vrs_fini(mlxsw_sp); mlxsw_sp_mr_fini(mlxsw_sp); mlxsw_sp_lpm_fini(mlxsw_sp); - rhashtable_destroy(&mlxsw_sp->router->nexthop_group_ht); - rhashtable_destroy(&mlxsw_sp->router->nexthop_ht); - mlxsw_sp_ipips_fini(mlxsw_sp); + rhashtable_destroy(&router->nexthop_group_ht); + rhashtable_destroy(&router->nexthop_ht); mlxsw_sp_rifs_fini(mlxsw_sp); + rhashtable_destroy(&mlxsw_sp->router->crif_ht); + mlxsw_sp_ipips_fini(mlxsw_sp); __mlxsw_sp_router_fini(mlxsw_sp); - cancel_delayed_work_sync(&mlxsw_sp->router->nh_grp_activity_dw); - mutex_destroy(&mlxsw_sp->router->lock); - kfree(mlxsw_sp->router); + cancel_delayed_work_sync(&router->nh_grp_activity_dw); + mutex_destroy(&router->lock); + kfree(router); } diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h index 37d6e4c80e6a6642d9b607c7b740b8ae937ca315..9a2669a084800b2631eec89f326c6d4d5b145116 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h @@ -20,6 +20,7 @@ struct mlxsw_sp_router_nve_decap { struct mlxsw_sp_router { struct mlxsw_sp *mlxsw_sp; + struct rhashtable crif_ht; struct gen_pool *rifs_table; struct mlxsw_sp_rif **rifs; struct idr rif_mac_profiles_idr; @@ -52,12 +53,14 @@ struct mlxsw_sp_router { struct notifier_block inetaddr_nb; struct notifier_block inet6addr_nb; struct notifier_block netdevice_nb; + struct notifier_block inetaddr_valid_nb; + struct notifier_block inet6addr_valid_nb; const struct mlxsw_sp_rif_ops **rif_ops_arr; const struct mlxsw_sp_ipip_ops **ipip_ops_arr; struct mlxsw_sp_router_nve_decap nve_decap_config; struct mutex lock; /* Protects shared router resources */ struct mlxsw_sp_fib_entry_op_ctx *ll_op_ctx; - u16 lb_rif_index; + struct mlxsw_sp_crif *lb_crif; const struct mlxsw_sp_adj_grp_size_range *adj_grp_size_ranges; size_t adj_grp_size_ranges_count; struct delayed_work nh_grp_activity_dw; @@ -91,7 +94,9 @@ u16 mlxsw_sp_ipip_lb_ul_vr_id(const struct mlxsw_sp_rif_ipip_lb *rif); u16 mlxsw_sp_ipip_lb_ul_rif_id(const struct mlxsw_sp_rif_ipip_lb *lb_rif); u32 mlxsw_sp_ipip_dev_ul_tb_id(const struct net_device *ol_dev); int mlxsw_sp_rif_dev_ifindex(const struct mlxsw_sp_rif *rif); -const struct net_device *mlxsw_sp_rif_dev(const struct mlxsw_sp_rif *rif); +bool mlxsw_sp_rif_has_dev(const struct mlxsw_sp_rif *rif); +bool mlxsw_sp_rif_dev_is(const struct mlxsw_sp_rif *rif, + const struct net_device *dev); int mlxsw_sp_rif_counter_value_get(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_rif *rif, enum mlxsw_sp_rif_counter_dir dir, @@ -166,5 +171,8 @@ int mlxsw_sp_ipip_ecn_encap_init(struct mlxsw_sp *mlxsw_sp); int mlxsw_sp_ipip_ecn_decap_init(struct mlxsw_sp *mlxsw_sp); struct net_device * mlxsw_sp_ipip_netdev_ul_dev_get(const struct net_device *ol_dev); +int mlxsw_sp_router_port_join_lag(struct mlxsw_sp_port *mlxsw_sp_port, + struct net_device *lag_dev, + struct netlink_ext_ack *extack); #endif /* _MLXSW_ROUTER_H_*/ diff --git a/drivers/net/ethernet/microchip/Kconfig b/drivers/net/ethernet/microchip/Kconfig index 24c994baad1355560115365d8cec8241d097e9f7..329e374b9539c9ac684149e441b6fd1b6c4dadf8 100644 --- a/drivers/net/ethernet/microchip/Kconfig +++ b/drivers/net/ethernet/microchip/Kconfig @@ -46,7 +46,7 @@ config LAN743X tristate "LAN743x support" depends on PCI depends on PTP_1588_CLOCK_OPTIONAL - select PHYLIB + select FIXED_PHY select CRC16 select CRC32 help diff --git a/drivers/net/ethernet/microchip/enc28j60.c b/drivers/net/ethernet/microchip/enc28j60.c index 176efbeae12735712835e48da7baed4ee7c8edc6..d6c9491537e47c58947291bd1c3271a137e26951 100644 --- a/drivers/net/ethernet/microchip/enc28j60.c +++ b/drivers/net/ethernet/microchip/enc28j60.c @@ -58,7 +58,6 @@ struct enc28j60_net { struct mutex lock; struct sk_buff *tx_skb; struct work_struct tx_work; - struct work_struct irq_work; struct work_struct setrx_work; struct work_struct restart_work; u8 bank; /* current register bank selected */ @@ -1118,10 +1117,9 @@ static int enc28j60_rx_interrupt(struct net_device *ndev) return ret; } -static void enc28j60_irq_work_handler(struct work_struct *work) +static irqreturn_t enc28j60_irq(int irq, void *dev_id) { - struct enc28j60_net *priv = - container_of(work, struct enc28j60_net, irq_work); + struct enc28j60_net *priv = dev_id; struct net_device *ndev = priv->netdev; int intflags, loop; @@ -1225,6 +1223,8 @@ static void enc28j60_irq_work_handler(struct work_struct *work) /* re-enable interrupts */ locked_reg_bfset(priv, EIE, EIE_INTIE); + + return IRQ_HANDLED; } /* @@ -1309,22 +1309,6 @@ static void enc28j60_tx_work_handler(struct work_struct *work) enc28j60_hw_tx(priv); } -static irqreturn_t enc28j60_irq(int irq, void *dev_id) -{ - struct enc28j60_net *priv = dev_id; - - /* - * Can't do anything in interrupt context because we need to - * block (spi_sync() is blocking) so fire of the interrupt - * handling workqueue. - * Remember that we access enc28j60 registers through SPI bus - * via spi_sync() call. - */ - schedule_work(&priv->irq_work); - - return IRQ_HANDLED; -} - static void enc28j60_tx_timeout(struct net_device *ndev, unsigned int txqueue) { struct enc28j60_net *priv = netdev_priv(ndev); @@ -1559,7 +1543,6 @@ static int enc28j60_probe(struct spi_device *spi) mutex_init(&priv->lock); INIT_WORK(&priv->tx_work, enc28j60_tx_work_handler); INIT_WORK(&priv->setrx_work, enc28j60_setrx_work_handler); - INIT_WORK(&priv->irq_work, enc28j60_irq_work_handler); INIT_WORK(&priv->restart_work, enc28j60_restart_work_handler); spi_set_drvdata(spi, priv); /* spi to priv reference */ SET_NETDEV_DEV(dev, &spi->dev); @@ -1578,7 +1561,8 @@ static int enc28j60_probe(struct spi_device *spi) /* Board setup must set the relevant edge trigger type; * level triggers won't currently work. */ - ret = request_irq(spi->irq, enc28j60_irq, 0, DRV_NAME, priv); + ret = request_threaded_irq(spi->irq, NULL, enc28j60_irq, IRQF_ONESHOT, + DRV_NAME, priv); if (ret < 0) { if (netif_msg_probe(priv)) dev_err(&spi->dev, "request irq %d failed (ret = %d)\n", diff --git a/drivers/net/ethernet/microchip/lan743x_main.c b/drivers/net/ethernet/microchip/lan743x_main.c index 957d96a91a8af749dd4f81d112f633c3fbab867c..a36f6369f13277c0d84224afc5ae2a4b93b2540c 100644 --- a/drivers/net/ethernet/microchip/lan743x_main.c +++ b/drivers/net/ethernet/microchip/lan743x_main.c @@ -144,6 +144,18 @@ static int lan743x_csr_light_reset(struct lan743x_adapter *adapter) !(data & HW_CFG_LRST_), 100000, 10000000); } +static int lan743x_csr_wait_for_bit_atomic(struct lan743x_adapter *adapter, + int offset, u32 bit_mask, + int target_value, int udelay_min, + int udelay_max, int count) +{ + u32 data; + + return readx_poll_timeout_atomic(LAN743X_CSR_READ_OP, offset, data, + target_value == !!(data & bit_mask), + udelay_max, udelay_min * count); +} + static int lan743x_csr_wait_for_bit(struct lan743x_adapter *adapter, int offset, u32 bit_mask, int target_value, int usleep_min, @@ -152,7 +164,7 @@ static int lan743x_csr_wait_for_bit(struct lan743x_adapter *adapter, u32 data; return readx_poll_timeout(LAN743X_CSR_READ_OP, offset, data, - target_value == ((data & bit_mask) ? 1 : 0), + target_value == !!(data & bit_mask), usleep_max, usleep_min * count); } @@ -160,16 +172,13 @@ static int lan743x_csr_init(struct lan743x_adapter *adapter) { struct lan743x_csr *csr = &adapter->csr; resource_size_t bar_start, bar_length; - int result; bar_start = pci_resource_start(adapter->pdev, 0); bar_length = pci_resource_len(adapter->pdev, 0); csr->csr_address = devm_ioremap(&adapter->pdev->dev, bar_start, bar_length); - if (!csr->csr_address) { - result = -ENOMEM; - goto clean_up; - } + if (!csr->csr_address) + return -ENOMEM; csr->id_rev = lan743x_csr_read(adapter, ID_REV); csr->fpga_rev = lan743x_csr_read(adapter, FPGA_REV); @@ -177,10 +186,8 @@ static int lan743x_csr_init(struct lan743x_adapter *adapter) "ID_REV = 0x%08X, FPGA_REV = %d.%d\n", csr->id_rev, FPGA_REV_GET_MAJOR_(csr->fpga_rev), FPGA_REV_GET_MINOR_(csr->fpga_rev)); - if (!ID_REV_IS_VALID_CHIP_ID_(csr->id_rev)) { - result = -ENODEV; - goto clean_up; - } + if (!ID_REV_IS_VALID_CHIP_ID_(csr->id_rev)) + return -ENODEV; csr->flags = LAN743X_CSR_FLAG_SUPPORTS_INTR_AUTO_SET_CLR; switch (csr->id_rev & ID_REV_CHIP_REV_MASK_) { @@ -193,12 +200,7 @@ static int lan743x_csr_init(struct lan743x_adapter *adapter) break; } - result = lan743x_csr_light_reset(adapter); - if (result) - goto clean_up; - return 0; -clean_up: - return result; + return lan743x_csr_light_reset(adapter); } static void lan743x_intr_software_isr(struct lan743x_adapter *adapter) @@ -746,8 +748,8 @@ static int lan743x_dp_write(struct lan743x_adapter *adapter, u32 dp_sel; int i; - if (lan743x_csr_wait_for_bit(adapter, DP_SEL, DP_SEL_DPRDY_, - 1, 40, 100, 100)) + if (lan743x_csr_wait_for_bit_atomic(adapter, DP_SEL, DP_SEL_DPRDY_, + 1, 40, 100, 100)) return -EIO; dp_sel = lan743x_csr_read(adapter, DP_SEL); dp_sel &= ~DP_SEL_MASK_; @@ -758,8 +760,9 @@ static int lan743x_dp_write(struct lan743x_adapter *adapter, lan743x_csr_write(adapter, DP_ADDR, addr + i); lan743x_csr_write(adapter, DP_DATA_0, buf[i]); lan743x_csr_write(adapter, DP_CMD, DP_CMD_WRITE_); - if (lan743x_csr_wait_for_bit(adapter, DP_SEL, DP_SEL_DPRDY_, - 1, 40, 100, 100)) + if (lan743x_csr_wait_for_bit_atomic(adapter, DP_SEL, + DP_SEL_DPRDY_, + 1, 40, 100, 100)) return -EIO; } diff --git a/drivers/net/ethernet/microchip/lan966x/Kconfig b/drivers/net/ethernet/microchip/lan966x/Kconfig index 571e6d4da1e9d6963119eeca8b573eee09b0f214..f9ebffc04eb855ee56e64e3ab2d956f0d10dd24e 100644 --- a/drivers/net/ethernet/microchip/lan966x/Kconfig +++ b/drivers/net/ethernet/microchip/lan966x/Kconfig @@ -10,3 +10,14 @@ config LAN966X_SWITCH select VCAP help This driver supports the Lan966x network switch device. + +config LAN966X_DCB + bool "Data Center Bridging (DCB) support" + depends on LAN966X_SWITCH && DCB + default y + help + Say Y here if you want to use Data Center Bridging (DCB) in the + driver. This can be used to assign priority to traffic, based on + DSCP and PCP. + + If unsure, set to Y. diff --git a/drivers/net/ethernet/microchip/lan966x/Makefile b/drivers/net/ethernet/microchip/lan966x/Makefile index 7b0cda4ffa6b5afd0b41b3a1305b4eb56c52731d..3b6ac331691d0b317cc95e77578a7a0f2c0372b7 100644 --- a/drivers/net/ethernet/microchip/lan966x/Makefile +++ b/drivers/net/ethernet/microchip/lan966x/Makefile @@ -15,6 +15,7 @@ lan966x-switch-objs := lan966x_main.o lan966x_phylink.o lan966x_port.o \ lan966x_xdp.o lan966x_vcap_impl.o lan966x_vcap_ag_api.o \ lan966x_tc_flower.o lan966x_goto.o +lan966x-switch-$(CONFIG_LAN966X_DCB) += lan966x_dcb.o lan966x-switch-$(CONFIG_DEBUG_FS) += lan966x_vcap_debugfs.o # Provide include files diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_dcb.c b/drivers/net/ethernet/microchip/lan966x/lan966x_dcb.c new file mode 100644 index 0000000000000000000000000000000000000000..ed2d96d7908eb2d39c37834e940f675f0c4a66e3 --- /dev/null +++ b/drivers/net/ethernet/microchip/lan966x/lan966x_dcb.c @@ -0,0 +1,365 @@ +// SPDX-License-Identifier: GPL-2.0+ + +#include "lan966x_main.h" + +enum lan966x_dcb_apptrust_values { + LAN966X_DCB_APPTRUST_EMPTY, + LAN966X_DCB_APPTRUST_DSCP, + LAN966X_DCB_APPTRUST_PCP, + LAN966X_DCB_APPTRUST_DSCP_PCP, + __LAN966X_DCB_APPTRUST_MAX +}; + +static const struct lan966x_dcb_apptrust { + u8 selectors[IEEE_8021QAZ_APP_SEL_MAX + 1]; + int nselectors; +} *lan966x_port_apptrust[NUM_PHYS_PORTS]; + +static const char *lan966x_dcb_apptrust_names[__LAN966X_DCB_APPTRUST_MAX] = { + [LAN966X_DCB_APPTRUST_EMPTY] = "empty", + [LAN966X_DCB_APPTRUST_DSCP] = "dscp", + [LAN966X_DCB_APPTRUST_PCP] = "pcp", + [LAN966X_DCB_APPTRUST_DSCP_PCP] = "dscp pcp" +}; + +/* Lan966x supported apptrust policies */ +static const struct lan966x_dcb_apptrust + lan966x_dcb_apptrust_policies[__LAN966X_DCB_APPTRUST_MAX] = { + /* Empty *must* be first */ + [LAN966X_DCB_APPTRUST_EMPTY] = { { 0 }, 0 }, + [LAN966X_DCB_APPTRUST_DSCP] = { { IEEE_8021QAZ_APP_SEL_DSCP }, 1 }, + [LAN966X_DCB_APPTRUST_PCP] = { { DCB_APP_SEL_PCP }, 1 }, + [LAN966X_DCB_APPTRUST_DSCP_PCP] = { { IEEE_8021QAZ_APP_SEL_DSCP, + DCB_APP_SEL_PCP }, 2 }, +}; + +static bool lan966x_dcb_apptrust_contains(int portno, u8 selector) +{ + const struct lan966x_dcb_apptrust *conf = lan966x_port_apptrust[portno]; + + for (int i = 0; i < conf->nselectors; i++) + if (conf->selectors[i] == selector) + return true; + + return false; +} + +static void lan966x_dcb_app_update(struct net_device *dev) +{ + struct dcb_ieee_app_prio_map dscp_rewr_map = {0}; + struct dcb_rewr_prio_pcp_map pcp_rewr_map = {0}; + struct lan966x_port *port = netdev_priv(dev); + struct lan966x_port_qos qos = {0}; + struct dcb_app app_itr; + bool dscp_rewr = false; + bool pcp_rewr = false; + + /* Get pcp ingress mapping */ + for (int i = 0; i < ARRAY_SIZE(qos.pcp.map); i++) { + app_itr.selector = DCB_APP_SEL_PCP; + app_itr.protocol = i; + qos.pcp.map[i] = dcb_getapp(dev, &app_itr); + } + + /* Get dscp ingress mapping */ + for (int i = 0; i < ARRAY_SIZE(qos.dscp.map); i++) { + app_itr.selector = IEEE_8021QAZ_APP_SEL_DSCP; + app_itr.protocol = i; + qos.dscp.map[i] = dcb_getapp(dev, &app_itr); + } + + /* Get default prio */ + qos.default_prio = dcb_ieee_getapp_default_prio_mask(dev); + if (qos.default_prio) + qos.default_prio = fls(qos.default_prio) - 1; + + /* Get pcp rewrite mapping */ + dcb_getrewr_prio_pcp_mask_map(dev, &pcp_rewr_map); + for (int i = 0; i < ARRAY_SIZE(pcp_rewr_map.map); i++) { + if (!pcp_rewr_map.map[i]) + continue; + + pcp_rewr = true; + qos.pcp_rewr.map[i] = fls(pcp_rewr_map.map[i]) - 1; + } + + /* Get dscp rewrite mapping */ + dcb_getrewr_prio_dscp_mask_map(dev, &dscp_rewr_map); + for (int i = 0; i < ARRAY_SIZE(dscp_rewr_map.map); i++) { + if (!dscp_rewr_map.map[i]) + continue; + + dscp_rewr = true; + qos.dscp_rewr.map[i] = fls64(dscp_rewr_map.map[i]) - 1; + } + + /* Enable use of pcp for queue classification */ + if (lan966x_dcb_apptrust_contains(port->chip_port, DCB_APP_SEL_PCP)) { + qos.pcp.enable = true; + + if (pcp_rewr) + qos.pcp_rewr.enable = true; + } + + /* Enable use of dscp for queue classification */ + if (lan966x_dcb_apptrust_contains(port->chip_port, IEEE_8021QAZ_APP_SEL_DSCP)) { + qos.dscp.enable = true; + + if (dscp_rewr) + qos.dscp_rewr.enable = true; + } + + lan966x_port_qos_set(port, &qos); +} + +/* DSCP mapping is global for all ports, so set and delete app entries are + * replicated for each port. + */ +static int lan966x_dcb_ieee_dscp_setdel(struct net_device *dev, + struct dcb_app *app, + int (*setdel)(struct net_device *, + struct dcb_app *)) +{ + struct lan966x_port *port = netdev_priv(dev); + struct lan966x *lan966x = port->lan966x; + int err; + + for (int i = 0; i < NUM_PHYS_PORTS; i++) { + port = lan966x->ports[i]; + if (!port) + continue; + + err = setdel(port->dev, app); + if (err) + return err; + } + + return 0; +} + +static int lan966x_dcb_app_validate(struct net_device *dev, + const struct dcb_app *app) +{ + int err = 0; + + switch (app->selector) { + /* Default priority checks */ + case IEEE_8021QAZ_APP_SEL_ETHERTYPE: + if (app->protocol) + err = -EINVAL; + else if (app->priority >= NUM_PRIO_QUEUES) + err = -ERANGE; + break; + /* Dscp checks */ + case IEEE_8021QAZ_APP_SEL_DSCP: + if (app->protocol >= LAN966X_PORT_QOS_DSCP_COUNT) + err = -EINVAL; + else if (app->priority >= NUM_PRIO_QUEUES) + err = -ERANGE; + break; + /* Pcp checks */ + case DCB_APP_SEL_PCP: + if (app->protocol >= LAN966X_PORT_QOS_PCP_DEI_COUNT) + err = -EINVAL; + else if (app->priority >= NUM_PRIO_QUEUES) + err = -ERANGE; + break; + default: + err = -EINVAL; + break; + } + + if (err) + netdev_err(dev, "Invalid entry: %d:%d\n", app->protocol, + app->priority); + + return err; +} + +static int lan966x_dcb_ieee_delapp(struct net_device *dev, struct dcb_app *app) +{ + int err; + + if (app->selector == IEEE_8021QAZ_APP_SEL_DSCP) + err = lan966x_dcb_ieee_dscp_setdel(dev, app, dcb_ieee_delapp); + else + err = dcb_ieee_delapp(dev, app); + + if (err) + return err; + + lan966x_dcb_app_update(dev); + + return 0; +} + +static int lan966x_dcb_ieee_setapp(struct net_device *dev, struct dcb_app *app) +{ + struct dcb_app app_itr; + int err; + u8 prio; + + err = lan966x_dcb_app_validate(dev, app); + if (err) + return err; + + /* Delete current mapping, if it exists */ + prio = dcb_getapp(dev, app); + if (prio) { + app_itr = *app; + app_itr.priority = prio; + lan966x_dcb_ieee_delapp(dev, &app_itr); + } + + if (app->selector == IEEE_8021QAZ_APP_SEL_DSCP) + err = lan966x_dcb_ieee_dscp_setdel(dev, app, dcb_ieee_setapp); + else + err = dcb_ieee_setapp(dev, app); + + if (err) + return err; + + lan966x_dcb_app_update(dev); + + return 0; +} + +static int lan966x_dcb_apptrust_validate(struct net_device *dev, + u8 *selectors, + int nselectors) +{ + for (int i = 0; i < ARRAY_SIZE(lan966x_dcb_apptrust_policies); i++) { + bool match; + + if (lan966x_dcb_apptrust_policies[i].nselectors != nselectors) + continue; + + match = true; + for (int j = 0; j < nselectors; j++) { + if (lan966x_dcb_apptrust_policies[i].selectors[j] != + *(selectors + j)) { + match = false; + break; + } + } + if (match) + return i; + } + + netdev_err(dev, "Valid apptrust configurations are:\n"); + for (int i = 0; i < ARRAY_SIZE(lan966x_dcb_apptrust_names); i++) + pr_info("order: %s\n", lan966x_dcb_apptrust_names[i]); + + return -EOPNOTSUPP; +} + +static int lan966x_dcb_setapptrust(struct net_device *dev, + u8 *selectors, + int nselectors) +{ + struct lan966x_port *port = netdev_priv(dev); + int idx; + + idx = lan966x_dcb_apptrust_validate(dev, selectors, nselectors); + if (idx < 0) + return idx; + + lan966x_port_apptrust[port->chip_port] = &lan966x_dcb_apptrust_policies[idx]; + lan966x_dcb_app_update(dev); + + return 0; +} + +static int lan966x_dcb_getapptrust(struct net_device *dev, u8 *selectors, + int *nselectors) +{ + struct lan966x_port *port = netdev_priv(dev); + const struct lan966x_dcb_apptrust *trust; + + trust = lan966x_port_apptrust[port->chip_port]; + + memcpy(selectors, trust->selectors, trust->nselectors); + *nselectors = trust->nselectors; + + return 0; +} + +static int lan966x_dcb_delrewr(struct net_device *dev, struct dcb_app *app) +{ + int err; + + if (app->selector == IEEE_8021QAZ_APP_SEL_DSCP) + err = lan966x_dcb_ieee_dscp_setdel(dev, app, dcb_delrewr); + else + err = dcb_delrewr(dev, app); + + if (err < 0) + return err; + + lan966x_dcb_app_update(dev); + + return 0; +} + +static int lan966x_dcb_setrewr(struct net_device *dev, struct dcb_app *app) +{ + struct dcb_app app_itr; + u16 proto; + int err; + + err = lan966x_dcb_app_validate(dev, app); + if (err) + goto out; + + /* Delete current mapping, if it exists. */ + proto = dcb_getrewr(dev, app); + if (proto) { + app_itr = *app; + app_itr.protocol = proto; + lan966x_dcb_delrewr(dev, &app_itr); + } + + if (app->selector == IEEE_8021QAZ_APP_SEL_DSCP) + err = lan966x_dcb_ieee_dscp_setdel(dev, app, dcb_setrewr); + else + err = dcb_setrewr(dev, app); + + if (err) + goto out; + + lan966x_dcb_app_update(dev); + +out: + return err; +} + +static const struct dcbnl_rtnl_ops lan966x_dcbnl_ops = { + .ieee_setapp = lan966x_dcb_ieee_setapp, + .ieee_delapp = lan966x_dcb_ieee_delapp, + .dcbnl_setapptrust = lan966x_dcb_setapptrust, + .dcbnl_getapptrust = lan966x_dcb_getapptrust, + .dcbnl_setrewr = lan966x_dcb_setrewr, + .dcbnl_delrewr = lan966x_dcb_delrewr, +}; + +void lan966x_dcb_init(struct lan966x *lan966x) +{ + for (int p = 0; p < lan966x->num_phys_ports; ++p) { + struct lan966x_port *port; + + port = lan966x->ports[p]; + if (!port) + continue; + + port->dev->dcbnl_ops = &lan966x_dcbnl_ops; + + lan966x_port_apptrust[port->chip_port] = + &lan966x_dcb_apptrust_policies[LAN966X_DCB_APPTRUST_DSCP_PCP]; + + /* Enable DSCP classification based on classified QoS class and + * DP, for all DSCP values, for all ports. + */ + lan966x_port_qos_dscp_rewr_mode_set(port, + LAN966X_PORT_QOS_REWR_DSCP_ALL); + } +} diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_main.c b/drivers/net/ethernet/microchip/lan966x/lan966x_main.c index ee2698698d71a43bb71256a085f91daf603ac095..fbb0bb4594cd7755115385e2051a2906c66d173f 100644 --- a/drivers/net/ethernet/microchip/lan966x/lan966x_main.c +++ b/drivers/net/ethernet/microchip/lan966x/lan966x_main.c @@ -818,6 +818,7 @@ static int lan966x_probe_port(struct lan966x *lan966x, u32 p, port->phylink_config.type = PHYLINK_NETDEV; port->phylink_pcs.poll = true; port->phylink_pcs.ops = &lan966x_phylink_pcs_ops; + port->phylink_pcs.neg_mode = true; port->phylink_config.mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE | MAC_10 | MAC_100 | MAC_1000FD | MAC_2500FD; @@ -1223,6 +1224,8 @@ static int lan966x_probe(struct platform_device *pdev) if (err) goto cleanup_fdma; + lan966x_dcb_init(lan966x); + return 0; cleanup_fdma: diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_main.h b/drivers/net/ethernet/microchip/lan966x/lan966x_main.h index c977c70abc3dc835e6f8bd15acb8ba506a8f37d1..27f272831ea5cda8260d4a2a7004a84bf396d0f7 100644 --- a/drivers/net/ethernet/microchip/lan966x/lan966x_main.h +++ b/drivers/net/ethernet/microchip/lan966x/lan966x_main.h @@ -101,6 +101,25 @@ #define LAN966X_VCAP_CID_IS2_L1 VCAP_CID_INGRESS_STAGE2_L1 /* IS2 lookup 1 */ #define LAN966X_VCAP_CID_IS2_MAX (VCAP_CID_INGRESS_STAGE2_L2 - 1) /* IS2 Max */ +#define LAN966X_VCAP_CID_ES0_L0 VCAP_CID_EGRESS_L0 /* ES0 lookup 0 */ +#define LAN966X_VCAP_CID_ES0_MAX (VCAP_CID_EGRESS_L1 - 1) /* ES0 Max */ + +#define LAN966X_PORT_QOS_PCP_COUNT 8 +#define LAN966X_PORT_QOS_DEI_COUNT 8 +#define LAN966X_PORT_QOS_PCP_DEI_COUNT \ + (LAN966X_PORT_QOS_PCP_COUNT + LAN966X_PORT_QOS_DEI_COUNT) + +#define LAN966X_PORT_QOS_DSCP_COUNT 64 + +/* Port PCP rewrite mode */ +#define LAN966X_PORT_REW_TAG_CTRL_CLASSIFIED 0 +#define LAN966X_PORT_REW_TAG_CTRL_MAPPED 2 + +/* Port DSCP rewrite mode */ +#define LAN966X_PORT_REW_DSCP_FRAME 0 +#define LAN966X_PORT_REW_DSCP_ANALIZER 1 +#define LAN966X_PORT_QOS_REWR_DSCP_ALL 3 + /* MAC table entry types. * ENTRYTYPE_NORMAL is subject to aging. * ENTRYTYPE_LOCKED is not subject to aging. @@ -389,6 +408,34 @@ struct lan966x_port_tc { struct flow_stats mirror_stat; }; +struct lan966x_port_qos_pcp { + u8 map[LAN966X_PORT_QOS_PCP_DEI_COUNT]; + bool enable; +}; + +struct lan966x_port_qos_dscp { + u8 map[LAN966X_PORT_QOS_DSCP_COUNT]; + bool enable; +}; + +struct lan966x_port_qos_pcp_rewr { + u16 map[NUM_PRIO_QUEUES]; + bool enable; +}; + +struct lan966x_port_qos_dscp_rewr { + u16 map[LAN966X_PORT_QOS_DSCP_COUNT]; + bool enable; +}; + +struct lan966x_port_qos { + struct lan966x_port_qos_pcp pcp; + struct lan966x_port_qos_dscp dscp; + struct lan966x_port_qos_pcp_rewr pcp_rewr; + struct lan966x_port_qos_dscp_rewr dscp_rewr; + u8 default_prio; +}; + struct lan966x_port { struct net_device *dev; struct lan966x *lan966x; @@ -453,6 +500,11 @@ int lan966x_port_pcs_set(struct lan966x_port *port, struct lan966x_port_config *config); void lan966x_port_init(struct lan966x_port *port); +void lan966x_port_qos_set(struct lan966x_port *port, + struct lan966x_port_qos *qos); +void lan966x_port_qos_dscp_rewr_mode_set(struct lan966x_port *port, + int mode); + int lan966x_mac_ip_learn(struct lan966x *lan966x, bool cpu_copy, const unsigned char mac[ETH_ALEN], @@ -677,6 +729,14 @@ int lan966x_goto_port_del(struct lan966x_port *port, unsigned long goto_id, struct netlink_ext_ack *extack); +#ifdef CONFIG_LAN966X_DCB +void lan966x_dcb_init(struct lan966x *lan966x); +#else +static inline void lan966x_dcb_init(struct lan966x *lan966x) +{ +} +#endif + static inline void __iomem *lan_addr(void __iomem *base[], int id, int tinst, int tcnt, int gbase, int ginst, diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_phylink.c b/drivers/net/ethernet/microchip/lan966x/lan966x_phylink.c index c5f9803e6e637e0d2eb387a7fc4d8b603740f4e0..1d63903f9006da9062ab47f083a4270f8967bd11 100644 --- a/drivers/net/ethernet/microchip/lan966x/lan966x_phylink.c +++ b/drivers/net/ethernet/microchip/lan966x/lan966x_phylink.c @@ -95,8 +95,7 @@ static void lan966x_pcs_get_state(struct phylink_pcs *pcs, lan966x_port_status_get(port, state); } -static int lan966x_pcs_config(struct phylink_pcs *pcs, - unsigned int mode, +static int lan966x_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode, phy_interface_t interface, const unsigned long *advertising, bool permit_pause_to_mac) @@ -107,8 +106,8 @@ static int lan966x_pcs_config(struct phylink_pcs *pcs, config = port->config; config.portmode = interface; - config.inband = phylink_autoneg_inband(mode); - config.autoneg = phylink_test(advertising, Autoneg); + config.inband = neg_mode & PHYLINK_PCS_NEG_INBAND; + config.autoneg = neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED; config.advertising = advertising; ret = lan966x_port_pcs_set(port, &config); diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_port.c b/drivers/net/ethernet/microchip/lan966x/lan966x_port.c index 0050fcb988b75e01e56abb3272caf194d01870dd..92108d354051c31c44c64b207fb11411d0b4295b 100644 --- a/drivers/net/ethernet/microchip/lan966x/lan966x_port.c +++ b/drivers/net/ethernet/microchip/lan966x/lan966x_port.c @@ -394,6 +394,155 @@ int lan966x_port_pcs_set(struct lan966x_port *port, return 0; } +static void lan966x_port_qos_pcp_set(struct lan966x_port *port, + struct lan966x_port_qos_pcp *qos) +{ + u8 *pcp_itr = qos->map; + u8 pcp, dp; + + lan_rmw(ANA_QOS_CFG_QOS_PCP_ENA_SET(qos->enable), + ANA_QOS_CFG_QOS_PCP_ENA, + port->lan966x, ANA_QOS_CFG(port->chip_port)); + + /* Map PCP and DEI to priority */ + for (int i = 0; i < ARRAY_SIZE(qos->map); i++) { + pcp = *(pcp_itr + i); + dp = (i < LAN966X_PORT_QOS_PCP_COUNT) ? 0 : 1; + + lan_rmw(ANA_PCP_DEI_CFG_QOS_PCP_DEI_VAL_SET(pcp) | + ANA_PCP_DEI_CFG_DP_PCP_DEI_VAL_SET(dp), + ANA_PCP_DEI_CFG_QOS_PCP_DEI_VAL | + ANA_PCP_DEI_CFG_DP_PCP_DEI_VAL, + port->lan966x, + ANA_PCP_DEI_CFG(port->chip_port, i)); + } +} + +static void lan966x_port_qos_dscp_set(struct lan966x_port *port, + struct lan966x_port_qos_dscp *qos) +{ + struct lan966x *lan966x = port->lan966x; + + /* Enable/disable dscp for qos classification. */ + lan_rmw(ANA_QOS_CFG_QOS_DSCP_ENA_SET(qos->enable), + ANA_QOS_CFG_QOS_DSCP_ENA, + lan966x, ANA_QOS_CFG(port->chip_port)); + + /* Map each dscp value to priority and dp */ + for (int i = 0; i < ARRAY_SIZE(qos->map); i++) + lan_rmw(ANA_DSCP_CFG_DP_DSCP_VAL_SET(0) | + ANA_DSCP_CFG_QOS_DSCP_VAL_SET(*(qos->map + i)), + ANA_DSCP_CFG_DP_DSCP_VAL | + ANA_DSCP_CFG_QOS_DSCP_VAL, + lan966x, ANA_DSCP_CFG(i)); + + /* Set per-dscp trust */ + for (int i = 0; i < ARRAY_SIZE(qos->map); i++) + lan_rmw(ANA_DSCP_CFG_DSCP_TRUST_ENA_SET(qos->enable), + ANA_DSCP_CFG_DSCP_TRUST_ENA, + lan966x, ANA_DSCP_CFG(i)); +} + +static int lan966x_port_qos_default_set(struct lan966x_port *port, + struct lan966x_port_qos *qos) +{ + /* Set default prio and dp level */ + lan_rmw(ANA_QOS_CFG_DP_DEFAULT_VAL_SET(0) | + ANA_QOS_CFG_QOS_DEFAULT_VAL_SET(qos->default_prio), + ANA_QOS_CFG_DP_DEFAULT_VAL | + ANA_QOS_CFG_QOS_DEFAULT_VAL, + port->lan966x, ANA_QOS_CFG(port->chip_port)); + + /* Set default pcp and dei for untagged frames */ + lan_rmw(ANA_VLAN_CFG_VLAN_DEI_SET(0) | + ANA_VLAN_CFG_VLAN_PCP_SET(0), + ANA_VLAN_CFG_VLAN_DEI | + ANA_VLAN_CFG_VLAN_PCP, + port->lan966x, ANA_VLAN_CFG(port->chip_port)); + + return 0; +} + +static void lan966x_port_qos_pcp_rewr_set(struct lan966x_port *port, + struct lan966x_port_qos_pcp_rewr *qos) +{ + u8 mode = LAN966X_PORT_REW_TAG_CTRL_CLASSIFIED; + u8 pcp, dei; + + if (qos->enable) + mode = LAN966X_PORT_REW_TAG_CTRL_MAPPED; + + /* Map the values only if it is enabled otherwise will be the classified + * value + */ + lan_rmw(REW_TAG_CFG_TAG_PCP_CFG_SET(mode) | + REW_TAG_CFG_TAG_DEI_CFG_SET(mode), + REW_TAG_CFG_TAG_PCP_CFG | + REW_TAG_CFG_TAG_DEI_CFG, + port->lan966x, REW_TAG_CFG(port->chip_port)); + + /* Map each value to pcp and dei */ + for (int i = 0; i < ARRAY_SIZE(qos->map); i++) { + pcp = qos->map[i]; + if (pcp > LAN966X_PORT_QOS_PCP_COUNT) + dei = 1; + else + dei = 0; + + lan_rmw(REW_PCP_DEI_CFG_DEI_QOS_VAL_SET(dei) | + REW_PCP_DEI_CFG_PCP_QOS_VAL_SET(pcp), + REW_PCP_DEI_CFG_DEI_QOS_VAL | + REW_PCP_DEI_CFG_PCP_QOS_VAL, + port->lan966x, + REW_PCP_DEI_CFG(port->chip_port, + i + dei * LAN966X_PORT_QOS_PCP_COUNT)); + } +} + +static void lan966x_port_qos_dscp_rewr_set(struct lan966x_port *port, + struct lan966x_port_qos_dscp_rewr *qos) +{ + u16 dscp; + u8 mode; + + if (qos->enable) + mode = LAN966X_PORT_REW_DSCP_ANALIZER; + else + mode = LAN966X_PORT_REW_DSCP_FRAME; + + /* Enable the rewrite otherwise will use the values from the frame */ + lan_rmw(REW_DSCP_CFG_DSCP_REWR_CFG_SET(mode), + REW_DSCP_CFG_DSCP_REWR_CFG, + port->lan966x, REW_DSCP_CFG(port->chip_port)); + + /* Map each classified Qos class and DP to classified DSCP value */ + for (int i = 0; i < ARRAY_SIZE(qos->map); i++) { + dscp = qos->map[i]; + + lan_rmw(ANA_DSCP_REWR_CFG_DSCP_QOS_REWR_VAL_SET(dscp), + ANA_DSCP_REWR_CFG_DSCP_QOS_REWR_VAL, + port->lan966x, ANA_DSCP_REWR_CFG(i)); + } +} + +void lan966x_port_qos_dscp_rewr_mode_set(struct lan966x_port *port, + int mode) +{ + lan_rmw(ANA_QOS_CFG_DSCP_REWR_CFG_SET(mode), + ANA_QOS_CFG_DSCP_REWR_CFG, + port->lan966x, ANA_QOS_CFG(port->chip_port)); +} + +void lan966x_port_qos_set(struct lan966x_port *port, + struct lan966x_port_qos *qos) +{ + lan966x_port_qos_pcp_set(port, &qos->pcp); + lan966x_port_qos_dscp_set(port, &qos->dscp); + lan966x_port_qos_default_set(port, qos); + lan966x_port_qos_pcp_rewr_set(port, &qos->pcp_rewr); + lan966x_port_qos_dscp_rewr_set(port, &qos->dscp_rewr); +} + void lan966x_port_init(struct lan966x_port *port) { struct lan966x_port_config *config = &port->config; diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_regs.h b/drivers/net/ethernet/microchip/lan966x/lan966x_regs.h index f99f88b5caa886dd24e38a7c5749793a91dd457a..4b553927d2e0edaadb17fa29fc741c687e453bb0 100644 --- a/drivers/net/ethernet/microchip/lan966x/lan966x_regs.h +++ b/drivers/net/ethernet/microchip/lan966x/lan966x_regs.h @@ -283,6 +283,18 @@ enum lan966x_target { #define ANA_VLAN_CFG_VLAN_POP_CNT_GET(x)\ FIELD_GET(ANA_VLAN_CFG_VLAN_POP_CNT, x) +#define ANA_VLAN_CFG_VLAN_PCP GENMASK(15, 13) +#define ANA_VLAN_CFG_VLAN_PCP_SET(x)\ + FIELD_PREP(ANA_VLAN_CFG_VLAN_PCP, x) +#define ANA_VLAN_CFG_VLAN_PCP_GET(x)\ + FIELD_GET(ANA_VLAN_CFG_VLAN_PCP, x) + +#define ANA_VLAN_CFG_VLAN_DEI BIT(12) +#define ANA_VLAN_CFG_VLAN_DEI_SET(x)\ + FIELD_PREP(ANA_VLAN_CFG_VLAN_DEI, x) +#define ANA_VLAN_CFG_VLAN_DEI_GET(x)\ + FIELD_GET(ANA_VLAN_CFG_VLAN_DEI, x) + #define ANA_VLAN_CFG_VLAN_VID GENMASK(11, 0) #define ANA_VLAN_CFG_VLAN_VID_SET(x)\ FIELD_PREP(ANA_VLAN_CFG_VLAN_VID, x) @@ -316,6 +328,39 @@ enum lan966x_target { #define ANA_DROP_CFG_DROP_MC_SMAC_ENA_GET(x)\ FIELD_GET(ANA_DROP_CFG_DROP_MC_SMAC_ENA, x) +/* ANA:PORT:QOS_CFG */ +#define ANA_QOS_CFG(g) __REG(TARGET_ANA, 0, 1, 28672, g, 9, 128, 8, 0, 1, 4) + +#define ANA_QOS_CFG_DP_DEFAULT_VAL BIT(8) +#define ANA_QOS_CFG_DP_DEFAULT_VAL_SET(x)\ + FIELD_PREP(ANA_QOS_CFG_DP_DEFAULT_VAL, x) +#define ANA_QOS_CFG_DP_DEFAULT_VAL_GET(x)\ + FIELD_GET(ANA_QOS_CFG_DP_DEFAULT_VAL, x) + +#define ANA_QOS_CFG_QOS_DEFAULT_VAL GENMASK(7, 5) +#define ANA_QOS_CFG_QOS_DEFAULT_VAL_SET(x)\ + FIELD_PREP(ANA_QOS_CFG_QOS_DEFAULT_VAL, x) +#define ANA_QOS_CFG_QOS_DEFAULT_VAL_GET(x)\ + FIELD_GET(ANA_QOS_CFG_QOS_DEFAULT_VAL, x) + +#define ANA_QOS_CFG_QOS_DSCP_ENA BIT(4) +#define ANA_QOS_CFG_QOS_DSCP_ENA_SET(x)\ + FIELD_PREP(ANA_QOS_CFG_QOS_DSCP_ENA, x) +#define ANA_QOS_CFG_QOS_DSCP_ENA_GET(x)\ + FIELD_GET(ANA_QOS_CFG_QOS_DSCP_ENA, x) + +#define ANA_QOS_CFG_QOS_PCP_ENA BIT(3) +#define ANA_QOS_CFG_QOS_PCP_ENA_SET(x)\ + FIELD_PREP(ANA_QOS_CFG_QOS_PCP_ENA, x) +#define ANA_QOS_CFG_QOS_PCP_ENA_GET(x)\ + FIELD_GET(ANA_QOS_CFG_QOS_PCP_ENA, x) + +#define ANA_QOS_CFG_DSCP_REWR_CFG GENMASK(1, 0) +#define ANA_QOS_CFG_DSCP_REWR_CFG_SET(x)\ + FIELD_PREP(ANA_QOS_CFG_DSCP_REWR_CFG, x) +#define ANA_QOS_CFG_DSCP_REWR_CFG_GET(x)\ + FIELD_GET(ANA_QOS_CFG_DSCP_REWR_CFG, x) + /* ANA:PORT:VCAP_CFG */ #define ANA_VCAP_CFG(g) __REG(TARGET_ANA, 0, 1, 28672, g, 9, 128, 12, 0, 1, 4) @@ -415,6 +460,21 @@ enum lan966x_target { #define ANA_VCAP_S2_CFG_OAM_DIS_GET(x)\ FIELD_GET(ANA_VCAP_S2_CFG_OAM_DIS, x) +/* ANA:PORT:QOS_PCP_DEI_MAP_CFG */ +#define ANA_PCP_DEI_CFG(g, r) __REG(TARGET_ANA, 0, 1, 28672, g, 9, 128, 32, r, 16, 4) + +#define ANA_PCP_DEI_CFG_DP_PCP_DEI_VAL BIT(3) +#define ANA_PCP_DEI_CFG_DP_PCP_DEI_VAL_SET(x)\ + FIELD_PREP(ANA_PCP_DEI_CFG_DP_PCP_DEI_VAL, x) +#define ANA_PCP_DEI_CFG_DP_PCP_DEI_VAL_GET(x)\ + FIELD_GET(ANA_PCP_DEI_CFG_DP_PCP_DEI_VAL, x) + +#define ANA_PCP_DEI_CFG_QOS_PCP_DEI_VAL GENMASK(2, 0) +#define ANA_PCP_DEI_CFG_QOS_PCP_DEI_VAL_SET(x)\ + FIELD_PREP(ANA_PCP_DEI_CFG_QOS_PCP_DEI_VAL, x) +#define ANA_PCP_DEI_CFG_QOS_PCP_DEI_VAL_GET(x)\ + FIELD_GET(ANA_PCP_DEI_CFG_QOS_PCP_DEI_VAL, x) + /* ANA:PORT:CPU_FWD_CFG */ #define ANA_CPU_FWD_CFG(g) __REG(TARGET_ANA, 0, 1, 28672, g, 9, 128, 96, 0, 1, 4) @@ -478,6 +538,15 @@ enum lan966x_target { #define ANA_PORT_CFG_PORTID_VAL_GET(x)\ FIELD_GET(ANA_PORT_CFG_PORTID_VAL, x) +/* ANA:COMMON:DSCP_REWR_CFG */ +#define ANA_DSCP_REWR_CFG(r) __REG(TARGET_ANA, 0, 1, 31232, 0, 1, 552, 332, r, 16, 4) + +#define ANA_DSCP_REWR_CFG_DSCP_QOS_REWR_VAL GENMASK(5, 0) +#define ANA_DSCP_REWR_CFG_DSCP_QOS_REWR_VAL_SET(x)\ + FIELD_PREP(ANA_DSCP_REWR_CFG_DSCP_QOS_REWR_VAL, x) +#define ANA_DSCP_REWR_CFG_DSCP_QOS_REWR_VAL_GET(x)\ + FIELD_GET(ANA_DSCP_REWR_CFG_DSCP_QOS_REWR_VAL, x) + /* ANA:PORT:POL_CFG */ #define ANA_POL_CFG(g) __REG(TARGET_ANA, 0, 1, 28672, g, 9, 128, 116, 0, 1, 4) @@ -547,6 +616,33 @@ enum lan966x_target { #define ANA_AGGR_CFG_AC_IP4_TCPUDP_ENA_GET(x)\ FIELD_GET(ANA_AGGR_CFG_AC_IP4_TCPUDP_ENA, x) +/* ANA:COMMON:DSCP_CFG */ +#define ANA_DSCP_CFG(r) __REG(TARGET_ANA, 0, 1, 31232, 0, 1, 552, 76, r, 64, 4) + +#define ANA_DSCP_CFG_DP_DSCP_VAL BIT(11) +#define ANA_DSCP_CFG_DP_DSCP_VAL_SET(x)\ + FIELD_PREP(ANA_DSCP_CFG_DP_DSCP_VAL, x) +#define ANA_DSCP_CFG_DP_DSCP_VAL_GET(x)\ + FIELD_GET(ANA_DSCP_CFG_DP_DSCP_VAL, x) + +#define ANA_DSCP_CFG_QOS_DSCP_VAL GENMASK(10, 8) +#define ANA_DSCP_CFG_QOS_DSCP_VAL_SET(x)\ + FIELD_PREP(ANA_DSCP_CFG_QOS_DSCP_VAL, x) +#define ANA_DSCP_CFG_QOS_DSCP_VAL_GET(x)\ + FIELD_GET(ANA_DSCP_CFG_QOS_DSCP_VAL, x) + +#define ANA_DSCP_CFG_DSCP_TRUST_ENA BIT(1) +#define ANA_DSCP_CFG_DSCP_TRUST_ENA_SET(x)\ + FIELD_PREP(ANA_DSCP_CFG_DSCP_TRUST_ENA, x) +#define ANA_DSCP_CFG_DSCP_TRUST_ENA_GET(x)\ + FIELD_GET(ANA_DSCP_CFG_DSCP_TRUST_ENA, x) + +#define ANA_DSCP_CFG_DSCP_REWR_ENA BIT(0) +#define ANA_DSCP_CFG_DSCP_REWR_ENA_SET(x)\ + FIELD_PREP(ANA_DSCP_CFG_DSCP_REWR_ENA, x) +#define ANA_DSCP_CFG_DSCP_REWR_ENA_GET(x)\ + FIELD_GET(ANA_DSCP_CFG_DSCP_REWR_ENA, x) + /* ANA:POL:POL_PIR_CFG */ #define ANA_POL_PIR_CFG(g) __REG(TARGET_ANA, 0, 1, 16384, g, 345, 32, 0, 0, 1, 4) @@ -1468,15 +1564,66 @@ enum lan966x_target { #define REW_TAG_CFG_TAG_TPID_CFG_GET(x)\ FIELD_GET(REW_TAG_CFG_TAG_TPID_CFG, x) +#define REW_TAG_CFG_TAG_PCP_CFG GENMASK(3, 2) +#define REW_TAG_CFG_TAG_PCP_CFG_SET(x)\ + FIELD_PREP(REW_TAG_CFG_TAG_PCP_CFG, x) +#define REW_TAG_CFG_TAG_PCP_CFG_GET(x)\ + FIELD_GET(REW_TAG_CFG_TAG_PCP_CFG, x) + +#define REW_TAG_CFG_TAG_DEI_CFG GENMASK(1, 0) +#define REW_TAG_CFG_TAG_DEI_CFG_SET(x)\ + FIELD_PREP(REW_TAG_CFG_TAG_DEI_CFG, x) +#define REW_TAG_CFG_TAG_DEI_CFG_GET(x)\ + FIELD_GET(REW_TAG_CFG_TAG_DEI_CFG, x) + /* REW:PORT:PORT_CFG */ #define REW_PORT_CFG(g) __REG(TARGET_REW, 0, 1, 0, g, 10, 128, 8, 0, 1, 4) +#define REW_PORT_CFG_ES0_EN BIT(4) +#define REW_PORT_CFG_ES0_EN_SET(x)\ + FIELD_PREP(REW_PORT_CFG_ES0_EN, x) +#define REW_PORT_CFG_ES0_EN_GET(x)\ + FIELD_GET(REW_PORT_CFG_ES0_EN, x) + #define REW_PORT_CFG_NO_REWRITE BIT(0) #define REW_PORT_CFG_NO_REWRITE_SET(x)\ FIELD_PREP(REW_PORT_CFG_NO_REWRITE, x) #define REW_PORT_CFG_NO_REWRITE_GET(x)\ FIELD_GET(REW_PORT_CFG_NO_REWRITE, x) +/* REW:PORT:DSCP_CFG */ +#define REW_DSCP_CFG(g) __REG(TARGET_REW, 0, 1, 0, g, 10, 128, 12, 0, 1, 4) + +#define REW_DSCP_CFG_DSCP_REWR_CFG GENMASK(1, 0) +#define REW_DSCP_CFG_DSCP_REWR_CFG_SET(x)\ + FIELD_PREP(REW_DSCP_CFG_DSCP_REWR_CFG, x) +#define REW_DSCP_CFG_DSCP_REWR_CFG_GET(x)\ + FIELD_GET(REW_DSCP_CFG_DSCP_REWR_CFG, x) + +/* REW:PORT:PCP_DEI_QOS_MAP_CFG */ +#define REW_PCP_DEI_CFG(g, r) __REG(TARGET_REW, 0, 1, 0, g, 10, 128, 16, r, 16, 4) + +#define REW_PCP_DEI_CFG_DEI_QOS_VAL BIT(3) +#define REW_PCP_DEI_CFG_DEI_QOS_VAL_SET(x)\ + FIELD_PREP(REW_PCP_DEI_CFG_DEI_QOS_VAL, x) +#define REW_PCP_DEI_CFG_DEI_QOS_VAL_GET(x)\ + FIELD_GET(REW_PCP_DEI_CFG_DEI_QOS_VAL, x) + +#define REW_PCP_DEI_CFG_PCP_QOS_VAL GENMASK(2, 0) +#define REW_PCP_DEI_CFG_PCP_QOS_VAL_SET(x)\ + FIELD_PREP(REW_PCP_DEI_CFG_PCP_QOS_VAL, x) +#define REW_PCP_DEI_CFG_PCP_QOS_VAL_GET(x)\ + FIELD_GET(REW_PCP_DEI_CFG_PCP_QOS_VAL, x) + +/* REW:COMMON:STAT_CFG */ +#define REW_STAT_CFG __REG(TARGET_REW, 0, 1, 3072, 0, 1, 528, 520, 0, 1, 4) + +#define REW_STAT_CFG_STAT_MODE GENMASK(1, 0) +#define REW_STAT_CFG_STAT_MODE_SET(x)\ + FIELD_PREP(REW_STAT_CFG_STAT_MODE, x) +#define REW_STAT_CFG_STAT_MODE_GET(x)\ + FIELD_GET(REW_STAT_CFG_STAT_MODE, x) + /* SYS:SYSTEM:RESET_CFG */ #define SYS_RESET_CFG __REG(TARGET_SYS, 0, 1, 4128, 0, 1, 168, 0, 0, 1, 4) diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_tc.c b/drivers/net/ethernet/microchip/lan966x/lan966x_tc.c index cf0cc7562d0423fc09f284eb8e52168dd635eb7b..ee652f2d235956cb240924699d058fd1e9739b5a 100644 --- a/drivers/net/ethernet/microchip/lan966x/lan966x_tc.c +++ b/drivers/net/ethernet/microchip/lan966x/lan966x_tc.c @@ -21,8 +21,14 @@ static int lan966x_tc_setup_qdisc_mqprio(struct lan966x_port *port, static int lan966x_tc_setup_qdisc_taprio(struct lan966x_port *port, struct tc_taprio_qopt_offload *taprio) { - return taprio->enable ? lan966x_taprio_add(port, taprio) : - lan966x_taprio_del(port); + switch (taprio->cmd) { + case TAPRIO_CMD_REPLACE: + return lan966x_taprio_add(port, taprio); + case TAPRIO_CMD_DESTROY: + return lan966x_taprio_del(port); + default: + return -EOPNOTSUPP; + } } static int lan966x_tc_setup_qdisc_tbf(struct lan966x_port *port, diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_tc_flower.c b/drivers/net/ethernet/microchip/lan966x/lan966x_tc_flower.c index 47b2f7579dd23a6c242d6c9e5a855918d2ce1f26..96b3def6c4741f5c7083267562fcf518347eff1d 100644 --- a/drivers/net/ethernet/microchip/lan966x/lan966x_tc_flower.c +++ b/drivers/net/ethernet/microchip/lan966x/lan966x_tc_flower.c @@ -5,6 +5,8 @@ #include "vcap_api_client.h" #include "vcap_tc.h" +#define LAN966X_FORCE_UNTAGED 3 + static bool lan966x_tc_is_known_etype(struct vcap_tc_flower_parse_usage *st, u16 etype) { @@ -29,6 +31,8 @@ static bool lan966x_tc_is_known_etype(struct vcap_tc_flower_parse_usage *st, return true; } break; + case VCAP_TYPE_ES0: + return true; default: NL_SET_ERR_MSG_MOD(st->fco->common.extack, "VCAP type not supported"); @@ -318,6 +322,9 @@ static int lan966x_tc_set_actionset(struct vcap_admin *admin, case VCAP_TYPE_IS2: aset = VCAP_AFS_BASE_TYPE; break; + case VCAP_TYPE_ES0: + aset = VCAP_AFS_VID; + break; default: return -EINVAL; } @@ -353,6 +360,10 @@ static int lan966x_tc_add_rule_link_target(struct vcap_admin *admin, /* Add IS2 specific PAG key (for chaining rules from IS1) */ return vcap_rule_add_key_u32(vrule, VCAP_KF_LOOKUP_PAG, link_val, ~0); + case VCAP_TYPE_ES0: + /* Add ES0 specific ISDX key (for chaining rules from IS1) */ + return vcap_rule_add_key_u32(vrule, VCAP_KF_ISDX_CLS, + link_val, ~0); default: break; } @@ -389,6 +400,18 @@ static int lan966x_tc_add_rule_link(struct vcap_control *vctrl, 0xff); if (err) return err; + } else if (admin->vtype == VCAP_TYPE_IS1 && + to_admin->vtype == VCAP_TYPE_ES0) { + /* This works for IS1->ES0 */ + err = vcap_rule_add_action_u32(vrule, VCAP_AF_ISDX_ADD_VAL, + diff); + if (err) + return err; + + err = vcap_rule_add_action_bit(vrule, VCAP_AF_ISDX_REPLACE_ENA, + VCAP_BIT_1); + if (err) + return err; } else { NL_SET_ERR_MSG_MOD(f->common.extack, "Unsupported chain destination"); @@ -398,6 +421,23 @@ static int lan966x_tc_add_rule_link(struct vcap_control *vctrl, return err; } +static int lan966x_tc_add_rule_counter(struct vcap_admin *admin, + struct vcap_rule *vrule) +{ + int err = 0; + + switch (admin->vtype) { + case VCAP_TYPE_ES0: + err = vcap_rule_mod_action_u32(vrule, VCAP_AF_ESDX, + vrule->id); + break; + default: + break; + } + + return err; +} + static int lan966x_tc_flower_add(struct lan966x_port *port, struct flow_cls_offload *f, struct vcap_admin *admin, @@ -465,6 +505,21 @@ static int lan966x_tc_flower_add(struct lan966x_port *port, if (err) goto out; + break; + case FLOW_ACTION_VLAN_POP: + if (admin->vtype != VCAP_TYPE_ES0) { + NL_SET_ERR_MSG_MOD(f->common.extack, + "Cannot use vlan pop on non es0"); + err = -EOPNOTSUPP; + goto out; + } + + /* Force untag */ + err = vcap_rule_add_action_u32(vrule, VCAP_AF_PUSH_OUTER_TAG, + LAN966X_FORCE_UNTAGED); + if (err) + goto out; + break; default: NL_SET_ERR_MSG_MOD(f->common.extack, @@ -474,6 +529,12 @@ static int lan966x_tc_flower_add(struct lan966x_port *port, } } + err = lan966x_tc_add_rule_counter(admin, vrule); + if (err) { + vcap_set_tc_exterr(f, vrule); + goto out; + } + err = vcap_val_rule(vrule, l3_proto); if (err) { vcap_set_tc_exterr(f, vrule); diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_vcap_ag_api.c b/drivers/net/ethernet/microchip/lan966x/lan966x_vcap_ag_api.c index 66400a082d0290dbdcab3b244c5f3803927d5bc1..fb6851b94528c51946e1df90d1345d9785e102bf 100644 --- a/drivers/net/ethernet/microchip/lan966x/lan966x_vcap_ag_api.c +++ b/drivers/net/ethernet/microchip/lan966x/lan966x_vcap_ag_api.c @@ -2121,6 +2121,69 @@ static const struct vcap_field is2_smac_sip6_keyfield[] = { }, }; +static const struct vcap_field es0_vid_keyfield[] = { + [VCAP_KF_IF_EGR_PORT_NO] = { + .type = VCAP_FIELD_U32, + .offset = 0, + .width = 4, + }, + [VCAP_KF_IF_IGR_PORT] = { + .type = VCAP_FIELD_U32, + .offset = 4, + .width = 4, + }, + [VCAP_KF_ISDX_GT0_IS] = { + .type = VCAP_FIELD_BIT, + .offset = 8, + .width = 1, + }, + [VCAP_KF_ISDX_CLS] = { + .type = VCAP_FIELD_U32, + .offset = 9, + .width = 8, + }, + [VCAP_KF_L2_MC_IS] = { + .type = VCAP_FIELD_BIT, + .offset = 17, + .width = 1, + }, + [VCAP_KF_L2_BC_IS] = { + .type = VCAP_FIELD_BIT, + .offset = 18, + .width = 1, + }, + [VCAP_KF_8021Q_VID_CLS] = { + .type = VCAP_FIELD_U32, + .offset = 19, + .width = 12, + }, + [VCAP_KF_8021Q_DEI_CLS] = { + .type = VCAP_FIELD_BIT, + .offset = 31, + .width = 1, + }, + [VCAP_KF_8021Q_PCP_CLS] = { + .type = VCAP_FIELD_U32, + .offset = 32, + .width = 3, + }, + [VCAP_KF_L3_DPL_CLS] = { + .type = VCAP_FIELD_BIT, + .offset = 35, + .width = 1, + }, + [VCAP_KF_RTP_ID] = { + .type = VCAP_FIELD_U32, + .offset = 36, + .width = 10, + }, + [VCAP_KF_PDU_TYPE] = { + .type = VCAP_FIELD_U32, + .offset = 46, + .width = 4, + }, +}; + /* keyfield_set */ static const struct vcap_set is1_keyfield_set[] = { [VCAP_KFS_NORMAL] = { @@ -2228,6 +2291,14 @@ static const struct vcap_set is2_keyfield_set[] = { }, }; +static const struct vcap_set es0_keyfield_set[] = { + [VCAP_KFS_VID] = { + .type_id = -1, + .sw_per_item = 1, + .sw_cnt = 1, + }, +}; + /* keyfield_set map */ static const struct vcap_field *is1_keyfield_set_map[] = { [VCAP_KFS_NORMAL] = is1_normal_keyfield, @@ -2255,6 +2326,10 @@ static const struct vcap_field *is2_keyfield_set_map[] = { [VCAP_KFS_SMAC_SIP6] = is2_smac_sip6_keyfield, }; +static const struct vcap_field *es0_keyfield_set_map[] = { + [VCAP_KFS_VID] = es0_vid_keyfield, +}; + /* keyfield_set map sizes */ static int is1_keyfield_set_map_size[] = { [VCAP_KFS_NORMAL] = ARRAY_SIZE(is1_normal_keyfield), @@ -2282,6 +2357,10 @@ static int is2_keyfield_set_map_size[] = { [VCAP_KFS_SMAC_SIP6] = ARRAY_SIZE(is2_smac_sip6_keyfield), }; +static int es0_keyfield_set_map_size[] = { + [VCAP_KFS_VID] = ARRAY_SIZE(es0_vid_keyfield), +}; + /* actionfields */ static const struct vcap_field is1_s1_actionfield[] = { [VCAP_AF_TYPE] = { @@ -2522,6 +2601,94 @@ static const struct vcap_field is2_smac_sip_actionfield[] = { }, }; +static const struct vcap_field es0_vid_actionfield[] = { + [VCAP_AF_PUSH_OUTER_TAG] = { + .type = VCAP_FIELD_U32, + .offset = 0, + .width = 2, + }, + [VCAP_AF_PUSH_INNER_TAG] = { + .type = VCAP_FIELD_BIT, + .offset = 2, + .width = 1, + }, + [VCAP_AF_TAG_A_TPID_SEL] = { + .type = VCAP_FIELD_U32, + .offset = 3, + .width = 2, + }, + [VCAP_AF_TAG_A_VID_SEL] = { + .type = VCAP_FIELD_BIT, + .offset = 5, + .width = 1, + }, + [VCAP_AF_TAG_A_PCP_SEL] = { + .type = VCAP_FIELD_U32, + .offset = 6, + .width = 2, + }, + [VCAP_AF_TAG_A_DEI_SEL] = { + .type = VCAP_FIELD_U32, + .offset = 8, + .width = 2, + }, + [VCAP_AF_TAG_B_TPID_SEL] = { + .type = VCAP_FIELD_U32, + .offset = 10, + .width = 2, + }, + [VCAP_AF_TAG_B_VID_SEL] = { + .type = VCAP_FIELD_BIT, + .offset = 12, + .width = 1, + }, + [VCAP_AF_TAG_B_PCP_SEL] = { + .type = VCAP_FIELD_U32, + .offset = 13, + .width = 2, + }, + [VCAP_AF_TAG_B_DEI_SEL] = { + .type = VCAP_FIELD_U32, + .offset = 15, + .width = 2, + }, + [VCAP_AF_VID_A_VAL] = { + .type = VCAP_FIELD_U32, + .offset = 17, + .width = 12, + }, + [VCAP_AF_PCP_A_VAL] = { + .type = VCAP_FIELD_U32, + .offset = 29, + .width = 3, + }, + [VCAP_AF_DEI_A_VAL] = { + .type = VCAP_FIELD_BIT, + .offset = 32, + .width = 1, + }, + [VCAP_AF_VID_B_VAL] = { + .type = VCAP_FIELD_U32, + .offset = 33, + .width = 12, + }, + [VCAP_AF_PCP_B_VAL] = { + .type = VCAP_FIELD_U32, + .offset = 45, + .width = 3, + }, + [VCAP_AF_DEI_B_VAL] = { + .type = VCAP_FIELD_BIT, + .offset = 48, + .width = 1, + }, + [VCAP_AF_ESDX] = { + .type = VCAP_FIELD_U32, + .offset = 49, + .width = 8, + }, +}; + /* actionfield_set */ static const struct vcap_set is1_actionfield_set[] = { [VCAP_AFS_S1] = { @@ -2544,6 +2711,14 @@ static const struct vcap_set is2_actionfield_set[] = { }, }; +static const struct vcap_set es0_actionfield_set[] = { + [VCAP_AFS_VID] = { + .type_id = -1, + .sw_per_item = 1, + .sw_cnt = 1, + }, +}; + /* actionfield_set map */ static const struct vcap_field *is1_actionfield_set_map[] = { [VCAP_AFS_S1] = is1_s1_actionfield, @@ -2554,6 +2729,10 @@ static const struct vcap_field *is2_actionfield_set_map[] = { [VCAP_AFS_SMAC_SIP] = is2_smac_sip_actionfield, }; +static const struct vcap_field *es0_actionfield_set_map[] = { + [VCAP_AFS_VID] = es0_vid_actionfield, +}; + /* actionfield_set map size */ static int is1_actionfield_set_map_size[] = { [VCAP_AFS_S1] = ARRAY_SIZE(is1_s1_actionfield), @@ -2564,6 +2743,10 @@ static int is2_actionfield_set_map_size[] = { [VCAP_AFS_SMAC_SIP] = ARRAY_SIZE(is2_smac_sip_actionfield), }; +static int es0_actionfield_set_map_size[] = { + [VCAP_AFS_VID] = ARRAY_SIZE(es0_vid_actionfield), +}; + /* Type Groups */ static const struct vcap_typegroup is1_x4_keyfield_set_typegroups[] = { { @@ -2659,6 +2842,10 @@ static const struct vcap_typegroup is2_x1_keyfield_set_typegroups[] = { {} }; +static const struct vcap_typegroup es0_x1_keyfield_set_typegroups[] = { + {} +}; + static const struct vcap_typegroup *is1_keyfield_set_typegroups[] = { [4] = is1_x4_keyfield_set_typegroups, [2] = is1_x2_keyfield_set_typegroups, @@ -2673,6 +2860,11 @@ static const struct vcap_typegroup *is2_keyfield_set_typegroups[] = { [5] = NULL, }; +static const struct vcap_typegroup *es0_keyfield_set_typegroups[] = { + [1] = es0_x1_keyfield_set_typegroups, + [2] = NULL, +}; + static const struct vcap_typegroup is1_x1_actionfield_set_typegroups[] = { {} }; @@ -2700,6 +2892,10 @@ static const struct vcap_typegroup is2_x1_actionfield_set_typegroups[] = { {} }; +static const struct vcap_typegroup es0_x1_actionfield_set_typegroups[] = { + {} +}; + static const struct vcap_typegroup *is1_actionfield_set_typegroups[] = { [1] = is1_x1_actionfield_set_typegroups, [5] = NULL, @@ -2711,6 +2907,11 @@ static const struct vcap_typegroup *is2_actionfield_set_typegroups[] = { [5] = NULL, }; +static const struct vcap_typegroup *es0_actionfield_set_typegroups[] = { + [1] = es0_x1_actionfield_set_typegroups, + [2] = NULL, +}; + /* Keyfieldset names */ static const char * const vcap_keyfield_set_names[] = { [VCAP_KFS_NO_VALUE] = "(None)", @@ -2743,6 +2944,7 @@ static const char * const vcap_keyfield_set_names[] = { [VCAP_KFS_RT] = "VCAP_KFS_RT", [VCAP_KFS_SMAC_SIP4] = "VCAP_KFS_SMAC_SIP4", [VCAP_KFS_SMAC_SIP6] = "VCAP_KFS_SMAC_SIP6", + [VCAP_KFS_VID] = "VCAP_KFS_VID", }; /* Actionfieldset names */ @@ -2751,9 +2953,11 @@ static const char * const vcap_actionfield_set_names[] = { [VCAP_AFS_BASE_TYPE] = "VCAP_AFS_BASE_TYPE", [VCAP_AFS_CLASSIFICATION] = "VCAP_AFS_CLASSIFICATION", [VCAP_AFS_CLASS_REDUCED] = "VCAP_AFS_CLASS_REDUCED", + [VCAP_AFS_ES0] = "VCAP_AFS_ES0", [VCAP_AFS_FULL] = "VCAP_AFS_FULL", [VCAP_AFS_S1] = "VCAP_AFS_S1", [VCAP_AFS_SMAC_SIP] = "VCAP_AFS_SMAC_SIP", + [VCAP_AFS_VID] = "VCAP_AFS_VID", }; /* Keyfield names */ @@ -2774,6 +2978,7 @@ static const char * const vcap_keyfield_names[] = { [VCAP_KF_8021Q_PCP1] = "8021Q_PCP1", [VCAP_KF_8021Q_PCP2] = "8021Q_PCP2", [VCAP_KF_8021Q_PCP_CLS] = "8021Q_PCP_CLS", + [VCAP_KF_8021Q_TPID] = "8021Q_TPID", [VCAP_KF_8021Q_TPID0] = "8021Q_TPID0", [VCAP_KF_8021Q_TPID1] = "8021Q_TPID1", [VCAP_KF_8021Q_TPID2] = "8021Q_TPID2", @@ -2799,6 +3004,7 @@ static const char * const vcap_keyfield_names[] = { [VCAP_KF_HOST_MATCH] = "HOST_MATCH", [VCAP_KF_IF_EGR_PORT_MASK] = "IF_EGR_PORT_MASK", [VCAP_KF_IF_EGR_PORT_MASK_RNG] = "IF_EGR_PORT_MASK_RNG", + [VCAP_KF_IF_EGR_PORT_NO] = "IF_EGR_PORT_NO", [VCAP_KF_IF_IGR_PORT] = "IF_IGR_PORT", [VCAP_KF_IF_IGR_PORT_MASK] = "IF_IGR_PORT_MASK", [VCAP_KF_IF_IGR_PORT_MASK_L3] = "IF_IGR_PORT_MASK_L3", @@ -2873,7 +3079,9 @@ static const char * const vcap_keyfield_names[] = { [VCAP_KF_OAM_OPCODE] = "OAM_OPCODE", [VCAP_KF_OAM_VER] = "OAM_VER", [VCAP_KF_OAM_Y1731_IS] = "OAM_Y1731_IS", + [VCAP_KF_PDU_TYPE] = "PDU_TYPE", [VCAP_KF_PROT_ACTIVE] = "PROT_ACTIVE", + [VCAP_KF_RTP_ID] = "RTP_ID", [VCAP_KF_RT_FRMID] = "RT_FRMID", [VCAP_KF_RT_TYPE] = "RT_TYPE", [VCAP_KF_RT_VLAN_IDX] = "RT_VLAN_IDX", @@ -2891,18 +3099,25 @@ static const char * const vcap_actionfield_names[] = { [VCAP_AF_COPY_PORT_NUM] = "COPY_PORT_NUM", [VCAP_AF_COPY_QUEUE_NUM] = "COPY_QUEUE_NUM", [VCAP_AF_CPU_COPY_ENA] = "CPU_COPY_ENA", + [VCAP_AF_CPU_QU] = "CPU_QU", [VCAP_AF_CPU_QUEUE_NUM] = "CPU_QUEUE_NUM", [VCAP_AF_CUSTOM_ACE_TYPE_ENA] = "CUSTOM_ACE_TYPE_ENA", + [VCAP_AF_DEI_A_VAL] = "DEI_A_VAL", + [VCAP_AF_DEI_B_VAL] = "DEI_B_VAL", + [VCAP_AF_DEI_C_VAL] = "DEI_C_VAL", [VCAP_AF_DEI_ENA] = "DEI_ENA", [VCAP_AF_DEI_VAL] = "DEI_VAL", [VCAP_AF_DLR_SEL] = "DLR_SEL", [VCAP_AF_DP_ENA] = "DP_ENA", [VCAP_AF_DP_VAL] = "DP_VAL", [VCAP_AF_DSCP_ENA] = "DSCP_ENA", + [VCAP_AF_DSCP_SEL] = "DSCP_SEL", [VCAP_AF_DSCP_VAL] = "DSCP_VAL", [VCAP_AF_ES2_REW_CMD] = "ES2_REW_CMD", + [VCAP_AF_ESDX] = "ESDX", [VCAP_AF_FWD_KILL_ENA] = "FWD_KILL_ENA", [VCAP_AF_FWD_MODE] = "FWD_MODE", + [VCAP_AF_FWD_SEL] = "FWD_SEL", [VCAP_AF_HIT_ME_ONCE] = "HIT_ME_ONCE", [VCAP_AF_HOST_MATCH] = "HOST_MATCH", [VCAP_AF_IGNORE_PIPELINE_CTRL] = "IGNORE_PIPELINE_CTRL", @@ -2912,6 +3127,7 @@ static const char * const vcap_actionfield_names[] = { [VCAP_AF_ISDX_ENA] = "ISDX_ENA", [VCAP_AF_ISDX_REPLACE_ENA] = "ISDX_REPLACE_ENA", [VCAP_AF_ISDX_VAL] = "ISDX_VAL", + [VCAP_AF_LOOP_ENA] = "LOOP_ENA", [VCAP_AF_LRN_DIS] = "LRN_DIS", [VCAP_AF_MAP_IDX] = "MAP_IDX", [VCAP_AF_MAP_KEY] = "MAP_KEY", @@ -2928,15 +3144,23 @@ static const char * const vcap_actionfield_names[] = { [VCAP_AF_OAM_SEL] = "OAM_SEL", [VCAP_AF_PAG_OVERRIDE_MASK] = "PAG_OVERRIDE_MASK", [VCAP_AF_PAG_VAL] = "PAG_VAL", + [VCAP_AF_PCP_A_VAL] = "PCP_A_VAL", + [VCAP_AF_PCP_B_VAL] = "PCP_B_VAL", + [VCAP_AF_PCP_C_VAL] = "PCP_C_VAL", [VCAP_AF_PCP_ENA] = "PCP_ENA", [VCAP_AF_PCP_VAL] = "PCP_VAL", + [VCAP_AF_PIPELINE_ACT] = "PIPELINE_ACT", [VCAP_AF_PIPELINE_FORCE_ENA] = "PIPELINE_FORCE_ENA", [VCAP_AF_PIPELINE_PT] = "PIPELINE_PT", [VCAP_AF_POLICE_ENA] = "POLICE_ENA", [VCAP_AF_POLICE_IDX] = "POLICE_IDX", [VCAP_AF_POLICE_REMARK] = "POLICE_REMARK", [VCAP_AF_POLICE_VCAP_ONLY] = "POLICE_VCAP_ONLY", + [VCAP_AF_POP_VAL] = "POP_VAL", [VCAP_AF_PORT_MASK] = "PORT_MASK", + [VCAP_AF_PUSH_CUSTOMER_TAG] = "PUSH_CUSTOMER_TAG", + [VCAP_AF_PUSH_INNER_TAG] = "PUSH_INNER_TAG", + [VCAP_AF_PUSH_OUTER_TAG] = "PUSH_OUTER_TAG", [VCAP_AF_QOS_ENA] = "QOS_ENA", [VCAP_AF_QOS_VAL] = "QOS_VAL", [VCAP_AF_REW_OP] = "REW_OP", @@ -2945,7 +3169,24 @@ static const char * const vcap_actionfield_names[] = { [VCAP_AF_SFID_VAL] = "SFID_VAL", [VCAP_AF_SGID_ENA] = "SGID_ENA", [VCAP_AF_SGID_VAL] = "SGID_VAL", + [VCAP_AF_SWAP_MACS_ENA] = "SWAP_MACS_ENA", + [VCAP_AF_TAG_A_DEI_SEL] = "TAG_A_DEI_SEL", + [VCAP_AF_TAG_A_PCP_SEL] = "TAG_A_PCP_SEL", + [VCAP_AF_TAG_A_TPID_SEL] = "TAG_A_TPID_SEL", + [VCAP_AF_TAG_A_VID_SEL] = "TAG_A_VID_SEL", + [VCAP_AF_TAG_B_DEI_SEL] = "TAG_B_DEI_SEL", + [VCAP_AF_TAG_B_PCP_SEL] = "TAG_B_PCP_SEL", + [VCAP_AF_TAG_B_TPID_SEL] = "TAG_B_TPID_SEL", + [VCAP_AF_TAG_B_VID_SEL] = "TAG_B_VID_SEL", + [VCAP_AF_TAG_C_DEI_SEL] = "TAG_C_DEI_SEL", + [VCAP_AF_TAG_C_PCP_SEL] = "TAG_C_PCP_SEL", + [VCAP_AF_TAG_C_TPID_SEL] = "TAG_C_TPID_SEL", + [VCAP_AF_TAG_C_VID_SEL] = "TAG_C_VID_SEL", [VCAP_AF_TYPE] = "TYPE", + [VCAP_AF_UNTAG_VID_ENA] = "UNTAG_VID_ENA", + [VCAP_AF_VID_A_VAL] = "VID_A_VAL", + [VCAP_AF_VID_B_VAL] = "VID_B_VAL", + [VCAP_AF_VID_C_VAL] = "VID_C_VAL", [VCAP_AF_VID_REPLACE_ENA] = "VID_REPLACE_ENA", [VCAP_AF_VID_VAL] = "VID_VAL", [VCAP_AF_VLAN_POP_CNT] = "VLAN_POP_CNT", @@ -2996,11 +3237,32 @@ const struct vcap_info lan966x_vcaps[] = { .keyfield_set_typegroups = is2_keyfield_set_typegroups, .actionfield_set_typegroups = is2_actionfield_set_typegroups, }, + [VCAP_TYPE_ES0] = { + .name = "es0", + .rows = 256, + .sw_count = 1, + .sw_width = 96, + .sticky_width = 1, + .act_width = 65, + .default_cnt = 8, + .require_cnt_dis = 0, + .version = 1, + .keyfield_set = es0_keyfield_set, + .keyfield_set_size = ARRAY_SIZE(es0_keyfield_set), + .actionfield_set = es0_actionfield_set, + .actionfield_set_size = ARRAY_SIZE(es0_actionfield_set), + .keyfield_set_map = es0_keyfield_set_map, + .keyfield_set_map_size = es0_keyfield_set_map_size, + .actionfield_set_map = es0_actionfield_set_map, + .actionfield_set_map_size = es0_actionfield_set_map_size, + .keyfield_set_typegroups = es0_keyfield_set_typegroups, + .actionfield_set_typegroups = es0_actionfield_set_typegroups, + }, }; const struct vcap_statistics lan966x_vcap_stats = { .name = "lan966x", - .count = 2, + .count = 3, .keyfield_set_names = vcap_keyfield_set_names, .actionfield_set_names = vcap_actionfield_set_names, .keyfield_names = vcap_keyfield_names, diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_vcap_debugfs.c b/drivers/net/ethernet/microchip/lan966x/lan966x_vcap_debugfs.c index d90c08cfcf142d3eb51bc7f94448b3fc432e1adf..ac525ff1503e696fd2260e9cb36165e0c103870d 100644 --- a/drivers/net/ethernet/microchip/lan966x/lan966x_vcap_debugfs.c +++ b/drivers/net/ethernet/microchip/lan966x/lan966x_vcap_debugfs.c @@ -190,6 +190,26 @@ static void lan966x_vcap_is2_port_keys(struct lan966x_port *port, out->prf(out->dst, "\n"); } +static void lan966x_vcap_es0_port_keys(struct lan966x_port *port, + struct vcap_admin *admin, + struct vcap_output_print *out) +{ + struct lan966x *lan966x = port->lan966x; + u32 val; + + out->prf(out->dst, " port[%d] (%s): ", port->chip_port, + netdev_name(port->dev)); + + val = lan_rd(lan966x, REW_PORT_CFG(port->chip_port)); + out->prf(out->dst, "\n state: "); + if (REW_PORT_CFG_ES0_EN_GET(val)) + out->prf(out->dst, "on"); + else + out->prf(out->dst, "off"); + + out->prf(out->dst, "\n"); +} + int lan966x_vcap_port_info(struct net_device *dev, struct vcap_admin *admin, struct vcap_output_print *out) @@ -210,6 +230,9 @@ int lan966x_vcap_port_info(struct net_device *dev, case VCAP_TYPE_IS1: lan966x_vcap_is1_port_keys(port, admin, out); break; + case VCAP_TYPE_ES0: + lan966x_vcap_es0_port_keys(port, admin, out); + break; default: out->prf(out->dst, " no info\n"); break; diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_vcap_impl.c b/drivers/net/ethernet/microchip/lan966x/lan966x_vcap_impl.c index 7ea8e86336091f0150c4a995c3b389fea6cc9bf6..a4414f63c9b1cc02acbb5f80ce52fb83139d5f2d 100644 --- a/drivers/net/ethernet/microchip/lan966x/lan966x_vcap_impl.c +++ b/drivers/net/ethernet/microchip/lan966x/lan966x_vcap_impl.c @@ -10,6 +10,12 @@ #define LAN966X_IS1_LOOKUPS 3 #define LAN966X_IS2_LOOKUPS 2 +#define LAN966X_ES0_LOOKUPS 1 + +#define LAN966X_STAT_ESDX_GRN_BYTES 0x300 +#define LAN966X_STAT_ESDX_GRN_PKTS 0x301 +#define LAN966X_STAT_ESDX_YEL_BYTES 0x302 +#define LAN966X_STAT_ESDX_YEL_PKTS 0x303 static struct lan966x_vcap_inst { enum vcap_type vtype; /* type of vcap */ @@ -20,6 +26,14 @@ static struct lan966x_vcap_inst { int count; /* number of available addresses */ bool ingress; /* is vcap in the ingress path */ } lan966x_vcap_inst_cfg[] = { + { + .vtype = VCAP_TYPE_ES0, + .tgt_inst = 0, + .lookups = LAN966X_ES0_LOOKUPS, + .first_cid = LAN966X_VCAP_CID_ES0_L0, + .last_cid = LAN966X_VCAP_CID_ES0_MAX, + .count = 64, + }, { .vtype = VCAP_TYPE_IS1, /* IS1-0 */ .tgt_inst = 1, @@ -279,6 +293,8 @@ lan966x_vcap_validate_keyset(struct net_device *dev, err = lan966x_vcap_is2_get_port_keysets(dev, lookup, &keysetlist, l3_proto); break; + case VCAP_TYPE_ES0: + return kslist->keysets[0]; default: pr_err("vcap type: %s not supported\n", lan966x_vcaps[admin->vtype].name); @@ -338,6 +354,14 @@ static void lan966x_vcap_is2_add_default_fields(struct lan966x_port *port, VCAP_BIT_0); } +static void lan966x_vcap_es0_add_default_fields(struct lan966x_port *port, + struct vcap_admin *admin, + struct vcap_rule *rule) +{ + vcap_rule_add_key_u32(rule, VCAP_KF_IF_EGR_PORT_NO, + port->chip_port, GENMASK(4, 0)); +} + static void lan966x_vcap_add_default_fields(struct net_device *dev, struct vcap_admin *admin, struct vcap_rule *rule) @@ -351,6 +375,9 @@ static void lan966x_vcap_add_default_fields(struct net_device *dev, case VCAP_TYPE_IS2: lan966x_vcap_is2_add_default_fields(port, admin, rule); break; + case VCAP_TYPE_ES0: + lan966x_vcap_es0_add_default_fields(port, admin, rule); + break; default: pr_err("vcap type: %s not supported\n", lan966x_vcaps[admin->vtype].name); @@ -366,6 +393,40 @@ static void lan966x_vcap_cache_erase(struct vcap_admin *admin) memset(&admin->cache.counter, 0, sizeof(admin->cache.counter)); } +/* The ESDX counter is only used/incremented if the frame has been classified + * with an ISDX > 0 (e.g by a rule in IS0). This is not mentioned in the + * datasheet. + */ +static void lan966x_es0_read_esdx_counter(struct lan966x *lan966x, + struct vcap_admin *admin, u32 id) +{ + u32 counter; + + id = id & 0xff; /* counter limit */ + mutex_lock(&lan966x->stats_lock); + lan_wr(SYS_STAT_CFG_STAT_VIEW_SET(id), lan966x, SYS_STAT_CFG); + counter = lan_rd(lan966x, SYS_CNT(LAN966X_STAT_ESDX_GRN_PKTS)) + + lan_rd(lan966x, SYS_CNT(LAN966X_STAT_ESDX_YEL_PKTS)); + mutex_unlock(&lan966x->stats_lock); + if (counter) + admin->cache.counter = counter; +} + +static void lan966x_es0_write_esdx_counter(struct lan966x *lan966x, + struct vcap_admin *admin, u32 id) +{ + id = id & 0xff; /* counter limit */ + + mutex_lock(&lan966x->stats_lock); + lan_wr(SYS_STAT_CFG_STAT_VIEW_SET(id), lan966x, SYS_STAT_CFG); + lan_wr(0, lan966x, SYS_CNT(LAN966X_STAT_ESDX_GRN_BYTES)); + lan_wr(admin->cache.counter, lan966x, + SYS_CNT(LAN966X_STAT_ESDX_GRN_PKTS)); + lan_wr(0, lan966x, SYS_CNT(LAN966X_STAT_ESDX_YEL_BYTES)); + lan_wr(0, lan966x, SYS_CNT(LAN966X_STAT_ESDX_YEL_PKTS)); + mutex_unlock(&lan966x->stats_lock); +} + static void lan966x_vcap_cache_write(struct net_device *dev, struct vcap_admin *admin, enum vcap_selection sel, @@ -398,6 +459,9 @@ static void lan966x_vcap_cache_write(struct net_device *dev, admin->cache.sticky = admin->cache.counter > 0; lan_wr(admin->cache.counter, lan966x, VCAP_CNT_DAT(admin->tgt_inst, 0)); + + if (admin->vtype == VCAP_TYPE_ES0) + lan966x_es0_write_esdx_counter(lan966x, admin, start); break; default: break; @@ -437,6 +501,9 @@ static void lan966x_vcap_cache_read(struct net_device *dev, admin->cache.counter = lan_rd(lan966x, VCAP_CNT_DAT(instance, 0)); admin->cache.sticky = admin->cache.counter > 0; + + if (admin->vtype == VCAP_TYPE_ES0) + lan966x_es0_read_esdx_counter(lan966x, admin, start); } } @@ -625,6 +692,12 @@ static void lan966x_vcap_port_key_deselection(struct lan966x *lan966x, lan_wr(0, lan966x, ANA_VCAP_S2_CFG(p)); break; + case VCAP_TYPE_ES0: + for (int p = 0; p < lan966x->num_phys_ports; ++p) + lan_rmw(REW_PORT_CFG_ES0_EN_SET(false), + REW_PORT_CFG_ES0_EN, lan966x, + REW_PORT_CFG(p)); + break; default: pr_err("vcap type: %s not supported\n", lan966x_vcaps[admin->vtype].name); @@ -674,9 +747,18 @@ int lan966x_vcap_init(struct lan966x *lan966x) lan_rmw(ANA_VCAP_CFG_S1_ENA_SET(true), ANA_VCAP_CFG_S1_ENA, lan966x, ANA_VCAP_CFG(lan966x->ports[p]->chip_port)); + + lan_rmw(REW_PORT_CFG_ES0_EN_SET(true), + REW_PORT_CFG_ES0_EN, lan966x, + REW_PORT_CFG(lan966x->ports[p]->chip_port)); } } + /* Statistics: Use ESDX from ES0 if hit, otherwise no counting */ + lan_rmw(REW_STAT_CFG_STAT_MODE_SET(1), + REW_STAT_CFG_STAT_MODE, lan966x, + REW_STAT_CFG); + lan966x->vcap_ctrl = ctrl; return 0; diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_main.c b/drivers/net/ethernet/microchip/sparx5/sparx5_main.c index a7edf524eedbc9b0bdb38c735ffa3316a7cd03f3..dc9af480bfea17351c32249c7de0310ceed7d22f 100644 --- a/drivers/net/ethernet/microchip/sparx5/sparx5_main.c +++ b/drivers/net/ethernet/microchip/sparx5/sparx5_main.c @@ -281,6 +281,7 @@ static int sparx5_create_port(struct sparx5 *sparx5, spx5_port->custom_etype = 0x8880; /* Vitesse */ spx5_port->phylink_pcs.poll = true; spx5_port->phylink_pcs.ops = &sparx5_phylink_pcs_ops; + spx5_port->phylink_pcs.neg_mode = true; spx5_port->is_mrouter = false; INIT_LIST_HEAD(&spx5_port->tc_templates); sparx5->ports[config->portno] = spx5_port; diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_phylink.c b/drivers/net/ethernet/microchip/sparx5/sparx5_phylink.c index bb97d27a1da4a4e550c0a9211b9ad8c9969a271d..f8562c1a894da24eb31342f167cc16adc3e59119 100644 --- a/drivers/net/ethernet/microchip/sparx5/sparx5_phylink.c +++ b/drivers/net/ethernet/microchip/sparx5/sparx5_phylink.c @@ -91,8 +91,7 @@ static void sparx5_pcs_get_state(struct phylink_pcs *pcs, state->pause = status.pause; } -static int sparx5_pcs_config(struct phylink_pcs *pcs, - unsigned int mode, +static int sparx5_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode, phy_interface_t interface, const unsigned long *advertising, bool permit_pause_to_mac) @@ -104,8 +103,9 @@ static int sparx5_pcs_config(struct phylink_pcs *pcs, conf = port->conf; conf.power_down = false; conf.portmode = interface; - conf.inband = phylink_autoneg_inband(mode); - conf.autoneg = phylink_test(advertising, Autoneg); + conf.inband = neg_mode == PHYLINK_PCS_NEG_INBAND_DISABLED || + neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED; + conf.autoneg = neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED; conf.pause_adv = 0; if (phylink_test(advertising, Pause)) conf.pause_adv |= ADVERTISE_1000XPAUSE; diff --git a/drivers/net/ethernet/microchip/vcap/vcap_ag_api.h b/drivers/net/ethernet/microchip/vcap/vcap_ag_api.h index a556c4419986ee897aca1a64a523666b07305d24..c3569a4c7b695597e368cd5e9dd045a05913252d 100644 --- a/drivers/net/ethernet/microchip/vcap/vcap_ag_api.h +++ b/drivers/net/ethernet/microchip/vcap/vcap_ag_api.h @@ -3,8 +3,8 @@ * Microchip VCAP API */ -/* This file is autogenerated by cml-utils 2023-02-16 11:41:14 +0100. - * Commit ID: be85f176b3a151fa748dcaf97c8824a5c2e065f3 +/* This file is autogenerated by cml-utils 2023-03-13 10:16:42 +0100. + * Commit ID: 259f0efd6d6d91bfbf62858de153cc757b6bffa3 (dirty) */ #ifndef __VCAP_AG_API__ @@ -51,6 +51,7 @@ enum vcap_keyfield_set { VCAP_KFS_RT, /* lan966x is1 X1 */ VCAP_KFS_SMAC_SIP4, /* lan966x is2 X1 */ VCAP_KFS_SMAC_SIP6, /* lan966x is2 X2 */ + VCAP_KFS_VID, /* lan966x es0 X1 */ }; /* List of keyfields with description @@ -79,7 +80,7 @@ enum vcap_keyfield_set { * Second DEI in multiple vlan tags (inner tag) * VCAP_KF_8021Q_DEI2: W1, sparx5: is0 * Third DEI in multiple vlan tags (not always available) - * VCAP_KF_8021Q_DEI_CLS: W1, sparx5: is2/es2, lan966x: is2 + * VCAP_KF_8021Q_DEI_CLS: W1, sparx5: is2/es2, lan966x: is2/es0 * Classified DEI * VCAP_KF_8021Q_PCP0: W3, sparx5: is0, lan966x: is1 * First PCP in multiple vlan tags (outer tag or default port tag) @@ -87,7 +88,7 @@ enum vcap_keyfield_set { * Second PCP in multiple vlan tags (inner tag) * VCAP_KF_8021Q_PCP2: W3, sparx5: is0 * Third PCP in multiple vlan tags (not always available) - * VCAP_KF_8021Q_PCP_CLS: W3, sparx5: is2/es2, lan966x: is2 + * VCAP_KF_8021Q_PCP_CLS: W3, sparx5: is2/es2, lan966x: is2/es0 * Classified PCP * VCAP_KF_8021Q_TPID: W3, sparx5: es0 * TPID for outer tag: 0: Customer TPID 1: Service TPID (88A8 or programmable) @@ -104,7 +105,7 @@ enum vcap_keyfield_set { * VCAP_KF_8021Q_VID2: W12, sparx5: is0 * Third VID in multiple vlan tags (not always available) * VCAP_KF_8021Q_VID_CLS: sparx5 is2 W13, sparx5 es0 W13, sparx5 es2 W13, - * lan966x is2 W12 + * lan966x is2 W12, lan966x es0 W12 * Classified VID * VCAP_KF_8021Q_VLAN_DBL_TAGGED_IS: W1, lan966x: is1 * Set if frame has two or more Q-tags. Independent of port VLAN awareness @@ -146,10 +147,10 @@ enum vcap_keyfield_set { * VCAP_KF_IF_EGR_PORT_MASK_RNG: W3, sparx5: es2 * Select which 32 port group is available in IF_EGR_PORT (or virtual ports or * CPU queue) - * VCAP_KF_IF_EGR_PORT_NO: W7, sparx5: es0 + * VCAP_KF_IF_EGR_PORT_NO: sparx5 es0 W7, lan966x es0 W4 * Egress port number * VCAP_KF_IF_IGR_PORT: sparx5 is0 W7, sparx5 es2 W9, lan966x is1 W3, lan966x - * is2 W4 + * is2 W4, lan966x es0 W4 * Sparx5: Logical ingress port number retrieved from * ANA_CL::PORT_ID_CFG.LPORT_NUM or ERLEG, LAN966x: ingress port nunmber * VCAP_KF_IF_IGR_PORT_MASK: sparx5 is0 W65, sparx5 is2 W32, sparx5 is2 W65, @@ -178,11 +179,12 @@ enum vcap_keyfield_set { * Payload after IPv6 header * VCAP_KF_IP_SNAP_IS: W1, sparx5: is0, lan966x: is1 * Set if frame is IPv4, IPv6, or SNAP frame - * VCAP_KF_ISDX_CLS: W12, sparx5: is2/es0/es2 + * VCAP_KF_ISDX_CLS: sparx5 is2 W12, sparx5 es0 W12, sparx5 es2 W12, lan966x es0 + * W8 * Classified ISDX - * VCAP_KF_ISDX_GT0_IS: W1, sparx5: is2/es0/es2, lan966x: is2 + * VCAP_KF_ISDX_GT0_IS: W1, sparx5: is2/es0/es2, lan966x: is2/es0 * Set if classified ISDX > 0 - * VCAP_KF_L2_BC_IS: W1, sparx5: is0/is2/es2, lan966x: is1/is2 + * VCAP_KF_L2_BC_IS: W1, sparx5: is0/is2/es2, lan966x: is1/is2/es0 * Set if frame's destination MAC address is the broadcast address * (FF-FF-FF-FF-FF-FF). * VCAP_KF_L2_DMAC: W48, sparx5: is0/is2/es2, lan966x: is1/is2 @@ -195,7 +197,7 @@ enum vcap_keyfield_set { * LLC header and data after up to two VLAN tags and the type/length field * VCAP_KF_L2_MAC: W48, lan966x: is1 * MAC address (FIRST=1: SMAC, FIRST=0: DMAC) - * VCAP_KF_L2_MC_IS: W1, sparx5: is0/is2/es2, lan966x: is1/is2 + * VCAP_KF_L2_MC_IS: W1, sparx5: is0/is2/es2, lan966x: is1/is2/es0 * Set if frame's destination MAC address is a multicast address (bit 40 = 1). * VCAP_KF_L2_PAYLOAD0: W16, lan966x: is2 * Payload bytes 0-1 after the frame's EtherType @@ -213,7 +215,7 @@ enum vcap_keyfield_set { * SNAP header after LLC header (AA-AA-03) * VCAP_KF_L3_DIP_EQ_SIP_IS: W1, sparx5: is2/es2, lan966x: is2 * Set if Src IP matches Dst IP address - * VCAP_KF_L3_DPL_CLS: W1, sparx5: es0/es2 + * VCAP_KF_L3_DPL_CLS: W1, sparx5: es0/es2, lan966x: es0 * The frames drop precedence level * VCAP_KF_L3_DSCP: W6, sparx5: is0, lan966x: is1 * Frame's DSCP value @@ -330,8 +332,12 @@ enum vcap_keyfield_set { * Frame's OAM version * VCAP_KF_OAM_Y1731_IS: W1, sparx5: is2/es2, lan966x: is2 * Set if frame's EtherType = 0x8902 + * VCAP_KF_PDU_TYPE: W4, lan966x: es0 + * PDU type value (none, OAM CCM, MRP, DLR, RTE, IPv4, IPv6, OAM non-CCM) * VCAP_KF_PROT_ACTIVE: W1, sparx5: es0/es2 * Protection is active + * VCAP_KF_RTP_ID: W10, lan966x: es0 + * Classified RTP_ID * VCAP_KF_RT_FRMID: W32, lan966x: is1 * Profinet or OPC-UA FrameId * VCAP_KF_RT_TYPE: W2, lan966x: is1 @@ -470,7 +476,9 @@ enum vcap_key_field { VCAP_KF_OAM_OPCODE, VCAP_KF_OAM_VER, VCAP_KF_OAM_Y1731_IS, + VCAP_KF_PDU_TYPE, VCAP_KF_PROT_ACTIVE, + VCAP_KF_RTP_ID, VCAP_KF_RT_FRMID, VCAP_KF_RT_TYPE, VCAP_KF_RT_VLAN_IDX, @@ -489,6 +497,7 @@ enum vcap_actionfield_set { VCAP_AFS_FULL, /* sparx5 is0 X3 */ VCAP_AFS_S1, /* lan966x is1 X1 */ VCAP_AFS_SMAC_SIP, /* lan966x is2 X1 */ + VCAP_AFS_VID, /* lan966x es0 X1 */ }; /* List of actionfields with description @@ -523,9 +532,9 @@ enum vcap_actionfield_set { * while bits 1:0 control first lookup. Encoding per lookup: 0: Disabled. 1: * Extract 40 bytes after position corresponding to the location of the IPv4 * header and use as key. 2: Extract 40 bytes after SMAC and use as key - * VCAP_AF_DEI_A_VAL: W1, sparx5: es0 + * VCAP_AF_DEI_A_VAL: W1, sparx5: es0, lan966x: es0 * DEI used in ES0 tag A. See TAG_A_DEI_SEL. - * VCAP_AF_DEI_B_VAL: W1, sparx5: es0 + * VCAP_AF_DEI_B_VAL: W1, sparx5: es0, lan966x: es0 * DEI used in ES0 tag B. See TAG_B_DEI_SEL. * VCAP_AF_DEI_C_VAL: W1, sparx5: es0 * DEI used in ES0 tag C. See TAG_C_DEI_SEL. @@ -556,7 +565,7 @@ enum vcap_actionfield_set { * VCAP_AF_ES2_REW_CMD: W3, sparx5: es2 * Command forwarded to REW: 0: No action. 1: SWAP MAC addresses. 2: Do L2CP * DMAC translation when entering or leaving a tunnel. - * VCAP_AF_ESDX: W13, sparx5: es0 + * VCAP_AF_ESDX: sparx5 es0 W13, lan966x es0 W8 * Egress counter index. Used to index egress counter set as defined in * REW::STAT_CFG. * VCAP_AF_FWD_KILL_ENA: W1, lan966x: is2 @@ -652,9 +661,9 @@ enum vcap_actionfield_set { * (input) AND ~PAG_OVERRIDE_MASK) OR (PAG_VAL AND PAG_OVERRIDE_MASK) * VCAP_AF_PAG_VAL: W8, sparx5: is0, lan966x: is1 * See PAG_OVERRIDE_MASK. - * VCAP_AF_PCP_A_VAL: W3, sparx5: es0 + * VCAP_AF_PCP_A_VAL: W3, sparx5: es0, lan966x: es0 * PCP used in ES0 tag A. See TAG_A_PCP_SEL. - * VCAP_AF_PCP_B_VAL: W3, sparx5: es0 + * VCAP_AF_PCP_B_VAL: W3, sparx5: es0, lan966x: es0 * PCP used in ES0 tag B. See TAG_B_PCP_SEL. * VCAP_AF_PCP_C_VAL: W3, sparx5: es0 * PCP used in ES0 tag C. See TAG_C_PCP_SEL. @@ -691,10 +700,10 @@ enum vcap_actionfield_set { * Selects tag C mode: 0: Do not push tag C. 1: Push tag C if * IFH.VSTAX.TAG.WAS_TAGGED = 1. 2: Push tag C if IFH.VSTAX.TAG.WAS_TAGGED = 0. * 3: Push tag C if UNTAG_VID_ENA = 0 or (C-TAG.VID ! = VID_C_VAL). - * VCAP_AF_PUSH_INNER_TAG: W1, sparx5: es0 + * VCAP_AF_PUSH_INNER_TAG: W1, sparx5: es0, lan966x: es0 * Controls inner tagging. 0: Do not push ES0 tag B as inner tag. 1: Push ES0 * tag B as inner tag. - * VCAP_AF_PUSH_OUTER_TAG: W2, sparx5: es0 + * VCAP_AF_PUSH_OUTER_TAG: W2, sparx5: es0, lan966x: es0 * Controls outer tagging. 0: No ES0 tag A: Port tag is allowed if enabled on * port. 1: ES0 tag A: Push ES0 tag A. No port tag. 2: Force port tag: Always * push port tag. No ES0 tag A. 3: Force untag: Never push port tag or ES0 tag @@ -720,29 +729,29 @@ enum vcap_actionfield_set { * VCAP_AF_SWAP_MACS_ENA: W1, sparx5: es0 * This setting is only active when FWD_SEL = 1 or FWD_SEL = 2 and PIPELINE_ACT * = LBK_ASM. 0: No action. 1: Swap MACs and clear bit 40 in new SMAC. - * VCAP_AF_TAG_A_DEI_SEL: W3, sparx5: es0 + * VCAP_AF_TAG_A_DEI_SEL: sparx5 es0 W3, lan966x es0 W2 * Selects PCP for ES0 tag A. 0: Classified DEI. 1: DEI_A_VAL. 2: DP and QoS * mapped to PCP (per port table). 3: DP. - * VCAP_AF_TAG_A_PCP_SEL: W3, sparx5: es0 + * VCAP_AF_TAG_A_PCP_SEL: sparx5 es0 W3, lan966x es0 W2 * Selects PCP for ES0 tag A. 0: Classified PCP. 1: PCP_A_VAL. 2: DP and QoS * mapped to PCP (per port table). 3: QoS class. - * VCAP_AF_TAG_A_TPID_SEL: W3, sparx5: es0 + * VCAP_AF_TAG_A_TPID_SEL: sparx5 es0 W3, lan966x es0 W2 * Selects TPID for ES0 tag A: 0: 0x8100. 1: 0x88A8. 2: Custom * (REW:PORT:PORT_VLAN_CFG.PORT_TPID). 3: If IFH.TAG_TYPE = 0 then 0x8100 else * custom. - * VCAP_AF_TAG_A_VID_SEL: W2, sparx5: es0 + * VCAP_AF_TAG_A_VID_SEL: sparx5 es0 W2, lan966x es0 W1 * Selects VID for ES0 tag A. 0: Classified VID + VID_A_VAL. 1: VID_A_VAL. - * VCAP_AF_TAG_B_DEI_SEL: W3, sparx5: es0 + * VCAP_AF_TAG_B_DEI_SEL: sparx5 es0 W3, lan966x es0 W2 * Selects PCP for ES0 tag B. 0: Classified DEI. 1: DEI_B_VAL. 2: DP and QoS * mapped to PCP (per port table). 3: DP. - * VCAP_AF_TAG_B_PCP_SEL: W3, sparx5: es0 + * VCAP_AF_TAG_B_PCP_SEL: sparx5 es0 W3, lan966x es0 W2 * Selects PCP for ES0 tag B. 0: Classified PCP. 1: PCP_B_VAL. 2: DP and QoS * mapped to PCP (per port table). 3: QoS class. - * VCAP_AF_TAG_B_TPID_SEL: W3, sparx5: es0 + * VCAP_AF_TAG_B_TPID_SEL: sparx5 es0 W3, lan966x es0 W2 * Selects TPID for ES0 tag B. 0: 0x8100. 1: 0x88A8. 2: Custom * (REW:PORT:PORT_VLAN_CFG.PORT_TPID). 3: If IFH.TAG_TYPE = 0 then 0x8100 else * custom. - * VCAP_AF_TAG_B_VID_SEL: W2, sparx5: es0 + * VCAP_AF_TAG_B_VID_SEL: sparx5 es0 W2, lan966x es0 W1 * Selects VID for ES0 tag B. 0: Classified VID + VID_B_VAL. 1: VID_B_VAL. * VCAP_AF_TAG_C_DEI_SEL: W3, sparx5: es0 * Selects DEI source for ES0 tag C. 0: Classified DEI. 1: DEI_C_VAL. 2: @@ -770,9 +779,9 @@ enum vcap_actionfield_set { * VCAP_AF_UNTAG_VID_ENA: W1, sparx5: es0 * Controls insertion of tag C. Untag or insert mode can be selected. See * PUSH_CUSTOMER_TAG. - * VCAP_AF_VID_A_VAL: W12, sparx5: es0 + * VCAP_AF_VID_A_VAL: W12, sparx5: es0, lan966x: es0 * VID used in ES0 tag A. See TAG_A_VID_SEL. - * VCAP_AF_VID_B_VAL: W12, sparx5: es0 + * VCAP_AF_VID_B_VAL: W12, sparx5: es0, lan966x: es0 * VID used in ES0 tag B. See TAG_B_VID_SEL. * VCAP_AF_VID_C_VAL: W12, sparx5: es0 * VID used in ES0 tag C. See TAG_C_VID_SEL. diff --git a/drivers/net/ethernet/microchip/vcap/vcap_api.c b/drivers/net/ethernet/microchip/vcap/vcap_api.c index 5675b0962bc3c690f54359d032556e36c66cbaec..a418ad8e8770ab8fb24f05be066422552c808cb6 100644 --- a/drivers/net/ethernet/microchip/vcap/vcap_api.c +++ b/drivers/net/ethernet/microchip/vcap/vcap_api.c @@ -1121,7 +1121,7 @@ static void vcap_copy_to_client_actionfield(struct vcap_rule_internal *ri, vcap_copy_from_w32be(field->data.u128.value, value, field_size, width); break; - }; + } } else { switch (field->ctrl.type) { case VCAP_FIELD_BIT: @@ -1162,7 +1162,7 @@ static void vcap_copy_to_client_actionfield(struct vcap_rule_internal *ri, value, width, field_size); break; - }; + } } } @@ -1236,7 +1236,7 @@ static void vcap_copy_to_client_keyfield(struct vcap_rule_internal *ri, vcap_copy_from_w32be(field->data.u128.mask, mask, field_size, width); break; - }; + } } else { switch (field->ctrl.type) { case VCAP_FIELD_BIT: @@ -1284,7 +1284,7 @@ static void vcap_copy_to_client_keyfield(struct vcap_rule_internal *ri, value, mask, width, field_size); break; - }; + } } } diff --git a/drivers/net/ethernet/microsoft/mana/hw_channel.c b/drivers/net/ethernet/microsoft/mana/hw_channel.c index 9d1507eba5b9091fd6000cd8d64b0e5b80949d0a..2bd1d74021f7cd0e6f42a2cff5ea09349b765feb 100644 --- a/drivers/net/ethernet/microsoft/mana/hw_channel.c +++ b/drivers/net/ethernet/microsoft/mana/hw_channel.c @@ -627,7 +627,7 @@ static int mana_hwc_establish_channel(struct gdma_context *gc, u16 *q_depth, if (WARN_ON(cq->id >= gc->max_num_cqs)) return -EPROTO; - gc->cq_table = vzalloc(gc->max_num_cqs * sizeof(struct gdma_queue *)); + gc->cq_table = vcalloc(gc->max_num_cqs, sizeof(struct gdma_queue *)); if (!gc->cq_table) return -ENOMEM; diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c b/drivers/net/ethernet/microsoft/mana/mana_en.c index d907727c7b7a5324b66e319683d4d611638cd09c..a499e460594b6598bdd501cf5d27084af5c15b73 100644 --- a/drivers/net/ethernet/microsoft/mana/mana_en.c +++ b/drivers/net/ethernet/microsoft/mana/mana_en.c @@ -179,6 +179,14 @@ netdev_tx_t mana_start_xmit(struct sk_buff *skb, struct net_device *ndev) pkg.tx_oob.s_oob.short_vp_offset = txq->vp_offset; } + if (skb_vlan_tag_present(skb)) { + pkt_fmt = MANA_LONG_PKT_FMT; + pkg.tx_oob.l_oob.inject_vlan_pri_tag = 1; + pkg.tx_oob.l_oob.pcp = skb_vlan_tag_get_prio(skb); + pkg.tx_oob.l_oob.dei = skb_vlan_tag_get_cfi(skb); + pkg.tx_oob.l_oob.vlan_id = skb_vlan_tag_get_id(skb); + } + pkg.tx_oob.s_oob.pkt_fmt = pkt_fmt; if (pkt_fmt == MANA_SHORT_PKT_FMT) { @@ -972,7 +980,7 @@ static int mana_cfg_vport_steering(struct mana_port_context *apc, bool update_tab) { u16 num_entries = MANA_INDIRECT_TABLE_SIZE; - struct mana_cfg_rx_steer_req *req = NULL; + struct mana_cfg_rx_steer_req_v2 *req; struct mana_cfg_rx_steer_resp resp = {}; struct net_device *ndev = apc->ndev; mana_handle_t *req_indir_tab; @@ -987,6 +995,8 @@ static int mana_cfg_vport_steering(struct mana_port_context *apc, mana_gd_init_req_hdr(&req->hdr, MANA_CONFIG_VPORT_RX, req_buf_size, sizeof(resp)); + req->hdr.req.msg_version = GDMA_MESSAGE_V2; + req->vport = apc->port_handle; req->num_indir_entries = num_entries; req->indir_tab_offset = sizeof(*req); @@ -996,6 +1006,7 @@ static int mana_cfg_vport_steering(struct mana_port_context *apc, req->update_hashkey = update_key; req->update_indir_tab = update_tab; req->default_rxobj = apc->default_rxobj; + req->cqe_coalescing_enable = 0; if (update_key) memcpy(&req->hashkey, apc->hashkey, MANA_HASH_KEY_SIZE); @@ -1457,6 +1468,12 @@ static void mana_rx_skb(void *buf_va, struct mana_rxcomp_oob *cqe, skb_set_hash(skb, hash_value, PKT_HASH_TYPE_L3); } + if (cqe->rx_vlantag_present) { + u16 vlan_tci = cqe->rx_vlan_id; + + __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vlan_tci); + } + u64_stats_update_begin(&rx_stats->syncp); rx_stats->packets++; rx_stats->bytes += pkt_len; @@ -2451,8 +2468,9 @@ static int mana_probe_port(struct mana_context *ac, int port_idx, ndev->hw_features |= NETIF_F_RXCSUM; ndev->hw_features |= NETIF_F_TSO | NETIF_F_TSO6; ndev->hw_features |= NETIF_F_RXHASH; - ndev->features = ndev->hw_features; - ndev->vlan_features = 0; + ndev->features = ndev->hw_features | NETIF_F_HW_VLAN_CTAG_TX | + NETIF_F_HW_VLAN_CTAG_RX; + ndev->vlan_features = ndev->features; ndev->xdp_features = NETDEV_XDP_ACT_BASIC | NETDEV_XDP_ACT_REDIRECT | NETDEV_XDP_ACT_NDO_XMIT; diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c index 1f5f00b3044180ff036082e073a7854c6e412492..56ccbd4c37fe6dab5c4df89d9c036270e3719455 100644 --- a/drivers/net/ethernet/mscc/ocelot.c +++ b/drivers/net/ethernet/mscc/ocelot.c @@ -2925,10 +2925,8 @@ int ocelot_init(struct ocelot *ocelot) } } - mutex_init(&ocelot->ptp_lock); mutex_init(&ocelot->mact_lock); mutex_init(&ocelot->fwd_domain_lock); - mutex_init(&ocelot->tas_lock); spin_lock_init(&ocelot->ptp_clock_lock); spin_lock_init(&ocelot->ts_id_lock); diff --git a/drivers/net/ethernet/mscc/ocelot_flower.c b/drivers/net/ethernet/mscc/ocelot_flower.c index ee052404eb55ae1d5499c65dc61ff87a22eb21cf..e0916afcddfb96c06d8d6ac7c075573135636f78 100644 --- a/drivers/net/ethernet/mscc/ocelot_flower.c +++ b/drivers/net/ethernet/mscc/ocelot_flower.c @@ -592,6 +592,16 @@ ocelot_flower_parse_key(struct ocelot *ocelot, int port, bool ingress, return -EOPNOTSUPP; } + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_META)) { + struct flow_match_meta match; + + flow_rule_match_meta(rule, &match); + if (match.mask->l2_miss) { + NL_SET_ERR_MSG_MOD(extack, "Can't match on \"l2_miss\""); + return -EOPNOTSUPP; + } + } + /* For VCAP ES0 (egress rewriter) we can match on the ingress port */ if (!ingress) { ret = ocelot_flower_parse_indev(ocelot, port, f, filter); diff --git a/drivers/net/ethernet/mscc/ocelot_mm.c b/drivers/net/ethernet/mscc/ocelot_mm.c index fb3145118d686fd7c3fa77748a34566a987601a5..c815ae64e39dd52d2b81c13fe9cce11435bf6bfd 100644 --- a/drivers/net/ethernet/mscc/ocelot_mm.c +++ b/drivers/net/ethernet/mscc/ocelot_mm.c @@ -67,10 +67,13 @@ void ocelot_port_update_active_preemptible_tcs(struct ocelot *ocelot, int port) val = mm->preemptible_tcs; /* Cut through switching doesn't work for preemptible priorities, - * so first make sure it is disabled. + * so first make sure it is disabled. Also, changing the preemptible + * TCs affects the oversized frame dropping logic, so that needs to be + * re-triggered. And since tas_guard_bands_update() also implicitly + * calls cut_through_fwd(), we don't need to explicitly call it. */ mm->active_preemptible_tcs = val; - ocelot->ops->cut_through_fwd(ocelot); + ocelot->ops->tas_guard_bands_update(ocelot, port); dev_dbg(ocelot->dev, "port %d %s/%s, MM TX %s, preemptible TCs 0x%x, active 0x%x\n", @@ -89,17 +92,14 @@ void ocelot_port_change_fp(struct ocelot *ocelot, int port, { struct ocelot_mm_state *mm = &ocelot->mm[port]; - mutex_lock(&ocelot->fwd_domain_lock); + lockdep_assert_held(&ocelot->fwd_domain_lock); if (mm->preemptible_tcs == preemptible_tcs) - goto out_unlock; + return; mm->preemptible_tcs = preemptible_tcs; ocelot_port_update_active_preemptible_tcs(ocelot, port); - -out_unlock: - mutex_unlock(&ocelot->fwd_domain_lock); } static void ocelot_mm_update_port_status(struct ocelot *ocelot, int port) diff --git a/drivers/net/ethernet/mscc/ocelot_ptp.c b/drivers/net/ethernet/mscc/ocelot_ptp.c index 2180ae94c74476387516581aafeb85f1db522605..cb32234a5bf1bcc01a827bf0a6450d7d2c37dfe3 100644 --- a/drivers/net/ethernet/mscc/ocelot_ptp.c +++ b/drivers/net/ethernet/mscc/ocelot_ptp.c @@ -439,8 +439,12 @@ static int ocelot_ipv6_ptp_trap_del(struct ocelot *ocelot, int port) static int ocelot_setup_ptp_traps(struct ocelot *ocelot, int port, bool l2, bool l4) { + struct ocelot_port *ocelot_port = ocelot->ports[port]; int err; + ocelot_port->trap_proto &= ~(OCELOT_PROTO_PTP_L2 | + OCELOT_PROTO_PTP_L4); + if (l2) err = ocelot_l2_ptp_trap_add(ocelot, port); else @@ -464,6 +468,11 @@ static int ocelot_setup_ptp_traps(struct ocelot *ocelot, int port, if (err) return err; + if (l2) + ocelot_port->trap_proto |= OCELOT_PROTO_PTP_L2; + if (l4) + ocelot_port->trap_proto |= OCELOT_PROTO_PTP_L4; + return 0; err_ipv6: @@ -474,10 +483,38 @@ static int ocelot_setup_ptp_traps(struct ocelot *ocelot, int port, return err; } +static int ocelot_traps_to_ptp_rx_filter(unsigned int proto) +{ + if ((proto & OCELOT_PROTO_PTP_L2) && (proto & OCELOT_PROTO_PTP_L4)) + return HWTSTAMP_FILTER_PTP_V2_EVENT; + else if (proto & OCELOT_PROTO_PTP_L2) + return HWTSTAMP_FILTER_PTP_V2_L2_EVENT; + else if (proto & OCELOT_PROTO_PTP_L4) + return HWTSTAMP_FILTER_PTP_V2_L4_EVENT; + + return HWTSTAMP_FILTER_NONE; +} + int ocelot_hwstamp_get(struct ocelot *ocelot, int port, struct ifreq *ifr) { - return copy_to_user(ifr->ifr_data, &ocelot->hwtstamp_config, - sizeof(ocelot->hwtstamp_config)) ? -EFAULT : 0; + struct ocelot_port *ocelot_port = ocelot->ports[port]; + struct hwtstamp_config cfg = {}; + + switch (ocelot_port->ptp_cmd) { + case IFH_REW_OP_TWO_STEP_PTP: + cfg.tx_type = HWTSTAMP_TX_ON; + break; + case IFH_REW_OP_ORIGIN_PTP: + cfg.tx_type = HWTSTAMP_TX_ONESTEP_SYNC; + break; + default: + cfg.tx_type = HWTSTAMP_TX_OFF; + break; + } + + cfg.rx_filter = ocelot_traps_to_ptp_rx_filter(ocelot_port->trap_proto); + + return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0; } EXPORT_SYMBOL(ocelot_hwstamp_get); @@ -509,8 +546,6 @@ int ocelot_hwstamp_set(struct ocelot *ocelot, int port, struct ifreq *ifr) return -ERANGE; } - mutex_lock(&ocelot->ptp_lock); - switch (cfg.rx_filter) { case HWTSTAMP_FILTER_NONE: break; @@ -531,28 +566,14 @@ int ocelot_hwstamp_set(struct ocelot *ocelot, int port, struct ifreq *ifr) l4 = true; break; default: - mutex_unlock(&ocelot->ptp_lock); return -ERANGE; } err = ocelot_setup_ptp_traps(ocelot, port, l2, l4); - if (err) { - mutex_unlock(&ocelot->ptp_lock); + if (err) return err; - } - if (l2 && l4) - cfg.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT; - else if (l2) - cfg.rx_filter = HWTSTAMP_FILTER_PTP_V2_L2_EVENT; - else if (l4) - cfg.rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_EVENT; - else - cfg.rx_filter = HWTSTAMP_FILTER_NONE; - - /* Commit back the result & save it */ - memcpy(&ocelot->hwtstamp_config, &cfg, sizeof(cfg)); - mutex_unlock(&ocelot->ptp_lock); + cfg.rx_filter = ocelot_traps_to_ptp_rx_filter(ocelot_port->trap_proto); return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0; } @@ -824,11 +845,6 @@ int ocelot_init_timestamp(struct ocelot *ocelot, ocelot_write(ocelot, PTP_CFG_MISC_PTP_EN, PTP_CFG_MISC); - /* There is no device reconfiguration, PTP Rx stamping is always - * enabled. - */ - ocelot->hwtstamp_config.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT; - return 0; } EXPORT_SYMBOL(ocelot_init_timestamp); diff --git a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c index c5687d94ea88506e408fe7a89067f2ddbf005c35..7b7e1c5b00f4728cccfb693e2ab4e32b9613616e 100644 --- a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c +++ b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c @@ -66,6 +66,7 @@ #include #include #include +#include #include #include #include diff --git a/drivers/net/ethernet/netronome/nfp/nfp_devlink.c b/drivers/net/ethernet/netronome/nfp/nfp_devlink.c index bf6bae5571585c684fa0cd9c90b844539f447142..8c6954c58a8863b8466179b0a751a16a975484cc 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_devlink.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_devlink.c @@ -311,8 +311,6 @@ nfp_devlink_flash_update(struct devlink *devlink, } const struct devlink_ops nfp_devlink_ops = { - .port_split = nfp_devlink_port_split, - .port_unsplit = nfp_devlink_port_unsplit, .sb_pool_get = nfp_devlink_sb_pool_get, .sb_pool_set = nfp_devlink_sb_pool_set, .eswitch_mode_get = nfp_devlink_eswitch_mode_get, @@ -321,6 +319,11 @@ const struct devlink_ops nfp_devlink_ops = { .flash_update = nfp_devlink_flash_update, }; +static const struct devlink_port_ops nfp_devlink_port_ops = { + .port_split = nfp_devlink_port_split, + .port_unsplit = nfp_devlink_port_unsplit, +}; + int nfp_devlink_port_register(struct nfp_app *app, struct nfp_port *port) { struct devlink_port_attrs attrs = {}; @@ -351,7 +354,8 @@ int nfp_devlink_port_register(struct nfp_app *app, struct nfp_port *port) devlink = priv_to_devlink(app->pf); - return devl_port_register(devlink, &port->dl_port, port->eth_id); + return devl_port_register_with_ops(devlink, &port->dl_port, + port->eth_id, &nfp_devlink_port_ops); } void nfp_devlink_port_unregister(struct nfp_port *port) diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c index 62f0bf91d1e1e52d9686bc7f6fa5249fdefd86c5..6b1fb57084347bee2ceb5f75b7eca5a29b020423 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c @@ -53,6 +53,8 @@ #include "crypto/crypto.h" #include "crypto/fw.h" +static int nfp_net_mc_unsync(struct net_device *netdev, const unsigned char *addr); + /** * nfp_net_get_fw_version() - Read and parse the FW version * @fw_ver: Output fw_version structure to read to @@ -598,7 +600,7 @@ nfp_net_tls_tx(struct nfp_net_dp *dp, struct nfp_net_r_vector *r_vec, if (likely(!dp->ktls_tx)) return skb; - if (!skb->sk || !tls_is_sk_tx_device_offloaded(skb->sk)) + if (!tls_is_skb_tx_device_offloaded(skb)) return skb; datalen = skb->len - skb_tcp_all_headers(skb); @@ -666,7 +668,7 @@ void nfp_net_tls_tx_undo(struct sk_buff *skb, u64 tls_handle) if (!tls_handle) return; - if (WARN_ON_ONCE(!skb->sk || !tls_is_sk_tx_device_offloaded(skb->sk))) + if (WARN_ON_ONCE(!tls_is_skb_tx_device_offloaded(skb))) return; datalen = skb->len - skb_tcp_all_headers(skb); @@ -1084,6 +1086,9 @@ static int nfp_net_netdev_close(struct net_device *netdev) /* Step 2: Tell NFP */ + if (nn->cap_w1 & NFP_NET_CFG_CTRL_MCAST_FILTER) + __dev_mc_unsync(netdev, nfp_net_mc_unsync); + nfp_net_clear_config_and_disable(nn); nfp_port_configure(netdev, false); @@ -2418,6 +2423,8 @@ static void nfp_net_rss_init(struct nfp_net *nn) /* Enable IPv4/IPv6 TCP by default */ nn->rss_cfg = NFP_NET_CFG_RSS_IPV4_TCP | NFP_NET_CFG_RSS_IPV6_TCP | + NFP_NET_CFG_RSS_IPV4_UDP | + NFP_NET_CFG_RSS_IPV6_UDP | FIELD_PREP(NFP_NET_CFG_RSS_HFUNC, nn->rss_hfunc) | NFP_NET_CFG_RSS_MASK; } diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c b/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c index dfedb52b7e70ada35f1fecd936b893c4b7b18721..e75cbb287625fc67214eee08e9eef89eebd178ab 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c @@ -436,49 +436,41 @@ static void nfp_add_media_link_mode(struct nfp_port *port, struct nfp_eth_table_port *eth_port, struct ethtool_link_ksettings *cmd) { - u64 supported_modes[2], advertised_modes[2]; - struct nfp_eth_media_buf ethm = { - .eth_index = eth_port->eth_index, - }; - struct nfp_cpp *cpp = port->app->cpp; - - if (nfp_eth_read_media(cpp, ðm)) { - bitmap_fill(port->speed_bitmap, NFP_SUP_SPEED_NUMBER); - return; - } - bitmap_zero(port->speed_bitmap, NFP_SUP_SPEED_NUMBER); - for (u32 i = 0; i < 2; i++) { - supported_modes[i] = le64_to_cpu(ethm.supported_modes[i]); - advertised_modes[i] = le64_to_cpu(ethm.advertised_modes[i]); - } - for (u32 i = 0; i < NFP_MEDIA_LINK_MODES_NUMBER; i++) { if (i < 64) { - if (supported_modes[0] & BIT_ULL(i)) { + if (eth_port->link_modes_supp[0] & BIT_ULL(i)) { __set_bit(nfp_eth_media_table[i].ethtool_link_mode, cmd->link_modes.supported); __set_bit(nfp_eth_media_table[i].speed, port->speed_bitmap); } - if (advertised_modes[0] & BIT_ULL(i)) + if (eth_port->link_modes_ad[0] & BIT_ULL(i)) __set_bit(nfp_eth_media_table[i].ethtool_link_mode, cmd->link_modes.advertising); } else { - if (supported_modes[1] & BIT_ULL(i - 64)) { + if (eth_port->link_modes_supp[1] & BIT_ULL(i - 64)) { __set_bit(nfp_eth_media_table[i].ethtool_link_mode, cmd->link_modes.supported); __set_bit(nfp_eth_media_table[i].speed, port->speed_bitmap); } - if (advertised_modes[1] & BIT_ULL(i - 64)) + if (eth_port->link_modes_ad[1] & BIT_ULL(i - 64)) __set_bit(nfp_eth_media_table[i].ethtool_link_mode, cmd->link_modes.advertising); } } + + /* We take all speeds as supported when it fails to read + * link modes due to old management firmware that doesn't + * support link modes reading or error occurring, so that + * speed change of this port is allowed. + */ + if (bitmap_empty(port->speed_bitmap, NFP_SUP_SPEED_NUMBER)) + bitmap_fill(port->speed_bitmap, NFP_SUP_SPEED_NUMBER); } /** diff --git a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.h b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.h index 781edc451bd436ddae8aac50d6710725b5251a6b..6e044ac049172e3713ee70c09d0e94a110115cd7 100644 --- a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.h +++ b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.h @@ -196,6 +196,9 @@ enum nfp_ethtool_link_mode_list { * subports) * @ports.is_split: is interface part of a split port * @ports.fec_modes_supported: bitmap of FEC modes supported + * + * @ports.link_modes_supp: bitmap of link modes supported + * @ports.link_modes_ad: bitmap of link modes advertised */ struct nfp_eth_table { unsigned int count; @@ -235,6 +238,9 @@ struct nfp_eth_table { bool is_split; unsigned int fec_modes_supported; + + u64 link_modes_supp[2]; + u64 link_modes_ad[2]; } ports[]; }; @@ -313,7 +319,6 @@ struct nfp_eth_media_buf { }; int nfp_nsp_read_media(struct nfp_nsp *state, void *buf, unsigned int size); -int nfp_eth_read_media(struct nfp_cpp *cpp, struct nfp_eth_media_buf *ethm); #define NFP_NSP_VERSION_BUFSZ 1024 /* reasonable size, not in the ABI */ diff --git a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp_eth.c b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp_eth.c index 570ac1bb2122f72fe429fb2f2b240c821a77caf8..9d62085d772a27b4e8666600c1432b5bb793fc2d 100644 --- a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp_eth.c +++ b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp_eth.c @@ -227,6 +227,30 @@ nfp_eth_calc_port_type(struct nfp_cpp *cpp, struct nfp_eth_table_port *entry) entry->port_type = PORT_DA; } +static void +nfp_eth_read_media(struct nfp_cpp *cpp, struct nfp_nsp *nsp, struct nfp_eth_table_port *entry) +{ + struct nfp_eth_media_buf ethm = { + .eth_index = entry->eth_index, + }; + unsigned int i; + int ret; + + if (!nfp_nsp_has_read_media(nsp)) + return; + + ret = nfp_nsp_read_media(nsp, ðm, sizeof(ethm)); + if (ret) { + nfp_err(cpp, "Reading media link modes failed: %d\n", ret); + return; + } + + for (i = 0; i < 2; i++) { + entry->link_modes_supp[i] = le64_to_cpu(ethm.supported_modes[i]); + entry->link_modes_ad[i] = le64_to_cpu(ethm.advertised_modes[i]); + } +} + /** * nfp_eth_read_ports() - retrieve port information * @cpp: NFP CPP handle @@ -293,8 +317,10 @@ __nfp_eth_read_ports(struct nfp_cpp *cpp, struct nfp_nsp *nsp) &table->ports[j++]); nfp_eth_calc_port_geometry(cpp, table); - for (i = 0; i < table->count; i++) + for (i = 0; i < table->count; i++) { nfp_eth_calc_port_type(cpp, &table->ports[i]); + nfp_eth_read_media(cpp, nsp, &table->ports[i]); + } kfree(entries); @@ -647,29 +673,3 @@ int __nfp_eth_set_split(struct nfp_nsp *nsp, unsigned int lanes) return NFP_ETH_SET_BIT_CONFIG(nsp, NSP_ETH_RAW_PORT, NSP_ETH_PORT_LANES, lanes, NSP_ETH_CTRL_SET_LANES); } - -int nfp_eth_read_media(struct nfp_cpp *cpp, struct nfp_eth_media_buf *ethm) -{ - struct nfp_nsp *nsp; - int ret; - - nsp = nfp_nsp_open(cpp); - if (IS_ERR(nsp)) { - nfp_err(cpp, "Failed to access the NSP: %pe\n", nsp); - return PTR_ERR(nsp); - } - - if (!nfp_nsp_has_read_media(nsp)) { - nfp_warn(cpp, "Reading media link modes not supported. Please update flash\n"); - ret = -EOPNOTSUPP; - goto exit_close_nsp; - } - - ret = nfp_nsp_read_media(nsp, ethm, sizeof(*ethm)); - if (ret) - nfp_err(cpp, "Reading media link modes failed: %pe\n", ERR_PTR(ret)); - -exit_close_nsp: - nfp_nsp_close(nsp); - return ret; -} diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/Kconfig b/drivers/net/ethernet/oki-semi/pch_gbe/Kconfig index 4e18b64dceb9a56b23adad2e01b2dce17c6fcf53..9651cc714ef267bccc5cb5adb1c6ab883b81f8d2 100644 --- a/drivers/net/ethernet/oki-semi/pch_gbe/Kconfig +++ b/drivers/net/ethernet/oki-semi/pch_gbe/Kconfig @@ -5,7 +5,7 @@ config PCH_GBE tristate "OKI SEMICONDUCTOR IOH(ML7223/ML7831) GbE" - depends on PCI && (X86_32 || COMPILE_TEST) + depends on PCI && (MIPS_GENERIC || X86_32 || COMPILE_TEST) depends on PTP_1588_CLOCK select MII select PTP_1588_CLOCK_PCH diff --git a/drivers/net/ethernet/pensando/ionic/ionic_bus_pci.c b/drivers/net/ethernet/pensando/ionic/ionic_bus_pci.c index b8678da1cce528ed8029db44e0fa1c39342775cb..ab7d217b98b37bc14704690b6debe35125a0afb4 100644 --- a/drivers/net/ethernet/pensando/ionic/ionic_bus_pci.c +++ b/drivers/net/ethernet/pensando/ionic/ionic_bus_pci.c @@ -353,12 +353,6 @@ static int ionic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ionic_reset(ionic); err_out_teardown: ionic_dev_teardown(ionic); - pci_clear_master(pdev); - /* Don't fail the probe for these errors, keep - * the hw interface around for inspection - */ - return 0; - err_out_unmap_bars: ionic_unmap_bars(ionic); err_out_pci_release_regions: diff --git a/drivers/net/ethernet/pensando/ionic/ionic_ethtool.c b/drivers/net/ethernet/pensando/ionic/ionic_ethtool.c index 9b2b96fa36af831d2b669d957bf7cf13e2bcb2af..3a6b0a9bc24147f8ef9eb156cc0997ee10384676 100644 --- a/drivers/net/ethernet/pensando/ionic/ionic_ethtool.c +++ b/drivers/net/ethernet/pensando/ionic/ionic_ethtool.c @@ -104,6 +104,15 @@ static void ionic_get_regs(struct net_device *netdev, struct ethtool_regs *regs, memcpy_fromio(p + offset, lif->ionic->idev.dev_cmd_regs->words, size); } +static void ionic_get_link_ext_stats(struct net_device *netdev, + struct ethtool_link_ext_stats *stats) +{ + struct ionic_lif *lif = netdev_priv(netdev); + + if (lif->ionic->pdev->is_physfn) + stats->link_down_events = lif->link_down_count; +} + static int ionic_get_link_ksettings(struct net_device *netdev, struct ethtool_link_ksettings *ks) { @@ -1074,6 +1083,7 @@ static const struct ethtool_ops ionic_ethtool_ops = { .get_regs_len = ionic_get_regs_len, .get_regs = ionic_get_regs, .get_link = ethtool_op_get_link, + .get_link_ext_stats = ionic_get_link_ext_stats, .get_link_ksettings = ionic_get_link_ksettings, .set_link_ksettings = ionic_set_link_ksettings, .get_coalesce = ionic_get_coalesce, diff --git a/drivers/net/ethernet/pensando/ionic/ionic_lif.c b/drivers/net/ethernet/pensando/ionic/ionic_lif.c index 957027e546b306dbb027997e2fcc3e932d86f776..612b0015dc43eb261f1cc603a46aa6eed6c6f489 100644 --- a/drivers/net/ethernet/pensando/ionic/ionic_lif.c +++ b/drivers/net/ethernet/pensando/ionic/ionic_lif.c @@ -168,6 +168,7 @@ static void ionic_link_status_check(struct ionic_lif *lif) } } else { if (netif_carrier_ok(netdev)) { + lif->link_down_count++; netdev_info(netdev, "Link down\n"); netif_carrier_off(netdev); } @@ -474,11 +475,6 @@ static void ionic_qcqs_free(struct ionic_lif *lif) static void ionic_link_qcq_interrupts(struct ionic_qcq *src_qcq, struct ionic_qcq *n_qcq) { - if (WARN_ON(n_qcq->flags & IONIC_QCQ_F_INTR)) { - ionic_intr_free(n_qcq->cq.lif->ionic, n_qcq->intr.index); - n_qcq->flags &= ~IONIC_QCQ_F_INTR; - } - n_qcq->intr.vector = src_qcq->intr.vector; n_qcq->intr.index = src_qcq->intr.index; n_qcq->napi_qcq = src_qcq->napi_qcq; @@ -560,7 +556,7 @@ static int ionic_qcq_alloc(struct ionic_lif *lif, unsigned int type, new->q.dev = dev; new->flags = flags; - new->q.info = vzalloc(num_descs * sizeof(*new->q.info)); + new->q.info = vcalloc(num_descs, sizeof(*new->q.info)); if (!new->q.info) { netdev_err(lif->netdev, "Cannot allocate queue info\n"); err = -ENOMEM; @@ -581,7 +577,7 @@ static int ionic_qcq_alloc(struct ionic_lif *lif, unsigned int type, if (err) goto err_out; - new->cq.info = vzalloc(num_descs * sizeof(*new->cq.info)); + new->cq.info = vcalloc(num_descs, sizeof(*new->cq.info)); if (!new->cq.info) { netdev_err(lif->netdev, "Cannot allocate completion queue info\n"); err = -ENOMEM; diff --git a/drivers/net/ethernet/pensando/ionic/ionic_lif.h b/drivers/net/ethernet/pensando/ionic/ionic_lif.h index c9c4c46d5a166fcb189da994b30a35b7f3645b78..fd2ea670e7d84c76e4ef941a518a11172770032d 100644 --- a/drivers/net/ethernet/pensando/ionic/ionic_lif.h +++ b/drivers/net/ethernet/pensando/ionic/ionic_lif.h @@ -201,6 +201,7 @@ struct ionic_lif { u64 hw_features; bool registered; u16 lif_type; + unsigned int link_down_count; unsigned int nmcast; unsigned int nucast; unsigned int nvlans; diff --git a/drivers/net/ethernet/qualcomm/qca_spi.c b/drivers/net/ethernet/qualcomm/qca_spi.c index c865a4be05eec2d4144792179a0517c997f66d95..4a1b94e5a8ea9d7f9c6c0518699c364a17b77b2b 100644 --- a/drivers/net/ethernet/qualcomm/qca_spi.c +++ b/drivers/net/ethernet/qualcomm/qca_spi.c @@ -582,8 +582,7 @@ qcaspi_spi_thread(void *data) while (!kthread_should_stop()) { set_current_state(TASK_INTERRUPTIBLE); if ((qca->intr_req == qca->intr_svc) && - (qca->txr.skb[qca->txr.head] == NULL) && - (qca->sync == QCASPI_SYNC_READY)) + !qca->txr.skb[qca->txr.head]) schedule(); set_current_state(TASK_RUNNING); diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c index 4b19803a7dd011c3fa13f2c65b6f886e8a291b7d..9445f04f8d48c17f616163e7c2bfc392f8086eca 100644 --- a/drivers/net/ethernet/realtek/r8169_main.c +++ b/drivers/net/ethernet/realtek/r8169_main.c @@ -5164,6 +5164,7 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) int jumbo_max, region, rc; enum mac_version chipset; struct net_device *dev; + u32 txconfig; u16 xid; dev = devm_alloc_etherdev(&pdev->dev, sizeof (*tp)); @@ -5195,38 +5196,35 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) /* enable device (incl. PCI PM wakeup and hotplug setup) */ rc = pcim_enable_device(pdev); - if (rc < 0) { - dev_err(&pdev->dev, "enable failure\n"); - return rc; - } + if (rc < 0) + return dev_err_probe(&pdev->dev, rc, "enable failure\n"); if (pcim_set_mwi(pdev) < 0) dev_info(&pdev->dev, "Mem-Wr-Inval unavailable\n"); /* use first MMIO region */ region = ffs(pci_select_bars(pdev, IORESOURCE_MEM)) - 1; - if (region < 0) { - dev_err(&pdev->dev, "no MMIO resource found\n"); - return -ENODEV; - } + if (region < 0) + return dev_err_probe(&pdev->dev, -ENODEV, "no MMIO resource found\n"); rc = pcim_iomap_regions(pdev, BIT(region), KBUILD_MODNAME); - if (rc < 0) { - dev_err(&pdev->dev, "cannot remap MMIO, aborting\n"); - return rc; - } + if (rc < 0) + return dev_err_probe(&pdev->dev, rc, "cannot remap MMIO, aborting\n"); tp->mmio_addr = pcim_iomap_table(pdev)[region]; - xid = (RTL_R32(tp, TxConfig) >> 20) & 0xfcf; + txconfig = RTL_R32(tp, TxConfig); + if (txconfig == ~0U) + return dev_err_probe(&pdev->dev, -EIO, "PCI read failed\n"); + + xid = (txconfig >> 20) & 0xfcf; /* Identify chip attached to board */ chipset = rtl8169_get_mac_version(xid, tp->supports_gmii); - if (chipset == RTL_GIGA_MAC_NONE) { - dev_err(&pdev->dev, "unknown chip XID %03x, contact r8169 maintainers (see MAINTAINERS file)\n", xid); - return -ENODEV; - } - + if (chipset == RTL_GIGA_MAC_NONE) + return dev_err_probe(&pdev->dev, -ENODEV, + "unknown chip XID %03x, contact r8169 maintainers (see MAINTAINERS file)\n", + xid); tp->mac_version = chipset; tp->dash_type = rtl_check_dash(tp); @@ -5246,10 +5244,9 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) rtl_hw_reset(tp); rc = rtl_alloc_irq(tp); - if (rc < 0) { - dev_err(&pdev->dev, "Can't allocate interrupt\n"); - return rc; - } + if (rc < 0) + return dev_err_probe(&pdev->dev, rc, "Can't allocate interrupt\n"); + tp->irq = pci_irq_vector(pdev, 0); INIT_WORK(&tp->wk.work, rtl_task); diff --git a/drivers/net/ethernet/renesas/rswitch.c b/drivers/net/ethernet/renesas/rswitch.c index fa6d6202b129d083a025cdec6cf1ff9f30aaddba..4e412ac0965a4f7d0b45652f2cfbc7cd3273deff 100644 --- a/drivers/net/ethernet/renesas/rswitch.c +++ b/drivers/net/ethernet/renesas/rswitch.c @@ -90,6 +90,11 @@ static int rswitch_bpool_config(struct rswitch_private *priv) return rswitch_reg_wait(priv->addr, CABPIRM, CABPIRM_BPR, CABPIRM_BPR); } +static void rswitch_coma_init(struct rswitch_private *priv) +{ + iowrite32(CABPPFLC_INIT_VALUE, priv->addr + CABPPFLC0); +} + /* R-Switch-2 block (TOP) */ static void rswitch_top_init(struct rswitch_private *priv) { @@ -156,24 +161,6 @@ static int rswitch_gwca_axi_ram_reset(struct rswitch_private *priv) return rswitch_reg_wait(priv->addr, GWARIRM, GWARIRM_ARR, GWARIRM_ARR); } -static void rswitch_gwca_set_rate_limit(struct rswitch_private *priv, int rate) -{ - u32 gwgrlulc, gwgrlc; - - switch (rate) { - case 1000: - gwgrlulc = 0x0000005f; - gwgrlc = 0x00010260; - break; - default: - dev_err(&priv->pdev->dev, "%s: This rate is not supported (%d)\n", __func__, rate); - return; - } - - iowrite32(gwgrlulc, priv->addr + GWGRLULC); - iowrite32(gwgrlc, priv->addr + GWGRLC); -} - static bool rswitch_is_any_data_irq(struct rswitch_private *priv, u32 *dis, bool tx) { u32 *mask = tx ? priv->gwca.tx_irq_bits : priv->gwca.rx_irq_bits; @@ -391,7 +378,7 @@ static int rswitch_gwca_queue_format(struct net_device *ndev, linkfix->die_dt = DT_LINKFIX; rswitch_desc_set_dptr(linkfix, gq->ring_dma); - iowrite32(GWDCC_BALR | (gq->dir_tx ? GWDCC_DQT : 0) | GWDCC_EDE, + iowrite32(GWDCC_BALR | (gq->dir_tx ? GWDCC_DCP(GWCA_IPV_NUM) | GWDCC_DQT : 0) | GWDCC_EDE, priv->addr + GWDCC_OFFS(gq->index)); return 0; @@ -489,7 +476,8 @@ static int rswitch_gwca_queue_ext_ts_format(struct net_device *ndev, linkfix->die_dt = DT_LINKFIX; rswitch_desc_set_dptr(linkfix, gq->ring_dma); - iowrite32(GWDCC_BALR | (gq->dir_tx ? GWDCC_DQT : 0) | GWDCC_ETS | GWDCC_EDE, + iowrite32(GWDCC_BALR | (gq->dir_tx ? GWDCC_DCP(GWCA_IPV_NUM) | GWDCC_DQT : 0) | + GWDCC_ETS | GWDCC_EDE, priv->addr + GWDCC_OFFS(gq->index)); return 0; @@ -660,7 +648,8 @@ static int rswitch_gwca_hw_init(struct rswitch_private *priv) iowrite32(lower_32_bits(priv->gwca.ts_queue.ring_dma), priv->addr + GWTDCAC10); iowrite32(upper_32_bits(priv->gwca.ts_queue.ring_dma), priv->addr + GWTDCAC00); iowrite32(GWCA_TS_IRQ_BIT, priv->addr + GWTSDCC0); - rswitch_gwca_set_rate_limit(priv, priv->gwca.speed); + + iowrite32(GWTPC_PPPL(GWCA_IPV_NUM), priv->addr + GWTPC0); for (i = 0; i < RSWITCH_NUM_PORTS; i++) { err = rswitch_rxdmac_init(priv, i); @@ -740,7 +729,7 @@ static bool rswitch_rx(struct net_device *ndev, int *quota) } skb_put(skb, pkt_len); skb->protocol = eth_type_trans(skb, ndev); - netif_receive_skb(skb); + napi_gro_receive(&rdev->napi, skb); rdev->ndev->stats.rx_packets++; rdev->ndev->stats.rx_bytes += pkt_len; @@ -1513,7 +1502,8 @@ static netdev_tx_t rswitch_start_xmit(struct sk_buff *skb, struct net_device *nd rswitch_desc_set_dptr(&desc->desc, dma_addr); desc->desc.info_ds = cpu_to_le16(skb->len); - desc->info1 = cpu_to_le64(INFO1_DV(BIT(rdev->etha->index)) | INFO1_FMT); + desc->info1 = cpu_to_le64(INFO1_DV(BIT(rdev->etha->index)) | + INFO1_IPV(GWCA_IPV_NUM) | INFO1_FMT); if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) { struct rswitch_gwca_ts_info *ts_info; @@ -1783,6 +1773,8 @@ static int rswitch_init(struct rswitch_private *priv) if (err < 0) return err; + rswitch_coma_init(priv); + err = rswitch_gwca_linkfix_alloc(priv); if (err < 0) return -ENOMEM; diff --git a/drivers/net/ethernet/renesas/rswitch.h b/drivers/net/ethernet/renesas/rswitch.h index b3e0411b408ef887b72c2ad0f343273a1f085178..bb9ed971a97cace8159c0ccff03f7adef03bb4b0 100644 --- a/drivers/net/ethernet/renesas/rswitch.h +++ b/drivers/net/ethernet/renesas/rswitch.h @@ -48,6 +48,7 @@ #define GWCA_NUM_IRQS 8 #define GWCA_INDEX 0 #define AGENT_INDEX_GWCA 3 +#define GWCA_IPV_NUM 0 #define GWRO RSWITCH_GWCA0_OFFSET #define GWCA_TS_IRQ_RESOURCE_NAME "gwca0_rxts0" @@ -768,11 +769,14 @@ enum rswitch_gwca_mode { #define GWARIRM_ARR BIT(1) #define GWDCC_BALR BIT(24) +#define GWDCC_DCP_MASK GENMASK(18, 16) +#define GWDCC_DCP(prio) FIELD_PREP(GWDCC_DCP_MASK, (prio)) #define GWDCC_DQT BIT(11) #define GWDCC_ETS BIT(9) #define GWDCC_EDE BIT(8) #define GWTRC(queue) (GWTRC0 + (queue) / 32 * 4) +#define GWTPC_PPPL(ipv) BIT(ipv) #define GWDCC_OFFS(queue) (GWDCC0 + (queue) * 4) #define GWDIS(i) (GWDIS0 + (i) * 0x10) @@ -789,6 +793,8 @@ enum rswitch_gwca_mode { #define CABPIRM_BPIOG BIT(0) #define CABPIRM_BPR BIT(1) +#define CABPPFLC_INIT_VALUE 0x00800080 + /* MFWD */ #define FWPC0_LTHTA BIT(0) #define FWPC0_IP4UE BIT(3) @@ -863,6 +869,7 @@ enum DIE_DT { /* For transmission */ #define INFO1_TSUN(val) ((u64)(val) << 8ULL) +#define INFO1_IPV(prio) ((u64)(prio) << 28ULL) #define INFO1_CSD0(index) ((u64)(index) << 32ULL) #define INFO1_CSD1(index) ((u64)(index) << 40ULL) #define INFO1_DV(port_vector) ((u64)(port_vector) << 48ULL) diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_common.h b/drivers/net/ethernet/samsung/sxgbe/sxgbe_common.h index 0f45107db8dda3027f986faae1d234a7af99bd96..d14e0cfc3a6b189b8796bb91cffc6283e771d202 100644 --- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_common.h +++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_common.h @@ -511,7 +511,7 @@ struct sxgbe_priv_data { struct sxgbe_priv_data *sxgbe_drv_probe(struct device *device, struct sxgbe_plat_data *plat_dat, void __iomem *addr); -int sxgbe_drv_remove(struct net_device *ndev); +void sxgbe_drv_remove(struct net_device *ndev); void sxgbe_set_ethtool_ops(struct net_device *netdev); int sxgbe_mdio_unregister(struct net_device *ndev); int sxgbe_mdio_register(struct net_device *ndev); diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c b/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c index 9664f029fa161c08d941500d47fe25957cc72cb5..71439825ea4e08f232c369166a279eb57328ac85 100644 --- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c +++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c @@ -2203,7 +2203,7 @@ struct sxgbe_priv_data *sxgbe_drv_probe(struct device *device, * Description: this function resets the TX/RX processes, disables the MAC RX/TX * changes the link status, releases the DMA descriptor rings. */ -int sxgbe_drv_remove(struct net_device *ndev) +void sxgbe_drv_remove(struct net_device *ndev) { struct sxgbe_priv_data *priv = netdev_priv(ndev); u8 queue_num; @@ -2231,8 +2231,6 @@ int sxgbe_drv_remove(struct net_device *ndev) kfree(priv->hw); free_netdev(ndev); - - return 0; } #ifdef CONFIG_PM diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_platform.c b/drivers/net/ethernet/samsung/sxgbe/sxgbe_platform.c index 4e5526303f0764e68175b2ffe27aabcec9856d2c..fb59ff94509a767d6c982c766a63669bc6dcee5c 100644 --- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_platform.c +++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_platform.c @@ -172,9 +172,10 @@ static int sxgbe_platform_probe(struct platform_device *pdev) static int sxgbe_platform_remove(struct platform_device *pdev) { struct net_device *ndev = platform_get_drvdata(pdev); - int ret = sxgbe_drv_remove(ndev); - return ret; + sxgbe_drv_remove(ndev); + + return 0; } #ifdef CONFIG_PM diff --git a/drivers/net/ethernet/sfc/Kconfig b/drivers/net/ethernet/sfc/Kconfig index 4af36ba8906baaf687c5a6458a87a430648e198e..3eb55dcfa8a61e731b68f289299dcd3719f3ce51 100644 --- a/drivers/net/ethernet/sfc/Kconfig +++ b/drivers/net/ethernet/sfc/Kconfig @@ -50,6 +50,7 @@ config SFC_MCDI_MON config SFC_SRIOV bool "Solarflare SFC9100-family SR-IOV support" depends on SFC && PCI_IOV + depends on INET default y help This enables support for the Single Root I/O Virtualization diff --git a/drivers/net/ethernet/sfc/Makefile b/drivers/net/ethernet/sfc/Makefile index 55b9c73cd8ef40669062341df66138ec377ce067..16293b58e0a89aecd0c7bd9c409f8574f38b9300 100644 --- a/drivers/net/ethernet/sfc/Makefile +++ b/drivers/net/ethernet/sfc/Makefile @@ -10,7 +10,8 @@ sfc-y += efx.o efx_common.o efx_channels.o nic.o \ efx_devlink.o sfc-$(CONFIG_SFC_MTD) += mtd.o sfc-$(CONFIG_SFC_SRIOV) += sriov.o ef10_sriov.o ef100_sriov.o ef100_rep.o \ - mae.o tc.o tc_bindings.o tc_counters.o + mae.o tc.o tc_bindings.o tc_counters.o \ + tc_encap_actions.o obj-$(CONFIG_SFC) += sfc.o diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c index d30459dbfe8f838e7677d26038824484353f5eff..8c019f382a7f34c476383e68ebd042737d521916 100644 --- a/drivers/net/ethernet/sfc/ef10.c +++ b/drivers/net/ethernet/sfc/ef10.c @@ -1297,8 +1297,10 @@ static void efx_ef10_fini_nic(struct efx_nic *efx) { struct efx_ef10_nic_data *nic_data = efx->nic_data; + spin_lock_bh(&efx->stats_lock); kfree(nic_data->mc_stats); nic_data->mc_stats = NULL; + spin_unlock_bh(&efx->stats_lock); } static int efx_ef10_init_nic(struct efx_nic *efx) @@ -1852,9 +1854,14 @@ static size_t efx_ef10_update_stats_pf(struct efx_nic *efx, u64 *full_stats, efx_ef10_get_stat_mask(efx, mask); - efx_nic_copy_stats(efx, nic_data->mc_stats); - efx_nic_update_stats(efx_ef10_stat_desc, EF10_STAT_COUNT, - mask, stats, nic_data->mc_stats, false); + /* If NIC was fini'd (probably resetting), then we can't read + * updated stats right now. + */ + if (nic_data->mc_stats) { + efx_nic_copy_stats(efx, nic_data->mc_stats); + efx_nic_update_stats(efx_ef10_stat_desc, EF10_STAT_COUNT, + mask, stats, nic_data->mc_stats, false); + } /* Update derived statistics */ efx_nic_fix_nodesc_drop_stat(efx, @@ -2950,7 +2957,7 @@ static u32 efx_ef10_extract_event_ts(efx_qword_t *event) return tstamp; } -static void +static int efx_ef10_handle_tx_event(struct efx_channel *channel, efx_qword_t *event) { struct efx_nic *efx = channel->efx; @@ -2958,13 +2965,14 @@ efx_ef10_handle_tx_event(struct efx_channel *channel, efx_qword_t *event) unsigned int tx_ev_desc_ptr; unsigned int tx_ev_q_label; unsigned int tx_ev_type; + int work_done; u64 ts_part; if (unlikely(READ_ONCE(efx->reset_pending))) - return; + return 0; if (unlikely(EFX_QWORD_FIELD(*event, ESF_DZ_TX_DROP_EVENT))) - return; + return 0; /* Get the transmit queue */ tx_ev_q_label = EFX_QWORD_FIELD(*event, ESF_DZ_TX_QLABEL); @@ -2973,8 +2981,7 @@ efx_ef10_handle_tx_event(struct efx_channel *channel, efx_qword_t *event) if (!tx_queue->timestamping) { /* Transmit completion */ tx_ev_desc_ptr = EFX_QWORD_FIELD(*event, ESF_DZ_TX_DESCR_INDX); - efx_xmit_done(tx_queue, tx_ev_desc_ptr & tx_queue->ptr_mask); - return; + return efx_xmit_done(tx_queue, tx_ev_desc_ptr & tx_queue->ptr_mask); } /* Transmit timestamps are only available for 8XXX series. They result @@ -3000,6 +3007,7 @@ efx_ef10_handle_tx_event(struct efx_channel *channel, efx_qword_t *event) * fields in the event. */ tx_ev_type = EFX_QWORD_FIELD(*event, ESF_EZ_TX_SOFT1); + work_done = 0; switch (tx_ev_type) { case TX_TIMESTAMP_EVENT_TX_EV_COMPLETION: @@ -3016,6 +3024,7 @@ efx_ef10_handle_tx_event(struct efx_channel *channel, efx_qword_t *event) tx_queue->completed_timestamp_major = ts_part; efx_xmit_done_single(tx_queue); + work_done = 1; break; default: @@ -3026,6 +3035,8 @@ efx_ef10_handle_tx_event(struct efx_channel *channel, efx_qword_t *event) EFX_QWORD_VAL(*event)); break; } + + return work_done; } static void @@ -3081,13 +3092,16 @@ static void efx_ef10_handle_driver_generated_event(struct efx_channel *channel, } } +#define EFX_NAPI_MAX_TX 512 + static int efx_ef10_ev_process(struct efx_channel *channel, int quota) { struct efx_nic *efx = channel->efx; efx_qword_t event, *p_event; unsigned int read_ptr; - int ev_code; + int spent_tx = 0; int spent = 0; + int ev_code; if (quota <= 0) return spent; @@ -3126,7 +3140,11 @@ static int efx_ef10_ev_process(struct efx_channel *channel, int quota) } break; case ESE_DZ_EV_CODE_TX_EV: - efx_ef10_handle_tx_event(channel, &event); + spent_tx += efx_ef10_handle_tx_event(channel, &event); + if (spent_tx >= EFX_NAPI_MAX_TX) { + spent = quota; + goto out; + } break; case ESE_DZ_EV_CODE_DRIVER_EV: efx_ef10_handle_driver_event(channel, &event); diff --git a/drivers/net/ethernet/sfc/ef100_netdev.c b/drivers/net/ethernet/sfc/ef100_netdev.c index be395cd8770bc71db641b710b90c3d00dc2f43fe..7f7d560cb2b4c956ad46ce794a593f3f4fda7829 100644 --- a/drivers/net/ethernet/sfc/ef100_netdev.c +++ b/drivers/net/ethernet/sfc/ef100_netdev.c @@ -24,6 +24,7 @@ #include "rx_common.h" #include "ef100_sriov.h" #include "tc_bindings.h" +#include "tc_encap_actions.h" #include "efx_devlink.h" static void ef100_update_name(struct efx_nic *efx) @@ -40,19 +41,26 @@ static int ef100_alloc_vis(struct efx_nic *efx, unsigned int *allocated_vis) unsigned int tx_vis = efx->n_tx_channels + efx->n_extra_tx_channels; unsigned int rx_vis = efx->n_rx_channels; unsigned int min_vis, max_vis; + int rc; EFX_WARN_ON_PARANOID(efx->tx_queues_per_channel != 1); tx_vis += efx->n_xdp_channels * efx->xdp_tx_per_channel; max_vis = max(rx_vis, tx_vis); - /* Currently don't handle resource starvation and only accept - * our maximum needs and no less. + /* We require at least a single complete TX channel worth of queues. */ + min_vis = efx->tx_queues_per_channel; + + rc = efx_mcdi_alloc_vis(efx, min_vis, max_vis, + NULL, allocated_vis); + + /* We retry allocating VIs by reallocating channels when we have not + * been able to allocate the maximum VIs. */ - min_vis = max_vis; + if (!rc && *allocated_vis < max_vis) + rc = -EAGAIN; - return efx_mcdi_alloc_vis(efx, min_vis, max_vis, - NULL, allocated_vis); + return rc; } static int ef100_remap_bar(struct efx_nic *efx, int max_vis) @@ -133,9 +141,41 @@ static int ef100_net_open(struct net_device *net_dev) goto fail; rc = ef100_alloc_vis(efx, &allocated_vis); - if (rc) + if (rc && rc != -EAGAIN) goto fail; + /* Try one more time but with the maximum number of channels + * equal to the allocated VIs, which would more likely succeed. + */ + if (rc == -EAGAIN) { + rc = efx_mcdi_free_vis(efx); + if (rc) + goto fail; + + efx_remove_interrupts(efx); + efx->max_channels = allocated_vis; + + rc = efx_probe_interrupts(efx); + if (rc) + goto fail; + + rc = efx_set_channels(efx); + if (rc) + goto fail; + + rc = ef100_alloc_vis(efx, &allocated_vis); + if (rc && rc != -EAGAIN) + goto fail; + + /* It should be very unlikely that we failed here again, but in + * such a case we return ENOSPC. + */ + if (rc == -EAGAIN) { + rc = -ENOSPC; + goto fail; + } + } + rc = efx_probe_channels(efx); if (rc) return rc; @@ -261,14 +301,38 @@ int ef100_netdev_event(struct notifier_block *this, { struct efx_nic *efx = container_of(this, struct efx_nic, netdev_notifier); struct net_device *net_dev = netdev_notifier_info_to_dev(ptr); + struct ef100_nic_data *nic_data = efx->nic_data; + int err; if (efx->net_dev == net_dev && (event == NETDEV_CHANGENAME || event == NETDEV_REGISTER)) ef100_update_name(efx); + if (!nic_data->grp_mae) + return NOTIFY_DONE; + err = efx_tc_netdev_event(efx, event, net_dev); + if (err & NOTIFY_STOP_MASK) + return err; + return NOTIFY_DONE; } +static int ef100_netevent_event(struct notifier_block *this, + unsigned long event, void *ptr) +{ + struct efx_nic *efx = container_of(this, struct efx_nic, netevent_notifier); + struct ef100_nic_data *nic_data = efx->nic_data; + int err; + + if (!nic_data->grp_mae) + return NOTIFY_DONE; + err = efx_tc_netevent_event(efx, event, ptr); + if (err & NOTIFY_STOP_MASK) + return err; + + return NOTIFY_DONE; +}; + static int ef100_register_netdev(struct efx_nic *efx) { struct net_device *net_dev = efx->net_dev; @@ -328,6 +392,7 @@ void ef100_remove_netdev(struct efx_probe_data *probe_data) rtnl_unlock(); unregister_netdevice_notifier(&efx->netdev_notifier); + unregister_netevent_notifier(&efx->netevent_notifier); #if defined(CONFIG_SFC_SRIOV) if (!efx->type->is_vf) efx_ef100_pci_sriov_disable(efx, true); @@ -448,6 +513,14 @@ int ef100_probe_netdev(struct efx_probe_data *probe_data) goto fail; } + efx->netevent_notifier.notifier_call = ef100_netevent_event; + rc = register_netevent_notifier(&efx->netevent_notifier); + if (rc) { + netif_err(efx, probe, efx->net_dev, + "Failed to register netevent notifier, rc=%d\n", rc); + goto fail; + } + efx_probe_devlink_unlock(efx); return rc; fail: diff --git a/drivers/net/ethernet/sfc/ef100_nic.c b/drivers/net/ethernet/sfc/ef100_nic.c index 4dc643b0d2db475bebae922dfda0f92b4f24028b..7adde9639c8aba091396236db1aa888241042ba7 100644 --- a/drivers/net/ethernet/sfc/ef100_nic.c +++ b/drivers/net/ethernet/sfc/ef100_nic.c @@ -253,6 +253,8 @@ static void ef100_ev_read_ack(struct efx_channel *channel) efx_reg(channel->efx, ER_GZ_EVQ_INT_PRIME)); } +#define EFX_NAPI_MAX_TX 512 + static int ef100_ev_process(struct efx_channel *channel, int quota) { struct efx_nic *efx = channel->efx; @@ -260,6 +262,7 @@ static int ef100_ev_process(struct efx_channel *channel, int quota) bool evq_phase, old_evq_phase; unsigned int read_ptr; efx_qword_t *p_event; + int spent_tx = 0; int spent = 0; bool ev_phase; int ev_type; @@ -295,7 +298,9 @@ static int ef100_ev_process(struct efx_channel *channel, int quota) efx_mcdi_process_event(channel, p_event); break; case ESE_GZ_EF100_EV_TX_COMPLETION: - ef100_ev_tx(channel, p_event); + spent_tx += ef100_ev_tx(channel, p_event); + if (spent_tx >= EFX_NAPI_MAX_TX) + spent = quota; break; case ESE_GZ_EF100_EV_DRIVER: netif_info(efx, drv, efx->net_dev, diff --git a/drivers/net/ethernet/sfc/ef100_tx.c b/drivers/net/ethernet/sfc/ef100_tx.c index 29ffaf35559d6ecb63c3c010d33bfaeccf449b28..849e5555bd1280a862f2d6e52c236820c4375374 100644 --- a/drivers/net/ethernet/sfc/ef100_tx.c +++ b/drivers/net/ethernet/sfc/ef100_tx.c @@ -346,7 +346,7 @@ void ef100_tx_write(struct efx_tx_queue *tx_queue) ef100_tx_push_buffers(tx_queue); } -void ef100_ev_tx(struct efx_channel *channel, const efx_qword_t *p_event) +int ef100_ev_tx(struct efx_channel *channel, const efx_qword_t *p_event) { unsigned int tx_done = EFX_QWORD_FIELD(*p_event, ESF_GZ_EV_TXCMPL_NUM_DESC); @@ -357,7 +357,7 @@ void ef100_ev_tx(struct efx_channel *channel, const efx_qword_t *p_event) unsigned int tx_index = (tx_queue->read_count + tx_done - 1) & tx_queue->ptr_mask; - efx_xmit_done(tx_queue, tx_index); + return efx_xmit_done(tx_queue, tx_index); } /* Add a socket buffer to a TX queue diff --git a/drivers/net/ethernet/sfc/ef100_tx.h b/drivers/net/ethernet/sfc/ef100_tx.h index e9e11540fcdeafdea63c11e68352c8d187707b12..d9a0819c5a72c0a3a68f9a234722f451a47ab65c 100644 --- a/drivers/net/ethernet/sfc/ef100_tx.h +++ b/drivers/net/ethernet/sfc/ef100_tx.h @@ -20,7 +20,7 @@ void ef100_tx_init(struct efx_tx_queue *tx_queue); void ef100_tx_write(struct efx_tx_queue *tx_queue); unsigned int ef100_tx_max_skb_descs(struct efx_nic *efx); -void ef100_ev_tx(struct efx_channel *channel, const efx_qword_t *p_event); +int ef100_ev_tx(struct efx_channel *channel, const efx_qword_t *p_event); netdev_tx_t ef100_enqueue_skb(struct efx_tx_queue *tx_queue, struct sk_buff *skb); int __ef100_enqueue_skb(struct efx_tx_queue *tx_queue, struct sk_buff *skb, diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c index a4f22d8e6ac7e72fe2cd90142ded046da62f4b58..d670a319b37995a9f6fe4b80235d70f5b294da66 100644 --- a/drivers/net/ethernet/sfc/efx.c +++ b/drivers/net/ethernet/sfc/efx.c @@ -32,6 +32,7 @@ #include "io.h" #include "selftest.h" #include "sriov.h" +#include "efx_devlink.h" #include "mcdi_port_common.h" #include "mcdi_pcol.h" @@ -877,6 +878,7 @@ static void efx_pci_remove(struct pci_dev *pci_dev) if (efx->type->sriov_fini) efx->type->sriov_fini(efx); + efx_fini_devlink_lock(efx); efx_unregister_netdev(efx); efx_mtd_remove(efx); @@ -886,6 +888,7 @@ static void efx_pci_remove(struct pci_dev *pci_dev) efx_fini_io(efx); pci_dbg(efx->pci_dev, "shutdown successful\n"); + efx_fini_devlink_and_unlock(efx); efx_fini_struct(efx); free_netdev(efx->net_dev); probe_data = container_of(efx, struct efx_probe_data, efx); @@ -1025,7 +1028,13 @@ static int efx_pci_probe_post_io(struct efx_nic *efx) NETDEV_XDP_ACT_REDIRECT | NETDEV_XDP_ACT_NDO_XMIT; + /* devlink creation, registration and lock */ + rc = efx_probe_devlink_and_lock(efx); + if (rc) + pci_err(efx->pci_dev, "devlink registration failed"); + rc = efx_register_netdev(efx); + efx_probe_devlink_unlock(efx); if (!rc) return 0; diff --git a/drivers/net/ethernet/sfc/efx_devlink.c b/drivers/net/ethernet/sfc/efx_devlink.c index ef9971cbb695d2e82fb58268522295ce853ebffe..3cd750820fdde327b819db6adb83b9350826d49c 100644 --- a/drivers/net/ethernet/sfc/efx_devlink.c +++ b/drivers/net/ethernet/sfc/efx_devlink.c @@ -25,40 +25,6 @@ struct efx_devlink { }; #ifdef CONFIG_SFC_SRIOV -static void efx_devlink_del_port(struct devlink_port *dl_port) -{ - if (!dl_port) - return; - devl_port_unregister(dl_port); -} - -static int efx_devlink_add_port(struct efx_nic *efx, - struct mae_mport_desc *mport) -{ - bool external = false; - - if (!ef100_mport_on_local_intf(efx, mport)) - external = true; - - switch (mport->mport_type) { - case MAE_MPORT_DESC_MPORT_TYPE_VNIC: - if (mport->vf_idx != MAE_MPORT_DESC_VF_IDX_NULL) - devlink_port_attrs_pci_vf_set(&mport->dl_port, 0, mport->pf_idx, - mport->vf_idx, - external); - else - devlink_port_attrs_pci_pf_set(&mport->dl_port, 0, mport->pf_idx, - external); - break; - default: - /* MAE_MPORT_DESC_MPORT_ALIAS and UNDEFINED */ - return 0; - } - - mport->dl_port.index = mport->mport_id; - - return devl_port_register(efx->devlink, &mport->dl_port, mport->mport_id); -} static int efx_devlink_port_addr_get(struct devlink_port *port, u8 *hw_addr, int *hw_addr_len, @@ -158,6 +124,48 @@ static int efx_devlink_port_addr_set(struct devlink_port *port, return rc; } +static const struct devlink_port_ops sfc_devlink_port_ops = { + .port_fn_hw_addr_get = efx_devlink_port_addr_get, + .port_fn_hw_addr_set = efx_devlink_port_addr_set, +}; + +static void efx_devlink_del_port(struct devlink_port *dl_port) +{ + if (!dl_port) + return; + devl_port_unregister(dl_port); +} + +static int efx_devlink_add_port(struct efx_nic *efx, + struct mae_mport_desc *mport) +{ + bool external = false; + + if (!ef100_mport_on_local_intf(efx, mport)) + external = true; + + switch (mport->mport_type) { + case MAE_MPORT_DESC_MPORT_TYPE_VNIC: + if (mport->vf_idx != MAE_MPORT_DESC_VF_IDX_NULL) + devlink_port_attrs_pci_vf_set(&mport->dl_port, 0, mport->pf_idx, + mport->vf_idx, + external); + else + devlink_port_attrs_pci_pf_set(&mport->dl_port, 0, mport->pf_idx, + external); + break; + default: + /* MAE_MPORT_DESC_MPORT_ALIAS and UNDEFINED */ + return 0; + } + + mport->dl_port.index = mport->mport_id; + + return devl_port_register_with_ops(efx->devlink, &mport->dl_port, + mport->mport_id, + &sfc_devlink_port_ops); +} + #endif static int efx_devlink_info_nvram_partition(struct efx_nic *efx, @@ -609,10 +617,6 @@ static int efx_devlink_info_get(struct devlink *devlink, static const struct devlink_ops sfc_devlink_ops = { .info_get = efx_devlink_info_get, -#ifdef CONFIG_SFC_SRIOV - .port_function_hw_addr_get = efx_devlink_port_addr_get, - .port_function_hw_addr_set = efx_devlink_port_addr_set, -#endif }; #ifdef CONFIG_SFC_SRIOV @@ -622,6 +626,9 @@ static struct devlink_port *ef100_set_devlink_port(struct efx_nic *efx, u32 idx) u32 id; int rc; + if (!efx->mae) + return NULL; + if (efx_mae_lookup_mport(efx, idx, &id)) { /* This should not happen. */ if (idx == MAE_MPORT_DESC_VF_IDX_NULL) diff --git a/drivers/net/ethernet/sfc/falcon/selftest.c b/drivers/net/ethernet/sfc/falcon/selftest.c index 6a454ac6f8763dee94177373dd5b7a51edd03094..9e5ce2a13787ab0ef95fc1f3a5f98763fee79d6c 100644 --- a/drivers/net/ethernet/sfc/falcon/selftest.c +++ b/drivers/net/ethernet/sfc/falcon/selftest.c @@ -39,12 +39,16 @@ * Falcon only performs RSS on TCP/UDP packets. */ struct ef4_loopback_payload { + char pad[2]; /* Ensures ip is 4-byte aligned */ struct ethhdr header; struct iphdr ip; struct udphdr udp; __be16 iteration; char msg[64]; -} __packed; +} __packed __aligned(4); +#define EF4_LOOPBACK_PAYLOAD_LEN (sizeof(struct ef4_loopback_payload) - \ + offsetof(struct ef4_loopback_payload, \ + header)) /* Loopback test source MAC address */ static const u8 payload_source[ETH_ALEN] __aligned(2) = { @@ -284,7 +288,7 @@ void ef4_loopback_rx_packet(struct ef4_nic *efx, const char *buf_ptr, int pkt_len) { struct ef4_loopback_state *state = efx->loopback_selftest; - struct ef4_loopback_payload *received; + struct ef4_loopback_payload received; struct ef4_loopback_payload *payload; BUG_ON(!buf_ptr); @@ -295,13 +299,14 @@ void ef4_loopback_rx_packet(struct ef4_nic *efx, payload = &state->payload; - received = (struct ef4_loopback_payload *) buf_ptr; - received->ip.saddr = payload->ip.saddr; + memcpy(&received.header, buf_ptr, + min_t(int, pkt_len, EF4_LOOPBACK_PAYLOAD_LEN)); + received.ip.saddr = payload->ip.saddr; if (state->offload_csum) - received->ip.check = payload->ip.check; + received.ip.check = payload->ip.check; /* Check that header exists */ - if (pkt_len < sizeof(received->header)) { + if (pkt_len < sizeof(received.header)) { netif_err(efx, drv, efx->net_dev, "saw runt RX packet (length %d) in %s loopback " "test\n", pkt_len, LOOPBACK_MODE(efx)); @@ -309,7 +314,7 @@ void ef4_loopback_rx_packet(struct ef4_nic *efx, } /* Check that the ethernet header exists */ - if (memcmp(&received->header, &payload->header, ETH_HLEN) != 0) { + if (memcmp(&received.header, &payload->header, ETH_HLEN) != 0) { netif_err(efx, drv, efx->net_dev, "saw non-loopback RX packet in %s loopback test\n", LOOPBACK_MODE(efx)); @@ -317,16 +322,16 @@ void ef4_loopback_rx_packet(struct ef4_nic *efx, } /* Check packet length */ - if (pkt_len != sizeof(*payload)) { + if (pkt_len != EF4_LOOPBACK_PAYLOAD_LEN) { netif_err(efx, drv, efx->net_dev, "saw incorrect RX packet length %d (wanted %d) in " - "%s loopback test\n", pkt_len, (int)sizeof(*payload), - LOOPBACK_MODE(efx)); + "%s loopback test\n", pkt_len, + (int)EF4_LOOPBACK_PAYLOAD_LEN, LOOPBACK_MODE(efx)); goto err; } /* Check that IP header matches */ - if (memcmp(&received->ip, &payload->ip, sizeof(payload->ip)) != 0) { + if (memcmp(&received.ip, &payload->ip, sizeof(payload->ip)) != 0) { netif_err(efx, drv, efx->net_dev, "saw corrupted IP header in %s loopback test\n", LOOPBACK_MODE(efx)); @@ -334,7 +339,7 @@ void ef4_loopback_rx_packet(struct ef4_nic *efx, } /* Check that msg and padding matches */ - if (memcmp(&received->msg, &payload->msg, sizeof(received->msg)) != 0) { + if (memcmp(&received.msg, &payload->msg, sizeof(received.msg)) != 0) { netif_err(efx, drv, efx->net_dev, "saw corrupted RX packet in %s loopback test\n", LOOPBACK_MODE(efx)); @@ -342,10 +347,10 @@ void ef4_loopback_rx_packet(struct ef4_nic *efx, } /* Check that iteration matches */ - if (received->iteration != payload->iteration) { + if (received.iteration != payload->iteration) { netif_err(efx, drv, efx->net_dev, "saw RX packet from iteration %d (wanted %d) in " - "%s loopback test\n", ntohs(received->iteration), + "%s loopback test\n", ntohs(received.iteration), ntohs(payload->iteration), LOOPBACK_MODE(efx)); goto err; } @@ -365,7 +370,8 @@ void ef4_loopback_rx_packet(struct ef4_nic *efx, buf_ptr, pkt_len, 0); netif_err(efx, drv, efx->net_dev, "expected packet:\n"); print_hex_dump(KERN_ERR, "", DUMP_PREFIX_OFFSET, 0x10, 1, - &state->payload, sizeof(state->payload), 0); + &state->payload.header, EF4_LOOPBACK_PAYLOAD_LEN, + 0); } #endif atomic_inc(&state->rx_bad); @@ -387,14 +393,15 @@ static void ef4_iterate_state(struct ef4_nic *efx) payload->ip.daddr = htonl(INADDR_LOOPBACK); payload->ip.ihl = 5; payload->ip.check = (__force __sum16) htons(0xdead); - payload->ip.tot_len = htons(sizeof(*payload) - sizeof(struct ethhdr)); + payload->ip.tot_len = htons(sizeof(*payload) - + offsetof(struct ef4_loopback_payload, ip)); payload->ip.version = IPVERSION; payload->ip.protocol = IPPROTO_UDP; /* Initialise udp header */ payload->udp.source = 0; - payload->udp.len = htons(sizeof(*payload) - sizeof(struct ethhdr) - - sizeof(struct iphdr)); + payload->udp.len = htons(sizeof(*payload) - + offsetof(struct ef4_loopback_payload, udp)); payload->udp.check = 0; /* checksum ignored */ /* Fill out payload */ @@ -420,7 +427,7 @@ static int ef4_begin_loopback(struct ef4_tx_queue *tx_queue) for (i = 0; i < state->packet_count; i++) { /* Allocate an skb, holding an extra reference for * transmit completion counting */ - skb = alloc_skb(sizeof(state->payload), GFP_KERNEL); + skb = alloc_skb(EF4_LOOPBACK_PAYLOAD_LEN, GFP_KERNEL); if (!skb) return -ENOMEM; state->skbs[i] = skb; @@ -431,6 +438,8 @@ static int ef4_begin_loopback(struct ef4_tx_queue *tx_queue) payload = skb_put(skb, sizeof(state->payload)); memcpy(payload, &state->payload, sizeof(state->payload)); payload->ip.saddr = htonl(INADDR_LOOPBACK | (i << 2)); + /* Strip off the leading padding */ + skb_pull(skb, offsetof(struct ef4_loopback_payload, header)); /* Ensure everything we've written is visible to the * interrupt handler. */ diff --git a/drivers/net/ethernet/sfc/mae.c b/drivers/net/ethernet/sfc/mae.c index 49706a7b94bf424ff06b724ed37c3e749548e281..0cab508f2f9d1896414ff33384dd14e2f12d8445 100644 --- a/drivers/net/ethernet/sfc/mae.c +++ b/drivers/net/ethernet/sfc/mae.c @@ -15,6 +15,7 @@ #include "mcdi.h" #include "mcdi_pcol.h" #include "mcdi_pcol_mae.h" +#include "tc_encap_actions.h" int efx_mae_allocate_mport(struct efx_nic *efx, u32 *id, u32 *label) { @@ -482,12 +483,14 @@ int efx_mae_match_check_caps(struct efx_nic *efx, rc; \ }) /* Checks that the fields needed for encap-rule matches are supported by the - * MAE. All the fields are exact-match. + * MAE. All the fields are exact-match, except possibly ENC_IP_TOS. */ int efx_mae_check_encap_match_caps(struct efx_nic *efx, bool ipv6, + u8 ip_tos_mask, __be16 udp_sport_mask, struct netlink_ext_ack *extack) { u8 *supported_fields = efx->tc->caps->outer_rule_fields; + enum mask_type typ; int rc; if (CHECK(ENC_ETHER_TYPE)) @@ -504,6 +507,22 @@ int efx_mae_check_encap_match_caps(struct efx_nic *efx, bool ipv6, if (CHECK(ENC_L4_DPORT) || CHECK(ENC_IP_PROTO)) return rc; + typ = classify_mask((const u8 *)&udp_sport_mask, sizeof(udp_sport_mask)); + rc = efx_mae_match_check_cap_typ(supported_fields[MAE_FIELD_ENC_L4_SPORT], + typ); + if (rc) { + NL_SET_ERR_MSG_FMT_MOD(extack, "No support for %s mask in field %s", + mask_type_name(typ), "enc_src_port"); + return rc; + } + typ = classify_mask(&ip_tos_mask, sizeof(ip_tos_mask)); + rc = efx_mae_match_check_cap_typ(supported_fields[MAE_FIELD_ENC_IP_TOS], + typ); + if (rc) { + NL_SET_ERR_MSG_FMT_MOD(extack, "No support for %s mask in field %s", + mask_type_name(typ), "enc_ip_tos"); + return rc; + } return 0; } #undef CHECK @@ -592,6 +611,87 @@ static int efx_mae_encap_type_to_mae_type(enum efx_encap_type type) } } +int efx_mae_allocate_encap_md(struct efx_nic *efx, + struct efx_tc_encap_action *encap) +{ + MCDI_DECLARE_BUF(inbuf, MC_CMD_MAE_ENCAP_HEADER_ALLOC_IN_LEN(EFX_TC_MAX_ENCAP_HDR)); + MCDI_DECLARE_BUF(outbuf, MC_CMD_MAE_ENCAP_HEADER_ALLOC_OUT_LEN); + size_t inlen, outlen; + int rc; + + rc = efx_mae_encap_type_to_mae_type(encap->type); + if (rc < 0) + return rc; + MCDI_SET_DWORD(inbuf, MAE_ENCAP_HEADER_ALLOC_IN_ENCAP_TYPE, rc); + inlen = MC_CMD_MAE_ENCAP_HEADER_ALLOC_IN_LEN(encap->encap_hdr_len); + if (WARN_ON(inlen > sizeof(inbuf))) /* can't happen */ + return -EINVAL; + memcpy(MCDI_PTR(inbuf, MAE_ENCAP_HEADER_ALLOC_IN_HDR_DATA), + encap->encap_hdr, + encap->encap_hdr_len); + rc = efx_mcdi_rpc(efx, MC_CMD_MAE_ENCAP_HEADER_ALLOC, inbuf, + inlen, outbuf, sizeof(outbuf), &outlen); + if (rc) + return rc; + if (outlen < sizeof(outbuf)) + return -EIO; + encap->fw_id = MCDI_DWORD(outbuf, MAE_ENCAP_HEADER_ALLOC_OUT_ENCAP_HEADER_ID); + return 0; +} + +int efx_mae_update_encap_md(struct efx_nic *efx, + struct efx_tc_encap_action *encap) +{ + MCDI_DECLARE_BUF(inbuf, MC_CMD_MAE_ENCAP_HEADER_UPDATE_IN_LEN(EFX_TC_MAX_ENCAP_HDR)); + size_t inlen; + int rc; + + rc = efx_mae_encap_type_to_mae_type(encap->type); + if (rc < 0) + return rc; + MCDI_SET_DWORD(inbuf, MAE_ENCAP_HEADER_UPDATE_IN_ENCAP_TYPE, rc); + MCDI_SET_DWORD(inbuf, MAE_ENCAP_HEADER_UPDATE_IN_EH_ID, + encap->fw_id); + inlen = MC_CMD_MAE_ENCAP_HEADER_UPDATE_IN_LEN(encap->encap_hdr_len); + if (WARN_ON(inlen > sizeof(inbuf))) /* can't happen */ + return -EINVAL; + memcpy(MCDI_PTR(inbuf, MAE_ENCAP_HEADER_UPDATE_IN_HDR_DATA), + encap->encap_hdr, + encap->encap_hdr_len); + + BUILD_BUG_ON(MC_CMD_MAE_ENCAP_HEADER_UPDATE_OUT_LEN != 0); + return efx_mcdi_rpc(efx, MC_CMD_MAE_ENCAP_HEADER_UPDATE, inbuf, + inlen, NULL, 0, NULL); +} + +int efx_mae_free_encap_md(struct efx_nic *efx, + struct efx_tc_encap_action *encap) +{ + MCDI_DECLARE_BUF(outbuf, MC_CMD_MAE_ENCAP_HEADER_FREE_OUT_LEN(1)); + MCDI_DECLARE_BUF(inbuf, MC_CMD_MAE_ENCAP_HEADER_FREE_IN_LEN(1)); + size_t outlen; + int rc; + + MCDI_SET_DWORD(inbuf, MAE_ENCAP_HEADER_FREE_IN_EH_ID, encap->fw_id); + rc = efx_mcdi_rpc(efx, MC_CMD_MAE_ENCAP_HEADER_FREE, inbuf, + sizeof(inbuf), outbuf, sizeof(outbuf), &outlen); + if (rc) + return rc; + if (outlen < sizeof(outbuf)) + return -EIO; + /* FW freed a different ID than we asked for, should also never happen. + * Warn because it means we've now got a different idea to the FW of + * what encap_mds exist, which could cause mayhem later. + */ + if (WARN_ON(MCDI_DWORD(outbuf, MAE_ENCAP_HEADER_FREE_OUT_FREED_EH_ID) != encap->fw_id)) + return -EIO; + /* We're probably about to free @encap, but let's just make sure its + * fw_id is blatted so that it won't look valid if it leaks out. + */ + encap->fw_id = MC_CMD_MAE_ENCAP_HEADER_ALLOC_OUT_ENCAP_HEADER_ID_NULL; + return 0; +} + int efx_mae_lookup_mport(struct efx_nic *efx, u32 vf_idx, u32 *id) { struct ef100_nic_data *nic_data = efx->nic_data; @@ -815,8 +915,12 @@ int efx_mae_alloc_action_set(struct efx_nic *efx, struct efx_tc_action_set *act) MCDI_SET_WORD_BE(inbuf, MAE_ACTION_SET_ALLOC_IN_VLAN1_PROTO_BE, act->vlan_proto[1]); } - MCDI_SET_DWORD(inbuf, MAE_ACTION_SET_ALLOC_IN_ENCAP_HEADER_ID, - MC_CMD_MAE_ENCAP_HEADER_ALLOC_OUT_ENCAP_HEADER_ID_NULL); + if (act->encap_md) + MCDI_SET_DWORD(inbuf, MAE_ACTION_SET_ALLOC_IN_ENCAP_HEADER_ID, + act->encap_md->fw_id); + else + MCDI_SET_DWORD(inbuf, MAE_ACTION_SET_ALLOC_IN_ENCAP_HEADER_ID, + MC_CMD_MAE_ENCAP_HEADER_ALLOC_OUT_ENCAP_HEADER_ID_NULL); if (act->deliver) MCDI_SET_DWORD(inbuf, MAE_ACTION_SET_ALLOC_IN_DELIVER, act->dest_mport); @@ -1001,8 +1105,16 @@ int efx_mae_register_encap_match(struct efx_nic *efx, encap->udp_dport); MCDI_STRUCT_SET_WORD_BE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_L4_DPORT_BE_MASK, ~(__be16)0); + MCDI_STRUCT_SET_WORD_BE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_L4_DPORT_BE, + encap->udp_sport); + MCDI_STRUCT_SET_WORD_BE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_L4_DPORT_BE_MASK, + encap->udp_sport_mask); MCDI_STRUCT_SET_BYTE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_IP_PROTO, IPPROTO_UDP); MCDI_STRUCT_SET_BYTE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_IP_PROTO_MASK, ~0); + MCDI_STRUCT_SET_BYTE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_IP_TOS, + encap->ip_tos); + MCDI_STRUCT_SET_BYTE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_IP_TOS_MASK, + encap->ip_tos_mask); rc = efx_mcdi_rpc(efx, MC_CMD_MAE_OUTER_RULE_INSERT, inbuf, sizeof(inbuf), outbuf, sizeof(outbuf), &outlen); if (rc) @@ -1203,6 +1315,29 @@ int efx_mae_insert_rule(struct efx_nic *efx, const struct efx_tc_match *match, return 0; } +int efx_mae_update_rule(struct efx_nic *efx, u32 acts_id, u32 id) +{ + MCDI_DECLARE_BUF(inbuf, MC_CMD_MAE_ACTION_RULE_UPDATE_IN_LEN); + MCDI_DECLARE_STRUCT_PTR(response); + + BUILD_BUG_ON(MC_CMD_MAE_ACTION_RULE_UPDATE_OUT_LEN); + response = _MCDI_DWORD(inbuf, MAE_ACTION_RULE_UPDATE_IN_RESPONSE); + + MCDI_SET_DWORD(inbuf, MAE_ACTION_RULE_UPDATE_IN_AR_ID, id); + if (efx_mae_asl_id(acts_id)) { + MCDI_STRUCT_SET_DWORD(response, MAE_ACTION_RULE_RESPONSE_ASL_ID, acts_id); + MCDI_STRUCT_SET_DWORD(response, MAE_ACTION_RULE_RESPONSE_AS_ID, + MC_CMD_MAE_ACTION_SET_ALLOC_OUT_ACTION_SET_ID_NULL); + } else { + /* We only had one AS, so we didn't wrap it in an ASL */ + MCDI_STRUCT_SET_DWORD(response, MAE_ACTION_RULE_RESPONSE_ASL_ID, + MC_CMD_MAE_ACTION_SET_LIST_ALLOC_OUT_ACTION_SET_LIST_ID_NULL); + MCDI_STRUCT_SET_DWORD(response, MAE_ACTION_RULE_RESPONSE_AS_ID, acts_id); + } + return efx_mcdi_rpc(efx, MC_CMD_MAE_ACTION_RULE_UPDATE, inbuf, sizeof(inbuf), + NULL, 0, NULL); +} + int efx_mae_delete_rule(struct efx_nic *efx, u32 id) { MCDI_DECLARE_BUF(outbuf, MC_CMD_MAE_ACTION_RULE_DELETE_OUT_LEN(1)); diff --git a/drivers/net/ethernet/sfc/mae.h b/drivers/net/ethernet/sfc/mae.h index 9226219491a0b5b3437246e9a42aa3af6d199903..24abfe50969091c052901c84d8a30dfb4d68fad3 100644 --- a/drivers/net/ethernet/sfc/mae.h +++ b/drivers/net/ethernet/sfc/mae.h @@ -82,6 +82,7 @@ int efx_mae_match_check_caps(struct efx_nic *efx, const struct efx_tc_match_fields *mask, struct netlink_ext_ack *extack); int efx_mae_check_encap_match_caps(struct efx_nic *efx, bool ipv6, + u8 ip_tos_mask, __be16 udp_sport_mask, struct netlink_ext_ack *extack); int efx_mae_check_encap_type_supported(struct efx_nic *efx, enum efx_encap_type typ); @@ -89,6 +90,13 @@ int efx_mae_check_encap_type_supported(struct efx_nic *efx, int efx_mae_allocate_counter(struct efx_nic *efx, struct efx_tc_counter *cnt); int efx_mae_free_counter(struct efx_nic *efx, struct efx_tc_counter *cnt); +int efx_mae_allocate_encap_md(struct efx_nic *efx, + struct efx_tc_encap_action *encap); +int efx_mae_update_encap_md(struct efx_nic *efx, + struct efx_tc_encap_action *encap); +int efx_mae_free_encap_md(struct efx_nic *efx, + struct efx_tc_encap_action *encap); + int efx_mae_alloc_action_set(struct efx_nic *efx, struct efx_tc_action_set *act); int efx_mae_free_action_set(struct efx_nic *efx, u32 fw_id); @@ -104,6 +112,7 @@ int efx_mae_unregister_encap_match(struct efx_nic *efx, int efx_mae_insert_rule(struct efx_nic *efx, const struct efx_tc_match *match, u32 prio, u32 acts_id, u32 *id); +int efx_mae_update_rule(struct efx_nic *efx, u32 acts_id, u32 id); int efx_mae_delete_rule(struct efx_nic *efx, u32 id); int efx_init_mae(struct efx_nic *efx); diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h index fcd51d3992fa68b55cba2cb8595794bb6d2c34f1..a7a22b01979479bd711975dfd240d09e6d687888 100644 --- a/drivers/net/ethernet/sfc/net_driver.h +++ b/drivers/net/ethernet/sfc/net_driver.h @@ -27,6 +27,7 @@ #include #include #include +#include #include "enum.h" #include "bitfield.h" @@ -996,6 +997,7 @@ struct efx_mae; * @xdp_rxq_info_failed: Have any of the rx queues failed to initialise their * xdp_rxq_info structures? * @netdev_notifier: Netdevice notifier. + * @netevent_notifier: Netevent notifier (for neighbour updates). * @tc: state for TC offload (EF100). * @devlink: reference to devlink structure owned by this device * @dl_port: devlink port associated with the PF @@ -1183,6 +1185,7 @@ struct efx_nic { bool xdp_rxq_info_failed; struct notifier_block netdev_notifier; + struct notifier_block netevent_notifier; struct efx_tc_state *tc; struct devlink *devlink; diff --git a/drivers/net/ethernet/sfc/selftest.c b/drivers/net/ethernet/sfc/selftest.c index 3c5227afd497739100382fd5a2d10d905519239f..96d856b9043c4ce6c78b6c2716de3e6b4bd4b4a2 100644 --- a/drivers/net/ethernet/sfc/selftest.c +++ b/drivers/net/ethernet/sfc/selftest.c @@ -42,12 +42,16 @@ * Falcon only performs RSS on TCP/UDP packets. */ struct efx_loopback_payload { + char pad[2]; /* Ensures ip is 4-byte aligned */ struct ethhdr header; struct iphdr ip; struct udphdr udp; __be16 iteration; char msg[64]; -} __packed; +} __packed __aligned(4); +#define EFX_LOOPBACK_PAYLOAD_LEN (sizeof(struct efx_loopback_payload) - \ + offsetof(struct efx_loopback_payload, \ + header)) /* Loopback test source MAC address */ static const u8 payload_source[ETH_ALEN] __aligned(2) = { @@ -282,7 +286,7 @@ void efx_loopback_rx_packet(struct efx_nic *efx, const char *buf_ptr, int pkt_len) { struct efx_loopback_state *state = efx->loopback_selftest; - struct efx_loopback_payload *received; + struct efx_loopback_payload received; struct efx_loopback_payload *payload; BUG_ON(!buf_ptr); @@ -293,13 +297,14 @@ void efx_loopback_rx_packet(struct efx_nic *efx, payload = &state->payload; - received = (struct efx_loopback_payload *) buf_ptr; - received->ip.saddr = payload->ip.saddr; + memcpy(&received.header, buf_ptr, + min_t(int, pkt_len, EFX_LOOPBACK_PAYLOAD_LEN)); + received.ip.saddr = payload->ip.saddr; if (state->offload_csum) - received->ip.check = payload->ip.check; + received.ip.check = payload->ip.check; /* Check that header exists */ - if (pkt_len < sizeof(received->header)) { + if (pkt_len < sizeof(received.header)) { netif_err(efx, drv, efx->net_dev, "saw runt RX packet (length %d) in %s loopback " "test\n", pkt_len, LOOPBACK_MODE(efx)); @@ -307,7 +312,7 @@ void efx_loopback_rx_packet(struct efx_nic *efx, } /* Check that the ethernet header exists */ - if (memcmp(&received->header, &payload->header, ETH_HLEN) != 0) { + if (memcmp(&received.header, &payload->header, ETH_HLEN) != 0) { netif_err(efx, drv, efx->net_dev, "saw non-loopback RX packet in %s loopback test\n", LOOPBACK_MODE(efx)); @@ -315,16 +320,16 @@ void efx_loopback_rx_packet(struct efx_nic *efx, } /* Check packet length */ - if (pkt_len != sizeof(*payload)) { + if (pkt_len != EFX_LOOPBACK_PAYLOAD_LEN) { netif_err(efx, drv, efx->net_dev, "saw incorrect RX packet length %d (wanted %d) in " - "%s loopback test\n", pkt_len, (int)sizeof(*payload), - LOOPBACK_MODE(efx)); + "%s loopback test\n", pkt_len, + (int)EFX_LOOPBACK_PAYLOAD_LEN, LOOPBACK_MODE(efx)); goto err; } /* Check that IP header matches */ - if (memcmp(&received->ip, &payload->ip, sizeof(payload->ip)) != 0) { + if (memcmp(&received.ip, &payload->ip, sizeof(payload->ip)) != 0) { netif_err(efx, drv, efx->net_dev, "saw corrupted IP header in %s loopback test\n", LOOPBACK_MODE(efx)); @@ -332,7 +337,7 @@ void efx_loopback_rx_packet(struct efx_nic *efx, } /* Check that msg and padding matches */ - if (memcmp(&received->msg, &payload->msg, sizeof(received->msg)) != 0) { + if (memcmp(&received.msg, &payload->msg, sizeof(received.msg)) != 0) { netif_err(efx, drv, efx->net_dev, "saw corrupted RX packet in %s loopback test\n", LOOPBACK_MODE(efx)); @@ -340,10 +345,10 @@ void efx_loopback_rx_packet(struct efx_nic *efx, } /* Check that iteration matches */ - if (received->iteration != payload->iteration) { + if (received.iteration != payload->iteration) { netif_err(efx, drv, efx->net_dev, "saw RX packet from iteration %d (wanted %d) in " - "%s loopback test\n", ntohs(received->iteration), + "%s loopback test\n", ntohs(received.iteration), ntohs(payload->iteration), LOOPBACK_MODE(efx)); goto err; } @@ -363,7 +368,8 @@ void efx_loopback_rx_packet(struct efx_nic *efx, buf_ptr, pkt_len, 0); netif_err(efx, drv, efx->net_dev, "expected packet:\n"); print_hex_dump(KERN_ERR, "", DUMP_PREFIX_OFFSET, 0x10, 1, - &state->payload, sizeof(state->payload), 0); + &state->payload.header, EFX_LOOPBACK_PAYLOAD_LEN, + 0); } #endif atomic_inc(&state->rx_bad); @@ -385,14 +391,15 @@ static void efx_iterate_state(struct efx_nic *efx) payload->ip.daddr = htonl(INADDR_LOOPBACK); payload->ip.ihl = 5; payload->ip.check = (__force __sum16) htons(0xdead); - payload->ip.tot_len = htons(sizeof(*payload) - sizeof(struct ethhdr)); + payload->ip.tot_len = htons(sizeof(*payload) - + offsetof(struct efx_loopback_payload, ip)); payload->ip.version = IPVERSION; payload->ip.protocol = IPPROTO_UDP; /* Initialise udp header */ payload->udp.source = 0; - payload->udp.len = htons(sizeof(*payload) - sizeof(struct ethhdr) - - sizeof(struct iphdr)); + payload->udp.len = htons(sizeof(*payload) - + offsetof(struct efx_loopback_payload, udp)); payload->udp.check = 0; /* checksum ignored */ /* Fill out payload */ @@ -418,7 +425,7 @@ static int efx_begin_loopback(struct efx_tx_queue *tx_queue) for (i = 0; i < state->packet_count; i++) { /* Allocate an skb, holding an extra reference for * transmit completion counting */ - skb = alloc_skb(sizeof(state->payload), GFP_KERNEL); + skb = alloc_skb(EFX_LOOPBACK_PAYLOAD_LEN, GFP_KERNEL); if (!skb) return -ENOMEM; state->skbs[i] = skb; @@ -429,6 +436,8 @@ static int efx_begin_loopback(struct efx_tx_queue *tx_queue) payload = skb_put(skb, sizeof(state->payload)); memcpy(payload, &state->payload, sizeof(state->payload)); payload->ip.saddr = htonl(INADDR_LOOPBACK | (i << 2)); + /* Strip off the leading padding */ + skb_pull(skb, offsetof(struct efx_loopback_payload, header)); /* Ensure everything we've written is visible to the * interrupt handler. */ diff --git a/drivers/net/ethernet/sfc/siena/selftest.c b/drivers/net/ethernet/sfc/siena/selftest.c index 07715a3d6beab7920cfb7c9df82a99f7af9ed58e..111ac17194a5637ceb279e12edf460491b27071f 100644 --- a/drivers/net/ethernet/sfc/siena/selftest.c +++ b/drivers/net/ethernet/sfc/siena/selftest.c @@ -42,12 +42,16 @@ * Falcon only performs RSS on TCP/UDP packets. */ struct efx_loopback_payload { + char pad[2]; /* Ensures ip is 4-byte aligned */ struct ethhdr header; struct iphdr ip; struct udphdr udp; __be16 iteration; char msg[64]; -} __packed; +} __packed __aligned(4); +#define EFX_LOOPBACK_PAYLOAD_LEN (sizeof(struct efx_loopback_payload) - \ + offsetof(struct efx_loopback_payload, \ + header)) /* Loopback test source MAC address */ static const u8 payload_source[ETH_ALEN] __aligned(2) = { @@ -282,7 +286,7 @@ void efx_siena_loopback_rx_packet(struct efx_nic *efx, const char *buf_ptr, int pkt_len) { struct efx_loopback_state *state = efx->loopback_selftest; - struct efx_loopback_payload *received; + struct efx_loopback_payload received; struct efx_loopback_payload *payload; BUG_ON(!buf_ptr); @@ -293,13 +297,14 @@ void efx_siena_loopback_rx_packet(struct efx_nic *efx, payload = &state->payload; - received = (struct efx_loopback_payload *) buf_ptr; - received->ip.saddr = payload->ip.saddr; + memcpy(&received.header, buf_ptr, + min_t(int, pkt_len, EFX_LOOPBACK_PAYLOAD_LEN)); + received.ip.saddr = payload->ip.saddr; if (state->offload_csum) - received->ip.check = payload->ip.check; + received.ip.check = payload->ip.check; /* Check that header exists */ - if (pkt_len < sizeof(received->header)) { + if (pkt_len < sizeof(received.header)) { netif_err(efx, drv, efx->net_dev, "saw runt RX packet (length %d) in %s loopback " "test\n", pkt_len, LOOPBACK_MODE(efx)); @@ -307,7 +312,7 @@ void efx_siena_loopback_rx_packet(struct efx_nic *efx, } /* Check that the ethernet header exists */ - if (memcmp(&received->header, &payload->header, ETH_HLEN) != 0) { + if (memcmp(&received.header, &payload->header, ETH_HLEN) != 0) { netif_err(efx, drv, efx->net_dev, "saw non-loopback RX packet in %s loopback test\n", LOOPBACK_MODE(efx)); @@ -315,16 +320,16 @@ void efx_siena_loopback_rx_packet(struct efx_nic *efx, } /* Check packet length */ - if (pkt_len != sizeof(*payload)) { + if (pkt_len != EFX_LOOPBACK_PAYLOAD_LEN) { netif_err(efx, drv, efx->net_dev, "saw incorrect RX packet length %d (wanted %d) in " - "%s loopback test\n", pkt_len, (int)sizeof(*payload), - LOOPBACK_MODE(efx)); + "%s loopback test\n", pkt_len, + (int)EFX_LOOPBACK_PAYLOAD_LEN, LOOPBACK_MODE(efx)); goto err; } /* Check that IP header matches */ - if (memcmp(&received->ip, &payload->ip, sizeof(payload->ip)) != 0) { + if (memcmp(&received.ip, &payload->ip, sizeof(payload->ip)) != 0) { netif_err(efx, drv, efx->net_dev, "saw corrupted IP header in %s loopback test\n", LOOPBACK_MODE(efx)); @@ -332,7 +337,7 @@ void efx_siena_loopback_rx_packet(struct efx_nic *efx, } /* Check that msg and padding matches */ - if (memcmp(&received->msg, &payload->msg, sizeof(received->msg)) != 0) { + if (memcmp(&received.msg, &payload->msg, sizeof(received.msg)) != 0) { netif_err(efx, drv, efx->net_dev, "saw corrupted RX packet in %s loopback test\n", LOOPBACK_MODE(efx)); @@ -340,10 +345,10 @@ void efx_siena_loopback_rx_packet(struct efx_nic *efx, } /* Check that iteration matches */ - if (received->iteration != payload->iteration) { + if (received.iteration != payload->iteration) { netif_err(efx, drv, efx->net_dev, "saw RX packet from iteration %d (wanted %d) in " - "%s loopback test\n", ntohs(received->iteration), + "%s loopback test\n", ntohs(received.iteration), ntohs(payload->iteration), LOOPBACK_MODE(efx)); goto err; } @@ -363,7 +368,8 @@ void efx_siena_loopback_rx_packet(struct efx_nic *efx, buf_ptr, pkt_len, 0); netif_err(efx, drv, efx->net_dev, "expected packet:\n"); print_hex_dump(KERN_ERR, "", DUMP_PREFIX_OFFSET, 0x10, 1, - &state->payload, sizeof(state->payload), 0); + &state->payload.header, EFX_LOOPBACK_PAYLOAD_LEN, + 0); } #endif atomic_inc(&state->rx_bad); @@ -385,14 +391,15 @@ static void efx_iterate_state(struct efx_nic *efx) payload->ip.daddr = htonl(INADDR_LOOPBACK); payload->ip.ihl = 5; payload->ip.check = (__force __sum16) htons(0xdead); - payload->ip.tot_len = htons(sizeof(*payload) - sizeof(struct ethhdr)); + payload->ip.tot_len = htons(sizeof(*payload) - + offsetof(struct efx_loopback_payload, ip)); payload->ip.version = IPVERSION; payload->ip.protocol = IPPROTO_UDP; /* Initialise udp header */ payload->udp.source = 0; - payload->udp.len = htons(sizeof(*payload) - sizeof(struct ethhdr) - - sizeof(struct iphdr)); + payload->udp.len = htons(sizeof(*payload) - + offsetof(struct efx_loopback_payload, udp)); payload->udp.check = 0; /* checksum ignored */ /* Fill out payload */ @@ -418,7 +425,7 @@ static int efx_begin_loopback(struct efx_tx_queue *tx_queue) for (i = 0; i < state->packet_count; i++) { /* Allocate an skb, holding an extra reference for * transmit completion counting */ - skb = alloc_skb(sizeof(state->payload), GFP_KERNEL); + skb = alloc_skb(EFX_LOOPBACK_PAYLOAD_LEN, GFP_KERNEL); if (!skb) return -ENOMEM; state->skbs[i] = skb; @@ -429,6 +436,8 @@ static int efx_begin_loopback(struct efx_tx_queue *tx_queue) payload = skb_put(skb, sizeof(state->payload)); memcpy(payload, &state->payload, sizeof(state->payload)); payload->ip.saddr = htonl(INADDR_LOOPBACK | (i << 2)); + /* Strip off the leading padding */ + skb_pull(skb, offsetof(struct efx_loopback_payload, header)); /* Ensure everything we've written is visible to the * interrupt handler. */ diff --git a/drivers/net/ethernet/sfc/siena/tx_common.c b/drivers/net/ethernet/sfc/siena/tx_common.c index 93a32d61944f08fdb9434174bbb68054ae01c3a9..a7a9ab304e13686dbddbb8718d1af4df664c44e5 100644 --- a/drivers/net/ethernet/sfc/siena/tx_common.c +++ b/drivers/net/ethernet/sfc/siena/tx_common.c @@ -12,6 +12,7 @@ #include "efx.h" #include "nic_common.h" #include "tx_common.h" +#include static unsigned int efx_tx_cb_page_count(struct efx_tx_queue *tx_queue) { diff --git a/drivers/net/ethernet/sfc/tc.c b/drivers/net/ethernet/sfc/tc.c index c004443c1d58c3eebe042489fb18b1430688cd27..15ebd39739224fdb7d87df83048c8a8b11775f1f 100644 --- a/drivers/net/ethernet/sfc/tc.c +++ b/drivers/net/ethernet/sfc/tc.c @@ -14,11 +14,12 @@ #include #include "tc.h" #include "tc_bindings.h" +#include "tc_encap_actions.h" #include "mae.h" #include "ef100_rep.h" #include "efx.h" -static enum efx_encap_type efx_tc_indr_netdev_type(struct net_device *net_dev) +enum efx_encap_type efx_tc_indr_netdev_type(struct net_device *net_dev) { if (netif_is_vxlan(net_dev)) return EFX_ENCAP_TYPE_VXLAN; @@ -33,8 +34,8 @@ static enum efx_encap_type efx_tc_indr_netdev_type(struct net_device *net_dev) * May return NULL for the PF (us), or an error pointer for a device that * isn't supported as a TC offload endpoint */ -static struct efx_rep *efx_tc_flower_lookup_efv(struct efx_nic *efx, - struct net_device *dev) +struct efx_rep *efx_tc_flower_lookup_efv(struct efx_nic *efx, + struct net_device *dev) { struct efx_rep *efv; @@ -70,7 +71,7 @@ static s64 efx_tc_flower_internal_mport(struct efx_nic *efx, struct efx_rep *efv } /* Convert a driver-internal vport ID into an external device (wire or VF) */ -static s64 efx_tc_flower_external_mport(struct efx_nic *efx, struct efx_rep *efv) +s64 efx_tc_flower_external_mport(struct efx_nic *efx, struct efx_rep *efv) { u32 mport; @@ -109,8 +110,17 @@ static void efx_tc_free_action_set(struct efx_nic *efx, */ list_del(&act->list); } - if (act->count) + if (act->count) { + spin_lock_bh(&act->count->cnt->lock); + if (!list_empty(&act->count_user)) + list_del(&act->count_user); + spin_unlock_bh(&act->count->cnt->lock); efx_tc_flower_put_counter_index(efx, act->count); + } + if (act->encap_md) { + list_del(&act->encap_user); + efx_tc_flower_release_encap_md(efx, act->encap_md); + } kfree(act); } @@ -132,23 +142,6 @@ static void efx_tc_free_action_set_list(struct efx_nic *efx, /* Don't kfree, as acts is embedded inside a struct efx_tc_flow_rule */ } -static void efx_tc_flow_free(void *ptr, void *arg) -{ - struct efx_tc_flow_rule *rule = ptr; - struct efx_nic *efx = arg; - - netif_err(efx, drv, efx->net_dev, - "tc rule %lx still present at teardown, removing\n", - rule->cookie); - - efx_mae_delete_rule(efx, rule->fw_id); - - /* Release entries in subsidiary tables */ - efx_tc_free_action_set_list(efx, &rule->acts, true); - - kfree(rule); -} - /* Boilerplate for the simple 'copy a field' cases */ #define _MAP_KEY_AND_MASK(_name, _type, _tcget, _tcfield, _field) \ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_##_name)) { \ @@ -219,6 +212,7 @@ static int efx_tc_flower_parse_match(struct efx_nic *efx, BIT(FLOW_DISSECTOR_KEY_ENC_KEYID) | BIT(FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS) | BIT(FLOW_DISSECTOR_KEY_ENC_IPV6_ADDRS) | + BIT(FLOW_DISSECTOR_KEY_ENC_IP) | BIT(FLOW_DISSECTOR_KEY_ENC_PORTS) | BIT(FLOW_DISSECTOR_KEY_ENC_CONTROL) | BIT(FLOW_DISSECTOR_KEY_TCP) | @@ -363,20 +357,48 @@ static int efx_tc_flower_parse_match(struct efx_nic *efx, return 0; } +static void efx_tc_flower_release_encap_match(struct efx_nic *efx, + struct efx_tc_encap_match *encap) +{ + int rc; + + if (!refcount_dec_and_test(&encap->ref)) + return; /* still in use */ + + if (encap->type == EFX_TC_EM_DIRECT) { + rc = efx_mae_unregister_encap_match(efx, encap); + if (rc) + /* Display message but carry on and remove entry from our + * SW tables, because there's not much we can do about it. + */ + netif_err(efx, drv, efx->net_dev, + "Failed to release encap match %#x, rc %d\n", + encap->fw_id, rc); + } + rhashtable_remove_fast(&efx->tc->encap_match_ht, &encap->linkage, + efx_tc_encap_match_ht_params); + if (encap->pseudo) + efx_tc_flower_release_encap_match(efx, encap->pseudo); + kfree(encap); +} + static int efx_tc_flower_record_encap_match(struct efx_nic *efx, struct efx_tc_match *match, enum efx_encap_type type, + enum efx_tc_em_pseudo_type em_type, + u8 child_ip_tos_mask, + __be16 child_udp_sport_mask, struct netlink_ext_ack *extack) { - struct efx_tc_encap_match *encap, *old; + struct efx_tc_encap_match *encap, *old, *pseudo = NULL; bool ipv6 = false; int rc; /* We require that the socket-defining fields (IP addrs and UDP dest - * port) are present and exact-match. Other fields are currently not - * allowed. This meets what OVS will ask for, and means that we don't - * need to handle difficult checks for overlapping matches as could - * come up if we allowed masks or varying sets of match fields. + * port) are present and exact-match. Other fields may only be used + * if the field-set (and any masks) are the same for all encap + * matches on the same tuple; this is enforced by + * pseudo encap matches. */ if (match->mask.enc_dst_ip | match->mask.enc_src_ip) { if (!IS_ALL_ONES(match->mask.enc_dst_ip)) { @@ -414,29 +436,42 @@ static int efx_tc_flower_record_encap_match(struct efx_nic *efx, NL_SET_ERR_MSG_MOD(extack, "Egress encap match is not exact on dst UDP port"); return -EOPNOTSUPP; } - if (match->mask.enc_sport) { - NL_SET_ERR_MSG_MOD(extack, "Egress encap match on src UDP port not supported"); - return -EOPNOTSUPP; - } - if (match->mask.enc_ip_tos) { - NL_SET_ERR_MSG_MOD(extack, "Egress encap match on IP ToS not supported"); - return -EOPNOTSUPP; + if (match->mask.enc_sport || match->mask.enc_ip_tos) { + struct efx_tc_match pmatch = *match; + + if (em_type == EFX_TC_EM_PSEUDO_MASK) { /* can't happen */ + NL_SET_ERR_MSG_MOD(extack, "Bad recursion in egress encap match handler"); + return -EOPNOTSUPP; + } + pmatch.value.enc_ip_tos = 0; + pmatch.mask.enc_ip_tos = 0; + pmatch.value.enc_sport = 0; + pmatch.mask.enc_sport = 0; + rc = efx_tc_flower_record_encap_match(efx, &pmatch, type, + EFX_TC_EM_PSEUDO_MASK, + match->mask.enc_ip_tos, + match->mask.enc_sport, + extack); + if (rc) + return rc; + pseudo = pmatch.encap; } if (match->mask.enc_ip_ttl) { NL_SET_ERR_MSG_MOD(extack, "Egress encap match on IP TTL not supported"); - return -EOPNOTSUPP; + rc = -EOPNOTSUPP; + goto fail_pseudo; } - rc = efx_mae_check_encap_match_caps(efx, ipv6, extack); - if (rc) { - NL_SET_ERR_MSG_FMT_MOD(extack, "MAE hw reports no support for IPv%d encap matches", - ipv6 ? 6 : 4); - return -EOPNOTSUPP; - } + rc = efx_mae_check_encap_match_caps(efx, ipv6, match->mask.enc_ip_tos, + match->mask.enc_sport, extack); + if (rc) + goto fail_pseudo; encap = kzalloc(sizeof(*encap), GFP_USER); - if (!encap) - return -ENOMEM; + if (!encap) { + rc = -ENOMEM; + goto fail_pseudo; + } encap->src_ip = match->value.enc_src_ip; encap->dst_ip = match->value.enc_dst_ip; #ifdef CONFIG_IPV6 @@ -445,12 +480,66 @@ static int efx_tc_flower_record_encap_match(struct efx_nic *efx, #endif encap->udp_dport = match->value.enc_dport; encap->tun_type = type; + encap->ip_tos = match->value.enc_ip_tos; + encap->ip_tos_mask = match->mask.enc_ip_tos; + encap->child_ip_tos_mask = child_ip_tos_mask; + encap->udp_sport = match->value.enc_sport; + encap->udp_sport_mask = match->mask.enc_sport; + encap->child_udp_sport_mask = child_udp_sport_mask; + encap->type = em_type; + encap->pseudo = pseudo; old = rhashtable_lookup_get_insert_fast(&efx->tc->encap_match_ht, &encap->linkage, efx_tc_encap_match_ht_params); if (old) { /* don't need our new entry */ kfree(encap); + if (pseudo) /* don't need our new pseudo either */ + efx_tc_flower_release_encap_match(efx, pseudo); + /* check old and new em_types are compatible */ + switch (old->type) { + case EFX_TC_EM_DIRECT: + /* old EM is in hardware, so mustn't overlap with a + * pseudo, but may be shared with another direct EM + */ + if (em_type == EFX_TC_EM_DIRECT) + break; + NL_SET_ERR_MSG_MOD(extack, "Pseudo encap match conflicts with existing direct entry"); + return -EEXIST; + case EFX_TC_EM_PSEUDO_MASK: + /* old EM is protecting a ToS- or src port-qualified + * filter, so may only be shared with another pseudo + * for the same ToS and src port masks. + */ + if (em_type != EFX_TC_EM_PSEUDO_MASK) { + NL_SET_ERR_MSG_FMT_MOD(extack, + "%s encap match conflicts with existing pseudo(MASK) entry", + em_type ? "Pseudo" : "Direct"); + return -EEXIST; + } + if (child_ip_tos_mask != old->child_ip_tos_mask) { + NL_SET_ERR_MSG_FMT_MOD(extack, + "Pseudo encap match for TOS mask %#04x conflicts with existing pseudo(MASK) entry for TOS mask %#04x", + child_ip_tos_mask, + old->child_ip_tos_mask); + return -EEXIST; + } + if (child_udp_sport_mask != old->child_udp_sport_mask) { + NL_SET_ERR_MSG_FMT_MOD(extack, + "Pseudo encap match for UDP src port mask %#x conflicts with existing pseudo(MASK) entry for mask %#x", + child_udp_sport_mask, + old->child_udp_sport_mask); + return -EEXIST; + } + break; + default: /* Unrecognised pseudo-type. Just say no */ + NL_SET_ERR_MSG_FMT_MOD(extack, + "%s encap match conflicts with existing pseudo(%d) entry", + em_type ? "Pseudo" : "Direct", + old->type); + return -EEXIST; + } + /* check old and new tun_types are compatible */ if (old->tun_type != type) { NL_SET_ERR_MSG_FMT_MOD(extack, "Egress encap match with conflicting tun_type %u != %u", @@ -462,10 +551,12 @@ static int efx_tc_flower_record_encap_match(struct efx_nic *efx, /* existing entry found */ encap = old; } else { - rc = efx_mae_register_encap_match(efx, encap); - if (rc) { - NL_SET_ERR_MSG_MOD(extack, "Failed to record egress encap match in HW"); - goto fail; + if (em_type == EFX_TC_EM_DIRECT) { + rc = efx_mae_register_encap_match(efx, encap); + if (rc) { + NL_SET_ERR_MSG_MOD(extack, "Failed to record egress encap match in HW"); + goto fail; + } } refcount_set(&encap->ref, 1); } @@ -475,30 +566,12 @@ static int efx_tc_flower_record_encap_match(struct efx_nic *efx, rhashtable_remove_fast(&efx->tc->encap_match_ht, &encap->linkage, efx_tc_encap_match_ht_params); kfree(encap); +fail_pseudo: + if (pseudo) + efx_tc_flower_release_encap_match(efx, pseudo); return rc; } -static void efx_tc_flower_release_encap_match(struct efx_nic *efx, - struct efx_tc_encap_match *encap) -{ - int rc; - - if (!refcount_dec_and_test(&encap->ref)) - return; /* still in use */ - - rc = efx_mae_unregister_encap_match(efx, encap); - if (rc) - /* Display message but carry on and remove entry from our - * SW tables, because there's not much we can do about it. - */ - netif_err(efx, drv, efx->net_dev, - "Failed to release encap match %#x, rc %d\n", - encap->fw_id, rc); - rhashtable_remove_fast(&efx->tc->encap_match_ht, &encap->linkage, - efx_tc_encap_match_ht_params); - kfree(encap); -} - static void efx_tc_delete_rule(struct efx_nic *efx, struct efx_tc_flow_rule *rule) { efx_mae_delete_rule(efx, rule->fw_id); @@ -531,6 +604,7 @@ enum efx_tc_action_order { EFX_TC_AO_VLAN_POP, EFX_TC_AO_VLAN_PUSH, EFX_TC_AO_COUNT, + EFX_TC_AO_ENCAP, EFX_TC_AO_DELIVER }; /* Determine whether we can add @new action without violating order */ @@ -560,6 +634,10 @@ static bool efx_tc_flower_action_order_ok(const struct efx_tc_action_set *act, if (act->count) return false; fallthrough; + case EFX_TC_AO_ENCAP: + if (act->encap_md) + return false; + fallthrough; case EFX_TC_AO_DELIVER: return !act->deliver; default: @@ -650,6 +728,7 @@ static int efx_tc_flower_replace_foreign(struct efx_nic *efx, } rc = efx_tc_flower_record_encap_match(efx, &match, type, + EFX_TC_EM_DIRECT, 0, 0, extack); if (rc) return rc; @@ -722,6 +801,7 @@ static int efx_tc_flower_replace_foreign(struct efx_nic *efx, goto release; } act->count = ctr; + INIT_LIST_HEAD(&act->count_user); } if (!efx_tc_flower_action_order_ok(act, EFX_TC_AO_DELIVER)) { @@ -854,11 +934,13 @@ static int efx_tc_flower_replace(struct efx_nic *efx, { struct flow_rule *fr = flow_cls_offload_flow_rule(tc); struct netlink_ext_ack *extack = tc->common.extack; + const struct ip_tunnel_info *encap_info = NULL; struct efx_tc_flow_rule *rule = NULL, *old; struct efx_tc_action_set *act = NULL; const struct flow_action_entry *fa; struct efx_rep *from_efv, *to_efv; struct efx_tc_match match; + u32 acts_id; s64 rc; int i; @@ -1007,6 +1089,7 @@ static int efx_tc_flower_replace(struct efx_nic *efx, goto release; } act->count = ctr; + INIT_LIST_HEAD(&act->count_user); } switch (fa->id) { @@ -1023,6 +1106,59 @@ static int efx_tc_flower_replace(struct efx_nic *efx, case FLOW_ACTION_MIRRED: save = *act; + if (encap_info) { + struct efx_tc_encap_action *encap; + + if (!efx_tc_flower_action_order_ok(act, + EFX_TC_AO_ENCAP)) { + rc = -EOPNOTSUPP; + NL_SET_ERR_MSG_MOD(extack, "Encap action violates action order"); + goto release; + } + encap = efx_tc_flower_create_encap_md( + efx, encap_info, fa->dev, extack); + if (IS_ERR_OR_NULL(encap)) { + rc = PTR_ERR(encap); + if (!rc) + rc = -EIO; /* arbitrary */ + goto release; + } + act->encap_md = encap; + list_add_tail(&act->encap_user, &encap->users); + act->dest_mport = encap->dest_mport; + act->deliver = 1; + if (act->count && !WARN_ON(!act->count->cnt)) { + /* This counter is used by an encap + * action, which needs a reference back + * so it can prod neighbouring whenever + * traffic is seen. + */ + spin_lock_bh(&act->count->cnt->lock); + list_add_tail(&act->count_user, + &act->count->cnt->users); + spin_unlock_bh(&act->count->cnt->lock); + } + rc = efx_mae_alloc_action_set(efx, act); + if (rc) { + NL_SET_ERR_MSG_MOD(extack, "Failed to write action set to hw (encap)"); + goto release; + } + list_add_tail(&act->list, &rule->acts.list); + act->user = &rule->acts; + act = NULL; + if (fa->id == FLOW_ACTION_REDIRECT) + break; /* end of the line */ + /* Mirror, so continue on with saved act */ + save.count = NULL; + act = kzalloc(sizeof(*act), GFP_USER); + if (!act) { + rc = -ENOMEM; + goto release; + } + *act = save; + break; + } + if (!efx_tc_flower_action_order_ok(act, EFX_TC_AO_DELIVER)) { /* can't happen */ rc = -EOPNOTSUPP; @@ -1086,6 +1222,37 @@ static int efx_tc_flower_replace(struct efx_nic *efx, act->vlan_proto[act->vlan_push] = fa->vlan.proto; act->vlan_push++; break; + case FLOW_ACTION_TUNNEL_ENCAP: + if (encap_info) { + /* Can't specify encap multiple times. + * If you want to overwrite an existing + * encap_info, use an intervening + * FLOW_ACTION_TUNNEL_DECAP to clear it. + */ + NL_SET_ERR_MSG_MOD(extack, "Tunnel key set when already set"); + rc = -EINVAL; + goto release; + } + if (!fa->tunnel) { + NL_SET_ERR_MSG_MOD(extack, "Tunnel key set is missing key"); + rc = -EOPNOTSUPP; + goto release; + } + encap_info = fa->tunnel; + break; + case FLOW_ACTION_TUNNEL_DECAP: + if (encap_info) { + encap_info = NULL; + break; + } + /* Since we don't support enc_key matches on ingress + * (and if we did there'd be no tunnel-device to give + * us a type), we can't offload a decap that's not + * just undoing a previous encap action. + */ + NL_SET_ERR_MSG_MOD(extack, "Cannot offload tunnel decap action without tunnel device"); + rc = -EOPNOTSUPP; + goto release; default: NL_SET_ERR_MSG_FMT_MOD(extack, "Unhandled action %u", fa->id); @@ -1129,8 +1296,21 @@ static int efx_tc_flower_replace(struct efx_nic *efx, NL_SET_ERR_MSG_MOD(extack, "Failed to write action set list to hw"); goto release; } + if (from_efv == EFX_EFV_PF) + /* PF netdev, so rule applies to traffic from wire */ + rule->fallback = &efx->tc->facts.pf; + else + /* repdev, so rule applies to traffic from representee */ + rule->fallback = &efx->tc->facts.reps; + if (!efx_tc_check_ready(efx, rule)) { + netif_dbg(efx, drv, efx->net_dev, "action not ready for hw\n"); + acts_id = rule->fallback->fw_id; + } else { + netif_dbg(efx, drv, efx->net_dev, "ready for hw\n"); + acts_id = rule->acts.fw_id; + } rc = efx_mae_insert_rule(efx, &rule->match, EFX_TC_PRIO_TC, - rule->acts.fw_id, &rule->fw_id); + acts_id, &rule->fw_id); if (rc) { NL_SET_ERR_MSG_MOD(extack, "Failed to insert rule in hw"); goto release_acts; @@ -1327,6 +1507,58 @@ void efx_tc_deconfigure_default_rule(struct efx_nic *efx, rule->fw_id = MC_CMD_MAE_ACTION_RULE_INSERT_OUT_ACTION_RULE_ID_NULL; } +static int efx_tc_configure_fallback_acts(struct efx_nic *efx, u32 eg_port, + struct efx_tc_action_set_list *acts) +{ + struct efx_tc_action_set *act; + int rc; + + act = kzalloc(sizeof(*act), GFP_KERNEL); + if (!act) + return -ENOMEM; + act->deliver = 1; + act->dest_mport = eg_port; + rc = efx_mae_alloc_action_set(efx, act); + if (rc) + goto fail1; + EFX_WARN_ON_PARANOID(!list_empty(&acts->list)); + list_add_tail(&act->list, &acts->list); + rc = efx_mae_alloc_action_set_list(efx, acts); + if (rc) + goto fail2; + return 0; +fail2: + list_del(&act->list); + efx_mae_free_action_set(efx, act->fw_id); +fail1: + kfree(act); + return rc; +} + +static int efx_tc_configure_fallback_acts_pf(struct efx_nic *efx) +{ + struct efx_tc_action_set_list *acts = &efx->tc->facts.pf; + u32 eg_port; + + efx_mae_mport_uplink(efx, &eg_port); + return efx_tc_configure_fallback_acts(efx, eg_port, acts); +} + +static int efx_tc_configure_fallback_acts_reps(struct efx_nic *efx) +{ + struct efx_tc_action_set_list *acts = &efx->tc->facts.reps; + u32 eg_port; + + efx_mae_mport_mport(efx, efx->tc->reps_mport_id, &eg_port); + return efx_tc_configure_fallback_acts(efx, eg_port, acts); +} + +static void efx_tc_deconfigure_fallback_acts(struct efx_nic *efx, + struct efx_tc_action_set_list *acts) +{ + efx_tc_free_action_set_list(efx, acts, true); +} + static int efx_tc_configure_rep_mport(struct efx_nic *efx) { u32 rep_mport_label; @@ -1417,6 +1649,12 @@ int efx_init_tc(struct efx_nic *efx) if (rc) return rc; rc = efx_tc_configure_rep_mport(efx); + if (rc) + return rc; + rc = efx_tc_configure_fallback_acts_pf(efx); + if (rc) + return rc; + rc = efx_tc_configure_fallback_acts_reps(efx); if (rc) return rc; efx->tc->up = true; @@ -1436,6 +1674,8 @@ void efx_fini_tc(struct efx_nic *efx) efx_tc_deconfigure_rep_mport(efx); efx_tc_deconfigure_default_rule(efx, &efx->tc->dflt.pf); efx_tc_deconfigure_default_rule(efx, &efx->tc->dflt.wire); + efx_tc_deconfigure_fallback_acts(efx, &efx->tc->facts.pf); + efx_tc_deconfigure_fallback_acts(efx, &efx->tc->facts.reps); efx->tc->up = false; } @@ -1451,6 +1691,21 @@ static void efx_tc_encap_match_free(void *ptr, void *__unused) kfree(encap); } +static void efx_tc_flow_free(void *ptr, void *arg) +{ + struct efx_tc_flow_rule *rule = ptr; + struct efx_nic *efx = arg; + + netif_err(efx, drv, efx->net_dev, + "tc rule %lx still present at teardown, removing\n", + rule->cookie); + + /* Also releases entries in subsidiary tables */ + efx_tc_delete_rule(efx, rule); + + kfree(rule); +} + int efx_init_struct_tc(struct efx_nic *efx) { int rc; @@ -1470,6 +1725,9 @@ int efx_init_struct_tc(struct efx_nic *efx) mutex_init(&efx->tc->mutex); init_waitqueue_head(&efx->tc->flush_wq); + rc = efx_tc_init_encap_actions(efx); + if (rc < 0) + goto fail_encap_actions; rc = efx_tc_init_counters(efx); if (rc < 0) goto fail_counters; @@ -1485,6 +1743,10 @@ int efx_init_struct_tc(struct efx_nic *efx) efx->tc->dflt.pf.fw_id = MC_CMD_MAE_ACTION_RULE_INSERT_OUT_ACTION_RULE_ID_NULL; INIT_LIST_HEAD(&efx->tc->dflt.wire.acts.list); efx->tc->dflt.wire.fw_id = MC_CMD_MAE_ACTION_RULE_INSERT_OUT_ACTION_RULE_ID_NULL; + INIT_LIST_HEAD(&efx->tc->facts.pf.list); + efx->tc->facts.pf.fw_id = MC_CMD_MAE_ACTION_SET_ALLOC_OUT_ACTION_SET_ID_NULL; + INIT_LIST_HEAD(&efx->tc->facts.reps.list); + efx->tc->facts.reps.fw_id = MC_CMD_MAE_ACTION_SET_ALLOC_OUT_ACTION_SET_ID_NULL; efx->extra_channel_type[EFX_EXTRA_CHANNEL_TC] = &efx_tc_channel_type; return 0; fail_match_action_ht: @@ -1492,6 +1754,8 @@ int efx_init_struct_tc(struct efx_nic *efx) fail_encap_match_ht: efx_tc_destroy_counters(efx); fail_counters: + efx_tc_destroy_encap_actions(efx); +fail_encap_actions: mutex_destroy(&efx->tc->mutex); kfree(efx->tc->caps); fail_alloc_caps: @@ -1510,11 +1774,16 @@ void efx_fini_struct_tc(struct efx_nic *efx) MC_CMD_MAE_ACTION_RULE_INSERT_OUT_ACTION_RULE_ID_NULL); EFX_WARN_ON_PARANOID(efx->tc->dflt.wire.fw_id != MC_CMD_MAE_ACTION_RULE_INSERT_OUT_ACTION_RULE_ID_NULL); + EFX_WARN_ON_PARANOID(efx->tc->facts.pf.fw_id != + MC_CMD_MAE_ACTION_SET_LIST_ALLOC_OUT_ACTION_SET_LIST_ID_NULL); + EFX_WARN_ON_PARANOID(efx->tc->facts.reps.fw_id != + MC_CMD_MAE_ACTION_SET_LIST_ALLOC_OUT_ACTION_SET_LIST_ID_NULL); rhashtable_free_and_destroy(&efx->tc->match_action_ht, efx_tc_flow_free, efx); rhashtable_free_and_destroy(&efx->tc->encap_match_ht, efx_tc_encap_match_free, NULL); efx_tc_fini_counters(efx); + efx_tc_fini_encap_actions(efx); mutex_unlock(&efx->tc->mutex); mutex_destroy(&efx->tc->mutex); kfree(efx->tc->caps); diff --git a/drivers/net/ethernet/sfc/tc.h b/drivers/net/ethernet/sfc/tc.h index 04cced6a2d39ffc1e015cf0f80f1bca266600097..1549c3df43bbe4744515f8a45e8632ddd8c32416 100644 --- a/drivers/net/ethernet/sfc/tc.h +++ b/drivers/net/ethernet/sfc/tc.h @@ -25,6 +25,8 @@ static inline bool efx_ipv6_addr_all_ones(struct in6_addr *addr) } #endif +struct efx_tc_encap_action; /* see tc_encap_actions.h */ + struct efx_tc_action_set { u16 vlan_push:2; u16 vlan_pop:2; @@ -33,6 +35,10 @@ struct efx_tc_action_set { __be16 vlan_tci[2]; /* TCIs for vlan_push */ __be16 vlan_proto[2]; /* Ethertypes for vlan_push */ struct efx_tc_counter_index *count; + struct efx_tc_encap_action *encap_md; /* entry in tc_encap_ht table */ + struct list_head encap_user; /* entry on encap_md->users list */ + struct efx_tc_action_set_list *user; /* Only populated if encap_md */ + struct list_head count_user; /* entry on counter->users list, if encap */ u32 dest_mport; u32 fw_id; /* index of this entry in firmware actions table */ struct list_head list; @@ -74,14 +80,41 @@ static inline bool efx_tc_match_is_encap(const struct efx_tc_match_fields *mask) mask->enc_ip_ttl || mask->enc_sport || mask->enc_dport; } +/** + * enum efx_tc_em_pseudo_type - &struct efx_tc_encap_match pseudo type + * + * These are used to classify "pseudo" encap matches, which don't refer + * to an entry in hardware but rather indicate that a section of the + * match space is in use by another Outer Rule. + * + * @EFX_TC_EM_DIRECT: real HW entry in Outer Rule table; not a pseudo. + * Hardware index in &struct efx_tc_encap_match.fw_id is valid. + * @EFX_TC_EM_PSEUDO_MASK: registered by an encap match which includes a + * match on an optional field (currently ip_tos and/or udp_sport), + * to prevent an overlapping encap match _without_ optional fields. + * The pseudo encap match may be referenced again by an encap match + * with different values for these fields, but all masks must match the + * first (stored in our child_* fields). + */ +enum efx_tc_em_pseudo_type { + EFX_TC_EM_DIRECT, + EFX_TC_EM_PSEUDO_MASK, +}; + struct efx_tc_encap_match { __be32 src_ip, dst_ip; struct in6_addr src_ip6, dst_ip6; __be16 udp_dport; + __be16 udp_sport, udp_sport_mask; + u8 ip_tos, ip_tos_mask; struct rhash_head linkage; enum efx_encap_type tun_type; + u8 child_ip_tos_mask; + __be16 child_udp_sport_mask; refcount_t ref; + enum efx_tc_em_pseudo_type type; u32 fw_id; /* index of this entry in firmware encap match table */ + struct efx_tc_encap_match *pseudo; /* Referenced pseudo EM if needed */ }; struct efx_tc_match { @@ -100,6 +133,7 @@ struct efx_tc_flow_rule { struct rhash_head linkage; struct efx_tc_match match; struct efx_tc_action_set_list acts; + struct efx_tc_action_set_list *fallback; /* what to use when unready? */ u32 fw_id; }; @@ -117,8 +151,10 @@ enum efx_tc_rule_prios { * @mutex: Used to serialise operations on TC hashtables * @counter_ht: Hashtable of TC counters (FW IDs and counter values) * @counter_id_ht: Hashtable mapping TC counter cookies to counters + * @encap_ht: Hashtable of TC encap actions * @encap_match_ht: Hashtable of TC encap matches * @match_action_ht: Hashtable of TC match-action rules + * @neigh_ht: Hashtable of neighbour watches (&struct efx_neigh_binder) * @reps_mport_id: MAE port allocated for representor RX * @reps_filter_uc: VNIC filter for representor unicast RX (promisc) * @reps_filter_mc: VNIC filter for representor multicast RX (allmulti) @@ -133,6 +169,11 @@ enum efx_tc_rule_prios { * %EFX_TC_PRIO_DFLT. Named by *ingress* port * @dflt.pf: rule for traffic ingressing from PF (egresses to wire) * @dflt.wire: rule for traffic ingressing from wire (egresses to PF) + * @facts: Fallback action-set-lists for unready rules. Named by *egress* port + * @facts.pf: action-set-list for unready rules on PF netdev, hence applying to + * traffic from wire, and egressing to PF + * @facts.reps: action-set-list for unready rules on representors, hence + * applying to traffic from representees, and egressing to the reps mport * @up: have TC datastructures been set up? */ struct efx_tc_state { @@ -141,8 +182,10 @@ struct efx_tc_state { struct mutex mutex; struct rhashtable counter_ht; struct rhashtable counter_id_ht; + struct rhashtable encap_ht; struct rhashtable encap_match_ht; struct rhashtable match_action_ht; + struct rhashtable neigh_ht; u32 reps_mport_id, reps_mport_vport_id; s32 reps_filter_uc, reps_filter_mc; bool flush_counters; @@ -153,11 +196,19 @@ struct efx_tc_state { struct efx_tc_flow_rule pf; struct efx_tc_flow_rule wire; } dflt; + struct { + struct efx_tc_action_set_list pf; + struct efx_tc_action_set_list reps; + } facts; bool up; }; struct efx_rep; +enum efx_encap_type efx_tc_indr_netdev_type(struct net_device *net_dev); +struct efx_rep *efx_tc_flower_lookup_efv(struct efx_nic *efx, + struct net_device *dev); +s64 efx_tc_flower_external_mport(struct efx_nic *efx, struct efx_rep *efv); int efx_tc_configure_default_rule_rep(struct efx_rep *efv); void efx_tc_deconfigure_default_rule(struct efx_nic *efx, struct efx_tc_flow_rule *rule); diff --git a/drivers/net/ethernet/sfc/tc_bindings.c b/drivers/net/ethernet/sfc/tc_bindings.c index c18d64519c2db92faf371e321a18ea0a46752488..1b79c535c54ed5a326f387fae178cc2113dcda8f 100644 --- a/drivers/net/ethernet/sfc/tc_bindings.c +++ b/drivers/net/ethernet/sfc/tc_bindings.c @@ -10,6 +10,7 @@ #include "tc_bindings.h" #include "tc.h" +#include "tc_encap_actions.h" struct efx_tc_block_binding { struct list_head list; @@ -226,3 +227,15 @@ int efx_tc_setup(struct net_device *net_dev, enum tc_setup_type type, return -EOPNOTSUPP; } + +int efx_tc_netdev_event(struct efx_nic *efx, unsigned long event, + struct net_device *net_dev) +{ + if (efx->type->is_vf) + return NOTIFY_DONE; + + if (event == NETDEV_UNREGISTER) + efx_tc_unregister_egdev(efx, net_dev); + + return NOTIFY_OK; +} diff --git a/drivers/net/ethernet/sfc/tc_bindings.h b/drivers/net/ethernet/sfc/tc_bindings.h index c210bb09150ee632734a89456512ec1348c362f6..a326d23d322b7b0e60dc5121aa3530c05ddf2640 100644 --- a/drivers/net/ethernet/sfc/tc_bindings.h +++ b/drivers/net/ethernet/sfc/tc_bindings.h @@ -12,6 +12,7 @@ #define EFX_TC_BINDINGS_H #include "net_driver.h" +#if IS_ENABLED(CONFIG_SFC_SRIOV) #include struct efx_rep; @@ -26,4 +27,17 @@ int efx_tc_indr_setup_cb(struct net_device *net_dev, struct Qdisc *sch, void *cb_priv, enum tc_setup_type type, void *type_data, void *data, void (*cleanup)(struct flow_block_cb *block_cb)); +int efx_tc_netdev_event(struct efx_nic *efx, unsigned long event, + struct net_device *net_dev); + +#else /* CONFIG_SFC_SRIOV */ + +static inline int efx_tc_netdev_event(struct efx_nic *efx, unsigned long event, + struct net_device *net_dev) +{ + return NOTIFY_DONE; +} + +#endif /* CONFIG_SFC_SRIOV */ + #endif /* EFX_TC_BINDINGS_H */ diff --git a/drivers/net/ethernet/sfc/tc_counters.c b/drivers/net/ethernet/sfc/tc_counters.c index d1a91d54c6bb4cdc1e8d558dd90e25fbee6bf20a..979f49058a0c0d89d88abe7d0e19c1732d00bb1b 100644 --- a/drivers/net/ethernet/sfc/tc_counters.c +++ b/drivers/net/ethernet/sfc/tc_counters.c @@ -9,6 +9,7 @@ */ #include "tc_counters.h" +#include "tc_encap_actions.h" #include "mae_counter_format.h" #include "mae.h" #include "rx_common.h" @@ -31,6 +32,15 @@ static void efx_tc_counter_free(void *ptr, void *__unused) { struct efx_tc_counter *cnt = ptr; + WARN_ON(!list_empty(&cnt->users)); + /* We'd like to synchronize_rcu() here, but unfortunately we aren't + * removing the element from the hashtable (it's not clear that's a + * safe thing to do in an rhashtable_free_and_destroy free_fn), so + * threads could still be obtaining new pointers to *cnt if they can + * race against this function at all. + */ + flush_work(&cnt->work); + EFX_WARN_ON_PARANOID(spin_is_locked(&cnt->lock)); kfree(cnt); } @@ -74,6 +84,49 @@ void efx_tc_fini_counters(struct efx_nic *efx) rhashtable_free_and_destroy(&efx->tc->counter_ht, efx_tc_counter_free, NULL); } +static void efx_tc_counter_work(struct work_struct *work) +{ + struct efx_tc_counter *cnt = container_of(work, struct efx_tc_counter, work); + struct efx_tc_encap_action *encap; + struct efx_tc_action_set *act; + unsigned long touched; + struct neighbour *n; + + spin_lock_bh(&cnt->lock); + touched = READ_ONCE(cnt->touched); + + list_for_each_entry(act, &cnt->users, count_user) { + encap = act->encap_md; + if (!encap) + continue; + if (!encap->neigh) /* can't happen */ + continue; + if (time_after_eq(encap->neigh->used, touched)) + continue; + encap->neigh->used = touched; + /* We have passed traffic using this ARP entry, so + * indicate to the ARP cache that it's still active + */ + if (encap->neigh->dst_ip) + n = neigh_lookup(&arp_tbl, &encap->neigh->dst_ip, + encap->neigh->egdev); + else +#if IS_ENABLED(CONFIG_IPV6) + n = neigh_lookup(ipv6_stub->nd_tbl, + &encap->neigh->dst_ip6, + encap->neigh->egdev); +#else + n = NULL; +#endif + if (!n) + continue; + + neigh_event_send(n, NULL); + neigh_release(n); + } + spin_unlock_bh(&cnt->lock); +} + /* Counter allocation */ static struct efx_tc_counter *efx_tc_flower_allocate_counter(struct efx_nic *efx, @@ -87,12 +140,14 @@ static struct efx_tc_counter *efx_tc_flower_allocate_counter(struct efx_nic *efx return ERR_PTR(-ENOMEM); spin_lock_init(&cnt->lock); + INIT_WORK(&cnt->work, efx_tc_counter_work); cnt->touched = jiffies; cnt->type = type; rc = efx_mae_allocate_counter(efx, cnt); if (rc) goto fail1; + INIT_LIST_HEAD(&cnt->users); rc = rhashtable_insert_fast(&efx->tc->counter_ht, &cnt->linkage, efx_tc_counter_ht_params); if (rc) @@ -126,6 +181,7 @@ static void efx_tc_flower_release_counter(struct efx_nic *efx, netif_warn(efx, hw, efx->net_dev, "Failed to free MAE counter %u, rc %d\n", cnt->fw_id, rc); + WARN_ON(!list_empty(&cnt->users)); /* This doesn't protect counter updates coming in arbitrarily long * after we deleted the counter. The RCU just ensures that we won't * free the counter while another thread has a pointer to it. @@ -133,6 +189,7 @@ static void efx_tc_flower_release_counter(struct efx_nic *efx, * is handled by the generation count. */ synchronize_rcu(); + flush_work(&cnt->work); EFX_WARN_ON_PARANOID(spin_is_locked(&cnt->lock)); kfree(cnt); } @@ -302,6 +359,7 @@ static void efx_tc_counter_update(struct efx_nic *efx, cnt->touched = jiffies; } spin_unlock_bh(&cnt->lock); + schedule_work(&cnt->work); out: rcu_read_unlock(); } diff --git a/drivers/net/ethernet/sfc/tc_counters.h b/drivers/net/ethernet/sfc/tc_counters.h index 8fc7c4bbb29ca9032fdf2bdfd4a8a63c165067cd..41e57f34b763a2e47101067445a42ec732a18833 100644 --- a/drivers/net/ethernet/sfc/tc_counters.h +++ b/drivers/net/ethernet/sfc/tc_counters.h @@ -32,6 +32,9 @@ struct efx_tc_counter { u64 old_packets, old_bytes; /* Values last time passed to userspace */ /* jiffies of the last time we saw packets increase */ unsigned long touched; + struct work_struct work; /* For notifying encap actions */ + /* owners of corresponding count actions */ + struct list_head users; }; struct efx_tc_counter_index { diff --git a/drivers/net/ethernet/sfc/tc_encap_actions.c b/drivers/net/ethernet/sfc/tc_encap_actions.c new file mode 100644 index 0000000000000000000000000000000000000000..7e8bcdb222ad18b4f175d5312613402d169dfbcd --- /dev/null +++ b/drivers/net/ethernet/sfc/tc_encap_actions.c @@ -0,0 +1,747 @@ +// SPDX-License-Identifier: GPL-2.0-only +/**************************************************************************** + * Driver for Solarflare network controllers and boards + * Copyright 2023, Advanced Micro Devices, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation, incorporated herein by reference. + */ + +#include "tc_encap_actions.h" +#include "tc.h" +#include "mae.h" +#include +#include +#include +#include + +static const struct rhashtable_params efx_neigh_ht_params = { + .key_len = offsetof(struct efx_neigh_binder, ha), + .key_offset = 0, + .head_offset = offsetof(struct efx_neigh_binder, linkage), +}; + +static const struct rhashtable_params efx_tc_encap_ht_params = { + .key_len = offsetofend(struct efx_tc_encap_action, key), + .key_offset = 0, + .head_offset = offsetof(struct efx_tc_encap_action, linkage), +}; + +static void efx_tc_encap_free(void *ptr, void *__unused) +{ + struct efx_tc_encap_action *enc = ptr; + + WARN_ON(refcount_read(&enc->ref)); + kfree(enc); +} + +static void efx_neigh_free(void *ptr, void *__unused) +{ + struct efx_neigh_binder *neigh = ptr; + + WARN_ON(refcount_read(&neigh->ref)); + WARN_ON(!list_empty(&neigh->users)); + put_net_track(neigh->net, &neigh->ns_tracker); + netdev_put(neigh->egdev, &neigh->dev_tracker); + kfree(neigh); +} + +int efx_tc_init_encap_actions(struct efx_nic *efx) +{ + int rc; + + rc = rhashtable_init(&efx->tc->neigh_ht, &efx_neigh_ht_params); + if (rc < 0) + goto fail_neigh_ht; + rc = rhashtable_init(&efx->tc->encap_ht, &efx_tc_encap_ht_params); + if (rc < 0) + goto fail_encap_ht; + return 0; +fail_encap_ht: + rhashtable_destroy(&efx->tc->neigh_ht); +fail_neigh_ht: + return rc; +} + +/* Only call this in init failure teardown. + * Normal exit should fini instead as there may be entries in the table. + */ +void efx_tc_destroy_encap_actions(struct efx_nic *efx) +{ + rhashtable_destroy(&efx->tc->encap_ht); + rhashtable_destroy(&efx->tc->neigh_ht); +} + +void efx_tc_fini_encap_actions(struct efx_nic *efx) +{ + rhashtable_free_and_destroy(&efx->tc->encap_ht, efx_tc_encap_free, NULL); + rhashtable_free_and_destroy(&efx->tc->neigh_ht, efx_neigh_free, NULL); +} + +static void efx_neigh_update(struct work_struct *work); + +static int efx_bind_neigh(struct efx_nic *efx, + struct efx_tc_encap_action *encap, struct net *net, + struct netlink_ext_ack *extack) +{ + struct efx_neigh_binder *neigh, *old; + struct flowi6 flow6 = {}; + struct flowi4 flow4 = {}; + int rc; + + /* GCC stupidly thinks that only values explicitly listed in the enum + * definition can _possibly_ be sensible case values, so without this + * cast it complains about the IPv6 versions. + */ + switch ((int)encap->type) { + case EFX_ENCAP_TYPE_VXLAN: + case EFX_ENCAP_TYPE_GENEVE: + flow4.flowi4_proto = IPPROTO_UDP; + flow4.fl4_dport = encap->key.tp_dst; + flow4.flowi4_tos = encap->key.tos; + flow4.daddr = encap->key.u.ipv4.dst; + flow4.saddr = encap->key.u.ipv4.src; + break; + case EFX_ENCAP_TYPE_VXLAN | EFX_ENCAP_FLAG_IPV6: + case EFX_ENCAP_TYPE_GENEVE | EFX_ENCAP_FLAG_IPV6: + flow6.flowi6_proto = IPPROTO_UDP; + flow6.fl6_dport = encap->key.tp_dst; + flow6.flowlabel = ip6_make_flowinfo(encap->key.tos, + encap->key.label); + flow6.daddr = encap->key.u.ipv6.dst; + flow6.saddr = encap->key.u.ipv6.src; + break; + default: + NL_SET_ERR_MSG_FMT_MOD(extack, "Unsupported encap type %d", + (int)encap->type); + return -EOPNOTSUPP; + } + + neigh = kzalloc(sizeof(*neigh), GFP_KERNEL_ACCOUNT); + if (!neigh) + return -ENOMEM; + neigh->net = get_net_track(net, &neigh->ns_tracker, GFP_KERNEL_ACCOUNT); + neigh->dst_ip = flow4.daddr; + neigh->dst_ip6 = flow6.daddr; + + old = rhashtable_lookup_get_insert_fast(&efx->tc->neigh_ht, + &neigh->linkage, + efx_neigh_ht_params); + if (old) { + /* don't need our new entry */ + put_net_track(neigh->net, &neigh->ns_tracker); + kfree(neigh); + if (!refcount_inc_not_zero(&old->ref)) + return -EAGAIN; + /* existing entry found, ref taken */ + neigh = old; + } else { + /* New entry. We need to initiate a lookup */ + struct neighbour *n; + struct rtable *rt; + + if (encap->type & EFX_ENCAP_FLAG_IPV6) { +#if IS_ENABLED(CONFIG_IPV6) + struct dst_entry *dst; + + dst = ipv6_stub->ipv6_dst_lookup_flow(net, NULL, &flow6, + NULL); + rc = PTR_ERR_OR_ZERO(dst); + if (rc) { + NL_SET_ERR_MSG_MOD(extack, "Failed to lookup route for IPv6 encap"); + goto out_free; + } + neigh->egdev = dst->dev; + netdev_hold(neigh->egdev, &neigh->dev_tracker, + GFP_KERNEL_ACCOUNT); + neigh->ttl = ip6_dst_hoplimit(dst); + n = dst_neigh_lookup(dst, &flow6.daddr); + dst_release(dst); +#else + /* We shouldn't ever get here, because if IPv6 isn't + * enabled how did someone create an IPv6 tunnel_key? + */ + rc = -EOPNOTSUPP; + NL_SET_ERR_MSG_MOD(extack, "No IPv6 support (neigh bind)"); + goto out_free; +#endif + } else { + rt = ip_route_output_key(net, &flow4); + if (IS_ERR_OR_NULL(rt)) { + rc = PTR_ERR_OR_ZERO(rt); + if (!rc) + rc = -EIO; + NL_SET_ERR_MSG_MOD(extack, "Failed to lookup route for encap"); + goto out_free; + } + neigh->egdev = rt->dst.dev; + netdev_hold(neigh->egdev, &neigh->dev_tracker, + GFP_KERNEL_ACCOUNT); + neigh->ttl = ip4_dst_hoplimit(&rt->dst); + n = dst_neigh_lookup(&rt->dst, &flow4.daddr); + ip_rt_put(rt); + } + if (!n) { + rc = -ENETUNREACH; + NL_SET_ERR_MSG_MOD(extack, "Failed to lookup neighbour for encap"); + netdev_put(neigh->egdev, &neigh->dev_tracker); + goto out_free; + } + refcount_set(&neigh->ref, 1); + INIT_LIST_HEAD(&neigh->users); + read_lock_bh(&n->lock); + ether_addr_copy(neigh->ha, n->ha); + neigh->n_valid = n->nud_state & NUD_VALID; + read_unlock_bh(&n->lock); + rwlock_init(&neigh->lock); + INIT_WORK(&neigh->work, efx_neigh_update); + neigh->efx = efx; + neigh->used = jiffies; + if (!neigh->n_valid) + /* Prod ARP to find us a neighbour */ + neigh_event_send(n, NULL); + neigh_release(n); + } + /* Add us to this neigh */ + encap->neigh = neigh; + list_add_tail(&encap->list, &neigh->users); + return 0; + +out_free: + /* cleanup common to several error paths */ + rhashtable_remove_fast(&efx->tc->neigh_ht, &neigh->linkage, + efx_neigh_ht_params); + synchronize_rcu(); + put_net_track(net, &neigh->ns_tracker); + kfree(neigh); + return rc; +} + +static void efx_free_neigh(struct efx_neigh_binder *neigh) +{ + struct efx_nic *efx = neigh->efx; + + rhashtable_remove_fast(&efx->tc->neigh_ht, &neigh->linkage, + efx_neigh_ht_params); + synchronize_rcu(); + netdev_put(neigh->egdev, &neigh->dev_tracker); + put_net_track(neigh->net, &neigh->ns_tracker); + kfree(neigh); +} + +static void efx_release_neigh(struct efx_nic *efx, + struct efx_tc_encap_action *encap) +{ + struct efx_neigh_binder *neigh = encap->neigh; + + if (!neigh) + return; + list_del(&encap->list); + encap->neigh = NULL; + if (!refcount_dec_and_test(&neigh->ref)) + return; /* still in use */ + efx_free_neigh(neigh); +} + +static void efx_gen_tun_header_eth(struct efx_tc_encap_action *encap, u16 proto) +{ + struct efx_neigh_binder *neigh = encap->neigh; + struct ethhdr *eth; + + encap->encap_hdr_len = sizeof(*eth); + eth = (struct ethhdr *)encap->encap_hdr; + + if (encap->neigh->n_valid) + ether_addr_copy(eth->h_dest, neigh->ha); + else + eth_zero_addr(eth->h_dest); + ether_addr_copy(eth->h_source, neigh->egdev->dev_addr); + eth->h_proto = htons(proto); +} + +static void efx_gen_tun_header_ipv4(struct efx_tc_encap_action *encap, u8 ipproto, u8 len) +{ + struct efx_neigh_binder *neigh = encap->neigh; + struct ip_tunnel_key *key = &encap->key; + struct iphdr *ip; + + ip = (struct iphdr *)(encap->encap_hdr + encap->encap_hdr_len); + encap->encap_hdr_len += sizeof(*ip); + + ip->daddr = key->u.ipv4.dst; + ip->saddr = key->u.ipv4.src; + ip->ttl = neigh->ttl; + ip->protocol = ipproto; + ip->version = 0x4; + ip->ihl = 0x5; + ip->tot_len = cpu_to_be16(ip->ihl * 4 + len); + ip_send_check(ip); +} + +#ifdef CONFIG_IPV6 +static void efx_gen_tun_header_ipv6(struct efx_tc_encap_action *encap, u8 ipproto, u8 len) +{ + struct efx_neigh_binder *neigh = encap->neigh; + struct ip_tunnel_key *key = &encap->key; + struct ipv6hdr *ip; + + ip = (struct ipv6hdr *)(encap->encap_hdr + encap->encap_hdr_len); + encap->encap_hdr_len += sizeof(*ip); + + ip6_flow_hdr(ip, key->tos, key->label); + ip->daddr = key->u.ipv6.dst; + ip->saddr = key->u.ipv6.src; + ip->hop_limit = neigh->ttl; + ip->nexthdr = ipproto; + ip->version = 0x6; + ip->payload_len = cpu_to_be16(len); +} +#endif + +static void efx_gen_tun_header_udp(struct efx_tc_encap_action *encap, u8 len) +{ + struct ip_tunnel_key *key = &encap->key; + struct udphdr *udp; + + udp = (struct udphdr *)(encap->encap_hdr + encap->encap_hdr_len); + encap->encap_hdr_len += sizeof(*udp); + + udp->dest = key->tp_dst; + udp->len = cpu_to_be16(sizeof(*udp) + len); +} + +static void efx_gen_tun_header_vxlan(struct efx_tc_encap_action *encap) +{ + struct ip_tunnel_key *key = &encap->key; + struct vxlanhdr *vxlan; + + vxlan = (struct vxlanhdr *)(encap->encap_hdr + encap->encap_hdr_len); + encap->encap_hdr_len += sizeof(*vxlan); + + vxlan->vx_flags = VXLAN_HF_VNI; + vxlan->vx_vni = vxlan_vni_field(tunnel_id_to_key32(key->tun_id)); +} + +static void efx_gen_tun_header_geneve(struct efx_tc_encap_action *encap) +{ + struct ip_tunnel_key *key = &encap->key; + struct genevehdr *geneve; + u32 vni; + + geneve = (struct genevehdr *)(encap->encap_hdr + encap->encap_hdr_len); + encap->encap_hdr_len += sizeof(*geneve); + + geneve->proto_type = htons(ETH_P_TEB); + /* convert tun_id to host-endian so we can use host arithmetic to + * extract individual bytes. + */ + vni = ntohl(tunnel_id_to_key32(key->tun_id)); + geneve->vni[0] = vni >> 16; + geneve->vni[1] = vni >> 8; + geneve->vni[2] = vni; +} + +#define vxlan_header_l4_len (sizeof(struct udphdr) + sizeof(struct vxlanhdr)) +#define vxlan4_header_len (sizeof(struct ethhdr) + sizeof(struct iphdr) + vxlan_header_l4_len) +static void efx_gen_vxlan_header_ipv4(struct efx_tc_encap_action *encap) +{ + BUILD_BUG_ON(sizeof(encap->encap_hdr) < vxlan4_header_len); + efx_gen_tun_header_eth(encap, ETH_P_IP); + efx_gen_tun_header_ipv4(encap, IPPROTO_UDP, vxlan_header_l4_len); + efx_gen_tun_header_udp(encap, sizeof(struct vxlanhdr)); + efx_gen_tun_header_vxlan(encap); +} + +#define geneve_header_l4_len (sizeof(struct udphdr) + sizeof(struct genevehdr)) +#define geneve4_header_len (sizeof(struct ethhdr) + sizeof(struct iphdr) + geneve_header_l4_len) +static void efx_gen_geneve_header_ipv4(struct efx_tc_encap_action *encap) +{ + BUILD_BUG_ON(sizeof(encap->encap_hdr) < geneve4_header_len); + efx_gen_tun_header_eth(encap, ETH_P_IP); + efx_gen_tun_header_ipv4(encap, IPPROTO_UDP, geneve_header_l4_len); + efx_gen_tun_header_udp(encap, sizeof(struct genevehdr)); + efx_gen_tun_header_geneve(encap); +} + +#ifdef CONFIG_IPV6 +#define vxlan6_header_len (sizeof(struct ethhdr) + sizeof(struct ipv6hdr) + vxlan_header_l4_len) +static void efx_gen_vxlan_header_ipv6(struct efx_tc_encap_action *encap) +{ + BUILD_BUG_ON(sizeof(encap->encap_hdr) < vxlan6_header_len); + efx_gen_tun_header_eth(encap, ETH_P_IPV6); + efx_gen_tun_header_ipv6(encap, IPPROTO_UDP, vxlan_header_l4_len); + efx_gen_tun_header_udp(encap, sizeof(struct vxlanhdr)); + efx_gen_tun_header_vxlan(encap); +} + +#define geneve6_header_len (sizeof(struct ethhdr) + sizeof(struct ipv6hdr) + geneve_header_l4_len) +static void efx_gen_geneve_header_ipv6(struct efx_tc_encap_action *encap) +{ + BUILD_BUG_ON(sizeof(encap->encap_hdr) < geneve6_header_len); + efx_gen_tun_header_eth(encap, ETH_P_IPV6); + efx_gen_tun_header_ipv6(encap, IPPROTO_UDP, geneve_header_l4_len); + efx_gen_tun_header_udp(encap, sizeof(struct genevehdr)); + efx_gen_tun_header_geneve(encap); +} +#endif + +static void efx_gen_encap_header(struct efx_nic *efx, + struct efx_tc_encap_action *encap) +{ + encap->n_valid = encap->neigh->n_valid; + + /* GCC stupidly thinks that only values explicitly listed in the enum + * definition can _possibly_ be sensible case values, so without this + * cast it complains about the IPv6 versions. + */ + switch ((int)encap->type) { + case EFX_ENCAP_TYPE_VXLAN: + efx_gen_vxlan_header_ipv4(encap); + break; + case EFX_ENCAP_TYPE_GENEVE: + efx_gen_geneve_header_ipv4(encap); + break; +#ifdef CONFIG_IPV6 + case EFX_ENCAP_TYPE_VXLAN | EFX_ENCAP_FLAG_IPV6: + efx_gen_vxlan_header_ipv6(encap); + break; + case EFX_ENCAP_TYPE_GENEVE | EFX_ENCAP_FLAG_IPV6: + efx_gen_geneve_header_ipv6(encap); + break; +#endif + default: + /* unhandled encap type, can't happen */ + if (net_ratelimit()) + netif_err(efx, drv, efx->net_dev, + "Bogus encap type %d, can't generate\n", + encap->type); + + /* Use fallback action. */ + encap->n_valid = false; + break; + } +} + +static void efx_tc_update_encap(struct efx_nic *efx, + struct efx_tc_encap_action *encap) +{ + struct efx_tc_action_set_list *acts, *fallback; + struct efx_tc_flow_rule *rule; + struct efx_tc_action_set *act; + int rc; + + if (encap->n_valid) { + /* Make sure no rules are using this encap while we change it */ + list_for_each_entry(act, &encap->users, encap_user) { + acts = act->user; + if (WARN_ON(!acts)) /* can't happen */ + continue; + rule = container_of(acts, struct efx_tc_flow_rule, acts); + if (rule->fallback) + fallback = rule->fallback; + else /* fallback fallback: deliver to PF */ + fallback = &efx->tc->facts.pf; + rc = efx_mae_update_rule(efx, fallback->fw_id, + rule->fw_id); + if (rc) + netif_err(efx, drv, efx->net_dev, + "Failed to update (f) rule %08x rc %d\n", + rule->fw_id, rc); + else + netif_dbg(efx, drv, efx->net_dev, "Updated (f) rule %08x\n", + rule->fw_id); + } + } + + /* Make sure we don't leak arbitrary bytes on the wire; + * set an all-0s ethernet header. A successful call to + * efx_gen_encap_header() will overwrite this. + */ + memset(encap->encap_hdr, 0, sizeof(encap->encap_hdr)); + encap->encap_hdr_len = ETH_HLEN; + + if (encap->neigh) { + read_lock_bh(&encap->neigh->lock); + efx_gen_encap_header(efx, encap); + read_unlock_bh(&encap->neigh->lock); + } else { + encap->n_valid = false; + } + + rc = efx_mae_update_encap_md(efx, encap); + if (rc) { + netif_err(efx, drv, efx->net_dev, + "Failed to update encap hdr %08x rc %d\n", + encap->fw_id, rc); + return; + } + netif_dbg(efx, drv, efx->net_dev, "Updated encap hdr %08x\n", + encap->fw_id); + if (!encap->n_valid) + return; + /* Update rule users: use the action if they are now ready */ + list_for_each_entry(act, &encap->users, encap_user) { + acts = act->user; + if (WARN_ON(!acts)) /* can't happen */ + continue; + rule = container_of(acts, struct efx_tc_flow_rule, acts); + if (!efx_tc_check_ready(efx, rule)) + continue; + rc = efx_mae_update_rule(efx, acts->fw_id, rule->fw_id); + if (rc) + netif_err(efx, drv, efx->net_dev, + "Failed to update rule %08x rc %d\n", + rule->fw_id, rc); + else + netif_dbg(efx, drv, efx->net_dev, "Updated rule %08x\n", + rule->fw_id); + } +} + +static void efx_neigh_update(struct work_struct *work) +{ + struct efx_neigh_binder *neigh = container_of(work, struct efx_neigh_binder, work); + struct efx_tc_encap_action *encap; + struct efx_nic *efx = neigh->efx; + + mutex_lock(&efx->tc->mutex); + list_for_each_entry(encap, &neigh->users, list) + efx_tc_update_encap(neigh->efx, encap); + /* release ref taken in efx_neigh_event() */ + if (refcount_dec_and_test(&neigh->ref)) + efx_free_neigh(neigh); + mutex_unlock(&efx->tc->mutex); +} + +static int efx_neigh_event(struct efx_nic *efx, struct neighbour *n) +{ + struct efx_neigh_binder keys = {NULL}, *neigh; + bool n_valid, ipv6 = false; + char ha[ETH_ALEN]; + size_t keysize; + + if (WARN_ON(!efx->tc)) + return NOTIFY_DONE; + + if (n->tbl == &arp_tbl) { + keysize = sizeof(keys.dst_ip); +#if IS_ENABLED(CONFIG_IPV6) + } else if (n->tbl == ipv6_stub->nd_tbl) { + ipv6 = true; + keysize = sizeof(keys.dst_ip6); +#endif + } else { + return NOTIFY_DONE; + } + if (!n->parms) { + netif_warn(efx, drv, efx->net_dev, "neigh_event with no parms!\n"); + return NOTIFY_DONE; + } + keys.net = read_pnet(&n->parms->net); + if (n->tbl->key_len != keysize) { + netif_warn(efx, drv, efx->net_dev, "neigh_event with bad key_len %u\n", + n->tbl->key_len); + return NOTIFY_DONE; + } + read_lock_bh(&n->lock); /* Get a consistent view */ + memcpy(ha, n->ha, ETH_ALEN); + n_valid = (n->nud_state & NUD_VALID) && !n->dead; + read_unlock_bh(&n->lock); + if (ipv6) + memcpy(&keys.dst_ip6, n->primary_key, n->tbl->key_len); + else + memcpy(&keys.dst_ip, n->primary_key, n->tbl->key_len); + rcu_read_lock(); + neigh = rhashtable_lookup_fast(&efx->tc->neigh_ht, &keys, + efx_neigh_ht_params); + if (!neigh || neigh->dying) + /* We're not interested in this neighbour */ + goto done; + write_lock_bh(&neigh->lock); + if (n_valid == neigh->n_valid && !memcmp(ha, neigh->ha, ETH_ALEN)) { + write_unlock_bh(&neigh->lock); + /* Nothing has changed; no work to do */ + goto done; + } + neigh->n_valid = n_valid; + memcpy(neigh->ha, ha, ETH_ALEN); + write_unlock_bh(&neigh->lock); + if (refcount_inc_not_zero(&neigh->ref)) { + rcu_read_unlock(); + if (!schedule_work(&neigh->work)) + /* failed to schedule, release the ref we just took */ + if (refcount_dec_and_test(&neigh->ref)) + efx_free_neigh(neigh); + } else { +done: + rcu_read_unlock(); + } + return NOTIFY_DONE; +} + +bool efx_tc_check_ready(struct efx_nic *efx, struct efx_tc_flow_rule *rule) +{ + struct efx_tc_action_set *act; + + /* Encap actions can only be offloaded if they have valid + * neighbour info for the outer Ethernet header. + */ + list_for_each_entry(act, &rule->acts.list, list) + if (act->encap_md && !act->encap_md->n_valid) + return false; + return true; +} + +struct efx_tc_encap_action *efx_tc_flower_create_encap_md( + struct efx_nic *efx, const struct ip_tunnel_info *info, + struct net_device *egdev, struct netlink_ext_ack *extack) +{ + enum efx_encap_type type = efx_tc_indr_netdev_type(egdev); + struct efx_tc_encap_action *encap, *old; + struct efx_rep *to_efv; + s64 rc; + + if (type == EFX_ENCAP_TYPE_NONE) { + /* dest is not an encap device */ + NL_SET_ERR_MSG_MOD(extack, "Not a (supported) tunnel device but tunnel_key is set"); + return ERR_PTR(-EOPNOTSUPP); + } + rc = efx_mae_check_encap_type_supported(efx, type); + if (rc < 0) { + NL_SET_ERR_MSG_MOD(extack, "Firmware reports no support for this tunnel type"); + return ERR_PTR(rc); + } + /* No support yet for Geneve options */ + if (info->options_len) { + NL_SET_ERR_MSG_MOD(extack, "Unsupported tunnel options"); + return ERR_PTR(-EOPNOTSUPP); + } + switch (info->mode) { + case IP_TUNNEL_INFO_TX: + break; + case IP_TUNNEL_INFO_TX | IP_TUNNEL_INFO_IPV6: + type |= EFX_ENCAP_FLAG_IPV6; + break; + default: + NL_SET_ERR_MSG_FMT_MOD(extack, "Unsupported tunnel mode %u", + info->mode); + return ERR_PTR(-EOPNOTSUPP); + } + encap = kzalloc(sizeof(*encap), GFP_KERNEL_ACCOUNT); + if (!encap) + return ERR_PTR(-ENOMEM); + encap->type = type; + encap->key = info->key; + INIT_LIST_HEAD(&encap->users); + old = rhashtable_lookup_get_insert_fast(&efx->tc->encap_ht, + &encap->linkage, + efx_tc_encap_ht_params); + if (old) { + /* don't need our new entry */ + kfree(encap); + if (!refcount_inc_not_zero(&old->ref)) + return ERR_PTR(-EAGAIN); + /* existing entry found, ref taken */ + return old; + } + + rc = efx_bind_neigh(efx, encap, dev_net(egdev), extack); + if (rc < 0) + goto out_remove; + to_efv = efx_tc_flower_lookup_efv(efx, encap->neigh->egdev); + if (IS_ERR(to_efv)) { + /* neigh->egdev isn't ours */ + NL_SET_ERR_MSG_MOD(extack, "Tunnel egress device not on switch"); + rc = PTR_ERR(to_efv); + goto out_release; + } + rc = efx_tc_flower_external_mport(efx, to_efv); + if (rc < 0) { + NL_SET_ERR_MSG_MOD(extack, "Failed to identify tunnel egress m-port"); + goto out_release; + } + encap->dest_mport = rc; + read_lock_bh(&encap->neigh->lock); + efx_gen_encap_header(efx, encap); + read_unlock_bh(&encap->neigh->lock); + + rc = efx_mae_allocate_encap_md(efx, encap); + if (rc < 0) { + NL_SET_ERR_MSG_MOD(extack, "Failed to write tunnel header to hw"); + goto out_release; + } + + /* ref and return */ + refcount_set(&encap->ref, 1); + return encap; +out_release: + efx_release_neigh(efx, encap); +out_remove: + rhashtable_remove_fast(&efx->tc->encap_ht, &encap->linkage, + efx_tc_encap_ht_params); + kfree(encap); + return ERR_PTR(rc); +} + +void efx_tc_flower_release_encap_md(struct efx_nic *efx, + struct efx_tc_encap_action *encap) +{ + if (!refcount_dec_and_test(&encap->ref)) + return; /* still in use */ + efx_release_neigh(efx, encap); + rhashtable_remove_fast(&efx->tc->encap_ht, &encap->linkage, + efx_tc_encap_ht_params); + efx_mae_free_encap_md(efx, encap); + kfree(encap); +} + +static void efx_tc_remove_neigh_users(struct efx_nic *efx, struct efx_neigh_binder *neigh) +{ + struct efx_tc_encap_action *encap, *next; + + list_for_each_entry_safe(encap, next, &neigh->users, list) { + /* Should cause neigh usage count to fall to zero, freeing it */ + efx_release_neigh(efx, encap); + /* The encap has lost its neigh, so it's now unready */ + efx_tc_update_encap(efx, encap); + } +} + +void efx_tc_unregister_egdev(struct efx_nic *efx, struct net_device *net_dev) +{ + struct efx_neigh_binder *neigh; + struct rhashtable_iter walk; + + mutex_lock(&efx->tc->mutex); + rhashtable_walk_enter(&efx->tc->neigh_ht, &walk); + rhashtable_walk_start(&walk); + while ((neigh = rhashtable_walk_next(&walk)) != NULL) { + if (IS_ERR(neigh)) + continue; + if (neigh->egdev != net_dev) + continue; + neigh->dying = true; + rhashtable_walk_stop(&walk); + synchronize_rcu(); /* Make sure any updates see dying flag */ + efx_tc_remove_neigh_users(efx, neigh); /* might sleep */ + rhashtable_walk_start(&walk); + } + rhashtable_walk_stop(&walk); + rhashtable_walk_exit(&walk); + mutex_unlock(&efx->tc->mutex); +} + +int efx_tc_netevent_event(struct efx_nic *efx, unsigned long event, + void *ptr) +{ + if (efx->type->is_vf) + return NOTIFY_DONE; + + switch (event) { + case NETEVENT_NEIGH_UPDATE: + return efx_neigh_event(efx, ptr); + default: + return NOTIFY_DONE; + } +} diff --git a/drivers/net/ethernet/sfc/tc_encap_actions.h b/drivers/net/ethernet/sfc/tc_encap_actions.h new file mode 100644 index 0000000000000000000000000000000000000000..c3c7904ad7ffa83fc7c5143a776c740750ba701f --- /dev/null +++ b/drivers/net/ethernet/sfc/tc_encap_actions.h @@ -0,0 +1,114 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/**************************************************************************** + * Driver for Solarflare network controllers and boards + * Copyright 2023, Advanced Micro Devices, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation, incorporated herein by reference. + */ + +#ifndef EFX_TC_ENCAP_ACTIONS_H +#define EFX_TC_ENCAP_ACTIONS_H +#include "net_driver.h" + +#if IS_ENABLED(CONFIG_SFC_SRIOV) +#include +#include + +/** + * struct efx_neigh_binder - driver state for a neighbour entry + * @net: the network namespace in which this neigh resides + * @dst_ip: the IPv4 destination address resolved by this neigh + * @dst_ip6: the IPv6 destination address resolved by this neigh + * @ha: the hardware (Ethernet) address of the neighbour + * @n_valid: true if the neighbour is in NUD_VALID state + * @lock: protects @ha and @n_valid + * @ttl: Time To Live associated with the route used + * @dying: set when egdev is going away, to skip further updates + * @egdev: egress device from the route lookup. Holds a reference + * @dev_tracker: reference tracker entry for @egdev + * @ns_tracker: reference tracker entry for @ns + * @ref: counts encap actions referencing this entry + * @used: jiffies of last time traffic hit any encap action using this. + * When counter reads update this, a new neighbour event is sent to + * indicate that the neighbour entry is still in use. + * @users: list of &struct efx_tc_encap_action + * @linkage: entry in efx->neigh_ht (keys are @net, @dst_ip, @dst_ip6). + * @work: processes neighbour state changes, updates the encap actions + * @efx: owning NIC instance. + * + * Associates a neighbour entry with the encap actions that are + * interested in it, allowing the latter to be updated when the + * neighbour details change. + * Whichever of @dst_ip and @dst_ip6 is not in use will be all-zeroes, + * this distinguishes IPv4 from IPv6 entries. + */ +struct efx_neigh_binder { + struct net *net; + __be32 dst_ip; + struct in6_addr dst_ip6; + char ha[ETH_ALEN]; + bool n_valid; + rwlock_t lock; + u8 ttl; + bool dying; + struct net_device *egdev; + netdevice_tracker dev_tracker; + netns_tracker ns_tracker; + refcount_t ref; + unsigned long used; + struct list_head users; + struct rhash_head linkage; + struct work_struct work; + struct efx_nic *efx; +}; + +/* This limit is arbitrary; current hardware (SN1022) handles encap headers + * of up to 126 bytes, but that limit is not enshrined in the MCDI protocol. + */ +#define EFX_TC_MAX_ENCAP_HDR 126 +struct efx_tc_encap_action { + enum efx_encap_type type; + struct ip_tunnel_key key; /* 52 bytes */ + u32 dest_mport; /* is copied into struct efx_tc_action_set */ + u8 encap_hdr_len; + bool n_valid; + u8 encap_hdr[EFX_TC_MAX_ENCAP_HDR]; + struct efx_neigh_binder *neigh; + struct list_head list; /* entry on neigh->users list */ + struct list_head users; /* action sets using this encap_md */ + struct rhash_head linkage; /* efx->tc_encap_ht */ + refcount_t ref; + u32 fw_id; /* index of this entry in firmware encap table */ +}; + +/* create/uncreate/teardown hashtables */ +int efx_tc_init_encap_actions(struct efx_nic *efx); +void efx_tc_destroy_encap_actions(struct efx_nic *efx); +void efx_tc_fini_encap_actions(struct efx_nic *efx); + +struct efx_tc_flow_rule; +bool efx_tc_check_ready(struct efx_nic *efx, struct efx_tc_flow_rule *rule); + +struct efx_tc_encap_action *efx_tc_flower_create_encap_md( + struct efx_nic *efx, const struct ip_tunnel_info *info, + struct net_device *egdev, struct netlink_ext_ack *extack); +void efx_tc_flower_release_encap_md(struct efx_nic *efx, + struct efx_tc_encap_action *encap); + +void efx_tc_unregister_egdev(struct efx_nic *efx, struct net_device *net_dev); +int efx_tc_netevent_event(struct efx_nic *efx, unsigned long event, + void *ptr); + +#else /* CONFIG_SFC_SRIOV */ + +static inline int efx_tc_netevent_event(struct efx_nic *efx, + unsigned long event, void *ptr) +{ + return NOTIFY_DONE; +} + +#endif /* CONFIG_SFC_SRIOV */ + +#endif /* EFX_TC_ENCAP_ACTIONS_H */ diff --git a/drivers/net/ethernet/sfc/tx_common.c b/drivers/net/ethernet/sfc/tx_common.c index 67e789b96c437cb8f230b074c846d6b5884d62cc..9f2393d343715d96fc2fbb3a19e3a5c2fde601ff 100644 --- a/drivers/net/ethernet/sfc/tx_common.c +++ b/drivers/net/ethernet/sfc/tx_common.c @@ -12,6 +12,7 @@ #include "efx.h" #include "nic_common.h" #include "tx_common.h" +#include static unsigned int efx_tx_cb_page_count(struct efx_tx_queue *tx_queue) { @@ -249,7 +250,7 @@ void efx_xmit_done_check_empty(struct efx_tx_queue *tx_queue) } } -void efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index) +int efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index) { unsigned int fill_level, pkts_compl = 0, bytes_compl = 0; unsigned int efv_pkts_compl = 0; @@ -279,6 +280,8 @@ void efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index) } efx_xmit_done_check_empty(tx_queue); + + return pkts_compl + efv_pkts_compl; } /* Remove buffers put into a tx_queue for the current packet. diff --git a/drivers/net/ethernet/sfc/tx_common.h b/drivers/net/ethernet/sfc/tx_common.h index d87aecbc7bf1ab35bca5e48bdf56073f4830008b..1e9f42938aac9207e7b06bc59d03471aef190a26 100644 --- a/drivers/net/ethernet/sfc/tx_common.h +++ b/drivers/net/ethernet/sfc/tx_common.h @@ -28,7 +28,7 @@ static inline bool efx_tx_buffer_in_use(struct efx_tx_buffer *buffer) } void efx_xmit_done_check_empty(struct efx_tx_queue *tx_queue); -void efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index); +int efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index); void efx_enqueue_unwind(struct efx_tx_queue *tx_queue, unsigned int insert_count); diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig index 5f5a997f21f363950d7a9a3ebe1af5f2f0817286..5583f0b055ec721dca3f8119757c8e4ad3e1d18a 100644 --- a/drivers/net/ethernet/stmicro/stmmac/Kconfig +++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig @@ -158,6 +158,9 @@ config DWMAC_SOCFPGA default ARCH_INTEL_SOCFPGA depends on OF && (ARCH_INTEL_SOCFPGA || COMPILE_TEST) select MFD_SYSCON + select MDIO_REGMAP + select REGMAP_MMIO + select PCS_LYNX help Support for ethernet controller on Altera SOCFPGA diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile index 8738fdbb4b2dc06a823c46a0828456aad522f5a8..7dd3d388068bdabd394a86c1d5f10b31f5fb0258 100644 --- a/drivers/net/ethernet/stmicro/stmmac/Makefile +++ b/drivers/net/ethernet/stmicro/stmmac/Makefile @@ -35,7 +35,7 @@ obj-$(CONFIG_DWMAC_IMX8) += dwmac-imx.o obj-$(CONFIG_DWMAC_TEGRA) += dwmac-tegra.o obj-$(CONFIG_DWMAC_VISCONTI) += dwmac-visconti.o stmmac-platform-objs:= stmmac_platform.o -dwmac-altr-socfpga-objs := altr_tse_pcs.o dwmac-socfpga.o +dwmac-altr-socfpga-objs := dwmac-socfpga.o obj-$(CONFIG_STMMAC_PCI) += stmmac-pci.o obj-$(CONFIG_DWMAC_INTEL) += dwmac-intel.o diff --git a/drivers/net/ethernet/stmicro/stmmac/altr_tse_pcs.c b/drivers/net/ethernet/stmicro/stmmac/altr_tse_pcs.c deleted file mode 100644 index 00f6d347eaf75b33ec43c60aea8aca1fcaebdc7a..0000000000000000000000000000000000000000 --- a/drivers/net/ethernet/stmicro/stmmac/altr_tse_pcs.c +++ /dev/null @@ -1,257 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* Copyright Altera Corporation (C) 2016. All rights reserved. - * - * Author: Tien Hock Loh - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "stmmac.h" -#include "stmmac_platform.h" -#include "altr_tse_pcs.h" - -#define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_GMII_MII 0 -#define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RGMII BIT(1) -#define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RMII BIT(2) -#define SYSMGR_EMACGRP_CTRL_PHYSEL_WIDTH 2 -#define SYSMGR_EMACGRP_CTRL_PHYSEL_MASK GENMASK(1, 0) - -#define TSE_PCS_CONTROL_AN_EN_MASK BIT(12) -#define TSE_PCS_CONTROL_REG 0x00 -#define TSE_PCS_CONTROL_RESTART_AN_MASK BIT(9) -#define TSE_PCS_CTRL_AUTONEG_SGMII 0x1140 -#define TSE_PCS_IF_MODE_REG 0x28 -#define TSE_PCS_LINK_TIMER_0_REG 0x24 -#define TSE_PCS_LINK_TIMER_1_REG 0x26 -#define TSE_PCS_SIZE 0x40 -#define TSE_PCS_STATUS_AN_COMPLETED_MASK BIT(5) -#define TSE_PCS_STATUS_LINK_MASK 0x0004 -#define TSE_PCS_STATUS_REG 0x02 -#define TSE_PCS_SGMII_SPEED_1000 BIT(3) -#define TSE_PCS_SGMII_SPEED_100 BIT(2) -#define TSE_PCS_SGMII_SPEED_10 0x0 -#define TSE_PCS_SW_RST_MASK 0x8000 -#define TSE_PCS_PARTNER_ABILITY_REG 0x0A -#define TSE_PCS_PARTNER_DUPLEX_FULL 0x1000 -#define TSE_PCS_PARTNER_DUPLEX_HALF 0x0000 -#define TSE_PCS_PARTNER_DUPLEX_MASK 0x1000 -#define TSE_PCS_PARTNER_SPEED_MASK GENMASK(11, 10) -#define TSE_PCS_PARTNER_SPEED_1000 BIT(11) -#define TSE_PCS_PARTNER_SPEED_100 BIT(10) -#define TSE_PCS_PARTNER_SPEED_10 0x0000 -#define TSE_PCS_PARTNER_SPEED_1000 BIT(11) -#define TSE_PCS_PARTNER_SPEED_100 BIT(10) -#define TSE_PCS_PARTNER_SPEED_10 0x0000 -#define TSE_PCS_SGMII_SPEED_MASK GENMASK(3, 2) -#define TSE_PCS_SGMII_LINK_TIMER_0 0x0D40 -#define TSE_PCS_SGMII_LINK_TIMER_1 0x0003 -#define TSE_PCS_SW_RESET_TIMEOUT 100 -#define TSE_PCS_USE_SGMII_AN_MASK BIT(1) -#define TSE_PCS_USE_SGMII_ENA BIT(0) -#define TSE_PCS_IF_USE_SGMII 0x03 - -#define AUTONEGO_LINK_TIMER 20 - -static int tse_pcs_reset(void __iomem *base, struct tse_pcs *pcs) -{ - int counter = 0; - u16 val; - - val = readw(base + TSE_PCS_CONTROL_REG); - val |= TSE_PCS_SW_RST_MASK; - writew(val, base + TSE_PCS_CONTROL_REG); - - while (counter < TSE_PCS_SW_RESET_TIMEOUT) { - val = readw(base + TSE_PCS_CONTROL_REG); - val &= TSE_PCS_SW_RST_MASK; - if (val == 0) - break; - counter++; - udelay(1); - } - if (counter >= TSE_PCS_SW_RESET_TIMEOUT) { - dev_err(pcs->dev, "PCS could not get out of sw reset\n"); - return -ETIMEDOUT; - } - - return 0; -} - -int tse_pcs_init(void __iomem *base, struct tse_pcs *pcs) -{ - int ret = 0; - - writew(TSE_PCS_IF_USE_SGMII, base + TSE_PCS_IF_MODE_REG); - - writew(TSE_PCS_CTRL_AUTONEG_SGMII, base + TSE_PCS_CONTROL_REG); - - writew(TSE_PCS_SGMII_LINK_TIMER_0, base + TSE_PCS_LINK_TIMER_0_REG); - writew(TSE_PCS_SGMII_LINK_TIMER_1, base + TSE_PCS_LINK_TIMER_1_REG); - - ret = tse_pcs_reset(base, pcs); - if (ret == 0) - writew(SGMII_ADAPTER_ENABLE, - pcs->sgmii_adapter_base + SGMII_ADAPTER_CTRL_REG); - - return ret; -} - -static void pcs_link_timer_callback(struct tse_pcs *pcs) -{ - u16 val = 0; - void __iomem *tse_pcs_base = pcs->tse_pcs_base; - void __iomem *sgmii_adapter_base = pcs->sgmii_adapter_base; - - val = readw(tse_pcs_base + TSE_PCS_STATUS_REG); - val &= TSE_PCS_STATUS_LINK_MASK; - - if (val != 0) { - dev_dbg(pcs->dev, "Adapter: Link is established\n"); - writew(SGMII_ADAPTER_ENABLE, - sgmii_adapter_base + SGMII_ADAPTER_CTRL_REG); - } else { - mod_timer(&pcs->aneg_link_timer, jiffies + - msecs_to_jiffies(AUTONEGO_LINK_TIMER)); - } -} - -static void auto_nego_timer_callback(struct tse_pcs *pcs) -{ - u16 val = 0; - u16 speed = 0; - u16 duplex = 0; - void __iomem *tse_pcs_base = pcs->tse_pcs_base; - void __iomem *sgmii_adapter_base = pcs->sgmii_adapter_base; - - val = readw(tse_pcs_base + TSE_PCS_STATUS_REG); - val &= TSE_PCS_STATUS_AN_COMPLETED_MASK; - - if (val != 0) { - dev_dbg(pcs->dev, "Adapter: Auto Negotiation is completed\n"); - val = readw(tse_pcs_base + TSE_PCS_PARTNER_ABILITY_REG); - speed = val & TSE_PCS_PARTNER_SPEED_MASK; - duplex = val & TSE_PCS_PARTNER_DUPLEX_MASK; - - if (speed == TSE_PCS_PARTNER_SPEED_10 && - duplex == TSE_PCS_PARTNER_DUPLEX_FULL) - dev_dbg(pcs->dev, - "Adapter: Link Partner is Up - 10/Full\n"); - else if (speed == TSE_PCS_PARTNER_SPEED_100 && - duplex == TSE_PCS_PARTNER_DUPLEX_FULL) - dev_dbg(pcs->dev, - "Adapter: Link Partner is Up - 100/Full\n"); - else if (speed == TSE_PCS_PARTNER_SPEED_1000 && - duplex == TSE_PCS_PARTNER_DUPLEX_FULL) - dev_dbg(pcs->dev, - "Adapter: Link Partner is Up - 1000/Full\n"); - else if (speed == TSE_PCS_PARTNER_SPEED_10 && - duplex == TSE_PCS_PARTNER_DUPLEX_HALF) - dev_err(pcs->dev, - "Adapter does not support Half Duplex\n"); - else if (speed == TSE_PCS_PARTNER_SPEED_100 && - duplex == TSE_PCS_PARTNER_DUPLEX_HALF) - dev_err(pcs->dev, - "Adapter does not support Half Duplex\n"); - else if (speed == TSE_PCS_PARTNER_SPEED_1000 && - duplex == TSE_PCS_PARTNER_DUPLEX_HALF) - dev_err(pcs->dev, - "Adapter does not support Half Duplex\n"); - else - dev_err(pcs->dev, - "Adapter: Invalid Partner Speed and Duplex\n"); - - if (duplex == TSE_PCS_PARTNER_DUPLEX_FULL && - (speed == TSE_PCS_PARTNER_SPEED_10 || - speed == TSE_PCS_PARTNER_SPEED_100 || - speed == TSE_PCS_PARTNER_SPEED_1000)) - writew(SGMII_ADAPTER_ENABLE, - sgmii_adapter_base + SGMII_ADAPTER_CTRL_REG); - } else { - val = readw(tse_pcs_base + TSE_PCS_CONTROL_REG); - val |= TSE_PCS_CONTROL_RESTART_AN_MASK; - writew(val, tse_pcs_base + TSE_PCS_CONTROL_REG); - - tse_pcs_reset(tse_pcs_base, pcs); - mod_timer(&pcs->aneg_link_timer, jiffies + - msecs_to_jiffies(AUTONEGO_LINK_TIMER)); - } -} - -static void aneg_link_timer_callback(struct timer_list *t) -{ - struct tse_pcs *pcs = from_timer(pcs, t, aneg_link_timer); - - if (pcs->autoneg == AUTONEG_ENABLE) - auto_nego_timer_callback(pcs); - else if (pcs->autoneg == AUTONEG_DISABLE) - pcs_link_timer_callback(pcs); -} - -void tse_pcs_fix_mac_speed(struct tse_pcs *pcs, struct phy_device *phy_dev, - unsigned int speed) -{ - void __iomem *tse_pcs_base = pcs->tse_pcs_base; - u32 val; - - pcs->autoneg = phy_dev->autoneg; - - if (phy_dev->autoneg == AUTONEG_ENABLE) { - val = readw(tse_pcs_base + TSE_PCS_CONTROL_REG); - val |= TSE_PCS_CONTROL_AN_EN_MASK; - writew(val, tse_pcs_base + TSE_PCS_CONTROL_REG); - - val = readw(tse_pcs_base + TSE_PCS_IF_MODE_REG); - val |= TSE_PCS_USE_SGMII_AN_MASK; - writew(val, tse_pcs_base + TSE_PCS_IF_MODE_REG); - - val = readw(tse_pcs_base + TSE_PCS_CONTROL_REG); - val |= TSE_PCS_CONTROL_RESTART_AN_MASK; - - tse_pcs_reset(tse_pcs_base, pcs); - - timer_setup(&pcs->aneg_link_timer, aneg_link_timer_callback, - 0); - mod_timer(&pcs->aneg_link_timer, jiffies + - msecs_to_jiffies(AUTONEGO_LINK_TIMER)); - } else if (phy_dev->autoneg == AUTONEG_DISABLE) { - val = readw(tse_pcs_base + TSE_PCS_CONTROL_REG); - val &= ~TSE_PCS_CONTROL_AN_EN_MASK; - writew(val, tse_pcs_base + TSE_PCS_CONTROL_REG); - - val = readw(tse_pcs_base + TSE_PCS_IF_MODE_REG); - val &= ~TSE_PCS_USE_SGMII_AN_MASK; - writew(val, tse_pcs_base + TSE_PCS_IF_MODE_REG); - - val = readw(tse_pcs_base + TSE_PCS_IF_MODE_REG); - val &= ~TSE_PCS_SGMII_SPEED_MASK; - - switch (speed) { - case 1000: - val |= TSE_PCS_SGMII_SPEED_1000; - break; - case 100: - val |= TSE_PCS_SGMII_SPEED_100; - break; - case 10: - val |= TSE_PCS_SGMII_SPEED_10; - break; - default: - return; - } - writew(val, tse_pcs_base + TSE_PCS_IF_MODE_REG); - - tse_pcs_reset(tse_pcs_base, pcs); - - timer_setup(&pcs->aneg_link_timer, aneg_link_timer_callback, - 0); - mod_timer(&pcs->aneg_link_timer, jiffies + - msecs_to_jiffies(AUTONEGO_LINK_TIMER)); - } -} diff --git a/drivers/net/ethernet/stmicro/stmmac/altr_tse_pcs.h b/drivers/net/ethernet/stmicro/stmmac/altr_tse_pcs.h deleted file mode 100644 index 694ac25ef426ba2e6a9848b6881b9e3386d32ef6..0000000000000000000000000000000000000000 --- a/drivers/net/ethernet/stmicro/stmmac/altr_tse_pcs.h +++ /dev/null @@ -1,29 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* Copyright Altera Corporation (C) 2016. All rights reserved. - * - * Author: Tien Hock Loh - */ - -#ifndef __TSE_PCS_H__ -#define __TSE_PCS_H__ - -#include -#include - -#define SGMII_ADAPTER_CTRL_REG 0x00 -#define SGMII_ADAPTER_ENABLE 0x0000 -#define SGMII_ADAPTER_DISABLE 0x0001 - -struct tse_pcs { - struct device *dev; - void __iomem *tse_pcs_base; - void __iomem *sgmii_adapter_base; - struct timer_list aneg_link_timer; - int autoneg; -}; - -int tse_pcs_init(void __iomem *base, struct tse_pcs *pcs); -void tse_pcs_fix_mac_speed(struct tse_pcs *pcs, struct phy_device *phy_dev, - unsigned int speed); - -#endif /* __TSE_PCS_H__ */ diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h index 4ad692c4116c8b10a470fd12662518dea0765ed9..16e67c18b6f713442f0642e1b30912d8dbf8046c 100644 --- a/drivers/net/ethernet/stmicro/stmmac/common.h +++ b/drivers/net/ethernet/stmicro/stmmac/common.h @@ -519,6 +519,7 @@ struct mac_device_info { const struct stmmac_tc_ops *tc; const struct stmmac_mmc_ops *mmc; struct dw_xpcs *xpcs; + struct phylink_pcs *lynx_pcs; /* Lynx external PCS */ struct mii_regs mii; /* MII register Addresses */ struct mac_link link; void __iomem *pcsr; /* vpointer to device CSRs */ diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-anarion.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-anarion.c index 9354bf4191120be180c039a0a395e00ff1c4958e..58a7f08e8d78be21e5d7572e51efe42ad70fe97a 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-anarion.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-anarion.c @@ -141,7 +141,7 @@ MODULE_DEVICE_TABLE(of, anarion_dwmac_match); static struct platform_driver anarion_dwmac_driver = { .probe = anarion_dwmac_probe, - .remove = stmmac_pltfr_remove, + .remove_new = stmmac_pltfr_remove, .driver = { .name = "anarion-dwmac", .pm = &stmmac_pltfr_pm_ops, diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c index 18acf7dd74e59a600d9b38db7c0c044d8f72bdd0..9f88530c5e8c80cb3eee5120eb6ceba8d9d8241a 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c @@ -464,7 +464,7 @@ static int dwc_eth_dwmac_probe(struct platform_device *pdev) return ret; } -static int dwc_eth_dwmac_remove(struct platform_device *pdev) +static void dwc_eth_dwmac_remove(struct platform_device *pdev) { struct net_device *ndev = platform_get_drvdata(pdev); struct stmmac_priv *priv = netdev_priv(ndev); @@ -477,8 +477,6 @@ static int dwc_eth_dwmac_remove(struct platform_device *pdev) data->remove(pdev); stmmac_remove_config_dt(pdev, priv->plat); - - return 0; } static const struct of_device_id dwc_eth_dwmac_match[] = { @@ -490,7 +488,7 @@ MODULE_DEVICE_TABLE(of, dwc_eth_dwmac_match); static struct platform_driver dwc_eth_dwmac_driver = { .probe = dwc_eth_dwmac_probe, - .remove = dwc_eth_dwmac_remove, + .remove_new = dwc_eth_dwmac_remove, .driver = { .name = "dwc-eth-dwmac", .pm = &stmmac_pltfr_pm_ops, diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-generic.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-generic.c index ef8f3a940938c0ee01dd4bc0db9b42c7a4a67030..20fc455b3337a5ef820d15f54c43f848e2314257 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-generic.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-generic.c @@ -46,22 +46,12 @@ static int dwmac_generic_probe(struct platform_device *pdev) plat_dat->unicast_filter_entries = 1; } - /* Custom initialisation (if needed) */ - if (plat_dat->init) { - ret = plat_dat->init(pdev, plat_dat->bsp_priv); - if (ret) - goto err_remove_config_dt; - } - - ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); + ret = stmmac_pltfr_probe(pdev, plat_dat, &stmmac_res); if (ret) - goto err_exit; + goto err_remove_config_dt; return 0; -err_exit: - if (plat_dat->exit) - plat_dat->exit(pdev, plat_dat->bsp_priv); err_remove_config_dt: if (pdev->dev.of_node) stmmac_remove_config_dt(pdev, plat_dat); @@ -87,7 +77,7 @@ MODULE_DEVICE_TABLE(of, dwmac_generic_match); static struct platform_driver dwmac_generic_driver = { .probe = dwmac_generic_probe, - .remove = stmmac_pltfr_remove, + .remove_new = stmmac_pltfr_remove, .driver = { .name = STMMAC_RESOURCE_NAME, .pm = &stmmac_pltfr_pm_ops, diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-imx.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-imx.c index 7c228bd0d099f37e9aa85a8c90c652286c2ec5d0..b9378a63f0e8791fff3c708f30eb7153b67a16c1 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-imx.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-imx.c @@ -376,7 +376,7 @@ MODULE_DEVICE_TABLE(of, imx_dwmac_match); static struct platform_driver imx_dwmac_driver = { .probe = imx_dwmac_probe, - .remove = stmmac_pltfr_remove, + .remove_new = stmmac_pltfr_remove, .driver = { .name = "imx-dwmac", .pm = &stmmac_pltfr_pm_ops, diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-ingenic.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-ingenic.c index 378b4dd826bb5e393382569a262047d309dd2b96..8063ba1c3ce838f558bd5da8822aa8d6a38a1c08 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-ingenic.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-ingenic.c @@ -386,7 +386,7 @@ MODULE_DEVICE_TABLE(of, ingenic_mac_of_matches); static struct platform_driver ingenic_mac_driver = { .probe = ingenic_mac_probe, - .remove = stmmac_pltfr_remove, + .remove_new = stmmac_pltfr_remove, .driver = { .name = "ingenic-mac", .pm = pm_ptr(&ingenic_mac_pm_ops), diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel-plat.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel-plat.c index 06d287f104bec9d01b4ff126e26f4a948ef4fe33..a5e639ab0b9e742e1caa0aac104fa5a88851dc77 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel-plat.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel-plat.c @@ -169,20 +169,17 @@ static int intel_eth_plat_probe(struct platform_device *pdev) return ret; } -static int intel_eth_plat_remove(struct platform_device *pdev) +static void intel_eth_plat_remove(struct platform_device *pdev) { struct intel_dwmac *dwmac = get_stmmac_bsp_priv(&pdev->dev); - int ret; - ret = stmmac_pltfr_remove(pdev); + stmmac_pltfr_remove(pdev); clk_disable_unprepare(dwmac->tx_clk); - - return ret; } static struct platform_driver intel_eth_plat_driver = { .probe = intel_eth_plat_probe, - .remove = intel_eth_plat_remove, + .remove_new = intel_eth_plat_remove, .driver = { .name = "intel-eth-plat", .pm = &stmmac_pltfr_pm_ops, diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c index e888c8a9c830de910985ea8e5e6b4ce20267aa7a..e39406df8516f1a0006725b1ad041747bd73b133 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c @@ -498,7 +498,7 @@ MODULE_DEVICE_TABLE(of, ipq806x_gmac_dwmac_match); static struct platform_driver ipq806x_gmac_dwmac_driver = { .probe = ipq806x_gmac_probe, - .remove = stmmac_pltfr_remove, + .remove_new = stmmac_pltfr_remove, .driver = { .name = "ipq806x-gmac-dwmac", .pm = &stmmac_pltfr_pm_ops, diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-lpc18xx.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-lpc18xx.c index 9d77c647badd5cfae2f1fe001073039f3c849f0f..18e84ba693a656d8730ccde5671edbd281845c9f 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-lpc18xx.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-lpc18xx.c @@ -83,7 +83,7 @@ MODULE_DEVICE_TABLE(of, lpc18xx_dwmac_match); static struct platform_driver lpc18xx_dwmac_driver = { .probe = lpc18xx_dwmac_probe, - .remove = stmmac_pltfr_remove, + .remove_new = stmmac_pltfr_remove, .driver = { .name = "lpc18xx-dwmac", .pm = &stmmac_pltfr_pm_ops, diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c index 9ae31e3dc82187c8abd6fe3fcaa959d36c84f207..73c1dfa7ecb1dbc06197dd7b01e99548ff6a0286 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c @@ -678,15 +678,12 @@ static int mediatek_dwmac_probe(struct platform_device *pdev) return ret; } -static int mediatek_dwmac_remove(struct platform_device *pdev) +static void mediatek_dwmac_remove(struct platform_device *pdev) { struct mediatek_dwmac_plat_data *priv_plat = get_stmmac_bsp_priv(&pdev->dev); - int ret; - ret = stmmac_pltfr_remove(pdev); + stmmac_pltfr_remove(pdev); mediatek_dwmac_clks_config(priv_plat, false); - - return ret; } static const struct of_device_id mediatek_dwmac_match[] = { @@ -701,7 +698,7 @@ MODULE_DEVICE_TABLE(of, mediatek_dwmac_match); static struct platform_driver mediatek_dwmac_driver = { .probe = mediatek_dwmac_probe, - .remove = mediatek_dwmac_remove, + .remove_new = mediatek_dwmac_remove, .driver = { .name = "dwmac-mediatek", .pm = &stmmac_pltfr_pm_ops, diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-meson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-meson.c index 16fb66a0ca72cab0e7c87b02013b2cf7dcfa5a5f..7aa5e6bc04ebab474bb5631c4b5a4b90c77b1d26 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-meson.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-meson.c @@ -91,7 +91,7 @@ MODULE_DEVICE_TABLE(of, meson6_dwmac_match); static struct platform_driver meson6_dwmac_driver = { .probe = meson6_dwmac_probe, - .remove = stmmac_pltfr_remove, + .remove_new = stmmac_pltfr_remove, .driver = { .name = "meson6-dwmac", .pm = &stmmac_pltfr_pm_ops, diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c index f6754e3643f3e37406218b0a797d758ac90bbfdd..92b16048f91c0d2140980591be204b2e0c2f12de 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c @@ -539,7 +539,7 @@ MODULE_DEVICE_TABLE(of, meson8b_dwmac_match); static struct platform_driver meson8b_dwmac_driver = { .probe = meson8b_dwmac_probe, - .remove = stmmac_pltfr_remove, + .remove_new = stmmac_pltfr_remove, .driver = { .name = "meson8b-dwmac", .pm = &stmmac_pltfr_pm_ops, diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-oxnas.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-oxnas.c index 62a69a91ab22dc76eb45b7cc5647e398925e4430..42954020de2ce1649486847fe185e61a65384d15 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-oxnas.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-oxnas.c @@ -231,7 +231,7 @@ MODULE_DEVICE_TABLE(of, oxnas_dwmac_match); static struct platform_driver oxnas_dwmac_driver = { .probe = oxnas_dwmac_probe, - .remove = stmmac_pltfr_remove, + .remove_new = stmmac_pltfr_remove, .driver = { .name = "oxnas-dwmac", .pm = &stmmac_pltfr_pm_ops, diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c index f07905f00f9888e64cc177e58edb16c220a8d1cc..e62940414e54b52a0a14f806e06d5c2a9180d521 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c @@ -6,6 +6,9 @@ #include #include #include +#include +#include + #include "stmmac.h" #include "stmmac_platform.h" @@ -72,6 +75,10 @@ #define RGMII_CONFIG2_DATA_DIVIDE_CLK_SEL BIT(6) #define RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN BIT(5) +/* MAC_CTRL_REG bits */ +#define ETHQOS_MAC_CTRL_SPEED_MODE BIT(14) +#define ETHQOS_MAC_CTRL_PORT_SEL BIT(15) + struct ethqos_emac_por { unsigned int offset; unsigned int value; @@ -81,22 +88,28 @@ struct ethqos_emac_driver_data { const struct ethqos_emac_por *por; unsigned int num_por; bool rgmii_config_loopback_en; - bool has_emac3; + bool has_emac_ge_3; + const char *link_clk_name; + bool has_integrated_pcs; struct dwmac4_addrs dwmac4_addrs; }; struct qcom_ethqos { struct platform_device *pdev; void __iomem *rgmii_base; + void __iomem *mac_base; + int (*configure_func)(struct qcom_ethqos *ethqos); - unsigned int rgmii_clk_rate; - struct clk *rgmii_clk; + unsigned int link_clk_rate; + struct clk *link_clk; + struct phy *serdes_phy; unsigned int speed; + int phy_mode; const struct ethqos_emac_por *por; unsigned int num_por; bool rgmii_config_loopback_en; - bool has_emac3; + bool has_emac_ge_3; }; static int rgmii_readl(struct qcom_ethqos *ethqos, unsigned int offset) @@ -115,7 +128,7 @@ static void rgmii_updatel(struct qcom_ethqos *ethqos, { unsigned int temp; - temp = rgmii_readl(ethqos, offset); + temp = rgmii_readl(ethqos, offset); temp = (temp & ~(mask)) | val; rgmii_writel(ethqos, temp, offset); } @@ -123,25 +136,26 @@ static void rgmii_updatel(struct qcom_ethqos *ethqos, static void rgmii_dump(void *priv) { struct qcom_ethqos *ethqos = priv; + struct device *dev = ðqos->pdev->dev; - dev_dbg(ðqos->pdev->dev, "Rgmii register dump\n"); - dev_dbg(ðqos->pdev->dev, "RGMII_IO_MACRO_CONFIG: %x\n", + dev_dbg(dev, "Rgmii register dump\n"); + dev_dbg(dev, "RGMII_IO_MACRO_CONFIG: %x\n", rgmii_readl(ethqos, RGMII_IO_MACRO_CONFIG)); - dev_dbg(ðqos->pdev->dev, "SDCC_HC_REG_DLL_CONFIG: %x\n", + dev_dbg(dev, "SDCC_HC_REG_DLL_CONFIG: %x\n", rgmii_readl(ethqos, SDCC_HC_REG_DLL_CONFIG)); - dev_dbg(ðqos->pdev->dev, "SDCC_HC_REG_DDR_CONFIG: %x\n", + dev_dbg(dev, "SDCC_HC_REG_DDR_CONFIG: %x\n", rgmii_readl(ethqos, SDCC_HC_REG_DDR_CONFIG)); - dev_dbg(ðqos->pdev->dev, "SDCC_HC_REG_DLL_CONFIG2: %x\n", + dev_dbg(dev, "SDCC_HC_REG_DLL_CONFIG2: %x\n", rgmii_readl(ethqos, SDCC_HC_REG_DLL_CONFIG2)); - dev_dbg(ðqos->pdev->dev, "SDC4_STATUS: %x\n", + dev_dbg(dev, "SDC4_STATUS: %x\n", rgmii_readl(ethqos, SDC4_STATUS)); - dev_dbg(ðqos->pdev->dev, "SDCC_USR_CTL: %x\n", + dev_dbg(dev, "SDCC_USR_CTL: %x\n", rgmii_readl(ethqos, SDCC_USR_CTL)); - dev_dbg(ðqos->pdev->dev, "RGMII_IO_MACRO_CONFIG2: %x\n", + dev_dbg(dev, "RGMII_IO_MACRO_CONFIG2: %x\n", rgmii_readl(ethqos, RGMII_IO_MACRO_CONFIG2)); - dev_dbg(ðqos->pdev->dev, "RGMII_IO_MACRO_DEBUG1: %x\n", + dev_dbg(dev, "RGMII_IO_MACRO_DEBUG1: %x\n", rgmii_readl(ethqos, RGMII_IO_MACRO_DEBUG1)); - dev_dbg(ðqos->pdev->dev, "EMAC_SYSTEM_LOW_POWER_DEBUG: %x\n", + dev_dbg(dev, "EMAC_SYSTEM_LOW_POWER_DEBUG: %x\n", rgmii_readl(ethqos, EMAC_SYSTEM_LOW_POWER_DEBUG)); } @@ -151,23 +165,23 @@ static void rgmii_dump(void *priv) #define RGMII_ID_MODE_10_LOW_SVS_CLK_FREQ (5 * 1000 * 1000UL) static void -ethqos_update_rgmii_clk(struct qcom_ethqos *ethqos, unsigned int speed) +ethqos_update_link_clk(struct qcom_ethqos *ethqos, unsigned int speed) { switch (speed) { case SPEED_1000: - ethqos->rgmii_clk_rate = RGMII_1000_NOM_CLK_FREQ; + ethqos->link_clk_rate = RGMII_1000_NOM_CLK_FREQ; break; case SPEED_100: - ethqos->rgmii_clk_rate = RGMII_ID_MODE_100_LOW_SVS_CLK_FREQ; + ethqos->link_clk_rate = RGMII_ID_MODE_100_LOW_SVS_CLK_FREQ; break; case SPEED_10: - ethqos->rgmii_clk_rate = RGMII_ID_MODE_10_LOW_SVS_CLK_FREQ; + ethqos->link_clk_rate = RGMII_ID_MODE_10_LOW_SVS_CLK_FREQ; break; } - clk_set_rate(ethqos->rgmii_clk, ethqos->rgmii_clk_rate); + clk_set_rate(ethqos->link_clk, ethqos->link_clk_rate); } static void ethqos_set_func_clk_en(struct qcom_ethqos *ethqos) @@ -189,7 +203,7 @@ static const struct ethqos_emac_driver_data emac_v2_3_0_data = { .por = emac_v2_3_0_por, .num_por = ARRAY_SIZE(emac_v2_3_0_por), .rgmii_config_loopback_en = true, - .has_emac3 = false, + .has_emac_ge_3 = false, }; static const struct ethqos_emac_por emac_v2_1_0_por[] = { @@ -205,7 +219,7 @@ static const struct ethqos_emac_driver_data emac_v2_1_0_data = { .por = emac_v2_1_0_por, .num_por = ARRAY_SIZE(emac_v2_1_0_por), .rgmii_config_loopback_en = false, - .has_emac3 = false, + .has_emac_ge_3 = false, }; static const struct ethqos_emac_por emac_v3_0_0_por[] = { @@ -221,7 +235,41 @@ static const struct ethqos_emac_driver_data emac_v3_0_0_data = { .por = emac_v3_0_0_por, .num_por = ARRAY_SIZE(emac_v3_0_0_por), .rgmii_config_loopback_en = false, - .has_emac3 = true, + .has_emac_ge_3 = true, + .dwmac4_addrs = { + .dma_chan = 0x00008100, + .dma_chan_offset = 0x1000, + .mtl_chan = 0x00008000, + .mtl_chan_offset = 0x1000, + .mtl_ets_ctrl = 0x00008010, + .mtl_ets_ctrl_offset = 0x1000, + .mtl_txq_weight = 0x00008018, + .mtl_txq_weight_offset = 0x1000, + .mtl_send_slp_cred = 0x0000801c, + .mtl_send_slp_cred_offset = 0x1000, + .mtl_high_cred = 0x00008020, + .mtl_high_cred_offset = 0x1000, + .mtl_low_cred = 0x00008024, + .mtl_low_cred_offset = 0x1000, + }, +}; + +static const struct ethqos_emac_por emac_v4_0_0_por[] = { + { .offset = RGMII_IO_MACRO_CONFIG, .value = 0x40c01343 }, + { .offset = SDCC_HC_REG_DLL_CONFIG, .value = 0x2004642c }, + { .offset = SDCC_HC_REG_DDR_CONFIG, .value = 0x80040800 }, + { .offset = SDCC_HC_REG_DLL_CONFIG2, .value = 0x00200000 }, + { .offset = SDCC_USR_CTL, .value = 0x00010800 }, + { .offset = RGMII_IO_MACRO_CONFIG2, .value = 0x00002060 }, +}; + +static const struct ethqos_emac_driver_data emac_v4_0_0_data = { + .por = emac_v4_0_0_por, + .num_por = ARRAY_SIZE(emac_v3_0_0_por), + .rgmii_config_loopback_en = false, + .has_emac_ge_3 = true, + .link_clk_name = "phyaux", + .has_integrated_pcs = true, .dwmac4_addrs = { .dma_chan = 0x00008100, .dma_chan_offset = 0x1000, @@ -242,6 +290,7 @@ static const struct ethqos_emac_driver_data emac_v3_0_0_data = { static int ethqos_dll_configure(struct qcom_ethqos *ethqos) { + struct device *dev = ðqos->pdev->dev; unsigned int val; int retry = 1000; @@ -261,7 +310,7 @@ static int ethqos_dll_configure(struct qcom_ethqos *ethqos) rgmii_updatel(ethqos, SDCC_DLL_CONFIG_DLL_EN, SDCC_DLL_CONFIG_DLL_EN, SDCC_HC_REG_DLL_CONFIG); - if (!ethqos->has_emac3) { + if (!ethqos->has_emac_ge_3) { rgmii_updatel(ethqos, SDCC_DLL_MCLK_GATING_EN, 0, SDCC_HC_REG_DLL_CONFIG); @@ -279,7 +328,7 @@ static int ethqos_dll_configure(struct qcom_ethqos *ethqos) retry--; } while (retry > 0); if (!retry) - dev_err(ðqos->pdev->dev, "Clear CK_OUT_EN timedout\n"); + dev_err(dev, "Clear CK_OUT_EN timedout\n"); /* Set CK_OUT_EN */ rgmii_updatel(ethqos, SDCC_DLL_CONFIG_CK_OUT_EN, @@ -296,13 +345,13 @@ static int ethqos_dll_configure(struct qcom_ethqos *ethqos) retry--; } while (retry > 0); if (!retry) - dev_err(ðqos->pdev->dev, "Set CK_OUT_EN timedout\n"); + dev_err(dev, "Set CK_OUT_EN timedout\n"); /* Set DDR_CAL_EN */ rgmii_updatel(ethqos, SDCC_DLL_CONFIG2_DDR_CAL_EN, SDCC_DLL_CONFIG2_DDR_CAL_EN, SDCC_HC_REG_DLL_CONFIG2); - if (!ethqos->has_emac3) { + if (!ethqos->has_emac_ge_3) { rgmii_updatel(ethqos, SDCC_DLL_CONFIG2_DLL_CLOCK_DIS, 0, SDCC_HC_REG_DLL_CONFIG2); @@ -322,14 +371,13 @@ static int ethqos_dll_configure(struct qcom_ethqos *ethqos) static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos) { + struct device *dev = ðqos->pdev->dev; int phase_shift; - int phy_mode; int loopback; /* Determine if the PHY adds a 2 ns TX delay or the MAC handles it */ - phy_mode = device_get_phy_mode(ðqos->pdev->dev); - if (phy_mode == PHY_INTERFACE_MODE_RGMII_ID || - phy_mode == PHY_INTERFACE_MODE_RGMII_TXID) + if (ethqos->phy_mode == PHY_INTERFACE_MODE_RGMII_ID || + ethqos->phy_mode == PHY_INTERFACE_MODE_RGMII_TXID) phase_shift = 0; else phase_shift = RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN; @@ -373,7 +421,7 @@ static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos) /* PRG_RCLK_DLY = TCXO period * TCXO_CYCLES_CNT / 2 * RX delay ns, * in practice this becomes PRG_RCLK_DLY = 52 * 4 / 2 * RX delay ns */ - if (ethqos->has_emac3) { + if (ethqos->has_emac_ge_3) { /* 0.9 ns */ rgmii_updatel(ethqos, SDCC_DDR_CONFIG_PRG_RCLK_DLY, 115, SDCC_HC_REG_DDR_CONFIG); @@ -408,7 +456,7 @@ static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos) rgmii_updatel(ethqos, RGMII_CONFIG2_RSVD_CONFIG15, 0, RGMII_IO_MACRO_CONFIG2); - if (ethqos->has_emac3) + if (ethqos->has_emac_ge_3) rgmii_updatel(ethqos, RGMII_CONFIG2_RX_PROG_SWAP, RGMII_CONFIG2_RX_PROG_SWAP, RGMII_IO_MACRO_CONFIG2); @@ -448,7 +496,7 @@ static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos) RGMII_IO_MACRO_CONFIG); rgmii_updatel(ethqos, RGMII_CONFIG2_RSVD_CONFIG15, 0, RGMII_IO_MACRO_CONFIG2); - if (ethqos->has_emac3) + if (ethqos->has_emac_ge_3) rgmii_updatel(ethqos, RGMII_CONFIG2_RX_PROG_SWAP, RGMII_CONFIG2_RX_PROG_SWAP, RGMII_IO_MACRO_CONFIG2); @@ -468,16 +516,16 @@ static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos) loopback, RGMII_IO_MACRO_CONFIG); break; default: - dev_err(ðqos->pdev->dev, - "Invalid speed %d\n", ethqos->speed); + dev_err(dev, "Invalid speed %d\n", ethqos->speed); return -EINVAL; } return 0; } -static int ethqos_configure(struct qcom_ethqos *ethqos) +static int ethqos_configure_rgmii(struct qcom_ethqos *ethqos) { + struct device *dev = ðqos->pdev->dev; volatile unsigned int dll_lock; unsigned int i, retry = 1000; @@ -497,7 +545,7 @@ static int ethqos_configure(struct qcom_ethqos *ethqos) rgmii_updatel(ethqos, SDCC_DLL_CONFIG_PDN, SDCC_DLL_CONFIG_PDN, SDCC_HC_REG_DLL_CONFIG); - if (ethqos->has_emac3) { + if (ethqos->has_emac_ge_3) { if (ethqos->speed == SPEED_1000) { rgmii_writel(ethqos, 0x1800000, SDCC_TEST_CTL); rgmii_writel(ethqos, 0x2C010800, SDCC_USR_CTL); @@ -527,7 +575,7 @@ static int ethqos_configure(struct qcom_ethqos *ethqos) SDCC_HC_REG_DLL_CONFIG); /* Set USR_CTL bit 26 with mask of 3 bits */ - if (!ethqos->has_emac3) + if (!ethqos->has_emac_ge_3) rgmii_updatel(ethqos, GENMASK(26, 24), BIT(26), SDCC_USR_CTL); @@ -540,8 +588,7 @@ static int ethqos_configure(struct qcom_ethqos *ethqos) retry--; } while (retry > 0); if (!retry) - dev_err(ðqos->pdev->dev, - "Timeout while waiting for DLL lock\n"); + dev_err(dev, "Timeout while waiting for DLL lock\n"); } if (ethqos->speed == SPEED_1000) @@ -552,24 +599,80 @@ static int ethqos_configure(struct qcom_ethqos *ethqos) return 0; } +static int ethqos_configure_sgmii(struct qcom_ethqos *ethqos) +{ + int val; + + val = readl(ethqos->mac_base + MAC_CTRL_REG); + + switch (ethqos->speed) { + case SPEED_1000: + val &= ~ETHQOS_MAC_CTRL_PORT_SEL; + rgmii_updatel(ethqos, RGMII_CONFIG2_RGMII_CLK_SEL_CFG, + RGMII_CONFIG2_RGMII_CLK_SEL_CFG, + RGMII_IO_MACRO_CONFIG2); + break; + case SPEED_100: + val |= ETHQOS_MAC_CTRL_PORT_SEL | ETHQOS_MAC_CTRL_SPEED_MODE; + break; + case SPEED_10: + val |= ETHQOS_MAC_CTRL_PORT_SEL; + val &= ~ETHQOS_MAC_CTRL_SPEED_MODE; + break; + } + + writel(val, ethqos->mac_base + MAC_CTRL_REG); + + return val; +} + +static int ethqos_configure(struct qcom_ethqos *ethqos) +{ + return ethqos->configure_func(ethqos); +} + static void ethqos_fix_mac_speed(void *priv, unsigned int speed) { struct qcom_ethqos *ethqos = priv; ethqos->speed = speed; - ethqos_update_rgmii_clk(ethqos, speed); + ethqos_update_link_clk(ethqos, speed); ethqos_configure(ethqos); } +static int qcom_ethqos_serdes_powerup(struct net_device *ndev, void *priv) +{ + struct qcom_ethqos *ethqos = priv; + int ret; + + ret = phy_init(ethqos->serdes_phy); + if (ret) + return ret; + + ret = phy_power_on(ethqos->serdes_phy); + if (ret) + return ret; + + return phy_set_speed(ethqos->serdes_phy, ethqos->speed); +} + +static void qcom_ethqos_serdes_powerdown(struct net_device *ndev, void *priv) +{ + struct qcom_ethqos *ethqos = priv; + + phy_power_off(ethqos->serdes_phy); + phy_exit(ethqos->serdes_phy); +} + static int ethqos_clks_config(void *priv, bool enabled) { struct qcom_ethqos *ethqos = priv; int ret = 0; if (enabled) { - ret = clk_prepare_enable(ethqos->rgmii_clk); + ret = clk_prepare_enable(ethqos->link_clk); if (ret) { - dev_err(ðqos->pdev->dev, "rgmii_clk enable failed\n"); + dev_err(ðqos->pdev->dev, "link_clk enable failed\n"); return ret; } @@ -580,18 +683,24 @@ static int ethqos_clks_config(void *priv, bool enabled) */ ethqos_set_func_clk_en(ethqos); } else { - clk_disable_unprepare(ethqos->rgmii_clk); + clk_disable_unprepare(ethqos->link_clk); } return ret; } +static void ethqos_clks_disable(void *data) +{ + ethqos_clks_config(data, false); +} + static int qcom_ethqos_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; + const struct ethqos_emac_driver_data *data; struct plat_stmmacenet_data *plat_dat; struct stmmac_resources stmmac_res; - const struct ethqos_emac_driver_data *data; + struct device *dev = &pdev->dev; struct qcom_ethqos *ethqos; int ret; @@ -599,90 +708,91 @@ static int qcom_ethqos_probe(struct platform_device *pdev) if (ret) return ret; - plat_dat = stmmac_probe_config_dt(pdev, stmmac_res.mac); + plat_dat = devm_stmmac_probe_config_dt(pdev, stmmac_res.mac); if (IS_ERR(plat_dat)) { - dev_err(&pdev->dev, "dt configuration failed\n"); + dev_err(dev, "dt configuration failed\n"); return PTR_ERR(plat_dat); } plat_dat->clks_config = ethqos_clks_config; - ethqos = devm_kzalloc(&pdev->dev, sizeof(*ethqos), GFP_KERNEL); - if (!ethqos) { - ret = -ENOMEM; - goto err_mem; + ethqos = devm_kzalloc(dev, sizeof(*ethqos), GFP_KERNEL); + if (!ethqos) + return -ENOMEM; + + ethqos->phy_mode = device_get_phy_mode(dev); + switch (ethqos->phy_mode) { + case PHY_INTERFACE_MODE_RGMII: + case PHY_INTERFACE_MODE_RGMII_ID: + case PHY_INTERFACE_MODE_RGMII_RXID: + case PHY_INTERFACE_MODE_RGMII_TXID: + ethqos->configure_func = ethqos_configure_rgmii; + break; + case PHY_INTERFACE_MODE_SGMII: + ethqos->configure_func = ethqos_configure_sgmii; + break; + case -ENODEV: + return -ENODEV; + default: + return -EINVAL; } ethqos->pdev = pdev; ethqos->rgmii_base = devm_platform_ioremap_resource_byname(pdev, "rgmii"); - if (IS_ERR(ethqos->rgmii_base)) { - ret = PTR_ERR(ethqos->rgmii_base); - goto err_mem; - } + if (IS_ERR(ethqos->rgmii_base)) + return PTR_ERR(ethqos->rgmii_base); + + ethqos->mac_base = stmmac_res.addr; - data = of_device_get_match_data(&pdev->dev); + data = of_device_get_match_data(dev); ethqos->por = data->por; ethqos->num_por = data->num_por; ethqos->rgmii_config_loopback_en = data->rgmii_config_loopback_en; - ethqos->has_emac3 = data->has_emac3; + ethqos->has_emac_ge_3 = data->has_emac_ge_3; - ethqos->rgmii_clk = devm_clk_get(&pdev->dev, "rgmii"); - if (IS_ERR(ethqos->rgmii_clk)) { - ret = PTR_ERR(ethqos->rgmii_clk); - goto err_mem; - } + ethqos->link_clk = devm_clk_get(dev, data->link_clk_name ?: "rgmii"); + if (IS_ERR(ethqos->link_clk)) + return PTR_ERR(ethqos->link_clk); ret = ethqos_clks_config(ethqos, true); if (ret) - goto err_mem; + return ret; + + ret = devm_add_action_or_reset(dev, ethqos_clks_disable, ethqos); + if (ret) + return ret; + + ethqos->serdes_phy = devm_phy_optional_get(dev, "serdes"); + if (IS_ERR(ethqos->serdes_phy)) + return PTR_ERR(ethqos->serdes_phy); ethqos->speed = SPEED_1000; - ethqos_update_rgmii_clk(ethqos, SPEED_1000); + ethqos_update_link_clk(ethqos, SPEED_1000); ethqos_set_func_clk_en(ethqos); plat_dat->bsp_priv = ethqos; plat_dat->fix_mac_speed = ethqos_fix_mac_speed; plat_dat->dump_debug_regs = rgmii_dump; plat_dat->has_gmac4 = 1; - if (ethqos->has_emac3) + if (ethqos->has_emac_ge_3) plat_dat->dwmac4_addrs = &data->dwmac4_addrs; plat_dat->pmt = 1; plat_dat->tso_en = of_property_read_bool(np, "snps,tso"); if (of_device_is_compatible(np, "qcom,qcs404-ethqos")) plat_dat->rx_clk_runs_in_lpi = 1; + plat_dat->has_integrated_pcs = data->has_integrated_pcs; - ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); - if (ret) - goto err_clk; - - return ret; - -err_clk: - ethqos_clks_config(ethqos, false); - -err_mem: - stmmac_remove_config_dt(pdev, plat_dat); - - return ret; -} - -static int qcom_ethqos_remove(struct platform_device *pdev) -{ - struct qcom_ethqos *ethqos; - int ret; - - ethqos = get_stmmac_bsp_priv(&pdev->dev); - if (!ethqos) - return -ENODEV; - - ret = stmmac_pltfr_remove(pdev); - ethqos_clks_config(ethqos, false); + if (ethqos->serdes_phy) { + plat_dat->serdes_powerup = qcom_ethqos_serdes_powerup; + plat_dat->serdes_powerdown = qcom_ethqos_serdes_powerdown; + } - return ret; + return devm_stmmac_pltfr_probe(pdev, plat_dat, &stmmac_res); } static const struct of_device_id qcom_ethqos_match[] = { { .compatible = "qcom,qcs404-ethqos", .data = &emac_v2_3_0_data}, + { .compatible = "qcom,sa8775p-ethqos", .data = &emac_v4_0_0_data}, { .compatible = "qcom,sc8280xp-ethqos", .data = &emac_v3_0_0_data}, { .compatible = "qcom,sm8150-ethqos", .data = &emac_v2_1_0_data}, { } @@ -691,7 +801,6 @@ MODULE_DEVICE_TABLE(of, qcom_ethqos_match); static struct platform_driver qcom_ethqos_driver = { .probe = qcom_ethqos_probe, - .remove = qcom_ethqos_remove, .driver = { .name = "qcom-ethqos", .pm = &stmmac_pltfr_pm_ops, diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c index 4ea31ccf24d096b6e69e906ec7ab73b06ce92392..d81591b470a283e1688e4cce61cd38b1862c565f 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c @@ -1863,15 +1863,13 @@ static int rk_gmac_probe(struct platform_device *pdev) return ret; } -static int rk_gmac_remove(struct platform_device *pdev) +static void rk_gmac_remove(struct platform_device *pdev) { struct rk_priv_data *bsp_priv = get_stmmac_bsp_priv(&pdev->dev); stmmac_dvr_remove(&pdev->dev); rk_gmac_powerdown(bsp_priv); - - return 0; } #ifdef CONFIG_PM_SLEEP @@ -1925,7 +1923,7 @@ MODULE_DEVICE_TABLE(of, rk_gmac_dwmac_match); static struct platform_driver rk_gmac_dwmac_driver = { .probe = rk_gmac_probe, - .remove = rk_gmac_remove, + .remove_new = rk_gmac_remove, .driver = { .name = "rk_gmac-dwmac", .pm = &rk_gmac_pm_ops, diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c index 6b447d8f0bd8a3fb25dc3076d8ec5f455512f640..6267bcb60206b3201d6990a01304e13d15034178 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c @@ -10,14 +10,14 @@ #include #include #include +#include +#include #include #include #include "stmmac.h" #include "stmmac_platform.h" -#include "altr_tse_pcs.h" - #define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_GMII_MII 0x0 #define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RGMII 0x1 #define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RMII 0x2 @@ -37,6 +37,10 @@ #define EMAC_SPLITTER_CTRL_SPEED_100 0x3 #define EMAC_SPLITTER_CTRL_SPEED_1000 0x0 +#define SGMII_ADAPTER_CTRL_REG 0x00 +#define SGMII_ADAPTER_ENABLE 0x0000 +#define SGMII_ADAPTER_DISABLE 0x0001 + struct socfpga_dwmac; struct socfpga_dwmac_ops { int (*set_phy_mode)(struct socfpga_dwmac *dwmac_priv); @@ -50,16 +54,18 @@ struct socfpga_dwmac { struct reset_control *stmmac_rst; struct reset_control *stmmac_ocp_rst; void __iomem *splitter_base; + void __iomem *tse_pcs_base; + void __iomem *sgmii_adapter_base; bool f2h_ptp_ref_clk; - struct tse_pcs pcs; const struct socfpga_dwmac_ops *ops; + struct mdio_device *pcs_mdiodev; }; static void socfpga_dwmac_fix_mac_speed(void *priv, unsigned int speed) { struct socfpga_dwmac *dwmac = (struct socfpga_dwmac *)priv; void __iomem *splitter_base = dwmac->splitter_base; - void __iomem *sgmii_adapter_base = dwmac->pcs.sgmii_adapter_base; + void __iomem *sgmii_adapter_base = dwmac->sgmii_adapter_base; struct device *dev = dwmac->dev; struct net_device *ndev = dev_get_drvdata(dev); struct phy_device *phy_dev = ndev->phydev; @@ -89,11 +95,9 @@ static void socfpga_dwmac_fix_mac_speed(void *priv, unsigned int speed) writel(val, splitter_base + EMAC_SPLITTER_CTRL_REG); } - if (phy_dev && sgmii_adapter_base) { + if (phy_dev && sgmii_adapter_base) writew(SGMII_ADAPTER_ENABLE, sgmii_adapter_base + SGMII_ADAPTER_CTRL_REG); - tse_pcs_fix_mac_speed(&dwmac->pcs, phy_dev, speed); - } } static int socfpga_dwmac_parse_data(struct socfpga_dwmac *dwmac, struct device *dev) @@ -183,11 +187,11 @@ static int socfpga_dwmac_parse_data(struct socfpga_dwmac *dwmac, struct device * goto err_node_put; } - dwmac->pcs.sgmii_adapter_base = + dwmac->sgmii_adapter_base = devm_ioremap_resource(dev, &res_sgmii_adapter); - if (IS_ERR(dwmac->pcs.sgmii_adapter_base)) { - ret = PTR_ERR(dwmac->pcs.sgmii_adapter_base); + if (IS_ERR(dwmac->sgmii_adapter_base)) { + ret = PTR_ERR(dwmac->sgmii_adapter_base); goto err_node_put; } } @@ -205,11 +209,11 @@ static int socfpga_dwmac_parse_data(struct socfpga_dwmac *dwmac, struct device * goto err_node_put; } - dwmac->pcs.tse_pcs_base = + dwmac->tse_pcs_base = devm_ioremap_resource(dev, &res_tse_pcs); - if (IS_ERR(dwmac->pcs.tse_pcs_base)) { - ret = PTR_ERR(dwmac->pcs.tse_pcs_base); + if (IS_ERR(dwmac->tse_pcs_base)) { + ret = PTR_ERR(dwmac->tse_pcs_base); goto err_node_put; } } @@ -235,6 +239,13 @@ static int socfpga_get_plat_phymode(struct socfpga_dwmac *dwmac) return priv->plat->interface; } +static void socfpga_sgmii_config(struct socfpga_dwmac *dwmac, bool enable) +{ + u16 val = enable ? SGMII_ADAPTER_ENABLE : SGMII_ADAPTER_DISABLE; + + writew(val, dwmac->sgmii_adapter_base + SGMII_ADAPTER_CTRL_REG); +} + static int socfpga_set_phy_mode_common(int phymode, u32 *val) { switch (phymode) { @@ -310,12 +321,8 @@ static int socfpga_gen5_set_phy_mode(struct socfpga_dwmac *dwmac) */ reset_control_deassert(dwmac->stmmac_ocp_rst); reset_control_deassert(dwmac->stmmac_rst); - if (phymode == PHY_INTERFACE_MODE_SGMII) { - if (tse_pcs_init(dwmac->pcs.tse_pcs_base, &dwmac->pcs) != 0) { - dev_err(dwmac->dev, "Unable to initialize TSE PCS"); - return -EINVAL; - } - } + if (phymode == PHY_INTERFACE_MODE_SGMII) + socfpga_sgmii_config(dwmac, true); return 0; } @@ -367,12 +374,8 @@ static int socfpga_gen10_set_phy_mode(struct socfpga_dwmac *dwmac) */ reset_control_deassert(dwmac->stmmac_ocp_rst); reset_control_deassert(dwmac->stmmac_rst); - if (phymode == PHY_INTERFACE_MODE_SGMII) { - if (tse_pcs_init(dwmac->pcs.tse_pcs_base, &dwmac->pcs) != 0) { - dev_err(dwmac->dev, "Unable to initialize TSE PCS"); - return -EINVAL; - } - } + if (phymode == PHY_INTERFACE_MODE_SGMII) + socfpga_sgmii_config(dwmac, true); return 0; } @@ -443,6 +446,48 @@ static int socfpga_dwmac_probe(struct platform_device *pdev) if (ret) goto err_dvr_remove; + /* Create a regmap for the PCS so that it can be used by the PCS driver, + * if we have such a PCS + */ + if (dwmac->tse_pcs_base) { + struct regmap_config pcs_regmap_cfg; + struct mdio_regmap_config mrc; + struct regmap *pcs_regmap; + struct mii_bus *pcs_bus; + + memset(&pcs_regmap_cfg, 0, sizeof(pcs_regmap_cfg)); + memset(&mrc, 0, sizeof(mrc)); + + pcs_regmap_cfg.reg_bits = 16; + pcs_regmap_cfg.val_bits = 16; + pcs_regmap_cfg.reg_shift = REGMAP_UPSHIFT(1); + + pcs_regmap = devm_regmap_init_mmio(&pdev->dev, dwmac->tse_pcs_base, + &pcs_regmap_cfg); + if (IS_ERR(pcs_regmap)) { + ret = PTR_ERR(pcs_regmap); + goto err_dvr_remove; + } + + mrc.regmap = pcs_regmap; + mrc.parent = &pdev->dev; + mrc.valid_addr = 0x0; + mrc.autoscan = false; + + snprintf(mrc.name, MII_BUS_ID_SIZE, "%s-pcs-mii", ndev->name); + pcs_bus = devm_mdio_regmap_register(&pdev->dev, &mrc); + if (IS_ERR(pcs_bus)) { + ret = PTR_ERR(pcs_bus); + goto err_dvr_remove; + } + + stpriv->hw->lynx_pcs = lynx_pcs_create_mdiodev(pcs_bus, 0); + if (IS_ERR(stpriv->hw->lynx_pcs)) { + ret = PTR_ERR(stpriv->hw->lynx_pcs); + goto err_dvr_remove; + } + } + return 0; err_dvr_remove: @@ -453,6 +498,17 @@ static int socfpga_dwmac_probe(struct platform_device *pdev) return ret; } +static void socfpga_dwmac_remove(struct platform_device *pdev) +{ + struct net_device *ndev = platform_get_drvdata(pdev); + struct stmmac_priv *priv = netdev_priv(ndev); + struct phylink_pcs *pcs = priv->hw->lynx_pcs; + + stmmac_pltfr_remove(pdev); + + lynx_pcs_destroy(pcs); +} + #ifdef CONFIG_PM_SLEEP static int socfpga_dwmac_resume(struct device *dev) { @@ -524,7 +580,7 @@ MODULE_DEVICE_TABLE(of, socfpga_dwmac_match); static struct platform_driver socfpga_dwmac_driver = { .probe = socfpga_dwmac_probe, - .remove = stmmac_pltfr_remove, + .remove_new = socfpga_dwmac_remove, .driver = { .name = "socfpga-dwmac", .pm = &socfpga_dwmac_pm_ops, diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-starfive.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-starfive.c index 4f51a7889642b3662ef7fadc5139bb2cf401df7c..d3a39d2fb3a9d8c3b936fffb551d55734efaedbf 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-starfive.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-starfive.c @@ -156,7 +156,7 @@ MODULE_DEVICE_TABLE(of, starfive_dwmac_match); static struct platform_driver starfive_dwmac_driver = { .probe = starfive_dwmac_probe, - .remove = stmmac_pltfr_remove, + .remove_new = stmmac_pltfr_remove, .driver = { .name = "starfive-dwmac", .pm = &stmmac_pltfr_pm_ops, diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c index 465ce66ef9c1fe277974d7b7e779804f965b1e43..dcbb17c4f07ad2c4656cf898277a02cb21dc24bb 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c @@ -317,15 +317,13 @@ static int sti_dwmac_probe(struct platform_device *pdev) return ret; } -static int sti_dwmac_remove(struct platform_device *pdev) +static void sti_dwmac_remove(struct platform_device *pdev) { struct sti_dwmac *dwmac = get_stmmac_bsp_priv(&pdev->dev); stmmac_dvr_remove(&pdev->dev); clk_disable_unprepare(dwmac->clk); - - return 0; } #ifdef CONFIG_PM_SLEEP @@ -365,7 +363,7 @@ MODULE_DEVICE_TABLE(of, sti_dwmac_match); static struct platform_driver sti_dwmac_driver = { .probe = sti_dwmac_probe, - .remove = sti_dwmac_remove, + .remove_new = sti_dwmac_remove, .driver = { .name = "sti-dwmac", .pm = &sti_dwmac_pm_ops, diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c index 0616b3a04ff3922ef5538c0c3f60e79611423112..bdb4de59a67274db0b000ef0cbbb0a29d3ba76ae 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c @@ -417,7 +417,7 @@ static int stm32_dwmac_probe(struct platform_device *pdev) return ret; } -static int stm32_dwmac_remove(struct platform_device *pdev) +static void stm32_dwmac_remove(struct platform_device *pdev) { struct net_device *ndev = platform_get_drvdata(pdev); struct stmmac_priv *priv = netdev_priv(ndev); @@ -431,8 +431,6 @@ static int stm32_dwmac_remove(struct platform_device *pdev) dev_pm_clear_wake_irq(&pdev->dev); device_init_wakeup(&pdev->dev, false); } - - return 0; } static int stm32mp1_suspend(struct stm32_dwmac *dwmac) @@ -528,7 +526,7 @@ MODULE_DEVICE_TABLE(of, stm32_dwmac_match); static struct platform_driver stm32_dwmac_driver = { .probe = stm32_dwmac_probe, - .remove = stm32_dwmac_remove, + .remove_new = stm32_dwmac_remove, .driver = { .name = "stm32-dwmac", .pm = &stm32_dwmac_pm_ops, diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c index c2c592ba0eb8afc9a3f019fdfbf5caf87c73ec6d..1e714380d1250be410b1e17a7fad40ae0b6c4b09 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c @@ -1294,7 +1294,7 @@ static int sun8i_dwmac_probe(struct platform_device *pdev) return ret; } -static int sun8i_dwmac_remove(struct platform_device *pdev) +static void sun8i_dwmac_remove(struct platform_device *pdev) { struct net_device *ndev = platform_get_drvdata(pdev); struct stmmac_priv *priv = netdev_priv(ndev); @@ -1309,8 +1309,6 @@ static int sun8i_dwmac_remove(struct platform_device *pdev) stmmac_pltfr_remove(pdev); sun8i_dwmac_unset_syscon(gmac); - - return 0; } static void sun8i_dwmac_shutdown(struct platform_device *pdev) @@ -1341,7 +1339,7 @@ MODULE_DEVICE_TABLE(of, sun8i_dwmac_match); static struct platform_driver sun8i_dwmac_driver = { .probe = sun8i_dwmac_probe, - .remove = sun8i_dwmac_remove, + .remove_new = sun8i_dwmac_remove, .shutdown = sun8i_dwmac_shutdown, .driver = { .name = "dwmac-sun8i", diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c index fc3b0acc8f99f0ee2cae3db690eb8fac78436f81..50963e91c347a3d589223c98059ea0fe93f8874e 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c @@ -179,7 +179,7 @@ MODULE_DEVICE_TABLE(of, sun7i_dwmac_match); static struct platform_driver sun7i_dwmac_driver = { .probe = sun7i_gmac_probe, - .remove = stmmac_pltfr_remove, + .remove_new = stmmac_pltfr_remove, .driver = { .name = "sun7i-dwmac", .pm = &stmmac_pltfr_pm_ops, diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-tegra.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-tegra.c index bdf990cf2f31035b7913edbc32ed90c577078f67..f8367c5b490baa64d01ac753ed5abf733defbab8 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-tegra.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-tegra.c @@ -353,15 +353,13 @@ static int tegra_mgbe_probe(struct platform_device *pdev) return err; } -static int tegra_mgbe_remove(struct platform_device *pdev) +static void tegra_mgbe_remove(struct platform_device *pdev) { struct tegra_mgbe *mgbe = get_stmmac_bsp_priv(&pdev->dev); clk_bulk_disable_unprepare(ARRAY_SIZE(mgbe_clks), mgbe->clks); stmmac_pltfr_remove(pdev); - - return 0; } static const struct of_device_id tegra_mgbe_match[] = { @@ -374,7 +372,7 @@ static SIMPLE_DEV_PM_OPS(tegra_mgbe_pm_ops, tegra_mgbe_suspend, tegra_mgbe_resum static struct platform_driver tegra_mgbe_driver = { .probe = tegra_mgbe_probe, - .remove = tegra_mgbe_remove, + .remove_new = tegra_mgbe_remove, .driver = { .name = "tegra-mgbe", .pm = &tegra_mgbe_pm_ops, diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-visconti.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-visconti.c index c3f10a92b62b804294d401c9e4b67618261aa8e4..acbb284be1741ec1f9268bf2d71cfd5febb92023 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-visconti.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-visconti.c @@ -198,7 +198,7 @@ static int visconti_eth_clock_probe(struct platform_device *pdev, return 0; } -static int visconti_eth_clock_remove(struct platform_device *pdev) +static void visconti_eth_clock_remove(struct platform_device *pdev) { struct visconti_eth *dwmac = get_stmmac_bsp_priv(&pdev->dev); struct net_device *ndev = platform_get_drvdata(pdev); @@ -206,8 +206,6 @@ static int visconti_eth_clock_remove(struct platform_device *pdev) clk_disable_unprepare(dwmac->phy_ref_clk); clk_disable_unprepare(priv->plat->stmmac_clk); - - return 0; } static int visconti_eth_dwmac_probe(struct platform_device *pdev) @@ -259,23 +257,16 @@ static int visconti_eth_dwmac_probe(struct platform_device *pdev) return ret; } -static int visconti_eth_dwmac_remove(struct platform_device *pdev) +static void visconti_eth_dwmac_remove(struct platform_device *pdev) { struct net_device *ndev = platform_get_drvdata(pdev); struct stmmac_priv *priv = netdev_priv(ndev); - int err; - err = stmmac_pltfr_remove(pdev); - if (err < 0) - dev_err(&pdev->dev, "failed to remove platform: %d\n", err); + stmmac_pltfr_remove(pdev); - err = visconti_eth_clock_remove(pdev); - if (err < 0) - dev_err(&pdev->dev, "failed to remove clock: %d\n", err); + visconti_eth_clock_remove(pdev); stmmac_remove_config_dt(pdev, priv->plat); - - return err; } static const struct of_device_id visconti_eth_dwmac_match[] = { @@ -286,7 +277,7 @@ MODULE_DEVICE_TABLE(of, visconti_eth_dwmac_match); static struct platform_driver visconti_eth_dwmac_driver = { .probe = visconti_eth_dwmac_probe, - .remove = visconti_eth_dwmac_remove, + .remove_new = visconti_eth_dwmac_remove, .driver = { .name = "visconti-eth-dwmac", .of_match_table = visconti_eth_dwmac_match, diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c index dfd53264e0360730290cb6d62ba871c249f5de59..070bd912580b7aecf24a127cf7d8d2bf2215161a 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c @@ -368,10 +368,12 @@ static int dwxgmac2_dma_interrupt(struct stmmac_priv *priv, if (likely(intr_status & XGMAC_RI)) { x->rx_normal_irq_n++; + x->rxq_stats[chan].rx_normal_irq_n++; ret |= handle_rx; } if (likely(intr_status & (XGMAC_TI | XGMAC_TBU))) { x->tx_normal_irq_n++; + x->txq_stats[chan].tx_normal_irq_n++; ret |= handle_tx; } } diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 87510951f4e80b4f6e3aa52424439886216fe195..4727f7be4f86ef1ef2c6b68df1fabac9a0f7b5c1 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -937,10 +937,13 @@ static struct phylink_pcs *stmmac_mac_select_pcs(struct phylink_config *config, { struct stmmac_priv *priv = netdev_priv(to_net_dev(config->dev)); - if (!priv->hw->xpcs) - return NULL; + if (priv->hw->xpcs) + return &priv->hw->xpcs->pcs; - return &priv->hw->xpcs->pcs; + if (priv->hw->lynx_pcs) + return priv->hw->lynx_pcs; + + return NULL; } static void stmmac_mac_config(struct phylink_config *config, unsigned int mode, @@ -3813,7 +3816,8 @@ static int __stmmac_open(struct net_device *dev, if (priv->hw->pcs != STMMAC_PCS_TBI && priv->hw->pcs != STMMAC_PCS_RTBI && (!priv->hw->xpcs || - xpcs_get_an_mode(priv->hw->xpcs, mode) != DW_AN_C73)) { + xpcs_get_an_mode(priv->hw->xpcs, mode) != DW_AN_C73) && + !priv->hw->lynx_pcs) { ret = stmmac_init_phy(dev); if (ret) { netdev_err(priv->dev, @@ -5794,7 +5798,7 @@ static void stmmac_common_interrupt(struct stmmac_priv *priv) } /* PCS link status */ - if (priv->hw->pcs) { + if (priv->hw->pcs && !priv->plat->has_integrated_pcs) { if (priv->xstats.pcs_link) netif_carrier_on(priv->dev); else @@ -7457,12 +7461,6 @@ void stmmac_dvr_remove(struct device *dev) netif_carrier_off(ndev); unregister_netdev(ndev); - /* Serdes power down needs to happen after VLAN filter - * is deleted that is triggered by unregister_netdev(). - */ - if (priv->plat->serdes_powerdown) - priv->plat->serdes_powerdown(ndev, priv->plat->bsp_priv); - #ifdef CONFIG_DEBUG_FS stmmac_exit_fs(ndev); #endif diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c index 6807c4c1a0a2f7dba6e0ba8194ed404de537e9a0..3db1cb0fd160ca4a8af5b2d3da6dec5d12fdd245 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c @@ -491,7 +491,6 @@ int stmmac_mdio_reset(struct mii_bus *bus) int stmmac_xpcs_setup(struct mii_bus *bus) { struct net_device *ndev = bus->priv; - struct mdio_device *mdiodev; struct stmmac_priv *priv; struct dw_xpcs *xpcs; int mode, addr; @@ -501,16 +500,10 @@ int stmmac_xpcs_setup(struct mii_bus *bus) /* Try to probe the XPCS by scanning all addresses. */ for (addr = 0; addr < PHY_MAX_ADDR; addr++) { - mdiodev = mdio_device_create(bus, addr); - if (IS_ERR(mdiodev)) + xpcs = xpcs_create_mdiodev(bus, addr, mode); + if (IS_ERR(xpcs)) continue; - xpcs = xpcs_create(mdiodev, mode); - if (IS_ERR_OR_NULL(xpcs)) { - mdio_device_free(mdiodev); - continue; - } - priv->hw->xpcs = xpcs; break; } @@ -669,10 +662,8 @@ int stmmac_mdio_unregister(struct net_device *ndev) if (!priv->mii) return 0; - if (priv->hw->xpcs) { - mdio_device_free(priv->hw->xpcs->mdiodev); + if (priv->hw->xpcs) xpcs_destroy(priv->hw->xpcs); - } mdiobus_unregister(priv->mii); priv->mii->priv = NULL; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c index eb0b2898daa3d78ac8484eb916f4495322a902a9..231152ee5a323e4dccb2b4b10e881cf8d290c95b 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c @@ -8,6 +8,7 @@ Author: Giuseppe Cavallaro *******************************************************************************/ +#include #include #include #include @@ -629,6 +630,39 @@ stmmac_probe_config_dt(struct platform_device *pdev, u8 *mac) return ret; } +static void devm_stmmac_remove_config_dt(void *data) +{ + struct plat_stmmacenet_data *plat = data; + + /* Platform data argument is unused */ + stmmac_remove_config_dt(NULL, plat); +} + +/** + * devm_stmmac_probe_config_dt + * @pdev: platform_device structure + * @mac: MAC address to use + * Description: Devres variant of stmmac_probe_config_dt(). Does not require + * the user to call stmmac_remove_config_dt() at driver detach. + */ +struct plat_stmmacenet_data * +devm_stmmac_probe_config_dt(struct platform_device *pdev, u8 *mac) +{ + struct plat_stmmacenet_data *plat; + int ret; + + plat = stmmac_probe_config_dt(pdev, mac); + if (IS_ERR(plat)) + return plat; + + ret = devm_add_action_or_reset(&pdev->dev, + devm_stmmac_remove_config_dt, plat); + if (ret) + return ERR_PTR(ret); + + return plat; +} + /** * stmmac_remove_config_dt - undo the effects of stmmac_probe_config_dt() * @pdev: platform_device structure @@ -651,12 +685,19 @@ stmmac_probe_config_dt(struct platform_device *pdev, u8 *mac) return ERR_PTR(-EINVAL); } +struct plat_stmmacenet_data * +devm_stmmac_probe_config_dt(struct platform_device *pdev, u8 *mac) +{ + return ERR_PTR(-EINVAL); +} + void stmmac_remove_config_dt(struct platform_device *pdev, struct plat_stmmacenet_data *plat) { } #endif /* CONFIG_OF */ EXPORT_SYMBOL_GPL(stmmac_probe_config_dt); +EXPORT_SYMBOL_GPL(devm_stmmac_probe_config_dt); EXPORT_SYMBOL_GPL(stmmac_remove_config_dt); int stmmac_get_platform_resources(struct platform_device *pdev, @@ -702,25 +743,127 @@ int stmmac_get_platform_resources(struct platform_device *pdev, EXPORT_SYMBOL_GPL(stmmac_get_platform_resources); /** - * stmmac_pltfr_remove + * stmmac_pltfr_init + * @pdev: pointer to the platform device + * @plat: driver data platform structure + * Description: Call the platform's init callback (if any) and propagate + * the return value. + */ +int stmmac_pltfr_init(struct platform_device *pdev, + struct plat_stmmacenet_data *plat) +{ + int ret = 0; + + if (plat->init) + ret = plat->init(pdev, plat->bsp_priv); + + return ret; +} +EXPORT_SYMBOL_GPL(stmmac_pltfr_init); + +/** + * stmmac_pltfr_exit + * @pdev: pointer to the platform device + * @plat: driver data platform structure + * Description: Call the platform's exit callback (if any). + */ +void stmmac_pltfr_exit(struct platform_device *pdev, + struct plat_stmmacenet_data *plat) +{ + if (plat->exit) + plat->exit(pdev, plat->bsp_priv); +} +EXPORT_SYMBOL_GPL(stmmac_pltfr_exit); + +/** + * stmmac_pltfr_probe * @pdev: platform device pointer - * Description: this function calls the main to free the net resources - * and calls the platforms hook and release the resources (e.g. mem). + * @plat: driver data platform structure + * @res: stmmac resources structure + * Description: This calls the platform's init() callback and probes the + * stmmac driver. */ -int stmmac_pltfr_remove(struct platform_device *pdev) +int stmmac_pltfr_probe(struct platform_device *pdev, + struct plat_stmmacenet_data *plat, + struct stmmac_resources *res) +{ + int ret; + + ret = stmmac_pltfr_init(pdev, plat); + if (ret) + return ret; + + ret = stmmac_dvr_probe(&pdev->dev, plat, res); + if (ret) { + stmmac_pltfr_exit(pdev, plat); + return ret; + } + + return ret; +} +EXPORT_SYMBOL_GPL(stmmac_pltfr_probe); + +static void devm_stmmac_pltfr_remove(void *data) +{ + struct platform_device *pdev = data; + + stmmac_pltfr_remove_no_dt(pdev); +} + +/** + * devm_stmmac_pltfr_probe + * @pdev: pointer to the platform device + * @plat: driver data platform structure + * @res: stmmac resources + * Description: Devres variant of stmmac_pltfr_probe(). Allows users to skip + * calling stmmac_pltfr_remove() on driver detach. + */ +int devm_stmmac_pltfr_probe(struct platform_device *pdev, + struct plat_stmmacenet_data *plat, + struct stmmac_resources *res) +{ + int ret; + + ret = stmmac_pltfr_probe(pdev, plat, res); + if (ret) + return ret; + + return devm_add_action_or_reset(&pdev->dev, devm_stmmac_pltfr_remove, + pdev); +} +EXPORT_SYMBOL_GPL(devm_stmmac_pltfr_probe); + +/** + * stmmac_pltfr_remove_no_dt + * @pdev: pointer to the platform device + * Description: This undoes the effects of stmmac_pltfr_probe() by removing the + * driver and calling the platform's exit() callback. + */ +void stmmac_pltfr_remove_no_dt(struct platform_device *pdev) { struct net_device *ndev = platform_get_drvdata(pdev); struct stmmac_priv *priv = netdev_priv(ndev); struct plat_stmmacenet_data *plat = priv->plat; stmmac_dvr_remove(&pdev->dev); + stmmac_pltfr_exit(pdev, plat); +} +EXPORT_SYMBOL_GPL(stmmac_pltfr_remove_no_dt); - if (plat->exit) - plat->exit(pdev, plat->bsp_priv); +/** + * stmmac_pltfr_remove + * @pdev: platform device pointer + * Description: this function calls the main to free the net resources + * and calls the platforms hook and release the resources (e.g. mem). + */ +void stmmac_pltfr_remove(struct platform_device *pdev) +{ + struct net_device *ndev = platform_get_drvdata(pdev); + struct stmmac_priv *priv = netdev_priv(ndev); + struct plat_stmmacenet_data *plat = priv->plat; + stmmac_pltfr_remove_no_dt(pdev); stmmac_remove_config_dt(pdev, plat); - - return 0; } EXPORT_SYMBOL_GPL(stmmac_pltfr_remove); @@ -739,8 +882,7 @@ static int __maybe_unused stmmac_pltfr_suspend(struct device *dev) struct platform_device *pdev = to_platform_device(dev); ret = stmmac_suspend(dev); - if (priv->plat->exit) - priv->plat->exit(pdev, priv->plat->bsp_priv); + stmmac_pltfr_exit(pdev, priv->plat); return ret; } @@ -757,9 +899,11 @@ static int __maybe_unused stmmac_pltfr_resume(struct device *dev) struct net_device *ndev = dev_get_drvdata(dev); struct stmmac_priv *priv = netdev_priv(ndev); struct platform_device *pdev = to_platform_device(dev); + int ret; - if (priv->plat->init) - priv->plat->init(pdev, priv->plat->bsp_priv); + ret = stmmac_pltfr_init(pdev, priv->plat->bsp_priv); + if (ret) + return ret; return stmmac_resume(dev); } diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.h b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.h index 3fff3f59d73d8961aa5162280ed8751a2ea6eeb1..c5565b2a70acc611242f47ac2f5c8681d6d8887a 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.h +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.h @@ -13,13 +13,27 @@ struct plat_stmmacenet_data * stmmac_probe_config_dt(struct platform_device *pdev, u8 *mac); +struct plat_stmmacenet_data * +devm_stmmac_probe_config_dt(struct platform_device *pdev, u8 *mac); void stmmac_remove_config_dt(struct platform_device *pdev, struct plat_stmmacenet_data *plat); int stmmac_get_platform_resources(struct platform_device *pdev, struct stmmac_resources *stmmac_res); -int stmmac_pltfr_remove(struct platform_device *pdev); +int stmmac_pltfr_init(struct platform_device *pdev, + struct plat_stmmacenet_data *plat); +void stmmac_pltfr_exit(struct platform_device *pdev, + struct plat_stmmacenet_data *plat); + +int stmmac_pltfr_probe(struct platform_device *pdev, + struct plat_stmmacenet_data *plat, + struct stmmac_resources *res); +int devm_stmmac_pltfr_probe(struct platform_device *pdev, + struct plat_stmmacenet_data *plat, + struct stmmac_resources *res); +void stmmac_pltfr_remove_no_dt(struct platform_device *pdev); +void stmmac_pltfr_remove(struct platform_device *pdev); extern const struct dev_pm_ops stmmac_pltfr_pm_ops; static inline void *get_stmmac_bsp_priv(struct device *dev) diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c index 9d55226479b4a701f10cb4c8003d151d5c8c77c4..ac41ef4cbd2f0243e984d81171ef15ea0173edff 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c @@ -966,8 +966,11 @@ static int tc_setup_taprio(struct stmmac_priv *priv, return -EOPNOTSUPP; } - if (!qopt->enable) + if (qopt->cmd == TAPRIO_CMD_DESTROY) goto disable; + else if (qopt->cmd != TAPRIO_CMD_REPLACE) + return -EOPNOTSUPP; + if (qopt->num_entries >= dep) return -EINVAL; if (!qopt->cycle_time) @@ -988,7 +991,7 @@ static int tc_setup_taprio(struct stmmac_priv *priv, mutex_lock(&priv->plat->est->lock); priv->plat->est->gcl_size = size; - priv->plat->est->enable = qopt->enable; + priv->plat->est->enable = qopt->cmd == TAPRIO_CMD_REPLACE; mutex_unlock(&priv->plat->est->lock); for (i = 0; i < size; i++) { diff --git a/drivers/net/ethernet/sun/cassini.c b/drivers/net/ethernet/sun/cassini.c index d61dfa250feb722b67352104b272dbeebd056f0d..b317b94864554a291be736dd0d0146ba920694c6 100644 --- a/drivers/net/ethernet/sun/cassini.c +++ b/drivers/net/ethernet/sun/cassini.c @@ -1998,10 +1998,8 @@ static int cas_rx_process_pkt(struct cas *cp, struct cas_rx_comp *rxc, skb->truesize += hlen - swivel; skb->len += hlen - swivel; - __skb_frag_set_page(frag, page->buffer); + skb_frag_fill_page_desc(frag, page->buffer, off, hlen - swivel); __skb_frag_ref(frag); - skb_frag_off_set(frag, off); - skb_frag_size_set(frag, hlen - swivel); /* any more data? */ if ((words[0] & RX_COMP1_SPLIT_PKT) && ((dlen -= hlen) > 0)) { @@ -2024,10 +2022,8 @@ static int cas_rx_process_pkt(struct cas *cp, struct cas_rx_comp *rxc, skb->len += hlen; frag++; - __skb_frag_set_page(frag, page->buffer); + skb_frag_fill_page_desc(frag, page->buffer, 0, hlen); __skb_frag_ref(frag); - skb_frag_off_set(frag, 0); - skb_frag_size_set(frag, hlen); RX_USED_ADD(page, hlen + cp->crc_size); } diff --git a/drivers/net/ethernet/sun/sunvnet_common.c b/drivers/net/ethernet/sun/sunvnet_common.c index a6211b95ed1781265c6fdc2003007cd93b8ca727..3525d5c0d694ca30fea4ddc12b1286a40bda359a 100644 --- a/drivers/net/ethernet/sun/sunvnet_common.c +++ b/drivers/net/ethernet/sun/sunvnet_common.c @@ -25,6 +25,7 @@ #endif #include +#include #include #include diff --git a/drivers/net/ethernet/ti/am65-cpsw-qos.c b/drivers/net/ethernet/ti/am65-cpsw-qos.c index 3a908db6e5b22eec99526cb6c8b263cb33e68fef..eced87fa261c9c02ba47379c0334a61942101870 100644 --- a/drivers/net/ethernet/ti/am65-cpsw-qos.c +++ b/drivers/net/ethernet/ti/am65-cpsw-qos.c @@ -450,7 +450,7 @@ static int am65_cpsw_configure_taprio(struct net_device *ndev, am65_cpsw_est_update_state(ndev); - if (!est_new->taprio.enable) { + if (est_new->taprio.cmd == TAPRIO_CMD_DESTROY) { am65_cpsw_stop_est(ndev); return ret; } @@ -476,7 +476,7 @@ static int am65_cpsw_configure_taprio(struct net_device *ndev, am65_cpsw_est_set_sched_list(ndev, est_new); am65_cpsw_port_est_assign_buf_num(ndev, est_new->buf); - am65_cpsw_est_set(ndev, est_new->taprio.enable); + am65_cpsw_est_set(ndev, est_new->taprio.cmd == TAPRIO_CMD_REPLACE); if (tact == TACT_PROG) { ret = am65_cpsw_timer_set(ndev, est_new); @@ -520,7 +520,7 @@ static int am65_cpsw_set_taprio(struct net_device *ndev, void *type_data) am65_cpsw_cp_taprio(taprio, &est_new->taprio); ret = am65_cpsw_configure_taprio(ndev, est_new); if (!ret) { - if (taprio->enable) { + if (taprio->cmd == TAPRIO_CMD_REPLACE) { devm_kfree(&ndev->dev, port->qos.est_admin); port->qos.est_admin = est_new; @@ -564,8 +564,13 @@ static void am65_cpsw_est_link_up(struct net_device *ndev, int link_speed) static int am65_cpsw_setup_taprio(struct net_device *ndev, void *type_data) { struct am65_cpsw_port *port = am65_ndev_to_port(ndev); + struct tc_taprio_qopt_offload *taprio = type_data; struct am65_cpsw_common *common = port->common; + if (taprio->cmd != TAPRIO_CMD_REPLACE && + taprio->cmd != TAPRIO_CMD_DESTROY) + return -EOPNOTSUPP; + if (!IS_ENABLED(CONFIG_TI_AM65_CPSW_TAS)) return -ENODEV; diff --git a/drivers/net/ethernet/wangxun/Kconfig b/drivers/net/ethernet/wangxun/Kconfig index c9d88673d30628205a7a80296c95fe39693938e2..39596cd135394878b778154bed09993eac94062d 100644 --- a/drivers/net/ethernet/wangxun/Kconfig +++ b/drivers/net/ethernet/wangxun/Kconfig @@ -40,6 +40,16 @@ config NGBE config TXGBE tristate "Wangxun(R) 10GbE PCI Express adapters support" depends on PCI + depends on COMMON_CLK + select REGMAP + select I2C + select I2C_DESIGNWARE_PLATFORM + select PHYLINK + select HWMON if TXGBE=y + select SFP + select GPIOLIB + select GPIOLIB_IRQCHIP + select PCS_XPCS select LIBWX help This driver supports Wangxun(R) 10GbE PCI Express family of diff --git a/drivers/net/ethernet/wangxun/libwx/wx_hw.c b/drivers/net/ethernet/wangxun/libwx/wx_hw.c index ca409b4054d0609f97ec15da5de1c8c4aecd2bbb..39a9aeee7aab228d96c578d1411f9ab140c4487f 100644 --- a/drivers/net/ethernet/wangxun/libwx/wx_hw.c +++ b/drivers/net/ethernet/wangxun/libwx/wx_hw.c @@ -1182,12 +1182,28 @@ static void wx_enable_sec_rx_path(struct wx *wx) WX_WRITE_FLUSH(wx); } +static void wx_vlan_strip_control(struct wx *wx, bool enable) +{ + int i, j; + + for (i = 0; i < wx->num_rx_queues; i++) { + struct wx_ring *ring = wx->rx_ring[i]; + + j = ring->reg_idx; + wr32m(wx, WX_PX_RR_CFG(j), WX_PX_RR_CFG_VLAN, + enable ? WX_PX_RR_CFG_VLAN : 0); + } +} + void wx_set_rx_mode(struct net_device *netdev) { struct wx *wx = netdev_priv(netdev); + netdev_features_t features; u32 fctrl, vmolr, vlnctrl; int count; + features = netdev->features; + /* Check for Promiscuous and All Multicast modes */ fctrl = rd32(wx, WX_PSR_CTL); fctrl &= ~(WX_PSR_CTL_UPE | WX_PSR_CTL_MPE); @@ -1254,6 +1270,13 @@ void wx_set_rx_mode(struct net_device *netdev) wr32(wx, WX_PSR_VLAN_CTL, vlnctrl); wr32(wx, WX_PSR_CTL, fctrl); wr32(wx, WX_PSR_VM_L2CTL(0), vmolr); + + if ((features & NETIF_F_HW_VLAN_CTAG_RX) && + (features & NETIF_F_HW_VLAN_STAG_RX)) + wx_vlan_strip_control(wx, true); + else + wx_vlan_strip_control(wx, false); + } EXPORT_SYMBOL(wx_set_rx_mode); @@ -1462,6 +1485,16 @@ static void wx_configure_tx(struct wx *wx) WX_MAC_TX_CFG_TE, WX_MAC_TX_CFG_TE); } +static void wx_restore_vlan(struct wx *wx) +{ + u16 vid = 1; + + wx_vlan_rx_add_vid(wx->netdev, htons(ETH_P_8021Q), 0); + + for_each_set_bit_from(vid, wx->active_vlans, VLAN_N_VID) + wx_vlan_rx_add_vid(wx->netdev, htons(ETH_P_8021Q), vid); +} + /** * wx_configure_rx - Configure Receive Unit after Reset * @wx: pointer to private structure @@ -1527,7 +1560,7 @@ void wx_configure(struct wx *wx) wx_configure_port(wx); wx_set_rx_mode(wx->netdev); - + wx_restore_vlan(wx); wx_enable_sec_rx_path(wx); wx_configure_tx(wx); @@ -1727,4 +1760,241 @@ int wx_sw_init(struct wx *wx) } EXPORT_SYMBOL(wx_sw_init); +/** + * wx_find_vlvf_slot - find the vlanid or the first empty slot + * @wx: pointer to hardware structure + * @vlan: VLAN id to write to VLAN filter + * + * return the VLVF index where this VLAN id should be placed + * + **/ +static int wx_find_vlvf_slot(struct wx *wx, u32 vlan) +{ + u32 bits = 0, first_empty_slot = 0; + int regindex; + + /* short cut the special case */ + if (vlan == 0) + return 0; + + /* Search for the vlan id in the VLVF entries. Save off the first empty + * slot found along the way + */ + for (regindex = 1; regindex < WX_PSR_VLAN_SWC_ENTRIES; regindex++) { + wr32(wx, WX_PSR_VLAN_SWC_IDX, regindex); + bits = rd32(wx, WX_PSR_VLAN_SWC); + if (!bits && !(first_empty_slot)) + first_empty_slot = regindex; + else if ((bits & 0x0FFF) == vlan) + break; + } + + if (regindex >= WX_PSR_VLAN_SWC_ENTRIES) { + if (first_empty_slot) + regindex = first_empty_slot; + else + regindex = -ENOMEM; + } + + return regindex; +} + +/** + * wx_set_vlvf - Set VLAN Pool Filter + * @wx: pointer to hardware structure + * @vlan: VLAN id to write to VLAN filter + * @vind: VMDq output index that maps queue to VLAN id in VFVFB + * @vlan_on: boolean flag to turn on/off VLAN in VFVF + * @vfta_changed: pointer to boolean flag which indicates whether VFTA + * should be changed + * + * Turn on/off specified bit in VLVF table. + **/ +static int wx_set_vlvf(struct wx *wx, u32 vlan, u32 vind, bool vlan_on, + bool *vfta_changed) +{ + int vlvf_index; + u32 vt, bits; + + /* If VT Mode is set + * Either vlan_on + * make sure the vlan is in VLVF + * set the vind bit in the matching VLVFB + * Or !vlan_on + * clear the pool bit and possibly the vind + */ + vt = rd32(wx, WX_CFG_PORT_CTL); + if (!(vt & WX_CFG_PORT_CTL_NUM_VT_MASK)) + return 0; + + vlvf_index = wx_find_vlvf_slot(wx, vlan); + if (vlvf_index < 0) + return vlvf_index; + + wr32(wx, WX_PSR_VLAN_SWC_IDX, vlvf_index); + if (vlan_on) { + /* set the pool bit */ + if (vind < 32) { + bits = rd32(wx, WX_PSR_VLAN_SWC_VM_L); + bits |= (1 << vind); + wr32(wx, WX_PSR_VLAN_SWC_VM_L, bits); + } else { + bits = rd32(wx, WX_PSR_VLAN_SWC_VM_H); + bits |= (1 << (vind - 32)); + wr32(wx, WX_PSR_VLAN_SWC_VM_H, bits); + } + } else { + /* clear the pool bit */ + if (vind < 32) { + bits = rd32(wx, WX_PSR_VLAN_SWC_VM_L); + bits &= ~(1 << vind); + wr32(wx, WX_PSR_VLAN_SWC_VM_L, bits); + bits |= rd32(wx, WX_PSR_VLAN_SWC_VM_H); + } else { + bits = rd32(wx, WX_PSR_VLAN_SWC_VM_H); + bits &= ~(1 << (vind - 32)); + wr32(wx, WX_PSR_VLAN_SWC_VM_H, bits); + bits |= rd32(wx, WX_PSR_VLAN_SWC_VM_L); + } + } + + if (bits) { + wr32(wx, WX_PSR_VLAN_SWC, (WX_PSR_VLAN_SWC_VIEN | vlan)); + if (!vlan_on && vfta_changed) + *vfta_changed = false; + } else { + wr32(wx, WX_PSR_VLAN_SWC, 0); + } + + return 0; +} + +/** + * wx_set_vfta - Set VLAN filter table + * @wx: pointer to hardware structure + * @vlan: VLAN id to write to VLAN filter + * @vind: VMDq output index that maps queue to VLAN id in VFVFB + * @vlan_on: boolean flag to turn on/off VLAN in VFVF + * + * Turn on/off specified VLAN in the VLAN filter table. + **/ +static int wx_set_vfta(struct wx *wx, u32 vlan, u32 vind, bool vlan_on) +{ + u32 bitindex, vfta, targetbit; + bool vfta_changed = false; + int regindex, ret; + + /* this is a 2 part operation - first the VFTA, then the + * VLVF and VLVFB if VT Mode is set + * We don't write the VFTA until we know the VLVF part succeeded. + */ + + /* Part 1 + * The VFTA is a bitstring made up of 128 32-bit registers + * that enable the particular VLAN id, much like the MTA: + * bits[11-5]: which register + * bits[4-0]: which bit in the register + */ + regindex = (vlan >> 5) & 0x7F; + bitindex = vlan & 0x1F; + targetbit = (1 << bitindex); + /* errata 5 */ + vfta = wx->mac.vft_shadow[regindex]; + if (vlan_on) { + if (!(vfta & targetbit)) { + vfta |= targetbit; + vfta_changed = true; + } + } else { + if ((vfta & targetbit)) { + vfta &= ~targetbit; + vfta_changed = true; + } + } + /* Part 2 + * Call wx_set_vlvf to set VLVFB and VLVF + */ + ret = wx_set_vlvf(wx, vlan, vind, vlan_on, &vfta_changed); + if (ret != 0) + return ret; + + if (vfta_changed) + wr32(wx, WX_PSR_VLAN_TBL(regindex), vfta); + wx->mac.vft_shadow[regindex] = vfta; + + return 0; +} + +/** + * wx_clear_vfta - Clear VLAN filter table + * @wx: pointer to hardware structure + * + * Clears the VLAN filer table, and the VMDq index associated with the filter + **/ +static void wx_clear_vfta(struct wx *wx) +{ + u32 offset; + + for (offset = 0; offset < wx->mac.vft_size; offset++) { + wr32(wx, WX_PSR_VLAN_TBL(offset), 0); + wx->mac.vft_shadow[offset] = 0; + } + + for (offset = 0; offset < WX_PSR_VLAN_SWC_ENTRIES; offset++) { + wr32(wx, WX_PSR_VLAN_SWC_IDX, offset); + wr32(wx, WX_PSR_VLAN_SWC, 0); + wr32(wx, WX_PSR_VLAN_SWC_VM_L, 0); + wr32(wx, WX_PSR_VLAN_SWC_VM_H, 0); + } +} + +int wx_vlan_rx_add_vid(struct net_device *netdev, + __be16 proto, u16 vid) +{ + struct wx *wx = netdev_priv(netdev); + + /* add VID to filter table */ + wx_set_vfta(wx, vid, VMDQ_P(0), true); + set_bit(vid, wx->active_vlans); + + return 0; +} +EXPORT_SYMBOL(wx_vlan_rx_add_vid); + +int wx_vlan_rx_kill_vid(struct net_device *netdev, __be16 proto, u16 vid) +{ + struct wx *wx = netdev_priv(netdev); + + /* remove VID from filter table */ + if (vid) + wx_set_vfta(wx, vid, VMDQ_P(0), false); + clear_bit(vid, wx->active_vlans); + + return 0; +} +EXPORT_SYMBOL(wx_vlan_rx_kill_vid); + +/** + * wx_start_hw - Prepare hardware for Tx/Rx + * @wx: pointer to hardware structure + * + * Starts the hardware using the generic start_hw function + * and the generation start_hw function. + * Then performs revision-specific operations, if any. + **/ +void wx_start_hw(struct wx *wx) +{ + int i; + + /* Clear the VLAN filter table */ + wx_clear_vfta(wx); + WX_WRITE_FLUSH(wx); + /* Clear the rate limiters */ + for (i = 0; i < wx->mac.max_tx_queues; i++) { + wr32(wx, WX_TDM_RP_IDX, i); + wr32(wx, WX_TDM_RP_RATE, 0); + } +} +EXPORT_SYMBOL(wx_start_hw); + MODULE_LICENSE("GPL"); diff --git a/drivers/net/ethernet/wangxun/libwx/wx_hw.h b/drivers/net/ethernet/wangxun/libwx/wx_hw.h index c173c56f0ab5d2f28aa14fb2db7fe1e039c714c1..1f93ca32c92125b695860b20a4414d7e81331f21 100644 --- a/drivers/net/ethernet/wangxun/libwx/wx_hw.h +++ b/drivers/net/ethernet/wangxun/libwx/wx_hw.h @@ -26,10 +26,13 @@ void wx_set_rx_mode(struct net_device *netdev); int wx_change_mtu(struct net_device *netdev, int new_mtu); void wx_disable_rx_queue(struct wx *wx, struct wx_ring *ring); void wx_configure(struct wx *wx); +void wx_start_hw(struct wx *wx); int wx_disable_pcie_master(struct wx *wx); int wx_stop_adapter(struct wx *wx); void wx_reset_misc(struct wx *wx); int wx_get_pcie_msix_counts(struct wx *wx, u16 *msix_count, u16 max_msix_count); int wx_sw_init(struct wx *wx); +int wx_vlan_rx_add_vid(struct net_device *netdev, __be16 proto, u16 vid); +int wx_vlan_rx_kill_vid(struct net_device *netdev, __be16 proto, u16 vid); #endif /* _WX_HW_H_ */ diff --git a/drivers/net/ethernet/wangxun/libwx/wx_lib.c b/drivers/net/ethernet/wangxun/libwx/wx_lib.c index 1e8d8b7b0c62e2b1c38a39e97d0e8488b09f5ec6..2c3f08be8c37432b569834152064c56d2a138a5c 100644 --- a/drivers/net/ethernet/wangxun/libwx/wx_lib.c +++ b/drivers/net/ethernet/wangxun/libwx/wx_lib.c @@ -2,14 +2,157 @@ /* Copyright (c) 2019 - 2022 Beijing WangXun Technology Co., Ltd. */ #include +#include #include +#include #include +#include #include +#include +#include #include "wx_type.h" #include "wx_lib.h" #include "wx_hw.h" +/* Lookup table mapping the HW PTYPE to the bit field for decoding */ +static struct wx_dec_ptype wx_ptype_lookup[256] = { + /* L2: mac */ + [0x11] = WX_PTT(L2, NONE, NONE, NONE, NONE, PAY2), + [0x12] = WX_PTT(L2, NONE, NONE, NONE, TS, PAY2), + [0x13] = WX_PTT(L2, NONE, NONE, NONE, NONE, PAY2), + [0x14] = WX_PTT(L2, NONE, NONE, NONE, NONE, PAY2), + [0x15] = WX_PTT(L2, NONE, NONE, NONE, NONE, NONE), + [0x16] = WX_PTT(L2, NONE, NONE, NONE, NONE, PAY2), + [0x17] = WX_PTT(L2, NONE, NONE, NONE, NONE, NONE), + + /* L2: ethertype filter */ + [0x18 ... 0x1F] = WX_PTT(L2, NONE, NONE, NONE, NONE, NONE), + + /* L3: ip non-tunnel */ + [0x21] = WX_PTT(IP, FGV4, NONE, NONE, NONE, PAY3), + [0x22] = WX_PTT(IP, IPV4, NONE, NONE, NONE, PAY3), + [0x23] = WX_PTT(IP, IPV4, NONE, NONE, UDP, PAY4), + [0x24] = WX_PTT(IP, IPV4, NONE, NONE, TCP, PAY4), + [0x25] = WX_PTT(IP, IPV4, NONE, NONE, SCTP, PAY4), + [0x29] = WX_PTT(IP, FGV6, NONE, NONE, NONE, PAY3), + [0x2A] = WX_PTT(IP, IPV6, NONE, NONE, NONE, PAY3), + [0x2B] = WX_PTT(IP, IPV6, NONE, NONE, UDP, PAY3), + [0x2C] = WX_PTT(IP, IPV6, NONE, NONE, TCP, PAY4), + [0x2D] = WX_PTT(IP, IPV6, NONE, NONE, SCTP, PAY4), + + /* L2: fcoe */ + [0x30 ... 0x34] = WX_PTT(FCOE, NONE, NONE, NONE, NONE, PAY3), + [0x38 ... 0x3C] = WX_PTT(FCOE, NONE, NONE, NONE, NONE, PAY3), + + /* IPv4 --> IPv4/IPv6 */ + [0x81] = WX_PTT(IP, IPV4, IPIP, FGV4, NONE, PAY3), + [0x82] = WX_PTT(IP, IPV4, IPIP, IPV4, NONE, PAY3), + [0x83] = WX_PTT(IP, IPV4, IPIP, IPV4, UDP, PAY4), + [0x84] = WX_PTT(IP, IPV4, IPIP, IPV4, TCP, PAY4), + [0x85] = WX_PTT(IP, IPV4, IPIP, IPV4, SCTP, PAY4), + [0x89] = WX_PTT(IP, IPV4, IPIP, FGV6, NONE, PAY3), + [0x8A] = WX_PTT(IP, IPV4, IPIP, IPV6, NONE, PAY3), + [0x8B] = WX_PTT(IP, IPV4, IPIP, IPV6, UDP, PAY4), + [0x8C] = WX_PTT(IP, IPV4, IPIP, IPV6, TCP, PAY4), + [0x8D] = WX_PTT(IP, IPV4, IPIP, IPV6, SCTP, PAY4), + + /* IPv4 --> GRE/NAT --> NONE/IPv4/IPv6 */ + [0x90] = WX_PTT(IP, IPV4, IG, NONE, NONE, PAY3), + [0x91] = WX_PTT(IP, IPV4, IG, FGV4, NONE, PAY3), + [0x92] = WX_PTT(IP, IPV4, IG, IPV4, NONE, PAY3), + [0x93] = WX_PTT(IP, IPV4, IG, IPV4, UDP, PAY4), + [0x94] = WX_PTT(IP, IPV4, IG, IPV4, TCP, PAY4), + [0x95] = WX_PTT(IP, IPV4, IG, IPV4, SCTP, PAY4), + [0x99] = WX_PTT(IP, IPV4, IG, FGV6, NONE, PAY3), + [0x9A] = WX_PTT(IP, IPV4, IG, IPV6, NONE, PAY3), + [0x9B] = WX_PTT(IP, IPV4, IG, IPV6, UDP, PAY4), + [0x9C] = WX_PTT(IP, IPV4, IG, IPV6, TCP, PAY4), + [0x9D] = WX_PTT(IP, IPV4, IG, IPV6, SCTP, PAY4), + + /* IPv4 --> GRE/NAT --> MAC --> NONE/IPv4/IPv6 */ + [0xA0] = WX_PTT(IP, IPV4, IGM, NONE, NONE, PAY3), + [0xA1] = WX_PTT(IP, IPV4, IGM, FGV4, NONE, PAY3), + [0xA2] = WX_PTT(IP, IPV4, IGM, IPV4, NONE, PAY3), + [0xA3] = WX_PTT(IP, IPV4, IGM, IPV4, UDP, PAY4), + [0xA4] = WX_PTT(IP, IPV4, IGM, IPV4, TCP, PAY4), + [0xA5] = WX_PTT(IP, IPV4, IGM, IPV4, SCTP, PAY4), + [0xA9] = WX_PTT(IP, IPV4, IGM, FGV6, NONE, PAY3), + [0xAA] = WX_PTT(IP, IPV4, IGM, IPV6, NONE, PAY3), + [0xAB] = WX_PTT(IP, IPV4, IGM, IPV6, UDP, PAY4), + [0xAC] = WX_PTT(IP, IPV4, IGM, IPV6, TCP, PAY4), + [0xAD] = WX_PTT(IP, IPV4, IGM, IPV6, SCTP, PAY4), + + /* IPv4 --> GRE/NAT --> MAC+VLAN --> NONE/IPv4/IPv6 */ + [0xB0] = WX_PTT(IP, IPV4, IGMV, NONE, NONE, PAY3), + [0xB1] = WX_PTT(IP, IPV4, IGMV, FGV4, NONE, PAY3), + [0xB2] = WX_PTT(IP, IPV4, IGMV, IPV4, NONE, PAY3), + [0xB3] = WX_PTT(IP, IPV4, IGMV, IPV4, UDP, PAY4), + [0xB4] = WX_PTT(IP, IPV4, IGMV, IPV4, TCP, PAY4), + [0xB5] = WX_PTT(IP, IPV4, IGMV, IPV4, SCTP, PAY4), + [0xB9] = WX_PTT(IP, IPV4, IGMV, FGV6, NONE, PAY3), + [0xBA] = WX_PTT(IP, IPV4, IGMV, IPV6, NONE, PAY3), + [0xBB] = WX_PTT(IP, IPV4, IGMV, IPV6, UDP, PAY4), + [0xBC] = WX_PTT(IP, IPV4, IGMV, IPV6, TCP, PAY4), + [0xBD] = WX_PTT(IP, IPV4, IGMV, IPV6, SCTP, PAY4), + + /* IPv6 --> IPv4/IPv6 */ + [0xC1] = WX_PTT(IP, IPV6, IPIP, FGV4, NONE, PAY3), + [0xC2] = WX_PTT(IP, IPV6, IPIP, IPV4, NONE, PAY3), + [0xC3] = WX_PTT(IP, IPV6, IPIP, IPV4, UDP, PAY4), + [0xC4] = WX_PTT(IP, IPV6, IPIP, IPV4, TCP, PAY4), + [0xC5] = WX_PTT(IP, IPV6, IPIP, IPV4, SCTP, PAY4), + [0xC9] = WX_PTT(IP, IPV6, IPIP, FGV6, NONE, PAY3), + [0xCA] = WX_PTT(IP, IPV6, IPIP, IPV6, NONE, PAY3), + [0xCB] = WX_PTT(IP, IPV6, IPIP, IPV6, UDP, PAY4), + [0xCC] = WX_PTT(IP, IPV6, IPIP, IPV6, TCP, PAY4), + [0xCD] = WX_PTT(IP, IPV6, IPIP, IPV6, SCTP, PAY4), + + /* IPv6 --> GRE/NAT -> NONE/IPv4/IPv6 */ + [0xD0] = WX_PTT(IP, IPV6, IG, NONE, NONE, PAY3), + [0xD1] = WX_PTT(IP, IPV6, IG, FGV4, NONE, PAY3), + [0xD2] = WX_PTT(IP, IPV6, IG, IPV4, NONE, PAY3), + [0xD3] = WX_PTT(IP, IPV6, IG, IPV4, UDP, PAY4), + [0xD4] = WX_PTT(IP, IPV6, IG, IPV4, TCP, PAY4), + [0xD5] = WX_PTT(IP, IPV6, IG, IPV4, SCTP, PAY4), + [0xD9] = WX_PTT(IP, IPV6, IG, FGV6, NONE, PAY3), + [0xDA] = WX_PTT(IP, IPV6, IG, IPV6, NONE, PAY3), + [0xDB] = WX_PTT(IP, IPV6, IG, IPV6, UDP, PAY4), + [0xDC] = WX_PTT(IP, IPV6, IG, IPV6, TCP, PAY4), + [0xDD] = WX_PTT(IP, IPV6, IG, IPV6, SCTP, PAY4), + + /* IPv6 --> GRE/NAT -> MAC -> NONE/IPv4/IPv6 */ + [0xE0] = WX_PTT(IP, IPV6, IGM, NONE, NONE, PAY3), + [0xE1] = WX_PTT(IP, IPV6, IGM, FGV4, NONE, PAY3), + [0xE2] = WX_PTT(IP, IPV6, IGM, IPV4, NONE, PAY3), + [0xE3] = WX_PTT(IP, IPV6, IGM, IPV4, UDP, PAY4), + [0xE4] = WX_PTT(IP, IPV6, IGM, IPV4, TCP, PAY4), + [0xE5] = WX_PTT(IP, IPV6, IGM, IPV4, SCTP, PAY4), + [0xE9] = WX_PTT(IP, IPV6, IGM, FGV6, NONE, PAY3), + [0xEA] = WX_PTT(IP, IPV6, IGM, IPV6, NONE, PAY3), + [0xEB] = WX_PTT(IP, IPV6, IGM, IPV6, UDP, PAY4), + [0xEC] = WX_PTT(IP, IPV6, IGM, IPV6, TCP, PAY4), + [0xED] = WX_PTT(IP, IPV6, IGM, IPV6, SCTP, PAY4), + + /* IPv6 --> GRE/NAT -> MAC--> NONE/IPv */ + [0xF0] = WX_PTT(IP, IPV6, IGMV, NONE, NONE, PAY3), + [0xF1] = WX_PTT(IP, IPV6, IGMV, FGV4, NONE, PAY3), + [0xF2] = WX_PTT(IP, IPV6, IGMV, IPV4, NONE, PAY3), + [0xF3] = WX_PTT(IP, IPV6, IGMV, IPV4, UDP, PAY4), + [0xF4] = WX_PTT(IP, IPV6, IGMV, IPV4, TCP, PAY4), + [0xF5] = WX_PTT(IP, IPV6, IGMV, IPV4, SCTP, PAY4), + [0xF9] = WX_PTT(IP, IPV6, IGMV, FGV6, NONE, PAY3), + [0xFA] = WX_PTT(IP, IPV6, IGMV, IPV6, NONE, PAY3), + [0xFB] = WX_PTT(IP, IPV6, IGMV, IPV6, UDP, PAY4), + [0xFC] = WX_PTT(IP, IPV6, IGMV, IPV6, TCP, PAY4), + [0xFD] = WX_PTT(IP, IPV6, IGMV, IPV6, SCTP, PAY4), +}; + +static struct wx_dec_ptype wx_decode_ptype(const u8 ptype) +{ + return wx_ptype_lookup[ptype]; +} + /* wx_test_staterr - tests bits in Rx descriptor status and error fields */ static __le32 wx_test_staterr(union wx_rx_desc *rx_desc, const u32 stat_err_bits) @@ -419,6 +562,116 @@ static bool wx_cleanup_headers(struct wx_ring *rx_ring, return false; } +static void wx_rx_hash(struct wx_ring *ring, + union wx_rx_desc *rx_desc, + struct sk_buff *skb) +{ + u16 rss_type; + + if (!(ring->netdev->features & NETIF_F_RXHASH)) + return; + + rss_type = le16_to_cpu(rx_desc->wb.lower.lo_dword.hs_rss.pkt_info) & + WX_RXD_RSSTYPE_MASK; + + if (!rss_type) + return; + + skb_set_hash(skb, le32_to_cpu(rx_desc->wb.lower.hi_dword.rss), + (WX_RSS_L4_TYPES_MASK & (1ul << rss_type)) ? + PKT_HASH_TYPE_L4 : PKT_HASH_TYPE_L3); +} + +/** + * wx_rx_checksum - indicate in skb if hw indicated a good cksum + * @ring: structure containing ring specific data + * @rx_desc: current Rx descriptor being processed + * @skb: skb currently being received and modified + **/ +static void wx_rx_checksum(struct wx_ring *ring, + union wx_rx_desc *rx_desc, + struct sk_buff *skb) +{ + struct wx_dec_ptype dptype = wx_decode_ptype(WX_RXD_PKTTYPE(rx_desc)); + + skb_checksum_none_assert(skb); + /* Rx csum disabled */ + if (!(ring->netdev->features & NETIF_F_RXCSUM)) + return; + + /* if IPv4 header checksum error */ + if ((wx_test_staterr(rx_desc, WX_RXD_STAT_IPCS) && + wx_test_staterr(rx_desc, WX_RXD_ERR_IPE)) || + (wx_test_staterr(rx_desc, WX_RXD_STAT_OUTERIPCS) && + wx_test_staterr(rx_desc, WX_RXD_ERR_OUTERIPER))) { + ring->rx_stats.csum_err++; + return; + } + + /* L4 checksum offload flag must set for the below code to work */ + if (!wx_test_staterr(rx_desc, WX_RXD_STAT_L4CS)) + return; + + /* Hardware can't guarantee csum if IPv6 Dest Header found */ + if (dptype.prot != WX_DEC_PTYPE_PROT_SCTP && WX_RXD_IPV6EX(rx_desc)) + return; + + /* if L4 checksum error */ + if (wx_test_staterr(rx_desc, WX_RXD_ERR_TCPE)) { + ring->rx_stats.csum_err++; + return; + } + + /* It must be a TCP or UDP or SCTP packet with a valid checksum */ + skb->ip_summed = CHECKSUM_UNNECESSARY; + + /* If there is an outer header present that might contain a checksum + * we need to bump the checksum level by 1 to reflect the fact that + * we are indicating we validated the inner checksum. + */ + if (dptype.etype >= WX_DEC_PTYPE_ETYPE_IG) + __skb_incr_checksum_unnecessary(skb); + ring->rx_stats.csum_good_cnt++; +} + +static void wx_rx_vlan(struct wx_ring *ring, union wx_rx_desc *rx_desc, + struct sk_buff *skb) +{ + u16 ethertype; + u8 idx = 0; + + if ((ring->netdev->features & + (NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_STAG_RX)) && + wx_test_staterr(rx_desc, WX_RXD_STAT_VP)) { + idx = (le16_to_cpu(rx_desc->wb.lower.lo_dword.hs_rss.pkt_info) & + 0x1c0) >> 6; + ethertype = ring->q_vector->wx->tpid[idx]; + __vlan_hwaccel_put_tag(skb, htons(ethertype), + le16_to_cpu(rx_desc->wb.upper.vlan)); + } +} + +/** + * wx_process_skb_fields - Populate skb header fields from Rx descriptor + * @rx_ring: rx descriptor ring packet is being transacted on + * @rx_desc: pointer to the EOP Rx descriptor + * @skb: pointer to current skb being populated + * + * This function checks the ring, descriptor, and packet information in + * order to populate the hash, checksum, protocol, and + * other fields within the skb. + **/ +static void wx_process_skb_fields(struct wx_ring *rx_ring, + union wx_rx_desc *rx_desc, + struct sk_buff *skb) +{ + wx_rx_hash(rx_ring, rx_desc, skb); + wx_rx_checksum(rx_ring, rx_desc, skb); + wx_rx_vlan(rx_ring, rx_desc, skb); + skb_record_rx_queue(skb, rx_ring->queue_index); + skb->protocol = eth_type_trans(skb, rx_ring->netdev); +} + /** * wx_clean_rx_irq - Clean completed descriptors from Rx ring - bounce buf * @q_vector: structure containing interrupt and ring information @@ -486,8 +739,8 @@ static int wx_clean_rx_irq(struct wx_q_vector *q_vector, /* probably a little skewed due to removing CRC */ total_rx_bytes += skb->len; - skb_record_rx_queue(skb, rx_ring->queue_index); - skb->protocol = eth_type_trans(skb, rx_ring->netdev); + /* populate checksum, timestamp, VLAN, and protocol */ + wx_process_skb_fields(rx_ring, rx_desc, skb); napi_gro_receive(&q_vector->napi, skb); /* update budget accounting */ @@ -707,11 +960,50 @@ static int wx_maybe_stop_tx(struct wx_ring *tx_ring, u16 size) return 0; } +static u32 wx_tx_cmd_type(u32 tx_flags) +{ + /* set type for advanced descriptor with frame checksum insertion */ + u32 cmd_type = WX_TXD_DTYP_DATA | WX_TXD_IFCS; + + /* set HW vlan bit if vlan is present */ + cmd_type |= WX_SET_FLAG(tx_flags, WX_TX_FLAGS_HW_VLAN, WX_TXD_VLE); + /* set segmentation enable bits for TSO/FSO */ + cmd_type |= WX_SET_FLAG(tx_flags, WX_TX_FLAGS_TSO, WX_TXD_TSE); + /* set timestamp bit if present */ + cmd_type |= WX_SET_FLAG(tx_flags, WX_TX_FLAGS_TSTAMP, WX_TXD_MAC_TSTAMP); + cmd_type |= WX_SET_FLAG(tx_flags, WX_TX_FLAGS_LINKSEC, WX_TXD_LINKSEC); + + return cmd_type; +} + +static void wx_tx_olinfo_status(union wx_tx_desc *tx_desc, + u32 tx_flags, unsigned int paylen) +{ + u32 olinfo_status = paylen << WX_TXD_PAYLEN_SHIFT; + + /* enable L4 checksum for TSO and TX checksum offload */ + olinfo_status |= WX_SET_FLAG(tx_flags, WX_TX_FLAGS_CSUM, WX_TXD_L4CS); + /* enable IPv4 checksum for TSO */ + olinfo_status |= WX_SET_FLAG(tx_flags, WX_TX_FLAGS_IPV4, WX_TXD_IIPCS); + /* enable outer IPv4 checksum for TSO */ + olinfo_status |= WX_SET_FLAG(tx_flags, WX_TX_FLAGS_OUTER_IPV4, + WX_TXD_EIPCS); + /* Check Context must be set if Tx switch is enabled, which it + * always is for case where virtual functions are running + */ + olinfo_status |= WX_SET_FLAG(tx_flags, WX_TX_FLAGS_CC, WX_TXD_CC); + olinfo_status |= WX_SET_FLAG(tx_flags, WX_TX_FLAGS_IPSEC, + WX_TXD_IPSEC); + tx_desc->read.olinfo_status = cpu_to_le32(olinfo_status); +} + static void wx_tx_map(struct wx_ring *tx_ring, - struct wx_tx_buffer *first) + struct wx_tx_buffer *first, + const u8 hdr_len) { struct sk_buff *skb = first->skb; struct wx_tx_buffer *tx_buffer; + u32 tx_flags = first->tx_flags; u16 i = tx_ring->next_to_use; unsigned int data_len, size; union wx_tx_desc *tx_desc; @@ -719,10 +1011,9 @@ static void wx_tx_map(struct wx_ring *tx_ring, dma_addr_t dma; u32 cmd_type; - cmd_type = WX_TXD_DTYP_DATA | WX_TXD_IFCS; + cmd_type = wx_tx_cmd_type(tx_flags); tx_desc = WX_TX_DESC(tx_ring, i); - - tx_desc->read.olinfo_status = cpu_to_le32(skb->len << WX_TXD_PAYLEN_SHIFT); + wx_tx_olinfo_status(tx_desc, tx_flags, skb->len - hdr_len); size = skb_headlen(skb); data_len = skb->data_len; @@ -838,12 +1129,399 @@ static void wx_tx_map(struct wx_ring *tx_ring, tx_ring->next_to_use = i; } +static void wx_tx_ctxtdesc(struct wx_ring *tx_ring, u32 vlan_macip_lens, + u32 fcoe_sof_eof, u32 type_tucmd, u32 mss_l4len_idx) +{ + struct wx_tx_context_desc *context_desc; + u16 i = tx_ring->next_to_use; + + context_desc = WX_TX_CTXTDESC(tx_ring, i); + i++; + tx_ring->next_to_use = (i < tx_ring->count) ? i : 0; + + /* set bits to identify this as an advanced context descriptor */ + type_tucmd |= WX_TXD_DTYP_CTXT; + context_desc->vlan_macip_lens = cpu_to_le32(vlan_macip_lens); + context_desc->seqnum_seed = cpu_to_le32(fcoe_sof_eof); + context_desc->type_tucmd_mlhl = cpu_to_le32(type_tucmd); + context_desc->mss_l4len_idx = cpu_to_le32(mss_l4len_idx); +} + +static void wx_get_ipv6_proto(struct sk_buff *skb, int offset, u8 *nexthdr) +{ + struct ipv6hdr *hdr = (struct ipv6hdr *)(skb->data + offset); + + *nexthdr = hdr->nexthdr; + offset += sizeof(struct ipv6hdr); + while (ipv6_ext_hdr(*nexthdr)) { + struct ipv6_opt_hdr _hdr, *hp; + + if (*nexthdr == NEXTHDR_NONE) + return; + hp = skb_header_pointer(skb, offset, sizeof(_hdr), &_hdr); + if (!hp) + return; + if (*nexthdr == NEXTHDR_FRAGMENT) + break; + *nexthdr = hp->nexthdr; + } +} + +union network_header { + struct iphdr *ipv4; + struct ipv6hdr *ipv6; + void *raw; +}; + +static u8 wx_encode_tx_desc_ptype(const struct wx_tx_buffer *first) +{ + u8 tun_prot = 0, l4_prot = 0, ptype = 0; + struct sk_buff *skb = first->skb; + + if (skb->encapsulation) { + union network_header hdr; + + switch (first->protocol) { + case htons(ETH_P_IP): + tun_prot = ip_hdr(skb)->protocol; + ptype = WX_PTYPE_TUN_IPV4; + break; + case htons(ETH_P_IPV6): + wx_get_ipv6_proto(skb, skb_network_offset(skb), &tun_prot); + ptype = WX_PTYPE_TUN_IPV6; + break; + default: + return ptype; + } + + if (tun_prot == IPPROTO_IPIP) { + hdr.raw = (void *)inner_ip_hdr(skb); + ptype |= WX_PTYPE_PKT_IPIP; + } else if (tun_prot == IPPROTO_UDP) { + hdr.raw = (void *)inner_ip_hdr(skb); + if (skb->inner_protocol_type != ENCAP_TYPE_ETHER || + skb->inner_protocol != htons(ETH_P_TEB)) { + ptype |= WX_PTYPE_PKT_IG; + } else { + if (((struct ethhdr *)skb_inner_mac_header(skb))->h_proto + == htons(ETH_P_8021Q)) + ptype |= WX_PTYPE_PKT_IGMV; + else + ptype |= WX_PTYPE_PKT_IGM; + } + + } else if (tun_prot == IPPROTO_GRE) { + hdr.raw = (void *)inner_ip_hdr(skb); + if (skb->inner_protocol == htons(ETH_P_IP) || + skb->inner_protocol == htons(ETH_P_IPV6)) { + ptype |= WX_PTYPE_PKT_IG; + } else { + if (((struct ethhdr *)skb_inner_mac_header(skb))->h_proto + == htons(ETH_P_8021Q)) + ptype |= WX_PTYPE_PKT_IGMV; + else + ptype |= WX_PTYPE_PKT_IGM; + } + } else { + return ptype; + } + + switch (hdr.ipv4->version) { + case IPVERSION: + l4_prot = hdr.ipv4->protocol; + break; + case 6: + wx_get_ipv6_proto(skb, skb_inner_network_offset(skb), &l4_prot); + ptype |= WX_PTYPE_PKT_IPV6; + break; + default: + return ptype; + } + } else { + switch (first->protocol) { + case htons(ETH_P_IP): + l4_prot = ip_hdr(skb)->protocol; + ptype = WX_PTYPE_PKT_IP; + break; + case htons(ETH_P_IPV6): + wx_get_ipv6_proto(skb, skb_network_offset(skb), &l4_prot); + ptype = WX_PTYPE_PKT_IP | WX_PTYPE_PKT_IPV6; + break; + default: + return WX_PTYPE_PKT_MAC | WX_PTYPE_TYP_MAC; + } + } + switch (l4_prot) { + case IPPROTO_TCP: + ptype |= WX_PTYPE_TYP_TCP; + break; + case IPPROTO_UDP: + ptype |= WX_PTYPE_TYP_UDP; + break; + case IPPROTO_SCTP: + ptype |= WX_PTYPE_TYP_SCTP; + break; + default: + ptype |= WX_PTYPE_TYP_IP; + break; + } + + return ptype; +} + +static int wx_tso(struct wx_ring *tx_ring, struct wx_tx_buffer *first, + u8 *hdr_len, u8 ptype) +{ + u32 vlan_macip_lens, type_tucmd, mss_l4len_idx; + struct net_device *netdev = tx_ring->netdev; + u32 l4len, tunhdr_eiplen_tunlen = 0; + struct sk_buff *skb = first->skb; + bool enc = skb->encapsulation; + struct ipv6hdr *ipv6h; + struct tcphdr *tcph; + struct iphdr *iph; + u8 tun_prot = 0; + int err; + + if (skb->ip_summed != CHECKSUM_PARTIAL) + return 0; + + if (!skb_is_gso(skb)) + return 0; + + err = skb_cow_head(skb, 0); + if (err < 0) + return err; + + /* indicates the inner headers in the skbuff are valid. */ + iph = enc ? inner_ip_hdr(skb) : ip_hdr(skb); + if (iph->version == 4) { + tcph = enc ? inner_tcp_hdr(skb) : tcp_hdr(skb); + iph->tot_len = 0; + iph->check = 0; + tcph->check = ~csum_tcpudp_magic(iph->saddr, + iph->daddr, 0, + IPPROTO_TCP, 0); + first->tx_flags |= WX_TX_FLAGS_TSO | + WX_TX_FLAGS_CSUM | + WX_TX_FLAGS_IPV4 | + WX_TX_FLAGS_CC; + } else if (iph->version == 6 && skb_is_gso_v6(skb)) { + ipv6h = enc ? inner_ipv6_hdr(skb) : ipv6_hdr(skb); + tcph = enc ? inner_tcp_hdr(skb) : tcp_hdr(skb); + ipv6h->payload_len = 0; + tcph->check = ~csum_ipv6_magic(&ipv6h->saddr, + &ipv6h->daddr, 0, + IPPROTO_TCP, 0); + first->tx_flags |= WX_TX_FLAGS_TSO | + WX_TX_FLAGS_CSUM | + WX_TX_FLAGS_CC; + } + + /* compute header lengths */ + l4len = enc ? inner_tcp_hdrlen(skb) : tcp_hdrlen(skb); + *hdr_len = enc ? (skb_inner_transport_header(skb) - skb->data) : + skb_transport_offset(skb); + *hdr_len += l4len; + + /* update gso size and bytecount with header size */ + first->gso_segs = skb_shinfo(skb)->gso_segs; + first->bytecount += (first->gso_segs - 1) * *hdr_len; + + /* mss_l4len_id: use 0 as index for TSO */ + mss_l4len_idx = l4len << WX_TXD_L4LEN_SHIFT; + mss_l4len_idx |= skb_shinfo(skb)->gso_size << WX_TXD_MSS_SHIFT; + + /* vlan_macip_lens: HEADLEN, MACLEN, VLAN tag */ + if (enc) { + switch (first->protocol) { + case htons(ETH_P_IP): + tun_prot = ip_hdr(skb)->protocol; + first->tx_flags |= WX_TX_FLAGS_OUTER_IPV4; + break; + case htons(ETH_P_IPV6): + tun_prot = ipv6_hdr(skb)->nexthdr; + break; + default: + break; + } + switch (tun_prot) { + case IPPROTO_UDP: + tunhdr_eiplen_tunlen = WX_TXD_TUNNEL_UDP; + tunhdr_eiplen_tunlen |= ((skb_network_header_len(skb) >> 2) << + WX_TXD_OUTER_IPLEN_SHIFT) | + (((skb_inner_mac_header(skb) - + skb_transport_header(skb)) >> 1) << + WX_TXD_TUNNEL_LEN_SHIFT); + break; + case IPPROTO_GRE: + tunhdr_eiplen_tunlen = WX_TXD_TUNNEL_GRE; + tunhdr_eiplen_tunlen |= ((skb_network_header_len(skb) >> 2) << + WX_TXD_OUTER_IPLEN_SHIFT) | + (((skb_inner_mac_header(skb) - + skb_transport_header(skb)) >> 1) << + WX_TXD_TUNNEL_LEN_SHIFT); + break; + case IPPROTO_IPIP: + tunhdr_eiplen_tunlen = (((char *)inner_ip_hdr(skb) - + (char *)ip_hdr(skb)) >> 2) << + WX_TXD_OUTER_IPLEN_SHIFT; + break; + default: + break; + } + vlan_macip_lens = skb_inner_network_header_len(skb) >> 1; + } else { + vlan_macip_lens = skb_network_header_len(skb) >> 1; + } + + vlan_macip_lens |= skb_network_offset(skb) << WX_TXD_MACLEN_SHIFT; + vlan_macip_lens |= first->tx_flags & WX_TX_FLAGS_VLAN_MASK; + + type_tucmd = ptype << 24; + if (skb->vlan_proto == htons(ETH_P_8021AD) && + netdev->features & NETIF_F_HW_VLAN_STAG_TX) + type_tucmd |= WX_SET_FLAG(first->tx_flags, + WX_TX_FLAGS_HW_VLAN, + 0x1 << WX_TXD_TAG_TPID_SEL_SHIFT); + wx_tx_ctxtdesc(tx_ring, vlan_macip_lens, tunhdr_eiplen_tunlen, + type_tucmd, mss_l4len_idx); + + return 1; +} + +static void wx_tx_csum(struct wx_ring *tx_ring, struct wx_tx_buffer *first, + u8 ptype) +{ + u32 tunhdr_eiplen_tunlen = 0, vlan_macip_lens = 0; + struct net_device *netdev = tx_ring->netdev; + u32 mss_l4len_idx = 0, type_tucmd; + struct sk_buff *skb = first->skb; + u8 tun_prot = 0; + + if (skb->ip_summed != CHECKSUM_PARTIAL) { + if (!(first->tx_flags & WX_TX_FLAGS_HW_VLAN) && + !(first->tx_flags & WX_TX_FLAGS_CC)) + return; + vlan_macip_lens = skb_network_offset(skb) << + WX_TXD_MACLEN_SHIFT; + } else { + u8 l4_prot = 0; + union { + struct iphdr *ipv4; + struct ipv6hdr *ipv6; + u8 *raw; + } network_hdr; + union { + struct tcphdr *tcphdr; + u8 *raw; + } transport_hdr; + + if (skb->encapsulation) { + network_hdr.raw = skb_inner_network_header(skb); + transport_hdr.raw = skb_inner_transport_header(skb); + vlan_macip_lens = skb_network_offset(skb) << + WX_TXD_MACLEN_SHIFT; + switch (first->protocol) { + case htons(ETH_P_IP): + tun_prot = ip_hdr(skb)->protocol; + break; + case htons(ETH_P_IPV6): + tun_prot = ipv6_hdr(skb)->nexthdr; + break; + default: + return; + } + switch (tun_prot) { + case IPPROTO_UDP: + tunhdr_eiplen_tunlen = WX_TXD_TUNNEL_UDP; + tunhdr_eiplen_tunlen |= + ((skb_network_header_len(skb) >> 2) << + WX_TXD_OUTER_IPLEN_SHIFT) | + (((skb_inner_mac_header(skb) - + skb_transport_header(skb)) >> 1) << + WX_TXD_TUNNEL_LEN_SHIFT); + break; + case IPPROTO_GRE: + tunhdr_eiplen_tunlen = WX_TXD_TUNNEL_GRE; + tunhdr_eiplen_tunlen |= ((skb_network_header_len(skb) >> 2) << + WX_TXD_OUTER_IPLEN_SHIFT) | + (((skb_inner_mac_header(skb) - + skb_transport_header(skb)) >> 1) << + WX_TXD_TUNNEL_LEN_SHIFT); + break; + case IPPROTO_IPIP: + tunhdr_eiplen_tunlen = (((char *)inner_ip_hdr(skb) - + (char *)ip_hdr(skb)) >> 2) << + WX_TXD_OUTER_IPLEN_SHIFT; + break; + default: + break; + } + + } else { + network_hdr.raw = skb_network_header(skb); + transport_hdr.raw = skb_transport_header(skb); + vlan_macip_lens = skb_network_offset(skb) << + WX_TXD_MACLEN_SHIFT; + } + + switch (network_hdr.ipv4->version) { + case IPVERSION: + vlan_macip_lens |= (transport_hdr.raw - network_hdr.raw) >> 1; + l4_prot = network_hdr.ipv4->protocol; + break; + case 6: + vlan_macip_lens |= (transport_hdr.raw - network_hdr.raw) >> 1; + l4_prot = network_hdr.ipv6->nexthdr; + break; + default: + break; + } + + switch (l4_prot) { + case IPPROTO_TCP: + mss_l4len_idx = (transport_hdr.tcphdr->doff * 4) << + WX_TXD_L4LEN_SHIFT; + break; + case IPPROTO_SCTP: + mss_l4len_idx = sizeof(struct sctphdr) << + WX_TXD_L4LEN_SHIFT; + break; + case IPPROTO_UDP: + mss_l4len_idx = sizeof(struct udphdr) << + WX_TXD_L4LEN_SHIFT; + break; + default: + break; + } + + /* update TX checksum flag */ + first->tx_flags |= WX_TX_FLAGS_CSUM; + } + first->tx_flags |= WX_TX_FLAGS_CC; + /* vlan_macip_lens: MACLEN, VLAN tag */ + vlan_macip_lens |= first->tx_flags & WX_TX_FLAGS_VLAN_MASK; + + type_tucmd = ptype << 24; + if (skb->vlan_proto == htons(ETH_P_8021AD) && + netdev->features & NETIF_F_HW_VLAN_STAG_TX) + type_tucmd |= WX_SET_FLAG(first->tx_flags, + WX_TX_FLAGS_HW_VLAN, + 0x1 << WX_TXD_TAG_TPID_SEL_SHIFT); + wx_tx_ctxtdesc(tx_ring, vlan_macip_lens, tunhdr_eiplen_tunlen, + type_tucmd, mss_l4len_idx); +} + static netdev_tx_t wx_xmit_frame_ring(struct sk_buff *skb, struct wx_ring *tx_ring) { u16 count = TXD_USE_COUNT(skb_headlen(skb)); struct wx_tx_buffer *first; + u8 hdr_len = 0, ptype; unsigned short f; + u32 tx_flags = 0; + int tso; /* need: 1 descriptor per page * PAGE_SIZE/WX_MAX_DATA_PER_TXD, * + 1 desc for skb_headlen/WX_MAX_DATA_PER_TXD, @@ -864,7 +1542,29 @@ static netdev_tx_t wx_xmit_frame_ring(struct sk_buff *skb, first->bytecount = skb->len; first->gso_segs = 1; - wx_tx_map(tx_ring, first); + /* if we have a HW VLAN tag being added default to the HW one */ + if (skb_vlan_tag_present(skb)) { + tx_flags |= skb_vlan_tag_get(skb) << WX_TX_FLAGS_VLAN_SHIFT; + tx_flags |= WX_TX_FLAGS_HW_VLAN; + } + + /* record initial flags and protocol */ + first->tx_flags = tx_flags; + first->protocol = vlan_get_protocol(skb); + + ptype = wx_encode_tx_desc_ptype(first); + + tso = wx_tso(tx_ring, first, &hdr_len, ptype); + if (tso < 0) + goto out_drop; + else if (!tso) + wx_tx_csum(tx_ring, first, ptype); + wx_tx_map(tx_ring, first, hdr_len); + + return NETDEV_TX_OK; +out_drop: + dev_kfree_skb_any(first->skb); + first->skb = NULL; return NETDEV_TX_OK; } @@ -1348,7 +2048,8 @@ void wx_free_irq(struct wx *wx) free_irq(entry->vector, q_vector); } - free_irq(wx->msix_entries[vector].vector, wx); + if (wx->mac.type == wx_mac_em) + free_irq(wx->msix_entries[vector].vector, wx); } EXPORT_SYMBOL(wx_free_irq); @@ -2004,4 +2705,24 @@ void wx_get_stats64(struct net_device *netdev, } EXPORT_SYMBOL(wx_get_stats64); +int wx_set_features(struct net_device *netdev, netdev_features_t features) +{ + netdev_features_t changed = netdev->features ^ features; + struct wx *wx = netdev_priv(netdev); + + if (changed & NETIF_F_RXHASH) + wr32m(wx, WX_RDB_RA_CTL, WX_RDB_RA_CTL_RSS_EN, + WX_RDB_RA_CTL_RSS_EN); + else + wr32m(wx, WX_RDB_RA_CTL, WX_RDB_RA_CTL_RSS_EN, 0); + + if (changed & + (NETIF_F_HW_VLAN_CTAG_RX | + NETIF_F_HW_VLAN_STAG_RX)) + wx_set_rx_mode(netdev); + + return 1; +} +EXPORT_SYMBOL(wx_set_features); + MODULE_LICENSE("GPL"); diff --git a/drivers/net/ethernet/wangxun/libwx/wx_lib.h b/drivers/net/ethernet/wangxun/libwx/wx_lib.h index 50ee41f1fa10d2e2273ad547259a0a1f5880a674..df1f4a5951f06ccb44e583ac6a3301838e999832 100644 --- a/drivers/net/ethernet/wangxun/libwx/wx_lib.h +++ b/drivers/net/ethernet/wangxun/libwx/wx_lib.h @@ -28,5 +28,6 @@ void wx_free_resources(struct wx *wx); int wx_setup_resources(struct wx *wx); void wx_get_stats64(struct net_device *netdev, struct rtnl_link_stats64 *stats); +int wx_set_features(struct net_device *netdev, netdev_features_t features); #endif /* _NGBE_LIB_H_ */ diff --git a/drivers/net/ethernet/wangxun/libwx/wx_type.h b/drivers/net/ethernet/wangxun/libwx/wx_type.h index 32f952d930097d827fe7a6c9e1a91bec2c2dc808..29dfb561887d3000c3029636331332b698be4d24 100644 --- a/drivers/net/ethernet/wangxun/libwx/wx_type.h +++ b/drivers/net/ethernet/wangxun/libwx/wx_type.h @@ -6,6 +6,8 @@ #include #include +#include +#include #define WX_NCSI_SUP 0x8000 #define WX_NCSI_MASK 0x8000 @@ -64,6 +66,8 @@ #define WX_CFG_PORT_CTL_QINQ BIT(2) #define WX_CFG_PORT_CTL_D_VLAN BIT(0) /* double vlan*/ #define WX_CFG_TAG_TPID(_i) (0x14430 + ((_i) * 4)) +#define WX_CFG_PORT_CTL_NUM_VT_MASK GENMASK(13, 12) /* number of TVs */ + /* GPIO Registers */ #define WX_GPIO_DR 0x14800 @@ -79,7 +83,9 @@ #define WX_GPIO_INTMASK 0x14834 #define WX_GPIO_INTTYPE_LEVEL 0x14838 #define WX_GPIO_POLARITY 0x1483C +#define WX_GPIO_INTSTATUS 0x14844 #define WX_GPIO_EOI 0x1484C +#define WX_GPIO_EXT 0x14850 /*********************** Transmit DMA registers **************************/ /* transmit global control */ @@ -87,6 +93,8 @@ /* TDM CTL BIT */ #define WX_TDM_CTL_TE BIT(0) /* Transmit Enable */ #define WX_TDM_PB_THRE(_i) (0x18020 + ((_i) * 4)) +#define WX_TDM_RP_IDX 0x1820C +#define WX_TDM_RP_RATE 0x18404 /***************************** RDB registers *********************************/ /* receive packet buffer */ @@ -105,6 +113,8 @@ #define WX_RDB_PL_CFG_L2HDR BIT(3) #define WX_RDB_PL_CFG_TUN_TUNHDR BIT(4) #define WX_RDB_PL_CFG_TUN_OUTL2HDR BIT(5) +#define WX_RDB_RA_CTL 0x194F4 +#define WX_RDB_RA_CTL_RSS_EN BIT(2) /* RSS Enable */ /******************************* PSR Registers *******************************/ /* psr control */ @@ -150,6 +160,9 @@ #define WX_PSR_LAN_FLEX_DW_H(_i) (0x15C04 + ((_i) * 16)) #define WX_PSR_LAN_FLEX_MSK(_i) (0x15C08 + ((_i) * 16)) +/* vlan tbl */ +#define WX_PSR_VLAN_TBL(_i) (0x16000 + ((_i) * 4)) + /* mac switcher */ #define WX_PSR_MAC_SWC_AD_L 0x16200 #define WX_PSR_MAC_SWC_AD_H 0x16204 @@ -161,6 +174,15 @@ #define WX_PSR_MAC_SWC_IDX 0x16210 #define WX_CLEAR_VMDQ_ALL 0xFFFFFFFFU +/* vlan switch */ +#define WX_PSR_VLAN_SWC 0x16220 +#define WX_PSR_VLAN_SWC_VM_L 0x16224 +#define WX_PSR_VLAN_SWC_VM_H 0x16228 +#define WX_PSR_VLAN_SWC_IDX 0x16230 /* 64 vlan entries */ +/* VLAN pool filtering masks */ +#define WX_PSR_VLAN_SWC_VIEN BIT(31) /* filter is valid */ +#define WX_PSR_VLAN_SWC_ENTRIES 64 + /********************************* RSEC **************************************/ /* general rsec */ #define WX_RSC_CTL 0x17000 @@ -255,6 +277,7 @@ #define WX_PX_RR_RP(_i) (0x0100C + ((_i) * 0x40)) #define WX_PX_RR_CFG(_i) (0x01010 + ((_i) * 0x40)) /* PX_RR_CFG bit definitions */ +#define WX_PX_RR_CFG_VLAN BIT(31) #define WX_PX_RR_CFG_SPLIT_MODE BIT(26) #define WX_PX_RR_CFG_RR_THER_SHIFT 16 #define WX_PX_RR_CFG_RR_HDR_SZ GENMASK(15, 12) @@ -296,6 +319,7 @@ #define WX_MAX_TXD 8192 #define WX_MAX_JUMBO_FRAME_SIZE 9432 /* max payload 9414 */ +#define VMDQ_P(p) p /* Supported Rx Buffer Sizes */ #define WX_RXBUFFER_256 256 /* Used for skb receive header */ @@ -315,17 +339,64 @@ #define TXD_USE_COUNT(S) DIV_ROUND_UP((S), WX_MAX_DATA_PER_TXD) #define DESC_NEEDED (MAX_SKB_FRAGS + 4) -/* Ether Types */ -#define WX_ETH_P_CNM 0x22E7 - #define WX_CFG_PORT_ST 0x14404 /******************* Receive Descriptor bit definitions **********************/ #define WX_RXD_STAT_DD BIT(0) /* Done */ #define WX_RXD_STAT_EOP BIT(1) /* End of Packet */ +#define WX_RXD_STAT_VP BIT(5) /* IEEE VLAN Pkt */ +#define WX_RXD_STAT_L4CS BIT(7) /* L4 xsum calculated */ +#define WX_RXD_STAT_IPCS BIT(8) /* IP xsum calculated */ +#define WX_RXD_STAT_OUTERIPCS BIT(10) /* Cloud IP xsum calculated*/ +#define WX_RXD_ERR_OUTERIPER BIT(26) /* CRC IP Header error */ #define WX_RXD_ERR_RXE BIT(29) /* Any MAC Error */ - +#define WX_RXD_ERR_TCPE BIT(30) /* TCP/UDP Checksum Error */ +#define WX_RXD_ERR_IPE BIT(31) /* IP Checksum Error */ + +/* RSS Hash results */ +#define WX_RXD_RSSTYPE_MASK GENMASK(3, 0) +#define WX_RXD_RSSTYPE_IPV4_TCP 0x00000001U +#define WX_RXD_RSSTYPE_IPV6_TCP 0x00000003U +#define WX_RXD_RSSTYPE_IPV4_SCTP 0x00000004U +#define WX_RXD_RSSTYPE_IPV6_SCTP 0x00000006U +#define WX_RXD_RSSTYPE_IPV4_UDP 0x00000007U +#define WX_RXD_RSSTYPE_IPV6_UDP 0x00000008U + +#define WX_RSS_L4_TYPES_MASK \ + ((1ul << WX_RXD_RSSTYPE_IPV4_TCP) | \ + (1ul << WX_RXD_RSSTYPE_IPV4_UDP) | \ + (1ul << WX_RXD_RSSTYPE_IPV4_SCTP) | \ + (1ul << WX_RXD_RSSTYPE_IPV6_TCP) | \ + (1ul << WX_RXD_RSSTYPE_IPV6_UDP) | \ + (1ul << WX_RXD_RSSTYPE_IPV6_SCTP)) +/* TUN */ +#define WX_PTYPE_TUN_IPV4 0x80 +#define WX_PTYPE_TUN_IPV6 0xC0 + +/* PKT for TUN */ +#define WX_PTYPE_PKT_IPIP 0x00 /* IP+IP */ +#define WX_PTYPE_PKT_IG 0x10 /* IP+GRE */ +#define WX_PTYPE_PKT_IGM 0x20 /* IP+GRE+MAC */ +#define WX_PTYPE_PKT_IGMV 0x30 /* IP+GRE+MAC+VLAN */ +/* PKT for !TUN */ +#define WX_PTYPE_PKT_MAC 0x10 +#define WX_PTYPE_PKT_IP 0x20 + +/* TYP for PKT=mac */ +#define WX_PTYPE_TYP_MAC 0x01 +/* TYP for PKT=ip */ +#define WX_PTYPE_PKT_IPV6 0x08 +#define WX_PTYPE_TYP_IPFRAG 0x01 +#define WX_PTYPE_TYP_IP 0x02 +#define WX_PTYPE_TYP_UDP 0x03 +#define WX_PTYPE_TYP_TCP 0x04 +#define WX_PTYPE_TYP_SCTP 0x05 + +#define WX_RXD_PKTTYPE(_rxd) \ + ((le32_to_cpu((_rxd)->wb.lower.lo_dword.data) >> 9) & 0xFF) +#define WX_RXD_IPV6EX(_rxd) \ + ((le32_to_cpu((_rxd)->wb.lower.lo_dword.data) >> 6) & 0x1) /*********************** Transmit Descriptor Config Masks ****************/ #define WX_TXD_STAT_DD BIT(0) /* Descriptor Done */ #define WX_TXD_DTYP_DATA 0 /* Adv Data Descriptor */ @@ -334,6 +405,113 @@ #define WX_TXD_IFCS BIT(25) /* Insert FCS */ #define WX_TXD_RS BIT(27) /* Report Status */ +/*********************** Adv Transmit Descriptor Config Masks ****************/ +#define WX_TXD_MAC_TSTAMP BIT(19) /* IEEE1588 time stamp */ +#define WX_TXD_DTYP_CTXT BIT(20) /* Adv Context Desc */ +#define WX_TXD_LINKSEC BIT(26) /* enable linksec */ +#define WX_TXD_VLE BIT(30) /* VLAN pkt enable */ +#define WX_TXD_TSE BIT(31) /* TCP Seg enable */ +#define WX_TXD_CC BIT(7) /* Check Context */ +#define WX_TXD_IPSEC BIT(8) /* enable ipsec esp */ +#define WX_TXD_L4CS BIT(9) +#define WX_TXD_IIPCS BIT(10) +#define WX_TXD_EIPCS BIT(11) +#define WX_TXD_PAYLEN_SHIFT 13 /* Adv desc PAYLEN shift */ +#define WX_TXD_MACLEN_SHIFT 9 /* Adv ctxt desc mac len shift */ +#define WX_TXD_TAG_TPID_SEL_SHIFT 11 + +#define WX_TXD_L4LEN_SHIFT 8 /* Adv ctxt L4LEN shift */ +#define WX_TXD_MSS_SHIFT 16 /* Adv ctxt MSS shift */ + +#define WX_TXD_OUTER_IPLEN_SHIFT 12 /* Adv ctxt OUTERIPLEN shift */ +#define WX_TXD_TUNNEL_LEN_SHIFT 21 /* Adv ctxt TUNNELLEN shift */ +#define WX_TXD_TUNNEL_TYPE_SHIFT 11 /* Adv Tx Desc Tunnel Type shift */ +#define WX_TXD_TUNNEL_UDP FIELD_PREP(BIT(WX_TXD_TUNNEL_TYPE_SHIFT), 0) +#define WX_TXD_TUNNEL_GRE FIELD_PREP(BIT(WX_TXD_TUNNEL_TYPE_SHIFT), 1) + +enum wx_tx_flags { + /* cmd_type flags */ + WX_TX_FLAGS_HW_VLAN = 0x01, + WX_TX_FLAGS_TSO = 0x02, + WX_TX_FLAGS_TSTAMP = 0x04, + + /* olinfo flags */ + WX_TX_FLAGS_CC = 0x08, + WX_TX_FLAGS_IPV4 = 0x10, + WX_TX_FLAGS_CSUM = 0x20, + WX_TX_FLAGS_OUTER_IPV4 = 0x100, + WX_TX_FLAGS_LINKSEC = 0x200, + WX_TX_FLAGS_IPSEC = 0x400, +}; + +/* VLAN info */ +#define WX_TX_FLAGS_VLAN_MASK GENMASK(31, 16) +#define WX_TX_FLAGS_VLAN_SHIFT 16 + +/* wx_dec_ptype.mac: outer mac */ +enum wx_dec_ptype_mac { + WX_DEC_PTYPE_MAC_IP = 0, + WX_DEC_PTYPE_MAC_L2 = 2, + WX_DEC_PTYPE_MAC_FCOE = 3, +}; + +/* wx_dec_ptype.[e]ip: outer&encaped ip */ +#define WX_DEC_PTYPE_IP_FRAG 0x4 +enum wx_dec_ptype_ip { + WX_DEC_PTYPE_IP_NONE = 0, + WX_DEC_PTYPE_IP_IPV4 = 1, + WX_DEC_PTYPE_IP_IPV6 = 2, + WX_DEC_PTYPE_IP_FGV4 = WX_DEC_PTYPE_IP_FRAG | WX_DEC_PTYPE_IP_IPV4, + WX_DEC_PTYPE_IP_FGV6 = WX_DEC_PTYPE_IP_FRAG | WX_DEC_PTYPE_IP_IPV6, +}; + +/* wx_dec_ptype.etype: encaped type */ +enum wx_dec_ptype_etype { + WX_DEC_PTYPE_ETYPE_NONE = 0, + WX_DEC_PTYPE_ETYPE_IPIP = 1, /* IP+IP */ + WX_DEC_PTYPE_ETYPE_IG = 2, /* IP+GRE */ + WX_DEC_PTYPE_ETYPE_IGM = 3, /* IP+GRE+MAC */ + WX_DEC_PTYPE_ETYPE_IGMV = 4, /* IP+GRE+MAC+VLAN */ +}; + +/* wx_dec_ptype.proto: payload proto */ +enum wx_dec_ptype_prot { + WX_DEC_PTYPE_PROT_NONE = 0, + WX_DEC_PTYPE_PROT_UDP = 1, + WX_DEC_PTYPE_PROT_TCP = 2, + WX_DEC_PTYPE_PROT_SCTP = 3, + WX_DEC_PTYPE_PROT_ICMP = 4, + WX_DEC_PTYPE_PROT_TS = 5, /* time sync */ +}; + +/* wx_dec_ptype.layer: payload layer */ +enum wx_dec_ptype_layer { + WX_DEC_PTYPE_LAYER_NONE = 0, + WX_DEC_PTYPE_LAYER_PAY2 = 1, + WX_DEC_PTYPE_LAYER_PAY3 = 2, + WX_DEC_PTYPE_LAYER_PAY4 = 3, +}; + +struct wx_dec_ptype { + u32 known:1; + u32 mac:2; /* outer mac */ + u32 ip:3; /* outer ip*/ + u32 etype:3; /* encaped type */ + u32 eip:3; /* encaped ip */ + u32 prot:4; /* payload proto */ + u32 layer:3; /* payload layer */ +}; + +/* macro to make the table lines short */ +#define WX_PTT(mac, ip, etype, eip, proto, layer)\ + {1, \ + WX_DEC_PTYPE_MAC_##mac, /* mac */\ + WX_DEC_PTYPE_IP_##ip, /* ip */ \ + WX_DEC_PTYPE_ETYPE_##etype, /* etype */\ + WX_DEC_PTYPE_IP_##eip, /* eip */\ + WX_DEC_PTYPE_PROT_##proto, /* proto */\ + WX_DEC_PTYPE_LAYER_##layer /* layer */} + /* Host Interface Command Structures */ struct wx_hic_hdr { u8 cmd; @@ -412,6 +590,8 @@ struct wx_mac_info { u32 mta_shadow[128]; s32 mc_filter_type; u32 mcft_size; + u32 vft_shadow[128]; + u32 vft_size; u32 num_rar_entries; u32 rx_pb_size; u32 tx_pb_size; @@ -508,10 +688,25 @@ union wx_rx_desc { } wb; /* writeback */ }; +struct wx_tx_context_desc { + __le32 vlan_macip_lens; + __le32 seqnum_seed; + __le32 type_tucmd_mlhl; + __le32 mss_l4len_idx; +}; + +/* if _flag is in _input, return _result */ +#define WX_SET_FLAG(_input, _flag, _result) \ + (((_flag) <= (_result)) ? \ + ((u32)((_input) & (_flag)) * ((_result) / (_flag))) : \ + ((u32)((_input) & (_flag)) / ((_flag) / (_result)))) + #define WX_RX_DESC(R, i) \ (&(((union wx_rx_desc *)((R)->desc))[i])) #define WX_TX_DESC(R, i) \ (&(((union wx_tx_desc *)((R)->desc))[i])) +#define WX_TX_CTXTDESC(R, i) \ + (&(((struct wx_tx_context_desc *)((R)->desc))[i])) /* wrapper around a pointer to a socket buffer, * so a DMA handle can be stored along with the buffer @@ -523,6 +718,8 @@ struct wx_tx_buffer { unsigned short gso_segs; DEFINE_DMA_UNMAP_ADDR(dma); DEFINE_DMA_UNMAP_LEN(len); + __be16 protocol; + u32 tx_flags; }; struct wx_rx_buffer { @@ -539,6 +736,11 @@ struct wx_queue_stats { u64 bytes; }; +struct wx_rx_queue_stats { + u64 csum_good_cnt; + u64 csum_err; +}; + /* iterator for handling rings in ring container */ #define wx_for_each_ring(posm, headm) \ for (posm = (headm).ring; posm; posm = posm->next) @@ -550,7 +752,6 @@ struct wx_ring_container { u8 count; /* total number of rings in vector */ u8 itr; /* current ITR setting for ring */ }; - struct wx_ring { struct wx_ring *next; /* pointer to next ring in q_vector */ struct wx_q_vector *q_vector; /* backpointer to host q_vector */ @@ -580,6 +781,9 @@ struct wx_ring { struct wx_queue_stats stats; struct u64_stats_sync syncp; + union { + struct wx_rx_queue_stats rx_stats; + }; } ____cacheline_internodealigned_in_smp; struct wx_q_vector { @@ -598,7 +802,7 @@ struct wx_q_vector { char name[IFNAMSIZ + 17]; /* for dynamic allocation of rings associated with this q_vector */ - struct wx_ring ring[0] ____cacheline_internodealigned_in_smp; + struct wx_ring ring[] ____cacheline_internodealigned_in_smp; }; enum wx_isb_idx { @@ -610,6 +814,9 @@ enum wx_isb_idx { }; struct wx { + unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)]; + + void *priv; u8 __iomem *hw_addr; struct pci_dev *pdev; struct net_device *netdev; @@ -642,6 +849,7 @@ struct wx { bool wol_enabled; bool ncsi_enabled; bool gpio_ctrl; + raw_spinlock_t gpio_lock; /* Tx fast path data */ int num_tx_queues; diff --git a/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c b/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c index df6b870aa871163df5b186be2c433190d33a4dff..c99a5d3de72e60358bc32b9a2bdab707caaa6bfb 100644 --- a/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c +++ b/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c @@ -115,6 +115,7 @@ static int ngbe_sw_init(struct wx *wx) wx->mac.max_rx_queues = NGBE_MAX_RX_QUEUES; wx->mac.max_tx_queues = NGBE_MAX_TX_QUEUES; wx->mac.mcft_size = NGBE_MC_TBL_SIZE; + wx->mac.vft_size = NGBE_SP_VFT_TBL_SIZE; wx->mac.rx_pb_size = NGBE_RX_PB_SIZE; wx->mac.tx_pb_size = NGBE_TDB_PB_SZ; @@ -473,9 +474,12 @@ static const struct net_device_ops ngbe_netdev_ops = { .ndo_change_mtu = wx_change_mtu, .ndo_start_xmit = wx_xmit_frame, .ndo_set_rx_mode = wx_set_rx_mode, + .ndo_set_features = wx_set_features, .ndo_validate_addr = eth_validate_addr, .ndo_set_mac_address = wx_set_mac, .ndo_get_stats64 = wx_get_stats64, + .ndo_vlan_rx_add_vid = wx_vlan_rx_add_vid, + .ndo_vlan_rx_kill_vid = wx_vlan_rx_kill_vid, }; /** @@ -551,12 +555,18 @@ static int ngbe_probe(struct pci_dev *pdev, ngbe_set_ethtool_ops(netdev); netdev->netdev_ops = &ngbe_netdev_ops; - netdev->features |= NETIF_F_HIGHDMA; - netdev->features = NETIF_F_SG; - + netdev->features = NETIF_F_SG | NETIF_F_IP_CSUM | + NETIF_F_TSO | NETIF_F_TSO6 | + NETIF_F_RXHASH | NETIF_F_RXCSUM; + netdev->features |= NETIF_F_SCTP_CRC | NETIF_F_TSO_MANGLEID; + netdev->vlan_features |= netdev->features; + netdev->features |= NETIF_F_IPV6_CSUM | NETIF_F_VLAN_FEATURES; /* copy netdev features into list of user selectable features */ - netdev->hw_features |= netdev->features | - NETIF_F_RXALL; + netdev->hw_features |= netdev->features | NETIF_F_RXALL; + netdev->hw_features |= NETIF_F_NTUPLE | NETIF_F_HW_TC; + netdev->features |= NETIF_F_HIGHDMA; + netdev->hw_features |= NETIF_F_GRO; + netdev->features |= NETIF_F_GRO; netdev->priv_flags |= IFF_UNICAST_FLT; netdev->priv_flags |= IFF_SUPP_NOFCS; diff --git a/drivers/net/ethernet/wangxun/ngbe/ngbe_type.h b/drivers/net/ethernet/wangxun/ngbe/ngbe_type.h index 373d5af628cd5245a0e09770b78213738a983d88..b70eca397b672270820f8a2904c0c264f86a86b0 100644 --- a/drivers/net/ethernet/wangxun/ngbe/ngbe_type.h +++ b/drivers/net/ethernet/wangxun/ngbe/ngbe_type.h @@ -136,6 +136,7 @@ enum NGBE_MSCA_CMD_value { #define NGBE_RAR_ENTRIES 32 #define NGBE_RX_PB_SIZE 42 #define NGBE_MC_TBL_SIZE 128 +#define NGBE_SP_VFT_TBL_SIZE 128 #define NGBE_TDB_PB_SZ (20 * 1024) /* 160KB Packet Buffer */ /* TX/RX descriptor defines */ diff --git a/drivers/net/ethernet/wangxun/txgbe/Makefile b/drivers/net/ethernet/wangxun/txgbe/Makefile index 6db14a2cb2d04a08c7ad635248437df682014f37..7507f762edfe54de6dfdd27ea61ebcd0f380bffb 100644 --- a/drivers/net/ethernet/wangxun/txgbe/Makefile +++ b/drivers/net/ethernet/wangxun/txgbe/Makefile @@ -8,4 +8,5 @@ obj-$(CONFIG_TXGBE) += txgbe.o txgbe-objs := txgbe_main.o \ txgbe_hw.o \ + txgbe_phy.o \ txgbe_ethtool.o diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_ethtool.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_ethtool.c index d914e9a05404044da62bf4dae1b7de411d94a2b1..859da112586a427043e2f608793d4d81226bcc63 100644 --- a/drivers/net/ethernet/wangxun/txgbe/txgbe_ethtool.c +++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_ethtool.c @@ -6,11 +6,39 @@ #include #include "../libwx/wx_ethtool.h" +#include "../libwx/wx_type.h" +#include "txgbe_type.h" #include "txgbe_ethtool.h" +static int txgbe_nway_reset(struct net_device *netdev) +{ + struct txgbe *txgbe = netdev_to_txgbe(netdev); + + return phylink_ethtool_nway_reset(txgbe->phylink); +} + +static int txgbe_get_link_ksettings(struct net_device *netdev, + struct ethtool_link_ksettings *cmd) +{ + struct txgbe *txgbe = netdev_to_txgbe(netdev); + + return phylink_ethtool_ksettings_get(txgbe->phylink, cmd); +} + +static int txgbe_set_link_ksettings(struct net_device *netdev, + const struct ethtool_link_ksettings *cmd) +{ + struct txgbe *txgbe = netdev_to_txgbe(netdev); + + return phylink_ethtool_ksettings_set(txgbe->phylink, cmd); +} + static const struct ethtool_ops txgbe_ethtool_ops = { .get_drvinfo = wx_get_drvinfo, + .nway_reset = txgbe_nway_reset, .get_link = ethtool_op_get_link, + .get_link_ksettings = txgbe_get_link_ksettings, + .set_link_ksettings = txgbe_set_link_ksettings, }; void txgbe_set_ethtool_ops(struct net_device *netdev) diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_hw.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_hw.c index ebc46f3be0569c5450fc32a18751128fd511134d..0772eb14eabf6e8fda0c8b6c3f8a4e002d37f05b 100644 --- a/drivers/net/ethernet/wangxun/txgbe/txgbe_hw.c +++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_hw.c @@ -160,34 +160,24 @@ int txgbe_read_pba_string(struct wx *wx, u8 *pba_num, u32 pba_num_size) static int txgbe_calc_eeprom_checksum(struct wx *wx, u16 *checksum) { u16 *eeprom_ptrs = NULL; - u32 buffer_size = 0; - u16 *buffer = NULL; u16 *local_buffer; int status; u16 i; wx_init_eeprom_params(wx); - if (!buffer) { - eeprom_ptrs = kvmalloc_array(TXGBE_EEPROM_LAST_WORD, sizeof(u16), - GFP_KERNEL); - if (!eeprom_ptrs) - return -ENOMEM; - /* Read pointer area */ - status = wx_read_ee_hostif_buffer(wx, 0, - TXGBE_EEPROM_LAST_WORD, - eeprom_ptrs); - if (status != 0) { - wx_err(wx, "Failed to read EEPROM image\n"); - kvfree(eeprom_ptrs); - return status; - } - local_buffer = eeprom_ptrs; - } else { - if (buffer_size < TXGBE_EEPROM_LAST_WORD) - return -EFAULT; - local_buffer = buffer; + eeprom_ptrs = kvmalloc_array(TXGBE_EEPROM_LAST_WORD, sizeof(u16), + GFP_KERNEL); + if (!eeprom_ptrs) + return -ENOMEM; + /* Read pointer area */ + status = wx_read_ee_hostif_buffer(wx, 0, TXGBE_EEPROM_LAST_WORD, eeprom_ptrs); + if (status != 0) { + wx_err(wx, "Failed to read EEPROM image\n"); + kvfree(eeprom_ptrs); + return status; } + local_buffer = eeprom_ptrs; for (i = 0; i < TXGBE_EEPROM_LAST_WORD; i++) if (i != wx->eeprom.sw_region_offset + TXGBE_EEPROM_CHECKSUM) @@ -196,9 +186,6 @@ static int txgbe_calc_eeprom_checksum(struct wx *wx, u16 *checksum) if (eeprom_ptrs) kvfree(eeprom_ptrs); - if (*checksum > TXGBE_EEPROM_SUM) - return -EINVAL; - *checksum = TXGBE_EEPROM_SUM - *checksum; return 0; diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c index 5b8a121fb496b3d68557bb4e7cb8c53723bbcc47..46eba6d6188b2f5305d3a1dc7dade2c23191058b 100644 --- a/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c +++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -15,6 +16,7 @@ #include "../libwx/wx_hw.h" #include "txgbe_type.h" #include "txgbe_hw.h" +#include "txgbe_phy.h" #include "txgbe_ethtool.h" char txgbe_driver_name[] = "txgbe"; @@ -81,6 +83,8 @@ static int txgbe_enumerate_functions(struct wx *wx) **/ static void txgbe_irq_enable(struct wx *wx, bool queues) { + wr32(wx, WX_PX_MISC_IEN, TXGBE_PX_MISC_IEN_MASK); + /* unmask interrupt */ wx_intr_enable(wx, TXGBE_INTR_MISC(wx)); if (queues) @@ -128,17 +132,6 @@ static irqreturn_t txgbe_intr(int __always_unused irq, void *data) return IRQ_HANDLED; } -static irqreturn_t txgbe_msix_other(int __always_unused irq, void *data) -{ - struct wx *wx = data; - - /* re-enable the original interrupt state */ - if (netif_running(wx->netdev)) - txgbe_irq_enable(wx, false); - - return IRQ_HANDLED; -} - /** * txgbe_request_msix_irqs - Initialize MSI-X interrupts * @wx: board private structure @@ -170,13 +163,6 @@ static int txgbe_request_msix_irqs(struct wx *wx) } } - err = request_irq(wx->msix_entries[vector].vector, - txgbe_msix_other, 0, netdev->name, wx); - if (err) { - wx_err(wx, "request_irq for msix_other failed: %d\n", err); - goto free_queue_irqs; - } - return 0; free_queue_irqs: @@ -219,7 +205,8 @@ static int txgbe_request_irq(struct wx *wx) static void txgbe_up_complete(struct wx *wx) { - u32 reg; + struct net_device *netdev = wx->netdev; + struct txgbe *txgbe; wx_control_hw(wx, true); wx_configure_vectors(wx); @@ -228,24 +215,17 @@ static void txgbe_up_complete(struct wx *wx) smp_mb__before_atomic(); wx_napi_enable_all(wx); + txgbe = netdev_to_txgbe(netdev); + phylink_start(txgbe->phylink); + /* clear any pending interrupts, may auto mask */ rd32(wx, WX_PX_IC(0)); rd32(wx, WX_PX_IC(1)); rd32(wx, WX_PX_MISC_IC); txgbe_irq_enable(wx, true); - /* Configure MAC Rx and Tx when link is up */ - reg = rd32(wx, WX_MAC_RX_CFG); - wr32(wx, WX_MAC_RX_CFG, reg); - wr32(wx, WX_MAC_PKT_FLT, WX_MAC_PKT_FLT_PR); - reg = rd32(wx, WX_MAC_WDG_TIMEOUT); - wr32(wx, WX_MAC_WDG_TIMEOUT, reg); - reg = rd32(wx, WX_MAC_TX_CFG); - wr32(wx, WX_MAC_TX_CFG, (reg & ~WX_MAC_TX_CFG_SPEED_MASK) | WX_MAC_TX_CFG_SPEED_10G); - /* enable transmits */ - netif_tx_start_all_queues(wx->netdev); - netif_carrier_on(wx->netdev); + netif_tx_start_all_queues(netdev); } static void txgbe_reset(struct wx *wx) @@ -258,6 +238,7 @@ static void txgbe_reset(struct wx *wx) if (err != 0) wx_err(wx, "Hardware Error: %d\n", err); + wx_start_hw(wx); /* do not flush user set addresses */ memcpy(old_addr, &wx->mac_table[0].addr, netdev->addr_len); wx_flush_sw_mac_table(wx); @@ -279,7 +260,6 @@ static void txgbe_disable_device(struct wx *wx) wx_disable_rx_queue(wx, wx->rx_ring[i]); netif_tx_stop_all_queues(netdev); - netif_carrier_off(netdev); netif_tx_disable(netdev); wx_irq_disable(wx); @@ -310,8 +290,11 @@ static void txgbe_disable_device(struct wx *wx) static void txgbe_down(struct wx *wx) { + struct txgbe *txgbe = netdev_to_txgbe(wx->netdev); + txgbe_disable_device(wx); txgbe_reset(wx); + phylink_stop(txgbe->phylink); wx_clean_all_tx_rings(wx); wx_clean_all_rx_rings(wx); @@ -330,6 +313,7 @@ static int txgbe_sw_init(struct wx *wx) wx->mac.max_tx_queues = TXGBE_SP_MAX_TX_QUEUES; wx->mac.max_rx_queues = TXGBE_SP_MAX_RX_QUEUES; wx->mac.mcft_size = TXGBE_SP_MC_TBL_SIZE; + wx->mac.vft_size = TXGBE_SP_VFT_TBL_SIZE; wx->mac.rx_pb_size = TXGBE_SP_RX_PB_SIZE; wx->mac.tx_pb_size = TXGBE_SP_TDB_PB_SZ; @@ -455,7 +439,7 @@ static int txgbe_close(struct net_device *netdev) return 0; } -static void txgbe_dev_shutdown(struct pci_dev *pdev, bool *enable_wake) +static void txgbe_dev_shutdown(struct pci_dev *pdev) { struct wx *wx = pci_get_drvdata(pdev); struct net_device *netdev; @@ -475,12 +459,10 @@ static void txgbe_dev_shutdown(struct pci_dev *pdev, bool *enable_wake) static void txgbe_shutdown(struct pci_dev *pdev) { - bool wake; - - txgbe_dev_shutdown(pdev, &wake); + txgbe_dev_shutdown(pdev); if (system_state == SYSTEM_POWER_OFF) { - pci_wake_from_d3(pdev, wake); + pci_wake_from_d3(pdev, false); pci_set_power_state(pdev, PCI_D3hot); } } @@ -491,9 +473,12 @@ static const struct net_device_ops txgbe_netdev_ops = { .ndo_change_mtu = wx_change_mtu, .ndo_start_xmit = wx_xmit_frame, .ndo_set_rx_mode = wx_set_rx_mode, + .ndo_set_features = wx_set_features, .ndo_validate_addr = eth_validate_addr, .ndo_set_mac_address = wx_set_mac, .ndo_get_stats64 = wx_get_stats64, + .ndo_vlan_rx_add_vid = wx_vlan_rx_add_vid, + .ndo_vlan_rx_kill_vid = wx_vlan_rx_kill_vid, }; /** @@ -513,6 +498,7 @@ static int txgbe_probe(struct pci_dev *pdev, struct net_device *netdev; int err, expected_gts; struct wx *wx = NULL; + struct txgbe *txgbe; u16 eeprom_verh = 0, eeprom_verl = 0, offset = 0; u16 eeprom_cfg_blkh = 0, eeprom_cfg_blkl = 0; @@ -596,11 +582,25 @@ static int txgbe_probe(struct pci_dev *pdev, goto err_free_mac_table; } - netdev->features |= NETIF_F_HIGHDMA; - netdev->features = NETIF_F_SG; - + netdev->features = NETIF_F_SG | + NETIF_F_TSO | + NETIF_F_TSO6 | + NETIF_F_RXHASH | + NETIF_F_RXCSUM | + NETIF_F_HW_CSUM; + + netdev->gso_partial_features = NETIF_F_GSO_ENCAP_ALL; + netdev->features |= netdev->gso_partial_features; + netdev->features |= NETIF_F_SCTP_CRC; + netdev->vlan_features |= netdev->features | NETIF_F_TSO_MANGLEID; + netdev->hw_enc_features |= netdev->vlan_features; + netdev->features |= NETIF_F_VLAN_FEATURES; /* copy netdev features into list of user selectable features */ netdev->hw_features |= netdev->features | NETIF_F_RXALL; + netdev->hw_features |= NETIF_F_NTUPLE | NETIF_F_HW_TC; + netdev->features |= NETIF_F_HIGHDMA; + netdev->hw_features |= NETIF_F_GRO; + netdev->features |= NETIF_F_GRO; netdev->priv_flags |= IFF_UNICAST_FLT; netdev->priv_flags |= IFF_SUPP_NOFCS; @@ -663,10 +663,23 @@ static int txgbe_probe(struct pci_dev *pdev, "0x%08x", etrack_id); } - err = register_netdev(netdev); + txgbe = devm_kzalloc(&pdev->dev, sizeof(*txgbe), GFP_KERNEL); + if (!txgbe) { + err = -ENOMEM; + goto err_release_hw; + } + + txgbe->wx = wx; + wx->priv = txgbe; + + err = txgbe_init_phy(txgbe); if (err) goto err_release_hw; + err = register_netdev(netdev); + if (err) + goto err_remove_phy; + pci_set_drvdata(pdev, wx); netif_tx_stop_all_queues(netdev); @@ -694,6 +707,8 @@ static int txgbe_probe(struct pci_dev *pdev, return 0; +err_remove_phy: + txgbe_remove_phy(txgbe); err_release_hw: wx_clear_interrupt_scheme(wx); wx_control_hw(wx, false); @@ -719,11 +734,14 @@ static int txgbe_probe(struct pci_dev *pdev, static void txgbe_remove(struct pci_dev *pdev) { struct wx *wx = pci_get_drvdata(pdev); + struct txgbe *txgbe = wx->priv; struct net_device *netdev; netdev = wx->netdev; unregister_netdev(netdev); + txgbe_remove_phy(txgbe); + pci_release_selected_regions(pdev, pci_select_bars(pdev, IORESOURCE_MEM)); diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c new file mode 100644 index 0000000000000000000000000000000000000000..8779645a54be470c97583f7ba576ba0c62c6d264 --- /dev/null +++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c @@ -0,0 +1,673 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2015 - 2023 Beijing WangXun Technology Co., Ltd. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../libwx/wx_type.h" +#include "../libwx/wx_lib.h" +#include "../libwx/wx_hw.h" +#include "txgbe_type.h" +#include "txgbe_phy.h" + +static int txgbe_swnodes_register(struct txgbe *txgbe) +{ + struct txgbe_nodes *nodes = &txgbe->nodes; + struct pci_dev *pdev = txgbe->wx->pdev; + struct software_node *swnodes; + u32 id; + + id = (pdev->bus->number << 8) | pdev->devfn; + + snprintf(nodes->gpio_name, sizeof(nodes->gpio_name), "txgbe_gpio-%x", id); + snprintf(nodes->i2c_name, sizeof(nodes->i2c_name), "txgbe_i2c-%x", id); + snprintf(nodes->sfp_name, sizeof(nodes->sfp_name), "txgbe_sfp-%x", id); + snprintf(nodes->phylink_name, sizeof(nodes->phylink_name), "txgbe_phylink-%x", id); + + swnodes = nodes->swnodes; + + /* GPIO 0: tx fault + * GPIO 1: tx disable + * GPIO 2: sfp module absent + * GPIO 3: rx signal lost + * GPIO 4: rate select, 1G(0) 10G(1) + * GPIO 5: rate select, 1G(0) 10G(1) + */ + nodes->gpio_props[0] = PROPERTY_ENTRY_STRING("pinctrl-names", "default"); + swnodes[SWNODE_GPIO] = NODE_PROP(nodes->gpio_name, nodes->gpio_props); + nodes->gpio0_ref[0] = SOFTWARE_NODE_REFERENCE(&swnodes[SWNODE_GPIO], 0, GPIO_ACTIVE_HIGH); + nodes->gpio1_ref[0] = SOFTWARE_NODE_REFERENCE(&swnodes[SWNODE_GPIO], 1, GPIO_ACTIVE_HIGH); + nodes->gpio2_ref[0] = SOFTWARE_NODE_REFERENCE(&swnodes[SWNODE_GPIO], 2, GPIO_ACTIVE_LOW); + nodes->gpio3_ref[0] = SOFTWARE_NODE_REFERENCE(&swnodes[SWNODE_GPIO], 3, GPIO_ACTIVE_HIGH); + nodes->gpio4_ref[0] = SOFTWARE_NODE_REFERENCE(&swnodes[SWNODE_GPIO], 4, GPIO_ACTIVE_HIGH); + nodes->gpio5_ref[0] = SOFTWARE_NODE_REFERENCE(&swnodes[SWNODE_GPIO], 5, GPIO_ACTIVE_HIGH); + + nodes->i2c_props[0] = PROPERTY_ENTRY_STRING("compatible", "snps,designware-i2c"); + nodes->i2c_props[1] = PROPERTY_ENTRY_BOOL("wx,i2c-snps-model"); + nodes->i2c_props[2] = PROPERTY_ENTRY_U32("clock-frequency", I2C_MAX_STANDARD_MODE_FREQ); + swnodes[SWNODE_I2C] = NODE_PROP(nodes->i2c_name, nodes->i2c_props); + nodes->i2c_ref[0] = SOFTWARE_NODE_REFERENCE(&swnodes[SWNODE_I2C]); + + nodes->sfp_props[0] = PROPERTY_ENTRY_STRING("compatible", "sff,sfp"); + nodes->sfp_props[1] = PROPERTY_ENTRY_REF_ARRAY("i2c-bus", nodes->i2c_ref); + nodes->sfp_props[2] = PROPERTY_ENTRY_REF_ARRAY("tx-fault-gpios", nodes->gpio0_ref); + nodes->sfp_props[3] = PROPERTY_ENTRY_REF_ARRAY("tx-disable-gpios", nodes->gpio1_ref); + nodes->sfp_props[4] = PROPERTY_ENTRY_REF_ARRAY("mod-def0-gpios", nodes->gpio2_ref); + nodes->sfp_props[5] = PROPERTY_ENTRY_REF_ARRAY("los-gpios", nodes->gpio3_ref); + nodes->sfp_props[6] = PROPERTY_ENTRY_REF_ARRAY("rate-select1-gpios", nodes->gpio4_ref); + nodes->sfp_props[7] = PROPERTY_ENTRY_REF_ARRAY("rate-select0-gpios", nodes->gpio5_ref); + swnodes[SWNODE_SFP] = NODE_PROP(nodes->sfp_name, nodes->sfp_props); + nodes->sfp_ref[0] = SOFTWARE_NODE_REFERENCE(&swnodes[SWNODE_SFP]); + + nodes->phylink_props[0] = PROPERTY_ENTRY_STRING("managed", "in-band-status"); + nodes->phylink_props[1] = PROPERTY_ENTRY_REF_ARRAY("sfp", nodes->sfp_ref); + swnodes[SWNODE_PHYLINK] = NODE_PROP(nodes->phylink_name, nodes->phylink_props); + + nodes->group[SWNODE_GPIO] = &swnodes[SWNODE_GPIO]; + nodes->group[SWNODE_I2C] = &swnodes[SWNODE_I2C]; + nodes->group[SWNODE_SFP] = &swnodes[SWNODE_SFP]; + nodes->group[SWNODE_PHYLINK] = &swnodes[SWNODE_PHYLINK]; + + return software_node_register_node_group(nodes->group); +} + +static int txgbe_pcs_read(struct mii_bus *bus, int addr, int devnum, int regnum) +{ + struct wx *wx = bus->priv; + u32 offset, val; + + if (addr) + return -EOPNOTSUPP; + + offset = devnum << 16 | regnum; + + /* Set the LAN port indicator to IDA_ADDR */ + wr32(wx, TXGBE_XPCS_IDA_ADDR, offset); + + /* Read the data from IDA_DATA register */ + val = rd32(wx, TXGBE_XPCS_IDA_DATA); + + return (u16)val; +} + +static int txgbe_pcs_write(struct mii_bus *bus, int addr, int devnum, int regnum, u16 val) +{ + struct wx *wx = bus->priv; + u32 offset; + + if (addr) + return -EOPNOTSUPP; + + offset = devnum << 16 | regnum; + + /* Set the LAN port indicator to IDA_ADDR */ + wr32(wx, TXGBE_XPCS_IDA_ADDR, offset); + + /* Write the data to IDA_DATA register */ + wr32(wx, TXGBE_XPCS_IDA_DATA, val); + + return 0; +} + +static int txgbe_mdio_pcs_init(struct txgbe *txgbe) +{ + struct mii_bus *mii_bus; + struct dw_xpcs *xpcs; + struct pci_dev *pdev; + struct wx *wx; + int ret = 0; + + wx = txgbe->wx; + pdev = wx->pdev; + + mii_bus = devm_mdiobus_alloc(&pdev->dev); + if (!mii_bus) + return -ENOMEM; + + mii_bus->name = "txgbe_pcs_mdio_bus"; + mii_bus->read_c45 = &txgbe_pcs_read; + mii_bus->write_c45 = &txgbe_pcs_write; + mii_bus->parent = &pdev->dev; + mii_bus->phy_mask = ~0; + mii_bus->priv = wx; + snprintf(mii_bus->id, MII_BUS_ID_SIZE, "txgbe_pcs-%x", + (pdev->bus->number << 8) | pdev->devfn); + + ret = devm_mdiobus_register(&pdev->dev, mii_bus); + if (ret) + return ret; + + xpcs = xpcs_create_mdiodev(mii_bus, 0, PHY_INTERFACE_MODE_10GBASER); + if (IS_ERR(xpcs)) + return PTR_ERR(xpcs); + + txgbe->xpcs = xpcs; + + return 0; +} + +static struct phylink_pcs *txgbe_phylink_mac_select(struct phylink_config *config, + phy_interface_t interface) +{ + struct txgbe *txgbe = netdev_to_txgbe(to_net_dev(config->dev)); + + return &txgbe->xpcs->pcs; +} + +static void txgbe_mac_config(struct phylink_config *config, unsigned int mode, + const struct phylink_link_state *state) +{ +} + +static void txgbe_mac_link_down(struct phylink_config *config, + unsigned int mode, phy_interface_t interface) +{ + struct wx *wx = netdev_priv(to_net_dev(config->dev)); + + wr32m(wx, WX_MAC_TX_CFG, WX_MAC_TX_CFG_TE, 0); +} + +static void txgbe_mac_link_up(struct phylink_config *config, + struct phy_device *phy, + unsigned int mode, phy_interface_t interface, + int speed, int duplex, + bool tx_pause, bool rx_pause) +{ + struct wx *wx = netdev_priv(to_net_dev(config->dev)); + u32 txcfg, wdg; + + txcfg = rd32(wx, WX_MAC_TX_CFG); + txcfg &= ~WX_MAC_TX_CFG_SPEED_MASK; + + switch (speed) { + case SPEED_10000: + txcfg |= WX_MAC_TX_CFG_SPEED_10G; + break; + case SPEED_1000: + case SPEED_100: + case SPEED_10: + txcfg |= WX_MAC_TX_CFG_SPEED_1G; + break; + default: + break; + } + + wr32(wx, WX_MAC_TX_CFG, txcfg | WX_MAC_TX_CFG_TE); + + /* Re configure MAC Rx */ + wr32m(wx, WX_MAC_RX_CFG, WX_MAC_RX_CFG_RE, WX_MAC_RX_CFG_RE); + wr32(wx, WX_MAC_PKT_FLT, WX_MAC_PKT_FLT_PR); + wdg = rd32(wx, WX_MAC_WDG_TIMEOUT); + wr32(wx, WX_MAC_WDG_TIMEOUT, wdg); +} + +static const struct phylink_mac_ops txgbe_mac_ops = { + .mac_select_pcs = txgbe_phylink_mac_select, + .mac_config = txgbe_mac_config, + .mac_link_down = txgbe_mac_link_down, + .mac_link_up = txgbe_mac_link_up, +}; + +static int txgbe_phylink_init(struct txgbe *txgbe) +{ + struct phylink_config *config; + struct fwnode_handle *fwnode; + struct wx *wx = txgbe->wx; + phy_interface_t phy_mode; + struct phylink *phylink; + + config = devm_kzalloc(&wx->pdev->dev, sizeof(*config), GFP_KERNEL); + if (!config) + return -ENOMEM; + + config->dev = &wx->netdev->dev; + config->type = PHYLINK_NETDEV; + config->mac_capabilities = MAC_10000FD | MAC_1000FD | MAC_SYM_PAUSE | MAC_ASYM_PAUSE; + phy_mode = PHY_INTERFACE_MODE_10GBASER; + __set_bit(PHY_INTERFACE_MODE_10GBASER, config->supported_interfaces); + fwnode = software_node_fwnode(txgbe->nodes.group[SWNODE_PHYLINK]); + phylink = phylink_create(config, fwnode, phy_mode, &txgbe_mac_ops); + if (IS_ERR(phylink)) + return PTR_ERR(phylink); + + txgbe->phylink = phylink; + + return 0; +} + +static int txgbe_gpio_get(struct gpio_chip *chip, unsigned int offset) +{ + struct wx *wx = gpiochip_get_data(chip); + int val; + + val = rd32m(wx, WX_GPIO_EXT, BIT(offset)); + + return !!(val & BIT(offset)); +} + +static int txgbe_gpio_get_direction(struct gpio_chip *chip, unsigned int offset) +{ + struct wx *wx = gpiochip_get_data(chip); + u32 val; + + val = rd32(wx, WX_GPIO_DDR); + if (BIT(offset) & val) + return GPIO_LINE_DIRECTION_OUT; + + return GPIO_LINE_DIRECTION_IN; +} + +static int txgbe_gpio_direction_in(struct gpio_chip *chip, unsigned int offset) +{ + struct wx *wx = gpiochip_get_data(chip); + unsigned long flags; + + raw_spin_lock_irqsave(&wx->gpio_lock, flags); + wr32m(wx, WX_GPIO_DDR, BIT(offset), 0); + raw_spin_unlock_irqrestore(&wx->gpio_lock, flags); + + return 0; +} + +static int txgbe_gpio_direction_out(struct gpio_chip *chip, unsigned int offset, + int val) +{ + struct wx *wx = gpiochip_get_data(chip); + unsigned long flags; + u32 set; + + set = val ? BIT(offset) : 0; + + raw_spin_lock_irqsave(&wx->gpio_lock, flags); + wr32m(wx, WX_GPIO_DR, BIT(offset), set); + wr32m(wx, WX_GPIO_DDR, BIT(offset), BIT(offset)); + raw_spin_unlock_irqrestore(&wx->gpio_lock, flags); + + return 0; +} + +static void txgbe_gpio_irq_ack(struct irq_data *d) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + irq_hw_number_t hwirq = irqd_to_hwirq(d); + struct wx *wx = gpiochip_get_data(gc); + unsigned long flags; + + raw_spin_lock_irqsave(&wx->gpio_lock, flags); + wr32(wx, WX_GPIO_EOI, BIT(hwirq)); + raw_spin_unlock_irqrestore(&wx->gpio_lock, flags); +} + +static void txgbe_gpio_irq_mask(struct irq_data *d) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + irq_hw_number_t hwirq = irqd_to_hwirq(d); + struct wx *wx = gpiochip_get_data(gc); + unsigned long flags; + + gpiochip_disable_irq(gc, hwirq); + + raw_spin_lock_irqsave(&wx->gpio_lock, flags); + wr32m(wx, WX_GPIO_INTMASK, BIT(hwirq), BIT(hwirq)); + raw_spin_unlock_irqrestore(&wx->gpio_lock, flags); +} + +static void txgbe_gpio_irq_unmask(struct irq_data *d) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + irq_hw_number_t hwirq = irqd_to_hwirq(d); + struct wx *wx = gpiochip_get_data(gc); + unsigned long flags; + + gpiochip_enable_irq(gc, hwirq); + + raw_spin_lock_irqsave(&wx->gpio_lock, flags); + wr32m(wx, WX_GPIO_INTMASK, BIT(hwirq), 0); + raw_spin_unlock_irqrestore(&wx->gpio_lock, flags); +} + +static void txgbe_toggle_trigger(struct gpio_chip *gc, unsigned int offset) +{ + struct wx *wx = gpiochip_get_data(gc); + u32 pol, val; + + pol = rd32(wx, WX_GPIO_POLARITY); + val = rd32(wx, WX_GPIO_EXT); + + if (val & BIT(offset)) + pol &= ~BIT(offset); + else + pol |= BIT(offset); + + wr32(wx, WX_GPIO_POLARITY, pol); +} + +static int txgbe_gpio_set_type(struct irq_data *d, unsigned int type) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + irq_hw_number_t hwirq = irqd_to_hwirq(d); + struct wx *wx = gpiochip_get_data(gc); + u32 level, polarity, mask; + unsigned long flags; + + mask = BIT(hwirq); + + if (type & IRQ_TYPE_LEVEL_MASK) { + level = 0; + irq_set_handler_locked(d, handle_level_irq); + } else { + level = mask; + irq_set_handler_locked(d, handle_edge_irq); + } + + if (type == IRQ_TYPE_EDGE_RISING || type == IRQ_TYPE_LEVEL_HIGH) + polarity = mask; + else + polarity = 0; + + raw_spin_lock_irqsave(&wx->gpio_lock, flags); + + wr32m(wx, WX_GPIO_INTEN, mask, mask); + wr32m(wx, WX_GPIO_INTTYPE_LEVEL, mask, level); + if (type == IRQ_TYPE_EDGE_BOTH) + txgbe_toggle_trigger(gc, hwirq); + else + wr32m(wx, WX_GPIO_POLARITY, mask, polarity); + + raw_spin_unlock_irqrestore(&wx->gpio_lock, flags); + + return 0; +} + +static const struct irq_chip txgbe_gpio_irq_chip = { + .name = "txgbe_gpio_irq", + .irq_ack = txgbe_gpio_irq_ack, + .irq_mask = txgbe_gpio_irq_mask, + .irq_unmask = txgbe_gpio_irq_unmask, + .irq_set_type = txgbe_gpio_set_type, + .flags = IRQCHIP_IMMUTABLE, + GPIOCHIP_IRQ_RESOURCE_HELPERS, +}; + +static void txgbe_irq_handler(struct irq_desc *desc) +{ + struct irq_chip *chip = irq_desc_get_chip(desc); + struct wx *wx = irq_desc_get_handler_data(desc); + struct txgbe *txgbe = wx->priv; + irq_hw_number_t hwirq; + unsigned long gpioirq; + struct gpio_chip *gc; + unsigned long flags; + u32 eicr; + + eicr = wx_misc_isb(wx, WX_ISB_MISC); + + chained_irq_enter(chip, desc); + + gpioirq = rd32(wx, WX_GPIO_INTSTATUS); + + gc = txgbe->gpio; + for_each_set_bit(hwirq, &gpioirq, gc->ngpio) { + int gpio = irq_find_mapping(gc->irq.domain, hwirq); + u32 irq_type = irq_get_trigger_type(gpio); + + generic_handle_domain_irq(gc->irq.domain, hwirq); + + if ((irq_type & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) { + raw_spin_lock_irqsave(&wx->gpio_lock, flags); + txgbe_toggle_trigger(gc, hwirq); + raw_spin_unlock_irqrestore(&wx->gpio_lock, flags); + } + } + + chained_irq_exit(chip, desc); + + if (eicr & (TXGBE_PX_MISC_ETH_LK | TXGBE_PX_MISC_ETH_LKDN)) { + u32 reg = rd32(wx, TXGBE_CFG_PORT_ST); + + phylink_mac_change(txgbe->phylink, !!(reg & TXGBE_CFG_PORT_ST_LINK_UP)); + } + + /* unmask interrupt */ + wx_intr_enable(wx, TXGBE_INTR_MISC(wx)); +} + +static int txgbe_gpio_init(struct txgbe *txgbe) +{ + struct gpio_irq_chip *girq; + struct gpio_chip *gc; + struct device *dev; + struct wx *wx; + int ret; + + wx = txgbe->wx; + dev = &wx->pdev->dev; + + raw_spin_lock_init(&wx->gpio_lock); + + gc = devm_kzalloc(dev, sizeof(*gc), GFP_KERNEL); + if (!gc) + return -ENOMEM; + + gc->label = devm_kasprintf(dev, GFP_KERNEL, "txgbe_gpio-%x", + (wx->pdev->bus->number << 8) | wx->pdev->devfn); + if (!gc->label) + return -ENOMEM; + + gc->base = -1; + gc->ngpio = 6; + gc->owner = THIS_MODULE; + gc->parent = dev; + gc->fwnode = software_node_fwnode(txgbe->nodes.group[SWNODE_GPIO]); + gc->get = txgbe_gpio_get; + gc->get_direction = txgbe_gpio_get_direction; + gc->direction_input = txgbe_gpio_direction_in; + gc->direction_output = txgbe_gpio_direction_out; + + girq = &gc->irq; + gpio_irq_chip_set_chip(girq, &txgbe_gpio_irq_chip); + girq->parent_handler = txgbe_irq_handler; + girq->parent_handler_data = wx; + girq->num_parents = 1; + girq->parents = devm_kcalloc(dev, girq->num_parents, + sizeof(*girq->parents), GFP_KERNEL); + if (!girq->parents) + return -ENOMEM; + girq->parents[0] = wx->msix_entries[wx->num_q_vectors].vector; + girq->default_type = IRQ_TYPE_NONE; + girq->handler = handle_bad_irq; + + ret = devm_gpiochip_add_data(dev, gc, wx); + if (ret) + return ret; + + txgbe->gpio = gc; + + return 0; +} + +static int txgbe_clock_register(struct txgbe *txgbe) +{ + struct pci_dev *pdev = txgbe->wx->pdev; + struct clk_lookup *clock; + char clk_name[32]; + struct clk *clk; + + snprintf(clk_name, sizeof(clk_name), "i2c_designware.%d", + (pdev->bus->number << 8) | pdev->devfn); + + clk = clk_register_fixed_rate(NULL, clk_name, NULL, 0, 156250000); + if (IS_ERR(clk)) + return PTR_ERR(clk); + + clock = clkdev_create(clk, NULL, clk_name); + if (!clock) { + clk_unregister(clk); + return -ENOMEM; + } + + txgbe->clk = clk; + txgbe->clock = clock; + + return 0; +} + +static int txgbe_i2c_read(void *context, unsigned int reg, unsigned int *val) +{ + struct wx *wx = context; + + *val = rd32(wx, reg + TXGBE_I2C_BASE); + + return 0; +} + +static int txgbe_i2c_write(void *context, unsigned int reg, unsigned int val) +{ + struct wx *wx = context; + + wr32(wx, reg + TXGBE_I2C_BASE, val); + + return 0; +} + +static const struct regmap_config i2c_regmap_config = { + .reg_bits = 32, + .val_bits = 32, + .reg_read = txgbe_i2c_read, + .reg_write = txgbe_i2c_write, + .fast_io = true, +}; + +static int txgbe_i2c_register(struct txgbe *txgbe) +{ + struct platform_device_info info = {}; + struct platform_device *i2c_dev; + struct regmap *i2c_regmap; + struct pci_dev *pdev; + struct wx *wx; + + wx = txgbe->wx; + pdev = wx->pdev; + i2c_regmap = devm_regmap_init(&pdev->dev, NULL, wx, &i2c_regmap_config); + if (IS_ERR(i2c_regmap)) { + wx_err(wx, "failed to init I2C regmap\n"); + return PTR_ERR(i2c_regmap); + } + + info.parent = &pdev->dev; + info.fwnode = software_node_fwnode(txgbe->nodes.group[SWNODE_I2C]); + info.name = "i2c_designware"; + info.id = (pdev->bus->number << 8) | pdev->devfn; + + info.res = &DEFINE_RES_IRQ(pdev->irq); + info.num_res = 1; + i2c_dev = platform_device_register_full(&info); + if (IS_ERR(i2c_dev)) + return PTR_ERR(i2c_dev); + + txgbe->i2c_dev = i2c_dev; + + return 0; +} + +static int txgbe_sfp_register(struct txgbe *txgbe) +{ + struct pci_dev *pdev = txgbe->wx->pdev; + struct platform_device_info info = {}; + struct platform_device *sfp_dev; + + info.parent = &pdev->dev; + info.fwnode = software_node_fwnode(txgbe->nodes.group[SWNODE_SFP]); + info.name = "sfp"; + info.id = (pdev->bus->number << 8) | pdev->devfn; + sfp_dev = platform_device_register_full(&info); + if (IS_ERR(sfp_dev)) + return PTR_ERR(sfp_dev); + + txgbe->sfp_dev = sfp_dev; + + return 0; +} + +int txgbe_init_phy(struct txgbe *txgbe) +{ + int ret; + + ret = txgbe_swnodes_register(txgbe); + if (ret) { + wx_err(txgbe->wx, "failed to register software nodes\n"); + return ret; + } + + ret = txgbe_mdio_pcs_init(txgbe); + if (ret) { + wx_err(txgbe->wx, "failed to init mdio pcs: %d\n", ret); + goto err_unregister_swnode; + } + + ret = txgbe_phylink_init(txgbe); + if (ret) { + wx_err(txgbe->wx, "failed to init phylink\n"); + goto err_destroy_xpcs; + } + + ret = txgbe_gpio_init(txgbe); + if (ret) { + wx_err(txgbe->wx, "failed to init gpio\n"); + goto err_destroy_phylink; + } + + ret = txgbe_clock_register(txgbe); + if (ret) { + wx_err(txgbe->wx, "failed to register clock: %d\n", ret); + goto err_destroy_phylink; + } + + ret = txgbe_i2c_register(txgbe); + if (ret) { + wx_err(txgbe->wx, "failed to init i2c interface: %d\n", ret); + goto err_unregister_clk; + } + + ret = txgbe_sfp_register(txgbe); + if (ret) { + wx_err(txgbe->wx, "failed to register sfp\n"); + goto err_unregister_i2c; + } + + return 0; + +err_unregister_i2c: + platform_device_unregister(txgbe->i2c_dev); +err_unregister_clk: + clkdev_drop(txgbe->clock); + clk_unregister(txgbe->clk); +err_destroy_phylink: + phylink_destroy(txgbe->phylink); +err_destroy_xpcs: + xpcs_destroy(txgbe->xpcs); +err_unregister_swnode: + software_node_unregister_node_group(txgbe->nodes.group); + + return ret; +} + +void txgbe_remove_phy(struct txgbe *txgbe) +{ + platform_device_unregister(txgbe->sfp_dev); + platform_device_unregister(txgbe->i2c_dev); + clkdev_drop(txgbe->clock); + clk_unregister(txgbe->clk); + phylink_destroy(txgbe->phylink); + xpcs_destroy(txgbe->xpcs); + software_node_unregister_node_group(txgbe->nodes.group); +} diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.h b/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.h new file mode 100644 index 0000000000000000000000000000000000000000..1ab592124986aea4254a3e334193a11382eeac4b --- /dev/null +++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.h @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (c) 2015 - 2023 Beijing WangXun Technology Co., Ltd. */ + +#ifndef _TXGBE_PHY_H_ +#define _TXGBE_PHY_H_ + +int txgbe_init_phy(struct txgbe *txgbe); +void txgbe_remove_phy(struct txgbe *txgbe); + +#endif /* _TXGBE_NODE_H_ */ diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h b/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h index 63a1c733718d3f735a795a862cf9c321ad2cea47..51199c355f95ce4f21e2fbcb745474316f282e72 100644 --- a/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h +++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h @@ -4,6 +4,8 @@ #ifndef _TXGBE_TYPE_H_ #define _TXGBE_TYPE_H_ +#include + /* Device IDs */ #define TXGBE_DEV_ID_SP1000 0x1001 #define TXGBE_DEV_ID_WX1820 0x2001 @@ -53,6 +55,39 @@ #define TXGBE_TS_CTL 0x10300 #define TXGBE_TS_CTL_EVAL_MD BIT(31) +/* GPIO register bit */ +#define TXGBE_GPIOBIT_0 BIT(0) /* I:tx fault */ +#define TXGBE_GPIOBIT_1 BIT(1) /* O:tx disabled */ +#define TXGBE_GPIOBIT_2 BIT(2) /* I:sfp module absent */ +#define TXGBE_GPIOBIT_3 BIT(3) /* I:rx signal lost */ +#define TXGBE_GPIOBIT_4 BIT(4) /* O:rate select, 1G(0) 10G(1) */ +#define TXGBE_GPIOBIT_5 BIT(5) /* O:rate select, 1G(0) 10G(1) */ + +/* Extended Interrupt Enable Set */ +#define TXGBE_PX_MISC_ETH_LKDN BIT(8) +#define TXGBE_PX_MISC_DEV_RST BIT(10) +#define TXGBE_PX_MISC_ETH_EVENT BIT(17) +#define TXGBE_PX_MISC_ETH_LK BIT(18) +#define TXGBE_PX_MISC_ETH_AN BIT(19) +#define TXGBE_PX_MISC_INT_ERR BIT(20) +#define TXGBE_PX_MISC_GPIO BIT(26) +#define TXGBE_PX_MISC_IEN_MASK \ + (TXGBE_PX_MISC_ETH_LKDN | TXGBE_PX_MISC_DEV_RST | \ + TXGBE_PX_MISC_ETH_EVENT | TXGBE_PX_MISC_ETH_LK | \ + TXGBE_PX_MISC_ETH_AN | TXGBE_PX_MISC_INT_ERR | \ + TXGBE_PX_MISC_GPIO) + +/* Port cfg registers */ +#define TXGBE_CFG_PORT_ST 0x14404 +#define TXGBE_CFG_PORT_ST_LINK_UP BIT(0) + +/* I2C registers */ +#define TXGBE_I2C_BASE 0x14900 + +/************************************** ETH PHY ******************************/ +#define TXGBE_XPCS_IDA_ADDR 0x13000 +#define TXGBE_XPCS_IDA_DATA 0x13004 + /* Part Number String Length */ #define TXGBE_PBANUM_LENGTH 32 @@ -77,6 +112,7 @@ #define TXGBE_SP_MAX_RX_QUEUES 128 #define TXGBE_SP_RAR_ENTRIES 128 #define TXGBE_SP_MC_TBL_SIZE 128 +#define TXGBE_SP_VFT_TBL_SIZE 128 #define TXGBE_SP_RX_PB_SIZE 512 #define TXGBE_SP_TDB_PB_SZ (160 * 1024) /* 160KB Packet Buffer */ @@ -99,4 +135,58 @@ extern char txgbe_driver_name[]; +static inline struct txgbe *netdev_to_txgbe(struct net_device *netdev) +{ + struct wx *wx = netdev_priv(netdev); + + return wx->priv; +} + +#define NODE_PROP(_NAME, _PROP) \ + (const struct software_node) { \ + .name = _NAME, \ + .properties = _PROP, \ + } + +enum txgbe_swnodes { + SWNODE_GPIO = 0, + SWNODE_I2C, + SWNODE_SFP, + SWNODE_PHYLINK, + SWNODE_MAX +}; + +struct txgbe_nodes { + char gpio_name[32]; + char i2c_name[32]; + char sfp_name[32]; + char phylink_name[32]; + struct property_entry gpio_props[1]; + struct property_entry i2c_props[3]; + struct property_entry sfp_props[8]; + struct property_entry phylink_props[2]; + struct software_node_ref_args i2c_ref[1]; + struct software_node_ref_args gpio0_ref[1]; + struct software_node_ref_args gpio1_ref[1]; + struct software_node_ref_args gpio2_ref[1]; + struct software_node_ref_args gpio3_ref[1]; + struct software_node_ref_args gpio4_ref[1]; + struct software_node_ref_args gpio5_ref[1]; + struct software_node_ref_args sfp_ref[1]; + struct software_node swnodes[SWNODE_MAX]; + const struct software_node *group[SWNODE_MAX + 1]; +}; + +struct txgbe { + struct wx *wx; + struct txgbe_nodes nodes; + struct dw_xpcs *xpcs; + struct phylink *phylink; + struct platform_device *sfp_dev; + struct platform_device *i2c_dev; + struct clk_lookup *clock; + struct clk *clk; + struct gpio_chip *gpio; +}; + #endif /* _TXGBE_TYPE_H_ */ diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c index 3e310b55bce2b1dd7d4e14e3c31951fd54d9f7dc..8e32dc50a40808a3718a441c7615ef98fc94ccbf 100644 --- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c @@ -1631,7 +1631,7 @@ static void axienet_pcs_an_restart(struct phylink_pcs *pcs) phylink_mii_c22_pcs_an_restart(pcs_phy); } -static int axienet_pcs_config(struct phylink_pcs *pcs, unsigned int mode, +static int axienet_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode, phy_interface_t interface, const unsigned long *advertising, bool permit_pause_to_mac) @@ -1653,7 +1653,8 @@ static int axienet_pcs_config(struct phylink_pcs *pcs, unsigned int mode, } } - ret = phylink_mii_c22_pcs_config(pcs_phy, mode, interface, advertising); + ret = phylink_mii_c22_pcs_config(pcs_phy, interface, advertising, + neg_mode); if (ret < 0) netdev_warn(ndev, "Failed to configure PCS: %d\n", ret); @@ -2042,6 +2043,11 @@ static int axienet_probe(struct platform_device *pdev) goto cleanup_clk; } + /* Reset core now that clocks are enabled, prior to accessing MDIO */ + ret = __axienet_device_reset(lp); + if (ret) + goto cleanup_clk; + /* Autodetect the need for 64-bit DMA pointers. * When the IP is configured for a bus width bigger than 32 bits, * writing the MSB registers is mandatory, even if they are all 0. @@ -2096,11 +2102,6 @@ static int axienet_probe(struct platform_device *pdev) lp->coalesce_count_tx = XAXIDMA_DFT_TX_THRESHOLD; lp->coalesce_usec_tx = XAXIDMA_DFT_TX_USEC; - /* Reset core now that clocks are enabled, prior to accessing MDIO */ - ret = __axienet_device_reset(lp); - if (ret) - goto cleanup_clk; - ret = axienet_mdio_setup(lp); if (ret) dev_warn(&pdev->dev, @@ -2129,6 +2130,7 @@ static int axienet_probe(struct platform_device *pdev) } of_node_put(np); lp->pcs.ops = &axienet_pcs_ops; + lp->pcs.neg_mode = true; lp->pcs.poll = true; } diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c index 15c7dc82107f45fc068be92b43d29d3ff9d9ee72..acb20ad4e37eb33d3cc76ca5ed1a3963284f94c6 100644 --- a/drivers/net/gtp.c +++ b/drivers/net/gtp.c @@ -631,7 +631,9 @@ static void __gtp_encap_destroy(struct sock *sk) gtp->sk1u = NULL; udp_sk(sk)->encap_type = 0; rcu_assign_sk_user_data(sk, NULL); + release_sock(sk); sock_put(sk); + return; } release_sock(sk); } diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h index 33d51e363913961eeb377a5cb65bbd339966da77..c9dd69dbe1b8fba549a680d7674149999cd19249 100644 --- a/drivers/net/hyperv/hyperv_net.h +++ b/drivers/net/hyperv/hyperv_net.h @@ -74,6 +74,7 @@ struct ndis_recv_scale_cap { /* NDIS_RECEIVE_SCALE_CAPABILITIES */ #define NDIS_RSS_HASH_SECRET_KEY_MAX_SIZE_REVISION_2 40 #define ITAB_NUM 128 +#define ITAB_NUM_MAX 256 struct ndis_recv_scale_param { /* NDIS_RECEIVE_SCALE_PARAMETERS */ struct ndis_obj_header hdr; @@ -1034,7 +1035,9 @@ struct net_device_context { u32 tx_table[VRSS_SEND_TAB_SIZE]; - u16 rx_table[ITAB_NUM]; + u16 *rx_table; + + u32 rx_table_sz; /* Ethtool settings */ u8 duplex; diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c index 0103ff91402454dc9005d26c99273ffce017dcae..3ba3c8fb28a5d692c268b243a2fcfb893a31c36e 100644 --- a/drivers/net/hyperv/netvsc_drv.c +++ b/drivers/net/hyperv/netvsc_drv.c @@ -1747,7 +1747,9 @@ static u32 netvsc_get_rxfh_key_size(struct net_device *dev) static u32 netvsc_rss_indir_size(struct net_device *dev) { - return ITAB_NUM; + struct net_device_context *ndc = netdev_priv(dev); + + return ndc->rx_table_sz; } static int netvsc_get_rxfh(struct net_device *dev, u32 *indir, u8 *key, @@ -1766,7 +1768,7 @@ static int netvsc_get_rxfh(struct net_device *dev, u32 *indir, u8 *key, rndis_dev = ndev->extension; if (indir) { - for (i = 0; i < ITAB_NUM; i++) + for (i = 0; i < ndc->rx_table_sz; i++) indir[i] = ndc->rx_table[i]; } @@ -1792,11 +1794,11 @@ static int netvsc_set_rxfh(struct net_device *dev, const u32 *indir, rndis_dev = ndev->extension; if (indir) { - for (i = 0; i < ITAB_NUM; i++) + for (i = 0; i < ndc->rx_table_sz; i++) if (indir[i] >= ndev->num_chn) return -EINVAL; - for (i = 0; i < ITAB_NUM; i++) + for (i = 0; i < ndc->rx_table_sz; i++) ndc->rx_table[i] = indir[i]; } diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c index eea777ec2541b7d53b4fe52e2dff654e4175ee3d..af95947a87c5525b72f4cbbb634fc1ae7307ca80 100644 --- a/drivers/net/hyperv/rndis_filter.c +++ b/drivers/net/hyperv/rndis_filter.c @@ -21,6 +21,7 @@ #include #include #include +#include #include "hyperv_net.h" #include "netvsc_trace.h" @@ -927,7 +928,7 @@ static int rndis_set_rss_param_msg(struct rndis_device *rdev, struct rndis_set_request *set; struct rndis_set_complete *set_complete; u32 extlen = sizeof(struct ndis_recv_scale_param) + - 4 * ITAB_NUM + NETVSC_HASH_KEYLEN; + 4 * ndc->rx_table_sz + NETVSC_HASH_KEYLEN; struct ndis_recv_scale_param *rssp; u32 *itab; u8 *keyp; @@ -953,7 +954,7 @@ static int rndis_set_rss_param_msg(struct rndis_device *rdev, rssp->hashinfo = NDIS_HASH_FUNC_TOEPLITZ | NDIS_HASH_IPV4 | NDIS_HASH_TCP_IPV4 | NDIS_HASH_IPV6 | NDIS_HASH_TCP_IPV6; - rssp->indirect_tabsize = 4*ITAB_NUM; + rssp->indirect_tabsize = 4 * ndc->rx_table_sz; rssp->indirect_taboffset = sizeof(struct ndis_recv_scale_param); rssp->hashkey_size = NETVSC_HASH_KEYLEN; rssp->hashkey_offset = rssp->indirect_taboffset + @@ -961,7 +962,7 @@ static int rndis_set_rss_param_msg(struct rndis_device *rdev, /* Set indirection table entries */ itab = (u32 *)(rssp + 1); - for (i = 0; i < ITAB_NUM; i++) + for (i = 0; i < ndc->rx_table_sz; i++) itab[i] = ndc->rx_table[i]; /* Set hask key values */ @@ -1548,6 +1549,18 @@ struct netvsc_device *rndis_filter_device_add(struct hv_device *dev, if (ret || rsscap.num_recv_que < 2) goto out; + if (rsscap.num_indirect_tabent && + rsscap.num_indirect_tabent <= ITAB_NUM_MAX) + ndc->rx_table_sz = rsscap.num_indirect_tabent; + else + ndc->rx_table_sz = ITAB_NUM; + + ndc->rx_table = kcalloc(ndc->rx_table_sz, sizeof(u16), GFP_KERNEL); + if (!ndc->rx_table) { + ret = -ENOMEM; + goto err_dev_remv; + } + /* This guarantees that num_possible_rss_qs <= num_online_cpus */ num_possible_rss_qs = min_t(u32, num_online_cpus(), rsscap.num_recv_que); @@ -1558,7 +1571,7 @@ struct netvsc_device *rndis_filter_device_add(struct hv_device *dev, net_device->num_chn = min(net_device->max_chn, device_info->num_chn); if (!netif_is_rxfh_configured(net)) { - for (i = 0; i < ITAB_NUM; i++) + for (i = 0; i < ndc->rx_table_sz; i++) ndc->rx_table[i] = ethtool_rxfh_indir_default( i, net_device->num_chn); } @@ -1596,11 +1609,19 @@ void rndis_filter_device_remove(struct hv_device *dev, struct netvsc_device *net_dev) { struct rndis_device *rndis_dev = net_dev->extension; + struct net_device *net = hv_get_drvdata(dev); + struct net_device_context *ndc; + + ndc = netdev_priv(net); /* Halt and release the rndis device */ rndis_filter_halt_device(net_dev, rndis_dev); netvsc_device_remove(dev); + + ndc->rx_table_sz = 0; + kfree(ndc->rx_table); + ndc->rx_table = NULL; } int rndis_filter_open(struct netvsc_device *nvdev) diff --git a/drivers/net/ieee802154/adf7242.c b/drivers/net/ieee802154/adf7242.c index f9972b8140f9f7f3ba599cc42b2f4db2a6c7434c..a03490ba2e5b38a798fbd6cee5a451d16990de60 100644 --- a/drivers/net/ieee802154/adf7242.c +++ b/drivers/net/ieee802154/adf7242.c @@ -1348,3 +1348,5 @@ module_spi_driver(adf7242_driver); MODULE_AUTHOR("Michael Hennerich "); MODULE_DESCRIPTION("ADF7242 IEEE802.15.4 Transceiver Driver"); MODULE_LICENSE("GPL"); + +MODULE_FIRMWARE(FIRMWARE); diff --git a/drivers/net/ieee802154/ca8210.c b/drivers/net/ieee802154/ca8210.c index 0134ebac227abaff6dda124800ef745019549fcc..f9b10e84de067a1509ede1e95d72ee1f785f6df2 100644 --- a/drivers/net/ieee802154/ca8210.c +++ b/drivers/net/ieee802154/ca8210.c @@ -2855,7 +2855,6 @@ static int ca8210_interrupt_init(struct spi_device *spi) ); if (ret) { dev_crit(&spi->dev, "request_irq %d failed\n", pdata->irq_id); - gpiod_unexport(gpio_to_desc(pdata->gpio_irq)); gpio_free(pdata->gpio_irq); } @@ -2945,7 +2944,8 @@ static void ca8210_hw_setup(struct ieee802154_hw *ca8210_hw) ca8210_hw->phy->flags = WPAN_PHY_FLAG_TXPOWER | WPAN_PHY_FLAG_CCA_ED_LEVEL | - WPAN_PHY_FLAG_CCA_MODE; + WPAN_PHY_FLAG_CCA_MODE | + WPAN_PHY_FLAG_DATAGRAMS_ONLY; } /** diff --git a/drivers/net/ieee802154/mac802154_hwsim.c b/drivers/net/ieee802154/mac802154_hwsim.c index 8445c2189d11664ab4910cc8f03e622790ba7b06..31cba9aa76366467aeb7175bb8b02cf60e77f133 100644 --- a/drivers/net/ieee802154/mac802154_hwsim.c +++ b/drivers/net/ieee802154/mac802154_hwsim.c @@ -685,7 +685,7 @@ static int hwsim_del_edge_nl(struct sk_buff *msg, struct genl_info *info) static int hwsim_set_edge_lqi(struct sk_buff *msg, struct genl_info *info) { struct nlattr *edge_attrs[MAC802154_HWSIM_EDGE_ATTR_MAX + 1]; - struct hwsim_edge_info *einfo; + struct hwsim_edge_info *einfo, *einfo_old; struct hwsim_phy *phy_v0; struct hwsim_edge *e; u32 v0, v1; @@ -723,8 +723,10 @@ static int hwsim_set_edge_lqi(struct sk_buff *msg, struct genl_info *info) list_for_each_entry_rcu(e, &phy_v0->edges, list) { if (e->endpoint->idx == v1) { einfo->lqi = lqi; - rcu_assign_pointer(e->info, einfo); + einfo_old = rcu_replace_pointer(e->info, einfo, + lockdep_is_held(&hwsim_phys_lock)); rcu_read_unlock(); + kfree_rcu(einfo_old, rcu); mutex_unlock(&hwsim_phys_lock); return 0; } diff --git a/drivers/net/ipvlan/ipvlan_core.c b/drivers/net/ipvlan/ipvlan_core.c index ab5133eb1d51783efdab2542265b4e0293e59af9..c0c49f1813673acebdae2f3f52259fb6b9678c36 100644 --- a/drivers/net/ipvlan/ipvlan_core.c +++ b/drivers/net/ipvlan/ipvlan_core.c @@ -555,8 +555,7 @@ static void ipvlan_multicast_enqueue(struct ipvl_port *port, spin_lock(&port->backlog.lock); if (skb_queue_len(&port->backlog) < IPVLAN_QBACKLOG_LIMIT) { - if (skb->dev) - dev_hold(skb->dev); + dev_hold(skb->dev); __skb_queue_tail(&port->backlog, skb); spin_unlock(&port->backlog.lock); schedule_work(&port->wq); @@ -585,7 +584,8 @@ static int ipvlan_xmit_mode_l3(struct sk_buff *skb, struct net_device *dev) consume_skb(skb); return NET_XMIT_DROP; } - return ipvlan_rcv_frame(addr, &skb, true); + ipvlan_rcv_frame(addr, &skb, true); + return NET_XMIT_SUCCESS; } } out: @@ -611,7 +611,8 @@ static int ipvlan_xmit_mode_l2(struct sk_buff *skb, struct net_device *dev) consume_skb(skb); return NET_XMIT_DROP; } - return ipvlan_rcv_frame(addr, &skb, true); + ipvlan_rcv_frame(addr, &skb, true); + return NET_XMIT_SUCCESS; } } skb = skb_share_check(skb, GFP_ATOMIC); @@ -623,7 +624,8 @@ static int ipvlan_xmit_mode_l2(struct sk_buff *skb, struct net_device *dev) * the skb for the main-dev. At the RX side we just return * RX_PASS for it to be processed further on the stack. */ - return dev_forward_skb(ipvlan->phy_dev, skb); + dev_forward_skb(ipvlan->phy_dev, skb); + return NET_XMIT_SUCCESS; } else if (is_multicast_ether_addr(eth->h_dest)) { skb_reset_mac_header(skb); diff --git a/drivers/net/mctp/mctp-i2c.c b/drivers/net/mctp/mctp-i2c.c index 1d67a3ca1fd1168979c1912eb48c52751a6b7380..b37a9e4bade4a00254f07241861dcf716283646a 100644 --- a/drivers/net/mctp/mctp-i2c.c +++ b/drivers/net/mctp/mctp-i2c.c @@ -1058,7 +1058,7 @@ static struct i2c_driver mctp_i2c_driver = { .name = "mctp-i2c-interface", .of_match_table = mctp_i2c_of_match, }, - .probe_new = mctp_i2c_probe, + .probe = mctp_i2c_probe, .remove = mctp_i2c_remove, .id_table = mctp_i2c_id, }; diff --git a/drivers/net/mdio/Kconfig b/drivers/net/mdio/Kconfig index 9ff2e6f22f3f6b335177e026e84fa36e774b5a4a..4a7a303be2f7444223554a64ae6006d293fea89d 100644 --- a/drivers/net/mdio/Kconfig +++ b/drivers/net/mdio/Kconfig @@ -185,6 +185,17 @@ config MDIO_IPQ8064 This driver supports the MDIO interface found in the network interface units of the IPQ8064 SoC +config MDIO_REGMAP + tristate + help + This driver allows using MDIO devices that are not sitting on a + regular MDIO bus, but still exposes the standard 802.3 register + layout. It's regmap-based so that it can be used on integrated, + memory-mapped PHYs, SPI PHYs and so on. A new virtual MDIO bus is + created, and its read/write operations are mapped to the underlying + regmap. Users willing to use this driver must explicitly select + REGMAP. + config MDIO_THUNDER tristate "ThunderX SOCs MDIO buses" depends on 64BIT diff --git a/drivers/net/mdio/Makefile b/drivers/net/mdio/Makefile index 7d4cb4c11e4ec105ff3fb7553669aa4891ae5d00..1015f0db4531dba5c0da0bcabfc877aaaa67d78a 100644 --- a/drivers/net/mdio/Makefile +++ b/drivers/net/mdio/Makefile @@ -19,6 +19,7 @@ obj-$(CONFIG_MDIO_MOXART) += mdio-moxart.o obj-$(CONFIG_MDIO_MSCC_MIIM) += mdio-mscc-miim.o obj-$(CONFIG_MDIO_MVUSB) += mdio-mvusb.o obj-$(CONFIG_MDIO_OCTEON) += mdio-octeon.o +obj-$(CONFIG_MDIO_REGMAP) += mdio-regmap.o obj-$(CONFIG_MDIO_SUN4I) += mdio-sun4i.o obj-$(CONFIG_MDIO_THUNDER) += mdio-thunder.o obj-$(CONFIG_MDIO_XGENE) += mdio-xgene.o diff --git a/drivers/net/mdio/mdio-mux-mmioreg.c b/drivers/net/mdio/mdio-mux-mmioreg.c index c02c9c66001696c709e354f35f4a875cdf6869ae..09af150ed77413331a8b2a15002b9a10c900db3d 100644 --- a/drivers/net/mdio/mdio-mux-mmioreg.c +++ b/drivers/net/mdio/mdio-mux-mmioreg.c @@ -140,14 +140,15 @@ static int mdio_mux_mmioreg_probe(struct platform_device *pdev) * set any bits outside of the 'mask'. */ for_each_available_child_of_node(np, np2) { - iprop = of_get_property(np2, "reg", &len); - if (!iprop || len != sizeof(uint32_t)) { + u64 reg; + + if (of_property_read_reg(np2, 0, ®, NULL)) { dev_err(&pdev->dev, "mdio-mux child node %pOF is " "missing a 'reg' property\n", np2); of_node_put(np2); return -ENODEV; } - if (be32_to_cpup(iprop) & ~s->mask) { + if ((u32)reg & ~s->mask) { dev_err(&pdev->dev, "mdio-mux child node %pOF has " "a 'reg' value with unmasked bits\n", np2); diff --git a/drivers/net/mdio/mdio-regmap.c b/drivers/net/mdio/mdio-regmap.c new file mode 100644 index 0000000000000000000000000000000000000000..8a742a8d6387dabae22884a14589e2bea6e18bdf --- /dev/null +++ b/drivers/net/mdio/mdio-regmap.c @@ -0,0 +1,93 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* Driver for MMIO-Mapped MDIO devices. Some IPs expose internal PHYs or PCS + * within the MMIO-mapped area + * + * Copyright (C) 2023 Maxime Chevallier + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRV_NAME "mdio-regmap" + +struct mdio_regmap_priv { + struct regmap *regmap; + u8 valid_addr; +}; + +static int mdio_regmap_read_c22(struct mii_bus *bus, int addr, int regnum) +{ + struct mdio_regmap_priv *ctx = bus->priv; + unsigned int val; + int ret; + + if (ctx->valid_addr != addr) + return -ENODEV; + + ret = regmap_read(ctx->regmap, regnum, &val); + if (ret < 0) + return ret; + + return val; +} + +static int mdio_regmap_write_c22(struct mii_bus *bus, int addr, int regnum, + u16 val) +{ + struct mdio_regmap_priv *ctx = bus->priv; + + if (ctx->valid_addr != addr) + return -ENODEV; + + return regmap_write(ctx->regmap, regnum, val); +} + +struct mii_bus *devm_mdio_regmap_register(struct device *dev, + const struct mdio_regmap_config *config) +{ + struct mdio_regmap_priv *mr; + struct mii_bus *mii; + int rc; + + if (!config->parent) + return ERR_PTR(-EINVAL); + + mii = devm_mdiobus_alloc_size(config->parent, sizeof(*mr)); + if (!mii) + return ERR_PTR(-ENOMEM); + + mr = mii->priv; + mr->regmap = config->regmap; + mr->valid_addr = config->valid_addr; + + mii->name = DRV_NAME; + strscpy(mii->id, config->name, MII_BUS_ID_SIZE); + mii->parent = config->parent; + mii->read = mdio_regmap_read_c22; + mii->write = mdio_regmap_write_c22; + + if (config->autoscan) + mii->phy_mask = ~BIT(config->valid_addr); + else + mii->phy_mask = ~0; + + rc = devm_mdiobus_register(dev, mii); + if (rc) { + dev_err(config->parent, "Cannot register MDIO bus![%s] (%d)\n", mii->id, rc); + return ERR_PTR(rc); + } + + return mii; +} +EXPORT_SYMBOL_GPL(devm_mdio_regmap_register); + +MODULE_DESCRIPTION("MDIO API over regmap"); +MODULE_AUTHOR("Maxime Chevallier "); +MODULE_LICENSE("GPL"); diff --git a/drivers/net/netdevsim/dev.c b/drivers/net/netdevsim/dev.c index 6045bece2654d69ab7af7fffd787c271caaa6d26..b4d3b9cde8bd685202f135cf9c845d1be76ef428 100644 --- a/drivers/net/netdevsim/dev.c +++ b/drivers/net/netdevsim/dev.c @@ -184,13 +184,10 @@ static ssize_t nsim_dev_trap_fa_cookie_write(struct file *file, cookie_len = (count - 1) / 2; if ((count - 1) % 2) return -EINVAL; - buf = kmalloc(count, GFP_KERNEL | __GFP_NOWARN); - if (!buf) - return -ENOMEM; - ret = simple_write_to_buffer(buf, count, ppos, data, count); - if (ret < 0) - goto free_buf; + buf = memdup_user(data, count); + if (IS_ERR(buf)) + return PTR_ERR(buf); fa_cookie = kmalloc(sizeof(*fa_cookie) + cookie_len, GFP_KERNEL | __GFP_NOWARN); diff --git a/drivers/net/ntb_netdev.c b/drivers/net/ntb_netdev.c index 85dbe7f73e3194443ab42b75b9a192c232a0bcc1..536bd6564f8b8a44993b50b63e3e175cf5d0c22c 100644 --- a/drivers/net/ntb_netdev.c +++ b/drivers/net/ntb_netdev.c @@ -493,7 +493,7 @@ static int __init ntb_netdev_init_module(void) return 0; } -module_init(ntb_netdev_init_module); +late_initcall(ntb_netdev_init_module); static void __exit ntb_netdev_exit_module(void) { diff --git a/drivers/net/pcs/Kconfig b/drivers/net/pcs/Kconfig index 7c34fb7cbf7b431050c7ebe7ba8440d820e476b3..87cf308fc6d8b682a245f21aee7b96cc78861fbf 100644 --- a/drivers/net/pcs/Kconfig +++ b/drivers/net/pcs/Kconfig @@ -33,10 +33,4 @@ config PCS_RZN1_MIIC on RZ/N1 SoCs. This PCS converts MII to RMII/RGMII or can be set in pass-through mode for MII. -config PCS_ALTERA_TSE - tristate - help - This module provides helper functions for the Altera Triple Speed - Ethernet SGMII PCS, that can be found on the Intel Socfpga family. - endmenu diff --git a/drivers/net/pcs/Makefile b/drivers/net/pcs/Makefile index 9b9afd6b1c22d7b3e79e0c403104605dd1fa9b04..ea662a7989b29d09260a1b43ab338bef1ad0a40f 100644 --- a/drivers/net/pcs/Makefile +++ b/drivers/net/pcs/Makefile @@ -7,4 +7,3 @@ obj-$(CONFIG_PCS_XPCS) += pcs_xpcs.o obj-$(CONFIG_PCS_LYNX) += pcs-lynx.o obj-$(CONFIG_PCS_MTK_LYNXI) += pcs-mtk-lynxi.o obj-$(CONFIG_PCS_RZN1_MIIC) += pcs-rzn1-miic.o -obj-$(CONFIG_PCS_ALTERA_TSE) += pcs-altera-tse.o diff --git a/drivers/net/pcs/pcs-altera-tse.c b/drivers/net/pcs/pcs-altera-tse.c deleted file mode 100644 index d616749761f41129b90a4e77c8b308ce658ca07e..0000000000000000000000000000000000000000 --- a/drivers/net/pcs/pcs-altera-tse.c +++ /dev/null @@ -1,160 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright (C) 2022 Bootlin - * - * Maxime Chevallier - */ - -#include -#include -#include -#include - -/* SGMII PCS register addresses - */ -#define SGMII_PCS_LINK_TIMER_0 0x12 -#define SGMII_PCS_LINK_TIMER_1 0x13 -#define SGMII_PCS_IF_MODE 0x14 -#define PCS_IF_MODE_SGMII_ENA BIT(0) -#define PCS_IF_MODE_USE_SGMII_AN BIT(1) -#define PCS_IF_MODE_SGMI_HALF_DUPLEX BIT(4) -#define PCS_IF_MODE_SGMI_PHY_AN BIT(5) -#define SGMII_PCS_SW_RESET_TIMEOUT 100 /* usecs */ - -struct altera_tse_pcs { - struct phylink_pcs pcs; - void __iomem *base; - int reg_width; -}; - -static struct altera_tse_pcs *phylink_pcs_to_tse_pcs(struct phylink_pcs *pcs) -{ - return container_of(pcs, struct altera_tse_pcs, pcs); -} - -static u16 tse_pcs_read(struct altera_tse_pcs *tse_pcs, int regnum) -{ - if (tse_pcs->reg_width == 4) - return readl(tse_pcs->base + regnum * 4); - else - return readw(tse_pcs->base + regnum * 2); -} - -static void tse_pcs_write(struct altera_tse_pcs *tse_pcs, int regnum, - u16 value) -{ - if (tse_pcs->reg_width == 4) - writel(value, tse_pcs->base + regnum * 4); - else - writew(value, tse_pcs->base + regnum * 2); -} - -static int tse_pcs_reset(struct altera_tse_pcs *tse_pcs) -{ - u16 bmcr; - - /* Reset PCS block */ - bmcr = tse_pcs_read(tse_pcs, MII_BMCR); - bmcr |= BMCR_RESET; - tse_pcs_write(tse_pcs, MII_BMCR, bmcr); - - return read_poll_timeout(tse_pcs_read, bmcr, (bmcr & BMCR_RESET), - 10, SGMII_PCS_SW_RESET_TIMEOUT, 1, - tse_pcs, MII_BMCR); -} - -static int alt_tse_pcs_validate(struct phylink_pcs *pcs, - unsigned long *supported, - const struct phylink_link_state *state) -{ - if (state->interface == PHY_INTERFACE_MODE_SGMII || - state->interface == PHY_INTERFACE_MODE_1000BASEX) - return 1; - - return -EINVAL; -} - -static int alt_tse_pcs_config(struct phylink_pcs *pcs, unsigned int mode, - phy_interface_t interface, - const unsigned long *advertising, - bool permit_pause_to_mac) -{ - struct altera_tse_pcs *tse_pcs = phylink_pcs_to_tse_pcs(pcs); - u32 ctrl, if_mode; - - ctrl = tse_pcs_read(tse_pcs, MII_BMCR); - if_mode = tse_pcs_read(tse_pcs, SGMII_PCS_IF_MODE); - - /* Set link timer to 1.6ms, as per the MegaCore Function User Guide */ - tse_pcs_write(tse_pcs, SGMII_PCS_LINK_TIMER_0, 0x0D40); - tse_pcs_write(tse_pcs, SGMII_PCS_LINK_TIMER_1, 0x03); - - if (interface == PHY_INTERFACE_MODE_SGMII) { - if_mode |= PCS_IF_MODE_USE_SGMII_AN | PCS_IF_MODE_SGMII_ENA; - } else if (interface == PHY_INTERFACE_MODE_1000BASEX) { - if_mode &= ~(PCS_IF_MODE_USE_SGMII_AN | PCS_IF_MODE_SGMII_ENA); - } - - ctrl |= (BMCR_SPEED1000 | BMCR_FULLDPLX | BMCR_ANENABLE); - - tse_pcs_write(tse_pcs, MII_BMCR, ctrl); - tse_pcs_write(tse_pcs, SGMII_PCS_IF_MODE, if_mode); - - return tse_pcs_reset(tse_pcs); -} - -static void alt_tse_pcs_get_state(struct phylink_pcs *pcs, - struct phylink_link_state *state) -{ - struct altera_tse_pcs *tse_pcs = phylink_pcs_to_tse_pcs(pcs); - u16 bmsr, lpa; - - bmsr = tse_pcs_read(tse_pcs, MII_BMSR); - lpa = tse_pcs_read(tse_pcs, MII_LPA); - - phylink_mii_c22_pcs_decode_state(state, bmsr, lpa); -} - -static void alt_tse_pcs_an_restart(struct phylink_pcs *pcs) -{ - struct altera_tse_pcs *tse_pcs = phylink_pcs_to_tse_pcs(pcs); - u16 bmcr; - - bmcr = tse_pcs_read(tse_pcs, MII_BMCR); - bmcr |= BMCR_ANRESTART; - tse_pcs_write(tse_pcs, MII_BMCR, bmcr); - - /* This PCS seems to require a soft reset to re-sync the AN logic */ - tse_pcs_reset(tse_pcs); -} - -static const struct phylink_pcs_ops alt_tse_pcs_ops = { - .pcs_validate = alt_tse_pcs_validate, - .pcs_get_state = alt_tse_pcs_get_state, - .pcs_config = alt_tse_pcs_config, - .pcs_an_restart = alt_tse_pcs_an_restart, -}; - -struct phylink_pcs *alt_tse_pcs_create(struct net_device *ndev, - void __iomem *pcs_base, int reg_width) -{ - struct altera_tse_pcs *tse_pcs; - - if (reg_width != 4 && reg_width != 2) - return ERR_PTR(-EINVAL); - - tse_pcs = devm_kzalloc(&ndev->dev, sizeof(*tse_pcs), GFP_KERNEL); - if (!tse_pcs) - return ERR_PTR(-ENOMEM); - - tse_pcs->pcs.ops = &alt_tse_pcs_ops; - tse_pcs->base = pcs_base; - tse_pcs->reg_width = reg_width; - - return &tse_pcs->pcs; -} -EXPORT_SYMBOL_GPL(alt_tse_pcs_create); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Altera TSE PCS driver"); -MODULE_AUTHOR("Maxime Chevallier "); diff --git a/drivers/net/pcs/pcs-lynx.c b/drivers/net/pcs/pcs-lynx.c index 622c3de3f3a8b4b252d8a76d79362509e14f2c3f..9021b96d4f9df1fb1ccfc3b942e107ee72bb496c 100644 --- a/drivers/net/pcs/pcs-lynx.c +++ b/drivers/net/pcs/pcs-lynx.c @@ -6,6 +6,7 @@ #include #include #include +#include #define SGMII_CLOCK_PERIOD_NS 8 /* PCS is clocked at 125 MHz */ #define LINK_TIMER_VAL(ns) ((u32)((ns) / SGMII_CLOCK_PERIOD_NS)) @@ -34,14 +35,6 @@ enum sgmii_speed { #define phylink_pcs_to_lynx(pl_pcs) container_of((pl_pcs), struct lynx_pcs, pcs) #define lynx_to_phylink_pcs(lynx) (&(lynx)->pcs) -struct mdio_device *lynx_get_mdio_device(struct phylink_pcs *pcs) -{ - struct lynx_pcs *lynx = phylink_pcs_to_lynx(pcs); - - return lynx->mdio; -} -EXPORT_SYMBOL(lynx_get_mdio_device); - static void lynx_pcs_get_state_usxgmii(struct mdio_device *pcs, struct phylink_link_state *state) { @@ -119,9 +112,10 @@ static void lynx_pcs_get_state(struct phylink_pcs *pcs, state->link, state->an_complete); } -static int lynx_pcs_config_giga(struct mdio_device *pcs, unsigned int mode, +static int lynx_pcs_config_giga(struct mdio_device *pcs, phy_interface_t interface, - const unsigned long *advertising) + const unsigned long *advertising, + unsigned int neg_mode) { int link_timer_ns; u32 link_timer; @@ -139,8 +133,9 @@ static int lynx_pcs_config_giga(struct mdio_device *pcs, unsigned int mode, if (interface == PHY_INTERFACE_MODE_1000BASEX) { if_mode = 0; } else { + /* SGMII and QSGMII */ if_mode = IF_MODE_SGMII_EN; - if (mode == MLO_AN_INBAND) + if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED) if_mode |= IF_MODE_USE_SGMII_AN; } @@ -150,16 +145,18 @@ static int lynx_pcs_config_giga(struct mdio_device *pcs, unsigned int mode, if (err) return err; - return phylink_mii_c22_pcs_config(pcs, mode, interface, advertising); + return phylink_mii_c22_pcs_config(pcs, interface, advertising, + neg_mode); } -static int lynx_pcs_config_usxgmii(struct mdio_device *pcs, unsigned int mode, - const unsigned long *advertising) +static int lynx_pcs_config_usxgmii(struct mdio_device *pcs, + const unsigned long *advertising, + unsigned int neg_mode) { struct mii_bus *bus = pcs->bus; int addr = pcs->addr; - if (!phylink_autoneg_inband(mode)) { + if (neg_mode != PHYLINK_PCS_NEG_INBAND_ENABLED) { dev_err(&pcs->dev, "USXGMII only supports in-band AN for now\n"); return -EOPNOTSUPP; } @@ -171,10 +168,9 @@ static int lynx_pcs_config_usxgmii(struct mdio_device *pcs, unsigned int mode, ADVERTISE_SGMII | ADVERTISE_LPACK); } -static int lynx_pcs_config(struct phylink_pcs *pcs, unsigned int mode, +static int lynx_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode, phy_interface_t ifmode, - const unsigned long *advertising, - bool permit) + const unsigned long *advertising, bool permit) { struct lynx_pcs *lynx = phylink_pcs_to_lynx(pcs); @@ -182,17 +178,18 @@ static int lynx_pcs_config(struct phylink_pcs *pcs, unsigned int mode, case PHY_INTERFACE_MODE_1000BASEX: case PHY_INTERFACE_MODE_SGMII: case PHY_INTERFACE_MODE_QSGMII: - return lynx_pcs_config_giga(lynx->mdio, mode, ifmode, - advertising); + return lynx_pcs_config_giga(lynx->mdio, ifmode, advertising, + neg_mode); case PHY_INTERFACE_MODE_2500BASEX: - if (phylink_autoneg_inband(mode)) { + if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED) { dev_err(&lynx->mdio->dev, "AN not supported on 3.125GHz SerDes lane\n"); return -EOPNOTSUPP; } break; case PHY_INTERFACE_MODE_USXGMII: - return lynx_pcs_config_usxgmii(lynx->mdio, mode, advertising); + return lynx_pcs_config_usxgmii(lynx->mdio, advertising, + neg_mode); case PHY_INTERFACE_MODE_10GBASER: /* Nothing to do here for 10GBASER */ break; @@ -210,7 +207,8 @@ static void lynx_pcs_an_restart(struct phylink_pcs *pcs) phylink_mii_c22_pcs_an_restart(lynx->mdio); } -static void lynx_pcs_link_up_sgmii(struct mdio_device *pcs, unsigned int mode, +static void lynx_pcs_link_up_sgmii(struct mdio_device *pcs, + unsigned int neg_mode, int speed, int duplex) { u16 if_mode = 0, sgmii_speed; @@ -218,7 +216,7 @@ static void lynx_pcs_link_up_sgmii(struct mdio_device *pcs, unsigned int mode, /* The PCS needs to be configured manually only * when not operating on in-band mode */ - if (mode == MLO_AN_INBAND) + if (neg_mode != PHYLINK_PCS_NEG_INBAND_ENABLED) return; if (duplex == DUPLEX_HALF) @@ -265,12 +263,12 @@ static void lynx_pcs_link_up_sgmii(struct mdio_device *pcs, unsigned int mode, * 2500 Mbps and we do rate adaptation through pause frames. */ static void lynx_pcs_link_up_2500basex(struct mdio_device *pcs, - unsigned int mode, + unsigned int neg_mode, int speed, int duplex) { u16 if_mode = 0; - if (mode == MLO_AN_INBAND) { + if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED) { dev_err(&pcs->dev, "AN not supported for 2500BaseX\n"); return; } @@ -284,7 +282,7 @@ static void lynx_pcs_link_up_2500basex(struct mdio_device *pcs, if_mode); } -static void lynx_pcs_link_up(struct phylink_pcs *pcs, unsigned int mode, +static void lynx_pcs_link_up(struct phylink_pcs *pcs, unsigned int neg_mode, phy_interface_t interface, int speed, int duplex) { @@ -293,10 +291,10 @@ static void lynx_pcs_link_up(struct phylink_pcs *pcs, unsigned int mode, switch (interface) { case PHY_INTERFACE_MODE_SGMII: case PHY_INTERFACE_MODE_QSGMII: - lynx_pcs_link_up_sgmii(lynx->mdio, mode, speed, duplex); + lynx_pcs_link_up_sgmii(lynx->mdio, neg_mode, speed, duplex); break; case PHY_INTERFACE_MODE_2500BASEX: - lynx_pcs_link_up_2500basex(lynx->mdio, mode, speed, duplex); + lynx_pcs_link_up_2500basex(lynx->mdio, neg_mode, speed, duplex); break; case PHY_INTERFACE_MODE_USXGMII: /* At the moment, only in-band AN is supported for USXGMII @@ -315,26 +313,87 @@ static const struct phylink_pcs_ops lynx_pcs_phylink_ops = { .pcs_link_up = lynx_pcs_link_up, }; -struct phylink_pcs *lynx_pcs_create(struct mdio_device *mdio) +static struct phylink_pcs *lynx_pcs_create(struct mdio_device *mdio) { struct lynx_pcs *lynx; lynx = kzalloc(sizeof(*lynx), GFP_KERNEL); if (!lynx) - return NULL; + return ERR_PTR(-ENOMEM); + mdio_device_get(mdio); lynx->mdio = mdio; lynx->pcs.ops = &lynx_pcs_phylink_ops; + lynx->pcs.neg_mode = true; lynx->pcs.poll = true; return lynx_to_phylink_pcs(lynx); } -EXPORT_SYMBOL(lynx_pcs_create); + +struct phylink_pcs *lynx_pcs_create_mdiodev(struct mii_bus *bus, int addr) +{ + struct mdio_device *mdio; + struct phylink_pcs *pcs; + + mdio = mdio_device_create(bus, addr); + if (IS_ERR(mdio)) + return ERR_CAST(mdio); + + pcs = lynx_pcs_create(mdio); + + /* lynx_create() has taken a refcount on the mdiodev if it was + * successful. If lynx_create() fails, this will free the mdio + * device here. In any case, we don't need to hold our reference + * anymore, and putting it here will allow mdio_device_put() in + * lynx_destroy() to automatically free the mdio device. + */ + mdio_device_put(mdio); + + return pcs; +} +EXPORT_SYMBOL(lynx_pcs_create_mdiodev); + +/* + * lynx_pcs_create_fwnode() creates a lynx PCS instance from the fwnode + * device indicated by node. + * + * Returns: + * -ENODEV if the fwnode is marked unavailable + * -EPROBE_DEFER if we fail to find the device + * -ENOMEM if we fail to allocate memory + * pointer to a phylink_pcs on success + */ +struct phylink_pcs *lynx_pcs_create_fwnode(struct fwnode_handle *node) +{ + struct mdio_device *mdio; + struct phylink_pcs *pcs; + + if (!fwnode_device_is_available(node)) + return ERR_PTR(-ENODEV); + + mdio = fwnode_mdio_find_device(node); + if (!mdio) + return ERR_PTR(-EPROBE_DEFER); + + pcs = lynx_pcs_create(mdio); + + /* lynx_create() has taken a refcount on the mdiodev if it was + * successful. If lynx_create() fails, this will free the mdio + * device here. In any case, we don't need to hold our reference + * anymore, and putting it here will allow mdio_device_put() in + * lynx_destroy() to automatically free the mdio device. + */ + mdio_device_put(mdio); + + return pcs; +} +EXPORT_SYMBOL_GPL(lynx_pcs_create_fwnode); void lynx_pcs_destroy(struct phylink_pcs *pcs) { struct lynx_pcs *lynx = phylink_pcs_to_lynx(pcs); + mdio_device_put(lynx->mdio); kfree(lynx); } EXPORT_SYMBOL(lynx_pcs_destroy); diff --git a/drivers/net/pcs/pcs-mtk-lynxi.c b/drivers/net/pcs/pcs-mtk-lynxi.c index 888452325edc4884227b97b159e40082678c1d84..b0f3ede945d96cda528e028d5f9d01d770b67351 100644 --- a/drivers/net/pcs/pcs-mtk-lynxi.c +++ b/drivers/net/pcs/pcs-mtk-lynxi.c @@ -102,13 +102,13 @@ static void mtk_pcs_lynxi_get_state(struct phylink_pcs *pcs, FIELD_GET(SGMII_LPA, adv)); } -static int mtk_pcs_lynxi_config(struct phylink_pcs *pcs, unsigned int mode, +static int mtk_pcs_lynxi_config(struct phylink_pcs *pcs, unsigned int neg_mode, phy_interface_t interface, const unsigned long *advertising, bool permit_pause_to_mac) { struct mtk_pcs_lynxi *mpcs = pcs_to_mtk_pcs_lynxi(pcs); - bool mode_changed = false, changed, use_an; + bool mode_changed = false, changed; unsigned int rgc3, sgm_mode, bmcr; int advertise, link_timer; @@ -121,30 +121,21 @@ static int mtk_pcs_lynxi_config(struct phylink_pcs *pcs, unsigned int mode, * we assume that fixes it's speed at bitrate = line rate (in * other words, 1000Mbps or 2500Mbps). */ - if (interface == PHY_INTERFACE_MODE_SGMII) { + if (interface == PHY_INTERFACE_MODE_SGMII) sgm_mode = SGMII_IF_MODE_SGMII; - if (phylink_autoneg_inband(mode)) { - sgm_mode |= SGMII_REMOTE_FAULT_DIS | - SGMII_SPEED_DUPLEX_AN; - use_an = true; - } else { - use_an = false; - } - } else if (phylink_autoneg_inband(mode)) { - /* 1000base-X or 2500base-X autoneg */ - sgm_mode = SGMII_REMOTE_FAULT_DIS; - use_an = linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, - advertising); - } else { - /* 1000base-X or 2500base-X without autoneg */ + else sgm_mode = 0; - use_an = false; - } - if (use_an) + if (neg_mode & PHYLINK_PCS_NEG_INBAND) + sgm_mode |= SGMII_REMOTE_FAULT_DIS; + + if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED) { + if (interface == PHY_INTERFACE_MODE_SGMII) + sgm_mode |= SGMII_SPEED_DUPLEX_AN; bmcr = BMCR_ANENABLE; - else + } else { bmcr = 0; + } if (mpcs->interface != interface) { link_timer = phylink_get_link_timer_ns(interface); @@ -216,14 +207,15 @@ static void mtk_pcs_lynxi_restart_an(struct phylink_pcs *pcs) regmap_set_bits(mpcs->regmap, SGMSYS_PCS_CONTROL_1, BMCR_ANRESTART); } -static void mtk_pcs_lynxi_link_up(struct phylink_pcs *pcs, unsigned int mode, +static void mtk_pcs_lynxi_link_up(struct phylink_pcs *pcs, + unsigned int neg_mode, phy_interface_t interface, int speed, int duplex) { struct mtk_pcs_lynxi *mpcs = pcs_to_mtk_pcs_lynxi(pcs); unsigned int sgm_mode; - if (!phylink_autoneg_inband(mode)) { + if (neg_mode != PHYLINK_PCS_NEG_INBAND_ENABLED) { /* Force the speed and duplex setting */ if (speed == SPEED_10) sgm_mode = SGMII_SPEED_10; @@ -286,6 +278,7 @@ struct phylink_pcs *mtk_pcs_lynxi_create(struct device *dev, mpcs->regmap = regmap; mpcs->flags = flags; mpcs->pcs.ops = &mtk_pcs_lynxi_ops; + mpcs->pcs.neg_mode = true; mpcs->pcs.poll = true; mpcs->interface = PHY_INTERFACE_MODE_NA; diff --git a/drivers/net/pcs/pcs-xpcs.c b/drivers/net/pcs/pcs-xpcs.c index 72f25e778840f9330ca862e611732aabd11c340c..44b0376468653a445e05d478213f0f23f8a98b93 100644 --- a/drivers/net/pcs/pcs-xpcs.c +++ b/drivers/net/pcs/pcs-xpcs.c @@ -64,6 +64,16 @@ static const int xpcs_xlgmii_features[] = { __ETHTOOL_LINK_MODE_MASK_NBITS, }; +static const int xpcs_10gbaser_features[] = { + ETHTOOL_LINK_MODE_Pause_BIT, + ETHTOOL_LINK_MODE_Asym_Pause_BIT, + ETHTOOL_LINK_MODE_10000baseSR_Full_BIT, + ETHTOOL_LINK_MODE_10000baseLR_Full_BIT, + ETHTOOL_LINK_MODE_10000baseLRM_Full_BIT, + ETHTOOL_LINK_MODE_10000baseER_Full_BIT, + __ETHTOOL_LINK_MODE_MASK_NBITS, +}; + static const int xpcs_sgmii_features[] = { ETHTOOL_LINK_MODE_Pause_BIT, ETHTOOL_LINK_MODE_Asym_Pause_BIT, @@ -106,6 +116,10 @@ static const phy_interface_t xpcs_xlgmii_interfaces[] = { PHY_INTERFACE_MODE_XLGMII, }; +static const phy_interface_t xpcs_10gbaser_interfaces[] = { + PHY_INTERFACE_MODE_10GBASER, +}; + static const phy_interface_t xpcs_sgmii_interfaces[] = { PHY_INTERFACE_MODE_SGMII, }; @@ -123,6 +137,7 @@ enum { DW_XPCS_USXGMII, DW_XPCS_10GKR, DW_XPCS_XLGMII, + DW_XPCS_10GBASER, DW_XPCS_SGMII, DW_XPCS_1000BASEX, DW_XPCS_2500BASEX, @@ -246,6 +261,7 @@ static int xpcs_soft_reset(struct dw_xpcs *xpcs, switch (compat->an_mode) { case DW_AN_C73: + case DW_10GBASER: dev = MDIO_MMD_PCS; break; case DW_AN_C37_SGMII: @@ -271,15 +287,12 @@ static int xpcs_soft_reset(struct dw_xpcs *xpcs, }) static int xpcs_read_fault_c73(struct dw_xpcs *xpcs, - struct phylink_link_state *state) + struct phylink_link_state *state, + u16 pcs_stat1) { int ret; - ret = xpcs_read(xpcs, MDIO_MMD_PCS, MDIO_STAT1); - if (ret < 0) - return ret; - - if (ret & MDIO_STAT1_FAULT) { + if (pcs_stat1 & MDIO_STAT1_FAULT) { xpcs_warn(xpcs, state, "Link fault condition detected!\n"); return -EFAULT; } @@ -321,37 +334,6 @@ static int xpcs_read_fault_c73(struct dw_xpcs *xpcs, return 0; } -static int xpcs_read_link_c73(struct dw_xpcs *xpcs) -{ - bool link = true; - int ret; - - ret = xpcs_read(xpcs, MDIO_MMD_PCS, MDIO_STAT1); - if (ret < 0) - return ret; - - if (!(ret & MDIO_STAT1_LSTATUS)) - link = false; - - return link; -} - -static int xpcs_get_max_usxgmii_speed(const unsigned long *supported) -{ - int max = SPEED_UNKNOWN; - - if (phylink_test(supported, 1000baseKX_Full)) - max = SPEED_1000; - if (phylink_test(supported, 2500baseX_Full)) - max = SPEED_2500; - if (phylink_test(supported, 10000baseKX4_Full)) - max = SPEED_10000; - if (phylink_test(supported, 10000baseKR_Full)) - max = SPEED_10000; - - return max; -} - static void xpcs_config_usxgmii(struct dw_xpcs *xpcs, int speed) { int ret, speed_sel; @@ -478,16 +460,12 @@ static int xpcs_config_aneg_c73(struct dw_xpcs *xpcs, static int xpcs_aneg_done_c73(struct dw_xpcs *xpcs, struct phylink_link_state *state, - const struct xpcs_compat *compat) + const struct xpcs_compat *compat, u16 an_stat1) { int ret; - ret = xpcs_read(xpcs, MDIO_MMD_AN, MDIO_STAT1); - if (ret < 0) - return ret; - - if (ret & MDIO_AN_STAT1_COMPLETE) { - ret = xpcs_read(xpcs, MDIO_MMD_AN, DW_SR_AN_LP_ABL1); + if (an_stat1 & MDIO_AN_STAT1_COMPLETE) { + ret = xpcs_read(xpcs, MDIO_MMD_AN, MDIO_AN_LPA); if (ret < 0) return ret; @@ -504,64 +482,32 @@ static int xpcs_aneg_done_c73(struct dw_xpcs *xpcs, } static int xpcs_read_lpa_c73(struct dw_xpcs *xpcs, - struct phylink_link_state *state) + struct phylink_link_state *state, u16 an_stat1) { - int ret; - - ret = xpcs_read(xpcs, MDIO_MMD_AN, MDIO_STAT1); - if (ret < 0) - return ret; + u16 lpa[3]; + int i, ret; - if (!(ret & MDIO_AN_STAT1_LPABLE)) { + if (!(an_stat1 & MDIO_AN_STAT1_LPABLE)) { phylink_clear(state->lp_advertising, Autoneg); return 0; } phylink_set(state->lp_advertising, Autoneg); - /* Clause 73 outcome */ - ret = xpcs_read(xpcs, MDIO_MMD_AN, DW_SR_AN_LP_ABL3); - if (ret < 0) - return ret; - - if (ret & DW_C73_2500KX) - phylink_set(state->lp_advertising, 2500baseX_Full); - - ret = xpcs_read(xpcs, MDIO_MMD_AN, DW_SR_AN_LP_ABL2); - if (ret < 0) - return ret; - - if (ret & DW_C73_1000KX) - phylink_set(state->lp_advertising, 1000baseKX_Full); - if (ret & DW_C73_10000KX4) - phylink_set(state->lp_advertising, 10000baseKX4_Full); - if (ret & DW_C73_10000KR) - phylink_set(state->lp_advertising, 10000baseKR_Full); + /* Read Clause 73 link partner advertisement */ + for (i = ARRAY_SIZE(lpa); --i >= 0; ) { + ret = xpcs_read(xpcs, MDIO_MMD_AN, MDIO_AN_LPA + i); + if (ret < 0) + return ret; - ret = xpcs_read(xpcs, MDIO_MMD_AN, DW_SR_AN_LP_ABL1); - if (ret < 0) - return ret; + lpa[i] = ret; + } - if (ret & DW_C73_PAUSE) - phylink_set(state->lp_advertising, Pause); - if (ret & DW_C73_ASYM_PAUSE) - phylink_set(state->lp_advertising, Asym_Pause); + mii_c73_mod_linkmode(state->lp_advertising, lpa); - linkmode_and(state->lp_advertising, state->lp_advertising, - state->advertising); return 0; } -static void xpcs_resolve_lpa_c73(struct dw_xpcs *xpcs, - struct phylink_link_state *state) -{ - int max_speed = xpcs_get_max_usxgmii_speed(state->lp_advertising); - - state->pause = MLO_PAUSE_TX | MLO_PAUSE_RX; - state->speed = max_speed; - state->duplex = DUPLEX_FULL; -} - static int xpcs_get_max_xlgmii_speed(struct dw_xpcs *xpcs, struct phylink_link_state *state) { @@ -711,7 +657,8 @@ int xpcs_config_eee(struct dw_xpcs *xpcs, int mult_fact_100ns, int enable) } EXPORT_SYMBOL_GPL(xpcs_config_eee); -static int xpcs_config_aneg_c37_sgmii(struct dw_xpcs *xpcs, unsigned int mode) +static int xpcs_config_aneg_c37_sgmii(struct dw_xpcs *xpcs, + unsigned int neg_mode) { int ret, mdio_ctrl; @@ -761,7 +708,7 @@ static int xpcs_config_aneg_c37_sgmii(struct dw_xpcs *xpcs, unsigned int mode) if (ret < 0) return ret; - if (phylink_autoneg_inband(mode)) + if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED) ret |= DW_VR_MII_DIG_CTRL1_MAC_AUTO_SW; else ret &= ~DW_VR_MII_DIG_CTRL1_MAC_AUTO_SW; @@ -770,14 +717,15 @@ static int xpcs_config_aneg_c37_sgmii(struct dw_xpcs *xpcs, unsigned int mode) if (ret < 0) return ret; - if (phylink_autoneg_inband(mode)) + if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED) ret = xpcs_write(xpcs, MDIO_MMD_VEND2, DW_VR_MII_MMD_CTRL, mdio_ctrl | AN_CL37_EN); return ret; } -static int xpcs_config_aneg_c37_1000basex(struct dw_xpcs *xpcs, unsigned int mode, +static int xpcs_config_aneg_c37_1000basex(struct dw_xpcs *xpcs, + unsigned int neg_mode, const unsigned long *advertising) { phy_interface_t interface = PHY_INTERFACE_MODE_1000BASEX; @@ -828,8 +776,7 @@ static int xpcs_config_aneg_c37_1000basex(struct dw_xpcs *xpcs, unsigned int mod if (ret < 0) return ret; - if (phylink_autoneg_inband(mode) && - linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, advertising)) { + if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED) { ret = xpcs_write(xpcs, MDIO_MMD_VEND2, DW_VR_MII_MMD_CTRL, mdio_ctrl | AN_CL37_EN); if (ret < 0) @@ -862,7 +809,7 @@ static int xpcs_config_2500basex(struct dw_xpcs *xpcs) } int xpcs_do_config(struct dw_xpcs *xpcs, phy_interface_t interface, - unsigned int mode, const unsigned long *advertising) + const unsigned long *advertising, unsigned int neg_mode) { const struct xpcs_compat *compat; int ret; @@ -872,20 +819,22 @@ int xpcs_do_config(struct dw_xpcs *xpcs, phy_interface_t interface, return -ENODEV; switch (compat->an_mode) { + case DW_10GBASER: + break; case DW_AN_C73: - if (test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, advertising)) { + if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED) { ret = xpcs_config_aneg_c73(xpcs, compat); if (ret) return ret; } break; case DW_AN_C37_SGMII: - ret = xpcs_config_aneg_c37_sgmii(xpcs, mode); + ret = xpcs_config_aneg_c37_sgmii(xpcs, neg_mode); if (ret) return ret; break; case DW_AN_C37_1000BASEX: - ret = xpcs_config_aneg_c37_1000basex(xpcs, mode, + ret = xpcs_config_aneg_c37_1000basex(xpcs, neg_mode, advertising); if (ret) return ret; @@ -909,14 +858,14 @@ int xpcs_do_config(struct dw_xpcs *xpcs, phy_interface_t interface, } EXPORT_SYMBOL_GPL(xpcs_do_config); -static int xpcs_config(struct phylink_pcs *pcs, unsigned int mode, +static int xpcs_config(struct phylink_pcs *pcs, unsigned int neg_mode, phy_interface_t interface, const unsigned long *advertising, bool permit_pause_to_mac) { struct dw_xpcs *xpcs = phylink_pcs_to_xpcs(pcs); - return xpcs_do_config(xpcs, interface, mode, advertising); + return xpcs_do_config(xpcs, interface, advertising, neg_mode); } static int xpcs_get_state_c73(struct dw_xpcs *xpcs, @@ -924,13 +873,25 @@ static int xpcs_get_state_c73(struct dw_xpcs *xpcs, const struct xpcs_compat *compat) { bool an_enabled; + int pcs_stat1; + int an_stat1; int ret; + /* The link status bit is latching-low, so it is important to + * avoid unnecessary re-reads of this register to avoid missing + * a link-down event. + */ + pcs_stat1 = xpcs_read(xpcs, MDIO_MMD_PCS, MDIO_STAT1); + if (pcs_stat1 < 0) { + state->link = false; + return pcs_stat1; + } + /* Link needs to be read first ... */ - state->link = xpcs_read_link_c73(xpcs) > 0 ? 1 : 0; + state->link = !!(pcs_stat1 & MDIO_STAT1_LSTATUS); /* ... and then we check the faults. */ - ret = xpcs_read_fault_c73(xpcs, state); + ret = xpcs_read_fault_c73(xpcs, state, pcs_stat1); if (ret) { ret = xpcs_soft_reset(xpcs, compat); if (ret) @@ -938,18 +899,42 @@ static int xpcs_get_state_c73(struct dw_xpcs *xpcs, state->link = 0; - return xpcs_do_config(xpcs, state->interface, MLO_AN_INBAND, NULL); + return xpcs_do_config(xpcs, state->interface, NULL, + PHYLINK_PCS_NEG_INBAND_ENABLED); } + /* There is no point doing anything else if the link is down. */ + if (!state->link) + return 0; + an_enabled = linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, state->advertising); - if (an_enabled && xpcs_aneg_done_c73(xpcs, state, compat)) { - state->an_complete = true; - xpcs_read_lpa_c73(xpcs, state); - xpcs_resolve_lpa_c73(xpcs, state); - } else if (an_enabled) { - state->link = 0; - } else if (state->link) { + if (an_enabled) { + /* The link status bit is latching-low, so it is important to + * avoid unnecessary re-reads of this register to avoid missing + * a link-down event. + */ + an_stat1 = xpcs_read(xpcs, MDIO_MMD_AN, MDIO_STAT1); + if (an_stat1 < 0) { + state->link = false; + return an_stat1; + } + + state->an_complete = xpcs_aneg_done_c73(xpcs, state, compat, + an_stat1); + if (!state->an_complete) { + state->link = false; + return 0; + } + + ret = xpcs_read_lpa_c73(xpcs, state, an_stat1); + if (ret < 0) { + state->link = false; + return ret; + } + + phylink_resolve_c73(state); + } else { xpcs_resolve_pma(xpcs, state); } @@ -1033,6 +1018,9 @@ static void xpcs_get_state(struct phylink_pcs *pcs, return; switch (compat->an_mode) { + case DW_10GBASER: + phylink_mii_c45_pcs_get_state(xpcs->mdiodev, state); + break; case DW_AN_C73: ret = xpcs_get_state_c73(xpcs, state, compat); if (ret) { @@ -1060,12 +1048,12 @@ static void xpcs_get_state(struct phylink_pcs *pcs, } } -static void xpcs_link_up_sgmii(struct dw_xpcs *xpcs, unsigned int mode, +static void xpcs_link_up_sgmii(struct dw_xpcs *xpcs, unsigned int neg_mode, int speed, int duplex) { int val, ret; - if (phylink_autoneg_inband(mode)) + if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED) return; val = mii_bmcr_encode_fixed(speed, duplex); @@ -1074,12 +1062,12 @@ static void xpcs_link_up_sgmii(struct dw_xpcs *xpcs, unsigned int mode, pr_err("%s: xpcs_write returned %pe\n", __func__, ERR_PTR(ret)); } -static void xpcs_link_up_1000basex(struct dw_xpcs *xpcs, unsigned int mode, +static void xpcs_link_up_1000basex(struct dw_xpcs *xpcs, unsigned int neg_mode, int speed, int duplex) { int val, ret; - if (phylink_autoneg_inband(mode)) + if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED) return; switch (speed) { @@ -1103,7 +1091,7 @@ static void xpcs_link_up_1000basex(struct dw_xpcs *xpcs, unsigned int mode, pr_err("%s: xpcs_write returned %pe\n", __func__, ERR_PTR(ret)); } -void xpcs_link_up(struct phylink_pcs *pcs, unsigned int mode, +void xpcs_link_up(struct phylink_pcs *pcs, unsigned int neg_mode, phy_interface_t interface, int speed, int duplex) { struct dw_xpcs *xpcs = phylink_pcs_to_xpcs(pcs); @@ -1111,9 +1099,9 @@ void xpcs_link_up(struct phylink_pcs *pcs, unsigned int mode, if (interface == PHY_INTERFACE_MODE_USXGMII) return xpcs_config_usxgmii(xpcs, speed); if (interface == PHY_INTERFACE_MODE_SGMII) - return xpcs_link_up_sgmii(xpcs, mode, speed, duplex); + return xpcs_link_up_sgmii(xpcs, neg_mode, speed, duplex); if (interface == PHY_INTERFACE_MODE_1000BASEX) - return xpcs_link_up_1000basex(xpcs, mode, speed, duplex); + return xpcs_link_up_1000basex(xpcs, neg_mode, speed, duplex); } EXPORT_SYMBOL_GPL(xpcs_link_up); @@ -1188,6 +1176,12 @@ static const struct xpcs_compat synopsys_xpcs_compat[DW_XPCS_INTERFACE_MAX] = { .num_interfaces = ARRAY_SIZE(xpcs_xlgmii_interfaces), .an_mode = DW_AN_C73, }, + [DW_XPCS_10GBASER] = { + .supported = xpcs_10gbaser_features, + .interface = xpcs_10gbaser_interfaces, + .num_interfaces = ARRAY_SIZE(xpcs_10gbaser_interfaces), + .an_mode = DW_10GBASER, + }, [DW_XPCS_SGMII] = { .supported = xpcs_sgmii_features, .interface = xpcs_sgmii_interfaces, @@ -1259,8 +1253,8 @@ static const struct phylink_pcs_ops xpcs_phylink_ops = { .pcs_link_up = xpcs_link_up, }; -struct dw_xpcs *xpcs_create(struct mdio_device *mdiodev, - phy_interface_t interface) +static struct dw_xpcs *xpcs_create(struct mdio_device *mdiodev, + phy_interface_t interface) { struct dw_xpcs *xpcs; u32 xpcs_id; @@ -1270,6 +1264,7 @@ struct dw_xpcs *xpcs_create(struct mdio_device *mdiodev, if (!xpcs) return ERR_PTR(-ENOMEM); + mdio_device_get(mdiodev); xpcs->mdiodev = mdiodev; xpcs_id = xpcs_get_id(xpcs); @@ -1290,6 +1285,10 @@ struct dw_xpcs *xpcs_create(struct mdio_device *mdiodev, } xpcs->pcs.ops = &xpcs_phylink_ops; + xpcs->pcs.neg_mode = true; + if (compat->an_mode == DW_10GBASER) + return xpcs; + xpcs->pcs.poll = true; ret = xpcs_soft_reset(xpcs, compat); @@ -1302,16 +1301,42 @@ struct dw_xpcs *xpcs_create(struct mdio_device *mdiodev, ret = -ENODEV; out: + mdio_device_put(mdiodev); kfree(xpcs); return ERR_PTR(ret); } -EXPORT_SYMBOL_GPL(xpcs_create); void xpcs_destroy(struct dw_xpcs *xpcs) { + if (xpcs) + mdio_device_put(xpcs->mdiodev); kfree(xpcs); } EXPORT_SYMBOL_GPL(xpcs_destroy); +struct dw_xpcs *xpcs_create_mdiodev(struct mii_bus *bus, int addr, + phy_interface_t interface) +{ + struct mdio_device *mdiodev; + struct dw_xpcs *xpcs; + + mdiodev = mdio_device_create(bus, addr); + if (IS_ERR(mdiodev)) + return ERR_CAST(mdiodev); + + xpcs = xpcs_create(mdiodev, interface); + + /* xpcs_create() has taken a refcount on the mdiodev if it was + * successful. If xpcs_create() fails, this will free the mdio + * device here. In any case, we don't need to hold our reference + * anymore, and putting it here will allow mdio_device_put() in + * xpcs_destroy() to automatically free the mdio device. + */ + mdio_device_put(mdiodev); + + return xpcs; +} +EXPORT_SYMBOL_GPL(xpcs_create_mdiodev); + MODULE_LICENSE("GPL v2"); diff --git a/drivers/net/pcs/pcs-xpcs.h b/drivers/net/pcs/pcs-xpcs.h index 770df50323a017600a058aa5d0828b7ecda16a7b..68c6b5a620881eed555b23fbad3e6fa904ab3804 100644 --- a/drivers/net/pcs/pcs-xpcs.h +++ b/drivers/net/pcs/pcs-xpcs.h @@ -32,9 +32,6 @@ #define DW_SR_AN_ADV1 0x10 #define DW_SR_AN_ADV2 0x11 #define DW_SR_AN_ADV3 0x12 -#define DW_SR_AN_LP_ABL1 0x13 -#define DW_SR_AN_LP_ABL2 0x14 -#define DW_SR_AN_LP_ABL3 0x15 /* Clause 73 Defines */ /* AN_LP_ABL1 */ diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index 93b8efc79227373bf196d5abcf24674a8363a907..78e6981650d9448e54be54f3dd7ecef59fbab2d7 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig @@ -236,6 +236,18 @@ config MEDIATEK_GE_PHY help Supports the MediaTek Gigabit Ethernet PHYs. +config MEDIATEK_GE_SOC_PHY + tristate "MediaTek SoC Ethernet PHYs" + depends on (ARM64 && ARCH_MEDIATEK) || COMPILE_TEST + depends on NVMEM_MTK_EFUSE + help + Supports MediaTek SoC built-in Gigabit Ethernet PHYs. + + Include support for built-in Ethernet PHYs which are present in + the MT7981 and MT7988 SoCs. These PHYs need calibration data + present in the SoCs efuse and will dynamically calibrate VCM + (common-mode voltage) during startup. + config MICREL_PHY tristate "Micrel PHYs" depends on PTP_1588_CLOCK_OPTIONAL @@ -243,9 +255,10 @@ config MICREL_PHY Supports the KSZ9021, VSC8201, KS8001 PHYs. config MICROCHIP_T1S_PHY - tristate "Microchip 10BASE-T1S Ethernet PHY" + tristate "Microchip 10BASE-T1S Ethernet PHYs" help - Currently supports the LAN8670, LAN8671, LAN8672 + Currently supports the LAN8670/1/2 Rev.B1 and LAN8650/1 Rev.B0 Internal + PHYs. config MICROCHIP_PHY tristate "Microchip PHYs" diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile index f289ab16a1dab39e6670d7289f4a994ce8b2e8bc..2fe51ea83babee327c2ebd0966be86d1aee44e09 100644 --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile @@ -69,6 +69,7 @@ obj-$(CONFIG_MARVELL_PHY) += marvell.o obj-$(CONFIG_MARVELL_88X2222_PHY) += marvell-88x2222.o obj-$(CONFIG_MAXLINEAR_GPHY) += mxl-gpy.o obj-$(CONFIG_MEDIATEK_GE_PHY) += mediatek-ge.o +obj-$(CONFIG_MEDIATEK_GE_SOC_PHY) += mediatek-ge-soc.o obj-$(CONFIG_MESON_GXL_PHY) += meson-gxl.o obj-$(CONFIG_MICREL_KS8995MA) += spi_ks8995.o obj-$(CONFIG_MICREL_PHY) += micrel.o diff --git a/drivers/net/phy/at803x.c b/drivers/net/phy/at803x.c index 656136628ffd85d77230d7e80d8fffc42e876235..c1f307d90518b93f992fdce7d50b66a4c1edc433 100644 --- a/drivers/net/phy/at803x.c +++ b/drivers/net/phy/at803x.c @@ -304,7 +304,6 @@ struct at803x_priv { bool is_1000basex; struct regulator_dev *vddio_rdev; struct regulator_dev *vddh_rdev; - struct regulator *vddio; u64 stats[ARRAY_SIZE(at803x_hw_stats)]; }; @@ -824,11 +823,11 @@ static int at803x_parse_dt(struct phy_device *phydev) if (ret < 0) return ret; - priv->vddio = devm_regulator_get_optional(&phydev->mdio.dev, - "vddio"); - if (IS_ERR(priv->vddio)) { + ret = devm_regulator_get_enable_optional(&phydev->mdio.dev, + "vddio"); + if (ret) { phydev_err(phydev, "failed to get VDDIO regulator\n"); - return PTR_ERR(priv->vddio); + return ret; } /* Only AR8031/8033 support 1000Base-X for SFP modules */ @@ -856,12 +855,6 @@ static int at803x_probe(struct phy_device *phydev) if (ret) return ret; - if (priv->vddio) { - ret = regulator_enable(priv->vddio); - if (ret < 0) - return ret; - } - if (phydev->drv->phy_id == ATH8031_PHY_ID) { int ccr = phy_read(phydev, AT803X_REG_CHIP_CONFIG); int mode_cfg; @@ -869,10 +862,8 @@ static int at803x_probe(struct phy_device *phydev) .wolopts = 0, }; - if (ccr < 0) { - ret = ccr; - goto err; - } + if (ccr < 0) + return ccr; mode_cfg = ccr & AT803X_MODE_CFG_MASK; switch (mode_cfg) { @@ -890,25 +881,11 @@ static int at803x_probe(struct phy_device *phydev) ret = at803x_set_wol(phydev, &wol); if (ret < 0) { phydev_err(phydev, "failed to disable WOL on probe: %d\n", ret); - goto err; + return ret; } } return 0; - -err: - if (priv->vddio) - regulator_disable(priv->vddio); - - return ret; -} - -static void at803x_remove(struct phy_device *phydev) -{ - struct at803x_priv *priv = phydev->priv; - - if (priv->vddio) - regulator_disable(priv->vddio); } static int at803x_get_features(struct phy_device *phydev) @@ -2021,7 +1998,6 @@ static struct phy_driver at803x_driver[] = { .name = "Qualcomm Atheros AR8035", .flags = PHY_POLL_CABLE_TEST, .probe = at803x_probe, - .remove = at803x_remove, .config_aneg = at803x_config_aneg, .config_init = at803x_config_init, .soft_reset = genphy_soft_reset, @@ -2043,7 +2019,6 @@ static struct phy_driver at803x_driver[] = { .name = "Qualcomm Atheros AR8030", .phy_id_mask = AT8030_PHY_ID_MASK, .probe = at803x_probe, - .remove = at803x_remove, .config_init = at803x_config_init, .link_change_notify = at803x_link_change_notify, .set_wol = at803x_set_wol, @@ -2059,7 +2034,6 @@ static struct phy_driver at803x_driver[] = { .name = "Qualcomm Atheros AR8031/AR8033", .flags = PHY_POLL_CABLE_TEST, .probe = at803x_probe, - .remove = at803x_remove, .config_init = at803x_config_init, .config_aneg = at803x_config_aneg, .soft_reset = genphy_soft_reset, @@ -2082,7 +2056,6 @@ static struct phy_driver at803x_driver[] = { PHY_ID_MATCH_EXACT(ATH8032_PHY_ID), .name = "Qualcomm Atheros AR8032", .probe = at803x_probe, - .remove = at803x_remove, .flags = PHY_POLL_CABLE_TEST, .config_init = at803x_config_init, .link_change_notify = at803x_link_change_notify, @@ -2100,7 +2073,6 @@ static struct phy_driver at803x_driver[] = { PHY_ID_MATCH_EXACT(ATH9331_PHY_ID), .name = "Qualcomm Atheros AR9331 built-in PHY", .probe = at803x_probe, - .remove = at803x_remove, .suspend = at803x_suspend, .resume = at803x_resume, .flags = PHY_POLL_CABLE_TEST, @@ -2117,7 +2089,6 @@ static struct phy_driver at803x_driver[] = { PHY_ID_MATCH_EXACT(QCA9561_PHY_ID), .name = "Qualcomm Atheros QCA9561 built-in PHY", .probe = at803x_probe, - .remove = at803x_remove, .suspend = at803x_suspend, .resume = at803x_resume, .flags = PHY_POLL_CABLE_TEST, @@ -2183,7 +2154,6 @@ static struct phy_driver at803x_driver[] = { .name = "Qualcomm QCA8081", .flags = PHY_POLL_CABLE_TEST, .probe = at803x_probe, - .remove = at803x_remove, .config_intr = at803x_config_intr, .handle_interrupt = at803x_handle_interrupt, .get_tunable = at803x_get_tunable, diff --git a/drivers/net/phy/bcm-phy-lib.c b/drivers/net/phy/bcm-phy-lib.c index b2c0baa51f39ebad65a51d65e0e9c0f12bc03133..876f28fd82565da2b97ca6ecffc1cbc2006c45f2 100644 --- a/drivers/net/phy/bcm-phy-lib.c +++ b/drivers/net/phy/bcm-phy-lib.c @@ -6,12 +6,14 @@ #include "bcm-phy-lib.h" #include #include +#include #include #include #include #include #include #include +#include #define MII_BCM_CHANNEL_WIDTH 0x2000 #define BCM_CL45VEN_EEE_ADV 0x3c @@ -494,18 +496,20 @@ EXPORT_SYMBOL_GPL(bcm_phy_downshift_set); struct bcm_phy_hw_stat { const char *string; - u8 reg; + int devad; + u16 reg; u8 shift; u8 bits; }; /* Counters freeze at either 0xffff or 0xff, better than nothing */ static const struct bcm_phy_hw_stat bcm_phy_hw_stats[] = { - { "phy_receive_errors", MII_BRCM_CORE_BASE12, 0, 16 }, - { "phy_serdes_ber_errors", MII_BRCM_CORE_BASE13, 8, 8 }, - { "phy_false_carrier_sense_errors", MII_BRCM_CORE_BASE13, 0, 8 }, - { "phy_local_rcvr_nok", MII_BRCM_CORE_BASE14, 8, 8 }, - { "phy_remote_rcv_nok", MII_BRCM_CORE_BASE14, 0, 8 }, + { "phy_receive_errors", -1, MII_BRCM_CORE_BASE12, 0, 16 }, + { "phy_serdes_ber_errors", -1, MII_BRCM_CORE_BASE13, 8, 8 }, + { "phy_false_carrier_sense_errors", -1, MII_BRCM_CORE_BASE13, 0, 8 }, + { "phy_local_rcvr_nok", -1, MII_BRCM_CORE_BASE14, 8, 8 }, + { "phy_remote_rcv_nok", -1, MII_BRCM_CORE_BASE14, 0, 8 }, + { "phy_lpi_count", MDIO_MMD_AN, BRCM_CL45VEN_EEE_LPI_CNT, 0, 16 }, }; int bcm_phy_get_sset_count(struct phy_device *phydev) @@ -534,7 +538,10 @@ static u64 bcm_phy_get_stat(struct phy_device *phydev, u64 *shadow, int val; u64 ret; - val = phy_read(phydev, stat.reg); + if (stat.devad < 0) + val = phy_read(phydev, stat.reg); + else + val = phy_read_mmd(phydev, stat.devad, stat.reg); if (val < 0) { ret = U64_MAX; } else { @@ -816,6 +823,249 @@ int bcm_phy_cable_test_get_status_rdb(struct phy_device *phydev, } EXPORT_SYMBOL_GPL(bcm_phy_cable_test_get_status_rdb); +#define BCM54XX_WOL_SUPPORTED_MASK (WAKE_UCAST | \ + WAKE_MCAST | \ + WAKE_BCAST | \ + WAKE_MAGIC | \ + WAKE_MAGICSECURE) + +int bcm_phy_set_wol(struct phy_device *phydev, struct ethtool_wolinfo *wol) +{ + struct net_device *ndev = phydev->attached_dev; + u8 da[ETH_ALEN], mask[ETH_ALEN]; + unsigned int i; + u16 ctl; + int ret; + + /* Allow a MAC driver to play through its own Wake-on-LAN + * implementation + */ + if (wol->wolopts & ~BCM54XX_WOL_SUPPORTED_MASK) + return -EOPNOTSUPP; + + /* The PHY supports passwords of 4, 6 and 8 bytes in size, but Linux's + * ethtool only supports 6, for now. + */ + BUILD_BUG_ON(sizeof(wol->sopass) != ETH_ALEN); + + /* Clear previous interrupts */ + ret = bcm_phy_read_exp(phydev, BCM54XX_WOL_INT_STATUS); + if (ret < 0) + return ret; + + ret = bcm_phy_read_exp(phydev, BCM54XX_WOL_MAIN_CTL); + if (ret < 0) + return ret; + + ctl = ret; + + if (!wol->wolopts) { + if (phy_interrupt_is_valid(phydev)) + disable_irq_wake(phydev->irq); + + /* Leave all interrupts disabled */ + ret = bcm_phy_write_exp(phydev, BCM54XX_WOL_INT_MASK, + BCM54XX_WOL_ALL_INTRS); + if (ret < 0) + return ret; + + /* Disable the global Wake-on-LAN enable bit */ + ctl &= ~BCM54XX_WOL_EN; + + return bcm_phy_write_exp(phydev, BCM54XX_WOL_MAIN_CTL, ctl); + } + + /* Clear the previously configured mode and mask mode for Wake-on-LAN */ + ctl &= ~(BCM54XX_WOL_MODE_MASK << BCM54XX_WOL_MODE_SHIFT); + ctl &= ~(BCM54XX_WOL_MASK_MODE_MASK << BCM54XX_WOL_MASK_MODE_SHIFT); + ctl &= ~BCM54XX_WOL_DIR_PKT_EN; + ctl &= ~(BCM54XX_WOL_SECKEY_OPT_MASK << BCM54XX_WOL_SECKEY_OPT_SHIFT); + + /* When using WAKE_MAGIC, we program the magic pattern filter to match + * the device's MAC address and we accept any MAC DA in the Ethernet + * frame. + * + * When using WAKE_UCAST, WAKE_BCAST or WAKE_MCAST, we program the + * following: + * - WAKE_UCAST -> MAC DA is the device's MAC with a perfect match + * - WAKE_MCAST -> MAC DA is X1:XX:XX:XX:XX:XX where XX is don't care + * - WAKE_BCAST -> MAC DA is FF:FF:FF:FF:FF:FF with a perfect match + * + * Note that the Broadcast MAC DA is inherently going to match the + * multicast pattern being matched. + */ + memset(mask, 0, sizeof(mask)); + + if (wol->wolopts & WAKE_MCAST) { + memset(da, 0, sizeof(da)); + memset(mask, 0xff, sizeof(mask)); + da[0] = 0x01; + mask[0] = ~da[0]; + } else { + if (wol->wolopts & WAKE_UCAST) { + ether_addr_copy(da, ndev->dev_addr); + } else if (wol->wolopts & WAKE_BCAST) { + eth_broadcast_addr(da); + } else if (wol->wolopts & WAKE_MAGICSECURE) { + ether_addr_copy(da, wol->sopass); + } else if (wol->wolopts & WAKE_MAGIC) { + memset(da, 0, sizeof(da)); + memset(mask, 0xff, sizeof(mask)); + } + } + + for (i = 0; i < ETH_ALEN / 2; i++) { + if (wol->wolopts & (WAKE_MAGIC | WAKE_MAGICSECURE)) { + ret = bcm_phy_write_exp(phydev, + BCM54XX_WOL_MPD_DATA1(2 - i), + ndev->dev_addr[i * 2] << 8 | + ndev->dev_addr[i * 2 + 1]); + if (ret < 0) + return ret; + } + + ret = bcm_phy_write_exp(phydev, BCM54XX_WOL_MPD_DATA2(2 - i), + da[i * 2] << 8 | da[i * 2 + 1]); + if (ret < 0) + return ret; + + ret = bcm_phy_write_exp(phydev, BCM54XX_WOL_MASK(2 - i), + mask[i * 2] << 8 | mask[i * 2 + 1]); + if (ret) + return ret; + } + + if (wol->wolopts & WAKE_MAGICSECURE) { + ctl |= BCM54XX_WOL_SECKEY_OPT_6B << + BCM54XX_WOL_SECKEY_OPT_SHIFT; + ctl |= BCM54XX_WOL_MODE_SINGLE_MPDSEC << BCM54XX_WOL_MODE_SHIFT; + ctl |= BCM54XX_WOL_MASK_MODE_DA_FF << + BCM54XX_WOL_MASK_MODE_SHIFT; + } else { + if (wol->wolopts & WAKE_MAGIC) + ctl |= BCM54XX_WOL_MODE_SINGLE_MPD; + else + ctl |= BCM54XX_WOL_DIR_PKT_EN; + ctl |= BCM54XX_WOL_MASK_MODE_DA_ONLY << + BCM54XX_WOL_MASK_MODE_SHIFT; + } + + /* Globally enable Wake-on-LAN */ + ctl |= BCM54XX_WOL_EN | BCM54XX_WOL_CRC_CHK; + + ret = bcm_phy_write_exp(phydev, BCM54XX_WOL_MAIN_CTL, ctl); + if (ret < 0) + return ret; + + /* Enable WOL interrupt on LED4 */ + ret = bcm_phy_read_exp(phydev, BCM54XX_TOP_MISC_LED_CTL); + if (ret < 0) + return ret; + + ret |= BCM54XX_LED4_SEL_INTR; + ret = bcm_phy_write_exp(phydev, BCM54XX_TOP_MISC_LED_CTL, ret); + if (ret < 0) + return ret; + + /* Enable all Wake-on-LAN interrupt sources */ + ret = bcm_phy_write_exp(phydev, BCM54XX_WOL_INT_MASK, 0); + if (ret < 0) + return ret; + + if (phy_interrupt_is_valid(phydev)) + enable_irq_wake(phydev->irq); + + return 0; +} +EXPORT_SYMBOL_GPL(bcm_phy_set_wol); + +void bcm_phy_get_wol(struct phy_device *phydev, struct ethtool_wolinfo *wol) +{ + struct net_device *ndev = phydev->attached_dev; + u8 da[ETH_ALEN]; + unsigned int i; + int ret; + u16 ctl; + + wol->supported = BCM54XX_WOL_SUPPORTED_MASK; + wol->wolopts = 0; + + ret = bcm_phy_read_exp(phydev, BCM54XX_WOL_MAIN_CTL); + if (ret < 0) + return; + + ctl = ret; + + if (!(ctl & BCM54XX_WOL_EN)) + return; + + for (i = 0; i < sizeof(da) / 2; i++) { + ret = bcm_phy_read_exp(phydev, + BCM54XX_WOL_MPD_DATA2(2 - i)); + if (ret < 0) + return; + + da[i * 2] = ret >> 8; + da[i * 2 + 1] = ret & 0xff; + } + + if (ctl & BCM54XX_WOL_DIR_PKT_EN) { + if (is_broadcast_ether_addr(da)) + wol->wolopts |= WAKE_BCAST; + else if (is_multicast_ether_addr(da)) + wol->wolopts |= WAKE_MCAST; + else if (ether_addr_equal(da, ndev->dev_addr)) + wol->wolopts |= WAKE_UCAST; + } else { + ctl = (ctl >> BCM54XX_WOL_MODE_SHIFT) & BCM54XX_WOL_MODE_MASK; + switch (ctl) { + case BCM54XX_WOL_MODE_SINGLE_MPD: + wol->wolopts |= WAKE_MAGIC; + break; + case BCM54XX_WOL_MODE_SINGLE_MPDSEC: + wol->wolopts |= WAKE_MAGICSECURE; + memcpy(wol->sopass, da, sizeof(da)); + break; + default: + break; + } + } +} +EXPORT_SYMBOL_GPL(bcm_phy_get_wol); + +irqreturn_t bcm_phy_wol_isr(int irq, void *dev_id) +{ + return IRQ_HANDLED; +} +EXPORT_SYMBOL_GPL(bcm_phy_wol_isr); + +int bcm_phy_led_brightness_set(struct phy_device *phydev, + u8 index, enum led_brightness value) +{ + u8 led_num; + int ret; + u16 reg; + + if (index >= 4) + return -EINVAL; + + /* Two LEDS per register */ + led_num = index % 2; + reg = index >= 2 ? BCM54XX_SHD_LEDS2 : BCM54XX_SHD_LEDS1; + + ret = bcm_phy_read_shadow(phydev, reg); + if (ret < 0) + return ret; + + ret &= ~(BCM_LED_SRC_MASK << BCM54XX_SHD_LEDS_SHIFT(led_num)); + if (value == LED_OFF) + ret |= BCM_LED_SRC_OFF << BCM54XX_SHD_LEDS_SHIFT(led_num); + else + ret |= BCM_LED_SRC_ON << BCM54XX_SHD_LEDS_SHIFT(led_num); + return bcm_phy_write_shadow(phydev, reg, ret); +} +EXPORT_SYMBOL_GPL(bcm_phy_led_brightness_set); + MODULE_DESCRIPTION("Broadcom PHY Library"); MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Broadcom Corporation"); diff --git a/drivers/net/phy/bcm-phy-lib.h b/drivers/net/phy/bcm-phy-lib.h index 729db441797a0e8c8059c33e08fe998e0e18c188..b52189e45a848199db559e74e3422a465e105175 100644 --- a/drivers/net/phy/bcm-phy-lib.h +++ b/drivers/net/phy/bcm-phy-lib.h @@ -8,6 +8,9 @@ #include #include +#include + +struct ethtool_wolinfo; /* 28nm only register definitions */ #define MISC_ADDR(base, channel) base, channel @@ -111,4 +114,11 @@ static inline void bcm_ptp_stop(struct bcm_ptp_private *priv) } #endif +int bcm_phy_set_wol(struct phy_device *phydev, struct ethtool_wolinfo *wol); +void bcm_phy_get_wol(struct phy_device *phydev, struct ethtool_wolinfo *wol); +irqreturn_t bcm_phy_wol_isr(int irq, void *dev_id); + +int bcm_phy_led_brightness_set(struct phy_device *phydev, + u8 index, enum led_brightness value); + #endif /* _LINUX_BCM_PHY_LIB_H */ diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c index ad71c88c87e78d0185e0dd309787061895bd68f8..59cae0d808aa2ec33537a1a5c5ddf9182e894a1c 100644 --- a/drivers/net/phy/broadcom.c +++ b/drivers/net/phy/broadcom.c @@ -14,8 +14,12 @@ #include #include #include +#include #include #include +#include +#include +#include #define BRCM_PHY_MODEL(phydev) \ ((phydev)->drv->phy_id & (phydev)->drv->phy_id_mask) @@ -30,8 +34,17 @@ MODULE_LICENSE("GPL"); struct bcm54xx_phy_priv { u64 *stats; struct bcm_ptp_private *ptp; + int wake_irq; + bool wake_irq_enabled; }; +static bool bcm54xx_phy_can_wakeup(struct phy_device *phydev) +{ + struct bcm54xx_phy_priv *priv = phydev->priv; + + return phy_interrupt_is_valid(phydev) || priv->wake_irq >= 0; +} + static int bcm54xx_config_clock_delay(struct phy_device *phydev) { int rc, val; @@ -401,18 +414,28 @@ static int bcm54xx_config_init(struct phy_device *phydev) * these settings will cause LOS to malfunction. */ if (!phy_on_sfp(phydev)) { - val = BCM5482_SHD_LEDS1_LED1(BCM_LED_SRC_MULTICOLOR1) | - BCM5482_SHD_LEDS1_LED3(BCM_LED_SRC_MULTICOLOR1); - bcm_phy_write_shadow(phydev, BCM5482_SHD_LEDS1, val); + val = BCM54XX_SHD_LEDS1_LED1(BCM_LED_SRC_MULTICOLOR1) | + BCM54XX_SHD_LEDS1_LED3(BCM_LED_SRC_MULTICOLOR1); + bcm_phy_write_shadow(phydev, BCM54XX_SHD_LEDS1, val); val = BCM_LED_MULTICOLOR_IN_PHASE | - BCM5482_SHD_LEDS1_LED1(BCM_LED_MULTICOLOR_LINK_ACT) | - BCM5482_SHD_LEDS1_LED3(BCM_LED_MULTICOLOR_LINK_ACT); + BCM54XX_SHD_LEDS1_LED1(BCM_LED_MULTICOLOR_LINK_ACT) | + BCM54XX_SHD_LEDS1_LED3(BCM_LED_MULTICOLOR_LINK_ACT); bcm_phy_write_exp(phydev, BCM_EXP_MULTICOLOR, val); } bcm54xx_ptp_config_init(phydev); + /* Acknowledge any left over interrupt and charge the device for + * wake-up. + */ + err = bcm_phy_read_exp(phydev, BCM54XX_WOL_INT_STATUS); + if (err < 0) + return err; + + if (err) + pm_wakeup_event(&phydev->mdio.dev, 0); + return 0; } @@ -437,12 +460,39 @@ static int bcm54xx_iddq_set(struct phy_device *phydev, bool enable) return ret; } +static int bcm54xx_set_wakeup_irq(struct phy_device *phydev, bool state) +{ + struct bcm54xx_phy_priv *priv = phydev->priv; + int ret = 0; + + if (!bcm54xx_phy_can_wakeup(phydev)) + return ret; + + if (priv->wake_irq_enabled != state) { + if (state) + ret = enable_irq_wake(priv->wake_irq); + else + ret = disable_irq_wake(priv->wake_irq); + priv->wake_irq_enabled = state; + } + + return ret; +} + static int bcm54xx_suspend(struct phy_device *phydev) { - int ret; + int ret = 0; bcm54xx_ptp_stop(phydev); + /* Acknowledge any Wake-on-LAN interrupt prior to suspend */ + ret = bcm_phy_read_exp(phydev, BCM54XX_WOL_INT_STATUS); + if (ret < 0) + return ret; + + if (phydev->wol_enabled) + return bcm54xx_set_wakeup_irq(phydev, true); + /* We cannot use a read/modify/write here otherwise the PHY gets into * a bad state where its LEDs keep flashing, thus defeating the purpose * of low power mode. @@ -456,7 +506,13 @@ static int bcm54xx_suspend(struct phy_device *phydev) static int bcm54xx_resume(struct phy_device *phydev) { - int ret; + int ret = 0; + + if (phydev->wol_enabled) { + ret = bcm54xx_set_wakeup_irq(phydev, false); + if (ret) + return ret; + } ret = bcm54xx_iddq_set(phydev, false); if (ret < 0) @@ -608,17 +664,6 @@ static int bcm54616s_read_status(struct phy_device *phydev) return err; } -static int brcm_phy_setbits(struct phy_device *phydev, int reg, int set) -{ - int val; - - val = phy_read(phydev, reg); - if (val < 0) - return val; - - return phy_write(phydev, reg, val | set); -} - static int brcm_fet_config_init(struct phy_device *phydev) { int reg, err, err2, brcmtest; @@ -689,15 +734,15 @@ static int brcm_fet_config_init(struct phy_device *phydev) goto done; /* Enable auto MDIX */ - err = brcm_phy_setbits(phydev, MII_BRCM_FET_SHDW_MISCCTRL, - MII_BRCM_FET_SHDW_MC_FAME); + err = phy_set_bits(phydev, MII_BRCM_FET_SHDW_MISCCTRL, + MII_BRCM_FET_SHDW_MC_FAME); if (err < 0) goto done; if (phydev->dev_flags & PHY_BRCM_AUTO_PWRDWN_ENABLE) { /* Enable auto power down */ - err = brcm_phy_setbits(phydev, MII_BRCM_FET_SHDW_AUXSTAT2, - MII_BRCM_FET_SHDW_AS2_APDE); + err = phy_set_bits(phydev, MII_BRCM_FET_SHDW_AUXSTAT2, + MII_BRCM_FET_SHDW_AS2_APDE); } done: @@ -801,14 +846,54 @@ static int brcm_fet_suspend(struct phy_device *phydev) return err; } +static void bcm54xx_phy_get_wol(struct phy_device *phydev, + struct ethtool_wolinfo *wol) +{ + /* We cannot wake-up if we do not have a dedicated PHY interrupt line + * or an out of band GPIO descriptor for wake-up. Zeroing + * wol->supported allows the caller (MAC driver) to play through and + * offer its own Wake-on-LAN scheme if available. + */ + if (!bcm54xx_phy_can_wakeup(phydev)) { + wol->supported = 0; + return; + } + + bcm_phy_get_wol(phydev, wol); +} + +static int bcm54xx_phy_set_wol(struct phy_device *phydev, + struct ethtool_wolinfo *wol) +{ + int ret; + + /* We cannot wake-up if we do not have a dedicated PHY interrupt line + * or an out of band GPIO descriptor for wake-up. Returning -EOPNOTSUPP + * allows the caller (MAC driver) to play through and offer its own + * Wake-on-LAN scheme if available. + */ + if (!bcm54xx_phy_can_wakeup(phydev)) + return -EOPNOTSUPP; + + ret = bcm_phy_set_wol(phydev, wol); + if (ret < 0) + return ret; + + return 0; +} + static int bcm54xx_phy_probe(struct phy_device *phydev) { struct bcm54xx_phy_priv *priv; + struct gpio_desc *wakeup_gpio; + int ret = 0; priv = devm_kzalloc(&phydev->mdio.dev, sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; + priv->wake_irq = -ENXIO; + phydev->priv = priv; priv->stats = devm_kcalloc(&phydev->mdio.dev, @@ -821,7 +906,35 @@ static int bcm54xx_phy_probe(struct phy_device *phydev) if (IS_ERR(priv->ptp)) return PTR_ERR(priv->ptp); - return 0; + /* We cannot utilize the _optional variant here since we want to know + * whether the GPIO descriptor exists or not to advertise Wake-on-LAN + * support or not. + */ + wakeup_gpio = devm_gpiod_get(&phydev->mdio.dev, "wakeup", GPIOD_IN); + if (PTR_ERR(wakeup_gpio) == -EPROBE_DEFER) + return PTR_ERR(wakeup_gpio); + + if (!IS_ERR(wakeup_gpio)) { + priv->wake_irq = gpiod_to_irq(wakeup_gpio); + + /* Dummy interrupt handler which is not enabled but is provided + * in order for the interrupt descriptor to be fully set-up. + */ + ret = devm_request_irq(&phydev->mdio.dev, priv->wake_irq, + bcm_phy_wol_isr, + IRQF_TRIGGER_LOW | IRQF_NO_AUTOEN, + dev_name(&phydev->mdio.dev), phydev); + if (ret) + return ret; + } + + /* If we do not have a main interrupt or a side-band wake-up interrupt, + * then the device cannot be marked as wake-up capable. + */ + if (!bcm54xx_phy_can_wakeup(phydev)) + return 0; + + return device_init_wakeup(&phydev->mdio.dev, true); } static void bcm54xx_get_stats(struct phy_device *phydev, @@ -894,6 +1007,7 @@ static struct phy_driver broadcom_drivers[] = { .phy_id_mask = 0xfffffff0, .name = "Broadcom BCM54210E", /* PHY_GBIT_FEATURES */ + .flags = PHY_ALWAYS_CALL_SUSPEND, .get_sset_count = bcm_phy_get_sset_count, .get_strings = bcm_phy_get_strings, .get_stats = bcm54xx_get_stats, @@ -904,6 +1018,9 @@ static struct phy_driver broadcom_drivers[] = { .link_change_notify = bcm54xx_link_change_notify, .suspend = bcm54xx_suspend, .resume = bcm54xx_resume, + .get_wol = bcm54xx_phy_get_wol, + .set_wol = bcm54xx_phy_set_wol, + .led_brightness_set = bcm_phy_led_brightness_set, }, { .phy_id = PHY_ID_BCM5461, .phy_id_mask = 0xfffffff0, @@ -917,6 +1034,7 @@ static struct phy_driver broadcom_drivers[] = { .config_intr = bcm_phy_config_intr, .handle_interrupt = bcm_phy_handle_interrupt, .link_change_notify = bcm54xx_link_change_notify, + .led_brightness_set = bcm_phy_led_brightness_set, }, { .phy_id = PHY_ID_BCM54612E, .phy_id_mask = 0xfffffff0, @@ -930,6 +1048,7 @@ static struct phy_driver broadcom_drivers[] = { .config_intr = bcm_phy_config_intr, .handle_interrupt = bcm_phy_handle_interrupt, .link_change_notify = bcm54xx_link_change_notify, + .led_brightness_set = bcm_phy_led_brightness_set, }, { .phy_id = PHY_ID_BCM54616S, .phy_id_mask = 0xfffffff0, @@ -943,6 +1062,7 @@ static struct phy_driver broadcom_drivers[] = { .read_status = bcm54616s_read_status, .probe = bcm54616s_probe, .link_change_notify = bcm54xx_link_change_notify, + .led_brightness_set = bcm_phy_led_brightness_set, }, { .phy_id = PHY_ID_BCM5464, .phy_id_mask = 0xfffffff0, @@ -958,6 +1078,7 @@ static struct phy_driver broadcom_drivers[] = { .suspend = genphy_suspend, .resume = genphy_resume, .link_change_notify = bcm54xx_link_change_notify, + .led_brightness_set = bcm_phy_led_brightness_set, }, { .phy_id = PHY_ID_BCM5481, .phy_id_mask = 0xfffffff0, @@ -972,6 +1093,7 @@ static struct phy_driver broadcom_drivers[] = { .config_intr = bcm_phy_config_intr, .handle_interrupt = bcm_phy_handle_interrupt, .link_change_notify = bcm54xx_link_change_notify, + .led_brightness_set = bcm_phy_led_brightness_set, }, { .phy_id = PHY_ID_BCM54810, .phy_id_mask = 0xfffffff0, @@ -988,6 +1110,7 @@ static struct phy_driver broadcom_drivers[] = { .suspend = bcm54xx_suspend, .resume = bcm54xx_resume, .link_change_notify = bcm54xx_link_change_notify, + .led_brightness_set = bcm_phy_led_brightness_set, }, { .phy_id = PHY_ID_BCM54811, .phy_id_mask = 0xfffffff0, @@ -1004,6 +1127,7 @@ static struct phy_driver broadcom_drivers[] = { .suspend = bcm54xx_suspend, .resume = bcm54xx_resume, .link_change_notify = bcm54xx_link_change_notify, + .led_brightness_set = bcm_phy_led_brightness_set, }, { .phy_id = PHY_ID_BCM5482, .phy_id_mask = 0xfffffff0, @@ -1017,6 +1141,7 @@ static struct phy_driver broadcom_drivers[] = { .config_intr = bcm_phy_config_intr, .handle_interrupt = bcm_phy_handle_interrupt, .link_change_notify = bcm54xx_link_change_notify, + .led_brightness_set = bcm_phy_led_brightness_set, }, { .phy_id = PHY_ID_BCM50610, .phy_id_mask = 0xfffffff0, @@ -1032,6 +1157,7 @@ static struct phy_driver broadcom_drivers[] = { .link_change_notify = bcm54xx_link_change_notify, .suspend = bcm54xx_suspend, .resume = bcm54xx_resume, + .led_brightness_set = bcm_phy_led_brightness_set, }, { .phy_id = PHY_ID_BCM50610M, .phy_id_mask = 0xfffffff0, @@ -1047,6 +1173,7 @@ static struct phy_driver broadcom_drivers[] = { .link_change_notify = bcm54xx_link_change_notify, .suspend = bcm54xx_suspend, .resume = bcm54xx_resume, + .led_brightness_set = bcm_phy_led_brightness_set, }, { .phy_id = PHY_ID_BCM57780, .phy_id_mask = 0xfffffff0, @@ -1060,6 +1187,7 @@ static struct phy_driver broadcom_drivers[] = { .config_intr = bcm_phy_config_intr, .handle_interrupt = bcm_phy_handle_interrupt, .link_change_notify = bcm54xx_link_change_notify, + .led_brightness_set = bcm_phy_led_brightness_set, }, { .phy_id = PHY_ID_BCMAC131, .phy_id_mask = 0xfffffff0, @@ -1091,6 +1219,7 @@ static struct phy_driver broadcom_drivers[] = { .get_stats = bcm54xx_get_stats, .probe = bcm54xx_phy_probe, .link_change_notify = bcm54xx_link_change_notify, + .led_brightness_set = bcm_phy_led_brightness_set, }, { .phy_id = PHY_ID_BCM53125, .phy_id_mask = 0xfffffff0, @@ -1105,6 +1234,7 @@ static struct phy_driver broadcom_drivers[] = { .config_intr = bcm_phy_config_intr, .handle_interrupt = bcm_phy_handle_interrupt, .link_change_notify = bcm54xx_link_change_notify, + .led_brightness_set = bcm_phy_led_brightness_set, }, { .phy_id = PHY_ID_BCM53128, .phy_id_mask = 0xfffffff0, @@ -1119,6 +1249,7 @@ static struct phy_driver broadcom_drivers[] = { .config_intr = bcm_phy_config_intr, .handle_interrupt = bcm_phy_handle_interrupt, .link_change_notify = bcm54xx_link_change_notify, + .led_brightness_set = bcm_phy_led_brightness_set, }, { .phy_id = PHY_ID_BCM89610, .phy_id_mask = 0xfffffff0, diff --git a/drivers/net/phy/dp83867.c b/drivers/net/phy/dp83867.c index 76f5a2402fb060dcc6c85aa4f6f6727f9c105317..e397e7d642d925079f5346fbb9433a81fa96d74a 100644 --- a/drivers/net/phy/dp83867.c +++ b/drivers/net/phy/dp83867.c @@ -936,7 +936,7 @@ static int dp83867_phy_reset(struct phy_device *phydev) { int err; - err = phy_write(phydev, DP83867_CTRL, DP83867_SW_RESTART); + err = phy_write(phydev, DP83867_CTRL, DP83867_SW_RESET); if (err < 0) return err; diff --git a/drivers/net/phy/dp83869.c b/drivers/net/phy/dp83869.c index 9ab5eff502b71640b1022baf1d6b7567a65c240f..fa8c6fdcf30181067c7c3f164e997171908a70b8 100644 --- a/drivers/net/phy/dp83869.c +++ b/drivers/net/phy/dp83869.c @@ -692,8 +692,19 @@ static int dp83869_configure_mode(struct phy_device *phydev, /* Below init sequence for each operational mode is defined in * section 9.4.8 of the datasheet. */ + phy_ctrl_val = dp83869->mode; + if (phydev->interface == PHY_INTERFACE_MODE_MII) { + if (dp83869->mode == DP83869_100M_MEDIA_CONVERT || + dp83869->mode == DP83869_RGMII_100_BASE) { + phy_ctrl_val |= DP83869_OP_MODE_MII; + } else { + phydev_err(phydev, "selected op-mode is not valid with MII mode\n"); + return -EINVAL; + } + } + ret = phy_write_mmd(phydev, DP83869_DEVADDR, DP83869_OP_MODE, - dp83869->mode); + phy_ctrl_val); if (ret) return ret; diff --git a/drivers/net/phy/dp83td510.c b/drivers/net/phy/dp83td510.c index 3cd9a77f9532434848db2667762f2261e708fe9f..d7616b13c59469f230013d1358758d52baceb088 100644 --- a/drivers/net/phy/dp83td510.c +++ b/drivers/net/phy/dp83td510.c @@ -12,6 +12,11 @@ /* MDIO_MMD_VEND2 registers */ #define DP83TD510E_PHY_STS 0x10 +/* Bit 7 - mii_interrupt, active high. Clears on read. + * Note: Clearing does not necessarily deactivate IRQ pin if interrupts pending. + * This differs from the DP83TD510E datasheet (2020) which states this bit + * clears on write 0. + */ #define DP83TD510E_STS_MII_INT BIT(7) #define DP83TD510E_LINK_STATUS BIT(0) @@ -53,12 +58,6 @@ static int dp83td510_config_intr(struct phy_device *phydev) int ret; if (phydev->interrupts == PHY_INTERRUPT_ENABLED) { - /* Clear any pending interrupts */ - ret = phy_write_mmd(phydev, MDIO_MMD_VEND2, DP83TD510E_PHY_STS, - 0x0); - if (ret) - return ret; - ret = phy_write_mmd(phydev, MDIO_MMD_VEND2, DP83TD510E_INTERRUPT_REG_1, DP83TD510E_INT1_LINK_EN); @@ -81,10 +80,6 @@ static int dp83td510_config_intr(struct phy_device *phydev) DP83TD510E_GENCFG_INT_EN); if (ret) return ret; - - /* Clear any pending interrupts */ - ret = phy_write_mmd(phydev, MDIO_MMD_VEND2, DP83TD510E_PHY_STS, - 0x0); } return ret; @@ -94,14 +89,6 @@ static irqreturn_t dp83td510_handle_interrupt(struct phy_device *phydev) { int ret; - ret = phy_read_mmd(phydev, MDIO_MMD_VEND2, DP83TD510E_PHY_STS); - if (ret < 0) { - phy_error(phydev); - return IRQ_NONE; - } else if (!(ret & DP83TD510E_STS_MII_INT)) { - return IRQ_NONE; - } - /* Read the current enabled interrupts */ ret = phy_read_mmd(phydev, MDIO_MMD_VEND2, DP83TD510E_INTERRUPT_REG_1); if (ret < 0) { diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c index 389f33a12534419ded1015b780fd4dbb1b32a55c..8b3618d3da4aa552596a3e22a8ded47204335be0 100644 --- a/drivers/net/phy/mdio_bus.c +++ b/drivers/net/phy/mdio_bus.c @@ -1287,7 +1287,7 @@ EXPORT_SYMBOL_GPL(mdiobus_modify_changed); * @mask: bit mask of bits to clear * @set: bit mask of bits to set */ -int mdiobus_c45_modify_changed(struct mii_bus *bus, int devad, int addr, +int mdiobus_c45_modify_changed(struct mii_bus *bus, int addr, int devad, u32 regnum, u16 mask, u16 set) { int err; diff --git a/drivers/net/phy/mediatek-ge-soc.c b/drivers/net/phy/mediatek-ge-soc.c new file mode 100644 index 0000000000000000000000000000000000000000..95369171a7ba6f656daeba49f2e4f37c8195486a --- /dev/null +++ b/drivers/net/phy/mediatek-ge-soc.c @@ -0,0 +1,1116 @@ +// SPDX-License-Identifier: GPL-2.0+ +#include +#include +#include +#include +#include +#include +#include + +#define MTK_GPHY_ID_MT7981 0x03a29461 +#define MTK_GPHY_ID_MT7988 0x03a29481 + +#define MTK_EXT_PAGE_ACCESS 0x1f +#define MTK_PHY_PAGE_STANDARD 0x0000 +#define MTK_PHY_PAGE_EXTENDED_3 0x0003 + +#define MTK_PHY_LPI_REG_14 0x14 +#define MTK_PHY_LPI_WAKE_TIMER_1000_MASK GENMASK(8, 0) + +#define MTK_PHY_LPI_REG_1c 0x1c +#define MTK_PHY_SMI_DET_ON_THRESH_MASK GENMASK(13, 8) + +#define MTK_PHY_PAGE_EXTENDED_2A30 0x2a30 +#define MTK_PHY_PAGE_EXTENDED_52B5 0x52b5 + +#define ANALOG_INTERNAL_OPERATION_MAX_US 20 +#define TXRESERVE_MIN 0 +#define TXRESERVE_MAX 7 + +#define MTK_PHY_ANARG_RG 0x10 +#define MTK_PHY_TCLKOFFSET_MASK GENMASK(12, 8) + +/* Registers on MDIO_MMD_VEND1 */ +#define MTK_PHY_TXVLD_DA_RG 0x12 +#define MTK_PHY_DA_TX_I2MPB_A_GBE_MASK GENMASK(15, 10) +#define MTK_PHY_DA_TX_I2MPB_A_TBT_MASK GENMASK(5, 0) + +#define MTK_PHY_TX_I2MPB_TEST_MODE_A2 0x16 +#define MTK_PHY_DA_TX_I2MPB_A_HBT_MASK GENMASK(15, 10) +#define MTK_PHY_DA_TX_I2MPB_A_TST_MASK GENMASK(5, 0) + +#define MTK_PHY_TX_I2MPB_TEST_MODE_B1 0x17 +#define MTK_PHY_DA_TX_I2MPB_B_GBE_MASK GENMASK(13, 8) +#define MTK_PHY_DA_TX_I2MPB_B_TBT_MASK GENMASK(5, 0) + +#define MTK_PHY_TX_I2MPB_TEST_MODE_B2 0x18 +#define MTK_PHY_DA_TX_I2MPB_B_HBT_MASK GENMASK(13, 8) +#define MTK_PHY_DA_TX_I2MPB_B_TST_MASK GENMASK(5, 0) + +#define MTK_PHY_TX_I2MPB_TEST_MODE_C1 0x19 +#define MTK_PHY_DA_TX_I2MPB_C_GBE_MASK GENMASK(13, 8) +#define MTK_PHY_DA_TX_I2MPB_C_TBT_MASK GENMASK(5, 0) + +#define MTK_PHY_TX_I2MPB_TEST_MODE_C2 0x20 +#define MTK_PHY_DA_TX_I2MPB_C_HBT_MASK GENMASK(13, 8) +#define MTK_PHY_DA_TX_I2MPB_C_TST_MASK GENMASK(5, 0) + +#define MTK_PHY_TX_I2MPB_TEST_MODE_D1 0x21 +#define MTK_PHY_DA_TX_I2MPB_D_GBE_MASK GENMASK(13, 8) +#define MTK_PHY_DA_TX_I2MPB_D_TBT_MASK GENMASK(5, 0) + +#define MTK_PHY_TX_I2MPB_TEST_MODE_D2 0x22 +#define MTK_PHY_DA_TX_I2MPB_D_HBT_MASK GENMASK(13, 8) +#define MTK_PHY_DA_TX_I2MPB_D_TST_MASK GENMASK(5, 0) + +#define MTK_PHY_RXADC_CTRL_RG7 0xc6 +#define MTK_PHY_DA_AD_BUF_BIAS_LP_MASK GENMASK(9, 8) + +#define MTK_PHY_RXADC_CTRL_RG9 0xc8 +#define MTK_PHY_DA_RX_PSBN_TBT_MASK GENMASK(14, 12) +#define MTK_PHY_DA_RX_PSBN_HBT_MASK GENMASK(10, 8) +#define MTK_PHY_DA_RX_PSBN_GBE_MASK GENMASK(6, 4) +#define MTK_PHY_DA_RX_PSBN_LP_MASK GENMASK(2, 0) + +#define MTK_PHY_LDO_OUTPUT_V 0xd7 + +#define MTK_PHY_RG_ANA_CAL_RG0 0xdb +#define MTK_PHY_RG_CAL_CKINV BIT(12) +#define MTK_PHY_RG_ANA_CALEN BIT(8) +#define MTK_PHY_RG_ZCALEN_A BIT(0) + +#define MTK_PHY_RG_ANA_CAL_RG1 0xdc +#define MTK_PHY_RG_ZCALEN_B BIT(12) +#define MTK_PHY_RG_ZCALEN_C BIT(8) +#define MTK_PHY_RG_ZCALEN_D BIT(4) +#define MTK_PHY_RG_TXVOS_CALEN BIT(0) + +#define MTK_PHY_RG_ANA_CAL_RG5 0xe0 +#define MTK_PHY_RG_REXT_TRIM_MASK GENMASK(13, 8) + +#define MTK_PHY_RG_TX_FILTER 0xfe + +#define MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG120 0x120 +#define MTK_PHY_LPI_SIG_EN_LO_THRESH1000_MASK GENMASK(12, 8) +#define MTK_PHY_LPI_SIG_EN_HI_THRESH1000_MASK GENMASK(4, 0) + +#define MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG122 0x122 +#define MTK_PHY_LPI_NORM_MSE_HI_THRESH1000_MASK GENMASK(7, 0) + +#define MTK_PHY_RG_TESTMUX_ADC_CTRL 0x144 +#define MTK_PHY_RG_TXEN_DIG_MASK GENMASK(5, 5) + +#define MTK_PHY_RG_CR_TX_AMP_OFFSET_A_B 0x172 +#define MTK_PHY_CR_TX_AMP_OFFSET_A_MASK GENMASK(13, 8) +#define MTK_PHY_CR_TX_AMP_OFFSET_B_MASK GENMASK(6, 0) + +#define MTK_PHY_RG_CR_TX_AMP_OFFSET_C_D 0x173 +#define MTK_PHY_CR_TX_AMP_OFFSET_C_MASK GENMASK(13, 8) +#define MTK_PHY_CR_TX_AMP_OFFSET_D_MASK GENMASK(6, 0) + +#define MTK_PHY_RG_AD_CAL_COMP 0x17a +#define MTK_PHY_AD_CAL_COMP_OUT_SHIFT (8) + +#define MTK_PHY_RG_AD_CAL_CLK 0x17b +#define MTK_PHY_DA_CAL_CLK BIT(0) + +#define MTK_PHY_RG_AD_CALIN 0x17c +#define MTK_PHY_DA_CALIN_FLAG BIT(0) + +#define MTK_PHY_RG_DASN_DAC_IN0_A 0x17d +#define MTK_PHY_DASN_DAC_IN0_A_MASK GENMASK(9, 0) + +#define MTK_PHY_RG_DASN_DAC_IN0_B 0x17e +#define MTK_PHY_DASN_DAC_IN0_B_MASK GENMASK(9, 0) + +#define MTK_PHY_RG_DASN_DAC_IN0_C 0x17f +#define MTK_PHY_DASN_DAC_IN0_C_MASK GENMASK(9, 0) + +#define MTK_PHY_RG_DASN_DAC_IN0_D 0x180 +#define MTK_PHY_DASN_DAC_IN0_D_MASK GENMASK(9, 0) + +#define MTK_PHY_RG_DASN_DAC_IN1_A 0x181 +#define MTK_PHY_DASN_DAC_IN1_A_MASK GENMASK(9, 0) + +#define MTK_PHY_RG_DASN_DAC_IN1_B 0x182 +#define MTK_PHY_DASN_DAC_IN1_B_MASK GENMASK(9, 0) + +#define MTK_PHY_RG_DASN_DAC_IN1_C 0x183 +#define MTK_PHY_DASN_DAC_IN1_C_MASK GENMASK(9, 0) + +#define MTK_PHY_RG_DASN_DAC_IN1_D 0x184 +#define MTK_PHY_DASN_DAC_IN1_D_MASK GENMASK(9, 0) + +#define MTK_PHY_RG_DEV1E_REG19b 0x19b +#define MTK_PHY_BYPASS_DSP_LPI_READY BIT(8) + +#define MTK_PHY_RG_LP_IIR2_K1_L 0x22a +#define MTK_PHY_RG_LP_IIR2_K1_U 0x22b +#define MTK_PHY_RG_LP_IIR2_K2_L 0x22c +#define MTK_PHY_RG_LP_IIR2_K2_U 0x22d +#define MTK_PHY_RG_LP_IIR2_K3_L 0x22e +#define MTK_PHY_RG_LP_IIR2_K3_U 0x22f +#define MTK_PHY_RG_LP_IIR2_K4_L 0x230 +#define MTK_PHY_RG_LP_IIR2_K4_U 0x231 +#define MTK_PHY_RG_LP_IIR2_K5_L 0x232 +#define MTK_PHY_RG_LP_IIR2_K5_U 0x233 + +#define MTK_PHY_RG_DEV1E_REG234 0x234 +#define MTK_PHY_TR_OPEN_LOOP_EN_MASK GENMASK(0, 0) +#define MTK_PHY_LPF_X_AVERAGE_MASK GENMASK(7, 4) +#define MTK_PHY_TR_LP_IIR_EEE_EN BIT(12) + +#define MTK_PHY_RG_LPF_CNT_VAL 0x235 + +#define MTK_PHY_RG_DEV1E_REG238 0x238 +#define MTK_PHY_LPI_SLV_SEND_TX_TIMER_MASK GENMASK(8, 0) +#define MTK_PHY_LPI_SLV_SEND_TX_EN BIT(12) + +#define MTK_PHY_RG_DEV1E_REG239 0x239 +#define MTK_PHY_LPI_SEND_LOC_TIMER_MASK GENMASK(8, 0) +#define MTK_PHY_LPI_TXPCS_LOC_RCV BIT(12) + +#define MTK_PHY_RG_DEV1E_REG27C 0x27c +#define MTK_PHY_VGASTATE_FFE_THR_ST1_MASK GENMASK(12, 8) +#define MTK_PHY_RG_DEV1E_REG27D 0x27d +#define MTK_PHY_VGASTATE_FFE_THR_ST2_MASK GENMASK(4, 0) + +#define MTK_PHY_RG_DEV1E_REG2C7 0x2c7 +#define MTK_PHY_MAX_GAIN_MASK GENMASK(4, 0) +#define MTK_PHY_MIN_GAIN_MASK GENMASK(12, 8) + +#define MTK_PHY_RG_DEV1E_REG2D1 0x2d1 +#define MTK_PHY_VCO_SLICER_THRESH_BITS_HIGH_EEE_MASK GENMASK(7, 0) +#define MTK_PHY_LPI_SKIP_SD_SLV_TR BIT(8) +#define MTK_PHY_LPI_TR_READY BIT(9) +#define MTK_PHY_LPI_VCO_EEE_STG0_EN BIT(10) + +#define MTK_PHY_RG_DEV1E_REG323 0x323 +#define MTK_PHY_EEE_WAKE_MAS_INT_DC BIT(0) +#define MTK_PHY_EEE_WAKE_SLV_INT_DC BIT(4) + +#define MTK_PHY_RG_DEV1E_REG324 0x324 +#define MTK_PHY_SMI_DETCNT_MAX_MASK GENMASK(5, 0) +#define MTK_PHY_SMI_DET_MAX_EN BIT(8) + +#define MTK_PHY_RG_DEV1E_REG326 0x326 +#define MTK_PHY_LPI_MODE_SD_ON BIT(0) +#define MTK_PHY_RESET_RANDUPD_CNT BIT(1) +#define MTK_PHY_TREC_UPDATE_ENAB_CLR BIT(2) +#define MTK_PHY_LPI_QUIT_WAIT_DFE_SIG_DET_OFF BIT(4) +#define MTK_PHY_TR_READY_SKIP_AFE_WAKEUP BIT(5) + +#define MTK_PHY_LDO_PUMP_EN_PAIRAB 0x502 +#define MTK_PHY_LDO_PUMP_EN_PAIRCD 0x503 + +#define MTK_PHY_DA_TX_R50_PAIR_A 0x53d +#define MTK_PHY_DA_TX_R50_PAIR_B 0x53e +#define MTK_PHY_DA_TX_R50_PAIR_C 0x53f +#define MTK_PHY_DA_TX_R50_PAIR_D 0x540 + +#define MTK_PHY_RG_BG_RASEL 0x115 +#define MTK_PHY_RG_BG_RASEL_MASK GENMASK(2, 0) + +/* These macro privides efuse parsing for internal phy. */ +#define EFS_DA_TX_I2MPB_A(x) (((x) >> 0) & GENMASK(5, 0)) +#define EFS_DA_TX_I2MPB_B(x) (((x) >> 6) & GENMASK(5, 0)) +#define EFS_DA_TX_I2MPB_C(x) (((x) >> 12) & GENMASK(5, 0)) +#define EFS_DA_TX_I2MPB_D(x) (((x) >> 18) & GENMASK(5, 0)) +#define EFS_DA_TX_AMP_OFFSET_A(x) (((x) >> 24) & GENMASK(5, 0)) + +#define EFS_DA_TX_AMP_OFFSET_B(x) (((x) >> 0) & GENMASK(5, 0)) +#define EFS_DA_TX_AMP_OFFSET_C(x) (((x) >> 6) & GENMASK(5, 0)) +#define EFS_DA_TX_AMP_OFFSET_D(x) (((x) >> 12) & GENMASK(5, 0)) +#define EFS_DA_TX_R50_A(x) (((x) >> 18) & GENMASK(5, 0)) +#define EFS_DA_TX_R50_B(x) (((x) >> 24) & GENMASK(5, 0)) + +#define EFS_DA_TX_R50_C(x) (((x) >> 0) & GENMASK(5, 0)) +#define EFS_DA_TX_R50_D(x) (((x) >> 6) & GENMASK(5, 0)) + +#define EFS_RG_BG_RASEL(x) (((x) >> 4) & GENMASK(2, 0)) +#define EFS_RG_REXT_TRIM(x) (((x) >> 7) & GENMASK(5, 0)) + +enum { + NO_PAIR, + PAIR_A, + PAIR_B, + PAIR_C, + PAIR_D, +}; + +enum { + GPHY_PORT0, + GPHY_PORT1, + GPHY_PORT2, + GPHY_PORT3, +}; + +enum calibration_mode { + EFUSE_K, + SW_K +}; + +enum CAL_ITEM { + REXT, + TX_OFFSET, + TX_AMP, + TX_R50, + TX_VCM +}; + +enum CAL_MODE { + EFUSE_M, + SW_M +}; + +static int mtk_socphy_read_page(struct phy_device *phydev) +{ + return __phy_read(phydev, MTK_EXT_PAGE_ACCESS); +} + +static int mtk_socphy_write_page(struct phy_device *phydev, int page) +{ + return __phy_write(phydev, MTK_EXT_PAGE_ACCESS, page); +} + +/* One calibration cycle consists of: + * 1.Set DA_CALIN_FLAG high to start calibration. Keep it high + * until AD_CAL_COMP is ready to output calibration result. + * 2.Wait until DA_CAL_CLK is available. + * 3.Fetch AD_CAL_COMP_OUT. + */ +static int cal_cycle(struct phy_device *phydev, int devad, + u32 regnum, u16 mask, u16 cal_val) +{ + int reg_val; + int ret; + + phy_modify_mmd(phydev, devad, regnum, + mask, cal_val); + phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_AD_CALIN, + MTK_PHY_DA_CALIN_FLAG); + + ret = phy_read_mmd_poll_timeout(phydev, MDIO_MMD_VEND1, + MTK_PHY_RG_AD_CAL_CLK, reg_val, + reg_val & MTK_PHY_DA_CAL_CLK, 500, + ANALOG_INTERNAL_OPERATION_MAX_US, false); + if (ret) { + phydev_err(phydev, "Calibration cycle timeout\n"); + return ret; + } + + phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_AD_CALIN, + MTK_PHY_DA_CALIN_FLAG); + ret = phy_read_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_AD_CAL_COMP) >> + MTK_PHY_AD_CAL_COMP_OUT_SHIFT; + phydev_dbg(phydev, "cal_val: 0x%x, ret: %d\n", cal_val, ret); + + return ret; +} + +static int rext_fill_result(struct phy_device *phydev, u16 *buf) +{ + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG5, + MTK_PHY_RG_REXT_TRIM_MASK, buf[0] << 8); + phy_modify_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_RG_BG_RASEL, + MTK_PHY_RG_BG_RASEL_MASK, buf[1]); + + return 0; +} + +static int rext_cal_efuse(struct phy_device *phydev, u32 *buf) +{ + u16 rext_cal_val[2]; + + rext_cal_val[0] = EFS_RG_REXT_TRIM(buf[3]); + rext_cal_val[1] = EFS_RG_BG_RASEL(buf[3]); + rext_fill_result(phydev, rext_cal_val); + + return 0; +} + +static int tx_offset_fill_result(struct phy_device *phydev, u16 *buf) +{ + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_CR_TX_AMP_OFFSET_A_B, + MTK_PHY_CR_TX_AMP_OFFSET_A_MASK, buf[0] << 8); + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_CR_TX_AMP_OFFSET_A_B, + MTK_PHY_CR_TX_AMP_OFFSET_B_MASK, buf[1]); + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_CR_TX_AMP_OFFSET_C_D, + MTK_PHY_CR_TX_AMP_OFFSET_C_MASK, buf[2] << 8); + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_CR_TX_AMP_OFFSET_C_D, + MTK_PHY_CR_TX_AMP_OFFSET_D_MASK, buf[3]); + + return 0; +} + +static int tx_offset_cal_efuse(struct phy_device *phydev, u32 *buf) +{ + u16 tx_offset_cal_val[4]; + + tx_offset_cal_val[0] = EFS_DA_TX_AMP_OFFSET_A(buf[0]); + tx_offset_cal_val[1] = EFS_DA_TX_AMP_OFFSET_B(buf[1]); + tx_offset_cal_val[2] = EFS_DA_TX_AMP_OFFSET_C(buf[1]); + tx_offset_cal_val[3] = EFS_DA_TX_AMP_OFFSET_D(buf[1]); + + tx_offset_fill_result(phydev, tx_offset_cal_val); + + return 0; +} + +static int tx_amp_fill_result(struct phy_device *phydev, u16 *buf) +{ + int i; + int bias[16] = {}; + const int vals_9461[16] = { 7, 1, 4, 7, + 7, 1, 4, 7, + 7, 1, 4, 7, + 7, 1, 4, 7 }; + const int vals_9481[16] = { 10, 6, 6, 10, + 10, 6, 6, 10, + 10, 6, 6, 10, + 10, 6, 6, 10 }; + switch (phydev->drv->phy_id) { + case MTK_GPHY_ID_MT7981: + /* We add some calibration to efuse values + * due to board level influence. + * GBE: +7, TBT: +1, HBT: +4, TST: +7 + */ + memcpy(bias, (const void *)vals_9461, sizeof(bias)); + break; + case MTK_GPHY_ID_MT7988: + memcpy(bias, (const void *)vals_9481, sizeof(bias)); + break; + } + + /* Prevent overflow */ + for (i = 0; i < 12; i++) { + if (buf[i >> 2] + bias[i] > 63) { + buf[i >> 2] = 63; + bias[i] = 0; + } + } + + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TXVLD_DA_RG, + MTK_PHY_DA_TX_I2MPB_A_GBE_MASK, (buf[0] + bias[0]) << 10); + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TXVLD_DA_RG, + MTK_PHY_DA_TX_I2MPB_A_TBT_MASK, buf[0] + bias[1]); + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_A2, + MTK_PHY_DA_TX_I2MPB_A_HBT_MASK, (buf[0] + bias[2]) << 10); + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_A2, + MTK_PHY_DA_TX_I2MPB_A_TST_MASK, buf[0] + bias[3]); + + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_B1, + MTK_PHY_DA_TX_I2MPB_B_GBE_MASK, (buf[1] + bias[4]) << 8); + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_B1, + MTK_PHY_DA_TX_I2MPB_B_TBT_MASK, buf[1] + bias[5]); + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_B2, + MTK_PHY_DA_TX_I2MPB_B_HBT_MASK, (buf[1] + bias[6]) << 8); + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_B2, + MTK_PHY_DA_TX_I2MPB_B_TST_MASK, buf[1] + bias[7]); + + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_C1, + MTK_PHY_DA_TX_I2MPB_C_GBE_MASK, (buf[2] + bias[8]) << 8); + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_C1, + MTK_PHY_DA_TX_I2MPB_C_TBT_MASK, buf[2] + bias[9]); + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_C2, + MTK_PHY_DA_TX_I2MPB_C_HBT_MASK, (buf[2] + bias[10]) << 8); + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_C2, + MTK_PHY_DA_TX_I2MPB_C_TST_MASK, buf[2] + bias[11]); + + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_D1, + MTK_PHY_DA_TX_I2MPB_D_GBE_MASK, (buf[3] + bias[12]) << 8); + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_D1, + MTK_PHY_DA_TX_I2MPB_D_TBT_MASK, buf[3] + bias[13]); + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_D2, + MTK_PHY_DA_TX_I2MPB_D_HBT_MASK, (buf[3] + bias[14]) << 8); + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_D2, + MTK_PHY_DA_TX_I2MPB_D_TST_MASK, buf[3] + bias[15]); + + return 0; +} + +static int tx_amp_cal_efuse(struct phy_device *phydev, u32 *buf) +{ + u16 tx_amp_cal_val[4]; + + tx_amp_cal_val[0] = EFS_DA_TX_I2MPB_A(buf[0]); + tx_amp_cal_val[1] = EFS_DA_TX_I2MPB_B(buf[0]); + tx_amp_cal_val[2] = EFS_DA_TX_I2MPB_C(buf[0]); + tx_amp_cal_val[3] = EFS_DA_TX_I2MPB_D(buf[0]); + tx_amp_fill_result(phydev, tx_amp_cal_val); + + return 0; +} + +static int tx_r50_fill_result(struct phy_device *phydev, u16 tx_r50_cal_val, + u8 txg_calen_x) +{ + int bias = 0; + u16 reg, val; + + if (phydev->drv->phy_id == MTK_GPHY_ID_MT7988) + bias = -2; + + val = clamp_val(bias + tx_r50_cal_val, 0, 63); + + switch (txg_calen_x) { + case PAIR_A: + reg = MTK_PHY_DA_TX_R50_PAIR_A; + break; + case PAIR_B: + reg = MTK_PHY_DA_TX_R50_PAIR_B; + break; + case PAIR_C: + reg = MTK_PHY_DA_TX_R50_PAIR_C; + break; + case PAIR_D: + reg = MTK_PHY_DA_TX_R50_PAIR_D; + break; + default: + return -EINVAL; + } + + phy_write_mmd(phydev, MDIO_MMD_VEND1, reg, val | val << 8); + + return 0; +} + +static int tx_r50_cal_efuse(struct phy_device *phydev, u32 *buf, + u8 txg_calen_x) +{ + u16 tx_r50_cal_val; + + switch (txg_calen_x) { + case PAIR_A: + tx_r50_cal_val = EFS_DA_TX_R50_A(buf[1]); + break; + case PAIR_B: + tx_r50_cal_val = EFS_DA_TX_R50_B(buf[1]); + break; + case PAIR_C: + tx_r50_cal_val = EFS_DA_TX_R50_C(buf[2]); + break; + case PAIR_D: + tx_r50_cal_val = EFS_DA_TX_R50_D(buf[2]); + break; + default: + return -EINVAL; + } + tx_r50_fill_result(phydev, tx_r50_cal_val, txg_calen_x); + + return 0; +} + +static int tx_vcm_cal_sw(struct phy_device *phydev, u8 rg_txreserve_x) +{ + u8 lower_idx, upper_idx, txreserve_val; + u8 lower_ret, upper_ret; + int ret; + + phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG0, + MTK_PHY_RG_ANA_CALEN); + phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG0, + MTK_PHY_RG_CAL_CKINV); + phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG1, + MTK_PHY_RG_TXVOS_CALEN); + + switch (rg_txreserve_x) { + case PAIR_A: + phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, + MTK_PHY_RG_DASN_DAC_IN0_A, + MTK_PHY_DASN_DAC_IN0_A_MASK); + phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, + MTK_PHY_RG_DASN_DAC_IN1_A, + MTK_PHY_DASN_DAC_IN1_A_MASK); + phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, + MTK_PHY_RG_ANA_CAL_RG0, + MTK_PHY_RG_ZCALEN_A); + break; + case PAIR_B: + phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, + MTK_PHY_RG_DASN_DAC_IN0_B, + MTK_PHY_DASN_DAC_IN0_B_MASK); + phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, + MTK_PHY_RG_DASN_DAC_IN1_B, + MTK_PHY_DASN_DAC_IN1_B_MASK); + phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, + MTK_PHY_RG_ANA_CAL_RG1, + MTK_PHY_RG_ZCALEN_B); + break; + case PAIR_C: + phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, + MTK_PHY_RG_DASN_DAC_IN0_C, + MTK_PHY_DASN_DAC_IN0_C_MASK); + phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, + MTK_PHY_RG_DASN_DAC_IN1_C, + MTK_PHY_DASN_DAC_IN1_C_MASK); + phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, + MTK_PHY_RG_ANA_CAL_RG1, + MTK_PHY_RG_ZCALEN_C); + break; + case PAIR_D: + phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, + MTK_PHY_RG_DASN_DAC_IN0_D, + MTK_PHY_DASN_DAC_IN0_D_MASK); + phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, + MTK_PHY_RG_DASN_DAC_IN1_D, + MTK_PHY_DASN_DAC_IN1_D_MASK); + phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, + MTK_PHY_RG_ANA_CAL_RG1, + MTK_PHY_RG_ZCALEN_D); + break; + default: + ret = -EINVAL; + goto restore; + } + + lower_idx = TXRESERVE_MIN; + upper_idx = TXRESERVE_MAX; + + phydev_dbg(phydev, "Start TX-VCM SW cal.\n"); + while ((upper_idx - lower_idx) > 1) { + txreserve_val = DIV_ROUND_CLOSEST(lower_idx + upper_idx, 2); + ret = cal_cycle(phydev, MDIO_MMD_VEND1, MTK_PHY_RXADC_CTRL_RG9, + MTK_PHY_DA_RX_PSBN_TBT_MASK | + MTK_PHY_DA_RX_PSBN_HBT_MASK | + MTK_PHY_DA_RX_PSBN_GBE_MASK | + MTK_PHY_DA_RX_PSBN_LP_MASK, + txreserve_val << 12 | txreserve_val << 8 | + txreserve_val << 4 | txreserve_val); + if (ret == 1) { + upper_idx = txreserve_val; + upper_ret = ret; + } else if (ret == 0) { + lower_idx = txreserve_val; + lower_ret = ret; + } else { + goto restore; + } + } + + if (lower_idx == TXRESERVE_MIN) { + lower_ret = cal_cycle(phydev, MDIO_MMD_VEND1, + MTK_PHY_RXADC_CTRL_RG9, + MTK_PHY_DA_RX_PSBN_TBT_MASK | + MTK_PHY_DA_RX_PSBN_HBT_MASK | + MTK_PHY_DA_RX_PSBN_GBE_MASK | + MTK_PHY_DA_RX_PSBN_LP_MASK, + lower_idx << 12 | lower_idx << 8 | + lower_idx << 4 | lower_idx); + ret = lower_ret; + } else if (upper_idx == TXRESERVE_MAX) { + upper_ret = cal_cycle(phydev, MDIO_MMD_VEND1, + MTK_PHY_RXADC_CTRL_RG9, + MTK_PHY_DA_RX_PSBN_TBT_MASK | + MTK_PHY_DA_RX_PSBN_HBT_MASK | + MTK_PHY_DA_RX_PSBN_GBE_MASK | + MTK_PHY_DA_RX_PSBN_LP_MASK, + upper_idx << 12 | upper_idx << 8 | + upper_idx << 4 | upper_idx); + ret = upper_ret; + } + if (ret < 0) + goto restore; + + /* We calibrate TX-VCM in different logic. Check upper index and then + * lower index. If this calibration is valid, apply lower index's result. + */ + ret = upper_ret - lower_ret; + if (ret == 1) { + ret = 0; + /* Make sure we use upper_idx in our calibration system */ + cal_cycle(phydev, MDIO_MMD_VEND1, MTK_PHY_RXADC_CTRL_RG9, + MTK_PHY_DA_RX_PSBN_TBT_MASK | + MTK_PHY_DA_RX_PSBN_HBT_MASK | + MTK_PHY_DA_RX_PSBN_GBE_MASK | + MTK_PHY_DA_RX_PSBN_LP_MASK, + upper_idx << 12 | upper_idx << 8 | + upper_idx << 4 | upper_idx); + phydev_dbg(phydev, "TX-VCM SW cal result: 0x%x\n", upper_idx); + } else if (lower_idx == TXRESERVE_MIN && upper_ret == 1 && + lower_ret == 1) { + ret = 0; + cal_cycle(phydev, MDIO_MMD_VEND1, MTK_PHY_RXADC_CTRL_RG9, + MTK_PHY_DA_RX_PSBN_TBT_MASK | + MTK_PHY_DA_RX_PSBN_HBT_MASK | + MTK_PHY_DA_RX_PSBN_GBE_MASK | + MTK_PHY_DA_RX_PSBN_LP_MASK, + lower_idx << 12 | lower_idx << 8 | + lower_idx << 4 | lower_idx); + phydev_warn(phydev, "TX-VCM SW cal result at low margin 0x%x\n", + lower_idx); + } else if (upper_idx == TXRESERVE_MAX && upper_ret == 0 && + lower_ret == 0) { + ret = 0; + phydev_warn(phydev, "TX-VCM SW cal result at high margin 0x%x\n", + upper_idx); + } else { + ret = -EINVAL; + } + +restore: + phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG0, + MTK_PHY_RG_ANA_CALEN); + phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG1, + MTK_PHY_RG_TXVOS_CALEN); + phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG0, + MTK_PHY_RG_ZCALEN_A); + phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG1, + MTK_PHY_RG_ZCALEN_B | MTK_PHY_RG_ZCALEN_C | + MTK_PHY_RG_ZCALEN_D); + + return ret; +} + +static void mt798x_phy_common_finetune(struct phy_device *phydev) +{ + phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5); + /* EnabRandUpdTrig = 1 */ + __phy_write(phydev, 0x11, 0x2f00); + __phy_write(phydev, 0x12, 0xe); + __phy_write(phydev, 0x10, 0x8fb0); + + /* NormMseLoThresh = 85 */ + __phy_write(phydev, 0x11, 0x55a0); + __phy_write(phydev, 0x12, 0x0); + __phy_write(phydev, 0x10, 0x83aa); + + /* TrFreeze = 0 */ + __phy_write(phydev, 0x11, 0x0); + __phy_write(phydev, 0x12, 0x0); + __phy_write(phydev, 0x10, 0x9686); + + /* SSTrKp1000Slv = 5 */ + __phy_write(phydev, 0x11, 0xbaef); + __phy_write(phydev, 0x12, 0x2e); + __phy_write(phydev, 0x10, 0x968c); + + /* MrvlTrFix100Kp = 3, MrvlTrFix100Kf = 2, + * MrvlTrFix1000Kp = 3, MrvlTrFix1000Kf = 2 + */ + __phy_write(phydev, 0x11, 0xd10a); + __phy_write(phydev, 0x12, 0x34); + __phy_write(phydev, 0x10, 0x8f82); + + /* VcoSlicerThreshBitsHigh */ + __phy_write(phydev, 0x11, 0x5555); + __phy_write(phydev, 0x12, 0x55); + __phy_write(phydev, 0x10, 0x8ec0); + phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0); + + /* TR_OPEN_LOOP_EN = 1, lpf_x_average = 9*/ + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG234, + MTK_PHY_TR_OPEN_LOOP_EN_MASK | MTK_PHY_LPF_X_AVERAGE_MASK, + BIT(0) | FIELD_PREP(MTK_PHY_LPF_X_AVERAGE_MASK, 0x9)); + + /* rg_tr_lpf_cnt_val = 512 */ + phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LPF_CNT_VAL, 0x200); + + /* IIR2 related */ + phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K1_L, 0x82); + phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K1_U, 0x0); + phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K2_L, 0x103); + phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K2_U, 0x0); + phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K3_L, 0x82); + phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K3_U, 0x0); + phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K4_L, 0xd177); + phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K4_U, 0x3); + phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K5_L, 0x2c82); + phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K5_U, 0xe); + + /* FFE peaking */ + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG27C, + MTK_PHY_VGASTATE_FFE_THR_ST1_MASK, 0x1b << 8); + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG27D, + MTK_PHY_VGASTATE_FFE_THR_ST2_MASK, 0x1e); + + /* Disable LDO pump */ + phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_LDO_PUMP_EN_PAIRAB, 0x0); + phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_LDO_PUMP_EN_PAIRCD, 0x0); + /* Adjust LDO output voltage */ + phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_LDO_OUTPUT_V, 0x2222); +} + +static void mt7981_phy_finetune(struct phy_device *phydev) +{ + u16 val[8] = { 0x01ce, 0x01c1, + 0x020f, 0x0202, + 0x03d0, 0x03c0, + 0x0013, 0x0005 }; + int i, k; + + /* 100M eye finetune: + * Keep middle level of TX MLT3 shapper as default. + * Only change TX MLT3 overshoot level here. + */ + for (k = 0, i = 1; i < 12; i++) { + if (i % 3 == 0) + continue; + phy_write_mmd(phydev, MDIO_MMD_VEND1, i, val[k++]); + } + + phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5); + /* SlvDSPreadyTime = 24, MasDSPreadyTime = 24 */ + __phy_write(phydev, 0x11, 0xc71); + __phy_write(phydev, 0x12, 0xc); + __phy_write(phydev, 0x10, 0x8fae); + + /* ResetSyncOffset = 6 */ + __phy_write(phydev, 0x11, 0x600); + __phy_write(phydev, 0x12, 0x0); + __phy_write(phydev, 0x10, 0x8fc0); + + /* VgaDecRate = 1 */ + __phy_write(phydev, 0x11, 0x4c2a); + __phy_write(phydev, 0x12, 0x3e); + __phy_write(phydev, 0x10, 0x8fa4); + + /* FfeUpdGainForce = 4 */ + __phy_write(phydev, 0x11, 0x240); + __phy_write(phydev, 0x12, 0x0); + __phy_write(phydev, 0x10, 0x9680); + + phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0); +} + +static void mt7988_phy_finetune(struct phy_device *phydev) +{ + u16 val[12] = { 0x0187, 0x01cd, 0x01c8, 0x0182, + 0x020d, 0x0206, 0x0384, 0x03d0, + 0x03c6, 0x030a, 0x0011, 0x0005 }; + int i; + + /* Set default MLT3 shaper first */ + for (i = 0; i < 12; i++) + phy_write_mmd(phydev, MDIO_MMD_VEND1, i, val[i]); + + /* TCT finetune */ + phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_TX_FILTER, 0x5); + + /* Disable TX power saving */ + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RXADC_CTRL_RG7, + MTK_PHY_DA_AD_BUF_BIAS_LP_MASK, 0x3 << 8); + + phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5); + + /* SlvDSPreadyTime = 24, MasDSPreadyTime = 12 */ + __phy_write(phydev, 0x11, 0x671); + __phy_write(phydev, 0x12, 0xc); + __phy_write(phydev, 0x10, 0x8fae); + + /* ResetSyncOffset = 5 */ + __phy_write(phydev, 0x11, 0x500); + __phy_write(phydev, 0x12, 0x0); + __phy_write(phydev, 0x10, 0x8fc0); + + /* VgaDecRate is 1 at default on mt7988 */ + + phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0); + + phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_2A30); + /* TxClkOffset = 2 */ + __phy_modify(phydev, MTK_PHY_ANARG_RG, MTK_PHY_TCLKOFFSET_MASK, + FIELD_PREP(MTK_PHY_TCLKOFFSET_MASK, 0x2)); + phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0); +} + +static void mt798x_phy_eee(struct phy_device *phydev) +{ + phy_modify_mmd(phydev, MDIO_MMD_VEND1, + MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG120, + MTK_PHY_LPI_SIG_EN_LO_THRESH1000_MASK | + MTK_PHY_LPI_SIG_EN_HI_THRESH1000_MASK, + FIELD_PREP(MTK_PHY_LPI_SIG_EN_LO_THRESH1000_MASK, 0x0) | + FIELD_PREP(MTK_PHY_LPI_SIG_EN_HI_THRESH1000_MASK, 0x14)); + + phy_modify_mmd(phydev, MDIO_MMD_VEND1, + MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG122, + MTK_PHY_LPI_NORM_MSE_HI_THRESH1000_MASK, + FIELD_PREP(MTK_PHY_LPI_NORM_MSE_HI_THRESH1000_MASK, + 0xff)); + + phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, + MTK_PHY_RG_TESTMUX_ADC_CTRL, + MTK_PHY_RG_TXEN_DIG_MASK); + + phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, + MTK_PHY_RG_DEV1E_REG19b, MTK_PHY_BYPASS_DSP_LPI_READY); + + phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, + MTK_PHY_RG_DEV1E_REG234, MTK_PHY_TR_LP_IIR_EEE_EN); + + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG238, + MTK_PHY_LPI_SLV_SEND_TX_TIMER_MASK | + MTK_PHY_LPI_SLV_SEND_TX_EN, + FIELD_PREP(MTK_PHY_LPI_SLV_SEND_TX_TIMER_MASK, 0x120)); + + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG239, + MTK_PHY_LPI_SEND_LOC_TIMER_MASK | + MTK_PHY_LPI_TXPCS_LOC_RCV, + FIELD_PREP(MTK_PHY_LPI_SEND_LOC_TIMER_MASK, 0x117)); + + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG2C7, + MTK_PHY_MAX_GAIN_MASK | MTK_PHY_MIN_GAIN_MASK, + FIELD_PREP(MTK_PHY_MAX_GAIN_MASK, 0x8) | + FIELD_PREP(MTK_PHY_MIN_GAIN_MASK, 0x13)); + + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG2D1, + MTK_PHY_VCO_SLICER_THRESH_BITS_HIGH_EEE_MASK, + FIELD_PREP(MTK_PHY_VCO_SLICER_THRESH_BITS_HIGH_EEE_MASK, + 0x33) | + MTK_PHY_LPI_SKIP_SD_SLV_TR | MTK_PHY_LPI_TR_READY | + MTK_PHY_LPI_VCO_EEE_STG0_EN); + + phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG323, + MTK_PHY_EEE_WAKE_MAS_INT_DC | + MTK_PHY_EEE_WAKE_SLV_INT_DC); + + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG324, + MTK_PHY_SMI_DETCNT_MAX_MASK, + FIELD_PREP(MTK_PHY_SMI_DETCNT_MAX_MASK, 0x3f) | + MTK_PHY_SMI_DET_MAX_EN); + + phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG326, + MTK_PHY_LPI_MODE_SD_ON | MTK_PHY_RESET_RANDUPD_CNT | + MTK_PHY_TREC_UPDATE_ENAB_CLR | + MTK_PHY_LPI_QUIT_WAIT_DFE_SIG_DET_OFF | + MTK_PHY_TR_READY_SKIP_AFE_WAKEUP); + + phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5); + /* Regsigdet_sel_1000 = 0 */ + __phy_write(phydev, 0x11, 0xb); + __phy_write(phydev, 0x12, 0x0); + __phy_write(phydev, 0x10, 0x9690); + + /* REG_EEE_st2TrKf1000 = 3 */ + __phy_write(phydev, 0x11, 0x114f); + __phy_write(phydev, 0x12, 0x2); + __phy_write(phydev, 0x10, 0x969a); + + /* RegEEE_slv_wake_tr_timer_tar = 6, RegEEE_slv_remtx_timer_tar = 20 */ + __phy_write(phydev, 0x11, 0x3028); + __phy_write(phydev, 0x12, 0x0); + __phy_write(phydev, 0x10, 0x969e); + + /* RegEEE_slv_wake_int_timer_tar = 8 */ + __phy_write(phydev, 0x11, 0x5010); + __phy_write(phydev, 0x12, 0x0); + __phy_write(phydev, 0x10, 0x96a0); + + /* RegEEE_trfreeze_timer2 = 586 */ + __phy_write(phydev, 0x11, 0x24a); + __phy_write(phydev, 0x12, 0x0); + __phy_write(phydev, 0x10, 0x96a8); + + /* RegEEE100Stg1_tar = 16 */ + __phy_write(phydev, 0x11, 0x3210); + __phy_write(phydev, 0x12, 0x0); + __phy_write(phydev, 0x10, 0x96b8); + + /* REGEEE_wake_slv_tr_wait_dfesigdet_en = 1 */ + __phy_write(phydev, 0x11, 0x1463); + __phy_write(phydev, 0x12, 0x0); + __phy_write(phydev, 0x10, 0x96ca); + + /* DfeTailEnableVgaThresh1000 = 27 */ + __phy_write(phydev, 0x11, 0x36); + __phy_write(phydev, 0x12, 0x0); + __phy_write(phydev, 0x10, 0x8f80); + phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0); + + phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_3); + __phy_modify(phydev, MTK_PHY_LPI_REG_14, MTK_PHY_LPI_WAKE_TIMER_1000_MASK, + FIELD_PREP(MTK_PHY_LPI_WAKE_TIMER_1000_MASK, 0x19c)); + + __phy_modify(phydev, MTK_PHY_LPI_REG_1c, MTK_PHY_SMI_DET_ON_THRESH_MASK, + FIELD_PREP(MTK_PHY_SMI_DET_ON_THRESH_MASK, 0xc)); + phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0); + + phy_modify_mmd(phydev, MDIO_MMD_VEND1, + MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG122, + MTK_PHY_LPI_NORM_MSE_HI_THRESH1000_MASK, + FIELD_PREP(MTK_PHY_LPI_NORM_MSE_HI_THRESH1000_MASK, 0xff)); +} + +static int cal_sw(struct phy_device *phydev, enum CAL_ITEM cal_item, + u8 start_pair, u8 end_pair) +{ + u8 pair_n; + int ret; + + for (pair_n = start_pair; pair_n <= end_pair; pair_n++) { + /* TX_OFFSET & TX_AMP have no SW calibration. */ + switch (cal_item) { + case TX_VCM: + ret = tx_vcm_cal_sw(phydev, pair_n); + break; + default: + return -EINVAL; + } + if (ret) + return ret; + } + return 0; +} + +static int cal_efuse(struct phy_device *phydev, enum CAL_ITEM cal_item, + u8 start_pair, u8 end_pair, u32 *buf) +{ + u8 pair_n; + int ret; + + for (pair_n = start_pair; pair_n <= end_pair; pair_n++) { + /* TX_VCM has no efuse calibration. */ + switch (cal_item) { + case REXT: + ret = rext_cal_efuse(phydev, buf); + break; + case TX_OFFSET: + ret = tx_offset_cal_efuse(phydev, buf); + break; + case TX_AMP: + ret = tx_amp_cal_efuse(phydev, buf); + break; + case TX_R50: + ret = tx_r50_cal_efuse(phydev, buf, pair_n); + break; + default: + return -EINVAL; + } + if (ret) + return ret; + } + + return 0; +} + +static int start_cal(struct phy_device *phydev, enum CAL_ITEM cal_item, + enum CAL_MODE cal_mode, u8 start_pair, + u8 end_pair, u32 *buf) +{ + int ret; + + switch (cal_mode) { + case EFUSE_M: + ret = cal_efuse(phydev, cal_item, start_pair, + end_pair, buf); + break; + case SW_M: + ret = cal_sw(phydev, cal_item, start_pair, end_pair); + break; + default: + return -EINVAL; + } + + if (ret) { + phydev_err(phydev, "cal %d failed\n", cal_item); + return -EIO; + } + + return 0; +} + +static int mt798x_phy_calibration(struct phy_device *phydev) +{ + int ret = 0; + u32 *buf; + size_t len; + struct nvmem_cell *cell; + + cell = nvmem_cell_get(&phydev->mdio.dev, "phy-cal-data"); + if (IS_ERR(cell)) { + if (PTR_ERR(cell) == -EPROBE_DEFER) + return PTR_ERR(cell); + return 0; + } + + buf = (u32 *)nvmem_cell_read(cell, &len); + if (IS_ERR(buf)) + return PTR_ERR(buf); + nvmem_cell_put(cell); + + if (!buf[0] || !buf[1] || !buf[2] || !buf[3] || len < 4 * sizeof(u32)) { + phydev_err(phydev, "invalid efuse data\n"); + ret = -EINVAL; + goto out; + } + + ret = start_cal(phydev, REXT, EFUSE_M, NO_PAIR, NO_PAIR, buf); + if (ret) + goto out; + ret = start_cal(phydev, TX_OFFSET, EFUSE_M, NO_PAIR, NO_PAIR, buf); + if (ret) + goto out; + ret = start_cal(phydev, TX_AMP, EFUSE_M, NO_PAIR, NO_PAIR, buf); + if (ret) + goto out; + ret = start_cal(phydev, TX_R50, EFUSE_M, PAIR_A, PAIR_D, buf); + if (ret) + goto out; + ret = start_cal(phydev, TX_VCM, SW_M, PAIR_A, PAIR_A, buf); + if (ret) + goto out; + +out: + kfree(buf); + return ret; +} + +static int mt798x_phy_config_init(struct phy_device *phydev) +{ + switch (phydev->drv->phy_id) { + case MTK_GPHY_ID_MT7981: + mt7981_phy_finetune(phydev); + break; + case MTK_GPHY_ID_MT7988: + mt7988_phy_finetune(phydev); + break; + } + + mt798x_phy_common_finetune(phydev); + mt798x_phy_eee(phydev); + + return mt798x_phy_calibration(phydev); +} + +static struct phy_driver mtk_socphy_driver[] = { + { + PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7981), + .name = "MediaTek MT7981 PHY", + .config_init = mt798x_phy_config_init, + .config_intr = genphy_no_config_intr, + .handle_interrupt = genphy_handle_interrupt_no_ack, + .probe = mt798x_phy_calibration, + .suspend = genphy_suspend, + .resume = genphy_resume, + .read_page = mtk_socphy_read_page, + .write_page = mtk_socphy_write_page, + }, + { + PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7988), + .name = "MediaTek MT7988 PHY", + .config_init = mt798x_phy_config_init, + .config_intr = genphy_no_config_intr, + .handle_interrupt = genphy_handle_interrupt_no_ack, + .probe = mt798x_phy_calibration, + .suspend = genphy_suspend, + .resume = genphy_resume, + .read_page = mtk_socphy_read_page, + .write_page = mtk_socphy_write_page, + }, +}; + +module_phy_driver(mtk_socphy_driver); + +static struct mdio_device_id __maybe_unused mtk_socphy_tbl[] = { + { PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7981) }, + { PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7988) }, + { } +}; + +MODULE_DESCRIPTION("MediaTek SoC Gigabit Ethernet PHY driver"); +MODULE_AUTHOR("Daniel Golle "); +MODULE_AUTHOR("SkyLake Huang "); +MODULE_LICENSE("GPL"); + +MODULE_DEVICE_TABLE(mdio, mtk_socphy_tbl); diff --git a/drivers/net/phy/mediatek-ge.c b/drivers/net/phy/mediatek-ge.c index 68ee434f9dea31952010b808793b195698fbc344..a493ae01b267a21ae778a4d72a50e6155bad1735 100644 --- a/drivers/net/phy/mediatek-ge.c +++ b/drivers/net/phy/mediatek-ge.c @@ -102,7 +102,8 @@ static struct phy_driver mtk_gephy_driver[] = { module_phy_driver(mtk_gephy_driver); static struct mdio_device_id __maybe_unused mtk_gephy_tbl[] = { - { PHY_ID_MATCH_VENDOR(0x03a29400) }, + { PHY_ID_MATCH_EXACT(0x03a29441) }, + { PHY_ID_MATCH_EXACT(0x03a29412) }, { } }; diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c index 3f81bb8dac44d64af61645f03dc7cfdf2fb7a4c5..b6d7981b2d1ee7f295b9ed9346a1f77489311360 100644 --- a/drivers/net/phy/micrel.c +++ b/drivers/net/phy/micrel.c @@ -252,6 +252,9 @@ #define PS_TO_REG 200 #define FIFO_SIZE 8 +/* Delay used to get the second part from the LTC */ +#define LAN8841_GET_SEC_LTC_DELAY (500 * NSEC_PER_MSEC) + struct kszphy_hw_stat { const char *string; u8 reg; @@ -319,6 +322,10 @@ struct kszphy_ptp_priv { /* Lock for ptp_clock */ struct mutex ptp_lock; struct ptp_pin_desc *pin_config; + + s64 seconds; + /* Lock for accessing seconds */ + spinlock_t seconds_lock; }; struct kszphy_priv { @@ -637,7 +644,7 @@ static int ksz8051_ksz8795_match_phy_device(struct phy_device *phydev, { int ret; - if ((phydev->phy_id & MICREL_PHY_ID_MASK) != PHY_ID_KSZ8051) + if (!phy_id_compare(phydev->phy_id, PHY_ID_KSZ8051, MICREL_PHY_ID_MASK)) return 0; ret = phy_read(phydev, MII_BMSR); @@ -1566,7 +1573,7 @@ static int ksz9x31_cable_test_fault_length(struct phy_device *phydev, u16 stat) * * distance to fault = (VCT_DATA - 22) * 4 / cable propagation velocity */ - if ((phydev->phy_id & MICREL_PHY_ID_MASK) == PHY_ID_KSZ9131) + if (phydev_id_compare(phydev, PHY_ID_KSZ9131)) dt = clamp(dt - 22, 0, 255); return (dt * 400) / 10; @@ -1774,6 +1781,79 @@ static int ksz886x_read_status(struct phy_device *phydev) return genphy_read_status(phydev); } +struct ksz9477_errata_write { + u8 dev_addr; + u8 reg_addr; + u16 val; +}; + +static const struct ksz9477_errata_write ksz9477_errata_writes[] = { + /* Register settings are needed to improve PHY receive performance */ + {0x01, 0x6f, 0xdd0b}, + {0x01, 0x8f, 0x6032}, + {0x01, 0x9d, 0x248c}, + {0x01, 0x75, 0x0060}, + {0x01, 0xd3, 0x7777}, + {0x1c, 0x06, 0x3008}, + {0x1c, 0x08, 0x2000}, + + /* Transmit waveform amplitude can be improved (1000BASE-T, 100BASE-TX, 10BASE-Te) */ + {0x1c, 0x04, 0x00d0}, + + /* Energy Efficient Ethernet (EEE) feature select must be manually disabled */ + {0x07, 0x3c, 0x0000}, + + /* Register settings are required to meet data sheet supply current specifications */ + {0x1c, 0x13, 0x6eff}, + {0x1c, 0x14, 0xe6ff}, + {0x1c, 0x15, 0x6eff}, + {0x1c, 0x16, 0xe6ff}, + {0x1c, 0x17, 0x00ff}, + {0x1c, 0x18, 0x43ff}, + {0x1c, 0x19, 0xc3ff}, + {0x1c, 0x1a, 0x6fff}, + {0x1c, 0x1b, 0x07ff}, + {0x1c, 0x1c, 0x0fff}, + {0x1c, 0x1d, 0xe7ff}, + {0x1c, 0x1e, 0xefff}, + {0x1c, 0x20, 0xeeee}, +}; + +static int ksz9477_config_init(struct phy_device *phydev) +{ + int err; + int i; + + /* Apply PHY settings to address errata listed in + * KSZ9477, KSZ9897, KSZ9896, KSZ9567, KSZ8565 + * Silicon Errata and Data Sheet Clarification documents. + * + * Document notes: Before configuring the PHY MMD registers, it is + * necessary to set the PHY to 100 Mbps speed with auto-negotiation + * disabled by writing to register 0xN100-0xN101. After writing the + * MMD registers, and after all errata workarounds that involve PHY + * register settings, write register 0xN100-0xN101 again to enable + * and restart auto-negotiation. + */ + err = phy_write(phydev, MII_BMCR, BMCR_SPEED100 | BMCR_FULLDPLX); + if (err) + return err; + + for (i = 0; i < ARRAY_SIZE(ksz9477_errata_writes); ++i) { + const struct ksz9477_errata_write *errata = &ksz9477_errata_writes[i]; + + err = phy_write_mmd(phydev, errata->dev_addr, errata->reg_addr, errata->val); + if (err) + return err; + } + + err = genphy_restart_aneg(phydev); + if (err) + return err; + + return kszphy_config_init(phydev); +} + static int kszphy_get_sset_count(struct phy_device *phydev) { return ARRAY_SIZE(kszphy_hw_stats); @@ -1998,7 +2078,7 @@ static __always_inline int ksz886x_cable_test_fault_length(struct phy_device *ph */ dt = FIELD_GET(data_mask, status); - if ((phydev->phy_id & MICREL_PHY_ID_MASK) == PHY_ID_LAN8814) + if (phydev_id_compare(phydev, PHY_ID_LAN8814)) return ((dt - 22) * 800) / 10; else return (dt * 400) / 10; @@ -3238,6 +3318,9 @@ static int lan8814_probe(struct phy_device *phydev) #define LAN8841_PTP_CMD_CTL_PTP_RESET BIT(0) #define LAN8841_PTP_RX_PARSE_CONFIG 368 #define LAN8841_PTP_TX_PARSE_CONFIG 432 +#define LAN8841_PTP_RX_MODE 381 +#define LAN8841_PTP_INSERT_TS_EN BIT(0) +#define LAN8841_PTP_INSERT_TS_32BIT BIT(1) static int lan8841_config_init(struct phy_device *phydev) { @@ -3386,68 +3469,18 @@ static void lan8841_ptp_process_tx_ts(struct kszphy_ptp_priv *ptp_priv) lan8814_match_tx_skb(ptp_priv, sec, nsec, seq); } -#define LAN8841_PTP_RX_INGRESS_SEC_LO 389 -#define LAN8841_PTP_RX_INGRESS_SEC_HI 388 -#define LAN8841_PTP_RX_INGRESS_NS_LO 387 -#define LAN8841_PTP_RX_INGRESS_NS_HI 386 -#define LAN8841_PTP_RX_INGRESS_NSEC_HI_VALID BIT(15) -#define LAN8841_PTP_RX_MSG_HEADER2 391 - -static struct lan8814_ptp_rx_ts *lan8841_ptp_get_rx_ts(struct kszphy_ptp_priv *ptp_priv) -{ - struct phy_device *phydev = ptp_priv->phydev; - struct lan8814_ptp_rx_ts *rx_ts; - u32 sec, nsec; - u16 seq; - - nsec = phy_read_mmd(phydev, 2, LAN8841_PTP_RX_INGRESS_NS_HI); - if (!(nsec & LAN8841_PTP_RX_INGRESS_NSEC_HI_VALID)) - return NULL; - - nsec = ((nsec & 0x3fff) << 16); - nsec = nsec | phy_read_mmd(phydev, 2, LAN8841_PTP_RX_INGRESS_NS_LO); - - sec = phy_read_mmd(phydev, 2, LAN8841_PTP_RX_INGRESS_SEC_HI); - sec = sec << 16; - sec = sec | phy_read_mmd(phydev, 2, LAN8841_PTP_RX_INGRESS_SEC_LO); - - seq = phy_read_mmd(phydev, 2, LAN8841_PTP_RX_MSG_HEADER2); - - rx_ts = kzalloc(sizeof(*rx_ts), GFP_KERNEL); - if (!rx_ts) - return NULL; - - rx_ts->seconds = sec; - rx_ts->nsec = nsec; - rx_ts->seq_id = seq; - - return rx_ts; -} - -static void lan8841_ptp_process_rx_ts(struct kszphy_ptp_priv *ptp_priv) -{ - struct lan8814_ptp_rx_ts *rx_ts; - - while ((rx_ts = lan8841_ptp_get_rx_ts(ptp_priv)) != NULL) - lan8814_match_rx_ts(ptp_priv, rx_ts); -} - #define LAN8841_PTP_INT_STS 259 #define LAN8841_PTP_INT_STS_PTP_TX_TS_OVRFL_INT BIT(13) #define LAN8841_PTP_INT_STS_PTP_TX_TS_INT BIT(12) -#define LAN8841_PTP_INT_STS_PTP_RX_TS_OVRFL_INT BIT(9) -#define LAN8841_PTP_INT_STS_PTP_RX_TS_INT BIT(8) #define LAN8841_PTP_INT_STS_PTP_GPIO_CAP_INT BIT(2) -static void lan8841_ptp_flush_fifo(struct kszphy_ptp_priv *ptp_priv, bool egress) +static void lan8841_ptp_flush_fifo(struct kszphy_ptp_priv *ptp_priv) { struct phy_device *phydev = ptp_priv->phydev; int i; for (i = 0; i < FIFO_SIZE; ++i) - phy_read_mmd(phydev, 2, - egress ? LAN8841_PTP_TX_MSG_HEADER2 : - LAN8841_PTP_RX_MSG_HEADER2); + phy_read_mmd(phydev, 2, LAN8841_PTP_TX_MSG_HEADER2); phy_read_mmd(phydev, 2, LAN8841_PTP_INT_STS); } @@ -3525,23 +3558,17 @@ static void lan8841_handle_ptp_interrupt(struct phy_device *phydev) if (status & LAN8841_PTP_INT_STS_PTP_TX_TS_INT) lan8841_ptp_process_tx_ts(ptp_priv); - if (status & LAN8841_PTP_INT_STS_PTP_RX_TS_INT) - lan8841_ptp_process_rx_ts(ptp_priv); - if (status & LAN8841_PTP_INT_STS_PTP_GPIO_CAP_INT) lan8841_gpio_process_cap(ptp_priv); if (status & LAN8841_PTP_INT_STS_PTP_TX_TS_OVRFL_INT) { - lan8841_ptp_flush_fifo(ptp_priv, true); + lan8841_ptp_flush_fifo(ptp_priv); skb_queue_purge(&ptp_priv->tx_queue); } - if (status & LAN8841_PTP_INT_STS_PTP_RX_TS_OVRFL_INT) { - lan8841_ptp_flush_fifo(ptp_priv, false); - skb_queue_purge(&ptp_priv->rx_queue); - } - - } while (status); + } while (status & (LAN8841_PTP_INT_STS_PTP_TX_TS_INT | + LAN8841_PTP_INT_STS_PTP_GPIO_CAP_INT | + LAN8841_PTP_INT_STS_PTP_TX_TS_OVRFL_INT)); } #define LAN8841_INTS_PTP BIT(9) @@ -3605,32 +3632,46 @@ static int lan8841_ts_info(struct mii_timestamper *mii_ts, #define LAN8841_PTP_INT_EN 260 #define LAN8841_PTP_INT_EN_PTP_TX_TS_OVRFL_EN BIT(13) #define LAN8841_PTP_INT_EN_PTP_TX_TS_EN BIT(12) -#define LAN8841_PTP_INT_EN_PTP_RX_TS_OVRFL_EN BIT(9) -#define LAN8841_PTP_INT_EN_PTP_RX_TS_EN BIT(8) -static void lan8841_ptp_enable_int(struct kszphy_ptp_priv *ptp_priv, - bool enable) +static void lan8841_ptp_enable_processing(struct kszphy_ptp_priv *ptp_priv, + bool enable) { struct phy_device *phydev = ptp_priv->phydev; - if (enable) - /* Enable interrupts */ + if (enable) { + /* Enable interrupts on the TX side */ phy_modify_mmd(phydev, 2, LAN8841_PTP_INT_EN, LAN8841_PTP_INT_EN_PTP_TX_TS_OVRFL_EN | - LAN8841_PTP_INT_EN_PTP_RX_TS_OVRFL_EN | - LAN8841_PTP_INT_EN_PTP_TX_TS_EN | - LAN8841_PTP_INT_EN_PTP_RX_TS_EN, + LAN8841_PTP_INT_EN_PTP_TX_TS_EN, LAN8841_PTP_INT_EN_PTP_TX_TS_OVRFL_EN | - LAN8841_PTP_INT_EN_PTP_RX_TS_OVRFL_EN | - LAN8841_PTP_INT_EN_PTP_TX_TS_EN | - LAN8841_PTP_INT_EN_PTP_RX_TS_EN); - else - /* Disable interrupts */ + LAN8841_PTP_INT_EN_PTP_TX_TS_EN); + + /* Enable the modification of the frame on RX side, + * this will add the ns and 2 bits of sec in the reserved field + * of the PTP header + */ + phy_modify_mmd(phydev, KSZ9131RN_MMD_COMMON_CTRL_REG, + LAN8841_PTP_RX_MODE, + LAN8841_PTP_INSERT_TS_EN | + LAN8841_PTP_INSERT_TS_32BIT, + LAN8841_PTP_INSERT_TS_EN | + LAN8841_PTP_INSERT_TS_32BIT); + + ptp_schedule_worker(ptp_priv->ptp_clock, 0); + } else { + /* Disable interrupts on the TX side */ phy_modify_mmd(phydev, 2, LAN8841_PTP_INT_EN, LAN8841_PTP_INT_EN_PTP_TX_TS_OVRFL_EN | - LAN8841_PTP_INT_EN_PTP_RX_TS_OVRFL_EN | - LAN8841_PTP_INT_EN_PTP_TX_TS_EN | - LAN8841_PTP_INT_EN_PTP_RX_TS_EN, 0); + LAN8841_PTP_INT_EN_PTP_TX_TS_EN, 0); + + /* Disable modification of the RX frames */ + phy_modify_mmd(phydev, KSZ9131RN_MMD_COMMON_CTRL_REG, + LAN8841_PTP_RX_MODE, + LAN8841_PTP_INSERT_TS_EN | + LAN8841_PTP_INSERT_TS_32BIT, 0); + + ptp_cancel_worker_sync(ptp_priv->ptp_clock); + } } #define LAN8841_PTP_RX_TIMESTAMP_EN 379 @@ -3641,7 +3682,6 @@ static int lan8841_hwtstamp(struct mii_timestamper *mii_ts, struct ifreq *ifr) { struct kszphy_ptp_priv *ptp_priv = container_of(mii_ts, struct kszphy_ptp_priv, mii_ts); struct phy_device *phydev = ptp_priv->phydev; - struct lan8814_ptp_rx_ts *rx_ts, *tmp; struct hwtstamp_config config; int txcfg = 0, rxcfg = 0; int pkt_ts_enable; @@ -3705,24 +3745,61 @@ static int lan8841_hwtstamp(struct mii_timestamper *mii_ts, struct ifreq *ifr) PTP_TX_MOD_TX_PTP_SYNC_TS_INSERT_ : 0); /* Now enable/disable the timestamping */ - lan8841_ptp_enable_int(ptp_priv, - config.rx_filter != HWTSTAMP_FILTER_NONE); + lan8841_ptp_enable_processing(ptp_priv, + config.rx_filter != HWTSTAMP_FILTER_NONE); - /* In case of multiple starts and stops, these needs to be cleared */ - list_for_each_entry_safe(rx_ts, tmp, &ptp_priv->rx_ts_list, list) { - list_del(&rx_ts->list); - kfree(rx_ts); - } - - skb_queue_purge(&ptp_priv->rx_queue); skb_queue_purge(&ptp_priv->tx_queue); - lan8841_ptp_flush_fifo(ptp_priv, false); - lan8841_ptp_flush_fifo(ptp_priv, true); + lan8841_ptp_flush_fifo(ptp_priv); return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ? -EFAULT : 0; } +static bool lan8841_rxtstamp(struct mii_timestamper *mii_ts, + struct sk_buff *skb, int type) +{ + struct kszphy_ptp_priv *ptp_priv = + container_of(mii_ts, struct kszphy_ptp_priv, mii_ts); + struct ptp_header *header = ptp_parse_header(skb, type); + struct skb_shared_hwtstamps *shhwtstamps; + struct timespec64 ts; + unsigned long flags; + u32 ts_header; + + if (!header) + return false; + + if (ptp_priv->rx_filter == HWTSTAMP_FILTER_NONE || + type == PTP_CLASS_NONE) + return false; + + if ((type & ptp_priv->version) == 0 || (type & ptp_priv->layer) == 0) + return false; + + spin_lock_irqsave(&ptp_priv->seconds_lock, flags); + ts.tv_sec = ptp_priv->seconds; + spin_unlock_irqrestore(&ptp_priv->seconds_lock, flags); + ts_header = __be32_to_cpu(header->reserved2); + + shhwtstamps = skb_hwtstamps(skb); + memset(shhwtstamps, 0, sizeof(*shhwtstamps)); + + /* Check for any wrap arounds for the second part */ + if ((ts.tv_sec & GENMASK(1, 0)) == 0 && (ts_header >> 30) == 3) + ts.tv_sec -= GENMASK(1, 0) + 1; + else if ((ts.tv_sec & GENMASK(1, 0)) == 3 && (ts_header >> 30) == 0) + ts.tv_sec += 1; + + shhwtstamps->hwtstamp = + ktime_set((ts.tv_sec & ~(GENMASK(1, 0))) | ts_header >> 30, + ts_header & GENMASK(29, 0)); + header->reserved2 = 0; + + netif_rx(skb); + + return true; +} + #define LAN8841_EVENT_A 0 #define LAN8841_EVENT_B 1 #define LAN8841_PTP_LTC_TARGET_SEC_HI(event) ((event) == LAN8841_EVENT_A ? 278 : 288) @@ -3807,6 +3884,7 @@ static int lan8841_ptp_settime64(struct ptp_clock_info *ptp, struct kszphy_ptp_priv *ptp_priv = container_of(ptp, struct kszphy_ptp_priv, ptp_clock_info); struct phy_device *phydev = ptp_priv->phydev; + unsigned long flags; int ret; /* Set the value to be stored */ @@ -3823,6 +3901,10 @@ static int lan8841_ptp_settime64(struct ptp_clock_info *ptp, ret = lan8841_ptp_update_target(ptp_priv, ts); mutex_unlock(&ptp_priv->ptp_lock); + spin_lock_irqsave(&ptp_priv->seconds_lock, flags); + ptp_priv->seconds = ts->tv_sec; + spin_unlock_irqrestore(&ptp_priv->seconds_lock, flags); + return ret; } @@ -3863,6 +3945,30 @@ static int lan8841_ptp_gettime64(struct ptp_clock_info *ptp, return 0; } +static void lan8841_ptp_getseconds(struct ptp_clock_info *ptp, + struct timespec64 *ts) +{ + struct kszphy_ptp_priv *ptp_priv = container_of(ptp, struct kszphy_ptp_priv, + ptp_clock_info); + struct phy_device *phydev = ptp_priv->phydev; + time64_t s; + + mutex_lock(&ptp_priv->ptp_lock); + /* Issue the command to read the LTC */ + phy_write_mmd(phydev, 2, LAN8841_PTP_CMD_CTL, + LAN8841_PTP_CMD_CTL_PTP_LTC_READ); + + /* Read the LTC */ + s = phy_read_mmd(phydev, 2, LAN8841_PTP_LTC_RD_SEC_HI); + s <<= 16; + s |= phy_read_mmd(phydev, 2, LAN8841_PTP_LTC_RD_SEC_MID); + s <<= 16; + s |= phy_read_mmd(phydev, 2, LAN8841_PTP_LTC_RD_SEC_LO); + mutex_unlock(&ptp_priv->ptp_lock); + + set_normalized_timespec64(ts, s, 0); +} + #define LAN8841_PTP_LTC_STEP_ADJ_LO 276 #define LAN8841_PTP_LTC_STEP_ADJ_HI 275 #define LAN8841_PTP_LTC_STEP_ADJ_DIR BIT(15) @@ -4365,6 +4471,22 @@ static int lan8841_ptp_enable(struct ptp_clock_info *ptp, return 0; } +static long lan8841_ptp_do_aux_work(struct ptp_clock_info *ptp) +{ + struct kszphy_ptp_priv *ptp_priv = container_of(ptp, struct kszphy_ptp_priv, + ptp_clock_info); + struct timespec64 ts; + unsigned long flags; + + lan8841_ptp_getseconds(&ptp_priv->ptp_clock_info, &ts); + + spin_lock_irqsave(&ptp_priv->seconds_lock, flags); + ptp_priv->seconds = ts.tv_sec; + spin_unlock_irqrestore(&ptp_priv->seconds_lock, flags); + + return nsecs_to_jiffies(LAN8841_GET_SEC_LTC_DELAY); +} + static struct ptp_clock_info lan8841_ptp_clock_info = { .owner = THIS_MODULE, .name = "lan8841 ptp", @@ -4375,6 +4497,7 @@ static struct ptp_clock_info lan8841_ptp_clock_info = { .adjfine = lan8841_ptp_adjfine, .verify = lan8841_ptp_verify, .enable = lan8841_ptp_enable, + .do_aux_work = lan8841_ptp_do_aux_work, .n_per_out = LAN8841_PTP_GPIO_NUM, .n_ext_ts = LAN8841_PTP_GPIO_NUM, .n_pins = LAN8841_PTP_GPIO_NUM, @@ -4435,13 +4558,11 @@ static int lan8841_probe(struct phy_device *phydev) /* Initialize the SW */ skb_queue_head_init(&ptp_priv->tx_queue); - skb_queue_head_init(&ptp_priv->rx_queue); - INIT_LIST_HEAD(&ptp_priv->rx_ts_list); - spin_lock_init(&ptp_priv->rx_ts_lock); ptp_priv->phydev = phydev; mutex_init(&ptp_priv->ptp_lock); + spin_lock_init(&ptp_priv->seconds_lock); - ptp_priv->mii_ts.rxtstamp = lan8814_rxtstamp; + ptp_priv->mii_ts.rxtstamp = lan8841_rxtstamp; ptp_priv->mii_ts.txtstamp = lan8814_txtstamp; ptp_priv->mii_ts.hwtstamp = lan8841_hwtstamp; ptp_priv->mii_ts.ts_info = lan8841_ts_info; @@ -4451,6 +4572,16 @@ static int lan8841_probe(struct phy_device *phydev) return 0; } +static int lan8841_suspend(struct phy_device *phydev) +{ + struct kszphy_priv *priv = phydev->priv; + struct kszphy_ptp_priv *ptp_priv = &priv->ptp_priv; + + ptp_cancel_worker_sync(ptp_priv->ptp_clock); + + return genphy_suspend(phydev); +} + static struct phy_driver ksphy_driver[] = { { .phy_id = PHY_ID_KS8737, @@ -4674,7 +4805,7 @@ static struct phy_driver ksphy_driver[] = { .get_sset_count = kszphy_get_sset_count, .get_strings = kszphy_get_strings, .get_stats = kszphy_get_stats, - .suspend = genphy_suspend, + .suspend = lan8841_suspend, .resume = genphy_resume, .cable_test_start = lan8814_cable_test_start, .cable_test_get_status = ksz886x_cable_test_get_status, @@ -4735,7 +4866,7 @@ static struct phy_driver ksphy_driver[] = { .phy_id_mask = MICREL_PHY_ID_MASK, .name = "Microchip KSZ9477", /* PHY_GBIT_FEATURES */ - .config_init = kszphy_config_init, + .config_init = ksz9477_config_init, .config_intr = kszphy_config_intr, .handle_interrupt = kszphy_handle_interrupt, .suspend = genphy_suspend, diff --git a/drivers/net/phy/microchip_t1s.c b/drivers/net/phy/microchip_t1s.c index 094967b3c1117eea054811abbd92363596a5e60e..534ca7d1b061dd3421c7cf4c8812df8bedd039a4 100644 --- a/drivers/net/phy/microchip_t1s.c +++ b/drivers/net/phy/microchip_t1s.c @@ -1,19 +1,29 @@ // SPDX-License-Identifier: GPL-2.0+ /* - * Driver for Microchip 10BASE-T1S LAN867X PHY + * Driver for Microchip 10BASE-T1S PHYs * * Support: Microchip Phys: - * lan8670, lan8671, lan8672 + * lan8670/1/2 Rev.B1 + * lan8650/1 Rev.B0 Internal PHYs */ #include #include #include -#define PHY_ID_LAN867X 0x0007C160 +#define PHY_ID_LAN867X_REVB1 0x0007C162 +#define PHY_ID_LAN865X_REVB0 0x0007C1B3 -#define LAN867X_REG_IRQ_1_CTL 0x001C -#define LAN867X_REG_IRQ_2_CTL 0x001D +#define LAN867X_REG_STS2 0x0019 + +#define LAN867x_RESET_COMPLETE_STS BIT(11) + +#define LAN865X_REG_CFGPARAM_ADDR 0x00D8 +#define LAN865X_REG_CFGPARAM_DATA 0x00D9 +#define LAN865X_REG_CFGPARAM_CTRL 0x00DA +#define LAN865X_REG_STS2 0x0019 + +#define LAN865X_CFGPARAM_READ_ENABLE BIT(1) /* The arrays below are pulled from the following table from AN1699 * Access MMD Address Value Mask @@ -31,72 +41,219 @@ * W 0x1F 0x0099 0x7F80 ------ */ -static const int lan867x_fixup_registers[12] = { +static const u32 lan867x_revb1_fixup_registers[12] = { 0x00D0, 0x00D1, 0x0084, 0x0085, 0x008A, 0x0087, 0x0088, 0x008B, 0x0080, 0x00F1, 0x0096, 0x0099, }; -static const int lan867x_fixup_values[12] = { +static const u16 lan867x_revb1_fixup_values[12] = { 0x0002, 0x0000, 0x3380, 0x0006, 0xC000, 0x801C, 0x033F, 0x0404, 0x0600, 0x2400, 0x2000, 0x7F80, }; -static const int lan867x_fixup_masks[12] = { +static const u16 lan867x_revb1_fixup_masks[12] = { 0x0E03, 0x0300, 0xFFC0, 0x000F, 0xF800, 0x801C, 0x1FFF, 0xFFFF, 0x0600, 0x7F00, 0x2000, 0xFFFF, }; -static int lan867x_config_init(struct phy_device *phydev) +/* LAN865x Rev.B0 configuration parameters from AN1760 */ +static const u32 lan865x_revb0_fixup_registers[28] = { + 0x0091, 0x0081, 0x0043, 0x0044, + 0x0045, 0x0053, 0x0054, 0x0055, + 0x0040, 0x0050, 0x00D0, 0x00E9, + 0x00F5, 0x00F4, 0x00F8, 0x00F9, + 0x00B0, 0x00B1, 0x00B2, 0x00B3, + 0x00B4, 0x00B5, 0x00B6, 0x00B7, + 0x00B8, 0x00B9, 0x00BA, 0x00BB, +}; + +static const u16 lan865x_revb0_fixup_values[28] = { + 0x9660, 0x00C0, 0x00FF, 0xFFFF, + 0x0000, 0x00FF, 0xFFFF, 0x0000, + 0x0002, 0x0002, 0x5F21, 0x9E50, + 0x1CF8, 0xC020, 0x9B00, 0x4E53, + 0x0103, 0x0910, 0x1D26, 0x002A, + 0x0103, 0x070D, 0x1720, 0x0027, + 0x0509, 0x0E13, 0x1C25, 0x002B, +}; + +static const u16 lan865x_revb0_fixup_cfg_regs[5] = { + 0x0084, 0x008A, 0x00AD, 0x00AE, 0x00AF +}; + +/* Pulled from AN1760 describing 'indirect read' + * + * write_register(0x4, 0x00D8, addr) + * write_register(0x4, 0x00DA, 0x2) + * return (int8)(read_register(0x4, 0x00D9)) + * + * 0x4 refers to memory map selector 4, which maps to MDIO_MMD_VEND2 + */ +static int lan865x_revb0_indirect_read(struct phy_device *phydev, u16 addr) +{ + int ret; + + ret = phy_write_mmd(phydev, MDIO_MMD_VEND2, LAN865X_REG_CFGPARAM_ADDR, + addr); + if (ret) + return ret; + + ret = phy_write_mmd(phydev, MDIO_MMD_VEND2, LAN865X_REG_CFGPARAM_CTRL, + LAN865X_CFGPARAM_READ_ENABLE); + if (ret) + return ret; + + return phy_read_mmd(phydev, MDIO_MMD_VEND2, LAN865X_REG_CFGPARAM_DATA); +} + +/* This is pulled straight from AN1760 from 'calculation of offset 1' & + * 'calculation of offset 2' + */ +static int lan865x_generate_cfg_offsets(struct phy_device *phydev, s8 offsets[2]) +{ + const u16 fixup_regs[2] = {0x0004, 0x0008}; + int ret; + + for (int i = 0; i < ARRAY_SIZE(fixup_regs); i++) { + ret = lan865x_revb0_indirect_read(phydev, fixup_regs[i]); + if (ret < 0) + return ret; + if (ret & BIT(4)) + offsets[i] = ret | 0xE0; + else + offsets[i] = ret; + } + + return 0; +} + +static int lan865x_read_cfg_params(struct phy_device *phydev, u16 cfg_params[]) +{ + int ret; + + for (int i = 0; i < ARRAY_SIZE(lan865x_revb0_fixup_cfg_regs); i++) { + ret = phy_read_mmd(phydev, MDIO_MMD_VEND2, + lan865x_revb0_fixup_cfg_regs[i]); + if (ret < 0) + return ret; + cfg_params[i] = (u16)ret; + } + + return 0; +} + +static int lan865x_write_cfg_params(struct phy_device *phydev, u16 cfg_params[]) { - /* HW quirk: Microchip states in the application note (AN1699) for the phy - * that a set of read-modify-write (rmw) operations has to be performed - * on a set of seemingly magic registers. - * The result of these operations is just described as 'optimal performance' - * Microchip gives no explanation as to what these mmd regs do, - * in fact they are marked as reserved in the datasheet. - * It is unclear if phy_modify_mmd would be safe to use or if a write - * really has to happen to each register. - * In order to exactly conform to what is stated in the AN phy_write_mmd is - * used, which might then write the same value back as read + modified. + int ret; + + for (int i = 0; i < ARRAY_SIZE(lan865x_revb0_fixup_cfg_regs); i++) { + ret = phy_write_mmd(phydev, MDIO_MMD_VEND2, + lan865x_revb0_fixup_cfg_regs[i], + cfg_params[i]); + if (ret) + return ret; + } + + return 0; +} + +static int lan865x_setup_cfgparam(struct phy_device *phydev) +{ + u16 cfg_params[ARRAY_SIZE(lan865x_revb0_fixup_cfg_regs)]; + u16 cfg_results[5]; + s8 offsets[2]; + int ret; + + ret = lan865x_generate_cfg_offsets(phydev, offsets); + if (ret) + return ret; + + ret = lan865x_read_cfg_params(phydev, cfg_params); + if (ret) + return ret; + + cfg_results[0] = (cfg_params[0] & 0x000F) | + FIELD_PREP(GENMASK(15, 10), 9 + offsets[0]) | + FIELD_PREP(GENMASK(15, 4), 14 + offsets[0]); + cfg_results[1] = (cfg_params[1] & 0x03FF) | + FIELD_PREP(GENMASK(15, 10), 40 + offsets[1]); + cfg_results[2] = (cfg_params[2] & 0xC0C0) | + FIELD_PREP(GENMASK(15, 8), 5 + offsets[0]) | + (9 + offsets[0]); + cfg_results[3] = (cfg_params[3] & 0xC0C0) | + FIELD_PREP(GENMASK(15, 8), 9 + offsets[0]) | + (14 + offsets[0]); + cfg_results[4] = (cfg_params[4] & 0xC0C0) | + FIELD_PREP(GENMASK(15, 8), 17 + offsets[0]) | + (22 + offsets[0]); + + return lan865x_write_cfg_params(phydev, cfg_results); +} + +static int lan865x_revb0_config_init(struct phy_device *phydev) +{ + int ret; + + /* Reference to AN1760 + * https://ww1.microchip.com/downloads/aemDocuments/documents/AIS/ProductDocuments/SupportingCollateral/AN-LAN8650-1-Configuration-60001760.pdf + */ + for (int i = 0; i < ARRAY_SIZE(lan865x_revb0_fixup_registers); i++) { + ret = phy_write_mmd(phydev, MDIO_MMD_VEND2, + lan865x_revb0_fixup_registers[i], + lan865x_revb0_fixup_values[i]); + if (ret) + return ret; + } + /* Function to calculate and write the configuration parameters in the + * 0x0084, 0x008A, 0x00AD, 0x00AE and 0x00AF registers (from AN1760) */ + return lan865x_setup_cfgparam(phydev); +} - int reg_value; +static int lan867x_revb1_config_init(struct phy_device *phydev) +{ int err; - int reg; - /* Read-Modified Write Pseudocode (from AN1699) - * current_val = read_register(mmd, addr) // Read current register value - * new_val = current_val AND (NOT mask) // Clear bit fields to be written - * new_val = new_val OR value // Set bits - * write_register(mmd, addr, new_val) // Write back updated register value + /* The chip completes a reset in 3us, we might get here earlier than + * that, as an added margin we'll conditionally sleep 5us. */ - for (int i = 0; i < ARRAY_SIZE(lan867x_fixup_registers); i++) { - reg = lan867x_fixup_registers[i]; - reg_value = phy_read_mmd(phydev, MDIO_MMD_VEND2, reg); - reg_value &= ~lan867x_fixup_masks[i]; - reg_value |= lan867x_fixup_values[i]; - err = phy_write_mmd(phydev, MDIO_MMD_VEND2, reg, reg_value); - if (err != 0) + err = phy_read_mmd(phydev, MDIO_MMD_VEND2, LAN867X_REG_STS2); + if (err < 0) + return err; + + if (!(err & LAN867x_RESET_COMPLETE_STS)) { + udelay(5); + err = phy_read_mmd(phydev, MDIO_MMD_VEND2, LAN867X_REG_STS2); + if (err < 0) return err; + if (!(err & LAN867x_RESET_COMPLETE_STS)) { + phydev_err(phydev, "PHY reset failed\n"); + return -ENODEV; + } } - /* None of the interrupts in the lan867x phy seem relevant. - * Other phys inspect the link status and call phy_trigger_machine - * in the interrupt handler. - * This phy does not support link status, and thus has no interrupt - * for it either. - * So we'll just disable all interrupts on the chip. + /* Reference to AN1699 + * https://ww1.microchip.com/downloads/aemDocuments/documents/AIS/ProductDocuments/SupportingCollateral/AN-LAN8670-1-2-config-60001699.pdf + * AN1699 says Read, Modify, Write, but the Write is not required if the + * register already has the required value. So it is safe to use + * phy_modify_mmd here. */ - err = phy_write_mmd(phydev, MDIO_MMD_VEND2, LAN867X_REG_IRQ_1_CTL, 0xFFFF); - if (err != 0) - return err; - return phy_write_mmd(phydev, MDIO_MMD_VEND2, LAN867X_REG_IRQ_2_CTL, 0xFFFF); + for (int i = 0; i < ARRAY_SIZE(lan867x_revb1_fixup_registers); i++) { + err = phy_modify_mmd(phydev, MDIO_MMD_VEND2, + lan867x_revb1_fixup_registers[i], + lan867x_revb1_fixup_masks[i], + lan867x_revb1_fixup_values[i]); + if (err) + return err; + } + + return 0; } -static int lan867x_read_status(struct phy_device *phydev) +static int lan86xx_read_status(struct phy_device *phydev) { /* The phy has some limitations, namely: * - always reports link up @@ -111,28 +268,39 @@ static int lan867x_read_status(struct phy_device *phydev) return 0; } -static struct phy_driver lan867x_driver[] = { +static struct phy_driver microchip_t1s_driver[] = { { - PHY_ID_MATCH_MODEL(PHY_ID_LAN867X), - .name = "LAN867X", + PHY_ID_MATCH_EXACT(PHY_ID_LAN867X_REVB1), + .name = "LAN867X Rev.B1", .features = PHY_BASIC_T1S_P2MP_FEATURES, - .config_init = lan867x_config_init, - .read_status = lan867x_read_status, + .config_init = lan867x_revb1_config_init, + .read_status = lan86xx_read_status, .get_plca_cfg = genphy_c45_plca_get_cfg, .set_plca_cfg = genphy_c45_plca_set_cfg, .get_plca_status = genphy_c45_plca_get_status, - } + }, + { + PHY_ID_MATCH_EXACT(PHY_ID_LAN865X_REVB0), + .name = "LAN865X Rev.B0 Internal Phy", + .features = PHY_BASIC_T1S_P2MP_FEATURES, + .config_init = lan865x_revb0_config_init, + .read_status = lan86xx_read_status, + .get_plca_cfg = genphy_c45_plca_get_cfg, + .set_plca_cfg = genphy_c45_plca_set_cfg, + .get_plca_status = genphy_c45_plca_get_status, + }, }; -module_phy_driver(lan867x_driver); +module_phy_driver(microchip_t1s_driver); static struct mdio_device_id __maybe_unused tbl[] = { - { PHY_ID_MATCH_MODEL(PHY_ID_LAN867X) }, + { PHY_ID_MATCH_EXACT(PHY_ID_LAN867X_REVB1) }, + { PHY_ID_MATCH_EXACT(PHY_ID_LAN865X_REVB0) }, { } }; MODULE_DEVICE_TABLE(mdio, tbl); -MODULE_DESCRIPTION("Microchip 10BASE-T1S lan867x Phy driver"); +MODULE_DESCRIPTION("Microchip 10BASE-T1S PHYs driver"); MODULE_AUTHOR("Ramón Nordin Rodriguez"); MODULE_LICENSE("GPL"); diff --git a/drivers/net/phy/mscc/mscc.h b/drivers/net/phy/mscc/mscc.h index defe5cc6d4fcef4754edfb0aa5a1d6e562e0b282..7a962050a4d45e77707519826b7f135057034129 100644 --- a/drivers/net/phy/mscc/mscc.h +++ b/drivers/net/phy/mscc/mscc.h @@ -292,6 +292,7 @@ enum rgmii_clock_delay { #define PHY_ID_VSC8575 0x000707d0 #define PHY_ID_VSC8582 0x000707b0 #define PHY_ID_VSC8584 0x000707c0 +#define PHY_VENDOR_MSCC 0x00070400 #define MSCC_VDDMAC_1500 1500 #define MSCC_VDDMAC_1800 1800 diff --git a/drivers/net/phy/mscc/mscc_main.c b/drivers/net/phy/mscc/mscc_main.c index 28df8a2e4230f3ffd6f559e8ac9521cedc7d0100..4171f01d34e5792e91dff50837a9869802c8c36c 100644 --- a/drivers/net/phy/mscc/mscc_main.c +++ b/drivers/net/phy/mscc/mscc_main.c @@ -107,6 +107,9 @@ static const struct vsc8531_edge_rate_table edge_table[] = { }; #endif +static const int vsc85xx_internal_delay[] = {200, 800, 1100, 1700, 2000, 2300, + 2600, 3400}; + static int vsc85xx_phy_read_page(struct phy_device *phydev) { return __phy_read(phydev, MSCC_EXT_PAGE_ACCESS); @@ -525,8 +528,12 @@ static int vsc85xx_update_rgmii_cntl(struct phy_device *phydev, u32 rgmii_cntl, { u16 rgmii_rx_delay_pos = ffs(rgmii_rx_delay_mask) - 1; u16 rgmii_tx_delay_pos = ffs(rgmii_tx_delay_mask) - 1; + int delay_size = ARRAY_SIZE(vsc85xx_internal_delay); + struct device *dev = &phydev->mdio.dev; u16 reg_val = 0; u16 mask = 0; + s32 rx_delay; + s32 tx_delay; int rc = 0; /* For traffic to pass, the VSC8502 family needs the RX_CLK disable bit @@ -541,12 +548,28 @@ static int vsc85xx_update_rgmii_cntl(struct phy_device *phydev, u32 rgmii_cntl, if (phy_interface_is_rgmii(phydev)) mask |= rgmii_rx_delay_mask | rgmii_tx_delay_mask; - if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID || - phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) - reg_val |= RGMII_CLK_DELAY_2_0_NS << rgmii_rx_delay_pos; - if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID || - phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) - reg_val |= RGMII_CLK_DELAY_2_0_NS << rgmii_tx_delay_pos; + rx_delay = phy_get_internal_delay(phydev, dev, vsc85xx_internal_delay, + delay_size, true); + if (rx_delay < 0) { + if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID || + phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) + rx_delay = RGMII_CLK_DELAY_2_0_NS; + else + rx_delay = RGMII_CLK_DELAY_0_2_NS; + } + + tx_delay = phy_get_internal_delay(phydev, dev, vsc85xx_internal_delay, + delay_size, false); + if (tx_delay < 0) { + if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID || + phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) + tx_delay = RGMII_CLK_DELAY_2_0_NS; + else + tx_delay = RGMII_CLK_DELAY_0_2_NS; + } + + reg_val |= rx_delay << rgmii_rx_delay_pos; + reg_val |= tx_delay << rgmii_tx_delay_pos; if (mask) rc = phy_modify_paged(phydev, MSCC_PHY_PAGE_EXTENDED_2, @@ -2678,21 +2701,7 @@ static struct phy_driver vsc85xx_driver[] = { module_phy_driver(vsc85xx_driver); static struct mdio_device_id __maybe_unused vsc85xx_tbl[] = { - { PHY_ID_VSC8501, 0xfffffff0, }, - { PHY_ID_VSC8502, 0xfffffff0, }, - { PHY_ID_VSC8504, 0xfffffff0, }, - { PHY_ID_VSC8514, 0xfffffff0, }, - { PHY_ID_VSC8530, 0xfffffff0, }, - { PHY_ID_VSC8531, 0xfffffff0, }, - { PHY_ID_VSC8540, 0xfffffff0, }, - { PHY_ID_VSC8541, 0xfffffff0, }, - { PHY_ID_VSC8552, 0xfffffff0, }, - { PHY_ID_VSC856X, 0xfffffff0, }, - { PHY_ID_VSC8572, 0xfffffff0, }, - { PHY_ID_VSC8574, 0xfffffff0, }, - { PHY_ID_VSC8575, 0xfffffff0, }, - { PHY_ID_VSC8582, 0xfffffff0, }, - { PHY_ID_VSC8584, 0xfffffff0, }, + { PHY_ID_MATCH_VENDOR(PHY_VENDOR_MSCC) }, { } }; diff --git a/drivers/net/phy/phy-c45.c b/drivers/net/phy/phy-c45.c index fee514b96ab176a263916e921ffc3131ed92c65a..93ed072233779a31371d300f76a9a083c5c301f5 100644 --- a/drivers/net/phy/phy-c45.c +++ b/drivers/net/phy/phy-c45.c @@ -1425,12 +1425,15 @@ int genphy_c45_ethtool_get_eee(struct phy_device *phydev, EXPORT_SYMBOL(genphy_c45_ethtool_get_eee); /** - * genphy_c45_ethtool_set_eee - get EEE supported and status + * genphy_c45_ethtool_set_eee - set EEE supported and status * @phydev: target phy_device struct * @data: ethtool_eee data * - * Description: it reportes the Supported/Advertisement/LP Advertisement - * capabilities. + * Description: sets the Supported/Advertisement/LP Advertisement + * capabilities. If eee_enabled is false, no links modes are + * advertised, but the previously advertised link modes are + * retained. This allows EEE to be enabled/disabled in a + * non-destructive way. */ int genphy_c45_ethtool_set_eee(struct phy_device *phydev, struct ethtool_eee *data) diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index 0c0df38cd1ab8a2f0399d7aa20ef7a753c0ffb51..bdf00b2b2c1dc3ea0760d02476568b1398b7508c 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -52,6 +52,7 @@ static const char *phy_state_to_str(enum phy_state st) PHY_STATE_STR(NOLINK) PHY_STATE_STR(CABLETEST) PHY_STATE_STR(HALTED) + PHY_STATE_STR(ERROR) } return NULL; @@ -1184,7 +1185,7 @@ void phy_stop_machine(struct phy_device *phydev) static void phy_process_error(struct phy_device *phydev) { mutex_lock(&phydev->lock); - phydev->state = PHY_HALTED; + phydev->state = PHY_ERROR; mutex_unlock(&phydev->lock); phy_trigger_machine(phydev); @@ -1198,10 +1199,10 @@ static void phy_error_precise(struct phy_device *phydev, } /** - * phy_error - enter HALTED state for this PHY device + * phy_error - enter ERROR state for this PHY device * @phydev: target phy_device struct * - * Moves the PHY to the HALTED state in response to a read + * Moves the PHY to the ERROR state in response to a read * or write error, and tells the controller the link is down. * Must not be called from interrupt context, or while the * phydev->lock is held. @@ -1326,7 +1327,8 @@ void phy_stop(struct phy_device *phydev) struct net_device *dev = phydev->attached_dev; enum phy_state old_state; - if (!phy_is_started(phydev) && phydev->state != PHY_DOWN) { + if (!phy_is_started(phydev) && phydev->state != PHY_DOWN && + phydev->state != PHY_ERROR) { WARN(1, "called from state %s\n", phy_state_to_str(phydev->state)); return; @@ -1443,6 +1445,7 @@ void phy_state_machine(struct work_struct *work) } break; case PHY_HALTED: + case PHY_ERROR: if (phydev->link) { phydev->link = 0; phy_link_down(phydev); diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 17d0d0555a79f1349ed6e3325d31e799d8ef053d..0c2014accba7dd6d5ea4555b1f940a3c4db49958 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -454,8 +454,7 @@ int phy_unregister_fixup(const char *bus_id, u32 phy_uid, u32 phy_uid_mask) fixup = list_entry(pos, struct phy_fixup, list); if ((!strcmp(fixup->bus_id, bus_id)) && - ((fixup->phy_uid & phy_uid_mask) == - (phy_uid & phy_uid_mask))) { + phy_id_compare(fixup->phy_uid, phy_uid, phy_uid_mask)) { list_del(&fixup->list); kfree(fixup); ret = 0; @@ -491,8 +490,8 @@ static int phy_needs_fixup(struct phy_device *phydev, struct phy_fixup *fixup) if (strcmp(fixup->bus_id, PHY_ANY_ID) != 0) return 0; - if ((fixup->phy_uid & fixup->phy_uid_mask) != - (phydev->phy_id & fixup->phy_uid_mask)) + if (!phy_id_compare(phydev->phy_id, fixup->phy_uid, + fixup->phy_uid_mask)) if (fixup->phy_uid != PHY_ANY_UID) return 0; @@ -539,15 +538,14 @@ static int phy_bus_match(struct device *dev, struct device_driver *drv) if (phydev->c45_ids.device_ids[i] == 0xffffffff) continue; - if ((phydrv->phy_id & phydrv->phy_id_mask) == - (phydev->c45_ids.device_ids[i] & - phydrv->phy_id_mask)) + if (phy_id_compare(phydev->c45_ids.device_ids[i], + phydrv->phy_id, phydrv->phy_id_mask)) return 1; } return 0; } else { - return (phydrv->phy_id & phydrv->phy_id_mask) == - (phydev->phy_id & phydrv->phy_id_mask); + return phy_id_compare(phydev->phy_id, phydrv->phy_id, + phydrv->phy_id_mask); } } @@ -1860,9 +1858,10 @@ int phy_suspend(struct phy_device *phydev) if (phydev->suspended) return 0; - /* If the device has WOL enabled, we cannot suspend the PHY */ phy_ethtool_get_wol(phydev, &wol); - if (wol.wolopts || (netdev && netdev->wol_enabled)) + phydev->wol_enabled = wol.wolopts || (netdev && netdev->wol_enabled); + /* If the device has WOL enabled, we cannot suspend the PHY */ + if (phydev->wol_enabled && !(phydrv->flags & PHY_ALWAYS_CALL_SUSPEND)) return -EBUSY; if (!phydrv || !phydrv->suspend) @@ -3021,6 +3020,15 @@ static int phy_led_blink_set(struct led_classdev *led_cdev, return err; } +static void phy_leds_unregister(struct phy_device *phydev) +{ + struct phy_led *phyled; + + list_for_each_entry(phyled, &phydev->leds, list) { + led_classdev_unregister(&phyled->led_cdev); + } +} + static int of_phy_led(struct phy_device *phydev, struct device_node *led) { @@ -3054,7 +3062,7 @@ static int of_phy_led(struct phy_device *phydev, init_data.fwnode = of_fwnode_handle(led); init_data.devname_mandatory = true; - err = devm_led_classdev_register_ext(dev, cdev, &init_data); + err = led_classdev_register_ext(dev, cdev, &init_data); if (err) return err; @@ -3083,6 +3091,7 @@ static int of_phy_leds(struct phy_device *phydev) err = of_phy_led(phydev, led); if (err) { of_node_put(led); + phy_leds_unregister(phydev); return err; } } @@ -3305,6 +3314,9 @@ static int phy_remove(struct device *dev) cancel_delayed_work_sync(&phydev->state_queue); + if (IS_ENABLED(CONFIG_PHYLIB_LEDS)) + phy_leds_unregister(phydev); + phydev->state = PHY_DOWN; sfp_bus_del_upstream(phydev->sfp_bus); diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c index 5efdeb59f4b2972131b79453692591da481b8baa..d0aaa5cad85334504fdbb53f9f5fda3c8499ecb1 100644 --- a/drivers/net/phy/phylink.c +++ b/drivers/net/phy/phylink.c @@ -71,6 +71,7 @@ struct phylink { struct mutex state_mutex; struct phylink_link_state phy_state; struct work_struct resolve; + unsigned int pcs_neg_mode; bool mac_link_dropped; bool using_mac_select_pcs; @@ -156,6 +157,23 @@ static const char *phylink_an_mode_str(unsigned int mode) return mode < ARRAY_SIZE(modestr) ? modestr[mode] : "unknown"; } +static unsigned int phylink_interface_signal_rate(phy_interface_t interface) +{ + switch (interface) { + case PHY_INTERFACE_MODE_SGMII: + case PHY_INTERFACE_MODE_1000BASEX: /* 1.25Mbd */ + return 1250; + case PHY_INTERFACE_MODE_2500BASEX: /* 3.125Mbd */ + return 3125; + case PHY_INTERFACE_MODE_5GBASER: /* 5.15625Mbd */ + return 5156; + case PHY_INTERFACE_MODE_10GBASER: /* 10.3125Mbd */ + return 10313; + default: + return 0; + } +} + /** * phylink_interface_max_speed() - get the maximum speed of a phy interface * @interface: phy interface mode defined by &typedef phy_interface_t @@ -695,20 +713,17 @@ static int phylink_validate(struct phylink *pl, unsigned long *supported, { const unsigned long *interfaces = pl->config->supported_interfaces; - if (!phy_interface_empty(interfaces)) { - if (state->interface == PHY_INTERFACE_MODE_NA) - return phylink_validate_mask(pl, supported, state, - interfaces); + if (state->interface == PHY_INTERFACE_MODE_NA) + return phylink_validate_mask(pl, supported, state, interfaces); - if (!test_bit(state->interface, interfaces)) - return -EINVAL; - } + if (!test_bit(state->interface, interfaces)) + return -EINVAL; return phylink_validate_mac_and_pcs(pl, supported, state); } static int phylink_parse_fixedlink(struct phylink *pl, - struct fwnode_handle *fwnode) + const struct fwnode_handle *fwnode) { struct fwnode_handle *fixed_node; bool pause, asym_pause, autoneg; @@ -819,7 +834,8 @@ static int phylink_parse_fixedlink(struct phylink *pl, return 0; } -static int phylink_parse_mode(struct phylink *pl, struct fwnode_handle *fwnode) +static int phylink_parse_mode(struct phylink *pl, + const struct fwnode_handle *fwnode) { struct fwnode_handle *dn; const char *managed; @@ -962,11 +978,10 @@ static void phylink_apply_manual_flow(struct phylink *pl, state->pause = pl->link_config.pause; } -static void phylink_resolve_flow(struct phylink_link_state *state) +static void phylink_resolve_an_pause(struct phylink_link_state *state) { bool tx_pause, rx_pause; - state->pause = MLO_PAUSE_NONE; if (state->duplex == DUPLEX_FULL) { linkmode_resolve_pause(state->advertising, state->lp_advertising, @@ -978,6 +993,25 @@ static void phylink_resolve_flow(struct phylink_link_state *state) } } +static int phylink_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode, + const struct phylink_link_state *state, + bool permit_pause_to_mac) +{ + if (!pcs) + return 0; + + return pcs->ops->pcs_config(pcs, neg_mode, state->interface, + state->advertising, permit_pause_to_mac); +} + +static void phylink_pcs_link_up(struct phylink_pcs *pcs, unsigned int neg_mode, + phy_interface_t interface, int speed, + int duplex) +{ + if (pcs && pcs->ops->pcs_link_up) + pcs->ops->pcs_link_up(pcs, neg_mode, interface, speed, duplex); +} + static void phylink_pcs_poll_stop(struct phylink *pl) { if (pl->cfg_link_an_mode == MLO_AN_INBAND) @@ -1024,10 +1058,16 @@ static void phylink_major_config(struct phylink *pl, bool restart, { struct phylink_pcs *pcs = NULL; bool pcs_changed = false; + unsigned int rate_kbd; + unsigned int neg_mode; int err; phylink_dbg(pl, "major config %s\n", phy_modes(state->interface)); + pl->pcs_neg_mode = phylink_pcs_neg_mode(pl->cur_link_an_mode, + state->interface, + state->advertising); + if (pl->using_mac_select_pcs) { pcs = pl->mac_ops->mac_select_pcs(pl->config, state->interface); if (IS_ERR(pcs)) { @@ -1060,18 +1100,18 @@ static void phylink_major_config(struct phylink *pl, bool restart, phylink_mac_config(pl, state); - if (pl->pcs) { - err = pl->pcs->ops->pcs_config(pl->pcs, pl->cur_link_an_mode, - state->interface, - state->advertising, - !!(pl->link_config.pause & - MLO_PAUSE_AN)); - if (err < 0) - phylink_err(pl, "pcs_config failed: %pe\n", - ERR_PTR(err)); - if (err > 0) - restart = true; - } + neg_mode = pl->cur_link_an_mode; + if (pl->pcs && pl->pcs->neg_mode) + neg_mode = pl->pcs_neg_mode; + + err = phylink_pcs_config(pl->pcs, neg_mode, state, + !!(pl->link_config.pause & MLO_PAUSE_AN)); + if (err < 0) + phylink_err(pl, "pcs_config failed: %pe\n", + ERR_PTR(err)); + else if (err > 0) + restart = true; + if (restart) phylink_mac_pcs_an_restart(pl); @@ -1083,6 +1123,12 @@ static void phylink_major_config(struct phylink *pl, bool restart, ERR_PTR(err)); } + if (pl->sfp_bus) { + rate_kbd = phylink_interface_signal_rate(state->interface); + if (rate_kbd) + sfp_upstream_set_signal_rate(pl->sfp_bus, rate_kbd); + } + phylink_pcs_poll_start(pl); } @@ -1094,6 +1140,7 @@ static void phylink_major_config(struct phylink *pl, bool restart, */ static int phylink_change_inband_advert(struct phylink *pl) { + unsigned int neg_mode; int ret; if (test_bit(PHYLINK_DISABLE_STOPPED, &pl->phylink_disable_state)) @@ -1112,15 +1159,21 @@ static int phylink_change_inband_advert(struct phylink *pl) __ETHTOOL_LINK_MODE_MASK_NBITS, pl->link_config.advertising, pl->link_config.pause); + /* Recompute the PCS neg mode */ + pl->pcs_neg_mode = phylink_pcs_neg_mode(pl->cur_link_an_mode, + pl->link_config.interface, + pl->link_config.advertising); + + neg_mode = pl->cur_link_an_mode; + if (pl->pcs->neg_mode) + neg_mode = pl->pcs_neg_mode; + /* Modern PCS-based method; update the advert at the PCS, and * restart negotiation if the pcs_config() helper indicates that * the programmed advertisement has changed. */ - ret = pl->pcs->ops->pcs_config(pl->pcs, pl->cur_link_an_mode, - pl->link_config.interface, - pl->link_config.advertising, - !!(pl->link_config.pause & - MLO_PAUSE_AN)); + ret = phylink_pcs_config(pl->pcs, neg_mode, &pl->link_config, + !!(pl->link_config.pause & MLO_PAUSE_AN)); if (ret < 0) return ret; @@ -1171,7 +1224,8 @@ static void phylink_get_fixed_state(struct phylink *pl, else if (pl->link_gpio) state->link = !!gpiod_get_value_cansleep(pl->link_gpio); - phylink_resolve_flow(state); + state->pause = MLO_PAUSE_NONE; + phylink_resolve_an_pause(state); } static void phylink_mac_initial_config(struct phylink *pl, bool force_restart) @@ -1221,6 +1275,7 @@ static void phylink_link_up(struct phylink *pl, struct phylink_link_state link_state) { struct net_device *ndev = pl->netdev; + unsigned int neg_mode; int speed, duplex; bool rx_pause; @@ -1251,9 +1306,12 @@ static void phylink_link_up(struct phylink *pl, pl->cur_interface = link_state.interface; - if (pl->pcs && pl->pcs->ops->pcs_link_up) - pl->pcs->ops->pcs_link_up(pl->pcs, pl->cur_link_an_mode, - pl->cur_interface, speed, duplex); + neg_mode = pl->cur_link_an_mode; + if (pl->pcs && pl->pcs->neg_mode) + neg_mode = pl->pcs_neg_mode; + + phylink_pcs_link_up(pl->pcs, neg_mode, pl->cur_interface, speed, + duplex); pl->mac_ops->mac_link_up(pl->config, pl->phydev, pl->cur_link_an_mode, pl->cur_interface, speed, duplex, @@ -1441,7 +1499,7 @@ static void phylink_fixed_poll(struct timer_list *t) static const struct sfp_upstream_ops sfp_phylink_ops; static int phylink_register_sfp(struct phylink *pl, - struct fwnode_handle *fwnode) + const struct fwnode_handle *fwnode) { struct sfp_bus *bus; int ret; @@ -1480,7 +1538,7 @@ static int phylink_register_sfp(struct phylink *pl, * must use IS_ERR() to check for errors from this function. */ struct phylink *phylink_create(struct phylink_config *config, - struct fwnode_handle *fwnode, + const struct fwnode_handle *fwnode, phy_interface_t iface, const struct phylink_mac_ops *mac_ops) { @@ -1488,19 +1546,18 @@ struct phylink *phylink_create(struct phylink_config *config, struct phylink *pl; int ret; - if (mac_ops->mac_select_pcs && - mac_ops->mac_select_pcs(config, PHY_INTERFACE_MODE_NA) != - ERR_PTR(-EOPNOTSUPP)) - using_mac_select_pcs = true; - /* Validate the supplied configuration */ - if (using_mac_select_pcs && - phy_interface_empty(config->supported_interfaces)) { + if (phy_interface_empty(config->supported_interfaces)) { dev_err(config->dev, - "phylink: error: empty supported_interfaces but mac_select_pcs() method present\n"); + "phylink: error: empty supported_interfaces\n"); return ERR_PTR(-EINVAL); } + if (mac_ops->mac_select_pcs && + mac_ops->mac_select_pcs(config, PHY_INTERFACE_MODE_NA) != + ERR_PTR(-EOPNOTSUPP)) + using_mac_select_pcs = true; + pl = kzalloc(sizeof(*pl), GFP_KERNEL); if (!pl) return ERR_PTR(-ENOMEM); @@ -1809,7 +1866,7 @@ EXPORT_SYMBOL_GPL(phylink_of_phy_connect); * Returns 0 on success or a negative errno. */ int phylink_fwnode_phy_connect(struct phylink *pl, - struct fwnode_handle *fwnode, + const struct fwnode_handle *fwnode, u32 flags) { struct fwnode_handle *phy_fwnode; @@ -3131,8 +3188,8 @@ static void phylink_sfp_link_up(void *upstream) */ static bool phylink_phy_no_inband(struct phy_device *phy) { - return phy->is_c45 && - (phy->c45_ids.device_ids[1] & 0xfffffff0) == 0xae025150; + return phy->is_c45 && phy_id_compare(phy->c45_ids.device_ids[1], + 0xae025150, 0xfffffff0); } static int phylink_sfp_connect_phy(void *upstream, struct phy_device *phy) @@ -3196,10 +3253,48 @@ static const struct sfp_upstream_ops sfp_phylink_ops = { /* Helpers for MAC drivers */ +static struct { + int bit; + int speed; +} phylink_c73_priority_resolution[] = { + { ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT, SPEED_100000 }, + { ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT, SPEED_100000 }, + /* 100GBASE-KP4 and 100GBASE-CR10 not supported */ + { ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT, SPEED_40000 }, + { ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT, SPEED_40000 }, + { ETHTOOL_LINK_MODE_10000baseKR_Full_BIT, SPEED_10000 }, + { ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT, SPEED_10000 }, + /* 5GBASE-KR not supported */ + { ETHTOOL_LINK_MODE_2500baseX_Full_BIT, SPEED_2500 }, + { ETHTOOL_LINK_MODE_1000baseKX_Full_BIT, SPEED_1000 }, +}; + +void phylink_resolve_c73(struct phylink_link_state *state) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(phylink_c73_priority_resolution); i++) { + int bit = phylink_c73_priority_resolution[i].bit; + if (linkmode_test_bit(bit, state->advertising) && + linkmode_test_bit(bit, state->lp_advertising)) + break; + } + + if (i < ARRAY_SIZE(phylink_c73_priority_resolution)) { + state->speed = phylink_c73_priority_resolution[i].speed; + state->duplex = DUPLEX_FULL; + } else { + /* negotiation failure */ + state->link = false; + } + + phylink_resolve_an_pause(state); +} +EXPORT_SYMBOL_GPL(phylink_resolve_c73); + static void phylink_decode_c37_word(struct phylink_link_state *state, uint16_t config_reg, int speed) { - bool tx_pause, rx_pause; int fd_bit; if (speed == SPEED_2500) @@ -3218,13 +3313,7 @@ static void phylink_decode_c37_word(struct phylink_link_state *state, state->link = false; } - linkmode_resolve_pause(state->advertising, state->lp_advertising, - &tx_pause, &rx_pause); - - if (tx_pause) - state->pause |= MLO_PAUSE_TX; - if (rx_pause) - state->pause |= MLO_PAUSE_RX; + phylink_resolve_an_pause(state); } static void phylink_decode_sgmii_word(struct phylink_link_state *state, @@ -3456,18 +3545,19 @@ EXPORT_SYMBOL_GPL(phylink_mii_c22_pcs_encode_advertisement); /** * phylink_mii_c22_pcs_config() - configure clause 22 PCS * @pcs: a pointer to a &struct mdio_device. - * @mode: link autonegotiation mode * @interface: the PHY interface mode being configured * @advertising: the ethtool advertisement mask + * @neg_mode: PCS negotiation mode * * Configure a Clause 22 PCS PHY with the appropriate negotiation * parameters for the @mode, @interface and @advertising parameters. * Returns negative error number on failure, zero if the advertisement * has not changed, or positive if there is a change. */ -int phylink_mii_c22_pcs_config(struct mdio_device *pcs, unsigned int mode, +int phylink_mii_c22_pcs_config(struct mdio_device *pcs, phy_interface_t interface, - const unsigned long *advertising) + const unsigned long *advertising, + unsigned int neg_mode) { bool changed = 0; u16 bmcr; @@ -3482,15 +3572,12 @@ int phylink_mii_c22_pcs_config(struct mdio_device *pcs, unsigned int mode, changed = ret; } - /* Ensure ISOLATE bit is disabled */ - if (mode == MLO_AN_INBAND && - (interface == PHY_INTERFACE_MODE_SGMII || - interface == PHY_INTERFACE_MODE_QSGMII || - linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, advertising))) + if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED) bmcr = BMCR_ANENABLE; else bmcr = 0; + /* Configure the inband state. Ensure ISOLATE bit is disabled */ ret = mdiodev_modify(pcs, MII_BMCR, BMCR_ANENABLE | BMCR_ISOLATE, bmcr); if (ret < 0) return ret; diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c index 3d99fd6664d7a3a95877333b937a85bb283f9aab..894172a3e15fe8a6a86e38b64246ebefcb65362b 100644 --- a/drivers/net/phy/realtek.c +++ b/drivers/net/phy/realtek.c @@ -12,6 +12,7 @@ #include #include #include +#include #define RTL821x_PHYSR 0x11 #define RTL821x_PHYSR_DUPLEX BIT(13) @@ -80,6 +81,7 @@ struct rtl821x_priv { u16 phycr1; u16 phycr2; bool has_phycr2; + struct clk *clk; }; static int rtl821x_read_page(struct phy_device *phydev) @@ -103,6 +105,11 @@ static int rtl821x_probe(struct phy_device *phydev) if (!priv) return -ENOMEM; + priv->clk = devm_clk_get_optional_enabled(dev, NULL); + if (IS_ERR(priv->clk)) + return dev_err_probe(dev, PTR_ERR(priv->clk), + "failed to get phy clock\n"); + ret = phy_read_paged(phydev, 0xa43, RTL8211F_PHYCR1); if (ret < 0) return ret; @@ -419,10 +426,31 @@ static int rtl8211f_config_init(struct phy_device *phydev) return genphy_soft_reset(phydev); } +static int rtl821x_suspend(struct phy_device *phydev) +{ + struct rtl821x_priv *priv = phydev->priv; + int ret = 0; + + if (!phydev->wol_enabled) { + ret = genphy_suspend(phydev); + + if (ret) + return ret; + + clk_disable_unprepare(priv->clk); + } + + return ret; +} + static int rtl821x_resume(struct phy_device *phydev) { + struct rtl821x_priv *priv = phydev->priv; int ret; + if (!phydev->wol_enabled) + clk_prepare_enable(priv->clk); + ret = genphy_resume(phydev); if (ret < 0) return ret; @@ -927,10 +955,11 @@ static struct phy_driver realtek_drvs[] = { .read_status = rtlgen_read_status, .config_intr = &rtl8211f_config_intr, .handle_interrupt = rtl8211f_handle_interrupt, - .suspend = genphy_suspend, + .suspend = rtl821x_suspend, .resume = rtl821x_resume, .read_page = rtl821x_read_page, .write_page = rtl821x_write_page, + .flags = PHY_ALWAYS_CALL_SUSPEND, }, { PHY_ID_MATCH_EXACT(RTL_8211FVD_PHYID), .name = "RTL8211F-VD Gigabit Ethernet", @@ -939,10 +968,11 @@ static struct phy_driver realtek_drvs[] = { .read_status = rtlgen_read_status, .config_intr = &rtl8211f_config_intr, .handle_interrupt = rtl8211f_handle_interrupt, - .suspend = genphy_suspend, + .suspend = rtl821x_suspend, .resume = rtl821x_resume, .read_page = rtl821x_read_page, .write_page = rtl821x_write_page, + .flags = PHY_ALWAYS_CALL_SUSPEND, }, { .name = "Generic FE-GE Realtek PHY", .match_phy_device = rtlgen_match_phy_device, diff --git a/drivers/net/phy/sfp-bus.c b/drivers/net/phy/sfp-bus.c index 9372e5a4cadcf5f76ce2253dbf01d6080756ddb5..e8dd47bffe4356cd5cf436242d871795e2681ecf 100644 --- a/drivers/net/phy/sfp-bus.c +++ b/drivers/net/phy/sfp-bus.c @@ -575,6 +575,26 @@ static void sfp_upstream_clear(struct sfp_bus *bus) bus->upstream = NULL; } +/** + * sfp_upstream_set_signal_rate() - set data signalling rate + * @bus: a pointer to the &struct sfp_bus structure for the sfp module + * @rate_kbd: signalling rate in units of 1000 baud + * + * Configure the rate select settings on the SFP module for the signalling + * rate (not the same as the data rate). + * + * Locks that may be held: + * Phylink's state_mutex + * rtnl lock + * SFP's sm_mutex + */ +void sfp_upstream_set_signal_rate(struct sfp_bus *bus, unsigned int rate_kbd) +{ + if (bus->registered) + bus->socket_ops->set_signal_rate(bus->sfp, rate_kbd); +} +EXPORT_SYMBOL_GPL(sfp_upstream_set_signal_rate); + /** * sfp_bus_find_fwnode() - parse and locate the SFP bus from fwnode * @fwnode: firmware node for the parent device (MAC or PHY) diff --git a/drivers/net/phy/sfp.c b/drivers/net/phy/sfp.c index 89636dc71e483a00b9562808afa581e32a786635..d855a18308d789cee9b361e09407a5e4f03cc2c6 100644 --- a/drivers/net/phy/sfp.c +++ b/drivers/net/phy/sfp.c @@ -24,14 +24,18 @@ enum { GPIO_LOS, GPIO_TX_FAULT, GPIO_TX_DISABLE, - GPIO_RATE_SELECT, + GPIO_RS0, + GPIO_RS1, GPIO_MAX, SFP_F_PRESENT = BIT(GPIO_MODDEF0), SFP_F_LOS = BIT(GPIO_LOS), SFP_F_TX_FAULT = BIT(GPIO_TX_FAULT), SFP_F_TX_DISABLE = BIT(GPIO_TX_DISABLE), - SFP_F_RATE_SELECT = BIT(GPIO_RATE_SELECT), + SFP_F_RS0 = BIT(GPIO_RS0), + SFP_F_RS1 = BIT(GPIO_RS1), + + SFP_F_OUTPUTS = SFP_F_TX_DISABLE | SFP_F_RS0 | SFP_F_RS1, SFP_E_INSERT = 0, SFP_E_REMOVE, @@ -148,6 +152,7 @@ static const char *gpio_names[] = { "tx-fault", "tx-disable", "rate-select0", + "rate-select1", }; static const enum gpiod_flags gpio_flags[] = { @@ -156,6 +161,7 @@ static const enum gpiod_flags gpio_flags[] = { GPIOD_IN, GPIOD_ASIS, GPIOD_ASIS, + GPIOD_ASIS, }; /* t_start_up (SFF-8431) or t_init (SFF-8472) is the time required for a @@ -164,7 +170,6 @@ static const enum gpiod_flags gpio_flags[] = { * on board (for a copper SFP) time to initialise. */ #define T_WAIT msecs_to_jiffies(50) -#define T_WAIT_ROLLBALL msecs_to_jiffies(25000) #define T_START_UP msecs_to_jiffies(300) #define T_START_UP_BAD_GPON msecs_to_jiffies(60000) @@ -242,10 +247,18 @@ struct sfp { bool need_poll; + /* Access rules: + * state_hw_drive: st_mutex held + * state_hw_mask: st_mutex held + * state_soft_mask: st_mutex held + * state: st_mutex held unless reading input bits + */ struct mutex st_mutex; /* Protects state */ + unsigned int state_hw_drive; unsigned int state_hw_mask; unsigned int state_soft_mask; unsigned int state; + struct delayed_work poll; struct delayed_work timeout; struct mutex sm_mutex; /* Protects state machine */ @@ -262,6 +275,10 @@ struct sfp { unsigned int module_t_start_up; unsigned int module_t_wait; + unsigned int rate_kbd; + unsigned int rs_threshold_kbd; + unsigned int rs_state_mask; + bool have_a2; bool tx_fault_ignore; @@ -312,7 +329,7 @@ static bool sfp_module_supported(const struct sfp_eeprom_id *id) static const struct sff_data sfp_data = { .gpios = SFP_F_PRESENT | SFP_F_LOS | SFP_F_TX_FAULT | - SFP_F_TX_DISABLE | SFP_F_RATE_SELECT, + SFP_F_TX_DISABLE | SFP_F_RS0 | SFP_F_RS1, .module_supported = sfp_module_supported, }; @@ -333,6 +350,27 @@ static void sfp_fixup_ignore_tx_fault(struct sfp *sfp) sfp->tx_fault_ignore = true; } +// For 10GBASE-T short-reach modules +static void sfp_fixup_10gbaset_30m(struct sfp *sfp) +{ + sfp->id.base.connector = SFF8024_CONNECTOR_RJ45; + sfp->id.base.extended_cc = SFF8024_ECC_10GBASE_T_SR; +} + +static void sfp_fixup_rollball_proto(struct sfp *sfp, unsigned int secs) +{ + sfp->mdio_protocol = MDIO_I2C_ROLLBALL; + sfp->module_t_wait = msecs_to_jiffies(secs * 1000); +} + +static void sfp_fixup_fs_10gt(struct sfp *sfp) +{ + sfp_fixup_10gbaset_30m(sfp); + + // These SFPs need 4 seconds before the PHY can be accessed + sfp_fixup_rollball_proto(sfp, 4); +} + static void sfp_fixup_halny_gsfp(struct sfp *sfp) { /* Ignore the TX_FAULT and LOS signals on this module. @@ -344,8 +382,8 @@ static void sfp_fixup_halny_gsfp(struct sfp *sfp) static void sfp_fixup_rollball(struct sfp *sfp) { - sfp->mdio_protocol = MDIO_I2C_ROLLBALL; - sfp->module_t_wait = T_WAIT_ROLLBALL; + // Rollball SFPs need 25 seconds before the PHY can be accessed + sfp_fixup_rollball_proto(sfp, 25); } static void sfp_fixup_rollball_cc(struct sfp *sfp) @@ -410,6 +448,10 @@ static const struct sfp_quirk sfp_quirks[] = { SFP_QUIRK("ALCATELLUCENT", "3FE46541AA", sfp_quirk_2500basex, sfp_fixup_long_startup), + // Fiberstore SFP-10G-T doesn't identify as copper, and uses the + // Rollball protocol to talk to the PHY. + SFP_QUIRK_F("FS", "SFP-10G-T", sfp_fixup_fs_10gt), + SFP_QUIRK_F("HALNy", "HL-GSFP", sfp_fixup_halny_gsfp), // HG MXPD-483II-F 2.5G supports 2500Base-X, but incorrectly reports @@ -427,6 +469,11 @@ static const struct sfp_quirk sfp_quirks[] = { SFP_QUIRK_M("UBNT", "UF-INSTANT", sfp_quirk_ubnt_uf_instant), + // Walsun HXSX-ATR[CI]-1 don't identify as copper, and use the + // Rollball protocol to talk to the PHY. + SFP_QUIRK_F("Walsun", "HXSX-ATRC-1", sfp_fixup_fs_10gt), + SFP_QUIRK_F("Walsun", "HXSX-ATRI-1", sfp_fixup_fs_10gt), + SFP_QUIRK_F("OEM", "SFP-10G-T", sfp_fixup_rollball_cc), SFP_QUIRK_M("OEM", "SFP-2.5G-T", sfp_quirk_oem_2_5g), SFP_QUIRK_F("OEM", "RTSFP-10", sfp_fixup_rollball_cc), @@ -500,20 +547,37 @@ static unsigned int sff_gpio_get_state(struct sfp *sfp) static void sfp_gpio_set_state(struct sfp *sfp, unsigned int state) { - if (state & SFP_F_PRESENT) { - /* If the module is present, drive the signals */ - if (sfp->gpio[GPIO_TX_DISABLE]) + unsigned int drive; + + if (state & SFP_F_PRESENT) + /* If the module is present, drive the requested signals */ + drive = sfp->state_hw_drive; + else + /* Otherwise, let them float to the pull-ups */ + drive = 0; + + if (sfp->gpio[GPIO_TX_DISABLE]) { + if (drive & SFP_F_TX_DISABLE) gpiod_direction_output(sfp->gpio[GPIO_TX_DISABLE], state & SFP_F_TX_DISABLE); - if (state & SFP_F_RATE_SELECT) - gpiod_direction_output(sfp->gpio[GPIO_RATE_SELECT], - state & SFP_F_RATE_SELECT); - } else { - /* Otherwise, let them float to the pull-ups */ - if (sfp->gpio[GPIO_TX_DISABLE]) + else gpiod_direction_input(sfp->gpio[GPIO_TX_DISABLE]); - if (state & SFP_F_RATE_SELECT) - gpiod_direction_input(sfp->gpio[GPIO_RATE_SELECT]); + } + + if (sfp->gpio[GPIO_RS0]) { + if (drive & SFP_F_RS0) + gpiod_direction_output(sfp->gpio[GPIO_RS0], + state & SFP_F_RS0); + else + gpiod_direction_input(sfp->gpio[GPIO_RS0]); + } + + if (sfp->gpio[GPIO_RS1]) { + if (drive & SFP_F_RS1) + gpiod_direction_output(sfp->gpio[GPIO_RS1], + state & SFP_F_RS1); + else + gpiod_direction_input(sfp->gpio[GPIO_RS1]); } } @@ -675,16 +739,33 @@ static unsigned int sfp_soft_get_state(struct sfp *sfp) return state & sfp->state_soft_mask; } -static void sfp_soft_set_state(struct sfp *sfp, unsigned int state) +static void sfp_soft_set_state(struct sfp *sfp, unsigned int state, + unsigned int soft) { - u8 mask = SFP_STATUS_TX_DISABLE_FORCE; + u8 mask = 0; u8 val = 0; + if (soft & SFP_F_TX_DISABLE) + mask |= SFP_STATUS_TX_DISABLE_FORCE; if (state & SFP_F_TX_DISABLE) val |= SFP_STATUS_TX_DISABLE_FORCE; + if (soft & SFP_F_RS0) + mask |= SFP_STATUS_RS0_SELECT; + if (state & SFP_F_RS0) + val |= SFP_STATUS_RS0_SELECT; + + if (mask) + sfp_modify_u8(sfp, true, SFP_STATUS, mask, val); - sfp_modify_u8(sfp, true, SFP_STATUS, mask, val); + val = mask = 0; + if (soft & SFP_F_RS1) + mask |= SFP_EXT_STATUS_RS1_SELECT; + if (state & SFP_F_RS1) + val |= SFP_EXT_STATUS_RS1_SELECT; + + if (mask) + sfp_modify_u8(sfp, true, SFP_EXT_STATUS, mask, val); } static void sfp_soft_start_poll(struct sfp *sfp) @@ -692,27 +773,35 @@ static void sfp_soft_start_poll(struct sfp *sfp) const struct sfp_eeprom_id *id = &sfp->id; unsigned int mask = 0; - sfp->state_soft_mask = 0; if (id->ext.enhopts & SFP_ENHOPTS_SOFT_TX_DISABLE) mask |= SFP_F_TX_DISABLE; if (id->ext.enhopts & SFP_ENHOPTS_SOFT_TX_FAULT) mask |= SFP_F_TX_FAULT; if (id->ext.enhopts & SFP_ENHOPTS_SOFT_RX_LOS) mask |= SFP_F_LOS; + if (id->ext.enhopts & SFP_ENHOPTS_SOFT_RATE_SELECT) + mask |= sfp->rs_state_mask; + mutex_lock(&sfp->st_mutex); // Poll the soft state for hardware pins we want to ignore sfp->state_soft_mask = ~sfp->state_hw_mask & mask; if (sfp->state_soft_mask & (SFP_F_LOS | SFP_F_TX_FAULT) && !sfp->need_poll) mod_delayed_work(system_wq, &sfp->poll, poll_jiffies); + mutex_unlock(&sfp->st_mutex); } static void sfp_soft_stop_poll(struct sfp *sfp) { + mutex_lock(&sfp->st_mutex); sfp->state_soft_mask = 0; + mutex_unlock(&sfp->st_mutex); } +/* sfp_get_state() - must be called with st_mutex held, or in the + * initialisation path. + */ static unsigned int sfp_get_state(struct sfp *sfp) { unsigned int soft = sfp->state_soft_mask & (SFP_F_LOS | SFP_F_TX_FAULT); @@ -725,13 +814,26 @@ static unsigned int sfp_get_state(struct sfp *sfp) return state; } +/* sfp_set_state() - must be called with st_mutex held, or in the + * initialisation path. + */ static void sfp_set_state(struct sfp *sfp, unsigned int state) { + unsigned int soft; + sfp->set_state(sfp, state); - if (state & SFP_F_PRESENT && - sfp->state_soft_mask & SFP_F_TX_DISABLE) - sfp_soft_set_state(sfp, state); + soft = sfp->state_soft_mask & SFP_F_OUTPUTS; + if (state & SFP_F_PRESENT && soft) + sfp_soft_set_state(sfp, state, soft); +} + +static void sfp_mod_state(struct sfp *sfp, unsigned int mask, unsigned int set) +{ + mutex_lock(&sfp->st_mutex); + sfp->state = (sfp->state & ~mask) | set; + sfp_set_state(sfp, sfp->state); + mutex_unlock(&sfp->st_mutex); } static unsigned int sfp_check(void *buf, size_t len) @@ -1537,16 +1639,14 @@ static void sfp_module_tx_disable(struct sfp *sfp) { dev_dbg(sfp->dev, "tx disable %u -> %u\n", sfp->state & SFP_F_TX_DISABLE ? 1 : 0, 1); - sfp->state |= SFP_F_TX_DISABLE; - sfp_set_state(sfp, sfp->state); + sfp_mod_state(sfp, SFP_F_TX_DISABLE, SFP_F_TX_DISABLE); } static void sfp_module_tx_enable(struct sfp *sfp) { dev_dbg(sfp->dev, "tx disable %u -> %u\n", sfp->state & SFP_F_TX_DISABLE ? 1 : 0, 0); - sfp->state &= ~SFP_F_TX_DISABLE; - sfp_set_state(sfp, sfp->state); + sfp_mod_state(sfp, SFP_F_TX_DISABLE, 0); } #if IS_ENABLED(CONFIG_DEBUG_FS) @@ -1567,10 +1667,15 @@ static int sfp_debug_state_show(struct seq_file *s, void *data) sfp->sm_fault_retries); seq_printf(s, "PHY probe remaining retries: %d\n", sfp->sm_phy_retries); + seq_printf(s, "Signalling rate: %u kBd\n", sfp->rate_kbd); + seq_printf(s, "Rate select threshold: %u kBd\n", + sfp->rs_threshold_kbd); seq_printf(s, "moddef0: %d\n", !!(sfp->state & SFP_F_PRESENT)); seq_printf(s, "rx_los: %d\n", !!(sfp->state & SFP_F_LOS)); seq_printf(s, "tx_fault: %d\n", !!(sfp->state & SFP_F_TX_FAULT)); seq_printf(s, "tx_disable: %d\n", !!(sfp->state & SFP_F_TX_DISABLE)); + seq_printf(s, "rs0: %d\n", !!(sfp->state & SFP_F_RS0)); + seq_printf(s, "rs1: %d\n", !!(sfp->state & SFP_F_RS1)); return 0; } DEFINE_SHOW_ATTRIBUTE(sfp_debug_state); @@ -1599,16 +1704,18 @@ static void sfp_debugfs_exit(struct sfp *sfp) static void sfp_module_tx_fault_reset(struct sfp *sfp) { - unsigned int state = sfp->state; - - if (state & SFP_F_TX_DISABLE) - return; + unsigned int state; - sfp_set_state(sfp, state | SFP_F_TX_DISABLE); + mutex_lock(&sfp->st_mutex); + state = sfp->state; + if (!(state & SFP_F_TX_DISABLE)) { + sfp_set_state(sfp, state | SFP_F_TX_DISABLE); - udelay(T_RESET_US); + udelay(T_RESET_US); - sfp_set_state(sfp, state); + sfp_set_state(sfp, state); + } + mutex_unlock(&sfp->st_mutex); } /* SFP state machine */ @@ -1874,6 +1981,95 @@ static int sfp_sm_mod_hpower(struct sfp *sfp, bool enable) return 0; } +static void sfp_module_parse_rate_select(struct sfp *sfp) +{ + u8 rate_id; + + sfp->rs_threshold_kbd = 0; + sfp->rs_state_mask = 0; + + if (!(sfp->id.ext.options & cpu_to_be16(SFP_OPTIONS_RATE_SELECT))) + /* No support for RateSelect */ + return; + + /* Default to INF-8074 RateSelect operation. The signalling threshold + * rate is not well specified, so always select "Full Bandwidth", but + * SFF-8079 reveals that it is understood that RS0 will be low for + * 1.0625Gb/s and high for 2.125Gb/s. Choose a value half-way between. + * This method exists prior to SFF-8472. + */ + sfp->rs_state_mask = SFP_F_RS0; + sfp->rs_threshold_kbd = 1594; + + /* Parse the rate identifier, which is complicated due to history: + * SFF-8472 rev 9.5 marks this field as reserved. + * SFF-8079 references SFF-8472 rev 9.5 and defines bit 0. SFF-8472 + * compliance is not required. + * SFF-8472 rev 10.2 defines this field using values 0..4 + * SFF-8472 rev 11.0 redefines this field with bit 0 for SFF-8079 + * and even values. + */ + rate_id = sfp->id.base.rate_id; + if (rate_id == 0) + /* Unspecified */ + return; + + /* SFF-8472 rev 10.0..10.4 did not account for SFF-8079 using bit 0, + * and allocated value 3 to SFF-8431 independent tx/rx rate select. + * Convert this to a SFF-8472 rev 11.0 rate identifier. + */ + if (sfp->id.ext.sff8472_compliance >= SFP_SFF8472_COMPLIANCE_REV10_2 && + sfp->id.ext.sff8472_compliance < SFP_SFF8472_COMPLIANCE_REV11_0 && + rate_id == 3) + rate_id = SFF_RID_8431; + + if (rate_id & SFF_RID_8079) { + /* SFF-8079 RateSelect / Application Select in conjunction with + * SFF-8472 rev 9.5. SFF-8079 defines rate_id as a bitfield + * with only bit 0 used, which takes precedence over SFF-8472. + */ + if (!(sfp->id.ext.enhopts & SFP_ENHOPTS_APP_SELECT_SFF8079)) { + /* SFF-8079 Part 1 - rate selection between Fibre + * Channel 1.0625/2.125/4.25 Gbd modes. Note that RS0 + * is high for 2125, so we have to subtract 1 to + * include it. + */ + sfp->rs_threshold_kbd = 2125 - 1; + sfp->rs_state_mask = SFP_F_RS0; + } + return; + } + + /* SFF-8472 rev 9.5 does not define the rate identifier */ + if (sfp->id.ext.sff8472_compliance <= SFP_SFF8472_COMPLIANCE_REV9_5) + return; + + /* SFF-8472 rev 11.0 defines rate_id as a numerical value which will + * always have bit 0 clear due to SFF-8079's bitfield usage of rate_id. + */ + switch (rate_id) { + case SFF_RID_8431_RX_ONLY: + sfp->rs_threshold_kbd = 4250; + sfp->rs_state_mask = SFP_F_RS0; + break; + + case SFF_RID_8431_TX_ONLY: + sfp->rs_threshold_kbd = 4250; + sfp->rs_state_mask = SFP_F_RS1; + break; + + case SFF_RID_8431: + sfp->rs_threshold_kbd = 4250; + sfp->rs_state_mask = SFP_F_RS0 | SFP_F_RS1; + break; + + case SFF_RID_10G8G: + sfp->rs_threshold_kbd = 9000; + sfp->rs_state_mask = SFP_F_RS0 | SFP_F_RS1; + break; + } +} + /* GPON modules based on Realtek RTL8672 and RTL9601C chips (e.g. V-SOL * V2801F, CarlitoxxPro CPGOS03-0490, Ubiquiti U-Fiber Instant, ...) do * not support multibyte reads from the EEPROM. Each multi-byte read @@ -1953,6 +2149,7 @@ static int sfp_sm_mod_probe(struct sfp *sfp, bool report) /* SFP module inserted - read I2C data */ struct sfp_eeprom_id id; bool cotsworks_sfbg; + unsigned int mask; bool cotsworks; u8 check; int ret; @@ -2092,14 +2289,19 @@ static int sfp_sm_mod_probe(struct sfp *sfp, bool report) if (ret < 0) return ret; - /* Initialise state bits to use from hardware */ - sfp->state_hw_mask = SFP_F_PRESENT; + sfp_module_parse_rate_select(sfp); + + mask = SFP_F_PRESENT; if (sfp->gpio[GPIO_TX_DISABLE]) - sfp->state_hw_mask |= SFP_F_TX_DISABLE; + mask |= SFP_F_TX_DISABLE; if (sfp->gpio[GPIO_TX_FAULT]) - sfp->state_hw_mask |= SFP_F_TX_FAULT; + mask |= SFP_F_TX_FAULT; if (sfp->gpio[GPIO_LOS]) - sfp->state_hw_mask |= SFP_F_LOS; + mask |= SFP_F_LOS; + if (sfp->gpio[GPIO_RS0]) + mask |= SFP_F_RS0; + if (sfp->gpio[GPIO_RS1]) + mask |= SFP_F_RS1; sfp->module_t_start_up = T_START_UP; sfp->module_t_wait = T_WAIT; @@ -2117,8 +2319,17 @@ static int sfp_sm_mod_probe(struct sfp *sfp, bool report) sfp->mdio_protocol = MDIO_I2C_NONE; sfp->quirk = sfp_lookup_quirk(&id); + + mutex_lock(&sfp->st_mutex); + /* Initialise state bits to use from hardware */ + sfp->state_hw_mask = mask; + + /* We want to drive the rate select pins that the module is using */ + sfp->state_hw_drive |= sfp->rs_state_mask; + if (sfp->quirk && sfp->quirk->fixup) sfp->quirk->fixup(sfp); + mutex_unlock(&sfp->st_mutex); return 0; } @@ -2132,6 +2343,7 @@ static void sfp_sm_mod_remove(struct sfp *sfp) memset(&sfp->id, 0, sizeof(sfp->id)); sfp->module_power_mW = 0; + sfp->state_hw_drive = SFP_F_TX_DISABLE; sfp->have_a2 = false; dev_info(sfp->dev, "module removed\n"); @@ -2452,10 +2664,8 @@ static void sfp_sm_main(struct sfp *sfp, unsigned int event) } } -static void sfp_sm_event(struct sfp *sfp, unsigned int event) +static void __sfp_sm_event(struct sfp *sfp, unsigned int event) { - mutex_lock(&sfp->sm_mutex); - dev_dbg(sfp->dev, "SM: enter %s:%s:%s event %s\n", mod_state_to_str(sfp->sm_mod_state), dev_state_to_str(sfp->sm_dev_state), @@ -2470,7 +2680,12 @@ static void sfp_sm_event(struct sfp *sfp, unsigned int event) mod_state_to_str(sfp->sm_mod_state), dev_state_to_str(sfp->sm_dev_state), sm_state_to_str(sfp->sm_state)); +} +static void sfp_sm_event(struct sfp *sfp, unsigned int event) +{ + mutex_lock(&sfp->sm_mutex); + __sfp_sm_event(sfp, event); mutex_unlock(&sfp->sm_mutex); } @@ -2494,6 +2709,20 @@ static void sfp_stop(struct sfp *sfp) sfp_sm_event(sfp, SFP_E_DEV_DOWN); } +static void sfp_set_signal_rate(struct sfp *sfp, unsigned int rate_kbd) +{ + unsigned int set; + + sfp->rate_kbd = rate_kbd; + + if (rate_kbd > sfp->rs_threshold_kbd) + set = sfp->rs_state_mask; + else + set = 0; + + sfp_mod_state(sfp, SFP_F_RS0 | SFP_F_RS1, set); +} + static int sfp_module_info(struct sfp *sfp, struct ethtool_modinfo *modinfo) { /* locking... and check module is present */ @@ -2578,6 +2807,7 @@ static const struct sfp_socket_ops sfp_module_ops = { .detach = sfp_detach, .start = sfp_start, .stop = sfp_stop, + .set_signal_rate = sfp_set_signal_rate, .module_info = sfp_module_info, .module_eeprom = sfp_module_eeprom, .module_eeprom_by_page = sfp_module_eeprom_by_page, @@ -2596,6 +2826,7 @@ static void sfp_check_state(struct sfp *sfp) { unsigned int state, i, changed; + rtnl_lock(); mutex_lock(&sfp->st_mutex); state = sfp_get_state(sfp); changed = state ^ sfp->state; @@ -2609,23 +2840,24 @@ static void sfp_check_state(struct sfp *sfp) dev_dbg(sfp->dev, "%s %u -> %u\n", gpio_names[i], !!(sfp->state & BIT(i)), !!(state & BIT(i))); - state |= sfp->state & (SFP_F_TX_DISABLE | SFP_F_RATE_SELECT); + state |= sfp->state & SFP_F_OUTPUTS; sfp->state = state; + mutex_unlock(&sfp->st_mutex); - rtnl_lock(); + mutex_lock(&sfp->sm_mutex); if (changed & SFP_F_PRESENT) - sfp_sm_event(sfp, state & SFP_F_PRESENT ? - SFP_E_INSERT : SFP_E_REMOVE); + __sfp_sm_event(sfp, state & SFP_F_PRESENT ? + SFP_E_INSERT : SFP_E_REMOVE); if (changed & SFP_F_TX_FAULT) - sfp_sm_event(sfp, state & SFP_F_TX_FAULT ? - SFP_E_TX_FAULT : SFP_E_TX_CLEAR); + __sfp_sm_event(sfp, state & SFP_F_TX_FAULT ? + SFP_E_TX_FAULT : SFP_E_TX_CLEAR); if (changed & SFP_F_LOS) - sfp_sm_event(sfp, state & SFP_F_LOS ? - SFP_E_LOS_HIGH : SFP_E_LOS_LOW); + __sfp_sm_event(sfp, state & SFP_F_LOS ? + SFP_E_LOS_HIGH : SFP_E_LOS_LOW); + mutex_unlock(&sfp->sm_mutex); rtnl_unlock(); - mutex_unlock(&sfp->st_mutex); } static irqreturn_t sfp_irq(int irq, void *data) @@ -2643,6 +2875,8 @@ static void sfp_poll(struct work_struct *work) sfp_check_state(sfp); + // st_mutex doesn't need to be held here for state_soft_mask, + // it's unimportant if we race while reading this. if (sfp->state_soft_mask & (SFP_F_LOS | SFP_F_TX_FAULT) || sfp->need_poll) mod_delayed_work(system_wq, &sfp->poll, poll_jiffies); @@ -2748,6 +2982,7 @@ static int sfp_probe(struct platform_device *pdev) } sfp->state_hw_mask = SFP_F_PRESENT; + sfp->state_hw_drive = SFP_F_TX_DISABLE; sfp->get_state = sfp_gpio_get_state; sfp->set_state = sfp_gpio_set_state; @@ -2773,9 +3008,9 @@ static int sfp_probe(struct platform_device *pdev) */ sfp->state = sfp_get_state(sfp) | SFP_F_TX_DISABLE; - if (sfp->gpio[GPIO_RATE_SELECT] && - gpiod_get_value_cansleep(sfp->gpio[GPIO_RATE_SELECT])) - sfp->state |= SFP_F_RATE_SELECT; + if (sfp->gpio[GPIO_RS0] && + gpiod_get_value_cansleep(sfp->gpio[GPIO_RS0])) + sfp->state |= SFP_F_RS0; sfp_set_state(sfp, sfp->state); sfp_module_tx_disable(sfp); if (sfp->state & SFP_F_PRESENT) { diff --git a/drivers/net/phy/sfp.h b/drivers/net/phy/sfp.h index 6cf1643214d3ef34c0dfdb716be9b76823f0d3d1..c7cb50d1009992b46f657ac9c579f7cfe7ea48b2 100644 --- a/drivers/net/phy/sfp.h +++ b/drivers/net/phy/sfp.h @@ -19,6 +19,7 @@ struct sfp_socket_ops { void (*detach)(struct sfp *sfp); void (*start)(struct sfp *sfp); void (*stop)(struct sfp *sfp); + void (*set_signal_rate)(struct sfp *sfp, unsigned int rate_kbd); int (*module_info)(struct sfp *sfp, struct ethtool_modinfo *modinfo); int (*module_eeprom)(struct sfp *sfp, struct ethtool_eeprom *ee, u8 *data); diff --git a/drivers/net/ppp/Kconfig b/drivers/net/ppp/Kconfig index ac4d162d9455d80ca0c03dd1c59701fa637c011d..8c9ed1889d1af2442a0f5a315ce7bca30adf5ab3 100644 --- a/drivers/net/ppp/Kconfig +++ b/drivers/net/ppp/Kconfig @@ -129,6 +129,40 @@ config PPPOE which contains instruction on how to use this driver (under the heading "Kernel mode PPPoE"). +choice + prompt "Number of PPPoE hash bits" + default PPPOE_HASH_BITS_4 + depends on PPPOE + help + Select the number of bits used for hashing PPPoE interfaces. + + Larger sizes reduces the risk of hash collisions at the cost + of slightly increased memory usage. + + This hash table is on a per outer ethernet interface. + +config PPPOE_HASH_BITS_1 + bool "1 bit (2 buckets)" + +config PPPOE_HASH_BITS_2 + bool "2 bits (4 buckets)" + +config PPPOE_HASH_BITS_4 + bool "4 bits (16 buckets)" + +config PPPOE_HASH_BITS_8 + bool "8 bits (256 buckets)" + +endchoice + +config PPPOE_HASH_BITS + int + default 1 if PPPOE_HASH_BITS_1 + default 2 if PPPOE_HASH_BITS_2 + default 4 if PPPOE_HASH_BITS_4 + default 8 if PPPOE_HASH_BITS_8 + default 4 + config PPTP tristate "PPP over IPv4 (PPTP)" depends on PPP && NET_IPGRE_DEMUX diff --git a/drivers/net/ppp/pppoe.c b/drivers/net/ppp/pppoe.c index ce2cbb5903d7bc9ae490fc1cc290556f631d1e33..3b79c603b9363bbeb7437bd979479636d5655d67 100644 --- a/drivers/net/ppp/pppoe.c +++ b/drivers/net/ppp/pppoe.c @@ -80,7 +80,7 @@ #include -#define PPPOE_HASH_BITS 4 +#define PPPOE_HASH_BITS CONFIG_PPPOE_HASH_BITS #define PPPOE_HASH_SIZE (1 << PPPOE_HASH_BITS) #define PPPOE_HASH_MASK (PPPOE_HASH_SIZE - 1) diff --git a/drivers/net/ppp/pptp.c b/drivers/net/ppp/pptp.c index 0fe78826c8fa41442b4cc4b2198832f22eb3db91..32183f24e63ff7635a0a84155425b86b9928ebda 100644 --- a/drivers/net/ppp/pptp.c +++ b/drivers/net/ppp/pptp.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -128,6 +129,23 @@ static void del_chan(struct pppox_sock *sock) spin_unlock(&chan_lock); } +static struct rtable *pptp_route_output(struct pppox_sock *po, + struct flowi4 *fl4) +{ + struct sock *sk = &po->sk; + struct net *net; + + net = sock_net(sk); + flowi4_init_output(fl4, sk->sk_bound_dev_if, sk->sk_mark, 0, + RT_SCOPE_UNIVERSE, IPPROTO_GRE, 0, + po->proto.pptp.dst_addr.sin_addr.s_addr, + po->proto.pptp.src_addr.sin_addr.s_addr, + 0, 0, sock_net_uid(net, sk)); + security_sk_classify_flow(sk, flowi4_to_flowi_common(fl4)); + + return ip_route_output_flow(net, fl4, sk); +} + static int pptp_xmit(struct ppp_channel *chan, struct sk_buff *skb) { struct sock *sk = (struct sock *) chan->private; @@ -151,11 +169,7 @@ static int pptp_xmit(struct ppp_channel *chan, struct sk_buff *skb) if (sk_pppox(po)->sk_state & PPPOX_DEAD) goto tx_error; - rt = ip_route_output_ports(net, &fl4, NULL, - opt->dst_addr.sin_addr.s_addr, - opt->src_addr.sin_addr.s_addr, - 0, 0, IPPROTO_GRE, - RT_TOS(0), sk->sk_bound_dev_if); + rt = pptp_route_output(po, &fl4); if (IS_ERR(rt)) goto tx_error; @@ -438,12 +452,7 @@ static int pptp_connect(struct socket *sock, struct sockaddr *uservaddr, po->chan.private = sk; po->chan.ops = &pptp_chan_ops; - rt = ip_route_output_ports(sock_net(sk), &fl4, sk, - opt->dst_addr.sin_addr.s_addr, - opt->src_addr.sin_addr.s_addr, - 0, 0, - IPPROTO_GRE, RT_CONN_FLAGS(sk), - sk->sk_bound_dev_if); + rt = pptp_route_output(po, &fl4); if (IS_ERR(rt)) { error = -EHOSTUNREACH; goto end; diff --git a/drivers/net/tap.c b/drivers/net/tap.c index d30d730ed5a71b8cc31880acc0f82d4b0f65f739..9137fb8c1c420a792211cb70105144e8c2d73bc9 100644 --- a/drivers/net/tap.c +++ b/drivers/net/tap.c @@ -18,6 +18,7 @@ #include #include +#include #include #include #include diff --git a/drivers/net/usb/Kconfig b/drivers/net/usb/Kconfig index 4402eedb3d1a24e10561006a233d784cb06b869b..3fd7dccf0f9c98c91881398e509065753bcbb13d 100644 --- a/drivers/net/usb/Kconfig +++ b/drivers/net/usb/Kconfig @@ -583,12 +583,10 @@ config USB_IPHETH default n help Module used to share Internet connection (tethering) from your - iPhone (Original, 3G and 3GS) to your system. - Note that you need userspace libraries and programs that are needed - to pair your device with your system and that understand the iPhone - protocol. - - For more information: http://giagio.com/wiki/moin.cgi/iPhoneEthernetDriver + iPhone to your system. + Note that you need a corresponding userspace library/program + to pair your device with your system, for example usbmuxd + . config USB_SIERRA_NET tristate "USB-to-WWAN Driver for Sierra Wireless modems" diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c index 80849d115e5dd831194fc93838bb7e8353204eeb..c00a89b24df969466236e8ec1251b44a4718adfa 100644 --- a/drivers/net/usb/cdc_ether.c +++ b/drivers/net/usb/cdc_ether.c @@ -875,6 +875,12 @@ static const struct usb_device_id products[] = { USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), .driver_info = (unsigned long)&wwan_info, +}, { + /* U-blox LARA-R6 01B */ + USB_DEVICE_AND_INTERFACE_INFO(UBLOX_VENDOR_ID, 0x1313, USB_CLASS_COMM, + USB_CDC_SUBCLASS_ETHERNET, + USB_CDC_PROTO_NONE), + .driver_info = (unsigned long)&wwan_info, }, { /* U-blox LARA-L6 */ USB_DEVICE_AND_INTERFACE_INFO(UBLOX_VENDOR_ID, 0x1343, USB_CLASS_COMM, diff --git a/drivers/net/usb/ipheth.c b/drivers/net/usb/ipheth.c index 6a769df0b4213cc4cedb0aecc58910ac82b63b22..687d70cfc5563526d3e51d046bcc7a1bf3f00acc 100644 --- a/drivers/net/usb/ipheth.c +++ b/drivers/net/usb/ipheth.c @@ -52,6 +52,7 @@ #include #include #include +#include #define USB_VENDOR_APPLE 0x05ac @@ -59,8 +60,12 @@ #define IPHETH_USBINTF_SUBCLASS 253 #define IPHETH_USBINTF_PROTO 1 -#define IPHETH_BUF_SIZE 1514 #define IPHETH_IP_ALIGN 2 /* padding at front of URB */ +#define IPHETH_NCM_HEADER_SIZE (12 + 96) /* NCMH + NCM0 */ +#define IPHETH_TX_BUF_SIZE ETH_FRAME_LEN +#define IPHETH_RX_BUF_SIZE_LEGACY (IPHETH_IP_ALIGN + ETH_FRAME_LEN) +#define IPHETH_RX_BUF_SIZE_NCM 65536 + #define IPHETH_TX_TIMEOUT (5 * HZ) #define IPHETH_INTFNUM 2 @@ -71,6 +76,7 @@ #define IPHETH_CTRL_TIMEOUT (5 * HZ) #define IPHETH_CMD_GET_MACADDR 0x00 +#define IPHETH_CMD_ENABLE_NCM 0x04 #define IPHETH_CMD_CARRIER_CHECK 0x45 #define IPHETH_CARRIER_CHECK_TIMEOUT round_jiffies_relative(1 * HZ) @@ -97,6 +103,8 @@ struct ipheth_device { u8 bulk_out; struct delayed_work carrier_work; bool confirmed_pairing; + int (*rcvbulk_callback)(struct urb *urb); + size_t rx_buf_len; }; static int ipheth_rx_submit(struct ipheth_device *dev, gfp_t mem_flags); @@ -116,12 +124,12 @@ static int ipheth_alloc_urbs(struct ipheth_device *iphone) if (rx_urb == NULL) goto free_tx_urb; - tx_buf = usb_alloc_coherent(iphone->udev, IPHETH_BUF_SIZE, + tx_buf = usb_alloc_coherent(iphone->udev, IPHETH_TX_BUF_SIZE, GFP_KERNEL, &tx_urb->transfer_dma); if (tx_buf == NULL) goto free_rx_urb; - rx_buf = usb_alloc_coherent(iphone->udev, IPHETH_BUF_SIZE + IPHETH_IP_ALIGN, + rx_buf = usb_alloc_coherent(iphone->udev, iphone->rx_buf_len, GFP_KERNEL, &rx_urb->transfer_dma); if (rx_buf == NULL) goto free_tx_buf; @@ -134,7 +142,7 @@ static int ipheth_alloc_urbs(struct ipheth_device *iphone) return 0; free_tx_buf: - usb_free_coherent(iphone->udev, IPHETH_BUF_SIZE, tx_buf, + usb_free_coherent(iphone->udev, IPHETH_TX_BUF_SIZE, tx_buf, tx_urb->transfer_dma); free_rx_urb: usb_free_urb(rx_urb); @@ -146,9 +154,9 @@ static int ipheth_alloc_urbs(struct ipheth_device *iphone) static void ipheth_free_urbs(struct ipheth_device *iphone) { - usb_free_coherent(iphone->udev, IPHETH_BUF_SIZE + IPHETH_IP_ALIGN, iphone->rx_buf, + usb_free_coherent(iphone->udev, iphone->rx_buf_len, iphone->rx_buf, iphone->rx_urb->transfer_dma); - usb_free_coherent(iphone->udev, IPHETH_BUF_SIZE, iphone->tx_buf, + usb_free_coherent(iphone->udev, IPHETH_TX_BUF_SIZE, iphone->tx_buf, iphone->tx_urb->transfer_dma); usb_free_urb(iphone->rx_urb); usb_free_urb(iphone->tx_urb); @@ -160,14 +168,105 @@ static void ipheth_kill_urbs(struct ipheth_device *dev) usb_kill_urb(dev->rx_urb); } -static void ipheth_rcvbulk_callback(struct urb *urb) +static int ipheth_consume_skb(char *buf, int len, struct ipheth_device *dev) { - struct ipheth_device *dev; struct sk_buff *skb; - int status; + + skb = dev_alloc_skb(len); + if (!skb) { + dev->net->stats.rx_dropped++; + return -ENOMEM; + } + + skb_put_data(skb, buf, len); + skb->dev = dev->net; + skb->protocol = eth_type_trans(skb, dev->net); + + dev->net->stats.rx_packets++; + dev->net->stats.rx_bytes += len; + netif_rx(skb); + + return 0; +} + +static int ipheth_rcvbulk_callback_legacy(struct urb *urb) +{ + struct ipheth_device *dev; char *buf; int len; + dev = urb->context; + + if (urb->actual_length <= IPHETH_IP_ALIGN) { + dev->net->stats.rx_length_errors++; + return -EINVAL; + } + len = urb->actual_length - IPHETH_IP_ALIGN; + buf = urb->transfer_buffer + IPHETH_IP_ALIGN; + + return ipheth_consume_skb(buf, len, dev); +} + +static int ipheth_rcvbulk_callback_ncm(struct urb *urb) +{ + struct usb_cdc_ncm_nth16 *ncmh; + struct usb_cdc_ncm_ndp16 *ncm0; + struct usb_cdc_ncm_dpe16 *dpe; + struct ipheth_device *dev; + int retval = -EINVAL; + char *buf; + int len; + + dev = urb->context; + + if (urb->actual_length < IPHETH_NCM_HEADER_SIZE) { + dev->net->stats.rx_length_errors++; + return retval; + } + + ncmh = urb->transfer_buffer; + if (ncmh->dwSignature != cpu_to_le32(USB_CDC_NCM_NTH16_SIGN) || + le16_to_cpu(ncmh->wNdpIndex) >= urb->actual_length) { + dev->net->stats.rx_errors++; + return retval; + } + + ncm0 = urb->transfer_buffer + le16_to_cpu(ncmh->wNdpIndex); + if (ncm0->dwSignature != cpu_to_le32(USB_CDC_NCM_NDP16_NOCRC_SIGN) || + le16_to_cpu(ncmh->wHeaderLength) + le16_to_cpu(ncm0->wLength) >= + urb->actual_length) { + dev->net->stats.rx_errors++; + return retval; + } + + dpe = ncm0->dpe16; + while (le16_to_cpu(dpe->wDatagramIndex) != 0 && + le16_to_cpu(dpe->wDatagramLength) != 0) { + if (le16_to_cpu(dpe->wDatagramIndex) >= urb->actual_length || + le16_to_cpu(dpe->wDatagramIndex) + + le16_to_cpu(dpe->wDatagramLength) > urb->actual_length) { + dev->net->stats.rx_length_errors++; + return retval; + } + + buf = urb->transfer_buffer + le16_to_cpu(dpe->wDatagramIndex); + len = le16_to_cpu(dpe->wDatagramLength); + + retval = ipheth_consume_skb(buf, len, dev); + if (retval != 0) + return retval; + + dpe++; + } + + return 0; +} + +static void ipheth_rcvbulk_callback(struct urb *urb) +{ + struct ipheth_device *dev; + int retval, status; + dev = urb->context; if (dev == NULL) return; @@ -191,25 +290,27 @@ static void ipheth_rcvbulk_callback(struct urb *urb) dev->net->stats.rx_length_errors++; return; } - len = urb->actual_length - IPHETH_IP_ALIGN; - buf = urb->transfer_buffer + IPHETH_IP_ALIGN; - skb = dev_alloc_skb(len); - if (!skb) { - dev_err(&dev->intf->dev, "%s: dev_alloc_skb: -ENOMEM\n", - __func__); - dev->net->stats.rx_dropped++; + /* RX URBs starting with 0x00 0x01 do not encapsulate Ethernet frames, + * but rather are control frames. Their purpose is not documented, and + * they don't affect driver functionality, okay to drop them. + * There is usually just one 4-byte control frame as the very first + * URB received from the bulk IN endpoint. + */ + if (unlikely + (((char *)urb->transfer_buffer)[0] == 0 && + ((char *)urb->transfer_buffer)[1] == 1)) + goto rx_submit; + + retval = dev->rcvbulk_callback(urb); + if (retval != 0) { + dev_err(&dev->intf->dev, "%s: callback retval: %d\n", + __func__, retval); return; } - skb_put_data(skb, buf, len); - skb->dev = dev->net; - skb->protocol = eth_type_trans(skb, dev->net); - - dev->net->stats.rx_packets++; - dev->net->stats.rx_bytes += len; +rx_submit: dev->confirmed_pairing = true; - netif_rx(skb); ipheth_rx_submit(dev, GFP_ATOMIC); } @@ -310,6 +411,27 @@ static int ipheth_get_macaddr(struct ipheth_device *dev) return retval; } +static int ipheth_enable_ncm(struct ipheth_device *dev) +{ + struct usb_device *udev = dev->udev; + int retval; + + retval = usb_control_msg(udev, + usb_sndctrlpipe(udev, IPHETH_CTRL_ENDP), + IPHETH_CMD_ENABLE_NCM, /* request */ + 0x41, /* request type */ + 0x00, /* value */ + 0x02, /* index */ + NULL, + 0, + IPHETH_CTRL_TIMEOUT); + + dev_info(&dev->intf->dev, "%s: usb_control_msg: %d\n", + __func__, retval); + + return retval; +} + static int ipheth_rx_submit(struct ipheth_device *dev, gfp_t mem_flags) { struct usb_device *udev = dev->udev; @@ -317,7 +439,7 @@ static int ipheth_rx_submit(struct ipheth_device *dev, gfp_t mem_flags) usb_fill_bulk_urb(dev->rx_urb, udev, usb_rcvbulkpipe(udev, dev->bulk_in), - dev->rx_buf, IPHETH_BUF_SIZE + IPHETH_IP_ALIGN, + dev->rx_buf, dev->rx_buf_len, ipheth_rcvbulk_callback, dev); dev->rx_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; @@ -365,7 +487,7 @@ static netdev_tx_t ipheth_tx(struct sk_buff *skb, struct net_device *net) int retval; /* Paranoid */ - if (skb->len > IPHETH_BUF_SIZE) { + if (skb->len > IPHETH_TX_BUF_SIZE) { WARN(1, "%s: skb too large: %d bytes\n", __func__, skb->len); dev->net->stats.tx_dropped++; dev_kfree_skb_any(skb); @@ -373,12 +495,10 @@ static netdev_tx_t ipheth_tx(struct sk_buff *skb, struct net_device *net) } memcpy(dev->tx_buf, skb->data, skb->len); - if (skb->len < IPHETH_BUF_SIZE) - memset(dev->tx_buf + skb->len, 0, IPHETH_BUF_SIZE - skb->len); usb_fill_bulk_urb(dev->tx_urb, udev, usb_sndbulkpipe(udev, dev->bulk_out), - dev->tx_buf, IPHETH_BUF_SIZE, + dev->tx_buf, skb->len, ipheth_sndbulk_callback, dev); dev->tx_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; @@ -450,6 +570,8 @@ static int ipheth_probe(struct usb_interface *intf, dev->net = netdev; dev->intf = intf; dev->confirmed_pairing = false; + dev->rx_buf_len = IPHETH_RX_BUF_SIZE_LEGACY; + dev->rcvbulk_callback = ipheth_rcvbulk_callback_legacy; /* Set up endpoints */ hintf = usb_altnum_to_altsetting(intf, IPHETH_ALT_INTFNUM); if (hintf == NULL) { @@ -481,6 +603,12 @@ static int ipheth_probe(struct usb_interface *intf, if (retval) goto err_get_macaddr; + retval = ipheth_enable_ncm(dev); + if (!retval) { + dev->rx_buf_len = IPHETH_RX_BUF_SIZE_NCM; + dev->rcvbulk_callback = ipheth_rcvbulk_callback_ncm; + } + INIT_DELAYED_WORK(&dev->carrier_work, ipheth_carrier_check_work); retval = ipheth_alloc_urbs(dev); @@ -510,8 +638,8 @@ static int ipheth_probe(struct usb_interface *intf, ipheth_free_urbs(dev); err_alloc_urbs: err_get_macaddr: -err_alloc_ctrl_buf: kfree(dev->ctrl_buf); +err_alloc_ctrl_buf: err_endpoints: free_netdev(netdev); return retval; diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index 2e7c7b0cdc549e6b9e8799ea38083dca982c6db9..417f7ea1fffa692bd3ef274a942670fc53700d3c 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c @@ -1427,6 +1427,7 @@ static const struct usb_device_id products[] = { {QMI_FIXED_INTF(0x0489, 0xe0b4, 0)}, /* Foxconn T77W968 LTE */ {QMI_FIXED_INTF(0x0489, 0xe0b5, 0)}, /* Foxconn T77W968 LTE with eSIM support*/ {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 */ /* 4. Gobi 1000 devices */ diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c index 0999a58ca9d26945db7c5991e1637597a4a5d2e7..0738baa5b82e42ef156fe6bab3982d5440bfbeb7 100644 --- a/drivers/net/usb/r8152.c +++ b/drivers/net/usb/r8152.c @@ -27,6 +27,7 @@ #include #include #include +#include /* Information for net-next */ #define NETNEXT_VERSION "12" diff --git a/drivers/net/veth.c b/drivers/net/veth.c index dce9f9d63e04e09781a4d4c3aa62f70db14d83aa..614f3e3efab0950fa4bbe1ee897ba008fc5e3369 100644 --- a/drivers/net/veth.c +++ b/drivers/net/veth.c @@ -176,12 +176,27 @@ static int veth_get_sset_count(struct net_device *dev, int sset) } } +static void veth_get_page_pool_stats(struct net_device *dev, u64 *data) +{ +#ifdef CONFIG_PAGE_POOL_STATS + struct veth_priv *priv = netdev_priv(dev); + struct page_pool_stats pp_stats = {}; + int i; + + for (i = 0; i < dev->real_num_rx_queues; i++) { + if (!priv->rq[i].page_pool) + continue; + page_pool_get_stats(priv->rq[i].page_pool, &pp_stats); + } + page_pool_ethtool_stats_get(data, &pp_stats); +#endif /* CONFIG_PAGE_POOL_STATS */ +} + static void veth_get_ethtool_stats(struct net_device *dev, struct ethtool_stats *stats, u64 *data) { struct veth_priv *rcv_priv, *priv = netdev_priv(dev); struct net_device *peer = rtnl_dereference(priv->peer); - struct page_pool_stats pp_stats = {}; int i, j, idx, pp_idx; data[0] = peer ? peer->ifindex : 0; @@ -225,12 +240,7 @@ static void veth_get_ethtool_stats(struct net_device *dev, } page_pool_stats: - for (i = 0; i < dev->real_num_rx_queues; i++) { - if (!priv->rq[i].page_pool) - continue; - page_pool_get_stats(priv->rq[i].page_pool, &pp_stats); - } - page_pool_ethtool_stats_get(&data[pp_idx], &pp_stats); + veth_get_page_pool_stats(dev, &data[pp_idx]); } static void veth_get_channels(struct net_device *dev, @@ -747,7 +757,7 @@ static int veth_convert_skb_to_xdp_buff(struct veth_rq *rq, if (!page) goto drop; - nskb = build_skb(page_address(page), PAGE_SIZE); + nskb = napi_build_skb(page_address(page), PAGE_SIZE); if (!nskb) { page_pool_put_full_page(rq->page_pool, page, true); goto drop; diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 486b5849033dc96cf2ff3ded546c7736f840f61d..0db14f6b87d3ed76195beb242d894f434628ade8 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -445,6 +445,22 @@ static unsigned int mergeable_ctx_to_truesize(void *mrg_ctx) return (unsigned long)mrg_ctx & ((1 << MRG_CTX_HEADER_SHIFT) - 1); } +static struct sk_buff *virtnet_build_skb(void *buf, unsigned int buflen, + unsigned int headroom, + unsigned int len) +{ + struct sk_buff *skb; + + skb = build_skb(buf, buflen); + if (unlikely(!skb)) + return NULL; + + skb_reserve(skb, headroom); + skb_put(skb, len); + + return skb; +} + /* Called from bottom half context */ static struct sk_buff *page_to_skb(struct virtnet_info *vi, struct receive_queue *rq, @@ -478,13 +494,10 @@ static struct sk_buff *page_to_skb(struct virtnet_info *vi, /* copy small packet so we can reuse these pages */ if (!NET_IP_ALIGN && len > GOOD_COPY_LEN && tailroom >= shinfo_size) { - skb = build_skb(buf, truesize); + skb = virtnet_build_skb(buf, truesize, p - buf, len); if (unlikely(!skb)) return NULL; - skb_reserve(skb, p - buf); - skb_put(skb, len); - page = (struct page *)page->private; if (page) give_pages(rq, page); @@ -791,6 +804,75 @@ static int virtnet_xdp_xmit(struct net_device *dev, return ret; } +static void put_xdp_frags(struct xdp_buff *xdp) +{ + struct skb_shared_info *shinfo; + struct page *xdp_page; + int i; + + if (xdp_buff_has_frags(xdp)) { + shinfo = xdp_get_shared_info_from_buff(xdp); + for (i = 0; i < shinfo->nr_frags; i++) { + xdp_page = skb_frag_page(&shinfo->frags[i]); + put_page(xdp_page); + } + } +} + +static int virtnet_xdp_handler(struct bpf_prog *xdp_prog, struct xdp_buff *xdp, + struct net_device *dev, + unsigned int *xdp_xmit, + struct virtnet_rq_stats *stats) +{ + struct xdp_frame *xdpf; + int err; + u32 act; + + act = bpf_prog_run_xdp(xdp_prog, xdp); + stats->xdp_packets++; + + switch (act) { + case XDP_PASS: + return act; + + case XDP_TX: + stats->xdp_tx++; + xdpf = xdp_convert_buff_to_frame(xdp); + if (unlikely(!xdpf)) { + netdev_dbg(dev, "convert buff to frame failed for xdp\n"); + return XDP_DROP; + } + + err = virtnet_xdp_xmit(dev, 1, &xdpf, 0); + if (unlikely(!err)) { + xdp_return_frame_rx_napi(xdpf); + } else if (unlikely(err < 0)) { + trace_xdp_exception(dev, xdp_prog, act); + return XDP_DROP; + } + *xdp_xmit |= VIRTIO_XDP_TX; + return act; + + case XDP_REDIRECT: + stats->xdp_redirects++; + err = xdp_do_redirect(dev, xdp, xdp_prog); + if (err) + return XDP_DROP; + + *xdp_xmit |= VIRTIO_XDP_REDIR; + return act; + + default: + bpf_warn_invalid_xdp_action(dev, xdp_prog, act); + fallthrough; + case XDP_ABORTED: + trace_xdp_exception(dev, xdp_prog, act); + fallthrough; + case XDP_DROP: + return XDP_DROP; + } +} + static unsigned int virtnet_get_headroom(struct virtnet_info *vi) { return vi->xdp_enabled ? VIRTIO_XDP_HEADROOM : 0; @@ -864,134 +946,103 @@ static struct page *xdp_linearize_page(struct receive_queue *rq, return NULL; } -static struct sk_buff *receive_small(struct net_device *dev, - struct virtnet_info *vi, - struct receive_queue *rq, - void *buf, void *ctx, - unsigned int len, - unsigned int *xdp_xmit, - struct virtnet_rq_stats *stats) +static struct sk_buff *receive_small_build_skb(struct virtnet_info *vi, + unsigned int xdp_headroom, + void *buf, + unsigned int len) { + unsigned int header_offset; + unsigned int headroom; + unsigned int buflen; struct sk_buff *skb; - struct bpf_prog *xdp_prog; - unsigned int xdp_headroom = (unsigned long)ctx; + + header_offset = VIRTNET_RX_PAD + xdp_headroom; + headroom = vi->hdr_len + header_offset; + buflen = SKB_DATA_ALIGN(GOOD_PACKET_LEN + headroom) + + SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); + + skb = virtnet_build_skb(buf, buflen, headroom, len); + if (unlikely(!skb)) + return NULL; + + buf += header_offset; + memcpy(skb_vnet_hdr(skb), buf, vi->hdr_len); + + return skb; +} + +static struct sk_buff *receive_small_xdp(struct net_device *dev, + struct virtnet_info *vi, + struct receive_queue *rq, + struct bpf_prog *xdp_prog, + void *buf, + unsigned int xdp_headroom, + unsigned int len, + unsigned int *xdp_xmit, + struct virtnet_rq_stats *stats) +{ unsigned int header_offset = VIRTNET_RX_PAD + xdp_headroom; unsigned int headroom = vi->hdr_len + header_offset; - unsigned int buflen = SKB_DATA_ALIGN(GOOD_PACKET_LEN + headroom) + - SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); + struct virtio_net_hdr_mrg_rxbuf *hdr = buf + header_offset; struct page *page = virt_to_head_page(buf); - unsigned int delta = 0; struct page *xdp_page; - int err; + unsigned int buflen; + struct xdp_buff xdp; + struct sk_buff *skb; unsigned int metasize = 0; + u32 act; - len -= vi->hdr_len; - stats->bytes += len; + if (unlikely(hdr->hdr.gso_type)) + goto err_xdp; - if (unlikely(len > GOOD_PACKET_LEN)) { - pr_debug("%s: rx error: len %u exceeds max size %d\n", - dev->name, len, GOOD_PACKET_LEN); - dev->stats.rx_length_errors++; - goto err; - } + buflen = SKB_DATA_ALIGN(GOOD_PACKET_LEN + headroom) + + SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); + + if (unlikely(xdp_headroom < virtnet_get_headroom(vi))) { + int offset = buf - page_address(page) + header_offset; + unsigned int tlen = len + vi->hdr_len; + int num_buf = 1; + + xdp_headroom = virtnet_get_headroom(vi); + header_offset = VIRTNET_RX_PAD + xdp_headroom; + headroom = vi->hdr_len + header_offset; + buflen = SKB_DATA_ALIGN(GOOD_PACKET_LEN + headroom) + + SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); + xdp_page = xdp_linearize_page(rq, &num_buf, page, + offset, header_offset, + &tlen); + if (!xdp_page) + goto err_xdp; - if (likely(!vi->xdp_enabled)) { - xdp_prog = NULL; - goto skip_xdp; + buf = page_address(xdp_page); + put_page(page); + page = xdp_page; } - rcu_read_lock(); - xdp_prog = rcu_dereference(rq->xdp_prog); - if (xdp_prog) { - struct virtio_net_hdr_mrg_rxbuf *hdr = buf + header_offset; - struct xdp_frame *xdpf; - struct xdp_buff xdp; - void *orig_data; - u32 act; + xdp_init_buff(&xdp, buflen, &rq->xdp_rxq); + xdp_prepare_buff(&xdp, buf + VIRTNET_RX_PAD + vi->hdr_len, + xdp_headroom, len, true); - if (unlikely(hdr->hdr.gso_type)) - goto err_xdp; + act = virtnet_xdp_handler(xdp_prog, &xdp, dev, xdp_xmit, stats); - if (unlikely(xdp_headroom < virtnet_get_headroom(vi))) { - int offset = buf - page_address(page) + header_offset; - unsigned int tlen = len + vi->hdr_len; - int num_buf = 1; - - xdp_headroom = virtnet_get_headroom(vi); - header_offset = VIRTNET_RX_PAD + xdp_headroom; - headroom = vi->hdr_len + header_offset; - buflen = SKB_DATA_ALIGN(GOOD_PACKET_LEN + headroom) + - SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); - xdp_page = xdp_linearize_page(rq, &num_buf, page, - offset, header_offset, - &tlen); - if (!xdp_page) - goto err_xdp; - - buf = page_address(xdp_page); - put_page(page); - page = xdp_page; - } + switch (act) { + case XDP_PASS: + /* Recalculate length in case bpf program changed it */ + len = xdp.data_end - xdp.data; + metasize = xdp.data - xdp.data_meta; + break; - xdp_init_buff(&xdp, buflen, &rq->xdp_rxq); - xdp_prepare_buff(&xdp, buf + VIRTNET_RX_PAD + vi->hdr_len, - xdp_headroom, len, true); - orig_data = xdp.data; - act = bpf_prog_run_xdp(xdp_prog, &xdp); - stats->xdp_packets++; - - switch (act) { - case XDP_PASS: - /* Recalculate length in case bpf program changed it */ - delta = orig_data - xdp.data; - len = xdp.data_end - xdp.data; - metasize = xdp.data - xdp.data_meta; - break; - case XDP_TX: - stats->xdp_tx++; - xdpf = xdp_convert_buff_to_frame(&xdp); - if (unlikely(!xdpf)) - goto err_xdp; - err = virtnet_xdp_xmit(dev, 1, &xdpf, 0); - if (unlikely(!err)) { - xdp_return_frame_rx_napi(xdpf); - } else if (unlikely(err < 0)) { - trace_xdp_exception(vi->dev, xdp_prog, act); - goto err_xdp; - } - *xdp_xmit |= VIRTIO_XDP_TX; - rcu_read_unlock(); - goto xdp_xmit; - case XDP_REDIRECT: - stats->xdp_redirects++; - err = xdp_do_redirect(dev, &xdp, xdp_prog); - if (err) - goto err_xdp; - *xdp_xmit |= VIRTIO_XDP_REDIR; - rcu_read_unlock(); - goto xdp_xmit; - default: - bpf_warn_invalid_xdp_action(vi->dev, xdp_prog, act); - fallthrough; - case XDP_ABORTED: - trace_xdp_exception(vi->dev, xdp_prog, act); - goto err_xdp; - case XDP_DROP: - goto err_xdp; - } + case XDP_TX: + case XDP_REDIRECT: + goto xdp_xmit; + + default: + goto err_xdp; } - rcu_read_unlock(); -skip_xdp: - skb = build_skb(buf, buflen); - if (!skb) + skb = virtnet_build_skb(buf, buflen, xdp.data - buf, len); + if (unlikely(!skb)) goto err; - skb_reserve(skb, headroom - delta); - skb_put(skb, len); - if (!xdp_prog) { - buf += header_offset; - memcpy(skb_vnet_hdr(skb), buf, vi->hdr_len); - } /* keep zeroed vnet hdr since XDP is loaded */ if (metasize) skb_metadata_set(skb, metasize); @@ -999,7 +1050,6 @@ static struct sk_buff *receive_small(struct net_device *dev, return skb; err_xdp: - rcu_read_unlock(); stats->xdp_drops++; err: stats->drops++; @@ -1008,6 +1058,53 @@ static struct sk_buff *receive_small(struct net_device *dev, return NULL; } +static struct sk_buff *receive_small(struct net_device *dev, + struct virtnet_info *vi, + struct receive_queue *rq, + void *buf, void *ctx, + unsigned int len, + unsigned int *xdp_xmit, + struct virtnet_rq_stats *stats) +{ + unsigned int xdp_headroom = (unsigned long)ctx; + struct page *page = virt_to_head_page(buf); + struct sk_buff *skb; + + len -= vi->hdr_len; + stats->bytes += len; + + if (unlikely(len > GOOD_PACKET_LEN)) { + pr_debug("%s: rx error: len %u exceeds max size %d\n", + dev->name, len, GOOD_PACKET_LEN); + dev->stats.rx_length_errors++; + goto err; + } + + if (unlikely(vi->xdp_enabled)) { + struct bpf_prog *xdp_prog; + + rcu_read_lock(); + xdp_prog = rcu_dereference(rq->xdp_prog); + if (xdp_prog) { + skb = receive_small_xdp(dev, vi, rq, xdp_prog, buf, + xdp_headroom, len, xdp_xmit, + stats); + rcu_read_unlock(); + return skb; + } + rcu_read_unlock(); + } + + skb = receive_small_build_skb(vi, xdp_headroom, buf, len); + if (likely(skb)) + return skb; + +err: + stats->drops++; + put_page(page); + return NULL; +} + static struct sk_buff *receive_big(struct net_device *dev, struct virtnet_info *vi, struct receive_queue *rq, @@ -1031,6 +1128,28 @@ static struct sk_buff *receive_big(struct net_device *dev, return NULL; } +static void mergeable_buf_free(struct receive_queue *rq, int num_buf, + struct net_device *dev, + struct virtnet_rq_stats *stats) +{ + struct page *page; + void *buf; + int len; + + while (num_buf-- > 1) { + buf = virtqueue_get_buf(rq->vq, &len); + if (unlikely(!buf)) { + pr_debug("%s: rx error: %d buffers missing\n", + dev->name, num_buf); + dev->stats.rx_length_errors++; + break; + } + stats->bytes += len; + page = virt_to_head_page(buf); + put_page(page); + } +} + /* Why not use xdp_build_skb_from_frame() ? * XDP core assumes that xdp frags are PAGE_SIZE in length, while in * virtio-net there are 2 points that do not match its requirements: @@ -1132,7 +1251,7 @@ static int virtnet_build_xdp_buff_mrg(struct net_device *dev, dev->name, *num_buf, virtio16_to_cpu(vi->vdev, hdr->num_buffers)); dev->stats.rx_length_errors++; - return -EINVAL; + goto err; } stats->bytes += len; @@ -1151,13 +1270,11 @@ static int virtnet_build_xdp_buff_mrg(struct net_device *dev, pr_debug("%s: rx error: len %u exceeds truesize %lu\n", dev->name, len, (unsigned long)(truesize - room)); dev->stats.rx_length_errors++; - return -EINVAL; + goto err; } frag = &shinfo->frags[shinfo->nr_frags++]; - __skb_frag_set_page(frag, page); - skb_frag_off_set(frag, offset); - skb_frag_size_set(frag, len); + skb_frag_fill_page_desc(frag, page, offset, len); if (page_is_pfmemalloc(page)) xdp_buff_set_frag_pfmemalloc(xdp); @@ -1166,6 +1283,144 @@ static int virtnet_build_xdp_buff_mrg(struct net_device *dev, *xdp_frags_truesize = xdp_frags_truesz; return 0; + +err: + put_xdp_frags(xdp); + return -EINVAL; +} + +static void *mergeable_xdp_get_buf(struct virtnet_info *vi, + struct receive_queue *rq, + struct bpf_prog *xdp_prog, + void *ctx, + unsigned int *frame_sz, + int *num_buf, + struct page **page, + int offset, + unsigned int *len, + struct virtio_net_hdr_mrg_rxbuf *hdr) +{ + unsigned int truesize = mergeable_ctx_to_truesize(ctx); + unsigned int headroom = mergeable_ctx_to_headroom(ctx); + struct page *xdp_page; + unsigned int xdp_room; + + /* Transient failure which in theory could occur if + * in-flight packets from before XDP was enabled reach + * the receive path after XDP is loaded. + */ + if (unlikely(hdr->hdr.gso_type)) + return NULL; + + /* Now XDP core assumes frag size is PAGE_SIZE, but buffers + * with headroom may add hole in truesize, which + * make their length exceed PAGE_SIZE. So we disabled the + * hole mechanism for xdp. See add_recvbuf_mergeable(). + */ + *frame_sz = truesize; + + if (likely(headroom >= virtnet_get_headroom(vi) && + (*num_buf == 1 || xdp_prog->aux->xdp_has_frags))) { + return page_address(*page) + offset; + } + + /* This happens when headroom is not enough because + * of the buffer was prefilled before XDP is set. + * This should only happen for the first several packets. + * In fact, vq reset can be used here to help us clean up + * the prefilled buffers, but many existing devices do not + * support it, and we don't want to bother users who are + * using xdp normally. + */ + if (!xdp_prog->aux->xdp_has_frags) { + /* linearize data for XDP */ + xdp_page = xdp_linearize_page(rq, num_buf, + *page, offset, + VIRTIO_XDP_HEADROOM, + len); + if (!xdp_page) + return NULL; + } else { + xdp_room = SKB_DATA_ALIGN(VIRTIO_XDP_HEADROOM + + sizeof(struct skb_shared_info)); + if (*len + xdp_room > PAGE_SIZE) + return NULL; + + xdp_page = alloc_page(GFP_ATOMIC); + if (!xdp_page) + return NULL; + + memcpy(page_address(xdp_page) + VIRTIO_XDP_HEADROOM, + page_address(*page) + offset, *len); + } + + *frame_sz = PAGE_SIZE; + + put_page(*page); + + *page = xdp_page; + + return page_address(*page) + VIRTIO_XDP_HEADROOM; +} + +static struct sk_buff *receive_mergeable_xdp(struct net_device *dev, + struct virtnet_info *vi, + struct receive_queue *rq, + struct bpf_prog *xdp_prog, + void *buf, + void *ctx, + unsigned int len, + unsigned int *xdp_xmit, + struct virtnet_rq_stats *stats) +{ + struct virtio_net_hdr_mrg_rxbuf *hdr = buf; + int num_buf = virtio16_to_cpu(vi->vdev, hdr->num_buffers); + struct page *page = virt_to_head_page(buf); + int offset = buf - page_address(page); + unsigned int xdp_frags_truesz = 0; + struct sk_buff *head_skb; + unsigned int frame_sz; + struct xdp_buff xdp; + void *data; + u32 act; + int err; + + data = mergeable_xdp_get_buf(vi, rq, xdp_prog, ctx, &frame_sz, &num_buf, &page, + offset, &len, hdr); + if (unlikely(!data)) + goto err_xdp; + + err = virtnet_build_xdp_buff_mrg(dev, vi, rq, &xdp, data, len, frame_sz, + &num_buf, &xdp_frags_truesz, stats); + if (unlikely(err)) + goto err_xdp; + + act = virtnet_xdp_handler(xdp_prog, &xdp, dev, xdp_xmit, stats); + + switch (act) { + case XDP_PASS: + head_skb = build_skb_from_xdp_buff(dev, vi, &xdp, xdp_frags_truesz); + if (unlikely(!head_skb)) + break; + return head_skb; + + case XDP_TX: + case XDP_REDIRECT: + return NULL; + + default: + break; + } + + put_xdp_frags(&xdp); + +err_xdp: + put_page(page); + mergeable_buf_free(rq, num_buf, dev, stats); + + stats->xdp_drops++; + stats->drops++; + return NULL; } static struct sk_buff *receive_mergeable(struct net_device *dev, @@ -1182,13 +1437,10 @@ static struct sk_buff *receive_mergeable(struct net_device *dev, struct page *page = virt_to_head_page(buf); int offset = buf - page_address(page); struct sk_buff *head_skb, *curr_skb; - struct bpf_prog *xdp_prog; unsigned int truesize = mergeable_ctx_to_truesize(ctx); unsigned int headroom = mergeable_ctx_to_headroom(ctx); unsigned int tailroom = headroom ? sizeof(struct skb_shared_info) : 0; unsigned int room = SKB_DATA_ALIGN(headroom + tailroom); - unsigned int frame_sz, xdp_room; - int err; head_skb = NULL; stats->bytes += len - vi->hdr_len; @@ -1200,149 +1452,20 @@ static struct sk_buff *receive_mergeable(struct net_device *dev, goto err_skb; } - if (likely(!vi->xdp_enabled)) { - xdp_prog = NULL; - goto skip_xdp; - } - - rcu_read_lock(); - xdp_prog = rcu_dereference(rq->xdp_prog); - if (xdp_prog) { - unsigned int xdp_frags_truesz = 0; - struct skb_shared_info *shinfo; - struct xdp_frame *xdpf; - struct page *xdp_page; - struct xdp_buff xdp; - void *data; - u32 act; - int i; - - /* Transient failure which in theory could occur if - * in-flight packets from before XDP was enabled reach - * the receive path after XDP is loaded. - */ - if (unlikely(hdr->hdr.gso_type)) - goto err_xdp; - - /* Now XDP core assumes frag size is PAGE_SIZE, but buffers - * with headroom may add hole in truesize, which - * make their length exceed PAGE_SIZE. So we disabled the - * hole mechanism for xdp. See add_recvbuf_mergeable(). - */ - frame_sz = truesize; - - /* This happens when headroom is not enough because - * of the buffer was prefilled before XDP is set. - * This should only happen for the first several packets. - * In fact, vq reset can be used here to help us clean up - * the prefilled buffers, but many existing devices do not - * support it, and we don't want to bother users who are - * using xdp normally. - */ - if (!xdp_prog->aux->xdp_has_frags && - (num_buf > 1 || headroom < virtnet_get_headroom(vi))) { - /* linearize data for XDP */ - xdp_page = xdp_linearize_page(rq, &num_buf, - page, offset, - VIRTIO_XDP_HEADROOM, - &len); - frame_sz = PAGE_SIZE; - - if (!xdp_page) - goto err_xdp; - offset = VIRTIO_XDP_HEADROOM; - } else if (unlikely(headroom < virtnet_get_headroom(vi))) { - xdp_room = SKB_DATA_ALIGN(VIRTIO_XDP_HEADROOM + - sizeof(struct skb_shared_info)); - if (len + xdp_room > PAGE_SIZE) - goto err_xdp; - - xdp_page = alloc_page(GFP_ATOMIC); - if (!xdp_page) - goto err_xdp; - - memcpy(page_address(xdp_page) + VIRTIO_XDP_HEADROOM, - page_address(page) + offset, len); - frame_sz = PAGE_SIZE; - offset = VIRTIO_XDP_HEADROOM; - } else { - xdp_page = page; - } - - data = page_address(xdp_page) + offset; - err = virtnet_build_xdp_buff_mrg(dev, vi, rq, &xdp, data, len, frame_sz, - &num_buf, &xdp_frags_truesz, stats); - if (unlikely(err)) - goto err_xdp_frags; + if (unlikely(vi->xdp_enabled)) { + struct bpf_prog *xdp_prog; - act = bpf_prog_run_xdp(xdp_prog, &xdp); - stats->xdp_packets++; - - switch (act) { - case XDP_PASS: - head_skb = build_skb_from_xdp_buff(dev, vi, &xdp, xdp_frags_truesz); - if (unlikely(!head_skb)) - goto err_xdp_frags; - - if (unlikely(xdp_page != page)) - put_page(page); + rcu_read_lock(); + xdp_prog = rcu_dereference(rq->xdp_prog); + if (xdp_prog) { + head_skb = receive_mergeable_xdp(dev, vi, rq, xdp_prog, buf, ctx, + len, xdp_xmit, stats); rcu_read_unlock(); return head_skb; - case XDP_TX: - stats->xdp_tx++; - xdpf = xdp_convert_buff_to_frame(&xdp); - if (unlikely(!xdpf)) { - netdev_dbg(dev, "convert buff to frame failed for xdp\n"); - goto err_xdp_frags; - } - err = virtnet_xdp_xmit(dev, 1, &xdpf, 0); - if (unlikely(!err)) { - xdp_return_frame_rx_napi(xdpf); - } else if (unlikely(err < 0)) { - trace_xdp_exception(vi->dev, xdp_prog, act); - goto err_xdp_frags; - } - *xdp_xmit |= VIRTIO_XDP_TX; - if (unlikely(xdp_page != page)) - put_page(page); - rcu_read_unlock(); - goto xdp_xmit; - case XDP_REDIRECT: - stats->xdp_redirects++; - err = xdp_do_redirect(dev, &xdp, xdp_prog); - if (err) - goto err_xdp_frags; - *xdp_xmit |= VIRTIO_XDP_REDIR; - if (unlikely(xdp_page != page)) - put_page(page); - rcu_read_unlock(); - goto xdp_xmit; - default: - bpf_warn_invalid_xdp_action(vi->dev, xdp_prog, act); - fallthrough; - case XDP_ABORTED: - trace_xdp_exception(vi->dev, xdp_prog, act); - fallthrough; - case XDP_DROP: - goto err_xdp_frags; - } -err_xdp_frags: - if (unlikely(xdp_page != page)) - __free_pages(xdp_page, 0); - - if (xdp_buff_has_frags(&xdp)) { - shinfo = xdp_get_shared_info_from_buff(&xdp); - for (i = 0; i < shinfo->nr_frags; i++) { - xdp_page = skb_frag_page(&shinfo->frags[i]); - put_page(xdp_page); - } } - - goto err_xdp; + rcu_read_unlock(); } - rcu_read_unlock(); -skip_xdp: head_skb = page_to_skb(vi, rq, page, offset, len, truesize, headroom); curr_skb = head_skb; @@ -1408,27 +1531,13 @@ static struct sk_buff *receive_mergeable(struct net_device *dev, ewma_pkt_len_add(&rq->mrg_avg_pkt_len, head_skb->len); return head_skb; -err_xdp: - rcu_read_unlock(); - stats->xdp_drops++; err_skb: put_page(page); - while (num_buf-- > 1) { - buf = virtqueue_get_buf(rq->vq, &len); - if (unlikely(!buf)) { - pr_debug("%s: rx error: %d buffers missing\n", - dev->name, num_buf); - dev->stats.rx_length_errors++; - break; - } - stats->bytes += len; - page = virt_to_head_page(buf); - put_page(page); - } + mergeable_buf_free(rq, num_buf, dev, stats); + err_buf: stats->drops++; dev_kfree_skb(head_skb); -xdp_xmit: return NULL; } diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c index f2b76ee866a4a80154591bab17a4483d9897fcb8..7fa74b8b21001438568dc1da4d26aea9f77876ab 100644 --- a/drivers/net/vmxnet3/vmxnet3_drv.c +++ b/drivers/net/vmxnet3/vmxnet3_drv.c @@ -686,9 +686,7 @@ vmxnet3_append_frag(struct sk_buff *skb, struct Vmxnet3_RxCompDesc *rcd, BUG_ON(skb_shinfo(skb)->nr_frags >= MAX_SKB_FRAGS); - __skb_frag_set_page(frag, rbi->page); - skb_frag_off_set(frag, 0); - skb_frag_size_set(frag, rcd->len); + skb_frag_fill_page_desc(frag, rbi->page, 0, rcd->len); skb->data_len += rcd->len; skb->truesize += PAGE_SIZE; skb_shinfo(skb)->nr_frags++; diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c index 561fe1b314f5fb6b70bec9a2bc9471868fabf775..78744549c1b30d4c18fed0c5188cfef4bb292df4 100644 --- a/drivers/net/vxlan/vxlan_core.c +++ b/drivers/net/vxlan/vxlan_core.c @@ -2352,7 +2352,8 @@ static int encap_bypass_if_local(struct sk_buff *skb, struct net_device *dev, #endif /* Bypass encapsulation if the destination is local */ if (rt_flags & RTCF_LOCAL && - !(rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST))) { + !(rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST)) && + vxlan->cfg.flags & VXLAN_F_LOCALBYPASS) { struct vxlan_dev *dst_vxlan; dst_release(dst); @@ -3172,6 +3173,7 @@ static void vxlan_raw_setup(struct net_device *dev) } static const struct nla_policy vxlan_policy[IFLA_VXLAN_MAX + 1] = { + [IFLA_VXLAN_UNSPEC] = { .strict_start_type = IFLA_VXLAN_LOCALBYPASS }, [IFLA_VXLAN_ID] = { .type = NLA_U32 }, [IFLA_VXLAN_GROUP] = { .len = sizeof_field(struct iphdr, daddr) }, [IFLA_VXLAN_GROUP6] = { .len = sizeof(struct in6_addr) }, @@ -3202,6 +3204,7 @@ static const struct nla_policy vxlan_policy[IFLA_VXLAN_MAX + 1] = { [IFLA_VXLAN_TTL_INHERIT] = { .type = NLA_FLAG }, [IFLA_VXLAN_DF] = { .type = NLA_U8 }, [IFLA_VXLAN_VNIFILTER] = { .type = NLA_U8 }, + [IFLA_VXLAN_LOCALBYPASS] = NLA_POLICY_MAX(NLA_U8, 1), }; static int vxlan_validate(struct nlattr *tb[], struct nlattr *data[], @@ -4011,6 +4014,17 @@ static int vxlan_nl2conf(struct nlattr *tb[], struct nlattr *data[], conf->flags |= VXLAN_F_UDP_ZERO_CSUM_TX; } + if (data[IFLA_VXLAN_LOCALBYPASS]) { + err = vxlan_nl2flag(conf, data, IFLA_VXLAN_LOCALBYPASS, + VXLAN_F_LOCALBYPASS, changelink, + true, extack); + if (err) + return err; + } else if (!changelink) { + /* default to local bypass on a new device */ + conf->flags |= VXLAN_F_LOCALBYPASS; + } + if (data[IFLA_VXLAN_UDP_ZERO_CSUM6_TX]) { err = vxlan_nl2flag(conf, data, IFLA_VXLAN_UDP_ZERO_CSUM6_TX, VXLAN_F_UDP_ZERO_CSUM6_TX, changelink, @@ -4232,6 +4246,7 @@ static size_t vxlan_get_size(const struct net_device *dev) nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_UDP_ZERO_CSUM6_RX */ nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_REMCSUM_TX */ nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_REMCSUM_RX */ + nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_LOCALBYPASS */ 0; } @@ -4308,7 +4323,9 @@ static int vxlan_fill_info(struct sk_buff *skb, const struct net_device *dev) nla_put_u8(skb, IFLA_VXLAN_REMCSUM_TX, !!(vxlan->cfg.flags & VXLAN_F_REMCSUM_TX)) || nla_put_u8(skb, IFLA_VXLAN_REMCSUM_RX, - !!(vxlan->cfg.flags & VXLAN_F_REMCSUM_RX))) + !!(vxlan->cfg.flags & VXLAN_F_REMCSUM_RX)) || + nla_put_u8(skb, IFLA_VXLAN_LOCALBYPASS, + !!(vxlan->cfg.flags & VXLAN_F_LOCALBYPASS))) goto nla_put_failure; if (nla_put(skb, IFLA_VXLAN_PORT_RANGE, sizeof(ports), &ports)) diff --git a/drivers/net/wireguard/device.c b/drivers/net/wireguard/device.c index d58e9f818d3b791bc181beb888ff2165a107dec1..258dcc1039216f311a223fd348295d4b5e03a3ed 100644 --- a/drivers/net/wireguard/device.c +++ b/drivers/net/wireguard/device.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include diff --git a/drivers/net/wireguard/netlink.c b/drivers/net/wireguard/netlink.c index 43c8c84e7ea82377c4d2a532380fcc5c4554fab2..6d1bd9f52d02a07498ce5217348de1ee8f4bc03d 100644 --- a/drivers/net/wireguard/netlink.c +++ b/drivers/net/wireguard/netlink.c @@ -546,6 +546,7 @@ static int wg_set_device(struct sk_buff *skb, struct genl_info *info) u8 *private_key = nla_data(info->attrs[WGDEVICE_A_PRIVATE_KEY]); u8 public_key[NOISE_PUBLIC_KEY_LEN]; struct wg_peer *peer, *temp; + bool send_staged_packets; if (!crypto_memneq(wg->static_identity.static_private, private_key, NOISE_PUBLIC_KEY_LEN)) @@ -564,14 +565,17 @@ static int wg_set_device(struct sk_buff *skb, struct genl_info *info) } down_write(&wg->static_identity.lock); - wg_noise_set_static_identity_private_key(&wg->static_identity, - private_key); - list_for_each_entry_safe(peer, temp, &wg->peer_list, - peer_list) { + send_staged_packets = !wg->static_identity.has_identity && netif_running(wg->dev); + wg_noise_set_static_identity_private_key(&wg->static_identity, private_key); + send_staged_packets = send_staged_packets && wg->static_identity.has_identity; + + wg_cookie_checker_precompute_device_keys(&wg->cookie_checker); + list_for_each_entry_safe(peer, temp, &wg->peer_list, peer_list) { wg_noise_precompute_static_static(peer); wg_noise_expire_current_peer_keypairs(peer); + if (send_staged_packets) + wg_packet_send_staged_packets(peer); } - wg_cookie_checker_precompute_device_keys(&wg->cookie_checker); up_write(&wg->static_identity.lock); } skip_set_private_key: diff --git a/drivers/net/wireguard/queueing.c b/drivers/net/wireguard/queueing.c index 8084e7408c0ae9065f57bc463921cb985fd68c5e..26d235d152352f8b0b28a61b45d83f72db4f0b5d 100644 --- a/drivers/net/wireguard/queueing.c +++ b/drivers/net/wireguard/queueing.c @@ -28,6 +28,7 @@ int wg_packet_queue_init(struct crypt_queue *queue, work_func_t function, int ret; memset(queue, 0, sizeof(*queue)); + queue->last_cpu = -1; ret = ptr_ring_init(&queue->ring, len, GFP_KERNEL); if (ret) return ret; diff --git a/drivers/net/wireguard/queueing.h b/drivers/net/wireguard/queueing.h index 125284b346a7765f264c9e8ebaaeb0885c4bad91..1ea4f874e367ee4185efd0cce9f2358c0d3d5e01 100644 --- a/drivers/net/wireguard/queueing.h +++ b/drivers/net/wireguard/queueing.h @@ -117,20 +117,17 @@ static inline int wg_cpumask_choose_online(int *stored_cpu, unsigned int id) return cpu; } -/* This function is racy, in the sense that next is unlocked, so it could return - * the same CPU twice. A race-free version of this would be to instead store an - * atomic sequence number, do an increment-and-return, and then iterate through - * every possible CPU until we get to that index -- choose_cpu. However that's - * a bit slower, and it doesn't seem like this potential race actually - * introduces any performance loss, so we live with it. +/* This function is racy, in the sense that it's called while last_cpu is + * unlocked, so it could return the same CPU twice. Adding locking or using + * atomic sequence numbers is slower though, and the consequences of racing are + * harmless, so live with it. */ -static inline int wg_cpumask_next_online(int *next) +static inline int wg_cpumask_next_online(int *last_cpu) { - int cpu = *next; - - while (unlikely(!cpumask_test_cpu(cpu, cpu_online_mask))) - cpu = cpumask_next(cpu, cpu_online_mask) % nr_cpumask_bits; - *next = cpumask_next(cpu, cpu_online_mask) % nr_cpumask_bits; + int cpu = cpumask_next(*last_cpu, cpu_online_mask); + if (cpu >= nr_cpu_ids) + cpu = cpumask_first(cpu_online_mask); + *last_cpu = cpu; return cpu; } @@ -159,7 +156,7 @@ static inline void wg_prev_queue_drop_peeked(struct prev_queue *queue) static inline int wg_queue_enqueue_per_device_and_peer( struct crypt_queue *device_queue, struct prev_queue *peer_queue, - struct sk_buff *skb, struct workqueue_struct *wq, int *next_cpu) + struct sk_buff *skb, struct workqueue_struct *wq) { int cpu; @@ -173,7 +170,7 @@ static inline int wg_queue_enqueue_per_device_and_peer( /* Then we queue it up in the device queue, which consumes the * packet as soon as it can. */ - cpu = wg_cpumask_next_online(next_cpu); + cpu = wg_cpumask_next_online(&device_queue->last_cpu); if (unlikely(ptr_ring_produce_bh(&device_queue->ring, skb))) return -EPIPE; queue_work_on(cpu, wq, &per_cpu_ptr(device_queue->worker, cpu)->work); diff --git a/drivers/net/wireguard/receive.c b/drivers/net/wireguard/receive.c index 7135d51d2d872edb66c856379ce2923b214289e9..0b3f0c843550957ee1fe3bed7185a7d990246c2b 100644 --- a/drivers/net/wireguard/receive.c +++ b/drivers/net/wireguard/receive.c @@ -524,7 +524,7 @@ static void wg_packet_consume_data(struct wg_device *wg, struct sk_buff *skb) goto err; ret = wg_queue_enqueue_per_device_and_peer(&wg->decrypt_queue, &peer->rx_queue, skb, - wg->packet_crypt_wq, &wg->decrypt_queue.last_cpu); + wg->packet_crypt_wq); if (unlikely(ret == -EPIPE)) wg_queue_enqueue_per_peer_rx(skb, PACKET_STATE_DEAD); if (likely(!ret || ret == -EPIPE)) { diff --git a/drivers/net/wireguard/send.c b/drivers/net/wireguard/send.c index 5368f7c35b4bf21706ecc5801ebd1ae68a58d43b..95c853b59e1dae1df8b4e5cbf4e3541e35806b82 100644 --- a/drivers/net/wireguard/send.c +++ b/drivers/net/wireguard/send.c @@ -318,7 +318,7 @@ static void wg_packet_create_data(struct wg_peer *peer, struct sk_buff *first) goto err; ret = wg_queue_enqueue_per_device_and_peer(&wg->encrypt_queue, &peer->tx_queue, first, - wg->packet_crypt_wq, &wg->encrypt_queue.last_cpu); + wg->packet_crypt_wq); if (unlikely(ret == -EPIPE)) wg_queue_enqueue_per_peer_tx(first, PACKET_STATE_DEAD); err: diff --git a/drivers/net/wireguard/timers.c b/drivers/net/wireguard/timers.c index 53d8a57a0dfa391b386e3ef2ca4ca3b0cf13d7f7..968bdb4df0b300d12abf6fe4e1858225b3caf044 100644 --- a/drivers/net/wireguard/timers.c +++ b/drivers/net/wireguard/timers.c @@ -234,10 +234,10 @@ void wg_timers_init(struct wg_peer *peer) void wg_timers_stop(struct wg_peer *peer) { - del_timer_sync(&peer->timer_retransmit_handshake); - del_timer_sync(&peer->timer_send_keepalive); - del_timer_sync(&peer->timer_new_handshake); - del_timer_sync(&peer->timer_zero_key_material); - del_timer_sync(&peer->timer_persistent_keepalive); + timer_delete_sync(&peer->timer_retransmit_handshake); + timer_delete_sync(&peer->timer_send_keepalive); + timer_delete_sync(&peer->timer_new_handshake); + timer_delete_sync(&peer->timer_zero_key_material); + timer_delete_sync(&peer->timer_persistent_keepalive); flush_work(&peer->clear_peer_work); } diff --git a/drivers/net/wireless/ath/ath10k/ahb.c b/drivers/net/wireless/ath/ath10k/ahb.c index f0c615fa561433106b71338efe4deb9b229269f3..4a006fb4d424b4d2d08f5e777a516ff96002bca4 100644 --- a/drivers/net/wireless/ath/ath10k/ahb.c +++ b/drivers/net/wireless/ath/ath10k/ahb.c @@ -27,7 +27,7 @@ MODULE_DEVICE_TABLE(of, ath10k_ahb_of_match); static inline struct ath10k_ahb *ath10k_ahb_priv(struct ath10k *ar) { - return &((struct ath10k_pci *)ar->drv_priv)->ahb[0]; + return &ath10k_pci_priv(ar)->ahb[0]; } static void ath10k_ahb_write32(struct ath10k *ar, u32 offset, u32 value) @@ -816,23 +816,13 @@ static int ath10k_ahb_probe(struct platform_device *pdev) err_core_destroy: ath10k_core_destroy(ar); - platform_set_drvdata(pdev, NULL); return ret; } -static int ath10k_ahb_remove(struct platform_device *pdev) +static void ath10k_ahb_remove(struct platform_device *pdev) { struct ath10k *ar = platform_get_drvdata(pdev); - struct ath10k_ahb *ar_ahb; - - if (!ar) - return -EINVAL; - - ar_ahb = ath10k_ahb_priv(ar); - - if (!ar_ahb) - return -EINVAL; ath10k_dbg(ar, ATH10K_DBG_AHB, "ahb remove\n"); @@ -844,10 +834,6 @@ static int ath10k_ahb_remove(struct platform_device *pdev) ath10k_ahb_clock_disable(ar); ath10k_ahb_resource_deinit(ar); ath10k_core_destroy(ar); - - platform_set_drvdata(pdev, NULL); - - return 0; } static struct platform_driver ath10k_ahb_driver = { @@ -856,7 +842,7 @@ static struct platform_driver ath10k_ahb_driver = { .of_match_table = ath10k_ahb_of_match, }, .probe = ath10k_ahb_probe, - .remove = ath10k_ahb_remove, + .remove_new = ath10k_ahb_remove, }; int ath10k_ahb_init(void) diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index 5eb131ab916fd0a56581602680dc98d2f63480c6..6cdb225b7eaccc17ae6a7044ffd229d1a7ab527c 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -2504,7 +2504,6 @@ EXPORT_SYMBOL(ath10k_core_napi_sync_disable); static void ath10k_core_restart(struct work_struct *work) { struct ath10k *ar = container_of(work, struct ath10k, restart_work); - struct ath10k_vif *arvif; int ret; set_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags); @@ -2543,14 +2542,6 @@ static void ath10k_core_restart(struct work_struct *work) ar->state = ATH10K_STATE_RESTARTING; ath10k_halt(ar); ath10k_scan_finish(ar); - if (ar->hw_params.hw_restart_disconnect) { - list_for_each_entry(arvif, &ar->arvifs, list) { - if (arvif->is_up && - arvif->vdev_type == WMI_VDEV_TYPE_STA) - ieee80211_hw_restart_disconnect(arvif->vif); - } - } - ieee80211_restart_hw(ar->hw); break; case ATH10K_STATE_OFF: @@ -3643,6 +3634,9 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev, mutex_init(&ar->dump_mutex); spin_lock_init(&ar->data_lock); + for (int ac = 0; ac < IEEE80211_NUM_ACS; ac++) + spin_lock_init(&ar->queue_lock[ac]); + INIT_LIST_HEAD(&ar->peers); init_waitqueue_head(&ar->peer_mapping_wq); init_waitqueue_head(&ar->htt.empty_tx_wq); diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index f5de8ce8fb4561221f3aa0972284490c5f6640d0..4b5239de401840b628bb776ef2f585edb31f310e 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -1170,6 +1170,9 @@ struct ath10k { /* protects shared structure data */ spinlock_t data_lock; + /* serialize wake_tx_queue calls per ac */ + spinlock_t queue_lock[IEEE80211_NUM_ACS]; + struct list_head arvifs; struct list_head peers; struct ath10k_peer *peer_map[ATH10K_MAX_NUM_PEER_IDS]; diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c index b9aea1510f7bb7032ab62483f5e2d0ef661e41a8..f9518e1c99039ea99a32b0649ec0181d7382facd 100644 --- a/drivers/net/wireless/ath/ath10k/debug.c +++ b/drivers/net/wireless/ath/ath10k/debug.c @@ -293,8 +293,8 @@ void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb) goto free; } - num_peers = ath10k_wmi_fw_stats_num_peers(&ar->debug.fw_stats.peers); - num_vdevs = ath10k_wmi_fw_stats_num_vdevs(&ar->debug.fw_stats.vdevs); + num_peers = list_count_nodes(&ar->debug.fw_stats.peers); + num_vdevs = list_count_nodes(&ar->debug.fw_stats.vdevs); is_start = (list_empty(&ar->debug.fw_stats.pdevs) && !list_empty(&stats.pdevs)); is_end = (!list_empty(&ar->debug.fw_stats.pdevs) && diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h index c051a22fce145f1203a6a13b35b5140b6279d4e7..e0c9f45e74761a550158ed0acad088a1c646a1b0 100644 --- a/drivers/net/wireless/ath/ath10k/htt.h +++ b/drivers/net/wireless/ath/ath10k/htt.h @@ -707,7 +707,7 @@ struct htt_rx_indication_prefix { __le16 fw_rx_desc_bytes; u8 pad0; u8 pad1; -}; +} __packed; struct htt_rx_indication { struct htt_rx_indication_hdr hdr; @@ -1565,7 +1565,7 @@ struct htt_tx_fetch_ind { /* ath10k_htt_get_tx_fetch_ind_resp_ids() */ DECLARE_FLEX_ARRAY(__le32, resp_ids); DECLARE_FLEX_ARRAY(struct htt_tx_fetch_record, records); - }; + } __packed; } __packed; static inline void * @@ -1723,7 +1723,7 @@ struct htt_resp { struct htt_tx_mode_switch_ind tx_mode_switch_ind; struct htt_channel_change chan_change; struct htt_peer_tx_stats peer_tx_stats; - }; + } __packed; } __packed; /*** host side structures follow ***/ diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 7675858f069bd28669d96be5d8edc1eecfbde023..03e7bc5b6c0bd0ec05ea398305ce476c29e6bcbd 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -4732,13 +4732,14 @@ static void ath10k_mac_op_wake_tx_queue(struct ieee80211_hw *hw, { struct ath10k *ar = hw->priv; int ret; - u8 ac; + u8 ac = txq->ac; ath10k_htt_tx_txq_update(hw, txq); if (ar->htt.tx_q_state.mode != HTT_TX_MODE_SWITCH_PUSH) return; - ac = txq->ac; + spin_lock_bh(&ar->queue_lock[ac]); + ieee80211_txq_schedule_start(hw, ac); txq = ieee80211_next_txq(hw, ac); if (!txq) @@ -4753,6 +4754,7 @@ static void ath10k_mac_op_wake_tx_queue(struct ieee80211_hw *hw, ath10k_htt_tx_txq_update(hw, txq); out: ieee80211_txq_schedule_end(hw, ac); + spin_unlock_bh(&ar->queue_lock[ac]); } /* Must not be called with conf_mutex held as workers can use that also. */ @@ -8107,6 +8109,7 @@ static void ath10k_reconfig_complete(struct ieee80211_hw *hw, enum ieee80211_reconfig_type reconfig_type) { struct ath10k *ar = hw->priv; + struct ath10k_vif *arvif; if (reconfig_type != IEEE80211_RECONFIG_TYPE_RESTART) return; @@ -8121,6 +8124,12 @@ static void ath10k_reconfig_complete(struct ieee80211_hw *hw, ar->state = ATH10K_STATE_ON; ieee80211_wake_queues(ar->hw); clear_bit(ATH10K_FLAG_RESTARTING, &ar->dev_flags); + if (ar->hw_params.hw_restart_disconnect) { + list_for_each_entry(arvif, &ar->arvifs, list) { + if (arvif->is_up && arvif->vdev_type == WMI_VDEV_TYPE_STA) + ieee80211_hw_restart_disconnect(arvif->vif); + } + } } mutex_unlock(&ar->conf_mutex); diff --git a/drivers/net/wireless/ath/ath10k/qmi.c b/drivers/net/wireless/ath/ath10k/qmi.c index 038c5903c0dc15789ae9d192ee308b74c5d796a5..52c1a3de8da60a006fdddfc6289c5a73e4bb6422 100644 --- a/drivers/net/wireless/ath/ath10k/qmi.c +++ b/drivers/net/wireless/ath/ath10k/qmi.c @@ -1082,8 +1082,7 @@ int ath10k_qmi_init(struct ath10k *ar, u32 msa_size) if (ret) goto err; - qmi->event_wq = alloc_workqueue("ath10k_qmi_driver_event", - WQ_UNBOUND, 1); + qmi->event_wq = alloc_ordered_workqueue("ath10k_qmi_driver_event", 0); if (!qmi->event_wq) { ath10k_err(ar, "failed to allocate workqueue\n"); ret = -EFAULT; diff --git a/drivers/net/wireless/ath/ath10k/snoc.c b/drivers/net/wireless/ath/ath10k/snoc.c index 5128a452c65f14f9f41e8dd43f2877f60527a423..26214c00cd0d7ba8b37dd324ee58614e98ef1a17 100644 --- a/drivers/net/wireless/ath/ath10k/snoc.c +++ b/drivers/net/wireless/ath/ath10k/snoc.c @@ -1848,7 +1848,7 @@ static int ath10k_snoc_free_resources(struct ath10k *ar) return 0; } -static int ath10k_snoc_remove(struct platform_device *pdev) +static void ath10k_snoc_remove(struct platform_device *pdev) { struct ath10k *ar = platform_get_drvdata(pdev); struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar); @@ -1861,8 +1861,6 @@ static int ath10k_snoc_remove(struct platform_device *pdev) wait_for_completion_timeout(&ar->driver_recovery, 3 * HZ); ath10k_snoc_free_resources(ar); - - return 0; } static void ath10k_snoc_shutdown(struct platform_device *pdev) @@ -1875,8 +1873,8 @@ static void ath10k_snoc_shutdown(struct platform_device *pdev) static struct platform_driver ath10k_snoc_driver = { .probe = ath10k_snoc_probe, - .remove = ath10k_snoc_remove, - .shutdown = ath10k_snoc_shutdown, + .remove_new = ath10k_snoc_remove, + .shutdown = ath10k_snoc_shutdown, .driver = { .name = "ath10k_snoc", .of_match_table = ath10k_snoc_dt_match, diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index 980d4124fa287d5072fc2353bff7edb2c342af73..05fa7d4c0e1aba1cbad8ee28433d528f0d3cd679 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -8164,28 +8164,6 @@ ath10k_wmi_10_2_4_op_gen_pdev_get_tpc_config(struct ath10k *ar, u32 param) return skb; } -size_t ath10k_wmi_fw_stats_num_peers(struct list_head *head) -{ - struct ath10k_fw_stats_peer *i; - size_t num = 0; - - list_for_each_entry(i, head, list) - ++num; - - return num; -} - -size_t ath10k_wmi_fw_stats_num_vdevs(struct list_head *head) -{ - struct ath10k_fw_stats_vdev *i; - size_t num = 0; - - list_for_each_entry(i, head, list) - ++num; - - return num; -} - static void ath10k_wmi_fw_pdev_base_stats_fill(const struct ath10k_fw_stats_pdev *pdev, char *buf, u32 *length) @@ -8462,8 +8440,8 @@ void ath10k_wmi_main_op_fw_stats_fill(struct ath10k *ar, goto unlock; } - num_peers = ath10k_wmi_fw_stats_num_peers(&fw_stats->peers); - num_vdevs = ath10k_wmi_fw_stats_num_vdevs(&fw_stats->vdevs); + num_peers = list_count_nodes(&fw_stats->peers); + num_vdevs = list_count_nodes(&fw_stats->vdevs); ath10k_wmi_fw_pdev_base_stats_fill(pdev, buf, &len); ath10k_wmi_fw_pdev_tx_stats_fill(pdev, buf, &len); @@ -8520,8 +8498,8 @@ void ath10k_wmi_10x_op_fw_stats_fill(struct ath10k *ar, goto unlock; } - num_peers = ath10k_wmi_fw_stats_num_peers(&fw_stats->peers); - num_vdevs = ath10k_wmi_fw_stats_num_vdevs(&fw_stats->vdevs); + num_peers = list_count_nodes(&fw_stats->peers); + num_vdevs = list_count_nodes(&fw_stats->vdevs); ath10k_wmi_fw_pdev_base_stats_fill(pdev, buf, &len); ath10k_wmi_fw_pdev_extra_stats_fill(pdev, buf, &len); @@ -8668,8 +8646,8 @@ void ath10k_wmi_10_4_op_fw_stats_fill(struct ath10k *ar, goto unlock; } - num_peers = ath10k_wmi_fw_stats_num_peers(&fw_stats->peers); - num_vdevs = ath10k_wmi_fw_stats_num_vdevs(&fw_stats->vdevs); + num_peers = list_count_nodes(&fw_stats->peers); + num_vdevs = list_count_nodes(&fw_stats->vdevs); ath10k_wmi_fw_pdev_base_stats_fill(pdev, buf, &len); ath10k_wmi_fw_pdev_extra_stats_fill(pdev, buf, &len); diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index 6de3cc4640a0b6825179cadaa8b3e757b5942778..6d04a66fe5e02439f69bc4ca207eb34997e18154 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h @@ -7502,8 +7502,6 @@ void ath10k_wmi_main_op_fw_stats_fill(struct ath10k *ar, void ath10k_wmi_10x_op_fw_stats_fill(struct ath10k *ar, struct ath10k_fw_stats *fw_stats, char *buf); -size_t ath10k_wmi_fw_stats_num_peers(struct list_head *head); -size_t ath10k_wmi_fw_stats_num_vdevs(struct list_head *head); void ath10k_wmi_10_4_op_fw_stats_fill(struct ath10k *ar, struct ath10k_fw_stats *fw_stats, char *buf); diff --git a/drivers/net/wireless/ath/ath11k/ahb.c b/drivers/net/wireless/ath/ath11k/ahb.c index 5cbba9a8b6ba9ecc3a5ad63ef4dafd5ad227549c..1cebba7889d78d40e055c5e1f34ae9fcfccfbc2a 100644 --- a/drivers/net/wireless/ath/ath11k/ahb.c +++ b/drivers/net/wireless/ath/ath11k/ahb.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: BSD-3-Clause-Clear /* * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. - * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved. */ #include @@ -734,7 +734,7 @@ static int ath11k_ahb_hif_suspend(struct ath11k_base *ab) return ret; } - ath11k_dbg(ab, ATH11K_DBG_AHB, "ahb device suspended\n"); + ath11k_dbg(ab, ATH11K_DBG_AHB, "device suspended\n"); return ret; } @@ -777,7 +777,7 @@ static int ath11k_ahb_hif_resume(struct ath11k_base *ab) return -ETIMEDOUT; } - ath11k_dbg(ab, ATH11K_DBG_AHB, "ahb device resumed\n"); + ath11k_dbg(ab, ATH11K_DBG_AHB, "device resumed\n"); return 0; } @@ -1127,6 +1127,7 @@ static int ath11k_ahb_probe(struct platform_device *pdev) switch (hw_rev) { case ATH11K_HW_IPQ8074: case ATH11K_HW_IPQ6018_HW10: + case ATH11K_HW_IPQ5018_HW10: hif_ops = &ath11k_ahb_hif_ops_ipq8074; pci_ops = NULL; break; @@ -1155,6 +1156,7 @@ static int ath11k_ahb_probe(struct platform_device *pdev) ab->hif.ops = hif_ops; ab->pdev = pdev; ab->hw_rev = hw_rev; + ab->fw_mode = ATH11K_FIRMWARE_MODE_NORMAL; platform_set_drvdata(pdev, ab); ret = ath11k_pcic_register_pci_ops(ab, pci_ops); diff --git a/drivers/net/wireless/ath/ath11k/ce.c b/drivers/net/wireless/ath/ath11k/ce.c index f2da95fd4253a2575e165d111308e613879fe0d4..289d47ae92afc54de6a54ee755f71525ffdea152 100644 --- a/drivers/net/wireless/ath/ath11k/ce.c +++ b/drivers/net/wireless/ath/ath11k/ce.c @@ -442,7 +442,7 @@ static void ath11k_ce_recv_process_cb(struct ath11k_ce_pipe *pipe) } while ((skb = __skb_dequeue(&list))) { - ath11k_dbg(ab, ATH11K_DBG_AHB, "rx ce pipe %d len %d\n", + ath11k_dbg(ab, ATH11K_DBG_CE, "rx ce pipe %d len %d\n", pipe->pipe_num, skb->len); pipe->recv_cb(ab, skb); } @@ -520,7 +520,7 @@ static void ath11k_ce_tx_process_cb(struct ath11k_ce_pipe *pipe) } while ((skb = __skb_dequeue(&list))) { - ath11k_dbg(ab, ATH11K_DBG_AHB, "tx ce pipe %d len %d\n", + ath11k_dbg(ab, ATH11K_DBG_CE, "tx ce pipe %d len %d\n", pipe->pipe_num, skb->len); pipe->send_cb(ab, skb); } diff --git a/drivers/net/wireless/ath/ath11k/core.c b/drivers/net/wireless/ath/ath11k/core.c index b1b90bd34d67ee37e801c48081ba1ca20f7aa9fa..bebfd342e28b2beaa0a0130a3a326a4762ef5509 100644 --- a/drivers/net/wireless/ath/ath11k/core.c +++ b/drivers/net/wireless/ath/ath11k/core.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: BSD-3-Clause-Clear /* * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. - * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved. */ #include @@ -32,6 +32,10 @@ module_param_named(frame_mode, ath11k_frame_mode, uint, 0644); MODULE_PARM_DESC(frame_mode, "Datapath frame mode (0: raw, 1: native wifi (default), 2: ethernet)"); +bool ath11k_ftm_mode; +module_param_named(ftm_mode, ath11k_ftm_mode, bool, 0444); +MODULE_PARM_DESC(ftm_mode, "Boots up in factory test mode"); + static const struct ath11k_hw_params ath11k_hw_params[] = { { .hw_rev = ATH11K_HW_IPQ8074, @@ -664,6 +668,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = { .hal_params = &ath11k_hw_hal_params_ipq8074, .single_pdev_only = false, .cold_boot_calib = true, + .cbcal_restart_fw = true, .fix_l1ss = true, .supports_dynamic_smps_6ghz = false, .alloc_cacheable_memory = true, @@ -874,16 +879,16 @@ static void ath11k_core_check_cc_code_bdfext(const struct dmi_header *hdr, void case ATH11K_SMBIOS_CC_ISO: ab->new_alpha2[0] = (smbios->cc_code >> 8) & 0xff; ab->new_alpha2[1] = smbios->cc_code & 0xff; - ath11k_dbg(ab, ATH11K_DBG_BOOT, "boot smbios cc_code %c%c\n", + ath11k_dbg(ab, ATH11K_DBG_BOOT, "smbios cc_code %c%c\n", ab->new_alpha2[0], ab->new_alpha2[1]); break; case ATH11K_SMBIOS_CC_WW: ab->new_alpha2[0] = '0'; ab->new_alpha2[1] = '0'; - ath11k_dbg(ab, ATH11K_DBG_BOOT, "boot smbios worldwide regdomain\n"); + ath11k_dbg(ab, ATH11K_DBG_BOOT, "smbios worldwide regdomain\n"); break; default: - ath11k_dbg(ab, ATH11K_DBG_BOOT, "boot ignore smbios country code setting %d\n", + ath11k_dbg(ab, ATH11K_DBG_BOOT, "ignore smbios country code setting %d\n", smbios->country_code_flag); break; } @@ -961,7 +966,8 @@ int ath11k_core_check_dt(struct ath11k_base *ab) } static int __ath11k_core_create_board_name(struct ath11k_base *ab, char *name, - size_t name_len, bool with_variant) + size_t name_len, bool with_variant, + bool bus_type_mode) { /* strlen(',variant=') + strlen(ab->qmi.target.bdf_ext) */ char variant[9 + ATH11K_QMI_BDF_EXT_STR_LENGTH] = { 0 }; @@ -972,15 +978,20 @@ static int __ath11k_core_create_board_name(struct ath11k_base *ab, char *name, switch (ab->id.bdf_search) { case ATH11K_BDF_SEARCH_BUS_AND_BOARD: - scnprintf(name, name_len, - "bus=%s,vendor=%04x,device=%04x,subsystem-vendor=%04x,subsystem-device=%04x,qmi-chip-id=%d,qmi-board-id=%d%s", - ath11k_bus_str(ab->hif.bus), - ab->id.vendor, ab->id.device, - ab->id.subsystem_vendor, - ab->id.subsystem_device, - ab->qmi.target.chip_id, - ab->qmi.target.board_id, - variant); + if (bus_type_mode) + scnprintf(name, name_len, + "bus=%s", + ath11k_bus_str(ab->hif.bus)); + else + scnprintf(name, name_len, + "bus=%s,vendor=%04x,device=%04x,subsystem-vendor=%04x,subsystem-device=%04x,qmi-chip-id=%d,qmi-board-id=%d%s", + ath11k_bus_str(ab->hif.bus), + ab->id.vendor, ab->id.device, + ab->id.subsystem_vendor, + ab->id.subsystem_device, + ab->qmi.target.chip_id, + ab->qmi.target.board_id, + variant); break; default: scnprintf(name, name_len, @@ -991,7 +1002,7 @@ static int __ath11k_core_create_board_name(struct ath11k_base *ab, char *name, break; } - ath11k_dbg(ab, ATH11K_DBG_BOOT, "boot using board name '%s'\n", name); + ath11k_dbg(ab, ATH11K_DBG_BOOT, "using board name '%s'\n", name); return 0; } @@ -999,13 +1010,19 @@ static int __ath11k_core_create_board_name(struct ath11k_base *ab, char *name, static int ath11k_core_create_board_name(struct ath11k_base *ab, char *name, size_t name_len) { - return __ath11k_core_create_board_name(ab, name, name_len, true); + return __ath11k_core_create_board_name(ab, name, name_len, true, false); } static int ath11k_core_create_fallback_board_name(struct ath11k_base *ab, char *name, size_t name_len) { - return __ath11k_core_create_board_name(ab, name, name_len, false); + return __ath11k_core_create_board_name(ab, name, name_len, false, false); +} + +static int ath11k_core_create_bus_type_board_name(struct ath11k_base *ab, char *name, + size_t name_len) +{ + return __ath11k_core_create_board_name(ab, name, name_len, false, true); } const struct firmware *ath11k_core_firmware_request(struct ath11k_base *ab, @@ -1024,7 +1041,7 @@ const struct firmware *ath11k_core_firmware_request(struct ath11k_base *ab, if (ret) return ERR_PTR(ret); - ath11k_dbg(ab, ATH11K_DBG_BOOT, "boot firmware request %s size %zu\n", + ath11k_dbg(ab, ATH11K_DBG_BOOT, "firmware request %s size %zu\n", path, fw->size); return fw; @@ -1085,7 +1102,7 @@ static int ath11k_core_parse_bd_ie_board(struct ath11k_base *ab, name_match_found = true; ath11k_dbg(ab, ATH11K_DBG_BOOT, - "boot found match %s for name '%s'", + "found match %s for name '%s'", ath11k_bd_ie_type_str(ie_id), boardname); } else if (board_ie_id == data_id) { @@ -1094,7 +1111,7 @@ static int ath11k_core_parse_bd_ie_board(struct ath11k_base *ab, goto next; ath11k_dbg(ab, ATH11K_DBG_BOOT, - "boot found %s for '%s'", + "found %s for '%s'", ath11k_bd_ie_type_str(ie_id), boardname); @@ -1309,7 +1326,7 @@ int ath11k_core_fetch_bdf(struct ath11k_base *ab, struct ath11k_board_data *bd) int ath11k_core_fetch_regdb(struct ath11k_base *ab, struct ath11k_board_data *bd) { - char boardname[BOARD_NAME_SIZE]; + char boardname[BOARD_NAME_SIZE], default_boardname[BOARD_NAME_SIZE]; int ret; ret = ath11k_core_create_board_name(ab, boardname, BOARD_NAME_SIZE); @@ -1326,6 +1343,21 @@ int ath11k_core_fetch_regdb(struct ath11k_base *ab, struct ath11k_board_data *bd if (!ret) goto exit; + ret = ath11k_core_create_bus_type_board_name(ab, default_boardname, + BOARD_NAME_SIZE); + if (ret) { + ath11k_dbg(ab, ATH11K_DBG_BOOT, + "failed to create default board name for regdb: %d", ret); + goto exit; + } + + ret = ath11k_core_fetch_board_data_api_n(ab, bd, default_boardname, + ATH11K_BD_IE_REGDB, + ATH11K_BD_IE_REGDB_NAME, + ATH11K_BD_IE_REGDB_DATA); + if (!ret) + goto exit; + ret = ath11k_core_fetch_board_data_api_1(ab, bd, ATH11K_REGDB_FILE_NAME); if (ret) ath11k_dbg(ab, ATH11K_DBG_BOOT, "failed to fetch %s from %s\n", @@ -1354,6 +1386,11 @@ static int ath11k_core_soc_create(struct ath11k_base *ab) { int ret; + if (ath11k_ftm_mode) { + ab->fw_mode = ATH11K_FIRMWARE_MODE_FTM; + ath11k_info(ab, "Booting in factory test mode\n"); + } + ret = ath11k_qmi_init_service(ab); if (ret) { ath11k_err(ab, "failed to initialize qmi :%d\n", ret); @@ -1580,7 +1617,7 @@ int ath11k_core_qmi_firmware_ready(struct ath11k_base *ab) { int ret; - ret = ath11k_core_start_firmware(ab, ATH11K_FIRMWARE_MODE_NORMAL); + ret = ath11k_core_start_firmware(ab, ab->fw_mode); if (ret) { ath11k_err(ab, "failed to start firmware: %d\n", ret); return ret; @@ -1745,7 +1782,8 @@ void ath11k_core_pre_reconfigure_recovery(struct ath11k_base *ab) for (i = 0; i < ab->num_radios; i++) { pdev = &ab->pdevs[i]; ar = pdev->ar; - if (!ar || ar->state == ATH11K_STATE_OFF) + if (!ar || ar->state == ATH11K_STATE_OFF || + ar->state == ATH11K_STATE_FTM) continue; ieee80211_stop_queues(ar->hw); @@ -1814,7 +1852,12 @@ static void ath11k_core_post_reconfigure_recovery(struct ath11k_base *ab) ath11k_warn(ab, "device is wedged, will not restart radio %d\n", i); break; + case ATH11K_STATE_FTM: + ath11k_dbg(ab, ATH11K_DBG_TESTMODE, + "fw mode reset done radio %d\n", i); + break; } + mutex_unlock(&ar->conf_mutex); } complete(&ab->driver_recovery); diff --git a/drivers/net/wireless/ath/ath11k/core.h b/drivers/net/wireless/ath/ath11k/core.h index 0830276e5028103be5b9fdf3927713c7771b4b25..9d15b4390b9c88a335b61469483e51e0f5160a77 100644 --- a/drivers/net/wireless/ath/ath11k/core.h +++ b/drivers/net/wireless/ath/ath11k/core.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: BSD-3-Clause-Clear */ /* * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. - * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved. */ #ifndef ATH11K_CORE_H @@ -52,6 +52,7 @@ #define ATH11K_SMBIOS_BDF_EXT_MAGIC "BDF_" extern unsigned int ath11k_frame_mode; +extern bool ath11k_ftm_mode; #define ATH11K_SCAN_TIMEOUT_HZ (20 * HZ) @@ -277,6 +278,7 @@ enum ath11k_dev_flags { ATH11K_FLAG_FIXED_MEM_RGN, ATH11K_FLAG_DEVICE_INIT_DONE, ATH11K_FLAG_MULTI_MSI_VECTORS, + ATH11K_FLAG_FTM_SEGMENTED, }; enum ath11k_monitor_flags { @@ -530,6 +532,7 @@ enum ath11k_state { ATH11K_STATE_RESTARTING, ATH11K_STATE_RESTARTED, ATH11K_STATE_WEDGED, + ATH11K_STATE_FTM, /* Add other states as required */ }; @@ -709,6 +712,8 @@ struct ath11k { u32 last_ppdu_id; u32 cached_ppdu_id; int monitor_vdev_id; + struct completion fw_mode_reset; + u8 ftm_msgref; #ifdef CONFIG_ATH11K_DEBUGFS struct ath11k_debug debug; #endif @@ -838,6 +843,7 @@ struct ath11k_msi_config { /* Master structure to hold the hw data which may be used in core module */ struct ath11k_base { enum ath11k_hw_rev hw_rev; + enum ath11k_firmware_mode fw_mode; struct platform_device *pdev; struct device *dev; struct ath11k_qmi qmi; @@ -978,6 +984,14 @@ struct ath11k_base { const struct ath11k_pci_ops *ops; } pci; +#ifdef CONFIG_NL80211_TESTMODE + struct { + u32 data_pos; + u32 expected_seq; + u8 *eventdata; + } testmode; +#endif + /* must be last */ u8 drv_priv[] __aligned(sizeof(void *)); }; diff --git a/drivers/net/wireless/ath/ath11k/debug.c b/drivers/net/wireless/ath/ath11k/debug.c index 958d874290624a338b1b9d0470d331fb07f3108d..f5c8a34c8802f0c177997f2aa053d4a69db8c2c9 100644 --- a/drivers/net/wireless/ath/ath11k/debug.c +++ b/drivers/net/wireless/ath/ath11k/debug.c @@ -66,7 +66,7 @@ void __ath11k_dbg(struct ath11k_base *ab, enum ath11k_debug_mask mask, vaf.va = &args; if (ath11k_debug_mask & mask) - dev_printk(KERN_DEBUG, ab->dev, "%pV", &vaf); + dev_printk(KERN_DEBUG, ab->dev, "%s %pV", ath11k_dbg_str(mask), &vaf); trace_ath11k_log_dbg(ab, mask, &vaf); diff --git a/drivers/net/wireless/ath/ath11k/debug.h b/drivers/net/wireless/ath/ath11k/debug.h index 91545640c47b201bb825a6fda50d706df8270674..9c52804ef8ac3096eed2928d6c6209241a4212e6 100644 --- a/drivers/net/wireless/ath/ath11k/debug.h +++ b/drivers/net/wireless/ath/ath11k/debug.h @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: BSD-3-Clause-Clear */ /* * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved. */ #ifndef _ATH11K_DEBUG_H_ @@ -21,13 +22,57 @@ enum ath11k_debug_mask { ATH11K_DBG_MGMT = 0x00000100, ATH11K_DBG_REG = 0x00000200, ATH11K_DBG_TESTMODE = 0x00000400, - ATH11k_DBG_HAL = 0x00000800, + ATH11K_DBG_HAL = 0x00000800, ATH11K_DBG_PCI = 0x00001000, ATH11K_DBG_DP_TX = 0x00002000, ATH11K_DBG_DP_RX = 0x00004000, - ATH11K_DBG_ANY = 0xffffffff, + ATH11K_DBG_CE = 0x00008000, }; +static inline const char *ath11k_dbg_str(enum ath11k_debug_mask mask) +{ + switch (mask) { + case ATH11K_DBG_AHB: + return "ahb"; + case ATH11K_DBG_WMI: + return "wmi"; + case ATH11K_DBG_HTC: + return "htc"; + case ATH11K_DBG_DP_HTT: + return "dp_htt"; + case ATH11K_DBG_MAC: + return "mac"; + case ATH11K_DBG_BOOT: + return "boot"; + case ATH11K_DBG_QMI: + return "qmi"; + case ATH11K_DBG_DATA: + return "data"; + case ATH11K_DBG_MGMT: + return "mgmt"; + case ATH11K_DBG_REG: + return "reg"; + case ATH11K_DBG_TESTMODE: + return "testmode"; + case ATH11K_DBG_HAL: + return "hal"; + case ATH11K_DBG_PCI: + return "pci"; + case ATH11K_DBG_DP_TX: + return "dp_tx"; + case ATH11K_DBG_DP_RX: + return "dp_rx"; + case ATH11K_DBG_CE: + return "ce"; + + /* no default handler to allow compiler to check that the + * enum is fully handled + */ + } + + return ""; +} + __printf(2, 3) void ath11k_info(struct ath11k_base *ab, const char *fmt, ...); __printf(2, 3) void ath11k_err(struct ath11k_base *ab, const char *fmt, ...); __printf(2, 3) void ath11k_warn(struct ath11k_base *ab, const char *fmt, ...); diff --git a/drivers/net/wireless/ath/ath11k/debugfs_htt_stats.c b/drivers/net/wireless/ath/ath11k/debugfs_htt_stats.c index b3efca6bd7ddbd1f920c02cf795bdfb0dbae9fa3..0207fc4910f3429a6b3867171173150ad3a0e813 100644 --- a/drivers/net/wireless/ath/ath11k/debugfs_htt_stats.c +++ b/drivers/net/wireless/ath/ath11k/debugfs_htt_stats.c @@ -4011,6 +4011,114 @@ void htt_print_phy_stats_tlv(const void *tag_buf, stats_req->buf_len = len; } +static inline void +htt_print_phy_reset_counters_tlv(const void *tag_buf, + u16 tag_len, + struct debug_htt_stats_req *stats_req) +{ + const struct htt_phy_reset_counters_tlv *htt_stats_buf = tag_buf; + u8 *buf = stats_req->buf; + u32 len = stats_req->buf_len; + u32 buf_len = ATH11K_HTT_STATS_BUF_SIZE; + + if (tag_len < sizeof(*htt_stats_buf)) + return; + + len += scnprintf(buf + len, buf_len - len, "HTT_PHY_RESET_COUNTERS_TLV:\n"); + + len += scnprintf(buf + len, buf_len - len, "pdev_id = %u\n", + htt_stats_buf->pdev_id); + len += scnprintf(buf + len, buf_len - len, "cf_active_low_fail_cnt = %u\n", + htt_stats_buf->cf_active_low_fail_cnt); + len += scnprintf(buf + len, buf_len - len, "cf_active_low_pass_cnt = %u\n", + htt_stats_buf->cf_active_low_pass_cnt); + len += scnprintf(buf + len, buf_len - len, "phy_off_through_vreg_cnt = %u\n", + htt_stats_buf->phy_off_through_vreg_cnt); + len += scnprintf(buf + len, buf_len - len, "force_calibration_cnt = %u\n", + htt_stats_buf->force_calibration_cnt); + len += scnprintf(buf + len, buf_len - len, "rf_mode_switch_phy_off_cnt = %u\n", + htt_stats_buf->rf_mode_switch_phy_off_cnt); + + stats_req->buf_len = len; +} + +static inline void +htt_print_phy_reset_stats_tlv(const void *tag_buf, + u16 tag_len, + struct debug_htt_stats_req *stats_req) +{ + const struct htt_phy_reset_stats_tlv *htt_stats_buf = tag_buf; + u8 *buf = stats_req->buf; + u32 len = stats_req->buf_len; + u32 buf_len = ATH11K_HTT_STATS_BUF_SIZE; + + if (tag_len < sizeof(*htt_stats_buf)) + return; + + len += scnprintf(buf + len, buf_len - len, "HTT_PHY_RESET_STATS_TLV:\n"); + + len += scnprintf(buf + len, buf_len - len, "pdev_id = %u\n", + htt_stats_buf->pdev_id); + len += scnprintf(buf + len, buf_len - len, "chan_mhz = %u\n", + htt_stats_buf->chan_mhz); + len += scnprintf(buf + len, buf_len - len, "chan_band_center_freq1 = %u\n", + htt_stats_buf->chan_band_center_freq1); + len += scnprintf(buf + len, buf_len - len, "chan_band_center_freq2 = %u\n", + htt_stats_buf->chan_band_center_freq2); + len += scnprintf(buf + len, buf_len - len, "chan_phy_mode = %u\n", + htt_stats_buf->chan_phy_mode); + len += scnprintf(buf + len, buf_len - len, "chan_flags = 0x%0x\n", + htt_stats_buf->chan_flags); + len += scnprintf(buf + len, buf_len - len, "chan_num = %u\n", + htt_stats_buf->chan_num); + len += scnprintf(buf + len, buf_len - len, "reset_cause = 0x%0x\n", + htt_stats_buf->reset_cause); + len += scnprintf(buf + len, buf_len - len, "prev_reset_cause = 0x%0x\n", + htt_stats_buf->prev_reset_cause); + len += scnprintf(buf + len, buf_len - len, "phy_warm_reset_src = 0x%0x\n", + htt_stats_buf->phy_warm_reset_src); + len += scnprintf(buf + len, buf_len - len, "rx_gain_tbl_mode = %d\n", + htt_stats_buf->rx_gain_tbl_mode); + len += scnprintf(buf + len, buf_len - len, "xbar_val = 0x%0x\n", + htt_stats_buf->xbar_val); + len += scnprintf(buf + len, buf_len - len, "force_calibration = %u\n", + htt_stats_buf->force_calibration); + len += scnprintf(buf + len, buf_len - len, "phyrf_mode = %u\n", + htt_stats_buf->phyrf_mode); + len += scnprintf(buf + len, buf_len - len, "phy_homechan = %u\n", + htt_stats_buf->phy_homechan); + len += scnprintf(buf + len, buf_len - len, "phy_tx_ch_mask = 0x%0x\n", + htt_stats_buf->phy_tx_ch_mask); + len += scnprintf(buf + len, buf_len - len, "phy_rx_ch_mask = 0x%0x\n", + htt_stats_buf->phy_rx_ch_mask); + len += scnprintf(buf + len, buf_len - len, "phybb_ini_mask = 0x%0x\n", + htt_stats_buf->phybb_ini_mask); + len += scnprintf(buf + len, buf_len - len, "phyrf_ini_mask = 0x%0x\n", + htt_stats_buf->phyrf_ini_mask); + len += scnprintf(buf + len, buf_len - len, "phy_dfs_en_mask = 0x%0x\n", + htt_stats_buf->phy_dfs_en_mask); + len += scnprintf(buf + len, buf_len - len, "phy_sscan_en_mask = 0x%0x\n", + htt_stats_buf->phy_sscan_en_mask); + len += scnprintf(buf + len, buf_len - len, "phy_synth_sel_mask = 0x%0x\n", + htt_stats_buf->phy_synth_sel_mask); + len += scnprintf(buf + len, buf_len - len, "phy_adfs_freq = %u\n", + htt_stats_buf->phy_adfs_freq); + len += scnprintf(buf + len, buf_len - len, "cck_fir_settings = 0x%0x\n", + htt_stats_buf->cck_fir_settings); + len += scnprintf(buf + len, buf_len - len, "phy_dyn_pri_chan = %u\n", + htt_stats_buf->phy_dyn_pri_chan); + len += scnprintf(buf + len, buf_len - len, "cca_thresh = 0x%0x\n", + htt_stats_buf->cca_thresh); + len += scnprintf(buf + len, buf_len - len, "dyn_cca_status = %u\n", + htt_stats_buf->dyn_cca_status); + len += scnprintf(buf + len, buf_len - len, "rxdesense_thresh_hw = 0x%x\n", + htt_stats_buf->rxdesense_thresh_hw); + len += scnprintf(buf + len, buf_len - len, "rxdesense_thresh_sw = 0x%x\n", + htt_stats_buf->rxdesense_thresh_sw); + + stats_req->buf_len = len; +} + static inline void htt_print_peer_ctrl_path_txrx_stats_tlv(const void *tag_buf, struct debug_htt_stats_req *stats_req) @@ -4425,6 +4533,12 @@ static int ath11k_dbg_htt_ext_stats_parse(struct ath11k_base *ab, case HTT_STATS_PHY_STATS_TAG: htt_print_phy_stats_tlv(tag_buf, stats_req); break; + case HTT_STATS_PHY_RESET_COUNTERS_TAG: + htt_print_phy_reset_counters_tlv(tag_buf, len, stats_req); + break; + case HTT_STATS_PHY_RESET_STATS_TAG: + htt_print_phy_reset_stats_tlv(tag_buf, len, stats_req); + break; case HTT_STATS_PEER_CTRL_PATH_TXRX_STATS_TAG: htt_print_peer_ctrl_path_txrx_stats_tlv(tag_buf, stats_req); break; diff --git a/drivers/net/wireless/ath/ath11k/debugfs_htt_stats.h b/drivers/net/wireless/ath/ath11k/debugfs_htt_stats.h index 0bbd58a380de671bb771a06968cadb32d2babb92..96219301f05bd426b29c11ec92cb025338407f56 100644 --- a/drivers/net/wireless/ath/ath11k/debugfs_htt_stats.h +++ b/drivers/net/wireless/ath/ath11k/debugfs_htt_stats.h @@ -111,6 +111,8 @@ enum htt_tlv_tag_t { HTT_STATS_TXBF_OFDMA_STEER_STATS_TAG = 116, HTT_STATS_PHY_COUNTERS_TAG = 121, HTT_STATS_PHY_STATS_TAG = 122, + HTT_STATS_PHY_RESET_COUNTERS_TAG = 123, + HTT_STATS_PHY_RESET_STATS_TAG = 124, HTT_STATS_MAX_TAG, }; @@ -1964,6 +1966,47 @@ struct htt_phy_stats_tlv { u32 fw_run_time; }; +struct htt_phy_reset_counters_tlv { + u32 pdev_id; + u32 cf_active_low_fail_cnt; + u32 cf_active_low_pass_cnt; + u32 phy_off_through_vreg_cnt; + u32 force_calibration_cnt; + u32 rf_mode_switch_phy_off_cnt; +}; + +struct htt_phy_reset_stats_tlv { + u32 pdev_id; + u32 chan_mhz; + u32 chan_band_center_freq1; + u32 chan_band_center_freq2; + u32 chan_phy_mode; + u32 chan_flags; + u32 chan_num; + u32 reset_cause; + u32 prev_reset_cause; + u32 phy_warm_reset_src; + u32 rx_gain_tbl_mode; + u32 xbar_val; + u32 force_calibration; + u32 phyrf_mode; + u32 phy_homechan; + u32 phy_tx_ch_mask; + u32 phy_rx_ch_mask; + u32 phybb_ini_mask; + u32 phyrf_ini_mask; + u32 phy_dfs_en_mask; + u32 phy_sscan_en_mask; + u32 phy_synth_sel_mask; + u32 phy_adfs_freq; + u32 cck_fir_settings; + u32 phy_dyn_pri_chan; + u32 cca_thresh; + u32 dyn_cca_status; + u32 rxdesense_thresh_hw; + u32 rxdesense_thresh_sw; +}; + struct htt_peer_ctrl_path_txrx_stats_tlv { /* peer mac address */ u8 peer_mac_addr[ETH_ALEN]; diff --git a/drivers/net/wireless/ath/ath11k/dp_rx.c b/drivers/net/wireless/ath/ath11k/dp_rx.c index f67ce62b2b48d2629bcf361ac476ce9fefd1a46b..5c76664ba0dd921e9c299205404832d62b2f74e5 100644 --- a/drivers/net/wireless/ath/ath11k/dp_rx.c +++ b/drivers/net/wireless/ath/ath11k/dp_rx.c @@ -1651,7 +1651,7 @@ static void ath11k_htt_backpressure_event_handler(struct ath11k_base *ab, backpressure_time = *data; - ath11k_dbg(ab, ATH11K_DBG_DP_HTT, "htt backpressure event, pdev %d, ring type %d,ring id %d, hp %d tp %d, backpressure time %d\n", + ath11k_dbg(ab, ATH11K_DBG_DP_HTT, "backpressure event, pdev %d, ring type %d,ring id %d, hp %d tp %d, backpressure time %d\n", pdev_id, ring_type, ring_id, hp, tp, backpressure_time); if (ring_type == HTT_BACKPRESSURE_UMAC_RING_TYPE) { @@ -2466,7 +2466,7 @@ static void ath11k_dp_rx_deliver_msdu(struct ath11k *ar, struct napi_struct *nap spin_unlock_bh(&ar->ab->base_lock); ath11k_dbg(ar->ab, ATH11K_DBG_DATA, - "rx skb %pK len %u peer %pM %d %s sn %u %s%s%s%s%s%s%s %srate_idx %u vht_nss %u freq %u band %u flag 0x%x fcs-err %i mic-err %i amsdu-more %i\n", + "rx skb %p len %u peer %pM %d %s sn %u %s%s%s%s%s%s%s %srate_idx %u vht_nss %u freq %u band %u flag 0x%x fcs-err %i mic-err %i amsdu-more %i\n", msdu, msdu->len, peer ? peer->addr : NULL, @@ -4908,7 +4908,7 @@ ath11k_dp_rx_mon_merg_msdus(struct ath11k *ar, goto err_merge_fail; ath11k_dbg(ab, ATH11K_DBG_DATA, - "mpdu_buf %pK mpdu_buf->len %u", + "mpdu_buf %p mpdu_buf->len %u", prev_buf, prev_buf->len); } else { ath11k_dbg(ab, ATH11K_DBG_DATA, @@ -5099,7 +5099,7 @@ static void ath11k_dp_rx_mon_dest_process(struct ath11k *ar, int mac_id, if (!mon_dst_srng) { ath11k_warn(ar->ab, - "HAL Monitor Destination Ring Init Failed -- %pK", + "HAL Monitor Destination Ring Init Failed -- %p", mon_dst_srng); return; } diff --git a/drivers/net/wireless/ath/ath11k/dp_tx.c b/drivers/net/wireless/ath/ath11k/dp_tx.c index 08a28464eb7a949637bd9a65f79b5c612ebd1b89..a34833de7c6763e6606e4f4fb8d4ac486bc2c01f 100644 --- a/drivers/net/wireless/ath/ath11k/dp_tx.c +++ b/drivers/net/wireless/ath/ath11k/dp_tx.c @@ -964,14 +964,10 @@ int ath11k_dp_tx_htt_srng_setup(struct ath11k_base *ab, u32 ring_id, params.low_threshold); } - ath11k_dbg(ab, ATH11k_DBG_HAL, - "%s msi_addr_lo:0x%x, msi_addr_hi:0x%x, msi_data:0x%x\n", - __func__, cmd->ring_msi_addr_lo, cmd->ring_msi_addr_hi, - cmd->msi_data); - - ath11k_dbg(ab, ATH11k_DBG_HAL, - "ring_id:%d, ring_type:%d, intr_info:0x%x, flags:0x%x\n", - ring_id, ring_type, cmd->intr_info, cmd->info2); + ath11k_dbg(ab, ATH11K_DBG_DP_TX, + "htt srng setup msi_addr_lo 0x%x msi_addr_hi 0x%x msi_data 0x%x ring_id %d ring_type %d intr_info 0x%x flags 0x%x\n", + cmd->ring_msi_addr_lo, cmd->ring_msi_addr_hi, + cmd->msi_data, ring_id, ring_type, cmd->intr_info, cmd->info2); ret = ath11k_htc_send(&ab->htc, ab->dp.eid, skb); if (ret) diff --git a/drivers/net/wireless/ath/ath11k/hal.c b/drivers/net/wireless/ath/ath11k/hal.c index 22422237500cfd25ea444ef8cbdd38a77f00313d..0a99aa7ddbf45ad0e13bd4a81183d7c920e76d83 100644 --- a/drivers/net/wireless/ath/ath11k/hal.c +++ b/drivers/net/wireless/ath/ath11k/hal.c @@ -1009,8 +1009,8 @@ int ath11k_hal_srng_setup(struct ath11k_base *ab, enum hal_ring_type type, srng->u.src_ring.hp_addr = (u32 *)((unsigned long)ab->mem + reg_base); else - ath11k_dbg(ab, ATH11k_DBG_HAL, - "hal type %d ring_num %d reg_base 0x%x shadow 0x%lx\n", + ath11k_dbg(ab, ATH11K_DBG_HAL, + "type %d ring_num %d reg_base 0x%x shadow 0x%lx\n", type, ring_num, reg_base, (unsigned long)srng->u.src_ring.hp_addr - @@ -1043,7 +1043,7 @@ int ath11k_hal_srng_setup(struct ath11k_base *ab, enum hal_ring_type type, (u32 *)((unsigned long)ab->mem + reg_base + (HAL_REO1_RING_TP(ab) - HAL_REO1_RING_HP(ab))); else - ath11k_dbg(ab, ATH11k_DBG_HAL, + ath11k_dbg(ab, ATH11K_DBG_HAL, "type %d ring_num %d target_reg 0x%x shadow 0x%lx\n", type, ring_num, reg_base + (HAL_REO1_RING_TP(ab) - @@ -1118,8 +1118,8 @@ int ath11k_hal_srng_update_shadow_config(struct ath11k_base *ab, ath11k_hal_srng_update_hp_tp_addr(ab, shadow_cfg_idx, ring_type, ring_num); - ath11k_dbg(ab, ATH11k_DBG_HAL, - "target_reg %x, shadow reg 0x%x shadow_idx 0x%x, ring_type %d, ring num %d", + ath11k_dbg(ab, ATH11K_DBG_HAL, + "update shadow config target_reg %x shadow reg 0x%x shadow_idx 0x%x ring_type %d ring num %d", target_reg, HAL_SHADOW_REG(ab, shadow_cfg_idx), shadow_cfg_idx, diff --git a/drivers/net/wireless/ath/ath11k/hal_rx.c b/drivers/net/wireless/ath/ath11k/hal_rx.c index bb1d40034aa84ad624bebe92d18d4225c9167fbf..e5ed5efb139e114475ce419e246141c52f5f5bee 100644 --- a/drivers/net/wireless/ath/ath11k/hal_rx.c +++ b/drivers/net/wireless/ath/ath11k/hal_rx.c @@ -442,54 +442,54 @@ void ath11k_hal_reo_status_queue_stats(struct ath11k_base *ab, u32 *reo_desc, FIELD_GET(HAL_REO_STATUS_HDR_INFO0_EXEC_STATUS, desc->hdr.info0); - ath11k_dbg(ab, ATH11k_DBG_HAL, "Queue stats status:\n"); - ath11k_dbg(ab, ATH11k_DBG_HAL, "header: cmd_num %d status %d\n", + ath11k_dbg(ab, ATH11K_DBG_HAL, "Queue stats status:\n"); + ath11k_dbg(ab, ATH11K_DBG_HAL, "header: cmd_num %d status %d\n", status->uniform_hdr.cmd_num, status->uniform_hdr.cmd_status); - ath11k_dbg(ab, ATH11k_DBG_HAL, "ssn %ld cur_idx %ld\n", + ath11k_dbg(ab, ATH11K_DBG_HAL, "ssn %ld cur_idx %ld\n", FIELD_GET(HAL_REO_GET_QUEUE_STATS_STATUS_INFO0_SSN, desc->info0), FIELD_GET(HAL_REO_GET_QUEUE_STATS_STATUS_INFO0_CUR_IDX, desc->info0)); - ath11k_dbg(ab, ATH11k_DBG_HAL, "pn = [%08x, %08x, %08x, %08x]\n", + ath11k_dbg(ab, ATH11K_DBG_HAL, "pn = [%08x, %08x, %08x, %08x]\n", desc->pn[0], desc->pn[1], desc->pn[2], desc->pn[3]); - ath11k_dbg(ab, ATH11k_DBG_HAL, + ath11k_dbg(ab, ATH11K_DBG_HAL, "last_rx: enqueue_tstamp %08x dequeue_tstamp %08x\n", desc->last_rx_enqueue_timestamp, desc->last_rx_dequeue_timestamp); - ath11k_dbg(ab, ATH11k_DBG_HAL, + ath11k_dbg(ab, ATH11K_DBG_HAL, "rx_bitmap [%08x %08x %08x %08x %08x %08x %08x %08x]\n", desc->rx_bitmap[0], desc->rx_bitmap[1], desc->rx_bitmap[2], desc->rx_bitmap[3], desc->rx_bitmap[4], desc->rx_bitmap[5], desc->rx_bitmap[6], desc->rx_bitmap[7]); - ath11k_dbg(ab, ATH11k_DBG_HAL, "count: cur_mpdu %ld cur_msdu %ld\n", + ath11k_dbg(ab, ATH11K_DBG_HAL, "count: cur_mpdu %ld cur_msdu %ld\n", FIELD_GET(HAL_REO_GET_QUEUE_STATS_STATUS_INFO1_MPDU_COUNT, desc->info1), FIELD_GET(HAL_REO_GET_QUEUE_STATS_STATUS_INFO1_MSDU_COUNT, desc->info1)); - ath11k_dbg(ab, ATH11k_DBG_HAL, "fwd_timeout %ld fwd_bar %ld dup_count %ld\n", + ath11k_dbg(ab, ATH11K_DBG_HAL, "fwd_timeout %ld fwd_bar %ld dup_count %ld\n", FIELD_GET(HAL_REO_GET_QUEUE_STATS_STATUS_INFO2_TIMEOUT_COUNT, desc->info2), FIELD_GET(HAL_REO_GET_QUEUE_STATS_STATUS_INFO2_FDTB_COUNT, desc->info2), FIELD_GET(HAL_REO_GET_QUEUE_STATS_STATUS_INFO2_DUPLICATE_COUNT, desc->info2)); - ath11k_dbg(ab, ATH11k_DBG_HAL, "frames_in_order %ld bar_rcvd %ld\n", + ath11k_dbg(ab, ATH11K_DBG_HAL, "frames_in_order %ld bar_rcvd %ld\n", FIELD_GET(HAL_REO_GET_QUEUE_STATS_STATUS_INFO3_FIO_COUNT, desc->info3), FIELD_GET(HAL_REO_GET_QUEUE_STATS_STATUS_INFO3_BAR_RCVD_CNT, desc->info3)); - ath11k_dbg(ab, ATH11k_DBG_HAL, "num_mpdus %d num_msdus %d total_bytes %d\n", + ath11k_dbg(ab, ATH11K_DBG_HAL, "num_mpdus %d num_msdus %d total_bytes %d\n", desc->num_mpdu_frames, desc->num_msdu_frames, desc->total_bytes); - ath11k_dbg(ab, ATH11k_DBG_HAL, "late_rcvd %ld win_jump_2k %ld hole_cnt %ld\n", + ath11k_dbg(ab, ATH11K_DBG_HAL, "late_rcvd %ld win_jump_2k %ld hole_cnt %ld\n", FIELD_GET(HAL_REO_GET_QUEUE_STATS_STATUS_INFO4_LATE_RX_MPDU, desc->info4), FIELD_GET(HAL_REO_GET_QUEUE_STATS_STATUS_INFO4_WINDOW_JMP2K, desc->info4), FIELD_GET(HAL_REO_GET_QUEUE_STATS_STATUS_INFO4_HOLE_COUNT, desc->info4)); - ath11k_dbg(ab, ATH11k_DBG_HAL, "looping count %ld\n", + ath11k_dbg(ab, ATH11K_DBG_HAL, "looping count %ld\n", FIELD_GET(HAL_REO_GET_QUEUE_STATS_STATUS_INFO5_LOOPING_CNT, desc->info5)); } diff --git a/drivers/net/wireless/ath/ath11k/htc.c b/drivers/net/wireless/ath/ath11k/htc.c index ca3aedc0252d5ffc2993ced94f31da6f2944dd2c..2c2e425c86659556984a6c81e0a742c46f836ced 100644 --- a/drivers/net/wireless/ath/ath11k/htc.c +++ b/drivers/net/wireless/ath/ath11k/htc.c @@ -46,7 +46,6 @@ static struct sk_buff *ath11k_htc_build_tx_ctrl_skb(void *ab) skb_cb = ATH11K_SKB_CB(skb); memset(skb_cb, 0, sizeof(*skb_cb)); - ath11k_dbg(ab, ATH11K_DBG_HTC, "%s: skb %pK\n", __func__, skb); return skb; } @@ -96,7 +95,7 @@ int ath11k_htc_send(struct ath11k_htc *htc, spin_lock_bh(&htc->tx_lock); if (ep->tx_credits < credits) { ath11k_dbg(ab, ATH11K_DBG_HTC, - "htc insufficient credits ep %d required %d available %d\n", + "ep %d insufficient credits required %d total %d\n", eid, credits, ep->tx_credits); spin_unlock_bh(&htc->tx_lock); ret = -EAGAIN; @@ -104,7 +103,7 @@ int ath11k_htc_send(struct ath11k_htc *htc, } ep->tx_credits -= credits; ath11k_dbg(ab, ATH11K_DBG_HTC, - "htc ep %d consumed %d credits (total %d)\n", + "ep %d credits consumed %d total %d\n", eid, credits, ep->tx_credits); spin_unlock_bh(&htc->tx_lock); } @@ -119,6 +118,9 @@ int ath11k_htc_send(struct ath11k_htc *htc, goto err_credits; } + ath11k_dbg(ab, ATH11K_DBG_HTC, "tx skb %p eid %d paddr %pad\n", + skb, skb_cb->eid, &skb_cb->paddr); + ret = ath11k_ce_send(htc->ab, skb, ep->ul_pipe_id, ep->eid); if (ret) goto err_unmap; @@ -132,7 +134,7 @@ int ath11k_htc_send(struct ath11k_htc *htc, spin_lock_bh(&htc->tx_lock); ep->tx_credits += credits; ath11k_dbg(ab, ATH11K_DBG_HTC, - "htc ep %d reverted %d credits back (total %d)\n", + "ep %d credits reverted %d total %d\n", eid, credits, ep->tx_credits); spin_unlock_bh(&htc->tx_lock); @@ -167,7 +169,7 @@ ath11k_htc_process_credit_report(struct ath11k_htc *htc, ep = &htc->endpoint[report->eid]; ep->tx_credits += report->credits; - ath11k_dbg(ab, ATH11K_DBG_HTC, "htc ep %d got %d credits (total %d)\n", + ath11k_dbg(ab, ATH11K_DBG_HTC, "ep %d credits got %d total %d\n", report->eid, report->credits, ep->tx_credits); if (ep->ep_ops.ep_tx_credits) { @@ -239,7 +241,7 @@ static int ath11k_htc_process_trailer(struct ath11k_htc *htc, static void ath11k_htc_suspend_complete(struct ath11k_base *ab, bool ack) { - ath11k_dbg(ab, ATH11K_DBG_BOOT, "boot suspend complete %d\n", ack); + ath11k_dbg(ab, ATH11K_DBG_BOOT, "suspend complete %d\n", ack); if (ack) set_bit(ATH11K_FLAG_HTC_SUSPEND_COMPLETE, &ab->dev_flags); @@ -276,7 +278,7 @@ void ath11k_htc_tx_completion_handler(struct ath11k_base *ab, static void ath11k_htc_wakeup_from_suspend(struct ath11k_base *ab) { - ath11k_dbg(ab, ATH11K_DBG_BOOT, "boot wakeup from suspend is received\n"); + ath11k_dbg(ab, ATH11K_DBG_BOOT, "wakeup from suspend is received\n"); } void ath11k_htc_rx_completion_handler(struct ath11k_base *ab, @@ -287,7 +289,7 @@ void ath11k_htc_rx_completion_handler(struct ath11k_base *ab, struct ath11k_htc_hdr *hdr; struct ath11k_htc_ep *ep; u16 payload_len; - u32 trailer_len = 0; + u32 message_id, trailer_len = 0; size_t min_len; u8 eid; bool trailer_present; @@ -322,6 +324,9 @@ void ath11k_htc_rx_completion_handler(struct ath11k_base *ab, trailer_present = (FIELD_GET(HTC_HDR_FLAGS, hdr->htc_info)) & ATH11K_HTC_FLAG_TRAILER_PRESENT; + ath11k_dbg(ab, ATH11K_DBG_HTC, "rx ep %d skb %p trailer_present %d\n", + eid, skb, trailer_present); + if (trailer_present) { u8 *trailer; @@ -354,7 +359,12 @@ void ath11k_htc_rx_completion_handler(struct ath11k_base *ab, if (eid == ATH11K_HTC_EP_0) { struct ath11k_htc_msg *msg = (struct ath11k_htc_msg *)skb->data; - switch (FIELD_GET(HTC_MSG_MESSAGEID, msg->msg_svc_id)) { + message_id = FIELD_GET(HTC_MSG_MESSAGEID, msg->msg_svc_id); + + ath11k_dbg(ab, ATH11K_DBG_HTC, "rx ep %d skb %p message_id %d\n", + eid, skb, message_id); + + switch (message_id) { case ATH11K_HTC_MSG_READY_ID: case ATH11K_HTC_MSG_CONNECT_SERVICE_RESP_ID: /* handle HTC control message */ @@ -393,8 +403,6 @@ void ath11k_htc_rx_completion_handler(struct ath11k_base *ab, goto out; } - ath11k_dbg(ab, ATH11K_DBG_HTC, "htc rx completion ep %d skb %pK\n", - eid, skb); ep->ep_ops.ep_rx_complete(ab, skb); /* poll tx completion for interrupt disabled CE's */ @@ -564,7 +572,7 @@ int ath11k_htc_wait_target(struct ath11k_htc *htc) htc->target_credit_size = credit_size; ath11k_dbg(ab, ATH11K_DBG_HTC, - "Target ready! transmit resources: %d size:%d\n", + "target ready total_transmit_credits %d target_credit_size %d\n", htc->total_transmit_credits, htc->target_credit_size); if ((htc->total_transmit_credits == 0) || @@ -615,7 +623,7 @@ int ath11k_htc_connect_service(struct ath11k_htc *htc, conn_req->service_id); if (!tx_alloc) ath11k_dbg(ab, ATH11K_DBG_BOOT, - "boot htc service %s does not allocate target credits\n", + "htc service %s does not allocate target credits\n", htc_service_name(conn_req->service_id)); skb = ath11k_htc_build_tx_ctrl_skb(htc->ab); @@ -680,7 +688,7 @@ int ath11k_htc_connect_service(struct ath11k_htc *htc, } ath11k_dbg(ab, ATH11K_DBG_HTC, - "HTC Service %s connect response: status: 0x%lx, assigned ep: 0x%lx\n", + "service %s connect response status 0x%lx assigned ep 0x%lx\n", htc_service_name(service_id), FIELD_GET(HTC_SVC_RESP_MSG_STATUS, resp_msg->flags_len), FIELD_GET(HTC_SVC_RESP_MSG_ENDPOINTID, resp_msg->flags_len)); @@ -740,14 +748,14 @@ int ath11k_htc_connect_service(struct ath11k_htc *htc, return status; ath11k_dbg(ab, ATH11K_DBG_BOOT, - "boot htc service '%s' ul pipe %d dl pipe %d eid %d ready\n", + "htc service '%s' ul pipe %d dl pipe %d eid %d ready\n", htc_service_name(ep->service_id), ep->ul_pipe_id, ep->dl_pipe_id, ep->eid); if (disable_credit_flow_ctrl && ep->tx_credit_flow_enabled) { ep->tx_credit_flow_enabled = false; ath11k_dbg(ab, ATH11K_DBG_BOOT, - "boot htc service '%s' eid %d TX flow control disabled\n", + "htc service '%s' eid %d tx flow control disabled\n", htc_service_name(ep->service_id), assigned_eid); } @@ -773,7 +781,7 @@ int ath11k_htc_start(struct ath11k_htc *htc) ATH11K_HTC_MSG_SETUP_COMPLETE_EX_ID); if (ab->hw_params.credit_flow) - ath11k_dbg(ab, ATH11K_DBG_HTC, "HTC is using TX credit flow control\n"); + ath11k_dbg(ab, ATH11K_DBG_HTC, "using tx credit flow control\n"); else msg->flags |= ATH11K_GLOBAL_DISABLE_CREDIT_FLOW; diff --git a/drivers/net/wireless/ath/ath11k/hw.c b/drivers/net/wireless/ath/ath11k/hw.c index eb995f9cf0fa1289c5d7e73c239797a6252ec7ab..d7b5ec6e6904906cf08c87247324e207714b773a 100644 --- a/drivers/net/wireless/ath/ath11k/hw.c +++ b/drivers/net/wireless/ath/ath11k/hw.c @@ -202,6 +202,9 @@ static void ath11k_init_wmi_config_ipq8074(struct ath11k_base *ab, config->twt_ap_sta_count = 1000; config->flag1 |= WMI_RSRC_CFG_FLAG1_BSS_CHANNEL_INFO_64; config->flag1 |= WMI_RSRC_CFG_FLAG1_ACK_RSSI; + config->ema_max_vap_cnt = ab->num_radios; + config->ema_max_profile_period = TARGET_EMA_MAX_PROFILE_PERIOD; + config->beacon_tx_offload_max_vdev += config->ema_max_vap_cnt; } static int ath11k_hw_mac_id_to_pdev_id_ipq8074(struct ath11k_hw_params *hw, @@ -1175,7 +1178,7 @@ const struct ath11k_hw_ops ipq5018_ops = { .mpdu_info_get_peerid = ath11k_hw_ipq8074_mpdu_info_get_peerid, .rx_desc_mac_addr2_valid = ath11k_hw_ipq9074_rx_desc_mac_addr2_valid, .rx_desc_mpdu_start_addr2 = ath11k_hw_ipq9074_rx_desc_mpdu_start_addr2, - + .get_ring_selector = ath11k_hw_ipq8074_get_tcl_ring_selector, }; #define ATH11K_TX_RING_MASK_0 BIT(0) diff --git a/drivers/net/wireless/ath/ath11k/hw.h b/drivers/net/wireless/ath/ath11k/hw.h index 6a5dd2dbdb3abba264f519686d8b6ec63ce4a969..f5533630a7f9d3d03509b5f384ce4b8317bad651 100644 --- a/drivers/net/wireless/ath/ath11k/hw.h +++ b/drivers/net/wireless/ath/ath11k/hw.h @@ -64,6 +64,7 @@ #define TARGET_NUM_WDS_ENTRIES 32 #define TARGET_DMA_BURST_SIZE 1 #define TARGET_RX_BATCHMODE 1 +#define TARGET_EMA_MAX_PROFILE_PERIOD 8 #define ATH11K_HW_MAX_QUEUES 4 #define ATH11K_QUEUE_LEN 4096 diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c index 1c93f1afccc57b2f687c9e20de887f0b5fd22b4b..8c77ade49437fff1b94d4ef266fe775c678e8c40 100644 --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: BSD-3-Clause-Clear /* * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. - * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved. */ #include @@ -433,7 +433,7 @@ u8 ath11k_mac_bitrate_to_idx(const struct ieee80211_supported_band *sband, } static u32 -ath11k_mac_max_ht_nss(const u8 ht_mcs_mask[IEEE80211_HT_MCS_MASK_LEN]) +ath11k_mac_max_ht_nss(const u8 *ht_mcs_mask) { int nss; @@ -445,7 +445,7 @@ ath11k_mac_max_ht_nss(const u8 ht_mcs_mask[IEEE80211_HT_MCS_MASK_LEN]) } static u32 -ath11k_mac_max_vht_nss(const u16 vht_mcs_mask[NL80211_VHT_NSS_MAX]) +ath11k_mac_max_vht_nss(const u16 *vht_mcs_mask) { int nss; @@ -457,7 +457,7 @@ ath11k_mac_max_vht_nss(const u16 vht_mcs_mask[NL80211_VHT_NSS_MAX]) } static u32 -ath11k_mac_max_he_nss(const u16 he_mcs_mask[NL80211_HE_NSS_MAX]) +ath11k_mac_max_he_nss(const u16 *he_mcs_mask) { int nss; @@ -643,7 +643,10 @@ struct ath11k *ath11k_mac_get_ar_by_pdev_id(struct ath11k_base *ab, u32 pdev_id) return NULL; for (i = 0; i < ab->num_radios; i++) { - pdev = rcu_dereference(ab->pdevs_active[i]); + if (ab->fw_mode == ATH11K_FIRMWARE_MODE_FTM) + pdev = &ab->pdevs[i]; + else + pdev = rcu_dereference(ab->pdevs_active[i]); if (pdev && pdev->pdev_id == pdev_id) return (pdev->ar ? pdev->ar : NULL); @@ -815,7 +818,7 @@ static int ath11k_recalc_rtscts_prot(struct ath11k_vif *arvif) arvif->rtscts_prot_mode = rts_cts; - ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac vdev %d recalc rts/cts prot %d\n", + ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "vdev %d recalc rts/cts prot %d\n", arvif->vdev_id, rts_cts); ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, @@ -964,14 +967,14 @@ static int ath11k_mac_monitor_vdev_start(struct ath11k *ar, int vdev_id, return ret; } - ret = ath11k_wmi_vdev_up(ar, vdev_id, 0, ar->mac_addr); + ret = ath11k_wmi_vdev_up(ar, vdev_id, 0, ar->mac_addr, NULL, 0, 0); if (ret) { ath11k_warn(ar->ab, "failed to put up monitor vdev %i: %d\n", vdev_id, ret); goto vdev_stop; } - ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac monitor vdev %i started\n", + ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "monitor vdev %i started\n", vdev_id); return 0; @@ -1025,7 +1028,7 @@ static int ath11k_mac_monitor_vdev_stop(struct ath11k *ar) return ret; } - ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac monitor vdev %i stopped\n", + ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "monitor vdev %i stopped\n", ar->monitor_vdev_id); return 0; @@ -1096,7 +1099,7 @@ static int ath11k_mac_monitor_vdev_create(struct ath11k *ar) ar->num_created_vdevs++; set_bit(ATH11K_FLAG_MONITOR_VDEV_CREATED, &ar->monitor_flags); - ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac monitor vdev %d created\n", + ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "monitor vdev %d created\n", ar->monitor_vdev_id); return 0; @@ -1131,7 +1134,7 @@ static int ath11k_mac_monitor_vdev_delete(struct ath11k *ar) if (time_left == 0) { ath11k_warn(ar->ab, "Timeout in receiving vdev delete response\n"); } else { - ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac monitor vdev %d deleted\n", + ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "monitor vdev %d deleted\n", ar->monitor_vdev_id); ar->allocated_vdev_map &= ~(1LL << ar->monitor_vdev_id); @@ -1177,7 +1180,7 @@ static int ath11k_mac_monitor_start(struct ath11k *ar) return ret; } - ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac monitor started\n"); + ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "monitor started\n"); return 0; } @@ -1207,7 +1210,7 @@ static int ath11k_mac_monitor_stop(struct ath11k *ar) return ret; } - ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac monitor stopped ret %d\n", ret); + ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "monitor stopped ret %d\n", ret); return 0; } @@ -1258,7 +1261,7 @@ static int ath11k_mac_vif_setup_ps(struct ath11k_vif *arvif) psmode = WMI_STA_PS_MODE_DISABLED; } - ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac vdev %d psmode %s\n", + ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "vdev %d psmode %s\n", arvif->vdev_id, psmode ? "enable" : "disable"); ret = ath11k_wmi_pdev_set_ps_mode(ar, arvif->vdev_id, psmode); @@ -1351,28 +1354,92 @@ static int ath11k_mac_op_config(struct ieee80211_hw *hw, u32 changed) return ret; } -static int ath11k_mac_setup_bcn_tmpl(struct ath11k_vif *arvif) +static void ath11k_mac_setup_nontx_vif_rsnie(struct ath11k_vif *arvif, + bool tx_arvif_rsnie_present, + const u8 *profile, u8 profile_len) { - struct ath11k *ar = arvif->ar; - struct ath11k_base *ab = ar->ab; - struct ieee80211_hw *hw = ar->hw; - struct ieee80211_vif *vif = arvif->vif; - struct ieee80211_mutable_offsets offs = {}; - struct sk_buff *bcn; - struct ieee80211_mgmt *mgmt; - u8 *ies; - int ret; + if (cfg80211_find_ie(WLAN_EID_RSN, profile, profile_len)) { + arvif->rsnie_present = true; + } else if (tx_arvif_rsnie_present) { + int i; + u8 nie_len; + const u8 *nie = cfg80211_find_ext_ie(WLAN_EID_EXT_NON_INHERITANCE, + profile, profile_len); + if (!nie) + return; - if (arvif->vdev_type != WMI_VDEV_TYPE_AP) - return 0; + nie_len = nie[1]; + nie += 2; + for (i = 0; i < nie_len; i++) { + if (nie[i] == WLAN_EID_RSN) { + arvif->rsnie_present = false; + break; + } + } + } +} - bcn = ieee80211_beacon_get_template(hw, vif, &offs, 0); - if (!bcn) { - ath11k_warn(ab, "failed to get beacon template from mac80211\n"); - return -EPERM; +static bool ath11k_mac_set_nontx_vif_params(struct ath11k_vif *tx_arvif, + struct ath11k_vif *arvif, + struct sk_buff *bcn) +{ + struct ieee80211_mgmt *mgmt; + const u8 *ies, *profile, *next_profile; + int ies_len; + + ies = bcn->data + ieee80211_get_hdrlen_from_skb(bcn); + mgmt = (struct ieee80211_mgmt *)bcn->data; + ies += sizeof(mgmt->u.beacon); + ies_len = skb_tail_pointer(bcn) - ies; + + ies = cfg80211_find_ie(WLAN_EID_MULTIPLE_BSSID, ies, ies_len); + arvif->rsnie_present = tx_arvif->rsnie_present; + + while (ies) { + u8 mbssid_len; + + ies_len -= (2 + ies[1]); + mbssid_len = ies[1] - 1; + profile = &ies[3]; + + while (mbssid_len) { + u8 profile_len; + + profile_len = profile[1]; + next_profile = profile + (2 + profile_len); + mbssid_len -= (2 + profile_len); + + profile += 2; + profile_len -= (2 + profile[1]); + profile += (2 + profile[1]); /* nontx capabilities */ + profile_len -= (2 + profile[1]); + profile += (2 + profile[1]); /* SSID */ + if (profile[2] == arvif->vif->bss_conf.bssid_index) { + profile_len -= 5; + profile = profile + 5; + ath11k_mac_setup_nontx_vif_rsnie(arvif, + tx_arvif->rsnie_present, + profile, + profile_len); + return true; + } + profile = next_profile; + } + ies = cfg80211_find_ie(WLAN_EID_MULTIPLE_BSSID, profile, + ies_len); } + return false; +} + +static void ath11k_mac_set_vif_params(struct ath11k_vif *arvif, + struct sk_buff *bcn) +{ + struct ieee80211_mgmt *mgmt; + u8 *ies; + ies = bcn->data + ieee80211_get_hdrlen_from_skb(bcn); + mgmt = (struct ieee80211_mgmt *)bcn->data; ies += sizeof(mgmt->u.beacon); if (cfg80211_find_ie(WLAN_EID_RSN, ies, (skb_tail_pointer(bcn) - ies))) @@ -1386,9 +1453,95 @@ static int ath11k_mac_setup_bcn_tmpl(struct ath11k_vif *arvif) arvif->wpaie_present = true; else arvif->wpaie_present = false; +} + +static int ath11k_mac_setup_bcn_tmpl_ema(struct ath11k_vif *arvif) +{ + struct ath11k_vif *tx_arvif; + struct ieee80211_ema_beacons *beacons; + int ret = 0; + bool nontx_vif_params_set = false; + u32 params = 0; + u8 i = 0; + + tx_arvif = (void *)arvif->vif->mbssid_tx_vif->drv_priv; - ret = ath11k_wmi_bcn_tmpl(ar, arvif->vdev_id, &offs, bcn); + beacons = ieee80211_beacon_get_template_ema_list(tx_arvif->ar->hw, + tx_arvif->vif, 0); + if (!beacons || !beacons->cnt) { + ath11k_warn(arvif->ar->ab, + "failed to get ema beacon templates from mac80211\n"); + return -EPERM; + } + if (tx_arvif == arvif) + ath11k_mac_set_vif_params(tx_arvif, beacons->bcn[0].skb); + else + arvif->wpaie_present = tx_arvif->wpaie_present; + + for (i = 0; i < beacons->cnt; i++) { + if (tx_arvif != arvif && !nontx_vif_params_set) + nontx_vif_params_set = + ath11k_mac_set_nontx_vif_params(tx_arvif, arvif, + beacons->bcn[i].skb); + + params = beacons->cnt; + params |= (i << WMI_EMA_TMPL_IDX_SHIFT); + params |= ((!i ? 1 : 0) << WMI_EMA_FIRST_TMPL_SHIFT); + params |= ((i + 1 == beacons->cnt ? 1 : 0) << WMI_EMA_LAST_TMPL_SHIFT); + + ret = ath11k_wmi_bcn_tmpl(tx_arvif->ar, tx_arvif->vdev_id, + &beacons->bcn[i].offs, + beacons->bcn[i].skb, params); + if (ret) { + ath11k_warn(tx_arvif->ar->ab, + "failed to set ema beacon template id %i error %d\n", + i, ret); + break; + } + } + + ieee80211_beacon_free_ema_list(beacons); + + if (tx_arvif != arvif && !nontx_vif_params_set) + return -EINVAL; /* Profile not found in the beacons */ + + return ret; +} + +static int ath11k_mac_setup_bcn_tmpl_mbssid(struct ath11k_vif *arvif) +{ + struct ath11k *ar = arvif->ar; + struct ath11k_base *ab = ar->ab; + struct ath11k_vif *tx_arvif = arvif; + struct ieee80211_hw *hw = ar->hw; + struct ieee80211_vif *vif = arvif->vif; + struct ieee80211_mutable_offsets offs = {}; + struct sk_buff *bcn; + int ret; + + if (arvif->vif->mbssid_tx_vif) { + tx_arvif = (void *)arvif->vif->mbssid_tx_vif->drv_priv; + if (tx_arvif != arvif) { + ar = tx_arvif->ar; + ab = ar->ab; + hw = ar->hw; + vif = tx_arvif->vif; + } + } + + bcn = ieee80211_beacon_get_template(hw, vif, &offs, 0); + if (!bcn) { + ath11k_warn(ab, "failed to get beacon template from mac80211\n"); + return -EPERM; + } + + if (tx_arvif == arvif) + ath11k_mac_set_vif_params(tx_arvif, bcn); + else if (!ath11k_mac_set_nontx_vif_params(tx_arvif, arvif, bcn)) + return -EINVAL; + + ret = ath11k_wmi_bcn_tmpl(ar, arvif->vdev_id, &offs, bcn, 0); kfree_skb(bcn); if (ret) @@ -1398,6 +1551,26 @@ static int ath11k_mac_setup_bcn_tmpl(struct ath11k_vif *arvif) return ret; } +static int ath11k_mac_setup_bcn_tmpl(struct ath11k_vif *arvif) +{ + struct ieee80211_vif *vif = arvif->vif; + + if (arvif->vdev_type != WMI_VDEV_TYPE_AP) + return 0; + + /* Target does not expect beacon templates for the already up + * non-transmitting interfaces, and results in a crash if sent. + */ + if (vif->mbssid_tx_vif && + arvif != (void *)vif->mbssid_tx_vif->drv_priv && arvif->is_up) + return 0; + + if (vif->bss_conf.ema_ap && vif->mbssid_tx_vif) + return ath11k_mac_setup_bcn_tmpl_ema(arvif); + + return ath11k_mac_setup_bcn_tmpl_mbssid(arvif); +} + void ath11k_mac_bcn_tx_event(struct ath11k_vif *arvif) { struct ieee80211_vif *vif = arvif->vif; @@ -1423,6 +1596,7 @@ static void ath11k_control_beaconing(struct ath11k_vif *arvif, struct ieee80211_bss_conf *info) { struct ath11k *ar = arvif->ar; + struct ath11k_vif *tx_arvif = NULL; int ret = 0; lockdep_assert_held(&arvif->ar->conf_mutex); @@ -1451,8 +1625,14 @@ static void ath11k_control_beaconing(struct ath11k_vif *arvif, ether_addr_copy(arvif->bssid, info->bssid); + if (arvif->vif->mbssid_tx_vif) + tx_arvif = (struct ath11k_vif *)arvif->vif->mbssid_tx_vif->drv_priv; + ret = ath11k_wmi_vdev_up(arvif->ar, arvif->vdev_id, arvif->aid, - arvif->bssid); + arvif->bssid, + tx_arvif ? tx_arvif->bssid : NULL, + info->bssid_index, + 1 << info->bssid_indicator); if (ret) { ath11k_warn(ar->ab, "failed to bring up vdev %d: %i\n", arvif->vdev_id, ret); @@ -1461,7 +1641,7 @@ static void ath11k_control_beaconing(struct ath11k_vif *arvif, arvif->is_up = true; - ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac vdev %d up\n", arvif->vdev_id); + ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "vdev %d up\n", arvif->vdev_id); } static void ath11k_mac_handle_beacon_iter(void *data, u8 *mac, @@ -1658,7 +1838,7 @@ static void ath11k_peer_assoc_h_rates(struct ath11k *ar, } static bool -ath11k_peer_assoc_h_ht_masked(const u8 ht_mcs_mask[IEEE80211_HT_MCS_MASK_LEN]) +ath11k_peer_assoc_h_ht_masked(const u8 *ht_mcs_mask) { int nss; @@ -1670,7 +1850,7 @@ ath11k_peer_assoc_h_ht_masked(const u8 ht_mcs_mask[IEEE80211_HT_MCS_MASK_LEN]) } static bool -ath11k_peer_assoc_h_vht_masked(const u16 vht_mcs_mask[]) +ath11k_peer_assoc_h_vht_masked(const u16 *vht_mcs_mask) { int nss; @@ -1784,7 +1964,7 @@ static void ath11k_peer_assoc_h_ht(struct ath11k *ar, arg->peer_nss = min(sta->deflink.rx_nss, max_nss); } - ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac ht peer %pM mcs cnt %d nss %d\n", + ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "ht peer %pM mcs cnt %d nss %d\n", arg->peer_mac, arg->peer_ht_rates.num_rates, arg->peer_nss); @@ -1948,7 +2128,7 @@ static void ath11k_peer_assoc_h_vht(struct ath11k *ar, } if (!user_rate_valid) { - ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac setting vht range mcs value to peer supported nss %d for peer %pM\n", + ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "setting vht range mcs value to peer supported nss %d for peer %pM\n", sta->deflink.rx_nss, sta->addr); vht_mcs_mask[sta->deflink.rx_nss - 1] = vht_mcs_mask[vht_nss - 1]; } @@ -2005,7 +2185,7 @@ static void ath11k_peer_assoc_h_vht(struct ath11k *ar, } ath11k_dbg(ar->ab, ATH11K_DBG_MAC, - "mac vht peer %pM max_mpdu %d flags 0x%x nss_override 0x%x\n", + "vht peer %pM max_mpdu %d flags 0x%x nss_override 0x%x\n", sta->addr, arg->peer_max_mpdu, arg->peer_flags, arg->peer_bw_rxnss_override); } @@ -2065,7 +2245,7 @@ static u16 ath11k_peer_assoc_h_he_limit(u16 tx_mcs_set, } static bool -ath11k_peer_assoc_h_he_masked(const u16 he_mcs_mask[NL80211_HE_NSS_MAX]) +ath11k_peer_assoc_h_he_masked(const u16 *he_mcs_mask) { int nss; @@ -2230,7 +2410,7 @@ static void ath11k_peer_assoc_h_he(struct ath11k *ar, } if (!user_rate_valid) { - ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac setting he range mcs value to peer supported nss %d for peer %pM\n", + ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "setting he range mcs value to peer supported nss %d for peer %pM\n", sta->deflink.rx_nss, sta->addr); he_mcs_mask[sta->deflink.rx_nss - 1] = he_mcs_mask[he_nss - 1]; } @@ -2311,7 +2491,7 @@ static void ath11k_peer_assoc_h_he(struct ath11k *ar, } ath11k_dbg(ar->ab, ATH11K_DBG_MAC, - "mac he peer %pM nss %d mcs cnt %d nss_override 0x%x\n", + "he peer %pM nss %d mcs cnt %d nss_override 0x%x\n", sta->addr, arg->peer_nss, arg->peer_he_mcs_count, arg->peer_bw_rxnss_override); @@ -2431,7 +2611,7 @@ static void ath11k_peer_assoc_h_qos(struct ath11k *ar, break; } - ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac peer %pM qos %d\n", + ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "peer %pM qos %d\n", sta->addr, arg->qos_flag); } @@ -2448,7 +2628,7 @@ static int ath11k_peer_assoc_qos_ap(struct ath11k *ar, params.vdev_id = arvif->vdev_id; - ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac uapsd_queues 0x%x max_sp %d\n", + ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "uapsd_queues 0x%x max_sp %d\n", sta->uapsd_queues, sta->max_sp); uapsd = 0; @@ -2634,7 +2814,7 @@ static void ath11k_peer_assoc_h_phymode(struct ath11k *ar, break; } - ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac peer %pM phymode %s\n", + ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "peer %pM phymode %s\n", sta->addr, ath11k_wmi_phymode_str(phymode)); arg->peer_phymode = phymode; @@ -2825,7 +3005,7 @@ static void ath11k_bss_assoc(struct ieee80211_hw *hw, lockdep_assert_held(&ar->conf_mutex); - ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac vdev %i assoc bssid %pM aid %d\n", + ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "vdev %i assoc bssid %pM aid %d\n", arvif->vdev_id, arvif->bssid, arvif->aid); rcu_read_lock(); @@ -2879,7 +3059,8 @@ static void ath11k_bss_assoc(struct ieee80211_hw *hw, arvif->aid = vif->cfg.aid; ether_addr_copy(arvif->bssid, bss_conf->bssid); - ret = ath11k_wmi_vdev_up(ar, arvif->vdev_id, arvif->aid, arvif->bssid); + ret = ath11k_wmi_vdev_up(ar, arvif->vdev_id, arvif->aid, arvif->bssid, + NULL, 0, 0); if (ret) { ath11k_warn(ar->ab, "failed to set vdev %d up: %d\n", arvif->vdev_id, ret); @@ -2890,7 +3071,7 @@ static void ath11k_bss_assoc(struct ieee80211_hw *hw, arvif->rekey_data.enable_offload = false; ath11k_dbg(ar->ab, ATH11K_DBG_MAC, - "mac vdev %d up (associated) bssid %pM aid %d\n", + "vdev %d up (associated) bssid %pM aid %d\n", arvif->vdev_id, bss_conf->bssid, vif->cfg.aid); spin_lock_bh(&ar->ab->base_lock); @@ -2935,7 +3116,7 @@ static void ath11k_bss_disassoc(struct ieee80211_hw *hw, lockdep_assert_held(&ar->conf_mutex); - ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac vdev %i disassoc bssid %pM\n", + ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "vdev %i disassoc bssid %pM\n", arvif->vdev_id, arvif->bssid); ret = ath11k_wmi_vdev_down(ar, arvif->vdev_id); @@ -3084,7 +3265,7 @@ static int ath11k_mac_config_obss_pd(struct ath11k *ar, } ath11k_dbg(ar->ab, ATH11K_DBG_MAC, - "mac obss pd sr_ctrl %x non_srg_thres %u srg_max %u\n", + "obss pd sr_ctrl %x non_srg_thres %u srg_max %u\n", he_obss_pd->sr_ctrl, he_obss_pd->non_srg_max_offset, he_obss_pd->max_offset); @@ -3412,7 +3593,7 @@ static void ath11k_mac_op_bss_info_changed(struct ieee80211_hw *hw, } if (changed & BSS_CHANGED_TXPOWER) { - ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac vdev_id %i txpower %d\n", + ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "vdev_id %i txpower %d\n", arvif->vdev_id, info->txpower); arvif->txpower = info->txpower; @@ -3453,7 +3634,7 @@ static void ath11k_mac_op_bss_info_changed(struct ieee80211_hw *hw, rate = ATH11K_HW_RATE_CODE(hw_value, 0, preamble); ath11k_dbg(ar->ab, ATH11K_DBG_MAC, - "mac vdev %d mcast_rate %x\n", + "vdev %d mcast_rate %x\n", arvif->vdev_id, rate); vdev_param = WMI_VDEV_PARAM_MCAST_DATA_RATE; @@ -3562,7 +3743,7 @@ static void ath11k_mac_op_bss_info_changed(struct ieee80211_hw *hw, memcpy(arvif->arp_ns_offload.mac_addr, vif->addr, ETH_ALEN); arvif->arp_ns_offload.ipv4_count = ipv4_cnt; - ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac arp_addr_cnt %d vif->addr %pM, offload_addr %pI4\n", + ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "arp_addr_cnt %d vif->addr %pM, offload_addr %pI4\n", vif->cfg.arp_addr_cnt, vif->addr, arvif->arp_ns_offload.ipv4_addr); } @@ -4159,6 +4340,20 @@ static int ath11k_mac_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, return ret; } +static int +ath11k_mac_bitrate_mask_num_ht_rates(struct ath11k *ar, + enum nl80211_band band, + const struct cfg80211_bitrate_mask *mask) +{ + int num_rates = 0; + int i; + + for (i = 0; i < ARRAY_SIZE(mask->control[band].ht_mcs); i++) + num_rates += hweight8(mask->control[band].ht_mcs[i]); + + return num_rates; +} + static int ath11k_mac_bitrate_mask_num_vht_rates(struct ath11k *ar, enum nl80211_band band, @@ -4270,7 +4465,7 @@ ath11k_mac_set_peer_he_fixed_rate(struct ath11k_vif *arvif, return -EINVAL; ath11k_dbg(ar->ab, ATH11K_DBG_MAC, - "mac setting fixed he rate for peer %pM, device will not switch to any other selected rates", + "setting fixed he rate for peer %pM, device will not switch to any other selected rates", sta->addr); rate_code = ATH11K_HW_RATE_CODE(he_rate, nss - 1, @@ -4288,6 +4483,54 @@ ath11k_mac_set_peer_he_fixed_rate(struct ath11k_vif *arvif, return ret; } +static int +ath11k_mac_set_peer_ht_fixed_rate(struct ath11k_vif *arvif, + struct ieee80211_sta *sta, + const struct cfg80211_bitrate_mask *mask, + enum nl80211_band band) +{ + struct ath11k *ar = arvif->ar; + u8 ht_rate, nss = 0; + u32 rate_code; + int ret, i; + + lockdep_assert_held(&ar->conf_mutex); + + for (i = 0; i < ARRAY_SIZE(mask->control[band].ht_mcs); i++) { + if (hweight8(mask->control[band].ht_mcs[i]) == 1) { + nss = i + 1; + ht_rate = ffs(mask->control[band].ht_mcs[i]) - 1; + } + } + + if (!nss) { + ath11k_warn(ar->ab, "No single HT Fixed rate found to set for %pM", + sta->addr); + return -EINVAL; + } + + /* Avoid updating invalid nss as fixed rate*/ + if (nss > sta->deflink.rx_nss) + return -EINVAL; + + ath11k_dbg(ar->ab, ATH11K_DBG_MAC, + "Setting Fixed HT Rate for peer %pM. Device will not switch to any other selected rates", + sta->addr); + + rate_code = ATH11K_HW_RATE_CODE(ht_rate, nss - 1, + WMI_RATE_PREAMBLE_HT); + ret = ath11k_wmi_set_peer_param(ar, sta->addr, + arvif->vdev_id, + WMI_PEER_PARAM_FIXED_RATE, + rate_code); + if (ret) + ath11k_warn(ar->ab, + "failed to update STA %pM HT Fixed Rate %d: %d\n", + sta->addr, rate_code, ret); + + return ret; +} + static int ath11k_station_assoc(struct ath11k *ar, struct ieee80211_vif *vif, struct ieee80211_sta *sta, @@ -4299,7 +4542,7 @@ static int ath11k_station_assoc(struct ath11k *ar, struct cfg80211_chan_def def; enum nl80211_band band; struct cfg80211_bitrate_mask *mask; - u8 num_vht_rates, num_he_rates; + u8 num_ht_rates, num_vht_rates, num_he_rates; lockdep_assert_held(&ar->conf_mutex); @@ -4327,6 +4570,7 @@ static int ath11k_station_assoc(struct ath11k *ar, num_vht_rates = ath11k_mac_bitrate_mask_num_vht_rates(ar, band, mask); num_he_rates = ath11k_mac_bitrate_mask_num_he_rates(ar, band, mask); + num_ht_rates = ath11k_mac_bitrate_mask_num_ht_rates(ar, band, mask); /* If single VHT/HE rate is configured (by set_bitrate_mask()), * peer_assoc will disable VHT/HE. This is now enabled by a peer specific @@ -4343,6 +4587,11 @@ static int ath11k_station_assoc(struct ath11k *ar, band); if (ret) return ret; + } else if (sta->deflink.ht_cap.ht_supported && num_ht_rates == 1) { + ret = ath11k_mac_set_peer_ht_fixed_rate(arvif, sta, mask, + band); + if (ret) + return ret; } /* Re-assoc is run only to update supported rates for given station. It @@ -4416,7 +4665,7 @@ static void ath11k_sta_rc_update_wk(struct work_struct *wk) const u16 *vht_mcs_mask; const u16 *he_mcs_mask; u32 changed, bw, nss, smps, bw_prev; - int err, num_vht_rates, num_he_rates; + int err, num_ht_rates, num_vht_rates, num_he_rates; const struct cfg80211_bitrate_mask *mask; struct peer_assoc_params peer_arg; enum wmi_phy_mode peer_phymode; @@ -4458,14 +4707,14 @@ static void ath11k_sta_rc_update_wk(struct work_struct *wk) ath11k_peer_assoc_h_phymode(ar, arvif->vif, sta, &peer_arg); peer_phymode = peer_arg.peer_phymode; - ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac update sta %pM peer bw %d phymode %d\n", + ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "update sta %pM peer bw %d phymode %d\n", sta->addr, bw, peer_phymode); if (bw > bw_prev) { /* BW is upgraded. In this case we send WMI_PEER_PHYMODE * followed by WMI_PEER_CHWIDTH */ - ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac BW upgrade for sta %pM new BW %d, old BW %d\n", + ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "BW upgrade for sta %pM new BW %d, old BW %d\n", sta->addr, bw, bw_prev); err = ath11k_wmi_set_peer_param(ar, sta->addr, arvif->vdev_id, @@ -4487,7 +4736,7 @@ static void ath11k_sta_rc_update_wk(struct work_struct *wk) /* BW is downgraded. In this case we send WMI_PEER_CHWIDTH * followed by WMI_PEER_PHYMODE */ - ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac BW downgrade for sta %pM new BW %d,old BW %d\n", + ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "BW downgrade for sta %pM new BW %d,old BW %d\n", sta->addr, bw, bw_prev); err = ath11k_wmi_set_peer_param(ar, sta->addr, arvif->vdev_id, @@ -4509,7 +4758,7 @@ static void ath11k_sta_rc_update_wk(struct work_struct *wk) } if (changed & IEEE80211_RC_NSS_CHANGED) { - ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac update sta %pM nss %d\n", + ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "update sta %pM nss %d\n", sta->addr, nss); err = ath11k_wmi_set_peer_param(ar, sta->addr, arvif->vdev_id, @@ -4520,7 +4769,7 @@ static void ath11k_sta_rc_update_wk(struct work_struct *wk) } if (changed & IEEE80211_RC_SMPS_CHANGED) { - ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac update sta %pM smps %d\n", + ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "update sta %pM smps %d\n", sta->addr, smps); err = ath11k_wmi_set_peer_param(ar, sta->addr, arvif->vdev_id, @@ -4532,6 +4781,8 @@ static void ath11k_sta_rc_update_wk(struct work_struct *wk) if (changed & IEEE80211_RC_SUPP_RATES_CHANGED) { mask = &arvif->bitrate_mask; + num_ht_rates = ath11k_mac_bitrate_mask_num_ht_rates(ar, band, + mask); num_vht_rates = ath11k_mac_bitrate_mask_num_vht_rates(ar, band, mask); num_he_rates = ath11k_mac_bitrate_mask_num_he_rates(ar, band, @@ -4554,6 +4805,9 @@ static void ath11k_sta_rc_update_wk(struct work_struct *wk) } else if (sta->deflink.he_cap.has_he && num_he_rates == 1) { ath11k_mac_set_peer_he_fixed_rate(arvif, sta, mask, band); + } else if (sta->deflink.ht_cap.ht_supported && num_ht_rates == 1) { + ath11k_mac_set_peer_ht_fixed_rate(arvif, sta, mask, + band); } else { /* If the peer is non-VHT/HE or no fixed VHT/HE rate * is provided in the new bitrate mask we set the @@ -4973,7 +5227,7 @@ static void ath11k_mac_op_sta_rc_update(struct ieee80211_hw *hw, spin_unlock_bh(&ar->ab->base_lock); ath11k_dbg(ar->ab, ATH11K_DBG_MAC, - "mac sta rc update for %pM changed %08x bw %d nss %d smps %d\n", + "sta rc update for %pM changed %08x bw %d nss %d smps %d\n", sta->addr, changed, sta->deflink.bandwidth, sta->deflink.rx_nss, sta->deflink.smps_mode); @@ -5784,7 +6038,7 @@ static int ath11k_mac_mgmt_tx_wmi(struct ath11k *ar, struct ath11k_vif *arvif, spin_unlock_bh(&ar->txmgmt_idr_lock); ath11k_dbg(ar->ab, ATH11K_DBG_MAC, - "mac tx mgmt frame, buf id %d\n", buf_id); + "tx mgmt frame, buf id %d\n", buf_id); if (buf_id < 0) return -ENOSPC; @@ -5861,7 +6115,7 @@ static void ath11k_mgmt_over_wmi_tx_work(struct work_struct *work) ath11k_mgmt_over_wmi_tx_drop(ar, skb); } else { ath11k_dbg(ar->ab, ATH11K_DBG_MAC, - "mac tx mgmt frame, vdev_id %d\n", + "tx mgmt frame, vdev_id %d\n", arvif->vdev_id); } } else { @@ -6020,6 +6274,11 @@ static int ath11k_mac_op_start(struct ieee80211_hw *hw) struct ath11k_pdev *pdev = ar->pdev; int ret; + if (ath11k_ftm_mode) { + ath11k_warn(ab, "mac operations not supported in factory test mode\n"); + return -EOPNOTSUPP; + } + ath11k_mac_drain_tx(ar); mutex_lock(&ar->conf_mutex); @@ -6034,6 +6293,7 @@ static int ath11k_mac_op_start(struct ieee80211_hw *hw) case ATH11K_STATE_RESTARTED: case ATH11K_STATE_WEDGED: case ATH11K_STATE_ON: + case ATH11K_STATE_FTM: WARN_ON(1); ret = -EINVAL; goto err; @@ -6181,17 +6441,62 @@ static void ath11k_mac_op_stop(struct ieee80211_hw *hw) atomic_set(&ar->num_pending_mgmt_tx, 0); } -static void -ath11k_mac_setup_vdev_create_params(struct ath11k_vif *arvif, - struct vdev_create_params *params) +static int ath11k_mac_setup_vdev_params_mbssid(struct ath11k_vif *arvif, + u32 *flags, u32 *tx_vdev_id) +{ + struct ath11k *ar = arvif->ar; + struct ath11k_vif *tx_arvif; + struct ieee80211_vif *tx_vif; + + *tx_vdev_id = 0; + tx_vif = arvif->vif->mbssid_tx_vif; + if (!tx_vif) { + *flags = WMI_HOST_VDEV_FLAGS_NON_MBSSID_AP; + return 0; + } + + tx_arvif = (void *)tx_vif->drv_priv; + + if (arvif->vif->bss_conf.nontransmitted) { + if (ar->hw->wiphy != ieee80211_vif_to_wdev(tx_vif)->wiphy) + return -EINVAL; + + *flags = WMI_HOST_VDEV_FLAGS_NON_TRANSMIT_AP; + *tx_vdev_id = ath11k_vif_to_arvif(tx_vif)->vdev_id; + } else if (tx_arvif == arvif) { + *flags = WMI_HOST_VDEV_FLAGS_TRANSMIT_AP; + } else { + return -EINVAL; + } + + if (arvif->vif->bss_conf.ema_ap) + *flags |= WMI_HOST_VDEV_FLAGS_EMA_MODE; + + return 0; +} + +static int ath11k_mac_setup_vdev_create_params(struct ath11k_vif *arvif, + struct vdev_create_params *params) { struct ath11k *ar = arvif->ar; struct ath11k_pdev *pdev = ar->pdev; + int ret; params->if_id = arvif->vdev_id; params->type = arvif->vdev_type; params->subtype = arvif->vdev_subtype; params->pdev_id = pdev->pdev_id; + params->mbssid_flags = 0; + params->mbssid_tx_vdev_id = 0; + + if (!test_bit(WMI_TLV_SERVICE_MBSS_PARAM_IN_VDEV_START_SUPPORT, + ar->ab->wmi_ab.svc_map)) { + ret = ath11k_mac_setup_vdev_params_mbssid(arvif, + ¶ms->mbssid_flags, + ¶ms->mbssid_tx_vdev_id); + if (ret) + return ret; + } if (pdev->cap.supported_bands & WMI_HOST_WLAN_2G_CAP) { params->chains[NL80211_BAND_2GHZ].tx = ar->num_tx_chains; @@ -6206,6 +6511,7 @@ ath11k_mac_setup_vdev_create_params(struct ath11k_vif *arvif, params->chains[NL80211_BAND_6GHZ].tx = ar->num_tx_chains; params->chains[NL80211_BAND_6GHZ].rx = ar->num_rx_chains; } + return 0; } static void ath11k_mac_op_update_vif_offload(struct ieee80211_hw *hw, @@ -6281,7 +6587,7 @@ void ath11k_mac_11d_scan_start(struct ath11k *ar, u32 vdev_id) mutex_lock(&ar->ab->vdev_id_11d_lock); - ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac vdev id for 11d scan %d\n", + ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "vdev id for 11d scan %d\n", ar->vdev_id_11d_scan); if (ar->regdom_set_by_user) @@ -6300,7 +6606,7 @@ void ath11k_mac_11d_scan_start(struct ath11k *ar, u32 vdev_id) param.start_interval_msec = 0; param.scan_period_msec = ATH11K_SCAN_11D_INTERVAL; - ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac start 11d scan\n"); + ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "start 11d scan\n"); ret = ath11k_wmi_send_11d_scan_start_cmd(ar, ¶m); if (ret) { @@ -6329,11 +6635,11 @@ void ath11k_mac_11d_scan_stop(struct ath11k *ar) if (!test_bit(WMI_TLV_SERVICE_11D_OFFLOAD, ar->ab->wmi_ab.svc_map)) return; - ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac stop 11d scan\n"); + ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "stop 11d scan\n"); mutex_lock(&ar->ab->vdev_id_11d_lock); - ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac stop 11d vdev id %d\n", + ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "stop 11d vdev id %d\n", ar->vdev_id_11d_scan); if (ar->state_11d == ATH11K_11D_PREPARING) { @@ -6364,7 +6670,7 @@ void ath11k_mac_11d_scan_stop_all(struct ath11k_base *ab) struct ath11k_pdev *pdev; int i; - ath11k_dbg(ab, ATH11K_DBG_MAC, "mac stop soc 11d scan\n"); + ath11k_dbg(ab, ATH11K_DBG_MAC, "stop soc 11d scan\n"); for (i = 0; i < ab->num_radios; i++) { pdev = &ab->pdevs[i]; @@ -6492,7 +6798,7 @@ static int ath11k_mac_op_add_interface(struct ieee80211_hw *hw, break; } - ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac add interface id %d type %d subtype %d map %llx\n", + ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "add interface id %d type %d subtype %d map %llx\n", arvif->vdev_id, arvif->vdev_type, arvif->vdev_subtype, ab->free_vdev_map); @@ -6500,7 +6806,12 @@ static int ath11k_mac_op_add_interface(struct ieee80211_hw *hw, for (i = 0; i < ARRAY_SIZE(vif->hw_queue); i++) vif->hw_queue[i] = i % (ATH11K_HW_MAX_QUEUES - 1); - ath11k_mac_setup_vdev_create_params(arvif, &vdev_param); + ret = ath11k_mac_setup_vdev_create_params(arvif, &vdev_param); + if (ret) { + ath11k_warn(ab, "failed to create vdev parameters %d: %d\n", + arvif->vdev_id, ret); + goto err; + } ret = ath11k_wmi_vdev_create(ar, vif->addr, &vdev_param); if (ret) { @@ -6678,7 +6989,7 @@ static void ath11k_mac_op_remove_interface(struct ieee80211_hw *hw, mutex_lock(&ar->conf_mutex); - ath11k_dbg(ab, ATH11K_DBG_MAC, "mac remove interface (vdev %d)\n", + ath11k_dbg(ab, ATH11K_DBG_MAC, "remove interface (vdev %d)\n", arvif->vdev_id); ret = ath11k_spectral_vif_stop(arvif); @@ -6833,7 +7144,7 @@ static int ath11k_mac_op_add_chanctx(struct ieee80211_hw *hw, struct ath11k_base *ab = ar->ab; ath11k_dbg(ab, ATH11K_DBG_MAC, - "mac chanctx add freq %u width %d ptr %pK\n", + "chanctx add freq %u width %d ptr %p\n", ctx->def.chan->center_freq, ctx->def.width, ctx); mutex_lock(&ar->conf_mutex); @@ -6857,7 +7168,7 @@ static void ath11k_mac_op_remove_chanctx(struct ieee80211_hw *hw, struct ath11k_base *ab = ar->ab; ath11k_dbg(ab, ATH11K_DBG_MAC, - "mac chanctx remove freq %u width %d ptr %pK\n", + "chanctx remove freq %u width %d ptr %p\n", ctx->def.chan->center_freq, ctx->def.width, ctx); mutex_lock(&ar->conf_mutex); @@ -6905,6 +7216,17 @@ ath11k_mac_vdev_start_restart(struct ath11k_vif *arvif, arg.pref_tx_streams = ar->num_tx_chains; arg.pref_rx_streams = ar->num_rx_chains; + arg.mbssid_flags = 0; + arg.mbssid_tx_vdev_id = 0; + if (test_bit(WMI_TLV_SERVICE_MBSS_PARAM_IN_VDEV_START_SUPPORT, + ar->ab->wmi_ab.svc_map)) { + ret = ath11k_mac_setup_vdev_params_mbssid(arvif, + &arg.mbssid_flags, + &arg.mbssid_tx_vdev_id); + if (ret) + return ret; + } + if (arvif->vdev_type == WMI_VDEV_TYPE_AP) { arg.ssid = arvif->u.ap.ssid; arg.ssid_len = arvif->u.ap.ssid_len; @@ -6926,7 +7248,7 @@ ath11k_mac_vdev_start_restart(struct ath11k_vif *arvif, arg.channel.passive |= !!(chandef->chan->flags & IEEE80211_CHAN_NO_IR); ath11k_dbg(ab, ATH11K_DBG_MAC, - "mac vdev %d start center_freq %d phymode %s\n", + "vdev %d start center_freq %d phymode %s\n", arg.vdev_id, arg.channel.freq, ath11k_wmi_phymode_str(arg.channel.mode)); @@ -7071,7 +7393,8 @@ ath11k_mac_update_vif_chan(struct ath11k *ar, int n_vifs) { struct ath11k_base *ab = ar->ab; - struct ath11k_vif *arvif; + struct ath11k_vif *arvif, *tx_arvif = NULL; + struct ieee80211_vif *mbssid_tx_vif; int ret; int i; bool monitor_vif = false; @@ -7125,8 +7448,15 @@ ath11k_mac_update_vif_chan(struct ath11k *ar, ath11k_warn(ab, "failed to update bcn tmpl during csa: %d\n", ret); + mbssid_tx_vif = arvif->vif->mbssid_tx_vif; + if (mbssid_tx_vif) + tx_arvif = (struct ath11k_vif *)mbssid_tx_vif->drv_priv; + ret = ath11k_wmi_vdev_up(arvif->ar, arvif->vdev_id, arvif->aid, - arvif->bssid); + arvif->bssid, + tx_arvif ? tx_arvif->bssid : NULL, + arvif->vif->bss_conf.bssid_index, + 1 << arvif->vif->bss_conf.bssid_indicator); if (ret) { ath11k_warn(ab, "failed to bring vdev up %d: %d\n", arvif->vdev_id, ret); @@ -7192,7 +7522,7 @@ static void ath11k_mac_op_change_chanctx(struct ieee80211_hw *hw, mutex_lock(&ar->conf_mutex); ath11k_dbg(ab, ATH11K_DBG_MAC, - "mac chanctx change freq %u width %d ptr %pK changed %x\n", + "chanctx change freq %u width %d ptr %p changed %x\n", ctx->def.chan->center_freq, ctx->def.width, ctx, changed); /* This shouldn't really happen because channel switching should use @@ -7244,7 +7574,8 @@ static int ath11k_start_vdev_delay(struct ieee80211_hw *hw, } if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) { - ret = ath11k_wmi_vdev_up(ar, arvif->vdev_id, 0, ar->mac_addr); + ret = ath11k_wmi_vdev_up(ar, arvif->vdev_id, 0, ar->mac_addr, + NULL, 0, 0); if (ret) { ath11k_warn(ab, "failed put monitor up: %d\n", ret); return ret; @@ -7272,7 +7603,7 @@ ath11k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw, mutex_lock(&ar->conf_mutex); ath11k_dbg(ab, ATH11K_DBG_MAC, - "mac chanctx assign ptr %pK vdev_id %i\n", + "chanctx assign ptr %p vdev_id %i\n", ctx, arvif->vdev_id); /* for QCA6390 bss peer must be created before vdev_start */ @@ -7362,7 +7693,7 @@ ath11k_mac_op_unassign_vif_chanctx(struct ieee80211_hw *hw, mutex_lock(&ar->conf_mutex); ath11k_dbg(ab, ATH11K_DBG_MAC, - "mac chanctx unassign ptr %pK vdev_id %i\n", + "chanctx unassign ptr %p vdev_id %i\n", ctx, arvif->vdev_id); WARN_ON(!arvif->is_started); @@ -7406,7 +7737,7 @@ ath11k_mac_op_unassign_vif_chanctx(struct ieee80211_hw *hw, arvif->bssid, arvif->vdev_id, ret); else ath11k_dbg(ar->ab, ATH11K_DBG_MAC, - "mac removed peer %pM vdev %d after vdev stop\n", + "removed peer %pM vdev %d after vdev stop\n", arvif->bssid, arvif->vdev_id); } @@ -7441,7 +7772,7 @@ ath11k_mac_op_switch_vif_chanctx(struct ieee80211_hw *hw, mutex_lock(&ar->conf_mutex); ath11k_dbg(ar->ab, ATH11K_DBG_MAC, - "mac chanctx switch n_vifs %d mode %d\n", + "chanctx switch n_vifs %d mode %d\n", n_vifs, mode); ath11k_mac_update_vif_chan(ar, vifs, n_vifs); @@ -7542,20 +7873,6 @@ static void ath11k_mac_op_flush(struct ieee80211_hw *hw, struct ieee80211_vif *v ath11k_mac_flush_tx_complete(ar); } -static int -ath11k_mac_bitrate_mask_num_ht_rates(struct ath11k *ar, - enum nl80211_band band, - const struct cfg80211_bitrate_mask *mask) -{ - int num_rates = 0; - int i; - - for (i = 0; i < ARRAY_SIZE(mask->control[band].ht_mcs); i++) - num_rates += hweight16(mask->control[band].ht_mcs[i]); - - return num_rates; -} - static bool ath11k_mac_has_single_legacy_rate(struct ath11k *ar, enum nl80211_band band, @@ -7787,7 +8104,7 @@ static int ath11k_mac_set_rate_params(struct ath11k_vif *arvif, lockdep_assert_held(&ar->conf_mutex); ath11k_dbg(ar->ab, ATH11K_DBG_MAC, - "mac set rate params vdev %i rate 0x%02x nss 0x%02x sgi 0x%02x ldpc 0x%02x he_gi 0x%02x he_ltf 0x%02x he_fixed_rate %d\n", + "set rate params vdev %i rate 0x%02x nss 0x%02x sgi 0x%02x ldpc 0x%02x he_gi 0x%02x he_ltf 0x%02x he_fixed_rate %d\n", arvif->vdev_id, rate, nss, sgi, ldpc, he_gi, he_ltf, he_fixed_rate); @@ -8292,7 +8609,7 @@ static void ath11k_mac_put_chain_rssi(struct station_info *sinfo, arsta->chain_signal[i] = ATH11K_INVALID_RSSI_FULL; ath11k_dbg(ar->ab, ATH11K_DBG_MAC, - "mac sta statistics %s rssi[%d] %d\n", pre, i, rssi); + "sta statistics %s rssi[%d] %d\n", pre, i, rssi); if (rssi != ATH11K_DEFAULT_NOISE_FLOOR && rssi != ATH11K_INVALID_RSSI_FULL && @@ -8356,7 +8673,7 @@ static void ath11k_mac_op_sta_statistics(struct ieee80211_hw *hw, signal = arsta->rssi_beacon; ath11k_dbg(ar->ab, ATH11K_DBG_MAC, - "mac sta statistics db2dbm %u rssi comb %d rssi beacon %d\n", + "sta statistics db2dbm %u rssi comb %d rssi beacon %d\n", db2dbm, arsta->rssi_comb, arsta->rssi_beacon); if (signal) { @@ -8403,7 +8720,7 @@ static void ath11k_mac_op_ipv6_changed(struct ieee80211_hw *hw, struct list_head *p; u32 count, scope; - ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac op ipv6 changed\n"); + ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "op ipv6 changed\n"); offload = &arvif->arp_ns_offload; count = 0; @@ -8428,7 +8745,7 @@ static void ath11k_mac_op_ipv6_changed(struct ieee80211_hw *hw, memcpy(offload->ipv6_addr[count], &ifa6->addr.s6_addr, sizeof(ifa6->addr.s6_addr)); offload->ipv6_type[count] = ATH11K_IPV6_UC_TYPE; - ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac count %d ipv6 uc %pI6 scope %d\n", + ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "count %d ipv6 uc %pI6 scope %d\n", count, offload->ipv6_addr[count], scope); count++; @@ -8448,7 +8765,7 @@ static void ath11k_mac_op_ipv6_changed(struct ieee80211_hw *hw, memcpy(offload->ipv6_addr[count], &ifaca6->aca_addr, sizeof(ifaca6->aca_addr)); offload->ipv6_type[count] = ATH11K_IPV6_AC_TYPE; - ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac count %d ipv6 ac %pI6 scope %d\n", + ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "count %d ipv6 ac %pI6 scope %d\n", count, offload->ipv6_addr[count], scope); count++; @@ -8474,7 +8791,7 @@ static void ath11k_mac_op_set_rekey_data(struct ieee80211_hw *hw, struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif); struct ath11k_rekey_data *rekey_data = &arvif->rekey_data; - ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac set rekey data vdev %d\n", + ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "set rekey data vdev %d\n", arvif->vdev_id); mutex_lock(&ar->conf_mutex); @@ -8892,7 +9209,7 @@ static int ath11k_mac_setup_channels_rates(struct ath11k *ar, } if (supported_bands & WMI_HOST_WLAN_5G_CAP) { - if (reg_cap->high_5ghz_chan >= ATH11K_MAX_6G_FREQ) { + if (reg_cap->high_5ghz_chan >= ATH11K_MIN_6G_FREQ) { channels = kmemdup(ath11k_6ghz_channels, sizeof(ath11k_6ghz_channels), GFP_KERNEL); if (!channels) { @@ -9001,19 +9318,23 @@ static int ath11k_mac_setup_iface_combinations(struct ath11k *ar) static const u8 ath11k_if_types_ext_capa[] = { [0] = WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING, + [2] = WLAN_EXT_CAPA3_MULTI_BSSID_SUPPORT, [7] = WLAN_EXT_CAPA8_OPMODE_NOTIF, }; static const u8 ath11k_if_types_ext_capa_sta[] = { [0] = WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING, + [2] = WLAN_EXT_CAPA3_MULTI_BSSID_SUPPORT, [7] = WLAN_EXT_CAPA8_OPMODE_NOTIF, [9] = WLAN_EXT_CAPA10_TWT_REQUESTER_SUPPORT, }; static const u8 ath11k_if_types_ext_capa_ap[] = { [0] = WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING, + [2] = WLAN_EXT_CAPA3_MULTI_BSSID_SUPPORT, [7] = WLAN_EXT_CAPA8_OPMODE_NOTIF, [9] = WLAN_EXT_CAPA10_TWT_RESPONDER_SUPPORT, + [10] = WLAN_EXT_CAPA11_EMA_SUPPORT, }; static const struct wiphy_iftype_ext_capab ath11k_iftypes_ext_capa[] = { @@ -9251,6 +9572,9 @@ static int __ath11k_mac_register(struct ath11k *ar) wiphy_ext_feature_set(ar->hw->wiphy, NL80211_EXT_FEATURE_ENABLE_FTM_RESPONDER); + ar->hw->wiphy->mbssid_max_interfaces = TARGET_NUM_VDEVS(ab); + ar->hw->wiphy->ema_max_profile_periodicity = TARGET_EMA_MAX_PROFILE_PERIOD; + ath11k_reg_init(ar); if (!test_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags)) { @@ -9468,6 +9792,7 @@ void ath11k_mac_destroy(struct ath11k_base *ab) if (!ar) continue; + ath11k_fw_stats_free(&ar->fw_stats); ieee80211_free_hw(ar->hw); pdev->ar = NULL; } diff --git a/drivers/net/wireless/ath/ath11k/mhi.c b/drivers/net/wireless/ath/ath11k/mhi.c index a62ee05c54097253d3514ffbc1c2c7e95e1141d7..3ac689f1def403ccc80f74ce26264af977f46f35 100644 --- a/drivers/net/wireless/ath/ath11k/mhi.c +++ b/drivers/net/wireless/ath/ath11k/mhi.c @@ -211,7 +211,7 @@ void ath11k_mhi_set_mhictrl_reset(struct ath11k_base *ab) val = ath11k_pcic_read32(ab, MHISTATUS); - ath11k_dbg(ab, ATH11K_DBG_PCI, "MHISTATUS 0x%x\n", val); + ath11k_dbg(ab, ATH11K_DBG_PCI, "mhistatus 0x%x\n", val); /* Observed on QCA6390 that after SOC_GLOBAL_RESET, MHISTATUS * has SYSERR bit set and thus need to set MHICTRL_RESET @@ -263,7 +263,7 @@ static int ath11k_mhi_get_msi(struct ath11k_pci *ab_pci) if (ret) return ret; - ath11k_dbg(ab, ATH11K_DBG_PCI, "Number of assigned MSI for MHI is %d, base vector is %d\n", + ath11k_dbg(ab, ATH11K_DBG_PCI, "num_vectors %d base_vector %d\n", num_vectors, base_vector); irq = kcalloc(num_vectors, sizeof(int), GFP_KERNEL); @@ -325,7 +325,7 @@ static void ath11k_mhi_op_status_cb(struct mhi_controller *mhi_cntrl, { struct ath11k_base *ab = dev_get_drvdata(mhi_cntrl->cntrl_dev); - ath11k_dbg(ab, ATH11K_DBG_BOOT, "mhi notify status reason %s\n", + ath11k_dbg(ab, ATH11K_DBG_BOOT, "notify status reason %s\n", ath11k_mhi_op_callback_to_str(cb)); switch (cb) { diff --git a/drivers/net/wireless/ath/ath11k/pci.c b/drivers/net/wireless/ath/ath11k/pci.c index 7b33731a50ee7e597ec3832e7c5e8a352282f6c8..79e2cbe8263848c7d569449d71a0f0e9e868358c 100644 --- a/drivers/net/wireless/ath/ath11k/pci.c +++ b/drivers/net/wireless/ath/ath11k/pci.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: BSD-3-Clause-Clear /* * Copyright (c) 2019-2020 The Linux Foundation. All rights reserved. - * Copyright (c) 2021-2022, Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved. */ #include @@ -203,10 +203,10 @@ static void ath11k_pci_clear_dbg_registers(struct ath11k_base *ab) /* read cookie */ val = ath11k_pcic_read32(ab, PCIE_Q6_COOKIE_ADDR); - ath11k_dbg(ab, ATH11K_DBG_PCI, "cookie:0x%x\n", val); + ath11k_dbg(ab, ATH11K_DBG_PCI, "pcie_q6_cookie_addr 0x%x\n", val); val = ath11k_pcic_read32(ab, WLAON_WARM_SW_ENTRY); - ath11k_dbg(ab, ATH11K_DBG_PCI, "WLAON_WARM_SW_ENTRY 0x%x\n", val); + ath11k_dbg(ab, ATH11K_DBG_PCI, "wlaon_warm_sw_entry 0x%x\n", val); /* TODO: exact time to sleep is uncertain */ mdelay(10); @@ -218,13 +218,13 @@ static void ath11k_pci_clear_dbg_registers(struct ath11k_base *ab) mdelay(10); val = ath11k_pcic_read32(ab, WLAON_WARM_SW_ENTRY); - ath11k_dbg(ab, ATH11K_DBG_PCI, "WLAON_WARM_SW_ENTRY 0x%x\n", val); + ath11k_dbg(ab, ATH11K_DBG_PCI, "wlaon_warm_sw_entry 0x%x\n", val); /* A read clear register. clear the register to prevent * Q6 from entering wrong code path. */ val = ath11k_pcic_read32(ab, WLAON_SOC_RESET_CAUSE_REG); - ath11k_dbg(ab, ATH11K_DBG_PCI, "soc reset cause:%d\n", val); + ath11k_dbg(ab, ATH11K_DBG_PCI, "soc reset cause %d\n", val); } static int ath11k_pci_set_link_reg(struct ath11k_base *ab, @@ -312,14 +312,14 @@ static void ath11k_pci_enable_ltssm(struct ath11k_base *ab) val = ath11k_pcic_read32(ab, PCIE_PCIE_PARF_LTSSM); } - ath11k_dbg(ab, ATH11K_DBG_PCI, "pci ltssm 0x%x\n", val); + ath11k_dbg(ab, ATH11K_DBG_PCI, "ltssm 0x%x\n", val); val = ath11k_pcic_read32(ab, GCC_GCC_PCIE_HOT_RST); val |= GCC_GCC_PCIE_HOT_RST_VAL; ath11k_pcic_write32(ab, GCC_GCC_PCIE_HOT_RST, val); val = ath11k_pcic_read32(ab, GCC_GCC_PCIE_HOT_RST); - ath11k_dbg(ab, ATH11K_DBG_PCI, "pci pcie_hot_rst 0x%x\n", val); + ath11k_dbg(ab, ATH11K_DBG_PCI, "pcie_hot_rst 0x%x\n", val); mdelay(5); } @@ -433,7 +433,7 @@ static int ath11k_pci_alloc_msi(struct ath11k_pci *ab_pci) } clear_bit(ATH11K_FLAG_MULTI_MSI_VECTORS, &ab->dev_flags); ab->pci.msi.config = &msi_config_one_msi; - ath11k_dbg(ab, ATH11K_DBG_PCI, "request MSI one vector\n"); + ath11k_dbg(ab, ATH11K_DBG_PCI, "request one msi vector\n"); } ath11k_info(ab, "MSI vectors: %d\n", num_vectors); @@ -487,7 +487,7 @@ static int ath11k_pci_config_msi_data(struct ath11k_pci *ab_pci) ab_pci->ab->pci.msi.ep_base_data = msi_desc->msg.data; - ath11k_dbg(ab_pci->ab, ATH11K_DBG_PCI, "pci after request_irq msi_ep_base_data %d\n", + ath11k_dbg(ab_pci->ab, ATH11K_DBG_PCI, "after request_irq msi_ep_base_data %d\n", ab_pci->ab->pci.msi.ep_base_data); return 0; @@ -545,7 +545,7 @@ static int ath11k_pci_claim(struct ath11k_pci *ab_pci, struct pci_dev *pdev) ab->mem_ce = ab->mem; - ath11k_dbg(ab, ATH11K_DBG_BOOT, "boot pci_mem 0x%pK\n", ab->mem); + ath11k_dbg(ab, ATH11K_DBG_BOOT, "pci_mem 0x%p\n", ab->mem); return 0; release_region: @@ -575,7 +575,7 @@ static void ath11k_pci_aspm_disable(struct ath11k_pci *ab_pci) pcie_capability_read_word(ab_pci->pdev, PCI_EXP_LNKCTL, &ab_pci->link_ctl); - ath11k_dbg(ab, ATH11K_DBG_PCI, "pci link_ctl 0x%04x L0s %d L1 %d\n", + ath11k_dbg(ab, ATH11K_DBG_PCI, "link_ctl 0x%04x L0s %d L1 %d\n", ab_pci->link_ctl, u16_get_bits(ab_pci->link_ctl, PCI_EXP_LNKCTL_ASPM_L0S), u16_get_bits(ab_pci->link_ctl, PCI_EXP_LNKCTL_ASPM_L1)); @@ -709,7 +709,7 @@ static void ath11k_pci_read_hw_version(struct ath11k_base *ab, u32 *major, u32 * *minor = FIELD_GET(TCSR_SOC_HW_VERSION_MINOR_MASK, soc_hw_version); - ath11k_dbg(ab, ATH11K_DBG_PCI, "pci tcsr_soc_hw_version major %d minor %d\n", + ath11k_dbg(ab, ATH11K_DBG_PCI, "tcsr_soc_hw_version major %d minor %d\n", *major, *minor); } @@ -745,6 +745,7 @@ static int ath11k_pci_probe(struct pci_dev *pdev, ab_pci->ab = ab; ab_pci->pdev = pdev; ab->hif.ops = &ath11k_pci_hif_ops; + ab->fw_mode = ATH11K_FIRMWARE_MODE_NORMAL; pci_set_drvdata(pdev, ab); spin_lock_init(&ab_pci->window_lock); diff --git a/drivers/net/wireless/ath/ath11k/pcic.c b/drivers/net/wireless/ath/ath11k/pcic.c index 30d66147223f49cb98e05e4cd38ee71380493bf9..c899616fbee4b55a52cc1099ed5892021876f854 100644 --- a/drivers/net/wireless/ath/ath11k/pcic.c +++ b/drivers/net/wireless/ath/ath11k/pcic.c @@ -263,7 +263,7 @@ int ath11k_pcic_get_user_msi_assignment(struct ath11k_base *ab, char *user_name, *user_base_data = *base_vector + ab->pci.msi.ep_base_data; ath11k_dbg(ab, ATH11K_DBG_PCI, - "Assign MSI to user: %s, num_vectors: %d, user_base_data: %u, base_vector: %u\n", + "msi assignment %s num_vectors %d user_base_data %u base_vector %u\n", user_name, *num_vectors, *user_base_data, *base_vector); @@ -527,7 +527,7 @@ static irqreturn_t ath11k_pcic_ext_interrupt_handler(int irq, void *arg) if (!test_bit(ATH11K_FLAG_EXT_IRQ_ENABLED, &ab->dev_flags)) return IRQ_HANDLED; - ath11k_dbg(irq_grp->ab, ATH11K_DBG_PCI, "ext irq:%d\n", irq); + ath11k_dbg(irq_grp->ab, ATH11K_DBG_PCI, "ext irq %d\n", irq); /* last interrupt received for this group */ irq_grp->timestamp = jiffies; @@ -597,7 +597,7 @@ static int ath11k_pcic_ext_irq_config(struct ath11k_base *ab) ab->irq_num[irq_idx] = irq; ath11k_dbg(ab, ATH11K_DBG_PCI, - "irq:%d group:%d\n", irq, i); + "irq %d group %d\n", irq, i); irq_set_status_flags(irq, IRQ_DISABLE_UNLAZY); ret = request_irq(irq, ath11k_pcic_ext_interrupt_handler, diff --git a/drivers/net/wireless/ath/ath11k/peer.c b/drivers/net/wireless/ath/ath11k/peer.c index 1380811827a843111d6f1949738f8420f386a3fe..114aa3a9a3397b3a868cb5b7f1e557ae203b6ca3 100644 --- a/drivers/net/wireless/ath/ath11k/peer.c +++ b/drivers/net/wireless/ath/ath11k/peer.c @@ -106,7 +106,7 @@ void ath11k_peer_unmap_event(struct ath11k_base *ab, u16 peer_id) goto exit; } - ath11k_dbg(ab, ATH11K_DBG_DP_HTT, "htt peer unmap vdev %d peer %pM id %d\n", + ath11k_dbg(ab, ATH11K_DBG_DP_HTT, "peer unmap vdev %d peer %pM id %d\n", peer->vdev_id, peer->addr, peer_id); list_del(&peer->list); @@ -138,7 +138,7 @@ void ath11k_peer_map_event(struct ath11k_base *ab, u8 vdev_id, u16 peer_id, wake_up(&ab->peer_mapping_wq); } - ath11k_dbg(ab, ATH11K_DBG_DP_HTT, "htt peer map vdev %d peer %pM id %d\n", + ath11k_dbg(ab, ATH11K_DBG_DP_HTT, "peer map vdev %d peer %pM id %d\n", vdev_id, mac_addr, peer_id); exit: diff --git a/drivers/net/wireless/ath/ath11k/qmi.c b/drivers/net/wireless/ath/ath11k/qmi.c index ab923e24b0a9cc009a340ca4911dfe68208af4bb..d4eaf7d2ba84170a0cd3ddd034bfc06e97c1601b 100644 --- a/drivers/net/wireless/ath/ath11k/qmi.c +++ b/drivers/net/wireless/ath/ath11k/qmi.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: BSD-3-Clause-Clear /* * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. - * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved. */ #include @@ -1755,7 +1755,7 @@ static int ath11k_qmi_host_cap_send(struct ath11k_base *ab) req.nm_modem |= PLATFORM_CAP_PCIE_PME_D3COLD; - ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi host cap request\n"); + ath11k_dbg(ab, ATH11K_DBG_QMI, "host cap request\n"); ret = qmi_txn_init(&ab->qmi.handle, &txn, qmi_wlanfw_host_cap_resp_msg_v01_ei, &resp); @@ -1833,7 +1833,7 @@ static int ath11k_qmi_fw_ind_register_send(struct ath11k_base *ab) if (ret < 0) goto out; - ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi indication register request\n"); + ath11k_dbg(ab, ATH11K_DBG_QMI, "indication register request\n"); ret = qmi_send_request(&ab->qmi.handle, NULL, &txn, QMI_WLANFW_IND_REGISTER_REQ_V01, @@ -1889,7 +1889,7 @@ static int ath11k_qmi_respond_fw_mem_request(struct ath11k_base *ab) test_bit(ATH11K_FLAG_FIXED_MEM_RGN, &ab->dev_flags)) && ab->qmi.target_mem_delayed) { delayed = true; - ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi delays mem_request %d\n", + ath11k_dbg(ab, ATH11K_DBG_QMI, "delays mem_request %d\n", ab->qmi.mem_seg_count); memset(req, 0, sizeof(*req)); } else { @@ -1901,7 +1901,7 @@ static int ath11k_qmi_respond_fw_mem_request(struct ath11k_base *ab) req->mem_seg[i].size = ab->qmi.target_mem[i].size; req->mem_seg[i].type = ab->qmi.target_mem[i].type; ath11k_dbg(ab, ATH11K_DBG_QMI, - "qmi req mem_seg[%d] %pad %u %u\n", i, + "req mem_seg[%d] %pad %u %u\n", i, &ab->qmi.target_mem[i].paddr, ab->qmi.target_mem[i].size, ab->qmi.target_mem[i].type); @@ -1913,7 +1913,7 @@ static int ath11k_qmi_respond_fw_mem_request(struct ath11k_base *ab) if (ret < 0) goto out; - ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi respond memory request delayed %i\n", + ath11k_dbg(ab, ATH11K_DBG_QMI, "respond memory request delayed %i\n", delayed); ret = qmi_send_request(&ab->qmi.handle, NULL, &txn, @@ -2002,7 +2002,7 @@ static int ath11k_qmi_alloc_target_mem_chunk(struct ath11k_base *ab) if (!chunk->vaddr) { if (ab->qmi.mem_seg_count <= ATH11K_QMI_FW_MEM_REQ_SEGMENT_CNT) { ath11k_dbg(ab, ATH11K_DBG_QMI, - "qmi dma allocation failed (%d B type %u), will try later with small size\n", + "dma allocation failed (%d B type %u), will try later with small size\n", chunk->size, chunk->type); ath11k_qmi_free_target_mem_chunk(ab); @@ -2036,7 +2036,7 @@ static int ath11k_qmi_assign_target_mem_chunk(struct ath11k_base *ab) hremote_node = of_parse_phandle(dev->of_node, "memory-region", 0); if (!hremote_node) { ath11k_dbg(ab, ATH11K_DBG_QMI, - "qmi fail to get hremote_node\n"); + "fail to get hremote_node\n"); return -ENODEV; } @@ -2044,13 +2044,13 @@ static int ath11k_qmi_assign_target_mem_chunk(struct ath11k_base *ab) of_node_put(hremote_node); if (ret) { ath11k_dbg(ab, ATH11K_DBG_QMI, - "qmi fail to get reg from hremote\n"); + "fail to get reg from hremote\n"); return ret; } if (res.end - res.start + 1 < ab->qmi.target_mem[i].size) { ath11k_dbg(ab, ATH11K_DBG_QMI, - "qmi fail to assign memory of sz\n"); + "fail to assign memory of sz\n"); return -EINVAL; } @@ -2058,6 +2058,9 @@ static int ath11k_qmi_assign_target_mem_chunk(struct ath11k_base *ab) ab->qmi.target_mem[idx].iaddr = ioremap(ab->qmi.target_mem[idx].paddr, ab->qmi.target_mem[i].size); + if (!ab->qmi.target_mem[idx].iaddr) + return -EIO; + ab->qmi.target_mem[idx].size = ab->qmi.target_mem[i].size; host_ddr_sz = ab->qmi.target_mem[i].size; ab->qmi.target_mem[idx].type = ab->qmi.target_mem[i].type; @@ -2083,6 +2086,8 @@ static int ath11k_qmi_assign_target_mem_chunk(struct ath11k_base *ab) ab->qmi.target_mem[idx].iaddr = ioremap(ab->qmi.target_mem[idx].paddr, ab->qmi.target_mem[i].size); + if (!ab->qmi.target_mem[idx].iaddr) + return -EIO; } else { ab->qmi.target_mem[idx].paddr = ATH11K_QMI_CALDB_ADDRESS; @@ -2198,7 +2203,7 @@ static int ath11k_qmi_request_target_cap(struct ath11k_base *ab) if (ret < 0) goto out; - ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi target cap request\n"); + ath11k_dbg(ab, ATH11K_DBG_QMI, "target cap request\n"); ret = qmi_send_request(&ab->qmi.handle, NULL, &txn, QMI_WLANFW_CAP_REQ_V01, @@ -2251,7 +2256,7 @@ static int ath11k_qmi_request_target_cap(struct ath11k_base *ab) if (resp.eeprom_read_timeout_valid) { ab->qmi.target.eeprom_caldata = resp.eeprom_read_timeout; - ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi cal data supported from eeprom\n"); + ath11k_dbg(ab, ATH11K_DBG_QMI, "cal data supported from eeprom\n"); } fw_build_id = ab->qmi.target.fw_build_id; @@ -2348,7 +2353,7 @@ static int ath11k_qmi_load_file_target_mem(struct ath11k_base *ab, if (ret < 0) goto err_iounmap; - ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi bdf download req fixed addr type %d\n", + ath11k_dbg(ab, ATH11K_DBG_QMI, "bdf download req fixed addr type %d\n", type); ret = qmi_send_request(&ab->qmi.handle, NULL, &txn, @@ -2381,7 +2386,7 @@ static int ath11k_qmi_load_file_target_mem(struct ath11k_base *ab, remaining -= req->data_len; temp += req->data_len; req->seg_id++; - ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi bdf download request remaining %i\n", + ath11k_dbg(ab, ATH11K_DBG_QMI, "bdf download request remaining %i\n", remaining); } } @@ -2427,7 +2432,7 @@ static int ath11k_qmi_load_bdf_qmi(struct ath11k_base *ab, else bdf_type = ATH11K_QMI_BDF_TYPE_BIN; - ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi bdf_type %d\n", bdf_type); + ath11k_dbg(ab, ATH11K_DBG_QMI, "bdf_type %d\n", bdf_type); fw_size = min_t(u32, ab->hw_params.fw.board_size, bd.len); @@ -2457,6 +2462,14 @@ static int ath11k_qmi_load_bdf_qmi(struct ath11k_base *ab, fw_entry = ath11k_core_firmware_request(ab, ATH11K_DEFAULT_CAL_FILE); if (IS_ERR(fw_entry)) { + /* Caldata may not be present during first time calibration in + * factory hence allow to boot without loading caldata in ftm mode + */ + if (ath11k_ftm_mode) { + ath11k_info(ab, + "Booting without cal data file in factory test mode\n"); + return 0; + } ret = PTR_ERR(fw_entry); ath11k_warn(ab, "qmi failed to load CAL data file:%s\n", @@ -2474,14 +2487,14 @@ static int ath11k_qmi_load_bdf_qmi(struct ath11k_base *ab, goto out_qmi_cal; } - ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi caldata type: %u\n", file_type); + ath11k_dbg(ab, ATH11K_DBG_QMI, "caldata type: %u\n", file_type); out_qmi_cal: if (!ab->qmi.target.eeprom_caldata) release_firmware(fw_entry); out: ath11k_core_free_bdf(ab, &bd); - ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi BDF download sequence completed\n"); + ath11k_dbg(ab, ATH11K_DBG_QMI, "BDF download sequence completed\n"); return ret; } @@ -2566,7 +2579,7 @@ static int ath11k_qmi_wlanfw_m3_info_send(struct ath11k_base *ab) if (ret < 0) goto out; - ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi m3 info req\n"); + ath11k_dbg(ab, ATH11K_DBG_QMI, "m3 info req\n"); ret = qmi_send_request(&ab->qmi.handle, NULL, &txn, QMI_WLANFW_M3_INFO_REQ_V01, @@ -2615,7 +2628,7 @@ static int ath11k_qmi_wlanfw_mode_send(struct ath11k_base *ab, if (ret < 0) goto out; - ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi wlan mode req mode %d\n", mode); + ath11k_dbg(ab, ATH11K_DBG_QMI, "wlan mode req mode %d\n", mode); ret = qmi_send_request(&ab->qmi.handle, NULL, &txn, QMI_WLANFW_WLAN_MODE_REQ_V01, @@ -2710,7 +2723,7 @@ static int ath11k_qmi_wlanfw_wlan_cfg_send(struct ath11k_base *ab) if (ret < 0) goto out; - ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi wlan cfg req\n"); + ath11k_dbg(ab, ATH11K_DBG_QMI, "wlan cfg req\n"); ret = qmi_send_request(&ab->qmi.handle, NULL, &txn, QMI_WLANFW_WLAN_CFG_REQ_V01, @@ -2787,7 +2800,7 @@ void ath11k_qmi_firmware_stop(struct ath11k_base *ab) { int ret; - ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi firmware stop\n"); + ath11k_dbg(ab, ATH11K_DBG_QMI, "firmware stop\n"); ret = ath11k_qmi_wlanfw_mode_send(ab, ATH11K_FIRMWARE_MODE_OFF); if (ret < 0) { @@ -2801,7 +2814,7 @@ int ath11k_qmi_firmware_start(struct ath11k_base *ab, { int ret; - ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi firmware start\n"); + ath11k_dbg(ab, ATH11K_DBG_QMI, "firmware start\n"); if (ab->hw_params.fw_wmi_diag_event) { ret = ath11k_qmi_wlanfw_wlan_ini_send(ab, true); @@ -2959,7 +2972,7 @@ static void ath11k_qmi_msg_mem_request_cb(struct qmi_handle *qmi_hdl, const struct qmi_wlanfw_request_mem_ind_msg_v01 *msg = data; int i, ret; - ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi firmware request memory request\n"); + ath11k_dbg(ab, ATH11K_DBG_QMI, "firmware request memory request\n"); if (msg->mem_seg_len == 0 || msg->mem_seg_len > ATH11K_QMI_WLANFW_MAX_NUM_MEM_SEG_V01) @@ -2971,7 +2984,7 @@ static void ath11k_qmi_msg_mem_request_cb(struct qmi_handle *qmi_hdl, for (i = 0; i < qmi->mem_seg_count ; i++) { ab->qmi.target_mem[i].type = msg->mem_seg[i].type; ab->qmi.target_mem[i].size = msg->mem_seg[i].size; - ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi mem seg type %d size %d\n", + ath11k_dbg(ab, ATH11K_DBG_QMI, "mem seg type %d size %d\n", msg->mem_seg[i].type, msg->mem_seg[i].size); } @@ -3003,7 +3016,7 @@ static void ath11k_qmi_msg_mem_ready_cb(struct qmi_handle *qmi_hdl, struct ath11k_qmi *qmi = container_of(qmi_hdl, struct ath11k_qmi, handle); struct ath11k_base *ab = qmi->ab; - ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi firmware memory ready indication\n"); + ath11k_dbg(ab, ATH11K_DBG_QMI, "firmware memory ready indication\n"); ath11k_qmi_driver_event_post(qmi, ATH11K_QMI_EVENT_FW_MEM_READY, NULL); } @@ -3015,7 +3028,7 @@ static void ath11k_qmi_msg_fw_ready_cb(struct qmi_handle *qmi_hdl, struct ath11k_qmi *qmi = container_of(qmi_hdl, struct ath11k_qmi, handle); struct ath11k_base *ab = qmi->ab; - ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi firmware ready\n"); + ath11k_dbg(ab, ATH11K_DBG_QMI, "firmware ready\n"); if (!ab->qmi.cal_done) { ab->qmi.cal_done = 1; @@ -3036,7 +3049,7 @@ static void ath11k_qmi_msg_cold_boot_cal_done_cb(struct qmi_handle *qmi_hdl, ab->qmi.cal_done = 1; wake_up(&ab->qmi.cold_boot_waitq); - ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi cold boot calibration done\n"); + ath11k_dbg(ab, ATH11K_DBG_QMI, "cold boot calibration done\n"); } static void ath11k_qmi_msg_fw_init_done_cb(struct qmi_handle *qmi_hdl, @@ -3049,7 +3062,7 @@ static void ath11k_qmi_msg_fw_init_done_cb(struct qmi_handle *qmi_hdl, struct ath11k_base *ab = qmi->ab; ath11k_qmi_driver_event_post(qmi, ATH11K_QMI_EVENT_FW_INIT_DONE, NULL); - ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi firmware init done\n"); + ath11k_dbg(ab, ATH11K_DBG_QMI, "firmware init done\n"); } static const struct qmi_msg_handler ath11k_qmi_msg_handlers[] = { @@ -3114,7 +3127,7 @@ static int ath11k_qmi_ops_new_server(struct qmi_handle *qmi_hdl, return ret; } - ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi wifi fw qmi service connected\n"); + ath11k_dbg(ab, ATH11K_DBG_QMI, "wifi fw qmi service connected\n"); ath11k_qmi_driver_event_post(qmi, ATH11K_QMI_EVENT_SERVER_ARRIVE, NULL); return ret; @@ -3126,7 +3139,7 @@ static void ath11k_qmi_ops_del_server(struct qmi_handle *qmi_hdl, struct ath11k_qmi *qmi = container_of(qmi_hdl, struct ath11k_qmi, handle); struct ath11k_base *ab = qmi->ab; - ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi wifi fw del server\n"); + ath11k_dbg(ab, ATH11K_DBG_QMI, "wifi fw del server\n"); ath11k_qmi_driver_event_post(qmi, ATH11K_QMI_EVENT_SERVER_EXIT, NULL); } @@ -3256,8 +3269,7 @@ int ath11k_qmi_init_service(struct ath11k_base *ab) return ret; } - ab->qmi.event_wq = alloc_workqueue("ath11k_qmi_driver_event", - WQ_UNBOUND, 1); + ab->qmi.event_wq = alloc_ordered_workqueue("ath11k_qmi_driver_event", 0); if (!ab->qmi.event_wq) { ath11k_err(ab, "failed to allocate workqueue\n"); return -EFAULT; diff --git a/drivers/net/wireless/ath/ath11k/reg.c b/drivers/net/wireless/ath/ath11k/reg.c index 67443457f4daa1243580f5746e12ee6faa04dfd4..7f9fb968dac6d40fa3e72a08305392de4fa737a3 100644 --- a/drivers/net/wireless/ath/ath11k/reg.c +++ b/drivers/net/wireless/ath/ath11k/reg.c @@ -123,7 +123,7 @@ int ath11k_reg_update_chan_list(struct ath11k *ar, bool wait) ar->state_11d = ATH11K_11D_IDLE; } ath11k_dbg(ar->ab, ATH11K_DBG_REG, - "reg 11d scan wait left time %d\n", left); + "11d scan wait left time %d\n", left); } if (wait && @@ -136,7 +136,7 @@ int ath11k_reg_update_chan_list(struct ath11k *ar, bool wait) "failed to receive hw scan complete: timed out\n"); ath11k_dbg(ar->ab, ATH11K_DBG_REG, - "reg hw scan wait left time %d\n", left); + "hw scan wait left time %d\n", left); } if (ar->state == ATH11K_STATE_RESTARTING) diff --git a/drivers/net/wireless/ath/ath11k/testmode.c b/drivers/net/wireless/ath/ath11k/testmode.c index 4bf1931adbaaec6590aedb1e1930c7d48e28145d..8fc5cddb28bded48f2cc0949243171a83f0323eb 100644 --- a/drivers/net/wireless/ath/ath11k/testmode.c +++ b/drivers/net/wireless/ath/ath11k/testmode.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: BSD-3-Clause-Clear /* * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved. */ #include "testmode.h" @@ -11,6 +12,9 @@ #include "core.h" #include "testmode_i.h" +#define ATH11K_FTM_SEGHDR_CURRENT_SEQ GENMASK(3, 0) +#define ATH11K_FTM_SEGHDR_TOTAL_SEGMENTS GENMASK(7, 4) + static const struct nla_policy ath11k_tm_policy[ATH11K_TM_ATTR_MAX + 1] = { [ATH11K_TM_ATTR_CMD] = { .type = NLA_U32 }, [ATH11K_TM_ATTR_DATA] = { .type = NLA_BINARY, @@ -20,58 +24,162 @@ static const struct nla_policy ath11k_tm_policy[ATH11K_TM_ATTR_MAX + 1] = { [ATH11K_TM_ATTR_VERSION_MINOR] = { .type = NLA_U32 }, }; -/* Returns true if callee consumes the skb and the skb should be discarded. - * Returns false if skb is not used. Does not sleep. +static struct ath11k *ath11k_tm_get_ar(struct ath11k_base *ab) +{ + struct ath11k_pdev *pdev; + struct ath11k *ar = NULL; + int i; + + for (i = 0; i < ab->num_radios; i++) { + pdev = &ab->pdevs[i]; + ar = pdev->ar; + + if (ar && ar->state == ATH11K_STATE_FTM) + break; + } + + return ar; +} + +/* This function handles unsegmented events. Data in various events are aggregated + * in application layer, this event is unsegmented from host perspective. */ -bool ath11k_tm_event_wmi(struct ath11k *ar, u32 cmd_id, struct sk_buff *skb) +static void ath11k_tm_wmi_event_unsegmented(struct ath11k_base *ab, u32 cmd_id, + struct sk_buff *skb) { struct sk_buff *nl_skb; - bool consumed; - int ret; + struct ath11k *ar; - ath11k_dbg(ar->ab, ATH11K_DBG_TESTMODE, - "testmode event wmi cmd_id %d skb %pK skb->len %d\n", - cmd_id, skb, skb->len); + ath11k_dbg(ab, ATH11K_DBG_TESTMODE, + "event wmi cmd_id %d skb length %d\n", + cmd_id, skb->len); + ath11k_dbg_dump(ab, ATH11K_DBG_TESTMODE, NULL, "", skb->data, skb->len); - ath11k_dbg_dump(ar->ab, ATH11K_DBG_TESTMODE, NULL, "", skb->data, skb->len); + ar = ath11k_tm_get_ar(ab); + if (!ar) { + ath11k_warn(ab, "testmode event not handled due to invalid pdev\n"); + return; + } spin_lock_bh(&ar->data_lock); - consumed = true; - nl_skb = cfg80211_testmode_alloc_event_skb(ar->hw->wiphy, - 2 * sizeof(u32) + skb->len, + 2 * nla_total_size(sizeof(u32)) + + nla_total_size(skb->len), GFP_ATOMIC); if (!nl_skb) { - ath11k_warn(ar->ab, - "failed to allocate skb for testmode wmi event\n"); + ath11k_warn(ab, + "failed to allocate skb for unsegmented testmode wmi event\n"); goto out; } - ret = nla_put_u32(nl_skb, ATH11K_TM_ATTR_CMD, ATH11K_TM_CMD_WMI); - if (ret) { - ath11k_warn(ar->ab, - "failed to put testmode wmi event cmd attribute: %d\n", - ret); + if (nla_put_u32(nl_skb, ATH11K_TM_ATTR_CMD, ATH11K_TM_CMD_WMI) || + nla_put_u32(nl_skb, ATH11K_TM_ATTR_WMI_CMDID, cmd_id) || + nla_put(nl_skb, ATH11K_TM_ATTR_DATA, skb->len, skb->data)) { + ath11k_warn(ab, "failed to populate testmode unsegmented event\n"); kfree_skb(nl_skb); goto out; } - ret = nla_put_u32(nl_skb, ATH11K_TM_ATTR_WMI_CMDID, cmd_id); - if (ret) { - ath11k_warn(ar->ab, - "failed to put testmode wmi even cmd_id: %d\n", - ret); - kfree_skb(nl_skb); + cfg80211_testmode_event(nl_skb, GFP_ATOMIC); + spin_unlock_bh(&ar->data_lock); + return; + +out: + spin_unlock_bh(&ar->data_lock); + ath11k_warn(ab, "Failed to send testmode event to higher layers\n"); +} + +/* This function handles segmented events. Data of various events received + * from firmware is aggregated and sent to application layer + */ +static int ath11k_tm_process_event(struct ath11k_base *ab, u32 cmd_id, + const struct wmi_ftm_event_msg *ftm_msg, + u16 length) +{ + struct sk_buff *nl_skb; + int ret = 0; + struct ath11k *ar; + u8 const *buf_pos; + u16 datalen; + u8 total_segments, current_seq; + u32 data_pos; + u32 pdev_id; + + ath11k_dbg(ab, ATH11K_DBG_TESTMODE, + "event wmi cmd_id %d ftm event msg %pK datalen %d\n", + cmd_id, ftm_msg, length); + ath11k_dbg_dump(ab, ATH11K_DBG_TESTMODE, NULL, "", ftm_msg, length); + pdev_id = DP_HW2SW_MACID(ftm_msg->seg_hdr.pdev_id); + + if (pdev_id >= ab->num_radios) { + ath11k_warn(ab, "testmode event not handled due to invalid pdev id: %d\n", + pdev_id); + return -EINVAL; + } + + ar = ab->pdevs[pdev_id].ar; + if (!ar) { + ath11k_warn(ab, "testmode event not handled due to absence of pdev\n"); + return -ENODEV; + } + + current_seq = FIELD_GET(ATH11K_FTM_SEGHDR_CURRENT_SEQ, + ftm_msg->seg_hdr.segmentinfo); + total_segments = FIELD_GET(ATH11K_FTM_SEGHDR_TOTAL_SEGMENTS, + ftm_msg->seg_hdr.segmentinfo); + datalen = length - (sizeof(struct wmi_ftm_seg_hdr)); + buf_pos = ftm_msg->data; + + spin_lock_bh(&ar->data_lock); + + if (current_seq == 0) { + ab->testmode.expected_seq = 0; + ab->testmode.data_pos = 0; + } + + data_pos = ab->testmode.data_pos; + + if ((data_pos + datalen) > ATH11K_FTM_EVENT_MAX_BUF_LENGTH) { + ath11k_warn(ab, "Invalid ftm event length at %d: %d\n", + data_pos, datalen); + ret = -EINVAL; goto out; } - ret = nla_put(nl_skb, ATH11K_TM_ATTR_DATA, skb->len, skb->data); - if (ret) { - ath11k_warn(ar->ab, - "failed to copy skb to testmode wmi event: %d\n", - ret); + memcpy(&ab->testmode.eventdata[data_pos], buf_pos, datalen); + data_pos += datalen; + + if (++ab->testmode.expected_seq != total_segments) { + ab->testmode.data_pos = data_pos; + ath11k_dbg(ab, ATH11K_DBG_TESTMODE, + "partial data received current_seq %d total_seg %d\n", + current_seq, total_segments); + goto out; + } + + ath11k_dbg(ab, ATH11K_DBG_TESTMODE, + "total data length pos %d len %d\n", + data_pos, ftm_msg->seg_hdr.len); + nl_skb = cfg80211_testmode_alloc_event_skb(ar->hw->wiphy, + 2 * nla_total_size(sizeof(u32)) + + nla_total_size(data_pos), + GFP_ATOMIC); + if (!nl_skb) { + ath11k_warn(ab, + "failed to allocate skb for segmented testmode wmi event\n"); + ret = -ENOMEM; + goto out; + } + + if (nla_put_u32(nl_skb, ATH11K_TM_ATTR_CMD, + ATH11K_TM_CMD_WMI_FTM) || + nla_put_u32(nl_skb, ATH11K_TM_ATTR_WMI_CMDID, cmd_id) || + nla_put(nl_skb, ATH11K_TM_ATTR_DATA, data_pos, + &ab->testmode.eventdata[0])) { + ath11k_warn(ab, "failed to populate segmented testmode event"); kfree_skb(nl_skb); + ret = -ENOBUFS; goto out; } @@ -79,8 +187,45 @@ bool ath11k_tm_event_wmi(struct ath11k *ar, u32 cmd_id, struct sk_buff *skb) out: spin_unlock_bh(&ar->data_lock); + return ret; +} + +static void ath11k_tm_wmi_event_segmented(struct ath11k_base *ab, u32 cmd_id, + struct sk_buff *skb) +{ + const void **tb; + const struct wmi_ftm_event_msg *ev; + u16 length; + int ret; + + tb = ath11k_wmi_tlv_parse_alloc(ab, skb->data, skb->len, GFP_ATOMIC); + if (IS_ERR(tb)) { + ret = PTR_ERR(tb); + ath11k_warn(ab, "failed to parse ftm event tlv: %d\n", ret); + return; + } + + ev = tb[WMI_TAG_ARRAY_BYTE]; + if (!ev) { + ath11k_warn(ab, "failed to fetch ftm msg\n"); + kfree(tb); + return; + } - return consumed; + length = skb->len - TLV_HDR_SIZE; + ret = ath11k_tm_process_event(ab, cmd_id, ev, length); + if (ret) + ath11k_warn(ab, "Failed to process ftm event\n"); + + kfree(tb); +} + +void ath11k_tm_wmi_event(struct ath11k_base *ab, u32 cmd_id, struct sk_buff *skb) +{ + if (test_bit(ATH11K_FLAG_FTM_SEGMENTED, &ab->dev_flags)) + ath11k_tm_wmi_event_segmented(ab, cmd_id, skb); + else + ath11k_tm_wmi_event_unsegmented(ab, cmd_id, skb); } static int ath11k_tm_cmd_get_version(struct ath11k *ar, struct nlattr *tb[]) @@ -89,7 +234,7 @@ static int ath11k_tm_cmd_get_version(struct ath11k *ar, struct nlattr *tb[]) int ret; ath11k_dbg(ar->ab, ATH11K_DBG_TESTMODE, - "testmode cmd get version_major %d version_minor %d\n", + "cmd get version_major %d version_minor %d\n", ATH11K_TESTMODE_VERSION_MAJOR, ATH11K_TESTMODE_VERSION_MINOR); @@ -115,21 +260,56 @@ static int ath11k_tm_cmd_get_version(struct ath11k *ar, struct nlattr *tb[]) return cfg80211_testmode_reply(skb); } -static int ath11k_tm_cmd_wmi(struct ath11k *ar, struct nlattr *tb[]) +static int ath11k_tm_cmd_testmode_start(struct ath11k *ar, struct nlattr *tb[]) +{ + int ret; + + mutex_lock(&ar->conf_mutex); + + if (ar->state == ATH11K_STATE_FTM) { + ret = -EALREADY; + goto err; + } + + /* start utf only when the driver is not in use */ + if (ar->state != ATH11K_STATE_OFF) { + ret = -EBUSY; + goto err; + } + + ar->ab->testmode.eventdata = kzalloc(ATH11K_FTM_EVENT_MAX_BUF_LENGTH, + GFP_KERNEL); + if (!ar->ab->testmode.eventdata) { + ret = -ENOMEM; + goto err; + } + + ar->state = ATH11K_STATE_FTM; + ar->ftm_msgref = 0; + + mutex_unlock(&ar->conf_mutex); + + ath11k_dbg(ar->ab, ATH11K_DBG_TESTMODE, "cmd start\n"); + return 0; + +err: + mutex_unlock(&ar->conf_mutex); + return ret; +} + +static int ath11k_tm_cmd_wmi(struct ath11k *ar, struct nlattr *tb[], + struct ieee80211_vif *vif) { struct ath11k_pdev_wmi *wmi = ar->wmi; struct sk_buff *skb; + struct ath11k_vif *arvif; u32 cmd_id, buf_len; - int ret; + int ret, tag; void *buf; + u32 *ptr; mutex_lock(&ar->conf_mutex); - if (ar->state != ATH11K_STATE_ON) { - ret = -ENETDOWN; - goto out; - } - if (!tb[ATH11K_TM_ATTR_DATA]) { ret = -EINVAL; goto out; @@ -142,11 +322,45 @@ static int ath11k_tm_cmd_wmi(struct ath11k *ar, struct nlattr *tb[]) buf = nla_data(tb[ATH11K_TM_ATTR_DATA]); buf_len = nla_len(tb[ATH11K_TM_ATTR_DATA]); + if (!buf_len) { + ath11k_warn(ar->ab, "No data present in testmode wmi command\n"); + ret = -EINVAL; + goto out; + } + cmd_id = nla_get_u32(tb[ATH11K_TM_ATTR_WMI_CMDID]); + /* Make sure that the buffer length is long enough to + * hold TLV and pdev/vdev id. + */ + if (buf_len < sizeof(struct wmi_tlv) + sizeof(u32)) { + ret = -EINVAL; + goto out; + } + + ptr = buf; + tag = FIELD_GET(WMI_TLV_TAG, *ptr); + + /* pdev/vdev id start after TLV header */ + ptr++; + + if (tag == WMI_TAG_PDEV_SET_PARAM_CMD) + *ptr = ar->pdev->pdev_id; + + if (ar->ab->fw_mode != ATH11K_FIRMWARE_MODE_FTM && + (tag == WMI_TAG_VDEV_SET_PARAM_CMD || tag == WMI_TAG_UNIT_TEST_CMD)) { + if (vif) { + arvif = (struct ath11k_vif *)vif->drv_priv; + *ptr = arvif->vdev_id; + } else { + ret = -EINVAL; + goto out; + } + } + ath11k_dbg(ar->ab, ATH11K_DBG_TESTMODE, - "testmode cmd wmi cmd_id %d buf %pK buf_len %d\n", - cmd_id, buf, buf_len); + "cmd wmi cmd_id %d buf length %d\n", + cmd_id, buf_len); ath11k_dbg_dump(ar->ab, ATH11K_DBG_TESTMODE, NULL, "", buf, buf_len); @@ -173,6 +387,91 @@ static int ath11k_tm_cmd_wmi(struct ath11k *ar, struct nlattr *tb[]) return ret; } +static int ath11k_tm_cmd_wmi_ftm(struct ath11k *ar, struct nlattr *tb[]) +{ + struct ath11k_pdev_wmi *wmi = ar->wmi; + struct ath11k_base *ab = ar->ab; + struct sk_buff *skb; + u32 cmd_id, buf_len, hdr_info; + int ret; + void *buf; + u8 segnumber = 0, seginfo; + u16 chunk_len, total_bytes, num_segments; + u8 *bufpos; + struct wmi_ftm_cmd *ftm_cmd; + + set_bit(ATH11K_FLAG_FTM_SEGMENTED, &ab->dev_flags); + + mutex_lock(&ar->conf_mutex); + + if (ar->state != ATH11K_STATE_FTM) { + ret = -ENETDOWN; + goto out; + } + + if (!tb[ATH11K_TM_ATTR_DATA]) { + ret = -EINVAL; + goto out; + } + + buf = nla_data(tb[ATH11K_TM_ATTR_DATA]); + buf_len = nla_len(tb[ATH11K_TM_ATTR_DATA]); + cmd_id = WMI_PDEV_UTF_CMDID; + + ath11k_dbg(ar->ab, ATH11K_DBG_TESTMODE, + "cmd wmi ftm cmd_id %d buffer length %d\n", + cmd_id, buf_len); + ath11k_dbg_dump(ar->ab, ATH11K_DBG_TESTMODE, NULL, "", buf, buf_len); + + bufpos = buf; + total_bytes = buf_len; + num_segments = total_bytes / MAX_WMI_UTF_LEN; + + if (buf_len - (num_segments * MAX_WMI_UTF_LEN)) + num_segments++; + + while (buf_len) { + chunk_len = min_t(u16, buf_len, MAX_WMI_UTF_LEN); + + skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, (chunk_len + + sizeof(struct wmi_ftm_cmd))); + if (!skb) { + ret = -ENOMEM; + goto out; + } + + ftm_cmd = (struct wmi_ftm_cmd *)skb->data; + hdr_info = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_ARRAY_BYTE) | + FIELD_PREP(WMI_TLV_LEN, (chunk_len + + sizeof(struct wmi_ftm_seg_hdr))); + ftm_cmd->tlv_header = hdr_info; + ftm_cmd->seg_hdr.len = total_bytes; + ftm_cmd->seg_hdr.msgref = ar->ftm_msgref; + seginfo = FIELD_PREP(ATH11K_FTM_SEGHDR_TOTAL_SEGMENTS, num_segments) | + FIELD_PREP(ATH11K_FTM_SEGHDR_CURRENT_SEQ, segnumber); + ftm_cmd->seg_hdr.segmentinfo = seginfo; + segnumber++; + + memcpy(&ftm_cmd->data, bufpos, chunk_len); + + ret = ath11k_wmi_cmd_send(wmi, skb, cmd_id); + if (ret) { + ath11k_warn(ar->ab, "failed to send wmi ftm command: %d\n", ret); + goto out; + } + + buf_len -= chunk_len; + bufpos += chunk_len; + } + + ar->ftm_msgref++; + ret = 0; + +out: + mutex_unlock(&ar->conf_mutex); + return ret; +} + int ath11k_tm_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif, void *data, int len) { @@ -192,7 +491,11 @@ int ath11k_tm_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif, case ATH11K_TM_CMD_GET_VERSION: return ath11k_tm_cmd_get_version(ar, tb); case ATH11K_TM_CMD_WMI: - return ath11k_tm_cmd_wmi(ar, tb); + return ath11k_tm_cmd_wmi(ar, tb, vif); + case ATH11K_TM_CMD_TESTMODE_START: + return ath11k_tm_cmd_testmode_start(ar, tb); + case ATH11K_TM_CMD_WMI_FTM: + return ath11k_tm_cmd_wmi_ftm(ar, tb); default: return -EOPNOTSUPP; } diff --git a/drivers/net/wireless/ath/ath11k/testmode.h b/drivers/net/wireless/ath/ath11k/testmode.h index aaa122ed90697fecf67ce3926c54263dcb32921c..2f62f2c4422f4d1b7af25497600df28a465cdff8 100644 --- a/drivers/net/wireless/ath/ath11k/testmode.h +++ b/drivers/net/wireless/ath/ath11k/testmode.h @@ -1,22 +1,22 @@ /* SPDX-License-Identifier: BSD-3-Clause-Clear */ /* * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved. */ #include "core.h" #ifdef CONFIG_NL80211_TESTMODE -bool ath11k_tm_event_wmi(struct ath11k *ar, u32 cmd_id, struct sk_buff *skb); +void ath11k_tm_wmi_event(struct ath11k_base *ab, u32 cmd_id, struct sk_buff *skb); int ath11k_tm_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif, void *data, int len); #else -static inline bool ath11k_tm_event_wmi(struct ath11k *ar, u32 cmd_id, +static inline void ath11k_tm_wmi_event(struct ath11k_base *ab, u32 cmd_id, struct sk_buff *skb) { - return false; } static inline int ath11k_tm_cmd(struct ieee80211_hw *hw, diff --git a/drivers/net/wireless/ath/ath11k/testmode_i.h b/drivers/net/wireless/ath/ath11k/testmode_i.h index 4bae2a9eeea4f09197fdb6d42aae681b69adbeb1..91b83873d66085023ef0af1bb63e58a54465ae02 100644 --- a/drivers/net/wireless/ath/ath11k/testmode_i.h +++ b/drivers/net/wireless/ath/ath11k/testmode_i.h @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: BSD-3-Clause-Clear */ /* * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved. */ /* "API" level of the ath11k testmode interface. Bump it after every @@ -11,9 +12,10 @@ /* Bump this after every _compatible_ interface change, for example * addition of a new command or an attribute. */ -#define ATH11K_TESTMODE_VERSION_MINOR 0 +#define ATH11K_TESTMODE_VERSION_MINOR 1 #define ATH11K_TM_DATA_MAX_LEN 5000 +#define ATH11K_FTM_EVENT_MAX_BUF_LENGTH 2048 enum ath11k_tm_attr { __ATH11K_TM_ATTR_INVALID = 0, @@ -47,4 +49,18 @@ enum ath11k_tm_cmd { * ATH11K_TM_ATTR_DATA. */ ATH11K_TM_CMD_WMI = 1, + + /* Boots the UTF firmware, the netdev interface must be down at the + * time. + */ + ATH11K_TM_CMD_TESTMODE_START = 2, + + /* The command used to transmit a FTM WMI command to the firmware + * and the event to receive WMI events from the firmware. The data + * received only contain the payload, need to add the tlv header + * and send the cmd to firmware with command id WMI_PDEV_UTF_CMDID. + * The data payload size could be large and the driver needs to + * send segmented data to firmware. + */ + ATH11K_TM_CMD_WMI_FTM = 3, }; diff --git a/drivers/net/wireless/ath/ath11k/wmi.c b/drivers/net/wireless/ath/ath11k/wmi.c index d0b59bc2905a9b1c139efbf9418011d5692e6edb..23ad6825e5be584fd37d6c9d553d7a11779236e8 100644 --- a/drivers/net/wireless/ath/ath11k/wmi.c +++ b/drivers/net/wireless/ath/ath11k/wmi.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: BSD-3-Clause-Clear /* * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. - * Copyright (c) 2021, Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2021, 2023 Qualcomm Innovation Center, Inc. All rights reserved. */ #include #include @@ -19,6 +19,7 @@ #include "mac.h" #include "hw.h" #include "peer.h" +#include "testmode.h" struct wmi_tlv_policy { size_t min_len; @@ -237,9 +238,8 @@ static int ath11k_wmi_tlv_parse(struct ath11k_base *ar, const void **tb, (void *)tb); } -static const void ** -ath11k_wmi_tlv_parse_alloc(struct ath11k_base *ab, const void *ptr, - size_t len, gfp_t gfp) +const void **ath11k_wmi_tlv_parse_alloc(struct ath11k_base *ab, const void *ptr, + size_t len, gfp_t gfp) { const void **tb; int ret; @@ -606,6 +606,8 @@ static int ath11k_service_ready_event(struct ath11k_base *ab, struct sk_buff *sk return ret; } + ath11k_dbg(ab, ATH11K_DBG_WMI, "event service ready"); + return 0; } @@ -690,6 +692,8 @@ int ath11k_wmi_mgmt_send(struct ath11k *ar, u32 vdev_id, u32 buf_id, dev_kfree_skb(skb); } + ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "cmd mgmt tx send"); + return ret; } @@ -724,6 +728,9 @@ int ath11k_wmi_vdev_create(struct ath11k *ar, u8 *macaddr, cmd->vdev_subtype = param->subtype; cmd->num_cfg_txrx_streams = WMI_NUM_SUPPORTED_BAND_MAX; cmd->pdev_id = param->pdev_id; + cmd->mbssid_flags = param->mbssid_flags; + cmd->mbssid_tx_vdev_id = param->mbssid_tx_vdev_id; + ether_addr_copy(cmd->vdev_macaddr.addr, macaddr); ptr = skb->data + sizeof(*cmd); @@ -763,7 +770,7 @@ int ath11k_wmi_vdev_create(struct ath11k *ar, u8 *macaddr, } ath11k_dbg(ar->ab, ATH11K_DBG_WMI, - "WMI vdev create: id %d type %d subtype %d macaddr %pM pdevid %d\n", + "cmd vdev create id %d type %d subtype %d macaddr %pM pdevid %d\n", param->if_id, param->type, param->subtype, macaddr, param->pdev_id); @@ -792,7 +799,7 @@ int ath11k_wmi_vdev_delete(struct ath11k *ar, u8 vdev_id) dev_kfree_skb(skb); } - ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "WMI vdev delete id %d\n", vdev_id); + ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "cmd vdev delete id %d\n", vdev_id); return ret; } @@ -820,7 +827,7 @@ int ath11k_wmi_vdev_stop(struct ath11k *ar, u8 vdev_id) dev_kfree_skb(skb); } - ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "WMI vdev stop id 0x%x\n", vdev_id); + ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "cmd vdev stop id 0x%x\n", vdev_id); return ret; } @@ -848,7 +855,7 @@ int ath11k_wmi_vdev_down(struct ath11k *ar, u8 vdev_id) dev_kfree_skb(skb); } - ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "WMI vdev down id 0x%x\n", vdev_id); + ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "cmd vdev down id 0x%x\n", vdev_id); return ret; } @@ -941,6 +948,8 @@ int ath11k_wmi_vdev_start(struct ath11k *ar, struct wmi_vdev_start_req_arg *arg, cmd->cac_duration_ms = arg->cac_duration_ms; cmd->regdomain = arg->regdomain; cmd->he_ops = arg->he_ops; + cmd->mbssid_flags = arg->mbssid_flags; + cmd->mbssid_tx_vdev_id = arg->mbssid_tx_vdev_id; if (!restart) { if (arg->ssid) { @@ -989,14 +998,15 @@ int ath11k_wmi_vdev_start(struct ath11k *ar, struct wmi_vdev_start_req_arg *arg, dev_kfree_skb(skb); } - ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "vdev %s id 0x%x freq 0x%x mode 0x%x\n", + ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "cmd vdev %s id 0x%x freq 0x%x mode 0x%x\n", restart ? "restart" : "start", arg->vdev_id, arg->channel.freq, arg->channel.mode); return ret; } -int ath11k_wmi_vdev_up(struct ath11k *ar, u32 vdev_id, u32 aid, const u8 *bssid) +int ath11k_wmi_vdev_up(struct ath11k *ar, u32 vdev_id, u32 aid, const u8 *bssid, + u8 *tx_bssid, u32 nontx_profile_idx, u32 nontx_profile_cnt) { struct ath11k_pdev_wmi *wmi = ar->wmi; struct wmi_vdev_up_cmd *cmd; @@ -1020,14 +1030,19 @@ int ath11k_wmi_vdev_up(struct ath11k *ar, u32 vdev_id, u32 aid, const u8 *bssid) ether_addr_copy(cmd->vdev_bssid.addr, bssid); + cmd->nontx_profile_idx = nontx_profile_idx; + cmd->nontx_profile_cnt = nontx_profile_cnt; + if (tx_bssid) + ether_addr_copy(cmd->tx_vdev_bssid.addr, tx_bssid); + if (arvif && arvif->vif->type == NL80211_IFTYPE_STATION) { bss_conf = &arvif->vif->bss_conf; if (bss_conf->nontransmitted) { - ether_addr_copy(cmd->trans_bssid.addr, + ether_addr_copy(cmd->tx_vdev_bssid.addr, bss_conf->transmitter_bssid); - cmd->profile_idx = bss_conf->bssid_index; - cmd->profile_num = bss_conf->bssid_indicator; + cmd->nontx_profile_idx = bss_conf->bssid_index; + cmd->nontx_profile_cnt = bss_conf->bssid_indicator; } } @@ -1038,7 +1053,7 @@ int ath11k_wmi_vdev_up(struct ath11k *ar, u32 vdev_id, u32 aid, const u8 *bssid) } ath11k_dbg(ar->ab, ATH11K_DBG_WMI, - "WMI mgmt vdev up id 0x%x assoc id %d bssid %pM\n", + "cmd vdev up id 0x%x assoc id %d bssid %pM\n", vdev_id, aid, bssid); return ret; @@ -1071,7 +1086,7 @@ int ath11k_wmi_send_peer_create_cmd(struct ath11k *ar, } ath11k_dbg(ar->ab, ATH11K_DBG_WMI, - "WMI peer create vdev_id %d peer_addr %pM\n", + "cmd peer create vdev_id %d peer_addr %pM\n", param->vdev_id, param->peer_addr); return ret; @@ -1096,16 +1111,16 @@ int ath11k_wmi_send_peer_delete_cmd(struct ath11k *ar, ether_addr_copy(cmd->peer_macaddr.addr, peer_addr); cmd->vdev_id = vdev_id; - ath11k_dbg(ar->ab, ATH11K_DBG_WMI, - "WMI peer delete vdev_id %d peer_addr %pM\n", - vdev_id, peer_addr); - ret = ath11k_wmi_cmd_send(wmi, skb, WMI_PEER_DELETE_CMDID); if (ret) { ath11k_warn(ar->ab, "failed to send WMI_PEER_DELETE cmd\n"); dev_kfree_skb(skb); } + ath11k_dbg(ar->ab, ATH11K_DBG_WMI, + "cmd peer delete vdev_id %d peer_addr %pM\n", + vdev_id, peer_addr); + return ret; } @@ -1134,11 +1149,6 @@ int ath11k_wmi_send_pdev_set_regdomain(struct ath11k *ar, cmd->dfs_domain = param->dfs_domain; cmd->pdev_id = param->pdev_id; - ath11k_dbg(ar->ab, ATH11K_DBG_WMI, - "WMI pdev regd rd %d rd2g %d rd5g %d domain %d pdev id %d\n", - param->current_rd_in_use, param->current_rd_2g, - param->current_rd_5g, param->dfs_domain, param->pdev_id); - ret = ath11k_wmi_cmd_send(wmi, skb, WMI_PDEV_SET_REGDOMAIN_CMDID); if (ret) { ath11k_warn(ar->ab, @@ -1146,6 +1156,11 @@ int ath11k_wmi_send_pdev_set_regdomain(struct ath11k *ar, dev_kfree_skb(skb); } + ath11k_dbg(ar->ab, ATH11K_DBG_WMI, + "cmd pdev regd rd %d rd2g %d rd5g %d domain %d pdev id %d\n", + param->current_rd_in_use, param->current_rd_2g, + param->current_rd_5g, param->dfs_domain, param->pdev_id); + return ret; } @@ -1176,7 +1191,7 @@ int ath11k_wmi_set_peer_param(struct ath11k *ar, const u8 *peer_addr, } ath11k_dbg(ar->ab, ATH11K_DBG_WMI, - "WMI vdev %d peer 0x%pM set param %d value %d\n", + "cmd peer set param vdev %d peer 0x%pM set param %d value %d\n", vdev_id, peer_addr, param_id, param_val); return ret; @@ -1211,7 +1226,7 @@ int ath11k_wmi_send_peer_flush_tids_cmd(struct ath11k *ar, } ath11k_dbg(ar->ab, ATH11K_DBG_WMI, - "WMI peer flush vdev_id %d peer_addr %pM tids %08x\n", + "cmd peer flush tids vdev_id %d peer_addr %pM tids %08x\n", param->vdev_id, peer_addr, param->peer_tid_bitmap); return ret; @@ -1254,7 +1269,7 @@ int ath11k_wmi_peer_rx_reorder_queue_setup(struct ath11k *ar, } ath11k_dbg(ar->ab, ATH11K_DBG_WMI, - "wmi rx reorder queue setup addr %pM vdev_id %d tid %d\n", + "cmd peer reorder queue setup addr %pM vdev_id %d tid %d\n", addr, vdev_id, tid); return ret; @@ -1282,10 +1297,6 @@ ath11k_wmi_rx_reord_queue_remove(struct ath11k *ar, cmd->vdev_id = param->vdev_id; cmd->tid_mask = param->peer_tid_bitmap; - ath11k_dbg(ar->ab, ATH11K_DBG_WMI, - "%s: peer_macaddr %pM vdev_id %d, tid_map %d", __func__, - param->peer_macaddr, param->vdev_id, param->peer_tid_bitmap); - ret = ath11k_wmi_cmd_send(wmi, skb, WMI_PEER_REORDER_QUEUE_REMOVE_CMDID); if (ret) { @@ -1294,6 +1305,10 @@ ath11k_wmi_rx_reord_queue_remove(struct ath11k *ar, dev_kfree_skb(skb); } + ath11k_dbg(ar->ab, ATH11K_DBG_WMI, + "cmd peer reorder queue remove peer_macaddr %pM vdev_id %d tid_map %d", + param->peer_macaddr, param->vdev_id, param->peer_tid_bitmap); + return ret; } @@ -1323,7 +1338,7 @@ int ath11k_wmi_pdev_set_param(struct ath11k *ar, u32 param_id, } ath11k_dbg(ar->ab, ATH11K_DBG_WMI, - "WMI pdev set param %d pdev id %d value %d\n", + "cmd pdev set param %d pdev id %d value %d\n", param_id, pdev_id, param_value); return ret; @@ -1354,7 +1369,7 @@ int ath11k_wmi_pdev_set_ps_mode(struct ath11k *ar, int vdev_id, } ath11k_dbg(ar->ab, ATH11K_DBG_WMI, - "WMI vdev set psmode %d vdev id %d\n", + "cmd sta powersave mode psmode %d vdev id %d\n", psmode, vdev_id); return ret; @@ -1387,7 +1402,7 @@ int ath11k_wmi_pdev_suspend(struct ath11k *ar, u32 suspend_opt, } ath11k_dbg(ar->ab, ATH11K_DBG_WMI, - "WMI pdev suspend pdev_id %d\n", pdev_id); + "cmd pdev suspend pdev_id %d\n", pdev_id); return ret; } @@ -1409,15 +1424,15 @@ int ath11k_wmi_pdev_resume(struct ath11k *ar, u32 pdev_id) FIELD_PREP(WMI_TLV_LEN, sizeof(*cmd) - TLV_HDR_SIZE); cmd->pdev_id = pdev_id; - ath11k_dbg(ar->ab, ATH11K_DBG_WMI, - "WMI pdev resume pdev id %d\n", pdev_id); - ret = ath11k_wmi_cmd_send(wmi, skb, WMI_PDEV_RESUME_CMDID); if (ret) { ath11k_warn(ar->ab, "failed to send WMI_PDEV_RESUME cmd\n"); dev_kfree_skb(skb); } + ath11k_dbg(ar->ab, ATH11K_DBG_WMI, + "cmd pdev resume pdev id %d\n", pdev_id); + return ret; } @@ -1445,9 +1460,6 @@ int ath11k_wmi_pdev_bss_chan_info_request(struct ath11k *ar, cmd->req_type = type; cmd->pdev_id = ar->pdev->pdev_id; - ath11k_dbg(ar->ab, ATH11K_DBG_WMI, - "WMI bss chan info req type %d\n", type); - ret = ath11k_wmi_cmd_send(wmi, skb, WMI_PDEV_BSS_CHAN_INFO_REQUEST_CMDID); if (ret) { @@ -1456,6 +1468,9 @@ int ath11k_wmi_pdev_bss_chan_info_request(struct ath11k *ar, dev_kfree_skb(skb); } + ath11k_dbg(ar->ab, ATH11K_DBG_WMI, + "cmd pdev bss chan info request type %d\n", type); + return ret; } @@ -1488,7 +1503,7 @@ int ath11k_wmi_send_set_ap_ps_param_cmd(struct ath11k *ar, u8 *peer_addr, } ath11k_dbg(ar->ab, ATH11K_DBG_WMI, - "WMI set ap ps vdev id %d peer %pM param %d value %d\n", + "cmd ap ps peer param vdev id %d peer %pM param %d value %d\n", param->vdev_id, peer_addr, param->param, param->value); return ret; @@ -1515,16 +1530,16 @@ int ath11k_wmi_set_sta_ps_param(struct ath11k *ar, u32 vdev_id, cmd->param = param; cmd->value = param_value; - ath11k_dbg(ar->ab, ATH11K_DBG_WMI, - "WMI set sta ps vdev_id %d param %d value %d\n", - vdev_id, param, param_value); - ret = ath11k_wmi_cmd_send(wmi, skb, WMI_STA_POWERSAVE_PARAM_CMDID); if (ret) { ath11k_warn(ar->ab, "failed to send WMI_STA_POWERSAVE_PARAM_CMDID"); dev_kfree_skb(skb); } + ath11k_dbg(ar->ab, ATH11K_DBG_WMI, + "cmd set powersave param vdev_id %d param %d value %d\n", + vdev_id, param, param_value); + return ret; } @@ -1554,6 +1569,9 @@ int ath11k_wmi_force_fw_hang_cmd(struct ath11k *ar, u32 type, u32 delay_time_ms) ath11k_warn(ar->ab, "Failed to send WMI_FORCE_FW_HANG_CMDID"); dev_kfree_skb(skb); } + + ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "cmd force fw hang"); + return ret; } @@ -1585,7 +1603,7 @@ int ath11k_wmi_vdev_set_param_cmd(struct ath11k *ar, u32 vdev_id, } ath11k_dbg(ar->ab, ATH11K_DBG_WMI, - "WMI vdev id 0x%x set param %d value %d\n", + "cmd vdev set param vdev 0x%x param %d value %d\n", vdev_id, param_id, param_value); return ret; @@ -1618,7 +1636,7 @@ int ath11k_wmi_send_stats_request_cmd(struct ath11k *ar, } ath11k_dbg(ar->ab, ATH11K_DBG_WMI, - "WMI request stats 0x%x vdev id %d pdev id %d\n", + "cmd request stats 0x%x vdev id %d pdev id %d\n", param->stats_id, param->vdev_id, param->pdev_id); return ret; @@ -1647,7 +1665,7 @@ int ath11k_wmi_send_pdev_temperature_cmd(struct ath11k *ar) } ath11k_dbg(ar->ab, ATH11K_DBG_WMI, - "WMI pdev get temperature for pdev_id %d\n", ar->pdev->pdev_id); + "cmd pdev get temperature for pdev_id %d\n", ar->pdev->pdev_id); return ret; } @@ -1672,10 +1690,6 @@ int ath11k_wmi_send_bcn_offload_control_cmd(struct ath11k *ar, cmd->vdev_id = vdev_id; cmd->bcn_ctrl_op = bcn_ctrl_op; - ath11k_dbg(ar->ab, ATH11K_DBG_WMI, - "WMI bcn ctrl offload vdev id %d ctrl_op %d\n", - vdev_id, bcn_ctrl_op); - ret = ath11k_wmi_cmd_send(wmi, skb, WMI_BCN_OFFLOAD_CTRL_CMDID); if (ret) { ath11k_warn(ar->ab, @@ -1683,12 +1697,16 @@ int ath11k_wmi_send_bcn_offload_control_cmd(struct ath11k *ar, dev_kfree_skb(skb); } + ath11k_dbg(ar->ab, ATH11K_DBG_WMI, + "cmd bcn offload ctrl vdev id %d ctrl_op %d\n", + vdev_id, bcn_ctrl_op); + return ret; } int ath11k_wmi_bcn_tmpl(struct ath11k *ar, u32 vdev_id, struct ieee80211_mutable_offsets *offs, - struct sk_buff *bcn) + struct sk_buff *bcn, u32 ema_params) { struct ath11k_pdev_wmi *wmi = ar->wmi; struct wmi_bcn_tmpl_cmd *cmd; @@ -1726,6 +1744,8 @@ int ath11k_wmi_bcn_tmpl(struct ath11k *ar, u32 vdev_id, } cmd->buf_len = bcn->len; + cmd->mbssid_ie_offset = offs->mbssid_off; + cmd->ema_params = ema_params; ptr = skb->data + sizeof(*cmd); @@ -1750,6 +1770,8 @@ int ath11k_wmi_bcn_tmpl(struct ath11k *ar, u32 vdev_id, dev_kfree_skb(skb); } + ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "cmd bcn tmpl"); + return ret; } @@ -1799,7 +1821,7 @@ int ath11k_wmi_vdev_install_key(struct ath11k *ar, } ath11k_dbg(ar->ab, ATH11K_DBG_WMI, - "WMI vdev install key idx %d cipher %d len %d\n", + "cmd vdev install key idx %d cipher %d len %d\n", arg->key_idx, arg->key_cipher, arg->key_len); return ret; @@ -2035,7 +2057,7 @@ int ath11k_wmi_send_peer_assoc_cmd(struct ath11k *ar, } ath11k_dbg(ar->ab, ATH11K_DBG_WMI, - "wmi peer assoc vdev id %d assoc id %d peer mac %pM peer_flags %x rate_caps %x peer_caps %x listen_intval %d ht_caps %x max_mpdu %d nss %d phymode %d peer_mpdu_density %d vht_caps %x he cap_info %x he ops %x he cap_info_ext %x he phy %x %x %x peer_bw_rxnss_override %x\n", + "cmd peer assoc vdev id %d assoc id %d peer mac %pM peer_flags %x rate_caps %x peer_caps %x listen_intval %d ht_caps %x max_mpdu %d nss %d phymode %d peer_mpdu_density %d vht_caps %x he cap_info %x he ops %x he cap_info_ext %x he phy %x %x %x peer_bw_rxnss_override %x\n", cmd->vdev_id, cmd->peer_associd, param->peer_mac, cmd->peer_flags, cmd->peer_rate_caps, cmd->peer_caps, cmd->peer_listen_intval, cmd->peer_ht_caps, @@ -2352,6 +2374,8 @@ int ath11k_wmi_send_scan_start_cmd(struct ath11k *ar, dev_kfree_skb(skb); } + ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "cmd start scan"); + return ret; } @@ -2400,6 +2424,8 @@ int ath11k_wmi_send_scan_stop_cmd(struct ath11k *ar, dev_kfree_skb(skb); } + ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "cmd stop scan"); + return ret; } @@ -2444,7 +2470,7 @@ int ath11k_wmi_send_scan_chan_list_cmd(struct ath11k *ar, cmd->flags |= WMI_APPEND_TO_EXISTING_CHAN_LIST_FLAG; ath11k_dbg(ar->ab, ATH11K_DBG_WMI, - "WMI no.of chan = %d len = %d pdev_id = %d num_sends = %d\n", + "no.of chan = %d len = %d pdev_id = %d num_sends = %d\n", num_send_chans, len, cmd->pdev_id, num_sends); ptr = skb->data + sizeof(*cmd); @@ -2503,7 +2529,7 @@ int ath11k_wmi_send_scan_chan_list_cmd(struct ath11k *ar, tchan_info->maxregpower); ath11k_dbg(ar->ab, ATH11K_DBG_WMI, - "WMI chan scan list chan[%d] = %u, chan_info->info %8x\n", + "chan scan list chan[%d] = %u, chan_info->info %8x\n", i, chan_info->mhz, chan_info->info); ptr += sizeof(*chan_info); @@ -2518,6 +2544,9 @@ int ath11k_wmi_send_scan_chan_list_cmd(struct ath11k *ar, return ret; } + ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "cmd scan chan list channels %d", + num_send_chans); + num_sends++; } @@ -2577,7 +2606,7 @@ int ath11k_wmi_send_wmm_update_cmd_tlv(struct ath11k *ar, u32 vdev_id, wmm_param->no_ack = wmi_wmm_arg->no_ack; ath11k_dbg(ar->ab, ATH11K_DBG_WMI, - "wmi wmm set ac %d aifs %d cwmin %d cwmax %d txop %d acm %d no_ack %d\n", + "wmm set ac %d aifs %d cwmin %d cwmax %d txop %d acm %d no_ack %d\n", ac, wmm_param->aifs, wmm_param->cwmin, wmm_param->cwmax, wmm_param->txoplimit, wmm_param->acm, wmm_param->no_ack); @@ -2590,6 +2619,8 @@ int ath11k_wmi_send_wmm_update_cmd_tlv(struct ath11k *ar, u32 vdev_id, dev_kfree_skb(skb); } + ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "cmd vdev set wmm params"); + return ret; } @@ -2613,9 +2644,6 @@ int ath11k_wmi_send_dfs_phyerr_offload_enable_cmd(struct ath11k *ar, cmd->pdev_id = pdev_id; - ath11k_dbg(ar->ab, ATH11K_DBG_WMI, - "WMI dfs phy err offload enable pdev id %d\n", pdev_id); - ret = ath11k_wmi_cmd_send(wmi, skb, WMI_PDEV_DFS_PHYERR_OFFLOAD_ENABLE_CMDID); if (ret) { @@ -2624,6 +2652,9 @@ int ath11k_wmi_send_dfs_phyerr_offload_enable_cmd(struct ath11k *ar, dev_kfree_skb(skb); } + ath11k_dbg(ar->ab, ATH11K_DBG_WMI, + "cmd pdev dfs phyerr offload enable pdev id %d\n", pdev_id); + return ret; } @@ -2648,10 +2679,6 @@ int ath11k_wmi_delba_send(struct ath11k *ar, u32 vdev_id, const u8 *mac, cmd->initiator = initiator; cmd->reasoncode = reason; - ath11k_dbg(ar->ab, ATH11K_DBG_WMI, - "wmi delba send vdev_id 0x%X mac_addr %pM tid %u initiator %u reason %u\n", - vdev_id, mac, tid, initiator, reason); - ret = ath11k_wmi_cmd_send(wmi, skb, WMI_DELBA_SEND_CMDID); if (ret) { @@ -2660,6 +2687,10 @@ int ath11k_wmi_delba_send(struct ath11k *ar, u32 vdev_id, const u8 *mac, dev_kfree_skb(skb); } + ath11k_dbg(ar->ab, ATH11K_DBG_WMI, + "cmd delba send vdev_id 0x%X mac_addr %pM tid %u initiator %u reason %u\n", + vdev_id, mac, tid, initiator, reason); + return ret; } @@ -2684,10 +2715,6 @@ int ath11k_wmi_addba_set_resp(struct ath11k *ar, u32 vdev_id, const u8 *mac, cmd->tid = tid; cmd->statuscode = status; - ath11k_dbg(ar->ab, ATH11K_DBG_WMI, - "wmi addba set resp vdev_id 0x%X mac_addr %pM tid %u status %u\n", - vdev_id, mac, tid, status); - ret = ath11k_wmi_cmd_send(wmi, skb, WMI_ADDBA_SET_RESP_CMDID); if (ret) { @@ -2696,6 +2723,10 @@ int ath11k_wmi_addba_set_resp(struct ath11k *ar, u32 vdev_id, const u8 *mac, dev_kfree_skb(skb); } + ath11k_dbg(ar->ab, ATH11K_DBG_WMI, + "cmd addba set resp vdev_id 0x%X mac_addr %pM tid %u status %u\n", + vdev_id, mac, tid, status); + return ret; } @@ -2719,10 +2750,6 @@ int ath11k_wmi_addba_send(struct ath11k *ar, u32 vdev_id, const u8 *mac, cmd->tid = tid; cmd->buffersize = buf_size; - ath11k_dbg(ar->ab, ATH11K_DBG_WMI, - "wmi addba send vdev_id 0x%X mac_addr %pM tid %u bufsize %u\n", - vdev_id, mac, tid, buf_size); - ret = ath11k_wmi_cmd_send(wmi, skb, WMI_ADDBA_SEND_CMDID); if (ret) { @@ -2731,6 +2758,10 @@ int ath11k_wmi_addba_send(struct ath11k *ar, u32 vdev_id, const u8 *mac, dev_kfree_skb(skb); } + ath11k_dbg(ar->ab, ATH11K_DBG_WMI, + "cmd addba send vdev_id 0x%X mac_addr %pM tid %u bufsize %u\n", + vdev_id, mac, tid, buf_size); + return ret; } @@ -2752,10 +2783,6 @@ int ath11k_wmi_addba_clear_resp(struct ath11k *ar, u32 vdev_id, const u8 *mac) cmd->vdev_id = vdev_id; ether_addr_copy(cmd->peer_macaddr.addr, mac); - ath11k_dbg(ar->ab, ATH11K_DBG_WMI, - "wmi addba clear resp vdev_id 0x%X mac_addr %pM\n", - vdev_id, mac); - ret = ath11k_wmi_cmd_send(wmi, skb, WMI_ADDBA_CLEAR_RESP_CMDID); if (ret) { @@ -2764,6 +2791,10 @@ int ath11k_wmi_addba_clear_resp(struct ath11k *ar, u32 vdev_id, const u8 *mac) dev_kfree_skb(skb); } + ath11k_dbg(ar->ab, ATH11K_DBG_WMI, + "cmd addba clear resp vdev_id 0x%X mac_addr %pM\n", + vdev_id, mac); + return ret; } @@ -2812,6 +2843,8 @@ int ath11k_wmi_pdev_peer_pktlog_filter(struct ath11k *ar, u8 *addr, u8 enable) dev_kfree_skb(skb); } + ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "cmd pdev pktlog filter"); + return ret; } @@ -2851,21 +2884,27 @@ ath11k_wmi_send_init_country_cmd(struct ath11k *ar, cmd->cc_info.regdom_id = init_cc_params.cc_info.regdom_id; break; default: + ath11k_warn(ar->ab, "unknown cc params flags: 0x%x", + init_cc_params.flags); ret = -EINVAL; - goto out; + goto err; } ret = ath11k_wmi_cmd_send(wmi, skb, WMI_SET_INIT_COUNTRY_CMDID); - -out: if (ret) { ath11k_warn(ar->ab, "failed to send WMI_SET_INIT_COUNTRY CMD :%d\n", ret); - dev_kfree_skb(skb); + goto err; } + ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "cmd set init country"); + + return 0; + +err: + dev_kfree_skb(skb); return ret; } @@ -2888,20 +2927,20 @@ int ath11k_wmi_send_set_current_country_cmd(struct ath11k *ar, cmd->pdev_id = ar->pdev->pdev_id; memcpy(&cmd->new_alpha2, ¶m->alpha2, 3); - ret = ath11k_wmi_cmd_send(wmi, skb, WMI_SET_CURRENT_COUNTRY_CMDID); - - ath11k_dbg(ar->ab, ATH11K_DBG_WMI, - "set current country pdev id %d alpha2 %c%c\n", - ar->pdev->pdev_id, - param->alpha2[0], - param->alpha2[1]); + ret = ath11k_wmi_cmd_send(wmi, skb, WMI_SET_CURRENT_COUNTRY_CMDID); if (ret) { ath11k_warn(ar->ab, "failed to send WMI_SET_CURRENT_COUNTRY_CMDID: %d\n", ret); dev_kfree_skb(skb); } + ath11k_dbg(ar->ab, ATH11K_DBG_WMI, + "cmd set current country pdev id %d alpha2 %c%c\n", + ar->pdev->pdev_id, + param->alpha2[0], + param->alpha2[1]); + return ret; } @@ -2962,7 +3001,7 @@ ath11k_wmi_send_thermal_mitigation_param_cmd(struct ath11k *ar, } ath11k_dbg(ar->ab, ATH11K_DBG_WMI, - "WMI vdev set thermal throt pdev_id %d enable %d dc %d dc_per_event %x levels %d\n", + "cmd therm throt set conf pdev_id %d enable %d dc %d dc_per_event %x levels %d\n", ar->pdev->pdev_id, param->enable, param->dc, param->dc_per_event, THERMAL_LEVELS); @@ -2989,20 +3028,20 @@ int ath11k_wmi_send_11d_scan_start_cmd(struct ath11k *ar, cmd->vdev_id = param->vdev_id; cmd->scan_period_msec = param->scan_period_msec; cmd->start_interval_msec = param->start_interval_msec; - ret = ath11k_wmi_cmd_send(wmi, skb, WMI_11D_SCAN_START_CMDID); - - ath11k_dbg(ar->ab, ATH11K_DBG_WMI, - "send 11d scan start vdev id %d period %d ms internal %d ms\n", - cmd->vdev_id, - cmd->scan_period_msec, - cmd->start_interval_msec); + ret = ath11k_wmi_cmd_send(wmi, skb, WMI_11D_SCAN_START_CMDID); if (ret) { ath11k_warn(ar->ab, "failed to send WMI_11D_SCAN_START_CMDID: %d\n", ret); dev_kfree_skb(skb); } + ath11k_dbg(ar->ab, ATH11K_DBG_WMI, + "cmd 11d scan start vdev id %d period %d ms internal %d ms\n", + cmd->vdev_id, + cmd->scan_period_msec, + cmd->start_interval_msec); + return ret; } @@ -3023,18 +3062,18 @@ int ath11k_wmi_send_11d_scan_stop_cmd(struct ath11k *ar, u32 vdev_id) FIELD_PREP(WMI_TLV_LEN, sizeof(*cmd) - TLV_HDR_SIZE); cmd->vdev_id = vdev_id; - ret = ath11k_wmi_cmd_send(wmi, skb, WMI_11D_SCAN_STOP_CMDID); - - ath11k_dbg(ar->ab, ATH11K_DBG_WMI, - "send 11d scan stop vdev id %d\n", - cmd->vdev_id); + ret = ath11k_wmi_cmd_send(wmi, skb, WMI_11D_SCAN_STOP_CMDID); if (ret) { ath11k_warn(ar->ab, "failed to send WMI_11D_SCAN_STOP_CMDID: %d\n", ret); dev_kfree_skb(skb); } + ath11k_dbg(ar->ab, ATH11K_DBG_WMI, + "cmd 11d scan stop vdev id %d\n", + cmd->vdev_id); + return ret; } @@ -3065,6 +3104,8 @@ int ath11k_wmi_pdev_pktlog_enable(struct ath11k *ar, u32 pktlog_filter) dev_kfree_skb(skb); } + ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "cmd pdev pktlog enable"); + return ret; } @@ -3093,6 +3134,8 @@ int ath11k_wmi_pdev_pktlog_disable(struct ath11k *ar) dev_kfree_skb(skb); } + ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "cmd pdev pktlog disable"); + return ret; } @@ -3162,10 +3205,14 @@ int ath11k_wmi_send_twt_enable_cmd(struct ath11k *ar, u32 pdev_id, if (ret) { ath11k_warn(ab, "Failed to send WMI_TWT_ENABLE_CMDID"); dev_kfree_skb(skb); - } else { - ar->twt_enabled = 1; + return ret; } - return ret; + + ar->twt_enabled = 1; + + ath11k_dbg(ab, ATH11K_DBG_WMI, "cmd twt enable"); + + return 0; } int @@ -3192,10 +3239,14 @@ ath11k_wmi_send_twt_disable_cmd(struct ath11k *ar, u32 pdev_id) if (ret) { ath11k_warn(ab, "Failed to send WMI_TWT_DISABLE_CMDID"); dev_kfree_skb(skb); - } else { - ar->twt_enabled = 0; + return ret; } - return ret; + + ath11k_dbg(ab, ATH11K_DBG_WMI, "cmd twt disable"); + + ar->twt_enabled = 0; + + return 0; } int ath11k_wmi_send_twt_add_dialog_cmd(struct ath11k *ar, @@ -3234,21 +3285,22 @@ int ath11k_wmi_send_twt_add_dialog_cmd(struct ath11k *ar, if (params->flag_protection) cmd->flags |= WMI_TWT_ADD_DIALOG_FLAG_PROTECTION; - ath11k_dbg(ar->ab, ATH11K_DBG_WMI, - "wmi add twt dialog vdev %u dialog id %u wake interval %u mantissa %u wake duration %u service period offset %u flags 0x%x\n", - cmd->vdev_id, cmd->dialog_id, cmd->wake_intvl_us, - cmd->wake_intvl_mantis, cmd->wake_dura_us, cmd->sp_offset_us, - cmd->flags); - ret = ath11k_wmi_cmd_send(wmi, skb, WMI_TWT_ADD_DIALOG_CMDID); - if (ret) { ath11k_warn(ab, "failed to send wmi command to add twt dialog: %d", ret); dev_kfree_skb(skb); + return ret; } - return ret; + + ath11k_dbg(ar->ab, ATH11K_DBG_WMI, + "cmd twt add dialog vdev %u dialog id %u wake interval %u mantissa %u wake duration %u service period offset %u flags 0x%x\n", + cmd->vdev_id, cmd->dialog_id, cmd->wake_intvl_us, + cmd->wake_intvl_mantis, cmd->wake_dura_us, cmd->sp_offset_us, + cmd->flags); + + return 0; } int ath11k_wmi_send_twt_del_dialog_cmd(struct ath11k *ar, @@ -3274,18 +3326,20 @@ int ath11k_wmi_send_twt_del_dialog_cmd(struct ath11k *ar, ether_addr_copy(cmd->peer_macaddr.addr, params->peer_macaddr); cmd->dialog_id = params->dialog_id; - ath11k_dbg(ar->ab, ATH11K_DBG_WMI, - "wmi delete twt dialog vdev %u dialog id %u\n", - cmd->vdev_id, cmd->dialog_id); - ret = ath11k_wmi_cmd_send(wmi, skb, WMI_TWT_DEL_DIALOG_CMDID); if (ret) { ath11k_warn(ab, "failed to send wmi command to delete twt dialog: %d", ret); dev_kfree_skb(skb); + return ret; } - return ret; + + ath11k_dbg(ar->ab, ATH11K_DBG_WMI, + "cmd twt del dialog vdev %u dialog id %u\n", + cmd->vdev_id, cmd->dialog_id); + + return 0; } int ath11k_wmi_send_twt_pause_dialog_cmd(struct ath11k *ar, @@ -3312,18 +3366,20 @@ int ath11k_wmi_send_twt_pause_dialog_cmd(struct ath11k *ar, ether_addr_copy(cmd->peer_macaddr.addr, params->peer_macaddr); cmd->dialog_id = params->dialog_id; - ath11k_dbg(ar->ab, ATH11K_DBG_WMI, - "wmi pause twt dialog vdev %u dialog id %u\n", - cmd->vdev_id, cmd->dialog_id); - ret = ath11k_wmi_cmd_send(wmi, skb, WMI_TWT_PAUSE_DIALOG_CMDID); if (ret) { ath11k_warn(ab, "failed to send wmi command to pause twt dialog: %d", ret); dev_kfree_skb(skb); + return ret; } - return ret; + + ath11k_dbg(ar->ab, ATH11K_DBG_WMI, + "cmd twt pause dialog vdev %u dialog id %u\n", + cmd->vdev_id, cmd->dialog_id); + + return 0; } int ath11k_wmi_send_twt_resume_dialog_cmd(struct ath11k *ar, @@ -3352,19 +3408,21 @@ int ath11k_wmi_send_twt_resume_dialog_cmd(struct ath11k *ar, cmd->sp_offset_us = params->sp_offset_us; cmd->next_twt_size = params->next_twt_size; - ath11k_dbg(ar->ab, ATH11K_DBG_WMI, - "wmi resume twt dialog vdev %u dialog id %u service period offset %u next twt subfield size %u\n", - cmd->vdev_id, cmd->dialog_id, cmd->sp_offset_us, - cmd->next_twt_size); - ret = ath11k_wmi_cmd_send(wmi, skb, WMI_TWT_RESUME_DIALOG_CMDID); if (ret) { ath11k_warn(ab, "failed to send wmi command to resume twt dialog: %d", ret); dev_kfree_skb(skb); + return ret; } - return ret; + + ath11k_dbg(ar->ab, ATH11K_DBG_WMI, + "cmd twt resume dialog vdev %u dialog id %u service period offset %u next twt subfield size %u\n", + cmd->vdev_id, cmd->dialog_id, cmd->sp_offset_us, + cmd->next_twt_size); + + return 0; } int @@ -3398,8 +3456,12 @@ ath11k_wmi_send_obss_spr_cmd(struct ath11k *ar, u32 vdev_id, ath11k_warn(ab, "Failed to send WMI_PDEV_OBSS_PD_SPATIAL_REUSE_CMDID"); dev_kfree_skb(skb); + return ret; } - return ret; + + ath11k_dbg(ab, ATH11K_DBG_WMI, "cmd pdev obss pd spatial reuse"); + + return 0; } int @@ -3424,19 +3486,20 @@ ath11k_wmi_pdev_set_srg_bss_color_bitmap(struct ath11k *ar, u32 *bitmap) cmd->pdev_id = ar->pdev->pdev_id; memcpy(cmd->bitmap, bitmap, sizeof(cmd->bitmap)); - ath11k_dbg(ar->ab, ATH11K_DBG_WMI, - "obss pd pdev_id %d bss color bitmap %08x %08x\n", - cmd->pdev_id, cmd->bitmap[0], cmd->bitmap[1]); - ret = ath11k_wmi_cmd_send(wmi, skb, WMI_PDEV_SET_SRG_BSS_COLOR_BITMAP_CMDID); if (ret) { ath11k_warn(ab, "failed to send WMI_PDEV_SET_SRG_BSS_COLOR_BITMAP_CMDID"); dev_kfree_skb(skb); + return ret; } - return ret; + ath11k_dbg(ar->ab, ATH11K_DBG_WMI, + "cmd pdev set srg bss color bitmap pdev_id %d bss color bitmap %08x %08x\n", + cmd->pdev_id, cmd->bitmap[0], cmd->bitmap[1]); + + return 0; } int @@ -3462,19 +3525,20 @@ ath11k_wmi_pdev_set_srg_patial_bssid_bitmap(struct ath11k *ar, u32 *bitmap) cmd->pdev_id = ar->pdev->pdev_id; memcpy(cmd->bitmap, bitmap, sizeof(cmd->bitmap)); - ath11k_dbg(ar->ab, ATH11K_DBG_WMI, - "obss pd pdev_id %d partial bssid bitmap %08x %08x\n", - cmd->pdev_id, cmd->bitmap[0], cmd->bitmap[1]); - ret = ath11k_wmi_cmd_send(wmi, skb, WMI_PDEV_SET_SRG_PARTIAL_BSSID_BITMAP_CMDID); if (ret) { ath11k_warn(ab, "failed to send WMI_PDEV_SET_SRG_PARTIAL_BSSID_BITMAP_CMDID"); dev_kfree_skb(skb); + return ret; } - return ret; + ath11k_dbg(ar->ab, ATH11K_DBG_WMI, + "cmd pdev set srg partial bssid bitmap pdev_id %d partial bssid bitmap %08x %08x\n", + cmd->pdev_id, cmd->bitmap[0], cmd->bitmap[1]); + + return 0; } int @@ -3500,19 +3564,20 @@ ath11k_wmi_pdev_srg_obss_color_enable_bitmap(struct ath11k *ar, u32 *bitmap) cmd->pdev_id = ar->pdev->pdev_id; memcpy(cmd->bitmap, bitmap, sizeof(cmd->bitmap)); - ath11k_dbg(ar->ab, ATH11K_DBG_WMI, - "obss pd srg pdev_id %d bss color enable bitmap %08x %08x\n", - cmd->pdev_id, cmd->bitmap[0], cmd->bitmap[1]); - ret = ath11k_wmi_cmd_send(wmi, skb, WMI_PDEV_SET_SRG_OBSS_COLOR_ENABLE_BITMAP_CMDID); if (ret) { ath11k_warn(ab, "failed to send WMI_PDEV_SET_SRG_OBSS_COLOR_ENABLE_BITMAP_CMDID"); dev_kfree_skb(skb); + return ret; } - return ret; + ath11k_dbg(ar->ab, ATH11K_DBG_WMI, + "cmd pdev set srg obsscolor enable pdev_id %d bss color enable bitmap %08x %08x\n", + cmd->pdev_id, cmd->bitmap[0], cmd->bitmap[1]); + + return 0; } int @@ -3538,19 +3603,20 @@ ath11k_wmi_pdev_srg_obss_bssid_enable_bitmap(struct ath11k *ar, u32 *bitmap) cmd->pdev_id = ar->pdev->pdev_id; memcpy(cmd->bitmap, bitmap, sizeof(cmd->bitmap)); - ath11k_dbg(ar->ab, ATH11K_DBG_WMI, - "obss pd srg pdev_id %d bssid enable bitmap %08x %08x\n", - cmd->pdev_id, cmd->bitmap[0], cmd->bitmap[1]); - ret = ath11k_wmi_cmd_send(wmi, skb, WMI_PDEV_SET_SRG_OBSS_BSSID_ENABLE_BITMAP_CMDID); if (ret) { ath11k_warn(ab, "failed to send WMI_PDEV_SET_SRG_OBSS_BSSID_ENABLE_BITMAP_CMDID"); dev_kfree_skb(skb); + return ret; } - return ret; + ath11k_dbg(ar->ab, ATH11K_DBG_WMI, + "cmd pdev set srg obss bssid enable bitmap pdev_id %d bssid enable bitmap %08x %08x\n", + cmd->pdev_id, cmd->bitmap[0], cmd->bitmap[1]); + + return 0; } int @@ -3576,19 +3642,20 @@ ath11k_wmi_pdev_non_srg_obss_color_enable_bitmap(struct ath11k *ar, u32 *bitmap) cmd->pdev_id = ar->pdev->pdev_id; memcpy(cmd->bitmap, bitmap, sizeof(cmd->bitmap)); - ath11k_dbg(ar->ab, ATH11K_DBG_WMI, - "obss pd non_srg pdev_id %d bss color enable bitmap %08x %08x\n", - cmd->pdev_id, cmd->bitmap[0], cmd->bitmap[1]); - ret = ath11k_wmi_cmd_send(wmi, skb, WMI_PDEV_SET_NON_SRG_OBSS_COLOR_ENABLE_BITMAP_CMDID); if (ret) { ath11k_warn(ab, "failed to send WMI_PDEV_SET_NON_SRG_OBSS_COLOR_ENABLE_BITMAP_CMDID"); dev_kfree_skb(skb); + return ret; } - return ret; + ath11k_dbg(ar->ab, ATH11K_DBG_WMI, + "cmd pdev set non srg obss color enable bitmap pdev_id %d bss color enable bitmap %08x %08x\n", + cmd->pdev_id, cmd->bitmap[0], cmd->bitmap[1]); + + return 0; } int @@ -3614,19 +3681,20 @@ ath11k_wmi_pdev_non_srg_obss_bssid_enable_bitmap(struct ath11k *ar, u32 *bitmap) cmd->pdev_id = ar->pdev->pdev_id; memcpy(cmd->bitmap, bitmap, sizeof(cmd->bitmap)); - ath11k_dbg(ar->ab, ATH11K_DBG_WMI, - "obss pd non_srg pdev_id %d bssid enable bitmap %08x %08x\n", - cmd->pdev_id, cmd->bitmap[0], cmd->bitmap[1]); - ret = ath11k_wmi_cmd_send(wmi, skb, WMI_PDEV_SET_NON_SRG_OBSS_BSSID_ENABLE_BITMAP_CMDID); if (ret) { ath11k_warn(ab, "failed to send WMI_PDEV_SET_NON_SRG_OBSS_BSSID_ENABLE_BITMAP_CMDID"); dev_kfree_skb(skb); + return ret; } - return ret; + ath11k_dbg(ar->ab, ATH11K_DBG_WMI, + "cmd pdev set non srg obss bssid enable bitmap pdev_id %d bssid enable bitmap %08x %08x\n", + cmd->pdev_id, cmd->bitmap[0], cmd->bitmap[1]); + + return 0; } int @@ -3659,18 +3727,20 @@ ath11k_wmi_send_obss_color_collision_cfg_cmd(struct ath11k *ar, u32 vdev_id, cmd->free_slot_expiry_time_ms = 0; cmd->flags = 0; - ath11k_dbg(ar->ab, ATH11K_DBG_WMI, - "wmi_send_obss_color_collision_cfg id %d type %d bss_color %d detect_period %d scan_period %d\n", - cmd->vdev_id, cmd->evt_type, cmd->current_bss_color, - cmd->detection_period_ms, cmd->scan_period_ms); - ret = ath11k_wmi_cmd_send(wmi, skb, WMI_OBSS_COLOR_COLLISION_DET_CONFIG_CMDID); if (ret) { ath11k_warn(ab, "Failed to send WMI_OBSS_COLOR_COLLISION_DET_CONFIG_CMDID"); dev_kfree_skb(skb); + return ret; } - return ret; + + ath11k_dbg(ar->ab, ATH11K_DBG_WMI, + "cmd obss color collision det config id %d type %d bss_color %d detect_period %d scan_period %d\n", + cmd->vdev_id, cmd->evt_type, cmd->current_bss_color, + cmd->detection_period_ms, cmd->scan_period_ms); + + return 0; } int ath11k_wmi_send_bss_color_change_enable_cmd(struct ath11k *ar, u32 vdev_id, @@ -3694,17 +3764,19 @@ int ath11k_wmi_send_bss_color_change_enable_cmd(struct ath11k *ar, u32 vdev_id, cmd->vdev_id = vdev_id; cmd->enable = enable ? 1 : 0; - ath11k_dbg(ar->ab, ATH11K_DBG_WMI, - "wmi_send_bss_color_change_enable id %d enable %d\n", - cmd->vdev_id, cmd->enable); - ret = ath11k_wmi_cmd_send(wmi, skb, WMI_BSS_COLOR_CHANGE_ENABLE_CMDID); if (ret) { ath11k_warn(ab, "Failed to send WMI_BSS_COLOR_CHANGE_ENABLE_CMDID"); dev_kfree_skb(skb); + return ret; } - return ret; + + ath11k_dbg(ar->ab, ATH11K_DBG_WMI, + "cmd bss color change enable id %d enable %d\n", + cmd->vdev_id, cmd->enable); + + return 0; } int ath11k_wmi_fils_discovery_tmpl(struct ath11k *ar, u32 vdev_id, @@ -3721,7 +3793,7 @@ int ath11k_wmi_fils_discovery_tmpl(struct ath11k *ar, u32 vdev_id, len = sizeof(*cmd) + TLV_HDR_SIZE + aligned_len; ath11k_dbg(ar->ab, ATH11K_DBG_WMI, - "WMI vdev %i set FILS discovery template\n", vdev_id); + "vdev %i set FILS discovery template\n", vdev_id); skb = ath11k_wmi_alloc_skb(ar->wmi->wmi_ab, len); if (!skb) @@ -3746,8 +3818,12 @@ int ath11k_wmi_fils_discovery_tmpl(struct ath11k *ar, u32 vdev_id, "WMI vdev %i failed to send FILS discovery template command\n", vdev_id); dev_kfree_skb(skb); + return ret; } - return ret; + + ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "cmd fils discovery tmpl"); + + return 0; } int ath11k_wmi_probe_resp_tmpl(struct ath11k *ar, u32 vdev_id, @@ -3762,7 +3838,7 @@ int ath11k_wmi_probe_resp_tmpl(struct ath11k *ar, u32 vdev_id, size_t aligned_len = roundup(tmpl->len, 4); ath11k_dbg(ar->ab, ATH11K_DBG_WMI, - "WMI vdev %i set probe response template\n", vdev_id); + "vdev %i set probe response template\n", vdev_id); len = sizeof(*cmd) + sizeof(*probe_info) + TLV_HDR_SIZE + aligned_len; @@ -3799,8 +3875,12 @@ int ath11k_wmi_probe_resp_tmpl(struct ath11k *ar, u32 vdev_id, "WMI vdev %i failed to send probe response template command\n", vdev_id); dev_kfree_skb(skb); + return ret; } - return ret; + + ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "cmd "); + + return 0; } int ath11k_wmi_fils_discovery(struct ath11k *ar, u32 vdev_id, u32 interval, @@ -3811,7 +3891,7 @@ int ath11k_wmi_fils_discovery(struct ath11k *ar, u32 vdev_id, u32 interval, struct wmi_fils_discovery_cmd *cmd; ath11k_dbg(ar->ab, ATH11K_DBG_WMI, - "WMI vdev %i set %s interval to %u TU\n", + "vdev %i set %s interval to %u TU\n", vdev_id, unsol_bcast_probe_resp_enabled ? "unsolicited broadcast probe response" : "FILS discovery", interval); @@ -3834,8 +3914,12 @@ int ath11k_wmi_fils_discovery(struct ath11k *ar, u32 vdev_id, u32 interval, "WMI vdev %i failed to send FILS discovery enable/disable command\n", vdev_id); dev_kfree_skb(skb); + return ret; } - return ret; + + ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "cmd enable fils"); + + return 0; } static void @@ -3853,6 +3937,8 @@ ath11k_wmi_obss_color_collision_event(struct ath11k_base *ab, struct sk_buff *sk return; } + ath11k_dbg(ab, ATH11K_DBG_WMI, "event obss color collision"); + rcu_read_lock(); ev = tb[WMI_TAG_OBSS_COLOR_COLLISION_EVT]; @@ -3987,6 +4073,9 @@ ath11k_wmi_copy_resource_config(struct wmi_resource_config *wmi_cfg, ~(1 << WMI_CFG_HOST_SERVICE_FLAG_REG_CC_EXT); wmi_cfg->host_service_flags |= (tg_cfg->is_reg_cc_ext_event_supported << WMI_CFG_HOST_SERVICE_FLAG_REG_CC_EXT); + wmi_cfg->flags2 = WMI_RSRC_CFG_FLAG2_CALC_NEXT_DTIM_COUNT_SET; + wmi_cfg->ema_max_vap_cnt = tg_cfg->ema_max_vap_cnt; + wmi_cfg->ema_max_profile_period = tg_cfg->ema_max_profile_period; } static int ath11k_init_cmd_send(struct ath11k_pdev_wmi *wmi, @@ -4044,7 +4133,7 @@ static int ath11k_init_cmd_send(struct ath11k_pdev_wmi *wmi, host_mem_chunks[idx].req_id = param->mem_chunks[idx].req_id; ath11k_dbg(ab, ATH11K_DBG_WMI, - "WMI host mem chunk req_id %d paddr 0x%llx len %d\n", + "host mem chunk req_id %d paddr 0x%llx len %d\n", param->mem_chunks[idx].req_id, (u64)param->mem_chunks[idx].paddr, param->mem_chunks[idx].len); @@ -4098,9 +4187,12 @@ static int ath11k_init_cmd_send(struct ath11k_pdev_wmi *wmi, if (ret) { ath11k_warn(ab, "failed to send WMI_INIT_CMDID\n"); dev_kfree_skb(skb); + return ret; } - return ret; + ath11k_dbg(ab, ATH11K_DBG_WMI, "cmd wmi init"); + + return 0; } int ath11k_wmi_pdev_lro_cfg(struct ath11k *ar, @@ -4131,7 +4223,7 @@ int ath11k_wmi_pdev_lro_cfg(struct ath11k *ar, } ath11k_dbg(ar->ab, ATH11K_DBG_WMI, - "WMI lro cfg cmd pdev_id 0x%x\n", pdev_id); + "cmd lro config pdev_id 0x%x\n", pdev_id); return 0; err: dev_kfree_skb(skb); @@ -4189,9 +4281,12 @@ int ath11k_wmi_set_hw_mode(struct ath11k_base *ab, if (ret) { ath11k_warn(ab, "failed to send WMI_PDEV_SET_HW_MODE_CMDID\n"); dev_kfree_skb(skb); + return ret; } - return ret; + ath11k_dbg(ab, ATH11K_DBG_WMI, "cmd pdev set hw mode %d", cmd->hw_mode_index); + + return 0; } int ath11k_wmi_cmd_init(struct ath11k_base *ab) @@ -4252,7 +4347,7 @@ int ath11k_wmi_vdev_spectral_conf(struct ath11k *ar, } ath11k_dbg(ar->ab, ATH11K_DBG_WMI, - "WMI spectral scan config cmd vdev_id 0x%x\n", + "cmd vdev spectral scan configure vdev_id 0x%x\n", param->vdev_id); return 0; @@ -4290,7 +4385,7 @@ int ath11k_wmi_vdev_spectral_enable(struct ath11k *ar, u32 vdev_id, } ath11k_dbg(ar->ab, ATH11K_DBG_WMI, - "WMI spectral enable cmd vdev id 0x%x\n", + "cmd vdev spectral scan enable vdev id 0x%x\n", vdev_id); return 0; @@ -4336,7 +4431,7 @@ int ath11k_wmi_pdev_dma_ring_cfg(struct ath11k *ar, } ath11k_dbg(ar->ab, ATH11K_DBG_WMI, - "WMI DMA ring cfg req cmd pdev_id 0x%x\n", + "cmd pdev dma ring cfg req pdev_id 0x%x\n", param->pdev_id); return 0; @@ -4442,6 +4537,8 @@ static void ath11k_wmi_pdev_dma_ring_buf_release_event(struct ath11k_base *ab, return; } + ath11k_dbg(ab, ATH11K_DBG_WMI, "event pdev dma ring buf release"); + param.fixed = parse.fixed; param.buf_entry = parse.buf_entry; param.num_buf_entry = parse.num_buf_entry; @@ -4836,6 +4933,8 @@ static int ath11k_service_ready_ext_event(struct ath11k_base *ab, goto err; } + ath11k_dbg(ab, ATH11K_DBG_WMI, "event service ready ext"); + if (!test_bit(WMI_TLV_SERVICE_EXT2_MSG, ab->wmi_ab.svc_map)) complete(&ab->wmi_ab.service_ready); @@ -4886,6 +4985,8 @@ static int ath11k_service_ready_ext2_event(struct ath11k_base *ab, goto err; } + ath11k_dbg(ab, ATH11K_DBG_WMI, "event service ready ext2"); + complete(&ab->wmi_ab.service_ready); return 0; @@ -5757,7 +5858,7 @@ static int wmi_process_mgmt_tx_comp(struct ath11k *ar, WARN_ON_ONCE(1); ath11k_dbg(ar->ab, ATH11K_DBG_WMI, - "wmi mgmt tx comp pending %d desc id %d\n", + "mgmt tx comp pending %d desc id %d\n", num_mgmt, tx_compl_param->desc_id); if (!num_mgmt) @@ -6326,7 +6427,7 @@ static int ath11k_wmi_tlv_rssi_chain_parse(struct ath11k_base *ab, stats->stats_id = WMI_REQUEST_RSSI_PER_CHAIN_STAT; ath11k_dbg(ab, ATH11K_DBG_WMI, - "wmi stats vdev id %d mac %pM\n", + "stats vdev id %d mac %pM\n", stats_rssi->vdev_id, stats_rssi->peer_macaddr.addr); arvif = ath11k_mac_get_arvif(ar, stats_rssi->vdev_id); @@ -6338,7 +6439,7 @@ static int ath11k_wmi_tlv_rssi_chain_parse(struct ath11k_base *ab, } ath11k_dbg(ab, ATH11K_DBG_WMI, - "wmi stats bssid %pM vif %pK\n", + "stats bssid %pM vif %p\n", arvif->bssid, arvif->vif); sta = ieee80211_find_sta_by_ifaddr(ar->hw, @@ -6359,7 +6460,7 @@ static int ath11k_wmi_tlv_rssi_chain_parse(struct ath11k_base *ab, for (j = 0; j < ARRAY_SIZE(arsta->chain_signal); j++) { arsta->chain_signal[j] = stats_rssi->rssi_avg_beacon[j]; ath11k_dbg(ab, ATH11K_DBG_WMI, - "wmi stats beacon rssi[%d] %d data rssi[%d] %d\n", + "stats beacon rssi[%d] %d data rssi[%d] %d\n", j, stats_rssi->rssi_avg_beacon[j], j, @@ -6442,7 +6543,7 @@ static int ath11k_wmi_tlv_fw_stats_data_parse(struct ath11k_base *ab, arsta = (struct ath11k_sta *)sta->drv_priv; arsta->rssi_beacon = src->beacon_snr; ath11k_dbg(ab, ATH11K_DBG_WMI, - "wmi stats vdev id %d snr %d\n", + "stats vdev id %d snr %d\n", src->vdev_id, src->beacon_snr); } else { ath11k_dbg(ab, ATH11K_DBG_WMI, @@ -6512,7 +6613,7 @@ static int ath11k_wmi_tlv_fw_stats_parse(struct ath11k_base *ab, parse->rssi_num = parse->rssi->num_per_chain_rssi_stats; ath11k_dbg(ab, ATH11K_DBG_WMI, - "wmi stats id 0x%x num chain %d\n", + "stats id 0x%x num chain %d\n", parse->ev->stats_id, parse->rssi_num); break; @@ -6548,28 +6649,6 @@ int ath11k_wmi_pull_fw_stats(struct ath11k_base *ab, struct sk_buff *skb, &parse); } -size_t ath11k_wmi_fw_stats_num_vdevs(struct list_head *head) -{ - struct ath11k_fw_stats_vdev *i; - size_t num = 0; - - list_for_each_entry(i, head, list) - ++num; - - return num; -} - -static size_t ath11k_wmi_fw_stats_num_bcn(struct list_head *head) -{ - struct ath11k_fw_stats_bcn *i; - size_t num = 0; - - list_for_each_entry(i, head, list) - ++num; - - return num; -} - static void ath11k_wmi_fw_pdev_base_stats_fill(const struct ath11k_fw_stats_pdev *pdev, char *buf, u32 *length) @@ -6880,7 +6959,7 @@ void ath11k_wmi_fw_stats_fill(struct ath11k *ar, } if (stats_id == WMI_REQUEST_BCN_STAT) { - num_bcn = ath11k_wmi_fw_stats_num_bcn(&fw_stats->bcn); + num_bcn = list_count_nodes(&fw_stats->bcn); len += scnprintf(buf + len, buf_len - len, "\n"); len += scnprintf(buf + len, buf_len - len, "%30s (%zu)\n", @@ -6933,7 +7012,7 @@ static int ath11k_reg_11d_new_cc_event(struct ath11k_base *ab, struct sk_buff *s memcpy(&ab->new_alpha2, &ev->new_alpha2, 2); spin_unlock_bh(&ab->base_lock); - ath11k_dbg(ab, ATH11K_DBG_WMI, "wmi 11d new cc %c%c\n", + ath11k_dbg(ab, ATH11K_DBG_WMI, "event 11d new cc %c%c\n", ab->new_alpha2[0], ab->new_alpha2[1]); @@ -7017,6 +7096,8 @@ static int ath11k_reg_chan_list_event(struct ath11k_base *ab, goto fallback; } + ath11k_dbg(ab, ATH11K_DBG_WMI, "event reg chan list id %d", id); + if (reg_info->status_code != REG_SET_CC_STATUS_PASS) { /* In case of failure to set the requested ctry, * fw retains the current regd. We print a failure info @@ -7182,6 +7263,8 @@ static int ath11k_ready_event(struct ath11k_base *ab, struct sk_buff *skb) return ret; } + ath11k_dbg(ab, ATH11K_DBG_WMI, "event ready"); + complete(&ab->wmi_ab.unified_ready); return 0; } @@ -7196,6 +7279,8 @@ static void ath11k_peer_delete_resp_event(struct ath11k_base *ab, struct sk_buff return; } + ath11k_dbg(ab, ATH11K_DBG_WMI, "event peer delete resp"); + rcu_read_lock(); ar = ath11k_mac_get_ar_by_vdev_id(ab, peer_del_resp.vdev_id); if (!ar) { @@ -7235,7 +7320,7 @@ static void ath11k_vdev_delete_resp_event(struct ath11k_base *ab, rcu_read_unlock(); - ath11k_dbg(ab, ATH11K_DBG_WMI, "vdev delete resp for vdev id %d\n", + ath11k_dbg(ab, ATH11K_DBG_WMI, "event vdev delete resp for vdev id %d\n", vdev_id); } @@ -7266,6 +7351,8 @@ static void ath11k_vdev_start_resp_event(struct ath11k_base *ab, struct sk_buff return; } + ath11k_dbg(ab, ATH11K_DBG_WMI, "event start resp event"); + rcu_read_lock(); ar = ath11k_mac_get_ar_by_vdev_id(ab, vdev_start_resp.vdev_id); if (!ar) { @@ -7304,6 +7391,8 @@ static void ath11k_bcn_tx_status_event(struct ath11k_base *ab, struct sk_buff *s return; } + ath11k_dbg(ab, ATH11K_DBG_WMI, "event offload bcn tx status"); + rcu_read_lock(); arvif = ath11k_mac_get_arvif_by_vdev_id(ab, vdev_id); if (!arvif) { @@ -7343,7 +7432,7 @@ static void ath11k_wmi_event_peer_sta_ps_state_chg(struct ath11k_base *ab, } ath11k_dbg(ab, ATH11K_DBG_WMI, - "peer sta ps change ev addr %pM state %u sup_bitmap %x ps_valid %u ts %u\n", + "event peer sta ps change ev addr %pM state %u sup_bitmap %x ps_valid %u ts %u\n", ev->peer_macaddr.addr, ev->peer_ps_state, ev->ps_supported_bitmap, ev->peer_ps_valid, ev->peer_ps_timestamp); @@ -7427,6 +7516,8 @@ static void ath11k_vdev_stopped_event(struct ath11k_base *ab, struct sk_buff *sk return; } + ath11k_dbg(ab, ATH11K_DBG_WMI, "event vdev stopped"); + rcu_read_lock(); ar = ath11k_mac_get_ar_by_vdev_id(ab, vdev_id); if (!ar) { @@ -7460,7 +7551,7 @@ static void ath11k_mgmt_rx_event(struct ath11k_base *ab, struct sk_buff *skb) memset(status, 0, sizeof(*status)); - ath11k_dbg(ab, ATH11K_DBG_MGMT, "mgmt rx event status %08x\n", + ath11k_dbg(ab, ATH11K_DBG_MGMT, "event mgmt rx status %08x\n", rx_ev.status); rcu_read_lock(); @@ -7503,7 +7594,7 @@ static void ath11k_mgmt_rx_event(struct ath11k_base *ab, struct sk_buff *skb) if (rx_ev.phy_mode == MODE_11B && (status->band == NL80211_BAND_5GHZ || status->band == NL80211_BAND_6GHZ)) ath11k_dbg(ab, ATH11K_DBG_WMI, - "wmi mgmt rx 11b (CCK) on 5/6GHz, band = %d\n", status->band); + "mgmt rx 11b (CCK) on 5/6GHz, band = %d\n", status->band); sband = &ar->mac.sbands[status->band]; @@ -7543,7 +7634,7 @@ static void ath11k_mgmt_rx_event(struct ath11k_base *ab, struct sk_buff *skb) ath11k_mac_handle_beacon(ar, skb); ath11k_dbg(ab, ATH11K_DBG_MGMT, - "event mgmt rx skb %pK len %d ftype %02x stype %02x\n", + "event mgmt rx skb %p len %d ftype %02x stype %02x\n", skb, skb->len, fc & IEEE80211_FCTL_FTYPE, fc & IEEE80211_FCTL_STYPE); @@ -7579,7 +7670,7 @@ static void ath11k_mgmt_tx_compl_event(struct ath11k_base *ab, struct sk_buff *s wmi_process_mgmt_tx_comp(ar, &tx_compl_param); ath11k_dbg(ab, ATH11K_DBG_MGMT, - "mgmt tx compl ev pdev_id %d, desc_id %d, status %d ack_rssi %d", + "event mgmt tx compl ev pdev_id %d, desc_id %d, status %d ack_rssi %d", tx_compl_param.pdev_id, tx_compl_param.desc_id, tx_compl_param.status, tx_compl_param.ack_rssi); @@ -7650,7 +7741,7 @@ static void ath11k_scan_event(struct ath11k_base *ab, struct sk_buff *skb) spin_lock_bh(&ar->data_lock); ath11k_dbg(ab, ATH11K_DBG_WMI, - "scan event %s type %d reason %d freq %d req_id %d scan_id %d vdev_id %d state %s (%d)\n", + "event scan %s type %d reason %d freq %d req_id %d scan_id %d vdev_id %d state %s (%d)\n", ath11k_wmi_event_scan_type_str(scan_ev.event_type, scan_ev.reason), scan_ev.event_type, scan_ev.reason, scan_ev.channel_freq, scan_ev.scan_req_id, scan_ev.scan_id, scan_ev.vdev_id, @@ -7733,7 +7824,7 @@ static void ath11k_peer_sta_kickout_event(struct ath11k_base *ab, struct sk_buff goto exit; } - ath11k_dbg(ab, ATH11K_DBG_WMI, "peer sta kickout event %pM", + ath11k_dbg(ab, ATH11K_DBG_WMI, "event peer sta kickout %pM", arg.mac_addr); ieee80211_report_low_ack(sta, 10); @@ -7753,7 +7844,7 @@ static void ath11k_roam_event(struct ath11k_base *ab, struct sk_buff *skb) } ath11k_dbg(ab, ATH11K_DBG_WMI, - "wmi roam event vdev %u reason 0x%08x rssi %d\n", + "event roam vdev %u reason 0x%08x rssi %d\n", roam_ev.vdev_id, roam_ev.reason, roam_ev.rssi); rcu_read_lock(); @@ -7800,7 +7891,7 @@ static void ath11k_chan_info_event(struct ath11k_base *ab, struct sk_buff *skb) } ath11k_dbg(ab, ATH11K_DBG_WMI, - "chan info vdev_id %d err_code %d freq %d cmd_flags %d noise_floor %d rx_clear_count %d cycle_count %d mac_clk_mhz %d\n", + "event chan info vdev_id %d err_code %d freq %d cmd_flags %d noise_floor %d rx_clear_count %d cycle_count %d mac_clk_mhz %d\n", ch_info_ev.vdev_id, ch_info_ev.err_code, ch_info_ev.freq, ch_info_ev.cmd_flags, ch_info_ev.noise_floor, ch_info_ev.rx_clear_count, ch_info_ev.cycle_count, @@ -7889,7 +7980,7 @@ ath11k_pdev_bss_chan_info_event(struct ath11k_base *ab, struct sk_buff *skb) bss_ch_info_ev.rx_bss_cycle_count_low; ath11k_dbg(ab, ATH11K_DBG_WMI, - "pdev bss chan info:\n pdev_id: %d freq: %d noise: %d cycle: busy %llu total %llu tx %llu rx %llu rx_bss %llu\n", + "event pdev bss chan info:\n pdev_id: %d freq: %d noise: %d cycle: busy %llu total %llu tx %llu rx %llu rx_bss %llu\n", bss_ch_info_ev.pdev_id, bss_ch_info_ev.freq, bss_ch_info_ev.noise_floor, busy, total, tx, rx, rx_bss); @@ -7943,7 +8034,7 @@ static void ath11k_vdev_install_key_compl_event(struct ath11k_base *ab, } ath11k_dbg(ab, ATH11K_DBG_WMI, - "vdev install key ev idx %d flags %08x macaddr %pM status %d\n", + "event vdev install key ev idx %d flags %08x macaddr %pM status %d\n", install_key_compl.key_idx, install_key_compl.key_flags, install_key_compl.macaddr, install_key_compl.status); @@ -8026,6 +8117,8 @@ static void ath11k_service_available_event(struct ath11k_base *ab, struct sk_buf NULL); if (ret) ath11k_warn(ab, "failed to parse services available tlv %d\n", ret); + + ath11k_dbg(ab, ATH11K_DBG_WMI, "event service available"); } static void ath11k_peer_assoc_conf_event(struct ath11k_base *ab, struct sk_buff *skb) @@ -8039,7 +8132,7 @@ static void ath11k_peer_assoc_conf_event(struct ath11k_base *ab, struct sk_buff } ath11k_dbg(ab, ATH11K_DBG_WMI, - "peer assoc conf ev vdev id %d macaddr %pM\n", + "event peer assoc conf ev vdev id %d macaddr %pM\n", peer_assoc_conf.vdev_id, peer_assoc_conf.macaddr); rcu_read_lock(); @@ -8072,6 +8165,8 @@ static void ath11k_update_stats_event(struct ath11k_base *ab, struct sk_buff *sk goto free; } + ath11k_dbg(ab, ATH11K_DBG_WMI, "event update stats"); + rcu_read_lock(); ar = ath11k_mac_get_ar_by_pdev_id(ab, stats.pdev_id); if (!ar) { @@ -8103,6 +8198,11 @@ static void ath11k_update_stats_event(struct ath11k_base *ab, struct sk_buff *sk rcu_read_unlock(); spin_unlock_bh(&ar->data_lock); + /* Since the stats's pdev, vdev and beacon list are spliced and reinitialised + * at this point, no need to free the individual list. + */ + return; + free: ath11k_fw_stats_free(&stats); } @@ -8132,7 +8232,7 @@ static void ath11k_pdev_ctl_failsafe_check_event(struct ath11k_base *ab, } ath11k_dbg(ab, ATH11K_DBG_WMI, - "pdev ctl failsafe check ev status %d\n", + "event pdev ctl failsafe check status %d\n", ev->ctl_failsafe_status); /* If ctl_failsafe_status is set to 1 FW will max out the Transmit power @@ -8199,7 +8299,7 @@ ath11k_wmi_pdev_csa_switch_count_status_event(struct ath11k_base *ab, } ath11k_dbg(ab, ATH11K_DBG_WMI, - "pdev csa switch count %d for pdev %d, num_vdevs %d", + "event pdev csa switch count %d for pdev %d, num_vdevs %d", ev->current_switch_count, ev->pdev_id, ev->num_vdevs); @@ -8232,7 +8332,7 @@ ath11k_wmi_pdev_dfs_radar_detected_event(struct ath11k_base *ab, struct sk_buff } ath11k_dbg(ab, ATH11K_DBG_WMI, - "pdev dfs radar detected on pdev %d, detection mode %d, chan freq %d, chan_width %d, detector id %d, seg id %d, timestamp %d, chirp %d, freq offset %d, sidx %d", + "event pdev dfs radar detected on pdev %d, detection mode %d, chan freq %d, chan_width %d, detector id %d, seg id %d, timestamp %d, chirp %d, freq offset %d, sidx %d", ev->pdev_id, ev->detection_mode, ev->chan_freq, ev->chan_width, ev->detector_id, ev->segment_id, ev->timestamp, ev->is_chirp, ev->freq_offset, ev->sidx); @@ -8280,8 +8380,8 @@ ath11k_wmi_pdev_temperature_event(struct ath11k_base *ab, return; } - ath11k_dbg(ab, ATH11K_DBG_WMI, - "pdev temperature ev temp %d pdev_id %d\n", ev->temp, ev->pdev_id); + ath11k_dbg(ab, ATH11K_DBG_WMI, "event pdev temperature ev temp %d pdev_id %d\n", + ev->temp, ev->pdev_id); ar = ath11k_mac_get_ar_by_pdev_id(ab, ev->pdev_id); if (!ar) { @@ -8311,6 +8411,8 @@ static void ath11k_fils_discovery_event(struct ath11k_base *ab, return; } + ath11k_dbg(ab, ATH11K_DBG_WMI, "event fils discovery"); + ev = tb[WMI_TAG_HOST_SWFDA_EVENT]; if (!ev) { ath11k_warn(ab, "failed to fetch FILS discovery event\n"); @@ -8341,6 +8443,8 @@ static void ath11k_probe_resp_tx_status_event(struct ath11k_base *ab, return; } + ath11k_dbg(ab, ATH11K_DBG_WMI, "event probe resp tx status"); + ev = tb[WMI_TAG_OFFLOAD_PRB_RSP_TX_STATUS_EVENT]; if (!ev) { ath11k_warn(ab, @@ -8407,6 +8511,8 @@ static void ath11k_wmi_event_wow_wakeup_host(struct ath11k_base *ab, struct sk_b return; } + ath11k_dbg(ab, ATH11K_DBG_WMI, "event wow wakeup host"); + complete(&ab->wow.wakeup_completed); } @@ -8414,6 +8520,8 @@ static void ath11k_wmi_diag_event(struct ath11k_base *ab, struct sk_buff *skb) { + ath11k_dbg(ab, ATH11K_DBG_WMI, "event diag"); + trace_ath11k_wmi_diag(ab, skb->data, skb->len); } @@ -8461,6 +8569,8 @@ static void ath11k_wmi_twt_add_dialog_event(struct ath11k_base *ab, return; } + ath11k_dbg(ab, ATH11K_DBG_WMI, "event twt add dialog"); + ev = tb[WMI_TAG_TWT_ADD_DIALOG_COMPLETE_EVENT]; if (!ev) { ath11k_warn(ab, "failed to fetch twt add dialog wmi event\n"); @@ -8509,7 +8619,7 @@ static void ath11k_wmi_gtk_offload_status_event(struct ath11k_base *ab, return; } - ath11k_dbg(ab, ATH11K_DBG_WMI, "wmi gtk offload event refresh_cnt %d\n", + ath11k_dbg(ab, ATH11K_DBG_WMI, "event gtk offload refresh_cnt %d\n", ev->refresh_cnt); ath11k_dbg_dump(ab, ATH11K_DBG_WMI, "replay_cnt", NULL, ev->replay_ctr.counter, GTK_REPLAY_COUNTER_BYTES); @@ -8612,6 +8722,9 @@ static void ath11k_wmi_tlv_op_rx(struct ath11k_base *ab, struct sk_buff *skb) case WMI_PDEV_CSA_SWITCH_COUNT_STATUS_EVENTID: ath11k_wmi_pdev_csa_switch_count_status_event(ab, skb); break; + case WMI_PDEV_UTF_EVENTID: + ath11k_tm_wmi_event(ab, id, skb); + break; case WMI_PDEV_TEMPERATURE_EVENTID: ath11k_wmi_pdev_temperature_event(ab, skb); break; @@ -8630,19 +8743,6 @@ static void ath11k_wmi_tlv_op_rx(struct ath11k_base *ab, struct sk_buff *skb) case WMI_TWT_ADD_DIALOG_EVENTID: ath11k_wmi_twt_add_dialog_event(ab, skb); break; - /* add Unsupported events here */ - case WMI_TBTTOFFSET_EXT_UPDATE_EVENTID: - case WMI_PEER_OPER_MODE_CHANGE_EVENTID: - case WMI_TWT_ENABLE_EVENTID: - case WMI_TWT_DISABLE_EVENTID: - case WMI_TWT_DEL_DIALOG_EVENTID: - case WMI_TWT_PAUSE_DIALOG_EVENTID: - case WMI_TWT_RESUME_DIALOG_EVENTID: - case WMI_PDEV_DMA_RING_CFG_RSP_EVENTID: - case WMI_PEER_CREATE_CONF_EVENTID: - ath11k_dbg(ab, ATH11K_DBG_WMI, - "ignoring unsupported event 0x%x\n", id); - break; case WMI_PDEV_DFS_RADAR_DETECTION_EVENTID: ath11k_wmi_pdev_dfs_radar_detected_event(ab, skb); break; @@ -8664,9 +8764,8 @@ static void ath11k_wmi_tlv_op_rx(struct ath11k_base *ab, struct sk_buff *skb) case WMI_GTK_OFFLOAD_STATUS_EVENTID: ath11k_wmi_gtk_offload_status_event(ab, skb); break; - /* TODO: Add remaining events */ default: - ath11k_dbg(ab, ATH11K_DBG_WMI, "Unknown eventid: 0x%x\n", id); + ath11k_dbg(ab, ATH11K_DBG_WMI, "unsupported event id 0x%x\n", id); break; } @@ -8763,7 +8862,7 @@ ath11k_wmi_send_unit_test_cmd(struct ath11k *ar, } ath11k_dbg(ar->ab, ATH11K_DBG_WMI, - "WMI unit test : module %d vdev %d n_args %d token %d\n", + "cmd unit test module %d vdev %d n_args %d token %d\n", cmd->module_id, cmd->vdev_id, cmd->num_args, cmd->diag_token); @@ -8855,6 +8954,9 @@ int ath11k_wmi_fw_dbglog_cfg(struct ath11k *ar, u32 *module_id_bitmap, "failed to send WMI_DBGLOG_CFG_CMDID\n"); dev_kfree_skb(skb); } + + ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "cmd dbglog cfg"); + return ret; } @@ -8960,7 +9062,7 @@ int ath11k_wmi_hw_data_filter_cmd(struct ath11k *ar, u32 vdev_id, cmd->hw_filter_bitmap = ((u32)~0U); ath11k_dbg(ar->ab, ATH11K_DBG_WMI, - "wmi hw data filter enable %d filter_bitmap 0x%x\n", + "hw data filter enable %d filter_bitmap 0x%x\n", enable, filter_bitmap); return ath11k_wmi_cmd_send(ar->wmi, skb, WMI_HW_DATA_FILTER_CMDID); @@ -8982,7 +9084,7 @@ int ath11k_wmi_wow_host_wakeup_ind(struct ath11k *ar) WMI_TAG_WOW_HOSTWAKEUP_FROM_SLEEP_CMD) | FIELD_PREP(WMI_TLV_LEN, sizeof(*cmd) - TLV_HDR_SIZE); - ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "wmi tlv wow host wakeup ind\n"); + ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "tlv wow host wakeup ind\n"); return ath11k_wmi_cmd_send(ar->wmi, skb, WMI_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID); } @@ -9004,7 +9106,7 @@ int ath11k_wmi_wow_enable(struct ath11k *ar) cmd->enable = 1; cmd->pause_iface_config = WOW_IFACE_PAUSE_ENABLED; - ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "wmi tlv wow enable\n"); + ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "tlv wow enable\n"); return ath11k_wmi_cmd_send(ar->wmi, skb, WMI_WOW_ENABLE_CMDID); } @@ -9031,7 +9133,7 @@ int ath11k_wmi_scan_prob_req_oui(struct ath11k *ar, FIELD_PREP(WMI_TLV_LEN, sizeof(*cmd) - TLV_HDR_SIZE); cmd->prob_req_oui = prob_req_oui; - ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "wmi scan prob req oui %d\n", + ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "scan prob req oui %d\n", prob_req_oui); return ath11k_wmi_cmd_send(ar->wmi, skb, WMI_SCAN_PROB_REQ_OUI_CMDID); @@ -9058,7 +9160,7 @@ int ath11k_wmi_wow_add_wakeup_event(struct ath11k *ar, u32 vdev_id, cmd->is_add = enable; cmd->event_bitmap = (1 << event); - ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "wmi tlv wow add wakeup event %s enable %d vdev_id %d\n", + ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "tlv wow add wakeup event %s enable %d vdev_id %d\n", wow_wakeup_event(event), enable, vdev_id); return ath11k_wmi_cmd_send(ar->wmi, skb, WMI_WOW_ENABLE_DISABLE_WAKE_EVENT_CMDID); @@ -9163,7 +9265,7 @@ int ath11k_wmi_wow_add_pattern(struct ath11k *ar, u32 vdev_id, u32 pattern_id, WMI_TAG_ARRAY_UINT32) | FIELD_PREP(WMI_TLV_LEN, sizeof(u32)); - ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "wmi tlv wow add pattern vdev_id %d pattern_id %d pattern_offset %d\n", + ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "tlv wow add pattern vdev_id %d pattern_id %d pattern_offset %d\n", vdev_id, pattern_id, pattern_offset); return ath11k_wmi_cmd_send(ar->wmi, skb, WMI_WOW_ADD_WAKE_PATTERN_CMDID); @@ -9189,7 +9291,7 @@ int ath11k_wmi_wow_del_pattern(struct ath11k *ar, u32 vdev_id, u32 pattern_id) cmd->pattern_id = pattern_id; cmd->pattern_type = WOW_BITMAP_PATTERN; - ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "wmi tlv wow del pattern vdev_id %d pattern_id %d\n", + ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "tlv wow del pattern vdev_id %d pattern_id %d\n", vdev_id, pattern_id); return ath11k_wmi_cmd_send(ar->wmi, skb, WMI_WOW_DEL_WAKE_PATTERN_CMDID); @@ -9302,7 +9404,7 @@ ath11k_wmi_op_gen_config_pno_start(struct ath11k *ar, for (i = 0; i < cmd->num_of_channels; i++) channel_list[i] = pno->a_networks[0].channels[i]; - ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "wmi tlv start pno config vdev_id %d\n", + ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "tlv start pno config vdev_id %d\n", vdev_id); return skb; @@ -9328,7 +9430,7 @@ static struct sk_buff *ath11k_wmi_op_gen_config_pno_stop(struct ath11k *ar, cmd->flags = WMI_NLO_CONFIG_STOP; ath11k_dbg(ar->ab, ATH11K_DBG_WMI, - "wmi tlv stop pno config vdev_id %d\n", vdev_id); + "tlv stop pno config vdev_id %d\n", vdev_id); return skb; } @@ -9405,7 +9507,7 @@ static void ath11k_wmi_fill_ns_offload(struct ath11k *ar, } ath11k_dbg(ar->ab, ATH11K_DBG_WMI, - "wmi index %d ns_solicited %pI6 target %pI6", + "index %d ns_solicited %pI6 target %pI6", i, ns->solicitation_ipaddr, ns->target_ipaddr[0]); } @@ -9443,7 +9545,7 @@ static void ath11k_wmi_fill_arp_offload(struct ath11k *ar, memcpy(arp->target_ipaddr, offload->ipv4_addr[i], 4); ath11k_ce_byte_swap(arp->target_ipaddr, 4); - ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "wmi arp offload address %pI4", + ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "arp offload address %pI4", arp->target_ipaddr); } @@ -9676,7 +9778,7 @@ int ath11k_wmi_sta_keepalive(struct ath11k *ar, } ath11k_dbg(ar->ab, ATH11K_DBG_WMI, - "wmi sta keepalive vdev %d enabled %d method %d interval %d\n", + "sta keepalive vdev %d enabled %d method %d interval %d\n", arg->vdev_id, arg->enabled, arg->method, arg->interval); return ath11k_wmi_cmd_send(wmi, skb, WMI_STA_KEEPALIVE_CMDID); diff --git a/drivers/net/wireless/ath/ath11k/wmi.h b/drivers/net/wireless/ath/ath11k/wmi.h index 92fddb77669c237bdd32b00a90d6b6593c4dacde..100bb816b59230b9bb5ace8d06469d905aeb10a0 100644 --- a/drivers/net/wireless/ath/ath11k/wmi.h +++ b/drivers/net/wireless/ath/ath11k/wmi.h @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: BSD-3-Clause-Clear */ /* * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved. */ #ifndef ATH11K_WMI_H @@ -68,6 +69,7 @@ struct wmi_tlv { #define WMI_APPEND_TO_EXISTING_CHAN_LIST_FLAG 1 +#define MAX_WMI_UTF_LEN 252 #define WMI_BA_MODE_BUFFER_SIZE_256 3 /* * HW mode config type replicated from FW header @@ -137,6 +139,14 @@ enum { WMI_AUTORATE_3200NS_GI = BIT(11), }; +enum { + WMI_HOST_VDEV_FLAGS_NON_MBSSID_AP = 0x00000001, + WMI_HOST_VDEV_FLAGS_TRANSMIT_AP = 0x00000002, + WMI_HOST_VDEV_FLAGS_NON_TRANSMIT_AP = 0x00000004, + WMI_HOST_VDEV_FLAGS_EMA_MODE = 0x00000008, + WMI_HOST_VDEV_FLAGS_SCAN_MODE_VAP = 0x00000010, +}; + /* * wmi command groups. */ @@ -2096,6 +2106,7 @@ enum wmi_tlv_service { WMI_TLV_SERVICE_EXT2_MSG = 220, WMI_TLV_SERVICE_PEER_POWER_SAVE_DURATION_SUPPORT = 246, WMI_TLV_SERVICE_SRG_SRP_SPATIAL_REUSE_SUPPORT = 249, + WMI_TLV_SERVICE_MBSS_PARAM_IN_VDEV_START_SUPPORT = 253, WMI_TLV_SERVICE_PASSIVE_SCAN_START_TIME_ENHANCE = 263, /* The second 128 bits */ @@ -2317,6 +2328,7 @@ struct wmi_init_cmd { } __packed; #define WMI_RSRC_CFG_FLAG1_BSS_CHANNEL_INFO_64 BIT(5) +#define WMI_RSRC_CFG_FLAG2_CALC_NEXT_DTIM_COUNT_SET BIT(9) #define WMI_RSRC_CFG_FLAG1_ACK_RSSI BIT(18) #define WMI_CFG_HOST_SERVICE_FLAG_REG_CC_EXT 4 @@ -2389,6 +2401,9 @@ struct wmi_resource_config { u32 msdu_flow_override_config1; u32 flags2; u32 host_service_flags; + u32 max_rnr_neighbours; + u32 ema_max_vap_cnt; + u32 ema_max_profile_period; } __packed; struct wmi_service_ready_event { @@ -2579,6 +2594,8 @@ struct vdev_create_params { u8 rx; } chains[NUM_NL80211_BANDS]; u32 pdev_id; + u32 mbssid_flags; + u32 mbssid_tx_vdev_id; }; struct wmi_vdev_create_cmd { @@ -2589,6 +2606,8 @@ struct wmi_vdev_create_cmd { struct wmi_mac_addr vdev_macaddr; u32 num_cfg_txrx_streams; u32 pdev_id; + u32 mbssid_flags; + u32 mbssid_tx_vdev_id; } __packed; struct wmi_vdev_txrx_streams { @@ -2608,9 +2627,9 @@ struct wmi_vdev_up_cmd { u32 vdev_id; u32 vdev_assoc_id; struct wmi_mac_addr vdev_bssid; - struct wmi_mac_addr trans_bssid; - u32 profile_idx; - u32 profile_num; + struct wmi_mac_addr tx_vdev_bssid; + u32 nontx_profile_idx; + u32 nontx_profile_cnt; } __packed; struct wmi_vdev_stop_cmd { @@ -2652,6 +2671,9 @@ struct wmi_vdev_start_request_cmd { u32 he_ops; u32 cac_duration_ms; u32 regdomain; + u32 min_data_rate; + u32 mbssid_flags; + u32 mbssid_tx_vdev_id; } __packed; #define MGMT_TX_DL_FRM_LEN 64 @@ -2821,6 +2843,9 @@ struct wmi_vdev_start_req_arg { u32 pref_rx_streams; u32 pref_tx_streams; u32 num_noa_descriptors; + u32 min_data_rate; + u32 mbssid_flags; + u32 mbssid_tx_vdev_id; }; struct peer_create_params { @@ -3541,8 +3566,30 @@ struct wmi_get_pdev_temperature_cmd { u32 pdev_id; } __packed; +struct wmi_ftm_seg_hdr { + u32 len; + u32 msgref; + u32 segmentinfo; + u32 pdev_id; +} __packed; + +struct wmi_ftm_cmd { + u32 tlv_header; + struct wmi_ftm_seg_hdr seg_hdr; + u8 data[]; +} __packed; + +struct wmi_ftm_event_msg { + struct wmi_ftm_seg_hdr seg_hdr; + u8 data[]; +} __packed; + #define WMI_BEACON_TX_BUFFER_SIZE 512 +#define WMI_EMA_TMPL_IDX_SHIFT 8 +#define WMI_EMA_FIRST_TMPL_SHIFT 16 +#define WMI_EMA_LAST_TMPL_SHIFT 24 + struct wmi_bcn_tmpl_cmd { u32 tlv_header; u32 vdev_id; @@ -3553,6 +3600,11 @@ struct wmi_bcn_tmpl_cmd { u32 csa_event_bitmap; u32 mbssid_ie_offset; u32 esp_ie_offset; + u32 csc_switch_count_offset; + u32 csc_event_bitmap; + u32 mu_edca_ie_offset; + u32 feature_enable_bitmap; + u32 ema_params; } __packed; struct wmi_key_seq_counter { @@ -5646,6 +5698,8 @@ struct target_resource_config { u32 twt_ap_pdev_count; u32 twt_ap_sta_count; u8 is_reg_cc_ext_event_supported; + u32 ema_max_vap_cnt; + u32 ema_max_profile_period; }; enum wmi_debug_log_param { @@ -6266,6 +6320,8 @@ enum wmi_sta_keepalive_method { #define WMI_STA_KEEPALIVE_INTERVAL_DEFAULT 30 #define WMI_STA_KEEPALIVE_INTERVAL_DISABLE 0 +const void **ath11k_wmi_tlv_parse_alloc(struct ath11k_base *ab, const void *ptr, + size_t len, gfp_t gfp); int ath11k_wmi_cmd_send(struct ath11k_pdev_wmi *wmi, struct sk_buff *skb, u32 cmd_id); struct sk_buff *ath11k_wmi_alloc_skb(struct ath11k_wmi_base *wmi_sc, u32 len); @@ -6273,10 +6329,11 @@ int ath11k_wmi_mgmt_send(struct ath11k *ar, u32 vdev_id, u32 buf_id, struct sk_buff *frame); int ath11k_wmi_bcn_tmpl(struct ath11k *ar, u32 vdev_id, struct ieee80211_mutable_offsets *offs, - struct sk_buff *bcn); + struct sk_buff *bcn, u32 ema_param); int ath11k_wmi_vdev_down(struct ath11k *ar, u8 vdev_id); int ath11k_wmi_vdev_up(struct ath11k *ar, u32 vdev_id, u32 aid, - const u8 *bssid); + const u8 *bssid, u8 *tx_bssid, u32 nontx_profile_idx, + u32 nontx_profile_cnt); int ath11k_wmi_vdev_stop(struct ath11k *ar, u8 vdev_id); int ath11k_wmi_vdev_start(struct ath11k *ar, struct wmi_vdev_start_req_arg *arg, bool restart); @@ -6372,9 +6429,6 @@ int ath11k_wmi_send_pdev_set_regdomain(struct ath11k *ar, struct pdev_set_regdomain_params *param); int ath11k_wmi_pull_fw_stats(struct ath11k_base *ab, struct sk_buff *skb, struct ath11k_fw_stats *stats); -size_t ath11k_wmi_fw_stats_num_peers(struct list_head *head); -size_t ath11k_wmi_fw_stats_num_peers_extd(struct list_head *head); -size_t ath11k_wmi_fw_stats_num_vdevs(struct list_head *head); void ath11k_wmi_fw_stats_fill(struct ath11k *ar, struct ath11k_fw_stats *fw_stats, u32 stats_id, char *buf); diff --git a/drivers/net/wireless/ath/ath11k/wow.c b/drivers/net/wireless/ath/ath11k/wow.c index 1dec23b0699c86e2ae957b523ec286dc157d0abc..99d8ba45a75ba680d0b9a140599d4240a2eec3ea 100644 --- a/drivers/net/wireless/ath/ath11k/wow.c +++ b/drivers/net/wireless/ath/ath11k/wow.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: BSD-3-Clause-Clear /* * Copyright (c) 2020 The Linux Foundation. All rights reserved. - * Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved. */ #include @@ -838,6 +838,7 @@ int ath11k_wow_op_resume(struct ieee80211_hw *hw) case ATH11K_STATE_RESTARTING: case ATH11K_STATE_RESTARTED: case ATH11K_STATE_WEDGED: + case ATH11K_STATE_FTM: ath11k_warn(ar->ab, "encountered unexpected device state %d on resume, cannot recover\n", ar->state); ret = -EIO; diff --git a/drivers/net/wireless/ath/ath12k/core.c b/drivers/net/wireless/ath/ath12k/core.c index a89e66653f044ffc25ad720265da416a65e75afe..3df8059d55129b13e10b3898b7b5b52b533e9379 100644 --- a/drivers/net/wireless/ath/ath12k/core.c +++ b/drivers/net/wireless/ath/ath12k/core.c @@ -706,6 +706,7 @@ static void ath12k_core_pre_reconfigure_recovery(struct ath12k_base *ab) idr_for_each(&ar->txmgmt_idr, ath12k_mac_tx_mgmt_pending_free, ar); idr_destroy(&ar->txmgmt_idr); + wake_up(&ar->txmgmt_empty_waitq); } wake_up(&ab->wmi_ab.tx_credits_wq); @@ -885,6 +886,7 @@ void ath12k_core_deinit(struct ath12k_base *ab) void ath12k_core_free(struct ath12k_base *ab) { + timer_delete_sync(&ab->rx_replenish_retry); destroy_workqueue(ab->workqueue_aux); destroy_workqueue(ab->workqueue); kfree(ab); diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h index 9439052a652e818e520181fae54167ce4254f172..2f93296db792a501d775e98f17af6151c20b7a87 100644 --- a/drivers/net/wireless/ath/ath12k/core.h +++ b/drivers/net/wireless/ath/ath12k/core.h @@ -533,6 +533,7 @@ struct ath12k { /* protects txmgmt_idr data */ spinlock_t txmgmt_idr_lock; atomic_t num_pending_mgmt_tx; + wait_queue_head_t txmgmt_empty_waitq; /* cycle count is reported twice for each visited channel during scan. * access protected by data_lock diff --git a/drivers/net/wireless/ath/ath12k/dp_rx.c b/drivers/net/wireless/ath/ath12k/dp_rx.c index e78478a5b978224bdc9c4e343c4140a20e4f1c84..ffd9a2018610fe87d35716b2a51c2dea0d5ced21 100644 --- a/drivers/net/wireless/ath/ath12k/dp_rx.c +++ b/drivers/net/wireless/ath/ath12k/dp_rx.c @@ -193,11 +193,11 @@ static void ath12k_dp_rxdesc_set_msdu_len(struct ath12k_base *ab, ab->hw_params->hal_ops->rx_desc_set_msdu_len(desc, len); } -static bool ath12k_dp_rx_h_is_mcbc(struct ath12k_base *ab, - struct hal_rx_desc *desc) +static bool ath12k_dp_rx_h_is_da_mcbc(struct ath12k_base *ab, + struct hal_rx_desc *desc) { return (ath12k_dp_rx_h_first_msdu(ab, desc) && - ab->hw_params->hal_ops->rx_desc_is_mcbc(desc)); + ab->hw_params->hal_ops->rx_desc_is_da_mcbc(desc)); } static bool ath12k_dp_rxdesc_mac_addr2_valid(struct ath12k_base *ab, @@ -978,7 +978,19 @@ int ath12k_dp_rx_peer_tid_setup(struct ath12k *ar, const u8 *peer_mac, int vdev_ return ret; } - return ret; + if (!ab->hw_params->reoq_lut_support) { + ret = ath12k_wmi_peer_rx_reorder_queue_setup(ar, vdev_id, + peer_mac, + paddr, tid, 1, + ba_win_sz); + if (ret) { + ath12k_warn(ab, "failed to setup peer rx reorder queuefor tid %d: %d\n", + tid, ret); + return ret; + } + } + + return 0; } rx_tid->tid = tid; @@ -1362,11 +1374,6 @@ ath12k_update_per_peer_tx_stats(struct ath12k *ar, * Firmware rate's control to be skipped for this? */ - if (flags == WMI_RATE_PREAMBLE_HE && mcs > 11) { - ath12k_warn(ab, "Invalid HE mcs %d peer stats", mcs); - return; - } - if (flags == WMI_RATE_PREAMBLE_HE && mcs > ATH12K_HE_MCS_MAX) { ath12k_warn(ab, "Invalid HE mcs %d peer stats", mcs); return; @@ -2201,7 +2208,7 @@ static void ath12k_dp_rx_h_mpdu(struct ath12k *ar, /* PN for multicast packets will be checked in mac80211 */ rxcb = ATH12K_SKB_RXCB(msdu); - fill_crypto_hdr = ath12k_dp_rx_h_is_mcbc(ar->ab, rx_desc); + fill_crypto_hdr = ath12k_dp_rx_h_is_da_mcbc(ar->ab, rx_desc); rxcb->is_mcbc = fill_crypto_hdr; if (rxcb->is_mcbc) diff --git a/drivers/net/wireless/ath/ath12k/hal.c b/drivers/net/wireless/ath/ath12k/hal.c index 0ec53afe9915d267bc7b3090ff1d8359963d1670..e7a150e7158e91793e34c00f3470b81c87230410 100644 --- a/drivers/net/wireless/ath/ath12k/hal.c +++ b/drivers/net/wireless/ath/ath12k/hal.c @@ -447,10 +447,10 @@ static u8 *ath12k_hw_qcn9274_rx_desc_mpdu_start_addr2(struct hal_rx_desc *desc) return desc->u.qcn9274.mpdu_start.addr2; } -static bool ath12k_hw_qcn9274_rx_desc_is_mcbc(struct hal_rx_desc *desc) +static bool ath12k_hw_qcn9274_rx_desc_is_da_mcbc(struct hal_rx_desc *desc) { - return __le32_to_cpu(desc->u.qcn9274.mpdu_start.info6) & - RX_MPDU_START_INFO6_MCAST_BCAST; + return __le16_to_cpu(desc->u.qcn9274.msdu_end.info5) & + RX_MSDU_END_INFO5_DA_IS_MCBC; } static void ath12k_hw_qcn9274_rx_desc_get_dot11_hdr(struct hal_rx_desc *desc, @@ -708,7 +708,7 @@ const struct hal_ops hal_qcn9274_ops = { .rx_desc_get_msdu_end_offset = ath12k_hw_qcn9274_rx_desc_get_msdu_end_offset, .rx_desc_mac_addr2_valid = ath12k_hw_qcn9274_rx_desc_mac_addr2_valid, .rx_desc_mpdu_start_addr2 = ath12k_hw_qcn9274_rx_desc_mpdu_start_addr2, - .rx_desc_is_mcbc = ath12k_hw_qcn9274_rx_desc_is_mcbc, + .rx_desc_is_da_mcbc = ath12k_hw_qcn9274_rx_desc_is_da_mcbc, .rx_desc_get_dot11_hdr = ath12k_hw_qcn9274_rx_desc_get_dot11_hdr, .rx_desc_get_crypto_header = ath12k_hw_qcn9274_rx_desc_get_crypto_hdr, .rx_desc_get_mpdu_frame_ctl = ath12k_hw_qcn9274_rx_desc_get_mpdu_frame_ctl, @@ -887,10 +887,10 @@ static u8 *ath12k_hw_wcn7850_rx_desc_mpdu_start_addr2(struct hal_rx_desc *desc) return desc->u.wcn7850.mpdu_start.addr2; } -static bool ath12k_hw_wcn7850_rx_desc_is_mcbc(struct hal_rx_desc *desc) +static bool ath12k_hw_wcn7850_rx_desc_is_da_mcbc(struct hal_rx_desc *desc) { - return __le32_to_cpu(desc->u.wcn7850.mpdu_start.info6) & - RX_MPDU_START_INFO6_MCAST_BCAST; + return __le16_to_cpu(desc->u.wcn7850.msdu_end.info5) & + RX_MSDU_END_INFO5_DA_IS_MCBC; } static void ath12k_hw_wcn7850_rx_desc_get_dot11_hdr(struct hal_rx_desc *desc, @@ -1163,7 +1163,7 @@ const struct hal_ops hal_wcn7850_ops = { .rx_desc_get_msdu_end_offset = ath12k_hw_wcn7850_rx_desc_get_msdu_end_offset, .rx_desc_mac_addr2_valid = ath12k_hw_wcn7850_rx_desc_mac_addr2_valid, .rx_desc_mpdu_start_addr2 = ath12k_hw_wcn7850_rx_desc_mpdu_start_addr2, - .rx_desc_is_mcbc = ath12k_hw_wcn7850_rx_desc_is_mcbc, + .rx_desc_is_da_mcbc = ath12k_hw_wcn7850_rx_desc_is_da_mcbc, .rx_desc_get_dot11_hdr = ath12k_hw_wcn7850_rx_desc_get_dot11_hdr, .rx_desc_get_crypto_header = ath12k_hw_wcn7850_rx_desc_get_crypto_hdr, .rx_desc_get_mpdu_frame_ctl = ath12k_hw_wcn7850_rx_desc_get_mpdu_frame_ctl, diff --git a/drivers/net/wireless/ath/ath12k/hal.h b/drivers/net/wireless/ath/ath12k/hal.h index 0d4fa12ea622ba2c10a792049382394c58bc63b9..66035a787c728dee66e5c062026913d230469431 100644 --- a/drivers/net/wireless/ath/ath12k/hal.h +++ b/drivers/net/wireless/ath/ath12k/hal.h @@ -1063,7 +1063,7 @@ struct hal_ops { u32 (*rx_desc_get_msdu_end_offset)(void); bool (*rx_desc_mac_addr2_valid)(struct hal_rx_desc *desc); u8* (*rx_desc_mpdu_start_addr2)(struct hal_rx_desc *desc); - bool (*rx_desc_is_mcbc)(struct hal_rx_desc *desc); + bool (*rx_desc_is_da_mcbc)(struct hal_rx_desc *desc); void (*rx_desc_get_dot11_hdr)(struct hal_rx_desc *desc, struct ieee80211_hdr *hdr); u16 (*rx_desc_get_mpdu_frame_ctl)(struct hal_rx_desc *desc); diff --git a/drivers/net/wireless/ath/ath12k/hw.c b/drivers/net/wireless/ath/ath12k/hw.c index 1ffac7e3deaaf2efabf2a5553a3a2eb20c3c5cc3..5991cc91cd00f034826eccd96244d355604e7ead 100644 --- a/drivers/net/wireless/ath/ath12k/hw.c +++ b/drivers/net/wireless/ath/ath12k/hw.c @@ -906,6 +906,7 @@ static const struct ath12k_hw_params ath12k_hw_params[] = { .hal_ops = &hal_qcn9274_ops, + .qmi_cnss_feature_bitmap = BIT(CNSS_QDSS_CFG_MISS_V01), }, { .name = "wcn7850 hw2.0", @@ -960,6 +961,9 @@ static const struct ath12k_hw_params ath12k_hw_params[] = { .wmi_init = ath12k_wmi_init_wcn7850, .hal_ops = &hal_wcn7850_ops, + + .qmi_cnss_feature_bitmap = BIT(CNSS_QDSS_CFG_MISS_V01) | + BIT(CNSS_PCIE_PERST_NO_PULL_V01), }, { .name = "qcn9274 hw2.0", @@ -1013,6 +1017,8 @@ static const struct ath12k_hw_params ath12k_hw_params[] = { .wmi_init = ath12k_wmi_init_qcn9274, .hal_ops = &hal_qcn9274_ops, + + .qmi_cnss_feature_bitmap = BIT(CNSS_QDSS_CFG_MISS_V01), }, }; diff --git a/drivers/net/wireless/ath/ath12k/hw.h b/drivers/net/wireless/ath/ath12k/hw.h index e3461004188bd29824693b94512543dcbf67863c..e6c4223c283c30fb0c823ca0c864bf538d84fede 100644 --- a/drivers/net/wireless/ath/ath12k/hw.h +++ b/drivers/net/wireless/ath/ath12k/hw.h @@ -184,6 +184,8 @@ struct ath12k_hw_params { struct ath12k_wmi_resource_config_arg *config); const struct hal_ops *hal_ops; + + u64 qmi_cnss_feature_bitmap; }; struct ath12k_hw_ops { diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c index ee792822b41132ebb3711e1a7e645d2c9477437a..1bb9802ef5696c26639f9a9159f24bc5a540ab2f 100644 --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c @@ -381,7 +381,7 @@ u8 ath12k_mac_bitrate_to_idx(const struct ieee80211_supported_band *sband, } static u32 -ath12k_mac_max_ht_nss(const u8 ht_mcs_mask[IEEE80211_HT_MCS_MASK_LEN]) +ath12k_mac_max_ht_nss(const u8 *ht_mcs_mask) { int nss; @@ -393,7 +393,7 @@ ath12k_mac_max_ht_nss(const u8 ht_mcs_mask[IEEE80211_HT_MCS_MASK_LEN]) } static u32 -ath12k_mac_max_vht_nss(const u16 vht_mcs_mask[NL80211_VHT_NSS_MAX]) +ath12k_mac_max_vht_nss(const u16 *vht_mcs_mask) { int nss; @@ -771,6 +771,9 @@ static int ath12k_mac_vdev_setup_sync(struct ath12k *ar) if (test_bit(ATH12K_FLAG_CRASH_FLUSH, &ar->ab->dev_flags)) return -ESHUTDOWN; + ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "vdev setup timeout %d\n", + ATH12K_VDEV_SETUP_TIMEOUT_HZ); + if (!wait_for_completion_timeout(&ar->vdev_setup_done, ATH12K_VDEV_SETUP_TIMEOUT_HZ)) return -ETIMEDOUT; @@ -1303,7 +1306,7 @@ static void ath12k_peer_assoc_h_rates(struct ath12k *ar, } static bool -ath12k_peer_assoc_h_ht_masked(const u8 ht_mcs_mask[IEEE80211_HT_MCS_MASK_LEN]) +ath12k_peer_assoc_h_ht_masked(const u8 *ht_mcs_mask) { int nss; @@ -1315,7 +1318,7 @@ ath12k_peer_assoc_h_ht_masked(const u8 ht_mcs_mask[IEEE80211_HT_MCS_MASK_LEN]) } static bool -ath12k_peer_assoc_h_vht_masked(const u16 vht_mcs_mask[NL80211_VHT_NSS_MAX]) +ath12k_peer_assoc_h_vht_masked(const u16 *vht_mcs_mask) { int nss; @@ -4375,6 +4378,21 @@ static int __ath12k_set_antenna(struct ath12k *ar, u32 tx_ant, u32 rx_ant) return 0; } +static void ath12k_mgmt_over_wmi_tx_drop(struct ath12k *ar, struct sk_buff *skb) +{ + int num_mgmt; + + ieee80211_free_txskb(ar->hw, skb); + + num_mgmt = atomic_dec_if_positive(&ar->num_pending_mgmt_tx); + + if (num_mgmt < 0) + WARN_ON_ONCE(1); + + if (!num_mgmt) + wake_up(&ar->txmgmt_empty_waitq); +} + int ath12k_mac_tx_mgmt_pending_free(int buf_id, void *skb, void *ctx) { struct sk_buff *msdu = skb; @@ -4391,7 +4409,7 @@ int ath12k_mac_tx_mgmt_pending_free(int buf_id, void *skb, void *ctx) info = IEEE80211_SKB_CB(msdu); memset(&info->status, 0, sizeof(info->status)); - ieee80211_free_txskb(ar->hw, msdu); + ath12k_mgmt_over_wmi_tx_drop(ar, skb); return 0; } @@ -4425,6 +4443,7 @@ static int ath12k_mac_mgmt_tx_wmi(struct ath12k *ar, struct ath12k_vif *arvif, int buf_id; int ret; + ATH12K_SKB_CB(skb)->ar = ar; spin_lock_bh(&ar->txmgmt_idr_lock); buf_id = idr_alloc(&ar->txmgmt_idr, skb, 0, ATH12K_TX_MGMT_NUM_PENDING_MAX, GFP_ATOMIC); @@ -4475,7 +4494,7 @@ static void ath12k_mgmt_over_wmi_tx_purge(struct ath12k *ar) struct sk_buff *skb; while ((skb = skb_dequeue(&ar->wmi_mgmt_tx_queue)) != NULL) - ieee80211_free_txskb(ar->hw, skb); + ath12k_mgmt_over_wmi_tx_drop(ar, skb); } static void ath12k_mgmt_over_wmi_tx_work(struct work_struct *work) @@ -4490,7 +4509,7 @@ static void ath12k_mgmt_over_wmi_tx_work(struct work_struct *work) skb_cb = ATH12K_SKB_CB(skb); if (!skb_cb->vif) { ath12k_warn(ar->ab, "no vif found for mgmt frame\n"); - ieee80211_free_txskb(ar->hw, skb); + ath12k_mgmt_over_wmi_tx_drop(ar, skb); continue; } @@ -4501,16 +4520,14 @@ static void ath12k_mgmt_over_wmi_tx_work(struct work_struct *work) if (ret) { ath12k_warn(ar->ab, "failed to tx mgmt frame, vdev_id %d :%d\n", arvif->vdev_id, ret); - ieee80211_free_txskb(ar->hw, skb); - } else { - atomic_inc(&ar->num_pending_mgmt_tx); + ath12k_mgmt_over_wmi_tx_drop(ar, skb); } } else { ath12k_warn(ar->ab, "dropping mgmt frame for vdev %d, is_started %d\n", arvif->vdev_id, arvif->is_started); - ieee80211_free_txskb(ar->hw, skb); + ath12k_mgmt_over_wmi_tx_drop(ar, skb); } } } @@ -4535,12 +4552,13 @@ static int ath12k_mac_mgmt_tx(struct ath12k *ar, struct sk_buff *skb, return -ENOSPC; } - if (skb_queue_len(q) == ATH12K_TX_MGMT_NUM_PENDING_MAX) { + if (skb_queue_len_lockless(q) >= ATH12K_TX_MGMT_NUM_PENDING_MAX) { ath12k_warn(ar->ab, "mgmt tx queue is full\n"); return -ENOSPC; } skb_queue_tail(q, skb); + atomic_inc(&ar->num_pending_mgmt_tx); ieee80211_queue_work(ar->hw, &ar->wmi_mgmt_tx_work); return 0; @@ -5910,7 +5928,6 @@ ath12k_mac_op_unassign_vif_chanctx(struct ieee80211_hw *hw, } arvif->is_started = false; - mutex_unlock(&ar->conf_mutex); } ret = ath12k_mac_vdev_stop(arvif); @@ -6014,6 +6031,13 @@ static void ath12k_mac_op_flush(struct ieee80211_hw *hw, struct ieee80211_vif *v ATH12K_FLUSH_TIMEOUT); if (time_left == 0) ath12k_warn(ar->ab, "failed to flush transmit queue %ld\n", time_left); + + time_left = wait_event_timeout(ar->txmgmt_empty_waitq, + (atomic_read(&ar->num_pending_mgmt_tx) == 0), + ATH12K_FLUSH_TIMEOUT); + if (time_left == 0) + ath12k_warn(ar->ab, "failed to flush mgmt transmit queue %ld\n", + time_left); } static int @@ -6991,6 +7015,7 @@ int ath12k_mac_register(struct ath12k_base *ab) if (ret) goto err_cleanup; + init_waitqueue_head(&ar->txmgmt_empty_waitq); idr_init(&ar->txmgmt_idr); spin_lock_init(&ar->txmgmt_idr_lock); } diff --git a/drivers/net/wireless/ath/ath12k/pci.c b/drivers/net/wireless/ath/ath12k/pci.c index 9f174daf324c924268eae101a5274ece6e3549ea..5990a55801f0a3991cb588d6c4de65e52228818f 100644 --- a/drivers/net/wireless/ath/ath12k/pci.c +++ b/drivers/net/wireless/ath/ath12k/pci.c @@ -1227,8 +1227,20 @@ static int ath12k_pci_probe(struct pci_dev *pdev, case WCN7850_DEVICE_ID: ab_pci->msi_config = &ath12k_msi_config[0]; ab->static_window_map = false; - ab->hw_rev = ATH12K_HW_WCN7850_HW20; ab_pci->pci_ops = &ath12k_pci_ops_wcn7850; + ath12k_pci_read_hw_version(ab, &soc_hw_version_major, + &soc_hw_version_minor); + switch (soc_hw_version_major) { + case ATH12K_PCI_SOC_HW_VERSION_2: + ab->hw_rev = ATH12K_HW_WCN7850_HW20; + break; + default: + dev_err(&pdev->dev, + "Unknown hardware version found for WCN7850: 0x%x\n", + soc_hw_version_major); + ret = -EOPNOTSUPP; + goto err_pci_free_region; + } break; default: diff --git a/drivers/net/wireless/ath/ath12k/qmi.c b/drivers/net/wireless/ath/ath12k/qmi.c index 03ba245fbee92e85f66fbf003ad6494ecd2d26c0..b510c2de1bd43bedbc8a999c606448c8cec26056 100644 --- a/drivers/net/wireless/ath/ath12k/qmi.c +++ b/drivers/net/wireless/ath/ath12k/qmi.c @@ -1942,8 +1942,10 @@ static int ath12k_qmi_host_cap_send(struct ath12k_base *ab) req.cal_done_valid = 1; req.cal_done = ab->qmi.cal_done; - req.feature_list_valid = 1; - req.feature_list = BIT(CNSS_QDSS_CFG_MISS_V01); + if (ab->hw_params->qmi_cnss_feature_bitmap) { + req.feature_list_valid = 1; + req.feature_list = ab->hw_params->qmi_cnss_feature_bitmap; + } /* BRINGUP: here we are piggybacking a lot of stuff using * internal_sleep_clock, should it be split? @@ -3056,8 +3058,7 @@ int ath12k_qmi_init_service(struct ath12k_base *ab) return ret; } - ab->qmi.event_wq = alloc_workqueue("ath12k_qmi_driver_event", - WQ_UNBOUND, 1); + ab->qmi.event_wq = alloc_ordered_workqueue("ath12k_qmi_driver_event", 0); if (!ab->qmi.event_wq) { ath12k_err(ab, "failed to allocate workqueue\n"); return -EFAULT; diff --git a/drivers/net/wireless/ath/ath12k/qmi.h b/drivers/net/wireless/ath/ath12k/qmi.h index ad87f19903db8f28b9899baa7c27c7d4d4f86f01..df76149c49f5fe5f43cbcd51bb63efca937b7fff 100644 --- a/drivers/net/wireless/ath/ath12k/qmi.h +++ b/drivers/net/wireless/ath/ath12k/qmi.h @@ -189,6 +189,7 @@ struct wlfw_host_mlo_chip_info_s_v01 { enum ath12k_qmi_cnss_feature { CNSS_FEATURE_MIN_ENUM_VAL_V01 = INT_MIN, CNSS_QDSS_CFG_MISS_V01 = 3, + CNSS_PCIE_PERST_NO_PULL_V01 = 4, CNSS_MAX_FEATURE_V01 = 64, CNSS_FEATURE_MAX_ENUM_VAL_V01 = INT_MAX, }; diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c index 7ae0bb78b2b538924ddd8086304679ace7ab3b10..6512267ae4ca5d936be6f0cfe7d83abbc8273318 100644 --- a/drivers/net/wireless/ath/ath12k/wmi.c +++ b/drivers/net/wireless/ath/ath12k/wmi.c @@ -3181,8 +3181,8 @@ ath12k_wmi_copy_resource_config(struct ath12k_wmi_resource_config_params *wmi_cf wmi_cfg->sched_params = cpu_to_le32(tg_cfg->sched_params); wmi_cfg->twt_ap_pdev_count = cpu_to_le32(tg_cfg->twt_ap_pdev_count); wmi_cfg->twt_ap_sta_count = cpu_to_le32(tg_cfg->twt_ap_sta_count); - wmi_cfg->host_service_flags = - cpu_to_le32(1 << WMI_RSRC_CFG_HOST_SVC_FLAG_REG_CC_EXT_SUPPORT_BIT); + wmi_cfg->host_service_flags = cpu_to_le32(tg_cfg->is_reg_cc_ext_event_supported << + WMI_RSRC_CFG_HOST_SVC_FLAG_REG_CC_EXT_SUPPORT_BIT); } static int ath12k_init_cmd_send(struct ath12k_wmi_pdev *wmi, @@ -3390,6 +3390,10 @@ int ath12k_wmi_cmd_init(struct ath12k_base *ab) struct ath12k_wmi_base *wmi_sc = &ab->wmi_ab; struct ath12k_wmi_init_cmd_arg arg = {}; + if (test_bit(WMI_TLV_SERVICE_REG_CC_EXT_EVENT_SUPPORT, + ab->wmi_ab.svc_map)) + arg.res_cfg.is_reg_cc_ext_event_supported = true; + ab->hw_params->wmi_init(ab, &arg.res_cfg); arg.num_mem_chunks = wmi_sc->num_mem_chunks; @@ -4640,6 +4644,7 @@ static int wmi_process_mgmt_tx_comp(struct ath12k *ar, u32 desc_id, struct sk_buff *msdu; struct ieee80211_tx_info *info; struct ath12k_skb_cb *skb_cb; + int num_mgmt; spin_lock_bh(&ar->txmgmt_idr_lock); msdu = idr_find(&ar->txmgmt_idr, desc_id); @@ -4663,10 +4668,15 @@ static int wmi_process_mgmt_tx_comp(struct ath12k *ar, u32 desc_id, ieee80211_tx_status_irqsafe(ar->hw, msdu); + num_mgmt = atomic_dec_if_positive(&ar->num_pending_mgmt_tx); + /* WARN when we received this event without doing any mgmt tx */ - if (atomic_dec_if_positive(&ar->num_pending_mgmt_tx) < 0) + if (num_mgmt < 0) WARN_ON_ONCE(1); + if (!num_mgmt) + wake_up(&ar->txmgmt_empty_waitq); + return 0; } @@ -5979,47 +5989,72 @@ static void ath12k_vdev_install_key_compl_event(struct ath12k_base *ab, rcu_read_unlock(); } -static void ath12k_service_available_event(struct ath12k_base *ab, struct sk_buff *skb) +static int ath12k_wmi_tlv_services_parser(struct ath12k_base *ab, + u16 tag, u16 len, + const void *ptr, + void *data) { - const void **tb; const struct wmi_service_available_event *ev; - int ret; + u32 *wmi_ext2_service_bitmap; int i, j; + u16 expected_len; - tb = ath12k_wmi_tlv_parse_alloc(ab, skb->data, skb->len, GFP_ATOMIC); - if (IS_ERR(tb)) { - ret = PTR_ERR(tb); - ath12k_warn(ab, "failed to parse tlv: %d\n", ret); - return; + expected_len = WMI_SERVICE_SEGMENT_BM_SIZE32 * sizeof(u32); + if (len < expected_len) { + ath12k_warn(ab, "invalid length %d for the WMI services available tag 0x%x\n", + len, tag); + return -EINVAL; } - ev = tb[WMI_TAG_SERVICE_AVAILABLE_EVENT]; - if (!ev) { - ath12k_warn(ab, "failed to fetch svc available ev"); - kfree(tb); - return; - } + switch (tag) { + case WMI_TAG_SERVICE_AVAILABLE_EVENT: + ev = (struct wmi_service_available_event *)ptr; + for (i = 0, j = WMI_MAX_SERVICE; + i < WMI_SERVICE_SEGMENT_BM_SIZE32 && j < WMI_MAX_EXT_SERVICE; + i++) { + do { + if (le32_to_cpu(ev->wmi_service_segment_bitmap[i]) & + BIT(j % WMI_AVAIL_SERVICE_BITS_IN_SIZE32)) + set_bit(j, ab->wmi_ab.svc_map); + } while (++j % WMI_AVAIL_SERVICE_BITS_IN_SIZE32); + } - /* TODO: Use wmi_service_segment_offset information to get the service - * especially when more services are advertised in multiple service - * available events. - */ - for (i = 0, j = WMI_MAX_SERVICE; - i < WMI_SERVICE_SEGMENT_BM_SIZE32 && j < WMI_MAX_EXT_SERVICE; - i++) { - do { - if (le32_to_cpu(ev->wmi_service_segment_bitmap[i]) & - BIT(j % WMI_AVAIL_SERVICE_BITS_IN_SIZE32)) - set_bit(j, ab->wmi_ab.svc_map); - } while (++j % WMI_AVAIL_SERVICE_BITS_IN_SIZE32); + ath12k_dbg(ab, ATH12K_DBG_WMI, + "wmi_ext_service_bitmap 0x%x 0x%x 0x%x 0x%x", + ev->wmi_service_segment_bitmap[0], + ev->wmi_service_segment_bitmap[1], + ev->wmi_service_segment_bitmap[2], + ev->wmi_service_segment_bitmap[3]); + break; + case WMI_TAG_ARRAY_UINT32: + wmi_ext2_service_bitmap = (u32 *)ptr; + for (i = 0, j = WMI_MAX_EXT_SERVICE; + i < WMI_SERVICE_SEGMENT_BM_SIZE32 && j < WMI_MAX_EXT2_SERVICE; + i++) { + do { + if (wmi_ext2_service_bitmap[i] & + BIT(j % WMI_AVAIL_SERVICE_BITS_IN_SIZE32)) + set_bit(j, ab->wmi_ab.svc_map); + } while (++j % WMI_AVAIL_SERVICE_BITS_IN_SIZE32); + } + + ath12k_dbg(ab, ATH12K_DBG_WMI, + "wmi_ext2_service_bitmap 0x%04x 0x%04x 0x%04x 0x%04x", + wmi_ext2_service_bitmap[0], wmi_ext2_service_bitmap[1], + wmi_ext2_service_bitmap[2], wmi_ext2_service_bitmap[3]); + break; } + return 0; +} - ath12k_dbg(ab, ATH12K_DBG_WMI, - "wmi_ext_service_bitmap 0:0x%x, 1:0x%x, 2:0x%x, 3:0x%x", - ev->wmi_service_segment_bitmap[0], ev->wmi_service_segment_bitmap[1], - ev->wmi_service_segment_bitmap[2], ev->wmi_service_segment_bitmap[3]); +static int ath12k_service_available_event(struct ath12k_base *ab, struct sk_buff *skb) +{ + int ret; - kfree(tb); + ret = ath12k_wmi_tlv_iter(ab, skb->data, skb->len, + ath12k_wmi_tlv_services_parser, + NULL); + return ret; } static void ath12k_peer_assoc_conf_event(struct ath12k_base *ab, struct sk_buff *skb) diff --git a/drivers/net/wireless/ath/ath12k/wmi.h b/drivers/net/wireless/ath/ath12k/wmi.h index 08a8c9e0f59fbde74c627f44bf33d560d71b97f0..d89c12bfb009f37013c7198f40a70a04e024a915 100644 --- a/drivers/net/wireless/ath/ath12k/wmi.h +++ b/drivers/net/wireless/ath/ath12k/wmi.h @@ -2148,7 +2148,10 @@ enum wmi_tlv_service { WMI_TLV_SERVICE_FREQINFO_IN_METADATA = 219, WMI_TLV_SERVICE_EXT2_MSG = 220, - WMI_MAX_EXT_SERVICE + WMI_MAX_EXT_SERVICE = 256, + + WMI_TLV_SERVICE_REG_CC_EXT_EVENT_SUPPORT = 281, + WMI_MAX_EXT2_SERVICE, }; enum { @@ -2333,6 +2336,7 @@ struct ath12k_wmi_resource_config_arg { u32 sched_params; u32 twt_ap_pdev_count; u32 twt_ap_sta_count; + bool is_reg_cc_ext_event_supported; }; struct ath12k_wmi_init_cmd_arg { @@ -2682,7 +2686,7 @@ struct ath12k_wmi_ssid_params { u8 ssid[ATH12K_WMI_SSID_LEN]; } __packed; -#define ATH12K_VDEV_SETUP_TIMEOUT_HZ (1 * HZ) +#define ATH12K_VDEV_SETUP_TIMEOUT_HZ (5 * HZ) struct wmi_vdev_start_request_cmd { __le32 tlv_header; @@ -4664,7 +4668,7 @@ struct ath12k_wmi_base { struct completion service_ready; struct completion unified_ready; - DECLARE_BITMAP(svc_map, WMI_MAX_EXT_SERVICE); + DECLARE_BITMAP(svc_map, WMI_MAX_EXT2_SERVICE); wait_queue_head_t tx_credits_wq; const struct wmi_peer_flags_map *peer_flags; u32 num_mem_chunks; diff --git a/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/drivers/net/wireless/ath/ath9k/ar9003_hw.c index 4f27a9fb1482bf2bc82835e182423d6d5133c685..e9bd13eeee92fd89edab2ce46f9b3bb77fe16721 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c @@ -1099,17 +1099,22 @@ static bool ath9k_hw_verify_hang(struct ath_hw *ah, unsigned int queue) { u32 dma_dbg_chain, dma_dbg_complete; u8 dcu_chain_state, dcu_complete_state; + unsigned int dbg_reg, reg_offset; int i; - for (i = 0; i < NUM_STATUS_READS; i++) { - if (queue < 6) - dma_dbg_chain = REG_READ(ah, AR_DMADBG_4); - else - dma_dbg_chain = REG_READ(ah, AR_DMADBG_5); + if (queue < 6) { + dbg_reg = AR_DMADBG_4; + reg_offset = queue * 5; + } else { + dbg_reg = AR_DMADBG_5; + reg_offset = (queue - 6) * 5; + } + for (i = 0; i < NUM_STATUS_READS; i++) { + dma_dbg_chain = REG_READ(ah, dbg_reg); dma_dbg_complete = REG_READ(ah, AR_DMADBG_6); - dcu_chain_state = (dma_dbg_chain >> (5 * queue)) & 0x1f; + dcu_chain_state = (dma_dbg_chain >> reg_offset) & 0x1f; dcu_complete_state = dma_dbg_complete & 0x3; if ((dcu_chain_state != 0x6) || (dcu_complete_state != 0x1)) @@ -1128,6 +1133,7 @@ static bool ar9003_hw_detect_mac_hang(struct ath_hw *ah) u8 dcu_chain_state, dcu_complete_state; bool dcu_wait_frdone = false; unsigned long chk_dcu = 0; + unsigned int reg_offset; unsigned int i = 0; dma_dbg_4 = REG_READ(ah, AR_DMADBG_4); @@ -1139,12 +1145,15 @@ static bool ar9003_hw_detect_mac_hang(struct ath_hw *ah) goto exit; for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { - if (i < 6) + if (i < 6) { chk_dbg = dma_dbg_4; - else + reg_offset = i * 5; + } else { chk_dbg = dma_dbg_5; + reg_offset = (i - 6) * 5; + } - dcu_chain_state = (chk_dbg >> (5 * i)) & 0x1f; + dcu_chain_state = (chk_dbg >> reg_offset) & 0x1f; if (dcu_chain_state == 0x6) { dcu_wait_frdone = true; chk_dcu |= BIT(i); diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.c b/drivers/net/wireless/ath/ath9k/htc_hst.c index fe62ff668f757b621ac773e457f5c42ce7073e20..99667aba289df0c9aeac94c15e7b1992db8907e0 100644 --- a/drivers/net/wireless/ath/ath9k/htc_hst.c +++ b/drivers/net/wireless/ath/ath9k/htc_hst.c @@ -114,7 +114,13 @@ static void htc_process_conn_rsp(struct htc_target *target, if (svc_rspmsg->status == HTC_SERVICE_SUCCESS) { epid = svc_rspmsg->endpoint_id; - if (epid < 0 || epid >= ENDPOINT_MAX) + + /* Check that the received epid for the endpoint to attach + * a new service is valid. ENDPOINT0 can't be used here as it + * is already reserved for HTC_CTRL_RSVD_SVC service and thus + * should not be modified. + */ + if (epid <= ENDPOINT0 || epid >= ENDPOINT_MAX) return; service_id = be16_to_cpu(svc_rspmsg->service_id); diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index a4197c14f0a9202b36c073af6a00edb50f005f75..6360d3356e25648f0340a9c71d9665e9a426541a 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -203,7 +203,7 @@ void ath_cancel_work(struct ath_softc *sc) void ath_restart_work(struct ath_softc *sc) { ieee80211_queue_delayed_work(sc->hw, &sc->hw_check_work, - ATH_HW_CHECK_POLL_INT); + msecs_to_jiffies(ATH_HW_CHECK_POLL_INT)); if (AR_SREV_9340(sc->sc_ah) || AR_SREV_9330(sc->sc_ah)) ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, @@ -850,7 +850,7 @@ static bool ath9k_txq_list_has_key(struct list_head *txq_list, u32 keyix) static bool ath9k_txq_has_key(struct ath_softc *sc, u32 keyix) { struct ath_hw *ah = sc->sc_ah; - int i; + int i, j; struct ath_txq *txq; bool key_in_use = false; @@ -868,8 +868,9 @@ static bool ath9k_txq_has_key(struct ath_softc *sc, u32 keyix) if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) { int idx = txq->txq_tailidx; - while (!key_in_use && - !list_empty(&txq->txq_fifo[idx])) { + for (j = 0; !key_in_use && + !list_empty(&txq->txq_fifo[idx]) && + j < ATH_TXFIFO_DEPTH; j++) { key_in_use = ath9k_txq_list_has_key( &txq->txq_fifo[idx], keyix); INCR(idx, ATH_TXFIFO_DEPTH); @@ -2239,7 +2240,7 @@ void __ath9k_flush(struct ieee80211_hw *hw, u32 queues, bool drop, } ieee80211_queue_delayed_work(hw, &sc->hw_check_work, - ATH_HW_CHECK_POLL_INT); + msecs_to_jiffies(ATH_HW_CHECK_POLL_INT)); } static bool ath9k_tx_frames_pending(struct ieee80211_hw *hw) diff --git a/drivers/net/wireless/ath/ath9k/wmi.c b/drivers/net/wireless/ath/ath9k/wmi.c index 19345b8f7bfd59f04361356668cbe22506af633a..d652c647d56b5557b59f93afbdc5dcd60c38c9e3 100644 --- a/drivers/net/wireless/ath/ath9k/wmi.c +++ b/drivers/net/wireless/ath/ath9k/wmi.c @@ -221,6 +221,10 @@ static void ath9k_wmi_ctrl_rx(void *priv, struct sk_buff *skb, if (unlikely(wmi->stopped)) goto free_skb; + /* Validate the obtained SKB. */ + if (unlikely(skb->len < sizeof(struct wmi_cmd_hdr))) + goto free_skb; + hdr = (struct wmi_cmd_hdr *) skb->data; cmd_id = be16_to_cpu(hdr->command_id); diff --git a/drivers/net/wireless/ath/wil6210/fw.h b/drivers/net/wireless/ath/wil6210/fw.h index 440614d61156a7d78931dff295f8abbb7126b840..aa1620e0d24fab17f44c7a5fec79370c098be03a 100644 --- a/drivers/net/wireless/ath/wil6210/fw.h +++ b/drivers/net/wireless/ath/wil6210/fw.h @@ -47,7 +47,7 @@ struct wil_fw_record_fill { /* type == wil_fw_type_fill */ * for informational purpose, data_size is @head.size from record header */ struct wil_fw_record_comment { /* type == wil_fw_type_comment */ - u8 data[0]; /* free-form data [data_size], see above */ + DECLARE_FLEX_ARRAY(u8, data); /* free-form data [data_size], see above */ } __packed; /* Comment header - common for all comment record types */ @@ -131,7 +131,7 @@ struct wil_fw_data_dwrite { * data_size is @head.size where @head is record header */ struct wil_fw_record_direct_write { /* type == wil_fw_type_direct_write */ - struct wil_fw_data_dwrite data[0]; + DECLARE_FLEX_ARRAY(struct wil_fw_data_dwrite, data); } __packed; /* verify condition: [@addr] & @mask == @value diff --git a/drivers/net/wireless/ath/wil6210/wmi.h b/drivers/net/wireless/ath/wil6210/wmi.h index 9affa452560957a0292cebc9623d692b2f34d244..71bf2ae27a984f146117a712b4a460befaa3dfb2 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.h +++ b/drivers/net/wireless/ath/wil6210/wmi.h @@ -2763,7 +2763,7 @@ struct wmi_rf_xpm_write_result_event { /* WMI_TX_MGMT_PACKET_EVENTID */ struct wmi_tx_mgmt_packet_event { - u8 payload[0]; + DECLARE_FLEX_ARRAY(u8, payload); } __packed; /* WMI_RX_MGMT_PACKET_EVENTID */ diff --git a/drivers/net/wireless/atmel/Kconfig b/drivers/net/wireless/atmel/Kconfig index ca45a1021cf4ea34a4eaceb929d3ff86ed92026b..bafdd57b049a11957bab4dc36ae3697dea525873 100644 --- a/drivers/net/wireless/atmel/Kconfig +++ b/drivers/net/wireless/atmel/Kconfig @@ -14,7 +14,7 @@ if WLAN_VENDOR_ATMEL config ATMEL tristate "Atmel at76c50x chipset 802.11b support" - depends on CFG80211 && (PCI || PCMCIA) + depends on CFG80211 && (PCI || PCMCIA) && HAS_IOPORT select WIRELESS_EXT select WEXT_PRIV select FW_LOADER diff --git a/drivers/net/wireless/atmel/atmel_cs.c b/drivers/net/wireless/atmel/atmel_cs.c index 453bb84cb3386b002b3f16118a673539f61bd6aa..58bba9875d366726f0f6b6348aece627bb9a1297 100644 --- a/drivers/net/wireless/atmel/atmel_cs.c +++ b/drivers/net/wireless/atmel/atmel_cs.c @@ -72,6 +72,7 @@ struct local_info { static int atmel_probe(struct pcmcia_device *p_dev) { struct local_info *local; + int ret; dev_dbg(&p_dev->dev, "atmel_attach()\n"); @@ -82,8 +83,16 @@ static int atmel_probe(struct pcmcia_device *p_dev) p_dev->priv = local; - return atmel_config(p_dev); -} /* atmel_attach */ + ret = atmel_config(p_dev); + if (ret) + goto err_free_priv; + + return 0; + +err_free_priv: + kfree(p_dev->priv); + return ret; +} static void atmel_detach(struct pcmcia_device *link) { diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c index 9f9bf08a70bb46ca3f9d59d3b89413559b28a220..2ef92ef25517e8e90ea12e4d2c8b86ed66a6e4dd 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c @@ -972,6 +972,7 @@ static int brcmf_chip_recognition(struct brcmf_chip_priv *ci) u32 regdata; u32 socitype; int ret; + const u32 READ_FAILED = 0xFFFFFFFF; /* Get CC core rev * Chipid is assume to be at offset 0 from SI_ENUM_BASE @@ -980,6 +981,11 @@ static int brcmf_chip_recognition(struct brcmf_chip_priv *ci) */ regdata = ci->ops->read32(ci->ctx, CORE_CC_REG(ci->pub.enum_base, chipid)); + if (regdata == READ_FAILED) { + brcmf_err("MMIO read failed: 0x%08x\n", regdata); + return -ENODEV; + } + ci->pub.chip = regdata & CID_ID_MASK; ci->pub.chiprev = (regdata & CID_REV_MASK) >> CID_REV_SHIFT; socitype = (regdata & CID_TYPE_MASK) >> CID_TYPE_SHIFT; diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/tracepoint.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/tracepoint.h index 5a139d7ed47aac4f744b27892b137e1c0b77c98c..5d66e94c806d59a56cc9920655c4e9a233e2cc53 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/tracepoint.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/tracepoint.h @@ -28,6 +28,11 @@ static inline void trace_ ## name(proto) {} #define MAX_MSG_LEN 100 +#pragma GCC diagnostic push +#ifndef __clang__ +#pragma GCC diagnostic ignored "-Wsuggest-attribute=format" +#endif + TRACE_EVENT(brcmf_err, TP_PROTO(const char *func, struct va_format *vaf), TP_ARGS(func, vaf), @@ -123,6 +128,8 @@ TRACE_EVENT(brcmf_sdpcm_hdr, __entry->len, ((u8 *)__get_dynamic_array(hdr))[4]) ); +#pragma GCC diagnostic pop + #ifdef CONFIG_BRCM_TRACING #undef TRACE_INCLUDE_PATH diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/wcc/core.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/wcc/core.c index 02de99818efa7094b3e81d85330a9960f8ae7fa1..5573a47766ad5f74dec03af406a0726e84e89b93 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/wcc/core.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/wcc/core.c @@ -12,13 +12,13 @@ static int brcmf_wcc_attach(struct brcmf_pub *drvr) { - pr_err("%s: executing\n", __func__); + pr_debug("%s: executing\n", __func__); return 0; } static void brcmf_wcc_detach(struct brcmf_pub *drvr) { - pr_err("%s: executing\n", __func__); + pr_debug("%s: executing\n", __func__); } const struct brcmf_fwvid_ops brcmf_wcc_ops = { diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/brcms_trace_brcmsmac_msg.h b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/brcms_trace_brcmsmac_msg.h index 4884564203530b2b056978f8d2f0e82f195faca8..42b0a91656c45f9f3969282d2926771e8e890cca 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/brcms_trace_brcmsmac_msg.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/brcms_trace_brcmsmac_msg.h @@ -24,6 +24,11 @@ #define MAX_MSG_LEN 100 +#pragma GCC diagnostic push +#ifndef __clang__ +#pragma GCC diagnostic ignored "-Wsuggest-attribute=format" +#endif + DECLARE_EVENT_CLASS(brcms_msg_event, TP_PROTO(struct va_format *vaf), TP_ARGS(vaf), @@ -71,6 +76,9 @@ TRACE_EVENT(brcms_dbg, ), TP_printk("%s: %s", __get_str(func), __get_str(msg)) ); + +#pragma GCC diagnostic pop + #endif /* __TRACE_BRCMSMAC_MSG_H */ #ifdef CONFIG_BRCM_TRACING diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmutil/utils.c b/drivers/net/wireless/broadcom/brcm80211/brcmutil/utils.c index e87e68cc46e22969f75c6deb22a30b97839bd39c..fe94db0ba3f33c01dc04c58f8f79d012feca7f26 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmutil/utils.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmutil/utils.c @@ -186,7 +186,7 @@ struct sk_buff *brcmu_pktq_peek_tail(struct pktq *pq, int *prec_out) { int prec; - if (pq->len == 0) + if (pktq_empty(pq)) return NULL; for (prec = 0; prec < pq->hi_prec; prec++) @@ -223,7 +223,7 @@ struct sk_buff *brcmu_pktq_mdeq(struct pktq *pq, uint prec_bmp, struct sk_buff *p; int prec; - if (pq->len == 0) + if (pktq_empty(pq)) return NULL; while ((prec = pq->hi_prec) > 0 && diff --git a/drivers/net/wireless/cisco/airo.c b/drivers/net/wireless/cisco/airo.c index 7c4cc5f5e1eb463d02e89f380ee074d8db543ccf..dbd13f7aa3e6ead9f31a4e4f3fe46080fafba973 100644 --- a/drivers/net/wireless/cisco/airo.c +++ b/drivers/net/wireless/cisco/airo.c @@ -6157,8 +6157,11 @@ static int airo_get_rate(struct net_device *dev, struct iw_param *vwrq = &wrqu->bitrate; struct airo_info *local = dev->ml_priv; StatusRid status_rid; /* Card status info */ + int ret; - readStatusRid(local, &status_rid, 1); + ret = readStatusRid(local, &status_rid, 1); + if (ret) + return -EBUSY; vwrq->value = le16_to_cpu(status_rid.currentXmitRate) * 500000; /* If more than one rate, set auto */ diff --git a/drivers/net/wireless/intel/iwlwifi/Makefile b/drivers/net/wireless/intel/iwlwifi/Makefile index 75a703eb1bdf452ad4dcab51803bdbb5169bbaea..b983982aee454c1795b27a3926f91fde23d21083 100644 --- a/drivers/net/wireless/intel/iwlwifi/Makefile +++ b/drivers/net/wireless/intel/iwlwifi/Makefile @@ -11,6 +11,7 @@ iwlwifi-objs += pcie/ctxt-info.o pcie/ctxt-info-gen3.o iwlwifi-objs += pcie/trans-gen2.o pcie/tx-gen2.o iwlwifi-$(CONFIG_IWLDVM) += cfg/1000.o cfg/2000.o cfg/5000.o cfg/6000.o iwlwifi-$(CONFIG_IWLMVM) += cfg/7000.o cfg/8000.o cfg/9000.o cfg/22000.o +iwlwifi-$(CONFIG_IWLMVM) += cfg/ax210.o cfg/bz.o cfg/sc.o iwlwifi-objs += iwl-dbg-tlv.o iwlwifi-objs += iwl-trans.o iwlwifi-objs += queue/tx.o diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/1000.c b/drivers/net/wireless/intel/iwlwifi/cfg/1000.c index 116defb15afbdf23635cf0cd3f7a779ecf3d2782..f172ffd2a84165639cab5f518d2597d70f772ecc 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/1000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/1000.c @@ -2,7 +2,7 @@ /****************************************************************************** * * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved. - * Copyright(c) 2018 - 2020 Intel Corporation + * Copyright(c) 2018 - 2020, 2023 Intel Corporation *****************************************************************************/ #include @@ -22,11 +22,11 @@ #define EEPROM_1000_TX_POWER_VERSION (4) #define EEPROM_1000_EEPROM_VERSION (0x15C) -#define IWL1000_FW_PRE "iwlwifi-1000-" -#define IWL1000_MODULE_FIRMWARE(api) IWL1000_FW_PRE __stringify(api) ".ucode" +#define IWL1000_FW_PRE "iwlwifi-1000" +#define IWL1000_MODULE_FIRMWARE(api) IWL1000_FW_PRE "-" __stringify(api) ".ucode" -#define IWL100_FW_PRE "iwlwifi-100-" -#define IWL100_MODULE_FIRMWARE(api) IWL100_FW_PRE __stringify(api) ".ucode" +#define IWL100_FW_PRE "iwlwifi-100" +#define IWL100_MODULE_FIRMWARE(api) IWL100_FW_PRE "-" __stringify(api) ".ucode" static const struct iwl_base_params iwl1000_base_params = { diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/2000.c b/drivers/net/wireless/intel/iwlwifi/cfg/2000.c index ab2038a3fbe21b0ab820f19487b999aa17b982ef..6f3f26da0ad51d6773986617322e250fcf351ccc 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/2000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/2000.c @@ -2,7 +2,7 @@ /****************************************************************************** * * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved. - * Copyright(c) 2018 - 2020 Intel Corporation + * Copyright(c) 2018 - 2020, 2023 Intel Corporation *****************************************************************************/ #include @@ -28,17 +28,17 @@ #define EEPROM_2000_EEPROM_VERSION (0x805) -#define IWL2030_FW_PRE "iwlwifi-2030-" -#define IWL2030_MODULE_FIRMWARE(api) IWL2030_FW_PRE __stringify(api) ".ucode" +#define IWL2030_FW_PRE "iwlwifi-2030" +#define IWL2030_MODULE_FIRMWARE(api) IWL2030_FW_PRE "-" __stringify(api) ".ucode" -#define IWL2000_FW_PRE "iwlwifi-2000-" -#define IWL2000_MODULE_FIRMWARE(api) IWL2000_FW_PRE __stringify(api) ".ucode" +#define IWL2000_FW_PRE "iwlwifi-2000" +#define IWL2000_MODULE_FIRMWARE(api) IWL2000_FW_PRE "-" __stringify(api) ".ucode" -#define IWL105_FW_PRE "iwlwifi-105-" -#define IWL105_MODULE_FIRMWARE(api) IWL105_FW_PRE __stringify(api) ".ucode" +#define IWL105_FW_PRE "iwlwifi-105" +#define IWL105_MODULE_FIRMWARE(api) IWL105_FW_PRE "-" __stringify(api) ".ucode" -#define IWL135_FW_PRE "iwlwifi-135-" -#define IWL135_MODULE_FIRMWARE(api) IWL135_FW_PRE __stringify(api) ".ucode" +#define IWL135_FW_PRE "iwlwifi-135" +#define IWL135_MODULE_FIRMWARE(api) IWL135_FW_PRE "-" __stringify(api) ".ucode" static const struct iwl_base_params iwl2000_base_params = { .eeprom_size = OTP_LOW_IMAGE_SIZE_2K, diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c index b6f82510e9807b972a7bded7aae3c9633e33aaf2..d594694206b33aaa2846071991dbb2e106cfb48b 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* * Copyright (C) 2015-2017 Intel Deutschland GmbH - * Copyright (C) 2018-2022 Intel Corporation + * Copyright (C) 2018-2023 Intel Corporation */ #include #include @@ -10,10 +10,10 @@ #include "fw/api/txq.h" /* Highest firmware API version supported */ -#define IWL_22000_UCODE_API_MAX 78 +#define IWL_22000_UCODE_API_MAX 77 /* Lowest firmware API version supported */ -#define IWL_22000_UCODE_API_MIN 39 +#define IWL_22000_UCODE_API_MIN 50 /* NVM versions */ #define IWL_22000_NVM_VERSION 0x0a1d @@ -26,162 +26,26 @@ #define IWL_22000_SMEM_OFFSET 0x400000 #define IWL_22000_SMEM_LEN 0xD0000 -#define IWL_QU_B_HR_B_FW_PRE "iwlwifi-Qu-b0-hr-b0-" -#define IWL_QNJ_B_HR_B_FW_PRE "iwlwifi-QuQnj-b0-hr-b0-" -#define IWL_QU_C_HR_B_FW_PRE "iwlwifi-Qu-c0-hr-b0-" -#define IWL_QU_B_JF_B_FW_PRE "iwlwifi-Qu-b0-jf-b0-" -#define IWL_QU_C_JF_B_FW_PRE "iwlwifi-Qu-c0-jf-b0-" -#define IWL_QUZ_A_HR_B_FW_PRE "iwlwifi-QuZ-a0-hr-b0-" -#define IWL_QUZ_A_JF_B_FW_PRE "iwlwifi-QuZ-a0-jf-b0-" -#define IWL_QNJ_B_JF_B_FW_PRE "iwlwifi-QuQnj-b0-jf-b0-" -#define IWL_CC_A_FW_PRE "iwlwifi-cc-a0-" -#define IWL_SO_A_JF_B_FW_PRE "iwlwifi-so-a0-jf-b0-" -#define IWL_SO_A_HR_B_FW_PRE "iwlwifi-so-a0-hr-b0-" -#define IWL_SO_A_GF_A_FW_PRE "iwlwifi-so-a0-gf-a0-" -#define IWL_TY_A_GF_A_FW_PRE "iwlwifi-ty-a0-gf-a0-" -#define IWL_SO_A_GF4_A_FW_PRE "iwlwifi-so-a0-gf4-a0-" -#define IWL_SO_A_MR_A_FW_PRE "iwlwifi-so-a0-mr-a0-" -#define IWL_SNJ_A_GF4_A_FW_PRE "iwlwifi-SoSnj-a0-gf4-a0-" -#define IWL_SNJ_A_GF_A_FW_PRE "iwlwifi-SoSnj-a0-gf-a0-" -#define IWL_SNJ_A_HR_B_FW_PRE "iwlwifi-SoSnj-a0-hr-b0-" -#define IWL_SNJ_A_JF_B_FW_PRE "iwlwifi-SoSnj-a0-jf-b0-" -#define IWL_MA_A_HR_B_FW_PRE "iwlwifi-ma-a0-hr-b0-" -#define IWL_MA_A_GF_A_FW_PRE "iwlwifi-ma-a0-gf-a0-" -#define IWL_MA_A_GF4_A_FW_PRE "iwlwifi-ma-a0-gf4-a0-" -#define IWL_MA_A_MR_A_FW_PRE "iwlwifi-ma-a0-mr-a0-" -#define IWL_MA_A_FM_A_FW_PRE "iwlwifi-ma-a0-fm-a0-" -#define IWL_MA_B_HR_B_FW_PRE "iwlwifi-ma-b0-hr-b0-" -#define IWL_MA_B_GF_A_FW_PRE "iwlwifi-ma-b0-gf-a0-" -#define IWL_MA_B_GF4_A_FW_PRE "iwlwifi-ma-b0-gf4-a0-" -#define IWL_MA_B_MR_A_FW_PRE "iwlwifi-ma-b0-mr-a0-" -#define IWL_MA_B_FM_A_FW_PRE "iwlwifi-ma-b0-fm-a0-" -#define IWL_SNJ_A_MR_A_FW_PRE "iwlwifi-SoSnj-a0-mr-a0-" -#define IWL_BZ_A_HR_A_FW_PRE "iwlwifi-bz-a0-hr-b0-" -#define IWL_BZ_A_HR_B_FW_PRE "iwlwifi-bz-a0-hr-b0-" -#define IWL_BZ_A_GF_A_FW_PRE "iwlwifi-bz-a0-gf-a0-" -#define IWL_BZ_A_GF4_A_FW_PRE "iwlwifi-bz-a0-gf4-a0-" -#define IWL_BZ_A_MR_A_FW_PRE "iwlwifi-bz-a0-mr-a0-" -#define IWL_BZ_A_FM_A_FW_PRE "iwlwifi-bz-a0-fm-a0-" -#define IWL_BZ_A_FM4_A_FW_PRE "iwlwifi-bz-a0-fm4-a0-" -#define IWL_BZ_A_FM_B_FW_PRE "iwlwifi-bz-a0-fm-b0-" -#define IWL_BZ_A_FM4_B_FW_PRE "iwlwifi-bz-a0-fm4-b0-" -#define IWL_GL_A_FM_A_FW_PRE "iwlwifi-gl-a0-fm-a0-" -#define IWL_GL_B_FM_B_FW_PRE "iwlwifi-gl-b0-fm-b0-" -#define IWL_BZ_Z_GF_A_FW_PRE "iwlwifi-bz-z0-gf-a0-" -#define IWL_BNJ_A_FM_A_FW_PRE "iwlwifi-BzBnj-a0-fm-a0-" -#define IWL_BNJ_A_FM4_A_FW_PRE "iwlwifi-BzBnj-a0-fm4-a0-" -#define IWL_BNJ_B_FM4_B_FW_PRE "iwlwifi-BzBnj-b0-fm4-b0-" -#define IWL_BNJ_A_GF_A_FW_PRE "iwlwifi-BzBnj-a0-gf-a0-" -#define IWL_BNJ_B_GF_A_FW_PRE "iwlwifi-BzBnj-b0-gf-a0-" -#define IWL_BNJ_A_GF4_A_FW_PRE "iwlwifi-BzBnj-a0-gf4-a0-" -#define IWL_BNJ_B_GF4_A_FW_PRE "iwlwifi-BzBnj-b0-gf4-a0-" -#define IWL_BNJ_A_HR_A_FW_PRE "iwlwifi-BzBnj-a0-hr-b0-" -#define IWL_BNJ_A_HR_B_FW_PRE "iwlwifi-BzBnj-a0-hr-b0-" -#define IWL_BNJ_B_HR_A_FW_PRE "iwlwifi-BzBnj-b0-hr-b0-" -#define IWL_BNJ_B_HR_B_FW_PRE "iwlwifi-BzBnj-b0-hr-b0-" -#define IWL_BNJ_B_FM_B_FW_PRE "iwlwifi-BzBnj-b0-fm-b0-" - +#define IWL_QU_B_HR_B_FW_PRE "iwlwifi-Qu-b0-hr-b0" +#define IWL_QU_C_HR_B_FW_PRE "iwlwifi-Qu-c0-hr-b0" +#define IWL_QU_B_JF_B_FW_PRE "iwlwifi-Qu-b0-jf-b0" +#define IWL_QU_C_JF_B_FW_PRE "iwlwifi-Qu-c0-jf-b0" +#define IWL_QUZ_A_HR_B_FW_PRE "iwlwifi-QuZ-a0-hr-b0" +#define IWL_QUZ_A_JF_B_FW_PRE "iwlwifi-QuZ-a0-jf-b0" +#define IWL_CC_A_FW_PRE "iwlwifi-cc-a0" #define IWL_QU_B_HR_B_MODULE_FIRMWARE(api) \ - IWL_QU_B_HR_B_FW_PRE __stringify(api) ".ucode" -#define IWL_QNJ_B_HR_B_MODULE_FIRMWARE(api) \ - IWL_QNJ_B_HR_B_FW_PRE __stringify(api) ".ucode" + IWL_QU_B_HR_B_FW_PRE "-" __stringify(api) ".ucode" #define IWL_QUZ_A_HR_B_MODULE_FIRMWARE(api) \ - IWL_QUZ_A_HR_B_FW_PRE __stringify(api) ".ucode" + IWL_QUZ_A_HR_B_FW_PRE "-" __stringify(api) ".ucode" #define IWL_QUZ_A_JF_B_MODULE_FIRMWARE(api) \ - IWL_QUZ_A_JF_B_FW_PRE __stringify(api) ".ucode" + IWL_QUZ_A_JF_B_FW_PRE "-" __stringify(api) ".ucode" #define IWL_QU_C_HR_B_MODULE_FIRMWARE(api) \ - IWL_QU_C_HR_B_FW_PRE __stringify(api) ".ucode" + IWL_QU_C_HR_B_FW_PRE "-" __stringify(api) ".ucode" #define IWL_QU_B_JF_B_MODULE_FIRMWARE(api) \ - IWL_QU_B_JF_B_FW_PRE __stringify(api) ".ucode" -#define IWL_QNJ_B_JF_B_MODULE_FIRMWARE(api) \ - IWL_QNJ_B_JF_B_FW_PRE __stringify(api) ".ucode" + IWL_QU_B_JF_B_FW_PRE "-" __stringify(api) ".ucode" #define IWL_CC_A_MODULE_FIRMWARE(api) \ - IWL_CC_A_FW_PRE __stringify(api) ".ucode" -#define IWL_SO_A_JF_B_MODULE_FIRMWARE(api) \ - IWL_SO_A_JF_B_FW_PRE __stringify(api) ".ucode" -#define IWL_SO_A_HR_B_MODULE_FIRMWARE(api) \ - IWL_SO_A_HR_B_FW_PRE __stringify(api) ".ucode" -#define IWL_SO_A_GF_A_MODULE_FIRMWARE(api) \ - IWL_SO_A_GF_A_FW_PRE __stringify(api) ".ucode" -#define IWL_TY_A_GF_A_MODULE_FIRMWARE(api) \ - IWL_TY_A_GF_A_FW_PRE __stringify(api) ".ucode" -#define IWL_SNJ_A_GF4_A_MODULE_FIRMWARE(api) \ - IWL_SNJ_A_GF4_A_FW_PRE __stringify(api) ".ucode" -#define IWL_SNJ_A_GF_A_MODULE_FIRMWARE(api) \ - IWL_SNJ_A_GF_A_FW_PRE __stringify(api) ".ucode" -#define IWL_SNJ_A_HR_B_MODULE_FIRMWARE(api) \ - IWL_SNJ_A_HR_B_FW_PRE __stringify(api) ".ucode" -#define IWL_SNJ_A_JF_B_MODULE_FIRMWARE(api) \ - IWL_SNJ_A_JF_B_FW_PRE __stringify(api) ".ucode" -#define IWL_MA_A_HR_B_FW_MODULE_FIRMWARE(api) \ - IWL_MA_A_HR_B_FW_PRE __stringify(api) ".ucode" -#define IWL_MA_A_GF_A_FW_MODULE_FIRMWARE(api) \ - IWL_MA_A_GF_A_FW_PRE __stringify(api) ".ucode" -#define IWL_MA_A_GF4_A_FW_MODULE_FIRMWARE(api) \ - IWL_MA_A_GF4_A_FW_PRE __stringify(api) ".ucode" -#define IWL_MA_A_MR_A_FW_MODULE_FIRMWARE(api) \ - IWL_MA_A_MR_A_FW_PRE __stringify(api) ".ucode" -#define IWL_MA_A_FM_A_FW_MODULE_FIRMWARE(api) \ - IWL_MA_A_FM_A_FW_PRE __stringify(api) ".ucode" -#define IWL_MA_B_HR_B_FW_MODULE_FIRMWARE(api) \ - IWL_MA_B_HR_B_FW_PRE __stringify(api) ".ucode" -#define IWL_MA_B_GF_A_FW_MODULE_FIRMWARE(api) \ - IWL_MA_B_GF_A_FW_PRE __stringify(api) ".ucode" -#define IWL_MA_B_GF4_A_FW_MODULE_FIRMWARE(api) \ - IWL_MA_B_GF4_A_FW_PRE __stringify(api) ".ucode" -#define IWL_MA_B_MR_A_FW_MODULE_FIRMWARE(api) \ - IWL_MA_B_MR_A_FW_PRE __stringify(api) ".ucode" -#define IWL_MA_B_FM_A_FW_MODULE_FIRMWARE(api) \ - IWL_MA_B_FM_A_FW_PRE __stringify(api) ".ucode" -#define IWL_SNJ_A_MR_A_MODULE_FIRMWARE(api) \ - IWL_SNJ_A_MR_A_FW_PRE __stringify(api) ".ucode" -#define IWL_BZ_A_HR_A_MODULE_FIRMWARE(api) \ - IWL_BZ_A_HR_A_FW_PRE __stringify(api) ".ucode" -#define IWL_BZ_A_HR_B_MODULE_FIRMWARE(api) \ - IWL_BZ_A_HR_B_FW_PRE __stringify(api) ".ucode" -#define IWL_BZ_A_GF_A_MODULE_FIRMWARE(api) \ - IWL_BZ_A_GF_A_FW_PRE __stringify(api) ".ucode" -#define IWL_BZ_A_GF4_A_MODULE_FIRMWARE(api) \ - IWL_BZ_A_GF4_A_FW_PRE __stringify(api) ".ucode" -#define IWL_BZ_A_MR_A_MODULE_FIRMWARE(api) \ - IWL_BZ_A_MR_A_FW_PRE __stringify(api) ".ucode" -#define IWL_BZ_A_FM_A_MODULE_FIRMWARE(api) \ - IWL_BZ_A_FM_A_FW_PRE __stringify(api) ".ucode" -#define IWL_BZ_A_FM4_A_MODULE_FIRMWARE(api) \ - IWL_BZ_A_FM4_A_FW_PRE __stringify(api) ".ucode" -#define IWL_BZ_A_FM_B_MODULE_FIRMWARE(api) \ - IWL_BZ_A_FM_B_FW_PRE __stringify(api) ".ucode" -#define IWL_BZ_A_FM4_B_MODULE_FIRMWARE(api) \ - IWL_BZ_A_FM4_B_FW_PRE __stringify(api) ".ucode" -#define IWL_GL_A_FM_A_MODULE_FIRMWARE(api) \ - IWL_GL_A_FM_A_FW_PRE __stringify(api) ".ucode" -#define IWL_GL_B_FM_B_MODULE_FIRMWARE(api) \ - IWL_GL_B_FM_B_FW_PRE __stringify(api) ".ucode" -#define IWL_BNJ_A_FM_A_MODULE_FIRMWARE(api) \ - IWL_BNJ_A_FM_A_FW_PRE __stringify(api) ".ucode" -#define IWL_BNJ_A_FM4_A_MODULE_FIRMWARE(api) \ - IWL_BNJ_A_FM4_A_FW_PRE __stringify(api) ".ucode" -#define IWL_BNJ_B_FM4_B_MODULE_FIRMWARE(api) \ - IWL_BNJ_B_FM4_B_FW_PRE __stringify(api) ".ucode" -#define IWL_BNJ_A_GF_A_MODULE_FIRMWARE(api) \ - IWL_BNJ_A_GF_A_FW_PRE __stringify(api) ".ucode" -#define IWL_BNJ_B_GF_A_MODULE_FIRMWARE(api) \ - IWL_BNJ_B_GF_A_FW_PRE __stringify(api) ".ucode" -#define IWL_BNJ_A_GF4_A_MODULE_FIRMWARE(api) \ - IWL_BNJ_A_GF4_A_FW_PRE __stringify(api) ".ucode" -#define IWL_BNJ_B_GF4_A_MODULE_FIRMWARE(api) \ - IWL_BNJ_B_GF4_A_FW_PRE __stringify(api) ".ucode" -#define IWL_BNJ_A_HR_A_MODULE_FIRMWARE(api) \ - IWL_BNJ_A_HR_A_FW_PRE __stringify(api) ".ucode" -#define IWL_BNJ_A_HR_B_MODULE_FIRMWARE(api) \ - IWL_BNJ_A_HR_B_FW_PRE __stringify(api) ".ucode" -#define IWL_BNJ_B_HR_A_MODULE_FIRMWARE(api) \ - IWL_BNJ_B_HR_A_FW_PRE __stringify(api) ".ucode" -#define IWL_BNJ_B_HR_B_MODULE_FIRMWARE(api) \ - IWL_BNJ_B_HR_B_FW_PRE __stringify(api) ".ucode" -#define IWL_BNJ_B_FM_B_MODULE_FIRMWARE(api) \ - IWL_BNJ_B_FM_B_FW_PRE __stringify(api) ".ucode" + IWL_CC_A_FW_PRE "-" __stringify(api) ".ucode" static const struct iwl_base_params iwl_22000_base_params = { .eeprom_size = OTP_LOW_IMAGE_SIZE_32K, @@ -195,34 +59,14 @@ static const struct iwl_base_params iwl_22000_base_params = { .pcie_l1_allowed = true, }; -static const struct iwl_base_params iwl_ax210_base_params = { - .eeprom_size = OTP_LOW_IMAGE_SIZE_32K, - .num_of_queues = 512, - .max_tfd_queue_size = 65536, - .shadow_ram_support = true, - .led_compensation = 57, - .wd_timeout = IWL_LONG_WD_TIMEOUT, - .max_event_log_size = 512, - .shadow_reg_enable = true, - .pcie_l1_allowed = true, -}; - -static const struct iwl_ht_params iwl_22000_ht_params = { +const struct iwl_ht_params iwl_22000_ht_params = { .stbc = true, .ldpc = true, .ht40_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ) | BIT(NL80211_BAND_6GHZ), }; -static const struct iwl_ht_params iwl_gl_a_ht_params = { - .stbc = false, /* we explicitly disable STBC for GL step A */ - .ldpc = true, - .ht40_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ) | - BIT(NL80211_BAND_6GHZ), -}; - #define IWL_DEVICE_22000_COMMON \ - .ucode_api_max = IWL_22000_UCODE_API_MAX, \ .ucode_api_min = IWL_22000_UCODE_API_MIN, \ .led_mode = IWL_LED_RF_STATE, \ .nvm_hw_section_num = 10, \ @@ -240,7 +84,6 @@ static const struct iwl_ht_params iwl_gl_a_ht_params = { .mac_addr_from_csr = 0x380, \ .ht_params = &iwl_22000_ht_params, \ .nvm_ver = IWL_22000_NVM_VERSION, \ - .trans.use_tfh = true, \ .trans.rf_id = true, \ .trans.gen2 = true, \ .nvm_type = IWL_NVM_EXT, \ @@ -261,6 +104,7 @@ static const struct iwl_ht_params iwl_gl_a_ht_params = { #define IWL_DEVICE_22500 \ IWL_DEVICE_22000_COMMON, \ + .ucode_api_max = IWL_22000_UCODE_API_MAX, \ .trans.device_family = IWL_DEVICE_FAMILY_22000, \ .trans.base_params = &iwl_22000_base_params, \ .gp2_reg_addr = 0xa02c68, \ @@ -275,111 +119,8 @@ static const struct iwl_ht_params iwl_gl_a_ht_params = { }, \ } -#define IWL_DEVICE_AX210 \ - IWL_DEVICE_22000_COMMON, \ - .trans.umac_prph_offset = 0x300000, \ - .trans.device_family = IWL_DEVICE_FAMILY_AX210, \ - .trans.base_params = &iwl_ax210_base_params, \ - .min_txq_size = 128, \ - .gp2_reg_addr = 0xd02c68, \ - .min_ba_txq_size = IWL_DEFAULT_QUEUE_SIZE_HE, \ - .mon_dram_regs = { \ - .write_ptr = { \ - .addr = DBGC_CUR_DBGBUF_STATUS, \ - .mask = DBGC_CUR_DBGBUF_STATUS_OFFSET_MSK, \ - }, \ - .cycle_cnt = { \ - .addr = DBGC_DBGBUF_WRAP_AROUND, \ - .mask = 0xffffffff, \ - }, \ - .cur_frag = { \ - .addr = DBGC_CUR_DBGBUF_STATUS, \ - .mask = DBGC_CUR_DBGBUF_STATUS_IDX_MSK, \ - }, \ - } - -#define IWL_DEVICE_BZ_COMMON \ - .ucode_api_max = IWL_22000_UCODE_API_MAX, \ - .ucode_api_min = IWL_22000_UCODE_API_MIN, \ - .led_mode = IWL_LED_RF_STATE, \ - .nvm_hw_section_num = 10, \ - .non_shared_ant = ANT_B, \ - .dccm_offset = IWL_22000_DCCM_OFFSET, \ - .dccm_len = IWL_22000_DCCM_LEN, \ - .dccm2_offset = IWL_22000_DCCM2_OFFSET, \ - .dccm2_len = IWL_22000_DCCM2_LEN, \ - .smem_offset = IWL_22000_SMEM_OFFSET, \ - .smem_len = IWL_22000_SMEM_LEN, \ - .apmg_not_supported = true, \ - .trans.mq_rx_supported = true, \ - .vht_mu_mimo_supported = true, \ - .mac_addr_from_csr = 0x30, \ - .nvm_ver = IWL_22000_NVM_VERSION, \ - .trans.use_tfh = true, \ - .trans.rf_id = true, \ - .trans.gen2 = true, \ - .nvm_type = IWL_NVM_EXT, \ - .dbgc_supported = true, \ - .min_umac_error_event_table = 0xD0000, \ - .d3_debug_data_base_addr = 0x401000, \ - .d3_debug_data_length = 60 * 1024, \ - .mon_smem_regs = { \ - .write_ptr = { \ - .addr = LDBG_M2S_BUF_WPTR, \ - .mask = LDBG_M2S_BUF_WPTR_VAL_MSK, \ - }, \ - .cycle_cnt = { \ - .addr = LDBG_M2S_BUF_WRAP_CNT, \ - .mask = LDBG_M2S_BUF_WRAP_CNT_VAL_MSK, \ - }, \ - }, \ - .trans.umac_prph_offset = 0x300000, \ - .trans.device_family = IWL_DEVICE_FAMILY_BZ, \ - .trans.base_params = &iwl_ax210_base_params, \ - .min_txq_size = 128, \ - .gp2_reg_addr = 0xd02c68, \ - .min_ba_txq_size = IWL_DEFAULT_QUEUE_SIZE_EHT, \ - .mon_dram_regs = { \ - .write_ptr = { \ - .addr = DBGC_CUR_DBGBUF_STATUS, \ - .mask = DBGC_CUR_DBGBUF_STATUS_OFFSET_MSK, \ - }, \ - .cycle_cnt = { \ - .addr = DBGC_DBGBUF_WRAP_AROUND, \ - .mask = 0xffffffff, \ - }, \ - .cur_frag = { \ - .addr = DBGC_CUR_DBGBUF_STATUS, \ - .mask = DBGC_CUR_DBGBUF_STATUS_IDX_MSK, \ - }, \ - }, \ - .mon_dbgi_regs = { \ - .write_ptr = { \ - .addr = DBGI_SRAM_FIFO_POINTERS, \ - .mask = DBGI_SRAM_FIFO_POINTERS_WR_PTR_MSK, \ - }, \ - } - -#define IWL_DEVICE_BZ \ - IWL_DEVICE_BZ_COMMON, \ - .ht_params = &iwl_22000_ht_params - -#define IWL_DEVICE_GL_A \ - IWL_DEVICE_BZ_COMMON, \ - .ht_params = &iwl_gl_a_ht_params - -const struct iwl_cfg_trans_params iwl_qnj_trans_cfg = { - .mq_rx_supported = true, - .use_tfh = true, - .rf_id = true, - .gen2 = true, - .device_family = IWL_DEVICE_FAMILY_22000, - .base_params = &iwl_22000_base_params, -}; - const struct iwl_cfg_trans_params iwl_qu_trans_cfg = { .mq_rx_supported = true, - .use_tfh = true, .rf_id = true, .gen2 = true, .device_family = IWL_DEVICE_FAMILY_22000, @@ -391,7 +132,6 @@ const struct iwl_cfg_trans_params iwl_qu_trans_cfg = { const struct iwl_cfg_trans_params iwl_qu_medium_latency_trans_cfg = { .mq_rx_supported = true, - .use_tfh = true, .rf_id = true, .gen2 = true, .device_family = IWL_DEVICE_FAMILY_22000, @@ -403,7 +143,6 @@ const struct iwl_cfg_trans_params iwl_qu_medium_latency_trans_cfg = { const struct iwl_cfg_trans_params iwl_qu_long_latency_trans_cfg = { .mq_rx_supported = true, - .use_tfh = true, .rf_id = true, .gen2 = true, .device_family = IWL_DEVICE_FAMILY_22000, @@ -414,59 +153,6 @@ const struct iwl_cfg_trans_params iwl_qu_long_latency_trans_cfg = { .ltr_delay = IWL_CFG_TRANS_LTR_DELAY_2500US, }; -const struct iwl_cfg_trans_params iwl_snj_trans_cfg = { - .mq_rx_supported = true, - .use_tfh = true, - .rf_id = true, - .gen2 = true, - .device_family = IWL_DEVICE_FAMILY_AX210, - .base_params = &iwl_ax210_base_params, - .umac_prph_offset = 0x300000, -}; - -const struct iwl_cfg_trans_params iwl_so_trans_cfg = { - .mq_rx_supported = true, - .use_tfh = true, - .rf_id = true, - .gen2 = true, - .device_family = IWL_DEVICE_FAMILY_AX210, - .base_params = &iwl_ax210_base_params, - .umac_prph_offset = 0x300000, - .integrated = true, - /* TODO: the following values need to be checked */ - .xtal_latency = 500, - .ltr_delay = IWL_CFG_TRANS_LTR_DELAY_200US, -}; - -const struct iwl_cfg_trans_params iwl_so_long_latency_trans_cfg = { - .mq_rx_supported = true, - .use_tfh = true, - .rf_id = true, - .gen2 = true, - .device_family = IWL_DEVICE_FAMILY_AX210, - .base_params = &iwl_ax210_base_params, - .umac_prph_offset = 0x300000, - .integrated = true, - .low_latency_xtal = true, - .xtal_latency = 12000, - .ltr_delay = IWL_CFG_TRANS_LTR_DELAY_2500US, -}; - -const struct iwl_cfg_trans_params iwl_so_long_latency_imr_trans_cfg = { - .mq_rx_supported = true, - .use_tfh = true, - .rf_id = true, - .gen2 = true, - .device_family = IWL_DEVICE_FAMILY_AX210, - .base_params = &iwl_ax210_base_params, - .umac_prph_offset = 0x300000, - .integrated = true, - .low_latency_xtal = true, - .xtal_latency = 12000, - .ltr_delay = IWL_CFG_TRANS_LTR_DELAY_2500US, - .imr_enabled = true, -}; - /* * If the device doesn't support HE, no need to have that many buffers. * 22000 devices can split multiple frames into a single RB, so fewer are @@ -476,7 +162,6 @@ const struct iwl_cfg_trans_params iwl_so_long_latency_imr_trans_cfg = { */ #define IWL_NUM_RBDS_NON_HE 512 #define IWL_NUM_RBDS_22000_HE 2048 -#define IWL_NUM_RBDS_AX210_HE 4096 /* * All JF radio modules are part of the 9000 series, but the MAC part @@ -507,63 +192,20 @@ const struct iwl_cfg iwl9560_quz_a0_jf_b0_cfg = { .num_rbds = IWL_NUM_RBDS_NON_HE, }; -const struct iwl_cfg iwl9560_qnj_b0_jf_b0_cfg = { - .fw_name_pre = IWL_QNJ_B_JF_B_FW_PRE, - IWL_DEVICE_22500, - /* - * This device doesn't support receiving BlockAck with a large bitmap - * so we need to restrict the size of transmitted aggregation to the - * HT size; mac80211 would otherwise pick the HE max (256) by default. - */ - .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT, - .num_rbds = IWL_NUM_RBDS_NON_HE, -}; - const struct iwl_cfg_trans_params iwl_ax200_trans_cfg = { .device_family = IWL_DEVICE_FAMILY_22000, .base_params = &iwl_22000_base_params, .mq_rx_supported = true, - .use_tfh = true, .rf_id = true, .gen2 = true, .bisr_workaround = 1, }; -const struct iwl_cfg_trans_params iwl_ma_trans_cfg = { - .device_family = IWL_DEVICE_FAMILY_AX210, - .base_params = &iwl_ax210_base_params, - .mq_rx_supported = true, - .use_tfh = true, - .rf_id = true, - .gen2 = true, - .integrated = true, - .umac_prph_offset = 0x300000 -}; - -const struct iwl_cfg_trans_params iwl_bz_trans_cfg = { - .device_family = IWL_DEVICE_FAMILY_BZ, - .base_params = &iwl_ax210_base_params, - .mq_rx_supported = true, - .use_tfh = true, - .rf_id = true, - .gen2 = true, - .integrated = true, - .umac_prph_offset = 0x300000, - .xtal_latency = 12000, - .low_latency_xtal = true, - .ltr_delay = IWL_CFG_TRANS_LTR_DELAY_2500US, -}; - const char iwl_ax101_name[] = "Intel(R) Wi-Fi 6 AX101"; const char iwl_ax200_name[] = "Intel(R) Wi-Fi 6 AX200 160MHz"; const char iwl_ax201_name[] = "Intel(R) Wi-Fi 6 AX201 160MHz"; const char iwl_ax203_name[] = "Intel(R) Wi-Fi 6 AX203"; const char iwl_ax204_name[] = "Intel(R) Wi-Fi 6 AX204 160MHz"; -const char iwl_ax211_name[] = "Intel(R) Wi-Fi 6E AX211 160MHz"; -const char iwl_ax221_name[] = "Intel(R) Wi-Fi 6E AX221 160MHz"; -const char iwl_ax231_name[] = "Intel(R) Wi-Fi 6E AX231 160MHz"; -const char iwl_ax411_name[] = "Intel(R) Wi-Fi 6E AX411 160MHz"; -const char iwl_bz_name[] = "Intel(R) TBD Bz device"; const char iwl_ax200_killer_1650w_name[] = "Killer(R) Wi-Fi 6 AX1650w 160MHz Wireless Network Adapter (200D2W)"; @@ -573,18 +215,6 @@ const char iwl_ax201_killer_1650s_name[] = "Killer(R) Wi-Fi 6 AX1650s 160MHz Wireless Network Adapter (201D2W)"; const char iwl_ax201_killer_1650i_name[] = "Killer(R) Wi-Fi 6 AX1650i 160MHz Wireless Network Adapter (201NGW)"; -const char iwl_ax210_killer_1675w_name[] = - "Killer(R) Wi-Fi 6E AX1675w 160MHz Wireless Network Adapter (210D2W)"; -const char iwl_ax210_killer_1675x_name[] = - "Killer(R) Wi-Fi 6E AX1675x 160MHz Wireless Network Adapter (210NGW)"; -const char iwl_ax211_killer_1675s_name[] = - "Killer(R) Wi-Fi 6E AX1675s 160MHz Wireless Network Adapter (211NGW)"; -const char iwl_ax211_killer_1675i_name[] = - "Killer(R) Wi-Fi 6E AX1675i 160MHz Wireless Network Adapter (211NGW)"; -const char iwl_ax411_killer_1690s_name[] = - "Killer(R) Wi-Fi 6E AX1690s 160MHz Wireless Network Adapter (411D2W)"; -const char iwl_ax411_killer_1690i_name[] = - "Killer(R) Wi-Fi 6E AX1690i 160MHz Wireless Network Adapter (411NGW)"; const struct iwl_cfg iwl_qu_b0_hr1_b0 = { .fw_name_pre = IWL_QU_B_HR_B_FW_PRE, @@ -778,203 +408,6 @@ const struct iwl_cfg killer1650i_2ax_cfg_qu_c0_hr_b0 = { .num_rbds = IWL_NUM_RBDS_22000_HE, }; -const struct iwl_cfg iwl_qnj_b0_hr_b0_cfg = { - .fw_name_pre = IWL_QNJ_B_HR_B_FW_PRE, - IWL_DEVICE_22500, - /* - * This device doesn't support receiving BlockAck with a large bitmap - * so we need to restrict the size of transmitted aggregation to the - * HT size; mac80211 would otherwise pick the HE max (256) by default. - */ - .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT, - .num_rbds = IWL_NUM_RBDS_22000_HE, -}; - -const struct iwl_cfg iwlax210_2ax_cfg_so_jf_b0 = { - .name = "Intel(R) Wireless-AC 9560 160MHz", - .fw_name_pre = IWL_SO_A_JF_B_FW_PRE, - IWL_DEVICE_AX210, - .num_rbds = IWL_NUM_RBDS_NON_HE, -}; - -const struct iwl_cfg iwlax211_2ax_cfg_so_gf_a0 = { - .name = iwl_ax211_name, - .fw_name_pre = IWL_SO_A_GF_A_FW_PRE, - .uhb_supported = true, - IWL_DEVICE_AX210, - .num_rbds = IWL_NUM_RBDS_AX210_HE, -}; - -const struct iwl_cfg iwlax211_2ax_cfg_so_gf_a0_long = { - .name = iwl_ax211_name, - .fw_name_pre = IWL_SO_A_GF_A_FW_PRE, - .uhb_supported = true, - IWL_DEVICE_AX210, - .num_rbds = IWL_NUM_RBDS_AX210_HE, - .trans.xtal_latency = 12000, - .trans.low_latency_xtal = true, -}; - -const struct iwl_cfg iwlax210_2ax_cfg_ty_gf_a0 = { - .name = "Intel(R) Wi-Fi 6 AX210 160MHz", - .fw_name_pre = IWL_TY_A_GF_A_FW_PRE, - .uhb_supported = true, - IWL_DEVICE_AX210, - .num_rbds = IWL_NUM_RBDS_AX210_HE, -}; - -const struct iwl_cfg iwlax411_2ax_cfg_so_gf4_a0 = { - .name = iwl_ax411_name, - .fw_name_pre = IWL_SO_A_GF4_A_FW_PRE, - .uhb_supported = true, - IWL_DEVICE_AX210, - .num_rbds = IWL_NUM_RBDS_AX210_HE, -}; - -const struct iwl_cfg iwlax411_2ax_cfg_so_gf4_a0_long = { - .name = iwl_ax411_name, - .fw_name_pre = IWL_SO_A_GF4_A_FW_PRE, - .uhb_supported = true, - IWL_DEVICE_AX210, - .num_rbds = IWL_NUM_RBDS_AX210_HE, - .trans.xtal_latency = 12000, - .trans.low_latency_xtal = true, -}; - -const struct iwl_cfg iwlax411_2ax_cfg_sosnj_gf4_a0 = { - .name = iwl_ax411_name, - .fw_name_pre = IWL_SNJ_A_GF4_A_FW_PRE, - .uhb_supported = true, - IWL_DEVICE_AX210, - .num_rbds = IWL_NUM_RBDS_AX210_HE, -}; - -const struct iwl_cfg iwlax211_cfg_snj_gf_a0 = { - .name = iwl_ax211_name, - .fw_name_pre = IWL_SNJ_A_GF_A_FW_PRE, - .uhb_supported = true, - IWL_DEVICE_AX210, - .num_rbds = IWL_NUM_RBDS_AX210_HE, -}; - -const struct iwl_cfg iwl_cfg_snj_hr_b0 = { - .fw_name_pre = IWL_SNJ_A_HR_B_FW_PRE, - .uhb_supported = true, - IWL_DEVICE_AX210, - .num_rbds = IWL_NUM_RBDS_AX210_HE, -}; - -const struct iwl_cfg iwl_cfg_snj_a0_jf_b0 = { - .fw_name_pre = IWL_SNJ_A_JF_B_FW_PRE, - .uhb_supported = true, - IWL_DEVICE_AX210, - .num_rbds = IWL_NUM_RBDS_AX210_HE, -}; - -const struct iwl_cfg iwl_cfg_ma_a0_hr_b0 = { - .fw_name_pre = IWL_MA_A_HR_B_FW_PRE, - .uhb_supported = true, - IWL_DEVICE_AX210, - .num_rbds = IWL_NUM_RBDS_AX210_HE, -}; - -const struct iwl_cfg iwl_cfg_ma_a0_gf_a0 = { - .fw_name_pre = IWL_MA_A_GF_A_FW_PRE, - .uhb_supported = true, - IWL_DEVICE_AX210, - .num_rbds = IWL_NUM_RBDS_AX210_HE, -}; - -const struct iwl_cfg iwl_cfg_ma_a0_gf4_a0 = { - .fw_name_pre = IWL_MA_A_GF4_A_FW_PRE, - .uhb_supported = true, - IWL_DEVICE_AX210, - .num_rbds = IWL_NUM_RBDS_AX210_HE, -}; - -const struct iwl_cfg iwl_cfg_ma_a0_mr_a0 = { - .fw_name_pre = IWL_MA_A_MR_A_FW_PRE, - .uhb_supported = true, - IWL_DEVICE_AX210, - .num_rbds = IWL_NUM_RBDS_AX210_HE, -}; - -const struct iwl_cfg iwl_cfg_ma_a0_ms_a0 = { - .fw_name_pre = IWL_MA_A_MR_A_FW_PRE, - .uhb_supported = false, - IWL_DEVICE_AX210, - .num_rbds = IWL_NUM_RBDS_AX210_HE, -}; - -const struct iwl_cfg iwl_cfg_ma_b0_fm_a0 = { - .fw_name_pre = IWL_MA_B_FM_A_FW_PRE, - .uhb_supported = true, - IWL_DEVICE_AX210, - .num_rbds = IWL_NUM_RBDS_AX210_HE, -}; - -const struct iwl_cfg iwl_cfg_ma_b0_hr_b0 = { - .fw_name_pre = IWL_MA_B_HR_B_FW_PRE, - .uhb_supported = true, - IWL_DEVICE_AX210, - .num_rbds = IWL_NUM_RBDS_AX210_HE, -}; - -const struct iwl_cfg iwl_cfg_ma_b0_gf_a0 = { - .fw_name_pre = IWL_MA_B_GF_A_FW_PRE, - .uhb_supported = true, - IWL_DEVICE_AX210, - .num_rbds = IWL_NUM_RBDS_AX210_HE, -}; - -const struct iwl_cfg iwl_cfg_ma_b0_gf4_a0 = { - .fw_name_pre = IWL_MA_B_GF4_A_FW_PRE, - .uhb_supported = true, - IWL_DEVICE_AX210, - .num_rbds = IWL_NUM_RBDS_AX210_HE, -}; - -const struct iwl_cfg iwl_cfg_ma_b0_mr_a0 = { - .fw_name_pre = IWL_MA_B_MR_A_FW_PRE, - .uhb_supported = true, - IWL_DEVICE_AX210, - .num_rbds = IWL_NUM_RBDS_AX210_HE, -}; - -const struct iwl_cfg iwl_cfg_so_a0_ms_a0 = { - .fw_name_pre = IWL_SO_A_MR_A_FW_PRE, - .uhb_supported = false, - IWL_DEVICE_AX210, - .num_rbds = IWL_NUM_RBDS_AX210_HE, -}; - -const struct iwl_cfg iwl_cfg_ma_a0_fm_a0 = { - .fw_name_pre = IWL_MA_A_FM_A_FW_PRE, - .uhb_supported = true, - IWL_DEVICE_AX210, - .num_rbds = IWL_NUM_RBDS_AX210_HE, -}; - -const struct iwl_cfg iwl_cfg_snj_a0_mr_a0 = { - .fw_name_pre = IWL_SNJ_A_MR_A_FW_PRE, - .uhb_supported = true, - IWL_DEVICE_AX210, - .num_rbds = IWL_NUM_RBDS_AX210_HE, -}; - -const struct iwl_cfg iwl_cfg_snj_a0_ms_a0 = { - .fw_name_pre = IWL_SNJ_A_MR_A_FW_PRE, - .uhb_supported = false, - IWL_DEVICE_AX210, - .num_rbds = IWL_NUM_RBDS_AX210_HE, -}; - -const struct iwl_cfg iwl_cfg_so_a0_hr_a0 = { - .fw_name_pre = IWL_SO_A_HR_B_FW_PRE, - IWL_DEVICE_AX210, - .num_rbds = IWL_NUM_RBDS_AX210_HE, -}; - const struct iwl_cfg iwl_cfg_quz_a0_hr_b0 = { .fw_name_pre = IWL_QUZ_A_HR_B_FW_PRE, IWL_DEVICE_22500, @@ -987,243 +420,9 @@ const struct iwl_cfg iwl_cfg_quz_a0_hr_b0 = { .num_rbds = IWL_NUM_RBDS_22000_HE, }; -const struct iwl_cfg iwl_cfg_bz_a0_hr_a0 = { - .fw_name_pre = IWL_BZ_A_HR_A_FW_PRE, - .uhb_supported = true, - IWL_DEVICE_BZ, - .features = IWL_TX_CSUM_NETIF_FLAGS_BZ | NETIF_F_RXCSUM, - .num_rbds = IWL_NUM_RBDS_AX210_HE, -}; - -const struct iwl_cfg iwl_cfg_bz_a0_hr_b0 = { - .fw_name_pre = IWL_BZ_A_HR_B_FW_PRE, - .uhb_supported = true, - IWL_DEVICE_BZ, - .features = IWL_TX_CSUM_NETIF_FLAGS_BZ | NETIF_F_RXCSUM, - .num_rbds = IWL_NUM_RBDS_AX210_HE, -}; - -const struct iwl_cfg iwl_cfg_bz_a0_gf_a0 = { - .fw_name_pre = IWL_BZ_A_GF_A_FW_PRE, - .uhb_supported = true, - IWL_DEVICE_BZ, - .features = IWL_TX_CSUM_NETIF_FLAGS_BZ | NETIF_F_RXCSUM, - .num_rbds = IWL_NUM_RBDS_AX210_HE, -}; - -const struct iwl_cfg iwl_cfg_bz_a0_gf4_a0 = { - .fw_name_pre = IWL_BZ_A_GF4_A_FW_PRE, - .uhb_supported = true, - IWL_DEVICE_BZ, - .features = IWL_TX_CSUM_NETIF_FLAGS_BZ | NETIF_F_RXCSUM, - .num_rbds = IWL_NUM_RBDS_AX210_HE, -}; - -const struct iwl_cfg iwl_cfg_bz_a0_mr_a0 = { - .fw_name_pre = IWL_BZ_A_MR_A_FW_PRE, - .uhb_supported = true, - IWL_DEVICE_BZ, - .features = IWL_TX_CSUM_NETIF_FLAGS_BZ | NETIF_F_RXCSUM, - .num_rbds = IWL_NUM_RBDS_AX210_HE, -}; - -const struct iwl_cfg iwl_cfg_bz_a0_fm_a0 = { - .fw_name_pre = IWL_BZ_A_FM_A_FW_PRE, - .uhb_supported = true, - IWL_DEVICE_BZ, - .features = IWL_TX_CSUM_NETIF_FLAGS_BZ | NETIF_F_RXCSUM, - .num_rbds = IWL_NUM_RBDS_AX210_HE, -}; - -const struct iwl_cfg iwl_cfg_bz_a0_fm4_a0 = { - .fw_name_pre = IWL_BZ_A_FM4_A_FW_PRE, - .uhb_supported = true, - IWL_DEVICE_BZ, - .features = IWL_TX_CSUM_NETIF_FLAGS_BZ | NETIF_F_RXCSUM, - .num_rbds = IWL_NUM_RBDS_AX210_HE, -}; - -const struct iwl_cfg iwl_cfg_bz_a0_fm_b0 = { - .fw_name_pre = IWL_BZ_A_FM_B_FW_PRE, - .uhb_supported = true, - IWL_DEVICE_BZ, - .features = IWL_TX_CSUM_NETIF_FLAGS_BZ | NETIF_F_RXCSUM, - .num_rbds = IWL_NUM_RBDS_AX210_HE, -}; - -const struct iwl_cfg iwl_cfg_bz_a0_fm4_b0 = { - .fw_name_pre = IWL_BZ_A_FM4_B_FW_PRE, - .uhb_supported = true, - IWL_DEVICE_BZ, - .features = IWL_TX_CSUM_NETIF_FLAGS_BZ | NETIF_F_RXCSUM, - .num_rbds = IWL_NUM_RBDS_AX210_HE, -}; - -const struct iwl_cfg iwl_cfg_gl_a0_fm_a0 = { - .fw_name_pre = IWL_GL_A_FM_A_FW_PRE, - .uhb_supported = true, - IWL_DEVICE_GL_A, - .features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM, - .num_rbds = IWL_NUM_RBDS_AX210_HE, -}; - -const struct iwl_cfg iwl_cfg_gl_b0_fm_b0 = { - .fw_name_pre = IWL_GL_B_FM_B_FW_PRE, - .uhb_supported = true, - IWL_DEVICE_BZ, - .features = IWL_TX_CSUM_NETIF_FLAGS_BZ | NETIF_F_RXCSUM, - .num_rbds = IWL_NUM_RBDS_AX210_HE, -}; - -const struct iwl_cfg iwl_cfg_bz_z0_gf_a0 = { - .fw_name_pre = IWL_BZ_Z_GF_A_FW_PRE, - .uhb_supported = true, - IWL_DEVICE_BZ, - .features = IWL_TX_CSUM_NETIF_FLAGS_BZ | NETIF_F_RXCSUM, - .num_rbds = IWL_NUM_RBDS_AX210_HE, -}; - -const struct iwl_cfg iwl_cfg_bnj_a0_fm_a0 = { - .fw_name_pre = IWL_BNJ_A_FM_A_FW_PRE, - .uhb_supported = true, - IWL_DEVICE_BZ, - .features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM, - .num_rbds = IWL_NUM_RBDS_AX210_HE, -}; - -const struct iwl_cfg iwl_cfg_bnj_a0_fm4_a0 = { - .fw_name_pre = IWL_BNJ_A_FM4_A_FW_PRE, - .uhb_supported = true, - IWL_DEVICE_BZ, - .features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM, - .num_rbds = IWL_NUM_RBDS_AX210_HE, -}; - -const struct iwl_cfg iwl_cfg_bnj_b0_fm4_b0 = { - .fw_name_pre = IWL_BNJ_B_FM4_B_FW_PRE, - .uhb_supported = true, - IWL_DEVICE_BZ, - .features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM, - .num_rbds = IWL_NUM_RBDS_AX210_HE, -}; - -const struct iwl_cfg iwl_cfg_bnj_a0_gf_a0 = { - .fw_name_pre = IWL_BNJ_A_GF_A_FW_PRE, - .uhb_supported = true, - IWL_DEVICE_BZ, - .features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM, - .num_rbds = IWL_NUM_RBDS_AX210_HE, -}; - -const struct iwl_cfg iwl_cfg_bnj_b0_gf_a0 = { - .fw_name_pre = IWL_BNJ_B_GF_A_FW_PRE, - .uhb_supported = true, - IWL_DEVICE_BZ, - .features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM, - .num_rbds = IWL_NUM_RBDS_AX210_HE, -}; - -const struct iwl_cfg iwl_cfg_bnj_a0_gf4_a0 = { - .fw_name_pre = IWL_BNJ_A_GF4_A_FW_PRE, - .uhb_supported = true, - IWL_DEVICE_BZ, - .features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM, - .num_rbds = IWL_NUM_RBDS_AX210_HE, -}; - -const struct iwl_cfg iwl_cfg_bnj_b0_gf4_a0 = { - .fw_name_pre = IWL_BNJ_B_GF4_A_FW_PRE, - .uhb_supported = true, - IWL_DEVICE_BZ, - .features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM, - .num_rbds = IWL_NUM_RBDS_AX210_HE, -}; - -const struct iwl_cfg iwl_cfg_bnj_a0_hr_a0 = { - .fw_name_pre = IWL_BNJ_A_HR_A_FW_PRE, - .uhb_supported = true, - IWL_DEVICE_BZ, - .features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM, - .num_rbds = IWL_NUM_RBDS_AX210_HE, -}; - -const struct iwl_cfg iwl_cfg_bnj_a0_hr_b0 = { - .fw_name_pre = IWL_BNJ_A_HR_B_FW_PRE, - .uhb_supported = true, - IWL_DEVICE_BZ, - .features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM, - .num_rbds = IWL_NUM_RBDS_AX210_HE, -}; - -const struct iwl_cfg iwl_cfg_bnj_b0_hr_a0 = { - .fw_name_pre = IWL_BNJ_B_HR_A_FW_PRE, - .uhb_supported = true, - IWL_DEVICE_BZ, - .features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM, - .num_rbds = IWL_NUM_RBDS_AX210_HE, -}; - -const struct iwl_cfg iwl_cfg_bnj_b0_hr_b0 = { - .fw_name_pre = IWL_BNJ_B_HR_B_FW_PRE, - .uhb_supported = true, - IWL_DEVICE_BZ, - .features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM, - .num_rbds = IWL_NUM_RBDS_AX210_HE, -}; - -const struct iwl_cfg iwl_cfg_bnj_b0_fm_b0 = { - .fw_name_pre = IWL_BNJ_B_FM_B_FW_PRE, - .uhb_supported = true, - IWL_DEVICE_BZ, - .features = IWL_TX_CSUM_NETIF_FLAGS_BZ | NETIF_F_RXCSUM, - .num_rbds = IWL_NUM_RBDS_AX210_HE, -}; MODULE_FIRMWARE(IWL_QU_B_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); -MODULE_FIRMWARE(IWL_QNJ_B_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); MODULE_FIRMWARE(IWL_QU_C_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); MODULE_FIRMWARE(IWL_QU_B_JF_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); MODULE_FIRMWARE(IWL_QUZ_A_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); MODULE_FIRMWARE(IWL_QUZ_A_JF_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); -MODULE_FIRMWARE(IWL_QNJ_B_JF_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); MODULE_FIRMWARE(IWL_CC_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); -MODULE_FIRMWARE(IWL_SO_A_JF_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); -MODULE_FIRMWARE(IWL_SO_A_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); -MODULE_FIRMWARE(IWL_SO_A_GF_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); -MODULE_FIRMWARE(IWL_TY_A_GF_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); -MODULE_FIRMWARE(IWL_SNJ_A_GF4_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); -MODULE_FIRMWARE(IWL_SNJ_A_GF_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); -MODULE_FIRMWARE(IWL_SNJ_A_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); -MODULE_FIRMWARE(IWL_SNJ_A_JF_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); -MODULE_FIRMWARE(IWL_MA_A_HR_B_FW_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); -MODULE_FIRMWARE(IWL_MA_A_GF_A_FW_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); -MODULE_FIRMWARE(IWL_MA_A_GF4_A_FW_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); -MODULE_FIRMWARE(IWL_MA_A_MR_A_FW_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); -MODULE_FIRMWARE(IWL_MA_A_FM_A_FW_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); -MODULE_FIRMWARE(IWL_MA_B_HR_B_FW_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); -MODULE_FIRMWARE(IWL_MA_B_GF_A_FW_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); -MODULE_FIRMWARE(IWL_MA_B_GF4_A_FW_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); -MODULE_FIRMWARE(IWL_MA_B_MR_A_FW_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); -MODULE_FIRMWARE(IWL_MA_B_FM_A_FW_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); -MODULE_FIRMWARE(IWL_SNJ_A_MR_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); -MODULE_FIRMWARE(IWL_BZ_A_HR_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); -MODULE_FIRMWARE(IWL_BZ_A_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); -MODULE_FIRMWARE(IWL_BZ_A_GF_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); -MODULE_FIRMWARE(IWL_BZ_A_GF4_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); -MODULE_FIRMWARE(IWL_BZ_A_MR_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); -MODULE_FIRMWARE(IWL_BZ_A_FM_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); -MODULE_FIRMWARE(IWL_BZ_A_FM_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); -MODULE_FIRMWARE(IWL_GL_A_FM_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); -MODULE_FIRMWARE(IWL_BNJ_A_FM_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); -MODULE_FIRMWARE(IWL_BNJ_A_FM4_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); -MODULE_FIRMWARE(IWL_BNJ_B_FM4_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); -MODULE_FIRMWARE(IWL_BNJ_A_GF_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); -MODULE_FIRMWARE(IWL_BNJ_B_GF_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); -MODULE_FIRMWARE(IWL_BNJ_A_GF4_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); -MODULE_FIRMWARE(IWL_BNJ_B_GF4_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); -MODULE_FIRMWARE(IWL_BNJ_A_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); -MODULE_FIRMWARE(IWL_BNJ_B_HR_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); -MODULE_FIRMWARE(IWL_BNJ_B_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); -MODULE_FIRMWARE(IWL_BZ_A_FM4_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); -MODULE_FIRMWARE(IWL_BZ_A_FM4_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); -MODULE_FIRMWARE(IWL_GL_B_FM_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); -MODULE_FIRMWARE(IWL_BNJ_B_FM_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/5000.c b/drivers/net/wireless/intel/iwlwifi/cfg/5000.c index e2e23d2bc1fe5ef51c8ebe0c7a7b47adea4a2f00..de7ede59a9941713f9ddc3660dfaaa96c5c4fe2c 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/5000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/5000.c @@ -2,7 +2,7 @@ /****************************************************************************** * * Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved. - * Copyright(c) 2018 - 2020 Intel Corporation + * Copyright(c) 2018 - 2020, 2023 Intel Corporation *****************************************************************************/ #include @@ -24,11 +24,11 @@ #define EEPROM_5050_TX_POWER_VERSION (4) #define EEPROM_5050_EEPROM_VERSION (0x21E) -#define IWL5000_FW_PRE "iwlwifi-5000-" -#define IWL5000_MODULE_FIRMWARE(api) IWL5000_FW_PRE __stringify(api) ".ucode" +#define IWL5000_FW_PRE "iwlwifi-5000" +#define IWL5000_MODULE_FIRMWARE(api) IWL5000_FW_PRE "-" __stringify(api) ".ucode" -#define IWL5150_FW_PRE "iwlwifi-5150-" -#define IWL5150_MODULE_FIRMWARE(api) IWL5150_FW_PRE __stringify(api) ".ucode" +#define IWL5150_FW_PRE "iwlwifi-5150" +#define IWL5150_MODULE_FIRMWARE(api) IWL5150_FW_PRE "-" __stringify(api) ".ucode" static const struct iwl_base_params iwl5000_base_params = { .eeprom_size = IWLAGN_EEPROM_IMG_SIZE, diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/6000.c b/drivers/net/wireless/intel/iwlwifi/cfg/6000.c index 20929e59c2f4d20022e24a5099254f55afda98e8..f013cf4205693d42625dae9d0fb00c05ed7ae411 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/6000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/6000.c @@ -2,7 +2,7 @@ /****************************************************************************** * * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved. - * Copyright(c) 2018 - 2020 Intel Corporation + * Copyright(c) 2018 - 2020, 2023 Intel Corporation *****************************************************************************/ #include @@ -37,17 +37,17 @@ #define EEPROM_6035_TX_POWER_VERSION (6) #define EEPROM_6035_EEPROM_VERSION (0x753) -#define IWL6000_FW_PRE "iwlwifi-6000-" -#define IWL6000_MODULE_FIRMWARE(api) IWL6000_FW_PRE __stringify(api) ".ucode" +#define IWL6000_FW_PRE "iwlwifi-6000" +#define IWL6000_MODULE_FIRMWARE(api) IWL6000_FW_PRE "-" __stringify(api) ".ucode" -#define IWL6050_FW_PRE "iwlwifi-6050-" -#define IWL6050_MODULE_FIRMWARE(api) IWL6050_FW_PRE __stringify(api) ".ucode" +#define IWL6050_FW_PRE "iwlwifi-6050" +#define IWL6050_MODULE_FIRMWARE(api) IWL6050_FW_PRE "-" __stringify(api) ".ucode" -#define IWL6005_FW_PRE "iwlwifi-6000g2a-" -#define IWL6005_MODULE_FIRMWARE(api) IWL6005_FW_PRE __stringify(api) ".ucode" +#define IWL6005_FW_PRE "iwlwifi-6000g2a" +#define IWL6005_MODULE_FIRMWARE(api) IWL6005_FW_PRE "-" __stringify(api) ".ucode" -#define IWL6030_FW_PRE "iwlwifi-6000g2b-" -#define IWL6030_MODULE_FIRMWARE(api) IWL6030_FW_PRE __stringify(api) ".ucode" +#define IWL6030_FW_PRE "iwlwifi-6000g2b" +#define IWL6030_MODULE_FIRMWARE(api) IWL6030_FW_PRE "-" __stringify(api) ".ucode" static const struct iwl_base_params iwl6000_base_params = { .eeprom_size = OTP_LOW_IMAGE_SIZE_2K, diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/7000.c b/drivers/net/wireless/intel/iwlwifi/cfg/7000.c index b24dc5523a526e78df3014cc505e48f5eeb72080..4e2afdedf4c6a92ebc5e9613b7ebf121b0a920ce 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/7000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/7000.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* - * Copyright (C) 2012-2014, 2018-2020 Intel Corporation + * Copyright (C) 2012-2014, 2018-2020, 2023 Intel Corporation * Copyright (C) 2013-2014 Intel Mobile Communications GmbH * Copyright (C) 2015 Intel Deutschland GmbH */ @@ -34,20 +34,20 @@ #define IWL3160_DCCM_LEN 0x10000 #define IWL7265_DCCM_LEN 0x17A00 -#define IWL7260_FW_PRE "iwlwifi-7260-" -#define IWL7260_MODULE_FIRMWARE(api) IWL7260_FW_PRE __stringify(api) ".ucode" +#define IWL7260_FW_PRE "iwlwifi-7260" +#define IWL7260_MODULE_FIRMWARE(api) IWL7260_FW_PRE "-" __stringify(api) ".ucode" -#define IWL3160_FW_PRE "iwlwifi-3160-" -#define IWL3160_MODULE_FIRMWARE(api) IWL3160_FW_PRE __stringify(api) ".ucode" +#define IWL3160_FW_PRE "iwlwifi-3160" +#define IWL3160_MODULE_FIRMWARE(api) IWL3160_FW_PRE "-" __stringify(api) ".ucode" -#define IWL3168_FW_PRE "iwlwifi-3168-" -#define IWL3168_MODULE_FIRMWARE(api) IWL3168_FW_PRE __stringify(api) ".ucode" +#define IWL3168_FW_PRE "iwlwifi-3168" +#define IWL3168_MODULE_FIRMWARE(api) IWL3168_FW_PRE "-" __stringify(api) ".ucode" -#define IWL7265_FW_PRE "iwlwifi-7265-" -#define IWL7265_MODULE_FIRMWARE(api) IWL7265_FW_PRE __stringify(api) ".ucode" +#define IWL7265_FW_PRE "iwlwifi-7265" +#define IWL7265_MODULE_FIRMWARE(api) IWL7265_FW_PRE "-" __stringify(api) ".ucode" -#define IWL7265D_FW_PRE "iwlwifi-7265D-" -#define IWL7265D_MODULE_FIRMWARE(api) IWL7265D_FW_PRE __stringify(api) ".ucode" +#define IWL7265D_FW_PRE "iwlwifi-7265D" +#define IWL7265D_MODULE_FIRMWARE(api) IWL7265D_FW_PRE "-" __stringify(api) ".ucode" static const struct iwl_base_params iwl7000_base_params = { .eeprom_size = OTP_LOW_IMAGE_SIZE_16K, diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/8000.c b/drivers/net/wireless/intel/iwlwifi/cfg/8000.c index a6454287d506fe756c5b4891a41a52d8767f266e..d09cf8d7dc01cbb8df1826564ce3ca1162be453c 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/8000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/8000.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* - * Copyright (C) 2014, 2018-2020 Intel Corporation + * Copyright (C) 2014, 2018-2020, 2023 Intel Corporation * Copyright (C) 2014-2015 Intel Mobile Communications GmbH * Copyright (C) 2016 Intel Deutschland GmbH */ @@ -27,13 +27,13 @@ #define IWL8260_SMEM_OFFSET 0x400000 #define IWL8260_SMEM_LEN 0x68000 -#define IWL8000_FW_PRE "iwlwifi-8000C-" +#define IWL8000_FW_PRE "iwlwifi-8000C" #define IWL8000_MODULE_FIRMWARE(api) \ - IWL8000_FW_PRE __stringify(api) ".ucode" + IWL8000_FW_PRE "-" __stringify(api) ".ucode" -#define IWL8265_FW_PRE "iwlwifi-8265-" +#define IWL8265_FW_PRE "iwlwifi-8265" #define IWL8265_MODULE_FIRMWARE(api) \ - IWL8265_FW_PRE __stringify(api) ".ucode" + IWL8265_FW_PRE "-" __stringify(api) ".ucode" #define DEFAULT_NVM_FILE_FAMILY_8000C "nvmData-8000C" diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/9000.c b/drivers/net/wireless/intel/iwlwifi/cfg/9000.c index 7a7ca06d46c1886005bd86e165cf84619fe1cbe9..0130d9a9b78bea5a834989939028be72649d0370 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/9000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/9000.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* * Copyright (C) 2015-2017 Intel Deutschland GmbH - * Copyright (C) 2018-2021 Intel Corporation + * Copyright (C) 2018-2021, 2023 Intel Corporation */ #include #include @@ -26,12 +26,12 @@ #define IWL9000_SMEM_OFFSET 0x400000 #define IWL9000_SMEM_LEN 0x68000 -#define IWL9000_FW_PRE "iwlwifi-9000-pu-b0-jf-b0-" -#define IWL9260_FW_PRE "iwlwifi-9260-th-b0-jf-b0-" +#define IWL9000_FW_PRE "iwlwifi-9000-pu-b0-jf-b0" +#define IWL9260_FW_PRE "iwlwifi-9260-th-b0-jf-b0" #define IWL9000_MODULE_FIRMWARE(api) \ - IWL9000_FW_PRE __stringify(api) ".ucode" + IWL9000_FW_PRE "-" __stringify(api) ".ucode" #define IWL9260_MODULE_FIRMWARE(api) \ - IWL9260_FW_PRE __stringify(api) ".ucode" + IWL9260_FW_PRE "-" __stringify(api) ".ucode" static const struct iwl_base_params iwl9000_base_params = { .eeprom_size = OTP_LOW_IMAGE_SIZE_32K, diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/ax210.c b/drivers/net/wireless/intel/iwlwifi/cfg/ax210.c new file mode 100644 index 0000000000000000000000000000000000000000..8d5f9dce71d58bd7a81dd8353cb76756756ce8b6 --- /dev/null +++ b/drivers/net/wireless/intel/iwlwifi/cfg/ax210.c @@ -0,0 +1,301 @@ +// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause +/* + * Copyright (C) 2015-2017 Intel Deutschland GmbH + * Copyright (C) 2018-2023 Intel Corporation + */ +#include +#include +#include "iwl-config.h" +#include "iwl-prph.h" +#include "fw/api/txq.h" + +/* Highest firmware API version supported */ +#define IWL_AX210_UCODE_API_MAX 83 + +/* Lowest firmware API version supported */ +#define IWL_AX210_UCODE_API_MIN 59 + +/* NVM versions */ +#define IWL_AX210_NVM_VERSION 0x0a1d + +/* Memory offsets and lengths */ +#define IWL_AX210_DCCM_OFFSET 0x800000 /* LMAC1 */ +#define IWL_AX210_DCCM_LEN 0x10000 /* LMAC1 */ +#define IWL_AX210_DCCM2_OFFSET 0x880000 +#define IWL_AX210_DCCM2_LEN 0x8000 +#define IWL_AX210_SMEM_OFFSET 0x400000 +#define IWL_AX210_SMEM_LEN 0xD0000 + +#define IWL_SO_A_JF_B_FW_PRE "iwlwifi-so-a0-jf-b0" +#define IWL_SO_A_HR_B_FW_PRE "iwlwifi-so-a0-hr-b0" +#define IWL_SO_A_GF_A_FW_PRE "iwlwifi-so-a0-gf-a0" +#define IWL_TY_A_GF_A_FW_PRE "iwlwifi-ty-a0-gf-a0" +#define IWL_SO_A_GF4_A_FW_PRE "iwlwifi-so-a0-gf4-a0" +#define IWL_SO_A_MR_A_FW_PRE "iwlwifi-so-a0-mr-a0" +#define IWL_MA_A_HR_B_FW_PRE "iwlwifi-ma-a0-hr-b0" +#define IWL_MA_A_GF_A_FW_PRE "iwlwifi-ma-a0-gf-a0" +#define IWL_MA_A_GF4_A_FW_PRE "iwlwifi-ma-a0-gf4-a0" +#define IWL_MA_A_MR_A_FW_PRE "iwlwifi-ma-a0-mr-a0" +#define IWL_MA_B_HR_B_FW_PRE "iwlwifi-ma-b0-hr-b0" +#define IWL_MA_B_GF_A_FW_PRE "iwlwifi-ma-b0-gf-a0" +#define IWL_MA_B_GF4_A_FW_PRE "iwlwifi-ma-b0-gf4-a0" +#define IWL_MA_B_MR_A_FW_PRE "iwlwifi-ma-b0-mr-a0" + +#define IWL_SO_A_JF_B_MODULE_FIRMWARE(api) \ + IWL_SO_A_JF_B_FW_PRE "-" __stringify(api) ".ucode" +#define IWL_SO_A_HR_B_MODULE_FIRMWARE(api) \ + IWL_SO_A_HR_B_FW_PRE "-" __stringify(api) ".ucode" +#define IWL_SO_A_GF_A_MODULE_FIRMWARE(api) \ + IWL_SO_A_GF_A_FW_PRE "-" __stringify(api) ".ucode" +#define IWL_TY_A_GF_A_MODULE_FIRMWARE(api) \ + IWL_TY_A_GF_A_FW_PRE "-" __stringify(api) ".ucode" +#define IWL_MA_A_HR_B_FW_MODULE_FIRMWARE(api) \ + IWL_MA_A_HR_B_FW_PRE "-" __stringify(api) ".ucode" +#define IWL_MA_A_GF_A_FW_MODULE_FIRMWARE(api) \ + IWL_MA_A_GF_A_FW_PRE "-" __stringify(api) ".ucode" +#define IWL_MA_A_GF4_A_FW_MODULE_FIRMWARE(api) \ + IWL_MA_A_GF4_A_FW_PRE "-" __stringify(api) ".ucode" +#define IWL_MA_A_MR_A_FW_MODULE_FIRMWARE(api) \ + IWL_MA_A_MR_A_FW_PRE "-" __stringify(api) ".ucode" +#define IWL_MA_B_HR_B_FW_MODULE_FIRMWARE(api) \ + IWL_MA_B_HR_B_FW_PRE "-" __stringify(api) ".ucode" +#define IWL_MA_B_GF_A_FW_MODULE_FIRMWARE(api) \ + IWL_MA_B_GF_A_FW_PRE "-" __stringify(api) ".ucode" +#define IWL_MA_B_GF4_A_FW_MODULE_FIRMWARE(api) \ + IWL_MA_B_GF4_A_FW_PRE "-" __stringify(api) ".ucode" +#define IWL_MA_B_MR_A_FW_MODULE_FIRMWARE(api) \ + IWL_MA_B_MR_A_FW_PRE "-" __stringify(api) ".ucode" + +static const struct iwl_base_params iwl_ax210_base_params = { + .eeprom_size = OTP_LOW_IMAGE_SIZE_32K, + .num_of_queues = 512, + .max_tfd_queue_size = 65536, + .shadow_ram_support = true, + .led_compensation = 57, + .wd_timeout = IWL_LONG_WD_TIMEOUT, + .max_event_log_size = 512, + .shadow_reg_enable = true, + .pcie_l1_allowed = true, +}; + +#define IWL_DEVICE_AX210_COMMON \ + .ucode_api_min = IWL_AX210_UCODE_API_MIN, \ + .led_mode = IWL_LED_RF_STATE, \ + .nvm_hw_section_num = 10, \ + .non_shared_ant = ANT_B, \ + .dccm_offset = IWL_AX210_DCCM_OFFSET, \ + .dccm_len = IWL_AX210_DCCM_LEN, \ + .dccm2_offset = IWL_AX210_DCCM2_OFFSET, \ + .dccm2_len = IWL_AX210_DCCM2_LEN, \ + .smem_offset = IWL_AX210_SMEM_OFFSET, \ + .smem_len = IWL_AX210_SMEM_LEN, \ + .features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM, \ + .apmg_not_supported = true, \ + .trans.mq_rx_supported = true, \ + .vht_mu_mimo_supported = true, \ + .mac_addr_from_csr = 0x380, \ + .ht_params = &iwl_22000_ht_params, \ + .nvm_ver = IWL_AX210_NVM_VERSION, \ + .trans.rf_id = true, \ + .trans.gen2 = true, \ + .nvm_type = IWL_NVM_EXT, \ + .dbgc_supported = true, \ + .min_umac_error_event_table = 0x400000, \ + .d3_debug_data_base_addr = 0x401000, \ + .d3_debug_data_length = 60 * 1024, \ + .mon_smem_regs = { \ + .write_ptr = { \ + .addr = LDBG_M2S_BUF_WPTR, \ + .mask = LDBG_M2S_BUF_WPTR_VAL_MSK, \ + }, \ + .cycle_cnt = { \ + .addr = LDBG_M2S_BUF_WRAP_CNT, \ + .mask = LDBG_M2S_BUF_WRAP_CNT_VAL_MSK, \ + }, \ + } + +#define IWL_DEVICE_AX210 \ + IWL_DEVICE_AX210_COMMON, \ + .ucode_api_max = IWL_AX210_UCODE_API_MAX, \ + .trans.umac_prph_offset = 0x300000, \ + .trans.device_family = IWL_DEVICE_FAMILY_AX210, \ + .trans.base_params = &iwl_ax210_base_params, \ + .min_txq_size = 128, \ + .gp2_reg_addr = 0xd02c68, \ + .min_ba_txq_size = IWL_DEFAULT_QUEUE_SIZE_HE, \ + .mon_dram_regs = { \ + .write_ptr = { \ + .addr = DBGC_CUR_DBGBUF_STATUS, \ + .mask = DBGC_CUR_DBGBUF_STATUS_OFFSET_MSK, \ + }, \ + .cycle_cnt = { \ + .addr = DBGC_DBGBUF_WRAP_AROUND, \ + .mask = 0xffffffff, \ + }, \ + .cur_frag = { \ + .addr = DBGC_CUR_DBGBUF_STATUS, \ + .mask = DBGC_CUR_DBGBUF_STATUS_IDX_MSK, \ + }, \ + } + +const struct iwl_cfg_trans_params iwl_so_trans_cfg = { + .mq_rx_supported = true, + .rf_id = true, + .gen2 = true, + .device_family = IWL_DEVICE_FAMILY_AX210, + .base_params = &iwl_ax210_base_params, + .umac_prph_offset = 0x300000, + .integrated = true, + /* TODO: the following values need to be checked */ + .xtal_latency = 500, + .ltr_delay = IWL_CFG_TRANS_LTR_DELAY_200US, +}; + +const struct iwl_cfg_trans_params iwl_so_long_latency_trans_cfg = { + .mq_rx_supported = true, + .rf_id = true, + .gen2 = true, + .device_family = IWL_DEVICE_FAMILY_AX210, + .base_params = &iwl_ax210_base_params, + .umac_prph_offset = 0x300000, + .integrated = true, + .low_latency_xtal = true, + .xtal_latency = 12000, + .ltr_delay = IWL_CFG_TRANS_LTR_DELAY_2500US, +}; + +const struct iwl_cfg_trans_params iwl_so_long_latency_imr_trans_cfg = { + .mq_rx_supported = true, + .rf_id = true, + .gen2 = true, + .device_family = IWL_DEVICE_FAMILY_AX210, + .base_params = &iwl_ax210_base_params, + .umac_prph_offset = 0x300000, + .integrated = true, + .low_latency_xtal = true, + .xtal_latency = 12000, + .ltr_delay = IWL_CFG_TRANS_LTR_DELAY_2500US, + .imr_enabled = true, +}; + +/* + * If the device doesn't support HE, no need to have that many buffers. + * AX210 devices can split multiple frames into a single RB, so fewer are + * needed; AX210 cannot (but use smaller RBs by default) - these sizes + * were picked according to 8 MSDUs inside 256 A-MSDUs in an A-MPDU, with + * additional overhead to account for processing time. + */ +#define IWL_NUM_RBDS_NON_HE 512 +#define IWL_NUM_RBDS_AX210_HE 4096 + +const struct iwl_cfg_trans_params iwl_ma_trans_cfg = { + .device_family = IWL_DEVICE_FAMILY_AX210, + .base_params = &iwl_ax210_base_params, + .mq_rx_supported = true, + .rf_id = true, + .gen2 = true, + .integrated = true, + .umac_prph_offset = 0x300000 +}; + +const char iwl_ax211_name[] = "Intel(R) Wi-Fi 6E AX211 160MHz"; +const char iwl_ax221_name[] = "Intel(R) Wi-Fi 6E AX221 160MHz"; +const char iwl_ax231_name[] = "Intel(R) Wi-Fi 6E AX231 160MHz"; +const char iwl_ax411_name[] = "Intel(R) Wi-Fi 6E AX411 160MHz"; + +const char iwl_ax210_killer_1675w_name[] = + "Killer(R) Wi-Fi 6E AX1675w 160MHz Wireless Network Adapter (210D2W)"; +const char iwl_ax210_killer_1675x_name[] = + "Killer(R) Wi-Fi 6E AX1675x 160MHz Wireless Network Adapter (210NGW)"; +const char iwl_ax211_killer_1675s_name[] = + "Killer(R) Wi-Fi 6E AX1675s 160MHz Wireless Network Adapter (211NGW)"; +const char iwl_ax211_killer_1675i_name[] = + "Killer(R) Wi-Fi 6E AX1675i 160MHz Wireless Network Adapter (211NGW)"; +const char iwl_ax411_killer_1690s_name[] = + "Killer(R) Wi-Fi 6E AX1690s 160MHz Wireless Network Adapter (411D2W)"; +const char iwl_ax411_killer_1690i_name[] = + "Killer(R) Wi-Fi 6E AX1690i 160MHz Wireless Network Adapter (411NGW)"; + +const struct iwl_cfg iwlax210_2ax_cfg_so_jf_b0 = { + .name = "Intel(R) Wireless-AC 9560 160MHz", + .fw_name_pre = IWL_SO_A_JF_B_FW_PRE, + IWL_DEVICE_AX210, + .num_rbds = IWL_NUM_RBDS_NON_HE, +}; + +const struct iwl_cfg iwlax211_2ax_cfg_so_gf_a0 = { + .name = iwl_ax211_name, + .fw_name_pre = IWL_SO_A_GF_A_FW_PRE, + .uhb_supported = true, + IWL_DEVICE_AX210, + .num_rbds = IWL_NUM_RBDS_AX210_HE, +}; + +const struct iwl_cfg iwlax211_2ax_cfg_so_gf_a0_long = { + .name = iwl_ax211_name, + .fw_name_pre = IWL_SO_A_GF_A_FW_PRE, + .uhb_supported = true, + IWL_DEVICE_AX210, + .num_rbds = IWL_NUM_RBDS_AX210_HE, + .trans.xtal_latency = 12000, + .trans.low_latency_xtal = true, +}; + +const struct iwl_cfg iwlax210_2ax_cfg_ty_gf_a0 = { + .name = "Intel(R) Wi-Fi 6 AX210 160MHz", + .fw_name_pre = IWL_TY_A_GF_A_FW_PRE, + .uhb_supported = true, + IWL_DEVICE_AX210, + .num_rbds = IWL_NUM_RBDS_AX210_HE, +}; + +const struct iwl_cfg iwlax411_2ax_cfg_so_gf4_a0 = { + .name = iwl_ax411_name, + .fw_name_pre = IWL_SO_A_GF4_A_FW_PRE, + .uhb_supported = true, + IWL_DEVICE_AX210, + .num_rbds = IWL_NUM_RBDS_AX210_HE, +}; + +const struct iwl_cfg iwlax411_2ax_cfg_so_gf4_a0_long = { + .name = iwl_ax411_name, + .fw_name_pre = IWL_SO_A_GF4_A_FW_PRE, + .uhb_supported = true, + IWL_DEVICE_AX210, + .num_rbds = IWL_NUM_RBDS_AX210_HE, + .trans.xtal_latency = 12000, + .trans.low_latency_xtal = true, +}; + +const struct iwl_cfg iwl_cfg_so_a0_ms_a0 = { + .fw_name_pre = IWL_SO_A_MR_A_FW_PRE, + .uhb_supported = false, + IWL_DEVICE_AX210, + .num_rbds = IWL_NUM_RBDS_AX210_HE, +}; + +const struct iwl_cfg iwl_cfg_ma = { + .fw_name_mac = "ma", + .uhb_supported = true, + IWL_DEVICE_AX210, + .num_rbds = IWL_NUM_RBDS_AX210_HE, +}; + +const struct iwl_cfg iwl_cfg_so_a0_hr_a0 = { + .fw_name_pre = IWL_SO_A_HR_B_FW_PRE, + IWL_DEVICE_AX210, + .num_rbds = IWL_NUM_RBDS_AX210_HE, +}; + +MODULE_FIRMWARE(IWL_SO_A_JF_B_MODULE_FIRMWARE(IWL_AX210_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL_SO_A_HR_B_MODULE_FIRMWARE(IWL_AX210_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL_SO_A_GF_A_MODULE_FIRMWARE(IWL_AX210_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL_TY_A_GF_A_MODULE_FIRMWARE(IWL_AX210_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL_MA_A_HR_B_FW_MODULE_FIRMWARE(IWL_AX210_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL_MA_A_GF_A_FW_MODULE_FIRMWARE(IWL_AX210_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL_MA_A_GF4_A_FW_MODULE_FIRMWARE(IWL_AX210_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL_MA_A_MR_A_FW_MODULE_FIRMWARE(IWL_AX210_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL_MA_B_HR_B_FW_MODULE_FIRMWARE(IWL_AX210_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL_MA_B_GF_A_FW_MODULE_FIRMWARE(IWL_AX210_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL_MA_B_GF4_A_FW_MODULE_FIRMWARE(IWL_AX210_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL_MA_B_MR_A_FW_MODULE_FIRMWARE(IWL_AX210_UCODE_API_MAX)); diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/bz.c b/drivers/net/wireless/intel/iwlwifi/cfg/bz.c new file mode 100644 index 0000000000000000000000000000000000000000..b9893b22e41da6d75e52de9b8c110f51aa23f889 --- /dev/null +++ b/drivers/net/wireless/intel/iwlwifi/cfg/bz.c @@ -0,0 +1,183 @@ +// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause +/* + * Copyright (C) 2015-2017 Intel Deutschland GmbH + * Copyright (C) 2018-2023 Intel Corporation + */ +#include +#include +#include "iwl-config.h" +#include "iwl-prph.h" +#include "fw/api/txq.h" + +/* Highest firmware API version supported */ +#define IWL_BZ_UCODE_API_MAX 83 + +/* Lowest firmware API version supported */ +#define IWL_BZ_UCODE_API_MIN 80 + +/* NVM versions */ +#define IWL_BZ_NVM_VERSION 0x0a1d + +/* Memory offsets and lengths */ +#define IWL_BZ_DCCM_OFFSET 0x800000 /* LMAC1 */ +#define IWL_BZ_DCCM_LEN 0x10000 /* LMAC1 */ +#define IWL_BZ_DCCM2_OFFSET 0x880000 +#define IWL_BZ_DCCM2_LEN 0x8000 +#define IWL_BZ_SMEM_OFFSET 0x400000 +#define IWL_BZ_SMEM_LEN 0xD0000 + +#define IWL_BZ_A_HR_B_FW_PRE "iwlwifi-bz-a0-hr-b0" +#define IWL_BZ_A_GF_A_FW_PRE "iwlwifi-bz-a0-gf-a0" +#define IWL_BZ_A_GF4_A_FW_PRE "iwlwifi-bz-a0-gf4-a0" +#define IWL_BZ_A_FM_B_FW_PRE "iwlwifi-bz-a0-fm-b0" +#define IWL_BZ_A_FM_C_FW_PRE "iwlwifi-bz-a0-fm-c0" +#define IWL_BZ_A_FM4_B_FW_PRE "iwlwifi-bz-a0-fm4-b0" +#define IWL_GL_B_FM_B_FW_PRE "iwlwifi-gl-b0-fm-b0" +#define IWL_GL_C_FM_C_FW_PRE "iwlwifi-gl-c0-fm-c0" + +#define IWL_BZ_A_HR_B_MODULE_FIRMWARE(api) \ + IWL_BZ_A_HR_B_FW_PRE "-" __stringify(api) ".ucode" +#define IWL_BZ_A_GF_A_MODULE_FIRMWARE(api) \ + IWL_BZ_A_GF_A_FW_PRE "-" __stringify(api) ".ucode" +#define IWL_BZ_A_GF4_A_MODULE_FIRMWARE(api) \ + IWL_BZ_A_GF4_A_FW_PRE "-" __stringify(api) ".ucode" +#define IWL_BZ_A_FM_B_MODULE_FIRMWARE(api) \ + IWL_BZ_A_FM_B_FW_PRE "-" __stringify(api) ".ucode" +#define IWL_BZ_A_FM_C_MODULE_FIRMWARE(api) \ + IWL_BZ_A_FM_C_FW_PRE "-" __stringify(api) ".ucode" +#define IWL_BZ_A_FM4_B_MODULE_FIRMWARE(api) \ + IWL_BZ_A_FM4_B_FW_PRE "-" __stringify(api) ".ucode" +#define IWL_GL_B_FM_B_MODULE_FIRMWARE(api) \ + IWL_GL_B_FM_B_FW_PRE "-" __stringify(api) ".ucode" +#define IWL_GL_C_FM_C_MODULE_FIRMWARE(api) \ + IWL_GL_C_FM_C_FW_PRE "-" __stringify(api) ".ucode" + +static const struct iwl_base_params iwl_bz_base_params = { + .eeprom_size = OTP_LOW_IMAGE_SIZE_32K, + .num_of_queues = 512, + .max_tfd_queue_size = 65536, + .shadow_ram_support = true, + .led_compensation = 57, + .wd_timeout = IWL_LONG_WD_TIMEOUT, + .max_event_log_size = 512, + .shadow_reg_enable = true, + .pcie_l1_allowed = true, +}; + +#define IWL_DEVICE_BZ_COMMON \ + .ucode_api_max = IWL_BZ_UCODE_API_MAX, \ + .ucode_api_min = IWL_BZ_UCODE_API_MIN, \ + .led_mode = IWL_LED_RF_STATE, \ + .nvm_hw_section_num = 10, \ + .non_shared_ant = ANT_B, \ + .dccm_offset = IWL_BZ_DCCM_OFFSET, \ + .dccm_len = IWL_BZ_DCCM_LEN, \ + .dccm2_offset = IWL_BZ_DCCM2_OFFSET, \ + .dccm2_len = IWL_BZ_DCCM2_LEN, \ + .smem_offset = IWL_BZ_SMEM_OFFSET, \ + .smem_len = IWL_BZ_SMEM_LEN, \ + .apmg_not_supported = true, \ + .trans.mq_rx_supported = true, \ + .vht_mu_mimo_supported = true, \ + .mac_addr_from_csr = 0x30, \ + .nvm_ver = IWL_BZ_NVM_VERSION, \ + .trans.rf_id = true, \ + .trans.gen2 = true, \ + .nvm_type = IWL_NVM_EXT, \ + .dbgc_supported = true, \ + .min_umac_error_event_table = 0xD0000, \ + .d3_debug_data_base_addr = 0x401000, \ + .d3_debug_data_length = 60 * 1024, \ + .mon_smem_regs = { \ + .write_ptr = { \ + .addr = LDBG_M2S_BUF_WPTR, \ + .mask = LDBG_M2S_BUF_WPTR_VAL_MSK, \ + }, \ + .cycle_cnt = { \ + .addr = LDBG_M2S_BUF_WRAP_CNT, \ + .mask = LDBG_M2S_BUF_WRAP_CNT_VAL_MSK, \ + }, \ + }, \ + .trans.umac_prph_offset = 0x300000, \ + .trans.device_family = IWL_DEVICE_FAMILY_BZ, \ + .trans.base_params = &iwl_bz_base_params, \ + .min_txq_size = 128, \ + .gp2_reg_addr = 0xd02c68, \ + .min_ba_txq_size = IWL_DEFAULT_QUEUE_SIZE_EHT, \ + .mon_dram_regs = { \ + .write_ptr = { \ + .addr = DBGC_CUR_DBGBUF_STATUS, \ + .mask = DBGC_CUR_DBGBUF_STATUS_OFFSET_MSK, \ + }, \ + .cycle_cnt = { \ + .addr = DBGC_DBGBUF_WRAP_AROUND, \ + .mask = 0xffffffff, \ + }, \ + .cur_frag = { \ + .addr = DBGC_CUR_DBGBUF_STATUS, \ + .mask = DBGC_CUR_DBGBUF_STATUS_IDX_MSK, \ + }, \ + }, \ + .mon_dbgi_regs = { \ + .write_ptr = { \ + .addr = DBGI_SRAM_FIFO_POINTERS, \ + .mask = DBGI_SRAM_FIFO_POINTERS_WR_PTR_MSK, \ + }, \ + } + +#define IWL_DEVICE_BZ \ + IWL_DEVICE_BZ_COMMON, \ + .ht_params = &iwl_22000_ht_params + +#define IWL_DEVICE_GL_A \ + IWL_DEVICE_BZ_COMMON, \ + .ht_params = &iwl_gl_a_ht_params + +/* + * If the device doesn't support HE, no need to have that many buffers. + * These sizes were picked according to 8 MSDUs inside 256 A-MSDUs in an + * A-MPDU, with additional overhead to account for processing time. + */ +#define IWL_NUM_RBDS_NON_HE 512 +#define IWL_NUM_RBDS_BZ_HE 4096 + +const struct iwl_cfg_trans_params iwl_bz_trans_cfg = { + .device_family = IWL_DEVICE_FAMILY_BZ, + .base_params = &iwl_bz_base_params, + .mq_rx_supported = true, + .rf_id = true, + .gen2 = true, + .integrated = true, + .umac_prph_offset = 0x300000, + .xtal_latency = 12000, + .low_latency_xtal = true, + .ltr_delay = IWL_CFG_TRANS_LTR_DELAY_2500US, +}; + +const char iwl_bz_name[] = "Intel(R) TBD Bz device"; + +const struct iwl_cfg iwl_cfg_bz = { + .fw_name_mac = "bz", + .uhb_supported = true, + IWL_DEVICE_BZ, + .features = IWL_TX_CSUM_NETIF_FLAGS_BZ | NETIF_F_RXCSUM, + .num_rbds = IWL_NUM_RBDS_BZ_HE, +}; + +const struct iwl_cfg iwl_cfg_gl = { + .fw_name_mac = "gl", + .uhb_supported = true, + IWL_DEVICE_BZ, + .features = IWL_TX_CSUM_NETIF_FLAGS_BZ | NETIF_F_RXCSUM, + .num_rbds = IWL_NUM_RBDS_BZ_HE, +}; + + +MODULE_FIRMWARE(IWL_BZ_A_HR_B_MODULE_FIRMWARE(IWL_BZ_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL_BZ_A_GF_A_MODULE_FIRMWARE(IWL_BZ_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL_BZ_A_GF4_A_MODULE_FIRMWARE(IWL_BZ_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL_BZ_A_FM_B_MODULE_FIRMWARE(IWL_BZ_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL_BZ_A_FM_C_MODULE_FIRMWARE(IWL_BZ_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL_BZ_A_FM4_B_MODULE_FIRMWARE(IWL_BZ_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL_GL_B_FM_B_MODULE_FIRMWARE(IWL_BZ_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL_GL_C_FM_C_MODULE_FIRMWARE(IWL_BZ_UCODE_API_MAX)); diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/sc.c b/drivers/net/wireless/intel/iwlwifi/cfg/sc.c new file mode 100644 index 0000000000000000000000000000000000000000..ad283fd22e2a264c2b98b5c98c44f8b7428a4df8 --- /dev/null +++ b/drivers/net/wireless/intel/iwlwifi/cfg/sc.c @@ -0,0 +1,166 @@ +// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause +/* + * Copyright (C) 2015-2017 Intel Deutschland GmbH + * Copyright (C) 2018-2023 Intel Corporation + */ +#include +#include +#include "iwl-config.h" +#include "iwl-prph.h" +#include "fw/api/txq.h" + +/* Highest firmware API version supported */ +#define IWL_SC_UCODE_API_MAX 83 + +/* Lowest firmware API version supported */ +#define IWL_SC_UCODE_API_MIN 82 + +/* NVM versions */ +#define IWL_SC_NVM_VERSION 0x0a1d + +/* Memory offsets and lengths */ +#define IWL_SC_DCCM_OFFSET 0x800000 /* LMAC1 */ +#define IWL_SC_DCCM_LEN 0x10000 /* LMAC1 */ +#define IWL_SC_DCCM2_OFFSET 0x880000 +#define IWL_SC_DCCM2_LEN 0x8000 +#define IWL_SC_SMEM_OFFSET 0x400000 +#define IWL_SC_SMEM_LEN 0xD0000 + +#define IWL_SC_A_FM_B_FW_PRE "iwlwifi-sc-a0-fm-b0" +#define IWL_SC_A_FM_C_FW_PRE "iwlwifi-sc-a0-fm-c0" +#define IWL_SC_A_HR_A_FW_PRE "iwlwifi-sc-a0-hr-b0" +#define IWL_SC_A_HR_B_FW_PRE "iwlwifi-sc-a0-hr-b0" +#define IWL_SC_A_GF_A_FW_PRE "iwlwifi-sc-a0-gf-a0" +#define IWL_SC_A_GF4_A_FW_PRE "iwlwifi-sc-a0-gf4-a0" +#define IWL_SC_A_WH_A_FW_PRE "iwlwifi-sc-a0-wh-a0" + +#define IWL_SC_A_FM_B_FW_MODULE_FIRMWARE(api) \ + IWL_SC_A_FM_B_FW_PRE "-" __stringify(api) ".ucode" +#define IWL_SC_A_FM_C_FW_MODULE_FIRMWARE(api) \ + IWL_SC_A_FM_C_FW_PRE "-" __stringify(api) ".ucode" +#define IWL_SC_A_HR_A_FW_MODULE_FIRMWARE(api) \ + IWL_SC_A_HR_A_FW_PRE "-" __stringify(api) ".ucode" +#define IWL_SC_A_HR_B_FW_MODULE_FIRMWARE(api) \ + IWL_SC_A_HR_B_FW_PRE "-" __stringify(api) ".ucode" +#define IWL_SC_A_GF_A_FW_MODULE_FIRMWARE(api) \ + IWL_SC_A_GF_A_FW_PRE "-" __stringify(api) ".ucode" +#define IWL_SC_A_GF4_A_FW_MODULE_FIRMWARE(api) \ + IWL_SC_A_GF4_A_FW_PRE "-" __stringify(api) ".ucode" +#define IWL_SC_A_WH_A_FW_MODULE_FIRMWARE(api) \ + IWL_SC_A_WH_A_FW_PRE "-" __stringify(api) ".ucode" + +static const struct iwl_base_params iwl_sc_base_params = { + .eeprom_size = OTP_LOW_IMAGE_SIZE_32K, + .num_of_queues = 512, + .max_tfd_queue_size = 65536, + .shadow_ram_support = true, + .led_compensation = 57, + .wd_timeout = IWL_LONG_WD_TIMEOUT, + .max_event_log_size = 512, + .shadow_reg_enable = true, + .pcie_l1_allowed = true, +}; + +#define IWL_DEVICE_BZ_COMMON \ + .ucode_api_max = IWL_SC_UCODE_API_MAX, \ + .ucode_api_min = IWL_SC_UCODE_API_MIN, \ + .led_mode = IWL_LED_RF_STATE, \ + .nvm_hw_section_num = 10, \ + .non_shared_ant = ANT_B, \ + .dccm_offset = IWL_SC_DCCM_OFFSET, \ + .dccm_len = IWL_SC_DCCM_LEN, \ + .dccm2_offset = IWL_SC_DCCM2_OFFSET, \ + .dccm2_len = IWL_SC_DCCM2_LEN, \ + .smem_offset = IWL_SC_SMEM_OFFSET, \ + .smem_len = IWL_SC_SMEM_LEN, \ + .apmg_not_supported = true, \ + .trans.mq_rx_supported = true, \ + .vht_mu_mimo_supported = true, \ + .mac_addr_from_csr = 0x30, \ + .nvm_ver = IWL_SC_NVM_VERSION, \ + .trans.rf_id = true, \ + .trans.gen2 = true, \ + .nvm_type = IWL_NVM_EXT, \ + .dbgc_supported = true, \ + .min_umac_error_event_table = 0xD0000, \ + .d3_debug_data_base_addr = 0x401000, \ + .d3_debug_data_length = 60 * 1024, \ + .mon_smem_regs = { \ + .write_ptr = { \ + .addr = LDBG_M2S_BUF_WPTR, \ + .mask = LDBG_M2S_BUF_WPTR_VAL_MSK, \ + }, \ + .cycle_cnt = { \ + .addr = LDBG_M2S_BUF_WRAP_CNT, \ + .mask = LDBG_M2S_BUF_WRAP_CNT_VAL_MSK, \ + }, \ + }, \ + .trans.umac_prph_offset = 0x300000, \ + .trans.device_family = IWL_DEVICE_FAMILY_SC, \ + .trans.base_params = &iwl_sc_base_params, \ + .min_txq_size = 128, \ + .gp2_reg_addr = 0xd02c68, \ + .min_ba_txq_size = IWL_DEFAULT_QUEUE_SIZE_EHT, \ + .mon_dram_regs = { \ + .write_ptr = { \ + .addr = DBGC_CUR_DBGBUF_STATUS, \ + .mask = DBGC_CUR_DBGBUF_STATUS_OFFSET_MSK, \ + }, \ + .cycle_cnt = { \ + .addr = DBGC_DBGBUF_WRAP_AROUND, \ + .mask = 0xffffffff, \ + }, \ + .cur_frag = { \ + .addr = DBGC_CUR_DBGBUF_STATUS, \ + .mask = DBGC_CUR_DBGBUF_STATUS_IDX_MSK, \ + }, \ + }, \ + .mon_dbgi_regs = { \ + .write_ptr = { \ + .addr = DBGI_SRAM_FIFO_POINTERS, \ + .mask = DBGI_SRAM_FIFO_POINTERS_WR_PTR_MSK, \ + }, \ + } + +#define IWL_DEVICE_SC \ + IWL_DEVICE_BZ_COMMON, \ + .ht_params = &iwl_22000_ht_params + +/* + * If the device doesn't support HE, no need to have that many buffers. + * These sizes were picked according to 8 MSDUs inside 256 A-MSDUs in an + * A-MPDU, with additional overhead to account for processing time. + */ +#define IWL_NUM_RBDS_NON_HE 512 +#define IWL_NUM_RBDS_SC_HE 4096 + +const struct iwl_cfg_trans_params iwl_sc_trans_cfg = { + .device_family = IWL_DEVICE_FAMILY_SC, + .base_params = &iwl_sc_base_params, + .mq_rx_supported = true, + .rf_id = true, + .gen2 = true, + .integrated = true, + .umac_prph_offset = 0x300000, + .xtal_latency = 12000, + .low_latency_xtal = true, + .ltr_delay = IWL_CFG_TRANS_LTR_DELAY_2500US, +}; + +const char iwl_sc_name[] = "Intel(R) TBD Sc device"; + +const struct iwl_cfg iwl_cfg_sc = { + .fw_name_mac = "sc", + .uhb_supported = true, + IWL_DEVICE_SC, + .features = IWL_TX_CSUM_NETIF_FLAGS_BZ | NETIF_F_RXCSUM, + .num_rbds = IWL_NUM_RBDS_SC_HE, +}; + +MODULE_FIRMWARE(IWL_SC_A_FM_B_FW_MODULE_FIRMWARE(IWL_SC_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL_SC_A_FM_C_FW_MODULE_FIRMWARE(IWL_SC_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL_SC_A_HR_A_FW_MODULE_FIRMWARE(IWL_SC_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL_SC_A_HR_B_FW_MODULE_FIRMWARE(IWL_SC_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL_SC_A_GF_A_FW_MODULE_FIRMWARE(IWL_SC_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL_SC_A_GF4_A_FW_MODULE_FIRMWARE(IWL_SC_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL_SC_A_WH_A_FW_MODULE_FIRMWARE(IWL_SC_UCODE_API_MAX)); diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/rs.c b/drivers/net/wireless/intel/iwlwifi/dvm/rs.c index 687c906a9d727cf5b126944e0dd8c59a07054c9f..f4a6f76cf193ab6886fc787911ef807e8acdbc8f 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/rs.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/rs.c @@ -2,7 +2,7 @@ /****************************************************************************** * * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. - * Copyright (C) 2019 - 2020, 2022 Intel Corporation + * Copyright (C) 2019 - 2020, 2022 - 2023 Intel Corporation *****************************************************************************/ #include #include @@ -125,7 +125,7 @@ static int iwl_hwrate_to_plcp_idx(u32 rate_n_flags) return idx; } - return -1; + return IWL_RATE_INVALID; } static void rs_rate_scale_perform(struct iwl_priv *priv, @@ -203,23 +203,6 @@ static const u16 expected_tpt_mimo3_40MHz[4][IWL_RATE_COUNT] = { {0, 0, 0, 0, 277, 0, 478, 624, 737, 911, 1026, 1070, 1109}, /* AGG+SGI */ }; -/* mbps, mcs */ -static const struct iwl_rate_mcs_info iwl_rate_mcs[IWL_RATE_COUNT] = { - { "1", "BPSK DSSS"}, - { "2", "QPSK DSSS"}, - {"5.5", "BPSK CCK"}, - { "11", "QPSK CCK"}, - { "6", "BPSK 1/2"}, - { "9", "BPSK 1/2"}, - { "12", "QPSK 1/2"}, - { "18", "QPSK 3/4"}, - { "24", "16QAM 1/2"}, - { "36", "16QAM 3/4"}, - { "48", "64QAM 2/3"}, - { "54", "64QAM 3/4"}, - { "60", "64QAM 5/6"}, -}; - #define MCS_INDEX_PER_STREAM (8) static void rs_rate_scale_clear_window(struct iwl_rate_scale_data *window) @@ -3089,6 +3072,23 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file, int index = 0; ssize_t ret; + /* mbps, mcs */ + static const struct iwl_rate_mcs_info iwl_rate_mcs[IWL_RATE_COUNT] = { + { "1", "BPSK DSSS"}, + { "2", "QPSK DSSS"}, + {"5.5", "BPSK CCK"}, + { "11", "QPSK CCK"}, + { "6", "BPSK 1/2"}, + { "9", "BPSK 1/2"}, + { "12", "QPSK 1/2"}, + { "18", "QPSK 3/4"}, + { "24", "16QAM 1/2"}, + { "36", "16QAM 3/4"}, + { "48", "64QAM 2/3"}, + { "54", "64QAM 3/4"}, + { "60", "64QAM 5/6"}, + }; + struct iwl_lq_sta *lq_sta = file->private_data; struct iwl_priv *priv; struct iwl_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); @@ -3146,7 +3146,10 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file, for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) { index = iwl_hwrate_to_plcp_idx( le32_to_cpu(lq_sta->lq.rs_table[i].rate_n_flags)); - if (is_legacy(tbl->lq_type)) { + if (index == IWL_RATE_INVALID) { + desc += sprintf(buff + desc, " rate[%d] 0x%X invalid rate\n", + i, le32_to_cpu(lq_sta->lq.rs_table[i].rate_n_flags)); + } else if (is_legacy(tbl->lq_type)) { desc += sprintf(buff+desc, " rate[%d] 0x%X %smbps\n", i, le32_to_cpu(lq_sta->lq.rs_table[i].rate_n_flags), iwl_rate_mcs[index].mbps); diff --git a/drivers/net/wireless/intel/iwlwifi/fw/acpi.c b/drivers/net/wireless/intel/iwlwifi/fw/acpi.c index cb9181f05501130b3cd6fb9cf348996397f6082c..dfe8357036eb07783b84ea3ceb953aa18e23a322 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/acpi.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/acpi.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* * Copyright (C) 2017 Intel Deutschland GmbH - * Copyright (C) 2019-2022 Intel Corporation + * Copyright (C) 2019-2023 Intel Corporation */ #include #include @@ -41,6 +41,34 @@ static const struct dmi_system_id dmi_ppag_approved_list[] = { DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), }, }, + { .ident = "GOOGLE-HP", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Google"), + DMI_MATCH(DMI_BOARD_VENDOR, "HP"), + }, + }, + { .ident = "GOOGLE-ASUS", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Google"), + DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTek COMPUTER INC."), + }, + }, + { .ident = "GOOGLE-SAMSUNG", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Google"), + DMI_MATCH(DMI_BOARD_VENDOR, "SAMSUNG ELECTRONICS CO., LTD"), + }, + }, + { .ident = "DELL", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + }, + }, + { .ident = "DELL", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Alienware"), + }, + }, {} }; @@ -66,7 +94,7 @@ static int iwl_acpi_get_handle(struct device *dev, acpi_string method, return 0; } -void *iwl_acpi_get_object(struct device *dev, acpi_string method) +static void *iwl_acpi_get_object(struct device *dev, acpi_string method) { struct acpi_buffer buf = {ACPI_ALLOCATE_BUFFER, NULL}; acpi_handle handle; @@ -87,7 +115,6 @@ void *iwl_acpi_get_object(struct device *dev, acpi_string method) } return buf.pointer; } -IWL_EXPORT_SYMBOL(iwl_acpi_get_object); /* * Generic function for evaluating a method defined in the device specific @@ -209,11 +236,12 @@ int iwl_acpi_get_dsm_u32(struct device *dev, int rev, int func, } IWL_EXPORT_SYMBOL(iwl_acpi_get_dsm_u32); -union acpi_object *iwl_acpi_get_wifi_pkg_range(struct device *dev, - union acpi_object *data, - int min_data_size, - int max_data_size, - int *tbl_rev) +static union acpi_object * +iwl_acpi_get_wifi_pkg_range(struct device *dev, + union acpi_object *data, + int min_data_size, + int max_data_size, + int *tbl_rev) { int i; union acpi_object *wifi_pkg; @@ -264,7 +292,16 @@ union acpi_object *iwl_acpi_get_wifi_pkg_range(struct device *dev, found: return wifi_pkg; } -IWL_EXPORT_SYMBOL(iwl_acpi_get_wifi_pkg_range); + +static union acpi_object * +iwl_acpi_get_wifi_pkg(struct device *dev, + union acpi_object *data, + int data_size, int *tbl_rev) +{ + return iwl_acpi_get_wifi_pkg_range(dev, data, data_size, data_size, + tbl_rev); +} + int iwl_acpi_get_tas(struct iwl_fw_runtime *fwrt, union iwl_tas_config_cmd *cmd, int fw_ver) @@ -1141,33 +1178,48 @@ int iwl_read_ppag_table(struct iwl_fw_runtime *fwrt, union iwl_ppag_table_cmd *c */ cmd->v1.flags = cpu_to_le32(fwrt->ppag_flags); + IWL_DEBUG_RADIO(fwrt, "PPAG cmd ver is %d\n", cmd_ver); if (cmd_ver == 1) { num_sub_bands = IWL_NUM_SUB_BANDS_V1; gain = cmd->v1.gain[0]; *cmd_size = sizeof(cmd->v1); if (fwrt->ppag_ver == 1 || fwrt->ppag_ver == 2) { + /* in this case FW supports revision 0 */ IWL_DEBUG_RADIO(fwrt, - "PPAG table rev is %d but FW supports v1, sending truncated table\n", + "PPAG table rev is %d, send truncated table\n", fwrt->ppag_ver); - cmd->v1.flags &= cpu_to_le32(IWL_PPAG_ETSI_MASK); } } else if (cmd_ver >= 2 && cmd_ver <= 4) { num_sub_bands = IWL_NUM_SUB_BANDS_V2; gain = cmd->v2.gain[0]; *cmd_size = sizeof(cmd->v2); if (fwrt->ppag_ver == 0) { + /* in this case FW supports revisions 1 or 2 */ IWL_DEBUG_RADIO(fwrt, - "PPAG table is v1 but FW supports v2, sending padded table\n"); - } else if (cmd_ver == 2 && fwrt->ppag_ver == 2) { - IWL_DEBUG_RADIO(fwrt, - "PPAG table is v3 but FW supports v2, sending partial bitmap.\n"); - cmd->v1.flags &= cpu_to_le32(IWL_PPAG_ETSI_MASK); + "PPAG table rev is 0, send padded table\n"); } } else { IWL_DEBUG_RADIO(fwrt, "Unsupported PPAG command version\n"); return -EINVAL; } + /* ppag mode */ + IWL_DEBUG_RADIO(fwrt, + "PPAG MODE bits were read from bios: %d\n", + cmd->v1.flags & cpu_to_le32(ACPI_PPAG_MASK)); + if ((cmd_ver == 1 && !fw_has_capa(&fwrt->fw->ucode_capa, + IWL_UCODE_TLV_CAPA_PPAG_CHINA_BIOS_SUPPORT)) || + (cmd_ver == 2 && fwrt->ppag_ver == 2)) { + cmd->v1.flags &= cpu_to_le32(IWL_PPAG_ETSI_MASK); + IWL_DEBUG_RADIO(fwrt, "masking ppag China bit\n"); + } else { + IWL_DEBUG_RADIO(fwrt, "isn't masking ppag China bit\n"); + } + + IWL_DEBUG_RADIO(fwrt, + "PPAG MODE bits going to be sent: %d\n", + cmd->v1.flags & cpu_to_le32(ACPI_PPAG_MASK)); + for (i = 0; i < IWL_NUM_CHAIN_LIMITS; i++) { for (j = 0; j < num_sub_bands; j++) { gain[i * num_sub_bands + j] = @@ -1196,3 +1248,40 @@ bool iwl_acpi_is_ppag_approved(struct iwl_fw_runtime *fwrt) return true; } IWL_EXPORT_SYMBOL(iwl_acpi_is_ppag_approved); + +void iwl_acpi_get_phy_filters(struct iwl_fw_runtime *fwrt, + struct iwl_phy_specific_cfg *filters) +{ + struct iwl_phy_specific_cfg tmp = {}; + union acpi_object *wifi_pkg, *data; + int tbl_rev, i; + + data = iwl_acpi_get_object(fwrt->dev, ACPI_WPFC_METHOD); + if (IS_ERR(data)) + return; + + /* try to read wtas table revision 1 or revision 0*/ + wifi_pkg = iwl_acpi_get_wifi_pkg(fwrt->dev, data, + ACPI_WPFC_WIFI_DATA_SIZE, + &tbl_rev); + if (IS_ERR(wifi_pkg)) + goto out_free; + + if (tbl_rev != 0) + goto out_free; + + BUILD_BUG_ON(ARRAY_SIZE(filters->filter_cfg_chains) != ACPI_WPFC_WIFI_DATA_SIZE); + + for (i = 0; i < ARRAY_SIZE(filters->filter_cfg_chains); i++) { + if (wifi_pkg->package.elements[i].type != ACPI_TYPE_INTEGER) + return; + tmp.filter_cfg_chains[i] = + cpu_to_le32(wifi_pkg->package.elements[i].integer.value); + } + + IWL_DEBUG_RADIO(fwrt, "Loaded WPFC filter config from ACPI\n"); + *filters = tmp; +out_free: + kfree(data); +} +IWL_EXPORT_SYMBOL(iwl_acpi_get_phy_filters); diff --git a/drivers/net/wireless/intel/iwlwifi/fw/acpi.h b/drivers/net/wireless/intel/iwlwifi/fw/acpi.h index 6f361c59106f31a44d37429daa038b8f79c78da9..c36c62d6414de888d4e915a67185cdd2987ab722 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/acpi.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/acpi.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ /* * Copyright (C) 2017 Intel Deutschland GmbH - * Copyright (C) 2018-2022 Intel Corporation + * Copyright (C) 2018-2023 Intel Corporation */ #ifndef __iwl_fw_acpi__ #define __iwl_fw_acpi__ @@ -11,6 +11,7 @@ #include "fw/api/power.h" #include "fw/api/phy.h" #include "fw/api/nvm-reg.h" +#include "fw/api/config.h" #include "fw/img.h" #include "iwl-trans.h" @@ -23,6 +24,7 @@ #define ACPI_ECKV_METHOD "ECKV" #define ACPI_PPAG_METHOD "PPAG" #define ACPI_WTAS_METHOD "WTAS" +#define ACPI_WPFC_METHOD "WPFC" #define ACPI_WIFI_DOMAIN (0x07) @@ -54,6 +56,7 @@ #define ACPI_EWRD_WIFI_DATA_SIZE_REV2 ((ACPI_SAR_PROFILE_NUM - 1) * \ ACPI_SAR_NUM_CHAINS_REV2 * \ ACPI_SAR_NUM_SUB_BANDS_REV2 + 3) +#define ACPI_WPFC_WIFI_DATA_SIZE 4 /* 4 filter config words */ /* revision 0 and 1 are identical, except for the semantics in the FW */ #define ACPI_GEO_NUM_BANDS_REV0 2 @@ -168,19 +171,12 @@ struct iwl_fw_runtime; extern const guid_t iwl_guid; extern const guid_t iwl_rfi_guid; -void *iwl_acpi_get_object(struct device *dev, acpi_string method); - int iwl_acpi_get_dsm_u8(struct device *dev, int rev, int func, const guid_t *guid, u8 *value); int iwl_acpi_get_dsm_u32(struct device *dev, int rev, int func, const guid_t *guid, u32 *value); -union acpi_object *iwl_acpi_get_wifi_pkg_range(struct device *dev, - union acpi_object *data, - int min_data_size, - int max_data_size, - int *tbl_rev); /** * iwl_acpi_get_mcc - read MCC from ACPI, if available * @@ -232,12 +228,10 @@ int iwl_read_ppag_table(struct iwl_fw_runtime *fwrt, union iwl_ppag_table_cmd *c bool iwl_acpi_is_ppag_approved(struct iwl_fw_runtime *fwrt); -#else /* CONFIG_ACPI */ +void iwl_acpi_get_phy_filters(struct iwl_fw_runtime *fwrt, + struct iwl_phy_specific_cfg *filters); -static inline void *iwl_acpi_get_object(struct device *dev, acpi_string method) -{ - return ERR_PTR(-ENOENT); -} +#else /* CONFIG_ACPI */ static inline void *iwl_acpi_get_dsm_object(struct device *dev, int rev, int func, union acpi_object *args) @@ -257,15 +251,6 @@ static inline int iwl_acpi_get_dsm_u32(struct device *dev, int rev, int func, return -ENOENT; } -static inline union acpi_object * -iwl_acpi_get_wifi_pkg_range(struct device *dev, - union acpi_object *data, - int min_data_size, int max_data_size, - int *tbl_rev) -{ - return ERR_PTR(-ENOENT); -} - static inline int iwl_acpi_get_mcc(struct device *dev, char *mcc) { return -ENOENT; @@ -335,15 +320,11 @@ static inline bool iwl_acpi_is_ppag_approved(struct iwl_fw_runtime *fwrt) return false; } -#endif /* CONFIG_ACPI */ - -static inline union acpi_object * -iwl_acpi_get_wifi_pkg(struct device *dev, - union acpi_object *data, - int data_size, int *tbl_rev) +static inline void iwl_acpi_get_phy_filters(struct iwl_fw_runtime *fwrt, + struct iwl_phy_specific_cfg *filters) { - return iwl_acpi_get_wifi_pkg_range(dev, data, data_size, data_size, - tbl_rev); } +#endif /* CONFIG_ACPI */ + #endif /* __iwl_fw_acpi__ */ diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/binding.h b/drivers/net/wireless/intel/iwlwifi/fw/api/binding.h index 29e2816e70520f3b2a235351cc302f4a6475b160..d9044ada6a431dac1aa9d3763a93d7289162bfcf 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/binding.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/binding.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ /* - * Copyright (C) 2012-2014, 2020 Intel Corporation + * Copyright (C) 2012-2014, 2020, 2022 Intel Corporation * Copyright (C) 2013-2015 Intel Mobile Communications GmbH * Copyright (C) 2016-2017 Intel Deutschland GmbH */ @@ -18,7 +18,7 @@ * ( BINDING_CONTEXT_CMD = 0x2b ) * @id_and_color: ID and color of the relevant Binding, * &enum iwl_ctxt_id_and_color - * @action: action to perform, one of FW_CTXT_ACTION_* + * @action: action to perform, see &enum iwl_ctxt_action * @macs: array of MAC id and colors which belong to the binding, * &enum iwl_ctxt_id_and_color * @phy: PHY id and color which belongs to the binding, @@ -38,7 +38,7 @@ struct iwl_binding_cmd_v1 { * ( BINDING_CONTEXT_CMD = 0x2b ) * @id_and_color: ID and color of the relevant Binding, * &enum iwl_ctxt_id_and_color - * @action: action to perform, one of FW_CTXT_ACTION_* + * @action: action to perform, see &enum iwl_ctxt_action * @macs: array of MAC id and colors which belong to the binding * &enum iwl_ctxt_id_and_color * @phy: PHY id and color which belongs to the binding @@ -59,14 +59,6 @@ struct iwl_binding_cmd { #define IWL_LMAC_24G_INDEX 0 #define IWL_LMAC_5G_INDEX 1 -static inline u32 iwl_mvm_get_lmac_id(const struct iwl_fw *fw, - enum nl80211_band band){ - if (!fw_has_capa(&fw->ucode_capa, IWL_UCODE_TLV_CAPA_CDB_SUPPORT) || - band == NL80211_BAND_2GHZ) - return IWL_LMAC_24G_INDEX; - return IWL_LMAC_5G_INDEX; -} - /* The maximal number of fragments in the FW's schedule session */ #define IWL_MVM_MAX_QUOTA 128 diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/commands.h b/drivers/net/wireless/intel/iwlwifi/fw/api/commands.h index 111d96cbde6f819f9f9dc74d5ca1ac10d62aaa39..13cb0d53a1a37ce3ea61db70acc0b539efc31b53 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/commands.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/commands.h @@ -138,11 +138,6 @@ enum iwl_legacy_cmds { */ REMOVE_STA = 0x19, - /** - * @FW_GET_ITEM_CMD: uses &struct iwl_fw_get_item_cmd - */ - FW_GET_ITEM_CMD = 0x1a, - /** * @TX_CMD: uses &struct iwl_tx_cmd or &struct iwl_tx_cmd_gen2 or * &struct iwl_tx_cmd_gen3, @@ -533,12 +528,6 @@ enum iwl_legacy_cmds { */ PROT_OFFLOAD_CONFIG_CMD = 0xd4, - /** - * @OFFLOADS_QUERY_CMD: - * No data in command, response in &struct iwl_wowlan_status - */ - OFFLOADS_QUERY_CMD = 0xd5, - /** * @D0I3_END_CMD: End D0i3/D3 state, no command data */ @@ -566,18 +555,22 @@ enum iwl_legacy_cmds { WOWLAN_TKIP_PARAM = 0xe3, /** - * @WOWLAN_KEK_KCK_MATERIAL: &struct iwl_wowlan_kek_kck_material_cmd + * @WOWLAN_KEK_KCK_MATERIAL: &struct iwl_wowlan_kek_kck_material_cmd_v2, + * &struct iwl_wowlan_kek_kck_material_cmd_v3 or + * &struct iwl_wowlan_kek_kck_material_cmd_v4 */ WOWLAN_KEK_KCK_MATERIAL = 0xe4, /** - * @WOWLAN_GET_STATUSES: response in &struct iwl_wowlan_status + * @WOWLAN_GET_STATUSES: response in &struct iwl_wowlan_status_v6, + * &struct iwl_wowlan_status_v7, &struct iwl_wowlan_status_v9 or + * &struct iwl_wowlan_status_v12 */ WOWLAN_GET_STATUSES = 0xe5, /** - * @SCAN_OFFLOAD_PROFILES_QUERY_CMD: - * No command data, response is &struct iwl_scan_offload_profiles_query + * @SCAN_OFFLOAD_PROFILES_QUERY_CMD: No command data, response is + * &struct iwl_scan_offload_profiles_query_v1 */ SCAN_OFFLOAD_PROFILES_QUERY_CMD = 0x56, }; diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/config.h b/drivers/net/wireless/intel/iwlwifi/fw/api/config.h index 087354b3c3080b722433d6980f148adad803778f..4419631604b4fdb507b212feab608a1a1f69d850 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/config.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/config.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ /* - * Copyright (C) 2012-2014, 2018-2019 Intel Corporation + * Copyright (C) 2012-2014, 2018-2019, 2023 Intel Corporation * Copyright (C) 2013-2015 Intel Mobile Communications GmbH * Copyright (C) 2016-2017 Intel Deutschland GmbH */ @@ -67,17 +67,12 @@ enum iwl_calib_cfg { * Sent as part of the phy configuration command (v3) to configure specific FW * defined PHY filters that can be applied to each antenna. * - * @filter_cfg_chain_a: filter config id for LMAC1 chain A - * @filter_cfg_chain_b: filter config id for LMAC1 chain B - * @filter_cfg_chain_c: filter config id for LMAC2 chain A - * @filter_cfg_chain_d: filter config id for LMAC2 chain B - * values: 0 - no filter; 0xffffffff - reserved; otherwise - filter id + * @filter_cfg_chains: filter config id for LMAC1 chain A, LMAC1 chain B, + * LMAC2 chain A, LMAC2 chain B (in that order) + * values: 0: no filter; 0xffffffff: reserved; otherwise: filter id */ struct iwl_phy_specific_cfg { - __le32 filter_cfg_chain_a; - __le32 filter_cfg_chain_b; - __le32 filter_cfg_chain_c; - __le32 filter_cfg_chain_d; + __le32 filter_cfg_chains[4]; } __packed; /* PHY_SPECIFIC_CONFIGURATION_API_VER_1*/ /** diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/context.h b/drivers/net/wireless/intel/iwlwifi/fw/api/context.h index 105ba7170c3f0894421337387c129538ab594e8a..1fa5678c1cd6b7788d6c1731a884e882fadf2ac4 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/context.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/context.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ /* - * Copyright (C) 2012-2014 Intel Corporation + * Copyright (C) 2012-2014, 2022 Intel Corporation * Copyright (C) 2013-2015 Intel Mobile Communications GmbH * Copyright (C) 2016-2017 Intel Deutschland GmbH */ @@ -26,13 +26,18 @@ enum iwl_ctxt_id_and_color { #define FW_CMD_ID_AND_COLOR(_id, _color) (((_id) << FW_CTXT_ID_POS) |\ ((_color) << FW_CTXT_COLOR_POS)) -/* Possible actions on PHYs, MACs and Bindings */ +/** + * enum iwl_ctxt_action - Posssible actions on PHYs, MACs, Bindings and other + * @FW_CTXT_ACTION_INVALID: unused, invalid action + * @FW_CTXT_ACTION_ADD: add the context + * @FW_CTXT_ACTION_MODIFY: modify the context + * @FW_CTXT_ACTION_REMOVE: remove the context + */ enum iwl_ctxt_action { - FW_CTXT_ACTION_STUB = 0, + FW_CTXT_ACTION_INVALID = 0, FW_CTXT_ACTION_ADD, FW_CTXT_ACTION_MODIFY, FW_CTXT_ACTION_REMOVE, - FW_CTXT_ACTION_NUM }; /* COMMON_CONTEXT_ACTION_API_E_VER_1 */ #endif /* __iwl_fw_api_context_h__ */ diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h b/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h index 8a613e150a0245e6820f425c60baee6337d730f6..72d461c47323b6fe03cbe9306b3e270fecf4b6b3 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ /* - * Copyright (C) 2012-2014, 2018-2022 Intel Corporation + * Copyright (C) 2012-2014, 2018-2023 Intel Corporation * Copyright (C) 2013-2014 Intel Mobile Communications GmbH * Copyright (C) 2015-2017 Intel Deutschland GmbH */ @@ -47,12 +47,14 @@ struct iwl_d3_manager_config { * @IWL_D3_PROTO_OFFLOAD_NS: NS (Neighbor Solicitation) is enabled * @IWL_D3_PROTO_IPV4_VALID: IPv4 data is valid * @IWL_D3_PROTO_IPV6_VALID: IPv6 data is valid + * @IWL_D3_PROTO_OFFLOAD_BTM: BTM offload is enabled */ enum iwl_proto_offloads { IWL_D3_PROTO_OFFLOAD_ARP = BIT(0), IWL_D3_PROTO_OFFLOAD_NS = BIT(1), IWL_D3_PROTO_IPV4_VALID = BIT(2), IWL_D3_PROTO_IPV6_VALID = BIT(3), + IWL_D3_PROTO_OFFLOAD_BTM = BIT(4), }; #define IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_V1 2 @@ -394,6 +396,7 @@ struct iwl_wowlan_config_cmd { #define WOWLAN_KEY_MAX_SIZE 32 #define WOWLAN_GTK_KEYS_NUM 2 #define WOWLAN_IGTK_KEYS_NUM 2 +#define WOWLAN_IGTK_MIN_INDEX 4 /* * WOWLAN_TSC_RSC_PARAMS @@ -610,6 +613,7 @@ struct iwl_wowlan_gtk_status_v3 { } __packed; /* WOWLAN_GTK_MATERIAL_VER_3 */ #define IWL_WOWLAN_GTK_IDX_MASK (BIT(0) | BIT(1)) +#define IWL_WOWLAN_IGTK_BIGTK_IDX_MASK (BIT(0)) /** * struct iwl_wowlan_igtk_status - IGTK status diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/datapath.h b/drivers/net/wireless/intel/iwlwifi/fw/api/datapath.h index 6f59381b9f9a97e7e165d6535471a08fc6b84db3..751b596ea1a51be6155a08d8cd10dce11d4d79c8 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/datapath.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/datapath.h @@ -38,7 +38,9 @@ enum iwl_data_path_subcmd_ids { WNM_80211V_TIMING_MEASUREMENT_CONFIG_CMD = 0x4, /** - * @STA_HE_CTXT_CMD: &struct iwl_he_sta_context_cmd + * @STA_HE_CTXT_CMD: &struct iwl_he_sta_context_cmd_v1, + * &struct iwl_he_sta_context_cmd_v2 or + * &struct iwl_he_sta_context_cmd_v3 */ STA_HE_CTXT_CMD = 0x7, @@ -447,7 +449,7 @@ struct iwl_sad_properties { * @phy_id: PHY index * @rlc: RLC properties, &struct iwl_rlc_properties * @sad: SAD (single antenna diversity) options, &struct iwl_sad_properties - * @flags: flags, &enum iwl_rlc_flags + * @flags: flags (unused) * @reserved: reserved */ struct iwl_rlc_config_cmd { diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/location.h b/drivers/net/wireless/intel/iwlwifi/fw/api/location.h index 12af94e166ed0bbddb0d559c129d6fac3f52590d..b044990c7b87646c6c0166e53a7c707a03eb6e16 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/location.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/location.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ /* * Copyright (C) 2015-2017 Intel Deutschland GmbH - * Copyright (C) 2018-2021 Intel Corporation + * Copyright (C) 2018-2022 Intel Corporation */ #ifndef __iwl_fw_api_location_h__ #define __iwl_fw_api_location_h__ @@ -35,8 +35,11 @@ enum iwl_location_subcmd_ids { */ TOF_RANGE_REQ_EXT_CMD = 0x3, /** - * @TOF_RESPONDER_CONFIG_CMD: FTM responder configuration, - * uses &struct iwl_tof_responder_config_cmd + * @TOF_RESPONDER_CONFIG_CMD: FTM responder configuration, one of + * &struct iwl_tof_responder_config_cmd_v6, + * &struct iwl_tof_responder_config_cmd_v7, + * &struct iwl_tof_responder_config_cmd_v8 or + * &struct iwl_tof_responder_config_cmd_v9 */ TOF_RESPONDER_CONFIG_CMD = 0x4, /** @@ -69,8 +72,11 @@ enum iwl_location_subcmd_ids { */ TOF_MCSI_DEBUG_NOTIF = 0xFE, /** - * @TOF_RANGE_RESPONSE_NOTIF: ranging response, using - * &struct iwl_tof_range_rsp_ntfy + * @TOF_RANGE_RESPONSE_NOTIF: ranging response, using one of + * &struct iwl_tof_range_rsp_ntfy_v5, + * &struct iwl_tof_range_rsp_ntfy_v6, + * &struct iwl_tof_range_rsp_ntfy_v7 or + * &struct iwl_tof_range_rsp_ntfy_v8 */ TOF_RANGE_RESPONSE_NOTIF = 0xFF, }; diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h b/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h index 74f2efbad34e468062dc8b6668b2b8f89cf71bfb..184db5a6f06f1e03b8de662a4c10144c2ce009ec 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h @@ -140,40 +140,60 @@ struct iwl_missed_vap_notif { * * @id_and_color: ID and color of the MAC */ -struct iwl_channel_switch_start_notif { +struct iwl_channel_switch_start_notif_v1 { __le32 id_and_color; } __packed; /* CHANNEL_SWITCH_START_NTFY_API_S_VER_1 */ +/** + * struct iwl_channel_switch_start_notif - Channel switch start notification + * + * @link_id: FW link id + */ +struct iwl_channel_switch_start_notif { + __le32 link_id; +} __packed; /* CHANNEL_SWITCH_START_NTFY_API_S_VER_3 */ + #define CS_ERR_COUNT_ERROR BIT(0) #define CS_ERR_LONG_DELAY_AFTER_CS BIT(1) #define CS_ERR_LONG_TX_BLOCK BIT(2) #define CS_ERR_TX_BLOCK_TIMER_EXPIRED BIT(3) /** - * struct iwl_channel_switch_error_notif - Channel switch error notification + * struct iwl_channel_switch_error_notif_v1 - Channel switch error notification * * @mac_id: the mac for which the ucode sends the notification for * @csa_err_mask: mask of channel switch error that can occur */ -struct iwl_channel_switch_error_notif { +struct iwl_channel_switch_error_notif_v1 { __le32 mac_id; __le32 csa_err_mask; } __packed; /* CHANNEL_SWITCH_ERROR_NTFY_API_S_VER_1 */ +/** + * struct iwl_channel_switch_error_notif - Channel switch error notification + * + * @link_id: FW link id + * @csa_err_mask: mask of channel switch error that can occur + */ +struct iwl_channel_switch_error_notif { + __le32 link_id; + __le32 csa_err_mask; +} __packed; /* CHANNEL_SWITCH_ERROR_NTFY_API_S_VER_2 */ + /** * struct iwl_cancel_channel_switch_cmd - Cancel Channel Switch command * - * @mac_id: the mac that should cancel the channel switch + * @id: the id of the link or mac that should cancel the channel switch */ struct iwl_cancel_channel_switch_cmd { - __le32 mac_id; + __le32 id; } __packed; /* MAC_CANCEL_CHANNEL_SWITCH_S_VER_1 */ /** * struct iwl_chan_switch_te_cmd - Channel Switch Time Event command * * @mac_id: MAC ID for channel switch - * @action: action to perform, one of FW_CTXT_ACTION_* + * @action: action to perform, see &enum iwl_ctxt_action * @tsf: beacon tsf * @cs_count: channel switch count from CSA/eCSA IE * @cs_delayed_bcn_count: if set to N (!= 0) GO/AP can delay N beacon intervals @@ -211,17 +231,30 @@ struct iwl_mac_low_latency_cmd { * struct iwl_mac_client_data - configuration data for client MAC context * * @is_assoc: 1 for associated state, 0 otherwise + * @esr_transition_timeout: the timeout required by the AP for the + * eSR transition. + * Available only from version 2 of the command. + * This values comes from the EMLSR transition delay in the EML + * Capabilities subfield. + * @medium_sync_delay: the value as it appeasr in P802.11be_D2.2 Figure 9-1002j. * @assoc_id: unique ID assigned by the AP during association + * @reserved1: alignment * @data_policy: see &enum iwl_mac_data_policy + * @reserved2: alignment * @ctwin: client traffic window in TU (period after TBTT when GO is present). * 0 indicates that there is no CT window. */ struct iwl_mac_client_data { - __le32 is_assoc; - __le32 assoc_id; - __le32 data_policy; + u8 is_assoc; + u8 esr_transition_timeout; + __le16 medium_sync_delay; + + __le16 assoc_id; + __le16 reserved1; + __le16 data_policy; + __le16 reserved2; __le32 ctwin; -} __packed; /* MAC_CONTEXT_CONFIG_CLIENT_DATA_API_S_VER_1 */ +} __packed; /* MAC_CONTEXT_CONFIG_CLIENT_DATA_API_S_VER_2 */ /** * struct iwl_mac_p2p_dev_data - configuration data for P2P device MAC context @@ -263,7 +296,7 @@ enum iwl_mac_config_filter_flags { * ( MAC_CONTEXT_CONFIG_CMD = 0x8 ) * * @id_and_color: ID and color of the MAC - * @action: action to perform, one of FW_CTXT_ACTION_* + * @action: action to perform, see &enum iwl_ctxt_action * @mac_type: one of &enum iwl_mac_types * @local_mld_addr: mld address * @reserved_for_local_mld_addr: reserved @@ -292,12 +325,12 @@ struct iwl_mac_config_cmd { __le16 he_ap_support; __le32 eht_support; __le32 nic_not_ack_enabled; - /* MAC_CONTEXT_CONFIG_SPECIFIC_DATA_API_U_VER_1 */ + /* MAC_CONTEXT_CONFIG_SPECIFIC_DATA_API_U_VER_2 */ union { struct iwl_mac_client_data client; struct iwl_mac_p2p_dev_data p2p_dev; }; -} __packed; /* MAC_CONTEXT_CONFIG_CMD_API_S_VER_1 */ +} __packed; /* MAC_CONTEXT_CONFIG_CMD_API_S_VER_2 */ /** * enum iwl_link_ctx_modify_flags - indicate to the fw what fields are being @@ -390,7 +423,7 @@ enum iwl_link_ctx_flags { * in MLD API * ( LINK_CONFIG_CMD =0x9 ) * - * @action: action to perform, one of FW_CTXT_ACTION_* + * @action: action to perform, see &enum iwl_ctxt_action * @link_id: the id of the link that this cmd configures * @mac_id: interface ID. Relevant only if action is FW_CTXT_ACTION_ADD * @phy_id: PHY index. Can be changed only if the link was inactive @@ -430,6 +463,7 @@ enum iwl_link_ctx_flags { * @reserved_for_ref_bssid_addr: reserved * @bssid_index: index of the associated VAP * @bss_color: 11ax AP ID that is used in the HE SIG-A to mark inter BSS frame + * @spec_link_id: link_id as the AP knows it * @reserved: alignment * @ibss_bssid_addr: bssid for ibss * @reserved_for_ibss_bssid_addr: reserved @@ -469,7 +503,8 @@ struct iwl_link_config_cmd { __le16 reserved_for_ref_bssid_addr; u8 bssid_index; u8 bss_color; - u8 reserved[2]; + u8 spec_link_id; + u8 reserved; u8 ibss_bssid_addr[6]; __le16 reserved_for_ibss_bssid_addr; __le32 reserved1[8]; diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/mac.h b/drivers/net/wireless/intel/iwlwifi/fw/api/mac.h index e3eda251c728a6ba7d7b6c18893962cc861a7120..55882190251c58965b0f4c6844737c37e2ac2958 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/mac.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/mac.h @@ -295,7 +295,7 @@ struct iwl_ac_qos { * struct iwl_mac_ctx_cmd - command structure to configure MAC contexts * ( MAC_CONTEXT_CMD = 0x28 ) * @id_and_color: ID and color of the MAC - * @action: action to perform, one of FW_CTXT_ACTION_* + * @action: action to perform, see &enum iwl_ctxt_action * @mac_type: one of &enum iwl_mac_types * @tsf_id: TSF HW timer, one of &enum iwl_tsf_id * @node_addr: MAC address @@ -353,7 +353,7 @@ struct iwl_nonqos_seq_query_cmd { } __packed; /* NON_QOS_TX_COUNTER_GET_SET_API_S_VER_1 */ /** - * struct iwl_missed_beacons_notif - information on missed beacons + * struct iwl_missed_beacons_notif_ver_3 - information on missed beacons * ( MISSED_BEACONS_NOTIFICATION = 0xa2 ) * @mac_id: interface ID * @consec_missed_beacons_since_last_rx: number of consecutive missed @@ -362,7 +362,7 @@ struct iwl_nonqos_seq_query_cmd { * @num_expected_beacons: number of expected beacons * @num_recvd_beacons: number of received beacons */ -struct iwl_missed_beacons_notif { +struct iwl_missed_beacons_notif_ver_3 { __le32 mac_id; __le32 consec_missed_beacons_since_last_rx; __le32 consec_missed_beacons; @@ -370,6 +370,24 @@ struct iwl_missed_beacons_notif { __le32 num_recvd_beacons; } __packed; /* MISSED_BEACON_NTFY_API_S_VER_3 */ +/** + * struct iwl_missed_beacons_notif - information on missed beacons + * ( MISSED_BEACONS_NOTIFICATION = 0xa2 ) + * @link_id: fw link ID + * @consec_missed_beacons_since_last_rx: number of consecutive missed + * beacons since last RX. + * @consec_missed_beacons: number of consecutive missed beacons + * @num_expected_beacons: number of expected beacons + * @num_recvd_beacons: number of received beacons + */ +struct iwl_missed_beacons_notif { + __le32 link_id; + __le32 consec_missed_beacons_since_last_rx; + __le32 consec_missed_beacons; + __le32 num_expected_beacons; + __le32 num_recvd_beacons; +} __packed; /* MISSED_BEACON_NTFY_API_S_VER_4 */ + /** * struct iwl_he_backoff_conf - used for backoff configuration * Per each trigger-based AC, (set by MU EDCA Parameter set info-element) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h b/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h index 91bfde6d5367f1f3345fe38b0a365f26aafd42d1..28bfabb399b2f0b7e4dade4c7d4eb591b1f73994 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h @@ -17,7 +17,12 @@ enum iwl_regulatory_and_nvm_subcmd_ids { NVM_ACCESS_COMPLETE = 0x0, /** - * @LARI_CONFIG_CHANGE: &struct iwl_lari_config_change_cmd + * @LARI_CONFIG_CHANGE: &struct iwl_lari_config_change_cmd_v1, + * &struct iwl_lari_config_change_cmd_v2, + * &struct iwl_lari_config_change_cmd_v3, + * &struct iwl_lari_config_change_cmd_v4, + * &struct iwl_lari_config_change_cmd_v5 or + * &struct iwl_lari_config_change_cmd_v6 */ LARI_CONFIG_CHANGE = 0x1, @@ -29,12 +34,12 @@ enum iwl_regulatory_and_nvm_subcmd_ids { NVM_GET_INFO = 0x2, /** - * @TAS_CONFIG: &struct iwl_tas_config_cmd + * @TAS_CONFIG: &union iwl_tas_config_cmd */ TAS_CONFIG = 0x3, /** - * @SAR_OFFSET_MAPPING_TABLE_CMD: &iwl_sar_offset_mapping_cmd + * @SAR_OFFSET_MAPPING_TABLE_CMD: &struct iwl_sar_offset_mapping_cmd */ SAR_OFFSET_MAPPING_TABLE_CMD = 0x4, @@ -317,7 +322,7 @@ struct iwl_mcc_update_resp_v3 { } __packed; /* LAR_UPDATE_MCC_CMD_RESP_S_VER_3 */ /** - * struct iwl_mcc_update_resp - response to MCC_UPDATE_CMD. + * struct iwl_mcc_update_resp_v4 - response to MCC_UPDATE_CMD. * Contains the new channel control profile map, if changed, and the new MCC * (mobile country code). * The new MCC may be different than what was requested in MCC_UPDATE_CMD. @@ -333,7 +338,7 @@ struct iwl_mcc_update_resp_v3 { * @channels: channel control data map, DWORD for each channel. Only the first * 16bits are used. */ -struct iwl_mcc_update_resp { +struct iwl_mcc_update_resp_v4 { __le32 status; __le16 mcc; __le16 cap; @@ -345,6 +350,37 @@ struct iwl_mcc_update_resp { __le32 channels[]; } __packed; /* LAR_UPDATE_MCC_CMD_RESP_S_VER_4 */ +/** + * struct iwl_mcc_update_resp_v8 - response to MCC_UPDATE_CMD. + * Contains the new channel control profile map, if changed, and the new MCC + * (mobile country code). + * The new MCC may be different than what was requested in MCC_UPDATE_CMD. + * @status: see &enum iwl_mcc_update_status + * @mcc: the new applied MCC + * @padding: padding for 2 bytes. + * @cap: capabilities for all channels which matches the MCC + * @time: time elapsed from the MCC test start (in units of 30 seconds) + * @geo_info: geographic specific profile information + * see &enum iwl_geo_information. + * @source_id: the MCC source, see iwl_mcc_source + * @reserved: for four bytes alignment. + * @n_channels: number of channels in @channels_data. + * @channels: channel control data map, DWORD for each channel. Only the first + * 16bits are used. + */ +struct iwl_mcc_update_resp_v8 { + __le32 status; + __le16 mcc; + u8 padding[2]; + __le32 cap; + __le16 time; + __le16 geo_info; + u8 source_id; + u8 reserved[3]; + __le32 n_channels; + __le32 channels[]; +} __packed; /* LAR_UPDATE_MCC_CMD_RESP_S_VER_8 */ + /** * struct iwl_mcc_chub_notif - chub notifies of mcc change * (MCC_CHUB_UPDATE_CMD = 0xc9) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/offload.h b/drivers/net/wireless/intel/iwlwifi/fw/api/offload.h index a0123f81f5d8a301243c545bfcebb4799cfd6a34..898bf351f6e4d183eb820fc50c2a9f5971712ecb 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/offload.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/offload.h @@ -28,7 +28,8 @@ enum iwl_prot_offload_subcmd_ids { D3_END_NOTIFICATION = 0xFE, /** - * @STORED_BEACON_NTF: &struct iwl_stored_beacon_notif + * @STORED_BEACON_NTF: &struct iwl_stored_beacon_notif_v2 or + * &struct iwl_stored_beacon_notif_v3 */ STORED_BEACON_NTF = 0xFF, }; diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/phy-ctxt.h b/drivers/net/wireless/intel/iwlwifi/fw/api/phy-ctxt.h index 2f7d8558becd221a8d447cd213b6f3a4bf246034..8fe42cff1102ff9d5c2afbfb209f62c4824537a3 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/phy-ctxt.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/phy-ctxt.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ /* - * Copyright (C) 2012-2014, 2018, 2020-2021 Intel Corporation + * Copyright (C) 2012-2014, 2018, 2020-2022 Intel Corporation * Copyright (C) 2013-2015 Intel Mobile Communications GmbH * Copyright (C) 2016-2017 Intel Deutschland GmbH */ @@ -116,7 +116,7 @@ struct iwl_phy_context_cmd_tail { * struct iwl_phy_context_cmd - config of the PHY context * ( PHY_CONTEXT_CMD = 0x8 ) * @id_and_color: ID and color of the relevant Binding - * @action: action to perform, one of FW_CTXT_ACTION_* + * @action: action to perform, see &enum iwl_ctxt_action * @apply_time: 0 means immediate apply and context switch. * other value means apply new params after X usecs * @tx_param_color: ??? @@ -138,7 +138,7 @@ struct iwl_phy_context_cmd_v1 { * struct iwl_phy_context_cmd - config of the PHY context * ( PHY_CONTEXT_CMD = 0x8 ) * @id_and_color: ID and color of the relevant Binding - * @action: action to perform, one of FW_CTXT_ACTION_* + * @action: action to perform, see &enum iwl_ctxt_action * @lmac_id: the lmac id the phy context belongs to * @ci: channel info * @rxchain_info: ??? diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/phy.h b/drivers/net/wireless/intel/iwlwifi/fw/api/phy.h index b1b9c29859c17e02ecd445d5e27929dffcc5c447..5a3f30e5e06d76899aac5a8c634f95257d5daa87 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/phy.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/phy.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ /* - * Copyright (C) 2012-2014, 2019-2021 Intel Corporation + * Copyright (C) 2012-2014, 2019-2022 Intel Corporation * Copyright (C) 2013-2015 Intel Mobile Communications GmbH * Copyright (C) 2016-2017 Intel Deutschland GmbH */ @@ -29,12 +29,16 @@ enum iwl_phy_ops_subcmd_ids { TEMP_REPORTING_THRESHOLDS_CMD = 0x04, /** - * @PER_CHAIN_LIMIT_OFFSET_CMD: &struct iwl_geo_tx_power_profiles_cmd + * @PER_CHAIN_LIMIT_OFFSET_CMD: &struct iwl_geo_tx_power_profiles_cmd_v1, + * &struct iwl_geo_tx_power_profiles_cmd_v2, + * &struct iwl_geo_tx_power_profiles_cmd_v3, + * &struct iwl_geo_tx_power_profiles_cmd_v4 or + * &struct iwl_geo_tx_power_profiles_cmd_v5 */ PER_CHAIN_LIMIT_OFFSET_CMD = 0x05, /** - * @PER_PLATFORM_ANT_GAIN_CMD: &struct iwl_ppag_table_cmd + * @PER_PLATFORM_ANT_GAIN_CMD: &union iwl_ppag_table_cmd */ PER_PLATFORM_ANT_GAIN_CMD = 0x07, diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/power.h b/drivers/net/wireless/intel/iwlwifi/fw/api/power.h index f92cac1da764ac7ba59ea5edfee85f12db853a97..85d89f559f6c858a3d139a77f39a241b145655ff 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/power.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/power.h @@ -537,7 +537,7 @@ union iwl_ppag_table_cmd { struct iwl_sar_offset_mapping_cmd { u8 offset_map[MCC_TO_SAR_OFFSET_TABLE_ROW_SIZE] [MCC_TO_SAR_OFFSET_TABLE_COL_SIZE]; - u16 reserved; + __le16 reserved; } __packed; /*SAR_OFFSET_MAPPING_TABLE_CMD_API_S*/ /** diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/rs.h b/drivers/net/wireless/intel/iwlwifi/fw/api/rs.h index c9a48fc5fac88bdfe14e8bc98364ed2ccd472953..a1a272433b09b453fd91344960c73698891059f5 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/rs.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/rs.h @@ -21,6 +21,7 @@ * @IWL_TLC_MNG_CFG_FLAGS_HE_DCM_NSS_2_MSK: enable HE Dual Carrier Modulation * for BPSK (MCS 0) with 2 spatial * streams + * @IWL_TLC_MNG_CFG_FLAGS_EHT_EXTRA_LTF_MSK: enable support for EHT extra LTF */ enum iwl_tlc_mng_cfg_flags { IWL_TLC_MNG_CFG_FLAGS_STBC_MSK = BIT(0), @@ -28,6 +29,7 @@ enum iwl_tlc_mng_cfg_flags { IWL_TLC_MNG_CFG_FLAGS_HE_STBC_160MHZ_MSK = BIT(2), IWL_TLC_MNG_CFG_FLAGS_HE_DCM_NSS_1_MSK = BIT(3), IWL_TLC_MNG_CFG_FLAGS_HE_DCM_NSS_2_MSK = BIT(4), + IWL_TLC_MNG_CFG_FLAGS_EHT_EXTRA_LTF_MSK = BIT(6), }; /** diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h b/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h index fdd8b01f09e4ca00d0003a67bddd3a849a56e7f8..25e2e23dce3d8a87e7d41e7658e3a1c9cb0534dc 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h @@ -292,7 +292,7 @@ enum iwl_rx_phy_he_data0 { /* TSF overload low dword */ enum iwl_rx_phy_eht_data0 { /* info type: EHT any */ - /* 1 bits reserved */ + IWL_RX_PHY_DATA0_EHT_VALIDATE = BIT(0), IWL_RX_PHY_DATA0_EHT_UPLINK = BIT(1), IWL_RX_PHY_DATA0_EHT_BSS_COLOR_MASK = 0x000000fc, IWL_RX_PHY_DATA0_ETH_SPATIAL_REUSE_MASK = 0x00000f00, @@ -367,8 +367,8 @@ enum iwl_rx_phy_eht_data1 { /* number of EHT-LTF symbols 0 - 1 EHT-LTF, 1 - 2 EHT-LTFs, 2 - 4 EHT-LTFs, * 3 - 6 EHT-LTFs, 4 - 8 EHT-LTFs */ IWL_RX_PHY_DATA1_EHT_SIG_LTF_NUM = 0x000000e0, - IWL_RX_PHY_DATA1_EHT_B0 = 0x00000100, - IWL_RX_PHY_DATA1_EHT_RU_B1_B7_ALLOC = 0x0000fe00, + IWL_RX_PHY_DATA1_EHT_RU_ALLOC_B0 = 0x00000100, + IWL_RX_PHY_DATA1_EHT_RU_ALLOC_B1_B7 = 0x0000fe00, }; /* goes into Metadata DW 7 */ diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/scan.h b/drivers/net/wireless/intel/iwlwifi/fw/api/scan.h index ec96ba053a5c951494432a6adeca669e9934b268..93078f8cc08c03d6b8c9b4fd0e8699845d175568 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/scan.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/scan.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ /* - * Copyright (C) 2012-2014, 2018-2022 Intel Corporation + * Copyright (C) 2012-2014, 2018-2023 Intel Corporation * Copyright (C) 2013-2015 Intel Mobile Communications GmbH * Copyright (C) 2016-2017 Intel Deutschland GmbH */ @@ -727,8 +727,10 @@ enum iwl_umac_scan_general_params_flags2 { * @iter_interval: interval between two scan iterations on one channel. */ struct iwl_scan_channel_cfg_umac { +#define IWL_CHAN_CFG_FLAGS_BAND_POS 30 __le32 flags; - /* Both versions are of the same size, so use a union without adjusting + + /* All versions are of the same size, so use a union without adjusting * the command size later */ union { @@ -746,6 +748,12 @@ struct iwl_scan_channel_cfg_umac { * SCAN_CHANNEL_CONFIG_API_S_VER_3 * SCAN_CHANNEL_CONFIG_API_S_VER_4 */ + struct { + u8 channel_num; + u8 psd_20; + u8 iter_count; + u8 iter_interval; + } v5; /* SCAN_CHANNEL_CONFIG_API_S_VER_5 */ }; } __packed; @@ -982,7 +990,7 @@ struct iwl_scan_channel_params_v4 { SCAN_CHANNEL_PARAMS_API_S_VER_5 */ /** - * struct iwl_scan_channel_params_v6 + * struct iwl_scan_channel_params_v7 * @flags: channel flags &enum iwl_scan_channel_flags * @count: num of channels in scan request * @n_aps_override: override the number of APs the FW uses to calculate dwell @@ -992,7 +1000,7 @@ struct iwl_scan_channel_params_v4 { * @channel_config: array of explicit channel configurations * for 2.4Ghz and 5.2Ghz bands */ -struct iwl_scan_channel_params_v6 { +struct iwl_scan_channel_params_v7 { u8 flags; u8 count; u8 n_aps_override[2]; @@ -1003,7 +1011,8 @@ struct iwl_scan_channel_params_v6 { * struct iwl_scan_general_params_v11 * @flags: &enum iwl_umac_scan_general_flags_v2 * @reserved: reserved for future - * @scan_start_mac_id: report the scan start TSF time according to this mac TSF + * @scan_start_mac_or_link_id: report the scan start TSF time according to this + * mac (up to verion 11) or link (starting with version 12) TSF * @active_dwell: dwell time for active scan per LMAC * @adwell_default_2g: adaptive dwell default number of APs * for 2.4GHz channel @@ -1026,7 +1035,7 @@ struct iwl_scan_channel_params_v6 { struct iwl_scan_general_params_v11 { __le16 flags; u8 reserved; - u8 scan_start_mac_id; + u8 scan_start_mac_or_link_id; u8 active_dwell[SCAN_TWO_LMACS]; u8 adwell_default_2g; u8 adwell_default_5g; @@ -1038,7 +1047,7 @@ struct iwl_scan_general_params_v11 { __le32 scan_priority; u8 passive_dwell[SCAN_TWO_LMACS]; u8 num_of_fragments[SCAN_TWO_LMACS]; -} __packed; /* SCAN_GENERAL_PARAMS_API_S_VER_11 and *_VER_10 */ +} __packed; /* SCAN_GENERAL_PARAMS_API_S_VER_12, *_VER_11 and *_VER_10 */ /** * struct iwl_scan_periodic_parms_v1 @@ -1067,18 +1076,18 @@ struct iwl_scan_req_params_v12 { } __packed; /* SCAN_REQUEST_PARAMS_API_S_VER_12 */ /** - * struct iwl_scan_req_params_v15 + * struct iwl_scan_req_params_v16 * @general_params: &struct iwl_scan_general_params_v11 - * @channel_params: &struct iwl_scan_channel_params_v6 + * @channel_params: &struct iwl_scan_channel_params_v7 * @periodic_params: &struct iwl_scan_periodic_parms_v1 * @probe_params: &struct iwl_scan_probe_params_v4 */ -struct iwl_scan_req_params_v15 { +struct iwl_scan_req_params_v17 { struct iwl_scan_general_params_v11 general_params; - struct iwl_scan_channel_params_v6 channel_params; + struct iwl_scan_channel_params_v7 channel_params; struct iwl_scan_periodic_parms_v1 periodic_params; struct iwl_scan_probe_params_v4 probe_params; -} __packed; /* SCAN_REQUEST_PARAMS_API_S_VER_15 and *_VER_14 */ +} __packed; /* SCAN_REQUEST_PARAMS_API_S_VER_17 - 14 */ /** * struct iwl_scan_req_umac_v12 @@ -1093,16 +1102,16 @@ struct iwl_scan_req_umac_v12 { } __packed; /* SCAN_REQUEST_CMD_UMAC_API_S_VER_12 */ /** - * struct iwl_scan_req_umac_v15 + * struct iwl_scan_req_umac_v16 * @uid: scan id, &enum iwl_umac_scan_uid_offsets * @ooc_priority: out of channel priority - &enum iwl_scan_priority * @scan_params: scan parameters */ -struct iwl_scan_req_umac_v15 { +struct iwl_scan_req_umac_v17 { __le32 uid; __le32 ooc_priority; - struct iwl_scan_req_params_v15 scan_params; -} __packed; /* SCAN_REQUEST_CMD_UMAC_API_S_VER_15 and *_VER_14 */ + struct iwl_scan_req_params_v17 scan_params; +} __packed; /* SCAN_REQUEST_CMD_UMAC_API_S_VER_17 - 14 */ /** * struct iwl_umac_scan_abort diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/time-event.h b/drivers/net/wireless/intel/iwlwifi/fw/api/time-event.h index 904cd78a9fa03d314e294d40d20ff0ff8a9dbaca..7cc706731d706a321376b741ad466dd6e6d10c70 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/time-event.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/time-event.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ /* - * Copyright (C) 2012-2014, 2018-2020 Intel Corporation + * Copyright (C) 2012-2014, 2018-2020, 2022 Intel Corporation * Copyright (C) 2013-2015 Intel Mobile Communications GmbH * Copyright (C) 2016-2017 Intel Deutschland GmbH */ @@ -292,7 +292,7 @@ struct iwl_hs20_roc_req_tail { * ( HOT_SPOT_CMD 0x53 ) * * @id_and_color: ID and color of the MAC - * @action: action to perform, one of FW_CTXT_ACTION_* + * @action: action to perform, see &enum iwl_ctxt_action * @event_unique_id: If the action FW_CTXT_ACTION_REMOVE then the * event_unique_id should be the id of the time event assigned by ucode. * Otherwise ignore the event_unique_id. @@ -377,7 +377,8 @@ enum iwl_mvm_session_prot_conf_id { * struct iwl_mvm_session_prot_cmd - configure a session protection * @id_and_color: the id and color of the mac for which this session protection * is sent - * @action: can be either FW_CTXT_ACTION_ADD or FW_CTXT_ACTION_REMOVE + * @action: can be either FW_CTXT_ACTION_ADD or FW_CTXT_ACTION_REMOVE, + * see &enum iwl_ctxt_action * @conf_id: see &enum iwl_mvm_session_prot_conf_id * @duration_tu: the duration of the whole protection in TUs. * @repetition_count: not used diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/tx.h b/drivers/net/wireless/intel/iwlwifi/fw/api/tx.h index 97edf5477ba7d8d5aa5dbef594e21d083f09085c..842360b1e995cd05148fab4ebbf6d99a726417b8 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/tx.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/tx.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ /* - * Copyright (C) 2012-2014, 2018-2022 Intel Corporation + * Copyright (C) 2012-2014, 2018-2023 Intel Corporation * Copyright (C) 2016-2017 Intel Deutschland GmbH */ #ifndef __iwl_fw_api_tx_h__ @@ -177,17 +177,6 @@ enum iwl_tx_offload_assist_flags_pos { #define IWL_TX_CMD_OFFLD_MH_MASK 0x1f #define IWL_TX_CMD_OFFLD_IP_HDR_MASK 0x3f -enum iwl_tx_offload_assist_bz { - IWL_TX_CMD_OFFLD_BZ_RESULT_OFFS = 0x000003ff, - IWL_TX_CMD_OFFLD_BZ_START_OFFS = 0x001ff800, - IWL_TX_CMD_OFFLD_BZ_MH_LEN = 0x07c00000, - IWL_TX_CMD_OFFLD_BZ_MH_PAD = 0x08000000, - IWL_TX_CMD_OFFLD_BZ_AMSDU = 0x10000000, - IWL_TX_CMD_OFFLD_BZ_ZERO2ONES = 0x20000000, - IWL_TX_CMD_OFFLD_BZ_ENABLE_CSUM = 0x40000000, - IWL_TX_CMD_OFFLD_BZ_PARTIAL_CSUM = 0x80000000, -}; - /* TODO: complete documentation for try_cnt and btkill_cnt */ /** * struct iwl_tx_cmd - TX command struct to FW diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index 55219974b92bf73c6ab70aa3e53ca4408257753a..3ab6a68f1e9f94f2f0a4455581758fe8cfb8e532 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* - * Copyright (C) 2005-2014, 2018-2021 Intel Corporation + * Copyright (C) 2005-2014, 2018-2023 Intel Corporation * Copyright (C) 2013-2015 Intel Mobile Communications GmbH * Copyright (C) 2015-2017 Intel Deutschland GmbH */ @@ -1038,7 +1038,7 @@ iwl_dump_ini_prph_mac_iter(struct iwl_fw_runtime *fwrt, range->range_data_size = reg->dev_addr.size; for (i = 0; i < le32_to_cpu(reg->dev_addr.size); i += 4) { prph_val = iwl_read_prph(fwrt->trans, addr + i); - if ((prph_val & ~0xf) == 0xa5a5a5a0) + if (iwl_trans_is_hw_error_value(prph_val)) return -EBUSY; *val++ = cpu_to_le32(prph_val); } @@ -1562,7 +1562,7 @@ iwl_dump_ini_dbgi_sram_iter(struct iwl_fw_runtime *fwrt, prph_data = iwl_read_prph_no_grab(fwrt->trans, (i % 2) ? DBGI_SRAM_TARGET_ACCESS_RDATA_MSB : DBGI_SRAM_TARGET_ACCESS_RDATA_LSB); - if ((prph_data & ~0xf) == 0xa5a5a5a0) { + if (iwl_trans_is_hw_error_value(prph_data)) { iwl_trans_release_nic_access(fwrt->trans); return -EBUSY; } @@ -2034,7 +2034,6 @@ static u32 iwl_dump_ini_imr_get_size(struct iwl_fw_runtime *fwrt, struct iwl_dump_ini_region_data *reg_data) { - u32 size = 0; u32 ranges = 0; u32 imr_enable = fwrt->trans->dbg.imr_data.imr_enable; u32 imr_size = fwrt->trans->dbg.imr_data.imr_size; @@ -2044,17 +2043,16 @@ iwl_dump_ini_imr_get_size(struct iwl_fw_runtime *fwrt, IWL_DEBUG_INFO(fwrt, "WRT: Invalid imr data enable: %d, imr_size: %d, sram_size: %d\n", imr_enable, imr_size, sram_size); - return size; + return 0; } - size = imr_size; ranges = iwl_dump_ini_imr_ranges(fwrt, reg_data); - if (!size && !ranges) { - IWL_ERR(fwrt, "WRT: imr_size :=%d, ranges :=%d\n", size, ranges); + if (!ranges) { + IWL_ERR(fwrt, "WRT: ranges :=%d\n", ranges); return 0; } - size += sizeof(struct iwl_fw_ini_error_dump) + + imr_size += sizeof(struct iwl_fw_ini_error_dump) + ranges * sizeof(struct iwl_fw_ini_error_dump_range); - return size; + return imr_size; } /** @@ -3156,6 +3154,51 @@ static int iwl_fw_dbg_restart_recording(struct iwl_trans *trans, return 0; } +int iwl_fw_send_timestamp_marker_cmd(struct iwl_fw_runtime *fwrt) +{ + struct iwl_mvm_marker marker = { + .dw_len = sizeof(struct iwl_mvm_marker) / 4, + .marker_id = MARKER_ID_SYNC_CLOCK, + }; + struct iwl_host_cmd hcmd = { + .flags = CMD_ASYNC, + .id = WIDE_ID(LONG_GROUP, MARKER_CMD), + .dataflags = {}, + }; + struct iwl_mvm_marker_rsp *resp; + int cmd_ver = iwl_fw_lookup_cmd_ver(fwrt->fw, + WIDE_ID(LONG_GROUP, MARKER_CMD), + IWL_FW_CMD_VER_UNKNOWN); + int ret; + + if (cmd_ver == 1) { + /* the real timestamp is taken from the ftrace clock + * this is for finding the match between fw and kernel logs + */ + marker.timestamp = cpu_to_le64(fwrt->timestamp.seq++); + } else if (cmd_ver == 2) { + marker.timestamp = cpu_to_le64(ktime_get_boottime_ns()); + } else { + IWL_DEBUG_INFO(fwrt, + "Invalid version of Marker CMD. Ver = %d\n", + cmd_ver); + return -EINVAL; + } + + hcmd.data[0] = ▮ + hcmd.len[0] = sizeof(marker); + + ret = iwl_trans_send_cmd(fwrt->trans, &hcmd); + + if (cmd_ver > 1 && hcmd.resp_pkt) { + resp = (void *)hcmd.resp_pkt->data; + IWL_DEBUG_INFO(fwrt, "FW GP2 time: %u\n", + le32_to_cpu(resp->gp2)); + } + + return ret; +} + void iwl_fw_dbg_stop_restart_recording(struct iwl_fw_runtime *fwrt, struct iwl_fw_dbg_params *params, bool stop) @@ -3166,12 +3209,15 @@ void iwl_fw_dbg_stop_restart_recording(struct iwl_fw_runtime *fwrt, return; if (fw_has_capa(&fwrt->fw->ucode_capa, - IWL_UCODE_TLV_CAPA_DBG_SUSPEND_RESUME_CMD_SUPP)) + IWL_UCODE_TLV_CAPA_DBG_SUSPEND_RESUME_CMD_SUPP)) { + if (stop) + iwl_fw_send_timestamp_marker_cmd(fwrt); ret = iwl_fw_dbg_suspend_resume_hcmd(fwrt->trans, stop); - else if (stop) + } else if (stop) { iwl_fw_dbg_stop_recording(fwrt->trans, params); - else + } else { ret = iwl_fw_dbg_restart_recording(fwrt->trans, params); + } #ifdef CONFIG_IWLWIFI_DEBUGFS if (!ret) { if (stop) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.h b/drivers/net/wireless/intel/iwlwifi/fw/dbg.h index be7806407de833a82a6bdbd9638a24a52d778982..4227fbd2b97718bce7789f1a26ca7d4ea656b5ee 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ /* - * Copyright (C) 2005-2014, 2018-2019, 2021-2022 Intel Corporation + * Copyright (C) 2005-2014, 2018-2019, 2021-2023 Intel Corporation * Copyright (C) 2013-2015 Intel Mobile Communications GmbH * Copyright (C) 2015-2017 Intel Deutschland GmbH */ @@ -227,6 +227,8 @@ static inline void iwl_fw_flush_dumps(struct iwl_fw_runtime *fwrt) flush_delayed_work(&fwrt->dump.wks[i].wk); } +int iwl_fw_send_timestamp_marker_cmd(struct iwl_fw_runtime *fwrt); + #ifdef CONFIG_IWLWIFI_DEBUGFS static inline void iwl_fw_cancel_timestamp(struct iwl_fw_runtime *fwrt) { @@ -327,4 +329,18 @@ void iwl_fwrt_dump_error_logs(struct iwl_fw_runtime *fwrt); void iwl_send_dbg_dump_complete_cmd(struct iwl_fw_runtime *fwrt, u32 timepoint, u32 timepoint_data); + +#define IWL_FW_CHECK_FAILED(_obj, _fmt, ...) \ + IWL_ERR_LIMIT(_obj, _fmt, __VA_ARGS__) + +#define IWL_FW_CHECK(_obj, _cond, _fmt, ...) \ + ({ \ + bool __cond = (_cond); \ + \ + if (unlikely(__cond)) \ + IWL_FW_CHECK_FAILED(_obj, _fmt, __VA_ARGS__); \ + \ + unlikely(__cond); \ + }) + #endif /* __iwl_fw_dbg_h__ */ diff --git a/drivers/net/wireless/intel/iwlwifi/fw/debugfs.c b/drivers/net/wireless/intel/iwlwifi/fw/debugfs.c index 607e07ed2477cd5d46f011ecacb24161f88d23de..3cdbc6ac7ae5d62282a4f071ae204df413d92e5e 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/debugfs.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/debugfs.c @@ -123,28 +123,6 @@ static const struct file_operations iwl_dbgfs_##name##_ops = { \ #define FWRT_DEBUGFS_ADD_FILE(name, parent, mode) \ FWRT_DEBUGFS_ADD_FILE_ALIAS(#name, name, parent, mode) -static int iwl_fw_send_timestamp_marker_cmd(struct iwl_fw_runtime *fwrt) -{ - struct iwl_mvm_marker marker = { - .dw_len = sizeof(struct iwl_mvm_marker) / 4, - .marker_id = MARKER_ID_SYNC_CLOCK, - - /* the real timestamp is taken from the ftrace clock - * this is for finding the match between fw and kernel logs - */ - .timestamp = cpu_to_le64(fwrt->timestamp.seq++), - }; - - struct iwl_host_cmd hcmd = { - .id = MARKER_CMD, - .flags = CMD_ASYNC, - .data[0] = &marker, - .len[0] = sizeof(marker), - }; - - return iwl_trans_send_cmd(fwrt->trans, &hcmd); -} - static int iwl_dbgfs_enabled_severities_write(struct iwl_fw_runtime *fwrt, char *buf, size_t count) { @@ -354,9 +332,18 @@ static int iwl_dbgfs_fw_info_seq_show(struct seq_file *seq, void *v) const struct iwl_fw *fw = priv->fwrt->fw; const struct iwl_fw_cmd_version *ver; u32 cmd_id; - - if (!state->pos) + int has_capa; + + if (!state->pos) { + seq_puts(seq, "fw_capa:\n"); + has_capa = fw_has_capa(&fw->ucode_capa, + IWL_UCODE_TLV_CAPA_PPAG_CHINA_BIOS_SUPPORT) ? 1 : 0; + seq_printf(seq, + " %d: %d\n", + IWL_UCODE_TLV_CAPA_PPAG_CHINA_BIOS_SUPPORT, + has_capa); seq_puts(seq, "fw_api_ver:\n"); + } ver = &fw->ucode_capa.cmd_versions[state->pos]; diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dump.c b/drivers/net/wireless/intel/iwlwifi/fw/dump.c index f86f7b4baa18194212cc9f5f665f6430e918b0a7..5876f917e5361b11d89c7c6d2b5c7106babf0173 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dump.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dump.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* - * Copyright (C) 2012-2014, 2018-2022 Intel Corporation + * Copyright (C) 2012-2014, 2018-2023 Intel Corporation * Copyright (C) 2013-2014 Intel Mobile Communications GmbH * Copyright (C) 2015-2017 Intel Deutschland GmbH */ @@ -194,7 +194,7 @@ static void iwl_fwrt_dump_lmac_error_log(struct iwl_fw_runtime *fwrt, u8 lmac_nu /* check if there is a HW error */ val = iwl_trans_read_mem32(trans, base); - if (((val & ~0xf) == 0xa5a5a5a0) || ((val & ~0xf) == 0x5a5a5a50)) { + if (iwl_trans_is_hw_error_value(val)) { int err; IWL_ERR(trans, "HW error, resetting before reading\n"); @@ -467,6 +467,10 @@ static void iwl_fwrt_dump_fseq_regs(struct iwl_fw_runtime *fwrt) FSEQ_REG(CNVR_AUX_MISC_CHIP), FSEQ_REG(CNVR_SCU_SD_REGS_SD_REG_DIG_DCDC_VTRIM), FSEQ_REG(CNVR_SCU_SD_REGS_SD_REG_ACTIVE_VDIG_MIRROR), + FSEQ_REG(FSEQ_PREV_CNVIO_INIT_VERSION), + FSEQ_REG(FSEQ_WIFI_FSEQ_VERSION), + FSEQ_REG(FSEQ_BT_FSEQ_VERSION), + FSEQ_REG(FSEQ_CLASS_TP_VERSION), }; if (!iwl_trans_grab_nic_access(trans)) @@ -507,11 +511,16 @@ void iwl_fwrt_dump_error_logs(struct iwl_fw_runtime *fwrt) iwl_fwrt_dump_fseq_regs(fwrt); if (fwrt->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_22000) { pc_data = fwrt->trans->dbg.pc_data; + + if (!iwl_trans_grab_nic_access(fwrt->trans)) + return; for (count = 0; count < fwrt->trans->dbg.num_pc; count++, pc_data++) IWL_ERR(fwrt, "%s: 0x%x\n", pc_data->pc_name, - pc_data->pc_address); + iwl_read_prph_no_grab(fwrt->trans, + pc_data->pc_address)); + iwl_trans_release_nic_access(fwrt->trans); } if (fwrt->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) { diff --git a/drivers/net/wireless/intel/iwlwifi/fw/file.h b/drivers/net/wireless/intel/iwlwifi/fw/file.h index cddf09d6be1c5c61db4fc7446277c74a19d50263..b36e9613a52c8cd65177da90facf5b3410c239ba 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/file.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/file.h @@ -323,6 +323,7 @@ typedef unsigned int __bitwise iwl_ucode_tlv_capa_t; * is supported. * @IWL_UCODE_TLV_CAPA_BT_COEX_RRC: supports BT Coex RRC * @IWL_UCODE_TLV_CAPA_GSCAN_SUPPORT: supports gscan (no longer used) + * @IWL_UCODE_TLV_CAPA_FRAGMENTED_PNVM_IMG: supports fragmented PNVM image * @IWL_UCODE_TLV_CAPA_SOC_LATENCY_SUPPORT: the firmware supports setting * stabilization latency for SoCs. * @IWL_UCODE_TLV_CAPA_STA_PM_NOTIF: firmware will send STA PM notification @@ -398,6 +399,7 @@ enum iwl_ucode_tlv_capa { IWL_UCODE_TLV_CAPA_GSCAN_SUPPORT = (__force iwl_ucode_tlv_capa_t)31, /* set 1 */ + IWL_UCODE_TLV_CAPA_FRAGMENTED_PNVM_IMG = (__force iwl_ucode_tlv_capa_t)32, IWL_UCODE_TLV_CAPA_SOC_LATENCY_SUPPORT = (__force iwl_ucode_tlv_capa_t)37, IWL_UCODE_TLV_CAPA_STA_PM_NOTIF = (__force iwl_ucode_tlv_capa_t)38, IWL_UCODE_TLV_CAPA_BINDING_CDB_SUPPORT = (__force iwl_ucode_tlv_capa_t)39, @@ -462,6 +464,10 @@ enum iwl_ucode_tlv_capa { IWL_UCODE_TLV_CAPA_BIGTK_TX_SUPPORT = (__force iwl_ucode_tlv_capa_t)109, IWL_UCODE_TLV_CAPA_MLD_API_SUPPORT = (__force iwl_ucode_tlv_capa_t)110, IWL_UCODE_TLV_CAPA_SCAN_DONT_TOGGLE_ANT = (__force iwl_ucode_tlv_capa_t)111, + IWL_UCODE_TLV_CAPA_PPAG_CHINA_BIOS_SUPPORT = (__force iwl_ucode_tlv_capa_t)112, + IWL_UCODE_TLV_CAPA_OFFLOAD_BTM_SUPPORT = (__force iwl_ucode_tlv_capa_t)113, + IWL_UCODE_TLV_CAPA_STA_EXP_MFP_SUPPORT = (__force iwl_ucode_tlv_capa_t)114, + IWL_UCODE_TLV_CAPA_SNIFF_VALIDATE_SUPPORT = (__force iwl_ucode_tlv_capa_t)116, #ifdef __CHECKER__ /* sparse says it cannot increment the previous enum member */ diff --git a/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c b/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c index c6f2672fdc73765a4ad7ad93f48336e165ce719c..650e4bde9c17b999411b013f8bfebc4df78de80b 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* - * Copyright(c) 2020-2022 Intel Corporation + * Copyright(c) 2020-2023 Intel Corporation */ #include "iwl-drv.h" @@ -31,18 +31,18 @@ static bool iwl_pnvm_complete_fn(struct iwl_notif_wait_data *notif_wait, } static int iwl_pnvm_handle_section(struct iwl_trans *trans, const u8 *data, - size_t len) + size_t len, + struct iwl_pnvm_image *pnvm_data) { const struct iwl_ucode_tlv *tlv; u32 sha1 = 0; u16 mac_type = 0, rf_id = 0; - u8 *pnvm_data = NULL, *tmp; bool hw_match = false; - u32 size = 0; - int ret; IWL_DEBUG_FW(trans, "Handling PNVM section\n"); + memset(pnvm_data, 0, sizeof(*pnvm_data)); + while (len >= sizeof(*tlv)) { u32 tlv_len, tlv_type; @@ -55,8 +55,7 @@ static int iwl_pnvm_handle_section(struct iwl_trans *trans, const u8 *data, if (len < tlv_len) { IWL_ERR(trans, "invalid TLV len: %zd/%u\n", len, tlv_len); - ret = -EINVAL; - goto out; + return -EINVAL; } data += sizeof(*tlv); @@ -75,6 +74,7 @@ static int iwl_pnvm_handle_section(struct iwl_trans *trans, const u8 *data, IWL_DEBUG_FW(trans, "Got IWL_UCODE_TLV_PNVM_VERSION %0x\n", sha1); + pnvm_data->version = sha1; break; case IWL_UCODE_TLV_HW_TYPE: if (tlv_len < 2 * sizeof(__le16)) { @@ -112,26 +112,26 @@ static int iwl_pnvm_handle_section(struct iwl_trans *trans, const u8 *data, break; } - IWL_DEBUG_FW(trans, "Adding data (size %d)\n", - data_len); - - tmp = krealloc(pnvm_data, size + data_len, GFP_KERNEL); - if (!tmp) { + if (pnvm_data->n_chunks == IPC_DRAM_MAP_ENTRY_NUM_MAX) { IWL_DEBUG_FW(trans, - "Couldn't allocate (more) pnvm_data\n"); - - ret = -ENOMEM; - goto out; + "too many payloads to allocate in DRAM.\n"); + return -EINVAL; } - pnvm_data = tmp; - - memcpy(pnvm_data + size, section->data, data_len); + IWL_DEBUG_FW(trans, "Adding data (size %d)\n", + data_len); - size += data_len; + pnvm_data->chunks[pnvm_data->n_chunks].data = section->data; + pnvm_data->chunks[pnvm_data->n_chunks].len = data_len; + pnvm_data->n_chunks++; break; } + case IWL_UCODE_TLV_MEM_DESC: + if (iwl_uefi_handle_tlv_mem_desc(trans, data, tlv_len, + pnvm_data)) + return -EINVAL; + break; case IWL_UCODE_TLV_PNVM_SKU: IWL_DEBUG_FW(trans, "New PNVM section started, stop parsing.\n"); @@ -152,26 +152,20 @@ static int iwl_pnvm_handle_section(struct iwl_trans *trans, const u8 *data, "HW mismatch, skipping PNVM section (need mac_type 0x%x rf_id 0x%x)\n", CSR_HW_REV_TYPE(trans->hw_rev), CSR_HW_RFID_TYPE(trans->hw_rf_id)); - ret = -ENOENT; - goto out; + return -ENOENT; } - if (!size) { + if (!pnvm_data->n_chunks) { IWL_DEBUG_FW(trans, "Empty PNVM, skipping.\n"); - ret = -ENOENT; - goto out; + return -ENOENT; } - IWL_INFO(trans, "loaded PNVM version %08x\n", sha1); - - ret = iwl_trans_set_pnvm(trans, pnvm_data, size); -out: - kfree(pnvm_data); - return ret; + return 0; } static int iwl_pnvm_parse(struct iwl_trans *trans, const u8 *data, - size_t len) + size_t len, + struct iwl_pnvm_image *pnvm_data) { const struct iwl_ucode_tlv *tlv; @@ -212,7 +206,8 @@ static int iwl_pnvm_parse(struct iwl_trans *trans, const u8 *data, trans->sku_id[2] == le32_to_cpu(sku_id->data[2])) { int ret; - ret = iwl_pnvm_handle_section(trans, data, len); + ret = iwl_pnvm_handle_section(trans, data, len, + pnvm_data); if (!ret) return 0; } else { @@ -255,89 +250,136 @@ static int iwl_pnvm_get_from_fs(struct iwl_trans *trans, u8 **data, size_t *len) return 0; } -int iwl_pnvm_load(struct iwl_trans *trans, - struct iwl_notif_wait_data *notif_wait) +static u8 *iwl_get_pnvm_image(struct iwl_trans *trans_p, size_t *len) { - u8 *data; - size_t len; struct pnvm_sku_package *package; - struct iwl_notification_wait pnvm_wait; - static const u16 ntf_cmds[] = { WIDE_ID(REGULATORY_AND_NVM_GROUP, - PNVM_INIT_COMPLETE_NTFY) }; - int ret; - - /* if the SKU_ID is empty, there's nothing to do */ - if (!trans->sku_id[0] && !trans->sku_id[1] && !trans->sku_id[2]) - return 0; - - /* - * If we already loaded (or tried to load) it before, we just - * need to set it again. - */ - if (trans->pnvm_loaded) { - ret = iwl_trans_set_pnvm(trans, NULL, 0); - if (ret) - return ret; - goto skip_parse; - } + u8 *image = NULL; /* First attempt to get the PNVM from BIOS */ - package = iwl_uefi_get_pnvm(trans, &len); + package = iwl_uefi_get_pnvm(trans_p, len); if (!IS_ERR_OR_NULL(package)) { - if (len >= sizeof(*package)) { + if (*len >= sizeof(*package)) { /* we need only the data */ - len -= sizeof(*package); - data = kmemdup(package->data, len, GFP_KERNEL); - } else { - data = NULL; + *len -= sizeof(*package); + image = kmemdup(package->data, *len, GFP_KERNEL); } - /* free package regardless of whether kmemdup succeeded */ kfree(package); - - if (data) - goto parse; + if (image) + return image; } /* If it's not available, try from the filesystem */ - ret = iwl_pnvm_get_from_fs(trans, &data, &len); + if (iwl_pnvm_get_from_fs(trans_p, &image, len)) + return NULL; + return image; +} + +static void iwl_pnvm_load_pnvm_to_trans(struct iwl_trans *trans, + const struct iwl_ucode_capabilities *capa) +{ + struct iwl_pnvm_image *pnvm_data = NULL; + u8 *data = NULL; + size_t length; + int ret; + + /* failed to get/parse the image in the past, no use trying again */ + if (trans->fail_to_parse_pnvm_image) + return; + + if (trans->pnvm_loaded) + goto set; + + data = iwl_get_pnvm_image(trans, &length); + if (!data) { + trans->fail_to_parse_pnvm_image = true; + return; + } + + pnvm_data = kzalloc(sizeof(*pnvm_data), GFP_KERNEL); + if (!pnvm_data) + goto free; + + ret = iwl_pnvm_parse(trans, data, length, pnvm_data); if (ret) { - /* - * Pretend we've loaded it - at least we've tried and - * couldn't load it at all, so there's no point in - * trying again over and over. - */ - trans->pnvm_loaded = true; - - goto skip_parse; + trans->fail_to_parse_pnvm_image = true; + goto free; } -parse: - iwl_pnvm_parse(trans, data, len); + ret = iwl_trans_load_pnvm(trans, pnvm_data, capa); + if (ret) + goto free; + IWL_INFO(trans, "loaded PNVM version %08x\n", pnvm_data->version); +set: + iwl_trans_set_pnvm(trans, capa); +free: kfree(data); + kfree(pnvm_data); +} -skip_parse: - /* now try to get the reduce power table, if not loaded yet */ - if (!trans->reduce_power_loaded) { - data = iwl_uefi_get_reduced_power(trans, &len); - if (IS_ERR_OR_NULL(data)) { - /* - * Pretend we've loaded it - at least we've tried and - * couldn't load it at all, so there's no point in - * trying again over and over. - */ - trans->reduce_power_loaded = true; - } else { - ret = iwl_trans_set_reduce_power(trans, data, len); - if (ret) - IWL_DEBUG_FW(trans, - "Failed to set reduce power table %d\n", - ret); - kfree(data); - } +static void +iwl_pnvm_load_reduce_power_to_trans(struct iwl_trans *trans, + const struct iwl_ucode_capabilities *capa) +{ + struct iwl_pnvm_image *pnvm_data = NULL; + u8 *data = NULL; + size_t length; + int ret; + + if (trans->failed_to_load_reduce_power_image) + return; + + if (trans->reduce_power_loaded) + goto set; + + data = iwl_uefi_get_reduced_power(trans, &length); + if (IS_ERR(data)) { + trans->failed_to_load_reduce_power_image = true; + return; } + pnvm_data = kzalloc(sizeof(*pnvm_data), GFP_KERNEL); + if (!pnvm_data) + goto free; + + ret = iwl_uefi_reduce_power_parse(trans, data, length, pnvm_data); + if (ret) { + trans->failed_to_load_reduce_power_image = true; + goto free; + } + + ret = iwl_trans_load_reduce_power(trans, pnvm_data, capa); + if (ret) { + IWL_DEBUG_FW(trans, + "Failed to load reduce power table %d\n", + ret); + trans->failed_to_load_reduce_power_image = true; + goto free; + } + +set: + iwl_trans_set_reduce_power(trans, capa); +free: + kfree(data); + kfree(pnvm_data); +} + +int iwl_pnvm_load(struct iwl_trans *trans, + struct iwl_notif_wait_data *notif_wait, + const struct iwl_ucode_capabilities *capa) +{ + struct iwl_notification_wait pnvm_wait; + static const u16 ntf_cmds[] = { WIDE_ID(REGULATORY_AND_NVM_GROUP, + PNVM_INIT_COMPLETE_NTFY) }; + + /* if the SKU_ID is empty, there's nothing to do */ + if (!trans->sku_id[0] && !trans->sku_id[1] && !trans->sku_id[2]) + return 0; + + iwl_pnvm_load_pnvm_to_trans(trans, capa); + iwl_pnvm_load_reduce_power_to_trans(trans, capa); + iwl_init_notification_wait(notif_wait, &pnvm_wait, ntf_cmds, ARRAY_SIZE(ntf_cmds), iwl_pnvm_complete_fn, trans); diff --git a/drivers/net/wireless/intel/iwlwifi/fw/pnvm.h b/drivers/net/wireless/intel/iwlwifi/fw/pnvm.h index 203c367dd4deec56b9acc1b9a5e2b1aae948390c..1bac3466154c2ef6ecc326ee904717657192df92 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/pnvm.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/pnvm.h @@ -1,13 +1,11 @@ /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ -/****************************************************************************** - * - * Copyright(c) 2020-2021 Intel Corporation - * - *****************************************************************************/ - +/* + * Copyright(c) 2020-2023 Intel Corporation + */ #ifndef __IWL_PNVM_H__ #define __IWL_PNVM_H__ +#include "iwl-drv.h" #include "fw/notif-wait.h" #define MVM_UCODE_PNVM_TIMEOUT (HZ / 4) @@ -15,24 +13,17 @@ #define MAX_PNVM_NAME 64 int iwl_pnvm_load(struct iwl_trans *trans, - struct iwl_notif_wait_data *notif_wait); + struct iwl_notif_wait_data *notif_wait, + const struct iwl_ucode_capabilities *capa); static inline void iwl_pnvm_get_fs_name(struct iwl_trans *trans, u8 *pnvm_name, size_t max_len) { - int pre_len; - - /* - * The prefix unfortunately includes a hyphen at the end, so - * don't add the dot here... - */ - snprintf(pnvm_name, max_len, "%spnvm", trans->cfg->fw_name_pre); + char _fw_name_pre[FW_NAME_PRE_BUFSIZE]; - /* ...but replace the hyphen with the dot here. */ - pre_len = strlen(trans->cfg->fw_name_pre); - if (pre_len < max_len && pre_len > 0) - pnvm_name[pre_len - 1] = '.'; + snprintf(pnvm_name, max_len, "%s.pnvm", + iwl_drv_get_fwname_pre(trans, _fw_name_pre)); } #endif /* __IWL_PNVM_H__ */ diff --git a/drivers/net/wireless/intel/iwlwifi/fw/runtime.h b/drivers/net/wireless/intel/iwlwifi/fw/runtime.h index df689a9b7e2cb1f704097150bb9ff307cb7e856d..702586945533eefe9b1ac880945f30904208a0ce 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/runtime.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/runtime.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ /* * Copyright (C) 2017 Intel Deutschland GmbH - * Copyright (C) 2018-2022 Intel Corporation + * Copyright (C) 2018-2023 Intel Corporation */ #ifndef __iwl_fw_runtime_h__ #define __iwl_fw_runtime_h__ @@ -146,12 +146,14 @@ struct iwl_fw_runtime { u32 umac_minor; } fw_ver; } dump; -#ifdef CONFIG_IWLWIFI_DEBUGFS struct { +#ifdef CONFIG_IWLWIFI_DEBUGFS struct delayed_work wk; u32 delay; +#endif u64 seq; } timestamp; +#ifdef CONFIG_IWLWIFI_DEBUGFS bool tpc_enabled; #endif /* CONFIG_IWLWIFI_DEBUGFS */ #ifdef CONFIG_ACPI diff --git a/drivers/net/wireless/intel/iwlwifi/fw/uefi.c b/drivers/net/wireless/intel/iwlwifi/fw/uefi.c index 01afea33c38cc04446900bdddab868331f041e27..9877988db0d277c5b418fc38c91473473e70b43e 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/uefi.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/uefi.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* - * Copyright(c) 2021-2022 Intel Corporation + * Copyright(c) 2021-2023 Intel Corporation */ #include "iwl-drv.h" @@ -17,52 +17,109 @@ 0xb2, 0xec, 0xf5, 0xa3, \ 0x59, 0x4f, 0x4a, 0xea) -void *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len) +struct iwl_uefi_pnvm_mem_desc { + __le32 addr; + __le32 size; + const u8 data[]; +} __packed; + +static void *iwl_uefi_get_variable(efi_char16_t *name, efi_guid_t *guid, + unsigned long *data_size) { - void *data; - unsigned long package_size; efi_status_t status; + void *data; - *len = 0; + if (!data_size) + return ERR_PTR(-EINVAL); if (!efi_rt_services_supported(EFI_RT_SUPPORTED_GET_VARIABLE)) return ERR_PTR(-ENODEV); - /* - * TODO: we hardcode a maximum length here, because reading - * from the UEFI is not working. To implement this properly, - * we have to call efivar_entry_size(). - */ - package_size = IWL_HARDCODED_PNVM_SIZE; + /* first call with NULL data to get the exact entry size */ + *data_size = 0; + status = efi.get_variable(name, guid, NULL, data_size, NULL); + if (status != EFI_BUFFER_TOO_SMALL || !*data_size) + return ERR_PTR(-EIO); - data = kmalloc(package_size, GFP_KERNEL); + data = kmalloc(*data_size, GFP_KERNEL); if (!data) return ERR_PTR(-ENOMEM); - status = efi.get_variable(IWL_UEFI_OEM_PNVM_NAME, &IWL_EFI_VAR_GUID, - NULL, &package_size, data); + status = efi.get_variable(name, guid, NULL, data_size, data); if (status != EFI_SUCCESS) { - IWL_DEBUG_FW(trans, - "PNVM UEFI variable not found 0x%lx (len %lu)\n", - status, package_size); kfree(data); return ERR_PTR(-ENOENT); } + return data; +} + +void *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len) +{ + unsigned long package_size; + void *data; + + *len = 0; + + data = iwl_uefi_get_variable(IWL_UEFI_OEM_PNVM_NAME, &IWL_EFI_VAR_GUID, + &package_size); + if (IS_ERR(data)) { + IWL_DEBUG_FW(trans, + "PNVM UEFI variable not found 0x%lx (len %lu)\n", + PTR_ERR(data), package_size); + return data; + } + IWL_DEBUG_FW(trans, "Read PNVM from UEFI with size %lu\n", package_size); *len = package_size; return data; } -static void *iwl_uefi_reduce_power_section(struct iwl_trans *trans, - const u8 *data, size_t len) +int iwl_uefi_handle_tlv_mem_desc(struct iwl_trans *trans, const u8 *data, + u32 tlv_len, struct iwl_pnvm_image *pnvm_data) +{ + const struct iwl_uefi_pnvm_mem_desc *desc = (const void *)data; + u32 data_len; + + if (tlv_len < sizeof(*desc)) { + IWL_DEBUG_FW(trans, "TLV len (%d) is too small\n", tlv_len); + return -EINVAL; + } + + data_len = tlv_len - sizeof(*desc); + + IWL_DEBUG_FW(trans, + "Handle IWL_UCODE_TLV_MEM_DESC, len %d data_len %d\n", + tlv_len, data_len); + + if (le32_to_cpu(desc->size) != data_len) { + IWL_DEBUG_FW(trans, "invalid mem desc size %d\n", desc->size); + return -EINVAL; + } + + if (pnvm_data->n_chunks == IPC_DRAM_MAP_ENTRY_NUM_MAX) { + IWL_DEBUG_FW(trans, "too many payloads to allocate in DRAM.\n"); + return -EINVAL; + } + + IWL_DEBUG_FW(trans, "Adding data (size %d)\n", data_len); + + pnvm_data->chunks[pnvm_data->n_chunks].data = desc->data; + pnvm_data->chunks[pnvm_data->n_chunks].len = data_len; + pnvm_data->n_chunks++; + + return 0; +} + +static int iwl_uefi_reduce_power_section(struct iwl_trans *trans, + const u8 *data, size_t len, + struct iwl_pnvm_image *pnvm_data) { const struct iwl_ucode_tlv *tlv; - u8 *reduce_power_data = NULL, *tmp; - u32 size = 0; IWL_DEBUG_FW(trans, "Handling REDUCE_POWER section\n"); + memset(pnvm_data, 0, sizeof(*pnvm_data)); while (len >= sizeof(*tlv)) { u32 tlv_len, tlv_type; @@ -76,39 +133,17 @@ static void *iwl_uefi_reduce_power_section(struct iwl_trans *trans, if (len < tlv_len) { IWL_ERR(trans, "invalid TLV len: %zd/%u\n", len, tlv_len); - kfree(reduce_power_data); - reduce_power_data = ERR_PTR(-EINVAL); - goto out; + return -EINVAL; } data += sizeof(*tlv); switch (tlv_type) { - case IWL_UCODE_TLV_MEM_DESC: { - IWL_DEBUG_FW(trans, - "Got IWL_UCODE_TLV_MEM_DESC len %d\n", - tlv_len); - - IWL_DEBUG_FW(trans, "Adding data (size %d)\n", tlv_len); - - tmp = krealloc(reduce_power_data, size + tlv_len, GFP_KERNEL); - if (!tmp) { - IWL_DEBUG_FW(trans, - "Couldn't allocate (more) reduce_power_data\n"); - - kfree(reduce_power_data); - reduce_power_data = ERR_PTR(-ENOMEM); - goto out; - } - - reduce_power_data = tmp; - - memcpy(reduce_power_data + size, data, tlv_len); - - size += tlv_len; - + case IWL_UCODE_TLV_MEM_DESC: + if (iwl_uefi_handle_tlv_mem_desc(trans, data, tlv_len, + pnvm_data)) + return -EINVAL; break; - } case IWL_UCODE_TLV_PNVM_SKU: IWL_DEBUG_FW(trans, "New REDUCE_POWER section started, stop parsing.\n"); @@ -124,27 +159,18 @@ static void *iwl_uefi_reduce_power_section(struct iwl_trans *trans, } done: - if (!size) { + if (!pnvm_data->n_chunks) { IWL_DEBUG_FW(trans, "Empty REDUCE_POWER, skipping.\n"); - /* Better safe than sorry, but 'reduce_power_data' should - * always be NULL if !size. - */ - kfree(reduce_power_data); - reduce_power_data = ERR_PTR(-ENOENT); - goto out; + return -ENOENT; } - - IWL_INFO(trans, "loaded REDUCE_POWER\n"); - -out: - return reduce_power_data; + return 0; } -static void *iwl_uefi_reduce_power_parse(struct iwl_trans *trans, - const u8 *data, size_t len) +int iwl_uefi_reduce_power_parse(struct iwl_trans *trans, + const u8 *data, size_t len, + struct iwl_pnvm_image *pnvm_data) { const struct iwl_ucode_tlv *tlv; - void *sec_data; IWL_DEBUG_FW(trans, "Parsing REDUCE_POWER data\n"); @@ -160,7 +186,7 @@ static void *iwl_uefi_reduce_power_parse(struct iwl_trans *trans, if (len < tlv_len) { IWL_ERR(trans, "invalid TLV len: %zd/%u\n", len, tlv_len); - return ERR_PTR(-EINVAL); + return -EINVAL; } if (tlv_type == IWL_UCODE_TLV_PNVM_SKU) { @@ -181,11 +207,11 @@ static void *iwl_uefi_reduce_power_parse(struct iwl_trans *trans, if (trans->sku_id[0] == le32_to_cpu(sku_id->data[0]) && trans->sku_id[1] == le32_to_cpu(sku_id->data[1]) && trans->sku_id[2] == le32_to_cpu(sku_id->data[2])) { - sec_data = iwl_uefi_reduce_power_section(trans, - data, - len); - if (!IS_ERR(sec_data)) - return sec_data; + int ret = iwl_uefi_reduce_power_section(trans, + data, len, + pnvm_data); + if (!ret) + return 0; } else { IWL_DEBUG_FW(trans, "SKU ID didn't match!\n"); } @@ -195,51 +221,45 @@ static void *iwl_uefi_reduce_power_parse(struct iwl_trans *trans, } } - return ERR_PTR(-ENOENT); + return -ENOENT; } -void *iwl_uefi_get_reduced_power(struct iwl_trans *trans, size_t *len) +u8 *iwl_uefi_get_reduced_power(struct iwl_trans *trans, size_t *len) { struct pnvm_sku_package *package; - void *data = NULL; unsigned long package_size; - efi_status_t status; + u8 *data; - *len = 0; + package = iwl_uefi_get_variable(IWL_UEFI_REDUCED_POWER_NAME, + &IWL_EFI_VAR_GUID, &package_size); - if (!efi_rt_services_supported(EFI_RT_SUPPORTED_GET_VARIABLE)) - return ERR_PTR(-ENODEV); - - /* - * TODO: we hardcode a maximum length here, because reading - * from the UEFI is not working. To implement this properly, - * we have to call efivar_entry_size(). - */ - package_size = IWL_HARDCODED_REDUCE_POWER_SIZE; - - package = kmalloc(package_size, GFP_KERNEL); - if (!package) - return ERR_PTR(-ENOMEM); - - status = efi.get_variable(IWL_UEFI_REDUCED_POWER_NAME, &IWL_EFI_VAR_GUID, - NULL, &package_size, package); - if (status != EFI_SUCCESS) { + if (IS_ERR(package)) { IWL_DEBUG_FW(trans, "Reduced Power UEFI variable not found 0x%lx (len %lu)\n", - status, package_size); + PTR_ERR(package), package_size); + return ERR_CAST(package); + } + + if (package_size < sizeof(*package)) { + IWL_DEBUG_FW(trans, + "Invalid Reduced Power UEFI variable len (%lu)\n", + package_size); kfree(package); - return ERR_PTR(-ENOENT); + return ERR_PTR(-EINVAL); } IWL_DEBUG_FW(trans, "Read reduced power from UEFI with size %lu\n", package_size); - *len = package_size; IWL_DEBUG_FW(trans, "rev %d, total_size %d, n_skus %d\n", package->rev, package->total_size, package->n_skus); - data = iwl_uefi_reduce_power_parse(trans, package->data, - *len - sizeof(*package)); + *len = package_size - sizeof(*package); + data = kmemdup(package->data, *len, GFP_KERNEL); + if (!data) { + kfree(package); + return ERR_PTR(-ENOMEM); + } kfree(package); @@ -264,31 +284,27 @@ void iwl_uefi_get_step_table(struct iwl_trans *trans) { struct uefi_cnv_common_step_data *data; unsigned long package_size; - efi_status_t status; int ret; if (trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_AX210) return; - if (!efi_rt_services_supported(EFI_RT_SUPPORTED_GET_VARIABLE)) - return; + data = iwl_uefi_get_variable(IWL_UEFI_STEP_NAME, &IWL_EFI_VAR_GUID, + &package_size); - /* TODO: we hardcode a maximum length here, because reading - * from the UEFI is not working. To implement this properly, - * we have to call efivar_entry_size(). - */ - package_size = IWL_HARDCODED_STEP_SIZE; - - data = kmalloc(package_size, GFP_KERNEL); - if (!data) + if (IS_ERR(data)) { + IWL_DEBUG_FW(trans, + "STEP UEFI variable not found 0x%lx\n", + PTR_ERR(data)); return; + } - status = efi.get_variable(IWL_UEFI_STEP_NAME, &IWL_EFI_VAR_GUID, - NULL, &package_size, data); - if (status != EFI_SUCCESS) { + if (package_size < sizeof(*data)) { IWL_DEBUG_FW(trans, - "STEP UEFI variable not found 0x%lx\n", status); - goto out_free; + "Invalid STEP table UEFI variable len (%lu)\n", + package_size); + kfree(data); + return; } IWL_DEBUG_FW(trans, "Read STEP from UEFI with size %lu\n", @@ -298,7 +314,6 @@ void iwl_uefi_get_step_table(struct iwl_trans *trans) if (ret < 0) IWL_DEBUG_FW(trans, "Cannot read STEP tables. rev is invalid\n"); -out_free: kfree(data); } IWL_EXPORT_SYMBOL(iwl_uefi_get_step_table); @@ -341,29 +356,26 @@ void iwl_uefi_get_sgom_table(struct iwl_trans *trans, { struct uefi_cnv_wlan_sgom_data *data; unsigned long package_size; - efi_status_t status; int ret; - if (!fwrt->geo_enabled || - !efi_rt_services_supported(EFI_RT_SUPPORTED_GET_VARIABLE)) + if (!fwrt->geo_enabled) return; - /* TODO: we hardcode a maximum length here, because reading - * from the UEFI is not working. To implement this properly, - * we have to call efivar_entry_size(). - */ - package_size = IWL_HARDCODED_SGOM_SIZE; - - data = kmalloc(package_size, GFP_KERNEL); - if (!data) + data = iwl_uefi_get_variable(IWL_UEFI_SGOM_NAME, &IWL_EFI_VAR_GUID, + &package_size); + if (IS_ERR(data)) { + IWL_DEBUG_FW(trans, + "SGOM UEFI variable not found 0x%lx\n", + PTR_ERR(data)); return; + } - status = efi.get_variable(IWL_UEFI_SGOM_NAME, &IWL_EFI_VAR_GUID, - NULL, &package_size, data); - if (status != EFI_SUCCESS) { + if (package_size < sizeof(*data)) { IWL_DEBUG_FW(trans, - "SGOM UEFI variable not found 0x%lx\n", status); - goto out_free; + "Invalid SGOM table UEFI variable len (%lu)\n", + package_size); + kfree(data); + return; } IWL_DEBUG_FW(trans, "Read SGOM from UEFI with size %lu\n", @@ -373,9 +385,7 @@ void iwl_uefi_get_sgom_table(struct iwl_trans *trans, if (ret < 0) IWL_DEBUG_FW(trans, "Cannot read SGOM tables. rev is invalid\n"); -out_free: kfree(data); - } IWL_EXPORT_SYMBOL(iwl_uefi_get_sgom_table); #endif /* CONFIG_ACPI */ diff --git a/drivers/net/wireless/intel/iwlwifi/fw/uefi.h b/drivers/net/wireless/intel/iwlwifi/fw/uefi.h index 17089bc74cf92236a7d83808b9b2b444fa73819c..1369cc4855c3a5172de438f4e448d2b107f51430 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/uefi.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/uefi.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ /* - * Copyright(c) 2021-2022 Intel Corporation + * Copyright(c) 2021-2023 Intel Corporation */ #ifndef __iwl_fw_uefi__ #define __iwl_fw_uefi__ @@ -10,16 +10,7 @@ #define IWL_UEFI_SGOM_NAME L"UefiCnvWlanSarGeoOffsetMapping" #define IWL_UEFI_STEP_NAME L"UefiCnvCommonSTEP" -/* - * TODO: we have these hardcoded values that the caller must pass, - * because reading from the UEFI is not working. To implement this - * properly, we have to change iwl_pnvm_get_from_uefi() to call - * efivar_entry_size() and return the value to the caller instead. - */ -#define IWL_HARDCODED_PNVM_SIZE 4096 -#define IWL_HARDCODED_REDUCE_POWER_SIZE 32768 -#define IWL_HARDCODED_SGOM_SIZE 339 -#define IWL_HARDCODED_STEP_SIZE 6 +#define IWL_SGOM_MAP_SIZE 339 struct pnvm_sku_package { u8 rev; @@ -31,7 +22,7 @@ struct pnvm_sku_package { struct uefi_cnv_wlan_sgom_data { u8 revision; - u8 offset_map[IWL_HARDCODED_SGOM_SIZE - 1]; + u8 offset_map[IWL_SGOM_MAP_SIZE - 1]; } __packed; struct uefi_cnv_common_step_data { @@ -50,24 +41,42 @@ struct uefi_cnv_common_step_data { */ #ifdef CONFIG_EFI void *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len); -void *iwl_uefi_get_reduced_power(struct iwl_trans *trans, size_t *len); +u8 *iwl_uefi_get_reduced_power(struct iwl_trans *trans, size_t *len); +int iwl_uefi_reduce_power_parse(struct iwl_trans *trans, + const u8 *data, size_t len, + struct iwl_pnvm_image *pnvm_data); void iwl_uefi_get_step_table(struct iwl_trans *trans); +int iwl_uefi_handle_tlv_mem_desc(struct iwl_trans *trans, const u8 *data, + u32 tlv_len, struct iwl_pnvm_image *pnvm_data); #else /* CONFIG_EFI */ -static inline -void *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len) +static inline void *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len) { return ERR_PTR(-EOPNOTSUPP); } -static inline -void *iwl_uefi_get_reduced_power(struct iwl_trans *trans, size_t *len) +static inline int +iwl_uefi_reduce_power_parse(struct iwl_trans *trans, + const u8 *data, size_t len, + struct iwl_pnvm_image *pnvm_data) +{ + return -EOPNOTSUPP; +} + +static inline u8 * +iwl_uefi_get_reduced_power(struct iwl_trans *trans, size_t *len) { return ERR_PTR(-EOPNOTSUPP); } -static inline -void iwl_uefi_get_step_table(struct iwl_trans *trans) +static inline void iwl_uefi_get_step_table(struct iwl_trans *trans) +{ +} + +static inline int +iwl_uefi_handle_tlv_mem_desc(struct iwl_trans *trans, const u8 *data, + u32 tlv_len, struct iwl_pnvm_image *pnvm_data) { + return 0; } #endif /* CONFIG_EFI */ diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-config.h b/drivers/net/wireless/intel/iwlwifi/iwl-config.h index 411b7d4fcc9abd5eee072f8a1093e787396a87bd..241a9e3f2a1a712cc463e968ee4fe566ac230303 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-config.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-config.h @@ -2,6 +2,7 @@ /* * Copyright (C) 2005-2014, 2018-2021 Intel Corporation * Copyright (C) 2016-2017 Intel Deutschland GmbH + * Copyright (C) 2018-2023 Intel Corporation */ #ifndef __IWL_CONFIG_H__ #define __IWL_CONFIG_H__ @@ -34,6 +35,7 @@ enum iwl_device_family { IWL_DEVICE_FAMILY_22000, IWL_DEVICE_FAMILY_AX210, IWL_DEVICE_FAMILY_BZ, + IWL_DEVICE_FAMILY_SC, }; /* @@ -254,7 +256,6 @@ enum iwl_cfg_trans_ltr_delay { * @xtal_latency: power up latency to get the xtal stabilized * @extra_phy_cfg_flags: extra configuration flags to pass to the PHY * @rf_id: need to read rf_id to determine the firmware image - * @use_tfh: use TFH * @gen2: 22000 and on transport operation * @mq_rx_supported: multi-queue rx support * @integrated: discrete or integrated @@ -269,7 +270,6 @@ struct iwl_cfg_trans_params { u32 xtal_latency; u32 extra_phy_cfg_flags; u32 rf_id:1, - use_tfh:1, gen2:1, mq_rx_supported:1, integrated:1, @@ -307,7 +307,9 @@ struct iwl_fw_mon_regs { * @name: Official name of the device * @fw_name_pre: Firmware filename prefix. The api version and extension * (.ucode) will be added to filename before loading from disk. The - * filename is constructed as fw_name_pre.ucode. + * filename is constructed as -.ucode. + * @fw_name_mac: MAC name for this config, the remaining pieces of the + * name will be generated dynamically * @ucode_api_max: Highest version of uCode API supported by driver. * @ucode_api_min: Lowest version of uCode API supported by driver. * @max_inst_size: The maximal length of the fw inst section (only DVM) @@ -361,6 +363,7 @@ struct iwl_cfg { /* params specific to an individual device within a device family */ const char *name; const char *fw_name_pre; + const char *fw_name_mac; /* params likely to change within a device family */ const struct iwl_ht_params *ht_params; const struct iwl_eeprom_params *eeprom_params; @@ -388,7 +391,6 @@ struct iwl_cfg { high_temp:1, mac_addr_from_csr:10, lp_xtal_workaround:1, - disable_dummy_notification:1, apmg_not_supported:1, vht_mu_mimo_supported:1, cdb:1, @@ -416,17 +418,15 @@ struct iwl_cfg { #define IWL_CFG_ANY (~0) #define IWL_CFG_MAC_TYPE_PU 0x31 -#define IWL_CFG_MAC_TYPE_PNJ 0x32 #define IWL_CFG_MAC_TYPE_TH 0x32 #define IWL_CFG_MAC_TYPE_QU 0x33 #define IWL_CFG_MAC_TYPE_QUZ 0x35 -#define IWL_CFG_MAC_TYPE_QNJ 0x36 #define IWL_CFG_MAC_TYPE_SO 0x37 -#define IWL_CFG_MAC_TYPE_SNJ 0x42 #define IWL_CFG_MAC_TYPE_SOF 0x43 #define IWL_CFG_MAC_TYPE_MA 0x44 #define IWL_CFG_MAC_TYPE_BZ 0x46 #define IWL_CFG_MAC_TYPE_GL 0x47 +#define IWL_CFG_MAC_TYPE_SC 0x48 #define IWL_CFG_RF_TYPE_TH 0x105 #define IWL_CFG_RF_TYPE_TH1 0x108 @@ -438,6 +438,7 @@ struct iwl_cfg { #define IWL_CFG_RF_TYPE_MR 0x110 #define IWL_CFG_RF_TYPE_MS 0x111 #define IWL_CFG_RF_TYPE_FM 0x112 +#define IWL_CFG_RF_TYPE_WH 0x113 #define IWL_CFG_RF_ID_TH 0x1 #define IWL_CFG_RF_ID_TH1 0x1 @@ -486,17 +487,16 @@ extern const struct iwl_cfg_trans_params iwl9000_trans_cfg; extern const struct iwl_cfg_trans_params iwl9560_trans_cfg; extern const struct iwl_cfg_trans_params iwl9560_long_latency_trans_cfg; extern const struct iwl_cfg_trans_params iwl9560_shared_clk_trans_cfg; -extern const struct iwl_cfg_trans_params iwl_qnj_trans_cfg; extern const struct iwl_cfg_trans_params iwl_qu_trans_cfg; extern const struct iwl_cfg_trans_params iwl_qu_medium_latency_trans_cfg; extern const struct iwl_cfg_trans_params iwl_qu_long_latency_trans_cfg; extern const struct iwl_cfg_trans_params iwl_ax200_trans_cfg; -extern const struct iwl_cfg_trans_params iwl_snj_trans_cfg; extern const struct iwl_cfg_trans_params iwl_so_trans_cfg; extern const struct iwl_cfg_trans_params iwl_so_long_latency_trans_cfg; extern const struct iwl_cfg_trans_params iwl_so_long_latency_imr_trans_cfg; extern const struct iwl_cfg_trans_params iwl_ma_trans_cfg; extern const struct iwl_cfg_trans_params iwl_bz_trans_cfg; +extern const struct iwl_cfg_trans_params iwl_sc_trans_cfg; extern const char iwl9162_name[]; extern const char iwl9260_name[]; extern const char iwl9260_1_name[]; @@ -535,6 +535,7 @@ extern const char iwl_ax221_name[]; extern const char iwl_ax231_name[]; extern const char iwl_ax411_name[]; extern const char iwl_bz_name[]; +extern const char iwl_sc_name[]; #if IS_ENABLED(CONFIG_IWLDVM) extern const struct iwl_cfg iwl5300_agn_cfg; extern const struct iwl_cfg iwl5100_agn_cfg; @@ -580,6 +581,7 @@ extern const struct iwl_cfg iwl105_bgn_d_cfg; extern const struct iwl_cfg iwl135_bgn_cfg; #endif /* CONFIG_IWLDVM */ #if IS_ENABLED(CONFIG_IWLMVM) +extern const struct iwl_ht_params iwl_22000_ht_params; extern const struct iwl_cfg iwl7260_2ac_cfg; extern const struct iwl_cfg iwl7260_2ac_cfg_high_temp; extern const struct iwl_cfg iwl7260_2n_cfg; @@ -604,7 +606,6 @@ extern const struct iwl_cfg iwl9260_2ac_cfg; extern const struct iwl_cfg iwl9560_qu_b0_jf_b0_cfg; extern const struct iwl_cfg iwl9560_qu_c0_jf_b0_cfg; extern const struct iwl_cfg iwl9560_quz_a0_jf_b0_cfg; -extern const struct iwl_cfg iwl9560_qnj_b0_jf_b0_cfg; extern const struct iwl_cfg iwl9560_2ac_cfg_soc; extern const struct iwl_cfg iwl_qu_b0_hr1_b0; extern const struct iwl_cfg iwl_qu_c0_hr1_b0; @@ -623,57 +624,23 @@ extern const struct iwl_cfg killer1650s_2ax_cfg_qu_c0_hr_b0; extern const struct iwl_cfg killer1650i_2ax_cfg_qu_c0_hr_b0; extern const struct iwl_cfg killer1650x_2ax_cfg; extern const struct iwl_cfg killer1650w_2ax_cfg; -extern const struct iwl_cfg iwl_qnj_b0_hr_b0_cfg; extern const struct iwl_cfg iwlax210_2ax_cfg_so_jf_b0; extern const struct iwl_cfg iwlax211_2ax_cfg_so_gf_a0; extern const struct iwl_cfg iwlax211_2ax_cfg_so_gf_a0_long; extern const struct iwl_cfg iwlax210_2ax_cfg_ty_gf_a0; extern const struct iwl_cfg iwlax411_2ax_cfg_so_gf4_a0; extern const struct iwl_cfg iwlax411_2ax_cfg_so_gf4_a0_long; -extern const struct iwl_cfg iwlax411_2ax_cfg_sosnj_gf4_a0; -extern const struct iwl_cfg iwlax211_cfg_snj_gf_a0; -extern const struct iwl_cfg iwl_cfg_snj_hr_b0; -extern const struct iwl_cfg iwl_cfg_snj_a0_jf_b0; -extern const struct iwl_cfg iwl_cfg_ma_a0_hr_b0; -extern const struct iwl_cfg iwl_cfg_ma_a0_gf_a0; -extern const struct iwl_cfg iwl_cfg_ma_a0_gf4_a0; -extern const struct iwl_cfg iwl_cfg_ma_a0_mr_a0; -extern const struct iwl_cfg iwl_cfg_ma_a0_ms_a0; -extern const struct iwl_cfg iwl_cfg_ma_a0_fm_a0; -extern const struct iwl_cfg iwl_cfg_ma_b0_hr_b0; -extern const struct iwl_cfg iwl_cfg_ma_b0_gf_a0; -extern const struct iwl_cfg iwl_cfg_ma_b0_gf4_a0; -extern const struct iwl_cfg iwl_cfg_ma_b0_mr_a0; -extern const struct iwl_cfg iwl_cfg_ma_b0_fm_a0; -extern const struct iwl_cfg iwl_cfg_snj_a0_mr_a0; -extern const struct iwl_cfg iwl_cfg_snj_a0_ms_a0; + +extern const struct iwl_cfg iwl_cfg_ma; + extern const struct iwl_cfg iwl_cfg_so_a0_hr_a0; extern const struct iwl_cfg iwl_cfg_so_a0_ms_a0; extern const struct iwl_cfg iwl_cfg_quz_a0_hr_b0; -extern const struct iwl_cfg iwl_cfg_bz_a0_hr_a0; -extern const struct iwl_cfg iwl_cfg_bz_a0_hr_b0; -extern const struct iwl_cfg iwl_cfg_bz_a0_gf_a0; -extern const struct iwl_cfg iwl_cfg_bz_a0_gf4_a0; -extern const struct iwl_cfg iwl_cfg_bz_a0_mr_a0; -extern const struct iwl_cfg iwl_cfg_bz_a0_fm_a0; -extern const struct iwl_cfg iwl_cfg_bz_a0_fm4_a0; -extern const struct iwl_cfg iwl_cfg_bz_a0_fm_b0; -extern const struct iwl_cfg iwl_cfg_bz_a0_fm4_b0; -extern const struct iwl_cfg iwl_cfg_gl_a0_fm_a0; -extern const struct iwl_cfg iwl_cfg_gl_b0_fm_b0; -extern const struct iwl_cfg iwl_cfg_bz_z0_gf_a0; -extern const struct iwl_cfg iwl_cfg_bnj_a0_fm_a0; -extern const struct iwl_cfg iwl_cfg_bnj_a0_fm4_a0; -extern const struct iwl_cfg iwl_cfg_bnj_a0_gf_a0; -extern const struct iwl_cfg iwl_cfg_bnj_b0_gf_a0; -extern const struct iwl_cfg iwl_cfg_bnj_a0_gf4_a0; -extern const struct iwl_cfg iwl_cfg_bnj_b0_gf4_a0; -extern const struct iwl_cfg iwl_cfg_bnj_a0_hr_a0; -extern const struct iwl_cfg iwl_cfg_bnj_a0_hr_b0; -extern const struct iwl_cfg iwl_cfg_bnj_b0_hr_a0; -extern const struct iwl_cfg iwl_cfg_bnj_b0_hr_b0; -extern const struct iwl_cfg iwl_cfg_bnj_b0_fm_b0; -extern const struct iwl_cfg iwl_cfg_bnj_b0_fm4_b0; + +extern const struct iwl_cfg iwl_cfg_bz; +extern const struct iwl_cfg iwl_cfg_gl; + +extern const struct iwl_cfg iwl_cfg_sc; #endif /* CONFIG_IWLMVM */ #endif /* __IWL_CONFIG_H__ */ diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-context-info-gen3.h b/drivers/net/wireless/intel/iwlwifi/iwl-context-info-gen3.h index 3f7278014009101b91749a44fb7a8630f3f41017..96bf353469b8d67669f73a8e9df0236476fcb80d 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-context-info-gen3.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-context-info-gen3.h @@ -13,6 +13,8 @@ #define CSR_IML_SIZE_ADDR 0x128 #define CSR_IML_RESP_ADDR 0x12c +#define UNFRAGMENTED_PNVM_PAYLOADS_NUMBER 2 + /* Set bit for enabling automatic function boot */ #define CSR_AUTO_FUNC_BOOT_ENA BIT(1) /* Set bit for initiating function boot */ @@ -96,9 +98,9 @@ struct iwl_prph_scratch_control { } __packed; /* PERIPH_SCRATCH_CONTROL_S */ /* - * struct iwl_prph_scratch_pnvm_cfg - ror config + * struct iwl_prph_scratch_pnvm_cfg - PNVM scratch * @pnvm_base_addr: PNVM start address - * @pnvm_size: PNVM size in DWs + * @pnvm_size: the size of the PNVM image in bytes * @reserved: reserved */ struct iwl_prph_scratch_pnvm_cfg { @@ -107,6 +109,14 @@ struct iwl_prph_scratch_pnvm_cfg { __le32 reserved; } __packed; /* PERIPH_SCRATCH_PNVM_CFG_S */ +/** + * struct iwl_prph_scrath_mem_desc_addr_array + * @mem_descs: array of dram addresses. + * Each address is the beggining of a pnvm payload. + */ +struct iwl_prph_scrath_mem_desc_addr_array { + __le64 mem_descs[IPC_DRAM_MAP_ENTRY_NUM_MAX]; +} __packed; /* PERIPH_SCRATCH_MEM_DESC_ADDR_ARRAY_S_VER_1 */ /* * struct iwl_prph_scratch_hwm_cfg - hwm config * @hwm_base_addr: hwm start address @@ -132,7 +142,7 @@ struct iwl_prph_scratch_rbd_cfg { /* * struct iwl_prph_scratch_uefi_cfg - prph scratch reduce power table * @base_addr: reduce power table address - * @size: table size in dwords + * @size: the size of the entire power table image */ struct iwl_prph_scratch_uefi_cfg { __le64 base_addr; @@ -277,10 +287,18 @@ int iwl_pcie_ctxt_info_gen3_init(struct iwl_trans *trans, const struct fw_img *fw); void iwl_pcie_ctxt_info_gen3_free(struct iwl_trans *trans, bool alive); -int iwl_trans_pcie_ctx_info_gen3_set_pnvm(struct iwl_trans *trans, - const void *data, u32 len); -int iwl_trans_pcie_ctx_info_gen3_set_reduce_power(struct iwl_trans *trans, - const void *data, u32 len); +int iwl_trans_pcie_ctx_info_gen3_load_pnvm(struct iwl_trans *trans, + const struct iwl_pnvm_image *pnvm_payloads, + const struct iwl_ucode_capabilities *capa); +void iwl_trans_pcie_ctx_info_gen3_set_pnvm(struct iwl_trans *trans, + const struct iwl_ucode_capabilities *capa); +int +iwl_trans_pcie_ctx_info_gen3_load_reduce_power(struct iwl_trans *trans, + const struct iwl_pnvm_image *payloads, + const struct iwl_ucode_capabilities *capa); +void +iwl_trans_pcie_ctx_info_gen3_set_reduce_power(struct iwl_trans *trans, + const struct iwl_ucode_capabilities *capa); int iwl_trans_pcie_ctx_info_gen3_set_step(struct iwl_trans *trans, u32 mbx_addr_0_step, u32 mbx_addr_1_step); #endif /* __iwl_context_info_file_gen3_h__ */ diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-context-info.h b/drivers/net/wireless/intel/iwlwifi/iwl-context-info.h index 4354d5acac9f887107f41aff0bff5b710f5af0f2..1a1321db137ca96cbcddeeaf924b5877c15ec6af 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-context-info.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-context-info.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ /* * Copyright (C) 2017 Intel Deutschland GmbH - * Copyright (C) 2018-2020 Intel Corporation + * Copyright (C) 2018-2020, 2022 Intel Corporation */ #ifndef __iwl_context_info_file_h__ #define __iwl_context_info_file_h__ @@ -177,6 +177,9 @@ void iwl_pcie_ctxt_info_free_paging(struct iwl_trans *trans); int iwl_pcie_init_fw_sec(struct iwl_trans *trans, const struct fw_img *fw, struct iwl_context_info_dram *ctxt_dram); +void *iwl_pcie_ctxt_info_dma_alloc_coherent(struct iwl_trans *trans, + size_t size, + dma_addr_t *phys); int iwl_pcie_ctxt_info_alloc_dma(struct iwl_trans *trans, const void *data, u32 len, struct iwl_dram_data *dram); diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c b/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c index 898d5dcf1012ef48c16e82faa0717fee3a98835b..ef5baee6c9c52db71a1ccde7873ea66b6b0724cd 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* - * Copyright (C) 2018-2022 Intel Corporation + * Copyright (C) 2018-2023 Intel Corporation */ #include #include "iwl-drv.h" @@ -586,8 +586,14 @@ static int iwl_dbg_tlv_alloc_fragments(struct iwl_fw_runtime *fwrt, fw_mon_cfg = &fwrt->trans->dbg.fw_mon_cfg[alloc_id]; fw_mon = &fwrt->trans->dbg.fw_mon_ini[alloc_id]; - if (fw_mon->num_frags || - fw_mon_cfg->buf_location != + if (fw_mon->num_frags) { + for (i = 0; i < fw_mon->num_frags; i++) + memset(fw_mon->frags[i].block, 0, + fw_mon->frags[i].size); + return 0; + } + + if (fw_mon_cfg->buf_location != cpu_to_le32(IWL_FW_INI_LOCATION_DRAM_PATH)) return 0; @@ -738,7 +744,8 @@ static int iwl_dbg_tlv_update_dram(struct iwl_fw_runtime *fwrt, if (le32_to_cpu(fwrt->trans->dbg.fw_mon_cfg[alloc_id].buf_location) != IWL_FW_INI_LOCATION_DRAM_PATH) { - IWL_DEBUG_FW(fwrt, "DRAM_PATH is not supported alloc_id %u\n", alloc_id); + IWL_DEBUG_FW(fwrt, "WRT: alloc_id %u location is not in DRAM_PATH\n", + alloc_id); return -1; } @@ -794,11 +801,14 @@ static void iwl_dbg_tlv_update_drams(struct iwl_fw_runtime *fwrt) IWL_UCODE_TLV_CAPA_DRAM_FRAG_SUPPORT)) return; - dram_info->first_word = cpu_to_le32(DRAM_INFO_FIRST_MAGIC_WORD); - dram_info->second_word = cpu_to_le32(DRAM_INFO_SECOND_MAGIC_WORD); + memset(dram_info, 0, sizeof(*dram_info)); for (i = IWL_FW_INI_ALLOCATION_ID_DBGC1; i < IWL_FW_INI_ALLOCATION_NUM; i++) { + if (fwrt->trans->dbg.fw_mon_cfg[i].buf_location == + IWL_FW_INI_LOCATION_INVALID) + continue; + ret = iwl_dbg_tlv_update_dram(fwrt, i, dram_info); if (!ret) dram_alloc = true; @@ -808,11 +818,10 @@ static void iwl_dbg_tlv_update_drams(struct iwl_fw_runtime *fwrt) i, ret); } - if (dram_alloc) - IWL_DEBUG_FW(fwrt, "block data after %08x\n", - dram_info->first_word); - else - memset(frags->block, 0, sizeof(*dram_info)); + if (dram_alloc) { + dram_info->first_word = cpu_to_le32(DRAM_INFO_FIRST_MAGIC_WORD); + dram_info->second_word = cpu_to_le32(DRAM_INFO_SECOND_MAGIC_WORD); + } } static void iwl_dbg_tlv_send_hcmds(struct iwl_fw_runtime *fwrt, @@ -1269,18 +1278,23 @@ static void iwl_dbg_tlv_init_cfg(struct iwl_fw_runtime *fwrt) int ret, i; u32 failed_alloc = 0; - if (*ini_dest != IWL_FW_INI_LOCATION_INVALID) - return; - - IWL_DEBUG_FW(fwrt, - "WRT: Generating active triggers list, domain 0x%x\n", - fwrt->trans->dbg.domains_bitmap); + if (*ini_dest == IWL_FW_INI_LOCATION_INVALID) { + IWL_DEBUG_FW(fwrt, + "WRT: Generating active triggers list, domain 0x%x\n", + fwrt->trans->dbg.domains_bitmap); - for (i = 0; i < ARRAY_SIZE(fwrt->trans->dbg.time_point); i++) { - struct iwl_dbg_tlv_time_point_data *tp = - &fwrt->trans->dbg.time_point[i]; + for (i = 0; i < ARRAY_SIZE(fwrt->trans->dbg.time_point); i++) { + struct iwl_dbg_tlv_time_point_data *tp = + &fwrt->trans->dbg.time_point[i]; - iwl_dbg_tlv_gen_active_trig_list(fwrt, tp); + iwl_dbg_tlv_gen_active_trig_list(fwrt, tp); + } + } else if (*ini_dest != IWL_FW_INI_LOCATION_DRAM_PATH) { + /* For DRAM, go through the loop below to clear all the buffers + * properly on restart, otherwise garbage may be left there and + * leak into new debug dumps. + */ + return; } *ini_dest = IWL_FW_INI_LOCATION_INVALID; diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c index 34feb4d29adc8ff2bbb729ea3fa4c0cc5d7f7f14..3d87d26845e74ba51f04e815110b4bd00b20433f 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c @@ -158,12 +158,71 @@ static int iwl_alloc_fw_desc(struct iwl_drv *drv, struct fw_desc *desc, return 0; } +static inline char iwl_drv_get_step(int step) +{ + if (step == SILICON_Z_STEP) + return 'z'; + return 'a' + step; +} + +const char *iwl_drv_get_fwname_pre(struct iwl_trans *trans, char *buf) +{ + char mac_step, rf_step; + const char *rf, *cdb; + + if (trans->cfg->fw_name_pre) + return trans->cfg->fw_name_pre; + + if (WARN_ON(!trans->cfg->fw_name_mac)) + return "unconfigured"; + + mac_step = iwl_drv_get_step(trans->hw_rev_step); + + switch (CSR_HW_RFID_TYPE(trans->hw_rf_id)) { + case IWL_CFG_RF_TYPE_HR1: + case IWL_CFG_RF_TYPE_HR2: + rf = "hr"; + break; + case IWL_CFG_RF_TYPE_GF: + rf = "gf"; + break; + case IWL_CFG_RF_TYPE_MR: + rf = "mr"; + break; + case IWL_CFG_RF_TYPE_MS: + rf = "ms"; + break; + case IWL_CFG_RF_TYPE_FM: + rf = "fm"; + break; + case IWL_CFG_RF_TYPE_WH: + rf = "wh"; + break; + default: + return "unknown-rf"; + } + + cdb = CSR_HW_RFID_IS_CDB(trans->hw_rf_id) ? "4" : ""; + + rf_step = iwl_drv_get_step(CSR_HW_RFID_STEP(trans->hw_rf_id)); + + scnprintf(buf, FW_NAME_PRE_BUFSIZE, + "iwlwifi-%s-%c0-%s%s-%c0", + trans->cfg->fw_name_mac, mac_step, + rf, cdb, rf_step); + + return buf; +} +IWL_EXPORT_SYMBOL(iwl_drv_get_fwname_pre); + static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context); static int iwl_request_firmware(struct iwl_drv *drv, bool first) { const struct iwl_cfg *cfg = drv->trans->cfg; + char _fw_name_pre[FW_NAME_PRE_BUFSIZE]; + const char *fw_name_pre; if (drv->trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_9000 && (drv->trans->hw_rev_step != SILICON_B_STEP && @@ -174,6 +233,8 @@ static int iwl_request_firmware(struct iwl_drv *drv, bool first) return -EINVAL; } + fw_name_pre = iwl_drv_get_fwname_pre(drv->trans, _fw_name_pre); + if (first) drv->fw_index = cfg->ucode_api_max; else @@ -183,13 +244,13 @@ static int iwl_request_firmware(struct iwl_drv *drv, bool first) IWL_ERR(drv, "no suitable firmware found!\n"); if (cfg->ucode_api_min == cfg->ucode_api_max) { - IWL_ERR(drv, "%s%d is required\n", cfg->fw_name_pre, + IWL_ERR(drv, "%s-%d is required\n", fw_name_pre, cfg->ucode_api_max); } else { - IWL_ERR(drv, "minimum version required: %s%d\n", - cfg->fw_name_pre, cfg->ucode_api_min); - IWL_ERR(drv, "maximum version supported: %s%d\n", - cfg->fw_name_pre, cfg->ucode_api_max); + IWL_ERR(drv, "minimum version required: %s-%d\n", + fw_name_pre, cfg->ucode_api_min); + IWL_ERR(drv, "maximum version supported: %s-%d\n", + fw_name_pre, cfg->ucode_api_max); } IWL_ERR(drv, @@ -197,8 +258,8 @@ static int iwl_request_firmware(struct iwl_drv *drv, bool first) return -ENOENT; } - snprintf(drv->firmware_name, sizeof(drv->firmware_name), "%s%d.ucode", - cfg->fw_name_pre, drv->fw_index); + snprintf(drv->firmware_name, sizeof(drv->firmware_name), "%s-%d.ucode", + fw_name_pre, drv->fw_index); IWL_DEBUG_FW_INFO(drv, "attempting to load firmware '%s'\n", drv->firmware_name); diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-drv.h b/drivers/net/wireless/intel/iwlwifi/iwl-drv.h index 80073f973334fc7a0014c506b0ceba7c79b761ca..6c19989e4ab7de2a3d5f49bbf5f0cfa4151ec66f 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-drv.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-drv.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ /* - * Copyright (C) 2005-2014, 2020-2021 Intel Corporation + * Copyright (C) 2005-2014, 2020-2021, 2023 Intel Corporation * Copyright (C) 2013-2014 Intel Mobile Communications GmbH */ #ifndef __iwl_drv_h__ @@ -92,4 +92,8 @@ void iwl_drv_stop(struct iwl_drv *drv); /* max retry for init flow */ #define IWL_MAX_INIT_RETRY 2 +#define FW_NAME_PRE_BUFSIZE 64 +struct iwl_trans; +const char *iwl_drv_get_fwname_pre(struct iwl_trans *trans, char *buf); + #endif /* __iwl_drv_h__ */ diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-fh.h b/drivers/net/wireless/intel/iwlwifi/iwl-fh.h index bedd78a47f671a3ec0bb05a425a61c324c5593e5..4e4a60ddf9b274510c4c26b4595b74335069cd0f 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-fh.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-fh.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ /* - * Copyright (C) 2005-2014, 2018-2021 Intel Corporation + * Copyright (C) 2005-2014, 2018-2021, 2023 Intel Corporation * Copyright (C) 2015-2017 Intel Deutschland GmbH */ #ifndef __iwl_fh_h__ @@ -71,7 +71,7 @@ static inline unsigned int FH_MEM_CBBC_QUEUE(struct iwl_trans *trans, unsigned int chnl) { - if (trans->trans_cfg->use_tfh) { + if (trans->trans_cfg->gen2) { WARN_ON_ONCE(chnl >= 64); return TFH_TFDQ_CBB_TABLE + 8 * chnl; } diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-io.c b/drivers/net/wireless/intel/iwlwifi/iwl-io.c index 396f2c997da6f39aa211e56773e76418e0ad26b9..c60f9466c5fd2a1bdc6c6aa52fb841f3a8c019c5 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-io.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-io.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* - * Copyright (C) 2003-2014, 2018-2021 Intel Corporation + * Copyright (C) 2003-2014, 2018-2022 Intel Corporation * Copyright (C) 2015-2016 Intel Deutschland GmbH */ #include @@ -72,6 +72,7 @@ u32 iwl_read_direct32(struct iwl_trans *trans, u32 reg) return value; } + /* return as if we have a HW timeout/failure */ return 0x5a5a5a5a; } IWL_EXPORT_SYMBOL(iwl_read_direct32); @@ -143,6 +144,7 @@ u32 iwl_read_prph(struct iwl_trans *trans, u32 ofs) return val; } + /* return as if we have a HW timeout/failure */ return 0x5a5a5a5a; } IWL_EXPORT_SYMBOL(iwl_read_prph); diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c index 7dcb1c3ab7282386cafb0f31a059e16616be3eb5..8c23f57f5c89f44d82d529b4f7ed6c0cdf454a18 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* - * Copyright (C) 2005-2014, 2018-2022 Intel Corporation + * Copyright (C) 2005-2014, 2018-2023 Intel Corporation * Copyright (C) 2013-2015 Intel Mobile Communications GmbH * Copyright (C) 2016-2017 Intel Deutschland GmbH */ @@ -173,34 +173,34 @@ enum iwl_nvm_channel_flags { }; /** - * enum iwl_reg_capa_flags - global flags applied for the whole regulatory + * enum iwl_reg_capa_flags_v1 - global flags applied for the whole regulatory * domain. - * @REG_CAPA_BF_CCD_LOW_BAND: Beam-forming or Cyclic Delay Diversity in the + * @REG_CAPA_V1_BF_CCD_LOW_BAND: Beam-forming or Cyclic Delay Diversity in the * 2.4Ghz band is allowed. - * @REG_CAPA_BF_CCD_HIGH_BAND: Beam-forming or Cyclic Delay Diversity in the + * @REG_CAPA_V1_BF_CCD_HIGH_BAND: Beam-forming or Cyclic Delay Diversity in the * 5Ghz band is allowed. - * @REG_CAPA_160MHZ_ALLOWED: 11ac channel with a width of 160Mhz is allowed + * @REG_CAPA_V1_160MHZ_ALLOWED: 11ac channel with a width of 160Mhz is allowed * for this regulatory domain (valid only in 5Ghz). - * @REG_CAPA_80MHZ_ALLOWED: 11ac channel with a width of 80Mhz is allowed + * @REG_CAPA_V1_80MHZ_ALLOWED: 11ac channel with a width of 80Mhz is allowed * for this regulatory domain (valid only in 5Ghz). - * @REG_CAPA_MCS_8_ALLOWED: 11ac with MCS 8 is allowed. - * @REG_CAPA_MCS_9_ALLOWED: 11ac with MCS 9 is allowed. - * @REG_CAPA_40MHZ_FORBIDDEN: 11n channel with a width of 40Mhz is forbidden + * @REG_CAPA_V1_MCS_8_ALLOWED: 11ac with MCS 8 is allowed. + * @REG_CAPA_V1_MCS_9_ALLOWED: 11ac with MCS 9 is allowed. + * @REG_CAPA_V1_40MHZ_FORBIDDEN: 11n channel with a width of 40Mhz is forbidden * for this regulatory domain (valid only in 5Ghz). - * @REG_CAPA_DC_HIGH_ENABLED: DC HIGH allowed. - * @REG_CAPA_11AX_DISABLED: 11ax is forbidden for this regulatory domain. + * @REG_CAPA_V1_DC_HIGH_ENABLED: DC HIGH allowed. + * @REG_CAPA_V1_11AX_DISABLED: 11ax is forbidden for this regulatory domain. */ -enum iwl_reg_capa_flags { - REG_CAPA_BF_CCD_LOW_BAND = BIT(0), - REG_CAPA_BF_CCD_HIGH_BAND = BIT(1), - REG_CAPA_160MHZ_ALLOWED = BIT(2), - REG_CAPA_80MHZ_ALLOWED = BIT(3), - REG_CAPA_MCS_8_ALLOWED = BIT(4), - REG_CAPA_MCS_9_ALLOWED = BIT(5), - REG_CAPA_40MHZ_FORBIDDEN = BIT(7), - REG_CAPA_DC_HIGH_ENABLED = BIT(9), - REG_CAPA_11AX_DISABLED = BIT(10), -}; +enum iwl_reg_capa_flags_v1 { + REG_CAPA_V1_BF_CCD_LOW_BAND = BIT(0), + REG_CAPA_V1_BF_CCD_HIGH_BAND = BIT(1), + REG_CAPA_V1_160MHZ_ALLOWED = BIT(2), + REG_CAPA_V1_80MHZ_ALLOWED = BIT(3), + REG_CAPA_V1_MCS_8_ALLOWED = BIT(4), + REG_CAPA_V1_MCS_9_ALLOWED = BIT(5), + REG_CAPA_V1_40MHZ_FORBIDDEN = BIT(7), + REG_CAPA_V1_DC_HIGH_ENABLED = BIT(9), + REG_CAPA_V1_11AX_DISABLED = BIT(10), +}; /* GEO_CHANNEL_CAPABILITIES_API_S_VER_1 */ /** * enum iwl_reg_capa_flags_v2 - global flags applied for the whole regulatory @@ -234,7 +234,31 @@ enum iwl_reg_capa_flags_v2 { REG_CAPA_V2_WEATHER_DISABLED = BIT(7), REG_CAPA_V2_40MHZ_ALLOWED = BIT(8), REG_CAPA_V2_11AX_DISABLED = BIT(10), -}; +}; /* GEO_CHANNEL_CAPABILITIES_API_S_VER_2 */ + +/** + * enum iwl_reg_capa_flags_v4 - global flags applied for the whole regulatory + * domain. + * @REG_CAPA_V4_160MHZ_ALLOWED: 11ac channel with a width of 160Mhz is allowed + * for this regulatory domain (valid only in 5Ghz). + * @REG_CAPA_V4_80MHZ_ALLOWED: 11ac channel with a width of 80Mhz is allowed + * for this regulatory domain (valid only in 5Ghz). + * @REG_CAPA_V4_MCS_12_ALLOWED: 11ac with MCS 12 is allowed. + * @REG_CAPA_V4_MCS_13_ALLOWED: 11ac with MCS 13 is allowed. + * @REG_CAPA_V4_11BE_DISABLED: 11be is forbidden for this regulatory domain. + * @REG_CAPA_V4_11AX_DISABLED: 11ax is forbidden for this regulatory domain. + * @REG_CAPA_V4_320MHZ_ALLOWED: 11be channel with a width of 320Mhz is allowed + * for this regulatory domain (valid only in 5GHz). + */ +enum iwl_reg_capa_flags_v4 { + REG_CAPA_V4_160MHZ_ALLOWED = BIT(3), + REG_CAPA_V4_80MHZ_ALLOWED = BIT(4), + REG_CAPA_V4_MCS_12_ALLOWED = BIT(5), + REG_CAPA_V4_MCS_13_ALLOWED = BIT(6), + REG_CAPA_V4_11BE_DISABLED = BIT(8), + REG_CAPA_V4_11AX_DISABLED = BIT(13), + REG_CAPA_V4_320MHZ_ALLOWED = BIT(16), +}; /* GEO_CHANNEL_CAPABILITIES_API_S_VER_4 */ /* * API v2 for reg_capa_flags is relevant from version 6 and onwards of the @@ -242,23 +266,33 @@ enum iwl_reg_capa_flags_v2 { */ #define REG_CAPA_V2_RESP_VER 6 +/* API v4 for reg_capa_flags is relevant from version 8 and onwards of the + * MCC update command response. + */ +#define REG_CAPA_V4_RESP_VER 8 + /** * struct iwl_reg_capa - struct for global regulatory capabilities, Used for * handling the different APIs of reg_capa_flags. * * @allow_40mhz: 11n channel with a width of 40Mhz is allowed - * for this regulatory domain (valid only in 5Ghz). + * for this regulatory domain. * @allow_80mhz: 11ac channel with a width of 80Mhz is allowed - * for this regulatory domain (valid only in 5Ghz). + * for this regulatory domain (valid only in 5 and 6 Ghz). * @allow_160mhz: 11ac channel with a width of 160Mhz is allowed - * for this regulatory domain (valid only in 5Ghz). + * for this regulatory domain (valid only in 5 and 6 Ghz). + * @allow_320mhz: 11be channel with a width of 320Mhz is allowed + * for this regulatory domain (valid only in 6 Ghz). * @disable_11ax: 11ax is forbidden for this regulatory domain. + * @disable_11be: 11be is forbidden for this regulatory domain. */ struct iwl_reg_capa { - u16 allow_40mhz; - u16 allow_80mhz; - u16 allow_160mhz; - u16 disable_11ax; + bool allow_40mhz; + bool allow_80mhz; + bool allow_160mhz; + bool allow_320mhz; + bool disable_11ax; + bool disable_11be; }; static inline void iwl_nvm_print_channel_flags(struct device *dev, u32 level, @@ -464,6 +498,9 @@ static void iwl_init_vht_hw_capab(struct iwl_trans *trans, IEEE80211_VHT_MAX_AMPDU_1024K << IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT; + if (!trans->cfg->ht_params->stbc) + vht_cap->cap &= ~IEEE80211_VHT_CAP_RXSTBC_MASK; + if (data->vht160_supported) vht_cap->cap |= IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ | IEEE80211_VHT_CAP_SHORT_GI_160; @@ -479,7 +516,7 @@ static void iwl_init_vht_hw_capab(struct iwl_trans *trans, num_tx_ants = 1; } - if (num_tx_ants > 1) + if (trans->cfg->ht_params->stbc && num_tx_ants > 1) vht_cap->cap |= IEEE80211_VHT_CAP_TXSTBC; else vht_cap->cap |= IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN; @@ -643,8 +680,7 @@ static const struct ieee80211_sband_iftype_data iwl_he_eht_capa[] = { IEEE80211_EHT_PHY_CAP0_BEAMFORMEE_SS_80MHZ_MASK, .phy_cap_info[1] = IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_80MHZ_MASK | - IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_160MHZ_MASK | - IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_320MHZ_MASK, + IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_160MHZ_MASK, .phy_cap_info[3] = IEEE80211_EHT_PHY_CAP3_NG_16_SU_FEEDBACK | IEEE80211_EHT_PHY_CAP3_NG_16_MU_FEEDBACK | @@ -853,6 +889,10 @@ iwl_nvm_fixup_sband_iftd(struct iwl_trans *trans, const struct iwl_fw *fw) { bool is_ap = iftype_data->types_mask & BIT(NL80211_IFTYPE_AP); + bool no_320; + + no_320 = !trans->trans_cfg->integrated && + trans->pcie_link_speed < PCI_EXP_LNKSTA_CLS_8_0GB; if (!data->sku_cap_11be_enable || iwlwifi_mod_params.disable_11be) iftype_data->eht_cap.has_eht = false; @@ -879,8 +919,12 @@ iwl_nvm_fixup_sband_iftd(struct iwl_trans *trans, IEEE80211_EHT_MAC_CAP0_MAX_MPDU_LEN_MASK); break; case NL80211_BAND_6GHZ: - iftype_data->eht_cap.eht_cap_elem.phy_cap_info[0] |= - IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ; + if (!no_320) { + iftype_data->eht_cap.eht_cap_elem.phy_cap_info[0] |= + IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ; + iftype_data->eht_cap.eht_cap_elem.phy_cap_info[1] |= + IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_320MHZ_MASK; + } fallthrough; case NL80211_BAND_5GHZ: iftype_data->he_cap.he_cap_elem.phy_cap_info[0] |= @@ -975,6 +1019,8 @@ iwl_nvm_fixup_sband_iftd(struct iwl_trans *trans, iftype_data->eht_cap.eht_cap_elem.phy_cap_info[6] &= ~(IEEE80211_EHT_PHY_CAP6_MCS15_SUPP_MASK | IEEE80211_EHT_PHY_CAP6_EHT_DUP_6GHZ_SUPP); + iftype_data->eht_cap.eht_cap_elem.phy_cap_info[5] |= + IEEE80211_EHT_PHY_CAP5_SUPP_EXTRA_EHT_LTF; } if (fw_has_capa(&fw->ucode_capa, IWL_UCODE_TLV_CAPA_BROADCAST_TWT)) @@ -986,6 +1032,13 @@ iwl_nvm_fixup_sband_iftd(struct iwl_trans *trans, iftype_data->vendor_elems.data = iwl_vendor_caps; iftype_data->vendor_elems.len = ARRAY_SIZE(iwl_vendor_caps); } + + if (!trans->cfg->ht_params->stbc) { + iftype_data->he_cap.he_cap_elem.phy_cap_info[2] &= + ~IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ; + iftype_data->he_cap.he_cap_elem.phy_cap_info[7] &= + ~IEEE80211_HE_PHY_CAP7_STBC_RX_ABOVE_80MHZ; + } } static void iwl_init_he_hw_capab(struct iwl_trans *trans, @@ -1521,27 +1574,41 @@ static u32 iwl_nvm_get_regdom_bw_flags(const u16 *nvm_chan, if (!reg_capa.allow_160mhz) flags |= NL80211_RRF_NO_160MHZ; + + if (!reg_capa.allow_320mhz) + flags |= NL80211_RRF_NO_320MHZ; } + if (reg_capa.disable_11ax) flags |= NL80211_RRF_NO_HE; + if (reg_capa.disable_11be) + flags |= NL80211_RRF_NO_EHT; + return flags; } -static struct iwl_reg_capa iwl_get_reg_capa(u16 flags, u8 resp_ver) +static struct iwl_reg_capa iwl_get_reg_capa(u32 flags, u8 resp_ver) { - struct iwl_reg_capa reg_capa; - - if (resp_ver >= REG_CAPA_V2_RESP_VER) { + struct iwl_reg_capa reg_capa = {}; + + if (resp_ver >= REG_CAPA_V4_RESP_VER) { + reg_capa.allow_40mhz = true; + reg_capa.allow_80mhz = flags & REG_CAPA_V4_80MHZ_ALLOWED; + reg_capa.allow_160mhz = flags & REG_CAPA_V4_160MHZ_ALLOWED; + reg_capa.allow_320mhz = flags & REG_CAPA_V4_320MHZ_ALLOWED; + reg_capa.disable_11ax = flags & REG_CAPA_V4_11AX_DISABLED; + reg_capa.disable_11be = flags & REG_CAPA_V4_11BE_DISABLED; + } else if (resp_ver >= REG_CAPA_V2_RESP_VER) { reg_capa.allow_40mhz = flags & REG_CAPA_V2_40MHZ_ALLOWED; reg_capa.allow_80mhz = flags & REG_CAPA_V2_80MHZ_ALLOWED; reg_capa.allow_160mhz = flags & REG_CAPA_V2_160MHZ_ALLOWED; reg_capa.disable_11ax = flags & REG_CAPA_V2_11AX_DISABLED; } else { - reg_capa.allow_40mhz = !(flags & REG_CAPA_40MHZ_FORBIDDEN); - reg_capa.allow_80mhz = flags & REG_CAPA_80MHZ_ALLOWED; - reg_capa.allow_160mhz = flags & REG_CAPA_160MHZ_ALLOWED; - reg_capa.disable_11ax = flags & REG_CAPA_11AX_DISABLED; + reg_capa.allow_40mhz = !(flags & REG_CAPA_V1_40MHZ_FORBIDDEN); + reg_capa.allow_80mhz = flags & REG_CAPA_V1_80MHZ_ALLOWED; + reg_capa.allow_160mhz = flags & REG_CAPA_V1_160MHZ_ALLOWED; + reg_capa.disable_11ax = flags & REG_CAPA_V1_11AX_DISABLED; } return reg_capa; } @@ -1549,7 +1616,7 @@ static struct iwl_reg_capa iwl_get_reg_capa(u16 flags, u8 resp_ver) struct ieee80211_regdomain * iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg, int num_of_ch, __le32 *channels, u16 fw_mcc, - u16 geo_info, u16 cap, u8 resp_ver) + u16 geo_info, u32 cap, u8 resp_ver) { int ch_idx; u16 ch_flags; diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.h b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.h index e01f7751cf11309cc5535c56e7fb9a74c3a6f15e..c79f72d5448273870507d100888def3e3774952e 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ /* - * Copyright (C) 2005-2015, 2018-2021 Intel Corporation + * Copyright (C) 2005-2015, 2018-2022 Intel Corporation * Copyright (C) 2016-2017 Intel Deutschland GmbH */ #ifndef __iwl_nvm_parse_h__ @@ -50,7 +50,7 @@ iwl_parse_nvm_data(struct iwl_trans *trans, const struct iwl_cfg *cfg, struct ieee80211_regdomain * iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg, int num_of_ch, __le32 *channels, u16 fw_mcc, - u16 geo_info, u16 cap, u8 resp_ver); + u16 geo_info, u32 cap, u8 resp_ver); /** * struct iwl_nvm_section - describes an NVM section in memory. diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-prph.h b/drivers/net/wireless/intel/iwlwifi/iwl-prph.h index 0dfe00eae05d61b2bcc05beca456efd74f2910d3..6dd381ff0f9e70d5c0f563a8f081b4eb4ff5ce7c 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-prph.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-prph.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ /* - * Copyright (C) 2005-2014, 2018-2022 Intel Corporation + * Copyright (C) 2005-2014, 2018-2023 Intel Corporation * Copyright (C) 2013-2015 Intel Mobile Communications GmbH * Copyright (C) 2016 Intel Deutschland GmbH */ @@ -486,6 +486,10 @@ enum { #define FSEQ_ALIVE_TOKEN 0xA340F0 #define FSEQ_CNVI_ID 0xA3408C #define FSEQ_CNVR_ID 0xA34090 +#define FSEQ_PREV_CNVIO_INIT_VERSION 0xA34084 +#define FSEQ_WIFI_FSEQ_VERSION 0xA34040 +#define FSEQ_BT_FSEQ_VERSION 0xA34044 +#define FSEQ_CLASS_TP_VERSION 0xA34078 #define IWL_D3_SLEEP_STATUS_SUSPEND 0xD3 #define IWL_D3_SLEEP_STATUS_RESUME 0xD0 diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c index b1af9359cea5e0c9d77487832bf487d6331aefca..4bd759432d44b0dc79b19600ec09a973815cb07f 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c @@ -2,7 +2,7 @@ /* * Copyright (C) 2015 Intel Mobile Communications GmbH * Copyright (C) 2016-2017 Intel Deutschland GmbH - * Copyright (C) 2019-2021 Intel Corporation + * Copyright (C) 2019-2021, 2023 Intel Corporation */ #include #include @@ -42,7 +42,7 @@ struct iwl_trans *iwl_trans_alloc(unsigned int priv_size, WARN_ON(!ops->wait_txq_empty && !ops->wait_tx_queues_empty); - if (trans->trans_cfg->use_tfh) { + if (trans->trans_cfg->gen2) { trans->txqs.tfd.addr_size = 64; trans->txqs.tfd.max_tbs = IWL_TFH_NUM_TBS; trans->txqs.tfd.size = sizeof(struct iwl_tfh_tfd); @@ -101,7 +101,7 @@ int iwl_trans_init(struct iwl_trans *trans) /* Some things must not change even if the config does */ WARN_ON(trans->txqs.tfd.addr_size != - (trans->trans_cfg->use_tfh ? 64 : 36)); + (trans->trans_cfg->gen2 ? 64 : 36)); snprintf(trans->dev_cmd_pool_name, sizeof(trans->dev_cmd_pool_name), "iwl_cmd_pool:%s", dev_name(trans->dev)); diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h index 9f1228b5a38432a5c8579849af69633255b25ba5..d02943d0ea625efedb92e09d0def1487a894b488 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h @@ -459,6 +459,24 @@ struct iwl_trans_rxq_dma_data { u64 ur_bd_cb; }; +/* maximal number of DRAM MAP entries supported by FW */ +#define IPC_DRAM_MAP_ENTRY_NUM_MAX 64 + +/** + * struct iwl_pnvm_image - contains info about the parsed pnvm image + * @chunks: array of pointers to pnvm payloads and their sizes + * @n_chunks: the number of the pnvm payloads. + * @version: the version of the loaded PNVM image + */ +struct iwl_pnvm_image { + struct { + const void *data; + u32 len; + } chunks[IPC_DRAM_MAP_ENTRY_NUM_MAX]; + u32 n_chunks; + u32 version; +}; + /** * struct iwl_trans_ops - transport specific operations * @@ -541,8 +559,11 @@ struct iwl_trans_rxq_dma_data { * Note that the transport must fill in the proper file headers. * @debugfs_cleanup: used in the driver unload flow to make a proper cleanup * of the trans debugfs + * @load_pnvm: save the pnvm data in DRAM * @set_pnvm: set the pnvm data in the prph scratch buffer, inside the * context info. + * @load_reduce_power: copy reduce power table to the corresponding DRAM memory + * @set_reduce_power: set reduce power table addresses in the sratch buffer * @interrupts: disable/enable interrupts to transport */ struct iwl_trans_ops { @@ -614,9 +635,17 @@ struct iwl_trans_ops { void *sanitize_ctx); void (*debugfs_cleanup)(struct iwl_trans *trans); void (*sync_nmi)(struct iwl_trans *trans); - int (*set_pnvm)(struct iwl_trans *trans, const void *data, u32 len); - int (*set_reduce_power)(struct iwl_trans *trans, - const void *data, u32 len); + int (*load_pnvm)(struct iwl_trans *trans, + const struct iwl_pnvm_image *pnvm_payloads, + const struct iwl_ucode_capabilities *capa); + void (*set_pnvm)(struct iwl_trans *trans, + const struct iwl_ucode_capabilities *capa); + int (*load_reduce_power)(struct iwl_trans *trans, + const struct iwl_pnvm_image *payloads, + const struct iwl_ucode_capabilities *capa); + void (*set_reduce_power)(struct iwl_trans *trans, + const struct iwl_ucode_capabilities *capa); + void (*interrupts)(struct iwl_trans *trans, bool enable); int (*imr_dma_data)(struct iwl_trans *trans, u32 dst_addr, u64 src_addr, @@ -704,6 +733,19 @@ struct iwl_dram_data { int size; }; +/** + * @drams: array of several DRAM areas that contains the pnvm and power + * reduction table payloads. + * @n_regions: number of DRAM regions that were allocated + * @prph_scratch_mem_desc: points to a structure allocated in dram, + * designed to show FW where all the payloads are. + */ +struct iwl_dram_regions { + struct iwl_dram_data drams[IPC_DRAM_MAP_ENTRY_NUM_MAX]; + struct iwl_dram_data prph_scratch_mem_desc; + u8 n_regions; +}; + /** * struct iwl_fw_mon - fw monitor per allocation id * @num_frags: number of fragments @@ -1004,6 +1046,8 @@ struct iwl_trans_txqs { * @hw_rev_step: The mac step of the HW * @pm_support: set to true in start_hw if link pm is supported * @ltr_enabled: set to true if the LTR is enabled + * @fail_to_parse_pnvm_image: set to true if pnvm parsing failed + * @failed_to_load_reduce_power_image: set to true if pnvm loading failed * @wide_cmd_header: true when ucode supports wide command header format * @wait_command_queue: wait queue for sync commands * @num_rx_queues: number of RX queues allocated by the transport; @@ -1023,6 +1067,8 @@ struct iwl_trans_txqs { * @iwl_trans_txqs: transport tx queues data. * @mbx_addr_0_step: step address data 0 * @mbx_addr_1_step: step address data 1 + * @pcie_link_speed: current PCIe link speed (%PCI_EXP_LNKSTA_CLS_*), + * only valid for discrete (not integrated) NICs */ struct iwl_trans { bool csme_own; @@ -1051,7 +1097,9 @@ struct iwl_trans { bool pm_support; bool ltr_enabled; u8 pnvm_loaded:1; + u8 fail_to_parse_pnvm_image:1; u8 reduce_power_loaded:1; + u8 failed_to_load_reduce_power_image:1; const struct iwl_hcmd_arr *command_groups; int command_groups_size; @@ -1083,6 +1131,8 @@ struct iwl_trans { u32 mbx_addr_0_step; u32 mbx_addr_1_step; + u8 pcie_link_speed; + /* pointer to trans specific struct */ /*Ensure that this pointer will always be aligned to sizeof pointer */ char trans_specific[] __aligned(sizeof(void *)); @@ -1160,7 +1210,7 @@ static inline int iwl_trans_d3_suspend(struct iwl_trans *trans, bool test, { might_sleep(); if (!trans->ops->d3_suspend) - return 0; + return -EOPNOTSUPP; return trans->ops->d3_suspend(trans, test, reset); } @@ -1171,7 +1221,7 @@ static inline int iwl_trans_d3_resume(struct iwl_trans *trans, { might_sleep(); if (!trans->ops->d3_resume) - return 0; + return -EOPNOTSUPP; return trans->ops->d3_resume(trans, status, test, reset); } @@ -1515,33 +1565,34 @@ static inline void iwl_trans_sync_nmi(struct iwl_trans *trans) void iwl_trans_sync_nmi_with_addr(struct iwl_trans *trans, u32 inta_addr, u32 sw_err_bit); -static inline int iwl_trans_set_pnvm(struct iwl_trans *trans, - const void *data, u32 len) +static inline int iwl_trans_load_pnvm(struct iwl_trans *trans, + const struct iwl_pnvm_image *pnvm_data, + const struct iwl_ucode_capabilities *capa) { - if (trans->ops->set_pnvm) { - int ret = trans->ops->set_pnvm(trans, data, len); - - if (ret) - return ret; - } - - trans->pnvm_loaded = true; - - return 0; + return trans->ops->load_pnvm(trans, pnvm_data, capa); } -static inline int iwl_trans_set_reduce_power(struct iwl_trans *trans, - const void *data, u32 len) +static inline void iwl_trans_set_pnvm(struct iwl_trans *trans, + const struct iwl_ucode_capabilities *capa) { - if (trans->ops->set_reduce_power) { - int ret = trans->ops->set_reduce_power(trans, data, len); + if (trans->ops->set_pnvm) + trans->ops->set_pnvm(trans, capa); +} - if (ret) - return ret; - } +static inline int iwl_trans_load_reduce_power + (struct iwl_trans *trans, + const struct iwl_pnvm_image *payloads, + const struct iwl_ucode_capabilities *capa) +{ + return trans->ops->load_reduce_power(trans, payloads, capa); +} - trans->reduce_power_loaded = true; - return 0; +static inline void +iwl_trans_set_reduce_power(struct iwl_trans *trans, + const struct iwl_ucode_capabilities *capa) +{ + if (trans->ops->set_reduce_power) + trans->ops->set_reduce_power(trans, capa); } static inline bool iwl_trans_dbg_ini_valid(struct iwl_trans *trans) @@ -1566,6 +1617,11 @@ struct iwl_trans *iwl_trans_alloc(unsigned int priv_size, int iwl_trans_init(struct iwl_trans *trans); void iwl_trans_free(struct iwl_trans *trans); +static inline bool iwl_trans_is_hw_error_value(u32 val) +{ + return ((val & ~0xf) == 0xa5a5a5a0) || ((val & ~0xf) == 0x5a5a5a50); +} + /***************************************************** * driver (transport) register/unregister functions ******************************************************/ diff --git a/drivers/net/wireless/intel/iwlwifi/mei/main.c b/drivers/net/wireless/intel/iwlwifi/mei/main.c index 0a29fb013005db706d977532c67fe9d20b0001e8..54445f39fd551acdc73b9f0284f1a9a09b33ba70 100644 --- a/drivers/net/wireless/intel/iwlwifi/mei/main.c +++ b/drivers/net/wireless/intel/iwlwifi/mei/main.c @@ -1791,9 +1791,8 @@ int iwl_mei_register(void *priv, const struct iwl_mei_ops *ops) if (iwl_mei_is_connected()) { if (mei->amt_enabled) iwl_mei_send_sap_msg(mei->cldev, - SAP_MSG_NOTIF_WIFIDR_UP, - false); - ops->rfkill(priv, mei->link_prot_state); + SAP_MSG_NOTIF_WIFIDR_UP); + ops->rfkill(priv, mei->link_prot_state, false); } } ret = 0; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/binding.c b/drivers/net/wireless/intel/iwlwifi/mvm/binding.c index ef50ccabcc73bae65673843f67c9c5cb2e338886..458b97930059ecde4acb100fa2b90a69130eddf3 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/binding.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/binding.c @@ -32,7 +32,7 @@ static int iwl_mvm_binding_cmd(struct iwl_mvm *mvm, u32 action, if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_BINDING_CDB_SUPPORT)) { size = sizeof(cmd); - cmd.lmac_id = cpu_to_le32(iwl_mvm_get_lmac_id(mvm->fw, + cmd.lmac_id = cpu_to_le32(iwl_mvm_get_lmac_id(mvm, phyctxt->channel->band)); } else { size = IWL_BINDING_CMD_SIZE_V1; @@ -164,3 +164,11 @@ int iwl_mvm_binding_remove_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif) return ret; } + +u32 iwl_mvm_get_lmac_id(struct iwl_mvm *mvm, enum nl80211_band band) +{ + if (!fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_CDB_SUPPORT) || + band == NL80211_BAND_2GHZ) + return IWL_LMAC_24G_INDEX; + return IWL_LMAC_5G_INDEX; +} diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/constants.h b/drivers/net/wireless/intel/iwlwifi/mvm/constants.h index c604f9f39b248bca3923bb3f9a8dd151e81b5781..243eccc68cb050d884a31bae0704c3c2789aefaf 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/constants.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/constants.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ /* * Copyright (C) 2013-2015 Intel Mobile Communications GmbH - * Copyright (C) 2013-2014, 2018-2021 Intel Corporation + * Copyright (C) 2013-2014, 2018-2023 Intel Corporation * Copyright (C) 2015 Intel Deutschland GmbH */ #ifndef __MVM_CONSTANTS_H @@ -109,10 +109,6 @@ #define IWL_MVM_USE_TWT true #define IWL_MVM_AMPDU_CONSEC_DROPS_DELBA 20 #define IWL_MVM_USE_NSSN_SYNC 0 -#define IWL_MVM_PHY_FILTER_CHAIN_A 0 -#define IWL_MVM_PHY_FILTER_CHAIN_B 0 -#define IWL_MVM_PHY_FILTER_CHAIN_C 0 -#define IWL_MVM_PHY_FILTER_CHAIN_D 0 #define IWL_MVM_FTM_INITIATOR_ENABLE_SMOOTH false #define IWL_MVM_FTM_INITIATOR_SMOOTH_ALPHA 40 /* 20016 pSec is 6 meter RTT, meaning 3 meter range */ diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c index 6d1007f24b4aa91ba33e4e60d1019eb309a35984..f6488b4bbe68bcc3ae236949a6e85146b37cd853 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* - * Copyright (C) 2012-2014, 2018-2022 Intel Corporation + * Copyright (C) 2012-2014, 2018-2023 Intel Corporation * Copyright (C) 2013-2015 Intel Mobile Communications GmbH * Copyright (C) 2016-2017 Intel Deutschland GmbH */ @@ -1380,6 +1380,14 @@ int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) return __iwl_mvm_suspend(hw, wowlan, false); } +struct iwl_multicast_key_data { + u8 key[WOWLAN_KEY_MAX_SIZE]; + u8 len; + u8 flags; + u8 id; + u8 ipn[6]; +}; + /* converted data from the different status responses */ struct iwl_wowlan_status_data { u64 replay_ctr; @@ -1398,7 +1406,8 @@ struct iwl_wowlan_status_data { u8 key[WOWLAN_KEY_MAX_SIZE]; u8 len; u8 flags; - } gtk; + u8 id; + } gtk[WOWLAN_GTK_KEYS_NUM]; struct { /* @@ -1428,12 +1437,7 @@ struct iwl_wowlan_status_data { } tkip, aes; } ptk; - struct { - u64 ipn; - u8 key[WOWLAN_KEY_MAX_SIZE]; - u8 len; - u8 flags; - } igtk; + struct iwl_multicast_key_data igtk; u8 *wake_packet; }; @@ -1758,7 +1762,7 @@ static void iwl_mvm_set_key_rx_seq(struct ieee80211_key_conf *key, s8 new_key_id = -1; if (status->num_of_gtk_rekeys) - new_key_id = status->gtk.flags & + new_key_id = status->gtk[0].flags & IWL_WOWLAN_GTK_IDX_MASK; /* Don't install a new key's value to an old key */ @@ -1777,20 +1781,18 @@ static void iwl_mvm_set_key_rx_seq(struct ieee80211_key_conf *key, struct iwl_mvm_d3_gtk_iter_data { struct iwl_mvm *mvm; struct iwl_wowlan_status_data *status; - void *last_gtk; - u32 cipher; - bool find_phase, unhandled_cipher; + u32 gtk_cipher, igtk_cipher; + bool unhandled_cipher, igtk_support; int num_keys; }; -static void iwl_mvm_d3_update_keys(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta, - struct ieee80211_key_conf *key, - void *_data) +static void iwl_mvm_d3_find_last_keys(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + struct ieee80211_key_conf *key, + void *_data) { struct iwl_mvm_d3_gtk_iter_data *data = _data; - struct iwl_wowlan_status_data *status = data->status; if (data->unhandled_cipher) return; @@ -1805,51 +1807,230 @@ static void iwl_mvm_d3_update_keys(struct ieee80211_hw *hw, case WLAN_CIPHER_SUITE_GCMP_256: case WLAN_CIPHER_SUITE_TKIP: /* we support these */ + data->gtk_cipher = key->cipher; + break; + case WLAN_CIPHER_SUITE_BIP_GMAC_128: + case WLAN_CIPHER_SUITE_BIP_GMAC_256: + case WLAN_CIPHER_SUITE_BIP_CMAC_256: + case WLAN_CIPHER_SUITE_AES_CMAC: + /* we support these */ + if (data->igtk_support && + (key->keyidx == 4 || key->keyidx == 5)) { + data->igtk_cipher = key->cipher; + } else { + data->unhandled_cipher = true; + return; + } break; default: - /* everything else (even CMAC for MFP) - disconnect from AP */ + /* everything else - disconnect from AP */ data->unhandled_cipher = true; return; } data->num_keys++; +} - /* - * pairwise key - update sequence counters only; - * note that this assumes no TDLS sessions are active - */ - if (sta) { - if (data->find_phase) - return; +static void +iwl_mvm_d3_set_igtk_bigtk_ipn(const struct iwl_multicast_key_data *key, + struct ieee80211_key_seq *seq, u32 cipher) +{ + switch (cipher) { + case WLAN_CIPHER_SUITE_BIP_GMAC_128: + case WLAN_CIPHER_SUITE_BIP_GMAC_256: + BUILD_BUG_ON(sizeof(seq->aes_gmac.pn) != sizeof(key->ipn)); + memcpy(seq->aes_gmac.pn, key->ipn, sizeof(seq->aes_gmac.pn)); + break; + case WLAN_CIPHER_SUITE_BIP_CMAC_256: + BUILD_BUG_ON(sizeof(seq->aes_cmac.pn) != sizeof(key->ipn)); + memcpy(seq->aes_cmac.pn, key->ipn, sizeof(seq->aes_cmac.pn)); + break; + } +} + +static void iwl_mvm_d3_update_keys(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + struct ieee80211_key_conf *key, + void *_data) +{ + struct iwl_mvm_d3_gtk_iter_data *data = _data; + struct iwl_wowlan_status_data *status = data->status; + s8 keyidx; + + if (data->unhandled_cipher) + return; - switch (key->cipher) { - case WLAN_CIPHER_SUITE_CCMP: - case WLAN_CIPHER_SUITE_GCMP: - case WLAN_CIPHER_SUITE_GCMP_256: + switch (key->cipher) { + case WLAN_CIPHER_SUITE_WEP40: + case WLAN_CIPHER_SUITE_WEP104: + /* ignore WEP completely, nothing to do */ + return; + case WLAN_CIPHER_SUITE_CCMP: + case WLAN_CIPHER_SUITE_GCMP: + case WLAN_CIPHER_SUITE_GCMP_256: + if (sta) { atomic64_set(&key->tx_pn, status->ptk.aes.tx_pn); iwl_mvm_set_aes_ptk_rx_seq(data->mvm, status, sta, key); - break; - case WLAN_CIPHER_SUITE_TKIP: + return; + } + fallthrough; + case WLAN_CIPHER_SUITE_TKIP: + if (sta) { atomic64_set(&key->tx_pn, status->ptk.tkip.tx_pn); iwl_mvm_set_key_rx_seq_tids(key, status->ptk.tkip.seq); - break; + return; } + keyidx = key->keyidx; + /* The current key is always sent by the FW, even if it wasn't + * rekeyed during D3. + * We remove an existing key if it has the same index as + * a new key + */ + if (status->num_of_gtk_rekeys && + ((status->gtk[0].len && keyidx == status->gtk[0].id) || + (status->gtk[1].len && keyidx == status->gtk[1].id))) { + ieee80211_remove_key(key); + } else { + iwl_mvm_set_key_rx_seq(key, data->status, false); + } + break; + case WLAN_CIPHER_SUITE_BIP_GMAC_128: + case WLAN_CIPHER_SUITE_BIP_GMAC_256: + case WLAN_CIPHER_SUITE_BIP_CMAC_256: + case WLAN_CIPHER_SUITE_AES_CMAC: + if (key->keyidx == 4 || key->keyidx == 5) { + /* remove rekeyed key */ + if (status->num_of_gtk_rekeys) { + ieee80211_remove_key(key); + } else { + struct ieee80211_key_seq seq; - /* that's it for this key */ - return; + iwl_mvm_d3_set_igtk_bigtk_ipn(&status->igtk, + &seq, + key->cipher); + ieee80211_set_key_rx_seq(key, 0, &seq); + } + } } +} - if (data->find_phase) { - data->last_gtk = key; - data->cipher = key->cipher; - return; +static bool iwl_mvm_gtk_rekey(struct iwl_wowlan_status_data *status, + struct ieee80211_vif *vif, + struct iwl_mvm *mvm, u32 gtk_cipher) +{ + int i; + struct ieee80211_key_conf *key; + struct { + struct ieee80211_key_conf conf; + u8 key[32]; + } conf = { + .conf.cipher = gtk_cipher, + }; + + BUILD_BUG_ON(WLAN_KEY_LEN_CCMP != WLAN_KEY_LEN_GCMP); + BUILD_BUG_ON(sizeof(conf.key) < WLAN_KEY_LEN_CCMP); + BUILD_BUG_ON(sizeof(conf.key) < WLAN_KEY_LEN_GCMP_256); + BUILD_BUG_ON(sizeof(conf.key) < WLAN_KEY_LEN_TKIP); + BUILD_BUG_ON(sizeof(conf.key) < sizeof(status->gtk[0].key)); + + switch (gtk_cipher) { + case WLAN_CIPHER_SUITE_CCMP: + case WLAN_CIPHER_SUITE_GCMP: + conf.conf.keylen = WLAN_KEY_LEN_CCMP; + break; + case WLAN_CIPHER_SUITE_GCMP_256: + conf.conf.keylen = WLAN_KEY_LEN_GCMP_256; + break; + case WLAN_CIPHER_SUITE_TKIP: + conf.conf.keylen = WLAN_KEY_LEN_TKIP; + break; + default: + WARN_ON(1); + } + + for (i = 0; i < ARRAY_SIZE(status->gtk); i++) { + if (!status->gtk[i].len) + continue; + + conf.conf.keyidx = status->gtk[i].id; + IWL_DEBUG_WOWLAN(mvm, + "Received from FW GTK cipher %d, key index %d\n", + conf.conf.cipher, conf.conf.keyidx); + memcpy(conf.conf.key, status->gtk[i].key, + sizeof(status->gtk[i].key)); + + key = ieee80211_gtk_rekey_add(vif, &conf.conf); + if (IS_ERR(key)) + return false; + iwl_mvm_set_key_rx_seq_idx(key, status, i); } - if (data->status->num_of_gtk_rekeys) - ieee80211_remove_key(key); + return true; +} + +static bool +iwl_mvm_d3_igtk_bigtk_rekey_add(struct iwl_wowlan_status_data *status, + struct ieee80211_vif *vif, u32 cipher, + struct iwl_multicast_key_data *key_data) +{ + struct ieee80211_key_conf *key_config; + struct { + struct ieee80211_key_conf conf; + u8 key[WOWLAN_KEY_MAX_SIZE]; + } conf = { + .conf.cipher = cipher, + .conf.keyidx = key_data->id, + }; + struct ieee80211_key_seq seq; + + if (!key_data->len) + return true; + + iwl_mvm_d3_set_igtk_bigtk_ipn(key_data, &seq, conf.conf.cipher); + + switch (cipher) { + case WLAN_CIPHER_SUITE_BIP_GMAC_128: + conf.conf.keylen = WLAN_KEY_LEN_BIP_GMAC_128; + break; + case WLAN_CIPHER_SUITE_BIP_GMAC_256: + conf.conf.keylen = WLAN_KEY_LEN_BIP_GMAC_256; + break; + case WLAN_CIPHER_SUITE_AES_CMAC: + conf.conf.keylen = WLAN_KEY_LEN_AES_CMAC; + break; + case WLAN_CIPHER_SUITE_BIP_CMAC_256: + conf.conf.keylen = WLAN_KEY_LEN_BIP_CMAC_256; + break; + default: + WARN_ON(1); + } + BUILD_BUG_ON(sizeof(conf.key) < sizeof(key_data->key)); + memcpy(conf.conf.key, key_data->key, conf.conf.keylen); + + key_config = ieee80211_gtk_rekey_add(vif, &conf.conf); + if (IS_ERR(key_config)) + return false; + ieee80211_set_key_rx_seq(key_config, 0, &seq); + return true; +} + +static int iwl_mvm_lookup_wowlan_status_ver(struct iwl_mvm *mvm) +{ + u8 notif_ver; + + if (!fw_has_api(&mvm->fw->ucode_capa, + IWL_UCODE_TLV_API_WOWLAN_KEY_MATERIAL)) + return 6; + + /* default to 7 (when we have IWL_UCODE_TLV_API_WOWLAN_KEY_MATERIAL) */ + notif_ver = iwl_fw_lookup_notif_ver(mvm->fw, LONG_GROUP, + WOWLAN_GET_STATUSES, 0); + if (!notif_ver) + notif_ver = iwl_fw_lookup_notif_ver(mvm->fw, LEGACY_GROUP, + WOWLAN_GET_STATUSES, 7); - if (data->last_gtk == key) - iwl_mvm_set_key_rx_seq(key, data->status, false); + return notif_ver; } static bool iwl_mvm_setup_connection_keep(struct iwl_mvm *mvm, @@ -1871,71 +2052,41 @@ static bool iwl_mvm_setup_connection_keep(struct iwl_mvm *mvm, if (status->wakeup_reasons & disconnection_reasons) return false; + if (iwl_mvm_lookup_wowlan_status_ver(mvm) > 6 || + iwl_fw_lookup_notif_ver(mvm->fw, PROT_OFFLOAD_GROUP, + WOWLAN_INFO_NOTIFICATION, + 0)) + gtkdata.igtk_support = true; + /* find last GTK that we used initially, if any */ - gtkdata.find_phase = true; ieee80211_iter_keys(mvm->hw, vif, - iwl_mvm_d3_update_keys, >kdata); + iwl_mvm_d3_find_last_keys, >kdata); /* not trying to keep connections with MFP/unhandled ciphers */ if (gtkdata.unhandled_cipher) return false; if (!gtkdata.num_keys) goto out; - if (!gtkdata.last_gtk) - return false; /* * invalidate all other GTKs that might still exist and update * the one that we used */ - gtkdata.find_phase = false; ieee80211_iter_keys(mvm->hw, vif, iwl_mvm_d3_update_keys, >kdata); - IWL_DEBUG_WOWLAN(mvm, "num of GTK rekeying %d\n", - status->num_of_gtk_rekeys); if (status->num_of_gtk_rekeys) { - struct ieee80211_key_conf *key; - struct { - struct ieee80211_key_conf conf; - u8 key[32]; - } conf = { - .conf.cipher = gtkdata.cipher, - .conf.keyidx = - status->gtk.flags & IWL_WOWLAN_GTK_IDX_MASK, - }; - __be64 replay_ctr; + __be64 replay_ctr = cpu_to_be64(status->replay_ctr); - IWL_DEBUG_WOWLAN(mvm, - "Received from FW GTK cipher %d, key index %d\n", - conf.conf.cipher, conf.conf.keyidx); - - BUILD_BUG_ON(WLAN_KEY_LEN_CCMP != WLAN_KEY_LEN_GCMP); - BUILD_BUG_ON(sizeof(conf.key) < WLAN_KEY_LEN_CCMP); - BUILD_BUG_ON(sizeof(conf.key) < WLAN_KEY_LEN_GCMP_256); - BUILD_BUG_ON(sizeof(conf.key) < WLAN_KEY_LEN_TKIP); - BUILD_BUG_ON(sizeof(conf.key) < sizeof(status->gtk.key)); + IWL_DEBUG_WOWLAN(mvm, "num of GTK rekeying %d\n", + status->num_of_gtk_rekeys); - memcpy(conf.conf.key, status->gtk.key, sizeof(status->gtk.key)); - - switch (gtkdata.cipher) { - case WLAN_CIPHER_SUITE_CCMP: - case WLAN_CIPHER_SUITE_GCMP: - conf.conf.keylen = WLAN_KEY_LEN_CCMP; - break; - case WLAN_CIPHER_SUITE_GCMP_256: - conf.conf.keylen = WLAN_KEY_LEN_GCMP_256; - break; - case WLAN_CIPHER_SUITE_TKIP: - conf.conf.keylen = WLAN_KEY_LEN_TKIP; - break; - } - - key = ieee80211_gtk_rekey_add(vif, &conf.conf); - if (IS_ERR(key)) + if (!iwl_mvm_gtk_rekey(status, vif, mvm, gtkdata.gtk_cipher)) return false; - iwl_mvm_set_key_rx_seq(key, status, true); - replay_ctr = cpu_to_be64(status->replay_ctr); + if (!iwl_mvm_d3_igtk_bigtk_rekey_add(status, vif, + gtkdata.igtk_cipher, + &status->igtk)) + return false; ieee80211_gtk_rekey_notify(vif, vif->bss_conf.bssid, (void *)&replay_ctr, GFP_KERNEL); @@ -1955,60 +2106,70 @@ static bool iwl_mvm_setup_connection_keep(struct iwl_mvm *mvm, static void iwl_mvm_convert_gtk_v2(struct iwl_wowlan_status_data *status, struct iwl_wowlan_gtk_status_v2 *data) { - BUILD_BUG_ON(sizeof(status->gtk.key) < sizeof(data->key)); + BUILD_BUG_ON(sizeof(status->gtk[0].key) < sizeof(data->key)); BUILD_BUG_ON(NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY + sizeof(data->tkip_mic_key) > - sizeof(status->gtk.key)); + sizeof(status->gtk[0].key)); - status->gtk.len = data->key_len; - status->gtk.flags = data->key_flags; + status->gtk[0].len = data->key_len; + status->gtk[0].flags = data->key_flags; - memcpy(status->gtk.key, data->key, sizeof(data->key)); + memcpy(status->gtk[0].key, data->key, sizeof(data->key)); /* if it's as long as the TKIP encryption key, copy MIC key */ - if (status->gtk.len == NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY) - memcpy(status->gtk.key + NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY, + if (status->gtk[0].len == NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY) + memcpy(status->gtk[0].key + NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY, data->tkip_mic_key, sizeof(data->tkip_mic_key)); } static void iwl_mvm_convert_gtk_v3(struct iwl_wowlan_status_data *status, struct iwl_wowlan_gtk_status_v3 *data) { - /* The parts we need are identical in v2 and v3 */ -#define CHECK(_f) do { \ - BUILD_BUG_ON(offsetof(struct iwl_wowlan_gtk_status_v2, _f) != \ - offsetof(struct iwl_wowlan_gtk_status_v3, _f)); \ - BUILD_BUG_ON(offsetofend(struct iwl_wowlan_gtk_status_v2, _f) !=\ - offsetofend(struct iwl_wowlan_gtk_status_v3, _f)); \ -} while (0) + int data_idx, status_idx = 0; - CHECK(key); - CHECK(key_len); - CHECK(key_flags); - CHECK(tkip_mic_key); -#undef CHECK + BUILD_BUG_ON(sizeof(status->gtk[0].key) < sizeof(data[0].key)); + BUILD_BUG_ON(NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY + + sizeof(data[0].tkip_mic_key) > + sizeof(status->gtk[0].key)); + BUILD_BUG_ON(ARRAY_SIZE(status->gtk) < WOWLAN_GTK_KEYS_NUM); + for (data_idx = 0; data_idx < ARRAY_SIZE(status->gtk); data_idx++) { + if (!(data[data_idx].key_len)) + continue; + status->gtk[status_idx].len = data[data_idx].key_len; + status->gtk[status_idx].flags = data[data_idx].key_flags; + status->gtk[status_idx].id = status->gtk[status_idx].flags & + IWL_WOWLAN_GTK_IDX_MASK; - iwl_mvm_convert_gtk_v2(status, (void *)data); + memcpy(status->gtk[status_idx].key, data[data_idx].key, + sizeof(data[data_idx].key)); + + /* if it's as long as the TKIP encryption key, copy MIC key */ + if (status->gtk[status_idx].len == + NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY) + memcpy(status->gtk[status_idx].key + + NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY, + data[data_idx].tkip_mic_key, + sizeof(data[data_idx].tkip_mic_key)); + status_idx++; + } } static void iwl_mvm_convert_igtk(struct iwl_wowlan_status_data *status, struct iwl_wowlan_igtk_status *data) { - const u8 *ipn = data->ipn; - BUILD_BUG_ON(sizeof(status->igtk.key) < sizeof(data->key)); + if (!data->key_len) + return; + status->igtk.len = data->key_len; status->igtk.flags = data->key_flags; + status->igtk.id = u32_get_bits(data->key_flags, + IWL_WOWLAN_IGTK_BIGTK_IDX_MASK) + + WOWLAN_IGTK_MIN_INDEX; memcpy(status->igtk.key, data->key, sizeof(data->key)); - - status->igtk.ipn = ((u64)ipn[5] << 0) | - ((u64)ipn[4] << 8) | - ((u64)ipn[3] << 16) | - ((u64)ipn[2] << 24) | - ((u64)ipn[1] << 32) | - ((u64)ipn[0] << 40); + memcpy(status->igtk.ipn, data->ipn, sizeof(data->ipn)); } static void iwl_mvm_parse_wowlan_info_notif(struct iwl_mvm *mvm, @@ -2031,7 +2192,7 @@ static void iwl_mvm_parse_wowlan_info_notif(struct iwl_mvm *mvm, } iwl_mvm_convert_key_counters_v5(status, &data->gtk[0].sc); - iwl_mvm_convert_gtk_v3(status, &data->gtk[0]); + iwl_mvm_convert_gtk_v3(status, data->gtk); iwl_mvm_convert_igtk(status, &data->igtk[0]); status->replay_ctr = le64_to_cpu(data->replay_ctr); @@ -2139,14 +2300,9 @@ iwl_mvm_send_wowlan_get_status(struct iwl_mvm *mvm, u8 sta_id) len = iwl_rx_packet_payload_len(cmd.resp_pkt); /* default to 7 (when we have IWL_UCODE_TLV_API_WOWLAN_KEY_MATERIAL) */ - notif_ver = iwl_fw_lookup_notif_ver(mvm->fw, LONG_GROUP, - WOWLAN_GET_STATUSES, 0); - if (!notif_ver) - notif_ver = iwl_fw_lookup_notif_ver(mvm->fw, LEGACY_GROUP, - WOWLAN_GET_STATUSES, 7); + notif_ver = iwl_mvm_lookup_wowlan_status_ver(mvm); - if (!fw_has_api(&mvm->fw->ucode_capa, - IWL_UCODE_TLV_API_WOWLAN_KEY_MATERIAL)) { + if (notif_ver < 7) { struct iwl_wowlan_status_v6 *v6 = (void *)cmd.resp_pkt->data; status = iwl_mvm_parse_wowlan_status_common_v6(mvm, v6, len); @@ -2154,29 +2310,29 @@ iwl_mvm_send_wowlan_get_status(struct iwl_mvm *mvm, u8 sta_id) goto out_free_resp; BUILD_BUG_ON(sizeof(v6->gtk.decrypt_key) > - sizeof(status->gtk.key)); + sizeof(status->gtk[0].key)); BUILD_BUG_ON(NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY + sizeof(v6->gtk.tkip_mic_key) > - sizeof(status->gtk.key)); + sizeof(status->gtk[0].key)); /* copy GTK info to the right place */ - memcpy(status->gtk.key, v6->gtk.decrypt_key, + memcpy(status->gtk[0].key, v6->gtk.decrypt_key, sizeof(v6->gtk.decrypt_key)); - memcpy(status->gtk.key + NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY, + memcpy(status->gtk[0].key + NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY, v6->gtk.tkip_mic_key, sizeof(v6->gtk.tkip_mic_key)); iwl_mvm_convert_key_counters(status, &v6->gtk.rsc.all_tsc_rsc); /* hardcode the key length to 16 since v6 only supports 16 */ - status->gtk.len = 16; + status->gtk[0].len = 16; /* * The key index only uses 2 bits (values 0 to 3) and * we always set bit 7 which means this is the * currently used key. */ - status->gtk.flags = v6->gtk.key_index | BIT(7); + status->gtk[0].flags = v6->gtk.key_index | BIT(7); } else if (notif_ver == 7) { struct iwl_wowlan_status_v7 *v7 = (void *)cmd.resp_pkt->data; @@ -2210,7 +2366,7 @@ iwl_mvm_send_wowlan_get_status(struct iwl_mvm *mvm, u8 sta_id) goto out_free_resp; iwl_mvm_convert_key_counters_v5(status, &v12->gtk[0].sc); - iwl_mvm_convert_gtk_v3(status, &v12->gtk[0]); + iwl_mvm_convert_gtk_v3(status, v12->gtk); iwl_mvm_convert_igtk(status, &v12->igtk[0]); status->tid_tear_down = v12->tid_tear_down; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c index 3613b1fdc5d9d252084fbdb181cd28d31fb257ef..cb4ecad6103f5e7eccb56011b1b7f1c974457658 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* - * Copyright (C) 2012-2014, 2018-2021 Intel Corporation + * Copyright (C) 2012-2014, 2018-2023 Intel Corporation * Copyright (C) 2013-2015 Intel Mobile Communications GmbH * Copyright (C) 2016-2017 Intel Deutschland GmbH */ @@ -554,7 +554,7 @@ static ssize_t iwl_dbgfs_uapsd_misbehaving_read(struct file *file, char buf[20]; int len; - len = sprintf(buf, "%pM\n", mvmvif->uapsd_misbehaving_bssid); + len = sprintf(buf, "%pM\n", mvmvif->uapsd_misbehaving_ap_addr); return simple_read_from_buffer(user_buf, count, ppos, buf, len); } @@ -567,7 +567,7 @@ static ssize_t iwl_dbgfs_uapsd_misbehaving_write(struct ieee80211_vif *vif, bool ret; mutex_lock(&mvm->mutex); - ret = mac_pton(buf, mvmvif->uapsd_misbehaving_bssid); + ret = mac_pton(buf, mvmvif->uapsd_misbehaving_ap_addr); mutex_unlock(&mvm->mutex); return ret ? count : -EINVAL; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c index 84a48853842702c5dcfd3951e8c8588fe90dd569..cf27f106d4d56a0064dcb7e9d26cbdbf0b60b1fc 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c @@ -15,6 +15,7 @@ #include "iwl-io.h" #include "debugfs.h" #include "iwl-modparams.h" +#include "iwl-drv.h" #include "fw/error-dump.h" #include "fw/api/phy-ctxt.h" @@ -391,13 +392,14 @@ static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf, return simple_read_from_buffer(user_buf, count, ppos, buf, pos); } -static ssize_t iwl_dbgfs_rs_data_read(struct file *file, char __user *user_buf, +static ssize_t iwl_dbgfs_rs_data_read(struct ieee80211_link_sta *link_sta, + struct iwl_mvm_sta *mvmsta, + struct iwl_mvm *mvm, + struct iwl_mvm_link_sta *mvm_link_sta, + char __user *user_buf, size_t count, loff_t *ppos) { - struct ieee80211_sta *sta = file->private_data; - struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); - struct iwl_lq_sta_rs_fw *lq_sta = &mvmsta->deflink.lq_sta.rs_fw; - struct iwl_mvm *mvm = lq_sta->pers.drv; + struct iwl_lq_sta_rs_fw *lq_sta = &mvm_link_sta->lq_sta.rs_fw; static const size_t bufsz = 2048; char *buff; int desc = 0; @@ -407,8 +409,6 @@ static ssize_t iwl_dbgfs_rs_data_read(struct file *file, char __user *user_buf, if (!buff) return -ENOMEM; - mutex_lock(&mvm->mutex); - desc += scnprintf(buff + desc, bufsz - desc, "sta_id %d\n", lq_sta->pers.sta_id); desc += scnprintf(buff + desc, bufsz - desc, @@ -429,18 +429,19 @@ static ssize_t iwl_dbgfs_rs_data_read(struct file *file, char __user *user_buf, lq_sta->last_rate_n_flags); if (desc < bufsz - 1) buff[desc++] = '\n'; - mutex_unlock(&mvm->mutex); ret = simple_read_from_buffer(user_buf, count, ppos, buff, desc); kfree(buff); return ret; } -static ssize_t iwl_dbgfs_amsdu_len_write(struct ieee80211_sta *sta, +static ssize_t iwl_dbgfs_amsdu_len_write(struct ieee80211_link_sta *link_sta, + struct iwl_mvm_sta *mvmsta, + struct iwl_mvm *mvm, + struct iwl_mvm_link_sta *mvm_link_sta, char *buf, size_t count, loff_t *ppos) { - struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); int i; u16 amsdu_len; @@ -448,36 +449,39 @@ static ssize_t iwl_dbgfs_amsdu_len_write(struct ieee80211_sta *sta, return -EINVAL; /* only change from debug set <-> debug unset */ - if (amsdu_len && mvmsta->orig_amsdu_len) + if (amsdu_len && mvm_link_sta->orig_amsdu_len) return -EBUSY; if (amsdu_len) { - mvmsta->orig_amsdu_len = sta->cur->max_amsdu_len; - sta->deflink.agg.max_amsdu_len = amsdu_len; - sta->deflink.agg.max_amsdu_len = amsdu_len; - for (i = 0; i < ARRAY_SIZE(sta->deflink.agg.max_tid_amsdu_len); i++) - sta->deflink.agg.max_tid_amsdu_len[i] = amsdu_len; + mvm_link_sta->orig_amsdu_len = link_sta->agg.max_amsdu_len; + link_sta->agg.max_amsdu_len = amsdu_len; + link_sta->agg.max_amsdu_len = amsdu_len; + for (i = 0; i < ARRAY_SIZE(link_sta->agg.max_tid_amsdu_len); i++) + link_sta->agg.max_tid_amsdu_len[i] = amsdu_len; } else { - sta->deflink.agg.max_amsdu_len = mvmsta->orig_amsdu_len; - mvmsta->orig_amsdu_len = 0; + link_sta->agg.max_amsdu_len = mvm_link_sta->orig_amsdu_len; + mvm_link_sta->orig_amsdu_len = 0; } + ieee80211_sta_recalc_aggregates(link_sta->sta); + return count; } -static ssize_t iwl_dbgfs_amsdu_len_read(struct file *file, +static ssize_t iwl_dbgfs_amsdu_len_read(struct ieee80211_link_sta *link_sta, + struct iwl_mvm_sta *mvmsta, + struct iwl_mvm *mvm, + struct iwl_mvm_link_sta *mvm_link_sta, char __user *user_buf, size_t count, loff_t *ppos) { - struct ieee80211_sta *sta = file->private_data; - struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); - char buf[32]; int pos; - pos = scnprintf(buf, sizeof(buf), "current %d ", sta->cur->max_amsdu_len); + pos = scnprintf(buf, sizeof(buf), "current %d ", + link_sta->agg.max_amsdu_len); pos += scnprintf(buf + pos, sizeof(buf) - pos, "stored %d\n", - mvmsta->orig_amsdu_len); + mvm_link_sta->orig_amsdu_len); return simple_read_from_buffer(user_buf, count, ppos, buf, pos); } @@ -712,6 +716,7 @@ static ssize_t iwl_dbgfs_fw_ver_read(struct file *file, char __user *user_buf, struct iwl_mvm *mvm = file->private_data; char *buff, *pos, *endpos; static const size_t bufsz = 1024; + char _fw_name_pre[FW_NAME_PRE_BUFSIZE]; int ret; buff = kmalloc(bufsz, GFP_KERNEL); @@ -722,7 +727,7 @@ static ssize_t iwl_dbgfs_fw_ver_read(struct file *file, char __user *user_buf, endpos = pos + bufsz; pos += scnprintf(pos, endpos - pos, "FW prefix: %s\n", - mvm->trans->cfg->fw_name_pre); + iwl_drv_get_fwname_pre(mvm->trans, _fw_name_pre)); pos += scnprintf(pos, endpos - pos, "FW: %s\n", mvm->fwrt.fw->human_readable); pos += scnprintf(pos, endpos - pos, "Device: %s\n", @@ -1596,17 +1601,127 @@ static ssize_t iwl_dbgfs_dbg_time_point_write(struct iwl_mvm *mvm, #define MVM_DEBUGFS_ADD_FILE(name, parent, mode) \ MVM_DEBUGFS_ADD_FILE_ALIAS(#name, name, parent, mode) -#define MVM_DEBUGFS_WRITE_STA_FILE_OPS(name, bufsz) \ - _MVM_DEBUGFS_WRITE_FILE_OPS(name, bufsz, struct ieee80211_sta) -#define MVM_DEBUGFS_READ_WRITE_STA_FILE_OPS(name, bufsz) \ - _MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz, struct ieee80211_sta) +static ssize_t +_iwl_dbgfs_link_sta_wrap_write(ssize_t (*real)(struct ieee80211_link_sta *, + struct iwl_mvm_sta *, + struct iwl_mvm *, + struct iwl_mvm_link_sta *, + char *, + size_t, loff_t *), + struct file *file, + char *buf, size_t buf_size, loff_t *ppos) +{ + struct ieee80211_link_sta *link_sta = file->private_data; + struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(link_sta->sta); + struct iwl_mvm *mvm = iwl_mvm_vif_from_mac80211(mvmsta->vif)->mvm; + struct iwl_mvm_link_sta *mvm_link_sta; + ssize_t ret; -#define MVM_DEBUGFS_ADD_STA_FILE_ALIAS(alias, name, parent, mode) do { \ - debugfs_create_file(alias, mode, parent, sta, \ - &iwl_dbgfs_##name##_ops); \ - } while (0) -#define MVM_DEBUGFS_ADD_STA_FILE(name, parent, mode) \ - MVM_DEBUGFS_ADD_STA_FILE_ALIAS(#name, name, parent, mode) + mutex_lock(&mvm->mutex); + + mvm_link_sta = rcu_dereference_protected(mvmsta->link[link_sta->link_id], + lockdep_is_held(&mvm->mutex)); + if (WARN_ON(!mvm_link_sta)) { + mutex_unlock(&mvm->mutex); + return -ENODEV; + } + + ret = real(link_sta, mvmsta, mvm, mvm_link_sta, buf, buf_size, ppos); + + mutex_unlock(&mvm->mutex); + + return ret; +} + +static ssize_t +_iwl_dbgfs_link_sta_wrap_read(ssize_t (*real)(struct ieee80211_link_sta *, + struct iwl_mvm_sta *, + struct iwl_mvm *, + struct iwl_mvm_link_sta *, + char __user *, + size_t, loff_t *), + struct file *file, + char __user *user_buf, size_t count, loff_t *ppos) +{ + struct ieee80211_link_sta *link_sta = file->private_data; + struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(link_sta->sta); + struct iwl_mvm *mvm = iwl_mvm_vif_from_mac80211(mvmsta->vif)->mvm; + struct iwl_mvm_link_sta *mvm_link_sta; + ssize_t ret; + + mutex_lock(&mvm->mutex); + + mvm_link_sta = rcu_dereference_protected(mvmsta->link[link_sta->link_id], + lockdep_is_held(&mvm->mutex)); + if (WARN_ON(!mvm_link_sta)) { + mutex_unlock(&mvm->mutex); + return -ENODEV; + } + + ret = real(link_sta, mvmsta, mvm, mvm_link_sta, user_buf, count, ppos); + + mutex_unlock(&mvm->mutex); + + return ret; +} + +#define MVM_DEBUGFS_LINK_STA_WRITE_WRAPPER(name, buflen) \ +static ssize_t _iwl_dbgfs_link_sta_##name##_write(struct file *file, \ + const char __user *user_buf, \ + size_t count, loff_t *ppos) \ +{ \ + char buf[buflen] = {}; \ + size_t buf_size = min(count, sizeof(buf) - 1); \ + \ + if (copy_from_user(buf, user_buf, sizeof(buf))) \ + return -EFAULT; \ + \ + return _iwl_dbgfs_link_sta_wrap_write(iwl_dbgfs_##name##_write, \ + file, \ + buf, buf_size, ppos); \ +} \ + +#define MVM_DEBUGFS_LINK_STA_READ_WRAPPER(name) \ +static ssize_t _iwl_dbgfs_link_sta_##name##_read(struct file *file, \ + char __user *user_buf, \ + size_t count, loff_t *ppos) \ +{ \ + return _iwl_dbgfs_link_sta_wrap_read(iwl_dbgfs_##name##_read, \ + file, \ + user_buf, count, ppos); \ +} \ + +#define MVM_DEBUGFS_WRITE_LINK_STA_FILE_OPS(name, bufsz) \ +MVM_DEBUGFS_LINK_STA_WRITE_WRAPPER(name, bufsz) \ +static const struct file_operations iwl_dbgfs_link_sta_##name##_ops = { \ + .write = _iwl_dbgfs_link_sta_##name##_write, \ + .open = simple_open, \ + .llseek = generic_file_llseek, \ +} + +#define MVM_DEBUGFS_READ_LINK_STA_FILE_OPS(name) \ +MVM_DEBUGFS_LINK_STA_READ_WRAPPER(name) \ +static const struct file_operations iwl_dbgfs_link_sta_##name##_ops = { \ + .read = _iwl_dbgfs_link_sta_##name##_read, \ + .open = simple_open, \ + .llseek = generic_file_llseek, \ +} + +#define MVM_DEBUGFS_READ_WRITE_LINK_STA_FILE_OPS(name, bufsz) \ +MVM_DEBUGFS_LINK_STA_READ_WRAPPER(name) \ +MVM_DEBUGFS_LINK_STA_WRITE_WRAPPER(name, bufsz) \ +static const struct file_operations iwl_dbgfs_link_sta_##name##_ops = { \ + .read = _iwl_dbgfs_link_sta_##name##_read, \ + .write = _iwl_dbgfs_link_sta_##name##_write, \ + .open = simple_open, \ + .llseek = generic_file_llseek, \ +} + +#define MVM_DEBUGFS_ADD_LINK_STA_FILE_ALIAS(alias, name, parent, mode) \ + debugfs_create_file(alias, mode, parent, link_sta, \ + &iwl_dbgfs_link_sta_##name##_ops) +#define MVM_DEBUGFS_ADD_LINK_STA_FILE(name, parent, mode) \ + MVM_DEBUGFS_ADD_LINK_STA_FILE_ALIAS(#name, name, parent, mode) static ssize_t iwl_dbgfs_prph_reg_read(struct file *file, @@ -1891,7 +2006,7 @@ MVM_DEBUGFS_READ_WRITE_FILE_OPS(sram, 64); MVM_DEBUGFS_READ_WRITE_FILE_OPS(set_nic_temperature, 64); MVM_DEBUGFS_READ_FILE_OPS(nic_temp); MVM_DEBUGFS_READ_FILE_OPS(stations); -MVM_DEBUGFS_READ_FILE_OPS(rs_data); +MVM_DEBUGFS_READ_LINK_STA_FILE_OPS(rs_data); MVM_DEBUGFS_READ_FILE_OPS(bt_notif); MVM_DEBUGFS_READ_FILE_OPS(bt_cmd); MVM_DEBUGFS_READ_WRITE_FILE_OPS(disable_power_off, 64); @@ -1921,7 +2036,7 @@ MVM_DEBUGFS_READ_FILE_OPS(sar_geo_profile); MVM_DEBUGFS_READ_FILE_OPS(wifi_6e_enable); #endif -MVM_DEBUGFS_READ_WRITE_STA_FILE_OPS(amsdu_len, 16); +MVM_DEBUGFS_READ_WRITE_LINK_STA_FILE_OPS(amsdu_len, 16); MVM_DEBUGFS_READ_WRITE_FILE_OPS(he_sniffer_params, 32); @@ -2068,17 +2183,18 @@ static const struct file_operations iwl_dbgfs_mem_ops = { .llseek = default_llseek, }; -void iwl_mvm_sta_add_debugfs(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta, - struct dentry *dir) +void iwl_mvm_link_sta_add_debugfs(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_link_sta *link_sta, + struct dentry *dir) { struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); if (iwl_mvm_has_tlc_offload(mvm)) { - MVM_DEBUGFS_ADD_STA_FILE(rs_data, dir, 0400); + MVM_DEBUGFS_ADD_LINK_STA_FILE(rs_data, dir, 0400); } - MVM_DEBUGFS_ADD_STA_FILE(amsdu_len, dir, 0600); + + MVM_DEBUGFS_ADD_LINK_STA_FILE(amsdu_len, dir, 0600); } void iwl_mvm_dbgfs_register(struct iwl_mvm *mvm) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c index 652a603c4500efed3be6162d4f26a520eeda3f93..233ae81884a0ea3a710f4bc5406b3e95ba4b611f 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c @@ -72,15 +72,24 @@ int iwl_mvm_ftm_add_pasn_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif, * the TK is already configured for this station, so it * shouldn't be set again here. */ - if (vif->cfg.assoc && - !memcmp(addr, vif->bss_conf.bssid, ETH_ALEN)) { + if (vif->cfg.assoc) { struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); + struct ieee80211_bss_conf *link_conf; + unsigned int link_id; struct ieee80211_sta *sta; + u8 sta_id; rcu_read_lock(); - sta = rcu_dereference(mvm->fw_id_to_mac_id[mvmvif->deflink.ap_sta_id]); - if (!IS_ERR_OR_NULL(sta) && sta->mfp) - expected_tk_len = 0; + for_each_vif_active_link(vif, link_conf, link_id) { + if (memcmp(addr, link_conf->bssid, ETH_ALEN)) + continue; + + sta_id = mvmvif->link[link_id]->ap_sta_id; + sta = rcu_dereference(mvm->fw_id_to_mac_id[sta_id]); + if (!IS_ERR_OR_NULL(sta) && sta->mfp) + expected_tk_len = 0; + break; + } rcu_read_unlock(); } @@ -518,25 +527,30 @@ iwl_mvm_ftm_put_target(struct iwl_mvm *mvm, struct ieee80211_vif *vif, iwl_mvm_ftm_put_target_common(mvm, peer, target); - if (vif->cfg.assoc && - !memcmp(peer->addr, vif->bss_conf.bssid, ETH_ALEN)) { + if (vif->cfg.assoc) { struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); struct ieee80211_sta *sta; + struct ieee80211_bss_conf *link_conf; + unsigned int link_id; rcu_read_lock(); + for_each_vif_active_link(vif, link_conf, link_id) { + if (memcmp(peer->addr, link_conf->bssid, ETH_ALEN)) + continue; + + target->sta_id = mvmvif->link[link_id]->ap_sta_id; + sta = rcu_dereference(mvm->fw_id_to_mac_id[target->sta_id]); + if (WARN_ON_ONCE(IS_ERR_OR_NULL(sta))) { + rcu_read_unlock(); + return PTR_ERR_OR_ZERO(sta); + } - sta = rcu_dereference(mvm->fw_id_to_mac_id[mvmvif->deflink.ap_sta_id]); - if (WARN_ON_ONCE(IS_ERR_OR_NULL(sta))) { - rcu_read_unlock(); - return PTR_ERR_OR_ZERO(sta); + if (sta->mfp && (peer->ftm.trigger_based || + peer->ftm.non_trigger_based)) + FTM_PUT_FLAG(PMF); + break; } - - if (sta->mfp && (peer->ftm.trigger_based || peer->ftm.non_trigger_based)) - FTM_PUT_FLAG(PMF); - rcu_read_unlock(); - - target->sta_id = mvmvif->deflink.ap_sta_id; } else { target->sta_id = IWL_MVM_INVALID_STA; } diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-responder.c b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-responder.c index 1b6fb73ddfc784da9ee5138e62a91a5259690ff1..b49781d1a07a7a721b3e0e076f8b8487f3aac941 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-responder.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-responder.c @@ -104,7 +104,8 @@ iwl_mvm_ftm_responder_set_ndp(struct iwl_mvm *mvm, static int iwl_mvm_ftm_responder_cmd(struct iwl_mvm *mvm, struct ieee80211_vif *vif, - struct cfg80211_chan_def *chandef) + struct cfg80211_chan_def *chandef, + struct ieee80211_bss_conf *link_conf) { u32 cmd_id = WIDE_ID(LOCATION_GROUP, TOF_RESPONDER_CONFIG_CMD); struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); @@ -119,7 +120,7 @@ iwl_mvm_ftm_responder_cmd(struct iwl_mvm *mvm, cpu_to_le32(IWL_TOF_RESPONDER_CMD_VALID_CHAN_INFO | IWL_TOF_RESPONDER_CMD_VALID_BSSID | IWL_TOF_RESPONDER_CMD_VALID_STA_ID), - .sta_id = mvmvif->deflink.bcast_sta.sta_id, + .sta_id = mvmvif->link[link_conf->link_id]->bcast_sta.sta_id, }; u8 cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw, cmd_id, 6); int err; @@ -386,7 +387,8 @@ int iwl_mvm_ftm_resp_remove_pasn_sta(struct iwl_mvm *mvm, return -EINVAL; } -int iwl_mvm_ftm_start_responder(struct iwl_mvm *mvm, struct ieee80211_vif *vif) +int iwl_mvm_ftm_start_responder(struct iwl_mvm *mvm, struct ieee80211_vif *vif, + struct ieee80211_bss_conf *bss_conf) { struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); struct ieee80211_ftm_responder_params *params; @@ -395,11 +397,11 @@ int iwl_mvm_ftm_start_responder(struct iwl_mvm *mvm, struct ieee80211_vif *vif) struct iwl_mvm_phy_ctxt *phy_ctxt; int ret; - params = vif->bss_conf.ftmr_params; + params = bss_conf->ftmr_params; lockdep_assert_held(&mvm->mutex); - if (WARN_ON_ONCE(!vif->bss_conf.ftm_responder)) + if (WARN_ON_ONCE(!bss_conf->ftm_responder)) return -EINVAL; if (vif->p2p || vif->type != NL80211_IFTYPE_AP || @@ -409,7 +411,7 @@ int iwl_mvm_ftm_start_responder(struct iwl_mvm *mvm, struct ieee80211_vif *vif) } rcu_read_lock(); - pctx = rcu_dereference(vif->bss_conf.chanctx_conf); + pctx = rcu_dereference(bss_conf->chanctx_conf); /* Copy the ctx to unlock the rcu and send the phy ctxt. We don't care * about changes in the ctx after releasing the lock because the driver * is still protected by the mutex. */ @@ -424,7 +426,7 @@ int iwl_mvm_ftm_start_responder(struct iwl_mvm *mvm, struct ieee80211_vif *vif) if (ret) return ret; - ret = iwl_mvm_ftm_responder_cmd(mvm, vif, &ctx.def); + ret = iwl_mvm_ftm_responder_cmd(mvm, vif, &ctx.def, bss_conf); if (ret) return ret; @@ -446,13 +448,14 @@ void iwl_mvm_ftm_responder_clear(struct iwl_mvm *mvm, } void iwl_mvm_ftm_restart_responder(struct iwl_mvm *mvm, - struct ieee80211_vif *vif) + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *bss_conf) { - if (!vif->bss_conf.ftm_responder) + if (!bss_conf->ftm_responder) return; iwl_mvm_ftm_responder_clear(mvm, vif); - iwl_mvm_ftm_start_responder(mvm, vif); + iwl_mvm_ftm_start_responder(mvm, vif, bss_conf); } void iwl_mvm_ftm_responder_stats(struct iwl_mvm *mvm, diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c index 205c09bc986342ff8d98866310a4056dd0366602..1f5db65a088d3b657dde7344b3bb2202358f760d 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* - * Copyright (C) 2012-2014, 2018-2022 Intel Corporation + * Copyright (C) 2012-2014, 2018-2023 Intel Corporation * Copyright (C) 2013-2015 Intel Mobile Communications GmbH * Copyright (C) 2016-2017 Intel Deutschland GmbH */ @@ -433,7 +433,8 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm, /* if reached this point, Alive notification was received */ iwl_mei_alive_notif(true); - ret = iwl_pnvm_load(mvm->trans, &mvm->notif_wait); + ret = iwl_pnvm_load(mvm->trans, &mvm->notif_wait, + &mvm->fw->ucode_capa); if (ret) { IWL_ERR(mvm, "Timeout waiting for PNVM load!\n"); iwl_fw_set_current_image(&mvm->fwrt, old_type); @@ -477,40 +478,13 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm, return 0; } -#ifdef CONFIG_ACPI -static void iwl_mvm_phy_filter_init(struct iwl_mvm *mvm, - struct iwl_phy_specific_cfg *phy_filters) -{ - /* - * TODO: read specific phy config from BIOS - * ACPI table for this feature has not been defined yet, - * so for now we use hardcoded values. - */ - - if (IWL_MVM_PHY_FILTER_CHAIN_A) { - phy_filters->filter_cfg_chain_a = - cpu_to_le32(IWL_MVM_PHY_FILTER_CHAIN_A); - } - if (IWL_MVM_PHY_FILTER_CHAIN_B) { - phy_filters->filter_cfg_chain_b = - cpu_to_le32(IWL_MVM_PHY_FILTER_CHAIN_B); - } - if (IWL_MVM_PHY_FILTER_CHAIN_C) { - phy_filters->filter_cfg_chain_c = - cpu_to_le32(IWL_MVM_PHY_FILTER_CHAIN_C); - } - if (IWL_MVM_PHY_FILTER_CHAIN_D) { - phy_filters->filter_cfg_chain_d = - cpu_to_le32(IWL_MVM_PHY_FILTER_CHAIN_D); - } -} -#else /* CONFIG_ACPI */ - static void iwl_mvm_phy_filter_init(struct iwl_mvm *mvm, struct iwl_phy_specific_cfg *phy_filters) { -} +#ifdef CONFIG_ACPI + *phy_filters = mvm->phy_filters; #endif /* CONFIG_ACPI */ +} #if defined(CONFIG_ACPI) && defined(CONFIG_EFI) static int iwl_mvm_sgom_init(struct iwl_mvm *mvm) @@ -559,7 +533,6 @@ static int iwl_send_phy_cfg_cmd(struct iwl_mvm *mvm) u32 cmd_id = PHY_CONFIGURATION_CMD; struct iwl_phy_cfg_cmd_v3 phy_cfg_cmd; enum iwl_ucode_type ucode_type = mvm->fwrt.cur_fw_img; - struct iwl_phy_specific_cfg phy_filters = {}; u8 cmd_ver; size_t cmd_size; @@ -590,11 +563,8 @@ static int iwl_send_phy_cfg_cmd(struct iwl_mvm *mvm) cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw, cmd_id, IWL_FW_CMD_VER_UNKNOWN); - if (cmd_ver == 3) { - iwl_mvm_phy_filter_init(mvm, &phy_filters); - memcpy(&phy_cfg_cmd.phy_specific_cfg, &phy_filters, - sizeof(struct iwl_phy_specific_cfg)); - } + if (cmd_ver >= 3) + iwl_mvm_phy_filter_init(mvm, &phy_cfg_cmd.phy_specific_cfg); IWL_DEBUG_INFO(mvm, "Sending Phy CFG command: 0x%x\n", phy_cfg_cmd.phy_cfg); @@ -1104,7 +1074,26 @@ static const struct dmi_system_id dmi_tas_approved_list[] = { DMI_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"), }, }, - + { .ident = "Acer", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Acer"), + }, + }, + { .ident = "ASUS", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + }, + }, + { .ident = "MSI", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International Co., Ltd."), + }, + }, + { .ident = "Honor", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "HONOR"), + }, + }, /* keep last */ {} }; @@ -1162,7 +1151,7 @@ static void iwl_mvm_tas_init(struct iwl_mvm *mvm) if (ret == 0) return; - if (!dmi_check_system(dmi_tas_approved_list)) { + if (!iwl_mvm_is_vendor_in_approved_list()) { IWL_DEBUG_RADIO(mvm, "System vendor '%s' is not in the approved list, disabling TAS in US and Canada.\n", dmi_get_system_info(DMI_SYS_VENDOR)); @@ -1176,6 +1165,10 @@ static void iwl_mvm_tas_init(struct iwl_mvm *mvm) "Unable to add US/Canada to TAS block list, disabling TAS\n"); return; } + } else { + IWL_DEBUG_RADIO(mvm, + "System vendor '%s' is in the approved list.\n", + dmi_get_system_info(DMI_SYS_VENDOR)); } /* v4 is the same size as v3, so no need to differentiate here */ @@ -1356,6 +1349,8 @@ void iwl_mvm_get_acpi_tables(struct iwl_mvm *mvm) /* we don't fail if the table is not available */ } } + + iwl_acpi_get_phy_filters(&mvm->fwrt, &mvm->phy_filters); } #else /* CONFIG_ACPI */ @@ -1571,6 +1566,8 @@ int iwl_mvm_up(struct iwl_mvm *mvm) goto error; } + iwl_mvm_lari_cfg(mvm); + /* Init RSS configuration */ ret = iwl_configure_rxq(&mvm->fwrt); if (ret) @@ -1591,6 +1588,9 @@ int iwl_mvm_up(struct iwl_mvm *mvm) RCU_INIT_POINTER(mvm->fw_id_to_link_sta[i], NULL); } + for (i = 0; i < IWL_MVM_FW_MAX_LINK_ID + 1; i++) + RCU_INIT_POINTER(mvm->link_id_to_link_conf[i], NULL); + memset(&mvm->fw_link_ids_map, 0, sizeof(mvm->fw_link_ids_map)); mvm->tdls_cs.peer.sta_id = IWL_MVM_INVALID_STA; @@ -1610,7 +1610,7 @@ int iwl_mvm_up(struct iwl_mvm *mvm) * internal aux station for all aux activities that don't * requires a dedicated data queue. */ - if (iwl_fw_lookup_cmd_ver(mvm->fw, ADD_STA, 0) < 12) { + if (!iwl_mvm_has_new_station_api(mvm->fw)) { /* * In old version the aux station uses mac id like other * station and not lmac id @@ -1678,7 +1678,6 @@ int iwl_mvm_up(struct iwl_mvm *mvm) if (ret) goto error; - iwl_mvm_lari_cfg(mvm); /* * RTNL is not taken during Ct-kill, but we don't need to scan/Tx * anyway, so don't init MCC. @@ -1699,9 +1698,11 @@ int iwl_mvm_up(struct iwl_mvm *mvm) if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) { iwl_mvm_send_recovery_cmd(mvm, ERROR_RECOVERY_UPDATE_DB); - iwl_mvm_time_sync_config(mvm, mvm->time_sync.peer_addr, - IWL_TIME_SYNC_PROTOCOL_TM | - IWL_TIME_SYNC_PROTOCOL_FTM); + + if (mvm->time_sync.active) + iwl_mvm_time_sync_config(mvm, mvm->time_sync.peer_addr, + IWL_TIME_SYNC_PROTOCOL_TM | + IWL_TIME_SYNC_PROTOCOL_FTM); } if (!mvm->ptp_data.ptp_clock) @@ -1777,7 +1778,7 @@ int iwl_mvm_load_d3_fw(struct iwl_mvm *mvm) RCU_INIT_POINTER(mvm->fw_id_to_link_sta[i], NULL); } - if (iwl_fw_lookup_cmd_ver(mvm->fw, ADD_STA, 0) < 12) { + if (!iwl_mvm_has_new_station_api(mvm->fw)) { /* * Add auxiliary station for scanning. * Newer versions of this command implies that the fw uses diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/link.c b/drivers/net/wireless/intel/iwlwifi/mvm/link.c index 3814915cb1a67df435b3b84a973af9fa9e29505f..ace82e2c5bd913bf54c917d2a67f1067b0622670 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/link.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/link.c @@ -63,6 +63,9 @@ int iwl_mvm_add_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif, mvmvif); if (link_info->fw_link_id == IWL_MVM_FW_LINK_ID_INVALID) return -EINVAL; + + rcu_assign_pointer(mvm->link_id_to_link_conf[link_info->fw_link_id], + link_conf); } /* Update SF - Disable if needed. if this fails, SF might still be on @@ -73,6 +76,7 @@ int iwl_mvm_add_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif, cmd.link_id = cpu_to_le32(link_info->fw_link_id); cmd.mac_id = cpu_to_le32(mvmvif->id); + cmd.spec_link_id = link_conf->link_id; /* P2P-Device already has a valid PHY context during add */ phyctxt = link_info->phy_ctxt; if (phyctxt) @@ -85,6 +89,8 @@ int iwl_mvm_add_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif, if (vif->type == NL80211_IFTYPE_ADHOC && link_conf->bssid) memcpy(cmd.ibss_bssid_addr, link_conf->bssid, ETH_ALEN); + cmd.listen_lmac = cpu_to_le32(link_info->listen_lmac); + return iwl_mvm_link_cmd_send(mvm, &cmd, FW_CTXT_ACTION_ADD); } @@ -114,24 +120,6 @@ int iwl_mvm_link_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif, if (!link_info->phy_ctxt) return 0; - /* check there aren't too many active links */ - if (!link_info->active && active) { - int i, count = 0; - - /* link with phy_ctxt is active in FW */ - for_each_mvm_vif_valid_link(mvmvif, i) - if (mvmvif->link[i]->phy_ctxt) - count++; - - if (vif->type == NL80211_IFTYPE_AP) { - if (count > mvm->fw->ucode_capa.num_beacons) - return -EOPNOTSUPP; - /* this should be per HW or such */ - } else if (count >= IWL_MVM_FW_MAX_ACTIVE_LINKS_NUM) { - return -EOPNOTSUPP; - } - } - /* Catch early if driver tries to activate or deactivate a link * twice. */ @@ -163,10 +151,6 @@ int iwl_mvm_link_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif, if (vif->type == NL80211_IFTYPE_ADHOC && link_conf->bssid) memcpy(cmd.ibss_bssid_addr, link_conf->bssid, ETH_ALEN); - /* TODO: set a value to cmd.listen_lmac when system requiremens - * will define it - */ - iwl_mvm_set_fw_basic_rates(mvm, vif, link_conf, &cmd.cck_rates, &cmd.ofdm_rates); @@ -179,7 +163,7 @@ int iwl_mvm_link_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif, &cmd.protection_flags, ht_flag, LINK_PROT_FLG_TGG_PROTECT); - iwl_mvm_set_fw_qos_params(mvm, vif, link_conf, &cmd.ac[0], + iwl_mvm_set_fw_qos_params(mvm, vif, link_conf, cmd.ac, &cmd.qos_flags); @@ -204,7 +188,7 @@ int iwl_mvm_link_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif, /* TODO how to set ndp_fdbk_buff_th_exp? */ - if (iwl_mvm_set_fw_mu_edca_params(mvm, mvmvif, + if (iwl_mvm_set_fw_mu_edca_params(mvm, mvmvif->link[link_id], &cmd.trig_based_txf[0])) { flags |= LINK_FLG_MU_EDCA_CW; flags_mask |= LINK_FLG_MU_EDCA_CW; @@ -241,6 +225,8 @@ int iwl_mvm_link_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif, cmd.modify_mask = cpu_to_le32(changes); cmd.flags = cpu_to_le32(flags); cmd.flags_mask = cpu_to_le32(flags_mask); + cmd.spec_link_id = link_conf->link_id; + cmd.listen_lmac = cpu_to_le32(link_info->listen_lmac); ret = iwl_mvm_link_cmd_send(mvm, &cmd, FW_CTXT_ACTION_MODIFY); if (!ret && (changes & LINK_CONTEXT_MODIFY_ACTIVE)) @@ -262,9 +248,12 @@ int iwl_mvm_remove_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif, link_info->fw_link_id == IWL_MVM_FW_LINK_ID_INVALID)) return -EINVAL; + RCU_INIT_POINTER(mvm->link_id_to_link_conf[link_info->fw_link_id], + NULL); cmd.link_id = cpu_to_le32(link_info->fw_link_id); iwl_mvm_release_fw_link_id(mvm, link_info->fw_link_id); link_info->fw_link_id = IWL_MVM_FW_LINK_ID_INVALID; + cmd.spec_link_id = link_conf->link_id; ret = iwl_mvm_link_cmd_send(mvm, &cmd, FW_CTXT_ACTION_REMOVE); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c index cc90f2884cff62155e1b0252e12029f31bbfcbaf..7369a45f7f2bd7a4b23ff7f8ba07486f78b5993e 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* - * Copyright (C) 2012-2014, 2018-2022 Intel Corporation + * Copyright (C) 2012-2014, 2018-2023 Intel Corporation * Copyright (C) 2013-2014 Intel Mobile Communications GmbH * Copyright (C) 2015-2017 Intel Deutschland GmbH */ @@ -470,19 +470,24 @@ void iwl_mvm_set_fw_qos_params(struct iwl_mvm *mvm, struct ieee80211_vif *vif, struct iwl_ac_qos *ac, __le32 *qos_flags) { struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); + struct iwl_mvm_vif_link_info *mvm_link = + mvmvif->link[link_conf->link_id]; int i; + if (!mvm_link) + return; + for (i = 0; i < IEEE80211_NUM_ACS; i++) { u8 txf = iwl_mvm_mac_ac_to_tx_fifo(mvm, i); u8 ucode_ac = iwl_mvm_mac80211_ac_to_ucode_ac(i); ac[ucode_ac].cw_min = - cpu_to_le16(mvmvif->deflink.queue_params[i].cw_min); + cpu_to_le16(mvm_link->queue_params[i].cw_min); ac[ucode_ac].cw_max = - cpu_to_le16(mvmvif->deflink.queue_params[i].cw_max); + cpu_to_le16(mvm_link->queue_params[i].cw_max); ac[ucode_ac].edca_txop = - cpu_to_le16(mvmvif->deflink.queue_params[i].txop * 32); - ac[ucode_ac].aifsn = mvmvif->deflink.queue_params[i].aifs; + cpu_to_le16(mvm_link->queue_params[i].txop * 32); + ac[ucode_ac].aifsn = mvm_link->queue_params[i].aifs; ac[ucode_ac].fifos_mask = BIT(txf); } @@ -558,7 +563,7 @@ static void iwl_mvm_mac_ctxt_cmd_common(struct iwl_mvm *mvm, cmd->filter_flags = 0; - iwl_mvm_set_fw_qos_params(mvm, vif, &vif->bss_conf, &cmd->ac[0], + iwl_mvm_set_fw_qos_params(mvm, vif, &vif->bss_conf, cmd->ac, &cmd->qos_flags); /* The fw does not distinguish between ht and fat */ @@ -629,17 +634,17 @@ __le32 iwl_mvm_mac_ctxt_cmd_p2p_sta_get_oppps_ctwin(struct iwl_mvm *mvm, IEEE80211_P2P_OPPPS_CTWINDOW_MASK); } -__le32 iwl_mvm_mac_ctxt_cmd_sta_get_twt_policy(struct iwl_mvm *mvm, - struct ieee80211_vif *vif) +u32 iwl_mvm_mac_ctxt_cmd_sta_get_twt_policy(struct iwl_mvm *mvm, + struct ieee80211_vif *vif) { - __le32 twt_policy = cpu_to_le32(0); + u32 twt_policy = 0; if (vif->bss_conf.twt_requester && IWL_MVM_USE_TWT) - twt_policy |= cpu_to_le32(TWT_SUPPORTED); + twt_policy |= TWT_SUPPORTED; if (vif->bss_conf.twt_protected) - twt_policy |= cpu_to_le32(PROTECTED_TWT_SUPPORTED); + twt_policy |= PROTECTED_TWT_SUPPORTED; if (vif->bss_conf.twt_broadcast) - twt_policy |= cpu_to_le32(BROADCAST_TWT_SUPPORTED); + twt_policy |= BROADCAST_TWT_SUPPORTED; return twt_policy; } @@ -711,7 +716,7 @@ static int iwl_mvm_mac_ctxt_cmd_sta(struct iwl_mvm *mvm, if (vif->bss_conf.he_support && !iwlwifi_mod_params.disable_11ax) { cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_11AX); ctxt_sta->data_policy |= - iwl_mvm_mac_ctxt_cmd_sta_get_twt_policy(mvm, vif); + cpu_to_le32(iwl_mvm_mac_ctxt_cmd_sta_get_twt_policy(mvm, vif)); } @@ -888,7 +893,7 @@ u8 iwl_mvm_mac_ctxt_get_lowest_rate(struct iwl_mvm *mvm, u8 rate; u32 i; - if (link_id == IEEE80211_LINK_UNSPECIFIED && vif->valid_links) { + if (link_id == IEEE80211_LINK_UNSPECIFIED && ieee80211_vif_is_mld(vif)) { for (i = 0; i < ARRAY_SIZE(mvmvif->link); i++) { if (!mvmvif->link[i]) continue; @@ -1111,6 +1116,10 @@ static int iwl_mvm_mac_ctxt_send_beacon_v9(struct iwl_mvm *mvm, beacon_cmd.flags = cpu_to_le16(flags); beacon_cmd.byte_cnt = cpu_to_le16((u16)beacon->len); + + if (WARN_ON(!mvmvif->link[link_conf->link_id])) + return -EINVAL; + if (iwl_fw_lookup_cmd_ver(mvm->fw, BEACON_TEMPLATE_CMD, 0) > 12) beacon_cmd.link_id = cpu_to_le32(mvmvif->link[link_conf->link_id]->fw_link_id); @@ -1555,21 +1564,38 @@ void iwl_mvm_rx_missed_beacons_notif(struct iwl_mvm *mvm, u32 stop_trig_missed_bcon, stop_trig_missed_bcon_since_rx; u32 rx_missed_bcon, rx_missed_bcon_since_rx; struct ieee80211_vif *vif; - u32 id = le32_to_cpu(mb->mac_id); + /* Id can be mac/link id depending on the notification version */ + u32 id = le32_to_cpu(mb->link_id); union iwl_dbg_tlv_tp_data tp_data = { .fw_pkt = pkt }; u32 mac_type; + u8 notif_ver = iwl_fw_lookup_notif_ver(mvm->fw, LEGACY_GROUP, + MISSED_BEACONS_NOTIFICATION, + 0); + + rcu_read_lock(); + + /* before version four the ID in the notification refers to mac ID */ + if (notif_ver < 4) { + vif = iwl_mvm_rcu_dereference_vif_id(mvm, id, true); + } else { + struct ieee80211_bss_conf *bss_conf = + iwl_mvm_rcu_fw_link_id_to_link_conf(mvm, id, true); + + if (!bss_conf) + goto out; + + vif = bss_conf->vif; + } IWL_DEBUG_INFO(mvm, - "missed bcn mac_id=%u, consecutive=%u (%u, %u, %u)\n", - le32_to_cpu(mb->mac_id), + "missed bcn %s_id=%u, consecutive=%u (%u, %u, %u)\n", + notif_ver < 4 ? "mac" : "link", + id, le32_to_cpu(mb->consec_missed_beacons), le32_to_cpu(mb->consec_missed_beacons_since_last_rx), le32_to_cpu(mb->num_recvd_beacons), le32_to_cpu(mb->num_expected_beacons)); - rcu_read_lock(); - - vif = iwl_mvm_rcu_dereference_vif_id(mvm, id, true); if (!vif) goto out; @@ -1730,20 +1756,47 @@ void iwl_mvm_channel_switch_start_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb) { struct iwl_rx_packet *pkt = rxb_addr(rxb); - struct iwl_channel_switch_start_notif *notif = (void *)pkt->data; struct ieee80211_vif *csa_vif, *vif; - struct iwl_mvm_vif *mvmvif; - u32 id_n_color, csa_id, mac_id; + struct iwl_mvm_vif *mvmvif, *csa_mvmvif; + u32 id_n_color, csa_id; + /* save mac_id or link_id to use later to cancel csa if needed */ + u32 id; + u8 notif_ver = iwl_fw_lookup_notif_ver(mvm->fw, MAC_CONF_GROUP, + CHANNEL_SWITCH_START_NOTIF, 0); + bool csa_active; - id_n_color = le32_to_cpu(notif->id_and_color); - mac_id = id_n_color & FW_CTXT_ID_MSK; + rcu_read_lock(); - if (WARN_ON_ONCE(mac_id >= NUM_MAC_INDEX_DRIVER)) - return; + if (notif_ver < 3) { + struct iwl_channel_switch_start_notif_v1 *notif = (void *)pkt->data; + u32 mac_id; + + id_n_color = le32_to_cpu(notif->id_and_color); + mac_id = id_n_color & FW_CTXT_ID_MSK; + + vif = iwl_mvm_rcu_dereference_vif_id(mvm, mac_id, true); + if (!vif) + goto out_unlock; + + id = mac_id; + csa_active = vif->bss_conf.csa_active; + } else { + struct iwl_channel_switch_start_notif *notif = (void *)pkt->data; + u32 link_id = le32_to_cpu(notif->link_id); + struct ieee80211_bss_conf *bss_conf = + iwl_mvm_rcu_fw_link_id_to_link_conf(mvm, link_id, true); + + if (!bss_conf) + goto out_unlock; + + id = link_id; + vif = bss_conf->vif; + csa_active = bss_conf->csa_active; + } - rcu_read_lock(); - vif = rcu_dereference(mvm->vif_id_to_mac[mac_id]); mvmvif = iwl_mvm_vif_from_mac80211(vif); + if (notif_ver >= 3) + id_n_color = FW_CMD_ID_AND_COLOR(mvmvif->id, mvmvif->color); switch (vif->type) { case NL80211_IFTYPE_AP: @@ -1752,7 +1805,8 @@ void iwl_mvm_channel_switch_start_notif(struct iwl_mvm *mvm, csa_vif != vif)) goto out_unlock; - csa_id = FW_CMD_ID_AND_COLOR(mvmvif->id, mvmvif->color); + csa_mvmvif = iwl_mvm_vif_from_mac80211(csa_vif); + csa_id = FW_CMD_ID_AND_COLOR(csa_mvmvif->id, csa_mvmvif->color); if (WARN(csa_id != id_n_color, "channel switch noa notification on unexpected vif (csa_vif=%d, notif=%d)", csa_id, id_n_color)) @@ -1777,9 +1831,9 @@ void iwl_mvm_channel_switch_start_notif(struct iwl_mvm *mvm, */ if (iwl_fw_lookup_notif_ver(mvm->fw, MAC_CONF_GROUP, CHANNEL_SWITCH_ERROR_NOTIF, - 0) && !vif->bss_conf.csa_active) { + 0) && !csa_active) { IWL_DEBUG_INFO(mvm, "Channel Switch was canceled\n"); - iwl_mvm_cancel_channel_switch(mvm, vif, mac_id); + iwl_mvm_cancel_channel_switch(mvm, vif, id); break; } @@ -1802,7 +1856,7 @@ void iwl_mvm_channel_switch_error_notif(struct iwl_mvm *mvm, struct iwl_rx_packet *pkt = rxb_addr(rxb); struct iwl_channel_switch_error_notif *notif = (void *)pkt->data; struct ieee80211_vif *vif; - u32 id = le32_to_cpu(notif->mac_id); + u32 id = le32_to_cpu(notif->link_id); u32 csa_err_mask = le32_to_cpu(notif->csa_err_mask); rcu_read_lock(); @@ -1812,7 +1866,7 @@ void iwl_mvm_channel_switch_error_notif(struct iwl_mvm *mvm, return; } - IWL_DEBUG_INFO(mvm, "FW reports CSA error: mac_id=%u, csa_err_mask=%u\n", + IWL_DEBUG_INFO(mvm, "FW reports CSA error: id=%u, csa_err_mask=%u\n", id, csa_err_mask); if (csa_err_mask & (CS_ERR_COUNT_ERROR | CS_ERR_LONG_DELAY_AFTER_CS | diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index 17f788a5ff6ba686e0d9743c3e8677dfecf9dc6d..ce7905faa08ffd65bf22a2613ec7b9d64eff846f 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c @@ -108,7 +108,7 @@ struct ieee80211_regdomain *iwl_mvm_get_regdomain(struct wiphy *wiphy, struct ieee80211_regdomain *regd = NULL; struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); - struct iwl_mcc_update_resp *resp; + struct iwl_mcc_update_resp_v8 *resp; u8 resp_ver; IWL_DEBUG_LAR(mvm, "Getting regdomain data for %s from FW\n", alpha2); @@ -138,7 +138,7 @@ struct ieee80211_regdomain *iwl_mvm_get_regdomain(struct wiphy *wiphy, resp->channels, __le16_to_cpu(resp->mcc), __le16_to_cpu(resp->geo_info), - __le16_to_cpu(resp->cap), resp_ver); + le32_to_cpu(resp->cap), resp_ver); /* Store the return source id */ src_id = resp->source_id; if (IS_ERR_OR_NULL(regd)) { @@ -245,12 +245,21 @@ static const u8 tm_if_types_ext_capa_sta[] = { /* Additional interface types for which extended capabilities are * specified separately */ + +#define IWL_MVM_EMLSR_CAPA (IEEE80211_EML_CAP_EMLSR_SUPP | \ + IEEE80211_EML_CAP_EMLSR_PADDING_DELAY_32US << \ + __bf_shf(IEEE80211_EML_CAP_EMLSR_PADDING_DELAY) | \ + IEEE80211_EML_CAP_EMLSR_TRANSITION_DELAY_64US << \ + __bf_shf(IEEE80211_EML_CAP_EMLSR_TRANSITION_DELAY)) + static const struct wiphy_iftype_ext_capab add_iftypes_ext_capa[] = { { .iftype = NL80211_IFTYPE_STATION, .extended_capabilities = he_if_types_ext_capa_sta, .extended_capabilities_mask = he_if_types_ext_capa_sta, .extended_capabilities_len = sizeof(he_if_types_ext_capa_sta), + /* relevant only if EHT is supported */ + .eml_capabilities = IWL_MVM_EMLSR_CAPA, }, { .iftype = NL80211_IFTYPE_STATION, @@ -258,7 +267,7 @@ static const struct wiphy_iftype_ext_capab add_iftypes_ext_capa[] = { .extended_capabilities_mask = tm_if_types_ext_capa_sta, .extended_capabilities_len = sizeof(tm_if_types_ext_capa_sta), /* relevant only if EHT is supported */ - .eml_capabilities = IEEE80211_EML_CAP_EMLSR_SUPP, + .eml_capabilities = IWL_MVM_EMLSR_CAPA, }, }; @@ -1029,6 +1038,7 @@ static void iwl_mvm_cleanup_iterator(void *data, u8 *mac, mvmvif->link[link_id]->fw_link_id = IWL_MVM_FW_LINK_ID_INVALID; mvmvif->link[link_id]->phy_ctxt = NULL; mvmvif->link[link_id]->active = 0; + mvmvif->link[link_id]->igtk = NULL; } probe_data = rcu_dereference_protected(mvmvif->deflink.probe_resp_data, @@ -1233,7 +1243,7 @@ void __iwl_mvm_mac_stop(struct iwl_mvm *mvm) /* async_handlers_wk is now blocked */ - if (iwl_fw_lookup_cmd_ver(mvm->fw, ADD_STA, 0) < 12) + if (!iwl_mvm_has_new_station_api(mvm->fw)) iwl_mvm_rm_aux_sta(mvm); iwl_mvm_stop_device(mvm); @@ -1478,21 +1488,37 @@ iwl_mvm_chandef_get_primary_80(struct cfg80211_chan_def *chandef) return (control_start - data_start) / 80; } -/* - * Returns true if addding the interface is done - * (either with success or failure) - * - * FIXME: remove this again and merge it in - */ -static bool iwl_mvm_mac_add_interface_common(struct iwl_mvm *mvm, - struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - int *ret) +static int iwl_mvm_alloc_bcast_mcast_sta(struct iwl_mvm *mvm, + struct ieee80211_vif *vif) { struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); + int ret; lockdep_assert_held(&mvm->mutex); + ret = iwl_mvm_alloc_bcast_sta(mvm, vif); + if (ret) { + IWL_ERR(mvm, "Failed to allocate bcast sta\n"); + return ret; + } + + /* Only queue for this station is the mcast queue, + * which shouldn't be in TFD mask anyway + */ + return iwl_mvm_allocate_int_sta(mvm, &mvmvif->deflink.mcast_sta, 0, + vif->type, + IWL_STA_MULTICAST); +} + +static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) +{ + struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); + struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); + int ret; + + mutex_lock(&mvm->mutex); + mvmvif->mvm = mvm; /* the first link always points to the default one */ @@ -1510,12 +1536,18 @@ static bool iwl_mvm_mac_add_interface_common(struct iwl_mvm *mvm, mvmvif->deflink.beacon_stats.num_beacons; /* Allocate resources for the MAC context, and add it to the fw */ - *ret = iwl_mvm_mac_ctxt_init(mvm, vif); - if (*ret) - return true; + ret = iwl_mvm_mac_ctxt_init(mvm, vif); + if (ret) + goto out; rcu_assign_pointer(mvm->vif_id_to_mac[mvmvif->id], vif); + /* Currently not much to do for NAN */ + if (vif->type == NL80211_IFTYPE_NAN) { + ret = 0; + goto out; + } + /* * The AP binding flow can be done only after the beacon * template is configured (which happens only in the mac80211 @@ -1530,50 +1562,12 @@ static bool iwl_mvm_mac_add_interface_common(struct iwl_mvm *mvm, if (vif->type == NL80211_IFTYPE_AP || vif->type == NL80211_IFTYPE_ADHOC) { iwl_mvm_vif_dbgfs_register(mvm, vif); - return true; + ret = 0; + goto out; } mvmvif->features |= hw->netdev_features; - return false; -} - -static int iwl_mvm_alloc_bcast_mcast_sta(struct iwl_mvm *mvm, - struct ieee80211_vif *vif) -{ - struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); - int ret; - - lockdep_assert_held(&mvm->mutex); - - ret = iwl_mvm_alloc_bcast_sta(mvm, vif); - if (ret) { - IWL_ERR(mvm, "Failed to allocate bcast sta\n"); - return ret; - } - - /* - * Only queue for this station is the mcast queue, - * which shouldn't be in TFD mask anyway - */ - return iwl_mvm_allocate_int_sta(mvm, &mvmvif->deflink.mcast_sta, 0, - vif->type, - IWL_STA_MULTICAST); -} - -static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw, - struct ieee80211_vif *vif) -{ - struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); - struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); - int ret; - - mutex_lock(&mvm->mutex); - - /* Common for MLD and non-MLD API */ - if (iwl_mvm_mac_add_interface_common(mvm, hw, vif, &ret)) - goto out; - ret = iwl_mvm_mac_ctxt_add(mvm, vif); if (ret) goto out_unlock; @@ -2246,7 +2240,7 @@ int iwl_mvm_set_sta_pkt_ext(struct iwl_mvm *mvm, * is enabled or not */ bool iwl_mvm_set_fw_mu_edca_params(struct iwl_mvm *mvm, - struct iwl_mvm_vif *mvmvif, + const struct iwl_mvm_vif_link_info *link_info, struct iwl_he_backoff_conf *trig_based_txf) { int i; @@ -2254,11 +2248,11 @@ bool iwl_mvm_set_fw_mu_edca_params(struct iwl_mvm *mvm, bool mu_edca_enabled = true; for (i = 0; i < IEEE80211_NUM_ACS; i++) { - struct ieee80211_he_mu_edca_param_ac_rec *mu_edca = - &mvmvif->deflink.queue_params[i].mu_edca_param_rec; + const struct ieee80211_he_mu_edca_param_ac_rec *mu_edca = + &link_info->queue_params[i].mu_edca_param_rec; u8 ac = iwl_mvm_mac80211_ac_to_ucode_ac(i); - if (!mvmvif->deflink.queue_params[i].mu_edca) { + if (!link_info->queue_params[i].mu_edca) { mu_edca_enabled = false; break; } @@ -2285,8 +2279,7 @@ bool iwl_mvm_is_nic_ack_enabled(struct iwl_mvm *mvm, struct ieee80211_vif *vif) * so take it from one of them. */ sband = mvm->hw->wiphy->bands[NL80211_BAND_2GHZ]; - own_he_cap = ieee80211_get_he_iftype_cap(sband, - ieee80211_vif_type_p2p(vif)); + own_he_cap = ieee80211_get_he_iftype_cap_vif(sband, vif); return (own_he_cap && (own_he_cap->he_cap_elem.mac_cap_info[2] & IEEE80211_HE_MAC_CAP2_ACK_EN)); @@ -2405,7 +2398,7 @@ static void iwl_mvm_cfg_he_sta(struct iwl_mvm *mvm, rcu_read_unlock(); - if (iwl_mvm_set_fw_mu_edca_params(mvm, mvmvif, + if (iwl_mvm_set_fw_mu_edca_params(mvm, &mvmvif->deflink, &sta_ctxt_cmd.trig_based_txf[0])) flags |= STA_CTXT_HE_MU_EDCA_CW; @@ -2898,7 +2891,7 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw, if (iwl_mvm_phy_ctx_count(mvm) > 1) iwl_mvm_teardown_tdls_peers(mvm); - iwl_mvm_ftm_restart_responder(mvm, vif); + iwl_mvm_ftm_restart_responder(mvm, vif, &vif->bss_conf); goto out_unlock; @@ -3040,7 +3033,7 @@ iwl_mvm_bss_info_changed_ap_ibss(struct iwl_mvm *mvm, IWL_WARN(mvm, "Failed updating beacon data\n"); if (changes & BSS_CHANGED_FTM_RESPONDER) { - int ret = iwl_mvm_ftm_start_responder(mvm, vif); + int ret = iwl_mvm_ftm_start_responder(mvm, vif, &vif->bss_conf); if (ret) IWL_WARN(mvm, "Failed to enable FTM responder (%d)\n", @@ -3054,7 +3047,7 @@ static void iwl_mvm_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_bss_conf *bss_conf, u64 changes) { - struct iwl_mvm_bss_info_changed_ops callbacks = { + static const struct iwl_mvm_bss_info_changed_ops callbacks = { .bss_info_changed_sta = iwl_mvm_bss_info_changed_station, .bss_info_changed_ap_ibss = iwl_mvm_bss_info_changed_ap_ibss, }; @@ -3067,7 +3060,7 @@ void iwl_mvm_bss_info_changed_common(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *bss_conf, - struct iwl_mvm_bss_info_changed_ops *callbacks, + const struct iwl_mvm_bss_info_changed_ops *callbacks, u64 changes) { struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); @@ -3468,8 +3461,7 @@ static void iwl_mvm_reset_cca_40mhz_workaround(struct iwl_mvm *mvm, sband->ht_cap.cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40; - he_cap = ieee80211_get_he_iftype_cap(sband, - ieee80211_vif_type_p2p(vif)); + he_cap = ieee80211_get_he_iftype_cap_vif(sband, vif); if (he_cap) { /* we know that ours is writable */ @@ -3564,7 +3556,7 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw, enum ieee80211_sta_state old_state, enum ieee80211_sta_state new_state) { - struct iwl_mvm_sta_state_ops callbacks = { + static const struct iwl_mvm_sta_state_ops callbacks = { .add_sta = iwl_mvm_add_sta, .update_sta = iwl_mvm_update_sta, .rm_sta = iwl_mvm_rm_sta, @@ -3669,7 +3661,7 @@ static int iwl_mvm_sta_state_notexist_to_none(struct iwl_mvm *mvm, struct ieee80211_vif *vif, struct ieee80211_sta *sta, - struct iwl_mvm_sta_state_ops *callbacks) + const struct iwl_mvm_sta_state_ops *callbacks) { struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); struct ieee80211_link_sta *link_sta; @@ -3713,7 +3705,7 @@ iwl_mvm_sta_state_auth_to_assoc(struct ieee80211_hw *hw, struct iwl_mvm *mvm, struct ieee80211_vif *vif, struct ieee80211_sta *sta, - struct iwl_mvm_sta_state_ops *callbacks) + const struct iwl_mvm_sta_state_ops *callbacks) { struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta); @@ -3770,7 +3762,7 @@ static int iwl_mvm_sta_state_assoc_to_authorized(struct iwl_mvm *mvm, struct ieee80211_vif *vif, struct ieee80211_sta *sta, - struct iwl_mvm_sta_state_ops *callbacks) + const struct iwl_mvm_sta_state_ops *callbacks) { struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta); @@ -3805,11 +3797,10 @@ static int iwl_mvm_sta_state_authorized_to_assoc(struct iwl_mvm *mvm, struct ieee80211_vif *vif, struct ieee80211_sta *sta, - struct iwl_mvm_sta_state_ops *callbacks) + const struct iwl_mvm_sta_state_ops *callbacks) { struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); - int ret; lockdep_assert_held(&mvm->mutex); @@ -3828,10 +3819,7 @@ iwl_mvm_sta_state_authorized_to_assoc(struct iwl_mvm *mvm, mvmvif->authorized = 0; /* disable beacon filtering */ - ret = iwl_mvm_disable_beacon_filter(mvm, vif, 0); - WARN_ON(ret && - !test_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED, - &mvm->status)); + iwl_mvm_disable_beacon_filter(mvm, vif, 0); } return 0; @@ -3843,11 +3831,12 @@ int iwl_mvm_mac_sta_state_common(struct ieee80211_hw *hw, struct ieee80211_sta *sta, enum ieee80211_sta_state old_state, enum ieee80211_sta_state new_state, - struct iwl_mvm_sta_state_ops *callbacks) + const struct iwl_mvm_sta_state_ops *callbacks) { struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta); + struct ieee80211_link_sta *link_sta; unsigned int link_id; int ret; @@ -3889,7 +3878,7 @@ int iwl_mvm_mac_sta_state_common(struct ieee80211_hw *hw, mutex_lock(&mvm->mutex); /* this would be a mac80211 bug ... but don't crash */ - for_each_mvm_vif_valid_link(mvmvif, link_id) { + for_each_sta_active_link(vif, sta, link_sta, link_id) { if (WARN_ON_ONCE(!mvmvif->link[link_id]->phy_ctxt)) { mutex_unlock(&mvm->mutex); return test_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED, @@ -4533,7 +4522,7 @@ static int iwl_mvm_add_aux_sta_for_hs20(struct iwl_mvm *mvm, u32 lmac_id) return -EINVAL; } - if (iwl_fw_lookup_cmd_ver(mvm->fw, ADD_STA, 0) >= 12) { + if (iwl_mvm_has_new_station_api(mvm->fw)) { ret = iwl_mvm_add_aux_sta(mvm, lmac_id); WARN(ret, "Failed to allocate aux station"); } @@ -4573,7 +4562,7 @@ static int iwl_mvm_roc(struct ieee80211_hw *hw, int duration, enum ieee80211_roc_type type) { - struct iwl_mvm_roc_ops ops = { + static const struct iwl_mvm_roc_ops ops = { .add_aux_sta_for_hs20 = iwl_mvm_add_aux_sta_for_hs20, .switch_phy_ctxt = iwl_mvm_roc_switch_binding, }; @@ -4585,7 +4574,7 @@ static int iwl_mvm_roc(struct ieee80211_hw *hw, int iwl_mvm_roc_common(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_channel *channel, int duration, enum ieee80211_roc_type type, - struct iwl_mvm_roc_ops *ops) + const struct iwl_mvm_roc_ops *ops) { struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); @@ -4608,7 +4597,7 @@ int iwl_mvm_roc_common(struct ieee80211_hw *hw, struct ieee80211_vif *vif, switch (vif->type) { case NL80211_IFTYPE_STATION: - lmac_id = iwl_mvm_get_lmac_id(mvm->fw, channel->band); + lmac_id = iwl_mvm_get_lmac_id(mvm, channel->band); /* Use aux roc framework (HS20) */ ret = ops->add_aux_sta_for_hs20(mvm, lmac_id); @@ -5092,7 +5081,7 @@ static void iwl_mvm_unassign_vif_chanctx(struct ieee80211_hw *hw, static int iwl_mvm_switch_vif_chanctx_swap(struct iwl_mvm *mvm, struct ieee80211_vif_chanctx_switch *vifs, - struct iwl_mvm_switch_vif_chanctx_ops *ops) + const struct iwl_mvm_switch_vif_chanctx_ops *ops) { int ret; @@ -5151,7 +5140,7 @@ iwl_mvm_switch_vif_chanctx_swap(struct iwl_mvm *mvm, static int iwl_mvm_switch_vif_chanctx_reassign(struct iwl_mvm *mvm, struct ieee80211_vif_chanctx_switch *vifs, - struct iwl_mvm_switch_vif_chanctx_ops *ops) + const struct iwl_mvm_switch_vif_chanctx_ops *ops) { int ret; @@ -5194,7 +5183,7 @@ iwl_mvm_switch_vif_chanctx_common(struct ieee80211_hw *hw, struct ieee80211_vif_chanctx_switch *vifs, int n_vifs, enum ieee80211_chanctx_switch_mode mode, - struct iwl_mvm_switch_vif_chanctx_ops *ops) + const struct iwl_mvm_switch_vif_chanctx_ops *ops) { struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); int ret; @@ -5223,7 +5212,7 @@ static int iwl_mvm_switch_vif_chanctx(struct ieee80211_hw *hw, int n_vifs, enum ieee80211_chanctx_switch_mode mode) { - struct iwl_mvm_switch_vif_chanctx_ops ops = { + static const struct iwl_mvm_switch_vif_chanctx_ops ops = { .__assign_vif_chanctx = __iwl_mvm_assign_vif_chanctx, .__unassign_vif_chanctx = __iwl_mvm_unassign_vif_chanctx, }; @@ -5664,6 +5653,30 @@ void iwl_mvm_mac_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif, iwl_trans_wait_tx_queues_empty(mvm->trans, msk); } +void iwl_mvm_mac_flush_sta(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); + int i; + + mutex_lock(&mvm->mutex); + for (i = 0; i < mvm->fw->ucode_capa.num_stations; i++) { + struct iwl_mvm_sta *mvmsta; + struct ieee80211_sta *tmp; + + tmp = rcu_dereference_protected(mvm->fw_id_to_mac_id[i], + lockdep_is_held(&mvm->mutex)); + if (tmp != sta) + continue; + + mvmsta = iwl_mvm_sta_from_mac80211(sta); + + if (iwl_mvm_flush_sta(mvm, mvmsta, false)) + IWL_ERR(mvm, "flush request fail\n"); + } + mutex_unlock(&mvm->mutex); +} + int iwl_mvm_mac_get_survey(struct ieee80211_hw *hw, int idx, struct survey_info *survey) { @@ -6154,10 +6167,6 @@ static bool iwl_mvm_mac_can_aggregate(struct ieee80211_hw *hw, { struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); - if (iwl_mvm_has_new_tx_csum(mvm)) - return iwl_mvm_tx_csum_bz(mvm, head, true) == - iwl_mvm_tx_csum_bz(mvm, skb, true); - /* For now don't aggregate IPv6 in AMSDU */ if (skb->protocol != htons(ETH_P_IP)) return false; @@ -6220,6 +6229,7 @@ const struct ieee80211_ops iwl_mvm_hw_ops = { .mgd_complete_tx = iwl_mvm_mac_mgd_complete_tx, .mgd_protect_tdls_discover = iwl_mvm_mac_mgd_protect_tdls_discover, .flush = iwl_mvm_mac_flush, + .flush_sta = iwl_mvm_mac_flush_sta, .sched_scan_start = iwl_mvm_mac_sched_scan_start, .sched_scan_stop = iwl_mvm_mac_sched_scan_stop, .set_key = iwl_mvm_mac_set_key, @@ -6277,7 +6287,7 @@ const struct ieee80211_ops iwl_mvm_hw_ops = { .can_aggregate_in_amsdu = iwl_mvm_mac_can_aggregate, #ifdef CONFIG_IWLWIFI_DEBUGFS - .sta_add_debugfs = iwl_mvm_sta_add_debugfs, + .link_sta_add_debugfs = iwl_mvm_link_sta_add_debugfs, #endif .set_hw_timestamp = iwl_mvm_set_hw_timestamp, }; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-key.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-key.c index 8853821b3716817b1b45cc6f4ad1b6e01d6acd07..2c9f2f71b083a555b2031519a96969d8b95cfeba 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-key.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-key.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* - * Copyright (C) 2022 Intel Corporation + * Copyright (C) 2022 - 2023 Intel Corporation */ #include #include @@ -42,7 +42,7 @@ static u32 iwl_mvm_get_sec_sta_mask(struct iwl_mvm *mvm, * Of course the same can be done during add as well, but we must do * it during remove, since we don't have the mvmvif->ap_sta pointer. */ - if (!sta && (keyconf->link_id >= 0 || !vif->valid_links)) + if (!sta && (keyconf->link_id >= 0 || !ieee80211_vif_is_mld(vif))) return BIT(link_info->ap_sta_id); /* STA should be non-NULL now, but iwl_mvm_sta_fw_id_mask() checks */ @@ -51,10 +51,10 @@ static u32 iwl_mvm_get_sec_sta_mask(struct iwl_mvm *mvm, return iwl_mvm_sta_fw_id_mask(mvm, sta, keyconf->link_id); } -static u32 iwl_mvm_get_sec_flags(struct iwl_mvm *mvm, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta, - struct ieee80211_key_conf *keyconf) +u32 iwl_mvm_get_sec_flags(struct iwl_mvm *mvm, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + struct ieee80211_key_conf *keyconf) { struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); u32 flags = 0; @@ -164,13 +164,9 @@ static int __iwl_mvm_sec_key_del(struct iwl_mvm *mvm, u32 sta_mask, return iwl_mvm_send_cmd_pdu(mvm, cmd_id, flags, sizeof(cmd), &cmd); } -int iwl_mvm_sec_key_add(struct iwl_mvm *mvm, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta, - struct ieee80211_key_conf *keyconf) +int iwl_mvm_mld_send_key(struct iwl_mvm *mvm, u32 sta_mask, u32 key_flags, + struct ieee80211_key_conf *keyconf) { - u32 sta_mask = iwl_mvm_get_sec_sta_mask(mvm, vif, sta, keyconf); - u32 key_flags = iwl_mvm_get_sec_flags(mvm, vif, sta, keyconf); u32 cmd_id = WIDE_ID(DATA_PATH_GROUP, SEC_KEY_CMD); struct iwl_sec_key_cmd cmd = { .action = cpu_to_le32(FW_CTXT_ACTION_ADD), @@ -179,9 +175,14 @@ int iwl_mvm_sec_key_add(struct iwl_mvm *mvm, .u.add.key_flags = cpu_to_le32(key_flags), .u.add.tx_seq = cpu_to_le64(atomic64_read(&keyconf->tx_pn)), }; + int max_key_len = sizeof(cmd.u.add.key); int ret; - if (WARN_ON(keyconf->keylen > sizeof(cmd.u.add.key))) + if (keyconf->cipher == WLAN_CIPHER_SUITE_WEP40 || + keyconf->cipher == WLAN_CIPHER_SUITE_WEP104) + max_key_len -= IWL_SEC_WEP_KEY_OFFSET; + + if (WARN_ON(keyconf->keylen > max_key_len)) return -EINVAL; if (WARN_ON(!sta_mask)) @@ -223,6 +224,58 @@ int iwl_mvm_sec_key_add(struct iwl_mvm *mvm, return ret; } +int iwl_mvm_sec_key_add(struct iwl_mvm *mvm, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + struct ieee80211_key_conf *keyconf) +{ + u32 sta_mask = iwl_mvm_get_sec_sta_mask(mvm, vif, sta, keyconf); + u32 key_flags = iwl_mvm_get_sec_flags(mvm, vif, sta, keyconf); + struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); + struct iwl_mvm_vif_link_info *mvm_link = NULL; + int ret; + + if (keyconf->keyidx == 4 || keyconf->keyidx == 5) { + unsigned int link_id = 0; + + /* set to -1 for non-MLO right now */ + if (keyconf->link_id >= 0) + link_id = keyconf->link_id; + + mvm_link = mvmvif->link[link_id]; + if (WARN_ON(!mvm_link)) + return -EINVAL; + + if (mvm_link->igtk) { + IWL_DEBUG_MAC80211(mvm, "remove old IGTK %d\n", + mvm_link->igtk->keyidx); + ret = iwl_mvm_sec_key_del(mvm, vif, sta, + mvm_link->igtk); + if (ret) + IWL_ERR(mvm, + "failed to remove old IGTK (ret=%d)\n", + ret); + } + + WARN_ON(mvm_link->igtk); + } + + ret = iwl_mvm_mld_send_key(mvm, sta_mask, key_flags, keyconf); + if (ret) + return ret; + + if (mvm_link) + mvm_link->igtk = keyconf; + + /* We don't really need this, but need it to be not invalid, + * and if we switch links multiple times it might go to be + * invalid when removed. + */ + keyconf->hw_key_idx = 0; + + return 0; +} + static int _iwl_mvm_sec_key_del(struct iwl_mvm *mvm, struct ieee80211_vif *vif, struct ieee80211_sta *sta, @@ -231,11 +284,31 @@ static int _iwl_mvm_sec_key_del(struct iwl_mvm *mvm, { u32 sta_mask = iwl_mvm_get_sec_sta_mask(mvm, vif, sta, keyconf); u32 key_flags = iwl_mvm_get_sec_flags(mvm, vif, sta, keyconf); + struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); int ret; if (WARN_ON(!sta_mask)) return -EINVAL; + if (keyconf->keyidx == 4 || keyconf->keyidx == 5) { + struct iwl_mvm_vif_link_info *mvm_link; + unsigned int link_id = 0; + + /* set to -1 for non-MLO right now */ + if (keyconf->link_id >= 0) + link_id = keyconf->link_id; + + mvm_link = mvmvif->link[link_id]; + if (WARN_ON(!mvm_link)) + return -EINVAL; + + if (mvm_link->igtk == keyconf) { + /* no longer in HW - mark for later */ + mvm_link->igtk->hw_key_idx = STA_KEY_IDX_INVALID; + mvm_link->igtk = NULL; + } + } + ret = __iwl_mvm_sec_key_del(mvm, sta_mask, key_flags, keyconf->keyidx, flags); if (ret) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac.c index 1717fb52dc12373eb94c5e941119ad71991bef1e..f313a8d771e42ed8e68c803623572cc64848dbba 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* - * Copyright (C) 2022 Intel Corporation + * Copyright (C) 2022 - 2023 Intel Corporation */ #include "mvm.h" @@ -50,7 +50,7 @@ static void iwl_mvm_mld_mac_ctxt_cmd_common(struct iwl_mvm *mvm, * the association response successfully, so just skip all that * and enable both when we have MLO. */ - if (vif->valid_links) { + if (ieee80211_vif_is_mld(vif)) { iwl_mvm_mld_set_he_support(mvm, vif, cmd); cmd->eht_support = cpu_to_le32(1); return; @@ -96,6 +96,7 @@ static int iwl_mvm_mld_mac_ctxt_cmd_sta(struct iwl_mvm *mvm, u32 action, bool force_assoc_off) { struct iwl_mac_config_cmd cmd = {}; + u16 esr_transition_timeout; WARN_ON(vif->type != NL80211_IFTYPE_STATION); @@ -115,16 +116,16 @@ static int iwl_mvm_mld_mac_ctxt_cmd_sta(struct iwl_mvm *mvm, if (vif->cfg.assoc && !force_assoc_off) { struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); - cmd.client.is_assoc = cpu_to_le32(1); + cmd.client.is_assoc = 1; if (!mvmvif->authorized && fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_COEX_HIGH_PRIO)) cmd.client.data_policy |= - cpu_to_le32(COEX_HIGH_PRIORITY_ENABLE); + cpu_to_le16(COEX_HIGH_PRIORITY_ENABLE); } else { - cmd.client.is_assoc = cpu_to_le32(0); + cmd.client.is_assoc = 0; /* Allow beacons to pass through as long as we are not * associated, or we do not have dtim period information. @@ -132,14 +133,25 @@ static int iwl_mvm_mld_mac_ctxt_cmd_sta(struct iwl_mvm *mvm, cmd.filter_flags |= cpu_to_le32(MAC_CFG_FILTER_ACCEPT_BEACON); } - cmd.client.assoc_id = cpu_to_le32(vif->cfg.aid); + cmd.client.assoc_id = cpu_to_le16(vif->cfg.aid); + if (ieee80211_vif_is_mld(vif)) { + esr_transition_timeout = + u16_get_bits(vif->cfg.eml_cap, + IEEE80211_EML_CAP_TRANSITION_TIMEOUT); + + cmd.client.esr_transition_timeout = + min_t(u16, IEEE80211_EML_CAP_TRANSITION_TIMEOUT_128TU, + esr_transition_timeout); + cmd.client.medium_sync_delay = + cpu_to_le16(vif->cfg.eml_med_sync_delay); + } if (vif->probe_req_reg && vif->cfg.assoc && vif->p2p) cmd.filter_flags |= cpu_to_le32(MAC_CFG_FILTER_ACCEPT_PROBE_REQ); if (vif->bss_conf.he_support && !iwlwifi_mod_params.disable_11ax) cmd.client.data_policy |= - iwl_mvm_mac_ctxt_cmd_sta_get_twt_policy(mvm, vif); + cpu_to_le16(iwl_mvm_mac_ctxt_cmd_sta_get_twt_policy(mvm, vif)); return iwl_mvm_mld_mac_ctxt_send_cmd(mvm, &cmd); } diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c index 7fb66c5709596af2ffa7c1168e1bcf96879643a4..8b6c641772ee6f697529cbd5eb9ff373b6639f22 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* - * Copyright (C) 2022 Intel Corporation + * Copyright (C) 2022-2023 Intel Corporation */ #include "mvm.h" @@ -215,6 +215,53 @@ static void iwl_mvm_mld_mac_remove_interface(struct ieee80211_hw *hw, mutex_unlock(&mvm->mutex); } +static unsigned int iwl_mvm_mld_count_active_links(struct ieee80211_vif *vif) +{ + unsigned int n_active = 0; + int i; + + for (i = 0; i < IEEE80211_MLD_MAX_NUM_LINKS; i++) { + struct ieee80211_bss_conf *link_conf; + + link_conf = link_conf_dereference_protected(vif, i); + if (link_conf && + rcu_access_pointer(link_conf->chanctx_conf)) + n_active++; + } + + return n_active; +} + +static int iwl_mvm_esr_mode_active(struct iwl_mvm *mvm, + struct ieee80211_vif *vif) +{ + struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); + int link_id, ret = 0; + + mvmvif->esr_active = true; + + /* Disable SMPS overrideing by user */ + vif->driver_flags |= IEEE80211_VIF_DISABLE_SMPS_OVERRIDE; + + iwl_mvm_update_smps_on_active_links(mvm, vif, IWL_MVM_SMPS_REQ_FW, + IEEE80211_SMPS_OFF); + + for_each_mvm_vif_valid_link(mvmvif, link_id) { + struct iwl_mvm_vif_link_info *link = mvmvif->link[link_id]; + + if (!link->phy_ctxt) + continue; + + ret = iwl_mvm_phy_send_rlc(mvm, link->phy_ctxt, 2, 2); + if (ret) + break; + + link->phy_ctxt->rlc_disabled = true; + } + + return ret; +} + static int __iwl_mvm_mld_assign_vif_chanctx(struct iwl_mvm *mvm, struct ieee80211_vif *vif, @@ -224,10 +271,18 @@ __iwl_mvm_mld_assign_vif_chanctx(struct iwl_mvm *mvm, { u16 *phy_ctxt_id = (u16 *)ctx->drv_priv; struct iwl_mvm_phy_ctxt *phy_ctxt = &mvm->phy_ctxts[*phy_ctxt_id]; + unsigned int n_active = iwl_mvm_mld_count_active_links(vif); struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); unsigned int link_id = link_conf->link_id; int ret; + /* if the assigned one was not counted yet, count it now */ + if (!rcu_access_pointer(link_conf->chanctx_conf)) + n_active++; + + if (n_active > iwl_mvm_max_active_links(mvm, vif)) + return -EOPNOTSUPP; + if (WARN_ON_ONCE(!mvmvif->link[link_id])) return -EINVAL; @@ -243,6 +298,15 @@ __iwl_mvm_mld_assign_vif_chanctx(struct iwl_mvm *mvm, } } + if (iwl_mvm_is_esr_supported(mvm->fwrt.trans) && n_active > 1) { + mvmvif->link[link_id]->listen_lmac = true; + ret = iwl_mvm_esr_mode_active(mvm, vif); + if (ret) { + IWL_ERR(mvm, "failed to activate ESR mode (%d)\n", ret); + return ret; + } + } + mvmvif->link[link_id]->phy_ctxt = phy_ctxt; if (switching_chanctx) { @@ -326,14 +390,62 @@ static int iwl_mvm_mld_assign_vif_chanctx(struct ieee80211_hw *hw, return ret; } +static int iwl_mvm_esr_mode_inactive(struct iwl_mvm *mvm, + struct ieee80211_vif *vif) +{ + struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); + struct ieee80211_bss_conf *link_conf; + int link_id, ret = 0; + + mvmvif->esr_active = false; + + vif->driver_flags &= ~IEEE80211_VIF_DISABLE_SMPS_OVERRIDE; + + iwl_mvm_update_smps_on_active_links(mvm, vif, IWL_MVM_SMPS_REQ_FW, + IEEE80211_SMPS_AUTOMATIC); + + for_each_vif_active_link(vif, link_conf, link_id) { + struct ieee80211_chanctx_conf *chanctx_conf; + struct iwl_mvm_phy_ctxt *phy_ctxt; + u8 static_chains, dynamic_chains; + + mvmvif->link[link_id]->listen_lmac = false; + + rcu_read_lock(); + + chanctx_conf = rcu_dereference(link_conf->chanctx_conf); + phy_ctxt = mvmvif->link[link_id]->phy_ctxt; + + if (!chanctx_conf || !phy_ctxt) { + rcu_read_unlock(); + continue; + } + + phy_ctxt->rlc_disabled = false; + static_chains = chanctx_conf->rx_chains_static; + dynamic_chains = chanctx_conf->rx_chains_dynamic; + + rcu_read_unlock(); + + ret = iwl_mvm_phy_send_rlc(mvm, phy_ctxt, static_chains, + dynamic_chains); + if (ret) + break; + } + + return ret; +} + static void __iwl_mvm_mld_unassign_vif_chanctx(struct iwl_mvm *mvm, struct ieee80211_vif *vif, struct ieee80211_bss_conf *link_conf, struct ieee80211_chanctx_conf *ctx, bool switching_chanctx) + { struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); + unsigned int n_active = iwl_mvm_mld_count_active_links(vif); unsigned int link_id = link_conf->link_id; /* shouldn't happen, but verify link_id is valid before accessing */ @@ -352,6 +464,14 @@ __iwl_mvm_mld_unassign_vif_chanctx(struct iwl_mvm *mvm, mvmvif->ap_ibss_active = false; } + if (iwl_mvm_is_esr_supported(mvm->fwrt.trans) && n_active > 1) { + int ret = iwl_mvm_esr_mode_inactive(mvm, vif); + + if (ret) + IWL_ERR(mvm, "failed to deactivate ESR mode (%d)\n", + ret); + } + if (vif->type == NL80211_IFTYPE_MONITOR) iwl_mvm_mld_rm_snif_sta(mvm, vif); @@ -422,7 +542,7 @@ static int iwl_mvm_mld_start_ap_ibss(struct ieee80211_hw *hw, if (iwl_mvm_phy_ctx_count(mvm) > 1) iwl_mvm_teardown_tdls_peers(mvm); - iwl_mvm_ftm_restart_responder(mvm, vif); + iwl_mvm_ftm_restart_responder(mvm, vif, link_conf); goto out_unlock; @@ -492,7 +612,7 @@ static int iwl_mvm_mld_mac_sta_state(struct ieee80211_hw *hw, enum ieee80211_sta_state old_state, enum ieee80211_sta_state new_state) { - struct iwl_mvm_sta_state_ops callbacks = { + static const struct iwl_mvm_sta_state_ops callbacks = { .add_sta = iwl_mvm_mld_add_sta, .update_sta = iwl_mvm_mld_update_sta, .rm_sta = iwl_mvm_mld_rm_sta, @@ -697,7 +817,11 @@ iwl_mvm_mld_link_info_changed_ap_ibss(struct iwl_mvm *mvm, if (link_conf->he_support) link_changes |= LINK_CONTEXT_MODIFY_HE_PARAMS; - if (changes & (BSS_CHANGED_ERP_CTS_PROT | BSS_CHANGED_HT | + if (changes & BSS_CHANGED_ERP_SLOT) + link_changes |= LINK_CONTEXT_MODIFY_RATES_INFO; + + if (changes & (BSS_CHANGED_ERP_CTS_PROT | BSS_CHANGED_ERP_SLOT | + BSS_CHANGED_HT | BSS_CHANGED_BANDWIDTH | BSS_CHANGED_QOS | BSS_CHANGED_HE_BSS_COLOR) && iwl_mvm_link_changed(mvm, vif, link_conf, @@ -711,7 +835,7 @@ iwl_mvm_mld_link_info_changed_ap_ibss(struct iwl_mvm *mvm, /* FIXME: need to decide if we need FTM responder per link */ if (changes & BSS_CHANGED_FTM_RESPONDER) { - int ret = iwl_mvm_ftm_start_responder(mvm, vif); + int ret = iwl_mvm_ftm_start_responder(mvm, vif, link_conf); if (ret) IWL_WARN(mvm, "Failed to enable FTM responder (%d)\n", @@ -779,7 +903,7 @@ iwl_mvm_mld_switch_vif_chanctx(struct ieee80211_hw *hw, int n_vifs, enum ieee80211_chanctx_switch_mode mode) { - struct iwl_mvm_switch_vif_chanctx_ops ops = { + static const struct iwl_mvm_switch_vif_chanctx_ops ops = { .__assign_vif_chanctx = __iwl_mvm_mld_assign_vif_chanctx, .__unassign_vif_chanctx = __iwl_mvm_mld_unassign_vif_chanctx, }; @@ -816,8 +940,12 @@ iwl_mvm_mld_mac_conf_tx(struct ieee80211_hw *hw, { struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); + struct iwl_mvm_vif_link_info *mvm_link = mvmvif->link[link_id]; - mvmvif->deflink.queue_params[ac] = *params; + if (!mvm_link) + return -EINVAL; + + mvm_link->queue_params[ac] = *params; /* No need to update right away, we'll get BSS_CHANGED_QOS * The exception is P2P_DEVICE interface which needs immediate update. @@ -871,7 +999,7 @@ static int iwl_mvm_mld_roc(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_channel *channel, int duration, enum ieee80211_roc_type type) { - struct iwl_mvm_roc_ops ops = { + static const struct iwl_mvm_roc_ops ops = { .add_aux_sta_for_hs20 = iwl_mvm_mld_add_aux_sta, .switch_phy_ctxt = iwl_mvm_link_switch_phy_ctx, }; @@ -886,33 +1014,16 @@ iwl_mvm_mld_change_vif_links(struct ieee80211_hw *hw, struct ieee80211_bss_conf *old[IEEE80211_MLD_MAX_NUM_LINKS]) { struct iwl_mvm_vif_link_info *new_link[IEEE80211_MLD_MAX_NUM_LINKS] = {}; + unsigned int n_active = iwl_mvm_mld_count_active_links(vif); struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); u16 removed = old_links & ~new_links; u16 added = new_links & ~old_links; int err, i; - if (hweight16(new_links) > 2) { + if (hweight16(new_links) > 1 && + n_active > iwl_mvm_max_active_links(mvm, vif)) return -EOPNOTSUPP; - } else if (hweight16(new_links) > 1) { - unsigned int n_active = 0; - - for (i = 0; i < IEEE80211_MLD_MAX_NUM_LINKS; i++) { - struct ieee80211_bss_conf *link_conf; - - link_conf = link_conf_dereference_protected(vif, i); - if (link_conf && - rcu_access_pointer(link_conf->chanctx_conf)) - n_active++; - } - - if (vif->type == NL80211_IFTYPE_AP) { - if (n_active > mvm->fw->ucode_capa.num_beacons) - return -EOPNOTSUPP; - } else if (n_active > 1) { - return -EOPNOTSUPP; - } - } for (i = 0; i < IEEE80211_MLD_MAX_NUM_LINKS; i++) { int r; @@ -956,9 +1067,7 @@ iwl_mvm_mld_change_vif_links(struct ieee80211_hw *hw, goto out_err; kfree(mvmvif->link[i]); mvmvif->link[i] = NULL; - } - - if (added & BIT(i)) { + } else if (added & BIT(i)) { struct ieee80211_bss_conf *link_conf; link_conf = link_conf_dereference_protected(vif, i); @@ -975,6 +1084,9 @@ iwl_mvm_mld_change_vif_links(struct ieee80211_hw *hw, } } + if (err) + goto out_err; + err = 0; if (new_links == 0) { mvmvif->link[0] = &mvmvif->deflink; @@ -1037,6 +1149,7 @@ const struct ieee80211_ops iwl_mvm_mld_hw_ops = { .mgd_complete_tx = iwl_mvm_mac_mgd_complete_tx, .mgd_protect_tdls_discover = iwl_mvm_mac_mgd_protect_tdls_discover, .flush = iwl_mvm_mac_flush, + .flush_sta = iwl_mvm_mac_flush_sta, .sched_scan_start = iwl_mvm_mac_sched_scan_start, .sched_scan_stop = iwl_mvm_mac_sched_scan_stop, .set_key = iwl_mvm_mac_set_key, @@ -1093,7 +1206,7 @@ const struct ieee80211_ops iwl_mvm_mld_hw_ops = { .abort_pmsr = iwl_mvm_abort_pmsr, #ifdef CONFIG_IWLWIFI_DEBUGFS - .sta_add_debugfs = iwl_mvm_sta_add_debugfs, + .link_sta_add_debugfs = iwl_mvm_link_sta_add_debugfs, #endif .set_hw_timestamp = iwl_mvm_set_hw_timestamp, diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c index 85a4ce8449ade824dc067961ac2938b4e4cfc661..524852cf5cd2db22a6781f48b06c1b978c752e7a 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* - * Copyright (C) 2022 Intel Corporation + * Copyright (C) 2022-2023 Intel Corporation */ #include "mvm.h" #include "time-sync.h" @@ -71,6 +71,11 @@ static int iwl_mvm_mld_add_int_sta_to_fw(struct iwl_mvm *mvm, cmd.station_type = cpu_to_le32(sta->type); + if (fw_has_capa(&mvm->fw->ucode_capa, + IWL_UCODE_TLV_CAPA_STA_EXP_MFP_SUPPORT) && + sta->type == STATION_TYPE_BCAST_MGMT) + cmd.mfp = cpu_to_le32(1); + if (addr) { memcpy(cmd.peer_mld_address, addr, ETH_ALEN); memcpy(cmd.peer_link_address, addr, ETH_ALEN); @@ -128,11 +133,11 @@ static int iwl_mvm_add_aux_sta_to_fw(struct iwl_mvm *mvm, /* * Adds an internal sta to the FW table with its queues */ -static int iwl_mvm_mld_add_int_sta_with_queue(struct iwl_mvm *mvm, - struct iwl_mvm_int_sta *sta, - const u8 *addr, int link_id, - u16 *queue, u8 tid, - unsigned int *_wdg_timeout) +int iwl_mvm_mld_add_int_sta_with_queue(struct iwl_mvm *mvm, + struct iwl_mvm_int_sta *sta, + const u8 *addr, int link_id, + u16 *queue, u8 tid, + unsigned int *_wdg_timeout) { int ret, txq; unsigned int wdg_timeout = _wdg_timeout ? *_wdg_timeout : @@ -364,6 +369,9 @@ int iwl_mvm_mld_rm_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif, lockdep_assert_held(&mvm->mutex); + if (WARN_ON(!link)) + return -EIO; + switch (vif->type) { case NL80211_IFTYPE_AP: case NL80211_IFTYPE_ADHOC: @@ -393,6 +401,9 @@ int iwl_mvm_mld_rm_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif, lockdep_assert_held(&mvm->mutex); + if (WARN_ON(!link)) + return -EIO; + return iwl_mvm_mld_rm_int_sta(mvm, &link->mcast_sta, true, 0, &link->cab_queue); } @@ -442,6 +453,11 @@ static int iwl_mvm_mld_cfg_sta(struct iwl_mvm *mvm, struct ieee80211_sta *sta, if (mvm_sta->sta_state >= IEEE80211_STA_ASSOC) cmd.assoc_id = cpu_to_le32(sta->aid); + if (fw_has_capa(&mvm->fw->ucode_capa, + IWL_UCODE_TLV_CAPA_STA_EXP_MFP_SUPPORT) && + (sta->mfp || mvm_sta->sta_state < IEEE80211_STA_AUTHORIZED)) + cmd.mfp = cpu_to_le32(1); + switch (link_sta->rx_nss) { case 1: cmd.mimo = cpu_to_le32(0); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index 9e5008e0e47f5c1824854c654a101cda4600caa3..b18c91c5dd5d1c0691ab910c38184344776a5566 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ /* - * Copyright (C) 2012-2014, 2018-2022 Intel Corporation + * Copyright (C) 2012-2014, 2018-2023 Intel Corporation * Copyright (C) 2013-2015 Intel Mobile Communications GmbH * Copyright (C) 2016-2017 Intel Deutschland GmbH */ @@ -104,6 +104,7 @@ struct iwl_mvm_phy_ctxt { /* track for RLC config command */ u32 center_freq1; + bool rlc_disabled; }; struct iwl_mvm_time_event_data { @@ -300,6 +301,8 @@ struct iwl_probe_resp_data { * @he_ru_2mhz_block: 26-tone RU OFDMA transmissions should be blocked * @queue_params: QoS params for this MAC * @mgmt_queue: queue number for unbufferable management frames + * @igtk: the current IGTK programmed into the firmware + * @listen_lmac: indicates this link is allocated to the listen LMAC */ struct iwl_mvm_vif_link_info { u8 bssid[ETH_ALEN]; @@ -317,8 +320,11 @@ struct iwl_mvm_vif_link_info { enum ieee80211_smps_mode smps_requests[NUM_IWL_MVM_SMPS_REQ]; struct iwl_probe_resp_data __rcu *probe_resp_data; + struct ieee80211_key_conf *igtk; + bool he_ru_2mhz_block; bool active; + bool listen_lmac; u16 cab_queue; /* Assigned while mac80211 has the link in a channel context, @@ -370,6 +376,7 @@ struct iwl_mvm_vif { bool ap_ibss_active; bool pm_enabled; bool monitor_active; + bool esr_active; u8 low_latency: 6; u8 low_latency_actual: 1; @@ -415,7 +422,7 @@ struct iwl_mvm_vif { #endif /* FW identified misbehaving AP */ - u8 uapsd_misbehaving_bssid[ETH_ALEN]; + u8 uapsd_misbehaving_ap_addr[ETH_ALEN] __aligned(2); struct delayed_work uapsd_nonagg_detected_wk; bool csa_countdown; @@ -1003,6 +1010,8 @@ struct iwl_mvm { struct ieee80211_vif __rcu *vif_id_to_mac[NUM_MAC_INDEX_DRIVER]; + struct ieee80211_bss_conf __rcu *link_id_to_link_conf[IWL_MVM_FW_MAX_LINK_ID + 1]; + /* -1 for always, 0 for never, >0 for that many times */ s8 fw_restart; u8 *error_recovery_buf; @@ -1174,6 +1183,10 @@ struct iwl_mvm { __le16 cur_aid; u8 cur_bssid[ETH_ALEN]; +#ifdef CONFIG_ACPI + struct iwl_phy_specific_cfg phy_filters; +#endif + unsigned long last_6ghz_passive_scan_jiffies; unsigned long last_reset_or_resume_time_jiffies; @@ -1302,6 +1315,19 @@ iwl_mvm_rcu_dereference_vif_id(struct iwl_mvm *mvm, u8 vif_id, bool rcu) lockdep_is_held(&mvm->mutex)); } +static inline struct ieee80211_bss_conf * +iwl_mvm_rcu_fw_link_id_to_link_conf(struct iwl_mvm *mvm, u8 link_id, bool rcu) +{ + if (WARN_ON(link_id >= ARRAY_SIZE(mvm->link_id_to_link_conf))) + return NULL; + + if (rcu) + return rcu_dereference(mvm->link_id_to_link_conf[link_id]); + + return rcu_dereference_protected(mvm->link_id_to_link_conf[link_id], + lockdep_is_held(&mvm->mutex)); +} + static inline bool iwl_mvm_is_adaptive_dwell_supported(struct iwl_mvm *mvm) { return fw_has_api(&mvm->fw->ucode_capa, @@ -1415,10 +1441,16 @@ static inline bool iwl_mvm_has_mld_api(const struct iwl_fw *fw) IWL_UCODE_TLV_CAPA_MLD_API_SUPPORT); } +static inline bool iwl_mvm_has_new_station_api(const struct iwl_fw *fw) +{ + return iwl_mvm_has_mld_api(fw) || + iwl_fw_lookup_cmd_ver(fw, ADD_STA, 0) >= 12; +} + static inline bool iwl_mvm_has_new_tx_api(struct iwl_mvm *mvm) { /* TODO - replace with TLV once defined */ - return mvm->trans->trans_cfg->use_tfh; + return mvm->trans->trans_cfg->gen2; } static inline bool iwl_mvm_has_unified_ucode(struct iwl_mvm *mvm) @@ -1516,17 +1548,30 @@ static inline bool iwl_mvm_is_ctdp_supported(struct iwl_mvm *mvm) IWL_UCODE_TLV_CAPA_CTDP_SUPPORT); } -static inline bool iwl_mvm_has_new_tx_csum(struct iwl_mvm *mvm) +static inline bool iwl_mvm_is_esr_supported(struct iwl_trans *trans) +{ + if ((CSR_HW_RFID_TYPE(trans->hw_rf_id) == IWL_CFG_RF_TYPE_FM) && + !CSR_HW_RFID_IS_CDB(trans->hw_rf_id)) + /* Step A doesn't support eSR */ + return CSR_HW_RFID_STEP(trans->hw_rf_id); + + return false; +} + +static inline int iwl_mvm_max_active_links(struct iwl_mvm *mvm, + struct ieee80211_vif *vif) { - if (mvm->trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_BZ) - return false; + struct iwl_trans *trans = mvm->fwrt.trans; + + if (vif->type == NL80211_IFTYPE_AP) + return mvm->fw->ucode_capa.num_beacons; - if (mvm->trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_BZ && - CSR_HW_REV_TYPE(mvm->trans->hw_rev) == IWL_CFG_MAC_TYPE_GL && - mvm->trans->hw_rev_step <= SILICON_B_STEP) - return false; + if (iwl_mvm_is_esr_supported(trans) || + (CSR_HW_RFID_TYPE(trans->hw_rf_id) == IWL_CFG_RF_TYPE_FM && + CSR_HW_RFID_IS_CDB(trans->hw_rf_id))) + return IWL_MVM_FW_MAX_ACTIVE_LINKS_NUM; - return true; + return 1; } extern const u8 iwl_mvm_ac_to_tx_fifo[]; @@ -1606,7 +1651,6 @@ void iwl_mvm_mac_itxq_xmit(struct ieee80211_hw *hw, struct ieee80211_txq *txq); unsigned int iwl_mvm_max_amsdu_size(struct iwl_mvm *mvm, struct ieee80211_sta *sta, unsigned int tid); -u32 iwl_mvm_tx_csum_bz(struct iwl_mvm *mvm, struct sk_buff *skb, bool amsdu); #ifdef CONFIG_IWLWIFI_DEBUG const char *iwl_mvm_get_tx_fail_reason(u32 status); @@ -1741,6 +1785,8 @@ void iwl_mvm_phy_ctxt_unref(struct iwl_mvm *mvm, int iwl_mvm_phy_ctx_count(struct iwl_mvm *mvm); u8 iwl_mvm_get_channel_width(struct cfg80211_chan_def *chandef); u8 iwl_mvm_get_ctrl_pos(struct cfg80211_chan_def *chandef); +int iwl_mvm_phy_send_rlc(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt, + u8 chains_static, u8 chains_dynamic); /* MAC (virtual interface) programming */ @@ -1758,7 +1804,7 @@ void iwl_mvm_set_fw_qos_params(struct iwl_mvm *mvm, struct ieee80211_vif *vif, struct ieee80211_bss_conf *link_conf, struct iwl_ac_qos *ac, __le32 *qos_flags); bool iwl_mvm_set_fw_mu_edca_params(struct iwl_mvm *mvm, - struct iwl_mvm_vif *mvmvif, + const struct iwl_mvm_vif_link_info *link_info, struct iwl_he_backoff_conf *trig_based_txf); void iwl_mvm_set_fw_dtim_tbtt(struct iwl_mvm *mvm, struct ieee80211_vif *vif, struct ieee80211_bss_conf *link_conf, @@ -1774,8 +1820,8 @@ void iwl_mvm_mac_ctxt_cmd_ap_set_filter_flags(struct iwl_mvm *mvm, int iwl_mvm_get_mac_type(struct ieee80211_vif *vif); __le32 iwl_mvm_mac_ctxt_cmd_p2p_sta_get_oppps_ctwin(struct iwl_mvm *mvm, struct ieee80211_vif *vif); -__le32 iwl_mvm_mac_ctxt_cmd_sta_get_twt_policy(struct iwl_mvm *mvm, - struct ieee80211_vif *vif); +u32 iwl_mvm_mac_ctxt_cmd_sta_get_twt_policy(struct iwl_mvm *mvm, + struct ieee80211_vif *vif); int iwl_mvm_mld_mac_ctxt_add(struct iwl_mvm *mvm, struct ieee80211_vif *vif); int iwl_mvm_mld_mac_ctxt_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif, bool force_assoc_off); @@ -1826,6 +1872,7 @@ void iwl_mvm_channel_switch_error_notif(struct iwl_mvm *mvm, /* Bindings */ int iwl_mvm_binding_add_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif); int iwl_mvm_binding_remove_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif); +u32 iwl_mvm_get_lmac_id(struct iwl_mvm *mvm, enum nl80211_band band); /* Links */ int iwl_mvm_add_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif, @@ -1873,7 +1920,7 @@ void iwl_mvm_bss_info_changed_common(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *bss_conf, - struct iwl_mvm_bss_info_changed_ops *callbacks, + const struct iwl_mvm_bss_info_changed_ops *callbacks, u64 changes); void iwl_mvm_bss_info_changed_station_common(struct iwl_mvm *mvm, @@ -1907,7 +1954,7 @@ struct iwl_mvm_roc_ops { int iwl_mvm_roc_common(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_channel *channel, int duration, enum ieee80211_roc_type type, - struct iwl_mvm_roc_ops *ops); + const struct iwl_mvm_roc_ops *ops); int iwl_mvm_cancel_roc(struct ieee80211_hw *hw, struct ieee80211_vif *vif); /*Session Protection */ @@ -2204,7 +2251,7 @@ static inline void iwl_mvm_vendor_cmds_register(struct iwl_mvm *mvm) {} #endif /* Location Aware Regulatory */ -struct iwl_mcc_update_resp * +struct iwl_mcc_update_resp_v8 * iwl_mvm_update_mcc(struct iwl_mvm *mvm, const char *alpha2, enum iwl_mcc_source src_id); int iwl_mvm_init_mcc(struct iwl_mvm *mvm); @@ -2224,9 +2271,11 @@ int iwl_mvm_sf_update(struct iwl_mvm *mvm, struct ieee80211_vif *vif, bool added_vif); /* FTM responder */ -int iwl_mvm_ftm_start_responder(struct iwl_mvm *mvm, struct ieee80211_vif *vif); +int iwl_mvm_ftm_start_responder(struct iwl_mvm *mvm, struct ieee80211_vif *vif, + struct ieee80211_bss_conf *bss_conf); void iwl_mvm_ftm_restart_responder(struct iwl_mvm *mvm, - struct ieee80211_vif *vif); + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *bss_conf); void iwl_mvm_ftm_responder_stats(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb); int iwl_mvm_ftm_resp_remove_pasn_sta(struct iwl_mvm *mvm, @@ -2322,10 +2371,10 @@ int iwl_mvm_get_sar_geo_profile(struct iwl_mvm *mvm); int iwl_mvm_ppag_send_cmd(struct iwl_mvm *mvm); void iwl_mvm_get_acpi_tables(struct iwl_mvm *mvm); #ifdef CONFIG_IWLWIFI_DEBUGFS -void iwl_mvm_sta_add_debugfs(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta, - struct dentry *dir); +void iwl_mvm_link_sta_add_debugfs(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_link_sta *link_sta, + struct dentry *dir); #endif /* new MLD related APIs */ @@ -2346,6 +2395,12 @@ int iwl_mvm_mld_update_sta_keys(struct iwl_mvm *mvm, struct ieee80211_sta *sta, u32 old_sta_mask, u32 new_sta_mask); +int iwl_mvm_mld_send_key(struct iwl_mvm *mvm, u32 sta_mask, u32 key_flags, + struct ieee80211_key_conf *keyconf); +u32 iwl_mvm_get_sec_flags(struct iwl_mvm *mvm, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + struct ieee80211_key_conf *keyconf); bool iwl_rfi_supported(struct iwl_mvm *mvm); int iwl_rfi_send_config_cmd(struct iwl_mvm *mvm, @@ -2406,7 +2461,7 @@ iwl_mvm_switch_vif_chanctx_common(struct ieee80211_hw *hw, struct ieee80211_vif_chanctx_switch *vifs, int n_vifs, enum ieee80211_chanctx_switch_mode mode, - struct iwl_mvm_switch_vif_chanctx_ops *ops); + const struct iwl_mvm_switch_vif_chanctx_ops *ops); /* Channel info utils */ static inline bool iwl_mvm_has_ultra_hb_channel(struct iwl_mvm *mvm) @@ -2604,6 +2659,8 @@ void iwl_mvm_mac_mgd_complete_tx(struct ieee80211_hw *hw, struct ieee80211_prep_tx_info *info); void iwl_mvm_mac_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u32 queues, bool drop); +void iwl_mvm_mac_flush_sta(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_sta *sta); int iwl_mvm_mac_sched_scan_start(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct cfg80211_sched_scan_request *req, diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c b/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c index fdf60afb0f3f26ec9e96f9132aacf45d61564ae4..f67ab8ee18c243a7bb92f063a227301c0900de41 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c @@ -404,7 +404,7 @@ int iwl_nvm_init(struct iwl_mvm *mvm) return ret < 0 ? ret : 0; } -struct iwl_mcc_update_resp * +struct iwl_mcc_update_resp_v8 * iwl_mvm_update_mcc(struct iwl_mvm *mvm, const char *alpha2, enum iwl_mcc_source src_id) { @@ -412,7 +412,7 @@ iwl_mvm_update_mcc(struct iwl_mvm *mvm, const char *alpha2, .mcc = cpu_to_le16(alpha2[0] << 8 | alpha2[1]), .source_id = (u8)src_id, }; - struct iwl_mcc_update_resp *resp_cp; + struct iwl_mcc_update_resp_v8 *resp_cp; struct iwl_rx_packet *pkt; struct iwl_host_cmd cmd = { .id = MCC_UPDATE_CMD, @@ -420,7 +420,7 @@ iwl_mvm_update_mcc(struct iwl_mvm *mvm, const char *alpha2, .data = { &mcc_update_cmd }, }; - int ret; + int ret, resp_ver; u32 status; int resp_len, n_channels; u16 mcc; @@ -439,24 +439,60 @@ iwl_mvm_update_mcc(struct iwl_mvm *mvm, const char *alpha2, pkt = cmd.resp_pkt; + resp_ver = iwl_fw_lookup_notif_ver(mvm->fw, IWL_ALWAYS_LONG_GROUP, + MCC_UPDATE_CMD, 0); + /* Extract MCC response */ - if (fw_has_capa(&mvm->fw->ucode_capa, - IWL_UCODE_TLV_CAPA_MCC_UPDATE_11AX_SUPPORT)) { - struct iwl_mcc_update_resp *mcc_resp = (void *)pkt->data; + if (resp_ver >= 8) { + struct iwl_mcc_update_resp_v8 *mcc_resp_v8 = (void *)pkt->data; + + n_channels = __le32_to_cpu(mcc_resp_v8->n_channels); + if (iwl_rx_packet_payload_len(pkt) != + struct_size(mcc_resp_v8, channels, n_channels)) { + resp_cp = ERR_PTR(-EINVAL); + goto exit; + } + resp_len = struct_size(resp_cp, channels, n_channels); + resp_cp = kzalloc(resp_len, GFP_KERNEL); + if (!resp_cp) { + resp_cp = ERR_PTR(-ENOMEM); + goto exit; + } + resp_cp->status = mcc_resp_v8->status; + resp_cp->mcc = mcc_resp_v8->mcc; + resp_cp->cap = mcc_resp_v8->cap; + resp_cp->source_id = mcc_resp_v8->source_id; + resp_cp->time = mcc_resp_v8->time; + resp_cp->geo_info = mcc_resp_v8->geo_info; + resp_cp->n_channels = mcc_resp_v8->n_channels; + memcpy(resp_cp->channels, mcc_resp_v8->channels, + n_channels * sizeof(__le32)); + } else if (fw_has_capa(&mvm->fw->ucode_capa, + IWL_UCODE_TLV_CAPA_MCC_UPDATE_11AX_SUPPORT)) { + struct iwl_mcc_update_resp_v4 *mcc_resp_v4 = (void *)pkt->data; - n_channels = __le32_to_cpu(mcc_resp->n_channels); + n_channels = __le32_to_cpu(mcc_resp_v4->n_channels); if (iwl_rx_packet_payload_len(pkt) != - struct_size(mcc_resp, channels, n_channels)) { + struct_size(mcc_resp_v4, channels, n_channels)) { resp_cp = ERR_PTR(-EINVAL); goto exit; } - resp_len = sizeof(struct iwl_mcc_update_resp) + - n_channels * sizeof(__le32); - resp_cp = kmemdup(mcc_resp, resp_len, GFP_KERNEL); + resp_len = struct_size(resp_cp, channels, n_channels); + resp_cp = kzalloc(resp_len, GFP_KERNEL); if (!resp_cp) { resp_cp = ERR_PTR(-ENOMEM); goto exit; } + + resp_cp->status = mcc_resp_v4->status; + resp_cp->mcc = mcc_resp_v4->mcc; + resp_cp->cap = cpu_to_le32(le16_to_cpu(mcc_resp_v4->cap)); + resp_cp->source_id = mcc_resp_v4->source_id; + resp_cp->time = mcc_resp_v4->time; + resp_cp->geo_info = mcc_resp_v4->geo_info; + resp_cp->n_channels = mcc_resp_v4->n_channels; + memcpy(resp_cp->channels, mcc_resp_v4->channels, + n_channels * sizeof(__le32)); } else { struct iwl_mcc_update_resp_v3 *mcc_resp_v3 = (void *)pkt->data; @@ -466,8 +502,7 @@ iwl_mvm_update_mcc(struct iwl_mvm *mvm, const char *alpha2, resp_cp = ERR_PTR(-EINVAL); goto exit; } - resp_len = sizeof(struct iwl_mcc_update_resp) + - n_channels * sizeof(__le32); + resp_len = struct_size(resp_cp, channels, n_channels); resp_cp = kzalloc(resp_len, GFP_KERNEL); if (!resp_cp) { resp_cp = ERR_PTR(-ENOMEM); @@ -476,7 +511,7 @@ iwl_mvm_update_mcc(struct iwl_mvm *mvm, const char *alpha2, resp_cp->status = mcc_resp_v3->status; resp_cp->mcc = mcc_resp_v3->mcc; - resp_cp->cap = cpu_to_le16(mcc_resp_v3->cap); + resp_cp->cap = cpu_to_le32(mcc_resp_v3->cap); resp_cp->source_id = mcc_resp_v3->source_id; resp_cp->time = mcc_resp_v3->time; resp_cp->geo_info = mcc_resp_v3->geo_info; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/offloading.c b/drivers/net/wireless/intel/iwlwifi/mvm/offloading.c index a8bd0f5f795cc109471219499aee42916fc6af93..dfb16ca5b4388e38355b4adcd0e63e3d58853b67 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/offloading.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/offloading.c @@ -198,6 +198,10 @@ int iwl_mvm_send_proto_offload(struct iwl_mvm *mvm, memcpy(common->arp_mac_addr, vif->addr, ETH_ALEN); } + if (fw_has_capa(&mvm->fw->ucode_capa, + IWL_UCODE_TLV_CAPA_OFFLOAD_BTM_SUPPORT)) + enabled |= IWL_D3_PROTO_OFFLOAD_BTM; + if (!disable_offloading) common->enabled = cpu_to_le32(enabled); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c index 32625bfacaaef3ba017a12fea9efb5d691c49fe9..5336a4afde4d23e2beb0d6fc9c2e02adb9ba1703 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* - * Copyright (C) 2012-2014, 2018-2020 Intel Corporation + * Copyright (C) 2012-2014, 2018-2023 Intel Corporation * Copyright (C) 2013-2015 Intel Mobile Communications GmbH * Copyright (C) 2016-2017 Intel Deutschland GmbH */ @@ -192,8 +192,7 @@ static void iwl_mvm_rx_monitor_notif(struct iwl_mvm *mvm, WARN_ON(!(sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40)); sband->ht_cap.cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; - he_cap = ieee80211_get_he_iftype_cap(sband, - ieee80211_vif_type_p2p(vif)); + he_cap = ieee80211_get_he_iftype_cap_vif(sband, vif); if (he_cap) { /* we know that ours is writable */ @@ -449,7 +448,6 @@ static const struct iwl_hcmd_names iwl_mvm_legacy_names[] = { HCMD_NAME(ADD_STA_KEY), HCMD_NAME(ADD_STA), HCMD_NAME(REMOVE_STA), - HCMD_NAME(FW_GET_ITEM_CMD), HCMD_NAME(TX_CMD), HCMD_NAME(SCD_QUEUE_CFG), HCMD_NAME(TXPATH_FLUSH), @@ -512,7 +510,6 @@ static const struct iwl_hcmd_names iwl_mvm_legacy_names[] = { HCMD_NAME(REPLY_BEACON_FILTERING_CMD), HCMD_NAME(D3_CONFIG_CMD), HCMD_NAME(PROT_OFFLOAD_CONFIG_CMD), - HCMD_NAME(OFFLOADS_QUERY_CMD), HCMD_NAME(MATCH_FOUND_NOTIFICATION), HCMD_NAME(DTS_MEASUREMENT_NOTIFICATION), HCMD_NAME(WOWLAN_PATTERNS), @@ -1604,7 +1601,9 @@ static void iwl_mvm_rx_common(struct iwl_mvm *mvm, if (rx_h->cmd_id != WIDE_ID(pkt->hdr.group_id, pkt->hdr.cmd)) continue; - if (unlikely(pkt_len < rx_h->min_size)) + if (IWL_FW_CHECK(mvm, pkt_len < rx_h->min_size, + "unexpected notification 0x%04x size %d, need %d\n", + rx_h->cmd_id, pkt_len, rx_h->min_size)) return; if (rx_h->context == RX_HANDLER_SYNC) { @@ -1743,8 +1742,11 @@ static void iwl_mvm_queue_state_change(struct iwl_op_mode *op_mode, else set_bit(IWL_MVM_TXQ_STATE_STOP_FULL, &mvmtxq->state); - if (start && mvmsta->sta_state != IEEE80211_STA_NOTEXIST) + if (start && mvmsta->sta_state != IEEE80211_STA_NOTEXIST) { + local_bh_disable(); iwl_mvm_mac_itxq_xmit(mvm->hw, txq); + local_bh_enable(); + } } out: diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/phy-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/phy-ctxt.c index 3ab6fb83a1756efb98b88ca17c24fbd32449169d..a5b432bc9e2f82e3394c9b1b5761f6c4d3e5857b 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/phy-ctxt.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/phy-ctxt.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* - * Copyright (C) 2012-2014, 2018-2022 Intel Corporation + * Copyright (C) 2012-2014, 2018-2023 Intel Corporation * Copyright (C) 2013-2014 Intel Mobile Communications GmbH * Copyright (C) 2017 Intel Deutschland GmbH */ @@ -151,7 +151,7 @@ static void iwl_mvm_phy_ctxt_cmd_data(struct iwl_mvm *mvm, struct cfg80211_chan_def *chandef, u8 chains_static, u8 chains_dynamic) { - cmd->lmac_id = cpu_to_le32(iwl_mvm_get_lmac_id(mvm->fw, + cmd->lmac_id = cpu_to_le32(iwl_mvm_get_lmac_id(mvm, chandef->chan->band)); /* Set the channel info data */ @@ -163,15 +163,18 @@ static void iwl_mvm_phy_ctxt_cmd_data(struct iwl_mvm *mvm, chains_static, chains_dynamic); } -static int iwl_mvm_phy_send_rlc(struct iwl_mvm *mvm, - struct iwl_mvm_phy_ctxt *ctxt, - u8 chains_static, u8 chains_dynamic) +int iwl_mvm_phy_send_rlc(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt, + u8 chains_static, u8 chains_dynamic) { struct iwl_rlc_config_cmd cmd = { .phy_id = cpu_to_le32(ctxt->id), }; - if (iwl_fw_lookup_cmd_ver(mvm->fw, WIDE_ID(DATA_PATH_GROUP, RLC_CONFIG_CMD), 0) < 2) + if (ctxt->rlc_disabled) + return 0; + + if (iwl_fw_lookup_cmd_ver(mvm->fw, WIDE_ID(DATA_PATH_GROUP, + RLC_CONFIG_CMD), 0) < 2) return 0; BUILD_BUG_ON(IWL_RLC_CHAIN_INFO_DRIVER_FORCE != diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/power.c b/drivers/net/wireless/intel/iwlwifi/mvm/power.c index ac1dae52556f8b632d2126dd4a79845f70079965..9131b5f1bc76174c33270fb60dba95c5429cb2a4 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/power.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/power.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* - * Copyright (C) 2012-2014, 2018-2019, 2021 Intel Corporation + * Copyright (C) 2012-2014, 2018-2019, 2021-2023 Intel Corporation * Copyright (C) 2013-2014 Intel Mobile Communications GmbH * Copyright (C) 2015-2017 Intel Deutschland GmbH */ @@ -237,8 +237,8 @@ static bool iwl_mvm_power_allow_uapsd(struct iwl_mvm *mvm, { struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); - if (!memcmp(mvmvif->uapsd_misbehaving_bssid, vif->bss_conf.bssid, - ETH_ALEN)) + if (ether_addr_equal(mvmvif->uapsd_misbehaving_ap_addr, + vif->cfg.ap_addr)) return false; /* @@ -327,12 +327,11 @@ static void iwl_mvm_power_config_skip_dtim(struct iwl_mvm *mvm, if (WARN_ON(!dtimper_tu)) return; - /* configure skip over dtim up to 306TU - 314 msec */ - skip = max_t(u8, 1, 306 / dtimper_tu); + /* configure skip over dtim up to 900 TU DTIM interval */ + skip = max_t(u8, 1, 900 / dtimper_tu); } - /* the firmware really expects "look at every X DTIMs", so add 1 */ - cmd->skip_dtim_periods = 1 + skip; + cmd->skip_dtim_periods = skip; cmd->flags |= cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK); } @@ -502,9 +501,9 @@ void iwl_mvm_power_vif_assoc(struct iwl_mvm *mvm, struct ieee80211_vif *vif) { struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); - if (memcmp(vif->bss_conf.bssid, mvmvif->uapsd_misbehaving_bssid, - ETH_ALEN)) - eth_zero_addr(mvmvif->uapsd_misbehaving_bssid); + if (!ether_addr_equal(mvmvif->uapsd_misbehaving_ap_addr, + vif->cfg.ap_addr)) + eth_zero_addr(mvmvif->uapsd_misbehaving_ap_addr); } static void iwl_mvm_power_uapsd_misbehav_ap_iterator(void *_data, u8 *mac, @@ -512,14 +511,23 @@ static void iwl_mvm_power_uapsd_misbehav_ap_iterator(void *_data, u8 *mac, { u8 *ap_sta_id = _data; struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); + struct ieee80211_bss_conf *link_conf; + unsigned int link_id; - /* The ap_sta_id is not expected to change during current association - * so no explicit protection is needed - */ - if (mvmvif->deflink.ap_sta_id == *ap_sta_id) - memcpy(mvmvif->uapsd_misbehaving_bssid, - vif->bss_conf.bssid, - ETH_ALEN); + rcu_read_lock(); + for_each_vif_active_link(vif, link_conf, link_id) { + struct iwl_mvm_vif_link_info *link_info = mvmvif->link[link_id]; + + /* The ap_sta_id is not expected to change during current + * association so no explicit protection is needed + */ + if (link_info->ap_sta_id == *ap_sta_id) { + ether_addr_copy(mvmvif->uapsd_misbehaving_ap_addr, + vif->cfg.ap_addr); + break; + } + } + rcu_read_unlock(); } void iwl_mvm_power_uapsd_misbehaving_ap_notif(struct iwl_mvm *mvm, @@ -647,30 +655,32 @@ static void iwl_mvm_power_set_pm(struct iwl_mvm *mvm, return; /* enable PM on bss if bss stand alone */ - if (vifs->bss_active && !vifs->p2p_active && !vifs->ap_active) { + if (bss_mvmvif && vifs->bss_active && !vifs->p2p_active && + !vifs->ap_active) { bss_mvmvif->pm_enabled = true; return; } /* enable PM on p2p if p2p stand alone */ - if (vifs->p2p_active && !vifs->bss_active && !vifs->ap_active) { + if (p2p_mvmvif && vifs->p2p_active && !vifs->bss_active && + !vifs->ap_active) { p2p_mvmvif->pm_enabled = true; return; } - if (vifs->bss_active && vifs->p2p_active) + if (p2p_mvmvif && bss_mvmvif && vifs->bss_active && vifs->p2p_active) client_same_channel = iwl_mvm_have_links_same_channel(bss_mvmvif, p2p_mvmvif); - if (vifs->bss_active && vifs->ap_active) + if (bss_mvmvif && ap_mvmvif && vifs->bss_active && vifs->ap_active) ap_same_channel = iwl_mvm_have_links_same_channel(bss_mvmvif, ap_mvmvif); /* clients are not stand alone: enable PM if DCM */ if (!(client_same_channel || ap_same_channel)) { - if (vifs->bss_active) + if (bss_mvmvif && vifs->bss_active) bss_mvmvif->pm_enabled = true; - if (vifs->p2p_active) + if (p2p_mvmvif && vifs->p2p_active) p2p_mvmvif->pm_enabled = true; return; } diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c index c3a00bfbeef2cd0dd496983608904eb01490e86f..6cba8a353b531268818249df09d874b76feb7290 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* * Copyright (C) 2017 Intel Deutschland GmbH - * Copyright (C) 2018-2022 Intel Corporation + * Copyright (C) 2018-2023 Intel Corporation */ #include "rs.h" #include "fw-api.h" @@ -63,12 +63,11 @@ static u8 rs_fw_sgi_cw_support(struct ieee80211_link_sta *link_sta) static u16 rs_fw_get_config_flags(struct iwl_mvm *mvm, struct ieee80211_vif *vif, struct ieee80211_link_sta *link_sta, - struct ieee80211_supported_band *sband) + const struct ieee80211_sta_he_cap *sband_he_cap) { struct ieee80211_sta_ht_cap *ht_cap = &link_sta->ht_cap; struct ieee80211_sta_vht_cap *vht_cap = &link_sta->vht_cap; struct ieee80211_sta_he_cap *he_cap = &link_sta->he_cap; - const struct ieee80211_sta_he_cap *sband_he_cap; bool vht_ena = vht_cap->vht_supported; u16 flags = 0; @@ -94,8 +93,6 @@ static u16 rs_fw_get_config_flags(struct iwl_mvm *mvm, IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD)) flags |= IWL_TLC_MNG_CFG_FLAGS_LDPC_MSK; - sband_he_cap = ieee80211_get_he_iftype_cap(sband, - ieee80211_vif_type_p2p(vif)); if (sband_he_cap && !(sband_he_cap->he_cap_elem.phy_cap_info[1] & IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD)) @@ -197,16 +194,14 @@ static u16 rs_fw_he_ieee80211_mcs_to_rs_mcs(u16 mcs) static void rs_fw_he_set_enabled_rates(const struct ieee80211_link_sta *link_sta, - struct ieee80211_supported_band *sband, + const struct ieee80211_sta_he_cap *sband_he_cap, struct iwl_tlc_config_cmd_v4 *cmd) { const struct ieee80211_sta_he_cap *he_cap = &link_sta->he_cap; u16 mcs_160 = le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_160); u16 mcs_80 = le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_80); - u16 tx_mcs_80 = - le16_to_cpu(sband->iftype_data->he_cap.he_mcs_nss_supp.tx_mcs_80); - u16 tx_mcs_160 = - le16_to_cpu(sband->iftype_data->he_cap.he_mcs_nss_supp.tx_mcs_160); + u16 tx_mcs_80 = le16_to_cpu(sband_he_cap->he_mcs_nss_supp.tx_mcs_80); + u16 tx_mcs_160 = le16_to_cpu(sband_he_cap->he_mcs_nss_supp.tx_mcs_160); int i; u8 nss = link_sta->rx_nss; @@ -289,7 +284,8 @@ rs_fw_rs_mcs2eht_mcs(enum IWL_TLC_MCS_PER_BW bw, static void rs_fw_eht_set_enabled_rates(struct ieee80211_vif *vif, const struct ieee80211_link_sta *link_sta, - struct ieee80211_supported_band *sband, + const struct ieee80211_sta_he_cap *sband_he_cap, + const struct ieee80211_sta_eht_cap *sband_eht_cap, struct iwl_tlc_config_cmd_v4 *cmd) { /* peer RX mcs capa */ @@ -297,7 +293,7 @@ rs_fw_eht_set_enabled_rates(struct ieee80211_vif *vif, &link_sta->eht_cap.eht_mcs_nss_supp; /* our TX mcs capa */ const struct ieee80211_eht_mcs_nss_supp *eht_tx_mcs = - &sband->iftype_data->eht_cap.eht_mcs_nss_supp; + &sband_eht_cap->eht_mcs_nss_supp; enum IWL_TLC_MCS_PER_BW bw; struct ieee80211_eht_mcs_nss_supp_20mhz_only mcs_rx_20; @@ -316,7 +312,7 @@ rs_fw_eht_set_enabled_rates(struct ieee80211_vif *vif, } /* nic is 20Mhz only */ - if (!(sband->iftype_data->he_cap.he_cap_elem.phy_cap_info[0] & + if (!(sband_he_cap->he_cap_elem.phy_cap_info[0] & IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_MASK_ALL)) { mcs_tx_20 = eht_tx_mcs->only_20mhz; } else { @@ -370,6 +366,8 @@ rs_fw_eht_set_enabled_rates(struct ieee80211_vif *vif, static void rs_fw_set_supp_rates(struct ieee80211_vif *vif, struct ieee80211_link_sta *link_sta, struct ieee80211_supported_band *sband, + const struct ieee80211_sta_he_cap *sband_he_cap, + const struct ieee80211_sta_eht_cap *sband_eht_cap, struct iwl_tlc_config_cmd_v4 *cmd) { int i; @@ -388,12 +386,13 @@ static void rs_fw_set_supp_rates(struct ieee80211_vif *vif, cmd->mode = IWL_TLC_MNG_MODE_NON_HT; /* HT/VHT rates */ - if (link_sta->eht_cap.has_eht) { + if (link_sta->eht_cap.has_eht && sband_he_cap && sband_eht_cap) { cmd->mode = IWL_TLC_MNG_MODE_EHT; - rs_fw_eht_set_enabled_rates(vif, link_sta, sband, cmd); - } else if (he_cap->has_he) { + rs_fw_eht_set_enabled_rates(vif, link_sta, sband_he_cap, + sband_eht_cap, cmd); + } else if (he_cap->has_he && sband_he_cap) { cmd->mode = IWL_TLC_MNG_MODE_HE; - rs_fw_he_set_enabled_rates(link_sta, sband, cmd); + rs_fw_he_set_enabled_rates(link_sta, sband_he_cap, cmd); } else if (vht_cap->vht_supported) { cmd->mode = IWL_TLC_MNG_MODE_VHT; rs_fw_vht_set_enabled_rates(link_sta, vht_cap, cmd); @@ -479,7 +478,7 @@ void iwl_mvm_tlc_update_notif(struct iwl_mvm *mvm, IWL_DEBUG_RATE(mvm, "new rate: %s\n", pretty_rate); } - if (flags & IWL_TLC_NOTIF_FLAG_AMSDU && !mvmsta->orig_amsdu_len) { + if (flags & IWL_TLC_NOTIF_FLAG_AMSDU && !mvm_link_sta->orig_amsdu_len) { u16 size = le32_to_cpu(notif->amsdu_size); int i; @@ -489,7 +488,7 @@ void iwl_mvm_tlc_update_notif(struct iwl_mvm *mvm, * so also check with orig_amsdu_len which holds the * original data before debugfs changed the value */ - WARN_ON(mvmsta->orig_amsdu_len < size); + WARN_ON(mvm_link_sta->orig_amsdu_len < size); goto out; } @@ -524,6 +523,7 @@ u16 rs_fw_get_max_amsdu_len(struct ieee80211_sta *sta, { const struct ieee80211_sta_vht_cap *vht_cap = &link_sta->vht_cap; const struct ieee80211_sta_ht_cap *ht_cap = &link_sta->ht_cap; + const struct ieee80211_sta_eht_cap *eht_cap = &link_sta->eht_cap; if (WARN_ON_ONCE(!link_conf->chandef.chan)) return IEEE80211_MAX_MPDU_LEN_VHT_3895; @@ -538,8 +538,18 @@ u16 rs_fw_get_max_amsdu_len(struct ieee80211_sta *sta, default: return IEEE80211_MAX_MPDU_LEN_VHT_3895; } - } else - if (vht_cap->vht_supported) { + } else if (link_conf->chandef.chan->band == NL80211_BAND_2GHZ && + eht_cap->has_eht) { + switch (u8_get_bits(eht_cap->eht_cap_elem.mac_cap_info[0], + IEEE80211_EHT_MAC_CAP0_MAX_MPDU_LEN_MASK)) { + case IEEE80211_EHT_MAC_CAP0_MAX_MPDU_LEN_11454: + return IEEE80211_MAX_MPDU_LEN_VHT_11454; + case IEEE80211_EHT_MAC_CAP0_MAX_MPDU_LEN_7991: + return IEEE80211_MAX_MPDU_LEN_VHT_7991; + default: + return IEEE80211_MAX_MPDU_LEN_VHT_3895; + } + } else if (vht_cap->vht_supported) { switch (vht_cap->cap & IEEE80211_VHT_CAP_MAX_MPDU_MASK) { case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454: return IEEE80211_MAX_MPDU_LEN_VHT_11454; @@ -576,13 +586,17 @@ void iwl_mvm_rs_fw_rate_init(struct iwl_mvm *mvm, u32 cmd_id = WIDE_ID(DATA_PATH_GROUP, TLC_MNG_CONFIG_CMD); struct ieee80211_supported_band *sband = hw->wiphy->bands[band]; u16 max_amsdu_len = rs_fw_get_max_amsdu_len(sta, link_conf, link_sta); + const struct ieee80211_sta_he_cap *sband_he_cap = + ieee80211_get_he_iftype_cap_vif(sband, vif); + const struct ieee80211_sta_eht_cap *sband_eht_cap = + ieee80211_get_eht_iftype_cap_vif(sband, vif); struct iwl_mvm_link_sta *mvm_link_sta; struct iwl_lq_sta_rs_fw *lq_sta; struct iwl_tlc_config_cmd_v4 cfg_cmd = { .max_ch_width = mvmsta->authorized ? rs_fw_bw_from_sta_bw(link_sta) : IWL_TLC_MNG_CH_WIDTH_20MHZ, .flags = cpu_to_le16(rs_fw_get_config_flags(mvm, vif, link_sta, - sband)), + sband_he_cap)), .chains = rs_fw_set_active_chains(iwl_mvm_get_valid_tx_ant(mvm)), .sgi_ch_width_supp = rs_fw_sgi_cw_support(link_sta), .max_mpdu_len = iwl_mvm_is_csum_supported(mvm) ? @@ -592,6 +606,21 @@ void iwl_mvm_rs_fw_rate_init(struct iwl_mvm *mvm, int cmd_ver; int ret; + /* Enable external EHT LTF only for GL device and if there's + * mutual support by AP and client + */ + if (CSR_HW_REV_TYPE(mvm->trans->hw_rev) == IWL_CFG_MAC_TYPE_GL && + sband_eht_cap && + sband_eht_cap->eht_cap_elem.phy_cap_info[5] & + IEEE80211_EHT_PHY_CAP5_SUPP_EXTRA_EHT_LTF && + link_sta->eht_cap.has_eht && + link_sta->eht_cap.eht_cap_elem.phy_cap_info[5] & + IEEE80211_EHT_PHY_CAP5_SUPP_EXTRA_EHT_LTF) { + IWL_DEBUG_RATE(mvm, "Set support for Extra EHT LTF\n"); + cfg_cmd.flags |= + cpu_to_le16(IWL_TLC_MNG_CFG_FLAGS_EHT_EXTRA_LTF_MSK); + } + rcu_read_lock(); mvm_link_sta = rcu_dereference(mvmsta->link[link_id]); if (WARN_ON_ONCE(!mvm_link_sta)) { @@ -609,7 +638,9 @@ void iwl_mvm_rs_fw_rate_init(struct iwl_mvm *mvm, #ifdef CONFIG_IWLWIFI_DEBUGFS iwl_mvm_reset_frame_stats(mvm); #endif - rs_fw_set_supp_rates(vif, link_sta, sband, &cfg_cmd); + rs_fw_set_supp_rates(vif, link_sta, sband, + sband_he_cap, sband_eht_cap, + &cfg_cmd); /* * since TLC offload works with one mode we can assume diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c index 9a20468345e49db727cfe087da652f73d71b7026..481d68cbbbd84c707bd95bc404b94f46f9a7e84f 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /****************************************************************************** * - * Copyright(c) 2005 - 2014, 2018 - 2022 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2014, 2018 - 2023 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH *****************************************************************************/ @@ -1070,10 +1070,13 @@ static void rs_get_lower_rate_down_column(struct iwl_lq_sta *lq_sta, rate->bw = RATE_MCS_CHAN_WIDTH_20; - WARN_ON_ONCE(rate->index < IWL_RATE_MCS_0_INDEX || - rate->index > IWL_RATE_MCS_9_INDEX); + if (WARN_ON_ONCE(rate->index < IWL_RATE_MCS_0_INDEX)) + rate->index = rs_ht_to_legacy[IWL_RATE_MCS_0_INDEX]; + else if (WARN_ON_ONCE(rate->index > IWL_RATE_MCS_9_INDEX)) + rate->index = rs_ht_to_legacy[IWL_RATE_MCS_9_INDEX]; + else + rate->index = rs_ht_to_legacy[rate->index]; - rate->index = rs_ht_to_legacy[rate->index]; rate->ldpc = false; } else { /* Downgrade to SISO with same MCS if in MIMO */ diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rx.c b/drivers/net/wireless/intel/iwlwifi/mvm/rx.c index b38b2424667519a12b37dee261279755bf728926..542c192698a4b35a7f22813932cad66a9d559c26 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rx.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* - * Copyright (C) 2012-2014, 2018-2022 Intel Corporation + * Copyright (C) 2012-2014, 2018-2023 Intel Corporation * Copyright (C) 2013-2015 Intel Mobile Communications GmbH * Copyright (C) 2016-2017 Intel Deutschland GmbH */ @@ -213,8 +213,12 @@ static void iwl_mvm_rx_handle_tcm(struct iwl_mvm *mvm, }; u16 thr; - if (ieee80211_is_data_qos(hdr->frame_control)) - ac = tid_to_mac80211_ac[ieee80211_get_tid(hdr)]; + if (ieee80211_is_data_qos(hdr->frame_control)) { + u8 tid = ieee80211_get_tid(hdr); + + if (tid < IWL_MAX_TID_COUNT) + ac = tid_to_mac80211_ac[tid]; + } mvmsta = iwl_mvm_sta_from_mac80211(sta); mac = mvmsta->mac_id_n_color & FW_CTXT_ID_MSK; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c index 6226e4e54a51d2775a19174f7683d2c1db5ec729..8d1e44fd9de73b18fcc631aa8deefc2bf2583743 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c @@ -279,7 +279,8 @@ static void iwl_mvm_get_signal_strength(struct iwl_mvm *mvm, static int iwl_mvm_rx_mgmt_prot(struct ieee80211_sta *sta, struct ieee80211_hdr *hdr, struct iwl_rx_mpdu_desc *desc, - u32 status) + u32 status, + struct ieee80211_rx_status *stats) { struct iwl_mvm_sta *mvmsta; struct iwl_mvm_vif *mvmvif; @@ -308,8 +309,10 @@ static int iwl_mvm_rx_mgmt_prot(struct ieee80211_sta *sta, /* good cases */ if (likely(status & IWL_RX_MPDU_STATUS_MIC_OK && - !(status & IWL_RX_MPDU_STATUS_REPLAY_ERROR))) + !(status & IWL_RX_MPDU_STATUS_REPLAY_ERROR))) { + stats->flag |= RX_FLAG_DECRYPTED; return 0; + } if (!sta) return -1; @@ -378,7 +381,7 @@ static int iwl_mvm_rx_crypto(struct iwl_mvm *mvm, struct ieee80211_sta *sta, if (unlikely(ieee80211_is_mgmt(hdr->frame_control) && !ieee80211_has_protected(hdr->frame_control))) - return iwl_mvm_rx_mgmt_prot(sta, hdr, desc, status); + return iwl_mvm_rx_mgmt_prot(sta, hdr, desc, status, stats); if (!ieee80211_has_protected(hdr->frame_control) || (status & IWL_RX_MPDU_STATUS_SEC_MASK) == @@ -484,7 +487,7 @@ static void iwl_mvm_rx_csum(struct iwl_mvm *mvm, } /* - * returns true if a packet is a duplicate and should be dropped. + * returns true if a packet is a duplicate or invalid tid and should be dropped. * Updates AMSDU PN tracking info */ static bool iwl_mvm_is_dup(struct ieee80211_sta *sta, int queue, @@ -513,11 +516,14 @@ static bool iwl_mvm_is_dup(struct ieee80211_sta *sta, int queue, return false; } - if (ieee80211_is_data_qos(hdr->frame_control)) + if (ieee80211_is_data_qos(hdr->frame_control)) { /* frame has qos control */ tid = ieee80211_get_tid(hdr); - else + if (tid >= IWL_MAX_TID_COUNT) + return true; + } else { tid = IWL_MAX_TID_COUNT; + } /* If this wasn't a part of an A-MSDU the sub-frame index will be 0 */ sub_frame_idx = desc->amsdu_info & @@ -985,10 +991,12 @@ static bool iwl_mvm_reorder(struct iwl_mvm *mvm, sta_mask = iwl_mvm_sta_fw_id_mask(mvm, sta, -1); rcu_read_unlock(); - if (WARN(tid != baid_data->tid || - !(sta_mask & baid_data->sta_mask), - "baid 0x%x is mapped to sta_mask:0x%x tid:%d, but was received for sta_mask:0x%x tid:%d\n", - baid, baid_data->sta_mask, baid_data->tid, sta_mask, tid)) + if (IWL_FW_CHECK(mvm, + tid != baid_data->tid || + !(sta_mask & baid_data->sta_mask), + "baid 0x%x is mapped to sta_mask:0x%x tid:%d, but was received for sta_mask:0x%x tid:%d\n", + baid, baid_data->sta_mask, baid_data->tid, + sta_mask, tid)) return false; nssn = reorder & IWL_RX_MPDU_REORDER_NSSN_MASK; @@ -1773,6 +1781,15 @@ static void iwl_mvm_decode_eht_phy_data(struct iwl_mvm *mvm, IEEE80211_RADIOTAP_EHT_USIG_COMMON_BSS_COLOR); } + if (fw_has_capa(&mvm->fw->ucode_capa, + IWL_UCODE_TLV_CAPA_SNIFF_VALIDATE_SUPPORT)) { + usig->common |= + cpu_to_le32(IEEE80211_RADIOTAP_EHT_USIG_COMMON_VALIDATE_BITS_CHECKED); + usig->common |= + LE32_DEC_ENC(data0, IWL_RX_PHY_DATA0_EHT_VALIDATE, + IEEE80211_RADIOTAP_EHT_USIG_COMMON_VALIDATE_BITS_OK); + } + eht->known |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_KNOWN_SPATIAL_REUSE); eht->data[0] |= LE32_DEC_ENC(data0, IWL_RX_PHY_DATA0_ETH_SPATIAL_REUSE_MASK, @@ -1782,9 +1799,9 @@ static void iwl_mvm_decode_eht_phy_data(struct iwl_mvm *mvm, eht->known |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_KNOWN_RU_ALLOC_TB_FMT); eht->data[8] |= LE32_DEC_ENC(data0, IWL_RX_PHY_DATA0_EHT_PS160, IEEE80211_RADIOTAP_EHT_DATA8_RU_ALLOC_TB_FMT_PS_160); - eht->data[8] |= LE32_DEC_ENC(data1, IWL_RX_PHY_DATA1_EHT_B0, + eht->data[8] |= LE32_DEC_ENC(data1, IWL_RX_PHY_DATA1_EHT_RU_ALLOC_B0, IEEE80211_RADIOTAP_EHT_DATA8_RU_ALLOC_TB_FMT_B0); - eht->data[8] |= LE32_DEC_ENC(data1, IWL_RX_PHY_DATA1_EHT_RU_B1_B7_ALLOC, + eht->data[8] |= LE32_DEC_ENC(data1, IWL_RX_PHY_DATA1_EHT_RU_ALLOC_B1_B7, IEEE80211_RADIOTAP_EHT_DATA8_RU_ALLOC_TB_FMT_B7_B1); iwl_mvm_decode_eht_ru(mvm, rx_status, eht); @@ -2633,6 +2650,8 @@ void iwl_mvm_rx_monitor_no_data(struct iwl_mvm *mvm, struct napi_struct *napi, phy_data.energy_b = u32_get_bits(rssi, RX_NO_DATA_CHAIN_B_MSK); phy_data.channel = u32_get_bits(rssi, RX_NO_DATA_CHANNEL_MSK); phy_data.with_data = false; + phy_data.rx_vec[0] = desc->rx_vec[0]; + phy_data.rx_vec[1] = desc->rx_vec[1]; if (iwl_fw_lookup_notif_ver(mvm->fw, DATA_PATH_GROUP, RX_NO_DATA_NOTIF, 0) < 2) { @@ -2651,7 +2670,8 @@ void iwl_mvm_rx_monitor_no_data(struct iwl_mvm *mvm, struct napi_struct *napi, sizeof(struct iwl_rx_no_data_ver_3))) /* invalid len for ver 3 */ return; - memcpy(phy_data.rx_vec, desc->rx_vec, sizeof(phy_data.rx_vec)); + phy_data.rx_vec[2] = desc->rx_vec[2]; + phy_data.rx_vec[3] = desc->rx_vec[3]; } else { if (format == RATE_MCS_EHT_MSK) /* no support for EHT before version 3 API */ diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c index 175615755d9daafac5e8ce3865af4a8177756d0b..c1d9ce75346882033495d1fbf3e42a59a0662ff2 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* - * Copyright (C) 2012-2014, 2018-2021 Intel Corporation + * Copyright (C) 2012-2014, 2018-2023 Intel Corporation * Copyright (C) 2013-2015 Intel Mobile Communications GmbH * Copyright (C) 2016-2017 Intel Deutschland GmbH */ @@ -647,7 +647,7 @@ static void iwl_mvm_scan_fill_tx_cmd(struct iwl_mvm *mvm, NL80211_BAND_2GHZ, no_cck); - if (iwl_fw_lookup_cmd_ver(mvm->fw, ADD_STA, 0) < 12) { + if (!iwl_mvm_has_new_station_api(mvm->fw)) { tx_cmd[0].sta_id = mvm->aux_sta.sta_id; tx_cmd[1].sta_id = mvm->aux_sta.sta_id; @@ -1084,7 +1084,7 @@ static void iwl_mvm_fill_scan_config_v1(struct iwl_mvm *mvm, void *config, memcpy(&cfg->mac_addr, &mvm->addresses[0].addr, ETH_ALEN); /* This function should not be called when using ADD_STA ver >=12 */ - WARN_ON_ONCE(iwl_fw_lookup_cmd_ver(mvm->fw, ADD_STA, 0) >= 12); + WARN_ON_ONCE(iwl_mvm_has_new_station_api(mvm->fw)); cfg->bcast_sta_id = mvm->aux_sta.sta_id; cfg->channel_flags = channel_flags; @@ -1135,7 +1135,7 @@ static void iwl_mvm_fill_scan_config_v2(struct iwl_mvm *mvm, void *config, memcpy(&cfg->mac_addr, &mvm->addresses[0].addr, ETH_ALEN); /* This function should not be called when using ADD_STA ver >=12 */ - WARN_ON_ONCE(iwl_fw_lookup_cmd_ver(mvm->fw, ADD_STA, 0) >= 12); + WARN_ON_ONCE(iwl_mvm_has_new_station_api(mvm->fw)); cfg->bcast_sta_id = mvm->aux_sta.sta_id; cfg->channel_flags = channel_flags; @@ -1250,7 +1250,7 @@ int iwl_mvm_config_scan(struct iwl_mvm *mvm) memset(&cfg, 0, sizeof(cfg)); - if (iwl_fw_lookup_cmd_ver(mvm->fw, ADD_STA, 0) < 12) { + if (!iwl_mvm_has_new_station_api(mvm->fw)) { cfg.bcast_sta_id = mvm->aux_sta.sta_id; } else if (iwl_fw_lookup_cmd_ver(mvm->fw, SCAN_CFG_CMD, 0) < 5) { /* @@ -1627,11 +1627,11 @@ iwl_mvm_umac_scan_cfg_channels_v4(struct iwl_mvm *mvm, } static void -iwl_mvm_umac_scan_cfg_channels_v6(struct iwl_mvm *mvm, +iwl_mvm_umac_scan_cfg_channels_v7(struct iwl_mvm *mvm, struct ieee80211_channel **channels, - struct iwl_scan_channel_params_v6 *cp, + struct iwl_scan_channel_params_v7 *cp, int n_channels, u32 flags, - enum nl80211_iftype vif_type) + enum nl80211_iftype vif_type, u32 version) { int i; @@ -1641,14 +1641,19 @@ iwl_mvm_umac_scan_cfg_channels_v6(struct iwl_mvm *mvm, u32 n_aps_flag = iwl_mvm_scan_ch_n_aps_flag(vif_type, channels[i]->hw_value); + u8 iwl_band = iwl_mvm_phy_band_from_nl80211(band); cfg->flags = cpu_to_le32(flags | n_aps_flag); cfg->v2.channel_num = channels[i]->hw_value; - cfg->v2.band = iwl_mvm_phy_band_from_nl80211(band); if (cfg80211_channel_is_psc(channels[i])) cfg->flags = 0; cfg->v2.iter_count = 1; cfg->v2.iter_interval = 0; + if (version < 17) + cfg->v2.band = iwl_band; + else + cfg->flags |= cpu_to_le32((iwl_band << + IWL_CHAN_CFG_FLAGS_BAND_POS)); } } @@ -1723,14 +1728,15 @@ iwl_mvm_umac_scan_fill_6g_chan_list(struct iwl_mvm *mvm, pp->bssid_num = idex_b; } -/* TODO: this function can be merged with iwl_mvm_scan_umac_fill_ch_p_v6 */ +/* TODO: this function can be merged with iwl_mvm_scan_umac_fill_ch_p_v7 */ static u32 -iwl_mvm_umac_scan_cfg_channels_v6_6g(struct iwl_mvm *mvm, +iwl_mvm_umac_scan_cfg_channels_v7_6g(struct iwl_mvm *mvm, struct iwl_mvm_scan_params *params, u32 n_channels, struct iwl_scan_probe_params_v4 *pp, - struct iwl_scan_channel_params_v6 *cp, - enum nl80211_iftype vif_type) + struct iwl_scan_channel_params_v7 *cp, + enum nl80211_iftype vif_type, + u32 version) { int i; struct cfg80211_scan_6ghz_params *scan_6ghz_params = @@ -1745,6 +1751,7 @@ iwl_mvm_umac_scan_cfg_channels_v6_6g(struct iwl_mvm *mvm, u8 j, k, s_max = 0, b_max = 0, n_used_bssid_entries; bool force_passive, found = false, allow_passive = true, unsolicited_probe_on_chan = false, psc_no_listen = false; + s8 psd_20 = IEEE80211_RNR_TBTT_PARAMS_PSD_RESERVED; /* * Avoid performing passive scan on non PSC channels unless the @@ -1756,9 +1763,14 @@ iwl_mvm_umac_scan_cfg_channels_v6_6g(struct iwl_mvm *mvm, continue; cfg->v1.channel_num = params->channels[i]->hw_value; - cfg->v2.band = 2; - cfg->v2.iter_count = 1; - cfg->v2.iter_interval = 0; + if (version < 17) + cfg->v2.band = PHY_BAND_6; + else + cfg->flags |= cpu_to_le32(PHY_BAND_6 << + IWL_CHAN_CFG_FLAGS_BAND_POS); + + cfg->v5.iter_count = 1; + cfg->v5.iter_interval = 0; /* * The optimize the scan time, i.e., reduce the scan dwell time @@ -1769,9 +1781,22 @@ iwl_mvm_umac_scan_cfg_channels_v6_6g(struct iwl_mvm *mvm, */ n_used_bssid_entries = 3; for (j = 0; j < params->n_6ghz_params; j++) { + s8 tmp_psd_20; + if (!(scan_6ghz_params[j].channel_idx == i)) continue; + /* Use the highest PSD value allowed as advertised by + * APs for this channel + */ + tmp_psd_20 = scan_6ghz_params[j].psd_20; + if (tmp_psd_20 != + IEEE80211_RNR_TBTT_PARAMS_PSD_RESERVED && + (psd_20 == + IEEE80211_RNR_TBTT_PARAMS_PSD_RESERVED || + psd_20 < tmp_psd_20)) + psd_20 = tmp_psd_20; + found = false; unsolicited_probe_on_chan |= scan_6ghz_params[j].unsolicited_probe; @@ -1875,6 +1900,9 @@ iwl_mvm_umac_scan_cfg_channels_v6_6g(struct iwl_mvm *mvm, flags |= bssid_bitmap | (s_ssid_bitmap << 16); cfg->flags |= cpu_to_le32(flags); + if (version >= 17) + cfg->v5.psd_20 = psd_20; + ch_cnt++; } @@ -2292,11 +2320,12 @@ static int iwl_mvm_scan_umac(struct iwl_mvm *mvm, struct ieee80211_vif *vif, } static void -iwl_mvm_scan_umac_fill_general_p_v11(struct iwl_mvm *mvm, +iwl_mvm_scan_umac_fill_general_p_v12(struct iwl_mvm *mvm, struct iwl_mvm_scan_params *params, struct ieee80211_vif *vif, struct iwl_scan_general_params_v11 *gp, - u16 gen_flags, u8 gen_flags2) + u16 gen_flags, u8 gen_flags2, + u32 version) { struct iwl_mvm_vif *scan_vif = iwl_mvm_vif_from_mac80211(vif); @@ -2313,7 +2342,23 @@ iwl_mvm_scan_umac_fill_general_p_v11(struct iwl_mvm *mvm, if (gen_flags & IWL_UMAC_SCAN_GEN_FLAGS_V2_FRAGMENTED_LMAC2) gp->num_of_fragments[SCAN_HB_LMAC_IDX] = IWL_SCAN_NUM_OF_FRAGS; - gp->scan_start_mac_id = scan_vif->id; + if (version < 12) { + gp->scan_start_mac_or_link_id = scan_vif->id; + } else { + struct iwl_mvm_vif_link_info *link_info; + u8 link_id = 0; + + /* Use one of the active link (if any). In the future it would + * be possible that the link ID would be part of the scan + * request coming from upper layers so we would need to use it. + */ + if (vif->active_links) + link_id = ffs(vif->active_links) - 1; + + link_info = scan_vif->link[link_id]; + if (!WARN_ON(!link_info)) + gp->scan_start_mac_or_link_id = link_info->fw_link_id; + } } static void @@ -2352,21 +2397,22 @@ iwl_mvm_scan_umac_fill_ch_p_v4(struct iwl_mvm *mvm, } static void -iwl_mvm_scan_umac_fill_ch_p_v6(struct iwl_mvm *mvm, +iwl_mvm_scan_umac_fill_ch_p_v7(struct iwl_mvm *mvm, struct iwl_mvm_scan_params *params, struct ieee80211_vif *vif, - struct iwl_scan_channel_params_v6 *cp, - u32 channel_cfg_flags) + struct iwl_scan_channel_params_v7 *cp, + u32 channel_cfg_flags, + u32 version) { cp->flags = iwl_mvm_scan_umac_chan_flags_v2(mvm, params, vif); cp->count = params->n_channels; cp->n_aps_override[0] = IWL_SCAN_ADWELL_N_APS_GO_FRIENDLY; cp->n_aps_override[1] = IWL_SCAN_ADWELL_N_APS_SOCIAL_CHS; - iwl_mvm_umac_scan_cfg_channels_v6(mvm, params->channels, cp, + iwl_mvm_umac_scan_cfg_channels_v7(mvm, params->channels, cp, params->n_channels, channel_cfg_flags, - vif->type); + vif->type, version); if (params->enable_6ghz_passive) { struct ieee80211_supported_band *sband = @@ -2383,11 +2429,19 @@ iwl_mvm_scan_umac_fill_ch_p_v6(struct iwl_mvm *mvm, if (!cfg80211_channel_is_psc(channel)) continue; - cfg->flags = 0; - cfg->v2.channel_num = channel->hw_value; - cfg->v2.band = PHY_BAND_6; - cfg->v2.iter_count = 1; - cfg->v2.iter_interval = 0; + cfg->v5.channel_num = channel->hw_value; + cfg->v5.iter_count = 1; + cfg->v5.iter_interval = 0; + + if (version < 17) { + cfg->flags = 0; + cfg->v2.band = PHY_BAND_6; + } else { + cfg->flags = cpu_to_le32(PHY_BAND_6 << + IWL_CHAN_CFG_FLAGS_BAND_POS); + cfg->v5.psd_20 = + IEEE80211_RNR_TBTT_PARAMS_PSD_RESERVED; + } cp->count++; } } @@ -2408,9 +2462,9 @@ static int iwl_mvm_scan_umac_v12(struct iwl_mvm *mvm, struct ieee80211_vif *vif, cmd->uid = cpu_to_le32(uid); gen_flags = iwl_mvm_scan_umac_flags_v2(mvm, params, vif, type); - iwl_mvm_scan_umac_fill_general_p_v11(mvm, params, vif, + iwl_mvm_scan_umac_fill_general_p_v12(mvm, params, vif, &scan_p->general_params, - gen_flags, 0); + gen_flags, 0, 12); ret = iwl_mvm_fill_scan_sched_params(params, scan_p->periodic_params.schedule, @@ -2430,9 +2484,9 @@ static int iwl_mvm_scan_umac_v14_and_above(struct iwl_mvm *mvm, struct iwl_mvm_scan_params *params, int type, int uid, u32 version) { - struct iwl_scan_req_umac_v15 *cmd = mvm->scan_cmd; - struct iwl_scan_req_params_v15 *scan_p = &cmd->scan_params; - struct iwl_scan_channel_params_v6 *cp = &scan_p->channel_params; + struct iwl_scan_req_umac_v17 *cmd = mvm->scan_cmd; + struct iwl_scan_req_params_v17 *scan_p = &cmd->scan_params; + struct iwl_scan_channel_params_v7 *cp = &scan_p->channel_params; struct iwl_scan_probe_params_v4 *pb = &scan_p->probe_params; int ret; u16 gen_flags; @@ -2451,9 +2505,9 @@ static int iwl_mvm_scan_umac_v14_and_above(struct iwl_mvm *mvm, else gen_flags2 = 0; - iwl_mvm_scan_umac_fill_general_p_v11(mvm, params, vif, + iwl_mvm_scan_umac_fill_general_p_v12(mvm, params, vif, &scan_p->general_params, - gen_flags, gen_flags2); + gen_flags, gen_flags2, version); ret = iwl_mvm_fill_scan_sched_params(params, scan_p->periodic_params.schedule, @@ -2462,11 +2516,13 @@ static int iwl_mvm_scan_umac_v14_and_above(struct iwl_mvm *mvm, return ret; if (!params->scan_6ghz) { - iwl_mvm_scan_umac_fill_probe_p_v4(params, &scan_p->probe_params, - &bitmap_ssid); - iwl_mvm_scan_umac_fill_ch_p_v6(mvm, params, vif, - &scan_p->channel_params, bitmap_ssid); - + iwl_mvm_scan_umac_fill_probe_p_v4(params, + &scan_p->probe_params, + &bitmap_ssid); + iwl_mvm_scan_umac_fill_ch_p_v7(mvm, params, vif, + &scan_p->channel_params, + bitmap_ssid, + version); return 0; } else { pb->preq = params->preq; @@ -2478,9 +2534,10 @@ static int iwl_mvm_scan_umac_v14_and_above(struct iwl_mvm *mvm, iwl_mvm_umac_scan_fill_6g_chan_list(mvm, params, pb); - cp->count = iwl_mvm_umac_scan_cfg_channels_v6_6g(mvm, params, + cp->count = iwl_mvm_umac_scan_cfg_channels_v7_6g(mvm, params, params->n_channels, - pb, cp, vif->type); + pb, cp, vif->type, + version); if (!cp->count) { mvm->scan_uid_status[uid] = 0; return -EINVAL; @@ -2507,6 +2564,20 @@ static int iwl_mvm_scan_umac_v15(struct iwl_mvm *mvm, struct ieee80211_vif *vif, return iwl_mvm_scan_umac_v14_and_above(mvm, vif, params, type, uid, 15); } +static int iwl_mvm_scan_umac_v16(struct iwl_mvm *mvm, struct ieee80211_vif *vif, + struct iwl_mvm_scan_params *params, int type, + int uid) +{ + return iwl_mvm_scan_umac_v14_and_above(mvm, vif, params, type, uid, 16); +} + +static int iwl_mvm_scan_umac_v17(struct iwl_mvm *mvm, struct ieee80211_vif *vif, + struct iwl_mvm_scan_params *params, int type, + int uid) +{ + return iwl_mvm_scan_umac_v14_and_above(mvm, vif, params, type, uid, 17); +} + static int iwl_mvm_num_scans(struct iwl_mvm *mvm) { return hweight32(mvm->scan_status & IWL_MVM_SCAN_MASK); @@ -2622,6 +2693,8 @@ struct iwl_scan_umac_handler { static const struct iwl_scan_umac_handler iwl_scan_umac_handlers[] = { /* set the newest version first to shorten the list traverse time */ + IWL_SCAN_UMAC_HANDLER(17), + IWL_SCAN_UMAC_HANDLER(16), IWL_SCAN_UMAC_HANDLER(15), IWL_SCAN_UMAC_HANDLER(14), IWL_SCAN_UMAC_HANDLER(12), @@ -3210,7 +3283,9 @@ static size_t iwl_scan_req_umac_get_size(u8 scan_ver) return sizeof(struct iwl_scan_req_umac_v12); case 14: case 15: - return sizeof(struct iwl_scan_req_umac_v15); + case 16: + case 17: + return sizeof(struct iwl_scan_req_umac_v17); } return 0; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sf.c b/drivers/net/wireless/intel/iwlwifi/mvm/sf.c index 98f330fcf678e835eb141a977537e9149d181cba..30d4233595e889fce6bd7b3bf08aff07d97adf7b 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/sf.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/sf.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* - * Copyright (C) 2013-2014, 2018-2019, 2022 Intel Corporation + * Copyright (C) 2013-2014, 2018-2019, 2022-2023 Intel Corporation * Copyright (C) 2013-2014 Intel Mobile Communications GmbH */ #include "mvm.h" @@ -180,9 +180,6 @@ static int iwl_mvm_sf_config(struct iwl_mvm *mvm, struct ieee80211_sta *sta, }; int ret = 0; - if (mvm->cfg->disable_dummy_notification) - sf_cmd.state |= cpu_to_le32(SF_CFG_DUMMY_NOTIF_OFF); - /* * If an associated AP sta changed its antenna configuration, the state * will remain FULL_ON but SF parameters need to be reconsidered. diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c index 05a54a69c1357c59f121803204c8d7d448d4c0ef..3b9a343d4f672bff3d60e86ebd49c96ec5bb54d4 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* - * Copyright (C) 2012-2015, 2018-2022 Intel Corporation + * Copyright (C) 2012-2015, 2018-2023 Intel Corporation * Copyright (C) 2013-2015 Intel Mobile Communications GmbH * Copyright (C) 2016-2017 Intel Deutschland GmbH */ @@ -60,22 +60,27 @@ u32 iwl_mvm_get_sta_ampdu_dens(struct ieee80211_link_sta *link_sta, if (WARN_ON(!link_sta)) return 0; - if (link_sta->ht_cap.ht_supported) + /* Note that we always use only legacy & highest supported PPDUs, so + * of Draft P802.11be D.30 Table 10-12a--Fields used for calculating + * the maximum A-MPDU size of various PPDU types in different bands, + * we only need to worry about the highest supported PPDU type here. + */ + + if (link_sta->ht_cap.ht_supported) { + agg_size = link_sta->ht_cap.ampdu_factor; mpdu_dens = link_sta->ht_cap.ampdu_density; + } - if (link_conf->chandef.chan->band == - NL80211_BAND_6GHZ) { + if (link_conf->chandef.chan->band == NL80211_BAND_6GHZ) { + /* overwrite HT values on 6 GHz */ mpdu_dens = le16_get_bits(link_sta->he_6ghz_capa.capa, IEEE80211_HE_6GHZ_CAP_MIN_MPDU_START); agg_size = le16_get_bits(link_sta->he_6ghz_capa.capa, IEEE80211_HE_6GHZ_CAP_MAX_AMPDU_LEN_EXP); } else if (link_sta->vht_cap.vht_supported) { - agg_size = link_sta->vht_cap.cap & - IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK; - agg_size >>= - IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT; - } else if (link_sta->ht_cap.ht_supported) { - agg_size = link_sta->ht_cap.ampdu_factor; + /* if VHT supported overwrite HT value */ + agg_size = u32_get_bits(link_sta->vht_cap.cap, + IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK); } /* D6.0 10.12.2 A-MPDU length limit rules @@ -91,10 +96,13 @@ u32 iwl_mvm_get_sta_ampdu_dens(struct ieee80211_link_sta *link_sta, u8_get_bits(link_sta->he_cap.he_cap_elem.mac_cap_info[3], IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_MASK); + if (link_sta->eht_cap.has_eht) + agg_size += u8_get_bits(link_sta->eht_cap.eht_cap_elem.mac_cap_info[1], + IEEE80211_EHT_MAC_CAP1_MAX_AMPDU_LEN_MASK); + /* Limit to max A-MPDU supported by FW */ - if (agg_size > (STA_FLG_MAX_AGG_SIZE_4M >> STA_FLG_MAX_AGG_SIZE_SHIFT)) - agg_size = (STA_FLG_MAX_AGG_SIZE_4M >> - STA_FLG_MAX_AGG_SIZE_SHIFT); + agg_size = min_t(u32, agg_size, + STA_FLG_MAX_AGG_SIZE_4M >> STA_FLG_MAX_AGG_SIZE_SHIFT); *_agg_size = agg_size; return mpdu_dens; @@ -1679,7 +1687,7 @@ static int iwl_mvm_add_int_sta_common(struct iwl_mvm *mvm, memset(&cmd, 0, sizeof(cmd)); cmd.sta_id = sta->sta_id; - if (iwl_fw_lookup_cmd_ver(mvm->fw, ADD_STA, 0) >= 12 && + if (iwl_mvm_has_new_station_api(mvm->fw) && sta->type == IWL_STA_AUX_ACTIVITY) cmd.mac_id_n_color = cpu_to_le32(mac_id); else @@ -1859,6 +1867,8 @@ int iwl_mvm_add_sta(struct iwl_mvm *mvm, ret = iwl_mvm_sta_init(mvm, vif, sta, sta_id, sta->tdls ? IWL_STA_TDLS_LINK : IWL_STA_LINK); + if (ret) + goto err; update_fw: ret = iwl_mvm_sta_send_to_fw(mvm, sta, sta_update, sta_flags); @@ -2070,13 +2080,6 @@ bool iwl_mvm_sta_del(struct iwl_mvm *mvm, struct ieee80211_vif *vif, cancel_delayed_work(&mvm->tdls_cs.dwork); } - /* - * Make sure that the tx response code sees the station as -EBUSY and - * calls the drain worker. - */ - spin_lock_bh(&mvm_sta->lock); - spin_unlock_bh(&mvm_sta->lock); - return false; } @@ -2882,7 +2885,7 @@ int iwl_mvm_sta_rx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta, } if (iwl_mvm_has_new_rx_api(mvm) && start) { - u16 reorder_buf_size = buf_size * sizeof(baid_data->entries[0]); + u32 reorder_buf_size = buf_size * sizeof(baid_data->entries[0]); /* sparse doesn't like the __align() so don't check */ #ifndef __CHECKER__ @@ -4306,16 +4309,27 @@ int iwl_mvm_add_pasn_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif, u16 queue; struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); struct ieee80211_key_conf *keyconf; + unsigned int wdg_timeout = + iwl_mvm_get_wd_timeout(mvm, vif, false, false); + bool mld = iwl_mvm_has_mld_api(mvm->fw); + u32 type = mld ? STATION_TYPE_PEER : IWL_STA_LINK; ret = iwl_mvm_allocate_int_sta(mvm, sta, 0, - NL80211_IFTYPE_UNSPECIFIED, - IWL_STA_LINK); + NL80211_IFTYPE_UNSPECIFIED, type); if (ret) return ret; - ret = iwl_mvm_add_int_sta_with_queue(mvm, mvmvif->id, mvmvif->color, - addr, sta, &queue, - IWL_MVM_TX_FIFO_BE); + if (mld) + ret = iwl_mvm_mld_add_int_sta_with_queue(mvm, sta, addr, + mvmvif->deflink.fw_link_id, + &queue, + IWL_MAX_TID_COUNT, + &wdg_timeout); + else + ret = iwl_mvm_add_int_sta_with_queue(mvm, mvmvif->id, + mvmvif->color, addr, sta, + &queue, + IWL_MVM_TX_FIFO_BE); if (ret) goto out; @@ -4328,9 +4342,23 @@ int iwl_mvm_add_pasn_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif, keyconf->cipher = cipher; memcpy(keyconf->key, key, key_len); keyconf->keylen = key_len; + keyconf->flags = IEEE80211_KEY_FLAG_PAIRWISE; + + if (mld) { + /* The MFP flag is set according to the station mfp field. Since + * we don't have a station, set it manually. + */ + u32 key_flags = + iwl_mvm_get_sec_flags(mvm, vif, NULL, keyconf) | + IWL_SEC_KEY_FLAG_MFP; + u32 sta_mask = BIT(sta->sta_id); + + ret = iwl_mvm_mld_send_key(mvm, sta_mask, key_flags, keyconf); + } else { + ret = iwl_mvm_send_sta_key(mvm, sta->sta_id, keyconf, false, + 0, NULL, 0, 0, true); + } - ret = iwl_mvm_send_sta_key(mvm, sta->sta_id, keyconf, false, - 0, NULL, 0, 0, true); kfree(keyconf); return 0; out: @@ -4340,10 +4368,10 @@ int iwl_mvm_add_pasn_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif, void iwl_mvm_cancel_channel_switch(struct iwl_mvm *mvm, struct ieee80211_vif *vif, - u32 mac_id) + u32 id) { struct iwl_cancel_channel_switch_cmd cancel_channel_switch_cmd = { - .mac_id = cpu_to_le32(mac_id), + .id = cpu_to_le32(id), }; int ret; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h index a61d4f88125f0281ba07ae45af6cae38e1f2cf38..7364346a1209fc05ec3c32bffdcb2b16ead8aabe 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h @@ -336,6 +336,9 @@ struct iwl_mvm_rxq_dup_data { * @sta_id: the index of the station in the fw * @lq_sta: holds rate scaling data, either for the case when RS is done in * the driver - %rs_drv or in the FW - %rs_fw. + * @orig_amsdu_len: used to save the original amsdu_len when it is changed via + * debugfs. If it's set to 0, it means that it is it's not set via + * debugfs. * @avg_energy: energy as reported by FW statistics notification */ struct iwl_mvm_link_sta { @@ -346,6 +349,8 @@ struct iwl_mvm_link_sta { struct iwl_lq_sta rs_drv; } lq_sta; + u16 orig_amsdu_len; + u8 avg_energy; }; @@ -365,6 +370,7 @@ struct iwl_mvm_link_sta { * and from Tx response flow, it needs a spinlock. * @tid_data: per tid data + mgmt. Look at %iwl_mvm_tid_data. * @tid_to_baid: a simple map of TID to baid + * @vif: a vif pointer * @reserved_queue: the queue reserved for this STA for DQA purposes * Every STA has is given one reserved queue to allow it to operate. If no * such queue can be guaranteed, the STA addition will fail. @@ -374,10 +380,8 @@ struct iwl_mvm_link_sta { * @amsdu_enabled: bitmap of TX AMSDU allowed TIDs. * In case TLC offload is not active it is either 0xFFFF or 0. * @max_amsdu_len: max AMSDU length - * @orig_amsdu_len: used to save the original amsdu_len when it is changed via - * debugfs. If it's set to 0, it means that it is it's not set via - * debugfs. * @agg_tids: bitmap of tids whose status is operational aggregated (IWL_AGG_ON) + * @sleeping: sta sleep transitions in power management * @sleep_tx_count: the number of frames that we told the firmware to let out * even when that station is asleep. This is useful in case the queue * gets empty before all the frames were sent, which can happen when @@ -427,7 +431,6 @@ struct iwl_mvm_sta { bool disable_tx; u16 amsdu_enabled; u16 max_amsdu_len; - u16 orig_amsdu_len; bool sleeping; u8 agg_tids; u8 sleep_tx_count; @@ -580,7 +583,7 @@ int iwl_mvm_add_pasn_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif, u8 *key, u32 key_len); void iwl_mvm_cancel_channel_switch(struct iwl_mvm *mvm, struct ieee80211_vif *vif, - u32 mac_id); + u32 id); /* Queues */ int iwl_mvm_tvqm_enable_txq(struct iwl_mvm *mvm, struct ieee80211_sta *sta, @@ -616,7 +619,7 @@ int iwl_mvm_mac_sta_state_common(struct ieee80211_hw *hw, struct ieee80211_sta *sta, enum ieee80211_sta_state old_state, enum ieee80211_sta_state new_state, - struct iwl_mvm_sta_state_ops *callbacks); + const struct iwl_mvm_sta_state_ops *callbacks); /* New MLD STA related APIs */ /* STA */ @@ -646,6 +649,11 @@ int iwl_mvm_mld_update_sta_links(struct iwl_mvm *mvm, u16 old_links, u16 new_links); u32 iwl_mvm_sta_fw_id_mask(struct iwl_mvm *mvm, struct ieee80211_sta *sta, int filter_link_id); +int iwl_mvm_mld_add_int_sta_with_queue(struct iwl_mvm *mvm, + struct iwl_mvm_int_sta *sta, + const u8 *addr, int link_id, + u16 *queue, u8 tid, + unsigned int *_wdg_timeout); /* Queues */ void iwl_mvm_mld_modify_all_sta_disable_tx(struct iwl_mvm *mvm, diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c b/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c index 6b7b6250f1bbdffd66681e28e5354fe884fc6eaf..5f0e7144a951ce9f1eaeb0e781acdfbe13ea01b3 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* - * Copyright (C) 2012-2014, 2018-2022 Intel Corporation + * Copyright (C) 2012-2014, 2018-2023 Intel Corporation * Copyright (C) 2013-2015 Intel Mobile Communications GmbH * Copyright (C) 2017 Intel Deutschland GmbH */ @@ -103,7 +103,7 @@ void iwl_mvm_roc_done_wk(struct work_struct *wk) /* In newer version of this command an aux station is added only * in cases of dedicated tx queue and need to be removed in end * of use */ - if (iwl_fw_lookup_cmd_ver(mvm->fw, ADD_STA, 0) >= 12) + if (iwl_mvm_has_new_station_api(mvm->fw)) iwl_mvm_rm_aux_sta(mvm); } diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c index 00719e1304386454f350677322764e46483fab57..36d70d589aedda6511f3274cacc411cf5b483b38 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c @@ -1,12 +1,13 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* - * Copyright (C) 2012-2014, 2018-2022 Intel Corporation + * Copyright (C) 2012-2014, 2018-2023 Intel Corporation * Copyright (C) 2013-2015 Intel Mobile Communications GmbH * Copyright (C) 2016-2017 Intel Deutschland GmbH */ #include #include #include +#include #include #include @@ -40,13 +41,14 @@ iwl_mvm_bar_check_trigger(struct iwl_mvm *mvm, const u8 *addr, #define OPT_HDR(type, skb, off) \ (type *)(skb_network_header(skb) + (off)) -static u16 iwl_mvm_tx_csum_pre_bz(struct iwl_mvm *mvm, struct sk_buff *skb, - struct ieee80211_tx_info *info, bool amsdu) +static u32 iwl_mvm_tx_csum(struct iwl_mvm *mvm, struct sk_buff *skb, + struct ieee80211_tx_info *info, + bool amsdu) { struct ieee80211_hdr *hdr = (void *)skb->data; + u16 mh_len = ieee80211_hdrlen(hdr->frame_control); u16 offload_assist = 0; #if IS_ENABLED(CONFIG_INET) - u16 mh_len = ieee80211_hdrlen(hdr->frame_control); u8 protocol = 0; /* Do not compute checksum if already computed */ @@ -118,6 +120,8 @@ static u16 iwl_mvm_tx_csum_pre_bz(struct iwl_mvm *mvm, struct sk_buff *skb, else udp_hdr(skb)->check = 0; +out: +#endif /* * mac header len should include IV, size is in words unless * the IV is added by the firmware like in WEP. @@ -130,8 +134,6 @@ static u16 iwl_mvm_tx_csum_pre_bz(struct iwl_mvm *mvm, struct sk_buff *skb, mh_len /= 2; offload_assist |= mh_len << TX_CMD_OFFLD_MH_SIZE; -out: -#endif if (amsdu) offload_assist |= BIT(TX_CMD_OFFLD_AMSDU); else if (ieee80211_hdrlen(hdr->frame_control) % 4) @@ -141,54 +143,6 @@ static u16 iwl_mvm_tx_csum_pre_bz(struct iwl_mvm *mvm, struct sk_buff *skb, return offload_assist; } -u32 iwl_mvm_tx_csum_bz(struct iwl_mvm *mvm, struct sk_buff *skb, bool amsdu) -{ - struct ieee80211_hdr *hdr = (void *)skb->data; - u32 offload_assist = IWL_TX_CMD_OFFLD_BZ_PARTIAL_CSUM; - unsigned int hdrlen = ieee80211_hdrlen(hdr->frame_control); - unsigned int csum_start = skb_checksum_start_offset(skb); - - offload_assist |= u32_encode_bits(hdrlen / 2, - IWL_TX_CMD_OFFLD_BZ_MH_LEN); - if (amsdu) - offload_assist |= IWL_TX_CMD_OFFLD_BZ_AMSDU; - else if (hdrlen % 4) - /* padding is inserted later in transport */ - offload_assist |= IWL_TX_CMD_OFFLD_BZ_MH_PAD; - - if (skb->ip_summed != CHECKSUM_PARTIAL) - return offload_assist; - - offload_assist |= IWL_TX_CMD_OFFLD_BZ_ENABLE_CSUM | - IWL_TX_CMD_OFFLD_BZ_ZERO2ONES; - - /* - * mac80211 will always calculate checksum in software for - * non-fast-xmit, and so we can only do offloaded checksum - * for fast-xmit frames. In this case, we always have the - * RFC 1042 header present. skb_checksum_start_offset() - * returns the offset from the beginning, but the hardware - * needs it from after the header & SNAP header. - */ - csum_start -= hdrlen + 8; - - offload_assist |= u32_encode_bits(csum_start, - IWL_TX_CMD_OFFLD_BZ_START_OFFS); - offload_assist |= u32_encode_bits(csum_start + skb->csum_offset, - IWL_TX_CMD_OFFLD_BZ_RESULT_OFFS); - - return offload_assist; -} - -static u32 iwl_mvm_tx_csum(struct iwl_mvm *mvm, struct sk_buff *skb, - struct ieee80211_tx_info *info, - bool amsdu) -{ - if (!iwl_mvm_has_new_tx_csum(mvm)) - return iwl_mvm_tx_csum_pre_bz(mvm, skb, info, amsdu); - return iwl_mvm_tx_csum_bz(mvm, skb, amsdu); -} - /* * Sets most of the Tx cmd's fields */ @@ -288,7 +242,7 @@ void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb, tx_cmd->sta_id = sta_id; tx_cmd->offload_assist = - cpu_to_le16(iwl_mvm_tx_csum_pre_bz(mvm, skb, info, amsdu)); + cpu_to_le16(iwl_mvm_tx_csum(mvm, skb, info, amsdu)); } static u32 iwl_mvm_get_tx_ant(struct iwl_mvm *mvm, @@ -308,6 +262,54 @@ static u32 iwl_mvm_get_tx_ant(struct iwl_mvm *mvm, return BIT(mvm->mgmt_last_antenna_idx) << RATE_MCS_ANT_POS; } +static u32 iwl_mvm_get_inject_tx_rate(struct iwl_mvm *mvm, + struct ieee80211_tx_info *info) +{ + struct ieee80211_tx_rate *rate = &info->control.rates[0]; + u32 result; + + /* + * we only care about legacy/HT/VHT so far, so we can + * build in v1 and use iwl_new_rate_from_v1() + */ + + if (rate->flags & IEEE80211_TX_RC_VHT_MCS) { + u8 mcs = ieee80211_rate_get_vht_mcs(rate); + u8 nss = ieee80211_rate_get_vht_nss(rate); + + result = RATE_MCS_VHT_MSK_V1; + result |= u32_encode_bits(mcs, RATE_VHT_MCS_RATE_CODE_MSK); + result |= u32_encode_bits(nss, RATE_MCS_NSS_MSK); + if (rate->flags & IEEE80211_TX_RC_SHORT_GI) + result |= RATE_MCS_SGI_MSK_V1; + if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) + result |= u32_encode_bits(1, RATE_MCS_CHAN_WIDTH_MSK_V1); + else if (rate->flags & IEEE80211_TX_RC_80_MHZ_WIDTH) + result |= u32_encode_bits(2, RATE_MCS_CHAN_WIDTH_MSK_V1); + else if (rate->flags & IEEE80211_TX_RC_160_MHZ_WIDTH) + result |= u32_encode_bits(3, RATE_MCS_CHAN_WIDTH_MSK_V1); + } else if (rate->flags & IEEE80211_TX_RC_MCS) { + result = RATE_MCS_HT_MSK_V1; + result |= u32_encode_bits(rate->idx, + RATE_HT_MCS_RATE_CODE_MSK_V1 | + RATE_HT_MCS_NSS_MSK_V1); + if (rate->flags & IEEE80211_TX_RC_SHORT_GI) + result |= RATE_MCS_SGI_MSK_V1; + if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) + result |= u32_encode_bits(1, RATE_MCS_CHAN_WIDTH_MSK_V1); + if (info->flags & IEEE80211_TX_CTL_LDPC) + result |= RATE_MCS_LDPC_MSK_V1; + if (u32_get_bits(info->flags, IEEE80211_TX_CTL_STBC)) + result |= RATE_MCS_STBC_MSK; + } else { + return 0; + } + + if (iwl_fw_lookup_notif_ver(mvm->fw, LONG_GROUP, TX_CMD, 0) > 6) + return iwl_new_rate_from_v1(result); + return result; +} + static u32 iwl_mvm_get_tx_rate(struct iwl_mvm *mvm, struct ieee80211_tx_info *info, struct ieee80211_sta *sta, __le16 fc) @@ -317,8 +319,15 @@ static u32 iwl_mvm_get_tx_rate(struct iwl_mvm *mvm, u32 rate_flags = 0; bool is_cck; - /* info->control is only relevant for non HW rate control */ - if (!ieee80211_hw_check(mvm->hw, HAS_RATE_CONTROL)) { + if (unlikely(info->control.flags & IEEE80211_TX_CTRL_RATE_INJECT)) { + u32 result = iwl_mvm_get_inject_tx_rate(mvm, info); + + if (result) + return result; + rate_idx = info->control.rates[0].idx; + } else if (!ieee80211_hw_check(mvm->hw, HAS_RATE_CONTROL)) { + /* info->control is only relevant for non HW rate control */ + /* HT rate doesn't make sense for a non data frame */ WARN_ONCE(info->control.rates[0].flags & IEEE80211_TX_RC_MCS && !ieee80211_is_data(fc), @@ -398,7 +407,8 @@ void iwl_mvm_set_tx_cmd_rate(struct iwl_mvm *mvm, struct iwl_tx_cmd *tx_cmd, * table is controlled by LINK_QUALITY commands */ - if (ieee80211_is_data(fc) && sta) { + if (likely(ieee80211_is_data(fc) && sta && + !(info->control.flags & IEEE80211_TX_CTRL_RATE_INJECT))) { struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); if (mvmsta->sta_state >= IEEE80211_STA_AUTHORIZED) { @@ -556,9 +566,8 @@ iwl_mvm_set_tx_params(struct iwl_mvm *mvm, struct sk_buff *skb, cmd->rate_n_flags = cpu_to_le32(rate_n_flags); } else { struct iwl_tx_cmd_gen2 *cmd = (void *)dev_cmd->payload; - u16 offload_assist = iwl_mvm_tx_csum_pre_bz(mvm, skb, - info, - amsdu); + u16 offload_assist = iwl_mvm_tx_csum(mvm, skb, + info, amsdu); cmd->offload_assist = cpu_to_le16(offload_assist); @@ -749,6 +758,8 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb) } link = mvmvif->link[link_id]; + if (WARN_ON(!link)) + return -1; if (!ieee80211_is_data(hdr->frame_control)) sta_id = link->bcast_sta.sta_id; @@ -840,7 +851,7 @@ unsigned int iwl_mvm_max_amsdu_size(struct iwl_mvm *mvm, band = mvmsta->vif->bss_conf.chandef.chan->band; } - lmac = iwl_mvm_get_lmac_id(mvm->fw, band); + lmac = iwl_mvm_get_lmac_id(mvm, band); } else if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_CDB_SUPPORT)) { /* for real MLO restrict to both LMACs if they exist */ @@ -2065,7 +2076,8 @@ void iwl_mvm_rx_ba_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb) u16 tfd_cnt; int i; - if (unlikely(sizeof(*ba_res) > pkt_len)) + if (IWL_FW_CHECK(mvm, sizeof(*ba_res) > pkt_len, + "short BA notification (%d)\n", pkt_len)) return; sta_id = ba_res->sta_id; @@ -2077,7 +2089,13 @@ void iwl_mvm_rx_ba_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb) (void *)(uintptr_t)ba_res->reduced_txp; tfd_cnt = le16_to_cpu(ba_res->tfd_cnt); - if (!tfd_cnt || struct_size(ba_res, tfd, tfd_cnt) > pkt_len) + if (!tfd_cnt) + return; + + if (IWL_FW_CHECK(mvm, + struct_size(ba_res, tfd, tfd_cnt) > pkt_len, + "short BA notification (tfds:%d, size:%d)\n", + tfd_cnt, pkt_len)) return; rcu_read_lock(); @@ -2135,7 +2153,9 @@ void iwl_mvm_rx_ba_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb) rcu_read_lock(); mvmsta = iwl_mvm_sta_from_staid_rcu(mvm, sta_id); - if (WARN_ON_ONCE(!mvmsta)) { + if (IWL_FW_CHECK(mvm, !mvmsta, + "invalid STA ID %d in BA notif\n", + sta_id)) { rcu_read_unlock(); return; } diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c index af31b09c396644aca5d3fa3f9ac63392e37807a3..48016b4343d26f7ef27aa3c114d4ed64a8aab3e1 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* - * Copyright (C) 2012-2014, 2018-2022 Intel Corporation + * Copyright (C) 2012-2014, 2018-2023 Intel Corporation * Copyright (C) 2013-2014 Intel Mobile Communications GmbH * Copyright (C) 2015-2017 Intel Deutschland GmbH */ @@ -312,6 +312,10 @@ void iwl_mvm_update_smps(struct iwl_mvm *mvm, struct ieee80211_vif *vif, smps_mode = IEEE80211_SMPS_DYNAMIC; } + /* SMPS is disabled in eSR */ + if (mvmvif->esr_active) + smps_mode = IEEE80211_SMPS_OFF; + ieee80211_request_smps(vif, link_id, smps_mode); } @@ -413,16 +417,20 @@ static void iwl_mvm_diversity_iter(void *_data, u8 *mac, { struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); struct iwl_mvm_diversity_iter_data *data = _data; - int i; + int i, link_id; - if (mvmvif->deflink.phy_ctxt != data->ctxt) - return; + for_each_mvm_vif_valid_link(mvmvif, link_id) { + struct iwl_mvm_vif_link_info *link_info = mvmvif->link[link_id]; - for (i = 0; i < NUM_IWL_MVM_SMPS_REQ; i++) { - if (mvmvif->deflink.smps_requests[i] == IEEE80211_SMPS_STATIC || - mvmvif->deflink.smps_requests[i] == IEEE80211_SMPS_DYNAMIC) { - data->result = false; - break; + if (link_info->phy_ctxt != data->ctxt) + continue; + + for (i = 0; i < NUM_IWL_MVM_SMPS_REQ; i++) { + if (link_info->smps_requests[i] == IEEE80211_SMPS_STATIC || + link_info->smps_requests[i] == IEEE80211_SMPS_DYNAMIC) { + data->result = false; + break; + } } } } diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c index cb60ba40fe973d31db8cf15ee8057a2b005c24b2..fa4a145468601217cb66b051a86d596047f0104f 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* - * Copyright (C) 2018-2022 Intel Corporation + * Copyright (C) 2018-2023 Intel Corporation */ #include "iwl-trans.h" #include "iwl-fh.h" @@ -281,70 +281,273 @@ void iwl_pcie_ctxt_info_gen3_free(struct iwl_trans *trans, bool alive) trans_pcie->prph_info = NULL; } -int iwl_trans_pcie_ctx_info_gen3_set_pnvm(struct iwl_trans *trans, - const void *data, u32 len) +static int iwl_pcie_load_payloads_continuously(struct iwl_trans *trans, + const struct iwl_pnvm_image *pnvm_data, + struct iwl_dram_data *dram) +{ + u32 len, len0, len1; + + if (pnvm_data->n_chunks != UNFRAGMENTED_PNVM_PAYLOADS_NUMBER) { + IWL_DEBUG_FW(trans, "expected 2 payloads, got %d.\n", + pnvm_data->n_chunks); + return -EINVAL; + } + + len0 = pnvm_data->chunks[0].len; + len1 = pnvm_data->chunks[1].len; + if (len1 > 0xFFFFFFFF - len0) { + IWL_DEBUG_FW(trans, "sizes of payloads overflow.\n"); + return -EINVAL; + } + len = len0 + len1; + + dram->block = iwl_pcie_ctxt_info_dma_alloc_coherent(trans, len, + &dram->physical); + if (!dram->block) { + IWL_DEBUG_FW(trans, "Failed to allocate PNVM DMA.\n"); + return -ENOMEM; + } + + dram->size = len; + memcpy(dram->block, pnvm_data->chunks[0].data, len0); + memcpy((u8 *)dram->block + len0, pnvm_data->chunks[1].data, len1); + + return 0; +} + +static int iwl_pcie_load_payloads_segments + (struct iwl_trans *trans, + struct iwl_dram_regions *dram_regions, + const struct iwl_pnvm_image *pnvm_data) +{ + struct iwl_dram_data *cur_payload_dram = &dram_regions->drams[0]; + struct iwl_dram_data *desc_dram = &dram_regions->prph_scratch_mem_desc; + struct iwl_prph_scrath_mem_desc_addr_array *addresses; + const void *data; + u32 len; + int i; + + /* allocate and init DRAM descriptors array */ + len = sizeof(struct iwl_prph_scrath_mem_desc_addr_array); + desc_dram->block = iwl_pcie_ctxt_info_dma_alloc_coherent + (trans, + len, + &desc_dram->physical); + if (!desc_dram->block) { + IWL_DEBUG_FW(trans, "Failed to allocate PNVM DMA.\n"); + return -ENOMEM; + } + desc_dram->size = len; + memset(desc_dram->block, 0, len); + + /* allocate DRAM region for each payload */ + dram_regions->n_regions = 0; + for (i = 0; i < pnvm_data->n_chunks; i++) { + len = pnvm_data->chunks[i].len; + data = pnvm_data->chunks[i].data; + + if (iwl_pcie_ctxt_info_alloc_dma(trans, + data, + len, + cur_payload_dram)) { + iwl_trans_pcie_free_pnvm_dram_regions(dram_regions, + trans->dev); + return -ENOMEM; + } + + dram_regions->n_regions++; + cur_payload_dram++; + } + + /* fill desc with the DRAM payloads addresses */ + addresses = desc_dram->block; + for (i = 0; i < pnvm_data->n_chunks; i++) { + addresses->mem_descs[i] = + cpu_to_le64(dram_regions->drams[i].physical); + } + + return 0; + +} + +int iwl_trans_pcie_ctx_info_gen3_load_pnvm(struct iwl_trans *trans, + const struct iwl_pnvm_image *pnvm_payloads, + const struct iwl_ucode_capabilities *capa) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); struct iwl_prph_scratch_ctrl_cfg *prph_sc_ctrl = &trans_pcie->prph_scratch->ctrl_cfg; - int ret; + struct iwl_dram_regions *dram_regions = &trans_pcie->pnvm_data; + int ret = 0; + + /* only allocate the DRAM if not allocated yet */ + if (trans->pnvm_loaded) + return 0; + + if (WARN_ON(prph_sc_ctrl->pnvm_cfg.pnvm_size)) + return -EBUSY; if (trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_AX210) return 0; - /* only allocate the DRAM if not allocated yet */ - if (!trans->pnvm_loaded) { - if (WARN_ON(prph_sc_ctrl->pnvm_cfg.pnvm_size)) - return -EBUSY; - - ret = iwl_pcie_ctxt_info_alloc_dma(trans, data, len, - &trans_pcie->pnvm_dram); - if (ret < 0) { - IWL_DEBUG_FW(trans, "Failed to allocate PNVM DMA %d.\n", - ret); - return ret; + if (!pnvm_payloads->n_chunks) { + IWL_DEBUG_FW(trans, "no payloads\n"); + return -EINVAL; + } + + /* save payloads in several DRAM sections */ + if (fw_has_capa(capa, IWL_UCODE_TLV_CAPA_FRAGMENTED_PNVM_IMG)) { + ret = iwl_pcie_load_payloads_segments(trans, + dram_regions, + pnvm_payloads); + if (!ret) + trans->pnvm_loaded = true; + } else { + /* save only in one DRAM section */ + ret = iwl_pcie_load_payloads_continuously + (trans, + pnvm_payloads, + &dram_regions->drams[0]); + if (!ret) { + dram_regions->n_regions = 1; + trans->pnvm_loaded = true; } } + return ret; +} + +static inline size_t +iwl_dram_regions_size(const struct iwl_dram_regions *dram_regions) +{ + size_t total_size = 0; + int i; + + for (i = 0; i < dram_regions->n_regions; i++) + total_size += dram_regions->drams[i].size; + + return total_size; +} + +static void iwl_pcie_set_pnvm_segments(struct iwl_trans *trans) +{ + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); + struct iwl_prph_scratch_ctrl_cfg *prph_sc_ctrl = + &trans_pcie->prph_scratch->ctrl_cfg; + struct iwl_dram_regions *dram_regions = &trans_pcie->pnvm_data; + prph_sc_ctrl->pnvm_cfg.pnvm_base_addr = - cpu_to_le64(trans_pcie->pnvm_dram.physical); + cpu_to_le64(dram_regions->prph_scratch_mem_desc.physical); prph_sc_ctrl->pnvm_cfg.pnvm_size = - cpu_to_le32(trans_pcie->pnvm_dram.size); + cpu_to_le32(iwl_dram_regions_size(dram_regions)); +} - return 0; +static void iwl_pcie_set_continuous_pnvm(struct iwl_trans *trans) +{ + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); + struct iwl_prph_scratch_ctrl_cfg *prph_sc_ctrl = + &trans_pcie->prph_scratch->ctrl_cfg; + + prph_sc_ctrl->pnvm_cfg.pnvm_base_addr = + cpu_to_le64(trans_pcie->pnvm_data.drams[0].physical); + prph_sc_ctrl->pnvm_cfg.pnvm_size = + cpu_to_le32(trans_pcie->pnvm_data.drams[0].size); +} + +void iwl_trans_pcie_ctx_info_gen3_set_pnvm(struct iwl_trans *trans, + const struct iwl_ucode_capabilities *capa) +{ + if (trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_AX210) + return; + + if (fw_has_capa(capa, IWL_UCODE_TLV_CAPA_FRAGMENTED_PNVM_IMG)) + iwl_pcie_set_pnvm_segments(trans); + else + iwl_pcie_set_continuous_pnvm(trans); } -int iwl_trans_pcie_ctx_info_gen3_set_reduce_power(struct iwl_trans *trans, - const void *data, u32 len) +int iwl_trans_pcie_ctx_info_gen3_load_reduce_power(struct iwl_trans *trans, + const struct iwl_pnvm_image *payloads, + const struct iwl_ucode_capabilities *capa) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); struct iwl_prph_scratch_ctrl_cfg *prph_sc_ctrl = &trans_pcie->prph_scratch->ctrl_cfg; - int ret; + struct iwl_dram_regions *dram_regions = &trans_pcie->reduced_tables_data; + int ret = 0; + + /* only allocate the DRAM if not allocated yet */ + if (trans->reduce_power_loaded) + return 0; if (trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_AX210) return 0; - /* only allocate the DRAM if not allocated yet */ - if (!trans->reduce_power_loaded) { - if (WARN_ON(prph_sc_ctrl->reduce_power_cfg.size)) - return -EBUSY; + if (WARN_ON(prph_sc_ctrl->reduce_power_cfg.size)) + return -EBUSY; - ret = iwl_pcie_ctxt_info_alloc_dma(trans, data, len, - &trans_pcie->reduce_power_dram); - if (ret < 0) { - IWL_DEBUG_FW(trans, - "Failed to allocate reduce power DMA %d.\n", - ret); - return ret; + if (!payloads->n_chunks) { + IWL_DEBUG_FW(trans, "no payloads\n"); + return -EINVAL; + } + + /* save payloads in several DRAM sections */ + if (fw_has_capa(capa, IWL_UCODE_TLV_CAPA_FRAGMENTED_PNVM_IMG)) { + ret = iwl_pcie_load_payloads_segments(trans, + dram_regions, + payloads); + if (!ret) + trans->reduce_power_loaded = true; + } else { + /* save only in one DRAM section */ + ret = iwl_pcie_load_payloads_continuously + (trans, + payloads, + &dram_regions->drams[0]); + if (!ret) { + dram_regions->n_regions = 1; + trans->reduce_power_loaded = true; } } + return ret; +} + +static void iwl_pcie_set_reduce_power_segments(struct iwl_trans *trans) +{ + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); + struct iwl_prph_scratch_ctrl_cfg *prph_sc_ctrl = + &trans_pcie->prph_scratch->ctrl_cfg; + struct iwl_dram_regions *dram_regions = &trans_pcie->reduced_tables_data; + prph_sc_ctrl->reduce_power_cfg.base_addr = - cpu_to_le64(trans_pcie->reduce_power_dram.physical); + cpu_to_le64(dram_regions->prph_scratch_mem_desc.physical); prph_sc_ctrl->reduce_power_cfg.size = - cpu_to_le32(trans_pcie->reduce_power_dram.size); + cpu_to_le32(iwl_dram_regions_size(dram_regions)); +} - return 0; +static void iwl_pcie_set_continuous_reduce_power(struct iwl_trans *trans) +{ + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); + struct iwl_prph_scratch_ctrl_cfg *prph_sc_ctrl = + &trans_pcie->prph_scratch->ctrl_cfg; + + prph_sc_ctrl->reduce_power_cfg.base_addr = + cpu_to_le64(trans_pcie->reduced_tables_data.drams[0].physical); + prph_sc_ctrl->reduce_power_cfg.size = + cpu_to_le32(trans_pcie->reduced_tables_data.drams[0].size); +} + +void +iwl_trans_pcie_ctx_info_gen3_set_reduce_power(struct iwl_trans *trans, + const struct iwl_ucode_capabilities *capa) +{ + if (trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_AX210) + return; + + if (fw_has_capa(capa, IWL_UCODE_TLV_CAPA_FRAGMENTED_PNVM_IMG)) + iwl_pcie_set_reduce_power_segments(trans); + else + iwl_pcie_set_continuous_reduce_power(trans); } diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c index 74ce31fdf45e974bdd6c5c8ce5cc1f959647f97b..5f55efe64bf5c4cc86d2d1418a901d5b55bc5d6f 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* * Copyright (C) 2017 Intel Deutschland GmbH - * Copyright (C) 2018-2021 Intel Corporation + * Copyright (C) 2018-2022 Intel Corporation */ #include "iwl-trans.h" #include "iwl-fh.h" @@ -38,9 +38,9 @@ static void *_iwl_pcie_ctxt_info_dma_alloc_coherent(struct iwl_trans *trans, return result; } -static void *iwl_pcie_ctxt_info_dma_alloc_coherent(struct iwl_trans *trans, - size_t size, - dma_addr_t *phys) +void *iwl_pcie_ctxt_info_dma_alloc_coherent(struct iwl_trans *trans, + size_t size, + dma_addr_t *phys) { return _iwl_pcie_ctxt_info_dma_alloc_coherent(trans, size, phys, 0); } diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c index dba1123948386c2199123f18f006d957b77153ff..73c1fb3c0c5ecdafa4aa678a60a4e034ac63db54 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c @@ -484,17 +484,15 @@ static const struct pci_device_id iwl_hw_card_ids[] = { {IWL_PCI_DEVICE(0x43F0, PCI_ANY_ID, iwl_qu_long_latency_trans_cfg)}, {IWL_PCI_DEVICE(0xA0F0, PCI_ANY_ID, iwl_qu_long_latency_trans_cfg)}, - {IWL_PCI_DEVICE(0x2720, PCI_ANY_ID, iwl_qnj_trans_cfg)}, - {IWL_PCI_DEVICE(0x2723, PCI_ANY_ID, iwl_ax200_trans_cfg)}, /* So devices */ {IWL_PCI_DEVICE(0x2725, PCI_ANY_ID, iwl_so_trans_cfg)}, - {IWL_PCI_DEVICE(0x2726, PCI_ANY_ID, iwl_snj_trans_cfg)}, {IWL_PCI_DEVICE(0x7A70, PCI_ANY_ID, iwl_so_long_latency_imr_trans_cfg)}, {IWL_PCI_DEVICE(0x7AF0, PCI_ANY_ID, iwl_so_trans_cfg)}, {IWL_PCI_DEVICE(0x51F0, PCI_ANY_ID, iwl_so_long_latency_trans_cfg)}, {IWL_PCI_DEVICE(0x51F1, PCI_ANY_ID, iwl_so_long_latency_imr_trans_cfg)}, + {IWL_PCI_DEVICE(0x51F1, PCI_ANY_ID, iwl_so_long_latency_trans_cfg)}, {IWL_PCI_DEVICE(0x54F0, PCI_ANY_ID, iwl_so_long_latency_trans_cfg)}, {IWL_PCI_DEVICE(0x7F70, PCI_ANY_ID, iwl_so_trans_cfg)}, @@ -507,6 +505,9 @@ static const struct pci_device_id iwl_hw_card_ids[] = { {IWL_PCI_DEVICE(0x272b, PCI_ANY_ID, iwl_bz_trans_cfg)}, {IWL_PCI_DEVICE(0xA840, PCI_ANY_ID, iwl_bz_trans_cfg)}, {IWL_PCI_DEVICE(0x7740, PCI_ANY_ID, iwl_bz_trans_cfg)}, + +/* Sc devices */ + {IWL_PCI_DEVICE(0xE440, PCI_ANY_ID, iwl_sc_trans_cfg)}, #endif /* CONFIG_IWLMVM */ {0} @@ -514,17 +515,16 @@ static const struct pci_device_id iwl_hw_card_ids[] = { MODULE_DEVICE_TABLE(pci, iwl_hw_card_ids); #define _IWL_DEV_INFO(_device, _subdevice, _mac_type, _mac_step, _rf_type, \ - _rf_id, _rf_step, _no_160, _cores, _cdb, _jacket, _cfg, \ - _name) \ + _rf_id, _rf_step, _no_160, _cores, _cdb, _cfg, _name) \ { .device = (_device), .subdevice = (_subdevice), .cfg = &(_cfg), \ .name = _name, .mac_type = _mac_type, .rf_type = _rf_type, .rf_step = _rf_step, \ .no_160 = _no_160, .cores = _cores, .rf_id = _rf_id, \ - .mac_step = _mac_step, .cdb = _cdb, .jacket = _jacket } + .mac_step = _mac_step, .cdb = _cdb, .jacket = IWL_CFG_ANY } #define IWL_DEV_INFO(_device, _subdevice, _cfg, _name) \ - _IWL_DEV_INFO(_device, _subdevice, IWL_CFG_ANY, IWL_CFG_ANY, \ - IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY, \ - IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY, _cfg, _name) + _IWL_DEV_INFO(_device, _subdevice, IWL_CFG_ANY, IWL_CFG_ANY, \ + IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY, \ + IWL_CFG_ANY, _cfg, _name) static const struct iwl_dev_info iwl_dev_info_table[] = { #if IS_ENABLED(CONFIG_IWLMVM) @@ -544,14 +544,17 @@ static const struct iwl_dev_info iwl_dev_info_table[] = { IWL_DEV_INFO(0x51F0, 0x1551, iwl9560_2ac_cfg_soc, iwl9560_killer_1550i_160_name), IWL_DEV_INFO(0x51F0, 0x1691, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690s_name), IWL_DEV_INFO(0x51F0, 0x1692, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690i_name), + IWL_DEV_INFO(0x51F1, 0x1692, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690i_name), IWL_DEV_INFO(0x54F0, 0x1691, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690s_name), IWL_DEV_INFO(0x54F0, 0x1692, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690i_name), IWL_DEV_INFO(0x7A70, 0x1691, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690s_name), IWL_DEV_INFO(0x7A70, 0x1692, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690i_name), + IWL_DEV_INFO(0x7AF0, 0x1691, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690s_name), + IWL_DEV_INFO(0x7AF0, 0x1692, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690i_name), IWL_DEV_INFO(0x271C, 0x0214, iwl9260_2ac_cfg, iwl9260_1_name), - IWL_DEV_INFO(0x7E40, 0x1691, iwl_cfg_ma_a0_gf4_a0, iwl_ax411_killer_1690s_name), - IWL_DEV_INFO(0x7E40, 0x1692, iwl_cfg_ma_a0_gf4_a0, iwl_ax411_killer_1690i_name), + IWL_DEV_INFO(0x7E40, 0x1691, iwl_cfg_ma, iwl_ax411_killer_1690s_name), + IWL_DEV_INFO(0x7E40, 0x1692, iwl_cfg_ma, iwl_ax411_killer_1690i_name), /* AX200 */ IWL_DEV_INFO(0x2723, IWL_CFG_ANY, iwl_ax200_cfg_cc, iwl_ax200_name), @@ -661,25 +664,13 @@ static const struct iwl_dev_info iwl_dev_info_table[] = { IWL_DEV_INFO(0x7AF0, 0x1551, iwl9560_2ac_cfg_soc, iwl9560_killer_1550s_160_name), IWL_DEV_INFO(0x7AF0, 0x1552, iwl9560_2ac_cfg_soc, iwl9560_killer_1550i_160_name), - /* SnJ with HR */ - IWL_DEV_INFO(0x2725, 0x00B0, iwlax411_2ax_cfg_sosnj_gf4_a0, NULL), - IWL_DEV_INFO(0x2726, 0x0090, iwlax211_cfg_snj_gf_a0, NULL), - IWL_DEV_INFO(0x2726, 0x0098, iwlax211_cfg_snj_gf_a0, NULL), - IWL_DEV_INFO(0x2726, 0x00B0, iwlax411_2ax_cfg_sosnj_gf4_a0, NULL), - IWL_DEV_INFO(0x2726, 0x00B4, iwlax411_2ax_cfg_sosnj_gf4_a0, NULL), - IWL_DEV_INFO(0x2726, 0x0510, iwlax211_cfg_snj_gf_a0, NULL), - IWL_DEV_INFO(0x2726, 0x1651, iwl_cfg_snj_hr_b0, iwl_ax201_killer_1650s_name), - IWL_DEV_INFO(0x2726, 0x1652, iwl_cfg_snj_hr_b0, iwl_ax201_killer_1650i_name), - IWL_DEV_INFO(0x2726, 0x1691, iwlax411_2ax_cfg_sosnj_gf4_a0, iwl_ax411_killer_1690s_name), - IWL_DEV_INFO(0x2726, 0x1692, iwlax411_2ax_cfg_sosnj_gf4_a0, iwl_ax411_killer_1690i_name), - IWL_DEV_INFO(0x7F70, 0x1691, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690s_name), - IWL_DEV_INFO(0x7F70, 0x1692, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690i_name), - /* SO with GF2 */ IWL_DEV_INFO(0x2726, 0x1671, iwlax211_2ax_cfg_so_gf_a0, iwl_ax211_killer_1675s_name), IWL_DEV_INFO(0x2726, 0x1672, iwlax211_2ax_cfg_so_gf_a0, iwl_ax211_killer_1675i_name), IWL_DEV_INFO(0x51F0, 0x1671, iwlax211_2ax_cfg_so_gf_a0, iwl_ax211_killer_1675s_name), IWL_DEV_INFO(0x51F0, 0x1672, iwlax211_2ax_cfg_so_gf_a0, iwl_ax211_killer_1675i_name), + IWL_DEV_INFO(0x51F1, 0x1671, iwlax211_2ax_cfg_so_gf_a0, iwl_ax211_killer_1675s_name), + IWL_DEV_INFO(0x51F1, 0x1672, iwlax211_2ax_cfg_so_gf_a0, iwl_ax211_killer_1675i_name), IWL_DEV_INFO(0x54F0, 0x1671, iwlax211_2ax_cfg_so_gf_a0, iwl_ax211_killer_1675s_name), IWL_DEV_INFO(0x54F0, 0x1672, iwlax211_2ax_cfg_so_gf_a0, iwl_ax211_killer_1675i_name), IWL_DEV_INFO(0x7A70, 0x1671, iwlax211_2ax_cfg_so_gf_a0, iwl_ax211_killer_1675s_name), @@ -690,93 +681,72 @@ static const struct iwl_dev_info iwl_dev_info_table[] = { IWL_DEV_INFO(0x7F70, 0x1672, iwlax211_2ax_cfg_so_gf_a0, iwl_ax211_killer_1675i_name), /* MA with GF2 */ - IWL_DEV_INFO(0x7E40, 0x1671, iwl_cfg_ma_a0_gf_a0, iwl_ax211_killer_1675s_name), - IWL_DEV_INFO(0x7E40, 0x1672, iwl_cfg_ma_a0_gf_a0, iwl_ax211_killer_1675i_name), + IWL_DEV_INFO(0x7E40, 0x1671, iwl_cfg_ma, iwl_ax211_killer_1675s_name), + IWL_DEV_INFO(0x7E40, 0x1672, iwl_cfg_ma, iwl_ax211_killer_1675i_name), _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_MAC_TYPE_PU, IWL_CFG_ANY, IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1, IWL_CFG_ANY, - IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY, + IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, iwl9560_2ac_cfg_soc, iwl9461_160_name), _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_MAC_TYPE_PU, IWL_CFG_ANY, IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1, IWL_CFG_ANY, - IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY, + IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, iwl9560_2ac_cfg_soc, iwl9461_name), _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_MAC_TYPE_PU, IWL_CFG_ANY, IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV, IWL_CFG_ANY, - IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY, + IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, iwl9560_2ac_cfg_soc, iwl9462_160_name), _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_MAC_TYPE_PU, IWL_CFG_ANY, IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV, IWL_CFG_ANY, - IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY, + IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, iwl9560_2ac_cfg_soc, iwl9462_name), _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_MAC_TYPE_PU, IWL_CFG_ANY, IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY, - IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY, + IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, iwl9560_2ac_cfg_soc, iwl9560_160_name), _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_MAC_TYPE_PU, IWL_CFG_ANY, IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY, - IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY, + IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, iwl9560_2ac_cfg_soc, iwl9560_name), - _IWL_DEV_INFO(0x2526, IWL_CFG_ANY, - IWL_CFG_MAC_TYPE_PNJ, IWL_CFG_ANY, - IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1, IWL_CFG_ANY, - IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY, - iwl9260_2ac_cfg, iwl9461_160_name), - _IWL_DEV_INFO(0x2526, IWL_CFG_ANY, - IWL_CFG_MAC_TYPE_PNJ, IWL_CFG_ANY, - IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1, IWL_CFG_ANY, - IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY, - iwl9260_2ac_cfg, iwl9461_name), - _IWL_DEV_INFO(0x2526, IWL_CFG_ANY, - IWL_CFG_MAC_TYPE_PNJ, IWL_CFG_ANY, - IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV, IWL_CFG_ANY, - IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY, - iwl9260_2ac_cfg, iwl9462_160_name), - _IWL_DEV_INFO(0x2526, IWL_CFG_ANY, - IWL_CFG_MAC_TYPE_PNJ, IWL_CFG_ANY, - IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV, IWL_CFG_ANY, - IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY, - iwl9260_2ac_cfg, iwl9462_name), - _IWL_DEV_INFO(0x2526, IWL_CFG_ANY, IWL_CFG_MAC_TYPE_TH, IWL_CFG_ANY, IWL_CFG_RF_TYPE_TH, IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_160, IWL_CFG_CORES_BT_GNSS, IWL_CFG_NO_CDB, IWL_CFG_ANY, + IWL_CFG_160, IWL_CFG_CORES_BT_GNSS, IWL_CFG_NO_CDB, iwl9260_2ac_cfg, iwl9270_160_name), _IWL_DEV_INFO(0x2526, IWL_CFG_ANY, IWL_CFG_MAC_TYPE_TH, IWL_CFG_ANY, IWL_CFG_RF_TYPE_TH, IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_NO_160, IWL_CFG_CORES_BT_GNSS, IWL_CFG_NO_CDB, IWL_CFG_ANY, + IWL_CFG_NO_160, IWL_CFG_CORES_BT_GNSS, IWL_CFG_NO_CDB, iwl9260_2ac_cfg, iwl9270_name), _IWL_DEV_INFO(0x271B, IWL_CFG_ANY, IWL_CFG_MAC_TYPE_TH, IWL_CFG_ANY, IWL_CFG_RF_TYPE_TH1, IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY, + IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, iwl9260_2ac_cfg, iwl9162_160_name), _IWL_DEV_INFO(0x271B, IWL_CFG_ANY, IWL_CFG_MAC_TYPE_TH, IWL_CFG_ANY, IWL_CFG_RF_TYPE_TH1, IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY, + IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, iwl9260_2ac_cfg, iwl9162_name), _IWL_DEV_INFO(0x2526, IWL_CFG_ANY, IWL_CFG_MAC_TYPE_TH, IWL_CFG_ANY, IWL_CFG_RF_TYPE_TH, IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY, + IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, iwl9260_2ac_cfg, iwl9260_160_name), _IWL_DEV_INFO(0x2526, IWL_CFG_ANY, IWL_CFG_MAC_TYPE_TH, IWL_CFG_ANY, IWL_CFG_RF_TYPE_TH, IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY, + IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, iwl9260_2ac_cfg, iwl9260_name), /* Qu with Jf */ @@ -784,585 +754,341 @@ static const struct iwl_dev_info iwl_dev_info_table[] = { _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_MAC_TYPE_QU, SILICON_B_STEP, IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1, IWL_CFG_ANY, - IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY, + IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, iwl9560_qu_b0_jf_b0_cfg, iwl9461_160_name), _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_MAC_TYPE_QU, SILICON_B_STEP, IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1, IWL_CFG_ANY, - IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY, + IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, iwl9560_qu_b0_jf_b0_cfg, iwl9461_name), _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_MAC_TYPE_QU, SILICON_B_STEP, IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV, IWL_CFG_ANY, - IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY, + IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, iwl9560_qu_b0_jf_b0_cfg, iwl9462_160_name), _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_MAC_TYPE_QU, SILICON_B_STEP, IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV, IWL_CFG_ANY, - IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY, + IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, iwl9560_qu_b0_jf_b0_cfg, iwl9462_name), _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_MAC_TYPE_QU, SILICON_B_STEP, IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY, - IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY, + IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, iwl9560_qu_b0_jf_b0_cfg, iwl9560_160_name), _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_MAC_TYPE_QU, SILICON_B_STEP, IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY, - IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY, + IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, iwl9560_qu_b0_jf_b0_cfg, iwl9560_name), _IWL_DEV_INFO(IWL_CFG_ANY, 0x1551, IWL_CFG_MAC_TYPE_QU, SILICON_B_STEP, IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY, - IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY, + IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, iwl9560_qu_b0_jf_b0_cfg, iwl9560_killer_1550s_name), _IWL_DEV_INFO(IWL_CFG_ANY, 0x1552, IWL_CFG_MAC_TYPE_QU, SILICON_B_STEP, IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY, - IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY, + IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, iwl9560_qu_b0_jf_b0_cfg, iwl9560_killer_1550i_name), /* Qu C step */ _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_MAC_TYPE_QU, SILICON_C_STEP, IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1, IWL_CFG_ANY, - IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY, + IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, iwl9560_qu_c0_jf_b0_cfg, iwl9461_160_name), _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_MAC_TYPE_QU, SILICON_C_STEP, IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1, IWL_CFG_ANY, - IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY, + IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, iwl9560_qu_c0_jf_b0_cfg, iwl9461_name), _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_MAC_TYPE_QU, SILICON_C_STEP, IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV, IWL_CFG_ANY, - IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY, + IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, iwl9560_qu_c0_jf_b0_cfg, iwl9462_160_name), _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_MAC_TYPE_QU, SILICON_C_STEP, IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV, IWL_CFG_ANY, - IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY, + IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, iwl9560_qu_c0_jf_b0_cfg, iwl9462_name), _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_MAC_TYPE_QU, SILICON_C_STEP, IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY, - IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY, + IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, iwl9560_qu_c0_jf_b0_cfg, iwl9560_160_name), _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_MAC_TYPE_QU, SILICON_C_STEP, IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY, - IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY, + IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, iwl9560_qu_c0_jf_b0_cfg, iwl9560_name), _IWL_DEV_INFO(IWL_CFG_ANY, 0x1551, IWL_CFG_MAC_TYPE_QU, SILICON_C_STEP, IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY, - IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY, + IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, iwl9560_qu_c0_jf_b0_cfg, iwl9560_killer_1550s_name), _IWL_DEV_INFO(IWL_CFG_ANY, 0x1552, IWL_CFG_MAC_TYPE_QU, SILICON_C_STEP, IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY, - IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY, + IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, iwl9560_qu_c0_jf_b0_cfg, iwl9560_killer_1550i_name), /* QuZ */ _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_MAC_TYPE_QUZ, IWL_CFG_ANY, IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1, IWL_CFG_ANY, - IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY, + IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, iwl9560_quz_a0_jf_b0_cfg, iwl9461_160_name), _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_MAC_TYPE_QUZ, IWL_CFG_ANY, IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1, IWL_CFG_ANY, - IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY, + IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, iwl9560_quz_a0_jf_b0_cfg, iwl9461_name), _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_MAC_TYPE_QUZ, IWL_CFG_ANY, IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV, IWL_CFG_ANY, - IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY, + IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, iwl9560_quz_a0_jf_b0_cfg, iwl9462_160_name), _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_MAC_TYPE_QUZ, IWL_CFG_ANY, IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV, IWL_CFG_ANY, - IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY, + IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, iwl9560_quz_a0_jf_b0_cfg, iwl9462_name), _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_MAC_TYPE_QUZ, IWL_CFG_ANY, IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY, - IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY, + IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, iwl9560_quz_a0_jf_b0_cfg, iwl9560_160_name), _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_MAC_TYPE_QUZ, IWL_CFG_ANY, IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY, - IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY, + IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, iwl9560_quz_a0_jf_b0_cfg, iwl9560_name), _IWL_DEV_INFO(IWL_CFG_ANY, 0x1551, IWL_CFG_MAC_TYPE_QUZ, IWL_CFG_ANY, IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY, - IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY, + IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, iwl9560_quz_a0_jf_b0_cfg, iwl9560_killer_1550s_name), _IWL_DEV_INFO(IWL_CFG_ANY, 0x1552, IWL_CFG_MAC_TYPE_QUZ, IWL_CFG_ANY, IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY, - IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY, + IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, iwl9560_quz_a0_jf_b0_cfg, iwl9560_killer_1550i_name), - /* QnJ */ - _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_MAC_TYPE_QNJ, IWL_CFG_ANY, - IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1, IWL_CFG_ANY, - IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY, - iwl9560_qnj_b0_jf_b0_cfg, iwl9461_160_name), - _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_MAC_TYPE_QNJ, IWL_CFG_ANY, - IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1, IWL_CFG_ANY, - IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY, - iwl9560_qnj_b0_jf_b0_cfg, iwl9461_name), - _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_MAC_TYPE_QNJ, IWL_CFG_ANY, - IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV, IWL_CFG_ANY, - IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY, - iwl9560_qnj_b0_jf_b0_cfg, iwl9462_160_name), - _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_MAC_TYPE_QNJ, IWL_CFG_ANY, - IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV, IWL_CFG_ANY, - IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY, - iwl9560_qnj_b0_jf_b0_cfg, iwl9462_name), - - _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_MAC_TYPE_QNJ, IWL_CFG_ANY, - IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY, - IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY, - iwl9560_qnj_b0_jf_b0_cfg, iwl9560_160_name), - _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_MAC_TYPE_QNJ, IWL_CFG_ANY, - IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY, - IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY, - iwl9560_qnj_b0_jf_b0_cfg, iwl9560_name), - - _IWL_DEV_INFO(IWL_CFG_ANY, 0x1551, - IWL_CFG_MAC_TYPE_QNJ, IWL_CFG_ANY, - IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY, - IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY, - iwl9560_qnj_b0_jf_b0_cfg, iwl9560_killer_1550s_name), - _IWL_DEV_INFO(IWL_CFG_ANY, 0x1552, - IWL_CFG_MAC_TYPE_QNJ, IWL_CFG_ANY, - IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY, - IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY, - iwl9560_qnj_b0_jf_b0_cfg, iwl9560_killer_1550i_name), - /* Qu with Hr */ /* Qu B step */ _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_MAC_TYPE_QU, SILICON_B_STEP, IWL_CFG_RF_TYPE_HR1, IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY, + IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, iwl_qu_b0_hr1_b0, iwl_ax101_name), _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_MAC_TYPE_QU, SILICON_B_STEP, IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_NO_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY, + IWL_CFG_NO_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, iwl_qu_b0_hr_b0, iwl_ax203_name), /* Qu C step */ _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_MAC_TYPE_QU, SILICON_C_STEP, IWL_CFG_RF_TYPE_HR1, IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY, + IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, iwl_qu_c0_hr1_b0, iwl_ax101_name), _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_MAC_TYPE_QU, SILICON_C_STEP, IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_NO_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY, + IWL_CFG_NO_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, iwl_qu_c0_hr_b0, iwl_ax203_name), _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_MAC_TYPE_QU, SILICON_C_STEP, IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY, + IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, iwl_qu_c0_hr_b0, iwl_ax201_name), /* QuZ */ _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_MAC_TYPE_QUZ, IWL_CFG_ANY, IWL_CFG_RF_TYPE_HR1, IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY, + IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, iwl_quz_a0_hr1_b0, iwl_ax101_name), _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_MAC_TYPE_QUZ, SILICON_B_STEP, IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_NO_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY, + IWL_CFG_NO_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, iwl_cfg_quz_a0_hr_b0, iwl_ax203_name), _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_MAC_TYPE_QUZ, SILICON_B_STEP, IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY, + IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, iwl_cfg_quz_a0_hr_b0, iwl_ax201_name), -/* QnJ with Hr */ - _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_MAC_TYPE_QNJ, IWL_CFG_ANY, - IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY, - iwl_qnj_b0_hr_b0_cfg, iwl_ax201_name), - -/* SnJ with Jf */ - _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_MAC_TYPE_SNJ, IWL_CFG_ANY, - IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1, IWL_CFG_ANY, - IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY, - iwl_cfg_snj_a0_jf_b0, iwl9461_160_name), - _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_MAC_TYPE_SNJ, IWL_CFG_ANY, - IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1, IWL_CFG_ANY, - IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY, - iwl_cfg_snj_a0_jf_b0, iwl9461_name), - _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_MAC_TYPE_SNJ, IWL_CFG_ANY, - IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV, IWL_CFG_ANY, - IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY, - iwl_cfg_snj_a0_jf_b0, iwl9462_160_name), - _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_MAC_TYPE_SNJ, IWL_CFG_ANY, - IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV, IWL_CFG_ANY, - IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY, - iwl_cfg_snj_a0_jf_b0, iwl9462_name), - - _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_MAC_TYPE_SNJ, IWL_CFG_ANY, - IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY, - IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY, - iwl_cfg_snj_a0_jf_b0, iwl9560_160_name), - _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_MAC_TYPE_SNJ, IWL_CFG_ANY, - IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY, - IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY, - iwl_cfg_snj_a0_jf_b0, iwl9560_name), - -/* SnJ with Hr */ - _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_MAC_TYPE_SNJ, IWL_CFG_ANY, - IWL_CFG_RF_TYPE_HR1, IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY, - iwl_cfg_snj_hr_b0, iwl_ax101_name), - - _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_MAC_TYPE_SNJ, IWL_CFG_ANY, - IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY, - iwl_cfg_snj_hr_b0, iwl_ax201_name), - /* Ma */ _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_MAC_TYPE_MA, SILICON_A_STEP, - IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY, - iwl_cfg_ma_a0_hr_b0, iwl_ax201_name), - _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_MAC_TYPE_MA, SILICON_A_STEP, - IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY, - iwl_cfg_ma_a0_gf_a0, iwl_ax211_name), - _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_MAC_TYPE_MA, SILICON_A_STEP, - IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_CDB, IWL_CFG_ANY, - iwl_cfg_ma_a0_gf4_a0, iwl_ax211_name), - _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_MAC_TYPE_MA, SILICON_A_STEP, - IWL_CFG_RF_TYPE_MR, IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY, - iwl_cfg_ma_a0_mr_a0, iwl_ax221_name), - _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_MAC_TYPE_MA, SILICON_A_STEP, - IWL_CFG_RF_TYPE_FM, IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY, - iwl_cfg_ma_a0_fm_a0, iwl_ax231_name), - _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_MAC_TYPE_SNJ, IWL_CFG_ANY, - IWL_CFG_RF_TYPE_MR, IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY, - iwl_cfg_snj_a0_mr_a0, iwl_ax221_name), - _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_MAC_TYPE_MA, SILICON_B_STEP, + IWL_CFG_MAC_TYPE_MA, IWL_CFG_ANY, IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY, - iwl_cfg_ma_b0_hr_b0, iwl_ax201_name), - _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_MAC_TYPE_MA, SILICON_B_STEP, - IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY, - iwl_cfg_ma_b0_gf_a0, iwl_ax211_name), + IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, + iwl_cfg_ma, iwl_ax201_name), _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_MAC_TYPE_MA, SILICON_B_STEP, + IWL_CFG_MAC_TYPE_MA, IWL_CFG_ANY, IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_CDB, IWL_CFG_ANY, - iwl_cfg_ma_b0_gf4_a0, iwl_ax211_name), + IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY, + iwl_cfg_ma, iwl_ax211_name), _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_MAC_TYPE_MA, SILICON_B_STEP, + IWL_CFG_MAC_TYPE_MA, IWL_CFG_ANY, IWL_CFG_RF_TYPE_MR, IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY, - iwl_cfg_ma_b0_mr_a0, iwl_ax221_name), + IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, + iwl_cfg_ma, iwl_ax221_name), _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_MAC_TYPE_MA, SILICON_B_STEP, + IWL_CFG_MAC_TYPE_MA, IWL_CFG_ANY, IWL_CFG_RF_TYPE_FM, IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY, - iwl_cfg_ma_b0_fm_a0, iwl_ax231_name), + IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, + iwl_cfg_ma, iwl_ax231_name), /* So with Hr */ _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY, IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_NO_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY, + IWL_CFG_NO_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, iwl_cfg_so_a0_hr_a0, iwl_ax203_name), _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY, IWL_CFG_RF_TYPE_HR1, IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_NO_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY, + IWL_CFG_NO_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, iwl_cfg_so_a0_hr_a0, iwl_ax101_name), _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY, IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY, + IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, iwl_cfg_so_a0_hr_a0, iwl_ax201_name), /* So-F with Hr */ _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY, IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_NO_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY, + IWL_CFG_NO_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, iwl_cfg_so_a0_hr_a0, iwl_ax203_name), _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY, IWL_CFG_RF_TYPE_HR1, IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_NO_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY, + IWL_CFG_NO_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, iwl_cfg_so_a0_hr_a0, iwl_ax101_name), _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY, IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY, + IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, iwl_cfg_so_a0_hr_a0, iwl_ax201_name), /* So-F with Gf */ _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY, IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY, + IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, iwlax211_2ax_cfg_so_gf_a0, iwl_ax211_name), _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY, IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_CDB, IWL_CFG_ANY, + IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_CDB, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_name), /* Bz */ _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_MAC_TYPE_BZ, IWL_CFG_ANY, - IWL_CFG_RF_TYPE_HR1, IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY, - iwl_cfg_bz_a0_hr_a0, iwl_bz_name), - _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_MAC_TYPE_BZ, IWL_CFG_ANY, - IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY, - iwl_cfg_bz_a0_hr_b0, iwl_bz_name), - _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_MAC_TYPE_BZ, IWL_CFG_ANY, - IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY, - iwl_cfg_bz_a0_gf_a0, iwl_bz_name), - _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_MAC_TYPE_BZ, IWL_CFG_ANY, - IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_CDB, IWL_CFG_ANY, - iwl_cfg_bz_a0_gf4_a0, iwl_bz_name), - _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_MAC_TYPE_BZ, IWL_CFG_ANY, - IWL_CFG_RF_TYPE_MR, IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY, - iwl_cfg_bz_a0_mr_a0, iwl_bz_name), - _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_MAC_TYPE_BZ, SILICON_A_STEP, - IWL_CFG_RF_TYPE_FM, IWL_CFG_ANY, SILICON_A_STEP, - IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY, - iwl_cfg_bz_a0_fm_a0, iwl_bz_name), - _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_MAC_TYPE_BZ, IWL_CFG_ANY, - IWL_CFG_RF_TYPE_FM, IWL_CFG_ANY, SILICON_A_STEP, - IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_CDB, IWL_CFG_NO_JACKET, - iwl_cfg_bz_a0_fm4_a0, iwl_bz_name), - _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_MAC_TYPE_BZ, IWL_CFG_ANY, - IWL_CFG_RF_TYPE_FM, IWL_CFG_ANY, SILICON_B_STEP, - IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_IS_JACKET, - iwl_cfg_bz_a0_fm_b0, iwl_bz_name), - _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_MAC_TYPE_BZ, IWL_CFG_ANY, - IWL_CFG_RF_TYPE_FM, IWL_CFG_ANY, SILICON_B_STEP, - IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_CDB, IWL_CFG_IS_JACKET, - iwl_cfg_bz_a0_fm4_b0, iwl_bz_name), - _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_MAC_TYPE_GL, SILICON_A_STEP, - IWL_CFG_RF_TYPE_FM, IWL_CFG_ANY, SILICON_A_STEP, - IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_NO_JACKET, - iwl_cfg_gl_a0_fm_a0, iwl_bz_name), - _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_MAC_TYPE_GL, SILICON_B_STEP, - IWL_CFG_RF_TYPE_FM, IWL_CFG_ANY, SILICON_B_STEP, - IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_NO_JACKET, - iwl_cfg_gl_b0_fm_b0, iwl_bz_name), - -/* BZ Z step */ - _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_MAC_TYPE_BZ, SILICON_Z_STEP, - IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY, - iwl_cfg_bz_z0_gf_a0, iwl_bz_name), + IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY, + IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY, + iwl_cfg_bz, iwl_bz_name), -/* BNJ */ - _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_MAC_TYPE_GL, SILICON_A_STEP, - IWL_CFG_RF_TYPE_FM, IWL_CFG_ANY, SILICON_A_STEP, - IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_IS_JACKET, - iwl_cfg_bnj_a0_fm_a0, iwl_bz_name), - _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_MAC_TYPE_GL, SILICON_B_STEP, - IWL_CFG_RF_TYPE_FM, IWL_CFG_ANY, SILICON_B_STEP, - IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_IS_JACKET, - iwl_cfg_bnj_b0_fm_b0, iwl_bz_name), - _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_MAC_TYPE_GL, SILICON_A_STEP, - IWL_CFG_RF_TYPE_FM, IWL_CFG_ANY, SILICON_A_STEP, - IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_CDB, IWL_CFG_IS_JACKET, - iwl_cfg_bnj_a0_fm4_a0, iwl_bz_name), - _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_MAC_TYPE_GL, SILICON_B_STEP, - IWL_CFG_RF_TYPE_FM, IWL_CFG_ANY, SILICON_B_STEP, - IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_CDB, IWL_CFG_IS_JACKET, - iwl_cfg_bnj_b0_fm4_b0, iwl_bz_name), +/* Ga (Gl) */ _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_MAC_TYPE_GL, IWL_CFG_ANY, - IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_IS_JACKET, - iwl_cfg_bnj_a0_gf_a0, iwl_bz_name), - _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_MAC_TYPE_GL, SILICON_B_STEP, - IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_IS_JACKET, - iwl_cfg_bnj_b0_gf_a0, iwl_bz_name), - _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_MAC_TYPE_GL, SILICON_A_STEP, - IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_CDB, IWL_CFG_IS_JACKET, - iwl_cfg_bnj_a0_gf4_a0, iwl_bz_name), - _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_MAC_TYPE_GL, SILICON_B_STEP, - IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_CDB, IWL_CFG_IS_JACKET, - iwl_cfg_bnj_b0_gf4_a0, iwl_bz_name), - _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_MAC_TYPE_GL, SILICON_A_STEP, - IWL_CFG_RF_TYPE_HR1, IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY, - iwl_cfg_bnj_a0_hr_a0, iwl_bz_name), - _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_MAC_TYPE_GL, SILICON_A_STEP, - IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY, - iwl_cfg_bnj_a0_hr_b0, iwl_bz_name), - _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_MAC_TYPE_GL, SILICON_B_STEP, - IWL_CFG_RF_TYPE_HR1, IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY, - iwl_cfg_bnj_b0_hr_a0, iwl_bz_name), - _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_MAC_TYPE_GL, SILICON_B_STEP, - IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY, - iwl_cfg_bnj_b0_hr_b0, iwl_bz_name), + IWL_CFG_RF_TYPE_FM, IWL_CFG_ANY, IWL_CFG_ANY, + IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, + iwl_cfg_gl, iwl_bz_name), /* SoF with JF2 */ _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY, IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY, - IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY, + IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, iwlax210_2ax_cfg_so_jf_b0, iwl9560_160_name), _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY, IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY, - IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY, + IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, iwlax210_2ax_cfg_so_jf_b0, iwl9560_name), /* SoF with JF */ _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY, IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1, IWL_CFG_ANY, - IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY, + IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, iwlax210_2ax_cfg_so_jf_b0, iwl9461_160_name), _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY, IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV, IWL_CFG_ANY, - IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY, + IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, iwlax210_2ax_cfg_so_jf_b0, iwl9462_160_name), _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY, IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1, IWL_CFG_ANY, - IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY, + IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, iwlax210_2ax_cfg_so_jf_b0, iwl9461_name), _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY, IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV, IWL_CFG_ANY, - IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY, + IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, iwlax210_2ax_cfg_so_jf_b0, iwl9462_name), /* So with GF */ _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY, IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY, + IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, iwlax211_2ax_cfg_so_gf_a0, iwl_ax211_name), _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY, IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_CDB, IWL_CFG_ANY, + IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_CDB, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_name), /* So with JF2 */ _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY, IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY, - IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY, + IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, iwlax210_2ax_cfg_so_jf_b0, iwl9560_160_name), _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY, IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY, - IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY, + IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, iwlax210_2ax_cfg_so_jf_b0, iwl9560_name), /* So with JF */ _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY, IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1, IWL_CFG_ANY, - IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY, + IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, iwlax210_2ax_cfg_so_jf_b0, iwl9461_160_name), _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY, IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV, IWL_CFG_ANY, - IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY, + IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, iwlax210_2ax_cfg_so_jf_b0, iwl9462_160_name), _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY, IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1, IWL_CFG_ANY, - IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY, + IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, iwlax210_2ax_cfg_so_jf_b0, iwl9461_name), _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY, IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV, IWL_CFG_ANY, - IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY, + IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, iwlax210_2ax_cfg_so_jf_b0, iwl9462_name), /* MsP */ @@ -1370,24 +1096,25 @@ static const struct iwl_dev_info iwl_dev_info_table[] = { _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY, IWL_CFG_RF_TYPE_MS, IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY, + IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, iwl_cfg_so_a0_ms_a0, iwl_ax204_name), _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY, IWL_CFG_RF_TYPE_MS, IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY, + IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, iwl_cfg_so_a0_ms_a0, iwl_ax204_name), _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_MAC_TYPE_MA, IWL_CFG_ANY, IWL_CFG_RF_TYPE_MS, IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY, - iwl_cfg_ma_a0_ms_a0, iwl_ax204_name), - _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_MAC_TYPE_SNJ, IWL_CFG_ANY, - IWL_CFG_RF_TYPE_MS, IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY, - iwl_cfg_snj_a0_ms_a0, iwl_ax204_name) + IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, + iwl_cfg_ma, iwl_ax204_name), +/* Sc */ + _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, + IWL_CFG_MAC_TYPE_SC, IWL_CFG_ANY, + IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY, + IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY, + iwl_cfg_sc, iwl_sc_name), #endif /* CONFIG_IWLMVM */ }; @@ -1667,17 +1394,6 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) } #if IS_ENABLED(CONFIG_IWLMVM) - - /* - * Workaround for problematic SnJ device: sometimes when - * certain RF modules are connected to SnJ, the device ID - * changes to QnJ's ID. So we are using QnJ's trans_cfg until - * here. But if we detect that the MAC type is actually SnJ, - * we should switch to it here to avoid problems later. - */ - if (CSR_HW_REV_TYPE(iwl_trans->hw_rev) == IWL_CFG_MAC_TYPE_SNJ) - iwl_trans->trans_cfg = &iwl_so_trans_cfg; - /* * special-case 7265D, it has the same PCI IDs. * @@ -1750,6 +1466,15 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) trans_pcie->num_rx_bufs = RX_QUEUE_SIZE; } + if (!iwl_trans->trans_cfg->integrated) { + u16 link_status; + + pcie_capability_read_word(pdev, PCI_EXP_LNKSTA, &link_status); + + iwl_trans->pcie_link_speed = + u16_get_bits(link_status, PCI_EXP_LNKSTA_CLS); + } + ret = iwl_trans_init(iwl_trans); if (ret) goto out_free_trans; diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h index 69b95ad5993b0acad217a4ab752825766c3a0add..0adcf0e13e85aa44e999bb2d33dc363b4a9307a5 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h +++ b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h @@ -23,6 +23,7 @@ #include "iwl-op-mode.h" #include "iwl-drv.h" #include "queue/tx.h" +#include "iwl-context-info.h" /* * RX related structures and functions @@ -306,7 +307,9 @@ enum iwl_pcie_imr_status { * @trans: pointer to the generic transport area * @scd_base_addr: scheduler sram base address in SRAM * @kw: keep warm address - * @pnvm_dram: DRAM area that contains the PNVM data + * @pnvm_data: holds info about pnvm payloads allocated in DRAM + * @reduced_tables_data: holds info about power reduced tablse + * payloads allocated in DRAM * @pci_dev: basic pci-network driver stuff * @hw_base: pci hardware address support * @ucode_write_complete: indicates that the ucode has been copied. @@ -380,8 +383,9 @@ struct iwl_trans_pcie { u32 scd_base_addr; struct iwl_dma_ptr kw; - struct iwl_dram_data pnvm_dram; - struct iwl_dram_data reduce_power_dram; + /* pnvm data */ + struct iwl_dram_regions pnvm_data; + struct iwl_dram_regions reduced_tables_data; struct iwl_txq *txq_memory; @@ -478,6 +482,8 @@ struct iwl_trans const struct pci_device_id *ent, const struct iwl_cfg_trans_params *cfg_trans); void iwl_trans_pcie_free(struct iwl_trans *trans); +void iwl_trans_pcie_free_pnvm_dram_regions(struct iwl_dram_regions *dram_regions, + struct device *dev); bool __iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans); #define _iwl_trans_pcie_grab_nic_access(trans) \ diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c index 0d7890f99a5fbc3232a4d7b525845a4a0e56888e..f87b28edc267da509b4d53494aeab01f1df206b9 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c @@ -699,17 +699,25 @@ static void iwl_pcie_free_rxq_dma(struct iwl_trans *trans, rxq->used_bd = NULL; } +static size_t iwl_pcie_rb_stts_size(struct iwl_trans *trans) +{ + bool use_rx_td = (trans->trans_cfg->device_family >= + IWL_DEVICE_FAMILY_AX210); + + if (use_rx_td) + return sizeof(__le16); + + return sizeof(struct iwl_rb_status); +} + static int iwl_pcie_alloc_rxq_dma(struct iwl_trans *trans, struct iwl_rxq *rxq) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); + size_t rb_stts_size = iwl_pcie_rb_stts_size(trans); struct device *dev = trans->dev; int i; int free_size; - bool use_rx_td = (trans->trans_cfg->device_family >= - IWL_DEVICE_FAMILY_AX210); - size_t rb_stts_size = use_rx_td ? sizeof(__le16) : - sizeof(struct iwl_rb_status); spin_lock_init(&rxq->lock); if (trans->trans_cfg->mq_rx_supported) @@ -757,11 +765,9 @@ static int iwl_pcie_alloc_rxq_dma(struct iwl_trans *trans, static int iwl_pcie_rx_alloc(struct iwl_trans *trans) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); + size_t rb_stts_size = iwl_pcie_rb_stts_size(trans); struct iwl_rb_allocator *rba = &trans_pcie->rba; int i, ret; - size_t rb_stts_size = trans->trans_cfg->device_family >= - IWL_DEVICE_FAMILY_AX210 ? - sizeof(__le16) : sizeof(struct iwl_rb_status); if (WARN_ON(trans_pcie->rxq)) return -EINVAL; @@ -1193,11 +1199,9 @@ int iwl_pcie_gen2_rx_init(struct iwl_trans *trans) void iwl_pcie_rx_free(struct iwl_trans *trans) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); + size_t rb_stts_size = iwl_pcie_rb_stts_size(trans); struct iwl_rb_allocator *rba = &trans_pcie->rba; int i; - size_t rb_stts_size = trans->trans_cfg->device_family >= - IWL_DEVICE_FAMILY_AX210 ? - sizeof(__le16) : sizeof(struct iwl_rb_status); /* * if rxq is NULL, it means that nothing has been allocated, @@ -1636,14 +1640,14 @@ irqreturn_t iwl_pcie_irq_rx_msix_handler(int irq, void *dev_id) struct msix_entry *entry = dev_id; struct iwl_trans_pcie *trans_pcie = iwl_pcie_get_trans_pcie(entry); struct iwl_trans *trans = trans_pcie->trans; - struct iwl_rxq *rxq = &trans_pcie->rxq[entry->entry]; + struct iwl_rxq *rxq; trace_iwlwifi_dev_irq_msix(trans->dev, entry, false, 0, 0); if (WARN_ON(entry->entry >= trans->num_rx_queues)) return IRQ_NONE; - if (!rxq) { + if (!trans_pcie->rxq) { if (net_ratelimit()) IWL_ERR(trans, "[%d] Got MSI-X interrupt before we have Rx queues\n", @@ -1651,6 +1655,7 @@ irqreturn_t iwl_pcie_irq_rx_msix_handler(int irq, void *dev_id) return IRQ_NONE; } + rxq = &trans_pcie->rxq[entry->entry]; lock_map_acquire(&trans->sync_cmd_lockdep_map); IWL_DEBUG_ISR(trans, "[%d] Got interrupt\n", entry->entry); @@ -1873,7 +1878,7 @@ irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id) return IRQ_NONE; } - if (unlikely(inta == 0xFFFFFFFF || (inta & 0xFFFFFFF0) == 0xa5a5a5a0)) { + if (unlikely(inta == 0xFFFFFFFF || iwl_trans_is_hw_error_value(inta))) { /* * Hardware disappeared. It might have * already raised an interrupt. diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c index 73b395841ca8a546f3c98e3f26d07e7a6c390ea4..fa46dad5fd6802189f120150c87ea8027567cdff 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* * Copyright (C) 2017 Intel Deutschland GmbH - * Copyright (C) 2018-2022 Intel Corporation + * Copyright (C) 2018-2023 Intel Corporation */ #include "iwl-trans.h" #include "iwl-prph.h" @@ -117,9 +117,14 @@ static void iwl_trans_pcie_fw_reset_handshake(struct iwl_trans *trans) trans_pcie->fw_reset_state != FW_RESET_REQUESTED, FW_RESET_TIMEOUT); if (!ret || trans_pcie->fw_reset_state == FW_RESET_ERROR) { - IWL_INFO(trans, - "firmware didn't ACK the reset - continue anyway\n"); - iwl_trans_fw_error(trans, true); + u32 inta_hw = iwl_read32(trans, CSR_MSIX_HW_INT_CAUSES_AD); + + IWL_ERR(trans, + "timeout waiting for FW reset ACK (inta_hw=0x%x)\n", + inta_hw); + + if (!(inta_hw & MSIX_HW_INT_CAUSES_REG_RESET_DONE)) + iwl_trans_fw_error(trans, true); } trans_pcie->fw_reset_state = FW_RESET_IDLE; diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index b281850fbf7a99f49db21a9b6bfcf6e9f66b427e..3e988da4497387b61ff0743ab064eba153f2057d 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* - * Copyright (C) 2007-2015, 2018-2022 Intel Corporation + * Copyright (C) 2007-2015, 2018-2023 Intel Corporation * Copyright (C) 2013-2015 Intel Mobile Communications GmbH * Copyright (C) 2016-2017 Intel Deutschland GmbH */ @@ -131,13 +131,15 @@ static int iwl_trans_pcie_sw_reset(struct iwl_trans *trans, bool retake_ownership) { /* Reset entire device - do controller reset (results in SHRD_HW_RST) */ - if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) + if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) { iwl_set_bit(trans, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_SW_RESET); - else + usleep_range(10000, 20000); + } else { iwl_set_bit(trans, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET); - usleep_range(5000, 6000); + usleep_range(5000, 6000); + } if (retake_ownership) return iwl_pcie_prepare_card_hw(trans); @@ -161,7 +163,7 @@ static void iwl_pcie_free_fw_monitor(struct iwl_trans *trans) } static void iwl_pcie_alloc_fw_monitor_block(struct iwl_trans *trans, - u8 max_power, u8 min_power) + u8 max_power) { struct iwl_dram_data *fw_mon = &trans->dbg.fw_mon; void *block = NULL; @@ -169,10 +171,13 @@ static void iwl_pcie_alloc_fw_monitor_block(struct iwl_trans *trans, u32 size = 0; u8 power; - if (fw_mon->size) + if (fw_mon->size) { + memset(fw_mon->block, 0, fw_mon->size); return; + } - for (power = max_power; power >= min_power; power--) { + /* need at least 2 KiB, so stop at 11 */ + for (power = max_power; power >= 11; power--) { size = BIT(power); block = dma_alloc_coherent(trans->dev, size, &physical, GFP_KERNEL | __GFP_NOWARN); @@ -213,10 +218,7 @@ void iwl_pcie_alloc_fw_monitor(struct iwl_trans *trans, u8 max_power) max_power)) return; - if (trans->dbg.fw_mon.size) - return; - - iwl_pcie_alloc_fw_monitor_block(trans, max_power, 11); + iwl_pcie_alloc_fw_monitor_block(trans, max_power); } static u32 iwl_trans_pcie_read_shr(struct iwl_trans *trans, u32 reg) @@ -475,7 +477,7 @@ void iwl_pcie_apm_stop_master(struct iwl_trans *trans) CSR_GP_CNTRL_REG_FLAG_BUS_MASTER_DISABLE_STATUS, CSR_GP_CNTRL_REG_FLAG_BUS_MASTER_DISABLE_STATUS, 100); - msleep(100); + usleep_range(10000, 20000); } else { iwl_set_bit(trans, CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER); @@ -817,7 +819,7 @@ static int iwl_pcie_load_cpu_sections_8000(struct iwl_trans *trans, iwl_enable_interrupts(trans); - if (trans->trans_cfg->use_tfh) { + if (trans->trans_cfg->gen2) { if (cpu == 1) iwl_write_prph(trans, UREG_UCODE_LOAD_STATUS, 0xFFFF); @@ -1786,7 +1788,7 @@ static int iwl_trans_pcie_clear_persistence_bit(struct iwl_trans *trans) } hpm = iwl_read_umac_prph_no_grab(trans, HPM_DEBUG); - if (hpm != 0xa5a5a5a0 && (hpm & PERSISTENCE_BIT)) { + if (!iwl_trans_is_hw_error_value(hpm) && (hpm & PERSISTENCE_BIT)) { u32 wprot_val = iwl_read_umac_prph_no_grab(trans, wprot); if (wprot_val & PREG_WFPM_ACCESS) { @@ -1993,6 +1995,29 @@ static void iwl_trans_pcie_configure(struct iwl_trans *trans, trans_pcie->fw_reset_handshake = trans_cfg->fw_reset_handshake; } +void iwl_trans_pcie_free_pnvm_dram_regions(struct iwl_dram_regions *dram_regions, + struct device *dev) +{ + u8 i; + struct iwl_dram_data *desc_dram = &dram_regions->prph_scratch_mem_desc; + + /* free DRAM payloads */ + for (i = 0; i < dram_regions->n_regions; i++) { + dma_free_coherent(dev, dram_regions->drams[i].size, + dram_regions->drams[i].block, + dram_regions->drams[i].physical); + } + dram_regions->n_regions = 0; + + /* free DRAM addresses array */ + if (desc_dram->block) { + dma_free_coherent(dev, desc_dram->size, + desc_dram->block, + desc_dram->physical); + } + memset(desc_dram, 0, sizeof(*desc_dram)); +} + void iwl_trans_pcie_free(struct iwl_trans *trans) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); @@ -2025,16 +2050,10 @@ void iwl_trans_pcie_free(struct iwl_trans *trans) iwl_pcie_free_fw_monitor(trans); - if (trans_pcie->pnvm_dram.size) - dma_free_coherent(trans->dev, trans_pcie->pnvm_dram.size, - trans_pcie->pnvm_dram.block, - trans_pcie->pnvm_dram.physical); - - if (trans_pcie->reduce_power_dram.size) - dma_free_coherent(trans->dev, - trans_pcie->reduce_power_dram.size, - trans_pcie->reduce_power_dram.block, - trans_pcie->reduce_power_dram.physical); + iwl_trans_pcie_free_pnvm_dram_regions(&trans_pcie->pnvm_data, + trans->dev); + iwl_trans_pcie_free_pnvm_dram_regions(&trans_pcie->reduced_tables_data, + trans->dev); mutex_destroy(&trans_pcie->mutex); iwl_trans_free(trans); @@ -3375,7 +3394,7 @@ iwl_trans_pcie_dump_data(struct iwl_trans *trans, u8 tfdidx; u32 caplen, cmdlen; - if (trans->trans_cfg->use_tfh) + if (trans->trans_cfg->gen2) tfdidx = idx; else tfdidx = ptr; @@ -3534,7 +3553,9 @@ static const struct iwl_trans_ops trans_ops_pcie_gen2 = { .txq_free = iwl_txq_dyn_free, .wait_txq_empty = iwl_trans_pcie_wait_txq_empty, .rxq_dma_data = iwl_trans_pcie_rxq_dma_data, + .load_pnvm = iwl_trans_pcie_ctx_info_gen3_load_pnvm, .set_pnvm = iwl_trans_pcie_ctx_info_gen3_set_pnvm, + .load_reduce_power = iwl_trans_pcie_ctx_info_gen3_load_reduce_power, .set_reduce_power = iwl_trans_pcie_ctx_info_gen3_set_reduce_power, #ifdef CONFIG_IWLWIFI_DEBUGFS .debugfs_cleanup = iwl_trans_pcie_debugfs_cleanup, @@ -3576,7 +3597,7 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, init_waitqueue_head(&trans_pcie->imr_waitq); trans_pcie->rba.alloc_wq = alloc_workqueue("rb_allocator", - WQ_HIGHPRI | WQ_UNBOUND, 1); + WQ_HIGHPRI | WQ_UNBOUND, 0); if (!trans_pcie->rba.alloc_wq) { ret = -ENOMEM; goto out_free_trans; diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c index 3546c5269c3b6339319d6390c85cdd0a2c9d6044..790e5b124740e4133b6fe088acac13511e53fb3a 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* - * Copyright (C) 2003-2014, 2018-2021 Intel Corporation + * Copyright (C) 2003-2014, 2018-2021, 2023 Intel Corporation * Copyright (C) 2013-2015 Intel Mobile Communications GmbH * Copyright (C) 2016-2017 Intel Deutschland GmbH */ @@ -364,7 +364,7 @@ void iwl_trans_pcie_tx_reset(struct iwl_trans *trans) for (txq_id = 0; txq_id < trans->trans_cfg->base_params->num_of_queues; txq_id++) { struct iwl_txq *txq = trans->txqs.txq[txq_id]; - if (trans->trans_cfg->use_tfh) + if (trans->trans_cfg->gen2) iwl_write_direct64(trans, FH_MEM_CBBC_QUEUE(trans, txq_id), txq->dma_addr); @@ -1547,6 +1547,9 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, /* there must be data left over for TB1 or this code must be changed */ BUILD_BUG_ON(sizeof(struct iwl_tx_cmd) < IWL_FIRST_TB_SIZE); + BUILD_BUG_ON(sizeof(struct iwl_cmd_header) + + offsetofend(struct iwl_tx_cmd, scratch) > + IWL_FIRST_TB_SIZE); /* map the data for TB1 */ tb1_addr = ((u8 *)&dev_cmd->hdr) + IWL_FIRST_TB_SIZE; diff --git a/drivers/net/wireless/intel/iwlwifi/queue/tx.c b/drivers/net/wireless/intel/iwlwifi/queue/tx.c index d1c39c214f95ae5980a66b3bab1ca70710380701..5bb3cc3367c9fe86fa269715614289858e9191b1 100644 --- a/drivers/net/wireless/intel/iwlwifi/queue/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/queue/tx.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* - * Copyright (C) 2020-2022 Intel Corporation + * Copyright (C) 2020-2023 Intel Corporation */ #include #include @@ -648,6 +648,13 @@ struct iwl_tfh_tfd *iwl_txq_gen2_build_tfd(struct iwl_trans *trans, /* There must be data left over for TB1 or this code must be changed */ BUILD_BUG_ON(sizeof(struct iwl_tx_cmd_gen2) < IWL_FIRST_TB_SIZE); + BUILD_BUG_ON(sizeof(struct iwl_cmd_header) + + offsetofend(struct iwl_tx_cmd_gen2, dram_info) > + IWL_FIRST_TB_SIZE); + BUILD_BUG_ON(sizeof(struct iwl_tx_cmd_gen3) < IWL_FIRST_TB_SIZE); + BUILD_BUG_ON(sizeof(struct iwl_cmd_header) + + offsetofend(struct iwl_tx_cmd_gen3, dram_info) > + IWL_FIRST_TB_SIZE); memset(tfd, 0, sizeof(*tfd)); @@ -978,7 +985,7 @@ void iwl_txq_log_scd_error(struct iwl_trans *trans, struct iwl_txq *txq) bool active; u8 fifo; - if (trans->trans_cfg->use_tfh) { + if (trans->trans_cfg->gen2) { IWL_ERR(trans, "Queue %d is stuck %d %d\n", txq_id, txq->read_ptr, txq->write_ptr); /* TODO: access new SCD registers and dump them */ @@ -1027,10 +1034,13 @@ int iwl_txq_alloc(struct iwl_trans *trans, struct iwl_txq *txq, int slots_num, size_t tb0_buf_sz; int i; + if (WARN_ONCE(slots_num <= 0, "Invalid slots num:%d\n", slots_num)) + return -EINVAL; + if (WARN_ON(txq->entries || txq->tfds)) return -EINVAL; - if (trans->trans_cfg->use_tfh) + if (trans->trans_cfg->gen2) tfd_sz = trans->txqs.tfd.size * slots_num; timer_setup(&txq->stuck_timer, iwl_txq_stuck_timer, 0); @@ -1337,7 +1347,7 @@ static inline dma_addr_t iwl_txq_gen1_tfd_tb_get_addr(struct iwl_trans *trans, dma_addr_t addr; dma_addr_t hi_len; - if (trans->trans_cfg->use_tfh) { + if (trans->trans_cfg->gen2) { struct iwl_tfh_tfd *tfh_tfd = _tfd; struct iwl_tfh_tb *tfh_tb = &tfh_tfd->tbs[idx]; @@ -1398,7 +1408,7 @@ void iwl_txq_gen1_tfd_unmap(struct iwl_trans *trans, meta->tbs = 0; - if (trans->trans_cfg->use_tfh) { + if (trans->trans_cfg->gen2) { struct iwl_tfh_tfd *tfd_fh = (void *)tfd; tfd_fh->num_tbs = 0; @@ -1615,7 +1625,7 @@ void iwl_txq_reclaim(struct iwl_trans *trans, int txq_id, int ssn, txq->entries[read_ptr].skb = NULL; - if (!trans->trans_cfg->use_tfh) + if (!trans->trans_cfg->gen2) iwl_txq_gen1_inval_byte_cnt_tbl(trans, txq); iwl_txq_free_tfd(trans, txq); diff --git a/drivers/net/wireless/intel/iwlwifi/queue/tx.h b/drivers/net/wireless/intel/iwlwifi/queue/tx.h index eca53bfd326d1a63ddbbf2a2dd8988f49298d067..1e4a24ab9bab223be86fb01233d5fc26badea314 100644 --- a/drivers/net/wireless/intel/iwlwifi/queue/tx.h +++ b/drivers/net/wireless/intel/iwlwifi/queue/tx.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ /* - * Copyright (C) 2020-2022 Intel Corporation + * Copyright (C) 2020-2023 Intel Corporation */ #ifndef __iwl_trans_queue_tx_h__ #define __iwl_trans_queue_tx_h__ @@ -38,7 +38,7 @@ static inline void iwl_wake_queue(struct iwl_trans *trans, static inline void *iwl_txq_get_tfd(struct iwl_trans *trans, struct iwl_txq *txq, int idx) { - if (trans->trans_cfg->use_tfh) + if (trans->trans_cfg->gen2) idx = iwl_txq_get_cmd_index(txq, idx); return (u8 *)txq->tfds + trans->txqs.tfd.size * idx; @@ -135,7 +135,7 @@ static inline u8 iwl_txq_gen1_tfd_get_num_tbs(struct iwl_trans *trans, { struct iwl_tfd *tfd; - if (trans->trans_cfg->use_tfh) { + if (trans->trans_cfg->gen2) { struct iwl_tfh_tfd *tfh_tfd = _tfd; return le16_to_cpu(tfh_tfd->num_tbs) & 0x1f; @@ -151,7 +151,7 @@ static inline u16 iwl_txq_gen1_tfd_tb_get_len(struct iwl_trans *trans, struct iwl_tfd *tfd; struct iwl_tfd_tb *tb; - if (trans->trans_cfg->use_tfh) { + if (trans->trans_cfg->gen2) { struct iwl_tfh_tfd *tfh_tfd = _tfd; struct iwl_tfh_tb *tfh_tb = &tfh_tfd->tbs[idx]; diff --git a/drivers/net/wireless/intersil/hostap/Kconfig b/drivers/net/wireless/intersil/hostap/Kconfig index c865d3156ceaa2da7305bb327791efa2d6f7d6a4..2edff8efbcbb1161473bd2744dc9cb77ef65e1fd 100644 --- a/drivers/net/wireless/intersil/hostap/Kconfig +++ b/drivers/net/wireless/intersil/hostap/Kconfig @@ -56,7 +56,7 @@ config HOSTAP_FIRMWARE_NVRAM config HOSTAP_PLX tristate "Host AP driver for Prism2/2.5/3 in PLX9052 PCI adaptors" - depends on PCI && HOSTAP + depends on PCI && HOSTAP && HAS_IOPORT help Host AP driver's version for Prism2/2.5/3 PC Cards in PLX9052 based PCI adaptors. diff --git a/drivers/net/wireless/intersil/hostap/hostap_ioctl.c b/drivers/net/wireless/intersil/hostap/hostap_ioctl.c index 26287b129d186560e1964ade74a1c8b3aeb6d588..b4adfc190ae877fc54cd89bb6fb26a13fca0768b 100644 --- a/drivers/net/wireless/intersil/hostap/hostap_ioctl.c +++ b/drivers/net/wireless/intersil/hostap/hostap_ioctl.c @@ -3630,7 +3630,7 @@ static int prism2_ioctl_get_encryption(local_info_t *local, param->u.crypt.key_len = 0; param->u.crypt.idx = 0xff; } else { - strncpy(param->u.crypt.alg, (*crypt)->ops->name, + strscpy(param->u.crypt.alg, (*crypt)->ops->name, HOSTAP_CRYPT_ALG_NAME_LEN); param->u.crypt.key_len = 0; diff --git a/drivers/net/wireless/intersil/orinoco/orinoco_cs.c b/drivers/net/wireless/intersil/orinoco/orinoco_cs.c index a956f965a1e5ec77e19c03e86ec87dc810461315..03bfd2482656c09143249928c3bf74a7edca5a1e 100644 --- a/drivers/net/wireless/intersil/orinoco/orinoco_cs.c +++ b/drivers/net/wireless/intersil/orinoco/orinoco_cs.c @@ -96,6 +96,7 @@ orinoco_cs_probe(struct pcmcia_device *link) { struct orinoco_private *priv; struct orinoco_pccard *card; + int ret; priv = alloc_orinocodev(sizeof(*card), &link->dev, orinoco_cs_hard_reset, NULL); @@ -107,8 +108,16 @@ orinoco_cs_probe(struct pcmcia_device *link) card->p_dev = link; link->priv = priv; - return orinoco_cs_config(link); -} /* orinoco_cs_attach */ + ret = orinoco_cs_config(link); + if (ret) + goto err_free_orinocodev; + + return 0; + +err_free_orinocodev: + free_orinocodev(priv); + return ret; +} static void orinoco_cs_detach(struct pcmcia_device *link) { diff --git a/drivers/net/wireless/intersil/orinoco/spectrum_cs.c b/drivers/net/wireless/intersil/orinoco/spectrum_cs.c index 291ef97ed45ec44f2b6c03c14e1ce6d16e01d824..841d623c621ac7e147037c26e3d11fa24f2f415a 100644 --- a/drivers/net/wireless/intersil/orinoco/spectrum_cs.c +++ b/drivers/net/wireless/intersil/orinoco/spectrum_cs.c @@ -157,6 +157,7 @@ spectrum_cs_probe(struct pcmcia_device *link) { struct orinoco_private *priv; struct orinoco_pccard *card; + int ret; priv = alloc_orinocodev(sizeof(*card), &link->dev, spectrum_cs_hard_reset, @@ -169,8 +170,16 @@ spectrum_cs_probe(struct pcmcia_device *link) card->p_dev = link; link->priv = priv; - return spectrum_cs_config(link); -} /* spectrum_cs_attach */ + ret = spectrum_cs_config(link); + if (ret) + goto err_free_orinocodev; + + return 0; + +err_free_orinocodev: + free_orinocodev(priv); + return ret; +} static void spectrum_cs_detach(struct pcmcia_device *link) { diff --git a/drivers/net/wireless/intersil/p54/p54spi.c b/drivers/net/wireless/intersil/p54/p54spi.c index 19152fd449ba7dca19706ef939370e28ac1f949d..ce0179b8ab368fa7138a394afbc32678b05d20fc 100644 --- a/drivers/net/wireless/intersil/p54/p54spi.c +++ b/drivers/net/wireless/intersil/p54/p54spi.c @@ -28,6 +28,7 @@ #endif /* CONFIG_P54_SPI_DEFAULT_EEPROM */ MODULE_FIRMWARE("3826.arm"); +MODULE_FIRMWARE("3826.eeprom"); /* gpios should be handled in board files and provided via platform data, * but because it's currently impossible for p54spi to have a header file diff --git a/drivers/net/wireless/legacy/ray_cs.c b/drivers/net/wireless/legacy/ray_cs.c index 1f57a0055bbd80ca73f60a330cc6d43594ce1e63..8ace797ce951c501621015f0b93a426c0e1dc2f1 100644 --- a/drivers/net/wireless/legacy/ray_cs.c +++ b/drivers/net/wireless/legacy/ray_cs.c @@ -270,13 +270,14 @@ static int ray_probe(struct pcmcia_device *p_dev) { ray_dev_t *local; struct net_device *dev; + int ret; dev_dbg(&p_dev->dev, "ray_attach()\n"); /* Allocate space for private device-specific data */ dev = alloc_etherdev(sizeof(ray_dev_t)); if (!dev) - goto fail_alloc_dev; + return -ENOMEM; local = netdev_priv(dev); local->finder = p_dev; @@ -313,16 +314,20 @@ static int ray_probe(struct pcmcia_device *p_dev) timer_setup(&local->timer, NULL, 0); this_device = p_dev; - return ray_config(p_dev); + ret = ray_config(p_dev); + if (ret) + goto err_free_dev; -fail_alloc_dev: - return -ENOMEM; -} /* ray_attach */ + return 0; + +err_free_dev: + free_netdev(dev); + return ret; +} static void ray_detach(struct pcmcia_device *link) { struct net_device *dev; - ray_dev_t *local; dev_dbg(&link->dev, "ray_detach\n"); @@ -331,9 +336,6 @@ static void ray_detach(struct pcmcia_device *link) ray_release(link); - local = netdev_priv(dev); - del_timer_sync(&local->timer); - if (link->priv) { unregister_netdev(dev); free_netdev(dev); @@ -625,7 +627,7 @@ static void init_startup_params(ray_dev_t *local) local->sparm.b4.a_acting_as_ap_status = TYPE_STA; if (essid != NULL) - strncpy(local->sparm.b4.a_current_ess_id, essid, ESSID_SIZE); + strscpy(local->sparm.b4.a_current_ess_id, essid, ESSID_SIZE); } /* init_startup_params */ /*===========================================================================*/ @@ -734,11 +736,14 @@ static void ray_release(struct pcmcia_device *link) dev_dbg(&link->dev, "ray_release\n"); - del_timer(&local->timer); + del_timer_sync(&local->timer); - iounmap(local->sram); - iounmap(local->rmem); - iounmap(local->amem); + if (local->sram) + iounmap(local->sram); + if (local->rmem) + iounmap(local->rmem); + if (local->amem) + iounmap(local->amem); pcmcia_disable_device(link); dev_dbg(&link->dev, "ray_release ending\n"); diff --git a/drivers/net/wireless/legacy/wl3501_cs.c b/drivers/net/wireless/legacy/wl3501_cs.c index 7fb2f95134760094ae9e61c8e6f54f98e66c6442..c45c4b7cbbaf1898ef8fd038553e919451159fa5 100644 --- a/drivers/net/wireless/legacy/wl3501_cs.c +++ b/drivers/net/wireless/legacy/wl3501_cs.c @@ -1862,6 +1862,7 @@ static int wl3501_probe(struct pcmcia_device *p_dev) { struct net_device *dev; struct wl3501_card *this; + int ret; /* The io structure describes IO port mapping */ p_dev->resource[0]->end = 16; @@ -1873,8 +1874,7 @@ static int wl3501_probe(struct pcmcia_device *p_dev) dev = alloc_etherdev(sizeof(struct wl3501_card)); if (!dev) - goto out_link; - + return -ENOMEM; dev->netdev_ops = &wl3501_netdev_ops; dev->watchdog_timeo = 5 * HZ; @@ -1887,9 +1887,15 @@ static int wl3501_probe(struct pcmcia_device *p_dev) netif_stop_queue(dev); p_dev->priv = dev; - return wl3501_config(p_dev); -out_link: - return -ENOMEM; + ret = wl3501_config(p_dev); + if (ret) + goto out_free_etherdev; + + return 0; + +out_free_etherdev: + free_netdev(dev); + return ret; } static int wl3501_config(struct pcmcia_device *link) diff --git a/drivers/net/wireless/marvell/mwifiex/11n.h b/drivers/net/wireless/marvell/mwifiex/11n.h index 94b5e3e4ba0843615a8cc572cdbb9e6895eaa8d2..7738ebe1fec1728cd17996752ec1658c6812972c 100644 --- a/drivers/net/wireless/marvell/mwifiex/11n.h +++ b/drivers/net/wireless/marvell/mwifiex/11n.h @@ -102,14 +102,14 @@ static inline u8 mwifiex_space_avail_for_new_ba_stream( { struct mwifiex_private *priv; u8 i; - u32 ba_stream_num = 0, ba_stream_max; + size_t ba_stream_num = 0, ba_stream_max; ba_stream_max = MWIFIEX_MAX_TX_BASTREAM_SUPPORTED; for (i = 0; i < adapter->priv_num; i++) { priv = adapter->priv[i]; if (priv) - ba_stream_num += mwifiex_wmm_list_len( + ba_stream_num += list_count_nodes( &priv->tx_ba_stream_tbl_ptr); } diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.c b/drivers/net/wireless/marvell/mwifiex/cfg80211.c index bcd564dc3554a80c8a37ab18abd31d24c0cbdbe0..813d1cbebe19beab3f59cb02820b275373705de7 100644 --- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c +++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c @@ -3127,7 +3127,7 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy, priv->dfs_cac_workqueue = alloc_workqueue("MWIFIEX_DFS_CAC%s", WQ_HIGHPRI | WQ_MEM_RECLAIM | - WQ_UNBOUND, 1, name); + WQ_UNBOUND, 0, name); if (!priv->dfs_cac_workqueue) { mwifiex_dbg(adapter, ERROR, "cannot alloc DFS CAC queue\n"); ret = -ENOMEM; @@ -3138,7 +3138,7 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy, priv->dfs_chan_sw_workqueue = alloc_workqueue("MWIFIEX_DFS_CHSW%s", WQ_HIGHPRI | WQ_UNBOUND | - WQ_MEM_RECLAIM, 1, name); + WQ_MEM_RECLAIM, 0, name); if (!priv->dfs_chan_sw_workqueue) { mwifiex_dbg(adapter, ERROR, "cannot alloc DFS channel sw queue\n"); ret = -ENOMEM; @@ -3753,10 +3753,10 @@ static int mwifiex_cfg80211_set_coalesce(struct wiphy *wiphy, */ static int mwifiex_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev, - const u8 *peer, u8 action_code, u8 dialog_token, - u16 status_code, u32 peer_capability, - bool initiator, const u8 *extra_ies, - size_t extra_ies_len) + const u8 *peer, int link_id, u8 action_code, + u8 dialog_token, u16 status_code, + u32 peer_capability, bool initiator, + const u8 *extra_ies, size_t extra_ies_len) { struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); int ret; diff --git a/drivers/net/wireless/marvell/mwifiex/main.c b/drivers/net/wireless/marvell/mwifiex/main.c index ea22a08e6c083ed7adfdb1d95fb3d2319c13b596..1cd9d20cca16eee2a0b1a3e325e83f3e0fe6f128 100644 --- a/drivers/net/wireless/marvell/mwifiex/main.c +++ b/drivers/net/wireless/marvell/mwifiex/main.c @@ -1547,7 +1547,7 @@ mwifiex_reinit_sw(struct mwifiex_adapter *adapter) adapter->workqueue = alloc_workqueue("MWIFIEX_WORK_QUEUE", - WQ_HIGHPRI | WQ_MEM_RECLAIM | WQ_UNBOUND, 1); + WQ_HIGHPRI | WQ_MEM_RECLAIM | WQ_UNBOUND, 0); if (!adapter->workqueue) goto err_kmalloc; @@ -1557,7 +1557,7 @@ mwifiex_reinit_sw(struct mwifiex_adapter *adapter) adapter->rx_workqueue = alloc_workqueue("MWIFIEX_RX_WORK_QUEUE", WQ_HIGHPRI | WQ_MEM_RECLAIM | - WQ_UNBOUND, 1); + WQ_UNBOUND, 0); if (!adapter->rx_workqueue) goto err_kmalloc; INIT_WORK(&adapter->rx_work, mwifiex_rx_work_queue); @@ -1702,7 +1702,7 @@ mwifiex_add_card(void *card, struct completion *fw_done, adapter->workqueue = alloc_workqueue("MWIFIEX_WORK_QUEUE", - WQ_HIGHPRI | WQ_MEM_RECLAIM | WQ_UNBOUND, 1); + WQ_HIGHPRI | WQ_MEM_RECLAIM | WQ_UNBOUND, 0); if (!adapter->workqueue) goto err_kmalloc; @@ -1712,7 +1712,7 @@ mwifiex_add_card(void *card, struct completion *fw_done, adapter->rx_workqueue = alloc_workqueue("MWIFIEX_RX_WORK_QUEUE", WQ_HIGHPRI | WQ_MEM_RECLAIM | - WQ_UNBOUND, 1); + WQ_UNBOUND, 0); if (!adapter->rx_workqueue) goto err_kmalloc; diff --git a/drivers/net/wireless/marvell/mwifiex/scan.c b/drivers/net/wireless/marvell/mwifiex/scan.c index ac8001c842935994725eb25170e2b22497531b46..644b1e134b01c4d69ba4d332c42713844969fe82 100644 --- a/drivers/net/wireless/marvell/mwifiex/scan.c +++ b/drivers/net/wireless/marvell/mwifiex/scan.c @@ -2187,9 +2187,9 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv, if (nd_config) { adapter->nd_info = - kzalloc(sizeof(struct cfg80211_wowlan_nd_match) + - sizeof(struct cfg80211_wowlan_nd_match *) * - scan_rsp->number_of_sets, GFP_ATOMIC); + kzalloc(struct_size(adapter->nd_info, matches, + scan_rsp->number_of_sets), + GFP_ATOMIC); if (adapter->nd_info) adapter->nd_info->n_matches = scan_rsp->number_of_sets; diff --git a/drivers/net/wireless/marvell/mwifiex/wmm.h b/drivers/net/wireless/marvell/mwifiex/wmm.h index 4f53a271dae041d1bba5d377d6e52e2e3db60bc0..d7659e6889332f1f7407c10a71f5cf165c2c05ea 100644 --- a/drivers/net/wireless/marvell/mwifiex/wmm.h +++ b/drivers/net/wireless/marvell/mwifiex/wmm.h @@ -38,21 +38,6 @@ mwifiex_get_tid(struct mwifiex_ra_list_tbl *ptr) return skb->priority; } -/* - * This function gets the length of a list. - */ -static inline int -mwifiex_wmm_list_len(struct list_head *head) -{ - struct list_head *pos; - int count = 0; - - list_for_each(pos, head) - ++count; - - return count; -} - /* * This function checks if a RA list is empty or not. */ diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/dma.c b/drivers/net/wireless/mediatek/mt76/mt7921/dma.c index f0a80c2b476ab319582b81a832db23c3de79808f..4153cd6c2a01d94d27a841ed7b0d8a39650864f4 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/dma.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/dma.c @@ -231,10 +231,6 @@ int mt7921_dma_init(struct mt7921_dev *dev) if (ret) return ret; - ret = mt7921_wfsys_reset(dev); - if (ret) - return ret; - /* init tx queue */ ret = mt76_connac_init_tx_queues(dev->phy.mt76, MT7921_TXQ_BAND0, MT7921_TX_RING_SIZE, diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c index c69ce6df49561f11d24b7ea9361fdadc3f50ad9b..f55caa00ac69b8e940c2aced2cb46a67a248cf76 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c @@ -476,12 +476,6 @@ static int mt7921_load_firmware(struct mt7921_dev *dev) { int ret; - ret = mt76_get_field(dev, MT_CONN_ON_MISC, MT_TOP_MISC2_FW_N9_RDY); - if (ret && mt76_is_mmio(&dev->mt76)) { - dev_dbg(dev->mt76.dev, "Firmware is already download\n"); - goto fw_loaded; - } - ret = mt76_connac2_load_patch(&dev->mt76, mt7921_patch_name(dev)); if (ret) return ret; @@ -504,8 +498,6 @@ static int mt7921_load_firmware(struct mt7921_dev *dev) return -EIO; } -fw_loaded: - #ifdef CONFIG_PM dev->mt76.hw->wiphy->wowlan = &mt76_connac_wowlan_support; #endif /* CONFIG_PM */ diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c index ddb1fa4ee01d766701980cfb7bb0c5e957f45a3e..95610a117d2f0e6644cc1f7d832d31ceb0558df4 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c @@ -325,6 +325,10 @@ static int mt7921_pci_probe(struct pci_dev *pdev, bus_ops->rmw = mt7921_rmw; dev->mt76.bus = bus_ops; + ret = mt7921e_mcu_fw_pmctrl(dev); + if (ret) + goto err_free_dev; + ret = __mt7921e_mcu_drv_pmctrl(dev); if (ret) goto err_free_dev; @@ -333,6 +337,10 @@ static int mt7921_pci_probe(struct pci_dev *pdev, (mt7921_l1_rr(dev, MT_HW_REV) & 0xff); dev_info(mdev->dev, "ASIC revision: %04x\n", mdev->rev); + ret = mt7921_wfsys_reset(dev); + if (ret) + goto err_free_dev; + mt76_wr(dev, MT_WFDMA0_HOST_INT_ENA, 0); mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff); diff --git a/drivers/net/wireless/mediatek/mt7601u/debugfs.c b/drivers/net/wireless/mediatek/mt7601u/debugfs.c index 230b0e1061a7e12d232ae9f0a83af7eb86e7643e..dbddf256921b575d59b28940370047d8ec0acd85 100644 --- a/drivers/net/wireless/mediatek/mt7601u/debugfs.c +++ b/drivers/net/wireless/mediatek/mt7601u/debugfs.c @@ -127,8 +127,6 @@ void mt7601u_init_debugfs(struct mt7601u_dev *dev) struct dentry *dir; dir = debugfs_create_dir("mt7601u", dev->hw->wiphy->debugfsdir); - if (!dir) - return; debugfs_create_u8("temperature", 0400, dir, &dev->raw_temp); debugfs_create_u32("temp_mode", 0400, dir, &dev->temp_mode); diff --git a/drivers/net/wireless/mediatek/mt7601u/trace.h b/drivers/net/wireless/mediatek/mt7601u/trace.h index 5a6ba015085f0ef1c5e4807ee26ec89a3206d667..07696b6721616b363ed2ed852371a8f2b6fce216 100644 --- a/drivers/net/wireless/mediatek/mt7601u/trace.h +++ b/drivers/net/wireless/mediatek/mt7601u/trace.h @@ -16,7 +16,7 @@ #define MAXNAME 32 #define DEV_ENTRY __array(char, wiphy_name, 32) -#define DEV_ASSIGN strlcpy(__entry->wiphy_name, \ +#define DEV_ASSIGN strscpy(__entry->wiphy_name, \ wiphy_name(dev->hw->wiphy), MAXNAME) #define DEV_PR_FMT "%s " #define DEV_PR_ARG __entry->wiphy_name diff --git a/drivers/net/wireless/microchip/wilc1000/hif.c b/drivers/net/wireless/microchip/wilc1000/hif.c index 5adc69d5bcae37838eb7acdd78798f6be3f31c65..a28da5938481340101d547e88f639e07d8683ad3 100644 --- a/drivers/net/wireless/microchip/wilc1000/hif.c +++ b/drivers/net/wireless/microchip/wilc1000/hif.c @@ -485,6 +485,9 @@ void *wilc_parse_join_bss_param(struct cfg80211_bss *bss, int rsn_ie_len = sizeof(struct element) + rsn_ie[1]; int offset = 8; + param->mode_802_11i = 2; + param->rsn_found = true; + /* extract RSN capabilities */ if (offset < rsn_ie_len) { /* skip over pairwise suites */ @@ -494,11 +497,8 @@ void *wilc_parse_join_bss_param(struct cfg80211_bss *bss, /* skip over authentication suites */ offset += (rsn_ie[offset] * 4) + 2; - if (offset + 1 < rsn_ie_len) { - param->mode_802_11i = 2; - param->rsn_found = true; + if (offset + 1 < rsn_ie_len) memcpy(param->rsn_cap, &rsn_ie[offset], 2); - } } } } diff --git a/drivers/net/wireless/microchip/wilc1000/hif.h b/drivers/net/wireless/microchip/wilc1000/hif.h index baa2881f4465dbd7f5969fa44247d89c623c1d7e..8e386db72e45883301f47116237361ab5ba39dc9 100644 --- a/drivers/net/wireless/microchip/wilc1000/hif.h +++ b/drivers/net/wireless/microchip/wilc1000/hif.h @@ -30,8 +30,6 @@ enum { WILC_GET_CFG }; -#define WILC_MAX_ASSOC_RESP_FRAME_SIZE 256 - struct rf_info { u8 link_speed; s8 rssi; diff --git a/drivers/net/wireless/microchip/wilc1000/wlan_cfg.h b/drivers/net/wireless/microchip/wilc1000/wlan_cfg.h index 614c5673f2328b3e6a7fcb77f15a664322388437..7038b74f8e8ff6d1af7db3f1653ff4ed8eed05c0 100644 --- a/drivers/net/wireless/microchip/wilc1000/wlan_cfg.h +++ b/drivers/net/wireless/microchip/wilc1000/wlan_cfg.h @@ -30,7 +30,7 @@ struct wilc_cfg_str { struct wilc_cfg_str_vals { u8 mac_address[7]; u8 firmware_version[129]; - u8 assoc_rsp[256]; + u8 assoc_rsp[WILC_MAX_ASSOC_RESP_FRAME_SIZE]; }; struct wilc_cfg { diff --git a/drivers/net/wireless/microchip/wilc1000/wlan_if.h b/drivers/net/wireless/microchip/wilc1000/wlan_if.h index df2f5a63bdf6fa08d5939e38451bed9b6c34f404..254a046e3b1bfb398947729c0612b7f7eef6635f 100644 --- a/drivers/net/wireless/microchip/wilc1000/wlan_if.h +++ b/drivers/net/wireless/microchip/wilc1000/wlan_if.h @@ -10,6 +10,8 @@ #include #include "fw.h" +#define WILC_MAX_ASSOC_RESP_FRAME_SIZE 512 + /******************************************** * * Wlan Configuration ID diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00link.c b/drivers/net/wireless/ralink/rt2x00/rt2x00link.c index b052c96347d6d23f9da368d377ace4a790a0e079..6cf7e7c997c2bce59816a60ac0fab438983edcfb 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2x00link.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00link.c @@ -192,7 +192,7 @@ void rt2x00link_update_stats(struct rt2x00_dev *rt2x00dev, return; /* - * Frame was received successfully since non-succesfull + * Frame was received successfully since non-successful * frames would have been dropped by the hardware. */ qual->rx_success++; diff --git a/drivers/net/wireless/realtek/rtl8xxxu/Kconfig b/drivers/net/wireless/realtek/rtl8xxxu/Kconfig index 82bcaf44a65f58dd0da581278a5b02bd3c4a055d..44ad94757a03e97116505cd3a93a6a2c7a475a5b 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/Kconfig +++ b/drivers/net/wireless/realtek/rtl8xxxu/Kconfig @@ -11,7 +11,8 @@ config RTL8XXXU parts written to utilize the Linux mac80211 stack. The driver is known to work with a number of RTL8723AU, RL8188CU, RTL8188RU, RTL8191CU, RTL8192CU, RTL8723BU, RTL8192EU, - RTL8188FU, RTL8188EU, and RTL8710BU (aka RTL8188GU) devices. + RTL8188FU, RTL8188EU, RTL8710BU (aka RTL8188GU), and RTL8192FU + devices. This driver is under development and has a limited feature set. In particular it does not yet support 40MHz channels diff --git a/drivers/net/wireless/realtek/rtl8xxxu/Makefile b/drivers/net/wireless/realtek/rtl8xxxu/Makefile index 1bf083c15dcd3912c65e44499f3b1c93505ccade..fa466589eccb9cfc3a7352666d7d7385425e40f0 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/Makefile +++ b/drivers/net/wireless/realtek/rtl8xxxu/Makefile @@ -3,4 +3,4 @@ obj-$(CONFIG_RTL8XXXU) += rtl8xxxu.o rtl8xxxu-y := rtl8xxxu_core.o rtl8xxxu_8192e.o rtl8xxxu_8723b.o \ rtl8xxxu_8723a.o rtl8xxxu_8192c.o rtl8xxxu_8188f.o \ - rtl8xxxu_8188e.o rtl8xxxu_8710b.o + rtl8xxxu_8188e.o rtl8xxxu_8710b.o rtl8xxxu_8192f.o diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h index 808c1c895113dacf4190674fa6aae9e7ffe121e9..4695fb4e2d2dbaf0ecd78686c0f963205e5d33e5 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h @@ -39,6 +39,7 @@ #define TX_TOTAL_PAGE_NUM_8188E 0xa9 #define TX_TOTAL_PAGE_NUM_8192E 0xf3 #define TX_TOTAL_PAGE_NUM_8723B 0xf7 +#define TX_TOTAL_PAGE_NUM_8192F 0xf7 /* (HPQ + LPQ + NPQ + PUBQ) = TX_TOTAL_PAGE_NUM */ #define TX_PAGE_NUM_PUBQ 0xe7 #define TX_PAGE_NUM_HI_PQ 0x0c @@ -65,6 +66,11 @@ #define TX_PAGE_NUM_LO_PQ_8723B 0x02 #define TX_PAGE_NUM_NORM_PQ_8723B 0x02 +#define TX_PAGE_NUM_PUBQ_8192F 0xde +#define TX_PAGE_NUM_HI_PQ_8192F 0x08 +#define TX_PAGE_NUM_LO_PQ_8192F 0x08 +#define TX_PAGE_NUM_NORM_PQ_8192F 0x08 + #define RTL_FW_PAGE_SIZE 4096 #define RTL8XXXU_FIRMWARE_POLL_MAX 1000 @@ -81,6 +87,7 @@ #define EFUSE_REAL_CONTENT_LEN_8723A 512 #define EFUSE_BT_MAP_LEN_8723A 1024 #define EFUSE_MAX_WORD_UNIT 4 +#define EFUSE_UNDEFINED 0xff enum rtl8xxxu_rtl_chip { RTL8192S = 0x81920, @@ -105,6 +112,7 @@ enum rtl8xxxu_rtl_chip { RTL8195A = 0x8195a, RTL8188F = 0x8188f, RTL8710B = 0x8710b, + RTL8192F = 0x8192f, }; enum rtl8xxxu_rx_type { @@ -1246,6 +1254,40 @@ struct rtl8710bu_efuse { u8 res7[0x3c]; } __packed; +struct rtl8192fu_efuse { + __le16 rtl_id; + u8 res0[0x0e]; + struct rtl8192eu_efuse_tx_power tx_power_index_A; /* 0x10 */ + struct rtl8192eu_efuse_tx_power tx_power_index_B; /* 0x3a */ + u8 res2[0x54]; + u8 channel_plan; /* 0xb8 */ + u8 xtal_k; /* 0xb9 */ + u8 thermal_meter; /* 0xba */ + u8 iqk_lck; /* 0xbb */ + u8 pa_type; /* 0xbc */ + u8 lna_type_2g; /* 0xbd */ + u8 res3[1]; + u8 lna_type_5g; /* 0xbf */ + u8 res4[1]; + u8 rf_board_option; /* 0xc1 */ + u8 rf_feature_option; /* 0xc2 */ + u8 rf_bt_setting; /* 0xc3 */ + u8 eeprom_version; /* 0xc4 */ + u8 eeprom_customer_id; /* 0xc5 */ + u8 res5[3]; + u8 rf_antenna_option; /* 0xc9 */ + u8 rfe_option; /* 0xca */ + u8 country_code; /* 0xcb */ + u8 res6[52]; + u8 vid[2]; /* 0x100 */ + u8 pid[2]; /* 0x102 */ + u8 usb_optional_function; /* 0x104 */ + u8 res7[2]; + u8 mac_addr[ETH_ALEN]; /* 0x107 */ + u8 device_info[80]; /* 0x10d */ + u8 res9[163]; +} __packed; + struct rtl8xxxu_reg8val { u16 reg; u8 val; @@ -1280,6 +1322,9 @@ struct rtl8xxxu_rfregs { #define H2C_JOIN_BSS_DISCONNECT 0 #define H2C_JOIN_BSS_CONNECT 1 +#define H2C_MACID_ROLE_STA 1 +#define H2C_MACID_ROLE_AP 2 + /* * H2C (firmware) commands differ between the older generation chips * 8188[cr]u, 819[12]cu, and 8723au, and the more recent chips 8723bu, @@ -1727,6 +1772,8 @@ struct rtl8xxxu_cfo_tracking { }; #define RTL8XXXU_HW_LED_CONTROL 2 +#define RTL8XXXU_MAX_MAC_ID_NUM 128 +#define RTL8XXXU_BC_MC_MACID 0 struct rtl8xxxu_priv { struct ieee80211_hw *hw; @@ -1791,6 +1838,7 @@ struct rtl8xxxu_priv { u32 cck_agc_report_type:1; u32 cck_new_agc:1; u8 default_crystal_cap; + u8 rfe_type; unsigned int pipe_interrupt; unsigned int pipe_in; unsigned int pipe_out[TXDESC_QUEUE_MAX]; @@ -1831,6 +1879,7 @@ struct rtl8xxxu_priv { struct rtl8188fu_efuse efuse8188fu; struct rtl8188eu_efuse efuse8188eu; struct rtl8710bu_efuse efuse8710bu; + struct rtl8192fu_efuse efuse8192fu; } efuse_wifi; u32 adda_backup[RTL8XXXU_ADDA_REGS]; u32 mac_backup[RTL8XXXU_MAC_REGS]; @@ -1851,6 +1900,7 @@ struct rtl8xxxu_priv { struct delayed_work ra_watchdog; struct work_struct c2hcmd_work; struct sk_buff_head c2hcmd_queue; + struct work_struct update_beacon_work; struct rtl8xxxu_btcoex bt_coex; struct rtl8xxxu_ra_report ra_report; struct rtl8xxxu_cfo_tracking cfo_tracking; @@ -1859,6 +1909,14 @@ struct rtl8xxxu_priv { bool led_registered; char led_name[32]; struct led_classdev led_cdev; + DECLARE_BITMAP(mac_id_map, RTL8XXXU_MAX_MAC_ID_NUM); +}; + +struct rtl8xxxu_sta_info { + struct ieee80211_sta *sta; + struct ieee80211_vif *vif; + + u8 macid; }; struct rtl8xxxu_rx_urb { @@ -1903,15 +1961,16 @@ struct rtl8xxxu_fileops { void (*set_tx_power) (struct rtl8xxxu_priv *priv, int channel, bool ht40); void (*update_rate_mask) (struct rtl8xxxu_priv *priv, - u32 ramask, u8 rateid, int sgi, int txbw_40mhz); + u32 ramask, u8 rateid, int sgi, int txbw_40mhz, + u8 macid); void (*report_connect) (struct rtl8xxxu_priv *priv, - u8 macid, bool connect); + u8 macid, u8 role, bool connect); void (*report_rssi) (struct rtl8xxxu_priv *priv, u8 macid, u8 rssi); void (*fill_txdesc) (struct ieee80211_hw *hw, struct ieee80211_hdr *hdr, struct ieee80211_tx_info *tx_info, struct rtl8xxxu_txdesc32 *tx_desc, bool sgi, bool short_preamble, bool ampdu_enable, - u32 rts_rate); + u32 rts_rate, u8 macid); void (*set_crystal_cap) (struct rtl8xxxu_priv *priv, u8 crystal_cap); s8 (*cck_rssi) (struct rtl8xxxu_priv *priv, struct rtl8723au_phy_stats *phy_stats); int (*led_classdev_brightness_set) (struct led_classdev *led_cdev, @@ -1929,6 +1988,9 @@ struct rtl8xxxu_fileops { u8 init_reg_hmtfr:1; u8 ampdu_max_time; u8 ustime_tsf_edca; + u16 max_aggr_num; + u8 supports_ap:1; + u16 max_macid_num; u32 adda_1t_init; u32 adda_1t_path_on; u32 adda_2t_path_on_a; @@ -2015,6 +2077,7 @@ void rtl8xxxu_gen1_phy_iq_calibrate(struct rtl8xxxu_priv *priv); void rtl8xxxu_gen1_init_phy_bb(struct rtl8xxxu_priv *priv); void rtl8xxxu_gen1_set_tx_power(struct rtl8xxxu_priv *priv, int channel, bool ht40); +void rtl8188f_channel_to_group(int channel, int *group, int *cck_group); void rtl8188f_set_tx_power(struct rtl8xxxu_priv *priv, int channel, bool ht40); void rtl8xxxu_gen1_config_channel(struct ieee80211_hw *hw); @@ -2022,13 +2085,13 @@ void rtl8xxxu_gen2_config_channel(struct ieee80211_hw *hw); void rtl8xxxu_gen1_usb_quirks(struct rtl8xxxu_priv *priv); void rtl8xxxu_gen2_usb_quirks(struct rtl8xxxu_priv *priv); void rtl8xxxu_update_rate_mask(struct rtl8xxxu_priv *priv, - u32 ramask, u8 rateid, int sgi, int txbw_40mhz); + u32 ramask, u8 rateid, int sgi, int txbw_40mhz, u8 macid); void rtl8xxxu_gen2_update_rate_mask(struct rtl8xxxu_priv *priv, - u32 ramask, u8 rateid, int sgi, int txbw_40mhz); + u32 ramask, u8 rateid, int sgi, int txbw_40mhz, u8 macid); void rtl8xxxu_gen1_report_connect(struct rtl8xxxu_priv *priv, - u8 macid, bool connect); + u8 macid, u8 role, bool connect); void rtl8xxxu_gen2_report_connect(struct rtl8xxxu_priv *priv, - u8 macid, bool connect); + u8 macid, u8 role, bool connect); void rtl8xxxu_gen1_report_rssi(struct rtl8xxxu_priv *priv, u8 macid, u8 rssi); void rtl8xxxu_gen2_report_rssi(struct rtl8xxxu_priv *priv, u8 macid, u8 rssi); void rtl8xxxu_gen1_init_aggregation(struct rtl8xxxu_priv *priv); @@ -2057,17 +2120,17 @@ void rtl8xxxu_fill_txdesc_v1(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr, struct ieee80211_tx_info *tx_info, struct rtl8xxxu_txdesc32 *tx_desc, bool sgi, bool short_preamble, bool ampdu_enable, - u32 rts_rate); + u32 rts_rate, u8 macid); void rtl8xxxu_fill_txdesc_v2(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr, struct ieee80211_tx_info *tx_info, struct rtl8xxxu_txdesc32 *tx_desc32, bool sgi, bool short_preamble, bool ampdu_enable, - u32 rts_rate); + u32 rts_rate, u8 macid); void rtl8xxxu_fill_txdesc_v3(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr, struct ieee80211_tx_info *tx_info, struct rtl8xxxu_txdesc32 *tx_desc32, bool sgi, bool short_preamble, bool ampdu_enable, - u32 rts_rate); + u32 rts_rate, u8 macid); void rtl8723bu_set_ps_tdma(struct rtl8xxxu_priv *priv, u8 arg1, u8 arg2, u8 arg3, u8 arg4, u8 arg5); void rtl8723bu_phy_init_antenna_selection(struct rtl8xxxu_priv *priv); @@ -2079,6 +2142,7 @@ void rtl8xxxu_update_ra_report(struct rtl8xxxu_ra_report *rarpt, void rtl8188e_ra_info_init_all(struct rtl8xxxu_ra_info *ra); void rtl8188e_handle_ra_tx_report2(struct rtl8xxxu_priv *priv, struct sk_buff *skb); +extern struct rtl8xxxu_fileops rtl8192fu_fops; extern struct rtl8xxxu_fileops rtl8710bu_fops; extern struct rtl8xxxu_fileops rtl8188fu_fops; extern struct rtl8xxxu_fileops rtl8188eu_fops; diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188e.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188e.c index 8986783ae8fa7fa6628245664453498817de84c1..6d0f975f891b74efd9d4d912eeb1972520a562c5 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188e.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188e.c @@ -1794,7 +1794,8 @@ static void rtl8188e_arfb_refresh(struct rtl8xxxu_ra_info *ra) static void rtl8188e_update_rate_mask(struct rtl8xxxu_priv *priv, - u32 ramask, u8 rateid, int sgi, int txbw_40mhz) + u32 ramask, u8 rateid, int sgi, int txbw_40mhz, + u8 macid) { struct rtl8xxxu_ra_info *ra = &priv->ra_info; diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188f.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188f.c index dbdfd778746552269e2ea3578bc9425cd21d34d8..1e1c8fa194cb833e694a78ce75cc3e92b6e5be85 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188f.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188f.c @@ -351,7 +351,7 @@ static int rtl8188fu_identify_chip(struct rtl8xxxu_priv *priv) return ret; } -static void rtl8188f_channel_to_group(int channel, int *group, int *cck_group) +void rtl8188f_channel_to_group(int channel, int *group, int *cck_group) { if (channel < 3) *group = 0; @@ -654,7 +654,7 @@ static void rtl8188fu_config_channel(struct ieee80211_hw *hw) rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_RX_BB2, val32); /* RC Corner */ - rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, 0x00140); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, 0x00140); rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_RX_G2, 0x01c6c); } @@ -854,8 +854,8 @@ static int rtl8188fu_iqk_path_a(struct rtl8xxxu_priv *priv, u32 *lok_result) rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_TXPA_G2, 0x07ff7); /* PA,PAD gain adjust */ - rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, 0x980); - rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_56, 0x5102a); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, 0x980); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_PAD_TXG, 0x5102a); /* enter IQK mode */ val32 = rtl8xxxu_read32(priv, REG_FPGA0_IQK); @@ -886,7 +886,7 @@ static int rtl8188fu_iqk_path_a(struct rtl8xxxu_priv *priv, u32 *lok_result) val32 &= 0x000000ff; rtl8xxxu_write32(priv, REG_FPGA0_IQK, val32); - rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, 0x180); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, 0x180); /* save LOK result */ *lok_result = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_TXM_IDAC); @@ -927,8 +927,8 @@ static int rtl8188fu_rx_iqk_path_a(struct rtl8xxxu_priv *priv, u32 lok_result) rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_TXPA_G2, 0xf1173); /* PA,PAD gain adjust */ - rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, 0x980); - rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_56, 0x5102a); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, 0x980); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_PAD_TXG, 0x5102a); /* * Enter IQK mode @@ -967,7 +967,7 @@ static int rtl8188fu_rx_iqk_path_a(struct rtl8xxxu_priv *priv, u32 lok_result) val32 &= 0x000000ff; rtl8xxxu_write32(priv, REG_FPGA0_IQK, val32); - rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, 0x180); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, 0x180); /* Check failed */ reg_eac = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_A_2); @@ -1002,8 +1002,8 @@ static int rtl8188fu_rx_iqk_path_a(struct rtl8xxxu_priv *priv, u32 lok_result) /* * PA, PAD setting */ - rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, 0x980); - rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_56, 0x51000); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, 0x980); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_PAD_TXG, 0x51000); /* * Enter IQK mode @@ -1041,7 +1041,7 @@ static int rtl8188fu_rx_iqk_path_a(struct rtl8xxxu_priv *priv, u32 lok_result) val32 &= 0x000000ff; rtl8xxxu_write32(priv, REG_FPGA0_IQK, val32); - rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, 0x180); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, 0x180); /* reload LOK value */ rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_TXM_IDAC, lok_result); @@ -1748,6 +1748,9 @@ struct rtl8xxxu_fileops rtl8188fu_fops = { .init_reg_hmtfr = 1, .ampdu_max_time = 0x70, .ustime_tsf_edca = 0x28, + .max_aggr_num = 0x0c14, + .supports_ap = 1, + .max_macid_num = 16, .adda_1t_init = 0x03c00014, .adda_1t_path_on = 0x03c00014, .trxff_boundary = 0x3f7f, diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c index fcc2926ea938946a873d50edcea30c2561e0aad0..f673aa9ba15a57b7dca40a9aa04fdbdae88237c7 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c @@ -716,7 +716,7 @@ static int rtl8192eu_iqk_path_a(struct rtl8xxxu_priv *priv) * PA/PAD controlled by 0x0 */ rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x00000000); - rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, 0x00180); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, 0x00180); rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_WE_LUT, 0x800a0); rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_RCK_OS, 0x20000); @@ -776,8 +776,8 @@ static int rtl8192eu_rx_iqk_path_a(struct rtl8xxxu_priv *priv) rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_TXPA_G2, 0xf1173); /* PA/PAD control by 0x56, and set = 0x0 */ - rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, 0x00980); - rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_56, 0x511e0); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, 0x00980); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_PAD_TXG, 0x511e0); /* Enter IQK mode */ rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x80800000); @@ -816,7 +816,7 @@ static int rtl8192eu_rx_iqk_path_a(struct rtl8xxxu_priv *priv) } else { /* PA/PAD controlled by 0x0 */ rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x00000000); - rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, 0x180); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, 0x180); goto out; } @@ -838,8 +838,8 @@ static int rtl8192eu_rx_iqk_path_a(struct rtl8xxxu_priv *priv) rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_TXPA_G2, 0xf7ff2); /* PA/PAD control by 0x56, and set = 0x0 */ - rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, 0x00980); - rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_56, 0x510e0); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, 0x00980); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_PAD_TXG, 0x510e0); /* Enter IQK mode */ rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x80800000); @@ -869,7 +869,7 @@ static int rtl8192eu_rx_iqk_path_a(struct rtl8xxxu_priv *priv) reg_ea4 = rtl8xxxu_read32(priv, REG_RX_POWER_BEFORE_IQK_A_2); rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x00000000); - rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, 0x180); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, 0x180); if (!(reg_eac & BIT(27)) && ((reg_ea4 & 0x03ff0000) != 0x01320000) && @@ -889,7 +889,7 @@ static int rtl8192eu_iqk_path_b(struct rtl8xxxu_priv *priv) int result = 0; rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x00000000); - rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_UNKNOWN_DF, 0x00180); + rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_GAIN_CCA, 0x00180); rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_WE_LUT, 0x800a0); rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_RCK_OS, 0x20000); @@ -952,8 +952,8 @@ static int rtl8192eu_rx_iqk_path_b(struct rtl8xxxu_priv *priv) rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_TXPA_G2, 0xf1173); /* PA/PAD control by 0x56, and set = 0x0 */ - rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_UNKNOWN_DF, 0x00980); - rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_UNKNOWN_56, 0x511e0); + rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_GAIN_CCA, 0x00980); + rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_PAD_TXG, 0x511e0); /* Enter IQK mode */ rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x80800000); @@ -995,7 +995,7 @@ static int rtl8192eu_rx_iqk_path_b(struct rtl8xxxu_priv *priv) * Vendor driver restores RF_A here which I believe is a bug */ rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x00000000); - rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_UNKNOWN_DF, 0x180); + rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_GAIN_CCA, 0x180); goto out; } @@ -1017,8 +1017,8 @@ static int rtl8192eu_rx_iqk_path_b(struct rtl8xxxu_priv *priv) rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_TXPA_G2, 0xf7ff2); /* PA/PAD control by 0x56, and set = 0x0 */ - rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_UNKNOWN_DF, 0x00980); - rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_UNKNOWN_56, 0x510e0); + rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_GAIN_CCA, 0x00980); + rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_PAD_TXG, 0x510e0); /* Enter IQK mode */ rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x80800000); @@ -1049,7 +1049,7 @@ static int rtl8192eu_rx_iqk_path_b(struct rtl8xxxu_priv *priv) reg_ecc = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_B_2); rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x00000000); - rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_UNKNOWN_DF, 0x180); + rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_GAIN_CCA, 0x180); if (!(reg_eac & BIT(30)) && ((reg_ec4 & 0x03ff0000) != 0x01320000) && diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192f.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192f.c new file mode 100644 index 0000000000000000000000000000000000000000..18dc5221a9c0c4559b97e3c587a0bbf8554caf51 --- /dev/null +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192f.c @@ -0,0 +1,2090 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * RTL8XXXU mac80211 USB driver - 8192fu specific subdriver + * + * Copyright (c) 2023 Bitterblue Smith + * + * Portions copied from existing rtl8xxxu code: + * Copyright (c) 2014 - 2017 Jes Sorensen + * + * Portions, notably calibration code: + * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "rtl8xxxu.h" +#include "rtl8xxxu_regs.h" + +static const struct rtl8xxxu_reg8val rtl8192f_mac_init_table[] = { + {0x420, 0x00}, {0x422, 0x78}, {0x428, 0x0a}, {0x429, 0x10}, + {0x430, 0x00}, {0x431, 0x00}, {0x432, 0x00}, {0x433, 0x01}, + {0x434, 0x04}, {0x435, 0x05}, {0x436, 0x07}, {0x437, 0x08}, + {0x43c, 0x04}, {0x43d, 0x05}, {0x43e, 0x07}, {0x43f, 0x08}, + {0x440, 0x5d}, {0x441, 0x01}, {0x442, 0x00}, {0x444, 0x10}, + {0x445, 0xf0}, {0x446, 0x0e}, {0x447, 0x1f}, {0x448, 0x00}, + {0x449, 0x00}, {0x44a, 0x00}, {0x44b, 0x00}, {0x44c, 0x10}, + {0x44d, 0xf0}, {0x44e, 0x0e}, {0x44f, 0x00}, {0x450, 0x00}, + {0x451, 0x00}, {0x452, 0x00}, {0x453, 0x00}, {0x480, 0x20}, + {0x49c, 0x30}, {0x49d, 0xf0}, {0x49e, 0x03}, {0x49f, 0x3e}, + {0x4a0, 0x00}, {0x4a1, 0x00}, {0x4a2, 0x00}, {0x4a3, 0x00}, + {0x4a4, 0x15}, {0x4a5, 0xf0}, {0x4a6, 0x01}, {0x4a7, 0x0e}, + {0x4a8, 0xe0}, {0x4a9, 0x00}, {0x4aa, 0x00}, {0x4ab, 0x00}, + {0x2448, 0x06}, {0x244a, 0x06}, {0x244c, 0x06}, {0x244e, 0x06}, + {0x4c7, 0x80}, {0x4c8, 0xff}, {0x4c9, 0x08}, {0x4ca, 0x3c}, + {0x4cb, 0x3c}, {0x4cc, 0xff}, {0x4cd, 0xff}, {0x4ce, 0x01}, + {0x500, 0x26}, {0x501, 0xa2}, {0x502, 0x2f}, {0x503, 0x00}, + {0x504, 0x28}, {0x505, 0xa3}, {0x506, 0x5e}, {0x507, 0x00}, + {0x508, 0x2b}, {0x509, 0xa4}, {0x50a, 0x5e}, {0x50b, 0x00}, + {0x50c, 0x4f}, {0x50d, 0xa4}, {0x50e, 0x00}, {0x50f, 0x00}, + {0x512, 0x1c}, {0x514, 0x0a}, {0x516, 0x0a}, {0x521, 0x2f}, + {0x525, 0x0f}, {0x550, 0x10}, {0x551, 0x10}, {0x559, 0x02}, + {0x55c, 0x50}, {0x55d, 0xff}, {0x605, 0x30}, {0x608, 0x0e}, + {0x609, 0x2a}, {0x60c, 0x18}, {0x620, 0xff}, {0x621, 0xff}, + {0x622, 0xff}, {0x623, 0xff}, {0x624, 0xff}, {0x625, 0xff}, + {0x626, 0xff}, {0x627, 0xff}, {0x638, 0x50}, {0x63c, 0x0a}, + {0x63d, 0x0a}, {0x63e, 0x0e}, {0x63f, 0x0e}, {0x640, 0x40}, + {0x642, 0x40}, {0x643, 0x00}, {0x652, 0xc8}, {0x66e, 0x05}, + {0x6a0, 0xff}, {0x6a1, 0xff}, {0x6a2, 0xff}, {0x6a3, 0xff}, + {0x6a4, 0xff}, {0x6a5, 0xff}, {0x6de, 0x84}, {0x700, 0x21}, + {0x701, 0x43}, {0x702, 0x65}, {0x703, 0x87}, {0x708, 0x21}, + {0x709, 0x43}, {0x70a, 0x65}, {0x70b, 0x87}, {0x718, 0x40}, + {0x7c0, 0x38}, {0x7c2, 0x0f}, {0x7c3, 0xc0}, {0x073, 0x04}, + {0x7c4, 0x77}, {0x024, 0xc7}, {0x7ec, 0xff}, {0x7ed, 0xff}, + {0x7ee, 0xff}, {0x7ef, 0xff}, + {0xffff, 0xff}, +}; + +/* If updating the phy init table, also update rtl8192f_revise_cck_tx_psf(). */ +static const struct rtl8xxxu_reg32val rtl8192fu_phy_init_table[] = { + {0x800, 0x80006C00}, {0x804, 0x00004001}, + {0x808, 0x0000FC00}, {0x80C, 0x00000000}, + {0x810, 0x20200322}, {0x814, 0x020C3910}, + {0x818, 0x00000385}, {0x81C, 0x07000000}, + {0x820, 0x01000100}, {0x824, 0x00390204}, + {0x828, 0x01000100}, {0x82C, 0x00390204}, + {0x830, 0x25252525}, {0x834, 0x25252525}, + {0x838, 0x25252525}, {0x83C, 0x25252525}, + {0x840, 0x00010000}, {0x844, 0x00010000}, + {0x848, 0x25252525}, {0x84C, 0x25252525}, + {0x850, 0x00031FE0}, {0x854, 0x00000000}, + {0x858, 0x569A569A}, {0x85C, 0x00400040}, + {0x860, 0x66F60000}, {0x864, 0x061F0000}, + {0x868, 0x25252525}, {0x86C, 0x25252525}, + {0x870, 0x00000300}, {0x874, 0x04003400}, + {0x878, 0x08080808}, {0x87C, 0x004F0201}, + {0x880, 0xD8001402}, {0x884, 0xC0000120}, + {0x888, 0x00000000}, {0x88C, 0xCC0000C0}, + {0x890, 0x00000000}, {0x894, 0xFFFFFFFE}, + {0x898, 0x40302010}, {0x89C, 0x00706050}, + {0x900, 0x00000000}, {0x904, 0x00000023}, + {0x908, 0x00000F00}, {0x90C, 0x81121313}, + {0x910, 0x024C0000}, {0x914, 0x00000000}, + {0x918, 0x00000000}, {0x91C, 0x00000000}, + {0x920, 0x00000000}, {0x924, 0x00000000}, + {0x928, 0x00000000}, {0x92C, 0x00000000}, + {0x930, 0x88000000}, {0x934, 0x00000245}, + {0x938, 0x00024588}, {0x93C, 0x00000000}, + {0x940, 0x000007FF}, {0x944, 0x3F3F0000}, + {0x948, 0x000001A3}, {0x94C, 0x20200008}, + {0x950, 0x00338A98}, {0x954, 0x00000000}, + {0x958, 0xCBCAD87A}, {0x95C, 0x06EB5735}, + {0x960, 0x00000000}, {0x964, 0x00000000}, + {0x968, 0x00000000}, {0x96C, 0x00000003}, + {0x970, 0x00000000}, {0x974, 0x00000000}, + {0x978, 0x00000000}, {0x97C, 0x10030000}, + {0x980, 0x00000000}, {0x984, 0x02800280}, + {0x988, 0x020A5704}, {0x98C, 0x1461C826}, + {0x990, 0x0001469E}, {0x994, 0x008858D1}, + {0x998, 0x400086C9}, {0x99C, 0x44444242}, + {0x9A0, 0x00000000}, {0x9A4, 0x00000000}, + {0x9A8, 0x00000000}, {0x9AC, 0xC0000000}, + {0xA00, 0x00D047C8}, {0xA04, 0xC1FF0008}, + {0xA08, 0x88838300}, {0xA0C, 0x2E20100F}, + {0xA10, 0x9500BB78}, {0xA14, 0x11144028}, + {0xA18, 0x00881117}, {0xA1C, 0x89140F00}, + {0xA20, 0xE82C0001}, {0xA24, 0x64B80C1C}, + {0xA28, 0x00158810}, {0xA2C, 0x10BB8000}, + {0xA70, 0x00008000}, {0xA74, 0x80800100}, + {0xA78, 0x000089F0}, {0xA7C, 0x225B0606}, + {0xA80, 0x20803210}, {0xA84, 0x00200200}, + {0xA88, 0x00000000}, {0xA8C, 0x00000000}, + {0xA90, 0x00000000}, {0xA94, 0x00000000}, + {0xA98, 0x00000000}, {0xA9C, 0x00460000}, + {0xAA0, 0x00000000}, {0xAA4, 0x00020014}, + {0xAA8, 0xBA0A0008}, {0xAAC, 0x01235667}, + {0xAB0, 0x00000000}, {0xAB4, 0x00201402}, + {0xAB8, 0x0000001C}, {0xABC, 0x0000F7FF}, + {0xAC0, 0xD4C0A742}, {0xAC4, 0x00000000}, + {0xAC8, 0x00000F08}, {0xACC, 0x00000F07}, + {0xAD0, 0xA1052A10}, {0xAD4, 0x0D9D8452}, + {0xAD8, 0x9E024024}, {0xADC, 0x0023C001}, + {0xAE0, 0x00000391}, {0xB2C, 0x00000000}, + {0xC00, 0x00000080}, {0xC04, 0x6F005433}, + {0xC08, 0x000004E4}, {0xC0C, 0x6C6C6C6C}, + {0xC10, 0x22000000}, {0xC14, 0x40000100}, + {0xC18, 0x22000000}, {0xC1C, 0x40000100}, + {0xC20, 0x00000000}, {0xC24, 0x40000100}, + {0xC28, 0x00000000}, {0xC2C, 0x40000100}, + {0xC30, 0x0401E809}, {0xC34, 0x30000020}, + {0xC38, 0x23808080}, {0xC3C, 0x00002F44}, + {0xC40, 0x1CF8403F}, {0xC44, 0x000100C7}, + {0xC48, 0xEC060106}, {0xC4C, 0x007F037F}, + {0xC50, 0x00E48020}, {0xC54, 0x04008017}, + {0xC58, 0x00000020}, {0xC5C, 0x00708492}, + {0xC60, 0x09280200}, {0xC64, 0x5014838B}, + {0xC68, 0x47C006C7}, {0xC6C, 0x00000035}, + {0xC70, 0x00001007}, {0xC74, 0x02815269}, + {0xC78, 0x0FE07F1F}, {0xC7C, 0x00B91612}, + {0xC80, 0x40000100}, {0xC84, 0x32000000}, + {0xC88, 0x40000100}, {0xC8C, 0xA0240000}, + {0xC90, 0x400E161E}, {0xC94, 0x00000F00}, + {0xC98, 0x400E161E}, {0xC9C, 0x0000BDC8}, + {0xCA0, 0x00000000}, {0xCA4, 0x098300A0}, + {0xCA8, 0x00006B00}, {0xCAC, 0x87F45B1A}, + {0xCB0, 0x0000002D}, {0xCB4, 0x00000000}, + {0xCB8, 0x00000000}, {0xCBC, 0x28100200}, + {0xCC0, 0x0010A3D0}, {0xCC4, 0x00000F7D}, + {0xCC8, 0x00000000}, {0xCCC, 0x00000000}, + {0xCD0, 0x593659AD}, {0xCD4, 0xB7545121}, + {0xCD8, 0x64B22427}, {0xCDC, 0x00766932}, + {0xCE0, 0x40201000}, {0xCE4, 0x00000000}, + {0xCE8, 0x40E04407}, {0xCEC, 0x2E572000}, + {0xD00, 0x000D8780}, {0xD04, 0x40020403}, + {0xD08, 0x0002907F}, {0xD0C, 0x20010201}, + {0xD10, 0x06288888}, {0xD14, 0x8888367B}, + {0xD18, 0x7D806DB3}, {0xD1C, 0x0000007F}, + {0xD20, 0x567600B8}, {0xD24, 0x0000018B}, + {0xD28, 0xD513FF7D}, {0xD2C, 0xCC979975}, + {0xD30, 0x04928000}, {0xD34, 0x40608000}, + {0xD38, 0x88DDA000}, {0xD3C, 0x00026EE2}, + {0xD50, 0x67270001}, {0xD54, 0x20500000}, + {0xD58, 0x16161616}, {0xD5C, 0x71F20064}, + {0xD60, 0x4653DA60}, {0xD64, 0x3E718A3C}, + {0xD68, 0x00000183}, {0xD7C, 0x00000000}, + {0xD80, 0x50000000}, {0xD84, 0x31310400}, + {0xD88, 0xF5B50000}, {0xD8C, 0x00000000}, + {0xD90, 0x00000000}, {0xD94, 0x44BBBB44}, + {0xD98, 0x44BB44FF}, {0xD9C, 0x06033688}, + {0xE00, 0x25252525}, {0xE04, 0x25252525}, + {0xE08, 0x25252525}, {0xE10, 0x25252525}, + {0xE14, 0x25252525}, {0xE18, 0x25252525}, + {0xE1C, 0x25252525}, {0xE20, 0x00000000}, + {0xE24, 0x00200000}, {0xE28, 0x00000000}, + {0xE2C, 0x00000000}, {0xE30, 0x01007C00}, + {0xE34, 0x01004800}, {0xE38, 0x10008C0F}, + {0xE3C, 0x3C008C0F}, {0xE40, 0x01007C00}, + {0xE44, 0x00000000}, {0xE48, 0x00000000}, + {0xE4C, 0x00000000}, {0xE50, 0x01007C00}, + {0xE54, 0x01004800}, {0xE58, 0x10008C0F}, + {0xE5C, 0x3C008C0F}, {0xE60, 0x02100000}, + {0xE64, 0xBBBBBBBB}, {0xE68, 0x40404040}, + {0xE6C, 0x80408040}, {0xE70, 0x80408040}, + {0xE74, 0x40404040}, {0xE78, 0x00400040}, + {0xE7C, 0x40404040}, {0xE80, 0x00FF0000}, + {0xE84, 0x80408040}, {0xE88, 0x40404040}, + {0xE8C, 0x80408040}, {0xED0, 0x80408040}, + {0xED4, 0x80408040}, {0xED8, 0x80408040}, + {0xEDC, 0xC040C040}, {0xEE0, 0xC040C040}, + {0xEE4, 0x00400040}, {0xEE8, 0xD8001402}, + {0xEEC, 0xC0000120}, {0xEF0, 0x02000B09}, + {0xEF4, 0x00000001}, {0xEF8, 0x00000000}, + {0xF00, 0x00000300}, {0xF04, 0x00000002}, + {0xF08, 0x00007D0C}, {0xF0C, 0x0000A907}, + {0xF10, 0x00005807}, {0xF14, 0x00000003}, + {0xF18, 0x07D003E8}, {0xF1C, 0x8000001F}, + {0xF20, 0x00000000}, {0xF24, 0x00000000}, + {0xF28, 0x00000000}, {0xF2C, 0x00000000}, + {0xF30, 0x00000000}, {0xF34, 0x00000000}, + {0xF38, 0x00030055}, {0xF3C, 0x0000003A}, + {0xF40, 0x00000002}, {0xF44, 0x00000000}, + {0xF48, 0x00000000}, {0xF4C, 0x0B000000}, + {0xF50, 0x00000000}, + {0xffff, 0xffffffff}, +}; + +static const struct rtl8xxxu_reg32val rtl8192f_agc_table[] = { + {0xC78, 0x0FA0001F}, {0xC78, 0x0FA0011F}, + {0xC78, 0x0FA0021F}, {0xC78, 0x0FA0031F}, + {0xC78, 0x0FA0041F}, {0xC78, 0x0FA0051F}, + {0xC78, 0x0F90061F}, {0xC78, 0x0F80071F}, + {0xC78, 0x0F70081F}, {0xC78, 0x0F60091F}, + {0xC78, 0x0F500A1F}, {0xC78, 0x0F400B1F}, + {0xC78, 0x0F300C1F}, {0xC78, 0x0F200D1F}, + {0xC78, 0x0F100E1F}, {0xC78, 0x0F000F1F}, + {0xC78, 0x0EF0101F}, {0xC78, 0x0EE0111F}, + {0xC78, 0x0ED0121F}, {0xC78, 0x0EC0131F}, + {0xC78, 0x0EB0141F}, {0xC78, 0x0EA0151F}, + {0xC78, 0x0E90161F}, {0xC78, 0x0E80171F}, + {0xC78, 0x0E70181F}, {0xC78, 0x0E60191F}, + {0xC78, 0x0E501A1F}, {0xC78, 0x0E401B1F}, + {0xC78, 0x0E301C1F}, {0xC78, 0x0C701D1F}, + {0xC78, 0x0C601E1F}, {0xC78, 0x0C501F1F}, + {0xC78, 0x0C40201F}, {0xC78, 0x0C30211F}, + {0xC78, 0x0A60221F}, {0xC78, 0x0A50231F}, + {0xC78, 0x0A40241F}, {0xC78, 0x0A30251F}, + {0xC78, 0x0860261F}, {0xC78, 0x0850271F}, + {0xC78, 0x0840281F}, {0xC78, 0x0830291F}, + {0xC78, 0x06702A1F}, {0xC78, 0x06602B1F}, + {0xC78, 0x06502C1F}, {0xC78, 0x06402D1F}, + {0xC78, 0x06302E1F}, {0xC78, 0x04602F1F}, + {0xC78, 0x0450301F}, {0xC78, 0x0440311F}, + {0xC78, 0x0430321F}, {0xC78, 0x0260331F}, + {0xC78, 0x0250341F}, {0xC78, 0x0240351F}, + {0xC78, 0x0230361F}, {0xC78, 0x0050371F}, + {0xC78, 0x0040381F}, {0xC78, 0x0030391F}, + {0xC78, 0x00203A1F}, {0xC78, 0x00103B1F}, + {0xC78, 0x00003C1F}, {0xC78, 0x00003D1F}, + {0xC78, 0x00003E1F}, {0xC78, 0x00003F1F}, + + {0xC78, 0x0FA0401F}, {0xC78, 0x0FA0411F}, + {0xC78, 0x0FA0421F}, {0xC78, 0x0FA0431F}, + {0xC78, 0x0F90441F}, {0xC78, 0x0F80451F}, + {0xC78, 0x0F70461F}, {0xC78, 0x0F60471F}, + {0xC78, 0x0F50481F}, {0xC78, 0x0F40491F}, + {0xC78, 0x0F304A1F}, {0xC78, 0x0F204B1F}, + {0xC78, 0x0F104C1F}, {0xC78, 0x0F004D1F}, + {0xC78, 0x0EF04E1F}, {0xC78, 0x0EE04F1F}, + {0xC78, 0x0ED0501F}, {0xC78, 0x0EC0511F}, + {0xC78, 0x0EB0521F}, {0xC78, 0x0EA0531F}, + {0xC78, 0x0E90541F}, {0xC78, 0x0E80551F}, + {0xC78, 0x0E70561F}, {0xC78, 0x0E60571F}, + {0xC78, 0x0E50581F}, {0xC78, 0x0E40591F}, + {0xC78, 0x0E305A1F}, {0xC78, 0x0E205B1F}, + {0xC78, 0x0E105C1F}, {0xC78, 0x0C505D1F}, + {0xC78, 0x0C405E1F}, {0xC78, 0x0C305F1F}, + {0xC78, 0x0C20601F}, {0xC78, 0x0C10611F}, + {0xC78, 0x0A40621F}, {0xC78, 0x0A30631F}, + {0xC78, 0x0A20641F}, {0xC78, 0x0A10651F}, + {0xC78, 0x0840661F}, {0xC78, 0x0830671F}, + {0xC78, 0x0820681F}, {0xC78, 0x0810691F}, + {0xC78, 0x06506A1F}, {0xC78, 0x06406B1F}, + {0xC78, 0x06306C1F}, {0xC78, 0x06206D1F}, + {0xC78, 0x06106E1F}, {0xC78, 0x04406F1F}, + {0xC78, 0x0430701F}, {0xC78, 0x0420711F}, + {0xC78, 0x0410721F}, {0xC78, 0x0240731F}, + {0xC78, 0x0230741F}, {0xC78, 0x0220751F}, + {0xC78, 0x0210761F}, {0xC78, 0x0030771F}, + {0xC78, 0x0020781F}, {0xC78, 0x0010791F}, + {0xC78, 0x00007A1F}, {0xC78, 0x00007B1F}, + {0xC78, 0x00007C1F}, {0xC78, 0x00007D1F}, + {0xC78, 0x00007E1F}, {0xC78, 0x00007F1F}, + + {0xC78, 0x0FA0801F}, {0xC78, 0x0FA0811F}, + {0xC78, 0x0FA0821F}, {0xC78, 0x0FA0831F}, + {0xC78, 0x0FA0841F}, {0xC78, 0x0FA0851F}, + {0xC78, 0x0F90861F}, {0xC78, 0x0F80871F}, + {0xC78, 0x0F70881F}, {0xC78, 0x0F60891F}, + {0xC78, 0x0F508A1F}, {0xC78, 0x0F408B1F}, + {0xC78, 0x0F308C1F}, {0xC78, 0x0F208D1F}, + {0xC78, 0x0F108E1F}, {0xC78, 0x0B908F1F}, + {0xC78, 0x0B80901F}, {0xC78, 0x0B70911F}, + {0xC78, 0x0B60921F}, {0xC78, 0x0B50931F}, + {0xC78, 0x0B40941F}, {0xC78, 0x0B30951F}, + {0xC78, 0x0B20961F}, {0xC78, 0x0B10971F}, + {0xC78, 0x0B00981F}, {0xC78, 0x0AF0991F}, + {0xC78, 0x0AE09A1F}, {0xC78, 0x0AD09B1F}, + {0xC78, 0x0AC09C1F}, {0xC78, 0x0AB09D1F}, + {0xC78, 0x0AA09E1F}, {0xC78, 0x0A909F1F}, + {0xC78, 0x0A80A01F}, {0xC78, 0x0A70A11F}, + {0xC78, 0x0A60A21F}, {0xC78, 0x0A50A31F}, + {0xC78, 0x0A40A41F}, {0xC78, 0x0A30A51F}, + {0xC78, 0x0A20A61F}, {0xC78, 0x0A10A71F}, + {0xC78, 0x0A00A81F}, {0xC78, 0x0830A91F}, + {0xC78, 0x0820AA1F}, {0xC78, 0x0810AB1F}, + {0xC78, 0x0800AC1F}, {0xC78, 0x0640AD1F}, + {0xC78, 0x0630AE1F}, {0xC78, 0x0620AF1F}, + {0xC78, 0x0610B01F}, {0xC78, 0x0600B11F}, + {0xC78, 0x0430B21F}, {0xC78, 0x0420B31F}, + {0xC78, 0x0410B41F}, {0xC78, 0x0400B51F}, + {0xC78, 0x0230B61F}, {0xC78, 0x0220B71F}, + {0xC78, 0x0210B81F}, {0xC78, 0x0200B91F}, + {0xC78, 0x0000BA1F}, {0xC78, 0x0000BB1F}, + {0xC78, 0x0000BC1F}, {0xC78, 0x0000BD1F}, + {0xC78, 0x0000BE1F}, {0xC78, 0x0000BF1F}, + {0xC50, 0x00E48024}, {0xC50, 0x00E48020}, + {0xffff, 0xffffffff} +}; + +static const struct rtl8xxxu_rfregval rtl8192fu_radioa_init_table[] = { + {0x00, 0x30000}, {0x18, 0x0FC07}, {0x81, 0x0FC00}, {0x82, 0x003C0}, + {0x84, 0x00005}, {0x86, 0xA33A5}, {0x87, 0x00000}, {0x88, 0x58010}, + {0x8E, 0x64540}, {0x8F, 0x282D8}, {0x51, 0x02C06}, {0x52, 0x7A007}, + {0x53, 0x10061}, {0x54, 0x60018}, {0x55, 0x82020}, {0x56, 0x08CC6}, + {0x57, 0x2CC00}, {0x58, 0x00000}, {0x5A, 0x50000}, {0x5B, 0x00006}, + {0x5C, 0x00015}, {0x65, 0x20000}, {0x6E, 0x38319}, {0xF5, 0x43180}, + {0xEF, 0x00002}, {0x33, 0x00301}, {0x33, 0x1032A}, {0x33, 0x2032A}, + {0xEF, 0x00000}, {0xDF, 0x00002}, {0x35, 0x00000}, {0xF0, 0x08008}, + {0xEF, 0x00800}, {0x33, 0x0040E}, {0x33, 0x04845}, {0x33, 0x08848}, + {0x33, 0x0C84B}, {0x33, 0x1088A}, {0x33, 0x14C50}, {0x33, 0x18C8E}, + {0x33, 0x1CCCD}, {0x33, 0x20CD0}, {0x33, 0x24CD3}, {0x33, 0x28CD6}, + {0x33, 0x4002B}, {0x33, 0x4402E}, {0x33, 0x48846}, {0x33, 0x4C849}, + {0x33, 0x50888}, {0x33, 0x54CC6}, {0x33, 0x58CC9}, {0x33, 0x5CCCC}, + {0x33, 0x60CCF}, {0x33, 0x64CD2}, {0x33, 0x68CD5}, {0xEF, 0x00000}, + {0xEF, 0x00400}, {0x33, 0x01C23}, {0x33, 0x05C23}, {0x33, 0x09D23}, + {0x33, 0x0DD23}, {0x33, 0x11FA3}, {0x33, 0x15FA3}, {0x33, 0x19FAB}, + {0x33, 0x1DFAB}, {0xEF, 0x00000}, {0xEF, 0x00200}, {0x33, 0x00030}, + {0x33, 0x04030}, {0x33, 0x08030}, {0x33, 0x0C030}, {0x33, 0x10030}, + {0x33, 0x14030}, {0x33, 0x18030}, {0x33, 0x1C030}, {0x33, 0x20030}, + {0x33, 0x24030}, {0x33, 0x28030}, {0x33, 0x2C030}, {0x33, 0x30030}, + {0x33, 0x34030}, {0x33, 0x38030}, {0x33, 0x3C030}, {0xEF, 0x00000}, + {0xEF, 0x00100}, {0x33, 0x44001}, {0x33, 0x48001}, {0x33, 0x4C001}, + {0x33, 0x50001}, {0x33, 0x54001}, {0x33, 0x58001}, {0x33, 0x5C001}, + {0x33, 0x60001}, {0x33, 0x64001}, {0x33, 0x68001}, {0x33, 0x6C001}, + {0x33, 0x70001}, {0x33, 0x74001}, {0x33, 0x78001}, {0x33, 0x04000}, + {0x33, 0x08000}, {0x33, 0x0C000}, {0x33, 0x10000}, {0x33, 0x14000}, + {0x33, 0x18001}, {0x33, 0x1C002}, {0x33, 0x20002}, {0x33, 0x24002}, + {0x33, 0x28002}, {0x33, 0x2C002}, {0x33, 0x30002}, {0x33, 0x34002}, + {0x33, 0x38002}, {0xEF, 0x00000}, {0x84, 0x00000}, {0xEF, 0x80010}, + {0x30, 0x20000}, {0x31, 0x0006F}, {0x32, 0x01FF7}, {0xEF, 0x00000}, + {0x84, 0x00000}, {0xEF, 0x80000}, {0x30, 0x30000}, {0x31, 0x0006F}, + {0x32, 0xF1DF3}, {0xEF, 0x00000}, {0x84, 0x00000}, {0xEF, 0x80000}, + {0x30, 0x38000}, {0x31, 0x0006F}, {0x32, 0xF1FF2}, {0xEF, 0x00000}, + {0x1B, 0x746CE}, {0xEF, 0x20000}, {0x33, 0x30000}, {0x33, 0x38000}, + {0x33, 0x70000}, {0x33, 0x78000}, {0xEF, 0x00000}, {0xDF, 0x08000}, + {0xB0, 0xFFBCB}, {0xB3, 0x06000}, {0xB7, 0x18DF0}, {0xB8, 0x38FF0}, + {0xC9, 0x00600}, {0xDF, 0x00000}, {0xB1, 0x33B8F}, {0xB2, 0x33762}, + {0xB4, 0x141F0}, {0xB5, 0x14080}, {0xB6, 0x12425}, {0xB9, 0xC0008}, + {0xBA, 0x40005}, {0xC2, 0x02C01}, {0xC3, 0x0000B}, {0xC4, 0x81E2F}, + {0xC5, 0x5C28F}, {0xC6, 0x000A0}, {0xCA, 0x02000}, {0xFE, 0x00000}, + {0x18, 0x08C07}, {0xFE, 0x00000}, {0xFE, 0x00000}, {0xFE, 0x00000}, + {0x00, 0x31DD5}, + {0xff, 0xffffffff} +}; + +static const struct rtl8xxxu_rfregval rtl8192fu_radiob_init_table[] = { + {0x00, 0x30000}, {0x81, 0x0FC00}, {0x82, 0x003C0}, {0x84, 0x00005}, + {0x86, 0xA33A5}, {0x87, 0x00000}, {0x88, 0x58010}, {0x8E, 0x64540}, + {0x8F, 0x282D8}, {0x51, 0x02C06}, {0x52, 0x7A007}, {0x53, 0x10061}, + {0x54, 0x60018}, {0x55, 0x82020}, {0x56, 0x08CC6}, {0x57, 0x2CC00}, + {0x58, 0x00000}, {0x5A, 0x50000}, {0x5B, 0x00006}, {0x5C, 0x00015}, + {0x65, 0x20000}, {0x6E, 0x38319}, {0xF5, 0x43180}, {0xEF, 0x00002}, + {0x33, 0x00301}, {0x33, 0x1032A}, {0x33, 0x2032A}, {0xEF, 0x00000}, + {0xDF, 0x00002}, {0x35, 0x00000}, {0xF0, 0x08008}, {0xEF, 0x00800}, + {0x33, 0x0040E}, {0x33, 0x04845}, {0x33, 0x08848}, {0x33, 0x0C84B}, + {0x33, 0x1088A}, {0x33, 0x14CC8}, {0x33, 0x18CCB}, {0x33, 0x1CCCE}, + {0x33, 0x20CD1}, {0x33, 0x24CD4}, {0x33, 0x28CD7}, {0x33, 0x4002B}, + {0x33, 0x4402E}, {0x33, 0x48846}, {0x33, 0x4C849}, {0x33, 0x50888}, + {0x33, 0x54CC6}, {0x33, 0x58CC9}, {0x33, 0x5CCCC}, {0x33, 0x60CCF}, + {0x33, 0x64CD2}, {0x33, 0x68CD5}, {0xEF, 0x00000}, {0xEF, 0x00400}, + {0x33, 0x01D23}, {0x33, 0x05D23}, {0x33, 0x09FA3}, {0x33, 0x0DFA3}, + {0x33, 0x11D2B}, {0x33, 0x15D2B}, {0x33, 0x19FAB}, {0x33, 0x1DFAB}, + {0xEF, 0x00000}, {0xEF, 0x00200}, {0x33, 0x00030}, {0x33, 0x04030}, + {0x33, 0x08030}, {0x33, 0x0C030}, {0x33, 0x10030}, {0x33, 0x14030}, + {0x33, 0x18030}, {0x33, 0x1C030}, {0x33, 0x20030}, {0x33, 0x24030}, + {0x33, 0x28030}, {0x33, 0x2C030}, {0x33, 0x30030}, {0x33, 0x34030}, + {0x33, 0x38030}, {0x33, 0x3C030}, {0xEF, 0x00000}, {0xEF, 0x00100}, + {0x33, 0x44000}, {0x33, 0x48000}, {0x33, 0x4C000}, {0x33, 0x50000}, + {0x33, 0x54000}, {0x33, 0x58000}, {0x33, 0x5C000}, {0x33, 0x60000}, + {0x33, 0x64000}, {0x33, 0x68000}, {0x33, 0x6C000}, {0x33, 0x70000}, + {0x33, 0x74000}, {0x33, 0x78000}, {0x33, 0x04000}, {0x33, 0x08000}, + {0x33, 0x0C000}, {0x33, 0x10000}, {0x33, 0x14000}, {0x33, 0x18000}, + {0x33, 0x1C001}, {0x33, 0x20001}, {0x33, 0x24001}, {0x33, 0x28001}, + {0x33, 0x2C001}, {0x33, 0x30001}, {0x33, 0x34001}, {0x33, 0x38001}, + {0xEF, 0x00000}, {0x84, 0x00000}, {0xEF, 0x80010}, {0x30, 0x20000}, + {0x31, 0x0006F}, {0x32, 0x01FF7}, {0xEF, 0x00000}, {0x84, 0x00000}, + {0xEF, 0x80000}, {0x30, 0x30000}, {0x31, 0x0006F}, {0x32, 0xF1DF3}, + {0xEF, 0x00000}, {0x84, 0x00000}, {0xEF, 0x80000}, {0x30, 0x38000}, + {0x31, 0x0006F}, {0x32, 0xF1FF2}, {0xEF, 0x00000}, {0x1B, 0x746CE}, + {0xEF, 0x20000}, {0x33, 0x30000}, {0x33, 0x38000}, {0x33, 0x70000}, + {0x33, 0x78000}, {0xEF, 0x00000}, {0x00, 0x31DD5}, + {0xff, 0xffffffff} +}; + +static int rtl8192fu_identify_chip(struct rtl8xxxu_priv *priv) +{ + struct device *dev = &priv->udev->dev; + u32 sys_cfg, vendor, val32; + + strscpy(priv->chip_name, "8192FU", sizeof(priv->chip_name)); + priv->rtl_chip = RTL8192F; + priv->rf_paths = 2; + priv->rx_paths = 2; + priv->tx_paths = 2; + + sys_cfg = rtl8xxxu_read32(priv, REG_SYS_CFG); + priv->chip_cut = u32_get_bits(sys_cfg, SYS_CFG_CHIP_VERSION_MASK); + if (sys_cfg & SYS_CFG_TRP_VAUX_EN) { + dev_info(dev, "Unsupported test chip\n"); + return -EOPNOTSUPP; + } + + val32 = rtl8xxxu_read32(priv, REG_MULTI_FUNC_CTRL); + priv->has_wifi = u32_get_bits(val32, MULTI_WIFI_FUNC_EN); + priv->has_bluetooth = u32_get_bits(val32, MULTI_BT_FUNC_EN); + priv->has_gps = u32_get_bits(val32, MULTI_GPS_FUNC_EN); + priv->is_multi_func = 1; + + vendor = sys_cfg & SYS_CFG_VENDOR_ID; + rtl8xxxu_identify_vendor_1bit(priv, vendor); + + val32 = rtl8xxxu_read32(priv, REG_GPIO_OUTSTS); + priv->rom_rev = u32_get_bits(val32, GPIO_RF_RL_ID); + + return rtl8xxxu_config_endpoints_no_sie(priv); +} + +static void +rtl8192f_set_tx_power(struct rtl8xxxu_priv *priv, int channel, bool ht40) +{ + u8 cck, ofdmbase, mcsbase; + u32 val32, ofdm, mcs; + int group, cck_group; + + rtl8188f_channel_to_group(channel, &group, &cck_group); + + cck = priv->cck_tx_power_index_A[cck_group]; + + rtl8xxxu_write32_mask(priv, REG_TX_AGC_A_CCK1_MCS32, 0x00007f00, cck); + + val32 = (cck << 16) | (cck << 8) | cck; + rtl8xxxu_write32_mask(priv, REG_TX_AGC_B_CCK11_A_CCK2_11, + 0x7f7f7f00, val32); + + ofdmbase = priv->ht40_1s_tx_power_index_A[group]; + ofdmbase += priv->ofdm_tx_power_diff[RF_A].a; + ofdm = ofdmbase | ofdmbase << 8 | ofdmbase << 16 | ofdmbase << 24; + + rtl8xxxu_write32_mask(priv, REG_TX_AGC_A_RATE18_06, 0x7f7f7f7f, ofdm); + rtl8xxxu_write32_mask(priv, REG_TX_AGC_A_RATE54_24, 0x7f7f7f7f, ofdm); + + mcsbase = priv->ht40_1s_tx_power_index_A[group]; + if (ht40) + mcsbase += priv->ht40_tx_power_diff[RF_A].a; + else + mcsbase += priv->ht20_tx_power_diff[RF_A].a; + mcs = mcsbase | mcsbase << 8 | mcsbase << 16 | mcsbase << 24; + + rtl8xxxu_write32_mask(priv, REG_TX_AGC_A_MCS03_MCS00, 0x7f7f7f7f, mcs); + rtl8xxxu_write32_mask(priv, REG_TX_AGC_A_MCS07_MCS04, 0x7f7f7f7f, mcs); + rtl8xxxu_write32_mask(priv, REG_TX_AGC_A_MCS11_MCS08, 0x7f7f7f7f, mcs); + rtl8xxxu_write32_mask(priv, REG_TX_AGC_A_MCS15_MCS12, 0x7f7f7f7f, mcs); + + if (priv->tx_paths == 1) + return; + + cck = priv->cck_tx_power_index_B[cck_group]; + + val32 = (cck << 16) | (cck << 8) | cck; + rtl8xxxu_write32_mask(priv, REG_TX_AGC_B_CCK1_55_MCS32, + 0x7f7f7f00, val32); + + rtl8xxxu_write32_mask(priv, REG_TX_AGC_B_CCK11_A_CCK2_11, + 0x0000007f, cck); + + ofdmbase = priv->ht40_1s_tx_power_index_B[group]; + ofdmbase += priv->ofdm_tx_power_diff[RF_B].b; + ofdm = ofdmbase | ofdmbase << 8 | ofdmbase << 16 | ofdmbase << 24; + + rtl8xxxu_write32_mask(priv, REG_TX_AGC_B_RATE18_06, 0x7f7f7f7f, ofdm); + rtl8xxxu_write32_mask(priv, REG_TX_AGC_B_RATE54_24, 0x7f7f7f7f, ofdm); + + mcsbase = priv->ht40_1s_tx_power_index_B[group]; + if (ht40) + mcsbase += priv->ht40_tx_power_diff[RF_B].b; + else + mcsbase += priv->ht20_tx_power_diff[RF_B].b; + mcs = mcsbase | mcsbase << 8 | mcsbase << 16 | mcsbase << 24; + + rtl8xxxu_write32_mask(priv, REG_TX_AGC_B_MCS03_MCS00, 0x7f7f7f7f, mcs); + rtl8xxxu_write32_mask(priv, REG_TX_AGC_B_MCS07_MCS04, 0x7f7f7f7f, mcs); + rtl8xxxu_write32_mask(priv, REG_TX_AGC_B_MCS11_MCS08, 0x7f7f7f7f, mcs); + rtl8xxxu_write32_mask(priv, REG_TX_AGC_B_MCS15_MCS12, 0x7f7f7f7f, mcs); +} + +static void rtl8192f_revise_cck_tx_psf(struct rtl8xxxu_priv *priv, u8 channel) +{ + if (channel == 13) { + /* Special value for channel 13 */ + rtl8xxxu_write32(priv, REG_CCK0_TX_FILTER1, 0xf8fe0001); + /* Normal values */ + rtl8xxxu_write32(priv, REG_CCK0_TX_FILTER2, 0x64B80C1C); + rtl8xxxu_write16(priv, REG_CCK0_DEBUG_PORT, 0x8810); + rtl8xxxu_write32(priv, REG_CCK0_TX_FILTER3, 0x01235667); + } else if (channel == 14) { + /* Normal value */ + rtl8xxxu_write32(priv, REG_CCK0_TX_FILTER1, 0xE82C0001); + /* Special values for channel 14 */ + rtl8xxxu_write32(priv, REG_CCK0_TX_FILTER2, 0x0000B81C); + rtl8xxxu_write16(priv, REG_CCK0_DEBUG_PORT, 0x0000); + rtl8xxxu_write32(priv, REG_CCK0_TX_FILTER3, 0x00003667); + } else { + /* Restore normal values from the phy init table */ + rtl8xxxu_write32(priv, REG_CCK0_TX_FILTER1, 0xE82C0001); + rtl8xxxu_write32(priv, REG_CCK0_TX_FILTER2, 0x64B80C1C); + rtl8xxxu_write16(priv, REG_CCK0_DEBUG_PORT, 0x8810); + rtl8xxxu_write32(priv, REG_CCK0_TX_FILTER3, 0x01235667); + } +} + +static void rtl8192fu_config_kfree(struct rtl8xxxu_priv *priv, u8 channel) +{ + u8 bb_gain[3] = { EFUSE_UNDEFINED, EFUSE_UNDEFINED, EFUSE_UNDEFINED }; + u8 bb_gain_path_mask[2] = { 0x0f, 0xf0 }; + enum rtl8xxxu_rfpath rfpath; + u8 bb_gain_for_path; + u8 channel_idx = 0; + + if (channel >= 1 && channel <= 3) + channel_idx = 0; + if (channel >= 4 && channel <= 9) + channel_idx = 1; + if (channel >= 10 && channel <= 14) + channel_idx = 2; + + rtl8xxxu_read_efuse8(priv, 0x1ee, &bb_gain[1]); + rtl8xxxu_read_efuse8(priv, 0x1ec, &bb_gain[0]); + rtl8xxxu_read_efuse8(priv, 0x1ea, &bb_gain[2]); + + if (bb_gain[1] == EFUSE_UNDEFINED) + return; + + if (bb_gain[0] == EFUSE_UNDEFINED) + bb_gain[0] = bb_gain[1]; + + if (bb_gain[2] == EFUSE_UNDEFINED) + bb_gain[2] = bb_gain[1]; + + for (rfpath = RF_A; rfpath < priv->rf_paths; rfpath++) { + /* power_trim based on 55[19:14] */ + rtl8xxxu_write_rfreg_mask(priv, rfpath, RF6052_REG_UNKNOWN_55, + BIT(5), 1); + + /* enable 55[14] for 0.5db step */ + rtl8xxxu_write_rfreg_mask(priv, rfpath, RF6052_REG_GAIN_CTRL, + BIT(18), 1); + + /* enter power_trim debug mode */ + rtl8xxxu_write_rfreg_mask(priv, rfpath, RF6052_REG_GAIN_CCA, + BIT(7), 1); + + /* write enable */ + rtl8xxxu_write_rfreg_mask(priv, rfpath, RF6052_REG_WE_LUT, BIT(7), 1); + + bb_gain_for_path = (bb_gain[channel_idx] & bb_gain_path_mask[rfpath]); + bb_gain_for_path >>= __ffs(bb_gain_path_mask[rfpath]); + + rtl8xxxu_write_rfreg_mask(priv, rfpath, RF6052_REG_TXPA_G3, + 0x70000, channel_idx * 2); + rtl8xxxu_write_rfreg_mask(priv, rfpath, RF6052_REG_TXPA_G3, + 0x3f, bb_gain_for_path); + + rtl8xxxu_write_rfreg_mask(priv, rfpath, RF6052_REG_TXPA_G3, + 0x70000, channel_idx * 2 + 1); + rtl8xxxu_write_rfreg_mask(priv, rfpath, RF6052_REG_TXPA_G3, + 0x3f, bb_gain_for_path); + + /* leave power_trim debug mode */ + rtl8xxxu_write_rfreg_mask(priv, rfpath, RF6052_REG_GAIN_CCA, + BIT(7), 0); + + /* write disable */ + rtl8xxxu_write_rfreg_mask(priv, rfpath, RF6052_REG_WE_LUT, BIT(7), 0); + } +} + +static void rtl8192fu_config_channel(struct ieee80211_hw *hw) +{ + struct rtl8xxxu_priv *priv = hw->priv; + bool ht40 = conf_is_ht40(&hw->conf); + u8 channel, subchannel = 0; + bool sec_ch_above = 0; + u32 val32; + + channel = (u8)hw->conf.chandef.chan->hw_value; + + if (conf_is_ht40_plus(&hw->conf)) { + sec_ch_above = 1; + channel += 2; + subchannel = 2; + } else if (conf_is_ht40_minus(&hw->conf)) { + sec_ch_above = 0; + channel -= 2; + subchannel = 1; + } + + val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_MODE_AG); + + rtl8192f_revise_cck_tx_psf(priv, channel); + + /* Set channel */ + val32 &= ~(BIT(18) | BIT(17)); /* select the 2.4G band(?) */ + u32p_replace_bits(&val32, channel, 0xff); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_MODE_AG, val32); + if (priv->rf_paths > 1) + rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_MODE_AG, val32); + + rtl8192fu_config_kfree(priv, channel); + + rtl8xxxu_write8(priv, REG_DATA_SUBCHANNEL, subchannel); + + /* small BW */ + rtl8xxxu_write32_clear(priv, REG_OFDM0_TX_PSDO_NOISE_WEIGHT, GENMASK(31, 30)); + + rtl8xxxu_write32_mask(priv, REG_FPGA0_RF_MODE, FPGA_RF_MODE, ht40); + rtl8xxxu_write32_mask(priv, REG_FPGA1_RF_MODE, FPGA_RF_MODE, ht40); + + /* ADC clock = 160M */ + rtl8xxxu_write32_mask(priv, REG_FPGA0_RF_MODE, GENMASK(10, 8), 4); + + /* DAC clock = 80M */ + rtl8xxxu_write32_mask(priv, REG_FPGA0_RF_MODE, BIT(13) | BIT(12), 2); + + /* ADC buffer clk */ + rtl8xxxu_write32_mask(priv, REG_ANTDIV_PARA1, BIT(27) | BIT(26), 2); + + if (ht40) + /* Set Control channel to upper or lower. */ + rtl8xxxu_write32_mask(priv, REG_CCK0_SYSTEM, + CCK0_SIDEBAND, !sec_ch_above); + + /* Enable CCK */ + rtl8xxxu_write32_set(priv, REG_FPGA0_RF_MODE, FPGA_RF_MODE_CCK); + + /* RF TRX_BW */ + val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_MODE_AG); + val32 &= ~MODE_AG_BW_MASK; + if (ht40) + val32 |= MODE_AG_BW_40MHZ_8723B; + else + val32 |= MODE_AG_BW_20MHZ_8723B; + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_MODE_AG, val32); + if (priv->rf_paths > 1) + rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_MODE_AG, val32); + + /* Modify RX DFIR parameters */ + rtl8xxxu_write32_mask(priv, REG_TAP_UPD_97F, BIT(21) | BIT(20), 2); + + rtl8xxxu_write32_mask(priv, REG_DOWNSAM_FACTOR, BIT(29) | BIT(28), 2); + + if (ht40) + val32 = 0x3; + else + val32 = 0x1a3; + rtl8xxxu_write32_mask(priv, REG_RX_DFIR_MOD_97F, 0x1ff, val32); +} + +static void rtl8192fu_init_aggregation(struct rtl8xxxu_priv *priv) +{ + u32 agg_rx; + u8 agg_ctrl; + + /* RX aggregation */ + agg_ctrl = rtl8xxxu_read8(priv, REG_TRXDMA_CTRL); + agg_ctrl &= ~TRXDMA_CTRL_RXDMA_AGG_EN; + + agg_rx = rtl8xxxu_read32(priv, REG_RXDMA_AGG_PG_TH); + agg_rx &= ~RXDMA_USB_AGG_ENABLE; + agg_rx &= ~0xFF0F; /* reset agg size and timeout */ + + rtl8xxxu_write8(priv, REG_TRXDMA_CTRL, agg_ctrl); + rtl8xxxu_write32(priv, REG_RXDMA_AGG_PG_TH, agg_rx); +} + +static int rtl8192fu_parse_efuse(struct rtl8xxxu_priv *priv) +{ + struct rtl8192fu_efuse *efuse = &priv->efuse_wifi.efuse8192fu; + int i; + + if (efuse->rtl_id != cpu_to_le16(0x8129)) + return -EINVAL; + + ether_addr_copy(priv->mac_addr, efuse->mac_addr); + + memcpy(priv->cck_tx_power_index_A, efuse->tx_power_index_A.cck_base, + sizeof(efuse->tx_power_index_A.cck_base)); + memcpy(priv->cck_tx_power_index_B, efuse->tx_power_index_B.cck_base, + sizeof(efuse->tx_power_index_B.cck_base)); + + memcpy(priv->ht40_1s_tx_power_index_A, + efuse->tx_power_index_A.ht40_base, + sizeof(efuse->tx_power_index_A.ht40_base)); + memcpy(priv->ht40_1s_tx_power_index_B, + efuse->tx_power_index_B.ht40_base, + sizeof(efuse->tx_power_index_B.ht40_base)); + + priv->ht20_tx_power_diff[0].a = + efuse->tx_power_index_A.ht20_ofdm_1s_diff.b; + priv->ht20_tx_power_diff[0].b = + efuse->tx_power_index_B.ht20_ofdm_1s_diff.b; + + priv->ht40_tx_power_diff[0].a = 0; + priv->ht40_tx_power_diff[0].b = 0; + + for (i = 1; i < RTL8723B_TX_COUNT; i++) { + priv->ofdm_tx_power_diff[i].a = + efuse->tx_power_index_A.pwr_diff[i - 1].ofdm; + priv->ofdm_tx_power_diff[i].b = + efuse->tx_power_index_B.pwr_diff[i - 1].ofdm; + + priv->ht20_tx_power_diff[i].a = + efuse->tx_power_index_A.pwr_diff[i - 1].ht20; + priv->ht20_tx_power_diff[i].b = + efuse->tx_power_index_B.pwr_diff[i - 1].ht20; + + priv->ht40_tx_power_diff[i].a = + efuse->tx_power_index_A.pwr_diff[i - 1].ht40; + priv->ht40_tx_power_diff[i].b = + efuse->tx_power_index_B.pwr_diff[i - 1].ht40; + } + + priv->default_crystal_cap = efuse->xtal_k & 0x3f; + + priv->rfe_type = efuse->rfe_option & 0x1f; + + if (priv->rfe_type != 5 && priv->rfe_type != 1) + dev_warn(&priv->udev->dev, + "%s: RFE type %d was not tested. Please send an email to linux-wireless@vger.kernel.org about this.\n", + __func__, priv->rfe_type); + + return 0; +} + +static int rtl8192fu_load_firmware(struct rtl8xxxu_priv *priv) +{ + return rtl8xxxu_load_firmware(priv, "rtlwifi/rtl8192fufw.bin"); +} + +static void rtl8192fu_init_phy_bb(struct rtl8xxxu_priv *priv) +{ + /* Enable BB and RF */ + rtl8xxxu_write16_set(priv, REG_SYS_FUNC, + SYS_FUNC_BBRSTB | SYS_FUNC_BB_GLB_RSTN); + + rtl8xxxu_write8(priv, REG_RF_CTRL, RF_ENABLE | RF_RSTB | RF_SDMRSTB); + + /* To Fix MAC loopback mode fail. */ + rtl8xxxu_write8(priv, REG_LDOHCI12_CTRL, 0xf); + rtl8xxxu_write8(priv, REG_SYS_SWR_CTRL2 + 1, 0xe9); + + rtl8xxxu_init_phy_regs(priv, rtl8192fu_phy_init_table); + + rtl8xxxu_init_phy_regs(priv, rtl8192f_agc_table); +} + +static int rtl8192fu_init_phy_rf(struct rtl8xxxu_priv *priv) +{ + int ret; + + ret = rtl8xxxu_init_phy_rf(priv, rtl8192fu_radioa_init_table, RF_A); + if (ret) + return ret; + + return rtl8xxxu_init_phy_rf(priv, rtl8192fu_radiob_init_table, RF_B); +} + +static void rtl8192f_phy_lc_calibrate(struct rtl8xxxu_priv *priv) +{ + u32 backup_mask = BIT(31) | BIT(30); + u32 backup; + u32 val32; + + /* Aries's NarrowBand */ + val32 = rtl8xxxu_read32(priv, REG_OFDM0_TX_PSDO_NOISE_WEIGHT); + backup = u32_get_bits(val32, backup_mask); + + u32p_replace_bits(&val32, 0, backup_mask); + rtl8xxxu_write32(priv, REG_OFDM0_TX_PSDO_NOISE_WEIGHT, val32); + + rtl8188f_phy_lc_calibrate(priv); + + /* Aries's NarrowBand */ + val32 = rtl8xxxu_read32(priv, REG_OFDM0_TX_PSDO_NOISE_WEIGHT); + u32p_replace_bits(&val32, backup, backup_mask); + rtl8xxxu_write32(priv, REG_OFDM0_TX_PSDO_NOISE_WEIGHT, val32); + + /* reset OFDM state */ + rtl8xxxu_write32_clear(priv, REG_FPGA0_RF_MODE, FPGA_RF_MODE_OFDM); + rtl8xxxu_write32_set(priv, REG_FPGA0_RF_MODE, FPGA_RF_MODE_OFDM); +} + +static int rtl8192fu_iqk_path_a(struct rtl8xxxu_priv *priv) +{ + u32 reg_eac, reg_e94, reg_e9c, val32; + u32 rf_0x58_i, rf_0x58_q; + u8 rfe = priv->rfe_type; + int result = 0; + int ktime, i; + + /* Leave IQK mode */ + rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0); + + rtl8xxxu_write32(priv, REG_FPGA0_ANALOG4, 0xccf000c0); + rtl8xxxu_write32(priv, REG_ANAPWR1, 0x44ffbb44); + rtl8xxxu_write32(priv, REG_RX_WAIT_CCA, 0x00400040); + rtl8xxxu_write32(priv, REG_OFDM0_TRX_PATH_ENABLE, 0x6f005403); + rtl8xxxu_write32(priv, REG_OFDM0_TR_MUX_PAR, 0x000804e4); + rtl8xxxu_write32(priv, REG_FPGA0_XCD_RF_SW_CTRL, 0x04203400); + rtl8xxxu_write32(priv, REG_FPGA0_XA_HSSI_PARM1, 0x01000100); + + rtl8xxxu_write_rfreg_mask(priv, RF_A, RF6052_REG_GAIN_CCA, BIT(4), 1); + rtl8xxxu_write_rfreg_mask(priv, RF_A, RF6052_REG_GAIN_CCA, BIT(11), 1); + if (rfe == 7 || rfe == 8 || rfe == 9 || rfe == 12) + val32 = 0x30; + else + val32 = 0xe9; + rtl8xxxu_write_rfreg_mask(priv, RF_A, RF6052_REG_PAD_TXG, 0x003ff, val32); + + rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0x808000); + + /* path-A IQK setting */ + rtl8xxxu_write32(priv, REG_TX_IQK_TONE_A, 0x18008c1c); + rtl8xxxu_write32(priv, REG_RX_IQK_TONE_A, 0x38008c1c); + rtl8xxxu_write32(priv, REG_TX_IQK_TONE_B, 0x38008c1c); + rtl8xxxu_write32(priv, REG_RX_IQK_TONE_B, 0x38008c1c); + + rtl8xxxu_write32(priv, REG_TX_IQK_PI_A, 0x8214000f); + rtl8xxxu_write32(priv, REG_RX_IQK_PI_A, 0x28140000); + + rtl8xxxu_write32(priv, REG_TX_IQK, 0x01007c00); + rtl8xxxu_write32(priv, REG_RX_IQK, 0x01004800); + + /* LO calibration setting */ + rtl8xxxu_write32(priv, REG_IQK_AGC_RSP, 0x00e62911); + + /* One shot, path A LOK & IQK */ + rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xfa005800); + rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xf8005800); + + mdelay(15); + + ktime = 0; + while (rtl8xxxu_read32(priv, REG_IQK_RPT_TXA) == 0 && ktime < 21) { + mdelay(5); + ktime += 5; + } + + /* Check failed */ + reg_eac = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_A_2); + reg_e94 = rtl8xxxu_read32(priv, REG_TX_POWER_BEFORE_IQK_A); + reg_e9c = rtl8xxxu_read32(priv, REG_TX_POWER_AFTER_IQK_A); + + /* reload 0xdf and CCK_IND off */ + rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0); + + rtl8xxxu_write_rfreg_mask(priv, RF_A, RF6052_REG_WE_LUT, BIT(4), 1); + + val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_TXMOD); + rf_0x58_i = u32_get_bits(val32, 0xfc000); + rf_0x58_q = u32_get_bits(val32, 0x003f0); + + for (i = 0; i < 8; i++) { + rtl8xxxu_write_rfreg_mask(priv, RF_A, RF6052_REG_TXPA_G3, + 0x1c000, i); + rtl8xxxu_write_rfreg_mask(priv, RF_A, RF6052_REG_TXPA_G3, + 0x00fc0, rf_0x58_i); + rtl8xxxu_write_rfreg_mask(priv, RF_A, RF6052_REG_TXPA_G3, + 0x0003f, rf_0x58_q); + } + + rtl8xxxu_write_rfreg_mask(priv, RF_A, RF6052_REG_AC, BIT(14), 0); + rtl8xxxu_write_rfreg_mask(priv, RF_A, RF6052_REG_WE_LUT, BIT(4), 0); + rtl8xxxu_write_rfreg_mask(priv, RF_A, RF6052_REG_GAIN_CCA, 0x00810, 0); + + if (!(reg_eac & BIT(28)) && + ((reg_e94 & 0x03ff0000) != 0x01420000) && + ((reg_e9c & 0x03ff0000) != 0x00420000)) + result |= 0x01; + + return result; +} + +static int rtl8192fu_rx_iqk_path_a(struct rtl8xxxu_priv *priv) +{ + u32 reg_ea4, reg_eac, reg_e94, reg_e9c, val32; + int result = 0; + int ktime; + + /* Leave IQK mode */ + rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0); + + /* PA/PAD control by 0x56, and set = 0x0 */ + rtl8xxxu_write_rfreg_mask(priv, RF_A, RF6052_REG_GAIN_CCA, BIT(1), 1); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_P1, 0); + rtl8xxxu_write_rfreg_mask(priv, RF_A, RF6052_REG_GAIN_CCA, BIT(11), 1); + rtl8xxxu_write_rfreg_mask(priv, RF_A, RF6052_REG_PAD_TXG, 0x003ff, 0x27); + + /* Enter IQK mode */ + rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0x808000); + + /* path-A IQK setting */ + rtl8xxxu_write32(priv, REG_TX_IQK_TONE_A, 0x18008c1c); + rtl8xxxu_write32(priv, REG_RX_IQK_TONE_A, 0x38008c1c); + rtl8xxxu_write32(priv, REG_TX_IQK_TONE_B, 0x38008c1c); + rtl8xxxu_write32(priv, REG_RX_IQK_TONE_B, 0x38008c1c); + + rtl8xxxu_write32(priv, REG_TX_IQK_PI_A, 0x82160027); + rtl8xxxu_write32(priv, REG_RX_IQK_PI_A, 0x28160000); + + /* Tx IQK setting */ + rtl8xxxu_write32(priv, REG_TX_IQK, 0x01007c00); + rtl8xxxu_write32(priv, REG_RX_IQK, 0x01004800); + + /* LO calibration setting */ + rtl8xxxu_write32(priv, REG_IQK_AGC_RSP, 0x0086a911); + + /* One shot, path A LOK & IQK */ + rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xfa005800); + rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xf8005800); + + mdelay(15); + + ktime = 0; + while (rtl8xxxu_read32(priv, REG_IQK_RPT_TXA) == 0 && ktime < 21) { + mdelay(5); + ktime += 5; + } + + /* Check failed */ + reg_eac = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_A_2); + reg_e94 = rtl8xxxu_read32(priv, REG_TX_POWER_BEFORE_IQK_A); + reg_e9c = rtl8xxxu_read32(priv, REG_TX_POWER_AFTER_IQK_A); + + if (!(reg_eac & BIT(28)) && + ((reg_e94 & 0x03ff0000) != 0x01420000) && + ((reg_e9c & 0x03ff0000) != 0x00420000)) { + result |= 0x01; + } else { /* If TX not OK, ignore RX */ + /* PA/PAD controlled by 0x0 */ + rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0); + + rtl8xxxu_write_rfreg_mask(priv, RF_A, RF6052_REG_GAIN_CCA, + BIT(11), 0); + + return result; + } + + val32 = 0x80007c00 | (reg_e94 & 0x3ff0000) | ((reg_e9c & 0x3ff0000) >> 16); + rtl8xxxu_write32(priv, REG_TX_IQK, val32); + + /* Modify RX IQK mode table */ + rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0); + + /* PA/PAD control by 0x56, and set = 0x0 */ + rtl8xxxu_write_rfreg_mask(priv, RF_A, RF6052_REG_GAIN_CCA, BIT(1), 1); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_P1, 0); + rtl8xxxu_write_rfreg_mask(priv, RF_A, RF6052_REG_GAIN_CCA, BIT(11), 1); + rtl8xxxu_write_rfreg_mask(priv, RF_A, RF6052_REG_PAD_TXG, 0x003ff, 0x1e0); + + rtl8xxxu_write32(priv, REG_FPGA0_ANALOG4, 0xccf000c0); + rtl8xxxu_write32(priv, REG_ANAPWR1, 0x44ffbb44); + rtl8xxxu_write32(priv, REG_RX_WAIT_CCA, 0x00400040); + rtl8xxxu_write32(priv, REG_OFDM0_TRX_PATH_ENABLE, 0x6f005403); + rtl8xxxu_write32(priv, REG_OFDM0_TR_MUX_PAR, 0x000804e4); + rtl8xxxu_write32(priv, REG_FPGA0_XCD_RF_SW_CTRL, 0x04203400); + rtl8xxxu_write32(priv, REG_FPGA0_XA_HSSI_PARM1, 0x01000100); + + /* Enter IQK mode */ + rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0x808000); + + /* path-A IQK setting */ + rtl8xxxu_write32(priv, REG_TX_IQK_TONE_A, 0x38008c1c); + rtl8xxxu_write32(priv, REG_RX_IQK_TONE_A, 0x18008c1c); + rtl8xxxu_write32(priv, REG_TX_IQK_TONE_B, 0x38008c1c); + rtl8xxxu_write32(priv, REG_RX_IQK_TONE_B, 0x38008c1c); + + rtl8xxxu_write32(priv, REG_TX_IQK_PI_A, 0x82170000); + rtl8xxxu_write32(priv, REG_RX_IQK_PI_A, 0x28170000); + + /* RX IQK setting */ + rtl8xxxu_write32(priv, REG_RX_IQK, 0x01004800); + + /* LO calibration setting */ + rtl8xxxu_write32(priv, REG_IQK_AGC_RSP, 0x0046a8d1); + + /* One shot, path A LOK & IQK */ + rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xfa005800); + rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xf8005800); + + mdelay(15); + + ktime = 0; + while (rtl8xxxu_read32(priv, REG_IQK_RPT_RXA) == 0 && ktime < 21) { + mdelay(5); + ktime += 5; + } + + /* Check failed */ + reg_eac = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_A_2); + reg_ea4 = rtl8xxxu_read32(priv, REG_RX_POWER_BEFORE_IQK_A_2); + + /* Leave IQK mode */ + rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0); + + rtl8xxxu_write_rfreg_mask(priv, RF_A, RF6052_REG_GAIN_CCA, BIT(11), 0); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_P1, 0x02000); + + if (!(reg_eac & BIT(27)) && + ((reg_ea4 & 0x03ff0000) != 0x01320000) && + ((reg_eac & 0x03ff0000) != 0x00360000)) + result |= 0x02; + + return result; +} + +static int rtl8192fu_iqk_path_b(struct rtl8xxxu_priv *priv) +{ + u32 reg_eac, reg_eb4, reg_ebc, val32; + u32 rf_0x58_i, rf_0x58_q; + u8 rfe = priv->rfe_type; + int result = 0; + int ktime, i; + + /* PA/PAD controlled by 0x0 */ + rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0); + + rtl8xxxu_write32(priv, REG_FPGA0_ANALOG4, 0xccf000c0); + rtl8xxxu_write32(priv, REG_ANAPWR1, 0x44ffbb44); + rtl8xxxu_write32(priv, REG_RX_WAIT_CCA, 0x00400040); + rtl8xxxu_write32(priv, REG_OFDM0_TRX_PATH_ENABLE, 0x6f005403); + rtl8xxxu_write32(priv, REG_OFDM0_TR_MUX_PAR, 0x000804e4); + rtl8xxxu_write32(priv, REG_FPGA0_XCD_RF_SW_CTRL, 0x04203400); + rtl8xxxu_write32(priv, REG_FPGA0_XA_HSSI_PARM1, 0x01000000); + + rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_GAIN_CCA, BIT(4), 1); + rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_GAIN_CCA, BIT(11), 1); + if (rfe == 7 || rfe == 8 || rfe == 9 || rfe == 12) + rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_PAD_TXG, + 0x003ff, 0x30); + else + rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_PAD_TXG, + 0x00fff, 0xe9); + + rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0x808000); + + /* Path B IQK setting */ + rtl8xxxu_write32(priv, REG_TX_IQK_TONE_A, 0x38008c1c); + rtl8xxxu_write32(priv, REG_RX_IQK_TONE_A, 0x38008c1c); + rtl8xxxu_write32(priv, REG_TX_IQK_TONE_B, 0x18008c1c); + rtl8xxxu_write32(priv, REG_RX_IQK_TONE_B, 0x38008c1c); + + rtl8xxxu_write32(priv, REG_TX_IQK_PI_B, 0x8214000F); + rtl8xxxu_write32(priv, REG_RX_IQK_PI_B, 0x28140000); + + rtl8xxxu_write32(priv, REG_TX_IQK, 0x01007c00); + rtl8xxxu_write32(priv, REG_RX_IQK, 0x01004800); + + /* LO calibration setting */ + rtl8xxxu_write32(priv, REG_IQK_AGC_RSP, 0x00e62911); + + /* One shot, path B LOK & IQK */ + rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xfa005800); + rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xf8005800); + + mdelay(15); + + ktime = 0; + while (rtl8xxxu_read32(priv, REG_IQK_RPT_TXB) == 0 && ktime < 21) { + mdelay(5); + ktime += 5; + } + + /* Check failed */ + reg_eac = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_A_2); + reg_eb4 = rtl8xxxu_read32(priv, REG_TX_POWER_BEFORE_IQK_B); + reg_ebc = rtl8xxxu_read32(priv, REG_TX_POWER_AFTER_IQK_B); + + /* reload 0xdf and CCK_IND off */ + rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0); + + rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_WE_LUT, BIT(4), 1); + + val32 = rtl8xxxu_read_rfreg(priv, RF_B, RF6052_REG_TXMOD); + rf_0x58_i = u32_get_bits(val32, 0xfc000); + rf_0x58_q = u32_get_bits(val32, 0x003f0); + + for (i = 0; i < 8; i++) { + rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_TXPA_G3, + 0x1c000, i); + rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_TXPA_G3, + 0x00fc0, rf_0x58_i); + rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_TXPA_G3, + 0x0003f, rf_0x58_q); + } + + rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_AC, BIT(14), 0); + rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_WE_LUT, BIT(4), 0); + rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_GAIN_CCA, 0x00810, 0); + + if (!(reg_eac & BIT(31)) && + ((reg_eb4 & 0x03ff0000) != 0x01420000) && + ((reg_ebc & 0x03ff0000) != 0x00420000)) + result |= 0x01; + else + dev_warn(&priv->udev->dev, "%s: Path B IQK failed!\n", + __func__); + + return result; +} + +static int rtl8192fu_rx_iqk_path_b(struct rtl8xxxu_priv *priv) +{ + u32 reg_eac, reg_eb4, reg_ebc, reg_ec4, reg_ecc, val32; + int result = 0; + int ktime; + + /* Leave IQK mode */ + rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0); + + rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_GAIN_CCA, BIT(1), 1); + rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_GAIN_P1, 0); + rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_GAIN_CCA, BIT(11), 1); + rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_PAD_TXG, 0x003ff, 0x67); + + rtl8xxxu_write32(priv, REG_FPGA0_ANALOG4, 0xccf000c0); + rtl8xxxu_write32(priv, REG_ANAPWR1, 0x44ffbb44); + rtl8xxxu_write32(priv, REG_RX_WAIT_CCA, 0x00400040); + rtl8xxxu_write32(priv, REG_OFDM0_TRX_PATH_ENABLE, 0x6f005403); + rtl8xxxu_write32(priv, REG_OFDM0_TR_MUX_PAR, 0x000804e4); + rtl8xxxu_write32(priv, REG_FPGA0_XCD_RF_SW_CTRL, 0x04203400); + rtl8xxxu_write32(priv, REG_FPGA0_XA_HSSI_PARM1, 0x01000000); + + rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0x808000); + + /* path-B IQK setting */ + rtl8xxxu_write32(priv, REG_TX_IQK_TONE_A, 0x38008c1c); + rtl8xxxu_write32(priv, REG_RX_IQK_TONE_A, 0x38008c1c); + rtl8xxxu_write32(priv, REG_TX_IQK_TONE_B, 0x18008c1c); + rtl8xxxu_write32(priv, REG_RX_IQK_TONE_B, 0x38008c1c); + + rtl8xxxu_write32(priv, REG_TX_IQK_PI_B, 0x82160027); + rtl8xxxu_write32(priv, REG_RX_IQK_PI_B, 0x28160000); + + /* LO calibration setting */ + rtl8xxxu_write32(priv, REG_IQK_AGC_RSP, 0x0086a911); + + /* One shot, path A LOK & IQK */ + rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xfa005800); + rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xf8005800); + + mdelay(15); + + ktime = 0; + while (rtl8xxxu_read32(priv, REG_IQK_RPT_TXB) == 0 && ktime < 21) { + mdelay(5); + ktime += 5; + } + + /* Check failed */ + reg_eac = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_A_2); + reg_eb4 = rtl8xxxu_read32(priv, REG_TX_POWER_BEFORE_IQK_B); + reg_ebc = rtl8xxxu_read32(priv, REG_TX_POWER_AFTER_IQK_B); + + if (!(reg_eac & BIT(31)) && + ((reg_eb4 & 0x03ff0000) != 0x01420000) && + ((reg_ebc & 0x03ff0000) != 0x00420000)) { + result |= 0x01; + } else { + /* PA/PAD controlled by 0x0 */ + rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0); + + rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_GAIN_CCA, + BIT(11), 0); + + return result; + } + + val32 = 0x80007c00 | (reg_eb4 & 0x03ff0000) | ((reg_ebc >> 16) & 0x03ff); + rtl8xxxu_write32(priv, REG_TX_IQK, val32); + + /* Modify RX IQK mode table */ + rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0); + + rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_GAIN_CCA, BIT(1), 1); + rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_GAIN_P1, 0); + rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_GAIN_CCA, BIT(11), 1); + rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_PAD_TXG, 0x003ff, 0x1e0); + + rtl8xxxu_write32(priv, REG_FPGA0_ANALOG4, 0xccf000c0); + rtl8xxxu_write32(priv, REG_ANAPWR1, 0x44ffbb44); + rtl8xxxu_write32(priv, REG_RX_WAIT_CCA, 0x00400040); + rtl8xxxu_write32(priv, REG_OFDM0_TRX_PATH_ENABLE, 0x6f005403); + rtl8xxxu_write32(priv, REG_OFDM0_TR_MUX_PAR, 0x000804e4); + rtl8xxxu_write32(priv, REG_FPGA0_XCD_RF_SW_CTRL, 0x04203400); + rtl8xxxu_write32(priv, REG_FPGA0_XA_HSSI_PARM1, 0x01000000); + + rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0x808000); + + /* Path B IQK setting */ + rtl8xxxu_write32(priv, REG_TX_IQK_TONE_A, 0x38008c1c); + rtl8xxxu_write32(priv, REG_RX_IQK_TONE_A, 0x38008c1c); + rtl8xxxu_write32(priv, REG_TX_IQK_TONE_B, 0x38008c1c); + rtl8xxxu_write32(priv, REG_RX_IQK_TONE_B, 0x18008c1c); + + rtl8xxxu_write32(priv, REG_TX_IQK_PI_B, 0x82170000); + rtl8xxxu_write32(priv, REG_RX_IQK_PI_B, 0x28170000); + + /* IQK setting */ + rtl8xxxu_write32(priv, REG_RX_IQK, 0x01004800); + + /* LO calibration setting */ + rtl8xxxu_write32(priv, REG_IQK_AGC_RSP, 0x0046a911); + + /* One shot, path A LOK & IQK */ + rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xfa005800); + rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xf8005800); + + mdelay(15); + + ktime = 0; + while (rtl8xxxu_read32(priv, REG_IQK_RPT_RXB) == 0 && ktime < 21) { + mdelay(5); + ktime += 5; + } + + reg_eac = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_A_2); + reg_ec4 = rtl8xxxu_read32(priv, REG_RX_POWER_BEFORE_IQK_B_2); + reg_ecc = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_B_2); + + rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0); + rtl8xxxu_write32(priv, REG_FPGA0_XA_HSSI_PARM1, 0x01000100); + + rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_GAIN_CCA, BIT(11), 0); + rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_GAIN_CCA, BIT(1), 0); + rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_GAIN_P1, 0x02000); + + if (!(reg_eac & BIT(30)) && + ((reg_ec4 & 0x03ff0000) != 0x01320000) && + ((reg_ecc & 0x03ff0000) != 0x00360000)) + result |= 0x02; + else + dev_warn(&priv->udev->dev, "%s: Path B RX IQK failed!\n", + __func__); + + return result; +} + +static void rtl8192fu_phy_iqcalibrate(struct rtl8xxxu_priv *priv, + int result[][8], int t) +{ + static const u32 adda_regs[2] = { + REG_ANAPWR1, REG_RX_WAIT_CCA + }; + static const u32 iqk_mac_regs[RTL8XXXU_MAC_REGS] = { + REG_TXPAUSE, REG_BEACON_CTRL, + REG_BEACON_CTRL_1, REG_GPIO_MUXCFG + }; + static const u32 iqk_bb_regs[RTL8XXXU_BB_REGS] = { + REG_OFDM0_TRX_PATH_ENABLE, REG_OFDM0_TR_MUX_PAR, + REG_FPGA0_XCD_RF_SW_CTRL, REG_CONFIG_ANT_A, REG_CONFIG_ANT_B, + REG_DPDT_CTRL, REG_RFE_CTRL_ANTA_SRC, + REG_RFE_CTRL_ANT_SRC2, REG_CCK0_AFE_SETTING + }; + u32 rx_initial_gain_a, rx_initial_gain_b; + struct device *dev = &priv->udev->dev; + int path_a_ok, path_b_ok; + u8 rfe = priv->rfe_type; + int retry = 2; + u32 i, val32; + + /* + * Note: IQ calibration must be performed after loading + * PHY_REG.txt , and radio_a, radio_b.txt + */ + + rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0); + + rx_initial_gain_a = rtl8xxxu_read32(priv, REG_OFDM0_XA_AGC_CORE1); + rx_initial_gain_b = rtl8xxxu_read32(priv, REG_OFDM0_XB_AGC_CORE1); + + if (t == 0) { + /* Save ADDA parameters, turn Path A ADDA on */ + rtl8xxxu_save_regs(priv, adda_regs, priv->adda_backup, + ARRAY_SIZE(adda_regs)); + rtl8xxxu_save_mac_regs(priv, iqk_mac_regs, priv->mac_backup); + rtl8xxxu_save_regs(priv, iqk_bb_regs, + priv->bb_backup, RTL8XXXU_BB_REGS); + } + + /* Instead of rtl8xxxu_path_adda_on */ + rtl8xxxu_write32_set(priv, REG_FPGA0_XCD_RF_PARM, BIT(31)); + + /* MAC settings */ + rtl8xxxu_write8(priv, REG_TXPAUSE, 0xff); + rtl8xxxu_write8_clear(priv, REG_GPIO_MUXCFG, GPIO_MUXCFG_IO_SEL_ENBT); + + if (rfe == 7 || rfe == 8 || rfe == 9 || rfe == 12) { + /* in ePA IQK, rfe_func_config & SW both pull down */ + /* path A */ + rtl8xxxu_write32_mask(priv, REG_RFE_CTRL_ANTA_SRC, 0xF, 0x7); + rtl8xxxu_write32_mask(priv, REG_DPDT_CTRL, 0x1, 0x0); + + rtl8xxxu_write32_mask(priv, REG_RFE_CTRL_ANTA_SRC, 0xF00, 0x7); + rtl8xxxu_write32_mask(priv, REG_DPDT_CTRL, 0x4, 0x0); + + rtl8xxxu_write32_mask(priv, REG_RFE_CTRL_ANTA_SRC, 0xF000, 0x7); + rtl8xxxu_write32_mask(priv, REG_DPDT_CTRL, 0x8, 0x0); + + /* path B */ + rtl8xxxu_write32_mask(priv, REG_RFE_CTRL_ANT_SRC2, 0xF0, 0x7); + rtl8xxxu_write32_mask(priv, REG_DPDT_CTRL, 0x20000, 0x0); + + rtl8xxxu_write32_mask(priv, REG_RFE_CTRL_ANT_SRC2, 0xF0000, 0x7); + rtl8xxxu_write32_mask(priv, REG_DPDT_CTRL, 0x100000, 0x0); + + rtl8xxxu_write32_mask(priv, REG_RFE_CTRL_ANT_SRC3, 0xF000, 0x7); + rtl8xxxu_write32_mask(priv, REG_DPDT_CTRL, 0x8000000, 0x0); + } + + if (priv->rf_paths > 1) { + /* path B standby */ + rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0x000000); + rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_AC, 0x10000); + rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0x808000); + } + + for (i = 0; i < retry; i++) { + path_a_ok = rtl8192fu_iqk_path_a(priv); + + if (path_a_ok == 0x01) { + val32 = rtl8xxxu_read32(priv, REG_TX_POWER_BEFORE_IQK_A); + result[t][0] = (val32 >> 16) & 0x3ff; + + val32 = rtl8xxxu_read32(priv, REG_TX_POWER_AFTER_IQK_A); + result[t][1] = (val32 >> 16) & 0x3ff; + break; + } else { + result[t][0] = 0x100; + result[t][1] = 0x0; + } + } + + for (i = 0; i < retry; i++) { + path_a_ok = rtl8192fu_rx_iqk_path_a(priv); + + if (path_a_ok == 0x03) { + val32 = rtl8xxxu_read32(priv, REG_RX_POWER_BEFORE_IQK_A_2); + result[t][2] = (val32 >> 16) & 0x3ff; + + val32 = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_A_2); + result[t][3] = (val32 >> 16) & 0x3ff; + break; + } else { + result[t][2] = 0x100; + result[t][3] = 0x0; + } + } + + if (!path_a_ok) + dev_warn(dev, "%s: Path A IQK failed!\n", __func__); + + if (priv->rf_paths > 1) { + for (i = 0; i < retry; i++) { + path_b_ok = rtl8192fu_iqk_path_b(priv); + + if (path_b_ok == 0x01) { + val32 = rtl8xxxu_read32(priv, REG_TX_POWER_BEFORE_IQK_B); + result[t][4] = (val32 >> 16) & 0x3ff; + + val32 = rtl8xxxu_read32(priv, REG_TX_POWER_AFTER_IQK_B); + result[t][5] = (val32 >> 16) & 0x3ff; + break; + } else { + result[t][4] = 0x100; + result[t][5] = 0x0; + } + } + + for (i = 0; i < retry; i++) { + path_b_ok = rtl8192fu_rx_iqk_path_b(priv); + + if (path_b_ok == 0x03) { + val32 = rtl8xxxu_read32(priv, REG_RX_POWER_BEFORE_IQK_B_2); + result[t][6] = (val32 >> 16) & 0x3ff; + + val32 = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_B_2); + result[t][7] = (val32 >> 16) & 0x3ff; + break; + } else { + result[t][6] = 0x100; + result[t][7] = 0x0; + } + } + + if (!path_b_ok) + dev_warn(dev, "%s: Path B IQK failed!\n", __func__); + } + + /* Back to BB mode, load original value */ + rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0); + + rtl8xxxu_write32(priv, REG_FPGA0_ANALOG4, 0xcc0000c0); + + rtl8xxxu_write32(priv, REG_ANAPWR1, 0x44bbbb44); + rtl8xxxu_write32(priv, REG_RX_WAIT_CCA, 0x80408040); + rtl8xxxu_write32(priv, REG_OFDM0_TRX_PATH_ENABLE, 0x6f005433); + rtl8xxxu_write32(priv, REG_OFDM0_TR_MUX_PAR, 0x000004e4); + rtl8xxxu_write32(priv, REG_FPGA0_XCD_RF_SW_CTRL, 0x04003400); + rtl8xxxu_write32(priv, REG_FPGA0_XA_HSSI_PARM1, 0x01000100); + + /* Reload ADDA power saving parameters */ + rtl8xxxu_restore_regs(priv, adda_regs, priv->adda_backup, + ARRAY_SIZE(adda_regs)); + + /* Reload MAC parameters */ + rtl8xxxu_restore_mac_regs(priv, iqk_mac_regs, priv->mac_backup); + + /* Reload BB parameters */ + rtl8xxxu_restore_regs(priv, iqk_bb_regs, priv->bb_backup, RTL8XXXU_BB_REGS); + + rtl8xxxu_write32_clear(priv, REG_FPGA0_XCD_RF_PARM, BIT(31)); + + /* Restore RX initial gain */ + rtl8xxxu_write32_mask(priv, REG_OFDM0_XA_AGC_CORE1, 0xff, 0x50); + rtl8xxxu_write32_mask(priv, REG_OFDM0_XA_AGC_CORE1, 0xff, + rx_initial_gain_a & 0xff); + if (priv->rf_paths > 1) { + rtl8xxxu_write32_mask(priv, REG_OFDM0_XB_AGC_CORE1, 0xff, 0x50); + rtl8xxxu_write32_mask(priv, REG_OFDM0_XB_AGC_CORE1, 0xff, + rx_initial_gain_b & 0xff); + } +} + +static void rtl8192fu_phy_iq_calibrate(struct rtl8xxxu_priv *priv) +{ + s32 reg_e94, reg_e9c, reg_ea4, reg_eac; + s32 reg_eb4, reg_ebc, reg_ec4, reg_ecc; + struct device *dev = &priv->udev->dev; + u32 path_a_0xdf, path_a_0x35; + u32 path_b_0xdf, path_b_0x35; + bool path_a_ok, path_b_ok; + u8 rfe = priv->rfe_type; + u32 rfe_path_select; + int result[4][8]; /* last is final result */ + int i, candidate; + s32 reg_tmp = 0; + bool simu; + u32 val32; + + rfe_path_select = rtl8xxxu_read32(priv, REG_RFE_PATH_SELECT); + + path_a_0xdf = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA); + path_a_0x35 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_GAIN_P1); + path_b_0xdf = rtl8xxxu_read_rfreg(priv, RF_B, RF6052_REG_GAIN_CCA); + path_b_0x35 = rtl8xxxu_read_rfreg(priv, RF_B, RF6052_REG_GAIN_P1); + + memset(result, 0, sizeof(result)); + candidate = -1; + + path_a_ok = false; + path_b_ok = false; + + for (i = 0; i < 3; i++) { + rtl8192fu_phy_iqcalibrate(priv, result, i); + + if (i == 1) { + simu = rtl8xxxu_gen2_simularity_compare(priv, result, 0, 1); + if (simu) { + candidate = 0; + break; + } + } + + if (i == 2) { + simu = rtl8xxxu_gen2_simularity_compare(priv, result, 0, 2); + if (simu) { + candidate = 0; + break; + } + + simu = rtl8xxxu_gen2_simularity_compare(priv, result, 1, 2); + if (simu) { + candidate = 1; + } else { + for (i = 0; i < 8; i++) + reg_tmp += result[3][i]; + + if (reg_tmp) + candidate = 3; + else + candidate = -1; + } + } + } + + if (candidate >= 0) { + reg_e94 = result[candidate][0]; + reg_e9c = result[candidate][1]; + reg_ea4 = result[candidate][2]; + reg_eac = result[candidate][3]; + reg_eb4 = result[candidate][4]; + reg_ebc = result[candidate][5]; + reg_ec4 = result[candidate][6]; + reg_ecc = result[candidate][7]; + + dev_dbg(dev, "%s: candidate is %x\n", __func__, candidate); + dev_dbg(dev, "%s: e94=%x e9c=%x ea4=%x eac=%x eb4=%x ebc=%x ec4=%x ecc=%c\n", + __func__, reg_e94, reg_e9c, reg_ea4, reg_eac, + reg_eb4, reg_ebc, reg_ec4, reg_ecc); + + path_a_ok = true; + path_b_ok = true; + } + + rtl8xxxu_write32_mask(priv, REG_TX_IQK_TONE_A, 0x3ff00000, 0x100); + rtl8xxxu_write32_mask(priv, REG_NP_ANTA, 0x3ff, 0); + rtl8xxxu_write32_mask(priv, REG_TX_IQK_TONE_B, 0x3ff00000, 0x100); + rtl8xxxu_write32_mask(priv, REG_TAP_UPD_97F, 0x3ff, 0); + + if (candidate >= 0) { + if (reg_e94) + rtl8xxxu_fill_iqk_matrix_a(priv, path_a_ok, result, + candidate, (reg_ea4 == 0)); + + if (reg_eb4) + rtl8xxxu_fill_iqk_matrix_b(priv, path_b_ok, result, + candidate, (reg_ec4 == 0)); + } + + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, path_a_0xdf); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_P1, path_a_0x35); + rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_GAIN_CCA, path_b_0xdf); + rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_GAIN_P1, path_b_0x35); + + if (rfe == 7 || rfe == 8 || rfe == 9 || rfe == 12) { + rtl8xxxu_write32_set(priv, REG_SW_GPIO_SHARE_CTRL_1, 0x70000); + rtl8xxxu_write32_clear(priv, REG_LEDCFG0, 0x6c00000); + rtl8xxxu_write32_set(priv, REG_PAD_CTRL1, BIT(29) | BIT(28)); + rtl8xxxu_write32_clear(priv, REG_SW_GPIO_SHARE_CTRL_0, + 0x600000 | BIT(4)); + + /* + * Originally: + * odm_set_bb_reg(dm, R_0x944, BIT(11) | 0x1F, 0x3F); + * + * It clears bit 11 and sets bits 0..4. The mask doesn't cover + * bit 5 so it's not modified. Is that what it's supposed to + * accomplish? + */ + val32 = rtl8xxxu_read32(priv, REG_RFE_BUFFER); + val32 &= ~BIT(11); + val32 |= 0x1f; + rtl8xxxu_write32(priv, REG_RFE_BUFFER, val32); + + if (rfe == 7) { + rtl8xxxu_write32_mask(priv, REG_RFE_CTRL_ANTA_SRC, + 0xfffff, 0x23200); + rtl8xxxu_write32_mask(priv, REG_RFE_CTRL_ANT_SRC2, + 0xfffff, 0x23200); + rtl8xxxu_write32_mask(priv, REG_RFE_CTRL_ANT_SRC1, + 0xf000, 0x3); + rtl8xxxu_write32_mask(priv, REG_RFE_CTRL_ANT_SRC3, + 0xf000, 0x3); + } else { + rtl8xxxu_write32_mask(priv, REG_RFE_CTRL_ANTA_SRC, + 0xfffff, 0x22200); + rtl8xxxu_write32_mask(priv, REG_RFE_CTRL_ANT_SRC2, + 0xfffff, 0x22200); + rtl8xxxu_write32_mask(priv, REG_RFE_CTRL_ANT_SRC1, + 0xf000, 0x2); + rtl8xxxu_write32_mask(priv, REG_RFE_CTRL_ANT_SRC3, + 0xf000, 0x2); + } + + rtl8xxxu_write32_clear(priv, REG_RFE_OPT62, BIT(2)); + + if (rfe == 7) + rtl8xxxu_write32(priv, REG_RFE_OPT, 0x03000003); + + rtl8xxxu_write32(priv, REG_RFE_PATH_SELECT, rfe_path_select); + } +} + +static void rtl8192fu_disabled_to_emu(struct rtl8xxxu_priv *priv) +{ + rtl8xxxu_write16_clear(priv, REG_APS_FSMCO, + APS_FSMCO_HW_POWERDOWN | APS_FSMCO_HW_SUSPEND); + + rtl8xxxu_write32_clear(priv, REG_GPIO_INTM, BIT(16)); + + rtl8xxxu_write16_clear(priv, REG_APS_FSMCO, + APS_FSMCO_PCIE | APS_FSMCO_HW_SUSPEND); +} + +static int rtl8192fu_emu_to_active(struct rtl8xxxu_priv *priv) +{ + u32 val32; + u16 val16; + int count; + + /* enable LDOA12 MACRO block for all interface */ + rtl8xxxu_write8_set(priv, REG_LDOA15_CTRL, LDOA15_ENABLE); + + /* disable BT_GPS_SEL pins */ + rtl8xxxu_write32_clear(priv, REG_PAD_CTRL1, BIT(28)); + + mdelay(1); + + /* release analog Ips to digital */ + rtl8xxxu_write8_clear(priv, REG_SYS_ISO_CTRL, SYS_ISO_ANALOG_IPS); + + val16 = APS_FSMCO_PCIE | APS_FSMCO_HW_SUSPEND | APS_FSMCO_SW_LPS; + rtl8xxxu_write16_clear(priv, REG_APS_FSMCO, val16); + + /* wait till 0x04[17] = 1 power ready */ + for (count = RTL8XXXU_MAX_REG_POLL; count; count--) { + val32 = rtl8xxxu_read32(priv, REG_APS_FSMCO); + if (val32 & BIT(17)) + break; + + udelay(10); + } + + if (!count) + return -EBUSY; + + rtl8xxxu_write32_set(priv, REG_APS_FSMCO, APS_FSMCO_WLON_RESET); + + for (count = RTL8XXXU_MAX_REG_POLL; count; count--) { + val32 = rtl8xxxu_read32(priv, REG_APS_FSMCO); + if ((val32 & (APS_FSMCO_MAC_ENABLE | APS_FSMCO_MAC_OFF)) == 0) + break; + + udelay(10); + } + + if (!count) + return -EBUSY; + + /* SWR OCP enable */ + rtl8xxxu_write32_set(priv, REG_AFE_MISC, BIT(18)); + + rtl8xxxu_write16_clear(priv, REG_APS_FSMCO, APS_FSMCO_HW_POWERDOWN); + + rtl8xxxu_write16_clear(priv, REG_APS_FSMCO, + APS_FSMCO_PCIE | APS_FSMCO_HW_SUSPEND); + + /* 0x7c[31]=1, LDO has max output capability */ + rtl8xxxu_write32_set(priv, REG_LDO_SW_CTRL, BIT(31)); + + rtl8xxxu_write16_set(priv, REG_APS_FSMCO, APS_FSMCO_MAC_ENABLE); + + for (count = RTL8XXXU_MAX_REG_POLL; count; count--) { + val32 = rtl8xxxu_read32(priv, REG_APS_FSMCO); + if ((val32 & APS_FSMCO_MAC_ENABLE) == 0) + break; + + udelay(10); + } + + if (!count) + return -EBUSY; + + /* Enable WL control XTAL setting */ + rtl8xxxu_write8_set(priv, REG_AFE_MISC, AFE_MISC_WL_XTAL_CTRL); + + /* Enable falling edge triggering interrupt */ + rtl8xxxu_write16_set(priv, REG_GPIO_INTM, GPIO_INTM_EDGE_TRIG_IRQ); + + /* Enable GPIO9 data mode */ + rtl8xxxu_write16_clear(priv, REG_GPIO_IO_SEL_2, GPIO_IO_SEL_2_GPIO09_IRQ); + + /* Enable GPIO9 input mode */ + rtl8xxxu_write16_clear(priv, REG_GPIO_IO_SEL_2, GPIO_IO_SEL_2_GPIO09_INPUT); + + /* Enable HSISR GPIO[C:0] interrupt */ + rtl8xxxu_write8_set(priv, REG_HSIMR, BIT(0)); + + /* RF HW ON/OFF Enable */ + rtl8xxxu_write8_clear(priv, REG_MULTI_FUNC_CTRL, MULTI_WIFI_HW_ROF_EN); + + /* Register Lock Disable */ + rtl8xxxu_write8_set(priv, REG_RSV_CTRL, BIT(7)); + + /* For GPIO9 internal pull high setting */ + rtl8xxxu_write16_set(priv, REG_MULTI_FUNC_CTRL, BIT(14)); + + /* reset RF path S1 */ + rtl8xxxu_write8(priv, REG_RF_CTRL, 0); + + /* reset RF path S0 */ + rtl8xxxu_write8(priv, REG_AFE_CTRL4 + 3, 0); + + /* enable RF path S1 */ + rtl8xxxu_write8(priv, REG_RF_CTRL, RF_SDMRSTB | RF_RSTB | RF_ENABLE); + + /* enable RF path S0 */ + rtl8xxxu_write8(priv, REG_AFE_CTRL4 + 3, RF_SDMRSTB | RF_RSTB | RF_ENABLE); + + /* AFE_Ctrl */ + rtl8xxxu_write8_set(priv, REG_RSVD_1, BIT(5)); + + /* AFE_Ctrl */ + rtl8xxxu_write8(priv, REG_RSVD_4, 0xcc); + + /* AFE_Ctrl 0x24[4:3]=00 for xtal gmn */ + rtl8xxxu_write8_clear(priv, REG_AFE_XTAL_CTRL, BIT(4) | BIT(3)); + + /* GPIO_A[31:0] Pull down software register */ + rtl8xxxu_write32(priv, REG_GPIO_A0, 0xffffffff); + + /* GPIO_B[7:0] Pull down software register */ + rtl8xxxu_write8(priv, REG_GPIO_B0, 0xff); + + /* Register Lock Enable */ + rtl8xxxu_write8_clear(priv, REG_RSV_CTRL, BIT(7)); + + return 0; +} + +static int rtl8192fu_active_to_emu(struct rtl8xxxu_priv *priv) +{ + u32 val32; + int count; + + /* Reset BB, RF enter Power Down mode */ + rtl8xxxu_write8_clear(priv, REG_SYS_FUNC, SYS_FUNC_BBRSTB); + + /* Enable rising edge triggering interrupt */ + rtl8xxxu_write16_clear(priv, REG_GPIO_INTM, GPIO_INTM_EDGE_TRIG_IRQ); + + /* release WLON reset */ + rtl8xxxu_write32_set(priv, REG_APS_FSMCO, APS_FSMCO_WLON_RESET); + + /* turn off MAC by HW state machine */ + rtl8xxxu_write16_set(priv, REG_APS_FSMCO, APS_FSMCO_MAC_OFF); + + for (count = RTL8XXXU_MAX_REG_POLL; count; count--) { + val32 = rtl8xxxu_read32(priv, REG_APS_FSMCO); + if ((val32 & APS_FSMCO_MAC_OFF) == 0) + break; + + udelay(10); + } + + if (!count) + return -EBUSY; + + /* analog Ips to digital, 1:isolation */ + rtl8xxxu_write8_set(priv, REG_SYS_ISO_CTRL, SYS_ISO_ANALOG_IPS); + + /* disable LDOA12 MACRO block */ + rtl8xxxu_write8_clear(priv, REG_LDOA15_CTRL, LDOA15_ENABLE); + + return 0; +} + +static int rtl8192fu_emu_to_disabled(struct rtl8xxxu_priv *priv) +{ + u16 val16; + + /* SOP option to disable BG/MB */ + rtl8xxxu_write8(priv, REG_APS_FSMCO + 3, 0x20); + + /* 0x04[12:11] = 2b'01 enable WL suspend */ + val16 = rtl8xxxu_read16(priv, REG_APS_FSMCO); + val16 &= ~APS_FSMCO_PCIE; + val16 |= APS_FSMCO_HW_SUSPEND; + rtl8xxxu_write16(priv, REG_APS_FSMCO, val16); + + /* enable GPIO9 as EXT WAKEUP */ + rtl8xxxu_write32_set(priv, REG_GPIO_INTM, BIT(16)); + + return 0; +} + +static int rtl8192fu_active_to_lps(struct rtl8xxxu_priv *priv) +{ + struct device *dev = &priv->udev->dev; + u16 val16; + u32 val32; + int retry; + + /* Tx Pause */ + rtl8xxxu_write8(priv, REG_TXPAUSE, 0xff); + + retry = 100; + + /* Poll 32 bit wide REG_SCH_TX_CMD for 0 to ensure no TX is pending. */ + do { + val32 = rtl8xxxu_read32(priv, REG_SCH_TX_CMD); + if (!val32) + break; + + udelay(10); + } while (retry--); + + if (!retry) { + dev_warn(dev, "%s: Failed to flush TX queue\n", __func__); + return -EBUSY; + } + + /* Disable CCK and OFDM, clock gated */ + rtl8xxxu_write8_clear(priv, REG_SYS_FUNC, SYS_FUNC_BBRSTB); + + udelay(2); + + /* Whole BB is reset */ + rtl8xxxu_write8_clear(priv, REG_SYS_FUNC, SYS_FUNC_BB_GLB_RSTN); + + /* Reset MAC TRX */ + val16 = rtl8xxxu_read16(priv, REG_CR); + val16 &= 0xff00; + val16 |= CR_HCI_RXDMA_ENABLE | CR_HCI_TXDMA_ENABLE; + val16 &= ~CR_SECURITY_ENABLE; + rtl8xxxu_write16(priv, REG_CR, val16); + + /* Respond TxOK to scheduler */ + rtl8xxxu_write8_set(priv, REG_DUAL_TSF_RST, DUAL_TSF_TX_OK); + + return 0; +} + +static int rtl8192fu_power_on(struct rtl8xxxu_priv *priv) +{ + u16 val16; + int ret; + + rtl8xxxu_write8(priv, REG_USB_ACCESS_TIMEOUT, 0x80); + + rtl8192fu_disabled_to_emu(priv); + + ret = rtl8192fu_emu_to_active(priv); + if (ret) + return ret; + + rtl8xxxu_write16(priv, REG_CR, 0); + + val16 = rtl8xxxu_read16(priv, REG_CR); + + val16 |= CR_HCI_TXDMA_ENABLE | CR_HCI_RXDMA_ENABLE | + CR_TXDMA_ENABLE | CR_RXDMA_ENABLE | + CR_PROTOCOL_ENABLE | CR_SCHEDULE_ENABLE | + CR_SECURITY_ENABLE | CR_CALTIMER_ENABLE; + rtl8xxxu_write16(priv, REG_CR, val16); + + return 0; +} + +static void rtl8192fu_power_off(struct rtl8xxxu_priv *priv) +{ + rtl8xxxu_flush_fifo(priv); + + /* Stop Tx Report Timer. 0x4EC[Bit1]=b'0 */ + rtl8xxxu_write8_clear(priv, REG_TX_REPORT_CTRL, + TX_REPORT_CTRL_TIMER_ENABLE); + + /* stop rx */ + rtl8xxxu_write8(priv, REG_CR, 0x00); + + rtl8192fu_active_to_lps(priv); + + /* Reset Firmware if running in RAM */ + if (rtl8xxxu_read8(priv, REG_MCU_FW_DL) & MCU_FW_RAM_SEL) + rtl8xxxu_firmware_self_reset(priv); + + /* Reset MCU */ + rtl8xxxu_write16_clear(priv, REG_SYS_FUNC, SYS_FUNC_CPU_ENABLE); + + /* Reset MCU ready status */ + rtl8xxxu_write8(priv, REG_MCU_FW_DL, 0x00); + + rtl8192fu_active_to_emu(priv); + rtl8192fu_emu_to_disabled(priv); +} + +static void rtl8192f_reset_8051(struct rtl8xxxu_priv *priv) +{ + rtl8xxxu_write8_clear(priv, REG_RSV_CTRL, BIT(1)); + + rtl8xxxu_write8_clear(priv, REG_RSV_CTRL + 1, BIT(0)); + + rtl8xxxu_write16_clear(priv, REG_SYS_FUNC, SYS_FUNC_CPU_ENABLE); + + rtl8xxxu_write8_clear(priv, REG_RSV_CTRL, BIT(1)); + + rtl8xxxu_write8_set(priv, REG_RSV_CTRL + 1, BIT(0)); + + rtl8xxxu_write16_set(priv, REG_SYS_FUNC, SYS_FUNC_CPU_ENABLE); +} + +static void rtl8192f_enable_rf(struct rtl8xxxu_priv *priv) +{ + u32 val32; + + rtl8xxxu_write8(priv, REG_RF_CTRL, RF_ENABLE | RF_RSTB | RF_SDMRSTB); + + val32 = rtl8xxxu_read32(priv, REG_OFDM0_TRX_PATH_ENABLE); + val32 &= ~(OFDM_RF_PATH_RX_MASK | OFDM_RF_PATH_TX_MASK); + val32 |= OFDM_RF_PATH_RX_A | OFDM_RF_PATH_RX_B | + OFDM_RF_PATH_TX_A | OFDM_RF_PATH_TX_B; + rtl8xxxu_write32(priv, REG_OFDM0_TRX_PATH_ENABLE, val32); + + rtl8xxxu_write8(priv, REG_TXPAUSE, 0x00); +} + +static void rtl8192f_disable_rf(struct rtl8xxxu_priv *priv) +{ + u32 val32; + + val32 = rtl8xxxu_read32(priv, REG_OFDM0_TRX_PATH_ENABLE); + val32 &= ~OFDM_RF_PATH_TX_MASK; + rtl8xxxu_write32(priv, REG_OFDM0_TRX_PATH_ENABLE, val32); + + /* Power down RF module */ + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_AC, 0); +} + +static void rtl8192f_usb_quirks(struct rtl8xxxu_priv *priv) +{ + u16 val16; + + rtl8xxxu_gen2_usb_quirks(priv); + + val16 = rtl8xxxu_read16(priv, REG_CR); + val16 |= (CR_MAC_TX_ENABLE | CR_MAC_RX_ENABLE); + rtl8xxxu_write16(priv, REG_CR, val16); +} + +#define XTAL1 GENMASK(6, 1) +#define XTAL0 GENMASK(30, 25) + +static void rtl8192f_set_crystal_cap(struct rtl8xxxu_priv *priv, u8 crystal_cap) +{ + struct rtl8xxxu_cfo_tracking *cfo = &priv->cfo_tracking; + u32 xtal1, xtal0; + + if (crystal_cap == cfo->crystal_cap) + return; + + xtal1 = rtl8xxxu_read32(priv, REG_AFE_PLL_CTRL); + xtal0 = rtl8xxxu_read32(priv, REG_AFE_XTAL_CTRL); + + dev_dbg(&priv->udev->dev, + "%s: Adjusting crystal cap from 0x%x (actually 0x%x 0x%x) to 0x%x\n", + __func__, + cfo->crystal_cap, + u32_get_bits(xtal1, XTAL1), + u32_get_bits(xtal0, XTAL0), + crystal_cap); + + u32p_replace_bits(&xtal1, crystal_cap, XTAL1); + u32p_replace_bits(&xtal0, crystal_cap, XTAL0); + rtl8xxxu_write32(priv, REG_AFE_PLL_CTRL, xtal1); + rtl8xxxu_write32(priv, REG_AFE_XTAL_CTRL, xtal0); + + cfo->crystal_cap = crystal_cap; +} + +static s8 rtl8192f_cck_rssi(struct rtl8xxxu_priv *priv, struct rtl8723au_phy_stats *phy_stats) +{ + struct jaguar2_phy_stats_type0 *phy_stats0 = (struct jaguar2_phy_stats_type0 *)phy_stats; + u8 lna_idx = (phy_stats0->lna_h << 3) | phy_stats0->lna_l; + u8 vga_idx = phy_stats0->vga; + s8 rx_pwr_all; + + switch (lna_idx) { + case 7: + rx_pwr_all = -44 - (2 * vga_idx); + break; + case 5: + rx_pwr_all = -28 - (2 * vga_idx); + break; + case 3: + rx_pwr_all = -10 - (2 * vga_idx); + break; + case 0: + rx_pwr_all = 14 - (2 * vga_idx); + break; + default: + rx_pwr_all = 0; + break; + } + + return rx_pwr_all; +} + +static int rtl8192fu_led_brightness_set(struct led_classdev *led_cdev, + enum led_brightness brightness) +{ + struct rtl8xxxu_priv *priv = container_of(led_cdev, + struct rtl8xxxu_priv, + led_cdev); + u16 ledcfg; + + /* Values obtained by observing the USB traffic from the Windows driver. */ + rtl8xxxu_write32(priv, REG_SW_GPIO_SHARE_CTRL_0, 0x20080); + rtl8xxxu_write32(priv, REG_SW_GPIO_SHARE_CTRL_1, 0x1b0000); + + ledcfg = rtl8xxxu_read16(priv, REG_LEDCFG0); + + if (brightness == LED_OFF) { + /* Value obtained like above. */ + ledcfg = BIT(1) | BIT(7); + } else if (brightness == LED_ON) { + /* Value obtained like above. */ + ledcfg = BIT(1) | BIT(7) | BIT(11); + } else if (brightness == RTL8XXXU_HW_LED_CONTROL) { + /* Value obtained by brute force. */ + ledcfg = BIT(8) | BIT(9); + } + + rtl8xxxu_write16(priv, REG_LEDCFG0, ledcfg); + + return 0; +} + +struct rtl8xxxu_fileops rtl8192fu_fops = { + .identify_chip = rtl8192fu_identify_chip, + .parse_efuse = rtl8192fu_parse_efuse, + .load_firmware = rtl8192fu_load_firmware, + .power_on = rtl8192fu_power_on, + .power_off = rtl8192fu_power_off, + .read_efuse = rtl8xxxu_read_efuse, + .reset_8051 = rtl8192f_reset_8051, + .llt_init = rtl8xxxu_auto_llt_table, + .init_phy_bb = rtl8192fu_init_phy_bb, + .init_phy_rf = rtl8192fu_init_phy_rf, + .phy_lc_calibrate = rtl8192f_phy_lc_calibrate, + .phy_iq_calibrate = rtl8192fu_phy_iq_calibrate, + .config_channel = rtl8192fu_config_channel, + .parse_rx_desc = rtl8xxxu_parse_rxdesc24, + .parse_phystats = jaguar2_rx_parse_phystats, + .init_aggregation = rtl8192fu_init_aggregation, + .init_burst = rtl8xxxu_init_burst, + .enable_rf = rtl8192f_enable_rf, + .disable_rf = rtl8192f_disable_rf, + .usb_quirks = rtl8192f_usb_quirks, + .set_tx_power = rtl8192f_set_tx_power, + .update_rate_mask = rtl8xxxu_gen2_update_rate_mask, + .report_connect = rtl8xxxu_gen2_report_connect, + .report_rssi = rtl8xxxu_gen2_report_rssi, + .fill_txdesc = rtl8xxxu_fill_txdesc_v2, + .set_crystal_cap = rtl8192f_set_crystal_cap, + .cck_rssi = rtl8192f_cck_rssi, + .led_classdev_brightness_set = rtl8192fu_led_brightness_set, + .writeN_block_size = 254, + .rx_desc_size = sizeof(struct rtl8xxxu_rxdesc24), + .tx_desc_size = sizeof(struct rtl8xxxu_txdesc40), + .has_tx_report = 1, + .gen2_thermal_meter = 1, + .needs_full_init = 1, + .init_reg_rxfltmap = 1, + .init_reg_pkt_life_time = 1, + .init_reg_hmtfr = 1, + .ampdu_max_time = 0x5e, + .ustime_tsf_edca = 0x50, + .max_aggr_num = 0x1f1f, + .trxff_boundary = 0x3f3f, + .pbp_rx = PBP_PAGE_SIZE_256, + .pbp_tx = PBP_PAGE_SIZE_256, + .mactable = rtl8192f_mac_init_table, + .total_page_num = TX_TOTAL_PAGE_NUM_8192F, + .page_num_hi = TX_PAGE_NUM_HI_PQ_8192F, + .page_num_lo = TX_PAGE_NUM_LO_PQ_8192F, + .page_num_norm = TX_PAGE_NUM_NORM_PQ_8192F, +}; diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8710b.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8710b.c index 22d4704dd31e1897df9d274a7a61d718b94d75ae..f0d17b75c5f10b664880f1a2fe435932c3d7cde0 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8710b.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8710b.c @@ -1031,12 +1031,12 @@ static int rtl8710bu_iqk_path_a(struct rtl8xxxu_priv *priv, u32 *lok_result) rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_TXPA_G2, 0x07ff7); /* PA,PAD gain adjust */ - val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF); + val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA); val32 |= BIT(11); - rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, val32); - val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_56); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, val32); + val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_PAD_TXG); u32p_replace_bits(&val32, 0x1ed, 0x00fff); - rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_56, val32); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_PAD_TXG, val32); /* enter IQK mode */ val32 = rtl8xxxu_read32(priv, REG_FPGA0_IQK); @@ -1068,9 +1068,9 @@ static int rtl8710bu_iqk_path_a(struct rtl8xxxu_priv *priv, u32 *lok_result) u32p_replace_bits(&val32, 0, 0xffffff00); rtl8xxxu_write32(priv, REG_FPGA0_IQK, val32); - val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF); + val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA); val32 &= ~BIT(11); - rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, val32); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, val32); /* save LOK result */ *lok_result = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_TXM_IDAC); @@ -1113,12 +1113,12 @@ static int rtl8710bu_rx_iqk_path_a(struct rtl8xxxu_priv *priv, u32 lok_result) rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_TXPA_G2, 0xf1173); /* PA,PAD gain adjust */ - val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF); + val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA); val32 |= BIT(11); - rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, val32); - val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_56); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, val32); + val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_PAD_TXG); u32p_replace_bits(&val32, 0xf, 0x003e0); - rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_56, val32); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_PAD_TXG, val32); /* * Enter IQK mode @@ -1170,9 +1170,9 @@ static int rtl8710bu_rx_iqk_path_a(struct rtl8xxxu_priv *priv, u32 lok_result) u32p_replace_bits(&val32, 0, 0xffffff00); rtl8xxxu_write32(priv, REG_FPGA0_IQK, val32); - val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF); + val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA); val32 &= ~BIT(11); - rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, val32); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, val32); return result; } @@ -1197,12 +1197,12 @@ static int rtl8710bu_rx_iqk_path_a(struct rtl8xxxu_priv *priv, u32 lok_result) /* * PA, PAD setting */ - val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF); + val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA); val32 |= BIT(11); - rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, val32); - val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_56); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, val32); + val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_PAD_TXG); u32p_replace_bits(&val32, 0x2a, 0x00fff); - rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_56, val32); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_PAD_TXG, val32); /* * Enter IQK mode @@ -1241,9 +1241,9 @@ static int rtl8710bu_rx_iqk_path_a(struct rtl8xxxu_priv *priv, u32 lok_result) u32p_replace_bits(&val32, 0, 0xffffff00); rtl8xxxu_write32(priv, REG_FPGA0_IQK, val32); - val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF); + val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA); val32 &= ~BIT(11); - rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, val32); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, val32); /* reload LOK value */ rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_TXM_IDAC, lok_result); @@ -1874,6 +1874,7 @@ struct rtl8xxxu_fileops rtl8710bu_fops = { * but in rtl8xxxu 0x50 causes slow upload and random packet loss. Why? */ .ustime_tsf_edca = 0x28, + .max_aggr_num = 0x0c14, .adda_1t_init = 0x03c00016, .adda_1t_path_on = 0x03c00016, .trxff_boundary = 0x3f7f, diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723b.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723b.c index abc56c7de6f756102950fe3c0db61bdedc61fa3d..13ad5d5b73f4e60f1cc352df035fbc27b30825ba 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723b.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723b.c @@ -824,7 +824,7 @@ static int rtl8723bu_rx_iqk_path_a(struct rtl8xxxu_priv *priv) /* * PA, PAD setting */ - rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, 0xf80); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, 0xf80); rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_55, 0x4021f); /* @@ -888,7 +888,7 @@ static int rtl8723bu_rx_iqk_path_a(struct rtl8xxxu_priv *priv) reg_eac = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_A_2); reg_ea4 = rtl8xxxu_read32(priv, REG_RX_POWER_BEFORE_IQK_A_2); - rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, 0x780); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, 0x780); val32 = (reg_eac >> 16) & 0x3ff; if (val32 & 0x200) @@ -1741,6 +1741,7 @@ struct rtl8xxxu_fileops rtl8723bu_fops = { .init_reg_hmtfr = 1, .ampdu_max_time = 0x5e, .ustime_tsf_edca = 0x50, + .max_aggr_num = 0x0c14, .adda_1t_init = 0x01c00014, .adda_1t_path_on = 0x01c00014, .adda_2t_path_on_a = 0x01c00014, diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c index 831639d73657be9c338ec21d6cf4108331c40ac3..5d102a1246a301a2c105470ddef333bb5af6db12 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c @@ -56,6 +56,7 @@ MODULE_FIRMWARE("rtlwifi/rtl8723bu_bt.bin"); MODULE_FIRMWARE("rtlwifi/rtl8188fufw.bin"); MODULE_FIRMWARE("rtlwifi/rtl8710bufw_SMIC.bin"); MODULE_FIRMWARE("rtlwifi/rtl8710bufw_UMC.bin"); +MODULE_FIRMWARE("rtlwifi/rtl8192fufw.bin"); module_param_named(debug, rtl8xxxu_debug, int, 0600); MODULE_PARM_DESC(debug, "Set debug mask"); @@ -642,7 +643,7 @@ const u32 rtl8xxxu_iqk_phy_iq_bb_reg[RTL8XXXU_BB_REGS] = { REG_OFDM0_XA_RX_IQ_IMBALANCE, REG_OFDM0_XB_RX_IQ_IMBALANCE, REG_OFDM0_ENERGY_CCA_THRES, - REG_OFDM0_AGCR_SSI_TABLE, + REG_OFDM0_AGC_RSSI_TABLE, REG_OFDM0_XA_TX_IQ_IMBALANCE, REG_OFDM0_XB_TX_IQ_IMBALANCE, REG_OFDM0_XC_TX_AFE, @@ -1185,6 +1186,20 @@ static void rtl8xxxu_stop_tx_beacon(struct rtl8xxxu_priv *priv) rtl8xxxu_write8(priv, REG_TBTT_PROHIBIT + 2, val8); } +static void rtl8xxxu_start_tx_beacon(struct rtl8xxxu_priv *priv) +{ + u8 val8; + + val8 = rtl8xxxu_read8(priv, REG_FWHW_TXQ_CTRL + 2); + val8 |= EN_BCNQ_DL >> 16; + rtl8xxxu_write8(priv, REG_FWHW_TXQ_CTRL + 2, val8); + + rtl8xxxu_write8(priv, REG_TBTT_PROHIBIT + 1, 0x80); + val8 = rtl8xxxu_read8(priv, REG_TBTT_PROHIBIT + 2); + val8 &= 0xF0; + rtl8xxxu_write8(priv, REG_TBTT_PROHIBIT + 2, val8); +} + /* * The rtl8723a has 3 channel groups for it's efuse settings. It only @@ -2006,12 +2021,18 @@ static int rtl8xxxu_start_firmware(struct rtl8xxxu_priv *priv) static int rtl8xxxu_download_firmware(struct rtl8xxxu_priv *priv) { int pages, remainder, i, ret; + u16 reg_fw_start_address; u16 reg_mcu_fw_dl; u8 val8; u16 val16; u32 val32; u8 *fwptr; + if (priv->rtl_chip == RTL8192F) + reg_fw_start_address = REG_FW_START_ADDRESS_8192F; + else + reg_fw_start_address = REG_FW_START_ADDRESS; + if (priv->rtl_chip == RTL8710B) { reg_mcu_fw_dl = REG_8051FW_CTRL_V1_8710B; } else { @@ -2067,7 +2088,7 @@ static int rtl8xxxu_download_firmware(struct rtl8xxxu_priv *priv) val8 |= i; rtl8xxxu_write8(priv, reg_mcu_fw_dl + 2, val8); - ret = rtl8xxxu_writeN(priv, REG_FW_START_ADDRESS, + ret = rtl8xxxu_writeN(priv, reg_fw_start_address, fwptr, RTL_FW_PAGE_SIZE); if (ret != RTL_FW_PAGE_SIZE) { ret = -EAGAIN; @@ -2081,7 +2102,7 @@ static int rtl8xxxu_download_firmware(struct rtl8xxxu_priv *priv) val8 = rtl8xxxu_read8(priv, reg_mcu_fw_dl + 2) & 0xF8; val8 |= i; rtl8xxxu_write8(priv, reg_mcu_fw_dl + 2, val8); - ret = rtl8xxxu_writeN(priv, REG_FW_START_ADDRESS, + ret = rtl8xxxu_writeN(priv, reg_fw_start_address, fwptr, remainder); if (ret != remainder) { ret = -EAGAIN; @@ -2135,6 +2156,7 @@ int rtl8xxxu_load_firmware(struct rtl8xxxu_priv *priv, const char *fw_name) case 0x2300: case 0x88f0: case 0x10b0: + case 0x92f0: break; default: ret = -EINVAL; @@ -2581,6 +2603,7 @@ static int rtl8xxxu_init_queue_priority(struct rtl8xxxu_priv *priv) u16 hiq, mgq, bkq, beq, viq, voq; int hip, mgp, bkp, bep, vip, vop; int ret = 0; + u32 val32; switch (priv->ep_tx_count) { case 1: @@ -2663,15 +2686,28 @@ static int rtl8xxxu_init_queue_priority(struct rtl8xxxu_priv *priv) * queue here .... why? */ if (!ret) { - val16 = rtl8xxxu_read16(priv, REG_TRXDMA_CTRL); - val16 &= 0x7; - val16 |= (voq << TRXDMA_CTRL_VOQ_SHIFT) | - (viq << TRXDMA_CTRL_VIQ_SHIFT) | - (beq << TRXDMA_CTRL_BEQ_SHIFT) | - (bkq << TRXDMA_CTRL_BKQ_SHIFT) | - (mgq << TRXDMA_CTRL_MGQ_SHIFT) | - (hiq << TRXDMA_CTRL_HIQ_SHIFT); - rtl8xxxu_write16(priv, REG_TRXDMA_CTRL, val16); + /* Only RTL8192F seems to do it like this. */ + if (priv->rtl_chip == RTL8192F) { + val32 = rtl8xxxu_read32(priv, REG_TRXDMA_CTRL); + val32 &= 0x7; + val32 |= (voq << TRXDMA_CTRL_VOQ_SHIFT_8192F) | + (viq << TRXDMA_CTRL_VIQ_SHIFT_8192F) | + (beq << TRXDMA_CTRL_BEQ_SHIFT_8192F) | + (bkq << TRXDMA_CTRL_BKQ_SHIFT_8192F) | + (mgq << TRXDMA_CTRL_MGQ_SHIFT_8192F) | + (hiq << TRXDMA_CTRL_HIQ_SHIFT_8192F); + rtl8xxxu_write32(priv, REG_TRXDMA_CTRL, val32); + } else { + val16 = rtl8xxxu_read16(priv, REG_TRXDMA_CTRL); + val16 &= 0x7; + val16 |= (voq << TRXDMA_CTRL_VOQ_SHIFT) | + (viq << TRXDMA_CTRL_VIQ_SHIFT) | + (beq << TRXDMA_CTRL_BEQ_SHIFT) | + (bkq << TRXDMA_CTRL_BKQ_SHIFT) | + (mgq << TRXDMA_CTRL_MGQ_SHIFT) | + (hiq << TRXDMA_CTRL_HIQ_SHIFT); + rtl8xxxu_write16(priv, REG_TRXDMA_CTRL, val16); + } priv->pipe_out[TXDESC_QUEUE_VO] = usb_sndbulkpipe(priv->udev, priv->out_ep[vop]); @@ -2842,10 +2878,14 @@ void rtl8xxxu_fill_iqk_matrix_b(struct rtl8xxxu_priv *priv, bool iqk_ok, reg = (result[candidate][7] >> 6) & 0xf; - val32 = rtl8xxxu_read32(priv, REG_OFDM0_AGCR_SSI_TABLE); - val32 &= ~0x0000f000; - val32 |= (reg << 12); - rtl8xxxu_write32(priv, REG_OFDM0_AGCR_SSI_TABLE, val32); + if (priv->rtl_chip == RTL8192F) { + rtl8xxxu_write32_mask(priv, REG_RXIQB_EXT, 0x000000f0, reg); + } else { + val32 = rtl8xxxu_read32(priv, REG_OFDM0_AGC_RSSI_TABLE); + val32 &= ~0x0000f000; + val32 |= (reg << 12); + rtl8xxxu_write32(priv, REG_OFDM0_AGC_RSSI_TABLE, val32); + } } #define MAX_TOLERANCE 5 @@ -3944,13 +3984,14 @@ void rtl8xxxu_init_burst(struct rtl8xxxu_priv *priv) val8 |= HT_SINGLE_AMPDU_ENABLE; rtl8xxxu_write8(priv, REG_HT_SINGLE_AMPDU_8723B, val8); - rtl8xxxu_write16(priv, REG_MAX_AGGR_NUM, 0x0c14); + rtl8xxxu_write16(priv, REG_MAX_AGGR_NUM, priv->fops->max_aggr_num); rtl8xxxu_write8(priv, REG_AMPDU_MAX_TIME_8723B, priv->fops->ampdu_max_time); rtl8xxxu_write32(priv, REG_AGGLEN_LMT, 0xffffffff); rtl8xxxu_write8(priv, REG_RX_PKT_LIMIT, 0x18); rtl8xxxu_write8(priv, REG_PIFS, 0x00); - if (priv->rtl_chip == RTL8188F || priv->rtl_chip == RTL8710B) { + if (priv->rtl_chip == RTL8188F || priv->rtl_chip == RTL8710B || + priv->rtl_chip == RTL8192F) { rtl8xxxu_write8(priv, REG_FWHW_TXQ_CTRL, FWHW_TXQ_CTRL_AMPDU_RETRY); rtl8xxxu_write32(priv, REG_FAST_EDCA_CTRL, 0x03086666); } @@ -3963,6 +4004,34 @@ void rtl8xxxu_init_burst(struct rtl8xxxu_priv *priv) rtl8xxxu_write8(priv, REG_RSV_CTRL, val8); } +static u8 rtl8xxxu_acquire_macid(struct rtl8xxxu_priv *priv) +{ + u8 macid; + + macid = find_first_zero_bit(priv->mac_id_map, RTL8XXXU_MAX_MAC_ID_NUM); + if (macid < RTL8XXXU_MAX_MAC_ID_NUM) + set_bit(macid, priv->mac_id_map); + + return macid; +} + +static void rtl8xxxu_release_macid(struct rtl8xxxu_priv *priv, u8 macid) +{ + clear_bit(macid, priv->mac_id_map); +} + +static inline u8 rtl8xxxu_get_macid(struct rtl8xxxu_priv *priv, + struct ieee80211_sta *sta) +{ + struct rtl8xxxu_sta_info *sta_info; + + if (!priv->vif || priv->vif->type == NL80211_IFTYPE_STATION || !sta) + return 0; + + sta_info = (struct rtl8xxxu_sta_info *)sta->drv_priv; + return sta_info->macid; +} + static int rtl8xxxu_init_device(struct ieee80211_hw *hw) { struct rtl8xxxu_priv *priv = hw->priv; @@ -4036,9 +4105,14 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) if (ret) goto exit; + /* Mac APLL Setting */ + if (priv->rtl_chip == RTL8192F) + rtl8xxxu_write16_set(priv, REG_AFE_CTRL4, BIT(4) | BIT(15)); + /* RFSW Control - clear bit 14 ?? */ if (priv->rtl_chip != RTL8723B && priv->rtl_chip != RTL8192E && - priv->rtl_chip != RTL8188E && priv->rtl_chip != RTL8710B) + priv->rtl_chip != RTL8188E && priv->rtl_chip != RTL8710B && + priv->rtl_chip != RTL8192F) rtl8xxxu_write32(priv, REG_FPGA0_TX_INFO, 0x00000003); val32 = FPGA0_RF_TRSW | FPGA0_RF_TRSWB | FPGA0_RF_ANTSW | @@ -4052,7 +4126,7 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) /* 0x860[6:5]= 00 - why? - this sets antenna B */ if (priv->rtl_chip != RTL8192E && priv->rtl_chip != RTL8188E && - priv->rtl_chip != RTL8710B) + priv->rtl_chip != RTL8710B && priv->rtl_chip != RTL8192F) rtl8xxxu_write32(priv, REG_FPGA0_XA_RF_INT_OE, 0x66f60210); if (!macpower) { @@ -4126,7 +4200,7 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) rtl8xxxu_write8(priv, 0xa3, val8); } - if (priv->rtl_chip == RTL8710B) + if (priv->rtl_chip == RTL8710B || priv->rtl_chip == RTL8192F) rtl8xxxu_write8(priv, REG_EARLY_MODE_CONTROL_8710B, 0); } @@ -4153,7 +4227,7 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) rtl8xxxu_write8(priv, REG_USB_SPECIAL_OPTION, val8); } else if (priv->rtl_chip == RTL8710B) { rtl8xxxu_write32(priv, REG_HIMR0_8710B, 0); - } else { + } else if (priv->rtl_chip != RTL8192F) { /* * Enable all interrupts - not obvious USB needs to do this */ @@ -4242,7 +4316,8 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) val16 = BEACON_DISABLE_TSF_UPDATE | (BEACON_DISABLE_TSF_UPDATE << 8); rtl8xxxu_write16(priv, REG_BEACON_CTRL, val16); rtl8xxxu_write16(priv, REG_TBTT_PROHIBIT, 0x6404); - if (priv->rtl_chip != RTL8188F && priv->rtl_chip != RTL8710B) + if (priv->rtl_chip != RTL8188F && priv->rtl_chip != RTL8710B && + priv->rtl_chip != RTL8192F) /* Firmware will control REG_DRVERLYINT when power saving is enable, */ /* so don't set this register on STA mode. */ rtl8xxxu_write8(priv, REG_DRIVER_EARLY_INT, DRIVER_EARLY_INT_TIME); @@ -4293,7 +4368,8 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) /* Disable BAR - not sure if this has any effect on USB */ rtl8xxxu_write32(priv, REG_BAR_MODE_CTRL, 0x0201ffff); - if (priv->rtl_chip != RTL8188F && priv->rtl_chip != RTL8188E && priv->rtl_chip != RTL8710B) + if (priv->rtl_chip != RTL8188F && priv->rtl_chip != RTL8188E && + priv->rtl_chip != RTL8710B && priv->rtl_chip != RTL8192F) rtl8xxxu_write16(priv, REG_FAST_EDCA_CTRL, 0); if (fops->init_statistics) @@ -4311,9 +4387,10 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) * Reset USB mode switch setting */ rtl8xxxu_write8(priv, REG_ACLK_MON, 0x00); - } else if (priv->rtl_chip == RTL8188F || priv->rtl_chip == RTL8188E) { + } else if (priv->rtl_chip == RTL8188F || priv->rtl_chip == RTL8188E || + priv->rtl_chip == RTL8192F) { /* - * Init GPIO settings for 8188f, 8188e + * Init GPIO settings for 8188f, 8188e, 8192f */ val8 = rtl8xxxu_read8(priv, REG_GPIO_MUXCFG); val8 &= ~GPIO_MUXCFG_IO_SEL_ENBT; @@ -4433,6 +4510,8 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) if (priv->rtl_chip == RTL8188E) rtl8188e_ra_info_init_all(&priv->ra_info); + set_bit(RTL8XXXU_BC_MC_MACID, priv->mac_id_map); + exit: return ret; } @@ -4490,6 +4569,16 @@ int rtl8xxxu_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant) return 0; } +static int rtl8xxxu_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, + bool set) +{ + struct rtl8xxxu_priv *priv = hw->priv; + + schedule_work(&priv->update_beacon_work); + + return 0; +} + static void rtl8xxxu_sw_scan_start(struct ieee80211_hw *hw, struct ieee80211_vif *vif, const u8 *mac) { @@ -4513,7 +4602,8 @@ static void rtl8xxxu_sw_scan_complete(struct ieee80211_hw *hw, } void rtl8xxxu_update_rate_mask(struct rtl8xxxu_priv *priv, - u32 ramask, u8 rateid, int sgi, int txbw_40mhz) + u32 ramask, u8 rateid, int sgi, int txbw_40mhz, + u8 macid) { struct h2c_cmd h2c; @@ -4533,7 +4623,8 @@ void rtl8xxxu_update_rate_mask(struct rtl8xxxu_priv *priv, } void rtl8xxxu_gen2_update_rate_mask(struct rtl8xxxu_priv *priv, - u32 ramask, u8 rateid, int sgi, int txbw_40mhz) + u32 ramask, u8 rateid, int sgi, int txbw_40mhz, + u8 macid) { struct h2c_cmd h2c; u8 bw; @@ -4550,6 +4641,7 @@ void rtl8xxxu_gen2_update_rate_mask(struct rtl8xxxu_priv *priv, h2c.b_macid_cfg.ramask1 = (ramask >> 8) & 0xff; h2c.b_macid_cfg.ramask2 = (ramask >> 16) & 0xff; h2c.b_macid_cfg.ramask3 = (ramask >> 24) & 0xff; + h2c.b_macid_cfg.macid = macid; h2c.b_macid_cfg.data1 = rateid; if (sgi) @@ -4563,7 +4655,7 @@ void rtl8xxxu_gen2_update_rate_mask(struct rtl8xxxu_priv *priv, } void rtl8xxxu_gen1_report_connect(struct rtl8xxxu_priv *priv, - u8 macid, bool connect) + u8 macid, u8 role, bool connect) { struct h2c_cmd h2c; @@ -4580,7 +4672,7 @@ void rtl8xxxu_gen1_report_connect(struct rtl8xxxu_priv *priv, } void rtl8xxxu_gen2_report_connect(struct rtl8xxxu_priv *priv, - u8 macid, bool connect) + u8 macid, u8 role, bool connect) { /* * The firmware turns on the rate control when it knows it's @@ -4596,6 +4688,9 @@ void rtl8xxxu_gen2_report_connect(struct rtl8xxxu_priv *priv, else h2c.media_status_rpt.parm &= ~BIT(0); + h2c.media_status_rpt.parm |= ((role << 4) & 0xf0); + h2c.media_status_rpt.macid = macid; + rtl8xxxu_gen2_h2c_cmd(priv, &h2c, sizeof(h2c.media_status_rpt)); } @@ -4912,7 +5007,8 @@ rtl8xxxu_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, priv->vif = vif; priv->rssi_level = RTL8XXXU_RATR_STA_INIT; - priv->fops->update_rate_mask(priv, ramask, 0, sgi, bw == RATE_INFO_BW_40); + priv->fops->update_rate_mask(priv, ramask, 0, sgi, + bw == RATE_INFO_BW_40, 0); rtl8xxxu_write8(priv, REG_BCN_MAX_ERR, 0xff); @@ -4922,13 +5018,13 @@ rtl8xxxu_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, rtl8xxxu_write16(priv, REG_BCN_PSR_RPT, 0xc000 | vif->cfg.aid); - priv->fops->report_connect(priv, 0, true); + priv->fops->report_connect(priv, 0, H2C_MACID_ROLE_AP, true); } else { val8 = rtl8xxxu_read8(priv, REG_BEACON_CTRL); val8 |= BEACON_DISABLE_TSF_UPDATE; rtl8xxxu_write8(priv, REG_BEACON_CTRL, val8); - priv->fops->report_connect(priv, 0, false); + priv->fops->report_connect(priv, 0, H2C_MACID_ROLE_AP, false); } } @@ -4965,10 +5061,35 @@ rtl8xxxu_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, dev_dbg(dev, "Changed BASIC_RATES!\n"); rtl8xxxu_set_basic_rates(priv, bss_conf->basic_rates); } + + if (changed & BSS_CHANGED_BEACON_ENABLED) { + if (bss_conf->enable_beacon) + rtl8xxxu_start_tx_beacon(priv); + else + rtl8xxxu_stop_tx_beacon(priv); + } + + if (changed & BSS_CHANGED_BEACON) + schedule_work(&priv->update_beacon_work); + error: return; } +static int rtl8xxxu_start_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_bss_conf *link_conf) +{ + struct rtl8xxxu_priv *priv = hw->priv; + struct device *dev = &priv->udev->dev; + + dev_dbg(dev, "Start AP mode\n"); + rtl8xxxu_set_bssid(priv, vif->bss_conf.bssid); + rtl8xxxu_write16(priv, REG_BCN_INTERVAL, vif->bss_conf.beacon_int); + priv->fops->report_connect(priv, RTL8XXXU_BC_MC_MACID, 0, true); + + return 0; +} + static u32 rtl8xxxu_80211_to_rtl_queue(u32 queue) { u32 rtlqueue; @@ -4997,7 +5118,9 @@ static u32 rtl8xxxu_queue_select(struct ieee80211_hdr *hdr, struct sk_buff *skb) { u32 queue; - if (ieee80211_is_mgmt(hdr->frame_control)) + if (unlikely(ieee80211_is_beacon(hdr->frame_control))) + queue = TXDESC_QUEUE_BEACON; + else if (ieee80211_is_mgmt(hdr->frame_control)) queue = TXDESC_QUEUE_MGNT; else queue = rtl8xxxu_80211_to_rtl_queue(skb_get_queue_mapping(skb)); @@ -5160,23 +5283,16 @@ void rtl8xxxu_fill_txdesc_v1(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr, struct ieee80211_tx_info *tx_info, struct rtl8xxxu_txdesc32 *tx_desc, bool sgi, - bool short_preamble, bool ampdu_enable, u32 rts_rate) + bool short_preamble, bool ampdu_enable, u32 rts_rate, + u8 macid) { - struct ieee80211_rate *tx_rate = ieee80211_get_tx_rate(hw, tx_info); struct rtl8xxxu_priv *priv = hw->priv; struct device *dev = &priv->udev->dev; u8 *qc = ieee80211_get_qos_ctl(hdr); u8 tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; - u32 rate; - u16 rate_flags = tx_info->control.rates[0].flags; + u32 rate = 0; u16 seq_number; - if (rate_flags & IEEE80211_TX_RC_MCS && - !ieee80211_is_mgmt(hdr->frame_control)) - rate = tx_info->control.rates[0].idx + DESC_RATE_MCS0; - else - rate = tx_rate->hw_value; - if (rtl8xxxu_debug & RTL8XXXU_DEBUG_TX) dev_info(dev, "%s: TX rate: %d, pkt size %u\n", __func__, rate, le16_to_cpu(tx_desc->pkt_size)); @@ -5215,10 +5331,10 @@ rtl8xxxu_fill_txdesc_v1(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr, * rts_rate is zero if RTS/CTS or CTS to SELF are not enabled */ tx_desc->txdw4 |= cpu_to_le32(rts_rate << TXDESC32_RTS_RATE_SHIFT); - if (ampdu_enable || (rate_flags & IEEE80211_TX_RC_USE_RTS_CTS)) { + if (ampdu_enable || tx_info->control.use_rts) { tx_desc->txdw4 |= cpu_to_le32(TXDESC32_RTS_CTS_ENABLE); tx_desc->txdw4 |= cpu_to_le32(TXDESC32_HW_RTS_ENABLE); - } else if (rate_flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { + } else if (tx_info->control.use_cts_prot) { tx_desc->txdw4 |= cpu_to_le32(TXDESC32_CTS_SELF_ENABLE); tx_desc->txdw4 |= cpu_to_le32(TXDESC32_HW_RTS_ENABLE); } @@ -5232,30 +5348,25 @@ void rtl8xxxu_fill_txdesc_v2(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr, struct ieee80211_tx_info *tx_info, struct rtl8xxxu_txdesc32 *tx_desc32, bool sgi, - bool short_preamble, bool ampdu_enable, u32 rts_rate) + bool short_preamble, bool ampdu_enable, u32 rts_rate, + u8 macid) { - struct ieee80211_rate *tx_rate = ieee80211_get_tx_rate(hw, tx_info); struct rtl8xxxu_priv *priv = hw->priv; struct device *dev = &priv->udev->dev; struct rtl8xxxu_txdesc40 *tx_desc40; u8 *qc = ieee80211_get_qos_ctl(hdr); u8 tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; - u32 rate; - u16 rate_flags = tx_info->control.rates[0].flags; + u32 rate = 0; u16 seq_number; tx_desc40 = (struct rtl8xxxu_txdesc40 *)tx_desc32; - if (rate_flags & IEEE80211_TX_RC_MCS && - !ieee80211_is_mgmt(hdr->frame_control)) - rate = tx_info->control.rates[0].idx + DESC_RATE_MCS0; - else - rate = tx_rate->hw_value; - if (rtl8xxxu_debug & RTL8XXXU_DEBUG_TX) dev_info(dev, "%s: TX rate: %d, pkt size %u\n", __func__, rate, le16_to_cpu(tx_desc40->pkt_size)); + tx_desc40->txdw1 |= cpu_to_le32(macid << TXDESC40_MACID_SHIFT); + seq_number = IEEE80211_SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl)); tx_desc40->txdw4 = cpu_to_le32(rate); @@ -5279,17 +5390,21 @@ rtl8xxxu_fill_txdesc_v2(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr, tx_desc40->txdw4 |= cpu_to_le32(TXDESC40_RETRY_LIMIT_ENABLE); } + if (tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) + tx_desc40->txdw8 |= cpu_to_le32(TXDESC40_HW_SEQ_ENABLE); + if (short_preamble) tx_desc40->txdw5 |= cpu_to_le32(TXDESC40_SHORT_PREAMBLE); tx_desc40->txdw4 |= cpu_to_le32(rts_rate << TXDESC40_RTS_RATE_SHIFT); + /* * rts_rate is zero if RTS/CTS or CTS to SELF are not enabled */ - if (ampdu_enable || (rate_flags & IEEE80211_TX_RC_USE_RTS_CTS)) { + if (ampdu_enable || tx_info->control.use_rts) { tx_desc40->txdw3 |= cpu_to_le32(TXDESC40_RTS_CTS_ENABLE); tx_desc40->txdw3 |= cpu_to_le32(TXDESC40_HW_RTS_ENABLE); - } else if (rate_flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { + } else if (tx_info->control.use_cts_prot) { /* * For some reason the vendor driver doesn't set * TXDESC40_HW_RTS_ENABLE for CTS to SELF @@ -5307,24 +5422,17 @@ void rtl8xxxu_fill_txdesc_v3(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr, struct ieee80211_tx_info *tx_info, struct rtl8xxxu_txdesc32 *tx_desc, bool sgi, - bool short_preamble, bool ampdu_enable, u32 rts_rate) + bool short_preamble, bool ampdu_enable, u32 rts_rate, + u8 macid) { - struct ieee80211_rate *tx_rate = ieee80211_get_tx_rate(hw, tx_info); struct rtl8xxxu_priv *priv = hw->priv; struct device *dev = &priv->udev->dev; struct rtl8xxxu_ra_info *ra = &priv->ra_info; u8 *qc = ieee80211_get_qos_ctl(hdr); u8 tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; - u32 rate; - u16 rate_flags = tx_info->control.rates[0].flags; + u32 rate = 0; u16 seq_number; - if (rate_flags & IEEE80211_TX_RC_MCS && - !ieee80211_is_mgmt(hdr->frame_control)) - rate = tx_info->control.rates[0].idx + DESC_RATE_MCS0; - else - rate = tx_rate->hw_value; - seq_number = IEEE80211_SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl)); if (ieee80211_is_data(hdr->frame_control)) { @@ -5377,10 +5485,10 @@ rtl8xxxu_fill_txdesc_v3(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr, * rts_rate is zero if RTS/CTS or CTS to SELF are not enabled */ tx_desc->txdw4 |= cpu_to_le32(rts_rate << TXDESC32_RTS_RATE_SHIFT); - if (ampdu_enable || (rate_flags & IEEE80211_TX_RC_USE_RTS_CTS)) { + if (ampdu_enable || tx_info->control.use_rts) { tx_desc->txdw4 |= cpu_to_le32(TXDESC32_RTS_CTS_ENABLE); tx_desc->txdw4 |= cpu_to_le32(TXDESC32_HW_RTS_ENABLE); - } else if (rate_flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { + } else if (tx_info->control.use_cts_prot) { tx_desc->txdw4 |= cpu_to_le32(TXDESC32_CTS_SELF_ENABLE); tx_desc->txdw4 |= cpu_to_le32(TXDESC32_HW_RTS_ENABLE); } @@ -5404,8 +5512,8 @@ static void rtl8xxxu_tx(struct ieee80211_hw *hw, struct device *dev = &priv->udev->dev; u32 queue, rts_rate; u16 pktlen = skb->len; - u16 rate_flag = tx_info->control.rates[0].flags; int tx_desc_size = priv->fops->tx_desc_size; + u8 macid; int ret; bool ampdu_enable, sgi = false, short_preamble = false; @@ -5444,8 +5552,10 @@ static void rtl8xxxu_tx(struct ieee80211_hw *hw, tx_desc->pkt_size = cpu_to_le16(pktlen); tx_desc->pkt_offset = tx_desc_size; - tx_desc->txdw0 = - TXDESC_OWN | TXDESC_FIRST_SEGMENT | TXDESC_LAST_SEGMENT; + /* These bits mean different things to the RTL8192F. */ + if (priv->rtl_chip != RTL8192F) + tx_desc->txdw0 = + TXDESC_OWN | TXDESC_FIRST_SEGMENT | TXDESC_LAST_SEGMENT; if (is_multicast_ether_addr(ieee80211_get_DA(hdr)) || is_broadcast_ether_addr(ieee80211_get_DA(hdr))) tx_desc->txdw0 |= TXDESC_BROADMULTICAST; @@ -5488,31 +5598,34 @@ static void rtl8xxxu_tx(struct ieee80211_hw *hw, } } - if (rate_flag & IEEE80211_TX_RC_SHORT_GI || - (ieee80211_is_data_qos(hdr->frame_control) && - sta && sta->deflink.ht_cap.cap & - (IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SGI_20))) + if (ieee80211_is_data_qos(hdr->frame_control) && + sta && sta->deflink.ht_cap.cap & + (IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SGI_20)) sgi = true; - if (rate_flag & IEEE80211_TX_RC_USE_SHORT_PREAMBLE || - (sta && vif && vif->bss_conf.use_short_preamble)) + if (sta && vif && vif->bss_conf.use_short_preamble) short_preamble = true; - if (rate_flag & IEEE80211_TX_RC_USE_RTS_CTS) - rts_rate = ieee80211_get_rts_cts_rate(hw, tx_info)->hw_value; - else if (rate_flag & IEEE80211_TX_RC_USE_CTS_PROTECT) - rts_rate = ieee80211_get_rts_cts_rate(hw, tx_info)->hw_value; + if (skb->len > hw->wiphy->rts_threshold) + tx_info->control.use_rts = true; + + if (sta && vif && vif->bss_conf.use_cts_prot) + tx_info->control.use_cts_prot = true; + + if (ampdu_enable || tx_info->control.use_rts || + tx_info->control.use_cts_prot) + rts_rate = DESC_RATE_24M; else rts_rate = 0; - + macid = rtl8xxxu_get_macid(priv, sta); priv->fops->fill_txdesc(hw, hdr, tx_info, tx_desc, sgi, short_preamble, - ampdu_enable, rts_rate); + ampdu_enable, rts_rate, macid); rtl8xxxu_calc_tx_desc_csum(tx_desc); /* avoid zero checksum make tx hang */ - if (priv->rtl_chip == RTL8710B) + if (priv->rtl_chip == RTL8710B || priv->rtl_chip == RTL8192F) tx_desc->csum = ~tx_desc->csum; usb_fill_bulk_urb(&tx_urb->urb, priv->udev, priv->pipe_out[queue], @@ -5530,6 +5643,55 @@ static void rtl8xxxu_tx(struct ieee80211_hw *hw, dev_kfree_skb(skb); } +static void rtl8xxxu_send_beacon_frame(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) +{ + struct rtl8xxxu_priv *priv = hw->priv; + struct sk_buff *skb = ieee80211_beacon_get(hw, vif, 0); + struct device *dev = &priv->udev->dev; + int retry; + u8 val8; + + /* BCN_VALID, write 1 to clear, cleared by SW */ + val8 = rtl8xxxu_read8(priv, REG_TDECTRL + 2); + val8 |= BIT_BCN_VALID >> 16; + rtl8xxxu_write8(priv, REG_TDECTRL + 2, val8); + + /* SW_BCN_SEL - Port0 */ + val8 = rtl8xxxu_read8(priv, REG_DWBCN1_CTRL_8723B + 2); + val8 &= ~(BIT_SW_BCN_SEL >> 16); + rtl8xxxu_write8(priv, REG_DWBCN1_CTRL_8723B + 2, val8); + + if (skb) + rtl8xxxu_tx(hw, NULL, skb); + + retry = 100; + do { + val8 = rtl8xxxu_read8(priv, REG_TDECTRL + 2); + if (val8 & (BIT_BCN_VALID >> 16)) + break; + usleep_range(10, 20); + } while (--retry); + + if (!retry) + dev_err(dev, "%s: Failed to read beacon valid bit\n", __func__); +} + +static void rtl8xxxu_update_beacon_work_callback(struct work_struct *work) +{ + struct rtl8xxxu_priv *priv = + container_of(work, struct rtl8xxxu_priv, update_beacon_work); + struct ieee80211_hw *hw = priv->hw; + struct ieee80211_vif *vif = priv->vif; + + if (!vif) { + WARN_ONCE(true, "no vif to update beacon\n"); + return; + } + + rtl8xxxu_send_beacon_frame(hw, vif); +} + void rtl8723au_rx_parse_phystats(struct rtl8xxxu_priv *priv, struct ieee80211_rx_status *rx_status, struct rtl8723au_phy_stats *phy_stats, @@ -6198,61 +6360,98 @@ int rtl8xxxu_parse_rxdesc16(struct rtl8xxxu_priv *priv, struct sk_buff *skb) int rtl8xxxu_parse_rxdesc24(struct rtl8xxxu_priv *priv, struct sk_buff *skb) { struct ieee80211_hw *hw = priv->hw; - struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb); - struct rtl8xxxu_rxdesc24 *rx_desc = - (struct rtl8xxxu_rxdesc24 *)skb->data; + struct ieee80211_rx_status *rx_status; + struct rtl8xxxu_rxdesc24 *rx_desc; struct rtl8723au_phy_stats *phy_stats; - __le32 *_rx_desc_le = (__le32 *)skb->data; - u32 *_rx_desc = (u32 *)skb->data; + struct sk_buff *next_skb = NULL; + __le32 *_rx_desc_le; + u32 *_rx_desc; int drvinfo_sz, desc_shift; - int i; + int i, pkt_len, urb_len, pkt_offset; - for (i = 0; i < (sizeof(struct rtl8xxxu_rxdesc24) / sizeof(u32)); i++) - _rx_desc[i] = le32_to_cpu(_rx_desc_le[i]); + urb_len = skb->len; - memset(rx_status, 0, sizeof(struct ieee80211_rx_status)); + if (urb_len < sizeof(struct rtl8xxxu_rxdesc24)) { + kfree_skb(skb); + return RX_TYPE_ERROR; + } - skb_pull(skb, sizeof(struct rtl8xxxu_rxdesc24)); + do { + rx_desc = (struct rtl8xxxu_rxdesc24 *)skb->data; + _rx_desc_le = (__le32 *)skb->data; + _rx_desc = (u32 *)skb->data; - phy_stats = (struct rtl8723au_phy_stats *)skb->data; + for (i = 0; i < (sizeof(struct rtl8xxxu_rxdesc24) / sizeof(u32)); i++) + _rx_desc[i] = le32_to_cpu(_rx_desc_le[i]); - drvinfo_sz = rx_desc->drvinfo_sz * 8; - desc_shift = rx_desc->shift; - skb_pull(skb, drvinfo_sz + desc_shift); + pkt_len = rx_desc->pktlen; - if (rx_desc->rpt_sel) { - struct device *dev = &priv->udev->dev; - dev_dbg(dev, "%s: C2H packet\n", __func__); - rtl8723bu_handle_c2h(priv, skb); - return RX_TYPE_C2H; - } + drvinfo_sz = rx_desc->drvinfo_sz * 8; + desc_shift = rx_desc->shift; + pkt_offset = roundup(pkt_len + drvinfo_sz + desc_shift + + sizeof(struct rtl8xxxu_rxdesc24), 8); + + /* + * Only clone the skb if there's enough data at the end to + * at least cover the rx descriptor + */ + if (urb_len >= (pkt_offset + sizeof(struct rtl8xxxu_rxdesc24))) + next_skb = skb_clone(skb, GFP_ATOMIC); - if (rx_desc->phy_stats) - priv->fops->parse_phystats(priv, rx_status, phy_stats, - rx_desc->rxmcs, (struct ieee80211_hdr *)skb->data, - rx_desc->crc32 || rx_desc->icverr); + rx_status = IEEE80211_SKB_RXCB(skb); + memset(rx_status, 0, sizeof(struct ieee80211_rx_status)); - rx_status->mactime = rx_desc->tsfl; - rx_status->flag |= RX_FLAG_MACTIME_START; + skb_pull(skb, sizeof(struct rtl8xxxu_rxdesc24)); - if (!rx_desc->swdec) - rx_status->flag |= RX_FLAG_DECRYPTED; - if (rx_desc->crc32) - rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; - if (rx_desc->bw) - rx_status->bw = RATE_INFO_BW_40; + phy_stats = (struct rtl8723au_phy_stats *)skb->data; - if (rx_desc->rxmcs >= DESC_RATE_MCS0) { - rx_status->encoding = RX_ENC_HT; - rx_status->rate_idx = rx_desc->rxmcs - DESC_RATE_MCS0; - } else { - rx_status->rate_idx = rx_desc->rxmcs; - } + skb_pull(skb, drvinfo_sz + desc_shift); - rx_status->freq = hw->conf.chandef.chan->center_freq; - rx_status->band = hw->conf.chandef.chan->band; + skb_trim(skb, pkt_len); + + if (rx_desc->rpt_sel) { + struct device *dev = &priv->udev->dev; + dev_dbg(dev, "%s: C2H packet\n", __func__); + rtl8723bu_handle_c2h(priv, skb); + } else { + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + + if (rx_desc->phy_stats) + priv->fops->parse_phystats(priv, rx_status, phy_stats, + rx_desc->rxmcs, hdr, + rx_desc->crc32 || rx_desc->icverr); + + rx_status->mactime = rx_desc->tsfl; + rx_status->flag |= RX_FLAG_MACTIME_START; + + if (!rx_desc->swdec) + rx_status->flag |= RX_FLAG_DECRYPTED; + if (rx_desc->crc32) + rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; + if (rx_desc->bw) + rx_status->bw = RATE_INFO_BW_40; + + if (rx_desc->rxmcs >= DESC_RATE_MCS0) { + rx_status->encoding = RX_ENC_HT; + rx_status->rate_idx = rx_desc->rxmcs - DESC_RATE_MCS0; + } else { + rx_status->rate_idx = rx_desc->rxmcs; + } + + rx_status->freq = hw->conf.chandef.chan->center_freq; + rx_status->band = hw->conf.chandef.chan->band; + + ieee80211_rx_irqsafe(hw, skb); + } + + skb = next_skb; + if (skb) + skb_pull(next_skb, pkt_offset); + + urb_len -= pkt_offset; + next_skb = NULL; + } while (skb && urb_len >= sizeof(struct rtl8xxxu_rxdesc24)); - ieee80211_rx_irqsafe(hw, skb); return RX_TYPE_DATA_PKT; } @@ -6282,7 +6481,6 @@ static void rtl8xxxu_rx_complete(struct urb *urb) cleanup: usb_free_urb(urb); dev_kfree_skb(skb); - return; } static int rtl8xxxu_submit_rx_urb(struct rtl8xxxu_priv *priv, @@ -6372,18 +6570,39 @@ static int rtl8xxxu_add_interface(struct ieee80211_hw *hw, int ret; u8 val8; + if (!priv->vif) + priv->vif = vif; + else + return -EOPNOTSUPP; + switch (vif->type) { case NL80211_IFTYPE_STATION: - if (!priv->vif) - priv->vif = vif; - else - return -EOPNOTSUPP; rtl8xxxu_stop_tx_beacon(priv); val8 = rtl8xxxu_read8(priv, REG_BEACON_CTRL); val8 |= BEACON_ATIM | BEACON_FUNCTION_ENABLE | BEACON_DISABLE_TSF_UPDATE; rtl8xxxu_write8(priv, REG_BEACON_CTRL, val8); + ret = 0; + break; + case NL80211_IFTYPE_AP: + rtl8xxxu_write8(priv, REG_BEACON_CTRL, + BEACON_DISABLE_TSF_UPDATE | BEACON_CTRL_MBSSID); + rtl8xxxu_write8(priv, REG_ATIMWND, 0x0c); /* 12ms */ + rtl8xxxu_write16(priv, REG_TSFTR_SYN_OFFSET, 0x7fff); /* ~32ms */ + rtl8xxxu_write8(priv, REG_DUAL_TSF_RST, DUAL_TSF_RESET_TSF0); + + /* enable BCN0 function */ + rtl8xxxu_write8(priv, REG_BEACON_CTRL, + BEACON_DISABLE_TSF_UPDATE | + BEACON_FUNCTION_ENABLE | BEACON_CTRL_MBSSID | + BEACON_CTRL_TX_BEACON_RPT); + + /* select BCN on port 0 */ + val8 = rtl8xxxu_read8(priv, REG_CCK_CHECK); + val8 &= ~BIT_BCN_PORT_SEL; + rtl8xxxu_write8(priv, REG_CCK_CHECK, val8); + ret = 0; break; default: @@ -6391,6 +6610,8 @@ static int rtl8xxxu_add_interface(struct ieee80211_hw *hw, } rtl8xxxu_set_linktype(priv, vif->type); + ether_addr_copy(priv->mac_addr, vif->addr); + rtl8xxxu_set_mac(priv); return ret; } @@ -6521,22 +6742,22 @@ static void rtl8xxxu_configure_filter(struct ieee80211_hw *hw, */ if (*total_flags & FIF_BCN_PRBRESP_PROMISC) - rcr &= ~RCR_CHECK_BSSID_BEACON; + rcr &= ~(RCR_CHECK_BSSID_BEACON | RCR_CHECK_BSSID_MATCH); else - rcr |= RCR_CHECK_BSSID_BEACON; + rcr |= RCR_CHECK_BSSID_BEACON | RCR_CHECK_BSSID_MATCH; + + if (priv->vif && priv->vif->type == NL80211_IFTYPE_AP) + rcr &= ~RCR_CHECK_BSSID_MATCH; if (*total_flags & FIF_CONTROL) rcr |= RCR_ACCEPT_CTRL_FRAME; else rcr &= ~RCR_ACCEPT_CTRL_FRAME; - if (*total_flags & FIF_OTHER_BSS) { + if (*total_flags & FIF_OTHER_BSS) rcr |= RCR_ACCEPT_AP; - rcr &= ~RCR_CHECK_BSSID_MATCH; - } else { + else rcr &= ~RCR_ACCEPT_AP; - rcr |= RCR_CHECK_BSSID_MATCH; - } if (*total_flags & FIF_PSPOLL) rcr |= RCR_ACCEPT_PM; @@ -6557,7 +6778,7 @@ static void rtl8xxxu_configure_filter(struct ieee80211_hw *hw, static int rtl8xxxu_set_rts_threshold(struct ieee80211_hw *hw, u32 rts) { - if (rts > 2347) + if (rts > 2347 && rts != (u32)-1) return -EINVAL; return 0; @@ -6706,7 +6927,8 @@ static u8 rtl8xxxu_signal_to_snr(int signal) } static void rtl8xxxu_refresh_rate_mask(struct rtl8xxxu_priv *priv, - int signal, struct ieee80211_sta *sta) + int signal, struct ieee80211_sta *sta, + bool force) { struct ieee80211_hw *hw = priv->hw; u16 wireless_mode; @@ -6714,6 +6936,7 @@ static void rtl8xxxu_refresh_rate_mask(struct rtl8xxxu_priv *priv, u8 txbw_40mhz; u8 snr, snr_thresh_high, snr_thresh_low; u8 go_up_gap = 5; + u8 macid = rtl8xxxu_get_macid(priv, sta); rssi_level = priv->rssi_level; snr = rtl8xxxu_signal_to_snr(signal); @@ -6740,7 +6963,7 @@ static void rtl8xxxu_refresh_rate_mask(struct rtl8xxxu_priv *priv, else rssi_level = RTL8XXXU_RATR_STA_LOW; - if (rssi_level != priv->rssi_level) { + if (rssi_level != priv->rssi_level || force) { int sgi = 0; u32 rate_bitmap = 0; @@ -6833,7 +7056,7 @@ static void rtl8xxxu_refresh_rate_mask(struct rtl8xxxu_priv *priv, } priv->rssi_level = rssi_level; - priv->fops->update_rate_mask(priv, rate_bitmap, ratr_idx, sgi, txbw_40mhz); + priv->fops->update_rate_mask(priv, rate_bitmap, ratr_idx, sgi, txbw_40mhz, macid); } } @@ -6956,7 +7179,7 @@ static void rtl8xxxu_watchdog_callback(struct work_struct *work) if (priv->fops->set_crystal_cap) rtl8xxxu_track_cfo(priv); - rtl8xxxu_refresh_rate_mask(priv, signal, sta); + rtl8xxxu_refresh_rate_mask(priv, signal, sta, false); } out: @@ -7087,6 +7310,38 @@ static void rtl8xxxu_stop(struct ieee80211_hw *hw) rtl8xxxu_free_tx_resources(priv); } +static int rtl8xxxu_sta_add(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + struct rtl8xxxu_sta_info *sta_info = (struct rtl8xxxu_sta_info *)sta->drv_priv; + struct rtl8xxxu_priv *priv = hw->priv; + + if (vif->type == NL80211_IFTYPE_AP) { + sta_info->macid = rtl8xxxu_acquire_macid(priv); + if (sta_info->macid >= RTL8XXXU_MAX_MAC_ID_NUM) + return -ENOSPC; + + rtl8xxxu_refresh_rate_mask(priv, 0, sta, true); + priv->fops->report_connect(priv, sta_info->macid, H2C_MACID_ROLE_STA, true); + } + + return 0; +} + +static int rtl8xxxu_sta_remove(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + struct rtl8xxxu_sta_info *sta_info = (struct rtl8xxxu_sta_info *)sta->drv_priv; + struct rtl8xxxu_priv *priv = hw->priv; + + if (vif->type == NL80211_IFTYPE_AP) + rtl8xxxu_release_macid(priv, sta_info->macid); + + return 0; +} + static const struct ieee80211_ops rtl8xxxu_ops = { .tx = rtl8xxxu_tx, .wake_tx_queue = ieee80211_handle_wake_tx_queue, @@ -7095,6 +7350,7 @@ static const struct ieee80211_ops rtl8xxxu_ops = { .config = rtl8xxxu_config, .conf_tx = rtl8xxxu_conf_tx, .bss_info_changed = rtl8xxxu_bss_info_changed, + .start_ap = rtl8xxxu_start_ap, .configure_filter = rtl8xxxu_configure_filter, .set_rts_threshold = rtl8xxxu_set_rts_threshold, .start = rtl8xxxu_start, @@ -7105,6 +7361,9 @@ static const struct ieee80211_ops rtl8xxxu_ops = { .ampdu_action = rtl8xxxu_ampdu_action, .sta_statistics = rtl8xxxu_sta_statistics, .get_antenna = rtl8xxxu_get_antenna, + .set_tim = rtl8xxxu_set_tim, + .sta_add = rtl8xxxu_sta_add, + .sta_remove = rtl8xxxu_sta_remove, }; static int rtl8xxxu_parse_usb(struct rtl8xxxu_priv *priv, @@ -7240,6 +7499,7 @@ static int rtl8xxxu_probe(struct usb_interface *interface, case 0xf179: case 0x8179: case 0xb711: + case 0xf192: untested = 0; break; } @@ -7264,6 +7524,10 @@ static int rtl8xxxu_probe(struct usb_interface *interface, if (id->idProduct == 0x0109) untested = 0; break; + case 0x0b05: + if (id->idProduct == 0x18f1) + untested = 0; + break; default: break; } @@ -7296,6 +7560,7 @@ static int rtl8xxxu_probe(struct usb_interface *interface, spin_lock_init(&priv->rx_urb_lock); INIT_WORK(&priv->rx_urb_wq, rtl8xxxu_rx_urb_work); INIT_DELAYED_WORK(&priv->ra_watchdog, rtl8xxxu_watchdog_callback); + INIT_WORK(&priv->update_beacon_work, rtl8xxxu_update_beacon_work_callback); skb_queue_head_init(&priv->c2hcmd_queue); usb_set_intfdata(interface, hw); @@ -7347,7 +7612,11 @@ static int rtl8xxxu_probe(struct usb_interface *interface, hw->wiphy->max_scan_ssids = 1; hw->wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN; + if (priv->fops->max_macid_num) + hw->wiphy->max_ap_assoc_sta = priv->fops->max_macid_num - 1; hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); + if (priv->fops->supports_ap) + hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP); hw->queues = 4; sband = &rtl8xxxu_supported_band; @@ -7525,6 +7794,16 @@ static const struct usb_device_id dev_table[] = { /* TOTOLINK N150UA V5 / N150UA-B */ {USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x2005, 0xff, 0xff, 0xff), .driver_info = (unsigned long)&rtl8710bu_fops}, +/* Comfast CF-826F */ +{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0xf192, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192fu_fops}, +/* Asus USB-N13 rev C1 */ +{USB_DEVICE_AND_INTERFACE_INFO(0x0b05, 0x18f1, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192fu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x7392, 0xb722, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192fu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x318b, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192fu_fops}, #ifdef CONFIG_RTL8XXXU_UNTESTED /* Still supported by rtlwifi */ {USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x8176, 0xff, 0xff, 0xff), diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h index 4dffbab494c3b8dc8c72a85429b4c4c4fd04ff42..920ee50e211536403a962349a1ca197337fa3dc7 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h @@ -67,6 +67,7 @@ #define REG_SPS0_CTRL 0x0011 #define REG_SPS_OCP_CFG 0x0018 #define REG_8192E_LDOV12_CTRL 0x0014 +#define REG_SYS_SWR_CTRL2 0x0014 #define REG_RSV_CTRL 0x001c #define RSV_CTRL_WLOCK_1C BIT(5) #define RSV_CTRL_DIS_PRST BIT(6) @@ -215,6 +216,8 @@ #define REG_HMBOX_EXT_2 0x008c #define REG_HMBOX_EXT_3 0x008e +#define REG_RSVD_1 0x0097 + /* Interrupt registers for 8192e/8723bu/8812 */ #define REG_HIMR0 0x00b0 #define IMR0_TXCCK BIT(30) /* TXRPT interrupt when CCX bit @@ -283,6 +286,7 @@ #define REG_BIST_SCAN 0x00d0 #define REG_BIST_RPT 0x00d4 #define REG_BIST_ROM_RPT 0x00d8 +#define REG_RSVD_4 0x00dc #define REG_USB_SIE_INTF 0x00e0 #define REG_PCIE_MIO_INTF 0x00e4 #define REG_PCIE_MIO_INTD 0x00e8 @@ -390,6 +394,12 @@ #define TRXDMA_CTRL_BKQ_SHIFT 10 #define TRXDMA_CTRL_MGQ_SHIFT 12 #define TRXDMA_CTRL_HIQ_SHIFT 14 +#define TRXDMA_CTRL_VOQ_SHIFT_8192F 4 +#define TRXDMA_CTRL_VIQ_SHIFT_8192F 7 +#define TRXDMA_CTRL_BEQ_SHIFT_8192F 10 +#define TRXDMA_CTRL_BKQ_SHIFT_8192F 13 +#define TRXDMA_CTRL_MGQ_SHIFT_8192F 16 +#define TRXDMA_CTRL_HIQ_SHIFT_8192F 19 #define TRXDMA_QUEUE_LOW 1 #define TRXDMA_QUEUE_NORMAL 2 #define TRXDMA_QUEUE_HIGH 3 @@ -439,7 +449,7 @@ #define LLT_OP_READ (0x2 << 30) #define LLT_OP_MASK (0x3 << 30) -#define REG_BB_ACCEESS_CTRL 0x01e8 +#define REG_BB_ACCESS_CTRL 0x01e8 #define REG_BB_ACCESS_DATA 0x01ec #define REG_HMBOX_EXT0_8723B 0x01f0 @@ -456,6 +466,7 @@ #define REG_FIFOPAGE 0x0204 #define REG_TDECTRL 0x0208 +#define BIT_BCN_VALID BIT(16) #define REG_DWBCN0_CTRL_8188F REG_TDECTRL @@ -470,6 +481,7 @@ #define AUTO_LLT_INIT_LLT BIT(16) #define REG_DWBCN1_CTRL_8723B 0x0228 +#define BIT_SW_BCN_SEL BIT(20) /* 0x0280 ~ 0x02FF RXDMA Configuration */ #define REG_RXDMA_AGG_PG_TH 0x0280 /* 0-7 : USB DMA size bits @@ -516,6 +528,7 @@ #define REG_FWHW_TXQ_CTRL 0x0420 #define FWHW_TXQ_CTRL_AMPDU_RETRY BIT(7) #define FWHW_TXQ_CTRL_XMIT_MGMT_ACK BIT(12) +#define EN_BCNQ_DL BIT(22) #define REG_HWSEQ_CTRL 0x0423 #define REG_TXPKTBUF_BCNQ_BDNY 0x0424 @@ -572,6 +585,8 @@ #define REG_ARFR1 0x0448 #define REG_ARFR2 0x044c #define REG_ARFR3 0x0450 +#define REG_CCK_CHECK 0x0454 +#define BIT_BCN_PORT_SEL BIT(5) #define REG_AMPDU_MAX_TIME_8723B 0x0456 #define REG_AGGLEN_LMT 0x0458 #define REG_AMPDU_MIN_SPACE 0x045c @@ -968,12 +983,18 @@ #define FPGA1_TX_OFDM_TXSC_MASK 0x30000000 #define REG_ANT_MAPPING1 0x0914 +#define REG_RFE_OPT 0x0920 #define REG_DPDT_CTRL 0x092c /* 8723BU */ #define REG_RFE_CTRL_ANTA_SRC 0x0930 /* 8723BU */ +#define REG_RFE_CTRL_ANT_SRC1 0x0934 +#define REG_RFE_CTRL_ANT_SRC2 0x0938 +#define REG_RFE_CTRL_ANT_SRC3 0x093c #define REG_RFE_PATH_SELECT 0x0940 /* 8723BU */ #define REG_RFE_BUFFER 0x0944 /* 8723BU */ #define REG_S0S1_PATH_SWITCH 0x0948 /* 8723BU */ +#define REG_RX_DFIR_MOD_97F 0x0948 #define REG_OFDM_RX_DFIR 0x954 +#define REG_RFE_OPT62 0x0968 #define REG_CCK0_SYSTEM 0x0a00 #define CCK0_SIDEBAND BIT(4) @@ -1033,6 +1054,8 @@ #define REG_OFDM0_FA_RSTC 0x0c0c +#define REG_DOWNSAM_FACTOR 0x0c10 + #define REG_OFDM0_XA_RX_AFE 0x0c10 #define REG_OFDM0_XA_RX_IQ_IMBALANCE 0x0c14 #define REG_OFDM0_XB_RX_IQ_IMBALANCE 0x0c1c @@ -1054,7 +1077,7 @@ #define REG_OFDM0_AGC_PARM1 0x0c70 -#define REG_OFDM0_AGCR_SSI_TABLE 0x0c78 +#define REG_OFDM0_AGC_RSSI_TABLE 0x0c78 #define REG_OFDM0_XA_TX_IQ_IMBALANCE 0x0c80 #define REG_OFDM0_XB_TX_IQ_IMBALANCE 0x0c88 @@ -1069,6 +1092,8 @@ /* 8188eu */ #define REG_ANTDIV_PARA1 0x0ca4 +#define REG_RXIQB_EXT 0x0ca8 + /* 8723bu */ #define REG_OFDM0_TX_PSDO_NOISE_WEIGHT 0x0ce4 @@ -1088,6 +1113,8 @@ #define REG_OFDM1_CSI_FIX_MASK1 0x0d40 #define REG_OFDM1_CSI_FIX_MASK2 0x0d44 +#define REG_ANAPWR1 0x0d94 + #define REG_TX_AGC_A_RATE18_06 0x0e00 #define REG_TX_AGC_A_RATE54_24 0x0e04 #define REG_TX_AGC_A_CCK1_MCS32 0x0e08 @@ -1096,6 +1123,10 @@ #define REG_TX_AGC_A_MCS11_MCS08 0x0e18 #define REG_TX_AGC_A_MCS15_MCS12 0x0e1c +#define REG_NP_ANTA 0x0e20 + +#define REG_TAP_UPD_97F 0x0e24 + #define REG_FPGA0_IQK 0x0e28 #define REG_TX_IQK_TONE_A 0x0e30 @@ -1124,19 +1155,23 @@ #define REG_RX_CCK 0x0e8c #define REG_TX_POWER_BEFORE_IQK_A 0x0e94 +#define REG_IQK_RPT_TXA 0x0e98 #define REG_TX_POWER_AFTER_IQK_A 0x0e9c #define REG_RX_POWER_BEFORE_IQK_A 0x0ea0 #define REG_RX_POWER_BEFORE_IQK_A_2 0x0ea4 #define REG_RX_POWER_AFTER_IQK_A 0x0ea8 +#define REG_IQK_RPT_RXA 0x0ea8 #define REG_RX_POWER_AFTER_IQK_A_2 0x0eac #define REG_TX_POWER_BEFORE_IQK_B 0x0eb4 +#define REG_IQK_RPT_TXB 0x0eb8 #define REG_TX_POWER_AFTER_IQK_B 0x0ebc #define REG_RX_POWER_BEFORE_IQK_B 0x0ec0 #define REG_RX_POWER_BEFORE_IQK_B_2 0x0ec4 #define REG_RX_POWER_AFTER_IQK_B 0x0ec8 +#define REG_IQK_RPT_RXB 0x0ec8 #define REG_RX_POWER_AFTER_IQK_B_2 0x0ecc #define REG_RX_OFDM 0x0ed0 @@ -1147,6 +1182,12 @@ #define REG_PMPD_ANAEN 0x0eec #define REG_FW_START_ADDRESS 0x1000 +#define REG_FW_START_ADDRESS_8192F 0x4000 + +#define REG_SW_GPIO_SHARE_CTRL_0 0x1038 +#define REG_SW_GPIO_SHARE_CTRL_1 0x103c +#define REG_GPIO_A0 0x1050 +#define REG_GPIO_B0 0x105b #define REG_USB_INFO 0xfe17 #define REG_USB_HIMR 0xfe38 @@ -1311,12 +1352,15 @@ /* * NextGen regs: 8723BU */ +#define RF6052_REG_GAIN_P1 0x35 #define RF6052_REG_T_METER_8723B 0x42 #define RF6052_REG_UNKNOWN_43 0x43 #define RF6052_REG_UNKNOWN_55 0x55 -#define RF6052_REG_UNKNOWN_56 0x56 +#define RF6052_REG_PAD_TXG 0x56 +#define RF6052_REG_TXMOD 0x58 #define RF6052_REG_RXG_MIX_SWBW 0x87 #define RF6052_REG_S0S1 0xb0 -#define RF6052_REG_UNKNOWN_DF 0xdf +#define RF6052_REG_GAIN_CCA 0xdf #define RF6052_REG_UNKNOWN_ED 0xed #define RF6052_REG_WE_LUT 0xef +#define RF6052_REG_GAIN_CTRL 0xf5 diff --git a/drivers/net/wireless/realtek/rtlwifi/base.c b/drivers/net/wireless/realtek/rtlwifi/base.c index 9e7e98b55eff805cb76d9a8c1f67ade71ce89562..807a53a97325bfd8b2e4c80c976ea587ece315f4 100644 --- a/drivers/net/wireless/realtek/rtlwifi/base.c +++ b/drivers/net/wireless/realtek/rtlwifi/base.c @@ -452,8 +452,7 @@ static int _rtl_init_deferred_work(struct ieee80211_hw *hw) /* <1> timer */ timer_setup(&rtlpriv->works.watchdog_timer, rtl_watch_dog_timer_callback, 0); - timer_setup(&rtlpriv->works.dualmac_easyconcurrent_retrytimer, - rtl_easy_concurrent_retrytimer_callback, 0); + /* <2> work queue */ rtlpriv->works.hw = hw; rtlpriv->works.rtl_wq = wq; @@ -1905,7 +1904,7 @@ EXPORT_SYMBOL(rtl_rx_ampdu_apply); void rtl_beacon_statistic(struct ieee80211_hw *hw, struct sk_buff *skb) { struct rtl_priv *rtlpriv = rtl_priv(hw); - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + struct ieee80211_hdr *hdr = rtl_get_hdr(skb); if (rtlpriv->mac80211.opmode != NL80211_IFTYPE_STATION) return; @@ -1991,7 +1990,7 @@ void rtl_scan_list_expire(struct ieee80211_hw *hw) void rtl_collect_scan_list(struct ieee80211_hw *hw, struct sk_buff *skb) { struct rtl_priv *rtlpriv = rtl_priv(hw); - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + struct ieee80211_hdr *hdr = rtl_get_hdr(skb); struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); unsigned long flags; @@ -2366,19 +2365,6 @@ static void rtl_c2hcmd_wq_callback(struct work_struct *work) rtl_c2hcmd_launcher(hw, 1); } -void rtl_easy_concurrent_retrytimer_callback(struct timer_list *t) -{ - struct rtl_priv *rtlpriv = - from_timer(rtlpriv, t, works.dualmac_easyconcurrent_retrytimer); - struct ieee80211_hw *hw = rtlpriv->hw; - struct rtl_priv *buddy_priv = rtlpriv->buddy_priv; - - if (buddy_priv == NULL) - return; - - rtlpriv->cfg->ops->dualmac_easy_concurrent(hw); -} - /********************************************************* * * frame process functions diff --git a/drivers/net/wireless/realtek/rtlwifi/base.h b/drivers/net/wireless/realtek/rtlwifi/base.h index 0e4f8a8ae3a5fcf51eb61da992e9dc3d9087b208..f081a9a90563f5388224df32f76eddd18cee0720 100644 --- a/drivers/net/wireless/realtek/rtlwifi/base.h +++ b/drivers/net/wireless/realtek/rtlwifi/base.h @@ -124,7 +124,6 @@ int rtl_send_smps_action(struct ieee80211_hw *hw, u8 *rtl_find_ie(u8 *data, unsigned int len, u8 ie); void rtl_recognize_peer(struct ieee80211_hw *hw, u8 *data, unsigned int len); u8 rtl_tid_to_ac(u8 tid); -void rtl_easy_concurrent_retrytimer_callback(struct timer_list *t); extern struct rtl_global_var rtl_global_var; void rtl_phy_scan_operation_backup(struct ieee80211_hw *hw, u8 operation); diff --git a/drivers/net/wireless/realtek/rtlwifi/core.c b/drivers/net/wireless/realtek/rtlwifi/core.c index 6f10727cdb943eddfc1edb007d382c6e4ef10e8c..4fb16f5f6f83b0b296c0ef809863855c81327cbe 100644 --- a/drivers/net/wireless/realtek/rtlwifi/core.c +++ b/drivers/net/wireless/realtek/rtlwifi/core.c @@ -1908,6 +1908,16 @@ bool rtl_cmd_send_packet(struct ieee80211_hw *hw, struct sk_buff *skb) return true; } EXPORT_SYMBOL(rtl_cmd_send_packet); + +void rtl_init_sw_leds(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + rtlpriv->ledctl.sw_led0 = LED_PIN_LED0; + rtlpriv->ledctl.sw_led1 = LED_PIN_LED1; +} +EXPORT_SYMBOL(rtl_init_sw_leds); + const struct ieee80211_ops rtl_ops = { .start = rtl_op_start, .stop = rtl_op_stop, diff --git a/drivers/net/wireless/realtek/rtlwifi/core.h b/drivers/net/wireless/realtek/rtlwifi/core.h index 345161b474423d80c9b0a81fa028ec3c2407085e..42c2d9e13bb877cd57d957eb45063fceed8490ef 100644 --- a/drivers/net/wireless/realtek/rtlwifi/core.h +++ b/drivers/net/wireless/realtek/rtlwifi/core.h @@ -51,6 +51,8 @@ enum dm_dig_connect_e { }; extern const struct ieee80211_ops rtl_ops; + +void rtl_init_sw_leds(struct ieee80211_hw *hw); void rtl_fw_cb(const struct firmware *firmware, void *context); void rtl_wowlan_fw_cb(const struct firmware *firmware, void *context); void rtl_addr_delay(u32 addr); diff --git a/drivers/net/wireless/realtek/rtlwifi/pci.c b/drivers/net/wireless/realtek/rtlwifi/pci.c index ca79f652fef3c1f6a23b66e677eda86a56e55fe6..9886e719739be0533a0ce24c8792593669e2481d 100644 --- a/drivers/net/wireless/realtek/rtlwifi/pci.c +++ b/drivers/net/wireless/realtek/rtlwifi/pci.c @@ -482,11 +482,6 @@ static void _rtl_pci_tx_chk_waitq(struct ieee80211_hw *hw) if (!rtlpriv->rtlhal.earlymode_enable) return; - if (rtlpriv->dm.supp_phymode_switch && - (rtlpriv->easy_concurrent_ctl.switch_in_process || - (rtlpriv->buddy_priv && - rtlpriv->buddy_priv->easy_concurrent_ctl.switch_in_process))) - return; /* we just use em for BE/BK/VI/VO */ for (tid = 7; tid >= 0; tid--) { u8 hw_queue = ac_to_hwq[rtl_tid_to_ac(tid)]; @@ -2265,7 +2260,7 @@ int rtl_pci_probe(struct pci_dev *pdev, err = -ENODEV; goto fail3; } - rtlpriv->cfg->ops->init_sw_leds(hw); + rtl_init_sw_leds(hw); /*aspm */ rtl_pci_init_aspm(hw); diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/hw.c index de61c9c0ddec45b14e5847865e48a92b4d6b0e3b..58b1a46066b57d96fa17e9a95186c651e73dd4ac 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/hw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/hw.c @@ -803,17 +803,17 @@ static void _rtl88ee_gen_refresh_led_state(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - struct rtl_led *pled0 = &rtlpriv->ledctl.sw_led0; + enum rtl_led_pin pin0 = rtlpriv->ledctl.sw_led0; if (rtlpriv->rtlhal.up_first_time) return; if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS) - rtl88ee_sw_led_on(hw, pled0); + rtl88ee_sw_led_on(hw, pin0); else if (ppsc->rfoff_reason == RF_CHANGE_BY_INIT) - rtl88ee_sw_led_on(hw, pled0); + rtl88ee_sw_led_on(hw, pin0); else - rtl88ee_sw_led_off(hw, pled0); + rtl88ee_sw_led_off(hw, pin0); } static bool _rtl88ee_init_mac(struct ieee80211_hw *hw) diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/led.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/led.c index 006b979da1c6bf822ddfc7340c8d5b1d9ef1e7a5..b57ba45902f91a346e01d9732541f5de2f0259fb 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/led.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/led.c @@ -6,23 +6,15 @@ #include "reg.h" #include "led.h" -static void _rtl88ee_init_led(struct ieee80211_hw *hw, - struct rtl_led *pled, enum rtl_led_pin ledpin) -{ - pled->hw = hw; - pled->ledpin = ledpin; - pled->ledon = false; -} - -void rtl88ee_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled) +void rtl88ee_sw_led_on(struct ieee80211_hw *hw, enum rtl_led_pin pin) { u8 ledcfg; struct rtl_priv *rtlpriv = rtl_priv(hw); rtl_dbg(rtlpriv, COMP_LED, DBG_LOUD, - "LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pled->ledpin); + "LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pin); - switch (pled->ledpin) { + switch (pin) { case LED_PIN_GPIO0: break; case LED_PIN_LED0: @@ -36,21 +28,20 @@ void rtl88ee_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled) break; default: rtl_dbg(rtlpriv, COMP_ERR, DBG_LOUD, - "switch case %#x not processed\n", pled->ledpin); + "switch case %#x not processed\n", pin); break; } - pled->ledon = true; } -void rtl88ee_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled) +void rtl88ee_sw_led_off(struct ieee80211_hw *hw, enum rtl_led_pin pin) { struct rtl_priv *rtlpriv = rtl_priv(hw); u8 ledcfg; rtl_dbg(rtlpriv, COMP_LED, DBG_LOUD, - "LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pled->ledpin); + "LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pin); - switch (pled->ledpin) { + switch (pin) { case LED_PIN_GPIO0: break; case LED_PIN_LED0: @@ -73,34 +64,25 @@ void rtl88ee_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled) break; default: rtl_dbg(rtlpriv, COMP_ERR, DBG_LOUD, - "switch case %#x not processed\n", pled->ledpin); + "switch case %#x not processed\n", pin); break; } - pled->ledon = false; -} - -void rtl88ee_init_sw_leds(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - _rtl88ee_init_led(hw, &rtlpriv->ledctl.sw_led0, LED_PIN_LED0); - _rtl88ee_init_led(hw, &rtlpriv->ledctl.sw_led1, LED_PIN_LED1); } static void _rtl88ee_sw_led_control(struct ieee80211_hw *hw, enum led_ctl_mode ledaction) { struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_led *pled0 = &rtlpriv->ledctl.sw_led0; + enum rtl_led_pin pin0 = rtlpriv->ledctl.sw_led0; switch (ledaction) { case LED_CTL_POWER_ON: case LED_CTL_LINK: case LED_CTL_NO_LINK: - rtl88ee_sw_led_on(hw, pled0); + rtl88ee_sw_led_on(hw, pin0); break; case LED_CTL_POWER_OFF: - rtl88ee_sw_led_off(hw, pled0); + rtl88ee_sw_led_off(hw, pin0); break; default: break; diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/led.h b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/led.h index 67d3dc389ba0a37e4886bb668899e31dfeba07c3..e5cc35d4c298b92ea144758760f1a7bfa9da48dc 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/led.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/led.h @@ -4,9 +4,8 @@ #ifndef __RTL92CE_LED_H__ #define __RTL92CE_LED_H__ -void rtl88ee_init_sw_leds(struct ieee80211_hw *hw); -void rtl88ee_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled); -void rtl88ee_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled); +void rtl88ee_sw_led_on(struct ieee80211_hw *hw, enum rtl_led_pin pin); +void rtl88ee_sw_led_off(struct ieee80211_hw *hw, enum rtl_led_pin pin); void rtl88ee_led_control(struct ieee80211_hw *hw, enum led_ctl_mode ledaction); #endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.c index 02b77521b5cdaf9e55996ca270b16c9d200b4822..b77937fe24483264c6bec37a4187040310cca091 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.c @@ -230,7 +230,6 @@ static struct rtl_hal_ops rtl8188ee_hal_ops = { .tx_polling = rtl88ee_tx_polling, .enable_hw_sec = rtl88ee_enable_hw_security_config, .set_key = rtl88ee_set_key, - .init_sw_leds = rtl88ee_init_sw_leds, .get_bbreg = rtl88e_phy_query_bb_reg, .set_bbreg = rtl88e_phy_set_bb_reg, .get_rfreg = rtl88e_phy_query_rf_reg, diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.c index 6e4741e9483f60a8232c62341da304986a6b62df..65ebe52883d3f5c399f039daad66be05d9ef54e1 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.c @@ -674,7 +674,7 @@ void rtl88ee_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 fw_queue = QSLT_BEACON; __le32 *pdesc = (__le32 *)pdesc8; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data); + struct ieee80211_hdr *hdr = rtl_get_hdr(skb); __le16 fc = hdr->frame_control; dma_addr_t mapping = dma_map_single(&rtlpci->pdev->dev, skb->data, diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.c index dc480323c9cbff5729d950964737aa60a4d8b653..049c4fe9eeed4bf1234aee1a8c23e365eae028bc 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.c @@ -639,17 +639,17 @@ static void _rtl92ce_gen_refresh_led_state(struct ieee80211_hw *hw) struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - struct rtl_led *pled0 = &rtlpriv->ledctl.sw_led0; + enum rtl_led_pin pin0 = rtlpriv->ledctl.sw_led0; if (rtlpci->up_first_time) return; if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS) - rtl92ce_sw_led_on(hw, pled0); + rtl92ce_sw_led_on(hw, pin0); else if (ppsc->rfoff_reason == RF_CHANGE_BY_INIT) - rtl92ce_sw_led_on(hw, pled0); + rtl92ce_sw_led_on(hw, pin0); else - rtl92ce_sw_led_off(hw, pled0); + rtl92ce_sw_led_off(hw, pin0); } static bool _rtl92ce_init_mac(struct ieee80211_hw *hw) diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/led.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/led.c index 57132278eb5c6a30b9c36111f11d8e5b58463994..9d3ffed13ba89dce8f51b0c25398c694d92dd79c 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/led.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/led.c @@ -6,25 +6,17 @@ #include "reg.h" #include "led.h" -static void _rtl92ce_init_led(struct ieee80211_hw *hw, - struct rtl_led *pled, enum rtl_led_pin ledpin) -{ - pled->hw = hw; - pled->ledpin = ledpin; - pled->ledon = false; -} - -void rtl92ce_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled) +void rtl92ce_sw_led_on(struct ieee80211_hw *hw, enum rtl_led_pin pin) { u8 ledcfg; struct rtl_priv *rtlpriv = rtl_priv(hw); rtl_dbg(rtlpriv, COMP_LED, DBG_LOUD, "LedAddr:%X ledpin=%d\n", - REG_LEDCFG2, pled->ledpin); + REG_LEDCFG2, pin); ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG2); - switch (pled->ledpin) { + switch (pin) { case LED_PIN_GPIO0: break; case LED_PIN_LED0: @@ -35,24 +27,22 @@ void rtl92ce_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled) rtl_write_byte(rtlpriv, REG_LEDCFG2, (ledcfg & 0x0f) | BIT(5)); break; default: - pr_err("switch case %#x not processed\n", - pled->ledpin); + pr_err("switch case %#x not processed\n", pin); break; } - pled->ledon = true; } -void rtl92ce_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled) +void rtl92ce_sw_led_off(struct ieee80211_hw *hw, enum rtl_led_pin pin) { struct rtl_priv *rtlpriv = rtl_priv(hw); u8 ledcfg; rtl_dbg(rtlpriv, COMP_LED, DBG_LOUD, "LedAddr:%X ledpin=%d\n", - REG_LEDCFG2, pled->ledpin); + REG_LEDCFG2, pin); ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG2); - switch (pled->ledpin) { + switch (pin) { case LED_PIN_GPIO0: break; case LED_PIN_LED0: @@ -69,34 +59,25 @@ void rtl92ce_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled) rtl_write_byte(rtlpriv, REG_LEDCFG2, (ledcfg | BIT(3))); break; default: - pr_info("switch case %#x not processed\n", pled->ledpin); + pr_info("switch case %#x not processed\n", pin); break; } - pled->ledon = false; -} - -void rtl92ce_init_sw_leds(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - _rtl92ce_init_led(hw, &rtlpriv->ledctl.sw_led0, LED_PIN_LED0); - _rtl92ce_init_led(hw, &rtlpriv->ledctl.sw_led1, LED_PIN_LED1); } static void _rtl92ce_sw_led_control(struct ieee80211_hw *hw, enum led_ctl_mode ledaction) { struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_led *pled0 = &rtlpriv->ledctl.sw_led0; + enum rtl_led_pin pin0 = rtlpriv->ledctl.sw_led0; switch (ledaction) { case LED_CTL_POWER_ON: case LED_CTL_LINK: case LED_CTL_NO_LINK: - rtl92ce_sw_led_on(hw, pled0); + rtl92ce_sw_led_on(hw, pin0); break; case LED_CTL_POWER_OFF: - rtl92ce_sw_led_off(hw, pled0); + rtl92ce_sw_led_off(hw, pin0); break; default: break; diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/led.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/led.h index 97ab1e00af5fa3275f69cf0290a4b41871607662..66dc28d620030d4fcd9c9b101385ba991ec54f5e 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/led.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/led.h @@ -4,9 +4,8 @@ #ifndef __RTL92CE_LED_H__ #define __RTL92CE_LED_H__ -void rtl92ce_init_sw_leds(struct ieee80211_hw *hw); -void rtl92ce_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled); -void rtl92ce_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled); +void rtl92ce_sw_led_on(struct ieee80211_hw *hw, enum rtl_led_pin pin); +void rtl92ce_sw_led_off(struct ieee80211_hw *hw, enum rtl_led_pin pin); void rtl92ce_led_control(struct ieee80211_hw *hw, enum led_ctl_mode ledaction); #endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.c index ed68c850f9a2f4c054ead85d80ee7c6b127fde94..e452275d87894dc0e3f67f3aafed937f5e7fdb52 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.c @@ -207,7 +207,6 @@ static struct rtl_hal_ops rtl8192ce_hal_ops = { .tx_polling = rtl92ce_tx_polling, .enable_hw_sec = rtl92ce_enable_hw_security_config, .set_key = rtl92ce_set_key, - .init_sw_leds = rtl92ce_init_sw_leds, .get_bbreg = rtl92c_phy_query_bb_reg, .set_bbreg = rtl92c_phy_set_bb_reg, .set_rfreg = rtl92ce_phy_set_rf_reg, diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.c index 730c7e939bd2e0cdb0bdd74f8af65db1171fdde8..5376bb34251f7c5a29e43f78693f27836a4d8df5 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.c @@ -527,7 +527,7 @@ void rtl92ce_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 fw_queue = QSLT_BEACON; __le32 *pdesc = (__le32 *)pdesc8; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data); + struct ieee80211_hdr *hdr = rtl_get_hdr(skb); __le16 fc = hdr->frame_control; dma_addr_t mapping = dma_map_single(&rtlpci->pdev->dev, skb->data, diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/led.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/led.c index 1488f52a2d2f30bc0965b17fa039db28aa0f37d7..bfc07efd0eb0e93acc083ae63573d7144e402ac8 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/led.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/led.c @@ -6,27 +6,15 @@ #include "reg.h" #include "led.h" -static void _rtl92cu_init_led(struct ieee80211_hw *hw, - struct rtl_led *pled, enum rtl_led_pin ledpin) -{ - pled->hw = hw; - pled->ledpin = ledpin; - pled->ledon = false; -} - -static void rtl92cu_deinit_led(struct rtl_led *pled) -{ -} - -void rtl92cu_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled) +void rtl92cu_sw_led_on(struct ieee80211_hw *hw, enum rtl_led_pin pin) { u8 ledcfg; struct rtl_priv *rtlpriv = rtl_priv(hw); rtl_dbg(rtlpriv, COMP_LED, DBG_LOUD, "LedAddr:%X ledpin=%d\n", - REG_LEDCFG2, pled->ledpin); + REG_LEDCFG2, pin); ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG2); - switch (pled->ledpin) { + switch (pin) { case LED_PIN_GPIO0: break; case LED_PIN_LED0: @@ -37,22 +25,20 @@ void rtl92cu_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled) rtl_write_byte(rtlpriv, REG_LEDCFG2, (ledcfg & 0x0f) | BIT(5)); break; default: - pr_err("switch case %#x not processed\n", - pled->ledpin); + pr_err("switch case %#x not processed\n", pin); break; } - pled->ledon = true; } -void rtl92cu_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled) +void rtl92cu_sw_led_off(struct ieee80211_hw *hw, enum rtl_led_pin pin) { struct rtl_priv *rtlpriv = rtl_priv(hw); u8 ledcfg; rtl_dbg(rtlpriv, COMP_LED, DBG_LOUD, "LedAddr:%X ledpin=%d\n", - REG_LEDCFG2, pled->ledpin); + REG_LEDCFG2, pin); ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG2); - switch (pled->ledpin) { + switch (pin) { case LED_PIN_GPIO0: break; case LED_PIN_LED0: @@ -69,36 +55,13 @@ void rtl92cu_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled) rtl_write_byte(rtlpriv, REG_LEDCFG2, (ledcfg | BIT(3))); break; default: - pr_err("switch case %#x not processed\n", - pled->ledpin); + pr_err("switch case %#x not processed\n", pin); break; } - pled->ledon = false; -} - -void rtl92cu_init_sw_leds(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - _rtl92cu_init_led(hw, &rtlpriv->ledctl.sw_led0, LED_PIN_LED0); - _rtl92cu_init_led(hw, &rtlpriv->ledctl.sw_led1, LED_PIN_LED1); -} - -void rtl92cu_deinit_sw_leds(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - rtl92cu_deinit_led(&rtlpriv->ledctl.sw_led0); - rtl92cu_deinit_led(&rtlpriv->ledctl.sw_led1); -} - -static void _rtl92cu_sw_led_control(struct ieee80211_hw *hw, - enum led_ctl_mode ledaction) -{ } void rtl92cu_led_control(struct ieee80211_hw *hw, - enum led_ctl_mode ledaction) + enum led_ctl_mode ledaction) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); @@ -114,5 +77,4 @@ void rtl92cu_led_control(struct ieee80211_hw *hw, return; } rtl_dbg(rtlpriv, COMP_LED, DBG_LOUD, "ledaction %d\n", ledaction); - _rtl92cu_sw_led_control(hw, ledaction); } diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/led.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/led.h index 3fc1e7c8f78b447bdf699f559f070392c3af3f8e..8175f8bddd6d8e90516c291bd619225d9ab70bc4 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/led.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/led.h @@ -4,10 +4,8 @@ #ifndef __RTL92CU_LED_H__ #define __RTL92CU_LED_H__ -void rtl92cu_init_sw_leds(struct ieee80211_hw *hw); -void rtl92cu_deinit_sw_leds(struct ieee80211_hw *hw); -void rtl92cu_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled); -void rtl92cu_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled); +void rtl92cu_sw_led_on(struct ieee80211_hw *hw, enum rtl_led_pin pin); +void rtl92cu_sw_led_off(struct ieee80211_hw *hw, enum rtl_led_pin pin); void rtl92cu_led_control(struct ieee80211_hw *hw, enum led_ctl_mode ledaction); #endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.c index 876c14d46c2fa6564fe434b6c4874754c9ba7940..e6403d4c937c8cd21b9945aa1689b8b55f990dca 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.c @@ -115,8 +115,6 @@ static struct rtl_hal_ops rtl8192cu_hal_ops = { .led_control = rtl92cu_led_control, .enable_hw_sec = rtl92cu_enable_hw_security_config, .set_key = rtl92c_set_key, - .init_sw_leds = rtl92cu_init_sw_leds, - .deinit_sw_leds = rtl92cu_deinit_sw_leds, .get_bbreg = rtl92c_phy_query_bb_reg, .set_bbreg = rtl92c_phy_set_bb_reg, .get_rfreg = rtl92cu_phy_query_rf_reg, diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c index ae3c4f97637ebcce2b89aa6032f98e04bde962d2..b70767e72f3d9b151e00b71f6863d7e58007e96a 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c @@ -394,7 +394,7 @@ static void _rtl_rx_process(struct ieee80211_hw *hw, struct sk_buff *skb) (struct rx_desc_92c *)rxdesc, p_drvinfo); } skb_pull(skb, (drvinfo_len + RTL_RX_DESC_SIZE)); - hdr = (struct ieee80211_hdr *)(skb->data); + hdr = rtl_get_hdr(skb); fc = hdr->frame_control; bv = ieee80211_is_probe_resp(fc); if (bv) @@ -632,7 +632,7 @@ void rtl92cu_tx_fill_cmddesc(struct ieee80211_hw *hw, { struct rtl_priv *rtlpriv = rtl_priv(hw); u8 fw_queue = QSLT_BEACON; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data); + struct ieee80211_hdr *hdr = rtl_get_hdr(skb); __le16 fc = hdr->frame_control; __le32 *pdesc = (__le32 *)pdesc8; diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/hw.c index df1e36fbc348ac123d663d6460baf94c5f829b37..31a18bbface94c55e8614ad52a083d50cde10f35 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/hw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/hw.c @@ -595,16 +595,16 @@ static void _rtl92de_gen_refresh_led_state(struct ieee80211_hw *hw) struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - struct rtl_led *pled0 = &rtlpriv->ledctl.sw_led0; + enum rtl_led_pin pin0 = rtlpriv->ledctl.sw_led0; if (rtlpci->up_first_time) return; if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS) - rtl92de_sw_led_on(hw, pled0); + rtl92de_sw_led_on(hw, pin0); else if (ppsc->rfoff_reason == RF_CHANGE_BY_INIT) - rtl92de_sw_led_on(hw, pled0); + rtl92de_sw_led_on(hw, pin0); else - rtl92de_sw_led_off(hw, pled0); + rtl92de_sw_led_off(hw, pin0); } static bool _rtl92de_init_mac(struct ieee80211_hw *hw) diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/led.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/led.c index 93d1c6a610c3483a1c794b1e6871ed7ea7d2c31a..4bd708570992c0509b13b6a1d8d5bb69480e7c9e 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/led.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/led.c @@ -6,23 +6,15 @@ #include "reg.h" #include "led.h" -static void _rtl92ce_init_led(struct ieee80211_hw *hw, - struct rtl_led *pled, enum rtl_led_pin ledpin) -{ - pled->hw = hw; - pled->ledpin = ledpin; - pled->ledon = false; -} - -void rtl92de_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled) +void rtl92de_sw_led_on(struct ieee80211_hw *hw, enum rtl_led_pin pin) { u8 ledcfg; struct rtl_priv *rtlpriv = rtl_priv(hw); rtl_dbg(rtlpriv, COMP_LED, DBG_LOUD, "LedAddr:%X ledpin=%d\n", - REG_LEDCFG2, pled->ledpin); + REG_LEDCFG2, pin); - switch (pled->ledpin) { + switch (pin) { case LED_PIN_GPIO0: break; case LED_PIN_LED0: @@ -44,24 +36,22 @@ void rtl92de_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled) rtl_write_byte(rtlpriv, REG_LEDCFG2, (ledcfg & 0x0f) | BIT(5)); break; default: - pr_err("switch case %#x not processed\n", - pled->ledpin); + pr_err("switch case %#x not processed\n", pin); break; } - pled->ledon = true; } -void rtl92de_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled) +void rtl92de_sw_led_off(struct ieee80211_hw *hw, enum rtl_led_pin pin) { struct rtl_priv *rtlpriv = rtl_priv(hw); u8 ledcfg; rtl_dbg(rtlpriv, COMP_LED, DBG_LOUD, "LedAddr:%X ledpin=%d\n", - REG_LEDCFG2, pled->ledpin); + REG_LEDCFG2, pin); ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG2); - switch (pled->ledpin) { + switch (pin) { case LED_PIN_GPIO0: break; case LED_PIN_LED0: @@ -78,35 +68,25 @@ void rtl92de_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled) rtl_write_byte(rtlpriv, REG_LEDCFG2, (ledcfg | BIT(3))); break; default: - pr_err("switch case %#x not processed\n", - pled->ledpin); + pr_err("switch case %#x not processed\n", pin); break; } - pled->ledon = false; -} - -void rtl92de_init_sw_leds(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - _rtl92ce_init_led(hw, &rtlpriv->ledctl.sw_led0, LED_PIN_LED0); - _rtl92ce_init_led(hw, &rtlpriv->ledctl.sw_led1, LED_PIN_LED1); } static void _rtl92ce_sw_led_control(struct ieee80211_hw *hw, enum led_ctl_mode ledaction) { struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_led *pled0 = &rtlpriv->ledctl.sw_led0; + enum rtl_led_pin pin0 = rtlpriv->ledctl.sw_led0; switch (ledaction) { case LED_CTL_POWER_ON: case LED_CTL_LINK: case LED_CTL_NO_LINK: - rtl92de_sw_led_on(hw, pled0); + rtl92de_sw_led_on(hw, pin0); break; case LED_CTL_POWER_OFF: - rtl92de_sw_led_off(hw, pled0); + rtl92de_sw_led_off(hw, pin0); break; default: break; diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/led.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/led.h index 7599c7e5ecc3f73fe99bdb914a16e66892a28449..33e544ad6f99b7740dbe6815344737feaa11a72f 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/led.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/led.h @@ -4,9 +4,8 @@ #ifndef __RTL92CE_LED_H__ #define __RTL92CE_LED_H__ -void rtl92de_init_sw_leds(struct ieee80211_hw *hw); -void rtl92de_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled); -void rtl92de_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled); +void rtl92de_sw_led_on(struct ieee80211_hw *hw, enum rtl_led_pin pin); +void rtl92de_sw_led_off(struct ieee80211_hw *hw, enum rtl_led_pin pin); void rtl92de_led_control(struct ieee80211_hw *hw, enum led_ctl_mode ledaction); #endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.c index a74724c971b9db9e90ea4592036602e2e1a2aa28..11f319c97124af76e7797562afac09b526e0974d 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.c @@ -220,7 +220,6 @@ static struct rtl_hal_ops rtl8192de_hal_ops = { .tx_polling = rtl92de_tx_polling, .enable_hw_sec = rtl92de_enable_hw_security_config, .set_key = rtl92de_set_key, - .init_sw_leds = rtl92de_init_sw_leds, .get_bbreg = rtl92d_phy_query_bb_reg, .set_bbreg = rtl92d_phy_set_bb_reg, .get_rfreg = rtl92d_phy_query_rf_reg, diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.c index 807b66c16e111ed5ba8d5677a1346e7e7b4eb90d..c09c0c3126658a16dd7dd25b0e04631305a61f13 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.c @@ -665,7 +665,7 @@ void rtl92de_tx_fill_cmddesc(struct ieee80211_hw *hw, struct rtl_hal *rtlhal = rtl_hal(rtlpriv); u8 fw_queue = QSLT_BEACON; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data); + struct ieee80211_hdr *hdr = rtl_get_hdr(skb); __le16 fc = hdr->frame_control; __le32 *pdesc = (__le32 *)pdesc8; diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/hw.c index 47d8999e31c00c207edf8ce439ecab78f31f5485..ebb7abd0c9adf7adb8eeb8e5761dd3b10c2b6176 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/hw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/hw.c @@ -714,17 +714,17 @@ static void _rtl92ee_gen_refresh_led_state(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - struct rtl_led *pled0 = &rtlpriv->ledctl.sw_led0; + enum rtl_led_pin pin0 = rtlpriv->ledctl.sw_led0; if (rtlpriv->rtlhal.up_first_time) return; if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS) - rtl92ee_sw_led_on(hw, pled0); + rtl92ee_sw_led_on(hw, pin0); else if (ppsc->rfoff_reason == RF_CHANGE_BY_INIT) - rtl92ee_sw_led_on(hw, pled0); + rtl92ee_sw_led_on(hw, pin0); else - rtl92ee_sw_led_off(hw, pled0); + rtl92ee_sw_led_off(hw, pin0); } static bool _rtl92ee_init_mac(struct ieee80211_hw *hw) diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/led.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/led.c index fb4ea3a8481f8f021ae34bccf80eecae8f148c9a..a9b5e3c884ee444c212920a8847146177f9c7c33 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/led.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/led.c @@ -6,23 +6,15 @@ #include "reg.h" #include "led.h" -static void _rtl92ee_init_led(struct ieee80211_hw *hw, - struct rtl_led *pled, enum rtl_led_pin ledpin) -{ - pled->hw = hw; - pled->ledpin = ledpin; - pled->ledon = false; -} - -void rtl92ee_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled) +void rtl92ee_sw_led_on(struct ieee80211_hw *hw, enum rtl_led_pin pin) { u32 ledcfg; struct rtl_priv *rtlpriv = rtl_priv(hw); rtl_dbg(rtlpriv, COMP_LED, DBG_LOUD, - "LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pled->ledpin); + "LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pin); - switch (pled->ledpin) { + switch (pin) { case LED_PIN_GPIO0: break; case LED_PIN_LED0: @@ -39,21 +31,20 @@ void rtl92ee_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled) break; default: rtl_dbg(rtlpriv, COMP_ERR, DBG_LOUD, - "switch case %#x not processed\n", pled->ledpin); + "switch case %#x not processed\n", pin); break; } - pled->ledon = true; } -void rtl92ee_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled) +void rtl92ee_sw_led_off(struct ieee80211_hw *hw, enum rtl_led_pin pin) { struct rtl_priv *rtlpriv = rtl_priv(hw); u32 ledcfg; rtl_dbg(rtlpriv, COMP_LED, DBG_LOUD, - "LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pled->ledpin); + "LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pin); - switch (pled->ledpin) { + switch (pin) { case LED_PIN_GPIO0: break; case LED_PIN_LED0: @@ -69,34 +60,25 @@ void rtl92ee_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled) break; default: rtl_dbg(rtlpriv, COMP_ERR, DBG_LOUD, - "switch case %#x not processed\n", pled->ledpin); + "switch case %#x not processed\n", pin); break; } - pled->ledon = false; -} - -void rtl92ee_init_sw_leds(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - _rtl92ee_init_led(hw, &rtlpriv->ledctl.sw_led0, LED_PIN_LED0); - _rtl92ee_init_led(hw, &rtlpriv->ledctl.sw_led1, LED_PIN_LED1); } static void _rtl92ee_sw_led_control(struct ieee80211_hw *hw, enum led_ctl_mode ledaction) { struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_led *pled0 = &rtlpriv->ledctl.sw_led0; + enum rtl_led_pin pin0 = rtlpriv->ledctl.sw_led0; switch (ledaction) { case LED_CTL_POWER_ON: case LED_CTL_LINK: case LED_CTL_NO_LINK: - rtl92ee_sw_led_on(hw, pled0); + rtl92ee_sw_led_on(hw, pin0); break; case LED_CTL_POWER_OFF: - rtl92ee_sw_led_off(hw, pled0); + rtl92ee_sw_led_off(hw, pin0); break; default: break; diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/led.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/led.h index 6d775e14846fcd12eeb2cff3034804a261f77a2b..08b8ff328b632c5e8653b7e7efd1062447b05b91 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/led.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/led.h @@ -4,9 +4,8 @@ #ifndef __RTL92E_LED_H__ #define __RTL92E_LED_H__ -void rtl92ee_init_sw_leds(struct ieee80211_hw *hw); -void rtl92ee_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled); -void rtl92ee_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled); +void rtl92ee_sw_led_on(struct ieee80211_hw *hw, enum rtl_led_pin pin); +void rtl92ee_sw_led_off(struct ieee80211_hw *hw, enum rtl_led_pin pin); void rtl92ee_led_control(struct ieee80211_hw *hw, enum led_ctl_mode ledaction); #endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.c index 7a16563b3a5dac2679a2bc136d44833cdc8cac51..616a47d8d97a28d17a071b316acc4e0e0f0614ed 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.c @@ -220,7 +220,6 @@ static struct rtl_hal_ops rtl8192ee_hal_ops = { .tx_polling = rtl92ee_tx_polling, .enable_hw_sec = rtl92ee_enable_hw_security_config, .set_key = rtl92ee_set_key, - .init_sw_leds = rtl92ee_init_sw_leds, .get_bbreg = rtl92ee_phy_query_bb_reg, .set_bbreg = rtl92ee_phy_set_bb_reg, .get_rfreg = rtl92ee_phy_query_rf_reg, diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/hw.c index a8b5bf45b1bba33b19ae5681f770a41deed9d43d..e5775b94f04eeb286f6856691f1f6f297dd7c37e 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/hw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/hw.c @@ -731,12 +731,12 @@ static void _rtl92se_macconfig_before_fwdownload(struct ieee80211_hw *hw) /* After MACIO reset,we must refresh LED state. */ if ((ppsc->rfoff_reason == RF_CHANGE_BY_IPS) || (ppsc->rfoff_reason == 0)) { - struct rtl_led *pled0 = &rtlpriv->ledctl.sw_led0; + enum rtl_led_pin pin0 = rtlpriv->ledctl.sw_led0; enum rf_pwrstate rfpwr_state_toset; rfpwr_state_toset = _rtl92se_rf_onoff_detect(hw); if (rfpwr_state_toset == ERFON) - rtl92se_sw_led_on(hw, pled0); + rtl92se_sw_led_on(hw, pin0); } } @@ -1302,7 +1302,7 @@ static void _rtl92s_phy_set_rfhalt(struct ieee80211_hw *hw) struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); u8 u1btmp; - if (rtlhal->driver_going2unload) + if (rtlhal->driver_is_goingto_unload) rtl_write_byte(rtlpriv, 0x560, 0x0); /* Power save for BB/RF */ @@ -1323,7 +1323,7 @@ static void _rtl92s_phy_set_rfhalt(struct ieee80211_hw *hw) rtl_write_word(rtlpriv, CMDR, 0x57FC); rtl_write_word(rtlpriv, CMDR, 0x0000); - if (rtlhal->driver_going2unload) { + if (rtlhal->driver_is_goingto_unload) { u1btmp = rtl_read_byte(rtlpriv, (REG_SYS_FUNC_EN + 1)); u1btmp &= ~(BIT(0)); rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, u1btmp); @@ -1345,7 +1345,7 @@ static void _rtl92s_phy_set_rfhalt(struct ieee80211_hw *hw) /* Power save for MAC */ if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS && - !rtlhal->driver_going2unload) { + !rtlhal->driver_is_goingto_unload) { /* enable LED function */ rtl_write_byte(rtlpriv, 0x03, 0xF9); /* SW/HW radio off or halt adapter!! For example S3/S4 */ @@ -1371,15 +1371,15 @@ static void _rtl92se_gen_refreshledstate(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl_led *pled0 = &rtlpriv->ledctl.sw_led0; + enum rtl_led_pin pin0 = rtlpriv->ledctl.sw_led0; if (rtlpci->up_first_time) return; if (rtlpriv->psc.rfoff_reason == RF_CHANGE_BY_IPS) - rtl92se_sw_led_on(hw, pled0); + rtl92se_sw_led_on(hw, pin0); else - rtl92se_sw_led_off(hw, pled0); + rtl92se_sw_led_off(hw, pin0); } diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/led.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/led.c index ecbf425f679f8868298d93013aad96318c8ed48e..db16a325c5e6e514016753ebf54a2d6d69cd6642 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/led.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/led.c @@ -6,33 +6,17 @@ #include "reg.h" #include "led.h" -static void _rtl92se_init_led(struct ieee80211_hw *hw, - struct rtl_led *pled, enum rtl_led_pin ledpin) -{ - pled->hw = hw; - pled->ledpin = ledpin; - pled->ledon = false; -} - -void rtl92se_init_sw_leds(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - _rtl92se_init_led(hw, &rtlpriv->ledctl.sw_led0, LED_PIN_LED0); - _rtl92se_init_led(hw, &rtlpriv->ledctl.sw_led1, LED_PIN_LED1); -} - -void rtl92se_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled) +void rtl92se_sw_led_on(struct ieee80211_hw *hw, enum rtl_led_pin pin) { u8 ledcfg; struct rtl_priv *rtlpriv = rtl_priv(hw); rtl_dbg(rtlpriv, COMP_LED, DBG_LOUD, "LedAddr:%X ledpin=%d\n", - LEDCFG, pled->ledpin); + LEDCFG, pin); ledcfg = rtl_read_byte(rtlpriv, LEDCFG); - switch (pled->ledpin) { + switch (pin) { case LED_PIN_GPIO0: break; case LED_PIN_LED0: @@ -42,14 +26,12 @@ void rtl92se_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled) rtl_write_byte(rtlpriv, LEDCFG, ledcfg & 0x0f); break; default: - pr_err("switch case %#x not processed\n", - pled->ledpin); + pr_err("switch case %#x not processed\n", pin); break; } - pled->ledon = true; } -void rtl92se_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled) +void rtl92se_sw_led_off(struct ieee80211_hw *hw, enum rtl_led_pin pin) { struct rtl_priv *rtlpriv; u8 ledcfg; @@ -58,11 +40,11 @@ void rtl92se_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled) if (!rtlpriv || rtlpriv->max_fw_size) return; rtl_dbg(rtlpriv, COMP_LED, DBG_LOUD, "LedAddr:%X ledpin=%d\n", - LEDCFG, pled->ledpin); + LEDCFG, pin); ledcfg = rtl_read_byte(rtlpriv, LEDCFG); - switch (pled->ledpin) { + switch (pin) { case LED_PIN_GPIO0: break; case LED_PIN_LED0: @@ -77,27 +59,25 @@ void rtl92se_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled) rtl_write_byte(rtlpriv, LEDCFG, (ledcfg | BIT(3))); break; default: - pr_err("switch case %#x not processed\n", - pled->ledpin); + pr_err("switch case %#x not processed\n", pin); break; } - pled->ledon = false; } static void _rtl92se_sw_led_control(struct ieee80211_hw *hw, enum led_ctl_mode ledaction) { struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_led *pled0 = &rtlpriv->ledctl.sw_led0; + enum rtl_led_pin pin0 = rtlpriv->ledctl.sw_led0; switch (ledaction) { case LED_CTL_POWER_ON: case LED_CTL_LINK: case LED_CTL_NO_LINK: - rtl92se_sw_led_on(hw, pled0); + rtl92se_sw_led_on(hw, pin0); break; case LED_CTL_POWER_OFF: - rtl92se_sw_led_off(hw, pled0); + rtl92se_sw_led_off(hw, pin0); break; default: break; diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/led.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/led.h index c9e481a8d943a9f9fb74139638b2d582c9cb1cc7..43fcc3c77bc174d137791a520f01c7d10c71d790 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/led.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/led.h @@ -4,9 +4,8 @@ #ifndef __REALTEK_PCI92SE_LED_H__ #define __REALTEK_PCI92SE_LED_H__ -void rtl92se_init_sw_leds(struct ieee80211_hw *hw); -void rtl92se_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled); -void rtl92se_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled); +void rtl92se_sw_led_on(struct ieee80211_hw *hw, enum rtl_led_pin pin); +void rtl92se_sw_led_off(struct ieee80211_hw *hw, enum rtl_led_pin pin); void rtl92se_led_control(struct ieee80211_hw *hw, enum led_ctl_mode ledaction); #endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.c index 6d352a3161b8f79822708e5cd5f513e27075ef06..30bce381c3bb709915ee2109d8733b7f04c797ad 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.c @@ -260,7 +260,6 @@ static struct rtl_hal_ops rtl8192se_hal_ops = { .tx_polling = rtl92se_tx_polling, .enable_hw_sec = rtl92se_enable_hw_security_config, .set_key = rtl92se_set_key, - .init_sw_leds = rtl92se_init_sw_leds, .get_bbreg = rtl92s_phy_query_bb_reg, .set_bbreg = rtl92s_phy_set_bb_reg, .get_rfreg = rtl92s_phy_query_rf_reg, diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hw.c index 965d98b9b09f78de2fd6be1e9fd06d5d447dae36..d26d4c4314a3d6d20e661004f764d0417eb8e1de 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hw.c @@ -643,17 +643,17 @@ static void _rtl8723e_gen_refresh_led_state(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - struct rtl_led *pled0 = &rtlpriv->ledctl.sw_led0; + enum rtl_led_pin pin0 = rtlpriv->ledctl.sw_led0; if (rtlpriv->rtlhal.up_first_time) return; if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS) - rtl8723e_sw_led_on(hw, pled0); + rtl8723e_sw_led_on(hw, pin0); else if (ppsc->rfoff_reason == RF_CHANGE_BY_INIT) - rtl8723e_sw_led_on(hw, pled0); + rtl8723e_sw_led_on(hw, pin0); else - rtl8723e_sw_led_off(hw, pled0); + rtl8723e_sw_led_off(hw, pin0); } static bool _rtl8712e_init_mac(struct ieee80211_hw *hw) diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/led.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/led.c index 7fab02e01a8c4c4b5175feb0d005037703220922..90d3f6ae82d5e374747e11cd855b8d8a75263a62 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/led.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/led.c @@ -6,23 +6,15 @@ #include "reg.h" #include "led.h" -static void _rtl8723e_init_led(struct ieee80211_hw *hw, - struct rtl_led *pled, enum rtl_led_pin ledpin) -{ - pled->hw = hw; - pled->ledpin = ledpin; - pled->ledon = false; -} - -void rtl8723e_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled) +void rtl8723e_sw_led_on(struct ieee80211_hw *hw, enum rtl_led_pin pin) { u8 ledcfg; struct rtl_priv *rtlpriv = rtl_priv(hw); rtl_dbg(rtlpriv, COMP_LED, DBG_LOUD, - "LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pled->ledpin); + "LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pin); - switch (pled->ledpin) { + switch (pin) { case LED_PIN_GPIO0: break; case LED_PIN_LED0: @@ -36,24 +28,22 @@ void rtl8723e_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled) rtl_write_byte(rtlpriv, REG_LEDCFG1, ledcfg & 0x10); break; default: - pr_err("switch case %#x not processed\n", - pled->ledpin); + pr_err("switch case %#x not processed\n", pin); break; } - pled->ledon = true; } -void rtl8723e_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled) +void rtl8723e_sw_led_off(struct ieee80211_hw *hw, enum rtl_led_pin pin) { struct rtl_priv *rtlpriv = rtl_priv(hw); u8 ledcfg; rtl_dbg(rtlpriv, COMP_LED, DBG_LOUD, - "LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pled->ledpin); + "LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pin); ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG2); - switch (pled->ledpin) { + switch (pin) { case LED_PIN_GPIO0: break; case LED_PIN_LED0: @@ -77,35 +67,25 @@ void rtl8723e_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled) break; default: - pr_err("switch case %#x not processed\n", - pled->ledpin); + pr_err("switch case %#x not processed\n", pin); break; } - pled->ledon = false; -} - -void rtl8723e_init_sw_leds(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - _rtl8723e_init_led(hw, &rtlpriv->ledctl.sw_led0, LED_PIN_LED0); - _rtl8723e_init_led(hw, &rtlpriv->ledctl.sw_led1, LED_PIN_LED1); } static void _rtl8723e_sw_led_control(struct ieee80211_hw *hw, enum led_ctl_mode ledaction) { struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_led *pled0 = &rtlpriv->ledctl.sw_led0; + enum rtl_led_pin pin0 = rtlpriv->ledctl.sw_led0; switch (ledaction) { case LED_CTL_POWER_ON: case LED_CTL_LINK: case LED_CTL_NO_LINK: - rtl8723e_sw_led_on(hw, pled0); + rtl8723e_sw_led_on(hw, pin0); break; case LED_CTL_POWER_OFF: - rtl8723e_sw_led_off(hw, pled0); + rtl8723e_sw_led_off(hw, pin0); break; default: break; diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/led.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/led.h index 9f85845d23cd33948bd584184d9dce85a9b7736a..6db5290da8060a7d99cf434cb6e435a7ef0721e6 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/led.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/led.h @@ -4,9 +4,8 @@ #ifndef __RTL92CE_LED_H__ #define __RTL92CE_LED_H__ -void rtl8723e_init_sw_leds(struct ieee80211_hw *hw); -void rtl8723e_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled); -void rtl8723e_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled); +void rtl8723e_sw_led_on(struct ieee80211_hw *hw, enum rtl_led_pin pin); +void rtl8723e_sw_led_off(struct ieee80211_hw *hw, enum rtl_led_pin pin); void rtl8723e_led_control(struct ieee80211_hw *hw, enum led_ctl_mode ledaction); #endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.c index 7828acb1de3f2f47d1e6c21f075913a6fffe2fbb..c821436a199166a0a1498841b1d9eea4820ead96 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.c @@ -223,7 +223,6 @@ static struct rtl_hal_ops rtl8723e_hal_ops = { .tx_polling = rtl8723e_tx_polling, .enable_hw_sec = rtl8723e_enable_hw_security_config, .set_key = rtl8723e_set_key, - .init_sw_leds = rtl8723e_init_sw_leds, .get_bbreg = rtl8723_phy_query_bb_reg, .set_bbreg = rtl8723_phy_set_bb_reg, .get_rfreg = rtl8723e_phy_query_rf_reg, diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/trx.c index 27fddbcade3258cff9eb2ae2eb29a506d9dd2a5d..7f294e698994792f60534f1b15573d8594b1f5ad 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/trx.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/trx.c @@ -528,7 +528,7 @@ void rtl8723e_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 fw_queue = QSLT_BEACON; __le32 *pdesc = (__le32 *)pdesc8; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data); + struct ieee80211_hdr *hdr = rtl_get_hdr(skb); __le16 fc = hdr->frame_control; dma_addr_t mapping = dma_map_single(&rtlpci->pdev->dev, skb->data, diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c index 0ba3bbed6ed360784173f007d5203363f74ceb66..15575644551f0d8a84e787317b1605de5f03ac62 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c @@ -793,17 +793,17 @@ static void _rtl8723be_gen_refresh_led_state(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - struct rtl_led *pled0 = &rtlpriv->ledctl.sw_led0; + enum rtl_led_pin pin0 = rtlpriv->ledctl.sw_led0; if (rtlpriv->rtlhal.up_first_time) return; if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS) - rtl8723be_sw_led_on(hw, pled0); + rtl8723be_sw_led_on(hw, pin0); else if (ppsc->rfoff_reason == RF_CHANGE_BY_INIT) - rtl8723be_sw_led_on(hw, pled0); + rtl8723be_sw_led_on(hw, pin0); else - rtl8723be_sw_led_off(hw, pled0); + rtl8723be_sw_led_off(hw, pin0); } static bool _rtl8723be_init_mac(struct ieee80211_hw *hw) diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/led.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/led.c index 3954624ab314f766079f722bd320286d69c85c84..462fe1d0262b2817d996a8382e71e66c5086ab26 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/led.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/led.c @@ -6,23 +6,15 @@ #include "reg.h" #include "led.h" -static void _rtl8723be_init_led(struct ieee80211_hw *hw, struct rtl_led *pled, - enum rtl_led_pin ledpin) -{ - pled->hw = hw; - pled->ledpin = ledpin; - pled->ledon = false; -} - -void rtl8723be_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled) +void rtl8723be_sw_led_on(struct ieee80211_hw *hw, enum rtl_led_pin pin) { u8 ledcfg; struct rtl_priv *rtlpriv = rtl_priv(hw); rtl_dbg(rtlpriv, COMP_LED, DBG_LOUD, - "LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pled->ledpin); + "LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pin); - switch (pled->ledpin) { + switch (pin) { case LED_PIN_GPIO0: break; case LED_PIN_LED0: @@ -35,24 +27,22 @@ void rtl8723be_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled) rtl_write_byte(rtlpriv, REG_LEDCFG1, ledcfg & 0x10); break; default: - pr_err("switch case %#x not processed\n", - pled->ledpin); + pr_err("switch case %#x not processed\n", pin); break; } - pled->ledon = true; } -void rtl8723be_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled) +void rtl8723be_sw_led_off(struct ieee80211_hw *hw, enum rtl_led_pin pin) { struct rtl_priv *rtlpriv = rtl_priv(hw); u8 ledcfg; rtl_dbg(rtlpriv, COMP_LED, DBG_LOUD, - "LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pled->ledpin); + "LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pin); ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG2); - switch (pled->ledpin) { + switch (pin) { case LED_PIN_GPIO0: break; case LED_PIN_LED0: @@ -76,35 +66,25 @@ void rtl8723be_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled) break; default: - pr_err("switch case %#x not processed\n", - pled->ledpin); + pr_err("switch case %#x not processed\n", pin); break; } - pled->ledon = false; -} - -void rtl8723be_init_sw_leds(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - _rtl8723be_init_led(hw, &rtlpriv->ledctl.sw_led0, LED_PIN_LED0); - _rtl8723be_init_led(hw, &rtlpriv->ledctl.sw_led1, LED_PIN_LED1); } static void _rtl8723be_sw_led_control(struct ieee80211_hw *hw, enum led_ctl_mode ledaction) { struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_led *pled0 = &rtlpriv->ledctl.sw_led0; + enum rtl_led_pin pin0 = rtlpriv->ledctl.sw_led0; switch (ledaction) { case LED_CTL_POWER_ON: case LED_CTL_LINK: case LED_CTL_NO_LINK: - rtl8723be_sw_led_on(hw, pled0); + rtl8723be_sw_led_on(hw, pin0); break; case LED_CTL_POWER_OFF: - rtl8723be_sw_led_off(hw, pled0); + rtl8723be_sw_led_off(hw, pin0); break; default: break; diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/led.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/led.h index 8ac59374b632c33fe08b59f335bfacc906c4177d..3ca9277152f7d62afb15778732706b07b834865d 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/led.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/led.h @@ -4,9 +4,8 @@ #ifndef __RTL8723BE_LED_H__ #define __RTL8723BE_LED_H__ -void rtl8723be_init_sw_leds(struct ieee80211_hw *hw); -void rtl8723be_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled); -void rtl8723be_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled); +void rtl8723be_sw_led_on(struct ieee80211_hw *hw, enum rtl_led_pin pin); +void rtl8723be_sw_led_off(struct ieee80211_hw *hw, enum rtl_led_pin pin); void rtl8723be_led_control(struct ieee80211_hw *hw, enum led_ctl_mode ledaction); diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c index d220e8955e372fc423b7b8c93b0d533e9d8b26aa..43b611d5288d960d1f85b5a505387758ff7da11e 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c @@ -227,7 +227,6 @@ static struct rtl_hal_ops rtl8723be_hal_ops = { .tx_polling = rtl8723be_tx_polling, .enable_hw_sec = rtl8723be_enable_hw_security_config, .set_key = rtl8723be_set_key, - .init_sw_leds = rtl8723be_init_sw_leds, .get_bbreg = rtl8723_phy_query_bb_reg, .set_bbreg = rtl8723_phy_set_bb_reg, .get_rfreg = rtl8723be_phy_query_rf_reg, diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c index a7e3250957dc991d8e7bcf888949b95e1c53678a..3f8f6da33b12dcada076636c389059e091e4d78a 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c @@ -869,7 +869,7 @@ static void _rtl8821ae_gen_refresh_led_state(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - struct rtl_led *pled0 = &rtlpriv->ledctl.sw_led0; + enum rtl_led_pin pin0 = rtlpriv->ledctl.sw_led0; struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); if (rtlpriv->rtlhal.up_first_time) @@ -877,19 +877,19 @@ static void _rtl8821ae_gen_refresh_led_state(struct ieee80211_hw *hw) if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS) if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) - rtl8812ae_sw_led_on(hw, pled0); + rtl8812ae_sw_led_on(hw, pin0); else - rtl8821ae_sw_led_on(hw, pled0); + rtl8821ae_sw_led_on(hw, pin0); else if (ppsc->rfoff_reason == RF_CHANGE_BY_INIT) if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) - rtl8812ae_sw_led_on(hw, pled0); + rtl8812ae_sw_led_on(hw, pin0); else - rtl8821ae_sw_led_on(hw, pled0); + rtl8821ae_sw_led_on(hw, pin0); else if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) - rtl8812ae_sw_led_off(hw, pled0); + rtl8812ae_sw_led_off(hw, pin0); else - rtl8821ae_sw_led_off(hw, pled0); + rtl8821ae_sw_led_off(hw, pin0); } static bool _rtl8821ae_init_mac(struct ieee80211_hw *hw) diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/led.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/led.c index 7d6fb134c10f1c7f3cd701ee75d039f8e64ac7c0..fb003f9ce1ac192fe236803c0fed7689ddec5802 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/led.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/led.c @@ -6,24 +6,15 @@ #include "reg.h" #include "led.h" -static void _rtl8821ae_init_led(struct ieee80211_hw *hw, - struct rtl_led *pled, - enum rtl_led_pin ledpin) -{ - pled->hw = hw; - pled->ledpin = ledpin; - pled->ledon = false; -} - -void rtl8821ae_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled) +void rtl8821ae_sw_led_on(struct ieee80211_hw *hw, enum rtl_led_pin pin) { u8 ledcfg; struct rtl_priv *rtlpriv = rtl_priv(hw); rtl_dbg(rtlpriv, COMP_LED, DBG_LOUD, - "LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pled->ledpin); + "LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pin); - switch (pled->ledpin) { + switch (pin) { case LED_PIN_GPIO0: break; case LED_PIN_LED0: @@ -38,19 +29,18 @@ void rtl8821ae_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled) break; default: rtl_dbg(rtlpriv, COMP_ERR, DBG_LOUD, - "switch case %#x not processed\n", pled->ledpin); + "switch case %#x not processed\n", pin); break; } - pled->ledon = true; } -void rtl8812ae_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled) +void rtl8812ae_sw_led_on(struct ieee80211_hw *hw, enum rtl_led_pin pin) { u16 ledreg = REG_LEDCFG1; u8 ledcfg = 0; struct rtl_priv *rtlpriv = rtl_priv(hw); - switch (pled->ledpin) { + switch (pin) { case LED_PIN_LED0: ledreg = REG_LEDCFG1; break; @@ -66,27 +56,26 @@ void rtl8812ae_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled) rtl_dbg(rtlpriv, COMP_LED, DBG_LOUD, "In SwLedOn, LedAddr:%X LEDPIN=%d\n", - ledreg, pled->ledpin); + ledreg, pin); ledcfg = rtl_read_byte(rtlpriv, ledreg); ledcfg |= BIT(5); /*Set 0x4c[21]*/ ledcfg &= ~(BIT(7) | BIT(6) | BIT(3) | BIT(2) | BIT(1) | BIT(0)); /*Clear 0x4c[23:22] and 0x4c[19:16]*/ rtl_write_byte(rtlpriv, ledreg, ledcfg); /*SW control led0 on.*/ - pled->ledon = true; } -void rtl8821ae_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled) +void rtl8821ae_sw_led_off(struct ieee80211_hw *hw, enum rtl_led_pin pin) { struct rtl_priv *rtlpriv = rtl_priv(hw); u8 ledcfg; rtl_dbg(rtlpriv, COMP_LED, DBG_LOUD, - "LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pled->ledpin); + "LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pin); ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG2); - switch (pled->ledpin) { + switch (pin) { case LED_PIN_GPIO0: break; case LED_PIN_LED0: @@ -110,18 +99,17 @@ void rtl8821ae_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled) break; default: rtl_dbg(rtlpriv, COMP_ERR, DBG_LOUD, - "switch case %#x not processed\n", pled->ledpin); + "switch case %#x not processed\n", pin); break; } - pled->ledon = false; } -void rtl8812ae_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled) +void rtl8812ae_sw_led_off(struct ieee80211_hw *hw, enum rtl_led_pin pin) { u16 ledreg = REG_LEDCFG1; struct rtl_priv *rtlpriv = rtl_priv(hw); - switch (pled->ledpin) { + switch (pin) { case LED_PIN_LED0: ledreg = REG_LEDCFG1; break; @@ -137,7 +125,7 @@ void rtl8812ae_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled) rtl_dbg(rtlpriv, COMP_LED, DBG_LOUD, "In SwLedOff,LedAddr:%X LEDPIN=%d\n", - ledreg, pled->ledpin); + ledreg, pin); /*Open-drain arrangement for controlling the LED*/ if (rtlpriv->ledctl.led_opendrain) { u8 ledcfg = rtl_read_byte(rtlpriv, ledreg); @@ -152,23 +140,13 @@ void rtl8812ae_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled) } else { rtl_write_byte(rtlpriv, ledreg, 0x28); } - - pled->ledon = false; -} - -void rtl8821ae_init_sw_leds(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - _rtl8821ae_init_led(hw, &rtlpriv->ledctl.sw_led0, LED_PIN_LED0); - _rtl8821ae_init_led(hw, &rtlpriv->ledctl.sw_led1, LED_PIN_LED1); } static void _rtl8821ae_sw_led_control(struct ieee80211_hw *hw, enum led_ctl_mode ledaction) { struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_led *pled0 = &rtlpriv->ledctl.sw_led0; + enum rtl_led_pin pin0 = rtlpriv->ledctl.sw_led0; struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); switch (ledaction) { @@ -176,15 +154,15 @@ static void _rtl8821ae_sw_led_control(struct ieee80211_hw *hw, case LED_CTL_LINK: case LED_CTL_NO_LINK: if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) - rtl8812ae_sw_led_on(hw, pled0); + rtl8812ae_sw_led_on(hw, pin0); else - rtl8821ae_sw_led_on(hw, pled0); + rtl8821ae_sw_led_on(hw, pin0); break; case LED_CTL_POWER_OFF: if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) - rtl8812ae_sw_led_off(hw, pled0); + rtl8812ae_sw_led_off(hw, pin0); else - rtl8821ae_sw_led_off(hw, pled0); + rtl8821ae_sw_led_off(hw, pin0); break; default: break; diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/led.h b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/led.h index 249a37a8d9db43f499de0c7e77c81603a09ce818..76d5c0b0e39e6e830b8500db1da37a5bbc67ac6f 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/led.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/led.h @@ -4,11 +4,10 @@ #ifndef __RTL8821AE_LED_H__ #define __RTL8821AE_LED_H__ -void rtl8821ae_init_sw_leds(struct ieee80211_hw *hw); -void rtl8821ae_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled); -void rtl8812ae_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled); -void rtl8821ae_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled); -void rtl8812ae_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled); +void rtl8821ae_sw_led_on(struct ieee80211_hw *hw, enum rtl_led_pin pin); +void rtl8812ae_sw_led_on(struct ieee80211_hw *hw, enum rtl_led_pin pin); +void rtl8821ae_sw_led_off(struct ieee80211_hw *hw, enum rtl_led_pin pin); +void rtl8812ae_sw_led_off(struct ieee80211_hw *hw, enum rtl_led_pin pin); void rtl8821ae_led_control(struct ieee80211_hw *hw, enum led_ctl_mode ledaction); diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.c index 950542a24e314ac2e805f458c9298ff81278a9e0..0bca542e103f030f49c443c822d22e77bfd6469e 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.c @@ -269,7 +269,6 @@ static struct rtl_hal_ops rtl8821ae_hal_ops = { .tx_polling = rtl8821ae_tx_polling, .enable_hw_sec = rtl8821ae_enable_hw_security_config, .set_key = rtl8821ae_set_key, - .init_sw_leds = rtl8821ae_init_sw_leds, .get_bbreg = rtl8821ae_phy_query_bb_reg, .set_bbreg = rtl8821ae_phy_set_bb_reg, .get_rfreg = rtl8821ae_phy_query_rf_reg, diff --git a/drivers/net/wireless/realtek/rtlwifi/usb.c b/drivers/net/wireless/realtek/rtlwifi/usb.c index a8eebafb9a7ee2b5a7b813c537c9a3a3384ec2b5..30bf2775a335bc447e56fa8bf67cf1d52bfb6944 100644 --- a/drivers/net/wireless/realtek/rtlwifi/usb.c +++ b/drivers/net/wireless/realtek/rtlwifi/usb.c @@ -164,13 +164,17 @@ static void _usb_write_async(struct usb_device *udev, u32 addr, u32 val, u16 wvalue; u16 index; __le32 data; + int ret; request = REALTEK_USB_VENQT_CMD_REQ; index = REALTEK_USB_VENQT_CMD_IDX; /* n/a */ wvalue = (u16)(addr&0x0000ffff); data = cpu_to_le32(val); - _usbctrl_vendorreq_async_write(udev, request, wvalue, index, &data, - len); + + ret = _usbctrl_vendorreq_async_write(udev, request, wvalue, + index, &data, len); + if (ret < 0) + dev_err(&udev->dev, "error %d writing at 0x%x\n", ret, addr); } static void _usb_write8_async(struct rtl_priv *rtlpriv, u32 addr, u8 val) @@ -194,28 +198,6 @@ static void _usb_write32_async(struct rtl_priv *rtlpriv, u32 addr, u32 val) _usb_write_async(to_usb_device(dev), addr, val, 4); } -static void _usb_writen_sync(struct rtl_priv *rtlpriv, u32 addr, void *data, - u16 len) -{ - struct device *dev = rtlpriv->io.dev; - struct usb_device *udev = to_usb_device(dev); - u8 request = REALTEK_USB_VENQT_CMD_REQ; - u8 reqtype = REALTEK_USB_VENQT_WRITE; - u16 wvalue; - u16 index = REALTEK_USB_VENQT_CMD_IDX; - int pipe = usb_sndctrlpipe(udev, 0); /* write_out */ - u8 *buffer; - - wvalue = (u16)(addr & 0x0000ffff); - buffer = kmemdup(data, len, GFP_ATOMIC); - if (!buffer) - return; - usb_control_msg(udev, pipe, request, reqtype, wvalue, - index, buffer, len, 50); - - kfree(buffer); -} - static void _rtl_usb_io_handler_init(struct device *dev, struct ieee80211_hw *hw) { @@ -229,7 +211,6 @@ static void _rtl_usb_io_handler_init(struct device *dev, rtlpriv->io.read8_sync = _usb_read8_sync; rtlpriv->io.read16_sync = _usb_read16_sync; rtlpriv->io.read32_sync = _usb_read32_sync; - rtlpriv->io.writen_sync = _usb_writen_sync; } static void _rtl_usb_io_handler_release(struct ieee80211_hw *hw) @@ -433,7 +414,7 @@ static void _rtl_usb_rx_process_agg(struct ieee80211_hw *hw, skb_pull(skb, RTL_RX_DESC_SIZE); rtlpriv->cfg->ops->query_rx_desc(hw, &stats, &rx_status, rxdesc, skb); skb_pull(skb, (stats.rx_drvinfo_size + stats.rx_bufshift)); - hdr = (struct ieee80211_hdr *)(skb->data); + hdr = rtl_get_hdr(skb); fc = hdr->frame_control; if (!stats.crc) { memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status)); @@ -475,7 +456,7 @@ static void _rtl_usb_rx_process_noagg(struct ieee80211_hw *hw, skb_pull(skb, RTL_RX_DESC_SIZE); rtlpriv->cfg->ops->query_rx_desc(hw, &stats, &rx_status, rxdesc, skb); skb_pull(skb, (stats.rx_drvinfo_size + stats.rx_bufshift)); - hdr = (struct ieee80211_hdr *)(skb->data); + hdr = rtl_get_hdr(skb); fc = hdr->frame_control; if (!stats.crc) { memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status)); @@ -926,7 +907,7 @@ static void _rtl_usb_tx_preprocess(struct ieee80211_hw *hw, struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct rtl_tx_desc *pdesc = NULL; struct rtl_tcb_desc tcb_desc; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data); + struct ieee80211_hdr *hdr = rtl_get_hdr(skb); __le16 fc = hdr->frame_control; u8 *pda_addr = hdr->addr1; @@ -961,7 +942,7 @@ static int rtl_usb_tx(struct ieee80211_hw *hw, { struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw)); struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data); + struct ieee80211_hdr *hdr = rtl_get_hdr(skb); __le16 fc = hdr->frame_control; u16 hw_queue; @@ -1068,7 +1049,7 @@ int rtl_usb_probe(struct usb_interface *intf, pr_err("Can't init_sw_vars\n"); goto error_out; } - rtlpriv->cfg->ops->init_sw_leds(hw); + rtl_init_sw_leds(hw); err = ieee80211_register_hw(hw); if (err) { @@ -1117,7 +1098,6 @@ void rtl_usb_disconnect(struct usb_interface *intf) rtl_usb_deinit(hw); rtl_deinit_core(hw); kfree(rtlpriv->usb_data); - rtlpriv->cfg->ops->deinit_sw_leds(hw); rtlpriv->cfg->ops->deinit_sw_vars(hw); _rtl_usb_io_handler_release(hw); usb_put_dev(rtlusb->udev); diff --git a/drivers/net/wireless/realtek/rtlwifi/wifi.h b/drivers/net/wireless/realtek/rtlwifi/wifi.h index 082af216760f8e5aadc84b7dddfc6afc216748e4..2e7e04f91279350ad3b191ef4381050eb89edede 100644 --- a/drivers/net/wireless/realtek/rtlwifi/wifi.h +++ b/drivers/net/wireless/realtek/rtlwifi/wifi.h @@ -1070,18 +1070,10 @@ struct rtl_probe_rsp { struct rtl_info_element info_element[]; } __packed; -/*LED related.*/ -/*ledpin Identify how to implement this SW led.*/ -struct rtl_led { - void *hw; - enum rtl_led_pin ledpin; - bool ledon; -}; - struct rtl_led_ctl { bool led_opendrain; - struct rtl_led sw_led0; - struct rtl_led sw_led1; + enum rtl_led_pin sw_led0; + enum rtl_led_pin sw_led1; }; struct rtl_qos_parameters { @@ -1465,8 +1457,6 @@ struct rtl_io { void (*write8_async)(struct rtl_priv *rtlpriv, u32 addr, u8 val); void (*write16_async)(struct rtl_priv *rtlpriv, u32 addr, u16 val); void (*write32_async)(struct rtl_priv *rtlpriv, u32 addr, u32 val); - void (*writen_sync)(struct rtl_priv *rtlpriv, u32 addr, void *buf, - u16 len); u8 (*read8_sync)(struct rtl_priv *rtlpriv, u32 addr); u16 (*read16_sync)(struct rtl_priv *rtlpriv, u32 addr); @@ -1673,8 +1663,6 @@ struct rtl_hal { bool fw_clk_change_in_progress; bool allow_sw_to_change_hwclc; u8 fw_ps_state; - /**/ - bool driver_going2unload; /*AMPDU init min space*/ u8 minspace_cfg; /*For Min spacing configurations */ @@ -2289,8 +2277,6 @@ struct rtl_hal_ops { void (*set_key)(struct ieee80211_hw *hw, u32 key_index, u8 *macaddr, bool is_group, u8 enc_algo, bool is_wepkey, bool clear_all); - void (*init_sw_leds)(struct ieee80211_hw *hw); - void (*deinit_sw_leds)(struct ieee80211_hw *hw); u32 (*get_bbreg)(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask); void (*set_bbreg)(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask, u32 data); @@ -2300,7 +2286,6 @@ struct rtl_hal_ops { u32 regaddr, u32 bitmask, u32 data); void (*linked_set_reg)(struct ieee80211_hw *hw); void (*chk_switch_dmdp)(struct ieee80211_hw *hw); - void (*dualmac_easy_concurrent)(struct ieee80211_hw *hw); void (*dualmac_switch_to_dmdp)(struct ieee80211_hw *hw); bool (*phy_rf6052_config)(struct ieee80211_hw *hw); void (*phy_rf6052_set_cck_txpower)(struct ieee80211_hw *hw, @@ -2465,7 +2450,6 @@ struct rtl_works { /*timer */ struct timer_list watchdog_timer; - struct timer_list dualmac_easyconcurrent_retrytimer; struct timer_list fw_clockoff_timer; struct timer_list fast_antenna_training_timer; /*task */ @@ -2498,14 +2482,6 @@ struct rtl_debug { #define MIMO_PS_DYNAMIC 1 #define MIMO_PS_NOLIMIT 3 -struct rtl_dualmac_easy_concurrent_ctl { - enum band_type currentbandtype_backfordmdp; - bool close_bbandrf_for_dmsp; - bool change_to_dmdp; - bool change_to_dmsp; - bool switch_in_process; -}; - struct rtl_dmsp_ctl { bool activescan_for_slaveofdmsp; bool scan_for_anothermac_fordmsp; @@ -2746,7 +2722,6 @@ struct rtl_priv { struct list_head list; struct rtl_priv *buddy_priv; struct rtl_global_var *glb_var; - struct rtl_dualmac_easy_concurrent_ctl easy_concurrent_ctl; struct rtl_dmsp_ctl dmsp_ctl; struct rtl_locks locks; struct rtl_works works; diff --git a/drivers/net/wireless/realtek/rtw88/Kconfig b/drivers/net/wireless/realtek/rtw88/Kconfig index 29eb2f8e0eb79817869ab30e4b8806c20cd37f70..cffad1c012499e0cb28a533dca8f5a9537ce5645 100644 --- a/drivers/net/wireless/realtek/rtw88/Kconfig +++ b/drivers/net/wireless/realtek/rtw88/Kconfig @@ -111,6 +111,17 @@ config RTW88_8723DE 802.11n PCIe wireless network adapter +config RTW88_8723DS + tristate "Realtek 8723DS SDIO wireless network adapter" + depends on MMC + select RTW88_CORE + select RTW88_SDIO + select RTW88_8723D + help + Select this option will enable support for 8723DS chipset + + 802.11n SDIO wireless network adapter + config RTW88_8723DU tristate "Realtek 8723DU USB wireless network adapter" depends on USB diff --git a/drivers/net/wireless/realtek/rtw88/Makefile b/drivers/net/wireless/realtek/rtw88/Makefile index 82979b30ae8dd3a7b0c6901b70e02cfb935d1b0f..fd212c09d88a9ed275a81b25ba7b8f9206f45832 100644 --- a/drivers/net/wireless/realtek/rtw88/Makefile +++ b/drivers/net/wireless/realtek/rtw88/Makefile @@ -50,6 +50,9 @@ rtw88_8723d-objs := rtw8723d.o rtw8723d_table.o obj-$(CONFIG_RTW88_8723DE) += rtw88_8723de.o rtw88_8723de-objs := rtw8723de.o +obj-$(CONFIG_RTW88_8723DS) += rtw88_8723ds.o +rtw88_8723ds-objs := rtw8723ds.o + obj-$(CONFIG_RTW88_8723DU) += rtw88_8723du.o rtw88_8723du-objs := rtw8723du.o diff --git a/drivers/net/wireless/realtek/rtw88/debug.c b/drivers/net/wireless/realtek/rtw88/debug.c index fa3d73b333ba0bb34e7e41e8f9a67e33ecab1fc7..f8ba133baff0692bf357deb3245bca343fcfd354 100644 --- a/drivers/net/wireless/realtek/rtw88/debug.c +++ b/drivers/net/wireless/realtek/rtw88/debug.c @@ -183,8 +183,8 @@ static int rtw_debugfs_copy_from_user(char tmp[], int size, tmp_len = (count > size - 1 ? size - 1 : count); - if (!buffer || copy_from_user(tmp, buffer, tmp_len)) - return count; + if (copy_from_user(tmp, buffer, tmp_len)) + return -EFAULT; tmp[tmp_len] = '\0'; @@ -201,13 +201,16 @@ static ssize_t rtw_debugfs_set_read_reg(struct file *filp, char tmp[32 + 1]; u32 addr, len; int num; + int ret; - rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 2); + ret = rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 2); + if (ret) + return ret; num = sscanf(tmp, "%x %x", &addr, &len); if (num != 2) - return count; + return -EINVAL; if (len != 1 && len != 2 && len != 4) { rtw_warn(rtwdev, "read reg setting wrong len\n"); @@ -288,8 +291,11 @@ static ssize_t rtw_debugfs_set_rsvd_page(struct file *filp, char tmp[32 + 1]; u32 offset, page_num; int num; + int ret; - rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 2); + ret = rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 2); + if (ret) + return ret; num = sscanf(tmp, "%d %d", &offset, &page_num); @@ -314,8 +320,11 @@ static ssize_t rtw_debugfs_set_single_input(struct file *filp, char tmp[32 + 1]; u32 input; int num; + int ret; - rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 1); + ret = rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 1); + if (ret) + return ret; num = kstrtoint(tmp, 0, &input); @@ -338,14 +347,17 @@ static ssize_t rtw_debugfs_set_write_reg(struct file *filp, char tmp[32 + 1]; u32 addr, val, len; int num; + int ret; - rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 3); + ret = rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 3); + if (ret) + return ret; /* write BB/MAC register */ num = sscanf(tmp, "%x %x %x", &addr, &val, &len); if (num != 3) - return count; + return -EINVAL; switch (len) { case 1: @@ -381,8 +393,11 @@ static ssize_t rtw_debugfs_set_h2c(struct file *filp, char tmp[32 + 1]; u8 param[8]; int num; + int ret; - rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 3); + ret = rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 3); + if (ret) + return ret; num = sscanf(tmp, "%hhx,%hhx,%hhx,%hhx,%hhx,%hhx,%hhx,%hhx", ¶m[0], ¶m[1], ¶m[2], ¶m[3], @@ -408,14 +423,17 @@ static ssize_t rtw_debugfs_set_rf_write(struct file *filp, char tmp[32 + 1]; u32 path, addr, mask, val; int num; + int ret; - rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 4); + ret = rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 4); + if (ret) + return ret; num = sscanf(tmp, "%x %x %x %x", &path, &addr, &mask, &val); if (num != 4) { rtw_warn(rtwdev, "invalid args, [path] [addr] [mask] [val]\n"); - return count; + return -EINVAL; } mutex_lock(&rtwdev->mutex); @@ -438,14 +456,17 @@ static ssize_t rtw_debugfs_set_rf_read(struct file *filp, char tmp[32 + 1]; u32 path, addr, mask; int num; + int ret; - rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 3); + ret = rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 3); + if (ret) + return ret; num = sscanf(tmp, "%x %x %x", &path, &addr, &mask); if (num != 3) { rtw_warn(rtwdev, "invalid args, [path] [addr] [mask] [val]\n"); - return count; + return -EINVAL; } debugfs_priv->rf_path = path; @@ -467,7 +488,9 @@ static ssize_t rtw_debugfs_set_fix_rate(struct file *filp, char tmp[32 + 1]; int ret; - rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 1); + ret = rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 1); + if (ret) + return ret; ret = kstrtou8(tmp, 0, &fix_rate); if (ret) { @@ -860,7 +883,9 @@ static ssize_t rtw_debugfs_set_coex_enable(struct file *filp, bool enable; int ret; - rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 1); + ret = rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 1); + if (ret) + return ret; ret = kstrtobool(tmp, &enable); if (ret) { @@ -930,7 +955,9 @@ static ssize_t rtw_debugfs_set_fw_crash(struct file *filp, bool input; int ret; - rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 1); + ret = rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 1); + if (ret) + return ret; ret = kstrtobool(tmp, &input); if (ret) diff --git a/drivers/net/wireless/realtek/rtw88/fw.c b/drivers/net/wireless/realtek/rtw88/fw.c index 2a8ccc8a7f60d06f9795204aa30ba25097f921a6..567bbedd8ee09ba468b85b2404d27d9156756b99 100644 --- a/drivers/net/wireless/realtek/rtw88/fw.c +++ b/drivers/net/wireless/realtek/rtw88/fw.c @@ -308,6 +308,57 @@ void rtw_fw_c2h_cmd_isr(struct rtw_dev *rtwdev) } EXPORT_SYMBOL(rtw_fw_c2h_cmd_isr); +static void rtw_fw_send_h2c_command_register(struct rtw_dev *rtwdev, + struct rtw_h2c_register *h2c) +{ + u32 box_reg, box_ex_reg; + u8 box_state, box; + int ret; + + rtw_dbg(rtwdev, RTW_DBG_FW, "send H2C content %08x %08x\n", h2c->w0, + h2c->w1); + + lockdep_assert_held(&rtwdev->mutex); + + box = rtwdev->h2c.last_box_num; + switch (box) { + case 0: + box_reg = REG_HMEBOX0; + box_ex_reg = REG_HMEBOX0_EX; + break; + case 1: + box_reg = REG_HMEBOX1; + box_ex_reg = REG_HMEBOX1_EX; + break; + case 2: + box_reg = REG_HMEBOX2; + box_ex_reg = REG_HMEBOX2_EX; + break; + case 3: + box_reg = REG_HMEBOX3; + box_ex_reg = REG_HMEBOX3_EX; + break; + default: + WARN(1, "invalid h2c mail box number\n"); + return; + } + + ret = read_poll_timeout_atomic(rtw_read8, box_state, + !((box_state >> box) & 0x1), 100, 3000, + false, rtwdev, REG_HMETFR); + + if (ret) { + rtw_err(rtwdev, "failed to send h2c command\n"); + return; + } + + rtw_write32(rtwdev, box_ex_reg, h2c->w1); + rtw_write32(rtwdev, box_reg, h2c->w0); + + if (++rtwdev->h2c.last_box_num >= 4) + rtwdev->h2c.last_box_num = 0; +} + static void rtw_fw_send_h2c_command(struct rtw_dev *rtwdev, u8 *h2c) { @@ -468,6 +519,23 @@ void rtw_fw_query_bt_info(struct rtw_dev *rtwdev) rtw_fw_send_h2c_command(rtwdev, h2c_pkt); } +void rtw_fw_default_port(struct rtw_dev *rtwdev, struct rtw_vif *rtwvif) +{ + struct rtw_h2c_register h2c = {}; + + if (rtwvif->net_type != RTW_NET_MGD_LINKED) + return; + + /* Leave LPS before default port H2C so FW timer is correct */ + rtw_leave_lps(rtwdev); + + h2c.w0 = u32_encode_bits(H2C_CMD_DEFAULT_PORT, RTW_H2C_W0_CMDID) | + u32_encode_bits(rtwvif->port, RTW_H2C_DEFAULT_PORT_W0_PORTID) | + u32_encode_bits(rtwvif->mac_id, RTW_H2C_DEFAULT_PORT_W0_MACID); + + rtw_fw_send_h2c_command_register(rtwdev, &h2c); +} + void rtw_fw_wl_ch_info(struct rtw_dev *rtwdev, u8 link, u8 ch, u8 bw) { u8 h2c_pkt[H2C_PKT_SIZE] = {0}; diff --git a/drivers/net/wireless/realtek/rtw88/fw.h b/drivers/net/wireless/realtek/rtw88/fw.h index 397cbc3f6af6e9c190625e14497484b6fe128ac8..43ccdf9965ac46ea8dca247389a402c883958154 100644 --- a/drivers/net/wireless/realtek/rtw88/fw.h +++ b/drivers/net/wireless/realtek/rtw88/fw.h @@ -81,6 +81,17 @@ struct rtw_c2h_adaptivity { u8 option; } __packed; +struct rtw_h2c_register { + u32 w0; + u32 w1; +} __packed; + +#define RTW_H2C_W0_CMDID GENMASK(7, 0) + +/* H2C_CMD_DEFAULT_PORT command */ +#define RTW_H2C_DEFAULT_PORT_W0_PORTID GENMASK(15, 8) +#define RTW_H2C_DEFAULT_PORT_W0_MACID GENMASK(23, 16) + struct rtw_h2c_cmd { __le32 msg; __le32 msg_ext; @@ -530,6 +541,7 @@ static inline void rtw_h2c_pkt_set_header(u8 *h2c_pkt, u8 sub_id) #define H2C_CMD_MEDIA_STATUS_RPT 0x01 #define H2C_CMD_SET_PWR_MODE 0x20 #define H2C_CMD_LPS_PG_INFO 0x2b +#define H2C_CMD_DEFAULT_PORT 0x2c #define H2C_CMD_RA_INFO 0x40 #define H2C_CMD_RSSI_MONITOR 0x42 #define H2C_CMD_BCN_FILTER_OFFLOAD_P0 0x56 @@ -801,6 +813,7 @@ void rtw_fw_c2h_cmd_rx_irqsafe(struct rtw_dev *rtwdev, u32 pkt_offset, void rtw_fw_c2h_cmd_handle(struct rtw_dev *rtwdev, struct sk_buff *skb); void rtw_fw_send_general_info(struct rtw_dev *rtwdev); void rtw_fw_send_phydm_info(struct rtw_dev *rtwdev); +void rtw_fw_default_port(struct rtw_dev *rtwdev, struct rtw_vif *rtwvif); void rtw_fw_do_iqk(struct rtw_dev *rtwdev, struct rtw_iqk_para *para); void rtw_fw_inform_rfk_status(struct rtw_dev *rtwdev, bool start); diff --git a/drivers/net/wireless/realtek/rtw88/mac.c b/drivers/net/wireless/realtek/rtw88/mac.c index a168f36c38ece8b6341a602ebfd2587818b11e91..298663b03580853ce4d3fc171eadc332944d7cbb 100644 --- a/drivers/net/wireless/realtek/rtw88/mac.c +++ b/drivers/net/wireless/realtek/rtw88/mac.c @@ -794,8 +794,10 @@ static int __rtw_download_firmware(struct rtw_dev *rtwdev, wlan_cpu_enable(rtwdev, true); - if (!ltecoex_reg_write(rtwdev, 0x38, ltecoex_bckp)) - return -EBUSY; + if (!ltecoex_reg_write(rtwdev, 0x38, ltecoex_bckp)) { + ret = -EBUSY; + goto dlfw_fail; + } ret = download_firmware_validate(rtwdev); if (ret) diff --git a/drivers/net/wireless/realtek/rtw88/mac80211.c b/drivers/net/wireless/realtek/rtw88/mac80211.c index 144618bb94c8654ad731dc872286dc068d0df801..a99b53d4426763dd719beeef43235fd6dd072184 100644 --- a/drivers/net/wireless/realtek/rtw88/mac80211.c +++ b/drivers/net/wireless/realtek/rtw88/mac80211.c @@ -43,7 +43,11 @@ static void rtw_ops_wake_tx_queue(struct ieee80211_hw *hw, list_add_tail(&rtwtxq->list, &rtwdev->txqs); spin_unlock_bh(&rtwdev->txq_lock); - queue_work(rtwdev->tx_wq, &rtwdev->tx_work); + /* ensure to dequeue EAPOL (4/4) at the right time */ + if (txq->ac == IEEE80211_AC_VO) + __rtw_tx_work(rtwdev); + else + queue_work(rtwdev->tx_wq, &rtwdev->tx_work); } static int rtw_ops_start(struct ieee80211_hw *hw) @@ -164,8 +168,10 @@ static int rtw_ops_add_interface(struct ieee80211_hw *hw, mutex_lock(&rtwdev->mutex); port = find_first_zero_bit(rtwdev->hw_port, RTW_PORT_NUM); - if (port >= RTW_PORT_NUM) + if (port >= RTW_PORT_NUM) { + mutex_unlock(&rtwdev->mutex); return -EINVAL; + } set_bit(port, rtwdev->hw_port); rtwvif->port = port; @@ -376,6 +382,7 @@ static void rtw_ops_bss_info_changed(struct ieee80211_hw *hw, rtw_fw_download_rsvd_page(rtwdev); rtw_send_rsvd_page_h2c(rtwdev); + rtw_fw_default_port(rtwdev, rtwvif); rtw_coex_media_status_notify(rtwdev, vif->cfg.assoc); if (rtw_bf_support) rtw_bf_assoc(rtwdev, vif, conf); @@ -447,6 +454,7 @@ static int rtw_ops_start_ap(struct ieee80211_hw *hw, const struct rtw_chip_info *chip = rtwdev->chip; mutex_lock(&rtwdev->mutex); + rtw_write32_set(rtwdev, REG_TCR, BIT_TCR_UPDATE_HGQMD); rtwdev->ap_active = true; rtw_store_op_chan(rtwdev, true); chip->ops->phy_calibration(rtwdev); @@ -462,6 +470,7 @@ static void rtw_ops_stop_ap(struct ieee80211_hw *hw, struct rtw_dev *rtwdev = hw->priv; mutex_lock(&rtwdev->mutex); + rtw_write32_clr(rtwdev, REG_TCR, BIT_TCR_UPDATE_HGQMD); rtwdev->ap_active = false; if (!rtw_core_check_sta_active(rtwdev)) rtw_clear_op_chan(rtwdev); diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c index 9447a3aae3b5e16d4beb86c2129e283847c5fc70..c853e2f2d448f12f7147accbe0e0eb47722ecf44 100644 --- a/drivers/net/wireless/realtek/rtw88/main.c +++ b/drivers/net/wireless/realtek/rtw88/main.c @@ -334,12 +334,15 @@ int rtw_sta_add(struct rtw_dev *rtwdev, struct ieee80211_sta *sta, struct ieee80211_vif *vif) { struct rtw_sta_info *si = (struct rtw_sta_info *)sta->drv_priv; + struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv; int i; si->mac_id = rtw_acquire_macid(rtwdev); if (si->mac_id >= RTW_MAX_MAC_ID_NUM) return -ENOSPC; + if (vif->type == NL80211_IFTYPE_STATION && vif->cfg.assoc == 0) + rtwvif->mac_id = si->mac_id; si->rtwdev = rtwdev; si->sta = sta; si->vif = vif; @@ -2340,6 +2343,9 @@ static void rtw_port_switch_iter(void *data, u8 *mac, struct ieee80211_vif *vif) rtw_dbg(rtwdev, RTW_DBG_STATE, "AP port switch from %d -> %d\n", rtwvif_ap->port, rtwvif_target->port); + /* Leave LPS so the value swapped are not in PS mode */ + rtw_leave_lps(rtwdev); + reg1 = &rtwvif_ap->conf->net_type; reg2 = &rtwvif_target->conf->net_type; rtw_swap_reg_mask(rtwdev, reg1, reg2); @@ -2358,6 +2364,8 @@ static void rtw_port_switch_iter(void *data, u8 *mac, struct ieee80211_vif *vif) swap(rtwvif_target->port, rtwvif_ap->port); swap(rtwvif_target->conf, rtwvif_ap->conf); + + rtw_fw_default_port(rtwdev, rtwvif_target); } void rtw_core_port_switch(struct rtw_dev *rtwdev, struct ieee80211_vif *vif) @@ -2403,10 +2411,13 @@ void rtw_core_enable_beacon(struct rtw_dev *rtwdev, bool enable) if (!rtwdev->ap_active) return; - if (enable) + if (enable) { rtw_write32_set(rtwdev, REG_BCN_CTRL, BIT_EN_BCN_FUNCTION); - else + rtw_write32_clr(rtwdev, REG_TXPAUSE, BIT_HIGH_QUEUE); + } else { rtw_write32_clr(rtwdev, REG_BCN_CTRL, BIT_EN_BCN_FUNCTION); + rtw_write32_set(rtwdev, REG_TXPAUSE, BIT_HIGH_QUEUE); + } } MODULE_AUTHOR("Realtek Corporation"); diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h index 9e841f6991a9a4d0d984fe5892282bd8d473ade4..f9dd2ab941c8fbb4de72d33ab481d8956862433a 100644 --- a/drivers/net/wireless/realtek/rtw88/main.h +++ b/drivers/net/wireless/realtek/rtw88/main.h @@ -803,6 +803,7 @@ struct rtw_bf_info { struct rtw_vif { enum rtw_net_type net_type; u16 aid; + u8 mac_id; /* for STA mode only */ u8 mac_addr[ETH_ALEN]; u8 bssid[ETH_ALEN]; u8 port; diff --git a/drivers/net/wireless/realtek/rtw88/pci.c b/drivers/net/wireless/realtek/rtw88/pci.c index 672ddde80816047d82b42185546816f53cff44c8..44a8fff34cddf19d7c0cbef2df9f142c732d0af6 100644 --- a/drivers/net/wireless/realtek/rtw88/pci.c +++ b/drivers/net/wireless/realtek/rtw88/pci.c @@ -738,8 +738,9 @@ static void __rtw_pci_flush_queues(struct rtw_dev *rtwdev, u32 pci_queues, u8 q; for (q = 0; q < RTK_MAX_TX_QUEUE_NUM; q++) { - /* It may be not necessary to flush BCN and H2C tx queues. */ - if (q == RTW_TX_QUEUE_BCN || q == RTW_TX_QUEUE_H2C) + /* Unnecessary to flush BCN, H2C and HI tx queues. */ + if (q == RTW_TX_QUEUE_BCN || q == RTW_TX_QUEUE_H2C || + q == RTW_TX_QUEUE_HI0) continue; if (pci_queues & BIT(q)) diff --git a/drivers/net/wireless/realtek/rtw88/ps.c b/drivers/net/wireless/realtek/rtw88/ps.c index 53933fb38a33084dcbdb81f68ba8f524e73feb02..43e80a3a8136d34aee8c52bc140199a04013b0ae 100644 --- a/drivers/net/wireless/realtek/rtw88/ps.c +++ b/drivers/net/wireless/realtek/rtw88/ps.c @@ -18,6 +18,7 @@ static int rtw_ips_pwr_up(struct rtw_dev *rtwdev) if (ret) rtw_err(rtwdev, "leave idle state failed\n"); + rtw_coex_ips_notify(rtwdev, COEX_IPS_LEAVE); rtw_set_channel(rtwdev); return ret; @@ -63,8 +64,6 @@ int rtw_leave_ips(struct rtw_dev *rtwdev) rtw_iterate_vifs(rtwdev, rtw_restore_port_cfg_iter, rtwdev); - rtw_coex_ips_notify(rtwdev, COEX_IPS_LEAVE); - return 0; } diff --git a/drivers/net/wireless/realtek/rtw88/reg.h b/drivers/net/wireless/realtek/rtw88/reg.h index 2a2ae2081f34747643dd3b17fb289a19af6ad00e..7c6c11d50ff30f966b895bb5594e18cf08d03888 100644 --- a/drivers/net/wireless/realtek/rtw88/reg.h +++ b/drivers/net/wireless/realtek/rtw88/reg.h @@ -378,6 +378,7 @@ #define BIT_SIFS_BK_EN BIT(12) #define REG_TXPAUSE 0x0522 #define BIT_AC_QUEUE GENMASK(7, 0) +#define BIT_HIGH_QUEUE BIT(5) #define REG_RD_CTRL 0x0524 #define BIT_EDCCA_MSK_CNTDOWN_EN BIT(11) #define BIT_DIS_TXOP_CFE BIT(10) @@ -410,6 +411,7 @@ #define REG_TCR 0x0604 #define BIT_PWRMGT_HWDATA_EN BIT(7) #define BIT_TCR_UPDATE_TIMIE BIT(5) +#define BIT_TCR_UPDATE_HGQMD BIT(4) #define REG_RCR 0x0608 #define BIT_APP_FCS BIT(31) #define BIT_APP_MIC BIT(30) diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723d.c b/drivers/net/wireless/realtek/rtw88/rtw8723d.c index 06e7454c9ca69305086edecc4ddfdf014fb30446..c575476a002079ebf949645a9c39665b5c527055 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8723d.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8723d.c @@ -216,6 +216,12 @@ static void rtw8723du_efuse_parsing(struct rtw_efuse *efuse, ether_addr_copy(efuse->addr, map->u.mac_addr); } +static void rtw8723ds_efuse_parsing(struct rtw_efuse *efuse, + struct rtw8723d_efuse *map) +{ + ether_addr_copy(efuse->addr, map->s.mac_addr); +} + static int rtw8723d_read_efuse(struct rtw_dev *rtwdev, u8 *log_map) { struct rtw_efuse *efuse = &rtwdev->efuse; @@ -248,6 +254,9 @@ static int rtw8723d_read_efuse(struct rtw_dev *rtwdev, u8 *log_map) case RTW_HCI_TYPE_USB: rtw8723du_efuse_parsing(efuse, map); break; + case RTW_HCI_TYPE_SDIO: + rtw8723ds_efuse_parsing(efuse, map); + break; default: /* unsupported now */ return -ENOTSUPP; @@ -1961,15 +1970,17 @@ static void rtw8723d_fill_txdesc_checksum(struct rtw_dev *rtwdev, size_t words = 32 / 2; /* calculate the first 32 bytes (16 words) */ __le16 chksum = 0; __le16 *data = (__le16 *)(txdesc); + struct rtw_tx_desc *tx_desc = (struct rtw_tx_desc *)txdesc; - SET_TX_DESC_TXDESC_CHECKSUM(txdesc, 0x0000); + le32p_replace_bits(&tx_desc->w7, 0, RTW_TX_DESC_W7_TXDESC_CHECKSUM); while (words--) chksum ^= *data++; chksum = ~chksum; - SET_TX_DESC_TXDESC_CHECKSUM(txdesc, __le16_to_cpu(chksum)); + le32p_replace_bits(&tx_desc->w7, __le16_to_cpu(chksum), + RTW_TX_DESC_W7_TXDESC_CHECKSUM); } static struct rtw_chip_ops rtw8723d_ops = { diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723d.h b/drivers/net/wireless/realtek/rtw88/rtw8723d.h index a356318a5c15b225ed05e5b2b3535ab167666281..3642a2c7f80c984dc2111880b7ac3729cdaaea5a 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8723d.h +++ b/drivers/net/wireless/realtek/rtw88/rtw8723d.h @@ -49,6 +49,11 @@ struct rtw8723du_efuse { u8 mac_addr[ETH_ALEN]; /* 0x107 */ }; +struct rtw8723ds_efuse { + u8 res4[0x4a]; /* 0xd0 */ + u8 mac_addr[ETH_ALEN]; /* 0x11a */ +}; + struct rtw8723d_efuse { __le16 rtl_id; u8 rsvd[2]; @@ -80,6 +85,7 @@ struct rtw8723d_efuse { union { struct rtw8723de_efuse e; struct rtw8723du_efuse u; + struct rtw8723ds_efuse s; }; }; diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723ds.c b/drivers/net/wireless/realtek/rtw88/rtw8723ds.c new file mode 100644 index 0000000000000000000000000000000000000000..e5b6960ba0a02c3370511514e4d36ebe8de76ae9 --- /dev/null +++ b/drivers/net/wireless/realtek/rtw88/rtw8723ds.c @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause +/* Copyright(c) Martin Blumenstingl + */ + +#include +#include +#include +#include "main.h" +#include "rtw8723d.h" +#include "sdio.h" + +static const struct sdio_device_id rtw_8723ds_id_table[] = { + { + SDIO_DEVICE(SDIO_VENDOR_ID_REALTEK, + SDIO_DEVICE_ID_REALTEK_RTW8723DS_1ANT), + .driver_data = (kernel_ulong_t)&rtw8723d_hw_spec, + }, + { + SDIO_DEVICE(SDIO_VENDOR_ID_REALTEK, + SDIO_DEVICE_ID_REALTEK_RTW8723DS_2ANT), + .driver_data = (kernel_ulong_t)&rtw8723d_hw_spec, + }, + {} +}; +MODULE_DEVICE_TABLE(sdio, rtw_8723ds_id_table); + +static struct sdio_driver rtw_8723ds_driver = { + .name = "rtw_8723ds", + .probe = rtw_sdio_probe, + .remove = rtw_sdio_remove, + .id_table = rtw_8723ds_id_table, + .drv = { + .pm = &rtw_sdio_pm_ops, + .shutdown = rtw_sdio_shutdown, + } +}; +module_sdio_driver(rtw_8723ds_driver); + +MODULE_AUTHOR("Martin Blumenstingl "); +MODULE_DESCRIPTION("Realtek 802.11n wireless 8723ds driver"); +MODULE_LICENSE("Dual BSD/GPL"); diff --git a/drivers/net/wireless/realtek/rtw88/sdio.c b/drivers/net/wireless/realtek/rtw88/sdio.c index 06fce7c3addaa395bc5c622621bf8bc7c0537dae..2c1fb2dabd40a40d45311dded79b2f2ed10a54b2 100644 --- a/drivers/net/wireless/realtek/rtw88/sdio.c +++ b/drivers/net/wireless/realtek/rtw88/sdio.c @@ -998,9 +998,9 @@ static void rtw_sdio_rxfifo_recv(struct rtw_dev *rtwdev, u32 rx_len) static void rtw_sdio_rx_isr(struct rtw_dev *rtwdev) { - u32 rx_len, total_rx_bytes = 0; + u32 rx_len, hisr, total_rx_bytes = 0; - while (total_rx_bytes < SZ_64K) { + do { if (rtw_chip_wcpu_11n(rtwdev)) rx_len = rtw_read16(rtwdev, REG_SDIO_RX0_REQ_LEN); else @@ -1012,7 +1012,25 @@ static void rtw_sdio_rx_isr(struct rtw_dev *rtwdev) rtw_sdio_rxfifo_recv(rtwdev, rx_len); total_rx_bytes += rx_len; - } + + if (rtw_chip_wcpu_11n(rtwdev)) { + /* Stop if no more RX requests are pending, even if + * rx_len could be greater than zero in the next + * iteration. This is needed because the RX buffer may + * already contain data while either HW or FW are not + * done filling that buffer yet. Still reading the + * buffer can result in packets where + * rtw_rx_pkt_stat.pkt_len is zero or points beyond the + * end of the buffer. + */ + hisr = rtw_read32(rtwdev, REG_SDIO_HISR); + } else { + /* RTW_WCPU_11AC chips have improved hardware or + * firmware and can use rx_len unconditionally. + */ + hisr = REG_SDIO_HISR_RX_REQUEST; + } + } while (total_rx_bytes < SZ_64K && hisr & REG_SDIO_HISR_RX_REQUEST); } static void rtw_sdio_handle_interrupt(struct sdio_func *sdio_func) diff --git a/drivers/net/wireless/realtek/rtw88/tx.c b/drivers/net/wireless/realtek/rtw88/tx.c index bb5c7492c98b045c6810c76712ea3763cff30676..2821119dc9308e4ff8e9d8d5d0b655e7c7c69b0d 100644 --- a/drivers/net/wireless/realtek/rtw88/tx.c +++ b/drivers/net/wireless/realtek/rtw88/tx.c @@ -34,43 +34,57 @@ void rtw_tx_stats(struct rtw_dev *rtwdev, struct ieee80211_vif *vif, void rtw_tx_fill_tx_desc(struct rtw_tx_pkt_info *pkt_info, struct sk_buff *skb) { - __le32 *txdesc = (__le32 *)skb->data; - - SET_TX_DESC_TXPKTSIZE(txdesc, pkt_info->tx_pkt_size); - SET_TX_DESC_OFFSET(txdesc, pkt_info->offset); - SET_TX_DESC_PKT_OFFSET(txdesc, pkt_info->pkt_offset); - SET_TX_DESC_QSEL(txdesc, pkt_info->qsel); - SET_TX_DESC_BMC(txdesc, pkt_info->bmc); - SET_TX_DESC_RATE_ID(txdesc, pkt_info->rate_id); - SET_TX_DESC_DATARATE(txdesc, pkt_info->rate); - SET_TX_DESC_DISDATAFB(txdesc, pkt_info->dis_rate_fallback); - SET_TX_DESC_USE_RATE(txdesc, pkt_info->use_rate); - SET_TX_DESC_SEC_TYPE(txdesc, pkt_info->sec_type); - SET_TX_DESC_DATA_BW(txdesc, pkt_info->bw); - SET_TX_DESC_SW_SEQ(txdesc, pkt_info->seq); - SET_TX_DESC_MAX_AGG_NUM(txdesc, pkt_info->ampdu_factor); - SET_TX_DESC_AMPDU_DENSITY(txdesc, pkt_info->ampdu_density); - SET_TX_DESC_DATA_STBC(txdesc, pkt_info->stbc); - SET_TX_DESC_DATA_LDPC(txdesc, pkt_info->ldpc); - SET_TX_DESC_AGG_EN(txdesc, pkt_info->ampdu_en); - SET_TX_DESC_LS(txdesc, pkt_info->ls); - SET_TX_DESC_DATA_SHORT(txdesc, pkt_info->short_gi); - SET_TX_DESC_SPE_RPT(txdesc, pkt_info->report); - SET_TX_DESC_SW_DEFINE(txdesc, pkt_info->sn); - SET_TX_DESC_USE_RTS(txdesc, pkt_info->rts); + struct rtw_tx_desc *tx_desc = (struct rtw_tx_desc *)skb->data; + bool more_data = false; + + if (pkt_info->qsel == TX_DESC_QSEL_HIGH) + more_data = true; + + tx_desc->w0 = le32_encode_bits(pkt_info->tx_pkt_size, RTW_TX_DESC_W0_TXPKTSIZE) | + le32_encode_bits(pkt_info->offset, RTW_TX_DESC_W0_OFFSET) | + le32_encode_bits(pkt_info->bmc, RTW_TX_DESC_W0_BMC) | + le32_encode_bits(pkt_info->ls, RTW_TX_DESC_W0_LS) | + le32_encode_bits(pkt_info->dis_qselseq, RTW_TX_DESC_W0_DISQSELSEQ); + + tx_desc->w1 = le32_encode_bits(pkt_info->qsel, RTW_TX_DESC_W1_QSEL) | + le32_encode_bits(pkt_info->rate_id, RTW_TX_DESC_W1_RATE_ID) | + le32_encode_bits(pkt_info->sec_type, RTW_TX_DESC_W1_SEC_TYPE) | + le32_encode_bits(pkt_info->pkt_offset, RTW_TX_DESC_W1_PKT_OFFSET) | + le32_encode_bits(more_data, RTW_TX_DESC_W1_MORE_DATA); + + tx_desc->w2 = le32_encode_bits(pkt_info->ampdu_en, RTW_TX_DESC_W2_AGG_EN) | + le32_encode_bits(pkt_info->report, RTW_TX_DESC_W2_SPE_RPT) | + le32_encode_bits(pkt_info->ampdu_density, RTW_TX_DESC_W2_AMPDU_DEN) | + le32_encode_bits(pkt_info->bt_null, RTW_TX_DESC_W2_BT_NULL); + + tx_desc->w3 = le32_encode_bits(pkt_info->hw_ssn_sel, RTW_TX_DESC_W3_HW_SSN_SEL) | + le32_encode_bits(pkt_info->use_rate, RTW_TX_DESC_W3_USE_RATE) | + le32_encode_bits(pkt_info->dis_rate_fallback, RTW_TX_DESC_W3_DISDATAFB) | + le32_encode_bits(pkt_info->rts, RTW_TX_DESC_W3_USE_RTS) | + le32_encode_bits(pkt_info->nav_use_hdr, RTW_TX_DESC_W3_NAVUSEHDR) | + le32_encode_bits(pkt_info->ampdu_factor, RTW_TX_DESC_W3_MAX_AGG_NUM); + + tx_desc->w4 = le32_encode_bits(pkt_info->rate, RTW_TX_DESC_W4_DATARATE); + + tx_desc->w5 = le32_encode_bits(pkt_info->short_gi, RTW_TX_DESC_W5_DATA_SHORT) | + le32_encode_bits(pkt_info->bw, RTW_TX_DESC_W5_DATA_BW) | + le32_encode_bits(pkt_info->ldpc, RTW_TX_DESC_W5_DATA_LDPC) | + le32_encode_bits(pkt_info->stbc, RTW_TX_DESC_W5_DATA_STBC); + + tx_desc->w6 = le32_encode_bits(pkt_info->sn, RTW_TX_DESC_W6_SW_DEFINE); + + tx_desc->w8 = le32_encode_bits(pkt_info->en_hwseq, RTW_TX_DESC_W8_EN_HWSEQ); + + tx_desc->w9 = le32_encode_bits(pkt_info->seq, RTW_TX_DESC_W9_SW_SEQ); + if (pkt_info->rts) { - SET_TX_DESC_RTSRATE(txdesc, DESC_RATE24M); - SET_TX_DESC_DATA_RTS_SHORT(txdesc, 1); - } - SET_TX_DESC_DISQSELSEQ(txdesc, pkt_info->dis_qselseq); - SET_TX_DESC_EN_HWSEQ(txdesc, pkt_info->en_hwseq); - SET_TX_DESC_HW_SSN_SEL(txdesc, pkt_info->hw_ssn_sel); - SET_TX_DESC_NAVUSEHDR(txdesc, pkt_info->nav_use_hdr); - SET_TX_DESC_BT_NULL(txdesc, pkt_info->bt_null); - if (pkt_info->tim_offset) { - SET_TX_DESC_TIM_EN(txdesc, 1); - SET_TX_DESC_TIM_OFFSET(txdesc, pkt_info->tim_offset); + tx_desc->w4 |= le32_encode_bits(DESC_RATE24M, RTW_TX_DESC_W4_RTSRATE); + tx_desc->w5 |= le32_encode_bits(1, RTW_TX_DESC_W5_DATA_RTS_SHORT); } + + if (pkt_info->tim_offset) + tx_desc->w9 |= le32_encode_bits(1, RTW_TX_DESC_W9_TIM_EN) | + le32_encode_bits(pkt_info->tim_offset, RTW_TX_DESC_W9_TIM_OFFSET); } EXPORT_SYMBOL(rtw_tx_fill_tx_desc); @@ -635,9 +649,8 @@ static void rtw_txq_push(struct rtw_dev *rtwdev, rcu_read_unlock(); } -void rtw_tx_work(struct work_struct *w) +void __rtw_tx_work(struct rtw_dev *rtwdev) { - struct rtw_dev *rtwdev = container_of(w, struct rtw_dev, tx_work); struct rtw_txq *rtwtxq, *tmp; spin_lock_bh(&rtwdev->txq_lock); @@ -658,6 +671,13 @@ void rtw_tx_work(struct work_struct *w) spin_unlock_bh(&rtwdev->txq_lock); } +void rtw_tx_work(struct work_struct *w) +{ + struct rtw_dev *rtwdev = container_of(w, struct rtw_dev, tx_work); + + __rtw_tx_work(rtwdev); +} + void rtw_txq_init(struct rtw_dev *rtwdev, struct ieee80211_txq *txq) { struct rtw_txq *rtwtxq; diff --git a/drivers/net/wireless/realtek/rtw88/tx.h b/drivers/net/wireless/realtek/rtw88/tx.h index 197d5868c8ad9453def0d5f5923dbe3f39d3477c..3241896062577ba771cc6225ae503c273856ada7 100644 --- a/drivers/net/wireless/realtek/rtw88/tx.h +++ b/drivers/net/wireless/realtek/rtw88/tx.h @@ -9,76 +9,53 @@ #define RTW_TX_PROBE_TIMEOUT msecs_to_jiffies(500) -#define SET_TX_DESC_TXPKTSIZE(txdesc, value) \ - le32p_replace_bits((__le32 *)(txdesc) + 0x00, value, GENMASK(15, 0)) -#define SET_TX_DESC_OFFSET(txdesc, value) \ - le32p_replace_bits((__le32 *)(txdesc) + 0x00, value, GENMASK(23, 16)) -#define SET_TX_DESC_PKT_OFFSET(txdesc, value) \ - le32p_replace_bits((__le32 *)(txdesc) + 0x01, value, GENMASK(28, 24)) -#define SET_TX_DESC_QSEL(txdesc, value) \ - le32p_replace_bits((__le32 *)(txdesc) + 0x01, value, GENMASK(12, 8)) -#define SET_TX_DESC_BMC(txdesc, value) \ - le32p_replace_bits((__le32 *)(txdesc) + 0x00, value, BIT(24)) -#define SET_TX_DESC_RATE_ID(txdesc, value) \ - le32p_replace_bits((__le32 *)(txdesc) + 0x01, value, GENMASK(20, 16)) -#define SET_TX_DESC_DATARATE(txdesc, value) \ - le32p_replace_bits((__le32 *)(txdesc) + 0x04, value, GENMASK(6, 0)) -#define SET_TX_DESC_DISDATAFB(txdesc, value) \ - le32p_replace_bits((__le32 *)(txdesc) + 0x03, value, BIT(10)) -#define SET_TX_DESC_USE_RATE(txdesc, value) \ - le32p_replace_bits((__le32 *)(txdesc) + 0x03, value, BIT(8)) -#define SET_TX_DESC_SEC_TYPE(txdesc, value) \ - le32p_replace_bits((__le32 *)(txdesc) + 0x01, value, GENMASK(23, 22)) -#define SET_TX_DESC_DATA_BW(txdesc, value) \ - le32p_replace_bits((__le32 *)(txdesc) + 0x05, value, GENMASK(6, 5)) -#define SET_TX_DESC_SW_SEQ(txdesc, value) \ - le32p_replace_bits((__le32 *)(txdesc) + 0x09, value, GENMASK(23, 12)) -#define SET_TX_DESC_TIM_EN(txdesc, value) \ - le32p_replace_bits((__le32 *)(txdesc) + 0x09, value, BIT(7)) -#define SET_TX_DESC_TIM_OFFSET(txdesc, value) \ - le32p_replace_bits((__le32 *)(txdesc) + 0x09, value, GENMASK(6, 0)) -#define SET_TX_DESC_MAX_AGG_NUM(txdesc, value) \ - le32p_replace_bits((__le32 *)(txdesc) + 0x03, value, GENMASK(21, 17)) -#define SET_TX_DESC_USE_RTS(tx_desc, value) \ - le32p_replace_bits((__le32 *)(txdesc) + 0x03, value, BIT(12)) -#define SET_TX_DESC_RTSRATE(txdesc, value) \ - le32p_replace_bits((__le32 *)(txdesc) + 0x04, value, GENMASK(28, 24)) -#define SET_TX_DESC_DATA_RTS_SHORT(txdesc, value) \ - le32p_replace_bits((__le32 *)(txdesc) + 0x05, value, BIT(12)) -#define SET_TX_DESC_AMPDU_DENSITY(txdesc, value) \ - le32p_replace_bits((__le32 *)(txdesc) + 0x02, value, GENMASK(22, 20)) -#define SET_TX_DESC_DATA_STBC(txdesc, value) \ - le32p_replace_bits((__le32 *)(txdesc) + 0x05, value, GENMASK(9, 8)) -#define SET_TX_DESC_DATA_LDPC(txdesc, value) \ - le32p_replace_bits((__le32 *)(txdesc) + 0x05, value, BIT(7)) -#define SET_TX_DESC_AGG_EN(txdesc, value) \ - le32p_replace_bits((__le32 *)(txdesc) + 0x02, value, BIT(12)) -#define SET_TX_DESC_LS(txdesc, value) \ - le32p_replace_bits((__le32 *)(txdesc) + 0x00, value, BIT(26)) -#define SET_TX_DESC_DATA_SHORT(txdesc, value) \ - le32p_replace_bits((__le32 *)(txdesc) + 0x05, value, BIT(4)) -#define SET_TX_DESC_SPE_RPT(tx_desc, value) \ - le32p_replace_bits((__le32 *)(txdesc) + 0x02, value, BIT(19)) -#define SET_TX_DESC_SW_DEFINE(tx_desc, value) \ - le32p_replace_bits((__le32 *)(txdesc) + 0x06, value, GENMASK(11, 0)) -#define SET_TX_DESC_DISQSELSEQ(txdesc, value) \ - le32p_replace_bits((__le32 *)(txdesc) + 0x00, value, BIT(31)) -#define SET_TX_DESC_EN_HWSEQ(txdesc, value) \ - le32p_replace_bits((__le32 *)(txdesc) + 0x08, value, BIT(15)) -#define SET_TX_DESC_HW_SSN_SEL(txdesc, value) \ - le32p_replace_bits((__le32 *)(txdesc) + 0x03, value, GENMASK(7, 6)) -#define SET_TX_DESC_NAVUSEHDR(txdesc, value) \ - le32p_replace_bits((__le32 *)(txdesc) + 0x03, value, BIT(15)) -#define SET_TX_DESC_BT_NULL(txdesc, value) \ - le32p_replace_bits((__le32 *)(txdesc) + 0x02, value, BIT(23)) -#define SET_TX_DESC_TXDESC_CHECKSUM(txdesc, value) \ - le32p_replace_bits((__le32 *)(txdesc) + 0x07, value, GENMASK(15, 0)) -#define SET_TX_DESC_DMA_TXAGG_NUM(txdesc, value) \ - le32p_replace_bits((__le32 *)(txdesc) + 0x07, value, GENMASK(31, 24)) -#define GET_TX_DESC_PKT_OFFSET(txdesc) \ - le32_get_bits(*((__le32 *)(txdesc) + 0x01), GENMASK(28, 24)) -#define GET_TX_DESC_QSEL(txdesc) \ - le32_get_bits(*((__le32 *)(txdesc) + 0x01), GENMASK(12, 8)) +struct rtw_tx_desc { + __le32 w0; + __le32 w1; + __le32 w2; + __le32 w3; + __le32 w4; + __le32 w5; + __le32 w6; + __le32 w7; + __le32 w8; + __le32 w9; +} __packed; + +#define RTW_TX_DESC_W0_TXPKTSIZE GENMASK(15, 0) +#define RTW_TX_DESC_W0_OFFSET GENMASK(23, 16) +#define RTW_TX_DESC_W0_BMC BIT(24) +#define RTW_TX_DESC_W0_LS BIT(26) +#define RTW_TX_DESC_W0_DISQSELSEQ BIT(31) +#define RTW_TX_DESC_W1_QSEL GENMASK(12, 8) +#define RTW_TX_DESC_W1_RATE_ID GENMASK(20, 16) +#define RTW_TX_DESC_W1_SEC_TYPE GENMASK(23, 22) +#define RTW_TX_DESC_W1_PKT_OFFSET GENMASK(28, 24) +#define RTW_TX_DESC_W1_MORE_DATA BIT(29) +#define RTW_TX_DESC_W2_AGG_EN BIT(12) +#define RTW_TX_DESC_W2_SPE_RPT BIT(19) +#define RTW_TX_DESC_W2_AMPDU_DEN GENMASK(22, 20) +#define RTW_TX_DESC_W2_BT_NULL BIT(23) +#define RTW_TX_DESC_W3_HW_SSN_SEL GENMASK(7, 6) +#define RTW_TX_DESC_W3_USE_RATE BIT(8) +#define RTW_TX_DESC_W3_DISDATAFB BIT(10) +#define RTW_TX_DESC_W3_USE_RTS BIT(12) +#define RTW_TX_DESC_W3_NAVUSEHDR BIT(15) +#define RTW_TX_DESC_W3_MAX_AGG_NUM GENMASK(21, 17) +#define RTW_TX_DESC_W4_DATARATE GENMASK(6, 0) +#define RTW_TX_DESC_W4_RTSRATE GENMASK(28, 24) +#define RTW_TX_DESC_W5_DATA_SHORT BIT(4) +#define RTW_TX_DESC_W5_DATA_BW GENMASK(6, 5) +#define RTW_TX_DESC_W5_DATA_LDPC BIT(7) +#define RTW_TX_DESC_W5_DATA_STBC GENMASK(9, 8) +#define RTW_TX_DESC_W5_DATA_RTS_SHORT BIT(12) +#define RTW_TX_DESC_W6_SW_DEFINE GENMASK(11, 0) +#define RTW_TX_DESC_W7_TXDESC_CHECKSUM GENMASK(15, 0) +#define RTW_TX_DESC_W7_DMA_TXAGG_NUM GENMASK(31, 24) +#define RTW_TX_DESC_W8_EN_HWSEQ BIT(15) +#define RTW_TX_DESC_W9_SW_SEQ GENMASK(23, 12) +#define RTW_TX_DESC_W9_TIM_EN BIT(7) +#define RTW_TX_DESC_W9_TIM_OFFSET GENMASK(6, 0) enum rtw_tx_desc_queue_select { TX_DESC_QSEL_TID0 = 0, @@ -111,6 +88,7 @@ void rtw_tx(struct rtw_dev *rtwdev, void rtw_txq_init(struct rtw_dev *rtwdev, struct ieee80211_txq *txq); void rtw_txq_cleanup(struct rtw_dev *rtwdev, struct ieee80211_txq *txq); void rtw_tx_work(struct work_struct *w); +void __rtw_tx_work(struct rtw_dev *rtwdev); void rtw_tx_pkt_info_update(struct rtw_dev *rtwdev, struct rtw_tx_pkt_info *pkt_info, struct ieee80211_sta *sta, @@ -139,13 +117,15 @@ void fill_txdesc_checksum_common(u8 *txdesc, size_t words) { __le16 chksum = 0; __le16 *data = (__le16 *)(txdesc); + struct rtw_tx_desc *tx_desc = (struct rtw_tx_desc *)txdesc; - SET_TX_DESC_TXDESC_CHECKSUM(txdesc, 0x0000); + le32p_replace_bits(&tx_desc->w7, 0, RTW_TX_DESC_W7_TXDESC_CHECKSUM); while (words--) chksum ^= *data++; - SET_TX_DESC_TXDESC_CHECKSUM(txdesc, __le16_to_cpu(chksum)); + le32p_replace_bits(&tx_desc->w7, __le16_to_cpu(chksum), + RTW_TX_DESC_W7_TXDESC_CHECKSUM); } static inline void rtw_tx_fill_txdesc_checksum(struct rtw_dev *rtwdev, diff --git a/drivers/net/wireless/realtek/rtw88/usb.c b/drivers/net/wireless/realtek/rtw88/usb.c index 44a5fafb99055159e5e924a268574ffdd147f7fe..4a57efdba97bbf3f9a79ae9b38f911934f20136a 100644 --- a/drivers/net/wireless/realtek/rtw88/usb.c +++ b/drivers/net/wireless/realtek/rtw88/usb.c @@ -24,11 +24,12 @@ struct rtw_usb_txcb { static void rtw_usb_fill_tx_checksum(struct rtw_usb *rtwusb, struct sk_buff *skb, int agg_num) { + struct rtw_tx_desc *tx_desc = (struct rtw_tx_desc *)skb->data; struct rtw_dev *rtwdev = rtwusb->rtwdev; struct rtw_tx_pkt_info pkt_info; - SET_TX_DESC_DMA_TXAGG_NUM(skb->data, agg_num); - pkt_info.pkt_offset = GET_TX_DESC_PKT_OFFSET(skb->data); + le32p_replace_bits(&tx_desc->w7, agg_num, RTW_TX_DESC_W7_DMA_TXAGG_NUM); + pkt_info.pkt_offset = le32_get_bits(tx_desc->w1, RTW_TX_DESC_W1_PKT_OFFSET); rtw_tx_fill_txdesc_checksum(rtwdev, &pkt_info, skb->data); } @@ -306,11 +307,13 @@ static int rtw_usb_write_port(struct rtw_dev *rtwdev, u8 qsel, struct sk_buff *s static bool rtw_usb_tx_agg_skb(struct rtw_usb *rtwusb, struct sk_buff_head *list) { struct rtw_dev *rtwdev = rtwusb->rtwdev; + struct rtw_tx_desc *tx_desc; struct rtw_usb_txcb *txcb; struct sk_buff *skb_head; struct sk_buff *skb_iter; int agg_num = 0; unsigned int align_next = 0; + u8 qsel; if (skb_queue_empty(list)) return false; @@ -363,9 +366,10 @@ static bool rtw_usb_tx_agg_skb(struct rtw_usb *rtwusb, struct sk_buff_head *list queue: skb_queue_tail(&txcb->tx_ack_queue, skb_head); + tx_desc = (struct rtw_tx_desc *)skb_head->data; + qsel = le32_get_bits(tx_desc->w1, RTW_TX_DESC_W1_QSEL); - rtw_usb_write_port(rtwdev, GET_TX_DESC_QSEL(skb_head->data), skb_head, - rtw_usb_write_port_tx_complete, txcb); + rtw_usb_write_port(rtwdev, qsel, skb_head, rtw_usb_write_port_tx_complete, txcb); return true; } @@ -465,6 +469,9 @@ static u8 rtw_usb_tx_queue_mapping_to_qsel(struct sk_buff *skb) if (unlikely(ieee80211_is_mgmt(fc) || ieee80211_is_ctl(fc))) qsel = TX_DESC_QSEL_MGMT; + else if (is_broadcast_ether_addr(hdr->addr1) || + is_multicast_ether_addr(hdr->addr1)) + qsel = TX_DESC_QSEL_HIGH; else if (skb_get_queue_mapping(skb) <= IEEE80211_AC_BK) qsel = skb->priority; else @@ -535,7 +542,7 @@ static void rtw_usb_rx_handler(struct work_struct *work) } if (skb_queue_len(&rtwusb->rx_queue) >= RTW_USB_MAX_RXQ_LEN) { - rtw_err(rtwdev, "failed to get rx_queue, overflow\n"); + dev_dbg_ratelimited(rtwdev->dev, "failed to get rx_queue, overflow\n"); dev_kfree_skb_any(skb); continue; } diff --git a/drivers/net/wireless/realtek/rtw89/Kconfig b/drivers/net/wireless/realtek/rtw89/Kconfig index 2b20cf8bbf3aa349d771c41059567b046cb5357f..90ffbab7cc4c6d0b65fb08ec14ce58928e76c700 100644 --- a/drivers/net/wireless/realtek/rtw89/Kconfig +++ b/drivers/net/wireless/realtek/rtw89/Kconfig @@ -16,6 +16,9 @@ config RTW89_CORE config RTW89_PCI tristate +config RTW89_8851B + tristate + config RTW89_8852A tristate @@ -25,6 +28,17 @@ config RTW89_8852B config RTW89_8852C tristate +config RTW89_8851BE + tristate "Realtek 8851BE PCI wireless network (Wi-Fi 6) adapter" + depends on PCI + select RTW89_CORE + select RTW89_PCI + select RTW89_8851B + help + Select this option will enable support for 8851BE chipset + + 802.11ax PCIe wireless network (Wi-Fi 6) adapter + config RTW89_8852AE tristate "Realtek 8852AE PCI wireless network (Wi-Fi 6) adapter" depends on PCI diff --git a/drivers/net/wireless/realtek/rtw89/Makefile b/drivers/net/wireless/realtek/rtw89/Makefile index 2dc48fa10c6b6bf5827f0b06cd99576ebf838f48..41940099af1b69a2f2eaec530ee69a7a799820f3 100644 --- a/drivers/net/wireless/realtek/rtw89/Makefile +++ b/drivers/net/wireless/realtek/rtw89/Makefile @@ -13,10 +13,20 @@ rtw89_core-y += core.o \ coex.o \ ps.o \ chan.o \ - ser.o + ser.o \ + acpi.o rtw89_core-$(CONFIG_PM) += wow.o +obj-$(CONFIG_RTW89_8851B) += rtw89_8851b.o +rtw89_8851b-objs := rtw8851b.o \ + rtw8851b_table.o \ + rtw8851b_rfk.o \ + rtw8851b_rfk_table.o + +obj-$(CONFIG_RTW89_8851BE) += rtw89_8851be.o +rtw89_8851be-objs := rtw8851be.o + obj-$(CONFIG_RTW89_8852A) += rtw89_8852a.o rtw89_8852a-objs := rtw8852a.o \ rtw8852a_table.o \ diff --git a/drivers/net/wireless/realtek/rtw89/acpi.c b/drivers/net/wireless/realtek/rtw89/acpi.c new file mode 100644 index 0000000000000000000000000000000000000000..8aaf83a2a6b48d0f3bbbfa457862f724a5a990ae --- /dev/null +++ b/drivers/net/wireless/realtek/rtw89/acpi.c @@ -0,0 +1,52 @@ +// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause +/* Copyright(c) 2021-2023 Realtek Corporation + */ + +#include +#include + +#include "acpi.h" +#include "debug.h" + +static const guid_t rtw89_guid = GUID_INIT(0xD2A8C3E8, 0x4B69, 0x4F00, + 0x82, 0xBD, 0xFE, 0x86, + 0x07, 0x80, 0x3A, 0xA7); + +static int rtw89_acpi_dsm_get(struct rtw89_dev *rtwdev, union acpi_object *obj, + u8 *value) +{ + switch (obj->type) { + case ACPI_TYPE_INTEGER: + *value = (u8)obj->integer.value; + break; + case ACPI_TYPE_BUFFER: + *value = obj->buffer.pointer[0]; + break; + default: + rtw89_debug(rtwdev, RTW89_DBG_UNEXP, + "acpi dsm return unhandled type: %d\n", obj->type); + return -EINVAL; + } + + return 0; +} + +int rtw89_acpi_evaluate_dsm(struct rtw89_dev *rtwdev, + enum rtw89_acpi_dsm_func func, u8 *value) +{ + union acpi_object *obj; + int ret; + + obj = acpi_evaluate_dsm(ACPI_HANDLE(rtwdev->dev), &rtw89_guid, + 0, func, NULL); + if (!obj) { + rtw89_debug(rtwdev, RTW89_DBG_UNEXP, + "acpi dsm fail to evaluate func: %d\n", func); + return -ENOENT; + } + + ret = rtw89_acpi_dsm_get(rtwdev, obj, value); + + ACPI_FREE(obj); + return ret; +} diff --git a/drivers/net/wireless/realtek/rtw89/acpi.h b/drivers/net/wireless/realtek/rtw89/acpi.h new file mode 100644 index 0000000000000000000000000000000000000000..ed74d8ceb733994b89f2add2e443da4b9a91c414 --- /dev/null +++ b/drivers/net/wireless/realtek/rtw89/acpi.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ +/* Copyright(c) 2021-2023 Realtek Corporation + */ + +#ifndef __RTW89_ACPI_H__ +#define __RTW89_ACPI_H__ + +#include "core.h" + +enum rtw89_acpi_dsm_func { + RTW89_ACPI_DSM_FUNC_IDN_BAND_SUP = 2, + RTW89_ACPI_DSM_FUNC_6G_DIS = 3, + RTW89_ACPI_DSM_FUNC_6G_BP = 4, + RTW89_ACPI_DSM_FUNC_TAS_EN = 5, + RTW89_ACPI_DSM_FUNC_59G_EN = 6, +}; + +int rtw89_acpi_evaluate_dsm(struct rtw89_dev *rtwdev, + enum rtw89_acpi_dsm_func func, u8 *value); + +#endif diff --git a/drivers/net/wireless/realtek/rtw89/coex.c b/drivers/net/wireless/realtek/rtw89/coex.c index acb3fac0c96d4f1881fe028e2588ecf9b8a8c564..bda0e1e99a8c6b636199b194a23222e0428d83ce 100644 --- a/drivers/net/wireless/realtek/rtw89/coex.c +++ b/drivers/net/wireless/realtek/rtw89/coex.c @@ -127,6 +127,13 @@ static const u32 cxtbl[] = { static const struct rtw89_btc_ver rtw89_btc_ver_defs[] = { /* firmware version must be in decreasing order for each chip */ + {RTL8851B, RTW89_FW_VER_CODE(0, 29, 29, 0), + .fcxbtcrpt = 105, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 5, + .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 2, .fcxgpiodbg = 1, + .fcxbtver = 1, .fcxbtscan = 2, .fcxbtafh = 2, .fcxbtdevinfo = 1, + .fwlrole = 1, .frptmap = 3, .fcxctrl = 1, + .info_buf = 1800, .max_role_num = 6, + }, {RTL8852C, RTW89_FW_VER_CODE(0, 27, 57, 0), .fcxbtcrpt = 4, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 3, .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 1, .fcxgpiodbg = 1, @@ -199,7 +206,7 @@ static const struct rtw89_btc_ver rtw89_btc_ver_defs[] = { struct rtw89_btc_btf_tlv { u8 type; u8 len; - u8 val[1]; + u8 val[]; } __packed; enum btc_btf_set_report_en { diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c index bad864d56bd5cc7a16dc4c3eca81121db00efa89..69b181fa2966748a3e02a7018cf100f40563584b 100644 --- a/drivers/net/wireless/realtek/rtw89/core.c +++ b/drivers/net/wireless/realtek/rtw89/core.c @@ -77,6 +77,9 @@ static struct ieee80211_channel rtw89_channels_5ghz[] = { RTW89_DEF_CHAN_5G(5785, 157), RTW89_DEF_CHAN_5G(5805, 161), RTW89_DEF_CHAN_5G_NO_HT40MINUS(5825, 165), + RTW89_DEF_CHAN_5G(5845, 169), + RTW89_DEF_CHAN_5G(5865, 173), + RTW89_DEF_CHAN_5G(5885, 177), }; static struct ieee80211_channel rtw89_channels_6ghz[] = { @@ -333,8 +336,7 @@ void rtw89_core_set_chip_txpwr(struct rtw89_dev *rtwdev) sub_entity_idx = RTW89_SUB_ENTITY_0; phy_idx = RTW89_PHY_0; chan = rtw89_chan_get(rtwdev, sub_entity_idx); - if (chip->ops->set_txpwr) - chip->ops->set_txpwr(rtwdev, chan, phy_idx); + chip->ops->set_txpwr(rtwdev, chan, phy_idx); } void rtw89_set_channel(struct rtw89_dev *rtwdev) @@ -370,7 +372,7 @@ void rtw89_set_channel(struct rtw89_dev *rtwdev) chip->ops->set_channel(rtwdev, &chan, mac_idx, phy_idx); - rtw89_core_set_chip_txpwr(rtwdev); + chip->ops->set_txpwr(rtwdev, &chan, phy_idx); rtw89_chip_set_channel_done(rtwdev, &bak, &chan, mac_idx, phy_idx); @@ -1210,14 +1212,15 @@ static int rtw89_core_rx_process_mac_ppdu(struct rtw89_dev *rtwdev, struct sk_buff *skb, struct rtw89_rx_phy_ppdu *phy_ppdu) { + const struct rtw89_rxinfo *rxinfo = (const struct rtw89_rxinfo *)skb->data; bool rx_cnt_valid = false; u8 plcp_size = 0; u8 usr_num = 0; u8 *phy_sts; - rx_cnt_valid = RTW89_GET_RXINFO_RX_CNT_VLD(skb->data); - plcp_size = RTW89_GET_RXINFO_PLCP_LEN(skb->data) << 3; - usr_num = RTW89_GET_RXINFO_USR_NUM(skb->data); + rx_cnt_valid = le32_get_bits(rxinfo->w0, RTW89_RXINFO_W0_RX_CNT_VLD); + plcp_size = le32_get_bits(rxinfo->w1, RTW89_RXINFO_W1_PLCP_LEN) << 3; + usr_num = le32_get_bits(rxinfo->w0, RTW89_RXINFO_W0_USR_NUM); if (usr_num > RTW89_PPDU_MAX_USR) { rtw89_warn(rtwdev, "Invalid user number in mac info\n"); return -EINVAL; @@ -1244,18 +1247,40 @@ static void rtw89_core_rx_process_phy_ppdu_iter(void *data, struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; struct rtw89_rx_phy_ppdu *phy_ppdu = (struct rtw89_rx_phy_ppdu *)data; struct rtw89_dev *rtwdev = rtwsta->rtwdev; + struct rtw89_hal *hal = &rtwdev->hal; + u8 ant_num = hal->ant_diversity ? 2 : rtwdev->chip->rf_path_num; + u8 ant_pos = U8_MAX; + u8 evm_pos = 0; int i; - if (rtwsta->mac_id == phy_ppdu->mac_id && phy_ppdu->to_self) { - ewma_rssi_add(&rtwsta->avg_rssi, phy_ppdu->rssi_avg); + if (rtwsta->mac_id != phy_ppdu->mac_id || !phy_ppdu->to_self) + return; + + if (hal->ant_diversity && hal->antenna_rx) { + ant_pos = __ffs(hal->antenna_rx); + evm_pos = ant_pos; + } + + ewma_rssi_add(&rtwsta->avg_rssi, phy_ppdu->rssi_avg); + + if (ant_pos < ant_num) { + ewma_rssi_add(&rtwsta->rssi[ant_pos], phy_ppdu->rssi[0]); + } else { for (i = 0; i < rtwdev->chip->rf_path_num; i++) ewma_rssi_add(&rtwsta->rssi[i], phy_ppdu->rssi[i]); } + + if (phy_ppdu->ofdm.has) { + ewma_snr_add(&rtwsta->avg_snr, phy_ppdu->ofdm.avg_snr); + ewma_evm_add(&rtwsta->evm_min[evm_pos], phy_ppdu->ofdm.evm_min); + ewma_evm_add(&rtwsta->evm_max[evm_pos], phy_ppdu->ofdm.evm_max); + } } #define VAR_LEN 0xff #define VAR_LEN_UNIT 8 -static u16 rtw89_core_get_phy_status_ie_len(struct rtw89_dev *rtwdev, u8 *addr) +static u16 rtw89_core_get_phy_status_ie_len(struct rtw89_dev *rtwdev, + const struct rtw89_phy_sts_iehdr *iehdr) { static const u8 physts_ie_len_tab[32] = { 16, 32, 24, 24, 8, 8, 8, 8, VAR_LEN, 8, VAR_LEN, 176, VAR_LEN, @@ -1265,45 +1290,58 @@ static u16 rtw89_core_get_phy_status_ie_len(struct rtw89_dev *rtwdev, u8 *addr) u16 ie_len; u8 ie; - ie = RTW89_GET_PHY_STS_IE_TYPE(addr); + ie = le32_get_bits(iehdr->w0, RTW89_PHY_STS_IEHDR_TYPE); if (physts_ie_len_tab[ie] != VAR_LEN) ie_len = physts_ie_len_tab[ie]; else - ie_len = RTW89_GET_PHY_STS_IE_LEN(addr) * VAR_LEN_UNIT; + ie_len = le32_get_bits(iehdr->w0, RTW89_PHY_STS_IEHDR_LEN) * VAR_LEN_UNIT; return ie_len; } -static void rtw89_core_parse_phy_status_ie01(struct rtw89_dev *rtwdev, u8 *addr, +static void rtw89_core_parse_phy_status_ie01(struct rtw89_dev *rtwdev, + const struct rtw89_phy_sts_iehdr *iehdr, struct rtw89_rx_phy_ppdu *phy_ppdu) { + const struct rtw89_phy_sts_ie0 *ie = (const struct rtw89_phy_sts_ie0 *)iehdr; s16 cfo; + u32 t; - phy_ppdu->chan_idx = RTW89_GET_PHY_STS_IE01_CH_IDX(addr); + phy_ppdu->chan_idx = le32_get_bits(ie->w0, RTW89_PHY_STS_IE01_W0_CH_IDX); if (phy_ppdu->rate < RTW89_HW_RATE_OFDM6) return; if (!phy_ppdu->to_self) return; + phy_ppdu->ofdm.avg_snr = le32_get_bits(ie->w2, RTW89_PHY_STS_IE01_W2_AVG_SNR); + phy_ppdu->ofdm.evm_max = le32_get_bits(ie->w2, RTW89_PHY_STS_IE01_W2_EVM_MAX); + phy_ppdu->ofdm.evm_min = le32_get_bits(ie->w2, RTW89_PHY_STS_IE01_W2_EVM_MIN); + phy_ppdu->ofdm.has = true; + /* sign conversion for S(12,2) */ - if (rtwdev->chip->cfo_src_fd) - cfo = sign_extend32(RTW89_GET_PHY_STS_IE01_FD_CFO(addr), 11); - else - cfo = sign_extend32(RTW89_GET_PHY_STS_IE01_PREMB_CFO(addr), 11); + if (rtwdev->chip->cfo_src_fd) { + t = le32_get_bits(ie->w1, RTW89_PHY_STS_IE01_W1_FD_CFO); + cfo = sign_extend32(t, 11); + } else { + t = le32_get_bits(ie->w1, RTW89_PHY_STS_IE01_W1_PREMB_CFO); + cfo = sign_extend32(t, 11); + } rtw89_phy_cfo_parse(rtwdev, cfo, phy_ppdu); } -static int rtw89_core_process_phy_status_ie(struct rtw89_dev *rtwdev, u8 *addr, +static int rtw89_core_process_phy_status_ie(struct rtw89_dev *rtwdev, + const struct rtw89_phy_sts_iehdr *iehdr, struct rtw89_rx_phy_ppdu *phy_ppdu) { u8 ie; - ie = RTW89_GET_PHY_STS_IE_TYPE(addr); + ie = le32_get_bits(iehdr->w0, RTW89_PHY_STS_IEHDR_TYPE); + switch (ie) { case RTW89_PHYSTS_IE01_CMN_OFDM: - rtw89_core_parse_phy_status_ie01(rtwdev, addr, phy_ppdu); + rtw89_core_parse_phy_status_ie01(rtwdev, iehdr, phy_ppdu); break; default: break; @@ -1314,28 +1352,30 @@ static int rtw89_core_process_phy_status_ie(struct rtw89_dev *rtwdev, u8 *addr, static void rtw89_core_update_phy_ppdu(struct rtw89_rx_phy_ppdu *phy_ppdu) { + const struct rtw89_phy_sts_hdr *hdr = phy_ppdu->buf; u8 *rssi = phy_ppdu->rssi; - u8 *buf = phy_ppdu->buf; - phy_ppdu->ie = RTW89_GET_PHY_STS_IE_MAP(buf); - phy_ppdu->rssi_avg = RTW89_GET_PHY_STS_RSSI_AVG(buf); - rssi[RF_PATH_A] = RTW89_GET_PHY_STS_RSSI_A(buf); - rssi[RF_PATH_B] = RTW89_GET_PHY_STS_RSSI_B(buf); - rssi[RF_PATH_C] = RTW89_GET_PHY_STS_RSSI_C(buf); - rssi[RF_PATH_D] = RTW89_GET_PHY_STS_RSSI_D(buf); + phy_ppdu->ie = le32_get_bits(hdr->w0, RTW89_PHY_STS_HDR_W0_IE_MAP); + phy_ppdu->rssi_avg = le32_get_bits(hdr->w0, RTW89_PHY_STS_HDR_W0_RSSI_AVG); + rssi[RF_PATH_A] = le32_get_bits(hdr->w1, RTW89_PHY_STS_HDR_W1_RSSI_A); + rssi[RF_PATH_B] = le32_get_bits(hdr->w1, RTW89_PHY_STS_HDR_W1_RSSI_B); + rssi[RF_PATH_C] = le32_get_bits(hdr->w1, RTW89_PHY_STS_HDR_W1_RSSI_C); + rssi[RF_PATH_D] = le32_get_bits(hdr->w1, RTW89_PHY_STS_HDR_W1_RSSI_D); } static int rtw89_core_rx_process_phy_ppdu(struct rtw89_dev *rtwdev, struct rtw89_rx_phy_ppdu *phy_ppdu) { - if (RTW89_GET_PHY_STS_LEN(phy_ppdu->buf) << 3 != phy_ppdu->len) { + const struct rtw89_phy_sts_hdr *hdr = phy_ppdu->buf; + u32 len_from_header; + + len_from_header = le32_get_bits(hdr->w0, RTW89_PHY_STS_HDR_W0_LEN) << 3; + + if (len_from_header != phy_ppdu->len) { rtw89_debug(rtwdev, RTW89_DBG_UNEXP, "phy ppdu len mismatch\n"); return -EINVAL; } rtw89_core_update_phy_ppdu(phy_ppdu); - ieee80211_iterate_stations_atomic(rtwdev->hw, - rtw89_core_rx_process_phy_ppdu_iter, - phy_ppdu); return 0; } @@ -1344,17 +1384,19 @@ static int rtw89_core_rx_parse_phy_sts(struct rtw89_dev *rtwdev, struct rtw89_rx_phy_ppdu *phy_ppdu) { u16 ie_len; - u8 *pos, *end; + void *pos, *end; /* mark invalid reports and bypass them */ if (phy_ppdu->ie < RTW89_CCK_PKT) return -EINVAL; - pos = (u8 *)phy_ppdu->buf + PHY_STS_HDR_LEN; - end = (u8 *)phy_ppdu->buf + phy_ppdu->len; + pos = phy_ppdu->buf + PHY_STS_HDR_LEN; + end = phy_ppdu->buf + phy_ppdu->len; while (pos < end) { - ie_len = rtw89_core_get_phy_status_ie_len(rtwdev, pos); - rtw89_core_process_phy_status_ie(rtwdev, pos, phy_ppdu); + const struct rtw89_phy_sts_iehdr *iehdr = pos; + + ie_len = rtw89_core_get_phy_status_ie_len(rtwdev, iehdr); + rtw89_core_process_phy_status_ie(rtwdev, iehdr, phy_ppdu); pos += ie_len; if (pos > end || ie_len == 0) { rtw89_debug(rtwdev, RTW89_DBG_TXRX, @@ -1363,6 +1405,8 @@ static int rtw89_core_rx_parse_phy_sts(struct rtw89_dev *rtwdev, } } + rtw89_phy_antdiv_parse(rtwdev, phy_ppdu); + return 0; } @@ -1376,6 +1420,10 @@ static void rtw89_core_rx_process_phy_sts(struct rtw89_dev *rtwdev, rtw89_debug(rtwdev, RTW89_DBG_TXRX, "parse phy sts failed\n"); else phy_ppdu->valid = true; + + ieee80211_iterate_stations_atomic(rtwdev->hw, + rtw89_core_rx_process_phy_ppdu_iter, + phy_ppdu); } static u8 rtw89_rxdesc_to_nl_he_gi(struct rtw89_dev *rtwdev, @@ -1481,6 +1529,34 @@ static void rtw89_stats_trigger_frame(struct rtw89_dev *rtwdev, } } +static void rtw89_cancel_6ghz_probe_work(struct work_struct *work) +{ + struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev, + cancel_6ghz_probe_work); + struct list_head *pkt_list = rtwdev->scan_info.pkt_list; + struct rtw89_pktofld_info *info; + + mutex_lock(&rtwdev->mutex); + + if (!rtwdev->scanning) + goto out; + + list_for_each_entry(info, &pkt_list[NL80211_BAND_6GHZ], list) { + if (!info->cancel || !test_bit(info->id, rtwdev->pkt_offload)) + continue; + + rtw89_fw_h2c_del_pkt_offload(rtwdev, info->id); + + /* Don't delete/free info from pkt_list at this moment. Let it + * be deleted/freed in rtw89_release_pkt_list() after scanning, + * since if during scanning, pkt_list is accessed in bottom half. + */ + } + +out: + mutex_unlock(&rtwdev->mutex); +} + static void rtw89_core_cancel_6ghz_probe_tx(struct rtw89_dev *rtwdev, struct sk_buff *skb) { @@ -1489,6 +1565,7 @@ static void rtw89_core_cancel_6ghz_probe_tx(struct rtw89_dev *rtwdev, struct list_head *pkt_list = rtwdev->scan_info.pkt_list; struct rtw89_pktofld_info *info; const u8 *ies = mgmt->u.beacon.variable, *ssid_ie; + bool queue_work = false; if (rx_status->band != NL80211_BAND_6GHZ) return; @@ -1497,16 +1574,22 @@ static void rtw89_core_cancel_6ghz_probe_tx(struct rtw89_dev *rtwdev, list_for_each_entry(info, &pkt_list[NL80211_BAND_6GHZ], list) { if (ether_addr_equal(info->bssid, mgmt->bssid)) { - rtw89_fw_h2c_del_pkt_offload(rtwdev, info->id); + info->cancel = true; + queue_work = true; continue; } if (!ssid_ie || ssid_ie[1] != info->ssid_len || info->ssid_len == 0) continue; - if (memcmp(&ssid_ie[2], info->ssid, info->ssid_len) == 0) - rtw89_fw_h2c_del_pkt_offload(rtwdev, info->id); + if (memcmp(&ssid_ie[2], info->ssid, info->ssid_len) == 0) { + info->cancel = true; + queue_work = true; + } } + + if (queue_work) + ieee80211_queue_work(rtwdev->hw, &rtwdev->cancel_6ghz_probe_work); } static void rtw89_vif_rx_stats_iter(void *data, u8 *mac, @@ -1722,43 +1805,47 @@ void rtw89_core_query_rxdesc(struct rtw89_dev *rtwdev, u8 shift_len, drv_info_len; rxd_s = (struct rtw89_rxdesc_short *)(data + data_offset); - desc_info->pkt_size = RTW89_GET_RXWD_PKT_SIZE(rxd_s); - desc_info->drv_info_size = RTW89_GET_RXWD_DRV_INFO_SIZE(rxd_s); - desc_info->long_rxdesc = RTW89_GET_RXWD_LONG_RXD(rxd_s); - desc_info->pkt_type = RTW89_GET_RXWD_RPKT_TYPE(rxd_s); - desc_info->mac_info_valid = RTW89_GET_RXWD_MAC_INFO_VALID(rxd_s); + desc_info->pkt_size = le32_get_bits(rxd_s->dword0, AX_RXD_RPKT_LEN_MASK); + desc_info->drv_info_size = le32_get_bits(rxd_s->dword0, AX_RXD_DRV_INFO_SIZE_MASK); + desc_info->long_rxdesc = le32_get_bits(rxd_s->dword0, AX_RXD_LONG_RXD); + desc_info->pkt_type = le32_get_bits(rxd_s->dword0, AX_RXD_RPKT_TYPE_MASK); + desc_info->mac_info_valid = le32_get_bits(rxd_s->dword0, AX_RXD_MAC_INFO_VLD); if (chip->chip_id == RTL8852C) - desc_info->bw = RTW89_GET_RXWD_BW_V1(rxd_s); + desc_info->bw = le32_get_bits(rxd_s->dword1, AX_RXD_BW_v1_MASK); else - desc_info->bw = RTW89_GET_RXWD_BW(rxd_s); - desc_info->data_rate = RTW89_GET_RXWD_DATA_RATE(rxd_s); - desc_info->gi_ltf = RTW89_GET_RXWD_GI_LTF(rxd_s); - desc_info->user_id = RTW89_GET_RXWD_USER_ID(rxd_s); - desc_info->sr_en = RTW89_GET_RXWD_SR_EN(rxd_s); - desc_info->ppdu_cnt = RTW89_GET_RXWD_PPDU_CNT(rxd_s); - desc_info->ppdu_type = RTW89_GET_RXWD_PPDU_TYPE(rxd_s); - desc_info->free_run_cnt = RTW89_GET_RXWD_FREE_RUN_CNT(rxd_s); - desc_info->icv_err = RTW89_GET_RXWD_ICV_ERR(rxd_s); - desc_info->crc32_err = RTW89_GET_RXWD_CRC32_ERR(rxd_s); - desc_info->hw_dec = RTW89_GET_RXWD_HW_DEC(rxd_s); - desc_info->sw_dec = RTW89_GET_RXWD_SW_DEC(rxd_s); - desc_info->addr1_match = RTW89_GET_RXWD_A1_MATCH(rxd_s); + desc_info->bw = le32_get_bits(rxd_s->dword1, AX_RXD_BW_MASK); + desc_info->data_rate = le32_get_bits(rxd_s->dword1, AX_RXD_RX_DATARATE_MASK); + desc_info->gi_ltf = le32_get_bits(rxd_s->dword1, AX_RXD_RX_GI_LTF_MASK); + desc_info->user_id = le32_get_bits(rxd_s->dword1, AX_RXD_USER_ID_MASK); + desc_info->sr_en = le32_get_bits(rxd_s->dword1, AX_RXD_SR_EN); + desc_info->ppdu_cnt = le32_get_bits(rxd_s->dword1, AX_RXD_PPDU_CNT_MASK); + desc_info->ppdu_type = le32_get_bits(rxd_s->dword1, AX_RXD_PPDU_TYPE_MASK); + desc_info->free_run_cnt = le32_get_bits(rxd_s->dword2, AX_RXD_FREERUN_CNT_MASK); + desc_info->icv_err = le32_get_bits(rxd_s->dword3, AX_RXD_ICV_ERR); + desc_info->crc32_err = le32_get_bits(rxd_s->dword3, AX_RXD_CRC32_ERR); + desc_info->hw_dec = le32_get_bits(rxd_s->dword3, AX_RXD_HW_DEC); + desc_info->sw_dec = le32_get_bits(rxd_s->dword3, AX_RXD_SW_DEC); + desc_info->addr1_match = le32_get_bits(rxd_s->dword3, AX_RXD_A1_MATCH); shift_len = desc_info->shift << 1; /* 2-byte unit */ drv_info_len = desc_info->drv_info_size << 3; /* 8-byte unit */ desc_info->offset = data_offset + shift_len + drv_info_len; + if (desc_info->long_rxdesc) + desc_info->rxd_len = sizeof(struct rtw89_rxdesc_long); + else + desc_info->rxd_len = sizeof(struct rtw89_rxdesc_short); desc_info->ready = true; if (!desc_info->long_rxdesc) return; rxd_l = (struct rtw89_rxdesc_long *)(data + data_offset); - desc_info->frame_type = RTW89_GET_RXWD_TYPE(rxd_l); - desc_info->addr_cam_valid = RTW89_GET_RXWD_ADDR_CAM_VLD(rxd_l); - desc_info->addr_cam_id = RTW89_GET_RXWD_ADDR_CAM_ID(rxd_l); - desc_info->sec_cam_id = RTW89_GET_RXWD_SEC_CAM_ID(rxd_l); - desc_info->mac_id = RTW89_GET_RXWD_MAC_ID(rxd_l); - desc_info->rx_pl_id = RTW89_GET_RXWD_RX_PL_ID(rxd_l); + desc_info->frame_type = le32_get_bits(rxd_l->dword4, AX_RXD_TYPE_MASK); + desc_info->addr_cam_valid = le32_get_bits(rxd_l->dword5, AX_RXD_ADDR_CAM_VLD); + desc_info->addr_cam_id = le32_get_bits(rxd_l->dword5, AX_RXD_ADDR_CAM_MASK); + desc_info->sec_cam_id = le32_get_bits(rxd_l->dword5, AX_RXD_SEC_CAM_IDX_MASK); + desc_info->mac_id = le32_get_bits(rxd_l->dword5, AX_RXD_MAC_ID_MASK); + desc_info->rx_pl_id = le32_get_bits(rxd_l->dword5, AX_RXD_RX_PL_ID_MASK); } EXPORT_SYMBOL(rtw89_core_query_rxdesc); @@ -2593,6 +2680,7 @@ static void rtw89_track_work(struct work_struct *work) rtw89_phy_ra_update(rtwdev); rtw89_phy_cfo_track(rtwdev); rtw89_phy_tx_path_div_track(rtwdev); + rtw89_phy_antdiv_track(rtwdev); rtw89_phy_ul_tb_ctrl_track(rtwdev); if (rtwdev->lps_enabled && !rtwdev->btc.lps) @@ -2756,6 +2844,8 @@ int rtw89_core_sta_add(struct rtw89_dev *rtwdev, { struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; + struct rtw89_hal *hal = &rtwdev->hal; + u8 ant_num = hal->ant_diversity ? 2 : rtwdev->chip->rf_path_num; int i; int ret; @@ -2769,12 +2859,18 @@ int rtw89_core_sta_add(struct rtw89_dev *rtwdev, rtw89_core_txq_init(rtwdev, sta->txq[i]); ewma_rssi_init(&rtwsta->avg_rssi); - for (i = 0; i < rtwdev->chip->rf_path_num; i++) + ewma_snr_init(&rtwsta->avg_snr); + for (i = 0; i < ant_num; i++) { ewma_rssi_init(&rtwsta->rssi[i]); + ewma_evm_init(&rtwsta->evm_min[i]); + ewma_evm_init(&rtwsta->evm_max[i]); + } if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls) { /* for station mode, assign the mac_id from itself */ rtwsta->mac_id = rtwvif->mac_id; + /* must do rtw89_reg_6ghz_power_recalc() before rfk channel */ + rtw89_reg_6ghz_power_recalc(rtwdev, rtwvif, true); rtw89_btc_ntfy_role_info(rtwdev, rtwvif, rtwsta, BTC_ROLE_MSTS_STA_CONN_START); rtw89_chip_rfk_channel(rtwdev); @@ -2948,10 +3044,11 @@ int rtw89_core_sta_remove(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; int ret; - if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls) + if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls) { + rtw89_reg_6ghz_power_recalc(rtwdev, rtwvif, false); rtw89_btc_ntfy_role_info(rtwdev, rtwvif, rtwsta, BTC_ROLE_MSTS_STA_DIS_CONN); - else if (vif->type == NL80211_IFTYPE_AP || sta->tdls) { + } else if (vif->type == NL80211_IFTYPE_AP || sta->tdls) { rtw89_core_release_bit_map(rtwdev->mac_id_map, rtwsta->mac_id); ret = rtw89_fw_h2c_role_maintain(rtwdev, rtwvif, rtwsta, @@ -3292,8 +3389,10 @@ static void rtw89_core_clr_supported_band(struct rtw89_dev *rtwdev) { struct ieee80211_hw *hw = rtwdev->hw; - kfree(hw->wiphy->bands[NL80211_BAND_2GHZ]->iftype_data); - kfree(hw->wiphy->bands[NL80211_BAND_5GHZ]->iftype_data); + if (hw->wiphy->bands[NL80211_BAND_2GHZ]) + kfree(hw->wiphy->bands[NL80211_BAND_2GHZ]->iftype_data); + if (hw->wiphy->bands[NL80211_BAND_5GHZ]) + kfree(hw->wiphy->bands[NL80211_BAND_5GHZ]->iftype_data); if (hw->wiphy->bands[NL80211_BAND_6GHZ]) kfree(hw->wiphy->bands[NL80211_BAND_6GHZ]->iftype_data); kfree(hw->wiphy->bands[NL80211_BAND_2GHZ]); @@ -3430,6 +3529,7 @@ void rtw89_core_stop(struct rtw89_dev *rtwdev) mutex_unlock(&rtwdev->mutex); cancel_work_sync(&rtwdev->c2h_work); + cancel_work_sync(&rtwdev->cancel_6ghz_probe_work); cancel_work_sync(&btc->eapol_notify_work); cancel_work_sync(&btc->arp_notify_work); cancel_work_sync(&btc->dhcp_notify_work); @@ -3441,6 +3541,7 @@ void rtw89_core_stop(struct rtw89_dev *rtwdev) cancel_delayed_work_sync(&rtwdev->coex_rfk_chk_work); cancel_delayed_work_sync(&rtwdev->cfo_track_work); cancel_delayed_work_sync(&rtwdev->forbid_ba_work); + cancel_delayed_work_sync(&rtwdev->antdiv_work); mutex_lock(&rtwdev->mutex); @@ -3476,6 +3577,7 @@ int rtw89_core_init(struct rtw89_dev *rtwdev) INIT_DELAYED_WORK(&rtwdev->coex_rfk_chk_work, rtw89_coex_rfk_chk_work); INIT_DELAYED_WORK(&rtwdev->cfo_track_work, rtw89_phy_cfo_track_work); INIT_DELAYED_WORK(&rtwdev->forbid_ba_work, rtw89_forbid_ba_work); + INIT_DELAYED_WORK(&rtwdev->antdiv_work, rtw89_phy_antdiv_work); rtwdev->txq_wq = alloc_workqueue("rtw89_tx_wq", WQ_UNBOUND | WQ_HIGHPRI, 0); if (!rtwdev->txq_wq) return -ENOMEM; @@ -3486,10 +3588,12 @@ int rtw89_core_init(struct rtw89_dev *rtwdev) rtwdev->total_sta_assoc = 0; rtw89_init_wait(&rtwdev->mcc.wait); + rtw89_init_wait(&rtwdev->mac.fw_ofld_wait); INIT_WORK(&rtwdev->c2h_work, rtw89_fw_c2h_work); INIT_WORK(&rtwdev->ips_work, rtw89_ips_work); INIT_WORK(&rtwdev->load_firmware_work, rtw89_load_firmware_work); + INIT_WORK(&rtwdev->cancel_6ghz_probe_work, rtw89_cancel_6ghz_probe_work); skb_queue_head_init(&rtwdev->c2h_queue); rtw89_core_ppdu_sts_init(rtwdev); @@ -3584,7 +3688,7 @@ static void rtw89_read_chip_ver(struct rtw89_dev *rtwdev) if (chip->chip_id == RTL8852B || chip->chip_id == RTL8851B) { ret = rtw89_mac_read_xtal_si(rtwdev, XTAL_SI_CV, &val); - if (!ret) + if (ret) return; rtwdev->hal.acv = u8_get_bits(val, XTAL_SI_ACV_MASK); @@ -3693,6 +3797,7 @@ static int rtw89_core_register_hw(struct rtw89_dev *rtwdev) { struct ieee80211_hw *hw = rtwdev->hw; struct rtw89_efuse *efuse = &rtwdev->efuse; + struct rtw89_hal *hal = &rtwdev->hal; int ret; int tx_headroom = IEEE80211_HT_CTL_LEN; @@ -3731,8 +3836,13 @@ static int rtw89_core_register_hw(struct rtw89_dev *rtwdev) BIT(NL80211_IFTYPE_P2P_CLIENT) | BIT(NL80211_IFTYPE_P2P_GO); - hw->wiphy->available_antennas_tx = BIT(rtwdev->chip->rf_path_num) - 1; - hw->wiphy->available_antennas_rx = BIT(rtwdev->chip->rf_path_num) - 1; + if (hal->ant_diversity) { + hw->wiphy->available_antennas_tx = 0x3; + hw->wiphy->available_antennas_rx = 0x3; + } else { + hw->wiphy->available_antennas_tx = BIT(rtwdev->chip->rf_path_num) - 1; + hw->wiphy->available_antennas_rx = BIT(rtwdev->chip->rf_path_num) - 1; + } hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS | WIPHY_FLAG_TDLS_EXTERNAL_SETUP | @@ -3760,7 +3870,12 @@ static int rtw89_core_register_hw(struct rtw89_dev *rtwdev) return ret; } - hw->wiphy->reg_notifier = rtw89_regd_notifier; + ret = rtw89_regd_setup(rtwdev); + if (ret) { + rtw89_err(rtwdev, "failed to set up regd\n"); + goto err_free_supported_band; + } + hw->wiphy->sar_capa = &rtw89_sar_capa; ret = ieee80211_register_hw(hw); diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h index 6df386a38fb41c11b484663d1e2276689e51bb3f..d2c67db97db1aeb720055798784a97bb4ba431eb 100644 --- a/drivers/net/wireless/realtek/rtw89/core.h +++ b/drivers/net/wireless/realtek/rtw89/core.h @@ -122,6 +122,13 @@ enum rtw89_cv { CHIP_CV_INVALID = CHIP_CV_MAX, }; +enum rtw89_bacam_ver { + RTW89_BACAM_V0, + RTW89_BACAM_V1, + + RTW89_BACAM_V0_EXT = 99, +}; + enum rtw89_core_tx_type { RTW89_CORE_TX_TYPE_DATA, RTW89_CORE_TX_TYPE_MGMT, @@ -244,7 +251,7 @@ enum rtw89_band { RTW89_BAND_2G = 0, RTW89_BAND_5G = 1, RTW89_BAND_6G = 2, - RTW89_BAND_MAX, + RTW89_BAND_NUM, }; enum rtw89_hw_rate { @@ -427,27 +434,27 @@ enum rtw89_rate_section { RTW89_RS_MCS, /* for HT/VHT/HE */ RTW89_RS_HEDCM, RTW89_RS_OFFSET, - RTW89_RS_MAX, + RTW89_RS_NUM, RTW89_RS_LMT_NUM = RTW89_RS_MCS + 1, RTW89_RS_TX_SHAPE_NUM = RTW89_RS_OFDM + 1, }; -enum rtw89_rate_max { - RTW89_RATE_CCK_MAX = 4, - RTW89_RATE_OFDM_MAX = 8, - RTW89_RATE_MCS_MAX = 12, - RTW89_RATE_HEDCM_MAX = 4, /* for HEDCM MCS0/1/3/4 */ - RTW89_RATE_OFFSET_MAX = 5, /* for HE(HEDCM)/VHT/HT/OFDM/CCK offset */ +enum rtw89_rate_num { + RTW89_RATE_CCK_NUM = 4, + RTW89_RATE_OFDM_NUM = 8, + RTW89_RATE_MCS_NUM = 12, + RTW89_RATE_HEDCM_NUM = 4, /* for HEDCM MCS0/1/3/4 */ + RTW89_RATE_OFFSET_NUM = 5, /* for HE(HEDCM)/VHT/HT/OFDM/CCK offset */ }; enum rtw89_nss { RTW89_NSS_1 = 0, RTW89_NSS_2 = 1, /* HE DCM only support 1ss and 2ss */ - RTW89_NSS_HEDCM_MAX = RTW89_NSS_2 + 1, + RTW89_NSS_HEDCM_NUM = RTW89_NSS_2 + 1, RTW89_NSS_3 = 2, RTW89_NSS_4 = 3, - RTW89_NSS_MAX, + RTW89_NSS_NUM, }; enum rtw89_ntx { @@ -481,6 +488,15 @@ enum rtw89_regulation_type { RTW89_REGD_NUM, }; +enum rtw89_reg_6ghz_power { + RTW89_REG_6GHZ_POWER_VLP = 0, + RTW89_REG_6GHZ_POWER_LPI = 1, + RTW89_REG_6GHZ_POWER_STD = 2, + + NUM_OF_RTW89_REG_6GHZ_POWER, + RTW89_REG_6GHZ_POWER_DFLT = RTW89_REG_6GHZ_POWER_VLP, +}; + enum rtw89_fw_pkt_ofld_type { RTW89_PKT_OFLD_TYPE_PROBE_RSP = 0, RTW89_PKT_OFLD_TYPE_PS_POLL = 1, @@ -496,11 +512,11 @@ enum rtw89_fw_pkt_ofld_type { }; struct rtw89_txpwr_byrate { - s8 cck[RTW89_RATE_CCK_MAX]; - s8 ofdm[RTW89_RATE_OFDM_MAX]; - s8 mcs[RTW89_NSS_MAX][RTW89_RATE_MCS_MAX]; - s8 hedcm[RTW89_NSS_HEDCM_MAX][RTW89_RATE_HEDCM_MAX]; - s8 offset[RTW89_RATE_OFFSET_MAX]; + s8 cck[RTW89_RATE_CCK_NUM]; + s8 ofdm[RTW89_RATE_OFDM_NUM]; + s8 mcs[RTW89_NSS_NUM][RTW89_RATE_MCS_NUM]; + s8 hedcm[RTW89_NSS_HEDCM_NUM][RTW89_RATE_HEDCM_NUM]; + s8 offset[RTW89_RATE_OFFSET_NUM]; }; enum rtw89_bandwidth_section_num { @@ -543,7 +559,7 @@ struct rtw89_rate_desc { #define RF_PATH_MAX 4 #define RTW89_MAX_PPDU_CNT 8 struct rtw89_rx_phy_ppdu { - u8 *buf; + void *buf; u32 len; u8 rssi_avg; u8 rssi[RF_PATH_MAX]; @@ -551,6 +567,12 @@ struct rtw89_rx_phy_ppdu { u8 chan_idx; u8 ie; u16 rate; + struct { + bool has; + u8 avg_snr; + u8 evm_max; + u8 evm_min; + } ofdm; bool to_self; bool valid; }; @@ -763,6 +785,7 @@ struct rtw89_rx_desc_info { u8 sec_cam_id; u8 mac_id; u16 offset; + u16 rxd_len; bool ready; }; @@ -1382,7 +1405,6 @@ struct rtw89_btc_wl_nhm { u8 current_status; u8 refresh; bool start_flag; - u8 last_ccx_rpt_stamp; s8 pwr_max; s8 pwr_min; }; @@ -2533,6 +2555,8 @@ struct rtw89_ra_report { }; DECLARE_EWMA(rssi, 10, 16); +DECLARE_EWMA(evm, 10, 16); +DECLARE_EWMA(snr, 10, 16); struct rtw89_ba_cam_entry { struct list_head list; @@ -2595,6 +2619,9 @@ struct rtw89_sta { u8 prev_rssi; struct ewma_rssi avg_rssi; struct ewma_rssi rssi[RF_PATH_MAX]; + struct ewma_snr avg_snr; + struct ewma_evm evm_min[RF_PATH_MAX]; + struct ewma_evm evm_max[RF_PATH_MAX]; struct rtw89_ampdu_params ampdu_params[IEEE80211_NUM_TIDS]; struct ieee80211_rx_status rx_status; u16 rx_hw_rate; @@ -2663,6 +2690,7 @@ struct rtw89_vif { struct rtw89_dev *rtwdev; struct rtw89_roc roc; enum rtw89_sub_entity_idx sub_entity_idx; + enum rtw89_reg_6ghz_power reg_6ghz_power; u8 mac_id; u8 port; @@ -2781,6 +2809,7 @@ struct rtw89_chip_ops { int (*read_efuse)(struct rtw89_dev *rtwdev, u8 *log_map); int (*read_phycap)(struct rtw89_dev *rtwdev, u8 *phycap_map); void (*fem_setup)(struct rtw89_dev *rtwdev); + void (*rfe_gpio)(struct rtw89_dev *rtwdev); void (*rfk_init)(struct rtw89_dev *rtwdev); void (*rfk_channel)(struct rtw89_dev *rtwdev); void (*rfk_band_changed)(struct rtw89_dev *rtwdev, @@ -2805,6 +2834,9 @@ struct rtw89_chip_ops { s8 pw_ofst, enum rtw89_mac_idx mac_idx); int (*pwr_on_func)(struct rtw89_dev *rtwdev); int (*pwr_off_func)(struct rtw89_dev *rtwdev); + void (*query_rxdesc)(struct rtw89_dev *rtwdev, + struct rtw89_rx_desc_info *desc_info, + u8 *data, u32 data_offset); void (*fill_txdesc)(struct rtw89_dev *rtwdev, struct rtw89_tx_desc_info *desc_info, void *txdesc); @@ -3013,9 +3045,11 @@ struct rtw89_txpwr_rule_5ghz { struct rtw89_txpwr_rule_6ghz { const s8 (*lmt)[RTW89_6G_BW_NUM][RTW89_NTX_NUM] [RTW89_RS_LMT_NUM][RTW89_BF_NUM] - [RTW89_REGD_NUM][RTW89_6G_CH_NUM]; + [RTW89_REGD_NUM][NUM_OF_RTW89_REG_6GHZ_POWER] + [RTW89_6G_CH_NUM]; const s8 (*lmt_ru)[RTW89_RU_NUM][RTW89_NTX_NUM] - [RTW89_REGD_NUM][RTW89_6G_CH_NUM]; + [RTW89_REGD_NUM][NUM_OF_RTW89_REG_6GHZ_POWER] + [RTW89_6G_CH_NUM]; }; struct rtw89_rfe_parms { @@ -3090,6 +3124,12 @@ struct rtw89_imr_info { u32 tmac_imr_set; }; +struct rtw89_xtal_info { + u32 xcap_reg; + u32 sc_xo_mask; + u32 sc_xi_mask; +}; + struct rtw89_rrsr_cfgs { struct rtw89_reg3_def ref_rate; struct rtw89_reg3_def rsc; @@ -3116,6 +3156,25 @@ struct rtw89_phy_ul_tb_info { u8 def_if_bandedge; }; +struct rtw89_antdiv_stats { + struct ewma_rssi cck_rssi_avg; + struct ewma_rssi ofdm_rssi_avg; + struct ewma_rssi non_legacy_rssi_avg; + u16 pkt_cnt_cck; + u16 pkt_cnt_ofdm; + u16 pkt_cnt_non_legacy; + u32 evm; +}; + +struct rtw89_antdiv_info { + struct rtw89_antdiv_stats target_stats; + struct rtw89_antdiv_stats main_stats; + struct rtw89_antdiv_stats aux_stats; + u8 training_count; + u8 rssi_pre; + bool get_stats; +}; + struct rtw89_chip_info { enum rtw89_core_chip_id chip_id; const struct rtw89_chip_ops *ops; @@ -3123,6 +3182,7 @@ struct rtw89_chip_info { u8 fw_format_max; bool try_ce_fw; u32 fifo_size; + bool small_fifo_size; u32 dle_scc_rsvd_size; u16 max_amsdu_limit; bool dis_2g_40m_ul_ofdma; @@ -3135,6 +3195,7 @@ struct rtw89_chip_info { u8 support_chanctx_num; u8 support_bands; bool support_bw160; + bool support_unii4; bool support_ul_tb_ctrl; bool hw_sec_hdr; u8 rf_path_num; @@ -3145,7 +3206,7 @@ struct rtw89_chip_info { u8 scam_num; u8 bacam_num; u8 bacam_dynamic_num; - bool bacam_v1; + enum rtw89_bacam_ver bacam_ver; u8 sec_ctrl_efuse_size; u32 physical_efuse_size; @@ -3162,6 +3223,7 @@ struct rtw89_chip_info { const struct rtw89_phy_table *bb_gain_table; const struct rtw89_phy_table *rf_table[RF_PATH_MAX]; const struct rtw89_phy_table *nctl_table; + const struct rtw89_rfk_tbl *nctl_post_table; const struct rtw89_txpwr_table *byr_table; const struct rtw89_phy_dig_gain_table *dig_table; const struct rtw89_dig_regs *dig_regs; @@ -3215,6 +3277,7 @@ struct rtw89_chip_info { u32 dma_ch_mask; u32 edcca_lvl_reg; const struct wiphy_wowlan_support *wowlan_stub; + const struct rtw89_xtal_info *xtal_info; }; union rtw89_bus_info { @@ -3237,7 +3300,6 @@ enum rtw89_hcifc_mode { struct rtw89_dle_info { enum rtw89_qta_mode qta_mode; - u16 wde_pg_size; u16 ple_pg_size; u16 c0_rx_qta; u16 c1_rx_qta; @@ -3248,14 +3310,6 @@ enum rtw89_host_rpr_mode { RTW89_RPR_MODE_STF }; -struct rtw89_mac_info { - struct rtw89_dle_info dle_info; - struct rtw89_hfc_param hfc_param; - enum rtw89_qta_mode qta_mode; - u8 rpwm_seq_num; - u8 cpwm_seq_num; -}; - #define RTW89_COMPLETION_BUF_SIZE 24 #define RTW89_WAIT_COND_IDLE UINT_MAX @@ -3278,6 +3332,17 @@ static inline void rtw89_init_wait(struct rtw89_wait_info *wait) atomic_set(&wait->cond, RTW89_WAIT_COND_IDLE); } +struct rtw89_mac_info { + struct rtw89_dle_info dle_info; + struct rtw89_hfc_param hfc_param; + enum rtw89_qta_mode qta_mode; + u8 rpwm_seq_num; + u8 cpwm_seq_num; + + /* see RTW89_FW_OFLD_WAIT_COND series for wait condition */ + struct rtw89_wait_info fw_ofld_wait; +}; + enum rtw89_fw_type { RTW89_FW_NORMAL = 1, RTW89_FW_WOWLAN = 3, @@ -3322,10 +3387,10 @@ struct rtw89_fw_suit { (mfw_hdr)->ver.idx) #define RTW89_FW_HDR_VER_CODE(fw_hdr) \ - RTW89_FW_VER_CODE(GET_FW_HDR_MAJOR_VERSION(fw_hdr), \ - GET_FW_HDR_MINOR_VERSION(fw_hdr), \ - GET_FW_HDR_SUBVERSION(fw_hdr), \ - GET_FW_HDR_SUBINDEX(fw_hdr)) + RTW89_FW_VER_CODE(le32_get_bits((fw_hdr)->w1, FW_HDR_W1_MAJOR_VERSION), \ + le32_get_bits((fw_hdr)->w1, FW_HDR_W1_MINOR_VERSION), \ + le32_get_bits((fw_hdr)->w1, FW_HDR_W1_SUBVERSION), \ + le32_get_bits((fw_hdr)->w1, FW_HDR_W1_SUBINDEX)) struct rtw89_fw_req_info { const struct firmware *firmware; @@ -3417,12 +3482,13 @@ struct rtw89_hal { u32 rx_fltr; u8 cv; u8 acv; - u32 sw_amsdu_max_size; u32 antenna_tx; u32 antenna_rx; u8 tx_nss; u8 rx_nss; bool tx_path_diversity; + bool ant_diversity; + bool ant_diversity_fixed; bool support_cckpd; bool support_igi; atomic_t roc_entity_idx; @@ -3452,6 +3518,7 @@ enum rtw89_flags { RTW89_FLAG_LOW_POWER_MODE, RTW89_FLAG_INACTIVE_PS, RTW89_FLAG_CRASH_SIMULATING, + RTW89_FLAG_SER_HANDLING, RTW89_FLAG_WOWLAN, RTW89_FLAG_FORBIDDEN_TRACK_WROK, RTW89_FLAG_CHANGING_INTERFACE, @@ -3543,7 +3610,6 @@ struct rtw89_iqk_info { u8 iqk_band[RTW89_IQK_PATH_NR]; u8 iqk_ch[RTW89_IQK_PATH_NR]; u8 iqk_bw[RTW89_IQK_PATH_NR]; - u8 kcount; u8 iqk_times; u8 version; u32 nb_txcfir[RTW89_IQK_PATH_NR]; @@ -3558,8 +3624,6 @@ struct rtw89_iqk_info { bool iqk_xym_en; bool iqk_sram_en; bool iqk_cfir_en; - u8 thermal[RTW89_IQK_PATH_NR]; - bool thermal_rek_en; u32 syn1to2; u8 iqk_mcc_ch[RTW89_IQK_CHS_NR][RTW89_IQK_PATH_NR]; u8 iqk_table_idx[RTW89_IQK_PATH_NR]; @@ -3749,9 +3813,14 @@ struct rtw89_power_trim_info { u8 pa_bias_trim[RF_PATH_MAX]; }; -struct rtw89_regulatory { +struct rtw89_regd { char alpha2[3]; - u8 txpwr_regd[RTW89_BAND_MAX]; + u8 txpwr_regd[RTW89_BAND_NUM]; +}; + +struct rtw89_regulatory_info { + const struct rtw89_regd *regd; + enum rtw89_reg_6ghz_power reg_6ghz_power; }; enum rtw89_ifs_clm_application { @@ -3815,35 +3884,16 @@ enum rtw89_ccx_edcca_opt_bw_idx { #define RTW89_FAHM_RPT_NUM 12 #define RTW89_IFS_CLM_NUM 4 struct rtw89_env_monitor_info { - u32 ccx_trigger_time; - u64 start_time; - u8 ccx_rpt_stamp; u8 ccx_watchdog_result; bool ccx_ongoing; u8 ccx_rac_lv; bool ccx_manual_ctrl; - u8 ccx_pre_rssi; - u16 clm_mntr_time; - u16 nhm_mntr_time; u16 ifs_clm_mntr_time; enum rtw89_ifs_clm_application ifs_clm_app; - u16 fahm_mntr_time; - u16 edcca_clm_mntr_time; u16 ccx_period; u8 ccx_unit_idx; - enum rtw89_ccx_edcca_opt_bw_idx ccx_edcca_opt_bw_idx; - u8 nhm_th[RTW89_NHM_TH_NUM]; u16 ifs_clm_th_l[RTW89_IFS_CLM_NUM]; u16 ifs_clm_th_h[RTW89_IFS_CLM_NUM]; - u8 fahm_numer_opt; - u8 fahm_denom_opt; - u8 fahm_th[RTW89_FAHM_TH_NUM]; - u16 clm_result; - u16 nhm_result[RTW89_NHM_RPT_NUM]; - u8 nhm_wgt[RTW89_NHM_RPT_NUM]; - u16 nhm_tx_cnt; - u16 nhm_cca_cnt; - u16 nhm_idle_cnt; u16 ifs_clm_tx; u16 ifs_clm_edcca_excl_cca; u16 ifs_clm_ofdmfa; @@ -3854,17 +3904,6 @@ struct rtw89_env_monitor_info { u8 ifs_clm_his[RTW89_IFS_CLM_NUM]; u16 ifs_clm_avg[RTW89_IFS_CLM_NUM]; u16 ifs_clm_cca[RTW89_IFS_CLM_NUM]; - u16 fahm_result[RTW89_FAHM_RPT_NUM]; - u16 fahm_denom_result; - u16 edcca_clm_result; - u8 clm_ratio; - u8 nhm_rpt[RTW89_NHM_RPT_NUM]; - u8 nhm_tx_ratio; - u8 nhm_cca_ratio; - u8 nhm_idle_ratio; - u8 nhm_ratio; - u16 nhm_result_sum; - u8 nhm_pwr; u8 ifs_clm_tx_ratio; u8 ifs_clm_edcca_excl_cca_ratio; u8 ifs_clm_cck_fa_ratio; @@ -3875,12 +3914,6 @@ struct rtw89_env_monitor_info { u16 ifs_clm_ofdm_fa_permil; u32 ifs_clm_ifs_avg[RTW89_IFS_CLM_NUM]; u32 ifs_clm_cca_avg[RTW89_IFS_CLM_NUM]; - u8 fahm_rpt[RTW89_FAHM_RPT_NUM]; - u16 fahm_result_sum; - u8 fahm_ratio; - u8 fahm_denom_ratio; - u8 fahm_pwr; - u8 edcca_clm_ratio; }; enum rtw89_ser_rcvy_step { @@ -3888,12 +3921,14 @@ enum rtw89_ser_rcvy_step { RTW89_SER_DRV_STOP_RX, RTW89_SER_DRV_STOP_RUN, RTW89_SER_HAL_STOP_DMA, + RTW89_SER_SUPPRESS_LOG, RTW89_NUM_OF_SER_FLAGS }; struct rtw89_ser { u8 state; u8 alarm_event; + bool prehandle_l1; struct work_struct ser_hdl_work; struct delayed_work ser_alarm_work; @@ -4054,6 +4089,7 @@ struct rtw89_dev { struct work_struct c2h_work; struct work_struct ips_work; struct work_struct load_firmware_work; + struct work_struct cancel_6ghz_probe_work; struct list_head early_h2c_list; @@ -4075,7 +4111,7 @@ struct rtw89_dev { bool is_bt_iqk_timeout; struct rtw89_fem_info fem; - struct rtw89_txpwr_byrate byr[RTW89_BAND_MAX]; + struct rtw89_txpwr_byrate byr[RTW89_BAND_NUM]; struct rtw89_tssi_info tssi; struct rtw89_power_trim_info pwr_trim; @@ -4086,6 +4122,7 @@ struct rtw89_dev { struct rtw89_phy_bb_gain_info bb_gain; struct rtw89_phy_efuse_gain efuse_gain; struct rtw89_phy_ul_tb_info ul_tb_info; + struct rtw89_antdiv_info antdiv; struct delayed_work track_work; struct delayed_work coex_act1_work; @@ -4094,11 +4131,12 @@ struct rtw89_dev { struct delayed_work cfo_track_work; struct delayed_work forbid_ba_work; struct delayed_work roc_work; + struct delayed_work antdiv_work; struct rtw89_ppdu_sts_info ppdu_sts; u8 total_sta_assoc; bool scanning; - const struct rtw89_regulatory *regd; + struct rtw89_regulatory_info regulatory; struct rtw89_sar_info sar; struct rtw89_btc btc; @@ -4643,6 +4681,14 @@ static inline void rtw89_chip_fem_setup(struct rtw89_dev *rtwdev) chip->ops->fem_setup(rtwdev); } +static inline void rtw89_chip_rfe_gpio(struct rtw89_dev *rtwdev) +{ + const struct rtw89_chip_info *chip = rtwdev->chip; + + if (chip->ops->rfe_gpio) + chip->ops->rfe_gpio(rtwdev); +} + static inline void rtw89_chip_bb_sethw(struct rtw89_dev *rtwdev) { const struct rtw89_chip_info *chip = rtwdev->chip; @@ -4777,7 +4823,9 @@ static inline void rtw89_load_txpwr_table(struct rtw89_dev *rtwdev, static inline u8 rtw89_regd_get(struct rtw89_dev *rtwdev, u8 band) { - return rtwdev->regd->txpwr_regd[band]; + const struct rtw89_regd *regd = rtwdev->regulatory.regd; + + return regd->txpwr_regd[band]; } static inline void rtw89_ctrl_btg(struct rtw89_dev *rtwdev, bool btg) @@ -4788,6 +4836,16 @@ static inline void rtw89_ctrl_btg(struct rtw89_dev *rtwdev, bool btg) chip->ops->ctrl_btg(rtwdev, btg); } +static inline +void rtw89_chip_query_rxdesc(struct rtw89_dev *rtwdev, + struct rtw89_rx_desc_info *desc_info, + u8 *data, u32 data_offset) +{ + const struct rtw89_chip_info *chip = rtwdev->chip; + + chip->ops->query_rxdesc(rtwdev, desc_info, data, data_offset); +} + static inline void rtw89_chip_fill_txdesc(struct rtw89_dev *rtwdev, struct rtw89_tx_desc_info *desc_info, @@ -4990,6 +5048,7 @@ int rtw89_core_release_sta_ba_entry(struct rtw89_dev *rtwdev, void rtw89_vif_type_mapping(struct ieee80211_vif *vif, bool assoc); int rtw89_chip_info_setup(struct rtw89_dev *rtwdev); bool rtw89_ra_report_to_bitrate(struct rtw89_dev *rtwdev, u8 rpt_rate, u16 *bitrate); +int rtw89_regd_setup(struct rtw89_dev *rtwdev); int rtw89_regd_init(struct rtw89_dev *rtwdev, void (*reg_notifier)(struct wiphy *wiphy, struct regulatory_request *request)); void rtw89_regd_notifier(struct wiphy *wiphy, struct regulatory_request *request); @@ -5008,5 +5067,7 @@ void rtw89_core_scan_start(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, const u8 *mac_addr, bool hw_scan); void rtw89_core_scan_complete(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, bool hw_scan); +void rtw89_reg_6ghz_power_recalc(struct rtw89_dev *rtwdev, + struct rtw89_vif *rtwvif, bool active); #endif diff --git a/drivers/net/wireless/realtek/rtw89/debug.c b/drivers/net/wireless/realtek/rtw89/debug.c index 1e5b7a9987163515d7f125b842f46f7f7118d636..a4bbac916e22b9ec4c5a8182f88c26f08166e6ef 100644 --- a/drivers/net/wireless/realtek/rtw89/debug.c +++ b/drivers/net/wireless/realtek/rtw89/debug.c @@ -30,7 +30,7 @@ struct rtw89_debugfs_priv { u32 cb_data; struct { u32 addr; - u8 len; + u32 len; } read_reg; struct { u32 addr; @@ -164,12 +164,15 @@ static int rtw89_debug_priv_read_reg_get(struct seq_file *m, void *v) { struct rtw89_debugfs_priv *debugfs_priv = m->private; struct rtw89_dev *rtwdev = debugfs_priv->rtwdev; - u32 addr, data; - u8 len; + u32 addr, end, data, k; + u32 len; len = debugfs_priv->read_reg.len; addr = debugfs_priv->read_reg.addr; + if (len > 4) + goto ndata; + switch (len) { case 1: data = rtw89_read8(rtwdev, addr); @@ -187,6 +190,20 @@ static int rtw89_debug_priv_read_reg_get(struct seq_file *m, void *v) seq_printf(m, "get %d bytes at 0x%08x=0x%08x\n", len, addr, data); + return 0; + +ndata: + end = addr + len; + + for (; addr < end; addr += 16) { + seq_printf(m, "%08xh : ", 0x18600000 + addr); + for (k = 0; k < 16; k += 4) { + data = rtw89_read32(rtwdev, addr + k); + seq_printf(m, "%08x ", data); + } + seq_puts(m, "\n"); + } + return 0; } @@ -359,6 +376,7 @@ struct txpwr_map { u8 size; u32 addr_from; u32 addr_to; + u32 addr_to_1ss; }; #define __GEN_TXPWR_ENT2(_t, _e0, _e1) \ @@ -396,6 +414,7 @@ static const struct txpwr_map __txpwr_map_byr = { .size = ARRAY_SIZE(__txpwr_ent_byr), .addr_from = R_AX_PWR_BY_RATE, .addr_to = R_AX_PWR_BY_RATE_MAX, + .addr_to_1ss = R_AX_PWR_BY_RATE_1SS_MAX, }; static const struct txpwr_ent __txpwr_ent_lmt[] = { @@ -451,6 +470,7 @@ static const struct txpwr_map __txpwr_map_lmt = { .size = ARRAY_SIZE(__txpwr_ent_lmt), .addr_from = R_AX_PWR_LMT, .addr_to = R_AX_PWR_LMT_MAX, + .addr_to_1ss = R_AX_PWR_LMT_1SS_MAX, }; static const struct txpwr_ent __txpwr_ent_lmt_ru[] = { @@ -478,6 +498,7 @@ static const struct txpwr_map __txpwr_map_lmt_ru = { .size = ARRAY_SIZE(__txpwr_ent_lmt_ru), .addr_from = R_AX_PWR_RU_LMT, .addr_to = R_AX_PWR_RU_LMT_MAX, + .addr_to_1ss = R_AX_PWR_RU_LMT_1SS_MAX, }; static u8 __print_txpwr_ent(struct seq_file *m, const struct txpwr_ent *ent, @@ -510,6 +531,8 @@ static int __print_txpwr_map(struct seq_file *m, struct rtw89_dev *rtwdev, const struct txpwr_map *map) { u8 fct = rtwdev->chip->txpwr_factor_mac; + u8 path_num = rtwdev->chip->rf_path_num; + u32 max_valid_addr; u32 val, addr; s8 *buf, tmp; u8 cur, i; @@ -519,7 +542,12 @@ static int __print_txpwr_map(struct seq_file *m, struct rtw89_dev *rtwdev, if (!buf) return -ENOMEM; - for (addr = map->addr_from; addr <= map->addr_to; addr += 4) { + if (path_num == 1) + max_valid_addr = map->addr_to_1ss; + else + max_valid_addr = map->addr_to; + + for (addr = map->addr_from; addr <= max_valid_addr; addr += 4) { ret = rtw89_mac_txpwr_read32(rtwdev, RTW89_PHY_0, addr, &val); if (ret) val = MASKDWORD; @@ -2998,17 +3026,18 @@ static ssize_t rtw89_debug_priv_send_h2c_set(struct file *filp, struct rtw89_debugfs_priv *debugfs_priv = filp->private_data; struct rtw89_dev *rtwdev = debugfs_priv->rtwdev; u8 *h2c; + int ret; u16 h2c_len = count / 2; h2c = rtw89_hex2bin_user(rtwdev, user_buf, count); if (IS_ERR(h2c)) return -EFAULT; - rtw89_fw_h2c_raw(rtwdev, h2c, h2c_len); + ret = rtw89_fw_h2c_raw(rtwdev, h2c, h2c_len); kfree(h2c); - return count; + return ret ? ret : count; } static int @@ -3206,7 +3235,11 @@ static void rtw89_sta_info_get_iter(void *data, struct ieee80211_sta *sta) struct seq_file *m = (struct seq_file *)data; struct rtw89_dev *rtwdev = rtwsta->rtwdev; struct rtw89_hal *hal = &rtwdev->hal; + u8 ant_num = hal->ant_diversity ? 2 : rtwdev->chip->rf_path_num; + bool ant_asterisk = hal->tx_path_diversity || hal->ant_diversity; + u8 evm_min, evm_max; u8 rssi; + u8 snr; int i; seq_printf(m, "TX rate [%d]: ", rtwsta->mac_id); @@ -3256,13 +3289,27 @@ static void rtw89_sta_info_get_iter(void *data, struct ieee80211_sta *sta) rssi = ewma_rssi_read(&rtwsta->avg_rssi); seq_printf(m, "RSSI: %d dBm (raw=%d, prev=%d) [", RTW89_RSSI_RAW_TO_DBM(rssi), rssi, rtwsta->prev_rssi); - for (i = 0; i < rtwdev->chip->rf_path_num; i++) { + for (i = 0; i < ant_num; i++) { rssi = ewma_rssi_read(&rtwsta->rssi[i]); seq_printf(m, "%d%s%s", RTW89_RSSI_RAW_TO_DBM(rssi), - hal->tx_path_diversity && (hal->antenna_tx & BIT(i)) ? "*" : "", - i + 1 == rtwdev->chip->rf_path_num ? "" : ", "); + ant_asterisk && (hal->antenna_tx & BIT(i)) ? "*" : "", + i + 1 == ant_num ? "" : ", "); } seq_puts(m, "]\n"); + + seq_puts(m, "EVM: ["); + for (i = 0; i < (hal->ant_diversity ? 2 : 1); i++) { + evm_min = ewma_evm_read(&rtwsta->evm_min[i]); + evm_max = ewma_evm_read(&rtwsta->evm_max[i]); + + seq_printf(m, "%s(%2u.%02u, %2u.%02u)", i == 0 ? "" : " ", + evm_min >> 2, (evm_min & 0x3) * 25, + evm_max >> 2, (evm_max & 0x3) * 25); + } + seq_puts(m, "]\t"); + + snr = ewma_snr_read(&rtwsta->avg_snr); + seq_printf(m, "SNR: %u\n", snr); } static void diff --git a/drivers/net/wireless/realtek/rtw89/efuse.c b/drivers/net/wireless/realtek/rtw89/efuse.c index 7bd4f8558e03b624b5f4da10c13c441e705e4f6c..2aaf4d013e464597c80b78af9cb035a8c3546eb6 100644 --- a/drivers/net/wireless/realtek/rtw89/efuse.c +++ b/drivers/net/wireless/realtek/rtw89/efuse.c @@ -7,6 +7,10 @@ #include "mac.h" #include "reg.h" +#define EF_FV_OFSET 0x5ea +#define EF_CV_MASK GENMASK(7, 4) +#define EF_CV_INV 15 + enum rtw89_efuse_bank { RTW89_EFUSE_BANK_WIFI, RTW89_EFUSE_BANK_BT, @@ -328,3 +332,20 @@ int rtw89_parse_phycap_map(struct rtw89_dev *rtwdev) return ret; } + +int rtw89_read_efuse_ver(struct rtw89_dev *rtwdev, u8 *ecv) +{ + int ret; + u8 val; + + ret = rtw89_dump_physical_efuse_map(rtwdev, &val, EF_FV_OFSET, 1, false); + if (ret) + return ret; + + *ecv = u8_get_bits(val, EF_CV_MASK); + if (*ecv == EF_CV_INV) + return -ENOENT; + + return 0; +} +EXPORT_SYMBOL(rtw89_read_efuse_ver); diff --git a/drivers/net/wireless/realtek/rtw89/efuse.h b/drivers/net/wireless/realtek/rtw89/efuse.h index 622ff95e74763af9d593871b621c9ff72f4d3418..79071aff28de3832a7888bc99176074c40504f76 100644 --- a/drivers/net/wireless/realtek/rtw89/efuse.h +++ b/drivers/net/wireless/realtek/rtw89/efuse.h @@ -9,5 +9,6 @@ int rtw89_parse_efuse_map(struct rtw89_dev *rtwdev); int rtw89_parse_phycap_map(struct rtw89_dev *rtwdev); +int rtw89_read_efuse_ver(struct rtw89_dev *rtwdev, u8 *efv); #endif diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c index b9b675bf9d0500326db3e4466dfcab13d985194f..9637f5e48d842e6d3b5b10f75c0ffdd319da71ed 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.c +++ b/drivers/net/wireless/realtek/rtw89/fw.c @@ -14,6 +14,8 @@ static void rtw89_fw_c2h_cmd_handle(struct rtw89_dev *rtwdev, struct sk_buff *skb); +static int rtw89_h2c_tx_and_wait(struct rtw89_dev *rtwdev, struct sk_buff *skb, + struct rtw89_wait_info *wait, unsigned int cond); static struct sk_buff *rtw89_fw_h2c_alloc_skb(struct rtw89_dev *rtwdev, u32 len, bool header) @@ -87,9 +89,11 @@ int rtw89_fw_check_rdy(struct rtw89_dev *rtwdev) static int rtw89_fw_hdr_parser(struct rtw89_dev *rtwdev, const u8 *fw, u32 len, struct rtw89_fw_bin_info *info) { + const struct rtw89_fw_hdr *fw_hdr = (const struct rtw89_fw_hdr *)fw; struct rtw89_fw_hdr_section_info *section_info; + const struct rtw89_fw_dynhdr_hdr *fwdynhdr; + const struct rtw89_fw_hdr_section *section; const u8 *fw_end = fw + len; - const u8 *fwdynhdr; const u8 *bin; u32 base_hdr_len; u32 mssc_len = 0; @@ -98,16 +102,15 @@ static int rtw89_fw_hdr_parser(struct rtw89_dev *rtwdev, const u8 *fw, u32 len, if (!info) return -EINVAL; - info->section_num = GET_FW_HDR_SEC_NUM(fw); - base_hdr_len = RTW89_FW_HDR_SIZE + - info->section_num * RTW89_FW_SECTION_HDR_SIZE; - info->dynamic_hdr_en = GET_FW_HDR_DYN_HDR(fw); + info->section_num = le32_get_bits(fw_hdr->w6, FW_HDR_W6_SEC_NUM); + base_hdr_len = struct_size(fw_hdr, sections, info->section_num); + info->dynamic_hdr_en = le32_get_bits(fw_hdr->w7, FW_HDR_W7_DYN_HDR); if (info->dynamic_hdr_en) { - info->hdr_len = GET_FW_HDR_LEN(fw); + info->hdr_len = le32_get_bits(fw_hdr->w3, FW_HDR_W3_LEN); info->dynamic_hdr_len = info->hdr_len - base_hdr_len; - fwdynhdr = fw + base_hdr_len; - if (GET_FW_DYNHDR_LEN(fwdynhdr) != info->dynamic_hdr_len) { + fwdynhdr = (const struct rtw89_fw_dynhdr_hdr *)(fw + base_hdr_len); + if (le32_to_cpu(fwdynhdr->hdr_len) != info->dynamic_hdr_len) { rtw89_err(rtwdev, "[ERR]invalid fw dynamic header len\n"); return -EINVAL; } @@ -119,26 +122,27 @@ static int rtw89_fw_hdr_parser(struct rtw89_dev *rtwdev, const u8 *fw, u32 len, bin = fw + info->hdr_len; /* jump to section header */ - fw += RTW89_FW_HDR_SIZE; section_info = info->section_info; for (i = 0; i < info->section_num; i++) { - section_info->type = GET_FWSECTION_HDR_SECTIONTYPE(fw); + section = &fw_hdr->sections[i]; + section_info->type = + le32_get_bits(section->w1, FWSECTION_HDR_W1_SECTIONTYPE); if (section_info->type == FWDL_SECURITY_SECTION_TYPE) { - section_info->mssc = GET_FWSECTION_HDR_MSSC(fw); + section_info->mssc = + le32_get_bits(section->w2, FWSECTION_HDR_W2_MSSC); mssc_len += section_info->mssc * FWDL_SECURITY_SIGLEN; } else { section_info->mssc = 0; } - section_info->len = GET_FWSECTION_HDR_SEC_SIZE(fw); - if (GET_FWSECTION_HDR_CHECKSUM(fw)) + section_info->len = le32_get_bits(section->w1, FWSECTION_HDR_W1_SEC_SIZE); + if (le32_get_bits(section->w1, FWSECTION_HDR_W1_CHECKSUM)) section_info->len += FWDL_SECTION_CHKSUM_LEN; - section_info->redl = GET_FWSECTION_HDR_REDL(fw); + section_info->redl = le32_get_bits(section->w1, FWSECTION_HDR_W1_REDL); section_info->dladdr = - GET_FWSECTION_HDR_DL_ADDR(fw) & 0x1fffffff; + le32_get_bits(section->w0, FWSECTION_HDR_W0_DL_ADDR) & 0x1fffffff; section_info->addr = bin; bin += section_info->len; - fw += RTW89_FW_SECTION_HDR_SIZE; section_info++; } @@ -193,18 +197,18 @@ static void rtw89_fw_update_ver(struct rtw89_dev *rtwdev, enum rtw89_fw_type type, struct rtw89_fw_suit *fw_suit) { - const u8 *hdr = fw_suit->data; - - fw_suit->major_ver = GET_FW_HDR_MAJOR_VERSION(hdr); - fw_suit->minor_ver = GET_FW_HDR_MINOR_VERSION(hdr); - fw_suit->sub_ver = GET_FW_HDR_SUBVERSION(hdr); - fw_suit->sub_idex = GET_FW_HDR_SUBINDEX(hdr); - fw_suit->build_year = GET_FW_HDR_YEAR(hdr); - fw_suit->build_mon = GET_FW_HDR_MONTH(hdr); - fw_suit->build_date = GET_FW_HDR_DATE(hdr); - fw_suit->build_hour = GET_FW_HDR_HOUR(hdr); - fw_suit->build_min = GET_FW_HDR_MIN(hdr); - fw_suit->cmd_ver = GET_FW_HDR_CMD_VERSERION(hdr); + const struct rtw89_fw_hdr *hdr = (const struct rtw89_fw_hdr *)fw_suit->data; + + fw_suit->major_ver = le32_get_bits(hdr->w1, FW_HDR_W1_MAJOR_VERSION); + fw_suit->minor_ver = le32_get_bits(hdr->w1, FW_HDR_W1_MINOR_VERSION); + fw_suit->sub_ver = le32_get_bits(hdr->w1, FW_HDR_W1_SUBVERSION); + fw_suit->sub_idex = le32_get_bits(hdr->w1, FW_HDR_W1_SUBINDEX); + fw_suit->build_year = le32_get_bits(hdr->w5, FW_HDR_W5_YEAR); + fw_suit->build_mon = le32_get_bits(hdr->w4, FW_HDR_W4_MONTH); + fw_suit->build_date = le32_get_bits(hdr->w4, FW_HDR_W4_DATE); + fw_suit->build_hour = le32_get_bits(hdr->w4, FW_HDR_W4_HOUR); + fw_suit->build_min = le32_get_bits(hdr->w4, FW_HDR_W4_MIN); + fw_suit->cmd_ver = le32_get_bits(hdr->w7, FW_HDR_W7_CMD_VERSERION); rtw89_info(rtwdev, "Firmware version %u.%u.%u.%u, cmd version %u, type %u\n", @@ -254,6 +258,9 @@ struct __fw_feat_cfg { } static const struct __fw_feat_cfg fw_feat_tbl[] = { + __CFG_FW_FEAT(RTL8851B, ge, 0, 29, 37, 1, TX_WAKE), + __CFG_FW_FEAT(RTL8851B, ge, 0, 29, 37, 1, SCAN_OFFLOAD), + __CFG_FW_FEAT(RTL8851B, ge, 0, 29, 41, 0, CRASH_TRIGGER), __CFG_FW_FEAT(RTL8852A, le, 0, 13, 29, 0, OLD_HT_RA_FORMAT), __CFG_FW_FEAT(RTL8852A, ge, 0, 13, 35, 0, SCAN_OFFLOAD), __CFG_FW_FEAT(RTL8852A, ge, 0, 13, 35, 0, TX_WAKE), @@ -807,7 +814,7 @@ int rtw89_fw_h2c_ba_cam(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta, } skb_put(skb, H2C_BA_CAM_LEN); SET_BA_CAM_MACID(skb->data, macid); - if (chip->bacam_v1) + if (chip->bacam_ver == RTW89_BACAM_V0_EXT) SET_BA_CAM_ENTRY_IDX_V1(skb->data, entry_idx); else SET_BA_CAM_ENTRY_IDX(skb->data, entry_idx); @@ -823,7 +830,7 @@ int rtw89_fw_h2c_ba_cam(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta, SET_BA_CAM_INIT_REQ(skb->data, 1); SET_BA_CAM_SSN(skb->data, params->ssn); - if (chip->bacam_v1) { + if (chip->bacam_ver == RTW89_BACAM_V0_EXT) { SET_BA_CAM_STD_EN(skb->data, 1); SET_BA_CAM_BAND(skb->data, rtwvif->mac_idx); } @@ -848,8 +855,8 @@ int rtw89_fw_h2c_ba_cam(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta, return ret; } -static int rtw89_fw_h2c_init_dynamic_ba_cam_v1(struct rtw89_dev *rtwdev, - u8 entry_idx, u8 uid) +static int rtw89_fw_h2c_init_ba_cam_v0_ext(struct rtw89_dev *rtwdev, + u8 entry_idx, u8 uid) { struct sk_buff *skb; int ret; @@ -886,7 +893,7 @@ static int rtw89_fw_h2c_init_dynamic_ba_cam_v1(struct rtw89_dev *rtwdev, return ret; } -void rtw89_fw_h2c_init_ba_cam_v1(struct rtw89_dev *rtwdev) +void rtw89_fw_h2c_init_dynamic_ba_cam_v0_ext(struct rtw89_dev *rtwdev) { const struct rtw89_chip_info *chip = rtwdev->chip; u8 entry_idx = chip->bacam_num; @@ -894,7 +901,7 @@ void rtw89_fw_h2c_init_ba_cam_v1(struct rtw89_dev *rtwdev) int i; for (i = 0; i < chip->bacam_dynamic_num; i++) { - rtw89_fw_h2c_init_dynamic_ba_cam_v1(rtwdev, entry_idx, uid); + rtw89_fw_h2c_init_ba_cam_v0_ext(rtwdev, entry_idx, uid); entry_idx++; uid++; } @@ -997,8 +1004,8 @@ void rtw89_fw_release_general_pkt_list_vif(struct rtw89_dev *rtwdev, list_for_each_entry_safe(info, tmp, pkt_list, list) { if (notify_fw) rtw89_fw_h2c_del_pkt_offload(rtwdev, info->id); - rtw89_core_release_bit_map(rtwdev->pkt_offload, - info->id); + else + rtw89_core_release_bit_map(rtwdev->pkt_offload, info->id); list_del(&info->list); kfree(info); } @@ -2440,7 +2447,9 @@ int rtw89_fw_h2c_cxdrv_rfk(struct rtw89_dev *rtwdev) #define H2C_LEN_PKT_OFLD 4 int rtw89_fw_h2c_del_pkt_offload(struct rtw89_dev *rtwdev, u8 id) { + struct rtw89_wait_info *wait = &rtwdev->mac.fw_ofld_wait; struct sk_buff *skb; + unsigned int cond; u8 *cmd; int ret; @@ -2460,23 +2469,26 @@ int rtw89_fw_h2c_del_pkt_offload(struct rtw89_dev *rtwdev, u8 id) H2C_FUNC_PACKET_OFLD, 1, 1, H2C_LEN_PKT_OFLD); - ret = rtw89_h2c_tx(rtwdev, skb, false); - if (ret) { - rtw89_err(rtwdev, "failed to send h2c\n"); - goto fail; + cond = RTW89_FW_OFLD_WAIT_COND_PKT_OFLD(id, RTW89_PKT_OFLD_OP_DEL); + + ret = rtw89_h2c_tx_and_wait(rtwdev, skb, wait, cond); + if (ret < 0) { + rtw89_debug(rtwdev, RTW89_DBG_FW, + "failed to del pkt ofld: id %d, ret %d\n", + id, ret); + return ret; } + rtw89_core_release_bit_map(rtwdev->pkt_offload, id); return 0; -fail: - dev_kfree_skb_any(skb); - - return ret; } int rtw89_fw_h2c_add_pkt_offload(struct rtw89_dev *rtwdev, u8 *id, struct sk_buff *skb_ofld) { + struct rtw89_wait_info *wait = &rtwdev->mac.fw_ofld_wait; struct sk_buff *skb; + unsigned int cond; u8 *cmd; u8 alloc_id; int ret; @@ -2507,27 +2519,29 @@ int rtw89_fw_h2c_add_pkt_offload(struct rtw89_dev *rtwdev, u8 *id, H2C_FUNC_PACKET_OFLD, 1, 1, H2C_LEN_PKT_OFLD + skb_ofld->len); - ret = rtw89_h2c_tx(rtwdev, skb, false); - if (ret) { - rtw89_err(rtwdev, "failed to send h2c\n"); + cond = RTW89_FW_OFLD_WAIT_COND_PKT_OFLD(alloc_id, RTW89_PKT_OFLD_OP_ADD); + + ret = rtw89_h2c_tx_and_wait(rtwdev, skb, wait, cond); + if (ret < 0) { + rtw89_debug(rtwdev, RTW89_DBG_FW, + "failed to add pkt ofld: id %d, ret %d\n", + alloc_id, ret); rtw89_core_release_bit_map(rtwdev->pkt_offload, alloc_id); - goto fail; + return ret; } return 0; -fail: - dev_kfree_skb_any(skb); - - return ret; } #define H2C_LEN_SCAN_LIST_OFFLOAD 4 int rtw89_fw_h2c_scan_list_offload(struct rtw89_dev *rtwdev, int len, struct list_head *chan_list) { + struct rtw89_wait_info *wait = &rtwdev->mac.fw_ofld_wait; struct rtw89_mac_chinfo *ch_info; struct sk_buff *skb; int skb_len = H2C_LEN_SCAN_LIST_OFFLOAD + len * RTW89_MAC_CHINFO_SIZE; + unsigned int cond; u8 *cmd; int ret; @@ -2574,27 +2588,27 @@ int rtw89_fw_h2c_scan_list_offload(struct rtw89_dev *rtwdev, int len, H2C_CAT_MAC, H2C_CL_MAC_FW_OFLD, H2C_FUNC_ADD_SCANOFLD_CH, 1, 1, skb_len); - ret = rtw89_h2c_tx(rtwdev, skb, false); + cond = RTW89_FW_OFLD_WAIT_COND(0, H2C_FUNC_ADD_SCANOFLD_CH); + + ret = rtw89_h2c_tx_and_wait(rtwdev, skb, wait, cond); if (ret) { - rtw89_err(rtwdev, "failed to send h2c\n"); - goto fail; + rtw89_debug(rtwdev, RTW89_DBG_FW, "failed to add scan ofld ch\n"); + return ret; } return 0; -fail: - dev_kfree_skb_any(skb); - - return ret; } int rtw89_fw_h2c_scan_offload(struct rtw89_dev *rtwdev, struct rtw89_scan_option *option, struct rtw89_vif *rtwvif) { + struct rtw89_wait_info *wait = &rtwdev->mac.fw_ofld_wait; struct rtw89_chan *op = &rtwdev->scan_info.op_chan; struct rtw89_h2c_scanofld *h2c; u32 len = sizeof(*h2c); struct sk_buff *skb; + unsigned int cond; int ret; skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len); @@ -2633,17 +2647,15 @@ int rtw89_fw_h2c_scan_offload(struct rtw89_dev *rtwdev, H2C_FUNC_SCANOFLD, 1, 1, len); - ret = rtw89_h2c_tx(rtwdev, skb, false); + cond = RTW89_FW_OFLD_WAIT_COND(0, H2C_FUNC_SCANOFLD); + + ret = rtw89_h2c_tx_and_wait(rtwdev, skb, wait, cond); if (ret) { - rtw89_err(rtwdev, "failed to send h2c\n"); - goto fail; + rtw89_debug(rtwdev, RTW89_DBG_FW, "failed to scan ofld\n"); + return ret; } return 0; -fail: - dev_kfree_skb_any(skb); - - return ret; } int rtw89_fw_h2c_rf_reg(struct rtw89_dev *rtwdev, @@ -2909,12 +2921,13 @@ static int rtw89_fw_write_h2c_reg(struct rtw89_dev *rtwdev, } len = DIV_ROUND_UP(info->content_len + RTW89_H2CREG_HDR_LEN, - sizeof(info->h2creg[0])); + sizeof(info->u.h2creg[0])); + + u32p_replace_bits(&info->u.hdr.w0, info->id, RTW89_H2CREG_HDR_FUNC_MASK); + u32p_replace_bits(&info->u.hdr.w0, len, RTW89_H2CREG_HDR_LEN_MASK); - RTW89_SET_H2CREG_HDR_FUNC(&info->h2creg[0], info->id); - RTW89_SET_H2CREG_HDR_LEN(&info->h2creg[0], len); for (i = 0; i < RTW89_H2CREG_MAX; i++) - rtw89_write32(rtwdev, h2c_reg[i], info->h2creg[i]); + rtw89_write32(rtwdev, h2c_reg[i], info->u.h2creg[i]); fw_info->h2c_counter++; rtw89_write8_mask(rtwdev, chip->h2c_counter_reg.addr, @@ -2944,13 +2957,14 @@ static int rtw89_fw_read_c2h_reg(struct rtw89_dev *rtwdev, } for (i = 0; i < RTW89_C2HREG_MAX; i++) - info->c2hreg[i] = rtw89_read32(rtwdev, c2h_reg[i]); + info->u.c2hreg[i] = rtw89_read32(rtwdev, c2h_reg[i]); rtw89_write8(rtwdev, chip->c2h_ctrl_reg, 0); - info->id = RTW89_GET_C2H_HDR_FUNC(*info->c2hreg); - info->content_len = (RTW89_GET_C2H_HDR_LEN(*info->c2hreg) << 2) - - RTW89_C2HREG_HDR_LEN; + info->id = u32_get_bits(info->u.hdr.w0, RTW89_C2HREG_HDR_FUNC_MASK); + info->content_len = + (u32_get_bits(info->u.hdr.w0, RTW89_C2HREG_HDR_LEN_MASK) << 2) - + RTW89_C2HREG_HDR_LEN; fw_info->c2h_counter++; rtw89_write8_mask(rtwdev, chip->c2h_counter_reg.addr, @@ -3019,9 +3033,8 @@ static void rtw89_release_pkt_list(struct rtw89_dev *rtwdev) continue; list_for_each_entry_safe(info, tmp, &pkt_list[idx], list) { - rtw89_fw_h2c_del_pkt_offload(rtwdev, info->id); - rtw89_core_release_bit_map(rtwdev->pkt_offload, - info->id); + if (test_bit(info->id, rtwdev->pkt_offload)) + rtw89_fw_h2c_del_pkt_offload(rtwdev, info->id); list_del(&info->list); kfree(info); } @@ -3786,6 +3799,11 @@ int rtw89_fw_wow_cam_update(struct rtw89_dev *rtwdev, return ret; } +/* Return < 0, if failures happen during waiting for the condition. + * Return 0, when waiting for the condition succeeds. + * Return > 0, if the wait is considered unreachable due to driver/FW design, + * where 1 means during SER. + */ static int rtw89_h2c_tx_and_wait(struct rtw89_dev *rtwdev, struct sk_buff *skb, struct rtw89_wait_info *wait, unsigned int cond) { @@ -3798,6 +3816,9 @@ static int rtw89_h2c_tx_and_wait(struct rtw89_dev *rtwdev, struct sk_buff *skb, return -EBUSY; } + if (test_bit(RTW89_FLAG_SER_HANDLING, rtwdev->flags)) + return 1; + return rtw89_wait_for_cond(wait, cond); } diff --git a/drivers/net/wireless/realtek/rtw89/fw.h b/drivers/net/wireless/realtek/rtw89/fw.h index 675f85c41471b4ea04151975e8132aa8bd102195..45f927dc212ef0a90caca1dd128d83a9c5120cbb 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.h +++ b/drivers/net/wireless/realtek/rtw89/fw.h @@ -18,15 +18,51 @@ enum rtw89_fw_dl_status { RTW89_FWDL_WCPU_FW_INIT_RDY = 7 }; -#define RTW89_GET_C2H_HDR_FUNC(info) \ - u32_get_bits(info, GENMASK(6, 0)) -#define RTW89_GET_C2H_HDR_LEN(info) \ - u32_get_bits(info, GENMASK(11, 8)) +struct rtw89_c2hreg_hdr { + u32 w0; +}; + +#define RTW89_C2HREG_HDR_FUNC_MASK GENMASK(6, 0) +#define RTW89_C2HREG_HDR_ACK BIT(7) +#define RTW89_C2HREG_HDR_LEN_MASK GENMASK(11, 8) +#define RTW89_C2HREG_HDR_SEQ_MASK GENMASK(15, 12) + +struct rtw89_c2hreg_phycap { + u32 w0; + u32 w1; + u32 w2; + u32 w3; +} __packed; + +#define RTW89_C2HREG_PHYCAP_W0_FUNC GENMASK(6, 0) +#define RTW89_C2HREG_PHYCAP_W0_ACK BIT(7) +#define RTW89_C2HREG_PHYCAP_W0_LEN GENMASK(11, 8) +#define RTW89_C2HREG_PHYCAP_W0_SEQ GENMASK(15, 12) +#define RTW89_C2HREG_PHYCAP_W0_RX_NSS GENMASK(23, 16) +#define RTW89_C2HREG_PHYCAP_W0_BW GENMASK(31, 24) +#define RTW89_C2HREG_PHYCAP_W1_TX_NSS GENMASK(7, 0) +#define RTW89_C2HREG_PHYCAP_W1_PROT GENMASK(15, 8) +#define RTW89_C2HREG_PHYCAP_W1_NIC GENMASK(23, 16) +#define RTW89_C2HREG_PHYCAP_W1_WL_FUNC GENMASK(31, 24) +#define RTW89_C2HREG_PHYCAP_W2_HW_TYPE GENMASK(7, 0) +#define RTW89_C2HREG_PHYCAP_W3_ANT_TX_NUM GENMASK(15, 8) +#define RTW89_C2HREG_PHYCAP_W3_ANT_RX_NUM GENMASK(23, 16) + +struct rtw89_h2creg_hdr { + u32 w0; +}; + +#define RTW89_H2CREG_HDR_FUNC_MASK GENMASK(6, 0) +#define RTW89_H2CREG_HDR_LEN_MASK GENMASK(11, 8) -#define RTW89_SET_H2CREG_HDR_FUNC(info, val) \ - u32p_replace_bits(info, val, GENMASK(6, 0)) -#define RTW89_SET_H2CREG_HDR_LEN(info, val) \ - u32p_replace_bits(info, val, GENMASK(11, 8)) +struct rtw89_h2creg_sch_tx_en { + u32 w0; + u32 w1; +} __packed; + +#define RTW89_H2CREG_SCH_TX_EN_W0_EN GENMASK(31, 16) +#define RTW89_H2CREG_SCH_TX_EN_W1_MASK GENMASK(15, 0) +#define RTW89_H2CREG_SCH_TX_EN_W1_BAND BIT(16) #define RTW89_H2CREG_MAX 4 #define RTW89_C2HREG_MAX 4 @@ -36,13 +72,21 @@ enum rtw89_fw_dl_status { struct rtw89_mac_c2h_info { u8 id; u8 content_len; - u32 c2hreg[RTW89_C2HREG_MAX]; + union { + u32 c2hreg[RTW89_C2HREG_MAX]; + struct rtw89_c2hreg_hdr hdr; + struct rtw89_c2hreg_phycap phycap; + } u; }; struct rtw89_mac_h2c_info { u8 id; u8 content_len; - u32 h2creg[RTW89_H2CREG_MAX]; + union { + u32 h2creg[RTW89_H2CREG_MAX]; + struct rtw89_h2creg_hdr hdr; + struct rtw89_h2creg_sch_tx_en sch_tx_en; + } u; }; enum rtw89_mac_h2c_type { @@ -63,33 +107,6 @@ enum rtw89_mac_c2h_type { RTW89_FWCMD_C2HREG_FUNC_NULL = 0xFF }; -#define RTW89_GET_C2H_PHYCAP_FUNC(info) \ - u32_get_bits(*((const u32 *)(info)), GENMASK(6, 0)) -#define RTW89_GET_C2H_PHYCAP_ACK(info) \ - u32_get_bits(*((const u32 *)(info)), BIT(7)) -#define RTW89_GET_C2H_PHYCAP_LEN(info) \ - u32_get_bits(*((const u32 *)(info)), GENMASK(11, 8)) -#define RTW89_GET_C2H_PHYCAP_SEQ(info) \ - u32_get_bits(*((const u32 *)(info)), GENMASK(15, 12)) -#define RTW89_GET_C2H_PHYCAP_RX_NSS(info) \ - u32_get_bits(*((const u32 *)(info)), GENMASK(23, 16)) -#define RTW89_GET_C2H_PHYCAP_BW(info) \ - u32_get_bits(*((const u32 *)(info)), GENMASK(31, 24)) -#define RTW89_GET_C2H_PHYCAP_TX_NSS(info) \ - u32_get_bits(*((const u32 *)(info) + 1), GENMASK(7, 0)) -#define RTW89_GET_C2H_PHYCAP_PROT(info) \ - u32_get_bits(*((const u32 *)(info) + 1), GENMASK(15, 8)) -#define RTW89_GET_C2H_PHYCAP_NIC(info) \ - u32_get_bits(*((const u32 *)(info) + 1), GENMASK(23, 16)) -#define RTW89_GET_C2H_PHYCAP_WL_FUNC(info) \ - u32_get_bits(*((const u32 *)(info) + 1), GENMASK(31, 24)) -#define RTW89_GET_C2H_PHYCAP_HW_TYPE(info) \ - u32_get_bits(*((const u32 *)(info) + 2), GENMASK(7, 0)) -#define RTW89_GET_C2H_PHYCAP_ANT_TX_NUM(info) \ - u32_get_bits(*((const u32 *)(info) + 3), GENMASK(15, 8)) -#define RTW89_GET_C2H_PHYCAP_ANT_RX_NUM(info) \ - u32_get_bits(*((const u32 *)(info) + 3), GENMASK(23, 16)) - enum rtw89_fw_c2h_category { RTW89_C2H_CAT_TEST, RTW89_C2H_CAT_MAC, @@ -138,8 +155,13 @@ enum rtw89_pkt_offload_op { RTW89_PKT_OFLD_OP_ADD, RTW89_PKT_OFLD_OP_DEL, RTW89_PKT_OFLD_OP_READ, + + NUM_OF_RTW89_PKT_OFFLOAD_OP, }; +#define RTW89_PKT_OFLD_WAIT_TAG(pkt_id, pkt_op) \ + ((pkt_id) * NUM_OF_RTW89_PKT_OFFLOAD_OP + (pkt_op)) + enum rtw89_scanofld_notify_reason { RTW89_SCAN_DWELL_NOTIFY, RTW89_SCAN_PRE_TX_NOTIFY, @@ -209,17 +231,6 @@ struct rtw89_fw_macid_pause_grp { __le32 mask_grp[4]; } __packed; -struct rtw89_h2creg_sch_tx_en { - u8 func:7; - u8 ack:1; - u8 total_len:4; - u8 seq_num:4; - u16 tx_en:16; - u16 mask:16; - u8 band:1; - u16 rsvd:15; -} __packed; - #define RTW89_H2C_MAX_SIZE 2048 #define RTW89_CHANNEL_TIME 45 #define RTW89_CHANNEL_TIME_6G 20 @@ -232,7 +243,7 @@ struct rtw89_h2creg_sch_tx_en { #define RTW89_SCANOFLD_MAX_IE_LEN 512 #define RTW89_SCANOFLD_PKT_NONE 0xFF #define RTW89_SCANOFLD_DEBUG_MASK 0x1F -#define RTW89_MAC_CHINFO_SIZE 24 +#define RTW89_MAC_CHINFO_SIZE 28 #define RTW89_SCAN_LIST_GUARD 4 #define RTW89_SCAN_LIST_LIMIT \ ((RTW89_H2C_MAX_SIZE / RTW89_MAC_CHINFO_SIZE) - RTW89_SCAN_LIST_GUARD) @@ -277,6 +288,7 @@ struct rtw89_pktofld_info { u8 ssid_len; u8 bssid[ETH_ALEN]; u16 channel_6ghz; + bool cancel; }; static inline void RTW89_SET_FWCMD_RA_IS_DIS(void *cmd, u32 val) @@ -516,50 +528,58 @@ static inline void RTW89_SET_EDCA_PARAM(void *cmd, u32 val) #define FWDL_SECURITY_SECTION_TYPE 9 #define FWDL_SECURITY_SIGLEN 512 -#define GET_FWSECTION_HDR_DL_ADDR(fwhdr) \ - le32_get_bits(*((const __le32 *)(fwhdr)), GENMASK(31, 0)) -#define GET_FWSECTION_HDR_SECTIONTYPE(fwhdr) \ - le32_get_bits(*((const __le32 *)(fwhdr) + 1), GENMASK(27, 24)) -#define GET_FWSECTION_HDR_SEC_SIZE(fwhdr) \ - le32_get_bits(*((const __le32 *)(fwhdr) + 1), GENMASK(23, 0)) -#define GET_FWSECTION_HDR_CHECKSUM(fwhdr) \ - le32_get_bits(*((const __le32 *)(fwhdr) + 1), BIT(28)) -#define GET_FWSECTION_HDR_REDL(fwhdr) \ - le32_get_bits(*((const __le32 *)(fwhdr) + 1), BIT(29)) -#define GET_FWSECTION_HDR_MSSC(fwhdr) \ - le32_get_bits(*((const __le32 *)(fwhdr) + 2), GENMASK(31, 0)) - -#define GET_FW_HDR_MAJOR_VERSION(fwhdr) \ - le32_get_bits(*((const __le32 *)(fwhdr) + 1), GENMASK(7, 0)) -#define GET_FW_HDR_MINOR_VERSION(fwhdr) \ - le32_get_bits(*((const __le32 *)(fwhdr) + 1), GENMASK(15, 8)) -#define GET_FW_HDR_SUBVERSION(fwhdr) \ - le32_get_bits(*((const __le32 *)(fwhdr) + 1), GENMASK(23, 16)) -#define GET_FW_HDR_SUBINDEX(fwhdr) \ - le32_get_bits(*((const __le32 *)(fwhdr) + 1), GENMASK(31, 24)) -#define GET_FW_HDR_LEN(fwhdr) \ - le32_get_bits(*((const __le32 *)(fwhdr) + 3), GENMASK(23, 16)) -#define GET_FW_HDR_MONTH(fwhdr) \ - le32_get_bits(*((const __le32 *)(fwhdr) + 4), GENMASK(7, 0)) -#define GET_FW_HDR_DATE(fwhdr) \ - le32_get_bits(*((const __le32 *)(fwhdr) + 4), GENMASK(15, 8)) -#define GET_FW_HDR_HOUR(fwhdr) \ - le32_get_bits(*((const __le32 *)(fwhdr) + 4), GENMASK(23, 16)) -#define GET_FW_HDR_MIN(fwhdr) \ - le32_get_bits(*((const __le32 *)(fwhdr) + 4), GENMASK(31, 24)) -#define GET_FW_HDR_YEAR(fwhdr) \ - le32_get_bits(*((const __le32 *)(fwhdr) + 5), GENMASK(31, 0)) -#define GET_FW_HDR_SEC_NUM(fwhdr) \ - le32_get_bits(*((const __le32 *)(fwhdr) + 6), GENMASK(15, 8)) -#define GET_FW_HDR_DYN_HDR(fwhdr) \ - le32_get_bits(*((const __le32 *)(fwhdr) + 7), BIT(16)) -#define GET_FW_HDR_CMD_VERSERION(fwhdr) \ - le32_get_bits(*((const __le32 *)(fwhdr) + 7), GENMASK(31, 24)) - -#define GET_FW_DYNHDR_LEN(fwdynhdr) \ - le32_get_bits(*((const __le32 *)(fwdynhdr)), GENMASK(31, 0)) -#define GET_FW_DYNHDR_COUNT(fwdynhdr) \ - le32_get_bits(*((const __le32 *)(fwdynhdr) + 1), GENMASK(31, 0)) +struct rtw89_fw_dynhdr_sec { + __le32 w0; + u8 content[]; +} __packed; + +struct rtw89_fw_dynhdr_hdr { + __le32 hdr_len; + __le32 setcion_count; + /* struct rtw89_fw_dynhdr_sec (nested flexible structures) */ +} __packed; + +struct rtw89_fw_hdr_section { + __le32 w0; + __le32 w1; + __le32 w2; + __le32 w3; +} __packed; + +#define FWSECTION_HDR_W0_DL_ADDR GENMASK(31, 0) +#define FWSECTION_HDR_W1_METADATA GENMASK(31, 24) +#define FWSECTION_HDR_W1_SECTIONTYPE GENMASK(27, 24) +#define FWSECTION_HDR_W1_SEC_SIZE GENMASK(23, 0) +#define FWSECTION_HDR_W1_CHECKSUM BIT(28) +#define FWSECTION_HDR_W1_REDL BIT(29) +#define FWSECTION_HDR_W2_MSSC GENMASK(31, 0) + +struct rtw89_fw_hdr { + __le32 w0; + __le32 w1; + __le32 w2; + __le32 w3; + __le32 w4; + __le32 w5; + __le32 w6; + __le32 w7; + struct rtw89_fw_hdr_section sections[]; + /* struct rtw89_fw_dynhdr_hdr (optional) */ +} __packed; + +#define FW_HDR_W1_MAJOR_VERSION GENMASK(7, 0) +#define FW_HDR_W1_MINOR_VERSION GENMASK(15, 8) +#define FW_HDR_W1_SUBVERSION GENMASK(23, 16) +#define FW_HDR_W1_SUBINDEX GENMASK(31, 24) +#define FW_HDR_W3_LEN GENMASK(23, 16) +#define FW_HDR_W4_MONTH GENMASK(7, 0) +#define FW_HDR_W4_DATE GENMASK(15, 8) +#define FW_HDR_W4_HOUR GENMASK(23, 16) +#define FW_HDR_W4_MIN GENMASK(31, 24) +#define FW_HDR_W5_YEAR GENMASK(31, 0) +#define FW_HDR_W6_SEC_NUM GENMASK(15, 8) +#define FW_HDR_W7_DYN_HDR BIT(16) +#define FW_HDR_W7_CMD_VERSERION GENMASK(31, 24) static inline void SET_FW_HDR_PART_SIZE(void *fwhdr, u32 val) { @@ -3215,16 +3235,17 @@ static inline struct rtw89_fw_c2h_attr *RTW89_SKB_C2H_CB(struct sk_buff *skb) #define RTW89_GET_C2H_LOG_SRT_PRT(c2h) (char *)((__le32 *)(c2h) + 2) #define RTW89_GET_C2H_LOG_LEN(len) ((len) - RTW89_C2H_HEADER_LEN) -#define RTW89_GET_MAC_C2H_DONE_ACK_CAT(c2h) \ - le32_get_bits(*((const __le32 *)(c2h) + 2), GENMASK(1, 0)) -#define RTW89_GET_MAC_C2H_DONE_ACK_CLASS(c2h) \ - le32_get_bits(*((const __le32 *)(c2h) + 2), GENMASK(7, 2)) -#define RTW89_GET_MAC_C2H_DONE_ACK_FUNC(c2h) \ - le32_get_bits(*((const __le32 *)(c2h) + 2), GENMASK(15, 8)) -#define RTW89_GET_MAC_C2H_DONE_ACK_H2C_RETURN(c2h) \ - le32_get_bits(*((const __le32 *)(c2h) + 2), GENMASK(23, 16)) -#define RTW89_GET_MAC_C2H_DONE_ACK_H2C_SEQ(c2h) \ - le32_get_bits(*((const __le32 *)(c2h) + 2), GENMASK(31, 24)) +struct rtw89_c2h_done_ack { + __le32 w0; + __le32 w1; + __le32 w2; +} __packed; + +#define RTW89_C2H_DONE_ACK_W2_CAT GENMASK(1, 0) +#define RTW89_C2H_DONE_ACK_W2_CLASS GENMASK(7, 2) +#define RTW89_C2H_DONE_ACK_W2_FUNC GENMASK(15, 8) +#define RTW89_C2H_DONE_ACK_W2_H2C_RETURN GENMASK(23, 16) +#define RTW89_C2H_DONE_ACK_W2_H2C_SEQ GENMASK(31, 24) #define RTW89_GET_MAC_C2H_REV_ACK_CAT(c2h) \ le32_get_bits(*((const __le32 *)(c2h) + 2), GENMASK(1, 0)) @@ -3339,6 +3360,16 @@ static_assert(sizeof(struct rtw89_mac_mcc_tsf_rpt) <= RTW89_COMPLETION_BUF_SIZE) #define RTW89_GET_MAC_C2H_MCC_STATUS_RPT_TSF_HIGH(c2h) \ le32_get_bits(*((const __le32 *)(c2h) + 4), GENMASK(31, 0)) +struct rtw89_c2h_pkt_ofld_rsp { + __le32 w0; + __le32 w1; + __le32 w2; +} __packed; + +#define RTW89_C2H_PKT_OFLD_RSP_W2_PTK_ID GENMASK(7, 0) +#define RTW89_C2H_PKT_OFLD_RSP_W2_PTK_OP GENMASK(10, 8) +#define RTW89_C2H_PKT_OFLD_RSP_W2_PTK_LEN GENMASK(31, 16) + struct rtw89_h2c_bcnfltr { __le32 w0; } __packed; @@ -3369,9 +3400,6 @@ struct rtw89_h2c_ofld { #define RTW89_H2C_OFLD_W0_TX_TP GENMASK(17, 8) #define RTW89_H2C_OFLD_W0_RX_TP GENMASK(27, 18) -#define RTW89_FW_HDR_SIZE 32 -#define RTW89_FW_SECTION_HDR_SIZE 16 - #define RTW89_MFW_SIG 0xFF struct rtw89_mfw_info { @@ -3405,7 +3433,7 @@ struct fwcmd_hdr { union rtw89_compat_fw_hdr { struct rtw89_mfw_hdr mfw_hdr; - u8 fw_hdr[RTW89_FW_HDR_SIZE]; + struct rtw89_fw_hdr fw_hdr; }; static inline u32 rtw89_compat_fw_hdr_ver_code(const void *fw_buf) @@ -3497,17 +3525,28 @@ struct rtw89_fw_h2c_rf_reg_info { /* CLASS 9 - FW offload */ #define H2C_CL_MAC_FW_OFLD 0x9 -#define H2C_FUNC_PACKET_OFLD 0x1 -#define H2C_FUNC_MAC_MACID_PAUSE 0x8 -#define H2C_FUNC_USR_EDCA 0xF -#define H2C_FUNC_TSF32_TOGL 0x10 -#define H2C_FUNC_OFLD_CFG 0x14 -#define H2C_FUNC_ADD_SCANOFLD_CH 0x16 -#define H2C_FUNC_SCANOFLD 0x17 -#define H2C_FUNC_PKT_DROP 0x1b -#define H2C_FUNC_CFG_BCNFLTR 0x1e -#define H2C_FUNC_OFLD_RSSI 0x1f -#define H2C_FUNC_OFLD_TP 0x20 +enum rtw89_fw_ofld_h2c_func { + H2C_FUNC_PACKET_OFLD = 0x1, + H2C_FUNC_MAC_MACID_PAUSE = 0x8, + H2C_FUNC_USR_EDCA = 0xF, + H2C_FUNC_TSF32_TOGL = 0x10, + H2C_FUNC_OFLD_CFG = 0x14, + H2C_FUNC_ADD_SCANOFLD_CH = 0x16, + H2C_FUNC_SCANOFLD = 0x17, + H2C_FUNC_PKT_DROP = 0x1b, + H2C_FUNC_CFG_BCNFLTR = 0x1e, + H2C_FUNC_OFLD_RSSI = 0x1f, + H2C_FUNC_OFLD_TP = 0x20, + + NUM_OF_RTW89_FW_OFLD_H2C_FUNC, +}; + +#define RTW89_FW_OFLD_WAIT_COND(tag, func) \ + ((tag) * NUM_OF_RTW89_FW_OFLD_H2C_FUNC + (func)) + +#define RTW89_FW_OFLD_WAIT_COND_PKT_OFLD(pkt_id, pkt_op) \ + RTW89_FW_OFLD_WAIT_COND(RTW89_PKT_OFLD_WAIT_TAG(pkt_id, pkt_op), \ + H2C_FUNC_PACKET_OFLD) /* CLASS 10 - Security CAM */ #define H2C_CL_MAC_SEC_CAM 0xa @@ -3648,7 +3687,7 @@ void rtw89_fw_release_general_pkt_list_vif(struct rtw89_dev *rtwdev, void rtw89_fw_release_general_pkt_list(struct rtw89_dev *rtwdev, bool notify_fw); int rtw89_fw_h2c_ba_cam(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta, bool valid, struct ieee80211_ampdu_params *params); -void rtw89_fw_h2c_init_ba_cam_v1(struct rtw89_dev *rtwdev); +void rtw89_fw_h2c_init_dynamic_ba_cam_v0_ext(struct rtw89_dev *rtwdev); int rtw89_fw_h2c_lps_parm(struct rtw89_dev *rtwdev, struct rtw89_lps_parm *lps_param); @@ -3711,8 +3750,8 @@ static inline void rtw89_fw_h2c_init_ba_cam(struct rtw89_dev *rtwdev) { const struct rtw89_chip_info *chip = rtwdev->chip; - if (chip->bacam_v1) - rtw89_fw_h2c_init_ba_cam_v1(rtwdev); + if (chip->bacam_ver == RTW89_BACAM_V0_EXT) + rtw89_fw_h2c_init_dynamic_ba_cam_v0_ext(rtwdev); } #endif diff --git a/drivers/net/wireless/realtek/rtw89/mac.c b/drivers/net/wireless/realtek/rtw89/mac.c index 512de491a064b1b741ad34802b423e7a2b59a968..b114babec698c00f30c5b3310186c4fa376ca10b 100644 --- a/drivers/net/wireless/realtek/rtw89/mac.c +++ b/drivers/net/wireless/realtek/rtw89/mac.c @@ -644,6 +644,39 @@ static void rtw89_mac_dump_err_status(struct rtw89_dev *rtwdev, rtw89_info(rtwdev, "<---\n"); } +static bool rtw89_mac_suppress_log(struct rtw89_dev *rtwdev, u32 err) +{ + struct rtw89_ser *ser = &rtwdev->ser; + u32 dmac_err, imr, isr; + int ret; + + if (rtwdev->chip->chip_id == RTL8852C) { + ret = rtw89_mac_check_mac_en(rtwdev, 0, RTW89_DMAC_SEL); + if (ret) + return true; + + if (err == MAC_AX_ERR_L1_ERR_DMAC) { + dmac_err = rtw89_read32(rtwdev, R_AX_DMAC_ERR_ISR); + imr = rtw89_read32(rtwdev, R_AX_TXPKTCTL_B0_ERRFLAG_IMR); + isr = rtw89_read32(rtwdev, R_AX_TXPKTCTL_B0_ERRFLAG_ISR); + + if ((dmac_err & B_AX_TXPKTCTRL_ERR_FLAG) && + ((isr & imr) & B_AX_B0_ISR_ERR_CMDPSR_FRZTO)) { + set_bit(RTW89_SER_SUPPRESS_LOG, ser->flags); + return true; + } + } else if (err == MAC_AX_ERR_L1_RESET_DISABLE_DMAC_DONE) { + if (test_bit(RTW89_SER_SUPPRESS_LOG, ser->flags)) + return true; + } else if (err == MAC_AX_ERR_L1_RESET_RECOVERY_DONE) { + if (test_and_clear_bit(RTW89_SER_SUPPRESS_LOG, ser->flags)) + return true; + } + } + + return false; +} + u32 rtw89_mac_get_err_status(struct rtw89_dev *rtwdev) { u32 err, err_scnr; @@ -667,6 +700,9 @@ u32 rtw89_mac_get_err_status(struct rtw89_dev *rtwdev) else if (err_scnr == RTW89_RXI300_ERROR) err = MAC_AX_ERR_RXI300; + if (rtw89_mac_suppress_log(rtwdev, err)) + return err; + rtw89_fw_st_dbg_dump(rtwdev); rtw89_mac_dump_err_status(rtwdev, err); @@ -676,6 +712,7 @@ EXPORT_SYMBOL(rtw89_mac_get_err_status); int rtw89_mac_set_err_status(struct rtw89_dev *rtwdev, u32 err) { + struct rtw89_ser *ser = &rtwdev->ser; u32 halt; int ret = 0; @@ -692,6 +729,11 @@ int rtw89_mac_set_err_status(struct rtw89_dev *rtwdev, u32 err) } rtw89_write32(rtwdev, R_AX_HALT_H2C, err); + + if (ser->prehandle_l1 && + (err == MAC_AX_ERR_L1_DISABLE_EN || err == MAC_AX_ERR_L1_RCVY_EN)) + return 0; + rtw89_write32(rtwdev, R_AX_HALT_H2C_CTRL, B_AX_HALT_H2C_TRIGGER); return 0; @@ -716,11 +758,8 @@ static int hfc_reset_param(struct rtw89_dev *rtwdev) if (param_ini.pub_cfg) param->pub_cfg = *param_ini.pub_cfg; - if (param_ini.prec_cfg) { + if (param_ini.prec_cfg) param->prec_cfg = *param_ini.prec_cfg; - rtwdev->hal.sw_amsdu_max_size = - param->prec_cfg.wp_ch07_prec * HFC_PAGE_UNIT; - } if (param_ini.ch_cfg) param->ch_cfg = param_ini.ch_cfg; @@ -1479,6 +1518,8 @@ const struct rtw89_mac_size_set rtw89_mac_size = { .ple_qt_52a_wow = {264, 0, 32, 20, 64, 13, 1005, 0, 64, 128, 120,}, /* 8852B PCIE WOW */ .ple_qt_52b_wow = {147, 0, 16, 20, 157, 13, 133, 0, 172, 14, 24, 0,}, + /* 8851B PCIE WOW */ + .ple_qt_51b_wow = {147, 0, 16, 20, 157, 13, 133, 0, 172, 14, 24, 0,}, }; EXPORT_SYMBOL(rtw89_mac_size); @@ -1497,7 +1538,6 @@ static const struct rtw89_dle_mem *get_dle_mem_cfg(struct rtw89_dev *rtwdev, return NULL; } - mac->dle_info.wde_pg_size = cfg->wde_size->pge_size; mac->dle_info.ple_pg_size = cfg->ple_size->pge_size; mac->dle_info.qta_mode = mode; mac->dle_info.c0_rx_qta = cfg->ple_min_qt->cma0_dma; @@ -2602,9 +2642,11 @@ static int rtw89_mac_read_phycap(struct rtw89_dev *rtwdev, int rtw89_mac_setup_phycap(struct rtw89_dev *rtwdev) { + struct rtw89_efuse *efuse = &rtwdev->efuse; struct rtw89_hal *hal = &rtwdev->hal; const struct rtw89_chip_info *chip = rtwdev->chip; struct rtw89_mac_c2h_info c2h_info = {0}; + const struct rtw89_c2hreg_phycap *phycap; u8 tx_nss; u8 rx_nss; u8 tx_ant; @@ -2615,10 +2657,12 @@ int rtw89_mac_setup_phycap(struct rtw89_dev *rtwdev) if (ret) return ret; - tx_nss = RTW89_GET_C2H_PHYCAP_TX_NSS(c2h_info.c2hreg); - rx_nss = RTW89_GET_C2H_PHYCAP_RX_NSS(c2h_info.c2hreg); - tx_ant = RTW89_GET_C2H_PHYCAP_ANT_TX_NUM(c2h_info.c2hreg); - rx_ant = RTW89_GET_C2H_PHYCAP_ANT_RX_NUM(c2h_info.c2hreg); + phycap = &c2h_info.u.phycap; + + tx_nss = u32_get_bits(phycap->w1, RTW89_C2HREG_PHYCAP_W1_TX_NSS); + rx_nss = u32_get_bits(phycap->w0, RTW89_C2HREG_PHYCAP_W0_RX_NSS); + tx_ant = u32_get_bits(phycap->w3, RTW89_C2HREG_PHYCAP_W3_ANT_TX_NUM); + rx_ant = u32_get_bits(phycap->w3, RTW89_C2HREG_PHYCAP_W3_ANT_RX_NUM); hal->tx_nss = tx_nss ? min_t(u8, tx_nss, chip->tx_nss) : chip->tx_nss; hal->rx_nss = rx_nss ? min_t(u8, rx_nss, chip->rx_nss) : chip->rx_nss; @@ -2633,6 +2677,13 @@ int rtw89_mac_setup_phycap(struct rtw89_dev *rtwdev) hal->tx_path_diversity = true; } + if (chip->rf_path_num == 1) { + hal->antenna_tx = RF_A; + hal->antenna_rx = RF_A; + if ((efuse->rfe_type % 3) == 2) + hal->ant_diversity = true; + } + rtw89_debug(rtwdev, RTW89_DBG_FW, "phycap hal/phy/chip: tx_nss=0x%x/0x%x/0x%x rx_nss=0x%x/0x%x/0x%x\n", hal->tx_nss, tx_nss, chip->tx_nss, @@ -2641,6 +2692,7 @@ int rtw89_mac_setup_phycap(struct rtw89_dev *rtwdev) "ant num/bitmap: tx=%d/0x%x rx=%d/0x%x\n", tx_ant, hal->antenna_tx, rx_ant, hal->antenna_rx); rtw89_debug(rtwdev, RTW89_DBG_FW, "TX path diversity=%d\n", hal->tx_path_diversity); + rtw89_debug(rtwdev, RTW89_DBG_FW, "Antenna diversity=%d\n", hal->ant_diversity); return 0; } @@ -2651,14 +2703,14 @@ static int rtw89_hw_sch_tx_en_h2c(struct rtw89_dev *rtwdev, u8 band, u32 ret; struct rtw89_mac_c2h_info c2h_info = {0}; struct rtw89_mac_h2c_info h2c_info = {0}; - struct rtw89_h2creg_sch_tx_en *h2creg = - (struct rtw89_h2creg_sch_tx_en *)h2c_info.h2creg; + struct rtw89_h2creg_sch_tx_en *sch_tx_en = &h2c_info.u.sch_tx_en; h2c_info.id = RTW89_FWCMD_H2CREG_FUNC_SCH_TX_EN; - h2c_info.content_len = sizeof(*h2creg) - RTW89_H2CREG_HDR_LEN; - h2creg->tx_en = tx_en_u16; - h2creg->mask = mask_u16; - h2creg->band = band; + h2c_info.content_len = sizeof(*sch_tx_en) - RTW89_H2CREG_HDR_LEN; + + u32p_replace_bits(&sch_tx_en->w0, tx_en_u16, RTW89_H2CREG_SCH_TX_EN_W0_EN); + u32p_replace_bits(&sch_tx_en->w1, mask_u16, RTW89_H2CREG_SCH_TX_EN_W1_MASK); + u32p_replace_bits(&sch_tx_en->w1, band, RTW89_H2CREG_SCH_TX_EN_W1_BAND); ret = rtw89_fw_msg_reg(rtwdev, &h2c_info, &c2h_info); if (ret) @@ -4331,6 +4383,8 @@ rtw89_mac_c2h_bcn_fltr_rpt(struct rtw89_dev *rtwdev, struct sk_buff *c2h, static void rtw89_mac_c2h_rec_ack(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len) { + /* N.B. This will run in interrupt context. */ + rtw89_debug(rtwdev, RTW89_DBG_FW, "C2H rev ack recv, cat: %d, class: %d, func: %d, seq : %d\n", RTW89_GET_MAC_C2H_REV_ACK_CAT(c2h->data), @@ -4340,15 +4394,44 @@ rtw89_mac_c2h_rec_ack(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len) } static void -rtw89_mac_c2h_done_ack(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len) -{ +rtw89_mac_c2h_done_ack(struct rtw89_dev *rtwdev, struct sk_buff *skb_c2h, u32 len) +{ + /* N.B. This will run in interrupt context. */ + struct rtw89_wait_info *fw_ofld_wait = &rtwdev->mac.fw_ofld_wait; + const struct rtw89_c2h_done_ack *c2h = + (const struct rtw89_c2h_done_ack *)skb_c2h->data; + u8 h2c_cat = le32_get_bits(c2h->w2, RTW89_C2H_DONE_ACK_W2_CAT); + u8 h2c_class = le32_get_bits(c2h->w2, RTW89_C2H_DONE_ACK_W2_CLASS); + u8 h2c_func = le32_get_bits(c2h->w2, RTW89_C2H_DONE_ACK_W2_FUNC); + u8 h2c_return = le32_get_bits(c2h->w2, RTW89_C2H_DONE_ACK_W2_H2C_RETURN); + u8 h2c_seq = le32_get_bits(c2h->w2, RTW89_C2H_DONE_ACK_W2_H2C_SEQ); + struct rtw89_completion_data data = {}; + unsigned int cond; + rtw89_debug(rtwdev, RTW89_DBG_FW, "C2H done ack recv, cat: %d, class: %d, func: %d, ret: %d, seq : %d\n", - RTW89_GET_MAC_C2H_DONE_ACK_CAT(c2h->data), - RTW89_GET_MAC_C2H_DONE_ACK_CLASS(c2h->data), - RTW89_GET_MAC_C2H_DONE_ACK_FUNC(c2h->data), - RTW89_GET_MAC_C2H_DONE_ACK_H2C_RETURN(c2h->data), - RTW89_GET_MAC_C2H_DONE_ACK_H2C_SEQ(c2h->data)); + h2c_cat, h2c_class, h2c_func, h2c_return, h2c_seq); + + if (h2c_cat != H2C_CAT_MAC) + return; + + switch (h2c_class) { + default: + return; + case H2C_CL_MAC_FW_OFLD: + switch (h2c_func) { + default: + return; + case H2C_FUNC_ADD_SCANOFLD_CH: + case H2C_FUNC_SCANOFLD: + cond = RTW89_FW_OFLD_WAIT_COND(0, h2c_func); + break; + } + + data.err = !!h2c_return; + rtw89_complete_cond(fw_ofld_wait, cond, &data); + return; + } } static void @@ -4364,9 +4447,25 @@ rtw89_mac_c2h_bcn_cnt(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len) } static void -rtw89_mac_c2h_pkt_ofld_rsp(struct rtw89_dev *rtwdev, struct sk_buff *c2h, +rtw89_mac_c2h_pkt_ofld_rsp(struct rtw89_dev *rtwdev, struct sk_buff *skb_c2h, u32 len) { + struct rtw89_wait_info *wait = &rtwdev->mac.fw_ofld_wait; + const struct rtw89_c2h_pkt_ofld_rsp *c2h = + (const struct rtw89_c2h_pkt_ofld_rsp *)skb_c2h->data; + u16 pkt_len = le32_get_bits(c2h->w2, RTW89_C2H_PKT_OFLD_RSP_W2_PTK_LEN); + u8 pkt_id = le32_get_bits(c2h->w2, RTW89_C2H_PKT_OFLD_RSP_W2_PTK_ID); + u8 pkt_op = le32_get_bits(c2h->w2, RTW89_C2H_PKT_OFLD_RSP_W2_PTK_OP); + struct rtw89_completion_data data = {}; + unsigned int cond; + + rtw89_debug(rtwdev, RTW89_DBG_FW, "pkt ofld rsp: id %d op %d len %d\n", + pkt_id, pkt_op, pkt_len); + + data.err = !pkt_len; + cond = RTW89_FW_OFLD_WAIT_COND_PKT_OFLD(pkt_id, pkt_op); + + rtw89_complete_cond(wait, cond, &data); } static void @@ -4574,6 +4673,21 @@ bool rtw89_mac_c2h_chk_atomic(struct rtw89_dev *rtwdev, u8 class, u8 func) switch (class) { default: return false; + case RTW89_MAC_C2H_CLASS_INFO: + switch (func) { + default: + return false; + case RTW89_MAC_C2H_FUNC_REC_ACK: + case RTW89_MAC_C2H_FUNC_DONE_ACK: + return true; + } + case RTW89_MAC_C2H_CLASS_OFLD: + switch (func) { + default: + return false; + case RTW89_MAC_C2H_FUNC_PKT_OFLD_RSP: + return true; + } case RTW89_MAC_C2H_CLASS_MCC: return true; } diff --git a/drivers/net/wireless/realtek/rtw89/mac.h b/drivers/net/wireless/realtek/rtw89/mac.h index 6ba633ccdd0377ff571a5c0bbf2017c8bb11807e..0e1570451c2c5f098054583f07863784e8f7973a 100644 --- a/drivers/net/wireless/realtek/rtw89/mac.h +++ b/drivers/net/wireless/realtek/rtw89/mac.h @@ -642,6 +642,7 @@ enum mac_ax_err_info { MAC_AX_ERR_L0_PROMOTE_TO_L1 = 0x0010, /* L1 */ + MAC_AX_ERR_L1_PREERR_DMAC = 0x999, MAC_AX_ERR_L1_ERR_DMAC = 0x1000, MAC_AX_ERR_L1_RESET_DISABLE_DMAC_DONE = 0x1001, MAC_AX_ERR_L1_RESET_RECOVERY_DONE = 0x1002, @@ -780,6 +781,7 @@ enum mac_ax_err_info { MAC_AX_ERR_L1_RCVY_EN = 0x0002, MAC_AX_ERR_L1_RCVY_STOP_REQ = 0x0003, MAC_AX_ERR_L1_RCVY_START_REQ = 0x0004, + MAC_AX_ERR_L1_RESET_START_DMAC = 0x000A, MAC_AX_ERR_L0_CFG_NOTIFY = 0x0010, MAC_AX_ERR_L0_CFG_DIS_NOTIFY = 0x0011, MAC_AX_ERR_L0_CFG_HANDSHAKE = 0x0012, @@ -819,6 +821,7 @@ struct rtw89_mac_size_set { const struct rtw89_ple_quota ple_qt58; const struct rtw89_ple_quota ple_qt_52a_wow; const struct rtw89_ple_quota ple_qt_52b_wow; + const struct rtw89_ple_quota ple_qt_51b_wow; }; extern const struct rtw89_mac_size_set rtw89_mac_size; @@ -1115,6 +1118,8 @@ enum rtw89_mac_xtal_si_offset { XTAL_SI_PWR_CUT = 0x10, #define XTAL_SI_SMALL_PWR_CUT BIT(0) #define XTAL_SI_BIG_PWR_CUT BIT(1) + XTAL_SI_XTAL_DRV = 0x15, +#define XTAL_SI_DRV_LATCH BIT(4) XTAL_SI_XTAL_XMD_2 = 0x24, #define XTAL_SI_LDO_LPS GENMASK(6, 4) XTAL_SI_XTAL_XMD_4 = 0x26, diff --git a/drivers/net/wireless/realtek/rtw89/mac80211.c b/drivers/net/wireless/realtek/rtw89/mac80211.c index c42e310690351a37fcd7053a30362918155b6cfe..a66503eb35b807abbe30a9636a250916d325670c 100644 --- a/drivers/net/wireless/realtek/rtw89/mac80211.c +++ b/drivers/net/wireless/realtek/rtw89/mac80211.c @@ -146,6 +146,7 @@ static int rtw89_ops_add_interface(struct ieee80211_hw *hw, rtwvif->phy_idx = RTW89_PHY_0; rtwvif->sub_entity_idx = RTW89_SUB_ENTITY_0; rtwvif->hit_rule = 0; + rtwvif->reg_6ghz_power = RTW89_REG_6GHZ_POWER_DFLT; ether_addr_copy(rtwvif->mac_addr, vif->addr); INIT_LIST_HEAD(&rtwvif->general_pkt_list); @@ -457,8 +458,16 @@ static int rtw89_ops_start_ap(struct ieee80211_hw *hw, { struct rtw89_dev *rtwdev = hw->priv; struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; + const struct rtw89_chan *chan; mutex_lock(&rtwdev->mutex); + + chan = rtw89_chan_get(rtwdev, rtwvif->sub_entity_idx); + if (chan->band_type == RTW89_BAND_6G) { + mutex_unlock(&rtwdev->mutex); + return -EOPNOTSUPP; + } + ether_addr_copy(rtwvif->bssid, vif->bss_conf.bssid); rtw89_cam_bssid_changed(rtwdev, rtwvif); rtw89_mac_port_update(rtwdev, rtwvif); @@ -759,13 +768,18 @@ int rtw89_ops_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant) struct rtw89_dev *rtwdev = hw->priv; struct rtw89_hal *hal = &rtwdev->hal; - if (rx_ant != hw->wiphy->available_antennas_rx && rx_ant != hal->antenna_rx) + if (hal->ant_diversity) { + if (tx_ant != rx_ant || hweight32(tx_ant) != 1) + return -EINVAL; + } else if (rx_ant != hw->wiphy->available_antennas_rx && rx_ant != hal->antenna_rx) { return -EINVAL; + } mutex_lock(&rtwdev->mutex); hal->antenna_tx = tx_ant; hal->antenna_rx = rx_ant; hal->tx_path_diversity = false; + hal->ant_diversity_fixed = true; mutex_unlock(&rtwdev->mutex); return 0; diff --git a/drivers/net/wireless/realtek/rtw89/pci.c b/drivers/net/wireless/realtek/rtw89/pci.c index 70b4754667c9883bbd642268d75791a2592540c2..9402f1a0caea8aa35c8e85804523adb37c37e75c 100644 --- a/drivers/net/wireless/realtek/rtw89/pci.c +++ b/drivers/net/wireless/realtek/rtw89/pci.c @@ -265,7 +265,7 @@ static u32 rtw89_pci_rxbd_deliver_skbs(struct rtw89_dev *rtwdev, goto err_sync_device; } - rtw89_core_query_rxdesc(rtwdev, desc_info, skb->data, rxinfo_size); + rtw89_chip_query_rxdesc(rtwdev, desc_info, skb->data, rxinfo_size); new = rtw89_alloc_skb_for_rx(rtwdev, desc_info->pkt_size); if (!new) @@ -274,9 +274,7 @@ static u32 rtw89_pci_rxbd_deliver_skbs(struct rtw89_dev *rtwdev, rx_ring->diliver_skb = new; /* first segment has RX desc */ - offset = desc_info->offset; - offset += desc_info->long_rxdesc ? sizeof(struct rtw89_rxdesc_long) : - sizeof(struct rtw89_rxdesc_short); + offset = desc_info->offset + desc_info->rxd_len; } else { offset = sizeof(struct rtw89_pci_rxbd_info); if (!new) { @@ -546,12 +544,10 @@ static u32 rtw89_pci_release_tx_skbs(struct rtw89_dev *rtwdev, return cnt; } - rtw89_core_query_rxdesc(rtwdev, &desc_info, skb->data, rxinfo_size); + rtw89_chip_query_rxdesc(rtwdev, &desc_info, skb->data, rxinfo_size); /* first segment has RX desc */ - offset = desc_info.offset; - offset += desc_info.long_rxdesc ? sizeof(struct rtw89_rxdesc_long) : - sizeof(struct rtw89_rxdesc_short); + offset = desc_info.offset + desc_info.rxd_len; for (; offset + rpp_size <= rx_info->len; offset += rpp_size) { rpp = (struct rtw89_pci_rpp_fmt *)(skb->data + offset); rtw89_pci_release_rpp(rtwdev, rpp); @@ -1003,10 +999,10 @@ static u32 __rtw89_pci_check_and_reclaim_tx_resource(struct rtw89_dev *rtwdev, min_cnt = min(bd_cnt, wd_cnt); if (min_cnt == 0) { /* This message can be frequently shown in low power mode or - * high traffic with 8852B, and we have recognized it as normal + * high traffic with small FIFO chips, and we have recognized it as normal * behavior, so print with mask RTW89_DBG_TXRX in these situations. */ - if (rtwpci->low_power || chip->chip_id == RTL8852B) + if (rtwpci->low_power || chip->small_fifo_size) debug_mask = RTW89_DBG_TXRX; else debug_mask = RTW89_DBG_UNEXP; @@ -3216,11 +3212,16 @@ static void rtw89_pci_clear_resource(struct rtw89_dev *rtwdev, void rtw89_pci_config_intr_mask(struct rtw89_dev *rtwdev) { struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv; + const struct rtw89_chip_info *chip = rtwdev->chip; + u32 hs0isr_ind_int_en = B_AX_HS0ISR_IND_INT_EN; + + if (chip->chip_id == RTL8851B) + hs0isr_ind_int_en = B_AX_HS0ISR_IND_INT_EN_WKARND; rtwpci->halt_c2h_intrs = B_AX_HALT_C2H_INT_EN | 0; if (rtwpci->under_recovery) { - rtwpci->intrs[0] = B_AX_HS0ISR_IND_INT_EN; + rtwpci->intrs[0] = hs0isr_ind_int_en; rtwpci->intrs[1] = 0; } else { rtwpci->intrs[0] = B_AX_TXDMA_STUCK_INT_EN | @@ -3230,7 +3231,7 @@ void rtw89_pci_config_intr_mask(struct rtw89_dev *rtwdev) B_AX_RXDMA_STUCK_INT_EN | B_AX_RDU_INT_EN | B_AX_RPQBD_FULL_INT_EN | - B_AX_HS0ISR_IND_INT_EN; + hs0isr_ind_int_en; rtwpci->intrs[1] = B_AX_HC10ISR_IND_INT_EN; } diff --git a/drivers/net/wireless/realtek/rtw89/pci.h b/drivers/net/wireless/realtek/rtw89/pci.h index 0e4bd210b100fdd87b3a3197612647226976f6c3..2f3d1ad3b0f7d0b7b75657bc215110c434adabe0 100644 --- a/drivers/net/wireless/realtek/rtw89/pci.h +++ b/drivers/net/wireless/realtek/rtw89/pci.h @@ -150,6 +150,7 @@ #define B_AX_HD1ISR_IND_INT_EN BIT(26) #define B_AX_HD0ISR_IND_INT_EN BIT(25) #define B_AX_HS0ISR_IND_INT_EN BIT(24) +#define B_AX_HS0ISR_IND_INT_EN_WKARND BIT(23) #define B_AX_RETRAIN_INT_EN BIT(21) #define B_AX_RPQBD_FULL_INT_EN BIT(20) #define B_AX_RDU_INT_EN BIT(19) diff --git a/drivers/net/wireless/realtek/rtw89/phy.c b/drivers/net/wireless/realtek/rtw89/phy.c index c7e906123416998232f55b53002fbd86bb63fab5..fb15c852fdd4887714ce5c0bb9c97ef2842ff85c 100644 --- a/drivers/net/wireless/realtek/rtw89/phy.c +++ b/drivers/net/wireless/realtek/rtw89/phy.c @@ -10,6 +10,7 @@ #include "ps.h" #include "reg.h" #include "sar.h" +#include "txrx.h" #include "util.h" static u16 get_max_amsdu_len(struct rtw89_dev *rtwdev, @@ -1400,7 +1401,8 @@ static void rtw89_phy_init_rf_nctl(struct rtw89_dev *rtwdev) rtw89_phy_write32_set(rtwdev, R_IOQ_IQK_DPK, 0x3); rtw89_phy_write32_set(rtwdev, R_GNT_BT_WGT_EN, 0x1); rtw89_phy_write32_set(rtwdev, R_P0_PATH_RST, 0x8000000); - rtw89_phy_write32_set(rtwdev, R_P1_PATH_RST, 0x8000000); + if (chip->chip_id != RTL8851B) + rtw89_phy_write32_set(rtwdev, R_P1_PATH_RST, 0x8000000); if (chip->chip_id == RTL8852B) rtw89_phy_write32_set(rtwdev, R_IOQ_IQK_DPK, 0x2); @@ -1414,6 +1416,9 @@ static void rtw89_phy_init_rf_nctl(struct rtw89_dev *rtwdev) nctl_table = chip->nctl_table; rtw89_phy_init_reg(rtwdev, nctl_table, rtw89_phy_config_bb_reg, NULL); + + if (chip->nctl_post_table) + rtw89_rfk_parser(rtwdev, chip->nctl_post_table); } static u32 rtw89_phy0_phy1_offset(struct rtw89_dev *rtwdev, u32 addr) @@ -1489,19 +1494,19 @@ void rtw89_phy_write_reg3_tbl(struct rtw89_dev *rtwdev, } EXPORT_SYMBOL(rtw89_phy_write_reg3_tbl); -static const u8 rtw89_rs_idx_max[] = { - [RTW89_RS_CCK] = RTW89_RATE_CCK_MAX, - [RTW89_RS_OFDM] = RTW89_RATE_OFDM_MAX, - [RTW89_RS_MCS] = RTW89_RATE_MCS_MAX, - [RTW89_RS_HEDCM] = RTW89_RATE_HEDCM_MAX, - [RTW89_RS_OFFSET] = RTW89_RATE_OFFSET_MAX, +static const u8 rtw89_rs_idx_num[] = { + [RTW89_RS_CCK] = RTW89_RATE_CCK_NUM, + [RTW89_RS_OFDM] = RTW89_RATE_OFDM_NUM, + [RTW89_RS_MCS] = RTW89_RATE_MCS_NUM, + [RTW89_RS_HEDCM] = RTW89_RATE_HEDCM_NUM, + [RTW89_RS_OFFSET] = RTW89_RATE_OFFSET_NUM, }; -static const u8 rtw89_rs_nss_max[] = { +static const u8 rtw89_rs_nss_num[] = { [RTW89_RS_CCK] = 1, [RTW89_RS_OFDM] = 1, - [RTW89_RS_MCS] = RTW89_NSS_MAX, - [RTW89_RS_HEDCM] = RTW89_NSS_HEDCM_MAX, + [RTW89_RS_MCS] = RTW89_NSS_NUM, + [RTW89_RS_HEDCM] = RTW89_NSS_HEDCM_NUM, [RTW89_RS_OFFSET] = 1, }; @@ -1514,9 +1519,9 @@ static const u8 _byr_of_rs[] = { }; #define _byr_seek(rs, raw) ((s8 *)(raw) + _byr_of_rs[rs]) -#define _byr_idx(rs, nss, idx) ((nss) * rtw89_rs_idx_max[rs] + (idx)) +#define _byr_idx(rs, nss, idx) ((nss) * rtw89_rs_idx_num[rs] + (idx)) #define _byr_chk(rs, nss, idx) \ - ((nss) < rtw89_rs_nss_max[rs] && (idx) < rtw89_rs_idx_max[rs]) + ((nss) < rtw89_rs_nss_num[rs] && (idx) < rtw89_rs_idx_num[rs]) void rtw89_phy_load_txpwr_byrate(struct rtw89_dev *rtwdev, const struct rtw89_txpwr_table *tbl) @@ -1621,8 +1626,10 @@ s8 rtw89_phy_read_txpwr_limit(struct rtw89_dev *rtwdev, u8 band, const struct rtw89_txpwr_rule_2ghz *rule_2ghz = &rfe_parms->rule_2ghz; const struct rtw89_txpwr_rule_5ghz *rule_5ghz = &rfe_parms->rule_5ghz; const struct rtw89_txpwr_rule_6ghz *rule_6ghz = &rfe_parms->rule_6ghz; + struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory; u8 ch_idx = rtw89_channel_to_idx(rtwdev, band, ch); u8 regd = rtw89_regd_get(rtwdev, band); + u8 reg6 = regulatory->reg_6ghz_power; s8 lmt = 0, sar; switch (band) { @@ -1641,11 +1648,13 @@ s8 rtw89_phy_read_txpwr_limit(struct rtw89_dev *rtwdev, u8 band, lmt = (*rule_5ghz->lmt)[bw][ntx][rs][bf][RTW89_WW][ch_idx]; break; case RTW89_BAND_6G: - lmt = (*rule_6ghz->lmt)[bw][ntx][rs][bf][regd][ch_idx]; + lmt = (*rule_6ghz->lmt)[bw][ntx][rs][bf][regd][reg6][ch_idx]; if (lmt) break; - lmt = (*rule_6ghz->lmt)[bw][ntx][rs][bf][RTW89_WW][ch_idx]; + lmt = (*rule_6ghz->lmt)[bw][ntx][rs][bf][RTW89_WW] + [RTW89_REG_6GHZ_POWER_DFLT] + [ch_idx]; break; default: rtw89_warn(rtwdev, "unknown band type: %d\n", band); @@ -1872,8 +1881,10 @@ static s8 rtw89_phy_read_txpwr_limit_ru(struct rtw89_dev *rtwdev, u8 band, const struct rtw89_txpwr_rule_2ghz *rule_2ghz = &rfe_parms->rule_2ghz; const struct rtw89_txpwr_rule_5ghz *rule_5ghz = &rfe_parms->rule_5ghz; const struct rtw89_txpwr_rule_6ghz *rule_6ghz = &rfe_parms->rule_6ghz; + struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory; u8 ch_idx = rtw89_channel_to_idx(rtwdev, band, ch); u8 regd = rtw89_regd_get(rtwdev, band); + u8 reg6 = regulatory->reg_6ghz_power; s8 lmt_ru = 0, sar; switch (band) { @@ -1892,11 +1903,13 @@ static s8 rtw89_phy_read_txpwr_limit_ru(struct rtw89_dev *rtwdev, u8 band, lmt_ru = (*rule_5ghz->lmt_ru)[ru][ntx][RTW89_WW][ch_idx]; break; case RTW89_BAND_6G: - lmt_ru = (*rule_6ghz->lmt_ru)[ru][ntx][regd][ch_idx]; + lmt_ru = (*rule_6ghz->lmt_ru)[ru][ntx][regd][reg6][ch_idx]; if (lmt_ru) break; - lmt_ru = (*rule_6ghz->lmt_ru)[ru][ntx][RTW89_WW][ch_idx]; + lmt_ru = (*rule_6ghz->lmt_ru)[ru][ntx][RTW89_WW] + [RTW89_REG_6GHZ_POWER_DFLT] + [ch_idx]; break; default: rtw89_warn(rtwdev, "unknown band type: %d\n", band); @@ -2071,19 +2084,19 @@ void rtw89_phy_set_txpwr_byrate(struct rtw89_dev *rtwdev, rtw89_debug(rtwdev, RTW89_DBG_TXPWR, "[TXPWR] set txpwr byrate with ch=%d\n", ch); - BUILD_BUG_ON(rtw89_rs_idx_max[RTW89_RS_CCK] % 4); - BUILD_BUG_ON(rtw89_rs_idx_max[RTW89_RS_OFDM] % 4); - BUILD_BUG_ON(rtw89_rs_idx_max[RTW89_RS_MCS] % 4); - BUILD_BUG_ON(rtw89_rs_idx_max[RTW89_RS_HEDCM] % 4); + BUILD_BUG_ON(rtw89_rs_idx_num[RTW89_RS_CCK] % 4); + BUILD_BUG_ON(rtw89_rs_idx_num[RTW89_RS_OFDM] % 4); + BUILD_BUG_ON(rtw89_rs_idx_num[RTW89_RS_MCS] % 4); + BUILD_BUG_ON(rtw89_rs_idx_num[RTW89_RS_HEDCM] % 4); addr = R_AX_PWR_BY_RATE; for (cur.nss = 0; cur.nss < max_nss_num; cur.nss++) { for (i = 0; i < ARRAY_SIZE(rs); i++) { - if (cur.nss >= rtw89_rs_nss_max[rs[i]]) + if (cur.nss >= rtw89_rs_nss_num[rs[i]]) continue; cur.rs = rs[i]; - for (cur.idx = 0; cur.idx < rtw89_rs_idx_max[rs[i]]; + for (cur.idx = 0; cur.idx < rtw89_rs_idx_num[rs[i]]; cur.idx++) { v[cur.idx % 4] = rtw89_phy_read_txpwr_byrate(rtwdev, @@ -2116,15 +2129,15 @@ void rtw89_phy_set_txpwr_offset(struct rtw89_dev *rtwdev, .rs = RTW89_RS_OFFSET, }; u8 band = chan->band_type; - s8 v[RTW89_RATE_OFFSET_MAX] = {}; + s8 v[RTW89_RATE_OFFSET_NUM] = {}; u32 val; rtw89_debug(rtwdev, RTW89_DBG_TXPWR, "[TXPWR] set txpwr offset\n"); - for (desc.idx = 0; desc.idx < RTW89_RATE_OFFSET_MAX; desc.idx++) + for (desc.idx = 0; desc.idx < RTW89_RATE_OFFSET_NUM; desc.idx++) v[desc.idx] = rtw89_phy_read_txpwr_byrate(rtwdev, band, &desc); - BUILD_BUG_ON(RTW89_RATE_OFFSET_MAX != 5); + BUILD_BUG_ON(RTW89_RATE_OFFSET_NUM != 5); val = FIELD_PREP(GENMASK(3, 0), v[0]) | FIELD_PREP(GENMASK(7, 4), v[1]) | FIELD_PREP(GENMASK(11, 8), v[2]) | @@ -2338,27 +2351,29 @@ void rtw89_phy_c2h_handle(struct rtw89_dev *rtwdev, struct sk_buff *skb, static u8 rtw89_phy_cfo_get_xcap_reg(struct rtw89_dev *rtwdev, bool sc_xo) { + const struct rtw89_xtal_info *xtal = rtwdev->chip->xtal_info; u32 reg_mask; if (sc_xo) - reg_mask = B_AX_XTAL_SC_XO_MASK; + reg_mask = xtal->sc_xo_mask; else - reg_mask = B_AX_XTAL_SC_XI_MASK; + reg_mask = xtal->sc_xi_mask; - return (u8)rtw89_read32_mask(rtwdev, R_AX_XTAL_ON_CTRL0, reg_mask); + return (u8)rtw89_read32_mask(rtwdev, xtal->xcap_reg, reg_mask); } static void rtw89_phy_cfo_set_xcap_reg(struct rtw89_dev *rtwdev, bool sc_xo, u8 val) { + const struct rtw89_xtal_info *xtal = rtwdev->chip->xtal_info; u32 reg_mask; if (sc_xo) - reg_mask = B_AX_XTAL_SC_XO_MASK; + reg_mask = xtal->sc_xo_mask; else - reg_mask = B_AX_XTAL_SC_XI_MASK; + reg_mask = xtal->sc_xi_mask; - rtw89_write32_mask(rtwdev, R_AX_XTAL_ON_CTRL0, reg_mask, val); + rtw89_write32_mask(rtwdev, xtal->xcap_reg, reg_mask, val); } static void rtw89_phy_cfo_set_crystal_cap(struct rtw89_dev *rtwdev, @@ -2371,7 +2386,7 @@ static void rtw89_phy_cfo_set_crystal_cap(struct rtw89_dev *rtwdev, if (!force && cfo->crystal_cap == crystal_cap) return; crystal_cap = clamp_t(u8, crystal_cap, 0, 127); - if (chip->chip_id == RTL8852A) { + if (chip->chip_id == RTL8852A || chip->chip_id == RTL8851B) { rtw89_phy_cfo_set_xcap_reg(rtwdev, true, crystal_cap); rtw89_phy_cfo_set_xcap_reg(rtwdev, false, crystal_cap); sc_xo_val = rtw89_phy_cfo_get_xcap_reg(rtwdev, true); @@ -2946,6 +2961,126 @@ static void rtw89_phy_ul_tb_info_init(struct rtw89_dev *rtwdev) rtw89_phy_read32_mask(rtwdev, R_BANDEDGE, B_BANDEDGE_EN); } +static +void rtw89_phy_antdiv_sts_instance_reset(struct rtw89_antdiv_stats *antdiv_sts) +{ + ewma_rssi_init(&antdiv_sts->cck_rssi_avg); + ewma_rssi_init(&antdiv_sts->ofdm_rssi_avg); + ewma_rssi_init(&antdiv_sts->non_legacy_rssi_avg); + antdiv_sts->pkt_cnt_cck = 0; + antdiv_sts->pkt_cnt_ofdm = 0; + antdiv_sts->pkt_cnt_non_legacy = 0; + antdiv_sts->evm = 0; +} + +static void rtw89_phy_antdiv_sts_instance_add(struct rtw89_dev *rtwdev, + struct rtw89_rx_phy_ppdu *phy_ppdu, + struct rtw89_antdiv_stats *stats) +{ + if (GET_DATA_RATE_MODE(phy_ppdu->rate) == DATA_RATE_MODE_NON_HT) { + if (phy_ppdu->rate < RTW89_HW_RATE_OFDM6) { + ewma_rssi_add(&stats->cck_rssi_avg, phy_ppdu->rssi_avg); + stats->pkt_cnt_cck++; + } else { + ewma_rssi_add(&stats->ofdm_rssi_avg, phy_ppdu->rssi_avg); + stats->pkt_cnt_ofdm++; + stats->evm += phy_ppdu->ofdm.evm_min; + } + } else { + ewma_rssi_add(&stats->non_legacy_rssi_avg, phy_ppdu->rssi_avg); + stats->pkt_cnt_non_legacy++; + stats->evm += phy_ppdu->ofdm.evm_min; + } +} + +static u8 rtw89_phy_antdiv_sts_instance_get_rssi(struct rtw89_antdiv_stats *stats) +{ + if (stats->pkt_cnt_non_legacy >= stats->pkt_cnt_cck && + stats->pkt_cnt_non_legacy >= stats->pkt_cnt_ofdm) + return ewma_rssi_read(&stats->non_legacy_rssi_avg); + else if (stats->pkt_cnt_ofdm >= stats->pkt_cnt_cck && + stats->pkt_cnt_ofdm >= stats->pkt_cnt_non_legacy) + return ewma_rssi_read(&stats->ofdm_rssi_avg); + else + return ewma_rssi_read(&stats->cck_rssi_avg); +} + +static u8 rtw89_phy_antdiv_sts_instance_get_evm(struct rtw89_antdiv_stats *stats) +{ + return phy_div(stats->evm, stats->pkt_cnt_non_legacy + stats->pkt_cnt_ofdm); +} + +void rtw89_phy_antdiv_parse(struct rtw89_dev *rtwdev, + struct rtw89_rx_phy_ppdu *phy_ppdu) +{ + struct rtw89_antdiv_info *antdiv = &rtwdev->antdiv; + struct rtw89_hal *hal = &rtwdev->hal; + + if (!hal->ant_diversity || hal->ant_diversity_fixed) + return; + + rtw89_phy_antdiv_sts_instance_add(rtwdev, phy_ppdu, &antdiv->target_stats); + + if (!antdiv->get_stats) + return; + + if (hal->antenna_rx == RF_A) + rtw89_phy_antdiv_sts_instance_add(rtwdev, phy_ppdu, &antdiv->main_stats); + else if (hal->antenna_rx == RF_B) + rtw89_phy_antdiv_sts_instance_add(rtwdev, phy_ppdu, &antdiv->aux_stats); +} + +static void rtw89_phy_antdiv_reg_init(struct rtw89_dev *rtwdev) +{ + rtw89_phy_write32_idx(rtwdev, R_P0_TRSW, B_P0_ANT_TRAIN_EN, + 0x0, RTW89_PHY_0); + rtw89_phy_write32_idx(rtwdev, R_P0_TRSW, B_P0_TX_ANT_SEL, + 0x0, RTW89_PHY_0); + + rtw89_phy_write32_idx(rtwdev, R_P0_ANT_SW, B_P0_TRSW_TX_EXTEND, + 0x0, RTW89_PHY_0); + rtw89_phy_write32_idx(rtwdev, R_P0_ANT_SW, B_P0_HW_ANTSW_DIS_BY_GNT_BT, + 0x0, RTW89_PHY_0); + + rtw89_phy_write32_idx(rtwdev, R_P0_TRSW, B_P0_BT_FORCE_ANTIDX_EN, + 0x0, RTW89_PHY_0); + + rtw89_phy_write32_idx(rtwdev, R_RFSW_CTRL_ANT0_BASE, B_RFSW_CTRL_ANT_MAPPING, + 0x0100, RTW89_PHY_0); + + rtw89_phy_write32_idx(rtwdev, R_P0_ANTSEL, B_P0_ANTSEL_BTG_TRX, + 0x1, RTW89_PHY_0); + rtw89_phy_write32_idx(rtwdev, R_P0_ANTSEL, B_P0_ANTSEL_HW_CTRL, + 0x0, RTW89_PHY_0); + rtw89_phy_write32_idx(rtwdev, R_P0_ANTSEL, B_P0_ANTSEL_SW_2G, + 0x0, RTW89_PHY_0); + rtw89_phy_write32_idx(rtwdev, R_P0_ANTSEL, B_P0_ANTSEL_SW_5G, + 0x0, RTW89_PHY_0); +} + +static void rtw89_phy_antdiv_sts_reset(struct rtw89_dev *rtwdev) +{ + struct rtw89_antdiv_info *antdiv = &rtwdev->antdiv; + + rtw89_phy_antdiv_sts_instance_reset(&antdiv->target_stats); + rtw89_phy_antdiv_sts_instance_reset(&antdiv->main_stats); + rtw89_phy_antdiv_sts_instance_reset(&antdiv->aux_stats); +} + +static void rtw89_phy_antdiv_init(struct rtw89_dev *rtwdev) +{ + struct rtw89_antdiv_info *antdiv = &rtwdev->antdiv; + struct rtw89_hal *hal = &rtwdev->hal; + + if (!hal->ant_diversity) + return; + + antdiv->get_stats = false; + antdiv->rssi_pre = 0; + rtw89_phy_antdiv_sts_reset(rtwdev); + rtw89_phy_antdiv_reg_init(rtwdev); +} + static void rtw89_phy_stat_thermal_update(struct rtw89_dev *rtwdev) { struct rtw89_phy_stat *phystat = &rtwdev->phystat; @@ -3053,11 +3188,8 @@ static void rtw89_phy_ccx_top_setting_init(struct rtw89_dev *rtwdev) env->ccx_manual_ctrl = false; env->ccx_ongoing = false; env->ccx_rac_lv = RTW89_RAC_RELEASE; - env->ccx_rpt_stamp = 0; env->ccx_period = 0; env->ccx_unit_idx = RTW89_CCX_32_US; - env->ccx_trigger_time = 0; - env->ccx_edcca_opt_bw_idx = RTW89_CCX_EDCCA_BW20_0; rtw89_phy_set_phy_regs(rtwdev, R_CCX, B_CCX_EN_MSK, 1); rtw89_phy_set_phy_regs(rtwdev, R_CCX, B_CCX_TRIG_OPT_MSK, 1); @@ -3265,7 +3397,6 @@ static void rtw89_phy_ccx_trigger(struct rtw89_dev *rtwdev) rtw89_phy_set_phy_regs(rtwdev, R_IFS_COUNTER, B_IFS_COUNTER_CLR_MSK, 1); rtw89_phy_set_phy_regs(rtwdev, R_CCX, B_MEASUREMENT_TRIG_MSK, 1); - env->ccx_rpt_stamp++; env->ccx_ongoing = true; } @@ -4114,6 +4245,144 @@ void rtw89_phy_tx_path_div_track(struct rtw89_dev *rtwdev) &done); } +#define ANTDIV_MAIN 0 +#define ANTDIV_AUX 1 + +static void rtw89_phy_antdiv_set_ant(struct rtw89_dev *rtwdev) +{ + struct rtw89_hal *hal = &rtwdev->hal; + u8 default_ant, optional_ant; + + if (!hal->ant_diversity || hal->antenna_tx == 0) + return; + + if (hal->antenna_tx == RF_B) { + default_ant = ANTDIV_AUX; + optional_ant = ANTDIV_MAIN; + } else { + default_ant = ANTDIV_MAIN; + optional_ant = ANTDIV_AUX; + } + + rtw89_phy_write32_idx(rtwdev, R_P0_ANTSEL, B_P0_ANTSEL_CGCS_CTRL, + default_ant, RTW89_PHY_0); + rtw89_phy_write32_idx(rtwdev, R_P0_ANTSEL, B_P0_ANTSEL_RX_ORI, + default_ant, RTW89_PHY_0); + rtw89_phy_write32_idx(rtwdev, R_P0_ANTSEL, B_P0_ANTSEL_RX_ALT, + optional_ant, RTW89_PHY_0); + rtw89_phy_write32_idx(rtwdev, R_P0_ANTSEL, B_P0_ANTSEL_TX_ORI, + default_ant, RTW89_PHY_0); +} + +static void rtw89_phy_swap_hal_antenna(struct rtw89_dev *rtwdev) +{ + struct rtw89_hal *hal = &rtwdev->hal; + + hal->antenna_rx = hal->antenna_rx == RF_A ? RF_B : RF_A; + hal->antenna_tx = hal->antenna_rx; +} + +static void rtw89_phy_antdiv_decision_state(struct rtw89_dev *rtwdev) +{ + struct rtw89_antdiv_info *antdiv = &rtwdev->antdiv; + struct rtw89_hal *hal = &rtwdev->hal; + bool no_change = false; + u8 main_rssi, aux_rssi; + u8 main_evm, aux_evm; + u32 candidate; + + antdiv->get_stats = false; + antdiv->training_count = 0; + + main_rssi = rtw89_phy_antdiv_sts_instance_get_rssi(&antdiv->main_stats); + main_evm = rtw89_phy_antdiv_sts_instance_get_evm(&antdiv->main_stats); + aux_rssi = rtw89_phy_antdiv_sts_instance_get_rssi(&antdiv->aux_stats); + aux_evm = rtw89_phy_antdiv_sts_instance_get_evm(&antdiv->aux_stats); + + if (main_evm > aux_evm + ANTDIV_EVM_DIFF_TH) + candidate = RF_A; + else if (aux_evm > main_evm + ANTDIV_EVM_DIFF_TH) + candidate = RF_B; + else if (main_rssi > aux_rssi + RTW89_TX_DIV_RSSI_RAW_TH) + candidate = RF_A; + else if (aux_rssi > main_rssi + RTW89_TX_DIV_RSSI_RAW_TH) + candidate = RF_B; + else + no_change = true; + + if (no_change) { + /* swap back from training antenna to original */ + rtw89_phy_swap_hal_antenna(rtwdev); + return; + } + + hal->antenna_tx = candidate; + hal->antenna_rx = candidate; +} + +static void rtw89_phy_antdiv_training_state(struct rtw89_dev *rtwdev) +{ + struct rtw89_antdiv_info *antdiv = &rtwdev->antdiv; + u64 state_period; + + if (antdiv->training_count % 2 == 0) { + if (antdiv->training_count == 0) + rtw89_phy_antdiv_sts_reset(rtwdev); + + antdiv->get_stats = true; + state_period = msecs_to_jiffies(ANTDIV_TRAINNING_INTVL); + } else { + antdiv->get_stats = false; + state_period = msecs_to_jiffies(ANTDIV_DELAY); + + rtw89_phy_swap_hal_antenna(rtwdev); + rtw89_phy_antdiv_set_ant(rtwdev); + } + + antdiv->training_count++; + ieee80211_queue_delayed_work(rtwdev->hw, &rtwdev->antdiv_work, + state_period); +} + +void rtw89_phy_antdiv_work(struct work_struct *work) +{ + struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev, + antdiv_work.work); + struct rtw89_antdiv_info *antdiv = &rtwdev->antdiv; + + mutex_lock(&rtwdev->mutex); + + if (antdiv->training_count <= ANTDIV_TRAINNING_CNT) { + rtw89_phy_antdiv_training_state(rtwdev); + } else { + rtw89_phy_antdiv_decision_state(rtwdev); + rtw89_phy_antdiv_set_ant(rtwdev); + } + + mutex_unlock(&rtwdev->mutex); +} + +void rtw89_phy_antdiv_track(struct rtw89_dev *rtwdev) +{ + struct rtw89_antdiv_info *antdiv = &rtwdev->antdiv; + struct rtw89_hal *hal = &rtwdev->hal; + u8 rssi, rssi_pre; + + if (!hal->ant_diversity || hal->ant_diversity_fixed) + return; + + rssi = rtw89_phy_antdiv_sts_instance_get_rssi(&antdiv->target_stats); + rssi_pre = antdiv->rssi_pre; + antdiv->rssi_pre = rssi; + rtw89_phy_antdiv_sts_instance_reset(&antdiv->target_stats); + + if (abs((int)rssi - (int)rssi_pre) < ANTDIV_RSSI_DIFF_TH) + return; + + antdiv->training_count = 0; + ieee80211_queue_delayed_work(rtwdev->hw, &rtwdev->antdiv_work, 0); +} + static void rtw89_phy_env_monitor_init(struct rtw89_dev *rtwdev) { rtw89_phy_ccx_top_setting_init(rtwdev); @@ -4133,6 +4402,9 @@ void rtw89_phy_dm_init(struct rtw89_dev *rtwdev) rtw89_phy_dig_init(rtwdev); rtw89_phy_cfo_init(rtwdev); rtw89_phy_ul_tb_info_init(rtwdev); + rtw89_phy_antdiv_init(rtwdev); + rtw89_chip_rfe_gpio(rtwdev); + rtw89_phy_antdiv_set_ant(rtwdev); rtw89_phy_init_rf_nctl(rtwdev); rtw89_chip_rfk_init(rtwdev); diff --git a/drivers/net/wireless/realtek/rtw89/phy.h b/drivers/net/wireless/realtek/rtw89/phy.h index 7535867d0f484e33ea273e2ffed9c08a969d8bea..ab174a0ba4888b0893530b64bf7df56c750cee52 100644 --- a/drivers/net/wireless/realtek/rtw89/phy.h +++ b/drivers/net/wireless/realtek/rtw89/phy.h @@ -67,6 +67,14 @@ #define UL_TB_TF_CNT_L2H_TH 100 #define UL_TB_TF_CNT_H2L_TH 70 +#define ANTDIV_TRAINNING_CNT 2 +#define ANTDIV_TRAINNING_INTVL 30 +#define ANTDIV_DELAY 110 +#define ANTDIV_TP_DIFF_TH_HIGH 100 +#define ANTDIV_TP_DIFF_TH_LOW 5 +#define ANTDIV_EVM_DIFF_TH 8 +#define ANTDIV_RSSI_DIFF_TH 3 + #define CCX_MAX_PERIOD 2097 #define CCX_MAX_PERIOD_UNIT 32 #define MS_TO_4US_RATIO 250 @@ -549,6 +557,10 @@ void rtw89_phy_set_phy_regs(struct rtw89_dev *rtwdev, u32 addr, u32 mask, void rtw89_phy_dig_reset(struct rtw89_dev *rtwdev); void rtw89_phy_dig(struct rtw89_dev *rtwdev); void rtw89_phy_tx_path_div_track(struct rtw89_dev *rtwdev); +void rtw89_phy_antdiv_parse(struct rtw89_dev *rtwdev, + struct rtw89_rx_phy_ppdu *phy_ppdu); +void rtw89_phy_antdiv_track(struct rtw89_dev *rtwdev); +void rtw89_phy_antdiv_work(struct work_struct *work); void rtw89_phy_set_bss_color(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif); void rtw89_phy_tssi_ctrl_set_bandedge_cfg(struct rtw89_dev *rtwdev, enum rtw89_mac_idx mac_idx, diff --git a/drivers/net/wireless/realtek/rtw89/reg.h b/drivers/net/wireless/realtek/rtw89/reg.h index 266e4231b5f34c16826575d70e69b95000f06e2c..55595fde74949946b9eb79e863286bfd374bb608 100644 --- a/drivers/net/wireless/realtek/rtw89/reg.h +++ b/drivers/net/wireless/realtek/rtw89/reg.h @@ -19,6 +19,8 @@ #define B_AX_FEN_BBRSTB BIT(0) #define R_AX_SYS_PW_CTRL 0x0004 +#define B_AX_SOP_ASWRM BIT(31) +#define B_AX_SOP_PWMM_DSWR BIT(29) #define B_AX_XTAL_OFF_A_DIE BIT(22) #define B_AX_DIS_WLBT_PDNSUSEN_SOPC BIT(18) #define B_AX_RDY_SYSPWR BIT(17) @@ -134,6 +136,8 @@ #define B_AX_PLATFORM_EN BIT(0) #define R_AX_WLLPS_CTRL 0x0090 +#define B_AX_LPSOP_ASWRM BIT(17) +#define B_AX_LPSOP_DSWRM BIT(9) #define B_AX_DIS_WLBT_LPSEN_LOPC BIT(1) #define SW_LPS_OPTION 0x0001A0B2 @@ -222,9 +226,14 @@ #define B_AX_OCP_L1_MASK GENMASK(15, 13) #define B_AX_VOL_L1_MASK GENMASK(3, 0) +#define R_AX_SPSLDO_ON_CTRL1 0x0204 +#define B_AX_FPWMDELAY BIT(3) + #define R_AX_LDO_AON_CTRL0 0x0218 #define B_AX_PD_REGU_L BIT(16) +#define R_AX_SPSANA_ON_CTRL1 0x0224 + #define R_AX_WLAN_XTAL_SI_CTRL 0x0270 #define B_AX_WL_XTAL_SI_CMD_POLL BIT(31) #define B_AX_BT_XTAL_SI_ERR_FLAG BIT(30) @@ -237,17 +246,30 @@ #define B_AX_WL_XTAL_SI_DATA_MASK GENMASK(15, 8) #define B_AX_WL_XTAL_SI_ADDR_MASK GENMASK(7, 0) +#define R_AX_WLAN_XTAL_SI_CONFIG 0x0274 +#define B_AX_XTAL_SI_ADDR_NOT_CHK BIT(0) + #define R_AX_XTAL_ON_CTRL0 0x0280 #define B_AX_XTAL_SC_LPS BIT(31) #define B_AX_XTAL_SC_XO_MASK GENMASK(23, 17) #define B_AX_XTAL_SC_XI_MASK GENMASK(16, 10) #define B_AX_XTAL_SC_MASK GENMASK(6, 0) +#define R_AX_XTAL_ON_CTRL3 0x028C +#define B_AX_XTAL_SC_INIT_A_BLOCK_MASK GENMASK(30, 24) +#define B_AX_XTAL_SC_LPS_A_BLOCK_MASK GENMASK(22, 16) +#define B_AX_XTAL_SC_XO_A_BLOCK_MASK GENMASK(14, 8) +#define B_AX_XTAL_SC_XI_A_BLOCK_MASK GENMASK(6, 0) + #define R_AX_GPIO0_7_FUNC_SEL 0x02D0 #define R_AX_EECS_EESK_FUNC_SEL 0x02D8 #define B_AX_PINMUX_EESK_FUNC_SEL_MASK GENMASK(7, 4) +#define R_AX_GPIO16_23_FUNC_SEL 0x02D8 +#define B_AX_PINMUX_GPIO17_FUNC_SEL_MASK GENMASK(7, 4) +#define B_AX_PINMUX_GPIO16_FUNC_SEL_MASK GENMASK(3, 0) + #define R_AX_LED1_FUNC_SEL 0x02DC #define B_AX_PINMUX_EESK_FUNC_SEL_V1_MASK GENMASK(27, 24) #define PINMUX_EESK_FUNC_SEL_BT_LOG 0x1 @@ -257,6 +279,10 @@ #define B_AX_EESK_PULL_LOW_EN BIT(17) #define B_AX_EECS_PULL_LOW_EN BIT(16) +#define R_AX_GPIO0_16_EECS_EESK_LED1_PULL_LOW_EN 0x02E4 +#define B_AX_GPIO16_PULL_LOW_EN_V1 BIT(19) +#define B_AX_GPIO10_PULL_LOW_EN BIT(10) + #define R_AX_WLRF_CTRL 0x02F0 #define B_AX_AFC_AFEDIG BIT(17) #define B_AX_WLRF1_CTRL_7 BIT(15) @@ -3299,10 +3325,36 @@ #define B_AX_TXAGC_BT_EN BIT(1) #define B_AX_TXAGC_BT_MASK GENMASK(11, 3) +#define R_AX_PWR_SWING_OTHER_CTRL0 0xD230 +#define R_AX_PWR_SWING_OTHER_CTRL0_C1 0xF230 +#define B_AX_CFIR_BY_RATE_OFF_MASK GENMASK(17, 0) + #define R_AX_PWR_UL_CTRL0 0xD240 #define R_AX_PWR_UL_CTRL2 0xD248 #define B_AX_PWR_UL_CFO_MASK GENMASK(2, 0) #define B_AX_PWR_UL_CTRL2_MASK 0x07700007 + +#define R_AX_PWR_NORM_FORCE1 0xD260 +#define R_AX_PWR_NORM_FORCE1_C1 0xF260 +#define B_AX_TXAGC_BF_PWR_BOOST_FORCE_VAL_EN BIT(29) +#define B_AX_TXAGC_BF_PWR_BOOST_FORCE_VAL_MASK GENMASK(28, 24) +#define B_AX_FORCE_HE_ER_SU_EN_EN BIT(23) +#define B_AX_FORCE_HE_ER_SU_EN_VALUE BIT(22) +#define B_AX_FORCE_MACID_CCA_TH_EN_EN BIT(21) +#define B_AX_FORCE_MACID_CCA_TH_EN_VALUE BIT(20) +#define B_AX_FORCE_BT_GRANT_EN BIT(19) +#define B_AX_FORCE_BT_GRANT_VALUE BIT(18) +#define B_AX_FORCE_RX_LTE_EN BIT(17) +#define B_AX_FORCE_RX_LTE_VALUE BIT(16) +#define B_AX_FORCE_TXBF_EN_EN BIT(15) +#define B_AX_FORCE_TXBF_EN_VALUE BIT(14) +#define B_AX_FORCE_TXSC_EN BIT(13) +#define B_AX_FORCE_TXSC_VALUE_MASK GENMASK(12, 9) +#define B_AX_FORCE_NTX_EN BIT(6) +#define B_AX_FORCE_NTX_VALUE BIT(5) +#define B_AX_FORCE_PWR_MODE_EN BIT(3) +#define B_AX_FORCE_PWR_MODE_VALUE_MASK GENMASK(2, 0) + #define R_AX_PWR_UL_TB_CTRL 0xD288 #define B_AX_PWR_UL_TB_CTRL_EN BIT(31) #define R_AX_PWR_UL_TB_1T 0xD28C @@ -3312,16 +3364,22 @@ #define B_AX_PWR_UL_TB_2T_MASK GENMASK(4, 0) #define B_AX_PWR_UL_TB_2T_V1_MASK GENMASK(7, 0) #define R_AX_PWR_BY_RATE_TABLE0 0xD2C0 +#define R_AX_PWR_BY_RATE_TABLE6 0xD2D8 #define R_AX_PWR_BY_RATE_TABLE10 0xD2E8 #define R_AX_PWR_BY_RATE R_AX_PWR_BY_RATE_TABLE0 +#define R_AX_PWR_BY_RATE_1SS_MAX R_AX_PWR_BY_RATE_TABLE6 #define R_AX_PWR_BY_RATE_MAX R_AX_PWR_BY_RATE_TABLE10 #define R_AX_PWR_LMT_TABLE0 0xD2EC +#define R_AX_PWR_LMT_TABLE9 0xD310 #define R_AX_PWR_LMT_TABLE19 0xD338 #define R_AX_PWR_LMT R_AX_PWR_LMT_TABLE0 +#define R_AX_PWR_LMT_1SS_MAX R_AX_PWR_LMT_TABLE9 #define R_AX_PWR_LMT_MAX R_AX_PWR_LMT_TABLE19 #define R_AX_PWR_RU_LMT_TABLE0 0xD33C +#define R_AX_PWR_RU_LMT_TABLE5 0xD350 #define R_AX_PWR_RU_LMT_TABLE11 0xD368 #define R_AX_PWR_RU_LMT R_AX_PWR_RU_LMT_TABLE0 +#define R_AX_PWR_RU_LMT_1SS_MAX R_AX_PWR_RU_LMT_TABLE5 #define R_AX_PWR_RU_LMT_MAX R_AX_PWR_RU_LMT_TABLE11 #define R_AX_PWR_MACID_LMT_TABLE0 0xD36C #define R_AX_PWR_MACID_LMT_TABLE127 0xD568 @@ -3574,6 +3632,7 @@ #define RR_MOD_MASK GENMASK(19, 16) #define RR_MOD_DCK GENMASK(14, 10) #define RR_MOD_RGM GENMASK(13, 4) +#define RR_MOD_RXB GENMASK(9, 5) #define RR_MOD_V_DOWN 0x0 #define RR_MOD_V_STANDBY 0x1 #define RR_TXAGC 0x10001 @@ -3713,6 +3772,7 @@ #define RR_RXBB 0x83 #define RR_RXBB_VOBUF GENMASK(15, 12) #define RR_RXBB_C2G GENMASK(16, 10) +#define RR_RXBB_C2 GENMASK(11, 8) #define RR_RXBB_C1G GENMASK(9, 8) #define RR_RXBB_FATT GENMASK(7, 0) #define RR_RXBB_ATTR GENMASK(7, 4) @@ -3727,6 +3787,7 @@ #define RR_RXA_DPK GENMASK(9, 8) #define RR_RXA_LNA 0x8b #define RR_RXA2 0x8c +#define RR_RAA2_SATT GENMASK(15, 13) #define RR_RAA2_SWATT GENMASK(15, 9) #define RR_RXA2_C1 GENMASK(12, 10) #define RR_RXA2_C2 GENMASK(9, 3) @@ -3776,19 +3837,26 @@ #define RR_LOGEN 0xa3 #define RR_LOGEN_RPT GENMASK(19, 16) #define RR_SX 0xaf +#define RR_IBD 0xc9 +#define RR_IBD_VAL GENMASK(4, 0) #define RR_LDO 0xb1 #define RR_LDO_SEL GENMASK(8, 6) #define RR_VCO 0xb2 +#define RR_VCO_SEL GENMASK(9, 8) +#define RR_VCI 0xb3 +#define RR_VCI_ON BIT(7) #define RR_LPF 0xb7 #define RR_LPF_BUSY BIT(8) #define RR_XTALX2 0xb8 #define RR_MALSEL 0xbe #define RR_SYNFB 0xc5 #define RR_SYNFB_LK BIT(15) +#define RR_AACK 0xca #define RR_LCKST 0xcf #define RR_LCKST_BIN BIT(0) #define RR_LCK_TRG 0xd3 #define RR_LCK_TRGSEL BIT(8) +#define RR_LCK_ST BIT(4) #define RR_MMD 0xd5 #define RR_MMD_RST_EN BIT(8) #define RR_MMD_RST_SYN BIT(6) @@ -3807,6 +3875,7 @@ #define RR_CAL_RW BIT(19) #define RR_LUTWE2 0xee #define RR_LUTWE2_RTXBW BIT(2) +#define RR_LUTWE2_DIS BIT(6) #define RR_LUTWE 0xef #define RR_LUTWE_LOK BIT(2) #define RR_RFC 0xf0 @@ -3832,6 +3901,7 @@ #define R_RFE_E_A2 0x0334 #define R_RFE_O_SEL_A2 0x0338 #define R_RFE_SEL0_A2 0x033C +#define B_RFE_SEL0_MASK GENMASK(1, 0) #define R_RFE_SEL32_A2 0x0340 #define R_CIRST 0x035c #define B_CIRST_SYN GENMASK(11, 10) @@ -3852,6 +3922,9 @@ #define B_ENABLE_CCK BIT(5) #define R_RSTB_ASYNC 0x0704 #define B_RSTB_ASYNC_ALL BIT(1) +#define R_P0_ANT_SW 0x0728 +#define B_P0_HW_ANTSW_DIS_BY_GNT_BT BIT(12) +#define B_P0_TRSW_TX_EXTEND GENMASK(3, 0) #define R_MAC_PIN_SEL 0x0734 #define B_CH_IDX_SEG0 GENMASK(23, 16) #define R_PLCP_HISTOGRAM 0x0738 @@ -3961,6 +4034,7 @@ #define R_S0_HW_SI_DIS 0x1200 #define B_S0_HW_SI_DIS_W_R_TRIG GENMASK(30, 28) #define R_P0_RXCK 0x12A0 +#define B_P0_RXCK_ADJ GENMASK(31, 23) #define B_P0_RXCK_BW3 BIT(30) #define B_P0_TXCK_ALL GENMASK(19, 12) #define B_P0_RXCK_ON BIT(19) @@ -4034,6 +4108,7 @@ #define R_TXAGC_BB 0x1C60 #define B_TXAGC_BB_OFT GENMASK(31, 16) #define B_TXAGC_BB GENMASK(31, 24) +#define B_TXAGC_RF GENMASK(5, 0) #define R_S0_ADDCK 0x1E00 #define B_S0_ADDCK_I GENMASK(9, 0) #define B_S0_ADDCK_Q GENMASK(19, 10) @@ -4117,8 +4192,10 @@ #define R_DCFO 0x4264 #define B_DCFO GENMASK(7, 0) #define R_SEG0CSI 0x42AC +#define R_SEG0CSI_V1 0x42B0 #define B_SEG0CSI_IDX GENMASK(10, 0) #define R_SEG0CSI_EN 0x42C4 +#define R_SEG0CSI_EN_V1 0x42C8 #define B_SEG0CSI_EN BIT(23) #define R_BSS_CLR_MAP 0x43ac #define R_BSS_CLR_MAP_V1 0x43B0 @@ -4350,6 +4427,14 @@ #define B_PATH0_BT_BACKOFF_V1 GENMASK(23, 0) #define R_PATH1_BT_BACKOFF_V1 0x4AEC #define B_PATH1_BT_BACKOFF_V1 GENMASK(23, 0) +#define R_DCFO_COMP_S0_V2 0x4B20 +#define B_DCFO_COMP_S0_MSK_V2 GENMASK(13, 0) +#define R_PATH0_TX_CFR 0x4B30 +#define B_PATH0_TX_CFR_LGC1 GENMASK(19, 10) +#define B_PATH0_TX_CFR_LGC0 GENMASK(9, 0) +#define R_PATH0_TX_POLAR_CLIPPING 0x4B3C +#define B_PATH0_TX_POLAR_CLIPPING_LGC1 GENMASK(19, 16) +#define B_PATH0_TX_POLAR_CLIPPING_LGC0 GENMASK(15, 12) #define R_PATH0_FRC_FIR_TYPE_V1 0x4C00 #define B_PATH0_FRC_FIR_TYPE_MSK_V1 GENMASK(1, 0) #define R_PATH0_NOTCH 0x4C14 @@ -4455,10 +4540,29 @@ #define B_P0_RFCTM_VAL GENMASK(25, 20) #define R_P0_RFCTM_RDY BIT(26) #define R_P0_TRSW 0x5868 -#define B_P0_TRSW_B BIT(0) -#define B_P0_TRSW_A BIT(1) +#define B_P0_BT_FORCE_ANTIDX_EN BIT(12) #define B_P0_TRSW_X BIT(2) +#define B_P0_TRSW_A BIT(1) +#define B_P0_TX_ANT_SEL BIT(1) +#define B_P0_TRSW_B BIT(0) +#define B_P0_ANT_TRAIN_EN BIT(0) #define B_P0_TRSW_SO_A2 GENMASK(7, 5) +#define R_P0_ANTSEL 0x586C +#define B_P0_ANTSEL_SW_5G BIT(25) +#define B_P0_ANTSEL_SW_2G BIT(23) +#define B_P0_ANTSEL_BTG_TRX BIT(21) +#define B_P0_ANTSEL_CGCS_CTRL BIT(17) +#define B_P0_ANTSEL_HW_CTRL BIT(16) +#define B_P0_ANTSEL_TX_ORI GENMASK(15, 12) +#define B_P0_ANTSEL_RX_ALT GENMASK(11, 8) +#define B_P0_ANTSEL_RX_ORI GENMASK(7, 4) +#define R_RFSW_CTRL_ANT0_BASE 0x5870 +#define B_RFSW_CTRL_ANT_MAPPING GENMASK(15, 0) +#define R_RFE_SEL0_BASE 0x5880 +#define B_RFE_SEL0_SRC_MASK GENMASK(3, 0) +#define R_RFE_SEL32_BASE 0x5884 +#define RFE_SEL0_SRC_ANTSEL_0 8 +#define R_RFE_INV0 0x5890 #define R_P0_RFM 0x5894 #define B_P0_RFM_DIS_WL BIT(7) #define B_P0_RFM_TX_OPT BIT(6) @@ -4572,12 +4676,15 @@ #define IQK_DF4_TXT_8_25MHZ 0x021 #define R_IQK_CFG 0x8034 #define B_IQK_CFG_SET GENMASK(5, 4) +#define R_IQK_RXA 0x8044 +#define B_IQK_RXAGC GENMASK(15, 13) #define R_TPG_SEL 0x8068 #define R_TPG_MOD 0x806C #define B_TPG_MOD_F GENMASK(2, 1) #define R_MDPK_SYNC 0x8070 #define B_MDPK_SYNC_SEL BIT(31) #define B_MDPK_SYNC_MAN GENMASK(31, 28) +#define B_MDPK_SYNC_DMAN GENMASK(30, 28) #define R_MDPK_RX_DCK 0x8074 #define B_MDPK_RX_DCK_EN BIT(31) #define R_KIP_MOD 0x8078 @@ -4586,6 +4693,7 @@ #define R_KIP_SYSCFG 0x8088 #define R_KIP_CLK 0x808C #define R_DPK_IDL 0x809C +#define B_DPK_IDL_SEL GENMASK(10, 9) #define B_DPK_IDL BIT(8) #define R_LDL_NORM 0x80A0 #define B_LDL_NORM_MA BIT(16) @@ -4604,6 +4712,10 @@ #define B_KIP_RPT1_SEL GENMASK(21, 16) #define B_KIP_RPT1_SEL_V1 GENMASK(19, 16) #define R_SRAM_IQRX 0x80D8 +#define R_IDL_MPA 0x80DC +#define B_IDL_DN BIT(31) +#define B_IDL_MD530 BIT(1) +#define B_IDL_MD500 BIT(0) #define R_GAPK 0x80E0 #define B_GAPK_ADR BIT(0) #define R_SRAM_IQRX2 0x80E8 @@ -4619,6 +4731,7 @@ #define B_PRT_COM_SYNERR BIT(30) #define B_PRT_COM_DCI GENMASK(27, 16) #define B_PRT_COM_CORV GENMASK(15, 8) +#define B_RPT_COM_RDY GENMASK(15, 0) #define B_PRT_COM_DCQ GENMASK(11, 0) #define B_PRT_COM_RXOV BIT(8) #define B_PRT_COM_GL GENMASK(7, 4) @@ -4690,6 +4803,7 @@ #define B_DPK_GL_A0 GENMASK(31, 28) #define B_DPK_GL_A1 GENMASK(17, 0) #define R_RPT_PER 0x81FC +#define B_RPT_PER_KSET GENMASK(31, 29) #define B_RPT_PER_TSSI GENMASK(28, 16) #define B_RPT_PER_OF GENMASK(15, 8) #define B_RPT_PER_TH GENMASK(5, 0) @@ -4730,11 +4844,15 @@ #define B_IQKINF2_KCNT GENMASK(15, 8) #define B_IQKINF2_NCTLV GENMASK(7, 0) #define R_DCOF0 0xC000 +#define B_DCOF0_RST BIT(17) #define B_DCOF0_V GENMASK(4, 1) #define R_DCOF1 0xC004 +#define B_DCOF1_RST BIT(17) #define B_DCOF1_S BIT(0) #define R_DCOF8 0xC020 #define B_DCOF8_V GENMASK(4, 1) +#define R_DCOF9 0xC024 +#define B_DCOF9_RST BIT(17) #define R_DACK_S0P0 0xC040 #define B_DACK_S0P0_OK BIT(31) #define R_DACK_BIAS00 0xc048 @@ -4779,13 +4897,19 @@ #define R_P0_CFCH_BW1 0xC0D8 #define B_P0_CFCH_EX BIT(13) #define B_P0_CFCH_BW1 GENMASK(8, 5) +#define R_WDADC 0xC0E4 +#define B_WDADC_SEL GENMASK(5, 4) #define R_ADCMOD 0xC0E8 #define B_ADCMOD_LP GENMASK(31, 16) +#define R_DCIM 0xC0EC +#define B_DCIM_FR GENMASK(14, 13) #define R_ADDCK0D 0xC0F0 #define B_ADDCK0D_VAL2 GENMASK(31, 26) #define B_ADDCK0D_VAL GENMASK(25, 16) +#define B_ADDCK_DS BIT(16) #define R_ADDCK0 0xC0F4 #define B_ADDCK0_TRG BIT(11) +#define B_ADDCK0_IQ BIT(10) #define B_ADDCK0 GENMASK(9, 8) #define B_ADDCK0_MAN GENMASK(5, 4) #define B_ADDCK0_EN BIT(4) @@ -4797,6 +4921,7 @@ #define B_ADDCK0_RL0 GENMASK(17, 8) #define R_ADDCKR0 0xC0FC #define B_ADDCKR0_A0 GENMASK(19, 10) +#define B_ADDCKR0_DC GENMASK(15, 4) #define B_ADDCKR0_A1 GENMASK(9, 0) #define R_DACK10 0xC100 #define B_DACK10 GENMASK(4, 1) @@ -4847,6 +4972,11 @@ #define R_ADDCKR1 0xC1fC #define B_ADDCKR1_A0 GENMASK(19, 10) #define B_ADDCKR1_A1 GENMASK(9, 0) +#define R_DACKN0_CTL 0xC210 +#define B_DACKN0_EN BIT(0) +#define B_DACKN0_V GENMASK(21, 14) +#define R_DACKN1_CTL 0xC224 +#define B_DACKN1_V GENMASK(21, 14) /* WiFi CPU local domain */ #define R_AX_WDT_CTRL 0x0040 diff --git a/drivers/net/wireless/realtek/rtw89/regd.c b/drivers/net/wireless/realtek/rtw89/regd.c index 6e5a740b128f027ca4dfeefcaf133e3cad3a6dca..34c4d40cfa022cd72d8b15aa8b2be6adef75faaf 100644 --- a/drivers/net/wireless/realtek/rtw89/regd.c +++ b/drivers/net/wireless/realtek/rtw89/regd.c @@ -2,33 +2,35 @@ /* Copyright(c) 2019-2020 Realtek Corporation */ +#include "acpi.h" #include "debug.h" #include "ps.h" +#include "util.h" #define COUNTRY_REGD(_alpha2, _txpwr_regd...) \ {.alpha2 = (_alpha2), \ .txpwr_regd = {_txpwr_regd}, \ } -static const struct rtw89_regulatory rtw89_ww_regd = +static const struct rtw89_regd rtw89_ww_regd = COUNTRY_REGD("00", RTW89_WW, RTW89_WW); -static const struct rtw89_regulatory rtw89_regd_map[] = { +static const struct rtw89_regd rtw89_regd_map[] = { COUNTRY_REGD("AR", RTW89_MEXICO, RTW89_MEXICO, RTW89_NA), - COUNTRY_REGD("BO", RTW89_FCC, RTW89_FCC, RTW89_NA), + COUNTRY_REGD("BO", RTW89_FCC, RTW89_FCC, RTW89_FCC), COUNTRY_REGD("BR", RTW89_FCC, RTW89_FCC, RTW89_FCC), COUNTRY_REGD("CL", RTW89_CHILE, RTW89_CHILE, RTW89_CHILE), - COUNTRY_REGD("CO", RTW89_FCC, RTW89_FCC, RTW89_NA), + COUNTRY_REGD("CO", RTW89_FCC, RTW89_FCC, RTW89_FCC), COUNTRY_REGD("CR", RTW89_FCC, RTW89_FCC, RTW89_FCC), COUNTRY_REGD("EC", RTW89_FCC, RTW89_FCC, RTW89_NA), - COUNTRY_REGD("SV", RTW89_FCC, RTW89_FCC, RTW89_NA), - COUNTRY_REGD("GT", RTW89_FCC, RTW89_FCC, RTW89_NA), + COUNTRY_REGD("SV", RTW89_FCC, RTW89_FCC, RTW89_FCC), + COUNTRY_REGD("GT", RTW89_FCC, RTW89_FCC, RTW89_FCC), COUNTRY_REGD("HN", RTW89_FCC, RTW89_FCC, RTW89_FCC), COUNTRY_REGD("MX", RTW89_MEXICO, RTW89_MEXICO, RTW89_NA), COUNTRY_REGD("NI", RTW89_FCC, RTW89_FCC, RTW89_NA), COUNTRY_REGD("PA", RTW89_FCC, RTW89_FCC, RTW89_NA), COUNTRY_REGD("PY", RTW89_FCC, RTW89_FCC, RTW89_NA), - COUNTRY_REGD("PE", RTW89_FCC, RTW89_FCC, RTW89_NA), + COUNTRY_REGD("PE", RTW89_FCC, RTW89_FCC, RTW89_FCC), COUNTRY_REGD("US", RTW89_FCC, RTW89_FCC, RTW89_FCC), COUNTRY_REGD("UY", RTW89_FCC, RTW89_FCC, RTW89_NA), COUNTRY_REGD("VE", RTW89_FCC, RTW89_FCC, RTW89_NA), @@ -65,37 +67,37 @@ static const struct rtw89_regulatory rtw89_regd_map[] = { COUNTRY_REGD("CH", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("GB", RTW89_UK, RTW89_UK, RTW89_UK), COUNTRY_REGD("AL", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("AZ", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("BH", RTW89_ETSI, RTW89_ETSI, RTW89_NA), + COUNTRY_REGD("AZ", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), + COUNTRY_REGD("BH", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("BA", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("BG", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("HR", RTW89_ETSI, RTW89_ETSI, RTW89_NA), + COUNTRY_REGD("BG", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), + COUNTRY_REGD("HR", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("EG", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("GH", RTW89_ETSI, RTW89_ETSI, RTW89_NA), + COUNTRY_REGD("GH", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("IQ", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("IL", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("JO", RTW89_ETSI, RTW89_ETSI, RTW89_NA), + COUNTRY_REGD("IL", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), + COUNTRY_REGD("JO", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("KZ", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("KE", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("KW", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("KG", RTW89_ETSI, RTW89_ETSI, RTW89_NA), + COUNTRY_REGD("KE", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), + COUNTRY_REGD("KW", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), + COUNTRY_REGD("KG", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("LB", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("LS", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("MK", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("MA", RTW89_ETSI, RTW89_ETSI, RTW89_NA), + COUNTRY_REGD("MA", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("MZ", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("NA", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("NG", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("OM", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("QA", RTW89_QATAR, RTW89_QATAR, RTW89_QATAR), - COUNTRY_REGD("RO", RTW89_ETSI, RTW89_ETSI, RTW89_NA), + COUNTRY_REGD("RO", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("RU", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("SA", RTW89_ETSI, RTW89_ETSI, RTW89_NA), + COUNTRY_REGD("SA", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("SN", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("RS", RTW89_ETSI, RTW89_ETSI, RTW89_NA), + COUNTRY_REGD("RS", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("ME", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("ZA", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("TR", RTW89_ETSI, RTW89_ETSI, RTW89_NA), + COUNTRY_REGD("TR", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("UA", RTW89_UKRAINE, RTW89_UKRAINE, RTW89_UKRAINE), COUNTRY_REGD("AE", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("YE", RTW89_ETSI, RTW89_ETSI, RTW89_NA), @@ -103,11 +105,11 @@ static const struct rtw89_regulatory rtw89_regd_map[] = { COUNTRY_REGD("BD", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("KH", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("CN", RTW89_CN, RTW89_CN, RTW89_CN), - COUNTRY_REGD("HK", RTW89_ETSI, RTW89_ETSI, RTW89_NA), + COUNTRY_REGD("HK", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("IN", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("ID", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("KR", RTW89_KCC, RTW89_KCC, RTW89_KCC), - COUNTRY_REGD("MY", RTW89_ETSI, RTW89_ETSI, RTW89_NA), + COUNTRY_REGD("MY", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("PK", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("PH", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("SG", RTW89_ETSI, RTW89_ETSI, RTW89_NA), @@ -115,55 +117,55 @@ static const struct rtw89_regulatory rtw89_regd_map[] = { COUNTRY_REGD("TW", RTW89_FCC, RTW89_FCC, RTW89_NA), COUNTRY_REGD("TH", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("VN", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("AU", RTW89_ACMA, RTW89_ACMA, RTW89_NA), - COUNTRY_REGD("NZ", RTW89_ACMA, RTW89_ACMA, RTW89_NA), - COUNTRY_REGD("PG", RTW89_ETSI, RTW89_ETSI, RTW89_NA), + COUNTRY_REGD("AU", RTW89_ACMA, RTW89_ACMA, RTW89_ACMA), + COUNTRY_REGD("NZ", RTW89_ACMA, RTW89_ACMA, RTW89_ACMA), + COUNTRY_REGD("PG", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("CA", RTW89_IC, RTW89_IC, RTW89_IC), - COUNTRY_REGD("JP", RTW89_MKK, RTW89_MKK, RTW89_NA), - COUNTRY_REGD("JM", RTW89_FCC, RTW89_FCC, RTW89_NA), - COUNTRY_REGD("AN", RTW89_FCC, RTW89_FCC, RTW89_NA), + COUNTRY_REGD("JP", RTW89_MKK, RTW89_MKK, RTW89_MKK), + COUNTRY_REGD("JM", RTW89_FCC, RTW89_FCC, RTW89_FCC), + COUNTRY_REGD("AN", RTW89_FCC, RTW89_FCC, RTW89_FCC), COUNTRY_REGD("TT", RTW89_FCC, RTW89_FCC, RTW89_NA), COUNTRY_REGD("TN", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("AF", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("DZ", RTW89_ETSI, RTW89_ETSI, RTW89_NA), + COUNTRY_REGD("DZ", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("AS", RTW89_FCC, RTW89_FCC, RTW89_NA), COUNTRY_REGD("AD", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("AO", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("AI", RTW89_ETSI, RTW89_ETSI, RTW89_NA), + COUNTRY_REGD("AI", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("AQ", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("AG", RTW89_FCC, RTW89_FCC, RTW89_NA), - COUNTRY_REGD("AM", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("AW", RTW89_FCC, RTW89_FCC, RTW89_NA), - COUNTRY_REGD("BS", RTW89_FCC, RTW89_FCC, RTW89_NA), - COUNTRY_REGD("BB", RTW89_FCC, RTW89_FCC, RTW89_NA), + COUNTRY_REGD("AG", RTW89_FCC, RTW89_FCC, RTW89_FCC), + COUNTRY_REGD("AM", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), + COUNTRY_REGD("AW", RTW89_FCC, RTW89_FCC, RTW89_FCC), + COUNTRY_REGD("BS", RTW89_FCC, RTW89_FCC, RTW89_FCC), + COUNTRY_REGD("BB", RTW89_FCC, RTW89_FCC, RTW89_FCC), COUNTRY_REGD("BY", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("BZ", RTW89_FCC, RTW89_FCC, RTW89_NA), COUNTRY_REGD("BJ", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("BM", RTW89_FCC, RTW89_FCC, RTW89_NA), + COUNTRY_REGD("BM", RTW89_FCC, RTW89_FCC, RTW89_FCC), COUNTRY_REGD("BT", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("BW", RTW89_ETSI, RTW89_ETSI, RTW89_NA), + COUNTRY_REGD("BW", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("BV", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("IO", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("VG", RTW89_FCC, RTW89_FCC, RTW89_NA), + COUNTRY_REGD("VG", RTW89_FCC, RTW89_FCC, RTW89_FCC), COUNTRY_REGD("BN", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("BF", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("MM", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("BI", RTW89_ETSI, RTW89_ETSI, RTW89_NA), + COUNTRY_REGD("BI", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("CM", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("CV", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("KY", RTW89_FCC, RTW89_FCC, RTW89_NA), + COUNTRY_REGD("KY", RTW89_FCC, RTW89_FCC, RTW89_FCC), COUNTRY_REGD("CF", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("TD", RTW89_ETSI, RTW89_ETSI, RTW89_NA), + COUNTRY_REGD("TD", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("CX", RTW89_ACMA, RTW89_ACMA, RTW89_NA), - COUNTRY_REGD("CC", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("KM", RTW89_ETSI, RTW89_ETSI, RTW89_NA), + COUNTRY_REGD("CC", RTW89_ACMA, RTW89_ACMA, RTW89_NA), + COUNTRY_REGD("KM", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("CG", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("CD", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("CK", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("CI", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("DJ", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("DM", RTW89_FCC, RTW89_FCC, RTW89_NA), - COUNTRY_REGD("GQ", RTW89_ETSI, RTW89_ETSI, RTW89_NA), + COUNTRY_REGD("DJ", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), + COUNTRY_REGD("DM", RTW89_FCC, RTW89_FCC, RTW89_FCC), + COUNTRY_REGD("GQ", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("ER", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("ET", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("FK", RTW89_ETSI, RTW89_ETSI, RTW89_NA), @@ -173,17 +175,17 @@ static const struct rtw89_regulatory rtw89_regd_map[] = { COUNTRY_REGD("PF", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("TF", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("GA", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("GM", RTW89_ETSI, RTW89_ETSI, RTW89_NA), + COUNTRY_REGD("GM", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("GE", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("GI", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("GL", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("GD", RTW89_FCC, RTW89_FCC, RTW89_NA), + COUNTRY_REGD("GD", RTW89_FCC, RTW89_FCC, RTW89_FCC), COUNTRY_REGD("GP", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("GU", RTW89_FCC, RTW89_FCC, RTW89_NA), COUNTRY_REGD("GG", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("GN", RTW89_ETSI, RTW89_ETSI, RTW89_NA), + COUNTRY_REGD("GN", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("GW", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("GY", RTW89_NCC, RTW89_NCC, RTW89_NA), + COUNTRY_REGD("GY", RTW89_FCC, RTW89_FCC, RTW89_FCC), COUNTRY_REGD("HT", RTW89_FCC, RTW89_FCC, RTW89_NA), COUNTRY_REGD("HM", RTW89_ACMA, RTW89_ACMA, RTW89_NA), COUNTRY_REGD("VA", RTW89_ETSI, RTW89_ETSI, RTW89_NA), @@ -194,17 +196,17 @@ static const struct rtw89_regulatory rtw89_regd_map[] = { COUNTRY_REGD("LR", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("LY", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("MO", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("MG", RTW89_ETSI, RTW89_ETSI, RTW89_NA), + COUNTRY_REGD("MG", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("MW", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("MV", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("ML", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("MH", RTW89_FCC, RTW89_FCC, RTW89_NA), COUNTRY_REGD("MQ", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("MR", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("MU", RTW89_ETSI, RTW89_ETSI, RTW89_NA), + COUNTRY_REGD("MU", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("YT", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("FM", RTW89_FCC, RTW89_FCC, RTW89_NA), - COUNTRY_REGD("MD", RTW89_ETSI, RTW89_ETSI, RTW89_NA), + COUNTRY_REGD("MD", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("MN", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("MS", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("NR", RTW89_ETSI, RTW89_ETSI, RTW89_NA), @@ -218,26 +220,26 @@ static const struct rtw89_regulatory rtw89_regd_map[] = { COUNTRY_REGD("RE", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("RW", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("SH", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("KN", RTW89_FCC, RTW89_FCC, RTW89_NA), - COUNTRY_REGD("LC", RTW89_FCC, RTW89_FCC, RTW89_NA), + COUNTRY_REGD("KN", RTW89_FCC, RTW89_FCC, RTW89_FCC), + COUNTRY_REGD("LC", RTW89_FCC, RTW89_FCC, RTW89_FCC), COUNTRY_REGD("MF", RTW89_FCC, RTW89_FCC, RTW89_NA), COUNTRY_REGD("SX", RTW89_FCC, RTW89_FCC, RTW89_NA), COUNTRY_REGD("PM", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("VC", RTW89_FCC, RTW89_FCC, RTW89_NA), COUNTRY_REGD("WS", RTW89_FCC, RTW89_FCC, RTW89_NA), COUNTRY_REGD("SM", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("ST", RTW89_FCC, RTW89_FCC, RTW89_NA), + COUNTRY_REGD("ST", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("SC", RTW89_FCC, RTW89_FCC, RTW89_NA), - COUNTRY_REGD("SL", RTW89_ETSI, RTW89_ETSI, RTW89_NA), + COUNTRY_REGD("SL", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("SB", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("SO", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("GS", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("SR", RTW89_FCC, RTW89_FCC, RTW89_NA), + COUNTRY_REGD("SR", RTW89_FCC, RTW89_FCC, RTW89_FCC), COUNTRY_REGD("SJ", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("SZ", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("TJ", RTW89_ETSI, RTW89_ETSI, RTW89_NA), + COUNTRY_REGD("TJ", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("TZ", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("TG", RTW89_ETSI, RTW89_ETSI, RTW89_NA), + COUNTRY_REGD("TG", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("TK", RTW89_ACMA, RTW89_ACMA, RTW89_NA), COUNTRY_REGD("TO", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("TM", RTW89_ETSI, RTW89_ETSI, RTW89_NA), @@ -245,7 +247,7 @@ static const struct rtw89_regulatory rtw89_regd_map[] = { COUNTRY_REGD("TV", RTW89_ETSI, RTW89_NA, RTW89_NA), COUNTRY_REGD("UG", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("VI", RTW89_FCC, RTW89_FCC, RTW89_NA), - COUNTRY_REGD("UZ", RTW89_ETSI, RTW89_ETSI, RTW89_NA), + COUNTRY_REGD("UZ", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("VU", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("WF", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("EH", RTW89_ETSI, RTW89_ETSI, RTW89_NA), @@ -254,7 +256,7 @@ static const struct rtw89_regulatory rtw89_regd_map[] = { COUNTRY_REGD("PS", RTW89_ETSI, RTW89_ETSI, RTW89_NA), }; -static const struct rtw89_regulatory *rtw89_regd_find_reg_by_name(char *alpha2) +static const struct rtw89_regd *rtw89_regd_find_reg_by_name(char *alpha2) { u32 i; @@ -266,7 +268,7 @@ static const struct rtw89_regulatory *rtw89_regd_find_reg_by_name(char *alpha2) return &rtw89_ww_regd; } -static bool rtw89_regd_is_ww(const struct rtw89_regulatory *regd) +static bool rtw89_regd_is_ww(const struct rtw89_regd *regd) { return regd == &rtw89_ww_regd; } @@ -282,25 +284,139 @@ do { \ __r->txpwr_regd[RTW89_BAND_6G]); \ } while (0) +static void rtw89_regd_setup_unii4(struct rtw89_dev *rtwdev, + struct wiphy *wiphy) +{ + const struct rtw89_chip_info *chip = rtwdev->chip; + bool regd_allow_unii_4 = chip->support_unii4; + struct ieee80211_supported_band *sband; + int ret; + u8 val; + + if (!chip->support_unii4) + goto bottom; + + ret = rtw89_acpi_evaluate_dsm(rtwdev, RTW89_ACPI_DSM_FUNC_59G_EN, &val); + if (ret) { + rtw89_debug(rtwdev, RTW89_DBG_REGD, + "acpi: cannot eval unii 4: %d\n", ret); + goto bottom; + } + + rtw89_debug(rtwdev, RTW89_DBG_REGD, + "acpi: eval if allow unii 4: %d\n", val); + + switch (val) { + case 0: + regd_allow_unii_4 = false; + break; + case 1: + regd_allow_unii_4 = true; + break; + default: + break; + } + +bottom: + rtw89_debug(rtwdev, RTW89_DBG_REGD, "regd: allow unii 4: %d\n", + regd_allow_unii_4); + + if (regd_allow_unii_4) + return; + + sband = wiphy->bands[NL80211_BAND_5GHZ]; + if (!sband) + return; + + sband->n_channels -= 3; +} + +static void rtw89_regd_setup_6ghz(struct rtw89_dev *rtwdev, struct wiphy *wiphy) +{ + const struct rtw89_chip_info *chip = rtwdev->chip; + bool chip_support_6ghz = chip->support_bands & BIT(NL80211_BAND_6GHZ); + bool regd_allow_6ghz = chip_support_6ghz; + struct ieee80211_supported_band *sband; + int ret; + u8 val; + + if (!chip_support_6ghz) + goto bottom; + + ret = rtw89_acpi_evaluate_dsm(rtwdev, RTW89_ACPI_DSM_FUNC_6G_DIS, &val); + if (ret) { + rtw89_debug(rtwdev, RTW89_DBG_REGD, + "acpi: cannot eval 6ghz: %d\n", ret); + goto bottom; + } + + rtw89_debug(rtwdev, RTW89_DBG_REGD, + "acpi: eval if disallow 6ghz: %d\n", val); + + switch (val) { + case 0: + regd_allow_6ghz = true; + break; + case 1: + regd_allow_6ghz = false; + break; + default: + break; + } + +bottom: + rtw89_debug(rtwdev, RTW89_DBG_REGD, "regd: allow 6ghz: %d\n", + regd_allow_6ghz); + + if (regd_allow_6ghz) + return; + + sband = wiphy->bands[NL80211_BAND_6GHZ]; + if (!sband) + return; + + wiphy->bands[NL80211_BAND_6GHZ] = NULL; + kfree(sband->iftype_data); + kfree(sband); +} + +int rtw89_regd_setup(struct rtw89_dev *rtwdev) +{ + struct wiphy *wiphy = rtwdev->hw->wiphy; + + if (!wiphy) + return -EINVAL; + + rtw89_regd_setup_unii4(rtwdev, wiphy); + rtw89_regd_setup_6ghz(rtwdev, wiphy); + + wiphy->reg_notifier = rtw89_regd_notifier; + return 0; +} + int rtw89_regd_init(struct rtw89_dev *rtwdev, void (*reg_notifier)(struct wiphy *wiphy, struct regulatory_request *request)) { - const struct rtw89_regulatory *chip_regd; + struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory; + const struct rtw89_regd *chip_regd; struct wiphy *wiphy = rtwdev->hw->wiphy; int ret; + regulatory->reg_6ghz_power = RTW89_REG_6GHZ_POWER_DFLT; + if (!wiphy) return -EINVAL; chip_regd = rtw89_regd_find_reg_by_name(rtwdev->efuse.country_code); if (!rtw89_regd_is_ww(chip_regd)) { - rtwdev->regd = chip_regd; + rtwdev->regulatory.regd = chip_regd; /* Ignore country ie if there is a country domain programmed in chip */ wiphy->regulatory_flags |= REGULATORY_COUNTRY_IE_IGNORE; wiphy->regulatory_flags |= REGULATORY_STRICT_REG; - ret = regulatory_hint(rtwdev->hw->wiphy, rtwdev->regd->alpha2); + ret = regulatory_hint(rtwdev->hw->wiphy, + rtwdev->regulatory.regd->alpha2); if (ret) rtw89_warn(rtwdev, "failed to hint regulatory:%d\n", ret); @@ -308,7 +424,7 @@ int rtw89_regd_init(struct rtw89_dev *rtwdev, return 0; } - rtw89_debug_regd(rtwdev, rtwdev->regd, + rtw89_debug_regd(rtwdev, rtwdev->regulatory.regd, "worldwide roaming chip, follow the setting of stack"); return 0; } @@ -317,13 +433,13 @@ static void rtw89_regd_notifier_apply(struct rtw89_dev *rtwdev, struct wiphy *wiphy, struct regulatory_request *request) { - rtwdev->regd = rtw89_regd_find_reg_by_name(request->alpha2); + rtwdev->regulatory.regd = rtw89_regd_find_reg_by_name(request->alpha2); /* This notification might be set from the system of distros, * and it does not expect the regulatory will be modified by * connecting to an AP (i.e. country ie). */ if (request->initiator == NL80211_REGDOM_SET_BY_USER && - !rtw89_regd_is_ww(rtwdev->regd)) + !rtw89_regd_is_ww(rtwdev->regulatory.regd)) wiphy->regulatory_flags |= REGULATORY_COUNTRY_IE_IGNORE; else wiphy->regulatory_flags &= ~REGULATORY_COUNTRY_IE_IGNORE; @@ -343,7 +459,8 @@ void rtw89_regd_notifier(struct wiphy *wiphy, struct regulatory_request *request goto exit; } rtw89_regd_notifier_apply(rtwdev, wiphy, request); - rtw89_debug_regd(rtwdev, rtwdev->regd, "get from initiator %d, alpha2", + rtw89_debug_regd(rtwdev, rtwdev->regulatory.regd, + "get from initiator %d, alpha2", request->initiator); rtw89_core_set_chip_txpwr(rtwdev); @@ -351,3 +468,66 @@ void rtw89_regd_notifier(struct wiphy *wiphy, struct regulatory_request *request exit: mutex_unlock(&rtwdev->mutex); } + +static void __rtw89_reg_6ghz_power_recalc(struct rtw89_dev *rtwdev) +{ + struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory; + enum rtw89_reg_6ghz_power sel; + const struct rtw89_chan *chan; + struct rtw89_vif *rtwvif; + int count = 0; + + rtw89_for_each_rtwvif(rtwdev, rtwvif) { + chan = rtw89_chan_get(rtwdev, rtwvif->sub_entity_idx); + if (chan->band_type != RTW89_BAND_6G) + continue; + + if (count != 0 && rtwvif->reg_6ghz_power == sel) + continue; + + sel = rtwvif->reg_6ghz_power; + count++; + } + + if (count != 1) + sel = RTW89_REG_6GHZ_POWER_DFLT; + + if (regulatory->reg_6ghz_power == sel) + return; + + rtw89_debug(rtwdev, RTW89_DBG_REGD, + "recalc 6 GHz reg power type to %d\n", sel); + + regulatory->reg_6ghz_power = sel; + + rtw89_core_set_chip_txpwr(rtwdev); +} + +void rtw89_reg_6ghz_power_recalc(struct rtw89_dev *rtwdev, + struct rtw89_vif *rtwvif, bool active) +{ + struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); + + lockdep_assert_held(&rtwdev->mutex); + + if (active) { + switch (vif->bss_conf.power_type) { + case IEEE80211_REG_VLP_AP: + rtwvif->reg_6ghz_power = RTW89_REG_6GHZ_POWER_VLP; + break; + case IEEE80211_REG_LPI_AP: + rtwvif->reg_6ghz_power = RTW89_REG_6GHZ_POWER_LPI; + break; + case IEEE80211_REG_SP_AP: + rtwvif->reg_6ghz_power = RTW89_REG_6GHZ_POWER_STD; + break; + default: + rtwvif->reg_6ghz_power = RTW89_REG_6GHZ_POWER_DFLT; + break; + } + } else { + rtwvif->reg_6ghz_power = RTW89_REG_6GHZ_POWER_DFLT; + } + + __rtw89_reg_6ghz_power_recalc(rtwdev); +} diff --git a/drivers/net/wireless/realtek/rtw89/rtw8851b.c b/drivers/net/wireless/realtek/rtw89/rtw8851b.c new file mode 100644 index 0000000000000000000000000000000000000000..c3ffcb645ebf74e90778553a8dcc83d610f0ee83 --- /dev/null +++ b/drivers/net/wireless/realtek/rtw89/rtw8851b.c @@ -0,0 +1,2442 @@ +// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause +/* Copyright(c) 2022-2023 Realtek Corporation + */ + +#include "coex.h" +#include "efuse.h" +#include "fw.h" +#include "mac.h" +#include "phy.h" +#include "reg.h" +#include "rtw8851b.h" +#include "rtw8851b_rfk.h" +#include "rtw8851b_rfk_table.h" +#include "rtw8851b_table.h" +#include "txrx.h" +#include "util.h" + +#define RTW8851B_FW_FORMAT_MAX 0 +#define RTW8851B_FW_BASENAME "rtw89/rtw8851b_fw" +#define RTW8851B_MODULE_FIRMWARE \ + RTW8851B_FW_BASENAME ".bin" + +static const struct rtw89_hfc_ch_cfg rtw8851b_hfc_chcfg_pcie[] = { + {5, 343, grp_0}, /* ACH 0 */ + {5, 343, grp_0}, /* ACH 1 */ + {5, 343, grp_0}, /* ACH 2 */ + {5, 343, grp_0}, /* ACH 3 */ + {0, 0, grp_0}, /* ACH 4 */ + {0, 0, grp_0}, /* ACH 5 */ + {0, 0, grp_0}, /* ACH 6 */ + {0, 0, grp_0}, /* ACH 7 */ + {4, 344, grp_0}, /* B0MGQ */ + {4, 344, grp_0}, /* B0HIQ */ + {0, 0, grp_0}, /* B1MGQ */ + {0, 0, grp_0}, /* B1HIQ */ + {40, 0, 0} /* FWCMDQ */ +}; + +static const struct rtw89_hfc_pub_cfg rtw8851b_hfc_pubcfg_pcie = { + 448, /* Group 0 */ + 0, /* Group 1 */ + 448, /* Public Max */ + 0 /* WP threshold */ +}; + +static const struct rtw89_hfc_param_ini rtw8851b_hfc_param_ini_pcie[] = { + [RTW89_QTA_SCC] = {rtw8851b_hfc_chcfg_pcie, &rtw8851b_hfc_pubcfg_pcie, + &rtw89_mac_size.hfc_preccfg_pcie, RTW89_HCIFC_POH}, + [RTW89_QTA_DLFW] = {NULL, NULL, &rtw89_mac_size.hfc_preccfg_pcie, + RTW89_HCIFC_POH}, + [RTW89_QTA_INVALID] = {NULL}, +}; + +static const struct rtw89_dle_mem rtw8851b_dle_mem_pcie[] = { + [RTW89_QTA_SCC] = {RTW89_QTA_SCC, &rtw89_mac_size.wde_size6, + &rtw89_mac_size.ple_size6, &rtw89_mac_size.wde_qt6, + &rtw89_mac_size.wde_qt6, &rtw89_mac_size.ple_qt18, + &rtw89_mac_size.ple_qt58}, + [RTW89_QTA_WOW] = {RTW89_QTA_WOW, &rtw89_mac_size.wde_size6, + &rtw89_mac_size.ple_size6, &rtw89_mac_size.wde_qt6, + &rtw89_mac_size.wde_qt6, &rtw89_mac_size.ple_qt18, + &rtw89_mac_size.ple_qt_51b_wow}, + [RTW89_QTA_DLFW] = {RTW89_QTA_DLFW, &rtw89_mac_size.wde_size9, + &rtw89_mac_size.ple_size8, &rtw89_mac_size.wde_qt4, + &rtw89_mac_size.wde_qt4, &rtw89_mac_size.ple_qt13, + &rtw89_mac_size.ple_qt13}, + [RTW89_QTA_INVALID] = {RTW89_QTA_INVALID, NULL, NULL, NULL, NULL, NULL, + NULL}, +}; + +static const struct rtw89_reg3_def rtw8851b_btc_preagc_en_defs[] = { + {0x46D0, GENMASK(1, 0), 0x3}, + {0x4AD4, GENMASK(31, 0), 0xf}, + {0x4688, GENMASK(23, 16), 0x80}, + {0x4688, GENMASK(31, 24), 0x80}, + {0x4694, GENMASK(7, 0), 0x80}, + {0x4694, GENMASK(15, 8), 0x80}, + {0x4AE4, GENMASK(11, 6), 0x34}, + {0x4AE4, GENMASK(17, 12), 0x0}, + {0x469C, GENMASK(31, 26), 0x34}, +}; + +static DECLARE_PHY_REG3_TBL(rtw8851b_btc_preagc_en_defs); + +static const struct rtw89_reg3_def rtw8851b_btc_preagc_dis_defs[] = { + {0x46D0, GENMASK(1, 0), 0x0}, + {0x4AD4, GENMASK(31, 0), 0x60}, + {0x4688, GENMASK(23, 16), 0x10}, + {0x4690, GENMASK(31, 24), 0x2a}, + {0x4694, GENMASK(15, 8), 0x2a}, + {0x4AE4, GENMASK(11, 6), 0x26}, + {0x4AE4, GENMASK(17, 12), 0x1e}, + {0x469C, GENMASK(31, 26), 0x26}, +}; + +static DECLARE_PHY_REG3_TBL(rtw8851b_btc_preagc_dis_defs); + +static const u32 rtw8851b_h2c_regs[RTW89_H2CREG_MAX] = { + R_AX_H2CREG_DATA0, R_AX_H2CREG_DATA1, R_AX_H2CREG_DATA2, + R_AX_H2CREG_DATA3 +}; + +static const u32 rtw8851b_c2h_regs[RTW89_C2HREG_MAX] = { + R_AX_C2HREG_DATA0, R_AX_C2HREG_DATA1, R_AX_C2HREG_DATA2, + R_AX_C2HREG_DATA3 +}; + +static const struct rtw89_page_regs rtw8851b_page_regs = { + .hci_fc_ctrl = R_AX_HCI_FC_CTRL, + .ch_page_ctrl = R_AX_CH_PAGE_CTRL, + .ach_page_ctrl = R_AX_ACH0_PAGE_CTRL, + .ach_page_info = R_AX_ACH0_PAGE_INFO, + .pub_page_info3 = R_AX_PUB_PAGE_INFO3, + .pub_page_ctrl1 = R_AX_PUB_PAGE_CTRL1, + .pub_page_ctrl2 = R_AX_PUB_PAGE_CTRL2, + .pub_page_info1 = R_AX_PUB_PAGE_INFO1, + .pub_page_info2 = R_AX_PUB_PAGE_INFO2, + .wp_page_ctrl1 = R_AX_WP_PAGE_CTRL1, + .wp_page_ctrl2 = R_AX_WP_PAGE_CTRL2, + .wp_page_info1 = R_AX_WP_PAGE_INFO1, +}; + +static const struct rtw89_reg_def rtw8851b_dcfo_comp = { + R_DCFO_COMP_S0_V2, B_DCFO_COMP_S0_MSK_V2 +}; + +static const struct rtw89_imr_info rtw8851b_imr_info = { + .wdrls_imr_set = B_AX_WDRLS_IMR_SET, + .wsec_imr_reg = R_AX_SEC_DEBUG, + .wsec_imr_set = B_AX_IMR_ERROR, + .mpdu_tx_imr_set = 0, + .mpdu_rx_imr_set = 0, + .sta_sch_imr_set = B_AX_STA_SCHEDULER_IMR_SET, + .txpktctl_imr_b0_reg = R_AX_TXPKTCTL_ERR_IMR_ISR, + .txpktctl_imr_b0_clr = B_AX_TXPKTCTL_IMR_B0_CLR, + .txpktctl_imr_b0_set = B_AX_TXPKTCTL_IMR_B0_SET, + .txpktctl_imr_b1_reg = R_AX_TXPKTCTL_ERR_IMR_ISR_B1, + .txpktctl_imr_b1_clr = B_AX_TXPKTCTL_IMR_B1_CLR, + .txpktctl_imr_b1_set = B_AX_TXPKTCTL_IMR_B1_SET, + .wde_imr_clr = B_AX_WDE_IMR_CLR, + .wde_imr_set = B_AX_WDE_IMR_SET, + .ple_imr_clr = B_AX_PLE_IMR_CLR, + .ple_imr_set = B_AX_PLE_IMR_SET, + .host_disp_imr_clr = B_AX_HOST_DISP_IMR_CLR, + .host_disp_imr_set = B_AX_HOST_DISP_IMR_SET, + .cpu_disp_imr_clr = B_AX_CPU_DISP_IMR_CLR, + .cpu_disp_imr_set = B_AX_CPU_DISP_IMR_SET, + .other_disp_imr_clr = B_AX_OTHER_DISP_IMR_CLR, + .other_disp_imr_set = 0, + .bbrpt_com_err_imr_reg = R_AX_BBRPT_COM_ERR_IMR_ISR, + .bbrpt_chinfo_err_imr_reg = R_AX_BBRPT_CHINFO_ERR_IMR_ISR, + .bbrpt_err_imr_set = 0, + .bbrpt_dfs_err_imr_reg = R_AX_BBRPT_DFS_ERR_IMR_ISR, + .ptcl_imr_clr = B_AX_PTCL_IMR_CLR_ALL, + .ptcl_imr_set = B_AX_PTCL_IMR_SET, + .cdma_imr_0_reg = R_AX_DLE_CTRL, + .cdma_imr_0_clr = B_AX_DLE_IMR_CLR, + .cdma_imr_0_set = B_AX_DLE_IMR_SET, + .cdma_imr_1_reg = 0, + .cdma_imr_1_clr = 0, + .cdma_imr_1_set = 0, + .phy_intf_imr_reg = R_AX_PHYINFO_ERR_IMR, + .phy_intf_imr_clr = 0, + .phy_intf_imr_set = 0, + .rmac_imr_reg = R_AX_RMAC_ERR_ISR, + .rmac_imr_clr = B_AX_RMAC_IMR_CLR, + .rmac_imr_set = B_AX_RMAC_IMR_SET, + .tmac_imr_reg = R_AX_TMAC_ERR_IMR_ISR, + .tmac_imr_clr = B_AX_TMAC_IMR_CLR, + .tmac_imr_set = B_AX_TMAC_IMR_SET, +}; + +static const struct rtw89_xtal_info rtw8851b_xtal_info = { + .xcap_reg = R_AX_XTAL_ON_CTRL3, + .sc_xo_mask = B_AX_XTAL_SC_XO_A_BLOCK_MASK, + .sc_xi_mask = B_AX_XTAL_SC_XI_A_BLOCK_MASK, +}; + +static const struct rtw89_rrsr_cfgs rtw8851b_rrsr_cfgs = { + .ref_rate = {R_AX_TRXPTCL_RRSR_CTL_0, B_AX_WMAC_RESP_REF_RATE_SEL, 0}, + .rsc = {R_AX_TRXPTCL_RRSR_CTL_0, B_AX_WMAC_RESP_RSC_MASK, 2}, +}; + +static const struct rtw89_dig_regs rtw8851b_dig_regs = { + .seg0_pd_reg = R_SEG0R_PD_V1, + .pd_lower_bound_mask = B_SEG0R_PD_LOWER_BOUND_MSK, + .pd_spatial_reuse_en = B_SEG0R_PD_SPATIAL_REUSE_EN_MSK_V1, + .p0_lna_init = {R_PATH0_LNA_INIT_V1, B_PATH0_LNA_INIT_IDX_MSK}, + .p1_lna_init = {R_PATH1_LNA_INIT_V1, B_PATH1_LNA_INIT_IDX_MSK}, + .p0_tia_init = {R_PATH0_TIA_INIT_V1, B_PATH0_TIA_INIT_IDX_MSK_V1}, + .p1_tia_init = {R_PATH1_TIA_INIT_V1, B_PATH1_TIA_INIT_IDX_MSK_V1}, + .p0_rxb_init = {R_PATH0_RXB_INIT_V1, B_PATH0_RXB_INIT_IDX_MSK_V1}, + .p1_rxb_init = {R_PATH1_RXB_INIT_V1, B_PATH1_RXB_INIT_IDX_MSK_V1}, + .p0_p20_pagcugc_en = {R_PATH0_P20_FOLLOW_BY_PAGCUGC_V2, + B_PATH0_P20_FOLLOW_BY_PAGCUGC_EN_MSK}, + .p0_s20_pagcugc_en = {R_PATH0_S20_FOLLOW_BY_PAGCUGC_V2, + B_PATH0_S20_FOLLOW_BY_PAGCUGC_EN_MSK}, + .p1_p20_pagcugc_en = {R_PATH1_P20_FOLLOW_BY_PAGCUGC_V2, + B_PATH1_P20_FOLLOW_BY_PAGCUGC_EN_MSK}, + .p1_s20_pagcugc_en = {R_PATH1_S20_FOLLOW_BY_PAGCUGC_V2, + B_PATH1_S20_FOLLOW_BY_PAGCUGC_EN_MSK}, +}; + +static const struct rtw89_btc_rf_trx_para rtw89_btc_8851b_rf_ul[] = { + {255, 0, 0, 7}, /* 0 -> original */ + {255, 2, 0, 7}, /* 1 -> for BT-connected ACI issue && BTG co-rx */ + {255, 0, 0, 7}, /* 2 ->reserved for shared-antenna */ + {255, 0, 0, 7}, /* 3- >reserved for shared-antenna */ + {255, 0, 0, 7}, /* 4 ->reserved for shared-antenna */ + {255, 1, 0, 7}, /* the below id is for non-shared-antenna free-run */ + {6, 1, 0, 7}, + {13, 1, 0, 7}, + {13, 1, 0, 7} +}; + +static const struct rtw89_btc_rf_trx_para rtw89_btc_8851b_rf_dl[] = { + {255, 0, 0, 7}, /* 0 -> original */ + {255, 2, 0, 7}, /* 1 -> reserved for shared-antenna */ + {255, 0, 0, 7}, /* 2 ->reserved for shared-antenna */ + {255, 0, 0, 7}, /* 3- >reserved for shared-antenna */ + {255, 0, 0, 7}, /* 4 ->reserved for shared-antenna */ + {255, 1, 0, 7}, /* the below id is for non-shared-antenna free-run */ + {255, 1, 0, 7}, + {255, 1, 0, 7}, + {255, 1, 0, 7} +}; + +static const struct rtw89_btc_fbtc_mreg rtw89_btc_8851b_mon_reg[] = { + RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xda24), + RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xda28), + RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xda2c), + RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xda30), + RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xda4c), + RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xda10), + RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xda20), + RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xda34), + RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xcef4), + RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0x8424), + RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xd200), + RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xd220), + RTW89_DEF_FBTC_MREG(REG_BB, 4, 0x980), + RTW89_DEF_FBTC_MREG(REG_BB, 4, 0x4738), + RTW89_DEF_FBTC_MREG(REG_BB, 4, 0x4688), + RTW89_DEF_FBTC_MREG(REG_BB, 4, 0x4694), +}; + +static const u8 rtw89_btc_8851b_wl_rssi_thres[BTC_WL_RSSI_THMAX] = {70, 60, 50, 40}; +static const u8 rtw89_btc_8851b_bt_rssi_thres[BTC_BT_RSSI_THMAX] = {50, 40, 30, 20}; + +static int rtw8851b_pwr_on_func(struct rtw89_dev *rtwdev) +{ + u32 val32; + u8 val8; + u32 ret; + + rtw89_write32_clr(rtwdev, R_AX_SYS_PW_CTRL, B_AX_AFSM_WLSUS_EN | + B_AX_AFSM_PCIE_SUS_EN); + rtw89_write32_set(rtwdev, R_AX_SYS_PW_CTRL, B_AX_DIS_WLBT_PDNSUSEN_SOPC); + rtw89_write32_set(rtwdev, R_AX_WLLPS_CTRL, B_AX_DIS_WLBT_LPSEN_LOPC); + rtw89_write32_clr(rtwdev, R_AX_SYS_PW_CTRL, B_AX_APDM_HPDN); + rtw89_write32_clr(rtwdev, R_AX_SYS_PW_CTRL, B_AX_APFM_SWLPS); + + ret = read_poll_timeout(rtw89_read32, val32, val32 & B_AX_RDY_SYSPWR, + 1000, 20000, false, rtwdev, R_AX_SYS_PW_CTRL); + if (ret) + return ret; + + rtw89_write32_set(rtwdev, R_AX_SYS_PW_CTRL, B_AX_EN_WLON); + rtw89_write32_set(rtwdev, R_AX_SYS_PW_CTRL, B_AX_APFN_ONMAC); + + ret = read_poll_timeout(rtw89_read32, val32, !(val32 & B_AX_APFN_ONMAC), + 1000, 20000, false, rtwdev, R_AX_SYS_PW_CTRL); + if (ret) + return ret; + + rtw89_write8_set(rtwdev, R_AX_PLATFORM_ENABLE, B_AX_PLATFORM_EN); + rtw89_write8_clr(rtwdev, R_AX_PLATFORM_ENABLE, B_AX_PLATFORM_EN); + rtw89_write8_set(rtwdev, R_AX_PLATFORM_ENABLE, B_AX_PLATFORM_EN); + rtw89_write8_clr(rtwdev, R_AX_PLATFORM_ENABLE, B_AX_PLATFORM_EN); + + rtw89_write8_set(rtwdev, R_AX_PLATFORM_ENABLE, B_AX_PLATFORM_EN); + rtw89_write32_clr(rtwdev, R_AX_SYS_SDIO_CTRL, B_AX_PCIE_CALIB_EN_V1); + + ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_ANAPAR_WL, XTAL_SI_OFF_WEI, + XTAL_SI_OFF_WEI); + if (ret) + return ret; + ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_ANAPAR_WL, XTAL_SI_OFF_EI, + XTAL_SI_OFF_EI); + if (ret) + return ret; + ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_ANAPAR_WL, 0, XTAL_SI_RFC2RF); + if (ret) + return ret; + ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_ANAPAR_WL, XTAL_SI_PON_WEI, + XTAL_SI_PON_WEI); + if (ret) + return ret; + ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_ANAPAR_WL, XTAL_SI_PON_EI, + XTAL_SI_PON_EI); + if (ret) + return ret; + ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_ANAPAR_WL, 0, XTAL_SI_SRAM2RFC); + if (ret) + return ret; + ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_SRAM_CTRL, 0, XTAL_SI_SRAM_DIS); + if (ret) + return ret; + ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_XTAL_XMD_2, 0, XTAL_SI_LDO_LPS); + if (ret) + return ret; + ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_XTAL_XMD_4, 0, XTAL_SI_LPS_CAP); + if (ret) + return ret; + ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_XTAL_DRV, 0, XTAL_SI_DRV_LATCH); + if (ret) + return ret; + + rtw89_write32_set(rtwdev, R_AX_PMC_DBG_CTRL2, B_AX_SYSON_DIS_PMCR_AX_WRMSK); + rtw89_write32_set(rtwdev, R_AX_SYS_ISO_CTRL, B_AX_ISO_EB2CORE); + rtw89_write32_clr(rtwdev, R_AX_SYS_ISO_CTRL, B_AX_PWC_EV2EF_B15); + + fsleep(1000); + + rtw89_write32_clr(rtwdev, R_AX_SYS_ISO_CTRL, B_AX_PWC_EV2EF_B14); + rtw89_write32_clr(rtwdev, R_AX_PMC_DBG_CTRL2, B_AX_SYSON_DIS_PMCR_AX_WRMSK); + rtw89_write32_set(rtwdev, R_AX_GPIO0_16_EECS_EESK_LED1_PULL_LOW_EN, + B_AX_GPIO10_PULL_LOW_EN | B_AX_GPIO16_PULL_LOW_EN_V1); + + if (rtwdev->hal.cv == CHIP_CAV) { + ret = rtw89_read_efuse_ver(rtwdev, &val8); + if (!ret) + rtwdev->hal.cv = val8; + } + + rtw89_write32_clr(rtwdev, R_AX_WLAN_XTAL_SI_CONFIG, + B_AX_XTAL_SI_ADDR_NOT_CHK); + if (rtwdev->hal.cv != CHIP_CAV) { + rtw89_write32_set(rtwdev, R_AX_SPSLDO_ON_CTRL1, B_AX_FPWMDELAY); + rtw89_write32_set(rtwdev, R_AX_SPSANA_ON_CTRL1, B_AX_FPWMDELAY); + } + + rtw89_write32_set(rtwdev, R_AX_DMAC_FUNC_EN, + B_AX_MAC_FUNC_EN | B_AX_DMAC_FUNC_EN | B_AX_MPDU_PROC_EN | + B_AX_WD_RLS_EN | B_AX_DLE_WDE_EN | B_AX_TXPKT_CTRL_EN | + B_AX_STA_SCH_EN | B_AX_DLE_PLE_EN | B_AX_PKT_BUF_EN | + B_AX_DMAC_TBL_EN | B_AX_PKT_IN_EN | B_AX_DLE_CPUIO_EN | + B_AX_DISPATCHER_EN | B_AX_BBRPT_EN | B_AX_MAC_SEC_EN | + B_AX_DMACREG_GCKEN); + rtw89_write32_set(rtwdev, R_AX_CMAC_FUNC_EN, + B_AX_CMAC_EN | B_AX_CMAC_TXEN | B_AX_CMAC_RXEN | + B_AX_FORCE_CMACREG_GCKEN | B_AX_PHYINTF_EN | B_AX_CMAC_DMA_EN | + B_AX_PTCLTOP_EN | B_AX_SCHEDULER_EN | B_AX_TMAC_EN | + B_AX_RMAC_EN); + + rtw89_write32_mask(rtwdev, R_AX_EECS_EESK_FUNC_SEL, B_AX_PINMUX_EESK_FUNC_SEL_MASK, + PINMUX_EESK_FUNC_SEL_BT_LOG); + + return 0; +} + +static void rtw8851b_patch_swr_pfm2pwm(struct rtw89_dev *rtwdev) +{ + rtw89_write32_set(rtwdev, R_AX_SYS_PW_CTRL, B_AX_SOP_PWMM_DSWR); + rtw89_write32_set(rtwdev, R_AX_SYS_PW_CTRL, B_AX_SOP_ASWRM); + rtw89_write32_set(rtwdev, R_AX_WLLPS_CTRL, B_AX_LPSOP_DSWRM); + rtw89_write32_set(rtwdev, R_AX_WLLPS_CTRL, B_AX_LPSOP_ASWRM); +} + +static int rtw8851b_pwr_off_func(struct rtw89_dev *rtwdev) +{ + u32 val32; + u32 ret; + + ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_ANAPAR_WL, XTAL_SI_RFC2RF, + XTAL_SI_RFC2RF); + if (ret) + return ret; + ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_ANAPAR_WL, 0, XTAL_SI_OFF_EI); + if (ret) + return ret; + ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_ANAPAR_WL, 0, XTAL_SI_OFF_WEI); + if (ret) + return ret; + ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_WL_RFC_S0, 0, XTAL_SI_RF00); + if (ret) + return ret; + ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_ANAPAR_WL, XTAL_SI_SRAM2RFC, + XTAL_SI_SRAM2RFC); + if (ret) + return ret; + ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_ANAPAR_WL, 0, XTAL_SI_PON_EI); + if (ret) + return ret; + ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_ANAPAR_WL, 0, XTAL_SI_PON_WEI); + if (ret) + return ret; + + rtw89_write32_set(rtwdev, R_AX_WLAN_XTAL_SI_CONFIG, + B_AX_XTAL_SI_ADDR_NOT_CHK); + rtw89_write32_set(rtwdev, R_AX_SYS_PW_CTRL, B_AX_EN_WLON); + rtw89_write32_clr(rtwdev, R_AX_WLRF_CTRL, B_AX_AFC_AFEDIG); + rtw89_write8_clr(rtwdev, R_AX_SYS_FUNC_EN, B_AX_FEN_BB_GLB_RSTN | B_AX_FEN_BBRSTB); + + rtw89_write32_set(rtwdev, R_AX_SYS_PW_CTRL, B_AX_APFM_OFFMAC); + + ret = read_poll_timeout(rtw89_read32, val32, !(val32 & B_AX_APFM_OFFMAC), + 1000, 20000, false, rtwdev, R_AX_SYS_PW_CTRL); + if (ret) + return ret; + + rtw89_write32(rtwdev, R_AX_WLLPS_CTRL, SW_LPS_OPTION); + + if (rtwdev->hal.cv == CHIP_CAV) { + rtw8851b_patch_swr_pfm2pwm(rtwdev); + } else { + rtw89_write32_set(rtwdev, R_AX_SPSLDO_ON_CTRL1, B_AX_FPWMDELAY); + rtw89_write32_set(rtwdev, R_AX_SPSANA_ON_CTRL1, B_AX_FPWMDELAY); + } + + rtw89_write32_set(rtwdev, R_AX_SYS_PW_CTRL, B_AX_APFM_SWLPS); + + return 0; +} + +static void rtw8851b_efuse_parsing(struct rtw89_efuse *efuse, + struct rtw8851b_efuse *map) +{ + ether_addr_copy(efuse->addr, map->e.mac_addr); + efuse->rfe_type = map->rfe_type; + efuse->xtal_cap = map->xtal_k; +} + +static void rtw8851b_efuse_parsing_tssi(struct rtw89_dev *rtwdev, + struct rtw8851b_efuse *map) +{ + struct rtw89_tssi_info *tssi = &rtwdev->tssi; + struct rtw8851b_tssi_offset *ofst[] = {&map->path_a_tssi}; + u8 i, j; + + tssi->thermal[RF_PATH_A] = map->path_a_therm; + + for (i = 0; i < RF_PATH_NUM_8851B; i++) { + memcpy(tssi->tssi_cck[i], ofst[i]->cck_tssi, + sizeof(ofst[i]->cck_tssi)); + + for (j = 0; j < TSSI_CCK_CH_GROUP_NUM; j++) + rtw89_debug(rtwdev, RTW89_DBG_TSSI, + "[TSSI][EFUSE] path=%d cck[%d]=0x%x\n", + i, j, tssi->tssi_cck[i][j]); + + memcpy(tssi->tssi_mcs[i], ofst[i]->bw40_tssi, + sizeof(ofst[i]->bw40_tssi)); + memcpy(tssi->tssi_mcs[i] + TSSI_MCS_2G_CH_GROUP_NUM, + ofst[i]->bw40_1s_tssi_5g, sizeof(ofst[i]->bw40_1s_tssi_5g)); + + for (j = 0; j < TSSI_MCS_CH_GROUP_NUM; j++) + rtw89_debug(rtwdev, RTW89_DBG_TSSI, + "[TSSI][EFUSE] path=%d mcs[%d]=0x%x\n", + i, j, tssi->tssi_mcs[i][j]); + } +} + +static bool _decode_efuse_gain(u8 data, s8 *high, s8 *low) +{ + if (high) + *high = sign_extend32(u8_get_bits(data, GENMASK(7, 4)), 3); + if (low) + *low = sign_extend32(u8_get_bits(data, GENMASK(3, 0)), 3); + + return data != 0xff; +} + +static void rtw8851b_efuse_parsing_gain_offset(struct rtw89_dev *rtwdev, + struct rtw8851b_efuse *map) +{ + struct rtw89_phy_efuse_gain *gain = &rtwdev->efuse_gain; + bool valid = false; + + valid |= _decode_efuse_gain(map->rx_gain_2g_cck, + &gain->offset[RF_PATH_A][RTW89_GAIN_OFFSET_2G_CCK], + NULL); + valid |= _decode_efuse_gain(map->rx_gain_2g_ofdm, + &gain->offset[RF_PATH_A][RTW89_GAIN_OFFSET_2G_OFDM], + NULL); + valid |= _decode_efuse_gain(map->rx_gain_5g_low, + &gain->offset[RF_PATH_A][RTW89_GAIN_OFFSET_5G_LOW], + NULL); + valid |= _decode_efuse_gain(map->rx_gain_5g_mid, + &gain->offset[RF_PATH_A][RTW89_GAIN_OFFSET_5G_MID], + NULL); + valid |= _decode_efuse_gain(map->rx_gain_5g_high, + &gain->offset[RF_PATH_A][RTW89_GAIN_OFFSET_5G_HIGH], + NULL); + + gain->offset_valid = valid; +} + +static int rtw8851b_read_efuse(struct rtw89_dev *rtwdev, u8 *log_map) +{ + struct rtw89_efuse *efuse = &rtwdev->efuse; + struct rtw8851b_efuse *map; + + map = (struct rtw8851b_efuse *)log_map; + + efuse->country_code[0] = map->country_code[0]; + efuse->country_code[1] = map->country_code[1]; + rtw8851b_efuse_parsing_tssi(rtwdev, map); + rtw8851b_efuse_parsing_gain_offset(rtwdev, map); + + switch (rtwdev->hci.type) { + case RTW89_HCI_TYPE_PCIE: + rtw8851b_efuse_parsing(efuse, map); + break; + default: + return -EOPNOTSUPP; + } + + rtw89_info(rtwdev, "chip rfe_type is %d\n", efuse->rfe_type); + + return 0; +} + +static void rtw8851b_phycap_parsing_tssi(struct rtw89_dev *rtwdev, u8 *phycap_map) +{ + struct rtw89_tssi_info *tssi = &rtwdev->tssi; + static const u32 tssi_trim_addr[RF_PATH_NUM_8851B] = {0x5D6}; + u32 addr = rtwdev->chip->phycap_addr; + bool pg = false; + u32 ofst; + u8 i, j; + + for (i = 0; i < RF_PATH_NUM_8851B; i++) { + for (j = 0; j < TSSI_TRIM_CH_GROUP_NUM; j++) { + /* addrs are in decreasing order */ + ofst = tssi_trim_addr[i] - addr - j; + tssi->tssi_trim[i][j] = phycap_map[ofst]; + + if (phycap_map[ofst] != 0xff) + pg = true; + } + } + + if (!pg) { + memset(tssi->tssi_trim, 0, sizeof(tssi->tssi_trim)); + rtw89_debug(rtwdev, RTW89_DBG_TSSI, + "[TSSI][TRIM] no PG, set all trim info to 0\n"); + } + + for (i = 0; i < RF_PATH_NUM_8851B; i++) + for (j = 0; j < TSSI_TRIM_CH_GROUP_NUM; j++) + rtw89_debug(rtwdev, RTW89_DBG_TSSI, + "[TSSI] path=%d idx=%d trim=0x%x addr=0x%x\n", + i, j, tssi->tssi_trim[i][j], + tssi_trim_addr[i] - j); +} + +static void rtw8851b_phycap_parsing_thermal_trim(struct rtw89_dev *rtwdev, + u8 *phycap_map) +{ + struct rtw89_power_trim_info *info = &rtwdev->pwr_trim; + static const u32 thm_trim_addr[RF_PATH_NUM_8851B] = {0x5DF}; + u32 addr = rtwdev->chip->phycap_addr; + u8 i; + + for (i = 0; i < RF_PATH_NUM_8851B; i++) { + info->thermal_trim[i] = phycap_map[thm_trim_addr[i] - addr]; + + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[THERMAL][TRIM] path=%d thermal_trim=0x%x\n", + i, info->thermal_trim[i]); + + if (info->thermal_trim[i] != 0xff) + info->pg_thermal_trim = true; + } +} + +static void rtw8851b_thermal_trim(struct rtw89_dev *rtwdev) +{ +#define __thm_setting(raw) \ +({ \ + u8 __v = (raw); \ + ((__v & 0x1) << 3) | ((__v & 0x1f) >> 1); \ +}) + struct rtw89_power_trim_info *info = &rtwdev->pwr_trim; + u8 i, val; + + if (!info->pg_thermal_trim) { + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[THERMAL][TRIM] no PG, do nothing\n"); + + return; + } + + for (i = 0; i < RF_PATH_NUM_8851B; i++) { + val = __thm_setting(info->thermal_trim[i]); + rtw89_write_rf(rtwdev, i, RR_TM2, RR_TM2_OFF, val); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[THERMAL][TRIM] path=%d thermal_setting=0x%x\n", + i, val); + } +#undef __thm_setting +} + +static void rtw8851b_phycap_parsing_pa_bias_trim(struct rtw89_dev *rtwdev, + u8 *phycap_map) +{ + struct rtw89_power_trim_info *info = &rtwdev->pwr_trim; + static const u32 pabias_trim_addr[] = {0x5DE}; + u32 addr = rtwdev->chip->phycap_addr; + u8 i; + + for (i = 0; i < RF_PATH_NUM_8851B; i++) { + info->pa_bias_trim[i] = phycap_map[pabias_trim_addr[i] - addr]; + + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[PA_BIAS][TRIM] path=%d pa_bias_trim=0x%x\n", + i, info->pa_bias_trim[i]); + + if (info->pa_bias_trim[i] != 0xff) + info->pg_pa_bias_trim = true; + } +} + +static void rtw8851b_pa_bias_trim(struct rtw89_dev *rtwdev) +{ + struct rtw89_power_trim_info *info = &rtwdev->pwr_trim; + u8 pabias_2g, pabias_5g; + u8 i; + + if (!info->pg_pa_bias_trim) { + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[PA_BIAS][TRIM] no PG, do nothing\n"); + + return; + } + + for (i = 0; i < RF_PATH_NUM_8851B; i++) { + pabias_2g = u8_get_bits(info->pa_bias_trim[i], GENMASK(3, 0)); + pabias_5g = u8_get_bits(info->pa_bias_trim[i], GENMASK(7, 4)); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[PA_BIAS][TRIM] path=%d 2G=0x%x 5G=0x%x\n", + i, pabias_2g, pabias_5g); + + rtw89_write_rf(rtwdev, i, RR_BIASA, RR_BIASA_TXG, pabias_2g); + rtw89_write_rf(rtwdev, i, RR_BIASA, RR_BIASA_TXA, pabias_5g); + } +} + +static void rtw8851b_phycap_parsing_gain_comp(struct rtw89_dev *rtwdev, u8 *phycap_map) +{ + static const u32 comp_addrs[][RTW89_SUBBAND_2GHZ_5GHZ_NR] = { + {0x5BB, 0x5BA, 0, 0x5B9, 0x5B8}, + }; + struct rtw89_phy_efuse_gain *gain = &rtwdev->efuse_gain; + u32 phycap_addr = rtwdev->chip->phycap_addr; + bool valid = false; + int path, i; + u8 data; + + for (path = 0; path < BB_PATH_NUM_8851B; path++) + for (i = 0; i < RTW89_SUBBAND_2GHZ_5GHZ_NR; i++) { + if (comp_addrs[path][i] == 0) + continue; + + data = phycap_map[comp_addrs[path][i] - phycap_addr]; + valid |= _decode_efuse_gain(data, NULL, + &gain->comp[path][i]); + } + + gain->comp_valid = valid; +} + +static int rtw8851b_read_phycap(struct rtw89_dev *rtwdev, u8 *phycap_map) +{ + rtw8851b_phycap_parsing_tssi(rtwdev, phycap_map); + rtw8851b_phycap_parsing_thermal_trim(rtwdev, phycap_map); + rtw8851b_phycap_parsing_pa_bias_trim(rtwdev, phycap_map); + rtw8851b_phycap_parsing_gain_comp(rtwdev, phycap_map); + + return 0; +} + +static void rtw8851b_set_bb_gpio(struct rtw89_dev *rtwdev, u8 gpio_idx, bool inv, + u8 src_sel) +{ + u32 addr, mask; + + if (gpio_idx >= 32) + return; + + /* 2 continual 32-bit registers for 32 GPIOs, and each GPIO occupies 2 bits */ + addr = R_RFE_SEL0_A2 + (gpio_idx / 16) * sizeof(u32); + mask = B_RFE_SEL0_MASK << (gpio_idx % 16) * 2; + + rtw89_phy_write32_mask(rtwdev, addr, mask, RF_PATH_A); + rtw89_phy_write32_mask(rtwdev, R_RFE_INV0, BIT(gpio_idx), inv); + + /* 4 continual 32-bit registers for 32 GPIOs, and each GPIO occupies 4 bits */ + addr = R_RFE_SEL0_BASE + (gpio_idx / 8) * sizeof(u32); + mask = B_RFE_SEL0_SRC_MASK << (gpio_idx % 8) * 4; + + rtw89_phy_write32_mask(rtwdev, addr, mask, src_sel); +} + +static void rtw8851b_set_mac_gpio(struct rtw89_dev *rtwdev, u8 func) +{ + static const struct rtw89_reg3_def func16 = { + R_AX_GPIO16_23_FUNC_SEL, B_AX_PINMUX_GPIO16_FUNC_SEL_MASK, BIT(3) + }; + static const struct rtw89_reg3_def func17 = { + R_AX_GPIO16_23_FUNC_SEL, B_AX_PINMUX_GPIO17_FUNC_SEL_MASK, BIT(7) >> 4, + }; + const struct rtw89_reg3_def *def; + + switch (func) { + case 16: + def = &func16; + break; + case 17: + def = &func17; + break; + default: + rtw89_warn(rtwdev, "undefined gpio func %d\n", func); + return; + } + + rtw89_write8_mask(rtwdev, def->addr, def->mask, def->data); +} + +static void rtw8851b_rfe_gpio(struct rtw89_dev *rtwdev) +{ + u8 rfe_type = rtwdev->efuse.rfe_type; + + if (rfe_type > 50) + return; + + if (rfe_type % 3 == 2) { + rtw8851b_set_bb_gpio(rtwdev, 16, true, RFE_SEL0_SRC_ANTSEL_0); + rtw8851b_set_bb_gpio(rtwdev, 17, false, RFE_SEL0_SRC_ANTSEL_0); + + rtw8851b_set_mac_gpio(rtwdev, 16); + rtw8851b_set_mac_gpio(rtwdev, 17); + } +} + +static void rtw8851b_power_trim(struct rtw89_dev *rtwdev) +{ + rtw8851b_thermal_trim(rtwdev); + rtw8851b_pa_bias_trim(rtwdev); +} + +static void rtw8851b_set_channel_mac(struct rtw89_dev *rtwdev, + const struct rtw89_chan *chan, + u8 mac_idx) +{ + u32 sub_carr = rtw89_mac_reg_by_idx(R_AX_TX_SUB_CARRIER_VALUE, mac_idx); + u32 chk_rate = rtw89_mac_reg_by_idx(R_AX_TXRATE_CHK, mac_idx); + u32 rf_mod = rtw89_mac_reg_by_idx(R_AX_WMAC_RFMOD, mac_idx); + u8 txsc20 = 0, txsc40 = 0; + + switch (chan->band_width) { + case RTW89_CHANNEL_WIDTH_80: + txsc40 = rtw89_phy_get_txsc(rtwdev, chan, RTW89_CHANNEL_WIDTH_40); + fallthrough; + case RTW89_CHANNEL_WIDTH_40: + txsc20 = rtw89_phy_get_txsc(rtwdev, chan, RTW89_CHANNEL_WIDTH_20); + break; + default: + break; + } + + switch (chan->band_width) { + case RTW89_CHANNEL_WIDTH_80: + rtw89_write8_mask(rtwdev, rf_mod, B_AX_WMAC_RFMOD_MASK, BIT(1)); + rtw89_write32(rtwdev, sub_carr, txsc20 | (txsc40 << 4)); + break; + case RTW89_CHANNEL_WIDTH_40: + rtw89_write8_mask(rtwdev, rf_mod, B_AX_WMAC_RFMOD_MASK, BIT(0)); + rtw89_write32(rtwdev, sub_carr, txsc20); + break; + case RTW89_CHANNEL_WIDTH_20: + rtw89_write8_clr(rtwdev, rf_mod, B_AX_WMAC_RFMOD_MASK); + rtw89_write32(rtwdev, sub_carr, 0); + break; + default: + break; + } + + if (chan->channel > 14) { + rtw89_write8_clr(rtwdev, chk_rate, B_AX_BAND_MODE); + rtw89_write8_set(rtwdev, chk_rate, + B_AX_CHECK_CCK_EN | B_AX_RTS_LIMIT_IN_OFDM6); + } else { + rtw89_write8_set(rtwdev, chk_rate, B_AX_BAND_MODE); + rtw89_write8_clr(rtwdev, chk_rate, + B_AX_CHECK_CCK_EN | B_AX_RTS_LIMIT_IN_OFDM6); + } +} + +static const u32 rtw8851b_sco_barker_threshold[14] = { + 0x1cfea, 0x1d0e1, 0x1d1d7, 0x1d2cd, 0x1d3c3, 0x1d4b9, 0x1d5b0, 0x1d6a6, + 0x1d79c, 0x1d892, 0x1d988, 0x1da7f, 0x1db75, 0x1ddc4 +}; + +static const u32 rtw8851b_sco_cck_threshold[14] = { + 0x27de3, 0x27f35, 0x28088, 0x281da, 0x2832d, 0x2847f, 0x285d2, 0x28724, + 0x28877, 0x289c9, 0x28b1c, 0x28c6e, 0x28dc1, 0x290ed +}; + +static void rtw8851b_ctrl_sco_cck(struct rtw89_dev *rtwdev, u8 primary_ch) +{ + u8 ch_element = primary_ch - 1; + + rtw89_phy_write32_mask(rtwdev, R_RXSCOBC, B_RXSCOBC_TH, + rtw8851b_sco_barker_threshold[ch_element]); + rtw89_phy_write32_mask(rtwdev, R_RXSCOCCK, B_RXSCOCCK_TH, + rtw8851b_sco_cck_threshold[ch_element]); +} + +static u8 rtw8851b_sco_mapping(u8 central_ch) +{ + if (central_ch == 1) + return 109; + else if (central_ch >= 2 && central_ch <= 6) + return 108; + else if (central_ch >= 7 && central_ch <= 10) + return 107; + else if (central_ch >= 11 && central_ch <= 14) + return 106; + else if (central_ch == 36 || central_ch == 38) + return 51; + else if (central_ch >= 40 && central_ch <= 58) + return 50; + else if (central_ch >= 60 && central_ch <= 64) + return 49; + else if (central_ch == 100 || central_ch == 102) + return 48; + else if (central_ch >= 104 && central_ch <= 126) + return 47; + else if (central_ch >= 128 && central_ch <= 151) + return 46; + else if (central_ch >= 153 && central_ch <= 177) + return 45; + else + return 0; +} + +struct rtw8851b_bb_gain { + u32 gain_g[BB_PATH_NUM_8851B]; + u32 gain_a[BB_PATH_NUM_8851B]; + u32 gain_mask; +}; + +static const struct rtw8851b_bb_gain bb_gain_lna[LNA_GAIN_NUM] = { + { .gain_g = {0x4678}, .gain_a = {0x45DC}, + .gain_mask = 0x00ff0000 }, + { .gain_g = {0x4678}, .gain_a = {0x45DC}, + .gain_mask = 0xff000000 }, + { .gain_g = {0x467C}, .gain_a = {0x4660}, + .gain_mask = 0x000000ff }, + { .gain_g = {0x467C}, .gain_a = {0x4660}, + .gain_mask = 0x0000ff00 }, + { .gain_g = {0x467C}, .gain_a = {0x4660}, + .gain_mask = 0x00ff0000 }, + { .gain_g = {0x467C}, .gain_a = {0x4660}, + .gain_mask = 0xff000000 }, + { .gain_g = {0x4680}, .gain_a = {0x4664}, + .gain_mask = 0x000000ff }, +}; + +static const struct rtw8851b_bb_gain bb_gain_tia[TIA_GAIN_NUM] = { + { .gain_g = {0x4680}, .gain_a = {0x4664}, + .gain_mask = 0x00ff0000 }, + { .gain_g = {0x4680}, .gain_a = {0x4664}, + .gain_mask = 0xff000000 }, +}; + +static void rtw8851b_set_gain_error(struct rtw89_dev *rtwdev, + enum rtw89_subband subband, + enum rtw89_rf_path path) +{ + const struct rtw89_phy_bb_gain_info *gain = &rtwdev->bb_gain; + u8 gain_band = rtw89_subband_to_bb_gain_band(subband); + s32 val; + u32 reg; + u32 mask; + int i; + + for (i = 0; i < LNA_GAIN_NUM; i++) { + if (subband == RTW89_CH_2G) + reg = bb_gain_lna[i].gain_g[path]; + else + reg = bb_gain_lna[i].gain_a[path]; + + mask = bb_gain_lna[i].gain_mask; + val = gain->lna_gain[gain_band][path][i]; + rtw89_phy_write32_mask(rtwdev, reg, mask, val); + } + + for (i = 0; i < TIA_GAIN_NUM; i++) { + if (subband == RTW89_CH_2G) + reg = bb_gain_tia[i].gain_g[path]; + else + reg = bb_gain_tia[i].gain_a[path]; + + mask = bb_gain_tia[i].gain_mask; + val = gain->tia_gain[gain_band][path][i]; + rtw89_phy_write32_mask(rtwdev, reg, mask, val); + } +} + +static void rtw8851b_set_gain_offset(struct rtw89_dev *rtwdev, + enum rtw89_subband subband, + enum rtw89_phy_idx phy_idx) +{ + static const u32 rssi_ofst_addr[] = {R_PATH0_G_TIA1_LNA6_OP1DB_V1}; + static const u32 gain_err_addr[] = {R_P0_AGC_RSVD}; + struct rtw89_phy_efuse_gain *efuse_gain = &rtwdev->efuse_gain; + enum rtw89_gain_offset gain_ofdm_band; + s32 offset_ofdm, offset_cck; + s32 offset_a; + s32 tmp; + u8 path; + + if (!efuse_gain->comp_valid) + goto next; + + for (path = RF_PATH_A; path < BB_PATH_NUM_8851B; path++) { + tmp = efuse_gain->comp[path][subband]; + tmp = clamp_t(s32, tmp << 2, S8_MIN, S8_MAX); + rtw89_phy_write32_mask(rtwdev, gain_err_addr[path], MASKBYTE0, tmp); + } + +next: + if (!efuse_gain->offset_valid) + return; + + gain_ofdm_band = rtw89_subband_to_gain_offset_band_of_ofdm(subband); + + offset_a = -efuse_gain->offset[RF_PATH_A][gain_ofdm_band]; + + tmp = -((offset_a << 2) + (efuse_gain->offset_base[RTW89_PHY_0] >> 2)); + tmp = clamp_t(s32, tmp, S8_MIN, S8_MAX); + rtw89_phy_write32_mask(rtwdev, rssi_ofst_addr[RF_PATH_A], B_PATH0_R_G_OFST_MASK, tmp); + + offset_ofdm = -efuse_gain->offset[RF_PATH_A][gain_ofdm_band]; + offset_cck = -efuse_gain->offset[RF_PATH_A][0]; + + tmp = (offset_ofdm << 4) + efuse_gain->offset_base[RTW89_PHY_0]; + tmp = clamp_t(s32, tmp, S8_MIN, S8_MAX); + rtw89_phy_write32_idx(rtwdev, R_P0_RPL1, B_P0_RPL1_BIAS_MASK, tmp, phy_idx); + + tmp = (offset_ofdm << 4) + efuse_gain->rssi_base[RTW89_PHY_0]; + tmp = clamp_t(s32, tmp, S8_MIN, S8_MAX); + rtw89_phy_write32_idx(rtwdev, R_P1_RPL1, B_P0_RPL1_BIAS_MASK, tmp, phy_idx); + + if (subband == RTW89_CH_2G) { + tmp = (offset_cck << 3) + (efuse_gain->offset_base[RTW89_PHY_0] >> 1); + tmp = clamp_t(s32, tmp, S8_MIN >> 1, S8_MAX >> 1); + rtw89_phy_write32_mask(rtwdev, R_RX_RPL_OFST, + B_RX_RPL_OFST_CCK_MASK, tmp); + } +} + +static +void rtw8851b_set_rxsc_rpl_comp(struct rtw89_dev *rtwdev, enum rtw89_subband subband) +{ + const struct rtw89_phy_bb_gain_info *gain = &rtwdev->bb_gain; + u8 band = rtw89_subband_to_bb_gain_band(subband); + u32 val; + + val = u32_encode_bits(gain->rpl_ofst_20[band][RF_PATH_A], B_P0_RPL1_20_MASK) | + u32_encode_bits(gain->rpl_ofst_40[band][RF_PATH_A][0], B_P0_RPL1_40_MASK) | + u32_encode_bits(gain->rpl_ofst_40[band][RF_PATH_A][1], B_P0_RPL1_41_MASK); + val >>= B_P0_RPL1_SHIFT; + rtw89_phy_write32_mask(rtwdev, R_P0_RPL1, B_P0_RPL1_MASK, val); + rtw89_phy_write32_mask(rtwdev, R_P1_RPL1, B_P0_RPL1_MASK, val); + + val = u32_encode_bits(gain->rpl_ofst_40[band][RF_PATH_A][2], B_P0_RTL2_42_MASK) | + u32_encode_bits(gain->rpl_ofst_80[band][RF_PATH_A][0], B_P0_RTL2_80_MASK) | + u32_encode_bits(gain->rpl_ofst_80[band][RF_PATH_A][1], B_P0_RTL2_81_MASK) | + u32_encode_bits(gain->rpl_ofst_80[band][RF_PATH_A][10], B_P0_RTL2_8A_MASK); + rtw89_phy_write32(rtwdev, R_P0_RPL2, val); + rtw89_phy_write32(rtwdev, R_P1_RPL2, val); + + val = u32_encode_bits(gain->rpl_ofst_80[band][RF_PATH_A][2], B_P0_RTL3_82_MASK) | + u32_encode_bits(gain->rpl_ofst_80[band][RF_PATH_A][3], B_P0_RTL3_83_MASK) | + u32_encode_bits(gain->rpl_ofst_80[band][RF_PATH_A][4], B_P0_RTL3_84_MASK) | + u32_encode_bits(gain->rpl_ofst_80[band][RF_PATH_A][9], B_P0_RTL3_89_MASK); + rtw89_phy_write32(rtwdev, R_P0_RPL3, val); + rtw89_phy_write32(rtwdev, R_P1_RPL3, val); +} + +static void rtw8851b_ctrl_ch(struct rtw89_dev *rtwdev, + const struct rtw89_chan *chan, + enum rtw89_phy_idx phy_idx) +{ + u8 subband = chan->subband_type; + u8 central_ch = chan->channel; + bool is_2g = central_ch <= 14; + u8 sco_comp; + + if (is_2g) + rtw89_phy_write32_idx(rtwdev, R_PATH0_BAND_SEL_V1, + B_PATH0_BAND_SEL_MSK_V1, 1, phy_idx); + else + rtw89_phy_write32_idx(rtwdev, R_PATH0_BAND_SEL_V1, + B_PATH0_BAND_SEL_MSK_V1, 0, phy_idx); + /* SCO compensate FC setting */ + sco_comp = rtw8851b_sco_mapping(central_ch); + rtw89_phy_write32_idx(rtwdev, R_FC0_BW_V1, B_FC0_BW_INV, sco_comp, phy_idx); + + if (chan->band_type == RTW89_BAND_6G) + return; + + /* CCK parameters */ + if (central_ch == 14) { + rtw89_phy_write32_mask(rtwdev, R_TXFIR0, B_TXFIR_C01, 0x3b13ff); + rtw89_phy_write32_mask(rtwdev, R_TXFIR2, B_TXFIR_C23, 0x1c42de); + rtw89_phy_write32_mask(rtwdev, R_TXFIR4, B_TXFIR_C45, 0xfdb0ad); + rtw89_phy_write32_mask(rtwdev, R_TXFIR6, B_TXFIR_C67, 0xf60f6e); + rtw89_phy_write32_mask(rtwdev, R_TXFIR8, B_TXFIR_C89, 0xfd8f92); + rtw89_phy_write32_mask(rtwdev, R_TXFIRA, B_TXFIR_CAB, 0x2d011); + rtw89_phy_write32_mask(rtwdev, R_TXFIRC, B_TXFIR_CCD, 0x1c02c); + rtw89_phy_write32_mask(rtwdev, R_TXFIRE, B_TXFIR_CEF, 0xfff00a); + } else { + rtw89_phy_write32_mask(rtwdev, R_TXFIR0, B_TXFIR_C01, 0x3d23ff); + rtw89_phy_write32_mask(rtwdev, R_TXFIR2, B_TXFIR_C23, 0x29b354); + rtw89_phy_write32_mask(rtwdev, R_TXFIR4, B_TXFIR_C45, 0xfc1c8); + rtw89_phy_write32_mask(rtwdev, R_TXFIR6, B_TXFIR_C67, 0xfdb053); + rtw89_phy_write32_mask(rtwdev, R_TXFIR8, B_TXFIR_C89, 0xf86f9a); + rtw89_phy_write32_mask(rtwdev, R_TXFIRA, B_TXFIR_CAB, 0xfaef92); + rtw89_phy_write32_mask(rtwdev, R_TXFIRC, B_TXFIR_CCD, 0xfe5fcc); + rtw89_phy_write32_mask(rtwdev, R_TXFIRE, B_TXFIR_CEF, 0xffdff5); + } + + rtw8851b_set_gain_error(rtwdev, subband, RF_PATH_A); + rtw8851b_set_gain_offset(rtwdev, subband, phy_idx); + rtw8851b_set_rxsc_rpl_comp(rtwdev, subband); +} + +static void rtw8851b_bw_setting(struct rtw89_dev *rtwdev, u8 bw) +{ + rtw89_phy_write32_mask(rtwdev, R_P0_CFCH_BW0, B_P0_CFCH_CTL, 0x8); + rtw89_phy_write32_mask(rtwdev, R_P0_CFCH_BW0, B_P0_CFCH_EN, 0x2); + rtw89_phy_write32_mask(rtwdev, R_P0_CFCH_BW0, B_P0_CFCH_BW0, 0x2); + rtw89_phy_write32_mask(rtwdev, R_P0_CFCH_BW1, B_P0_CFCH_BW1, 0x4); + rtw89_phy_write32_mask(rtwdev, R_DRCK, B_DRCK_MUL, 0xf); + rtw89_phy_write32_mask(rtwdev, R_ADCMOD, B_ADCMOD_LP, 0xa); + rtw89_phy_write32_mask(rtwdev, R_P0_RXCK, B_P0_RXCK_ADJ, 0x92); + + switch (bw) { + case RTW89_CHANNEL_WIDTH_5: + rtw89_phy_write32_mask(rtwdev, R_DCIM, B_DCIM_FR, 0x1); + rtw89_phy_write32_mask(rtwdev, R_WDADC, B_WDADC_SEL, 0x0); + rtw89_phy_write32_mask(rtwdev, R_ADDCK0D, B_ADDCK_DS, 0x1); + break; + case RTW89_CHANNEL_WIDTH_10: + rtw89_phy_write32_mask(rtwdev, R_DCIM, B_DCIM_FR, 0x1); + rtw89_phy_write32_mask(rtwdev, R_WDADC, B_WDADC_SEL, 0x1); + rtw89_phy_write32_mask(rtwdev, R_ADDCK0D, B_ADDCK_DS, 0x0); + break; + case RTW89_CHANNEL_WIDTH_20: + rtw89_phy_write32_mask(rtwdev, R_DCIM, B_DCIM_FR, 0x2); + rtw89_phy_write32_mask(rtwdev, R_WDADC, B_WDADC_SEL, 0x2); + rtw89_phy_write32_mask(rtwdev, R_ADDCK0D, B_ADDCK_DS, 0x0); + break; + case RTW89_CHANNEL_WIDTH_40: + rtw89_phy_write32_mask(rtwdev, R_DCIM, B_DCIM_FR, 0x2); + rtw89_phy_write32_mask(rtwdev, R_WDADC, B_WDADC_SEL, 0x2); + rtw89_phy_write32_mask(rtwdev, R_ADDCK0D, B_ADDCK_DS, 0x0); + break; + case RTW89_CHANNEL_WIDTH_80: + rtw89_phy_write32_mask(rtwdev, R_DCIM, B_DCIM_FR, 0x0); + rtw89_phy_write32_mask(rtwdev, R_WDADC, B_WDADC_SEL, 0x2); + rtw89_phy_write32_mask(rtwdev, R_ADDCK0D, B_ADDCK_DS, 0x0); + break; + default: + rtw89_warn(rtwdev, "Fail to set ADC\n"); + } +} + +static void rtw8851b_ctrl_bw(struct rtw89_dev *rtwdev, u8 pri_ch, u8 bw, + enum rtw89_phy_idx phy_idx) +{ + switch (bw) { + case RTW89_CHANNEL_WIDTH_5: + rtw89_phy_write32_idx(rtwdev, R_FC0_BW_V1, B_FC0_BW_SET, 0x0, phy_idx); + rtw89_phy_write32_idx(rtwdev, R_CHBW_MOD_V1, B_CHBW_MOD_SBW, 0x1, phy_idx); + rtw89_phy_write32_idx(rtwdev, R_CHBW_MOD_V1, B_CHBW_MOD_PRICH, 0x0, phy_idx); + break; + case RTW89_CHANNEL_WIDTH_10: + rtw89_phy_write32_idx(rtwdev, R_FC0_BW_V1, B_FC0_BW_SET, 0x0, phy_idx); + rtw89_phy_write32_idx(rtwdev, R_CHBW_MOD_V1, B_CHBW_MOD_SBW, 0x2, phy_idx); + rtw89_phy_write32_idx(rtwdev, R_CHBW_MOD_V1, B_CHBW_MOD_PRICH, 0x0, phy_idx); + break; + case RTW89_CHANNEL_WIDTH_20: + rtw89_phy_write32_idx(rtwdev, R_FC0_BW_V1, B_FC0_BW_SET, 0x0, phy_idx); + rtw89_phy_write32_idx(rtwdev, R_CHBW_MOD_V1, B_CHBW_MOD_SBW, 0x0, phy_idx); + rtw89_phy_write32_idx(rtwdev, R_CHBW_MOD_V1, B_CHBW_MOD_PRICH, 0x0, phy_idx); + break; + case RTW89_CHANNEL_WIDTH_40: + rtw89_phy_write32_idx(rtwdev, R_FC0_BW_V1, B_FC0_BW_SET, 0x1, phy_idx); + rtw89_phy_write32_idx(rtwdev, R_CHBW_MOD_V1, B_CHBW_MOD_SBW, 0x0, phy_idx); + rtw89_phy_write32_idx(rtwdev, R_CHBW_MOD_V1, B_CHBW_MOD_PRICH, + pri_ch, phy_idx); + /* CCK primary channel */ + if (pri_ch == RTW89_SC_20_UPPER) + rtw89_phy_write32_mask(rtwdev, R_RXSC, B_RXSC_EN, 1); + else + rtw89_phy_write32_mask(rtwdev, R_RXSC, B_RXSC_EN, 0); + + break; + case RTW89_CHANNEL_WIDTH_80: + rtw89_phy_write32_idx(rtwdev, R_FC0_BW_V1, B_FC0_BW_SET, 0x2, phy_idx); + rtw89_phy_write32_idx(rtwdev, R_CHBW_MOD_V1, B_CHBW_MOD_SBW, 0x0, phy_idx); + rtw89_phy_write32_idx(rtwdev, R_CHBW_MOD_V1, B_CHBW_MOD_PRICH, + pri_ch, phy_idx); + break; + default: + rtw89_warn(rtwdev, "Fail to switch bw (bw:%d, pri ch:%d)\n", bw, + pri_ch); + } + + rtw8851b_bw_setting(rtwdev, bw); +} + +static void rtw8851b_ctrl_cck_en(struct rtw89_dev *rtwdev, bool cck_en) +{ + if (cck_en) { + rtw89_phy_write32_mask(rtwdev, R_RXCCA, B_RXCCA_DIS, 0); + rtw89_phy_write32_mask(rtwdev, R_PD_ARBITER_OFF, + B_PD_ARBITER_OFF, 0); + rtw89_phy_write32_mask(rtwdev, R_UPD_CLK_ADC, B_ENABLE_CCK, 1); + } else { + rtw89_phy_write32_mask(rtwdev, R_RXCCA, B_RXCCA_DIS, 1); + rtw89_phy_write32_mask(rtwdev, R_PD_ARBITER_OFF, + B_PD_ARBITER_OFF, 1); + rtw89_phy_write32_mask(rtwdev, R_UPD_CLK_ADC, B_ENABLE_CCK, 0); + } +} + +static u32 rtw8851b_spur_freq(struct rtw89_dev *rtwdev, + const struct rtw89_chan *chan) +{ + u8 center_chan = chan->channel; + + switch (chan->band_type) { + case RTW89_BAND_5G: + if (center_chan == 151 || center_chan == 153 || + center_chan == 155 || center_chan == 163) + return 5760; + else if (center_chan == 54 || center_chan == 58) + return 5280; + break; + default: + break; + } + + return 0; +} + +#define CARRIER_SPACING_312_5 312500 /* 312.5 kHz */ +#define CARRIER_SPACING_78_125 78125 /* 78.125 kHz */ +#define MAX_TONE_NUM 2048 + +static void rtw8851b_set_csi_tone_idx(struct rtw89_dev *rtwdev, + const struct rtw89_chan *chan, + enum rtw89_phy_idx phy_idx) +{ + u32 spur_freq; + s32 freq_diff, csi_idx, csi_tone_idx; + + spur_freq = rtw8851b_spur_freq(rtwdev, chan); + if (spur_freq == 0) { + rtw89_phy_write32_idx(rtwdev, R_SEG0CSI_EN_V1, B_SEG0CSI_EN, + 0, phy_idx); + return; + } + + freq_diff = (spur_freq - chan->freq) * 1000000; + csi_idx = s32_div_u32_round_closest(freq_diff, CARRIER_SPACING_78_125); + s32_div_u32_round_down(csi_idx, MAX_TONE_NUM, &csi_tone_idx); + + rtw89_phy_write32_idx(rtwdev, R_SEG0CSI_V1, B_SEG0CSI_IDX, + csi_tone_idx, phy_idx); + rtw89_phy_write32_idx(rtwdev, R_SEG0CSI_EN_V1, B_SEG0CSI_EN, 1, phy_idx); +} + +static const struct rtw89_nbi_reg_def rtw8851b_nbi_reg_def = { + .notch1_idx = {0x46E4, 0xFF}, + .notch1_frac_idx = {0x46E4, 0xC00}, + .notch1_en = {0x46E4, 0x1000}, + .notch2_idx = {0x47A4, 0xFF}, + .notch2_frac_idx = {0x47A4, 0xC00}, + .notch2_en = {0x47A4, 0x1000}, +}; + +static void rtw8851b_set_nbi_tone_idx(struct rtw89_dev *rtwdev, + const struct rtw89_chan *chan) +{ + const struct rtw89_nbi_reg_def *nbi = &rtw8851b_nbi_reg_def; + s32 nbi_frac_idx, nbi_frac_tone_idx; + s32 nbi_idx, nbi_tone_idx; + bool notch2_chk = false; + u32 spur_freq, fc; + s32 freq_diff; + + spur_freq = rtw8851b_spur_freq(rtwdev, chan); + if (spur_freq == 0) { + rtw89_phy_write32_mask(rtwdev, nbi->notch1_en.addr, + nbi->notch1_en.mask, 0); + rtw89_phy_write32_mask(rtwdev, nbi->notch2_en.addr, + nbi->notch2_en.mask, 0); + return; + } + + fc = chan->freq; + if (chan->band_width == RTW89_CHANNEL_WIDTH_160) { + fc = (spur_freq > fc) ? fc + 40 : fc - 40; + if ((fc > spur_freq && + chan->channel < chan->primary_channel) || + (fc < spur_freq && + chan->channel > chan->primary_channel)) + notch2_chk = true; + } + + freq_diff = (spur_freq - fc) * 1000000; + nbi_idx = s32_div_u32_round_down(freq_diff, CARRIER_SPACING_312_5, + &nbi_frac_idx); + + if (chan->band_width == RTW89_CHANNEL_WIDTH_20) { + s32_div_u32_round_down(nbi_idx + 32, 64, &nbi_tone_idx); + } else { + u16 tone_para = (chan->band_width == RTW89_CHANNEL_WIDTH_40) ? + 128 : 256; + + s32_div_u32_round_down(nbi_idx, tone_para, &nbi_tone_idx); + } + nbi_frac_tone_idx = s32_div_u32_round_closest(nbi_frac_idx, + CARRIER_SPACING_78_125); + + if (chan->band_width == RTW89_CHANNEL_WIDTH_160 && notch2_chk) { + rtw89_phy_write32_mask(rtwdev, nbi->notch2_idx.addr, + nbi->notch2_idx.mask, nbi_tone_idx); + rtw89_phy_write32_mask(rtwdev, nbi->notch2_frac_idx.addr, + nbi->notch2_frac_idx.mask, nbi_frac_tone_idx); + rtw89_phy_write32_mask(rtwdev, nbi->notch2_en.addr, + nbi->notch2_en.mask, 0); + rtw89_phy_write32_mask(rtwdev, nbi->notch2_en.addr, + nbi->notch2_en.mask, 1); + rtw89_phy_write32_mask(rtwdev, nbi->notch1_en.addr, + nbi->notch1_en.mask, 0); + } else { + rtw89_phy_write32_mask(rtwdev, nbi->notch1_idx.addr, + nbi->notch1_idx.mask, nbi_tone_idx); + rtw89_phy_write32_mask(rtwdev, nbi->notch1_frac_idx.addr, + nbi->notch1_frac_idx.mask, nbi_frac_tone_idx); + rtw89_phy_write32_mask(rtwdev, nbi->notch1_en.addr, + nbi->notch1_en.mask, 0); + rtw89_phy_write32_mask(rtwdev, nbi->notch1_en.addr, + nbi->notch1_en.mask, 1); + rtw89_phy_write32_mask(rtwdev, nbi->notch2_en.addr, + nbi->notch2_en.mask, 0); + } +} + +static void rtw8851b_set_cfr(struct rtw89_dev *rtwdev, const struct rtw89_chan *chan) +{ + if (chan->band_type == RTW89_BAND_2G && + chan->band_width == RTW89_CHANNEL_WIDTH_20 && + (chan->channel == 1 || chan->channel == 13)) { + rtw89_phy_write32_mask(rtwdev, R_PATH0_TX_CFR, + B_PATH0_TX_CFR_LGC0, 0xf8); + rtw89_phy_write32_mask(rtwdev, R_PATH0_TX_CFR, + B_PATH0_TX_CFR_LGC1, 0x120); + rtw89_phy_write32_mask(rtwdev, R_PATH0_TX_POLAR_CLIPPING, + B_PATH0_TX_POLAR_CLIPPING_LGC0, 0x0); + rtw89_phy_write32_mask(rtwdev, R_PATH0_TX_POLAR_CLIPPING, + B_PATH0_TX_POLAR_CLIPPING_LGC1, 0x3); + } else { + rtw89_phy_write32_mask(rtwdev, R_PATH0_TX_CFR, + B_PATH0_TX_CFR_LGC0, 0x120); + rtw89_phy_write32_mask(rtwdev, R_PATH0_TX_CFR, + B_PATH0_TX_CFR_LGC1, 0x3ff); + rtw89_phy_write32_mask(rtwdev, R_PATH0_TX_POLAR_CLIPPING, + B_PATH0_TX_POLAR_CLIPPING_LGC0, 0x3); + rtw89_phy_write32_mask(rtwdev, R_PATH0_TX_POLAR_CLIPPING, + B_PATH0_TX_POLAR_CLIPPING_LGC1, 0x7); + } +} + +static void rtw8851b_5m_mask(struct rtw89_dev *rtwdev, const struct rtw89_chan *chan, + enum rtw89_phy_idx phy_idx) +{ + u8 pri_ch = chan->pri_ch_idx; + bool mask_5m_low; + bool mask_5m_en; + + switch (chan->band_width) { + case RTW89_CHANNEL_WIDTH_40: + /* Prich=1: Mask 5M High, Prich=2: Mask 5M Low */ + mask_5m_en = true; + mask_5m_low = pri_ch == RTW89_SC_20_LOWER; + break; + case RTW89_CHANNEL_WIDTH_80: + /* Prich=3: Mask 5M High, Prich=4: Mask 5M Low, Else: Disable */ + mask_5m_en = pri_ch == RTW89_SC_20_UPMOST || + pri_ch == RTW89_SC_20_LOWEST; + mask_5m_low = pri_ch == RTW89_SC_20_LOWEST; + break; + default: + mask_5m_en = false; + break; + } + + if (!mask_5m_en) { + rtw89_phy_write32_mask(rtwdev, R_PATH0_5MDET_V1, B_PATH0_5MDET_EN, 0x0); + rtw89_phy_write32_idx(rtwdev, R_ASSIGN_SBD_OPT_V1, + B_ASSIGN_SBD_OPT_EN_V1, 0x0, phy_idx); + return; + } + + if (mask_5m_low) { + rtw89_phy_write32_mask(rtwdev, R_PATH0_5MDET_V1, B_PATH0_5MDET_TH, 0x5); + rtw89_phy_write32_mask(rtwdev, R_PATH0_5MDET_V1, B_PATH0_5MDET_EN, 0x1); + rtw89_phy_write32_mask(rtwdev, R_PATH0_5MDET_V1, B_PATH0_5MDET_SB2, 0x0); + rtw89_phy_write32_mask(rtwdev, R_PATH0_5MDET_V1, B_PATH0_5MDET_SB0, 0x1); + } else { + rtw89_phy_write32_mask(rtwdev, R_PATH0_5MDET_V1, B_PATH0_5MDET_TH, 0x5); + rtw89_phy_write32_mask(rtwdev, R_PATH0_5MDET_V1, B_PATH0_5MDET_EN, 0x1); + rtw89_phy_write32_mask(rtwdev, R_PATH0_5MDET_V1, B_PATH0_5MDET_SB2, 0x1); + rtw89_phy_write32_mask(rtwdev, R_PATH0_5MDET_V1, B_PATH0_5MDET_SB0, 0x0); + } + rtw89_phy_write32_idx(rtwdev, R_ASSIGN_SBD_OPT_V1, + B_ASSIGN_SBD_OPT_EN_V1, 0x1, phy_idx); +} + +static void rtw8851b_bb_reset_all(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx) +{ + rtw89_phy_write32_idx(rtwdev, R_S0_HW_SI_DIS, B_S0_HW_SI_DIS_W_R_TRIG, 0x7, phy_idx); + fsleep(1); + rtw89_phy_write32_idx(rtwdev, R_RSTB_ASYNC, B_RSTB_ASYNC_ALL, 1, phy_idx); + rtw89_phy_write32_idx(rtwdev, R_RSTB_ASYNC, B_RSTB_ASYNC_ALL, 0, phy_idx); + rtw89_phy_write32_idx(rtwdev, R_S0_HW_SI_DIS, B_S0_HW_SI_DIS_W_R_TRIG, 0x0, phy_idx); + rtw89_phy_write32_idx(rtwdev, R_RSTB_ASYNC, B_RSTB_ASYNC_ALL, 1, phy_idx); +} + +static void rtw8851b_bb_reset_en(struct rtw89_dev *rtwdev, enum rtw89_band band, + enum rtw89_phy_idx phy_idx, bool en) +{ + if (en) { + rtw89_phy_write32_idx(rtwdev, R_S0_HW_SI_DIS, + B_S0_HW_SI_DIS_W_R_TRIG, 0x0, phy_idx); + rtw89_phy_write32_idx(rtwdev, R_RSTB_ASYNC, B_RSTB_ASYNC_ALL, 1, phy_idx); + if (band == RTW89_BAND_2G) + rtw89_phy_write32_mask(rtwdev, R_RXCCA, B_RXCCA_DIS, 0x0); + rtw89_phy_write32_mask(rtwdev, R_PD_CTRL, B_PD_HIT_DIS, 0x0); + } else { + rtw89_phy_write32_mask(rtwdev, R_RXCCA, B_RXCCA_DIS, 0x1); + rtw89_phy_write32_mask(rtwdev, R_PD_CTRL, B_PD_HIT_DIS, 0x1); + rtw89_phy_write32_idx(rtwdev, R_S0_HW_SI_DIS, + B_S0_HW_SI_DIS_W_R_TRIG, 0x7, phy_idx); + fsleep(1); + rtw89_phy_write32_idx(rtwdev, R_RSTB_ASYNC, B_RSTB_ASYNC_ALL, 0, phy_idx); + } +} + +static void rtw8851b_bb_reset(struct rtw89_dev *rtwdev, + enum rtw89_phy_idx phy_idx) +{ + rtw89_phy_write32_mask(rtwdev, R_P0_TXPW_RSTB, + B_P0_TXPW_RSTB_MANON | B_P0_TXPW_RSTB_TSSI, 0x1); + rtw89_phy_write32_set(rtwdev, R_P0_TSSI_TRK, B_P0_TSSI_TRK_EN); + rtw8851b_bb_reset_all(rtwdev, phy_idx); + rtw89_phy_write32_mask(rtwdev, R_P0_TXPW_RSTB, + B_P0_TXPW_RSTB_MANON | B_P0_TXPW_RSTB_TSSI, 0x3); + rtw89_phy_write32_clr(rtwdev, R_P0_TSSI_TRK, B_P0_TSSI_TRK_EN); +} + +static +void rtw8851b_bb_gpio_trsw(struct rtw89_dev *rtwdev, enum rtw89_rf_path path, + u8 tx_path_en, u8 trsw_tx, + u8 trsw_rx, u8 trsw_a, u8 trsw_b) +{ + u32 mask_ofst = 16; + u32 val; + + if (path != RF_PATH_A) + return; + + mask_ofst += (tx_path_en * 4 + trsw_tx * 2 + trsw_rx) * 2; + val = u32_encode_bits(trsw_a, B_P0_TRSW_A) | + u32_encode_bits(trsw_b, B_P0_TRSW_B); + + rtw89_phy_write32_mask(rtwdev, R_P0_TRSW, + (B_P0_TRSW_A | B_P0_TRSW_B) << mask_ofst, val); +} + +static void rtw8851b_bb_gpio_init(struct rtw89_dev *rtwdev) +{ + rtw89_phy_write32_set(rtwdev, R_P0_TRSW, B_P0_TRSW_A); + rtw89_phy_write32_clr(rtwdev, R_P0_TRSW, B_P0_TRSW_X); + rtw89_phy_write32_clr(rtwdev, R_P0_TRSW, B_P0_TRSW_SO_A2); + rtw89_phy_write32(rtwdev, R_RFE_SEL0_BASE, 0x77777777); + rtw89_phy_write32(rtwdev, R_RFE_SEL32_BASE, 0x77777777); + + rtw89_phy_write32(rtwdev, R_RFE_E_A2, 0xffffffff); + rtw89_phy_write32(rtwdev, R_RFE_O_SEL_A2, 0); + rtw89_phy_write32(rtwdev, R_RFE_SEL0_A2, 0); + rtw89_phy_write32(rtwdev, R_RFE_SEL32_A2, 0); + + rtw8851b_bb_gpio_trsw(rtwdev, RF_PATH_A, 0, 0, 0, 0, 1); + rtw8851b_bb_gpio_trsw(rtwdev, RF_PATH_A, 0, 0, 1, 1, 0); + rtw8851b_bb_gpio_trsw(rtwdev, RF_PATH_A, 0, 1, 0, 1, 0); + rtw8851b_bb_gpio_trsw(rtwdev, RF_PATH_A, 0, 1, 1, 1, 0); + rtw8851b_bb_gpio_trsw(rtwdev, RF_PATH_A, 1, 0, 0, 0, 1); + rtw8851b_bb_gpio_trsw(rtwdev, RF_PATH_A, 1, 0, 1, 1, 0); + rtw8851b_bb_gpio_trsw(rtwdev, RF_PATH_A, 1, 1, 0, 1, 0); + rtw8851b_bb_gpio_trsw(rtwdev, RF_PATH_A, 1, 1, 1, 1, 0); +} + +static void rtw8851b_bb_macid_ctrl_init(struct rtw89_dev *rtwdev, + enum rtw89_phy_idx phy_idx) +{ + u32 addr; + + for (addr = R_AX_PWR_MACID_LMT_TABLE0; + addr <= R_AX_PWR_MACID_LMT_TABLE127; addr += 4) + rtw89_mac_txpwr_write32(rtwdev, phy_idx, addr, 0); +} + +static void rtw8851b_bb_sethw(struct rtw89_dev *rtwdev) +{ + struct rtw89_phy_efuse_gain *gain = &rtwdev->efuse_gain; + + rtw89_phy_write32_clr(rtwdev, R_P0_EN_SOUND_WO_NDP, B_P0_EN_SOUND_WO_NDP); + + rtw8851b_bb_macid_ctrl_init(rtwdev, RTW89_PHY_0); + rtw8851b_bb_gpio_init(rtwdev); + + rtw89_write32_clr(rtwdev, R_AX_PWR_NORM_FORCE1, B_AX_FORCE_NTX_VALUE); + rtw89_write32_set(rtwdev, R_AX_PWR_NORM_FORCE1, B_AX_FORCE_NTX_EN); + + /* read these registers after loading BB parameters */ + gain->offset_base[RTW89_PHY_0] = + rtw89_phy_read32_mask(rtwdev, R_P0_RPL1, B_P0_RPL1_BIAS_MASK); + gain->rssi_base[RTW89_PHY_0] = + rtw89_phy_read32_mask(rtwdev, R_P1_RPL1, B_P0_RPL1_BIAS_MASK); +} + +static void rtw8851b_set_channel_bb(struct rtw89_dev *rtwdev, const struct rtw89_chan *chan, + enum rtw89_phy_idx phy_idx) +{ + u8 band = chan->band_type, chan_idx; + bool cck_en = chan->channel <= 14; + u8 pri_ch_idx = chan->pri_ch_idx; + + if (cck_en) + rtw8851b_ctrl_sco_cck(rtwdev, chan->primary_channel); + + rtw8851b_ctrl_ch(rtwdev, chan, phy_idx); + rtw8851b_ctrl_bw(rtwdev, pri_ch_idx, chan->band_width, phy_idx); + rtw8851b_ctrl_cck_en(rtwdev, cck_en); + rtw8851b_set_nbi_tone_idx(rtwdev, chan); + rtw8851b_set_csi_tone_idx(rtwdev, chan, phy_idx); + + if (chan->band_type == RTW89_BAND_5G) { + rtw89_phy_write32_mask(rtwdev, R_PATH0_BT_SHARE_V1, + B_PATH0_BT_SHARE_V1, 0x0); + rtw89_phy_write32_mask(rtwdev, R_PATH0_BTG_PATH_V1, + B_PATH0_BTG_PATH_V1, 0x0); + rtw89_phy_write32_mask(rtwdev, R_CHBW_MOD_V1, B_BT_SHARE, 0x0); + rtw89_phy_write32_mask(rtwdev, R_FC0_BW_V1, B_ANT_RX_BT_SEG0, 0x0); + rtw89_phy_write32_mask(rtwdev, R_BT_DYN_DC_EST_EN_V1, + B_BT_DYN_DC_EST_EN_MSK, 0x0); + rtw89_phy_write32_mask(rtwdev, R_GNT_BT_WGT_EN, B_GNT_BT_WGT_EN, 0x0); + } + + chan_idx = rtw89_encode_chan_idx(rtwdev, chan->primary_channel, band); + rtw89_phy_write32_mask(rtwdev, R_MAC_PIN_SEL, B_CH_IDX_SEG0, chan_idx); + rtw8851b_5m_mask(rtwdev, chan, phy_idx); + rtw8851b_set_cfr(rtwdev, chan); + rtw8851b_bb_reset_all(rtwdev, phy_idx); +} + +static void rtw8851b_set_channel(struct rtw89_dev *rtwdev, + const struct rtw89_chan *chan, + enum rtw89_mac_idx mac_idx, + enum rtw89_phy_idx phy_idx) +{ + rtw8851b_set_channel_mac(rtwdev, chan, mac_idx); + rtw8851b_set_channel_bb(rtwdev, chan, phy_idx); + rtw8851b_set_channel_rf(rtwdev, chan, phy_idx); +} + +static void rtw8851b_tssi_cont_en(struct rtw89_dev *rtwdev, bool en, + enum rtw89_rf_path path) +{ + if (en) { + rtw89_phy_write32_mask(rtwdev, R_P0_TXPW_RSTB, B_P0_TXPW_RSTB_MANON, 0x0); + rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_TRK, B_P0_TSSI_TRK_EN, 0x0); + } else { + rtw89_phy_write32_mask(rtwdev, R_P0_TXPW_RSTB, B_P0_TXPW_RSTB_MANON, 0x1); + rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_TRK, B_P0_TSSI_TRK_EN, 0x1); + } +} + +static void rtw8851b_tssi_cont_en_phyidx(struct rtw89_dev *rtwdev, bool en, + u8 phy_idx) +{ + rtw8851b_tssi_cont_en(rtwdev, en, RF_PATH_A); +} + +static void rtw8851b_adc_en(struct rtw89_dev *rtwdev, bool en) +{ + if (en) + rtw89_phy_write32_mask(rtwdev, R_ADC_FIFO, B_ADC_FIFO_RST, 0x0); + else + rtw89_phy_write32_mask(rtwdev, R_ADC_FIFO, B_ADC_FIFO_RST, 0xf); +} + +static void rtw8851b_set_channel_help(struct rtw89_dev *rtwdev, bool enter, + struct rtw89_channel_help_params *p, + const struct rtw89_chan *chan, + enum rtw89_mac_idx mac_idx, + enum rtw89_phy_idx phy_idx) +{ + if (enter) { + rtw89_chip_stop_sch_tx(rtwdev, RTW89_MAC_0, &p->tx_en, RTW89_SCH_TX_SEL_ALL); + rtw89_mac_cfg_ppdu_status(rtwdev, RTW89_MAC_0, false); + rtw8851b_tssi_cont_en_phyidx(rtwdev, false, RTW89_PHY_0); + rtw8851b_adc_en(rtwdev, false); + fsleep(40); + rtw8851b_bb_reset_en(rtwdev, chan->band_type, phy_idx, false); + } else { + rtw89_mac_cfg_ppdu_status(rtwdev, RTW89_MAC_0, true); + rtw8851b_adc_en(rtwdev, true); + rtw8851b_tssi_cont_en_phyidx(rtwdev, true, RTW89_PHY_0); + rtw8851b_bb_reset_en(rtwdev, chan->band_type, phy_idx, true); + rtw89_chip_resume_sch_tx(rtwdev, RTW89_MAC_0, p->tx_en); + } +} + +static void rtw8851b_rfk_init(struct rtw89_dev *rtwdev) +{ + rtwdev->is_tssi_mode[RF_PATH_A] = false; + rtwdev->is_tssi_mode[RF_PATH_B] = false; + rtw8851b_lck_init(rtwdev); + + rtw8851b_dpk_init(rtwdev); + rtw8851b_aack(rtwdev); + rtw8851b_rck(rtwdev); + rtw8851b_dack(rtwdev); + rtw8851b_rx_dck(rtwdev, RTW89_PHY_0); +} + +static void rtw8851b_rfk_channel(struct rtw89_dev *rtwdev) +{ + enum rtw89_phy_idx phy_idx = RTW89_PHY_0; + + rtw8851b_rx_dck(rtwdev, phy_idx); + rtw8851b_iqk(rtwdev, phy_idx); + rtw8851b_tssi(rtwdev, phy_idx, true); + rtw8851b_dpk(rtwdev, phy_idx); +} + +static void rtw8851b_rfk_band_changed(struct rtw89_dev *rtwdev, + enum rtw89_phy_idx phy_idx) +{ + rtw8851b_tssi_scan(rtwdev, phy_idx); +} + +static void rtw8851b_rfk_scan(struct rtw89_dev *rtwdev, bool start) +{ + rtw8851b_wifi_scan_notify(rtwdev, start, RTW89_PHY_0); +} + +static void rtw8851b_rfk_track(struct rtw89_dev *rtwdev) +{ + rtw8851b_dpk_track(rtwdev); + rtw8851b_lck_track(rtwdev); +} + +static u32 rtw8851b_bb_cal_txpwr_ref(struct rtw89_dev *rtwdev, + enum rtw89_phy_idx phy_idx, s16 ref) +{ + const u16 tssi_16dbm_cw = 0x12c; + const u8 base_cw_0db = 0x27; + const s8 ofst_int = 0; + s16 pwr_s10_3; + s16 rf_pwr_cw; + u16 bb_pwr_cw; + u32 pwr_cw; + u32 tssi_ofst_cw; + + pwr_s10_3 = (ref << 1) + (s16)(ofst_int) + (s16)(base_cw_0db << 3); + bb_pwr_cw = u16_get_bits(pwr_s10_3, GENMASK(2, 0)); + rf_pwr_cw = u16_get_bits(pwr_s10_3, GENMASK(8, 3)); + rf_pwr_cw = clamp_t(s16, rf_pwr_cw, 15, 63); + pwr_cw = (rf_pwr_cw << 3) | bb_pwr_cw; + + tssi_ofst_cw = (u32)((s16)tssi_16dbm_cw + (ref << 1) - (16 << 3)); + rtw89_debug(rtwdev, RTW89_DBG_TXPWR, + "[TXPWR] tssi_ofst_cw=%d rf_cw=0x%x bb_cw=0x%x\n", + tssi_ofst_cw, rf_pwr_cw, bb_pwr_cw); + + return u32_encode_bits(tssi_ofst_cw, B_DPD_TSSI_CW) | + u32_encode_bits(pwr_cw, B_DPD_PWR_CW) | + u32_encode_bits(ref, B_DPD_REF); +} + +static void rtw8851b_set_txpwr_ref(struct rtw89_dev *rtwdev, + enum rtw89_phy_idx phy_idx) +{ + static const u32 addr[RF_PATH_NUM_8851B] = {0x5800}; + const u32 mask = B_DPD_TSSI_CW | B_DPD_PWR_CW | B_DPD_REF; + const u8 ofst_ofdm = 0x4; + const u8 ofst_cck = 0x8; + const s16 ref_ofdm = 0; + const s16 ref_cck = 0; + u32 val; + u8 i; + + rtw89_debug(rtwdev, RTW89_DBG_TXPWR, "[TXPWR] set txpwr reference\n"); + + rtw89_mac_txpwr_write32_mask(rtwdev, phy_idx, R_AX_PWR_RATE_CTRL, + B_AX_PWR_REF, 0x0); + + rtw89_debug(rtwdev, RTW89_DBG_TXPWR, "[TXPWR] set bb ofdm txpwr ref\n"); + val = rtw8851b_bb_cal_txpwr_ref(rtwdev, phy_idx, ref_ofdm); + + for (i = 0; i < RF_PATH_NUM_8851B; i++) + rtw89_phy_write32_idx(rtwdev, addr[i] + ofst_ofdm, mask, val, + phy_idx); + + rtw89_debug(rtwdev, RTW89_DBG_TXPWR, "[TXPWR] set bb cck txpwr ref\n"); + val = rtw8851b_bb_cal_txpwr_ref(rtwdev, phy_idx, ref_cck); + + for (i = 0; i < RF_PATH_NUM_8851B; i++) + rtw89_phy_write32_idx(rtwdev, addr[i] + ofst_cck, mask, val, + phy_idx); +} + +static void rtw8851b_bb_set_tx_shape_dfir(struct rtw89_dev *rtwdev, + const struct rtw89_chan *chan, + u8 tx_shape_idx, + enum rtw89_phy_idx phy_idx) +{ +#define __DFIR_CFG_ADDR(i) (R_TXFIR0 + ((i) << 2)) +#define __DFIR_CFG_MASK 0xffffffff +#define __DFIR_CFG_NR 8 +#define __DECL_DFIR_PARAM(_name, _val...) \ + static const u32 param_ ## _name[] = {_val}; \ + static_assert(ARRAY_SIZE(param_ ## _name) == __DFIR_CFG_NR) + + __DECL_DFIR_PARAM(flat, + 0x023D23FF, 0x0029B354, 0x000FC1C8, 0x00FDB053, + 0x00F86F9A, 0x06FAEF92, 0x00FE5FCC, 0x00FFDFF5); + __DECL_DFIR_PARAM(sharp, + 0x023D83FF, 0x002C636A, 0x0013F204, 0x00008090, + 0x00F87FB0, 0x06F99F83, 0x00FDBFBA, 0x00003FF5); + __DECL_DFIR_PARAM(sharp_14, + 0x023B13FF, 0x001C42DE, 0x00FDB0AD, 0x00F60F6E, + 0x00FD8F92, 0x0602D011, 0x0001C02C, 0x00FFF00A); + u8 ch = chan->channel; + const u32 *param; + u32 addr; + int i; + + if (ch > 14) { + rtw89_warn(rtwdev, + "set tx shape dfir by unknown ch: %d on 2G\n", ch); + return; + } + + if (ch == 14) + param = param_sharp_14; + else + param = tx_shape_idx == 0 ? param_flat : param_sharp; + + for (i = 0; i < __DFIR_CFG_NR; i++) { + addr = __DFIR_CFG_ADDR(i); + rtw89_debug(rtwdev, RTW89_DBG_TXPWR, + "set tx shape dfir: 0x%x: 0x%x\n", addr, param[i]); + rtw89_phy_write32_idx(rtwdev, addr, __DFIR_CFG_MASK, param[i], + phy_idx); + } + +#undef __DECL_DFIR_PARAM +#undef __DFIR_CFG_NR +#undef __DFIR_CFG_MASK +#undef __DECL_CFG_ADDR +} + +static void rtw8851b_set_tx_shape(struct rtw89_dev *rtwdev, + const struct rtw89_chan *chan, + enum rtw89_phy_idx phy_idx) +{ + u8 band = chan->band_type; + u8 regd = rtw89_regd_get(rtwdev, band); + u8 tx_shape_cck = rtw89_8851b_tx_shape[band][RTW89_RS_CCK][regd]; + u8 tx_shape_ofdm = rtw89_8851b_tx_shape[band][RTW89_RS_OFDM][regd]; + + if (band == RTW89_BAND_2G) + rtw8851b_bb_set_tx_shape_dfir(rtwdev, chan, tx_shape_cck, phy_idx); + + rtw89_phy_write32_mask(rtwdev, R_DCFO_OPT, B_TXSHAPE_TRIANGULAR_CFG, + tx_shape_ofdm); +} + +static void rtw8851b_set_txpwr(struct rtw89_dev *rtwdev, + const struct rtw89_chan *chan, + enum rtw89_phy_idx phy_idx) +{ + rtw89_phy_set_txpwr_byrate(rtwdev, chan, phy_idx); + rtw89_phy_set_txpwr_offset(rtwdev, chan, phy_idx); + rtw8851b_set_tx_shape(rtwdev, chan, phy_idx); + rtw89_phy_set_txpwr_limit(rtwdev, chan, phy_idx); + rtw89_phy_set_txpwr_limit_ru(rtwdev, chan, phy_idx); +} + +static void rtw8851b_set_txpwr_ctrl(struct rtw89_dev *rtwdev, + enum rtw89_phy_idx phy_idx) +{ + rtw8851b_set_txpwr_ref(rtwdev, phy_idx); +} + +static +void rtw8851b_set_txpwr_ul_tb_offset(struct rtw89_dev *rtwdev, + s8 pw_ofst, enum rtw89_mac_idx mac_idx) +{ + u32 reg; + + if (pw_ofst < -16 || pw_ofst > 15) { + rtw89_warn(rtwdev, "[ULTB] Err pwr_offset=%d\n", pw_ofst); + return; + } + + reg = rtw89_mac_reg_by_idx(R_AX_PWR_UL_TB_CTRL, mac_idx); + rtw89_write32_set(rtwdev, reg, B_AX_PWR_UL_TB_CTRL_EN); + + reg = rtw89_mac_reg_by_idx(R_AX_PWR_UL_TB_1T, mac_idx); + rtw89_write32_mask(rtwdev, reg, B_AX_PWR_UL_TB_1T_MASK, pw_ofst); + + pw_ofst = max_t(s8, pw_ofst - 3, -16); + reg = rtw89_mac_reg_by_idx(R_AX_PWR_UL_TB_2T, mac_idx); + rtw89_write32_mask(rtwdev, reg, B_AX_PWR_UL_TB_2T_MASK, pw_ofst); +} + +static int +rtw8851b_init_txpwr_unit(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx) +{ + int ret; + + ret = rtw89_mac_txpwr_write32(rtwdev, phy_idx, R_AX_PWR_UL_CTRL2, 0x07763333); + if (ret) + return ret; + + ret = rtw89_mac_txpwr_write32(rtwdev, phy_idx, R_AX_PWR_COEXT_CTRL, 0x01ebf000); + if (ret) + return ret; + + ret = rtw89_mac_txpwr_write32(rtwdev, phy_idx, R_AX_PWR_UL_CTRL0, 0x0002f8ff); + if (ret) + return ret; + + rtw8851b_set_txpwr_ul_tb_offset(rtwdev, 0, phy_idx == RTW89_PHY_1 ? + RTW89_MAC_1 : RTW89_MAC_0); + + return 0; +} + +static void rtw8851b_bb_ctrl_btc_preagc(struct rtw89_dev *rtwdev, bool bt_en) +{ + const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0); + + rtw89_phy_write_reg3_tbl(rtwdev, bt_en ? &rtw8851b_btc_preagc_en_defs_tbl : + &rtw8851b_btc_preagc_dis_defs_tbl); + + if (!bt_en) { + if (chan->band_type == RTW89_BAND_2G) { + rtw89_phy_write32_mask(rtwdev, R_PATH0_G_LNA6_OP1DB_V1, + B_PATH0_G_LNA6_OP1DB_V1, 0x20); + rtw89_phy_write32_mask(rtwdev, R_PATH0_G_TIA0_LNA6_OP1DB_V1, + B_PATH0_G_TIA0_LNA6_OP1DB_V1, 0x30); + } else { + rtw89_phy_write32_mask(rtwdev, R_PATH0_G_LNA6_OP1DB_V1, + B_PATH0_G_LNA6_OP1DB_V1, 0x1a); + rtw89_phy_write32_mask(rtwdev, R_PATH0_G_TIA0_LNA6_OP1DB_V1, + B_PATH0_G_TIA0_LNA6_OP1DB_V1, 0x2a); + } + } +} + +static void rtw8851b_ctrl_btg(struct rtw89_dev *rtwdev, bool btg) +{ + const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0); + + if (btg) { + rtw89_phy_write32_mask(rtwdev, R_PATH0_BT_SHARE_V1, + B_PATH0_BT_SHARE_V1, 0x1); + rtw89_phy_write32_mask(rtwdev, R_PATH0_BTG_PATH_V1, + B_PATH0_BTG_PATH_V1, 0x1); + rtw89_phy_write32_mask(rtwdev, R_PATH0_G_LNA6_OP1DB_V1, + B_PATH0_G_LNA6_OP1DB_V1, 0x20); + rtw89_phy_write32_mask(rtwdev, R_PATH0_G_TIA0_LNA6_OP1DB_V1, + B_PATH0_G_TIA0_LNA6_OP1DB_V1, 0x30); + rtw89_phy_write32_mask(rtwdev, R_PMAC_GNT, B_PMAC_GNT_P1, 0x0); + rtw89_phy_write32_mask(rtwdev, R_CHBW_MOD_V1, B_BT_SHARE, 0x1); + rtw89_phy_write32_mask(rtwdev, R_FC0_BW_V1, B_ANT_RX_BT_SEG0, 0x1); + rtw89_phy_write32_mask(rtwdev, R_BT_DYN_DC_EST_EN_V1, + B_BT_DYN_DC_EST_EN_MSK, 0x1); + rtw89_phy_write32_mask(rtwdev, R_GNT_BT_WGT_EN, B_GNT_BT_WGT_EN, 0x1); + } else { + rtw89_phy_write32_mask(rtwdev, R_PATH0_BT_SHARE_V1, + B_PATH0_BT_SHARE_V1, 0x0); + rtw89_phy_write32_mask(rtwdev, R_PATH0_BTG_PATH_V1, + B_PATH0_BTG_PATH_V1, 0x0); + if (chan->band_type == RTW89_BAND_2G) { + rtw89_phy_write32_mask(rtwdev, R_PATH0_G_LNA6_OP1DB_V1, + B_PATH0_G_LNA6_OP1DB_V1, 0x80); + rtw89_phy_write32_mask(rtwdev, R_PATH0_G_TIA0_LNA6_OP1DB_V1, + B_PATH0_G_TIA0_LNA6_OP1DB_V1, 0x80); + } else { + rtw89_phy_write32_mask(rtwdev, R_PATH0_G_LNA6_OP1DB_V1, + B_PATH0_G_LNA6_OP1DB_V1, 0x1a); + rtw89_phy_write32_mask(rtwdev, R_PATH0_G_TIA0_LNA6_OP1DB_V1, + B_PATH0_G_TIA0_LNA6_OP1DB_V1, 0x2a); + } + rtw89_phy_write32_mask(rtwdev, R_PMAC_GNT, B_PMAC_GNT_P1, 0xc); + rtw89_phy_write32_mask(rtwdev, R_CHBW_MOD_V1, B_BT_SHARE, 0x0); + rtw89_phy_write32_mask(rtwdev, R_FC0_BW_V1, B_ANT_RX_BT_SEG0, 0x0); + rtw89_phy_write32_mask(rtwdev, R_BT_DYN_DC_EST_EN_V1, + B_BT_DYN_DC_EST_EN_MSK, 0x1); + rtw89_phy_write32_mask(rtwdev, R_GNT_BT_WGT_EN, B_GNT_BT_WGT_EN, 0x0); + } +} + +static void rtw8851b_bb_ctrl_rx_path(struct rtw89_dev *rtwdev, + enum rtw89_rf_path_bit rx_path) +{ + const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0); + u32 rst_mask0; + + if (rx_path == RF_A) { + rtw89_phy_write32_mask(rtwdev, R_CHBW_MOD_V1, B_ANT_RX_SEG0, 1); + rtw89_phy_write32_mask(rtwdev, R_FC0_BW_V1, B_ANT_RX_1RCCA_SEG0, 1); + rtw89_phy_write32_mask(rtwdev, R_FC0_BW_V1, B_ANT_RX_1RCCA_SEG1, 1); + rtw89_phy_write32_mask(rtwdev, R_RXHT_MCS_LIMIT, B_RXHT_MCS_LIMIT, 0); + rtw89_phy_write32_mask(rtwdev, R_RXVHT_MCS_LIMIT, B_RXVHT_MCS_LIMIT, 0); + rtw89_phy_write32_mask(rtwdev, R_RXHE, B_RXHE_USER_MAX, 4); + rtw89_phy_write32_mask(rtwdev, R_RXHE, B_RXHE_MAX_NSS, 0); + rtw89_phy_write32_mask(rtwdev, R_RXHE, B_RXHETB_MAX_NSS, 0); + } + + rtw8851b_set_gain_offset(rtwdev, chan->subband_type, RTW89_PHY_0); + + rst_mask0 = B_P0_TXPW_RSTB_MANON | B_P0_TXPW_RSTB_TSSI; + if (rx_path == RF_A) { + rtw89_phy_write32_mask(rtwdev, R_P0_TXPW_RSTB, rst_mask0, 1); + rtw89_phy_write32_mask(rtwdev, R_P0_TXPW_RSTB, rst_mask0, 3); + } +} + +static void rtw8851b_bb_cfg_txrx_path(struct rtw89_dev *rtwdev) +{ + rtw8851b_bb_ctrl_rx_path(rtwdev, RF_A); + + if (rtwdev->hal.rx_nss == 1) { + rtw89_phy_write32_mask(rtwdev, R_RXHT_MCS_LIMIT, B_RXHT_MCS_LIMIT, 0); + rtw89_phy_write32_mask(rtwdev, R_RXVHT_MCS_LIMIT, B_RXVHT_MCS_LIMIT, 0); + rtw89_phy_write32_mask(rtwdev, R_RXHE, B_RXHE_MAX_NSS, 0); + rtw89_phy_write32_mask(rtwdev, R_RXHE, B_RXHETB_MAX_NSS, 0); + } + + rtw89_phy_write32_idx(rtwdev, R_MAC_SEL, B_MAC_SEL_MOD, 0x0, RTW89_PHY_0); +} + +static u8 rtw8851b_get_thermal(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path) +{ + if (rtwdev->is_tssi_mode[rf_path]) { + u32 addr = R_TSSI_THER + (rf_path << 13); + + return rtw89_phy_read32_mask(rtwdev, addr, B_TSSI_THER); + } + + rtw89_write_rf(rtwdev, rf_path, RR_TM, RR_TM_TRI, 0x1); + rtw89_write_rf(rtwdev, rf_path, RR_TM, RR_TM_TRI, 0x0); + rtw89_write_rf(rtwdev, rf_path, RR_TM, RR_TM_TRI, 0x1); + + fsleep(200); + + return rtw89_read_rf(rtwdev, rf_path, RR_TM, RR_TM_VAL); +} + +static void rtw8851b_btc_set_rfe(struct rtw89_dev *rtwdev) +{ + struct rtw89_btc *btc = &rtwdev->btc; + struct rtw89_btc_module *module = &btc->mdinfo; + + module->rfe_type = rtwdev->efuse.rfe_type; + module->cv = rtwdev->hal.cv; + module->bt_solo = 0; + module->switch_type = BTC_SWITCH_INTERNAL; + module->ant.isolation = 10; + module->kt_ver_adie = rtwdev->hal.acv; + + if (module->rfe_type == 0) + return; + + /* rfe_type 3*n+1: 1-Ant(shared), + * 3*n+2: 2-Ant+Div(non-shared), + * 3*n+3: 2-Ant+no-Div(non-shared) + */ + module->ant.num = (module->rfe_type % 3 == 1) ? 1 : 2; + /* WL-1ss at S0, btg at s0 (On 1 WL RF) */ + module->ant.single_pos = RF_PATH_A; + module->ant.btg_pos = RF_PATH_A; + module->ant.stream_cnt = 1; + + if (module->ant.num == 1) { + module->ant.type = BTC_ANT_SHARED; + module->bt_pos = BTC_BT_BTG; + module->wa_type = 1; + module->ant.diversity = 0; + } else { /* ant.num == 2 */ + module->ant.type = BTC_ANT_DEDICATED; + module->bt_pos = BTC_BT_ALONE; + module->switch_type = BTC_SWITCH_EXTERNAL; + module->wa_type = 0; + if (module->rfe_type % 3 == 2) + module->ant.diversity = 1; + } +} + +static +void rtw8851b_set_trx_mask(struct rtw89_dev *rtwdev, u8 path, u8 group, u32 val) +{ + if (group > BTC_BT_SS_GROUP) + group--; /* Tx-group=1, Rx-group=2 */ + + if (rtwdev->btc.mdinfo.ant.type == BTC_ANT_SHARED) /* 1-Ant */ + group += 3; + + rtw89_write_rf(rtwdev, path, RR_LUTWA, RFREG_MASK, group); + rtw89_write_rf(rtwdev, path, RR_LUTWD0, RFREG_MASK, val); +} + +static void rtw8851b_btc_init_cfg(struct rtw89_dev *rtwdev) +{ + static const struct rtw89_mac_ax_coex coex_params = { + .pta_mode = RTW89_MAC_AX_COEX_RTK_MODE, + .direction = RTW89_MAC_AX_COEX_INNER, + }; + const struct rtw89_chip_info *chip = rtwdev->chip; + struct rtw89_btc *btc = &rtwdev->btc; + struct rtw89_btc_module *module = &btc->mdinfo; + struct rtw89_btc_ant_info *ant = &module->ant; + u8 path, path_min, path_max; + + /* PTA init */ + rtw89_mac_coex_init(rtwdev, &coex_params); + + /* set WL Tx response = Hi-Pri */ + chip->ops->btc_set_wl_pri(rtwdev, BTC_PRI_MASK_TX_RESP, true); + chip->ops->btc_set_wl_pri(rtwdev, BTC_PRI_MASK_BEACON, true); + + /* for 1-Ant && 1-ss case: only 1-path */ + if (ant->stream_cnt == 1) { + path_min = ant->single_pos; + path_max = path_min; + } else { + path_min = RF_PATH_A; + path_max = RF_PATH_B; + } + + for (path = path_min; path <= path_max; path++) { + /* set rf gnt-debug off */ + rtw89_write_rf(rtwdev, path, RR_WLSEL, RFREG_MASK, 0x0); + + /* set DEBUG_LUT_RFMODE_MASK = 1 to start trx-mask-setup */ + rtw89_write_rf(rtwdev, path, RR_LUTWE, RFREG_MASK, BIT(17)); + + /* if GNT_WL=0 && BT=SS_group --> WL Tx/Rx = THRU */ + rtw8851b_set_trx_mask(rtwdev, path, BTC_BT_SS_GROUP, 0x5ff); + + /* if GNT_WL=0 && BT=Rx_group --> WL-Rx = THRU + WL-Tx = MASK */ + rtw8851b_set_trx_mask(rtwdev, path, BTC_BT_RX_GROUP, 0x5df); + + /* if GNT_WL = 0 && BT = Tx_group --> + * Shared-Ant && BTG-path:WL mask(0x55f), others:WL THRU(0x5ff) + */ + if (ant->type == BTC_ANT_SHARED && ant->btg_pos == path) + rtw8851b_set_trx_mask(rtwdev, path, BTC_BT_TX_GROUP, 0x55f); + else + rtw8851b_set_trx_mask(rtwdev, path, BTC_BT_TX_GROUP, 0x5ff); + + /* set DEBUG_LUT_RFMODE_MASK = 0 to stop trx-mask-setup */ + rtw89_write_rf(rtwdev, path, RR_LUTWE, RFREG_MASK, 0); + } + + /* set PTA break table */ + rtw89_write32(rtwdev, R_BTC_BREAK_TABLE, BTC_BREAK_PARAM); + + /* enable BT counter 0xda40[16,2] = 2b'11 */ + rtw89_write32_set(rtwdev, R_AX_CSR_MODE, B_AX_BT_CNT_RST | B_AX_STATIS_BT_EN); + + btc->cx.wl.status.map.init_ok = true; +} + +static +void rtw8851b_btc_set_wl_pri(struct rtw89_dev *rtwdev, u8 map, bool state) +{ + u32 bitmap; + u32 reg; + + switch (map) { + case BTC_PRI_MASK_TX_RESP: + reg = R_BTC_BT_COEX_MSK_TABLE; + bitmap = B_BTC_PRI_MASK_TX_RESP_V1; + break; + case BTC_PRI_MASK_BEACON: + reg = R_AX_WL_PRI_MSK; + bitmap = B_AX_PTA_WL_PRI_MASK_BCNQ; + break; + case BTC_PRI_MASK_RX_CCK: + reg = R_BTC_BT_COEX_MSK_TABLE; + bitmap = B_BTC_PRI_MASK_RXCCK_V1; + break; + default: + return; + } + + if (state) + rtw89_write32_set(rtwdev, reg, bitmap); + else + rtw89_write32_clr(rtwdev, reg, bitmap); +} + +union rtw8851b_btc_wl_txpwr_ctrl { + u32 txpwr_val; + struct { + union { + u16 ctrl_all_time; + struct { + s16 data:9; + u16 rsvd:6; + u16 flag:1; + } all_time; + }; + union { + u16 ctrl_gnt_bt; + struct { + s16 data:9; + u16 rsvd:7; + } gnt_bt; + }; + }; +} __packed; + +static void +rtw8851b_btc_set_wl_txpwr_ctrl(struct rtw89_dev *rtwdev, u32 txpwr_val) +{ + union rtw8851b_btc_wl_txpwr_ctrl arg = { .txpwr_val = txpwr_val }; + s32 val; + +#define __write_ctrl(_reg, _msk, _val, _en, _cond) \ +do { \ + u32 _wrt = FIELD_PREP(_msk, _val); \ + BUILD_BUG_ON(!!(_msk & _en)); \ + if (_cond) \ + _wrt |= _en; \ + else \ + _wrt &= ~_en; \ + rtw89_mac_txpwr_write32_mask(rtwdev, RTW89_PHY_0, _reg, \ + _msk | _en, _wrt); \ +} while (0) + + switch (arg.ctrl_all_time) { + case 0xffff: + val = 0; + break; + default: + val = arg.all_time.data; + break; + } + + __write_ctrl(R_AX_PWR_RATE_CTRL, B_AX_FORCE_PWR_BY_RATE_VALUE_MASK, + val, B_AX_FORCE_PWR_BY_RATE_EN, + arg.ctrl_all_time != 0xffff); + + switch (arg.ctrl_gnt_bt) { + case 0xffff: + val = 0; + break; + default: + val = arg.gnt_bt.data; + break; + } + + __write_ctrl(R_AX_PWR_COEXT_CTRL, B_AX_TXAGC_BT_MASK, val, + B_AX_TXAGC_BT_EN, arg.ctrl_gnt_bt != 0xffff); + +#undef __write_ctrl +} + +static +s8 rtw8851b_btc_get_bt_rssi(struct rtw89_dev *rtwdev, s8 val) +{ + val = clamp_t(s8, val, -100, 0) + 100; + val = min(val + 6, 100); /* compensate offset */ + + return val; +} + +static +void rtw8851b_btc_update_bt_cnt(struct rtw89_dev *rtwdev) +{ + /* Feature move to firmware */ +} + +static void rtw8851b_btc_wl_s1_standby(struct rtw89_dev *rtwdev, bool state) +{ + struct rtw89_btc *btc = &rtwdev->btc; + struct rtw89_btc_ant_info *ant = &btc->mdinfo.ant; + + rtw89_write_rf(rtwdev, ant->btg_pos, RR_LUTWE, RFREG_MASK, 0x80000); + rtw89_write_rf(rtwdev, ant->btg_pos, RR_LUTWA, RFREG_MASK, 0x1); + rtw89_write_rf(rtwdev, ant->btg_pos, RR_LUTWD1, RFREG_MASK, 0x110); + + /* set WL standby = Rx for GNT_BT_Tx = 1->0 settle issue */ + if (state) + rtw89_write_rf(rtwdev, ant->btg_pos, RR_LUTWD0, RFREG_MASK, 0x179c); + else + rtw89_write_rf(rtwdev, ant->btg_pos, RR_LUTWD0, RFREG_MASK, 0x208); + + rtw89_write_rf(rtwdev, ant->btg_pos, RR_LUTWE, RFREG_MASK, 0x0); +} + +#define LNA2_51B_MA 0x700 + +static const struct rtw89_reg2_def btc_8851b_rf_0[] = {{0x2, 0x0}}; +static const struct rtw89_reg2_def btc_8851b_rf_1[] = {{0x2, 0x1}}; + +static void rtw8851b_btc_set_wl_rx_gain(struct rtw89_dev *rtwdev, u32 level) +{ + /* To improve BT ACI in co-rx + * level=0 Default: TIA 1/0= (LNA2,TIAN6) = (7,1)/(5,1) = 21dB/12dB + * level=1 Fix LNA2=5: TIA 1/0= (LNA2,TIAN6) = (5,0)/(5,1) = 18dB/12dB + */ + struct rtw89_btc *btc = &rtwdev->btc; + struct rtw89_btc_ant_info *ant = &btc->mdinfo.ant; + const struct rtw89_reg2_def *rf; + u32 n, i, val; + + switch (level) { + case 0: /* original */ + default: + btc->dm.wl_lna2 = 0; + break; + case 1: /* for FDD free-run */ + btc->dm.wl_lna2 = 0; + break; + case 2: /* for BTG Co-Rx*/ + btc->dm.wl_lna2 = 1; + break; + } + + if (btc->dm.wl_lna2 == 0) { + rf = btc_8851b_rf_0; + n = ARRAY_SIZE(btc_8851b_rf_0); + } else { + rf = btc_8851b_rf_1; + n = ARRAY_SIZE(btc_8851b_rf_1); + } + + for (i = 0; i < n; i++, rf++) { + val = rf->data; + /* bit[10] = 1 if non-shared-ant for 8851b */ + if (btc->mdinfo.ant.type == BTC_ANT_DEDICATED) + val |= 0x4; + + rtw89_write_rf(rtwdev, ant->btg_pos, rf->addr, LNA2_51B_MA, val); + } +} + +static void rtw8851b_fill_freq_with_ppdu(struct rtw89_dev *rtwdev, + struct rtw89_rx_phy_ppdu *phy_ppdu, + struct ieee80211_rx_status *status) +{ + u16 chan = phy_ppdu->chan_idx; + enum nl80211_band band; + u8 ch; + + if (chan == 0) + return; + + rtw89_decode_chan_idx(rtwdev, chan, &ch, &band); + status->freq = ieee80211_channel_to_frequency(ch, band); + status->band = band; +} + +static void rtw8851b_query_ppdu(struct rtw89_dev *rtwdev, + struct rtw89_rx_phy_ppdu *phy_ppdu, + struct ieee80211_rx_status *status) +{ + u8 path; + u8 *rx_power = phy_ppdu->rssi; + + status->signal = RTW89_RSSI_RAW_TO_DBM(rx_power[RF_PATH_A]); + + for (path = 0; path < rtwdev->chip->rf_path_num; path++) { + status->chains |= BIT(path); + status->chain_signal[path] = RTW89_RSSI_RAW_TO_DBM(rx_power[path]); + } + if (phy_ppdu->valid) + rtw8851b_fill_freq_with_ppdu(rtwdev, phy_ppdu, status); +} + +static int rtw8851b_mac_enable_bb_rf(struct rtw89_dev *rtwdev) +{ + int ret; + + rtw89_write8_set(rtwdev, R_AX_SYS_FUNC_EN, + B_AX_FEN_BBRSTB | B_AX_FEN_BB_GLB_RSTN); + rtw89_write32_set(rtwdev, R_AX_WLRF_CTRL, B_AX_AFC_AFEDIG); + rtw89_write32_clr(rtwdev, R_AX_WLRF_CTRL, B_AX_AFC_AFEDIG); + rtw89_write32_set(rtwdev, R_AX_WLRF_CTRL, B_AX_AFC_AFEDIG); + + ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_WL_RFC_S0, 0xC7, + FULL_BIT_MASK); + if (ret) + return ret; + + ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_WL_RFC_S1, 0xC7, + FULL_BIT_MASK); + if (ret) + return ret; + + rtw89_write8(rtwdev, R_AX_PHYREG_SET, PHYREG_SET_XYN_CYCLE); + + return 0; +} + +static int rtw8851b_mac_disable_bb_rf(struct rtw89_dev *rtwdev) +{ + u8 wl_rfc_s0; + u8 wl_rfc_s1; + int ret; + + rtw89_write8_clr(rtwdev, R_AX_SYS_FUNC_EN, + B_AX_FEN_BBRSTB | B_AX_FEN_BB_GLB_RSTN); + + ret = rtw89_mac_read_xtal_si(rtwdev, XTAL_SI_WL_RFC_S0, &wl_rfc_s0); + if (ret) + return ret; + wl_rfc_s0 &= ~XTAL_SI_RF00S_EN; + ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_WL_RFC_S0, wl_rfc_s0, + FULL_BIT_MASK); + if (ret) + return ret; + + ret = rtw89_mac_read_xtal_si(rtwdev, XTAL_SI_WL_RFC_S1, &wl_rfc_s1); + if (ret) + return ret; + wl_rfc_s1 &= ~XTAL_SI_RF10S_EN; + ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_WL_RFC_S1, wl_rfc_s1, + FULL_BIT_MASK); + return ret; +} + +static const struct rtw89_chip_ops rtw8851b_chip_ops = { + .enable_bb_rf = rtw8851b_mac_enable_bb_rf, + .disable_bb_rf = rtw8851b_mac_disable_bb_rf, + .bb_reset = rtw8851b_bb_reset, + .bb_sethw = rtw8851b_bb_sethw, + .read_rf = rtw89_phy_read_rf_v1, + .write_rf = rtw89_phy_write_rf_v1, + .set_channel = rtw8851b_set_channel, + .set_channel_help = rtw8851b_set_channel_help, + .read_efuse = rtw8851b_read_efuse, + .read_phycap = rtw8851b_read_phycap, + .fem_setup = NULL, + .rfe_gpio = rtw8851b_rfe_gpio, + .rfk_init = rtw8851b_rfk_init, + .rfk_channel = rtw8851b_rfk_channel, + .rfk_band_changed = rtw8851b_rfk_band_changed, + .rfk_scan = rtw8851b_rfk_scan, + .rfk_track = rtw8851b_rfk_track, + .power_trim = rtw8851b_power_trim, + .set_txpwr = rtw8851b_set_txpwr, + .set_txpwr_ctrl = rtw8851b_set_txpwr_ctrl, + .init_txpwr_unit = rtw8851b_init_txpwr_unit, + .get_thermal = rtw8851b_get_thermal, + .ctrl_btg = rtw8851b_ctrl_btg, + .query_ppdu = rtw8851b_query_ppdu, + .bb_ctrl_btc_preagc = rtw8851b_bb_ctrl_btc_preagc, + .cfg_txrx_path = rtw8851b_bb_cfg_txrx_path, + .set_txpwr_ul_tb_offset = rtw8851b_set_txpwr_ul_tb_offset, + .pwr_on_func = rtw8851b_pwr_on_func, + .pwr_off_func = rtw8851b_pwr_off_func, + .query_rxdesc = rtw89_core_query_rxdesc, + .fill_txdesc = rtw89_core_fill_txdesc, + .fill_txdesc_fwcmd = rtw89_core_fill_txdesc, + .cfg_ctrl_path = rtw89_mac_cfg_ctrl_path, + .mac_cfg_gnt = rtw89_mac_cfg_gnt, + .stop_sch_tx = rtw89_mac_stop_sch_tx, + .resume_sch_tx = rtw89_mac_resume_sch_tx, + .h2c_dctl_sec_cam = NULL, + + .btc_set_rfe = rtw8851b_btc_set_rfe, + .btc_init_cfg = rtw8851b_btc_init_cfg, + .btc_set_wl_pri = rtw8851b_btc_set_wl_pri, + .btc_set_wl_txpwr_ctrl = rtw8851b_btc_set_wl_txpwr_ctrl, + .btc_get_bt_rssi = rtw8851b_btc_get_bt_rssi, + .btc_update_bt_cnt = rtw8851b_btc_update_bt_cnt, + .btc_wl_s1_standby = rtw8851b_btc_wl_s1_standby, + .btc_set_wl_rx_gain = rtw8851b_btc_set_wl_rx_gain, + .btc_set_policy = rtw89_btc_set_policy_v1, +}; + +#ifdef CONFIG_PM +static const struct wiphy_wowlan_support rtw_wowlan_stub_8851b = { + .flags = WIPHY_WOWLAN_MAGIC_PKT | WIPHY_WOWLAN_DISCONNECT, + .n_patterns = RTW89_MAX_PATTERN_NUM, + .pattern_max_len = RTW89_MAX_PATTERN_SIZE, + .pattern_min_len = 1, +}; +#endif + +const struct rtw89_chip_info rtw8851b_chip_info = { + .chip_id = RTL8851B, + .ops = &rtw8851b_chip_ops, + .fw_basename = RTW8851B_FW_BASENAME, + .fw_format_max = RTW8851B_FW_FORMAT_MAX, + .try_ce_fw = true, + .fifo_size = 196608, + .small_fifo_size = true, + .dle_scc_rsvd_size = 98304, + .max_amsdu_limit = 3500, + .dis_2g_40m_ul_ofdma = true, + .rsvd_ple_ofst = 0x2f800, + .hfc_param_ini = rtw8851b_hfc_param_ini_pcie, + .dle_mem = rtw8851b_dle_mem_pcie, + .wde_qempty_acq_num = 4, + .wde_qempty_mgq_sel = 4, + .rf_base_addr = {0xe000}, + .pwr_on_seq = NULL, + .pwr_off_seq = NULL, + .bb_table = &rtw89_8851b_phy_bb_table, + .bb_gain_table = &rtw89_8851b_phy_bb_gain_table, + .rf_table = {&rtw89_8851b_phy_radioa_table,}, + .nctl_table = &rtw89_8851b_phy_nctl_table, + .nctl_post_table = &rtw8851b_nctl_post_defs_tbl, + .byr_table = &rtw89_8851b_byr_table, + .dflt_parms = &rtw89_8851b_dflt_parms, + .rfe_parms_conf = rtw89_8851b_rfe_parms_conf, + .txpwr_factor_rf = 2, + .txpwr_factor_mac = 1, + .dig_table = NULL, + .dig_regs = &rtw8851b_dig_regs, + .tssi_dbw_table = NULL, + .support_chanctx_num = 0, + .support_bands = BIT(NL80211_BAND_2GHZ) | + BIT(NL80211_BAND_5GHZ), + .support_bw160 = false, + .support_unii4 = true, + .support_ul_tb_ctrl = true, + .hw_sec_hdr = false, + .rf_path_num = 1, + .tx_nss = 1, + .rx_nss = 1, + .acam_num = 32, + .bcam_num = 20, + .scam_num = 128, + .bacam_num = 2, + .bacam_dynamic_num = 4, + .bacam_ver = RTW89_BACAM_V0, + .sec_ctrl_efuse_size = 4, + .physical_efuse_size = 1216, + .logical_efuse_size = 2048, + .limit_efuse_size = 1280, + .dav_phy_efuse_size = 0, + .dav_log_efuse_size = 0, + .phycap_addr = 0x580, + .phycap_size = 128, + .para_ver = 0, + .wlcx_desired = 0x06000000, + .btcx_desired = 0x7, + .scbd = 0x1, + .mailbox = 0x1, + + .afh_guard_ch = 6, + .wl_rssi_thres = rtw89_btc_8851b_wl_rssi_thres, + .bt_rssi_thres = rtw89_btc_8851b_bt_rssi_thres, + .rssi_tol = 2, + .mon_reg_num = ARRAY_SIZE(rtw89_btc_8851b_mon_reg), + .mon_reg = rtw89_btc_8851b_mon_reg, + .rf_para_ulink_num = ARRAY_SIZE(rtw89_btc_8851b_rf_ul), + .rf_para_ulink = rtw89_btc_8851b_rf_ul, + .rf_para_dlink_num = ARRAY_SIZE(rtw89_btc_8851b_rf_dl), + .rf_para_dlink = rtw89_btc_8851b_rf_dl, + .ps_mode_supported = BIT(RTW89_PS_MODE_RFOFF) | + BIT(RTW89_PS_MODE_CLK_GATED), + .low_power_hci_modes = 0, + .h2c_cctl_func_id = H2C_FUNC_MAC_CCTLINFO_UD, + .hci_func_en_addr = R_AX_HCI_FUNC_EN, + .h2c_desc_size = sizeof(struct rtw89_txwd_body), + .txwd_body_size = sizeof(struct rtw89_txwd_body), + .h2c_ctrl_reg = R_AX_H2CREG_CTRL, + .h2c_counter_reg = {R_AX_UDM1 + 1, B_AX_UDM1_HALMAC_H2C_DEQ_CNT_MASK >> 8}, + .h2c_regs = rtw8851b_h2c_regs, + .c2h_ctrl_reg = R_AX_C2HREG_CTRL, + .c2h_counter_reg = {R_AX_UDM1 + 1, B_AX_UDM1_HALMAC_C2H_ENQ_CNT_MASK >> 8}, + .c2h_regs = rtw8851b_c2h_regs, + .page_regs = &rtw8851b_page_regs, + .cfo_src_fd = true, + .cfo_hw_comp = true, + .dcfo_comp = &rtw8851b_dcfo_comp, + .dcfo_comp_sft = 12, + .imr_info = &rtw8851b_imr_info, + .rrsr_cfgs = &rtw8851b_rrsr_cfgs, + .bss_clr_map_reg = R_BSS_CLR_MAP_V1, + .dma_ch_mask = BIT(RTW89_DMA_ACH4) | BIT(RTW89_DMA_ACH5) | + BIT(RTW89_DMA_ACH6) | BIT(RTW89_DMA_ACH7) | + BIT(RTW89_DMA_B1MG) | BIT(RTW89_DMA_B1HI), + .edcca_lvl_reg = R_SEG0R_EDCCA_LVL_V1, +#ifdef CONFIG_PM + .wowlan_stub = &rtw_wowlan_stub_8851b, +#endif + .xtal_info = &rtw8851b_xtal_info, +}; +EXPORT_SYMBOL(rtw8851b_chip_info); + +MODULE_FIRMWARE(RTW8851B_MODULE_FIRMWARE); +MODULE_AUTHOR("Realtek Corporation"); +MODULE_DESCRIPTION("Realtek 802.11ax wireless 8851B driver"); +MODULE_LICENSE("Dual BSD/GPL"); diff --git a/drivers/net/wireless/realtek/rtw89/rtw8851b.h b/drivers/net/wireless/realtek/rtw89/rtw8851b.h new file mode 100644 index 0000000000000000000000000000000000000000..1a5c52654d8a440ef1e1cb16604cb8d26cafae3b --- /dev/null +++ b/drivers/net/wireless/realtek/rtw89/rtw8851b.h @@ -0,0 +1,76 @@ +/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ +/* Copyright(c) 2022-2023 Realtek Corporation + */ + +#ifndef __RTW89_8851B_H__ +#define __RTW89_8851B_H__ + +#include "core.h" + +#define RF_PATH_NUM_8851B 1 +#define BB_PATH_NUM_8851B 1 + +struct rtw8851bu_efuse { + u8 rsvd[0x88]; + u8 mac_addr[ETH_ALEN]; +}; + +struct rtw8851be_efuse { + u8 mac_addr[ETH_ALEN]; +}; + +struct rtw8851b_tssi_offset { + u8 cck_tssi[TSSI_CCK_CH_GROUP_NUM]; + u8 bw40_tssi[TSSI_MCS_2G_CH_GROUP_NUM]; + u8 rsvd[7]; + u8 bw40_1s_tssi_5g[TSSI_MCS_5G_CH_GROUP_NUM]; +} __packed; + +struct rtw8851b_efuse { + u8 rsvd[0x210]; + struct rtw8851b_tssi_offset path_a_tssi; + u8 rsvd1[136]; + u8 channel_plan; + u8 xtal_k; + u8 rsvd2; + u8 iqk_lck; + u8 rsvd3[8]; + u8 eeprom_version; + u8 customer_id; + u8 tx_bb_swing_2g; + u8 tx_bb_swing_5g; + u8 tx_cali_pwr_trk_mode; + u8 trx_path_selection; + u8 rfe_type; + u8 country_code[2]; + u8 rsvd4[3]; + u8 path_a_therm; + u8 rsvd5[3]; + u8 rx_gain_2g_ofdm; + u8 rsvd6; + u8 rx_gain_2g_cck; + u8 rsvd7; + u8 rx_gain_5g_low; + u8 rsvd8; + u8 rx_gain_5g_mid; + u8 rsvd9; + u8 rx_gain_5g_high; + u8 rsvd10[35]; + u8 path_a_cck_pwr_idx[6]; + u8 path_a_bw40_1tx_pwr_idx[5]; + u8 path_a_ofdm_1tx_pwr_idx_diff:4; + u8 path_a_bw20_1tx_pwr_idx_diff:4; + u8 path_a_bw20_2tx_pwr_idx_diff:4; + u8 path_a_bw40_2tx_pwr_idx_diff:4; + u8 path_a_cck_2tx_pwr_idx_diff:4; + u8 path_a_ofdm_2tx_pwr_idx_diff:4; + u8 rsvd11[0xf2]; + union { + struct rtw8851bu_efuse u; + struct rtw8851be_efuse e; + }; +} __packed; + +extern const struct rtw89_chip_info rtw8851b_chip_info; + +#endif diff --git a/drivers/net/wireless/realtek/rtw89/rtw8851b_rfk.c b/drivers/net/wireless/realtek/rtw89/rtw8851b_rfk.c new file mode 100644 index 0000000000000000000000000000000000000000..a221f94627f5b4071ba0146d26237b4fa976dbb2 --- /dev/null +++ b/drivers/net/wireless/realtek/rtw89/rtw8851b_rfk.c @@ -0,0 +1,3621 @@ +// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause +/* Copyright(c) 2022-2023 Realtek Corporation + */ + +#include "coex.h" +#include "debug.h" +#include "mac.h" +#include "phy.h" +#include "reg.h" +#include "rtw8851b.h" +#include "rtw8851b_rfk.h" +#include "rtw8851b_rfk_table.h" +#include "rtw8851b_table.h" + +#define DPK_VER_8851B 0x5 +#define DPK_KIP_REG_NUM_8851B 7 +#define DPK_RF_REG_NUM_8851B 4 +#define DPK_KSET_NUM 4 +#define RTW8851B_RXK_GROUP_NR 4 +#define RTW8851B_RXK_GROUP_IDX_NR 2 +#define RTW8851B_TXK_GROUP_NR 1 +#define RTW8851B_IQK_VER 0x2a +#define RTW8851B_IQK_SS 1 +#define RTW8851B_LOK_GRAM 10 +#define RTW8851B_TSSI_PATH_NR 1 + +#define _TSSI_DE_MASK GENMASK(21, 12) + +enum dpk_id { + LBK_RXIQK = 0x06, + SYNC = 0x10, + MDPK_IDL = 0x11, + MDPK_MPA = 0x12, + GAIN_LOSS = 0x13, + GAIN_CAL = 0x14, + DPK_RXAGC = 0x15, + KIP_PRESET = 0x16, + KIP_RESTORE = 0x17, + DPK_TXAGC = 0x19, + D_KIP_PRESET = 0x28, + D_TXAGC = 0x29, + D_RXAGC = 0x2a, + D_SYNC = 0x2b, + D_GAIN_LOSS = 0x2c, + D_MDPK_IDL = 0x2d, + D_MDPK_LDL = 0x2e, + D_GAIN_NORM = 0x2f, + D_KIP_THERMAL = 0x30, + D_KIP_RESTORE = 0x31 +}; + +enum dpk_agc_step { + DPK_AGC_STEP_SYNC_DGAIN, + DPK_AGC_STEP_GAIN_LOSS_IDX, + DPK_AGC_STEP_GL_GT_CRITERION, + DPK_AGC_STEP_GL_LT_CRITERION, + DPK_AGC_STEP_SET_TX_GAIN, +}; + +enum rtw8851b_iqk_type { + ID_TXAGC = 0x0, + ID_FLOK_COARSE = 0x1, + ID_FLOK_FINE = 0x2, + ID_TXK = 0x3, + ID_RXAGC = 0x4, + ID_RXK = 0x5, + ID_NBTXK = 0x6, + ID_NBRXK = 0x7, + ID_FLOK_VBUFFER = 0x8, + ID_A_FLOK_COARSE = 0x9, + ID_G_FLOK_COARSE = 0xa, + ID_A_FLOK_FINE = 0xb, + ID_G_FLOK_FINE = 0xc, + ID_IQK_RESTORE = 0x10, +}; + +enum rf_mode { + RF_SHUT_DOWN = 0x0, + RF_STANDBY = 0x1, + RF_TX = 0x2, + RF_RX = 0x3, + RF_TXIQK = 0x4, + RF_DPK = 0x5, + RF_RXK1 = 0x6, + RF_RXK2 = 0x7, +}; + +static const u32 _tssi_de_cck_long[RF_PATH_NUM_8851B] = {0x5858}; +static const u32 _tssi_de_cck_short[RF_PATH_NUM_8851B] = {0x5860}; +static const u32 _tssi_de_mcs_20m[RF_PATH_NUM_8851B] = {0x5838}; +static const u32 _tssi_de_mcs_40m[RF_PATH_NUM_8851B] = {0x5840}; +static const u32 _tssi_de_mcs_80m[RF_PATH_NUM_8851B] = {0x5848}; +static const u32 _tssi_de_mcs_80m_80m[RF_PATH_NUM_8851B] = {0x5850}; +static const u32 _tssi_de_mcs_5m[RF_PATH_NUM_8851B] = {0x5828}; +static const u32 _tssi_de_mcs_10m[RF_PATH_NUM_8851B] = {0x5830}; +static const u32 g_idxrxgain[RTW8851B_RXK_GROUP_NR] = {0x10e, 0x116, 0x28e, 0x296}; +static const u32 g_idxattc2[RTW8851B_RXK_GROUP_NR] = {0x0, 0xf, 0x0, 0xf}; +static const u32 g_idxrxagc[RTW8851B_RXK_GROUP_NR] = {0x0, 0x1, 0x2, 0x3}; +static const u32 a_idxrxgain[RTW8851B_RXK_GROUP_IDX_NR] = {0x10C, 0x28c}; +static const u32 a_idxattc2[RTW8851B_RXK_GROUP_IDX_NR] = {0xf, 0xf}; +static const u32 a_idxrxagc[RTW8851B_RXK_GROUP_IDX_NR] = {0x4, 0x6}; +static const u32 a_power_range[RTW8851B_TXK_GROUP_NR] = {0x0}; +static const u32 a_track_range[RTW8851B_TXK_GROUP_NR] = {0x6}; +static const u32 a_gain_bb[RTW8851B_TXK_GROUP_NR] = {0x0a}; +static const u32 a_itqt[RTW8851B_TXK_GROUP_NR] = {0x12}; +static const u32 g_power_range[RTW8851B_TXK_GROUP_NR] = {0x0}; +static const u32 g_track_range[RTW8851B_TXK_GROUP_NR] = {0x6}; +static const u32 g_gain_bb[RTW8851B_TXK_GROUP_NR] = {0x10}; +static const u32 g_itqt[RTW8851B_TXK_GROUP_NR] = {0x12}; + +static const u32 rtw8851b_backup_bb_regs[] = {0xc0d4, 0xc0d8, 0xc0c4, 0xc0ec, 0xc0e8}; +static const u32 rtw8851b_backup_rf_regs[] = { + 0xef, 0xde, 0x0, 0x1e, 0x2, 0x85, 0x90, 0x5}; + +#define BACKUP_BB_REGS_NR ARRAY_SIZE(rtw8851b_backup_bb_regs) +#define BACKUP_RF_REGS_NR ARRAY_SIZE(rtw8851b_backup_rf_regs) + +static const u32 dpk_kip_reg[DPK_KIP_REG_NUM_8851B] = { + 0x813c, 0x8124, 0xc0ec, 0xc0e8, 0xc0c4, 0xc0d4, 0xc0d8}; +static const u32 dpk_rf_reg[DPK_RF_REG_NUM_8851B] = {0xde, 0x8f, 0x5, 0x10005}; + +static void _set_ch(struct rtw89_dev *rtwdev, u32 val); + +static u8 _rxk_5ghz_group_from_idx(u8 idx) +{ + /* There are four RXK groups (RTW8851B_RXK_GROUP_NR), but only group 0 + * and 2 are used in 5 GHz band, so reduce elements to 2. + */ + if (idx < RTW8851B_RXK_GROUP_IDX_NR) + return idx * 2; + + return 0; +} + +static u8 _kpath(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx) +{ + return RF_A; +} + +static void _adc_fifo_rst(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx, + u8 path) +{ + rtw89_phy_write32_mask(rtwdev, R_ADC_FIFO, B_ADC_FIFO_RXK, 0x0101); + fsleep(10); + rtw89_phy_write32_mask(rtwdev, R_ADC_FIFO, B_ADC_FIFO_RXK, 0x1111); +} + +static void _rfk_rf_direct_cntrl(struct rtw89_dev *rtwdev, + enum rtw89_rf_path path, bool is_bybb) +{ + if (is_bybb) + rtw89_write_rf(rtwdev, path, RR_RSV1, RR_RSV1_RST, 0x1); + else + rtw89_write_rf(rtwdev, path, RR_RSV1, RR_RSV1_RST, 0x0); +} + +static void _rfk_drf_direct_cntrl(struct rtw89_dev *rtwdev, + enum rtw89_rf_path path, bool is_bybb) +{ + if (is_bybb) + rtw89_write_rf(rtwdev, path, RR_BBDC, RR_BBDC_SEL, 0x1); + else + rtw89_write_rf(rtwdev, path, RR_BBDC, RR_BBDC_SEL, 0x0); +} + +static void _wait_rx_mode(struct rtw89_dev *rtwdev, u8 kpath) +{ + u32 rf_mode; + u8 path; + int ret; + + for (path = 0; path < RF_PATH_MAX; path++) { + if (!(kpath & BIT(path))) + continue; + + ret = read_poll_timeout_atomic(rtw89_read_rf, rf_mode, + rf_mode != 2, 2, 5000, false, + rtwdev, path, 0x00, RR_MOD_MASK); + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[RFK] Wait S%d to Rx mode!! (ret = %d)\n", + path, ret); + } +} + +static void _dack_reset(struct rtw89_dev *rtwdev, enum rtw89_rf_path path) +{ + rtw89_phy_write32_mask(rtwdev, R_DCOF0, B_DCOF0_RST, 0x0); + rtw89_phy_write32_mask(rtwdev, R_DCOF0, B_DCOF0_RST, 0x1); +} + +static void _drck(struct rtw89_dev *rtwdev) +{ + u32 rck_d; + u32 val; + int ret; + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]Ddie RCK start!!!\n"); + + rtw89_phy_write32_mask(rtwdev, R_DRCK, B_DRCK_IDLE, 0x1); + rtw89_phy_write32_mask(rtwdev, R_DRCK, B_DRCK_EN, 0x1); + + ret = read_poll_timeout_atomic(rtw89_phy_read32_mask, val, val, + 1, 10000, false, + rtwdev, R_DRCK_RES, B_DRCK_POL); + if (ret) + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]DRCK timeout\n"); + + rtw89_phy_write32_mask(rtwdev, R_DRCK, B_DRCK_EN, 0x0); + rtw89_phy_write32_mask(rtwdev, R_DRCK_FH, B_DRCK_LAT, 0x1); + udelay(1); + rtw89_phy_write32_mask(rtwdev, R_DRCK_FH, B_DRCK_LAT, 0x0); + + rck_d = rtw89_phy_read32_mask(rtwdev, R_DRCK_RES, 0x7c00); + rtw89_phy_write32_mask(rtwdev, R_DRCK, B_DRCK_IDLE, 0x0); + rtw89_phy_write32_mask(rtwdev, R_DRCK, B_DRCK_VAL, rck_d); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]0xc0c4 = 0x%x\n", + rtw89_phy_read32_mask(rtwdev, R_DRCK, MASKDWORD)); +} + +static void _addck_backup(struct rtw89_dev *rtwdev) +{ + struct rtw89_dack_info *dack = &rtwdev->dack; + + rtw89_phy_write32_mask(rtwdev, R_ADDCK0, B_ADDCK0, 0x0); + + dack->addck_d[0][0] = rtw89_phy_read32_mask(rtwdev, R_ADDCKR0, B_ADDCKR0_A0); + dack->addck_d[0][1] = rtw89_phy_read32_mask(rtwdev, R_ADDCKR0, B_ADDCKR0_A1); +} + +static void _addck_reload(struct rtw89_dev *rtwdev) +{ + struct rtw89_dack_info *dack = &rtwdev->dack; + + rtw89_phy_write32_mask(rtwdev, R_ADDCK0_RL, B_ADDCK0_RL1, dack->addck_d[0][0]); + rtw89_phy_write32_mask(rtwdev, R_ADDCK0_RL, B_ADDCK0_RL0, dack->addck_d[0][1]); + rtw89_phy_write32_mask(rtwdev, R_ADDCK0_RL, B_ADDCK0_RLS, 0x3); +} + +static void _dack_backup_s0(struct rtw89_dev *rtwdev) +{ + struct rtw89_dack_info *dack = &rtwdev->dack; + u8 i; + + rtw89_phy_write32_mask(rtwdev, R_P0_NRBW, B_P0_NRBW_DBG, 0x1); + + for (i = 0; i < RTW89_DACK_MSBK_NR; i++) { + rtw89_phy_write32_mask(rtwdev, R_DCOF0, B_DCOF0_V, i); + dack->msbk_d[0][0][i] = + rtw89_phy_read32_mask(rtwdev, R_DACK_S0P2, B_DACK_S0M0); + + rtw89_phy_write32_mask(rtwdev, R_DCOF8, B_DCOF8_V, i); + dack->msbk_d[0][1][i] = + rtw89_phy_read32_mask(rtwdev, R_DACK_S0P3, B_DACK_S0M1); + } + + dack->biask_d[0][0] = + rtw89_phy_read32_mask(rtwdev, R_DACK_BIAS00, B_DACK_BIAS00); + dack->biask_d[0][1] = + rtw89_phy_read32_mask(rtwdev, R_DACK_BIAS01, B_DACK_BIAS01); + dack->dadck_d[0][0] = + rtw89_phy_read32_mask(rtwdev, R_DACK_DADCK00, B_DACK_DADCK00) + 24; + dack->dadck_d[0][1] = + rtw89_phy_read32_mask(rtwdev, R_DACK_DADCK01, B_DACK_DADCK01) + 24; +} + +static void _dack_reload_by_path(struct rtw89_dev *rtwdev, + enum rtw89_rf_path path, u8 index) +{ + struct rtw89_dack_info *dack = &rtwdev->dack; + u32 idx_offset, path_offset; + u32 offset, reg; + u32 tmp; + u8 i; + + if (index == 0) + idx_offset = 0; + else + idx_offset = 0x14; + + if (path == RF_PATH_A) + path_offset = 0; + else + path_offset = 0x28; + + offset = idx_offset + path_offset; + + rtw89_phy_write32_mask(rtwdev, R_DCOF1, B_DCOF1_RST, 0x1); + rtw89_phy_write32_mask(rtwdev, R_DCOF9, B_DCOF9_RST, 0x1); + + /* msbk_d: 15/14/13/12 */ + tmp = 0x0; + for (i = 0; i < 4; i++) + tmp |= dack->msbk_d[path][index][i + 12] << (i * 8); + reg = 0xc200 + offset; + rtw89_phy_write32(rtwdev, reg, tmp); + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]0x%x=0x%x\n", reg, + rtw89_phy_read32_mask(rtwdev, reg, MASKDWORD)); + + /* msbk_d: 11/10/9/8 */ + tmp = 0x0; + for (i = 0; i < 4; i++) + tmp |= dack->msbk_d[path][index][i + 8] << (i * 8); + reg = 0xc204 + offset; + rtw89_phy_write32(rtwdev, reg, tmp); + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]0x%x=0x%x\n", reg, + rtw89_phy_read32_mask(rtwdev, reg, MASKDWORD)); + + /* msbk_d: 7/6/5/4 */ + tmp = 0x0; + for (i = 0; i < 4; i++) + tmp |= dack->msbk_d[path][index][i + 4] << (i * 8); + reg = 0xc208 + offset; + rtw89_phy_write32(rtwdev, reg, tmp); + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]0x%x=0x%x\n", reg, + rtw89_phy_read32_mask(rtwdev, reg, MASKDWORD)); + + /* msbk_d: 3/2/1/0 */ + tmp = 0x0; + for (i = 0; i < 4; i++) + tmp |= dack->msbk_d[path][index][i] << (i * 8); + reg = 0xc20c + offset; + rtw89_phy_write32(rtwdev, reg, tmp); + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]0x%x=0x%x\n", reg, + rtw89_phy_read32_mask(rtwdev, reg, MASKDWORD)); + + /* dadak_d/biask_d */ + tmp = 0x0; + tmp = (dack->biask_d[path][index] << 22) | + (dack->dadck_d[path][index] << 14); + reg = 0xc210 + offset; + rtw89_phy_write32(rtwdev, reg, tmp); + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]0x%x=0x%x\n", reg, + rtw89_phy_read32_mask(rtwdev, reg, MASKDWORD)); + + rtw89_phy_write32_mask(rtwdev, R_DACKN0_CTL + offset, B_DACKN0_EN, 0x1); +} + +static void _dack_reload(struct rtw89_dev *rtwdev, enum rtw89_rf_path path) +{ + u8 index; + + for (index = 0; index < 2; index++) + _dack_reload_by_path(rtwdev, path, index); +} + +static void _addck(struct rtw89_dev *rtwdev) +{ + struct rtw89_dack_info *dack = &rtwdev->dack; + u32 val; + int ret; + + rtw89_phy_write32_mask(rtwdev, R_ADDCK0, B_ADDCK0_RST, 0x1); + rtw89_phy_write32_mask(rtwdev, R_ADDCK0, B_ADDCK0_EN, 0x1); + rtw89_phy_write32_mask(rtwdev, R_ADDCK0, B_ADDCK0_EN, 0x0); + udelay(1); + rtw89_phy_write32_mask(rtwdev, R_ADDCK0, B_ADDCK0, 0x1); + + ret = read_poll_timeout_atomic(rtw89_phy_read32_mask, val, val, + 1, 10000, false, + rtwdev, R_ADDCKR0, BIT(0)); + if (ret) { + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S0 ADDCK timeout\n"); + dack->addck_timeout[0] = true; + } + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]ADDCK ret = %d\n", ret); + + rtw89_phy_write32_mask(rtwdev, R_ADDCK0, B_ADDCK0_RST, 0x0); +} + +static void _new_dadck(struct rtw89_dev *rtwdev) +{ + struct rtw89_dack_info *dack = &rtwdev->dack; + u32 i_dc, q_dc, ic, qc; + u32 val; + int ret; + + rtw89_rfk_parser(rtwdev, &rtw8851b_dadck_setup_defs_tbl); + + ret = read_poll_timeout_atomic(rtw89_phy_read32_mask, val, val, + 1, 10000, false, + rtwdev, R_ADDCKR0, BIT(0)); + if (ret) { + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S0 DADCK timeout\n"); + dack->addck_timeout[0] = true; + } + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]DADCK ret = %d\n", ret); + + rtw89_phy_write32_mask(rtwdev, R_ADDCK0, B_ADDCK0_IQ, 0x0); + i_dc = rtw89_phy_read32_mask(rtwdev, R_ADDCKR0, B_ADDCKR0_DC); + rtw89_phy_write32_mask(rtwdev, R_ADDCK0, B_ADDCK0_IQ, 0x1); + q_dc = rtw89_phy_read32_mask(rtwdev, R_ADDCKR0, B_ADDCKR0_DC); + + ic = 0x80 - sign_extend32(i_dc, 11) * 6; + qc = 0x80 - sign_extend32(q_dc, 11) * 6; + + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[DACK]before DADCK, i_dc=0x%x, q_dc=0x%x\n", i_dc, q_dc); + + dack->dadck_d[0][0] = ic; + dack->dadck_d[0][1] = qc; + + rtw89_phy_write32_mask(rtwdev, R_DACKN0_CTL, B_DACKN0_V, dack->dadck_d[0][0]); + rtw89_phy_write32_mask(rtwdev, R_DACKN1_CTL, B_DACKN1_V, dack->dadck_d[0][1]); + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[DACK]after DADCK, 0xc210=0x%x, 0xc224=0x%x\n", + rtw89_phy_read32_mask(rtwdev, R_DACKN0_CTL, MASKDWORD), + rtw89_phy_read32_mask(rtwdev, R_DACKN1_CTL, MASKDWORD)); + + rtw89_rfk_parser(rtwdev, &rtw8851b_dadck_post_defs_tbl); +} + +static bool _dack_s0_poll(struct rtw89_dev *rtwdev) +{ + if (rtw89_phy_read32_mask(rtwdev, R_DACK_S0P0, B_DACK_S0P0_OK) == 0 || + rtw89_phy_read32_mask(rtwdev, R_DACK_S0P1, B_DACK_S0P1_OK) == 0 || + rtw89_phy_read32_mask(rtwdev, R_DACK_S0P2, B_DACK_S0P2_OK) == 0 || + rtw89_phy_read32_mask(rtwdev, R_DACK_S0P3, B_DACK_S0P3_OK) == 0) + return false; + + return true; +} + +static void _dack_s0(struct rtw89_dev *rtwdev) +{ + struct rtw89_dack_info *dack = &rtwdev->dack; + bool done; + int ret; + + rtw89_rfk_parser(rtwdev, &rtw8851b_dack_s0_1_defs_tbl); + _dack_reset(rtwdev, RF_PATH_A); + rtw89_phy_write32_mask(rtwdev, R_DCOF1, B_DCOF1_S, 0x1); + + ret = read_poll_timeout_atomic(_dack_s0_poll, done, done, + 1, 10000, false, rtwdev); + if (ret) { + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S0 DACK timeout\n"); + dack->msbk_timeout[0] = true; + } + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]DACK ret = %d\n", ret); + + rtw89_rfk_parser(rtwdev, &rtw8851b_dack_s0_2_defs_tbl); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]after S0 DADCK\n"); + + _dack_backup_s0(rtwdev); + _dack_reload(rtwdev, RF_PATH_A); + + rtw89_phy_write32_mask(rtwdev, R_P0_NRBW, B_P0_NRBW_DBG, 0x0); +} + +static void _dack(struct rtw89_dev *rtwdev) +{ + _dack_s0(rtwdev); +} + +static void _dack_dump(struct rtw89_dev *rtwdev) +{ + struct rtw89_dack_info *dack = &rtwdev->dack; + u8 i; + u8 t; + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S0 ADC_DCK ic = 0x%x, qc = 0x%x\n", + dack->addck_d[0][0], dack->addck_d[0][1]); + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S0 DAC_DCK ic = 0x%x, qc = 0x%x\n", + dack->dadck_d[0][0], dack->dadck_d[0][1]); + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S0 biask ic = 0x%x, qc = 0x%x\n", + dack->biask_d[0][0], dack->biask_d[0][1]); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S0 MSBK ic:\n"); + for (i = 0; i < RTW89_DACK_MSBK_NR; i++) { + t = dack->msbk_d[0][0][i]; + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]0x%x\n", t); + } + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S0 MSBK qc:\n"); + for (i = 0; i < RTW89_DACK_MSBK_NR; i++) { + t = dack->msbk_d[0][1][i]; + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]0x%x\n", t); + } +} + +static void _dack_manual_off(struct rtw89_dev *rtwdev) +{ + rtw89_rfk_parser(rtwdev, &rtw8851b_dack_manual_off_defs_tbl); +} + +static void _dac_cal(struct rtw89_dev *rtwdev, bool force) +{ + struct rtw89_dack_info *dack = &rtwdev->dack; + u32 rf0_0; + + dack->dack_done = false; + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]DACK 0x2\n"); + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]DACK start!!!\n"); + rf0_0 = rtw89_read_rf(rtwdev, RF_PATH_A, RR_MOD, RFREG_MASK); + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]RF0=0x%x\n", rf0_0); + + _drck(rtwdev); + _dack_manual_off(rtwdev); + rtw89_write_rf(rtwdev, RF_PATH_A, RR_MOD, RFREG_MASK, 0x337e1); + rtw89_write_rf(rtwdev, RF_PATH_A, RR_RSV1, RR_RSV1_RST, 0x0); + + _addck(rtwdev); + _addck_backup(rtwdev); + _addck_reload(rtwdev); + rtw89_write_rf(rtwdev, RF_PATH_A, RR_MOD, RFREG_MASK, 0x40001); + + _dack(rtwdev); + _new_dadck(rtwdev); + _dack_dump(rtwdev); + rtw89_write_rf(rtwdev, RF_PATH_A, RR_RSV1, RR_RSV1_RST, 0x1); + + dack->dack_done = true; + dack->dack_cnt++; + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]DACK finish!!!\n"); +} + +static void _rx_dck_info(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, + enum rtw89_rf_path path, bool is_afe) +{ + const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[RX_DCK] ==== S%d RX DCK (%s / CH%d / %s / by %s)====\n", path, + chan->band_type == RTW89_BAND_2G ? "2G" : + chan->band_type == RTW89_BAND_5G ? "5G" : "6G", + chan->channel, + chan->band_width == RTW89_CHANNEL_WIDTH_20 ? "20M" : + chan->band_width == RTW89_CHANNEL_WIDTH_40 ? "40M" : "80M", + is_afe ? "AFE" : "RFC"); +} + +static void _rxbb_ofst_swap(struct rtw89_dev *rtwdev, enum rtw89_rf_path path, u8 rf_mode) +{ + u32 val, val_i, val_q; + + val_i = rtw89_read_rf(rtwdev, path, RR_DCK, RR_DCK_S1); + val_q = rtw89_read_rf(rtwdev, path, RR_DCK1, RR_DCK1_S1); + + val = val_q << 4 | val_i; + + rtw89_write_rf(rtwdev, path, RR_LUTWE2, RR_LUTWE2_DIS, 0x1); + rtw89_write_rf(rtwdev, path, RR_LUTWA, RFREG_MASK, rf_mode); + rtw89_write_rf(rtwdev, path, RR_LUTWD0, RFREG_MASK, val); + rtw89_write_rf(rtwdev, path, RR_LUTWE2, RR_LUTWE2_DIS, 0x0); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[RX_DCK] val_i = 0x%x, val_q = 0x%x, 0x3F = 0x%x\n", + val_i, val_q, val); +} + +static void _set_rx_dck(struct rtw89_dev *rtwdev, enum rtw89_rf_path path, u8 rf_mode) +{ + u32 val; + int ret; + + rtw89_write_rf(rtwdev, path, RR_DCK, RR_DCK_LV, 0x0); + rtw89_write_rf(rtwdev, path, RR_DCK, RR_DCK_LV, 0x1); + + ret = read_poll_timeout_atomic(rtw89_read_rf, val, val, + 2, 2000, false, + rtwdev, path, RR_DCK, BIT(8)); + + rtw89_write_rf(rtwdev, path, RR_DCK, RR_DCK_LV, 0x0); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[RX_DCK] S%d RXDCK finish (ret = %d)\n", + path, ret); + + _rxbb_ofst_swap(rtwdev, path, rf_mode); +} + +static void _rx_dck(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, bool is_afe) +{ + u32 rf_reg5; + u8 path; + + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[RX_DCK] ****** RXDCK Start (Ver: 0x%x, Cv: %d) ******\n", + 0x2, rtwdev->hal.cv); + + for (path = 0; path < RF_PATH_NUM_8851B; path++) { + _rx_dck_info(rtwdev, phy, path, is_afe); + + rf_reg5 = rtw89_read_rf(rtwdev, path, RR_RSV1, RFREG_MASK); + + if (rtwdev->is_tssi_mode[path]) + rtw89_phy_write32_mask(rtwdev, + R_P0_TSSI_TRK + (path << 13), + B_P0_TSSI_TRK_EN, 0x1); + + rtw89_write_rf(rtwdev, path, RR_RSV1, RR_RSV1_RST, 0x0); + rtw89_write_rf(rtwdev, path, RR_MOD, RR_MOD_MASK, RF_RX); + _set_rx_dck(rtwdev, path, RF_RX); + rtw89_write_rf(rtwdev, path, RR_RSV1, RFREG_MASK, rf_reg5); + + if (rtwdev->is_tssi_mode[path]) + rtw89_phy_write32_mask(rtwdev, + R_P0_TSSI_TRK + (path << 13), + B_P0_TSSI_TRK_EN, 0x0); + } +} + +static void _iqk_sram(struct rtw89_dev *rtwdev, u8 path) +{ + u32 i; + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]===>%s\n", __func__); + + rtw89_phy_write32_mask(rtwdev, R_KIP_RPT1, MASKDWORD, 0x00020000); + rtw89_phy_write32_mask(rtwdev, R_MDPK_RX_DCK, MASKDWORD, 0x80000000); + rtw89_phy_write32_mask(rtwdev, R_SRAM_IQRX2, MASKDWORD, 0x00000080); + rtw89_phy_write32_mask(rtwdev, R_SRAM_IQRX, MASKDWORD, 0x00010000); + rtw89_phy_write32_mask(rtwdev, R_IQK_DIF4, B_IQK_DIF4_TXT, 0x009); + + for (i = 0; i <= 0x9f; i++) { + rtw89_phy_write32_mask(rtwdev, R_SRAM_IQRX, MASKDWORD, + 0x00010000 + i); + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]0x%x\n", + rtw89_phy_read32_mask(rtwdev, R_RPT_COM, B_PRT_COM_DCI)); + } + + for (i = 0; i <= 0x9f; i++) { + rtw89_phy_write32_mask(rtwdev, R_SRAM_IQRX, MASKDWORD, + 0x00010000 + i); + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]0x%x\n", + rtw89_phy_read32_mask(rtwdev, R_RPT_COM, B_PRT_COM_DCQ)); + } + + rtw89_phy_write32_mask(rtwdev, R_SRAM_IQRX2, MASKDWORD, 0x00000000); + rtw89_phy_write32_mask(rtwdev, R_SRAM_IQRX, MASKDWORD, 0x00000000); +} + +static void _iqk_rxk_setting(struct rtw89_dev *rtwdev, u8 path) +{ + rtw89_write_rf(rtwdev, path, RR_MOD, RR_MOD_MASK, 0xc); + rtw89_write_rf(rtwdev, path, RR_RXKPLL, RR_RXKPLL_POW, 0x0); + rtw89_write_rf(rtwdev, path, RR_RXKPLL, RR_RXKPLL_POW, 0x1); +} + +static bool _iqk_check_cal(struct rtw89_dev *rtwdev, u8 path) +{ + bool fail1 = false, fail2 = false; + u32 val; + int ret; + + ret = read_poll_timeout_atomic(rtw89_phy_read32_mask, val, val == 0x55, + 10, 8200, false, + rtwdev, 0xbff8, MASKBYTE0); + if (ret) { + fail1 = true; + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[IQK]NCTL1 IQK timeout!!!\n"); + } + + fsleep(10); + + ret = read_poll_timeout_atomic(rtw89_phy_read32_mask, val, val == 0x8000, + 10, 200, false, + rtwdev, R_RPT_COM, B_RPT_COM_RDY); + if (ret) { + fail2 = true; + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[IQK]NCTL2 IQK timeout!!!\n"); + } + + fsleep(10); + rtw89_phy_write32_mask(rtwdev, R_NCTL_N1, MASKBYTE0, 0x0); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[IQK]S%x, ret = %d, notready = %x fail=%d,%d\n", + path, ret, fail1 || fail2, fail1, fail2); + + return fail1 || fail2; +} + +static bool _iqk_one_shot(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx, + u8 path, u8 ktype) +{ + struct rtw89_iqk_info *iqk_info = &rtwdev->iqk; + bool notready; + u32 iqk_cmd; + + switch (ktype) { + case ID_A_FLOK_COARSE: + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[IQK]============ S%d ID_A_FLOK_COARSE ============\n", path); + rtw89_phy_write32_mask(rtwdev, R_UPD_CLK, B_IQK_RFC_ON, 0x1); + iqk_cmd = 0x108 | (1 << (4 + path)); + break; + case ID_G_FLOK_COARSE: + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[IQK]============ S%d ID_G_FLOK_COARSE ============\n", path); + rtw89_phy_write32_mask(rtwdev, R_UPD_CLK, B_IQK_RFC_ON, 0x1); + iqk_cmd = 0x108 | (1 << (4 + path)); + break; + case ID_A_FLOK_FINE: + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[IQK]============ S%d ID_A_FLOK_FINE ============\n", path); + rtw89_phy_write32_mask(rtwdev, R_UPD_CLK, B_IQK_RFC_ON, 0x1); + iqk_cmd = 0x308 | (1 << (4 + path)); + break; + case ID_G_FLOK_FINE: + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[IQK]============ S%d ID_G_FLOK_FINE ============\n", path); + rtw89_phy_write32_mask(rtwdev, R_UPD_CLK, B_IQK_RFC_ON, 0x1); + iqk_cmd = 0x308 | (1 << (4 + path)); + break; + case ID_TXK: + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[IQK]============ S%d ID_TXK ============\n", path); + rtw89_phy_write32_mask(rtwdev, R_UPD_CLK, B_IQK_RFC_ON, 0x0); + iqk_cmd = 0x008 | (1 << (path + 4)) | + (((0x8 + iqk_info->iqk_bw[path]) & 0xf) << 8); + break; + case ID_RXAGC: + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[IQK]============ S%d ID_RXAGC ============\n", path); + rtw89_phy_write32_mask(rtwdev, R_UPD_CLK, B_IQK_RFC_ON, 0x1); + iqk_cmd = 0x708 | (1 << (4 + path)) | (path << 1); + break; + case ID_RXK: + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[IQK]============ S%d ID_RXK ============\n", path); + rtw89_phy_write32_mask(rtwdev, R_UPD_CLK, B_IQK_RFC_ON, 0x1); + iqk_cmd = 0x008 | (1 << (path + 4)) | + (((0xc + iqk_info->iqk_bw[path]) & 0xf) << 8); + break; + case ID_NBTXK: + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[IQK]============ S%d ID_NBTXK ============\n", path); + rtw89_phy_write32_mask(rtwdev, R_UPD_CLK, B_IQK_RFC_ON, 0x0); + rtw89_phy_write32_mask(rtwdev, R_IQK_DIF4, B_IQK_DIF4_TXT, + 0x00b); + iqk_cmd = 0x408 | (1 << (4 + path)); + break; + case ID_NBRXK: + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[IQK]============ S%d ID_NBRXK ============\n", path); + rtw89_phy_write32_mask(rtwdev, R_UPD_CLK, B_IQK_RFC_ON, 0x1); + rtw89_phy_write32_mask(rtwdev, R_IQK_DIF4, B_IQK_DIF4_RXT, + 0x011); + iqk_cmd = 0x608 | (1 << (4 + path)); + break; + default: + return false; + } + + rtw89_phy_write32_mask(rtwdev, R_NCTL_CFG, MASKDWORD, iqk_cmd + 1); + notready = _iqk_check_cal(rtwdev, path); + if (iqk_info->iqk_sram_en && + (ktype == ID_NBRXK || ktype == ID_RXK)) + _iqk_sram(rtwdev, path); + + rtw89_phy_write32_mask(rtwdev, R_UPD_CLK, B_IQK_RFC_ON, 0x0); + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[IQK]S%x, ktype= %x, id = %x, notready = %x\n", + path, ktype, iqk_cmd + 1, notready); + + return notready; +} + +static bool _rxk_2g_group_sel(struct rtw89_dev *rtwdev, + enum rtw89_phy_idx phy_idx, u8 path) +{ + struct rtw89_iqk_info *iqk_info = &rtwdev->iqk; + bool kfail = false; + bool notready; + u32 rf_0; + u8 gp; + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]===>%s\n", __func__); + + for (gp = 0; gp < RTW8851B_RXK_GROUP_NR; gp++) { + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]S%x, gp = %x\n", path, gp); + + rtw89_write_rf(rtwdev, path, RR_MOD, RR_MOD_RGM, g_idxrxgain[gp]); + rtw89_write_rf(rtwdev, path, RR_RXBB, RR_RXBB_C2, g_idxattc2[gp]); + rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_SEL, 0x1); + rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_G3, 0x0); + rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_GP_V1, gp); + + rtw89_write_rf(rtwdev, path, RR_RXKPLL, RFREG_MASK, 0x80013); + fsleep(10); + rf_0 = rtw89_read_rf(rtwdev, path, RR_MOD, RFREG_MASK); + rtw89_phy_write32_mask(rtwdev, R_IQK_DIF2, B_IQK_DIF2_RXPI, rf_0); + rtw89_phy_write32_mask(rtwdev, R_IQK_RXA, B_IQK_RXAGC, g_idxrxagc[gp]); + rtw89_phy_write32_mask(rtwdev, R_IQK_DIF4, B_IQK_DIF4_RXT, 0x11); + + notready = _iqk_one_shot(rtwdev, phy_idx, path, ID_RXAGC); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[IQK]S%x, RXAGC 0x8008 = 0x%x, rxbb = %x\n", path, + rtw89_phy_read32_mask(rtwdev, R_NCTL_RPT, MASKDWORD), + rtw89_read_rf(rtwdev, path, RR_MOD, 0x003e0)); + + rtw89_write_rf(rtwdev, path, RR_RXKPLL, RR_RXKPLL_OFF, 0x13); + rtw89_phy_write32_mask(rtwdev, R_IQK_DIF4, B_IQK_DIF4_RXT, 0x011); + notready = _iqk_one_shot(rtwdev, phy_idx, path, ID_NBRXK); + iqk_info->nb_rxcfir[path] = + rtw89_phy_read32_mask(rtwdev, R_RXIQC, MASKDWORD) | 0x2; + + notready = _iqk_one_shot(rtwdev, phy_idx, path, ID_RXK); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[IQK]S%x, WBRXK 0x8008 = 0x%x\n", path, + rtw89_phy_read32_mask(rtwdev, R_NCTL_RPT, MASKDWORD)); + } + + if (!notready) + kfail = !!rtw89_phy_read32_mask(rtwdev, R_NCTL_RPT, B_NCTL_RPT_FLG); + + if (kfail) + _iqk_sram(rtwdev, path); + + if (kfail) { + rtw89_phy_write32_mask(rtwdev, R_RXIQC + (path << 8), + MASKDWORD, iqk_info->nb_rxcfir[path] | 0x2); + iqk_info->is_wb_txiqk[path] = false; + } else { + rtw89_phy_write32_mask(rtwdev, R_RXIQC + (path << 8), + MASKDWORD, 0x40000000); + iqk_info->is_wb_txiqk[path] = true; + } + + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[IQK]S%x, kfail = 0x%x, 0x8%x3c = 0x%x\n", path, kfail, + 1 << path, iqk_info->nb_rxcfir[path]); + return kfail; +} + +static bool _rxk_5g_group_sel(struct rtw89_dev *rtwdev, + enum rtw89_phy_idx phy_idx, u8 path) +{ + struct rtw89_iqk_info *iqk_info = &rtwdev->iqk; + bool kfail = false; + bool notready; + u32 rf_0; + u8 idx; + u8 gp; + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]===>%s\n", __func__); + + for (idx = 0; idx < RTW8851B_RXK_GROUP_IDX_NR; idx++) { + gp = _rxk_5ghz_group_from_idx(idx); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]S%x, gp = %x\n", path, gp); + + rtw89_write_rf(rtwdev, RF_PATH_A, RR_MOD, RR_MOD_RGM, a_idxrxgain[idx]); + rtw89_write_rf(rtwdev, RF_PATH_A, RR_RXA2, RR_RXA2_ATT, a_idxattc2[idx]); + + rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_SEL, 0x1); + rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_G3, 0x0); + rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_GP_V1, gp); + + rtw89_write_rf(rtwdev, path, RR_RXKPLL, RFREG_MASK, 0x80013); + fsleep(100); + rf_0 = rtw89_read_rf(rtwdev, path, RR_MOD, RFREG_MASK); + rtw89_phy_write32_mask(rtwdev, R_IQK_DIF2, B_IQK_DIF2_RXPI, rf_0); + rtw89_phy_write32_mask(rtwdev, R_IQK_RXA, B_IQK_RXAGC, a_idxrxagc[idx]); + rtw89_phy_write32_mask(rtwdev, R_IQK_DIF4, B_IQK_DIF4_RXT, 0x11); + notready = _iqk_one_shot(rtwdev, phy_idx, path, ID_RXAGC); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[IQK]S%x, RXAGC 0x8008 = 0x%x, rxbb = %x\n", path, + rtw89_phy_read32_mask(rtwdev, R_NCTL_RPT, MASKDWORD), + rtw89_read_rf(rtwdev, path, RR_MOD, RR_MOD_RXB)); + + rtw89_write_rf(rtwdev, path, RR_RXKPLL, RR_RXKPLL_OFF, 0x13); + rtw89_phy_write32_mask(rtwdev, R_IQK_DIF4, B_IQK_DIF4_RXT, 0x011); + notready = _iqk_one_shot(rtwdev, phy_idx, path, ID_NBRXK); + iqk_info->nb_rxcfir[path] = + rtw89_phy_read32_mask(rtwdev, R_RXIQC, MASKDWORD) | 0x2; + + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[IQK]S%x, NBRXK 0x8008 = 0x%x\n", path, + rtw89_phy_read32_mask(rtwdev, R_NCTL_RPT, MASKDWORD)); + + notready = _iqk_one_shot(rtwdev, phy_idx, path, ID_RXK); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[IQK]S%x, WBRXK 0x8008 = 0x%x\n", path, + rtw89_phy_read32_mask(rtwdev, R_NCTL_RPT, MASKDWORD)); + } + + if (!notready) + kfail = !!rtw89_phy_read32_mask(rtwdev, R_NCTL_RPT, B_NCTL_RPT_FLG); + + if (kfail) + _iqk_sram(rtwdev, path); + + if (kfail) { + rtw89_phy_write32_mask(rtwdev, R_RXIQC + (path << 8), MASKDWORD, + iqk_info->nb_rxcfir[path] | 0x2); + iqk_info->is_wb_txiqk[path] = false; + } else { + rtw89_phy_write32_mask(rtwdev, R_RXIQC + (path << 8), MASKDWORD, + 0x40000000); + iqk_info->is_wb_txiqk[path] = true; + } + + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[IQK]S%x, kfail = 0x%x, 0x8%x3c = 0x%x\n", path, kfail, + 1 << path, iqk_info->nb_rxcfir[path]); + return kfail; +} + +static bool _iqk_5g_nbrxk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx, + u8 path) +{ + struct rtw89_iqk_info *iqk_info = &rtwdev->iqk; + bool kfail = false; + bool notready; + u8 idx = 0x1; + u32 rf_0; + u8 gp; + + gp = _rxk_5ghz_group_from_idx(idx); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]===>%s\n", __func__); + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]S%x, gp = %x\n", path, gp); + + rtw89_write_rf(rtwdev, RF_PATH_A, RR_MOD, RR_MOD_RGM, a_idxrxgain[idx]); + rtw89_write_rf(rtwdev, RF_PATH_A, RR_RXA2, RR_RXA2_ATT, a_idxattc2[idx]); + + rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_SEL, 0x1); + rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_G3, 0x0); + rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_GP_V1, gp); + + rtw89_write_rf(rtwdev, path, RR_RXKPLL, RFREG_MASK, 0x80013); + fsleep(100); + rf_0 = rtw89_read_rf(rtwdev, path, RR_MOD, RFREG_MASK); + rtw89_phy_write32_mask(rtwdev, R_IQK_DIF2, B_IQK_DIF2_RXPI, rf_0); + rtw89_phy_write32_mask(rtwdev, R_IQK_RXA, B_IQK_RXAGC, a_idxrxagc[idx]); + rtw89_phy_write32_mask(rtwdev, R_IQK_DIF4, B_IQK_DIF4_RXT, 0x11); + notready = _iqk_one_shot(rtwdev, phy_idx, path, ID_RXAGC); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[IQK]S%x, RXAGC 0x8008 = 0x%x, rxbb = %x\n", path, + rtw89_phy_read32_mask(rtwdev, R_NCTL_RPT, MASKDWORD), + rtw89_read_rf(rtwdev, path, RR_MOD, 0x003e0)); + + rtw89_write_rf(rtwdev, path, RR_RXKPLL, RR_RXKPLL_OFF, 0x13); + rtw89_phy_write32_mask(rtwdev, R_IQK_DIF4, B_IQK_DIF4_RXT, 0x011); + notready = _iqk_one_shot(rtwdev, phy_idx, path, ID_NBRXK); + iqk_info->nb_rxcfir[path] = + rtw89_phy_read32_mask(rtwdev, R_RXIQC, MASKDWORD) | 0x2; + + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[IQK]S%x, NBRXK 0x8008 = 0x%x\n", path, + rtw89_phy_read32_mask(rtwdev, R_NCTL_RPT, MASKDWORD)); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]S%x, WBRXK 0x8008 = 0x%x\n", + path, rtw89_phy_read32_mask(rtwdev, R_NCTL_RPT, MASKDWORD)); + + if (!notready) + kfail = !!rtw89_phy_read32_mask(rtwdev, R_NCTL_RPT, B_NCTL_RPT_FLG); + + if (kfail) { + rtw89_phy_write32_mask(rtwdev, R_RXIQC + (path << 8), + MASKDWORD, 0x40000002); + iqk_info->is_wb_rxiqk[path] = false; + } else { + iqk_info->is_wb_rxiqk[path] = false; + } + + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[IQK]S%x, kfail = 0x%x, 0x8%x3c = 0x%x\n", path, kfail, + 1 << path, iqk_info->nb_rxcfir[path]); + + return kfail; +} + +static bool _iqk_2g_nbrxk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx, + u8 path) +{ + struct rtw89_iqk_info *iqk_info = &rtwdev->iqk; + bool kfail = false; + bool notready; + u8 gp = 0x3; + u32 rf_0; + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]===>%s\n", __func__); + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]S%x, gp = %x\n", path, gp); + + rtw89_write_rf(rtwdev, path, RR_MOD, RR_MOD_RGM, g_idxrxgain[gp]); + rtw89_write_rf(rtwdev, path, RR_RXBB, RR_RXBB_C2, g_idxattc2[gp]); + rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_SEL, 0x1); + rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_G3, 0x0); + rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_GP_V1, gp); + + rtw89_write_rf(rtwdev, path, RR_RXKPLL, RFREG_MASK, 0x80013); + fsleep(10); + rf_0 = rtw89_read_rf(rtwdev, path, RR_MOD, RFREG_MASK); + rtw89_phy_write32_mask(rtwdev, R_IQK_DIF2, B_IQK_DIF2_RXPI, rf_0); + rtw89_phy_write32_mask(rtwdev, R_IQK_RXA, B_IQK_RXAGC, g_idxrxagc[gp]); + rtw89_phy_write32_mask(rtwdev, R_IQK_DIF4, B_IQK_DIF4_RXT, 0x11); + notready = _iqk_one_shot(rtwdev, phy_idx, path, ID_RXAGC); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[IQK]S%x, RXAGC 0x8008 = 0x%x, rxbb = %x\n", + path, rtw89_phy_read32_mask(rtwdev, R_NCTL_RPT, MASKDWORD), + rtw89_read_rf(rtwdev, path, RR_MOD, 0x003e0)); + + rtw89_write_rf(rtwdev, path, RR_RXKPLL, RR_RXKPLL_OFF, 0x13); + rtw89_phy_write32_mask(rtwdev, R_IQK_DIF4, B_IQK_DIF4_RXT, 0x011); + notready = _iqk_one_shot(rtwdev, phy_idx, path, ID_NBRXK); + iqk_info->nb_rxcfir[path] = + rtw89_phy_read32_mask(rtwdev, R_RXIQC, MASKDWORD) | 0x2; + + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[IQK]S%x, NBRXK 0x8008 = 0x%x\n", path, + rtw89_phy_read32_mask(rtwdev, R_NCTL_RPT, MASKDWORD)); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]S%x, WBRXK 0x8008 = 0x%x\n", + path, rtw89_phy_read32_mask(rtwdev, R_NCTL_RPT, MASKDWORD)); + + if (!notready) + kfail = !!rtw89_phy_read32_mask(rtwdev, R_NCTL_RPT, B_NCTL_RPT_FLG); + + if (kfail) { + rtw89_phy_write32_mask(rtwdev, R_RXIQC + (path << 8), + MASKDWORD, 0x40000002); + iqk_info->is_wb_rxiqk[path] = false; + } else { + iqk_info->is_wb_rxiqk[path] = false; + } + + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[IQK]S%x, kfail = 0x%x, 0x8%x3c = 0x%x\n", path, kfail, + 1 << path, iqk_info->nb_rxcfir[path]); + return kfail; +} + +static void _iqk_rxclk_setting(struct rtw89_dev *rtwdev, u8 path) +{ + struct rtw89_iqk_info *iqk_info = &rtwdev->iqk; + + rtw89_write_rf(rtwdev, path, RR_RXBB2, RR_RXBB2_CKT, 0x1); + + if (iqk_info->iqk_bw[path] == RTW89_CHANNEL_WIDTH_80) + rtw89_rfk_parser(rtwdev, &rtw8851b_iqk_rxclk_80_defs_tbl); + else + rtw89_rfk_parser(rtwdev, &rtw8851b_iqk_rxclk_others_defs_tbl); +} + +static bool _txk_5g_group_sel(struct rtw89_dev *rtwdev, + enum rtw89_phy_idx phy_idx, u8 path) +{ + struct rtw89_iqk_info *iqk_info = &rtwdev->iqk; + bool kfail = false; + bool notready; + u8 gp; + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]===>%s\n", __func__); + + for (gp = 0x0; gp < RTW8851B_TXK_GROUP_NR; gp++) { + rtw89_write_rf(rtwdev, path, RR_TXIG, RR_TXIG_GR0, a_power_range[gp]); + rtw89_write_rf(rtwdev, path, RR_TXIG, RR_TXIG_GR1, a_track_range[gp]); + rtw89_write_rf(rtwdev, path, RR_TXIG, RR_TXIG_TG, a_gain_bb[gp]); + + rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_SEL, 0x1); + rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_G3, 0x1); + rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_G2, 0x0); + rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_GP, gp); + rtw89_phy_write32_mask(rtwdev, R_NCTL_N1, B_NCTL_N1_CIP, 0x00); + rtw89_phy_write32_mask(rtwdev, R_KIP_IQP, MASKDWORD, a_itqt[gp]); + + notready = _iqk_one_shot(rtwdev, phy_idx, path, ID_NBTXK); + iqk_info->nb_txcfir[path] = + rtw89_phy_read32_mask(rtwdev, R_TXIQC, MASKDWORD) | 0x2; + + rtw89_phy_write32_mask(rtwdev, R_KIP_IQP + (path << 8), + MASKDWORD, a_itqt[gp]); + notready = _iqk_one_shot(rtwdev, phy_idx, path, ID_TXK); + } + + if (!notready) + kfail = !!rtw89_phy_read32_mask(rtwdev, R_NCTL_RPT, B_NCTL_RPT_FLG); + + if (kfail) { + rtw89_phy_write32_mask(rtwdev, R_TXIQC + (path << 8), + MASKDWORD, iqk_info->nb_txcfir[path] | 0x2); + iqk_info->is_wb_txiqk[path] = false; + } else { + rtw89_phy_write32_mask(rtwdev, R_TXIQC + (path << 8), + MASKDWORD, 0x40000000); + iqk_info->is_wb_txiqk[path] = true; + } + + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[IQK]S%x, kfail = 0x%x, 0x8%x38 = 0x%x\n", path, kfail, + 1 << path, iqk_info->nb_txcfir[path]); + return kfail; +} + +static bool _txk_2g_group_sel(struct rtw89_dev *rtwdev, + enum rtw89_phy_idx phy_idx, u8 path) +{ + struct rtw89_iqk_info *iqk_info = &rtwdev->iqk; + bool kfail = false; + bool notready; + u8 gp; + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]===>%s\n", __func__); + + for (gp = 0x0; gp < RTW8851B_TXK_GROUP_NR; gp++) { + rtw89_write_rf(rtwdev, path, RR_TXIG, RR_TXIG_GR0, g_power_range[gp]); + rtw89_write_rf(rtwdev, path, RR_TXIG, RR_TXIG_GR1, g_track_range[gp]); + rtw89_write_rf(rtwdev, path, RR_TXIG, RR_TXIG_TG, g_gain_bb[gp]); + + rtw89_phy_write32_mask(rtwdev, R_KIP_IQP, MASKDWORD, g_itqt[gp]); + rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_SEL, 0x1); + rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_G3, 0x1); + rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_G2, 0x0); + rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_GP, gp); + rtw89_phy_write32_mask(rtwdev, R_NCTL_N1, B_NCTL_N1_CIP, 0x00); + + notready = _iqk_one_shot(rtwdev, phy_idx, path, ID_NBTXK); + iqk_info->nb_txcfir[path] = + rtw89_phy_read32_mask(rtwdev, R_TXIQC, MASKDWORD) | 0x2; + + rtw89_phy_write32_mask(rtwdev, R_KIP_IQP + (path << 8), + MASKDWORD, g_itqt[gp]); + notready = _iqk_one_shot(rtwdev, phy_idx, path, ID_TXK); + } + + if (!notready) + kfail = !!rtw89_phy_read32_mask(rtwdev, R_NCTL_RPT, B_NCTL_RPT_FLG); + + if (kfail) { + rtw89_phy_write32_mask(rtwdev, R_TXIQC + (path << 8), + MASKDWORD, iqk_info->nb_txcfir[path] | 0x2); + iqk_info->is_wb_txiqk[path] = false; + } else { + rtw89_phy_write32_mask(rtwdev, R_TXIQC + (path << 8), + MASKDWORD, 0x40000000); + iqk_info->is_wb_txiqk[path] = true; + } + + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[IQK]S%x, kfail = 0x%x, 0x8%x38 = 0x%x\n", path, kfail, + 1 << path, iqk_info->nb_txcfir[path]); + return kfail; +} + +static bool _iqk_5g_nbtxk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx, + u8 path) +{ + struct rtw89_iqk_info *iqk_info = &rtwdev->iqk; + bool kfail = false; + bool notready; + u8 gp; + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]===>%s\n", __func__); + + for (gp = 0x0; gp < RTW8851B_TXK_GROUP_NR; gp++) { + rtw89_write_rf(rtwdev, path, RR_TXIG, RR_TXIG_GR0, a_power_range[gp]); + rtw89_write_rf(rtwdev, path, RR_TXIG, RR_TXIG_GR1, a_track_range[gp]); + rtw89_write_rf(rtwdev, path, RR_TXIG, RR_TXIG_TG, a_gain_bb[gp]); + + rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_SEL, 0x1); + rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_G3, 0x1); + rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_G2, 0x0); + rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_GP, gp); + rtw89_phy_write32_mask(rtwdev, R_NCTL_N1, B_NCTL_N1_CIP, 0x00); + rtw89_phy_write32_mask(rtwdev, R_KIP_IQP, MASKDWORD, a_itqt[gp]); + + notready = _iqk_one_shot(rtwdev, phy_idx, path, ID_NBTXK); + iqk_info->nb_txcfir[path] = + rtw89_phy_read32_mask(rtwdev, R_TXIQC, MASKDWORD) | 0x2; + } + + if (!notready) + kfail = !!rtw89_phy_read32_mask(rtwdev, R_NCTL_RPT, B_NCTL_RPT_FLG); + + if (kfail) { + rtw89_phy_write32_mask(rtwdev, R_TXIQC + (path << 8), + MASKDWORD, 0x40000002); + iqk_info->is_wb_rxiqk[path] = false; + } else { + iqk_info->is_wb_rxiqk[path] = false; + } + + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[IQK]S%x, kfail = 0x%x, 0x8%x38 = 0x%x\n", path, kfail, + 1 << path, iqk_info->nb_txcfir[path]); + return kfail; +} + +static bool _iqk_2g_nbtxk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx, + u8 path) +{ + struct rtw89_iqk_info *iqk_info = &rtwdev->iqk; + bool kfail = false; + bool notready; + u8 gp; + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]===>%s\n", __func__); + + for (gp = 0x0; gp < RTW8851B_TXK_GROUP_NR; gp++) { + rtw89_write_rf(rtwdev, path, RR_TXIG, RR_TXIG_GR0, g_power_range[gp]); + rtw89_write_rf(rtwdev, path, RR_TXIG, RR_TXIG_GR1, g_track_range[gp]); + rtw89_write_rf(rtwdev, path, RR_TXIG, RR_TXIG_TG, g_gain_bb[gp]); + + rtw89_phy_write32_mask(rtwdev, R_KIP_IQP, MASKDWORD, g_itqt[gp]); + rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_SEL, 0x1); + rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_G3, 0x1); + rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_G2, 0x0); + rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_GP, gp); + rtw89_phy_write32_mask(rtwdev, R_NCTL_N1, B_NCTL_N1_CIP, 0x00); + + notready = _iqk_one_shot(rtwdev, phy_idx, path, ID_NBTXK); + iqk_info->nb_txcfir[path] = + rtw89_phy_read32_mask(rtwdev, R_TXIQC + (path << 8), + MASKDWORD) | 0x2; + } + + if (!notready) + kfail = !!rtw89_phy_read32_mask(rtwdev, R_NCTL_RPT, B_NCTL_RPT_FLG); + + if (kfail) { + rtw89_phy_write32_mask(rtwdev, R_TXIQC + (path << 8), + MASKDWORD, 0x40000002); + iqk_info->is_wb_rxiqk[path] = false; + } else { + iqk_info->is_wb_rxiqk[path] = false; + } + + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[IQK]S%x, kfail = 0x%x, 0x8%x38 = 0x%x\n", path, kfail, + 1 << path, iqk_info->nb_txcfir[path]); + return kfail; +} + +static bool _iqk_2g_lok(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx, + u8 path) +{ + static const u32 g_txbb[RTW8851B_LOK_GRAM] = { + 0x02, 0x06, 0x0a, 0x0c, 0x0e, 0x10, 0x12, 0x14, 0x16, 0x17}; + static const u32 g_itqt[RTW8851B_LOK_GRAM] = { + 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x12, 0x12, 0x12, 0x1b}; + static const u32 g_wa[RTW8851B_LOK_GRAM] = { + 0x00, 0x04, 0x08, 0x0c, 0x0e, 0x10, 0x12, 0x14, 0x16, 0x17}; + bool fail = false; + u8 i; + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]===>%s\n", __func__); + + rtw89_write_rf(rtwdev, RF_PATH_A, RR_LUTDBG, RR_LUTDBG_LOK, 0x0); + rtw89_write_rf(rtwdev, RF_PATH_A, RR_TXIG, RR_TXIG_GR0, 0x0); + rtw89_write_rf(rtwdev, RF_PATH_A, RR_TXIG, RR_TXIG_GR1, 0x6); + + for (i = 0; i < RTW8851B_LOK_GRAM; i++) { + rtw89_write_rf(rtwdev, RF_PATH_A, RR_TXIG, RR_TXIG_TG, g_txbb[i]); + rtw89_write_rf(rtwdev, RF_PATH_A, RR_LUTWA, RR_LUTWA_M1, g_wa[i]); + rtw89_phy_write32_mask(rtwdev, R_UPD_CLK, B_IQK_RFC_ON, 0x1); + rtw89_phy_write32_mask(rtwdev, R_KIP_IQP, B_KIP_IQP_IQSW, g_itqt[i]); + rtw89_phy_write32_mask(rtwdev, R_IQK_DIF4, B_IQK_DIF4_TXT, 0x021); + rtw89_phy_write32_mask(rtwdev, R_NCTL_CFG, MASKDWORD, + 0x00000109 | (1 << (4 + path))); + fail |= _iqk_check_cal(rtwdev, path); + + rtw89_phy_write32_mask(rtwdev, R_NCTL_N1, B_NCTL_N1_CIP, 0x00); + rtw89_phy_write32_mask(rtwdev, R_KIP_IQP, B_KIP_IQP_IQSW, g_itqt[i]); + rtw89_phy_write32_mask(rtwdev, R_NCTL_CFG, MASKDWORD, + 0x00000309 | (1 << (4 + path))); + fail |= _iqk_check_cal(rtwdev, path); + + rtw89_phy_write32_mask(rtwdev, R_NCTL_N1, B_NCTL_N1_CIP, 0x00); + rtw89_phy_write32_mask(rtwdev, R_UPD_CLK, B_IQK_RFC_ON, 0x0); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[IQK]S0, i = %x, 0x8[19:15] = 0x%x,0x8[09:05] = 0x%x\n", i, + rtw89_read_rf(rtwdev, RF_PATH_A, RR_DTXLOK, 0xf8000), + rtw89_read_rf(rtwdev, RF_PATH_A, RR_DTXLOK, 0x003e0)); + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[IQK]S0, i = %x, 0x9[19:16] = 0x%x,0x9[09:06] = 0x%x\n", i, + rtw89_read_rf(rtwdev, RF_PATH_A, RR_RSV2, 0xf0000), + rtw89_read_rf(rtwdev, RF_PATH_A, RR_RSV2, 0x003c0)); + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[IQK]S0, i = %x, 0x58 = %x\n", i, + rtw89_read_rf(rtwdev, RF_PATH_A, RR_TXMO, RFREG_MASK)); + } + + return fail; +} + +static bool _iqk_5g_lok(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx, + u8 path) +{ + static const u32 a_txbb[RTW8851B_LOK_GRAM] = { + 0x02, 0x06, 0x0a, 0x0c, 0x0e, 0x10, 0x12, 0x14, 0x16, 0x17}; + static const u32 a_itqt[RTW8851B_LOK_GRAM] = { + 0x09, 0x09, 0x09, 0x12, 0x12, 0x12, 0x1b, 0x1b, 0x1b, 0x1b}; + static const u32 a_wa[RTW8851B_LOK_GRAM] = { + 0x80, 0x84, 0x88, 0x8c, 0x8e, 0x90, 0x92, 0x94, 0x96, 0x97}; + bool fail = false; + u8 i; + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]===>%s\n", __func__); + + rtw89_write_rf(rtwdev, RF_PATH_A, RR_LUTDBG, RR_LUTDBG_LOK, 0x0); + rtw89_write_rf(rtwdev, RF_PATH_A, RR_TXIG, RR_TXIG_GR0, 0x0); + rtw89_write_rf(rtwdev, RF_PATH_A, RR_TXIG, RR_TXIG_GR1, 0x7); + + for (i = 0; i < RTW8851B_LOK_GRAM; i++) { + rtw89_write_rf(rtwdev, RF_PATH_A, RR_TXIG, RR_TXIG_TG, a_txbb[i]); + rtw89_write_rf(rtwdev, RF_PATH_A, RR_LUTWA, RR_LUTWA_M1, a_wa[i]); + rtw89_phy_write32_mask(rtwdev, R_UPD_CLK, B_IQK_RFC_ON, 0x1); + rtw89_phy_write32_mask(rtwdev, R_KIP_IQP, B_KIP_IQP_IQSW, a_itqt[i]); + rtw89_phy_write32_mask(rtwdev, R_IQK_DIF4, B_IQK_DIF4_TXT, 0x021); + rtw89_phy_write32_mask(rtwdev, R_NCTL_CFG, MASKDWORD, + 0x00000109 | (1 << (4 + path))); + fail |= _iqk_check_cal(rtwdev, path); + + rtw89_phy_write32_mask(rtwdev, R_NCTL_N1, B_NCTL_N1_CIP, 0x00); + rtw89_phy_write32_mask(rtwdev, R_KIP_IQP, B_KIP_IQP_IQSW, a_itqt[i]); + rtw89_phy_write32_mask(rtwdev, R_IQK_DIF4, B_IQK_DIF4_TXT, 0x021); + rtw89_phy_write32_mask(rtwdev, R_NCTL_CFG, MASKDWORD, + 0x00000309 | (1 << (4 + path))); + fail |= _iqk_check_cal(rtwdev, path); + + rtw89_phy_write32_mask(rtwdev, R_NCTL_N1, B_NCTL_N1_CIP, 0x00); + rtw89_phy_write32_mask(rtwdev, R_UPD_CLK, B_IQK_RFC_ON, 0x0); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[IQK]S0, i = %x, 0x8[19:15] = 0x%x,0x8[09:05] = 0x%x\n", i, + rtw89_read_rf(rtwdev, RF_PATH_A, RR_DTXLOK, 0xf8000), + rtw89_read_rf(rtwdev, RF_PATH_A, RR_DTXLOK, 0x003e0)); + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[IQK]S0, i = %x, 0x9[19:16] = 0x%x,0x9[09:06] = 0x%x\n", i, + rtw89_read_rf(rtwdev, RF_PATH_A, RR_RSV2, 0xf0000), + rtw89_read_rf(rtwdev, RF_PATH_A, RR_RSV2, 0x003c0)); + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[IQK]S0, i = %x, 0x58 = %x\n", i, + rtw89_read_rf(rtwdev, RF_PATH_A, RR_TXMO, RFREG_MASK)); + } + + return fail; +} + +static void _iqk_txk_setting(struct rtw89_dev *rtwdev, u8 path) +{ + struct rtw89_iqk_info *iqk_info = &rtwdev->iqk; + + switch (iqk_info->iqk_band[path]) { + case RTW89_BAND_2G: + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]RTW89_BAND_2G\n"); + rtw89_rfk_parser(rtwdev, &rtw8851b_iqk_txk_2ghz_defs_tbl); + break; + case RTW89_BAND_5G: + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]RTW89_BAND_5G\n"); + rtw89_rfk_parser(rtwdev, &rtw8851b_iqk_txk_5ghz_defs_tbl); + break; + default: + break; + } +} + +#define IQK_LOK_RETRY 1 + +static void _iqk_by_path(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx, + u8 path) +{ + struct rtw89_iqk_info *iqk_info = &rtwdev->iqk; + bool lok_is_fail; + u8 i; + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]===>%s\n", __func__); + + for (i = 0; i < IQK_LOK_RETRY; i++) { + _iqk_txk_setting(rtwdev, path); + if (iqk_info->iqk_band[path] == RTW89_BAND_2G) + lok_is_fail = _iqk_2g_lok(rtwdev, phy_idx, path); + else + lok_is_fail = _iqk_5g_lok(rtwdev, phy_idx, path); + + if (!lok_is_fail) + break; + } + + if (iqk_info->is_nbiqk) { + if (iqk_info->iqk_band[path] == RTW89_BAND_2G) + iqk_info->iqk_tx_fail[0][path] = + _iqk_2g_nbtxk(rtwdev, phy_idx, path); + else + iqk_info->iqk_tx_fail[0][path] = + _iqk_5g_nbtxk(rtwdev, phy_idx, path); + } else { + if (iqk_info->iqk_band[path] == RTW89_BAND_2G) + iqk_info->iqk_tx_fail[0][path] = + _txk_2g_group_sel(rtwdev, phy_idx, path); + else + iqk_info->iqk_tx_fail[0][path] = + _txk_5g_group_sel(rtwdev, phy_idx, path); + } + + _iqk_rxclk_setting(rtwdev, path); + _iqk_rxk_setting(rtwdev, path); + _adc_fifo_rst(rtwdev, phy_idx, path); + + if (iqk_info->is_nbiqk) { + if (iqk_info->iqk_band[path] == RTW89_BAND_2G) + iqk_info->iqk_rx_fail[0][path] = + _iqk_2g_nbrxk(rtwdev, phy_idx, path); + else + iqk_info->iqk_rx_fail[0][path] = + _iqk_5g_nbrxk(rtwdev, phy_idx, path); + } else { + if (iqk_info->iqk_band[path] == RTW89_BAND_2G) + iqk_info->iqk_rx_fail[0][path] = + _rxk_2g_group_sel(rtwdev, phy_idx, path); + else + iqk_info->iqk_rx_fail[0][path] = + _rxk_5g_group_sel(rtwdev, phy_idx, path); + } +} + +static void _rfk_backup_bb_reg(struct rtw89_dev *rtwdev, + u32 backup_bb_reg_val[]) +{ + u32 i; + + for (i = 0; i < BACKUP_BB_REGS_NR; i++) { + backup_bb_reg_val[i] = + rtw89_phy_read32_mask(rtwdev, rtw8851b_backup_bb_regs[i], + MASKDWORD); + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[RFK]backup bb reg : %x, value =%x\n", + rtw8851b_backup_bb_regs[i], backup_bb_reg_val[i]); + } +} + +static void _rfk_backup_rf_reg(struct rtw89_dev *rtwdev, + u32 backup_rf_reg_val[], u8 rf_path) +{ + u32 i; + + for (i = 0; i < BACKUP_RF_REGS_NR; i++) { + backup_rf_reg_val[i] = + rtw89_read_rf(rtwdev, rf_path, + rtw8851b_backup_rf_regs[i], RFREG_MASK); + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[RFK]backup rf S%d reg : %x, value =%x\n", rf_path, + rtw8851b_backup_rf_regs[i], backup_rf_reg_val[i]); + } +} + +static void _rfk_restore_bb_reg(struct rtw89_dev *rtwdev, + const u32 backup_bb_reg_val[]) +{ + u32 i; + + for (i = 0; i < BACKUP_BB_REGS_NR; i++) { + rtw89_phy_write32_mask(rtwdev, rtw8851b_backup_bb_regs[i], + MASKDWORD, backup_bb_reg_val[i]); + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[RFK]restore bb reg : %x, value =%x\n", + rtw8851b_backup_bb_regs[i], backup_bb_reg_val[i]); + } +} + +static void _rfk_restore_rf_reg(struct rtw89_dev *rtwdev, + const u32 backup_rf_reg_val[], u8 rf_path) +{ + u32 i; + + for (i = 0; i < BACKUP_RF_REGS_NR; i++) { + rtw89_write_rf(rtwdev, rf_path, rtw8851b_backup_rf_regs[i], + RFREG_MASK, backup_rf_reg_val[i]); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[RFK]restore rf S%d reg: %x, value =%x\n", rf_path, + rtw8851b_backup_rf_regs[i], backup_rf_reg_val[i]); + } +} + +static void _iqk_get_ch_info(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, + u8 path) +{ + const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0); + struct rtw89_iqk_info *iqk_info = &rtwdev->iqk; + u8 idx = 0; + + iqk_info->iqk_band[path] = chan->band_type; + iqk_info->iqk_bw[path] = chan->band_width; + iqk_info->iqk_ch[path] = chan->channel; + iqk_info->iqk_table_idx[path] = idx; + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]S%d (PHY%d): / DBCC %s/ %s/ CH%d/ %s\n", + path, phy, rtwdev->dbcc_en ? "on" : "off", + iqk_info->iqk_band[path] == 0 ? "2G" : + iqk_info->iqk_band[path] == 1 ? "5G" : "6G", + iqk_info->iqk_ch[path], + iqk_info->iqk_bw[path] == 0 ? "20M" : + iqk_info->iqk_bw[path] == 1 ? "40M" : "80M"); + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]times = 0x%x, ch =%x\n", + iqk_info->iqk_times, idx); + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]S%x, iqk_info->syn1to2= 0x%x\n", + path, iqk_info->syn1to2); +} + +static void _iqk_start_iqk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx, + u8 path) +{ + _iqk_by_path(rtwdev, phy_idx, path); +} + +static void _iqk_restore(struct rtw89_dev *rtwdev, u8 path) +{ + bool fail; + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]===>%s\n", __func__); + + rtw89_phy_write32_mask(rtwdev, R_NCTL_CFG, MASKDWORD, 0x00001219); + fsleep(10); + fail = _iqk_check_cal(rtwdev, path); + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK] restore fail=%d\n", fail); + + rtw89_write_rf(rtwdev, RF_PATH_A, RR_LUTWE, RR_LUTWE_LOK, 0x0); + rtw89_write_rf(rtwdev, RF_PATH_A, RR_LUTDBG, RR_LUTDBG_TIA, 0x0); + + rtw89_phy_write32_mask(rtwdev, R_NCTL_N1, B_NCTL_N1_CIP, 0x00); + rtw89_phy_write32_mask(rtwdev, R_NCTL_RPT, MASKDWORD, 0x00000000); + rtw89_phy_write32_mask(rtwdev, R_KIP_SYSCFG, MASKDWORD, 0x80000000); +} + +static void _iqk_afebb_restore(struct rtw89_dev *rtwdev, + enum rtw89_phy_idx phy_idx, u8 path) +{ + rtw89_rfk_parser(rtwdev, &rtw8851b_iqk_afebb_restore_defs_tbl); +} + +static void _iqk_preset(struct rtw89_dev *rtwdev, u8 path) +{ + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]===>%s\n", __func__); + + rtw89_write_rf(rtwdev, path, RR_RSV1, RR_RSV1_RST, 0x0); + rtw89_phy_write32_mask(rtwdev, R_NCTL_RPT, MASKDWORD, 0x00000080); + rtw89_phy_write32_mask(rtwdev, R_KIP_SYSCFG, MASKDWORD, 0x81ff010a); +} + +static void _iqk_macbb_setting(struct rtw89_dev *rtwdev, + enum rtw89_phy_idx phy_idx, u8 path) +{ + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]===>%s\n", __func__); + + rtw89_rfk_parser(rtwdev, &rtw8851b_iqk_macbb_defs_tbl); +} + +static void _iqk_init(struct rtw89_dev *rtwdev) +{ + struct rtw89_iqk_info *iqk_info = &rtwdev->iqk; + u8 idx, path; + + rtw89_phy_write32_mask(rtwdev, R_IQKINF, MASKDWORD, 0x0); + + if (iqk_info->is_iqk_init) + return; + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]===>%s\n", __func__); + + iqk_info->is_iqk_init = true; + iqk_info->is_nbiqk = false; + iqk_info->iqk_fft_en = false; + iqk_info->iqk_sram_en = false; + iqk_info->iqk_cfir_en = false; + iqk_info->iqk_xym_en = false; + iqk_info->iqk_times = 0x0; + + for (idx = 0; idx < RTW89_IQK_CHS_NR; idx++) { + iqk_info->iqk_channel[idx] = 0x0; + for (path = 0; path < RF_PATH_NUM_8851B; path++) { + iqk_info->lok_cor_fail[idx][path] = false; + iqk_info->lok_fin_fail[idx][path] = false; + iqk_info->iqk_tx_fail[idx][path] = false; + iqk_info->iqk_rx_fail[idx][path] = false; + iqk_info->iqk_table_idx[path] = 0x0; + } + } +} + +static void _doiqk(struct rtw89_dev *rtwdev, bool force, + enum rtw89_phy_idx phy_idx, u8 path) +{ + struct rtw89_iqk_info *iqk_info = &rtwdev->iqk; + u8 phy_map = rtw89_btc_phymap(rtwdev, phy_idx, RF_AB); + u32 backup_rf_val[RTW8851B_IQK_SS][BACKUP_RF_REGS_NR]; + u32 backup_bb_val[BACKUP_BB_REGS_NR]; + + rtw89_btc_ntfy_wl_rfk(rtwdev, phy_map, BTC_WRFKT_IQK, + BTC_WRFK_ONESHOT_START); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[IQK]==========IQK start!!!!!==========\n"); + iqk_info->iqk_times++; + iqk_info->version = RTW8851B_IQK_VER; + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]Test Ver 0x%x\n", iqk_info->version); + _iqk_get_ch_info(rtwdev, phy_idx, path); + + _rfk_backup_bb_reg(rtwdev, &backup_bb_val[0]); + _rfk_backup_rf_reg(rtwdev, &backup_rf_val[path][0], path); + _iqk_macbb_setting(rtwdev, phy_idx, path); + _iqk_preset(rtwdev, path); + _iqk_start_iqk(rtwdev, phy_idx, path); + _iqk_restore(rtwdev, path); + _iqk_afebb_restore(rtwdev, phy_idx, path); + _rfk_restore_bb_reg(rtwdev, &backup_bb_val[0]); + _rfk_restore_rf_reg(rtwdev, &backup_rf_val[path][0], path); + + rtw89_btc_ntfy_wl_rfk(rtwdev, phy_map, BTC_WRFKT_IQK, + BTC_WRFK_ONESHOT_STOP); +} + +static void _iqk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx, bool force) +{ + _doiqk(rtwdev, force, phy_idx, RF_PATH_A); +} + +static void _dpk_bkup_kip(struct rtw89_dev *rtwdev, const u32 *reg, + u32 reg_bkup[][DPK_KIP_REG_NUM_8851B], u8 path) +{ + u8 i; + + for (i = 0; i < DPK_KIP_REG_NUM_8851B; i++) { + reg_bkup[path][i] = + rtw89_phy_read32_mask(rtwdev, reg[i] + (path << 8), MASKDWORD); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] Backup 0x%x = %x\n", + reg[i] + (path << 8), reg_bkup[path][i]); + } +} + +static void _dpk_bkup_rf(struct rtw89_dev *rtwdev, const u32 *rf_reg, + u32 rf_bkup[][DPK_RF_REG_NUM_8851B], u8 path) +{ + u8 i; + + for (i = 0; i < DPK_RF_REG_NUM_8851B; i++) { + rf_bkup[path][i] = rtw89_read_rf(rtwdev, path, rf_reg[i], RFREG_MASK); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] Backup RF S%d 0x%x = %x\n", + path, rf_reg[i], rf_bkup[path][i]); + } +} + +static void _dpk_reload_kip(struct rtw89_dev *rtwdev, const u32 *reg, + u32 reg_bkup[][DPK_KIP_REG_NUM_8851B], u8 path) +{ + u8 i; + + for (i = 0; i < DPK_KIP_REG_NUM_8851B; i++) { + rtw89_phy_write32_mask(rtwdev, reg[i] + (path << 8), MASKDWORD, + reg_bkup[path][i]); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[DPK] Reload 0x%x = %x\n", + reg[i] + (path << 8), reg_bkup[path][i]); + } +} + +static void _dpk_reload_rf(struct rtw89_dev *rtwdev, const u32 *rf_reg, + u32 rf_bkup[][DPK_RF_REG_NUM_8851B], u8 path) +{ + u8 i; + + for (i = 0; i < DPK_RF_REG_NUM_8851B; i++) { + rtw89_write_rf(rtwdev, path, rf_reg[i], RFREG_MASK, rf_bkup[path][i]); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[DPK] Reload RF S%d 0x%x = %x\n", path, + rf_reg[i], rf_bkup[path][i]); + } +} + +static void _dpk_one_shot(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, + enum rtw89_rf_path path, enum dpk_id id) +{ + u16 dpk_cmd; + u32 val; + int ret; + + dpk_cmd = ((id << 8) | (0x19 + path * 0x12)); + rtw89_phy_write32_mask(rtwdev, R_NCTL_CFG, MASKDWORD, dpk_cmd); + + ret = read_poll_timeout_atomic(rtw89_phy_read32_mask, val, val == 0x55, + 10, 20000, false, + rtwdev, 0xbff8, MASKBYTE0); + if (ret) + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] one-shot 1 timeout\n"); + + udelay(1); + + ret = read_poll_timeout_atomic(rtw89_phy_read32_mask, val, val == 0x8000, + 1, 2000, false, + rtwdev, R_RPT_COM, MASKLWORD); + if (ret) + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] one-shot 2 timeout\n"); + + rtw89_phy_write32_mask(rtwdev, R_NCTL_N1, MASKBYTE0, 0x0); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[DPK] one-shot for %s = 0x%04x\n", + id == 0x28 ? "KIP_PRESET" : + id == 0x29 ? "DPK_TXAGC" : + id == 0x2a ? "DPK_RXAGC" : + id == 0x2b ? "SYNC" : + id == 0x2c ? "GAIN_LOSS" : + id == 0x2d ? "MDPK_IDL" : + id == 0x2f ? "DPK_GAIN_NORM" : + id == 0x31 ? "KIP_RESTORE" : + id == 0x6 ? "LBK_RXIQK" : "Unknown id", + dpk_cmd); +} + +static void _dpk_onoff(struct rtw89_dev *rtwdev, enum rtw89_rf_path path, + bool off) +{ + struct rtw89_dpk_info *dpk = &rtwdev->dpk; + u8 kidx = dpk->cur_idx[path]; + u8 off_reverse = off ? 0 : 1; + u8 val; + + val = dpk->is_dpk_enable * off_reverse * dpk->bp[path][kidx].path_ok; + + rtw89_phy_write32_mask(rtwdev, R_DPD_CH0A + (path << 8) + (kidx << 2), + 0xf0000000, val); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] S%d[%d] DPK %s !!!\n", path, + kidx, val == 0 ? "disable" : "enable"); +} + +static void _dpk_init(struct rtw89_dev *rtwdev, enum rtw89_rf_path path) +{ + struct rtw89_dpk_info *dpk = &rtwdev->dpk; + + u8 kidx = dpk->cur_idx[path]; + + dpk->bp[path][kidx].path_ok = 0; +} + +static void _dpk_information(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, + enum rtw89_rf_path path) +{ + const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0); + struct rtw89_dpk_info *dpk = &rtwdev->dpk; + + u8 kidx = dpk->cur_idx[path]; + + dpk->bp[path][kidx].band = chan->band_type; + dpk->bp[path][kidx].ch = chan->band_width; + dpk->bp[path][kidx].bw = chan->channel; + + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[DPK] S%d[%d] (PHY%d): TSSI %s/ DBCC %s/ %s/ CH%d/ %s\n", + path, dpk->cur_idx[path], phy, + rtwdev->is_tssi_mode[path] ? "on" : "off", + rtwdev->dbcc_en ? "on" : "off", + dpk->bp[path][kidx].band == 0 ? "2G" : + dpk->bp[path][kidx].band == 1 ? "5G" : "6G", + dpk->bp[path][kidx].ch, + dpk->bp[path][kidx].bw == 0 ? "20M" : + dpk->bp[path][kidx].bw == 1 ? "40M" : + dpk->bp[path][kidx].bw == 2 ? "80M" : "160M"); +} + +static void _dpk_rxagc_onoff(struct rtw89_dev *rtwdev, enum rtw89_rf_path path, + bool turn_on) +{ + if (path == RF_PATH_A) + rtw89_phy_write32_mask(rtwdev, R_P0_AGC_CTL, B_P0_AGC_EN, turn_on); + else + rtw89_phy_write32_mask(rtwdev, R_P1_AGC_CTL, B_P1_AGC_EN, turn_on); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] S%d RXAGC is %s\n", path, + turn_on ? "turn_on" : "turn_off"); +} + +static void _dpk_bb_afe_setting(struct rtw89_dev *rtwdev, enum rtw89_rf_path path) +{ + rtw89_phy_write32_mask(rtwdev, R_ADC_FIFO, BIT(16 + path), 0x1); + rtw89_phy_write32_mask(rtwdev, R_ADC_FIFO, BIT(20 + path), 0x0); + rtw89_phy_write32_mask(rtwdev, R_ADC_FIFO, BIT(24 + path), 0x1); + rtw89_phy_write32_mask(rtwdev, R_ADC_FIFO, BIT(28 + path), 0x0); + rtw89_phy_write32_mask(rtwdev, R_UPD_CLK + (path << 13), MASKDWORD, 0xd801dffd); + + rtw89_rfk_parser(rtwdev, &rtw8851b_iqk_bb_afe_defs_tbl); + + rtw89_phy_write32_mask(rtwdev, R_ADC_FIFO, BIT(20 + path), 0x1); + rtw89_phy_write32_mask(rtwdev, R_ADC_FIFO, BIT(28 + path), 0x1); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] S%d BB/AFE setting\n", path); +} + +static void _dpk_bb_afe_restore(struct rtw89_dev *rtwdev, enum rtw89_rf_path path) +{ + rtw89_phy_write32_mask(rtwdev, R_P0_NRBW + (path << 13), B_P0_NRBW_DBG, 0x0); + rtw89_phy_write32_mask(rtwdev, R_ADC_FIFO, BIT(16 + path), 0x1); + rtw89_phy_write32_mask(rtwdev, R_ADC_FIFO, BIT(20 + path), 0x0); + rtw89_phy_write32_mask(rtwdev, R_ADC_FIFO, BIT(24 + path), 0x1); + rtw89_phy_write32_mask(rtwdev, R_ADC_FIFO, BIT(28 + path), 0x0); + rtw89_phy_write32_mask(rtwdev, R_UPD_CLK + (path << 13), MASKDWORD, 0x00000000); + rtw89_phy_write32_mask(rtwdev, R_P0_RXCK + (path << 13), B_P0_TXCK_ALL, 0x00); + rtw89_phy_write32_mask(rtwdev, R_ADC_FIFO, BIT(16 + path), 0x0); + rtw89_phy_write32_mask(rtwdev, R_ADC_FIFO, BIT(24 + path), 0x0); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] S%d BB/AFE restore\n", path); +} + +static void _dpk_tssi_pause(struct rtw89_dev *rtwdev, enum rtw89_rf_path path, + bool is_pause) +{ + rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_TRK + (path << 13), + B_P0_TSSI_TRK_EN, is_pause); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] S%d TSSI %s\n", path, + is_pause ? "pause" : "resume"); +} + +static void _dpk_tpg_sel(struct rtw89_dev *rtwdev, enum rtw89_rf_path path, u8 kidx) +{ + struct rtw89_dpk_info *dpk = &rtwdev->dpk; + + if (dpk->bp[path][kidx].bw == RTW89_CHANNEL_WIDTH_80) { + rtw89_phy_write32_mask(rtwdev, R_TPG_MOD, B_TPG_MOD_F, 0x0); + rtw89_phy_write32_mask(rtwdev, R_TPG_SEL, MASKDWORD, 0xffe0fa00); + } else if (dpk->bp[path][kidx].bw == RTW89_CHANNEL_WIDTH_40) { + rtw89_phy_write32_mask(rtwdev, R_TPG_MOD, B_TPG_MOD_F, 0x2); + rtw89_phy_write32_mask(rtwdev, R_TPG_SEL, MASKDWORD, 0xff4009e0); + } else { + rtw89_phy_write32_mask(rtwdev, R_TPG_MOD, B_TPG_MOD_F, 0x1); + rtw89_phy_write32_mask(rtwdev, R_TPG_SEL, MASKDWORD, 0xf9f007d0); + } + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] TPG Select for %s\n", + dpk->bp[path][kidx].bw == RTW89_CHANNEL_WIDTH_80 ? "80M" : + dpk->bp[path][kidx].bw == RTW89_CHANNEL_WIDTH_40 ? "40M" : "20M"); +} + +static void _dpk_txpwr_bb_force(struct rtw89_dev *rtwdev, + enum rtw89_rf_path path, bool force) +{ + rtw89_phy_write32_mask(rtwdev, R_TXPWRB + (path << 13), B_TXPWRB_ON, force); + rtw89_phy_write32_mask(rtwdev, R_TXPWRB_H + (path << 13), B_TXPWRB_RDY, force); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] S%d txpwr_bb_force %s\n", + path, force ? "on" : "off"); +} + +static void _dpk_kip_pwr_clk_onoff(struct rtw89_dev *rtwdev, bool turn_on) +{ + if (turn_on) { + rtw89_phy_write32_mask(rtwdev, R_NCTL_RPT, MASKDWORD, 0x00000080); + rtw89_phy_write32_mask(rtwdev, R_KIP_SYSCFG, MASKDWORD, 0x807f030a); + } else { + rtw89_phy_write32_mask(rtwdev, R_NCTL_RPT, MASKDWORD, 0x00000000); + rtw89_phy_write32_mask(rtwdev, R_KIP_SYSCFG, MASKDWORD, 0x80000000); + rtw89_phy_write32_mask(rtwdev, R_DPK_WR, BIT(18), 0x1); + } +} + +static void _dpk_kip_control_rfc(struct rtw89_dev *rtwdev, + enum rtw89_rf_path path, bool ctrl_by_kip) +{ + rtw89_phy_write32_mask(rtwdev, R_UPD_CLK + (path << 13), + B_IQK_RFC_ON, ctrl_by_kip); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] RFC is controlled by %s\n", + ctrl_by_kip ? "KIP" : "BB"); +} + +static void _dpk_kip_preset(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, + enum rtw89_rf_path path, u8 kidx) +{ + rtw89_phy_write32_mask(rtwdev, R_KIP_MOD, B_KIP_MOD, + rtw89_read_rf(rtwdev, path, RR_MOD, RFREG_MASK)); + rtw89_phy_write32_mask(rtwdev, R_DPD_CH0A + (path << 8) + (kidx << 2), + B_DPD_SEL, 0x01); + + _dpk_kip_control_rfc(rtwdev, path, true); + _dpk_one_shot(rtwdev, phy, path, D_KIP_PRESET); +} + +static void _dpk_kip_restore(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, + enum rtw89_rf_path path) +{ + _dpk_one_shot(rtwdev, phy, path, D_KIP_RESTORE); + _dpk_kip_control_rfc(rtwdev, path, false); + _dpk_txpwr_bb_force(rtwdev, path, false); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] S%d restore KIP\n", path); +} + +static void _dpk_kset_query(struct rtw89_dev *rtwdev, enum rtw89_rf_path path) +{ + struct rtw89_dpk_info *dpk = &rtwdev->dpk; + + rtw89_phy_write32_mask(rtwdev, R_KIP_RPT + (path << 8), B_KIP_RPT_SEL, 0x10); + + dpk->cur_k_set = + rtw89_phy_read32_mask(rtwdev, R_RPT_PER + (path << 8), B_RPT_PER_KSET) - 1; +} + +static void _dpk_para_query(struct rtw89_dev *rtwdev, enum rtw89_rf_path path, u8 kidx) +{ + static const u32 reg[RTW89_DPK_BKUP_NUM][DPK_KSET_NUM] = { + {0x8190, 0x8194, 0x8198, 0x81a4}, + {0x81a8, 0x81c4, 0x81c8, 0x81e8} + }; + struct rtw89_dpk_info *dpk = &rtwdev->dpk; + u8 cur_k_set = dpk->cur_k_set; + u32 para; + + if (cur_k_set >= DPK_KSET_NUM) { + rtw89_warn(rtwdev, "DPK cur_k_set = %d\n", cur_k_set); + cur_k_set = 2; + } + + para = rtw89_phy_read32_mask(rtwdev, reg[kidx][cur_k_set] + (path << 8), + MASKDWORD); + + dpk->bp[path][kidx].txagc_dpk = (para >> 10) & 0x3f; + dpk->bp[path][kidx].ther_dpk = (para >> 26) & 0x3f; + + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[DPK] thermal/ txagc_RF (K%d) = 0x%x/ 0x%x\n", + dpk->cur_k_set, dpk->bp[path][kidx].ther_dpk, + dpk->bp[path][kidx].txagc_dpk); +} + +static bool _dpk_sync_check(struct rtw89_dev *rtwdev, enum rtw89_rf_path path, u8 kidx) +{ + struct rtw89_dpk_info *dpk = &rtwdev->dpk; + u8 corr_val, corr_idx, rxbb; + u16 dc_i, dc_q; + u8 rxbb_ov; + + rtw89_phy_write32_mask(rtwdev, R_KIP_RPT1, B_KIP_RPT1_SEL, 0x0); + + corr_idx = rtw89_phy_read32_mask(rtwdev, R_RPT_COM, B_PRT_COM_CORI); + corr_val = rtw89_phy_read32_mask(rtwdev, R_RPT_COM, B_PRT_COM_CORV); + dpk->corr_idx[path][kidx] = corr_idx; + dpk->corr_val[path][kidx] = corr_val; + + rtw89_phy_write32_mask(rtwdev, R_KIP_RPT1, B_KIP_RPT1_SEL, 0x9); + + dc_i = rtw89_phy_read32_mask(rtwdev, R_RPT_COM, B_PRT_COM_DCI); + dc_q = rtw89_phy_read32_mask(rtwdev, R_RPT_COM, B_PRT_COM_DCQ); + + dc_i = abs(sign_extend32(dc_i, 11)); + dc_q = abs(sign_extend32(dc_q, 11)); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[DPK] S%d Corr_idx/ Corr_val /DC I/Q, = %d / %d / %d / %d\n", + path, corr_idx, corr_val, dc_i, dc_q); + + dpk->dc_i[path][kidx] = dc_i; + dpk->dc_q[path][kidx] = dc_q; + + rtw89_phy_write32_mask(rtwdev, R_KIP_RPT1, B_KIP_RPT1_SEL, 0x8); + rxbb = rtw89_phy_read32_mask(rtwdev, R_RPT_COM, B_PRT_COM_RXBB); + + rtw89_phy_write32_mask(rtwdev, R_KIP_RPT1, B_KIP_RPT1_SEL, 0x31); + rxbb_ov = rtw89_phy_read32_mask(rtwdev, R_RPT_COM, B_PRT_COM_RXOV); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[DPK] S%d RXBB/ RXAGC_done /RXBB_ovlmt = %d / %d / %d\n", + path, rxbb, + rtw89_phy_read32_mask(rtwdev, R_RPT_COM, B_PRT_COM_DONE), + rxbb_ov); + + if (dc_i > 200 || dc_q > 200 || corr_val < 170) + return true; + else + return false; +} + +static void _dpk_kip_set_txagc(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, + enum rtw89_rf_path path, u8 dbm, + bool set_from_bb) +{ + if (set_from_bb) { + dbm = clamp_t(u8, dbm, 7, 24); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[DPK] set S%d txagc to %ddBm\n", path, dbm); + rtw89_phy_write32_mask(rtwdev, R_TXPWRB + (path << 13), + B_TXPWRB_VAL, dbm << 2); + } + + _dpk_one_shot(rtwdev, phy, path, D_TXAGC); + _dpk_kset_query(rtwdev, path); +} + +static bool _dpk_kip_set_rxagc(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, + enum rtw89_rf_path path, u8 kidx) +{ + _dpk_kip_control_rfc(rtwdev, path, false); + rtw89_phy_write32_mask(rtwdev, R_KIP_MOD, B_KIP_MOD, + rtw89_read_rf(rtwdev, path, RR_MOD, RFREG_MASK)); + _dpk_kip_control_rfc(rtwdev, path, true); + + _dpk_one_shot(rtwdev, phy, path, D_RXAGC); + return _dpk_sync_check(rtwdev, path, kidx); +} + +static void _dpk_lbk_rxiqk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, + enum rtw89_rf_path path) +{ + u32 rf_11, reg_81cc; + u8 cur_rxbb; + + rtw89_phy_write32_mask(rtwdev, R_DPD_V1 + (path << 8), B_DPD_LBK, 0x1); + rtw89_phy_write32_mask(rtwdev, R_MDPK_RX_DCK, B_MDPK_RX_DCK_EN, 0x1); + + _dpk_kip_control_rfc(rtwdev, path, false); + + cur_rxbb = rtw89_read_rf(rtwdev, path, RR_MOD, RR_MOD_RXB); + rf_11 = rtw89_read_rf(rtwdev, path, RR_TXIG, RFREG_MASK); + reg_81cc = rtw89_phy_read32_mask(rtwdev, R_KIP_IQP + (path << 8), + B_KIP_IQP_SW); + + rtw89_write_rf(rtwdev, path, RR_TXIG, RR_TXIG_GR0, 0x0); + rtw89_write_rf(rtwdev, path, RR_TXIG, RR_TXIG_GR1, 0x3); + rtw89_write_rf(rtwdev, path, RR_TXIG, RR_TXIG_TG, 0xd); + rtw89_write_rf(rtwdev, path, RR_MOD, RR_MOD_RXB, 0x1f); + + rtw89_phy_write32_mask(rtwdev, R_KIP_IQP + (path << 8), B_KIP_IQP_IQSW, 0x12); + rtw89_phy_write32_mask(rtwdev, R_KIP_IQP + (path << 8), B_KIP_IQP_SW, 0x3); + + _dpk_kip_control_rfc(rtwdev, path, true); + + rtw89_phy_write32_mask(rtwdev, R_IQK_DIF4, MASKDWORD, 0x00250025); + + _dpk_one_shot(rtwdev, phy, path, LBK_RXIQK); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] S%d LBK RXIQC = 0x%x\n", path, + rtw89_phy_read32_mask(rtwdev, R_RXIQC + (path << 8), MASKDWORD)); + + _dpk_kip_control_rfc(rtwdev, path, false); + + rtw89_write_rf(rtwdev, path, RR_TXIG, RFREG_MASK, rf_11); + rtw89_write_rf(rtwdev, path, RR_MOD, RR_MOD_RXB, cur_rxbb); + rtw89_phy_write32_mask(rtwdev, R_KIP_IQP + (path << 8), B_KIP_IQP_SW, reg_81cc); + + rtw89_phy_write32_mask(rtwdev, R_MDPK_RX_DCK, B_MDPK_RX_DCK_EN, 0x0); + rtw89_phy_write32_mask(rtwdev, R_KPATH_CFG, B_KPATH_CFG_ED, 0x0); + rtw89_phy_write32_mask(rtwdev, R_LOAD_COEF + (path << 8), B_LOAD_COEF_DI, 0x1); + + _dpk_kip_control_rfc(rtwdev, path, true); +} + +static void _dpk_rf_setting(struct rtw89_dev *rtwdev, enum rtw89_rf_path path, u8 kidx) +{ + struct rtw89_dpk_info *dpk = &rtwdev->dpk; + + if (dpk->bp[path][kidx].band == RTW89_BAND_2G) { + rtw89_write_rf(rtwdev, path, RR_MOD, RFREG_MASK, 0x50521); + rtw89_write_rf(rtwdev, path, RR_MOD_V1, RR_MOD_MASK, RF_DPK); + rtw89_write_rf(rtwdev, path, RR_RXBB, RR_RXBB_ATTC, 0x0); + rtw89_write_rf(rtwdev, path, RR_RXBB, RR_RXBB_ATTR, 0x7); + } else { + rtw89_write_rf(rtwdev, path, RR_MOD, RFREG_MASK, + 0x50521 | BIT(rtwdev->dbcc_en)); + rtw89_write_rf(rtwdev, path, RR_MOD_V1, RR_MOD_MASK, RF_DPK); + rtw89_write_rf(rtwdev, path, RR_RXA2, RR_RAA2_SATT, 0x3); + } + + rtw89_write_rf(rtwdev, path, RR_RCKD, RR_RCKD_BW, 0x1); + rtw89_write_rf(rtwdev, path, RR_BTC, RR_BTC_TXBB, dpk->bp[path][kidx].bw + 1); + rtw89_write_rf(rtwdev, path, RR_BTC, RR_BTC_RXBB, 0x0); + rtw89_write_rf(rtwdev, path, RR_RXBB2, RR_RXBB2_EBW, 0x0); +} + +static void _dpk_bypass_rxiqc(struct rtw89_dev *rtwdev, enum rtw89_rf_path path) +{ + rtw89_phy_write32_mask(rtwdev, R_DPD_V1 + (path << 8), B_DPD_LBK, 0x1); + rtw89_phy_write32_mask(rtwdev, R_RXIQC + (path << 8), MASKDWORD, 0x40000002); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] Bypass RXIQC\n"); +} + +static u16 _dpk_dgain_read(struct rtw89_dev *rtwdev) +{ + u16 dgain; + + rtw89_phy_write32_mask(rtwdev, R_KIP_RPT1, B_KIP_RPT1_SEL, 0x0); + dgain = rtw89_phy_read32_mask(rtwdev, R_RPT_COM, B_PRT_COM_DCI); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] DGain = 0x%x\n", dgain); + + return dgain; +} + +static u8 _dpk_gainloss_read(struct rtw89_dev *rtwdev) +{ + u8 result; + + rtw89_phy_write32_mask(rtwdev, R_KIP_RPT1, B_KIP_RPT1_SEL, 0x6); + rtw89_phy_write32_mask(rtwdev, R_DPK_CFG2, B_DPK_CFG2_ST, 0x1); + result = rtw89_phy_read32_mask(rtwdev, R_RPT_COM, B_PRT_COM_GL); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] tmp GL = %d\n", result); + + return result; +} + +static u8 _dpk_gainloss(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, + enum rtw89_rf_path path, u8 kidx) +{ + _dpk_one_shot(rtwdev, phy, path, D_GAIN_LOSS); + _dpk_kip_set_txagc(rtwdev, phy, path, 0xff, false); + + rtw89_phy_write32_mask(rtwdev, R_DPK_GL + (path << 8), B_DPK_GL_A1, 0xf078); + rtw89_phy_write32_mask(rtwdev, R_DPK_GL + (path << 8), B_DPK_GL_A0, 0x0); + + return _dpk_gainloss_read(rtwdev); +} + +static u8 _dpk_pas_read(struct rtw89_dev *rtwdev, u8 is_check) +{ + u32 val1_i = 0, val1_q = 0, val2_i = 0, val2_q = 0; + u32 val1_sqrt_sum, val2_sqrt_sum; + u8 i; + + rtw89_phy_write32_mask(rtwdev, R_KIP_RPT1, MASKBYTE2, 0x06); + rtw89_phy_write32_mask(rtwdev, R_DPK_CFG2, B_DPK_CFG2_ST, 0x0); + rtw89_phy_write32_mask(rtwdev, R_DPK_CFG3, MASKBYTE2, 0x08); + + if (is_check) { + rtw89_phy_write32_mask(rtwdev, R_DPK_CFG3, MASKBYTE3, 0x00); + val1_i = rtw89_phy_read32_mask(rtwdev, R_RPT_COM, MASKHWORD); + val1_i = abs(sign_extend32(val1_i, 11)); + val1_q = rtw89_phy_read32_mask(rtwdev, R_RPT_COM, MASKLWORD); + val1_q = abs(sign_extend32(val1_q, 11)); + + rtw89_phy_write32_mask(rtwdev, R_DPK_CFG3, MASKBYTE3, 0x1f); + val2_i = rtw89_phy_read32_mask(rtwdev, R_RPT_COM, MASKHWORD); + val2_i = abs(sign_extend32(val2_i, 11)); + val2_q = rtw89_phy_read32_mask(rtwdev, R_RPT_COM, MASKLWORD); + val2_q = abs(sign_extend32(val2_q, 11)); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] PAS_delta = 0x%x\n", + phy_div(val1_i * val1_i + val1_q * val1_q, + val2_i * val2_i + val2_q * val2_q)); + } else { + for (i = 0; i < 32; i++) { + rtw89_phy_write32_mask(rtwdev, R_DPK_CFG3, MASKBYTE3, i); + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[DPK] PAS_Read[%02d]= 0x%08x\n", i, + rtw89_phy_read32_mask(rtwdev, R_RPT_COM, MASKDWORD)); + } + } + + val1_sqrt_sum = val1_i * val1_i + val1_q * val1_q; + val2_sqrt_sum = val2_i * val2_i + val2_q * val2_q; + + if (val1_sqrt_sum < val2_sqrt_sum) + return 2; + else if (val1_sqrt_sum >= val2_sqrt_sum * 8 / 5) + return 1; + else + return 0; +} + +static u8 _dpk_agc(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, + enum rtw89_rf_path path, u8 kidx, u8 init_xdbm, u8 loss_only) +{ + struct rtw89_dpk_info *dpk = &rtwdev->dpk; + u8 tmp_dbm = init_xdbm, tmp_gl_idx = 0; + u8 step = DPK_AGC_STEP_SYNC_DGAIN; + u8 goout = 0, agc_cnt = 0; + bool is_fail = false; + int limit = 200; + u8 tmp_rxbb; + u16 dgain; + + do { + switch (step) { + case DPK_AGC_STEP_SYNC_DGAIN: + is_fail = _dpk_kip_set_rxagc(rtwdev, phy, path, kidx); + + if (is_fail) { + goout = 1; + break; + } + + dgain = _dpk_dgain_read(rtwdev); + + if (dgain > 0x5fc || dgain < 0x556) { + _dpk_one_shot(rtwdev, phy, path, D_SYNC); + dgain = _dpk_dgain_read(rtwdev); + } + + if (agc_cnt == 0) { + if (dpk->bp[path][kidx].band == RTW89_BAND_2G) + _dpk_bypass_rxiqc(rtwdev, path); + else + _dpk_lbk_rxiqk(rtwdev, phy, path); + } + step = DPK_AGC_STEP_GAIN_LOSS_IDX; + break; + + case DPK_AGC_STEP_GAIN_LOSS_IDX: + tmp_gl_idx = _dpk_gainloss(rtwdev, phy, path, kidx); + + if (_dpk_pas_read(rtwdev, true) == 2 && tmp_gl_idx > 0) + step = DPK_AGC_STEP_GL_LT_CRITERION; + else if ((tmp_gl_idx == 0 && _dpk_pas_read(rtwdev, true) == 1) || + tmp_gl_idx >= 7) + step = DPK_AGC_STEP_GL_GT_CRITERION; + else if (tmp_gl_idx == 0) + step = DPK_AGC_STEP_GL_LT_CRITERION; + else + step = DPK_AGC_STEP_SET_TX_GAIN; + break; + + case DPK_AGC_STEP_GL_GT_CRITERION: + if (tmp_dbm <= 7) { + goout = 1; + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[DPK] Txagc@lower bound!!\n"); + } else { + tmp_dbm = max_t(u8, tmp_dbm - 3, 7); + _dpk_kip_set_txagc(rtwdev, phy, path, tmp_dbm, true); + } + step = DPK_AGC_STEP_SYNC_DGAIN; + agc_cnt++; + break; + + case DPK_AGC_STEP_GL_LT_CRITERION: + if (tmp_dbm >= 24) { + goout = 1; + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[DPK] Txagc@upper bound!!\n"); + } else { + tmp_dbm = min_t(u8, tmp_dbm + 2, 24); + _dpk_kip_set_txagc(rtwdev, phy, path, tmp_dbm, true); + } + step = DPK_AGC_STEP_SYNC_DGAIN; + agc_cnt++; + break; + + case DPK_AGC_STEP_SET_TX_GAIN: + _dpk_kip_control_rfc(rtwdev, path, false); + tmp_rxbb = rtw89_read_rf(rtwdev, path, RR_MOD, RR_MOD_RXB); + tmp_rxbb = min_t(u8, tmp_rxbb + tmp_gl_idx, 0x1f); + + rtw89_write_rf(rtwdev, path, RR_MOD, RR_MOD_RXB, tmp_rxbb); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[DPK] Adjust RXBB (%+d) = 0x%x\n", + tmp_gl_idx, tmp_rxbb); + _dpk_kip_control_rfc(rtwdev, path, true); + goout = 1; + break; + default: + goout = 1; + break; + } + } while (!goout && agc_cnt < 6 && limit-- > 0); + + return is_fail; +} + +static void _dpk_set_mdpd_para(struct rtw89_dev *rtwdev, u8 order) +{ + switch (order) { + case 0: /* (5,3,1) */ + rtw89_phy_write32_mask(rtwdev, R_LDL_NORM, B_LDL_NORM_OP, 0x0); + rtw89_phy_write32_mask(rtwdev, R_DPK_IDL, B_DPK_IDL_SEL, 0x2); + rtw89_phy_write32_mask(rtwdev, R_LDL_NORM, B_LDL_NORM_PN, 0x4); + rtw89_phy_write32_mask(rtwdev, R_MDPK_SYNC, B_MDPK_SYNC_DMAN, 0x1); + break; + case 1: /* (5,3,0) */ + rtw89_phy_write32_mask(rtwdev, R_LDL_NORM, B_LDL_NORM_OP, 0x1); + rtw89_phy_write32_mask(rtwdev, R_DPK_IDL, B_DPK_IDL_SEL, 0x1); + rtw89_phy_write32_mask(rtwdev, R_LDL_NORM, B_LDL_NORM_PN, 0x0); + rtw89_phy_write32_mask(rtwdev, R_MDPK_SYNC, B_MDPK_SYNC_DMAN, 0x0); + break; + case 2: /* (5,0,0) */ + rtw89_phy_write32_mask(rtwdev, R_LDL_NORM, B_LDL_NORM_OP, 0x2); + rtw89_phy_write32_mask(rtwdev, R_DPK_IDL, B_DPK_IDL_SEL, 0x0); + rtw89_phy_write32_mask(rtwdev, R_LDL_NORM, B_LDL_NORM_PN, 0x0); + rtw89_phy_write32_mask(rtwdev, R_MDPK_SYNC, B_MDPK_SYNC_DMAN, 0x0); + break; + case 3: /* (7,3,1) */ + rtw89_phy_write32_mask(rtwdev, R_LDL_NORM, B_LDL_NORM_OP, 0x3); + rtw89_phy_write32_mask(rtwdev, R_DPK_IDL, B_DPK_IDL_SEL, 0x3); + rtw89_phy_write32_mask(rtwdev, R_LDL_NORM, B_LDL_NORM_PN, 0x4); + rtw89_phy_write32_mask(rtwdev, R_MDPK_SYNC, B_MDPK_SYNC_DMAN, 0x1); + break; + default: + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[DPK] Wrong MDPD order!!(0x%x)\n", order); + break; + } + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] Set %s for IDL\n", + order == 0x0 ? "(5,3,1)" : + order == 0x1 ? "(5,3,0)" : + order == 0x2 ? "(5,0,0)" : "(7,3,1)"); +} + +static void _dpk_idl_mpa(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, + enum rtw89_rf_path path, u8 kidx) +{ + rtw89_phy_write32_mask(rtwdev, R_LDL_NORM, B_LDL_NORM_MA, 0x1); + + if (rtw89_phy_read32_mask(rtwdev, R_IDL_MPA, B_IDL_MD500) == 0x1) + _dpk_set_mdpd_para(rtwdev, 0x2); + else if (rtw89_phy_read32_mask(rtwdev, R_IDL_MPA, B_IDL_MD530) == 0x1) + _dpk_set_mdpd_para(rtwdev, 0x1); + else + _dpk_set_mdpd_para(rtwdev, 0x0); + + rtw89_phy_write32_mask(rtwdev, R_DPK_IDL, B_DPK_IDL, 0x0); + fsleep(1000); + + _dpk_one_shot(rtwdev, phy, path, D_MDPK_IDL); +} + +static u8 _dpk_order_convert(struct rtw89_dev *rtwdev) +{ + u32 order; + u8 val; + + order = rtw89_phy_read32_mask(rtwdev, R_LDL_NORM, B_LDL_NORM_OP); + + switch (order) { + case 0: /* (5,3,1) */ + val = 0x6; + break; + case 1: /* (5,3,0) */ + val = 0x2; + break; + case 2: /* (5,0,0) */ + val = 0x0; + break; + default: + val = 0xff; + break; + } + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] convert MDPD order to 0x%x\n", val); + + return val; +} + +static void _dpk_gain_normalize(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, + enum rtw89_rf_path path, u8 kidx, bool is_execute) +{ + static const u32 reg[RTW89_DPK_BKUP_NUM][DPK_KSET_NUM] = { + {0x8190, 0x8194, 0x8198, 0x81a4}, + {0x81a8, 0x81c4, 0x81c8, 0x81e8} + }; + struct rtw89_dpk_info *dpk = &rtwdev->dpk; + u8 cur_k_set = dpk->cur_k_set; + + if (cur_k_set >= DPK_KSET_NUM) { + rtw89_warn(rtwdev, "DPK cur_k_set = %d\n", cur_k_set); + cur_k_set = 2; + } + + if (is_execute) { + rtw89_phy_write32_mask(rtwdev, R_DPK_GN + (path << 8), + B_DPK_GN_AG, 0x200); + rtw89_phy_write32_mask(rtwdev, R_DPK_GN + (path << 8), + B_DPK_GN_EN, 0x3); + + _dpk_one_shot(rtwdev, phy, path, D_GAIN_NORM); + } else { + rtw89_phy_write32_mask(rtwdev, reg[kidx][cur_k_set] + (path << 8), + 0x0000007F, 0x5b); + } + + dpk->bp[path][kidx].gs = + rtw89_phy_read32_mask(rtwdev, reg[kidx][cur_k_set] + (path << 8), + 0x0000007F); +} + +static void _dpk_on(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, + enum rtw89_rf_path path, u8 kidx) +{ + struct rtw89_dpk_info *dpk = &rtwdev->dpk; + + rtw89_phy_write32_mask(rtwdev, R_LOAD_COEF + (path << 8), B_LOAD_COEF_MDPD, 0x1); + rtw89_phy_write32_mask(rtwdev, R_LOAD_COEF + (path << 8), B_LOAD_COEF_MDPD, 0x0); + rtw89_phy_write32_mask(rtwdev, R_DPD_CH0A + (path << 8) + (kidx << 2), + B_DPD_ORDER, _dpk_order_convert(rtwdev)); + + dpk->bp[path][kidx].path_ok = + dpk->bp[path][kidx].path_ok | BIT(dpk->cur_k_set); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] S%d[%d] path_ok = 0x%x\n", + path, kidx, dpk->bp[path][kidx].path_ok); + + rtw89_phy_write32_mask(rtwdev, R_DPD_CH0A + (path << 8) + (kidx << 2), + B_DPD_MEN, dpk->bp[path][kidx].path_ok); + + _dpk_gain_normalize(rtwdev, phy, path, kidx, false); +} + +static bool _dpk_main(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, + enum rtw89_rf_path path) +{ + struct rtw89_dpk_info *dpk = &rtwdev->dpk; + u8 kidx = dpk->cur_idx[path]; + u8 init_xdbm = 17; + bool is_fail; + + if (dpk->bp[path][kidx].band != RTW89_BAND_2G) + init_xdbm = 15; + + _dpk_kip_control_rfc(rtwdev, path, false); + _rfk_rf_direct_cntrl(rtwdev, path, false); + rtw89_write_rf(rtwdev, path, RR_BBDC, RFREG_MASK, 0x03ffd); + + _dpk_rf_setting(rtwdev, path, kidx); + _set_rx_dck(rtwdev, path, RF_DPK); + + _dpk_kip_pwr_clk_onoff(rtwdev, true); + _dpk_kip_preset(rtwdev, phy, path, kidx); + _dpk_txpwr_bb_force(rtwdev, path, true); + _dpk_kip_set_txagc(rtwdev, phy, path, init_xdbm, true); + _dpk_tpg_sel(rtwdev, path, kidx); + is_fail = _dpk_agc(rtwdev, phy, path, kidx, init_xdbm, false); + if (is_fail) + goto _error; + + _dpk_idl_mpa(rtwdev, phy, path, kidx); + _dpk_para_query(rtwdev, path, kidx); + + _dpk_on(rtwdev, phy, path, kidx); +_error: + _dpk_kip_control_rfc(rtwdev, path, false); + rtw89_write_rf(rtwdev, path, RR_MOD, RR_MOD_MASK, RF_RX); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] S%d[%d]_K%d %s\n", path, kidx, + dpk->cur_k_set, is_fail ? "need Check" : "is Success"); + + return is_fail; +} + +static void _dpk_cal_select(struct rtw89_dev *rtwdev, bool force, + enum rtw89_phy_idx phy, u8 kpath) +{ + struct rtw89_dpk_info *dpk = &rtwdev->dpk; + u32 kip_bkup[RF_PATH_NUM_8851B][DPK_KIP_REG_NUM_8851B] = {}; + u32 rf_bkup[RF_PATH_NUM_8851B][DPK_RF_REG_NUM_8851B] = {}; + bool is_fail; + u8 path; + + for (path = 0; path < RF_PATH_NUM_8851B; path++) + dpk->cur_idx[path] = 0; + + for (path = 0; path < RF_PATH_NUM_8851B; path++) { + if (!(kpath & BIT(path))) + continue; + _dpk_bkup_kip(rtwdev, dpk_kip_reg, kip_bkup, path); + _dpk_bkup_rf(rtwdev, dpk_rf_reg, rf_bkup, path); + _dpk_information(rtwdev, phy, path); + _dpk_init(rtwdev, path); + + if (rtwdev->is_tssi_mode[path]) + _dpk_tssi_pause(rtwdev, path, true); + } + + for (path = 0; path < RF_PATH_NUM_8851B; path++) { + if (!(kpath & BIT(path))) + continue; + + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[DPK] ========= S%d[%d] DPK Start =========\n", + path, dpk->cur_idx[path]); + + _dpk_rxagc_onoff(rtwdev, path, false); + _rfk_drf_direct_cntrl(rtwdev, path, false); + _dpk_bb_afe_setting(rtwdev, path); + + is_fail = _dpk_main(rtwdev, phy, path); + _dpk_onoff(rtwdev, path, is_fail); + } + + for (path = 0; path < RF_PATH_NUM_8851B; path++) { + if (!(kpath & BIT(path))) + continue; + + _dpk_kip_restore(rtwdev, phy, path); + _dpk_reload_kip(rtwdev, dpk_kip_reg, kip_bkup, path); + _dpk_reload_rf(rtwdev, dpk_rf_reg, rf_bkup, path); + _dpk_bb_afe_restore(rtwdev, path); + _dpk_rxagc_onoff(rtwdev, path, true); + + if (rtwdev->is_tssi_mode[path]) + _dpk_tssi_pause(rtwdev, path, false); + } + + _dpk_kip_pwr_clk_onoff(rtwdev, false); +} + +static void _dpk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, bool force) +{ + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[DPK] ****** 8851B DPK Start (Ver: 0x%x, Cv: %d) ******\n", + DPK_VER_8851B, rtwdev->hal.cv); + + _dpk_cal_select(rtwdev, force, phy, _kpath(rtwdev, phy)); +} + +static void _dpk_track(struct rtw89_dev *rtwdev) +{ + struct rtw89_dpk_info *dpk = &rtwdev->dpk; + s8 txagc_bb, txagc_bb_tp, txagc_ofst; + s16 pwsf_tssi_ofst; + s8 delta_ther = 0; + u8 path, kidx; + u8 txagc_rf; + u8 cur_ther; + + for (path = 0; path < RF_PATH_NUM_8851B; path++) { + kidx = dpk->cur_idx[path]; + + rtw89_debug(rtwdev, RTW89_DBG_RFK_TRACK, + "[DPK_TRK] ================[S%d[%d] (CH %d)]================\n", + path, kidx, dpk->bp[path][kidx].ch); + + txagc_rf = rtw89_phy_read32_mask(rtwdev, R_TXAGC_BB + (path << 13), + B_TXAGC_RF); + txagc_bb = rtw89_phy_read32_mask(rtwdev, R_TXAGC_BB + (path << 13), + MASKBYTE2); + txagc_bb_tp = rtw89_phy_read32_mask(rtwdev, R_TXAGC_BTP + (path << 13), + B_TXAGC_BTP); + + rtw89_phy_write32_mask(rtwdev, R_KIP_RPT + (path << 8), + B_KIP_RPT_SEL, 0xf); + cur_ther = rtw89_phy_read32_mask(rtwdev, R_RPT_PER + (path << 8), + B_RPT_PER_TH); + txagc_ofst = rtw89_phy_read32_mask(rtwdev, R_RPT_PER + (path << 8), + B_RPT_PER_OF); + pwsf_tssi_ofst = rtw89_phy_read32_mask(rtwdev, R_RPT_PER + (path << 8), + B_RPT_PER_TSSI); + pwsf_tssi_ofst = sign_extend32(pwsf_tssi_ofst, 12); + + delta_ther = cur_ther - dpk->bp[path][kidx].ther_dpk; + + delta_ther = delta_ther * 2 / 3; + + rtw89_debug(rtwdev, RTW89_DBG_RFK_TRACK, + "[DPK_TRK] extra delta_ther = %d (0x%x / 0x%x@k)\n", + delta_ther, cur_ther, dpk->bp[path][kidx].ther_dpk); + + rtw89_debug(rtwdev, RTW89_DBG_RFK_TRACK, + "[DPK_TRK] delta_txagc = %d (0x%x / 0x%x@k)\n", + txagc_rf - dpk->bp[path][kidx].txagc_dpk, + txagc_rf, dpk->bp[path][kidx].txagc_dpk); + + rtw89_debug(rtwdev, RTW89_DBG_RFK_TRACK, + "[DPK_TRK] txagc_offset / pwsf_tssi_ofst = 0x%x / %+d\n", + txagc_ofst, pwsf_tssi_ofst); + + rtw89_debug(rtwdev, RTW89_DBG_RFK_TRACK, + "[DPK_TRK] txagc_bb_tp / txagc_bb = 0x%x / 0x%x\n", + txagc_bb_tp, txagc_bb); + + if (rtw89_phy_read32_mask(rtwdev, R_IDL_MPA, B_IDL_DN) == 0x0 && + txagc_rf != 0) { + rtw89_debug(rtwdev, RTW89_DBG_RFK_TRACK, + "[DPK_TRK] New pwsf = 0x%x\n", 0x78 - delta_ther); + + rtw89_phy_write32_mask(rtwdev, + R_DPD_BND + (path << 8) + (kidx << 2), + 0x07FC0000, 0x78 - delta_ther); + } + } +} + +static void _rck(struct rtw89_dev *rtwdev, enum rtw89_rf_path path) +{ + u32 rf_reg5; + u32 rck_val; + u32 val; + int ret; + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[RCK] ====== S%d RCK ======\n", path); + + rf_reg5 = rtw89_read_rf(rtwdev, path, RR_RSV1, RFREG_MASK); + + rtw89_write_rf(rtwdev, path, RR_RSV1, RR_RSV1_RST, 0x0); + rtw89_write_rf(rtwdev, path, RR_MOD, RR_MOD_MASK, RR_MOD_V_RX); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[RCK] RF0x00 = 0x%05x\n", + rtw89_read_rf(rtwdev, path, RR_MOD, RFREG_MASK)); + + /* RCK trigger */ + rtw89_write_rf(rtwdev, path, RR_RCKC, RFREG_MASK, 0x00240); + + ret = read_poll_timeout_atomic(rtw89_read_rf, val, val, 2, 30, + false, rtwdev, path, RR_RCKS, BIT(3)); + + rck_val = rtw89_read_rf(rtwdev, path, RR_RCKC, RR_RCKC_CA); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[RCK] rck_val = 0x%x, ret = %d\n", + rck_val, ret); + + rtw89_write_rf(rtwdev, path, RR_RCKC, RFREG_MASK, rck_val); + rtw89_write_rf(rtwdev, path, RR_RSV1, RFREG_MASK, rf_reg5); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[RCK] RF 0x1b = 0x%x\n", + rtw89_read_rf(rtwdev, path, RR_RCKC, RFREG_MASK)); +} + +static void _tssi_set_sys(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, + enum rtw89_rf_path path) +{ + const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0); + enum rtw89_band band = chan->band_type; + + rtw89_rfk_parser(rtwdev, &rtw8851b_tssi_sys_defs_tbl); + + rtw89_rfk_parser_by_cond(rtwdev, band == RTW89_BAND_2G, + &rtw8851b_tssi_sys_a_defs_2g_tbl, + &rtw8851b_tssi_sys_a_defs_5g_tbl); +} + +static void _tssi_ini_txpwr_ctrl_bb(struct rtw89_dev *rtwdev, + enum rtw89_phy_idx phy, + enum rtw89_rf_path path) +{ + rtw89_rfk_parser(rtwdev, &rtw8851b_tssi_init_txpwr_defs_a_tbl); +} + +static void _tssi_ini_txpwr_ctrl_bb_he_tb(struct rtw89_dev *rtwdev, + enum rtw89_phy_idx phy, + enum rtw89_rf_path path) +{ + rtw89_rfk_parser(rtwdev, &rtw8851b_tssi_init_txpwr_he_tb_defs_a_tbl); +} + +static void _tssi_set_dck(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, + enum rtw89_rf_path path) +{ + rtw89_rfk_parser(rtwdev, &rtw8851b_tssi_dck_defs_a_tbl); +} + +static void _tssi_set_tmeter_tbl(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, + enum rtw89_rf_path path) +{ +#define RTW8851B_TSSI_GET_VAL(ptr, idx) \ +({ \ + s8 *__ptr = (ptr); \ + u8 __idx = (idx), __i, __v; \ + u32 __val = 0; \ + for (__i = 0; __i < 4; __i++) { \ + __v = (__ptr[__idx + __i]); \ + __val |= (__v << (8 * __i)); \ + } \ + __val; \ +}) + struct rtw89_tssi_info *tssi_info = &rtwdev->tssi; + const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0); + u8 ch = chan->channel; + u8 subband = chan->subband_type; + const s8 *thm_up_a = NULL; + const s8 *thm_down_a = NULL; + u8 thermal = 0xff; + s8 thm_ofst[64] = {0}; + u32 tmp = 0; + u8 i, j; + + switch (subband) { + default: + case RTW89_CH_2G: + thm_up_a = rtw89_8851b_trk_cfg.delta_swingidx_2ga_p; + thm_down_a = rtw89_8851b_trk_cfg.delta_swingidx_2ga_n; + break; + case RTW89_CH_5G_BAND_1: + thm_up_a = rtw89_8851b_trk_cfg.delta_swingidx_5ga_p[0]; + thm_down_a = rtw89_8851b_trk_cfg.delta_swingidx_5ga_n[0]; + break; + case RTW89_CH_5G_BAND_3: + thm_up_a = rtw89_8851b_trk_cfg.delta_swingidx_5ga_p[1]; + thm_down_a = rtw89_8851b_trk_cfg.delta_swingidx_5ga_n[1]; + break; + case RTW89_CH_5G_BAND_4: + thm_up_a = rtw89_8851b_trk_cfg.delta_swingidx_5ga_p[2]; + thm_down_a = rtw89_8851b_trk_cfg.delta_swingidx_5ga_n[2]; + break; + } + + if (path == RF_PATH_A) { + thermal = tssi_info->thermal[RF_PATH_A]; + + rtw89_debug(rtwdev, RTW89_DBG_TSSI, + "[TSSI] ch=%d thermal_pathA=0x%x\n", ch, thermal); + + rtw89_phy_write32_mask(rtwdev, R_P0_TMETER, B_P0_TMETER_DIS, 0x0); + rtw89_phy_write32_mask(rtwdev, R_P0_TMETER, B_P0_TMETER_TRK, 0x1); + + if (thermal == 0xff) { + rtw89_phy_write32_mask(rtwdev, R_P0_TMETER, B_P0_TMETER, 32); + rtw89_phy_write32_mask(rtwdev, R_P0_RFCTM, B_P0_RFCTM_VAL, 32); + + for (i = 0; i < 64; i += 4) { + rtw89_phy_write32(rtwdev, R_P0_TSSI_BASE + i, 0x0); + + rtw89_debug(rtwdev, RTW89_DBG_TSSI, + "[TSSI] write 0x%x val=0x%08x\n", + R_P0_TSSI_BASE + i, 0x0); + } + + } else { + rtw89_phy_write32_mask(rtwdev, R_P0_TMETER, B_P0_TMETER, + thermal); + rtw89_phy_write32_mask(rtwdev, R_P0_RFCTM, B_P0_RFCTM_VAL, + thermal); + + i = 0; + for (j = 0; j < 32; j++) + thm_ofst[j] = i < DELTA_SWINGIDX_SIZE ? + -thm_down_a[i++] : + -thm_down_a[DELTA_SWINGIDX_SIZE - 1]; + + i = 1; + for (j = 63; j >= 32; j--) + thm_ofst[j] = i < DELTA_SWINGIDX_SIZE ? + thm_up_a[i++] : + thm_up_a[DELTA_SWINGIDX_SIZE - 1]; + + for (i = 0; i < 64; i += 4) { + tmp = RTW8851B_TSSI_GET_VAL(thm_ofst, i); + rtw89_phy_write32(rtwdev, R_P0_TSSI_BASE + i, tmp); + + rtw89_debug(rtwdev, RTW89_DBG_TSSI, + "[TSSI] write 0x%x val=0x%08x\n", + 0x5c00 + i, tmp); + } + } + rtw89_phy_write32_mask(rtwdev, R_P0_RFCTM, R_P0_RFCTM_RDY, 0x1); + rtw89_phy_write32_mask(rtwdev, R_P0_RFCTM, R_P0_RFCTM_RDY, 0x0); + } +#undef RTW8851B_TSSI_GET_VAL +} + +static void _tssi_set_dac_gain_tbl(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, + enum rtw89_rf_path path) +{ + rtw89_rfk_parser(rtwdev, &rtw8851b_tssi_dac_gain_defs_a_tbl); +} + +static void _tssi_slope_cal_org(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, + enum rtw89_rf_path path) +{ + const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0); + enum rtw89_band band = chan->band_type; + + rtw89_rfk_parser_by_cond(rtwdev, band == RTW89_BAND_2G, + &rtw8851b_tssi_slope_a_defs_2g_tbl, + &rtw8851b_tssi_slope_a_defs_5g_tbl); +} + +static void _tssi_alignment_default(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, + enum rtw89_rf_path path, bool all) +{ + const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0); + enum rtw89_band band = chan->band_type; + + rtw89_rfk_parser_by_cond(rtwdev, band == RTW89_BAND_2G, + &rtw8851b_tssi_align_a_2g_defs_tbl, + &rtw8851b_tssi_align_a_5g_defs_tbl); +} + +static void _tssi_set_tssi_slope(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, + enum rtw89_rf_path path) +{ + rtw89_rfk_parser(rtwdev, &rtw8851b_tssi_slope_defs_a_tbl); +} + +static void _tssi_set_tssi_track(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, + enum rtw89_rf_path path) +{ + rtw89_rfk_parser(rtwdev, &rtw8851b_tssi_track_defs_a_tbl); +} + +static void _tssi_set_txagc_offset_mv_avg(struct rtw89_dev *rtwdev, + enum rtw89_phy_idx phy, + enum rtw89_rf_path path) +{ + rtw89_rfk_parser(rtwdev, &rtw8851b_tssi_mv_avg_defs_a_tbl); +} + +static void _tssi_enable(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy) +{ + _tssi_set_tssi_track(rtwdev, phy, RF_PATH_A); + _tssi_set_txagc_offset_mv_avg(rtwdev, phy, RF_PATH_A); + + rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_MV_AVG, B_P0_TSSI_MV_CLR, 0x0); + rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_AVG, B_P0_TSSI_EN, 0x0); + rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_AVG, B_P0_TSSI_EN, 0x1); + rtw89_write_rf(rtwdev, RF_PATH_A, RR_TXGA_V1, RR_TXGA_V1_TRK_EN, 0x1); + + rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_TRK, B_P0_TSSI_OFT_EN, 0x0); + rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_TRK, B_P0_TSSI_RFC, 0x3); + rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_TRK, B_P0_TSSI_OFT, 0xc0); + rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_TRK, B_P0_TSSI_OFT_EN, 0x0); + rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_TRK, B_P0_TSSI_OFT_EN, 0x1); + + rtwdev->is_tssi_mode[RF_PATH_A] = true; +} + +static void _tssi_disable(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy) +{ + rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_AVG, B_P0_TSSI_EN, 0x0); + rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_TRK, B_P0_TSSI_OFT_EN, 0x0); + rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_TRK, B_P0_TSSI_OFT_EN, 0x1); + rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_TRK, B_P0_TSSI_OFT_EN, 0x0); + rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_MV_AVG, B_P0_TSSI_MV_CLR, 0x1); + + rtwdev->is_tssi_mode[RF_PATH_A] = false; +} + +static u32 _tssi_get_cck_group(struct rtw89_dev *rtwdev, u8 ch) +{ + switch (ch) { + case 1 ... 2: + return 0; + case 3 ... 5: + return 1; + case 6 ... 8: + return 2; + case 9 ... 11: + return 3; + case 12 ... 13: + return 4; + case 14: + return 5; + } + + return 0; +} + +#define TSSI_EXTRA_GROUP_BIT (BIT(31)) +#define TSSI_EXTRA_GROUP(idx) (TSSI_EXTRA_GROUP_BIT | (idx)) +#define IS_TSSI_EXTRA_GROUP(group) ((group) & TSSI_EXTRA_GROUP_BIT) +#define TSSI_EXTRA_GET_GROUP_IDX1(group) ((group) & ~TSSI_EXTRA_GROUP_BIT) +#define TSSI_EXTRA_GET_GROUP_IDX2(group) (TSSI_EXTRA_GET_GROUP_IDX1(group) + 1) + +static u32 _tssi_get_ofdm_group(struct rtw89_dev *rtwdev, u8 ch) +{ + switch (ch) { + case 1 ... 2: + return 0; + case 3 ... 5: + return 1; + case 6 ... 8: + return 2; + case 9 ... 11: + return 3; + case 12 ... 14: + return 4; + case 36 ... 40: + return 5; + case 41 ... 43: + return TSSI_EXTRA_GROUP(5); + case 44 ... 48: + return 6; + case 49 ... 51: + return TSSI_EXTRA_GROUP(6); + case 52 ... 56: + return 7; + case 57 ... 59: + return TSSI_EXTRA_GROUP(7); + case 60 ... 64: + return 8; + case 100 ... 104: + return 9; + case 105 ... 107: + return TSSI_EXTRA_GROUP(9); + case 108 ... 112: + return 10; + case 113 ... 115: + return TSSI_EXTRA_GROUP(10); + case 116 ... 120: + return 11; + case 121 ... 123: + return TSSI_EXTRA_GROUP(11); + case 124 ... 128: + return 12; + case 129 ... 131: + return TSSI_EXTRA_GROUP(12); + case 132 ... 136: + return 13; + case 137 ... 139: + return TSSI_EXTRA_GROUP(13); + case 140 ... 144: + return 14; + case 149 ... 153: + return 15; + case 154 ... 156: + return TSSI_EXTRA_GROUP(15); + case 157 ... 161: + return 16; + case 162 ... 164: + return TSSI_EXTRA_GROUP(16); + case 165 ... 169: + return 17; + case 170 ... 172: + return TSSI_EXTRA_GROUP(17); + case 173 ... 177: + return 18; + } + + return 0; +} + +static u32 _tssi_get_trim_group(struct rtw89_dev *rtwdev, u8 ch) +{ + switch (ch) { + case 1 ... 8: + return 0; + case 9 ... 14: + return 1; + case 36 ... 48: + return 2; + case 52 ... 64: + return 3; + case 100 ... 112: + return 4; + case 116 ... 128: + return 5; + case 132 ... 144: + return 6; + case 149 ... 177: + return 7; + } + + return 0; +} + +static s8 _tssi_get_ofdm_de(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, + enum rtw89_rf_path path) +{ + struct rtw89_tssi_info *tssi_info = &rtwdev->tssi; + const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0); + u32 gidx, gidx_1st, gidx_2nd; + u8 ch = chan->channel; + s8 de_1st; + s8 de_2nd; + s8 val; + + gidx = _tssi_get_ofdm_group(rtwdev, ch); + + rtw89_debug(rtwdev, RTW89_DBG_TSSI, + "[TSSI][TRIM]: path=%d mcs group_idx=0x%x\n", path, gidx); + + if (IS_TSSI_EXTRA_GROUP(gidx)) { + gidx_1st = TSSI_EXTRA_GET_GROUP_IDX1(gidx); + gidx_2nd = TSSI_EXTRA_GET_GROUP_IDX2(gidx); + de_1st = tssi_info->tssi_mcs[path][gidx_1st]; + de_2nd = tssi_info->tssi_mcs[path][gidx_2nd]; + val = (de_1st + de_2nd) / 2; + + rtw89_debug(rtwdev, RTW89_DBG_TSSI, + "[TSSI][TRIM]: path=%d mcs de=%d 1st=%d 2nd=%d\n", + path, val, de_1st, de_2nd); + } else { + val = tssi_info->tssi_mcs[path][gidx]; + + rtw89_debug(rtwdev, RTW89_DBG_TSSI, + "[TSSI][TRIM]: path=%d mcs de=%d\n", path, val); + } + + return val; +} + +static s8 _tssi_get_ofdm_trim_de(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, + enum rtw89_rf_path path) +{ + struct rtw89_tssi_info *tssi_info = &rtwdev->tssi; + const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0); + u32 tgidx, tgidx_1st, tgidx_2nd; + u8 ch = chan->channel; + s8 tde_1st; + s8 tde_2nd; + s8 val; + + tgidx = _tssi_get_trim_group(rtwdev, ch); + + rtw89_debug(rtwdev, RTW89_DBG_TSSI, + "[TSSI][TRIM]: path=%d mcs trim_group_idx=0x%x\n", + path, tgidx); + + if (IS_TSSI_EXTRA_GROUP(tgidx)) { + tgidx_1st = TSSI_EXTRA_GET_GROUP_IDX1(tgidx); + tgidx_2nd = TSSI_EXTRA_GET_GROUP_IDX2(tgidx); + tde_1st = tssi_info->tssi_trim[path][tgidx_1st]; + tde_2nd = tssi_info->tssi_trim[path][tgidx_2nd]; + val = (tde_1st + tde_2nd) / 2; + + rtw89_debug(rtwdev, RTW89_DBG_TSSI, + "[TSSI][TRIM]: path=%d mcs trim_de=%d 1st=%d 2nd=%d\n", + path, val, tde_1st, tde_2nd); + } else { + val = tssi_info->tssi_trim[path][tgidx]; + + rtw89_debug(rtwdev, RTW89_DBG_TSSI, + "[TSSI][TRIM]: path=%d mcs trim_de=%d\n", + path, val); + } + + return val; +} + +static void _tssi_set_efuse_to_de(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy) +{ + struct rtw89_tssi_info *tssi_info = &rtwdev->tssi; + const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0); + u8 ch = chan->channel; + u8 gidx; + s8 ofdm_de; + s8 trim_de; + s32 val; + u32 i; + + rtw89_debug(rtwdev, RTW89_DBG_TSSI, "[TSSI][TRIM]: phy=%d ch=%d\n", + phy, ch); + + for (i = RF_PATH_A; i < RTW8851B_TSSI_PATH_NR; i++) { + gidx = _tssi_get_cck_group(rtwdev, ch); + trim_de = _tssi_get_ofdm_trim_de(rtwdev, phy, i); + val = tssi_info->tssi_cck[i][gidx] + trim_de; + + rtw89_debug(rtwdev, RTW89_DBG_TSSI, + "[TSSI][TRIM]: path=%d cck[%d]=0x%x trim=0x%x\n", + i, gidx, tssi_info->tssi_cck[i][gidx], trim_de); + + rtw89_phy_write32_mask(rtwdev, _tssi_de_cck_long[i], _TSSI_DE_MASK, val); + rtw89_phy_write32_mask(rtwdev, _tssi_de_cck_short[i], _TSSI_DE_MASK, val); + + rtw89_debug(rtwdev, RTW89_DBG_TSSI, + "[TSSI] Set TSSI CCK DE 0x%x[21:12]=0x%x\n", + _tssi_de_cck_long[i], + rtw89_phy_read32_mask(rtwdev, _tssi_de_cck_long[i], + _TSSI_DE_MASK)); + + ofdm_de = _tssi_get_ofdm_de(rtwdev, phy, i); + trim_de = _tssi_get_ofdm_trim_de(rtwdev, phy, i); + val = ofdm_de + trim_de; + + rtw89_debug(rtwdev, RTW89_DBG_TSSI, + "[TSSI][TRIM]: path=%d mcs=0x%x trim=0x%x\n", + i, ofdm_de, trim_de); + + rtw89_phy_write32_mask(rtwdev, _tssi_de_mcs_20m[i], _TSSI_DE_MASK, val); + rtw89_phy_write32_mask(rtwdev, _tssi_de_mcs_40m[i], _TSSI_DE_MASK, val); + rtw89_phy_write32_mask(rtwdev, _tssi_de_mcs_80m[i], _TSSI_DE_MASK, val); + rtw89_phy_write32_mask(rtwdev, _tssi_de_mcs_80m_80m[i], _TSSI_DE_MASK, val); + rtw89_phy_write32_mask(rtwdev, _tssi_de_mcs_5m[i], _TSSI_DE_MASK, val); + rtw89_phy_write32_mask(rtwdev, _tssi_de_mcs_10m[i], _TSSI_DE_MASK, val); + + rtw89_debug(rtwdev, RTW89_DBG_TSSI, + "[TSSI] Set TSSI MCS DE 0x%x[21:12]=0x%x\n", + _tssi_de_mcs_20m[i], + rtw89_phy_read32_mask(rtwdev, _tssi_de_mcs_20m[i], + _TSSI_DE_MASK)); + } +} + +static void _tssi_alimentk_dump_result(struct rtw89_dev *rtwdev, enum rtw89_rf_path path) +{ + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[TSSI PA K]\n0x%x = 0x%08x\n0x%x = 0x%08x\n0x%x = 0x%08x\n0x%x = 0x%08x\n" + "0x%x = 0x%08x\n0x%x = 0x%08x\n0x%x = 0x%08x\n0x%x = 0x%08x\n", + R_TSSI_PA_K1 + (path << 13), + rtw89_phy_read32_mask(rtwdev, R_TSSI_PA_K1 + (path << 13), MASKDWORD), + R_TSSI_PA_K2 + (path << 13), + rtw89_phy_read32_mask(rtwdev, R_TSSI_PA_K2 + (path << 13), MASKDWORD), + R_P0_TSSI_ALIM1 + (path << 13), + rtw89_phy_read32_mask(rtwdev, R_P0_TSSI_ALIM1 + (path << 13), MASKDWORD), + R_P0_TSSI_ALIM3 + (path << 13), + rtw89_phy_read32_mask(rtwdev, R_P0_TSSI_ALIM3 + (path << 13), MASKDWORD), + R_TSSI_PA_K5 + (path << 13), + rtw89_phy_read32_mask(rtwdev, R_TSSI_PA_K5 + (path << 13), MASKDWORD), + R_P0_TSSI_ALIM2 + (path << 13), + rtw89_phy_read32_mask(rtwdev, R_P0_TSSI_ALIM2 + (path << 13), MASKDWORD), + R_P0_TSSI_ALIM4 + (path << 13), + rtw89_phy_read32_mask(rtwdev, R_P0_TSSI_ALIM4 + (path << 13), MASKDWORD), + R_TSSI_PA_K8 + (path << 13), + rtw89_phy_read32_mask(rtwdev, R_TSSI_PA_K8 + (path << 13), MASKDWORD)); +} + +static void _tssi_alimentk_done(struct rtw89_dev *rtwdev, + enum rtw89_phy_idx phy, enum rtw89_rf_path path) +{ + struct rtw89_tssi_info *tssi_info = &rtwdev->tssi; + const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0); + u8 channel = chan->channel; + u8 band; + + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "======>%s phy=%d path=%d\n", __func__, phy, path); + + if (channel >= 1 && channel <= 14) + band = TSSI_ALIMK_2G; + else if (channel >= 36 && channel <= 64) + band = TSSI_ALIMK_5GL; + else if (channel >= 100 && channel <= 144) + band = TSSI_ALIMK_5GM; + else if (channel >= 149 && channel <= 177) + band = TSSI_ALIMK_5GH; + else + band = TSSI_ALIMK_2G; + + if (tssi_info->alignment_done[path][band]) { + rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_ALIM1 + (path << 13), MASKDWORD, + tssi_info->alignment_value[path][band][0]); + rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_ALIM3 + (path << 13), MASKDWORD, + tssi_info->alignment_value[path][band][1]); + rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_ALIM2 + (path << 13), MASKDWORD, + tssi_info->alignment_value[path][band][2]); + rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_ALIM4 + (path << 13), MASKDWORD, + tssi_info->alignment_value[path][band][3]); + } + + _tssi_alimentk_dump_result(rtwdev, path); +} + +static void rtw8851b_by_rate_dpd(struct rtw89_dev *rtwdev) +{ + rtw89_write32_mask(rtwdev, R_AX_PWR_SWING_OTHER_CTRL0, + B_AX_CFIR_BY_RATE_OFF_MASK, 0x21861); +} + +void rtw8851b_dpk_init(struct rtw89_dev *rtwdev) +{ + rtw8851b_by_rate_dpd(rtwdev); +} + +void rtw8851b_aack(struct rtw89_dev *rtwdev) +{ + u32 tmp05, tmpd3, ib[4]; + u32 tmp; + int ret; + int rek; + int i; + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[LCK]DO AACK\n"); + + tmp05 = rtw89_read_rf(rtwdev, RF_PATH_A, RR_RSV1, RFREG_MASK); + tmpd3 = rtw89_read_rf(rtwdev, RF_PATH_A, RR_LCK_TRG, RFREG_MASK); + rtw89_write_rf(rtwdev, RF_PATH_A, RR_MOD, RR_MOD_MASK, 0x3); + rtw89_write_rf(rtwdev, RF_PATH_A, RR_RSV1, RFREG_MASK, 0x0); + rtw89_write_rf(rtwdev, RF_PATH_A, RR_LCK_TRG, RR_LCK_ST, 0x0); + + for (rek = 0; rek < 4; rek++) { + rtw89_write_rf(rtwdev, RF_PATH_A, RR_AACK, RFREG_MASK, 0x8201e); + rtw89_write_rf(rtwdev, RF_PATH_A, RR_AACK, RFREG_MASK, 0x8201f); + fsleep(100); + + ret = read_poll_timeout_atomic(rtw89_read_rf, tmp, tmp, + 1, 1000, false, + rtwdev, RF_PATH_A, 0xd0, BIT(16)); + if (ret) + rtw89_warn(rtwdev, "[LCK]AACK timeout\n"); + + rtw89_write_rf(rtwdev, RF_PATH_A, RR_VCI, RR_VCI_ON, 0x1); + for (i = 0; i < 4; i++) { + rtw89_write_rf(rtwdev, RF_PATH_A, RR_VCO, RR_VCO_SEL, i); + ib[i] = rtw89_read_rf(rtwdev, RF_PATH_A, RR_IBD, RR_IBD_VAL); + } + rtw89_write_rf(rtwdev, RF_PATH_A, RR_VCI, RR_VCI_ON, 0x0); + + if (ib[0] != 0 && ib[1] != 0 && ib[2] != 0 && ib[3] != 0) + break; + } + + if (rek != 0) + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[LCK]AACK rek = %d\n", rek); + + rtw89_write_rf(rtwdev, RF_PATH_A, RR_RSV1, RFREG_MASK, tmp05); + rtw89_write_rf(rtwdev, RF_PATH_A, RR_LCK_TRG, RFREG_MASK, tmpd3); +} + +static void _lck_keep_thermal(struct rtw89_dev *rtwdev) +{ + struct rtw89_lck_info *lck = &rtwdev->lck; + + lck->thermal[RF_PATH_A] = + ewma_thermal_read(&rtwdev->phystat.avg_thermal[RF_PATH_A]); + rtw89_debug(rtwdev, RTW89_DBG_RFK_TRACK, + "[LCK] path=%d thermal=0x%x", RF_PATH_A, lck->thermal[RF_PATH_A]); +} + +static void rtw8851b_lck(struct rtw89_dev *rtwdev) +{ + u32 tmp05, tmp18, tmpd3; + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[LCK]DO LCK\n"); + + tmp05 = rtw89_read_rf(rtwdev, RF_PATH_A, RR_RSV1, RFREG_MASK); + tmp18 = rtw89_read_rf(rtwdev, RF_PATH_A, RR_CFGCH, RFREG_MASK); + tmpd3 = rtw89_read_rf(rtwdev, RF_PATH_A, RR_LCK_TRG, RFREG_MASK); + + rtw89_write_rf(rtwdev, RF_PATH_A, RR_MOD, RR_MOD_MASK, 0x3); + rtw89_write_rf(rtwdev, RF_PATH_A, RR_RSV1, RFREG_MASK, 0x0); + rtw89_write_rf(rtwdev, RF_PATH_A, RR_LCK_TRG, RR_LCK_TRGSEL, 0x1); + + _set_ch(rtwdev, tmp18); + rtw89_write_rf(rtwdev, RF_PATH_A, RR_LCK_TRG, RFREG_MASK, tmpd3); + rtw89_write_rf(rtwdev, RF_PATH_A, RR_RSV1, RFREG_MASK, tmp05); + + _lck_keep_thermal(rtwdev); +} + +#define RTW8851B_LCK_TH 8 + +void rtw8851b_lck_track(struct rtw89_dev *rtwdev) +{ + struct rtw89_lck_info *lck = &rtwdev->lck; + u8 cur_thermal; + int delta; + + cur_thermal = + ewma_thermal_read(&rtwdev->phystat.avg_thermal[RF_PATH_A]); + delta = abs((int)cur_thermal - lck->thermal[RF_PATH_A]); + + rtw89_debug(rtwdev, RTW89_DBG_RFK_TRACK, + "[LCK] path=%d current thermal=0x%x delta=0x%x\n", + RF_PATH_A, cur_thermal, delta); + + if (delta >= RTW8851B_LCK_TH) { + rtw8851b_aack(rtwdev); + rtw8851b_lck(rtwdev); + } +} + +void rtw8851b_lck_init(struct rtw89_dev *rtwdev) +{ + _lck_keep_thermal(rtwdev); +} + +void rtw8851b_rck(struct rtw89_dev *rtwdev) +{ + _rck(rtwdev, RF_PATH_A); +} + +void rtw8851b_dack(struct rtw89_dev *rtwdev) +{ + _dac_cal(rtwdev, false); +} + +void rtw8851b_iqk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx) +{ + u8 phy_map = rtw89_btc_phymap(rtwdev, phy_idx, 0); + u32 tx_en; + + rtw89_btc_ntfy_wl_rfk(rtwdev, phy_map, BTC_WRFKT_IQK, BTC_WRFK_START); + rtw89_chip_stop_sch_tx(rtwdev, phy_idx, &tx_en, RTW89_SCH_TX_SEL_ALL); + _wait_rx_mode(rtwdev, _kpath(rtwdev, phy_idx)); + + _iqk_init(rtwdev); + _iqk(rtwdev, phy_idx, false); + + rtw89_chip_resume_sch_tx(rtwdev, phy_idx, tx_en); + rtw89_btc_ntfy_wl_rfk(rtwdev, phy_map, BTC_WRFKT_IQK, BTC_WRFK_STOP); +} + +void rtw8851b_rx_dck(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx) +{ + u8 phy_map = rtw89_btc_phymap(rtwdev, phy_idx, 0); + u32 tx_en; + + rtw89_btc_ntfy_wl_rfk(rtwdev, phy_map, BTC_WRFKT_RXDCK, BTC_WRFK_START); + rtw89_chip_stop_sch_tx(rtwdev, phy_idx, &tx_en, RTW89_SCH_TX_SEL_ALL); + _wait_rx_mode(rtwdev, _kpath(rtwdev, phy_idx)); + + _rx_dck(rtwdev, phy_idx, false); + + rtw89_chip_resume_sch_tx(rtwdev, phy_idx, tx_en); + rtw89_btc_ntfy_wl_rfk(rtwdev, phy_map, BTC_WRFKT_RXDCK, BTC_WRFK_STOP); +} + +void rtw8851b_dpk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx) +{ + u8 phy_map = rtw89_btc_phymap(rtwdev, phy_idx, 0); + u32 tx_en; + + rtw89_btc_ntfy_wl_rfk(rtwdev, phy_map, BTC_WRFKT_DPK, BTC_WRFK_START); + rtw89_chip_stop_sch_tx(rtwdev, phy_idx, &tx_en, RTW89_SCH_TX_SEL_ALL); + _wait_rx_mode(rtwdev, _kpath(rtwdev, phy_idx)); + + rtwdev->dpk.is_dpk_enable = true; + rtwdev->dpk.is_dpk_reload_en = false; + _dpk(rtwdev, phy_idx, false); + + rtw89_chip_resume_sch_tx(rtwdev, phy_idx, tx_en); + rtw89_btc_ntfy_wl_rfk(rtwdev, phy_map, BTC_WRFKT_DPK, BTC_WRFK_STOP); +} + +void rtw8851b_dpk_track(struct rtw89_dev *rtwdev) +{ + _dpk_track(rtwdev); +} + +void rtw8851b_tssi(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, bool hwtx_en) +{ + u8 phy_map = rtw89_btc_phymap(rtwdev, phy, RF_A); + u8 i; + + rtw89_debug(rtwdev, RTW89_DBG_TSSI, "[TSSI] %s: phy=%d\n", __func__, phy); + rtw89_btc_ntfy_wl_rfk(rtwdev, phy_map, BTC_WRFKT_IQK, BTC_WRFK_ONESHOT_START); + + _tssi_disable(rtwdev, phy); + + for (i = RF_PATH_A; i < RF_PATH_NUM_8851B; i++) { + _tssi_set_sys(rtwdev, phy, i); + _tssi_ini_txpwr_ctrl_bb(rtwdev, phy, i); + _tssi_ini_txpwr_ctrl_bb_he_tb(rtwdev, phy, i); + _tssi_set_dck(rtwdev, phy, i); + _tssi_set_tmeter_tbl(rtwdev, phy, i); + _tssi_set_dac_gain_tbl(rtwdev, phy, i); + _tssi_slope_cal_org(rtwdev, phy, i); + _tssi_alignment_default(rtwdev, phy, i, true); + _tssi_set_tssi_slope(rtwdev, phy, i); + } + + _tssi_enable(rtwdev, phy); + _tssi_set_efuse_to_de(rtwdev, phy); + + rtw89_btc_ntfy_wl_rfk(rtwdev, phy_map, BTC_WRFKT_IQK, BTC_WRFK_ONESHOT_STOP); +} + +void rtw8851b_tssi_scan(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy) +{ + const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0); + u8 channel = chan->channel; + u32 i; + + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "======>%s phy=%d channel=%d\n", __func__, phy, channel); + + _tssi_disable(rtwdev, phy); + + for (i = RF_PATH_A; i < RF_PATH_NUM_8851B; i++) { + _tssi_set_sys(rtwdev, phy, i); + _tssi_set_tmeter_tbl(rtwdev, phy, i); + _tssi_slope_cal_org(rtwdev, phy, i); + _tssi_alignment_default(rtwdev, phy, i, true); + } + + _tssi_enable(rtwdev, phy); + _tssi_set_efuse_to_de(rtwdev, phy); +} + +static void rtw8851b_tssi_default_txagc(struct rtw89_dev *rtwdev, + enum rtw89_phy_idx phy, bool enable) +{ + const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0); + u8 channel = chan->channel; + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "======> %s ch=%d\n", + __func__, channel); + + if (enable) + return; + + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "======>%s 1 SCAN_END Set 0x5818[7:0]=0x%x\n", + __func__, + rtw89_phy_read32_mask(rtwdev, R_P0_TSSI_TRK, B_P0_TSSI_OFT)); + + rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_TRK, B_P0_TSSI_OFT, 0xc0); + rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_TRK, B_P0_TSSI_OFT_EN, 0x0); + rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_TRK, B_P0_TSSI_OFT_EN, 0x1); + + _tssi_alimentk_done(rtwdev, phy, RF_PATH_A); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "======>%s 2 SCAN_END Set 0x5818[7:0]=0x%x\n", + __func__, + rtw89_phy_read32_mask(rtwdev, R_P0_TSSI_TRK, B_P0_TSSI_OFT)); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "======> %s SCAN_END\n", __func__); +} + +void rtw8851b_wifi_scan_notify(struct rtw89_dev *rtwdev, bool scan_start, + enum rtw89_phy_idx phy_idx) +{ + if (scan_start) + rtw8851b_tssi_default_txagc(rtwdev, phy_idx, true); + else + rtw8851b_tssi_default_txagc(rtwdev, phy_idx, false); +} + +static void _bw_setting(struct rtw89_dev *rtwdev, enum rtw89_rf_path path, + enum rtw89_bandwidth bw, bool dav) +{ + u32 reg18_addr = dav ? RR_CFGCH : RR_CFGCH_V1; + u32 rf_reg18; + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[RFK]===> %s\n", __func__); + + rf_reg18 = rtw89_read_rf(rtwdev, path, reg18_addr, RFREG_MASK); + if (rf_reg18 == INV_RF_DATA) { + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[RFK]Invalid RF_0x18 for Path-%d\n", path); + return; + } + rf_reg18 &= ~RR_CFGCH_BW; + + switch (bw) { + case RTW89_CHANNEL_WIDTH_5: + case RTW89_CHANNEL_WIDTH_10: + case RTW89_CHANNEL_WIDTH_20: + rf_reg18 |= FIELD_PREP(RR_CFGCH_BW, CFGCH_BW_20M); + break; + case RTW89_CHANNEL_WIDTH_40: + rf_reg18 |= FIELD_PREP(RR_CFGCH_BW, CFGCH_BW_40M); + break; + case RTW89_CHANNEL_WIDTH_80: + rf_reg18 |= FIELD_PREP(RR_CFGCH_BW, CFGCH_BW_80M); + break; + default: + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[RFK]Fail to set CH\n"); + } + + rf_reg18 &= ~(RR_CFGCH_POW_LCK | RR_CFGCH_TRX_AH | RR_CFGCH_BCN | + RR_CFGCH_BW2) & RFREG_MASK; + rf_reg18 |= RR_CFGCH_BW2; + rtw89_write_rf(rtwdev, path, reg18_addr, RFREG_MASK, rf_reg18); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[RFK] set %x at path%d, %x =0x%x\n", + bw, path, reg18_addr, + rtw89_read_rf(rtwdev, path, reg18_addr, RFREG_MASK)); +} + +static void _ctrl_bw(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, + enum rtw89_bandwidth bw) +{ + _bw_setting(rtwdev, RF_PATH_A, bw, true); + _bw_setting(rtwdev, RF_PATH_A, bw, false); +} + +static bool _set_s0_arfc18(struct rtw89_dev *rtwdev, u32 val) +{ + u32 bak; + u32 tmp; + int ret; + + bak = rtw89_read_rf(rtwdev, RF_PATH_A, RR_LDO, RFREG_MASK); + rtw89_write_rf(rtwdev, RF_PATH_A, RR_LDO, RR_LDO_SEL, 0x1); + rtw89_write_rf(rtwdev, RF_PATH_A, RR_CFGCH, RFREG_MASK, val); + + ret = read_poll_timeout_atomic(rtw89_read_rf, tmp, tmp == 0, 1, 1000, + false, rtwdev, RF_PATH_A, RR_LPF, RR_LPF_BUSY); + if (ret) + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[LCK]LCK timeout\n"); + + rtw89_write_rf(rtwdev, RF_PATH_A, RR_LDO, RFREG_MASK, bak); + + return !!ret; +} + +static void _lck_check(struct rtw89_dev *rtwdev) +{ + u32 tmp; + + if (rtw89_read_rf(rtwdev, RF_PATH_A, RR_SYNFB, RR_SYNFB_LK) == 0) { + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[LCK]SYN MMD reset\n"); + + rtw89_write_rf(rtwdev, RF_PATH_A, RR_MMD, RR_MMD_RST_EN, 0x1); + rtw89_write_rf(rtwdev, RF_PATH_A, RR_MMD, RR_MMD_RST_SYN, 0x0); + rtw89_write_rf(rtwdev, RF_PATH_A, RR_MMD, RR_MMD_RST_SYN, 0x1); + rtw89_write_rf(rtwdev, RF_PATH_A, RR_MMD, RR_MMD_RST_EN, 0x0); + } + + udelay(10); + + if (rtw89_read_rf(rtwdev, RF_PATH_A, RR_SYNFB, RR_SYNFB_LK) == 0) { + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[LCK]re-set RF 0x18\n"); + + rtw89_write_rf(rtwdev, RF_PATH_A, RR_LCK_TRG, RR_LCK_TRGSEL, 0x1); + tmp = rtw89_read_rf(rtwdev, RF_PATH_A, RR_CFGCH, RFREG_MASK); + _set_s0_arfc18(rtwdev, tmp); + rtw89_write_rf(rtwdev, RF_PATH_A, RR_LCK_TRG, RR_LCK_TRGSEL, 0x0); + } + + if (rtw89_read_rf(rtwdev, RF_PATH_A, RR_SYNFB, RR_SYNFB_LK) == 0) { + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[LCK]SYN off/on\n"); + + tmp = rtw89_read_rf(rtwdev, RF_PATH_A, RR_POW, RFREG_MASK); + rtw89_write_rf(rtwdev, RF_PATH_A, RR_POW, RFREG_MASK, tmp); + tmp = rtw89_read_rf(rtwdev, RF_PATH_A, RR_SX, RFREG_MASK); + rtw89_write_rf(rtwdev, RF_PATH_A, RR_SX, RFREG_MASK, tmp); + + rtw89_write_rf(rtwdev, RF_PATH_A, RR_SYNLUT, RR_SYNLUT_MOD, 0x1); + rtw89_write_rf(rtwdev, RF_PATH_A, RR_POW, RR_POW_SYN, 0x0); + rtw89_write_rf(rtwdev, RF_PATH_A, RR_POW, RR_POW_SYN, 0x3); + rtw89_write_rf(rtwdev, RF_PATH_A, RR_SYNLUT, RR_SYNLUT_MOD, 0x0); + + rtw89_write_rf(rtwdev, RF_PATH_A, RR_LCK_TRG, RR_LCK_TRGSEL, 0x1); + tmp = rtw89_read_rf(rtwdev, RF_PATH_A, RR_CFGCH, RFREG_MASK); + _set_s0_arfc18(rtwdev, tmp); + rtw89_write_rf(rtwdev, RF_PATH_A, RR_LCK_TRG, RR_LCK_TRGSEL, 0x0); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[LCK]0xb2=%x, 0xc5=%x\n", + rtw89_read_rf(rtwdev, RF_PATH_A, RR_VCO, RFREG_MASK), + rtw89_read_rf(rtwdev, RF_PATH_A, RR_SYNFB, RFREG_MASK)); + } +} + +static void _set_ch(struct rtw89_dev *rtwdev, u32 val) +{ + bool timeout; + + timeout = _set_s0_arfc18(rtwdev, val); + if (!timeout) + _lck_check(rtwdev); +} + +static void _ch_setting(struct rtw89_dev *rtwdev, enum rtw89_rf_path path, + u8 central_ch, bool dav) +{ + u32 reg18_addr = dav ? RR_CFGCH : RR_CFGCH_V1; + bool is_2g_ch = central_ch <= 14; + u32 rf_reg18; + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[RFK]===> %s\n", __func__); + + rf_reg18 = rtw89_read_rf(rtwdev, path, reg18_addr, RFREG_MASK); + rf_reg18 &= ~(RR_CFGCH_BAND1 | RR_CFGCH_POW_LCK | RR_CFGCH_TRX_AH | + RR_CFGCH_BCN | RR_CFGCH_BAND0 | RR_CFGCH_CH); + rf_reg18 |= FIELD_PREP(RR_CFGCH_CH, central_ch); + + if (!is_2g_ch) + rf_reg18 |= FIELD_PREP(RR_CFGCH_BAND1, CFGCH_BAND1_5G) | + FIELD_PREP(RR_CFGCH_BAND0, CFGCH_BAND0_5G); + + rf_reg18 &= ~(RR_CFGCH_POW_LCK | RR_CFGCH_TRX_AH | RR_CFGCH_BCN | + RR_CFGCH_BW2) & RFREG_MASK; + rf_reg18 |= RR_CFGCH_BW2; + + if (path == RF_PATH_A && dav) + _set_ch(rtwdev, rf_reg18); + else + rtw89_write_rf(rtwdev, path, reg18_addr, RFREG_MASK, rf_reg18); + + rtw89_write_rf(rtwdev, path, RR_LCKST, RR_LCKST_BIN, 0); + rtw89_write_rf(rtwdev, path, RR_LCKST, RR_LCKST_BIN, 1); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[RFK]CH: %d for Path-%d, reg0x%x = 0x%x\n", + central_ch, path, reg18_addr, + rtw89_read_rf(rtwdev, path, reg18_addr, RFREG_MASK)); +} + +static void _ctrl_ch(struct rtw89_dev *rtwdev, u8 central_ch) +{ + _ch_setting(rtwdev, RF_PATH_A, central_ch, true); + _ch_setting(rtwdev, RF_PATH_A, central_ch, false); +} + +static void _set_rxbb_bw(struct rtw89_dev *rtwdev, enum rtw89_bandwidth bw, + enum rtw89_rf_path path) +{ + rtw89_write_rf(rtwdev, path, RR_LUTWE2, RR_LUTWE2_RTXBW, 0x1); + rtw89_write_rf(rtwdev, path, RR_LUTWA, RR_LUTWA_M2, 0x12); + + if (bw == RTW89_CHANNEL_WIDTH_20) + rtw89_write_rf(rtwdev, path, RR_LUTWD0, RR_LUTWD0_LB, 0x1b); + else if (bw == RTW89_CHANNEL_WIDTH_40) + rtw89_write_rf(rtwdev, path, RR_LUTWD0, RR_LUTWD0_LB, 0x13); + else if (bw == RTW89_CHANNEL_WIDTH_80) + rtw89_write_rf(rtwdev, path, RR_LUTWD0, RR_LUTWD0_LB, 0xb); + else + rtw89_write_rf(rtwdev, path, RR_LUTWD0, RR_LUTWD0_LB, 0x3); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[RFK] set S%d RXBB BW 0x3F = 0x%x\n", path, + rtw89_read_rf(rtwdev, path, RR_LUTWD0, RR_LUTWD0_LB)); + + rtw89_write_rf(rtwdev, path, RR_LUTWE2, RR_LUTWE2_RTXBW, 0x0); +} + +static void _rxbb_bw(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, + enum rtw89_bandwidth bw) +{ + u8 kpath, path; + + kpath = _kpath(rtwdev, phy); + + for (path = 0; path < RF_PATH_NUM_8851B; path++) { + if (!(kpath & BIT(path))) + continue; + + _set_rxbb_bw(rtwdev, bw, path); + } +} + +static void rtw8851b_ctrl_bw_ch(struct rtw89_dev *rtwdev, + enum rtw89_phy_idx phy, u8 central_ch, + enum rtw89_band band, enum rtw89_bandwidth bw) +{ + _ctrl_ch(rtwdev, central_ch); + _ctrl_bw(rtwdev, phy, bw); + _rxbb_bw(rtwdev, phy, bw); +} + +void rtw8851b_set_channel_rf(struct rtw89_dev *rtwdev, + const struct rtw89_chan *chan, + enum rtw89_phy_idx phy_idx) +{ + rtw8851b_ctrl_bw_ch(rtwdev, phy_idx, chan->channel, chan->band_type, + chan->band_width); +} diff --git a/drivers/net/wireless/realtek/rtw89/rtw8851b_rfk.h b/drivers/net/wireless/realtek/rtw89/rtw8851b_rfk.h new file mode 100644 index 0000000000000000000000000000000000000000..b66a23d6d36732630579f7f0ca7df3e1bff6c3fc --- /dev/null +++ b/drivers/net/wireless/realtek/rtw89/rtw8851b_rfk.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ +/* Copyright(c) 2022-2023 Realtek Corporation + */ + +#ifndef __RTW89_8851B_RFK_H__ +#define __RTW89_8851B_RFK_H__ + +#include "core.h" + +void rtw8851b_aack(struct rtw89_dev *rtwdev); +void rtw8851b_lck_init(struct rtw89_dev *rtwdev); +void rtw8851b_lck_track(struct rtw89_dev *rtwdev); +void rtw8851b_rck(struct rtw89_dev *rtwdev); +void rtw8851b_dack(struct rtw89_dev *rtwdev); +void rtw8851b_iqk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx); +void rtw8851b_rx_dck(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx); +void rtw8851b_dpk_init(struct rtw89_dev *rtwdev); +void rtw8851b_dpk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy); +void rtw8851b_dpk_track(struct rtw89_dev *rtwdev); +void rtw8851b_tssi(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, bool hwtx_en); +void rtw8851b_tssi_scan(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy); +void rtw8851b_wifi_scan_notify(struct rtw89_dev *rtwdev, bool scan_start, + enum rtw89_phy_idx phy_idx); +void rtw8851b_set_channel_rf(struct rtw89_dev *rtwdev, + const struct rtw89_chan *chan, + enum rtw89_phy_idx phy_idx); + +#endif diff --git a/drivers/net/wireless/realtek/rtw89/rtw8851b_table.c b/drivers/net/wireless/realtek/rtw89/rtw8851b_table.c index bb724140df4f7708c4e7b4147cc4584542b76f0d..c447f91a4bd006cd93f44ec26a97e21119934f2c 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8851b_table.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8851b_table.c @@ -1273,6 +1273,25 @@ static const struct rtw89_reg2_def rtw89_8851b_phy_radioa_regs[] = { {0xF0010000, 0x00000000}, {0xF0020000, 0x00000001}, {0xF0030000, 0x00000002}, + {0xF0010001, 0x00000003}, + {0xF0020001, 0x00000004}, + {0xF0030001, 0x00000005}, + {0xF0040001, 0x00000006}, + {0xF0050001, 0x00000007}, + {0xF0060001, 0x00000008}, + {0x000, 0x00000000}, + {0x0EF, 0x00080000}, + {0x033, 0x00000003}, + {0x03E, 0x00000150}, + {0x03F, 0x0000D79C}, + {0x0EF, 0x00000000}, + {0x052, 0x000C3338}, + {0x053, 0x000608AF}, + {0x054, 0x00006C04}, + {0x063, 0x000FC082}, + {0x065, 0x00018122}, + {0x000, 0x00010000}, + {0x0FE, 0x0000005A}, {0x000, 0x00030000}, {0x018, 0x00013124}, {0x0EF, 0x00080000}, @@ -1834,8 +1853,6 @@ static const struct rtw89_reg2_def rtw89_8851b_phy_radioa_regs[] = { {0x059, 0x00050033}, {0x061, 0x0005F48A}, {0x062, 0x00077435}, - {0x063, 0x000F80A2}, - {0x065, 0x00018F22}, {0x067, 0x00008060}, {0x07E, 0x0009780B}, {0x0EE, 0x00000004}, @@ -2074,9 +2091,6 @@ static const struct rtw89_reg2_def rtw89_8851b_phy_radioa_regs[] = { {0x03F, 0x0001C3C3}, {0x0EF, 0x00000000}, {0x051, 0x0003D368}, - {0x052, 0x000A3338}, - {0x053, 0x000688AF}, - {0x054, 0x00012C04}, {0x058, 0x00084221}, {0x05B, 0x000EB000}, {0x100EE, 0x00002000}, @@ -2229,9 +2243,11 @@ static const struct rtw89_reg2_def rtw89_8851b_phy_radioa_regs[] = { {0x033, 0x00000000}, {0x03F, 0x00000004}, {0x0EF, 0x00000000}, + {0x000, 0x00010000}, + {0x0FE, 0x0000005A}, {0x005, 0x00000001}, {0x10005, 0x00000001}, - {0x0FE, 0x00000022}, + {0x0FE, 0x00000028}, }; static const struct rtw89_reg2_def rtw89_8851b_phy_nctl_regs[] = { @@ -2306,7 +2322,7 @@ static const struct rtw89_reg2_def rtw89_8851b_phy_nctl_regs[] = { {0x8144, 0x0b040b03}, {0x8148, 0x07020b04}, {0x814c, 0x07020b04}, - {0x8150, 0xe4e40000}, + {0x8150, 0xa0a00000}, {0x8158, 0xffffffff}, {0x815c, 0xffffffff}, {0x8160, 0xffffffff}, @@ -3305,7 +3321,7 @@ static const s8 _txpwr_track_delta_swingidx_2g_cck_a_p[] = { 0, 1, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4 }; -const u8 rtw89_8851b_tx_shape[RTW89_BAND_MAX][RTW89_RS_TX_SHAPE_NUM] +const u8 rtw89_8851b_tx_shape[RTW89_BAND_NUM][RTW89_RS_TX_SHAPE_NUM] [RTW89_REGD_NUM] = { [0][0][RTW89_ACMA] = 0, [0][0][RTW89_CN] = 0, @@ -3326,8 +3342,8 @@ const u8 rtw89_8851b_tx_shape[RTW89_BAND_MAX][RTW89_RS_TX_SHAPE_NUM] [1][1][RTW89_ACMA] = 0, [1][1][RTW89_CN] = 0, [1][1][RTW89_ETSI] = 0, - [1][1][RTW89_FCC] = 3, - [1][1][RTW89_IC] = 3, + [1][1][RTW89_FCC] = 1, + [1][1][RTW89_IC] = 1, [1][1][RTW89_KCC] = 0, [1][1][RTW89_MKK] = 0, [1][1][RTW89_UK] = 0, @@ -4880,9 +4896,9 @@ const s8 rtw89_8851b_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_WW][42] = 30, [0][0][1][0][RTW89_WW][44] = 30, [0][0][1][0][RTW89_WW][46] = 30, - [0][0][1][0][RTW89_WW][48] = 72, - [0][0][1][0][RTW89_WW][50] = 72, - [0][0][1][0][RTW89_WW][52] = 72, + [0][0][1][0][RTW89_WW][48] = 68, + [0][0][1][0][RTW89_WW][50] = 68, + [0][0][1][0][RTW89_WW][52] = 68, [0][1][1][0][RTW89_WW][0] = 0, [0][1][1][0][RTW89_WW][2] = 0, [0][1][1][0][RTW89_WW][4] = 0, @@ -4936,9 +4952,9 @@ const s8 rtw89_8851b_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_WW][42] = 30, [0][0][2][0][RTW89_WW][44] = 30, [0][0][2][0][RTW89_WW][46] = 30, - [0][0][2][0][RTW89_WW][48] = 74, - [0][0][2][0][RTW89_WW][50] = 76, - [0][0][2][0][RTW89_WW][52] = 76, + [0][0][2][0][RTW89_WW][48] = 70, + [0][0][2][0][RTW89_WW][50] = 72, + [0][0][2][0][RTW89_WW][52] = 72, [0][1][2][0][RTW89_WW][0] = 0, [0][1][2][0][RTW89_WW][2] = 0, [0][1][2][0][RTW89_WW][4] = 0, @@ -4995,11 +5011,11 @@ const s8 rtw89_8851b_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][1][RTW89_WW][48] = 0, [0][1][2][1][RTW89_WW][50] = 0, [0][1][2][1][RTW89_WW][52] = 0, - [1][0][2][0][RTW89_WW][1] = 64, + [1][0][2][0][RTW89_WW][1] = 60, [1][0][2][0][RTW89_WW][5] = 62, [1][0][2][0][RTW89_WW][9] = 64, - [1][0][2][0][RTW89_WW][13] = 64, - [1][0][2][0][RTW89_WW][16] = 66, + [1][0][2][0][RTW89_WW][13] = 60, + [1][0][2][0][RTW89_WW][16] = 62, [1][0][2][0][RTW89_WW][20] = 66, [1][0][2][0][RTW89_WW][24] = 66, [1][0][2][0][RTW89_WW][28] = 66, @@ -5007,8 +5023,8 @@ const s8 rtw89_8851b_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][0][2][0][RTW89_WW][36] = 76, [1][0][2][0][RTW89_WW][39] = 30, [1][0][2][0][RTW89_WW][43] = 30, - [1][0][2][0][RTW89_WW][47] = 84, - [1][0][2][0][RTW89_WW][51] = 84, + [1][0][2][0][RTW89_WW][47] = 80, + [1][0][2][0][RTW89_WW][51] = 80, [1][1][2][0][RTW89_WW][1] = 0, [1][1][2][0][RTW89_WW][5] = 0, [1][1][2][0][RTW89_WW][9] = 0, @@ -5037,13 +5053,13 @@ const s8 rtw89_8851b_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][1][2][1][RTW89_WW][43] = 0, [1][1][2][1][RTW89_WW][47] = 0, [1][1][2][1][RTW89_WW][51] = 0, - [2][0][2][0][RTW89_WW][3] = 62, - [2][0][2][0][RTW89_WW][11] = 62, - [2][0][2][0][RTW89_WW][18] = 64, + [2][0][2][0][RTW89_WW][3] = 60, + [2][0][2][0][RTW89_WW][11] = 58, + [2][0][2][0][RTW89_WW][18] = 62, [2][0][2][0][RTW89_WW][26] = 64, [2][0][2][0][RTW89_WW][34] = 72, [2][0][2][0][RTW89_WW][41] = 30, - [2][0][2][0][RTW89_WW][49] = 74, + [2][0][2][0][RTW89_WW][49] = 70, [2][1][2][0][RTW89_WW][3] = 0, [2][1][2][0][RTW89_WW][11] = 0, [2][1][2][0][RTW89_WW][18] = 0, @@ -5067,7 +5083,7 @@ const s8 rtw89_8851b_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [3][1][2][1][RTW89_WW][7] = 0, [3][1][2][1][RTW89_WW][22] = 0, [3][1][2][1][RTW89_WW][45] = 0, - [0][0][1][0][RTW89_FCC][0] = 80, + [0][0][1][0][RTW89_FCC][0] = 76, [0][0][1][0][RTW89_ETSI][0] = 58, [0][0][1][0][RTW89_MKK][0] = 60, [0][0][1][0][RTW89_IC][0] = 62, @@ -5123,7 +5139,7 @@ const s8 rtw89_8851b_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_ACMA][12] = 58, [0][0][1][0][RTW89_CN][12] = 60, [0][0][1][0][RTW89_UK][12] = 58, - [0][0][1][0][RTW89_FCC][14] = 78, + [0][0][1][0][RTW89_FCC][14] = 74, [0][0][1][0][RTW89_ETSI][14] = 58, [0][0][1][0][RTW89_MKK][14] = 60, [0][0][1][0][RTW89_IC][14] = 64, @@ -5131,10 +5147,10 @@ const s8 rtw89_8851b_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_ACMA][14] = 58, [0][0][1][0][RTW89_CN][14] = 60, [0][0][1][0][RTW89_UK][14] = 58, - [0][0][1][0][RTW89_FCC][15] = 78, + [0][0][1][0][RTW89_FCC][15] = 74, [0][0][1][0][RTW89_ETSI][15] = 58, [0][0][1][0][RTW89_MKK][15] = 78, - [0][0][1][0][RTW89_IC][15] = 78, + [0][0][1][0][RTW89_IC][15] = 74, [0][0][1][0][RTW89_KCC][15] = 78, [0][0][1][0][RTW89_ACMA][15] = 58, [0][0][1][0][RTW89_CN][15] = 127, @@ -5211,10 +5227,10 @@ const s8 rtw89_8851b_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_ACMA][33] = 60, [0][0][1][0][RTW89_CN][33] = 127, [0][0][1][0][RTW89_UK][33] = 60, - [0][0][1][0][RTW89_FCC][35] = 72, + [0][0][1][0][RTW89_FCC][35] = 68, [0][0][1][0][RTW89_ETSI][35] = 60, [0][0][1][0][RTW89_MKK][35] = 78, - [0][0][1][0][RTW89_IC][35] = 72, + [0][0][1][0][RTW89_IC][35] = 68, [0][0][1][0][RTW89_KCC][35] = 74, [0][0][1][0][RTW89_ACMA][35] = 60, [0][0][1][0][RTW89_CN][35] = 127, @@ -5267,7 +5283,7 @@ const s8 rtw89_8851b_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_ACMA][46] = 78, [0][0][1][0][RTW89_CN][46] = 78, [0][0][1][0][RTW89_UK][46] = 58, - [0][0][1][0][RTW89_FCC][48] = 72, + [0][0][1][0][RTW89_FCC][48] = 68, [0][0][1][0][RTW89_ETSI][48] = 127, [0][0][1][0][RTW89_MKK][48] = 127, [0][0][1][0][RTW89_IC][48] = 127, @@ -5275,7 +5291,7 @@ const s8 rtw89_8851b_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_ACMA][48] = 127, [0][0][1][0][RTW89_CN][48] = 127, [0][0][1][0][RTW89_UK][48] = 127, - [0][0][1][0][RTW89_FCC][50] = 72, + [0][0][1][0][RTW89_FCC][50] = 68, [0][0][1][0][RTW89_ETSI][50] = 127, [0][0][1][0][RTW89_MKK][50] = 127, [0][0][1][0][RTW89_IC][50] = 127, @@ -5283,7 +5299,7 @@ const s8 rtw89_8851b_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_ACMA][50] = 127, [0][0][1][0][RTW89_CN][50] = 127, [0][0][1][0][RTW89_UK][50] = 127, - [0][0][1][0][RTW89_FCC][52] = 72, + [0][0][1][0][RTW89_FCC][52] = 68, [0][0][1][0][RTW89_ETSI][52] = 127, [0][0][1][0][RTW89_MKK][52] = 127, [0][0][1][0][RTW89_IC][52] = 127, @@ -5515,7 +5531,7 @@ const s8 rtw89_8851b_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][1][0][RTW89_ACMA][52] = 127, [0][1][1][0][RTW89_CN][52] = 127, [0][1][1][0][RTW89_UK][52] = 127, - [0][0][2][0][RTW89_FCC][0] = 78, + [0][0][2][0][RTW89_FCC][0] = 74, [0][0][2][0][RTW89_ETSI][0] = 62, [0][0][2][0][RTW89_MKK][0] = 62, [0][0][2][0][RTW89_IC][0] = 64, @@ -5571,7 +5587,7 @@ const s8 rtw89_8851b_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_ACMA][12] = 62, [0][0][2][0][RTW89_CN][12] = 62, [0][0][2][0][RTW89_UK][12] = 62, - [0][0][2][0][RTW89_FCC][14] = 76, + [0][0][2][0][RTW89_FCC][14] = 72, [0][0][2][0][RTW89_ETSI][14] = 62, [0][0][2][0][RTW89_MKK][14] = 62, [0][0][2][0][RTW89_IC][14] = 64, @@ -5579,10 +5595,10 @@ const s8 rtw89_8851b_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_ACMA][14] = 62, [0][0][2][0][RTW89_CN][14] = 62, [0][0][2][0][RTW89_UK][14] = 62, - [0][0][2][0][RTW89_FCC][15] = 76, + [0][0][2][0][RTW89_FCC][15] = 72, [0][0][2][0][RTW89_ETSI][15] = 60, [0][0][2][0][RTW89_MKK][15] = 78, - [0][0][2][0][RTW89_IC][15] = 76, + [0][0][2][0][RTW89_IC][15] = 72, [0][0][2][0][RTW89_KCC][15] = 78, [0][0][2][0][RTW89_ACMA][15] = 60, [0][0][2][0][RTW89_CN][15] = 127, @@ -5659,10 +5675,10 @@ const s8 rtw89_8851b_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_ACMA][33] = 62, [0][0][2][0][RTW89_CN][33] = 127, [0][0][2][0][RTW89_UK][33] = 62, - [0][0][2][0][RTW89_FCC][35] = 72, + [0][0][2][0][RTW89_FCC][35] = 68, [0][0][2][0][RTW89_ETSI][35] = 62, [0][0][2][0][RTW89_MKK][35] = 78, - [0][0][2][0][RTW89_IC][35] = 72, + [0][0][2][0][RTW89_IC][35] = 68, [0][0][2][0][RTW89_KCC][35] = 74, [0][0][2][0][RTW89_ACMA][35] = 62, [0][0][2][0][RTW89_CN][35] = 127, @@ -5715,7 +5731,7 @@ const s8 rtw89_8851b_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_ACMA][46] = 78, [0][0][2][0][RTW89_CN][46] = 78, [0][0][2][0][RTW89_UK][46] = 60, - [0][0][2][0][RTW89_FCC][48] = 74, + [0][0][2][0][RTW89_FCC][48] = 70, [0][0][2][0][RTW89_ETSI][48] = 127, [0][0][2][0][RTW89_MKK][48] = 127, [0][0][2][0][RTW89_IC][48] = 127, @@ -5723,7 +5739,7 @@ const s8 rtw89_8851b_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_ACMA][48] = 127, [0][0][2][0][RTW89_CN][48] = 127, [0][0][2][0][RTW89_UK][48] = 127, - [0][0][2][0][RTW89_FCC][50] = 76, + [0][0][2][0][RTW89_FCC][50] = 72, [0][0][2][0][RTW89_ETSI][50] = 127, [0][0][2][0][RTW89_MKK][50] = 127, [0][0][2][0][RTW89_IC][50] = 127, @@ -5731,7 +5747,7 @@ const s8 rtw89_8851b_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_ACMA][50] = 127, [0][0][2][0][RTW89_CN][50] = 127, [0][0][2][0][RTW89_UK][50] = 127, - [0][0][2][0][RTW89_FCC][52] = 76, + [0][0][2][0][RTW89_FCC][52] = 72, [0][0][2][0][RTW89_ETSI][52] = 127, [0][0][2][0][RTW89_MKK][52] = 127, [0][0][2][0][RTW89_IC][52] = 127, @@ -6187,10 +6203,10 @@ const s8 rtw89_8851b_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][1][RTW89_ACMA][52] = 127, [0][1][2][1][RTW89_CN][52] = 127, [0][1][2][1][RTW89_UK][52] = 127, - [1][0][2][0][RTW89_FCC][1] = 68, + [1][0][2][0][RTW89_FCC][1] = 64, [1][0][2][0][RTW89_ETSI][1] = 64, [1][0][2][0][RTW89_MKK][1] = 64, - [1][0][2][0][RTW89_IC][1] = 64, + [1][0][2][0][RTW89_IC][1] = 60, [1][0][2][0][RTW89_KCC][1] = 74, [1][0][2][0][RTW89_ACMA][1] = 64, [1][0][2][0][RTW89_CN][1] = 64, @@ -6211,18 +6227,18 @@ const s8 rtw89_8851b_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][0][2][0][RTW89_ACMA][9] = 64, [1][0][2][0][RTW89_CN][9] = 64, [1][0][2][0][RTW89_UK][9] = 64, - [1][0][2][0][RTW89_FCC][13] = 66, + [1][0][2][0][RTW89_FCC][13] = 62, [1][0][2][0][RTW89_ETSI][13] = 64, [1][0][2][0][RTW89_MKK][13] = 64, - [1][0][2][0][RTW89_IC][13] = 64, + [1][0][2][0][RTW89_IC][13] = 60, [1][0][2][0][RTW89_KCC][13] = 72, [1][0][2][0][RTW89_ACMA][13] = 64, [1][0][2][0][RTW89_CN][13] = 64, [1][0][2][0][RTW89_UK][13] = 64, - [1][0][2][0][RTW89_FCC][16] = 66, + [1][0][2][0][RTW89_FCC][16] = 62, [1][0][2][0][RTW89_ETSI][16] = 66, [1][0][2][0][RTW89_MKK][16] = 80, - [1][0][2][0][RTW89_IC][16] = 66, + [1][0][2][0][RTW89_IC][16] = 62, [1][0][2][0][RTW89_KCC][16] = 74, [1][0][2][0][RTW89_ACMA][16] = 66, [1][0][2][0][RTW89_CN][16] = 127, @@ -6230,7 +6246,7 @@ const s8 rtw89_8851b_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][0][2][0][RTW89_FCC][20] = 80, [1][0][2][0][RTW89_ETSI][20] = 66, [1][0][2][0][RTW89_MKK][20] = 80, - [1][0][2][0][RTW89_IC][20] = 80, + [1][0][2][0][RTW89_IC][20] = 76, [1][0][2][0][RTW89_KCC][20] = 74, [1][0][2][0][RTW89_ACMA][20] = 66, [1][0][2][0][RTW89_CN][20] = 127, @@ -6251,10 +6267,10 @@ const s8 rtw89_8851b_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][0][2][0][RTW89_ACMA][28] = 127, [1][0][2][0][RTW89_CN][28] = 127, [1][0][2][0][RTW89_UK][28] = 66, - [1][0][2][0][RTW89_FCC][32] = 76, + [1][0][2][0][RTW89_FCC][32] = 72, [1][0][2][0][RTW89_ETSI][32] = 66, [1][0][2][0][RTW89_MKK][32] = 80, - [1][0][2][0][RTW89_IC][32] = 76, + [1][0][2][0][RTW89_IC][32] = 72, [1][0][2][0][RTW89_KCC][32] = 78, [1][0][2][0][RTW89_ACMA][32] = 66, [1][0][2][0][RTW89_CN][32] = 127, @@ -6270,7 +6286,7 @@ const s8 rtw89_8851b_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][0][2][0][RTW89_FCC][39] = 84, [1][0][2][0][RTW89_ETSI][39] = 30, [1][0][2][0][RTW89_MKK][39] = 127, - [1][0][2][0][RTW89_IC][39] = 84, + [1][0][2][0][RTW89_IC][39] = 80, [1][0][2][0][RTW89_KCC][39] = 68, [1][0][2][0][RTW89_ACMA][39] = 80, [1][0][2][0][RTW89_CN][39] = 70, @@ -6283,7 +6299,7 @@ const s8 rtw89_8851b_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][0][2][0][RTW89_ACMA][43] = 80, [1][0][2][0][RTW89_CN][43] = 80, [1][0][2][0][RTW89_UK][43] = 64, - [1][0][2][0][RTW89_FCC][47] = 84, + [1][0][2][0][RTW89_FCC][47] = 80, [1][0][2][0][RTW89_ETSI][47] = 127, [1][0][2][0][RTW89_MKK][47] = 127, [1][0][2][0][RTW89_IC][47] = 127, @@ -6291,7 +6307,7 @@ const s8 rtw89_8851b_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][0][2][0][RTW89_ACMA][47] = 127, [1][0][2][0][RTW89_CN][47] = 127, [1][0][2][0][RTW89_UK][47] = 127, - [1][0][2][0][RTW89_FCC][51] = 84, + [1][0][2][0][RTW89_FCC][51] = 80, [1][0][2][0][RTW89_ETSI][51] = 127, [1][0][2][0][RTW89_MKK][51] = 127, [1][0][2][0][RTW89_IC][51] = 127, @@ -6523,26 +6539,26 @@ const s8 rtw89_8851b_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][1][2][1][RTW89_ACMA][51] = 127, [1][1][2][1][RTW89_CN][51] = 127, [1][1][2][1][RTW89_UK][51] = 127, - [2][0][2][0][RTW89_FCC][3] = 76, + [2][0][2][0][RTW89_FCC][3] = 72, [2][0][2][0][RTW89_ETSI][3] = 64, [2][0][2][0][RTW89_MKK][3] = 62, - [2][0][2][0][RTW89_IC][3] = 64, + [2][0][2][0][RTW89_IC][3] = 60, [2][0][2][0][RTW89_KCC][3] = 72, [2][0][2][0][RTW89_ACMA][3] = 64, [2][0][2][0][RTW89_CN][3] = 64, [2][0][2][0][RTW89_UK][3] = 64, - [2][0][2][0][RTW89_FCC][11] = 64, + [2][0][2][0][RTW89_FCC][11] = 60, [2][0][2][0][RTW89_ETSI][11] = 64, [2][0][2][0][RTW89_MKK][11] = 64, - [2][0][2][0][RTW89_IC][11] = 62, + [2][0][2][0][RTW89_IC][11] = 58, [2][0][2][0][RTW89_KCC][11] = 72, [2][0][2][0][RTW89_ACMA][11] = 64, [2][0][2][0][RTW89_CN][11] = 64, [2][0][2][0][RTW89_UK][11] = 64, - [2][0][2][0][RTW89_FCC][18] = 66, + [2][0][2][0][RTW89_FCC][18] = 62, [2][0][2][0][RTW89_ETSI][18] = 64, [2][0][2][0][RTW89_MKK][18] = 72, - [2][0][2][0][RTW89_IC][18] = 66, + [2][0][2][0][RTW89_IC][18] = 62, [2][0][2][0][RTW89_KCC][18] = 72, [2][0][2][0][RTW89_ACMA][18] = 64, [2][0][2][0][RTW89_CN][18] = 127, @@ -6558,7 +6574,7 @@ const s8 rtw89_8851b_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [2][0][2][0][RTW89_FCC][34] = 76, [2][0][2][0][RTW89_ETSI][34] = 127, [2][0][2][0][RTW89_MKK][34] = 72, - [2][0][2][0][RTW89_IC][34] = 76, + [2][0][2][0][RTW89_IC][34] = 72, [2][0][2][0][RTW89_KCC][34] = 72, [2][0][2][0][RTW89_ACMA][34] = 72, [2][0][2][0][RTW89_CN][34] = 127, @@ -6566,12 +6582,12 @@ const s8 rtw89_8851b_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [2][0][2][0][RTW89_FCC][41] = 76, [2][0][2][0][RTW89_ETSI][41] = 30, [2][0][2][0][RTW89_MKK][41] = 127, - [2][0][2][0][RTW89_IC][41] = 76, + [2][0][2][0][RTW89_IC][41] = 72, [2][0][2][0][RTW89_KCC][41] = 64, [2][0][2][0][RTW89_ACMA][41] = 72, [2][0][2][0][RTW89_CN][41] = 72, [2][0][2][0][RTW89_UK][41] = 64, - [2][0][2][0][RTW89_FCC][49] = 74, + [2][0][2][0][RTW89_FCC][49] = 70, [2][0][2][0][RTW89_ETSI][49] = 127, [2][0][2][0][RTW89_MKK][49] = 127, [2][0][2][0][RTW89_IC][49] = 127, @@ -10590,9 +10606,9 @@ const s8 rtw89_8851b_txpwr_lmt_5g_type2[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_WW][42] = 30, [0][0][1][0][RTW89_WW][44] = 30, [0][0][1][0][RTW89_WW][46] = 30, - [0][0][1][0][RTW89_WW][48] = 72, - [0][0][1][0][RTW89_WW][50] = 72, - [0][0][1][0][RTW89_WW][52] = 72, + [0][0][1][0][RTW89_WW][48] = 68, + [0][0][1][0][RTW89_WW][50] = 68, + [0][0][1][0][RTW89_WW][52] = 68, [0][1][1][0][RTW89_WW][0] = 0, [0][1][1][0][RTW89_WW][2] = 0, [0][1][1][0][RTW89_WW][4] = 0, @@ -10646,9 +10662,9 @@ const s8 rtw89_8851b_txpwr_lmt_5g_type2[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_WW][42] = 30, [0][0][2][0][RTW89_WW][44] = 30, [0][0][2][0][RTW89_WW][46] = 30, - [0][0][2][0][RTW89_WW][48] = 74, - [0][0][2][0][RTW89_WW][50] = 74, - [0][0][2][0][RTW89_WW][52] = 74, + [0][0][2][0][RTW89_WW][48] = 70, + [0][0][2][0][RTW89_WW][50] = 70, + [0][0][2][0][RTW89_WW][52] = 70, [0][1][2][0][RTW89_WW][0] = 0, [0][1][2][0][RTW89_WW][2] = 0, [0][1][2][0][RTW89_WW][4] = 0, @@ -10705,11 +10721,11 @@ const s8 rtw89_8851b_txpwr_lmt_5g_type2[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][1][RTW89_WW][48] = 0, [0][1][2][1][RTW89_WW][50] = 0, [0][1][2][1][RTW89_WW][52] = 0, - [1][0][2][0][RTW89_WW][1] = 64, + [1][0][2][0][RTW89_WW][1] = 60, [1][0][2][0][RTW89_WW][5] = 62, [1][0][2][0][RTW89_WW][9] = 64, - [1][0][2][0][RTW89_WW][13] = 64, - [1][0][2][0][RTW89_WW][16] = 66, + [1][0][2][0][RTW89_WW][13] = 60, + [1][0][2][0][RTW89_WW][16] = 62, [1][0][2][0][RTW89_WW][20] = 66, [1][0][2][0][RTW89_WW][24] = 66, [1][0][2][0][RTW89_WW][28] = 66, @@ -10717,8 +10733,8 @@ const s8 rtw89_8851b_txpwr_lmt_5g_type2[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][0][2][0][RTW89_WW][36] = 76, [1][0][2][0][RTW89_WW][39] = 30, [1][0][2][0][RTW89_WW][43] = 30, - [1][0][2][0][RTW89_WW][47] = 80, - [1][0][2][0][RTW89_WW][51] = 80, + [1][0][2][0][RTW89_WW][47] = 76, + [1][0][2][0][RTW89_WW][51] = 76, [1][1][2][0][RTW89_WW][1] = 0, [1][1][2][0][RTW89_WW][5] = 0, [1][1][2][0][RTW89_WW][9] = 0, @@ -10747,13 +10763,13 @@ const s8 rtw89_8851b_txpwr_lmt_5g_type2[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][1][2][1][RTW89_WW][43] = 0, [1][1][2][1][RTW89_WW][47] = 0, [1][1][2][1][RTW89_WW][51] = 0, - [2][0][2][0][RTW89_WW][3] = 62, - [2][0][2][0][RTW89_WW][11] = 62, - [2][0][2][0][RTW89_WW][18] = 64, + [2][0][2][0][RTW89_WW][3] = 60, + [2][0][2][0][RTW89_WW][11] = 58, + [2][0][2][0][RTW89_WW][18] = 62, [2][0][2][0][RTW89_WW][26] = 64, [2][0][2][0][RTW89_WW][34] = 68, [2][0][2][0][RTW89_WW][41] = 30, - [2][0][2][0][RTW89_WW][49] = 72, + [2][0][2][0][RTW89_WW][49] = 68, [2][1][2][0][RTW89_WW][3] = 0, [2][1][2][0][RTW89_WW][11] = 0, [2][1][2][0][RTW89_WW][18] = 0, @@ -10777,7 +10793,7 @@ const s8 rtw89_8851b_txpwr_lmt_5g_type2[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [3][1][2][1][RTW89_WW][7] = 0, [3][1][2][1][RTW89_WW][22] = 0, [3][1][2][1][RTW89_WW][45] = 0, - [0][0][1][0][RTW89_FCC][0] = 78, + [0][0][1][0][RTW89_FCC][0] = 74, [0][0][1][0][RTW89_ETSI][0] = 58, [0][0][1][0][RTW89_MKK][0] = 60, [0][0][1][0][RTW89_IC][0] = 62, @@ -10833,7 +10849,7 @@ const s8 rtw89_8851b_txpwr_lmt_5g_type2[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_ACMA][12] = 58, [0][0][1][0][RTW89_CN][12] = 60, [0][0][1][0][RTW89_UK][12] = 58, - [0][0][1][0][RTW89_FCC][14] = 76, + [0][0][1][0][RTW89_FCC][14] = 72, [0][0][1][0][RTW89_ETSI][14] = 58, [0][0][1][0][RTW89_MKK][14] = 60, [0][0][1][0][RTW89_IC][14] = 62, @@ -10841,10 +10857,10 @@ const s8 rtw89_8851b_txpwr_lmt_5g_type2[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_ACMA][14] = 58, [0][0][1][0][RTW89_CN][14] = 60, [0][0][1][0][RTW89_UK][14] = 58, - [0][0][1][0][RTW89_FCC][15] = 76, + [0][0][1][0][RTW89_FCC][15] = 72, [0][0][1][0][RTW89_ETSI][15] = 58, [0][0][1][0][RTW89_MKK][15] = 74, - [0][0][1][0][RTW89_IC][15] = 76, + [0][0][1][0][RTW89_IC][15] = 72, [0][0][1][0][RTW89_KCC][15] = 74, [0][0][1][0][RTW89_ACMA][15] = 58, [0][0][1][0][RTW89_CN][15] = 127, @@ -10921,10 +10937,10 @@ const s8 rtw89_8851b_txpwr_lmt_5g_type2[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_ACMA][33] = 60, [0][0][1][0][RTW89_CN][33] = 127, [0][0][1][0][RTW89_UK][33] = 60, - [0][0][1][0][RTW89_FCC][35] = 70, + [0][0][1][0][RTW89_FCC][35] = 66, [0][0][1][0][RTW89_ETSI][35] = 60, [0][0][1][0][RTW89_MKK][35] = 74, - [0][0][1][0][RTW89_IC][35] = 70, + [0][0][1][0][RTW89_IC][35] = 66, [0][0][1][0][RTW89_KCC][35] = 74, [0][0][1][0][RTW89_ACMA][35] = 60, [0][0][1][0][RTW89_CN][35] = 127, @@ -10977,7 +10993,7 @@ const s8 rtw89_8851b_txpwr_lmt_5g_type2[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_ACMA][46] = 74, [0][0][1][0][RTW89_CN][46] = 74, [0][0][1][0][RTW89_UK][46] = 58, - [0][0][1][0][RTW89_FCC][48] = 72, + [0][0][1][0][RTW89_FCC][48] = 68, [0][0][1][0][RTW89_ETSI][48] = 127, [0][0][1][0][RTW89_MKK][48] = 127, [0][0][1][0][RTW89_IC][48] = 127, @@ -10985,7 +11001,7 @@ const s8 rtw89_8851b_txpwr_lmt_5g_type2[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_ACMA][48] = 127, [0][0][1][0][RTW89_CN][48] = 127, [0][0][1][0][RTW89_UK][48] = 127, - [0][0][1][0][RTW89_FCC][50] = 72, + [0][0][1][0][RTW89_FCC][50] = 68, [0][0][1][0][RTW89_ETSI][50] = 127, [0][0][1][0][RTW89_MKK][50] = 127, [0][0][1][0][RTW89_IC][50] = 127, @@ -10993,7 +11009,7 @@ const s8 rtw89_8851b_txpwr_lmt_5g_type2[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_ACMA][50] = 127, [0][0][1][0][RTW89_CN][50] = 127, [0][0][1][0][RTW89_UK][50] = 127, - [0][0][1][0][RTW89_FCC][52] = 72, + [0][0][1][0][RTW89_FCC][52] = 68, [0][0][1][0][RTW89_ETSI][52] = 127, [0][0][1][0][RTW89_MKK][52] = 127, [0][0][1][0][RTW89_IC][52] = 127, @@ -11225,7 +11241,7 @@ const s8 rtw89_8851b_txpwr_lmt_5g_type2[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][1][0][RTW89_ACMA][52] = 127, [0][1][1][0][RTW89_CN][52] = 127, [0][1][1][0][RTW89_UK][52] = 127, - [0][0][2][0][RTW89_FCC][0] = 76, + [0][0][2][0][RTW89_FCC][0] = 72, [0][0][2][0][RTW89_ETSI][0] = 62, [0][0][2][0][RTW89_MKK][0] = 62, [0][0][2][0][RTW89_IC][0] = 64, @@ -11281,7 +11297,7 @@ const s8 rtw89_8851b_txpwr_lmt_5g_type2[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_ACMA][12] = 62, [0][0][2][0][RTW89_CN][12] = 62, [0][0][2][0][RTW89_UK][12] = 62, - [0][0][2][0][RTW89_FCC][14] = 74, + [0][0][2][0][RTW89_FCC][14] = 70, [0][0][2][0][RTW89_ETSI][14] = 62, [0][0][2][0][RTW89_MKK][14] = 62, [0][0][2][0][RTW89_IC][14] = 64, @@ -11289,10 +11305,10 @@ const s8 rtw89_8851b_txpwr_lmt_5g_type2[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_ACMA][14] = 62, [0][0][2][0][RTW89_CN][14] = 62, [0][0][2][0][RTW89_UK][14] = 62, - [0][0][2][0][RTW89_FCC][15] = 74, + [0][0][2][0][RTW89_FCC][15] = 70, [0][0][2][0][RTW89_ETSI][15] = 60, [0][0][2][0][RTW89_MKK][15] = 74, - [0][0][2][0][RTW89_IC][15] = 74, + [0][0][2][0][RTW89_IC][15] = 70, [0][0][2][0][RTW89_KCC][15] = 74, [0][0][2][0][RTW89_ACMA][15] = 60, [0][0][2][0][RTW89_CN][15] = 127, @@ -11369,10 +11385,10 @@ const s8 rtw89_8851b_txpwr_lmt_5g_type2[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_ACMA][33] = 62, [0][0][2][0][RTW89_CN][33] = 127, [0][0][2][0][RTW89_UK][33] = 62, - [0][0][2][0][RTW89_FCC][35] = 72, + [0][0][2][0][RTW89_FCC][35] = 68, [0][0][2][0][RTW89_ETSI][35] = 62, [0][0][2][0][RTW89_MKK][35] = 74, - [0][0][2][0][RTW89_IC][35] = 72, + [0][0][2][0][RTW89_IC][35] = 68, [0][0][2][0][RTW89_KCC][35] = 74, [0][0][2][0][RTW89_ACMA][35] = 62, [0][0][2][0][RTW89_CN][35] = 127, @@ -11425,7 +11441,7 @@ const s8 rtw89_8851b_txpwr_lmt_5g_type2[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_ACMA][46] = 74, [0][0][2][0][RTW89_CN][46] = 74, [0][0][2][0][RTW89_UK][46] = 60, - [0][0][2][0][RTW89_FCC][48] = 74, + [0][0][2][0][RTW89_FCC][48] = 70, [0][0][2][0][RTW89_ETSI][48] = 127, [0][0][2][0][RTW89_MKK][48] = 127, [0][0][2][0][RTW89_IC][48] = 127, @@ -11433,7 +11449,7 @@ const s8 rtw89_8851b_txpwr_lmt_5g_type2[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_ACMA][48] = 127, [0][0][2][0][RTW89_CN][48] = 127, [0][0][2][0][RTW89_UK][48] = 127, - [0][0][2][0][RTW89_FCC][50] = 74, + [0][0][2][0][RTW89_FCC][50] = 70, [0][0][2][0][RTW89_ETSI][50] = 127, [0][0][2][0][RTW89_MKK][50] = 127, [0][0][2][0][RTW89_IC][50] = 127, @@ -11441,7 +11457,7 @@ const s8 rtw89_8851b_txpwr_lmt_5g_type2[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_ACMA][50] = 127, [0][0][2][0][RTW89_CN][50] = 127, [0][0][2][0][RTW89_UK][50] = 127, - [0][0][2][0][RTW89_FCC][52] = 74, + [0][0][2][0][RTW89_FCC][52] = 70, [0][0][2][0][RTW89_ETSI][52] = 127, [0][0][2][0][RTW89_MKK][52] = 127, [0][0][2][0][RTW89_IC][52] = 127, @@ -11897,10 +11913,10 @@ const s8 rtw89_8851b_txpwr_lmt_5g_type2[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][1][RTW89_ACMA][52] = 127, [0][1][2][1][RTW89_CN][52] = 127, [0][1][2][1][RTW89_UK][52] = 127, - [1][0][2][0][RTW89_FCC][1] = 66, + [1][0][2][0][RTW89_FCC][1] = 62, [1][0][2][0][RTW89_ETSI][1] = 64, [1][0][2][0][RTW89_MKK][1] = 64, - [1][0][2][0][RTW89_IC][1] = 64, + [1][0][2][0][RTW89_IC][1] = 60, [1][0][2][0][RTW89_KCC][1] = 74, [1][0][2][0][RTW89_ACMA][1] = 64, [1][0][2][0][RTW89_CN][1] = 64, @@ -11921,18 +11937,18 @@ const s8 rtw89_8851b_txpwr_lmt_5g_type2[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][0][2][0][RTW89_ACMA][9] = 64, [1][0][2][0][RTW89_CN][9] = 64, [1][0][2][0][RTW89_UK][9] = 64, - [1][0][2][0][RTW89_FCC][13] = 64, + [1][0][2][0][RTW89_FCC][13] = 60, [1][0][2][0][RTW89_ETSI][13] = 64, [1][0][2][0][RTW89_MKK][13] = 64, - [1][0][2][0][RTW89_IC][13] = 64, + [1][0][2][0][RTW89_IC][13] = 60, [1][0][2][0][RTW89_KCC][13] = 72, [1][0][2][0][RTW89_ACMA][13] = 64, [1][0][2][0][RTW89_CN][13] = 64, [1][0][2][0][RTW89_UK][13] = 64, - [1][0][2][0][RTW89_FCC][16] = 66, + [1][0][2][0][RTW89_FCC][16] = 62, [1][0][2][0][RTW89_ETSI][16] = 66, [1][0][2][0][RTW89_MKK][16] = 76, - [1][0][2][0][RTW89_IC][16] = 66, + [1][0][2][0][RTW89_IC][16] = 62, [1][0][2][0][RTW89_KCC][16] = 74, [1][0][2][0][RTW89_ACMA][16] = 66, [1][0][2][0][RTW89_CN][16] = 127, @@ -11940,7 +11956,7 @@ const s8 rtw89_8851b_txpwr_lmt_5g_type2[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][0][2][0][RTW89_FCC][20] = 80, [1][0][2][0][RTW89_ETSI][20] = 66, [1][0][2][0][RTW89_MKK][20] = 76, - [1][0][2][0][RTW89_IC][20] = 80, + [1][0][2][0][RTW89_IC][20] = 76, [1][0][2][0][RTW89_KCC][20] = 74, [1][0][2][0][RTW89_ACMA][20] = 66, [1][0][2][0][RTW89_CN][20] = 127, @@ -11961,10 +11977,10 @@ const s8 rtw89_8851b_txpwr_lmt_5g_type2[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][0][2][0][RTW89_ACMA][28] = 127, [1][0][2][0][RTW89_CN][28] = 127, [1][0][2][0][RTW89_UK][28] = 66, - [1][0][2][0][RTW89_FCC][32] = 74, + [1][0][2][0][RTW89_FCC][32] = 70, [1][0][2][0][RTW89_ETSI][32] = 66, [1][0][2][0][RTW89_MKK][32] = 76, - [1][0][2][0][RTW89_IC][32] = 74, + [1][0][2][0][RTW89_IC][32] = 70, [1][0][2][0][RTW89_KCC][32] = 76, [1][0][2][0][RTW89_ACMA][32] = 66, [1][0][2][0][RTW89_CN][32] = 127, @@ -11980,7 +11996,7 @@ const s8 rtw89_8851b_txpwr_lmt_5g_type2[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][0][2][0][RTW89_FCC][39] = 80, [1][0][2][0][RTW89_ETSI][39] = 30, [1][0][2][0][RTW89_MKK][39] = 127, - [1][0][2][0][RTW89_IC][39] = 80, + [1][0][2][0][RTW89_IC][39] = 76, [1][0][2][0][RTW89_KCC][39] = 68, [1][0][2][0][RTW89_ACMA][39] = 76, [1][0][2][0][RTW89_CN][39] = 70, @@ -11993,7 +12009,7 @@ const s8 rtw89_8851b_txpwr_lmt_5g_type2[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][0][2][0][RTW89_ACMA][43] = 76, [1][0][2][0][RTW89_CN][43] = 76, [1][0][2][0][RTW89_UK][43] = 64, - [1][0][2][0][RTW89_FCC][47] = 80, + [1][0][2][0][RTW89_FCC][47] = 76, [1][0][2][0][RTW89_ETSI][47] = 127, [1][0][2][0][RTW89_MKK][47] = 127, [1][0][2][0][RTW89_IC][47] = 127, @@ -12001,7 +12017,7 @@ const s8 rtw89_8851b_txpwr_lmt_5g_type2[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][0][2][0][RTW89_ACMA][47] = 127, [1][0][2][0][RTW89_CN][47] = 127, [1][0][2][0][RTW89_UK][47] = 127, - [1][0][2][0][RTW89_FCC][51] = 80, + [1][0][2][0][RTW89_FCC][51] = 76, [1][0][2][0][RTW89_ETSI][51] = 127, [1][0][2][0][RTW89_MKK][51] = 127, [1][0][2][0][RTW89_IC][51] = 127, @@ -12233,26 +12249,26 @@ const s8 rtw89_8851b_txpwr_lmt_5g_type2[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][1][2][1][RTW89_ACMA][51] = 127, [1][1][2][1][RTW89_CN][51] = 127, [1][1][2][1][RTW89_UK][51] = 127, - [2][0][2][0][RTW89_FCC][3] = 72, + [2][0][2][0][RTW89_FCC][3] = 68, [2][0][2][0][RTW89_ETSI][3] = 64, [2][0][2][0][RTW89_MKK][3] = 62, - [2][0][2][0][RTW89_IC][3] = 64, + [2][0][2][0][RTW89_IC][3] = 60, [2][0][2][0][RTW89_KCC][3] = 68, [2][0][2][0][RTW89_ACMA][3] = 64, [2][0][2][0][RTW89_CN][3] = 64, [2][0][2][0][RTW89_UK][3] = 64, - [2][0][2][0][RTW89_FCC][11] = 62, + [2][0][2][0][RTW89_FCC][11] = 58, [2][0][2][0][RTW89_ETSI][11] = 64, [2][0][2][0][RTW89_MKK][11] = 64, - [2][0][2][0][RTW89_IC][11] = 62, + [2][0][2][0][RTW89_IC][11] = 58, [2][0][2][0][RTW89_KCC][11] = 68, [2][0][2][0][RTW89_ACMA][11] = 64, [2][0][2][0][RTW89_CN][11] = 64, [2][0][2][0][RTW89_UK][11] = 64, - [2][0][2][0][RTW89_FCC][18] = 66, + [2][0][2][0][RTW89_FCC][18] = 62, [2][0][2][0][RTW89_ETSI][18] = 64, [2][0][2][0][RTW89_MKK][18] = 68, - [2][0][2][0][RTW89_IC][18] = 66, + [2][0][2][0][RTW89_IC][18] = 62, [2][0][2][0][RTW89_KCC][18] = 68, [2][0][2][0][RTW89_ACMA][18] = 64, [2][0][2][0][RTW89_CN][18] = 127, @@ -12268,7 +12284,7 @@ const s8 rtw89_8851b_txpwr_lmt_5g_type2[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [2][0][2][0][RTW89_FCC][34] = 72, [2][0][2][0][RTW89_ETSI][34] = 127, [2][0][2][0][RTW89_MKK][34] = 68, - [2][0][2][0][RTW89_IC][34] = 72, + [2][0][2][0][RTW89_IC][34] = 68, [2][0][2][0][RTW89_KCC][34] = 68, [2][0][2][0][RTW89_ACMA][34] = 68, [2][0][2][0][RTW89_CN][34] = 127, @@ -12276,12 +12292,12 @@ const s8 rtw89_8851b_txpwr_lmt_5g_type2[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [2][0][2][0][RTW89_FCC][41] = 72, [2][0][2][0][RTW89_ETSI][41] = 30, [2][0][2][0][RTW89_MKK][41] = 127, - [2][0][2][0][RTW89_IC][41] = 72, + [2][0][2][0][RTW89_IC][41] = 68, [2][0][2][0][RTW89_KCC][41] = 64, [2][0][2][0][RTW89_ACMA][41] = 68, [2][0][2][0][RTW89_CN][41] = 68, [2][0][2][0][RTW89_UK][41] = 64, - [2][0][2][0][RTW89_FCC][49] = 72, + [2][0][2][0][RTW89_FCC][49] = 68, [2][0][2][0][RTW89_ETSI][49] = 127, [2][0][2][0][RTW89_MKK][49] = 127, [2][0][2][0][RTW89_IC][49] = 127, diff --git a/drivers/net/wireless/realtek/rtw89/rtw8851b_table.h b/drivers/net/wireless/realtek/rtw89/rtw8851b_table.h index f2e673ba39c8cbf7aa4695923215e0a9238324d5..a8737de02f669fddb2794901f2a826e4ea27b386 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8851b_table.h +++ b/drivers/net/wireless/realtek/rtw89/rtw8851b_table.h @@ -13,7 +13,7 @@ extern const struct rtw89_phy_table rtw89_8851b_phy_radioa_table; extern const struct rtw89_phy_table rtw89_8851b_phy_nctl_table; extern const struct rtw89_txpwr_table rtw89_8851b_byr_table; extern const struct rtw89_txpwr_track_cfg rtw89_8851b_trk_cfg; -extern const u8 rtw89_8851b_tx_shape[RTW89_BAND_MAX][RTW89_RS_TX_SHAPE_NUM] +extern const u8 rtw89_8851b_tx_shape[RTW89_BAND_NUM][RTW89_RS_TX_SHAPE_NUM] [RTW89_REGD_NUM]; extern const struct rtw89_rfe_parms rtw89_8851b_dflt_parms; extern const struct rtw89_rfe_parms_conf rtw89_8851b_rfe_parms_conf[]; diff --git a/drivers/net/wireless/realtek/rtw89/rtw8851be.c b/drivers/net/wireless/realtek/rtw89/rtw8851be.c new file mode 100644 index 0000000000000000000000000000000000000000..0f7711c50bd155e1f264ee3f20b1c9648d7365ec --- /dev/null +++ b/drivers/net/wireless/realtek/rtw89/rtw8851be.c @@ -0,0 +1,86 @@ +// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause +/* Copyright(c) 2022-2023 Realtek Corporation + */ + +#include +#include + +#include "pci.h" +#include "reg.h" +#include "rtw8851b.h" + +static const struct rtw89_pci_info rtw8851b_pci_info = { + .txbd_trunc_mode = MAC_AX_BD_TRUNC, + .rxbd_trunc_mode = MAC_AX_BD_TRUNC, + .rxbd_mode = MAC_AX_RXBD_PKT, + .tag_mode = MAC_AX_TAG_MULTI, + .tx_burst = MAC_AX_TX_BURST_2048B, + .rx_burst = MAC_AX_RX_BURST_128B, + .wd_dma_idle_intvl = MAC_AX_WD_DMA_INTVL_256NS, + .wd_dma_act_intvl = MAC_AX_WD_DMA_INTVL_256NS, + .multi_tag_num = MAC_AX_TAG_NUM_8, + .lbc_en = MAC_AX_PCIE_ENABLE, + .lbc_tmr = MAC_AX_LBC_TMR_2MS, + .autok_en = MAC_AX_PCIE_DISABLE, + .io_rcy_en = MAC_AX_PCIE_DISABLE, + .io_rcy_tmr = MAC_AX_IO_RCY_ANA_TMR_6MS, + + .init_cfg_reg = R_AX_PCIE_INIT_CFG1, + .txhci_en_bit = B_AX_TXHCI_EN, + .rxhci_en_bit = B_AX_RXHCI_EN, + .rxbd_mode_bit = B_AX_RXBD_MODE, + .exp_ctrl_reg = R_AX_PCIE_EXP_CTRL, + .max_tag_num_mask = B_AX_MAX_TAG_NUM, + .rxbd_rwptr_clr_reg = R_AX_RXBD_RWPTR_CLR, + .txbd_rwptr_clr2_reg = 0, + .dma_stop1 = {R_AX_PCIE_DMA_STOP1, B_AX_TX_STOP1_MASK_V1}, + .dma_stop2 = {0}, + .dma_busy1 = {R_AX_PCIE_DMA_BUSY1, DMA_BUSY1_CHECK_V1}, + .dma_busy2_reg = 0, + .dma_busy3_reg = R_AX_PCIE_DMA_BUSY1, + + .rpwm_addr = R_AX_PCIE_HRPWM, + .cpwm_addr = R_AX_CPWM, + .tx_dma_ch_mask = BIT(RTW89_TXCH_ACH4) | BIT(RTW89_TXCH_ACH5) | + BIT(RTW89_TXCH_ACH6) | BIT(RTW89_TXCH_ACH7) | + BIT(RTW89_TXCH_CH10) | BIT(RTW89_TXCH_CH11), + .bd_idx_addr_low_power = NULL, + .dma_addr_set = &rtw89_pci_ch_dma_addr_set, + .bd_ram_table = &rtw89_bd_ram_table_single, + + .ltr_set = rtw89_pci_ltr_set, + .fill_txaddr_info = rtw89_pci_fill_txaddr_info, + .config_intr_mask = rtw89_pci_config_intr_mask, + .enable_intr = rtw89_pci_enable_intr, + .disable_intr = rtw89_pci_disable_intr, + .recognize_intrs = rtw89_pci_recognize_intrs, +}; + +static const struct rtw89_driver_info rtw89_8851be_info = { + .chip = &rtw8851b_chip_info, + .bus = { + .pci = &rtw8851b_pci_info, + }, +}; + +static const struct pci_device_id rtw89_8851be_id_table[] = { + { + PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0xb851), + .driver_data = (kernel_ulong_t)&rtw89_8851be_info, + }, + {}, +}; +MODULE_DEVICE_TABLE(pci, rtw89_8851be_id_table); + +static struct pci_driver rtw89_8851be_driver = { + .name = "rtw89_8851be", + .id_table = rtw89_8851be_id_table, + .probe = rtw89_pci_probe, + .remove = rtw89_pci_remove, + .driver.pm = &rtw89_pm_ops, +}; +module_pci_driver(rtw89_8851be_driver); + +MODULE_AUTHOR("Realtek Corporation"); +MODULE_DESCRIPTION("Realtek 802.11ax wireless 8851BE driver"); +MODULE_LICENSE("Dual BSD/GPL"); diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852a.c b/drivers/net/wireless/realtek/rtw89/rtw8852a.c index d7930efd89b7243fe7339f7b676a9a7e1d8a61cb..6257414a3b4bd804c6d15f9dffa94fa51f14f9a4 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852a.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852a.c @@ -463,6 +463,12 @@ static const struct rtw89_imr_info rtw8852a_imr_info = { .tmac_imr_set = B_AX_TMAC_IMR_SET, }; +static const struct rtw89_xtal_info rtw8852a_xtal_info = { + .xcap_reg = R_AX_XTAL_ON_CTRL0, + .sc_xo_mask = B_AX_XTAL_SC_XO_MASK, + .sc_xi_mask = B_AX_XTAL_SC_XI_MASK, +}; + static const struct rtw89_rrsr_cfgs rtw8852a_rrsr_cfgs = { .ref_rate = {R_AX_TRXPTCL_RRSR_CTL_0, B_AX_WMAC_RESP_REF_RATE_SEL, 0}, .rsc = {R_AX_TRXPTCL_RRSR_CTL_0, B_AX_WMAC_RESP_RSC_MASK, 2}, @@ -1332,7 +1338,6 @@ static void rtw8852a_rfk_scan(struct rtw89_dev *rtwdev, bool start) static void rtw8852a_rfk_track(struct rtw89_dev *rtwdev) { rtw8852a_dpk_track(rtwdev); - rtw8852a_iqk_track(rtwdev); rtw8852a_tssi_track(rtwdev); } @@ -2026,6 +2031,7 @@ static const struct rtw89_chip_ops rtw8852a_chip_ops = { .read_efuse = rtw8852a_read_efuse, .read_phycap = rtw8852a_read_phycap, .fem_setup = rtw8852a_fem_setup, + .rfe_gpio = NULL, .rfk_init = rtw8852a_rfk_init, .rfk_channel = rtw8852a_rfk_channel, .rfk_band_changed = rtw8852a_rfk_band_changed, @@ -2043,6 +2049,7 @@ static const struct rtw89_chip_ops rtw8852a_chip_ops = { .set_txpwr_ul_tb_offset = rtw8852a_set_txpwr_ul_tb_offset, .pwr_on_func = NULL, .pwr_off_func = NULL, + .query_rxdesc = rtw89_core_query_rxdesc, .fill_txdesc = rtw89_core_fill_txdesc, .fill_txdesc_fwcmd = rtw89_core_fill_txdesc, .cfg_ctrl_path = rtw89_mac_cfg_ctrl_path, @@ -2069,6 +2076,7 @@ const struct rtw89_chip_info rtw8852a_chip_info = { .fw_format_max = RTW8852A_FW_FORMAT_MAX, .try_ce_fw = false, .fifo_size = 458752, + .small_fifo_size = false, .dle_scc_rsvd_size = 0, .max_amsdu_limit = 3500, .dis_2g_40m_ul_ofdma = true, @@ -2085,6 +2093,7 @@ const struct rtw89_chip_info rtw8852a_chip_info = { .rf_table = {&rtw89_8852a_phy_radioa_table, &rtw89_8852a_phy_radiob_table,}, .nctl_table = &rtw89_8852a_phy_nctl_table, + .nctl_post_table = NULL, .byr_table = &rtw89_8852a_byr_table, .dflt_parms = &rtw89_8852a_dflt_parms, .rfe_parms_conf = NULL, @@ -2097,6 +2106,7 @@ const struct rtw89_chip_info rtw8852a_chip_info = { .support_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ), .support_bw160 = false, + .support_unii4 = false, .support_ul_tb_ctrl = false, .hw_sec_hdr = false, .rf_path_num = 2, @@ -2107,7 +2117,7 @@ const struct rtw89_chip_info rtw8852a_chip_info = { .scam_num = 128, .bacam_num = 2, .bacam_dynamic_num = 4, - .bacam_v1 = false, + .bacam_ver = RTW89_BACAM_V0, .sec_ctrl_efuse_size = 4, .physical_efuse_size = 1216, .logical_efuse_size = 1536, @@ -2159,6 +2169,7 @@ const struct rtw89_chip_info rtw8852a_chip_info = { #ifdef CONFIG_PM .wowlan_stub = &rtw_wowlan_stub_8852a, #endif + .xtal_info = &rtw8852a_xtal_info, }; EXPORT_SYMBOL(rtw8852a_chip_info); diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852a_rfk.c b/drivers/net/wireless/realtek/rtw89/rtw8852a_rfk.c index cd6c39b7f802595e8d964916656ecbc745796259..d86429e4a35ffeef74c583dcb4046cf838e8cd1e 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852a_rfk.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852a_rfk.c @@ -1284,11 +1284,8 @@ static void _iqk_info_iqk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx, u32 tmp = 0x0; bool flag = 0x0; - iqk_info->thermal[path] = - ewma_thermal_read(&rtwdev->phystat.avg_thermal[path]); - iqk_info->thermal_rek_en = false; - rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]S%d_thermal = %d\n", path, - iqk_info->thermal[path]); + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]S%d_thermal = %lu\n", path, + ewma_thermal_read(&rtwdev->phystat.avg_thermal[path])); rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]S%d_LOK_COR_fail= %d\n", path, iqk_info->lok_cor_fail[0][path]); rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]S%d_LOK_FIN_fail= %d\n", path, @@ -1536,28 +1533,6 @@ static void _iqk_dbcc(struct rtw89_dev *rtwdev, u8 path) _iqk_afebb_restore(rtwdev, phy_idx, path); } -static void _iqk_track(struct rtw89_dev *rtwdev) -{ - struct rtw89_iqk_info *iqk = &rtwdev->iqk; - u8 path = 0x0; - u8 cur_ther; - - if (iqk->iqk_band[0] == RTW89_BAND_2G) - return; - if (iqk->iqk_bw[0] < RTW89_CHANNEL_WIDTH_80) - return; - - /* only check path 0 */ - for (path = 0; path < 1; path++) { - cur_ther = ewma_thermal_read(&rtwdev->phystat.avg_thermal[path]); - - if (abs(cur_ther - iqk->thermal[path]) > RTW8852A_IQK_THR_REK) - iqk->thermal_rek_en = true; - else - iqk->thermal_rek_en = false; - } -} - static void _rck(struct rtw89_dev *rtwdev, enum rtw89_rf_path path) { u32 rf_reg5, rck_val = 0; @@ -1616,7 +1591,6 @@ static void _iqk_init(struct rtw89_dev *rtwdev) iqk_info->iqk_sram_en = false; iqk_info->iqk_cfir_en = false; iqk_info->iqk_xym_en = false; - iqk_info->thermal_rek_en = false; iqk_info->iqk_times = 0x0; for (ch = 0; ch < RTW89_IQK_CHS_NR; ch++) { @@ -1645,7 +1619,6 @@ static void _doiqk(struct rtw89_dev *rtwdev, bool force, rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]==========IQK start!!!!!==========\n"); iqk_info->iqk_times++; - iqk_info->kcount = 0; iqk_info->version = RTW8852A_IQK_VER; rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]Test Ver 0x%x\n", iqk_info->version); @@ -3655,11 +3628,6 @@ void rtw8852a_iqk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx) rtw89_btc_ntfy_wl_rfk(rtwdev, phy_map, BTC_WRFKT_IQK, BTC_WRFK_STOP); } -void rtw8852a_iqk_track(struct rtw89_dev *rtwdev) -{ - _iqk_track(rtwdev); -} - void rtw8852a_rx_dck(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx, bool is_afe) { diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852a_rfk.h b/drivers/net/wireless/realtek/rtw89/rtw8852a_rfk.h index ea36553a76b7c8b7faefde4972b940a8ebdf99db..fa058ccc8616d5b5247ca7f6472bbe85c8ca0ae8 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852a_rfk.h +++ b/drivers/net/wireless/realtek/rtw89/rtw8852a_rfk.h @@ -10,7 +10,6 @@ void rtw8852a_rck(struct rtw89_dev *rtwdev); void rtw8852a_dack(struct rtw89_dev *rtwdev); void rtw8852a_iqk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx); -void rtw8852a_iqk_track(struct rtw89_dev *rtwdev); void rtw8852a_rx_dck(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx, bool is_afe); void rtw8852a_dpk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy); diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852b.c b/drivers/net/wireless/realtek/rtw89/rtw8852b.c index 6da1b603a9a95c096fc531b727ea080c84ebeaa2..718f993da62afbf515426a33402d28873f54e488 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852b.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852b.c @@ -2454,6 +2454,7 @@ static const struct rtw89_chip_ops rtw8852b_chip_ops = { .read_efuse = rtw8852b_read_efuse, .read_phycap = rtw8852b_read_phycap, .fem_setup = NULL, + .rfe_gpio = NULL, .rfk_init = rtw8852b_rfk_init, .rfk_channel = rtw8852b_rfk_channel, .rfk_band_changed = rtw8852b_rfk_band_changed, @@ -2471,6 +2472,7 @@ static const struct rtw89_chip_ops rtw8852b_chip_ops = { .set_txpwr_ul_tb_offset = rtw8852b_set_txpwr_ul_tb_offset, .pwr_on_func = rtw8852b_pwr_on_func, .pwr_off_func = rtw8852b_pwr_off_func, + .query_rxdesc = rtw89_core_query_rxdesc, .fill_txdesc = rtw89_core_fill_txdesc, .fill_txdesc_fwcmd = rtw89_core_fill_txdesc, .cfg_ctrl_path = rtw89_mac_cfg_ctrl_path, @@ -2506,6 +2508,7 @@ const struct rtw89_chip_info rtw8852b_chip_info = { .fw_format_max = RTW8852B_FW_FORMAT_MAX, .try_ce_fw = true, .fifo_size = 196608, + .small_fifo_size = true, .dle_scc_rsvd_size = 98304, .max_amsdu_limit = 3500, .dis_2g_40m_ul_ofdma = true, @@ -2522,6 +2525,7 @@ const struct rtw89_chip_info rtw8852b_chip_info = { .rf_table = {&rtw89_8852b_phy_radioa_table, &rtw89_8852b_phy_radiob_table,}, .nctl_table = &rtw89_8852b_phy_nctl_table, + .nctl_post_table = NULL, .byr_table = &rtw89_8852b_byr_table, .dflt_parms = &rtw89_8852b_dflt_parms, .rfe_parms_conf = NULL, @@ -2534,6 +2538,7 @@ const struct rtw89_chip_info rtw8852b_chip_info = { .support_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ), .support_bw160 = false, + .support_unii4 = true, .support_ul_tb_ctrl = true, .hw_sec_hdr = false, .rf_path_num = 2, @@ -2544,7 +2549,7 @@ const struct rtw89_chip_info rtw8852b_chip_info = { .scam_num = 128, .bacam_num = 2, .bacam_dynamic_num = 4, - .bacam_v1 = false, + .bacam_ver = RTW89_BACAM_V0, .sec_ctrl_efuse_size = 4, .physical_efuse_size = 1216, .logical_efuse_size = 2048, @@ -2598,6 +2603,7 @@ const struct rtw89_chip_info rtw8852b_chip_info = { #ifdef CONFIG_PM .wowlan_stub = &rtw_wowlan_stub_8852b, #endif + .xtal_info = NULL, }; EXPORT_SYMBOL(rtw8852b_chip_info); diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852b_rfk.c b/drivers/net/wireless/realtek/rtw89/rtw8852b_rfk.c index 722ae34b09c1fcc2efc993b0b6a51190993b6775..fa018e1f499b2efac6be6e1d67d50f2f3a1a282b 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852b_rfk.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852b_rfk.c @@ -1317,10 +1317,6 @@ static void _iqk_info_iqk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx, u32 tmp; bool flag; - iqk_info->thermal[path] = - ewma_thermal_read(&rtwdev->phystat.avg_thermal[path]); - iqk_info->thermal_rek_en = false; - flag = iqk_info->lok_cor_fail[0][path]; rtw89_phy_write32_mask(rtwdev, R_IQKINF, B_IQKINF_FCOR << (path * 4), flag); flag = iqk_info->lok_fin_fail[0][path]; @@ -1568,7 +1564,6 @@ static void _iqk_init(struct rtw89_dev *rtwdev) iqk_info->iqk_sram_en = false; iqk_info->iqk_cfir_en = false; iqk_info->iqk_xym_en = false; - iqk_info->thermal_rek_en = false; iqk_info->iqk_times = 0x0; for (idx = 0; idx < RTW89_IQK_CHS_NR; idx++) { @@ -1622,9 +1617,8 @@ static void _doiqk(struct rtw89_dev *rtwdev, bool force, rtw89_btc_ntfy_wl_rfk(rtwdev, phy_map, BTC_WRFKT_IQK, BTC_WRFK_ONESHOT_START); rtw89_debug(rtwdev, RTW89_DBG_RFK, - "[IQK]==========IQK strat!!!!!==========\n"); + "[IQK]==========IQK start!!!!!==========\n"); iqk_info->iqk_times++; - iqk_info->kcount = 0; iqk_info->version = RTW8852B_IQK_VER; rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]Test Ver 0x%x\n", iqk_info->version); diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852b_table.c b/drivers/net/wireless/realtek/rtw89/rtw8852b_table.c index 904cdb9e56fa7f2266f0133bff9fb9351d5de95d..17124d851a228e17eff2a66a437432f9f4d3e872 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852b_table.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852b_table.c @@ -14666,7 +14666,7 @@ static const s8 _txpwr_track_delta_swingidx_2g_cck_a_p[] = { 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; -const u8 rtw89_8852b_tx_shape[RTW89_BAND_MAX][RTW89_RS_TX_SHAPE_NUM] +const u8 rtw89_8852b_tx_shape[RTW89_BAND_NUM][RTW89_RS_TX_SHAPE_NUM] [RTW89_REGD_NUM] = { [0][0][RTW89_ACMA] = 0, [0][0][RTW89_CHILE] = 0, diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852b_table.h b/drivers/net/wireless/realtek/rtw89/rtw8852b_table.h index 5f4161496a589774fc176b5d8dd5e1698038c843..7ef217629f46fc44d72ac00acea3e9aa2b6ede82 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852b_table.h +++ b/drivers/net/wireless/realtek/rtw89/rtw8852b_table.h @@ -14,7 +14,7 @@ extern const struct rtw89_phy_table rtw89_8852b_phy_radiob_table; extern const struct rtw89_phy_table rtw89_8852b_phy_nctl_table; extern const struct rtw89_txpwr_table rtw89_8852b_byr_table; extern const struct rtw89_txpwr_track_cfg rtw89_8852b_trk_cfg; -extern const u8 rtw89_8852b_tx_shape[RTW89_BAND_MAX][RTW89_RS_TX_SHAPE_NUM] +extern const u8 rtw89_8852b_tx_shape[RTW89_BAND_NUM][RTW89_RS_TX_SHAPE_NUM] [RTW89_REGD_NUM]; extern const struct rtw89_rfe_parms rtw89_8852b_dflt_parms; diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852c.c b/drivers/net/wireless/realtek/rtw89/rtw8852c.c index ceb819a62efc9d9a88e6ae7f17523626824d3c56..9c7c9812d4f45685031ed6c0bf6c78f35a4e12be 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852c.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852c.c @@ -2762,6 +2762,7 @@ static const struct rtw89_chip_ops rtw8852c_chip_ops = { .read_efuse = rtw8852c_read_efuse, .read_phycap = rtw8852c_read_phycap, .fem_setup = NULL, + .rfe_gpio = NULL, .rfk_init = rtw8852c_rfk_init, .rfk_channel = rtw8852c_rfk_channel, .rfk_band_changed = rtw8852c_rfk_band_changed, @@ -2779,6 +2780,7 @@ static const struct rtw89_chip_ops rtw8852c_chip_ops = { .set_txpwr_ul_tb_offset = rtw8852c_set_txpwr_ul_tb_offset, .pwr_on_func = rtw8852c_pwr_on_func, .pwr_off_func = rtw8852c_pwr_off_func, + .query_rxdesc = rtw89_core_query_rxdesc, .fill_txdesc = rtw89_core_fill_txdesc_v1, .fill_txdesc_fwcmd = rtw89_core_fill_txdesc_fwcmd_v1, .cfg_ctrl_path = rtw89_mac_cfg_ctrl_path_v1, @@ -2805,6 +2807,7 @@ const struct rtw89_chip_info rtw8852c_chip_info = { .fw_format_max = RTW8852C_FW_FORMAT_MAX, .try_ce_fw = false, .fifo_size = 458752, + .small_fifo_size = false, .dle_scc_rsvd_size = 0, .max_amsdu_limit = 8000, .dis_2g_40m_ul_ofdma = false, @@ -2821,6 +2824,7 @@ const struct rtw89_chip_info rtw8852c_chip_info = { .rf_table = {&rtw89_8852c_phy_radiob_table, &rtw89_8852c_phy_radioa_table,}, .nctl_table = &rtw89_8852c_phy_nctl_table, + .nctl_post_table = NULL, .byr_table = &rtw89_8852c_byr_table, .dflt_parms = &rtw89_8852c_dflt_parms, .rfe_parms_conf = NULL, @@ -2834,6 +2838,7 @@ const struct rtw89_chip_info rtw8852c_chip_info = { BIT(NL80211_BAND_5GHZ) | BIT(NL80211_BAND_6GHZ), .support_bw160 = true, + .support_unii4 = true, .support_ul_tb_ctrl = false, .hw_sec_hdr = true, .rf_path_num = 2, @@ -2844,7 +2849,7 @@ const struct rtw89_chip_info rtw8852c_chip_info = { .scam_num = 128, .bacam_num = 8, .bacam_dynamic_num = 8, - .bacam_v1 = true, + .bacam_ver = RTW89_BACAM_V0_EXT, .sec_ctrl_efuse_size = 4, .physical_efuse_size = 1216, .logical_efuse_size = 2048, @@ -2897,6 +2902,7 @@ const struct rtw89_chip_info rtw8852c_chip_info = { #ifdef CONFIG_PM .wowlan_stub = &rtw_wowlan_stub_8852c, #endif + .xtal_info = NULL, }; EXPORT_SYMBOL(rtw8852c_chip_info); diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.c b/drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.c index 2c0bc3a4ab3b153b94d936128fb127417637d7be..de7714f871d588955d6273ca522e77f9a440effa 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.c @@ -1261,11 +1261,8 @@ static void _iqk_info_iqk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx, u32 tmp; bool flag; - iqk_info->thermal[path] = - ewma_thermal_read(&rtwdev->phystat.avg_thermal[path]); - iqk_info->thermal_rek_en = false; - rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]S%d_thermal = %d\n", path, - iqk_info->thermal[path]); + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]S%d_thermal = %lu\n", path, + ewma_thermal_read(&rtwdev->phystat.avg_thermal[path])); rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]S%d_LOK_COR_fail= %d\n", path, iqk_info->lok_cor_fail[0][path]); rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]S%d_LOK_FIN_fail= %d\n", path, @@ -1502,7 +1499,6 @@ static void _iqk_init(struct rtw89_dev *rtwdev) iqk_info->iqk_sram_en = false; iqk_info->iqk_cfir_en = false; iqk_info->iqk_xym_en = false; - iqk_info->thermal_rek_en = false; iqk_info->iqk_times = 0x0; for (ch = 0; ch < RTW89_IQK_CHS_NR; ch++) { @@ -1529,9 +1525,8 @@ static void _doiqk(struct rtw89_dev *rtwdev, bool force, rtw89_btc_ntfy_wl_rfk(rtwdev, phy_map, BTC_WRFKT_IQK, BTC_WRFK_ONESHOT_START); rtw89_debug(rtwdev, RTW89_DBG_RFK, - "[IQK]==========IQK strat!!!!!==========\n"); + "[IQK]==========IQK start!!!!!==========\n"); iqk_info->iqk_times++; - iqk_info->kcount = 0; iqk_info->version = RTW8852C_IQK_VER; rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]Test Ver 0x%x\n", iqk_info->version); diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852c_table.c b/drivers/net/wireless/realtek/rtw89/rtw8852c_table.c index 7011e5a6f8fdac327bc05ac3fda8303ddd1db7eb..4b272fdf1fd7a412ec2b082e25751a4d250a2253 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852c_table.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852c_table.c @@ -2551,19 +2551,27 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0xF0040001, 0x0000000A}, {0xF0050001, 0x0000000B}, {0xF0070001, 0x0000000C}, - {0xF0320001, 0x0000000D}, - {0xF0330001, 0x0000000E}, - {0xF0340001, 0x0000000F}, - {0xF0350001, 0x00000010}, - {0xF0360001, 0x00000011}, - {0xF03F0001, 0x00000012}, - {0xF0400001, 0x00000013}, + {0xF0150001, 0x0000000D}, + {0xF0160001, 0x0000000E}, + {0xF0320001, 0x0000000F}, + {0xF0330001, 0x00000010}, + {0xF0340001, 0x00000011}, + {0xF0350001, 0x00000012}, + {0xF0360001, 0x00000013}, + {0xF03F0001, 0x00000014}, + {0xF0400001, 0x00000015}, {0x005, 0x00000000}, {0x10005, 0x00000000}, {0x000, 0x00030001}, {0x10000, 0x00030000}, {0x018, 0x00011124}, {0x10018, 0x00011124}, + {0x0A3, 0x000B9204}, + {0x0AD, 0x00091E0F}, + {0x05D, 0x00001012}, + {0x05C, 0x00061C5C}, + {0x062, 0x00055220}, + {0x0D3, 0x00000103}, {0x0EF, 0x00080000}, {0x033, 0x00000001}, {0x03E, 0x00000620}, @@ -2636,6 +2644,12 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x067, 0x0000D300}, {0x0DA, 0x000D4000}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x067, 0x0000D300}, + {0x0DA, 0x000D4000}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x067, 0x0000D300}, + {0x0DA, 0x000D4000}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x067, 0x0000D300}, {0x0DA, 0x000D4000}, @@ -2716,6 +2730,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x000000CC}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000000CC}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000000CC}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000000CC}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000000CC}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -2760,6 +2778,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x000000C4}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000000C4}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000000C4}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000000C4}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000000C4}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -2804,6 +2826,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x000000BC}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000000BC}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000000BC}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000000BC}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000000BC}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -2848,6 +2874,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x000000B4}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000000B4}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000000B4}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000000B4}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000000B4}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -2892,6 +2922,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x000000AC}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000000AC}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000000AC}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000000AC}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000000AC}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -2936,6 +2970,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x000000A4}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000000A4}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000000A4}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000000A4}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000000A4}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -2980,6 +3018,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x0000009C}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000009C}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000009C}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000009C}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000009C}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -3024,6 +3066,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000094}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000094}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000094}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000094}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000094}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -3068,6 +3114,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x0000008C}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000008C}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000008C}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000008C}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000008C}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -3112,6 +3162,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000084}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000084}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000084}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000084}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000084}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -3156,6 +3210,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x000000BC}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000000BC}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000000BC}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000000BC}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000000BC}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -3200,6 +3258,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x000000B4}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000000B4}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000000B4}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000000B4}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000000B4}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -3244,6 +3306,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x000000AC}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000000AC}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000000AC}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000000AC}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000000AC}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -3288,6 +3354,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x000000A4}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000000A4}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000000A4}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000000A4}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000000A4}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -3332,6 +3402,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x0000009C}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000009C}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000009C}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000009C}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000009C}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -3376,6 +3450,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000094}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000094}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000094}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000094}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000094}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -3420,6 +3498,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x0000008C}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000008C}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000008C}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000008C}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000008C}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -3464,6 +3546,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000084}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000084}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000084}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000084}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000084}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -3508,6 +3594,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x0000003C}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000003C}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000003C}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000003C}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000003C}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -3552,6 +3642,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000034}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000034}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000034}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000034}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000034}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -3596,6 +3690,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x0000002C}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000002C}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000002C}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000002C}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000002C}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -3640,6 +3738,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000024}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000024}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000024}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000024}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000024}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -3684,6 +3786,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x0000001C}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000001C}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000001C}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000001C}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000001C}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -3728,6 +3834,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000014}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000014}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000014}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000014}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000014}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -3772,6 +3882,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x0000000C}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000000C}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000000C}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000000C}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000000C}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -3816,6 +3930,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000004}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000004}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000004}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000004}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000004}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -3873,6 +3991,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x08F, 0x000D1352}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x08F, 0x000D1352}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x08F, 0x000D1352}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x08F, 0x000D1352}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x08F, 0x000D1352}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -3936,6 +4058,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000007}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000007}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000017}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000017}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000007}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -4472,6 +4598,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x0000EFFF}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000EFFF}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000EFFF}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000EFFF}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000EFFF}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -4810,6 +4940,32 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x030, 0x00050112}, {0x030, 0x00058101}, {0x030, 0x00060001}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x000085ED}, + {0x030, 0x000105CC}, + {0x030, 0x000184AA}, + {0x030, 0x00020388}, + {0x030, 0x00028377}, + {0x030, 0x00030377}, + {0x030, 0x00038255}, + {0x030, 0x00040244}, + {0x030, 0x00048133}, + {0x030, 0x00050112}, + {0x030, 0x00058101}, + {0x030, 0x00060001}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x000085ED}, + {0x030, 0x000105CC}, + {0x030, 0x000184AA}, + {0x030, 0x00020388}, + {0x030, 0x00028377}, + {0x030, 0x00030377}, + {0x030, 0x00038255}, + {0x030, 0x00040244}, + {0x030, 0x00048133}, + {0x030, 0x00050112}, + {0x030, 0x00058101}, + {0x030, 0x00060001}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x030, 0x000085ED}, {0x030, 0x000105CC}, @@ -5157,6 +5313,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x030, 0x000300FF}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x030, 0x000300FF}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x000300FF}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x000300FF}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x030, 0x000300FF}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -5178,152 +5338,632 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x0EF, 0x00000000}, {0x06E, 0x00077A18}, {0x06D, 0x00000C31}, + {0x80010000, 0x00000000}, {0x40000000, 0x00000000}, {0x06A, 0x000E0F8A}, {0x06B, 0x000018A0}, {0x06F, 0x000F81FC}, {0x05E, 0x0000001F}, - {0x0EF, 0x00000200}, - {0x030, 0x0003D407}, - {0x030, 0x00035A87}, - {0x030, 0x0002CF07}, - {0x030, 0x00024F07}, - {0x030, 0x0001CF07}, - {0x030, 0x00014F07}, - {0x030, 0x0000CF07}, - {0x030, 0x00004F07}, - {0x0EF, 0x00000000}, - {0x0EB, 0x00080000}, - {0x030, 0x00008038}, - {0x030, 0x00010038}, - {0x030, 0x00018038}, - {0x030, 0x00020038}, - {0x030, 0x00028038}, - {0x030, 0x00030038}, - {0x030, 0x0003803C}, - {0x030, 0x0004003C}, - {0x030, 0x0004803C}, - {0x030, 0x0005003C}, - {0x030, 0x0005803C}, - {0x030, 0x0006003C}, - {0x030, 0x0006803C}, - {0x030, 0x0007003C}, - {0x0EB, 0x00000000}, - {0x094, 0x000000FC}, - {0x80010000, 0x00000000}, {0x40000000, 0x00000000}, - {0x095, 0x00000000}, {0x90020000, 0x00000000}, {0x40000000, 0x00000000}, - {0x095, 0x00000000}, + {0x06A, 0x000E0F8A}, + {0x06B, 0x000018A0}, + {0x06F, 0x000F81FC}, + {0x05E, 0x0000001F}, {0x90320000, 0x00000000}, {0x40000000, 0x00000000}, - {0x095, 0x00000000}, + {0x06A, 0x000E0F8A}, + {0x06B, 0x000018A0}, + {0x06F, 0x000F81FC}, + {0x05E, 0x0000001F}, {0x90330000, 0x00000000}, {0x40000000, 0x00000000}, - {0x095, 0x00000000}, + {0x06A, 0x000E0F8A}, + {0x06B, 0x000018A0}, + {0x06F, 0x000F81FC}, + {0x05E, 0x0000001F}, {0x90340000, 0x00000000}, {0x40000000, 0x00000000}, - {0x095, 0x00000000}, + {0x06A, 0x000E0F8A}, + {0x06B, 0x000018A0}, + {0x06F, 0x000F81FC}, + {0x05E, 0x0000001F}, {0x90350000, 0x00000000}, {0x40000000, 0x00000000}, - {0x095, 0x00000000}, + {0x06A, 0x000E0F8A}, + {0x06B, 0x000018A0}, + {0x06F, 0x000F81FC}, + {0x05E, 0x0000001F}, {0x90360000, 0x00000000}, {0x40000000, 0x00000000}, - {0x095, 0x00000000}, + {0x06A, 0x000E0F8A}, + {0x06B, 0x000018A0}, + {0x06F, 0x000F81FC}, + {0x05E, 0x0000001F}, {0x90010001, 0x00000000}, {0x40000000, 0x00000000}, - {0x095, 0x00000008}, + {0x06A, 0x000E0F8A}, + {0x06B, 0x000018A0}, + {0x06F, 0x000F81FC}, + {0x05E, 0x0000001F}, {0x90020001, 0x00000000}, {0x40000000, 0x00000000}, - {0x095, 0x00000008}, + {0x06A, 0x000E0F8A}, + {0x06B, 0x000018A0}, + {0x06F, 0x000F81FC}, + {0x05E, 0x0000001F}, {0x90030001, 0x00000000}, {0x40000000, 0x00000000}, - {0x095, 0x00000008}, + {0x06A, 0x000E0F8A}, + {0x06B, 0x000018A0}, + {0x06F, 0x000F81FC}, + {0x05E, 0x0000001F}, {0x90040001, 0x00000000}, {0x40000000, 0x00000000}, - {0x095, 0x00000008}, + {0x06A, 0x000E0F8A}, + {0x06B, 0x000018A0}, + {0x06F, 0x000F81FC}, + {0x05E, 0x0000001F}, {0x90050001, 0x00000000}, {0x40000000, 0x00000000}, - {0x095, 0x00000008}, + {0x06A, 0x000E0F8A}, + {0x06B, 0x000018A0}, + {0x06F, 0x000F81FC}, + {0x05E, 0x0000001F}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, - {0x095, 0x00000008}, + {0x06A, 0x000E0F8A}, + {0x06B, 0x000018A0}, + {0x06F, 0x000F81FC}, + {0x05E, 0x0000001F}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x06A, 0x000E0380}, + {0x06B, 0x00003CA0}, + {0x06F, 0x000C01FC}, + {0x05E, 0x0000001F}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x06A, 0x000E0380}, + {0x06B, 0x00003CA0}, + {0x06F, 0x000C01FC}, + {0x05E, 0x0000001F}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, - {0x095, 0x00000008}, + {0x06A, 0x000E0F8A}, + {0x06B, 0x000018A0}, + {0x06F, 0x000F81FC}, + {0x05E, 0x0000001F}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x095, 0x00000008}, + {0x06A, 0x000E0F8A}, + {0x06B, 0x000018A0}, + {0x06F, 0x000F81FC}, + {0x05E, 0x0000001F}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x095, 0x00000008}, + {0x06A, 0x000E0F8A}, + {0x06B, 0x000018A0}, + {0x06F, 0x000F81FC}, + {0x05E, 0x0000001F}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x095, 0x00000008}, + {0x06A, 0x000E0F8A}, + {0x06B, 0x000018A0}, + {0x06F, 0x000F81FC}, + {0x05E, 0x0000001F}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x095, 0x00000008}, + {0x06A, 0x000E0F8A}, + {0x06B, 0x000018A0}, + {0x06F, 0x000F81FC}, + {0x05E, 0x0000001F}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x095, 0x00000008}, + {0x06A, 0x000E0F8A}, + {0x06B, 0x000018A0}, + {0x06F, 0x000F81FC}, + {0x05E, 0x0000001F}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x095, 0x00000008}, + {0x06A, 0x000E0F8A}, + {0x06B, 0x000018A0}, + {0x06F, 0x000F81FC}, + {0x05E, 0x0000001F}, {0xA0000000, 0x00000000}, - {0x095, 0x00000000}, + {0x06A, 0x000E0F8A}, + {0x06B, 0x000018A0}, + {0x06F, 0x000F81FC}, + {0x05E, 0x0000001F}, {0xB0000000, 0x00000000}, - {0x0EE, 0x00001000}, - {0x033, 0x00000020}, + {0x0EF, 0x00000200}, {0x80010000, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x030, 0x0003D407}, + {0x030, 0x00035A87}, + {0x030, 0x0002CF07}, + {0x030, 0x00024F07}, + {0x030, 0x0001CF07}, + {0x030, 0x00014F07}, + {0x030, 0x0000CF07}, + {0x030, 0x00004F07}, {0x90020000, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x030, 0x0003D407}, + {0x030, 0x00035A87}, + {0x030, 0x0002CF07}, + {0x030, 0x00024F07}, + {0x030, 0x0001CF07}, + {0x030, 0x00014F07}, + {0x030, 0x0000CF07}, + {0x030, 0x00004F07}, {0x90320000, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x030, 0x0003D407}, + {0x030, 0x00035A87}, + {0x030, 0x0002CF07}, + {0x030, 0x00024F07}, + {0x030, 0x0001CF07}, + {0x030, 0x00014F07}, + {0x030, 0x0000CF07}, + {0x030, 0x00004F07}, {0x90330000, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, - {0x90340000, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, - {0x90350000, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, - {0x90360000, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x030, 0x0003D407}, + {0x030, 0x00035A87}, + {0x030, 0x0002CF07}, + {0x030, 0x00024F07}, + {0x030, 0x0001CF07}, + {0x030, 0x00014F07}, + {0x030, 0x0000CF07}, + {0x030, 0x00004F07}, + {0x90340000, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x0003D407}, + {0x030, 0x00035A87}, + {0x030, 0x0002CF07}, + {0x030, 0x00024F07}, + {0x030, 0x0001CF07}, + {0x030, 0x00014F07}, + {0x030, 0x0000CF07}, + {0x030, 0x00004F07}, + {0x90350000, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x0003D407}, + {0x030, 0x00035A87}, + {0x030, 0x0002CF07}, + {0x030, 0x00024F07}, + {0x030, 0x0001CF07}, + {0x030, 0x00014F07}, + {0x030, 0x0000CF07}, + {0x030, 0x00004F07}, + {0x90360000, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x0003D407}, + {0x030, 0x00035A87}, + {0x030, 0x0002CF07}, + {0x030, 0x00024F07}, + {0x030, 0x0001CF07}, + {0x030, 0x00014F07}, + {0x030, 0x0000CF07}, + {0x030, 0x00004F07}, {0x90010001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000152}, + {0x030, 0x0003D407}, + {0x030, 0x00035A87}, + {0x030, 0x0002CF07}, + {0x030, 0x00024F07}, + {0x030, 0x0001CF07}, + {0x030, 0x00014F07}, + {0x030, 0x0000CF07}, + {0x030, 0x00004F07}, {0x90020001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000152}, + {0x030, 0x0003D407}, + {0x030, 0x00035A87}, + {0x030, 0x0002CF07}, + {0x030, 0x00024F07}, + {0x030, 0x0001CF07}, + {0x030, 0x00014F07}, + {0x030, 0x0000CF07}, + {0x030, 0x00004F07}, {0x90030001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000152}, + {0x030, 0x0003D407}, + {0x030, 0x00035A87}, + {0x030, 0x0002CF07}, + {0x030, 0x00024F07}, + {0x030, 0x0001CF07}, + {0x030, 0x00014F07}, + {0x030, 0x0000CF07}, + {0x030, 0x00004F07}, {0x90040001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000152}, + {0x030, 0x0003D407}, + {0x030, 0x00035A87}, + {0x030, 0x0002CF07}, + {0x030, 0x00024F07}, + {0x030, 0x0001CF07}, + {0x030, 0x00014F07}, + {0x030, 0x0000CF07}, + {0x030, 0x00004F07}, {0x90050001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000152}, + {0x030, 0x0003D407}, + {0x030, 0x00035A87}, + {0x030, 0x0002CF07}, + {0x030, 0x00024F07}, + {0x030, 0x0001CF07}, + {0x030, 0x00014F07}, + {0x030, 0x0000CF07}, + {0x030, 0x00004F07}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000152}, + {0x030, 0x0003D407}, + {0x030, 0x00035A87}, + {0x030, 0x0002CF07}, + {0x030, 0x00024F07}, + {0x030, 0x0001CF07}, + {0x030, 0x00014F07}, + {0x030, 0x0000CF07}, + {0x030, 0x00004F07}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x0003E207}, + {0x030, 0x0003E207}, + {0x030, 0x0003E207}, + {0x030, 0x0003E207}, + {0x030, 0x0003E207}, + {0x030, 0x0003E207}, + {0x030, 0x0003E207}, + {0x030, 0x0003E207}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x0003E207}, + {0x030, 0x0003E207}, + {0x030, 0x0003E207}, + {0x030, 0x0003E207}, + {0x030, 0x0003E207}, + {0x030, 0x0003E207}, + {0x030, 0x0003E207}, + {0x030, 0x0003E207}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000152}, + {0x030, 0x0003D407}, + {0x030, 0x00035A87}, + {0x030, 0x0002CF07}, + {0x030, 0x00024F07}, + {0x030, 0x0001CF07}, + {0x030, 0x00014F07}, + {0x030, 0x0000CF07}, + {0x030, 0x00004F07}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x030, 0x0003D407}, + {0x030, 0x00035A87}, + {0x030, 0x0002CF07}, + {0x030, 0x00024F07}, + {0x030, 0x0001CF07}, + {0x030, 0x00014F07}, + {0x030, 0x0000CF07}, + {0x030, 0x00004F07}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x030, 0x0003D407}, + {0x030, 0x00035A87}, + {0x030, 0x0002CF07}, + {0x030, 0x00024F07}, + {0x030, 0x0001CF07}, + {0x030, 0x00014F07}, + {0x030, 0x0000CF07}, + {0x030, 0x00004F07}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x030, 0x0003D407}, + {0x030, 0x00035A87}, + {0x030, 0x0002CF07}, + {0x030, 0x00024F07}, + {0x030, 0x0001CF07}, + {0x030, 0x00014F07}, + {0x030, 0x0000CF07}, + {0x030, 0x00004F07}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x030, 0x0003D407}, + {0x030, 0x00035A87}, + {0x030, 0x0002CF07}, + {0x030, 0x00024F07}, + {0x030, 0x0001CF07}, + {0x030, 0x00014F07}, + {0x030, 0x0000CF07}, + {0x030, 0x00004F07}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x030, 0x0003D407}, + {0x030, 0x00035A87}, + {0x030, 0x0002CF07}, + {0x030, 0x00024F07}, + {0x030, 0x0001CF07}, + {0x030, 0x00014F07}, + {0x030, 0x0000CF07}, + {0x030, 0x00004F07}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x030, 0x0003D407}, + {0x030, 0x00035A87}, + {0x030, 0x0002CF07}, + {0x030, 0x00024F07}, + {0x030, 0x0001CF07}, + {0x030, 0x00014F07}, + {0x030, 0x0000CF07}, + {0x030, 0x00004F07}, {0xA0000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x030, 0x0003D407}, + {0x030, 0x00035A87}, + {0x030, 0x0002CF07}, + {0x030, 0x00024F07}, + {0x030, 0x0001CF07}, + {0x030, 0x00014F07}, + {0x030, 0x0000CF07}, + {0x030, 0x00004F07}, {0xB0000000, 0x00000000}, - {0x033, 0x00000024}, + {0x0EF, 0x00000000}, + {0x0EB, 0x00080000}, {0x80010000, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x030, 0x00008038}, + {0x030, 0x00010038}, + {0x030, 0x00018038}, + {0x030, 0x00020038}, + {0x030, 0x00028038}, + {0x030, 0x00030038}, {0x90020000, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x030, 0x00008038}, + {0x030, 0x00010038}, + {0x030, 0x00018038}, + {0x030, 0x00020038}, + {0x030, 0x00028038}, + {0x030, 0x00030038}, {0x90320000, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x030, 0x00008038}, + {0x030, 0x00010038}, + {0x030, 0x00018038}, + {0x030, 0x00020038}, + {0x030, 0x00028038}, + {0x030, 0x00030038}, {0x90330000, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x030, 0x00008038}, + {0x030, 0x00010038}, + {0x030, 0x00018038}, + {0x030, 0x00020038}, + {0x030, 0x00028038}, + {0x030, 0x00030038}, {0x90340000, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x030, 0x00008038}, + {0x030, 0x00010038}, + {0x030, 0x00018038}, + {0x030, 0x00020038}, + {0x030, 0x00028038}, + {0x030, 0x00030038}, {0x90350000, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x030, 0x00008038}, + {0x030, 0x00010038}, + {0x030, 0x00018038}, + {0x030, 0x00020038}, + {0x030, 0x00028038}, + {0x030, 0x00030038}, {0x90360000, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x030, 0x00008038}, + {0x030, 0x00010038}, + {0x030, 0x00018038}, + {0x030, 0x00020038}, + {0x030, 0x00028038}, + {0x030, 0x00030038}, {0x90010001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000015A}, + {0x030, 0x00008038}, + {0x030, 0x00010038}, + {0x030, 0x00018038}, + {0x030, 0x00020038}, + {0x030, 0x00028038}, + {0x030, 0x00030038}, {0x90020001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000015A}, + {0x030, 0x00008038}, + {0x030, 0x00010038}, + {0x030, 0x00018038}, + {0x030, 0x00020038}, + {0x030, 0x00028038}, + {0x030, 0x00030038}, {0x90030001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000015A}, + {0x030, 0x00008038}, + {0x030, 0x00010038}, + {0x030, 0x00018038}, + {0x030, 0x00020038}, + {0x030, 0x00028038}, + {0x030, 0x00030038}, {0x90040001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000015A}, + {0x030, 0x00008038}, + {0x030, 0x00010038}, + {0x030, 0x00018038}, + {0x030, 0x00020038}, + {0x030, 0x00028038}, + {0x030, 0x00030038}, {0x90050001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000015A}, + {0x030, 0x00008038}, + {0x030, 0x00010038}, + {0x030, 0x00018038}, + {0x030, 0x00020038}, + {0x030, 0x00028038}, + {0x030, 0x00030038}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000015A}, + {0x030, 0x00008038}, + {0x030, 0x00010038}, + {0x030, 0x00018038}, + {0x030, 0x00020038}, + {0x030, 0x00028038}, + {0x030, 0x00030038}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x0000803C}, + {0x030, 0x0001003C}, + {0x030, 0x0001803C}, + {0x030, 0x0002003C}, + {0x030, 0x0002803C}, + {0x030, 0x0003003C}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x0000803C}, + {0x030, 0x0001003C}, + {0x030, 0x0001803C}, + {0x030, 0x0002003C}, + {0x030, 0x0002803C}, + {0x030, 0x0003003C}, + {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x00008038}, + {0x030, 0x00010038}, + {0x030, 0x00018038}, + {0x030, 0x00020038}, + {0x030, 0x00028038}, + {0x030, 0x00030038}, + {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x00008038}, + {0x030, 0x00010038}, + {0x030, 0x00018038}, + {0x030, 0x00020038}, + {0x030, 0x00028038}, + {0x030, 0x00030038}, + {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x00008038}, + {0x030, 0x00010038}, + {0x030, 0x00018038}, + {0x030, 0x00020038}, + {0x030, 0x00028038}, + {0x030, 0x00030038}, + {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x00008038}, + {0x030, 0x00010038}, + {0x030, 0x00018038}, + {0x030, 0x00020038}, + {0x030, 0x00028038}, + {0x030, 0x00030038}, + {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x00008038}, + {0x030, 0x00010038}, + {0x030, 0x00018038}, + {0x030, 0x00020038}, + {0x030, 0x00028038}, + {0x030, 0x00030038}, + {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x00008038}, + {0x030, 0x00010038}, + {0x030, 0x00018038}, + {0x030, 0x00020038}, + {0x030, 0x00028038}, + {0x030, 0x00030038}, + {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x00008038}, + {0x030, 0x00010038}, + {0x030, 0x00018038}, + {0x030, 0x00020038}, + {0x030, 0x00028038}, + {0x030, 0x00030038}, + {0xA0000000, 0x00000000}, + {0x030, 0x00008038}, + {0x030, 0x00010038}, + {0x030, 0x00018038}, + {0x030, 0x00020038}, + {0x030, 0x00028038}, + {0x030, 0x00030038}, + {0xB0000000, 0x00000000}, + {0x030, 0x0003803C}, + {0x030, 0x0004003C}, + {0x030, 0x0004803C}, + {0x030, 0x0005003C}, + {0x030, 0x0005803C}, + {0x030, 0x0006003C}, + {0x030, 0x0006803C}, + {0x030, 0x0007003C}, + {0x0EB, 0x00000000}, + {0x094, 0x000000FC}, + {0x80010000, 0x00000000}, {0x40000000, 0x00000000}, + {0x095, 0x00000000}, + {0x90020000, 0x00000000}, {0x40000000, 0x00000000}, + {0x095, 0x00000000}, + {0x90320000, 0x00000000}, {0x40000000, 0x00000000}, + {0x095, 0x00000000}, + {0x90330000, 0x00000000}, {0x40000000, 0x00000000}, + {0x095, 0x00000000}, + {0x90340000, 0x00000000}, {0x40000000, 0x00000000}, + {0x095, 0x00000000}, + {0x90350000, 0x00000000}, {0x40000000, 0x00000000}, + {0x095, 0x00000000}, + {0x90360000, 0x00000000}, {0x40000000, 0x00000000}, + {0x095, 0x00000000}, + {0x90010001, 0x00000000}, {0x40000000, 0x00000000}, + {0x095, 0x00000008}, + {0x90020001, 0x00000000}, {0x40000000, 0x00000000}, + {0x095, 0x00000008}, + {0x90030001, 0x00000000}, {0x40000000, 0x00000000}, + {0x095, 0x00000008}, + {0x90040001, 0x00000000}, {0x40000000, 0x00000000}, + {0x095, 0x00000008}, + {0x90050001, 0x00000000}, {0x40000000, 0x00000000}, + {0x095, 0x00000008}, + {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, + {0x095, 0x00000008}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x095, 0x00000008}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x095, 0x00000008}, + {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, + {0x095, 0x00000008}, + {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, + {0x095, 0x00000008}, + {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, + {0x095, 0x00000008}, + {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, + {0x095, 0x00000008}, + {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, + {0x095, 0x00000008}, + {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, + {0x095, 0x00000008}, + {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, + {0x095, 0x00000008}, + {0xA0000000, 0x00000000}, + {0x095, 0x00000000}, + {0xB0000000, 0x00000000}, + {0x0EE, 0x00001000}, + {0x033, 0x00000020}, + {0x80010000, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000052}, + {0x90020000, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000052}, + {0x90320000, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000052}, + {0x90330000, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000052}, + {0x90340000, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000052}, + {0x90350000, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000052}, + {0x90360000, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000052}, + {0x90010001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000152}, + {0x90020001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000152}, + {0x90030001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000152}, + {0x90040001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000152}, + {0x90050001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000152}, + {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000152}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000152}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000152}, + {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000152}, + {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000052}, + {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000052}, + {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000052}, + {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000052}, + {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000052}, + {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000052}, + {0xA0000000, 0x00000000}, + {0x03F, 0x00000052}, + {0xB0000000, 0x00000000}, + {0x033, 0x00000024}, + {0x80010000, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000005A}, + {0x90020000, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000005A}, + {0x90320000, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000005A}, + {0x90330000, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000005A}, + {0x90340000, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000005A}, + {0x90350000, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000005A}, + {0x90360000, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000005A}, + {0x90010001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000015A}, + {0x90020001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000015A}, + {0x90030001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000015A}, + {0x90040001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000015A}, + {0x90050001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000015A}, + {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000015A}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000015A}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000015A}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000015A}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -5368,6 +6008,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x0000019C}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000019C}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000019C}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000019C}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000019C}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -5412,6 +6056,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x000001A4}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001A4}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001A4}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001A4}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001A4}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -5456,6 +6104,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x000001E6}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001E6}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001E6}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001E6}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001E6}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -5500,6 +6152,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x000002E6}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E6}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E6}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E6}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E6}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -5548,6 +6204,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000152}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000152}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000152}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000152}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000152}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -5592,6 +6252,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x0000015A}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000015A}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000015A}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000015A}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000015A}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -5636,6 +6300,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x0000019C}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000019C}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000019C}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000019C}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000019C}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -5680,6 +6348,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x000001A4}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001A4}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001A4}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001A4}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001A4}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -5724,6 +6396,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x000001E6}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001E6}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001E6}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001E6}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001E6}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -5768,6 +6444,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x000002E6}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E6}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E6}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E6}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E6}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -5812,6 +6492,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x000002E7}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E7}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E7}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E7}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E7}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -5856,6 +6540,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x000003E7}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000003E7}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000003E7}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000003E7}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000003E7}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -5900,6 +6588,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000152}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000152}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000152}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000152}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000152}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -5944,6 +6636,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x0000015A}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000015A}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000015A}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000015A}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000015A}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -5988,6 +6684,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x0000019C}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000019C}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000019C}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000019C}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000019C}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -6032,6 +6732,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x000001A4}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001A4}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001A4}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001A4}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001A4}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -6076,6 +6780,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x000001E6}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001E6}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001E6}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001E6}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001E6}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -6120,6 +6828,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x000002E6}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E6}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E6}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E6}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E6}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -6164,6 +6876,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x000002E7}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E7}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E7}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E7}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E7}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -6208,6 +6924,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x000003E7}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000003E7}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000003E7}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000003E7}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000003E7}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -6252,20 +6972,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000152}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000152}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000152}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000152}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000152}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0xA0000000, 0x00000000}, {0x03F, 0x00000052}, {0xB0000000, 0x00000000}, @@ -6296,20 +7020,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x0000015A}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000015A}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000015A}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000015A}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000015A}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0xA0000000, 0x00000000}, {0x03F, 0x0000005A}, {0xB0000000, 0x00000000}, @@ -6340,20 +7068,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x0000019C}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000019C}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000019C}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000019C}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000019C}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0xA0000000, 0x00000000}, {0x03F, 0x0000009C}, {0xB0000000, 0x00000000}, @@ -6384,20 +7116,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x000001A4}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001A4}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001A4}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001A4}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001A4}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0xA0000000, 0x00000000}, {0x03F, 0x0000019C}, {0xB0000000, 0x00000000}, @@ -6428,20 +7164,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x000001E6}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001E6}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001E6}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001E6}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001E6}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0xA0000000, 0x00000000}, {0x03F, 0x000001A4}, {0xB0000000, 0x00000000}, @@ -6472,20 +7212,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x000002E6}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E6}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E6}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E6}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E6}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0xA0000000, 0x00000000}, {0x03F, 0x000001E6}, {0xB0000000, 0x00000000}, @@ -6516,20 +7260,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x000002E7}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E7}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E7}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E7}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E7}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000002E6}, + {0x03F, 0x000002E7}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000002E6}, + {0x03F, 0x000002E7}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000002E6}, + {0x03F, 0x000002E7}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000002E6}, + {0x03F, 0x000002E7}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000002E6}, + {0x03F, 0x000002E7}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000002E6}, + {0x03F, 0x000002E7}, {0xA0000000, 0x00000000}, {0x03F, 0x000002E6}, {0xB0000000, 0x00000000}, @@ -6560,20 +7308,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x000003E7}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000003E7}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000003E7}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000003E7}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000003E7}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000003E6}, + {0x03F, 0x000003E7}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000003E6}, + {0x03F, 0x000003E7}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000003E6}, + {0x03F, 0x000003E7}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000003E6}, + {0x03F, 0x000003E7}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000003E6}, + {0x03F, 0x000003E7}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000003E6}, + {0x03F, 0x000003E7}, {0xA0000000, 0x00000000}, {0x03F, 0x000003E6}, {0xB0000000, 0x00000000}, @@ -6604,20 +7356,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000152}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000152}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000152}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000152}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000152}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0xA0000000, 0x00000000}, {0x03F, 0x00000052}, {0xB0000000, 0x00000000}, @@ -6648,20 +7404,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x0000015A}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000015A}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000015A}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000015A}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000015A}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0xA0000000, 0x00000000}, {0x03F, 0x0000005A}, {0xB0000000, 0x00000000}, @@ -6692,20 +7452,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x0000019C}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000019C}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000019C}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000019C}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000019C}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0xA0000000, 0x00000000}, {0x03F, 0x0000009C}, {0xB0000000, 0x00000000}, @@ -6736,20 +7500,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x000001A4}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001A4}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001A4}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001A4}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001A4}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0xA0000000, 0x00000000}, {0x03F, 0x0000019C}, {0xB0000000, 0x00000000}, @@ -6780,20 +7548,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x000001E6}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001E6}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001E6}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001E6}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001E6}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0xA0000000, 0x00000000}, {0x03F, 0x000001A4}, {0xB0000000, 0x00000000}, @@ -6824,20 +7596,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x000002E6}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E6}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E6}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E6}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E6}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0xA0000000, 0x00000000}, {0x03F, 0x000001E6}, {0xB0000000, 0x00000000}, @@ -6868,20 +7644,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x000002E7}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E7}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E7}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E7}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E7}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000002E6}, + {0x03F, 0x000002E7}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000002E6}, + {0x03F, 0x000002E7}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000002E6}, + {0x03F, 0x000002E7}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000002E6}, + {0x03F, 0x000002E7}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000002E6}, + {0x03F, 0x000002E7}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000002E6}, + {0x03F, 0x000002E7}, {0xA0000000, 0x00000000}, {0x03F, 0x000002E6}, {0xB0000000, 0x00000000}, @@ -6912,20 +7692,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x000003E7}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000003E7}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000003E7}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000003E7}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000003E7}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000003E6}, + {0x03F, 0x000003E7}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000003E6}, + {0x03F, 0x000003E7}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000003E6}, + {0x03F, 0x000003E7}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000003E6}, + {0x03F, 0x000003E7}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000003E6}, + {0x03F, 0x000003E7}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000003E6}, + {0x03F, 0x000003E7}, {0xA0000000, 0x00000000}, {0x03F, 0x000003E6}, {0xB0000000, 0x00000000}, @@ -6956,20 +7740,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000152}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000152}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000152}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000152}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000152}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0xA0000000, 0x00000000}, {0x03F, 0x00000052}, {0xB0000000, 0x00000000}, @@ -7000,20 +7788,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x0000015A}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000015A}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000015A}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000015A}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000015A}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0xA0000000, 0x00000000}, {0x03F, 0x0000005A}, {0xB0000000, 0x00000000}, @@ -7044,20 +7836,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x0000019C}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000019C}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000019C}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000019C}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000019C}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0xA0000000, 0x00000000}, {0x03F, 0x0000009C}, {0xB0000000, 0x00000000}, @@ -7088,20 +7884,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x000001A4}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001A4}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001A4}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001A4}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001A4}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0xA0000000, 0x00000000}, {0x03F, 0x0000019C}, {0xB0000000, 0x00000000}, @@ -7132,20 +7932,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x000001E6}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001E6}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001E6}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001E6}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001E6}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0xA0000000, 0x00000000}, {0x03F, 0x000001A4}, {0xB0000000, 0x00000000}, @@ -7176,20 +7980,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x000002E6}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E6}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E6}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E6}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E6}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0xA0000000, 0x00000000}, {0x03F, 0x000001E6}, {0xB0000000, 0x00000000}, @@ -7220,20 +8028,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x000002E7}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E7}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E7}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E7}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E7}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000002E6}, + {0x03F, 0x000002E7}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000002E6}, + {0x03F, 0x000002E7}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000002E6}, + {0x03F, 0x000002E7}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000002E6}, + {0x03F, 0x000002E7}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000002E6}, + {0x03F, 0x000002E7}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000002E6}, + {0x03F, 0x000002E7}, {0xA0000000, 0x00000000}, {0x03F, 0x000002E6}, {0xB0000000, 0x00000000}, @@ -7264,20 +8076,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x000003E7}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000003E7}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000003E7}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000003E7}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000003E7}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000003E6}, + {0x03F, 0x000003E7}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000003E6}, + {0x03F, 0x000003E7}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000003E6}, + {0x03F, 0x000003E7}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000003E6}, + {0x03F, 0x000003E7}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000003E6}, + {0x03F, 0x000003E7}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000003E6}, + {0x03F, 0x000003E7}, {0xA0000000, 0x00000000}, {0x03F, 0x000003E6}, {0xB0000000, 0x00000000}, @@ -7308,20 +8124,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000152}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000152}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000152}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000152}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000152}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0xA0000000, 0x00000000}, {0x03F, 0x00000052}, {0xB0000000, 0x00000000}, @@ -7352,20 +8172,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x0000015A}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000015A}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000015A}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000015A}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000015A}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0xA0000000, 0x00000000}, {0x03F, 0x0000005A}, {0xB0000000, 0x00000000}, @@ -7396,20 +8220,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x0000019C}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000019C}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000019C}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000019C}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000019C}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0xA0000000, 0x00000000}, {0x03F, 0x0000009C}, {0xB0000000, 0x00000000}, @@ -7440,20 +8268,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x000001A4}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001A4}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001A4}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001A4}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001A4}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0xA0000000, 0x00000000}, {0x03F, 0x0000019C}, {0xB0000000, 0x00000000}, @@ -7484,20 +8316,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x000001E6}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001E6}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001E6}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001E6}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001E6}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0xA0000000, 0x00000000}, {0x03F, 0x000001A4}, {0xB0000000, 0x00000000}, @@ -7528,20 +8364,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x000002E6}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E6}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E6}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E6}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E6}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0xA0000000, 0x00000000}, {0x03F, 0x000001E6}, {0xB0000000, 0x00000000}, @@ -9436,7 +10276,7 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x10030, 0x0007BC1D}, {0x10030, 0x0007C017}, {0x10030, 0x0007C40F}, - {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x000001EF}, {0x10030, 0x000005E9}, {0x10030, 0x000009E3}, @@ -9581,7 +10421,7 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x10030, 0x0007BC1D}, {0x10030, 0x0007C017}, {0x10030, 0x0007C40F}, - {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x000001EF}, {0x10030, 0x000005E9}, {0x10030, 0x000009E3}, @@ -9600,60 +10440,60 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x10030, 0x00003C5F}, {0x10030, 0x00004059}, {0x10030, 0x00004453}, - {0x10030, 0x000201A7}, - {0x10030, 0x000205A1}, - {0x10030, 0x0002099B}, - {0x10030, 0x00020D95}, - {0x10030, 0x0002115B}, - {0x10030, 0x00021555}, - {0x10030, 0x00021921}, - {0x10030, 0x00021D1B}, - {0x10030, 0x000220E3}, - {0x10030, 0x000224DD}, + {0x10030, 0x000201EF}, + {0x10030, 0x000205E9}, + {0x10030, 0x000209E3}, + {0x10030, 0x00020DA3}, + {0x10030, 0x00021161}, + {0x10030, 0x0002155B}, + {0x10030, 0x0002191F}, + {0x10030, 0x00021D19}, + {0x10030, 0x000220E1}, + {0x10030, 0x000224DB}, {0x10030, 0x000228A3}, {0x10030, 0x00022C9D}, {0x10030, 0x00023063}, {0x10030, 0x0002345D}, {0x10030, 0x00023823}, - {0x10030, 0x00023C1D}, - {0x10030, 0x00024017}, - {0x10030, 0x00024411}, - {0x10030, 0x000281A9}, - {0x10030, 0x000285A3}, - {0x10030, 0x0002899D}, - {0x10030, 0x00028D97}, - {0x10030, 0x0002915D}, - {0x10030, 0x00029557}, - {0x10030, 0x0002991F}, - {0x10030, 0x00029D19}, - {0x10030, 0x0002A0E1}, - {0x10030, 0x0002A4DB}, + {0x10030, 0x00023C1B}, + {0x10030, 0x00024015}, + {0x10030, 0x0002440F}, + {0x10030, 0x000281EF}, + {0x10030, 0x000285E7}, + {0x10030, 0x000289A7}, + {0x10030, 0x00028D65}, + {0x10030, 0x0002915F}, + {0x10030, 0x00029523}, + {0x10030, 0x0002991D}, + {0x10030, 0x00029CE5}, + {0x10030, 0x0002A0DF}, + {0x10030, 0x0002A4A7}, {0x10030, 0x0002A8A1}, - {0x10030, 0x0002AC9B}, + {0x10030, 0x0002AC67}, {0x10030, 0x0002B061}, - {0x10030, 0x0002B45B}, + {0x10030, 0x0002B427}, {0x10030, 0x0002B821}, - {0x10030, 0x0002BC1B}, - {0x10030, 0x0002C015}, - {0x10030, 0x0002C40F}, - {0x10030, 0x000301A9}, - {0x10030, 0x000305A3}, - {0x10030, 0x0003099D}, - {0x10030, 0x00030D97}, - {0x10030, 0x0003115D}, - {0x10030, 0x00031557}, + {0x10030, 0x0002BC19}, + {0x10030, 0x0002C013}, + {0x10030, 0x0002C40D}, + {0x10030, 0x000301EF}, + {0x10030, 0x000305E7}, + {0x10030, 0x000309A7}, + {0x10030, 0x00030D65}, + {0x10030, 0x0003115F}, + {0x10030, 0x00031525}, {0x10030, 0x0003191F}, - {0x10030, 0x00031D19}, + {0x10030, 0x00031CE7}, {0x10030, 0x000320E1}, - {0x10030, 0x000324DB}, - {0x10030, 0x000328A1}, - {0x10030, 0x00032C9B}, - {0x10030, 0x00033061}, - {0x10030, 0x0003345B}, - {0x10030, 0x00033821}, - {0x10030, 0x00033C1B}, - {0x10030, 0x00034015}, - {0x10030, 0x0003440F}, + {0x10030, 0x000324A9}, + {0x10030, 0x000328A3}, + {0x10030, 0x00032C69}, + {0x10030, 0x00033063}, + {0x10030, 0x00033429}, + {0x10030, 0x00033823}, + {0x10030, 0x00033C1D}, + {0x10030, 0x00034013}, + {0x10030, 0x0003440D}, {0x10030, 0x000601F1}, {0x10030, 0x000605E9}, {0x10030, 0x000609A9}, @@ -9697,7 +10537,7 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x10030, 0x0007115B}, {0x10030, 0x00071523}, {0x10030, 0x0007191D}, - {0x10030, 0x00071CE5}, + {0x10030, 0x00071D17}, {0x10030, 0x000720DF}, {0x10030, 0x000724D9}, {0x10030, 0x000728A1}, @@ -9726,7 +10566,7 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x10030, 0x0007BC1D}, {0x10030, 0x0007C017}, {0x10030, 0x0007C40F}, - {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, + {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x000001EF}, {0x10030, 0x000005E9}, {0x10030, 0x000009E3}, @@ -9745,60 +10585,60 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x10030, 0x00003C5F}, {0x10030, 0x00004059}, {0x10030, 0x00004453}, - {0x10030, 0x000201A7}, - {0x10030, 0x000205A1}, - {0x10030, 0x0002099B}, - {0x10030, 0x00020D95}, - {0x10030, 0x0002115B}, - {0x10030, 0x00021555}, - {0x10030, 0x00021921}, - {0x10030, 0x00021D1B}, - {0x10030, 0x000220E3}, - {0x10030, 0x000224DD}, + {0x10030, 0x000201EF}, + {0x10030, 0x000205E9}, + {0x10030, 0x000209E3}, + {0x10030, 0x00020DA3}, + {0x10030, 0x00021161}, + {0x10030, 0x0002155B}, + {0x10030, 0x0002191F}, + {0x10030, 0x00021D19}, + {0x10030, 0x000220E1}, + {0x10030, 0x000224DB}, {0x10030, 0x000228A3}, {0x10030, 0x00022C9D}, {0x10030, 0x00023063}, {0x10030, 0x0002345D}, {0x10030, 0x00023823}, - {0x10030, 0x00023C1D}, - {0x10030, 0x00024017}, - {0x10030, 0x00024411}, - {0x10030, 0x000281A9}, - {0x10030, 0x000285A3}, - {0x10030, 0x0002899D}, - {0x10030, 0x00028D97}, - {0x10030, 0x0002915D}, - {0x10030, 0x00029557}, - {0x10030, 0x0002991F}, - {0x10030, 0x00029D19}, - {0x10030, 0x0002A0E1}, - {0x10030, 0x0002A4DB}, + {0x10030, 0x00023C1B}, + {0x10030, 0x00024015}, + {0x10030, 0x0002440F}, + {0x10030, 0x000281EF}, + {0x10030, 0x000285E7}, + {0x10030, 0x000289A7}, + {0x10030, 0x00028D65}, + {0x10030, 0x0002915F}, + {0x10030, 0x00029523}, + {0x10030, 0x0002991D}, + {0x10030, 0x00029CE5}, + {0x10030, 0x0002A0DF}, + {0x10030, 0x0002A4A7}, {0x10030, 0x0002A8A1}, - {0x10030, 0x0002AC9B}, + {0x10030, 0x0002AC67}, {0x10030, 0x0002B061}, - {0x10030, 0x0002B45B}, + {0x10030, 0x0002B427}, {0x10030, 0x0002B821}, - {0x10030, 0x0002BC1B}, - {0x10030, 0x0002C015}, - {0x10030, 0x0002C40F}, - {0x10030, 0x000301A9}, - {0x10030, 0x000305A3}, - {0x10030, 0x0003099D}, - {0x10030, 0x00030D97}, - {0x10030, 0x0003115D}, - {0x10030, 0x00031557}, + {0x10030, 0x0002BC19}, + {0x10030, 0x0002C013}, + {0x10030, 0x0002C40D}, + {0x10030, 0x000301EF}, + {0x10030, 0x000305E7}, + {0x10030, 0x000309A7}, + {0x10030, 0x00030D65}, + {0x10030, 0x0003115F}, + {0x10030, 0x00031525}, {0x10030, 0x0003191F}, - {0x10030, 0x00031D19}, + {0x10030, 0x00031CE7}, {0x10030, 0x000320E1}, - {0x10030, 0x000324DB}, - {0x10030, 0x000328A1}, - {0x10030, 0x00032C9B}, - {0x10030, 0x00033061}, - {0x10030, 0x0003345B}, - {0x10030, 0x00033821}, - {0x10030, 0x00033C1B}, - {0x10030, 0x00034015}, - {0x10030, 0x0003440F}, + {0x10030, 0x000324A9}, + {0x10030, 0x000328A3}, + {0x10030, 0x00032C69}, + {0x10030, 0x00033063}, + {0x10030, 0x00033429}, + {0x10030, 0x00033823}, + {0x10030, 0x00033C1D}, + {0x10030, 0x00034013}, + {0x10030, 0x0003440D}, {0x10030, 0x000601F1}, {0x10030, 0x000605E9}, {0x10030, 0x000609A9}, @@ -9842,7 +10682,7 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x10030, 0x0007115B}, {0x10030, 0x00071523}, {0x10030, 0x0007191D}, - {0x10030, 0x00071CE5}, + {0x10030, 0x00071D17}, {0x10030, 0x000720DF}, {0x10030, 0x000724D9}, {0x10030, 0x000728A1}, @@ -9871,7 +10711,7 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x10030, 0x0007BC1D}, {0x10030, 0x0007C017}, {0x10030, 0x0007C40F}, - {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, + {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x000001EF}, {0x10030, 0x000005E9}, {0x10030, 0x000009E3}, @@ -9949,74 +10789,74 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x10030, 0x000609A9}, {0x10030, 0x00060D65}, {0x10030, 0x0006115F}, - {0x10030, 0x00061525}, - {0x10030, 0x0006191F}, - {0x10030, 0x00061CE7}, - {0x10030, 0x000620E1}, - {0x10030, 0x000624DB}, - {0x10030, 0x000628A3}, - {0x10030, 0x00062C69}, - {0x10030, 0x00063063}, - {0x10030, 0x00063429}, - {0x10030, 0x00063823}, - {0x10030, 0x00063C1D}, - {0x10030, 0x00064013}, - {0x10030, 0x0006440D}, + {0x10030, 0x00061527}, + {0x10030, 0x00061921}, + {0x10030, 0x00061CE9}, + {0x10030, 0x000620E3}, + {0x10030, 0x000624DD}, + {0x10030, 0x000628A5}, + {0x10030, 0x00062C6B}, + {0x10030, 0x00063065}, + {0x10030, 0x0006342B}, + {0x10030, 0x00063825}, + {0x10030, 0x00063C1F}, + {0x10030, 0x00064019}, + {0x10030, 0x00064413}, {0x10030, 0x000681EF}, {0x10030, 0x000685E7}, {0x10030, 0x000689A7}, {0x10030, 0x00068D61}, {0x10030, 0x0006915B}, - {0x10030, 0x00069523}, - {0x10030, 0x0006991D}, - {0x10030, 0x00069CE5}, - {0x10030, 0x0006A0DF}, - {0x10030, 0x0006A4A7}, - {0x10030, 0x0006A8A1}, - {0x10030, 0x0006AC67}, - {0x10030, 0x0006B061}, + {0x10030, 0x00069525}, + {0x10030, 0x0006991F}, + {0x10030, 0x00069CE7}, + {0x10030, 0x0006A0E1}, + {0x10030, 0x0006A4A9}, + {0x10030, 0x0006A8A3}, + {0x10030, 0x0006AC69}, + {0x10030, 0x0006B063}, {0x10030, 0x0006B429}, {0x10030, 0x0006B823}, {0x10030, 0x0006BC1D}, {0x10030, 0x0006C017}, - {0x10030, 0x0006C40D}, + {0x10030, 0x0006C411}, {0x10030, 0x000701EF}, - {0x10030, 0x000705E7}, - {0x10030, 0x000709A7}, - {0x10030, 0x00070D61}, - {0x10030, 0x0007115B}, - {0x10030, 0x00071523}, - {0x10030, 0x0007191D}, - {0x10030, 0x00071CE5}, - {0x10030, 0x000720DF}, - {0x10030, 0x000724D9}, - {0x10030, 0x000728A1}, - {0x10030, 0x00072C67}, - {0x10030, 0x00073061}, - {0x10030, 0x00073427}, - {0x10030, 0x00073821}, - {0x10030, 0x00073C1B}, - {0x10030, 0x00074015}, - {0x10030, 0x0007440D}, + {0x10030, 0x000705E9}, + {0x10030, 0x000709A9}, + {0x10030, 0x00070D63}, + {0x10030, 0x0007115D}, + {0x10030, 0x00071525}, + {0x10030, 0x0007191F}, + {0x10030, 0x00071D19}, + {0x10030, 0x000720E1}, + {0x10030, 0x000724DB}, + {0x10030, 0x000728A3}, + {0x10030, 0x00072C69}, + {0x10030, 0x00073063}, + {0x10030, 0x00073429}, + {0x10030, 0x00073823}, + {0x10030, 0x00073C1D}, + {0x10030, 0x00074017}, + {0x10030, 0x00074411}, {0x10030, 0x000781EF}, {0x10030, 0x000785E9}, {0x10030, 0x000789E3}, {0x10030, 0x00078DA1}, {0x10030, 0x0007915F}, {0x10030, 0x00079559}, - {0x10030, 0x00079921}, - {0x10030, 0x00079D1B}, - {0x10030, 0x0007A0E3}, - {0x10030, 0x0007A4DD}, - {0x10030, 0x0007A8D7}, - {0x10030, 0x0007AC9D}, - {0x10030, 0x0007B063}, - {0x10030, 0x0007B45D}, - {0x10030, 0x0007B823}, - {0x10030, 0x0007BC1D}, - {0x10030, 0x0007C017}, - {0x10030, 0x0007C40F}, - {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, + {0x10030, 0x0007991F}, + {0x10030, 0x00079D19}, + {0x10030, 0x0007A0DF}, + {0x10030, 0x0007A4D9}, + {0x10030, 0x0007A8D3}, + {0x10030, 0x0007AC99}, + {0x10030, 0x0007B05F}, + {0x10030, 0x0007B459}, + {0x10030, 0x0007B81F}, + {0x10030, 0x0007BC19}, + {0x10030, 0x0007C013}, + {0x10030, 0x0007C40D}, + {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x000001EF}, {0x10030, 0x000005E9}, {0x10030, 0x000009E3}, @@ -10094,74 +10934,74 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x10030, 0x000609A9}, {0x10030, 0x00060D65}, {0x10030, 0x0006115F}, - {0x10030, 0x00061525}, - {0x10030, 0x0006191F}, - {0x10030, 0x00061CE7}, - {0x10030, 0x000620E1}, - {0x10030, 0x000624DB}, - {0x10030, 0x000628A3}, - {0x10030, 0x00062C69}, - {0x10030, 0x00063063}, - {0x10030, 0x00063429}, - {0x10030, 0x00063823}, - {0x10030, 0x00063C1D}, - {0x10030, 0x00064013}, - {0x10030, 0x0006440D}, + {0x10030, 0x00061527}, + {0x10030, 0x00061921}, + {0x10030, 0x00061CE9}, + {0x10030, 0x000620E3}, + {0x10030, 0x000624DD}, + {0x10030, 0x000628A5}, + {0x10030, 0x00062C6B}, + {0x10030, 0x00063065}, + {0x10030, 0x0006342B}, + {0x10030, 0x00063825}, + {0x10030, 0x00063C1F}, + {0x10030, 0x00064019}, + {0x10030, 0x00064413}, {0x10030, 0x000681EF}, {0x10030, 0x000685E7}, {0x10030, 0x000689A7}, {0x10030, 0x00068D61}, {0x10030, 0x0006915B}, - {0x10030, 0x00069523}, - {0x10030, 0x0006991D}, - {0x10030, 0x00069CE5}, - {0x10030, 0x0006A0DF}, - {0x10030, 0x0006A4A7}, - {0x10030, 0x0006A8A1}, - {0x10030, 0x0006AC67}, - {0x10030, 0x0006B061}, + {0x10030, 0x00069525}, + {0x10030, 0x0006991F}, + {0x10030, 0x00069CE7}, + {0x10030, 0x0006A0E1}, + {0x10030, 0x0006A4A9}, + {0x10030, 0x0006A8A3}, + {0x10030, 0x0006AC69}, + {0x10030, 0x0006B063}, {0x10030, 0x0006B429}, {0x10030, 0x0006B823}, {0x10030, 0x0006BC1D}, {0x10030, 0x0006C017}, - {0x10030, 0x0006C40D}, + {0x10030, 0x0006C411}, {0x10030, 0x000701EF}, - {0x10030, 0x000705E7}, - {0x10030, 0x000709A7}, - {0x10030, 0x00070D61}, - {0x10030, 0x0007115B}, - {0x10030, 0x00071523}, - {0x10030, 0x0007191D}, - {0x10030, 0x00071CE5}, - {0x10030, 0x000720DF}, - {0x10030, 0x000724D9}, - {0x10030, 0x000728A1}, - {0x10030, 0x00072C67}, - {0x10030, 0x00073061}, - {0x10030, 0x00073427}, - {0x10030, 0x00073821}, - {0x10030, 0x00073C1B}, - {0x10030, 0x00074015}, - {0x10030, 0x0007440D}, + {0x10030, 0x000705E9}, + {0x10030, 0x000709A9}, + {0x10030, 0x00070D63}, + {0x10030, 0x0007115D}, + {0x10030, 0x00071525}, + {0x10030, 0x0007191F}, + {0x10030, 0x00071D19}, + {0x10030, 0x000720E1}, + {0x10030, 0x000724DB}, + {0x10030, 0x000728A3}, + {0x10030, 0x00072C69}, + {0x10030, 0x00073063}, + {0x10030, 0x00073429}, + {0x10030, 0x00073823}, + {0x10030, 0x00073C1D}, + {0x10030, 0x00074017}, + {0x10030, 0x00074411}, {0x10030, 0x000781EF}, {0x10030, 0x000785E9}, {0x10030, 0x000789E3}, {0x10030, 0x00078DA1}, {0x10030, 0x0007915F}, {0x10030, 0x00079559}, - {0x10030, 0x00079921}, - {0x10030, 0x00079D1B}, - {0x10030, 0x0007A0E3}, - {0x10030, 0x0007A4DD}, - {0x10030, 0x0007A8D7}, - {0x10030, 0x0007AC9D}, - {0x10030, 0x0007B063}, - {0x10030, 0x0007B45D}, - {0x10030, 0x0007B823}, - {0x10030, 0x0007BC1D}, - {0x10030, 0x0007C017}, - {0x10030, 0x0007C40F}, - {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, + {0x10030, 0x0007991F}, + {0x10030, 0x00079D19}, + {0x10030, 0x0007A0DF}, + {0x10030, 0x0007A4D9}, + {0x10030, 0x0007A8D3}, + {0x10030, 0x0007AC99}, + {0x10030, 0x0007B05F}, + {0x10030, 0x0007B459}, + {0x10030, 0x0007B81F}, + {0x10030, 0x0007BC19}, + {0x10030, 0x0007C013}, + {0x10030, 0x0007C40D}, + {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x000001EF}, {0x10030, 0x000005E9}, {0x10030, 0x000009E3}, @@ -10239,74 +11079,74 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x10030, 0x000609A9}, {0x10030, 0x00060D65}, {0x10030, 0x0006115F}, - {0x10030, 0x00061525}, - {0x10030, 0x0006191F}, - {0x10030, 0x00061CE7}, - {0x10030, 0x000620E1}, - {0x10030, 0x000624DB}, - {0x10030, 0x000628A3}, - {0x10030, 0x00062C69}, - {0x10030, 0x00063063}, - {0x10030, 0x00063429}, - {0x10030, 0x00063823}, - {0x10030, 0x00063C1D}, - {0x10030, 0x00064013}, - {0x10030, 0x0006440D}, + {0x10030, 0x00061527}, + {0x10030, 0x00061921}, + {0x10030, 0x00061CE9}, + {0x10030, 0x000620E3}, + {0x10030, 0x000624DD}, + {0x10030, 0x000628A5}, + {0x10030, 0x00062C6B}, + {0x10030, 0x00063065}, + {0x10030, 0x0006342B}, + {0x10030, 0x00063825}, + {0x10030, 0x00063C1F}, + {0x10030, 0x00064019}, + {0x10030, 0x00064413}, {0x10030, 0x000681EF}, {0x10030, 0x000685E7}, {0x10030, 0x000689A7}, {0x10030, 0x00068D61}, {0x10030, 0x0006915B}, - {0x10030, 0x00069523}, - {0x10030, 0x0006991D}, - {0x10030, 0x00069CE5}, - {0x10030, 0x0006A0DF}, - {0x10030, 0x0006A4A7}, - {0x10030, 0x0006A8A1}, - {0x10030, 0x0006AC67}, - {0x10030, 0x0006B061}, + {0x10030, 0x00069525}, + {0x10030, 0x0006991F}, + {0x10030, 0x00069CE7}, + {0x10030, 0x0006A0E1}, + {0x10030, 0x0006A4A9}, + {0x10030, 0x0006A8A3}, + {0x10030, 0x0006AC69}, + {0x10030, 0x0006B063}, {0x10030, 0x0006B429}, {0x10030, 0x0006B823}, {0x10030, 0x0006BC1D}, {0x10030, 0x0006C017}, - {0x10030, 0x0006C40D}, + {0x10030, 0x0006C411}, {0x10030, 0x000701EF}, - {0x10030, 0x000705E7}, - {0x10030, 0x000709A7}, - {0x10030, 0x00070D61}, - {0x10030, 0x0007115B}, - {0x10030, 0x00071523}, - {0x10030, 0x0007191D}, - {0x10030, 0x00071CE5}, - {0x10030, 0x000720DF}, - {0x10030, 0x000724D9}, - {0x10030, 0x000728A1}, - {0x10030, 0x00072C67}, - {0x10030, 0x00073061}, - {0x10030, 0x00073427}, - {0x10030, 0x00073821}, - {0x10030, 0x00073C1B}, - {0x10030, 0x00074015}, - {0x10030, 0x0007440D}, + {0x10030, 0x000705E9}, + {0x10030, 0x000709A9}, + {0x10030, 0x00070D63}, + {0x10030, 0x0007115D}, + {0x10030, 0x00071525}, + {0x10030, 0x0007191F}, + {0x10030, 0x00071D19}, + {0x10030, 0x000720E1}, + {0x10030, 0x000724DB}, + {0x10030, 0x000728A3}, + {0x10030, 0x00072C69}, + {0x10030, 0x00073063}, + {0x10030, 0x00073429}, + {0x10030, 0x00073823}, + {0x10030, 0x00073C1D}, + {0x10030, 0x00074017}, + {0x10030, 0x00074411}, {0x10030, 0x000781EF}, {0x10030, 0x000785E9}, {0x10030, 0x000789E3}, {0x10030, 0x00078DA1}, {0x10030, 0x0007915F}, {0x10030, 0x00079559}, - {0x10030, 0x00079921}, - {0x10030, 0x00079D1B}, - {0x10030, 0x0007A0E3}, - {0x10030, 0x0007A4DD}, - {0x10030, 0x0007A8D7}, - {0x10030, 0x0007AC9D}, - {0x10030, 0x0007B063}, - {0x10030, 0x0007B45D}, - {0x10030, 0x0007B823}, - {0x10030, 0x0007BC1D}, - {0x10030, 0x0007C017}, - {0x10030, 0x0007C40F}, - {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, + {0x10030, 0x0007991F}, + {0x10030, 0x00079D19}, + {0x10030, 0x0007A0DF}, + {0x10030, 0x0007A4D9}, + {0x10030, 0x0007A8D3}, + {0x10030, 0x0007AC99}, + {0x10030, 0x0007B05F}, + {0x10030, 0x0007B459}, + {0x10030, 0x0007B81F}, + {0x10030, 0x0007BC19}, + {0x10030, 0x0007C013}, + {0x10030, 0x0007C40D}, + {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x000001EF}, {0x10030, 0x000005E9}, {0x10030, 0x000009E3}, @@ -10384,73 +11224,363 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x10030, 0x000609A9}, {0x10030, 0x00060D65}, {0x10030, 0x0006115F}, - {0x10030, 0x00061525}, - {0x10030, 0x0006191F}, - {0x10030, 0x00061CE7}, - {0x10030, 0x000620E1}, - {0x10030, 0x000624DB}, - {0x10030, 0x000628A3}, - {0x10030, 0x00062C69}, - {0x10030, 0x00063063}, - {0x10030, 0x00063429}, - {0x10030, 0x00063823}, - {0x10030, 0x00063C1D}, - {0x10030, 0x00064013}, - {0x10030, 0x0006440D}, + {0x10030, 0x00061527}, + {0x10030, 0x00061921}, + {0x10030, 0x00061CE9}, + {0x10030, 0x000620E3}, + {0x10030, 0x000624DD}, + {0x10030, 0x000628A5}, + {0x10030, 0x00062C6B}, + {0x10030, 0x00063065}, + {0x10030, 0x0006342B}, + {0x10030, 0x00063825}, + {0x10030, 0x00063C1F}, + {0x10030, 0x00064019}, + {0x10030, 0x00064413}, {0x10030, 0x000681EF}, {0x10030, 0x000685E7}, {0x10030, 0x000689A7}, {0x10030, 0x00068D61}, {0x10030, 0x0006915B}, - {0x10030, 0x00069523}, - {0x10030, 0x0006991D}, - {0x10030, 0x00069CE5}, - {0x10030, 0x0006A0DF}, - {0x10030, 0x0006A4A7}, - {0x10030, 0x0006A8A1}, - {0x10030, 0x0006AC67}, - {0x10030, 0x0006B061}, + {0x10030, 0x00069525}, + {0x10030, 0x0006991F}, + {0x10030, 0x00069CE7}, + {0x10030, 0x0006A0E1}, + {0x10030, 0x0006A4A9}, + {0x10030, 0x0006A8A3}, + {0x10030, 0x0006AC69}, + {0x10030, 0x0006B063}, {0x10030, 0x0006B429}, {0x10030, 0x0006B823}, {0x10030, 0x0006BC1D}, {0x10030, 0x0006C017}, - {0x10030, 0x0006C40D}, + {0x10030, 0x0006C411}, {0x10030, 0x000701EF}, - {0x10030, 0x000705E7}, - {0x10030, 0x000709A7}, - {0x10030, 0x00070D61}, - {0x10030, 0x0007115B}, - {0x10030, 0x00071523}, - {0x10030, 0x0007191D}, - {0x10030, 0x00071CE5}, - {0x10030, 0x000720DF}, - {0x10030, 0x000724D9}, - {0x10030, 0x000728A1}, - {0x10030, 0x00072C67}, - {0x10030, 0x00073061}, - {0x10030, 0x00073427}, - {0x10030, 0x00073821}, - {0x10030, 0x00073C1B}, - {0x10030, 0x00074015}, - {0x10030, 0x0007440D}, + {0x10030, 0x000705E9}, + {0x10030, 0x000709A9}, + {0x10030, 0x00070D63}, + {0x10030, 0x0007115D}, + {0x10030, 0x00071525}, + {0x10030, 0x0007191F}, + {0x10030, 0x00071D19}, + {0x10030, 0x000720E1}, + {0x10030, 0x000724DB}, + {0x10030, 0x000728A3}, + {0x10030, 0x00072C69}, + {0x10030, 0x00073063}, + {0x10030, 0x00073429}, + {0x10030, 0x00073823}, + {0x10030, 0x00073C1D}, + {0x10030, 0x00074017}, + {0x10030, 0x00074411}, {0x10030, 0x000781EF}, {0x10030, 0x000785E9}, {0x10030, 0x000789E3}, {0x10030, 0x00078DA1}, {0x10030, 0x0007915F}, {0x10030, 0x00079559}, - {0x10030, 0x00079921}, - {0x10030, 0x00079D1B}, - {0x10030, 0x0007A0E3}, - {0x10030, 0x0007A4DD}, - {0x10030, 0x0007A8D7}, - {0x10030, 0x0007AC9D}, - {0x10030, 0x0007B063}, - {0x10030, 0x0007B45D}, - {0x10030, 0x0007B823}, - {0x10030, 0x0007BC1D}, - {0x10030, 0x0007C017}, - {0x10030, 0x0007C40F}, + {0x10030, 0x0007991F}, + {0x10030, 0x00079D19}, + {0x10030, 0x0007A0DF}, + {0x10030, 0x0007A4D9}, + {0x10030, 0x0007A8D3}, + {0x10030, 0x0007AC99}, + {0x10030, 0x0007B05F}, + {0x10030, 0x0007B459}, + {0x10030, 0x0007B81F}, + {0x10030, 0x0007BC19}, + {0x10030, 0x0007C013}, + {0x10030, 0x0007C40D}, + {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, + {0x10030, 0x000001EF}, + {0x10030, 0x000005E9}, + {0x10030, 0x000009E3}, + {0x10030, 0x00000DDD}, + {0x10030, 0x000011D7}, + {0x10030, 0x0000159F}, + {0x10030, 0x00001999}, + {0x10030, 0x00001D5F}, + {0x10030, 0x00002159}, + {0x10030, 0x0000251F}, + {0x10030, 0x00002919}, + {0x10030, 0x00002CDF}, + {0x10030, 0x000030D9}, + {0x10030, 0x0000349F}, + {0x10030, 0x00003899}, + {0x10030, 0x00003C5F}, + {0x10030, 0x00004059}, + {0x10030, 0x00004453}, + {0x10030, 0x000201A7}, + {0x10030, 0x000205A1}, + {0x10030, 0x0002099B}, + {0x10030, 0x00020D95}, + {0x10030, 0x0002115B}, + {0x10030, 0x00021555}, + {0x10030, 0x00021921}, + {0x10030, 0x00021D1B}, + {0x10030, 0x000220E3}, + {0x10030, 0x000224DD}, + {0x10030, 0x000228A3}, + {0x10030, 0x00022C9D}, + {0x10030, 0x00023063}, + {0x10030, 0x0002345D}, + {0x10030, 0x00023823}, + {0x10030, 0x00023C1D}, + {0x10030, 0x00024017}, + {0x10030, 0x00024411}, + {0x10030, 0x000281A9}, + {0x10030, 0x000285A3}, + {0x10030, 0x0002899D}, + {0x10030, 0x00028D97}, + {0x10030, 0x0002915D}, + {0x10030, 0x00029557}, + {0x10030, 0x0002991F}, + {0x10030, 0x00029D19}, + {0x10030, 0x0002A0E1}, + {0x10030, 0x0002A4DB}, + {0x10030, 0x0002A8A1}, + {0x10030, 0x0002AC9B}, + {0x10030, 0x0002B061}, + {0x10030, 0x0002B45B}, + {0x10030, 0x0002B821}, + {0x10030, 0x0002BC1B}, + {0x10030, 0x0002C015}, + {0x10030, 0x0002C40F}, + {0x10030, 0x000301A9}, + {0x10030, 0x000305A3}, + {0x10030, 0x0003099D}, + {0x10030, 0x00030D97}, + {0x10030, 0x0003115D}, + {0x10030, 0x00031557}, + {0x10030, 0x0003191F}, + {0x10030, 0x00031D19}, + {0x10030, 0x000320E1}, + {0x10030, 0x000324DB}, + {0x10030, 0x000328A1}, + {0x10030, 0x00032C9B}, + {0x10030, 0x00033061}, + {0x10030, 0x0003345B}, + {0x10030, 0x00033821}, + {0x10030, 0x00033C1B}, + {0x10030, 0x00034015}, + {0x10030, 0x0003440F}, + {0x10030, 0x000601F1}, + {0x10030, 0x000605E9}, + {0x10030, 0x000609A9}, + {0x10030, 0x00060D65}, + {0x10030, 0x0006115F}, + {0x10030, 0x00061527}, + {0x10030, 0x00061921}, + {0x10030, 0x00061CE9}, + {0x10030, 0x000620E3}, + {0x10030, 0x000624DD}, + {0x10030, 0x000628A5}, + {0x10030, 0x00062C6B}, + {0x10030, 0x00063065}, + {0x10030, 0x0006342B}, + {0x10030, 0x00063825}, + {0x10030, 0x00063C1F}, + {0x10030, 0x00064019}, + {0x10030, 0x00064413}, + {0x10030, 0x000681EF}, + {0x10030, 0x000685E7}, + {0x10030, 0x000689A7}, + {0x10030, 0x00068D61}, + {0x10030, 0x0006915B}, + {0x10030, 0x00069525}, + {0x10030, 0x0006991F}, + {0x10030, 0x00069CE7}, + {0x10030, 0x0006A0E1}, + {0x10030, 0x0006A4A9}, + {0x10030, 0x0006A8A3}, + {0x10030, 0x0006AC69}, + {0x10030, 0x0006B063}, + {0x10030, 0x0006B429}, + {0x10030, 0x0006B823}, + {0x10030, 0x0006BC1D}, + {0x10030, 0x0006C017}, + {0x10030, 0x0006C411}, + {0x10030, 0x000701EF}, + {0x10030, 0x000705E9}, + {0x10030, 0x000709A9}, + {0x10030, 0x00070D63}, + {0x10030, 0x0007115D}, + {0x10030, 0x00071525}, + {0x10030, 0x0007191F}, + {0x10030, 0x00071D19}, + {0x10030, 0x000720E1}, + {0x10030, 0x000724DB}, + {0x10030, 0x000728A3}, + {0x10030, 0x00072C69}, + {0x10030, 0x00073063}, + {0x10030, 0x00073429}, + {0x10030, 0x00073823}, + {0x10030, 0x00073C1D}, + {0x10030, 0x00074017}, + {0x10030, 0x00074411}, + {0x10030, 0x000781EF}, + {0x10030, 0x000785E9}, + {0x10030, 0x000789E3}, + {0x10030, 0x00078DA1}, + {0x10030, 0x0007915F}, + {0x10030, 0x00079559}, + {0x10030, 0x0007991F}, + {0x10030, 0x00079D19}, + {0x10030, 0x0007A0DF}, + {0x10030, 0x0007A4D9}, + {0x10030, 0x0007A8D3}, + {0x10030, 0x0007AC99}, + {0x10030, 0x0007B05F}, + {0x10030, 0x0007B459}, + {0x10030, 0x0007B81F}, + {0x10030, 0x0007BC19}, + {0x10030, 0x0007C013}, + {0x10030, 0x0007C40D}, + {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, + {0x10030, 0x000001EF}, + {0x10030, 0x000005E9}, + {0x10030, 0x000009E3}, + {0x10030, 0x00000DDD}, + {0x10030, 0x000011D7}, + {0x10030, 0x0000159F}, + {0x10030, 0x00001999}, + {0x10030, 0x00001D5F}, + {0x10030, 0x00002159}, + {0x10030, 0x0000251F}, + {0x10030, 0x00002919}, + {0x10030, 0x00002CDF}, + {0x10030, 0x000030D9}, + {0x10030, 0x0000349F}, + {0x10030, 0x00003899}, + {0x10030, 0x00003C5F}, + {0x10030, 0x00004059}, + {0x10030, 0x00004453}, + {0x10030, 0x000201A7}, + {0x10030, 0x000205A1}, + {0x10030, 0x0002099B}, + {0x10030, 0x00020D95}, + {0x10030, 0x0002115B}, + {0x10030, 0x00021555}, + {0x10030, 0x00021921}, + {0x10030, 0x00021D1B}, + {0x10030, 0x000220E3}, + {0x10030, 0x000224DD}, + {0x10030, 0x000228A3}, + {0x10030, 0x00022C9D}, + {0x10030, 0x00023063}, + {0x10030, 0x0002345D}, + {0x10030, 0x00023823}, + {0x10030, 0x00023C1D}, + {0x10030, 0x00024017}, + {0x10030, 0x00024411}, + {0x10030, 0x000281A9}, + {0x10030, 0x000285A3}, + {0x10030, 0x0002899D}, + {0x10030, 0x00028D97}, + {0x10030, 0x0002915D}, + {0x10030, 0x00029557}, + {0x10030, 0x0002991F}, + {0x10030, 0x00029D19}, + {0x10030, 0x0002A0E1}, + {0x10030, 0x0002A4DB}, + {0x10030, 0x0002A8A1}, + {0x10030, 0x0002AC9B}, + {0x10030, 0x0002B061}, + {0x10030, 0x0002B45B}, + {0x10030, 0x0002B821}, + {0x10030, 0x0002BC1B}, + {0x10030, 0x0002C015}, + {0x10030, 0x0002C40F}, + {0x10030, 0x000301A9}, + {0x10030, 0x000305A3}, + {0x10030, 0x0003099D}, + {0x10030, 0x00030D97}, + {0x10030, 0x0003115D}, + {0x10030, 0x00031557}, + {0x10030, 0x0003191F}, + {0x10030, 0x00031D19}, + {0x10030, 0x000320E1}, + {0x10030, 0x000324DB}, + {0x10030, 0x000328A1}, + {0x10030, 0x00032C9B}, + {0x10030, 0x00033061}, + {0x10030, 0x0003345B}, + {0x10030, 0x00033821}, + {0x10030, 0x00033C1B}, + {0x10030, 0x00034015}, + {0x10030, 0x0003440F}, + {0x10030, 0x000601F1}, + {0x10030, 0x000605E9}, + {0x10030, 0x000609A9}, + {0x10030, 0x00060D65}, + {0x10030, 0x0006115F}, + {0x10030, 0x00061527}, + {0x10030, 0x00061921}, + {0x10030, 0x00061CE9}, + {0x10030, 0x000620E3}, + {0x10030, 0x000624DD}, + {0x10030, 0x000628A5}, + {0x10030, 0x00062C6B}, + {0x10030, 0x00063065}, + {0x10030, 0x0006342B}, + {0x10030, 0x00063825}, + {0x10030, 0x00063C1F}, + {0x10030, 0x00064019}, + {0x10030, 0x00064413}, + {0x10030, 0x000681EF}, + {0x10030, 0x000685E7}, + {0x10030, 0x000689A7}, + {0x10030, 0x00068D61}, + {0x10030, 0x0006915B}, + {0x10030, 0x00069525}, + {0x10030, 0x0006991F}, + {0x10030, 0x00069CE7}, + {0x10030, 0x0006A0E1}, + {0x10030, 0x0006A4A9}, + {0x10030, 0x0006A8A3}, + {0x10030, 0x0006AC69}, + {0x10030, 0x0006B063}, + {0x10030, 0x0006B429}, + {0x10030, 0x0006B823}, + {0x10030, 0x0006BC1D}, + {0x10030, 0x0006C017}, + {0x10030, 0x0006C411}, + {0x10030, 0x000701EF}, + {0x10030, 0x000705E9}, + {0x10030, 0x000709A9}, + {0x10030, 0x00070D63}, + {0x10030, 0x0007115D}, + {0x10030, 0x00071525}, + {0x10030, 0x0007191F}, + {0x10030, 0x00071D19}, + {0x10030, 0x000720E1}, + {0x10030, 0x000724DB}, + {0x10030, 0x000728A3}, + {0x10030, 0x00072C69}, + {0x10030, 0x00073063}, + {0x10030, 0x00073429}, + {0x10030, 0x00073823}, + {0x10030, 0x00073C1D}, + {0x10030, 0x00074017}, + {0x10030, 0x00074411}, + {0x10030, 0x000781EF}, + {0x10030, 0x000785E9}, + {0x10030, 0x000789E3}, + {0x10030, 0x00078DA1}, + {0x10030, 0x0007915F}, + {0x10030, 0x00079559}, + {0x10030, 0x0007991F}, + {0x10030, 0x00079D19}, + {0x10030, 0x0007A0DF}, + {0x10030, 0x0007A4D9}, + {0x10030, 0x0007A8D3}, + {0x10030, 0x0007AC99}, + {0x10030, 0x0007B05F}, + {0x10030, 0x0007B459}, + {0x10030, 0x0007B81F}, + {0x10030, 0x0007BC19}, + {0x10030, 0x0007C013}, + {0x10030, 0x0007C40D}, {0xA0000000, 0x00000000}, {0x10030, 0x000001EF}, {0x10030, 0x000005E9}, @@ -11294,12 +12424,116 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x10030, 0x000338CC}, {0x10030, 0x00033C09}, {0x10030, 0x00034006}, - {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, - {0x10030, 0x000200FA}, - {0x10030, 0x000204F7}, - {0x10030, 0x000208F4}, - {0x10030, 0x00020CF1}, - {0x10030, 0x000210EE}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x10030, 0x000200E8}, + {0x10030, 0x000204E5}, + {0x10030, 0x000208E2}, + {0x10030, 0x00020CDF}, + {0x10030, 0x000210DC}, + {0x10030, 0x000214D9}, + {0x10030, 0x000218D6}, + {0x10030, 0x00021CD3}, + {0x10030, 0x000220D0}, + {0x10030, 0x0002240D}, + {0x10030, 0x0002280A}, + {0x10030, 0x00022C07}, + {0x10030, 0x00023004}, + {0x10030, 0x00023401}, + {0x10030, 0x00023800}, + {0x10030, 0x00023C00}, + {0x10030, 0x00024000}, + {0x10030, 0x000280ED}, + {0x10030, 0x000284EA}, + {0x10030, 0x000288E7}, + {0x10030, 0x00028CE4}, + {0x10030, 0x000290E1}, + {0x10030, 0x000294DE}, + {0x10030, 0x000298DB}, + {0x10030, 0x00029CD8}, + {0x10030, 0x0002A0D5}, + {0x10030, 0x0002A4D2}, + {0x10030, 0x0002A8CF}, + {0x10030, 0x0002AC0C}, + {0x10030, 0x0002B009}, + {0x10030, 0x0002B406}, + {0x10030, 0x0002B803}, + {0x10030, 0x0002BC00}, + {0x10030, 0x0002C000}, + {0x10030, 0x000300EE}, + {0x10030, 0x000304EB}, + {0x10030, 0x000308E8}, + {0x10030, 0x00030CE5}, + {0x10030, 0x000310E2}, + {0x10030, 0x000314DF}, + {0x10030, 0x000318DC}, + {0x10030, 0x00031CD9}, + {0x10030, 0x000320D6}, + {0x10030, 0x000324D3}, + {0x10030, 0x000328D0}, + {0x10030, 0x00032CCD}, + {0x10030, 0x0003300A}, + {0x10030, 0x00033407}, + {0x10030, 0x00033804}, + {0x10030, 0x00033C01}, + {0x10030, 0x00034000}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x10030, 0x000200E8}, + {0x10030, 0x000204E5}, + {0x10030, 0x000208E2}, + {0x10030, 0x00020CDF}, + {0x10030, 0x000210DC}, + {0x10030, 0x000214D9}, + {0x10030, 0x000218D6}, + {0x10030, 0x00021CD3}, + {0x10030, 0x000220D0}, + {0x10030, 0x0002240D}, + {0x10030, 0x0002280A}, + {0x10030, 0x00022C07}, + {0x10030, 0x00023004}, + {0x10030, 0x00023401}, + {0x10030, 0x00023800}, + {0x10030, 0x00023C00}, + {0x10030, 0x00024000}, + {0x10030, 0x000280ED}, + {0x10030, 0x000284EA}, + {0x10030, 0x000288E7}, + {0x10030, 0x00028CE4}, + {0x10030, 0x000290E1}, + {0x10030, 0x000294DE}, + {0x10030, 0x000298DB}, + {0x10030, 0x00029CD8}, + {0x10030, 0x0002A0D5}, + {0x10030, 0x0002A4D2}, + {0x10030, 0x0002A8CF}, + {0x10030, 0x0002AC0C}, + {0x10030, 0x0002B009}, + {0x10030, 0x0002B406}, + {0x10030, 0x0002B803}, + {0x10030, 0x0002BC00}, + {0x10030, 0x0002C000}, + {0x10030, 0x000300EE}, + {0x10030, 0x000304EB}, + {0x10030, 0x000308E8}, + {0x10030, 0x00030CE5}, + {0x10030, 0x000310E2}, + {0x10030, 0x000314DF}, + {0x10030, 0x000318DC}, + {0x10030, 0x00031CD9}, + {0x10030, 0x000320D6}, + {0x10030, 0x000324D3}, + {0x10030, 0x000328D0}, + {0x10030, 0x00032CCD}, + {0x10030, 0x0003300A}, + {0x10030, 0x00033407}, + {0x10030, 0x00033804}, + {0x10030, 0x00033C01}, + {0x10030, 0x00034000}, + {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, + {0x10030, 0x000200FA}, + {0x10030, 0x000204F7}, + {0x10030, 0x000208F4}, + {0x10030, 0x00020CF1}, + {0x10030, 0x000210EE}, {0x10030, 0x000214EB}, {0x10030, 0x000218E8}, {0x10030, 0x00021CE5}, @@ -11841,6 +13075,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -11885,6 +13123,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -11941,6 +13183,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -11985,6 +13231,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -12041,6 +13291,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -12085,6 +13339,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -12141,6 +13399,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -12185,6 +13447,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -12241,6 +13507,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -12285,6 +13555,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -12305,7 +13579,53 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x033, 0x00000070}, {0x03F, 0x00050002}, {0x033, 0x00000071}, + {0x80010000, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00060032}, + {0x90020000, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00060032}, + {0x90320000, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00060032}, + {0x90330000, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00060032}, + {0x90340000, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00060032}, + {0x90350000, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00060032}, + {0x90360000, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00060032}, + {0x90010001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00060032}, + {0x90020001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00060032}, + {0x90030001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00060032}, + {0x90040001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00060032}, + {0x90050001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00060032}, + {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00060032}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00060032}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00060032}, + {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00060032}, + {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00060032}, + {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00060032}, + {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00060032}, + {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00060032}, + {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00060032}, + {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00060032}, + {0xA0000000, 0x00000000}, {0x03F, 0x00060032}, + {0xB0000000, 0x00000000}, {0x033, 0x00000072}, {0x03F, 0x00050042}, {0x033, 0x00000073}, @@ -12341,6 +13661,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -12385,6 +13709,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -12405,7 +13733,53 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x033, 0x00000078}, {0x03F, 0x00050002}, {0x033, 0x00000079}, + {0x80010000, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00060032}, + {0x90020000, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00060032}, + {0x90320000, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00060032}, + {0x90330000, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00060032}, + {0x90340000, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00060032}, + {0x90350000, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00060032}, + {0x90360000, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00060032}, + {0x90010001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00060032}, + {0x90020001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00060032}, + {0x90030001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00060032}, + {0x90040001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00060032}, + {0x90050001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00060032}, + {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00060032}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00060032}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00060032}, + {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00060032}, + {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00060032}, + {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00060032}, + {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00060032}, + {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00060032}, + {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00060032}, + {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00060032}, + {0xA0000000, 0x00000000}, {0x03F, 0x00060032}, + {0xB0000000, 0x00000000}, {0x033, 0x0000007A}, {0x03F, 0x00050042}, {0x033, 0x0000007B}, @@ -12441,6 +13815,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -12485,6 +13863,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -12541,6 +13923,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -12585,6 +13971,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -12641,6 +14031,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -12685,6 +14079,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -12741,6 +14139,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -12785,6 +14187,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -12841,6 +14247,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -12885,6 +14295,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -12941,6 +14355,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -12985,6 +14403,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -13041,6 +14463,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -13085,6 +14511,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -13141,6 +14571,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -13185,6 +14619,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -13241,6 +14679,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -13285,6 +14727,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -13341,6 +14787,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -13385,6 +14835,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -13441,6 +14895,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -13485,6 +14943,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -13541,6 +15003,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -13585,6 +15051,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -13641,6 +15111,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -13685,6 +15159,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -13741,6 +15219,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -13785,6 +15267,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -13841,6 +15327,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -13885,6 +15375,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -13941,6 +15435,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -13985,6 +15483,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -14041,6 +15543,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -14085,6 +15591,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -14141,6 +15651,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -14185,6 +15699,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -14241,6 +15759,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -14285,6 +15807,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -14341,6 +15867,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -14385,6 +15915,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -14441,6 +15975,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -14485,6 +16023,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -14541,6 +16083,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -14585,6 +16131,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -14669,6 +16219,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x10030, 0x00025003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x00025003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x10030, 0x00025003}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x10030, 0x00025003}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x00025003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -14719,6 +16273,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x10030, 0x0002D003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x0002D003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x10030, 0x0002D003}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x10030, 0x0002D003}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x0002D003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -14769,6 +16327,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x10030, 0x00035003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x00035003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x10030, 0x00035003}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x10030, 0x00035003}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x00035003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -14819,6 +16381,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x10030, 0x0003D003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x0003D003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x10030, 0x0003D003}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x10030, 0x0003D003}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x0003D003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -14882,6 +16448,12 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x00065003}, {0x10030, 0x00066003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x10030, 0x00065003}, + {0x10030, 0x00066003}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x10030, 0x00065003}, + {0x10030, 0x00066003}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x00065003}, {0x10030, 0x00066003}, @@ -14952,6 +16524,12 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x0006D003}, {0x10030, 0x0006E003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x10030, 0x0006D003}, + {0x10030, 0x0006E003}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x10030, 0x0006D003}, + {0x10030, 0x0006E003}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x0006D003}, {0x10030, 0x0006E003}, @@ -15022,6 +16600,12 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x00075003}, {0x10030, 0x00076003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x10030, 0x00075003}, + {0x10030, 0x00076003}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x10030, 0x00075003}, + {0x10030, 0x00076003}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x00075003}, {0x10030, 0x00076003}, @@ -15092,6 +16676,12 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x0007D003}, {0x10030, 0x0007E003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x10030, 0x0007D003}, + {0x10030, 0x0007E003}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x10030, 0x0007D003}, + {0x10030, 0x0007E003}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x0007D003}, {0x10030, 0x0007E003}, @@ -15119,7 +16709,7 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0xB0000000, 0x00000000}, {0x10030, 0x0007F003}, {0x100EE, 0x00000000}, - {0x0FE, 0x00000048}, + {0x0FE, 0x00000063}, }; static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { @@ -15136,13 +16726,15 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0xF0040001, 0x0000000A}, {0xF0050001, 0x0000000B}, {0xF0070001, 0x0000000C}, - {0xF0320001, 0x0000000D}, - {0xF0330001, 0x0000000E}, - {0xF0340001, 0x0000000F}, - {0xF0350001, 0x00000010}, - {0xF0360001, 0x00000011}, - {0xF03F0001, 0x00000012}, - {0xF0400001, 0x00000013}, + {0xF0150001, 0x0000000D}, + {0xF0160001, 0x0000000E}, + {0xF0320001, 0x0000000F}, + {0xF0330001, 0x00000010}, + {0xF0340001, 0x00000011}, + {0xF0350001, 0x00000012}, + {0xF0360001, 0x00000013}, + {0xF03F0001, 0x00000014}, + {0xF0400001, 0x00000015}, {0x005, 0x00000000}, {0x10005, 0x00000000}, {0x0B9, 0x00020440}, @@ -15150,6 +16742,12 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x10000, 0x00030000}, {0x018, 0x00011124}, {0x10018, 0x00011124}, + {0x0A3, 0x000B9204}, + {0x0AD, 0x00091E0F}, + {0x05D, 0x00001012}, + {0x05C, 0x00079C5C}, + {0x062, 0x00055220}, + {0x0D3, 0x00000103}, {0x05F, 0x00000038}, {0x097, 0x00043200}, {0x0A6, 0x00066DB7}, @@ -15253,6 +16851,12 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x067, 0x0000D300}, {0x0DA, 0x000D4000}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x067, 0x0000D300}, + {0x0DA, 0x000D4000}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x067, 0x0000D300}, + {0x0DA, 0x000D4000}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x067, 0x0000D300}, {0x0DA, 0x000D4000}, @@ -15319,6 +16923,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x08F, 0x000D1352}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x08F, 0x000D1352}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x08F, 0x000D1352}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x08F, 0x000D1352}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x08F, 0x000D1352}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -15382,6 +16990,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000007}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000007}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000017}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000017}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000007}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -15918,6 +17530,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x0000EFFF}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000EFFF}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000EFFF}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000EFFF}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000EFFF}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -16256,6 +17872,32 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x030, 0x00050112}, {0x030, 0x00058101}, {0x030, 0x00060001}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x000085ED}, + {0x030, 0x000105CC}, + {0x030, 0x000184AA}, + {0x030, 0x00020388}, + {0x030, 0x00028377}, + {0x030, 0x00030377}, + {0x030, 0x00038255}, + {0x030, 0x00040244}, + {0x030, 0x00048133}, + {0x030, 0x00050112}, + {0x030, 0x00058101}, + {0x030, 0x00060001}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x000085ED}, + {0x030, 0x000105CC}, + {0x030, 0x000184AA}, + {0x030, 0x00020388}, + {0x030, 0x00028377}, + {0x030, 0x00030377}, + {0x030, 0x00038255}, + {0x030, 0x00040244}, + {0x030, 0x00048133}, + {0x030, 0x00050112}, + {0x030, 0x00058101}, + {0x030, 0x00060001}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x030, 0x000085ED}, {0x030, 0x000105CC}, @@ -16582,11 +18224,255 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x0EF, 0x00000000}, {0x06E, 0x00077A18}, {0x06D, 0x00000C31}, + {0x80010000, 0x00000000}, {0x40000000, 0x00000000}, + {0x06A, 0x000E0F8A}, + {0x06B, 0x000018A0}, + {0x06F, 0x000F81FC}, + {0x90020000, 0x00000000}, {0x40000000, 0x00000000}, + {0x06A, 0x000E0F8A}, + {0x06B, 0x000018A0}, + {0x06F, 0x000F81FC}, + {0x90320000, 0x00000000}, {0x40000000, 0x00000000}, + {0x06A, 0x000E0F8A}, + {0x06B, 0x000018A0}, + {0x06F, 0x000F81FC}, + {0x90330000, 0x00000000}, {0x40000000, 0x00000000}, + {0x06A, 0x000E0F8A}, + {0x06B, 0x000018A0}, + {0x06F, 0x000F81FC}, + {0x90340000, 0x00000000}, {0x40000000, 0x00000000}, {0x06A, 0x000E0F8A}, {0x06B, 0x000018A0}, {0x06F, 0x000F81FC}, + {0x90350000, 0x00000000}, {0x40000000, 0x00000000}, + {0x06A, 0x000E0F8A}, + {0x06B, 0x000018A0}, + {0x06F, 0x000F81FC}, + {0x90360000, 0x00000000}, {0x40000000, 0x00000000}, + {0x06A, 0x000E0F8A}, + {0x06B, 0x000018A0}, + {0x06F, 0x000F81FC}, + {0x90010001, 0x00000000}, {0x40000000, 0x00000000}, + {0x06A, 0x000E0F8A}, + {0x06B, 0x000018A0}, + {0x06F, 0x000F81FC}, + {0x90020001, 0x00000000}, {0x40000000, 0x00000000}, + {0x06A, 0x000E0F8A}, + {0x06B, 0x000018A0}, + {0x06F, 0x000F81FC}, + {0x90030001, 0x00000000}, {0x40000000, 0x00000000}, + {0x06A, 0x000E0F8A}, + {0x06B, 0x000018A0}, + {0x06F, 0x000F81FC}, + {0x90040001, 0x00000000}, {0x40000000, 0x00000000}, + {0x06A, 0x000E0F8A}, + {0x06B, 0x000018A0}, + {0x06F, 0x000F81FC}, + {0x90050001, 0x00000000}, {0x40000000, 0x00000000}, + {0x06A, 0x000E0F8A}, + {0x06B, 0x000018A0}, + {0x06F, 0x000F81FC}, + {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, + {0x06A, 0x000E0F8A}, + {0x06B, 0x000018A0}, + {0x06F, 0x000F81FC}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x06A, 0x000E0380}, + {0x06B, 0x00003CA0}, + {0x06F, 0x000C01FC}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x06A, 0x000E0380}, + {0x06B, 0x00003CA0}, + {0x06F, 0x000C01FC}, + {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, + {0x06A, 0x000E0F8A}, + {0x06B, 0x000018A0}, + {0x06F, 0x000F81FC}, + {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, + {0x06A, 0x000E0F8A}, + {0x06B, 0x000018A0}, + {0x06F, 0x000F81FC}, + {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, + {0x06A, 0x000E0F8A}, + {0x06B, 0x000018A0}, + {0x06F, 0x000F81FC}, + {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, + {0x06A, 0x000E0F8A}, + {0x06B, 0x000018A0}, + {0x06F, 0x000F81FC}, + {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, + {0x06A, 0x000E0F8A}, + {0x06B, 0x000018A0}, + {0x06F, 0x000F81FC}, + {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, + {0x06A, 0x000E0F8A}, + {0x06B, 0x000018A0}, + {0x06F, 0x000F81FC}, + {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, + {0x06A, 0x000E0F8A}, + {0x06B, 0x000018A0}, + {0x06F, 0x000F81FC}, + {0xA0000000, 0x00000000}, + {0x06A, 0x000E0F8A}, + {0x06B, 0x000018A0}, + {0x06F, 0x000F81FC}, + {0xB0000000, 0x00000000}, {0x05E, 0x0000001F}, {0x0EF, 0x00000200}, + {0x80010000, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x0003D407}, + {0x030, 0x00035A87}, + {0x030, 0x0002CF07}, + {0x030, 0x00024F07}, + {0x030, 0x0001CF07}, + {0x030, 0x00014F07}, + {0x030, 0x0000CF07}, + {0x030, 0x00004F07}, + {0x90020000, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x0003D407}, + {0x030, 0x00035A87}, + {0x030, 0x0002CF07}, + {0x030, 0x00024F07}, + {0x030, 0x0001CF07}, + {0x030, 0x00014F07}, + {0x030, 0x0000CF07}, + {0x030, 0x00004F07}, + {0x90320000, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x0003D407}, + {0x030, 0x00035A87}, + {0x030, 0x0002CF07}, + {0x030, 0x00024F07}, + {0x030, 0x0001CF07}, + {0x030, 0x00014F07}, + {0x030, 0x0000CF07}, + {0x030, 0x00004F07}, + {0x90330000, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x0003D407}, + {0x030, 0x00035A87}, + {0x030, 0x0002CF07}, + {0x030, 0x00024F07}, + {0x030, 0x0001CF07}, + {0x030, 0x00014F07}, + {0x030, 0x0000CF07}, + {0x030, 0x00004F07}, + {0x90340000, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x0003D407}, + {0x030, 0x00035A87}, + {0x030, 0x0002CF07}, + {0x030, 0x00024F07}, + {0x030, 0x0001CF07}, + {0x030, 0x00014F07}, + {0x030, 0x0000CF07}, + {0x030, 0x00004F07}, + {0x90350000, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x0003D407}, + {0x030, 0x00035A87}, + {0x030, 0x0002CF07}, + {0x030, 0x00024F07}, + {0x030, 0x0001CF07}, + {0x030, 0x00014F07}, + {0x030, 0x0000CF07}, + {0x030, 0x00004F07}, + {0x90360000, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x0003D407}, + {0x030, 0x00035A87}, + {0x030, 0x0002CF07}, + {0x030, 0x00024F07}, + {0x030, 0x0001CF07}, + {0x030, 0x00014F07}, + {0x030, 0x0000CF07}, + {0x030, 0x00004F07}, + {0x90010001, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x0003D407}, + {0x030, 0x00035A87}, + {0x030, 0x0002CF07}, + {0x030, 0x00024F07}, + {0x030, 0x0001CF07}, + {0x030, 0x00014F07}, + {0x030, 0x0000CF07}, + {0x030, 0x00004F07}, + {0x90020001, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x0003D407}, + {0x030, 0x00035A87}, + {0x030, 0x0002CF07}, + {0x030, 0x00024F07}, + {0x030, 0x0001CF07}, + {0x030, 0x00014F07}, + {0x030, 0x0000CF07}, + {0x030, 0x00004F07}, + {0x90030001, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x0003D407}, + {0x030, 0x00035A87}, + {0x030, 0x0002CF07}, + {0x030, 0x00024F07}, + {0x030, 0x0001CF07}, + {0x030, 0x00014F07}, + {0x030, 0x0000CF07}, + {0x030, 0x00004F07}, + {0x90040001, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x0003D407}, + {0x030, 0x00035A87}, + {0x030, 0x0002CF07}, + {0x030, 0x00024F07}, + {0x030, 0x0001CF07}, + {0x030, 0x00014F07}, + {0x030, 0x0000CF07}, + {0x030, 0x00004F07}, + {0x90050001, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x0003D407}, + {0x030, 0x00035A87}, + {0x030, 0x0002CF07}, + {0x030, 0x00024F07}, + {0x030, 0x0001CF07}, + {0x030, 0x00014F07}, + {0x030, 0x0000CF07}, + {0x030, 0x00004F07}, + {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x0003D407}, + {0x030, 0x00035A87}, + {0x030, 0x0002CF07}, + {0x030, 0x00024F07}, + {0x030, 0x0001CF07}, + {0x030, 0x00014F07}, + {0x030, 0x0000CF07}, + {0x030, 0x00004F07}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x0003E207}, + {0x030, 0x0003E207}, + {0x030, 0x0003E207}, + {0x030, 0x0003E207}, + {0x030, 0x0003E207}, + {0x030, 0x0003E207}, + {0x030, 0x0003E207}, + {0x030, 0x0003E207}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x0003E207}, + {0x030, 0x0003E207}, + {0x030, 0x0003E207}, + {0x030, 0x0003E207}, + {0x030, 0x0003E207}, + {0x030, 0x0003E207}, + {0x030, 0x0003E207}, + {0x030, 0x0003E207}, + {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x0003D407}, + {0x030, 0x00035A87}, + {0x030, 0x0002CF07}, + {0x030, 0x00024F07}, + {0x030, 0x0001CF07}, + {0x030, 0x00014F07}, + {0x030, 0x0000CF07}, + {0x030, 0x00004F07}, + {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x0003D407}, + {0x030, 0x00035A87}, + {0x030, 0x0002CF07}, + {0x030, 0x00024F07}, + {0x030, 0x0001CF07}, + {0x030, 0x00014F07}, + {0x030, 0x0000CF07}, + {0x030, 0x00004F07}, + {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, {0x030, 0x0003D407}, {0x030, 0x00035A87}, {0x030, 0x0002CF07}, @@ -16595,14 +18481,216 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x030, 0x00014F07}, {0x030, 0x0000CF07}, {0x030, 0x00004F07}, + {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x0003D407}, + {0x030, 0x00035A87}, + {0x030, 0x0002CF07}, + {0x030, 0x00024F07}, + {0x030, 0x0001CF07}, + {0x030, 0x00014F07}, + {0x030, 0x0000CF07}, + {0x030, 0x00004F07}, + {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x0003D407}, + {0x030, 0x00035A87}, + {0x030, 0x0002CF07}, + {0x030, 0x00024F07}, + {0x030, 0x0001CF07}, + {0x030, 0x00014F07}, + {0x030, 0x0000CF07}, + {0x030, 0x00004F07}, + {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x0003D407}, + {0x030, 0x00035A87}, + {0x030, 0x0002CF07}, + {0x030, 0x00024F07}, + {0x030, 0x0001CF07}, + {0x030, 0x00014F07}, + {0x030, 0x0000CF07}, + {0x030, 0x00004F07}, + {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x0003D407}, + {0x030, 0x00035A87}, + {0x030, 0x0002CF07}, + {0x030, 0x00024F07}, + {0x030, 0x0001CF07}, + {0x030, 0x00014F07}, + {0x030, 0x0000CF07}, + {0x030, 0x00004F07}, + {0xA0000000, 0x00000000}, + {0x030, 0x0003D407}, + {0x030, 0x00035A87}, + {0x030, 0x0002CF07}, + {0x030, 0x00024F07}, + {0x030, 0x0001CF07}, + {0x030, 0x00014F07}, + {0x030, 0x0000CF07}, + {0x030, 0x00004F07}, + {0xB0000000, 0x00000000}, {0x0EF, 0x00000000}, {0x0EB, 0x00080000}, + {0x80010000, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x00008038}, + {0x030, 0x00010038}, + {0x030, 0x00018038}, + {0x030, 0x00020038}, + {0x030, 0x00028038}, + {0x030, 0x00030038}, + {0x90020000, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x00008038}, + {0x030, 0x00010038}, + {0x030, 0x00018038}, + {0x030, 0x00020038}, + {0x030, 0x00028038}, + {0x030, 0x00030038}, + {0x90320000, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x00008038}, + {0x030, 0x00010038}, + {0x030, 0x00018038}, + {0x030, 0x00020038}, + {0x030, 0x00028038}, + {0x030, 0x00030038}, + {0x90330000, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x00008038}, + {0x030, 0x00010038}, + {0x030, 0x00018038}, + {0x030, 0x00020038}, + {0x030, 0x00028038}, + {0x030, 0x00030038}, + {0x90340000, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x00008038}, + {0x030, 0x00010038}, + {0x030, 0x00018038}, + {0x030, 0x00020038}, + {0x030, 0x00028038}, + {0x030, 0x00030038}, + {0x90350000, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x00008038}, + {0x030, 0x00010038}, + {0x030, 0x00018038}, + {0x030, 0x00020038}, + {0x030, 0x00028038}, + {0x030, 0x00030038}, + {0x90360000, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x00008038}, + {0x030, 0x00010038}, + {0x030, 0x00018038}, + {0x030, 0x00020038}, + {0x030, 0x00028038}, + {0x030, 0x00030038}, + {0x90010001, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x00008038}, + {0x030, 0x00010038}, + {0x030, 0x00018038}, + {0x030, 0x00020038}, + {0x030, 0x00028038}, + {0x030, 0x00030038}, + {0x90020001, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x00008038}, + {0x030, 0x00010038}, + {0x030, 0x00018038}, + {0x030, 0x00020038}, + {0x030, 0x00028038}, + {0x030, 0x00030038}, + {0x90030001, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x00008038}, + {0x030, 0x00010038}, + {0x030, 0x00018038}, + {0x030, 0x00020038}, + {0x030, 0x00028038}, + {0x030, 0x00030038}, + {0x90040001, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x00008038}, + {0x030, 0x00010038}, + {0x030, 0x00018038}, + {0x030, 0x00020038}, + {0x030, 0x00028038}, + {0x030, 0x00030038}, + {0x90050001, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x00008038}, + {0x030, 0x00010038}, + {0x030, 0x00018038}, + {0x030, 0x00020038}, + {0x030, 0x00028038}, + {0x030, 0x00030038}, + {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x00008038}, + {0x030, 0x00010038}, + {0x030, 0x00018038}, + {0x030, 0x00020038}, + {0x030, 0x00028038}, + {0x030, 0x00030038}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x0000803C}, + {0x030, 0x0001003C}, + {0x030, 0x0001803C}, + {0x030, 0x0002003C}, + {0x030, 0x0002803C}, + {0x030, 0x0003003C}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x0000803C}, + {0x030, 0x0001003C}, + {0x030, 0x0001803C}, + {0x030, 0x0002003C}, + {0x030, 0x0002803C}, + {0x030, 0x0003003C}, + {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x030, 0x00008038}, {0x030, 0x00010038}, {0x030, 0x00018038}, {0x030, 0x00020038}, {0x030, 0x00028038}, {0x030, 0x00030038}, + {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x00008038}, + {0x030, 0x00010038}, + {0x030, 0x00018038}, + {0x030, 0x00020038}, + {0x030, 0x00028038}, + {0x030, 0x00030038}, + {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x00008038}, + {0x030, 0x00010038}, + {0x030, 0x00018038}, + {0x030, 0x00020038}, + {0x030, 0x00028038}, + {0x030, 0x00030038}, + {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x00008038}, + {0x030, 0x00010038}, + {0x030, 0x00018038}, + {0x030, 0x00020038}, + {0x030, 0x00028038}, + {0x030, 0x00030038}, + {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x00008038}, + {0x030, 0x00010038}, + {0x030, 0x00018038}, + {0x030, 0x00020038}, + {0x030, 0x00028038}, + {0x030, 0x00030038}, + {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x00008038}, + {0x030, 0x00010038}, + {0x030, 0x00018038}, + {0x030, 0x00020038}, + {0x030, 0x00028038}, + {0x030, 0x00030038}, + {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x00008038}, + {0x030, 0x00010038}, + {0x030, 0x00018038}, + {0x030, 0x00020038}, + {0x030, 0x00028038}, + {0x030, 0x00030038}, + {0xA0000000, 0x00000000}, + {0x030, 0x00008038}, + {0x030, 0x00010038}, + {0x030, 0x00018038}, + {0x030, 0x00020038}, + {0x030, 0x00028038}, + {0x030, 0x00030038}, + {0xB0000000, 0x00000000}, {0x030, 0x0003803C}, {0x030, 0x0004003C}, {0x030, 0x0004803C}, @@ -16639,6 +18727,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x095, 0x00000008}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x095, 0x00000008}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x095, 0x00000008}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x095, 0x00000008}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x095, 0x00000008}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -16684,6 +18776,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000152}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000152}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000152}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000152}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000152}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -16728,6 +18824,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x0000015A}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000015A}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000015A}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000015A}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000015A}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -16772,6 +18872,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x0000019C}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000019C}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000019C}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000019C}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000019C}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -16816,6 +18920,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x000001A4}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001A4}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001A4}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001A4}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001A4}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -16860,6 +18968,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x000001E6}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001E6}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001E6}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001E6}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001E6}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -16904,6 +19016,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x000002E6}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E6}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E6}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E6}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E6}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -16948,6 +19064,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x000002E7}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E7}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E7}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E7}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E7}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -16992,6 +19112,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x000003E7}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000003E7}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000003E7}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000003E7}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000003E7}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -17036,6 +19160,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000152}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000152}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000152}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000152}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000152}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -17080,6 +19208,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x0000015A}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000015A}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000015A}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000015A}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000015A}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -17124,6 +19256,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x0000019C}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000019C}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000019C}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000019C}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000019C}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -17168,6 +19304,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x000001A4}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001A4}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001A4}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001A4}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001A4}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -17212,6 +19352,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x000001E6}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001E6}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001E6}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001E6}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001E6}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -17256,6 +19400,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x000002E6}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E6}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E6}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E6}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E6}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -17300,6 +19448,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x000002E7}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E7}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E7}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E7}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E7}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -17344,6 +19496,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x000003E7}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000003E7}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000003E7}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000003E7}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000003E7}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -17388,6 +19544,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000152}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000152}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000152}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000152}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000152}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -17432,6 +19592,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x0000015A}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000015A}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000015A}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000015A}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000015A}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -17476,6 +19640,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x0000019C}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000019C}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000019C}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000019C}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000019C}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -17520,6 +19688,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x000001A4}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001A4}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001A4}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001A4}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001A4}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -17564,6 +19736,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x000001E6}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001E6}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001E6}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001E6}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001E6}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -17608,6 +19784,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x000002E6}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E6}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E6}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E6}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E6}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -17652,6 +19832,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x000002E7}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E7}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E7}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E7}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E7}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -17696,6 +19880,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x000003E7}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000003E7}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000003E7}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000003E7}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000003E7}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -17740,20 +19928,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000152}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000152}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000152}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000152}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000152}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0xA0000000, 0x00000000}, {0x03F, 0x00000052}, {0xB0000000, 0x00000000}, @@ -17784,20 +19976,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x0000015A}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000015A}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000015A}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000015A}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000015A}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0xA0000000, 0x00000000}, {0x03F, 0x0000005A}, {0xB0000000, 0x00000000}, @@ -17828,20 +20024,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x0000019C}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000019C}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000019C}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000019C}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000019C}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0xA0000000, 0x00000000}, {0x03F, 0x0000009C}, {0xB0000000, 0x00000000}, @@ -17872,20 +20072,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x000001A4}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001A4}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001A4}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001A4}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001A4}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0xA0000000, 0x00000000}, {0x03F, 0x0000019C}, {0xB0000000, 0x00000000}, @@ -17916,20 +20120,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x000001E6}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001E6}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001E6}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001E6}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001E6}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0xA0000000, 0x00000000}, {0x03F, 0x000001A4}, {0xB0000000, 0x00000000}, @@ -17960,20 +20168,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x000002E6}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E6}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E6}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E6}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E6}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0xA0000000, 0x00000000}, {0x03F, 0x000001E6}, {0xB0000000, 0x00000000}, @@ -18004,20 +20216,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x000002E7}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E7}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E7}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E7}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E7}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000002E6}, + {0x03F, 0x000002E7}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000002E6}, + {0x03F, 0x000002E7}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000002E6}, + {0x03F, 0x000002E7}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000002E6}, + {0x03F, 0x000002E7}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000002E6}, + {0x03F, 0x000002E7}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000002E6}, + {0x03F, 0x000002E7}, {0xA0000000, 0x00000000}, {0x03F, 0x000002E6}, {0xB0000000, 0x00000000}, @@ -18048,20 +20264,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x000003E7}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000003E7}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000003E7}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000003E7}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000003E7}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000003E6}, + {0x03F, 0x000003E7}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000003E6}, + {0x03F, 0x000003E7}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000003E6}, + {0x03F, 0x000003E7}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000003E6}, + {0x03F, 0x000003E7}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000003E6}, + {0x03F, 0x000003E7}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000003E6}, + {0x03F, 0x000003E7}, {0xA0000000, 0x00000000}, {0x03F, 0x000003E6}, {0xB0000000, 0x00000000}, @@ -18092,20 +20312,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000152}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000152}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000152}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000152}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000152}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0xA0000000, 0x00000000}, {0x03F, 0x00000052}, {0xB0000000, 0x00000000}, @@ -18136,20 +20360,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x0000015A}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000015A}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000015A}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000015A}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000015A}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0xA0000000, 0x00000000}, {0x03F, 0x0000005A}, {0xB0000000, 0x00000000}, @@ -18180,20 +20408,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x0000019C}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000019C}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000019C}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000019C}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000019C}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0xA0000000, 0x00000000}, {0x03F, 0x0000009C}, {0xB0000000, 0x00000000}, @@ -18224,20 +20456,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x000001A4}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001A4}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001A4}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001A4}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001A4}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0xA0000000, 0x00000000}, {0x03F, 0x0000019C}, {0xB0000000, 0x00000000}, @@ -18268,20 +20504,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x000001E6}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001E6}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001E6}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001E6}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001E6}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0xA0000000, 0x00000000}, {0x03F, 0x000001A4}, {0xB0000000, 0x00000000}, @@ -18312,20 +20552,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x000002E6}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E6}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E6}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E6}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E6}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0xA0000000, 0x00000000}, {0x03F, 0x000001E6}, {0xB0000000, 0x00000000}, @@ -18356,20 +20600,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x000002E7}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E7}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E7}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E7}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E7}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000002E6}, + {0x03F, 0x000002E7}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000002E6}, + {0x03F, 0x000002E7}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000002E6}, + {0x03F, 0x000002E7}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000002E6}, + {0x03F, 0x000002E7}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000002E6}, + {0x03F, 0x000002E7}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000002E6}, + {0x03F, 0x000002E7}, {0xA0000000, 0x00000000}, {0x03F, 0x000002E6}, {0xB0000000, 0x00000000}, @@ -18400,20 +20648,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x000003E7}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000003E7}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000003E7}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000003E7}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000003E7}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000003E6}, + {0x03F, 0x000003E7}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000003E6}, + {0x03F, 0x000003E7}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000003E6}, + {0x03F, 0x000003E7}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000003E6}, + {0x03F, 0x000003E7}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000003E6}, + {0x03F, 0x000003E7}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000003E6}, + {0x03F, 0x000003E7}, {0xA0000000, 0x00000000}, {0x03F, 0x000003E6}, {0xB0000000, 0x00000000}, @@ -18444,20 +20696,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000152}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000152}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000152}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000152}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000152}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0xA0000000, 0x00000000}, {0x03F, 0x00000052}, {0xB0000000, 0x00000000}, @@ -18488,20 +20744,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x0000015A}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000015A}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000015A}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000015A}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000015A}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0xA0000000, 0x00000000}, {0x03F, 0x0000005A}, {0xB0000000, 0x00000000}, @@ -18532,20 +20792,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x0000019C}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000019C}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000019C}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000019C}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000019C}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0xA0000000, 0x00000000}, {0x03F, 0x0000009C}, {0xB0000000, 0x00000000}, @@ -18576,20 +20840,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x000001A4}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001A4}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001A4}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001A4}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001A4}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0xA0000000, 0x00000000}, {0x03F, 0x0000019C}, {0xB0000000, 0x00000000}, @@ -18620,20 +20888,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x000001E6}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001E6}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001E6}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001E6}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001E6}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0xA0000000, 0x00000000}, {0x03F, 0x000001A4}, {0xB0000000, 0x00000000}, @@ -18664,20 +20936,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x000002E6}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E6}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E6}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E6}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E6}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0xA0000000, 0x00000000}, {0x03F, 0x000001E6}, {0xB0000000, 0x00000000}, @@ -18708,20 +20984,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x000002E7}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E7}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E7}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E7}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E7}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000002E6}, + {0x03F, 0x000002E7}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000002E6}, + {0x03F, 0x000002E7}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000002E6}, + {0x03F, 0x000002E7}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000002E6}, + {0x03F, 0x000002E7}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000002E6}, + {0x03F, 0x000002E7}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000002E6}, + {0x03F, 0x000002E7}, {0xA0000000, 0x00000000}, {0x03F, 0x000002E6}, {0xB0000000, 0x00000000}, @@ -18752,20 +21032,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x000003E7}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000003E7}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000003E7}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000003E7}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000003E7}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000003E6}, + {0x03F, 0x000003E7}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000003E6}, + {0x03F, 0x000003E7}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000003E6}, + {0x03F, 0x000003E7}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000003E6}, + {0x03F, 0x000003E7}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000003E6}, + {0x03F, 0x000003E7}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000003E6}, + {0x03F, 0x000003E7}, {0xA0000000, 0x00000000}, {0x03F, 0x000003E6}, {0xB0000000, 0x00000000}, @@ -18796,20 +21080,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000152}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000152}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000152}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000152}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000152}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0xA0000000, 0x00000000}, {0x03F, 0x00000052}, {0xB0000000, 0x00000000}, @@ -18840,20 +21128,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x0000015A}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000015A}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000015A}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000015A}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000015A}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0xA0000000, 0x00000000}, {0x03F, 0x0000005A}, {0xB0000000, 0x00000000}, @@ -18884,20 +21176,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x0000019C}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000019C}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000019C}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000019C}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000019C}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0xA0000000, 0x00000000}, {0x03F, 0x0000009C}, {0xB0000000, 0x00000000}, @@ -18928,20 +21224,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x000001A4}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001A4}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001A4}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001A4}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001A4}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0xA0000000, 0x00000000}, {0x03F, 0x0000019C}, {0xB0000000, 0x00000000}, @@ -18972,20 +21272,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x000001E6}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001E6}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001E6}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001E6}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001E6}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0xA0000000, 0x00000000}, {0x03F, 0x000001A4}, {0xB0000000, 0x00000000}, @@ -19016,20 +21320,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x000002E6}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E6}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E6}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E6}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E6}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0xA0000000, 0x00000000}, {0x03F, 0x000001E6}, {0xB0000000, 0x00000000}, @@ -20199,7 +22507,297 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x10030, 0x0007BC1D}, {0x10030, 0x0007C017}, {0x10030, 0x0007C40F}, - {0x90020001, 0x00000000}, {0x40000000, 0x00000000}, + {0x90020001, 0x00000000}, {0x40000000, 0x00000000}, + {0x10030, 0x000001EF}, + {0x10030, 0x000005E9}, + {0x10030, 0x000009E3}, + {0x10030, 0x00000DDD}, + {0x10030, 0x000011D7}, + {0x10030, 0x0000159F}, + {0x10030, 0x00001999}, + {0x10030, 0x00001D5F}, + {0x10030, 0x00002159}, + {0x10030, 0x0000251F}, + {0x10030, 0x00002919}, + {0x10030, 0x00002CDF}, + {0x10030, 0x000030D9}, + {0x10030, 0x0000349F}, + {0x10030, 0x00003899}, + {0x10030, 0x00003C5F}, + {0x10030, 0x00004059}, + {0x10030, 0x00004453}, + {0x10030, 0x000201EF}, + {0x10030, 0x000205E9}, + {0x10030, 0x000209E3}, + {0x10030, 0x00020DA3}, + {0x10030, 0x00021161}, + {0x10030, 0x0002155B}, + {0x10030, 0x0002191F}, + {0x10030, 0x00021D19}, + {0x10030, 0x000220E1}, + {0x10030, 0x000224DB}, + {0x10030, 0x000228A3}, + {0x10030, 0x00022C9D}, + {0x10030, 0x00023063}, + {0x10030, 0x0002345D}, + {0x10030, 0x00023823}, + {0x10030, 0x00023C1B}, + {0x10030, 0x00024015}, + {0x10030, 0x0002440F}, + {0x10030, 0x000281EF}, + {0x10030, 0x000285E7}, + {0x10030, 0x000289A7}, + {0x10030, 0x00028D65}, + {0x10030, 0x0002915F}, + {0x10030, 0x00029523}, + {0x10030, 0x0002991D}, + {0x10030, 0x00029CE5}, + {0x10030, 0x0002A0DF}, + {0x10030, 0x0002A4A7}, + {0x10030, 0x0002A8A1}, + {0x10030, 0x0002AC67}, + {0x10030, 0x0002B061}, + {0x10030, 0x0002B427}, + {0x10030, 0x0002B821}, + {0x10030, 0x0002BC19}, + {0x10030, 0x0002C013}, + {0x10030, 0x0002C40D}, + {0x10030, 0x000301EF}, + {0x10030, 0x000305E7}, + {0x10030, 0x000309A7}, + {0x10030, 0x00030D65}, + {0x10030, 0x0003115F}, + {0x10030, 0x00031525}, + {0x10030, 0x0003191F}, + {0x10030, 0x00031CE7}, + {0x10030, 0x000320E1}, + {0x10030, 0x000324A9}, + {0x10030, 0x000328A3}, + {0x10030, 0x00032C69}, + {0x10030, 0x00033063}, + {0x10030, 0x00033429}, + {0x10030, 0x00033823}, + {0x10030, 0x00033C1D}, + {0x10030, 0x00034013}, + {0x10030, 0x0003440D}, + {0x10030, 0x000601F1}, + {0x10030, 0x000605E9}, + {0x10030, 0x000609A9}, + {0x10030, 0x00060D65}, + {0x10030, 0x0006115F}, + {0x10030, 0x00061525}, + {0x10030, 0x0006191F}, + {0x10030, 0x00061CE7}, + {0x10030, 0x000620E1}, + {0x10030, 0x000624DB}, + {0x10030, 0x000628A3}, + {0x10030, 0x00062C69}, + {0x10030, 0x00063063}, + {0x10030, 0x00063429}, + {0x10030, 0x00063823}, + {0x10030, 0x00063C1D}, + {0x10030, 0x00064013}, + {0x10030, 0x0006440D}, + {0x10030, 0x000681EF}, + {0x10030, 0x000685E7}, + {0x10030, 0x000689A7}, + {0x10030, 0x00068D61}, + {0x10030, 0x0006915B}, + {0x10030, 0x00069523}, + {0x10030, 0x0006991D}, + {0x10030, 0x00069CE5}, + {0x10030, 0x0006A0DF}, + {0x10030, 0x0006A4A7}, + {0x10030, 0x0006A8A1}, + {0x10030, 0x0006AC67}, + {0x10030, 0x0006B061}, + {0x10030, 0x0006B429}, + {0x10030, 0x0006B823}, + {0x10030, 0x0006BC1D}, + {0x10030, 0x0006C017}, + {0x10030, 0x0006C40D}, + {0x10030, 0x000701F1}, + {0x10030, 0x000705E9}, + {0x10030, 0x000709A9}, + {0x10030, 0x00070D63}, + {0x10030, 0x0007115D}, + {0x10030, 0x00071523}, + {0x10030, 0x0007191D}, + {0x10030, 0x00071D17}, + {0x10030, 0x00072111}, + {0x10030, 0x000724D9}, + {0x10030, 0x000728D3}, + {0x10030, 0x00072C67}, + {0x10030, 0x00073061}, + {0x10030, 0x00073427}, + {0x10030, 0x00073821}, + {0x10030, 0x00073C1B}, + {0x10030, 0x00074015}, + {0x10030, 0x0007440D}, + {0x10030, 0x000781F1}, + {0x10030, 0x000785EB}, + {0x10030, 0x000789E5}, + {0x10030, 0x00078DA3}, + {0x10030, 0x00079161}, + {0x10030, 0x0007955B}, + {0x10030, 0x00079923}, + {0x10030, 0x00079D1D}, + {0x10030, 0x0007A117}, + {0x10030, 0x0007A4DD}, + {0x10030, 0x0007A8D7}, + {0x10030, 0x0007AC9D}, + {0x10030, 0x0007B063}, + {0x10030, 0x0007B45D}, + {0x10030, 0x0007B857}, + {0x10030, 0x0007BC1D}, + {0x10030, 0x0007C017}, + {0x10030, 0x0007C40F}, + {0x90030001, 0x00000000}, {0x40000000, 0x00000000}, + {0x10030, 0x000001EF}, + {0x10030, 0x000005E9}, + {0x10030, 0x000009E3}, + {0x10030, 0x00000DDD}, + {0x10030, 0x000011D7}, + {0x10030, 0x0000159F}, + {0x10030, 0x00001999}, + {0x10030, 0x00001D5F}, + {0x10030, 0x00002159}, + {0x10030, 0x0000251F}, + {0x10030, 0x00002919}, + {0x10030, 0x00002CDF}, + {0x10030, 0x000030D9}, + {0x10030, 0x0000349F}, + {0x10030, 0x00003899}, + {0x10030, 0x00003C5F}, + {0x10030, 0x00004059}, + {0x10030, 0x00004453}, + {0x10030, 0x000201EF}, + {0x10030, 0x000205E9}, + {0x10030, 0x000209E3}, + {0x10030, 0x00020DA3}, + {0x10030, 0x00021161}, + {0x10030, 0x0002155B}, + {0x10030, 0x0002191F}, + {0x10030, 0x00021D19}, + {0x10030, 0x000220E1}, + {0x10030, 0x000224DB}, + {0x10030, 0x000228A3}, + {0x10030, 0x00022C9D}, + {0x10030, 0x00023063}, + {0x10030, 0x0002345D}, + {0x10030, 0x00023823}, + {0x10030, 0x00023C1B}, + {0x10030, 0x00024015}, + {0x10030, 0x0002440F}, + {0x10030, 0x000281EF}, + {0x10030, 0x000285E7}, + {0x10030, 0x000289A7}, + {0x10030, 0x00028D65}, + {0x10030, 0x0002915F}, + {0x10030, 0x00029523}, + {0x10030, 0x0002991D}, + {0x10030, 0x00029CE5}, + {0x10030, 0x0002A0DF}, + {0x10030, 0x0002A4A7}, + {0x10030, 0x0002A8A1}, + {0x10030, 0x0002AC67}, + {0x10030, 0x0002B061}, + {0x10030, 0x0002B427}, + {0x10030, 0x0002B821}, + {0x10030, 0x0002BC19}, + {0x10030, 0x0002C013}, + {0x10030, 0x0002C40D}, + {0x10030, 0x000301EF}, + {0x10030, 0x000305E7}, + {0x10030, 0x000309A7}, + {0x10030, 0x00030D65}, + {0x10030, 0x0003115F}, + {0x10030, 0x00031525}, + {0x10030, 0x0003191F}, + {0x10030, 0x00031CE7}, + {0x10030, 0x000320E1}, + {0x10030, 0x000324A9}, + {0x10030, 0x000328A3}, + {0x10030, 0x00032C69}, + {0x10030, 0x00033063}, + {0x10030, 0x00033429}, + {0x10030, 0x00033823}, + {0x10030, 0x00033C1D}, + {0x10030, 0x00034013}, + {0x10030, 0x0003440D}, + {0x10030, 0x000601F1}, + {0x10030, 0x000605E9}, + {0x10030, 0x000609A9}, + {0x10030, 0x00060D65}, + {0x10030, 0x0006115F}, + {0x10030, 0x00061525}, + {0x10030, 0x0006191F}, + {0x10030, 0x00061CE7}, + {0x10030, 0x000620E1}, + {0x10030, 0x000624DB}, + {0x10030, 0x000628A3}, + {0x10030, 0x00062C69}, + {0x10030, 0x00063063}, + {0x10030, 0x00063429}, + {0x10030, 0x00063823}, + {0x10030, 0x00063C1D}, + {0x10030, 0x00064013}, + {0x10030, 0x0006440D}, + {0x10030, 0x000681EF}, + {0x10030, 0x000685E7}, + {0x10030, 0x000689A7}, + {0x10030, 0x00068D61}, + {0x10030, 0x0006915B}, + {0x10030, 0x00069523}, + {0x10030, 0x0006991D}, + {0x10030, 0x00069CE5}, + {0x10030, 0x0006A0DF}, + {0x10030, 0x0006A4A7}, + {0x10030, 0x0006A8A1}, + {0x10030, 0x0006AC67}, + {0x10030, 0x0006B061}, + {0x10030, 0x0006B429}, + {0x10030, 0x0006B823}, + {0x10030, 0x0006BC1D}, + {0x10030, 0x0006C017}, + {0x10030, 0x0006C40D}, + {0x10030, 0x000701F1}, + {0x10030, 0x000705E9}, + {0x10030, 0x000709A9}, + {0x10030, 0x00070D63}, + {0x10030, 0x0007115D}, + {0x10030, 0x00071523}, + {0x10030, 0x0007191D}, + {0x10030, 0x00071D17}, + {0x10030, 0x00072111}, + {0x10030, 0x000724D9}, + {0x10030, 0x000728D3}, + {0x10030, 0x00072C67}, + {0x10030, 0x00073061}, + {0x10030, 0x00073427}, + {0x10030, 0x00073821}, + {0x10030, 0x00073C1B}, + {0x10030, 0x00074015}, + {0x10030, 0x0007440D}, + {0x10030, 0x000781F1}, + {0x10030, 0x000785EB}, + {0x10030, 0x000789E5}, + {0x10030, 0x00078DA3}, + {0x10030, 0x00079161}, + {0x10030, 0x0007955B}, + {0x10030, 0x00079923}, + {0x10030, 0x00079D1D}, + {0x10030, 0x0007A117}, + {0x10030, 0x0007A4DD}, + {0x10030, 0x0007A8D7}, + {0x10030, 0x0007AC9D}, + {0x10030, 0x0007B063}, + {0x10030, 0x0007B45D}, + {0x10030, 0x0007B857}, + {0x10030, 0x0007BC1D}, + {0x10030, 0x0007C017}, + {0x10030, 0x0007C40F}, + {0x90040001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x000001EF}, {0x10030, 0x000005E9}, {0x10030, 0x000009E3}, @@ -20344,7 +22942,7 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x10030, 0x0007BC1D}, {0x10030, 0x0007C017}, {0x10030, 0x0007C40F}, - {0x90030001, 0x00000000}, {0x40000000, 0x00000000}, + {0x90050001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x000001EF}, {0x10030, 0x000005E9}, {0x10030, 0x000009E3}, @@ -20489,7 +23087,7 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x10030, 0x0007BC1D}, {0x10030, 0x0007C017}, {0x10030, 0x0007C40F}, - {0x90040001, 0x00000000}, {0x40000000, 0x00000000}, + {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x000001EF}, {0x10030, 0x000005E9}, {0x10030, 0x000009E3}, @@ -20634,7 +23232,7 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x10030, 0x0007BC1D}, {0x10030, 0x0007C017}, {0x10030, 0x0007C40F}, - {0x90050001, 0x00000000}, {0x40000000, 0x00000000}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x000001EF}, {0x10030, 0x000005E9}, {0x10030, 0x000009E3}, @@ -20779,7 +23377,7 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x10030, 0x0007BC1D}, {0x10030, 0x0007C017}, {0x10030, 0x0007C40F}, - {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x000001EF}, {0x10030, 0x000005E9}, {0x10030, 0x000009E3}, @@ -21147,73 +23745,73 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x10030, 0x000609A9}, {0x10030, 0x00060D65}, {0x10030, 0x0006115F}, - {0x10030, 0x00061525}, - {0x10030, 0x0006191F}, - {0x10030, 0x00061CE7}, - {0x10030, 0x000620E1}, - {0x10030, 0x000624DB}, - {0x10030, 0x000628A3}, - {0x10030, 0x00062C69}, - {0x10030, 0x00063063}, - {0x10030, 0x00063429}, - {0x10030, 0x00063823}, - {0x10030, 0x00063C1D}, - {0x10030, 0x00064013}, - {0x10030, 0x0006440D}, + {0x10030, 0x00061527}, + {0x10030, 0x00061921}, + {0x10030, 0x00061CE9}, + {0x10030, 0x000620E3}, + {0x10030, 0x000624DD}, + {0x10030, 0x000628A5}, + {0x10030, 0x00062C6B}, + {0x10030, 0x00063065}, + {0x10030, 0x0006342B}, + {0x10030, 0x00063825}, + {0x10030, 0x00063C1F}, + {0x10030, 0x00064019}, + {0x10030, 0x00064413}, {0x10030, 0x000681EF}, {0x10030, 0x000685E7}, {0x10030, 0x000689A7}, {0x10030, 0x00068D61}, {0x10030, 0x0006915B}, - {0x10030, 0x00069523}, - {0x10030, 0x0006991D}, - {0x10030, 0x00069CE5}, - {0x10030, 0x0006A0DF}, - {0x10030, 0x0006A4A7}, - {0x10030, 0x0006A8A1}, - {0x10030, 0x0006AC67}, - {0x10030, 0x0006B061}, + {0x10030, 0x00069525}, + {0x10030, 0x0006991F}, + {0x10030, 0x00069CE7}, + {0x10030, 0x0006A0E1}, + {0x10030, 0x0006A4A9}, + {0x10030, 0x0006A8A3}, + {0x10030, 0x0006AC69}, + {0x10030, 0x0006B063}, {0x10030, 0x0006B429}, {0x10030, 0x0006B823}, {0x10030, 0x0006BC1D}, {0x10030, 0x0006C017}, - {0x10030, 0x0006C40D}, - {0x10030, 0x000701F1}, + {0x10030, 0x0006C411}, + {0x10030, 0x000701EF}, {0x10030, 0x000705E9}, {0x10030, 0x000709A9}, {0x10030, 0x00070D63}, {0x10030, 0x0007115D}, - {0x10030, 0x00071523}, - {0x10030, 0x0007191D}, - {0x10030, 0x00071D17}, - {0x10030, 0x000720DF}, - {0x10030, 0x000724D9}, - {0x10030, 0x000728D3}, - {0x10030, 0x00072C67}, - {0x10030, 0x00073061}, - {0x10030, 0x00073427}, - {0x10030, 0x00073821}, - {0x10030, 0x00073C1B}, - {0x10030, 0x00074015}, - {0x10030, 0x0007440D}, - {0x10030, 0x000781F1}, - {0x10030, 0x000785EB}, - {0x10030, 0x000789E5}, - {0x10030, 0x00078DA3}, - {0x10030, 0x00079161}, - {0x10030, 0x0007955B}, - {0x10030, 0x00079923}, - {0x10030, 0x00079D1D}, - {0x10030, 0x0007A117}, - {0x10030, 0x0007A4DD}, - {0x10030, 0x0007A8D7}, - {0x10030, 0x0007AC9D}, - {0x10030, 0x0007B063}, - {0x10030, 0x0007B45D}, - {0x10030, 0x0007B857}, - {0x10030, 0x0007BC1D}, - {0x10030, 0x0007C017}, - {0x10030, 0x0007C40F}, + {0x10030, 0x00071525}, + {0x10030, 0x0007191F}, + {0x10030, 0x00071D19}, + {0x10030, 0x000720E1}, + {0x10030, 0x000724DB}, + {0x10030, 0x000728A3}, + {0x10030, 0x00072C69}, + {0x10030, 0x00073063}, + {0x10030, 0x00073429}, + {0x10030, 0x00073823}, + {0x10030, 0x00073C1D}, + {0x10030, 0x00074017}, + {0x10030, 0x00074411}, + {0x10030, 0x000781EF}, + {0x10030, 0x000785E9}, + {0x10030, 0x000789E3}, + {0x10030, 0x00078DA1}, + {0x10030, 0x0007915F}, + {0x10030, 0x00079559}, + {0x10030, 0x0007991F}, + {0x10030, 0x00079D19}, + {0x10030, 0x0007A0DF}, + {0x10030, 0x0007A4D9}, + {0x10030, 0x0007A8D3}, + {0x10030, 0x0007AC99}, + {0x10030, 0x0007B05F}, + {0x10030, 0x0007B459}, + {0x10030, 0x0007B81F}, + {0x10030, 0x0007BC19}, + {0x10030, 0x0007C013}, + {0x10030, 0x0007C40D}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x000001EF}, {0x10030, 0x000005E9}, @@ -21292,73 +23890,73 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x10030, 0x000609A9}, {0x10030, 0x00060D65}, {0x10030, 0x0006115F}, - {0x10030, 0x00061525}, - {0x10030, 0x0006191F}, - {0x10030, 0x00061CE7}, - {0x10030, 0x000620E1}, - {0x10030, 0x000624DB}, - {0x10030, 0x000628A3}, - {0x10030, 0x00062C69}, - {0x10030, 0x00063063}, - {0x10030, 0x00063429}, - {0x10030, 0x00063823}, - {0x10030, 0x00063C1D}, - {0x10030, 0x00064013}, - {0x10030, 0x0006440D}, + {0x10030, 0x00061527}, + {0x10030, 0x00061921}, + {0x10030, 0x00061CE9}, + {0x10030, 0x000620E3}, + {0x10030, 0x000624DD}, + {0x10030, 0x000628A5}, + {0x10030, 0x00062C6B}, + {0x10030, 0x00063065}, + {0x10030, 0x0006342B}, + {0x10030, 0x00063825}, + {0x10030, 0x00063C1F}, + {0x10030, 0x00064019}, + {0x10030, 0x00064413}, {0x10030, 0x000681EF}, {0x10030, 0x000685E7}, {0x10030, 0x000689A7}, {0x10030, 0x00068D61}, {0x10030, 0x0006915B}, - {0x10030, 0x00069523}, - {0x10030, 0x0006991D}, - {0x10030, 0x00069CE5}, - {0x10030, 0x0006A0DF}, - {0x10030, 0x0006A4A7}, - {0x10030, 0x0006A8A1}, - {0x10030, 0x0006AC67}, - {0x10030, 0x0006B061}, + {0x10030, 0x00069525}, + {0x10030, 0x0006991F}, + {0x10030, 0x00069CE7}, + {0x10030, 0x0006A0E1}, + {0x10030, 0x0006A4A9}, + {0x10030, 0x0006A8A3}, + {0x10030, 0x0006AC69}, + {0x10030, 0x0006B063}, {0x10030, 0x0006B429}, {0x10030, 0x0006B823}, {0x10030, 0x0006BC1D}, {0x10030, 0x0006C017}, - {0x10030, 0x0006C40D}, - {0x10030, 0x000701F1}, + {0x10030, 0x0006C411}, + {0x10030, 0x000701EF}, {0x10030, 0x000705E9}, {0x10030, 0x000709A9}, {0x10030, 0x00070D63}, {0x10030, 0x0007115D}, - {0x10030, 0x00071523}, - {0x10030, 0x0007191D}, - {0x10030, 0x00071D17}, - {0x10030, 0x000720DF}, - {0x10030, 0x000724D9}, - {0x10030, 0x000728D3}, - {0x10030, 0x00072C67}, - {0x10030, 0x00073061}, - {0x10030, 0x00073427}, - {0x10030, 0x00073821}, - {0x10030, 0x00073C1B}, - {0x10030, 0x00074015}, - {0x10030, 0x0007440D}, - {0x10030, 0x000781F1}, - {0x10030, 0x000785EB}, - {0x10030, 0x000789E5}, - {0x10030, 0x00078DA3}, - {0x10030, 0x00079161}, - {0x10030, 0x0007955B}, - {0x10030, 0x00079923}, - {0x10030, 0x00079D1D}, - {0x10030, 0x0007A117}, - {0x10030, 0x0007A4DD}, - {0x10030, 0x0007A8D7}, - {0x10030, 0x0007AC9D}, - {0x10030, 0x0007B063}, - {0x10030, 0x0007B45D}, - {0x10030, 0x0007B857}, - {0x10030, 0x0007BC1D}, - {0x10030, 0x0007C017}, - {0x10030, 0x0007C40F}, + {0x10030, 0x00071525}, + {0x10030, 0x0007191F}, + {0x10030, 0x00071D19}, + {0x10030, 0x000720E1}, + {0x10030, 0x000724DB}, + {0x10030, 0x000728A3}, + {0x10030, 0x00072C69}, + {0x10030, 0x00073063}, + {0x10030, 0x00073429}, + {0x10030, 0x00073823}, + {0x10030, 0x00073C1D}, + {0x10030, 0x00074017}, + {0x10030, 0x00074411}, + {0x10030, 0x000781EF}, + {0x10030, 0x000785E9}, + {0x10030, 0x000789E3}, + {0x10030, 0x00078DA1}, + {0x10030, 0x0007915F}, + {0x10030, 0x00079559}, + {0x10030, 0x0007991F}, + {0x10030, 0x00079D19}, + {0x10030, 0x0007A0DF}, + {0x10030, 0x0007A4D9}, + {0x10030, 0x0007A8D3}, + {0x10030, 0x0007AC99}, + {0x10030, 0x0007B05F}, + {0x10030, 0x0007B459}, + {0x10030, 0x0007B81F}, + {0x10030, 0x0007BC19}, + {0x10030, 0x0007C013}, + {0x10030, 0x0007C40D}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x000001EF}, {0x10030, 0x000005E9}, @@ -21428,82 +24026,82 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x10030, 0x00032C9B}, {0x10030, 0x00033061}, {0x10030, 0x0003345B}, - {0x10030, 0x00033821}, - {0x10030, 0x00033C1B}, - {0x10030, 0x00034015}, - {0x10030, 0x0003440F}, - {0x10030, 0x000601F1}, - {0x10030, 0x000605E9}, - {0x10030, 0x000609A9}, - {0x10030, 0x00060D65}, - {0x10030, 0x0006115F}, - {0x10030, 0x00061525}, - {0x10030, 0x0006191F}, - {0x10030, 0x00061CE7}, - {0x10030, 0x000620E1}, - {0x10030, 0x000624DB}, - {0x10030, 0x000628A3}, - {0x10030, 0x00062C69}, - {0x10030, 0x00063063}, - {0x10030, 0x00063429}, - {0x10030, 0x00063823}, - {0x10030, 0x00063C1D}, - {0x10030, 0x00064013}, - {0x10030, 0x0006440D}, - {0x10030, 0x000681EF}, - {0x10030, 0x000685E7}, - {0x10030, 0x000689A7}, - {0x10030, 0x00068D61}, - {0x10030, 0x0006915B}, - {0x10030, 0x00069523}, - {0x10030, 0x0006991D}, - {0x10030, 0x00069CE5}, - {0x10030, 0x0006A0DF}, - {0x10030, 0x0006A4A7}, - {0x10030, 0x0006A8A1}, - {0x10030, 0x0006AC67}, - {0x10030, 0x0006B061}, - {0x10030, 0x0006B429}, - {0x10030, 0x0006B823}, - {0x10030, 0x0006BC1D}, - {0x10030, 0x0006C017}, - {0x10030, 0x0006C40D}, - {0x10030, 0x000701F1}, - {0x10030, 0x000705E9}, - {0x10030, 0x000709A9}, - {0x10030, 0x00070D63}, - {0x10030, 0x0007115D}, - {0x10030, 0x00071523}, - {0x10030, 0x0007191D}, - {0x10030, 0x00071D17}, - {0x10030, 0x000720DF}, - {0x10030, 0x000724D9}, - {0x10030, 0x000728D3}, - {0x10030, 0x00072C67}, - {0x10030, 0x00073061}, - {0x10030, 0x00073427}, - {0x10030, 0x00073821}, - {0x10030, 0x00073C1B}, - {0x10030, 0x00074015}, - {0x10030, 0x0007440D}, - {0x10030, 0x000781F1}, - {0x10030, 0x000785EB}, - {0x10030, 0x000789E5}, - {0x10030, 0x00078DA3}, - {0x10030, 0x00079161}, - {0x10030, 0x0007955B}, - {0x10030, 0x00079923}, - {0x10030, 0x00079D1D}, - {0x10030, 0x0007A117}, - {0x10030, 0x0007A4DD}, - {0x10030, 0x0007A8D7}, - {0x10030, 0x0007AC9D}, - {0x10030, 0x0007B063}, - {0x10030, 0x0007B45D}, - {0x10030, 0x0007B857}, - {0x10030, 0x0007BC1D}, - {0x10030, 0x0007C017}, - {0x10030, 0x0007C40F}, + {0x10030, 0x00033821}, + {0x10030, 0x00033C1B}, + {0x10030, 0x00034015}, + {0x10030, 0x0003440F}, + {0x10030, 0x000601F1}, + {0x10030, 0x000605E9}, + {0x10030, 0x000609A9}, + {0x10030, 0x00060D65}, + {0x10030, 0x0006115F}, + {0x10030, 0x00061527}, + {0x10030, 0x00061921}, + {0x10030, 0x00061CE9}, + {0x10030, 0x000620E3}, + {0x10030, 0x000624DD}, + {0x10030, 0x000628A5}, + {0x10030, 0x00062C6B}, + {0x10030, 0x00063065}, + {0x10030, 0x0006342B}, + {0x10030, 0x00063825}, + {0x10030, 0x00063C1F}, + {0x10030, 0x00064019}, + {0x10030, 0x00064413}, + {0x10030, 0x000681EF}, + {0x10030, 0x000685E7}, + {0x10030, 0x000689A7}, + {0x10030, 0x00068D61}, + {0x10030, 0x0006915B}, + {0x10030, 0x00069525}, + {0x10030, 0x0006991F}, + {0x10030, 0x00069CE7}, + {0x10030, 0x0006A0E1}, + {0x10030, 0x0006A4A9}, + {0x10030, 0x0006A8A3}, + {0x10030, 0x0006AC69}, + {0x10030, 0x0006B063}, + {0x10030, 0x0006B429}, + {0x10030, 0x0006B823}, + {0x10030, 0x0006BC1D}, + {0x10030, 0x0006C017}, + {0x10030, 0x0006C411}, + {0x10030, 0x000701EF}, + {0x10030, 0x000705E9}, + {0x10030, 0x000709A9}, + {0x10030, 0x00070D63}, + {0x10030, 0x0007115D}, + {0x10030, 0x00071525}, + {0x10030, 0x0007191F}, + {0x10030, 0x00071D19}, + {0x10030, 0x000720E1}, + {0x10030, 0x000724DB}, + {0x10030, 0x000728A3}, + {0x10030, 0x00072C69}, + {0x10030, 0x00073063}, + {0x10030, 0x00073429}, + {0x10030, 0x00073823}, + {0x10030, 0x00073C1D}, + {0x10030, 0x00074017}, + {0x10030, 0x00074411}, + {0x10030, 0x000781EF}, + {0x10030, 0x000785E9}, + {0x10030, 0x000789E3}, + {0x10030, 0x00078DA1}, + {0x10030, 0x0007915F}, + {0x10030, 0x00079559}, + {0x10030, 0x0007991F}, + {0x10030, 0x00079D19}, + {0x10030, 0x0007A0DF}, + {0x10030, 0x0007A4D9}, + {0x10030, 0x0007A8D3}, + {0x10030, 0x0007AC99}, + {0x10030, 0x0007B05F}, + {0x10030, 0x0007B459}, + {0x10030, 0x0007B81F}, + {0x10030, 0x0007BC19}, + {0x10030, 0x0007C013}, + {0x10030, 0x0007C40D}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x000001EF}, {0x10030, 0x000005E9}, @@ -21582,73 +24180,73 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x10030, 0x000609A9}, {0x10030, 0x00060D65}, {0x10030, 0x0006115F}, - {0x10030, 0x00061525}, - {0x10030, 0x0006191F}, - {0x10030, 0x00061CE7}, - {0x10030, 0x000620E1}, - {0x10030, 0x000624DB}, - {0x10030, 0x000628A3}, - {0x10030, 0x00062C69}, - {0x10030, 0x00063063}, - {0x10030, 0x00063429}, - {0x10030, 0x00063823}, - {0x10030, 0x00063C1D}, - {0x10030, 0x00064013}, - {0x10030, 0x0006440D}, + {0x10030, 0x00061527}, + {0x10030, 0x00061921}, + {0x10030, 0x00061CE9}, + {0x10030, 0x000620E3}, + {0x10030, 0x000624DD}, + {0x10030, 0x000628A5}, + {0x10030, 0x00062C6B}, + {0x10030, 0x00063065}, + {0x10030, 0x0006342B}, + {0x10030, 0x00063825}, + {0x10030, 0x00063C1F}, + {0x10030, 0x00064019}, + {0x10030, 0x00064413}, {0x10030, 0x000681EF}, {0x10030, 0x000685E7}, {0x10030, 0x000689A7}, {0x10030, 0x00068D61}, {0x10030, 0x0006915B}, - {0x10030, 0x00069523}, - {0x10030, 0x0006991D}, - {0x10030, 0x00069CE5}, - {0x10030, 0x0006A0DF}, - {0x10030, 0x0006A4A7}, - {0x10030, 0x0006A8A1}, - {0x10030, 0x0006AC67}, - {0x10030, 0x0006B061}, + {0x10030, 0x00069525}, + {0x10030, 0x0006991F}, + {0x10030, 0x00069CE7}, + {0x10030, 0x0006A0E1}, + {0x10030, 0x0006A4A9}, + {0x10030, 0x0006A8A3}, + {0x10030, 0x0006AC69}, + {0x10030, 0x0006B063}, {0x10030, 0x0006B429}, {0x10030, 0x0006B823}, {0x10030, 0x0006BC1D}, {0x10030, 0x0006C017}, - {0x10030, 0x0006C40D}, - {0x10030, 0x000701F1}, + {0x10030, 0x0006C411}, + {0x10030, 0x000701EF}, {0x10030, 0x000705E9}, {0x10030, 0x000709A9}, {0x10030, 0x00070D63}, {0x10030, 0x0007115D}, - {0x10030, 0x00071523}, - {0x10030, 0x0007191D}, - {0x10030, 0x00071D17}, - {0x10030, 0x000720DF}, - {0x10030, 0x000724D9}, - {0x10030, 0x000728D3}, - {0x10030, 0x00072C67}, - {0x10030, 0x00073061}, - {0x10030, 0x00073427}, - {0x10030, 0x00073821}, - {0x10030, 0x00073C1B}, - {0x10030, 0x00074015}, - {0x10030, 0x0007440D}, - {0x10030, 0x000781F1}, - {0x10030, 0x000785EB}, - {0x10030, 0x000789E5}, - {0x10030, 0x00078DA3}, - {0x10030, 0x00079161}, - {0x10030, 0x0007955B}, - {0x10030, 0x00079923}, - {0x10030, 0x00079D1D}, - {0x10030, 0x0007A117}, - {0x10030, 0x0007A4DD}, - {0x10030, 0x0007A8D7}, - {0x10030, 0x0007AC9D}, - {0x10030, 0x0007B063}, - {0x10030, 0x0007B45D}, - {0x10030, 0x0007B857}, - {0x10030, 0x0007BC1D}, - {0x10030, 0x0007C017}, - {0x10030, 0x0007C40F}, + {0x10030, 0x00071525}, + {0x10030, 0x0007191F}, + {0x10030, 0x00071D19}, + {0x10030, 0x000720E1}, + {0x10030, 0x000724DB}, + {0x10030, 0x000728A3}, + {0x10030, 0x00072C69}, + {0x10030, 0x00073063}, + {0x10030, 0x00073429}, + {0x10030, 0x00073823}, + {0x10030, 0x00073C1D}, + {0x10030, 0x00074017}, + {0x10030, 0x00074411}, + {0x10030, 0x000781EF}, + {0x10030, 0x000785E9}, + {0x10030, 0x000789E3}, + {0x10030, 0x00078DA1}, + {0x10030, 0x0007915F}, + {0x10030, 0x00079559}, + {0x10030, 0x0007991F}, + {0x10030, 0x00079D19}, + {0x10030, 0x0007A0DF}, + {0x10030, 0x0007A4D9}, + {0x10030, 0x0007A8D3}, + {0x10030, 0x0007AC99}, + {0x10030, 0x0007B05F}, + {0x10030, 0x0007B459}, + {0x10030, 0x0007B81F}, + {0x10030, 0x0007BC19}, + {0x10030, 0x0007C013}, + {0x10030, 0x0007C40D}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x000001EF}, {0x10030, 0x000005E9}, @@ -21727,73 +24325,73 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x10030, 0x000609A9}, {0x10030, 0x00060D65}, {0x10030, 0x0006115F}, - {0x10030, 0x00061525}, - {0x10030, 0x0006191F}, - {0x10030, 0x00061CE7}, - {0x10030, 0x000620E1}, - {0x10030, 0x000624DB}, - {0x10030, 0x000628A3}, - {0x10030, 0x00062C69}, - {0x10030, 0x00063063}, - {0x10030, 0x00063429}, - {0x10030, 0x00063823}, - {0x10030, 0x00063C1D}, - {0x10030, 0x00064013}, - {0x10030, 0x0006440D}, + {0x10030, 0x00061527}, + {0x10030, 0x00061921}, + {0x10030, 0x00061CE9}, + {0x10030, 0x000620E3}, + {0x10030, 0x000624DD}, + {0x10030, 0x000628A5}, + {0x10030, 0x00062C6B}, + {0x10030, 0x00063065}, + {0x10030, 0x0006342B}, + {0x10030, 0x00063825}, + {0x10030, 0x00063C1F}, + {0x10030, 0x00064019}, + {0x10030, 0x00064413}, {0x10030, 0x000681EF}, {0x10030, 0x000685E7}, {0x10030, 0x000689A7}, {0x10030, 0x00068D61}, {0x10030, 0x0006915B}, - {0x10030, 0x00069523}, - {0x10030, 0x0006991D}, - {0x10030, 0x00069CE5}, - {0x10030, 0x0006A0DF}, - {0x10030, 0x0006A4A7}, - {0x10030, 0x0006A8A1}, - {0x10030, 0x0006AC67}, - {0x10030, 0x0006B061}, + {0x10030, 0x00069525}, + {0x10030, 0x0006991F}, + {0x10030, 0x00069CE7}, + {0x10030, 0x0006A0E1}, + {0x10030, 0x0006A4A9}, + {0x10030, 0x0006A8A3}, + {0x10030, 0x0006AC69}, + {0x10030, 0x0006B063}, {0x10030, 0x0006B429}, {0x10030, 0x0006B823}, {0x10030, 0x0006BC1D}, {0x10030, 0x0006C017}, - {0x10030, 0x0006C40D}, - {0x10030, 0x000701F1}, + {0x10030, 0x0006C411}, + {0x10030, 0x000701EF}, {0x10030, 0x000705E9}, {0x10030, 0x000709A9}, {0x10030, 0x00070D63}, {0x10030, 0x0007115D}, - {0x10030, 0x00071523}, - {0x10030, 0x0007191D}, - {0x10030, 0x00071D17}, - {0x10030, 0x000720DF}, - {0x10030, 0x000724D9}, - {0x10030, 0x000728D3}, - {0x10030, 0x00072C67}, - {0x10030, 0x00073061}, - {0x10030, 0x00073427}, - {0x10030, 0x00073821}, - {0x10030, 0x00073C1B}, - {0x10030, 0x00074015}, - {0x10030, 0x0007440D}, - {0x10030, 0x000781F1}, - {0x10030, 0x000785EB}, - {0x10030, 0x000789E5}, - {0x10030, 0x00078DA3}, - {0x10030, 0x00079161}, - {0x10030, 0x0007955B}, - {0x10030, 0x00079923}, - {0x10030, 0x00079D1D}, - {0x10030, 0x0007A117}, - {0x10030, 0x0007A4DD}, - {0x10030, 0x0007A8D7}, - {0x10030, 0x0007AC9D}, - {0x10030, 0x0007B063}, - {0x10030, 0x0007B45D}, - {0x10030, 0x0007B857}, - {0x10030, 0x0007BC1D}, - {0x10030, 0x0007C017}, - {0x10030, 0x0007C40F}, + {0x10030, 0x00071525}, + {0x10030, 0x0007191F}, + {0x10030, 0x00071D19}, + {0x10030, 0x000720E1}, + {0x10030, 0x000724DB}, + {0x10030, 0x000728A3}, + {0x10030, 0x00072C69}, + {0x10030, 0x00073063}, + {0x10030, 0x00073429}, + {0x10030, 0x00073823}, + {0x10030, 0x00073C1D}, + {0x10030, 0x00074017}, + {0x10030, 0x00074411}, + {0x10030, 0x000781EF}, + {0x10030, 0x000785E9}, + {0x10030, 0x000789E3}, + {0x10030, 0x00078DA1}, + {0x10030, 0x0007915F}, + {0x10030, 0x00079559}, + {0x10030, 0x0007991F}, + {0x10030, 0x00079D19}, + {0x10030, 0x0007A0DF}, + {0x10030, 0x0007A4D9}, + {0x10030, 0x0007A8D3}, + {0x10030, 0x0007AC99}, + {0x10030, 0x0007B05F}, + {0x10030, 0x0007B459}, + {0x10030, 0x0007B81F}, + {0x10030, 0x0007BC19}, + {0x10030, 0x0007C013}, + {0x10030, 0x0007C40D}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x000001EF}, {0x10030, 0x000005E9}, @@ -21872,73 +24470,73 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x10030, 0x000609A9}, {0x10030, 0x00060D65}, {0x10030, 0x0006115F}, - {0x10030, 0x00061525}, - {0x10030, 0x0006191F}, - {0x10030, 0x00061CE7}, - {0x10030, 0x000620E1}, - {0x10030, 0x000624DB}, - {0x10030, 0x000628A3}, - {0x10030, 0x00062C69}, - {0x10030, 0x00063063}, - {0x10030, 0x00063429}, - {0x10030, 0x00063823}, - {0x10030, 0x00063C1D}, - {0x10030, 0x00064013}, - {0x10030, 0x0006440D}, + {0x10030, 0x00061527}, + {0x10030, 0x00061921}, + {0x10030, 0x00061CE9}, + {0x10030, 0x000620E3}, + {0x10030, 0x000624DD}, + {0x10030, 0x000628A5}, + {0x10030, 0x00062C6B}, + {0x10030, 0x00063065}, + {0x10030, 0x0006342B}, + {0x10030, 0x00063825}, + {0x10030, 0x00063C1F}, + {0x10030, 0x00064019}, + {0x10030, 0x00064413}, {0x10030, 0x000681EF}, {0x10030, 0x000685E7}, {0x10030, 0x000689A7}, {0x10030, 0x00068D61}, {0x10030, 0x0006915B}, - {0x10030, 0x00069523}, - {0x10030, 0x0006991D}, - {0x10030, 0x00069CE5}, - {0x10030, 0x0006A0DF}, - {0x10030, 0x0006A4A7}, - {0x10030, 0x0006A8A1}, - {0x10030, 0x0006AC67}, - {0x10030, 0x0006B061}, + {0x10030, 0x00069525}, + {0x10030, 0x0006991F}, + {0x10030, 0x00069CE7}, + {0x10030, 0x0006A0E1}, + {0x10030, 0x0006A4A9}, + {0x10030, 0x0006A8A3}, + {0x10030, 0x0006AC69}, + {0x10030, 0x0006B063}, {0x10030, 0x0006B429}, {0x10030, 0x0006B823}, {0x10030, 0x0006BC1D}, {0x10030, 0x0006C017}, - {0x10030, 0x0006C40D}, - {0x10030, 0x000701F1}, + {0x10030, 0x0006C411}, + {0x10030, 0x000701EF}, {0x10030, 0x000705E9}, {0x10030, 0x000709A9}, {0x10030, 0x00070D63}, {0x10030, 0x0007115D}, - {0x10030, 0x00071523}, - {0x10030, 0x0007191D}, - {0x10030, 0x00071D17}, - {0x10030, 0x000720DF}, - {0x10030, 0x000724D9}, - {0x10030, 0x000728D3}, - {0x10030, 0x00072C67}, - {0x10030, 0x00073061}, - {0x10030, 0x00073427}, - {0x10030, 0x00073821}, - {0x10030, 0x00073C1B}, - {0x10030, 0x00074015}, - {0x10030, 0x0007440D}, - {0x10030, 0x000781F1}, - {0x10030, 0x000785EB}, - {0x10030, 0x000789E5}, - {0x10030, 0x00078DA3}, - {0x10030, 0x00079161}, - {0x10030, 0x0007955B}, - {0x10030, 0x00079923}, - {0x10030, 0x00079D1D}, - {0x10030, 0x0007A117}, - {0x10030, 0x0007A4DD}, - {0x10030, 0x0007A8D7}, - {0x10030, 0x0007AC9D}, - {0x10030, 0x0007B063}, - {0x10030, 0x0007B45D}, - {0x10030, 0x0007B857}, - {0x10030, 0x0007BC1D}, - {0x10030, 0x0007C017}, - {0x10030, 0x0007C40F}, + {0x10030, 0x00071525}, + {0x10030, 0x0007191F}, + {0x10030, 0x00071D19}, + {0x10030, 0x000720E1}, + {0x10030, 0x000724DB}, + {0x10030, 0x000728A3}, + {0x10030, 0x00072C69}, + {0x10030, 0x00073063}, + {0x10030, 0x00073429}, + {0x10030, 0x00073823}, + {0x10030, 0x00073C1D}, + {0x10030, 0x00074017}, + {0x10030, 0x00074411}, + {0x10030, 0x000781EF}, + {0x10030, 0x000785E9}, + {0x10030, 0x000789E3}, + {0x10030, 0x00078DA1}, + {0x10030, 0x0007915F}, + {0x10030, 0x00079559}, + {0x10030, 0x0007991F}, + {0x10030, 0x00079D19}, + {0x10030, 0x0007A0DF}, + {0x10030, 0x0007A4D9}, + {0x10030, 0x0007A8D3}, + {0x10030, 0x0007AC99}, + {0x10030, 0x0007B05F}, + {0x10030, 0x0007B459}, + {0x10030, 0x0007B81F}, + {0x10030, 0x0007BC19}, + {0x10030, 0x0007C013}, + {0x10030, 0x0007C40D}, {0xA0000000, 0x00000000}, {0x10030, 0x000001EF}, {0x10030, 0x000005E9}, @@ -22782,6 +25380,110 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x10030, 0x000338CC}, {0x10030, 0x00033C09}, {0x10030, 0x00034006}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x10030, 0x000200E8}, + {0x10030, 0x000204E5}, + {0x10030, 0x000208E2}, + {0x10030, 0x00020CDF}, + {0x10030, 0x000210DC}, + {0x10030, 0x000214D9}, + {0x10030, 0x000218D6}, + {0x10030, 0x00021CD3}, + {0x10030, 0x000220D0}, + {0x10030, 0x0002240D}, + {0x10030, 0x0002280A}, + {0x10030, 0x00022C07}, + {0x10030, 0x00023004}, + {0x10030, 0x00023401}, + {0x10030, 0x00023800}, + {0x10030, 0x00023C00}, + {0x10030, 0x00024000}, + {0x10030, 0x000280E7}, + {0x10030, 0x000284E4}, + {0x10030, 0x000288E1}, + {0x10030, 0x00028CDE}, + {0x10030, 0x000290DB}, + {0x10030, 0x000294D8}, + {0x10030, 0x000298D5}, + {0x10030, 0x00029CD2}, + {0x10030, 0x0002A0CF}, + {0x10030, 0x0002A40C}, + {0x10030, 0x0002A809}, + {0x10030, 0x0002AC06}, + {0x10030, 0x0002B003}, + {0x10030, 0x0002B400}, + {0x10030, 0x0002B800}, + {0x10030, 0x0002BC00}, + {0x10030, 0x0002C000}, + {0x10030, 0x000300E7}, + {0x10030, 0x000304E4}, + {0x10030, 0x000308E1}, + {0x10030, 0x00030CDE}, + {0x10030, 0x000310DB}, + {0x10030, 0x000314D8}, + {0x10030, 0x000318D5}, + {0x10030, 0x00031CD2}, + {0x10030, 0x000320CF}, + {0x10030, 0x000324CC}, + {0x10030, 0x00032809}, + {0x10030, 0x00032C06}, + {0x10030, 0x00033003}, + {0x10030, 0x00033400}, + {0x10030, 0x00033800}, + {0x10030, 0x00033C00}, + {0x10030, 0x00034000}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x10030, 0x000200E8}, + {0x10030, 0x000204E5}, + {0x10030, 0x000208E2}, + {0x10030, 0x00020CDF}, + {0x10030, 0x000210DC}, + {0x10030, 0x000214D9}, + {0x10030, 0x000218D6}, + {0x10030, 0x00021CD3}, + {0x10030, 0x000220D0}, + {0x10030, 0x0002240D}, + {0x10030, 0x0002280A}, + {0x10030, 0x00022C07}, + {0x10030, 0x00023004}, + {0x10030, 0x00023401}, + {0x10030, 0x00023800}, + {0x10030, 0x00023C00}, + {0x10030, 0x00024000}, + {0x10030, 0x000280E7}, + {0x10030, 0x000284E4}, + {0x10030, 0x000288E1}, + {0x10030, 0x00028CDE}, + {0x10030, 0x000290DB}, + {0x10030, 0x000294D8}, + {0x10030, 0x000298D5}, + {0x10030, 0x00029CD2}, + {0x10030, 0x0002A0CF}, + {0x10030, 0x0002A40C}, + {0x10030, 0x0002A809}, + {0x10030, 0x0002AC06}, + {0x10030, 0x0002B003}, + {0x10030, 0x0002B400}, + {0x10030, 0x0002B800}, + {0x10030, 0x0002BC00}, + {0x10030, 0x0002C000}, + {0x10030, 0x000300E7}, + {0x10030, 0x000304E4}, + {0x10030, 0x000308E1}, + {0x10030, 0x00030CDE}, + {0x10030, 0x000310DB}, + {0x10030, 0x000314D8}, + {0x10030, 0x000318D5}, + {0x10030, 0x00031CD2}, + {0x10030, 0x000320CF}, + {0x10030, 0x000324CC}, + {0x10030, 0x00032809}, + {0x10030, 0x00032C06}, + {0x10030, 0x00033003}, + {0x10030, 0x00033400}, + {0x10030, 0x00033800}, + {0x10030, 0x00033C00}, + {0x10030, 0x00034000}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x000200FA}, {0x10030, 0x000204F7}, @@ -23329,6 +26031,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -23373,6 +26079,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -23429,6 +26139,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -23473,6 +26187,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -23529,6 +26247,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -23573,6 +26295,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -23629,6 +26355,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -23673,6 +26403,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -23729,6 +26463,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -23773,6 +26511,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -23829,6 +26571,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -23873,6 +26619,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -23929,6 +26679,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -23973,6 +26727,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -24029,6 +26787,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -24073,6 +26835,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -24129,6 +26895,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -24173,6 +26943,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -24229,6 +27003,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -24273,6 +27051,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -24329,6 +27111,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -24373,6 +27159,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -24429,6 +27219,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -24473,6 +27267,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -24529,6 +27327,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -24573,6 +27375,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -24629,6 +27435,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -24673,6 +27483,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -24729,6 +27543,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -24773,6 +27591,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -24829,6 +27651,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -24873,6 +27699,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -24929,6 +27759,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -24973,6 +27807,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -25029,6 +27867,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -25073,6 +27915,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -25129,6 +27975,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -25173,6 +28023,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -25229,6 +28083,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -25273,6 +28131,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -25329,6 +28191,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -25373,6 +28239,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -25429,6 +28299,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -25473,6 +28347,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -25529,6 +28407,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -25573,6 +28455,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -25629,6 +28515,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -25673,6 +28563,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -25729,6 +28623,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -25773,6 +28671,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -25829,6 +28731,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -25873,6 +28779,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -25929,6 +28839,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -25973,6 +28887,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -26029,6 +28947,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -26073,6 +28995,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -26157,6 +29083,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x10030, 0x00025003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x00025003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x10030, 0x00025003}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x10030, 0x00025003}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x00025003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -26207,6 +29137,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x10030, 0x0002D003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x0002D003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x10030, 0x0002D003}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x10030, 0x0002D003}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x0002D003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -26257,6 +29191,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x10030, 0x00035003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x00035003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x10030, 0x00035003}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x10030, 0x00035003}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x00035003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -26307,6 +29245,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x10030, 0x0003D003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x0003D003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x10030, 0x0003D003}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x10030, 0x0003D003}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x0003D003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -26370,6 +29312,12 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x00065003}, {0x10030, 0x00066003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x10030, 0x00065003}, + {0x10030, 0x00066003}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x10030, 0x00065003}, + {0x10030, 0x00066003}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x00065003}, {0x10030, 0x00066003}, @@ -26440,6 +29388,12 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x0006D003}, {0x10030, 0x0006E003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x10030, 0x0006D003}, + {0x10030, 0x0006E003}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x10030, 0x0006D003}, + {0x10030, 0x0006E003}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x0006D003}, {0x10030, 0x0006E003}, @@ -26510,6 +29464,12 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x00075003}, {0x10030, 0x00076003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x10030, 0x00075003}, + {0x10030, 0x00076003}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x10030, 0x00075003}, + {0x10030, 0x00076003}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x00075003}, {0x10030, 0x00076003}, @@ -26580,6 +29540,12 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x0007D003}, {0x10030, 0x0007E003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x10030, 0x0007D003}, + {0x10030, 0x0007E003}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x10030, 0x0007D003}, + {0x10030, 0x0007E003}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x0007D003}, {0x10030, 0x0007E003}, @@ -26621,7 +29587,7 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x0000000A}, {0x0ED, 0x00000000}, {0x100EE, 0x00000000}, - {0x0FE, 0x00000048}, + {0x0FE, 0x00000063}, }; static const struct rtw89_reg2_def rtw89_8852c_phy_nctl_regs[] = { @@ -28430,11 +31396,11 @@ static const struct rtw89_txpwr_byrate_cfg rtw89_8852c_txpwr_byrate[] = { { 2, 0, 1, 4, 4, 0x383c4040, }, { 2, 0, 2, 0, 4, 0x40404040, }, { 2, 0, 2, 4, 4, 0x34383c40, }, - { 2, 0, 2, 8, 4, 0x24282c30, }, + { 2, 0, 2, 8, 4, 0x20282c30, }, { 2, 0, 3, 0, 4, 0x40404040, }, { 2, 1, 2, 0, 4, 0x40404040, }, { 2, 1, 2, 4, 4, 0x34383c40, }, - { 2, 1, 2, 8, 4, 0x24282c30, }, + { 2, 1, 2, 8, 4, 0x20282c30, }, { 2, 1, 3, 0, 4, 0x40404040, }, { 2, 0, 4, 0, 4, 0x00000000, }, }; @@ -28559,35 +31525,53 @@ static const s8 _txpwr_track_delta_swingidx_2g_cck_a_p[] = { 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 5, 5, 5 }; -const u8 rtw89_8852c_tx_shape[RTW89_BAND_MAX][RTW89_RS_TX_SHAPE_NUM] +const u8 rtw89_8852c_tx_shape[RTW89_BAND_NUM][RTW89_RS_TX_SHAPE_NUM] [RTW89_REGD_NUM] = { [0][0][RTW89_ACMA] = 0, + [0][0][RTW89_CHILE] = 0, [0][0][RTW89_CN] = 0, [0][0][RTW89_ETSI] = 0, [0][0][RTW89_FCC] = 1, [0][0][RTW89_IC] = 1, [0][0][RTW89_KCC] = 0, + [0][0][RTW89_MEXICO] = 1, [0][0][RTW89_MKK] = 0, + [0][0][RTW89_QATAR] = 0, [0][0][RTW89_UK] = 0, + [0][0][RTW89_UKRAINE] = 0, [0][1][RTW89_ACMA] = 0, + [0][1][RTW89_CHILE] = 0, [0][1][RTW89_CN] = 0, [0][1][RTW89_ETSI] = 0, [0][1][RTW89_FCC] = 3, [0][1][RTW89_IC] = 3, [0][1][RTW89_KCC] = 0, + [0][1][RTW89_MEXICO] = 3, [0][1][RTW89_MKK] = 0, + [0][1][RTW89_QATAR] = 0, [0][1][RTW89_UK] = 0, + [0][1][RTW89_UKRAINE] = 0, [1][1][RTW89_ACMA] = 0, + [1][1][RTW89_CHILE] = 0, [1][1][RTW89_CN] = 0, [1][1][RTW89_ETSI] = 0, [1][1][RTW89_FCC] = 3, [1][1][RTW89_IC] = 3, [1][1][RTW89_KCC] = 0, + [1][1][RTW89_MEXICO] = 3, [1][1][RTW89_MKK] = 0, + [1][1][RTW89_QATAR] = 0, [1][1][RTW89_UK] = 0, + [1][1][RTW89_UKRAINE] = 0, + [2][1][RTW89_ACMA] = 0, + [2][1][RTW89_CHILE] = 0, [2][1][RTW89_ETSI] = 0, [2][1][RTW89_FCC] = 0, + [2][1][RTW89_IC] = 0, [2][1][RTW89_KCC] = 0, + [2][1][RTW89_MKK] = 0, + [2][1][RTW89_QATAR] = 0, + [2][1][RTW89_UK] = 0, }; static @@ -28770,6 +31754,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][0][0][0][RTW89_ACMA][0] = 60, [0][0][0][0][RTW89_CN][0] = 58, [0][0][0][0][RTW89_UK][0] = 60, + [0][0][0][0][RTW89_MEXICO][0] = 76, + [0][0][0][0][RTW89_UKRAINE][0] = 60, + [0][0][0][0][RTW89_CHILE][0] = 76, + [0][0][0][0][RTW89_QATAR][0] = 60, [0][0][0][0][RTW89_FCC][1] = 76, [0][0][0][0][RTW89_ETSI][1] = 60, [0][0][0][0][RTW89_MKK][1] = 68, @@ -28778,6 +31766,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][0][0][0][RTW89_ACMA][1] = 60, [0][0][0][0][RTW89_CN][1] = 58, [0][0][0][0][RTW89_UK][1] = 60, + [0][0][0][0][RTW89_MEXICO][1] = 76, + [0][0][0][0][RTW89_UKRAINE][1] = 60, + [0][0][0][0][RTW89_CHILE][1] = 68, + [0][0][0][0][RTW89_QATAR][1] = 60, [0][0][0][0][RTW89_FCC][2] = 76, [0][0][0][0][RTW89_ETSI][2] = 60, [0][0][0][0][RTW89_MKK][2] = 68, @@ -28786,6 +31778,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][0][0][0][RTW89_ACMA][2] = 60, [0][0][0][0][RTW89_CN][2] = 58, [0][0][0][0][RTW89_UK][2] = 60, + [0][0][0][0][RTW89_MEXICO][2] = 76, + [0][0][0][0][RTW89_UKRAINE][2] = 60, + [0][0][0][0][RTW89_CHILE][2] = 68, + [0][0][0][0][RTW89_QATAR][2] = 60, [0][0][0][0][RTW89_FCC][3] = 76, [0][0][0][0][RTW89_ETSI][3] = 60, [0][0][0][0][RTW89_MKK][3] = 68, @@ -28794,6 +31790,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][0][0][0][RTW89_ACMA][3] = 60, [0][0][0][0][RTW89_CN][3] = 58, [0][0][0][0][RTW89_UK][3] = 60, + [0][0][0][0][RTW89_MEXICO][3] = 76, + [0][0][0][0][RTW89_UKRAINE][3] = 60, + [0][0][0][0][RTW89_CHILE][3] = 68, + [0][0][0][0][RTW89_QATAR][3] = 60, [0][0][0][0][RTW89_FCC][4] = 76, [0][0][0][0][RTW89_ETSI][4] = 60, [0][0][0][0][RTW89_MKK][4] = 68, @@ -28802,6 +31802,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][0][0][0][RTW89_ACMA][4] = 60, [0][0][0][0][RTW89_CN][4] = 58, [0][0][0][0][RTW89_UK][4] = 60, + [0][0][0][0][RTW89_MEXICO][4] = 76, + [0][0][0][0][RTW89_UKRAINE][4] = 60, + [0][0][0][0][RTW89_CHILE][4] = 68, + [0][0][0][0][RTW89_QATAR][4] = 60, [0][0][0][0][RTW89_FCC][5] = 76, [0][0][0][0][RTW89_ETSI][5] = 60, [0][0][0][0][RTW89_MKK][5] = 68, @@ -28810,6 +31814,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][0][0][0][RTW89_ACMA][5] = 60, [0][0][0][0][RTW89_CN][5] = 58, [0][0][0][0][RTW89_UK][5] = 60, + [0][0][0][0][RTW89_MEXICO][5] = 76, + [0][0][0][0][RTW89_UKRAINE][5] = 60, + [0][0][0][0][RTW89_CHILE][5] = 76, + [0][0][0][0][RTW89_QATAR][5] = 60, [0][0][0][0][RTW89_FCC][6] = 76, [0][0][0][0][RTW89_ETSI][6] = 60, [0][0][0][0][RTW89_MKK][6] = 68, @@ -28818,6 +31826,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][0][0][0][RTW89_ACMA][6] = 60, [0][0][0][0][RTW89_CN][6] = 58, [0][0][0][0][RTW89_UK][6] = 60, + [0][0][0][0][RTW89_MEXICO][6] = 76, + [0][0][0][0][RTW89_UKRAINE][6] = 60, + [0][0][0][0][RTW89_CHILE][6] = 76, + [0][0][0][0][RTW89_QATAR][6] = 60, [0][0][0][0][RTW89_FCC][7] = 76, [0][0][0][0][RTW89_ETSI][7] = 60, [0][0][0][0][RTW89_MKK][7] = 68, @@ -28826,6 +31838,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][0][0][0][RTW89_ACMA][7] = 60, [0][0][0][0][RTW89_CN][7] = 58, [0][0][0][0][RTW89_UK][7] = 60, + [0][0][0][0][RTW89_MEXICO][7] = 76, + [0][0][0][0][RTW89_UKRAINE][7] = 60, + [0][0][0][0][RTW89_CHILE][7] = 76, + [0][0][0][0][RTW89_QATAR][7] = 60, [0][0][0][0][RTW89_FCC][8] = 76, [0][0][0][0][RTW89_ETSI][8] = 60, [0][0][0][0][RTW89_MKK][8] = 68, @@ -28834,6 +31850,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][0][0][0][RTW89_ACMA][8] = 60, [0][0][0][0][RTW89_CN][8] = 58, [0][0][0][0][RTW89_UK][8] = 60, + [0][0][0][0][RTW89_MEXICO][8] = 76, + [0][0][0][0][RTW89_UKRAINE][8] = 60, + [0][0][0][0][RTW89_CHILE][8] = 76, + [0][0][0][0][RTW89_QATAR][8] = 60, [0][0][0][0][RTW89_FCC][9] = 76, [0][0][0][0][RTW89_ETSI][9] = 60, [0][0][0][0][RTW89_MKK][9] = 68, @@ -28842,6 +31862,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][0][0][0][RTW89_ACMA][9] = 60, [0][0][0][0][RTW89_CN][9] = 58, [0][0][0][0][RTW89_UK][9] = 60, + [0][0][0][0][RTW89_MEXICO][9] = 76, + [0][0][0][0][RTW89_UKRAINE][9] = 60, + [0][0][0][0][RTW89_CHILE][9] = 76, + [0][0][0][0][RTW89_QATAR][9] = 60, [0][0][0][0][RTW89_FCC][10] = 76, [0][0][0][0][RTW89_ETSI][10] = 60, [0][0][0][0][RTW89_MKK][10] = 68, @@ -28850,6 +31874,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][0][0][0][RTW89_ACMA][10] = 60, [0][0][0][0][RTW89_CN][10] = 58, [0][0][0][0][RTW89_UK][10] = 60, + [0][0][0][0][RTW89_MEXICO][10] = 76, + [0][0][0][0][RTW89_UKRAINE][10] = 60, + [0][0][0][0][RTW89_CHILE][10] = 76, + [0][0][0][0][RTW89_QATAR][10] = 60, [0][0][0][0][RTW89_FCC][11] = 58, [0][0][0][0][RTW89_ETSI][11] = 60, [0][0][0][0][RTW89_MKK][11] = 68, @@ -28858,6 +31886,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][0][0][0][RTW89_ACMA][11] = 60, [0][0][0][0][RTW89_CN][11] = 58, [0][0][0][0][RTW89_UK][11] = 60, + [0][0][0][0][RTW89_MEXICO][11] = 58, + [0][0][0][0][RTW89_UKRAINE][11] = 60, + [0][0][0][0][RTW89_CHILE][11] = 58, + [0][0][0][0][RTW89_QATAR][11] = 60, [0][0][0][0][RTW89_FCC][12] = 46, [0][0][0][0][RTW89_ETSI][12] = 60, [0][0][0][0][RTW89_MKK][12] = 68, @@ -28866,6 +31898,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][0][0][0][RTW89_ACMA][12] = 60, [0][0][0][0][RTW89_CN][12] = 58, [0][0][0][0][RTW89_UK][12] = 60, + [0][0][0][0][RTW89_MEXICO][12] = 46, + [0][0][0][0][RTW89_UKRAINE][12] = 60, + [0][0][0][0][RTW89_CHILE][12] = 46, + [0][0][0][0][RTW89_QATAR][12] = 60, [0][0][0][0][RTW89_FCC][13] = 127, [0][0][0][0][RTW89_ETSI][13] = 127, [0][0][0][0][RTW89_MKK][13] = 72, @@ -28874,6 +31910,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][0][0][0][RTW89_ACMA][13] = 127, [0][0][0][0][RTW89_CN][13] = 127, [0][0][0][0][RTW89_UK][13] = 127, + [0][0][0][0][RTW89_MEXICO][13] = 127, + [0][0][0][0][RTW89_UKRAINE][13] = 127, + [0][0][0][0][RTW89_CHILE][13] = 127, + [0][0][0][0][RTW89_QATAR][13] = 127, [0][1][0][0][RTW89_FCC][0] = 76, [0][1][0][0][RTW89_ETSI][0] = 48, [0][1][0][0][RTW89_MKK][0] = 58, @@ -28882,6 +31922,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][0][0][RTW89_ACMA][0] = 48, [0][1][0][0][RTW89_CN][0] = 42, [0][1][0][0][RTW89_UK][0] = 48, + [0][1][0][0][RTW89_MEXICO][0] = 76, + [0][1][0][0][RTW89_UKRAINE][0] = 48, + [0][1][0][0][RTW89_CHILE][0] = 76, + [0][1][0][0][RTW89_QATAR][0] = 48, [0][1][0][0][RTW89_FCC][1] = 76, [0][1][0][0][RTW89_ETSI][1] = 48, [0][1][0][0][RTW89_MKK][1] = 58, @@ -28890,6 +31934,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][0][0][RTW89_ACMA][1] = 48, [0][1][0][0][RTW89_CN][1] = 42, [0][1][0][0][RTW89_UK][1] = 48, + [0][1][0][0][RTW89_MEXICO][1] = 76, + [0][1][0][0][RTW89_UKRAINE][1] = 48, + [0][1][0][0][RTW89_CHILE][1] = 54, + [0][1][0][0][RTW89_QATAR][1] = 48, [0][1][0][0][RTW89_FCC][2] = 76, [0][1][0][0][RTW89_ETSI][2] = 48, [0][1][0][0][RTW89_MKK][2] = 58, @@ -28898,6 +31946,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][0][0][RTW89_ACMA][2] = 48, [0][1][0][0][RTW89_CN][2] = 42, [0][1][0][0][RTW89_UK][2] = 48, + [0][1][0][0][RTW89_MEXICO][2] = 76, + [0][1][0][0][RTW89_UKRAINE][2] = 48, + [0][1][0][0][RTW89_CHILE][2] = 54, + [0][1][0][0][RTW89_QATAR][2] = 48, [0][1][0][0][RTW89_FCC][3] = 76, [0][1][0][0][RTW89_ETSI][3] = 48, [0][1][0][0][RTW89_MKK][3] = 58, @@ -28906,6 +31958,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][0][0][RTW89_ACMA][3] = 48, [0][1][0][0][RTW89_CN][3] = 42, [0][1][0][0][RTW89_UK][3] = 48, + [0][1][0][0][RTW89_MEXICO][3] = 76, + [0][1][0][0][RTW89_UKRAINE][3] = 48, + [0][1][0][0][RTW89_CHILE][3] = 54, + [0][1][0][0][RTW89_QATAR][3] = 48, [0][1][0][0][RTW89_FCC][4] = 76, [0][1][0][0][RTW89_ETSI][4] = 48, [0][1][0][0][RTW89_MKK][4] = 58, @@ -28914,6 +31970,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][0][0][RTW89_ACMA][4] = 48, [0][1][0][0][RTW89_CN][4] = 42, [0][1][0][0][RTW89_UK][4] = 48, + [0][1][0][0][RTW89_MEXICO][4] = 76, + [0][1][0][0][RTW89_UKRAINE][4] = 48, + [0][1][0][0][RTW89_CHILE][4] = 54, + [0][1][0][0][RTW89_QATAR][4] = 48, [0][1][0][0][RTW89_FCC][5] = 76, [0][1][0][0][RTW89_ETSI][5] = 48, [0][1][0][0][RTW89_MKK][5] = 58, @@ -28922,6 +31982,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][0][0][RTW89_ACMA][5] = 48, [0][1][0][0][RTW89_CN][5] = 42, [0][1][0][0][RTW89_UK][5] = 48, + [0][1][0][0][RTW89_MEXICO][5] = 76, + [0][1][0][0][RTW89_UKRAINE][5] = 48, + [0][1][0][0][RTW89_CHILE][5] = 76, + [0][1][0][0][RTW89_QATAR][5] = 48, [0][1][0][0][RTW89_FCC][6] = 76, [0][1][0][0][RTW89_ETSI][6] = 48, [0][1][0][0][RTW89_MKK][6] = 58, @@ -28930,6 +31994,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][0][0][RTW89_ACMA][6] = 48, [0][1][0][0][RTW89_CN][6] = 42, [0][1][0][0][RTW89_UK][6] = 48, + [0][1][0][0][RTW89_MEXICO][6] = 76, + [0][1][0][0][RTW89_UKRAINE][6] = 48, + [0][1][0][0][RTW89_CHILE][6] = 76, + [0][1][0][0][RTW89_QATAR][6] = 48, [0][1][0][0][RTW89_FCC][7] = 76, [0][1][0][0][RTW89_ETSI][7] = 48, [0][1][0][0][RTW89_MKK][7] = 58, @@ -28938,6 +32006,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][0][0][RTW89_ACMA][7] = 48, [0][1][0][0][RTW89_CN][7] = 42, [0][1][0][0][RTW89_UK][7] = 48, + [0][1][0][0][RTW89_MEXICO][7] = 76, + [0][1][0][0][RTW89_UKRAINE][7] = 48, + [0][1][0][0][RTW89_CHILE][7] = 76, + [0][1][0][0][RTW89_QATAR][7] = 48, [0][1][0][0][RTW89_FCC][8] = 76, [0][1][0][0][RTW89_ETSI][8] = 48, [0][1][0][0][RTW89_MKK][8] = 58, @@ -28946,6 +32018,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][0][0][RTW89_ACMA][8] = 48, [0][1][0][0][RTW89_CN][8] = 42, [0][1][0][0][RTW89_UK][8] = 48, + [0][1][0][0][RTW89_MEXICO][8] = 76, + [0][1][0][0][RTW89_UKRAINE][8] = 48, + [0][1][0][0][RTW89_CHILE][8] = 76, + [0][1][0][0][RTW89_QATAR][8] = 48, [0][1][0][0][RTW89_FCC][9] = 70, [0][1][0][0][RTW89_ETSI][9] = 48, [0][1][0][0][RTW89_MKK][9] = 58, @@ -28954,6 +32030,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][0][0][RTW89_ACMA][9] = 48, [0][1][0][0][RTW89_CN][9] = 42, [0][1][0][0][RTW89_UK][9] = 48, + [0][1][0][0][RTW89_MEXICO][9] = 70, + [0][1][0][0][RTW89_UKRAINE][9] = 48, + [0][1][0][0][RTW89_CHILE][9] = 70, + [0][1][0][0][RTW89_QATAR][9] = 48, [0][1][0][0][RTW89_FCC][10] = 72, [0][1][0][0][RTW89_ETSI][10] = 48, [0][1][0][0][RTW89_MKK][10] = 58, @@ -28962,6 +32042,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][0][0][RTW89_ACMA][10] = 48, [0][1][0][0][RTW89_CN][10] = 42, [0][1][0][0][RTW89_UK][10] = 48, + [0][1][0][0][RTW89_MEXICO][10] = 72, + [0][1][0][0][RTW89_UKRAINE][10] = 48, + [0][1][0][0][RTW89_CHILE][10] = 72, + [0][1][0][0][RTW89_QATAR][10] = 48, [0][1][0][0][RTW89_FCC][11] = 44, [0][1][0][0][RTW89_ETSI][11] = 48, [0][1][0][0][RTW89_MKK][11] = 58, @@ -28970,6 +32054,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][0][0][RTW89_ACMA][11] = 48, [0][1][0][0][RTW89_CN][11] = 42, [0][1][0][0][RTW89_UK][11] = 48, + [0][1][0][0][RTW89_MEXICO][11] = 44, + [0][1][0][0][RTW89_UKRAINE][11] = 48, + [0][1][0][0][RTW89_CHILE][11] = 44, + [0][1][0][0][RTW89_QATAR][11] = 48, [0][1][0][0][RTW89_FCC][12] = 18, [0][1][0][0][RTW89_ETSI][12] = 48, [0][1][0][0][RTW89_MKK][12] = 58, @@ -28978,6 +32066,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][0][0][RTW89_ACMA][12] = 48, [0][1][0][0][RTW89_CN][12] = 42, [0][1][0][0][RTW89_UK][12] = 48, + [0][1][0][0][RTW89_MEXICO][12] = 18, + [0][1][0][0][RTW89_UKRAINE][12] = 48, + [0][1][0][0][RTW89_CHILE][12] = 18, + [0][1][0][0][RTW89_QATAR][12] = 48, [0][1][0][0][RTW89_FCC][13] = 127, [0][1][0][0][RTW89_ETSI][13] = 127, [0][1][0][0][RTW89_MKK][13] = 60, @@ -28986,6 +32078,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][0][0][RTW89_ACMA][13] = 127, [0][1][0][0][RTW89_CN][13] = 127, [0][1][0][0][RTW89_UK][13] = 127, + [0][1][0][0][RTW89_MEXICO][13] = 127, + [0][1][0][0][RTW89_UKRAINE][13] = 127, + [0][1][0][0][RTW89_CHILE][13] = 127, + [0][1][0][0][RTW89_QATAR][13] = 127, [1][0][0][0][RTW89_FCC][0] = 127, [1][0][0][0][RTW89_ETSI][0] = 127, [1][0][0][0][RTW89_MKK][0] = 127, @@ -28994,6 +32090,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][0][0][0][RTW89_ACMA][0] = 127, [1][0][0][0][RTW89_CN][0] = 127, [1][0][0][0][RTW89_UK][0] = 127, + [1][0][0][0][RTW89_MEXICO][0] = 127, + [1][0][0][0][RTW89_UKRAINE][0] = 127, + [1][0][0][0][RTW89_CHILE][0] = 127, + [1][0][0][0][RTW89_QATAR][0] = 127, [1][0][0][0][RTW89_FCC][1] = 127, [1][0][0][0][RTW89_ETSI][1] = 127, [1][0][0][0][RTW89_MKK][1] = 127, @@ -29002,6 +32102,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][0][0][0][RTW89_ACMA][1] = 127, [1][0][0][0][RTW89_CN][1] = 127, [1][0][0][0][RTW89_UK][1] = 127, + [1][0][0][0][RTW89_MEXICO][1] = 127, + [1][0][0][0][RTW89_UKRAINE][1] = 127, + [1][0][0][0][RTW89_CHILE][1] = 127, + [1][0][0][0][RTW89_QATAR][1] = 127, [1][0][0][0][RTW89_FCC][2] = 44, [1][0][0][0][RTW89_ETSI][2] = 60, [1][0][0][0][RTW89_MKK][2] = 66, @@ -29010,6 +32114,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][0][0][0][RTW89_ACMA][2] = 60, [1][0][0][0][RTW89_CN][2] = 58, [1][0][0][0][RTW89_UK][2] = 60, + [1][0][0][0][RTW89_MEXICO][2] = 44, + [1][0][0][0][RTW89_UKRAINE][2] = 60, + [1][0][0][0][RTW89_CHILE][2] = 44, + [1][0][0][0][RTW89_QATAR][2] = 60, [1][0][0][0][RTW89_FCC][3] = 60, [1][0][0][0][RTW89_ETSI][3] = 60, [1][0][0][0][RTW89_MKK][3] = 66, @@ -29018,6 +32126,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][0][0][0][RTW89_ACMA][3] = 60, [1][0][0][0][RTW89_CN][3] = 58, [1][0][0][0][RTW89_UK][3] = 60, + [1][0][0][0][RTW89_MEXICO][3] = 60, + [1][0][0][0][RTW89_UKRAINE][3] = 60, + [1][0][0][0][RTW89_CHILE][3] = 60, + [1][0][0][0][RTW89_QATAR][3] = 60, [1][0][0][0][RTW89_FCC][4] = 60, [1][0][0][0][RTW89_ETSI][4] = 60, [1][0][0][0][RTW89_MKK][4] = 66, @@ -29026,6 +32138,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][0][0][0][RTW89_ACMA][4] = 60, [1][0][0][0][RTW89_CN][4] = 58, [1][0][0][0][RTW89_UK][4] = 60, + [1][0][0][0][RTW89_MEXICO][4] = 60, + [1][0][0][0][RTW89_UKRAINE][4] = 60, + [1][0][0][0][RTW89_CHILE][4] = 60, + [1][0][0][0][RTW89_QATAR][4] = 60, [1][0][0][0][RTW89_FCC][5] = 62, [1][0][0][0][RTW89_ETSI][5] = 60, [1][0][0][0][RTW89_MKK][5] = 66, @@ -29034,6 +32150,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][0][0][0][RTW89_ACMA][5] = 60, [1][0][0][0][RTW89_CN][5] = 58, [1][0][0][0][RTW89_UK][5] = 60, + [1][0][0][0][RTW89_MEXICO][5] = 62, + [1][0][0][0][RTW89_UKRAINE][5] = 60, + [1][0][0][0][RTW89_CHILE][5] = 62, + [1][0][0][0][RTW89_QATAR][5] = 60, [1][0][0][0][RTW89_FCC][6] = 46, [1][0][0][0][RTW89_ETSI][6] = 60, [1][0][0][0][RTW89_MKK][6] = 66, @@ -29042,6 +32162,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][0][0][0][RTW89_ACMA][6] = 60, [1][0][0][0][RTW89_CN][6] = 58, [1][0][0][0][RTW89_UK][6] = 60, + [1][0][0][0][RTW89_MEXICO][6] = 46, + [1][0][0][0][RTW89_UKRAINE][6] = 60, + [1][0][0][0][RTW89_CHILE][6] = 46, + [1][0][0][0][RTW89_QATAR][6] = 60, [1][0][0][0][RTW89_FCC][7] = 46, [1][0][0][0][RTW89_ETSI][7] = 60, [1][0][0][0][RTW89_MKK][7] = 66, @@ -29050,6 +32174,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][0][0][0][RTW89_ACMA][7] = 60, [1][0][0][0][RTW89_CN][7] = 58, [1][0][0][0][RTW89_UK][7] = 60, + [1][0][0][0][RTW89_MEXICO][7] = 46, + [1][0][0][0][RTW89_UKRAINE][7] = 60, + [1][0][0][0][RTW89_CHILE][7] = 46, + [1][0][0][0][RTW89_QATAR][7] = 60, [1][0][0][0][RTW89_FCC][8] = 28, [1][0][0][0][RTW89_ETSI][8] = 60, [1][0][0][0][RTW89_MKK][8] = 66, @@ -29058,6 +32186,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][0][0][0][RTW89_ACMA][8] = 60, [1][0][0][0][RTW89_CN][8] = 58, [1][0][0][0][RTW89_UK][8] = 60, + [1][0][0][0][RTW89_MEXICO][8] = 28, + [1][0][0][0][RTW89_UKRAINE][8] = 60, + [1][0][0][0][RTW89_CHILE][8] = 28, + [1][0][0][0][RTW89_QATAR][8] = 60, [1][0][0][0][RTW89_FCC][9] = 26, [1][0][0][0][RTW89_ETSI][9] = 60, [1][0][0][0][RTW89_MKK][9] = 66, @@ -29066,6 +32198,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][0][0][0][RTW89_ACMA][9] = 60, [1][0][0][0][RTW89_CN][9] = 58, [1][0][0][0][RTW89_UK][9] = 60, + [1][0][0][0][RTW89_MEXICO][9] = 26, + [1][0][0][0][RTW89_UKRAINE][9] = 60, + [1][0][0][0][RTW89_CHILE][9] = 26, + [1][0][0][0][RTW89_QATAR][9] = 60, [1][0][0][0][RTW89_FCC][10] = 26, [1][0][0][0][RTW89_ETSI][10] = 60, [1][0][0][0][RTW89_MKK][10] = 66, @@ -29074,6 +32210,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][0][0][0][RTW89_ACMA][10] = 60, [1][0][0][0][RTW89_CN][10] = 58, [1][0][0][0][RTW89_UK][10] = 60, + [1][0][0][0][RTW89_MEXICO][10] = 26, + [1][0][0][0][RTW89_UKRAINE][10] = 60, + [1][0][0][0][RTW89_CHILE][10] = 26, + [1][0][0][0][RTW89_QATAR][10] = 60, [1][0][0][0][RTW89_FCC][11] = 127, [1][0][0][0][RTW89_ETSI][11] = 127, [1][0][0][0][RTW89_MKK][11] = 127, @@ -29082,6 +32222,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][0][0][0][RTW89_ACMA][11] = 127, [1][0][0][0][RTW89_CN][11] = 127, [1][0][0][0][RTW89_UK][11] = 127, + [1][0][0][0][RTW89_MEXICO][11] = 127, + [1][0][0][0][RTW89_UKRAINE][11] = 127, + [1][0][0][0][RTW89_CHILE][11] = 127, + [1][0][0][0][RTW89_QATAR][11] = 127, [1][0][0][0][RTW89_FCC][12] = 127, [1][0][0][0][RTW89_ETSI][12] = 127, [1][0][0][0][RTW89_MKK][12] = 127, @@ -29090,6 +32234,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][0][0][0][RTW89_ACMA][12] = 127, [1][0][0][0][RTW89_CN][12] = 127, [1][0][0][0][RTW89_UK][12] = 127, + [1][0][0][0][RTW89_MEXICO][12] = 127, + [1][0][0][0][RTW89_UKRAINE][12] = 127, + [1][0][0][0][RTW89_CHILE][12] = 127, + [1][0][0][0][RTW89_QATAR][12] = 127, [1][0][0][0][RTW89_FCC][13] = 127, [1][0][0][0][RTW89_ETSI][13] = 127, [1][0][0][0][RTW89_MKK][13] = 127, @@ -29098,6 +32246,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][0][0][0][RTW89_ACMA][13] = 127, [1][0][0][0][RTW89_CN][13] = 127, [1][0][0][0][RTW89_UK][13] = 127, + [1][0][0][0][RTW89_MEXICO][13] = 127, + [1][0][0][0][RTW89_UKRAINE][13] = 127, + [1][0][0][0][RTW89_CHILE][13] = 127, + [1][0][0][0][RTW89_QATAR][13] = 127, [1][1][0][0][RTW89_FCC][0] = 127, [1][1][0][0][RTW89_ETSI][0] = 127, [1][1][0][0][RTW89_MKK][0] = 127, @@ -29106,6 +32258,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][1][0][0][RTW89_ACMA][0] = 127, [1][1][0][0][RTW89_CN][0] = 127, [1][1][0][0][RTW89_UK][0] = 127, + [1][1][0][0][RTW89_MEXICO][0] = 127, + [1][1][0][0][RTW89_UKRAINE][0] = 127, + [1][1][0][0][RTW89_CHILE][0] = 127, + [1][1][0][0][RTW89_QATAR][0] = 127, [1][1][0][0][RTW89_FCC][1] = 127, [1][1][0][0][RTW89_ETSI][1] = 127, [1][1][0][0][RTW89_MKK][1] = 127, @@ -29114,6 +32270,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][1][0][0][RTW89_ACMA][1] = 127, [1][1][0][0][RTW89_CN][1] = 127, [1][1][0][0][RTW89_UK][1] = 127, + [1][1][0][0][RTW89_MEXICO][1] = 127, + [1][1][0][0][RTW89_UKRAINE][1] = 127, + [1][1][0][0][RTW89_CHILE][1] = 127, + [1][1][0][0][RTW89_QATAR][1] = 127, [1][1][0][0][RTW89_FCC][2] = 46, [1][1][0][0][RTW89_ETSI][2] = 48, [1][1][0][0][RTW89_MKK][2] = 58, @@ -29122,6 +32282,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][1][0][0][RTW89_ACMA][2] = 48, [1][1][0][0][RTW89_CN][2] = 46, [1][1][0][0][RTW89_UK][2] = 48, + [1][1][0][0][RTW89_MEXICO][2] = 46, + [1][1][0][0][RTW89_UKRAINE][2] = 48, + [1][1][0][0][RTW89_CHILE][2] = 46, + [1][1][0][0][RTW89_QATAR][2] = 48, [1][1][0][0][RTW89_FCC][3] = 46, [1][1][0][0][RTW89_ETSI][3] = 48, [1][1][0][0][RTW89_MKK][3] = 58, @@ -29130,6 +32294,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][1][0][0][RTW89_ACMA][3] = 48, [1][1][0][0][RTW89_CN][3] = 46, [1][1][0][0][RTW89_UK][3] = 48, + [1][1][0][0][RTW89_MEXICO][3] = 46, + [1][1][0][0][RTW89_UKRAINE][3] = 48, + [1][1][0][0][RTW89_CHILE][3] = 46, + [1][1][0][0][RTW89_QATAR][3] = 48, [1][1][0][0][RTW89_FCC][4] = 46, [1][1][0][0][RTW89_ETSI][4] = 48, [1][1][0][0][RTW89_MKK][4] = 58, @@ -29138,6 +32306,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][1][0][0][RTW89_ACMA][4] = 48, [1][1][0][0][RTW89_CN][4] = 46, [1][1][0][0][RTW89_UK][4] = 48, + [1][1][0][0][RTW89_MEXICO][4] = 46, + [1][1][0][0][RTW89_UKRAINE][4] = 48, + [1][1][0][0][RTW89_CHILE][4] = 46, + [1][1][0][0][RTW89_QATAR][4] = 48, [1][1][0][0][RTW89_FCC][5] = 48, [1][1][0][0][RTW89_ETSI][5] = 48, [1][1][0][0][RTW89_MKK][5] = 58, @@ -29146,6 +32318,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][1][0][0][RTW89_ACMA][5] = 48, [1][1][0][0][RTW89_CN][5] = 46, [1][1][0][0][RTW89_UK][5] = 48, + [1][1][0][0][RTW89_MEXICO][5] = 48, + [1][1][0][0][RTW89_UKRAINE][5] = 48, + [1][1][0][0][RTW89_CHILE][5] = 48, + [1][1][0][0][RTW89_QATAR][5] = 48, [1][1][0][0][RTW89_FCC][6] = 40, [1][1][0][0][RTW89_ETSI][6] = 48, [1][1][0][0][RTW89_MKK][6] = 58, @@ -29154,6 +32330,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][1][0][0][RTW89_ACMA][6] = 48, [1][1][0][0][RTW89_CN][6] = 46, [1][1][0][0][RTW89_UK][6] = 48, + [1][1][0][0][RTW89_MEXICO][6] = 40, + [1][1][0][0][RTW89_UKRAINE][6] = 48, + [1][1][0][0][RTW89_CHILE][6] = 40, + [1][1][0][0][RTW89_QATAR][6] = 48, [1][1][0][0][RTW89_FCC][7] = 40, [1][1][0][0][RTW89_ETSI][7] = 48, [1][1][0][0][RTW89_MKK][7] = 58, @@ -29162,6 +32342,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][1][0][0][RTW89_ACMA][7] = 48, [1][1][0][0][RTW89_CN][7] = 46, [1][1][0][0][RTW89_UK][7] = 48, + [1][1][0][0][RTW89_MEXICO][7] = 40, + [1][1][0][0][RTW89_UKRAINE][7] = 48, + [1][1][0][0][RTW89_CHILE][7] = 40, + [1][1][0][0][RTW89_QATAR][7] = 48, [1][1][0][0][RTW89_FCC][8] = 14, [1][1][0][0][RTW89_ETSI][8] = 48, [1][1][0][0][RTW89_MKK][8] = 58, @@ -29170,6 +32354,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][1][0][0][RTW89_ACMA][8] = 48, [1][1][0][0][RTW89_CN][8] = 46, [1][1][0][0][RTW89_UK][8] = 48, + [1][1][0][0][RTW89_MEXICO][8] = 14, + [1][1][0][0][RTW89_UKRAINE][8] = 48, + [1][1][0][0][RTW89_CHILE][8] = 14, + [1][1][0][0][RTW89_QATAR][8] = 48, [1][1][0][0][RTW89_FCC][9] = 14, [1][1][0][0][RTW89_ETSI][9] = 48, [1][1][0][0][RTW89_MKK][9] = 58, @@ -29178,6 +32366,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][1][0][0][RTW89_ACMA][9] = 48, [1][1][0][0][RTW89_CN][9] = 46, [1][1][0][0][RTW89_UK][9] = 48, + [1][1][0][0][RTW89_MEXICO][9] = 14, + [1][1][0][0][RTW89_UKRAINE][9] = 48, + [1][1][0][0][RTW89_CHILE][9] = 14, + [1][1][0][0][RTW89_QATAR][9] = 48, [1][1][0][0][RTW89_FCC][10] = 12, [1][1][0][0][RTW89_ETSI][10] = 48, [1][1][0][0][RTW89_MKK][10] = 56, @@ -29186,6 +32378,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][1][0][0][RTW89_ACMA][10] = 48, [1][1][0][0][RTW89_CN][10] = 46, [1][1][0][0][RTW89_UK][10] = 48, + [1][1][0][0][RTW89_MEXICO][10] = 12, + [1][1][0][0][RTW89_UKRAINE][10] = 48, + [1][1][0][0][RTW89_CHILE][10] = 12, + [1][1][0][0][RTW89_QATAR][10] = 48, [1][1][0][0][RTW89_FCC][11] = 127, [1][1][0][0][RTW89_ETSI][11] = 127, [1][1][0][0][RTW89_MKK][11] = 127, @@ -29194,6 +32390,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][1][0][0][RTW89_ACMA][11] = 127, [1][1][0][0][RTW89_CN][11] = 127, [1][1][0][0][RTW89_UK][11] = 127, + [1][1][0][0][RTW89_MEXICO][11] = 127, + [1][1][0][0][RTW89_UKRAINE][11] = 127, + [1][1][0][0][RTW89_CHILE][11] = 127, + [1][1][0][0][RTW89_QATAR][11] = 127, [1][1][0][0][RTW89_FCC][12] = 127, [1][1][0][0][RTW89_ETSI][12] = 127, [1][1][0][0][RTW89_MKK][12] = 127, @@ -29202,6 +32402,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][1][0][0][RTW89_ACMA][12] = 127, [1][1][0][0][RTW89_CN][12] = 127, [1][1][0][0][RTW89_UK][12] = 127, + [1][1][0][0][RTW89_MEXICO][12] = 127, + [1][1][0][0][RTW89_UKRAINE][12] = 127, + [1][1][0][0][RTW89_CHILE][12] = 127, + [1][1][0][0][RTW89_QATAR][12] = 127, [1][1][0][0][RTW89_FCC][13] = 127, [1][1][0][0][RTW89_ETSI][13] = 127, [1][1][0][0][RTW89_MKK][13] = 127, @@ -29210,6 +32414,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][1][0][0][RTW89_ACMA][13] = 127, [1][1][0][0][RTW89_CN][13] = 127, [1][1][0][0][RTW89_UK][13] = 127, + [1][1][0][0][RTW89_MEXICO][13] = 127, + [1][1][0][0][RTW89_UKRAINE][13] = 127, + [1][1][0][0][RTW89_CHILE][13] = 127, + [1][1][0][0][RTW89_QATAR][13] = 127, [0][0][1][0][RTW89_FCC][0] = 66, [0][0][1][0][RTW89_ETSI][0] = 60, [0][0][1][0][RTW89_MKK][0] = 76, @@ -29218,6 +32426,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_ACMA][0] = 60, [0][0][1][0][RTW89_CN][0] = 58, [0][0][1][0][RTW89_UK][0] = 60, + [0][0][1][0][RTW89_MEXICO][0] = 66, + [0][0][1][0][RTW89_UKRAINE][0] = 60, + [0][0][1][0][RTW89_CHILE][0] = 66, + [0][0][1][0][RTW89_QATAR][0] = 60, [0][0][1][0][RTW89_FCC][1] = 68, [0][0][1][0][RTW89_ETSI][1] = 60, [0][0][1][0][RTW89_MKK][1] = 78, @@ -29226,6 +32438,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_ACMA][1] = 60, [0][0][1][0][RTW89_CN][1] = 58, [0][0][1][0][RTW89_UK][1] = 60, + [0][0][1][0][RTW89_MEXICO][1] = 68, + [0][0][1][0][RTW89_UKRAINE][1] = 60, + [0][0][1][0][RTW89_CHILE][1] = 68, + [0][0][1][0][RTW89_QATAR][1] = 60, [0][0][1][0][RTW89_FCC][2] = 72, [0][0][1][0][RTW89_ETSI][2] = 60, [0][0][1][0][RTW89_MKK][2] = 78, @@ -29234,6 +32450,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_ACMA][2] = 60, [0][0][1][0][RTW89_CN][2] = 58, [0][0][1][0][RTW89_UK][2] = 60, + [0][0][1][0][RTW89_MEXICO][2] = 72, + [0][0][1][0][RTW89_UKRAINE][2] = 60, + [0][0][1][0][RTW89_CHILE][2] = 62, + [0][0][1][0][RTW89_QATAR][2] = 60, [0][0][1][0][RTW89_FCC][3] = 76, [0][0][1][0][RTW89_ETSI][3] = 60, [0][0][1][0][RTW89_MKK][3] = 78, @@ -29242,6 +32462,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_ACMA][3] = 60, [0][0][1][0][RTW89_CN][3] = 58, [0][0][1][0][RTW89_UK][3] = 60, + [0][0][1][0][RTW89_MEXICO][3] = 76, + [0][0][1][0][RTW89_UKRAINE][3] = 60, + [0][0][1][0][RTW89_CHILE][3] = 62, + [0][0][1][0][RTW89_QATAR][3] = 60, [0][0][1][0][RTW89_FCC][4] = 80, [0][0][1][0][RTW89_ETSI][4] = 60, [0][0][1][0][RTW89_MKK][4] = 78, @@ -29250,6 +32474,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_ACMA][4] = 60, [0][0][1][0][RTW89_CN][4] = 58, [0][0][1][0][RTW89_UK][4] = 60, + [0][0][1][0][RTW89_MEXICO][4] = 80, + [0][0][1][0][RTW89_UKRAINE][4] = 60, + [0][0][1][0][RTW89_CHILE][4] = 62, + [0][0][1][0][RTW89_QATAR][4] = 60, [0][0][1][0][RTW89_FCC][5] = 80, [0][0][1][0][RTW89_ETSI][5] = 60, [0][0][1][0][RTW89_MKK][5] = 78, @@ -29258,6 +32486,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_ACMA][5] = 60, [0][0][1][0][RTW89_CN][5] = 58, [0][0][1][0][RTW89_UK][5] = 60, + [0][0][1][0][RTW89_MEXICO][5] = 80, + [0][0][1][0][RTW89_UKRAINE][5] = 60, + [0][0][1][0][RTW89_CHILE][5] = 80, + [0][0][1][0][RTW89_QATAR][5] = 60, [0][0][1][0][RTW89_FCC][6] = 80, [0][0][1][0][RTW89_ETSI][6] = 60, [0][0][1][0][RTW89_MKK][6] = 76, @@ -29266,6 +32498,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_ACMA][6] = 60, [0][0][1][0][RTW89_CN][6] = 58, [0][0][1][0][RTW89_UK][6] = 60, + [0][0][1][0][RTW89_MEXICO][6] = 80, + [0][0][1][0][RTW89_UKRAINE][6] = 60, + [0][0][1][0][RTW89_CHILE][6] = 70, + [0][0][1][0][RTW89_QATAR][6] = 60, [0][0][1][0][RTW89_FCC][7] = 80, [0][0][1][0][RTW89_ETSI][7] = 60, [0][0][1][0][RTW89_MKK][7] = 78, @@ -29274,6 +32510,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_ACMA][7] = 60, [0][0][1][0][RTW89_CN][7] = 58, [0][0][1][0][RTW89_UK][7] = 60, + [0][0][1][0][RTW89_MEXICO][7] = 80, + [0][0][1][0][RTW89_UKRAINE][7] = 60, + [0][0][1][0][RTW89_CHILE][7] = 70, + [0][0][1][0][RTW89_QATAR][7] = 60, [0][0][1][0][RTW89_FCC][8] = 80, [0][0][1][0][RTW89_ETSI][8] = 60, [0][0][1][0][RTW89_MKK][8] = 78, @@ -29282,6 +32522,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_ACMA][8] = 60, [0][0][1][0][RTW89_CN][8] = 58, [0][0][1][0][RTW89_UK][8] = 60, + [0][0][1][0][RTW89_MEXICO][8] = 80, + [0][0][1][0][RTW89_UKRAINE][8] = 60, + [0][0][1][0][RTW89_CHILE][8] = 70, + [0][0][1][0][RTW89_QATAR][8] = 60, [0][0][1][0][RTW89_FCC][9] = 76, [0][0][1][0][RTW89_ETSI][9] = 60, [0][0][1][0][RTW89_MKK][9] = 78, @@ -29290,6 +32534,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_ACMA][9] = 60, [0][0][1][0][RTW89_CN][9] = 58, [0][0][1][0][RTW89_UK][9] = 60, + [0][0][1][0][RTW89_MEXICO][9] = 76, + [0][0][1][0][RTW89_UKRAINE][9] = 60, + [0][0][1][0][RTW89_CHILE][9] = 76, + [0][0][1][0][RTW89_QATAR][9] = 60, [0][0][1][0][RTW89_FCC][10] = 66, [0][0][1][0][RTW89_ETSI][10] = 60, [0][0][1][0][RTW89_MKK][10] = 78, @@ -29298,6 +32546,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_ACMA][10] = 60, [0][0][1][0][RTW89_CN][10] = 58, [0][0][1][0][RTW89_UK][10] = 60, + [0][0][1][0][RTW89_MEXICO][10] = 66, + [0][0][1][0][RTW89_UKRAINE][10] = 60, + [0][0][1][0][RTW89_CHILE][10] = 66, + [0][0][1][0][RTW89_QATAR][10] = 60, [0][0][1][0][RTW89_FCC][11] = 62, [0][0][1][0][RTW89_ETSI][11] = 60, [0][0][1][0][RTW89_MKK][11] = 78, @@ -29306,6 +32558,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_ACMA][11] = 60, [0][0][1][0][RTW89_CN][11] = 58, [0][0][1][0][RTW89_UK][11] = 60, + [0][0][1][0][RTW89_MEXICO][11] = 62, + [0][0][1][0][RTW89_UKRAINE][11] = 60, + [0][0][1][0][RTW89_CHILE][11] = 62, + [0][0][1][0][RTW89_QATAR][11] = 60, [0][0][1][0][RTW89_FCC][12] = 60, [0][0][1][0][RTW89_ETSI][12] = 60, [0][0][1][0][RTW89_MKK][12] = 78, @@ -29314,6 +32570,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_ACMA][12] = 60, [0][0][1][0][RTW89_CN][12] = 58, [0][0][1][0][RTW89_UK][12] = 60, + [0][0][1][0][RTW89_MEXICO][12] = 60, + [0][0][1][0][RTW89_UKRAINE][12] = 60, + [0][0][1][0][RTW89_CHILE][12] = 60, + [0][0][1][0][RTW89_QATAR][12] = 60, [0][0][1][0][RTW89_FCC][13] = 127, [0][0][1][0][RTW89_ETSI][13] = 127, [0][0][1][0][RTW89_MKK][13] = 127, @@ -29322,6 +32582,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_ACMA][13] = 127, [0][0][1][0][RTW89_CN][13] = 127, [0][0][1][0][RTW89_UK][13] = 127, + [0][0][1][0][RTW89_MEXICO][13] = 127, + [0][0][1][0][RTW89_UKRAINE][13] = 127, + [0][0][1][0][RTW89_CHILE][13] = 127, + [0][0][1][0][RTW89_QATAR][13] = 127, [0][1][1][0][RTW89_FCC][0] = 66, [0][1][1][0][RTW89_ETSI][0] = 48, [0][1][1][0][RTW89_MKK][0] = 66, @@ -29330,6 +32594,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][1][0][RTW89_ACMA][0] = 48, [0][1][1][0][RTW89_CN][0] = 46, [0][1][1][0][RTW89_UK][0] = 48, + [0][1][1][0][RTW89_MEXICO][0] = 66, + [0][1][1][0][RTW89_UKRAINE][0] = 48, + [0][1][1][0][RTW89_CHILE][0] = 66, + [0][1][1][0][RTW89_QATAR][0] = 48, [0][1][1][0][RTW89_FCC][1] = 68, [0][1][1][0][RTW89_ETSI][1] = 48, [0][1][1][0][RTW89_MKK][1] = 66, @@ -29338,6 +32606,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][1][0][RTW89_ACMA][1] = 48, [0][1][1][0][RTW89_CN][1] = 46, [0][1][1][0][RTW89_UK][1] = 48, + [0][1][1][0][RTW89_MEXICO][1] = 68, + [0][1][1][0][RTW89_UKRAINE][1] = 48, + [0][1][1][0][RTW89_CHILE][1] = 68, + [0][1][1][0][RTW89_QATAR][1] = 48, [0][1][1][0][RTW89_FCC][2] = 72, [0][1][1][0][RTW89_ETSI][2] = 48, [0][1][1][0][RTW89_MKK][2] = 66, @@ -29346,6 +32618,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][1][0][RTW89_ACMA][2] = 48, [0][1][1][0][RTW89_CN][2] = 46, [0][1][1][0][RTW89_UK][2] = 48, + [0][1][1][0][RTW89_MEXICO][2] = 72, + [0][1][1][0][RTW89_UKRAINE][2] = 48, + [0][1][1][0][RTW89_CHILE][2] = 54, + [0][1][1][0][RTW89_QATAR][2] = 48, [0][1][1][0][RTW89_FCC][3] = 76, [0][1][1][0][RTW89_ETSI][3] = 48, [0][1][1][0][RTW89_MKK][3] = 66, @@ -29354,6 +32630,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][1][0][RTW89_ACMA][3] = 48, [0][1][1][0][RTW89_CN][3] = 46, [0][1][1][0][RTW89_UK][3] = 48, + [0][1][1][0][RTW89_MEXICO][3] = 76, + [0][1][1][0][RTW89_UKRAINE][3] = 48, + [0][1][1][0][RTW89_CHILE][3] = 54, + [0][1][1][0][RTW89_QATAR][3] = 48, [0][1][1][0][RTW89_FCC][4] = 80, [0][1][1][0][RTW89_ETSI][4] = 48, [0][1][1][0][RTW89_MKK][4] = 66, @@ -29362,6 +32642,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][1][0][RTW89_ACMA][4] = 48, [0][1][1][0][RTW89_CN][4] = 46, [0][1][1][0][RTW89_UK][4] = 48, + [0][1][1][0][RTW89_MEXICO][4] = 80, + [0][1][1][0][RTW89_UKRAINE][4] = 48, + [0][1][1][0][RTW89_CHILE][4] = 54, + [0][1][1][0][RTW89_QATAR][4] = 48, [0][1][1][0][RTW89_FCC][5] = 80, [0][1][1][0][RTW89_ETSI][5] = 48, [0][1][1][0][RTW89_MKK][5] = 66, @@ -29370,6 +32654,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][1][0][RTW89_ACMA][5] = 48, [0][1][1][0][RTW89_CN][5] = 46, [0][1][1][0][RTW89_UK][5] = 48, + [0][1][1][0][RTW89_MEXICO][5] = 80, + [0][1][1][0][RTW89_UKRAINE][5] = 48, + [0][1][1][0][RTW89_CHILE][5] = 80, + [0][1][1][0][RTW89_QATAR][5] = 48, [0][1][1][0][RTW89_FCC][6] = 80, [0][1][1][0][RTW89_ETSI][6] = 48, [0][1][1][0][RTW89_MKK][6] = 66, @@ -29378,6 +32666,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][1][0][RTW89_ACMA][6] = 48, [0][1][1][0][RTW89_CN][6] = 46, [0][1][1][0][RTW89_UK][6] = 48, + [0][1][1][0][RTW89_MEXICO][6] = 80, + [0][1][1][0][RTW89_UKRAINE][6] = 48, + [0][1][1][0][RTW89_CHILE][6] = 56, + [0][1][1][0][RTW89_QATAR][6] = 48, [0][1][1][0][RTW89_FCC][7] = 78, [0][1][1][0][RTW89_ETSI][7] = 48, [0][1][1][0][RTW89_MKK][7] = 66, @@ -29386,6 +32678,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][1][0][RTW89_ACMA][7] = 48, [0][1][1][0][RTW89_CN][7] = 46, [0][1][1][0][RTW89_UK][7] = 48, + [0][1][1][0][RTW89_MEXICO][7] = 78, + [0][1][1][0][RTW89_UKRAINE][7] = 48, + [0][1][1][0][RTW89_CHILE][7] = 56, + [0][1][1][0][RTW89_QATAR][7] = 48, [0][1][1][0][RTW89_FCC][8] = 74, [0][1][1][0][RTW89_ETSI][8] = 48, [0][1][1][0][RTW89_MKK][8] = 66, @@ -29394,6 +32690,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][1][0][RTW89_ACMA][8] = 48, [0][1][1][0][RTW89_CN][8] = 46, [0][1][1][0][RTW89_UK][8] = 48, + [0][1][1][0][RTW89_MEXICO][8] = 74, + [0][1][1][0][RTW89_UKRAINE][8] = 48, + [0][1][1][0][RTW89_CHILE][8] = 56, + [0][1][1][0][RTW89_QATAR][8] = 48, [0][1][1][0][RTW89_FCC][9] = 70, [0][1][1][0][RTW89_ETSI][9] = 48, [0][1][1][0][RTW89_MKK][9] = 66, @@ -29402,6 +32702,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][1][0][RTW89_ACMA][9] = 48, [0][1][1][0][RTW89_CN][9] = 46, [0][1][1][0][RTW89_UK][9] = 48, + [0][1][1][0][RTW89_MEXICO][9] = 70, + [0][1][1][0][RTW89_UKRAINE][9] = 48, + [0][1][1][0][RTW89_CHILE][9] = 70, + [0][1][1][0][RTW89_QATAR][9] = 48, [0][1][1][0][RTW89_FCC][10] = 62, [0][1][1][0][RTW89_ETSI][10] = 48, [0][1][1][0][RTW89_MKK][10] = 66, @@ -29410,6 +32714,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][1][0][RTW89_ACMA][10] = 48, [0][1][1][0][RTW89_CN][10] = 46, [0][1][1][0][RTW89_UK][10] = 48, + [0][1][1][0][RTW89_MEXICO][10] = 62, + [0][1][1][0][RTW89_UKRAINE][10] = 48, + [0][1][1][0][RTW89_CHILE][10] = 62, + [0][1][1][0][RTW89_QATAR][10] = 48, [0][1][1][0][RTW89_FCC][11] = 60, [0][1][1][0][RTW89_ETSI][11] = 48, [0][1][1][0][RTW89_MKK][11] = 66, @@ -29418,6 +32726,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][1][0][RTW89_ACMA][11] = 48, [0][1][1][0][RTW89_CN][11] = 46, [0][1][1][0][RTW89_UK][11] = 48, + [0][1][1][0][RTW89_MEXICO][11] = 60, + [0][1][1][0][RTW89_UKRAINE][11] = 48, + [0][1][1][0][RTW89_CHILE][11] = 60, + [0][1][1][0][RTW89_QATAR][11] = 48, [0][1][1][0][RTW89_FCC][12] = 36, [0][1][1][0][RTW89_ETSI][12] = 48, [0][1][1][0][RTW89_MKK][12] = 66, @@ -29426,6 +32738,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][1][0][RTW89_ACMA][12] = 48, [0][1][1][0][RTW89_CN][12] = 46, [0][1][1][0][RTW89_UK][12] = 48, + [0][1][1][0][RTW89_MEXICO][12] = 36, + [0][1][1][0][RTW89_UKRAINE][12] = 48, + [0][1][1][0][RTW89_CHILE][12] = 36, + [0][1][1][0][RTW89_QATAR][12] = 48, [0][1][1][0][RTW89_FCC][13] = 127, [0][1][1][0][RTW89_ETSI][13] = 127, [0][1][1][0][RTW89_MKK][13] = 127, @@ -29434,6 +32750,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][1][0][RTW89_ACMA][13] = 127, [0][1][1][0][RTW89_CN][13] = 127, [0][1][1][0][RTW89_UK][13] = 127, + [0][1][1][0][RTW89_MEXICO][13] = 127, + [0][1][1][0][RTW89_UKRAINE][13] = 127, + [0][1][1][0][RTW89_CHILE][13] = 127, + [0][1][1][0][RTW89_QATAR][13] = 127, [0][0][2][0][RTW89_FCC][0] = 66, [0][0][2][0][RTW89_ETSI][0] = 60, [0][0][2][0][RTW89_MKK][0] = 78, @@ -29442,6 +32762,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_ACMA][0] = 60, [0][0][2][0][RTW89_CN][0] = 58, [0][0][2][0][RTW89_UK][0] = 60, + [0][0][2][0][RTW89_MEXICO][0] = 66, + [0][0][2][0][RTW89_UKRAINE][0] = 60, + [0][0][2][0][RTW89_CHILE][0] = 66, + [0][0][2][0][RTW89_QATAR][0] = 60, [0][0][2][0][RTW89_FCC][1] = 70, [0][0][2][0][RTW89_ETSI][1] = 60, [0][0][2][0][RTW89_MKK][1] = 78, @@ -29450,6 +32774,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_ACMA][1] = 60, [0][0][2][0][RTW89_CN][1] = 58, [0][0][2][0][RTW89_UK][1] = 60, + [0][0][2][0][RTW89_MEXICO][1] = 70, + [0][0][2][0][RTW89_UKRAINE][1] = 60, + [0][0][2][0][RTW89_CHILE][1] = 70, + [0][0][2][0][RTW89_QATAR][1] = 60, [0][0][2][0][RTW89_FCC][2] = 74, [0][0][2][0][RTW89_ETSI][2] = 60, [0][0][2][0][RTW89_MKK][2] = 78, @@ -29458,6 +32786,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_ACMA][2] = 60, [0][0][2][0][RTW89_CN][2] = 58, [0][0][2][0][RTW89_UK][2] = 60, + [0][0][2][0][RTW89_MEXICO][2] = 74, + [0][0][2][0][RTW89_UKRAINE][2] = 60, + [0][0][2][0][RTW89_CHILE][2] = 64, + [0][0][2][0][RTW89_QATAR][2] = 60, [0][0][2][0][RTW89_FCC][3] = 78, [0][0][2][0][RTW89_ETSI][3] = 60, [0][0][2][0][RTW89_MKK][3] = 78, @@ -29466,6 +32798,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_ACMA][3] = 60, [0][0][2][0][RTW89_CN][3] = 58, [0][0][2][0][RTW89_UK][3] = 60, + [0][0][2][0][RTW89_MEXICO][3] = 78, + [0][0][2][0][RTW89_UKRAINE][3] = 60, + [0][0][2][0][RTW89_CHILE][3] = 64, + [0][0][2][0][RTW89_QATAR][3] = 60, [0][0][2][0][RTW89_FCC][4] = 80, [0][0][2][0][RTW89_ETSI][4] = 60, [0][0][2][0][RTW89_MKK][4] = 78, @@ -29474,6 +32810,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_ACMA][4] = 60, [0][0][2][0][RTW89_CN][4] = 58, [0][0][2][0][RTW89_UK][4] = 60, + [0][0][2][0][RTW89_MEXICO][4] = 80, + [0][0][2][0][RTW89_UKRAINE][4] = 60, + [0][0][2][0][RTW89_CHILE][4] = 64, + [0][0][2][0][RTW89_QATAR][4] = 60, [0][0][2][0][RTW89_FCC][5] = 80, [0][0][2][0][RTW89_ETSI][5] = 60, [0][0][2][0][RTW89_MKK][5] = 78, @@ -29482,6 +32822,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_ACMA][5] = 60, [0][0][2][0][RTW89_CN][5] = 58, [0][0][2][0][RTW89_UK][5] = 60, + [0][0][2][0][RTW89_MEXICO][5] = 80, + [0][0][2][0][RTW89_UKRAINE][5] = 60, + [0][0][2][0][RTW89_CHILE][5] = 80, + [0][0][2][0][RTW89_QATAR][5] = 60, [0][0][2][0][RTW89_FCC][6] = 80, [0][0][2][0][RTW89_ETSI][6] = 60, [0][0][2][0][RTW89_MKK][6] = 78, @@ -29490,6 +32834,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_ACMA][6] = 60, [0][0][2][0][RTW89_CN][6] = 58, [0][0][2][0][RTW89_UK][6] = 60, + [0][0][2][0][RTW89_MEXICO][6] = 80, + [0][0][2][0][RTW89_UKRAINE][6] = 60, + [0][0][2][0][RTW89_CHILE][6] = 68, + [0][0][2][0][RTW89_QATAR][6] = 60, [0][0][2][0][RTW89_FCC][7] = 80, [0][0][2][0][RTW89_ETSI][7] = 60, [0][0][2][0][RTW89_MKK][7] = 78, @@ -29498,6 +32846,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_ACMA][7] = 60, [0][0][2][0][RTW89_CN][7] = 58, [0][0][2][0][RTW89_UK][7] = 60, + [0][0][2][0][RTW89_MEXICO][7] = 80, + [0][0][2][0][RTW89_UKRAINE][7] = 60, + [0][0][2][0][RTW89_CHILE][7] = 68, + [0][0][2][0][RTW89_QATAR][7] = 60, [0][0][2][0][RTW89_FCC][8] = 78, [0][0][2][0][RTW89_ETSI][8] = 60, [0][0][2][0][RTW89_MKK][8] = 78, @@ -29506,6 +32858,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_ACMA][8] = 60, [0][0][2][0][RTW89_CN][8] = 58, [0][0][2][0][RTW89_UK][8] = 60, + [0][0][2][0][RTW89_MEXICO][8] = 78, + [0][0][2][0][RTW89_UKRAINE][8] = 60, + [0][0][2][0][RTW89_CHILE][8] = 68, + [0][0][2][0][RTW89_QATAR][8] = 60, [0][0][2][0][RTW89_FCC][9] = 74, [0][0][2][0][RTW89_ETSI][9] = 60, [0][0][2][0][RTW89_MKK][9] = 78, @@ -29514,6 +32870,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_ACMA][9] = 60, [0][0][2][0][RTW89_CN][9] = 58, [0][0][2][0][RTW89_UK][9] = 60, + [0][0][2][0][RTW89_MEXICO][9] = 74, + [0][0][2][0][RTW89_UKRAINE][9] = 60, + [0][0][2][0][RTW89_CHILE][9] = 74, + [0][0][2][0][RTW89_QATAR][9] = 60, [0][0][2][0][RTW89_FCC][10] = 62, [0][0][2][0][RTW89_ETSI][10] = 60, [0][0][2][0][RTW89_MKK][10] = 78, @@ -29522,6 +32882,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_ACMA][10] = 60, [0][0][2][0][RTW89_CN][10] = 58, [0][0][2][0][RTW89_UK][10] = 60, + [0][0][2][0][RTW89_MEXICO][10] = 62, + [0][0][2][0][RTW89_UKRAINE][10] = 60, + [0][0][2][0][RTW89_CHILE][10] = 62, + [0][0][2][0][RTW89_QATAR][10] = 60, [0][0][2][0][RTW89_FCC][11] = 60, [0][0][2][0][RTW89_ETSI][11] = 60, [0][0][2][0][RTW89_MKK][11] = 78, @@ -29530,6 +32894,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_ACMA][11] = 60, [0][0][2][0][RTW89_CN][11] = 58, [0][0][2][0][RTW89_UK][11] = 60, + [0][0][2][0][RTW89_MEXICO][11] = 60, + [0][0][2][0][RTW89_UKRAINE][11] = 60, + [0][0][2][0][RTW89_CHILE][11] = 60, + [0][0][2][0][RTW89_QATAR][11] = 60, [0][0][2][0][RTW89_FCC][12] = 38, [0][0][2][0][RTW89_ETSI][12] = 60, [0][0][2][0][RTW89_MKK][12] = 78, @@ -29538,6 +32906,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_ACMA][12] = 60, [0][0][2][0][RTW89_CN][12] = 58, [0][0][2][0][RTW89_UK][12] = 60, + [0][0][2][0][RTW89_MEXICO][12] = 38, + [0][0][2][0][RTW89_UKRAINE][12] = 60, + [0][0][2][0][RTW89_CHILE][12] = 38, + [0][0][2][0][RTW89_QATAR][12] = 60, [0][0][2][0][RTW89_FCC][13] = 127, [0][0][2][0][RTW89_ETSI][13] = 127, [0][0][2][0][RTW89_MKK][13] = 127, @@ -29546,6 +32918,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_ACMA][13] = 127, [0][0][2][0][RTW89_CN][13] = 127, [0][0][2][0][RTW89_UK][13] = 127, + [0][0][2][0][RTW89_MEXICO][13] = 127, + [0][0][2][0][RTW89_UKRAINE][13] = 127, + [0][0][2][0][RTW89_CHILE][13] = 127, + [0][0][2][0][RTW89_QATAR][13] = 127, [0][1][2][0][RTW89_FCC][0] = 64, [0][1][2][0][RTW89_ETSI][0] = 48, [0][1][2][0][RTW89_MKK][0] = 68, @@ -29554,6 +32930,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][2][0][RTW89_ACMA][0] = 48, [0][1][2][0][RTW89_CN][0] = 46, [0][1][2][0][RTW89_UK][0] = 48, + [0][1][2][0][RTW89_MEXICO][0] = 64, + [0][1][2][0][RTW89_UKRAINE][0] = 48, + [0][1][2][0][RTW89_CHILE][0] = 64, + [0][1][2][0][RTW89_QATAR][0] = 48, [0][1][2][0][RTW89_FCC][1] = 70, [0][1][2][0][RTW89_ETSI][1] = 48, [0][1][2][0][RTW89_MKK][1] = 68, @@ -29562,6 +32942,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][2][0][RTW89_ACMA][1] = 48, [0][1][2][0][RTW89_CN][1] = 46, [0][1][2][0][RTW89_UK][1] = 48, + [0][1][2][0][RTW89_MEXICO][1] = 70, + [0][1][2][0][RTW89_UKRAINE][1] = 48, + [0][1][2][0][RTW89_CHILE][1] = 70, + [0][1][2][0][RTW89_QATAR][1] = 48, [0][1][2][0][RTW89_FCC][2] = 74, [0][1][2][0][RTW89_ETSI][2] = 48, [0][1][2][0][RTW89_MKK][2] = 68, @@ -29570,6 +32954,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][2][0][RTW89_ACMA][2] = 48, [0][1][2][0][RTW89_CN][2] = 46, [0][1][2][0][RTW89_UK][2] = 48, + [0][1][2][0][RTW89_MEXICO][2] = 74, + [0][1][2][0][RTW89_UKRAINE][2] = 48, + [0][1][2][0][RTW89_CHILE][2] = 56, + [0][1][2][0][RTW89_QATAR][2] = 48, [0][1][2][0][RTW89_FCC][3] = 78, [0][1][2][0][RTW89_ETSI][3] = 48, [0][1][2][0][RTW89_MKK][3] = 68, @@ -29578,6 +32966,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][2][0][RTW89_ACMA][3] = 48, [0][1][2][0][RTW89_CN][3] = 46, [0][1][2][0][RTW89_UK][3] = 48, + [0][1][2][0][RTW89_MEXICO][3] = 78, + [0][1][2][0][RTW89_UKRAINE][3] = 48, + [0][1][2][0][RTW89_CHILE][3] = 56, + [0][1][2][0][RTW89_QATAR][3] = 48, [0][1][2][0][RTW89_FCC][4] = 80, [0][1][2][0][RTW89_ETSI][4] = 48, [0][1][2][0][RTW89_MKK][4] = 68, @@ -29586,6 +32978,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][2][0][RTW89_ACMA][4] = 48, [0][1][2][0][RTW89_CN][4] = 46, [0][1][2][0][RTW89_UK][4] = 48, + [0][1][2][0][RTW89_MEXICO][4] = 80, + [0][1][2][0][RTW89_UKRAINE][4] = 48, + [0][1][2][0][RTW89_CHILE][4] = 56, + [0][1][2][0][RTW89_QATAR][4] = 48, [0][1][2][0][RTW89_FCC][5] = 80, [0][1][2][0][RTW89_ETSI][5] = 48, [0][1][2][0][RTW89_MKK][5] = 68, @@ -29594,6 +32990,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][2][0][RTW89_ACMA][5] = 48, [0][1][2][0][RTW89_CN][5] = 46, [0][1][2][0][RTW89_UK][5] = 48, + [0][1][2][0][RTW89_MEXICO][5] = 80, + [0][1][2][0][RTW89_UKRAINE][5] = 48, + [0][1][2][0][RTW89_CHILE][5] = 78, + [0][1][2][0][RTW89_QATAR][5] = 48, [0][1][2][0][RTW89_FCC][6] = 80, [0][1][2][0][RTW89_ETSI][6] = 48, [0][1][2][0][RTW89_MKK][6] = 68, @@ -29602,6 +33002,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][2][0][RTW89_ACMA][6] = 48, [0][1][2][0][RTW89_CN][6] = 46, [0][1][2][0][RTW89_UK][6] = 48, + [0][1][2][0][RTW89_MEXICO][6] = 80, + [0][1][2][0][RTW89_UKRAINE][6] = 48, + [0][1][2][0][RTW89_CHILE][6] = 54, + [0][1][2][0][RTW89_QATAR][6] = 48, [0][1][2][0][RTW89_FCC][7] = 74, [0][1][2][0][RTW89_ETSI][7] = 48, [0][1][2][0][RTW89_MKK][7] = 68, @@ -29610,6 +33014,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][2][0][RTW89_ACMA][7] = 48, [0][1][2][0][RTW89_CN][7] = 46, [0][1][2][0][RTW89_UK][7] = 48, + [0][1][2][0][RTW89_MEXICO][7] = 74, + [0][1][2][0][RTW89_UKRAINE][7] = 48, + [0][1][2][0][RTW89_CHILE][7] = 54, + [0][1][2][0][RTW89_QATAR][7] = 48, [0][1][2][0][RTW89_FCC][8] = 70, [0][1][2][0][RTW89_ETSI][8] = 48, [0][1][2][0][RTW89_MKK][8] = 68, @@ -29618,6 +33026,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][2][0][RTW89_ACMA][8] = 48, [0][1][2][0][RTW89_CN][8] = 46, [0][1][2][0][RTW89_UK][8] = 48, + [0][1][2][0][RTW89_MEXICO][8] = 70, + [0][1][2][0][RTW89_UKRAINE][8] = 48, + [0][1][2][0][RTW89_CHILE][8] = 54, + [0][1][2][0][RTW89_QATAR][8] = 48, [0][1][2][0][RTW89_FCC][9] = 66, [0][1][2][0][RTW89_ETSI][9] = 48, [0][1][2][0][RTW89_MKK][9] = 68, @@ -29626,6 +33038,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][2][0][RTW89_ACMA][9] = 48, [0][1][2][0][RTW89_CN][9] = 46, [0][1][2][0][RTW89_UK][9] = 48, + [0][1][2][0][RTW89_MEXICO][9] = 66, + [0][1][2][0][RTW89_UKRAINE][9] = 48, + [0][1][2][0][RTW89_CHILE][9] = 66, + [0][1][2][0][RTW89_QATAR][9] = 48, [0][1][2][0][RTW89_FCC][10] = 58, [0][1][2][0][RTW89_ETSI][10] = 48, [0][1][2][0][RTW89_MKK][10] = 68, @@ -29634,6 +33050,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][2][0][RTW89_ACMA][10] = 48, [0][1][2][0][RTW89_CN][10] = 46, [0][1][2][0][RTW89_UK][10] = 48, + [0][1][2][0][RTW89_MEXICO][10] = 58, + [0][1][2][0][RTW89_UKRAINE][10] = 48, + [0][1][2][0][RTW89_CHILE][10] = 58, + [0][1][2][0][RTW89_QATAR][10] = 48, [0][1][2][0][RTW89_FCC][11] = 58, [0][1][2][0][RTW89_ETSI][11] = 48, [0][1][2][0][RTW89_MKK][11] = 68, @@ -29642,6 +33062,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][2][0][RTW89_ACMA][11] = 48, [0][1][2][0][RTW89_CN][11] = 46, [0][1][2][0][RTW89_UK][11] = 48, + [0][1][2][0][RTW89_MEXICO][11] = 58, + [0][1][2][0][RTW89_UKRAINE][11] = 48, + [0][1][2][0][RTW89_CHILE][11] = 58, + [0][1][2][0][RTW89_QATAR][11] = 48, [0][1][2][0][RTW89_FCC][12] = 16, [0][1][2][0][RTW89_ETSI][12] = 48, [0][1][2][0][RTW89_MKK][12] = 68, @@ -29650,6 +33074,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][2][0][RTW89_ACMA][12] = 48, [0][1][2][0][RTW89_CN][12] = 46, [0][1][2][0][RTW89_UK][12] = 48, + [0][1][2][0][RTW89_MEXICO][12] = 16, + [0][1][2][0][RTW89_UKRAINE][12] = 48, + [0][1][2][0][RTW89_CHILE][12] = 16, + [0][1][2][0][RTW89_QATAR][12] = 48, [0][1][2][0][RTW89_FCC][13] = 127, [0][1][2][0][RTW89_ETSI][13] = 127, [0][1][2][0][RTW89_MKK][13] = 127, @@ -29658,6 +33086,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][2][0][RTW89_ACMA][13] = 127, [0][1][2][0][RTW89_CN][13] = 127, [0][1][2][0][RTW89_UK][13] = 127, + [0][1][2][0][RTW89_MEXICO][13] = 127, + [0][1][2][0][RTW89_UKRAINE][13] = 127, + [0][1][2][0][RTW89_CHILE][13] = 127, + [0][1][2][0][RTW89_QATAR][13] = 127, [0][1][2][1][RTW89_FCC][0] = 64, [0][1][2][1][RTW89_ETSI][0] = 36, [0][1][2][1][RTW89_MKK][0] = 68, @@ -29666,6 +33098,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][2][1][RTW89_ACMA][0] = 36, [0][1][2][1][RTW89_CN][0] = 36, [0][1][2][1][RTW89_UK][0] = 36, + [0][1][2][1][RTW89_MEXICO][0] = 64, + [0][1][2][1][RTW89_UKRAINE][0] = 36, + [0][1][2][1][RTW89_CHILE][0] = 64, + [0][1][2][1][RTW89_QATAR][0] = 36, [0][1][2][1][RTW89_FCC][1] = 70, [0][1][2][1][RTW89_ETSI][1] = 36, [0][1][2][1][RTW89_MKK][1] = 68, @@ -29674,6 +33110,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][2][1][RTW89_ACMA][1] = 36, [0][1][2][1][RTW89_CN][1] = 34, [0][1][2][1][RTW89_UK][1] = 36, + [0][1][2][1][RTW89_MEXICO][1] = 70, + [0][1][2][1][RTW89_UKRAINE][1] = 36, + [0][1][2][1][RTW89_CHILE][1] = 70, + [0][1][2][1][RTW89_QATAR][1] = 36, [0][1][2][1][RTW89_FCC][2] = 74, [0][1][2][1][RTW89_ETSI][2] = 36, [0][1][2][1][RTW89_MKK][2] = 68, @@ -29682,6 +33122,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][2][1][RTW89_ACMA][2] = 36, [0][1][2][1][RTW89_CN][2] = 34, [0][1][2][1][RTW89_UK][2] = 36, + [0][1][2][1][RTW89_MEXICO][2] = 74, + [0][1][2][1][RTW89_UKRAINE][2] = 36, + [0][1][2][1][RTW89_CHILE][2] = 44, + [0][1][2][1][RTW89_QATAR][2] = 36, [0][1][2][1][RTW89_FCC][3] = 78, [0][1][2][1][RTW89_ETSI][3] = 36, [0][1][2][1][RTW89_MKK][3] = 68, @@ -29690,6 +33134,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][2][1][RTW89_ACMA][3] = 36, [0][1][2][1][RTW89_CN][3] = 34, [0][1][2][1][RTW89_UK][3] = 36, + [0][1][2][1][RTW89_MEXICO][3] = 78, + [0][1][2][1][RTW89_UKRAINE][3] = 36, + [0][1][2][1][RTW89_CHILE][3] = 44, + [0][1][2][1][RTW89_QATAR][3] = 36, [0][1][2][1][RTW89_FCC][4] = 80, [0][1][2][1][RTW89_ETSI][4] = 36, [0][1][2][1][RTW89_MKK][4] = 68, @@ -29698,6 +33146,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][2][1][RTW89_ACMA][4] = 36, [0][1][2][1][RTW89_CN][4] = 34, [0][1][2][1][RTW89_UK][4] = 36, + [0][1][2][1][RTW89_MEXICO][4] = 80, + [0][1][2][1][RTW89_UKRAINE][4] = 36, + [0][1][2][1][RTW89_CHILE][4] = 44, + [0][1][2][1][RTW89_QATAR][4] = 36, [0][1][2][1][RTW89_FCC][5] = 80, [0][1][2][1][RTW89_ETSI][5] = 36, [0][1][2][1][RTW89_MKK][5] = 68, @@ -29706,6 +33158,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][2][1][RTW89_ACMA][5] = 36, [0][1][2][1][RTW89_CN][5] = 34, [0][1][2][1][RTW89_UK][5] = 36, + [0][1][2][1][RTW89_MEXICO][5] = 80, + [0][1][2][1][RTW89_UKRAINE][5] = 36, + [0][1][2][1][RTW89_CHILE][5] = 74, + [0][1][2][1][RTW89_QATAR][5] = 36, [0][1][2][1][RTW89_FCC][6] = 80, [0][1][2][1][RTW89_ETSI][6] = 36, [0][1][2][1][RTW89_MKK][6] = 68, @@ -29714,6 +33170,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][2][1][RTW89_ACMA][6] = 36, [0][1][2][1][RTW89_CN][6] = 34, [0][1][2][1][RTW89_UK][6] = 36, + [0][1][2][1][RTW89_MEXICO][6] = 80, + [0][1][2][1][RTW89_UKRAINE][6] = 36, + [0][1][2][1][RTW89_CHILE][6] = 42, + [0][1][2][1][RTW89_QATAR][6] = 36, [0][1][2][1][RTW89_FCC][7] = 74, [0][1][2][1][RTW89_ETSI][7] = 36, [0][1][2][1][RTW89_MKK][7] = 68, @@ -29722,6 +33182,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][2][1][RTW89_ACMA][7] = 36, [0][1][2][1][RTW89_CN][7] = 34, [0][1][2][1][RTW89_UK][7] = 36, + [0][1][2][1][RTW89_MEXICO][7] = 74, + [0][1][2][1][RTW89_UKRAINE][7] = 36, + [0][1][2][1][RTW89_CHILE][7] = 42, + [0][1][2][1][RTW89_QATAR][7] = 36, [0][1][2][1][RTW89_FCC][8] = 70, [0][1][2][1][RTW89_ETSI][8] = 36, [0][1][2][1][RTW89_MKK][8] = 68, @@ -29730,6 +33194,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][2][1][RTW89_ACMA][8] = 36, [0][1][2][1][RTW89_CN][8] = 34, [0][1][2][1][RTW89_UK][8] = 36, + [0][1][2][1][RTW89_MEXICO][8] = 70, + [0][1][2][1][RTW89_UKRAINE][8] = 36, + [0][1][2][1][RTW89_CHILE][8] = 42, + [0][1][2][1][RTW89_QATAR][8] = 36, [0][1][2][1][RTW89_FCC][9] = 66, [0][1][2][1][RTW89_ETSI][9] = 36, [0][1][2][1][RTW89_MKK][9] = 68, @@ -29738,6 +33206,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][2][1][RTW89_ACMA][9] = 36, [0][1][2][1][RTW89_CN][9] = 34, [0][1][2][1][RTW89_UK][9] = 36, + [0][1][2][1][RTW89_MEXICO][9] = 66, + [0][1][2][1][RTW89_UKRAINE][9] = 36, + [0][1][2][1][RTW89_CHILE][9] = 66, + [0][1][2][1][RTW89_QATAR][9] = 36, [0][1][2][1][RTW89_FCC][10] = 58, [0][1][2][1][RTW89_ETSI][10] = 36, [0][1][2][1][RTW89_MKK][10] = 68, @@ -29746,6 +33218,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][2][1][RTW89_ACMA][10] = 36, [0][1][2][1][RTW89_CN][10] = 34, [0][1][2][1][RTW89_UK][10] = 36, + [0][1][2][1][RTW89_MEXICO][10] = 58, + [0][1][2][1][RTW89_UKRAINE][10] = 36, + [0][1][2][1][RTW89_CHILE][10] = 58, + [0][1][2][1][RTW89_QATAR][10] = 36, [0][1][2][1][RTW89_FCC][11] = 58, [0][1][2][1][RTW89_ETSI][11] = 36, [0][1][2][1][RTW89_MKK][11] = 68, @@ -29754,6 +33230,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][2][1][RTW89_ACMA][11] = 36, [0][1][2][1][RTW89_CN][11] = 34, [0][1][2][1][RTW89_UK][11] = 36, + [0][1][2][1][RTW89_MEXICO][11] = 58, + [0][1][2][1][RTW89_UKRAINE][11] = 36, + [0][1][2][1][RTW89_CHILE][11] = 58, + [0][1][2][1][RTW89_QATAR][11] = 36, [0][1][2][1][RTW89_FCC][12] = 16, [0][1][2][1][RTW89_ETSI][12] = 36, [0][1][2][1][RTW89_MKK][12] = 68, @@ -29762,6 +33242,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][2][1][RTW89_ACMA][12] = 36, [0][1][2][1][RTW89_CN][12] = 34, [0][1][2][1][RTW89_UK][12] = 36, + [0][1][2][1][RTW89_MEXICO][12] = 16, + [0][1][2][1][RTW89_UKRAINE][12] = 36, + [0][1][2][1][RTW89_CHILE][12] = 16, + [0][1][2][1][RTW89_QATAR][12] = 36, [0][1][2][1][RTW89_FCC][13] = 127, [0][1][2][1][RTW89_ETSI][13] = 127, [0][1][2][1][RTW89_MKK][13] = 127, @@ -29770,6 +33254,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][2][1][RTW89_ACMA][13] = 127, [0][1][2][1][RTW89_CN][13] = 127, [0][1][2][1][RTW89_UK][13] = 127, + [0][1][2][1][RTW89_MEXICO][13] = 127, + [0][1][2][1][RTW89_UKRAINE][13] = 127, + [0][1][2][1][RTW89_CHILE][13] = 127, + [0][1][2][1][RTW89_QATAR][13] = 127, [1][0][2][0][RTW89_FCC][0] = 127, [1][0][2][0][RTW89_ETSI][0] = 127, [1][0][2][0][RTW89_MKK][0] = 127, @@ -29778,6 +33266,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][0][2][0][RTW89_ACMA][0] = 127, [1][0][2][0][RTW89_CN][0] = 127, [1][0][2][0][RTW89_UK][0] = 127, + [1][0][2][0][RTW89_MEXICO][0] = 127, + [1][0][2][0][RTW89_UKRAINE][0] = 127, + [1][0][2][0][RTW89_CHILE][0] = 127, + [1][0][2][0][RTW89_QATAR][0] = 127, [1][0][2][0][RTW89_FCC][1] = 127, [1][0][2][0][RTW89_ETSI][1] = 127, [1][0][2][0][RTW89_MKK][1] = 127, @@ -29786,6 +33278,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][0][2][0][RTW89_ACMA][1] = 127, [1][0][2][0][RTW89_CN][1] = 127, [1][0][2][0][RTW89_UK][1] = 127, + [1][0][2][0][RTW89_MEXICO][1] = 127, + [1][0][2][0][RTW89_UKRAINE][1] = 127, + [1][0][2][0][RTW89_CHILE][1] = 127, + [1][0][2][0][RTW89_QATAR][1] = 127, [1][0][2][0][RTW89_FCC][2] = 64, [1][0][2][0][RTW89_ETSI][2] = 60, [1][0][2][0][RTW89_MKK][2] = 74, @@ -29794,6 +33290,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][0][2][0][RTW89_ACMA][2] = 60, [1][0][2][0][RTW89_CN][2] = 58, [1][0][2][0][RTW89_UK][2] = 60, + [1][0][2][0][RTW89_MEXICO][2] = 64, + [1][0][2][0][RTW89_UKRAINE][2] = 60, + [1][0][2][0][RTW89_CHILE][2] = 64, + [1][0][2][0][RTW89_QATAR][2] = 60, [1][0][2][0][RTW89_FCC][3] = 64, [1][0][2][0][RTW89_ETSI][3] = 60, [1][0][2][0][RTW89_MKK][3] = 74, @@ -29802,6 +33302,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][0][2][0][RTW89_ACMA][3] = 60, [1][0][2][0][RTW89_CN][3] = 58, [1][0][2][0][RTW89_UK][3] = 60, + [1][0][2][0][RTW89_MEXICO][3] = 64, + [1][0][2][0][RTW89_UKRAINE][3] = 60, + [1][0][2][0][RTW89_CHILE][3] = 64, + [1][0][2][0][RTW89_QATAR][3] = 60, [1][0][2][0][RTW89_FCC][4] = 68, [1][0][2][0][RTW89_ETSI][4] = 60, [1][0][2][0][RTW89_MKK][4] = 74, @@ -29810,6 +33314,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][0][2][0][RTW89_ACMA][4] = 60, [1][0][2][0][RTW89_CN][4] = 58, [1][0][2][0][RTW89_UK][4] = 60, + [1][0][2][0][RTW89_MEXICO][4] = 68, + [1][0][2][0][RTW89_UKRAINE][4] = 60, + [1][0][2][0][RTW89_CHILE][4] = 68, + [1][0][2][0][RTW89_QATAR][4] = 60, [1][0][2][0][RTW89_FCC][5] = 68, [1][0][2][0][RTW89_ETSI][5] = 60, [1][0][2][0][RTW89_MKK][5] = 74, @@ -29818,6 +33326,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][0][2][0][RTW89_ACMA][5] = 60, [1][0][2][0][RTW89_CN][5] = 58, [1][0][2][0][RTW89_UK][5] = 60, + [1][0][2][0][RTW89_MEXICO][5] = 68, + [1][0][2][0][RTW89_UKRAINE][5] = 60, + [1][0][2][0][RTW89_CHILE][5] = 68, + [1][0][2][0][RTW89_QATAR][5] = 60, [1][0][2][0][RTW89_FCC][6] = 66, [1][0][2][0][RTW89_ETSI][6] = 60, [1][0][2][0][RTW89_MKK][6] = 74, @@ -29826,6 +33338,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][0][2][0][RTW89_ACMA][6] = 60, [1][0][2][0][RTW89_CN][6] = 58, [1][0][2][0][RTW89_UK][6] = 60, + [1][0][2][0][RTW89_MEXICO][6] = 66, + [1][0][2][0][RTW89_UKRAINE][6] = 60, + [1][0][2][0][RTW89_CHILE][6] = 66, + [1][0][2][0][RTW89_QATAR][6] = 60, [1][0][2][0][RTW89_FCC][7] = 62, [1][0][2][0][RTW89_ETSI][7] = 60, [1][0][2][0][RTW89_MKK][7] = 74, @@ -29834,6 +33350,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][0][2][0][RTW89_ACMA][7] = 60, [1][0][2][0][RTW89_CN][7] = 58, [1][0][2][0][RTW89_UK][7] = 60, + [1][0][2][0][RTW89_MEXICO][7] = 62, + [1][0][2][0][RTW89_UKRAINE][7] = 60, + [1][0][2][0][RTW89_CHILE][7] = 62, + [1][0][2][0][RTW89_QATAR][7] = 60, [1][0][2][0][RTW89_FCC][8] = 62, [1][0][2][0][RTW89_ETSI][8] = 60, [1][0][2][0][RTW89_MKK][8] = 74, @@ -29842,6 +33362,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][0][2][0][RTW89_ACMA][8] = 60, [1][0][2][0][RTW89_CN][8] = 58, [1][0][2][0][RTW89_UK][8] = 60, + [1][0][2][0][RTW89_MEXICO][8] = 62, + [1][0][2][0][RTW89_UKRAINE][8] = 60, + [1][0][2][0][RTW89_CHILE][8] = 62, + [1][0][2][0][RTW89_QATAR][8] = 60, [1][0][2][0][RTW89_FCC][9] = 60, [1][0][2][0][RTW89_ETSI][9] = 60, [1][0][2][0][RTW89_MKK][9] = 74, @@ -29850,6 +33374,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][0][2][0][RTW89_ACMA][9] = 60, [1][0][2][0][RTW89_CN][9] = 58, [1][0][2][0][RTW89_UK][9] = 60, + [1][0][2][0][RTW89_MEXICO][9] = 60, + [1][0][2][0][RTW89_UKRAINE][9] = 60, + [1][0][2][0][RTW89_CHILE][9] = 60, + [1][0][2][0][RTW89_QATAR][9] = 60, [1][0][2][0][RTW89_FCC][10] = 56, [1][0][2][0][RTW89_ETSI][10] = 60, [1][0][2][0][RTW89_MKK][10] = 74, @@ -29858,6 +33386,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][0][2][0][RTW89_ACMA][10] = 60, [1][0][2][0][RTW89_CN][10] = 58, [1][0][2][0][RTW89_UK][10] = 60, + [1][0][2][0][RTW89_MEXICO][10] = 56, + [1][0][2][0][RTW89_UKRAINE][10] = 60, + [1][0][2][0][RTW89_CHILE][10] = 56, + [1][0][2][0][RTW89_QATAR][10] = 60, [1][0][2][0][RTW89_FCC][11] = 127, [1][0][2][0][RTW89_ETSI][11] = 127, [1][0][2][0][RTW89_MKK][11] = 127, @@ -29866,6 +33398,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][0][2][0][RTW89_ACMA][11] = 127, [1][0][2][0][RTW89_CN][11] = 127, [1][0][2][0][RTW89_UK][11] = 127, + [1][0][2][0][RTW89_MEXICO][11] = 127, + [1][0][2][0][RTW89_UKRAINE][11] = 127, + [1][0][2][0][RTW89_CHILE][11] = 127, + [1][0][2][0][RTW89_QATAR][11] = 127, [1][0][2][0][RTW89_FCC][12] = 127, [1][0][2][0][RTW89_ETSI][12] = 127, [1][0][2][0][RTW89_MKK][12] = 127, @@ -29874,6 +33410,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][0][2][0][RTW89_ACMA][12] = 127, [1][0][2][0][RTW89_CN][12] = 127, [1][0][2][0][RTW89_UK][12] = 127, + [1][0][2][0][RTW89_MEXICO][12] = 127, + [1][0][2][0][RTW89_UKRAINE][12] = 127, + [1][0][2][0][RTW89_CHILE][12] = 127, + [1][0][2][0][RTW89_QATAR][12] = 127, [1][0][2][0][RTW89_FCC][13] = 127, [1][0][2][0][RTW89_ETSI][13] = 127, [1][0][2][0][RTW89_MKK][13] = 127, @@ -29882,6 +33422,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][0][2][0][RTW89_ACMA][13] = 127, [1][0][2][0][RTW89_CN][13] = 127, [1][0][2][0][RTW89_UK][13] = 127, + [1][0][2][0][RTW89_MEXICO][13] = 127, + [1][0][2][0][RTW89_UKRAINE][13] = 127, + [1][0][2][0][RTW89_CHILE][13] = 127, + [1][0][2][0][RTW89_QATAR][13] = 127, [1][1][2][0][RTW89_FCC][0] = 127, [1][1][2][0][RTW89_ETSI][0] = 127, [1][1][2][0][RTW89_MKK][0] = 127, @@ -29890,6 +33434,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][1][2][0][RTW89_ACMA][0] = 127, [1][1][2][0][RTW89_CN][0] = 127, [1][1][2][0][RTW89_UK][0] = 127, + [1][1][2][0][RTW89_MEXICO][0] = 127, + [1][1][2][0][RTW89_UKRAINE][0] = 127, + [1][1][2][0][RTW89_CHILE][0] = 127, + [1][1][2][0][RTW89_QATAR][0] = 127, [1][1][2][0][RTW89_FCC][1] = 127, [1][1][2][0][RTW89_ETSI][1] = 127, [1][1][2][0][RTW89_MKK][1] = 127, @@ -29898,6 +33446,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][1][2][0][RTW89_ACMA][1] = 127, [1][1][2][0][RTW89_CN][1] = 127, [1][1][2][0][RTW89_UK][1] = 127, + [1][1][2][0][RTW89_MEXICO][1] = 127, + [1][1][2][0][RTW89_UKRAINE][1] = 127, + [1][1][2][0][RTW89_CHILE][1] = 127, + [1][1][2][0][RTW89_QATAR][1] = 127, [1][1][2][0][RTW89_FCC][2] = 60, [1][1][2][0][RTW89_ETSI][2] = 48, [1][1][2][0][RTW89_MKK][2] = 68, @@ -29906,6 +33458,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][1][2][0][RTW89_ACMA][2] = 48, [1][1][2][0][RTW89_CN][2] = 34, [1][1][2][0][RTW89_UK][2] = 48, + [1][1][2][0][RTW89_MEXICO][2] = 60, + [1][1][2][0][RTW89_UKRAINE][2] = 48, + [1][1][2][0][RTW89_CHILE][2] = 60, + [1][1][2][0][RTW89_QATAR][2] = 48, [1][1][2][0][RTW89_FCC][3] = 60, [1][1][2][0][RTW89_ETSI][3] = 48, [1][1][2][0][RTW89_MKK][3] = 68, @@ -29914,6 +33470,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][1][2][0][RTW89_ACMA][3] = 48, [1][1][2][0][RTW89_CN][3] = 34, [1][1][2][0][RTW89_UK][3] = 48, + [1][1][2][0][RTW89_MEXICO][3] = 60, + [1][1][2][0][RTW89_UKRAINE][3] = 48, + [1][1][2][0][RTW89_CHILE][3] = 56, + [1][1][2][0][RTW89_QATAR][3] = 48, [1][1][2][0][RTW89_FCC][4] = 60, [1][1][2][0][RTW89_ETSI][4] = 48, [1][1][2][0][RTW89_MKK][4] = 68, @@ -29922,6 +33482,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][1][2][0][RTW89_ACMA][4] = 48, [1][1][2][0][RTW89_CN][4] = 34, [1][1][2][0][RTW89_UK][4] = 48, + [1][1][2][0][RTW89_MEXICO][4] = 60, + [1][1][2][0][RTW89_UKRAINE][4] = 48, + [1][1][2][0][RTW89_CHILE][4] = 56, + [1][1][2][0][RTW89_QATAR][4] = 48, [1][1][2][0][RTW89_FCC][5] = 60, [1][1][2][0][RTW89_ETSI][5] = 48, [1][1][2][0][RTW89_MKK][5] = 68, @@ -29930,6 +33494,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][1][2][0][RTW89_ACMA][5] = 48, [1][1][2][0][RTW89_CN][5] = 34, [1][1][2][0][RTW89_UK][5] = 48, + [1][1][2][0][RTW89_MEXICO][5] = 60, + [1][1][2][0][RTW89_UKRAINE][5] = 48, + [1][1][2][0][RTW89_CHILE][5] = 60, + [1][1][2][0][RTW89_QATAR][5] = 48, [1][1][2][0][RTW89_FCC][6] = 58, [1][1][2][0][RTW89_ETSI][6] = 48, [1][1][2][0][RTW89_MKK][6] = 68, @@ -29938,6 +33506,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][1][2][0][RTW89_ACMA][6] = 48, [1][1][2][0][RTW89_CN][6] = 34, [1][1][2][0][RTW89_UK][6] = 48, + [1][1][2][0][RTW89_MEXICO][6] = 58, + [1][1][2][0][RTW89_UKRAINE][6] = 48, + [1][1][2][0][RTW89_CHILE][6] = 52, + [1][1][2][0][RTW89_QATAR][6] = 48, [1][1][2][0][RTW89_FCC][7] = 54, [1][1][2][0][RTW89_ETSI][7] = 48, [1][1][2][0][RTW89_MKK][7] = 68, @@ -29946,6 +33518,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][1][2][0][RTW89_ACMA][7] = 48, [1][1][2][0][RTW89_CN][7] = 34, [1][1][2][0][RTW89_UK][7] = 48, + [1][1][2][0][RTW89_MEXICO][7] = 54, + [1][1][2][0][RTW89_UKRAINE][7] = 48, + [1][1][2][0][RTW89_CHILE][7] = 52, + [1][1][2][0][RTW89_QATAR][7] = 48, [1][1][2][0][RTW89_FCC][8] = 54, [1][1][2][0][RTW89_ETSI][8] = 48, [1][1][2][0][RTW89_MKK][8] = 68, @@ -29954,6 +33530,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][1][2][0][RTW89_ACMA][8] = 48, [1][1][2][0][RTW89_CN][8] = 34, [1][1][2][0][RTW89_UK][8] = 48, + [1][1][2][0][RTW89_MEXICO][8] = 54, + [1][1][2][0][RTW89_UKRAINE][8] = 48, + [1][1][2][0][RTW89_CHILE][8] = 54, + [1][1][2][0][RTW89_QATAR][8] = 48, [1][1][2][0][RTW89_FCC][9] = 54, [1][1][2][0][RTW89_ETSI][9] = 48, [1][1][2][0][RTW89_MKK][9] = 68, @@ -29962,6 +33542,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][1][2][0][RTW89_ACMA][9] = 48, [1][1][2][0][RTW89_CN][9] = 34, [1][1][2][0][RTW89_UK][9] = 48, + [1][1][2][0][RTW89_MEXICO][9] = 54, + [1][1][2][0][RTW89_UKRAINE][9] = 48, + [1][1][2][0][RTW89_CHILE][9] = 54, + [1][1][2][0][RTW89_QATAR][9] = 48, [1][1][2][0][RTW89_FCC][10] = 46, [1][1][2][0][RTW89_ETSI][10] = 48, [1][1][2][0][RTW89_MKK][10] = 68, @@ -29970,6 +33554,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][1][2][0][RTW89_ACMA][10] = 48, [1][1][2][0][RTW89_CN][10] = 34, [1][1][2][0][RTW89_UK][10] = 48, + [1][1][2][0][RTW89_MEXICO][10] = 46, + [1][1][2][0][RTW89_UKRAINE][10] = 48, + [1][1][2][0][RTW89_CHILE][10] = 46, + [1][1][2][0][RTW89_QATAR][10] = 48, [1][1][2][0][RTW89_FCC][11] = 127, [1][1][2][0][RTW89_ETSI][11] = 127, [1][1][2][0][RTW89_MKK][11] = 127, @@ -29978,6 +33566,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][1][2][0][RTW89_ACMA][11] = 127, [1][1][2][0][RTW89_CN][11] = 127, [1][1][2][0][RTW89_UK][11] = 127, + [1][1][2][0][RTW89_MEXICO][11] = 127, + [1][1][2][0][RTW89_UKRAINE][11] = 127, + [1][1][2][0][RTW89_CHILE][11] = 127, + [1][1][2][0][RTW89_QATAR][11] = 127, [1][1][2][0][RTW89_FCC][12] = 127, [1][1][2][0][RTW89_ETSI][12] = 127, [1][1][2][0][RTW89_MKK][12] = 127, @@ -29986,6 +33578,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][1][2][0][RTW89_ACMA][12] = 127, [1][1][2][0][RTW89_CN][12] = 127, [1][1][2][0][RTW89_UK][12] = 127, + [1][1][2][0][RTW89_MEXICO][12] = 127, + [1][1][2][0][RTW89_UKRAINE][12] = 127, + [1][1][2][0][RTW89_CHILE][12] = 127, + [1][1][2][0][RTW89_QATAR][12] = 127, [1][1][2][0][RTW89_FCC][13] = 127, [1][1][2][0][RTW89_ETSI][13] = 127, [1][1][2][0][RTW89_MKK][13] = 127, @@ -29994,6 +33590,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][1][2][0][RTW89_ACMA][13] = 127, [1][1][2][0][RTW89_CN][13] = 127, [1][1][2][0][RTW89_UK][13] = 127, + [1][1][2][0][RTW89_MEXICO][13] = 127, + [1][1][2][0][RTW89_UKRAINE][13] = 127, + [1][1][2][0][RTW89_CHILE][13] = 127, + [1][1][2][0][RTW89_QATAR][13] = 127, [1][1][2][1][RTW89_FCC][0] = 127, [1][1][2][1][RTW89_ETSI][0] = 127, [1][1][2][1][RTW89_MKK][0] = 127, @@ -30002,6 +33602,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][1][2][1][RTW89_ACMA][0] = 127, [1][1][2][1][RTW89_CN][0] = 127, [1][1][2][1][RTW89_UK][0] = 127, + [1][1][2][1][RTW89_MEXICO][0] = 127, + [1][1][2][1][RTW89_UKRAINE][0] = 127, + [1][1][2][1][RTW89_CHILE][0] = 127, + [1][1][2][1][RTW89_QATAR][0] = 127, [1][1][2][1][RTW89_FCC][1] = 127, [1][1][2][1][RTW89_ETSI][1] = 127, [1][1][2][1][RTW89_MKK][1] = 127, @@ -30010,6 +33614,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][1][2][1][RTW89_ACMA][1] = 127, [1][1][2][1][RTW89_CN][1] = 127, [1][1][2][1][RTW89_UK][1] = 127, + [1][1][2][1][RTW89_MEXICO][1] = 127, + [1][1][2][1][RTW89_UKRAINE][1] = 127, + [1][1][2][1][RTW89_CHILE][1] = 127, + [1][1][2][1][RTW89_QATAR][1] = 127, [1][1][2][1][RTW89_FCC][2] = 60, [1][1][2][1][RTW89_ETSI][2] = 36, [1][1][2][1][RTW89_MKK][2] = 68, @@ -30018,6 +33626,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][1][2][1][RTW89_ACMA][2] = 36, [1][1][2][1][RTW89_CN][2] = 34, [1][1][2][1][RTW89_UK][2] = 36, + [1][1][2][1][RTW89_MEXICO][2] = 60, + [1][1][2][1][RTW89_UKRAINE][2] = 36, + [1][1][2][1][RTW89_CHILE][2] = 60, + [1][1][2][1][RTW89_QATAR][2] = 36, [1][1][2][1][RTW89_FCC][3] = 60, [1][1][2][1][RTW89_ETSI][3] = 36, [1][1][2][1][RTW89_MKK][3] = 68, @@ -30026,6 +33638,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][1][2][1][RTW89_ACMA][3] = 36, [1][1][2][1][RTW89_CN][3] = 34, [1][1][2][1][RTW89_UK][3] = 36, + [1][1][2][1][RTW89_MEXICO][3] = 60, + [1][1][2][1][RTW89_UKRAINE][3] = 36, + [1][1][2][1][RTW89_CHILE][3] = 44, + [1][1][2][1][RTW89_QATAR][3] = 36, [1][1][2][1][RTW89_FCC][4] = 60, [1][1][2][1][RTW89_ETSI][4] = 36, [1][1][2][1][RTW89_MKK][4] = 68, @@ -30034,6 +33650,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][1][2][1][RTW89_ACMA][4] = 36, [1][1][2][1][RTW89_CN][4] = 34, [1][1][2][1][RTW89_UK][4] = 36, + [1][1][2][1][RTW89_MEXICO][4] = 60, + [1][1][2][1][RTW89_UKRAINE][4] = 36, + [1][1][2][1][RTW89_CHILE][4] = 44, + [1][1][2][1][RTW89_QATAR][4] = 36, [1][1][2][1][RTW89_FCC][5] = 60, [1][1][2][1][RTW89_ETSI][5] = 36, [1][1][2][1][RTW89_MKK][5] = 68, @@ -30042,6 +33662,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][1][2][1][RTW89_ACMA][5] = 36, [1][1][2][1][RTW89_CN][5] = 34, [1][1][2][1][RTW89_UK][5] = 36, + [1][1][2][1][RTW89_MEXICO][5] = 60, + [1][1][2][1][RTW89_UKRAINE][5] = 36, + [1][1][2][1][RTW89_CHILE][5] = 60, + [1][1][2][1][RTW89_QATAR][5] = 36, [1][1][2][1][RTW89_FCC][6] = 58, [1][1][2][1][RTW89_ETSI][6] = 36, [1][1][2][1][RTW89_MKK][6] = 68, @@ -30050,6 +33674,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][1][2][1][RTW89_ACMA][6] = 36, [1][1][2][1][RTW89_CN][6] = 34, [1][1][2][1][RTW89_UK][6] = 36, + [1][1][2][1][RTW89_MEXICO][6] = 58, + [1][1][2][1][RTW89_UKRAINE][6] = 36, + [1][1][2][1][RTW89_CHILE][6] = 40, + [1][1][2][1][RTW89_QATAR][6] = 36, [1][1][2][1][RTW89_FCC][7] = 54, [1][1][2][1][RTW89_ETSI][7] = 36, [1][1][2][1][RTW89_MKK][7] = 68, @@ -30058,6 +33686,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][1][2][1][RTW89_ACMA][7] = 36, [1][1][2][1][RTW89_CN][7] = 34, [1][1][2][1][RTW89_UK][7] = 36, + [1][1][2][1][RTW89_MEXICO][7] = 54, + [1][1][2][1][RTW89_UKRAINE][7] = 36, + [1][1][2][1][RTW89_CHILE][7] = 40, + [1][1][2][1][RTW89_QATAR][7] = 36, [1][1][2][1][RTW89_FCC][8] = 54, [1][1][2][1][RTW89_ETSI][8] = 36, [1][1][2][1][RTW89_MKK][8] = 68, @@ -30066,6 +33698,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][1][2][1][RTW89_ACMA][8] = 36, [1][1][2][1][RTW89_CN][8] = 34, [1][1][2][1][RTW89_UK][8] = 36, + [1][1][2][1][RTW89_MEXICO][8] = 54, + [1][1][2][1][RTW89_UKRAINE][8] = 36, + [1][1][2][1][RTW89_CHILE][8] = 54, + [1][1][2][1][RTW89_QATAR][8] = 36, [1][1][2][1][RTW89_FCC][9] = 54, [1][1][2][1][RTW89_ETSI][9] = 36, [1][1][2][1][RTW89_MKK][9] = 68, @@ -30074,6 +33710,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][1][2][1][RTW89_ACMA][9] = 36, [1][1][2][1][RTW89_CN][9] = 34, [1][1][2][1][RTW89_UK][9] = 36, + [1][1][2][1][RTW89_MEXICO][9] = 54, + [1][1][2][1][RTW89_UKRAINE][9] = 36, + [1][1][2][1][RTW89_CHILE][9] = 54, + [1][1][2][1][RTW89_QATAR][9] = 36, [1][1][2][1][RTW89_FCC][10] = 46, [1][1][2][1][RTW89_ETSI][10] = 36, [1][1][2][1][RTW89_MKK][10] = 68, @@ -30082,6 +33722,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][1][2][1][RTW89_ACMA][10] = 36, [1][1][2][1][RTW89_CN][10] = 36, [1][1][2][1][RTW89_UK][10] = 36, + [1][1][2][1][RTW89_MEXICO][10] = 46, + [1][1][2][1][RTW89_UKRAINE][10] = 36, + [1][1][2][1][RTW89_CHILE][10] = 46, + [1][1][2][1][RTW89_QATAR][10] = 36, [1][1][2][1][RTW89_FCC][11] = 127, [1][1][2][1][RTW89_ETSI][11] = 127, [1][1][2][1][RTW89_MKK][11] = 127, @@ -30090,6 +33734,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][1][2][1][RTW89_ACMA][11] = 127, [1][1][2][1][RTW89_CN][11] = 127, [1][1][2][1][RTW89_UK][11] = 127, + [1][1][2][1][RTW89_MEXICO][11] = 127, + [1][1][2][1][RTW89_UKRAINE][11] = 127, + [1][1][2][1][RTW89_CHILE][11] = 127, + [1][1][2][1][RTW89_QATAR][11] = 127, [1][1][2][1][RTW89_FCC][12] = 127, [1][1][2][1][RTW89_ETSI][12] = 127, [1][1][2][1][RTW89_MKK][12] = 127, @@ -30098,6 +33746,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][1][2][1][RTW89_ACMA][12] = 127, [1][1][2][1][RTW89_CN][12] = 127, [1][1][2][1][RTW89_UK][12] = 127, + [1][1][2][1][RTW89_MEXICO][12] = 127, + [1][1][2][1][RTW89_UKRAINE][12] = 127, + [1][1][2][1][RTW89_CHILE][12] = 127, + [1][1][2][1][RTW89_QATAR][12] = 127, [1][1][2][1][RTW89_FCC][13] = 127, [1][1][2][1][RTW89_ETSI][13] = 127, [1][1][2][1][RTW89_MKK][13] = 127, @@ -30106,6 +33758,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][1][2][1][RTW89_ACMA][13] = 127, [1][1][2][1][RTW89_CN][13] = 127, [1][1][2][1][RTW89_UK][13] = 127, + [1][1][2][1][RTW89_MEXICO][13] = 127, + [1][1][2][1][RTW89_UKRAINE][13] = 127, + [1][1][2][1][RTW89_CHILE][13] = 127, + [1][1][2][1][RTW89_QATAR][13] = 127, }; static @@ -30120,17 +33776,17 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_WW][10] = 50, [0][0][1][0][RTW89_WW][12] = 50, [0][0][1][0][RTW89_WW][14] = 50, - [0][0][1][0][RTW89_WW][15] = 66, - [0][0][1][0][RTW89_WW][17] = 66, - [0][0][1][0][RTW89_WW][19] = 66, - [0][0][1][0][RTW89_WW][21] = 66, - [0][0][1][0][RTW89_WW][23] = 66, - [0][0][1][0][RTW89_WW][25] = 66, - [0][0][1][0][RTW89_WW][27] = 66, - [0][0][1][0][RTW89_WW][29] = 66, - [0][0][1][0][RTW89_WW][31] = 66, - [0][0][1][0][RTW89_WW][33] = 66, - [0][0][1][0][RTW89_WW][35] = 60, + [0][0][1][0][RTW89_WW][15] = 54, + [0][0][1][0][RTW89_WW][17] = 54, + [0][0][1][0][RTW89_WW][19] = 54, + [0][0][1][0][RTW89_WW][21] = 54, + [0][0][1][0][RTW89_WW][23] = 54, + [0][0][1][0][RTW89_WW][25] = 54, + [0][0][1][0][RTW89_WW][27] = 54, + [0][0][1][0][RTW89_WW][29] = 54, + [0][0][1][0][RTW89_WW][31] = 54, + [0][0][1][0][RTW89_WW][33] = 54, + [0][0][1][0][RTW89_WW][35] = 54, [0][0][1][0][RTW89_WW][37] = 64, [0][0][1][0][RTW89_WW][38] = 30, [0][0][1][0][RTW89_WW][40] = 30, @@ -30144,21 +33800,21 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][1][0][RTW89_WW][2] = 34, [0][1][1][0][RTW89_WW][4] = 34, [0][1][1][0][RTW89_WW][6] = 36, - [0][1][1][0][RTW89_WW][8] = 46, - [0][1][1][0][RTW89_WW][10] = 46, - [0][1][1][0][RTW89_WW][12] = 46, - [0][1][1][0][RTW89_WW][14] = 46, - [0][1][1][0][RTW89_WW][15] = 54, - [0][1][1][0][RTW89_WW][17] = 54, - [0][1][1][0][RTW89_WW][19] = 54, - [0][1][1][0][RTW89_WW][21] = 54, - [0][1][1][0][RTW89_WW][23] = 54, - [0][1][1][0][RTW89_WW][25] = 54, - [0][1][1][0][RTW89_WW][27] = 54, - [0][1][1][0][RTW89_WW][29] = 54, - [0][1][1][0][RTW89_WW][31] = 54, - [0][1][1][0][RTW89_WW][33] = 54, - [0][1][1][0][RTW89_WW][35] = 52, + [0][1][1][0][RTW89_WW][8] = 42, + [0][1][1][0][RTW89_WW][10] = 42, + [0][1][1][0][RTW89_WW][12] = 42, + [0][1][1][0][RTW89_WW][14] = 42, + [0][1][1][0][RTW89_WW][15] = 42, + [0][1][1][0][RTW89_WW][17] = 42, + [0][1][1][0][RTW89_WW][19] = 42, + [0][1][1][0][RTW89_WW][21] = 42, + [0][1][1][0][RTW89_WW][23] = 42, + [0][1][1][0][RTW89_WW][25] = 42, + [0][1][1][0][RTW89_WW][27] = 42, + [0][1][1][0][RTW89_WW][29] = 42, + [0][1][1][0][RTW89_WW][31] = 42, + [0][1][1][0][RTW89_WW][33] = 42, + [0][1][1][0][RTW89_WW][35] = 42, [0][1][1][0][RTW89_WW][37] = 52, [0][1][1][0][RTW89_WW][38] = 18, [0][1][1][0][RTW89_WW][40] = 18, @@ -30176,17 +33832,17 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_WW][10] = 52, [0][0][2][0][RTW89_WW][12] = 52, [0][0][2][0][RTW89_WW][14] = 52, - [0][0][2][0][RTW89_WW][15] = 66, - [0][0][2][0][RTW89_WW][17] = 66, - [0][0][2][0][RTW89_WW][19] = 66, - [0][0][2][0][RTW89_WW][21] = 66, - [0][0][2][0][RTW89_WW][23] = 66, - [0][0][2][0][RTW89_WW][25] = 66, - [0][0][2][0][RTW89_WW][27] = 66, - [0][0][2][0][RTW89_WW][29] = 66, - [0][0][2][0][RTW89_WW][31] = 66, - [0][0][2][0][RTW89_WW][33] = 66, - [0][0][2][0][RTW89_WW][35] = 56, + [0][0][2][0][RTW89_WW][15] = 54, + [0][0][2][0][RTW89_WW][17] = 54, + [0][0][2][0][RTW89_WW][19] = 54, + [0][0][2][0][RTW89_WW][21] = 54, + [0][0][2][0][RTW89_WW][23] = 54, + [0][0][2][0][RTW89_WW][25] = 54, + [0][0][2][0][RTW89_WW][27] = 54, + [0][0][2][0][RTW89_WW][29] = 54, + [0][0][2][0][RTW89_WW][31] = 54, + [0][0][2][0][RTW89_WW][33] = 54, + [0][0][2][0][RTW89_WW][35] = 54, [0][0][2][0][RTW89_WW][37] = 64, [0][0][2][0][RTW89_WW][38] = 30, [0][0][2][0][RTW89_WW][40] = 30, @@ -30204,17 +33860,17 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][0][RTW89_WW][10] = 40, [0][1][2][0][RTW89_WW][12] = 40, [0][1][2][0][RTW89_WW][14] = 40, - [0][1][2][0][RTW89_WW][15] = 54, - [0][1][2][0][RTW89_WW][17] = 54, - [0][1][2][0][RTW89_WW][19] = 54, - [0][1][2][0][RTW89_WW][21] = 54, - [0][1][2][0][RTW89_WW][23] = 54, - [0][1][2][0][RTW89_WW][25] = 54, - [0][1][2][0][RTW89_WW][27] = 54, - [0][1][2][0][RTW89_WW][29] = 54, - [0][1][2][0][RTW89_WW][31] = 54, - [0][1][2][0][RTW89_WW][33] = 54, - [0][1][2][0][RTW89_WW][35] = 46, + [0][1][2][0][RTW89_WW][15] = 42, + [0][1][2][0][RTW89_WW][17] = 42, + [0][1][2][0][RTW89_WW][19] = 42, + [0][1][2][0][RTW89_WW][21] = 42, + [0][1][2][0][RTW89_WW][23] = 42, + [0][1][2][0][RTW89_WW][25] = 42, + [0][1][2][0][RTW89_WW][27] = 42, + [0][1][2][0][RTW89_WW][29] = 42, + [0][1][2][0][RTW89_WW][31] = 42, + [0][1][2][0][RTW89_WW][33] = 42, + [0][1][2][0][RTW89_WW][35] = 42, [0][1][2][0][RTW89_WW][37] = 52, [0][1][2][0][RTW89_WW][38] = 18, [0][1][2][0][RTW89_WW][40] = 18, @@ -30224,25 +33880,25 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][0][RTW89_WW][48] = 48, [0][1][2][0][RTW89_WW][50] = 50, [0][1][2][0][RTW89_WW][52] = 48, - [0][1][2][1][RTW89_WW][0] = 36, - [0][1][2][1][RTW89_WW][2] = 36, - [0][1][2][1][RTW89_WW][4] = 36, - [0][1][2][1][RTW89_WW][6] = 36, - [0][1][2][1][RTW89_WW][8] = 36, - [0][1][2][1][RTW89_WW][10] = 36, - [0][1][2][1][RTW89_WW][12] = 36, - [0][1][2][1][RTW89_WW][14] = 36, - [0][1][2][1][RTW89_WW][15] = 40, - [0][1][2][1][RTW89_WW][17] = 40, - [0][1][2][1][RTW89_WW][19] = 40, - [0][1][2][1][RTW89_WW][21] = 40, - [0][1][2][1][RTW89_WW][23] = 40, - [0][1][2][1][RTW89_WW][25] = 40, - [0][1][2][1][RTW89_WW][27] = 40, - [0][1][2][1][RTW89_WW][29] = 40, - [0][1][2][1][RTW89_WW][31] = 40, - [0][1][2][1][RTW89_WW][33] = 40, - [0][1][2][1][RTW89_WW][35] = 40, + [0][1][2][1][RTW89_WW][0] = 30, + [0][1][2][1][RTW89_WW][2] = 30, + [0][1][2][1][RTW89_WW][4] = 30, + [0][1][2][1][RTW89_WW][6] = 30, + [0][1][2][1][RTW89_WW][8] = 30, + [0][1][2][1][RTW89_WW][10] = 30, + [0][1][2][1][RTW89_WW][12] = 30, + [0][1][2][1][RTW89_WW][14] = 30, + [0][1][2][1][RTW89_WW][15] = 30, + [0][1][2][1][RTW89_WW][17] = 30, + [0][1][2][1][RTW89_WW][19] = 30, + [0][1][2][1][RTW89_WW][21] = 30, + [0][1][2][1][RTW89_WW][23] = 30, + [0][1][2][1][RTW89_WW][25] = 30, + [0][1][2][1][RTW89_WW][27] = 30, + [0][1][2][1][RTW89_WW][29] = 30, + [0][1][2][1][RTW89_WW][31] = 30, + [0][1][2][1][RTW89_WW][33] = 30, + [0][1][2][1][RTW89_WW][35] = 30, [0][1][2][1][RTW89_WW][37] = 40, [0][1][2][1][RTW89_WW][38] = 6, [0][1][2][1][RTW89_WW][40] = 6, @@ -30256,11 +33912,11 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][0][2][0][RTW89_WW][5] = 54, [1][0][2][0][RTW89_WW][9] = 54, [1][0][2][0][RTW89_WW][13] = 52, - [1][0][2][0][RTW89_WW][16] = 56, - [1][0][2][0][RTW89_WW][20] = 56, - [1][0][2][0][RTW89_WW][24] = 56, - [1][0][2][0][RTW89_WW][28] = 66, - [1][0][2][0][RTW89_WW][32] = 62, + [1][0][2][0][RTW89_WW][16] = 54, + [1][0][2][0][RTW89_WW][20] = 54, + [1][0][2][0][RTW89_WW][24] = 54, + [1][0][2][0][RTW89_WW][28] = 54, + [1][0][2][0][RTW89_WW][32] = 54, [1][0][2][0][RTW89_WW][36] = 64, [1][0][2][0][RTW89_WW][39] = 30, [1][0][2][0][RTW89_WW][43] = 30, @@ -30270,25 +33926,25 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][1][2][0][RTW89_WW][5] = 42, [1][1][2][0][RTW89_WW][9] = 42, [1][1][2][0][RTW89_WW][13] = 42, - [1][1][2][0][RTW89_WW][16] = 54, - [1][1][2][0][RTW89_WW][20] = 54, - [1][1][2][0][RTW89_WW][24] = 54, - [1][1][2][0][RTW89_WW][28] = 54, - [1][1][2][0][RTW89_WW][32] = 54, + [1][1][2][0][RTW89_WW][16] = 42, + [1][1][2][0][RTW89_WW][20] = 42, + [1][1][2][0][RTW89_WW][24] = 42, + [1][1][2][0][RTW89_WW][28] = 42, + [1][1][2][0][RTW89_WW][32] = 42, [1][1][2][0][RTW89_WW][36] = 52, [1][1][2][0][RTW89_WW][39] = 18, [1][1][2][0][RTW89_WW][43] = 18, [1][1][2][0][RTW89_WW][47] = 62, [1][1][2][0][RTW89_WW][51] = 60, - [1][1][2][1][RTW89_WW][1] = 40, - [1][1][2][1][RTW89_WW][5] = 40, - [1][1][2][1][RTW89_WW][9] = 40, - [1][1][2][1][RTW89_WW][13] = 40, - [1][1][2][1][RTW89_WW][16] = 40, - [1][1][2][1][RTW89_WW][20] = 40, - [1][1][2][1][RTW89_WW][24] = 40, - [1][1][2][1][RTW89_WW][28] = 40, - [1][1][2][1][RTW89_WW][32] = 40, + [1][1][2][1][RTW89_WW][1] = 30, + [1][1][2][1][RTW89_WW][5] = 30, + [1][1][2][1][RTW89_WW][9] = 30, + [1][1][2][1][RTW89_WW][13] = 30, + [1][1][2][1][RTW89_WW][16] = 30, + [1][1][2][1][RTW89_WW][20] = 30, + [1][1][2][1][RTW89_WW][24] = 30, + [1][1][2][1][RTW89_WW][28] = 30, + [1][1][2][1][RTW89_WW][32] = 30, [1][1][2][1][RTW89_WW][36] = 40, [1][1][2][1][RTW89_WW][39] = 6, [1][1][2][1][RTW89_WW][43] = 6, @@ -30296,22 +33952,22 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][1][2][1][RTW89_WW][51] = 60, [2][0][2][0][RTW89_WW][3] = 54, [2][0][2][0][RTW89_WW][11] = 50, - [2][0][2][0][RTW89_WW][18] = 56, - [2][0][2][0][RTW89_WW][26] = 60, + [2][0][2][0][RTW89_WW][18] = 54, + [2][0][2][0][RTW89_WW][26] = 54, [2][0][2][0][RTW89_WW][34] = 60, [2][0][2][0][RTW89_WW][41] = 30, [2][0][2][0][RTW89_WW][49] = 62, - [2][1][2][0][RTW89_WW][3] = 46, + [2][1][2][0][RTW89_WW][3] = 42, [2][1][2][0][RTW89_WW][11] = 38, - [2][1][2][0][RTW89_WW][18] = 50, - [2][1][2][0][RTW89_WW][26] = 52, + [2][1][2][0][RTW89_WW][18] = 42, + [2][1][2][0][RTW89_WW][26] = 42, [2][1][2][0][RTW89_WW][34] = 52, [2][1][2][0][RTW89_WW][41] = 18, [2][1][2][0][RTW89_WW][49] = 62, - [2][1][2][1][RTW89_WW][3] = 40, - [2][1][2][1][RTW89_WW][11] = 38, - [2][1][2][1][RTW89_WW][18] = 40, - [2][1][2][1][RTW89_WW][26] = 42, + [2][1][2][1][RTW89_WW][3] = 30, + [2][1][2][1][RTW89_WW][11] = 30, + [2][1][2][1][RTW89_WW][18] = 30, + [2][1][2][1][RTW89_WW][26] = 30, [2][1][2][1][RTW89_WW][34] = 40, [2][1][2][1][RTW89_WW][41] = 6, [2][1][2][1][RTW89_WW][49] = 62, @@ -30328,34 +33984,50 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_ETSI][0] = 66, [0][0][1][0][RTW89_MKK][0] = 66, [0][0][1][0][RTW89_IC][0] = 60, - [0][0][1][0][RTW89_KCC][0] = 52, + [0][0][1][0][RTW89_KCC][0] = 62, [0][0][1][0][RTW89_ACMA][0] = 66, [0][0][1][0][RTW89_CN][0] = 50, [0][0][1][0][RTW89_UK][0] = 66, + [0][0][1][0][RTW89_MEXICO][0] = 62, + [0][0][1][0][RTW89_UKRAINE][0] = 54, + [0][0][1][0][RTW89_CHILE][0] = 70, + [0][0][1][0][RTW89_QATAR][0] = 66, [0][0][1][0][RTW89_FCC][2] = 72, [0][0][1][0][RTW89_ETSI][2] = 66, [0][0][1][0][RTW89_MKK][2] = 66, [0][0][1][0][RTW89_IC][2] = 60, - [0][0][1][0][RTW89_KCC][2] = 52, + [0][0][1][0][RTW89_KCC][2] = 62, [0][0][1][0][RTW89_ACMA][2] = 66, [0][0][1][0][RTW89_CN][2] = 50, [0][0][1][0][RTW89_UK][2] = 66, + [0][0][1][0][RTW89_MEXICO][2] = 62, + [0][0][1][0][RTW89_UKRAINE][2] = 54, + [0][0][1][0][RTW89_CHILE][2] = 70, + [0][0][1][0][RTW89_QATAR][2] = 66, [0][0][1][0][RTW89_FCC][4] = 72, [0][0][1][0][RTW89_ETSI][4] = 66, [0][0][1][0][RTW89_MKK][4] = 66, [0][0][1][0][RTW89_IC][4] = 60, - [0][0][1][0][RTW89_KCC][4] = 52, + [0][0][1][0][RTW89_KCC][4] = 62, [0][0][1][0][RTW89_ACMA][4] = 66, [0][0][1][0][RTW89_CN][4] = 50, [0][0][1][0][RTW89_UK][4] = 66, + [0][0][1][0][RTW89_MEXICO][4] = 62, + [0][0][1][0][RTW89_UKRAINE][4] = 54, + [0][0][1][0][RTW89_CHILE][4] = 70, + [0][0][1][0][RTW89_QATAR][4] = 66, [0][0][1][0][RTW89_FCC][6] = 72, [0][0][1][0][RTW89_ETSI][6] = 66, [0][0][1][0][RTW89_MKK][6] = 66, [0][0][1][0][RTW89_IC][6] = 58, - [0][0][1][0][RTW89_KCC][6] = 62, + [0][0][1][0][RTW89_KCC][6] = 52, [0][0][1][0][RTW89_ACMA][6] = 66, [0][0][1][0][RTW89_CN][6] = 50, [0][0][1][0][RTW89_UK][6] = 66, + [0][0][1][0][RTW89_MEXICO][6] = 62, + [0][0][1][0][RTW89_UKRAINE][6] = 54, + [0][0][1][0][RTW89_CHILE][6] = 70, + [0][0][1][0][RTW89_QATAR][6] = 66, [0][0][1][0][RTW89_FCC][8] = 72, [0][0][1][0][RTW89_ETSI][8] = 66, [0][0][1][0][RTW89_MKK][8] = 66, @@ -30364,6 +34036,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_ACMA][8] = 66, [0][0][1][0][RTW89_CN][8] = 50, [0][0][1][0][RTW89_UK][8] = 66, + [0][0][1][0][RTW89_MEXICO][8] = 72, + [0][0][1][0][RTW89_UKRAINE][8] = 54, + [0][0][1][0][RTW89_CHILE][8] = 70, + [0][0][1][0][RTW89_QATAR][8] = 66, [0][0][1][0][RTW89_FCC][10] = 72, [0][0][1][0][RTW89_ETSI][10] = 66, [0][0][1][0][RTW89_MKK][10] = 66, @@ -30372,6 +34048,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_ACMA][10] = 66, [0][0][1][0][RTW89_CN][10] = 50, [0][0][1][0][RTW89_UK][10] = 66, + [0][0][1][0][RTW89_MEXICO][10] = 72, + [0][0][1][0][RTW89_UKRAINE][10] = 54, + [0][0][1][0][RTW89_CHILE][10] = 70, + [0][0][1][0][RTW89_QATAR][10] = 66, [0][0][1][0][RTW89_FCC][12] = 72, [0][0][1][0][RTW89_ETSI][12] = 66, [0][0][1][0][RTW89_MKK][12] = 66, @@ -30380,6 +34060,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_ACMA][12] = 66, [0][0][1][0][RTW89_CN][12] = 50, [0][0][1][0][RTW89_UK][12] = 66, + [0][0][1][0][RTW89_MEXICO][12] = 72, + [0][0][1][0][RTW89_UKRAINE][12] = 54, + [0][0][1][0][RTW89_CHILE][12] = 70, + [0][0][1][0][RTW89_QATAR][12] = 66, [0][0][1][0][RTW89_FCC][14] = 70, [0][0][1][0][RTW89_ETSI][14] = 66, [0][0][1][0][RTW89_MKK][14] = 66, @@ -30388,6 +34072,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_ACMA][14] = 66, [0][0][1][0][RTW89_CN][14] = 50, [0][0][1][0][RTW89_UK][14] = 66, + [0][0][1][0][RTW89_MEXICO][14] = 70, + [0][0][1][0][RTW89_UKRAINE][14] = 54, + [0][0][1][0][RTW89_CHILE][14] = 68, + [0][0][1][0][RTW89_QATAR][14] = 66, [0][0][1][0][RTW89_FCC][15] = 72, [0][0][1][0][RTW89_ETSI][15] = 66, [0][0][1][0][RTW89_MKK][15] = 70, @@ -30396,6 +34084,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_ACMA][15] = 66, [0][0][1][0][RTW89_CN][15] = 127, [0][0][1][0][RTW89_UK][15] = 66, + [0][0][1][0][RTW89_MEXICO][15] = 72, + [0][0][1][0][RTW89_UKRAINE][15] = 54, + [0][0][1][0][RTW89_CHILE][15] = 70, + [0][0][1][0][RTW89_QATAR][15] = 66, [0][0][1][0][RTW89_FCC][17] = 72, [0][0][1][0][RTW89_ETSI][17] = 66, [0][0][1][0][RTW89_MKK][17] = 70, @@ -30404,6 +34096,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_ACMA][17] = 66, [0][0][1][0][RTW89_CN][17] = 127, [0][0][1][0][RTW89_UK][17] = 66, + [0][0][1][0][RTW89_MEXICO][17] = 72, + [0][0][1][0][RTW89_UKRAINE][17] = 54, + [0][0][1][0][RTW89_CHILE][17] = 70, + [0][0][1][0][RTW89_QATAR][17] = 66, [0][0][1][0][RTW89_FCC][19] = 72, [0][0][1][0][RTW89_ETSI][19] = 66, [0][0][1][0][RTW89_MKK][19] = 70, @@ -30412,6 +34108,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_ACMA][19] = 66, [0][0][1][0][RTW89_CN][19] = 127, [0][0][1][0][RTW89_UK][19] = 66, + [0][0][1][0][RTW89_MEXICO][19] = 72, + [0][0][1][0][RTW89_UKRAINE][19] = 54, + [0][0][1][0][RTW89_CHILE][19] = 70, + [0][0][1][0][RTW89_QATAR][19] = 66, [0][0][1][0][RTW89_FCC][21] = 72, [0][0][1][0][RTW89_ETSI][21] = 66, [0][0][1][0][RTW89_MKK][21] = 70, @@ -30420,6 +34120,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_ACMA][21] = 66, [0][0][1][0][RTW89_CN][21] = 127, [0][0][1][0][RTW89_UK][21] = 66, + [0][0][1][0][RTW89_MEXICO][21] = 72, + [0][0][1][0][RTW89_UKRAINE][21] = 54, + [0][0][1][0][RTW89_CHILE][21] = 70, + [0][0][1][0][RTW89_QATAR][21] = 66, [0][0][1][0][RTW89_FCC][23] = 72, [0][0][1][0][RTW89_ETSI][23] = 66, [0][0][1][0][RTW89_MKK][23] = 70, @@ -30428,6 +34132,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_ACMA][23] = 66, [0][0][1][0][RTW89_CN][23] = 127, [0][0][1][0][RTW89_UK][23] = 66, + [0][0][1][0][RTW89_MEXICO][23] = 72, + [0][0][1][0][RTW89_UKRAINE][23] = 54, + [0][0][1][0][RTW89_CHILE][23] = 70, + [0][0][1][0][RTW89_QATAR][23] = 66, [0][0][1][0][RTW89_FCC][25] = 72, [0][0][1][0][RTW89_ETSI][25] = 66, [0][0][1][0][RTW89_MKK][25] = 70, @@ -30436,6 +34144,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_ACMA][25] = 127, [0][0][1][0][RTW89_CN][25] = 127, [0][0][1][0][RTW89_UK][25] = 66, + [0][0][1][0][RTW89_MEXICO][25] = 72, + [0][0][1][0][RTW89_UKRAINE][25] = 54, + [0][0][1][0][RTW89_CHILE][25] = 70, + [0][0][1][0][RTW89_QATAR][25] = 66, [0][0][1][0][RTW89_FCC][27] = 72, [0][0][1][0][RTW89_ETSI][27] = 66, [0][0][1][0][RTW89_MKK][27] = 70, @@ -30444,6 +34156,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_ACMA][27] = 127, [0][0][1][0][RTW89_CN][27] = 127, [0][0][1][0][RTW89_UK][27] = 66, + [0][0][1][0][RTW89_MEXICO][27] = 72, + [0][0][1][0][RTW89_UKRAINE][27] = 54, + [0][0][1][0][RTW89_CHILE][27] = 58, + [0][0][1][0][RTW89_QATAR][27] = 66, [0][0][1][0][RTW89_FCC][29] = 72, [0][0][1][0][RTW89_ETSI][29] = 66, [0][0][1][0][RTW89_MKK][29] = 70, @@ -30452,6 +34168,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_ACMA][29] = 127, [0][0][1][0][RTW89_CN][29] = 127, [0][0][1][0][RTW89_UK][29] = 66, + [0][0][1][0][RTW89_MEXICO][29] = 72, + [0][0][1][0][RTW89_UKRAINE][29] = 54, + [0][0][1][0][RTW89_CHILE][29] = 58, + [0][0][1][0][RTW89_QATAR][29] = 66, [0][0][1][0][RTW89_FCC][31] = 72, [0][0][1][0][RTW89_ETSI][31] = 66, [0][0][1][0][RTW89_MKK][31] = 70, @@ -30460,6 +34180,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_ACMA][31] = 66, [0][0][1][0][RTW89_CN][31] = 127, [0][0][1][0][RTW89_UK][31] = 66, + [0][0][1][0][RTW89_MEXICO][31] = 72, + [0][0][1][0][RTW89_UKRAINE][31] = 54, + [0][0][1][0][RTW89_CHILE][31] = 58, + [0][0][1][0][RTW89_QATAR][31] = 66, [0][0][1][0][RTW89_FCC][33] = 72, [0][0][1][0][RTW89_ETSI][33] = 66, [0][0][1][0][RTW89_MKK][33] = 70, @@ -30468,6 +34192,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_ACMA][33] = 66, [0][0][1][0][RTW89_CN][33] = 127, [0][0][1][0][RTW89_UK][33] = 66, + [0][0][1][0][RTW89_MEXICO][33] = 72, + [0][0][1][0][RTW89_UKRAINE][33] = 54, + [0][0][1][0][RTW89_CHILE][33] = 58, + [0][0][1][0][RTW89_QATAR][33] = 66, [0][0][1][0][RTW89_FCC][35] = 60, [0][0][1][0][RTW89_ETSI][35] = 66, [0][0][1][0][RTW89_MKK][35] = 70, @@ -30476,6 +34204,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_ACMA][35] = 66, [0][0][1][0][RTW89_CN][35] = 127, [0][0][1][0][RTW89_UK][35] = 66, + [0][0][1][0][RTW89_MEXICO][35] = 60, + [0][0][1][0][RTW89_UKRAINE][35] = 54, + [0][0][1][0][RTW89_CHILE][35] = 58, + [0][0][1][0][RTW89_QATAR][35] = 66, [0][0][1][0][RTW89_FCC][37] = 72, [0][0][1][0][RTW89_ETSI][37] = 127, [0][0][1][0][RTW89_MKK][37] = 70, @@ -30484,6 +34216,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_ACMA][37] = 70, [0][0][1][0][RTW89_CN][37] = 127, [0][0][1][0][RTW89_UK][37] = 64, + [0][0][1][0][RTW89_MEXICO][37] = 72, + [0][0][1][0][RTW89_UKRAINE][37] = 127, + [0][0][1][0][RTW89_CHILE][37] = 70, + [0][0][1][0][RTW89_QATAR][37] = 127, [0][0][1][0][RTW89_FCC][38] = 72, [0][0][1][0][RTW89_ETSI][38] = 30, [0][0][1][0][RTW89_MKK][38] = 127, @@ -30492,6 +34228,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_ACMA][38] = 70, [0][0][1][0][RTW89_CN][38] = 68, [0][0][1][0][RTW89_UK][38] = 64, + [0][0][1][0][RTW89_MEXICO][38] = 72, + [0][0][1][0][RTW89_UKRAINE][38] = 30, + [0][0][1][0][RTW89_CHILE][38] = 70, + [0][0][1][0][RTW89_QATAR][38] = 30, [0][0][1][0][RTW89_FCC][40] = 72, [0][0][1][0][RTW89_ETSI][40] = 30, [0][0][1][0][RTW89_MKK][40] = 127, @@ -30500,6 +34240,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_ACMA][40] = 70, [0][0][1][0][RTW89_CN][40] = 68, [0][0][1][0][RTW89_UK][40] = 64, + [0][0][1][0][RTW89_MEXICO][40] = 72, + [0][0][1][0][RTW89_UKRAINE][40] = 30, + [0][0][1][0][RTW89_CHILE][40] = 70, + [0][0][1][0][RTW89_QATAR][40] = 30, [0][0][1][0][RTW89_FCC][42] = 72, [0][0][1][0][RTW89_ETSI][42] = 30, [0][0][1][0][RTW89_MKK][42] = 127, @@ -30508,6 +34252,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_ACMA][42] = 70, [0][0][1][0][RTW89_CN][42] = 68, [0][0][1][0][RTW89_UK][42] = 64, + [0][0][1][0][RTW89_MEXICO][42] = 72, + [0][0][1][0][RTW89_UKRAINE][42] = 30, + [0][0][1][0][RTW89_CHILE][42] = 70, + [0][0][1][0][RTW89_QATAR][42] = 30, [0][0][1][0][RTW89_FCC][44] = 72, [0][0][1][0][RTW89_ETSI][44] = 30, [0][0][1][0][RTW89_MKK][44] = 127, @@ -30516,6 +34264,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_ACMA][44] = 70, [0][0][1][0][RTW89_CN][44] = 68, [0][0][1][0][RTW89_UK][44] = 64, + [0][0][1][0][RTW89_MEXICO][44] = 72, + [0][0][1][0][RTW89_UKRAINE][44] = 30, + [0][0][1][0][RTW89_CHILE][44] = 70, + [0][0][1][0][RTW89_QATAR][44] = 30, [0][0][1][0][RTW89_FCC][46] = 72, [0][0][1][0][RTW89_ETSI][46] = 30, [0][0][1][0][RTW89_MKK][46] = 127, @@ -30524,6 +34276,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_ACMA][46] = 70, [0][0][1][0][RTW89_CN][46] = 68, [0][0][1][0][RTW89_UK][46] = 64, + [0][0][1][0][RTW89_MEXICO][46] = 72, + [0][0][1][0][RTW89_UKRAINE][46] = 30, + [0][0][1][0][RTW89_CHILE][46] = 70, + [0][0][1][0][RTW89_QATAR][46] = 30, [0][0][1][0][RTW89_FCC][48] = 72, [0][0][1][0][RTW89_ETSI][48] = 127, [0][0][1][0][RTW89_MKK][48] = 127, @@ -30532,6 +34288,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_ACMA][48] = 127, [0][0][1][0][RTW89_CN][48] = 127, [0][0][1][0][RTW89_UK][48] = 127, + [0][0][1][0][RTW89_MEXICO][48] = 127, + [0][0][1][0][RTW89_UKRAINE][48] = 127, + [0][0][1][0][RTW89_CHILE][48] = 127, + [0][0][1][0][RTW89_QATAR][48] = 127, [0][0][1][0][RTW89_FCC][50] = 72, [0][0][1][0][RTW89_ETSI][50] = 127, [0][0][1][0][RTW89_MKK][50] = 127, @@ -30540,6 +34300,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_ACMA][50] = 127, [0][0][1][0][RTW89_CN][50] = 127, [0][0][1][0][RTW89_UK][50] = 127, + [0][0][1][0][RTW89_MEXICO][50] = 127, + [0][0][1][0][RTW89_UKRAINE][50] = 127, + [0][0][1][0][RTW89_CHILE][50] = 127, + [0][0][1][0][RTW89_QATAR][50] = 127, [0][0][1][0][RTW89_FCC][52] = 72, [0][0][1][0][RTW89_ETSI][52] = 127, [0][0][1][0][RTW89_MKK][52] = 127, @@ -30548,38 +34312,58 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_ACMA][52] = 127, [0][0][1][0][RTW89_CN][52] = 127, [0][0][1][0][RTW89_UK][52] = 127, + [0][0][1][0][RTW89_MEXICO][52] = 127, + [0][0][1][0][RTW89_UKRAINE][52] = 127, + [0][0][1][0][RTW89_CHILE][52] = 127, + [0][0][1][0][RTW89_QATAR][52] = 127, [0][1][1][0][RTW89_FCC][0] = 60, [0][1][1][0][RTW89_ETSI][0] = 54, [0][1][1][0][RTW89_MKK][0] = 54, [0][1][1][0][RTW89_IC][0] = 34, - [0][1][1][0][RTW89_KCC][0] = 40, + [0][1][1][0][RTW89_KCC][0] = 60, [0][1][1][0][RTW89_ACMA][0] = 54, [0][1][1][0][RTW89_CN][0] = 46, [0][1][1][0][RTW89_UK][0] = 54, + [0][1][1][0][RTW89_MEXICO][0] = 50, + [0][1][1][0][RTW89_UKRAINE][0] = 42, + [0][1][1][0][RTW89_CHILE][0] = 60, + [0][1][1][0][RTW89_QATAR][0] = 54, [0][1][1][0][RTW89_FCC][2] = 60, [0][1][1][0][RTW89_ETSI][2] = 54, [0][1][1][0][RTW89_MKK][2] = 54, [0][1][1][0][RTW89_IC][2] = 34, - [0][1][1][0][RTW89_KCC][2] = 40, + [0][1][1][0][RTW89_KCC][2] = 60, [0][1][1][0][RTW89_ACMA][2] = 54, [0][1][1][0][RTW89_CN][2] = 46, [0][1][1][0][RTW89_UK][2] = 54, + [0][1][1][0][RTW89_MEXICO][2] = 50, + [0][1][1][0][RTW89_UKRAINE][2] = 42, + [0][1][1][0][RTW89_CHILE][2] = 60, + [0][1][1][0][RTW89_QATAR][2] = 54, [0][1][1][0][RTW89_FCC][4] = 60, [0][1][1][0][RTW89_ETSI][4] = 54, [0][1][1][0][RTW89_MKK][4] = 54, [0][1][1][0][RTW89_IC][4] = 34, - [0][1][1][0][RTW89_KCC][4] = 40, + [0][1][1][0][RTW89_KCC][4] = 60, [0][1][1][0][RTW89_ACMA][4] = 54, [0][1][1][0][RTW89_CN][4] = 46, [0][1][1][0][RTW89_UK][4] = 54, + [0][1][1][0][RTW89_MEXICO][4] = 50, + [0][1][1][0][RTW89_UKRAINE][4] = 42, + [0][1][1][0][RTW89_CHILE][4] = 60, + [0][1][1][0][RTW89_QATAR][4] = 54, [0][1][1][0][RTW89_FCC][6] = 60, [0][1][1][0][RTW89_ETSI][6] = 54, [0][1][1][0][RTW89_MKK][6] = 54, [0][1][1][0][RTW89_IC][6] = 36, - [0][1][1][0][RTW89_KCC][6] = 60, + [0][1][1][0][RTW89_KCC][6] = 40, [0][1][1][0][RTW89_ACMA][6] = 54, [0][1][1][0][RTW89_CN][6] = 46, [0][1][1][0][RTW89_UK][6] = 54, + [0][1][1][0][RTW89_MEXICO][6] = 50, + [0][1][1][0][RTW89_UKRAINE][6] = 42, + [0][1][1][0][RTW89_CHILE][6] = 60, + [0][1][1][0][RTW89_QATAR][6] = 54, [0][1][1][0][RTW89_FCC][8] = 62, [0][1][1][0][RTW89_ETSI][8] = 54, [0][1][1][0][RTW89_MKK][8] = 52, @@ -30588,6 +34372,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][1][0][RTW89_ACMA][8] = 54, [0][1][1][0][RTW89_CN][8] = 46, [0][1][1][0][RTW89_UK][8] = 54, + [0][1][1][0][RTW89_MEXICO][8] = 62, + [0][1][1][0][RTW89_UKRAINE][8] = 42, + [0][1][1][0][RTW89_CHILE][8] = 62, + [0][1][1][0][RTW89_QATAR][8] = 54, [0][1][1][0][RTW89_FCC][10] = 62, [0][1][1][0][RTW89_ETSI][10] = 54, [0][1][1][0][RTW89_MKK][10] = 54, @@ -30596,6 +34384,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][1][0][RTW89_ACMA][10] = 54, [0][1][1][0][RTW89_CN][10] = 46, [0][1][1][0][RTW89_UK][10] = 54, + [0][1][1][0][RTW89_MEXICO][10] = 62, + [0][1][1][0][RTW89_UKRAINE][10] = 42, + [0][1][1][0][RTW89_CHILE][10] = 62, + [0][1][1][0][RTW89_QATAR][10] = 54, [0][1][1][0][RTW89_FCC][12] = 62, [0][1][1][0][RTW89_ETSI][12] = 54, [0][1][1][0][RTW89_MKK][12] = 54, @@ -30604,6 +34396,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][1][0][RTW89_ACMA][12] = 54, [0][1][1][0][RTW89_CN][12] = 46, [0][1][1][0][RTW89_UK][12] = 54, + [0][1][1][0][RTW89_MEXICO][12] = 62, + [0][1][1][0][RTW89_UKRAINE][12] = 42, + [0][1][1][0][RTW89_CHILE][12] = 62, + [0][1][1][0][RTW89_QATAR][12] = 54, [0][1][1][0][RTW89_FCC][14] = 60, [0][1][1][0][RTW89_ETSI][14] = 54, [0][1][1][0][RTW89_MKK][14] = 54, @@ -30612,6 +34408,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][1][0][RTW89_ACMA][14] = 54, [0][1][1][0][RTW89_CN][14] = 46, [0][1][1][0][RTW89_UK][14] = 54, + [0][1][1][0][RTW89_MEXICO][14] = 60, + [0][1][1][0][RTW89_UKRAINE][14] = 42, + [0][1][1][0][RTW89_CHILE][14] = 60, + [0][1][1][0][RTW89_QATAR][14] = 54, [0][1][1][0][RTW89_FCC][15] = 60, [0][1][1][0][RTW89_ETSI][15] = 54, [0][1][1][0][RTW89_MKK][15] = 70, @@ -30620,6 +34420,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][1][0][RTW89_ACMA][15] = 54, [0][1][1][0][RTW89_CN][15] = 127, [0][1][1][0][RTW89_UK][15] = 54, + [0][1][1][0][RTW89_MEXICO][15] = 60, + [0][1][1][0][RTW89_UKRAINE][15] = 42, + [0][1][1][0][RTW89_CHILE][15] = 60, + [0][1][1][0][RTW89_QATAR][15] = 54, [0][1][1][0][RTW89_FCC][17] = 60, [0][1][1][0][RTW89_ETSI][17] = 54, [0][1][1][0][RTW89_MKK][17] = 70, @@ -30628,6 +34432,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][1][0][RTW89_ACMA][17] = 54, [0][1][1][0][RTW89_CN][17] = 127, [0][1][1][0][RTW89_UK][17] = 54, + [0][1][1][0][RTW89_MEXICO][17] = 60, + [0][1][1][0][RTW89_UKRAINE][17] = 42, + [0][1][1][0][RTW89_CHILE][17] = 60, + [0][1][1][0][RTW89_QATAR][17] = 54, [0][1][1][0][RTW89_FCC][19] = 60, [0][1][1][0][RTW89_ETSI][19] = 54, [0][1][1][0][RTW89_MKK][19] = 70, @@ -30636,6 +34444,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][1][0][RTW89_ACMA][19] = 54, [0][1][1][0][RTW89_CN][19] = 127, [0][1][1][0][RTW89_UK][19] = 54, + [0][1][1][0][RTW89_MEXICO][19] = 60, + [0][1][1][0][RTW89_UKRAINE][19] = 42, + [0][1][1][0][RTW89_CHILE][19] = 60, + [0][1][1][0][RTW89_QATAR][19] = 54, [0][1][1][0][RTW89_FCC][21] = 60, [0][1][1][0][RTW89_ETSI][21] = 54, [0][1][1][0][RTW89_MKK][21] = 70, @@ -30644,6 +34456,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][1][0][RTW89_ACMA][21] = 54, [0][1][1][0][RTW89_CN][21] = 127, [0][1][1][0][RTW89_UK][21] = 54, + [0][1][1][0][RTW89_MEXICO][21] = 60, + [0][1][1][0][RTW89_UKRAINE][21] = 42, + [0][1][1][0][RTW89_CHILE][21] = 60, + [0][1][1][0][RTW89_QATAR][21] = 54, [0][1][1][0][RTW89_FCC][23] = 60, [0][1][1][0][RTW89_ETSI][23] = 54, [0][1][1][0][RTW89_MKK][23] = 70, @@ -30652,6 +34468,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][1][0][RTW89_ACMA][23] = 54, [0][1][1][0][RTW89_CN][23] = 127, [0][1][1][0][RTW89_UK][23] = 54, + [0][1][1][0][RTW89_MEXICO][23] = 60, + [0][1][1][0][RTW89_UKRAINE][23] = 42, + [0][1][1][0][RTW89_CHILE][23] = 60, + [0][1][1][0][RTW89_QATAR][23] = 54, [0][1][1][0][RTW89_FCC][25] = 60, [0][1][1][0][RTW89_ETSI][25] = 54, [0][1][1][0][RTW89_MKK][25] = 70, @@ -30660,6 +34480,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][1][0][RTW89_ACMA][25] = 127, [0][1][1][0][RTW89_CN][25] = 127, [0][1][1][0][RTW89_UK][25] = 54, + [0][1][1][0][RTW89_MEXICO][25] = 60, + [0][1][1][0][RTW89_UKRAINE][25] = 42, + [0][1][1][0][RTW89_CHILE][25] = 60, + [0][1][1][0][RTW89_QATAR][25] = 54, [0][1][1][0][RTW89_FCC][27] = 60, [0][1][1][0][RTW89_ETSI][27] = 54, [0][1][1][0][RTW89_MKK][27] = 70, @@ -30668,6 +34492,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][1][0][RTW89_ACMA][27] = 127, [0][1][1][0][RTW89_CN][27] = 127, [0][1][1][0][RTW89_UK][27] = 54, + [0][1][1][0][RTW89_MEXICO][27] = 60, + [0][1][1][0][RTW89_UKRAINE][27] = 42, + [0][1][1][0][RTW89_CHILE][27] = 52, + [0][1][1][0][RTW89_QATAR][27] = 54, [0][1][1][0][RTW89_FCC][29] = 60, [0][1][1][0][RTW89_ETSI][29] = 54, [0][1][1][0][RTW89_MKK][29] = 70, @@ -30676,6 +34504,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][1][0][RTW89_ACMA][29] = 127, [0][1][1][0][RTW89_CN][29] = 127, [0][1][1][0][RTW89_UK][29] = 54, + [0][1][1][0][RTW89_MEXICO][29] = 60, + [0][1][1][0][RTW89_UKRAINE][29] = 42, + [0][1][1][0][RTW89_CHILE][29] = 52, + [0][1][1][0][RTW89_QATAR][29] = 54, [0][1][1][0][RTW89_FCC][31] = 60, [0][1][1][0][RTW89_ETSI][31] = 54, [0][1][1][0][RTW89_MKK][31] = 70, @@ -30684,6 +34516,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][1][0][RTW89_ACMA][31] = 54, [0][1][1][0][RTW89_CN][31] = 127, [0][1][1][0][RTW89_UK][31] = 54, + [0][1][1][0][RTW89_MEXICO][31] = 60, + [0][1][1][0][RTW89_UKRAINE][31] = 42, + [0][1][1][0][RTW89_CHILE][31] = 52, + [0][1][1][0][RTW89_QATAR][31] = 54, [0][1][1][0][RTW89_FCC][33] = 60, [0][1][1][0][RTW89_ETSI][33] = 54, [0][1][1][0][RTW89_MKK][33] = 70, @@ -30692,6 +34528,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][1][0][RTW89_ACMA][33] = 54, [0][1][1][0][RTW89_CN][33] = 127, [0][1][1][0][RTW89_UK][33] = 54, + [0][1][1][0][RTW89_MEXICO][33] = 60, + [0][1][1][0][RTW89_UKRAINE][33] = 42, + [0][1][1][0][RTW89_CHILE][33] = 52, + [0][1][1][0][RTW89_QATAR][33] = 54, [0][1][1][0][RTW89_FCC][35] = 52, [0][1][1][0][RTW89_ETSI][35] = 54, [0][1][1][0][RTW89_MKK][35] = 70, @@ -30700,6 +34540,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][1][0][RTW89_ACMA][35] = 54, [0][1][1][0][RTW89_CN][35] = 127, [0][1][1][0][RTW89_UK][35] = 54, + [0][1][1][0][RTW89_MEXICO][35] = 52, + [0][1][1][0][RTW89_UKRAINE][35] = 42, + [0][1][1][0][RTW89_CHILE][35] = 52, + [0][1][1][0][RTW89_QATAR][35] = 54, [0][1][1][0][RTW89_FCC][37] = 62, [0][1][1][0][RTW89_ETSI][37] = 127, [0][1][1][0][RTW89_MKK][37] = 70, @@ -30708,6 +34552,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][1][0][RTW89_ACMA][37] = 64, [0][1][1][0][RTW89_CN][37] = 127, [0][1][1][0][RTW89_UK][37] = 52, + [0][1][1][0][RTW89_MEXICO][37] = 62, + [0][1][1][0][RTW89_UKRAINE][37] = 127, + [0][1][1][0][RTW89_CHILE][37] = 62, + [0][1][1][0][RTW89_QATAR][37] = 127, [0][1][1][0][RTW89_FCC][38] = 72, [0][1][1][0][RTW89_ETSI][38] = 18, [0][1][1][0][RTW89_MKK][38] = 127, @@ -30716,6 +34564,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][1][0][RTW89_ACMA][38] = 70, [0][1][1][0][RTW89_CN][38] = 64, [0][1][1][0][RTW89_UK][38] = 52, + [0][1][1][0][RTW89_MEXICO][38] = 72, + [0][1][1][0][RTW89_UKRAINE][38] = 18, + [0][1][1][0][RTW89_CHILE][38] = 70, + [0][1][1][0][RTW89_QATAR][38] = 18, [0][1][1][0][RTW89_FCC][40] = 72, [0][1][1][0][RTW89_ETSI][40] = 18, [0][1][1][0][RTW89_MKK][40] = 127, @@ -30724,6 +34576,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][1][0][RTW89_ACMA][40] = 70, [0][1][1][0][RTW89_CN][40] = 64, [0][1][1][0][RTW89_UK][40] = 52, + [0][1][1][0][RTW89_MEXICO][40] = 72, + [0][1][1][0][RTW89_UKRAINE][40] = 18, + [0][1][1][0][RTW89_CHILE][40] = 70, + [0][1][1][0][RTW89_QATAR][40] = 18, [0][1][1][0][RTW89_FCC][42] = 72, [0][1][1][0][RTW89_ETSI][42] = 18, [0][1][1][0][RTW89_MKK][42] = 127, @@ -30732,6 +34588,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][1][0][RTW89_ACMA][42] = 70, [0][1][1][0][RTW89_CN][42] = 64, [0][1][1][0][RTW89_UK][42] = 52, + [0][1][1][0][RTW89_MEXICO][42] = 72, + [0][1][1][0][RTW89_UKRAINE][42] = 18, + [0][1][1][0][RTW89_CHILE][42] = 70, + [0][1][1][0][RTW89_QATAR][42] = 18, [0][1][1][0][RTW89_FCC][44] = 72, [0][1][1][0][RTW89_ETSI][44] = 18, [0][1][1][0][RTW89_MKK][44] = 127, @@ -30740,6 +34600,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][1][0][RTW89_ACMA][44] = 70, [0][1][1][0][RTW89_CN][44] = 60, [0][1][1][0][RTW89_UK][44] = 52, + [0][1][1][0][RTW89_MEXICO][44] = 72, + [0][1][1][0][RTW89_UKRAINE][44] = 18, + [0][1][1][0][RTW89_CHILE][44] = 70, + [0][1][1][0][RTW89_QATAR][44] = 18, [0][1][1][0][RTW89_FCC][46] = 72, [0][1][1][0][RTW89_ETSI][46] = 18, [0][1][1][0][RTW89_MKK][46] = 127, @@ -30748,6 +34612,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][1][0][RTW89_ACMA][46] = 70, [0][1][1][0][RTW89_CN][46] = 60, [0][1][1][0][RTW89_UK][46] = 52, + [0][1][1][0][RTW89_MEXICO][46] = 72, + [0][1][1][0][RTW89_UKRAINE][46] = 18, + [0][1][1][0][RTW89_CHILE][46] = 70, + [0][1][1][0][RTW89_QATAR][46] = 18, [0][1][1][0][RTW89_FCC][48] = 48, [0][1][1][0][RTW89_ETSI][48] = 127, [0][1][1][0][RTW89_MKK][48] = 127, @@ -30756,6 +34624,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][1][0][RTW89_ACMA][48] = 127, [0][1][1][0][RTW89_CN][48] = 127, [0][1][1][0][RTW89_UK][48] = 127, + [0][1][1][0][RTW89_MEXICO][48] = 127, + [0][1][1][0][RTW89_UKRAINE][48] = 127, + [0][1][1][0][RTW89_CHILE][48] = 127, + [0][1][1][0][RTW89_QATAR][48] = 127, [0][1][1][0][RTW89_FCC][50] = 48, [0][1][1][0][RTW89_ETSI][50] = 127, [0][1][1][0][RTW89_MKK][50] = 127, @@ -30764,6 +34636,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][1][0][RTW89_ACMA][50] = 127, [0][1][1][0][RTW89_CN][50] = 127, [0][1][1][0][RTW89_UK][50] = 127, + [0][1][1][0][RTW89_MEXICO][50] = 127, + [0][1][1][0][RTW89_UKRAINE][50] = 127, + [0][1][1][0][RTW89_CHILE][50] = 127, + [0][1][1][0][RTW89_QATAR][50] = 127, [0][1][1][0][RTW89_FCC][52] = 48, [0][1][1][0][RTW89_ETSI][52] = 127, [0][1][1][0][RTW89_MKK][52] = 127, @@ -30772,38 +34648,58 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][1][0][RTW89_ACMA][52] = 127, [0][1][1][0][RTW89_CN][52] = 127, [0][1][1][0][RTW89_UK][52] = 127, + [0][1][1][0][RTW89_MEXICO][52] = 127, + [0][1][1][0][RTW89_UKRAINE][52] = 127, + [0][1][1][0][RTW89_CHILE][52] = 127, + [0][1][1][0][RTW89_QATAR][52] = 127, [0][0][2][0][RTW89_FCC][0] = 70, [0][0][2][0][RTW89_ETSI][0] = 66, [0][0][2][0][RTW89_MKK][0] = 68, [0][0][2][0][RTW89_IC][0] = 60, - [0][0][2][0][RTW89_KCC][0] = 54, + [0][0][2][0][RTW89_KCC][0] = 68, [0][0][2][0][RTW89_ACMA][0] = 66, [0][0][2][0][RTW89_CN][0] = 52, [0][0][2][0][RTW89_UK][0] = 66, + [0][0][2][0][RTW89_MEXICO][0] = 62, + [0][0][2][0][RTW89_UKRAINE][0] = 54, + [0][0][2][0][RTW89_CHILE][0] = 68, + [0][0][2][0][RTW89_QATAR][0] = 66, [0][0][2][0][RTW89_FCC][2] = 72, [0][0][2][0][RTW89_ETSI][2] = 66, [0][0][2][0][RTW89_MKK][2] = 68, [0][0][2][0][RTW89_IC][2] = 60, - [0][0][2][0][RTW89_KCC][2] = 54, + [0][0][2][0][RTW89_KCC][2] = 68, [0][0][2][0][RTW89_ACMA][2] = 66, [0][0][2][0][RTW89_CN][2] = 52, [0][0][2][0][RTW89_UK][2] = 66, + [0][0][2][0][RTW89_MEXICO][2] = 62, + [0][0][2][0][RTW89_UKRAINE][2] = 54, + [0][0][2][0][RTW89_CHILE][2] = 70, + [0][0][2][0][RTW89_QATAR][2] = 66, [0][0][2][0][RTW89_FCC][4] = 72, [0][0][2][0][RTW89_ETSI][4] = 66, [0][0][2][0][RTW89_MKK][4] = 68, [0][0][2][0][RTW89_IC][4] = 60, - [0][0][2][0][RTW89_KCC][4] = 54, + [0][0][2][0][RTW89_KCC][4] = 68, [0][0][2][0][RTW89_ACMA][4] = 66, [0][0][2][0][RTW89_CN][4] = 52, [0][0][2][0][RTW89_UK][4] = 66, + [0][0][2][0][RTW89_MEXICO][4] = 62, + [0][0][2][0][RTW89_UKRAINE][4] = 54, + [0][0][2][0][RTW89_CHILE][4] = 70, + [0][0][2][0][RTW89_QATAR][4] = 66, [0][0][2][0][RTW89_FCC][6] = 72, [0][0][2][0][RTW89_ETSI][6] = 66, [0][0][2][0][RTW89_MKK][6] = 60, [0][0][2][0][RTW89_IC][6] = 60, - [0][0][2][0][RTW89_KCC][6] = 68, + [0][0][2][0][RTW89_KCC][6] = 54, [0][0][2][0][RTW89_ACMA][6] = 66, [0][0][2][0][RTW89_CN][6] = 52, [0][0][2][0][RTW89_UK][6] = 66, + [0][0][2][0][RTW89_MEXICO][6] = 62, + [0][0][2][0][RTW89_UKRAINE][6] = 54, + [0][0][2][0][RTW89_CHILE][6] = 70, + [0][0][2][0][RTW89_QATAR][6] = 66, [0][0][2][0][RTW89_FCC][8] = 72, [0][0][2][0][RTW89_ETSI][8] = 66, [0][0][2][0][RTW89_MKK][8] = 58, @@ -30812,6 +34708,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_ACMA][8] = 66, [0][0][2][0][RTW89_CN][8] = 52, [0][0][2][0][RTW89_UK][8] = 66, + [0][0][2][0][RTW89_MEXICO][8] = 72, + [0][0][2][0][RTW89_UKRAINE][8] = 54, + [0][0][2][0][RTW89_CHILE][8] = 70, + [0][0][2][0][RTW89_QATAR][8] = 66, [0][0][2][0][RTW89_FCC][10] = 72, [0][0][2][0][RTW89_ETSI][10] = 66, [0][0][2][0][RTW89_MKK][10] = 70, @@ -30820,6 +34720,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_ACMA][10] = 66, [0][0][2][0][RTW89_CN][10] = 52, [0][0][2][0][RTW89_UK][10] = 66, + [0][0][2][0][RTW89_MEXICO][10] = 72, + [0][0][2][0][RTW89_UKRAINE][10] = 54, + [0][0][2][0][RTW89_CHILE][10] = 70, + [0][0][2][0][RTW89_QATAR][10] = 66, [0][0][2][0][RTW89_FCC][12] = 72, [0][0][2][0][RTW89_ETSI][12] = 66, [0][0][2][0][RTW89_MKK][12] = 70, @@ -30828,6 +34732,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_ACMA][12] = 66, [0][0][2][0][RTW89_CN][12] = 52, [0][0][2][0][RTW89_UK][12] = 66, + [0][0][2][0][RTW89_MEXICO][12] = 72, + [0][0][2][0][RTW89_UKRAINE][12] = 54, + [0][0][2][0][RTW89_CHILE][12] = 70, + [0][0][2][0][RTW89_QATAR][12] = 66, [0][0][2][0][RTW89_FCC][14] = 68, [0][0][2][0][RTW89_ETSI][14] = 66, [0][0][2][0][RTW89_MKK][14] = 70, @@ -30836,6 +34744,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_ACMA][14] = 66, [0][0][2][0][RTW89_CN][14] = 52, [0][0][2][0][RTW89_UK][14] = 66, + [0][0][2][0][RTW89_MEXICO][14] = 68, + [0][0][2][0][RTW89_UKRAINE][14] = 54, + [0][0][2][0][RTW89_CHILE][14] = 66, + [0][0][2][0][RTW89_QATAR][14] = 66, [0][0][2][0][RTW89_FCC][15] = 70, [0][0][2][0][RTW89_ETSI][15] = 66, [0][0][2][0][RTW89_MKK][15] = 70, @@ -30844,6 +34756,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_ACMA][15] = 66, [0][0][2][0][RTW89_CN][15] = 127, [0][0][2][0][RTW89_UK][15] = 66, + [0][0][2][0][RTW89_MEXICO][15] = 70, + [0][0][2][0][RTW89_UKRAINE][15] = 54, + [0][0][2][0][RTW89_CHILE][15] = 68, + [0][0][2][0][RTW89_QATAR][15] = 66, [0][0][2][0][RTW89_FCC][17] = 72, [0][0][2][0][RTW89_ETSI][17] = 66, [0][0][2][0][RTW89_MKK][17] = 70, @@ -30852,6 +34768,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_ACMA][17] = 66, [0][0][2][0][RTW89_CN][17] = 127, [0][0][2][0][RTW89_UK][17] = 66, + [0][0][2][0][RTW89_MEXICO][17] = 72, + [0][0][2][0][RTW89_UKRAINE][17] = 54, + [0][0][2][0][RTW89_CHILE][17] = 68, + [0][0][2][0][RTW89_QATAR][17] = 66, [0][0][2][0][RTW89_FCC][19] = 72, [0][0][2][0][RTW89_ETSI][19] = 66, [0][0][2][0][RTW89_MKK][19] = 70, @@ -30860,6 +34780,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_ACMA][19] = 66, [0][0][2][0][RTW89_CN][19] = 127, [0][0][2][0][RTW89_UK][19] = 66, + [0][0][2][0][RTW89_MEXICO][19] = 72, + [0][0][2][0][RTW89_UKRAINE][19] = 54, + [0][0][2][0][RTW89_CHILE][19] = 68, + [0][0][2][0][RTW89_QATAR][19] = 66, [0][0][2][0][RTW89_FCC][21] = 72, [0][0][2][0][RTW89_ETSI][21] = 66, [0][0][2][0][RTW89_MKK][21] = 70, @@ -30868,6 +34792,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_ACMA][21] = 66, [0][0][2][0][RTW89_CN][21] = 127, [0][0][2][0][RTW89_UK][21] = 66, + [0][0][2][0][RTW89_MEXICO][21] = 72, + [0][0][2][0][RTW89_UKRAINE][21] = 54, + [0][0][2][0][RTW89_CHILE][21] = 70, + [0][0][2][0][RTW89_QATAR][21] = 66, [0][0][2][0][RTW89_FCC][23] = 72, [0][0][2][0][RTW89_ETSI][23] = 66, [0][0][2][0][RTW89_MKK][23] = 70, @@ -30876,6 +34804,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_ACMA][23] = 66, [0][0][2][0][RTW89_CN][23] = 127, [0][0][2][0][RTW89_UK][23] = 66, + [0][0][2][0][RTW89_MEXICO][23] = 72, + [0][0][2][0][RTW89_UKRAINE][23] = 54, + [0][0][2][0][RTW89_CHILE][23] = 70, + [0][0][2][0][RTW89_QATAR][23] = 66, [0][0][2][0][RTW89_FCC][25] = 72, [0][0][2][0][RTW89_ETSI][25] = 66, [0][0][2][0][RTW89_MKK][25] = 70, @@ -30884,6 +34816,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_ACMA][25] = 127, [0][0][2][0][RTW89_CN][25] = 127, [0][0][2][0][RTW89_UK][25] = 66, + [0][0][2][0][RTW89_MEXICO][25] = 72, + [0][0][2][0][RTW89_UKRAINE][25] = 54, + [0][0][2][0][RTW89_CHILE][25] = 70, + [0][0][2][0][RTW89_QATAR][25] = 66, [0][0][2][0][RTW89_FCC][27] = 72, [0][0][2][0][RTW89_ETSI][27] = 66, [0][0][2][0][RTW89_MKK][27] = 70, @@ -30892,6 +34828,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_ACMA][27] = 127, [0][0][2][0][RTW89_CN][27] = 127, [0][0][2][0][RTW89_UK][27] = 66, + [0][0][2][0][RTW89_MEXICO][27] = 72, + [0][0][2][0][RTW89_UKRAINE][27] = 54, + [0][0][2][0][RTW89_CHILE][27] = 56, + [0][0][2][0][RTW89_QATAR][27] = 66, [0][0][2][0][RTW89_FCC][29] = 72, [0][0][2][0][RTW89_ETSI][29] = 66, [0][0][2][0][RTW89_MKK][29] = 70, @@ -30900,6 +34840,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_ACMA][29] = 127, [0][0][2][0][RTW89_CN][29] = 127, [0][0][2][0][RTW89_UK][29] = 66, + [0][0][2][0][RTW89_MEXICO][29] = 72, + [0][0][2][0][RTW89_UKRAINE][29] = 54, + [0][0][2][0][RTW89_CHILE][29] = 56, + [0][0][2][0][RTW89_QATAR][29] = 66, [0][0][2][0][RTW89_FCC][31] = 72, [0][0][2][0][RTW89_ETSI][31] = 66, [0][0][2][0][RTW89_MKK][31] = 70, @@ -30908,6 +34852,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_ACMA][31] = 66, [0][0][2][0][RTW89_CN][31] = 127, [0][0][2][0][RTW89_UK][31] = 66, + [0][0][2][0][RTW89_MEXICO][31] = 72, + [0][0][2][0][RTW89_UKRAINE][31] = 54, + [0][0][2][0][RTW89_CHILE][31] = 56, + [0][0][2][0][RTW89_QATAR][31] = 66, [0][0][2][0][RTW89_FCC][33] = 72, [0][0][2][0][RTW89_ETSI][33] = 66, [0][0][2][0][RTW89_MKK][33] = 70, @@ -30916,6 +34864,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_ACMA][33] = 66, [0][0][2][0][RTW89_CN][33] = 127, [0][0][2][0][RTW89_UK][33] = 66, + [0][0][2][0][RTW89_MEXICO][33] = 72, + [0][0][2][0][RTW89_UKRAINE][33] = 54, + [0][0][2][0][RTW89_CHILE][33] = 56, + [0][0][2][0][RTW89_QATAR][33] = 66, [0][0][2][0][RTW89_FCC][35] = 56, [0][0][2][0][RTW89_ETSI][35] = 66, [0][0][2][0][RTW89_MKK][35] = 70, @@ -30924,6 +34876,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_ACMA][35] = 66, [0][0][2][0][RTW89_CN][35] = 127, [0][0][2][0][RTW89_UK][35] = 66, + [0][0][2][0][RTW89_MEXICO][35] = 56, + [0][0][2][0][RTW89_UKRAINE][35] = 54, + [0][0][2][0][RTW89_CHILE][35] = 56, + [0][0][2][0][RTW89_QATAR][35] = 66, [0][0][2][0][RTW89_FCC][37] = 72, [0][0][2][0][RTW89_ETSI][37] = 127, [0][0][2][0][RTW89_MKK][37] = 70, @@ -30932,6 +34888,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_ACMA][37] = 70, [0][0][2][0][RTW89_CN][37] = 127, [0][0][2][0][RTW89_UK][37] = 64, + [0][0][2][0][RTW89_MEXICO][37] = 72, + [0][0][2][0][RTW89_UKRAINE][37] = 127, + [0][0][2][0][RTW89_CHILE][37] = 70, + [0][0][2][0][RTW89_QATAR][37] = 127, [0][0][2][0][RTW89_FCC][38] = 72, [0][0][2][0][RTW89_ETSI][38] = 30, [0][0][2][0][RTW89_MKK][38] = 127, @@ -30940,6 +34900,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_ACMA][38] = 70, [0][0][2][0][RTW89_CN][38] = 68, [0][0][2][0][RTW89_UK][38] = 64, + [0][0][2][0][RTW89_MEXICO][38] = 72, + [0][0][2][0][RTW89_UKRAINE][38] = 30, + [0][0][2][0][RTW89_CHILE][38] = 70, + [0][0][2][0][RTW89_QATAR][38] = 30, [0][0][2][0][RTW89_FCC][40] = 72, [0][0][2][0][RTW89_ETSI][40] = 30, [0][0][2][0][RTW89_MKK][40] = 127, @@ -30948,6 +34912,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_ACMA][40] = 70, [0][0][2][0][RTW89_CN][40] = 68, [0][0][2][0][RTW89_UK][40] = 64, + [0][0][2][0][RTW89_MEXICO][40] = 72, + [0][0][2][0][RTW89_UKRAINE][40] = 30, + [0][0][2][0][RTW89_CHILE][40] = 70, + [0][0][2][0][RTW89_QATAR][40] = 30, [0][0][2][0][RTW89_FCC][42] = 72, [0][0][2][0][RTW89_ETSI][42] = 30, [0][0][2][0][RTW89_MKK][42] = 127, @@ -30956,6 +34924,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_ACMA][42] = 70, [0][0][2][0][RTW89_CN][42] = 68, [0][0][2][0][RTW89_UK][42] = 64, + [0][0][2][0][RTW89_MEXICO][42] = 72, + [0][0][2][0][RTW89_UKRAINE][42] = 30, + [0][0][2][0][RTW89_CHILE][42] = 70, + [0][0][2][0][RTW89_QATAR][42] = 30, [0][0][2][0][RTW89_FCC][44] = 72, [0][0][2][0][RTW89_ETSI][44] = 30, [0][0][2][0][RTW89_MKK][44] = 127, @@ -30964,6 +34936,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_ACMA][44] = 70, [0][0][2][0][RTW89_CN][44] = 68, [0][0][2][0][RTW89_UK][44] = 64, + [0][0][2][0][RTW89_MEXICO][44] = 72, + [0][0][2][0][RTW89_UKRAINE][44] = 30, + [0][0][2][0][RTW89_CHILE][44] = 70, + [0][0][2][0][RTW89_QATAR][44] = 30, [0][0][2][0][RTW89_FCC][46] = 72, [0][0][2][0][RTW89_ETSI][46] = 30, [0][0][2][0][RTW89_MKK][46] = 127, @@ -30972,6 +34948,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_ACMA][46] = 70, [0][0][2][0][RTW89_CN][46] = 68, [0][0][2][0][RTW89_UK][46] = 64, + [0][0][2][0][RTW89_MEXICO][46] = 72, + [0][0][2][0][RTW89_UKRAINE][46] = 30, + [0][0][2][0][RTW89_CHILE][46] = 70, + [0][0][2][0][RTW89_QATAR][46] = 30, [0][0][2][0][RTW89_FCC][48] = 72, [0][0][2][0][RTW89_ETSI][48] = 127, [0][0][2][0][RTW89_MKK][48] = 127, @@ -30980,6 +34960,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_ACMA][48] = 127, [0][0][2][0][RTW89_CN][48] = 127, [0][0][2][0][RTW89_UK][48] = 127, + [0][0][2][0][RTW89_MEXICO][48] = 127, + [0][0][2][0][RTW89_UKRAINE][48] = 127, + [0][0][2][0][RTW89_CHILE][48] = 127, + [0][0][2][0][RTW89_QATAR][48] = 127, [0][0][2][0][RTW89_FCC][50] = 72, [0][0][2][0][RTW89_ETSI][50] = 127, [0][0][2][0][RTW89_MKK][50] = 127, @@ -30988,6 +34972,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_ACMA][50] = 127, [0][0][2][0][RTW89_CN][50] = 127, [0][0][2][0][RTW89_UK][50] = 127, + [0][0][2][0][RTW89_MEXICO][50] = 127, + [0][0][2][0][RTW89_UKRAINE][50] = 127, + [0][0][2][0][RTW89_CHILE][50] = 127, + [0][0][2][0][RTW89_QATAR][50] = 127, [0][0][2][0][RTW89_FCC][52] = 72, [0][0][2][0][RTW89_ETSI][52] = 127, [0][0][2][0][RTW89_MKK][52] = 127, @@ -30996,38 +34984,58 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_ACMA][52] = 127, [0][0][2][0][RTW89_CN][52] = 127, [0][0][2][0][RTW89_UK][52] = 127, + [0][0][2][0][RTW89_MEXICO][52] = 127, + [0][0][2][0][RTW89_UKRAINE][52] = 127, + [0][0][2][0][RTW89_CHILE][52] = 127, + [0][0][2][0][RTW89_QATAR][52] = 127, [0][1][2][0][RTW89_FCC][0] = 60, [0][1][2][0][RTW89_ETSI][0] = 54, [0][1][2][0][RTW89_MKK][0] = 54, [0][1][2][0][RTW89_IC][0] = 36, - [0][1][2][0][RTW89_KCC][0] = 40, + [0][1][2][0][RTW89_KCC][0] = 64, [0][1][2][0][RTW89_ACMA][0] = 54, [0][1][2][0][RTW89_CN][0] = 40, [0][1][2][0][RTW89_UK][0] = 54, + [0][1][2][0][RTW89_MEXICO][0] = 50, + [0][1][2][0][RTW89_UKRAINE][0] = 42, + [0][1][2][0][RTW89_CHILE][0] = 60, + [0][1][2][0][RTW89_QATAR][0] = 54, [0][1][2][0][RTW89_FCC][2] = 62, [0][1][2][0][RTW89_ETSI][2] = 54, [0][1][2][0][RTW89_MKK][2] = 54, [0][1][2][0][RTW89_IC][2] = 36, - [0][1][2][0][RTW89_KCC][2] = 40, + [0][1][2][0][RTW89_KCC][2] = 64, [0][1][2][0][RTW89_ACMA][2] = 54, [0][1][2][0][RTW89_CN][2] = 40, [0][1][2][0][RTW89_UK][2] = 54, + [0][1][2][0][RTW89_MEXICO][2] = 50, + [0][1][2][0][RTW89_UKRAINE][2] = 42, + [0][1][2][0][RTW89_CHILE][2] = 62, + [0][1][2][0][RTW89_QATAR][2] = 54, [0][1][2][0][RTW89_FCC][4] = 62, [0][1][2][0][RTW89_ETSI][4] = 54, [0][1][2][0][RTW89_MKK][4] = 54, [0][1][2][0][RTW89_IC][4] = 36, - [0][1][2][0][RTW89_KCC][4] = 40, + [0][1][2][0][RTW89_KCC][4] = 64, [0][1][2][0][RTW89_ACMA][4] = 54, [0][1][2][0][RTW89_CN][4] = 40, [0][1][2][0][RTW89_UK][4] = 54, + [0][1][2][0][RTW89_MEXICO][4] = 50, + [0][1][2][0][RTW89_UKRAINE][4] = 42, + [0][1][2][0][RTW89_CHILE][4] = 62, + [0][1][2][0][RTW89_QATAR][4] = 54, [0][1][2][0][RTW89_FCC][6] = 62, [0][1][2][0][RTW89_ETSI][6] = 54, [0][1][2][0][RTW89_MKK][6] = 50, [0][1][2][0][RTW89_IC][6] = 38, - [0][1][2][0][RTW89_KCC][6] = 64, + [0][1][2][0][RTW89_KCC][6] = 40, [0][1][2][0][RTW89_ACMA][6] = 54, [0][1][2][0][RTW89_CN][6] = 40, [0][1][2][0][RTW89_UK][6] = 54, + [0][1][2][0][RTW89_MEXICO][6] = 50, + [0][1][2][0][RTW89_UKRAINE][6] = 42, + [0][1][2][0][RTW89_CHILE][6] = 62, + [0][1][2][0][RTW89_QATAR][6] = 54, [0][1][2][0][RTW89_FCC][8] = 62, [0][1][2][0][RTW89_ETSI][8] = 54, [0][1][2][0][RTW89_MKK][8] = 42, @@ -31036,6 +35044,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][0][RTW89_ACMA][8] = 54, [0][1][2][0][RTW89_CN][8] = 40, [0][1][2][0][RTW89_UK][8] = 54, + [0][1][2][0][RTW89_MEXICO][8] = 62, + [0][1][2][0][RTW89_UKRAINE][8] = 42, + [0][1][2][0][RTW89_CHILE][8] = 62, + [0][1][2][0][RTW89_QATAR][8] = 54, [0][1][2][0][RTW89_FCC][10] = 62, [0][1][2][0][RTW89_ETSI][10] = 54, [0][1][2][0][RTW89_MKK][10] = 54, @@ -31044,6 +35056,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][0][RTW89_ACMA][10] = 54, [0][1][2][0][RTW89_CN][10] = 40, [0][1][2][0][RTW89_UK][10] = 54, + [0][1][2][0][RTW89_MEXICO][10] = 62, + [0][1][2][0][RTW89_UKRAINE][10] = 42, + [0][1][2][0][RTW89_CHILE][10] = 62, + [0][1][2][0][RTW89_QATAR][10] = 54, [0][1][2][0][RTW89_FCC][12] = 62, [0][1][2][0][RTW89_ETSI][12] = 54, [0][1][2][0][RTW89_MKK][12] = 54, @@ -31052,6 +35068,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][0][RTW89_ACMA][12] = 54, [0][1][2][0][RTW89_CN][12] = 40, [0][1][2][0][RTW89_UK][12] = 54, + [0][1][2][0][RTW89_MEXICO][12] = 62, + [0][1][2][0][RTW89_UKRAINE][12] = 42, + [0][1][2][0][RTW89_CHILE][12] = 62, + [0][1][2][0][RTW89_QATAR][12] = 54, [0][1][2][0][RTW89_FCC][14] = 62, [0][1][2][0][RTW89_ETSI][14] = 54, [0][1][2][0][RTW89_MKK][14] = 54, @@ -31060,6 +35080,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][0][RTW89_ACMA][14] = 54, [0][1][2][0][RTW89_CN][14] = 40, [0][1][2][0][RTW89_UK][14] = 54, + [0][1][2][0][RTW89_MEXICO][14] = 62, + [0][1][2][0][RTW89_UKRAINE][14] = 42, + [0][1][2][0][RTW89_CHILE][14] = 62, + [0][1][2][0][RTW89_QATAR][14] = 54, [0][1][2][0][RTW89_FCC][15] = 60, [0][1][2][0][RTW89_ETSI][15] = 54, [0][1][2][0][RTW89_MKK][15] = 68, @@ -31068,6 +35092,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][0][RTW89_ACMA][15] = 54, [0][1][2][0][RTW89_CN][15] = 127, [0][1][2][0][RTW89_UK][15] = 54, + [0][1][2][0][RTW89_MEXICO][15] = 60, + [0][1][2][0][RTW89_UKRAINE][15] = 42, + [0][1][2][0][RTW89_CHILE][15] = 60, + [0][1][2][0][RTW89_QATAR][15] = 54, [0][1][2][0][RTW89_FCC][17] = 62, [0][1][2][0][RTW89_ETSI][17] = 54, [0][1][2][0][RTW89_MKK][17] = 68, @@ -31076,6 +35104,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][0][RTW89_ACMA][17] = 54, [0][1][2][0][RTW89_CN][17] = 127, [0][1][2][0][RTW89_UK][17] = 54, + [0][1][2][0][RTW89_MEXICO][17] = 62, + [0][1][2][0][RTW89_UKRAINE][17] = 42, + [0][1][2][0][RTW89_CHILE][17] = 60, + [0][1][2][0][RTW89_QATAR][17] = 54, [0][1][2][0][RTW89_FCC][19] = 62, [0][1][2][0][RTW89_ETSI][19] = 54, [0][1][2][0][RTW89_MKK][19] = 68, @@ -31084,6 +35116,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][0][RTW89_ACMA][19] = 54, [0][1][2][0][RTW89_CN][19] = 127, [0][1][2][0][RTW89_UK][19] = 54, + [0][1][2][0][RTW89_MEXICO][19] = 62, + [0][1][2][0][RTW89_UKRAINE][19] = 42, + [0][1][2][0][RTW89_CHILE][19] = 62, + [0][1][2][0][RTW89_QATAR][19] = 54, [0][1][2][0][RTW89_FCC][21] = 62, [0][1][2][0][RTW89_ETSI][21] = 54, [0][1][2][0][RTW89_MKK][21] = 68, @@ -31092,6 +35128,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][0][RTW89_ACMA][21] = 54, [0][1][2][0][RTW89_CN][21] = 127, [0][1][2][0][RTW89_UK][21] = 54, + [0][1][2][0][RTW89_MEXICO][21] = 62, + [0][1][2][0][RTW89_UKRAINE][21] = 42, + [0][1][2][0][RTW89_CHILE][21] = 62, + [0][1][2][0][RTW89_QATAR][21] = 54, [0][1][2][0][RTW89_FCC][23] = 62, [0][1][2][0][RTW89_ETSI][23] = 54, [0][1][2][0][RTW89_MKK][23] = 68, @@ -31100,6 +35140,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][0][RTW89_ACMA][23] = 54, [0][1][2][0][RTW89_CN][23] = 127, [0][1][2][0][RTW89_UK][23] = 54, + [0][1][2][0][RTW89_MEXICO][23] = 62, + [0][1][2][0][RTW89_UKRAINE][23] = 42, + [0][1][2][0][RTW89_CHILE][23] = 62, + [0][1][2][0][RTW89_QATAR][23] = 54, [0][1][2][0][RTW89_FCC][25] = 62, [0][1][2][0][RTW89_ETSI][25] = 54, [0][1][2][0][RTW89_MKK][25] = 68, @@ -31108,6 +35152,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][0][RTW89_ACMA][25] = 127, [0][1][2][0][RTW89_CN][25] = 127, [0][1][2][0][RTW89_UK][25] = 54, + [0][1][2][0][RTW89_MEXICO][25] = 62, + [0][1][2][0][RTW89_UKRAINE][25] = 42, + [0][1][2][0][RTW89_CHILE][25] = 62, + [0][1][2][0][RTW89_QATAR][25] = 54, [0][1][2][0][RTW89_FCC][27] = 62, [0][1][2][0][RTW89_ETSI][27] = 54, [0][1][2][0][RTW89_MKK][27] = 68, @@ -31116,6 +35164,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][0][RTW89_ACMA][27] = 127, [0][1][2][0][RTW89_CN][27] = 127, [0][1][2][0][RTW89_UK][27] = 54, + [0][1][2][0][RTW89_MEXICO][27] = 62, + [0][1][2][0][RTW89_UKRAINE][27] = 42, + [0][1][2][0][RTW89_CHILE][27] = 46, + [0][1][2][0][RTW89_QATAR][27] = 54, [0][1][2][0][RTW89_FCC][29] = 62, [0][1][2][0][RTW89_ETSI][29] = 54, [0][1][2][0][RTW89_MKK][29] = 68, @@ -31124,6 +35176,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][0][RTW89_ACMA][29] = 127, [0][1][2][0][RTW89_CN][29] = 127, [0][1][2][0][RTW89_UK][29] = 54, + [0][1][2][0][RTW89_MEXICO][29] = 62, + [0][1][2][0][RTW89_UKRAINE][29] = 42, + [0][1][2][0][RTW89_CHILE][29] = 46, + [0][1][2][0][RTW89_QATAR][29] = 54, [0][1][2][0][RTW89_FCC][31] = 62, [0][1][2][0][RTW89_ETSI][31] = 54, [0][1][2][0][RTW89_MKK][31] = 68, @@ -31132,6 +35188,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][0][RTW89_ACMA][31] = 54, [0][1][2][0][RTW89_CN][31] = 127, [0][1][2][0][RTW89_UK][31] = 54, + [0][1][2][0][RTW89_MEXICO][31] = 62, + [0][1][2][0][RTW89_UKRAINE][31] = 42, + [0][1][2][0][RTW89_CHILE][31] = 46, + [0][1][2][0][RTW89_QATAR][31] = 54, [0][1][2][0][RTW89_FCC][33] = 62, [0][1][2][0][RTW89_ETSI][33] = 54, [0][1][2][0][RTW89_MKK][33] = 68, @@ -31140,6 +35200,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][0][RTW89_ACMA][33] = 54, [0][1][2][0][RTW89_CN][33] = 127, [0][1][2][0][RTW89_UK][33] = 54, + [0][1][2][0][RTW89_MEXICO][33] = 62, + [0][1][2][0][RTW89_UKRAINE][33] = 42, + [0][1][2][0][RTW89_CHILE][33] = 46, + [0][1][2][0][RTW89_QATAR][33] = 54, [0][1][2][0][RTW89_FCC][35] = 46, [0][1][2][0][RTW89_ETSI][35] = 54, [0][1][2][0][RTW89_MKK][35] = 68, @@ -31148,6 +35212,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][0][RTW89_ACMA][35] = 54, [0][1][2][0][RTW89_CN][35] = 127, [0][1][2][0][RTW89_UK][35] = 54, + [0][1][2][0][RTW89_MEXICO][35] = 46, + [0][1][2][0][RTW89_UKRAINE][35] = 42, + [0][1][2][0][RTW89_CHILE][35] = 46, + [0][1][2][0][RTW89_QATAR][35] = 54, [0][1][2][0][RTW89_FCC][37] = 64, [0][1][2][0][RTW89_ETSI][37] = 127, [0][1][2][0][RTW89_MKK][37] = 68, @@ -31156,6 +35224,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][0][RTW89_ACMA][37] = 64, [0][1][2][0][RTW89_CN][37] = 127, [0][1][2][0][RTW89_UK][37] = 52, + [0][1][2][0][RTW89_MEXICO][37] = 64, + [0][1][2][0][RTW89_UKRAINE][37] = 127, + [0][1][2][0][RTW89_CHILE][37] = 64, + [0][1][2][0][RTW89_QATAR][37] = 127, [0][1][2][0][RTW89_FCC][38] = 72, [0][1][2][0][RTW89_ETSI][38] = 18, [0][1][2][0][RTW89_MKK][38] = 127, @@ -31164,6 +35236,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][0][RTW89_ACMA][38] = 70, [0][1][2][0][RTW89_CN][38] = 68, [0][1][2][0][RTW89_UK][38] = 52, + [0][1][2][0][RTW89_MEXICO][38] = 72, + [0][1][2][0][RTW89_UKRAINE][38] = 18, + [0][1][2][0][RTW89_CHILE][38] = 70, + [0][1][2][0][RTW89_QATAR][38] = 18, [0][1][2][0][RTW89_FCC][40] = 72, [0][1][2][0][RTW89_ETSI][40] = 18, [0][1][2][0][RTW89_MKK][40] = 127, @@ -31172,6 +35248,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][0][RTW89_ACMA][40] = 70, [0][1][2][0][RTW89_CN][40] = 68, [0][1][2][0][RTW89_UK][40] = 52, + [0][1][2][0][RTW89_MEXICO][40] = 72, + [0][1][2][0][RTW89_UKRAINE][40] = 18, + [0][1][2][0][RTW89_CHILE][40] = 70, + [0][1][2][0][RTW89_QATAR][40] = 18, [0][1][2][0][RTW89_FCC][42] = 72, [0][1][2][0][RTW89_ETSI][42] = 18, [0][1][2][0][RTW89_MKK][42] = 127, @@ -31180,6 +35260,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][0][RTW89_ACMA][42] = 70, [0][1][2][0][RTW89_CN][42] = 68, [0][1][2][0][RTW89_UK][42] = 52, + [0][1][2][0][RTW89_MEXICO][42] = 72, + [0][1][2][0][RTW89_UKRAINE][42] = 18, + [0][1][2][0][RTW89_CHILE][42] = 70, + [0][1][2][0][RTW89_QATAR][42] = 18, [0][1][2][0][RTW89_FCC][44] = 72, [0][1][2][0][RTW89_ETSI][44] = 18, [0][1][2][0][RTW89_MKK][44] = 127, @@ -31188,6 +35272,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][0][RTW89_ACMA][44] = 70, [0][1][2][0][RTW89_CN][44] = 68, [0][1][2][0][RTW89_UK][44] = 52, + [0][1][2][0][RTW89_MEXICO][44] = 72, + [0][1][2][0][RTW89_UKRAINE][44] = 18, + [0][1][2][0][RTW89_CHILE][44] = 70, + [0][1][2][0][RTW89_QATAR][44] = 18, [0][1][2][0][RTW89_FCC][46] = 72, [0][1][2][0][RTW89_ETSI][46] = 18, [0][1][2][0][RTW89_MKK][46] = 127, @@ -31196,6 +35284,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][0][RTW89_ACMA][46] = 70, [0][1][2][0][RTW89_CN][46] = 68, [0][1][2][0][RTW89_UK][46] = 52, + [0][1][2][0][RTW89_MEXICO][46] = 72, + [0][1][2][0][RTW89_UKRAINE][46] = 18, + [0][1][2][0][RTW89_CHILE][46] = 70, + [0][1][2][0][RTW89_QATAR][46] = 18, [0][1][2][0][RTW89_FCC][48] = 48, [0][1][2][0][RTW89_ETSI][48] = 127, [0][1][2][0][RTW89_MKK][48] = 127, @@ -31204,6 +35296,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][0][RTW89_ACMA][48] = 127, [0][1][2][0][RTW89_CN][48] = 127, [0][1][2][0][RTW89_UK][48] = 127, + [0][1][2][0][RTW89_MEXICO][48] = 127, + [0][1][2][0][RTW89_UKRAINE][48] = 127, + [0][1][2][0][RTW89_CHILE][48] = 127, + [0][1][2][0][RTW89_QATAR][48] = 127, [0][1][2][0][RTW89_FCC][50] = 50, [0][1][2][0][RTW89_ETSI][50] = 127, [0][1][2][0][RTW89_MKK][50] = 127, @@ -31212,6 +35308,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][0][RTW89_ACMA][50] = 127, [0][1][2][0][RTW89_CN][50] = 127, [0][1][2][0][RTW89_UK][50] = 127, + [0][1][2][0][RTW89_MEXICO][50] = 127, + [0][1][2][0][RTW89_UKRAINE][50] = 127, + [0][1][2][0][RTW89_CHILE][50] = 127, + [0][1][2][0][RTW89_QATAR][50] = 127, [0][1][2][0][RTW89_FCC][52] = 48, [0][1][2][0][RTW89_ETSI][52] = 127, [0][1][2][0][RTW89_MKK][52] = 127, @@ -31220,38 +35320,58 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][0][RTW89_ACMA][52] = 127, [0][1][2][0][RTW89_CN][52] = 127, [0][1][2][0][RTW89_UK][52] = 127, + [0][1][2][0][RTW89_MEXICO][52] = 127, + [0][1][2][0][RTW89_UKRAINE][52] = 127, + [0][1][2][0][RTW89_CHILE][52] = 127, + [0][1][2][0][RTW89_QATAR][52] = 127, [0][1][2][1][RTW89_FCC][0] = 60, [0][1][2][1][RTW89_ETSI][0] = 40, [0][1][2][1][RTW89_MKK][0] = 54, [0][1][2][1][RTW89_IC][0] = 40, - [0][1][2][1][RTW89_KCC][0] = 40, + [0][1][2][1][RTW89_KCC][0] = 64, [0][1][2][1][RTW89_ACMA][0] = 40, [0][1][2][1][RTW89_CN][0] = 36, [0][1][2][1][RTW89_UK][0] = 40, + [0][1][2][1][RTW89_MEXICO][0] = 50, + [0][1][2][1][RTW89_UKRAINE][0] = 30, + [0][1][2][1][RTW89_CHILE][0] = 60, + [0][1][2][1][RTW89_QATAR][0] = 40, [0][1][2][1][RTW89_FCC][2] = 62, [0][1][2][1][RTW89_ETSI][2] = 40, [0][1][2][1][RTW89_MKK][2] = 54, [0][1][2][1][RTW89_IC][2] = 40, - [0][1][2][1][RTW89_KCC][2] = 40, + [0][1][2][1][RTW89_KCC][2] = 64, [0][1][2][1][RTW89_ACMA][2] = 40, [0][1][2][1][RTW89_CN][2] = 36, [0][1][2][1][RTW89_UK][2] = 40, + [0][1][2][1][RTW89_MEXICO][2] = 50, + [0][1][2][1][RTW89_UKRAINE][2] = 30, + [0][1][2][1][RTW89_CHILE][2] = 60, + [0][1][2][1][RTW89_QATAR][2] = 40, [0][1][2][1][RTW89_FCC][4] = 62, [0][1][2][1][RTW89_ETSI][4] = 40, [0][1][2][1][RTW89_MKK][4] = 54, [0][1][2][1][RTW89_IC][4] = 40, - [0][1][2][1][RTW89_KCC][4] = 40, + [0][1][2][1][RTW89_KCC][4] = 64, [0][1][2][1][RTW89_ACMA][4] = 40, [0][1][2][1][RTW89_CN][4] = 36, [0][1][2][1][RTW89_UK][4] = 40, + [0][1][2][1][RTW89_MEXICO][4] = 50, + [0][1][2][1][RTW89_UKRAINE][4] = 30, + [0][1][2][1][RTW89_CHILE][4] = 60, + [0][1][2][1][RTW89_QATAR][4] = 40, [0][1][2][1][RTW89_FCC][6] = 62, [0][1][2][1][RTW89_ETSI][6] = 40, [0][1][2][1][RTW89_MKK][6] = 50, [0][1][2][1][RTW89_IC][6] = 40, - [0][1][2][1][RTW89_KCC][6] = 64, + [0][1][2][1][RTW89_KCC][6] = 40, [0][1][2][1][RTW89_ACMA][6] = 40, [0][1][2][1][RTW89_CN][6] = 36, [0][1][2][1][RTW89_UK][6] = 40, + [0][1][2][1][RTW89_MEXICO][6] = 50, + [0][1][2][1][RTW89_UKRAINE][6] = 30, + [0][1][2][1][RTW89_CHILE][6] = 60, + [0][1][2][1][RTW89_QATAR][6] = 40, [0][1][2][1][RTW89_FCC][8] = 62, [0][1][2][1][RTW89_ETSI][8] = 40, [0][1][2][1][RTW89_MKK][8] = 42, @@ -31260,6 +35380,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][1][RTW89_ACMA][8] = 40, [0][1][2][1][RTW89_CN][8] = 36, [0][1][2][1][RTW89_UK][8] = 40, + [0][1][2][1][RTW89_MEXICO][8] = 62, + [0][1][2][1][RTW89_UKRAINE][8] = 30, + [0][1][2][1][RTW89_CHILE][8] = 60, + [0][1][2][1][RTW89_QATAR][8] = 40, [0][1][2][1][RTW89_FCC][10] = 62, [0][1][2][1][RTW89_ETSI][10] = 40, [0][1][2][1][RTW89_MKK][10] = 54, @@ -31268,6 +35392,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][1][RTW89_ACMA][10] = 40, [0][1][2][1][RTW89_CN][10] = 36, [0][1][2][1][RTW89_UK][10] = 40, + [0][1][2][1][RTW89_MEXICO][10] = 62, + [0][1][2][1][RTW89_UKRAINE][10] = 30, + [0][1][2][1][RTW89_CHILE][10] = 60, + [0][1][2][1][RTW89_QATAR][10] = 40, [0][1][2][1][RTW89_FCC][12] = 62, [0][1][2][1][RTW89_ETSI][12] = 40, [0][1][2][1][RTW89_MKK][12] = 54, @@ -31276,6 +35404,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][1][RTW89_ACMA][12] = 40, [0][1][2][1][RTW89_CN][12] = 36, [0][1][2][1][RTW89_UK][12] = 40, + [0][1][2][1][RTW89_MEXICO][12] = 62, + [0][1][2][1][RTW89_UKRAINE][12] = 30, + [0][1][2][1][RTW89_CHILE][12] = 60, + [0][1][2][1][RTW89_QATAR][12] = 40, [0][1][2][1][RTW89_FCC][14] = 62, [0][1][2][1][RTW89_ETSI][14] = 40, [0][1][2][1][RTW89_MKK][14] = 54, @@ -31284,6 +35416,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][1][RTW89_ACMA][14] = 40, [0][1][2][1][RTW89_CN][14] = 36, [0][1][2][1][RTW89_UK][14] = 40, + [0][1][2][1][RTW89_MEXICO][14] = 62, + [0][1][2][1][RTW89_UKRAINE][14] = 30, + [0][1][2][1][RTW89_CHILE][14] = 60, + [0][1][2][1][RTW89_QATAR][14] = 40, [0][1][2][1][RTW89_FCC][15] = 60, [0][1][2][1][RTW89_ETSI][15] = 40, [0][1][2][1][RTW89_MKK][15] = 68, @@ -31292,6 +35428,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][1][RTW89_ACMA][15] = 40, [0][1][2][1][RTW89_CN][15] = 127, [0][1][2][1][RTW89_UK][15] = 40, + [0][1][2][1][RTW89_MEXICO][15] = 60, + [0][1][2][1][RTW89_UKRAINE][15] = 30, + [0][1][2][1][RTW89_CHILE][15] = 60, + [0][1][2][1][RTW89_QATAR][15] = 40, [0][1][2][1][RTW89_FCC][17] = 62, [0][1][2][1][RTW89_ETSI][17] = 40, [0][1][2][1][RTW89_MKK][17] = 68, @@ -31300,6 +35440,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][1][RTW89_ACMA][17] = 40, [0][1][2][1][RTW89_CN][17] = 127, [0][1][2][1][RTW89_UK][17] = 40, + [0][1][2][1][RTW89_MEXICO][17] = 62, + [0][1][2][1][RTW89_UKRAINE][17] = 30, + [0][1][2][1][RTW89_CHILE][17] = 60, + [0][1][2][1][RTW89_QATAR][17] = 40, [0][1][2][1][RTW89_FCC][19] = 62, [0][1][2][1][RTW89_ETSI][19] = 40, [0][1][2][1][RTW89_MKK][19] = 68, @@ -31308,6 +35452,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][1][RTW89_ACMA][19] = 40, [0][1][2][1][RTW89_CN][19] = 127, [0][1][2][1][RTW89_UK][19] = 40, + [0][1][2][1][RTW89_MEXICO][19] = 62, + [0][1][2][1][RTW89_UKRAINE][19] = 30, + [0][1][2][1][RTW89_CHILE][19] = 60, + [0][1][2][1][RTW89_QATAR][19] = 40, [0][1][2][1][RTW89_FCC][21] = 62, [0][1][2][1][RTW89_ETSI][21] = 40, [0][1][2][1][RTW89_MKK][21] = 68, @@ -31316,6 +35464,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][1][RTW89_ACMA][21] = 40, [0][1][2][1][RTW89_CN][21] = 127, [0][1][2][1][RTW89_UK][21] = 40, + [0][1][2][1][RTW89_MEXICO][21] = 62, + [0][1][2][1][RTW89_UKRAINE][21] = 30, + [0][1][2][1][RTW89_CHILE][21] = 60, + [0][1][2][1][RTW89_QATAR][21] = 40, [0][1][2][1][RTW89_FCC][23] = 62, [0][1][2][1][RTW89_ETSI][23] = 40, [0][1][2][1][RTW89_MKK][23] = 68, @@ -31324,6 +35476,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][1][RTW89_ACMA][23] = 40, [0][1][2][1][RTW89_CN][23] = 127, [0][1][2][1][RTW89_UK][23] = 40, + [0][1][2][1][RTW89_MEXICO][23] = 62, + [0][1][2][1][RTW89_UKRAINE][23] = 30, + [0][1][2][1][RTW89_CHILE][23] = 60, + [0][1][2][1][RTW89_QATAR][23] = 40, [0][1][2][1][RTW89_FCC][25] = 46, [0][1][2][1][RTW89_ETSI][25] = 40, [0][1][2][1][RTW89_MKK][25] = 68, @@ -31332,6 +35488,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][1][RTW89_ACMA][25] = 127, [0][1][2][1][RTW89_CN][25] = 127, [0][1][2][1][RTW89_UK][25] = 40, + [0][1][2][1][RTW89_MEXICO][25] = 46, + [0][1][2][1][RTW89_UKRAINE][25] = 30, + [0][1][2][1][RTW89_CHILE][25] = 60, + [0][1][2][1][RTW89_QATAR][25] = 40, [0][1][2][1][RTW89_FCC][27] = 46, [0][1][2][1][RTW89_ETSI][27] = 40, [0][1][2][1][RTW89_MKK][27] = 68, @@ -31340,6 +35500,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][1][RTW89_ACMA][27] = 127, [0][1][2][1][RTW89_CN][27] = 127, [0][1][2][1][RTW89_UK][27] = 40, + [0][1][2][1][RTW89_MEXICO][27] = 46, + [0][1][2][1][RTW89_UKRAINE][27] = 30, + [0][1][2][1][RTW89_CHILE][27] = 46, + [0][1][2][1][RTW89_QATAR][27] = 40, [0][1][2][1][RTW89_FCC][29] = 46, [0][1][2][1][RTW89_ETSI][29] = 40, [0][1][2][1][RTW89_MKK][29] = 68, @@ -31348,6 +35512,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][1][RTW89_ACMA][29] = 127, [0][1][2][1][RTW89_CN][29] = 127, [0][1][2][1][RTW89_UK][29] = 40, + [0][1][2][1][RTW89_MEXICO][29] = 46, + [0][1][2][1][RTW89_UKRAINE][29] = 30, + [0][1][2][1][RTW89_CHILE][29] = 46, + [0][1][2][1][RTW89_QATAR][29] = 40, [0][1][2][1][RTW89_FCC][31] = 46, [0][1][2][1][RTW89_ETSI][31] = 40, [0][1][2][1][RTW89_MKK][31] = 68, @@ -31356,6 +35524,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][1][RTW89_ACMA][31] = 40, [0][1][2][1][RTW89_CN][31] = 127, [0][1][2][1][RTW89_UK][31] = 40, + [0][1][2][1][RTW89_MEXICO][31] = 46, + [0][1][2][1][RTW89_UKRAINE][31] = 30, + [0][1][2][1][RTW89_CHILE][31] = 46, + [0][1][2][1][RTW89_QATAR][31] = 40, [0][1][2][1][RTW89_FCC][33] = 46, [0][1][2][1][RTW89_ETSI][33] = 40, [0][1][2][1][RTW89_MKK][33] = 68, @@ -31364,6 +35536,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][1][RTW89_ACMA][33] = 40, [0][1][2][1][RTW89_CN][33] = 127, [0][1][2][1][RTW89_UK][33] = 40, + [0][1][2][1][RTW89_MEXICO][33] = 46, + [0][1][2][1][RTW89_UKRAINE][33] = 30, + [0][1][2][1][RTW89_CHILE][33] = 46, + [0][1][2][1][RTW89_QATAR][33] = 40, [0][1][2][1][RTW89_FCC][35] = 46, [0][1][2][1][RTW89_ETSI][35] = 40, [0][1][2][1][RTW89_MKK][35] = 68, @@ -31372,6 +35548,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][1][RTW89_ACMA][35] = 40, [0][1][2][1][RTW89_CN][35] = 127, [0][1][2][1][RTW89_UK][35] = 40, + [0][1][2][1][RTW89_MEXICO][35] = 46, + [0][1][2][1][RTW89_UKRAINE][35] = 30, + [0][1][2][1][RTW89_CHILE][35] = 46, + [0][1][2][1][RTW89_QATAR][35] = 40, [0][1][2][1][RTW89_FCC][37] = 64, [0][1][2][1][RTW89_ETSI][37] = 127, [0][1][2][1][RTW89_MKK][37] = 68, @@ -31380,6 +35560,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][1][RTW89_ACMA][37] = 64, [0][1][2][1][RTW89_CN][37] = 127, [0][1][2][1][RTW89_UK][37] = 40, + [0][1][2][1][RTW89_MEXICO][37] = 64, + [0][1][2][1][RTW89_UKRAINE][37] = 127, + [0][1][2][1][RTW89_CHILE][37] = 64, + [0][1][2][1][RTW89_QATAR][37] = 127, [0][1][2][1][RTW89_FCC][38] = 72, [0][1][2][1][RTW89_ETSI][38] = 6, [0][1][2][1][RTW89_MKK][38] = 127, @@ -31388,6 +35572,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][1][RTW89_ACMA][38] = 70, [0][1][2][1][RTW89_CN][38] = 60, [0][1][2][1][RTW89_UK][38] = 40, + [0][1][2][1][RTW89_MEXICO][38] = 72, + [0][1][2][1][RTW89_UKRAINE][38] = 6, + [0][1][2][1][RTW89_CHILE][38] = 60, + [0][1][2][1][RTW89_QATAR][38] = 6, [0][1][2][1][RTW89_FCC][40] = 72, [0][1][2][1][RTW89_ETSI][40] = 6, [0][1][2][1][RTW89_MKK][40] = 127, @@ -31396,6 +35584,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][1][RTW89_ACMA][40] = 70, [0][1][2][1][RTW89_CN][40] = 60, [0][1][2][1][RTW89_UK][40] = 40, + [0][1][2][1][RTW89_MEXICO][40] = 72, + [0][1][2][1][RTW89_UKRAINE][40] = 6, + [0][1][2][1][RTW89_CHILE][40] = 60, + [0][1][2][1][RTW89_QATAR][40] = 6, [0][1][2][1][RTW89_FCC][42] = 72, [0][1][2][1][RTW89_ETSI][42] = 6, [0][1][2][1][RTW89_MKK][42] = 127, @@ -31404,6 +35596,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][1][RTW89_ACMA][42] = 70, [0][1][2][1][RTW89_CN][42] = 60, [0][1][2][1][RTW89_UK][42] = 40, + [0][1][2][1][RTW89_MEXICO][42] = 72, + [0][1][2][1][RTW89_UKRAINE][42] = 6, + [0][1][2][1][RTW89_CHILE][42] = 60, + [0][1][2][1][RTW89_QATAR][42] = 6, [0][1][2][1][RTW89_FCC][44] = 72, [0][1][2][1][RTW89_ETSI][44] = 6, [0][1][2][1][RTW89_MKK][44] = 127, @@ -31412,6 +35608,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][1][RTW89_ACMA][44] = 70, [0][1][2][1][RTW89_CN][44] = 54, [0][1][2][1][RTW89_UK][44] = 40, + [0][1][2][1][RTW89_MEXICO][44] = 72, + [0][1][2][1][RTW89_UKRAINE][44] = 6, + [0][1][2][1][RTW89_CHILE][44] = 60, + [0][1][2][1][RTW89_QATAR][44] = 6, [0][1][2][1][RTW89_FCC][46] = 72, [0][1][2][1][RTW89_ETSI][46] = 6, [0][1][2][1][RTW89_MKK][46] = 127, @@ -31420,6 +35620,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][1][RTW89_ACMA][46] = 70, [0][1][2][1][RTW89_CN][46] = 54, [0][1][2][1][RTW89_UK][46] = 40, + [0][1][2][1][RTW89_MEXICO][46] = 72, + [0][1][2][1][RTW89_UKRAINE][46] = 6, + [0][1][2][1][RTW89_CHILE][46] = 60, + [0][1][2][1][RTW89_QATAR][46] = 6, [0][1][2][1][RTW89_FCC][48] = 48, [0][1][2][1][RTW89_ETSI][48] = 127, [0][1][2][1][RTW89_MKK][48] = 127, @@ -31428,6 +35632,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][1][RTW89_ACMA][48] = 127, [0][1][2][1][RTW89_CN][48] = 127, [0][1][2][1][RTW89_UK][48] = 127, + [0][1][2][1][RTW89_MEXICO][48] = 127, + [0][1][2][1][RTW89_UKRAINE][48] = 127, + [0][1][2][1][RTW89_CHILE][48] = 127, + [0][1][2][1][RTW89_QATAR][48] = 127, [0][1][2][1][RTW89_FCC][50] = 50, [0][1][2][1][RTW89_ETSI][50] = 127, [0][1][2][1][RTW89_MKK][50] = 127, @@ -31436,6 +35644,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][1][RTW89_ACMA][50] = 127, [0][1][2][1][RTW89_CN][50] = 127, [0][1][2][1][RTW89_UK][50] = 127, + [0][1][2][1][RTW89_MEXICO][50] = 127, + [0][1][2][1][RTW89_UKRAINE][50] = 127, + [0][1][2][1][RTW89_CHILE][50] = 127, + [0][1][2][1][RTW89_QATAR][50] = 127, [0][1][2][1][RTW89_FCC][52] = 48, [0][1][2][1][RTW89_ETSI][52] = 127, [0][1][2][1][RTW89_MKK][52] = 127, @@ -31444,22 +35656,34 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][1][RTW89_ACMA][52] = 127, [0][1][2][1][RTW89_CN][52] = 127, [0][1][2][1][RTW89_UK][52] = 127, + [0][1][2][1][RTW89_MEXICO][52] = 127, + [0][1][2][1][RTW89_UKRAINE][52] = 127, + [0][1][2][1][RTW89_CHILE][52] = 127, + [0][1][2][1][RTW89_QATAR][52] = 127, [1][0][2][0][RTW89_FCC][1] = 64, [1][0][2][0][RTW89_ETSI][1] = 66, [1][0][2][0][RTW89_MKK][1] = 66, [1][0][2][0][RTW89_IC][1] = 62, - [1][0][2][0][RTW89_KCC][1] = 66, + [1][0][2][0][RTW89_KCC][1] = 54, [1][0][2][0][RTW89_ACMA][1] = 66, [1][0][2][0][RTW89_CN][1] = 54, [1][0][2][0][RTW89_UK][1] = 66, + [1][0][2][0][RTW89_MEXICO][1] = 62, + [1][0][2][0][RTW89_UKRAINE][1] = 54, + [1][0][2][0][RTW89_CHILE][1] = 62, + [1][0][2][0][RTW89_QATAR][1] = 66, [1][0][2][0][RTW89_FCC][5] = 68, [1][0][2][0][RTW89_ETSI][5] = 66, [1][0][2][0][RTW89_MKK][5] = 66, [1][0][2][0][RTW89_IC][5] = 64, - [1][0][2][0][RTW89_KCC][5] = 54, + [1][0][2][0][RTW89_KCC][5] = 66, [1][0][2][0][RTW89_ACMA][5] = 66, [1][0][2][0][RTW89_CN][5] = 54, [1][0][2][0][RTW89_UK][5] = 66, + [1][0][2][0][RTW89_MEXICO][5] = 62, + [1][0][2][0][RTW89_UKRAINE][5] = 54, + [1][0][2][0][RTW89_CHILE][5] = 66, + [1][0][2][0][RTW89_QATAR][5] = 66, [1][0][2][0][RTW89_FCC][9] = 68, [1][0][2][0][RTW89_ETSI][9] = 66, [1][0][2][0][RTW89_MKK][9] = 66, @@ -31468,6 +35692,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][0][2][0][RTW89_ACMA][9] = 66, [1][0][2][0][RTW89_CN][9] = 54, [1][0][2][0][RTW89_UK][9] = 66, + [1][0][2][0][RTW89_MEXICO][9] = 68, + [1][0][2][0][RTW89_UKRAINE][9] = 54, + [1][0][2][0][RTW89_CHILE][9] = 66, + [1][0][2][0][RTW89_QATAR][9] = 66, [1][0][2][0][RTW89_FCC][13] = 60, [1][0][2][0][RTW89_ETSI][13] = 66, [1][0][2][0][RTW89_MKK][13] = 66, @@ -31476,6 +35704,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][0][2][0][RTW89_ACMA][13] = 66, [1][0][2][0][RTW89_CN][13] = 54, [1][0][2][0][RTW89_UK][13] = 66, + [1][0][2][0][RTW89_MEXICO][13] = 60, + [1][0][2][0][RTW89_UKRAINE][13] = 54, + [1][0][2][0][RTW89_CHILE][13] = 60, + [1][0][2][0][RTW89_QATAR][13] = 66, [1][0][2][0][RTW89_FCC][16] = 64, [1][0][2][0][RTW89_ETSI][16] = 66, [1][0][2][0][RTW89_MKK][16] = 66, @@ -31484,6 +35716,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][0][2][0][RTW89_ACMA][16] = 66, [1][0][2][0][RTW89_CN][16] = 127, [1][0][2][0][RTW89_UK][16] = 66, + [1][0][2][0][RTW89_MEXICO][16] = 64, + [1][0][2][0][RTW89_UKRAINE][16] = 54, + [1][0][2][0][RTW89_CHILE][16] = 64, + [1][0][2][0][RTW89_QATAR][16] = 66, [1][0][2][0][RTW89_FCC][20] = 68, [1][0][2][0][RTW89_ETSI][20] = 66, [1][0][2][0][RTW89_MKK][20] = 66, @@ -31492,6 +35728,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][0][2][0][RTW89_ACMA][20] = 66, [1][0][2][0][RTW89_CN][20] = 127, [1][0][2][0][RTW89_UK][20] = 66, + [1][0][2][0][RTW89_MEXICO][20] = 68, + [1][0][2][0][RTW89_UKRAINE][20] = 54, + [1][0][2][0][RTW89_CHILE][20] = 66, + [1][0][2][0][RTW89_QATAR][20] = 66, [1][0][2][0][RTW89_FCC][24] = 68, [1][0][2][0][RTW89_ETSI][24] = 66, [1][0][2][0][RTW89_MKK][24] = 66, @@ -31500,6 +35740,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][0][2][0][RTW89_ACMA][24] = 127, [1][0][2][0][RTW89_CN][24] = 127, [1][0][2][0][RTW89_UK][24] = 66, + [1][0][2][0][RTW89_MEXICO][24] = 68, + [1][0][2][0][RTW89_UKRAINE][24] = 54, + [1][0][2][0][RTW89_CHILE][24] = 66, + [1][0][2][0][RTW89_QATAR][24] = 66, [1][0][2][0][RTW89_FCC][28] = 68, [1][0][2][0][RTW89_ETSI][28] = 66, [1][0][2][0][RTW89_MKK][28] = 66, @@ -31508,6 +35752,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][0][2][0][RTW89_ACMA][28] = 127, [1][0][2][0][RTW89_CN][28] = 127, [1][0][2][0][RTW89_UK][28] = 66, + [1][0][2][0][RTW89_MEXICO][28] = 68, + [1][0][2][0][RTW89_UKRAINE][28] = 54, + [1][0][2][0][RTW89_CHILE][28] = 62, + [1][0][2][0][RTW89_QATAR][28] = 66, [1][0][2][0][RTW89_FCC][32] = 62, [1][0][2][0][RTW89_ETSI][32] = 66, [1][0][2][0][RTW89_MKK][32] = 66, @@ -31516,6 +35764,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][0][2][0][RTW89_ACMA][32] = 66, [1][0][2][0][RTW89_CN][32] = 127, [1][0][2][0][RTW89_UK][32] = 66, + [1][0][2][0][RTW89_MEXICO][32] = 62, + [1][0][2][0][RTW89_UKRAINE][32] = 54, + [1][0][2][0][RTW89_CHILE][32] = 62, + [1][0][2][0][RTW89_QATAR][32] = 66, [1][0][2][0][RTW89_FCC][36] = 68, [1][0][2][0][RTW89_ETSI][36] = 127, [1][0][2][0][RTW89_MKK][36] = 66, @@ -31524,6 +35776,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][0][2][0][RTW89_ACMA][36] = 66, [1][0][2][0][RTW89_CN][36] = 127, [1][0][2][0][RTW89_UK][36] = 64, + [1][0][2][0][RTW89_MEXICO][36] = 68, + [1][0][2][0][RTW89_UKRAINE][36] = 127, + [1][0][2][0][RTW89_CHILE][36] = 66, + [1][0][2][0][RTW89_QATAR][36] = 127, [1][0][2][0][RTW89_FCC][39] = 68, [1][0][2][0][RTW89_ETSI][39] = 30, [1][0][2][0][RTW89_MKK][39] = 127, @@ -31532,6 +35788,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][0][2][0][RTW89_ACMA][39] = 66, [1][0][2][0][RTW89_CN][39] = 62, [1][0][2][0][RTW89_UK][39] = 64, + [1][0][2][0][RTW89_MEXICO][39] = 68, + [1][0][2][0][RTW89_UKRAINE][39] = 30, + [1][0][2][0][RTW89_CHILE][39] = 66, + [1][0][2][0][RTW89_QATAR][39] = 30, [1][0][2][0][RTW89_FCC][43] = 68, [1][0][2][0][RTW89_ETSI][43] = 30, [1][0][2][0][RTW89_MKK][43] = 127, @@ -31540,6 +35800,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][0][2][0][RTW89_ACMA][43] = 66, [1][0][2][0][RTW89_CN][43] = 66, [1][0][2][0][RTW89_UK][43] = 64, + [1][0][2][0][RTW89_MEXICO][43] = 68, + [1][0][2][0][RTW89_UKRAINE][43] = 30, + [1][0][2][0][RTW89_CHILE][43] = 66, + [1][0][2][0][RTW89_QATAR][43] = 30, [1][0][2][0][RTW89_FCC][47] = 68, [1][0][2][0][RTW89_ETSI][47] = 127, [1][0][2][0][RTW89_MKK][47] = 127, @@ -31548,6 +35812,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][0][2][0][RTW89_ACMA][47] = 127, [1][0][2][0][RTW89_CN][47] = 127, [1][0][2][0][RTW89_UK][47] = 127, + [1][0][2][0][RTW89_MEXICO][47] = 127, + [1][0][2][0][RTW89_UKRAINE][47] = 127, + [1][0][2][0][RTW89_CHILE][47] = 127, + [1][0][2][0][RTW89_QATAR][47] = 127, [1][0][2][0][RTW89_FCC][51] = 68, [1][0][2][0][RTW89_ETSI][51] = 127, [1][0][2][0][RTW89_MKK][51] = 127, @@ -31556,6 +35824,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][0][2][0][RTW89_ACMA][51] = 127, [1][0][2][0][RTW89_CN][51] = 127, [1][0][2][0][RTW89_UK][51] = 127, + [1][0][2][0][RTW89_MEXICO][51] = 127, + [1][0][2][0][RTW89_UKRAINE][51] = 127, + [1][0][2][0][RTW89_CHILE][51] = 127, + [1][0][2][0][RTW89_QATAR][51] = 127, [1][1][2][0][RTW89_FCC][1] = 54, [1][1][2][0][RTW89_ETSI][1] = 54, [1][1][2][0][RTW89_MKK][1] = 48, @@ -31564,6 +35836,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][1][2][0][RTW89_ACMA][1] = 54, [1][1][2][0][RTW89_CN][1] = 42, [1][1][2][0][RTW89_UK][1] = 54, + [1][1][2][0][RTW89_MEXICO][1] = 50, + [1][1][2][0][RTW89_UKRAINE][1] = 42, + [1][1][2][0][RTW89_CHILE][1] = 54, + [1][1][2][0][RTW89_QATAR][1] = 54, [1][1][2][0][RTW89_FCC][5] = 68, [1][1][2][0][RTW89_ETSI][5] = 54, [1][1][2][0][RTW89_MKK][5] = 52, @@ -31572,6 +35848,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][1][2][0][RTW89_ACMA][5] = 54, [1][1][2][0][RTW89_CN][5] = 42, [1][1][2][0][RTW89_UK][5] = 54, + [1][1][2][0][RTW89_MEXICO][5] = 50, + [1][1][2][0][RTW89_UKRAINE][5] = 42, + [1][1][2][0][RTW89_CHILE][5] = 66, + [1][1][2][0][RTW89_QATAR][5] = 54, [1][1][2][0][RTW89_FCC][9] = 68, [1][1][2][0][RTW89_ETSI][9] = 54, [1][1][2][0][RTW89_MKK][9] = 52, @@ -31580,6 +35860,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][1][2][0][RTW89_ACMA][9] = 54, [1][1][2][0][RTW89_CN][9] = 42, [1][1][2][0][RTW89_UK][9] = 54, + [1][1][2][0][RTW89_MEXICO][9] = 68, + [1][1][2][0][RTW89_UKRAINE][9] = 42, + [1][1][2][0][RTW89_CHILE][9] = 66, + [1][1][2][0][RTW89_QATAR][9] = 54, [1][1][2][0][RTW89_FCC][13] = 54, [1][1][2][0][RTW89_ETSI][13] = 54, [1][1][2][0][RTW89_MKK][13] = 52, @@ -31588,6 +35872,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][1][2][0][RTW89_ACMA][13] = 54, [1][1][2][0][RTW89_CN][13] = 42, [1][1][2][0][RTW89_UK][13] = 54, + [1][1][2][0][RTW89_MEXICO][13] = 54, + [1][1][2][0][RTW89_UKRAINE][13] = 42, + [1][1][2][0][RTW89_CHILE][13] = 54, + [1][1][2][0][RTW89_QATAR][13] = 54, [1][1][2][0][RTW89_FCC][16] = 56, [1][1][2][0][RTW89_ETSI][16] = 54, [1][1][2][0][RTW89_MKK][16] = 66, @@ -31596,6 +35884,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][1][2][0][RTW89_ACMA][16] = 54, [1][1][2][0][RTW89_CN][16] = 127, [1][1][2][0][RTW89_UK][16] = 54, + [1][1][2][0][RTW89_MEXICO][16] = 56, + [1][1][2][0][RTW89_UKRAINE][16] = 42, + [1][1][2][0][RTW89_CHILE][16] = 54, + [1][1][2][0][RTW89_QATAR][16] = 54, [1][1][2][0][RTW89_FCC][20] = 68, [1][1][2][0][RTW89_ETSI][20] = 54, [1][1][2][0][RTW89_MKK][20] = 66, @@ -31604,6 +35896,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][1][2][0][RTW89_ACMA][20] = 54, [1][1][2][0][RTW89_CN][20] = 127, [1][1][2][0][RTW89_UK][20] = 54, + [1][1][2][0][RTW89_MEXICO][20] = 68, + [1][1][2][0][RTW89_UKRAINE][20] = 42, + [1][1][2][0][RTW89_CHILE][20] = 66, + [1][1][2][0][RTW89_QATAR][20] = 54, [1][1][2][0][RTW89_FCC][24] = 68, [1][1][2][0][RTW89_ETSI][24] = 54, [1][1][2][0][RTW89_MKK][24] = 66, @@ -31612,6 +35908,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][1][2][0][RTW89_ACMA][24] = 127, [1][1][2][0][RTW89_CN][24] = 127, [1][1][2][0][RTW89_UK][24] = 54, + [1][1][2][0][RTW89_MEXICO][24] = 68, + [1][1][2][0][RTW89_UKRAINE][24] = 42, + [1][1][2][0][RTW89_CHILE][24] = 66, + [1][1][2][0][RTW89_QATAR][24] = 54, [1][1][2][0][RTW89_FCC][28] = 68, [1][1][2][0][RTW89_ETSI][28] = 54, [1][1][2][0][RTW89_MKK][28] = 66, @@ -31620,6 +35920,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][1][2][0][RTW89_ACMA][28] = 127, [1][1][2][0][RTW89_CN][28] = 127, [1][1][2][0][RTW89_UK][28] = 54, + [1][1][2][0][RTW89_MEXICO][28] = 68, + [1][1][2][0][RTW89_UKRAINE][28] = 42, + [1][1][2][0][RTW89_CHILE][28] = 54, + [1][1][2][0][RTW89_QATAR][28] = 54, [1][1][2][0][RTW89_FCC][32] = 56, [1][1][2][0][RTW89_ETSI][32] = 54, [1][1][2][0][RTW89_MKK][32] = 66, @@ -31628,6 +35932,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][1][2][0][RTW89_ACMA][32] = 54, [1][1][2][0][RTW89_CN][32] = 127, [1][1][2][0][RTW89_UK][32] = 54, + [1][1][2][0][RTW89_MEXICO][32] = 56, + [1][1][2][0][RTW89_UKRAINE][32] = 42, + [1][1][2][0][RTW89_CHILE][32] = 54, + [1][1][2][0][RTW89_QATAR][32] = 54, [1][1][2][0][RTW89_FCC][36] = 68, [1][1][2][0][RTW89_ETSI][36] = 127, [1][1][2][0][RTW89_MKK][36] = 66, @@ -31636,6 +35944,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][1][2][0][RTW89_ACMA][36] = 66, [1][1][2][0][RTW89_CN][36] = 127, [1][1][2][0][RTW89_UK][36] = 52, + [1][1][2][0][RTW89_MEXICO][36] = 68, + [1][1][2][0][RTW89_UKRAINE][36] = 127, + [1][1][2][0][RTW89_CHILE][36] = 66, + [1][1][2][0][RTW89_QATAR][36] = 127, [1][1][2][0][RTW89_FCC][39] = 68, [1][1][2][0][RTW89_ETSI][39] = 18, [1][1][2][0][RTW89_MKK][39] = 127, @@ -31644,6 +35956,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][1][2][0][RTW89_ACMA][39] = 66, [1][1][2][0][RTW89_CN][39] = 62, [1][1][2][0][RTW89_UK][39] = 52, + [1][1][2][0][RTW89_MEXICO][39] = 68, + [1][1][2][0][RTW89_UKRAINE][39] = 18, + [1][1][2][0][RTW89_CHILE][39] = 66, + [1][1][2][0][RTW89_QATAR][39] = 18, [1][1][2][0][RTW89_FCC][43] = 68, [1][1][2][0][RTW89_ETSI][43] = 18, [1][1][2][0][RTW89_MKK][43] = 127, @@ -31652,6 +35968,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][1][2][0][RTW89_ACMA][43] = 66, [1][1][2][0][RTW89_CN][43] = 66, [1][1][2][0][RTW89_UK][43] = 52, + [1][1][2][0][RTW89_MEXICO][43] = 68, + [1][1][2][0][RTW89_UKRAINE][43] = 18, + [1][1][2][0][RTW89_CHILE][43] = 66, + [1][1][2][0][RTW89_QATAR][43] = 18, [1][1][2][0][RTW89_FCC][47] = 62, [1][1][2][0][RTW89_ETSI][47] = 127, [1][1][2][0][RTW89_MKK][47] = 127, @@ -31660,6 +35980,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][1][2][0][RTW89_ACMA][47] = 127, [1][1][2][0][RTW89_CN][47] = 127, [1][1][2][0][RTW89_UK][47] = 127, + [1][1][2][0][RTW89_MEXICO][47] = 127, + [1][1][2][0][RTW89_UKRAINE][47] = 127, + [1][1][2][0][RTW89_CHILE][47] = 127, + [1][1][2][0][RTW89_QATAR][47] = 127, [1][1][2][0][RTW89_FCC][51] = 60, [1][1][2][0][RTW89_ETSI][51] = 127, [1][1][2][0][RTW89_MKK][51] = 127, @@ -31668,6 +35992,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][1][2][0][RTW89_ACMA][51] = 127, [1][1][2][0][RTW89_CN][51] = 127, [1][1][2][0][RTW89_UK][51] = 127, + [1][1][2][0][RTW89_MEXICO][51] = 127, + [1][1][2][0][RTW89_UKRAINE][51] = 127, + [1][1][2][0][RTW89_CHILE][51] = 127, + [1][1][2][0][RTW89_QATAR][51] = 127, [1][1][2][1][RTW89_FCC][1] = 54, [1][1][2][1][RTW89_ETSI][1] = 40, [1][1][2][1][RTW89_MKK][1] = 48, @@ -31676,6 +36004,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][1][2][1][RTW89_ACMA][1] = 40, [1][1][2][1][RTW89_CN][1] = 42, [1][1][2][1][RTW89_UK][1] = 40, + [1][1][2][1][RTW89_MEXICO][1] = 50, + [1][1][2][1][RTW89_UKRAINE][1] = 30, + [1][1][2][1][RTW89_CHILE][1] = 54, + [1][1][2][1][RTW89_QATAR][1] = 40, [1][1][2][1][RTW89_FCC][5] = 68, [1][1][2][1][RTW89_ETSI][5] = 40, [1][1][2][1][RTW89_MKK][5] = 52, @@ -31684,6 +36016,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][1][2][1][RTW89_ACMA][5] = 40, [1][1][2][1][RTW89_CN][5] = 42, [1][1][2][1][RTW89_UK][5] = 40, + [1][1][2][1][RTW89_MEXICO][5] = 50, + [1][1][2][1][RTW89_UKRAINE][5] = 30, + [1][1][2][1][RTW89_CHILE][5] = 60, + [1][1][2][1][RTW89_QATAR][5] = 40, [1][1][2][1][RTW89_FCC][9] = 68, [1][1][2][1][RTW89_ETSI][9] = 40, [1][1][2][1][RTW89_MKK][9] = 52, @@ -31692,6 +36028,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][1][2][1][RTW89_ACMA][9] = 40, [1][1][2][1][RTW89_CN][9] = 42, [1][1][2][1][RTW89_UK][9] = 40, + [1][1][2][1][RTW89_MEXICO][9] = 68, + [1][1][2][1][RTW89_UKRAINE][9] = 30, + [1][1][2][1][RTW89_CHILE][9] = 60, + [1][1][2][1][RTW89_QATAR][9] = 40, [1][1][2][1][RTW89_FCC][13] = 54, [1][1][2][1][RTW89_ETSI][13] = 40, [1][1][2][1][RTW89_MKK][13] = 52, @@ -31700,6 +36040,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][1][2][1][RTW89_ACMA][13] = 40, [1][1][2][1][RTW89_CN][13] = 42, [1][1][2][1][RTW89_UK][13] = 40, + [1][1][2][1][RTW89_MEXICO][13] = 54, + [1][1][2][1][RTW89_UKRAINE][13] = 30, + [1][1][2][1][RTW89_CHILE][13] = 54, + [1][1][2][1][RTW89_QATAR][13] = 40, [1][1][2][1][RTW89_FCC][16] = 56, [1][1][2][1][RTW89_ETSI][16] = 40, [1][1][2][1][RTW89_MKK][16] = 66, @@ -31708,6 +36052,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][1][2][1][RTW89_ACMA][16] = 40, [1][1][2][1][RTW89_CN][16] = 127, [1][1][2][1][RTW89_UK][16] = 40, + [1][1][2][1][RTW89_MEXICO][16] = 56, + [1][1][2][1][RTW89_UKRAINE][16] = 30, + [1][1][2][1][RTW89_CHILE][16] = 54, + [1][1][2][1][RTW89_QATAR][16] = 40, [1][1][2][1][RTW89_FCC][20] = 68, [1][1][2][1][RTW89_ETSI][20] = 40, [1][1][2][1][RTW89_MKK][20] = 66, @@ -31716,6 +36064,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][1][2][1][RTW89_ACMA][20] = 40, [1][1][2][1][RTW89_CN][20] = 127, [1][1][2][1][RTW89_UK][20] = 40, + [1][1][2][1][RTW89_MEXICO][20] = 68, + [1][1][2][1][RTW89_UKRAINE][20] = 30, + [1][1][2][1][RTW89_CHILE][20] = 60, + [1][1][2][1][RTW89_QATAR][20] = 40, [1][1][2][1][RTW89_FCC][24] = 68, [1][1][2][1][RTW89_ETSI][24] = 40, [1][1][2][1][RTW89_MKK][24] = 66, @@ -31724,6 +36076,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][1][2][1][RTW89_ACMA][24] = 127, [1][1][2][1][RTW89_CN][24] = 127, [1][1][2][1][RTW89_UK][24] = 40, + [1][1][2][1][RTW89_MEXICO][24] = 68, + [1][1][2][1][RTW89_UKRAINE][24] = 30, + [1][1][2][1][RTW89_CHILE][24] = 60, + [1][1][2][1][RTW89_QATAR][24] = 40, [1][1][2][1][RTW89_FCC][28] = 68, [1][1][2][1][RTW89_ETSI][28] = 40, [1][1][2][1][RTW89_MKK][28] = 66, @@ -31732,6 +36088,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][1][2][1][RTW89_ACMA][28] = 127, [1][1][2][1][RTW89_CN][28] = 127, [1][1][2][1][RTW89_UK][28] = 40, + [1][1][2][1][RTW89_MEXICO][28] = 68, + [1][1][2][1][RTW89_UKRAINE][28] = 30, + [1][1][2][1][RTW89_CHILE][28] = 54, + [1][1][2][1][RTW89_QATAR][28] = 40, [1][1][2][1][RTW89_FCC][32] = 56, [1][1][2][1][RTW89_ETSI][32] = 40, [1][1][2][1][RTW89_MKK][32] = 66, @@ -31740,6 +36100,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][1][2][1][RTW89_ACMA][32] = 40, [1][1][2][1][RTW89_CN][32] = 127, [1][1][2][1][RTW89_UK][32] = 40, + [1][1][2][1][RTW89_MEXICO][32] = 56, + [1][1][2][1][RTW89_UKRAINE][32] = 30, + [1][1][2][1][RTW89_CHILE][32] = 54, + [1][1][2][1][RTW89_QATAR][32] = 40, [1][1][2][1][RTW89_FCC][36] = 68, [1][1][2][1][RTW89_ETSI][36] = 127, [1][1][2][1][RTW89_MKK][36] = 66, @@ -31748,6 +36112,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][1][2][1][RTW89_ACMA][36] = 66, [1][1][2][1][RTW89_CN][36] = 127, [1][1][2][1][RTW89_UK][36] = 40, + [1][1][2][1][RTW89_MEXICO][36] = 68, + [1][1][2][1][RTW89_UKRAINE][36] = 127, + [1][1][2][1][RTW89_CHILE][36] = 66, + [1][1][2][1][RTW89_QATAR][36] = 127, [1][1][2][1][RTW89_FCC][39] = 68, [1][1][2][1][RTW89_ETSI][39] = 6, [1][1][2][1][RTW89_MKK][39] = 127, @@ -31756,6 +36124,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][1][2][1][RTW89_ACMA][39] = 66, [1][1][2][1][RTW89_CN][39] = 60, [1][1][2][1][RTW89_UK][39] = 40, + [1][1][2][1][RTW89_MEXICO][39] = 68, + [1][1][2][1][RTW89_UKRAINE][39] = 6, + [1][1][2][1][RTW89_CHILE][39] = 60, + [1][1][2][1][RTW89_QATAR][39] = 6, [1][1][2][1][RTW89_FCC][43] = 68, [1][1][2][1][RTW89_ETSI][43] = 6, [1][1][2][1][RTW89_MKK][43] = 127, @@ -31764,6 +36136,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][1][2][1][RTW89_ACMA][43] = 66, [1][1][2][1][RTW89_CN][43] = 52, [1][1][2][1][RTW89_UK][43] = 40, + [1][1][2][1][RTW89_MEXICO][43] = 68, + [1][1][2][1][RTW89_UKRAINE][43] = 6, + [1][1][2][1][RTW89_CHILE][43] = 60, + [1][1][2][1][RTW89_QATAR][43] = 6, [1][1][2][1][RTW89_FCC][47] = 62, [1][1][2][1][RTW89_ETSI][47] = 127, [1][1][2][1][RTW89_MKK][47] = 127, @@ -31772,6 +36148,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][1][2][1][RTW89_ACMA][47] = 127, [1][1][2][1][RTW89_CN][47] = 127, [1][1][2][1][RTW89_UK][47] = 127, + [1][1][2][1][RTW89_MEXICO][47] = 127, + [1][1][2][1][RTW89_UKRAINE][47] = 127, + [1][1][2][1][RTW89_CHILE][47] = 127, + [1][1][2][1][RTW89_QATAR][47] = 127, [1][1][2][1][RTW89_FCC][51] = 60, [1][1][2][1][RTW89_ETSI][51] = 127, [1][1][2][1][RTW89_MKK][51] = 127, @@ -31780,6 +36160,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][1][2][1][RTW89_ACMA][51] = 127, [1][1][2][1][RTW89_CN][51] = 127, [1][1][2][1][RTW89_UK][51] = 127, + [1][1][2][1][RTW89_MEXICO][51] = 127, + [1][1][2][1][RTW89_UKRAINE][51] = 127, + [1][1][2][1][RTW89_CHILE][51] = 127, + [1][1][2][1][RTW89_QATAR][51] = 127, [2][0][2][0][RTW89_FCC][3] = 58, [2][0][2][0][RTW89_ETSI][3] = 60, [2][0][2][0][RTW89_MKK][3] = 60, @@ -31788,6 +36172,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [2][0][2][0][RTW89_ACMA][3] = 60, [2][0][2][0][RTW89_CN][3] = 54, [2][0][2][0][RTW89_UK][3] = 60, + [2][0][2][0][RTW89_MEXICO][3] = 58, + [2][0][2][0][RTW89_UKRAINE][3] = 54, + [2][0][2][0][RTW89_CHILE][3] = 58, + [2][0][2][0][RTW89_QATAR][3] = 60, [2][0][2][0][RTW89_FCC][11] = 50, [2][0][2][0][RTW89_ETSI][11] = 60, [2][0][2][0][RTW89_MKK][11] = 60, @@ -31796,6 +36184,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [2][0][2][0][RTW89_ACMA][11] = 60, [2][0][2][0][RTW89_CN][11] = 54, [2][0][2][0][RTW89_UK][11] = 60, + [2][0][2][0][RTW89_MEXICO][11] = 50, + [2][0][2][0][RTW89_UKRAINE][11] = 54, + [2][0][2][0][RTW89_CHILE][11] = 50, + [2][0][2][0][RTW89_QATAR][11] = 60, [2][0][2][0][RTW89_FCC][18] = 60, [2][0][2][0][RTW89_ETSI][18] = 60, [2][0][2][0][RTW89_MKK][18] = 60, @@ -31804,6 +36196,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [2][0][2][0][RTW89_ACMA][18] = 60, [2][0][2][0][RTW89_CN][18] = 127, [2][0][2][0][RTW89_UK][18] = 60, + [2][0][2][0][RTW89_MEXICO][18] = 60, + [2][0][2][0][RTW89_UKRAINE][18] = 54, + [2][0][2][0][RTW89_CHILE][18] = 60, + [2][0][2][0][RTW89_QATAR][18] = 60, [2][0][2][0][RTW89_FCC][26] = 62, [2][0][2][0][RTW89_ETSI][26] = 60, [2][0][2][0][RTW89_MKK][26] = 60, @@ -31812,6 +36208,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [2][0][2][0][RTW89_ACMA][26] = 127, [2][0][2][0][RTW89_CN][26] = 127, [2][0][2][0][RTW89_UK][26] = 60, + [2][0][2][0][RTW89_MEXICO][26] = 62, + [2][0][2][0][RTW89_UKRAINE][26] = 54, + [2][0][2][0][RTW89_CHILE][26] = 60, + [2][0][2][0][RTW89_QATAR][26] = 60, [2][0][2][0][RTW89_FCC][34] = 62, [2][0][2][0][RTW89_ETSI][34] = 127, [2][0][2][0][RTW89_MKK][34] = 60, @@ -31820,6 +36220,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [2][0][2][0][RTW89_ACMA][34] = 60, [2][0][2][0][RTW89_CN][34] = 127, [2][0][2][0][RTW89_UK][34] = 60, + [2][0][2][0][RTW89_MEXICO][34] = 62, + [2][0][2][0][RTW89_UKRAINE][34] = 127, + [2][0][2][0][RTW89_CHILE][34] = 60, + [2][0][2][0][RTW89_QATAR][34] = 127, [2][0][2][0][RTW89_FCC][41] = 62, [2][0][2][0][RTW89_ETSI][41] = 30, [2][0][2][0][RTW89_MKK][41] = 127, @@ -31828,6 +36232,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [2][0][2][0][RTW89_ACMA][41] = 60, [2][0][2][0][RTW89_CN][41] = 62, [2][0][2][0][RTW89_UK][41] = 60, + [2][0][2][0][RTW89_MEXICO][41] = 62, + [2][0][2][0][RTW89_UKRAINE][41] = 30, + [2][0][2][0][RTW89_CHILE][41] = 60, + [2][0][2][0][RTW89_QATAR][41] = 30, [2][0][2][0][RTW89_FCC][49] = 62, [2][0][2][0][RTW89_ETSI][49] = 127, [2][0][2][0][RTW89_MKK][49] = 127, @@ -31836,6 +36244,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [2][0][2][0][RTW89_ACMA][49] = 127, [2][0][2][0][RTW89_CN][49] = 127, [2][0][2][0][RTW89_UK][49] = 127, + [2][0][2][0][RTW89_MEXICO][49] = 127, + [2][0][2][0][RTW89_UKRAINE][49] = 127, + [2][0][2][0][RTW89_CHILE][49] = 127, + [2][0][2][0][RTW89_QATAR][49] = 127, [2][1][2][0][RTW89_FCC][3] = 48, [2][1][2][0][RTW89_ETSI][3] = 54, [2][1][2][0][RTW89_MKK][3] = 56, @@ -31844,6 +36256,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [2][1][2][0][RTW89_ACMA][3] = 54, [2][1][2][0][RTW89_CN][3] = 52, [2][1][2][0][RTW89_UK][3] = 54, + [2][1][2][0][RTW89_MEXICO][3] = 48, + [2][1][2][0][RTW89_UKRAINE][3] = 42, + [2][1][2][0][RTW89_CHILE][3] = 46, + [2][1][2][0][RTW89_QATAR][3] = 54, [2][1][2][0][RTW89_FCC][11] = 38, [2][1][2][0][RTW89_ETSI][11] = 54, [2][1][2][0][RTW89_MKK][11] = 54, @@ -31852,6 +36268,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [2][1][2][0][RTW89_ACMA][11] = 54, [2][1][2][0][RTW89_CN][11] = 52, [2][1][2][0][RTW89_UK][11] = 54, + [2][1][2][0][RTW89_MEXICO][11] = 38, + [2][1][2][0][RTW89_UKRAINE][11] = 42, + [2][1][2][0][RTW89_CHILE][11] = 38, + [2][1][2][0][RTW89_QATAR][11] = 54, [2][1][2][0][RTW89_FCC][18] = 50, [2][1][2][0][RTW89_ETSI][18] = 54, [2][1][2][0][RTW89_MKK][18] = 60, @@ -31860,6 +36280,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [2][1][2][0][RTW89_ACMA][18] = 54, [2][1][2][0][RTW89_CN][18] = 127, [2][1][2][0][RTW89_UK][18] = 54, + [2][1][2][0][RTW89_MEXICO][18] = 50, + [2][1][2][0][RTW89_UKRAINE][18] = 42, + [2][1][2][0][RTW89_CHILE][18] = 50, + [2][1][2][0][RTW89_QATAR][18] = 54, [2][1][2][0][RTW89_FCC][26] = 52, [2][1][2][0][RTW89_ETSI][26] = 54, [2][1][2][0][RTW89_MKK][26] = 56, @@ -31868,6 +36292,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [2][1][2][0][RTW89_ACMA][26] = 127, [2][1][2][0][RTW89_CN][26] = 127, [2][1][2][0][RTW89_UK][26] = 54, + [2][1][2][0][RTW89_MEXICO][26] = 52, + [2][1][2][0][RTW89_UKRAINE][26] = 42, + [2][1][2][0][RTW89_CHILE][26] = 52, + [2][1][2][0][RTW89_QATAR][26] = 54, [2][1][2][0][RTW89_FCC][34] = 62, [2][1][2][0][RTW89_ETSI][34] = 127, [2][1][2][0][RTW89_MKK][34] = 60, @@ -31876,6 +36304,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [2][1][2][0][RTW89_ACMA][34] = 60, [2][1][2][0][RTW89_CN][34] = 127, [2][1][2][0][RTW89_UK][34] = 52, + [2][1][2][0][RTW89_MEXICO][34] = 62, + [2][1][2][0][RTW89_UKRAINE][34] = 127, + [2][1][2][0][RTW89_CHILE][34] = 60, + [2][1][2][0][RTW89_QATAR][34] = 127, [2][1][2][0][RTW89_FCC][41] = 60, [2][1][2][0][RTW89_ETSI][41] = 18, [2][1][2][0][RTW89_MKK][41] = 127, @@ -31884,6 +36316,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [2][1][2][0][RTW89_ACMA][41] = 58, [2][1][2][0][RTW89_CN][41] = 62, [2][1][2][0][RTW89_UK][41] = 52, + [2][1][2][0][RTW89_MEXICO][41] = 60, + [2][1][2][0][RTW89_UKRAINE][41] = 18, + [2][1][2][0][RTW89_CHILE][41] = 58, + [2][1][2][0][RTW89_QATAR][41] = 18, [2][1][2][0][RTW89_FCC][49] = 62, [2][1][2][0][RTW89_ETSI][49] = 127, [2][1][2][0][RTW89_MKK][49] = 127, @@ -31892,6 +36328,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [2][1][2][0][RTW89_ACMA][49] = 127, [2][1][2][0][RTW89_CN][49] = 127, [2][1][2][0][RTW89_UK][49] = 127, + [2][1][2][0][RTW89_MEXICO][49] = 127, + [2][1][2][0][RTW89_UKRAINE][49] = 127, + [2][1][2][0][RTW89_CHILE][49] = 127, + [2][1][2][0][RTW89_QATAR][49] = 127, [2][1][2][1][RTW89_FCC][3] = 48, [2][1][2][1][RTW89_ETSI][3] = 40, [2][1][2][1][RTW89_MKK][3] = 56, @@ -31900,6 +36340,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [2][1][2][1][RTW89_ACMA][3] = 40, [2][1][2][1][RTW89_CN][3] = 42, [2][1][2][1][RTW89_UK][3] = 40, + [2][1][2][1][RTW89_MEXICO][3] = 48, + [2][1][2][1][RTW89_UKRAINE][3] = 30, + [2][1][2][1][RTW89_CHILE][3] = 46, + [2][1][2][1][RTW89_QATAR][3] = 40, [2][1][2][1][RTW89_FCC][11] = 38, [2][1][2][1][RTW89_ETSI][11] = 40, [2][1][2][1][RTW89_MKK][11] = 54, @@ -31908,6 +36352,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [2][1][2][1][RTW89_ACMA][11] = 40, [2][1][2][1][RTW89_CN][11] = 42, [2][1][2][1][RTW89_UK][11] = 40, + [2][1][2][1][RTW89_MEXICO][11] = 38, + [2][1][2][1][RTW89_UKRAINE][11] = 30, + [2][1][2][1][RTW89_CHILE][11] = 38, + [2][1][2][1][RTW89_QATAR][11] = 40, [2][1][2][1][RTW89_FCC][18] = 50, [2][1][2][1][RTW89_ETSI][18] = 40, [2][1][2][1][RTW89_MKK][18] = 60, @@ -31916,6 +36364,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [2][1][2][1][RTW89_ACMA][18] = 40, [2][1][2][1][RTW89_CN][18] = 127, [2][1][2][1][RTW89_UK][18] = 40, + [2][1][2][1][RTW89_MEXICO][18] = 50, + [2][1][2][1][RTW89_UKRAINE][18] = 30, + [2][1][2][1][RTW89_CHILE][18] = 50, + [2][1][2][1][RTW89_QATAR][18] = 40, [2][1][2][1][RTW89_FCC][26] = 52, [2][1][2][1][RTW89_ETSI][26] = 42, [2][1][2][1][RTW89_MKK][26] = 56, @@ -31924,6 +36376,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [2][1][2][1][RTW89_ACMA][26] = 127, [2][1][2][1][RTW89_CN][26] = 127, [2][1][2][1][RTW89_UK][26] = 42, + [2][1][2][1][RTW89_MEXICO][26] = 52, + [2][1][2][1][RTW89_UKRAINE][26] = 30, + [2][1][2][1][RTW89_CHILE][26] = 52, + [2][1][2][1][RTW89_QATAR][26] = 42, [2][1][2][1][RTW89_FCC][34] = 62, [2][1][2][1][RTW89_ETSI][34] = 127, [2][1][2][1][RTW89_MKK][34] = 60, @@ -31932,6 +36388,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [2][1][2][1][RTW89_ACMA][34] = 60, [2][1][2][1][RTW89_CN][34] = 127, [2][1][2][1][RTW89_UK][34] = 40, + [2][1][2][1][RTW89_MEXICO][34] = 62, + [2][1][2][1][RTW89_UKRAINE][34] = 127, + [2][1][2][1][RTW89_CHILE][34] = 60, + [2][1][2][1][RTW89_QATAR][34] = 127, [2][1][2][1][RTW89_FCC][41] = 60, [2][1][2][1][RTW89_ETSI][41] = 6, [2][1][2][1][RTW89_MKK][41] = 127, @@ -31940,6 +36400,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [2][1][2][1][RTW89_ACMA][41] = 58, [2][1][2][1][RTW89_CN][41] = 40, [2][1][2][1][RTW89_UK][41] = 40, + [2][1][2][1][RTW89_MEXICO][41] = 60, + [2][1][2][1][RTW89_UKRAINE][41] = 6, + [2][1][2][1][RTW89_CHILE][41] = 58, + [2][1][2][1][RTW89_QATAR][41] = 6, [2][1][2][1][RTW89_FCC][49] = 62, [2][1][2][1][RTW89_ETSI][49] = 127, [2][1][2][1][RTW89_MKK][49] = 127, @@ -31948,6 +36412,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [2][1][2][1][RTW89_ACMA][49] = 127, [2][1][2][1][RTW89_CN][49] = 127, [2][1][2][1][RTW89_UK][49] = 127, + [2][1][2][1][RTW89_MEXICO][49] = 127, + [2][1][2][1][RTW89_UKRAINE][49] = 127, + [2][1][2][1][RTW89_CHILE][49] = 127, + [2][1][2][1][RTW89_QATAR][49] = 127, [3][0][2][0][RTW89_FCC][7] = 40, [3][0][2][0][RTW89_ETSI][7] = 50, [3][0][2][0][RTW89_MKK][7] = 50, @@ -31956,6 +36424,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [3][0][2][0][RTW89_ACMA][7] = 127, [3][0][2][0][RTW89_CN][7] = 66, [3][0][2][0][RTW89_UK][7] = 127, + [3][0][2][0][RTW89_MEXICO][7] = 127, + [3][0][2][0][RTW89_UKRAINE][7] = 50, + [3][0][2][0][RTW89_CHILE][7] = 40, + [3][0][2][0][RTW89_QATAR][7] = 50, [3][0][2][0][RTW89_FCC][22] = 42, [3][0][2][0][RTW89_ETSI][22] = 50, [3][0][2][0][RTW89_MKK][22] = 50, @@ -31964,6 +36436,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [3][0][2][0][RTW89_ACMA][22] = 127, [3][0][2][0][RTW89_CN][22] = 66, [3][0][2][0][RTW89_UK][22] = 127, + [3][0][2][0][RTW89_MEXICO][22] = 127, + [3][0][2][0][RTW89_UKRAINE][22] = 50, + [3][0][2][0][RTW89_CHILE][22] = 42, + [3][0][2][0][RTW89_QATAR][22] = 50, [3][0][2][0][RTW89_FCC][45] = 52, [3][0][2][0][RTW89_ETSI][45] = 127, [3][0][2][0][RTW89_MKK][45] = 127, @@ -31972,6 +36448,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [3][0][2][0][RTW89_ACMA][45] = 127, [3][0][2][0][RTW89_CN][45] = 127, [3][0][2][0][RTW89_UK][45] = 127, + [3][0][2][0][RTW89_MEXICO][45] = 127, + [3][0][2][0][RTW89_UKRAINE][45] = 127, + [3][0][2][0][RTW89_CHILE][45] = 127, + [3][0][2][0][RTW89_QATAR][45] = 127, [3][1][2][0][RTW89_FCC][7] = 32, [3][1][2][0][RTW89_ETSI][7] = 50, [3][1][2][0][RTW89_MKK][7] = 36, @@ -31980,6 +36460,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [3][1][2][0][RTW89_ACMA][7] = 127, [3][1][2][0][RTW89_CN][7] = 54, [3][1][2][0][RTW89_UK][7] = 127, + [3][1][2][0][RTW89_MEXICO][7] = 127, + [3][1][2][0][RTW89_UKRAINE][7] = 50, + [3][1][2][0][RTW89_CHILE][7] = 32, + [3][1][2][0][RTW89_QATAR][7] = 50, [3][1][2][0][RTW89_FCC][22] = 36, [3][1][2][0][RTW89_ETSI][22] = 50, [3][1][2][0][RTW89_MKK][22] = 48, @@ -31988,6 +36472,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [3][1][2][0][RTW89_ACMA][22] = 127, [3][1][2][0][RTW89_CN][22] = 54, [3][1][2][0][RTW89_UK][22] = 127, + [3][1][2][0][RTW89_MEXICO][22] = 127, + [3][1][2][0][RTW89_UKRAINE][22] = 50, + [3][1][2][0][RTW89_CHILE][22] = 36, + [3][1][2][0][RTW89_QATAR][22] = 50, [3][1][2][0][RTW89_FCC][45] = 46, [3][1][2][0][RTW89_ETSI][45] = 127, [3][1][2][0][RTW89_MKK][45] = 127, @@ -31996,6 +36484,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [3][1][2][0][RTW89_ACMA][45] = 127, [3][1][2][0][RTW89_CN][45] = 127, [3][1][2][0][RTW89_UK][45] = 127, + [3][1][2][0][RTW89_MEXICO][45] = 127, + [3][1][2][0][RTW89_UKRAINE][45] = 127, + [3][1][2][0][RTW89_CHILE][45] = 127, + [3][1][2][0][RTW89_QATAR][45] = 127, [3][1][2][1][RTW89_FCC][7] = 32, [3][1][2][1][RTW89_ETSI][7] = 42, [3][1][2][1][RTW89_MKK][7] = 36, @@ -32004,6 +36496,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [3][1][2][1][RTW89_ACMA][7] = 127, [3][1][2][1][RTW89_CN][7] = 42, [3][1][2][1][RTW89_UK][7] = 127, + [3][1][2][1][RTW89_MEXICO][7] = 127, + [3][1][2][1][RTW89_UKRAINE][7] = 42, + [3][1][2][1][RTW89_CHILE][7] = 32, + [3][1][2][1][RTW89_QATAR][7] = 42, [3][1][2][1][RTW89_FCC][22] = 36, [3][1][2][1][RTW89_ETSI][22] = 42, [3][1][2][1][RTW89_MKK][22] = 48, @@ -32012,6 +36508,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [3][1][2][1][RTW89_ACMA][22] = 127, [3][1][2][1][RTW89_CN][22] = 42, [3][1][2][1][RTW89_UK][22] = 127, + [3][1][2][1][RTW89_MEXICO][22] = 127, + [3][1][2][1][RTW89_UKRAINE][22] = 42, + [3][1][2][1][RTW89_CHILE][22] = 36, + [3][1][2][1][RTW89_QATAR][22] = 42, [3][1][2][1][RTW89_FCC][45] = 46, [3][1][2][1][RTW89_ETSI][45] = 127, [3][1][2][1][RTW89_MKK][45] = 127, @@ -32020,1964 +36520,9289 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [3][1][2][1][RTW89_ACMA][45] = 127, [3][1][2][1][RTW89_CN][45] = 127, [3][1][2][1][RTW89_UK][45] = 127, + [3][1][2][1][RTW89_MEXICO][45] = 127, + [3][1][2][1][RTW89_UKRAINE][45] = 127, + [3][1][2][1][RTW89_CHILE][45] = 127, + [3][1][2][1][RTW89_QATAR][45] = 127, }; static const s8 rtw89_8852c_txpwr_lmt_6g[RTW89_6G_BW_NUM][RTW89_NTX_NUM] [RTW89_RS_LMT_NUM][RTW89_BF_NUM] - [RTW89_REGD_NUM][RTW89_6G_CH_NUM] = { - [0][0][1][0][RTW89_WW][0] = 24, - [0][0][1][0][RTW89_WW][2] = 22, - [0][0][1][0][RTW89_WW][4] = 22, - [0][0][1][0][RTW89_WW][6] = 22, - [0][0][1][0][RTW89_WW][8] = 22, - [0][0][1][0][RTW89_WW][10] = 22, - [0][0][1][0][RTW89_WW][12] = 22, - [0][0][1][0][RTW89_WW][14] = 22, - [0][0][1][0][RTW89_WW][15] = 22, - [0][0][1][0][RTW89_WW][17] = 22, - [0][0][1][0][RTW89_WW][19] = 22, - [0][0][1][0][RTW89_WW][21] = 22, - [0][0][1][0][RTW89_WW][23] = 22, - [0][0][1][0][RTW89_WW][25] = 22, - [0][0][1][0][RTW89_WW][27] = 22, - [0][0][1][0][RTW89_WW][29] = 22, - [0][0][1][0][RTW89_WW][30] = 22, - [0][0][1][0][RTW89_WW][32] = 22, - [0][0][1][0][RTW89_WW][34] = 22, - [0][0][1][0][RTW89_WW][36] = 22, - [0][0][1][0][RTW89_WW][38] = 22, - [0][0][1][0][RTW89_WW][40] = 22, - [0][0][1][0][RTW89_WW][42] = 22, - [0][0][1][0][RTW89_WW][44] = 22, - [0][0][1][0][RTW89_WW][45] = 22, - [0][0][1][0][RTW89_WW][47] = 22, - [0][0][1][0][RTW89_WW][49] = 24, - [0][0][1][0][RTW89_WW][51] = 22, - [0][0][1][0][RTW89_WW][53] = 22, - [0][0][1][0][RTW89_WW][55] = 22, - [0][0][1][0][RTW89_WW][57] = 22, - [0][0][1][0][RTW89_WW][59] = 22, - [0][0][1][0][RTW89_WW][60] = 22, - [0][0][1][0][RTW89_WW][62] = 22, - [0][0][1][0][RTW89_WW][64] = 22, - [0][0][1][0][RTW89_WW][66] = 22, - [0][0][1][0][RTW89_WW][68] = 22, - [0][0][1][0][RTW89_WW][70] = 24, - [0][0][1][0][RTW89_WW][72] = 22, - [0][0][1][0][RTW89_WW][74] = 22, - [0][0][1][0][RTW89_WW][75] = 22, - [0][0][1][0][RTW89_WW][77] = 22, - [0][0][1][0][RTW89_WW][79] = 22, - [0][0][1][0][RTW89_WW][81] = 22, - [0][0][1][0][RTW89_WW][83] = 22, - [0][0][1][0][RTW89_WW][85] = 22, - [0][0][1][0][RTW89_WW][87] = 22, - [0][0][1][0][RTW89_WW][89] = 22, - [0][0][1][0][RTW89_WW][90] = 22, - [0][0][1][0][RTW89_WW][92] = 22, - [0][0][1][0][RTW89_WW][94] = 22, - [0][0][1][0][RTW89_WW][96] = 22, - [0][0][1][0][RTW89_WW][98] = 22, - [0][0][1][0][RTW89_WW][100] = 22, - [0][0][1][0][RTW89_WW][102] = 22, - [0][0][1][0][RTW89_WW][104] = 22, - [0][0][1][0][RTW89_WW][105] = 22, - [0][0][1][0][RTW89_WW][107] = 24, - [0][0][1][0][RTW89_WW][109] = 24, - [0][0][1][0][RTW89_WW][111] = 0, - [0][0][1][0][RTW89_WW][113] = 0, - [0][0][1][0][RTW89_WW][115] = 0, - [0][0][1][0][RTW89_WW][117] = 0, - [0][0][1][0][RTW89_WW][119] = 0, - [0][1][1][0][RTW89_WW][0] = -2, - [0][1][1][0][RTW89_WW][2] = -4, - [0][1][1][0][RTW89_WW][4] = -4, - [0][1][1][0][RTW89_WW][6] = -4, - [0][1][1][0][RTW89_WW][8] = -4, - [0][1][1][0][RTW89_WW][10] = -4, - [0][1][1][0][RTW89_WW][12] = -4, - [0][1][1][0][RTW89_WW][14] = -4, - [0][1][1][0][RTW89_WW][15] = -4, - [0][1][1][0][RTW89_WW][17] = -4, - [0][1][1][0][RTW89_WW][19] = -4, - [0][1][1][0][RTW89_WW][21] = -4, - [0][1][1][0][RTW89_WW][23] = -4, - [0][1][1][0][RTW89_WW][25] = -4, - [0][1][1][0][RTW89_WW][27] = -4, - [0][1][1][0][RTW89_WW][29] = -4, - [0][1][1][0][RTW89_WW][30] = -4, - [0][1][1][0][RTW89_WW][32] = -4, - [0][1][1][0][RTW89_WW][34] = -4, - [0][1][1][0][RTW89_WW][36] = -4, - [0][1][1][0][RTW89_WW][38] = -4, - [0][1][1][0][RTW89_WW][40] = -4, - [0][1][1][0][RTW89_WW][42] = -4, - [0][1][1][0][RTW89_WW][44] = -2, - [0][1][1][0][RTW89_WW][45] = -2, - [0][1][1][0][RTW89_WW][47] = -2, - [0][1][1][0][RTW89_WW][49] = -2, - [0][1][1][0][RTW89_WW][51] = -2, - [0][1][1][0][RTW89_WW][53] = -2, - [0][1][1][0][RTW89_WW][55] = -2, - [0][1][1][0][RTW89_WW][57] = -2, - [0][1][1][0][RTW89_WW][59] = -2, - [0][1][1][0][RTW89_WW][60] = -2, - [0][1][1][0][RTW89_WW][62] = -2, - [0][1][1][0][RTW89_WW][64] = -2, - [0][1][1][0][RTW89_WW][66] = -2, - [0][1][1][0][RTW89_WW][68] = -2, - [0][1][1][0][RTW89_WW][70] = -2, - [0][1][1][0][RTW89_WW][72] = -2, - [0][1][1][0][RTW89_WW][74] = -2, - [0][1][1][0][RTW89_WW][75] = -2, - [0][1][1][0][RTW89_WW][77] = -2, - [0][1][1][0][RTW89_WW][79] = -2, - [0][1][1][0][RTW89_WW][81] = -2, - [0][1][1][0][RTW89_WW][83] = -2, - [0][1][1][0][RTW89_WW][85] = -2, - [0][1][1][0][RTW89_WW][87] = -2, - [0][1][1][0][RTW89_WW][89] = -2, - [0][1][1][0][RTW89_WW][90] = -2, - [0][1][1][0][RTW89_WW][92] = -2, - [0][1][1][0][RTW89_WW][94] = -2, - [0][1][1][0][RTW89_WW][96] = -2, - [0][1][1][0][RTW89_WW][98] = -2, - [0][1][1][0][RTW89_WW][100] = -2, - [0][1][1][0][RTW89_WW][102] = -2, - [0][1][1][0][RTW89_WW][104] = -2, - [0][1][1][0][RTW89_WW][105] = -2, - [0][1][1][0][RTW89_WW][107] = 1, - [0][1][1][0][RTW89_WW][109] = 1, - [0][1][1][0][RTW89_WW][111] = 0, - [0][1][1][0][RTW89_WW][113] = 0, - [0][1][1][0][RTW89_WW][115] = 0, - [0][1][1][0][RTW89_WW][117] = 0, - [0][1][1][0][RTW89_WW][119] = 0, - [0][0][2][0][RTW89_WW][0] = 24, - [0][0][2][0][RTW89_WW][2] = 22, - [0][0][2][0][RTW89_WW][4] = 22, - [0][0][2][0][RTW89_WW][6] = 22, - [0][0][2][0][RTW89_WW][8] = 22, - [0][0][2][0][RTW89_WW][10] = 22, - [0][0][2][0][RTW89_WW][12] = 22, - [0][0][2][0][RTW89_WW][14] = 22, - [0][0][2][0][RTW89_WW][15] = 22, - [0][0][2][0][RTW89_WW][17] = 22, - [0][0][2][0][RTW89_WW][19] = 22, - [0][0][2][0][RTW89_WW][21] = 22, - [0][0][2][0][RTW89_WW][23] = 22, - [0][0][2][0][RTW89_WW][25] = 22, - [0][0][2][0][RTW89_WW][27] = 22, - [0][0][2][0][RTW89_WW][29] = 22, - [0][0][2][0][RTW89_WW][30] = 22, - [0][0][2][0][RTW89_WW][32] = 22, - [0][0][2][0][RTW89_WW][34] = 22, - [0][0][2][0][RTW89_WW][36] = 22, - [0][0][2][0][RTW89_WW][38] = 22, - [0][0][2][0][RTW89_WW][40] = 22, - [0][0][2][0][RTW89_WW][42] = 22, - [0][0][2][0][RTW89_WW][44] = 22, - [0][0][2][0][RTW89_WW][45] = 22, - [0][0][2][0][RTW89_WW][47] = 22, - [0][0][2][0][RTW89_WW][49] = 24, - [0][0][2][0][RTW89_WW][51] = 22, - [0][0][2][0][RTW89_WW][53] = 22, - [0][0][2][0][RTW89_WW][55] = 22, - [0][0][2][0][RTW89_WW][57] = 22, - [0][0][2][0][RTW89_WW][59] = 22, - [0][0][2][0][RTW89_WW][60] = 22, - [0][0][2][0][RTW89_WW][62] = 22, - [0][0][2][0][RTW89_WW][64] = 22, - [0][0][2][0][RTW89_WW][66] = 22, - [0][0][2][0][RTW89_WW][68] = 22, - [0][0][2][0][RTW89_WW][70] = 24, - [0][0][2][0][RTW89_WW][72] = 22, - [0][0][2][0][RTW89_WW][74] = 22, - [0][0][2][0][RTW89_WW][75] = 22, - [0][0][2][0][RTW89_WW][77] = 22, - [0][0][2][0][RTW89_WW][79] = 22, - [0][0][2][0][RTW89_WW][81] = 22, - [0][0][2][0][RTW89_WW][83] = 22, - [0][0][2][0][RTW89_WW][85] = 22, - [0][0][2][0][RTW89_WW][87] = 22, - [0][0][2][0][RTW89_WW][89] = 22, - [0][0][2][0][RTW89_WW][90] = 22, - [0][0][2][0][RTW89_WW][92] = 22, - [0][0][2][0][RTW89_WW][94] = 22, - [0][0][2][0][RTW89_WW][96] = 22, - [0][0][2][0][RTW89_WW][98] = 22, - [0][0][2][0][RTW89_WW][100] = 22, - [0][0][2][0][RTW89_WW][102] = 22, - [0][0][2][0][RTW89_WW][104] = 22, - [0][0][2][0][RTW89_WW][105] = 22, - [0][0][2][0][RTW89_WW][107] = 24, - [0][0][2][0][RTW89_WW][109] = 24, - [0][0][2][0][RTW89_WW][111] = 0, - [0][0][2][0][RTW89_WW][113] = 0, - [0][0][2][0][RTW89_WW][115] = 0, - [0][0][2][0][RTW89_WW][117] = 0, - [0][0][2][0][RTW89_WW][119] = 0, - [0][1][2][0][RTW89_WW][0] = -2, - [0][1][2][0][RTW89_WW][2] = -4, - [0][1][2][0][RTW89_WW][4] = -4, - [0][1][2][0][RTW89_WW][6] = -4, - [0][1][2][0][RTW89_WW][8] = -4, - [0][1][2][0][RTW89_WW][10] = -4, - [0][1][2][0][RTW89_WW][12] = -4, - [0][1][2][0][RTW89_WW][14] = -4, - [0][1][2][0][RTW89_WW][15] = -4, - [0][1][2][0][RTW89_WW][17] = -4, - [0][1][2][0][RTW89_WW][19] = -4, - [0][1][2][0][RTW89_WW][21] = -4, - [0][1][2][0][RTW89_WW][23] = -4, - [0][1][2][0][RTW89_WW][25] = -4, - [0][1][2][0][RTW89_WW][27] = -4, - [0][1][2][0][RTW89_WW][29] = -4, - [0][1][2][0][RTW89_WW][30] = -4, - [0][1][2][0][RTW89_WW][32] = -4, - [0][1][2][0][RTW89_WW][34] = -4, - [0][1][2][0][RTW89_WW][36] = -4, - [0][1][2][0][RTW89_WW][38] = -4, - [0][1][2][0][RTW89_WW][40] = -4, - [0][1][2][0][RTW89_WW][42] = -4, - [0][1][2][0][RTW89_WW][44] = -2, - [0][1][2][0][RTW89_WW][45] = -2, - [0][1][2][0][RTW89_WW][47] = -2, - [0][1][2][0][RTW89_WW][49] = -2, - [0][1][2][0][RTW89_WW][51] = -2, - [0][1][2][0][RTW89_WW][53] = -2, - [0][1][2][0][RTW89_WW][55] = -2, - [0][1][2][0][RTW89_WW][57] = -2, - [0][1][2][0][RTW89_WW][59] = -2, - [0][1][2][0][RTW89_WW][60] = -2, - [0][1][2][0][RTW89_WW][62] = -2, - [0][1][2][0][RTW89_WW][64] = -2, - [0][1][2][0][RTW89_WW][66] = -2, - [0][1][2][0][RTW89_WW][68] = -2, - [0][1][2][0][RTW89_WW][70] = -2, - [0][1][2][0][RTW89_WW][72] = -2, - [0][1][2][0][RTW89_WW][74] = -2, - [0][1][2][0][RTW89_WW][75] = -2, - [0][1][2][0][RTW89_WW][77] = -2, - [0][1][2][0][RTW89_WW][79] = -2, - [0][1][2][0][RTW89_WW][81] = -2, - [0][1][2][0][RTW89_WW][83] = -2, - [0][1][2][0][RTW89_WW][85] = -2, - [0][1][2][0][RTW89_WW][87] = -2, - [0][1][2][0][RTW89_WW][89] = -2, - [0][1][2][0][RTW89_WW][90] = -2, - [0][1][2][0][RTW89_WW][92] = -2, - [0][1][2][0][RTW89_WW][94] = -2, - [0][1][2][0][RTW89_WW][96] = -2, - [0][1][2][0][RTW89_WW][98] = -2, - [0][1][2][0][RTW89_WW][100] = -2, - [0][1][2][0][RTW89_WW][102] = -2, - [0][1][2][0][RTW89_WW][104] = -2, - [0][1][2][0][RTW89_WW][105] = -2, - [0][1][2][0][RTW89_WW][107] = 1, - [0][1][2][0][RTW89_WW][109] = 1, - [0][1][2][0][RTW89_WW][111] = 0, - [0][1][2][0][RTW89_WW][113] = 0, - [0][1][2][0][RTW89_WW][115] = 0, - [0][1][2][0][RTW89_WW][117] = 0, - [0][1][2][0][RTW89_WW][119] = 0, - [0][1][2][1][RTW89_WW][0] = -2, - [0][1][2][1][RTW89_WW][2] = -4, - [0][1][2][1][RTW89_WW][4] = -4, - [0][1][2][1][RTW89_WW][6] = -4, - [0][1][2][1][RTW89_WW][8] = -4, - [0][1][2][1][RTW89_WW][10] = -4, - [0][1][2][1][RTW89_WW][12] = -4, - [0][1][2][1][RTW89_WW][14] = -4, - [0][1][2][1][RTW89_WW][15] = -4, - [0][1][2][1][RTW89_WW][17] = -4, - [0][1][2][1][RTW89_WW][19] = -4, - [0][1][2][1][RTW89_WW][21] = -4, - [0][1][2][1][RTW89_WW][23] = -4, - [0][1][2][1][RTW89_WW][25] = -4, - [0][1][2][1][RTW89_WW][27] = -4, - [0][1][2][1][RTW89_WW][29] = -4, - [0][1][2][1][RTW89_WW][30] = -4, - [0][1][2][1][RTW89_WW][32] = -4, - [0][1][2][1][RTW89_WW][34] = -4, - [0][1][2][1][RTW89_WW][36] = -4, - [0][1][2][1][RTW89_WW][38] = -4, - [0][1][2][1][RTW89_WW][40] = -4, - [0][1][2][1][RTW89_WW][42] = -4, - [0][1][2][1][RTW89_WW][44] = -2, - [0][1][2][1][RTW89_WW][45] = -2, - [0][1][2][1][RTW89_WW][47] = -2, - [0][1][2][1][RTW89_WW][49] = -2, - [0][1][2][1][RTW89_WW][51] = -2, - [0][1][2][1][RTW89_WW][53] = -2, - [0][1][2][1][RTW89_WW][55] = -2, - [0][1][2][1][RTW89_WW][57] = -2, - [0][1][2][1][RTW89_WW][59] = -2, - [0][1][2][1][RTW89_WW][60] = -2, - [0][1][2][1][RTW89_WW][62] = -2, - [0][1][2][1][RTW89_WW][64] = -2, - [0][1][2][1][RTW89_WW][66] = -2, - [0][1][2][1][RTW89_WW][68] = -2, - [0][1][2][1][RTW89_WW][70] = -2, - [0][1][2][1][RTW89_WW][72] = -2, - [0][1][2][1][RTW89_WW][74] = -2, - [0][1][2][1][RTW89_WW][75] = -2, - [0][1][2][1][RTW89_WW][77] = -2, - [0][1][2][1][RTW89_WW][79] = -2, - [0][1][2][1][RTW89_WW][81] = -2, - [0][1][2][1][RTW89_WW][83] = -2, - [0][1][2][1][RTW89_WW][85] = -2, - [0][1][2][1][RTW89_WW][87] = -2, - [0][1][2][1][RTW89_WW][89] = -2, - [0][1][2][1][RTW89_WW][90] = -2, - [0][1][2][1][RTW89_WW][92] = -2, - [0][1][2][1][RTW89_WW][94] = -2, - [0][1][2][1][RTW89_WW][96] = -2, - [0][1][2][1][RTW89_WW][98] = -2, - [0][1][2][1][RTW89_WW][100] = -2, - [0][1][2][1][RTW89_WW][102] = -2, - [0][1][2][1][RTW89_WW][104] = -2, - [0][1][2][1][RTW89_WW][105] = -2, - [0][1][2][1][RTW89_WW][107] = 1, - [0][1][2][1][RTW89_WW][109] = 1, - [0][1][2][1][RTW89_WW][111] = 0, - [0][1][2][1][RTW89_WW][113] = 0, - [0][1][2][1][RTW89_WW][115] = 0, - [0][1][2][1][RTW89_WW][117] = 0, - [0][1][2][1][RTW89_WW][119] = 0, - [1][0][2][0][RTW89_WW][1] = 34, - [1][0][2][0][RTW89_WW][5] = 34, - [1][0][2][0][RTW89_WW][9] = 34, - [1][0][2][0][RTW89_WW][13] = 34, - [1][0][2][0][RTW89_WW][16] = 34, - [1][0][2][0][RTW89_WW][20] = 34, - [1][0][2][0][RTW89_WW][24] = 36, - [1][0][2][0][RTW89_WW][28] = 34, - [1][0][2][0][RTW89_WW][31] = 34, - [1][0][2][0][RTW89_WW][35] = 34, - [1][0][2][0][RTW89_WW][39] = 34, - [1][0][2][0][RTW89_WW][43] = 34, - [1][0][2][0][RTW89_WW][46] = 34, - [1][0][2][0][RTW89_WW][50] = 34, - [1][0][2][0][RTW89_WW][54] = 36, - [1][0][2][0][RTW89_WW][58] = 36, - [1][0][2][0][RTW89_WW][61] = 34, - [1][0][2][0][RTW89_WW][65] = 34, - [1][0][2][0][RTW89_WW][69] = 34, - [1][0][2][0][RTW89_WW][73] = 34, - [1][0][2][0][RTW89_WW][76] = 34, - [1][0][2][0][RTW89_WW][80] = 34, - [1][0][2][0][RTW89_WW][84] = 34, - [1][0][2][0][RTW89_WW][88] = 34, - [1][0][2][0][RTW89_WW][91] = 36, - [1][0][2][0][RTW89_WW][95] = 34, - [1][0][2][0][RTW89_WW][99] = 34, - [1][0][2][0][RTW89_WW][103] = 34, - [1][0][2][0][RTW89_WW][106] = 36, - [1][0][2][0][RTW89_WW][110] = 0, - [1][0][2][0][RTW89_WW][114] = 0, - [1][0][2][0][RTW89_WW][118] = 0, - [1][1][2][0][RTW89_WW][1] = 10, - [1][1][2][0][RTW89_WW][5] = 10, - [1][1][2][0][RTW89_WW][9] = 10, - [1][1][2][0][RTW89_WW][13] = 10, - [1][1][2][0][RTW89_WW][16] = 10, - [1][1][2][0][RTW89_WW][20] = 10, - [1][1][2][0][RTW89_WW][24] = 10, - [1][1][2][0][RTW89_WW][28] = 10, - [1][1][2][0][RTW89_WW][31] = 10, - [1][1][2][0][RTW89_WW][35] = 10, - [1][1][2][0][RTW89_WW][39] = 10, - [1][1][2][0][RTW89_WW][43] = 10, - [1][1][2][0][RTW89_WW][46] = 12, - [1][1][2][0][RTW89_WW][50] = 12, - [1][1][2][0][RTW89_WW][54] = 10, - [1][1][2][0][RTW89_WW][58] = 10, - [1][1][2][0][RTW89_WW][61] = 10, - [1][1][2][0][RTW89_WW][65] = 10, - [1][1][2][0][RTW89_WW][69] = 10, - [1][1][2][0][RTW89_WW][73] = 10, - [1][1][2][0][RTW89_WW][76] = 10, - [1][1][2][0][RTW89_WW][80] = 10, - [1][1][2][0][RTW89_WW][84] = 10, - [1][1][2][0][RTW89_WW][88] = 10, - [1][1][2][0][RTW89_WW][91] = 12, - [1][1][2][0][RTW89_WW][95] = 10, - [1][1][2][0][RTW89_WW][99] = 10, - [1][1][2][0][RTW89_WW][103] = 10, - [1][1][2][0][RTW89_WW][106] = 12, - [1][1][2][0][RTW89_WW][110] = 0, - [1][1][2][0][RTW89_WW][114] = 0, - [1][1][2][0][RTW89_WW][118] = 0, - [1][1][2][1][RTW89_WW][1] = 10, - [1][1][2][1][RTW89_WW][5] = 10, - [1][1][2][1][RTW89_WW][9] = 10, - [1][1][2][1][RTW89_WW][13] = 10, - [1][1][2][1][RTW89_WW][16] = 10, - [1][1][2][1][RTW89_WW][20] = 10, - [1][1][2][1][RTW89_WW][24] = 10, - [1][1][2][1][RTW89_WW][28] = 10, - [1][1][2][1][RTW89_WW][31] = 10, - [1][1][2][1][RTW89_WW][35] = 10, - [1][1][2][1][RTW89_WW][39] = 10, - [1][1][2][1][RTW89_WW][43] = 10, - [1][1][2][1][RTW89_WW][46] = 12, - [1][1][2][1][RTW89_WW][50] = 12, - [1][1][2][1][RTW89_WW][54] = 10, - [1][1][2][1][RTW89_WW][58] = 10, - [1][1][2][1][RTW89_WW][61] = 10, - [1][1][2][1][RTW89_WW][65] = 10, - [1][1][2][1][RTW89_WW][69] = 10, - [1][1][2][1][RTW89_WW][73] = 10, - [1][1][2][1][RTW89_WW][76] = 10, - [1][1][2][1][RTW89_WW][80] = 10, - [1][1][2][1][RTW89_WW][84] = 10, - [1][1][2][1][RTW89_WW][88] = 10, - [1][1][2][1][RTW89_WW][91] = 12, - [1][1][2][1][RTW89_WW][95] = 10, - [1][1][2][1][RTW89_WW][99] = 10, - [1][1][2][1][RTW89_WW][103] = 10, - [1][1][2][1][RTW89_WW][106] = 12, - [1][1][2][1][RTW89_WW][110] = 0, - [1][1][2][1][RTW89_WW][114] = 0, - [1][1][2][1][RTW89_WW][118] = 0, - [2][0][2][0][RTW89_WW][3] = 46, - [2][0][2][0][RTW89_WW][11] = 46, - [2][0][2][0][RTW89_WW][18] = 46, - [2][0][2][0][RTW89_WW][26] = 46, - [2][0][2][0][RTW89_WW][33] = 46, - [2][0][2][0][RTW89_WW][41] = 46, - [2][0][2][0][RTW89_WW][48] = 46, - [2][0][2][0][RTW89_WW][56] = 46, - [2][0][2][0][RTW89_WW][63] = 46, - [2][0][2][0][RTW89_WW][71] = 46, - [2][0][2][0][RTW89_WW][78] = 46, - [2][0][2][0][RTW89_WW][86] = 46, - [2][0][2][0][RTW89_WW][93] = 46, - [2][0][2][0][RTW89_WW][101] = 44, - [2][0][2][0][RTW89_WW][108] = 0, - [2][0][2][0][RTW89_WW][116] = 0, - [2][1][2][0][RTW89_WW][3] = 22, - [2][1][2][0][RTW89_WW][11] = 20, - [2][1][2][0][RTW89_WW][18] = 20, - [2][1][2][0][RTW89_WW][26] = 20, - [2][1][2][0][RTW89_WW][33] = 20, - [2][1][2][0][RTW89_WW][41] = 22, - [2][1][2][0][RTW89_WW][48] = 22, - [2][1][2][0][RTW89_WW][56] = 20, - [2][1][2][0][RTW89_WW][63] = 22, - [2][1][2][0][RTW89_WW][71] = 20, - [2][1][2][0][RTW89_WW][78] = 20, - [2][1][2][0][RTW89_WW][86] = 20, - [2][1][2][0][RTW89_WW][93] = 22, - [2][1][2][0][RTW89_WW][101] = 22, - [2][1][2][0][RTW89_WW][108] = 0, - [2][1][2][0][RTW89_WW][116] = 0, - [2][1][2][1][RTW89_WW][3] = 22, - [2][1][2][1][RTW89_WW][11] = 20, - [2][1][2][1][RTW89_WW][18] = 20, - [2][1][2][1][RTW89_WW][26] = 20, - [2][1][2][1][RTW89_WW][33] = 20, - [2][1][2][1][RTW89_WW][41] = 22, - [2][1][2][1][RTW89_WW][48] = 22, - [2][1][2][1][RTW89_WW][56] = 20, - [2][1][2][1][RTW89_WW][63] = 22, - [2][1][2][1][RTW89_WW][71] = 20, - [2][1][2][1][RTW89_WW][78] = 20, - [2][1][2][1][RTW89_WW][86] = 20, - [2][1][2][1][RTW89_WW][93] = 22, - [2][1][2][1][RTW89_WW][101] = 22, - [2][1][2][1][RTW89_WW][108] = 0, - [2][1][2][1][RTW89_WW][116] = 0, - [3][0][2][0][RTW89_WW][7] = 38, - [3][0][2][0][RTW89_WW][22] = 38, - [3][0][2][0][RTW89_WW][37] = 38, - [3][0][2][0][RTW89_WW][52] = 54, - [3][0][2][0][RTW89_WW][67] = 54, - [3][0][2][0][RTW89_WW][82] = 26, - [3][0][2][0][RTW89_WW][97] = 26, - [3][0][2][0][RTW89_WW][112] = 0, - [3][1][2][0][RTW89_WW][7] = 32, - [3][1][2][0][RTW89_WW][22] = 30, - [3][1][2][0][RTW89_WW][37] = 30, - [3][1][2][0][RTW89_WW][52] = 30, - [3][1][2][0][RTW89_WW][67] = 32, - [3][1][2][0][RTW89_WW][82] = 24, - [3][1][2][0][RTW89_WW][97] = 14, - [3][1][2][0][RTW89_WW][112] = 0, - [3][1][2][1][RTW89_WW][7] = 32, - [3][1][2][1][RTW89_WW][22] = 30, - [3][1][2][1][RTW89_WW][37] = 30, - [3][1][2][1][RTW89_WW][52] = 30, - [3][1][2][1][RTW89_WW][67] = 32, - [3][1][2][1][RTW89_WW][82] = 24, - [3][1][2][1][RTW89_WW][97] = 14, - [3][1][2][1][RTW89_WW][112] = 0, - [0][0][1][0][RTW89_FCC][0] = 24, - [0][0][1][0][RTW89_ETSI][0] = 66, - [0][0][1][0][RTW89_KCC][0] = 24, - [0][0][1][0][RTW89_FCC][2] = 22, - [0][0][1][0][RTW89_ETSI][2] = 66, - [0][0][1][0][RTW89_KCC][2] = 24, - [0][0][1][0][RTW89_FCC][4] = 22, - [0][0][1][0][RTW89_ETSI][4] = 66, - [0][0][1][0][RTW89_KCC][4] = 24, - [0][0][1][0][RTW89_FCC][6] = 22, - [0][0][1][0][RTW89_ETSI][6] = 66, - [0][0][1][0][RTW89_KCC][6] = 24, - [0][0][1][0][RTW89_FCC][8] = 22, - [0][0][1][0][RTW89_ETSI][8] = 66, - [0][0][1][0][RTW89_KCC][8] = 24, - [0][0][1][0][RTW89_FCC][10] = 22, - [0][0][1][0][RTW89_ETSI][10] = 66, - [0][0][1][0][RTW89_KCC][10] = 24, - [0][0][1][0][RTW89_FCC][12] = 22, - [0][0][1][0][RTW89_ETSI][12] = 66, - [0][0][1][0][RTW89_KCC][12] = 24, - [0][0][1][0][RTW89_FCC][14] = 22, - [0][0][1][0][RTW89_ETSI][14] = 66, - [0][0][1][0][RTW89_KCC][14] = 24, - [0][0][1][0][RTW89_FCC][15] = 22, - [0][0][1][0][RTW89_ETSI][15] = 66, - [0][0][1][0][RTW89_KCC][15] = 24, - [0][0][1][0][RTW89_FCC][17] = 22, - [0][0][1][0][RTW89_ETSI][17] = 66, - [0][0][1][0][RTW89_KCC][17] = 24, - [0][0][1][0][RTW89_FCC][19] = 22, - [0][0][1][0][RTW89_ETSI][19] = 66, - [0][0][1][0][RTW89_KCC][19] = 24, - [0][0][1][0][RTW89_FCC][21] = 22, - [0][0][1][0][RTW89_ETSI][21] = 66, - [0][0][1][0][RTW89_KCC][21] = 24, - [0][0][1][0][RTW89_FCC][23] = 22, - [0][0][1][0][RTW89_ETSI][23] = 66, - [0][0][1][0][RTW89_KCC][23] = 24, - [0][0][1][0][RTW89_FCC][25] = 22, - [0][0][1][0][RTW89_ETSI][25] = 66, - [0][0][1][0][RTW89_KCC][25] = 24, - [0][0][1][0][RTW89_FCC][27] = 22, - [0][0][1][0][RTW89_ETSI][27] = 66, - [0][0][1][0][RTW89_KCC][27] = 24, - [0][0][1][0][RTW89_FCC][29] = 22, - [0][0][1][0][RTW89_ETSI][29] = 66, - [0][0][1][0][RTW89_KCC][29] = 24, - [0][0][1][0][RTW89_FCC][30] = 22, - [0][0][1][0][RTW89_ETSI][30] = 66, - [0][0][1][0][RTW89_KCC][30] = 24, - [0][0][1][0][RTW89_FCC][32] = 22, - [0][0][1][0][RTW89_ETSI][32] = 66, - [0][0][1][0][RTW89_KCC][32] = 24, - [0][0][1][0][RTW89_FCC][34] = 22, - [0][0][1][0][RTW89_ETSI][34] = 66, - [0][0][1][0][RTW89_KCC][34] = 24, - [0][0][1][0][RTW89_FCC][36] = 22, - [0][0][1][0][RTW89_ETSI][36] = 66, - [0][0][1][0][RTW89_KCC][36] = 24, - [0][0][1][0][RTW89_FCC][38] = 22, - [0][0][1][0][RTW89_ETSI][38] = 66, - [0][0][1][0][RTW89_KCC][38] = 24, - [0][0][1][0][RTW89_FCC][40] = 22, - [0][0][1][0][RTW89_ETSI][40] = 66, - [0][0][1][0][RTW89_KCC][40] = 24, - [0][0][1][0][RTW89_FCC][42] = 22, - [0][0][1][0][RTW89_ETSI][42] = 66, - [0][0][1][0][RTW89_KCC][42] = 24, - [0][0][1][0][RTW89_FCC][44] = 22, - [0][0][1][0][RTW89_ETSI][44] = 66, - [0][0][1][0][RTW89_KCC][44] = 24, - [0][0][1][0][RTW89_FCC][45] = 22, - [0][0][1][0][RTW89_ETSI][45] = 127, - [0][0][1][0][RTW89_KCC][45] = 24, - [0][0][1][0][RTW89_FCC][47] = 22, - [0][0][1][0][RTW89_ETSI][47] = 127, - [0][0][1][0][RTW89_KCC][47] = 24, - [0][0][1][0][RTW89_FCC][49] = 24, - [0][0][1][0][RTW89_ETSI][49] = 127, - [0][0][1][0][RTW89_KCC][49] = 24, - [0][0][1][0][RTW89_FCC][51] = 22, - [0][0][1][0][RTW89_ETSI][51] = 127, - [0][0][1][0][RTW89_KCC][51] = 24, - [0][0][1][0][RTW89_FCC][53] = 22, - [0][0][1][0][RTW89_ETSI][53] = 127, - [0][0][1][0][RTW89_KCC][53] = 24, - [0][0][1][0][RTW89_FCC][55] = 22, - [0][0][1][0][RTW89_ETSI][55] = 127, - [0][0][1][0][RTW89_KCC][55] = 26, - [0][0][1][0][RTW89_FCC][57] = 22, - [0][0][1][0][RTW89_ETSI][57] = 127, - [0][0][1][0][RTW89_KCC][57] = 26, - [0][0][1][0][RTW89_FCC][59] = 22, - [0][0][1][0][RTW89_ETSI][59] = 127, - [0][0][1][0][RTW89_KCC][59] = 26, - [0][0][1][0][RTW89_FCC][60] = 22, - [0][0][1][0][RTW89_ETSI][60] = 127, - [0][0][1][0][RTW89_KCC][60] = 26, - [0][0][1][0][RTW89_FCC][62] = 22, - [0][0][1][0][RTW89_ETSI][62] = 127, - [0][0][1][0][RTW89_KCC][62] = 26, - [0][0][1][0][RTW89_FCC][64] = 22, - [0][0][1][0][RTW89_ETSI][64] = 127, - [0][0][1][0][RTW89_KCC][64] = 26, - [0][0][1][0][RTW89_FCC][66] = 22, - [0][0][1][0][RTW89_ETSI][66] = 127, - [0][0][1][0][RTW89_KCC][66] = 26, - [0][0][1][0][RTW89_FCC][68] = 22, - [0][0][1][0][RTW89_ETSI][68] = 127, - [0][0][1][0][RTW89_KCC][68] = 26, - [0][0][1][0][RTW89_FCC][70] = 24, - [0][0][1][0][RTW89_ETSI][70] = 127, - [0][0][1][0][RTW89_KCC][70] = 26, - [0][0][1][0][RTW89_FCC][72] = 22, - [0][0][1][0][RTW89_ETSI][72] = 127, - [0][0][1][0][RTW89_KCC][72] = 26, - [0][0][1][0][RTW89_FCC][74] = 22, - [0][0][1][0][RTW89_ETSI][74] = 127, - [0][0][1][0][RTW89_KCC][74] = 26, - [0][0][1][0][RTW89_FCC][75] = 22, - [0][0][1][0][RTW89_ETSI][75] = 127, - [0][0][1][0][RTW89_KCC][75] = 26, - [0][0][1][0][RTW89_FCC][77] = 22, - [0][0][1][0][RTW89_ETSI][77] = 127, - [0][0][1][0][RTW89_KCC][77] = 26, - [0][0][1][0][RTW89_FCC][79] = 22, - [0][0][1][0][RTW89_ETSI][79] = 127, - [0][0][1][0][RTW89_KCC][79] = 26, - [0][0][1][0][RTW89_FCC][81] = 22, - [0][0][1][0][RTW89_ETSI][81] = 127, - [0][0][1][0][RTW89_KCC][81] = 26, - [0][0][1][0][RTW89_FCC][83] = 22, - [0][0][1][0][RTW89_ETSI][83] = 127, - [0][0][1][0][RTW89_KCC][83] = 32, - [0][0][1][0][RTW89_FCC][85] = 22, - [0][0][1][0][RTW89_ETSI][85] = 127, - [0][0][1][0][RTW89_KCC][85] = 32, - [0][0][1][0][RTW89_FCC][87] = 22, - [0][0][1][0][RTW89_ETSI][87] = 127, - [0][0][1][0][RTW89_KCC][87] = 32, - [0][0][1][0][RTW89_FCC][89] = 22, - [0][0][1][0][RTW89_ETSI][89] = 127, - [0][0][1][0][RTW89_KCC][89] = 32, - [0][0][1][0][RTW89_FCC][90] = 22, - [0][0][1][0][RTW89_ETSI][90] = 127, - [0][0][1][0][RTW89_KCC][90] = 32, - [0][0][1][0][RTW89_FCC][92] = 22, - [0][0][1][0][RTW89_ETSI][92] = 127, - [0][0][1][0][RTW89_KCC][92] = 32, - [0][0][1][0][RTW89_FCC][94] = 22, - [0][0][1][0][RTW89_ETSI][94] = 127, - [0][0][1][0][RTW89_KCC][94] = 32, - [0][0][1][0][RTW89_FCC][96] = 22, - [0][0][1][0][RTW89_ETSI][96] = 127, - [0][0][1][0][RTW89_KCC][96] = 32, - [0][0][1][0][RTW89_FCC][98] = 22, - [0][0][1][0][RTW89_ETSI][98] = 127, - [0][0][1][0][RTW89_KCC][98] = 32, - [0][0][1][0][RTW89_FCC][100] = 22, - [0][0][1][0][RTW89_ETSI][100] = 127, - [0][0][1][0][RTW89_KCC][100] = 32, - [0][0][1][0][RTW89_FCC][102] = 22, - [0][0][1][0][RTW89_ETSI][102] = 127, - [0][0][1][0][RTW89_KCC][102] = 32, - [0][0][1][0][RTW89_FCC][104] = 22, - [0][0][1][0][RTW89_ETSI][104] = 127, - [0][0][1][0][RTW89_KCC][104] = 32, - [0][0][1][0][RTW89_FCC][105] = 22, - [0][0][1][0][RTW89_ETSI][105] = 127, - [0][0][1][0][RTW89_KCC][105] = 32, - [0][0][1][0][RTW89_FCC][107] = 24, - [0][0][1][0][RTW89_ETSI][107] = 127, - [0][0][1][0][RTW89_KCC][107] = 32, - [0][0][1][0][RTW89_FCC][109] = 24, - [0][0][1][0][RTW89_ETSI][109] = 127, - [0][0][1][0][RTW89_KCC][109] = 32, - [0][0][1][0][RTW89_FCC][111] = 127, - [0][0][1][0][RTW89_ETSI][111] = 127, - [0][0][1][0][RTW89_KCC][111] = 127, - [0][0][1][0][RTW89_FCC][113] = 127, - [0][0][1][0][RTW89_ETSI][113] = 127, - [0][0][1][0][RTW89_KCC][113] = 127, - [0][0][1][0][RTW89_FCC][115] = 127, - [0][0][1][0][RTW89_ETSI][115] = 127, - [0][0][1][0][RTW89_KCC][115] = 127, - [0][0][1][0][RTW89_FCC][117] = 127, - [0][0][1][0][RTW89_ETSI][117] = 127, - [0][0][1][0][RTW89_KCC][117] = 127, - [0][0][1][0][RTW89_FCC][119] = 127, - [0][0][1][0][RTW89_ETSI][119] = 127, - [0][0][1][0][RTW89_KCC][119] = 127, - [0][1][1][0][RTW89_FCC][0] = -2, - [0][1][1][0][RTW89_ETSI][0] = 54, - [0][1][1][0][RTW89_KCC][0] = 12, - [0][1][1][0][RTW89_FCC][2] = -4, - [0][1][1][0][RTW89_ETSI][2] = 54, - [0][1][1][0][RTW89_KCC][2] = 12, - [0][1][1][0][RTW89_FCC][4] = -4, - [0][1][1][0][RTW89_ETSI][4] = 54, - [0][1][1][0][RTW89_KCC][4] = 12, - [0][1][1][0][RTW89_FCC][6] = -4, - [0][1][1][0][RTW89_ETSI][6] = 54, - [0][1][1][0][RTW89_KCC][6] = 12, - [0][1][1][0][RTW89_FCC][8] = -4, - [0][1][1][0][RTW89_ETSI][8] = 54, - [0][1][1][0][RTW89_KCC][8] = 12, - [0][1][1][0][RTW89_FCC][10] = -4, - [0][1][1][0][RTW89_ETSI][10] = 54, - [0][1][1][0][RTW89_KCC][10] = 12, - [0][1][1][0][RTW89_FCC][12] = -4, - [0][1][1][0][RTW89_ETSI][12] = 54, - [0][1][1][0][RTW89_KCC][12] = 12, - [0][1][1][0][RTW89_FCC][14] = -4, - [0][1][1][0][RTW89_ETSI][14] = 54, - [0][1][1][0][RTW89_KCC][14] = 12, - [0][1][1][0][RTW89_FCC][15] = -4, - [0][1][1][0][RTW89_ETSI][15] = 54, - [0][1][1][0][RTW89_KCC][15] = 12, - [0][1][1][0][RTW89_FCC][17] = -4, - [0][1][1][0][RTW89_ETSI][17] = 54, - [0][1][1][0][RTW89_KCC][17] = 12, - [0][1][1][0][RTW89_FCC][19] = -4, - [0][1][1][0][RTW89_ETSI][19] = 54, - [0][1][1][0][RTW89_KCC][19] = 12, - [0][1][1][0][RTW89_FCC][21] = -4, - [0][1][1][0][RTW89_ETSI][21] = 54, - [0][1][1][0][RTW89_KCC][21] = 12, - [0][1][1][0][RTW89_FCC][23] = -4, - [0][1][1][0][RTW89_ETSI][23] = 54, - [0][1][1][0][RTW89_KCC][23] = 12, - [0][1][1][0][RTW89_FCC][25] = -4, - [0][1][1][0][RTW89_ETSI][25] = 54, - [0][1][1][0][RTW89_KCC][25] = 12, - [0][1][1][0][RTW89_FCC][27] = -4, - [0][1][1][0][RTW89_ETSI][27] = 54, - [0][1][1][0][RTW89_KCC][27] = 12, - [0][1][1][0][RTW89_FCC][29] = -4, - [0][1][1][0][RTW89_ETSI][29] = 54, - [0][1][1][0][RTW89_KCC][29] = 12, - [0][1][1][0][RTW89_FCC][30] = -4, - [0][1][1][0][RTW89_ETSI][30] = 54, - [0][1][1][0][RTW89_KCC][30] = 12, - [0][1][1][0][RTW89_FCC][32] = -4, - [0][1][1][0][RTW89_ETSI][32] = 54, - [0][1][1][0][RTW89_KCC][32] = 12, - [0][1][1][0][RTW89_FCC][34] = -4, - [0][1][1][0][RTW89_ETSI][34] = 54, - [0][1][1][0][RTW89_KCC][34] = 12, - [0][1][1][0][RTW89_FCC][36] = -4, - [0][1][1][0][RTW89_ETSI][36] = 54, - [0][1][1][0][RTW89_KCC][36] = 12, - [0][1][1][0][RTW89_FCC][38] = -4, - [0][1][1][0][RTW89_ETSI][38] = 54, - [0][1][1][0][RTW89_KCC][38] = 12, - [0][1][1][0][RTW89_FCC][40] = -4, - [0][1][1][0][RTW89_ETSI][40] = 54, - [0][1][1][0][RTW89_KCC][40] = 12, - [0][1][1][0][RTW89_FCC][42] = -4, - [0][1][1][0][RTW89_ETSI][42] = 54, - [0][1][1][0][RTW89_KCC][42] = 12, - [0][1][1][0][RTW89_FCC][44] = -2, - [0][1][1][0][RTW89_ETSI][44] = 54, - [0][1][1][0][RTW89_KCC][44] = 12, - [0][1][1][0][RTW89_FCC][45] = -2, - [0][1][1][0][RTW89_ETSI][45] = 127, - [0][1][1][0][RTW89_KCC][45] = 12, - [0][1][1][0][RTW89_FCC][47] = -2, - [0][1][1][0][RTW89_ETSI][47] = 127, - [0][1][1][0][RTW89_KCC][47] = 12, - [0][1][1][0][RTW89_FCC][49] = -2, - [0][1][1][0][RTW89_ETSI][49] = 127, - [0][1][1][0][RTW89_KCC][49] = 12, - [0][1][1][0][RTW89_FCC][51] = -2, - [0][1][1][0][RTW89_ETSI][51] = 127, - [0][1][1][0][RTW89_KCC][51] = 12, - [0][1][1][0][RTW89_FCC][53] = -2, - [0][1][1][0][RTW89_ETSI][53] = 127, - [0][1][1][0][RTW89_KCC][53] = 12, - [0][1][1][0][RTW89_FCC][55] = -2, - [0][1][1][0][RTW89_ETSI][55] = 127, - [0][1][1][0][RTW89_KCC][55] = 12, - [0][1][1][0][RTW89_FCC][57] = -2, - [0][1][1][0][RTW89_ETSI][57] = 127, - [0][1][1][0][RTW89_KCC][57] = 12, - [0][1][1][0][RTW89_FCC][59] = -2, - [0][1][1][0][RTW89_ETSI][59] = 127, - [0][1][1][0][RTW89_KCC][59] = 12, - [0][1][1][0][RTW89_FCC][60] = -2, - [0][1][1][0][RTW89_ETSI][60] = 127, - [0][1][1][0][RTW89_KCC][60] = 12, - [0][1][1][0][RTW89_FCC][62] = -2, - [0][1][1][0][RTW89_ETSI][62] = 127, - [0][1][1][0][RTW89_KCC][62] = 12, - [0][1][1][0][RTW89_FCC][64] = -2, - [0][1][1][0][RTW89_ETSI][64] = 127, - [0][1][1][0][RTW89_KCC][64] = 12, - [0][1][1][0][RTW89_FCC][66] = -2, - [0][1][1][0][RTW89_ETSI][66] = 127, - [0][1][1][0][RTW89_KCC][66] = 12, - [0][1][1][0][RTW89_FCC][68] = -2, - [0][1][1][0][RTW89_ETSI][68] = 127, - [0][1][1][0][RTW89_KCC][68] = 12, - [0][1][1][0][RTW89_FCC][70] = -2, - [0][1][1][0][RTW89_ETSI][70] = 127, - [0][1][1][0][RTW89_KCC][70] = 12, - [0][1][1][0][RTW89_FCC][72] = -2, - [0][1][1][0][RTW89_ETSI][72] = 127, - [0][1][1][0][RTW89_KCC][72] = 12, - [0][1][1][0][RTW89_FCC][74] = -2, - [0][1][1][0][RTW89_ETSI][74] = 127, - [0][1][1][0][RTW89_KCC][74] = 12, - [0][1][1][0][RTW89_FCC][75] = -2, - [0][1][1][0][RTW89_ETSI][75] = 127, - [0][1][1][0][RTW89_KCC][75] = 12, - [0][1][1][0][RTW89_FCC][77] = -2, - [0][1][1][0][RTW89_ETSI][77] = 127, - [0][1][1][0][RTW89_KCC][77] = 12, - [0][1][1][0][RTW89_FCC][79] = -2, - [0][1][1][0][RTW89_ETSI][79] = 127, - [0][1][1][0][RTW89_KCC][79] = 12, - [0][1][1][0][RTW89_FCC][81] = -2, - [0][1][1][0][RTW89_ETSI][81] = 127, - [0][1][1][0][RTW89_KCC][81] = 12, - [0][1][1][0][RTW89_FCC][83] = -2, - [0][1][1][0][RTW89_ETSI][83] = 127, - [0][1][1][0][RTW89_KCC][83] = 20, - [0][1][1][0][RTW89_FCC][85] = -2, - [0][1][1][0][RTW89_ETSI][85] = 127, - [0][1][1][0][RTW89_KCC][85] = 20, - [0][1][1][0][RTW89_FCC][87] = -2, - [0][1][1][0][RTW89_ETSI][87] = 127, - [0][1][1][0][RTW89_KCC][87] = 20, - [0][1][1][0][RTW89_FCC][89] = -2, - [0][1][1][0][RTW89_ETSI][89] = 127, - [0][1][1][0][RTW89_KCC][89] = 20, - [0][1][1][0][RTW89_FCC][90] = -2, - [0][1][1][0][RTW89_ETSI][90] = 127, - [0][1][1][0][RTW89_KCC][90] = 20, - [0][1][1][0][RTW89_FCC][92] = -2, - [0][1][1][0][RTW89_ETSI][92] = 127, - [0][1][1][0][RTW89_KCC][92] = 20, - [0][1][1][0][RTW89_FCC][94] = -2, - [0][1][1][0][RTW89_ETSI][94] = 127, - [0][1][1][0][RTW89_KCC][94] = 20, - [0][1][1][0][RTW89_FCC][96] = -2, - [0][1][1][0][RTW89_ETSI][96] = 127, - [0][1][1][0][RTW89_KCC][96] = 20, - [0][1][1][0][RTW89_FCC][98] = -2, - [0][1][1][0][RTW89_ETSI][98] = 127, - [0][1][1][0][RTW89_KCC][98] = 20, - [0][1][1][0][RTW89_FCC][100] = -2, - [0][1][1][0][RTW89_ETSI][100] = 127, - [0][1][1][0][RTW89_KCC][100] = 20, - [0][1][1][0][RTW89_FCC][102] = -2, - [0][1][1][0][RTW89_ETSI][102] = 127, - [0][1][1][0][RTW89_KCC][102] = 20, - [0][1][1][0][RTW89_FCC][104] = -2, - [0][1][1][0][RTW89_ETSI][104] = 127, - [0][1][1][0][RTW89_KCC][104] = 20, - [0][1][1][0][RTW89_FCC][105] = -2, - [0][1][1][0][RTW89_ETSI][105] = 127, - [0][1][1][0][RTW89_KCC][105] = 20, - [0][1][1][0][RTW89_FCC][107] = 0, - [0][1][1][0][RTW89_ETSI][107] = 127, - [0][1][1][0][RTW89_KCC][107] = 20, - [0][1][1][0][RTW89_FCC][109] = 0, - [0][1][1][0][RTW89_ETSI][109] = 127, - [0][1][1][0][RTW89_KCC][109] = 20, - [0][1][1][0][RTW89_FCC][111] = 127, - [0][1][1][0][RTW89_ETSI][111] = 127, - [0][1][1][0][RTW89_KCC][111] = 127, - [0][1][1][0][RTW89_FCC][113] = 127, - [0][1][1][0][RTW89_ETSI][113] = 127, - [0][1][1][0][RTW89_KCC][113] = 127, - [0][1][1][0][RTW89_FCC][115] = 127, - [0][1][1][0][RTW89_ETSI][115] = 127, - [0][1][1][0][RTW89_KCC][115] = 127, - [0][1][1][0][RTW89_FCC][117] = 127, - [0][1][1][0][RTW89_ETSI][117] = 127, - [0][1][1][0][RTW89_KCC][117] = 127, - [0][1][1][0][RTW89_FCC][119] = 127, - [0][1][1][0][RTW89_ETSI][119] = 127, - [0][1][1][0][RTW89_KCC][119] = 127, - [0][0][2][0][RTW89_FCC][0] = 24, - [0][0][2][0][RTW89_ETSI][0] = 66, - [0][0][2][0][RTW89_KCC][0] = 24, - [0][0][2][0][RTW89_FCC][2] = 22, - [0][0][2][0][RTW89_ETSI][2] = 66, - [0][0][2][0][RTW89_KCC][2] = 24, - [0][0][2][0][RTW89_FCC][4] = 22, - [0][0][2][0][RTW89_ETSI][4] = 66, - [0][0][2][0][RTW89_KCC][4] = 24, - [0][0][2][0][RTW89_FCC][6] = 22, - [0][0][2][0][RTW89_ETSI][6] = 66, - [0][0][2][0][RTW89_KCC][6] = 24, - [0][0][2][0][RTW89_FCC][8] = 22, - [0][0][2][0][RTW89_ETSI][8] = 66, - [0][0][2][0][RTW89_KCC][8] = 24, - [0][0][2][0][RTW89_FCC][10] = 22, - [0][0][2][0][RTW89_ETSI][10] = 66, - [0][0][2][0][RTW89_KCC][10] = 24, - [0][0][2][0][RTW89_FCC][12] = 22, - [0][0][2][0][RTW89_ETSI][12] = 66, - [0][0][2][0][RTW89_KCC][12] = 24, - [0][0][2][0][RTW89_FCC][14] = 22, - [0][0][2][0][RTW89_ETSI][14] = 66, - [0][0][2][0][RTW89_KCC][14] = 24, - [0][0][2][0][RTW89_FCC][15] = 22, - [0][0][2][0][RTW89_ETSI][15] = 66, - [0][0][2][0][RTW89_KCC][15] = 24, - [0][0][2][0][RTW89_FCC][17] = 22, - [0][0][2][0][RTW89_ETSI][17] = 66, - [0][0][2][0][RTW89_KCC][17] = 24, - [0][0][2][0][RTW89_FCC][19] = 22, - [0][0][2][0][RTW89_ETSI][19] = 66, - [0][0][2][0][RTW89_KCC][19] = 24, - [0][0][2][0][RTW89_FCC][21] = 22, - [0][0][2][0][RTW89_ETSI][21] = 66, - [0][0][2][0][RTW89_KCC][21] = 24, - [0][0][2][0][RTW89_FCC][23] = 22, - [0][0][2][0][RTW89_ETSI][23] = 66, - [0][0][2][0][RTW89_KCC][23] = 24, - [0][0][2][0][RTW89_FCC][25] = 22, - [0][0][2][0][RTW89_ETSI][25] = 66, - [0][0][2][0][RTW89_KCC][25] = 24, - [0][0][2][0][RTW89_FCC][27] = 22, - [0][0][2][0][RTW89_ETSI][27] = 66, - [0][0][2][0][RTW89_KCC][27] = 24, - [0][0][2][0][RTW89_FCC][29] = 22, - [0][0][2][0][RTW89_ETSI][29] = 66, - [0][0][2][0][RTW89_KCC][29] = 24, - [0][0][2][0][RTW89_FCC][30] = 22, - [0][0][2][0][RTW89_ETSI][30] = 66, - [0][0][2][0][RTW89_KCC][30] = 24, - [0][0][2][0][RTW89_FCC][32] = 22, - [0][0][2][0][RTW89_ETSI][32] = 66, - [0][0][2][0][RTW89_KCC][32] = 24, - [0][0][2][0][RTW89_FCC][34] = 22, - [0][0][2][0][RTW89_ETSI][34] = 66, - [0][0][2][0][RTW89_KCC][34] = 24, - [0][0][2][0][RTW89_FCC][36] = 22, - [0][0][2][0][RTW89_ETSI][36] = 66, - [0][0][2][0][RTW89_KCC][36] = 24, - [0][0][2][0][RTW89_FCC][38] = 22, - [0][0][2][0][RTW89_ETSI][38] = 66, - [0][0][2][0][RTW89_KCC][38] = 24, - [0][0][2][0][RTW89_FCC][40] = 22, - [0][0][2][0][RTW89_ETSI][40] = 66, - [0][0][2][0][RTW89_KCC][40] = 24, - [0][0][2][0][RTW89_FCC][42] = 22, - [0][0][2][0][RTW89_ETSI][42] = 66, - [0][0][2][0][RTW89_KCC][42] = 24, - [0][0][2][0][RTW89_FCC][44] = 22, - [0][0][2][0][RTW89_ETSI][44] = 66, - [0][0][2][0][RTW89_KCC][44] = 24, - [0][0][2][0][RTW89_FCC][45] = 22, - [0][0][2][0][RTW89_ETSI][45] = 127, - [0][0][2][0][RTW89_KCC][45] = 24, - [0][0][2][0][RTW89_FCC][47] = 22, - [0][0][2][0][RTW89_ETSI][47] = 127, - [0][0][2][0][RTW89_KCC][47] = 24, - [0][0][2][0][RTW89_FCC][49] = 24, - [0][0][2][0][RTW89_ETSI][49] = 127, - [0][0][2][0][RTW89_KCC][49] = 24, - [0][0][2][0][RTW89_FCC][51] = 22, - [0][0][2][0][RTW89_ETSI][51] = 127, - [0][0][2][0][RTW89_KCC][51] = 24, - [0][0][2][0][RTW89_FCC][53] = 22, - [0][0][2][0][RTW89_ETSI][53] = 127, - [0][0][2][0][RTW89_KCC][53] = 24, - [0][0][2][0][RTW89_FCC][55] = 22, - [0][0][2][0][RTW89_ETSI][55] = 127, - [0][0][2][0][RTW89_KCC][55] = 26, - [0][0][2][0][RTW89_FCC][57] = 22, - [0][0][2][0][RTW89_ETSI][57] = 127, - [0][0][2][0][RTW89_KCC][57] = 26, - [0][0][2][0][RTW89_FCC][59] = 22, - [0][0][2][0][RTW89_ETSI][59] = 127, - [0][0][2][0][RTW89_KCC][59] = 26, - [0][0][2][0][RTW89_FCC][60] = 22, - [0][0][2][0][RTW89_ETSI][60] = 127, - [0][0][2][0][RTW89_KCC][60] = 26, - [0][0][2][0][RTW89_FCC][62] = 22, - [0][0][2][0][RTW89_ETSI][62] = 127, - [0][0][2][0][RTW89_KCC][62] = 26, - [0][0][2][0][RTW89_FCC][64] = 22, - [0][0][2][0][RTW89_ETSI][64] = 127, - [0][0][2][0][RTW89_KCC][64] = 26, - [0][0][2][0][RTW89_FCC][66] = 22, - [0][0][2][0][RTW89_ETSI][66] = 127, - [0][0][2][0][RTW89_KCC][66] = 26, - [0][0][2][0][RTW89_FCC][68] = 22, - [0][0][2][0][RTW89_ETSI][68] = 127, - [0][0][2][0][RTW89_KCC][68] = 26, - [0][0][2][0][RTW89_FCC][70] = 24, - [0][0][2][0][RTW89_ETSI][70] = 127, - [0][0][2][0][RTW89_KCC][70] = 26, - [0][0][2][0][RTW89_FCC][72] = 22, - [0][0][2][0][RTW89_ETSI][72] = 127, - [0][0][2][0][RTW89_KCC][72] = 26, - [0][0][2][0][RTW89_FCC][74] = 22, - [0][0][2][0][RTW89_ETSI][74] = 127, - [0][0][2][0][RTW89_KCC][74] = 26, - [0][0][2][0][RTW89_FCC][75] = 22, - [0][0][2][0][RTW89_ETSI][75] = 127, - [0][0][2][0][RTW89_KCC][75] = 26, - [0][0][2][0][RTW89_FCC][77] = 22, - [0][0][2][0][RTW89_ETSI][77] = 127, - [0][0][2][0][RTW89_KCC][77] = 26, - [0][0][2][0][RTW89_FCC][79] = 22, - [0][0][2][0][RTW89_ETSI][79] = 127, - [0][0][2][0][RTW89_KCC][79] = 26, - [0][0][2][0][RTW89_FCC][81] = 22, - [0][0][2][0][RTW89_ETSI][81] = 127, - [0][0][2][0][RTW89_KCC][81] = 26, - [0][0][2][0][RTW89_FCC][83] = 22, - [0][0][2][0][RTW89_ETSI][83] = 127, - [0][0][2][0][RTW89_KCC][83] = 32, - [0][0][2][0][RTW89_FCC][85] = 22, - [0][0][2][0][RTW89_ETSI][85] = 127, - [0][0][2][0][RTW89_KCC][85] = 32, - [0][0][2][0][RTW89_FCC][87] = 22, - [0][0][2][0][RTW89_ETSI][87] = 127, - [0][0][2][0][RTW89_KCC][87] = 32, - [0][0][2][0][RTW89_FCC][89] = 22, - [0][0][2][0][RTW89_ETSI][89] = 127, - [0][0][2][0][RTW89_KCC][89] = 32, - [0][0][2][0][RTW89_FCC][90] = 22, - [0][0][2][0][RTW89_ETSI][90] = 127, - [0][0][2][0][RTW89_KCC][90] = 32, - [0][0][2][0][RTW89_FCC][92] = 22, - [0][0][2][0][RTW89_ETSI][92] = 127, - [0][0][2][0][RTW89_KCC][92] = 32, - [0][0][2][0][RTW89_FCC][94] = 22, - [0][0][2][0][RTW89_ETSI][94] = 127, - [0][0][2][0][RTW89_KCC][94] = 32, - [0][0][2][0][RTW89_FCC][96] = 22, - [0][0][2][0][RTW89_ETSI][96] = 127, - [0][0][2][0][RTW89_KCC][96] = 32, - [0][0][2][0][RTW89_FCC][98] = 22, - [0][0][2][0][RTW89_ETSI][98] = 127, - [0][0][2][0][RTW89_KCC][98] = 32, - [0][0][2][0][RTW89_FCC][100] = 22, - [0][0][2][0][RTW89_ETSI][100] = 127, - [0][0][2][0][RTW89_KCC][100] = 32, - [0][0][2][0][RTW89_FCC][102] = 22, - [0][0][2][0][RTW89_ETSI][102] = 127, - [0][0][2][0][RTW89_KCC][102] = 32, - [0][0][2][0][RTW89_FCC][104] = 22, - [0][0][2][0][RTW89_ETSI][104] = 127, - [0][0][2][0][RTW89_KCC][104] = 32, - [0][0][2][0][RTW89_FCC][105] = 22, - [0][0][2][0][RTW89_ETSI][105] = 127, - [0][0][2][0][RTW89_KCC][105] = 32, - [0][0][2][0][RTW89_FCC][107] = 24, - [0][0][2][0][RTW89_ETSI][107] = 127, - [0][0][2][0][RTW89_KCC][107] = 32, - [0][0][2][0][RTW89_FCC][109] = 24, - [0][0][2][0][RTW89_ETSI][109] = 127, - [0][0][2][0][RTW89_KCC][109] = 32, - [0][0][2][0][RTW89_FCC][111] = 127, - [0][0][2][0][RTW89_ETSI][111] = 127, - [0][0][2][0][RTW89_KCC][111] = 127, - [0][0][2][0][RTW89_FCC][113] = 127, - [0][0][2][0][RTW89_ETSI][113] = 127, - [0][0][2][0][RTW89_KCC][113] = 127, - [0][0][2][0][RTW89_FCC][115] = 127, - [0][0][2][0][RTW89_ETSI][115] = 127, - [0][0][2][0][RTW89_KCC][115] = 127, - [0][0][2][0][RTW89_FCC][117] = 127, - [0][0][2][0][RTW89_ETSI][117] = 127, - [0][0][2][0][RTW89_KCC][117] = 127, - [0][0][2][0][RTW89_FCC][119] = 127, - [0][0][2][0][RTW89_ETSI][119] = 127, - [0][0][2][0][RTW89_KCC][119] = 127, - [0][1][2][0][RTW89_FCC][0] = -2, - [0][1][2][0][RTW89_ETSI][0] = 54, - [0][1][2][0][RTW89_KCC][0] = 12, - [0][1][2][0][RTW89_FCC][2] = -4, - [0][1][2][0][RTW89_ETSI][2] = 54, - [0][1][2][0][RTW89_KCC][2] = 12, - [0][1][2][0][RTW89_FCC][4] = -4, - [0][1][2][0][RTW89_ETSI][4] = 54, - [0][1][2][0][RTW89_KCC][4] = 12, - [0][1][2][0][RTW89_FCC][6] = -4, - [0][1][2][0][RTW89_ETSI][6] = 54, - [0][1][2][0][RTW89_KCC][6] = 12, - [0][1][2][0][RTW89_FCC][8] = -4, - [0][1][2][0][RTW89_ETSI][8] = 54, - [0][1][2][0][RTW89_KCC][8] = 12, - [0][1][2][0][RTW89_FCC][10] = -4, - [0][1][2][0][RTW89_ETSI][10] = 54, - [0][1][2][0][RTW89_KCC][10] = 12, - [0][1][2][0][RTW89_FCC][12] = -4, - [0][1][2][0][RTW89_ETSI][12] = 54, - [0][1][2][0][RTW89_KCC][12] = 12, - [0][1][2][0][RTW89_FCC][14] = -4, - [0][1][2][0][RTW89_ETSI][14] = 54, - [0][1][2][0][RTW89_KCC][14] = 12, - [0][1][2][0][RTW89_FCC][15] = -4, - [0][1][2][0][RTW89_ETSI][15] = 54, - [0][1][2][0][RTW89_KCC][15] = 12, - [0][1][2][0][RTW89_FCC][17] = -4, - [0][1][2][0][RTW89_ETSI][17] = 54, - [0][1][2][0][RTW89_KCC][17] = 12, - [0][1][2][0][RTW89_FCC][19] = -4, - [0][1][2][0][RTW89_ETSI][19] = 54, - [0][1][2][0][RTW89_KCC][19] = 12, - [0][1][2][0][RTW89_FCC][21] = -4, - [0][1][2][0][RTW89_ETSI][21] = 54, - [0][1][2][0][RTW89_KCC][21] = 12, - [0][1][2][0][RTW89_FCC][23] = -4, - [0][1][2][0][RTW89_ETSI][23] = 54, - [0][1][2][0][RTW89_KCC][23] = 12, - [0][1][2][0][RTW89_FCC][25] = -4, - [0][1][2][0][RTW89_ETSI][25] = 54, - [0][1][2][0][RTW89_KCC][25] = 12, - [0][1][2][0][RTW89_FCC][27] = -4, - [0][1][2][0][RTW89_ETSI][27] = 54, - [0][1][2][0][RTW89_KCC][27] = 12, - [0][1][2][0][RTW89_FCC][29] = -4, - [0][1][2][0][RTW89_ETSI][29] = 54, - [0][1][2][0][RTW89_KCC][29] = 12, - [0][1][2][0][RTW89_FCC][30] = -4, - [0][1][2][0][RTW89_ETSI][30] = 54, - [0][1][2][0][RTW89_KCC][30] = 12, - [0][1][2][0][RTW89_FCC][32] = -4, - [0][1][2][0][RTW89_ETSI][32] = 54, - [0][1][2][0][RTW89_KCC][32] = 12, - [0][1][2][0][RTW89_FCC][34] = -4, - [0][1][2][0][RTW89_ETSI][34] = 54, - [0][1][2][0][RTW89_KCC][34] = 12, - [0][1][2][0][RTW89_FCC][36] = -4, - [0][1][2][0][RTW89_ETSI][36] = 54, - [0][1][2][0][RTW89_KCC][36] = 12, - [0][1][2][0][RTW89_FCC][38] = -4, - [0][1][2][0][RTW89_ETSI][38] = 54, - [0][1][2][0][RTW89_KCC][38] = 12, - [0][1][2][0][RTW89_FCC][40] = -4, - [0][1][2][0][RTW89_ETSI][40] = 54, - [0][1][2][0][RTW89_KCC][40] = 12, - [0][1][2][0][RTW89_FCC][42] = -4, - [0][1][2][0][RTW89_ETSI][42] = 54, - [0][1][2][0][RTW89_KCC][42] = 12, - [0][1][2][0][RTW89_FCC][44] = -2, - [0][1][2][0][RTW89_ETSI][44] = 54, - [0][1][2][0][RTW89_KCC][44] = 12, - [0][1][2][0][RTW89_FCC][45] = -2, - [0][1][2][0][RTW89_ETSI][45] = 127, - [0][1][2][0][RTW89_KCC][45] = 12, - [0][1][2][0][RTW89_FCC][47] = -2, - [0][1][2][0][RTW89_ETSI][47] = 127, - [0][1][2][0][RTW89_KCC][47] = 12, - [0][1][2][0][RTW89_FCC][49] = -2, - [0][1][2][0][RTW89_ETSI][49] = 127, - [0][1][2][0][RTW89_KCC][49] = 12, - [0][1][2][0][RTW89_FCC][51] = -2, - [0][1][2][0][RTW89_ETSI][51] = 127, - [0][1][2][0][RTW89_KCC][51] = 12, - [0][1][2][0][RTW89_FCC][53] = -2, - [0][1][2][0][RTW89_ETSI][53] = 127, - [0][1][2][0][RTW89_KCC][53] = 12, - [0][1][2][0][RTW89_FCC][55] = -2, - [0][1][2][0][RTW89_ETSI][55] = 127, - [0][1][2][0][RTW89_KCC][55] = 12, - [0][1][2][0][RTW89_FCC][57] = -2, - [0][1][2][0][RTW89_ETSI][57] = 127, - [0][1][2][0][RTW89_KCC][57] = 12, - [0][1][2][0][RTW89_FCC][59] = -2, - [0][1][2][0][RTW89_ETSI][59] = 127, - [0][1][2][0][RTW89_KCC][59] = 12, - [0][1][2][0][RTW89_FCC][60] = -2, - [0][1][2][0][RTW89_ETSI][60] = 127, - [0][1][2][0][RTW89_KCC][60] = 12, - [0][1][2][0][RTW89_FCC][62] = -2, - [0][1][2][0][RTW89_ETSI][62] = 127, - [0][1][2][0][RTW89_KCC][62] = 12, - [0][1][2][0][RTW89_FCC][64] = -2, - [0][1][2][0][RTW89_ETSI][64] = 127, - [0][1][2][0][RTW89_KCC][64] = 12, - [0][1][2][0][RTW89_FCC][66] = -2, - [0][1][2][0][RTW89_ETSI][66] = 127, - [0][1][2][0][RTW89_KCC][66] = 12, - [0][1][2][0][RTW89_FCC][68] = -2, - [0][1][2][0][RTW89_ETSI][68] = 127, - [0][1][2][0][RTW89_KCC][68] = 12, - [0][1][2][0][RTW89_FCC][70] = -2, - [0][1][2][0][RTW89_ETSI][70] = 127, - [0][1][2][0][RTW89_KCC][70] = 12, - [0][1][2][0][RTW89_FCC][72] = -2, - [0][1][2][0][RTW89_ETSI][72] = 127, - [0][1][2][0][RTW89_KCC][72] = 12, - [0][1][2][0][RTW89_FCC][74] = -2, - [0][1][2][0][RTW89_ETSI][74] = 127, - [0][1][2][0][RTW89_KCC][74] = 12, - [0][1][2][0][RTW89_FCC][75] = -2, - [0][1][2][0][RTW89_ETSI][75] = 127, - [0][1][2][0][RTW89_KCC][75] = 12, - [0][1][2][0][RTW89_FCC][77] = -2, - [0][1][2][0][RTW89_ETSI][77] = 127, - [0][1][2][0][RTW89_KCC][77] = 12, - [0][1][2][0][RTW89_FCC][79] = -2, - [0][1][2][0][RTW89_ETSI][79] = 127, - [0][1][2][0][RTW89_KCC][79] = 12, - [0][1][2][0][RTW89_FCC][81] = -2, - [0][1][2][0][RTW89_ETSI][81] = 127, - [0][1][2][0][RTW89_KCC][81] = 12, - [0][1][2][0][RTW89_FCC][83] = -2, - [0][1][2][0][RTW89_ETSI][83] = 127, - [0][1][2][0][RTW89_KCC][83] = 20, - [0][1][2][0][RTW89_FCC][85] = -2, - [0][1][2][0][RTW89_ETSI][85] = 127, - [0][1][2][0][RTW89_KCC][85] = 20, - [0][1][2][0][RTW89_FCC][87] = -2, - [0][1][2][0][RTW89_ETSI][87] = 127, - [0][1][2][0][RTW89_KCC][87] = 20, - [0][1][2][0][RTW89_FCC][89] = -2, - [0][1][2][0][RTW89_ETSI][89] = 127, - [0][1][2][0][RTW89_KCC][89] = 20, - [0][1][2][0][RTW89_FCC][90] = -2, - [0][1][2][0][RTW89_ETSI][90] = 127, - [0][1][2][0][RTW89_KCC][90] = 20, - [0][1][2][0][RTW89_FCC][92] = -2, - [0][1][2][0][RTW89_ETSI][92] = 127, - [0][1][2][0][RTW89_KCC][92] = 20, - [0][1][2][0][RTW89_FCC][94] = -2, - [0][1][2][0][RTW89_ETSI][94] = 127, - [0][1][2][0][RTW89_KCC][94] = 20, - [0][1][2][0][RTW89_FCC][96] = -2, - [0][1][2][0][RTW89_ETSI][96] = 127, - [0][1][2][0][RTW89_KCC][96] = 20, - [0][1][2][0][RTW89_FCC][98] = -2, - [0][1][2][0][RTW89_ETSI][98] = 127, - [0][1][2][0][RTW89_KCC][98] = 20, - [0][1][2][0][RTW89_FCC][100] = -2, - [0][1][2][0][RTW89_ETSI][100] = 127, - [0][1][2][0][RTW89_KCC][100] = 20, - [0][1][2][0][RTW89_FCC][102] = -2, - [0][1][2][0][RTW89_ETSI][102] = 127, - [0][1][2][0][RTW89_KCC][102] = 20, - [0][1][2][0][RTW89_FCC][104] = -2, - [0][1][2][0][RTW89_ETSI][104] = 127, - [0][1][2][0][RTW89_KCC][104] = 20, - [0][1][2][0][RTW89_FCC][105] = -2, - [0][1][2][0][RTW89_ETSI][105] = 127, - [0][1][2][0][RTW89_KCC][105] = 20, - [0][1][2][0][RTW89_FCC][107] = 0, - [0][1][2][0][RTW89_ETSI][107] = 127, - [0][1][2][0][RTW89_KCC][107] = 20, - [0][1][2][0][RTW89_FCC][109] = 0, - [0][1][2][0][RTW89_ETSI][109] = 127, - [0][1][2][0][RTW89_KCC][109] = 20, - [0][1][2][0][RTW89_FCC][111] = 127, - [0][1][2][0][RTW89_ETSI][111] = 127, - [0][1][2][0][RTW89_KCC][111] = 127, - [0][1][2][0][RTW89_FCC][113] = 127, - [0][1][2][0][RTW89_ETSI][113] = 127, - [0][1][2][0][RTW89_KCC][113] = 127, - [0][1][2][0][RTW89_FCC][115] = 127, - [0][1][2][0][RTW89_ETSI][115] = 127, - [0][1][2][0][RTW89_KCC][115] = 127, - [0][1][2][0][RTW89_FCC][117] = 127, - [0][1][2][0][RTW89_ETSI][117] = 127, - [0][1][2][0][RTW89_KCC][117] = 127, - [0][1][2][0][RTW89_FCC][119] = 127, - [0][1][2][0][RTW89_ETSI][119] = 127, - [0][1][2][0][RTW89_KCC][119] = 127, - [0][1][2][1][RTW89_FCC][0] = -2, - [0][1][2][1][RTW89_ETSI][0] = 42, - [0][1][2][1][RTW89_KCC][0] = 12, - [0][1][2][1][RTW89_FCC][2] = -4, - [0][1][2][1][RTW89_ETSI][2] = 42, - [0][1][2][1][RTW89_KCC][2] = 12, - [0][1][2][1][RTW89_FCC][4] = -4, - [0][1][2][1][RTW89_ETSI][4] = 42, - [0][1][2][1][RTW89_KCC][4] = 12, - [0][1][2][1][RTW89_FCC][6] = -4, - [0][1][2][1][RTW89_ETSI][6] = 42, - [0][1][2][1][RTW89_KCC][6] = 12, - [0][1][2][1][RTW89_FCC][8] = -4, - [0][1][2][1][RTW89_ETSI][8] = 42, - [0][1][2][1][RTW89_KCC][8] = 12, - [0][1][2][1][RTW89_FCC][10] = -4, - [0][1][2][1][RTW89_ETSI][10] = 42, - [0][1][2][1][RTW89_KCC][10] = 12, - [0][1][2][1][RTW89_FCC][12] = -4, - [0][1][2][1][RTW89_ETSI][12] = 42, - [0][1][2][1][RTW89_KCC][12] = 12, - [0][1][2][1][RTW89_FCC][14] = -4, - [0][1][2][1][RTW89_ETSI][14] = 42, - [0][1][2][1][RTW89_KCC][14] = 12, - [0][1][2][1][RTW89_FCC][15] = -4, - [0][1][2][1][RTW89_ETSI][15] = 42, - [0][1][2][1][RTW89_KCC][15] = 12, - [0][1][2][1][RTW89_FCC][17] = -4, - [0][1][2][1][RTW89_ETSI][17] = 42, - [0][1][2][1][RTW89_KCC][17] = 12, - [0][1][2][1][RTW89_FCC][19] = -4, - [0][1][2][1][RTW89_ETSI][19] = 42, - [0][1][2][1][RTW89_KCC][19] = 12, - [0][1][2][1][RTW89_FCC][21] = -4, - [0][1][2][1][RTW89_ETSI][21] = 42, - [0][1][2][1][RTW89_KCC][21] = 12, - [0][1][2][1][RTW89_FCC][23] = -4, - [0][1][2][1][RTW89_ETSI][23] = 42, - [0][1][2][1][RTW89_KCC][23] = 12, - [0][1][2][1][RTW89_FCC][25] = -4, - [0][1][2][1][RTW89_ETSI][25] = 42, - [0][1][2][1][RTW89_KCC][25] = 12, - [0][1][2][1][RTW89_FCC][27] = -4, - [0][1][2][1][RTW89_ETSI][27] = 42, - [0][1][2][1][RTW89_KCC][27] = 12, - [0][1][2][1][RTW89_FCC][29] = -4, - [0][1][2][1][RTW89_ETSI][29] = 42, - [0][1][2][1][RTW89_KCC][29] = 12, - [0][1][2][1][RTW89_FCC][30] = -4, - [0][1][2][1][RTW89_ETSI][30] = 42, - [0][1][2][1][RTW89_KCC][30] = 12, - [0][1][2][1][RTW89_FCC][32] = -4, - [0][1][2][1][RTW89_ETSI][32] = 42, - [0][1][2][1][RTW89_KCC][32] = 12, - [0][1][2][1][RTW89_FCC][34] = -4, - [0][1][2][1][RTW89_ETSI][34] = 42, - [0][1][2][1][RTW89_KCC][34] = 12, - [0][1][2][1][RTW89_FCC][36] = -4, - [0][1][2][1][RTW89_ETSI][36] = 42, - [0][1][2][1][RTW89_KCC][36] = 12, - [0][1][2][1][RTW89_FCC][38] = -4, - [0][1][2][1][RTW89_ETSI][38] = 42, - [0][1][2][1][RTW89_KCC][38] = 12, - [0][1][2][1][RTW89_FCC][40] = -4, - [0][1][2][1][RTW89_ETSI][40] = 42, - [0][1][2][1][RTW89_KCC][40] = 12, - [0][1][2][1][RTW89_FCC][42] = -4, - [0][1][2][1][RTW89_ETSI][42] = 42, - [0][1][2][1][RTW89_KCC][42] = 12, - [0][1][2][1][RTW89_FCC][44] = -2, - [0][1][2][1][RTW89_ETSI][44] = 42, - [0][1][2][1][RTW89_KCC][44] = 12, - [0][1][2][1][RTW89_FCC][45] = -2, - [0][1][2][1][RTW89_ETSI][45] = 127, - [0][1][2][1][RTW89_KCC][45] = 12, - [0][1][2][1][RTW89_FCC][47] = -2, - [0][1][2][1][RTW89_ETSI][47] = 127, - [0][1][2][1][RTW89_KCC][47] = 12, - [0][1][2][1][RTW89_FCC][49] = -2, - [0][1][2][1][RTW89_ETSI][49] = 127, - [0][1][2][1][RTW89_KCC][49] = 12, - [0][1][2][1][RTW89_FCC][51] = -2, - [0][1][2][1][RTW89_ETSI][51] = 127, - [0][1][2][1][RTW89_KCC][51] = 12, - [0][1][2][1][RTW89_FCC][53] = -2, - [0][1][2][1][RTW89_ETSI][53] = 127, - [0][1][2][1][RTW89_KCC][53] = 12, - [0][1][2][1][RTW89_FCC][55] = -2, - [0][1][2][1][RTW89_ETSI][55] = 127, - [0][1][2][1][RTW89_KCC][55] = 12, - [0][1][2][1][RTW89_FCC][57] = -2, - [0][1][2][1][RTW89_ETSI][57] = 127, - [0][1][2][1][RTW89_KCC][57] = 12, - [0][1][2][1][RTW89_FCC][59] = -2, - [0][1][2][1][RTW89_ETSI][59] = 127, - [0][1][2][1][RTW89_KCC][59] = 12, - [0][1][2][1][RTW89_FCC][60] = -2, - [0][1][2][1][RTW89_ETSI][60] = 127, - [0][1][2][1][RTW89_KCC][60] = 12, - [0][1][2][1][RTW89_FCC][62] = -2, - [0][1][2][1][RTW89_ETSI][62] = 127, - [0][1][2][1][RTW89_KCC][62] = 12, - [0][1][2][1][RTW89_FCC][64] = -2, - [0][1][2][1][RTW89_ETSI][64] = 127, - [0][1][2][1][RTW89_KCC][64] = 12, - [0][1][2][1][RTW89_FCC][66] = -2, - [0][1][2][1][RTW89_ETSI][66] = 127, - [0][1][2][1][RTW89_KCC][66] = 12, - [0][1][2][1][RTW89_FCC][68] = -2, - [0][1][2][1][RTW89_ETSI][68] = 127, - [0][1][2][1][RTW89_KCC][68] = 12, - [0][1][2][1][RTW89_FCC][70] = -2, - [0][1][2][1][RTW89_ETSI][70] = 127, - [0][1][2][1][RTW89_KCC][70] = 12, - [0][1][2][1][RTW89_FCC][72] = -2, - [0][1][2][1][RTW89_ETSI][72] = 127, - [0][1][2][1][RTW89_KCC][72] = 12, - [0][1][2][1][RTW89_FCC][74] = -2, - [0][1][2][1][RTW89_ETSI][74] = 127, - [0][1][2][1][RTW89_KCC][74] = 12, - [0][1][2][1][RTW89_FCC][75] = -2, - [0][1][2][1][RTW89_ETSI][75] = 127, - [0][1][2][1][RTW89_KCC][75] = 12, - [0][1][2][1][RTW89_FCC][77] = -2, - [0][1][2][1][RTW89_ETSI][77] = 127, - [0][1][2][1][RTW89_KCC][77] = 12, - [0][1][2][1][RTW89_FCC][79] = -2, - [0][1][2][1][RTW89_ETSI][79] = 127, - [0][1][2][1][RTW89_KCC][79] = 12, - [0][1][2][1][RTW89_FCC][81] = -2, - [0][1][2][1][RTW89_ETSI][81] = 127, - [0][1][2][1][RTW89_KCC][81] = 12, - [0][1][2][1][RTW89_FCC][83] = -2, - [0][1][2][1][RTW89_ETSI][83] = 127, - [0][1][2][1][RTW89_KCC][83] = 20, - [0][1][2][1][RTW89_FCC][85] = -2, - [0][1][2][1][RTW89_ETSI][85] = 127, - [0][1][2][1][RTW89_KCC][85] = 20, - [0][1][2][1][RTW89_FCC][87] = -2, - [0][1][2][1][RTW89_ETSI][87] = 127, - [0][1][2][1][RTW89_KCC][87] = 20, - [0][1][2][1][RTW89_FCC][89] = -2, - [0][1][2][1][RTW89_ETSI][89] = 127, - [0][1][2][1][RTW89_KCC][89] = 20, - [0][1][2][1][RTW89_FCC][90] = -2, - [0][1][2][1][RTW89_ETSI][90] = 127, - [0][1][2][1][RTW89_KCC][90] = 20, - [0][1][2][1][RTW89_FCC][92] = -2, - [0][1][2][1][RTW89_ETSI][92] = 127, - [0][1][2][1][RTW89_KCC][92] = 20, - [0][1][2][1][RTW89_FCC][94] = -2, - [0][1][2][1][RTW89_ETSI][94] = 127, - [0][1][2][1][RTW89_KCC][94] = 20, - [0][1][2][1][RTW89_FCC][96] = -2, - [0][1][2][1][RTW89_ETSI][96] = 127, - [0][1][2][1][RTW89_KCC][96] = 20, - [0][1][2][1][RTW89_FCC][98] = -2, - [0][1][2][1][RTW89_ETSI][98] = 127, - [0][1][2][1][RTW89_KCC][98] = 20, - [0][1][2][1][RTW89_FCC][100] = -2, - [0][1][2][1][RTW89_ETSI][100] = 127, - [0][1][2][1][RTW89_KCC][100] = 20, - [0][1][2][1][RTW89_FCC][102] = -2, - [0][1][2][1][RTW89_ETSI][102] = 127, - [0][1][2][1][RTW89_KCC][102] = 20, - [0][1][2][1][RTW89_FCC][104] = -2, - [0][1][2][1][RTW89_ETSI][104] = 127, - [0][1][2][1][RTW89_KCC][104] = 20, - [0][1][2][1][RTW89_FCC][105] = -2, - [0][1][2][1][RTW89_ETSI][105] = 127, - [0][1][2][1][RTW89_KCC][105] = 20, - [0][1][2][1][RTW89_FCC][107] = 0, - [0][1][2][1][RTW89_ETSI][107] = 127, - [0][1][2][1][RTW89_KCC][107] = 20, - [0][1][2][1][RTW89_FCC][109] = 0, - [0][1][2][1][RTW89_ETSI][109] = 127, - [0][1][2][1][RTW89_KCC][109] = 20, - [0][1][2][1][RTW89_FCC][111] = 127, - [0][1][2][1][RTW89_ETSI][111] = 127, - [0][1][2][1][RTW89_KCC][111] = 127, - [0][1][2][1][RTW89_FCC][113] = 127, - [0][1][2][1][RTW89_ETSI][113] = 127, - [0][1][2][1][RTW89_KCC][113] = 127, - [0][1][2][1][RTW89_FCC][115] = 127, - [0][1][2][1][RTW89_ETSI][115] = 127, - [0][1][2][1][RTW89_KCC][115] = 127, - [0][1][2][1][RTW89_FCC][117] = 127, - [0][1][2][1][RTW89_ETSI][117] = 127, - [0][1][2][1][RTW89_KCC][117] = 127, - [0][1][2][1][RTW89_FCC][119] = 127, - [0][1][2][1][RTW89_ETSI][119] = 127, - [0][1][2][1][RTW89_KCC][119] = 127, - [1][0][2][0][RTW89_FCC][1] = 34, - [1][0][2][0][RTW89_ETSI][1] = 66, - [1][0][2][0][RTW89_KCC][1] = 40, - [1][0][2][0][RTW89_FCC][5] = 34, - [1][0][2][0][RTW89_ETSI][5] = 66, - [1][0][2][0][RTW89_KCC][5] = 40, - [1][0][2][0][RTW89_FCC][9] = 34, - [1][0][2][0][RTW89_ETSI][9] = 66, - [1][0][2][0][RTW89_KCC][9] = 40, - [1][0][2][0][RTW89_FCC][13] = 34, - [1][0][2][0][RTW89_ETSI][13] = 66, - [1][0][2][0][RTW89_KCC][13] = 40, - [1][0][2][0][RTW89_FCC][16] = 34, - [1][0][2][0][RTW89_ETSI][16] = 66, - [1][0][2][0][RTW89_KCC][16] = 40, - [1][0][2][0][RTW89_FCC][20] = 34, - [1][0][2][0][RTW89_ETSI][20] = 66, - [1][0][2][0][RTW89_KCC][20] = 40, - [1][0][2][0][RTW89_FCC][24] = 36, - [1][0][2][0][RTW89_ETSI][24] = 66, - [1][0][2][0][RTW89_KCC][24] = 40, - [1][0][2][0][RTW89_FCC][28] = 34, - [1][0][2][0][RTW89_ETSI][28] = 66, - [1][0][2][0][RTW89_KCC][28] = 40, - [1][0][2][0][RTW89_FCC][31] = 34, - [1][0][2][0][RTW89_ETSI][31] = 66, - [1][0][2][0][RTW89_KCC][31] = 40, - [1][0][2][0][RTW89_FCC][35] = 34, - [1][0][2][0][RTW89_ETSI][35] = 66, - [1][0][2][0][RTW89_KCC][35] = 40, - [1][0][2][0][RTW89_FCC][39] = 34, - [1][0][2][0][RTW89_ETSI][39] = 66, - [1][0][2][0][RTW89_KCC][39] = 40, - [1][0][2][0][RTW89_FCC][43] = 34, - [1][0][2][0][RTW89_ETSI][43] = 66, - [1][0][2][0][RTW89_KCC][43] = 40, - [1][0][2][0][RTW89_FCC][46] = 34, - [1][0][2][0][RTW89_ETSI][46] = 127, - [1][0][2][0][RTW89_KCC][46] = 40, - [1][0][2][0][RTW89_FCC][50] = 34, - [1][0][2][0][RTW89_ETSI][50] = 127, - [1][0][2][0][RTW89_KCC][50] = 40, - [1][0][2][0][RTW89_FCC][54] = 36, - [1][0][2][0][RTW89_ETSI][54] = 127, - [1][0][2][0][RTW89_KCC][54] = 40, - [1][0][2][0][RTW89_FCC][58] = 36, - [1][0][2][0][RTW89_ETSI][58] = 127, - [1][0][2][0][RTW89_KCC][58] = 40, - [1][0][2][0][RTW89_FCC][61] = 34, - [1][0][2][0][RTW89_ETSI][61] = 127, - [1][0][2][0][RTW89_KCC][61] = 40, - [1][0][2][0][RTW89_FCC][65] = 34, - [1][0][2][0][RTW89_ETSI][65] = 127, - [1][0][2][0][RTW89_KCC][65] = 40, - [1][0][2][0][RTW89_FCC][69] = 34, - [1][0][2][0][RTW89_ETSI][69] = 127, - [1][0][2][0][RTW89_KCC][69] = 40, - [1][0][2][0][RTW89_FCC][73] = 34, - [1][0][2][0][RTW89_ETSI][73] = 127, - [1][0][2][0][RTW89_KCC][73] = 40, - [1][0][2][0][RTW89_FCC][76] = 34, - [1][0][2][0][RTW89_ETSI][76] = 127, - [1][0][2][0][RTW89_KCC][76] = 40, - [1][0][2][0][RTW89_FCC][80] = 34, - [1][0][2][0][RTW89_ETSI][80] = 127, - [1][0][2][0][RTW89_KCC][80] = 42, - [1][0][2][0][RTW89_FCC][84] = 34, - [1][0][2][0][RTW89_ETSI][84] = 127, - [1][0][2][0][RTW89_KCC][84] = 42, - [1][0][2][0][RTW89_FCC][88] = 34, - [1][0][2][0][RTW89_ETSI][88] = 127, - [1][0][2][0][RTW89_KCC][88] = 42, - [1][0][2][0][RTW89_FCC][91] = 36, - [1][0][2][0][RTW89_ETSI][91] = 127, - [1][0][2][0][RTW89_KCC][91] = 42, - [1][0][2][0][RTW89_FCC][95] = 34, - [1][0][2][0][RTW89_ETSI][95] = 127, - [1][0][2][0][RTW89_KCC][95] = 42, - [1][0][2][0][RTW89_FCC][99] = 34, - [1][0][2][0][RTW89_ETSI][99] = 127, - [1][0][2][0][RTW89_KCC][99] = 42, - [1][0][2][0][RTW89_FCC][103] = 34, - [1][0][2][0][RTW89_ETSI][103] = 127, - [1][0][2][0][RTW89_KCC][103] = 42, - [1][0][2][0][RTW89_FCC][106] = 36, - [1][0][2][0][RTW89_ETSI][106] = 127, - [1][0][2][0][RTW89_KCC][106] = 42, - [1][0][2][0][RTW89_FCC][110] = 127, - [1][0][2][0][RTW89_ETSI][110] = 127, - [1][0][2][0][RTW89_KCC][110] = 127, - [1][0][2][0][RTW89_FCC][114] = 127, - [1][0][2][0][RTW89_ETSI][114] = 127, - [1][0][2][0][RTW89_KCC][114] = 127, - [1][0][2][0][RTW89_FCC][118] = 127, - [1][0][2][0][RTW89_ETSI][118] = 127, - [1][0][2][0][RTW89_KCC][118] = 127, - [1][1][2][0][RTW89_FCC][1] = 10, - [1][1][2][0][RTW89_ETSI][1] = 54, - [1][1][2][0][RTW89_KCC][1] = 28, - [1][1][2][0][RTW89_FCC][5] = 10, - [1][1][2][0][RTW89_ETSI][5] = 54, - [1][1][2][0][RTW89_KCC][5] = 28, - [1][1][2][0][RTW89_FCC][9] = 10, - [1][1][2][0][RTW89_ETSI][9] = 54, - [1][1][2][0][RTW89_KCC][9] = 28, - [1][1][2][0][RTW89_FCC][13] = 10, - [1][1][2][0][RTW89_ETSI][13] = 54, - [1][1][2][0][RTW89_KCC][13] = 28, - [1][1][2][0][RTW89_FCC][16] = 10, - [1][1][2][0][RTW89_ETSI][16] = 54, - [1][1][2][0][RTW89_KCC][16] = 28, - [1][1][2][0][RTW89_FCC][20] = 10, - [1][1][2][0][RTW89_ETSI][20] = 54, - [1][1][2][0][RTW89_KCC][20] = 28, - [1][1][2][0][RTW89_FCC][24] = 10, - [1][1][2][0][RTW89_ETSI][24] = 54, - [1][1][2][0][RTW89_KCC][24] = 28, - [1][1][2][0][RTW89_FCC][28] = 10, - [1][1][2][0][RTW89_ETSI][28] = 54, - [1][1][2][0][RTW89_KCC][28] = 28, - [1][1][2][0][RTW89_FCC][31] = 10, - [1][1][2][0][RTW89_ETSI][31] = 54, - [1][1][2][0][RTW89_KCC][31] = 28, - [1][1][2][0][RTW89_FCC][35] = 10, - [1][1][2][0][RTW89_ETSI][35] = 54, - [1][1][2][0][RTW89_KCC][35] = 28, - [1][1][2][0][RTW89_FCC][39] = 10, - [1][1][2][0][RTW89_ETSI][39] = 54, - [1][1][2][0][RTW89_KCC][39] = 28, - [1][1][2][0][RTW89_FCC][43] = 10, - [1][1][2][0][RTW89_ETSI][43] = 54, - [1][1][2][0][RTW89_KCC][43] = 28, - [1][1][2][0][RTW89_FCC][46] = 12, - [1][1][2][0][RTW89_ETSI][46] = 127, - [1][1][2][0][RTW89_KCC][46] = 28, - [1][1][2][0][RTW89_FCC][50] = 12, - [1][1][2][0][RTW89_ETSI][50] = 127, - [1][1][2][0][RTW89_KCC][50] = 28, - [1][1][2][0][RTW89_FCC][54] = 10, - [1][1][2][0][RTW89_ETSI][54] = 127, - [1][1][2][0][RTW89_KCC][54] = 28, - [1][1][2][0][RTW89_FCC][58] = 10, - [1][1][2][0][RTW89_ETSI][58] = 127, - [1][1][2][0][RTW89_KCC][58] = 28, - [1][1][2][0][RTW89_FCC][61] = 10, - [1][1][2][0][RTW89_ETSI][61] = 127, - [1][1][2][0][RTW89_KCC][61] = 28, - [1][1][2][0][RTW89_FCC][65] = 10, - [1][1][2][0][RTW89_ETSI][65] = 127, - [1][1][2][0][RTW89_KCC][65] = 28, - [1][1][2][0][RTW89_FCC][69] = 10, - [1][1][2][0][RTW89_ETSI][69] = 127, - [1][1][2][0][RTW89_KCC][69] = 28, - [1][1][2][0][RTW89_FCC][73] = 10, - [1][1][2][0][RTW89_ETSI][73] = 127, - [1][1][2][0][RTW89_KCC][73] = 28, - [1][1][2][0][RTW89_FCC][76] = 10, - [1][1][2][0][RTW89_ETSI][76] = 127, - [1][1][2][0][RTW89_KCC][76] = 28, - [1][1][2][0][RTW89_FCC][80] = 10, - [1][1][2][0][RTW89_ETSI][80] = 127, - [1][1][2][0][RTW89_KCC][80] = 32, - [1][1][2][0][RTW89_FCC][84] = 10, - [1][1][2][0][RTW89_ETSI][84] = 127, - [1][1][2][0][RTW89_KCC][84] = 32, - [1][1][2][0][RTW89_FCC][88] = 10, - [1][1][2][0][RTW89_ETSI][88] = 127, - [1][1][2][0][RTW89_KCC][88] = 32, - [1][1][2][0][RTW89_FCC][91] = 12, - [1][1][2][0][RTW89_ETSI][91] = 127, - [1][1][2][0][RTW89_KCC][91] = 32, - [1][1][2][0][RTW89_FCC][95] = 10, - [1][1][2][0][RTW89_ETSI][95] = 127, - [1][1][2][0][RTW89_KCC][95] = 32, - [1][1][2][0][RTW89_FCC][99] = 10, - [1][1][2][0][RTW89_ETSI][99] = 127, - [1][1][2][0][RTW89_KCC][99] = 32, - [1][1][2][0][RTW89_FCC][103] = 10, - [1][1][2][0][RTW89_ETSI][103] = 127, - [1][1][2][0][RTW89_KCC][103] = 32, - [1][1][2][0][RTW89_FCC][106] = 12, - [1][1][2][0][RTW89_ETSI][106] = 127, - [1][1][2][0][RTW89_KCC][106] = 32, - [1][1][2][0][RTW89_FCC][110] = 127, - [1][1][2][0][RTW89_ETSI][110] = 127, - [1][1][2][0][RTW89_KCC][110] = 127, - [1][1][2][0][RTW89_FCC][114] = 127, - [1][1][2][0][RTW89_ETSI][114] = 127, - [1][1][2][0][RTW89_KCC][114] = 127, - [1][1][2][0][RTW89_FCC][118] = 127, - [1][1][2][0][RTW89_ETSI][118] = 127, - [1][1][2][0][RTW89_KCC][118] = 127, - [1][1][2][1][RTW89_FCC][1] = 10, - [1][1][2][1][RTW89_ETSI][1] = 42, - [1][1][2][1][RTW89_KCC][1] = 28, - [1][1][2][1][RTW89_FCC][5] = 10, - [1][1][2][1][RTW89_ETSI][5] = 42, - [1][1][2][1][RTW89_KCC][5] = 28, - [1][1][2][1][RTW89_FCC][9] = 10, - [1][1][2][1][RTW89_ETSI][9] = 42, - [1][1][2][1][RTW89_KCC][9] = 28, - [1][1][2][1][RTW89_FCC][13] = 10, - [1][1][2][1][RTW89_ETSI][13] = 42, - [1][1][2][1][RTW89_KCC][13] = 28, - [1][1][2][1][RTW89_FCC][16] = 10, - [1][1][2][1][RTW89_ETSI][16] = 42, - [1][1][2][1][RTW89_KCC][16] = 28, - [1][1][2][1][RTW89_FCC][20] = 10, - [1][1][2][1][RTW89_ETSI][20] = 42, - [1][1][2][1][RTW89_KCC][20] = 28, - [1][1][2][1][RTW89_FCC][24] = 10, - [1][1][2][1][RTW89_ETSI][24] = 42, - [1][1][2][1][RTW89_KCC][24] = 28, - [1][1][2][1][RTW89_FCC][28] = 10, - [1][1][2][1][RTW89_ETSI][28] = 42, - [1][1][2][1][RTW89_KCC][28] = 28, - [1][1][2][1][RTW89_FCC][31] = 10, - [1][1][2][1][RTW89_ETSI][31] = 42, - [1][1][2][1][RTW89_KCC][31] = 28, - [1][1][2][1][RTW89_FCC][35] = 10, - [1][1][2][1][RTW89_ETSI][35] = 42, - [1][1][2][1][RTW89_KCC][35] = 28, - [1][1][2][1][RTW89_FCC][39] = 10, - [1][1][2][1][RTW89_ETSI][39] = 42, - [1][1][2][1][RTW89_KCC][39] = 28, - [1][1][2][1][RTW89_FCC][43] = 10, - [1][1][2][1][RTW89_ETSI][43] = 42, - [1][1][2][1][RTW89_KCC][43] = 28, - [1][1][2][1][RTW89_FCC][46] = 12, - [1][1][2][1][RTW89_ETSI][46] = 127, - [1][1][2][1][RTW89_KCC][46] = 28, - [1][1][2][1][RTW89_FCC][50] = 12, - [1][1][2][1][RTW89_ETSI][50] = 127, - [1][1][2][1][RTW89_KCC][50] = 28, - [1][1][2][1][RTW89_FCC][54] = 10, - [1][1][2][1][RTW89_ETSI][54] = 127, - [1][1][2][1][RTW89_KCC][54] = 28, - [1][1][2][1][RTW89_FCC][58] = 10, - [1][1][2][1][RTW89_ETSI][58] = 127, - [1][1][2][1][RTW89_KCC][58] = 28, - [1][1][2][1][RTW89_FCC][61] = 10, - [1][1][2][1][RTW89_ETSI][61] = 127, - [1][1][2][1][RTW89_KCC][61] = 28, - [1][1][2][1][RTW89_FCC][65] = 10, - [1][1][2][1][RTW89_ETSI][65] = 127, - [1][1][2][1][RTW89_KCC][65] = 28, - [1][1][2][1][RTW89_FCC][69] = 10, - [1][1][2][1][RTW89_ETSI][69] = 127, - [1][1][2][1][RTW89_KCC][69] = 28, - [1][1][2][1][RTW89_FCC][73] = 10, - [1][1][2][1][RTW89_ETSI][73] = 127, - [1][1][2][1][RTW89_KCC][73] = 28, - [1][1][2][1][RTW89_FCC][76] = 10, - [1][1][2][1][RTW89_ETSI][76] = 127, - [1][1][2][1][RTW89_KCC][76] = 28, - [1][1][2][1][RTW89_FCC][80] = 10, - [1][1][2][1][RTW89_ETSI][80] = 127, - [1][1][2][1][RTW89_KCC][80] = 32, - [1][1][2][1][RTW89_FCC][84] = 10, - [1][1][2][1][RTW89_ETSI][84] = 127, - [1][1][2][1][RTW89_KCC][84] = 32, - [1][1][2][1][RTW89_FCC][88] = 10, - [1][1][2][1][RTW89_ETSI][88] = 127, - [1][1][2][1][RTW89_KCC][88] = 32, - [1][1][2][1][RTW89_FCC][91] = 12, - [1][1][2][1][RTW89_ETSI][91] = 127, - [1][1][2][1][RTW89_KCC][91] = 32, - [1][1][2][1][RTW89_FCC][95] = 10, - [1][1][2][1][RTW89_ETSI][95] = 127, - [1][1][2][1][RTW89_KCC][95] = 32, - [1][1][2][1][RTW89_FCC][99] = 10, - [1][1][2][1][RTW89_ETSI][99] = 127, - [1][1][2][1][RTW89_KCC][99] = 32, - [1][1][2][1][RTW89_FCC][103] = 10, - [1][1][2][1][RTW89_ETSI][103] = 127, - [1][1][2][1][RTW89_KCC][103] = 32, - [1][1][2][1][RTW89_FCC][106] = 12, - [1][1][2][1][RTW89_ETSI][106] = 127, - [1][1][2][1][RTW89_KCC][106] = 32, - [1][1][2][1][RTW89_FCC][110] = 127, - [1][1][2][1][RTW89_ETSI][110] = 127, - [1][1][2][1][RTW89_KCC][110] = 127, - [1][1][2][1][RTW89_FCC][114] = 127, - [1][1][2][1][RTW89_ETSI][114] = 127, - [1][1][2][1][RTW89_KCC][114] = 127, - [1][1][2][1][RTW89_FCC][118] = 127, - [1][1][2][1][RTW89_ETSI][118] = 127, - [1][1][2][1][RTW89_KCC][118] = 127, - [2][0][2][0][RTW89_FCC][3] = 46, - [2][0][2][0][RTW89_ETSI][3] = 48, - [2][0][2][0][RTW89_KCC][3] = 50, - [2][0][2][0][RTW89_FCC][11] = 46, - [2][0][2][0][RTW89_ETSI][11] = 48, - [2][0][2][0][RTW89_KCC][11] = 50, - [2][0][2][0][RTW89_FCC][18] = 46, - [2][0][2][0][RTW89_ETSI][18] = 48, - [2][0][2][0][RTW89_KCC][18] = 50, - [2][0][2][0][RTW89_FCC][26] = 46, - [2][0][2][0][RTW89_ETSI][26] = 48, - [2][0][2][0][RTW89_KCC][26] = 50, - [2][0][2][0][RTW89_FCC][33] = 46, - [2][0][2][0][RTW89_ETSI][33] = 48, - [2][0][2][0][RTW89_KCC][33] = 50, - [2][0][2][0][RTW89_FCC][41] = 46, - [2][0][2][0][RTW89_ETSI][41] = 48, - [2][0][2][0][RTW89_KCC][41] = 50, - [2][0][2][0][RTW89_FCC][48] = 46, - [2][0][2][0][RTW89_ETSI][48] = 127, - [2][0][2][0][RTW89_KCC][48] = 48, - [2][0][2][0][RTW89_FCC][56] = 46, - [2][0][2][0][RTW89_ETSI][56] = 127, - [2][0][2][0][RTW89_KCC][56] = 48, - [2][0][2][0][RTW89_FCC][63] = 46, - [2][0][2][0][RTW89_ETSI][63] = 127, - [2][0][2][0][RTW89_KCC][63] = 48, - [2][0][2][0][RTW89_FCC][71] = 46, - [2][0][2][0][RTW89_ETSI][71] = 127, - [2][0][2][0][RTW89_KCC][71] = 48, - [2][0][2][0][RTW89_FCC][78] = 46, - [2][0][2][0][RTW89_ETSI][78] = 127, - [2][0][2][0][RTW89_KCC][78] = 52, - [2][0][2][0][RTW89_FCC][86] = 46, - [2][0][2][0][RTW89_ETSI][86] = 127, - [2][0][2][0][RTW89_KCC][86] = 52, - [2][0][2][0][RTW89_FCC][93] = 46, - [2][0][2][0][RTW89_ETSI][93] = 127, - [2][0][2][0][RTW89_KCC][93] = 50, - [2][0][2][0][RTW89_FCC][101] = 44, - [2][0][2][0][RTW89_ETSI][101] = 127, - [2][0][2][0][RTW89_KCC][101] = 50, - [2][0][2][0][RTW89_FCC][108] = 127, - [2][0][2][0][RTW89_ETSI][108] = 127, - [2][0][2][0][RTW89_KCC][108] = 127, - [2][0][2][0][RTW89_FCC][116] = 127, - [2][0][2][0][RTW89_ETSI][116] = 127, - [2][0][2][0][RTW89_KCC][116] = 127, - [2][1][2][0][RTW89_FCC][3] = 22, - [2][1][2][0][RTW89_ETSI][3] = 48, - [2][1][2][0][RTW89_KCC][3] = 38, - [2][1][2][0][RTW89_FCC][11] = 20, - [2][1][2][0][RTW89_ETSI][11] = 48, - [2][1][2][0][RTW89_KCC][11] = 38, - [2][1][2][0][RTW89_FCC][18] = 20, - [2][1][2][0][RTW89_ETSI][18] = 48, - [2][1][2][0][RTW89_KCC][18] = 38, - [2][1][2][0][RTW89_FCC][26] = 20, - [2][1][2][0][RTW89_ETSI][26] = 48, - [2][1][2][0][RTW89_KCC][26] = 38, - [2][1][2][0][RTW89_FCC][33] = 20, - [2][1][2][0][RTW89_ETSI][33] = 48, - [2][1][2][0][RTW89_KCC][33] = 38, - [2][1][2][0][RTW89_FCC][41] = 22, - [2][1][2][0][RTW89_ETSI][41] = 48, - [2][1][2][0][RTW89_KCC][41] = 38, - [2][1][2][0][RTW89_FCC][48] = 22, - [2][1][2][0][RTW89_ETSI][48] = 127, - [2][1][2][0][RTW89_KCC][48] = 38, - [2][1][2][0][RTW89_FCC][56] = 20, - [2][1][2][0][RTW89_ETSI][56] = 127, - [2][1][2][0][RTW89_KCC][56] = 38, - [2][1][2][0][RTW89_FCC][63] = 22, - [2][1][2][0][RTW89_ETSI][63] = 127, - [2][1][2][0][RTW89_KCC][63] = 38, - [2][1][2][0][RTW89_FCC][71] = 20, - [2][1][2][0][RTW89_ETSI][71] = 127, - [2][1][2][0][RTW89_KCC][71] = 38, - [2][1][2][0][RTW89_FCC][78] = 20, - [2][1][2][0][RTW89_ETSI][78] = 127, - [2][1][2][0][RTW89_KCC][78] = 38, - [2][1][2][0][RTW89_FCC][86] = 20, - [2][1][2][0][RTW89_ETSI][86] = 127, - [2][1][2][0][RTW89_KCC][86] = 38, - [2][1][2][0][RTW89_FCC][93] = 22, - [2][1][2][0][RTW89_ETSI][93] = 127, - [2][1][2][0][RTW89_KCC][93] = 38, - [2][1][2][0][RTW89_FCC][101] = 22, - [2][1][2][0][RTW89_ETSI][101] = 127, - [2][1][2][0][RTW89_KCC][101] = 38, - [2][1][2][0][RTW89_FCC][108] = 127, - [2][1][2][0][RTW89_ETSI][108] = 127, - [2][1][2][0][RTW89_KCC][108] = 127, - [2][1][2][0][RTW89_FCC][116] = 127, - [2][1][2][0][RTW89_ETSI][116] = 127, - [2][1][2][0][RTW89_KCC][116] = 127, - [2][1][2][1][RTW89_FCC][3] = 22, - [2][1][2][1][RTW89_ETSI][3] = 42, - [2][1][2][1][RTW89_KCC][3] = 38, - [2][1][2][1][RTW89_FCC][11] = 20, - [2][1][2][1][RTW89_ETSI][11] = 42, - [2][1][2][1][RTW89_KCC][11] = 38, - [2][1][2][1][RTW89_FCC][18] = 20, - [2][1][2][1][RTW89_ETSI][18] = 42, - [2][1][2][1][RTW89_KCC][18] = 38, - [2][1][2][1][RTW89_FCC][26] = 20, - [2][1][2][1][RTW89_ETSI][26] = 42, - [2][1][2][1][RTW89_KCC][26] = 38, - [2][1][2][1][RTW89_FCC][33] = 20, - [2][1][2][1][RTW89_ETSI][33] = 42, - [2][1][2][1][RTW89_KCC][33] = 38, - [2][1][2][1][RTW89_FCC][41] = 22, - [2][1][2][1][RTW89_ETSI][41] = 42, - [2][1][2][1][RTW89_KCC][41] = 38, - [2][1][2][1][RTW89_FCC][48] = 22, - [2][1][2][1][RTW89_ETSI][48] = 127, - [2][1][2][1][RTW89_KCC][48] = 38, - [2][1][2][1][RTW89_FCC][56] = 20, - [2][1][2][1][RTW89_ETSI][56] = 127, - [2][1][2][1][RTW89_KCC][56] = 38, - [2][1][2][1][RTW89_FCC][63] = 22, - [2][1][2][1][RTW89_ETSI][63] = 127, - [2][1][2][1][RTW89_KCC][63] = 38, - [2][1][2][1][RTW89_FCC][71] = 20, - [2][1][2][1][RTW89_ETSI][71] = 127, - [2][1][2][1][RTW89_KCC][71] = 38, - [2][1][2][1][RTW89_FCC][78] = 20, - [2][1][2][1][RTW89_ETSI][78] = 127, - [2][1][2][1][RTW89_KCC][78] = 38, - [2][1][2][1][RTW89_FCC][86] = 20, - [2][1][2][1][RTW89_ETSI][86] = 127, - [2][1][2][1][RTW89_KCC][86] = 38, - [2][1][2][1][RTW89_FCC][93] = 22, - [2][1][2][1][RTW89_ETSI][93] = 127, - [2][1][2][1][RTW89_KCC][93] = 38, - [2][1][2][1][RTW89_FCC][101] = 22, - [2][1][2][1][RTW89_ETSI][101] = 127, - [2][1][2][1][RTW89_KCC][101] = 38, - [2][1][2][1][RTW89_FCC][108] = 127, - [2][1][2][1][RTW89_ETSI][108] = 127, - [2][1][2][1][RTW89_KCC][108] = 127, - [2][1][2][1][RTW89_FCC][116] = 127, - [2][1][2][1][RTW89_ETSI][116] = 127, - [2][1][2][1][RTW89_KCC][116] = 127, - [3][0][2][0][RTW89_FCC][7] = 52, - [3][0][2][0][RTW89_ETSI][7] = 38, - [3][0][2][0][RTW89_KCC][7] = 42, - [3][0][2][0][RTW89_FCC][22] = 52, - [3][0][2][0][RTW89_ETSI][22] = 38, - [3][0][2][0][RTW89_KCC][22] = 42, - [3][0][2][0][RTW89_FCC][37] = 52, - [3][0][2][0][RTW89_ETSI][37] = 38, - [3][0][2][0][RTW89_KCC][37] = 42, - [3][0][2][0][RTW89_FCC][52] = 54, - [3][0][2][0][RTW89_ETSI][52] = 127, - [3][0][2][0][RTW89_KCC][52] = 56, - [3][0][2][0][RTW89_FCC][67] = 54, - [3][0][2][0][RTW89_ETSI][67] = 127, - [3][0][2][0][RTW89_KCC][67] = 54, - [3][0][2][0][RTW89_FCC][82] = 54, - [3][0][2][0][RTW89_ETSI][82] = 127, - [3][0][2][0][RTW89_KCC][82] = 26, - [3][0][2][0][RTW89_FCC][97] = 40, - [3][0][2][0][RTW89_ETSI][97] = 127, - [3][0][2][0][RTW89_KCC][97] = 26, - [3][0][2][0][RTW89_FCC][112] = 127, - [3][0][2][0][RTW89_ETSI][112] = 127, - [3][0][2][0][RTW89_KCC][112] = 127, - [3][1][2][0][RTW89_FCC][7] = 32, - [3][1][2][0][RTW89_ETSI][7] = 38, - [3][1][2][0][RTW89_KCC][7] = 40, - [3][1][2][0][RTW89_FCC][22] = 30, - [3][1][2][0][RTW89_ETSI][22] = 38, - [3][1][2][0][RTW89_KCC][22] = 40, - [3][1][2][0][RTW89_FCC][37] = 30, - [3][1][2][0][RTW89_ETSI][37] = 38, - [3][1][2][0][RTW89_KCC][37] = 40, - [3][1][2][0][RTW89_FCC][52] = 30, - [3][1][2][0][RTW89_ETSI][52] = 127, - [3][1][2][0][RTW89_KCC][52] = 48, - [3][1][2][0][RTW89_FCC][67] = 32, - [3][1][2][0][RTW89_ETSI][67] = 127, - [3][1][2][0][RTW89_KCC][67] = 48, - [3][1][2][0][RTW89_FCC][82] = 32, - [3][1][2][0][RTW89_ETSI][82] = 127, - [3][1][2][0][RTW89_KCC][82] = 24, - [3][1][2][0][RTW89_FCC][97] = 14, - [3][1][2][0][RTW89_ETSI][97] = 127, - [3][1][2][0][RTW89_KCC][97] = 24, - [3][1][2][0][RTW89_FCC][112] = 127, - [3][1][2][0][RTW89_ETSI][112] = 127, - [3][1][2][0][RTW89_KCC][112] = 127, - [3][1][2][1][RTW89_FCC][7] = 32, - [3][1][2][1][RTW89_ETSI][7] = 38, - [3][1][2][1][RTW89_KCC][7] = 40, - [3][1][2][1][RTW89_FCC][22] = 30, - [3][1][2][1][RTW89_ETSI][22] = 38, - [3][1][2][1][RTW89_KCC][22] = 40, - [3][1][2][1][RTW89_FCC][37] = 30, - [3][1][2][1][RTW89_ETSI][37] = 38, - [3][1][2][1][RTW89_KCC][37] = 40, - [3][1][2][1][RTW89_FCC][52] = 30, - [3][1][2][1][RTW89_ETSI][52] = 127, - [3][1][2][1][RTW89_KCC][52] = 48, - [3][1][2][1][RTW89_FCC][67] = 32, - [3][1][2][1][RTW89_ETSI][67] = 127, - [3][1][2][1][RTW89_KCC][67] = 48, - [3][1][2][1][RTW89_FCC][82] = 32, - [3][1][2][1][RTW89_ETSI][82] = 127, - [3][1][2][1][RTW89_KCC][82] = 24, - [3][1][2][1][RTW89_FCC][97] = 14, - [3][1][2][1][RTW89_ETSI][97] = 127, - [3][1][2][1][RTW89_KCC][97] = 24, - [3][1][2][1][RTW89_FCC][112] = 127, - [3][1][2][1][RTW89_ETSI][112] = 127, - [3][1][2][1][RTW89_KCC][112] = 127, + [RTW89_REGD_NUM][NUM_OF_RTW89_REG_6GHZ_POWER] + [RTW89_6G_CH_NUM] = { + [0][0][1][0][RTW89_WW][0][0] = 24, + [0][0][1][0][RTW89_WW][1][0] = 24, + [0][0][1][0][RTW89_WW][2][0] = 56, + [0][0][1][0][RTW89_WW][0][2] = 22, + [0][0][1][0][RTW89_WW][1][2] = 22, + [0][0][1][0][RTW89_WW][2][2] = 56, + [0][0][1][0][RTW89_WW][0][4] = 22, + [0][0][1][0][RTW89_WW][1][4] = 22, + [0][0][1][0][RTW89_WW][2][4] = 56, + [0][0][1][0][RTW89_WW][0][6] = 22, + [0][0][1][0][RTW89_WW][1][6] = 22, + [0][0][1][0][RTW89_WW][2][6] = 56, + [0][0][1][0][RTW89_WW][0][8] = 22, + [0][0][1][0][RTW89_WW][1][8] = 22, + [0][0][1][0][RTW89_WW][2][8] = 56, + [0][0][1][0][RTW89_WW][0][10] = 22, + [0][0][1][0][RTW89_WW][1][10] = 22, + [0][0][1][0][RTW89_WW][2][10] = 56, + [0][0][1][0][RTW89_WW][0][12] = 22, + [0][0][1][0][RTW89_WW][1][12] = 22, + [0][0][1][0][RTW89_WW][2][12] = 56, + [0][0][1][0][RTW89_WW][0][14] = 22, + [0][0][1][0][RTW89_WW][1][14] = 22, + [0][0][1][0][RTW89_WW][2][14] = 56, + [0][0][1][0][RTW89_WW][0][15] = 22, + [0][0][1][0][RTW89_WW][1][15] = 22, + [0][0][1][0][RTW89_WW][2][15] = 56, + [0][0][1][0][RTW89_WW][0][17] = 22, + [0][0][1][0][RTW89_WW][1][17] = 22, + [0][0][1][0][RTW89_WW][2][17] = 56, + [0][0][1][0][RTW89_WW][0][19] = 22, + [0][0][1][0][RTW89_WW][1][19] = 22, + [0][0][1][0][RTW89_WW][2][19] = 56, + [0][0][1][0][RTW89_WW][0][21] = 22, + [0][0][1][0][RTW89_WW][1][21] = 22, + [0][0][1][0][RTW89_WW][2][21] = 56, + [0][0][1][0][RTW89_WW][0][23] = 22, + [0][0][1][0][RTW89_WW][1][23] = 22, + [0][0][1][0][RTW89_WW][2][23] = 70, + [0][0][1][0][RTW89_WW][0][25] = 22, + [0][0][1][0][RTW89_WW][1][25] = 22, + [0][0][1][0][RTW89_WW][2][25] = 70, + [0][0][1][0][RTW89_WW][0][27] = 22, + [0][0][1][0][RTW89_WW][1][27] = 22, + [0][0][1][0][RTW89_WW][2][27] = 70, + [0][0][1][0][RTW89_WW][0][29] = 22, + [0][0][1][0][RTW89_WW][1][29] = 22, + [0][0][1][0][RTW89_WW][2][29] = 70, + [0][0][1][0][RTW89_WW][0][30] = 22, + [0][0][1][0][RTW89_WW][1][30] = 22, + [0][0][1][0][RTW89_WW][2][30] = 70, + [0][0][1][0][RTW89_WW][0][32] = 22, + [0][0][1][0][RTW89_WW][1][32] = 22, + [0][0][1][0][RTW89_WW][2][32] = 70, + [0][0][1][0][RTW89_WW][0][34] = 22, + [0][0][1][0][RTW89_WW][1][34] = 22, + [0][0][1][0][RTW89_WW][2][34] = 70, + [0][0][1][0][RTW89_WW][0][36] = 22, + [0][0][1][0][RTW89_WW][1][36] = 22, + [0][0][1][0][RTW89_WW][2][36] = 70, + [0][0][1][0][RTW89_WW][0][38] = 22, + [0][0][1][0][RTW89_WW][1][38] = 22, + [0][0][1][0][RTW89_WW][2][38] = 70, + [0][0][1][0][RTW89_WW][0][40] = 22, + [0][0][1][0][RTW89_WW][1][40] = 22, + [0][0][1][0][RTW89_WW][2][40] = 70, + [0][0][1][0][RTW89_WW][0][42] = 22, + [0][0][1][0][RTW89_WW][1][42] = 22, + [0][0][1][0][RTW89_WW][2][42] = 70, + [0][0][1][0][RTW89_WW][0][44] = 22, + [0][0][1][0][RTW89_WW][1][44] = 22, + [0][0][1][0][RTW89_WW][2][44] = 70, + [0][0][1][0][RTW89_WW][0][45] = 22, + [0][0][1][0][RTW89_WW][1][45] = 22, + [0][0][1][0][RTW89_WW][2][45] = 0, + [0][0][1][0][RTW89_WW][0][47] = 22, + [0][0][1][0][RTW89_WW][1][47] = 22, + [0][0][1][0][RTW89_WW][2][47] = 0, + [0][0][1][0][RTW89_WW][0][49] = 24, + [0][0][1][0][RTW89_WW][1][49] = 24, + [0][0][1][0][RTW89_WW][2][49] = 0, + [0][0][1][0][RTW89_WW][0][51] = 22, + [0][0][1][0][RTW89_WW][1][51] = 22, + [0][0][1][0][RTW89_WW][2][51] = 0, + [0][0][1][0][RTW89_WW][0][53] = 22, + [0][0][1][0][RTW89_WW][1][53] = 22, + [0][0][1][0][RTW89_WW][2][53] = 0, + [0][0][1][0][RTW89_WW][0][55] = 22, + [0][0][1][0][RTW89_WW][1][55] = 22, + [0][0][1][0][RTW89_WW][2][55] = 68, + [0][0][1][0][RTW89_WW][0][57] = 22, + [0][0][1][0][RTW89_WW][1][57] = 22, + [0][0][1][0][RTW89_WW][2][57] = 68, + [0][0][1][0][RTW89_WW][0][59] = 22, + [0][0][1][0][RTW89_WW][1][59] = 22, + [0][0][1][0][RTW89_WW][2][59] = 68, + [0][0][1][0][RTW89_WW][0][60] = 22, + [0][0][1][0][RTW89_WW][1][60] = 22, + [0][0][1][0][RTW89_WW][2][60] = 68, + [0][0][1][0][RTW89_WW][0][62] = 22, + [0][0][1][0][RTW89_WW][1][62] = 22, + [0][0][1][0][RTW89_WW][2][62] = 68, + [0][0][1][0][RTW89_WW][0][64] = 22, + [0][0][1][0][RTW89_WW][1][64] = 22, + [0][0][1][0][RTW89_WW][2][64] = 68, + [0][0][1][0][RTW89_WW][0][66] = 22, + [0][0][1][0][RTW89_WW][1][66] = 22, + [0][0][1][0][RTW89_WW][2][66] = 68, + [0][0][1][0][RTW89_WW][0][68] = 22, + [0][0][1][0][RTW89_WW][1][68] = 22, + [0][0][1][0][RTW89_WW][2][68] = 68, + [0][0][1][0][RTW89_WW][0][70] = 24, + [0][0][1][0][RTW89_WW][1][70] = 24, + [0][0][1][0][RTW89_WW][2][70] = 68, + [0][0][1][0][RTW89_WW][0][72] = 22, + [0][0][1][0][RTW89_WW][1][72] = 22, + [0][0][1][0][RTW89_WW][2][72] = 68, + [0][0][1][0][RTW89_WW][0][74] = 22, + [0][0][1][0][RTW89_WW][1][74] = 22, + [0][0][1][0][RTW89_WW][2][74] = 68, + [0][0][1][0][RTW89_WW][0][75] = 22, + [0][0][1][0][RTW89_WW][1][75] = 22, + [0][0][1][0][RTW89_WW][2][75] = 68, + [0][0][1][0][RTW89_WW][0][77] = 22, + [0][0][1][0][RTW89_WW][1][77] = 22, + [0][0][1][0][RTW89_WW][2][77] = 68, + [0][0][1][0][RTW89_WW][0][79] = 22, + [0][0][1][0][RTW89_WW][1][79] = 22, + [0][0][1][0][RTW89_WW][2][79] = 68, + [0][0][1][0][RTW89_WW][0][81] = 22, + [0][0][1][0][RTW89_WW][1][81] = 22, + [0][0][1][0][RTW89_WW][2][81] = 68, + [0][0][1][0][RTW89_WW][0][83] = 22, + [0][0][1][0][RTW89_WW][1][83] = 22, + [0][0][1][0][RTW89_WW][2][83] = 68, + [0][0][1][0][RTW89_WW][0][85] = 22, + [0][0][1][0][RTW89_WW][1][85] = 22, + [0][0][1][0][RTW89_WW][2][85] = 68, + [0][0][1][0][RTW89_WW][0][87] = 22, + [0][0][1][0][RTW89_WW][1][87] = 22, + [0][0][1][0][RTW89_WW][2][87] = 0, + [0][0][1][0][RTW89_WW][0][89] = 22, + [0][0][1][0][RTW89_WW][1][89] = 22, + [0][0][1][0][RTW89_WW][2][89] = 0, + [0][0][1][0][RTW89_WW][0][90] = 22, + [0][0][1][0][RTW89_WW][1][90] = 22, + [0][0][1][0][RTW89_WW][2][90] = 0, + [0][0][1][0][RTW89_WW][0][92] = 22, + [0][0][1][0][RTW89_WW][1][92] = 22, + [0][0][1][0][RTW89_WW][2][92] = 0, + [0][0][1][0][RTW89_WW][0][94] = 22, + [0][0][1][0][RTW89_WW][1][94] = 22, + [0][0][1][0][RTW89_WW][2][94] = 0, + [0][0][1][0][RTW89_WW][0][96] = 22, + [0][0][1][0][RTW89_WW][1][96] = 22, + [0][0][1][0][RTW89_WW][2][96] = 0, + [0][0][1][0][RTW89_WW][0][98] = 22, + [0][0][1][0][RTW89_WW][1][98] = 22, + [0][0][1][0][RTW89_WW][2][98] = 0, + [0][0][1][0][RTW89_WW][0][100] = 22, + [0][0][1][0][RTW89_WW][1][100] = 22, + [0][0][1][0][RTW89_WW][2][100] = 0, + [0][0][1][0][RTW89_WW][0][102] = 22, + [0][0][1][0][RTW89_WW][1][102] = 22, + [0][0][1][0][RTW89_WW][2][102] = 0, + [0][0][1][0][RTW89_WW][0][104] = 22, + [0][0][1][0][RTW89_WW][1][104] = 22, + [0][0][1][0][RTW89_WW][2][104] = 0, + [0][0][1][0][RTW89_WW][0][105] = 22, + [0][0][1][0][RTW89_WW][1][105] = 22, + [0][0][1][0][RTW89_WW][2][105] = 0, + [0][0][1][0][RTW89_WW][0][107] = 24, + [0][0][1][0][RTW89_WW][1][107] = 24, + [0][0][1][0][RTW89_WW][2][107] = 0, + [0][0][1][0][RTW89_WW][0][109] = 24, + [0][0][1][0][RTW89_WW][1][109] = 24, + [0][0][1][0][RTW89_WW][2][109] = 0, + [0][0][1][0][RTW89_WW][0][111] = 0, + [0][0][1][0][RTW89_WW][1][111] = 0, + [0][0][1][0][RTW89_WW][2][111] = 0, + [0][0][1][0][RTW89_WW][0][113] = 0, + [0][0][1][0][RTW89_WW][1][113] = 0, + [0][0][1][0][RTW89_WW][2][113] = 0, + [0][0][1][0][RTW89_WW][0][115] = 0, + [0][0][1][0][RTW89_WW][1][115] = 0, + [0][0][1][0][RTW89_WW][2][115] = 0, + [0][0][1][0][RTW89_WW][0][117] = 0, + [0][0][1][0][RTW89_WW][1][117] = 0, + [0][0][1][0][RTW89_WW][2][117] = 0, + [0][0][1][0][RTW89_WW][0][119] = 0, + [0][0][1][0][RTW89_WW][1][119] = 0, + [0][0][1][0][RTW89_WW][2][119] = 0, + [0][1][1][0][RTW89_WW][0][0] = -2, + [0][1][1][0][RTW89_WW][1][0] = -2, + [0][1][1][0][RTW89_WW][2][0] = 54, + [0][1][1][0][RTW89_WW][0][2] = -4, + [0][1][1][0][RTW89_WW][1][2] = -4, + [0][1][1][0][RTW89_WW][2][2] = 54, + [0][1][1][0][RTW89_WW][0][4] = -4, + [0][1][1][0][RTW89_WW][1][4] = -4, + [0][1][1][0][RTW89_WW][2][4] = 54, + [0][1][1][0][RTW89_WW][0][6] = -4, + [0][1][1][0][RTW89_WW][1][6] = -4, + [0][1][1][0][RTW89_WW][2][6] = 54, + [0][1][1][0][RTW89_WW][0][8] = -4, + [0][1][1][0][RTW89_WW][1][8] = -4, + [0][1][1][0][RTW89_WW][2][8] = 54, + [0][1][1][0][RTW89_WW][0][10] = -4, + [0][1][1][0][RTW89_WW][1][10] = -4, + [0][1][1][0][RTW89_WW][2][10] = 54, + [0][1][1][0][RTW89_WW][0][12] = -4, + [0][1][1][0][RTW89_WW][1][12] = -4, + [0][1][1][0][RTW89_WW][2][12] = 54, + [0][1][1][0][RTW89_WW][0][14] = -4, + [0][1][1][0][RTW89_WW][1][14] = -4, + [0][1][1][0][RTW89_WW][2][14] = 54, + [0][1][1][0][RTW89_WW][0][15] = -4, + [0][1][1][0][RTW89_WW][1][15] = -4, + [0][1][1][0][RTW89_WW][2][15] = 54, + [0][1][1][0][RTW89_WW][0][17] = -4, + [0][1][1][0][RTW89_WW][1][17] = -4, + [0][1][1][0][RTW89_WW][2][17] = 54, + [0][1][1][0][RTW89_WW][0][19] = -4, + [0][1][1][0][RTW89_WW][1][19] = -4, + [0][1][1][0][RTW89_WW][2][19] = 54, + [0][1][1][0][RTW89_WW][0][21] = -4, + [0][1][1][0][RTW89_WW][1][21] = -4, + [0][1][1][0][RTW89_WW][2][21] = 54, + [0][1][1][0][RTW89_WW][0][23] = -4, + [0][1][1][0][RTW89_WW][1][23] = -4, + [0][1][1][0][RTW89_WW][2][23] = 68, + [0][1][1][0][RTW89_WW][0][25] = -4, + [0][1][1][0][RTW89_WW][1][25] = -4, + [0][1][1][0][RTW89_WW][2][25] = 68, + [0][1][1][0][RTW89_WW][0][27] = -4, + [0][1][1][0][RTW89_WW][1][27] = -4, + [0][1][1][0][RTW89_WW][2][27] = 68, + [0][1][1][0][RTW89_WW][0][29] = -4, + [0][1][1][0][RTW89_WW][1][29] = -4, + [0][1][1][0][RTW89_WW][2][29] = 68, + [0][1][1][0][RTW89_WW][0][30] = -4, + [0][1][1][0][RTW89_WW][1][30] = -4, + [0][1][1][0][RTW89_WW][2][30] = 68, + [0][1][1][0][RTW89_WW][0][32] = -4, + [0][1][1][0][RTW89_WW][1][32] = -4, + [0][1][1][0][RTW89_WW][2][32] = 68, + [0][1][1][0][RTW89_WW][0][34] = -4, + [0][1][1][0][RTW89_WW][1][34] = -4, + [0][1][1][0][RTW89_WW][2][34] = 68, + [0][1][1][0][RTW89_WW][0][36] = -4, + [0][1][1][0][RTW89_WW][1][36] = -4, + [0][1][1][0][RTW89_WW][2][36] = 68, + [0][1][1][0][RTW89_WW][0][38] = -4, + [0][1][1][0][RTW89_WW][1][38] = -4, + [0][1][1][0][RTW89_WW][2][38] = 68, + [0][1][1][0][RTW89_WW][0][40] = -4, + [0][1][1][0][RTW89_WW][1][40] = -4, + [0][1][1][0][RTW89_WW][2][40] = 68, + [0][1][1][0][RTW89_WW][0][42] = -4, + [0][1][1][0][RTW89_WW][1][42] = -4, + [0][1][1][0][RTW89_WW][2][42] = 68, + [0][1][1][0][RTW89_WW][0][44] = -2, + [0][1][1][0][RTW89_WW][1][44] = -2, + [0][1][1][0][RTW89_WW][2][44] = 68, + [0][1][1][0][RTW89_WW][0][45] = -2, + [0][1][1][0][RTW89_WW][1][45] = -2, + [0][1][1][0][RTW89_WW][2][45] = 0, + [0][1][1][0][RTW89_WW][0][47] = -2, + [0][1][1][0][RTW89_WW][1][47] = -2, + [0][1][1][0][RTW89_WW][2][47] = 0, + [0][1][1][0][RTW89_WW][0][49] = -2, + [0][1][1][0][RTW89_WW][1][49] = -2, + [0][1][1][0][RTW89_WW][2][49] = 0, + [0][1][1][0][RTW89_WW][0][51] = -2, + [0][1][1][0][RTW89_WW][1][51] = -2, + [0][1][1][0][RTW89_WW][2][51] = 0, + [0][1][1][0][RTW89_WW][0][53] = -2, + [0][1][1][0][RTW89_WW][1][53] = -2, + [0][1][1][0][RTW89_WW][2][53] = 0, + [0][1][1][0][RTW89_WW][0][55] = -2, + [0][1][1][0][RTW89_WW][1][55] = -2, + [0][1][1][0][RTW89_WW][2][55] = 68, + [0][1][1][0][RTW89_WW][0][57] = -2, + [0][1][1][0][RTW89_WW][1][57] = -2, + [0][1][1][0][RTW89_WW][2][57] = 68, + [0][1][1][0][RTW89_WW][0][59] = -2, + [0][1][1][0][RTW89_WW][1][59] = -2, + [0][1][1][0][RTW89_WW][2][59] = 68, + [0][1][1][0][RTW89_WW][0][60] = -2, + [0][1][1][0][RTW89_WW][1][60] = -2, + [0][1][1][0][RTW89_WW][2][60] = 68, + [0][1][1][0][RTW89_WW][0][62] = -2, + [0][1][1][0][RTW89_WW][1][62] = -2, + [0][1][1][0][RTW89_WW][2][62] = 68, + [0][1][1][0][RTW89_WW][0][64] = -2, + [0][1][1][0][RTW89_WW][1][64] = -2, + [0][1][1][0][RTW89_WW][2][64] = 68, + [0][1][1][0][RTW89_WW][0][66] = -2, + [0][1][1][0][RTW89_WW][1][66] = -2, + [0][1][1][0][RTW89_WW][2][66] = 68, + [0][1][1][0][RTW89_WW][0][68] = -2, + [0][1][1][0][RTW89_WW][1][68] = -2, + [0][1][1][0][RTW89_WW][2][68] = 68, + [0][1][1][0][RTW89_WW][0][70] = -2, + [0][1][1][0][RTW89_WW][1][70] = -2, + [0][1][1][0][RTW89_WW][2][70] = 68, + [0][1][1][0][RTW89_WW][0][72] = -2, + [0][1][1][0][RTW89_WW][1][72] = -2, + [0][1][1][0][RTW89_WW][2][72] = 68, + [0][1][1][0][RTW89_WW][0][74] = -2, + [0][1][1][0][RTW89_WW][1][74] = -2, + [0][1][1][0][RTW89_WW][2][74] = 68, + [0][1][1][0][RTW89_WW][0][75] = -2, + [0][1][1][0][RTW89_WW][1][75] = -2, + [0][1][1][0][RTW89_WW][2][75] = 68, + [0][1][1][0][RTW89_WW][0][77] = -2, + [0][1][1][0][RTW89_WW][1][77] = -2, + [0][1][1][0][RTW89_WW][2][77] = 68, + [0][1][1][0][RTW89_WW][0][79] = -2, + [0][1][1][0][RTW89_WW][1][79] = -2, + [0][1][1][0][RTW89_WW][2][79] = 68, + [0][1][1][0][RTW89_WW][0][81] = -2, + [0][1][1][0][RTW89_WW][1][81] = -2, + [0][1][1][0][RTW89_WW][2][81] = 68, + [0][1][1][0][RTW89_WW][0][83] = -2, + [0][1][1][0][RTW89_WW][1][83] = -2, + [0][1][1][0][RTW89_WW][2][83] = 68, + [0][1][1][0][RTW89_WW][0][85] = -2, + [0][1][1][0][RTW89_WW][1][85] = -2, + [0][1][1][0][RTW89_WW][2][85] = 68, + [0][1][1][0][RTW89_WW][0][87] = -2, + [0][1][1][0][RTW89_WW][1][87] = -2, + [0][1][1][0][RTW89_WW][2][87] = 0, + [0][1][1][0][RTW89_WW][0][89] = -2, + [0][1][1][0][RTW89_WW][1][89] = -2, + [0][1][1][0][RTW89_WW][2][89] = 0, + [0][1][1][0][RTW89_WW][0][90] = -2, + [0][1][1][0][RTW89_WW][1][90] = -2, + [0][1][1][0][RTW89_WW][2][90] = 0, + [0][1][1][0][RTW89_WW][0][92] = -2, + [0][1][1][0][RTW89_WW][1][92] = -2, + [0][1][1][0][RTW89_WW][2][92] = 0, + [0][1][1][0][RTW89_WW][0][94] = -2, + [0][1][1][0][RTW89_WW][1][94] = -2, + [0][1][1][0][RTW89_WW][2][94] = 0, + [0][1][1][0][RTW89_WW][0][96] = -2, + [0][1][1][0][RTW89_WW][1][96] = -2, + [0][1][1][0][RTW89_WW][2][96] = 0, + [0][1][1][0][RTW89_WW][0][98] = -2, + [0][1][1][0][RTW89_WW][1][98] = -2, + [0][1][1][0][RTW89_WW][2][98] = 0, + [0][1][1][0][RTW89_WW][0][100] = -2, + [0][1][1][0][RTW89_WW][1][100] = -2, + [0][1][1][0][RTW89_WW][2][100] = 0, + [0][1][1][0][RTW89_WW][0][102] = -2, + [0][1][1][0][RTW89_WW][1][102] = -2, + [0][1][1][0][RTW89_WW][2][102] = 0, + [0][1][1][0][RTW89_WW][0][104] = -2, + [0][1][1][0][RTW89_WW][1][104] = -2, + [0][1][1][0][RTW89_WW][2][104] = 0, + [0][1][1][0][RTW89_WW][0][105] = -2, + [0][1][1][0][RTW89_WW][1][105] = -2, + [0][1][1][0][RTW89_WW][2][105] = 0, + [0][1][1][0][RTW89_WW][0][107] = 1, + [0][1][1][0][RTW89_WW][1][107] = 1, + [0][1][1][0][RTW89_WW][2][107] = 0, + [0][1][1][0][RTW89_WW][0][109] = 1, + [0][1][1][0][RTW89_WW][1][109] = 1, + [0][1][1][0][RTW89_WW][2][109] = 0, + [0][1][1][0][RTW89_WW][0][111] = 0, + [0][1][1][0][RTW89_WW][1][111] = 0, + [0][1][1][0][RTW89_WW][2][111] = 0, + [0][1][1][0][RTW89_WW][0][113] = 0, + [0][1][1][0][RTW89_WW][1][113] = 0, + [0][1][1][0][RTW89_WW][2][113] = 0, + [0][1][1][0][RTW89_WW][0][115] = 0, + [0][1][1][0][RTW89_WW][1][115] = 0, + [0][1][1][0][RTW89_WW][2][115] = 0, + [0][1][1][0][RTW89_WW][0][117] = 0, + [0][1][1][0][RTW89_WW][1][117] = 0, + [0][1][1][0][RTW89_WW][2][117] = 0, + [0][1][1][0][RTW89_WW][0][119] = 0, + [0][1][1][0][RTW89_WW][1][119] = 0, + [0][1][1][0][RTW89_WW][2][119] = 0, + [0][0][2][0][RTW89_WW][0][0] = 24, + [0][0][2][0][RTW89_WW][1][0] = 24, + [0][0][2][0][RTW89_WW][2][0] = 56, + [0][0][2][0][RTW89_WW][0][2] = 22, + [0][0][2][0][RTW89_WW][1][2] = 22, + [0][0][2][0][RTW89_WW][2][2] = 56, + [0][0][2][0][RTW89_WW][0][4] = 22, + [0][0][2][0][RTW89_WW][1][4] = 22, + [0][0][2][0][RTW89_WW][2][4] = 56, + [0][0][2][0][RTW89_WW][0][6] = 22, + [0][0][2][0][RTW89_WW][1][6] = 22, + [0][0][2][0][RTW89_WW][2][6] = 56, + [0][0][2][0][RTW89_WW][0][8] = 22, + [0][0][2][0][RTW89_WW][1][8] = 22, + [0][0][2][0][RTW89_WW][2][8] = 56, + [0][0][2][0][RTW89_WW][0][10] = 22, + [0][0][2][0][RTW89_WW][1][10] = 22, + [0][0][2][0][RTW89_WW][2][10] = 56, + [0][0][2][0][RTW89_WW][0][12] = 22, + [0][0][2][0][RTW89_WW][1][12] = 22, + [0][0][2][0][RTW89_WW][2][12] = 56, + [0][0][2][0][RTW89_WW][0][14] = 22, + [0][0][2][0][RTW89_WW][1][14] = 22, + [0][0][2][0][RTW89_WW][2][14] = 56, + [0][0][2][0][RTW89_WW][0][15] = 22, + [0][0][2][0][RTW89_WW][1][15] = 22, + [0][0][2][0][RTW89_WW][2][15] = 56, + [0][0][2][0][RTW89_WW][0][17] = 22, + [0][0][2][0][RTW89_WW][1][17] = 22, + [0][0][2][0][RTW89_WW][2][17] = 56, + [0][0][2][0][RTW89_WW][0][19] = 22, + [0][0][2][0][RTW89_WW][1][19] = 22, + [0][0][2][0][RTW89_WW][2][19] = 56, + [0][0][2][0][RTW89_WW][0][21] = 22, + [0][0][2][0][RTW89_WW][1][21] = 22, + [0][0][2][0][RTW89_WW][2][21] = 56, + [0][0][2][0][RTW89_WW][0][23] = 22, + [0][0][2][0][RTW89_WW][1][23] = 22, + [0][0][2][0][RTW89_WW][2][23] = 70, + [0][0][2][0][RTW89_WW][0][25] = 22, + [0][0][2][0][RTW89_WW][1][25] = 22, + [0][0][2][0][RTW89_WW][2][25] = 70, + [0][0][2][0][RTW89_WW][0][27] = 22, + [0][0][2][0][RTW89_WW][1][27] = 22, + [0][0][2][0][RTW89_WW][2][27] = 70, + [0][0][2][0][RTW89_WW][0][29] = 22, + [0][0][2][0][RTW89_WW][1][29] = 22, + [0][0][2][0][RTW89_WW][2][29] = 70, + [0][0][2][0][RTW89_WW][0][30] = 22, + [0][0][2][0][RTW89_WW][1][30] = 22, + [0][0][2][0][RTW89_WW][2][30] = 70, + [0][0][2][0][RTW89_WW][0][32] = 22, + [0][0][2][0][RTW89_WW][1][32] = 22, + [0][0][2][0][RTW89_WW][2][32] = 70, + [0][0][2][0][RTW89_WW][0][34] = 22, + [0][0][2][0][RTW89_WW][1][34] = 22, + [0][0][2][0][RTW89_WW][2][34] = 70, + [0][0][2][0][RTW89_WW][0][36] = 22, + [0][0][2][0][RTW89_WW][1][36] = 22, + [0][0][2][0][RTW89_WW][2][36] = 70, + [0][0][2][0][RTW89_WW][0][38] = 22, + [0][0][2][0][RTW89_WW][1][38] = 22, + [0][0][2][0][RTW89_WW][2][38] = 70, + [0][0][2][0][RTW89_WW][0][40] = 22, + [0][0][2][0][RTW89_WW][1][40] = 22, + [0][0][2][0][RTW89_WW][2][40] = 70, + [0][0][2][0][RTW89_WW][0][42] = 22, + [0][0][2][0][RTW89_WW][1][42] = 22, + [0][0][2][0][RTW89_WW][2][42] = 70, + [0][0][2][0][RTW89_WW][0][44] = 22, + [0][0][2][0][RTW89_WW][1][44] = 22, + [0][0][2][0][RTW89_WW][2][44] = 70, + [0][0][2][0][RTW89_WW][0][45] = 22, + [0][0][2][0][RTW89_WW][1][45] = 22, + [0][0][2][0][RTW89_WW][2][45] = 0, + [0][0][2][0][RTW89_WW][0][47] = 22, + [0][0][2][0][RTW89_WW][1][47] = 22, + [0][0][2][0][RTW89_WW][2][47] = 0, + [0][0][2][0][RTW89_WW][0][49] = 24, + [0][0][2][0][RTW89_WW][1][49] = 24, + [0][0][2][0][RTW89_WW][2][49] = 0, + [0][0][2][0][RTW89_WW][0][51] = 22, + [0][0][2][0][RTW89_WW][1][51] = 22, + [0][0][2][0][RTW89_WW][2][51] = 0, + [0][0][2][0][RTW89_WW][0][53] = 22, + [0][0][2][0][RTW89_WW][1][53] = 22, + [0][0][2][0][RTW89_WW][2][53] = 0, + [0][0][2][0][RTW89_WW][0][55] = 22, + [0][0][2][0][RTW89_WW][1][55] = 22, + [0][0][2][0][RTW89_WW][2][55] = 68, + [0][0][2][0][RTW89_WW][0][57] = 22, + [0][0][2][0][RTW89_WW][1][57] = 22, + [0][0][2][0][RTW89_WW][2][57] = 68, + [0][0][2][0][RTW89_WW][0][59] = 22, + [0][0][2][0][RTW89_WW][1][59] = 22, + [0][0][2][0][RTW89_WW][2][59] = 68, + [0][0][2][0][RTW89_WW][0][60] = 22, + [0][0][2][0][RTW89_WW][1][60] = 22, + [0][0][2][0][RTW89_WW][2][60] = 68, + [0][0][2][0][RTW89_WW][0][62] = 22, + [0][0][2][0][RTW89_WW][1][62] = 22, + [0][0][2][0][RTW89_WW][2][62] = 68, + [0][0][2][0][RTW89_WW][0][64] = 22, + [0][0][2][0][RTW89_WW][1][64] = 22, + [0][0][2][0][RTW89_WW][2][64] = 68, + [0][0][2][0][RTW89_WW][0][66] = 22, + [0][0][2][0][RTW89_WW][1][66] = 22, + [0][0][2][0][RTW89_WW][2][66] = 68, + [0][0][2][0][RTW89_WW][0][68] = 22, + [0][0][2][0][RTW89_WW][1][68] = 22, + [0][0][2][0][RTW89_WW][2][68] = 68, + [0][0][2][0][RTW89_WW][0][70] = 24, + [0][0][2][0][RTW89_WW][1][70] = 24, + [0][0][2][0][RTW89_WW][2][70] = 68, + [0][0][2][0][RTW89_WW][0][72] = 22, + [0][0][2][0][RTW89_WW][1][72] = 22, + [0][0][2][0][RTW89_WW][2][72] = 68, + [0][0][2][0][RTW89_WW][0][74] = 22, + [0][0][2][0][RTW89_WW][1][74] = 22, + [0][0][2][0][RTW89_WW][2][74] = 68, + [0][0][2][0][RTW89_WW][0][75] = 22, + [0][0][2][0][RTW89_WW][1][75] = 22, + [0][0][2][0][RTW89_WW][2][75] = 68, + [0][0][2][0][RTW89_WW][0][77] = 22, + [0][0][2][0][RTW89_WW][1][77] = 22, + [0][0][2][0][RTW89_WW][2][77] = 68, + [0][0][2][0][RTW89_WW][0][79] = 22, + [0][0][2][0][RTW89_WW][1][79] = 22, + [0][0][2][0][RTW89_WW][2][79] = 68, + [0][0][2][0][RTW89_WW][0][81] = 22, + [0][0][2][0][RTW89_WW][1][81] = 22, + [0][0][2][0][RTW89_WW][2][81] = 68, + [0][0][2][0][RTW89_WW][0][83] = 22, + [0][0][2][0][RTW89_WW][1][83] = 22, + [0][0][2][0][RTW89_WW][2][83] = 68, + [0][0][2][0][RTW89_WW][0][85] = 22, + [0][0][2][0][RTW89_WW][1][85] = 22, + [0][0][2][0][RTW89_WW][2][85] = 68, + [0][0][2][0][RTW89_WW][0][87] = 22, + [0][0][2][0][RTW89_WW][1][87] = 22, + [0][0][2][0][RTW89_WW][2][87] = 0, + [0][0][2][0][RTW89_WW][0][89] = 22, + [0][0][2][0][RTW89_WW][1][89] = 22, + [0][0][2][0][RTW89_WW][2][89] = 0, + [0][0][2][0][RTW89_WW][0][90] = 22, + [0][0][2][0][RTW89_WW][1][90] = 22, + [0][0][2][0][RTW89_WW][2][90] = 0, + [0][0][2][0][RTW89_WW][0][92] = 22, + [0][0][2][0][RTW89_WW][1][92] = 22, + [0][0][2][0][RTW89_WW][2][92] = 0, + [0][0][2][0][RTW89_WW][0][94] = 22, + [0][0][2][0][RTW89_WW][1][94] = 22, + [0][0][2][0][RTW89_WW][2][94] = 0, + [0][0][2][0][RTW89_WW][0][96] = 22, + [0][0][2][0][RTW89_WW][1][96] = 22, + [0][0][2][0][RTW89_WW][2][96] = 0, + [0][0][2][0][RTW89_WW][0][98] = 22, + [0][0][2][0][RTW89_WW][1][98] = 22, + [0][0][2][0][RTW89_WW][2][98] = 0, + [0][0][2][0][RTW89_WW][0][100] = 22, + [0][0][2][0][RTW89_WW][1][100] = 22, + [0][0][2][0][RTW89_WW][2][100] = 0, + [0][0][2][0][RTW89_WW][0][102] = 22, + [0][0][2][0][RTW89_WW][1][102] = 22, + [0][0][2][0][RTW89_WW][2][102] = 0, + [0][0][2][0][RTW89_WW][0][104] = 22, + [0][0][2][0][RTW89_WW][1][104] = 22, + [0][0][2][0][RTW89_WW][2][104] = 0, + [0][0][2][0][RTW89_WW][0][105] = 22, + [0][0][2][0][RTW89_WW][1][105] = 22, + [0][0][2][0][RTW89_WW][2][105] = 0, + [0][0][2][0][RTW89_WW][0][107] = 24, + [0][0][2][0][RTW89_WW][1][107] = 24, + [0][0][2][0][RTW89_WW][2][107] = 0, + [0][0][2][0][RTW89_WW][0][109] = 24, + [0][0][2][0][RTW89_WW][1][109] = 24, + [0][0][2][0][RTW89_WW][2][109] = 0, + [0][0][2][0][RTW89_WW][0][111] = 0, + [0][0][2][0][RTW89_WW][1][111] = 0, + [0][0][2][0][RTW89_WW][2][111] = 0, + [0][0][2][0][RTW89_WW][0][113] = 0, + [0][0][2][0][RTW89_WW][1][113] = 0, + [0][0][2][0][RTW89_WW][2][113] = 0, + [0][0][2][0][RTW89_WW][0][115] = 0, + [0][0][2][0][RTW89_WW][1][115] = 0, + [0][0][2][0][RTW89_WW][2][115] = 0, + [0][0][2][0][RTW89_WW][0][117] = 0, + [0][0][2][0][RTW89_WW][1][117] = 0, + [0][0][2][0][RTW89_WW][2][117] = 0, + [0][0][2][0][RTW89_WW][0][119] = 0, + [0][0][2][0][RTW89_WW][1][119] = 0, + [0][0][2][0][RTW89_WW][2][119] = 0, + [0][1][2][0][RTW89_WW][0][0] = -2, + [0][1][2][0][RTW89_WW][1][0] = -2, + [0][1][2][0][RTW89_WW][2][0] = 54, + [0][1][2][0][RTW89_WW][0][2] = -4, + [0][1][2][0][RTW89_WW][1][2] = -4, + [0][1][2][0][RTW89_WW][2][2] = 54, + [0][1][2][0][RTW89_WW][0][4] = -4, + [0][1][2][0][RTW89_WW][1][4] = -4, + [0][1][2][0][RTW89_WW][2][4] = 54, + [0][1][2][0][RTW89_WW][0][6] = -4, + [0][1][2][0][RTW89_WW][1][6] = -4, + [0][1][2][0][RTW89_WW][2][6] = 54, + [0][1][2][0][RTW89_WW][0][8] = -4, + [0][1][2][0][RTW89_WW][1][8] = -4, + [0][1][2][0][RTW89_WW][2][8] = 54, + [0][1][2][0][RTW89_WW][0][10] = -4, + [0][1][2][0][RTW89_WW][1][10] = -4, + [0][1][2][0][RTW89_WW][2][10] = 54, + [0][1][2][0][RTW89_WW][0][12] = -4, + [0][1][2][0][RTW89_WW][1][12] = -4, + [0][1][2][0][RTW89_WW][2][12] = 54, + [0][1][2][0][RTW89_WW][0][14] = -4, + [0][1][2][0][RTW89_WW][1][14] = -4, + [0][1][2][0][RTW89_WW][2][14] = 54, + [0][1][2][0][RTW89_WW][0][15] = -4, + [0][1][2][0][RTW89_WW][1][15] = -4, + [0][1][2][0][RTW89_WW][2][15] = 54, + [0][1][2][0][RTW89_WW][0][17] = -4, + [0][1][2][0][RTW89_WW][1][17] = -4, + [0][1][2][0][RTW89_WW][2][17] = 54, + [0][1][2][0][RTW89_WW][0][19] = -4, + [0][1][2][0][RTW89_WW][1][19] = -4, + [0][1][2][0][RTW89_WW][2][19] = 54, + [0][1][2][0][RTW89_WW][0][21] = -4, + [0][1][2][0][RTW89_WW][1][21] = -4, + [0][1][2][0][RTW89_WW][2][21] = 54, + [0][1][2][0][RTW89_WW][0][23] = -4, + [0][1][2][0][RTW89_WW][1][23] = -4, + [0][1][2][0][RTW89_WW][2][23] = 68, + [0][1][2][0][RTW89_WW][0][25] = -4, + [0][1][2][0][RTW89_WW][1][25] = -4, + [0][1][2][0][RTW89_WW][2][25] = 68, + [0][1][2][0][RTW89_WW][0][27] = -4, + [0][1][2][0][RTW89_WW][1][27] = -4, + [0][1][2][0][RTW89_WW][2][27] = 68, + [0][1][2][0][RTW89_WW][0][29] = -4, + [0][1][2][0][RTW89_WW][1][29] = -4, + [0][1][2][0][RTW89_WW][2][29] = 68, + [0][1][2][0][RTW89_WW][0][30] = -4, + [0][1][2][0][RTW89_WW][1][30] = -4, + [0][1][2][0][RTW89_WW][2][30] = 68, + [0][1][2][0][RTW89_WW][0][32] = -4, + [0][1][2][0][RTW89_WW][1][32] = -4, + [0][1][2][0][RTW89_WW][2][32] = 68, + [0][1][2][0][RTW89_WW][0][34] = -4, + [0][1][2][0][RTW89_WW][1][34] = -4, + [0][1][2][0][RTW89_WW][2][34] = 68, + [0][1][2][0][RTW89_WW][0][36] = -4, + [0][1][2][0][RTW89_WW][1][36] = -4, + [0][1][2][0][RTW89_WW][2][36] = 68, + [0][1][2][0][RTW89_WW][0][38] = -4, + [0][1][2][0][RTW89_WW][1][38] = -4, + [0][1][2][0][RTW89_WW][2][38] = 68, + [0][1][2][0][RTW89_WW][0][40] = -4, + [0][1][2][0][RTW89_WW][1][40] = -4, + [0][1][2][0][RTW89_WW][2][40] = 68, + [0][1][2][0][RTW89_WW][0][42] = -4, + [0][1][2][0][RTW89_WW][1][42] = -4, + [0][1][2][0][RTW89_WW][2][42] = 68, + [0][1][2][0][RTW89_WW][0][44] = -2, + [0][1][2][0][RTW89_WW][1][44] = -2, + [0][1][2][0][RTW89_WW][2][44] = 68, + [0][1][2][0][RTW89_WW][0][45] = -2, + [0][1][2][0][RTW89_WW][1][45] = -2, + [0][1][2][0][RTW89_WW][2][45] = 0, + [0][1][2][0][RTW89_WW][0][47] = -2, + [0][1][2][0][RTW89_WW][1][47] = -2, + [0][1][2][0][RTW89_WW][2][47] = 0, + [0][1][2][0][RTW89_WW][0][49] = -2, + [0][1][2][0][RTW89_WW][1][49] = -2, + [0][1][2][0][RTW89_WW][2][49] = 0, + [0][1][2][0][RTW89_WW][0][51] = -2, + [0][1][2][0][RTW89_WW][1][51] = -2, + [0][1][2][0][RTW89_WW][2][51] = 0, + [0][1][2][0][RTW89_WW][0][53] = -2, + [0][1][2][0][RTW89_WW][1][53] = -2, + [0][1][2][0][RTW89_WW][2][53] = 0, + [0][1][2][0][RTW89_WW][0][55] = -2, + [0][1][2][0][RTW89_WW][1][55] = -2, + [0][1][2][0][RTW89_WW][2][55] = 68, + [0][1][2][0][RTW89_WW][0][57] = -2, + [0][1][2][0][RTW89_WW][1][57] = -2, + [0][1][2][0][RTW89_WW][2][57] = 68, + [0][1][2][0][RTW89_WW][0][59] = -2, + [0][1][2][0][RTW89_WW][1][59] = -2, + [0][1][2][0][RTW89_WW][2][59] = 68, + [0][1][2][0][RTW89_WW][0][60] = -2, + [0][1][2][0][RTW89_WW][1][60] = -2, + [0][1][2][0][RTW89_WW][2][60] = 68, + [0][1][2][0][RTW89_WW][0][62] = -2, + [0][1][2][0][RTW89_WW][1][62] = -2, + [0][1][2][0][RTW89_WW][2][62] = 68, + [0][1][2][0][RTW89_WW][0][64] = -2, + [0][1][2][0][RTW89_WW][1][64] = -2, + [0][1][2][0][RTW89_WW][2][64] = 68, + [0][1][2][0][RTW89_WW][0][66] = -2, + [0][1][2][0][RTW89_WW][1][66] = -2, + [0][1][2][0][RTW89_WW][2][66] = 68, + [0][1][2][0][RTW89_WW][0][68] = -2, + [0][1][2][0][RTW89_WW][1][68] = -2, + [0][1][2][0][RTW89_WW][2][68] = 68, + [0][1][2][0][RTW89_WW][0][70] = -2, + [0][1][2][0][RTW89_WW][1][70] = -2, + [0][1][2][0][RTW89_WW][2][70] = 68, + [0][1][2][0][RTW89_WW][0][72] = -2, + [0][1][2][0][RTW89_WW][1][72] = -2, + [0][1][2][0][RTW89_WW][2][72] = 68, + [0][1][2][0][RTW89_WW][0][74] = -2, + [0][1][2][0][RTW89_WW][1][74] = -2, + [0][1][2][0][RTW89_WW][2][74] = 68, + [0][1][2][0][RTW89_WW][0][75] = -2, + [0][1][2][0][RTW89_WW][1][75] = -2, + [0][1][2][0][RTW89_WW][2][75] = 68, + [0][1][2][0][RTW89_WW][0][77] = -2, + [0][1][2][0][RTW89_WW][1][77] = -2, + [0][1][2][0][RTW89_WW][2][77] = 68, + [0][1][2][0][RTW89_WW][0][79] = -2, + [0][1][2][0][RTW89_WW][1][79] = -2, + [0][1][2][0][RTW89_WW][2][79] = 68, + [0][1][2][0][RTW89_WW][0][81] = -2, + [0][1][2][0][RTW89_WW][1][81] = -2, + [0][1][2][0][RTW89_WW][2][81] = 68, + [0][1][2][0][RTW89_WW][0][83] = -2, + [0][1][2][0][RTW89_WW][1][83] = -2, + [0][1][2][0][RTW89_WW][2][83] = 68, + [0][1][2][0][RTW89_WW][0][85] = -2, + [0][1][2][0][RTW89_WW][1][85] = -2, + [0][1][2][0][RTW89_WW][2][85] = 68, + [0][1][2][0][RTW89_WW][0][87] = -2, + [0][1][2][0][RTW89_WW][1][87] = -2, + [0][1][2][0][RTW89_WW][2][87] = 0, + [0][1][2][0][RTW89_WW][0][89] = -2, + [0][1][2][0][RTW89_WW][1][89] = -2, + [0][1][2][0][RTW89_WW][2][89] = 0, + [0][1][2][0][RTW89_WW][0][90] = -2, + [0][1][2][0][RTW89_WW][1][90] = -2, + [0][1][2][0][RTW89_WW][2][90] = 0, + [0][1][2][0][RTW89_WW][0][92] = -2, + [0][1][2][0][RTW89_WW][1][92] = -2, + [0][1][2][0][RTW89_WW][2][92] = 0, + [0][1][2][0][RTW89_WW][0][94] = -2, + [0][1][2][0][RTW89_WW][1][94] = -2, + [0][1][2][0][RTW89_WW][2][94] = 0, + [0][1][2][0][RTW89_WW][0][96] = -2, + [0][1][2][0][RTW89_WW][1][96] = -2, + [0][1][2][0][RTW89_WW][2][96] = 0, + [0][1][2][0][RTW89_WW][0][98] = -2, + [0][1][2][0][RTW89_WW][1][98] = -2, + [0][1][2][0][RTW89_WW][2][98] = 0, + [0][1][2][0][RTW89_WW][0][100] = -2, + [0][1][2][0][RTW89_WW][1][100] = -2, + [0][1][2][0][RTW89_WW][2][100] = 0, + [0][1][2][0][RTW89_WW][0][102] = -2, + [0][1][2][0][RTW89_WW][1][102] = -2, + [0][1][2][0][RTW89_WW][2][102] = 0, + [0][1][2][0][RTW89_WW][0][104] = -2, + [0][1][2][0][RTW89_WW][1][104] = -2, + [0][1][2][0][RTW89_WW][2][104] = 0, + [0][1][2][0][RTW89_WW][0][105] = -2, + [0][1][2][0][RTW89_WW][1][105] = -2, + [0][1][2][0][RTW89_WW][2][105] = 0, + [0][1][2][0][RTW89_WW][0][107] = 1, + [0][1][2][0][RTW89_WW][1][107] = 1, + [0][1][2][0][RTW89_WW][2][107] = 0, + [0][1][2][0][RTW89_WW][0][109] = 1, + [0][1][2][0][RTW89_WW][1][109] = 1, + [0][1][2][0][RTW89_WW][2][109] = 0, + [0][1][2][0][RTW89_WW][0][111] = 0, + [0][1][2][0][RTW89_WW][1][111] = 0, + [0][1][2][0][RTW89_WW][2][111] = 0, + [0][1][2][0][RTW89_WW][0][113] = 0, + [0][1][2][0][RTW89_WW][1][113] = 0, + [0][1][2][0][RTW89_WW][2][113] = 0, + [0][1][2][0][RTW89_WW][0][115] = 0, + [0][1][2][0][RTW89_WW][1][115] = 0, + [0][1][2][0][RTW89_WW][2][115] = 0, + [0][1][2][0][RTW89_WW][0][117] = 0, + [0][1][2][0][RTW89_WW][1][117] = 0, + [0][1][2][0][RTW89_WW][2][117] = 0, + [0][1][2][0][RTW89_WW][0][119] = 0, + [0][1][2][0][RTW89_WW][1][119] = 0, + [0][1][2][0][RTW89_WW][2][119] = 0, + [0][1][2][1][RTW89_WW][0][0] = -2, + [0][1][2][1][RTW89_WW][1][0] = -2, + [0][1][2][1][RTW89_WW][2][0] = 54, + [0][1][2][1][RTW89_WW][0][2] = -4, + [0][1][2][1][RTW89_WW][1][2] = -4, + [0][1][2][1][RTW89_WW][2][2] = 54, + [0][1][2][1][RTW89_WW][0][4] = -4, + [0][1][2][1][RTW89_WW][1][4] = -4, + [0][1][2][1][RTW89_WW][2][4] = 54, + [0][1][2][1][RTW89_WW][0][6] = -4, + [0][1][2][1][RTW89_WW][1][6] = -4, + [0][1][2][1][RTW89_WW][2][6] = 54, + [0][1][2][1][RTW89_WW][0][8] = -4, + [0][1][2][1][RTW89_WW][1][8] = -4, + [0][1][2][1][RTW89_WW][2][8] = 54, + [0][1][2][1][RTW89_WW][0][10] = -4, + [0][1][2][1][RTW89_WW][1][10] = -4, + [0][1][2][1][RTW89_WW][2][10] = 54, + [0][1][2][1][RTW89_WW][0][12] = -4, + [0][1][2][1][RTW89_WW][1][12] = -4, + [0][1][2][1][RTW89_WW][2][12] = 54, + [0][1][2][1][RTW89_WW][0][14] = -4, + [0][1][2][1][RTW89_WW][1][14] = -4, + [0][1][2][1][RTW89_WW][2][14] = 54, + [0][1][2][1][RTW89_WW][0][15] = -4, + [0][1][2][1][RTW89_WW][1][15] = -4, + [0][1][2][1][RTW89_WW][2][15] = 54, + [0][1][2][1][RTW89_WW][0][17] = -4, + [0][1][2][1][RTW89_WW][1][17] = -4, + [0][1][2][1][RTW89_WW][2][17] = 54, + [0][1][2][1][RTW89_WW][0][19] = -4, + [0][1][2][1][RTW89_WW][1][19] = -4, + [0][1][2][1][RTW89_WW][2][19] = 54, + [0][1][2][1][RTW89_WW][0][21] = -4, + [0][1][2][1][RTW89_WW][1][21] = -4, + [0][1][2][1][RTW89_WW][2][21] = 54, + [0][1][2][1][RTW89_WW][0][23] = -4, + [0][1][2][1][RTW89_WW][1][23] = -4, + [0][1][2][1][RTW89_WW][2][23] = 68, + [0][1][2][1][RTW89_WW][0][25] = -4, + [0][1][2][1][RTW89_WW][1][25] = -4, + [0][1][2][1][RTW89_WW][2][25] = 68, + [0][1][2][1][RTW89_WW][0][27] = -4, + [0][1][2][1][RTW89_WW][1][27] = -4, + [0][1][2][1][RTW89_WW][2][27] = 68, + [0][1][2][1][RTW89_WW][0][29] = -4, + [0][1][2][1][RTW89_WW][1][29] = -4, + [0][1][2][1][RTW89_WW][2][29] = 68, + [0][1][2][1][RTW89_WW][0][30] = -4, + [0][1][2][1][RTW89_WW][1][30] = -4, + [0][1][2][1][RTW89_WW][2][30] = 68, + [0][1][2][1][RTW89_WW][0][32] = -4, + [0][1][2][1][RTW89_WW][1][32] = -4, + [0][1][2][1][RTW89_WW][2][32] = 68, + [0][1][2][1][RTW89_WW][0][34] = -4, + [0][1][2][1][RTW89_WW][1][34] = -4, + [0][1][2][1][RTW89_WW][2][34] = 68, + [0][1][2][1][RTW89_WW][0][36] = -4, + [0][1][2][1][RTW89_WW][1][36] = -4, + [0][1][2][1][RTW89_WW][2][36] = 68, + [0][1][2][1][RTW89_WW][0][38] = -4, + [0][1][2][1][RTW89_WW][1][38] = -4, + [0][1][2][1][RTW89_WW][2][38] = 68, + [0][1][2][1][RTW89_WW][0][40] = -4, + [0][1][2][1][RTW89_WW][1][40] = -4, + [0][1][2][1][RTW89_WW][2][40] = 68, + [0][1][2][1][RTW89_WW][0][42] = -4, + [0][1][2][1][RTW89_WW][1][42] = -4, + [0][1][2][1][RTW89_WW][2][42] = 68, + [0][1][2][1][RTW89_WW][0][44] = -2, + [0][1][2][1][RTW89_WW][1][44] = -2, + [0][1][2][1][RTW89_WW][2][44] = 68, + [0][1][2][1][RTW89_WW][0][45] = -2, + [0][1][2][1][RTW89_WW][1][45] = -2, + [0][1][2][1][RTW89_WW][2][45] = 0, + [0][1][2][1][RTW89_WW][0][47] = -2, + [0][1][2][1][RTW89_WW][1][47] = -2, + [0][1][2][1][RTW89_WW][2][47] = 0, + [0][1][2][1][RTW89_WW][0][49] = -2, + [0][1][2][1][RTW89_WW][1][49] = -2, + [0][1][2][1][RTW89_WW][2][49] = 0, + [0][1][2][1][RTW89_WW][0][51] = -2, + [0][1][2][1][RTW89_WW][1][51] = -2, + [0][1][2][1][RTW89_WW][2][51] = 0, + [0][1][2][1][RTW89_WW][0][53] = -2, + [0][1][2][1][RTW89_WW][1][53] = -2, + [0][1][2][1][RTW89_WW][2][53] = 0, + [0][1][2][1][RTW89_WW][0][55] = -2, + [0][1][2][1][RTW89_WW][1][55] = -2, + [0][1][2][1][RTW89_WW][2][55] = 68, + [0][1][2][1][RTW89_WW][0][57] = -2, + [0][1][2][1][RTW89_WW][1][57] = -2, + [0][1][2][1][RTW89_WW][2][57] = 68, + [0][1][2][1][RTW89_WW][0][59] = -2, + [0][1][2][1][RTW89_WW][1][59] = -2, + [0][1][2][1][RTW89_WW][2][59] = 68, + [0][1][2][1][RTW89_WW][0][60] = -2, + [0][1][2][1][RTW89_WW][1][60] = -2, + [0][1][2][1][RTW89_WW][2][60] = 68, + [0][1][2][1][RTW89_WW][0][62] = -2, + [0][1][2][1][RTW89_WW][1][62] = -2, + [0][1][2][1][RTW89_WW][2][62] = 68, + [0][1][2][1][RTW89_WW][0][64] = -2, + [0][1][2][1][RTW89_WW][1][64] = -2, + [0][1][2][1][RTW89_WW][2][64] = 68, + [0][1][2][1][RTW89_WW][0][66] = -2, + [0][1][2][1][RTW89_WW][1][66] = -2, + [0][1][2][1][RTW89_WW][2][66] = 68, + [0][1][2][1][RTW89_WW][0][68] = -2, + [0][1][2][1][RTW89_WW][1][68] = -2, + [0][1][2][1][RTW89_WW][2][68] = 68, + [0][1][2][1][RTW89_WW][0][70] = -2, + [0][1][2][1][RTW89_WW][1][70] = -2, + [0][1][2][1][RTW89_WW][2][70] = 68, + [0][1][2][1][RTW89_WW][0][72] = -2, + [0][1][2][1][RTW89_WW][1][72] = -2, + [0][1][2][1][RTW89_WW][2][72] = 68, + [0][1][2][1][RTW89_WW][0][74] = -2, + [0][1][2][1][RTW89_WW][1][74] = -2, + [0][1][2][1][RTW89_WW][2][74] = 68, + [0][1][2][1][RTW89_WW][0][75] = -2, + [0][1][2][1][RTW89_WW][1][75] = -2, + [0][1][2][1][RTW89_WW][2][75] = 68, + [0][1][2][1][RTW89_WW][0][77] = -2, + [0][1][2][1][RTW89_WW][1][77] = -2, + [0][1][2][1][RTW89_WW][2][77] = 68, + [0][1][2][1][RTW89_WW][0][79] = -2, + [0][1][2][1][RTW89_WW][1][79] = -2, + [0][1][2][1][RTW89_WW][2][79] = 68, + [0][1][2][1][RTW89_WW][0][81] = -2, + [0][1][2][1][RTW89_WW][1][81] = -2, + [0][1][2][1][RTW89_WW][2][81] = 68, + [0][1][2][1][RTW89_WW][0][83] = -2, + [0][1][2][1][RTW89_WW][1][83] = -2, + [0][1][2][1][RTW89_WW][2][83] = 68, + [0][1][2][1][RTW89_WW][0][85] = -2, + [0][1][2][1][RTW89_WW][1][85] = -2, + [0][1][2][1][RTW89_WW][2][85] = 68, + [0][1][2][1][RTW89_WW][0][87] = -2, + [0][1][2][1][RTW89_WW][1][87] = -2, + [0][1][2][1][RTW89_WW][2][87] = 0, + [0][1][2][1][RTW89_WW][0][89] = -2, + [0][1][2][1][RTW89_WW][1][89] = -2, + [0][1][2][1][RTW89_WW][2][89] = 0, + [0][1][2][1][RTW89_WW][0][90] = -2, + [0][1][2][1][RTW89_WW][1][90] = -2, + [0][1][2][1][RTW89_WW][2][90] = 0, + [0][1][2][1][RTW89_WW][0][92] = -2, + [0][1][2][1][RTW89_WW][1][92] = -2, + [0][1][2][1][RTW89_WW][2][92] = 0, + [0][1][2][1][RTW89_WW][0][94] = -2, + [0][1][2][1][RTW89_WW][1][94] = -2, + [0][1][2][1][RTW89_WW][2][94] = 0, + [0][1][2][1][RTW89_WW][0][96] = -2, + [0][1][2][1][RTW89_WW][1][96] = -2, + [0][1][2][1][RTW89_WW][2][96] = 0, + [0][1][2][1][RTW89_WW][0][98] = -2, + [0][1][2][1][RTW89_WW][1][98] = -2, + [0][1][2][1][RTW89_WW][2][98] = 0, + [0][1][2][1][RTW89_WW][0][100] = -2, + [0][1][2][1][RTW89_WW][1][100] = -2, + [0][1][2][1][RTW89_WW][2][100] = 0, + [0][1][2][1][RTW89_WW][0][102] = -2, + [0][1][2][1][RTW89_WW][1][102] = -2, + [0][1][2][1][RTW89_WW][2][102] = 0, + [0][1][2][1][RTW89_WW][0][104] = -2, + [0][1][2][1][RTW89_WW][1][104] = -2, + [0][1][2][1][RTW89_WW][2][104] = 0, + [0][1][2][1][RTW89_WW][0][105] = -2, + [0][1][2][1][RTW89_WW][1][105] = -2, + [0][1][2][1][RTW89_WW][2][105] = 0, + [0][1][2][1][RTW89_WW][0][107] = 1, + [0][1][2][1][RTW89_WW][1][107] = 1, + [0][1][2][1][RTW89_WW][2][107] = 0, + [0][1][2][1][RTW89_WW][0][109] = 1, + [0][1][2][1][RTW89_WW][1][109] = 1, + [0][1][2][1][RTW89_WW][2][109] = 0, + [0][1][2][1][RTW89_WW][0][111] = 0, + [0][1][2][1][RTW89_WW][1][111] = 0, + [0][1][2][1][RTW89_WW][2][111] = 0, + [0][1][2][1][RTW89_WW][0][113] = 0, + [0][1][2][1][RTW89_WW][1][113] = 0, + [0][1][2][1][RTW89_WW][2][113] = 0, + [0][1][2][1][RTW89_WW][0][115] = 0, + [0][1][2][1][RTW89_WW][1][115] = 0, + [0][1][2][1][RTW89_WW][2][115] = 0, + [0][1][2][1][RTW89_WW][0][117] = 0, + [0][1][2][1][RTW89_WW][1][117] = 0, + [0][1][2][1][RTW89_WW][2][117] = 0, + [0][1][2][1][RTW89_WW][0][119] = 0, + [0][1][2][1][RTW89_WW][1][119] = 0, + [0][1][2][1][RTW89_WW][2][119] = 0, + [1][0][2][0][RTW89_WW][0][1] = 24, + [1][0][2][0][RTW89_WW][1][1] = 34, + [1][0][2][0][RTW89_WW][2][1] = 70, + [1][0][2][0][RTW89_WW][0][5] = 24, + [1][0][2][0][RTW89_WW][1][5] = 34, + [1][0][2][0][RTW89_WW][2][5] = 70, + [1][0][2][0][RTW89_WW][0][9] = 24, + [1][0][2][0][RTW89_WW][1][9] = 34, + [1][0][2][0][RTW89_WW][2][9] = 70, + [1][0][2][0][RTW89_WW][0][13] = 24, + [1][0][2][0][RTW89_WW][1][13] = 34, + [1][0][2][0][RTW89_WW][2][13] = 70, + [1][0][2][0][RTW89_WW][0][16] = 24, + [1][0][2][0][RTW89_WW][1][16] = 34, + [1][0][2][0][RTW89_WW][2][16] = 70, + [1][0][2][0][RTW89_WW][0][20] = 24, + [1][0][2][0][RTW89_WW][1][20] = 34, + [1][0][2][0][RTW89_WW][2][20] = 70, + [1][0][2][0][RTW89_WW][0][24] = 26, + [1][0][2][0][RTW89_WW][1][24] = 36, + [1][0][2][0][RTW89_WW][2][24] = 70, + [1][0][2][0][RTW89_WW][0][28] = 26, + [1][0][2][0][RTW89_WW][1][28] = 34, + [1][0][2][0][RTW89_WW][2][28] = 70, + [1][0][2][0][RTW89_WW][0][31] = 26, + [1][0][2][0][RTW89_WW][1][31] = 34, + [1][0][2][0][RTW89_WW][2][31] = 70, + [1][0][2][0][RTW89_WW][0][35] = 26, + [1][0][2][0][RTW89_WW][1][35] = 34, + [1][0][2][0][RTW89_WW][2][35] = 70, + [1][0][2][0][RTW89_WW][0][39] = 26, + [1][0][2][0][RTW89_WW][1][39] = 34, + [1][0][2][0][RTW89_WW][2][39] = 70, + [1][0][2][0][RTW89_WW][0][43] = 26, + [1][0][2][0][RTW89_WW][1][43] = 34, + [1][0][2][0][RTW89_WW][2][43] = 70, + [1][0][2][0][RTW89_WW][0][46] = 34, + [1][0][2][0][RTW89_WW][1][46] = 34, + [1][0][2][0][RTW89_WW][2][46] = 0, + [1][0][2][0][RTW89_WW][0][50] = 34, + [1][0][2][0][RTW89_WW][1][50] = 34, + [1][0][2][0][RTW89_WW][2][50] = 0, + [1][0][2][0][RTW89_WW][0][54] = 36, + [1][0][2][0][RTW89_WW][1][54] = 36, + [1][0][2][0][RTW89_WW][2][54] = 0, + [1][0][2][0][RTW89_WW][0][58] = 36, + [1][0][2][0][RTW89_WW][1][58] = 36, + [1][0][2][0][RTW89_WW][2][58] = 66, + [1][0][2][0][RTW89_WW][0][61] = 34, + [1][0][2][0][RTW89_WW][1][61] = 34, + [1][0][2][0][RTW89_WW][2][61] = 66, + [1][0][2][0][RTW89_WW][0][65] = 34, + [1][0][2][0][RTW89_WW][1][65] = 34, + [1][0][2][0][RTW89_WW][2][65] = 66, + [1][0][2][0][RTW89_WW][0][69] = 34, + [1][0][2][0][RTW89_WW][1][69] = 34, + [1][0][2][0][RTW89_WW][2][69] = 66, + [1][0][2][0][RTW89_WW][0][73] = 34, + [1][0][2][0][RTW89_WW][1][73] = 34, + [1][0][2][0][RTW89_WW][2][73] = 66, + [1][0][2][0][RTW89_WW][0][76] = 34, + [1][0][2][0][RTW89_WW][1][76] = 34, + [1][0][2][0][RTW89_WW][2][76] = 66, + [1][0][2][0][RTW89_WW][0][80] = 34, + [1][0][2][0][RTW89_WW][1][80] = 34, + [1][0][2][0][RTW89_WW][2][80] = 66, + [1][0][2][0][RTW89_WW][0][84] = 34, + [1][0][2][0][RTW89_WW][1][84] = 34, + [1][0][2][0][RTW89_WW][2][84] = 66, + [1][0][2][0][RTW89_WW][0][88] = 34, + [1][0][2][0][RTW89_WW][1][88] = 34, + [1][0][2][0][RTW89_WW][2][88] = 0, + [1][0][2][0][RTW89_WW][0][91] = 36, + [1][0][2][0][RTW89_WW][1][91] = 36, + [1][0][2][0][RTW89_WW][2][91] = 0, + [1][0][2][0][RTW89_WW][0][95] = 34, + [1][0][2][0][RTW89_WW][1][95] = 34, + [1][0][2][0][RTW89_WW][2][95] = 0, + [1][0][2][0][RTW89_WW][0][99] = 34, + [1][0][2][0][RTW89_WW][1][99] = 34, + [1][0][2][0][RTW89_WW][2][99] = 0, + [1][0][2][0][RTW89_WW][0][103] = 34, + [1][0][2][0][RTW89_WW][1][103] = 34, + [1][0][2][0][RTW89_WW][2][103] = 0, + [1][0][2][0][RTW89_WW][0][106] = 36, + [1][0][2][0][RTW89_WW][1][106] = 36, + [1][0][2][0][RTW89_WW][2][106] = 0, + [1][0][2][0][RTW89_WW][0][110] = 0, + [1][0][2][0][RTW89_WW][1][110] = 0, + [1][0][2][0][RTW89_WW][2][110] = 0, + [1][0][2][0][RTW89_WW][0][114] = 0, + [1][0][2][0][RTW89_WW][1][114] = 0, + [1][0][2][0][RTW89_WW][2][114] = 0, + [1][0][2][0][RTW89_WW][0][118] = 0, + [1][0][2][0][RTW89_WW][1][118] = 0, + [1][0][2][0][RTW89_WW][2][118] = 0, + [1][1][2][0][RTW89_WW][0][1] = 10, + [1][1][2][0][RTW89_WW][1][1] = 10, + [1][1][2][0][RTW89_WW][2][1] = 58, + [1][1][2][0][RTW89_WW][0][5] = 10, + [1][1][2][0][RTW89_WW][1][5] = 10, + [1][1][2][0][RTW89_WW][2][5] = 58, + [1][1][2][0][RTW89_WW][0][9] = 10, + [1][1][2][0][RTW89_WW][1][9] = 10, + [1][1][2][0][RTW89_WW][2][9] = 58, + [1][1][2][0][RTW89_WW][0][13] = 10, + [1][1][2][0][RTW89_WW][1][13] = 10, + [1][1][2][0][RTW89_WW][2][13] = 58, + [1][1][2][0][RTW89_WW][0][16] = 10, + [1][1][2][0][RTW89_WW][1][16] = 10, + [1][1][2][0][RTW89_WW][2][16] = 58, + [1][1][2][0][RTW89_WW][0][20] = 10, + [1][1][2][0][RTW89_WW][1][20] = 10, + [1][1][2][0][RTW89_WW][2][20] = 58, + [1][1][2][0][RTW89_WW][0][24] = 10, + [1][1][2][0][RTW89_WW][1][24] = 10, + [1][1][2][0][RTW89_WW][2][24] = 70, + [1][1][2][0][RTW89_WW][0][28] = 10, + [1][1][2][0][RTW89_WW][1][28] = 10, + [1][1][2][0][RTW89_WW][2][28] = 70, + [1][1][2][0][RTW89_WW][0][31] = 10, + [1][1][2][0][RTW89_WW][1][31] = 10, + [1][1][2][0][RTW89_WW][2][31] = 70, + [1][1][2][0][RTW89_WW][0][35] = 10, + [1][1][2][0][RTW89_WW][1][35] = 10, + [1][1][2][0][RTW89_WW][2][35] = 70, + [1][1][2][0][RTW89_WW][0][39] = 10, + [1][1][2][0][RTW89_WW][1][39] = 10, + [1][1][2][0][RTW89_WW][2][39] = 70, + [1][1][2][0][RTW89_WW][0][43] = 10, + [1][1][2][0][RTW89_WW][1][43] = 10, + [1][1][2][0][RTW89_WW][2][43] = 70, + [1][1][2][0][RTW89_WW][0][46] = 12, + [1][1][2][0][RTW89_WW][1][46] = 12, + [1][1][2][0][RTW89_WW][2][46] = 0, + [1][1][2][0][RTW89_WW][0][50] = 12, + [1][1][2][0][RTW89_WW][1][50] = 12, + [1][1][2][0][RTW89_WW][2][50] = 0, + [1][1][2][0][RTW89_WW][0][54] = 10, + [1][1][2][0][RTW89_WW][1][54] = 10, + [1][1][2][0][RTW89_WW][2][54] = 0, + [1][1][2][0][RTW89_WW][0][58] = 10, + [1][1][2][0][RTW89_WW][1][58] = 10, + [1][1][2][0][RTW89_WW][2][58] = 66, + [1][1][2][0][RTW89_WW][0][61] = 10, + [1][1][2][0][RTW89_WW][1][61] = 10, + [1][1][2][0][RTW89_WW][2][61] = 66, + [1][1][2][0][RTW89_WW][0][65] = 10, + [1][1][2][0][RTW89_WW][1][65] = 10, + [1][1][2][0][RTW89_WW][2][65] = 66, + [1][1][2][0][RTW89_WW][0][69] = 10, + [1][1][2][0][RTW89_WW][1][69] = 10, + [1][1][2][0][RTW89_WW][2][69] = 66, + [1][1][2][0][RTW89_WW][0][73] = 10, + [1][1][2][0][RTW89_WW][1][73] = 10, + [1][1][2][0][RTW89_WW][2][73] = 66, + [1][1][2][0][RTW89_WW][0][76] = 10, + [1][1][2][0][RTW89_WW][1][76] = 10, + [1][1][2][0][RTW89_WW][2][76] = 66, + [1][1][2][0][RTW89_WW][0][80] = 10, + [1][1][2][0][RTW89_WW][1][80] = 10, + [1][1][2][0][RTW89_WW][2][80] = 66, + [1][1][2][0][RTW89_WW][0][84] = 10, + [1][1][2][0][RTW89_WW][1][84] = 10, + [1][1][2][0][RTW89_WW][2][84] = 66, + [1][1][2][0][RTW89_WW][0][88] = 10, + [1][1][2][0][RTW89_WW][1][88] = 10, + [1][1][2][0][RTW89_WW][2][88] = 0, + [1][1][2][0][RTW89_WW][0][91] = 12, + [1][1][2][0][RTW89_WW][1][91] = 12, + [1][1][2][0][RTW89_WW][2][91] = 0, + [1][1][2][0][RTW89_WW][0][95] = 10, + [1][1][2][0][RTW89_WW][1][95] = 10, + [1][1][2][0][RTW89_WW][2][95] = 0, + [1][1][2][0][RTW89_WW][0][99] = 10, + [1][1][2][0][RTW89_WW][1][99] = 10, + [1][1][2][0][RTW89_WW][2][99] = 0, + [1][1][2][0][RTW89_WW][0][103] = 10, + [1][1][2][0][RTW89_WW][1][103] = 10, + [1][1][2][0][RTW89_WW][2][103] = 0, + [1][1][2][0][RTW89_WW][0][106] = 12, + [1][1][2][0][RTW89_WW][1][106] = 12, + [1][1][2][0][RTW89_WW][2][106] = 0, + [1][1][2][0][RTW89_WW][0][110] = 0, + [1][1][2][0][RTW89_WW][1][110] = 0, + [1][1][2][0][RTW89_WW][2][110] = 0, + [1][1][2][0][RTW89_WW][0][114] = 0, + [1][1][2][0][RTW89_WW][1][114] = 0, + [1][1][2][0][RTW89_WW][2][114] = 0, + [1][1][2][0][RTW89_WW][0][118] = 0, + [1][1][2][0][RTW89_WW][1][118] = 0, + [1][1][2][0][RTW89_WW][2][118] = 0, + [1][1][2][1][RTW89_WW][0][1] = 6, + [1][1][2][1][RTW89_WW][1][1] = 10, + [1][1][2][1][RTW89_WW][2][1] = 58, + [1][1][2][1][RTW89_WW][0][5] = 6, + [1][1][2][1][RTW89_WW][1][5] = 10, + [1][1][2][1][RTW89_WW][2][5] = 58, + [1][1][2][1][RTW89_WW][0][9] = 6, + [1][1][2][1][RTW89_WW][1][9] = 10, + [1][1][2][1][RTW89_WW][2][9] = 58, + [1][1][2][1][RTW89_WW][0][13] = 6, + [1][1][2][1][RTW89_WW][1][13] = 10, + [1][1][2][1][RTW89_WW][2][13] = 58, + [1][1][2][1][RTW89_WW][0][16] = 6, + [1][1][2][1][RTW89_WW][1][16] = 10, + [1][1][2][1][RTW89_WW][2][16] = 58, + [1][1][2][1][RTW89_WW][0][20] = 6, + [1][1][2][1][RTW89_WW][1][20] = 10, + [1][1][2][1][RTW89_WW][2][20] = 58, + [1][1][2][1][RTW89_WW][0][24] = 6, + [1][1][2][1][RTW89_WW][1][24] = 10, + [1][1][2][1][RTW89_WW][2][24] = 70, + [1][1][2][1][RTW89_WW][0][28] = 6, + [1][1][2][1][RTW89_WW][1][28] = 10, + [1][1][2][1][RTW89_WW][2][28] = 70, + [1][1][2][1][RTW89_WW][0][31] = 6, + [1][1][2][1][RTW89_WW][1][31] = 10, + [1][1][2][1][RTW89_WW][2][31] = 70, + [1][1][2][1][RTW89_WW][0][35] = 6, + [1][1][2][1][RTW89_WW][1][35] = 10, + [1][1][2][1][RTW89_WW][2][35] = 70, + [1][1][2][1][RTW89_WW][0][39] = 6, + [1][1][2][1][RTW89_WW][1][39] = 10, + [1][1][2][1][RTW89_WW][2][39] = 70, + [1][1][2][1][RTW89_WW][0][43] = 6, + [1][1][2][1][RTW89_WW][1][43] = 10, + [1][1][2][1][RTW89_WW][2][43] = 70, + [1][1][2][1][RTW89_WW][0][46] = 12, + [1][1][2][1][RTW89_WW][1][46] = 12, + [1][1][2][1][RTW89_WW][2][46] = 0, + [1][1][2][1][RTW89_WW][0][50] = 12, + [1][1][2][1][RTW89_WW][1][50] = 12, + [1][1][2][1][RTW89_WW][2][50] = 0, + [1][1][2][1][RTW89_WW][0][54] = 10, + [1][1][2][1][RTW89_WW][1][54] = 10, + [1][1][2][1][RTW89_WW][2][54] = 0, + [1][1][2][1][RTW89_WW][0][58] = 10, + [1][1][2][1][RTW89_WW][1][58] = 10, + [1][1][2][1][RTW89_WW][2][58] = 66, + [1][1][2][1][RTW89_WW][0][61] = 10, + [1][1][2][1][RTW89_WW][1][61] = 10, + [1][1][2][1][RTW89_WW][2][61] = 66, + [1][1][2][1][RTW89_WW][0][65] = 10, + [1][1][2][1][RTW89_WW][1][65] = 10, + [1][1][2][1][RTW89_WW][2][65] = 66, + [1][1][2][1][RTW89_WW][0][69] = 10, + [1][1][2][1][RTW89_WW][1][69] = 10, + [1][1][2][1][RTW89_WW][2][69] = 66, + [1][1][2][1][RTW89_WW][0][73] = 10, + [1][1][2][1][RTW89_WW][1][73] = 10, + [1][1][2][1][RTW89_WW][2][73] = 66, + [1][1][2][1][RTW89_WW][0][76] = 10, + [1][1][2][1][RTW89_WW][1][76] = 10, + [1][1][2][1][RTW89_WW][2][76] = 66, + [1][1][2][1][RTW89_WW][0][80] = 10, + [1][1][2][1][RTW89_WW][1][80] = 10, + [1][1][2][1][RTW89_WW][2][80] = 66, + [1][1][2][1][RTW89_WW][0][84] = 10, + [1][1][2][1][RTW89_WW][1][84] = 10, + [1][1][2][1][RTW89_WW][2][84] = 66, + [1][1][2][1][RTW89_WW][0][88] = 10, + [1][1][2][1][RTW89_WW][1][88] = 10, + [1][1][2][1][RTW89_WW][2][88] = 0, + [1][1][2][1][RTW89_WW][0][91] = 12, + [1][1][2][1][RTW89_WW][1][91] = 12, + [1][1][2][1][RTW89_WW][2][91] = 0, + [1][1][2][1][RTW89_WW][0][95] = 10, + [1][1][2][1][RTW89_WW][1][95] = 10, + [1][1][2][1][RTW89_WW][2][95] = 0, + [1][1][2][1][RTW89_WW][0][99] = 10, + [1][1][2][1][RTW89_WW][1][99] = 10, + [1][1][2][1][RTW89_WW][2][99] = 0, + [1][1][2][1][RTW89_WW][0][103] = 10, + [1][1][2][1][RTW89_WW][1][103] = 10, + [1][1][2][1][RTW89_WW][2][103] = 0, + [1][1][2][1][RTW89_WW][0][106] = 12, + [1][1][2][1][RTW89_WW][1][106] = 12, + [1][1][2][1][RTW89_WW][2][106] = 0, + [1][1][2][1][RTW89_WW][0][110] = 0, + [1][1][2][1][RTW89_WW][1][110] = 0, + [1][1][2][1][RTW89_WW][2][110] = 0, + [1][1][2][1][RTW89_WW][0][114] = 0, + [1][1][2][1][RTW89_WW][1][114] = 0, + [1][1][2][1][RTW89_WW][2][114] = 0, + [1][1][2][1][RTW89_WW][0][118] = 0, + [1][1][2][1][RTW89_WW][1][118] = 0, + [1][1][2][1][RTW89_WW][2][118] = 0, + [2][0][2][0][RTW89_WW][0][3] = 24, + [2][0][2][0][RTW89_WW][1][3] = 46, + [2][0][2][0][RTW89_WW][2][3] = 60, + [2][0][2][0][RTW89_WW][0][11] = 24, + [2][0][2][0][RTW89_WW][1][11] = 46, + [2][0][2][0][RTW89_WW][2][11] = 60, + [2][0][2][0][RTW89_WW][0][18] = 24, + [2][0][2][0][RTW89_WW][1][18] = 46, + [2][0][2][0][RTW89_WW][2][18] = 60, + [2][0][2][0][RTW89_WW][0][26] = 24, + [2][0][2][0][RTW89_WW][1][26] = 46, + [2][0][2][0][RTW89_WW][2][26] = 60, + [2][0][2][0][RTW89_WW][0][33] = 24, + [2][0][2][0][RTW89_WW][1][33] = 46, + [2][0][2][0][RTW89_WW][2][33] = 60, + [2][0][2][0][RTW89_WW][0][41] = 24, + [2][0][2][0][RTW89_WW][1][41] = 46, + [2][0][2][0][RTW89_WW][2][41] = 60, + [2][0][2][0][RTW89_WW][0][48] = 46, + [2][0][2][0][RTW89_WW][1][48] = 46, + [2][0][2][0][RTW89_WW][2][48] = 0, + [2][0][2][0][RTW89_WW][0][56] = 46, + [2][0][2][0][RTW89_WW][1][56] = 46, + [2][0][2][0][RTW89_WW][2][56] = 0, + [2][0][2][0][RTW89_WW][0][63] = 46, + [2][0][2][0][RTW89_WW][1][63] = 46, + [2][0][2][0][RTW89_WW][2][63] = 58, + [2][0][2][0][RTW89_WW][0][71] = 46, + [2][0][2][0][RTW89_WW][1][71] = 46, + [2][0][2][0][RTW89_WW][2][71] = 58, + [2][0][2][0][RTW89_WW][0][78] = 46, + [2][0][2][0][RTW89_WW][1][78] = 46, + [2][0][2][0][RTW89_WW][2][78] = 58, + [2][0][2][0][RTW89_WW][0][86] = 46, + [2][0][2][0][RTW89_WW][1][86] = 46, + [2][0][2][0][RTW89_WW][2][86] = 0, + [2][0][2][0][RTW89_WW][0][93] = 46, + [2][0][2][0][RTW89_WW][1][93] = 46, + [2][0][2][0][RTW89_WW][2][93] = 0, + [2][0][2][0][RTW89_WW][0][101] = 44, + [2][0][2][0][RTW89_WW][1][101] = 44, + [2][0][2][0][RTW89_WW][2][101] = 0, + [2][0][2][0][RTW89_WW][0][108] = 0, + [2][0][2][0][RTW89_WW][1][108] = 0, + [2][0][2][0][RTW89_WW][2][108] = 0, + [2][0][2][0][RTW89_WW][0][116] = 0, + [2][0][2][0][RTW89_WW][1][116] = 0, + [2][0][2][0][RTW89_WW][2][116] = 0, + [2][1][2][0][RTW89_WW][0][3] = 12, + [2][1][2][0][RTW89_WW][1][3] = 22, + [2][1][2][0][RTW89_WW][2][3] = 50, + [2][1][2][0][RTW89_WW][0][11] = 12, + [2][1][2][0][RTW89_WW][1][11] = 20, + [2][1][2][0][RTW89_WW][2][11] = 50, + [2][1][2][0][RTW89_WW][0][18] = 12, + [2][1][2][0][RTW89_WW][1][18] = 20, + [2][1][2][0][RTW89_WW][2][18] = 50, + [2][1][2][0][RTW89_WW][0][26] = 12, + [2][1][2][0][RTW89_WW][1][26] = 20, + [2][1][2][0][RTW89_WW][2][26] = 60, + [2][1][2][0][RTW89_WW][0][33] = 12, + [2][1][2][0][RTW89_WW][1][33] = 20, + [2][1][2][0][RTW89_WW][2][33] = 60, + [2][1][2][0][RTW89_WW][0][41] = 12, + [2][1][2][0][RTW89_WW][1][41] = 22, + [2][1][2][0][RTW89_WW][2][41] = 60, + [2][1][2][0][RTW89_WW][0][48] = 22, + [2][1][2][0][RTW89_WW][1][48] = 22, + [2][1][2][0][RTW89_WW][2][48] = 0, + [2][1][2][0][RTW89_WW][0][56] = 20, + [2][1][2][0][RTW89_WW][1][56] = 20, + [2][1][2][0][RTW89_WW][2][56] = 0, + [2][1][2][0][RTW89_WW][0][63] = 22, + [2][1][2][0][RTW89_WW][1][63] = 22, + [2][1][2][0][RTW89_WW][2][63] = 58, + [2][1][2][0][RTW89_WW][0][71] = 20, + [2][1][2][0][RTW89_WW][1][71] = 20, + [2][1][2][0][RTW89_WW][2][71] = 58, + [2][1][2][0][RTW89_WW][0][78] = 20, + [2][1][2][0][RTW89_WW][1][78] = 20, + [2][1][2][0][RTW89_WW][2][78] = 58, + [2][1][2][0][RTW89_WW][0][86] = 20, + [2][1][2][0][RTW89_WW][1][86] = 20, + [2][1][2][0][RTW89_WW][2][86] = 0, + [2][1][2][0][RTW89_WW][0][93] = 22, + [2][1][2][0][RTW89_WW][1][93] = 22, + [2][1][2][0][RTW89_WW][2][93] = 0, + [2][1][2][0][RTW89_WW][0][101] = 22, + [2][1][2][0][RTW89_WW][1][101] = 22, + [2][1][2][0][RTW89_WW][2][101] = 0, + [2][1][2][0][RTW89_WW][0][108] = 0, + [2][1][2][0][RTW89_WW][1][108] = 0, + [2][1][2][0][RTW89_WW][2][108] = 0, + [2][1][2][0][RTW89_WW][0][116] = 0, + [2][1][2][0][RTW89_WW][1][116] = 0, + [2][1][2][0][RTW89_WW][2][116] = 0, + [2][1][2][1][RTW89_WW][0][3] = 6, + [2][1][2][1][RTW89_WW][1][3] = 22, + [2][1][2][1][RTW89_WW][2][3] = 50, + [2][1][2][1][RTW89_WW][0][11] = 6, + [2][1][2][1][RTW89_WW][1][11] = 20, + [2][1][2][1][RTW89_WW][2][11] = 50, + [2][1][2][1][RTW89_WW][0][18] = 6, + [2][1][2][1][RTW89_WW][1][18] = 20, + [2][1][2][1][RTW89_WW][2][18] = 50, + [2][1][2][1][RTW89_WW][0][26] = 6, + [2][1][2][1][RTW89_WW][1][26] = 20, + [2][1][2][1][RTW89_WW][2][26] = 60, + [2][1][2][1][RTW89_WW][0][33] = 6, + [2][1][2][1][RTW89_WW][1][33] = 20, + [2][1][2][1][RTW89_WW][2][33] = 60, + [2][1][2][1][RTW89_WW][0][41] = 6, + [2][1][2][1][RTW89_WW][1][41] = 22, + [2][1][2][1][RTW89_WW][2][41] = 60, + [2][1][2][1][RTW89_WW][0][48] = 22, + [2][1][2][1][RTW89_WW][1][48] = 22, + [2][1][2][1][RTW89_WW][2][48] = 0, + [2][1][2][1][RTW89_WW][0][56] = 20, + [2][1][2][1][RTW89_WW][1][56] = 20, + [2][1][2][1][RTW89_WW][2][56] = 0, + [2][1][2][1][RTW89_WW][0][63] = 22, + [2][1][2][1][RTW89_WW][1][63] = 22, + [2][1][2][1][RTW89_WW][2][63] = 58, + [2][1][2][1][RTW89_WW][0][71] = 20, + [2][1][2][1][RTW89_WW][1][71] = 20, + [2][1][2][1][RTW89_WW][2][71] = 58, + [2][1][2][1][RTW89_WW][0][78] = 20, + [2][1][2][1][RTW89_WW][1][78] = 20, + [2][1][2][1][RTW89_WW][2][78] = 58, + [2][1][2][1][RTW89_WW][0][86] = 20, + [2][1][2][1][RTW89_WW][1][86] = 20, + [2][1][2][1][RTW89_WW][2][86] = 0, + [2][1][2][1][RTW89_WW][0][93] = 22, + [2][1][2][1][RTW89_WW][1][93] = 22, + [2][1][2][1][RTW89_WW][2][93] = 0, + [2][1][2][1][RTW89_WW][0][101] = 22, + [2][1][2][1][RTW89_WW][1][101] = 22, + [2][1][2][1][RTW89_WW][2][101] = 0, + [2][1][2][1][RTW89_WW][0][108] = 0, + [2][1][2][1][RTW89_WW][1][108] = 0, + [2][1][2][1][RTW89_WW][2][108] = 0, + [2][1][2][1][RTW89_WW][0][116] = 0, + [2][1][2][1][RTW89_WW][1][116] = 0, + [2][1][2][1][RTW89_WW][2][116] = 0, + [3][0][2][0][RTW89_WW][0][7] = 22, + [3][0][2][0][RTW89_WW][1][7] = 42, + [3][0][2][0][RTW89_WW][2][7] = 52, + [3][0][2][0][RTW89_WW][0][22] = 20, + [3][0][2][0][RTW89_WW][1][22] = 42, + [3][0][2][0][RTW89_WW][2][22] = 52, + [3][0][2][0][RTW89_WW][0][37] = 20, + [3][0][2][0][RTW89_WW][1][37] = 42, + [3][0][2][0][RTW89_WW][2][37] = 52, + [3][0][2][0][RTW89_WW][0][52] = 54, + [3][0][2][0][RTW89_WW][1][52] = 54, + [3][0][2][0][RTW89_WW][2][52] = 0, + [3][0][2][0][RTW89_WW][0][67] = 54, + [3][0][2][0][RTW89_WW][1][67] = 54, + [3][0][2][0][RTW89_WW][2][67] = 54, + [3][0][2][0][RTW89_WW][0][82] = 26, + [3][0][2][0][RTW89_WW][1][82] = 26, + [3][0][2][0][RTW89_WW][2][82] = 0, + [3][0][2][0][RTW89_WW][0][97] = 26, + [3][0][2][0][RTW89_WW][1][97] = 26, + [3][0][2][0][RTW89_WW][2][97] = 0, + [3][0][2][0][RTW89_WW][0][112] = 0, + [3][0][2][0][RTW89_WW][1][112] = 0, + [3][0][2][0][RTW89_WW][2][112] = 0, + [3][1][2][0][RTW89_WW][0][7] = 10, + [3][1][2][0][RTW89_WW][1][7] = 32, + [3][1][2][0][RTW89_WW][2][7] = 46, + [3][1][2][0][RTW89_WW][0][22] = 8, + [3][1][2][0][RTW89_WW][1][22] = 30, + [3][1][2][0][RTW89_WW][2][22] = 52, + [3][1][2][0][RTW89_WW][0][37] = 8, + [3][1][2][0][RTW89_WW][1][37] = 30, + [3][1][2][0][RTW89_WW][2][37] = 52, + [3][1][2][0][RTW89_WW][0][52] = 30, + [3][1][2][0][RTW89_WW][1][52] = 30, + [3][1][2][0][RTW89_WW][2][52] = 0, + [3][1][2][0][RTW89_WW][0][67] = 32, + [3][1][2][0][RTW89_WW][1][67] = 32, + [3][1][2][0][RTW89_WW][2][67] = 54, + [3][1][2][0][RTW89_WW][0][82] = 24, + [3][1][2][0][RTW89_WW][1][82] = 24, + [3][1][2][0][RTW89_WW][2][82] = 0, + [3][1][2][0][RTW89_WW][0][97] = 24, + [3][1][2][0][RTW89_WW][1][97] = 24, + [3][1][2][0][RTW89_WW][2][97] = 0, + [3][1][2][0][RTW89_WW][0][112] = 0, + [3][1][2][0][RTW89_WW][1][112] = 0, + [3][1][2][0][RTW89_WW][2][112] = 0, + [3][1][2][1][RTW89_WW][0][7] = 6, + [3][1][2][1][RTW89_WW][1][7] = 32, + [3][1][2][1][RTW89_WW][2][7] = 46, + [3][1][2][1][RTW89_WW][0][22] = 6, + [3][1][2][1][RTW89_WW][1][22] = 30, + [3][1][2][1][RTW89_WW][2][22] = 52, + [3][1][2][1][RTW89_WW][0][37] = 6, + [3][1][2][1][RTW89_WW][1][37] = 30, + [3][1][2][1][RTW89_WW][2][37] = 52, + [3][1][2][1][RTW89_WW][0][52] = 30, + [3][1][2][1][RTW89_WW][1][52] = 30, + [3][1][2][1][RTW89_WW][2][52] = 0, + [3][1][2][1][RTW89_WW][0][67] = 32, + [3][1][2][1][RTW89_WW][1][67] = 32, + [3][1][2][1][RTW89_WW][2][67] = 54, + [3][1][2][1][RTW89_WW][0][82] = 24, + [3][1][2][1][RTW89_WW][1][82] = 24, + [3][1][2][1][RTW89_WW][2][82] = 0, + [3][1][2][1][RTW89_WW][0][97] = 24, + [3][1][2][1][RTW89_WW][1][97] = 24, + [3][1][2][1][RTW89_WW][2][97] = 0, + [3][1][2][1][RTW89_WW][0][112] = 0, + [3][1][2][1][RTW89_WW][1][112] = 0, + [3][1][2][1][RTW89_WW][2][112] = 0, + [0][0][1][0][RTW89_FCC][1][0] = 24, + [0][0][1][0][RTW89_FCC][2][0] = 56, + [0][0][1][0][RTW89_ETSI][1][0] = 66, + [0][0][1][0][RTW89_ETSI][0][0] = 28, + [0][0][1][0][RTW89_MKK][1][0] = 66, + [0][0][1][0][RTW89_MKK][0][0] = 26, + [0][0][1][0][RTW89_IC][1][0] = 24, + [0][0][1][0][RTW89_KCC][1][0] = 24, + [0][0][1][0][RTW89_KCC][0][0] = 24, + [0][0][1][0][RTW89_ACMA][1][0] = 66, + [0][0][1][0][RTW89_ACMA][0][0] = 28, + [0][0][1][0][RTW89_CHILE][1][0] = 24, + [0][0][1][0][RTW89_QATAR][1][0] = 66, + [0][0][1][0][RTW89_QATAR][0][0] = 28, + [0][0][1][0][RTW89_UK][1][0] = 66, + [0][0][1][0][RTW89_UK][0][0] = 28, + [0][0][1][0][RTW89_FCC][1][2] = 22, + [0][0][1][0][RTW89_FCC][2][2] = 56, + [0][0][1][0][RTW89_ETSI][1][2] = 66, + [0][0][1][0][RTW89_ETSI][0][2] = 28, + [0][0][1][0][RTW89_MKK][1][2] = 66, + [0][0][1][0][RTW89_MKK][0][2] = 26, + [0][0][1][0][RTW89_IC][1][2] = 22, + [0][0][1][0][RTW89_KCC][1][2] = 24, + [0][0][1][0][RTW89_KCC][0][2] = 24, + [0][0][1][0][RTW89_ACMA][1][2] = 66, + [0][0][1][0][RTW89_ACMA][0][2] = 28, + [0][0][1][0][RTW89_CHILE][1][2] = 22, + [0][0][1][0][RTW89_QATAR][1][2] = 66, + [0][0][1][0][RTW89_QATAR][0][2] = 28, + [0][0][1][0][RTW89_UK][1][2] = 66, + [0][0][1][0][RTW89_UK][0][2] = 28, + [0][0][1][0][RTW89_FCC][1][4] = 22, + [0][0][1][0][RTW89_FCC][2][4] = 56, + [0][0][1][0][RTW89_ETSI][1][4] = 66, + [0][0][1][0][RTW89_ETSI][0][4] = 28, + [0][0][1][0][RTW89_MKK][1][4] = 66, + [0][0][1][0][RTW89_MKK][0][4] = 26, + [0][0][1][0][RTW89_IC][1][4] = 22, + [0][0][1][0][RTW89_KCC][1][4] = 24, + [0][0][1][0][RTW89_KCC][0][4] = 24, + [0][0][1][0][RTW89_ACMA][1][4] = 66, + [0][0][1][0][RTW89_ACMA][0][4] = 28, + [0][0][1][0][RTW89_CHILE][1][4] = 22, + [0][0][1][0][RTW89_QATAR][1][4] = 66, + [0][0][1][0][RTW89_QATAR][0][4] = 28, + [0][0][1][0][RTW89_UK][1][4] = 66, + [0][0][1][0][RTW89_UK][0][4] = 28, + [0][0][1][0][RTW89_FCC][1][6] = 22, + [0][0][1][0][RTW89_FCC][2][6] = 56, + [0][0][1][0][RTW89_ETSI][1][6] = 66, + [0][0][1][0][RTW89_ETSI][0][6] = 28, + [0][0][1][0][RTW89_MKK][1][6] = 66, + [0][0][1][0][RTW89_MKK][0][6] = 26, + [0][0][1][0][RTW89_IC][1][6] = 22, + [0][0][1][0][RTW89_KCC][1][6] = 24, + [0][0][1][0][RTW89_KCC][0][6] = 24, + [0][0][1][0][RTW89_ACMA][1][6] = 66, + [0][0][1][0][RTW89_ACMA][0][6] = 28, + [0][0][1][0][RTW89_CHILE][1][6] = 22, + [0][0][1][0][RTW89_QATAR][1][6] = 66, + [0][0][1][0][RTW89_QATAR][0][6] = 28, + [0][0][1][0][RTW89_UK][1][6] = 66, + [0][0][1][0][RTW89_UK][0][6] = 28, + [0][0][1][0][RTW89_FCC][1][8] = 22, + [0][0][1][0][RTW89_FCC][2][8] = 56, + [0][0][1][0][RTW89_ETSI][1][8] = 66, + [0][0][1][0][RTW89_ETSI][0][8] = 28, + [0][0][1][0][RTW89_MKK][1][8] = 66, + [0][0][1][0][RTW89_MKK][0][8] = 26, + [0][0][1][0][RTW89_IC][1][8] = 22, + [0][0][1][0][RTW89_KCC][1][8] = 24, + [0][0][1][0][RTW89_KCC][0][8] = 24, + [0][0][1][0][RTW89_ACMA][1][8] = 66, + [0][0][1][0][RTW89_ACMA][0][8] = 28, + [0][0][1][0][RTW89_CHILE][1][8] = 22, + [0][0][1][0][RTW89_QATAR][1][8] = 66, + [0][0][1][0][RTW89_QATAR][0][8] = 28, + [0][0][1][0][RTW89_UK][1][8] = 66, + [0][0][1][0][RTW89_UK][0][8] = 28, + [0][0][1][0][RTW89_FCC][1][10] = 22, + [0][0][1][0][RTW89_FCC][2][10] = 56, + [0][0][1][0][RTW89_ETSI][1][10] = 66, + [0][0][1][0][RTW89_ETSI][0][10] = 28, + [0][0][1][0][RTW89_MKK][1][10] = 66, + [0][0][1][0][RTW89_MKK][0][10] = 26, + [0][0][1][0][RTW89_IC][1][10] = 22, + [0][0][1][0][RTW89_KCC][1][10] = 24, + [0][0][1][0][RTW89_KCC][0][10] = 24, + [0][0][1][0][RTW89_ACMA][1][10] = 66, + [0][0][1][0][RTW89_ACMA][0][10] = 28, + [0][0][1][0][RTW89_CHILE][1][10] = 22, + [0][0][1][0][RTW89_QATAR][1][10] = 66, + [0][0][1][0][RTW89_QATAR][0][10] = 28, + [0][0][1][0][RTW89_UK][1][10] = 66, + [0][0][1][0][RTW89_UK][0][10] = 28, + [0][0][1][0][RTW89_FCC][1][12] = 22, + [0][0][1][0][RTW89_FCC][2][12] = 56, + [0][0][1][0][RTW89_ETSI][1][12] = 66, + [0][0][1][0][RTW89_ETSI][0][12] = 28, + [0][0][1][0][RTW89_MKK][1][12] = 66, + [0][0][1][0][RTW89_MKK][0][12] = 26, + [0][0][1][0][RTW89_IC][1][12] = 22, + [0][0][1][0][RTW89_KCC][1][12] = 24, + [0][0][1][0][RTW89_KCC][0][12] = 24, + [0][0][1][0][RTW89_ACMA][1][12] = 66, + [0][0][1][0][RTW89_ACMA][0][12] = 28, + [0][0][1][0][RTW89_CHILE][1][12] = 22, + [0][0][1][0][RTW89_QATAR][1][12] = 66, + [0][0][1][0][RTW89_QATAR][0][12] = 28, + [0][0][1][0][RTW89_UK][1][12] = 66, + [0][0][1][0][RTW89_UK][0][12] = 28, + [0][0][1][0][RTW89_FCC][1][14] = 22, + [0][0][1][0][RTW89_FCC][2][14] = 56, + [0][0][1][0][RTW89_ETSI][1][14] = 66, + [0][0][1][0][RTW89_ETSI][0][14] = 28, + [0][0][1][0][RTW89_MKK][1][14] = 66, + [0][0][1][0][RTW89_MKK][0][14] = 26, + [0][0][1][0][RTW89_IC][1][14] = 22, + [0][0][1][0][RTW89_KCC][1][14] = 24, + [0][0][1][0][RTW89_KCC][0][14] = 24, + [0][0][1][0][RTW89_ACMA][1][14] = 66, + [0][0][1][0][RTW89_ACMA][0][14] = 28, + [0][0][1][0][RTW89_CHILE][1][14] = 22, + [0][0][1][0][RTW89_QATAR][1][14] = 66, + [0][0][1][0][RTW89_QATAR][0][14] = 28, + [0][0][1][0][RTW89_UK][1][14] = 66, + [0][0][1][0][RTW89_UK][0][14] = 28, + [0][0][1][0][RTW89_FCC][1][15] = 22, + [0][0][1][0][RTW89_FCC][2][15] = 56, + [0][0][1][0][RTW89_ETSI][1][15] = 66, + [0][0][1][0][RTW89_ETSI][0][15] = 28, + [0][0][1][0][RTW89_MKK][1][15] = 66, + [0][0][1][0][RTW89_MKK][0][15] = 26, + [0][0][1][0][RTW89_IC][1][15] = 22, + [0][0][1][0][RTW89_KCC][1][15] = 24, + [0][0][1][0][RTW89_KCC][0][15] = 24, + [0][0][1][0][RTW89_ACMA][1][15] = 66, + [0][0][1][0][RTW89_ACMA][0][15] = 28, + [0][0][1][0][RTW89_CHILE][1][15] = 22, + [0][0][1][0][RTW89_QATAR][1][15] = 66, + [0][0][1][0][RTW89_QATAR][0][15] = 28, + [0][0][1][0][RTW89_UK][1][15] = 66, + [0][0][1][0][RTW89_UK][0][15] = 28, + [0][0][1][0][RTW89_FCC][1][17] = 22, + [0][0][1][0][RTW89_FCC][2][17] = 56, + [0][0][1][0][RTW89_ETSI][1][17] = 66, + [0][0][1][0][RTW89_ETSI][0][17] = 28, + [0][0][1][0][RTW89_MKK][1][17] = 66, + [0][0][1][0][RTW89_MKK][0][17] = 26, + [0][0][1][0][RTW89_IC][1][17] = 22, + [0][0][1][0][RTW89_KCC][1][17] = 24, + [0][0][1][0][RTW89_KCC][0][17] = 24, + [0][0][1][0][RTW89_ACMA][1][17] = 66, + [0][0][1][0][RTW89_ACMA][0][17] = 28, + [0][0][1][0][RTW89_CHILE][1][17] = 22, + [0][0][1][0][RTW89_QATAR][1][17] = 66, + [0][0][1][0][RTW89_QATAR][0][17] = 28, + [0][0][1][0][RTW89_UK][1][17] = 66, + [0][0][1][0][RTW89_UK][0][17] = 28, + [0][0][1][0][RTW89_FCC][1][19] = 22, + [0][0][1][0][RTW89_FCC][2][19] = 56, + [0][0][1][0][RTW89_ETSI][1][19] = 66, + [0][0][1][0][RTW89_ETSI][0][19] = 28, + [0][0][1][0][RTW89_MKK][1][19] = 66, + [0][0][1][0][RTW89_MKK][0][19] = 26, + [0][0][1][0][RTW89_IC][1][19] = 22, + [0][0][1][0][RTW89_KCC][1][19] = 24, + [0][0][1][0][RTW89_KCC][0][19] = 24, + [0][0][1][0][RTW89_ACMA][1][19] = 66, + [0][0][1][0][RTW89_ACMA][0][19] = 28, + [0][0][1][0][RTW89_CHILE][1][19] = 22, + [0][0][1][0][RTW89_QATAR][1][19] = 66, + [0][0][1][0][RTW89_QATAR][0][19] = 28, + [0][0][1][0][RTW89_UK][1][19] = 66, + [0][0][1][0][RTW89_UK][0][19] = 28, + [0][0][1][0][RTW89_FCC][1][21] = 22, + [0][0][1][0][RTW89_FCC][2][21] = 56, + [0][0][1][0][RTW89_ETSI][1][21] = 66, + [0][0][1][0][RTW89_ETSI][0][21] = 28, + [0][0][1][0][RTW89_MKK][1][21] = 66, + [0][0][1][0][RTW89_MKK][0][21] = 26, + [0][0][1][0][RTW89_IC][1][21] = 22, + [0][0][1][0][RTW89_KCC][1][21] = 24, + [0][0][1][0][RTW89_KCC][0][21] = 24, + [0][0][1][0][RTW89_ACMA][1][21] = 66, + [0][0][1][0][RTW89_ACMA][0][21] = 28, + [0][0][1][0][RTW89_CHILE][1][21] = 22, + [0][0][1][0][RTW89_QATAR][1][21] = 66, + [0][0][1][0][RTW89_QATAR][0][21] = 28, + [0][0][1][0][RTW89_UK][1][21] = 66, + [0][0][1][0][RTW89_UK][0][21] = 28, + [0][0][1][0][RTW89_FCC][1][23] = 22, + [0][0][1][0][RTW89_FCC][2][23] = 70, + [0][0][1][0][RTW89_ETSI][1][23] = 66, + [0][0][1][0][RTW89_ETSI][0][23] = 28, + [0][0][1][0][RTW89_MKK][1][23] = 66, + [0][0][1][0][RTW89_MKK][0][23] = 26, + [0][0][1][0][RTW89_IC][1][23] = 22, + [0][0][1][0][RTW89_KCC][1][23] = 24, + [0][0][1][0][RTW89_KCC][0][23] = 26, + [0][0][1][0][RTW89_ACMA][1][23] = 66, + [0][0][1][0][RTW89_ACMA][0][23] = 28, + [0][0][1][0][RTW89_CHILE][1][23] = 22, + [0][0][1][0][RTW89_QATAR][1][23] = 66, + [0][0][1][0][RTW89_QATAR][0][23] = 28, + [0][0][1][0][RTW89_UK][1][23] = 66, + [0][0][1][0][RTW89_UK][0][23] = 28, + [0][0][1][0][RTW89_FCC][1][25] = 22, + [0][0][1][0][RTW89_FCC][2][25] = 70, + [0][0][1][0][RTW89_ETSI][1][25] = 66, + [0][0][1][0][RTW89_ETSI][0][25] = 28, + [0][0][1][0][RTW89_MKK][1][25] = 66, + [0][0][1][0][RTW89_MKK][0][25] = 26, + [0][0][1][0][RTW89_IC][1][25] = 22, + [0][0][1][0][RTW89_KCC][1][25] = 24, + [0][0][1][0][RTW89_KCC][0][25] = 26, + [0][0][1][0][RTW89_ACMA][1][25] = 66, + [0][0][1][0][RTW89_ACMA][0][25] = 28, + [0][0][1][0][RTW89_CHILE][1][25] = 22, + [0][0][1][0][RTW89_QATAR][1][25] = 66, + [0][0][1][0][RTW89_QATAR][0][25] = 28, + [0][0][1][0][RTW89_UK][1][25] = 66, + [0][0][1][0][RTW89_UK][0][25] = 28, + [0][0][1][0][RTW89_FCC][1][27] = 22, + [0][0][1][0][RTW89_FCC][2][27] = 70, + [0][0][1][0][RTW89_ETSI][1][27] = 66, + [0][0][1][0][RTW89_ETSI][0][27] = 28, + [0][0][1][0][RTW89_MKK][1][27] = 66, + [0][0][1][0][RTW89_MKK][0][27] = 26, + [0][0][1][0][RTW89_IC][1][27] = 22, + [0][0][1][0][RTW89_KCC][1][27] = 24, + [0][0][1][0][RTW89_KCC][0][27] = 26, + [0][0][1][0][RTW89_ACMA][1][27] = 66, + [0][0][1][0][RTW89_ACMA][0][27] = 28, + [0][0][1][0][RTW89_CHILE][1][27] = 22, + [0][0][1][0][RTW89_QATAR][1][27] = 66, + [0][0][1][0][RTW89_QATAR][0][27] = 28, + [0][0][1][0][RTW89_UK][1][27] = 66, + [0][0][1][0][RTW89_UK][0][27] = 28, + [0][0][1][0][RTW89_FCC][1][29] = 22, + [0][0][1][0][RTW89_FCC][2][29] = 70, + [0][0][1][0][RTW89_ETSI][1][29] = 66, + [0][0][1][0][RTW89_ETSI][0][29] = 28, + [0][0][1][0][RTW89_MKK][1][29] = 66, + [0][0][1][0][RTW89_MKK][0][29] = 26, + [0][0][1][0][RTW89_IC][1][29] = 22, + [0][0][1][0][RTW89_KCC][1][29] = 24, + [0][0][1][0][RTW89_KCC][0][29] = 26, + [0][0][1][0][RTW89_ACMA][1][29] = 66, + [0][0][1][0][RTW89_ACMA][0][29] = 28, + [0][0][1][0][RTW89_CHILE][1][29] = 22, + [0][0][1][0][RTW89_QATAR][1][29] = 66, + [0][0][1][0][RTW89_QATAR][0][29] = 28, + [0][0][1][0][RTW89_UK][1][29] = 66, + [0][0][1][0][RTW89_UK][0][29] = 28, + [0][0][1][0][RTW89_FCC][1][30] = 22, + [0][0][1][0][RTW89_FCC][2][30] = 70, + [0][0][1][0][RTW89_ETSI][1][30] = 66, + [0][0][1][0][RTW89_ETSI][0][30] = 28, + [0][0][1][0][RTW89_MKK][1][30] = 66, + [0][0][1][0][RTW89_MKK][0][30] = 26, + [0][0][1][0][RTW89_IC][1][30] = 22, + [0][0][1][0][RTW89_KCC][1][30] = 24, + [0][0][1][0][RTW89_KCC][0][30] = 26, + [0][0][1][0][RTW89_ACMA][1][30] = 66, + [0][0][1][0][RTW89_ACMA][0][30] = 28, + [0][0][1][0][RTW89_CHILE][1][30] = 22, + [0][0][1][0][RTW89_QATAR][1][30] = 66, + [0][0][1][0][RTW89_QATAR][0][30] = 28, + [0][0][1][0][RTW89_UK][1][30] = 66, + [0][0][1][0][RTW89_UK][0][30] = 28, + [0][0][1][0][RTW89_FCC][1][32] = 22, + [0][0][1][0][RTW89_FCC][2][32] = 70, + [0][0][1][0][RTW89_ETSI][1][32] = 66, + [0][0][1][0][RTW89_ETSI][0][32] = 28, + [0][0][1][0][RTW89_MKK][1][32] = 66, + [0][0][1][0][RTW89_MKK][0][32] = 26, + [0][0][1][0][RTW89_IC][1][32] = 22, + [0][0][1][0][RTW89_KCC][1][32] = 24, + [0][0][1][0][RTW89_KCC][0][32] = 26, + [0][0][1][0][RTW89_ACMA][1][32] = 66, + [0][0][1][0][RTW89_ACMA][0][32] = 28, + [0][0][1][0][RTW89_CHILE][1][32] = 22, + [0][0][1][0][RTW89_QATAR][1][32] = 66, + [0][0][1][0][RTW89_QATAR][0][32] = 28, + [0][0][1][0][RTW89_UK][1][32] = 66, + [0][0][1][0][RTW89_UK][0][32] = 28, + [0][0][1][0][RTW89_FCC][1][34] = 22, + [0][0][1][0][RTW89_FCC][2][34] = 70, + [0][0][1][0][RTW89_ETSI][1][34] = 66, + [0][0][1][0][RTW89_ETSI][0][34] = 28, + [0][0][1][0][RTW89_MKK][1][34] = 66, + [0][0][1][0][RTW89_MKK][0][34] = 26, + [0][0][1][0][RTW89_IC][1][34] = 22, + [0][0][1][0][RTW89_KCC][1][34] = 24, + [0][0][1][0][RTW89_KCC][0][34] = 26, + [0][0][1][0][RTW89_ACMA][1][34] = 66, + [0][0][1][0][RTW89_ACMA][0][34] = 28, + [0][0][1][0][RTW89_CHILE][1][34] = 22, + [0][0][1][0][RTW89_QATAR][1][34] = 66, + [0][0][1][0][RTW89_QATAR][0][34] = 28, + [0][0][1][0][RTW89_UK][1][34] = 66, + [0][0][1][0][RTW89_UK][0][34] = 28, + [0][0][1][0][RTW89_FCC][1][36] = 22, + [0][0][1][0][RTW89_FCC][2][36] = 70, + [0][0][1][0][RTW89_ETSI][1][36] = 66, + [0][0][1][0][RTW89_ETSI][0][36] = 28, + [0][0][1][0][RTW89_MKK][1][36] = 66, + [0][0][1][0][RTW89_MKK][0][36] = 26, + [0][0][1][0][RTW89_IC][1][36] = 22, + [0][0][1][0][RTW89_KCC][1][36] = 24, + [0][0][1][0][RTW89_KCC][0][36] = 26, + [0][0][1][0][RTW89_ACMA][1][36] = 66, + [0][0][1][0][RTW89_ACMA][0][36] = 28, + [0][0][1][0][RTW89_CHILE][1][36] = 22, + [0][0][1][0][RTW89_QATAR][1][36] = 66, + [0][0][1][0][RTW89_QATAR][0][36] = 28, + [0][0][1][0][RTW89_UK][1][36] = 66, + [0][0][1][0][RTW89_UK][0][36] = 28, + [0][0][1][0][RTW89_FCC][1][38] = 22, + [0][0][1][0][RTW89_FCC][2][38] = 70, + [0][0][1][0][RTW89_ETSI][1][38] = 66, + [0][0][1][0][RTW89_ETSI][0][38] = 28, + [0][0][1][0][RTW89_MKK][1][38] = 66, + [0][0][1][0][RTW89_MKK][0][38] = 26, + [0][0][1][0][RTW89_IC][1][38] = 22, + [0][0][1][0][RTW89_KCC][1][38] = 24, + [0][0][1][0][RTW89_KCC][0][38] = 26, + [0][0][1][0][RTW89_ACMA][1][38] = 66, + [0][0][1][0][RTW89_ACMA][0][38] = 28, + [0][0][1][0][RTW89_CHILE][1][38] = 22, + [0][0][1][0][RTW89_QATAR][1][38] = 66, + [0][0][1][0][RTW89_QATAR][0][38] = 28, + [0][0][1][0][RTW89_UK][1][38] = 66, + [0][0][1][0][RTW89_UK][0][38] = 28, + [0][0][1][0][RTW89_FCC][1][40] = 22, + [0][0][1][0][RTW89_FCC][2][40] = 70, + [0][0][1][0][RTW89_ETSI][1][40] = 66, + [0][0][1][0][RTW89_ETSI][0][40] = 28, + [0][0][1][0][RTW89_MKK][1][40] = 66, + [0][0][1][0][RTW89_MKK][0][40] = 26, + [0][0][1][0][RTW89_IC][1][40] = 22, + [0][0][1][0][RTW89_KCC][1][40] = 24, + [0][0][1][0][RTW89_KCC][0][40] = 26, + [0][0][1][0][RTW89_ACMA][1][40] = 66, + [0][0][1][0][RTW89_ACMA][0][40] = 28, + [0][0][1][0][RTW89_CHILE][1][40] = 22, + [0][0][1][0][RTW89_QATAR][1][40] = 66, + [0][0][1][0][RTW89_QATAR][0][40] = 28, + [0][0][1][0][RTW89_UK][1][40] = 66, + [0][0][1][0][RTW89_UK][0][40] = 28, + [0][0][1][0][RTW89_FCC][1][42] = 22, + [0][0][1][0][RTW89_FCC][2][42] = 70, + [0][0][1][0][RTW89_ETSI][1][42] = 66, + [0][0][1][0][RTW89_ETSI][0][42] = 28, + [0][0][1][0][RTW89_MKK][1][42] = 66, + [0][0][1][0][RTW89_MKK][0][42] = 26, + [0][0][1][0][RTW89_IC][1][42] = 22, + [0][0][1][0][RTW89_KCC][1][42] = 24, + [0][0][1][0][RTW89_KCC][0][42] = 26, + [0][0][1][0][RTW89_ACMA][1][42] = 66, + [0][0][1][0][RTW89_ACMA][0][42] = 28, + [0][0][1][0][RTW89_CHILE][1][42] = 22, + [0][0][1][0][RTW89_QATAR][1][42] = 66, + [0][0][1][0][RTW89_QATAR][0][42] = 28, + [0][0][1][0][RTW89_UK][1][42] = 66, + [0][0][1][0][RTW89_UK][0][42] = 28, + [0][0][1][0][RTW89_FCC][1][44] = 22, + [0][0][1][0][RTW89_FCC][2][44] = 70, + [0][0][1][0][RTW89_ETSI][1][44] = 66, + [0][0][1][0][RTW89_ETSI][0][44] = 30, + [0][0][1][0][RTW89_MKK][1][44] = 44, + [0][0][1][0][RTW89_MKK][0][44] = 28, + [0][0][1][0][RTW89_IC][1][44] = 22, + [0][0][1][0][RTW89_KCC][1][44] = 24, + [0][0][1][0][RTW89_KCC][0][44] = 26, + [0][0][1][0][RTW89_ACMA][1][44] = 66, + [0][0][1][0][RTW89_ACMA][0][44] = 30, + [0][0][1][0][RTW89_CHILE][1][44] = 22, + [0][0][1][0][RTW89_QATAR][1][44] = 66, + [0][0][1][0][RTW89_QATAR][0][44] = 30, + [0][0][1][0][RTW89_UK][1][44] = 66, + [0][0][1][0][RTW89_UK][0][44] = 30, + [0][0][1][0][RTW89_FCC][1][45] = 22, + [0][0][1][0][RTW89_FCC][2][45] = 127, + [0][0][1][0][RTW89_ETSI][1][45] = 127, + [0][0][1][0][RTW89_ETSI][0][45] = 127, + [0][0][1][0][RTW89_MKK][1][45] = 127, + [0][0][1][0][RTW89_MKK][0][45] = 127, + [0][0][1][0][RTW89_IC][1][45] = 22, + [0][0][1][0][RTW89_KCC][1][45] = 24, + [0][0][1][0][RTW89_KCC][0][45] = 127, + [0][0][1][0][RTW89_ACMA][1][45] = 127, + [0][0][1][0][RTW89_ACMA][0][45] = 127, + [0][0][1][0][RTW89_CHILE][1][45] = 22, + [0][0][1][0][RTW89_QATAR][1][45] = 127, + [0][0][1][0][RTW89_QATAR][0][45] = 127, + [0][0][1][0][RTW89_UK][1][45] = 127, + [0][0][1][0][RTW89_UK][0][45] = 127, + [0][0][1][0][RTW89_FCC][1][47] = 22, + [0][0][1][0][RTW89_FCC][2][47] = 127, + [0][0][1][0][RTW89_ETSI][1][47] = 127, + [0][0][1][0][RTW89_ETSI][0][47] = 127, + [0][0][1][0][RTW89_MKK][1][47] = 127, + [0][0][1][0][RTW89_MKK][0][47] = 127, + [0][0][1][0][RTW89_IC][1][47] = 22, + [0][0][1][0][RTW89_KCC][1][47] = 24, + [0][0][1][0][RTW89_KCC][0][47] = 127, + [0][0][1][0][RTW89_ACMA][1][47] = 127, + [0][0][1][0][RTW89_ACMA][0][47] = 127, + [0][0][1][0][RTW89_CHILE][1][47] = 22, + [0][0][1][0][RTW89_QATAR][1][47] = 127, + [0][0][1][0][RTW89_QATAR][0][47] = 127, + [0][0][1][0][RTW89_UK][1][47] = 127, + [0][0][1][0][RTW89_UK][0][47] = 127, + [0][0][1][0][RTW89_FCC][1][49] = 24, + [0][0][1][0][RTW89_FCC][2][49] = 127, + [0][0][1][0][RTW89_ETSI][1][49] = 127, + [0][0][1][0][RTW89_ETSI][0][49] = 127, + [0][0][1][0][RTW89_MKK][1][49] = 127, + [0][0][1][0][RTW89_MKK][0][49] = 127, + [0][0][1][0][RTW89_IC][1][49] = 24, + [0][0][1][0][RTW89_KCC][1][49] = 24, + [0][0][1][0][RTW89_KCC][0][49] = 127, + [0][0][1][0][RTW89_ACMA][1][49] = 127, + [0][0][1][0][RTW89_ACMA][0][49] = 127, + [0][0][1][0][RTW89_CHILE][1][49] = 24, + [0][0][1][0][RTW89_QATAR][1][49] = 127, + [0][0][1][0][RTW89_QATAR][0][49] = 127, + [0][0][1][0][RTW89_UK][1][49] = 127, + [0][0][1][0][RTW89_UK][0][49] = 127, + [0][0][1][0][RTW89_FCC][1][51] = 22, + [0][0][1][0][RTW89_FCC][2][51] = 127, + [0][0][1][0][RTW89_ETSI][1][51] = 127, + [0][0][1][0][RTW89_ETSI][0][51] = 127, + [0][0][1][0][RTW89_MKK][1][51] = 127, + [0][0][1][0][RTW89_MKK][0][51] = 127, + [0][0][1][0][RTW89_IC][1][51] = 22, + [0][0][1][0][RTW89_KCC][1][51] = 24, + [0][0][1][0][RTW89_KCC][0][51] = 127, + [0][0][1][0][RTW89_ACMA][1][51] = 127, + [0][0][1][0][RTW89_ACMA][0][51] = 127, + [0][0][1][0][RTW89_CHILE][1][51] = 22, + [0][0][1][0][RTW89_QATAR][1][51] = 127, + [0][0][1][0][RTW89_QATAR][0][51] = 127, + [0][0][1][0][RTW89_UK][1][51] = 127, + [0][0][1][0][RTW89_UK][0][51] = 127, + [0][0][1][0][RTW89_FCC][1][53] = 22, + [0][0][1][0][RTW89_FCC][2][53] = 127, + [0][0][1][0][RTW89_ETSI][1][53] = 127, + [0][0][1][0][RTW89_ETSI][0][53] = 127, + [0][0][1][0][RTW89_MKK][1][53] = 127, + [0][0][1][0][RTW89_MKK][0][53] = 127, + [0][0][1][0][RTW89_IC][1][53] = 22, + [0][0][1][0][RTW89_KCC][1][53] = 24, + [0][0][1][0][RTW89_KCC][0][53] = 127, + [0][0][1][0][RTW89_ACMA][1][53] = 127, + [0][0][1][0][RTW89_ACMA][0][53] = 127, + [0][0][1][0][RTW89_CHILE][1][53] = 22, + [0][0][1][0][RTW89_QATAR][1][53] = 127, + [0][0][1][0][RTW89_QATAR][0][53] = 127, + [0][0][1][0][RTW89_UK][1][53] = 127, + [0][0][1][0][RTW89_UK][0][53] = 127, + [0][0][1][0][RTW89_FCC][1][55] = 22, + [0][0][1][0][RTW89_FCC][2][55] = 68, + [0][0][1][0][RTW89_ETSI][1][55] = 127, + [0][0][1][0][RTW89_ETSI][0][55] = 127, + [0][0][1][0][RTW89_MKK][1][55] = 127, + [0][0][1][0][RTW89_MKK][0][55] = 127, + [0][0][1][0][RTW89_IC][1][55] = 22, + [0][0][1][0][RTW89_KCC][1][55] = 26, + [0][0][1][0][RTW89_KCC][0][55] = 127, + [0][0][1][0][RTW89_ACMA][1][55] = 127, + [0][0][1][0][RTW89_ACMA][0][55] = 127, + [0][0][1][0][RTW89_CHILE][1][55] = 22, + [0][0][1][0][RTW89_QATAR][1][55] = 127, + [0][0][1][0][RTW89_QATAR][0][55] = 127, + [0][0][1][0][RTW89_UK][1][55] = 127, + [0][0][1][0][RTW89_UK][0][55] = 127, + [0][0][1][0][RTW89_FCC][1][57] = 22, + [0][0][1][0][RTW89_FCC][2][57] = 68, + [0][0][1][0][RTW89_ETSI][1][57] = 127, + [0][0][1][0][RTW89_ETSI][0][57] = 127, + [0][0][1][0][RTW89_MKK][1][57] = 127, + [0][0][1][0][RTW89_MKK][0][57] = 127, + [0][0][1][0][RTW89_IC][1][57] = 22, + [0][0][1][0][RTW89_KCC][1][57] = 26, + [0][0][1][0][RTW89_KCC][0][57] = 127, + [0][0][1][0][RTW89_ACMA][1][57] = 127, + [0][0][1][0][RTW89_ACMA][0][57] = 127, + [0][0][1][0][RTW89_CHILE][1][57] = 22, + [0][0][1][0][RTW89_QATAR][1][57] = 127, + [0][0][1][0][RTW89_QATAR][0][57] = 127, + [0][0][1][0][RTW89_UK][1][57] = 127, + [0][0][1][0][RTW89_UK][0][57] = 127, + [0][0][1][0][RTW89_FCC][1][59] = 22, + [0][0][1][0][RTW89_FCC][2][59] = 68, + [0][0][1][0][RTW89_ETSI][1][59] = 127, + [0][0][1][0][RTW89_ETSI][0][59] = 127, + [0][0][1][0][RTW89_MKK][1][59] = 127, + [0][0][1][0][RTW89_MKK][0][59] = 127, + [0][0][1][0][RTW89_IC][1][59] = 22, + [0][0][1][0][RTW89_KCC][1][59] = 26, + [0][0][1][0][RTW89_KCC][0][59] = 127, + [0][0][1][0][RTW89_ACMA][1][59] = 127, + [0][0][1][0][RTW89_ACMA][0][59] = 127, + [0][0][1][0][RTW89_CHILE][1][59] = 22, + [0][0][1][0][RTW89_QATAR][1][59] = 127, + [0][0][1][0][RTW89_QATAR][0][59] = 127, + [0][0][1][0][RTW89_UK][1][59] = 127, + [0][0][1][0][RTW89_UK][0][59] = 127, + [0][0][1][0][RTW89_FCC][1][60] = 22, + [0][0][1][0][RTW89_FCC][2][60] = 68, + [0][0][1][0][RTW89_ETSI][1][60] = 127, + [0][0][1][0][RTW89_ETSI][0][60] = 127, + [0][0][1][0][RTW89_MKK][1][60] = 127, + [0][0][1][0][RTW89_MKK][0][60] = 127, + [0][0][1][0][RTW89_IC][1][60] = 22, + [0][0][1][0][RTW89_KCC][1][60] = 26, + [0][0][1][0][RTW89_KCC][0][60] = 127, + [0][0][1][0][RTW89_ACMA][1][60] = 127, + [0][0][1][0][RTW89_ACMA][0][60] = 127, + [0][0][1][0][RTW89_CHILE][1][60] = 22, + [0][0][1][0][RTW89_QATAR][1][60] = 127, + [0][0][1][0][RTW89_QATAR][0][60] = 127, + [0][0][1][0][RTW89_UK][1][60] = 127, + [0][0][1][0][RTW89_UK][0][60] = 127, + [0][0][1][0][RTW89_FCC][1][62] = 22, + [0][0][1][0][RTW89_FCC][2][62] = 68, + [0][0][1][0][RTW89_ETSI][1][62] = 127, + [0][0][1][0][RTW89_ETSI][0][62] = 127, + [0][0][1][0][RTW89_MKK][1][62] = 127, + [0][0][1][0][RTW89_MKK][0][62] = 127, + [0][0][1][0][RTW89_IC][1][62] = 22, + [0][0][1][0][RTW89_KCC][1][62] = 26, + [0][0][1][0][RTW89_KCC][0][62] = 127, + [0][0][1][0][RTW89_ACMA][1][62] = 127, + [0][0][1][0][RTW89_ACMA][0][62] = 127, + [0][0][1][0][RTW89_CHILE][1][62] = 22, + [0][0][1][0][RTW89_QATAR][1][62] = 127, + [0][0][1][0][RTW89_QATAR][0][62] = 127, + [0][0][1][0][RTW89_UK][1][62] = 127, + [0][0][1][0][RTW89_UK][0][62] = 127, + [0][0][1][0][RTW89_FCC][1][64] = 22, + [0][0][1][0][RTW89_FCC][2][64] = 68, + [0][0][1][0][RTW89_ETSI][1][64] = 127, + [0][0][1][0][RTW89_ETSI][0][64] = 127, + [0][0][1][0][RTW89_MKK][1][64] = 127, + [0][0][1][0][RTW89_MKK][0][64] = 127, + [0][0][1][0][RTW89_IC][1][64] = 22, + [0][0][1][0][RTW89_KCC][1][64] = 26, + [0][0][1][0][RTW89_KCC][0][64] = 127, + [0][0][1][0][RTW89_ACMA][1][64] = 127, + [0][0][1][0][RTW89_ACMA][0][64] = 127, + [0][0][1][0][RTW89_CHILE][1][64] = 22, + [0][0][1][0][RTW89_QATAR][1][64] = 127, + [0][0][1][0][RTW89_QATAR][0][64] = 127, + [0][0][1][0][RTW89_UK][1][64] = 127, + [0][0][1][0][RTW89_UK][0][64] = 127, + [0][0][1][0][RTW89_FCC][1][66] = 22, + [0][0][1][0][RTW89_FCC][2][66] = 68, + [0][0][1][0][RTW89_ETSI][1][66] = 127, + [0][0][1][0][RTW89_ETSI][0][66] = 127, + [0][0][1][0][RTW89_MKK][1][66] = 127, + [0][0][1][0][RTW89_MKK][0][66] = 127, + [0][0][1][0][RTW89_IC][1][66] = 22, + [0][0][1][0][RTW89_KCC][1][66] = 26, + [0][0][1][0][RTW89_KCC][0][66] = 127, + [0][0][1][0][RTW89_ACMA][1][66] = 127, + [0][0][1][0][RTW89_ACMA][0][66] = 127, + [0][0][1][0][RTW89_CHILE][1][66] = 22, + [0][0][1][0][RTW89_QATAR][1][66] = 127, + [0][0][1][0][RTW89_QATAR][0][66] = 127, + [0][0][1][0][RTW89_UK][1][66] = 127, + [0][0][1][0][RTW89_UK][0][66] = 127, + [0][0][1][0][RTW89_FCC][1][68] = 22, + [0][0][1][0][RTW89_FCC][2][68] = 68, + [0][0][1][0][RTW89_ETSI][1][68] = 127, + [0][0][1][0][RTW89_ETSI][0][68] = 127, + [0][0][1][0][RTW89_MKK][1][68] = 127, + [0][0][1][0][RTW89_MKK][0][68] = 127, + [0][0][1][0][RTW89_IC][1][68] = 22, + [0][0][1][0][RTW89_KCC][1][68] = 26, + [0][0][1][0][RTW89_KCC][0][68] = 127, + [0][0][1][0][RTW89_ACMA][1][68] = 127, + [0][0][1][0][RTW89_ACMA][0][68] = 127, + [0][0][1][0][RTW89_CHILE][1][68] = 22, + [0][0][1][0][RTW89_QATAR][1][68] = 127, + [0][0][1][0][RTW89_QATAR][0][68] = 127, + [0][0][1][0][RTW89_UK][1][68] = 127, + [0][0][1][0][RTW89_UK][0][68] = 127, + [0][0][1][0][RTW89_FCC][1][70] = 24, + [0][0][1][0][RTW89_FCC][2][70] = 68, + [0][0][1][0][RTW89_ETSI][1][70] = 127, + [0][0][1][0][RTW89_ETSI][0][70] = 127, + [0][0][1][0][RTW89_MKK][1][70] = 127, + [0][0][1][0][RTW89_MKK][0][70] = 127, + [0][0][1][0][RTW89_IC][1][70] = 24, + [0][0][1][0][RTW89_KCC][1][70] = 26, + [0][0][1][0][RTW89_KCC][0][70] = 127, + [0][0][1][0][RTW89_ACMA][1][70] = 127, + [0][0][1][0][RTW89_ACMA][0][70] = 127, + [0][0][1][0][RTW89_CHILE][1][70] = 24, + [0][0][1][0][RTW89_QATAR][1][70] = 127, + [0][0][1][0][RTW89_QATAR][0][70] = 127, + [0][0][1][0][RTW89_UK][1][70] = 127, + [0][0][1][0][RTW89_UK][0][70] = 127, + [0][0][1][0][RTW89_FCC][1][72] = 22, + [0][0][1][0][RTW89_FCC][2][72] = 68, + [0][0][1][0][RTW89_ETSI][1][72] = 127, + [0][0][1][0][RTW89_ETSI][0][72] = 127, + [0][0][1][0][RTW89_MKK][1][72] = 127, + [0][0][1][0][RTW89_MKK][0][72] = 127, + [0][0][1][0][RTW89_IC][1][72] = 22, + [0][0][1][0][RTW89_KCC][1][72] = 26, + [0][0][1][0][RTW89_KCC][0][72] = 127, + [0][0][1][0][RTW89_ACMA][1][72] = 127, + [0][0][1][0][RTW89_ACMA][0][72] = 127, + [0][0][1][0][RTW89_CHILE][1][72] = 22, + [0][0][1][0][RTW89_QATAR][1][72] = 127, + [0][0][1][0][RTW89_QATAR][0][72] = 127, + [0][0][1][0][RTW89_UK][1][72] = 127, + [0][0][1][0][RTW89_UK][0][72] = 127, + [0][0][1][0][RTW89_FCC][1][74] = 22, + [0][0][1][0][RTW89_FCC][2][74] = 68, + [0][0][1][0][RTW89_ETSI][1][74] = 127, + [0][0][1][0][RTW89_ETSI][0][74] = 127, + [0][0][1][0][RTW89_MKK][1][74] = 127, + [0][0][1][0][RTW89_MKK][0][74] = 127, + [0][0][1][0][RTW89_IC][1][74] = 22, + [0][0][1][0][RTW89_KCC][1][74] = 26, + [0][0][1][0][RTW89_KCC][0][74] = 127, + [0][0][1][0][RTW89_ACMA][1][74] = 127, + [0][0][1][0][RTW89_ACMA][0][74] = 127, + [0][0][1][0][RTW89_CHILE][1][74] = 22, + [0][0][1][0][RTW89_QATAR][1][74] = 127, + [0][0][1][0][RTW89_QATAR][0][74] = 127, + [0][0][1][0][RTW89_UK][1][74] = 127, + [0][0][1][0][RTW89_UK][0][74] = 127, + [0][0][1][0][RTW89_FCC][1][75] = 22, + [0][0][1][0][RTW89_FCC][2][75] = 68, + [0][0][1][0][RTW89_ETSI][1][75] = 127, + [0][0][1][0][RTW89_ETSI][0][75] = 127, + [0][0][1][0][RTW89_MKK][1][75] = 127, + [0][0][1][0][RTW89_MKK][0][75] = 127, + [0][0][1][0][RTW89_IC][1][75] = 22, + [0][0][1][0][RTW89_KCC][1][75] = 26, + [0][0][1][0][RTW89_KCC][0][75] = 127, + [0][0][1][0][RTW89_ACMA][1][75] = 127, + [0][0][1][0][RTW89_ACMA][0][75] = 127, + [0][0][1][0][RTW89_CHILE][1][75] = 22, + [0][0][1][0][RTW89_QATAR][1][75] = 127, + [0][0][1][0][RTW89_QATAR][0][75] = 127, + [0][0][1][0][RTW89_UK][1][75] = 127, + [0][0][1][0][RTW89_UK][0][75] = 127, + [0][0][1][0][RTW89_FCC][1][77] = 22, + [0][0][1][0][RTW89_FCC][2][77] = 68, + [0][0][1][0][RTW89_ETSI][1][77] = 127, + [0][0][1][0][RTW89_ETSI][0][77] = 127, + [0][0][1][0][RTW89_MKK][1][77] = 127, + [0][0][1][0][RTW89_MKK][0][77] = 127, + [0][0][1][0][RTW89_IC][1][77] = 22, + [0][0][1][0][RTW89_KCC][1][77] = 26, + [0][0][1][0][RTW89_KCC][0][77] = 127, + [0][0][1][0][RTW89_ACMA][1][77] = 127, + [0][0][1][0][RTW89_ACMA][0][77] = 127, + [0][0][1][0][RTW89_CHILE][1][77] = 22, + [0][0][1][0][RTW89_QATAR][1][77] = 127, + [0][0][1][0][RTW89_QATAR][0][77] = 127, + [0][0][1][0][RTW89_UK][1][77] = 127, + [0][0][1][0][RTW89_UK][0][77] = 127, + [0][0][1][0][RTW89_FCC][1][79] = 22, + [0][0][1][0][RTW89_FCC][2][79] = 68, + [0][0][1][0][RTW89_ETSI][1][79] = 127, + [0][0][1][0][RTW89_ETSI][0][79] = 127, + [0][0][1][0][RTW89_MKK][1][79] = 127, + [0][0][1][0][RTW89_MKK][0][79] = 127, + [0][0][1][0][RTW89_IC][1][79] = 22, + [0][0][1][0][RTW89_KCC][1][79] = 26, + [0][0][1][0][RTW89_KCC][0][79] = 127, + [0][0][1][0][RTW89_ACMA][1][79] = 127, + [0][0][1][0][RTW89_ACMA][0][79] = 127, + [0][0][1][0][RTW89_CHILE][1][79] = 22, + [0][0][1][0][RTW89_QATAR][1][79] = 127, + [0][0][1][0][RTW89_QATAR][0][79] = 127, + [0][0][1][0][RTW89_UK][1][79] = 127, + [0][0][1][0][RTW89_UK][0][79] = 127, + [0][0][1][0][RTW89_FCC][1][81] = 22, + [0][0][1][0][RTW89_FCC][2][81] = 68, + [0][0][1][0][RTW89_ETSI][1][81] = 127, + [0][0][1][0][RTW89_ETSI][0][81] = 127, + [0][0][1][0][RTW89_MKK][1][81] = 127, + [0][0][1][0][RTW89_MKK][0][81] = 127, + [0][0][1][0][RTW89_IC][1][81] = 22, + [0][0][1][0][RTW89_KCC][1][81] = 26, + [0][0][1][0][RTW89_KCC][0][81] = 127, + [0][0][1][0][RTW89_ACMA][1][81] = 127, + [0][0][1][0][RTW89_ACMA][0][81] = 127, + [0][0][1][0][RTW89_CHILE][1][81] = 22, + [0][0][1][0][RTW89_QATAR][1][81] = 127, + [0][0][1][0][RTW89_QATAR][0][81] = 127, + [0][0][1][0][RTW89_UK][1][81] = 127, + [0][0][1][0][RTW89_UK][0][81] = 127, + [0][0][1][0][RTW89_FCC][1][83] = 22, + [0][0][1][0][RTW89_FCC][2][83] = 68, + [0][0][1][0][RTW89_ETSI][1][83] = 127, + [0][0][1][0][RTW89_ETSI][0][83] = 127, + [0][0][1][0][RTW89_MKK][1][83] = 127, + [0][0][1][0][RTW89_MKK][0][83] = 127, + [0][0][1][0][RTW89_IC][1][83] = 22, + [0][0][1][0][RTW89_KCC][1][83] = 32, + [0][0][1][0][RTW89_KCC][0][83] = 127, + [0][0][1][0][RTW89_ACMA][1][83] = 127, + [0][0][1][0][RTW89_ACMA][0][83] = 127, + [0][0][1][0][RTW89_CHILE][1][83] = 22, + [0][0][1][0][RTW89_QATAR][1][83] = 127, + [0][0][1][0][RTW89_QATAR][0][83] = 127, + [0][0][1][0][RTW89_UK][1][83] = 127, + [0][0][1][0][RTW89_UK][0][83] = 127, + [0][0][1][0][RTW89_FCC][1][85] = 22, + [0][0][1][0][RTW89_FCC][2][85] = 68, + [0][0][1][0][RTW89_ETSI][1][85] = 127, + [0][0][1][0][RTW89_ETSI][0][85] = 127, + [0][0][1][0][RTW89_MKK][1][85] = 127, + [0][0][1][0][RTW89_MKK][0][85] = 127, + [0][0][1][0][RTW89_IC][1][85] = 22, + [0][0][1][0][RTW89_KCC][1][85] = 32, + [0][0][1][0][RTW89_KCC][0][85] = 127, + [0][0][1][0][RTW89_ACMA][1][85] = 127, + [0][0][1][0][RTW89_ACMA][0][85] = 127, + [0][0][1][0][RTW89_CHILE][1][85] = 22, + [0][0][1][0][RTW89_QATAR][1][85] = 127, + [0][0][1][0][RTW89_QATAR][0][85] = 127, + [0][0][1][0][RTW89_UK][1][85] = 127, + [0][0][1][0][RTW89_UK][0][85] = 127, + [0][0][1][0][RTW89_FCC][1][87] = 22, + [0][0][1][0][RTW89_FCC][2][87] = 127, + [0][0][1][0][RTW89_ETSI][1][87] = 127, + [0][0][1][0][RTW89_ETSI][0][87] = 127, + [0][0][1][0][RTW89_MKK][1][87] = 127, + [0][0][1][0][RTW89_MKK][0][87] = 127, + [0][0][1][0][RTW89_IC][1][87] = 22, + [0][0][1][0][RTW89_KCC][1][87] = 32, + [0][0][1][0][RTW89_KCC][0][87] = 127, + [0][0][1][0][RTW89_ACMA][1][87] = 127, + [0][0][1][0][RTW89_ACMA][0][87] = 127, + [0][0][1][0][RTW89_CHILE][1][87] = 22, + [0][0][1][0][RTW89_QATAR][1][87] = 127, + [0][0][1][0][RTW89_QATAR][0][87] = 127, + [0][0][1][0][RTW89_UK][1][87] = 127, + [0][0][1][0][RTW89_UK][0][87] = 127, + [0][0][1][0][RTW89_FCC][1][89] = 22, + [0][0][1][0][RTW89_FCC][2][89] = 127, + [0][0][1][0][RTW89_ETSI][1][89] = 127, + [0][0][1][0][RTW89_ETSI][0][89] = 127, + [0][0][1][0][RTW89_MKK][1][89] = 127, + [0][0][1][0][RTW89_MKK][0][89] = 127, + [0][0][1][0][RTW89_IC][1][89] = 22, + [0][0][1][0][RTW89_KCC][1][89] = 32, + [0][0][1][0][RTW89_KCC][0][89] = 127, + [0][0][1][0][RTW89_ACMA][1][89] = 127, + [0][0][1][0][RTW89_ACMA][0][89] = 127, + [0][0][1][0][RTW89_CHILE][1][89] = 22, + [0][0][1][0][RTW89_QATAR][1][89] = 127, + [0][0][1][0][RTW89_QATAR][0][89] = 127, + [0][0][1][0][RTW89_UK][1][89] = 127, + [0][0][1][0][RTW89_UK][0][89] = 127, + [0][0][1][0][RTW89_FCC][1][90] = 22, + [0][0][1][0][RTW89_FCC][2][90] = 127, + [0][0][1][0][RTW89_ETSI][1][90] = 127, + [0][0][1][0][RTW89_ETSI][0][90] = 127, + [0][0][1][0][RTW89_MKK][1][90] = 127, + [0][0][1][0][RTW89_MKK][0][90] = 127, + [0][0][1][0][RTW89_IC][1][90] = 22, + [0][0][1][0][RTW89_KCC][1][90] = 32, + [0][0][1][0][RTW89_KCC][0][90] = 127, + [0][0][1][0][RTW89_ACMA][1][90] = 127, + [0][0][1][0][RTW89_ACMA][0][90] = 127, + [0][0][1][0][RTW89_CHILE][1][90] = 22, + [0][0][1][0][RTW89_QATAR][1][90] = 127, + [0][0][1][0][RTW89_QATAR][0][90] = 127, + [0][0][1][0][RTW89_UK][1][90] = 127, + [0][0][1][0][RTW89_UK][0][90] = 127, + [0][0][1][0][RTW89_FCC][1][92] = 22, + [0][0][1][0][RTW89_FCC][2][92] = 127, + [0][0][1][0][RTW89_ETSI][1][92] = 127, + [0][0][1][0][RTW89_ETSI][0][92] = 127, + [0][0][1][0][RTW89_MKK][1][92] = 127, + [0][0][1][0][RTW89_MKK][0][92] = 127, + [0][0][1][0][RTW89_IC][1][92] = 22, + [0][0][1][0][RTW89_KCC][1][92] = 32, + [0][0][1][0][RTW89_KCC][0][92] = 127, + [0][0][1][0][RTW89_ACMA][1][92] = 127, + [0][0][1][0][RTW89_ACMA][0][92] = 127, + [0][0][1][0][RTW89_CHILE][1][92] = 22, + [0][0][1][0][RTW89_QATAR][1][92] = 127, + [0][0][1][0][RTW89_QATAR][0][92] = 127, + [0][0][1][0][RTW89_UK][1][92] = 127, + [0][0][1][0][RTW89_UK][0][92] = 127, + [0][0][1][0][RTW89_FCC][1][94] = 22, + [0][0][1][0][RTW89_FCC][2][94] = 127, + [0][0][1][0][RTW89_ETSI][1][94] = 127, + [0][0][1][0][RTW89_ETSI][0][94] = 127, + [0][0][1][0][RTW89_MKK][1][94] = 127, + [0][0][1][0][RTW89_MKK][0][94] = 127, + [0][0][1][0][RTW89_IC][1][94] = 22, + [0][0][1][0][RTW89_KCC][1][94] = 32, + [0][0][1][0][RTW89_KCC][0][94] = 127, + [0][0][1][0][RTW89_ACMA][1][94] = 127, + [0][0][1][0][RTW89_ACMA][0][94] = 127, + [0][0][1][0][RTW89_CHILE][1][94] = 22, + [0][0][1][0][RTW89_QATAR][1][94] = 127, + [0][0][1][0][RTW89_QATAR][0][94] = 127, + [0][0][1][0][RTW89_UK][1][94] = 127, + [0][0][1][0][RTW89_UK][0][94] = 127, + [0][0][1][0][RTW89_FCC][1][96] = 22, + [0][0][1][0][RTW89_FCC][2][96] = 127, + [0][0][1][0][RTW89_ETSI][1][96] = 127, + [0][0][1][0][RTW89_ETSI][0][96] = 127, + [0][0][1][0][RTW89_MKK][1][96] = 127, + [0][0][1][0][RTW89_MKK][0][96] = 127, + [0][0][1][0][RTW89_IC][1][96] = 22, + [0][0][1][0][RTW89_KCC][1][96] = 32, + [0][0][1][0][RTW89_KCC][0][96] = 127, + [0][0][1][0][RTW89_ACMA][1][96] = 127, + [0][0][1][0][RTW89_ACMA][0][96] = 127, + [0][0][1][0][RTW89_CHILE][1][96] = 22, + [0][0][1][0][RTW89_QATAR][1][96] = 127, + [0][0][1][0][RTW89_QATAR][0][96] = 127, + [0][0][1][0][RTW89_UK][1][96] = 127, + [0][0][1][0][RTW89_UK][0][96] = 127, + [0][0][1][0][RTW89_FCC][1][98] = 22, + [0][0][1][0][RTW89_FCC][2][98] = 127, + [0][0][1][0][RTW89_ETSI][1][98] = 127, + [0][0][1][0][RTW89_ETSI][0][98] = 127, + [0][0][1][0][RTW89_MKK][1][98] = 127, + [0][0][1][0][RTW89_MKK][0][98] = 127, + [0][0][1][0][RTW89_IC][1][98] = 22, + [0][0][1][0][RTW89_KCC][1][98] = 32, + [0][0][1][0][RTW89_KCC][0][98] = 127, + [0][0][1][0][RTW89_ACMA][1][98] = 127, + [0][0][1][0][RTW89_ACMA][0][98] = 127, + [0][0][1][0][RTW89_CHILE][1][98] = 22, + [0][0][1][0][RTW89_QATAR][1][98] = 127, + [0][0][1][0][RTW89_QATAR][0][98] = 127, + [0][0][1][0][RTW89_UK][1][98] = 127, + [0][0][1][0][RTW89_UK][0][98] = 127, + [0][0][1][0][RTW89_FCC][1][100] = 22, + [0][0][1][0][RTW89_FCC][2][100] = 127, + [0][0][1][0][RTW89_ETSI][1][100] = 127, + [0][0][1][0][RTW89_ETSI][0][100] = 127, + [0][0][1][0][RTW89_MKK][1][100] = 127, + [0][0][1][0][RTW89_MKK][0][100] = 127, + [0][0][1][0][RTW89_IC][1][100] = 22, + [0][0][1][0][RTW89_KCC][1][100] = 32, + [0][0][1][0][RTW89_KCC][0][100] = 127, + [0][0][1][0][RTW89_ACMA][1][100] = 127, + [0][0][1][0][RTW89_ACMA][0][100] = 127, + [0][0][1][0][RTW89_CHILE][1][100] = 22, + [0][0][1][0][RTW89_QATAR][1][100] = 127, + [0][0][1][0][RTW89_QATAR][0][100] = 127, + [0][0][1][0][RTW89_UK][1][100] = 127, + [0][0][1][0][RTW89_UK][0][100] = 127, + [0][0][1][0][RTW89_FCC][1][102] = 22, + [0][0][1][0][RTW89_FCC][2][102] = 127, + [0][0][1][0][RTW89_ETSI][1][102] = 127, + [0][0][1][0][RTW89_ETSI][0][102] = 127, + [0][0][1][0][RTW89_MKK][1][102] = 127, + [0][0][1][0][RTW89_MKK][0][102] = 127, + [0][0][1][0][RTW89_IC][1][102] = 22, + [0][0][1][0][RTW89_KCC][1][102] = 32, + [0][0][1][0][RTW89_KCC][0][102] = 127, + [0][0][1][0][RTW89_ACMA][1][102] = 127, + [0][0][1][0][RTW89_ACMA][0][102] = 127, + [0][0][1][0][RTW89_CHILE][1][102] = 22, + [0][0][1][0][RTW89_QATAR][1][102] = 127, + [0][0][1][0][RTW89_QATAR][0][102] = 127, + [0][0][1][0][RTW89_UK][1][102] = 127, + [0][0][1][0][RTW89_UK][0][102] = 127, + [0][0][1][0][RTW89_FCC][1][104] = 22, + [0][0][1][0][RTW89_FCC][2][104] = 127, + [0][0][1][0][RTW89_ETSI][1][104] = 127, + [0][0][1][0][RTW89_ETSI][0][104] = 127, + [0][0][1][0][RTW89_MKK][1][104] = 127, + [0][0][1][0][RTW89_MKK][0][104] = 127, + [0][0][1][0][RTW89_IC][1][104] = 22, + [0][0][1][0][RTW89_KCC][1][104] = 32, + [0][0][1][0][RTW89_KCC][0][104] = 127, + [0][0][1][0][RTW89_ACMA][1][104] = 127, + [0][0][1][0][RTW89_ACMA][0][104] = 127, + [0][0][1][0][RTW89_CHILE][1][104] = 22, + [0][0][1][0][RTW89_QATAR][1][104] = 127, + [0][0][1][0][RTW89_QATAR][0][104] = 127, + [0][0][1][0][RTW89_UK][1][104] = 127, + [0][0][1][0][RTW89_UK][0][104] = 127, + [0][0][1][0][RTW89_FCC][1][105] = 22, + [0][0][1][0][RTW89_FCC][2][105] = 127, + [0][0][1][0][RTW89_ETSI][1][105] = 127, + [0][0][1][0][RTW89_ETSI][0][105] = 127, + [0][0][1][0][RTW89_MKK][1][105] = 127, + [0][0][1][0][RTW89_MKK][0][105] = 127, + [0][0][1][0][RTW89_IC][1][105] = 22, + [0][0][1][0][RTW89_KCC][1][105] = 32, + [0][0][1][0][RTW89_KCC][0][105] = 127, + [0][0][1][0][RTW89_ACMA][1][105] = 127, + [0][0][1][0][RTW89_ACMA][0][105] = 127, + [0][0][1][0][RTW89_CHILE][1][105] = 22, + [0][0][1][0][RTW89_QATAR][1][105] = 127, + [0][0][1][0][RTW89_QATAR][0][105] = 127, + [0][0][1][0][RTW89_UK][1][105] = 127, + [0][0][1][0][RTW89_UK][0][105] = 127, + [0][0][1][0][RTW89_FCC][1][107] = 24, + [0][0][1][0][RTW89_FCC][2][107] = 127, + [0][0][1][0][RTW89_ETSI][1][107] = 127, + [0][0][1][0][RTW89_ETSI][0][107] = 127, + [0][0][1][0][RTW89_MKK][1][107] = 127, + [0][0][1][0][RTW89_MKK][0][107] = 127, + [0][0][1][0][RTW89_IC][1][107] = 24, + [0][0][1][0][RTW89_KCC][1][107] = 32, + [0][0][1][0][RTW89_KCC][0][107] = 127, + [0][0][1][0][RTW89_ACMA][1][107] = 127, + [0][0][1][0][RTW89_ACMA][0][107] = 127, + [0][0][1][0][RTW89_CHILE][1][107] = 24, + [0][0][1][0][RTW89_QATAR][1][107] = 127, + [0][0][1][0][RTW89_QATAR][0][107] = 127, + [0][0][1][0][RTW89_UK][1][107] = 127, + [0][0][1][0][RTW89_UK][0][107] = 127, + [0][0][1][0][RTW89_FCC][1][109] = 24, + [0][0][1][0][RTW89_FCC][2][109] = 127, + [0][0][1][0][RTW89_ETSI][1][109] = 127, + [0][0][1][0][RTW89_ETSI][0][109] = 127, + [0][0][1][0][RTW89_MKK][1][109] = 127, + [0][0][1][0][RTW89_MKK][0][109] = 127, + [0][0][1][0][RTW89_IC][1][109] = 24, + [0][0][1][0][RTW89_KCC][1][109] = 32, + [0][0][1][0][RTW89_KCC][0][109] = 127, + [0][0][1][0][RTW89_ACMA][1][109] = 127, + [0][0][1][0][RTW89_ACMA][0][109] = 127, + [0][0][1][0][RTW89_CHILE][1][109] = 24, + [0][0][1][0][RTW89_QATAR][1][109] = 127, + [0][0][1][0][RTW89_QATAR][0][109] = 127, + [0][0][1][0][RTW89_UK][1][109] = 127, + [0][0][1][0][RTW89_UK][0][109] = 127, + [0][0][1][0][RTW89_FCC][1][111] = 127, + [0][0][1][0][RTW89_FCC][2][111] = 127, + [0][0][1][0][RTW89_ETSI][1][111] = 127, + [0][0][1][0][RTW89_ETSI][0][111] = 127, + [0][0][1][0][RTW89_MKK][1][111] = 127, + [0][0][1][0][RTW89_MKK][0][111] = 127, + [0][0][1][0][RTW89_IC][1][111] = 127, + [0][0][1][0][RTW89_KCC][1][111] = 127, + [0][0][1][0][RTW89_KCC][0][111] = 127, + [0][0][1][0][RTW89_ACMA][1][111] = 127, + [0][0][1][0][RTW89_ACMA][0][111] = 127, + [0][0][1][0][RTW89_CHILE][1][111] = 127, + [0][0][1][0][RTW89_QATAR][1][111] = 127, + [0][0][1][0][RTW89_QATAR][0][111] = 127, + [0][0][1][0][RTW89_UK][1][111] = 127, + [0][0][1][0][RTW89_UK][0][111] = 127, + [0][0][1][0][RTW89_FCC][1][113] = 127, + [0][0][1][0][RTW89_FCC][2][113] = 127, + [0][0][1][0][RTW89_ETSI][1][113] = 127, + [0][0][1][0][RTW89_ETSI][0][113] = 127, + [0][0][1][0][RTW89_MKK][1][113] = 127, + [0][0][1][0][RTW89_MKK][0][113] = 127, + [0][0][1][0][RTW89_IC][1][113] = 127, + [0][0][1][0][RTW89_KCC][1][113] = 127, + [0][0][1][0][RTW89_KCC][0][113] = 127, + [0][0][1][0][RTW89_ACMA][1][113] = 127, + [0][0][1][0][RTW89_ACMA][0][113] = 127, + [0][0][1][0][RTW89_CHILE][1][113] = 127, + [0][0][1][0][RTW89_QATAR][1][113] = 127, + [0][0][1][0][RTW89_QATAR][0][113] = 127, + [0][0][1][0][RTW89_UK][1][113] = 127, + [0][0][1][0][RTW89_UK][0][113] = 127, + [0][0][1][0][RTW89_FCC][1][115] = 127, + [0][0][1][0][RTW89_FCC][2][115] = 127, + [0][0][1][0][RTW89_ETSI][1][115] = 127, + [0][0][1][0][RTW89_ETSI][0][115] = 127, + [0][0][1][0][RTW89_MKK][1][115] = 127, + [0][0][1][0][RTW89_MKK][0][115] = 127, + [0][0][1][0][RTW89_IC][1][115] = 127, + [0][0][1][0][RTW89_KCC][1][115] = 127, + [0][0][1][0][RTW89_KCC][0][115] = 127, + [0][0][1][0][RTW89_ACMA][1][115] = 127, + [0][0][1][0][RTW89_ACMA][0][115] = 127, + [0][0][1][0][RTW89_CHILE][1][115] = 127, + [0][0][1][0][RTW89_QATAR][1][115] = 127, + [0][0][1][0][RTW89_QATAR][0][115] = 127, + [0][0][1][0][RTW89_UK][1][115] = 127, + [0][0][1][0][RTW89_UK][0][115] = 127, + [0][0][1][0][RTW89_FCC][1][117] = 127, + [0][0][1][0][RTW89_FCC][2][117] = 127, + [0][0][1][0][RTW89_ETSI][1][117] = 127, + [0][0][1][0][RTW89_ETSI][0][117] = 127, + [0][0][1][0][RTW89_MKK][1][117] = 127, + [0][0][1][0][RTW89_MKK][0][117] = 127, + [0][0][1][0][RTW89_IC][1][117] = 127, + [0][0][1][0][RTW89_KCC][1][117] = 127, + [0][0][1][0][RTW89_KCC][0][117] = 127, + [0][0][1][0][RTW89_ACMA][1][117] = 127, + [0][0][1][0][RTW89_ACMA][0][117] = 127, + [0][0][1][0][RTW89_CHILE][1][117] = 127, + [0][0][1][0][RTW89_QATAR][1][117] = 127, + [0][0][1][0][RTW89_QATAR][0][117] = 127, + [0][0][1][0][RTW89_UK][1][117] = 127, + [0][0][1][0][RTW89_UK][0][117] = 127, + [0][0][1][0][RTW89_FCC][1][119] = 127, + [0][0][1][0][RTW89_FCC][2][119] = 127, + [0][0][1][0][RTW89_ETSI][1][119] = 127, + [0][0][1][0][RTW89_ETSI][0][119] = 127, + [0][0][1][0][RTW89_MKK][1][119] = 127, + [0][0][1][0][RTW89_MKK][0][119] = 127, + [0][0][1][0][RTW89_IC][1][119] = 127, + [0][0][1][0][RTW89_KCC][1][119] = 127, + [0][0][1][0][RTW89_KCC][0][119] = 127, + [0][0][1][0][RTW89_ACMA][1][119] = 127, + [0][0][1][0][RTW89_ACMA][0][119] = 127, + [0][0][1][0][RTW89_CHILE][1][119] = 127, + [0][0][1][0][RTW89_QATAR][1][119] = 127, + [0][0][1][0][RTW89_QATAR][0][119] = 127, + [0][0][1][0][RTW89_UK][1][119] = 127, + [0][0][1][0][RTW89_UK][0][119] = 127, + [0][1][1][0][RTW89_FCC][1][0] = -2, + [0][1][1][0][RTW89_FCC][2][0] = 54, + [0][1][1][0][RTW89_ETSI][1][0] = 54, + [0][1][1][0][RTW89_ETSI][0][0] = 18, + [0][1][1][0][RTW89_MKK][1][0] = 56, + [0][1][1][0][RTW89_MKK][0][0] = 16, + [0][1][1][0][RTW89_IC][1][0] = -2, + [0][1][1][0][RTW89_KCC][1][0] = 12, + [0][1][1][0][RTW89_KCC][0][0] = 10, + [0][1][1][0][RTW89_ACMA][1][0] = 54, + [0][1][1][0][RTW89_ACMA][0][0] = 18, + [0][1][1][0][RTW89_CHILE][1][0] = -2, + [0][1][1][0][RTW89_QATAR][1][0] = 54, + [0][1][1][0][RTW89_QATAR][0][0] = 18, + [0][1][1][0][RTW89_UK][1][0] = 54, + [0][1][1][0][RTW89_UK][0][0] = 18, + [0][1][1][0][RTW89_FCC][1][2] = -4, + [0][1][1][0][RTW89_FCC][2][2] = 54, + [0][1][1][0][RTW89_ETSI][1][2] = 54, + [0][1][1][0][RTW89_ETSI][0][2] = 18, + [0][1][1][0][RTW89_MKK][1][2] = 54, + [0][1][1][0][RTW89_MKK][0][2] = 16, + [0][1][1][0][RTW89_IC][1][2] = -4, + [0][1][1][0][RTW89_KCC][1][2] = 12, + [0][1][1][0][RTW89_KCC][0][2] = 12, + [0][1][1][0][RTW89_ACMA][1][2] = 54, + [0][1][1][0][RTW89_ACMA][0][2] = 18, + [0][1][1][0][RTW89_CHILE][1][2] = -4, + [0][1][1][0][RTW89_QATAR][1][2] = 54, + [0][1][1][0][RTW89_QATAR][0][2] = 18, + [0][1][1][0][RTW89_UK][1][2] = 54, + [0][1][1][0][RTW89_UK][0][2] = 18, + [0][1][1][0][RTW89_FCC][1][4] = -4, + [0][1][1][0][RTW89_FCC][2][4] = 54, + [0][1][1][0][RTW89_ETSI][1][4] = 54, + [0][1][1][0][RTW89_ETSI][0][4] = 18, + [0][1][1][0][RTW89_MKK][1][4] = 54, + [0][1][1][0][RTW89_MKK][0][4] = 16, + [0][1][1][0][RTW89_IC][1][4] = -4, + [0][1][1][0][RTW89_KCC][1][4] = 12, + [0][1][1][0][RTW89_KCC][0][4] = 12, + [0][1][1][0][RTW89_ACMA][1][4] = 54, + [0][1][1][0][RTW89_ACMA][0][4] = 18, + [0][1][1][0][RTW89_CHILE][1][4] = -4, + [0][1][1][0][RTW89_QATAR][1][4] = 54, + [0][1][1][0][RTW89_QATAR][0][4] = 18, + [0][1][1][0][RTW89_UK][1][4] = 54, + [0][1][1][0][RTW89_UK][0][4] = 18, + [0][1][1][0][RTW89_FCC][1][6] = -4, + [0][1][1][0][RTW89_FCC][2][6] = 54, + [0][1][1][0][RTW89_ETSI][1][6] = 54, + [0][1][1][0][RTW89_ETSI][0][6] = 18, + [0][1][1][0][RTW89_MKK][1][6] = 54, + [0][1][1][0][RTW89_MKK][0][6] = 16, + [0][1][1][0][RTW89_IC][1][6] = -4, + [0][1][1][0][RTW89_KCC][1][6] = 12, + [0][1][1][0][RTW89_KCC][0][6] = 12, + [0][1][1][0][RTW89_ACMA][1][6] = 54, + [0][1][1][0][RTW89_ACMA][0][6] = 18, + [0][1][1][0][RTW89_CHILE][1][6] = -4, + [0][1][1][0][RTW89_QATAR][1][6] = 54, + [0][1][1][0][RTW89_QATAR][0][6] = 18, + [0][1][1][0][RTW89_UK][1][6] = 54, + [0][1][1][0][RTW89_UK][0][6] = 18, + [0][1][1][0][RTW89_FCC][1][8] = -4, + [0][1][1][0][RTW89_FCC][2][8] = 54, + [0][1][1][0][RTW89_ETSI][1][8] = 54, + [0][1][1][0][RTW89_ETSI][0][8] = 18, + [0][1][1][0][RTW89_MKK][1][8] = 54, + [0][1][1][0][RTW89_MKK][0][8] = 16, + [0][1][1][0][RTW89_IC][1][8] = -4, + [0][1][1][0][RTW89_KCC][1][8] = 12, + [0][1][1][0][RTW89_KCC][0][8] = 12, + [0][1][1][0][RTW89_ACMA][1][8] = 54, + [0][1][1][0][RTW89_ACMA][0][8] = 18, + [0][1][1][0][RTW89_CHILE][1][8] = -4, + [0][1][1][0][RTW89_QATAR][1][8] = 54, + [0][1][1][0][RTW89_QATAR][0][8] = 18, + [0][1][1][0][RTW89_UK][1][8] = 54, + [0][1][1][0][RTW89_UK][0][8] = 18, + [0][1][1][0][RTW89_FCC][1][10] = -4, + [0][1][1][0][RTW89_FCC][2][10] = 54, + [0][1][1][0][RTW89_ETSI][1][10] = 54, + [0][1][1][0][RTW89_ETSI][0][10] = 18, + [0][1][1][0][RTW89_MKK][1][10] = 54, + [0][1][1][0][RTW89_MKK][0][10] = 16, + [0][1][1][0][RTW89_IC][1][10] = -4, + [0][1][1][0][RTW89_KCC][1][10] = 12, + [0][1][1][0][RTW89_KCC][0][10] = 12, + [0][1][1][0][RTW89_ACMA][1][10] = 54, + [0][1][1][0][RTW89_ACMA][0][10] = 18, + [0][1][1][0][RTW89_CHILE][1][10] = -4, + [0][1][1][0][RTW89_QATAR][1][10] = 54, + [0][1][1][0][RTW89_QATAR][0][10] = 18, + [0][1][1][0][RTW89_UK][1][10] = 54, + [0][1][1][0][RTW89_UK][0][10] = 18, + [0][1][1][0][RTW89_FCC][1][12] = -4, + [0][1][1][0][RTW89_FCC][2][12] = 54, + [0][1][1][0][RTW89_ETSI][1][12] = 54, + [0][1][1][0][RTW89_ETSI][0][12] = 18, + [0][1][1][0][RTW89_MKK][1][12] = 54, + [0][1][1][0][RTW89_MKK][0][12] = 16, + [0][1][1][0][RTW89_IC][1][12] = -4, + [0][1][1][0][RTW89_KCC][1][12] = 12, + [0][1][1][0][RTW89_KCC][0][12] = 12, + [0][1][1][0][RTW89_ACMA][1][12] = 54, + [0][1][1][0][RTW89_ACMA][0][12] = 18, + [0][1][1][0][RTW89_CHILE][1][12] = -4, + [0][1][1][0][RTW89_QATAR][1][12] = 54, + [0][1][1][0][RTW89_QATAR][0][12] = 18, + [0][1][1][0][RTW89_UK][1][12] = 54, + [0][1][1][0][RTW89_UK][0][12] = 18, + [0][1][1][0][RTW89_FCC][1][14] = -4, + [0][1][1][0][RTW89_FCC][2][14] = 54, + [0][1][1][0][RTW89_ETSI][1][14] = 54, + [0][1][1][0][RTW89_ETSI][0][14] = 18, + [0][1][1][0][RTW89_MKK][1][14] = 54, + [0][1][1][0][RTW89_MKK][0][14] = 16, + [0][1][1][0][RTW89_IC][1][14] = -4, + [0][1][1][0][RTW89_KCC][1][14] = 12, + [0][1][1][0][RTW89_KCC][0][14] = 12, + [0][1][1][0][RTW89_ACMA][1][14] = 54, + [0][1][1][0][RTW89_ACMA][0][14] = 18, + [0][1][1][0][RTW89_CHILE][1][14] = -4, + [0][1][1][0][RTW89_QATAR][1][14] = 54, + [0][1][1][0][RTW89_QATAR][0][14] = 18, + [0][1][1][0][RTW89_UK][1][14] = 54, + [0][1][1][0][RTW89_UK][0][14] = 18, + [0][1][1][0][RTW89_FCC][1][15] = -4, + [0][1][1][0][RTW89_FCC][2][15] = 54, + [0][1][1][0][RTW89_ETSI][1][15] = 54, + [0][1][1][0][RTW89_ETSI][0][15] = 18, + [0][1][1][0][RTW89_MKK][1][15] = 54, + [0][1][1][0][RTW89_MKK][0][15] = 16, + [0][1][1][0][RTW89_IC][1][15] = -4, + [0][1][1][0][RTW89_KCC][1][15] = 12, + [0][1][1][0][RTW89_KCC][0][15] = 12, + [0][1][1][0][RTW89_ACMA][1][15] = 54, + [0][1][1][0][RTW89_ACMA][0][15] = 18, + [0][1][1][0][RTW89_CHILE][1][15] = -4, + [0][1][1][0][RTW89_QATAR][1][15] = 54, + [0][1][1][0][RTW89_QATAR][0][15] = 18, + [0][1][1][0][RTW89_UK][1][15] = 54, + [0][1][1][0][RTW89_UK][0][15] = 18, + [0][1][1][0][RTW89_FCC][1][17] = -4, + [0][1][1][0][RTW89_FCC][2][17] = 54, + [0][1][1][0][RTW89_ETSI][1][17] = 54, + [0][1][1][0][RTW89_ETSI][0][17] = 18, + [0][1][1][0][RTW89_MKK][1][17] = 54, + [0][1][1][0][RTW89_MKK][0][17] = 16, + [0][1][1][0][RTW89_IC][1][17] = -4, + [0][1][1][0][RTW89_KCC][1][17] = 12, + [0][1][1][0][RTW89_KCC][0][17] = 12, + [0][1][1][0][RTW89_ACMA][1][17] = 54, + [0][1][1][0][RTW89_ACMA][0][17] = 18, + [0][1][1][0][RTW89_CHILE][1][17] = -4, + [0][1][1][0][RTW89_QATAR][1][17] = 54, + [0][1][1][0][RTW89_QATAR][0][17] = 18, + [0][1][1][0][RTW89_UK][1][17] = 54, + [0][1][1][0][RTW89_UK][0][17] = 18, + [0][1][1][0][RTW89_FCC][1][19] = -4, + [0][1][1][0][RTW89_FCC][2][19] = 54, + [0][1][1][0][RTW89_ETSI][1][19] = 54, + [0][1][1][0][RTW89_ETSI][0][19] = 18, + [0][1][1][0][RTW89_MKK][1][19] = 54, + [0][1][1][0][RTW89_MKK][0][19] = 16, + [0][1][1][0][RTW89_IC][1][19] = -4, + [0][1][1][0][RTW89_KCC][1][19] = 12, + [0][1][1][0][RTW89_KCC][0][19] = 12, + [0][1][1][0][RTW89_ACMA][1][19] = 54, + [0][1][1][0][RTW89_ACMA][0][19] = 18, + [0][1][1][0][RTW89_CHILE][1][19] = -4, + [0][1][1][0][RTW89_QATAR][1][19] = 54, + [0][1][1][0][RTW89_QATAR][0][19] = 18, + [0][1][1][0][RTW89_UK][1][19] = 54, + [0][1][1][0][RTW89_UK][0][19] = 18, + [0][1][1][0][RTW89_FCC][1][21] = -4, + [0][1][1][0][RTW89_FCC][2][21] = 54, + [0][1][1][0][RTW89_ETSI][1][21] = 54, + [0][1][1][0][RTW89_ETSI][0][21] = 18, + [0][1][1][0][RTW89_MKK][1][21] = 54, + [0][1][1][0][RTW89_MKK][0][21] = 16, + [0][1][1][0][RTW89_IC][1][21] = -4, + [0][1][1][0][RTW89_KCC][1][21] = 12, + [0][1][1][0][RTW89_KCC][0][21] = 12, + [0][1][1][0][RTW89_ACMA][1][21] = 54, + [0][1][1][0][RTW89_ACMA][0][21] = 18, + [0][1][1][0][RTW89_CHILE][1][21] = -4, + [0][1][1][0][RTW89_QATAR][1][21] = 54, + [0][1][1][0][RTW89_QATAR][0][21] = 18, + [0][1][1][0][RTW89_UK][1][21] = 54, + [0][1][1][0][RTW89_UK][0][21] = 18, + [0][1][1][0][RTW89_FCC][1][23] = -4, + [0][1][1][0][RTW89_FCC][2][23] = 68, + [0][1][1][0][RTW89_ETSI][1][23] = 54, + [0][1][1][0][RTW89_ETSI][0][23] = 18, + [0][1][1][0][RTW89_MKK][1][23] = 54, + [0][1][1][0][RTW89_MKK][0][23] = 16, + [0][1][1][0][RTW89_IC][1][23] = -4, + [0][1][1][0][RTW89_KCC][1][23] = 12, + [0][1][1][0][RTW89_KCC][0][23] = 10, + [0][1][1][0][RTW89_ACMA][1][23] = 54, + [0][1][1][0][RTW89_ACMA][0][23] = 18, + [0][1][1][0][RTW89_CHILE][1][23] = -4, + [0][1][1][0][RTW89_QATAR][1][23] = 54, + [0][1][1][0][RTW89_QATAR][0][23] = 18, + [0][1][1][0][RTW89_UK][1][23] = 54, + [0][1][1][0][RTW89_UK][0][23] = 18, + [0][1][1][0][RTW89_FCC][1][25] = -4, + [0][1][1][0][RTW89_FCC][2][25] = 68, + [0][1][1][0][RTW89_ETSI][1][25] = 54, + [0][1][1][0][RTW89_ETSI][0][25] = 18, + [0][1][1][0][RTW89_MKK][1][25] = 54, + [0][1][1][0][RTW89_MKK][0][25] = 16, + [0][1][1][0][RTW89_IC][1][25] = -4, + [0][1][1][0][RTW89_KCC][1][25] = 12, + [0][1][1][0][RTW89_KCC][0][25] = 14, + [0][1][1][0][RTW89_ACMA][1][25] = 54, + [0][1][1][0][RTW89_ACMA][0][25] = 18, + [0][1][1][0][RTW89_CHILE][1][25] = -4, + [0][1][1][0][RTW89_QATAR][1][25] = 54, + [0][1][1][0][RTW89_QATAR][0][25] = 18, + [0][1][1][0][RTW89_UK][1][25] = 54, + [0][1][1][0][RTW89_UK][0][25] = 18, + [0][1][1][0][RTW89_FCC][1][27] = -4, + [0][1][1][0][RTW89_FCC][2][27] = 68, + [0][1][1][0][RTW89_ETSI][1][27] = 54, + [0][1][1][0][RTW89_ETSI][0][27] = 18, + [0][1][1][0][RTW89_MKK][1][27] = 54, + [0][1][1][0][RTW89_MKK][0][27] = 16, + [0][1][1][0][RTW89_IC][1][27] = -4, + [0][1][1][0][RTW89_KCC][1][27] = 12, + [0][1][1][0][RTW89_KCC][0][27] = 14, + [0][1][1][0][RTW89_ACMA][1][27] = 54, + [0][1][1][0][RTW89_ACMA][0][27] = 18, + [0][1][1][0][RTW89_CHILE][1][27] = -4, + [0][1][1][0][RTW89_QATAR][1][27] = 54, + [0][1][1][0][RTW89_QATAR][0][27] = 18, + [0][1][1][0][RTW89_UK][1][27] = 54, + [0][1][1][0][RTW89_UK][0][27] = 18, + [0][1][1][0][RTW89_FCC][1][29] = -4, + [0][1][1][0][RTW89_FCC][2][29] = 68, + [0][1][1][0][RTW89_ETSI][1][29] = 54, + [0][1][1][0][RTW89_ETSI][0][29] = 18, + [0][1][1][0][RTW89_MKK][1][29] = 54, + [0][1][1][0][RTW89_MKK][0][29] = 16, + [0][1][1][0][RTW89_IC][1][29] = -4, + [0][1][1][0][RTW89_KCC][1][29] = 12, + [0][1][1][0][RTW89_KCC][0][29] = 14, + [0][1][1][0][RTW89_ACMA][1][29] = 54, + [0][1][1][0][RTW89_ACMA][0][29] = 18, + [0][1][1][0][RTW89_CHILE][1][29] = -4, + [0][1][1][0][RTW89_QATAR][1][29] = 54, + [0][1][1][0][RTW89_QATAR][0][29] = 18, + [0][1][1][0][RTW89_UK][1][29] = 54, + [0][1][1][0][RTW89_UK][0][29] = 18, + [0][1][1][0][RTW89_FCC][1][30] = -4, + [0][1][1][0][RTW89_FCC][2][30] = 68, + [0][1][1][0][RTW89_ETSI][1][30] = 54, + [0][1][1][0][RTW89_ETSI][0][30] = 18, + [0][1][1][0][RTW89_MKK][1][30] = 54, + [0][1][1][0][RTW89_MKK][0][30] = 16, + [0][1][1][0][RTW89_IC][1][30] = -4, + [0][1][1][0][RTW89_KCC][1][30] = 12, + [0][1][1][0][RTW89_KCC][0][30] = 14, + [0][1][1][0][RTW89_ACMA][1][30] = 54, + [0][1][1][0][RTW89_ACMA][0][30] = 18, + [0][1][1][0][RTW89_CHILE][1][30] = -4, + [0][1][1][0][RTW89_QATAR][1][30] = 54, + [0][1][1][0][RTW89_QATAR][0][30] = 18, + [0][1][1][0][RTW89_UK][1][30] = 54, + [0][1][1][0][RTW89_UK][0][30] = 18, + [0][1][1][0][RTW89_FCC][1][32] = -4, + [0][1][1][0][RTW89_FCC][2][32] = 68, + [0][1][1][0][RTW89_ETSI][1][32] = 54, + [0][1][1][0][RTW89_ETSI][0][32] = 18, + [0][1][1][0][RTW89_MKK][1][32] = 54, + [0][1][1][0][RTW89_MKK][0][32] = 16, + [0][1][1][0][RTW89_IC][1][32] = -4, + [0][1][1][0][RTW89_KCC][1][32] = 12, + [0][1][1][0][RTW89_KCC][0][32] = 14, + [0][1][1][0][RTW89_ACMA][1][32] = 54, + [0][1][1][0][RTW89_ACMA][0][32] = 18, + [0][1][1][0][RTW89_CHILE][1][32] = -4, + [0][1][1][0][RTW89_QATAR][1][32] = 54, + [0][1][1][0][RTW89_QATAR][0][32] = 18, + [0][1][1][0][RTW89_UK][1][32] = 54, + [0][1][1][0][RTW89_UK][0][32] = 18, + [0][1][1][0][RTW89_FCC][1][34] = -4, + [0][1][1][0][RTW89_FCC][2][34] = 68, + [0][1][1][0][RTW89_ETSI][1][34] = 54, + [0][1][1][0][RTW89_ETSI][0][34] = 18, + [0][1][1][0][RTW89_MKK][1][34] = 54, + [0][1][1][0][RTW89_MKK][0][34] = 16, + [0][1][1][0][RTW89_IC][1][34] = -4, + [0][1][1][0][RTW89_KCC][1][34] = 12, + [0][1][1][0][RTW89_KCC][0][34] = 14, + [0][1][1][0][RTW89_ACMA][1][34] = 54, + [0][1][1][0][RTW89_ACMA][0][34] = 18, + [0][1][1][0][RTW89_CHILE][1][34] = -4, + [0][1][1][0][RTW89_QATAR][1][34] = 54, + [0][1][1][0][RTW89_QATAR][0][34] = 18, + [0][1][1][0][RTW89_UK][1][34] = 54, + [0][1][1][0][RTW89_UK][0][34] = 18, + [0][1][1][0][RTW89_FCC][1][36] = -4, + [0][1][1][0][RTW89_FCC][2][36] = 68, + [0][1][1][0][RTW89_ETSI][1][36] = 54, + [0][1][1][0][RTW89_ETSI][0][36] = 18, + [0][1][1][0][RTW89_MKK][1][36] = 54, + [0][1][1][0][RTW89_MKK][0][36] = 16, + [0][1][1][0][RTW89_IC][1][36] = -4, + [0][1][1][0][RTW89_KCC][1][36] = 12, + [0][1][1][0][RTW89_KCC][0][36] = 14, + [0][1][1][0][RTW89_ACMA][1][36] = 54, + [0][1][1][0][RTW89_ACMA][0][36] = 18, + [0][1][1][0][RTW89_CHILE][1][36] = -4, + [0][1][1][0][RTW89_QATAR][1][36] = 54, + [0][1][1][0][RTW89_QATAR][0][36] = 18, + [0][1][1][0][RTW89_UK][1][36] = 54, + [0][1][1][0][RTW89_UK][0][36] = 18, + [0][1][1][0][RTW89_FCC][1][38] = -4, + [0][1][1][0][RTW89_FCC][2][38] = 68, + [0][1][1][0][RTW89_ETSI][1][38] = 54, + [0][1][1][0][RTW89_ETSI][0][38] = 18, + [0][1][1][0][RTW89_MKK][1][38] = 54, + [0][1][1][0][RTW89_MKK][0][38] = 16, + [0][1][1][0][RTW89_IC][1][38] = -4, + [0][1][1][0][RTW89_KCC][1][38] = 12, + [0][1][1][0][RTW89_KCC][0][38] = 14, + [0][1][1][0][RTW89_ACMA][1][38] = 54, + [0][1][1][0][RTW89_ACMA][0][38] = 18, + [0][1][1][0][RTW89_CHILE][1][38] = -4, + [0][1][1][0][RTW89_QATAR][1][38] = 54, + [0][1][1][0][RTW89_QATAR][0][38] = 18, + [0][1][1][0][RTW89_UK][1][38] = 54, + [0][1][1][0][RTW89_UK][0][38] = 18, + [0][1][1][0][RTW89_FCC][1][40] = -4, + [0][1][1][0][RTW89_FCC][2][40] = 68, + [0][1][1][0][RTW89_ETSI][1][40] = 54, + [0][1][1][0][RTW89_ETSI][0][40] = 18, + [0][1][1][0][RTW89_MKK][1][40] = 54, + [0][1][1][0][RTW89_MKK][0][40] = 16, + [0][1][1][0][RTW89_IC][1][40] = -4, + [0][1][1][0][RTW89_KCC][1][40] = 12, + [0][1][1][0][RTW89_KCC][0][40] = 14, + [0][1][1][0][RTW89_ACMA][1][40] = 54, + [0][1][1][0][RTW89_ACMA][0][40] = 18, + [0][1][1][0][RTW89_CHILE][1][40] = -4, + [0][1][1][0][RTW89_QATAR][1][40] = 54, + [0][1][1][0][RTW89_QATAR][0][40] = 18, + [0][1][1][0][RTW89_UK][1][40] = 54, + [0][1][1][0][RTW89_UK][0][40] = 18, + [0][1][1][0][RTW89_FCC][1][42] = -4, + [0][1][1][0][RTW89_FCC][2][42] = 68, + [0][1][1][0][RTW89_ETSI][1][42] = 54, + [0][1][1][0][RTW89_ETSI][0][42] = 18, + [0][1][1][0][RTW89_MKK][1][42] = 54, + [0][1][1][0][RTW89_MKK][0][42] = 16, + [0][1][1][0][RTW89_IC][1][42] = -4, + [0][1][1][0][RTW89_KCC][1][42] = 12, + [0][1][1][0][RTW89_KCC][0][42] = 14, + [0][1][1][0][RTW89_ACMA][1][42] = 54, + [0][1][1][0][RTW89_ACMA][0][42] = 18, + [0][1][1][0][RTW89_CHILE][1][42] = -4, + [0][1][1][0][RTW89_QATAR][1][42] = 54, + [0][1][1][0][RTW89_QATAR][0][42] = 18, + [0][1][1][0][RTW89_UK][1][42] = 54, + [0][1][1][0][RTW89_UK][0][42] = 18, + [0][1][1][0][RTW89_FCC][1][44] = -2, + [0][1][1][0][RTW89_FCC][2][44] = 68, + [0][1][1][0][RTW89_ETSI][1][44] = 54, + [0][1][1][0][RTW89_ETSI][0][44] = 18, + [0][1][1][0][RTW89_MKK][1][44] = 34, + [0][1][1][0][RTW89_MKK][0][44] = 16, + [0][1][1][0][RTW89_IC][1][44] = -2, + [0][1][1][0][RTW89_KCC][1][44] = 12, + [0][1][1][0][RTW89_KCC][0][44] = 12, + [0][1][1][0][RTW89_ACMA][1][44] = 54, + [0][1][1][0][RTW89_ACMA][0][44] = 18, + [0][1][1][0][RTW89_CHILE][1][44] = -2, + [0][1][1][0][RTW89_QATAR][1][44] = 54, + [0][1][1][0][RTW89_QATAR][0][44] = 18, + [0][1][1][0][RTW89_UK][1][44] = 54, + [0][1][1][0][RTW89_UK][0][44] = 18, + [0][1][1][0][RTW89_FCC][1][45] = -2, + [0][1][1][0][RTW89_FCC][2][45] = 127, + [0][1][1][0][RTW89_ETSI][1][45] = 127, + [0][1][1][0][RTW89_ETSI][0][45] = 127, + [0][1][1][0][RTW89_MKK][1][45] = 127, + [0][1][1][0][RTW89_MKK][0][45] = 127, + [0][1][1][0][RTW89_IC][1][45] = -2, + [0][1][1][0][RTW89_KCC][1][45] = 12, + [0][1][1][0][RTW89_KCC][0][45] = 127, + [0][1][1][0][RTW89_ACMA][1][45] = 127, + [0][1][1][0][RTW89_ACMA][0][45] = 127, + [0][1][1][0][RTW89_CHILE][1][45] = -2, + [0][1][1][0][RTW89_QATAR][1][45] = 127, + [0][1][1][0][RTW89_QATAR][0][45] = 127, + [0][1][1][0][RTW89_UK][1][45] = 127, + [0][1][1][0][RTW89_UK][0][45] = 127, + [0][1][1][0][RTW89_FCC][1][47] = -2, + [0][1][1][0][RTW89_FCC][2][47] = 127, + [0][1][1][0][RTW89_ETSI][1][47] = 127, + [0][1][1][0][RTW89_ETSI][0][47] = 127, + [0][1][1][0][RTW89_MKK][1][47] = 127, + [0][1][1][0][RTW89_MKK][0][47] = 127, + [0][1][1][0][RTW89_IC][1][47] = -2, + [0][1][1][0][RTW89_KCC][1][47] = 12, + [0][1][1][0][RTW89_KCC][0][47] = 127, + [0][1][1][0][RTW89_ACMA][1][47] = 127, + [0][1][1][0][RTW89_ACMA][0][47] = 127, + [0][1][1][0][RTW89_CHILE][1][47] = -2, + [0][1][1][0][RTW89_QATAR][1][47] = 127, + [0][1][1][0][RTW89_QATAR][0][47] = 127, + [0][1][1][0][RTW89_UK][1][47] = 127, + [0][1][1][0][RTW89_UK][0][47] = 127, + [0][1][1][0][RTW89_FCC][1][49] = -2, + [0][1][1][0][RTW89_FCC][2][49] = 127, + [0][1][1][0][RTW89_ETSI][1][49] = 127, + [0][1][1][0][RTW89_ETSI][0][49] = 127, + [0][1][1][0][RTW89_MKK][1][49] = 127, + [0][1][1][0][RTW89_MKK][0][49] = 127, + [0][1][1][0][RTW89_IC][1][49] = -2, + [0][1][1][0][RTW89_KCC][1][49] = 12, + [0][1][1][0][RTW89_KCC][0][49] = 127, + [0][1][1][0][RTW89_ACMA][1][49] = 127, + [0][1][1][0][RTW89_ACMA][0][49] = 127, + [0][1][1][0][RTW89_CHILE][1][49] = -2, + [0][1][1][0][RTW89_QATAR][1][49] = 127, + [0][1][1][0][RTW89_QATAR][0][49] = 127, + [0][1][1][0][RTW89_UK][1][49] = 127, + [0][1][1][0][RTW89_UK][0][49] = 127, + [0][1][1][0][RTW89_FCC][1][51] = -2, + [0][1][1][0][RTW89_FCC][2][51] = 127, + [0][1][1][0][RTW89_ETSI][1][51] = 127, + [0][1][1][0][RTW89_ETSI][0][51] = 127, + [0][1][1][0][RTW89_MKK][1][51] = 127, + [0][1][1][0][RTW89_MKK][0][51] = 127, + [0][1][1][0][RTW89_IC][1][51] = -2, + [0][1][1][0][RTW89_KCC][1][51] = 12, + [0][1][1][0][RTW89_KCC][0][51] = 127, + [0][1][1][0][RTW89_ACMA][1][51] = 127, + [0][1][1][0][RTW89_ACMA][0][51] = 127, + [0][1][1][0][RTW89_CHILE][1][51] = -2, + [0][1][1][0][RTW89_QATAR][1][51] = 127, + [0][1][1][0][RTW89_QATAR][0][51] = 127, + [0][1][1][0][RTW89_UK][1][51] = 127, + [0][1][1][0][RTW89_UK][0][51] = 127, + [0][1][1][0][RTW89_FCC][1][53] = -2, + [0][1][1][0][RTW89_FCC][2][53] = 127, + [0][1][1][0][RTW89_ETSI][1][53] = 127, + [0][1][1][0][RTW89_ETSI][0][53] = 127, + [0][1][1][0][RTW89_MKK][1][53] = 127, + [0][1][1][0][RTW89_MKK][0][53] = 127, + [0][1][1][0][RTW89_IC][1][53] = -2, + [0][1][1][0][RTW89_KCC][1][53] = 12, + [0][1][1][0][RTW89_KCC][0][53] = 127, + [0][1][1][0][RTW89_ACMA][1][53] = 127, + [0][1][1][0][RTW89_ACMA][0][53] = 127, + [0][1][1][0][RTW89_CHILE][1][53] = -2, + [0][1][1][0][RTW89_QATAR][1][53] = 127, + [0][1][1][0][RTW89_QATAR][0][53] = 127, + [0][1][1][0][RTW89_UK][1][53] = 127, + [0][1][1][0][RTW89_UK][0][53] = 127, + [0][1][1][0][RTW89_FCC][1][55] = -2, + [0][1][1][0][RTW89_FCC][2][55] = 68, + [0][1][1][0][RTW89_ETSI][1][55] = 127, + [0][1][1][0][RTW89_ETSI][0][55] = 127, + [0][1][1][0][RTW89_MKK][1][55] = 127, + [0][1][1][0][RTW89_MKK][0][55] = 127, + [0][1][1][0][RTW89_IC][1][55] = -2, + [0][1][1][0][RTW89_KCC][1][55] = 12, + [0][1][1][0][RTW89_KCC][0][55] = 127, + [0][1][1][0][RTW89_ACMA][1][55] = 127, + [0][1][1][0][RTW89_ACMA][0][55] = 127, + [0][1][1][0][RTW89_CHILE][1][55] = -2, + [0][1][1][0][RTW89_QATAR][1][55] = 127, + [0][1][1][0][RTW89_QATAR][0][55] = 127, + [0][1][1][0][RTW89_UK][1][55] = 127, + [0][1][1][0][RTW89_UK][0][55] = 127, + [0][1][1][0][RTW89_FCC][1][57] = -2, + [0][1][1][0][RTW89_FCC][2][57] = 68, + [0][1][1][0][RTW89_ETSI][1][57] = 127, + [0][1][1][0][RTW89_ETSI][0][57] = 127, + [0][1][1][0][RTW89_MKK][1][57] = 127, + [0][1][1][0][RTW89_MKK][0][57] = 127, + [0][1][1][0][RTW89_IC][1][57] = -2, + [0][1][1][0][RTW89_KCC][1][57] = 12, + [0][1][1][0][RTW89_KCC][0][57] = 127, + [0][1][1][0][RTW89_ACMA][1][57] = 127, + [0][1][1][0][RTW89_ACMA][0][57] = 127, + [0][1][1][0][RTW89_CHILE][1][57] = -2, + [0][1][1][0][RTW89_QATAR][1][57] = 127, + [0][1][1][0][RTW89_QATAR][0][57] = 127, + [0][1][1][0][RTW89_UK][1][57] = 127, + [0][1][1][0][RTW89_UK][0][57] = 127, + [0][1][1][0][RTW89_FCC][1][59] = -2, + [0][1][1][0][RTW89_FCC][2][59] = 68, + [0][1][1][0][RTW89_ETSI][1][59] = 127, + [0][1][1][0][RTW89_ETSI][0][59] = 127, + [0][1][1][0][RTW89_MKK][1][59] = 127, + [0][1][1][0][RTW89_MKK][0][59] = 127, + [0][1][1][0][RTW89_IC][1][59] = -2, + [0][1][1][0][RTW89_KCC][1][59] = 12, + [0][1][1][0][RTW89_KCC][0][59] = 127, + [0][1][1][0][RTW89_ACMA][1][59] = 127, + [0][1][1][0][RTW89_ACMA][0][59] = 127, + [0][1][1][0][RTW89_CHILE][1][59] = -2, + [0][1][1][0][RTW89_QATAR][1][59] = 127, + [0][1][1][0][RTW89_QATAR][0][59] = 127, + [0][1][1][0][RTW89_UK][1][59] = 127, + [0][1][1][0][RTW89_UK][0][59] = 127, + [0][1][1][0][RTW89_FCC][1][60] = -2, + [0][1][1][0][RTW89_FCC][2][60] = 68, + [0][1][1][0][RTW89_ETSI][1][60] = 127, + [0][1][1][0][RTW89_ETSI][0][60] = 127, + [0][1][1][0][RTW89_MKK][1][60] = 127, + [0][1][1][0][RTW89_MKK][0][60] = 127, + [0][1][1][0][RTW89_IC][1][60] = -2, + [0][1][1][0][RTW89_KCC][1][60] = 12, + [0][1][1][0][RTW89_KCC][0][60] = 127, + [0][1][1][0][RTW89_ACMA][1][60] = 127, + [0][1][1][0][RTW89_ACMA][0][60] = 127, + [0][1][1][0][RTW89_CHILE][1][60] = -2, + [0][1][1][0][RTW89_QATAR][1][60] = 127, + [0][1][1][0][RTW89_QATAR][0][60] = 127, + [0][1][1][0][RTW89_UK][1][60] = 127, + [0][1][1][0][RTW89_UK][0][60] = 127, + [0][1][1][0][RTW89_FCC][1][62] = -2, + [0][1][1][0][RTW89_FCC][2][62] = 68, + [0][1][1][0][RTW89_ETSI][1][62] = 127, + [0][1][1][0][RTW89_ETSI][0][62] = 127, + [0][1][1][0][RTW89_MKK][1][62] = 127, + [0][1][1][0][RTW89_MKK][0][62] = 127, + [0][1][1][0][RTW89_IC][1][62] = -2, + [0][1][1][0][RTW89_KCC][1][62] = 12, + [0][1][1][0][RTW89_KCC][0][62] = 127, + [0][1][1][0][RTW89_ACMA][1][62] = 127, + [0][1][1][0][RTW89_ACMA][0][62] = 127, + [0][1][1][0][RTW89_CHILE][1][62] = -2, + [0][1][1][0][RTW89_QATAR][1][62] = 127, + [0][1][1][0][RTW89_QATAR][0][62] = 127, + [0][1][1][0][RTW89_UK][1][62] = 127, + [0][1][1][0][RTW89_UK][0][62] = 127, + [0][1][1][0][RTW89_FCC][1][64] = -2, + [0][1][1][0][RTW89_FCC][2][64] = 68, + [0][1][1][0][RTW89_ETSI][1][64] = 127, + [0][1][1][0][RTW89_ETSI][0][64] = 127, + [0][1][1][0][RTW89_MKK][1][64] = 127, + [0][1][1][0][RTW89_MKK][0][64] = 127, + [0][1][1][0][RTW89_IC][1][64] = -2, + [0][1][1][0][RTW89_KCC][1][64] = 12, + [0][1][1][0][RTW89_KCC][0][64] = 127, + [0][1][1][0][RTW89_ACMA][1][64] = 127, + [0][1][1][0][RTW89_ACMA][0][64] = 127, + [0][1][1][0][RTW89_CHILE][1][64] = -2, + [0][1][1][0][RTW89_QATAR][1][64] = 127, + [0][1][1][0][RTW89_QATAR][0][64] = 127, + [0][1][1][0][RTW89_UK][1][64] = 127, + [0][1][1][0][RTW89_UK][0][64] = 127, + [0][1][1][0][RTW89_FCC][1][66] = -2, + [0][1][1][0][RTW89_FCC][2][66] = 68, + [0][1][1][0][RTW89_ETSI][1][66] = 127, + [0][1][1][0][RTW89_ETSI][0][66] = 127, + [0][1][1][0][RTW89_MKK][1][66] = 127, + [0][1][1][0][RTW89_MKK][0][66] = 127, + [0][1][1][0][RTW89_IC][1][66] = -2, + [0][1][1][0][RTW89_KCC][1][66] = 12, + [0][1][1][0][RTW89_KCC][0][66] = 127, + [0][1][1][0][RTW89_ACMA][1][66] = 127, + [0][1][1][0][RTW89_ACMA][0][66] = 127, + [0][1][1][0][RTW89_CHILE][1][66] = -2, + [0][1][1][0][RTW89_QATAR][1][66] = 127, + [0][1][1][0][RTW89_QATAR][0][66] = 127, + [0][1][1][0][RTW89_UK][1][66] = 127, + [0][1][1][0][RTW89_UK][0][66] = 127, + [0][1][1][0][RTW89_FCC][1][68] = -2, + [0][1][1][0][RTW89_FCC][2][68] = 68, + [0][1][1][0][RTW89_ETSI][1][68] = 127, + [0][1][1][0][RTW89_ETSI][0][68] = 127, + [0][1][1][0][RTW89_MKK][1][68] = 127, + [0][1][1][0][RTW89_MKK][0][68] = 127, + [0][1][1][0][RTW89_IC][1][68] = -2, + [0][1][1][0][RTW89_KCC][1][68] = 12, + [0][1][1][0][RTW89_KCC][0][68] = 127, + [0][1][1][0][RTW89_ACMA][1][68] = 127, + [0][1][1][0][RTW89_ACMA][0][68] = 127, + [0][1][1][0][RTW89_CHILE][1][68] = -2, + [0][1][1][0][RTW89_QATAR][1][68] = 127, + [0][1][1][0][RTW89_QATAR][0][68] = 127, + [0][1][1][0][RTW89_UK][1][68] = 127, + [0][1][1][0][RTW89_UK][0][68] = 127, + [0][1][1][0][RTW89_FCC][1][70] = -2, + [0][1][1][0][RTW89_FCC][2][70] = 68, + [0][1][1][0][RTW89_ETSI][1][70] = 127, + [0][1][1][0][RTW89_ETSI][0][70] = 127, + [0][1][1][0][RTW89_MKK][1][70] = 127, + [0][1][1][0][RTW89_MKK][0][70] = 127, + [0][1][1][0][RTW89_IC][1][70] = -2, + [0][1][1][0][RTW89_KCC][1][70] = 12, + [0][1][1][0][RTW89_KCC][0][70] = 127, + [0][1][1][0][RTW89_ACMA][1][70] = 127, + [0][1][1][0][RTW89_ACMA][0][70] = 127, + [0][1][1][0][RTW89_CHILE][1][70] = -2, + [0][1][1][0][RTW89_QATAR][1][70] = 127, + [0][1][1][0][RTW89_QATAR][0][70] = 127, + [0][1][1][0][RTW89_UK][1][70] = 127, + [0][1][1][0][RTW89_UK][0][70] = 127, + [0][1][1][0][RTW89_FCC][1][72] = -2, + [0][1][1][0][RTW89_FCC][2][72] = 68, + [0][1][1][0][RTW89_ETSI][1][72] = 127, + [0][1][1][0][RTW89_ETSI][0][72] = 127, + [0][1][1][0][RTW89_MKK][1][72] = 127, + [0][1][1][0][RTW89_MKK][0][72] = 127, + [0][1][1][0][RTW89_IC][1][72] = -2, + [0][1][1][0][RTW89_KCC][1][72] = 12, + [0][1][1][0][RTW89_KCC][0][72] = 127, + [0][1][1][0][RTW89_ACMA][1][72] = 127, + [0][1][1][0][RTW89_ACMA][0][72] = 127, + [0][1][1][0][RTW89_CHILE][1][72] = -2, + [0][1][1][0][RTW89_QATAR][1][72] = 127, + [0][1][1][0][RTW89_QATAR][0][72] = 127, + [0][1][1][0][RTW89_UK][1][72] = 127, + [0][1][1][0][RTW89_UK][0][72] = 127, + [0][1][1][0][RTW89_FCC][1][74] = -2, + [0][1][1][0][RTW89_FCC][2][74] = 68, + [0][1][1][0][RTW89_ETSI][1][74] = 127, + [0][1][1][0][RTW89_ETSI][0][74] = 127, + [0][1][1][0][RTW89_MKK][1][74] = 127, + [0][1][1][0][RTW89_MKK][0][74] = 127, + [0][1][1][0][RTW89_IC][1][74] = -2, + [0][1][1][0][RTW89_KCC][1][74] = 12, + [0][1][1][0][RTW89_KCC][0][74] = 127, + [0][1][1][0][RTW89_ACMA][1][74] = 127, + [0][1][1][0][RTW89_ACMA][0][74] = 127, + [0][1][1][0][RTW89_CHILE][1][74] = -2, + [0][1][1][0][RTW89_QATAR][1][74] = 127, + [0][1][1][0][RTW89_QATAR][0][74] = 127, + [0][1][1][0][RTW89_UK][1][74] = 127, + [0][1][1][0][RTW89_UK][0][74] = 127, + [0][1][1][0][RTW89_FCC][1][75] = -2, + [0][1][1][0][RTW89_FCC][2][75] = 68, + [0][1][1][0][RTW89_ETSI][1][75] = 127, + [0][1][1][0][RTW89_ETSI][0][75] = 127, + [0][1][1][0][RTW89_MKK][1][75] = 127, + [0][1][1][0][RTW89_MKK][0][75] = 127, + [0][1][1][0][RTW89_IC][1][75] = -2, + [0][1][1][0][RTW89_KCC][1][75] = 12, + [0][1][1][0][RTW89_KCC][0][75] = 127, + [0][1][1][0][RTW89_ACMA][1][75] = 127, + [0][1][1][0][RTW89_ACMA][0][75] = 127, + [0][1][1][0][RTW89_CHILE][1][75] = -2, + [0][1][1][0][RTW89_QATAR][1][75] = 127, + [0][1][1][0][RTW89_QATAR][0][75] = 127, + [0][1][1][0][RTW89_UK][1][75] = 127, + [0][1][1][0][RTW89_UK][0][75] = 127, + [0][1][1][0][RTW89_FCC][1][77] = -2, + [0][1][1][0][RTW89_FCC][2][77] = 68, + [0][1][1][0][RTW89_ETSI][1][77] = 127, + [0][1][1][0][RTW89_ETSI][0][77] = 127, + [0][1][1][0][RTW89_MKK][1][77] = 127, + [0][1][1][0][RTW89_MKK][0][77] = 127, + [0][1][1][0][RTW89_IC][1][77] = -2, + [0][1][1][0][RTW89_KCC][1][77] = 12, + [0][1][1][0][RTW89_KCC][0][77] = 127, + [0][1][1][0][RTW89_ACMA][1][77] = 127, + [0][1][1][0][RTW89_ACMA][0][77] = 127, + [0][1][1][0][RTW89_CHILE][1][77] = -2, + [0][1][1][0][RTW89_QATAR][1][77] = 127, + [0][1][1][0][RTW89_QATAR][0][77] = 127, + [0][1][1][0][RTW89_UK][1][77] = 127, + [0][1][1][0][RTW89_UK][0][77] = 127, + [0][1][1][0][RTW89_FCC][1][79] = -2, + [0][1][1][0][RTW89_FCC][2][79] = 68, + [0][1][1][0][RTW89_ETSI][1][79] = 127, + [0][1][1][0][RTW89_ETSI][0][79] = 127, + [0][1][1][0][RTW89_MKK][1][79] = 127, + [0][1][1][0][RTW89_MKK][0][79] = 127, + [0][1][1][0][RTW89_IC][1][79] = -2, + [0][1][1][0][RTW89_KCC][1][79] = 12, + [0][1][1][0][RTW89_KCC][0][79] = 127, + [0][1][1][0][RTW89_ACMA][1][79] = 127, + [0][1][1][0][RTW89_ACMA][0][79] = 127, + [0][1][1][0][RTW89_CHILE][1][79] = -2, + [0][1][1][0][RTW89_QATAR][1][79] = 127, + [0][1][1][0][RTW89_QATAR][0][79] = 127, + [0][1][1][0][RTW89_UK][1][79] = 127, + [0][1][1][0][RTW89_UK][0][79] = 127, + [0][1][1][0][RTW89_FCC][1][81] = -2, + [0][1][1][0][RTW89_FCC][2][81] = 68, + [0][1][1][0][RTW89_ETSI][1][81] = 127, + [0][1][1][0][RTW89_ETSI][0][81] = 127, + [0][1][1][0][RTW89_MKK][1][81] = 127, + [0][1][1][0][RTW89_MKK][0][81] = 127, + [0][1][1][0][RTW89_IC][1][81] = -2, + [0][1][1][0][RTW89_KCC][1][81] = 12, + [0][1][1][0][RTW89_KCC][0][81] = 127, + [0][1][1][0][RTW89_ACMA][1][81] = 127, + [0][1][1][0][RTW89_ACMA][0][81] = 127, + [0][1][1][0][RTW89_CHILE][1][81] = -2, + [0][1][1][0][RTW89_QATAR][1][81] = 127, + [0][1][1][0][RTW89_QATAR][0][81] = 127, + [0][1][1][0][RTW89_UK][1][81] = 127, + [0][1][1][0][RTW89_UK][0][81] = 127, + [0][1][1][0][RTW89_FCC][1][83] = -2, + [0][1][1][0][RTW89_FCC][2][83] = 68, + [0][1][1][0][RTW89_ETSI][1][83] = 127, + [0][1][1][0][RTW89_ETSI][0][83] = 127, + [0][1][1][0][RTW89_MKK][1][83] = 127, + [0][1][1][0][RTW89_MKK][0][83] = 127, + [0][1][1][0][RTW89_IC][1][83] = -2, + [0][1][1][0][RTW89_KCC][1][83] = 20, + [0][1][1][0][RTW89_KCC][0][83] = 127, + [0][1][1][0][RTW89_ACMA][1][83] = 127, + [0][1][1][0][RTW89_ACMA][0][83] = 127, + [0][1][1][0][RTW89_CHILE][1][83] = -2, + [0][1][1][0][RTW89_QATAR][1][83] = 127, + [0][1][1][0][RTW89_QATAR][0][83] = 127, + [0][1][1][0][RTW89_UK][1][83] = 127, + [0][1][1][0][RTW89_UK][0][83] = 127, + [0][1][1][0][RTW89_FCC][1][85] = -2, + [0][1][1][0][RTW89_FCC][2][85] = 68, + [0][1][1][0][RTW89_ETSI][1][85] = 127, + [0][1][1][0][RTW89_ETSI][0][85] = 127, + [0][1][1][0][RTW89_MKK][1][85] = 127, + [0][1][1][0][RTW89_MKK][0][85] = 127, + [0][1][1][0][RTW89_IC][1][85] = -2, + [0][1][1][0][RTW89_KCC][1][85] = 20, + [0][1][1][0][RTW89_KCC][0][85] = 127, + [0][1][1][0][RTW89_ACMA][1][85] = 127, + [0][1][1][0][RTW89_ACMA][0][85] = 127, + [0][1][1][0][RTW89_CHILE][1][85] = -2, + [0][1][1][0][RTW89_QATAR][1][85] = 127, + [0][1][1][0][RTW89_QATAR][0][85] = 127, + [0][1][1][0][RTW89_UK][1][85] = 127, + [0][1][1][0][RTW89_UK][0][85] = 127, + [0][1][1][0][RTW89_FCC][1][87] = -2, + [0][1][1][0][RTW89_FCC][2][87] = 127, + [0][1][1][0][RTW89_ETSI][1][87] = 127, + [0][1][1][0][RTW89_ETSI][0][87] = 127, + [0][1][1][0][RTW89_MKK][1][87] = 127, + [0][1][1][0][RTW89_MKK][0][87] = 127, + [0][1][1][0][RTW89_IC][1][87] = -2, + [0][1][1][0][RTW89_KCC][1][87] = 20, + [0][1][1][0][RTW89_KCC][0][87] = 127, + [0][1][1][0][RTW89_ACMA][1][87] = 127, + [0][1][1][0][RTW89_ACMA][0][87] = 127, + [0][1][1][0][RTW89_CHILE][1][87] = -2, + [0][1][1][0][RTW89_QATAR][1][87] = 127, + [0][1][1][0][RTW89_QATAR][0][87] = 127, + [0][1][1][0][RTW89_UK][1][87] = 127, + [0][1][1][0][RTW89_UK][0][87] = 127, + [0][1][1][0][RTW89_FCC][1][89] = -2, + [0][1][1][0][RTW89_FCC][2][89] = 127, + [0][1][1][0][RTW89_ETSI][1][89] = 127, + [0][1][1][0][RTW89_ETSI][0][89] = 127, + [0][1][1][0][RTW89_MKK][1][89] = 127, + [0][1][1][0][RTW89_MKK][0][89] = 127, + [0][1][1][0][RTW89_IC][1][89] = -2, + [0][1][1][0][RTW89_KCC][1][89] = 20, + [0][1][1][0][RTW89_KCC][0][89] = 127, + [0][1][1][0][RTW89_ACMA][1][89] = 127, + [0][1][1][0][RTW89_ACMA][0][89] = 127, + [0][1][1][0][RTW89_CHILE][1][89] = -2, + [0][1][1][0][RTW89_QATAR][1][89] = 127, + [0][1][1][0][RTW89_QATAR][0][89] = 127, + [0][1][1][0][RTW89_UK][1][89] = 127, + [0][1][1][0][RTW89_UK][0][89] = 127, + [0][1][1][0][RTW89_FCC][1][90] = -2, + [0][1][1][0][RTW89_FCC][2][90] = 127, + [0][1][1][0][RTW89_ETSI][1][90] = 127, + [0][1][1][0][RTW89_ETSI][0][90] = 127, + [0][1][1][0][RTW89_MKK][1][90] = 127, + [0][1][1][0][RTW89_MKK][0][90] = 127, + [0][1][1][0][RTW89_IC][1][90] = -2, + [0][1][1][0][RTW89_KCC][1][90] = 20, + [0][1][1][0][RTW89_KCC][0][90] = 127, + [0][1][1][0][RTW89_ACMA][1][90] = 127, + [0][1][1][0][RTW89_ACMA][0][90] = 127, + [0][1][1][0][RTW89_CHILE][1][90] = -2, + [0][1][1][0][RTW89_QATAR][1][90] = 127, + [0][1][1][0][RTW89_QATAR][0][90] = 127, + [0][1][1][0][RTW89_UK][1][90] = 127, + [0][1][1][0][RTW89_UK][0][90] = 127, + [0][1][1][0][RTW89_FCC][1][92] = -2, + [0][1][1][0][RTW89_FCC][2][92] = 127, + [0][1][1][0][RTW89_ETSI][1][92] = 127, + [0][1][1][0][RTW89_ETSI][0][92] = 127, + [0][1][1][0][RTW89_MKK][1][92] = 127, + [0][1][1][0][RTW89_MKK][0][92] = 127, + [0][1][1][0][RTW89_IC][1][92] = -2, + [0][1][1][0][RTW89_KCC][1][92] = 20, + [0][1][1][0][RTW89_KCC][0][92] = 127, + [0][1][1][0][RTW89_ACMA][1][92] = 127, + [0][1][1][0][RTW89_ACMA][0][92] = 127, + [0][1][1][0][RTW89_CHILE][1][92] = -2, + [0][1][1][0][RTW89_QATAR][1][92] = 127, + [0][1][1][0][RTW89_QATAR][0][92] = 127, + [0][1][1][0][RTW89_UK][1][92] = 127, + [0][1][1][0][RTW89_UK][0][92] = 127, + [0][1][1][0][RTW89_FCC][1][94] = -2, + [0][1][1][0][RTW89_FCC][2][94] = 127, + [0][1][1][0][RTW89_ETSI][1][94] = 127, + [0][1][1][0][RTW89_ETSI][0][94] = 127, + [0][1][1][0][RTW89_MKK][1][94] = 127, + [0][1][1][0][RTW89_MKK][0][94] = 127, + [0][1][1][0][RTW89_IC][1][94] = -2, + [0][1][1][0][RTW89_KCC][1][94] = 20, + [0][1][1][0][RTW89_KCC][0][94] = 127, + [0][1][1][0][RTW89_ACMA][1][94] = 127, + [0][1][1][0][RTW89_ACMA][0][94] = 127, + [0][1][1][0][RTW89_CHILE][1][94] = -2, + [0][1][1][0][RTW89_QATAR][1][94] = 127, + [0][1][1][0][RTW89_QATAR][0][94] = 127, + [0][1][1][0][RTW89_UK][1][94] = 127, + [0][1][1][0][RTW89_UK][0][94] = 127, + [0][1][1][0][RTW89_FCC][1][96] = -2, + [0][1][1][0][RTW89_FCC][2][96] = 127, + [0][1][1][0][RTW89_ETSI][1][96] = 127, + [0][1][1][0][RTW89_ETSI][0][96] = 127, + [0][1][1][0][RTW89_MKK][1][96] = 127, + [0][1][1][0][RTW89_MKK][0][96] = 127, + [0][1][1][0][RTW89_IC][1][96] = -2, + [0][1][1][0][RTW89_KCC][1][96] = 20, + [0][1][1][0][RTW89_KCC][0][96] = 127, + [0][1][1][0][RTW89_ACMA][1][96] = 127, + [0][1][1][0][RTW89_ACMA][0][96] = 127, + [0][1][1][0][RTW89_CHILE][1][96] = -2, + [0][1][1][0][RTW89_QATAR][1][96] = 127, + [0][1][1][0][RTW89_QATAR][0][96] = 127, + [0][1][1][0][RTW89_UK][1][96] = 127, + [0][1][1][0][RTW89_UK][0][96] = 127, + [0][1][1][0][RTW89_FCC][1][98] = -2, + [0][1][1][0][RTW89_FCC][2][98] = 127, + [0][1][1][0][RTW89_ETSI][1][98] = 127, + [0][1][1][0][RTW89_ETSI][0][98] = 127, + [0][1][1][0][RTW89_MKK][1][98] = 127, + [0][1][1][0][RTW89_MKK][0][98] = 127, + [0][1][1][0][RTW89_IC][1][98] = -2, + [0][1][1][0][RTW89_KCC][1][98] = 20, + [0][1][1][0][RTW89_KCC][0][98] = 127, + [0][1][1][0][RTW89_ACMA][1][98] = 127, + [0][1][1][0][RTW89_ACMA][0][98] = 127, + [0][1][1][0][RTW89_CHILE][1][98] = -2, + [0][1][1][0][RTW89_QATAR][1][98] = 127, + [0][1][1][0][RTW89_QATAR][0][98] = 127, + [0][1][1][0][RTW89_UK][1][98] = 127, + [0][1][1][0][RTW89_UK][0][98] = 127, + [0][1][1][0][RTW89_FCC][1][100] = -2, + [0][1][1][0][RTW89_FCC][2][100] = 127, + [0][1][1][0][RTW89_ETSI][1][100] = 127, + [0][1][1][0][RTW89_ETSI][0][100] = 127, + [0][1][1][0][RTW89_MKK][1][100] = 127, + [0][1][1][0][RTW89_MKK][0][100] = 127, + [0][1][1][0][RTW89_IC][1][100] = -2, + [0][1][1][0][RTW89_KCC][1][100] = 20, + [0][1][1][0][RTW89_KCC][0][100] = 127, + [0][1][1][0][RTW89_ACMA][1][100] = 127, + [0][1][1][0][RTW89_ACMA][0][100] = 127, + [0][1][1][0][RTW89_CHILE][1][100] = -2, + [0][1][1][0][RTW89_QATAR][1][100] = 127, + [0][1][1][0][RTW89_QATAR][0][100] = 127, + [0][1][1][0][RTW89_UK][1][100] = 127, + [0][1][1][0][RTW89_UK][0][100] = 127, + [0][1][1][0][RTW89_FCC][1][102] = -2, + [0][1][1][0][RTW89_FCC][2][102] = 127, + [0][1][1][0][RTW89_ETSI][1][102] = 127, + [0][1][1][0][RTW89_ETSI][0][102] = 127, + [0][1][1][0][RTW89_MKK][1][102] = 127, + [0][1][1][0][RTW89_MKK][0][102] = 127, + [0][1][1][0][RTW89_IC][1][102] = -2, + [0][1][1][0][RTW89_KCC][1][102] = 20, + [0][1][1][0][RTW89_KCC][0][102] = 127, + [0][1][1][0][RTW89_ACMA][1][102] = 127, + [0][1][1][0][RTW89_ACMA][0][102] = 127, + [0][1][1][0][RTW89_CHILE][1][102] = -2, + [0][1][1][0][RTW89_QATAR][1][102] = 127, + [0][1][1][0][RTW89_QATAR][0][102] = 127, + [0][1][1][0][RTW89_UK][1][102] = 127, + [0][1][1][0][RTW89_UK][0][102] = 127, + [0][1][1][0][RTW89_FCC][1][104] = -2, + [0][1][1][0][RTW89_FCC][2][104] = 127, + [0][1][1][0][RTW89_ETSI][1][104] = 127, + [0][1][1][0][RTW89_ETSI][0][104] = 127, + [0][1][1][0][RTW89_MKK][1][104] = 127, + [0][1][1][0][RTW89_MKK][0][104] = 127, + [0][1][1][0][RTW89_IC][1][104] = -2, + [0][1][1][0][RTW89_KCC][1][104] = 20, + [0][1][1][0][RTW89_KCC][0][104] = 127, + [0][1][1][0][RTW89_ACMA][1][104] = 127, + [0][1][1][0][RTW89_ACMA][0][104] = 127, + [0][1][1][0][RTW89_CHILE][1][104] = -2, + [0][1][1][0][RTW89_QATAR][1][104] = 127, + [0][1][1][0][RTW89_QATAR][0][104] = 127, + [0][1][1][0][RTW89_UK][1][104] = 127, + [0][1][1][0][RTW89_UK][0][104] = 127, + [0][1][1][0][RTW89_FCC][1][105] = -2, + [0][1][1][0][RTW89_FCC][2][105] = 127, + [0][1][1][0][RTW89_ETSI][1][105] = 127, + [0][1][1][0][RTW89_ETSI][0][105] = 127, + [0][1][1][0][RTW89_MKK][1][105] = 127, + [0][1][1][0][RTW89_MKK][0][105] = 127, + [0][1][1][0][RTW89_IC][1][105] = -2, + [0][1][1][0][RTW89_KCC][1][105] = 20, + [0][1][1][0][RTW89_KCC][0][105] = 127, + [0][1][1][0][RTW89_ACMA][1][105] = 127, + [0][1][1][0][RTW89_ACMA][0][105] = 127, + [0][1][1][0][RTW89_CHILE][1][105] = -2, + [0][1][1][0][RTW89_QATAR][1][105] = 127, + [0][1][1][0][RTW89_QATAR][0][105] = 127, + [0][1][1][0][RTW89_UK][1][105] = 127, + [0][1][1][0][RTW89_UK][0][105] = 127, + [0][1][1][0][RTW89_FCC][1][107] = 1, + [0][1][1][0][RTW89_FCC][2][107] = 127, + [0][1][1][0][RTW89_ETSI][1][107] = 127, + [0][1][1][0][RTW89_ETSI][0][107] = 127, + [0][1][1][0][RTW89_MKK][1][107] = 127, + [0][1][1][0][RTW89_MKK][0][107] = 127, + [0][1][1][0][RTW89_IC][1][107] = 1, + [0][1][1][0][RTW89_KCC][1][107] = 20, + [0][1][1][0][RTW89_KCC][0][107] = 127, + [0][1][1][0][RTW89_ACMA][1][107] = 127, + [0][1][1][0][RTW89_ACMA][0][107] = 127, + [0][1][1][0][RTW89_CHILE][1][107] = 1, + [0][1][1][0][RTW89_QATAR][1][107] = 127, + [0][1][1][0][RTW89_QATAR][0][107] = 127, + [0][1][1][0][RTW89_UK][1][107] = 127, + [0][1][1][0][RTW89_UK][0][107] = 127, + [0][1][1][0][RTW89_FCC][1][109] = 1, + [0][1][1][0][RTW89_FCC][2][109] = 127, + [0][1][1][0][RTW89_ETSI][1][109] = 127, + [0][1][1][0][RTW89_ETSI][0][109] = 127, + [0][1][1][0][RTW89_MKK][1][109] = 127, + [0][1][1][0][RTW89_MKK][0][109] = 127, + [0][1][1][0][RTW89_IC][1][109] = 1, + [0][1][1][0][RTW89_KCC][1][109] = 20, + [0][1][1][0][RTW89_KCC][0][109] = 127, + [0][1][1][0][RTW89_ACMA][1][109] = 127, + [0][1][1][0][RTW89_ACMA][0][109] = 127, + [0][1][1][0][RTW89_CHILE][1][109] = 1, + [0][1][1][0][RTW89_QATAR][1][109] = 127, + [0][1][1][0][RTW89_QATAR][0][109] = 127, + [0][1][1][0][RTW89_UK][1][109] = 127, + [0][1][1][0][RTW89_UK][0][109] = 127, + [0][1][1][0][RTW89_FCC][1][111] = 127, + [0][1][1][0][RTW89_FCC][2][111] = 127, + [0][1][1][0][RTW89_ETSI][1][111] = 127, + [0][1][1][0][RTW89_ETSI][0][111] = 127, + [0][1][1][0][RTW89_MKK][1][111] = 127, + [0][1][1][0][RTW89_MKK][0][111] = 127, + [0][1][1][0][RTW89_IC][1][111] = 127, + [0][1][1][0][RTW89_KCC][1][111] = 127, + [0][1][1][0][RTW89_KCC][0][111] = 127, + [0][1][1][0][RTW89_ACMA][1][111] = 127, + [0][1][1][0][RTW89_ACMA][0][111] = 127, + [0][1][1][0][RTW89_CHILE][1][111] = 127, + [0][1][1][0][RTW89_QATAR][1][111] = 127, + [0][1][1][0][RTW89_QATAR][0][111] = 127, + [0][1][1][0][RTW89_UK][1][111] = 127, + [0][1][1][0][RTW89_UK][0][111] = 127, + [0][1][1][0][RTW89_FCC][1][113] = 127, + [0][1][1][0][RTW89_FCC][2][113] = 127, + [0][1][1][0][RTW89_ETSI][1][113] = 127, + [0][1][1][0][RTW89_ETSI][0][113] = 127, + [0][1][1][0][RTW89_MKK][1][113] = 127, + [0][1][1][0][RTW89_MKK][0][113] = 127, + [0][1][1][0][RTW89_IC][1][113] = 127, + [0][1][1][0][RTW89_KCC][1][113] = 127, + [0][1][1][0][RTW89_KCC][0][113] = 127, + [0][1][1][0][RTW89_ACMA][1][113] = 127, + [0][1][1][0][RTW89_ACMA][0][113] = 127, + [0][1][1][0][RTW89_CHILE][1][113] = 127, + [0][1][1][0][RTW89_QATAR][1][113] = 127, + [0][1][1][0][RTW89_QATAR][0][113] = 127, + [0][1][1][0][RTW89_UK][1][113] = 127, + [0][1][1][0][RTW89_UK][0][113] = 127, + [0][1][1][0][RTW89_FCC][1][115] = 127, + [0][1][1][0][RTW89_FCC][2][115] = 127, + [0][1][1][0][RTW89_ETSI][1][115] = 127, + [0][1][1][0][RTW89_ETSI][0][115] = 127, + [0][1][1][0][RTW89_MKK][1][115] = 127, + [0][1][1][0][RTW89_MKK][0][115] = 127, + [0][1][1][0][RTW89_IC][1][115] = 127, + [0][1][1][0][RTW89_KCC][1][115] = 127, + [0][1][1][0][RTW89_KCC][0][115] = 127, + [0][1][1][0][RTW89_ACMA][1][115] = 127, + [0][1][1][0][RTW89_ACMA][0][115] = 127, + [0][1][1][0][RTW89_CHILE][1][115] = 127, + [0][1][1][0][RTW89_QATAR][1][115] = 127, + [0][1][1][0][RTW89_QATAR][0][115] = 127, + [0][1][1][0][RTW89_UK][1][115] = 127, + [0][1][1][0][RTW89_UK][0][115] = 127, + [0][1][1][0][RTW89_FCC][1][117] = 127, + [0][1][1][0][RTW89_FCC][2][117] = 127, + [0][1][1][0][RTW89_ETSI][1][117] = 127, + [0][1][1][0][RTW89_ETSI][0][117] = 127, + [0][1][1][0][RTW89_MKK][1][117] = 127, + [0][1][1][0][RTW89_MKK][0][117] = 127, + [0][1][1][0][RTW89_IC][1][117] = 127, + [0][1][1][0][RTW89_KCC][1][117] = 127, + [0][1][1][0][RTW89_KCC][0][117] = 127, + [0][1][1][0][RTW89_ACMA][1][117] = 127, + [0][1][1][0][RTW89_ACMA][0][117] = 127, + [0][1][1][0][RTW89_CHILE][1][117] = 127, + [0][1][1][0][RTW89_QATAR][1][117] = 127, + [0][1][1][0][RTW89_QATAR][0][117] = 127, + [0][1][1][0][RTW89_UK][1][117] = 127, + [0][1][1][0][RTW89_UK][0][117] = 127, + [0][1][1][0][RTW89_FCC][1][119] = 127, + [0][1][1][0][RTW89_FCC][2][119] = 127, + [0][1][1][0][RTW89_ETSI][1][119] = 127, + [0][1][1][0][RTW89_ETSI][0][119] = 127, + [0][1][1][0][RTW89_MKK][1][119] = 127, + [0][1][1][0][RTW89_MKK][0][119] = 127, + [0][1][1][0][RTW89_IC][1][119] = 127, + [0][1][1][0][RTW89_KCC][1][119] = 127, + [0][1][1][0][RTW89_KCC][0][119] = 127, + [0][1][1][0][RTW89_ACMA][1][119] = 127, + [0][1][1][0][RTW89_ACMA][0][119] = 127, + [0][1][1][0][RTW89_CHILE][1][119] = 127, + [0][1][1][0][RTW89_QATAR][1][119] = 127, + [0][1][1][0][RTW89_QATAR][0][119] = 127, + [0][1][1][0][RTW89_UK][1][119] = 127, + [0][1][1][0][RTW89_UK][0][119] = 127, + [0][0][2][0][RTW89_FCC][1][0] = 24, + [0][0][2][0][RTW89_FCC][2][0] = 56, + [0][0][2][0][RTW89_ETSI][1][0] = 66, + [0][0][2][0][RTW89_ETSI][0][0] = 28, + [0][0][2][0][RTW89_MKK][1][0] = 66, + [0][0][2][0][RTW89_MKK][0][0] = 26, + [0][0][2][0][RTW89_IC][1][0] = 24, + [0][0][2][0][RTW89_KCC][1][0] = 24, + [0][0][2][0][RTW89_KCC][0][0] = 24, + [0][0][2][0][RTW89_ACMA][1][0] = 66, + [0][0][2][0][RTW89_ACMA][0][0] = 28, + [0][0][2][0][RTW89_CHILE][1][0] = 24, + [0][0][2][0][RTW89_QATAR][1][0] = 66, + [0][0][2][0][RTW89_QATAR][0][0] = 28, + [0][0][2][0][RTW89_UK][1][0] = 66, + [0][0][2][0][RTW89_UK][0][0] = 28, + [0][0][2][0][RTW89_FCC][1][2] = 22, + [0][0][2][0][RTW89_FCC][2][2] = 56, + [0][0][2][0][RTW89_ETSI][1][2] = 66, + [0][0][2][0][RTW89_ETSI][0][2] = 28, + [0][0][2][0][RTW89_MKK][1][2] = 66, + [0][0][2][0][RTW89_MKK][0][2] = 26, + [0][0][2][0][RTW89_IC][1][2] = 22, + [0][0][2][0][RTW89_KCC][1][2] = 24, + [0][0][2][0][RTW89_KCC][0][2] = 24, + [0][0][2][0][RTW89_ACMA][1][2] = 66, + [0][0][2][0][RTW89_ACMA][0][2] = 28, + [0][0][2][0][RTW89_CHILE][1][2] = 22, + [0][0][2][0][RTW89_QATAR][1][2] = 66, + [0][0][2][0][RTW89_QATAR][0][2] = 28, + [0][0][2][0][RTW89_UK][1][2] = 66, + [0][0][2][0][RTW89_UK][0][2] = 28, + [0][0][2][0][RTW89_FCC][1][4] = 22, + [0][0][2][0][RTW89_FCC][2][4] = 56, + [0][0][2][0][RTW89_ETSI][1][4] = 66, + [0][0][2][0][RTW89_ETSI][0][4] = 28, + [0][0][2][0][RTW89_MKK][1][4] = 66, + [0][0][2][0][RTW89_MKK][0][4] = 26, + [0][0][2][0][RTW89_IC][1][4] = 22, + [0][0][2][0][RTW89_KCC][1][4] = 24, + [0][0][2][0][RTW89_KCC][0][4] = 24, + [0][0][2][0][RTW89_ACMA][1][4] = 66, + [0][0][2][0][RTW89_ACMA][0][4] = 28, + [0][0][2][0][RTW89_CHILE][1][4] = 22, + [0][0][2][0][RTW89_QATAR][1][4] = 66, + [0][0][2][0][RTW89_QATAR][0][4] = 28, + [0][0][2][0][RTW89_UK][1][4] = 66, + [0][0][2][0][RTW89_UK][0][4] = 28, + [0][0][2][0][RTW89_FCC][1][6] = 22, + [0][0][2][0][RTW89_FCC][2][6] = 56, + [0][0][2][0][RTW89_ETSI][1][6] = 66, + [0][0][2][0][RTW89_ETSI][0][6] = 28, + [0][0][2][0][RTW89_MKK][1][6] = 66, + [0][0][2][0][RTW89_MKK][0][6] = 26, + [0][0][2][0][RTW89_IC][1][6] = 22, + [0][0][2][0][RTW89_KCC][1][6] = 24, + [0][0][2][0][RTW89_KCC][0][6] = 24, + [0][0][2][0][RTW89_ACMA][1][6] = 66, + [0][0][2][0][RTW89_ACMA][0][6] = 28, + [0][0][2][0][RTW89_CHILE][1][6] = 22, + [0][0][2][0][RTW89_QATAR][1][6] = 66, + [0][0][2][0][RTW89_QATAR][0][6] = 28, + [0][0][2][0][RTW89_UK][1][6] = 66, + [0][0][2][0][RTW89_UK][0][6] = 28, + [0][0][2][0][RTW89_FCC][1][8] = 22, + [0][0][2][0][RTW89_FCC][2][8] = 56, + [0][0][2][0][RTW89_ETSI][1][8] = 66, + [0][0][2][0][RTW89_ETSI][0][8] = 28, + [0][0][2][0][RTW89_MKK][1][8] = 66, + [0][0][2][0][RTW89_MKK][0][8] = 26, + [0][0][2][0][RTW89_IC][1][8] = 22, + [0][0][2][0][RTW89_KCC][1][8] = 24, + [0][0][2][0][RTW89_KCC][0][8] = 24, + [0][0][2][0][RTW89_ACMA][1][8] = 66, + [0][0][2][0][RTW89_ACMA][0][8] = 28, + [0][0][2][0][RTW89_CHILE][1][8] = 22, + [0][0][2][0][RTW89_QATAR][1][8] = 66, + [0][0][2][0][RTW89_QATAR][0][8] = 28, + [0][0][2][0][RTW89_UK][1][8] = 66, + [0][0][2][0][RTW89_UK][0][8] = 28, + [0][0][2][0][RTW89_FCC][1][10] = 22, + [0][0][2][0][RTW89_FCC][2][10] = 56, + [0][0][2][0][RTW89_ETSI][1][10] = 66, + [0][0][2][0][RTW89_ETSI][0][10] = 28, + [0][0][2][0][RTW89_MKK][1][10] = 66, + [0][0][2][0][RTW89_MKK][0][10] = 26, + [0][0][2][0][RTW89_IC][1][10] = 22, + [0][0][2][0][RTW89_KCC][1][10] = 24, + [0][0][2][0][RTW89_KCC][0][10] = 24, + [0][0][2][0][RTW89_ACMA][1][10] = 66, + [0][0][2][0][RTW89_ACMA][0][10] = 28, + [0][0][2][0][RTW89_CHILE][1][10] = 22, + [0][0][2][0][RTW89_QATAR][1][10] = 66, + [0][0][2][0][RTW89_QATAR][0][10] = 28, + [0][0][2][0][RTW89_UK][1][10] = 66, + [0][0][2][0][RTW89_UK][0][10] = 28, + [0][0][2][0][RTW89_FCC][1][12] = 22, + [0][0][2][0][RTW89_FCC][2][12] = 56, + [0][0][2][0][RTW89_ETSI][1][12] = 66, + [0][0][2][0][RTW89_ETSI][0][12] = 28, + [0][0][2][0][RTW89_MKK][1][12] = 66, + [0][0][2][0][RTW89_MKK][0][12] = 26, + [0][0][2][0][RTW89_IC][1][12] = 22, + [0][0][2][0][RTW89_KCC][1][12] = 24, + [0][0][2][0][RTW89_KCC][0][12] = 24, + [0][0][2][0][RTW89_ACMA][1][12] = 66, + [0][0][2][0][RTW89_ACMA][0][12] = 28, + [0][0][2][0][RTW89_CHILE][1][12] = 22, + [0][0][2][0][RTW89_QATAR][1][12] = 66, + [0][0][2][0][RTW89_QATAR][0][12] = 28, + [0][0][2][0][RTW89_UK][1][12] = 66, + [0][0][2][0][RTW89_UK][0][12] = 28, + [0][0][2][0][RTW89_FCC][1][14] = 22, + [0][0][2][0][RTW89_FCC][2][14] = 56, + [0][0][2][0][RTW89_ETSI][1][14] = 66, + [0][0][2][0][RTW89_ETSI][0][14] = 28, + [0][0][2][0][RTW89_MKK][1][14] = 66, + [0][0][2][0][RTW89_MKK][0][14] = 26, + [0][0][2][0][RTW89_IC][1][14] = 22, + [0][0][2][0][RTW89_KCC][1][14] = 24, + [0][0][2][0][RTW89_KCC][0][14] = 24, + [0][0][2][0][RTW89_ACMA][1][14] = 66, + [0][0][2][0][RTW89_ACMA][0][14] = 28, + [0][0][2][0][RTW89_CHILE][1][14] = 22, + [0][0][2][0][RTW89_QATAR][1][14] = 66, + [0][0][2][0][RTW89_QATAR][0][14] = 28, + [0][0][2][0][RTW89_UK][1][14] = 66, + [0][0][2][0][RTW89_UK][0][14] = 28, + [0][0][2][0][RTW89_FCC][1][15] = 22, + [0][0][2][0][RTW89_FCC][2][15] = 56, + [0][0][2][0][RTW89_ETSI][1][15] = 66, + [0][0][2][0][RTW89_ETSI][0][15] = 28, + [0][0][2][0][RTW89_MKK][1][15] = 66, + [0][0][2][0][RTW89_MKK][0][15] = 26, + [0][0][2][0][RTW89_IC][1][15] = 22, + [0][0][2][0][RTW89_KCC][1][15] = 24, + [0][0][2][0][RTW89_KCC][0][15] = 24, + [0][0][2][0][RTW89_ACMA][1][15] = 66, + [0][0][2][0][RTW89_ACMA][0][15] = 28, + [0][0][2][0][RTW89_CHILE][1][15] = 22, + [0][0][2][0][RTW89_QATAR][1][15] = 66, + [0][0][2][0][RTW89_QATAR][0][15] = 28, + [0][0][2][0][RTW89_UK][1][15] = 66, + [0][0][2][0][RTW89_UK][0][15] = 28, + [0][0][2][0][RTW89_FCC][1][17] = 22, + [0][0][2][0][RTW89_FCC][2][17] = 56, + [0][0][2][0][RTW89_ETSI][1][17] = 66, + [0][0][2][0][RTW89_ETSI][0][17] = 28, + [0][0][2][0][RTW89_MKK][1][17] = 66, + [0][0][2][0][RTW89_MKK][0][17] = 26, + [0][0][2][0][RTW89_IC][1][17] = 22, + [0][0][2][0][RTW89_KCC][1][17] = 24, + [0][0][2][0][RTW89_KCC][0][17] = 24, + [0][0][2][0][RTW89_ACMA][1][17] = 66, + [0][0][2][0][RTW89_ACMA][0][17] = 28, + [0][0][2][0][RTW89_CHILE][1][17] = 22, + [0][0][2][0][RTW89_QATAR][1][17] = 66, + [0][0][2][0][RTW89_QATAR][0][17] = 28, + [0][0][2][0][RTW89_UK][1][17] = 66, + [0][0][2][0][RTW89_UK][0][17] = 28, + [0][0][2][0][RTW89_FCC][1][19] = 22, + [0][0][2][0][RTW89_FCC][2][19] = 56, + [0][0][2][0][RTW89_ETSI][1][19] = 66, + [0][0][2][0][RTW89_ETSI][0][19] = 28, + [0][0][2][0][RTW89_MKK][1][19] = 66, + [0][0][2][0][RTW89_MKK][0][19] = 26, + [0][0][2][0][RTW89_IC][1][19] = 22, + [0][0][2][0][RTW89_KCC][1][19] = 24, + [0][0][2][0][RTW89_KCC][0][19] = 24, + [0][0][2][0][RTW89_ACMA][1][19] = 66, + [0][0][2][0][RTW89_ACMA][0][19] = 28, + [0][0][2][0][RTW89_CHILE][1][19] = 22, + [0][0][2][0][RTW89_QATAR][1][19] = 66, + [0][0][2][0][RTW89_QATAR][0][19] = 28, + [0][0][2][0][RTW89_UK][1][19] = 66, + [0][0][2][0][RTW89_UK][0][19] = 28, + [0][0][2][0][RTW89_FCC][1][21] = 22, + [0][0][2][0][RTW89_FCC][2][21] = 56, + [0][0][2][0][RTW89_ETSI][1][21] = 66, + [0][0][2][0][RTW89_ETSI][0][21] = 28, + [0][0][2][0][RTW89_MKK][1][21] = 66, + [0][0][2][0][RTW89_MKK][0][21] = 26, + [0][0][2][0][RTW89_IC][1][21] = 22, + [0][0][2][0][RTW89_KCC][1][21] = 24, + [0][0][2][0][RTW89_KCC][0][21] = 24, + [0][0][2][0][RTW89_ACMA][1][21] = 66, + [0][0][2][0][RTW89_ACMA][0][21] = 28, + [0][0][2][0][RTW89_CHILE][1][21] = 22, + [0][0][2][0][RTW89_QATAR][1][21] = 66, + [0][0][2][0][RTW89_QATAR][0][21] = 28, + [0][0][2][0][RTW89_UK][1][21] = 66, + [0][0][2][0][RTW89_UK][0][21] = 28, + [0][0][2][0][RTW89_FCC][1][23] = 22, + [0][0][2][0][RTW89_FCC][2][23] = 70, + [0][0][2][0][RTW89_ETSI][1][23] = 66, + [0][0][2][0][RTW89_ETSI][0][23] = 28, + [0][0][2][0][RTW89_MKK][1][23] = 66, + [0][0][2][0][RTW89_MKK][0][23] = 26, + [0][0][2][0][RTW89_IC][1][23] = 22, + [0][0][2][0][RTW89_KCC][1][23] = 24, + [0][0][2][0][RTW89_KCC][0][23] = 26, + [0][0][2][0][RTW89_ACMA][1][23] = 66, + [0][0][2][0][RTW89_ACMA][0][23] = 28, + [0][0][2][0][RTW89_CHILE][1][23] = 22, + [0][0][2][0][RTW89_QATAR][1][23] = 66, + [0][0][2][0][RTW89_QATAR][0][23] = 28, + [0][0][2][0][RTW89_UK][1][23] = 66, + [0][0][2][0][RTW89_UK][0][23] = 28, + [0][0][2][0][RTW89_FCC][1][25] = 22, + [0][0][2][0][RTW89_FCC][2][25] = 70, + [0][0][2][0][RTW89_ETSI][1][25] = 66, + [0][0][2][0][RTW89_ETSI][0][25] = 28, + [0][0][2][0][RTW89_MKK][1][25] = 66, + [0][0][2][0][RTW89_MKK][0][25] = 26, + [0][0][2][0][RTW89_IC][1][25] = 22, + [0][0][2][0][RTW89_KCC][1][25] = 24, + [0][0][2][0][RTW89_KCC][0][25] = 26, + [0][0][2][0][RTW89_ACMA][1][25] = 66, + [0][0][2][0][RTW89_ACMA][0][25] = 28, + [0][0][2][0][RTW89_CHILE][1][25] = 22, + [0][0][2][0][RTW89_QATAR][1][25] = 66, + [0][0][2][0][RTW89_QATAR][0][25] = 28, + [0][0][2][0][RTW89_UK][1][25] = 66, + [0][0][2][0][RTW89_UK][0][25] = 28, + [0][0][2][0][RTW89_FCC][1][27] = 22, + [0][0][2][0][RTW89_FCC][2][27] = 70, + [0][0][2][0][RTW89_ETSI][1][27] = 66, + [0][0][2][0][RTW89_ETSI][0][27] = 28, + [0][0][2][0][RTW89_MKK][1][27] = 66, + [0][0][2][0][RTW89_MKK][0][27] = 26, + [0][0][2][0][RTW89_IC][1][27] = 22, + [0][0][2][0][RTW89_KCC][1][27] = 24, + [0][0][2][0][RTW89_KCC][0][27] = 26, + [0][0][2][0][RTW89_ACMA][1][27] = 66, + [0][0][2][0][RTW89_ACMA][0][27] = 28, + [0][0][2][0][RTW89_CHILE][1][27] = 22, + [0][0][2][0][RTW89_QATAR][1][27] = 66, + [0][0][2][0][RTW89_QATAR][0][27] = 28, + [0][0][2][0][RTW89_UK][1][27] = 66, + [0][0][2][0][RTW89_UK][0][27] = 28, + [0][0][2][0][RTW89_FCC][1][29] = 22, + [0][0][2][0][RTW89_FCC][2][29] = 70, + [0][0][2][0][RTW89_ETSI][1][29] = 66, + [0][0][2][0][RTW89_ETSI][0][29] = 28, + [0][0][2][0][RTW89_MKK][1][29] = 66, + [0][0][2][0][RTW89_MKK][0][29] = 26, + [0][0][2][0][RTW89_IC][1][29] = 22, + [0][0][2][0][RTW89_KCC][1][29] = 24, + [0][0][2][0][RTW89_KCC][0][29] = 26, + [0][0][2][0][RTW89_ACMA][1][29] = 66, + [0][0][2][0][RTW89_ACMA][0][29] = 28, + [0][0][2][0][RTW89_CHILE][1][29] = 22, + [0][0][2][0][RTW89_QATAR][1][29] = 66, + [0][0][2][0][RTW89_QATAR][0][29] = 28, + [0][0][2][0][RTW89_UK][1][29] = 66, + [0][0][2][0][RTW89_UK][0][29] = 28, + [0][0][2][0][RTW89_FCC][1][30] = 22, + [0][0][2][0][RTW89_FCC][2][30] = 70, + [0][0][2][0][RTW89_ETSI][1][30] = 66, + [0][0][2][0][RTW89_ETSI][0][30] = 28, + [0][0][2][0][RTW89_MKK][1][30] = 66, + [0][0][2][0][RTW89_MKK][0][30] = 26, + [0][0][2][0][RTW89_IC][1][30] = 22, + [0][0][2][0][RTW89_KCC][1][30] = 24, + [0][0][2][0][RTW89_KCC][0][30] = 26, + [0][0][2][0][RTW89_ACMA][1][30] = 66, + [0][0][2][0][RTW89_ACMA][0][30] = 28, + [0][0][2][0][RTW89_CHILE][1][30] = 22, + [0][0][2][0][RTW89_QATAR][1][30] = 66, + [0][0][2][0][RTW89_QATAR][0][30] = 28, + [0][0][2][0][RTW89_UK][1][30] = 66, + [0][0][2][0][RTW89_UK][0][30] = 28, + [0][0][2][0][RTW89_FCC][1][32] = 22, + [0][0][2][0][RTW89_FCC][2][32] = 70, + [0][0][2][0][RTW89_ETSI][1][32] = 66, + [0][0][2][0][RTW89_ETSI][0][32] = 28, + [0][0][2][0][RTW89_MKK][1][32] = 66, + [0][0][2][0][RTW89_MKK][0][32] = 26, + [0][0][2][0][RTW89_IC][1][32] = 22, + [0][0][2][0][RTW89_KCC][1][32] = 24, + [0][0][2][0][RTW89_KCC][0][32] = 26, + [0][0][2][0][RTW89_ACMA][1][32] = 66, + [0][0][2][0][RTW89_ACMA][0][32] = 28, + [0][0][2][0][RTW89_CHILE][1][32] = 22, + [0][0][2][0][RTW89_QATAR][1][32] = 66, + [0][0][2][0][RTW89_QATAR][0][32] = 28, + [0][0][2][0][RTW89_UK][1][32] = 66, + [0][0][2][0][RTW89_UK][0][32] = 28, + [0][0][2][0][RTW89_FCC][1][34] = 22, + [0][0][2][0][RTW89_FCC][2][34] = 70, + [0][0][2][0][RTW89_ETSI][1][34] = 66, + [0][0][2][0][RTW89_ETSI][0][34] = 28, + [0][0][2][0][RTW89_MKK][1][34] = 66, + [0][0][2][0][RTW89_MKK][0][34] = 26, + [0][0][2][0][RTW89_IC][1][34] = 22, + [0][0][2][0][RTW89_KCC][1][34] = 24, + [0][0][2][0][RTW89_KCC][0][34] = 26, + [0][0][2][0][RTW89_ACMA][1][34] = 66, + [0][0][2][0][RTW89_ACMA][0][34] = 28, + [0][0][2][0][RTW89_CHILE][1][34] = 22, + [0][0][2][0][RTW89_QATAR][1][34] = 66, + [0][0][2][0][RTW89_QATAR][0][34] = 28, + [0][0][2][0][RTW89_UK][1][34] = 66, + [0][0][2][0][RTW89_UK][0][34] = 28, + [0][0][2][0][RTW89_FCC][1][36] = 22, + [0][0][2][0][RTW89_FCC][2][36] = 70, + [0][0][2][0][RTW89_ETSI][1][36] = 66, + [0][0][2][0][RTW89_ETSI][0][36] = 28, + [0][0][2][0][RTW89_MKK][1][36] = 66, + [0][0][2][0][RTW89_MKK][0][36] = 26, + [0][0][2][0][RTW89_IC][1][36] = 22, + [0][0][2][0][RTW89_KCC][1][36] = 24, + [0][0][2][0][RTW89_KCC][0][36] = 26, + [0][0][2][0][RTW89_ACMA][1][36] = 66, + [0][0][2][0][RTW89_ACMA][0][36] = 28, + [0][0][2][0][RTW89_CHILE][1][36] = 22, + [0][0][2][0][RTW89_QATAR][1][36] = 66, + [0][0][2][0][RTW89_QATAR][0][36] = 28, + [0][0][2][0][RTW89_UK][1][36] = 66, + [0][0][2][0][RTW89_UK][0][36] = 28, + [0][0][2][0][RTW89_FCC][1][38] = 22, + [0][0][2][0][RTW89_FCC][2][38] = 70, + [0][0][2][0][RTW89_ETSI][1][38] = 66, + [0][0][2][0][RTW89_ETSI][0][38] = 28, + [0][0][2][0][RTW89_MKK][1][38] = 66, + [0][0][2][0][RTW89_MKK][0][38] = 26, + [0][0][2][0][RTW89_IC][1][38] = 22, + [0][0][2][0][RTW89_KCC][1][38] = 24, + [0][0][2][0][RTW89_KCC][0][38] = 26, + [0][0][2][0][RTW89_ACMA][1][38] = 66, + [0][0][2][0][RTW89_ACMA][0][38] = 28, + [0][0][2][0][RTW89_CHILE][1][38] = 22, + [0][0][2][0][RTW89_QATAR][1][38] = 66, + [0][0][2][0][RTW89_QATAR][0][38] = 28, + [0][0][2][0][RTW89_UK][1][38] = 66, + [0][0][2][0][RTW89_UK][0][38] = 28, + [0][0][2][0][RTW89_FCC][1][40] = 22, + [0][0][2][0][RTW89_FCC][2][40] = 70, + [0][0][2][0][RTW89_ETSI][1][40] = 66, + [0][0][2][0][RTW89_ETSI][0][40] = 28, + [0][0][2][0][RTW89_MKK][1][40] = 66, + [0][0][2][0][RTW89_MKK][0][40] = 26, + [0][0][2][0][RTW89_IC][1][40] = 22, + [0][0][2][0][RTW89_KCC][1][40] = 24, + [0][0][2][0][RTW89_KCC][0][40] = 26, + [0][0][2][0][RTW89_ACMA][1][40] = 66, + [0][0][2][0][RTW89_ACMA][0][40] = 28, + [0][0][2][0][RTW89_CHILE][1][40] = 22, + [0][0][2][0][RTW89_QATAR][1][40] = 66, + [0][0][2][0][RTW89_QATAR][0][40] = 28, + [0][0][2][0][RTW89_UK][1][40] = 66, + [0][0][2][0][RTW89_UK][0][40] = 28, + [0][0][2][0][RTW89_FCC][1][42] = 22, + [0][0][2][0][RTW89_FCC][2][42] = 70, + [0][0][2][0][RTW89_ETSI][1][42] = 66, + [0][0][2][0][RTW89_ETSI][0][42] = 28, + [0][0][2][0][RTW89_MKK][1][42] = 66, + [0][0][2][0][RTW89_MKK][0][42] = 26, + [0][0][2][0][RTW89_IC][1][42] = 22, + [0][0][2][0][RTW89_KCC][1][42] = 24, + [0][0][2][0][RTW89_KCC][0][42] = 26, + [0][0][2][0][RTW89_ACMA][1][42] = 66, + [0][0][2][0][RTW89_ACMA][0][42] = 28, + [0][0][2][0][RTW89_CHILE][1][42] = 22, + [0][0][2][0][RTW89_QATAR][1][42] = 66, + [0][0][2][0][RTW89_QATAR][0][42] = 28, + [0][0][2][0][RTW89_UK][1][42] = 66, + [0][0][2][0][RTW89_UK][0][42] = 28, + [0][0][2][0][RTW89_FCC][1][44] = 22, + [0][0][2][0][RTW89_FCC][2][44] = 70, + [0][0][2][0][RTW89_ETSI][1][44] = 66, + [0][0][2][0][RTW89_ETSI][0][44] = 30, + [0][0][2][0][RTW89_MKK][1][44] = 44, + [0][0][2][0][RTW89_MKK][0][44] = 28, + [0][0][2][0][RTW89_IC][1][44] = 22, + [0][0][2][0][RTW89_KCC][1][44] = 24, + [0][0][2][0][RTW89_KCC][0][44] = 26, + [0][0][2][0][RTW89_ACMA][1][44] = 66, + [0][0][2][0][RTW89_ACMA][0][44] = 30, + [0][0][2][0][RTW89_CHILE][1][44] = 22, + [0][0][2][0][RTW89_QATAR][1][44] = 66, + [0][0][2][0][RTW89_QATAR][0][44] = 30, + [0][0][2][0][RTW89_UK][1][44] = 66, + [0][0][2][0][RTW89_UK][0][44] = 30, + [0][0][2][0][RTW89_FCC][1][45] = 22, + [0][0][2][0][RTW89_FCC][2][45] = 127, + [0][0][2][0][RTW89_ETSI][1][45] = 127, + [0][0][2][0][RTW89_ETSI][0][45] = 127, + [0][0][2][0][RTW89_MKK][1][45] = 127, + [0][0][2][0][RTW89_MKK][0][45] = 127, + [0][0][2][0][RTW89_IC][1][45] = 22, + [0][0][2][0][RTW89_KCC][1][45] = 24, + [0][0][2][0][RTW89_KCC][0][45] = 127, + [0][0][2][0][RTW89_ACMA][1][45] = 127, + [0][0][2][0][RTW89_ACMA][0][45] = 127, + [0][0][2][0][RTW89_CHILE][1][45] = 22, + [0][0][2][0][RTW89_QATAR][1][45] = 127, + [0][0][2][0][RTW89_QATAR][0][45] = 127, + [0][0][2][0][RTW89_UK][1][45] = 127, + [0][0][2][0][RTW89_UK][0][45] = 127, + [0][0][2][0][RTW89_FCC][1][47] = 22, + [0][0][2][0][RTW89_FCC][2][47] = 127, + [0][0][2][0][RTW89_ETSI][1][47] = 127, + [0][0][2][0][RTW89_ETSI][0][47] = 127, + [0][0][2][0][RTW89_MKK][1][47] = 127, + [0][0][2][0][RTW89_MKK][0][47] = 127, + [0][0][2][0][RTW89_IC][1][47] = 22, + [0][0][2][0][RTW89_KCC][1][47] = 24, + [0][0][2][0][RTW89_KCC][0][47] = 127, + [0][0][2][0][RTW89_ACMA][1][47] = 127, + [0][0][2][0][RTW89_ACMA][0][47] = 127, + [0][0][2][0][RTW89_CHILE][1][47] = 22, + [0][0][2][0][RTW89_QATAR][1][47] = 127, + [0][0][2][0][RTW89_QATAR][0][47] = 127, + [0][0][2][0][RTW89_UK][1][47] = 127, + [0][0][2][0][RTW89_UK][0][47] = 127, + [0][0][2][0][RTW89_FCC][1][49] = 24, + [0][0][2][0][RTW89_FCC][2][49] = 127, + [0][0][2][0][RTW89_ETSI][1][49] = 127, + [0][0][2][0][RTW89_ETSI][0][49] = 127, + [0][0][2][0][RTW89_MKK][1][49] = 127, + [0][0][2][0][RTW89_MKK][0][49] = 127, + [0][0][2][0][RTW89_IC][1][49] = 24, + [0][0][2][0][RTW89_KCC][1][49] = 24, + [0][0][2][0][RTW89_KCC][0][49] = 127, + [0][0][2][0][RTW89_ACMA][1][49] = 127, + [0][0][2][0][RTW89_ACMA][0][49] = 127, + [0][0][2][0][RTW89_CHILE][1][49] = 24, + [0][0][2][0][RTW89_QATAR][1][49] = 127, + [0][0][2][0][RTW89_QATAR][0][49] = 127, + [0][0][2][0][RTW89_UK][1][49] = 127, + [0][0][2][0][RTW89_UK][0][49] = 127, + [0][0][2][0][RTW89_FCC][1][51] = 22, + [0][0][2][0][RTW89_FCC][2][51] = 127, + [0][0][2][0][RTW89_ETSI][1][51] = 127, + [0][0][2][0][RTW89_ETSI][0][51] = 127, + [0][0][2][0][RTW89_MKK][1][51] = 127, + [0][0][2][0][RTW89_MKK][0][51] = 127, + [0][0][2][0][RTW89_IC][1][51] = 22, + [0][0][2][0][RTW89_KCC][1][51] = 24, + [0][0][2][0][RTW89_KCC][0][51] = 127, + [0][0][2][0][RTW89_ACMA][1][51] = 127, + [0][0][2][0][RTW89_ACMA][0][51] = 127, + [0][0][2][0][RTW89_CHILE][1][51] = 22, + [0][0][2][0][RTW89_QATAR][1][51] = 127, + [0][0][2][0][RTW89_QATAR][0][51] = 127, + [0][0][2][0][RTW89_UK][1][51] = 127, + [0][0][2][0][RTW89_UK][0][51] = 127, + [0][0][2][0][RTW89_FCC][1][53] = 22, + [0][0][2][0][RTW89_FCC][2][53] = 127, + [0][0][2][0][RTW89_ETSI][1][53] = 127, + [0][0][2][0][RTW89_ETSI][0][53] = 127, + [0][0][2][0][RTW89_MKK][1][53] = 127, + [0][0][2][0][RTW89_MKK][0][53] = 127, + [0][0][2][0][RTW89_IC][1][53] = 22, + [0][0][2][0][RTW89_KCC][1][53] = 24, + [0][0][2][0][RTW89_KCC][0][53] = 127, + [0][0][2][0][RTW89_ACMA][1][53] = 127, + [0][0][2][0][RTW89_ACMA][0][53] = 127, + [0][0][2][0][RTW89_CHILE][1][53] = 22, + [0][0][2][0][RTW89_QATAR][1][53] = 127, + [0][0][2][0][RTW89_QATAR][0][53] = 127, + [0][0][2][0][RTW89_UK][1][53] = 127, + [0][0][2][0][RTW89_UK][0][53] = 127, + [0][0][2][0][RTW89_FCC][1][55] = 22, + [0][0][2][0][RTW89_FCC][2][55] = 68, + [0][0][2][0][RTW89_ETSI][1][55] = 127, + [0][0][2][0][RTW89_ETSI][0][55] = 127, + [0][0][2][0][RTW89_MKK][1][55] = 127, + [0][0][2][0][RTW89_MKK][0][55] = 127, + [0][0][2][0][RTW89_IC][1][55] = 22, + [0][0][2][0][RTW89_KCC][1][55] = 26, + [0][0][2][0][RTW89_KCC][0][55] = 127, + [0][0][2][0][RTW89_ACMA][1][55] = 127, + [0][0][2][0][RTW89_ACMA][0][55] = 127, + [0][0][2][0][RTW89_CHILE][1][55] = 22, + [0][0][2][0][RTW89_QATAR][1][55] = 127, + [0][0][2][0][RTW89_QATAR][0][55] = 127, + [0][0][2][0][RTW89_UK][1][55] = 127, + [0][0][2][0][RTW89_UK][0][55] = 127, + [0][0][2][0][RTW89_FCC][1][57] = 22, + [0][0][2][0][RTW89_FCC][2][57] = 68, + [0][0][2][0][RTW89_ETSI][1][57] = 127, + [0][0][2][0][RTW89_ETSI][0][57] = 127, + [0][0][2][0][RTW89_MKK][1][57] = 127, + [0][0][2][0][RTW89_MKK][0][57] = 127, + [0][0][2][0][RTW89_IC][1][57] = 22, + [0][0][2][0][RTW89_KCC][1][57] = 26, + [0][0][2][0][RTW89_KCC][0][57] = 127, + [0][0][2][0][RTW89_ACMA][1][57] = 127, + [0][0][2][0][RTW89_ACMA][0][57] = 127, + [0][0][2][0][RTW89_CHILE][1][57] = 22, + [0][0][2][0][RTW89_QATAR][1][57] = 127, + [0][0][2][0][RTW89_QATAR][0][57] = 127, + [0][0][2][0][RTW89_UK][1][57] = 127, + [0][0][2][0][RTW89_UK][0][57] = 127, + [0][0][2][0][RTW89_FCC][1][59] = 22, + [0][0][2][0][RTW89_FCC][2][59] = 68, + [0][0][2][0][RTW89_ETSI][1][59] = 127, + [0][0][2][0][RTW89_ETSI][0][59] = 127, + [0][0][2][0][RTW89_MKK][1][59] = 127, + [0][0][2][0][RTW89_MKK][0][59] = 127, + [0][0][2][0][RTW89_IC][1][59] = 22, + [0][0][2][0][RTW89_KCC][1][59] = 26, + [0][0][2][0][RTW89_KCC][0][59] = 127, + [0][0][2][0][RTW89_ACMA][1][59] = 127, + [0][0][2][0][RTW89_ACMA][0][59] = 127, + [0][0][2][0][RTW89_CHILE][1][59] = 22, + [0][0][2][0][RTW89_QATAR][1][59] = 127, + [0][0][2][0][RTW89_QATAR][0][59] = 127, + [0][0][2][0][RTW89_UK][1][59] = 127, + [0][0][2][0][RTW89_UK][0][59] = 127, + [0][0][2][0][RTW89_FCC][1][60] = 22, + [0][0][2][0][RTW89_FCC][2][60] = 68, + [0][0][2][0][RTW89_ETSI][1][60] = 127, + [0][0][2][0][RTW89_ETSI][0][60] = 127, + [0][0][2][0][RTW89_MKK][1][60] = 127, + [0][0][2][0][RTW89_MKK][0][60] = 127, + [0][0][2][0][RTW89_IC][1][60] = 22, + [0][0][2][0][RTW89_KCC][1][60] = 26, + [0][0][2][0][RTW89_KCC][0][60] = 127, + [0][0][2][0][RTW89_ACMA][1][60] = 127, + [0][0][2][0][RTW89_ACMA][0][60] = 127, + [0][0][2][0][RTW89_CHILE][1][60] = 22, + [0][0][2][0][RTW89_QATAR][1][60] = 127, + [0][0][2][0][RTW89_QATAR][0][60] = 127, + [0][0][2][0][RTW89_UK][1][60] = 127, + [0][0][2][0][RTW89_UK][0][60] = 127, + [0][0][2][0][RTW89_FCC][1][62] = 22, + [0][0][2][0][RTW89_FCC][2][62] = 68, + [0][0][2][0][RTW89_ETSI][1][62] = 127, + [0][0][2][0][RTW89_ETSI][0][62] = 127, + [0][0][2][0][RTW89_MKK][1][62] = 127, + [0][0][2][0][RTW89_MKK][0][62] = 127, + [0][0][2][0][RTW89_IC][1][62] = 22, + [0][0][2][0][RTW89_KCC][1][62] = 26, + [0][0][2][0][RTW89_KCC][0][62] = 127, + [0][0][2][0][RTW89_ACMA][1][62] = 127, + [0][0][2][0][RTW89_ACMA][0][62] = 127, + [0][0][2][0][RTW89_CHILE][1][62] = 22, + [0][0][2][0][RTW89_QATAR][1][62] = 127, + [0][0][2][0][RTW89_QATAR][0][62] = 127, + [0][0][2][0][RTW89_UK][1][62] = 127, + [0][0][2][0][RTW89_UK][0][62] = 127, + [0][0][2][0][RTW89_FCC][1][64] = 22, + [0][0][2][0][RTW89_FCC][2][64] = 68, + [0][0][2][0][RTW89_ETSI][1][64] = 127, + [0][0][2][0][RTW89_ETSI][0][64] = 127, + [0][0][2][0][RTW89_MKK][1][64] = 127, + [0][0][2][0][RTW89_MKK][0][64] = 127, + [0][0][2][0][RTW89_IC][1][64] = 22, + [0][0][2][0][RTW89_KCC][1][64] = 26, + [0][0][2][0][RTW89_KCC][0][64] = 127, + [0][0][2][0][RTW89_ACMA][1][64] = 127, + [0][0][2][0][RTW89_ACMA][0][64] = 127, + [0][0][2][0][RTW89_CHILE][1][64] = 22, + [0][0][2][0][RTW89_QATAR][1][64] = 127, + [0][0][2][0][RTW89_QATAR][0][64] = 127, + [0][0][2][0][RTW89_UK][1][64] = 127, + [0][0][2][0][RTW89_UK][0][64] = 127, + [0][0][2][0][RTW89_FCC][1][66] = 22, + [0][0][2][0][RTW89_FCC][2][66] = 68, + [0][0][2][0][RTW89_ETSI][1][66] = 127, + [0][0][2][0][RTW89_ETSI][0][66] = 127, + [0][0][2][0][RTW89_MKK][1][66] = 127, + [0][0][2][0][RTW89_MKK][0][66] = 127, + [0][0][2][0][RTW89_IC][1][66] = 22, + [0][0][2][0][RTW89_KCC][1][66] = 26, + [0][0][2][0][RTW89_KCC][0][66] = 127, + [0][0][2][0][RTW89_ACMA][1][66] = 127, + [0][0][2][0][RTW89_ACMA][0][66] = 127, + [0][0][2][0][RTW89_CHILE][1][66] = 22, + [0][0][2][0][RTW89_QATAR][1][66] = 127, + [0][0][2][0][RTW89_QATAR][0][66] = 127, + [0][0][2][0][RTW89_UK][1][66] = 127, + [0][0][2][0][RTW89_UK][0][66] = 127, + [0][0][2][0][RTW89_FCC][1][68] = 22, + [0][0][2][0][RTW89_FCC][2][68] = 68, + [0][0][2][0][RTW89_ETSI][1][68] = 127, + [0][0][2][0][RTW89_ETSI][0][68] = 127, + [0][0][2][0][RTW89_MKK][1][68] = 127, + [0][0][2][0][RTW89_MKK][0][68] = 127, + [0][0][2][0][RTW89_IC][1][68] = 22, + [0][0][2][0][RTW89_KCC][1][68] = 26, + [0][0][2][0][RTW89_KCC][0][68] = 127, + [0][0][2][0][RTW89_ACMA][1][68] = 127, + [0][0][2][0][RTW89_ACMA][0][68] = 127, + [0][0][2][0][RTW89_CHILE][1][68] = 22, + [0][0][2][0][RTW89_QATAR][1][68] = 127, + [0][0][2][0][RTW89_QATAR][0][68] = 127, + [0][0][2][0][RTW89_UK][1][68] = 127, + [0][0][2][0][RTW89_UK][0][68] = 127, + [0][0][2][0][RTW89_FCC][1][70] = 24, + [0][0][2][0][RTW89_FCC][2][70] = 68, + [0][0][2][0][RTW89_ETSI][1][70] = 127, + [0][0][2][0][RTW89_ETSI][0][70] = 127, + [0][0][2][0][RTW89_MKK][1][70] = 127, + [0][0][2][0][RTW89_MKK][0][70] = 127, + [0][0][2][0][RTW89_IC][1][70] = 24, + [0][0][2][0][RTW89_KCC][1][70] = 26, + [0][0][2][0][RTW89_KCC][0][70] = 127, + [0][0][2][0][RTW89_ACMA][1][70] = 127, + [0][0][2][0][RTW89_ACMA][0][70] = 127, + [0][0][2][0][RTW89_CHILE][1][70] = 24, + [0][0][2][0][RTW89_QATAR][1][70] = 127, + [0][0][2][0][RTW89_QATAR][0][70] = 127, + [0][0][2][0][RTW89_UK][1][70] = 127, + [0][0][2][0][RTW89_UK][0][70] = 127, + [0][0][2][0][RTW89_FCC][1][72] = 22, + [0][0][2][0][RTW89_FCC][2][72] = 68, + [0][0][2][0][RTW89_ETSI][1][72] = 127, + [0][0][2][0][RTW89_ETSI][0][72] = 127, + [0][0][2][0][RTW89_MKK][1][72] = 127, + [0][0][2][0][RTW89_MKK][0][72] = 127, + [0][0][2][0][RTW89_IC][1][72] = 22, + [0][0][2][0][RTW89_KCC][1][72] = 26, + [0][0][2][0][RTW89_KCC][0][72] = 127, + [0][0][2][0][RTW89_ACMA][1][72] = 127, + [0][0][2][0][RTW89_ACMA][0][72] = 127, + [0][0][2][0][RTW89_CHILE][1][72] = 22, + [0][0][2][0][RTW89_QATAR][1][72] = 127, + [0][0][2][0][RTW89_QATAR][0][72] = 127, + [0][0][2][0][RTW89_UK][1][72] = 127, + [0][0][2][0][RTW89_UK][0][72] = 127, + [0][0][2][0][RTW89_FCC][1][74] = 22, + [0][0][2][0][RTW89_FCC][2][74] = 68, + [0][0][2][0][RTW89_ETSI][1][74] = 127, + [0][0][2][0][RTW89_ETSI][0][74] = 127, + [0][0][2][0][RTW89_MKK][1][74] = 127, + [0][0][2][0][RTW89_MKK][0][74] = 127, + [0][0][2][0][RTW89_IC][1][74] = 22, + [0][0][2][0][RTW89_KCC][1][74] = 26, + [0][0][2][0][RTW89_KCC][0][74] = 127, + [0][0][2][0][RTW89_ACMA][1][74] = 127, + [0][0][2][0][RTW89_ACMA][0][74] = 127, + [0][0][2][0][RTW89_CHILE][1][74] = 22, + [0][0][2][0][RTW89_QATAR][1][74] = 127, + [0][0][2][0][RTW89_QATAR][0][74] = 127, + [0][0][2][0][RTW89_UK][1][74] = 127, + [0][0][2][0][RTW89_UK][0][74] = 127, + [0][0][2][0][RTW89_FCC][1][75] = 22, + [0][0][2][0][RTW89_FCC][2][75] = 68, + [0][0][2][0][RTW89_ETSI][1][75] = 127, + [0][0][2][0][RTW89_ETSI][0][75] = 127, + [0][0][2][0][RTW89_MKK][1][75] = 127, + [0][0][2][0][RTW89_MKK][0][75] = 127, + [0][0][2][0][RTW89_IC][1][75] = 22, + [0][0][2][0][RTW89_KCC][1][75] = 26, + [0][0][2][0][RTW89_KCC][0][75] = 127, + [0][0][2][0][RTW89_ACMA][1][75] = 127, + [0][0][2][0][RTW89_ACMA][0][75] = 127, + [0][0][2][0][RTW89_CHILE][1][75] = 22, + [0][0][2][0][RTW89_QATAR][1][75] = 127, + [0][0][2][0][RTW89_QATAR][0][75] = 127, + [0][0][2][0][RTW89_UK][1][75] = 127, + [0][0][2][0][RTW89_UK][0][75] = 127, + [0][0][2][0][RTW89_FCC][1][77] = 22, + [0][0][2][0][RTW89_FCC][2][77] = 68, + [0][0][2][0][RTW89_ETSI][1][77] = 127, + [0][0][2][0][RTW89_ETSI][0][77] = 127, + [0][0][2][0][RTW89_MKK][1][77] = 127, + [0][0][2][0][RTW89_MKK][0][77] = 127, + [0][0][2][0][RTW89_IC][1][77] = 22, + [0][0][2][0][RTW89_KCC][1][77] = 26, + [0][0][2][0][RTW89_KCC][0][77] = 127, + [0][0][2][0][RTW89_ACMA][1][77] = 127, + [0][0][2][0][RTW89_ACMA][0][77] = 127, + [0][0][2][0][RTW89_CHILE][1][77] = 22, + [0][0][2][0][RTW89_QATAR][1][77] = 127, + [0][0][2][0][RTW89_QATAR][0][77] = 127, + [0][0][2][0][RTW89_UK][1][77] = 127, + [0][0][2][0][RTW89_UK][0][77] = 127, + [0][0][2][0][RTW89_FCC][1][79] = 22, + [0][0][2][0][RTW89_FCC][2][79] = 68, + [0][0][2][0][RTW89_ETSI][1][79] = 127, + [0][0][2][0][RTW89_ETSI][0][79] = 127, + [0][0][2][0][RTW89_MKK][1][79] = 127, + [0][0][2][0][RTW89_MKK][0][79] = 127, + [0][0][2][0][RTW89_IC][1][79] = 22, + [0][0][2][0][RTW89_KCC][1][79] = 26, + [0][0][2][0][RTW89_KCC][0][79] = 127, + [0][0][2][0][RTW89_ACMA][1][79] = 127, + [0][0][2][0][RTW89_ACMA][0][79] = 127, + [0][0][2][0][RTW89_CHILE][1][79] = 22, + [0][0][2][0][RTW89_QATAR][1][79] = 127, + [0][0][2][0][RTW89_QATAR][0][79] = 127, + [0][0][2][0][RTW89_UK][1][79] = 127, + [0][0][2][0][RTW89_UK][0][79] = 127, + [0][0][2][0][RTW89_FCC][1][81] = 22, + [0][0][2][0][RTW89_FCC][2][81] = 68, + [0][0][2][0][RTW89_ETSI][1][81] = 127, + [0][0][2][0][RTW89_ETSI][0][81] = 127, + [0][0][2][0][RTW89_MKK][1][81] = 127, + [0][0][2][0][RTW89_MKK][0][81] = 127, + [0][0][2][0][RTW89_IC][1][81] = 22, + [0][0][2][0][RTW89_KCC][1][81] = 26, + [0][0][2][0][RTW89_KCC][0][81] = 127, + [0][0][2][0][RTW89_ACMA][1][81] = 127, + [0][0][2][0][RTW89_ACMA][0][81] = 127, + [0][0][2][0][RTW89_CHILE][1][81] = 22, + [0][0][2][0][RTW89_QATAR][1][81] = 127, + [0][0][2][0][RTW89_QATAR][0][81] = 127, + [0][0][2][0][RTW89_UK][1][81] = 127, + [0][0][2][0][RTW89_UK][0][81] = 127, + [0][0][2][0][RTW89_FCC][1][83] = 22, + [0][0][2][0][RTW89_FCC][2][83] = 68, + [0][0][2][0][RTW89_ETSI][1][83] = 127, + [0][0][2][0][RTW89_ETSI][0][83] = 127, + [0][0][2][0][RTW89_MKK][1][83] = 127, + [0][0][2][0][RTW89_MKK][0][83] = 127, + [0][0][2][0][RTW89_IC][1][83] = 22, + [0][0][2][0][RTW89_KCC][1][83] = 32, + [0][0][2][0][RTW89_KCC][0][83] = 127, + [0][0][2][0][RTW89_ACMA][1][83] = 127, + [0][0][2][0][RTW89_ACMA][0][83] = 127, + [0][0][2][0][RTW89_CHILE][1][83] = 22, + [0][0][2][0][RTW89_QATAR][1][83] = 127, + [0][0][2][0][RTW89_QATAR][0][83] = 127, + [0][0][2][0][RTW89_UK][1][83] = 127, + [0][0][2][0][RTW89_UK][0][83] = 127, + [0][0][2][0][RTW89_FCC][1][85] = 22, + [0][0][2][0][RTW89_FCC][2][85] = 68, + [0][0][2][0][RTW89_ETSI][1][85] = 127, + [0][0][2][0][RTW89_ETSI][0][85] = 127, + [0][0][2][0][RTW89_MKK][1][85] = 127, + [0][0][2][0][RTW89_MKK][0][85] = 127, + [0][0][2][0][RTW89_IC][1][85] = 22, + [0][0][2][0][RTW89_KCC][1][85] = 32, + [0][0][2][0][RTW89_KCC][0][85] = 127, + [0][0][2][0][RTW89_ACMA][1][85] = 127, + [0][0][2][0][RTW89_ACMA][0][85] = 127, + [0][0][2][0][RTW89_CHILE][1][85] = 22, + [0][0][2][0][RTW89_QATAR][1][85] = 127, + [0][0][2][0][RTW89_QATAR][0][85] = 127, + [0][0][2][0][RTW89_UK][1][85] = 127, + [0][0][2][0][RTW89_UK][0][85] = 127, + [0][0][2][0][RTW89_FCC][1][87] = 22, + [0][0][2][0][RTW89_FCC][2][87] = 127, + [0][0][2][0][RTW89_ETSI][1][87] = 127, + [0][0][2][0][RTW89_ETSI][0][87] = 127, + [0][0][2][0][RTW89_MKK][1][87] = 127, + [0][0][2][0][RTW89_MKK][0][87] = 127, + [0][0][2][0][RTW89_IC][1][87] = 22, + [0][0][2][0][RTW89_KCC][1][87] = 32, + [0][0][2][0][RTW89_KCC][0][87] = 127, + [0][0][2][0][RTW89_ACMA][1][87] = 127, + [0][0][2][0][RTW89_ACMA][0][87] = 127, + [0][0][2][0][RTW89_CHILE][1][87] = 22, + [0][0][2][0][RTW89_QATAR][1][87] = 127, + [0][0][2][0][RTW89_QATAR][0][87] = 127, + [0][0][2][0][RTW89_UK][1][87] = 127, + [0][0][2][0][RTW89_UK][0][87] = 127, + [0][0][2][0][RTW89_FCC][1][89] = 22, + [0][0][2][0][RTW89_FCC][2][89] = 127, + [0][0][2][0][RTW89_ETSI][1][89] = 127, + [0][0][2][0][RTW89_ETSI][0][89] = 127, + [0][0][2][0][RTW89_MKK][1][89] = 127, + [0][0][2][0][RTW89_MKK][0][89] = 127, + [0][0][2][0][RTW89_IC][1][89] = 22, + [0][0][2][0][RTW89_KCC][1][89] = 32, + [0][0][2][0][RTW89_KCC][0][89] = 127, + [0][0][2][0][RTW89_ACMA][1][89] = 127, + [0][0][2][0][RTW89_ACMA][0][89] = 127, + [0][0][2][0][RTW89_CHILE][1][89] = 22, + [0][0][2][0][RTW89_QATAR][1][89] = 127, + [0][0][2][0][RTW89_QATAR][0][89] = 127, + [0][0][2][0][RTW89_UK][1][89] = 127, + [0][0][2][0][RTW89_UK][0][89] = 127, + [0][0][2][0][RTW89_FCC][1][90] = 22, + [0][0][2][0][RTW89_FCC][2][90] = 127, + [0][0][2][0][RTW89_ETSI][1][90] = 127, + [0][0][2][0][RTW89_ETSI][0][90] = 127, + [0][0][2][0][RTW89_MKK][1][90] = 127, + [0][0][2][0][RTW89_MKK][0][90] = 127, + [0][0][2][0][RTW89_IC][1][90] = 22, + [0][0][2][0][RTW89_KCC][1][90] = 32, + [0][0][2][0][RTW89_KCC][0][90] = 127, + [0][0][2][0][RTW89_ACMA][1][90] = 127, + [0][0][2][0][RTW89_ACMA][0][90] = 127, + [0][0][2][0][RTW89_CHILE][1][90] = 22, + [0][0][2][0][RTW89_QATAR][1][90] = 127, + [0][0][2][0][RTW89_QATAR][0][90] = 127, + [0][0][2][0][RTW89_UK][1][90] = 127, + [0][0][2][0][RTW89_UK][0][90] = 127, + [0][0][2][0][RTW89_FCC][1][92] = 22, + [0][0][2][0][RTW89_FCC][2][92] = 127, + [0][0][2][0][RTW89_ETSI][1][92] = 127, + [0][0][2][0][RTW89_ETSI][0][92] = 127, + [0][0][2][0][RTW89_MKK][1][92] = 127, + [0][0][2][0][RTW89_MKK][0][92] = 127, + [0][0][2][0][RTW89_IC][1][92] = 22, + [0][0][2][0][RTW89_KCC][1][92] = 32, + [0][0][2][0][RTW89_KCC][0][92] = 127, + [0][0][2][0][RTW89_ACMA][1][92] = 127, + [0][0][2][0][RTW89_ACMA][0][92] = 127, + [0][0][2][0][RTW89_CHILE][1][92] = 22, + [0][0][2][0][RTW89_QATAR][1][92] = 127, + [0][0][2][0][RTW89_QATAR][0][92] = 127, + [0][0][2][0][RTW89_UK][1][92] = 127, + [0][0][2][0][RTW89_UK][0][92] = 127, + [0][0][2][0][RTW89_FCC][1][94] = 22, + [0][0][2][0][RTW89_FCC][2][94] = 127, + [0][0][2][0][RTW89_ETSI][1][94] = 127, + [0][0][2][0][RTW89_ETSI][0][94] = 127, + [0][0][2][0][RTW89_MKK][1][94] = 127, + [0][0][2][0][RTW89_MKK][0][94] = 127, + [0][0][2][0][RTW89_IC][1][94] = 22, + [0][0][2][0][RTW89_KCC][1][94] = 32, + [0][0][2][0][RTW89_KCC][0][94] = 127, + [0][0][2][0][RTW89_ACMA][1][94] = 127, + [0][0][2][0][RTW89_ACMA][0][94] = 127, + [0][0][2][0][RTW89_CHILE][1][94] = 22, + [0][0][2][0][RTW89_QATAR][1][94] = 127, + [0][0][2][0][RTW89_QATAR][0][94] = 127, + [0][0][2][0][RTW89_UK][1][94] = 127, + [0][0][2][0][RTW89_UK][0][94] = 127, + [0][0][2][0][RTW89_FCC][1][96] = 22, + [0][0][2][0][RTW89_FCC][2][96] = 127, + [0][0][2][0][RTW89_ETSI][1][96] = 127, + [0][0][2][0][RTW89_ETSI][0][96] = 127, + [0][0][2][0][RTW89_MKK][1][96] = 127, + [0][0][2][0][RTW89_MKK][0][96] = 127, + [0][0][2][0][RTW89_IC][1][96] = 22, + [0][0][2][0][RTW89_KCC][1][96] = 32, + [0][0][2][0][RTW89_KCC][0][96] = 127, + [0][0][2][0][RTW89_ACMA][1][96] = 127, + [0][0][2][0][RTW89_ACMA][0][96] = 127, + [0][0][2][0][RTW89_CHILE][1][96] = 22, + [0][0][2][0][RTW89_QATAR][1][96] = 127, + [0][0][2][0][RTW89_QATAR][0][96] = 127, + [0][0][2][0][RTW89_UK][1][96] = 127, + [0][0][2][0][RTW89_UK][0][96] = 127, + [0][0][2][0][RTW89_FCC][1][98] = 22, + [0][0][2][0][RTW89_FCC][2][98] = 127, + [0][0][2][0][RTW89_ETSI][1][98] = 127, + [0][0][2][0][RTW89_ETSI][0][98] = 127, + [0][0][2][0][RTW89_MKK][1][98] = 127, + [0][0][2][0][RTW89_MKK][0][98] = 127, + [0][0][2][0][RTW89_IC][1][98] = 22, + [0][0][2][0][RTW89_KCC][1][98] = 32, + [0][0][2][0][RTW89_KCC][0][98] = 127, + [0][0][2][0][RTW89_ACMA][1][98] = 127, + [0][0][2][0][RTW89_ACMA][0][98] = 127, + [0][0][2][0][RTW89_CHILE][1][98] = 22, + [0][0][2][0][RTW89_QATAR][1][98] = 127, + [0][0][2][0][RTW89_QATAR][0][98] = 127, + [0][0][2][0][RTW89_UK][1][98] = 127, + [0][0][2][0][RTW89_UK][0][98] = 127, + [0][0][2][0][RTW89_FCC][1][100] = 22, + [0][0][2][0][RTW89_FCC][2][100] = 127, + [0][0][2][0][RTW89_ETSI][1][100] = 127, + [0][0][2][0][RTW89_ETSI][0][100] = 127, + [0][0][2][0][RTW89_MKK][1][100] = 127, + [0][0][2][0][RTW89_MKK][0][100] = 127, + [0][0][2][0][RTW89_IC][1][100] = 22, + [0][0][2][0][RTW89_KCC][1][100] = 32, + [0][0][2][0][RTW89_KCC][0][100] = 127, + [0][0][2][0][RTW89_ACMA][1][100] = 127, + [0][0][2][0][RTW89_ACMA][0][100] = 127, + [0][0][2][0][RTW89_CHILE][1][100] = 22, + [0][0][2][0][RTW89_QATAR][1][100] = 127, + [0][0][2][0][RTW89_QATAR][0][100] = 127, + [0][0][2][0][RTW89_UK][1][100] = 127, + [0][0][2][0][RTW89_UK][0][100] = 127, + [0][0][2][0][RTW89_FCC][1][102] = 22, + [0][0][2][0][RTW89_FCC][2][102] = 127, + [0][0][2][0][RTW89_ETSI][1][102] = 127, + [0][0][2][0][RTW89_ETSI][0][102] = 127, + [0][0][2][0][RTW89_MKK][1][102] = 127, + [0][0][2][0][RTW89_MKK][0][102] = 127, + [0][0][2][0][RTW89_IC][1][102] = 22, + [0][0][2][0][RTW89_KCC][1][102] = 32, + [0][0][2][0][RTW89_KCC][0][102] = 127, + [0][0][2][0][RTW89_ACMA][1][102] = 127, + [0][0][2][0][RTW89_ACMA][0][102] = 127, + [0][0][2][0][RTW89_CHILE][1][102] = 22, + [0][0][2][0][RTW89_QATAR][1][102] = 127, + [0][0][2][0][RTW89_QATAR][0][102] = 127, + [0][0][2][0][RTW89_UK][1][102] = 127, + [0][0][2][0][RTW89_UK][0][102] = 127, + [0][0][2][0][RTW89_FCC][1][104] = 22, + [0][0][2][0][RTW89_FCC][2][104] = 127, + [0][0][2][0][RTW89_ETSI][1][104] = 127, + [0][0][2][0][RTW89_ETSI][0][104] = 127, + [0][0][2][0][RTW89_MKK][1][104] = 127, + [0][0][2][0][RTW89_MKK][0][104] = 127, + [0][0][2][0][RTW89_IC][1][104] = 22, + [0][0][2][0][RTW89_KCC][1][104] = 32, + [0][0][2][0][RTW89_KCC][0][104] = 127, + [0][0][2][0][RTW89_ACMA][1][104] = 127, + [0][0][2][0][RTW89_ACMA][0][104] = 127, + [0][0][2][0][RTW89_CHILE][1][104] = 22, + [0][0][2][0][RTW89_QATAR][1][104] = 127, + [0][0][2][0][RTW89_QATAR][0][104] = 127, + [0][0][2][0][RTW89_UK][1][104] = 127, + [0][0][2][0][RTW89_UK][0][104] = 127, + [0][0][2][0][RTW89_FCC][1][105] = 22, + [0][0][2][0][RTW89_FCC][2][105] = 127, + [0][0][2][0][RTW89_ETSI][1][105] = 127, + [0][0][2][0][RTW89_ETSI][0][105] = 127, + [0][0][2][0][RTW89_MKK][1][105] = 127, + [0][0][2][0][RTW89_MKK][0][105] = 127, + [0][0][2][0][RTW89_IC][1][105] = 22, + [0][0][2][0][RTW89_KCC][1][105] = 32, + [0][0][2][0][RTW89_KCC][0][105] = 127, + [0][0][2][0][RTW89_ACMA][1][105] = 127, + [0][0][2][0][RTW89_ACMA][0][105] = 127, + [0][0][2][0][RTW89_CHILE][1][105] = 22, + [0][0][2][0][RTW89_QATAR][1][105] = 127, + [0][0][2][0][RTW89_QATAR][0][105] = 127, + [0][0][2][0][RTW89_UK][1][105] = 127, + [0][0][2][0][RTW89_UK][0][105] = 127, + [0][0][2][0][RTW89_FCC][1][107] = 24, + [0][0][2][0][RTW89_FCC][2][107] = 127, + [0][0][2][0][RTW89_ETSI][1][107] = 127, + [0][0][2][0][RTW89_ETSI][0][107] = 127, + [0][0][2][0][RTW89_MKK][1][107] = 127, + [0][0][2][0][RTW89_MKK][0][107] = 127, + [0][0][2][0][RTW89_IC][1][107] = 24, + [0][0][2][0][RTW89_KCC][1][107] = 32, + [0][0][2][0][RTW89_KCC][0][107] = 127, + [0][0][2][0][RTW89_ACMA][1][107] = 127, + [0][0][2][0][RTW89_ACMA][0][107] = 127, + [0][0][2][0][RTW89_CHILE][1][107] = 24, + [0][0][2][0][RTW89_QATAR][1][107] = 127, + [0][0][2][0][RTW89_QATAR][0][107] = 127, + [0][0][2][0][RTW89_UK][1][107] = 127, + [0][0][2][0][RTW89_UK][0][107] = 127, + [0][0][2][0][RTW89_FCC][1][109] = 24, + [0][0][2][0][RTW89_FCC][2][109] = 127, + [0][0][2][0][RTW89_ETSI][1][109] = 127, + [0][0][2][0][RTW89_ETSI][0][109] = 127, + [0][0][2][0][RTW89_MKK][1][109] = 127, + [0][0][2][0][RTW89_MKK][0][109] = 127, + [0][0][2][0][RTW89_IC][1][109] = 24, + [0][0][2][0][RTW89_KCC][1][109] = 32, + [0][0][2][0][RTW89_KCC][0][109] = 127, + [0][0][2][0][RTW89_ACMA][1][109] = 127, + [0][0][2][0][RTW89_ACMA][0][109] = 127, + [0][0][2][0][RTW89_CHILE][1][109] = 24, + [0][0][2][0][RTW89_QATAR][1][109] = 127, + [0][0][2][0][RTW89_QATAR][0][109] = 127, + [0][0][2][0][RTW89_UK][1][109] = 127, + [0][0][2][0][RTW89_UK][0][109] = 127, + [0][0][2][0][RTW89_FCC][1][111] = 127, + [0][0][2][0][RTW89_FCC][2][111] = 127, + [0][0][2][0][RTW89_ETSI][1][111] = 127, + [0][0][2][0][RTW89_ETSI][0][111] = 127, + [0][0][2][0][RTW89_MKK][1][111] = 127, + [0][0][2][0][RTW89_MKK][0][111] = 127, + [0][0][2][0][RTW89_IC][1][111] = 127, + [0][0][2][0][RTW89_KCC][1][111] = 127, + [0][0][2][0][RTW89_KCC][0][111] = 127, + [0][0][2][0][RTW89_ACMA][1][111] = 127, + [0][0][2][0][RTW89_ACMA][0][111] = 127, + [0][0][2][0][RTW89_CHILE][1][111] = 127, + [0][0][2][0][RTW89_QATAR][1][111] = 127, + [0][0][2][0][RTW89_QATAR][0][111] = 127, + [0][0][2][0][RTW89_UK][1][111] = 127, + [0][0][2][0][RTW89_UK][0][111] = 127, + [0][0][2][0][RTW89_FCC][1][113] = 127, + [0][0][2][0][RTW89_FCC][2][113] = 127, + [0][0][2][0][RTW89_ETSI][1][113] = 127, + [0][0][2][0][RTW89_ETSI][0][113] = 127, + [0][0][2][0][RTW89_MKK][1][113] = 127, + [0][0][2][0][RTW89_MKK][0][113] = 127, + [0][0][2][0][RTW89_IC][1][113] = 127, + [0][0][2][0][RTW89_KCC][1][113] = 127, + [0][0][2][0][RTW89_KCC][0][113] = 127, + [0][0][2][0][RTW89_ACMA][1][113] = 127, + [0][0][2][0][RTW89_ACMA][0][113] = 127, + [0][0][2][0][RTW89_CHILE][1][113] = 127, + [0][0][2][0][RTW89_QATAR][1][113] = 127, + [0][0][2][0][RTW89_QATAR][0][113] = 127, + [0][0][2][0][RTW89_UK][1][113] = 127, + [0][0][2][0][RTW89_UK][0][113] = 127, + [0][0][2][0][RTW89_FCC][1][115] = 127, + [0][0][2][0][RTW89_FCC][2][115] = 127, + [0][0][2][0][RTW89_ETSI][1][115] = 127, + [0][0][2][0][RTW89_ETSI][0][115] = 127, + [0][0][2][0][RTW89_MKK][1][115] = 127, + [0][0][2][0][RTW89_MKK][0][115] = 127, + [0][0][2][0][RTW89_IC][1][115] = 127, + [0][0][2][0][RTW89_KCC][1][115] = 127, + [0][0][2][0][RTW89_KCC][0][115] = 127, + [0][0][2][0][RTW89_ACMA][1][115] = 127, + [0][0][2][0][RTW89_ACMA][0][115] = 127, + [0][0][2][0][RTW89_CHILE][1][115] = 127, + [0][0][2][0][RTW89_QATAR][1][115] = 127, + [0][0][2][0][RTW89_QATAR][0][115] = 127, + [0][0][2][0][RTW89_UK][1][115] = 127, + [0][0][2][0][RTW89_UK][0][115] = 127, + [0][0][2][0][RTW89_FCC][1][117] = 127, + [0][0][2][0][RTW89_FCC][2][117] = 127, + [0][0][2][0][RTW89_ETSI][1][117] = 127, + [0][0][2][0][RTW89_ETSI][0][117] = 127, + [0][0][2][0][RTW89_MKK][1][117] = 127, + [0][0][2][0][RTW89_MKK][0][117] = 127, + [0][0][2][0][RTW89_IC][1][117] = 127, + [0][0][2][0][RTW89_KCC][1][117] = 127, + [0][0][2][0][RTW89_KCC][0][117] = 127, + [0][0][2][0][RTW89_ACMA][1][117] = 127, + [0][0][2][0][RTW89_ACMA][0][117] = 127, + [0][0][2][0][RTW89_CHILE][1][117] = 127, + [0][0][2][0][RTW89_QATAR][1][117] = 127, + [0][0][2][0][RTW89_QATAR][0][117] = 127, + [0][0][2][0][RTW89_UK][1][117] = 127, + [0][0][2][0][RTW89_UK][0][117] = 127, + [0][0][2][0][RTW89_FCC][1][119] = 127, + [0][0][2][0][RTW89_FCC][2][119] = 127, + [0][0][2][0][RTW89_ETSI][1][119] = 127, + [0][0][2][0][RTW89_ETSI][0][119] = 127, + [0][0][2][0][RTW89_MKK][1][119] = 127, + [0][0][2][0][RTW89_MKK][0][119] = 127, + [0][0][2][0][RTW89_IC][1][119] = 127, + [0][0][2][0][RTW89_KCC][1][119] = 127, + [0][0][2][0][RTW89_KCC][0][119] = 127, + [0][0][2][0][RTW89_ACMA][1][119] = 127, + [0][0][2][0][RTW89_ACMA][0][119] = 127, + [0][0][2][0][RTW89_CHILE][1][119] = 127, + [0][0][2][0][RTW89_QATAR][1][119] = 127, + [0][0][2][0][RTW89_QATAR][0][119] = 127, + [0][0][2][0][RTW89_UK][1][119] = 127, + [0][0][2][0][RTW89_UK][0][119] = 127, + [0][1][2][0][RTW89_FCC][1][0] = -2, + [0][1][2][0][RTW89_FCC][2][0] = 54, + [0][1][2][0][RTW89_ETSI][1][0] = 54, + [0][1][2][0][RTW89_ETSI][0][0] = 18, + [0][1][2][0][RTW89_MKK][1][0] = 56, + [0][1][2][0][RTW89_MKK][0][0] = 16, + [0][1][2][0][RTW89_IC][1][0] = -2, + [0][1][2][0][RTW89_KCC][1][0] = 12, + [0][1][2][0][RTW89_KCC][0][0] = 10, + [0][1][2][0][RTW89_ACMA][1][0] = 54, + [0][1][2][0][RTW89_ACMA][0][0] = 18, + [0][1][2][0][RTW89_CHILE][1][0] = -2, + [0][1][2][0][RTW89_QATAR][1][0] = 54, + [0][1][2][0][RTW89_QATAR][0][0] = 18, + [0][1][2][0][RTW89_UK][1][0] = 54, + [0][1][2][0][RTW89_UK][0][0] = 18, + [0][1][2][0][RTW89_FCC][1][2] = -4, + [0][1][2][0][RTW89_FCC][2][2] = 54, + [0][1][2][0][RTW89_ETSI][1][2] = 54, + [0][1][2][0][RTW89_ETSI][0][2] = 18, + [0][1][2][0][RTW89_MKK][1][2] = 54, + [0][1][2][0][RTW89_MKK][0][2] = 16, + [0][1][2][0][RTW89_IC][1][2] = -4, + [0][1][2][0][RTW89_KCC][1][2] = 12, + [0][1][2][0][RTW89_KCC][0][2] = 12, + [0][1][2][0][RTW89_ACMA][1][2] = 54, + [0][1][2][0][RTW89_ACMA][0][2] = 18, + [0][1][2][0][RTW89_CHILE][1][2] = -4, + [0][1][2][0][RTW89_QATAR][1][2] = 54, + [0][1][2][0][RTW89_QATAR][0][2] = 18, + [0][1][2][0][RTW89_UK][1][2] = 54, + [0][1][2][0][RTW89_UK][0][2] = 18, + [0][1][2][0][RTW89_FCC][1][4] = -4, + [0][1][2][0][RTW89_FCC][2][4] = 54, + [0][1][2][0][RTW89_ETSI][1][4] = 54, + [0][1][2][0][RTW89_ETSI][0][4] = 18, + [0][1][2][0][RTW89_MKK][1][4] = 54, + [0][1][2][0][RTW89_MKK][0][4] = 16, + [0][1][2][0][RTW89_IC][1][4] = -4, + [0][1][2][0][RTW89_KCC][1][4] = 12, + [0][1][2][0][RTW89_KCC][0][4] = 12, + [0][1][2][0][RTW89_ACMA][1][4] = 54, + [0][1][2][0][RTW89_ACMA][0][4] = 18, + [0][1][2][0][RTW89_CHILE][1][4] = -4, + [0][1][2][0][RTW89_QATAR][1][4] = 54, + [0][1][2][0][RTW89_QATAR][0][4] = 18, + [0][1][2][0][RTW89_UK][1][4] = 54, + [0][1][2][0][RTW89_UK][0][4] = 18, + [0][1][2][0][RTW89_FCC][1][6] = -4, + [0][1][2][0][RTW89_FCC][2][6] = 54, + [0][1][2][0][RTW89_ETSI][1][6] = 54, + [0][1][2][0][RTW89_ETSI][0][6] = 18, + [0][1][2][0][RTW89_MKK][1][6] = 54, + [0][1][2][0][RTW89_MKK][0][6] = 16, + [0][1][2][0][RTW89_IC][1][6] = -4, + [0][1][2][0][RTW89_KCC][1][6] = 12, + [0][1][2][0][RTW89_KCC][0][6] = 12, + [0][1][2][0][RTW89_ACMA][1][6] = 54, + [0][1][2][0][RTW89_ACMA][0][6] = 18, + [0][1][2][0][RTW89_CHILE][1][6] = -4, + [0][1][2][0][RTW89_QATAR][1][6] = 54, + [0][1][2][0][RTW89_QATAR][0][6] = 18, + [0][1][2][0][RTW89_UK][1][6] = 54, + [0][1][2][0][RTW89_UK][0][6] = 18, + [0][1][2][0][RTW89_FCC][1][8] = -4, + [0][1][2][0][RTW89_FCC][2][8] = 54, + [0][1][2][0][RTW89_ETSI][1][8] = 54, + [0][1][2][0][RTW89_ETSI][0][8] = 18, + [0][1][2][0][RTW89_MKK][1][8] = 54, + [0][1][2][0][RTW89_MKK][0][8] = 16, + [0][1][2][0][RTW89_IC][1][8] = -4, + [0][1][2][0][RTW89_KCC][1][8] = 12, + [0][1][2][0][RTW89_KCC][0][8] = 12, + [0][1][2][0][RTW89_ACMA][1][8] = 54, + [0][1][2][0][RTW89_ACMA][0][8] = 18, + [0][1][2][0][RTW89_CHILE][1][8] = -4, + [0][1][2][0][RTW89_QATAR][1][8] = 54, + [0][1][2][0][RTW89_QATAR][0][8] = 18, + [0][1][2][0][RTW89_UK][1][8] = 54, + [0][1][2][0][RTW89_UK][0][8] = 18, + [0][1][2][0][RTW89_FCC][1][10] = -4, + [0][1][2][0][RTW89_FCC][2][10] = 54, + [0][1][2][0][RTW89_ETSI][1][10] = 54, + [0][1][2][0][RTW89_ETSI][0][10] = 18, + [0][1][2][0][RTW89_MKK][1][10] = 54, + [0][1][2][0][RTW89_MKK][0][10] = 16, + [0][1][2][0][RTW89_IC][1][10] = -4, + [0][1][2][0][RTW89_KCC][1][10] = 12, + [0][1][2][0][RTW89_KCC][0][10] = 12, + [0][1][2][0][RTW89_ACMA][1][10] = 54, + [0][1][2][0][RTW89_ACMA][0][10] = 18, + [0][1][2][0][RTW89_CHILE][1][10] = -4, + [0][1][2][0][RTW89_QATAR][1][10] = 54, + [0][1][2][0][RTW89_QATAR][0][10] = 18, + [0][1][2][0][RTW89_UK][1][10] = 54, + [0][1][2][0][RTW89_UK][0][10] = 18, + [0][1][2][0][RTW89_FCC][1][12] = -4, + [0][1][2][0][RTW89_FCC][2][12] = 54, + [0][1][2][0][RTW89_ETSI][1][12] = 54, + [0][1][2][0][RTW89_ETSI][0][12] = 18, + [0][1][2][0][RTW89_MKK][1][12] = 54, + [0][1][2][0][RTW89_MKK][0][12] = 16, + [0][1][2][0][RTW89_IC][1][12] = -4, + [0][1][2][0][RTW89_KCC][1][12] = 12, + [0][1][2][0][RTW89_KCC][0][12] = 12, + [0][1][2][0][RTW89_ACMA][1][12] = 54, + [0][1][2][0][RTW89_ACMA][0][12] = 18, + [0][1][2][0][RTW89_CHILE][1][12] = -4, + [0][1][2][0][RTW89_QATAR][1][12] = 54, + [0][1][2][0][RTW89_QATAR][0][12] = 18, + [0][1][2][0][RTW89_UK][1][12] = 54, + [0][1][2][0][RTW89_UK][0][12] = 18, + [0][1][2][0][RTW89_FCC][1][14] = -4, + [0][1][2][0][RTW89_FCC][2][14] = 54, + [0][1][2][0][RTW89_ETSI][1][14] = 54, + [0][1][2][0][RTW89_ETSI][0][14] = 18, + [0][1][2][0][RTW89_MKK][1][14] = 54, + [0][1][2][0][RTW89_MKK][0][14] = 16, + [0][1][2][0][RTW89_IC][1][14] = -4, + [0][1][2][0][RTW89_KCC][1][14] = 12, + [0][1][2][0][RTW89_KCC][0][14] = 12, + [0][1][2][0][RTW89_ACMA][1][14] = 54, + [0][1][2][0][RTW89_ACMA][0][14] = 18, + [0][1][2][0][RTW89_CHILE][1][14] = -4, + [0][1][2][0][RTW89_QATAR][1][14] = 54, + [0][1][2][0][RTW89_QATAR][0][14] = 18, + [0][1][2][0][RTW89_UK][1][14] = 54, + [0][1][2][0][RTW89_UK][0][14] = 18, + [0][1][2][0][RTW89_FCC][1][15] = -4, + [0][1][2][0][RTW89_FCC][2][15] = 54, + [0][1][2][0][RTW89_ETSI][1][15] = 54, + [0][1][2][0][RTW89_ETSI][0][15] = 18, + [0][1][2][0][RTW89_MKK][1][15] = 54, + [0][1][2][0][RTW89_MKK][0][15] = 16, + [0][1][2][0][RTW89_IC][1][15] = -4, + [0][1][2][0][RTW89_KCC][1][15] = 12, + [0][1][2][0][RTW89_KCC][0][15] = 12, + [0][1][2][0][RTW89_ACMA][1][15] = 54, + [0][1][2][0][RTW89_ACMA][0][15] = 18, + [0][1][2][0][RTW89_CHILE][1][15] = -4, + [0][1][2][0][RTW89_QATAR][1][15] = 54, + [0][1][2][0][RTW89_QATAR][0][15] = 18, + [0][1][2][0][RTW89_UK][1][15] = 54, + [0][1][2][0][RTW89_UK][0][15] = 18, + [0][1][2][0][RTW89_FCC][1][17] = -4, + [0][1][2][0][RTW89_FCC][2][17] = 54, + [0][1][2][0][RTW89_ETSI][1][17] = 54, + [0][1][2][0][RTW89_ETSI][0][17] = 18, + [0][1][2][0][RTW89_MKK][1][17] = 54, + [0][1][2][0][RTW89_MKK][0][17] = 16, + [0][1][2][0][RTW89_IC][1][17] = -4, + [0][1][2][0][RTW89_KCC][1][17] = 12, + [0][1][2][0][RTW89_KCC][0][17] = 12, + [0][1][2][0][RTW89_ACMA][1][17] = 54, + [0][1][2][0][RTW89_ACMA][0][17] = 18, + [0][1][2][0][RTW89_CHILE][1][17] = -4, + [0][1][2][0][RTW89_QATAR][1][17] = 54, + [0][1][2][0][RTW89_QATAR][0][17] = 18, + [0][1][2][0][RTW89_UK][1][17] = 54, + [0][1][2][0][RTW89_UK][0][17] = 18, + [0][1][2][0][RTW89_FCC][1][19] = -4, + [0][1][2][0][RTW89_FCC][2][19] = 54, + [0][1][2][0][RTW89_ETSI][1][19] = 54, + [0][1][2][0][RTW89_ETSI][0][19] = 18, + [0][1][2][0][RTW89_MKK][1][19] = 54, + [0][1][2][0][RTW89_MKK][0][19] = 16, + [0][1][2][0][RTW89_IC][1][19] = -4, + [0][1][2][0][RTW89_KCC][1][19] = 12, + [0][1][2][0][RTW89_KCC][0][19] = 12, + [0][1][2][0][RTW89_ACMA][1][19] = 54, + [0][1][2][0][RTW89_ACMA][0][19] = 18, + [0][1][2][0][RTW89_CHILE][1][19] = -4, + [0][1][2][0][RTW89_QATAR][1][19] = 54, + [0][1][2][0][RTW89_QATAR][0][19] = 18, + [0][1][2][0][RTW89_UK][1][19] = 54, + [0][1][2][0][RTW89_UK][0][19] = 18, + [0][1][2][0][RTW89_FCC][1][21] = -4, + [0][1][2][0][RTW89_FCC][2][21] = 54, + [0][1][2][0][RTW89_ETSI][1][21] = 54, + [0][1][2][0][RTW89_ETSI][0][21] = 18, + [0][1][2][0][RTW89_MKK][1][21] = 54, + [0][1][2][0][RTW89_MKK][0][21] = 16, + [0][1][2][0][RTW89_IC][1][21] = -4, + [0][1][2][0][RTW89_KCC][1][21] = 12, + [0][1][2][0][RTW89_KCC][0][21] = 12, + [0][1][2][0][RTW89_ACMA][1][21] = 54, + [0][1][2][0][RTW89_ACMA][0][21] = 18, + [0][1][2][0][RTW89_CHILE][1][21] = -4, + [0][1][2][0][RTW89_QATAR][1][21] = 54, + [0][1][2][0][RTW89_QATAR][0][21] = 18, + [0][1][2][0][RTW89_UK][1][21] = 54, + [0][1][2][0][RTW89_UK][0][21] = 18, + [0][1][2][0][RTW89_FCC][1][23] = -4, + [0][1][2][0][RTW89_FCC][2][23] = 68, + [0][1][2][0][RTW89_ETSI][1][23] = 54, + [0][1][2][0][RTW89_ETSI][0][23] = 18, + [0][1][2][0][RTW89_MKK][1][23] = 54, + [0][1][2][0][RTW89_MKK][0][23] = 16, + [0][1][2][0][RTW89_IC][1][23] = -4, + [0][1][2][0][RTW89_KCC][1][23] = 12, + [0][1][2][0][RTW89_KCC][0][23] = 10, + [0][1][2][0][RTW89_ACMA][1][23] = 54, + [0][1][2][0][RTW89_ACMA][0][23] = 18, + [0][1][2][0][RTW89_CHILE][1][23] = -4, + [0][1][2][0][RTW89_QATAR][1][23] = 54, + [0][1][2][0][RTW89_QATAR][0][23] = 18, + [0][1][2][0][RTW89_UK][1][23] = 54, + [0][1][2][0][RTW89_UK][0][23] = 18, + [0][1][2][0][RTW89_FCC][1][25] = -4, + [0][1][2][0][RTW89_FCC][2][25] = 68, + [0][1][2][0][RTW89_ETSI][1][25] = 54, + [0][1][2][0][RTW89_ETSI][0][25] = 18, + [0][1][2][0][RTW89_MKK][1][25] = 54, + [0][1][2][0][RTW89_MKK][0][25] = 16, + [0][1][2][0][RTW89_IC][1][25] = -4, + [0][1][2][0][RTW89_KCC][1][25] = 12, + [0][1][2][0][RTW89_KCC][0][25] = 14, + [0][1][2][0][RTW89_ACMA][1][25] = 54, + [0][1][2][0][RTW89_ACMA][0][25] = 18, + [0][1][2][0][RTW89_CHILE][1][25] = -4, + [0][1][2][0][RTW89_QATAR][1][25] = 54, + [0][1][2][0][RTW89_QATAR][0][25] = 18, + [0][1][2][0][RTW89_UK][1][25] = 54, + [0][1][2][0][RTW89_UK][0][25] = 18, + [0][1][2][0][RTW89_FCC][1][27] = -4, + [0][1][2][0][RTW89_FCC][2][27] = 68, + [0][1][2][0][RTW89_ETSI][1][27] = 54, + [0][1][2][0][RTW89_ETSI][0][27] = 18, + [0][1][2][0][RTW89_MKK][1][27] = 54, + [0][1][2][0][RTW89_MKK][0][27] = 16, + [0][1][2][0][RTW89_IC][1][27] = -4, + [0][1][2][0][RTW89_KCC][1][27] = 12, + [0][1][2][0][RTW89_KCC][0][27] = 14, + [0][1][2][0][RTW89_ACMA][1][27] = 54, + [0][1][2][0][RTW89_ACMA][0][27] = 18, + [0][1][2][0][RTW89_CHILE][1][27] = -4, + [0][1][2][0][RTW89_QATAR][1][27] = 54, + [0][1][2][0][RTW89_QATAR][0][27] = 18, + [0][1][2][0][RTW89_UK][1][27] = 54, + [0][1][2][0][RTW89_UK][0][27] = 18, + [0][1][2][0][RTW89_FCC][1][29] = -4, + [0][1][2][0][RTW89_FCC][2][29] = 68, + [0][1][2][0][RTW89_ETSI][1][29] = 54, + [0][1][2][0][RTW89_ETSI][0][29] = 18, + [0][1][2][0][RTW89_MKK][1][29] = 54, + [0][1][2][0][RTW89_MKK][0][29] = 16, + [0][1][2][0][RTW89_IC][1][29] = -4, + [0][1][2][0][RTW89_KCC][1][29] = 12, + [0][1][2][0][RTW89_KCC][0][29] = 14, + [0][1][2][0][RTW89_ACMA][1][29] = 54, + [0][1][2][0][RTW89_ACMA][0][29] = 18, + [0][1][2][0][RTW89_CHILE][1][29] = -4, + [0][1][2][0][RTW89_QATAR][1][29] = 54, + [0][1][2][0][RTW89_QATAR][0][29] = 18, + [0][1][2][0][RTW89_UK][1][29] = 54, + [0][1][2][0][RTW89_UK][0][29] = 18, + [0][1][2][0][RTW89_FCC][1][30] = -4, + [0][1][2][0][RTW89_FCC][2][30] = 68, + [0][1][2][0][RTW89_ETSI][1][30] = 54, + [0][1][2][0][RTW89_ETSI][0][30] = 18, + [0][1][2][0][RTW89_MKK][1][30] = 54, + [0][1][2][0][RTW89_MKK][0][30] = 16, + [0][1][2][0][RTW89_IC][1][30] = -4, + [0][1][2][0][RTW89_KCC][1][30] = 12, + [0][1][2][0][RTW89_KCC][0][30] = 14, + [0][1][2][0][RTW89_ACMA][1][30] = 54, + [0][1][2][0][RTW89_ACMA][0][30] = 18, + [0][1][2][0][RTW89_CHILE][1][30] = -4, + [0][1][2][0][RTW89_QATAR][1][30] = 54, + [0][1][2][0][RTW89_QATAR][0][30] = 18, + [0][1][2][0][RTW89_UK][1][30] = 54, + [0][1][2][0][RTW89_UK][0][30] = 18, + [0][1][2][0][RTW89_FCC][1][32] = -4, + [0][1][2][0][RTW89_FCC][2][32] = 68, + [0][1][2][0][RTW89_ETSI][1][32] = 54, + [0][1][2][0][RTW89_ETSI][0][32] = 18, + [0][1][2][0][RTW89_MKK][1][32] = 54, + [0][1][2][0][RTW89_MKK][0][32] = 16, + [0][1][2][0][RTW89_IC][1][32] = -4, + [0][1][2][0][RTW89_KCC][1][32] = 12, + [0][1][2][0][RTW89_KCC][0][32] = 14, + [0][1][2][0][RTW89_ACMA][1][32] = 54, + [0][1][2][0][RTW89_ACMA][0][32] = 18, + [0][1][2][0][RTW89_CHILE][1][32] = -4, + [0][1][2][0][RTW89_QATAR][1][32] = 54, + [0][1][2][0][RTW89_QATAR][0][32] = 18, + [0][1][2][0][RTW89_UK][1][32] = 54, + [0][1][2][0][RTW89_UK][0][32] = 18, + [0][1][2][0][RTW89_FCC][1][34] = -4, + [0][1][2][0][RTW89_FCC][2][34] = 68, + [0][1][2][0][RTW89_ETSI][1][34] = 54, + [0][1][2][0][RTW89_ETSI][0][34] = 18, + [0][1][2][0][RTW89_MKK][1][34] = 54, + [0][1][2][0][RTW89_MKK][0][34] = 16, + [0][1][2][0][RTW89_IC][1][34] = -4, + [0][1][2][0][RTW89_KCC][1][34] = 12, + [0][1][2][0][RTW89_KCC][0][34] = 14, + [0][1][2][0][RTW89_ACMA][1][34] = 54, + [0][1][2][0][RTW89_ACMA][0][34] = 18, + [0][1][2][0][RTW89_CHILE][1][34] = -4, + [0][1][2][0][RTW89_QATAR][1][34] = 54, + [0][1][2][0][RTW89_QATAR][0][34] = 18, + [0][1][2][0][RTW89_UK][1][34] = 54, + [0][1][2][0][RTW89_UK][0][34] = 18, + [0][1][2][0][RTW89_FCC][1][36] = -4, + [0][1][2][0][RTW89_FCC][2][36] = 68, + [0][1][2][0][RTW89_ETSI][1][36] = 54, + [0][1][2][0][RTW89_ETSI][0][36] = 18, + [0][1][2][0][RTW89_MKK][1][36] = 54, + [0][1][2][0][RTW89_MKK][0][36] = 16, + [0][1][2][0][RTW89_IC][1][36] = -4, + [0][1][2][0][RTW89_KCC][1][36] = 12, + [0][1][2][0][RTW89_KCC][0][36] = 14, + [0][1][2][0][RTW89_ACMA][1][36] = 54, + [0][1][2][0][RTW89_ACMA][0][36] = 18, + [0][1][2][0][RTW89_CHILE][1][36] = -4, + [0][1][2][0][RTW89_QATAR][1][36] = 54, + [0][1][2][0][RTW89_QATAR][0][36] = 18, + [0][1][2][0][RTW89_UK][1][36] = 54, + [0][1][2][0][RTW89_UK][0][36] = 18, + [0][1][2][0][RTW89_FCC][1][38] = -4, + [0][1][2][0][RTW89_FCC][2][38] = 68, + [0][1][2][0][RTW89_ETSI][1][38] = 54, + [0][1][2][0][RTW89_ETSI][0][38] = 18, + [0][1][2][0][RTW89_MKK][1][38] = 54, + [0][1][2][0][RTW89_MKK][0][38] = 16, + [0][1][2][0][RTW89_IC][1][38] = -4, + [0][1][2][0][RTW89_KCC][1][38] = 12, + [0][1][2][0][RTW89_KCC][0][38] = 14, + [0][1][2][0][RTW89_ACMA][1][38] = 54, + [0][1][2][0][RTW89_ACMA][0][38] = 18, + [0][1][2][0][RTW89_CHILE][1][38] = -4, + [0][1][2][0][RTW89_QATAR][1][38] = 54, + [0][1][2][0][RTW89_QATAR][0][38] = 18, + [0][1][2][0][RTW89_UK][1][38] = 54, + [0][1][2][0][RTW89_UK][0][38] = 18, + [0][1][2][0][RTW89_FCC][1][40] = -4, + [0][1][2][0][RTW89_FCC][2][40] = 68, + [0][1][2][0][RTW89_ETSI][1][40] = 54, + [0][1][2][0][RTW89_ETSI][0][40] = 18, + [0][1][2][0][RTW89_MKK][1][40] = 54, + [0][1][2][0][RTW89_MKK][0][40] = 16, + [0][1][2][0][RTW89_IC][1][40] = -4, + [0][1][2][0][RTW89_KCC][1][40] = 12, + [0][1][2][0][RTW89_KCC][0][40] = 14, + [0][1][2][0][RTW89_ACMA][1][40] = 54, + [0][1][2][0][RTW89_ACMA][0][40] = 18, + [0][1][2][0][RTW89_CHILE][1][40] = -4, + [0][1][2][0][RTW89_QATAR][1][40] = 54, + [0][1][2][0][RTW89_QATAR][0][40] = 18, + [0][1][2][0][RTW89_UK][1][40] = 54, + [0][1][2][0][RTW89_UK][0][40] = 18, + [0][1][2][0][RTW89_FCC][1][42] = -4, + [0][1][2][0][RTW89_FCC][2][42] = 68, + [0][1][2][0][RTW89_ETSI][1][42] = 54, + [0][1][2][0][RTW89_ETSI][0][42] = 18, + [0][1][2][0][RTW89_MKK][1][42] = 54, + [0][1][2][0][RTW89_MKK][0][42] = 16, + [0][1][2][0][RTW89_IC][1][42] = -4, + [0][1][2][0][RTW89_KCC][1][42] = 12, + [0][1][2][0][RTW89_KCC][0][42] = 14, + [0][1][2][0][RTW89_ACMA][1][42] = 54, + [0][1][2][0][RTW89_ACMA][0][42] = 18, + [0][1][2][0][RTW89_CHILE][1][42] = -4, + [0][1][2][0][RTW89_QATAR][1][42] = 54, + [0][1][2][0][RTW89_QATAR][0][42] = 18, + [0][1][2][0][RTW89_UK][1][42] = 54, + [0][1][2][0][RTW89_UK][0][42] = 18, + [0][1][2][0][RTW89_FCC][1][44] = -2, + [0][1][2][0][RTW89_FCC][2][44] = 68, + [0][1][2][0][RTW89_ETSI][1][44] = 54, + [0][1][2][0][RTW89_ETSI][0][44] = 18, + [0][1][2][0][RTW89_MKK][1][44] = 34, + [0][1][2][0][RTW89_MKK][0][44] = 16, + [0][1][2][0][RTW89_IC][1][44] = -2, + [0][1][2][0][RTW89_KCC][1][44] = 12, + [0][1][2][0][RTW89_KCC][0][44] = 12, + [0][1][2][0][RTW89_ACMA][1][44] = 54, + [0][1][2][0][RTW89_ACMA][0][44] = 18, + [0][1][2][0][RTW89_CHILE][1][44] = -2, + [0][1][2][0][RTW89_QATAR][1][44] = 54, + [0][1][2][0][RTW89_QATAR][0][44] = 18, + [0][1][2][0][RTW89_UK][1][44] = 54, + [0][1][2][0][RTW89_UK][0][44] = 18, + [0][1][2][0][RTW89_FCC][1][45] = -2, + [0][1][2][0][RTW89_FCC][2][45] = 127, + [0][1][2][0][RTW89_ETSI][1][45] = 127, + [0][1][2][0][RTW89_ETSI][0][45] = 127, + [0][1][2][0][RTW89_MKK][1][45] = 127, + [0][1][2][0][RTW89_MKK][0][45] = 127, + [0][1][2][0][RTW89_IC][1][45] = -2, + [0][1][2][0][RTW89_KCC][1][45] = 12, + [0][1][2][0][RTW89_KCC][0][45] = 127, + [0][1][2][0][RTW89_ACMA][1][45] = 127, + [0][1][2][0][RTW89_ACMA][0][45] = 127, + [0][1][2][0][RTW89_CHILE][1][45] = -2, + [0][1][2][0][RTW89_QATAR][1][45] = 127, + [0][1][2][0][RTW89_QATAR][0][45] = 127, + [0][1][2][0][RTW89_UK][1][45] = 127, + [0][1][2][0][RTW89_UK][0][45] = 127, + [0][1][2][0][RTW89_FCC][1][47] = -2, + [0][1][2][0][RTW89_FCC][2][47] = 127, + [0][1][2][0][RTW89_ETSI][1][47] = 127, + [0][1][2][0][RTW89_ETSI][0][47] = 127, + [0][1][2][0][RTW89_MKK][1][47] = 127, + [0][1][2][0][RTW89_MKK][0][47] = 127, + [0][1][2][0][RTW89_IC][1][47] = -2, + [0][1][2][0][RTW89_KCC][1][47] = 12, + [0][1][2][0][RTW89_KCC][0][47] = 127, + [0][1][2][0][RTW89_ACMA][1][47] = 127, + [0][1][2][0][RTW89_ACMA][0][47] = 127, + [0][1][2][0][RTW89_CHILE][1][47] = -2, + [0][1][2][0][RTW89_QATAR][1][47] = 127, + [0][1][2][0][RTW89_QATAR][0][47] = 127, + [0][1][2][0][RTW89_UK][1][47] = 127, + [0][1][2][0][RTW89_UK][0][47] = 127, + [0][1][2][0][RTW89_FCC][1][49] = -2, + [0][1][2][0][RTW89_FCC][2][49] = 127, + [0][1][2][0][RTW89_ETSI][1][49] = 127, + [0][1][2][0][RTW89_ETSI][0][49] = 127, + [0][1][2][0][RTW89_MKK][1][49] = 127, + [0][1][2][0][RTW89_MKK][0][49] = 127, + [0][1][2][0][RTW89_IC][1][49] = -2, + [0][1][2][0][RTW89_KCC][1][49] = 12, + [0][1][2][0][RTW89_KCC][0][49] = 127, + [0][1][2][0][RTW89_ACMA][1][49] = 127, + [0][1][2][0][RTW89_ACMA][0][49] = 127, + [0][1][2][0][RTW89_CHILE][1][49] = -2, + [0][1][2][0][RTW89_QATAR][1][49] = 127, + [0][1][2][0][RTW89_QATAR][0][49] = 127, + [0][1][2][0][RTW89_UK][1][49] = 127, + [0][1][2][0][RTW89_UK][0][49] = 127, + [0][1][2][0][RTW89_FCC][1][51] = -2, + [0][1][2][0][RTW89_FCC][2][51] = 127, + [0][1][2][0][RTW89_ETSI][1][51] = 127, + [0][1][2][0][RTW89_ETSI][0][51] = 127, + [0][1][2][0][RTW89_MKK][1][51] = 127, + [0][1][2][0][RTW89_MKK][0][51] = 127, + [0][1][2][0][RTW89_IC][1][51] = -2, + [0][1][2][0][RTW89_KCC][1][51] = 12, + [0][1][2][0][RTW89_KCC][0][51] = 127, + [0][1][2][0][RTW89_ACMA][1][51] = 127, + [0][1][2][0][RTW89_ACMA][0][51] = 127, + [0][1][2][0][RTW89_CHILE][1][51] = -2, + [0][1][2][0][RTW89_QATAR][1][51] = 127, + [0][1][2][0][RTW89_QATAR][0][51] = 127, + [0][1][2][0][RTW89_UK][1][51] = 127, + [0][1][2][0][RTW89_UK][0][51] = 127, + [0][1][2][0][RTW89_FCC][1][53] = -2, + [0][1][2][0][RTW89_FCC][2][53] = 127, + [0][1][2][0][RTW89_ETSI][1][53] = 127, + [0][1][2][0][RTW89_ETSI][0][53] = 127, + [0][1][2][0][RTW89_MKK][1][53] = 127, + [0][1][2][0][RTW89_MKK][0][53] = 127, + [0][1][2][0][RTW89_IC][1][53] = -2, + [0][1][2][0][RTW89_KCC][1][53] = 12, + [0][1][2][0][RTW89_KCC][0][53] = 127, + [0][1][2][0][RTW89_ACMA][1][53] = 127, + [0][1][2][0][RTW89_ACMA][0][53] = 127, + [0][1][2][0][RTW89_CHILE][1][53] = -2, + [0][1][2][0][RTW89_QATAR][1][53] = 127, + [0][1][2][0][RTW89_QATAR][0][53] = 127, + [0][1][2][0][RTW89_UK][1][53] = 127, + [0][1][2][0][RTW89_UK][0][53] = 127, + [0][1][2][0][RTW89_FCC][1][55] = -2, + [0][1][2][0][RTW89_FCC][2][55] = 68, + [0][1][2][0][RTW89_ETSI][1][55] = 127, + [0][1][2][0][RTW89_ETSI][0][55] = 127, + [0][1][2][0][RTW89_MKK][1][55] = 127, + [0][1][2][0][RTW89_MKK][0][55] = 127, + [0][1][2][0][RTW89_IC][1][55] = -2, + [0][1][2][0][RTW89_KCC][1][55] = 12, + [0][1][2][0][RTW89_KCC][0][55] = 127, + [0][1][2][0][RTW89_ACMA][1][55] = 127, + [0][1][2][0][RTW89_ACMA][0][55] = 127, + [0][1][2][0][RTW89_CHILE][1][55] = -2, + [0][1][2][0][RTW89_QATAR][1][55] = 127, + [0][1][2][0][RTW89_QATAR][0][55] = 127, + [0][1][2][0][RTW89_UK][1][55] = 127, + [0][1][2][0][RTW89_UK][0][55] = 127, + [0][1][2][0][RTW89_FCC][1][57] = -2, + [0][1][2][0][RTW89_FCC][2][57] = 68, + [0][1][2][0][RTW89_ETSI][1][57] = 127, + [0][1][2][0][RTW89_ETSI][0][57] = 127, + [0][1][2][0][RTW89_MKK][1][57] = 127, + [0][1][2][0][RTW89_MKK][0][57] = 127, + [0][1][2][0][RTW89_IC][1][57] = -2, + [0][1][2][0][RTW89_KCC][1][57] = 12, + [0][1][2][0][RTW89_KCC][0][57] = 127, + [0][1][2][0][RTW89_ACMA][1][57] = 127, + [0][1][2][0][RTW89_ACMA][0][57] = 127, + [0][1][2][0][RTW89_CHILE][1][57] = -2, + [0][1][2][0][RTW89_QATAR][1][57] = 127, + [0][1][2][0][RTW89_QATAR][0][57] = 127, + [0][1][2][0][RTW89_UK][1][57] = 127, + [0][1][2][0][RTW89_UK][0][57] = 127, + [0][1][2][0][RTW89_FCC][1][59] = -2, + [0][1][2][0][RTW89_FCC][2][59] = 68, + [0][1][2][0][RTW89_ETSI][1][59] = 127, + [0][1][2][0][RTW89_ETSI][0][59] = 127, + [0][1][2][0][RTW89_MKK][1][59] = 127, + [0][1][2][0][RTW89_MKK][0][59] = 127, + [0][1][2][0][RTW89_IC][1][59] = -2, + [0][1][2][0][RTW89_KCC][1][59] = 12, + [0][1][2][0][RTW89_KCC][0][59] = 127, + [0][1][2][0][RTW89_ACMA][1][59] = 127, + [0][1][2][0][RTW89_ACMA][0][59] = 127, + [0][1][2][0][RTW89_CHILE][1][59] = -2, + [0][1][2][0][RTW89_QATAR][1][59] = 127, + [0][1][2][0][RTW89_QATAR][0][59] = 127, + [0][1][2][0][RTW89_UK][1][59] = 127, + [0][1][2][0][RTW89_UK][0][59] = 127, + [0][1][2][0][RTW89_FCC][1][60] = -2, + [0][1][2][0][RTW89_FCC][2][60] = 68, + [0][1][2][0][RTW89_ETSI][1][60] = 127, + [0][1][2][0][RTW89_ETSI][0][60] = 127, + [0][1][2][0][RTW89_MKK][1][60] = 127, + [0][1][2][0][RTW89_MKK][0][60] = 127, + [0][1][2][0][RTW89_IC][1][60] = -2, + [0][1][2][0][RTW89_KCC][1][60] = 12, + [0][1][2][0][RTW89_KCC][0][60] = 127, + [0][1][2][0][RTW89_ACMA][1][60] = 127, + [0][1][2][0][RTW89_ACMA][0][60] = 127, + [0][1][2][0][RTW89_CHILE][1][60] = -2, + [0][1][2][0][RTW89_QATAR][1][60] = 127, + [0][1][2][0][RTW89_QATAR][0][60] = 127, + [0][1][2][0][RTW89_UK][1][60] = 127, + [0][1][2][0][RTW89_UK][0][60] = 127, + [0][1][2][0][RTW89_FCC][1][62] = -2, + [0][1][2][0][RTW89_FCC][2][62] = 68, + [0][1][2][0][RTW89_ETSI][1][62] = 127, + [0][1][2][0][RTW89_ETSI][0][62] = 127, + [0][1][2][0][RTW89_MKK][1][62] = 127, + [0][1][2][0][RTW89_MKK][0][62] = 127, + [0][1][2][0][RTW89_IC][1][62] = -2, + [0][1][2][0][RTW89_KCC][1][62] = 12, + [0][1][2][0][RTW89_KCC][0][62] = 127, + [0][1][2][0][RTW89_ACMA][1][62] = 127, + [0][1][2][0][RTW89_ACMA][0][62] = 127, + [0][1][2][0][RTW89_CHILE][1][62] = -2, + [0][1][2][0][RTW89_QATAR][1][62] = 127, + [0][1][2][0][RTW89_QATAR][0][62] = 127, + [0][1][2][0][RTW89_UK][1][62] = 127, + [0][1][2][0][RTW89_UK][0][62] = 127, + [0][1][2][0][RTW89_FCC][1][64] = -2, + [0][1][2][0][RTW89_FCC][2][64] = 68, + [0][1][2][0][RTW89_ETSI][1][64] = 127, + [0][1][2][0][RTW89_ETSI][0][64] = 127, + [0][1][2][0][RTW89_MKK][1][64] = 127, + [0][1][2][0][RTW89_MKK][0][64] = 127, + [0][1][2][0][RTW89_IC][1][64] = -2, + [0][1][2][0][RTW89_KCC][1][64] = 12, + [0][1][2][0][RTW89_KCC][0][64] = 127, + [0][1][2][0][RTW89_ACMA][1][64] = 127, + [0][1][2][0][RTW89_ACMA][0][64] = 127, + [0][1][2][0][RTW89_CHILE][1][64] = -2, + [0][1][2][0][RTW89_QATAR][1][64] = 127, + [0][1][2][0][RTW89_QATAR][0][64] = 127, + [0][1][2][0][RTW89_UK][1][64] = 127, + [0][1][2][0][RTW89_UK][0][64] = 127, + [0][1][2][0][RTW89_FCC][1][66] = -2, + [0][1][2][0][RTW89_FCC][2][66] = 68, + [0][1][2][0][RTW89_ETSI][1][66] = 127, + [0][1][2][0][RTW89_ETSI][0][66] = 127, + [0][1][2][0][RTW89_MKK][1][66] = 127, + [0][1][2][0][RTW89_MKK][0][66] = 127, + [0][1][2][0][RTW89_IC][1][66] = -2, + [0][1][2][0][RTW89_KCC][1][66] = 12, + [0][1][2][0][RTW89_KCC][0][66] = 127, + [0][1][2][0][RTW89_ACMA][1][66] = 127, + [0][1][2][0][RTW89_ACMA][0][66] = 127, + [0][1][2][0][RTW89_CHILE][1][66] = -2, + [0][1][2][0][RTW89_QATAR][1][66] = 127, + [0][1][2][0][RTW89_QATAR][0][66] = 127, + [0][1][2][0][RTW89_UK][1][66] = 127, + [0][1][2][0][RTW89_UK][0][66] = 127, + [0][1][2][0][RTW89_FCC][1][68] = -2, + [0][1][2][0][RTW89_FCC][2][68] = 68, + [0][1][2][0][RTW89_ETSI][1][68] = 127, + [0][1][2][0][RTW89_ETSI][0][68] = 127, + [0][1][2][0][RTW89_MKK][1][68] = 127, + [0][1][2][0][RTW89_MKK][0][68] = 127, + [0][1][2][0][RTW89_IC][1][68] = -2, + [0][1][2][0][RTW89_KCC][1][68] = 12, + [0][1][2][0][RTW89_KCC][0][68] = 127, + [0][1][2][0][RTW89_ACMA][1][68] = 127, + [0][1][2][0][RTW89_ACMA][0][68] = 127, + [0][1][2][0][RTW89_CHILE][1][68] = -2, + [0][1][2][0][RTW89_QATAR][1][68] = 127, + [0][1][2][0][RTW89_QATAR][0][68] = 127, + [0][1][2][0][RTW89_UK][1][68] = 127, + [0][1][2][0][RTW89_UK][0][68] = 127, + [0][1][2][0][RTW89_FCC][1][70] = -2, + [0][1][2][0][RTW89_FCC][2][70] = 68, + [0][1][2][0][RTW89_ETSI][1][70] = 127, + [0][1][2][0][RTW89_ETSI][0][70] = 127, + [0][1][2][0][RTW89_MKK][1][70] = 127, + [0][1][2][0][RTW89_MKK][0][70] = 127, + [0][1][2][0][RTW89_IC][1][70] = -2, + [0][1][2][0][RTW89_KCC][1][70] = 12, + [0][1][2][0][RTW89_KCC][0][70] = 127, + [0][1][2][0][RTW89_ACMA][1][70] = 127, + [0][1][2][0][RTW89_ACMA][0][70] = 127, + [0][1][2][0][RTW89_CHILE][1][70] = -2, + [0][1][2][0][RTW89_QATAR][1][70] = 127, + [0][1][2][0][RTW89_QATAR][0][70] = 127, + [0][1][2][0][RTW89_UK][1][70] = 127, + [0][1][2][0][RTW89_UK][0][70] = 127, + [0][1][2][0][RTW89_FCC][1][72] = -2, + [0][1][2][0][RTW89_FCC][2][72] = 68, + [0][1][2][0][RTW89_ETSI][1][72] = 127, + [0][1][2][0][RTW89_ETSI][0][72] = 127, + [0][1][2][0][RTW89_MKK][1][72] = 127, + [0][1][2][0][RTW89_MKK][0][72] = 127, + [0][1][2][0][RTW89_IC][1][72] = -2, + [0][1][2][0][RTW89_KCC][1][72] = 12, + [0][1][2][0][RTW89_KCC][0][72] = 127, + [0][1][2][0][RTW89_ACMA][1][72] = 127, + [0][1][2][0][RTW89_ACMA][0][72] = 127, + [0][1][2][0][RTW89_CHILE][1][72] = -2, + [0][1][2][0][RTW89_QATAR][1][72] = 127, + [0][1][2][0][RTW89_QATAR][0][72] = 127, + [0][1][2][0][RTW89_UK][1][72] = 127, + [0][1][2][0][RTW89_UK][0][72] = 127, + [0][1][2][0][RTW89_FCC][1][74] = -2, + [0][1][2][0][RTW89_FCC][2][74] = 68, + [0][1][2][0][RTW89_ETSI][1][74] = 127, + [0][1][2][0][RTW89_ETSI][0][74] = 127, + [0][1][2][0][RTW89_MKK][1][74] = 127, + [0][1][2][0][RTW89_MKK][0][74] = 127, + [0][1][2][0][RTW89_IC][1][74] = -2, + [0][1][2][0][RTW89_KCC][1][74] = 12, + [0][1][2][0][RTW89_KCC][0][74] = 127, + [0][1][2][0][RTW89_ACMA][1][74] = 127, + [0][1][2][0][RTW89_ACMA][0][74] = 127, + [0][1][2][0][RTW89_CHILE][1][74] = -2, + [0][1][2][0][RTW89_QATAR][1][74] = 127, + [0][1][2][0][RTW89_QATAR][0][74] = 127, + [0][1][2][0][RTW89_UK][1][74] = 127, + [0][1][2][0][RTW89_UK][0][74] = 127, + [0][1][2][0][RTW89_FCC][1][75] = -2, + [0][1][2][0][RTW89_FCC][2][75] = 68, + [0][1][2][0][RTW89_ETSI][1][75] = 127, + [0][1][2][0][RTW89_ETSI][0][75] = 127, + [0][1][2][0][RTW89_MKK][1][75] = 127, + [0][1][2][0][RTW89_MKK][0][75] = 127, + [0][1][2][0][RTW89_IC][1][75] = -2, + [0][1][2][0][RTW89_KCC][1][75] = 12, + [0][1][2][0][RTW89_KCC][0][75] = 127, + [0][1][2][0][RTW89_ACMA][1][75] = 127, + [0][1][2][0][RTW89_ACMA][0][75] = 127, + [0][1][2][0][RTW89_CHILE][1][75] = -2, + [0][1][2][0][RTW89_QATAR][1][75] = 127, + [0][1][2][0][RTW89_QATAR][0][75] = 127, + [0][1][2][0][RTW89_UK][1][75] = 127, + [0][1][2][0][RTW89_UK][0][75] = 127, + [0][1][2][0][RTW89_FCC][1][77] = -2, + [0][1][2][0][RTW89_FCC][2][77] = 68, + [0][1][2][0][RTW89_ETSI][1][77] = 127, + [0][1][2][0][RTW89_ETSI][0][77] = 127, + [0][1][2][0][RTW89_MKK][1][77] = 127, + [0][1][2][0][RTW89_MKK][0][77] = 127, + [0][1][2][0][RTW89_IC][1][77] = -2, + [0][1][2][0][RTW89_KCC][1][77] = 12, + [0][1][2][0][RTW89_KCC][0][77] = 127, + [0][1][2][0][RTW89_ACMA][1][77] = 127, + [0][1][2][0][RTW89_ACMA][0][77] = 127, + [0][1][2][0][RTW89_CHILE][1][77] = -2, + [0][1][2][0][RTW89_QATAR][1][77] = 127, + [0][1][2][0][RTW89_QATAR][0][77] = 127, + [0][1][2][0][RTW89_UK][1][77] = 127, + [0][1][2][0][RTW89_UK][0][77] = 127, + [0][1][2][0][RTW89_FCC][1][79] = -2, + [0][1][2][0][RTW89_FCC][2][79] = 68, + [0][1][2][0][RTW89_ETSI][1][79] = 127, + [0][1][2][0][RTW89_ETSI][0][79] = 127, + [0][1][2][0][RTW89_MKK][1][79] = 127, + [0][1][2][0][RTW89_MKK][0][79] = 127, + [0][1][2][0][RTW89_IC][1][79] = -2, + [0][1][2][0][RTW89_KCC][1][79] = 12, + [0][1][2][0][RTW89_KCC][0][79] = 127, + [0][1][2][0][RTW89_ACMA][1][79] = 127, + [0][1][2][0][RTW89_ACMA][0][79] = 127, + [0][1][2][0][RTW89_CHILE][1][79] = -2, + [0][1][2][0][RTW89_QATAR][1][79] = 127, + [0][1][2][0][RTW89_QATAR][0][79] = 127, + [0][1][2][0][RTW89_UK][1][79] = 127, + [0][1][2][0][RTW89_UK][0][79] = 127, + [0][1][2][0][RTW89_FCC][1][81] = -2, + [0][1][2][0][RTW89_FCC][2][81] = 68, + [0][1][2][0][RTW89_ETSI][1][81] = 127, + [0][1][2][0][RTW89_ETSI][0][81] = 127, + [0][1][2][0][RTW89_MKK][1][81] = 127, + [0][1][2][0][RTW89_MKK][0][81] = 127, + [0][1][2][0][RTW89_IC][1][81] = -2, + [0][1][2][0][RTW89_KCC][1][81] = 12, + [0][1][2][0][RTW89_KCC][0][81] = 127, + [0][1][2][0][RTW89_ACMA][1][81] = 127, + [0][1][2][0][RTW89_ACMA][0][81] = 127, + [0][1][2][0][RTW89_CHILE][1][81] = -2, + [0][1][2][0][RTW89_QATAR][1][81] = 127, + [0][1][2][0][RTW89_QATAR][0][81] = 127, + [0][1][2][0][RTW89_UK][1][81] = 127, + [0][1][2][0][RTW89_UK][0][81] = 127, + [0][1][2][0][RTW89_FCC][1][83] = -2, + [0][1][2][0][RTW89_FCC][2][83] = 68, + [0][1][2][0][RTW89_ETSI][1][83] = 127, + [0][1][2][0][RTW89_ETSI][0][83] = 127, + [0][1][2][0][RTW89_MKK][1][83] = 127, + [0][1][2][0][RTW89_MKK][0][83] = 127, + [0][1][2][0][RTW89_IC][1][83] = -2, + [0][1][2][0][RTW89_KCC][1][83] = 20, + [0][1][2][0][RTW89_KCC][0][83] = 127, + [0][1][2][0][RTW89_ACMA][1][83] = 127, + [0][1][2][0][RTW89_ACMA][0][83] = 127, + [0][1][2][0][RTW89_CHILE][1][83] = -2, + [0][1][2][0][RTW89_QATAR][1][83] = 127, + [0][1][2][0][RTW89_QATAR][0][83] = 127, + [0][1][2][0][RTW89_UK][1][83] = 127, + [0][1][2][0][RTW89_UK][0][83] = 127, + [0][1][2][0][RTW89_FCC][1][85] = -2, + [0][1][2][0][RTW89_FCC][2][85] = 68, + [0][1][2][0][RTW89_ETSI][1][85] = 127, + [0][1][2][0][RTW89_ETSI][0][85] = 127, + [0][1][2][0][RTW89_MKK][1][85] = 127, + [0][1][2][0][RTW89_MKK][0][85] = 127, + [0][1][2][0][RTW89_IC][1][85] = -2, + [0][1][2][0][RTW89_KCC][1][85] = 20, + [0][1][2][0][RTW89_KCC][0][85] = 127, + [0][1][2][0][RTW89_ACMA][1][85] = 127, + [0][1][2][0][RTW89_ACMA][0][85] = 127, + [0][1][2][0][RTW89_CHILE][1][85] = -2, + [0][1][2][0][RTW89_QATAR][1][85] = 127, + [0][1][2][0][RTW89_QATAR][0][85] = 127, + [0][1][2][0][RTW89_UK][1][85] = 127, + [0][1][2][0][RTW89_UK][0][85] = 127, + [0][1][2][0][RTW89_FCC][1][87] = -2, + [0][1][2][0][RTW89_FCC][2][87] = 127, + [0][1][2][0][RTW89_ETSI][1][87] = 127, + [0][1][2][0][RTW89_ETSI][0][87] = 127, + [0][1][2][0][RTW89_MKK][1][87] = 127, + [0][1][2][0][RTW89_MKK][0][87] = 127, + [0][1][2][0][RTW89_IC][1][87] = -2, + [0][1][2][0][RTW89_KCC][1][87] = 20, + [0][1][2][0][RTW89_KCC][0][87] = 127, + [0][1][2][0][RTW89_ACMA][1][87] = 127, + [0][1][2][0][RTW89_ACMA][0][87] = 127, + [0][1][2][0][RTW89_CHILE][1][87] = -2, + [0][1][2][0][RTW89_QATAR][1][87] = 127, + [0][1][2][0][RTW89_QATAR][0][87] = 127, + [0][1][2][0][RTW89_UK][1][87] = 127, + [0][1][2][0][RTW89_UK][0][87] = 127, + [0][1][2][0][RTW89_FCC][1][89] = -2, + [0][1][2][0][RTW89_FCC][2][89] = 127, + [0][1][2][0][RTW89_ETSI][1][89] = 127, + [0][1][2][0][RTW89_ETSI][0][89] = 127, + [0][1][2][0][RTW89_MKK][1][89] = 127, + [0][1][2][0][RTW89_MKK][0][89] = 127, + [0][1][2][0][RTW89_IC][1][89] = -2, + [0][1][2][0][RTW89_KCC][1][89] = 20, + [0][1][2][0][RTW89_KCC][0][89] = 127, + [0][1][2][0][RTW89_ACMA][1][89] = 127, + [0][1][2][0][RTW89_ACMA][0][89] = 127, + [0][1][2][0][RTW89_CHILE][1][89] = -2, + [0][1][2][0][RTW89_QATAR][1][89] = 127, + [0][1][2][0][RTW89_QATAR][0][89] = 127, + [0][1][2][0][RTW89_UK][1][89] = 127, + [0][1][2][0][RTW89_UK][0][89] = 127, + [0][1][2][0][RTW89_FCC][1][90] = -2, + [0][1][2][0][RTW89_FCC][2][90] = 127, + [0][1][2][0][RTW89_ETSI][1][90] = 127, + [0][1][2][0][RTW89_ETSI][0][90] = 127, + [0][1][2][0][RTW89_MKK][1][90] = 127, + [0][1][2][0][RTW89_MKK][0][90] = 127, + [0][1][2][0][RTW89_IC][1][90] = -2, + [0][1][2][0][RTW89_KCC][1][90] = 20, + [0][1][2][0][RTW89_KCC][0][90] = 127, + [0][1][2][0][RTW89_ACMA][1][90] = 127, + [0][1][2][0][RTW89_ACMA][0][90] = 127, + [0][1][2][0][RTW89_CHILE][1][90] = -2, + [0][1][2][0][RTW89_QATAR][1][90] = 127, + [0][1][2][0][RTW89_QATAR][0][90] = 127, + [0][1][2][0][RTW89_UK][1][90] = 127, + [0][1][2][0][RTW89_UK][0][90] = 127, + [0][1][2][0][RTW89_FCC][1][92] = -2, + [0][1][2][0][RTW89_FCC][2][92] = 127, + [0][1][2][0][RTW89_ETSI][1][92] = 127, + [0][1][2][0][RTW89_ETSI][0][92] = 127, + [0][1][2][0][RTW89_MKK][1][92] = 127, + [0][1][2][0][RTW89_MKK][0][92] = 127, + [0][1][2][0][RTW89_IC][1][92] = -2, + [0][1][2][0][RTW89_KCC][1][92] = 20, + [0][1][2][0][RTW89_KCC][0][92] = 127, + [0][1][2][0][RTW89_ACMA][1][92] = 127, + [0][1][2][0][RTW89_ACMA][0][92] = 127, + [0][1][2][0][RTW89_CHILE][1][92] = -2, + [0][1][2][0][RTW89_QATAR][1][92] = 127, + [0][1][2][0][RTW89_QATAR][0][92] = 127, + [0][1][2][0][RTW89_UK][1][92] = 127, + [0][1][2][0][RTW89_UK][0][92] = 127, + [0][1][2][0][RTW89_FCC][1][94] = -2, + [0][1][2][0][RTW89_FCC][2][94] = 127, + [0][1][2][0][RTW89_ETSI][1][94] = 127, + [0][1][2][0][RTW89_ETSI][0][94] = 127, + [0][1][2][0][RTW89_MKK][1][94] = 127, + [0][1][2][0][RTW89_MKK][0][94] = 127, + [0][1][2][0][RTW89_IC][1][94] = -2, + [0][1][2][0][RTW89_KCC][1][94] = 20, + [0][1][2][0][RTW89_KCC][0][94] = 127, + [0][1][2][0][RTW89_ACMA][1][94] = 127, + [0][1][2][0][RTW89_ACMA][0][94] = 127, + [0][1][2][0][RTW89_CHILE][1][94] = -2, + [0][1][2][0][RTW89_QATAR][1][94] = 127, + [0][1][2][0][RTW89_QATAR][0][94] = 127, + [0][1][2][0][RTW89_UK][1][94] = 127, + [0][1][2][0][RTW89_UK][0][94] = 127, + [0][1][2][0][RTW89_FCC][1][96] = -2, + [0][1][2][0][RTW89_FCC][2][96] = 127, + [0][1][2][0][RTW89_ETSI][1][96] = 127, + [0][1][2][0][RTW89_ETSI][0][96] = 127, + [0][1][2][0][RTW89_MKK][1][96] = 127, + [0][1][2][0][RTW89_MKK][0][96] = 127, + [0][1][2][0][RTW89_IC][1][96] = -2, + [0][1][2][0][RTW89_KCC][1][96] = 20, + [0][1][2][0][RTW89_KCC][0][96] = 127, + [0][1][2][0][RTW89_ACMA][1][96] = 127, + [0][1][2][0][RTW89_ACMA][0][96] = 127, + [0][1][2][0][RTW89_CHILE][1][96] = -2, + [0][1][2][0][RTW89_QATAR][1][96] = 127, + [0][1][2][0][RTW89_QATAR][0][96] = 127, + [0][1][2][0][RTW89_UK][1][96] = 127, + [0][1][2][0][RTW89_UK][0][96] = 127, + [0][1][2][0][RTW89_FCC][1][98] = -2, + [0][1][2][0][RTW89_FCC][2][98] = 127, + [0][1][2][0][RTW89_ETSI][1][98] = 127, + [0][1][2][0][RTW89_ETSI][0][98] = 127, + [0][1][2][0][RTW89_MKK][1][98] = 127, + [0][1][2][0][RTW89_MKK][0][98] = 127, + [0][1][2][0][RTW89_IC][1][98] = -2, + [0][1][2][0][RTW89_KCC][1][98] = 20, + [0][1][2][0][RTW89_KCC][0][98] = 127, + [0][1][2][0][RTW89_ACMA][1][98] = 127, + [0][1][2][0][RTW89_ACMA][0][98] = 127, + [0][1][2][0][RTW89_CHILE][1][98] = -2, + [0][1][2][0][RTW89_QATAR][1][98] = 127, + [0][1][2][0][RTW89_QATAR][0][98] = 127, + [0][1][2][0][RTW89_UK][1][98] = 127, + [0][1][2][0][RTW89_UK][0][98] = 127, + [0][1][2][0][RTW89_FCC][1][100] = -2, + [0][1][2][0][RTW89_FCC][2][100] = 127, + [0][1][2][0][RTW89_ETSI][1][100] = 127, + [0][1][2][0][RTW89_ETSI][0][100] = 127, + [0][1][2][0][RTW89_MKK][1][100] = 127, + [0][1][2][0][RTW89_MKK][0][100] = 127, + [0][1][2][0][RTW89_IC][1][100] = -2, + [0][1][2][0][RTW89_KCC][1][100] = 20, + [0][1][2][0][RTW89_KCC][0][100] = 127, + [0][1][2][0][RTW89_ACMA][1][100] = 127, + [0][1][2][0][RTW89_ACMA][0][100] = 127, + [0][1][2][0][RTW89_CHILE][1][100] = -2, + [0][1][2][0][RTW89_QATAR][1][100] = 127, + [0][1][2][0][RTW89_QATAR][0][100] = 127, + [0][1][2][0][RTW89_UK][1][100] = 127, + [0][1][2][0][RTW89_UK][0][100] = 127, + [0][1][2][0][RTW89_FCC][1][102] = -2, + [0][1][2][0][RTW89_FCC][2][102] = 127, + [0][1][2][0][RTW89_ETSI][1][102] = 127, + [0][1][2][0][RTW89_ETSI][0][102] = 127, + [0][1][2][0][RTW89_MKK][1][102] = 127, + [0][1][2][0][RTW89_MKK][0][102] = 127, + [0][1][2][0][RTW89_IC][1][102] = -2, + [0][1][2][0][RTW89_KCC][1][102] = 20, + [0][1][2][0][RTW89_KCC][0][102] = 127, + [0][1][2][0][RTW89_ACMA][1][102] = 127, + [0][1][2][0][RTW89_ACMA][0][102] = 127, + [0][1][2][0][RTW89_CHILE][1][102] = -2, + [0][1][2][0][RTW89_QATAR][1][102] = 127, + [0][1][2][0][RTW89_QATAR][0][102] = 127, + [0][1][2][0][RTW89_UK][1][102] = 127, + [0][1][2][0][RTW89_UK][0][102] = 127, + [0][1][2][0][RTW89_FCC][1][104] = -2, + [0][1][2][0][RTW89_FCC][2][104] = 127, + [0][1][2][0][RTW89_ETSI][1][104] = 127, + [0][1][2][0][RTW89_ETSI][0][104] = 127, + [0][1][2][0][RTW89_MKK][1][104] = 127, + [0][1][2][0][RTW89_MKK][0][104] = 127, + [0][1][2][0][RTW89_IC][1][104] = -2, + [0][1][2][0][RTW89_KCC][1][104] = 20, + [0][1][2][0][RTW89_KCC][0][104] = 127, + [0][1][2][0][RTW89_ACMA][1][104] = 127, + [0][1][2][0][RTW89_ACMA][0][104] = 127, + [0][1][2][0][RTW89_CHILE][1][104] = -2, + [0][1][2][0][RTW89_QATAR][1][104] = 127, + [0][1][2][0][RTW89_QATAR][0][104] = 127, + [0][1][2][0][RTW89_UK][1][104] = 127, + [0][1][2][0][RTW89_UK][0][104] = 127, + [0][1][2][0][RTW89_FCC][1][105] = -2, + [0][1][2][0][RTW89_FCC][2][105] = 127, + [0][1][2][0][RTW89_ETSI][1][105] = 127, + [0][1][2][0][RTW89_ETSI][0][105] = 127, + [0][1][2][0][RTW89_MKK][1][105] = 127, + [0][1][2][0][RTW89_MKK][0][105] = 127, + [0][1][2][0][RTW89_IC][1][105] = -2, + [0][1][2][0][RTW89_KCC][1][105] = 20, + [0][1][2][0][RTW89_KCC][0][105] = 127, + [0][1][2][0][RTW89_ACMA][1][105] = 127, + [0][1][2][0][RTW89_ACMA][0][105] = 127, + [0][1][2][0][RTW89_CHILE][1][105] = -2, + [0][1][2][0][RTW89_QATAR][1][105] = 127, + [0][1][2][0][RTW89_QATAR][0][105] = 127, + [0][1][2][0][RTW89_UK][1][105] = 127, + [0][1][2][0][RTW89_UK][0][105] = 127, + [0][1][2][0][RTW89_FCC][1][107] = 1, + [0][1][2][0][RTW89_FCC][2][107] = 127, + [0][1][2][0][RTW89_ETSI][1][107] = 127, + [0][1][2][0][RTW89_ETSI][0][107] = 127, + [0][1][2][0][RTW89_MKK][1][107] = 127, + [0][1][2][0][RTW89_MKK][0][107] = 127, + [0][1][2][0][RTW89_IC][1][107] = 1, + [0][1][2][0][RTW89_KCC][1][107] = 20, + [0][1][2][0][RTW89_KCC][0][107] = 127, + [0][1][2][0][RTW89_ACMA][1][107] = 127, + [0][1][2][0][RTW89_ACMA][0][107] = 127, + [0][1][2][0][RTW89_CHILE][1][107] = 1, + [0][1][2][0][RTW89_QATAR][1][107] = 127, + [0][1][2][0][RTW89_QATAR][0][107] = 127, + [0][1][2][0][RTW89_UK][1][107] = 127, + [0][1][2][0][RTW89_UK][0][107] = 127, + [0][1][2][0][RTW89_FCC][1][109] = 1, + [0][1][2][0][RTW89_FCC][2][109] = 127, + [0][1][2][0][RTW89_ETSI][1][109] = 127, + [0][1][2][0][RTW89_ETSI][0][109] = 127, + [0][1][2][0][RTW89_MKK][1][109] = 127, + [0][1][2][0][RTW89_MKK][0][109] = 127, + [0][1][2][0][RTW89_IC][1][109] = 1, + [0][1][2][0][RTW89_KCC][1][109] = 20, + [0][1][2][0][RTW89_KCC][0][109] = 127, + [0][1][2][0][RTW89_ACMA][1][109] = 127, + [0][1][2][0][RTW89_ACMA][0][109] = 127, + [0][1][2][0][RTW89_CHILE][1][109] = 1, + [0][1][2][0][RTW89_QATAR][1][109] = 127, + [0][1][2][0][RTW89_QATAR][0][109] = 127, + [0][1][2][0][RTW89_UK][1][109] = 127, + [0][1][2][0][RTW89_UK][0][109] = 127, + [0][1][2][0][RTW89_FCC][1][111] = 127, + [0][1][2][0][RTW89_FCC][2][111] = 127, + [0][1][2][0][RTW89_ETSI][1][111] = 127, + [0][1][2][0][RTW89_ETSI][0][111] = 127, + [0][1][2][0][RTW89_MKK][1][111] = 127, + [0][1][2][0][RTW89_MKK][0][111] = 127, + [0][1][2][0][RTW89_IC][1][111] = 127, + [0][1][2][0][RTW89_KCC][1][111] = 127, + [0][1][2][0][RTW89_KCC][0][111] = 127, + [0][1][2][0][RTW89_ACMA][1][111] = 127, + [0][1][2][0][RTW89_ACMA][0][111] = 127, + [0][1][2][0][RTW89_CHILE][1][111] = 127, + [0][1][2][0][RTW89_QATAR][1][111] = 127, + [0][1][2][0][RTW89_QATAR][0][111] = 127, + [0][1][2][0][RTW89_UK][1][111] = 127, + [0][1][2][0][RTW89_UK][0][111] = 127, + [0][1][2][0][RTW89_FCC][1][113] = 127, + [0][1][2][0][RTW89_FCC][2][113] = 127, + [0][1][2][0][RTW89_ETSI][1][113] = 127, + [0][1][2][0][RTW89_ETSI][0][113] = 127, + [0][1][2][0][RTW89_MKK][1][113] = 127, + [0][1][2][0][RTW89_MKK][0][113] = 127, + [0][1][2][0][RTW89_IC][1][113] = 127, + [0][1][2][0][RTW89_KCC][1][113] = 127, + [0][1][2][0][RTW89_KCC][0][113] = 127, + [0][1][2][0][RTW89_ACMA][1][113] = 127, + [0][1][2][0][RTW89_ACMA][0][113] = 127, + [0][1][2][0][RTW89_CHILE][1][113] = 127, + [0][1][2][0][RTW89_QATAR][1][113] = 127, + [0][1][2][0][RTW89_QATAR][0][113] = 127, + [0][1][2][0][RTW89_UK][1][113] = 127, + [0][1][2][0][RTW89_UK][0][113] = 127, + [0][1][2][0][RTW89_FCC][1][115] = 127, + [0][1][2][0][RTW89_FCC][2][115] = 127, + [0][1][2][0][RTW89_ETSI][1][115] = 127, + [0][1][2][0][RTW89_ETSI][0][115] = 127, + [0][1][2][0][RTW89_MKK][1][115] = 127, + [0][1][2][0][RTW89_MKK][0][115] = 127, + [0][1][2][0][RTW89_IC][1][115] = 127, + [0][1][2][0][RTW89_KCC][1][115] = 127, + [0][1][2][0][RTW89_KCC][0][115] = 127, + [0][1][2][0][RTW89_ACMA][1][115] = 127, + [0][1][2][0][RTW89_ACMA][0][115] = 127, + [0][1][2][0][RTW89_CHILE][1][115] = 127, + [0][1][2][0][RTW89_QATAR][1][115] = 127, + [0][1][2][0][RTW89_QATAR][0][115] = 127, + [0][1][2][0][RTW89_UK][1][115] = 127, + [0][1][2][0][RTW89_UK][0][115] = 127, + [0][1][2][0][RTW89_FCC][1][117] = 127, + [0][1][2][0][RTW89_FCC][2][117] = 127, + [0][1][2][0][RTW89_ETSI][1][117] = 127, + [0][1][2][0][RTW89_ETSI][0][117] = 127, + [0][1][2][0][RTW89_MKK][1][117] = 127, + [0][1][2][0][RTW89_MKK][0][117] = 127, + [0][1][2][0][RTW89_IC][1][117] = 127, + [0][1][2][0][RTW89_KCC][1][117] = 127, + [0][1][2][0][RTW89_KCC][0][117] = 127, + [0][1][2][0][RTW89_ACMA][1][117] = 127, + [0][1][2][0][RTW89_ACMA][0][117] = 127, + [0][1][2][0][RTW89_CHILE][1][117] = 127, + [0][1][2][0][RTW89_QATAR][1][117] = 127, + [0][1][2][0][RTW89_QATAR][0][117] = 127, + [0][1][2][0][RTW89_UK][1][117] = 127, + [0][1][2][0][RTW89_UK][0][117] = 127, + [0][1][2][0][RTW89_FCC][1][119] = 127, + [0][1][2][0][RTW89_FCC][2][119] = 127, + [0][1][2][0][RTW89_ETSI][1][119] = 127, + [0][1][2][0][RTW89_ETSI][0][119] = 127, + [0][1][2][0][RTW89_MKK][1][119] = 127, + [0][1][2][0][RTW89_MKK][0][119] = 127, + [0][1][2][0][RTW89_IC][1][119] = 127, + [0][1][2][0][RTW89_KCC][1][119] = 127, + [0][1][2][0][RTW89_KCC][0][119] = 127, + [0][1][2][0][RTW89_ACMA][1][119] = 127, + [0][1][2][0][RTW89_ACMA][0][119] = 127, + [0][1][2][0][RTW89_CHILE][1][119] = 127, + [0][1][2][0][RTW89_QATAR][1][119] = 127, + [0][1][2][0][RTW89_QATAR][0][119] = 127, + [0][1][2][0][RTW89_UK][1][119] = 127, + [0][1][2][0][RTW89_UK][0][119] = 127, + [0][1][2][1][RTW89_FCC][1][0] = -2, + [0][1][2][1][RTW89_FCC][2][0] = 54, + [0][1][2][1][RTW89_ETSI][1][0] = 42, + [0][1][2][1][RTW89_ETSI][0][0] = 6, + [0][1][2][1][RTW89_MKK][1][0] = 56, + [0][1][2][1][RTW89_MKK][0][0] = 16, + [0][1][2][1][RTW89_IC][1][0] = -2, + [0][1][2][1][RTW89_KCC][1][0] = 12, + [0][1][2][1][RTW89_KCC][0][0] = 10, + [0][1][2][1][RTW89_ACMA][1][0] = 42, + [0][1][2][1][RTW89_ACMA][0][0] = 6, + [0][1][2][1][RTW89_CHILE][1][0] = -2, + [0][1][2][1][RTW89_QATAR][1][0] = 42, + [0][1][2][1][RTW89_QATAR][0][0] = 6, + [0][1][2][1][RTW89_UK][1][0] = 42, + [0][1][2][1][RTW89_UK][0][0] = 6, + [0][1][2][1][RTW89_FCC][1][2] = -4, + [0][1][2][1][RTW89_FCC][2][2] = 54, + [0][1][2][1][RTW89_ETSI][1][2] = 42, + [0][1][2][1][RTW89_ETSI][0][2] = 6, + [0][1][2][1][RTW89_MKK][1][2] = 54, + [0][1][2][1][RTW89_MKK][0][2] = 16, + [0][1][2][1][RTW89_IC][1][2] = -4, + [0][1][2][1][RTW89_KCC][1][2] = 12, + [0][1][2][1][RTW89_KCC][0][2] = 12, + [0][1][2][1][RTW89_ACMA][1][2] = 42, + [0][1][2][1][RTW89_ACMA][0][2] = 6, + [0][1][2][1][RTW89_CHILE][1][2] = -4, + [0][1][2][1][RTW89_QATAR][1][2] = 42, + [0][1][2][1][RTW89_QATAR][0][2] = 6, + [0][1][2][1][RTW89_UK][1][2] = 42, + [0][1][2][1][RTW89_UK][0][2] = 6, + [0][1][2][1][RTW89_FCC][1][4] = -4, + [0][1][2][1][RTW89_FCC][2][4] = 54, + [0][1][2][1][RTW89_ETSI][1][4] = 42, + [0][1][2][1][RTW89_ETSI][0][4] = 6, + [0][1][2][1][RTW89_MKK][1][4] = 54, + [0][1][2][1][RTW89_MKK][0][4] = 16, + [0][1][2][1][RTW89_IC][1][4] = -4, + [0][1][2][1][RTW89_KCC][1][4] = 12, + [0][1][2][1][RTW89_KCC][0][4] = 12, + [0][1][2][1][RTW89_ACMA][1][4] = 42, + [0][1][2][1][RTW89_ACMA][0][4] = 6, + [0][1][2][1][RTW89_CHILE][1][4] = -4, + [0][1][2][1][RTW89_QATAR][1][4] = 42, + [0][1][2][1][RTW89_QATAR][0][4] = 6, + [0][1][2][1][RTW89_UK][1][4] = 42, + [0][1][2][1][RTW89_UK][0][4] = 6, + [0][1][2][1][RTW89_FCC][1][6] = -4, + [0][1][2][1][RTW89_FCC][2][6] = 54, + [0][1][2][1][RTW89_ETSI][1][6] = 42, + [0][1][2][1][RTW89_ETSI][0][6] = 6, + [0][1][2][1][RTW89_MKK][1][6] = 54, + [0][1][2][1][RTW89_MKK][0][6] = 16, + [0][1][2][1][RTW89_IC][1][6] = -4, + [0][1][2][1][RTW89_KCC][1][6] = 12, + [0][1][2][1][RTW89_KCC][0][6] = 12, + [0][1][2][1][RTW89_ACMA][1][6] = 42, + [0][1][2][1][RTW89_ACMA][0][6] = 6, + [0][1][2][1][RTW89_CHILE][1][6] = -4, + [0][1][2][1][RTW89_QATAR][1][6] = 42, + [0][1][2][1][RTW89_QATAR][0][6] = 6, + [0][1][2][1][RTW89_UK][1][6] = 42, + [0][1][2][1][RTW89_UK][0][6] = 6, + [0][1][2][1][RTW89_FCC][1][8] = -4, + [0][1][2][1][RTW89_FCC][2][8] = 54, + [0][1][2][1][RTW89_ETSI][1][8] = 42, + [0][1][2][1][RTW89_ETSI][0][8] = 6, + [0][1][2][1][RTW89_MKK][1][8] = 54, + [0][1][2][1][RTW89_MKK][0][8] = 16, + [0][1][2][1][RTW89_IC][1][8] = -4, + [0][1][2][1][RTW89_KCC][1][8] = 12, + [0][1][2][1][RTW89_KCC][0][8] = 12, + [0][1][2][1][RTW89_ACMA][1][8] = 42, + [0][1][2][1][RTW89_ACMA][0][8] = 6, + [0][1][2][1][RTW89_CHILE][1][8] = -4, + [0][1][2][1][RTW89_QATAR][1][8] = 42, + [0][1][2][1][RTW89_QATAR][0][8] = 6, + [0][1][2][1][RTW89_UK][1][8] = 42, + [0][1][2][1][RTW89_UK][0][8] = 6, + [0][1][2][1][RTW89_FCC][1][10] = -4, + [0][1][2][1][RTW89_FCC][2][10] = 54, + [0][1][2][1][RTW89_ETSI][1][10] = 42, + [0][1][2][1][RTW89_ETSI][0][10] = 6, + [0][1][2][1][RTW89_MKK][1][10] = 54, + [0][1][2][1][RTW89_MKK][0][10] = 16, + [0][1][2][1][RTW89_IC][1][10] = -4, + [0][1][2][1][RTW89_KCC][1][10] = 12, + [0][1][2][1][RTW89_KCC][0][10] = 12, + [0][1][2][1][RTW89_ACMA][1][10] = 42, + [0][1][2][1][RTW89_ACMA][0][10] = 6, + [0][1][2][1][RTW89_CHILE][1][10] = -4, + [0][1][2][1][RTW89_QATAR][1][10] = 42, + [0][1][2][1][RTW89_QATAR][0][10] = 6, + [0][1][2][1][RTW89_UK][1][10] = 42, + [0][1][2][1][RTW89_UK][0][10] = 6, + [0][1][2][1][RTW89_FCC][1][12] = -4, + [0][1][2][1][RTW89_FCC][2][12] = 54, + [0][1][2][1][RTW89_ETSI][1][12] = 42, + [0][1][2][1][RTW89_ETSI][0][12] = 6, + [0][1][2][1][RTW89_MKK][1][12] = 54, + [0][1][2][1][RTW89_MKK][0][12] = 16, + [0][1][2][1][RTW89_IC][1][12] = -4, + [0][1][2][1][RTW89_KCC][1][12] = 12, + [0][1][2][1][RTW89_KCC][0][12] = 12, + [0][1][2][1][RTW89_ACMA][1][12] = 42, + [0][1][2][1][RTW89_ACMA][0][12] = 6, + [0][1][2][1][RTW89_CHILE][1][12] = -4, + [0][1][2][1][RTW89_QATAR][1][12] = 42, + [0][1][2][1][RTW89_QATAR][0][12] = 6, + [0][1][2][1][RTW89_UK][1][12] = 42, + [0][1][2][1][RTW89_UK][0][12] = 6, + [0][1][2][1][RTW89_FCC][1][14] = -4, + [0][1][2][1][RTW89_FCC][2][14] = 54, + [0][1][2][1][RTW89_ETSI][1][14] = 42, + [0][1][2][1][RTW89_ETSI][0][14] = 6, + [0][1][2][1][RTW89_MKK][1][14] = 54, + [0][1][2][1][RTW89_MKK][0][14] = 16, + [0][1][2][1][RTW89_IC][1][14] = -4, + [0][1][2][1][RTW89_KCC][1][14] = 12, + [0][1][2][1][RTW89_KCC][0][14] = 12, + [0][1][2][1][RTW89_ACMA][1][14] = 42, + [0][1][2][1][RTW89_ACMA][0][14] = 6, + [0][1][2][1][RTW89_CHILE][1][14] = -4, + [0][1][2][1][RTW89_QATAR][1][14] = 42, + [0][1][2][1][RTW89_QATAR][0][14] = 6, + [0][1][2][1][RTW89_UK][1][14] = 42, + [0][1][2][1][RTW89_UK][0][14] = 6, + [0][1][2][1][RTW89_FCC][1][15] = -4, + [0][1][2][1][RTW89_FCC][2][15] = 54, + [0][1][2][1][RTW89_ETSI][1][15] = 42, + [0][1][2][1][RTW89_ETSI][0][15] = 6, + [0][1][2][1][RTW89_MKK][1][15] = 54, + [0][1][2][1][RTW89_MKK][0][15] = 16, + [0][1][2][1][RTW89_IC][1][15] = -4, + [0][1][2][1][RTW89_KCC][1][15] = 12, + [0][1][2][1][RTW89_KCC][0][15] = 12, + [0][1][2][1][RTW89_ACMA][1][15] = 42, + [0][1][2][1][RTW89_ACMA][0][15] = 6, + [0][1][2][1][RTW89_CHILE][1][15] = -4, + [0][1][2][1][RTW89_QATAR][1][15] = 42, + [0][1][2][1][RTW89_QATAR][0][15] = 6, + [0][1][2][1][RTW89_UK][1][15] = 42, + [0][1][2][1][RTW89_UK][0][15] = 6, + [0][1][2][1][RTW89_FCC][1][17] = -4, + [0][1][2][1][RTW89_FCC][2][17] = 54, + [0][1][2][1][RTW89_ETSI][1][17] = 42, + [0][1][2][1][RTW89_ETSI][0][17] = 6, + [0][1][2][1][RTW89_MKK][1][17] = 54, + [0][1][2][1][RTW89_MKK][0][17] = 16, + [0][1][2][1][RTW89_IC][1][17] = -4, + [0][1][2][1][RTW89_KCC][1][17] = 12, + [0][1][2][1][RTW89_KCC][0][17] = 12, + [0][1][2][1][RTW89_ACMA][1][17] = 42, + [0][1][2][1][RTW89_ACMA][0][17] = 6, + [0][1][2][1][RTW89_CHILE][1][17] = -4, + [0][1][2][1][RTW89_QATAR][1][17] = 42, + [0][1][2][1][RTW89_QATAR][0][17] = 6, + [0][1][2][1][RTW89_UK][1][17] = 42, + [0][1][2][1][RTW89_UK][0][17] = 6, + [0][1][2][1][RTW89_FCC][1][19] = -4, + [0][1][2][1][RTW89_FCC][2][19] = 54, + [0][1][2][1][RTW89_ETSI][1][19] = 42, + [0][1][2][1][RTW89_ETSI][0][19] = 6, + [0][1][2][1][RTW89_MKK][1][19] = 54, + [0][1][2][1][RTW89_MKK][0][19] = 16, + [0][1][2][1][RTW89_IC][1][19] = -4, + [0][1][2][1][RTW89_KCC][1][19] = 12, + [0][1][2][1][RTW89_KCC][0][19] = 12, + [0][1][2][1][RTW89_ACMA][1][19] = 42, + [0][1][2][1][RTW89_ACMA][0][19] = 6, + [0][1][2][1][RTW89_CHILE][1][19] = -4, + [0][1][2][1][RTW89_QATAR][1][19] = 42, + [0][1][2][1][RTW89_QATAR][0][19] = 6, + [0][1][2][1][RTW89_UK][1][19] = 42, + [0][1][2][1][RTW89_UK][0][19] = 6, + [0][1][2][1][RTW89_FCC][1][21] = -4, + [0][1][2][1][RTW89_FCC][2][21] = 54, + [0][1][2][1][RTW89_ETSI][1][21] = 42, + [0][1][2][1][RTW89_ETSI][0][21] = 6, + [0][1][2][1][RTW89_MKK][1][21] = 54, + [0][1][2][1][RTW89_MKK][0][21] = 16, + [0][1][2][1][RTW89_IC][1][21] = -4, + [0][1][2][1][RTW89_KCC][1][21] = 12, + [0][1][2][1][RTW89_KCC][0][21] = 12, + [0][1][2][1][RTW89_ACMA][1][21] = 42, + [0][1][2][1][RTW89_ACMA][0][21] = 6, + [0][1][2][1][RTW89_CHILE][1][21] = -4, + [0][1][2][1][RTW89_QATAR][1][21] = 42, + [0][1][2][1][RTW89_QATAR][0][21] = 6, + [0][1][2][1][RTW89_UK][1][21] = 42, + [0][1][2][1][RTW89_UK][0][21] = 6, + [0][1][2][1][RTW89_FCC][1][23] = -4, + [0][1][2][1][RTW89_FCC][2][23] = 68, + [0][1][2][1][RTW89_ETSI][1][23] = 42, + [0][1][2][1][RTW89_ETSI][0][23] = 6, + [0][1][2][1][RTW89_MKK][1][23] = 54, + [0][1][2][1][RTW89_MKK][0][23] = 16, + [0][1][2][1][RTW89_IC][1][23] = -4, + [0][1][2][1][RTW89_KCC][1][23] = 12, + [0][1][2][1][RTW89_KCC][0][23] = 10, + [0][1][2][1][RTW89_ACMA][1][23] = 42, + [0][1][2][1][RTW89_ACMA][0][23] = 6, + [0][1][2][1][RTW89_CHILE][1][23] = -4, + [0][1][2][1][RTW89_QATAR][1][23] = 42, + [0][1][2][1][RTW89_QATAR][0][23] = 6, + [0][1][2][1][RTW89_UK][1][23] = 42, + [0][1][2][1][RTW89_UK][0][23] = 6, + [0][1][2][1][RTW89_FCC][1][25] = -4, + [0][1][2][1][RTW89_FCC][2][25] = 68, + [0][1][2][1][RTW89_ETSI][1][25] = 42, + [0][1][2][1][RTW89_ETSI][0][25] = 6, + [0][1][2][1][RTW89_MKK][1][25] = 54, + [0][1][2][1][RTW89_MKK][0][25] = 16, + [0][1][2][1][RTW89_IC][1][25] = -4, + [0][1][2][1][RTW89_KCC][1][25] = 12, + [0][1][2][1][RTW89_KCC][0][25] = 14, + [0][1][2][1][RTW89_ACMA][1][25] = 42, + [0][1][2][1][RTW89_ACMA][0][25] = 6, + [0][1][2][1][RTW89_CHILE][1][25] = -4, + [0][1][2][1][RTW89_QATAR][1][25] = 42, + [0][1][2][1][RTW89_QATAR][0][25] = 6, + [0][1][2][1][RTW89_UK][1][25] = 42, + [0][1][2][1][RTW89_UK][0][25] = 6, + [0][1][2][1][RTW89_FCC][1][27] = -4, + [0][1][2][1][RTW89_FCC][2][27] = 68, + [0][1][2][1][RTW89_ETSI][1][27] = 42, + [0][1][2][1][RTW89_ETSI][0][27] = 6, + [0][1][2][1][RTW89_MKK][1][27] = 54, + [0][1][2][1][RTW89_MKK][0][27] = 16, + [0][1][2][1][RTW89_IC][1][27] = -4, + [0][1][2][1][RTW89_KCC][1][27] = 12, + [0][1][2][1][RTW89_KCC][0][27] = 14, + [0][1][2][1][RTW89_ACMA][1][27] = 42, + [0][1][2][1][RTW89_ACMA][0][27] = 6, + [0][1][2][1][RTW89_CHILE][1][27] = -4, + [0][1][2][1][RTW89_QATAR][1][27] = 42, + [0][1][2][1][RTW89_QATAR][0][27] = 6, + [0][1][2][1][RTW89_UK][1][27] = 42, + [0][1][2][1][RTW89_UK][0][27] = 6, + [0][1][2][1][RTW89_FCC][1][29] = -4, + [0][1][2][1][RTW89_FCC][2][29] = 68, + [0][1][2][1][RTW89_ETSI][1][29] = 42, + [0][1][2][1][RTW89_ETSI][0][29] = 6, + [0][1][2][1][RTW89_MKK][1][29] = 54, + [0][1][2][1][RTW89_MKK][0][29] = 16, + [0][1][2][1][RTW89_IC][1][29] = -4, + [0][1][2][1][RTW89_KCC][1][29] = 12, + [0][1][2][1][RTW89_KCC][0][29] = 14, + [0][1][2][1][RTW89_ACMA][1][29] = 42, + [0][1][2][1][RTW89_ACMA][0][29] = 6, + [0][1][2][1][RTW89_CHILE][1][29] = -4, + [0][1][2][1][RTW89_QATAR][1][29] = 42, + [0][1][2][1][RTW89_QATAR][0][29] = 6, + [0][1][2][1][RTW89_UK][1][29] = 42, + [0][1][2][1][RTW89_UK][0][29] = 6, + [0][1][2][1][RTW89_FCC][1][30] = -4, + [0][1][2][1][RTW89_FCC][2][30] = 68, + [0][1][2][1][RTW89_ETSI][1][30] = 42, + [0][1][2][1][RTW89_ETSI][0][30] = 6, + [0][1][2][1][RTW89_MKK][1][30] = 54, + [0][1][2][1][RTW89_MKK][0][30] = 16, + [0][1][2][1][RTW89_IC][1][30] = -4, + [0][1][2][1][RTW89_KCC][1][30] = 12, + [0][1][2][1][RTW89_KCC][0][30] = 14, + [0][1][2][1][RTW89_ACMA][1][30] = 42, + [0][1][2][1][RTW89_ACMA][0][30] = 6, + [0][1][2][1][RTW89_CHILE][1][30] = -4, + [0][1][2][1][RTW89_QATAR][1][30] = 42, + [0][1][2][1][RTW89_QATAR][0][30] = 6, + [0][1][2][1][RTW89_UK][1][30] = 42, + [0][1][2][1][RTW89_UK][0][30] = 6, + [0][1][2][1][RTW89_FCC][1][32] = -4, + [0][1][2][1][RTW89_FCC][2][32] = 68, + [0][1][2][1][RTW89_ETSI][1][32] = 42, + [0][1][2][1][RTW89_ETSI][0][32] = 6, + [0][1][2][1][RTW89_MKK][1][32] = 54, + [0][1][2][1][RTW89_MKK][0][32] = 16, + [0][1][2][1][RTW89_IC][1][32] = -4, + [0][1][2][1][RTW89_KCC][1][32] = 12, + [0][1][2][1][RTW89_KCC][0][32] = 14, + [0][1][2][1][RTW89_ACMA][1][32] = 42, + [0][1][2][1][RTW89_ACMA][0][32] = 6, + [0][1][2][1][RTW89_CHILE][1][32] = -4, + [0][1][2][1][RTW89_QATAR][1][32] = 42, + [0][1][2][1][RTW89_QATAR][0][32] = 6, + [0][1][2][1][RTW89_UK][1][32] = 42, + [0][1][2][1][RTW89_UK][0][32] = 6, + [0][1][2][1][RTW89_FCC][1][34] = -4, + [0][1][2][1][RTW89_FCC][2][34] = 68, + [0][1][2][1][RTW89_ETSI][1][34] = 42, + [0][1][2][1][RTW89_ETSI][0][34] = 6, + [0][1][2][1][RTW89_MKK][1][34] = 54, + [0][1][2][1][RTW89_MKK][0][34] = 16, + [0][1][2][1][RTW89_IC][1][34] = -4, + [0][1][2][1][RTW89_KCC][1][34] = 12, + [0][1][2][1][RTW89_KCC][0][34] = 14, + [0][1][2][1][RTW89_ACMA][1][34] = 42, + [0][1][2][1][RTW89_ACMA][0][34] = 6, + [0][1][2][1][RTW89_CHILE][1][34] = -4, + [0][1][2][1][RTW89_QATAR][1][34] = 42, + [0][1][2][1][RTW89_QATAR][0][34] = 6, + [0][1][2][1][RTW89_UK][1][34] = 42, + [0][1][2][1][RTW89_UK][0][34] = 6, + [0][1][2][1][RTW89_FCC][1][36] = -4, + [0][1][2][1][RTW89_FCC][2][36] = 68, + [0][1][2][1][RTW89_ETSI][1][36] = 42, + [0][1][2][1][RTW89_ETSI][0][36] = 6, + [0][1][2][1][RTW89_MKK][1][36] = 54, + [0][1][2][1][RTW89_MKK][0][36] = 16, + [0][1][2][1][RTW89_IC][1][36] = -4, + [0][1][2][1][RTW89_KCC][1][36] = 12, + [0][1][2][1][RTW89_KCC][0][36] = 14, + [0][1][2][1][RTW89_ACMA][1][36] = 42, + [0][1][2][1][RTW89_ACMA][0][36] = 6, + [0][1][2][1][RTW89_CHILE][1][36] = -4, + [0][1][2][1][RTW89_QATAR][1][36] = 42, + [0][1][2][1][RTW89_QATAR][0][36] = 6, + [0][1][2][1][RTW89_UK][1][36] = 42, + [0][1][2][1][RTW89_UK][0][36] = 6, + [0][1][2][1][RTW89_FCC][1][38] = -4, + [0][1][2][1][RTW89_FCC][2][38] = 68, + [0][1][2][1][RTW89_ETSI][1][38] = 42, + [0][1][2][1][RTW89_ETSI][0][38] = 6, + [0][1][2][1][RTW89_MKK][1][38] = 54, + [0][1][2][1][RTW89_MKK][0][38] = 16, + [0][1][2][1][RTW89_IC][1][38] = -4, + [0][1][2][1][RTW89_KCC][1][38] = 12, + [0][1][2][1][RTW89_KCC][0][38] = 14, + [0][1][2][1][RTW89_ACMA][1][38] = 42, + [0][1][2][1][RTW89_ACMA][0][38] = 6, + [0][1][2][1][RTW89_CHILE][1][38] = -4, + [0][1][2][1][RTW89_QATAR][1][38] = 42, + [0][1][2][1][RTW89_QATAR][0][38] = 6, + [0][1][2][1][RTW89_UK][1][38] = 42, + [0][1][2][1][RTW89_UK][0][38] = 6, + [0][1][2][1][RTW89_FCC][1][40] = -4, + [0][1][2][1][RTW89_FCC][2][40] = 68, + [0][1][2][1][RTW89_ETSI][1][40] = 42, + [0][1][2][1][RTW89_ETSI][0][40] = 6, + [0][1][2][1][RTW89_MKK][1][40] = 54, + [0][1][2][1][RTW89_MKK][0][40] = 16, + [0][1][2][1][RTW89_IC][1][40] = -4, + [0][1][2][1][RTW89_KCC][1][40] = 12, + [0][1][2][1][RTW89_KCC][0][40] = 14, + [0][1][2][1][RTW89_ACMA][1][40] = 42, + [0][1][2][1][RTW89_ACMA][0][40] = 6, + [0][1][2][1][RTW89_CHILE][1][40] = -4, + [0][1][2][1][RTW89_QATAR][1][40] = 42, + [0][1][2][1][RTW89_QATAR][0][40] = 6, + [0][1][2][1][RTW89_UK][1][40] = 42, + [0][1][2][1][RTW89_UK][0][40] = 6, + [0][1][2][1][RTW89_FCC][1][42] = -4, + [0][1][2][1][RTW89_FCC][2][42] = 68, + [0][1][2][1][RTW89_ETSI][1][42] = 42, + [0][1][2][1][RTW89_ETSI][0][42] = 6, + [0][1][2][1][RTW89_MKK][1][42] = 54, + [0][1][2][1][RTW89_MKK][0][42] = 16, + [0][1][2][1][RTW89_IC][1][42] = -4, + [0][1][2][1][RTW89_KCC][1][42] = 12, + [0][1][2][1][RTW89_KCC][0][42] = 14, + [0][1][2][1][RTW89_ACMA][1][42] = 42, + [0][1][2][1][RTW89_ACMA][0][42] = 6, + [0][1][2][1][RTW89_CHILE][1][42] = -4, + [0][1][2][1][RTW89_QATAR][1][42] = 42, + [0][1][2][1][RTW89_QATAR][0][42] = 6, + [0][1][2][1][RTW89_UK][1][42] = 42, + [0][1][2][1][RTW89_UK][0][42] = 6, + [0][1][2][1][RTW89_FCC][1][44] = -2, + [0][1][2][1][RTW89_FCC][2][44] = 68, + [0][1][2][1][RTW89_ETSI][1][44] = 42, + [0][1][2][1][RTW89_ETSI][0][44] = 6, + [0][1][2][1][RTW89_MKK][1][44] = 34, + [0][1][2][1][RTW89_MKK][0][44] = 16, + [0][1][2][1][RTW89_IC][1][44] = -2, + [0][1][2][1][RTW89_KCC][1][44] = 12, + [0][1][2][1][RTW89_KCC][0][44] = 12, + [0][1][2][1][RTW89_ACMA][1][44] = 42, + [0][1][2][1][RTW89_ACMA][0][44] = 6, + [0][1][2][1][RTW89_CHILE][1][44] = -2, + [0][1][2][1][RTW89_QATAR][1][44] = 42, + [0][1][2][1][RTW89_QATAR][0][44] = 6, + [0][1][2][1][RTW89_UK][1][44] = 42, + [0][1][2][1][RTW89_UK][0][44] = 6, + [0][1][2][1][RTW89_FCC][1][45] = -2, + [0][1][2][1][RTW89_FCC][2][45] = 127, + [0][1][2][1][RTW89_ETSI][1][45] = 127, + [0][1][2][1][RTW89_ETSI][0][45] = 127, + [0][1][2][1][RTW89_MKK][1][45] = 127, + [0][1][2][1][RTW89_MKK][0][45] = 127, + [0][1][2][1][RTW89_IC][1][45] = -2, + [0][1][2][1][RTW89_KCC][1][45] = 12, + [0][1][2][1][RTW89_KCC][0][45] = 127, + [0][1][2][1][RTW89_ACMA][1][45] = 127, + [0][1][2][1][RTW89_ACMA][0][45] = 127, + [0][1][2][1][RTW89_CHILE][1][45] = -2, + [0][1][2][1][RTW89_QATAR][1][45] = 127, + [0][1][2][1][RTW89_QATAR][0][45] = 127, + [0][1][2][1][RTW89_UK][1][45] = 127, + [0][1][2][1][RTW89_UK][0][45] = 127, + [0][1][2][1][RTW89_FCC][1][47] = -2, + [0][1][2][1][RTW89_FCC][2][47] = 127, + [0][1][2][1][RTW89_ETSI][1][47] = 127, + [0][1][2][1][RTW89_ETSI][0][47] = 127, + [0][1][2][1][RTW89_MKK][1][47] = 127, + [0][1][2][1][RTW89_MKK][0][47] = 127, + [0][1][2][1][RTW89_IC][1][47] = -2, + [0][1][2][1][RTW89_KCC][1][47] = 12, + [0][1][2][1][RTW89_KCC][0][47] = 127, + [0][1][2][1][RTW89_ACMA][1][47] = 127, + [0][1][2][1][RTW89_ACMA][0][47] = 127, + [0][1][2][1][RTW89_CHILE][1][47] = -2, + [0][1][2][1][RTW89_QATAR][1][47] = 127, + [0][1][2][1][RTW89_QATAR][0][47] = 127, + [0][1][2][1][RTW89_UK][1][47] = 127, + [0][1][2][1][RTW89_UK][0][47] = 127, + [0][1][2][1][RTW89_FCC][1][49] = -2, + [0][1][2][1][RTW89_FCC][2][49] = 127, + [0][1][2][1][RTW89_ETSI][1][49] = 127, + [0][1][2][1][RTW89_ETSI][0][49] = 127, + [0][1][2][1][RTW89_MKK][1][49] = 127, + [0][1][2][1][RTW89_MKK][0][49] = 127, + [0][1][2][1][RTW89_IC][1][49] = -2, + [0][1][2][1][RTW89_KCC][1][49] = 12, + [0][1][2][1][RTW89_KCC][0][49] = 127, + [0][1][2][1][RTW89_ACMA][1][49] = 127, + [0][1][2][1][RTW89_ACMA][0][49] = 127, + [0][1][2][1][RTW89_CHILE][1][49] = -2, + [0][1][2][1][RTW89_QATAR][1][49] = 127, + [0][1][2][1][RTW89_QATAR][0][49] = 127, + [0][1][2][1][RTW89_UK][1][49] = 127, + [0][1][2][1][RTW89_UK][0][49] = 127, + [0][1][2][1][RTW89_FCC][1][51] = -2, + [0][1][2][1][RTW89_FCC][2][51] = 127, + [0][1][2][1][RTW89_ETSI][1][51] = 127, + [0][1][2][1][RTW89_ETSI][0][51] = 127, + [0][1][2][1][RTW89_MKK][1][51] = 127, + [0][1][2][1][RTW89_MKK][0][51] = 127, + [0][1][2][1][RTW89_IC][1][51] = -2, + [0][1][2][1][RTW89_KCC][1][51] = 12, + [0][1][2][1][RTW89_KCC][0][51] = 127, + [0][1][2][1][RTW89_ACMA][1][51] = 127, + [0][1][2][1][RTW89_ACMA][0][51] = 127, + [0][1][2][1][RTW89_CHILE][1][51] = -2, + [0][1][2][1][RTW89_QATAR][1][51] = 127, + [0][1][2][1][RTW89_QATAR][0][51] = 127, + [0][1][2][1][RTW89_UK][1][51] = 127, + [0][1][2][1][RTW89_UK][0][51] = 127, + [0][1][2][1][RTW89_FCC][1][53] = -2, + [0][1][2][1][RTW89_FCC][2][53] = 127, + [0][1][2][1][RTW89_ETSI][1][53] = 127, + [0][1][2][1][RTW89_ETSI][0][53] = 127, + [0][1][2][1][RTW89_MKK][1][53] = 127, + [0][1][2][1][RTW89_MKK][0][53] = 127, + [0][1][2][1][RTW89_IC][1][53] = -2, + [0][1][2][1][RTW89_KCC][1][53] = 12, + [0][1][2][1][RTW89_KCC][0][53] = 127, + [0][1][2][1][RTW89_ACMA][1][53] = 127, + [0][1][2][1][RTW89_ACMA][0][53] = 127, + [0][1][2][1][RTW89_CHILE][1][53] = -2, + [0][1][2][1][RTW89_QATAR][1][53] = 127, + [0][1][2][1][RTW89_QATAR][0][53] = 127, + [0][1][2][1][RTW89_UK][1][53] = 127, + [0][1][2][1][RTW89_UK][0][53] = 127, + [0][1][2][1][RTW89_FCC][1][55] = -2, + [0][1][2][1][RTW89_FCC][2][55] = 68, + [0][1][2][1][RTW89_ETSI][1][55] = 127, + [0][1][2][1][RTW89_ETSI][0][55] = 127, + [0][1][2][1][RTW89_MKK][1][55] = 127, + [0][1][2][1][RTW89_MKK][0][55] = 127, + [0][1][2][1][RTW89_IC][1][55] = -2, + [0][1][2][1][RTW89_KCC][1][55] = 12, + [0][1][2][1][RTW89_KCC][0][55] = 127, + [0][1][2][1][RTW89_ACMA][1][55] = 127, + [0][1][2][1][RTW89_ACMA][0][55] = 127, + [0][1][2][1][RTW89_CHILE][1][55] = -2, + [0][1][2][1][RTW89_QATAR][1][55] = 127, + [0][1][2][1][RTW89_QATAR][0][55] = 127, + [0][1][2][1][RTW89_UK][1][55] = 127, + [0][1][2][1][RTW89_UK][0][55] = 127, + [0][1][2][1][RTW89_FCC][1][57] = -2, + [0][1][2][1][RTW89_FCC][2][57] = 68, + [0][1][2][1][RTW89_ETSI][1][57] = 127, + [0][1][2][1][RTW89_ETSI][0][57] = 127, + [0][1][2][1][RTW89_MKK][1][57] = 127, + [0][1][2][1][RTW89_MKK][0][57] = 127, + [0][1][2][1][RTW89_IC][1][57] = -2, + [0][1][2][1][RTW89_KCC][1][57] = 12, + [0][1][2][1][RTW89_KCC][0][57] = 127, + [0][1][2][1][RTW89_ACMA][1][57] = 127, + [0][1][2][1][RTW89_ACMA][0][57] = 127, + [0][1][2][1][RTW89_CHILE][1][57] = -2, + [0][1][2][1][RTW89_QATAR][1][57] = 127, + [0][1][2][1][RTW89_QATAR][0][57] = 127, + [0][1][2][1][RTW89_UK][1][57] = 127, + [0][1][2][1][RTW89_UK][0][57] = 127, + [0][1][2][1][RTW89_FCC][1][59] = -2, + [0][1][2][1][RTW89_FCC][2][59] = 68, + [0][1][2][1][RTW89_ETSI][1][59] = 127, + [0][1][2][1][RTW89_ETSI][0][59] = 127, + [0][1][2][1][RTW89_MKK][1][59] = 127, + [0][1][2][1][RTW89_MKK][0][59] = 127, + [0][1][2][1][RTW89_IC][1][59] = -2, + [0][1][2][1][RTW89_KCC][1][59] = 12, + [0][1][2][1][RTW89_KCC][0][59] = 127, + [0][1][2][1][RTW89_ACMA][1][59] = 127, + [0][1][2][1][RTW89_ACMA][0][59] = 127, + [0][1][2][1][RTW89_CHILE][1][59] = -2, + [0][1][2][1][RTW89_QATAR][1][59] = 127, + [0][1][2][1][RTW89_QATAR][0][59] = 127, + [0][1][2][1][RTW89_UK][1][59] = 127, + [0][1][2][1][RTW89_UK][0][59] = 127, + [0][1][2][1][RTW89_FCC][1][60] = -2, + [0][1][2][1][RTW89_FCC][2][60] = 68, + [0][1][2][1][RTW89_ETSI][1][60] = 127, + [0][1][2][1][RTW89_ETSI][0][60] = 127, + [0][1][2][1][RTW89_MKK][1][60] = 127, + [0][1][2][1][RTW89_MKK][0][60] = 127, + [0][1][2][1][RTW89_IC][1][60] = -2, + [0][1][2][1][RTW89_KCC][1][60] = 12, + [0][1][2][1][RTW89_KCC][0][60] = 127, + [0][1][2][1][RTW89_ACMA][1][60] = 127, + [0][1][2][1][RTW89_ACMA][0][60] = 127, + [0][1][2][1][RTW89_CHILE][1][60] = -2, + [0][1][2][1][RTW89_QATAR][1][60] = 127, + [0][1][2][1][RTW89_QATAR][0][60] = 127, + [0][1][2][1][RTW89_UK][1][60] = 127, + [0][1][2][1][RTW89_UK][0][60] = 127, + [0][1][2][1][RTW89_FCC][1][62] = -2, + [0][1][2][1][RTW89_FCC][2][62] = 68, + [0][1][2][1][RTW89_ETSI][1][62] = 127, + [0][1][2][1][RTW89_ETSI][0][62] = 127, + [0][1][2][1][RTW89_MKK][1][62] = 127, + [0][1][2][1][RTW89_MKK][0][62] = 127, + [0][1][2][1][RTW89_IC][1][62] = -2, + [0][1][2][1][RTW89_KCC][1][62] = 12, + [0][1][2][1][RTW89_KCC][0][62] = 127, + [0][1][2][1][RTW89_ACMA][1][62] = 127, + [0][1][2][1][RTW89_ACMA][0][62] = 127, + [0][1][2][1][RTW89_CHILE][1][62] = -2, + [0][1][2][1][RTW89_QATAR][1][62] = 127, + [0][1][2][1][RTW89_QATAR][0][62] = 127, + [0][1][2][1][RTW89_UK][1][62] = 127, + [0][1][2][1][RTW89_UK][0][62] = 127, + [0][1][2][1][RTW89_FCC][1][64] = -2, + [0][1][2][1][RTW89_FCC][2][64] = 68, + [0][1][2][1][RTW89_ETSI][1][64] = 127, + [0][1][2][1][RTW89_ETSI][0][64] = 127, + [0][1][2][1][RTW89_MKK][1][64] = 127, + [0][1][2][1][RTW89_MKK][0][64] = 127, + [0][1][2][1][RTW89_IC][1][64] = -2, + [0][1][2][1][RTW89_KCC][1][64] = 12, + [0][1][2][1][RTW89_KCC][0][64] = 127, + [0][1][2][1][RTW89_ACMA][1][64] = 127, + [0][1][2][1][RTW89_ACMA][0][64] = 127, + [0][1][2][1][RTW89_CHILE][1][64] = -2, + [0][1][2][1][RTW89_QATAR][1][64] = 127, + [0][1][2][1][RTW89_QATAR][0][64] = 127, + [0][1][2][1][RTW89_UK][1][64] = 127, + [0][1][2][1][RTW89_UK][0][64] = 127, + [0][1][2][1][RTW89_FCC][1][66] = -2, + [0][1][2][1][RTW89_FCC][2][66] = 68, + [0][1][2][1][RTW89_ETSI][1][66] = 127, + [0][1][2][1][RTW89_ETSI][0][66] = 127, + [0][1][2][1][RTW89_MKK][1][66] = 127, + [0][1][2][1][RTW89_MKK][0][66] = 127, + [0][1][2][1][RTW89_IC][1][66] = -2, + [0][1][2][1][RTW89_KCC][1][66] = 12, + [0][1][2][1][RTW89_KCC][0][66] = 127, + [0][1][2][1][RTW89_ACMA][1][66] = 127, + [0][1][2][1][RTW89_ACMA][0][66] = 127, + [0][1][2][1][RTW89_CHILE][1][66] = -2, + [0][1][2][1][RTW89_QATAR][1][66] = 127, + [0][1][2][1][RTW89_QATAR][0][66] = 127, + [0][1][2][1][RTW89_UK][1][66] = 127, + [0][1][2][1][RTW89_UK][0][66] = 127, + [0][1][2][1][RTW89_FCC][1][68] = -2, + [0][1][2][1][RTW89_FCC][2][68] = 68, + [0][1][2][1][RTW89_ETSI][1][68] = 127, + [0][1][2][1][RTW89_ETSI][0][68] = 127, + [0][1][2][1][RTW89_MKK][1][68] = 127, + [0][1][2][1][RTW89_MKK][0][68] = 127, + [0][1][2][1][RTW89_IC][1][68] = -2, + [0][1][2][1][RTW89_KCC][1][68] = 12, + [0][1][2][1][RTW89_KCC][0][68] = 127, + [0][1][2][1][RTW89_ACMA][1][68] = 127, + [0][1][2][1][RTW89_ACMA][0][68] = 127, + [0][1][2][1][RTW89_CHILE][1][68] = -2, + [0][1][2][1][RTW89_QATAR][1][68] = 127, + [0][1][2][1][RTW89_QATAR][0][68] = 127, + [0][1][2][1][RTW89_UK][1][68] = 127, + [0][1][2][1][RTW89_UK][0][68] = 127, + [0][1][2][1][RTW89_FCC][1][70] = -2, + [0][1][2][1][RTW89_FCC][2][70] = 68, + [0][1][2][1][RTW89_ETSI][1][70] = 127, + [0][1][2][1][RTW89_ETSI][0][70] = 127, + [0][1][2][1][RTW89_MKK][1][70] = 127, + [0][1][2][1][RTW89_MKK][0][70] = 127, + [0][1][2][1][RTW89_IC][1][70] = -2, + [0][1][2][1][RTW89_KCC][1][70] = 12, + [0][1][2][1][RTW89_KCC][0][70] = 127, + [0][1][2][1][RTW89_ACMA][1][70] = 127, + [0][1][2][1][RTW89_ACMA][0][70] = 127, + [0][1][2][1][RTW89_CHILE][1][70] = -2, + [0][1][2][1][RTW89_QATAR][1][70] = 127, + [0][1][2][1][RTW89_QATAR][0][70] = 127, + [0][1][2][1][RTW89_UK][1][70] = 127, + [0][1][2][1][RTW89_UK][0][70] = 127, + [0][1][2][1][RTW89_FCC][1][72] = -2, + [0][1][2][1][RTW89_FCC][2][72] = 68, + [0][1][2][1][RTW89_ETSI][1][72] = 127, + [0][1][2][1][RTW89_ETSI][0][72] = 127, + [0][1][2][1][RTW89_MKK][1][72] = 127, + [0][1][2][1][RTW89_MKK][0][72] = 127, + [0][1][2][1][RTW89_IC][1][72] = -2, + [0][1][2][1][RTW89_KCC][1][72] = 12, + [0][1][2][1][RTW89_KCC][0][72] = 127, + [0][1][2][1][RTW89_ACMA][1][72] = 127, + [0][1][2][1][RTW89_ACMA][0][72] = 127, + [0][1][2][1][RTW89_CHILE][1][72] = -2, + [0][1][2][1][RTW89_QATAR][1][72] = 127, + [0][1][2][1][RTW89_QATAR][0][72] = 127, + [0][1][2][1][RTW89_UK][1][72] = 127, + [0][1][2][1][RTW89_UK][0][72] = 127, + [0][1][2][1][RTW89_FCC][1][74] = -2, + [0][1][2][1][RTW89_FCC][2][74] = 68, + [0][1][2][1][RTW89_ETSI][1][74] = 127, + [0][1][2][1][RTW89_ETSI][0][74] = 127, + [0][1][2][1][RTW89_MKK][1][74] = 127, + [0][1][2][1][RTW89_MKK][0][74] = 127, + [0][1][2][1][RTW89_IC][1][74] = -2, + [0][1][2][1][RTW89_KCC][1][74] = 12, + [0][1][2][1][RTW89_KCC][0][74] = 127, + [0][1][2][1][RTW89_ACMA][1][74] = 127, + [0][1][2][1][RTW89_ACMA][0][74] = 127, + [0][1][2][1][RTW89_CHILE][1][74] = -2, + [0][1][2][1][RTW89_QATAR][1][74] = 127, + [0][1][2][1][RTW89_QATAR][0][74] = 127, + [0][1][2][1][RTW89_UK][1][74] = 127, + [0][1][2][1][RTW89_UK][0][74] = 127, + [0][1][2][1][RTW89_FCC][1][75] = -2, + [0][1][2][1][RTW89_FCC][2][75] = 68, + [0][1][2][1][RTW89_ETSI][1][75] = 127, + [0][1][2][1][RTW89_ETSI][0][75] = 127, + [0][1][2][1][RTW89_MKK][1][75] = 127, + [0][1][2][1][RTW89_MKK][0][75] = 127, + [0][1][2][1][RTW89_IC][1][75] = -2, + [0][1][2][1][RTW89_KCC][1][75] = 12, + [0][1][2][1][RTW89_KCC][0][75] = 127, + [0][1][2][1][RTW89_ACMA][1][75] = 127, + [0][1][2][1][RTW89_ACMA][0][75] = 127, + [0][1][2][1][RTW89_CHILE][1][75] = -2, + [0][1][2][1][RTW89_QATAR][1][75] = 127, + [0][1][2][1][RTW89_QATAR][0][75] = 127, + [0][1][2][1][RTW89_UK][1][75] = 127, + [0][1][2][1][RTW89_UK][0][75] = 127, + [0][1][2][1][RTW89_FCC][1][77] = -2, + [0][1][2][1][RTW89_FCC][2][77] = 68, + [0][1][2][1][RTW89_ETSI][1][77] = 127, + [0][1][2][1][RTW89_ETSI][0][77] = 127, + [0][1][2][1][RTW89_MKK][1][77] = 127, + [0][1][2][1][RTW89_MKK][0][77] = 127, + [0][1][2][1][RTW89_IC][1][77] = -2, + [0][1][2][1][RTW89_KCC][1][77] = 12, + [0][1][2][1][RTW89_KCC][0][77] = 127, + [0][1][2][1][RTW89_ACMA][1][77] = 127, + [0][1][2][1][RTW89_ACMA][0][77] = 127, + [0][1][2][1][RTW89_CHILE][1][77] = -2, + [0][1][2][1][RTW89_QATAR][1][77] = 127, + [0][1][2][1][RTW89_QATAR][0][77] = 127, + [0][1][2][1][RTW89_UK][1][77] = 127, + [0][1][2][1][RTW89_UK][0][77] = 127, + [0][1][2][1][RTW89_FCC][1][79] = -2, + [0][1][2][1][RTW89_FCC][2][79] = 68, + [0][1][2][1][RTW89_ETSI][1][79] = 127, + [0][1][2][1][RTW89_ETSI][0][79] = 127, + [0][1][2][1][RTW89_MKK][1][79] = 127, + [0][1][2][1][RTW89_MKK][0][79] = 127, + [0][1][2][1][RTW89_IC][1][79] = -2, + [0][1][2][1][RTW89_KCC][1][79] = 12, + [0][1][2][1][RTW89_KCC][0][79] = 127, + [0][1][2][1][RTW89_ACMA][1][79] = 127, + [0][1][2][1][RTW89_ACMA][0][79] = 127, + [0][1][2][1][RTW89_CHILE][1][79] = -2, + [0][1][2][1][RTW89_QATAR][1][79] = 127, + [0][1][2][1][RTW89_QATAR][0][79] = 127, + [0][1][2][1][RTW89_UK][1][79] = 127, + [0][1][2][1][RTW89_UK][0][79] = 127, + [0][1][2][1][RTW89_FCC][1][81] = -2, + [0][1][2][1][RTW89_FCC][2][81] = 68, + [0][1][2][1][RTW89_ETSI][1][81] = 127, + [0][1][2][1][RTW89_ETSI][0][81] = 127, + [0][1][2][1][RTW89_MKK][1][81] = 127, + [0][1][2][1][RTW89_MKK][0][81] = 127, + [0][1][2][1][RTW89_IC][1][81] = -2, + [0][1][2][1][RTW89_KCC][1][81] = 12, + [0][1][2][1][RTW89_KCC][0][81] = 127, + [0][1][2][1][RTW89_ACMA][1][81] = 127, + [0][1][2][1][RTW89_ACMA][0][81] = 127, + [0][1][2][1][RTW89_CHILE][1][81] = -2, + [0][1][2][1][RTW89_QATAR][1][81] = 127, + [0][1][2][1][RTW89_QATAR][0][81] = 127, + [0][1][2][1][RTW89_UK][1][81] = 127, + [0][1][2][1][RTW89_UK][0][81] = 127, + [0][1][2][1][RTW89_FCC][1][83] = -2, + [0][1][2][1][RTW89_FCC][2][83] = 68, + [0][1][2][1][RTW89_ETSI][1][83] = 127, + [0][1][2][1][RTW89_ETSI][0][83] = 127, + [0][1][2][1][RTW89_MKK][1][83] = 127, + [0][1][2][1][RTW89_MKK][0][83] = 127, + [0][1][2][1][RTW89_IC][1][83] = -2, + [0][1][2][1][RTW89_KCC][1][83] = 20, + [0][1][2][1][RTW89_KCC][0][83] = 127, + [0][1][2][1][RTW89_ACMA][1][83] = 127, + [0][1][2][1][RTW89_ACMA][0][83] = 127, + [0][1][2][1][RTW89_CHILE][1][83] = -2, + [0][1][2][1][RTW89_QATAR][1][83] = 127, + [0][1][2][1][RTW89_QATAR][0][83] = 127, + [0][1][2][1][RTW89_UK][1][83] = 127, + [0][1][2][1][RTW89_UK][0][83] = 127, + [0][1][2][1][RTW89_FCC][1][85] = -2, + [0][1][2][1][RTW89_FCC][2][85] = 68, + [0][1][2][1][RTW89_ETSI][1][85] = 127, + [0][1][2][1][RTW89_ETSI][0][85] = 127, + [0][1][2][1][RTW89_MKK][1][85] = 127, + [0][1][2][1][RTW89_MKK][0][85] = 127, + [0][1][2][1][RTW89_IC][1][85] = -2, + [0][1][2][1][RTW89_KCC][1][85] = 20, + [0][1][2][1][RTW89_KCC][0][85] = 127, + [0][1][2][1][RTW89_ACMA][1][85] = 127, + [0][1][2][1][RTW89_ACMA][0][85] = 127, + [0][1][2][1][RTW89_CHILE][1][85] = -2, + [0][1][2][1][RTW89_QATAR][1][85] = 127, + [0][1][2][1][RTW89_QATAR][0][85] = 127, + [0][1][2][1][RTW89_UK][1][85] = 127, + [0][1][2][1][RTW89_UK][0][85] = 127, + [0][1][2][1][RTW89_FCC][1][87] = -2, + [0][1][2][1][RTW89_FCC][2][87] = 127, + [0][1][2][1][RTW89_ETSI][1][87] = 127, + [0][1][2][1][RTW89_ETSI][0][87] = 127, + [0][1][2][1][RTW89_MKK][1][87] = 127, + [0][1][2][1][RTW89_MKK][0][87] = 127, + [0][1][2][1][RTW89_IC][1][87] = -2, + [0][1][2][1][RTW89_KCC][1][87] = 20, + [0][1][2][1][RTW89_KCC][0][87] = 127, + [0][1][2][1][RTW89_ACMA][1][87] = 127, + [0][1][2][1][RTW89_ACMA][0][87] = 127, + [0][1][2][1][RTW89_CHILE][1][87] = -2, + [0][1][2][1][RTW89_QATAR][1][87] = 127, + [0][1][2][1][RTW89_QATAR][0][87] = 127, + [0][1][2][1][RTW89_UK][1][87] = 127, + [0][1][2][1][RTW89_UK][0][87] = 127, + [0][1][2][1][RTW89_FCC][1][89] = -2, + [0][1][2][1][RTW89_FCC][2][89] = 127, + [0][1][2][1][RTW89_ETSI][1][89] = 127, + [0][1][2][1][RTW89_ETSI][0][89] = 127, + [0][1][2][1][RTW89_MKK][1][89] = 127, + [0][1][2][1][RTW89_MKK][0][89] = 127, + [0][1][2][1][RTW89_IC][1][89] = -2, + [0][1][2][1][RTW89_KCC][1][89] = 20, + [0][1][2][1][RTW89_KCC][0][89] = 127, + [0][1][2][1][RTW89_ACMA][1][89] = 127, + [0][1][2][1][RTW89_ACMA][0][89] = 127, + [0][1][2][1][RTW89_CHILE][1][89] = -2, + [0][1][2][1][RTW89_QATAR][1][89] = 127, + [0][1][2][1][RTW89_QATAR][0][89] = 127, + [0][1][2][1][RTW89_UK][1][89] = 127, + [0][1][2][1][RTW89_UK][0][89] = 127, + [0][1][2][1][RTW89_FCC][1][90] = -2, + [0][1][2][1][RTW89_FCC][2][90] = 127, + [0][1][2][1][RTW89_ETSI][1][90] = 127, + [0][1][2][1][RTW89_ETSI][0][90] = 127, + [0][1][2][1][RTW89_MKK][1][90] = 127, + [0][1][2][1][RTW89_MKK][0][90] = 127, + [0][1][2][1][RTW89_IC][1][90] = -2, + [0][1][2][1][RTW89_KCC][1][90] = 20, + [0][1][2][1][RTW89_KCC][0][90] = 127, + [0][1][2][1][RTW89_ACMA][1][90] = 127, + [0][1][2][1][RTW89_ACMA][0][90] = 127, + [0][1][2][1][RTW89_CHILE][1][90] = -2, + [0][1][2][1][RTW89_QATAR][1][90] = 127, + [0][1][2][1][RTW89_QATAR][0][90] = 127, + [0][1][2][1][RTW89_UK][1][90] = 127, + [0][1][2][1][RTW89_UK][0][90] = 127, + [0][1][2][1][RTW89_FCC][1][92] = -2, + [0][1][2][1][RTW89_FCC][2][92] = 127, + [0][1][2][1][RTW89_ETSI][1][92] = 127, + [0][1][2][1][RTW89_ETSI][0][92] = 127, + [0][1][2][1][RTW89_MKK][1][92] = 127, + [0][1][2][1][RTW89_MKK][0][92] = 127, + [0][1][2][1][RTW89_IC][1][92] = -2, + [0][1][2][1][RTW89_KCC][1][92] = 20, + [0][1][2][1][RTW89_KCC][0][92] = 127, + [0][1][2][1][RTW89_ACMA][1][92] = 127, + [0][1][2][1][RTW89_ACMA][0][92] = 127, + [0][1][2][1][RTW89_CHILE][1][92] = -2, + [0][1][2][1][RTW89_QATAR][1][92] = 127, + [0][1][2][1][RTW89_QATAR][0][92] = 127, + [0][1][2][1][RTW89_UK][1][92] = 127, + [0][1][2][1][RTW89_UK][0][92] = 127, + [0][1][2][1][RTW89_FCC][1][94] = -2, + [0][1][2][1][RTW89_FCC][2][94] = 127, + [0][1][2][1][RTW89_ETSI][1][94] = 127, + [0][1][2][1][RTW89_ETSI][0][94] = 127, + [0][1][2][1][RTW89_MKK][1][94] = 127, + [0][1][2][1][RTW89_MKK][0][94] = 127, + [0][1][2][1][RTW89_IC][1][94] = -2, + [0][1][2][1][RTW89_KCC][1][94] = 20, + [0][1][2][1][RTW89_KCC][0][94] = 127, + [0][1][2][1][RTW89_ACMA][1][94] = 127, + [0][1][2][1][RTW89_ACMA][0][94] = 127, + [0][1][2][1][RTW89_CHILE][1][94] = -2, + [0][1][2][1][RTW89_QATAR][1][94] = 127, + [0][1][2][1][RTW89_QATAR][0][94] = 127, + [0][1][2][1][RTW89_UK][1][94] = 127, + [0][1][2][1][RTW89_UK][0][94] = 127, + [0][1][2][1][RTW89_FCC][1][96] = -2, + [0][1][2][1][RTW89_FCC][2][96] = 127, + [0][1][2][1][RTW89_ETSI][1][96] = 127, + [0][1][2][1][RTW89_ETSI][0][96] = 127, + [0][1][2][1][RTW89_MKK][1][96] = 127, + [0][1][2][1][RTW89_MKK][0][96] = 127, + [0][1][2][1][RTW89_IC][1][96] = -2, + [0][1][2][1][RTW89_KCC][1][96] = 20, + [0][1][2][1][RTW89_KCC][0][96] = 127, + [0][1][2][1][RTW89_ACMA][1][96] = 127, + [0][1][2][1][RTW89_ACMA][0][96] = 127, + [0][1][2][1][RTW89_CHILE][1][96] = -2, + [0][1][2][1][RTW89_QATAR][1][96] = 127, + [0][1][2][1][RTW89_QATAR][0][96] = 127, + [0][1][2][1][RTW89_UK][1][96] = 127, + [0][1][2][1][RTW89_UK][0][96] = 127, + [0][1][2][1][RTW89_FCC][1][98] = -2, + [0][1][2][1][RTW89_FCC][2][98] = 127, + [0][1][2][1][RTW89_ETSI][1][98] = 127, + [0][1][2][1][RTW89_ETSI][0][98] = 127, + [0][1][2][1][RTW89_MKK][1][98] = 127, + [0][1][2][1][RTW89_MKK][0][98] = 127, + [0][1][2][1][RTW89_IC][1][98] = -2, + [0][1][2][1][RTW89_KCC][1][98] = 20, + [0][1][2][1][RTW89_KCC][0][98] = 127, + [0][1][2][1][RTW89_ACMA][1][98] = 127, + [0][1][2][1][RTW89_ACMA][0][98] = 127, + [0][1][2][1][RTW89_CHILE][1][98] = -2, + [0][1][2][1][RTW89_QATAR][1][98] = 127, + [0][1][2][1][RTW89_QATAR][0][98] = 127, + [0][1][2][1][RTW89_UK][1][98] = 127, + [0][1][2][1][RTW89_UK][0][98] = 127, + [0][1][2][1][RTW89_FCC][1][100] = -2, + [0][1][2][1][RTW89_FCC][2][100] = 127, + [0][1][2][1][RTW89_ETSI][1][100] = 127, + [0][1][2][1][RTW89_ETSI][0][100] = 127, + [0][1][2][1][RTW89_MKK][1][100] = 127, + [0][1][2][1][RTW89_MKK][0][100] = 127, + [0][1][2][1][RTW89_IC][1][100] = -2, + [0][1][2][1][RTW89_KCC][1][100] = 20, + [0][1][2][1][RTW89_KCC][0][100] = 127, + [0][1][2][1][RTW89_ACMA][1][100] = 127, + [0][1][2][1][RTW89_ACMA][0][100] = 127, + [0][1][2][1][RTW89_CHILE][1][100] = -2, + [0][1][2][1][RTW89_QATAR][1][100] = 127, + [0][1][2][1][RTW89_QATAR][0][100] = 127, + [0][1][2][1][RTW89_UK][1][100] = 127, + [0][1][2][1][RTW89_UK][0][100] = 127, + [0][1][2][1][RTW89_FCC][1][102] = -2, + [0][1][2][1][RTW89_FCC][2][102] = 127, + [0][1][2][1][RTW89_ETSI][1][102] = 127, + [0][1][2][1][RTW89_ETSI][0][102] = 127, + [0][1][2][1][RTW89_MKK][1][102] = 127, + [0][1][2][1][RTW89_MKK][0][102] = 127, + [0][1][2][1][RTW89_IC][1][102] = -2, + [0][1][2][1][RTW89_KCC][1][102] = 20, + [0][1][2][1][RTW89_KCC][0][102] = 127, + [0][1][2][1][RTW89_ACMA][1][102] = 127, + [0][1][2][1][RTW89_ACMA][0][102] = 127, + [0][1][2][1][RTW89_CHILE][1][102] = -2, + [0][1][2][1][RTW89_QATAR][1][102] = 127, + [0][1][2][1][RTW89_QATAR][0][102] = 127, + [0][1][2][1][RTW89_UK][1][102] = 127, + [0][1][2][1][RTW89_UK][0][102] = 127, + [0][1][2][1][RTW89_FCC][1][104] = -2, + [0][1][2][1][RTW89_FCC][2][104] = 127, + [0][1][2][1][RTW89_ETSI][1][104] = 127, + [0][1][2][1][RTW89_ETSI][0][104] = 127, + [0][1][2][1][RTW89_MKK][1][104] = 127, + [0][1][2][1][RTW89_MKK][0][104] = 127, + [0][1][2][1][RTW89_IC][1][104] = -2, + [0][1][2][1][RTW89_KCC][1][104] = 20, + [0][1][2][1][RTW89_KCC][0][104] = 127, + [0][1][2][1][RTW89_ACMA][1][104] = 127, + [0][1][2][1][RTW89_ACMA][0][104] = 127, + [0][1][2][1][RTW89_CHILE][1][104] = -2, + [0][1][2][1][RTW89_QATAR][1][104] = 127, + [0][1][2][1][RTW89_QATAR][0][104] = 127, + [0][1][2][1][RTW89_UK][1][104] = 127, + [0][1][2][1][RTW89_UK][0][104] = 127, + [0][1][2][1][RTW89_FCC][1][105] = -2, + [0][1][2][1][RTW89_FCC][2][105] = 127, + [0][1][2][1][RTW89_ETSI][1][105] = 127, + [0][1][2][1][RTW89_ETSI][0][105] = 127, + [0][1][2][1][RTW89_MKK][1][105] = 127, + [0][1][2][1][RTW89_MKK][0][105] = 127, + [0][1][2][1][RTW89_IC][1][105] = -2, + [0][1][2][1][RTW89_KCC][1][105] = 20, + [0][1][2][1][RTW89_KCC][0][105] = 127, + [0][1][2][1][RTW89_ACMA][1][105] = 127, + [0][1][2][1][RTW89_ACMA][0][105] = 127, + [0][1][2][1][RTW89_CHILE][1][105] = -2, + [0][1][2][1][RTW89_QATAR][1][105] = 127, + [0][1][2][1][RTW89_QATAR][0][105] = 127, + [0][1][2][1][RTW89_UK][1][105] = 127, + [0][1][2][1][RTW89_UK][0][105] = 127, + [0][1][2][1][RTW89_FCC][1][107] = 1, + [0][1][2][1][RTW89_FCC][2][107] = 127, + [0][1][2][1][RTW89_ETSI][1][107] = 127, + [0][1][2][1][RTW89_ETSI][0][107] = 127, + [0][1][2][1][RTW89_MKK][1][107] = 127, + [0][1][2][1][RTW89_MKK][0][107] = 127, + [0][1][2][1][RTW89_IC][1][107] = 1, + [0][1][2][1][RTW89_KCC][1][107] = 20, + [0][1][2][1][RTW89_KCC][0][107] = 127, + [0][1][2][1][RTW89_ACMA][1][107] = 127, + [0][1][2][1][RTW89_ACMA][0][107] = 127, + [0][1][2][1][RTW89_CHILE][1][107] = 1, + [0][1][2][1][RTW89_QATAR][1][107] = 127, + [0][1][2][1][RTW89_QATAR][0][107] = 127, + [0][1][2][1][RTW89_UK][1][107] = 127, + [0][1][2][1][RTW89_UK][0][107] = 127, + [0][1][2][1][RTW89_FCC][1][109] = 1, + [0][1][2][1][RTW89_FCC][2][109] = 127, + [0][1][2][1][RTW89_ETSI][1][109] = 127, + [0][1][2][1][RTW89_ETSI][0][109] = 127, + [0][1][2][1][RTW89_MKK][1][109] = 127, + [0][1][2][1][RTW89_MKK][0][109] = 127, + [0][1][2][1][RTW89_IC][1][109] = 1, + [0][1][2][1][RTW89_KCC][1][109] = 20, + [0][1][2][1][RTW89_KCC][0][109] = 127, + [0][1][2][1][RTW89_ACMA][1][109] = 127, + [0][1][2][1][RTW89_ACMA][0][109] = 127, + [0][1][2][1][RTW89_CHILE][1][109] = 1, + [0][1][2][1][RTW89_QATAR][1][109] = 127, + [0][1][2][1][RTW89_QATAR][0][109] = 127, + [0][1][2][1][RTW89_UK][1][109] = 127, + [0][1][2][1][RTW89_UK][0][109] = 127, + [0][1][2][1][RTW89_FCC][1][111] = 127, + [0][1][2][1][RTW89_FCC][2][111] = 127, + [0][1][2][1][RTW89_ETSI][1][111] = 127, + [0][1][2][1][RTW89_ETSI][0][111] = 127, + [0][1][2][1][RTW89_MKK][1][111] = 127, + [0][1][2][1][RTW89_MKK][0][111] = 127, + [0][1][2][1][RTW89_IC][1][111] = 127, + [0][1][2][1][RTW89_KCC][1][111] = 127, + [0][1][2][1][RTW89_KCC][0][111] = 127, + [0][1][2][1][RTW89_ACMA][1][111] = 127, + [0][1][2][1][RTW89_ACMA][0][111] = 127, + [0][1][2][1][RTW89_CHILE][1][111] = 127, + [0][1][2][1][RTW89_QATAR][1][111] = 127, + [0][1][2][1][RTW89_QATAR][0][111] = 127, + [0][1][2][1][RTW89_UK][1][111] = 127, + [0][1][2][1][RTW89_UK][0][111] = 127, + [0][1][2][1][RTW89_FCC][1][113] = 127, + [0][1][2][1][RTW89_FCC][2][113] = 127, + [0][1][2][1][RTW89_ETSI][1][113] = 127, + [0][1][2][1][RTW89_ETSI][0][113] = 127, + [0][1][2][1][RTW89_MKK][1][113] = 127, + [0][1][2][1][RTW89_MKK][0][113] = 127, + [0][1][2][1][RTW89_IC][1][113] = 127, + [0][1][2][1][RTW89_KCC][1][113] = 127, + [0][1][2][1][RTW89_KCC][0][113] = 127, + [0][1][2][1][RTW89_ACMA][1][113] = 127, + [0][1][2][1][RTW89_ACMA][0][113] = 127, + [0][1][2][1][RTW89_CHILE][1][113] = 127, + [0][1][2][1][RTW89_QATAR][1][113] = 127, + [0][1][2][1][RTW89_QATAR][0][113] = 127, + [0][1][2][1][RTW89_UK][1][113] = 127, + [0][1][2][1][RTW89_UK][0][113] = 127, + [0][1][2][1][RTW89_FCC][1][115] = 127, + [0][1][2][1][RTW89_FCC][2][115] = 127, + [0][1][2][1][RTW89_ETSI][1][115] = 127, + [0][1][2][1][RTW89_ETSI][0][115] = 127, + [0][1][2][1][RTW89_MKK][1][115] = 127, + [0][1][2][1][RTW89_MKK][0][115] = 127, + [0][1][2][1][RTW89_IC][1][115] = 127, + [0][1][2][1][RTW89_KCC][1][115] = 127, + [0][1][2][1][RTW89_KCC][0][115] = 127, + [0][1][2][1][RTW89_ACMA][1][115] = 127, + [0][1][2][1][RTW89_ACMA][0][115] = 127, + [0][1][2][1][RTW89_CHILE][1][115] = 127, + [0][1][2][1][RTW89_QATAR][1][115] = 127, + [0][1][2][1][RTW89_QATAR][0][115] = 127, + [0][1][2][1][RTW89_UK][1][115] = 127, + [0][1][2][1][RTW89_UK][0][115] = 127, + [0][1][2][1][RTW89_FCC][1][117] = 127, + [0][1][2][1][RTW89_FCC][2][117] = 127, + [0][1][2][1][RTW89_ETSI][1][117] = 127, + [0][1][2][1][RTW89_ETSI][0][117] = 127, + [0][1][2][1][RTW89_MKK][1][117] = 127, + [0][1][2][1][RTW89_MKK][0][117] = 127, + [0][1][2][1][RTW89_IC][1][117] = 127, + [0][1][2][1][RTW89_KCC][1][117] = 127, + [0][1][2][1][RTW89_KCC][0][117] = 127, + [0][1][2][1][RTW89_ACMA][1][117] = 127, + [0][1][2][1][RTW89_ACMA][0][117] = 127, + [0][1][2][1][RTW89_CHILE][1][117] = 127, + [0][1][2][1][RTW89_QATAR][1][117] = 127, + [0][1][2][1][RTW89_QATAR][0][117] = 127, + [0][1][2][1][RTW89_UK][1][117] = 127, + [0][1][2][1][RTW89_UK][0][117] = 127, + [0][1][2][1][RTW89_FCC][1][119] = 127, + [0][1][2][1][RTW89_FCC][2][119] = 127, + [0][1][2][1][RTW89_ETSI][1][119] = 127, + [0][1][2][1][RTW89_ETSI][0][119] = 127, + [0][1][2][1][RTW89_MKK][1][119] = 127, + [0][1][2][1][RTW89_MKK][0][119] = 127, + [0][1][2][1][RTW89_IC][1][119] = 127, + [0][1][2][1][RTW89_KCC][1][119] = 127, + [0][1][2][1][RTW89_KCC][0][119] = 127, + [0][1][2][1][RTW89_ACMA][1][119] = 127, + [0][1][2][1][RTW89_ACMA][0][119] = 127, + [0][1][2][1][RTW89_CHILE][1][119] = 127, + [0][1][2][1][RTW89_QATAR][1][119] = 127, + [0][1][2][1][RTW89_QATAR][0][119] = 127, + [0][1][2][1][RTW89_UK][1][119] = 127, + [0][1][2][1][RTW89_UK][0][119] = 127, + [1][0][2][0][RTW89_FCC][1][1] = 34, + [1][0][2][0][RTW89_FCC][2][1] = 70, + [1][0][2][0][RTW89_ETSI][1][1] = 66, + [1][0][2][0][RTW89_ETSI][0][1] = 30, + [1][0][2][0][RTW89_MKK][1][1] = 62, + [1][0][2][0][RTW89_MKK][0][1] = 26, + [1][0][2][0][RTW89_IC][1][1] = 34, + [1][0][2][0][RTW89_KCC][1][1] = 40, + [1][0][2][0][RTW89_KCC][0][1] = 24, + [1][0][2][0][RTW89_ACMA][1][1] = 66, + [1][0][2][0][RTW89_ACMA][0][1] = 30, + [1][0][2][0][RTW89_CHILE][1][1] = 34, + [1][0][2][0][RTW89_QATAR][1][1] = 66, + [1][0][2][0][RTW89_QATAR][0][1] = 30, + [1][0][2][0][RTW89_UK][1][1] = 66, + [1][0][2][0][RTW89_UK][0][1] = 30, + [1][0][2][0][RTW89_FCC][1][5] = 34, + [1][0][2][0][RTW89_FCC][2][5] = 70, + [1][0][2][0][RTW89_ETSI][1][5] = 66, + [1][0][2][0][RTW89_ETSI][0][5] = 30, + [1][0][2][0][RTW89_MKK][1][5] = 62, + [1][0][2][0][RTW89_MKK][0][5] = 26, + [1][0][2][0][RTW89_IC][1][5] = 34, + [1][0][2][0][RTW89_KCC][1][5] = 40, + [1][0][2][0][RTW89_KCC][0][5] = 24, + [1][0][2][0][RTW89_ACMA][1][5] = 66, + [1][0][2][0][RTW89_ACMA][0][5] = 30, + [1][0][2][0][RTW89_CHILE][1][5] = 34, + [1][0][2][0][RTW89_QATAR][1][5] = 66, + [1][0][2][0][RTW89_QATAR][0][5] = 30, + [1][0][2][0][RTW89_UK][1][5] = 66, + [1][0][2][0][RTW89_UK][0][5] = 30, + [1][0][2][0][RTW89_FCC][1][9] = 34, + [1][0][2][0][RTW89_FCC][2][9] = 70, + [1][0][2][0][RTW89_ETSI][1][9] = 66, + [1][0][2][0][RTW89_ETSI][0][9] = 30, + [1][0][2][0][RTW89_MKK][1][9] = 62, + [1][0][2][0][RTW89_MKK][0][9] = 26, + [1][0][2][0][RTW89_IC][1][9] = 34, + [1][0][2][0][RTW89_KCC][1][9] = 40, + [1][0][2][0][RTW89_KCC][0][9] = 24, + [1][0][2][0][RTW89_ACMA][1][9] = 66, + [1][0][2][0][RTW89_ACMA][0][9] = 30, + [1][0][2][0][RTW89_CHILE][1][9] = 34, + [1][0][2][0][RTW89_QATAR][1][9] = 66, + [1][0][2][0][RTW89_QATAR][0][9] = 30, + [1][0][2][0][RTW89_UK][1][9] = 66, + [1][0][2][0][RTW89_UK][0][9] = 30, + [1][0][2][0][RTW89_FCC][1][13] = 34, + [1][0][2][0][RTW89_FCC][2][13] = 70, + [1][0][2][0][RTW89_ETSI][1][13] = 66, + [1][0][2][0][RTW89_ETSI][0][13] = 30, + [1][0][2][0][RTW89_MKK][1][13] = 62, + [1][0][2][0][RTW89_MKK][0][13] = 26, + [1][0][2][0][RTW89_IC][1][13] = 34, + [1][0][2][0][RTW89_KCC][1][13] = 40, + [1][0][2][0][RTW89_KCC][0][13] = 24, + [1][0][2][0][RTW89_ACMA][1][13] = 66, + [1][0][2][0][RTW89_ACMA][0][13] = 30, + [1][0][2][0][RTW89_CHILE][1][13] = 34, + [1][0][2][0][RTW89_QATAR][1][13] = 66, + [1][0][2][0][RTW89_QATAR][0][13] = 30, + [1][0][2][0][RTW89_UK][1][13] = 66, + [1][0][2][0][RTW89_UK][0][13] = 30, + [1][0][2][0][RTW89_FCC][1][16] = 34, + [1][0][2][0][RTW89_FCC][2][16] = 70, + [1][0][2][0][RTW89_ETSI][1][16] = 66, + [1][0][2][0][RTW89_ETSI][0][16] = 30, + [1][0][2][0][RTW89_MKK][1][16] = 62, + [1][0][2][0][RTW89_MKK][0][16] = 26, + [1][0][2][0][RTW89_IC][1][16] = 34, + [1][0][2][0][RTW89_KCC][1][16] = 40, + [1][0][2][0][RTW89_KCC][0][16] = 24, + [1][0][2][0][RTW89_ACMA][1][16] = 66, + [1][0][2][0][RTW89_ACMA][0][16] = 30, + [1][0][2][0][RTW89_CHILE][1][16] = 34, + [1][0][2][0][RTW89_QATAR][1][16] = 66, + [1][0][2][0][RTW89_QATAR][0][16] = 30, + [1][0][2][0][RTW89_UK][1][16] = 66, + [1][0][2][0][RTW89_UK][0][16] = 30, + [1][0][2][0][RTW89_FCC][1][20] = 34, + [1][0][2][0][RTW89_FCC][2][20] = 70, + [1][0][2][0][RTW89_ETSI][1][20] = 66, + [1][0][2][0][RTW89_ETSI][0][20] = 30, + [1][0][2][0][RTW89_MKK][1][20] = 62, + [1][0][2][0][RTW89_MKK][0][20] = 26, + [1][0][2][0][RTW89_IC][1][20] = 34, + [1][0][2][0][RTW89_KCC][1][20] = 40, + [1][0][2][0][RTW89_KCC][0][20] = 24, + [1][0][2][0][RTW89_ACMA][1][20] = 66, + [1][0][2][0][RTW89_ACMA][0][20] = 30, + [1][0][2][0][RTW89_CHILE][1][20] = 34, + [1][0][2][0][RTW89_QATAR][1][20] = 66, + [1][0][2][0][RTW89_QATAR][0][20] = 30, + [1][0][2][0][RTW89_UK][1][20] = 66, + [1][0][2][0][RTW89_UK][0][20] = 30, + [1][0][2][0][RTW89_FCC][1][24] = 36, + [1][0][2][0][RTW89_FCC][2][24] = 70, + [1][0][2][0][RTW89_ETSI][1][24] = 66, + [1][0][2][0][RTW89_ETSI][0][24] = 30, + [1][0][2][0][RTW89_MKK][1][24] = 64, + [1][0][2][0][RTW89_MKK][0][24] = 28, + [1][0][2][0][RTW89_IC][1][24] = 36, + [1][0][2][0][RTW89_KCC][1][24] = 40, + [1][0][2][0][RTW89_KCC][0][24] = 26, + [1][0][2][0][RTW89_ACMA][1][24] = 66, + [1][0][2][0][RTW89_ACMA][0][24] = 30, + [1][0][2][0][RTW89_CHILE][1][24] = 36, + [1][0][2][0][RTW89_QATAR][1][24] = 66, + [1][0][2][0][RTW89_QATAR][0][24] = 30, + [1][0][2][0][RTW89_UK][1][24] = 66, + [1][0][2][0][RTW89_UK][0][24] = 30, + [1][0][2][0][RTW89_FCC][1][28] = 34, + [1][0][2][0][RTW89_FCC][2][28] = 70, + [1][0][2][0][RTW89_ETSI][1][28] = 66, + [1][0][2][0][RTW89_ETSI][0][28] = 30, + [1][0][2][0][RTW89_MKK][1][28] = 64, + [1][0][2][0][RTW89_MKK][0][28] = 26, + [1][0][2][0][RTW89_IC][1][28] = 34, + [1][0][2][0][RTW89_KCC][1][28] = 40, + [1][0][2][0][RTW89_KCC][0][28] = 26, + [1][0][2][0][RTW89_ACMA][1][28] = 66, + [1][0][2][0][RTW89_ACMA][0][28] = 30, + [1][0][2][0][RTW89_CHILE][1][28] = 34, + [1][0][2][0][RTW89_QATAR][1][28] = 66, + [1][0][2][0][RTW89_QATAR][0][28] = 30, + [1][0][2][0][RTW89_UK][1][28] = 66, + [1][0][2][0][RTW89_UK][0][28] = 30, + [1][0][2][0][RTW89_FCC][1][31] = 34, + [1][0][2][0][RTW89_FCC][2][31] = 70, + [1][0][2][0][RTW89_ETSI][1][31] = 66, + [1][0][2][0][RTW89_ETSI][0][31] = 30, + [1][0][2][0][RTW89_MKK][1][31] = 64, + [1][0][2][0][RTW89_MKK][0][31] = 26, + [1][0][2][0][RTW89_IC][1][31] = 34, + [1][0][2][0][RTW89_KCC][1][31] = 40, + [1][0][2][0][RTW89_KCC][0][31] = 26, + [1][0][2][0][RTW89_ACMA][1][31] = 66, + [1][0][2][0][RTW89_ACMA][0][31] = 30, + [1][0][2][0][RTW89_CHILE][1][31] = 34, + [1][0][2][0][RTW89_QATAR][1][31] = 66, + [1][0][2][0][RTW89_QATAR][0][31] = 30, + [1][0][2][0][RTW89_UK][1][31] = 66, + [1][0][2][0][RTW89_UK][0][31] = 30, + [1][0][2][0][RTW89_FCC][1][35] = 34, + [1][0][2][0][RTW89_FCC][2][35] = 70, + [1][0][2][0][RTW89_ETSI][1][35] = 66, + [1][0][2][0][RTW89_ETSI][0][35] = 30, + [1][0][2][0][RTW89_MKK][1][35] = 64, + [1][0][2][0][RTW89_MKK][0][35] = 26, + [1][0][2][0][RTW89_IC][1][35] = 34, + [1][0][2][0][RTW89_KCC][1][35] = 40, + [1][0][2][0][RTW89_KCC][0][35] = 26, + [1][0][2][0][RTW89_ACMA][1][35] = 66, + [1][0][2][0][RTW89_ACMA][0][35] = 30, + [1][0][2][0][RTW89_CHILE][1][35] = 34, + [1][0][2][0][RTW89_QATAR][1][35] = 66, + [1][0][2][0][RTW89_QATAR][0][35] = 30, + [1][0][2][0][RTW89_UK][1][35] = 66, + [1][0][2][0][RTW89_UK][0][35] = 30, + [1][0][2][0][RTW89_FCC][1][39] = 34, + [1][0][2][0][RTW89_FCC][2][39] = 70, + [1][0][2][0][RTW89_ETSI][1][39] = 66, + [1][0][2][0][RTW89_ETSI][0][39] = 30, + [1][0][2][0][RTW89_MKK][1][39] = 64, + [1][0][2][0][RTW89_MKK][0][39] = 26, + [1][0][2][0][RTW89_IC][1][39] = 34, + [1][0][2][0][RTW89_KCC][1][39] = 40, + [1][0][2][0][RTW89_KCC][0][39] = 26, + [1][0][2][0][RTW89_ACMA][1][39] = 66, + [1][0][2][0][RTW89_ACMA][0][39] = 30, + [1][0][2][0][RTW89_CHILE][1][39] = 34, + [1][0][2][0][RTW89_QATAR][1][39] = 66, + [1][0][2][0][RTW89_QATAR][0][39] = 30, + [1][0][2][0][RTW89_UK][1][39] = 66, + [1][0][2][0][RTW89_UK][0][39] = 30, + [1][0][2][0][RTW89_FCC][1][43] = 34, + [1][0][2][0][RTW89_FCC][2][43] = 70, + [1][0][2][0][RTW89_ETSI][1][43] = 66, + [1][0][2][0][RTW89_ETSI][0][43] = 30, + [1][0][2][0][RTW89_MKK][1][43] = 64, + [1][0][2][0][RTW89_MKK][0][43] = 26, + [1][0][2][0][RTW89_IC][1][43] = 34, + [1][0][2][0][RTW89_KCC][1][43] = 40, + [1][0][2][0][RTW89_KCC][0][43] = 26, + [1][0][2][0][RTW89_ACMA][1][43] = 66, + [1][0][2][0][RTW89_ACMA][0][43] = 30, + [1][0][2][0][RTW89_CHILE][1][43] = 34, + [1][0][2][0][RTW89_QATAR][1][43] = 66, + [1][0][2][0][RTW89_QATAR][0][43] = 30, + [1][0][2][0][RTW89_UK][1][43] = 66, + [1][0][2][0][RTW89_UK][0][43] = 30, + [1][0][2][0][RTW89_FCC][1][46] = 34, + [1][0][2][0][RTW89_FCC][2][46] = 127, + [1][0][2][0][RTW89_ETSI][1][46] = 127, + [1][0][2][0][RTW89_ETSI][0][46] = 127, + [1][0][2][0][RTW89_MKK][1][46] = 127, + [1][0][2][0][RTW89_MKK][0][46] = 127, + [1][0][2][0][RTW89_IC][1][46] = 34, + [1][0][2][0][RTW89_KCC][1][46] = 40, + [1][0][2][0][RTW89_KCC][0][46] = 127, + [1][0][2][0][RTW89_ACMA][1][46] = 127, + [1][0][2][0][RTW89_ACMA][0][46] = 127, + [1][0][2][0][RTW89_CHILE][1][46] = 34, + [1][0][2][0][RTW89_QATAR][1][46] = 127, + [1][0][2][0][RTW89_QATAR][0][46] = 127, + [1][0][2][0][RTW89_UK][1][46] = 127, + [1][0][2][0][RTW89_UK][0][46] = 127, + [1][0][2][0][RTW89_FCC][1][50] = 34, + [1][0][2][0][RTW89_FCC][2][50] = 127, + [1][0][2][0][RTW89_ETSI][1][50] = 127, + [1][0][2][0][RTW89_ETSI][0][50] = 127, + [1][0][2][0][RTW89_MKK][1][50] = 127, + [1][0][2][0][RTW89_MKK][0][50] = 127, + [1][0][2][0][RTW89_IC][1][50] = 34, + [1][0][2][0][RTW89_KCC][1][50] = 40, + [1][0][2][0][RTW89_KCC][0][50] = 127, + [1][0][2][0][RTW89_ACMA][1][50] = 127, + [1][0][2][0][RTW89_ACMA][0][50] = 127, + [1][0][2][0][RTW89_CHILE][1][50] = 34, + [1][0][2][0][RTW89_QATAR][1][50] = 127, + [1][0][2][0][RTW89_QATAR][0][50] = 127, + [1][0][2][0][RTW89_UK][1][50] = 127, + [1][0][2][0][RTW89_UK][0][50] = 127, + [1][0][2][0][RTW89_FCC][1][54] = 36, + [1][0][2][0][RTW89_FCC][2][54] = 127, + [1][0][2][0][RTW89_ETSI][1][54] = 127, + [1][0][2][0][RTW89_ETSI][0][54] = 127, + [1][0][2][0][RTW89_MKK][1][54] = 127, + [1][0][2][0][RTW89_MKK][0][54] = 127, + [1][0][2][0][RTW89_IC][1][54] = 36, + [1][0][2][0][RTW89_KCC][1][54] = 40, + [1][0][2][0][RTW89_KCC][0][54] = 127, + [1][0][2][0][RTW89_ACMA][1][54] = 127, + [1][0][2][0][RTW89_ACMA][0][54] = 127, + [1][0][2][0][RTW89_CHILE][1][54] = 36, + [1][0][2][0][RTW89_QATAR][1][54] = 127, + [1][0][2][0][RTW89_QATAR][0][54] = 127, + [1][0][2][0][RTW89_UK][1][54] = 127, + [1][0][2][0][RTW89_UK][0][54] = 127, + [1][0][2][0][RTW89_FCC][1][58] = 36, + [1][0][2][0][RTW89_FCC][2][58] = 66, + [1][0][2][0][RTW89_ETSI][1][58] = 127, + [1][0][2][0][RTW89_ETSI][0][58] = 127, + [1][0][2][0][RTW89_MKK][1][58] = 127, + [1][0][2][0][RTW89_MKK][0][58] = 127, + [1][0][2][0][RTW89_IC][1][58] = 36, + [1][0][2][0][RTW89_KCC][1][58] = 40, + [1][0][2][0][RTW89_KCC][0][58] = 127, + [1][0][2][0][RTW89_ACMA][1][58] = 127, + [1][0][2][0][RTW89_ACMA][0][58] = 127, + [1][0][2][0][RTW89_CHILE][1][58] = 36, + [1][0][2][0][RTW89_QATAR][1][58] = 127, + [1][0][2][0][RTW89_QATAR][0][58] = 127, + [1][0][2][0][RTW89_UK][1][58] = 127, + [1][0][2][0][RTW89_UK][0][58] = 127, + [1][0][2][0][RTW89_FCC][1][61] = 34, + [1][0][2][0][RTW89_FCC][2][61] = 66, + [1][0][2][0][RTW89_ETSI][1][61] = 127, + [1][0][2][0][RTW89_ETSI][0][61] = 127, + [1][0][2][0][RTW89_MKK][1][61] = 127, + [1][0][2][0][RTW89_MKK][0][61] = 127, + [1][0][2][0][RTW89_IC][1][61] = 34, + [1][0][2][0][RTW89_KCC][1][61] = 40, + [1][0][2][0][RTW89_KCC][0][61] = 127, + [1][0][2][0][RTW89_ACMA][1][61] = 127, + [1][0][2][0][RTW89_ACMA][0][61] = 127, + [1][0][2][0][RTW89_CHILE][1][61] = 34, + [1][0][2][0][RTW89_QATAR][1][61] = 127, + [1][0][2][0][RTW89_QATAR][0][61] = 127, + [1][0][2][0][RTW89_UK][1][61] = 127, + [1][0][2][0][RTW89_UK][0][61] = 127, + [1][0][2][0][RTW89_FCC][1][65] = 34, + [1][0][2][0][RTW89_FCC][2][65] = 66, + [1][0][2][0][RTW89_ETSI][1][65] = 127, + [1][0][2][0][RTW89_ETSI][0][65] = 127, + [1][0][2][0][RTW89_MKK][1][65] = 127, + [1][0][2][0][RTW89_MKK][0][65] = 127, + [1][0][2][0][RTW89_IC][1][65] = 34, + [1][0][2][0][RTW89_KCC][1][65] = 40, + [1][0][2][0][RTW89_KCC][0][65] = 127, + [1][0][2][0][RTW89_ACMA][1][65] = 127, + [1][0][2][0][RTW89_ACMA][0][65] = 127, + [1][0][2][0][RTW89_CHILE][1][65] = 34, + [1][0][2][0][RTW89_QATAR][1][65] = 127, + [1][0][2][0][RTW89_QATAR][0][65] = 127, + [1][0][2][0][RTW89_UK][1][65] = 127, + [1][0][2][0][RTW89_UK][0][65] = 127, + [1][0][2][0][RTW89_FCC][1][69] = 34, + [1][0][2][0][RTW89_FCC][2][69] = 66, + [1][0][2][0][RTW89_ETSI][1][69] = 127, + [1][0][2][0][RTW89_ETSI][0][69] = 127, + [1][0][2][0][RTW89_MKK][1][69] = 127, + [1][0][2][0][RTW89_MKK][0][69] = 127, + [1][0][2][0][RTW89_IC][1][69] = 34, + [1][0][2][0][RTW89_KCC][1][69] = 40, + [1][0][2][0][RTW89_KCC][0][69] = 127, + [1][0][2][0][RTW89_ACMA][1][69] = 127, + [1][0][2][0][RTW89_ACMA][0][69] = 127, + [1][0][2][0][RTW89_CHILE][1][69] = 34, + [1][0][2][0][RTW89_QATAR][1][69] = 127, + [1][0][2][0][RTW89_QATAR][0][69] = 127, + [1][0][2][0][RTW89_UK][1][69] = 127, + [1][0][2][0][RTW89_UK][0][69] = 127, + [1][0][2][0][RTW89_FCC][1][73] = 34, + [1][0][2][0][RTW89_FCC][2][73] = 66, + [1][0][2][0][RTW89_ETSI][1][73] = 127, + [1][0][2][0][RTW89_ETSI][0][73] = 127, + [1][0][2][0][RTW89_MKK][1][73] = 127, + [1][0][2][0][RTW89_MKK][0][73] = 127, + [1][0][2][0][RTW89_IC][1][73] = 34, + [1][0][2][0][RTW89_KCC][1][73] = 40, + [1][0][2][0][RTW89_KCC][0][73] = 127, + [1][0][2][0][RTW89_ACMA][1][73] = 127, + [1][0][2][0][RTW89_ACMA][0][73] = 127, + [1][0][2][0][RTW89_CHILE][1][73] = 34, + [1][0][2][0][RTW89_QATAR][1][73] = 127, + [1][0][2][0][RTW89_QATAR][0][73] = 127, + [1][0][2][0][RTW89_UK][1][73] = 127, + [1][0][2][0][RTW89_UK][0][73] = 127, + [1][0][2][0][RTW89_FCC][1][76] = 34, + [1][0][2][0][RTW89_FCC][2][76] = 66, + [1][0][2][0][RTW89_ETSI][1][76] = 127, + [1][0][2][0][RTW89_ETSI][0][76] = 127, + [1][0][2][0][RTW89_MKK][1][76] = 127, + [1][0][2][0][RTW89_MKK][0][76] = 127, + [1][0][2][0][RTW89_IC][1][76] = 34, + [1][0][2][0][RTW89_KCC][1][76] = 40, + [1][0][2][0][RTW89_KCC][0][76] = 127, + [1][0][2][0][RTW89_ACMA][1][76] = 127, + [1][0][2][0][RTW89_ACMA][0][76] = 127, + [1][0][2][0][RTW89_CHILE][1][76] = 34, + [1][0][2][0][RTW89_QATAR][1][76] = 127, + [1][0][2][0][RTW89_QATAR][0][76] = 127, + [1][0][2][0][RTW89_UK][1][76] = 127, + [1][0][2][0][RTW89_UK][0][76] = 127, + [1][0][2][0][RTW89_FCC][1][80] = 34, + [1][0][2][0][RTW89_FCC][2][80] = 66, + [1][0][2][0][RTW89_ETSI][1][80] = 127, + [1][0][2][0][RTW89_ETSI][0][80] = 127, + [1][0][2][0][RTW89_MKK][1][80] = 127, + [1][0][2][0][RTW89_MKK][0][80] = 127, + [1][0][2][0][RTW89_IC][1][80] = 34, + [1][0][2][0][RTW89_KCC][1][80] = 42, + [1][0][2][0][RTW89_KCC][0][80] = 127, + [1][0][2][0][RTW89_ACMA][1][80] = 127, + [1][0][2][0][RTW89_ACMA][0][80] = 127, + [1][0][2][0][RTW89_CHILE][1][80] = 34, + [1][0][2][0][RTW89_QATAR][1][80] = 127, + [1][0][2][0][RTW89_QATAR][0][80] = 127, + [1][0][2][0][RTW89_UK][1][80] = 127, + [1][0][2][0][RTW89_UK][0][80] = 127, + [1][0][2][0][RTW89_FCC][1][84] = 34, + [1][0][2][0][RTW89_FCC][2][84] = 66, + [1][0][2][0][RTW89_ETSI][1][84] = 127, + [1][0][2][0][RTW89_ETSI][0][84] = 127, + [1][0][2][0][RTW89_MKK][1][84] = 127, + [1][0][2][0][RTW89_MKK][0][84] = 127, + [1][0][2][0][RTW89_IC][1][84] = 34, + [1][0][2][0][RTW89_KCC][1][84] = 42, + [1][0][2][0][RTW89_KCC][0][84] = 127, + [1][0][2][0][RTW89_ACMA][1][84] = 127, + [1][0][2][0][RTW89_ACMA][0][84] = 127, + [1][0][2][0][RTW89_CHILE][1][84] = 34, + [1][0][2][0][RTW89_QATAR][1][84] = 127, + [1][0][2][0][RTW89_QATAR][0][84] = 127, + [1][0][2][0][RTW89_UK][1][84] = 127, + [1][0][2][0][RTW89_UK][0][84] = 127, + [1][0][2][0][RTW89_FCC][1][88] = 34, + [1][0][2][0][RTW89_FCC][2][88] = 127, + [1][0][2][0][RTW89_ETSI][1][88] = 127, + [1][0][2][0][RTW89_ETSI][0][88] = 127, + [1][0][2][0][RTW89_MKK][1][88] = 127, + [1][0][2][0][RTW89_MKK][0][88] = 127, + [1][0][2][0][RTW89_IC][1][88] = 34, + [1][0][2][0][RTW89_KCC][1][88] = 42, + [1][0][2][0][RTW89_KCC][0][88] = 127, + [1][0][2][0][RTW89_ACMA][1][88] = 127, + [1][0][2][0][RTW89_ACMA][0][88] = 127, + [1][0][2][0][RTW89_CHILE][1][88] = 34, + [1][0][2][0][RTW89_QATAR][1][88] = 127, + [1][0][2][0][RTW89_QATAR][0][88] = 127, + [1][0][2][0][RTW89_UK][1][88] = 127, + [1][0][2][0][RTW89_UK][0][88] = 127, + [1][0][2][0][RTW89_FCC][1][91] = 36, + [1][0][2][0][RTW89_FCC][2][91] = 127, + [1][0][2][0][RTW89_ETSI][1][91] = 127, + [1][0][2][0][RTW89_ETSI][0][91] = 127, + [1][0][2][0][RTW89_MKK][1][91] = 127, + [1][0][2][0][RTW89_MKK][0][91] = 127, + [1][0][2][0][RTW89_IC][1][91] = 36, + [1][0][2][0][RTW89_KCC][1][91] = 42, + [1][0][2][0][RTW89_KCC][0][91] = 127, + [1][0][2][0][RTW89_ACMA][1][91] = 127, + [1][0][2][0][RTW89_ACMA][0][91] = 127, + [1][0][2][0][RTW89_CHILE][1][91] = 36, + [1][0][2][0][RTW89_QATAR][1][91] = 127, + [1][0][2][0][RTW89_QATAR][0][91] = 127, + [1][0][2][0][RTW89_UK][1][91] = 127, + [1][0][2][0][RTW89_UK][0][91] = 127, + [1][0][2][0][RTW89_FCC][1][95] = 34, + [1][0][2][0][RTW89_FCC][2][95] = 127, + [1][0][2][0][RTW89_ETSI][1][95] = 127, + [1][0][2][0][RTW89_ETSI][0][95] = 127, + [1][0][2][0][RTW89_MKK][1][95] = 127, + [1][0][2][0][RTW89_MKK][0][95] = 127, + [1][0][2][0][RTW89_IC][1][95] = 34, + [1][0][2][0][RTW89_KCC][1][95] = 42, + [1][0][2][0][RTW89_KCC][0][95] = 127, + [1][0][2][0][RTW89_ACMA][1][95] = 127, + [1][0][2][0][RTW89_ACMA][0][95] = 127, + [1][0][2][0][RTW89_CHILE][1][95] = 34, + [1][0][2][0][RTW89_QATAR][1][95] = 127, + [1][0][2][0][RTW89_QATAR][0][95] = 127, + [1][0][2][0][RTW89_UK][1][95] = 127, + [1][0][2][0][RTW89_UK][0][95] = 127, + [1][0][2][0][RTW89_FCC][1][99] = 34, + [1][0][2][0][RTW89_FCC][2][99] = 127, + [1][0][2][0][RTW89_ETSI][1][99] = 127, + [1][0][2][0][RTW89_ETSI][0][99] = 127, + [1][0][2][0][RTW89_MKK][1][99] = 127, + [1][0][2][0][RTW89_MKK][0][99] = 127, + [1][0][2][0][RTW89_IC][1][99] = 34, + [1][0][2][0][RTW89_KCC][1][99] = 42, + [1][0][2][0][RTW89_KCC][0][99] = 127, + [1][0][2][0][RTW89_ACMA][1][99] = 127, + [1][0][2][0][RTW89_ACMA][0][99] = 127, + [1][0][2][0][RTW89_CHILE][1][99] = 34, + [1][0][2][0][RTW89_QATAR][1][99] = 127, + [1][0][2][0][RTW89_QATAR][0][99] = 127, + [1][0][2][0][RTW89_UK][1][99] = 127, + [1][0][2][0][RTW89_UK][0][99] = 127, + [1][0][2][0][RTW89_FCC][1][103] = 34, + [1][0][2][0][RTW89_FCC][2][103] = 127, + [1][0][2][0][RTW89_ETSI][1][103] = 127, + [1][0][2][0][RTW89_ETSI][0][103] = 127, + [1][0][2][0][RTW89_MKK][1][103] = 127, + [1][0][2][0][RTW89_MKK][0][103] = 127, + [1][0][2][0][RTW89_IC][1][103] = 34, + [1][0][2][0][RTW89_KCC][1][103] = 42, + [1][0][2][0][RTW89_KCC][0][103] = 127, + [1][0][2][0][RTW89_ACMA][1][103] = 127, + [1][0][2][0][RTW89_ACMA][0][103] = 127, + [1][0][2][0][RTW89_CHILE][1][103] = 34, + [1][0][2][0][RTW89_QATAR][1][103] = 127, + [1][0][2][0][RTW89_QATAR][0][103] = 127, + [1][0][2][0][RTW89_UK][1][103] = 127, + [1][0][2][0][RTW89_UK][0][103] = 127, + [1][0][2][0][RTW89_FCC][1][106] = 36, + [1][0][2][0][RTW89_FCC][2][106] = 127, + [1][0][2][0][RTW89_ETSI][1][106] = 127, + [1][0][2][0][RTW89_ETSI][0][106] = 127, + [1][0][2][0][RTW89_MKK][1][106] = 127, + [1][0][2][0][RTW89_MKK][0][106] = 127, + [1][0][2][0][RTW89_IC][1][106] = 36, + [1][0][2][0][RTW89_KCC][1][106] = 42, + [1][0][2][0][RTW89_KCC][0][106] = 127, + [1][0][2][0][RTW89_ACMA][1][106] = 127, + [1][0][2][0][RTW89_ACMA][0][106] = 127, + [1][0][2][0][RTW89_CHILE][1][106] = 36, + [1][0][2][0][RTW89_QATAR][1][106] = 127, + [1][0][2][0][RTW89_QATAR][0][106] = 127, + [1][0][2][0][RTW89_UK][1][106] = 127, + [1][0][2][0][RTW89_UK][0][106] = 127, + [1][0][2][0][RTW89_FCC][1][110] = 127, + [1][0][2][0][RTW89_FCC][2][110] = 127, + [1][0][2][0][RTW89_ETSI][1][110] = 127, + [1][0][2][0][RTW89_ETSI][0][110] = 127, + [1][0][2][0][RTW89_MKK][1][110] = 127, + [1][0][2][0][RTW89_MKK][0][110] = 127, + [1][0][2][0][RTW89_IC][1][110] = 127, + [1][0][2][0][RTW89_KCC][1][110] = 127, + [1][0][2][0][RTW89_KCC][0][110] = 127, + [1][0][2][0][RTW89_ACMA][1][110] = 127, + [1][0][2][0][RTW89_ACMA][0][110] = 127, + [1][0][2][0][RTW89_CHILE][1][110] = 127, + [1][0][2][0][RTW89_QATAR][1][110] = 127, + [1][0][2][0][RTW89_QATAR][0][110] = 127, + [1][0][2][0][RTW89_UK][1][110] = 127, + [1][0][2][0][RTW89_UK][0][110] = 127, + [1][0][2][0][RTW89_FCC][1][114] = 127, + [1][0][2][0][RTW89_FCC][2][114] = 127, + [1][0][2][0][RTW89_ETSI][1][114] = 127, + [1][0][2][0][RTW89_ETSI][0][114] = 127, + [1][0][2][0][RTW89_MKK][1][114] = 127, + [1][0][2][0][RTW89_MKK][0][114] = 127, + [1][0][2][0][RTW89_IC][1][114] = 127, + [1][0][2][0][RTW89_KCC][1][114] = 127, + [1][0][2][0][RTW89_KCC][0][114] = 127, + [1][0][2][0][RTW89_ACMA][1][114] = 127, + [1][0][2][0][RTW89_ACMA][0][114] = 127, + [1][0][2][0][RTW89_CHILE][1][114] = 127, + [1][0][2][0][RTW89_QATAR][1][114] = 127, + [1][0][2][0][RTW89_QATAR][0][114] = 127, + [1][0][2][0][RTW89_UK][1][114] = 127, + [1][0][2][0][RTW89_UK][0][114] = 127, + [1][0][2][0][RTW89_FCC][1][118] = 127, + [1][0][2][0][RTW89_FCC][2][118] = 127, + [1][0][2][0][RTW89_ETSI][1][118] = 127, + [1][0][2][0][RTW89_ETSI][0][118] = 127, + [1][0][2][0][RTW89_MKK][1][118] = 127, + [1][0][2][0][RTW89_MKK][0][118] = 127, + [1][0][2][0][RTW89_IC][1][118] = 127, + [1][0][2][0][RTW89_KCC][1][118] = 127, + [1][0][2][0][RTW89_KCC][0][118] = 127, + [1][0][2][0][RTW89_ACMA][1][118] = 127, + [1][0][2][0][RTW89_ACMA][0][118] = 127, + [1][0][2][0][RTW89_CHILE][1][118] = 127, + [1][0][2][0][RTW89_QATAR][1][118] = 127, + [1][0][2][0][RTW89_QATAR][0][118] = 127, + [1][0][2][0][RTW89_UK][1][118] = 127, + [1][0][2][0][RTW89_UK][0][118] = 127, + [1][1][2][0][RTW89_FCC][1][1] = 10, + [1][1][2][0][RTW89_FCC][2][1] = 58, + [1][1][2][0][RTW89_ETSI][1][1] = 54, + [1][1][2][0][RTW89_ETSI][0][1] = 18, + [1][1][2][0][RTW89_MKK][1][1] = 52, + [1][1][2][0][RTW89_MKK][0][1] = 12, + [1][1][2][0][RTW89_IC][1][1] = 10, + [1][1][2][0][RTW89_KCC][1][1] = 28, + [1][1][2][0][RTW89_KCC][0][1] = 12, + [1][1][2][0][RTW89_ACMA][1][1] = 54, + [1][1][2][0][RTW89_ACMA][0][1] = 18, + [1][1][2][0][RTW89_CHILE][1][1] = 10, + [1][1][2][0][RTW89_QATAR][1][1] = 54, + [1][1][2][0][RTW89_QATAR][0][1] = 18, + [1][1][2][0][RTW89_UK][1][1] = 54, + [1][1][2][0][RTW89_UK][0][1] = 18, + [1][1][2][0][RTW89_FCC][1][5] = 10, + [1][1][2][0][RTW89_FCC][2][5] = 58, + [1][1][2][0][RTW89_ETSI][1][5] = 54, + [1][1][2][0][RTW89_ETSI][0][5] = 16, + [1][1][2][0][RTW89_MKK][1][5] = 52, + [1][1][2][0][RTW89_MKK][0][5] = 12, + [1][1][2][0][RTW89_IC][1][5] = 10, + [1][1][2][0][RTW89_KCC][1][5] = 28, + [1][1][2][0][RTW89_KCC][0][5] = 12, + [1][1][2][0][RTW89_ACMA][1][5] = 54, + [1][1][2][0][RTW89_ACMA][0][5] = 16, + [1][1][2][0][RTW89_CHILE][1][5] = 10, + [1][1][2][0][RTW89_QATAR][1][5] = 54, + [1][1][2][0][RTW89_QATAR][0][5] = 16, + [1][1][2][0][RTW89_UK][1][5] = 54, + [1][1][2][0][RTW89_UK][0][5] = 16, + [1][1][2][0][RTW89_FCC][1][9] = 10, + [1][1][2][0][RTW89_FCC][2][9] = 58, + [1][1][2][0][RTW89_ETSI][1][9] = 54, + [1][1][2][0][RTW89_ETSI][0][9] = 16, + [1][1][2][0][RTW89_MKK][1][9] = 52, + [1][1][2][0][RTW89_MKK][0][9] = 12, + [1][1][2][0][RTW89_IC][1][9] = 10, + [1][1][2][0][RTW89_KCC][1][9] = 28, + [1][1][2][0][RTW89_KCC][0][9] = 12, + [1][1][2][0][RTW89_ACMA][1][9] = 54, + [1][1][2][0][RTW89_ACMA][0][9] = 16, + [1][1][2][0][RTW89_CHILE][1][9] = 10, + [1][1][2][0][RTW89_QATAR][1][9] = 54, + [1][1][2][0][RTW89_QATAR][0][9] = 16, + [1][1][2][0][RTW89_UK][1][9] = 54, + [1][1][2][0][RTW89_UK][0][9] = 16, + [1][1][2][0][RTW89_FCC][1][13] = 10, + [1][1][2][0][RTW89_FCC][2][13] = 58, + [1][1][2][0][RTW89_ETSI][1][13] = 54, + [1][1][2][0][RTW89_ETSI][0][13] = 16, + [1][1][2][0][RTW89_MKK][1][13] = 52, + [1][1][2][0][RTW89_MKK][0][13] = 12, + [1][1][2][0][RTW89_IC][1][13] = 10, + [1][1][2][0][RTW89_KCC][1][13] = 28, + [1][1][2][0][RTW89_KCC][0][13] = 12, + [1][1][2][0][RTW89_ACMA][1][13] = 54, + [1][1][2][0][RTW89_ACMA][0][13] = 16, + [1][1][2][0][RTW89_CHILE][1][13] = 10, + [1][1][2][0][RTW89_QATAR][1][13] = 54, + [1][1][2][0][RTW89_QATAR][0][13] = 16, + [1][1][2][0][RTW89_UK][1][13] = 54, + [1][1][2][0][RTW89_UK][0][13] = 16, + [1][1][2][0][RTW89_FCC][1][16] = 10, + [1][1][2][0][RTW89_FCC][2][16] = 58, + [1][1][2][0][RTW89_ETSI][1][16] = 54, + [1][1][2][0][RTW89_ETSI][0][16] = 16, + [1][1][2][0][RTW89_MKK][1][16] = 52, + [1][1][2][0][RTW89_MKK][0][16] = 12, + [1][1][2][0][RTW89_IC][1][16] = 10, + [1][1][2][0][RTW89_KCC][1][16] = 28, + [1][1][2][0][RTW89_KCC][0][16] = 12, + [1][1][2][0][RTW89_ACMA][1][16] = 54, + [1][1][2][0][RTW89_ACMA][0][16] = 16, + [1][1][2][0][RTW89_CHILE][1][16] = 10, + [1][1][2][0][RTW89_QATAR][1][16] = 54, + [1][1][2][0][RTW89_QATAR][0][16] = 16, + [1][1][2][0][RTW89_UK][1][16] = 54, + [1][1][2][0][RTW89_UK][0][16] = 16, + [1][1][2][0][RTW89_FCC][1][20] = 10, + [1][1][2][0][RTW89_FCC][2][20] = 58, + [1][1][2][0][RTW89_ETSI][1][20] = 54, + [1][1][2][0][RTW89_ETSI][0][20] = 16, + [1][1][2][0][RTW89_MKK][1][20] = 52, + [1][1][2][0][RTW89_MKK][0][20] = 12, + [1][1][2][0][RTW89_IC][1][20] = 10, + [1][1][2][0][RTW89_KCC][1][20] = 28, + [1][1][2][0][RTW89_KCC][0][20] = 12, + [1][1][2][0][RTW89_ACMA][1][20] = 54, + [1][1][2][0][RTW89_ACMA][0][20] = 16, + [1][1][2][0][RTW89_CHILE][1][20] = 10, + [1][1][2][0][RTW89_QATAR][1][20] = 54, + [1][1][2][0][RTW89_QATAR][0][20] = 16, + [1][1][2][0][RTW89_UK][1][20] = 54, + [1][1][2][0][RTW89_UK][0][20] = 16, + [1][1][2][0][RTW89_FCC][1][24] = 10, + [1][1][2][0][RTW89_FCC][2][24] = 70, + [1][1][2][0][RTW89_ETSI][1][24] = 54, + [1][1][2][0][RTW89_ETSI][0][24] = 16, + [1][1][2][0][RTW89_MKK][1][24] = 54, + [1][1][2][0][RTW89_MKK][0][24] = 14, + [1][1][2][0][RTW89_IC][1][24] = 10, + [1][1][2][0][RTW89_KCC][1][24] = 28, + [1][1][2][0][RTW89_KCC][0][24] = 12, + [1][1][2][0][RTW89_ACMA][1][24] = 54, + [1][1][2][0][RTW89_ACMA][0][24] = 16, + [1][1][2][0][RTW89_CHILE][1][24] = 10, + [1][1][2][0][RTW89_QATAR][1][24] = 54, + [1][1][2][0][RTW89_QATAR][0][24] = 16, + [1][1][2][0][RTW89_UK][1][24] = 54, + [1][1][2][0][RTW89_UK][0][24] = 16, + [1][1][2][0][RTW89_FCC][1][28] = 10, + [1][1][2][0][RTW89_FCC][2][28] = 70, + [1][1][2][0][RTW89_ETSI][1][28] = 54, + [1][1][2][0][RTW89_ETSI][0][28] = 16, + [1][1][2][0][RTW89_MKK][1][28] = 52, + [1][1][2][0][RTW89_MKK][0][28] = 14, + [1][1][2][0][RTW89_IC][1][28] = 10, + [1][1][2][0][RTW89_KCC][1][28] = 28, + [1][1][2][0][RTW89_KCC][0][28] = 14, + [1][1][2][0][RTW89_ACMA][1][28] = 54, + [1][1][2][0][RTW89_ACMA][0][28] = 16, + [1][1][2][0][RTW89_CHILE][1][28] = 10, + [1][1][2][0][RTW89_QATAR][1][28] = 54, + [1][1][2][0][RTW89_QATAR][0][28] = 16, + [1][1][2][0][RTW89_UK][1][28] = 54, + [1][1][2][0][RTW89_UK][0][28] = 16, + [1][1][2][0][RTW89_FCC][1][31] = 10, + [1][1][2][0][RTW89_FCC][2][31] = 70, + [1][1][2][0][RTW89_ETSI][1][31] = 54, + [1][1][2][0][RTW89_ETSI][0][31] = 16, + [1][1][2][0][RTW89_MKK][1][31] = 52, + [1][1][2][0][RTW89_MKK][0][31] = 14, + [1][1][2][0][RTW89_IC][1][31] = 10, + [1][1][2][0][RTW89_KCC][1][31] = 28, + [1][1][2][0][RTW89_KCC][0][31] = 14, + [1][1][2][0][RTW89_ACMA][1][31] = 54, + [1][1][2][0][RTW89_ACMA][0][31] = 16, + [1][1][2][0][RTW89_CHILE][1][31] = 10, + [1][1][2][0][RTW89_QATAR][1][31] = 54, + [1][1][2][0][RTW89_QATAR][0][31] = 16, + [1][1][2][0][RTW89_UK][1][31] = 54, + [1][1][2][0][RTW89_UK][0][31] = 16, + [1][1][2][0][RTW89_FCC][1][35] = 10, + [1][1][2][0][RTW89_FCC][2][35] = 70, + [1][1][2][0][RTW89_ETSI][1][35] = 54, + [1][1][2][0][RTW89_ETSI][0][35] = 16, + [1][1][2][0][RTW89_MKK][1][35] = 52, + [1][1][2][0][RTW89_MKK][0][35] = 14, + [1][1][2][0][RTW89_IC][1][35] = 10, + [1][1][2][0][RTW89_KCC][1][35] = 28, + [1][1][2][0][RTW89_KCC][0][35] = 14, + [1][1][2][0][RTW89_ACMA][1][35] = 54, + [1][1][2][0][RTW89_ACMA][0][35] = 16, + [1][1][2][0][RTW89_CHILE][1][35] = 10, + [1][1][2][0][RTW89_QATAR][1][35] = 54, + [1][1][2][0][RTW89_QATAR][0][35] = 16, + [1][1][2][0][RTW89_UK][1][35] = 54, + [1][1][2][0][RTW89_UK][0][35] = 16, + [1][1][2][0][RTW89_FCC][1][39] = 10, + [1][1][2][0][RTW89_FCC][2][39] = 70, + [1][1][2][0][RTW89_ETSI][1][39] = 54, + [1][1][2][0][RTW89_ETSI][0][39] = 16, + [1][1][2][0][RTW89_MKK][1][39] = 52, + [1][1][2][0][RTW89_MKK][0][39] = 14, + [1][1][2][0][RTW89_IC][1][39] = 10, + [1][1][2][0][RTW89_KCC][1][39] = 28, + [1][1][2][0][RTW89_KCC][0][39] = 14, + [1][1][2][0][RTW89_ACMA][1][39] = 54, + [1][1][2][0][RTW89_ACMA][0][39] = 16, + [1][1][2][0][RTW89_CHILE][1][39] = 10, + [1][1][2][0][RTW89_QATAR][1][39] = 54, + [1][1][2][0][RTW89_QATAR][0][39] = 16, + [1][1][2][0][RTW89_UK][1][39] = 54, + [1][1][2][0][RTW89_UK][0][39] = 16, + [1][1][2][0][RTW89_FCC][1][43] = 10, + [1][1][2][0][RTW89_FCC][2][43] = 70, + [1][1][2][0][RTW89_ETSI][1][43] = 54, + [1][1][2][0][RTW89_ETSI][0][43] = 16, + [1][1][2][0][RTW89_MKK][1][43] = 52, + [1][1][2][0][RTW89_MKK][0][43] = 14, + [1][1][2][0][RTW89_IC][1][43] = 10, + [1][1][2][0][RTW89_KCC][1][43] = 28, + [1][1][2][0][RTW89_KCC][0][43] = 14, + [1][1][2][0][RTW89_ACMA][1][43] = 54, + [1][1][2][0][RTW89_ACMA][0][43] = 16, + [1][1][2][0][RTW89_CHILE][1][43] = 10, + [1][1][2][0][RTW89_QATAR][1][43] = 54, + [1][1][2][0][RTW89_QATAR][0][43] = 16, + [1][1][2][0][RTW89_UK][1][43] = 54, + [1][1][2][0][RTW89_UK][0][43] = 16, + [1][1][2][0][RTW89_FCC][1][46] = 12, + [1][1][2][0][RTW89_FCC][2][46] = 127, + [1][1][2][0][RTW89_ETSI][1][46] = 127, + [1][1][2][0][RTW89_ETSI][0][46] = 127, + [1][1][2][0][RTW89_MKK][1][46] = 127, + [1][1][2][0][RTW89_MKK][0][46] = 127, + [1][1][2][0][RTW89_IC][1][46] = 12, + [1][1][2][0][RTW89_KCC][1][46] = 28, + [1][1][2][0][RTW89_KCC][0][46] = 127, + [1][1][2][0][RTW89_ACMA][1][46] = 127, + [1][1][2][0][RTW89_ACMA][0][46] = 127, + [1][1][2][0][RTW89_CHILE][1][46] = 12, + [1][1][2][0][RTW89_QATAR][1][46] = 127, + [1][1][2][0][RTW89_QATAR][0][46] = 127, + [1][1][2][0][RTW89_UK][1][46] = 127, + [1][1][2][0][RTW89_UK][0][46] = 127, + [1][1][2][0][RTW89_FCC][1][50] = 12, + [1][1][2][0][RTW89_FCC][2][50] = 127, + [1][1][2][0][RTW89_ETSI][1][50] = 127, + [1][1][2][0][RTW89_ETSI][0][50] = 127, + [1][1][2][0][RTW89_MKK][1][50] = 127, + [1][1][2][0][RTW89_MKK][0][50] = 127, + [1][1][2][0][RTW89_IC][1][50] = 12, + [1][1][2][0][RTW89_KCC][1][50] = 28, + [1][1][2][0][RTW89_KCC][0][50] = 127, + [1][1][2][0][RTW89_ACMA][1][50] = 127, + [1][1][2][0][RTW89_ACMA][0][50] = 127, + [1][1][2][0][RTW89_CHILE][1][50] = 12, + [1][1][2][0][RTW89_QATAR][1][50] = 127, + [1][1][2][0][RTW89_QATAR][0][50] = 127, + [1][1][2][0][RTW89_UK][1][50] = 127, + [1][1][2][0][RTW89_UK][0][50] = 127, + [1][1][2][0][RTW89_FCC][1][54] = 10, + [1][1][2][0][RTW89_FCC][2][54] = 127, + [1][1][2][0][RTW89_ETSI][1][54] = 127, + [1][1][2][0][RTW89_ETSI][0][54] = 127, + [1][1][2][0][RTW89_MKK][1][54] = 127, + [1][1][2][0][RTW89_MKK][0][54] = 127, + [1][1][2][0][RTW89_IC][1][54] = 10, + [1][1][2][0][RTW89_KCC][1][54] = 28, + [1][1][2][0][RTW89_KCC][0][54] = 127, + [1][1][2][0][RTW89_ACMA][1][54] = 127, + [1][1][2][0][RTW89_ACMA][0][54] = 127, + [1][1][2][0][RTW89_CHILE][1][54] = 10, + [1][1][2][0][RTW89_QATAR][1][54] = 127, + [1][1][2][0][RTW89_QATAR][0][54] = 127, + [1][1][2][0][RTW89_UK][1][54] = 127, + [1][1][2][0][RTW89_UK][0][54] = 127, + [1][1][2][0][RTW89_FCC][1][58] = 10, + [1][1][2][0][RTW89_FCC][2][58] = 66, + [1][1][2][0][RTW89_ETSI][1][58] = 127, + [1][1][2][0][RTW89_ETSI][0][58] = 127, + [1][1][2][0][RTW89_MKK][1][58] = 127, + [1][1][2][0][RTW89_MKK][0][58] = 127, + [1][1][2][0][RTW89_IC][1][58] = 10, + [1][1][2][0][RTW89_KCC][1][58] = 28, + [1][1][2][0][RTW89_KCC][0][58] = 127, + [1][1][2][0][RTW89_ACMA][1][58] = 127, + [1][1][2][0][RTW89_ACMA][0][58] = 127, + [1][1][2][0][RTW89_CHILE][1][58] = 10, + [1][1][2][0][RTW89_QATAR][1][58] = 127, + [1][1][2][0][RTW89_QATAR][0][58] = 127, + [1][1][2][0][RTW89_UK][1][58] = 127, + [1][1][2][0][RTW89_UK][0][58] = 127, + [1][1][2][0][RTW89_FCC][1][61] = 10, + [1][1][2][0][RTW89_FCC][2][61] = 66, + [1][1][2][0][RTW89_ETSI][1][61] = 127, + [1][1][2][0][RTW89_ETSI][0][61] = 127, + [1][1][2][0][RTW89_MKK][1][61] = 127, + [1][1][2][0][RTW89_MKK][0][61] = 127, + [1][1][2][0][RTW89_IC][1][61] = 10, + [1][1][2][0][RTW89_KCC][1][61] = 28, + [1][1][2][0][RTW89_KCC][0][61] = 127, + [1][1][2][0][RTW89_ACMA][1][61] = 127, + [1][1][2][0][RTW89_ACMA][0][61] = 127, + [1][1][2][0][RTW89_CHILE][1][61] = 10, + [1][1][2][0][RTW89_QATAR][1][61] = 127, + [1][1][2][0][RTW89_QATAR][0][61] = 127, + [1][1][2][0][RTW89_UK][1][61] = 127, + [1][1][2][0][RTW89_UK][0][61] = 127, + [1][1][2][0][RTW89_FCC][1][65] = 10, + [1][1][2][0][RTW89_FCC][2][65] = 66, + [1][1][2][0][RTW89_ETSI][1][65] = 127, + [1][1][2][0][RTW89_ETSI][0][65] = 127, + [1][1][2][0][RTW89_MKK][1][65] = 127, + [1][1][2][0][RTW89_MKK][0][65] = 127, + [1][1][2][0][RTW89_IC][1][65] = 10, + [1][1][2][0][RTW89_KCC][1][65] = 28, + [1][1][2][0][RTW89_KCC][0][65] = 127, + [1][1][2][0][RTW89_ACMA][1][65] = 127, + [1][1][2][0][RTW89_ACMA][0][65] = 127, + [1][1][2][0][RTW89_CHILE][1][65] = 10, + [1][1][2][0][RTW89_QATAR][1][65] = 127, + [1][1][2][0][RTW89_QATAR][0][65] = 127, + [1][1][2][0][RTW89_UK][1][65] = 127, + [1][1][2][0][RTW89_UK][0][65] = 127, + [1][1][2][0][RTW89_FCC][1][69] = 10, + [1][1][2][0][RTW89_FCC][2][69] = 66, + [1][1][2][0][RTW89_ETSI][1][69] = 127, + [1][1][2][0][RTW89_ETSI][0][69] = 127, + [1][1][2][0][RTW89_MKK][1][69] = 127, + [1][1][2][0][RTW89_MKK][0][69] = 127, + [1][1][2][0][RTW89_IC][1][69] = 10, + [1][1][2][0][RTW89_KCC][1][69] = 28, + [1][1][2][0][RTW89_KCC][0][69] = 127, + [1][1][2][0][RTW89_ACMA][1][69] = 127, + [1][1][2][0][RTW89_ACMA][0][69] = 127, + [1][1][2][0][RTW89_CHILE][1][69] = 10, + [1][1][2][0][RTW89_QATAR][1][69] = 127, + [1][1][2][0][RTW89_QATAR][0][69] = 127, + [1][1][2][0][RTW89_UK][1][69] = 127, + [1][1][2][0][RTW89_UK][0][69] = 127, + [1][1][2][0][RTW89_FCC][1][73] = 10, + [1][1][2][0][RTW89_FCC][2][73] = 66, + [1][1][2][0][RTW89_ETSI][1][73] = 127, + [1][1][2][0][RTW89_ETSI][0][73] = 127, + [1][1][2][0][RTW89_MKK][1][73] = 127, + [1][1][2][0][RTW89_MKK][0][73] = 127, + [1][1][2][0][RTW89_IC][1][73] = 10, + [1][1][2][0][RTW89_KCC][1][73] = 28, + [1][1][2][0][RTW89_KCC][0][73] = 127, + [1][1][2][0][RTW89_ACMA][1][73] = 127, + [1][1][2][0][RTW89_ACMA][0][73] = 127, + [1][1][2][0][RTW89_CHILE][1][73] = 10, + [1][1][2][0][RTW89_QATAR][1][73] = 127, + [1][1][2][0][RTW89_QATAR][0][73] = 127, + [1][1][2][0][RTW89_UK][1][73] = 127, + [1][1][2][0][RTW89_UK][0][73] = 127, + [1][1][2][0][RTW89_FCC][1][76] = 10, + [1][1][2][0][RTW89_FCC][2][76] = 66, + [1][1][2][0][RTW89_ETSI][1][76] = 127, + [1][1][2][0][RTW89_ETSI][0][76] = 127, + [1][1][2][0][RTW89_MKK][1][76] = 127, + [1][1][2][0][RTW89_MKK][0][76] = 127, + [1][1][2][0][RTW89_IC][1][76] = 10, + [1][1][2][0][RTW89_KCC][1][76] = 28, + [1][1][2][0][RTW89_KCC][0][76] = 127, + [1][1][2][0][RTW89_ACMA][1][76] = 127, + [1][1][2][0][RTW89_ACMA][0][76] = 127, + [1][1][2][0][RTW89_CHILE][1][76] = 10, + [1][1][2][0][RTW89_QATAR][1][76] = 127, + [1][1][2][0][RTW89_QATAR][0][76] = 127, + [1][1][2][0][RTW89_UK][1][76] = 127, + [1][1][2][0][RTW89_UK][0][76] = 127, + [1][1][2][0][RTW89_FCC][1][80] = 10, + [1][1][2][0][RTW89_FCC][2][80] = 66, + [1][1][2][0][RTW89_ETSI][1][80] = 127, + [1][1][2][0][RTW89_ETSI][0][80] = 127, + [1][1][2][0][RTW89_MKK][1][80] = 127, + [1][1][2][0][RTW89_MKK][0][80] = 127, + [1][1][2][0][RTW89_IC][1][80] = 10, + [1][1][2][0][RTW89_KCC][1][80] = 32, + [1][1][2][0][RTW89_KCC][0][80] = 127, + [1][1][2][0][RTW89_ACMA][1][80] = 127, + [1][1][2][0][RTW89_ACMA][0][80] = 127, + [1][1][2][0][RTW89_CHILE][1][80] = 10, + [1][1][2][0][RTW89_QATAR][1][80] = 127, + [1][1][2][0][RTW89_QATAR][0][80] = 127, + [1][1][2][0][RTW89_UK][1][80] = 127, + [1][1][2][0][RTW89_UK][0][80] = 127, + [1][1][2][0][RTW89_FCC][1][84] = 10, + [1][1][2][0][RTW89_FCC][2][84] = 66, + [1][1][2][0][RTW89_ETSI][1][84] = 127, + [1][1][2][0][RTW89_ETSI][0][84] = 127, + [1][1][2][0][RTW89_MKK][1][84] = 127, + [1][1][2][0][RTW89_MKK][0][84] = 127, + [1][1][2][0][RTW89_IC][1][84] = 10, + [1][1][2][0][RTW89_KCC][1][84] = 32, + [1][1][2][0][RTW89_KCC][0][84] = 127, + [1][1][2][0][RTW89_ACMA][1][84] = 127, + [1][1][2][0][RTW89_ACMA][0][84] = 127, + [1][1][2][0][RTW89_CHILE][1][84] = 10, + [1][1][2][0][RTW89_QATAR][1][84] = 127, + [1][1][2][0][RTW89_QATAR][0][84] = 127, + [1][1][2][0][RTW89_UK][1][84] = 127, + [1][1][2][0][RTW89_UK][0][84] = 127, + [1][1][2][0][RTW89_FCC][1][88] = 10, + [1][1][2][0][RTW89_FCC][2][88] = 127, + [1][1][2][0][RTW89_ETSI][1][88] = 127, + [1][1][2][0][RTW89_ETSI][0][88] = 127, + [1][1][2][0][RTW89_MKK][1][88] = 127, + [1][1][2][0][RTW89_MKK][0][88] = 127, + [1][1][2][0][RTW89_IC][1][88] = 10, + [1][1][2][0][RTW89_KCC][1][88] = 32, + [1][1][2][0][RTW89_KCC][0][88] = 127, + [1][1][2][0][RTW89_ACMA][1][88] = 127, + [1][1][2][0][RTW89_ACMA][0][88] = 127, + [1][1][2][0][RTW89_CHILE][1][88] = 10, + [1][1][2][0][RTW89_QATAR][1][88] = 127, + [1][1][2][0][RTW89_QATAR][0][88] = 127, + [1][1][2][0][RTW89_UK][1][88] = 127, + [1][1][2][0][RTW89_UK][0][88] = 127, + [1][1][2][0][RTW89_FCC][1][91] = 12, + [1][1][2][0][RTW89_FCC][2][91] = 127, + [1][1][2][0][RTW89_ETSI][1][91] = 127, + [1][1][2][0][RTW89_ETSI][0][91] = 127, + [1][1][2][0][RTW89_MKK][1][91] = 127, + [1][1][2][0][RTW89_MKK][0][91] = 127, + [1][1][2][0][RTW89_IC][1][91] = 12, + [1][1][2][0][RTW89_KCC][1][91] = 32, + [1][1][2][0][RTW89_KCC][0][91] = 127, + [1][1][2][0][RTW89_ACMA][1][91] = 127, + [1][1][2][0][RTW89_ACMA][0][91] = 127, + [1][1][2][0][RTW89_CHILE][1][91] = 12, + [1][1][2][0][RTW89_QATAR][1][91] = 127, + [1][1][2][0][RTW89_QATAR][0][91] = 127, + [1][1][2][0][RTW89_UK][1][91] = 127, + [1][1][2][0][RTW89_UK][0][91] = 127, + [1][1][2][0][RTW89_FCC][1][95] = 10, + [1][1][2][0][RTW89_FCC][2][95] = 127, + [1][1][2][0][RTW89_ETSI][1][95] = 127, + [1][1][2][0][RTW89_ETSI][0][95] = 127, + [1][1][2][0][RTW89_MKK][1][95] = 127, + [1][1][2][0][RTW89_MKK][0][95] = 127, + [1][1][2][0][RTW89_IC][1][95] = 10, + [1][1][2][0][RTW89_KCC][1][95] = 32, + [1][1][2][0][RTW89_KCC][0][95] = 127, + [1][1][2][0][RTW89_ACMA][1][95] = 127, + [1][1][2][0][RTW89_ACMA][0][95] = 127, + [1][1][2][0][RTW89_CHILE][1][95] = 10, + [1][1][2][0][RTW89_QATAR][1][95] = 127, + [1][1][2][0][RTW89_QATAR][0][95] = 127, + [1][1][2][0][RTW89_UK][1][95] = 127, + [1][1][2][0][RTW89_UK][0][95] = 127, + [1][1][2][0][RTW89_FCC][1][99] = 10, + [1][1][2][0][RTW89_FCC][2][99] = 127, + [1][1][2][0][RTW89_ETSI][1][99] = 127, + [1][1][2][0][RTW89_ETSI][0][99] = 127, + [1][1][2][0][RTW89_MKK][1][99] = 127, + [1][1][2][0][RTW89_MKK][0][99] = 127, + [1][1][2][0][RTW89_IC][1][99] = 10, + [1][1][2][0][RTW89_KCC][1][99] = 32, + [1][1][2][0][RTW89_KCC][0][99] = 127, + [1][1][2][0][RTW89_ACMA][1][99] = 127, + [1][1][2][0][RTW89_ACMA][0][99] = 127, + [1][1][2][0][RTW89_CHILE][1][99] = 10, + [1][1][2][0][RTW89_QATAR][1][99] = 127, + [1][1][2][0][RTW89_QATAR][0][99] = 127, + [1][1][2][0][RTW89_UK][1][99] = 127, + [1][1][2][0][RTW89_UK][0][99] = 127, + [1][1][2][0][RTW89_FCC][1][103] = 10, + [1][1][2][0][RTW89_FCC][2][103] = 127, + [1][1][2][0][RTW89_ETSI][1][103] = 127, + [1][1][2][0][RTW89_ETSI][0][103] = 127, + [1][1][2][0][RTW89_MKK][1][103] = 127, + [1][1][2][0][RTW89_MKK][0][103] = 127, + [1][1][2][0][RTW89_IC][1][103] = 10, + [1][1][2][0][RTW89_KCC][1][103] = 32, + [1][1][2][0][RTW89_KCC][0][103] = 127, + [1][1][2][0][RTW89_ACMA][1][103] = 127, + [1][1][2][0][RTW89_ACMA][0][103] = 127, + [1][1][2][0][RTW89_CHILE][1][103] = 10, + [1][1][2][0][RTW89_QATAR][1][103] = 127, + [1][1][2][0][RTW89_QATAR][0][103] = 127, + [1][1][2][0][RTW89_UK][1][103] = 127, + [1][1][2][0][RTW89_UK][0][103] = 127, + [1][1][2][0][RTW89_FCC][1][106] = 12, + [1][1][2][0][RTW89_FCC][2][106] = 127, + [1][1][2][0][RTW89_ETSI][1][106] = 127, + [1][1][2][0][RTW89_ETSI][0][106] = 127, + [1][1][2][0][RTW89_MKK][1][106] = 127, + [1][1][2][0][RTW89_MKK][0][106] = 127, + [1][1][2][0][RTW89_IC][1][106] = 12, + [1][1][2][0][RTW89_KCC][1][106] = 32, + [1][1][2][0][RTW89_KCC][0][106] = 127, + [1][1][2][0][RTW89_ACMA][1][106] = 127, + [1][1][2][0][RTW89_ACMA][0][106] = 127, + [1][1][2][0][RTW89_CHILE][1][106] = 12, + [1][1][2][0][RTW89_QATAR][1][106] = 127, + [1][1][2][0][RTW89_QATAR][0][106] = 127, + [1][1][2][0][RTW89_UK][1][106] = 127, + [1][1][2][0][RTW89_UK][0][106] = 127, + [1][1][2][0][RTW89_FCC][1][110] = 127, + [1][1][2][0][RTW89_FCC][2][110] = 127, + [1][1][2][0][RTW89_ETSI][1][110] = 127, + [1][1][2][0][RTW89_ETSI][0][110] = 127, + [1][1][2][0][RTW89_MKK][1][110] = 127, + [1][1][2][0][RTW89_MKK][0][110] = 127, + [1][1][2][0][RTW89_IC][1][110] = 127, + [1][1][2][0][RTW89_KCC][1][110] = 127, + [1][1][2][0][RTW89_KCC][0][110] = 127, + [1][1][2][0][RTW89_ACMA][1][110] = 127, + [1][1][2][0][RTW89_ACMA][0][110] = 127, + [1][1][2][0][RTW89_CHILE][1][110] = 127, + [1][1][2][0][RTW89_QATAR][1][110] = 127, + [1][1][2][0][RTW89_QATAR][0][110] = 127, + [1][1][2][0][RTW89_UK][1][110] = 127, + [1][1][2][0][RTW89_UK][0][110] = 127, + [1][1][2][0][RTW89_FCC][1][114] = 127, + [1][1][2][0][RTW89_FCC][2][114] = 127, + [1][1][2][0][RTW89_ETSI][1][114] = 127, + [1][1][2][0][RTW89_ETSI][0][114] = 127, + [1][1][2][0][RTW89_MKK][1][114] = 127, + [1][1][2][0][RTW89_MKK][0][114] = 127, + [1][1][2][0][RTW89_IC][1][114] = 127, + [1][1][2][0][RTW89_KCC][1][114] = 127, + [1][1][2][0][RTW89_KCC][0][114] = 127, + [1][1][2][0][RTW89_ACMA][1][114] = 127, + [1][1][2][0][RTW89_ACMA][0][114] = 127, + [1][1][2][0][RTW89_CHILE][1][114] = 127, + [1][1][2][0][RTW89_QATAR][1][114] = 127, + [1][1][2][0][RTW89_QATAR][0][114] = 127, + [1][1][2][0][RTW89_UK][1][114] = 127, + [1][1][2][0][RTW89_UK][0][114] = 127, + [1][1][2][0][RTW89_FCC][1][118] = 127, + [1][1][2][0][RTW89_FCC][2][118] = 127, + [1][1][2][0][RTW89_ETSI][1][118] = 127, + [1][1][2][0][RTW89_ETSI][0][118] = 127, + [1][1][2][0][RTW89_MKK][1][118] = 127, + [1][1][2][0][RTW89_MKK][0][118] = 127, + [1][1][2][0][RTW89_IC][1][118] = 127, + [1][1][2][0][RTW89_KCC][1][118] = 127, + [1][1][2][0][RTW89_KCC][0][118] = 127, + [1][1][2][0][RTW89_ACMA][1][118] = 127, + [1][1][2][0][RTW89_ACMA][0][118] = 127, + [1][1][2][0][RTW89_CHILE][1][118] = 127, + [1][1][2][0][RTW89_QATAR][1][118] = 127, + [1][1][2][0][RTW89_QATAR][0][118] = 127, + [1][1][2][0][RTW89_UK][1][118] = 127, + [1][1][2][0][RTW89_UK][0][118] = 127, + [1][1][2][1][RTW89_FCC][1][1] = 10, + [1][1][2][1][RTW89_FCC][2][1] = 58, + [1][1][2][1][RTW89_ETSI][1][1] = 42, + [1][1][2][1][RTW89_ETSI][0][1] = 6, + [1][1][2][1][RTW89_MKK][1][1] = 52, + [1][1][2][1][RTW89_MKK][0][1] = 12, + [1][1][2][1][RTW89_IC][1][1] = 10, + [1][1][2][1][RTW89_KCC][1][1] = 28, + [1][1][2][1][RTW89_KCC][0][1] = 12, + [1][1][2][1][RTW89_ACMA][1][1] = 42, + [1][1][2][1][RTW89_ACMA][0][1] = 6, + [1][1][2][1][RTW89_CHILE][1][1] = 10, + [1][1][2][1][RTW89_QATAR][1][1] = 42, + [1][1][2][1][RTW89_QATAR][0][1] = 6, + [1][1][2][1][RTW89_UK][1][1] = 42, + [1][1][2][1][RTW89_UK][0][1] = 6, + [1][1][2][1][RTW89_FCC][1][5] = 10, + [1][1][2][1][RTW89_FCC][2][5] = 58, + [1][1][2][1][RTW89_ETSI][1][5] = 42, + [1][1][2][1][RTW89_ETSI][0][5] = 6, + [1][1][2][1][RTW89_MKK][1][5] = 52, + [1][1][2][1][RTW89_MKK][0][5] = 12, + [1][1][2][1][RTW89_IC][1][5] = 10, + [1][1][2][1][RTW89_KCC][1][5] = 28, + [1][1][2][1][RTW89_KCC][0][5] = 12, + [1][1][2][1][RTW89_ACMA][1][5] = 42, + [1][1][2][1][RTW89_ACMA][0][5] = 6, + [1][1][2][1][RTW89_CHILE][1][5] = 10, + [1][1][2][1][RTW89_QATAR][1][5] = 42, + [1][1][2][1][RTW89_QATAR][0][5] = 6, + [1][1][2][1][RTW89_UK][1][5] = 42, + [1][1][2][1][RTW89_UK][0][5] = 6, + [1][1][2][1][RTW89_FCC][1][9] = 10, + [1][1][2][1][RTW89_FCC][2][9] = 58, + [1][1][2][1][RTW89_ETSI][1][9] = 42, + [1][1][2][1][RTW89_ETSI][0][9] = 6, + [1][1][2][1][RTW89_MKK][1][9] = 52, + [1][1][2][1][RTW89_MKK][0][9] = 12, + [1][1][2][1][RTW89_IC][1][9] = 10, + [1][1][2][1][RTW89_KCC][1][9] = 28, + [1][1][2][1][RTW89_KCC][0][9] = 12, + [1][1][2][1][RTW89_ACMA][1][9] = 42, + [1][1][2][1][RTW89_ACMA][0][9] = 6, + [1][1][2][1][RTW89_CHILE][1][9] = 10, + [1][1][2][1][RTW89_QATAR][1][9] = 42, + [1][1][2][1][RTW89_QATAR][0][9] = 6, + [1][1][2][1][RTW89_UK][1][9] = 42, + [1][1][2][1][RTW89_UK][0][9] = 6, + [1][1][2][1][RTW89_FCC][1][13] = 10, + [1][1][2][1][RTW89_FCC][2][13] = 58, + [1][1][2][1][RTW89_ETSI][1][13] = 42, + [1][1][2][1][RTW89_ETSI][0][13] = 6, + [1][1][2][1][RTW89_MKK][1][13] = 52, + [1][1][2][1][RTW89_MKK][0][13] = 12, + [1][1][2][1][RTW89_IC][1][13] = 10, + [1][1][2][1][RTW89_KCC][1][13] = 28, + [1][1][2][1][RTW89_KCC][0][13] = 12, + [1][1][2][1][RTW89_ACMA][1][13] = 42, + [1][1][2][1][RTW89_ACMA][0][13] = 6, + [1][1][2][1][RTW89_CHILE][1][13] = 10, + [1][1][2][1][RTW89_QATAR][1][13] = 42, + [1][1][2][1][RTW89_QATAR][0][13] = 6, + [1][1][2][1][RTW89_UK][1][13] = 42, + [1][1][2][1][RTW89_UK][0][13] = 6, + [1][1][2][1][RTW89_FCC][1][16] = 10, + [1][1][2][1][RTW89_FCC][2][16] = 58, + [1][1][2][1][RTW89_ETSI][1][16] = 42, + [1][1][2][1][RTW89_ETSI][0][16] = 6, + [1][1][2][1][RTW89_MKK][1][16] = 52, + [1][1][2][1][RTW89_MKK][0][16] = 12, + [1][1][2][1][RTW89_IC][1][16] = 10, + [1][1][2][1][RTW89_KCC][1][16] = 28, + [1][1][2][1][RTW89_KCC][0][16] = 12, + [1][1][2][1][RTW89_ACMA][1][16] = 42, + [1][1][2][1][RTW89_ACMA][0][16] = 6, + [1][1][2][1][RTW89_CHILE][1][16] = 10, + [1][1][2][1][RTW89_QATAR][1][16] = 42, + [1][1][2][1][RTW89_QATAR][0][16] = 6, + [1][1][2][1][RTW89_UK][1][16] = 42, + [1][1][2][1][RTW89_UK][0][16] = 6, + [1][1][2][1][RTW89_FCC][1][20] = 10, + [1][1][2][1][RTW89_FCC][2][20] = 58, + [1][1][2][1][RTW89_ETSI][1][20] = 42, + [1][1][2][1][RTW89_ETSI][0][20] = 6, + [1][1][2][1][RTW89_MKK][1][20] = 52, + [1][1][2][1][RTW89_MKK][0][20] = 12, + [1][1][2][1][RTW89_IC][1][20] = 10, + [1][1][2][1][RTW89_KCC][1][20] = 28, + [1][1][2][1][RTW89_KCC][0][20] = 12, + [1][1][2][1][RTW89_ACMA][1][20] = 42, + [1][1][2][1][RTW89_ACMA][0][20] = 6, + [1][1][2][1][RTW89_CHILE][1][20] = 10, + [1][1][2][1][RTW89_QATAR][1][20] = 42, + [1][1][2][1][RTW89_QATAR][0][20] = 6, + [1][1][2][1][RTW89_UK][1][20] = 42, + [1][1][2][1][RTW89_UK][0][20] = 6, + [1][1][2][1][RTW89_FCC][1][24] = 10, + [1][1][2][1][RTW89_FCC][2][24] = 70, + [1][1][2][1][RTW89_ETSI][1][24] = 42, + [1][1][2][1][RTW89_ETSI][0][24] = 6, + [1][1][2][1][RTW89_MKK][1][24] = 54, + [1][1][2][1][RTW89_MKK][0][24] = 14, + [1][1][2][1][RTW89_IC][1][24] = 10, + [1][1][2][1][RTW89_KCC][1][24] = 28, + [1][1][2][1][RTW89_KCC][0][24] = 12, + [1][1][2][1][RTW89_ACMA][1][24] = 42, + [1][1][2][1][RTW89_ACMA][0][24] = 6, + [1][1][2][1][RTW89_CHILE][1][24] = 10, + [1][1][2][1][RTW89_QATAR][1][24] = 42, + [1][1][2][1][RTW89_QATAR][0][24] = 6, + [1][1][2][1][RTW89_UK][1][24] = 42, + [1][1][2][1][RTW89_UK][0][24] = 6, + [1][1][2][1][RTW89_FCC][1][28] = 10, + [1][1][2][1][RTW89_FCC][2][28] = 70, + [1][1][2][1][RTW89_ETSI][1][28] = 42, + [1][1][2][1][RTW89_ETSI][0][28] = 6, + [1][1][2][1][RTW89_MKK][1][28] = 52, + [1][1][2][1][RTW89_MKK][0][28] = 14, + [1][1][2][1][RTW89_IC][1][28] = 10, + [1][1][2][1][RTW89_KCC][1][28] = 28, + [1][1][2][1][RTW89_KCC][0][28] = 14, + [1][1][2][1][RTW89_ACMA][1][28] = 42, + [1][1][2][1][RTW89_ACMA][0][28] = 6, + [1][1][2][1][RTW89_CHILE][1][28] = 10, + [1][1][2][1][RTW89_QATAR][1][28] = 42, + [1][1][2][1][RTW89_QATAR][0][28] = 6, + [1][1][2][1][RTW89_UK][1][28] = 42, + [1][1][2][1][RTW89_UK][0][28] = 6, + [1][1][2][1][RTW89_FCC][1][31] = 10, + [1][1][2][1][RTW89_FCC][2][31] = 70, + [1][1][2][1][RTW89_ETSI][1][31] = 42, + [1][1][2][1][RTW89_ETSI][0][31] = 6, + [1][1][2][1][RTW89_MKK][1][31] = 52, + [1][1][2][1][RTW89_MKK][0][31] = 14, + [1][1][2][1][RTW89_IC][1][31] = 10, + [1][1][2][1][RTW89_KCC][1][31] = 28, + [1][1][2][1][RTW89_KCC][0][31] = 14, + [1][1][2][1][RTW89_ACMA][1][31] = 42, + [1][1][2][1][RTW89_ACMA][0][31] = 6, + [1][1][2][1][RTW89_CHILE][1][31] = 10, + [1][1][2][1][RTW89_QATAR][1][31] = 42, + [1][1][2][1][RTW89_QATAR][0][31] = 6, + [1][1][2][1][RTW89_UK][1][31] = 42, + [1][1][2][1][RTW89_UK][0][31] = 6, + [1][1][2][1][RTW89_FCC][1][35] = 10, + [1][1][2][1][RTW89_FCC][2][35] = 70, + [1][1][2][1][RTW89_ETSI][1][35] = 42, + [1][1][2][1][RTW89_ETSI][0][35] = 6, + [1][1][2][1][RTW89_MKK][1][35] = 52, + [1][1][2][1][RTW89_MKK][0][35] = 14, + [1][1][2][1][RTW89_IC][1][35] = 10, + [1][1][2][1][RTW89_KCC][1][35] = 28, + [1][1][2][1][RTW89_KCC][0][35] = 14, + [1][1][2][1][RTW89_ACMA][1][35] = 42, + [1][1][2][1][RTW89_ACMA][0][35] = 6, + [1][1][2][1][RTW89_CHILE][1][35] = 10, + [1][1][2][1][RTW89_QATAR][1][35] = 42, + [1][1][2][1][RTW89_QATAR][0][35] = 6, + [1][1][2][1][RTW89_UK][1][35] = 42, + [1][1][2][1][RTW89_UK][0][35] = 6, + [1][1][2][1][RTW89_FCC][1][39] = 10, + [1][1][2][1][RTW89_FCC][2][39] = 70, + [1][1][2][1][RTW89_ETSI][1][39] = 42, + [1][1][2][1][RTW89_ETSI][0][39] = 6, + [1][1][2][1][RTW89_MKK][1][39] = 52, + [1][1][2][1][RTW89_MKK][0][39] = 14, + [1][1][2][1][RTW89_IC][1][39] = 10, + [1][1][2][1][RTW89_KCC][1][39] = 28, + [1][1][2][1][RTW89_KCC][0][39] = 14, + [1][1][2][1][RTW89_ACMA][1][39] = 42, + [1][1][2][1][RTW89_ACMA][0][39] = 6, + [1][1][2][1][RTW89_CHILE][1][39] = 10, + [1][1][2][1][RTW89_QATAR][1][39] = 42, + [1][1][2][1][RTW89_QATAR][0][39] = 6, + [1][1][2][1][RTW89_UK][1][39] = 42, + [1][1][2][1][RTW89_UK][0][39] = 6, + [1][1][2][1][RTW89_FCC][1][43] = 10, + [1][1][2][1][RTW89_FCC][2][43] = 70, + [1][1][2][1][RTW89_ETSI][1][43] = 42, + [1][1][2][1][RTW89_ETSI][0][43] = 6, + [1][1][2][1][RTW89_MKK][1][43] = 52, + [1][1][2][1][RTW89_MKK][0][43] = 14, + [1][1][2][1][RTW89_IC][1][43] = 10, + [1][1][2][1][RTW89_KCC][1][43] = 28, + [1][1][2][1][RTW89_KCC][0][43] = 14, + [1][1][2][1][RTW89_ACMA][1][43] = 42, + [1][1][2][1][RTW89_ACMA][0][43] = 6, + [1][1][2][1][RTW89_CHILE][1][43] = 10, + [1][1][2][1][RTW89_QATAR][1][43] = 42, + [1][1][2][1][RTW89_QATAR][0][43] = 6, + [1][1][2][1][RTW89_UK][1][43] = 42, + [1][1][2][1][RTW89_UK][0][43] = 6, + [1][1][2][1][RTW89_FCC][1][46] = 12, + [1][1][2][1][RTW89_FCC][2][46] = 127, + [1][1][2][1][RTW89_ETSI][1][46] = 127, + [1][1][2][1][RTW89_ETSI][0][46] = 127, + [1][1][2][1][RTW89_MKK][1][46] = 127, + [1][1][2][1][RTW89_MKK][0][46] = 127, + [1][1][2][1][RTW89_IC][1][46] = 12, + [1][1][2][1][RTW89_KCC][1][46] = 28, + [1][1][2][1][RTW89_KCC][0][46] = 127, + [1][1][2][1][RTW89_ACMA][1][46] = 127, + [1][1][2][1][RTW89_ACMA][0][46] = 127, + [1][1][2][1][RTW89_CHILE][1][46] = 12, + [1][1][2][1][RTW89_QATAR][1][46] = 127, + [1][1][2][1][RTW89_QATAR][0][46] = 127, + [1][1][2][1][RTW89_UK][1][46] = 127, + [1][1][2][1][RTW89_UK][0][46] = 127, + [1][1][2][1][RTW89_FCC][1][50] = 12, + [1][1][2][1][RTW89_FCC][2][50] = 127, + [1][1][2][1][RTW89_ETSI][1][50] = 127, + [1][1][2][1][RTW89_ETSI][0][50] = 127, + [1][1][2][1][RTW89_MKK][1][50] = 127, + [1][1][2][1][RTW89_MKK][0][50] = 127, + [1][1][2][1][RTW89_IC][1][50] = 12, + [1][1][2][1][RTW89_KCC][1][50] = 28, + [1][1][2][1][RTW89_KCC][0][50] = 127, + [1][1][2][1][RTW89_ACMA][1][50] = 127, + [1][1][2][1][RTW89_ACMA][0][50] = 127, + [1][1][2][1][RTW89_CHILE][1][50] = 12, + [1][1][2][1][RTW89_QATAR][1][50] = 127, + [1][1][2][1][RTW89_QATAR][0][50] = 127, + [1][1][2][1][RTW89_UK][1][50] = 127, + [1][1][2][1][RTW89_UK][0][50] = 127, + [1][1][2][1][RTW89_FCC][1][54] = 10, + [1][1][2][1][RTW89_FCC][2][54] = 127, + [1][1][2][1][RTW89_ETSI][1][54] = 127, + [1][1][2][1][RTW89_ETSI][0][54] = 127, + [1][1][2][1][RTW89_MKK][1][54] = 127, + [1][1][2][1][RTW89_MKK][0][54] = 127, + [1][1][2][1][RTW89_IC][1][54] = 10, + [1][1][2][1][RTW89_KCC][1][54] = 28, + [1][1][2][1][RTW89_KCC][0][54] = 127, + [1][1][2][1][RTW89_ACMA][1][54] = 127, + [1][1][2][1][RTW89_ACMA][0][54] = 127, + [1][1][2][1][RTW89_CHILE][1][54] = 10, + [1][1][2][1][RTW89_QATAR][1][54] = 127, + [1][1][2][1][RTW89_QATAR][0][54] = 127, + [1][1][2][1][RTW89_UK][1][54] = 127, + [1][1][2][1][RTW89_UK][0][54] = 127, + [1][1][2][1][RTW89_FCC][1][58] = 10, + [1][1][2][1][RTW89_FCC][2][58] = 66, + [1][1][2][1][RTW89_ETSI][1][58] = 127, + [1][1][2][1][RTW89_ETSI][0][58] = 127, + [1][1][2][1][RTW89_MKK][1][58] = 127, + [1][1][2][1][RTW89_MKK][0][58] = 127, + [1][1][2][1][RTW89_IC][1][58] = 10, + [1][1][2][1][RTW89_KCC][1][58] = 28, + [1][1][2][1][RTW89_KCC][0][58] = 127, + [1][1][2][1][RTW89_ACMA][1][58] = 127, + [1][1][2][1][RTW89_ACMA][0][58] = 127, + [1][1][2][1][RTW89_CHILE][1][58] = 10, + [1][1][2][1][RTW89_QATAR][1][58] = 127, + [1][1][2][1][RTW89_QATAR][0][58] = 127, + [1][1][2][1][RTW89_UK][1][58] = 127, + [1][1][2][1][RTW89_UK][0][58] = 127, + [1][1][2][1][RTW89_FCC][1][61] = 10, + [1][1][2][1][RTW89_FCC][2][61] = 66, + [1][1][2][1][RTW89_ETSI][1][61] = 127, + [1][1][2][1][RTW89_ETSI][0][61] = 127, + [1][1][2][1][RTW89_MKK][1][61] = 127, + [1][1][2][1][RTW89_MKK][0][61] = 127, + [1][1][2][1][RTW89_IC][1][61] = 10, + [1][1][2][1][RTW89_KCC][1][61] = 28, + [1][1][2][1][RTW89_KCC][0][61] = 127, + [1][1][2][1][RTW89_ACMA][1][61] = 127, + [1][1][2][1][RTW89_ACMA][0][61] = 127, + [1][1][2][1][RTW89_CHILE][1][61] = 10, + [1][1][2][1][RTW89_QATAR][1][61] = 127, + [1][1][2][1][RTW89_QATAR][0][61] = 127, + [1][1][2][1][RTW89_UK][1][61] = 127, + [1][1][2][1][RTW89_UK][0][61] = 127, + [1][1][2][1][RTW89_FCC][1][65] = 10, + [1][1][2][1][RTW89_FCC][2][65] = 66, + [1][1][2][1][RTW89_ETSI][1][65] = 127, + [1][1][2][1][RTW89_ETSI][0][65] = 127, + [1][1][2][1][RTW89_MKK][1][65] = 127, + [1][1][2][1][RTW89_MKK][0][65] = 127, + [1][1][2][1][RTW89_IC][1][65] = 10, + [1][1][2][1][RTW89_KCC][1][65] = 28, + [1][1][2][1][RTW89_KCC][0][65] = 127, + [1][1][2][1][RTW89_ACMA][1][65] = 127, + [1][1][2][1][RTW89_ACMA][0][65] = 127, + [1][1][2][1][RTW89_CHILE][1][65] = 10, + [1][1][2][1][RTW89_QATAR][1][65] = 127, + [1][1][2][1][RTW89_QATAR][0][65] = 127, + [1][1][2][1][RTW89_UK][1][65] = 127, + [1][1][2][1][RTW89_UK][0][65] = 127, + [1][1][2][1][RTW89_FCC][1][69] = 10, + [1][1][2][1][RTW89_FCC][2][69] = 66, + [1][1][2][1][RTW89_ETSI][1][69] = 127, + [1][1][2][1][RTW89_ETSI][0][69] = 127, + [1][1][2][1][RTW89_MKK][1][69] = 127, + [1][1][2][1][RTW89_MKK][0][69] = 127, + [1][1][2][1][RTW89_IC][1][69] = 10, + [1][1][2][1][RTW89_KCC][1][69] = 28, + [1][1][2][1][RTW89_KCC][0][69] = 127, + [1][1][2][1][RTW89_ACMA][1][69] = 127, + [1][1][2][1][RTW89_ACMA][0][69] = 127, + [1][1][2][1][RTW89_CHILE][1][69] = 10, + [1][1][2][1][RTW89_QATAR][1][69] = 127, + [1][1][2][1][RTW89_QATAR][0][69] = 127, + [1][1][2][1][RTW89_UK][1][69] = 127, + [1][1][2][1][RTW89_UK][0][69] = 127, + [1][1][2][1][RTW89_FCC][1][73] = 10, + [1][1][2][1][RTW89_FCC][2][73] = 66, + [1][1][2][1][RTW89_ETSI][1][73] = 127, + [1][1][2][1][RTW89_ETSI][0][73] = 127, + [1][1][2][1][RTW89_MKK][1][73] = 127, + [1][1][2][1][RTW89_MKK][0][73] = 127, + [1][1][2][1][RTW89_IC][1][73] = 10, + [1][1][2][1][RTW89_KCC][1][73] = 28, + [1][1][2][1][RTW89_KCC][0][73] = 127, + [1][1][2][1][RTW89_ACMA][1][73] = 127, + [1][1][2][1][RTW89_ACMA][0][73] = 127, + [1][1][2][1][RTW89_CHILE][1][73] = 10, + [1][1][2][1][RTW89_QATAR][1][73] = 127, + [1][1][2][1][RTW89_QATAR][0][73] = 127, + [1][1][2][1][RTW89_UK][1][73] = 127, + [1][1][2][1][RTW89_UK][0][73] = 127, + [1][1][2][1][RTW89_FCC][1][76] = 10, + [1][1][2][1][RTW89_FCC][2][76] = 66, + [1][1][2][1][RTW89_ETSI][1][76] = 127, + [1][1][2][1][RTW89_ETSI][0][76] = 127, + [1][1][2][1][RTW89_MKK][1][76] = 127, + [1][1][2][1][RTW89_MKK][0][76] = 127, + [1][1][2][1][RTW89_IC][1][76] = 10, + [1][1][2][1][RTW89_KCC][1][76] = 28, + [1][1][2][1][RTW89_KCC][0][76] = 127, + [1][1][2][1][RTW89_ACMA][1][76] = 127, + [1][1][2][1][RTW89_ACMA][0][76] = 127, + [1][1][2][1][RTW89_CHILE][1][76] = 10, + [1][1][2][1][RTW89_QATAR][1][76] = 127, + [1][1][2][1][RTW89_QATAR][0][76] = 127, + [1][1][2][1][RTW89_UK][1][76] = 127, + [1][1][2][1][RTW89_UK][0][76] = 127, + [1][1][2][1][RTW89_FCC][1][80] = 10, + [1][1][2][1][RTW89_FCC][2][80] = 66, + [1][1][2][1][RTW89_ETSI][1][80] = 127, + [1][1][2][1][RTW89_ETSI][0][80] = 127, + [1][1][2][1][RTW89_MKK][1][80] = 127, + [1][1][2][1][RTW89_MKK][0][80] = 127, + [1][1][2][1][RTW89_IC][1][80] = 10, + [1][1][2][1][RTW89_KCC][1][80] = 32, + [1][1][2][1][RTW89_KCC][0][80] = 127, + [1][1][2][1][RTW89_ACMA][1][80] = 127, + [1][1][2][1][RTW89_ACMA][0][80] = 127, + [1][1][2][1][RTW89_CHILE][1][80] = 10, + [1][1][2][1][RTW89_QATAR][1][80] = 127, + [1][1][2][1][RTW89_QATAR][0][80] = 127, + [1][1][2][1][RTW89_UK][1][80] = 127, + [1][1][2][1][RTW89_UK][0][80] = 127, + [1][1][2][1][RTW89_FCC][1][84] = 10, + [1][1][2][1][RTW89_FCC][2][84] = 66, + [1][1][2][1][RTW89_ETSI][1][84] = 127, + [1][1][2][1][RTW89_ETSI][0][84] = 127, + [1][1][2][1][RTW89_MKK][1][84] = 127, + [1][1][2][1][RTW89_MKK][0][84] = 127, + [1][1][2][1][RTW89_IC][1][84] = 10, + [1][1][2][1][RTW89_KCC][1][84] = 32, + [1][1][2][1][RTW89_KCC][0][84] = 127, + [1][1][2][1][RTW89_ACMA][1][84] = 127, + [1][1][2][1][RTW89_ACMA][0][84] = 127, + [1][1][2][1][RTW89_CHILE][1][84] = 10, + [1][1][2][1][RTW89_QATAR][1][84] = 127, + [1][1][2][1][RTW89_QATAR][0][84] = 127, + [1][1][2][1][RTW89_UK][1][84] = 127, + [1][1][2][1][RTW89_UK][0][84] = 127, + [1][1][2][1][RTW89_FCC][1][88] = 10, + [1][1][2][1][RTW89_FCC][2][88] = 127, + [1][1][2][1][RTW89_ETSI][1][88] = 127, + [1][1][2][1][RTW89_ETSI][0][88] = 127, + [1][1][2][1][RTW89_MKK][1][88] = 127, + [1][1][2][1][RTW89_MKK][0][88] = 127, + [1][1][2][1][RTW89_IC][1][88] = 10, + [1][1][2][1][RTW89_KCC][1][88] = 32, + [1][1][2][1][RTW89_KCC][0][88] = 127, + [1][1][2][1][RTW89_ACMA][1][88] = 127, + [1][1][2][1][RTW89_ACMA][0][88] = 127, + [1][1][2][1][RTW89_CHILE][1][88] = 10, + [1][1][2][1][RTW89_QATAR][1][88] = 127, + [1][1][2][1][RTW89_QATAR][0][88] = 127, + [1][1][2][1][RTW89_UK][1][88] = 127, + [1][1][2][1][RTW89_UK][0][88] = 127, + [1][1][2][1][RTW89_FCC][1][91] = 12, + [1][1][2][1][RTW89_FCC][2][91] = 127, + [1][1][2][1][RTW89_ETSI][1][91] = 127, + [1][1][2][1][RTW89_ETSI][0][91] = 127, + [1][1][2][1][RTW89_MKK][1][91] = 127, + [1][1][2][1][RTW89_MKK][0][91] = 127, + [1][1][2][1][RTW89_IC][1][91] = 12, + [1][1][2][1][RTW89_KCC][1][91] = 32, + [1][1][2][1][RTW89_KCC][0][91] = 127, + [1][1][2][1][RTW89_ACMA][1][91] = 127, + [1][1][2][1][RTW89_ACMA][0][91] = 127, + [1][1][2][1][RTW89_CHILE][1][91] = 12, + [1][1][2][1][RTW89_QATAR][1][91] = 127, + [1][1][2][1][RTW89_QATAR][0][91] = 127, + [1][1][2][1][RTW89_UK][1][91] = 127, + [1][1][2][1][RTW89_UK][0][91] = 127, + [1][1][2][1][RTW89_FCC][1][95] = 10, + [1][1][2][1][RTW89_FCC][2][95] = 127, + [1][1][2][1][RTW89_ETSI][1][95] = 127, + [1][1][2][1][RTW89_ETSI][0][95] = 127, + [1][1][2][1][RTW89_MKK][1][95] = 127, + [1][1][2][1][RTW89_MKK][0][95] = 127, + [1][1][2][1][RTW89_IC][1][95] = 10, + [1][1][2][1][RTW89_KCC][1][95] = 32, + [1][1][2][1][RTW89_KCC][0][95] = 127, + [1][1][2][1][RTW89_ACMA][1][95] = 127, + [1][1][2][1][RTW89_ACMA][0][95] = 127, + [1][1][2][1][RTW89_CHILE][1][95] = 10, + [1][1][2][1][RTW89_QATAR][1][95] = 127, + [1][1][2][1][RTW89_QATAR][0][95] = 127, + [1][1][2][1][RTW89_UK][1][95] = 127, + [1][1][2][1][RTW89_UK][0][95] = 127, + [1][1][2][1][RTW89_FCC][1][99] = 10, + [1][1][2][1][RTW89_FCC][2][99] = 127, + [1][1][2][1][RTW89_ETSI][1][99] = 127, + [1][1][2][1][RTW89_ETSI][0][99] = 127, + [1][1][2][1][RTW89_MKK][1][99] = 127, + [1][1][2][1][RTW89_MKK][0][99] = 127, + [1][1][2][1][RTW89_IC][1][99] = 10, + [1][1][2][1][RTW89_KCC][1][99] = 32, + [1][1][2][1][RTW89_KCC][0][99] = 127, + [1][1][2][1][RTW89_ACMA][1][99] = 127, + [1][1][2][1][RTW89_ACMA][0][99] = 127, + [1][1][2][1][RTW89_CHILE][1][99] = 10, + [1][1][2][1][RTW89_QATAR][1][99] = 127, + [1][1][2][1][RTW89_QATAR][0][99] = 127, + [1][1][2][1][RTW89_UK][1][99] = 127, + [1][1][2][1][RTW89_UK][0][99] = 127, + [1][1][2][1][RTW89_FCC][1][103] = 10, + [1][1][2][1][RTW89_FCC][2][103] = 127, + [1][1][2][1][RTW89_ETSI][1][103] = 127, + [1][1][2][1][RTW89_ETSI][0][103] = 127, + [1][1][2][1][RTW89_MKK][1][103] = 127, + [1][1][2][1][RTW89_MKK][0][103] = 127, + [1][1][2][1][RTW89_IC][1][103] = 10, + [1][1][2][1][RTW89_KCC][1][103] = 32, + [1][1][2][1][RTW89_KCC][0][103] = 127, + [1][1][2][1][RTW89_ACMA][1][103] = 127, + [1][1][2][1][RTW89_ACMA][0][103] = 127, + [1][1][2][1][RTW89_CHILE][1][103] = 10, + [1][1][2][1][RTW89_QATAR][1][103] = 127, + [1][1][2][1][RTW89_QATAR][0][103] = 127, + [1][1][2][1][RTW89_UK][1][103] = 127, + [1][1][2][1][RTW89_UK][0][103] = 127, + [1][1][2][1][RTW89_FCC][1][106] = 12, + [1][1][2][1][RTW89_FCC][2][106] = 127, + [1][1][2][1][RTW89_ETSI][1][106] = 127, + [1][1][2][1][RTW89_ETSI][0][106] = 127, + [1][1][2][1][RTW89_MKK][1][106] = 127, + [1][1][2][1][RTW89_MKK][0][106] = 127, + [1][1][2][1][RTW89_IC][1][106] = 12, + [1][1][2][1][RTW89_KCC][1][106] = 32, + [1][1][2][1][RTW89_KCC][0][106] = 127, + [1][1][2][1][RTW89_ACMA][1][106] = 127, + [1][1][2][1][RTW89_ACMA][0][106] = 127, + [1][1][2][1][RTW89_CHILE][1][106] = 12, + [1][1][2][1][RTW89_QATAR][1][106] = 127, + [1][1][2][1][RTW89_QATAR][0][106] = 127, + [1][1][2][1][RTW89_UK][1][106] = 127, + [1][1][2][1][RTW89_UK][0][106] = 127, + [1][1][2][1][RTW89_FCC][1][110] = 127, + [1][1][2][1][RTW89_FCC][2][110] = 127, + [1][1][2][1][RTW89_ETSI][1][110] = 127, + [1][1][2][1][RTW89_ETSI][0][110] = 127, + [1][1][2][1][RTW89_MKK][1][110] = 127, + [1][1][2][1][RTW89_MKK][0][110] = 127, + [1][1][2][1][RTW89_IC][1][110] = 127, + [1][1][2][1][RTW89_KCC][1][110] = 127, + [1][1][2][1][RTW89_KCC][0][110] = 127, + [1][1][2][1][RTW89_ACMA][1][110] = 127, + [1][1][2][1][RTW89_ACMA][0][110] = 127, + [1][1][2][1][RTW89_CHILE][1][110] = 127, + [1][1][2][1][RTW89_QATAR][1][110] = 127, + [1][1][2][1][RTW89_QATAR][0][110] = 127, + [1][1][2][1][RTW89_UK][1][110] = 127, + [1][1][2][1][RTW89_UK][0][110] = 127, + [1][1][2][1][RTW89_FCC][1][114] = 127, + [1][1][2][1][RTW89_FCC][2][114] = 127, + [1][1][2][1][RTW89_ETSI][1][114] = 127, + [1][1][2][1][RTW89_ETSI][0][114] = 127, + [1][1][2][1][RTW89_MKK][1][114] = 127, + [1][1][2][1][RTW89_MKK][0][114] = 127, + [1][1][2][1][RTW89_IC][1][114] = 127, + [1][1][2][1][RTW89_KCC][1][114] = 127, + [1][1][2][1][RTW89_KCC][0][114] = 127, + [1][1][2][1][RTW89_ACMA][1][114] = 127, + [1][1][2][1][RTW89_ACMA][0][114] = 127, + [1][1][2][1][RTW89_CHILE][1][114] = 127, + [1][1][2][1][RTW89_QATAR][1][114] = 127, + [1][1][2][1][RTW89_QATAR][0][114] = 127, + [1][1][2][1][RTW89_UK][1][114] = 127, + [1][1][2][1][RTW89_UK][0][114] = 127, + [1][1][2][1][RTW89_FCC][1][118] = 127, + [1][1][2][1][RTW89_FCC][2][118] = 127, + [1][1][2][1][RTW89_ETSI][1][118] = 127, + [1][1][2][1][RTW89_ETSI][0][118] = 127, + [1][1][2][1][RTW89_MKK][1][118] = 127, + [1][1][2][1][RTW89_MKK][0][118] = 127, + [1][1][2][1][RTW89_IC][1][118] = 127, + [1][1][2][1][RTW89_KCC][1][118] = 127, + [1][1][2][1][RTW89_KCC][0][118] = 127, + [1][1][2][1][RTW89_ACMA][1][118] = 127, + [1][1][2][1][RTW89_ACMA][0][118] = 127, + [1][1][2][1][RTW89_CHILE][1][118] = 127, + [1][1][2][1][RTW89_QATAR][1][118] = 127, + [1][1][2][1][RTW89_QATAR][0][118] = 127, + [1][1][2][1][RTW89_UK][1][118] = 127, + [1][1][2][1][RTW89_UK][0][118] = 127, + [2][0][2][0][RTW89_FCC][1][3] = 46, + [2][0][2][0][RTW89_FCC][2][3] = 60, + [2][0][2][0][RTW89_ETSI][1][3] = 58, + [2][0][2][0][RTW89_ETSI][0][3] = 30, + [2][0][2][0][RTW89_MKK][1][3] = 58, + [2][0][2][0][RTW89_MKK][0][3] = 26, + [2][0][2][0][RTW89_IC][1][3] = 46, + [2][0][2][0][RTW89_KCC][1][3] = 50, + [2][0][2][0][RTW89_KCC][0][3] = 24, + [2][0][2][0][RTW89_ACMA][1][3] = 58, + [2][0][2][0][RTW89_ACMA][0][3] = 30, + [2][0][2][0][RTW89_CHILE][1][3] = 46, + [2][0][2][0][RTW89_QATAR][1][3] = 58, + [2][0][2][0][RTW89_QATAR][0][3] = 30, + [2][0][2][0][RTW89_UK][1][3] = 58, + [2][0][2][0][RTW89_UK][0][3] = 30, + [2][0][2][0][RTW89_FCC][1][11] = 46, + [2][0][2][0][RTW89_FCC][2][11] = 60, + [2][0][2][0][RTW89_ETSI][1][11] = 58, + [2][0][2][0][RTW89_ETSI][0][11] = 30, + [2][0][2][0][RTW89_MKK][1][11] = 58, + [2][0][2][0][RTW89_MKK][0][11] = 24, + [2][0][2][0][RTW89_IC][1][11] = 46, + [2][0][2][0][RTW89_KCC][1][11] = 50, + [2][0][2][0][RTW89_KCC][0][11] = 24, + [2][0][2][0][RTW89_ACMA][1][11] = 58, + [2][0][2][0][RTW89_ACMA][0][11] = 30, + [2][0][2][0][RTW89_CHILE][1][11] = 46, + [2][0][2][0][RTW89_QATAR][1][11] = 58, + [2][0][2][0][RTW89_QATAR][0][11] = 30, + [2][0][2][0][RTW89_UK][1][11] = 58, + [2][0][2][0][RTW89_UK][0][11] = 30, + [2][0][2][0][RTW89_FCC][1][18] = 46, + [2][0][2][0][RTW89_FCC][2][18] = 60, + [2][0][2][0][RTW89_ETSI][1][18] = 58, + [2][0][2][0][RTW89_ETSI][0][18] = 30, + [2][0][2][0][RTW89_MKK][1][18] = 58, + [2][0][2][0][RTW89_MKK][0][18] = 24, + [2][0][2][0][RTW89_IC][1][18] = 46, + [2][0][2][0][RTW89_KCC][1][18] = 50, + [2][0][2][0][RTW89_KCC][0][18] = 24, + [2][0][2][0][RTW89_ACMA][1][18] = 58, + [2][0][2][0][RTW89_ACMA][0][18] = 30, + [2][0][2][0][RTW89_CHILE][1][18] = 46, + [2][0][2][0][RTW89_QATAR][1][18] = 58, + [2][0][2][0][RTW89_QATAR][0][18] = 30, + [2][0][2][0][RTW89_UK][1][18] = 58, + [2][0][2][0][RTW89_UK][0][18] = 30, + [2][0][2][0][RTW89_FCC][1][26] = 46, + [2][0][2][0][RTW89_FCC][2][26] = 60, + [2][0][2][0][RTW89_ETSI][1][26] = 58, + [2][0][2][0][RTW89_ETSI][0][26] = 30, + [2][0][2][0][RTW89_MKK][1][26] = 58, + [2][0][2][0][RTW89_MKK][0][26] = 24, + [2][0][2][0][RTW89_IC][1][26] = 46, + [2][0][2][0][RTW89_KCC][1][26] = 50, + [2][0][2][0][RTW89_KCC][0][26] = 26, + [2][0][2][0][RTW89_ACMA][1][26] = 58, + [2][0][2][0][RTW89_ACMA][0][26] = 30, + [2][0][2][0][RTW89_CHILE][1][26] = 46, + [2][0][2][0][RTW89_QATAR][1][26] = 58, + [2][0][2][0][RTW89_QATAR][0][26] = 30, + [2][0][2][0][RTW89_UK][1][26] = 58, + [2][0][2][0][RTW89_UK][0][26] = 30, + [2][0][2][0][RTW89_FCC][1][33] = 46, + [2][0][2][0][RTW89_FCC][2][33] = 60, + [2][0][2][0][RTW89_ETSI][1][33] = 58, + [2][0][2][0][RTW89_ETSI][0][33] = 30, + [2][0][2][0][RTW89_MKK][1][33] = 58, + [2][0][2][0][RTW89_MKK][0][33] = 24, + [2][0][2][0][RTW89_IC][1][33] = 46, + [2][0][2][0][RTW89_KCC][1][33] = 50, + [2][0][2][0][RTW89_KCC][0][33] = 24, + [2][0][2][0][RTW89_ACMA][1][33] = 58, + [2][0][2][0][RTW89_ACMA][0][33] = 30, + [2][0][2][0][RTW89_CHILE][1][33] = 46, + [2][0][2][0][RTW89_QATAR][1][33] = 58, + [2][0][2][0][RTW89_QATAR][0][33] = 30, + [2][0][2][0][RTW89_UK][1][33] = 58, + [2][0][2][0][RTW89_UK][0][33] = 30, + [2][0][2][0][RTW89_FCC][1][41] = 46, + [2][0][2][0][RTW89_FCC][2][41] = 60, + [2][0][2][0][RTW89_ETSI][1][41] = 58, + [2][0][2][0][RTW89_ETSI][0][41] = 30, + [2][0][2][0][RTW89_MKK][1][41] = 58, + [2][0][2][0][RTW89_MKK][0][41] = 24, + [2][0][2][0][RTW89_IC][1][41] = 46, + [2][0][2][0][RTW89_KCC][1][41] = 50, + [2][0][2][0][RTW89_KCC][0][41] = 24, + [2][0][2][0][RTW89_ACMA][1][41] = 58, + [2][0][2][0][RTW89_ACMA][0][41] = 30, + [2][0][2][0][RTW89_CHILE][1][41] = 46, + [2][0][2][0][RTW89_QATAR][1][41] = 58, + [2][0][2][0][RTW89_QATAR][0][41] = 30, + [2][0][2][0][RTW89_UK][1][41] = 58, + [2][0][2][0][RTW89_UK][0][41] = 30, + [2][0][2][0][RTW89_FCC][1][48] = 46, + [2][0][2][0][RTW89_FCC][2][48] = 127, + [2][0][2][0][RTW89_ETSI][1][48] = 127, + [2][0][2][0][RTW89_ETSI][0][48] = 127, + [2][0][2][0][RTW89_MKK][1][48] = 127, + [2][0][2][0][RTW89_MKK][0][48] = 127, + [2][0][2][0][RTW89_IC][1][48] = 46, + [2][0][2][0][RTW89_KCC][1][48] = 48, + [2][0][2][0][RTW89_KCC][0][48] = 127, + [2][0][2][0][RTW89_ACMA][1][48] = 127, + [2][0][2][0][RTW89_ACMA][0][48] = 127, + [2][0][2][0][RTW89_CHILE][1][48] = 46, + [2][0][2][0][RTW89_QATAR][1][48] = 127, + [2][0][2][0][RTW89_QATAR][0][48] = 127, + [2][0][2][0][RTW89_UK][1][48] = 127, + [2][0][2][0][RTW89_UK][0][48] = 127, + [2][0][2][0][RTW89_FCC][1][56] = 46, + [2][0][2][0][RTW89_FCC][2][56] = 127, + [2][0][2][0][RTW89_ETSI][1][56] = 127, + [2][0][2][0][RTW89_ETSI][0][56] = 127, + [2][0][2][0][RTW89_MKK][1][56] = 127, + [2][0][2][0][RTW89_MKK][0][56] = 127, + [2][0][2][0][RTW89_IC][1][56] = 46, + [2][0][2][0][RTW89_KCC][1][56] = 48, + [2][0][2][0][RTW89_KCC][0][56] = 127, + [2][0][2][0][RTW89_ACMA][1][56] = 127, + [2][0][2][0][RTW89_ACMA][0][56] = 127, + [2][0][2][0][RTW89_CHILE][1][56] = 46, + [2][0][2][0][RTW89_QATAR][1][56] = 127, + [2][0][2][0][RTW89_QATAR][0][56] = 127, + [2][0][2][0][RTW89_UK][1][56] = 127, + [2][0][2][0][RTW89_UK][0][56] = 127, + [2][0][2][0][RTW89_FCC][1][63] = 46, + [2][0][2][0][RTW89_FCC][2][63] = 58, + [2][0][2][0][RTW89_ETSI][1][63] = 127, + [2][0][2][0][RTW89_ETSI][0][63] = 127, + [2][0][2][0][RTW89_MKK][1][63] = 127, + [2][0][2][0][RTW89_MKK][0][63] = 127, + [2][0][2][0][RTW89_IC][1][63] = 46, + [2][0][2][0][RTW89_KCC][1][63] = 48, + [2][0][2][0][RTW89_KCC][0][63] = 127, + [2][0][2][0][RTW89_ACMA][1][63] = 127, + [2][0][2][0][RTW89_ACMA][0][63] = 127, + [2][0][2][0][RTW89_CHILE][1][63] = 46, + [2][0][2][0][RTW89_QATAR][1][63] = 127, + [2][0][2][0][RTW89_QATAR][0][63] = 127, + [2][0][2][0][RTW89_UK][1][63] = 127, + [2][0][2][0][RTW89_UK][0][63] = 127, + [2][0][2][0][RTW89_FCC][1][71] = 46, + [2][0][2][0][RTW89_FCC][2][71] = 58, + [2][0][2][0][RTW89_ETSI][1][71] = 127, + [2][0][2][0][RTW89_ETSI][0][71] = 127, + [2][0][2][0][RTW89_MKK][1][71] = 127, + [2][0][2][0][RTW89_MKK][0][71] = 127, + [2][0][2][0][RTW89_IC][1][71] = 46, + [2][0][2][0][RTW89_KCC][1][71] = 48, + [2][0][2][0][RTW89_KCC][0][71] = 127, + [2][0][2][0][RTW89_ACMA][1][71] = 127, + [2][0][2][0][RTW89_ACMA][0][71] = 127, + [2][0][2][0][RTW89_CHILE][1][71] = 46, + [2][0][2][0][RTW89_QATAR][1][71] = 127, + [2][0][2][0][RTW89_QATAR][0][71] = 127, + [2][0][2][0][RTW89_UK][1][71] = 127, + [2][0][2][0][RTW89_UK][0][71] = 127, + [2][0][2][0][RTW89_FCC][1][78] = 46, + [2][0][2][0][RTW89_FCC][2][78] = 58, + [2][0][2][0][RTW89_ETSI][1][78] = 127, + [2][0][2][0][RTW89_ETSI][0][78] = 127, + [2][0][2][0][RTW89_MKK][1][78] = 127, + [2][0][2][0][RTW89_MKK][0][78] = 127, + [2][0][2][0][RTW89_IC][1][78] = 46, + [2][0][2][0][RTW89_KCC][1][78] = 52, + [2][0][2][0][RTW89_KCC][0][78] = 127, + [2][0][2][0][RTW89_ACMA][1][78] = 127, + [2][0][2][0][RTW89_ACMA][0][78] = 127, + [2][0][2][0][RTW89_CHILE][1][78] = 46, + [2][0][2][0][RTW89_QATAR][1][78] = 127, + [2][0][2][0][RTW89_QATAR][0][78] = 127, + [2][0][2][0][RTW89_UK][1][78] = 127, + [2][0][2][0][RTW89_UK][0][78] = 127, + [2][0][2][0][RTW89_FCC][1][86] = 46, + [2][0][2][0][RTW89_FCC][2][86] = 127, + [2][0][2][0][RTW89_ETSI][1][86] = 127, + [2][0][2][0][RTW89_ETSI][0][86] = 127, + [2][0][2][0][RTW89_MKK][1][86] = 127, + [2][0][2][0][RTW89_MKK][0][86] = 127, + [2][0][2][0][RTW89_IC][1][86] = 46, + [2][0][2][0][RTW89_KCC][1][86] = 52, + [2][0][2][0][RTW89_KCC][0][86] = 127, + [2][0][2][0][RTW89_ACMA][1][86] = 127, + [2][0][2][0][RTW89_ACMA][0][86] = 127, + [2][0][2][0][RTW89_CHILE][1][86] = 46, + [2][0][2][0][RTW89_QATAR][1][86] = 127, + [2][0][2][0][RTW89_QATAR][0][86] = 127, + [2][0][2][0][RTW89_UK][1][86] = 127, + [2][0][2][0][RTW89_UK][0][86] = 127, + [2][0][2][0][RTW89_FCC][1][93] = 46, + [2][0][2][0][RTW89_FCC][2][93] = 127, + [2][0][2][0][RTW89_ETSI][1][93] = 127, + [2][0][2][0][RTW89_ETSI][0][93] = 127, + [2][0][2][0][RTW89_MKK][1][93] = 127, + [2][0][2][0][RTW89_MKK][0][93] = 127, + [2][0][2][0][RTW89_IC][1][93] = 46, + [2][0][2][0][RTW89_KCC][1][93] = 50, + [2][0][2][0][RTW89_KCC][0][93] = 127, + [2][0][2][0][RTW89_ACMA][1][93] = 127, + [2][0][2][0][RTW89_ACMA][0][93] = 127, + [2][0][2][0][RTW89_CHILE][1][93] = 46, + [2][0][2][0][RTW89_QATAR][1][93] = 127, + [2][0][2][0][RTW89_QATAR][0][93] = 127, + [2][0][2][0][RTW89_UK][1][93] = 127, + [2][0][2][0][RTW89_UK][0][93] = 127, + [2][0][2][0][RTW89_FCC][1][101] = 44, + [2][0][2][0][RTW89_FCC][2][101] = 127, + [2][0][2][0][RTW89_ETSI][1][101] = 127, + [2][0][2][0][RTW89_ETSI][0][101] = 127, + [2][0][2][0][RTW89_MKK][1][101] = 127, + [2][0][2][0][RTW89_MKK][0][101] = 127, + [2][0][2][0][RTW89_IC][1][101] = 44, + [2][0][2][0][RTW89_KCC][1][101] = 50, + [2][0][2][0][RTW89_KCC][0][101] = 127, + [2][0][2][0][RTW89_ACMA][1][101] = 127, + [2][0][2][0][RTW89_ACMA][0][101] = 127, + [2][0][2][0][RTW89_CHILE][1][101] = 44, + [2][0][2][0][RTW89_QATAR][1][101] = 127, + [2][0][2][0][RTW89_QATAR][0][101] = 127, + [2][0][2][0][RTW89_UK][1][101] = 127, + [2][0][2][0][RTW89_UK][0][101] = 127, + [2][0][2][0][RTW89_FCC][1][108] = 127, + [2][0][2][0][RTW89_FCC][2][108] = 127, + [2][0][2][0][RTW89_ETSI][1][108] = 127, + [2][0][2][0][RTW89_ETSI][0][108] = 127, + [2][0][2][0][RTW89_MKK][1][108] = 127, + [2][0][2][0][RTW89_MKK][0][108] = 127, + [2][0][2][0][RTW89_IC][1][108] = 127, + [2][0][2][0][RTW89_KCC][1][108] = 127, + [2][0][2][0][RTW89_KCC][0][108] = 127, + [2][0][2][0][RTW89_ACMA][1][108] = 127, + [2][0][2][0][RTW89_ACMA][0][108] = 127, + [2][0][2][0][RTW89_CHILE][1][108] = 127, + [2][0][2][0][RTW89_QATAR][1][108] = 127, + [2][0][2][0][RTW89_QATAR][0][108] = 127, + [2][0][2][0][RTW89_UK][1][108] = 127, + [2][0][2][0][RTW89_UK][0][108] = 127, + [2][0][2][0][RTW89_FCC][1][116] = 127, + [2][0][2][0][RTW89_FCC][2][116] = 127, + [2][0][2][0][RTW89_ETSI][1][116] = 127, + [2][0][2][0][RTW89_ETSI][0][116] = 127, + [2][0][2][0][RTW89_MKK][1][116] = 127, + [2][0][2][0][RTW89_MKK][0][116] = 127, + [2][0][2][0][RTW89_IC][1][116] = 127, + [2][0][2][0][RTW89_KCC][1][116] = 127, + [2][0][2][0][RTW89_KCC][0][116] = 127, + [2][0][2][0][RTW89_ACMA][1][116] = 127, + [2][0][2][0][RTW89_ACMA][0][116] = 127, + [2][0][2][0][RTW89_CHILE][1][116] = 127, + [2][0][2][0][RTW89_QATAR][1][116] = 127, + [2][0][2][0][RTW89_QATAR][0][116] = 127, + [2][0][2][0][RTW89_UK][1][116] = 127, + [2][0][2][0][RTW89_UK][0][116] = 127, + [2][1][2][0][RTW89_FCC][1][3] = 22, + [2][1][2][0][RTW89_FCC][2][3] = 50, + [2][1][2][0][RTW89_ETSI][1][3] = 54, + [2][1][2][0][RTW89_ETSI][0][3] = 16, + [2][1][2][0][RTW89_MKK][1][3] = 52, + [2][1][2][0][RTW89_MKK][0][3] = 14, + [2][1][2][0][RTW89_IC][1][3] = 22, + [2][1][2][0][RTW89_KCC][1][3] = 38, + [2][1][2][0][RTW89_KCC][0][3] = 12, + [2][1][2][0][RTW89_ACMA][1][3] = 54, + [2][1][2][0][RTW89_ACMA][0][3] = 16, + [2][1][2][0][RTW89_CHILE][1][3] = 22, + [2][1][2][0][RTW89_QATAR][1][3] = 54, + [2][1][2][0][RTW89_QATAR][0][3] = 16, + [2][1][2][0][RTW89_UK][1][3] = 54, + [2][1][2][0][RTW89_UK][0][3] = 16, + [2][1][2][0][RTW89_FCC][1][11] = 20, + [2][1][2][0][RTW89_FCC][2][11] = 50, + [2][1][2][0][RTW89_ETSI][1][11] = 54, + [2][1][2][0][RTW89_ETSI][0][11] = 16, + [2][1][2][0][RTW89_MKK][1][11] = 52, + [2][1][2][0][RTW89_MKK][0][11] = 12, + [2][1][2][0][RTW89_IC][1][11] = 20, + [2][1][2][0][RTW89_KCC][1][11] = 38, + [2][1][2][0][RTW89_KCC][0][11] = 12, + [2][1][2][0][RTW89_ACMA][1][11] = 54, + [2][1][2][0][RTW89_ACMA][0][11] = 16, + [2][1][2][0][RTW89_CHILE][1][11] = 20, + [2][1][2][0][RTW89_QATAR][1][11] = 54, + [2][1][2][0][RTW89_QATAR][0][11] = 16, + [2][1][2][0][RTW89_UK][1][11] = 54, + [2][1][2][0][RTW89_UK][0][11] = 16, + [2][1][2][0][RTW89_FCC][1][18] = 20, + [2][1][2][0][RTW89_FCC][2][18] = 50, + [2][1][2][0][RTW89_ETSI][1][18] = 54, + [2][1][2][0][RTW89_ETSI][0][18] = 16, + [2][1][2][0][RTW89_MKK][1][18] = 52, + [2][1][2][0][RTW89_MKK][0][18] = 12, + [2][1][2][0][RTW89_IC][1][18] = 20, + [2][1][2][0][RTW89_KCC][1][18] = 38, + [2][1][2][0][RTW89_KCC][0][18] = 12, + [2][1][2][0][RTW89_ACMA][1][18] = 54, + [2][1][2][0][RTW89_ACMA][0][18] = 16, + [2][1][2][0][RTW89_CHILE][1][18] = 20, + [2][1][2][0][RTW89_QATAR][1][18] = 54, + [2][1][2][0][RTW89_QATAR][0][18] = 16, + [2][1][2][0][RTW89_UK][1][18] = 54, + [2][1][2][0][RTW89_UK][0][18] = 16, + [2][1][2][0][RTW89_FCC][1][26] = 20, + [2][1][2][0][RTW89_FCC][2][26] = 60, + [2][1][2][0][RTW89_ETSI][1][26] = 54, + [2][1][2][0][RTW89_ETSI][0][26] = 16, + [2][1][2][0][RTW89_MKK][1][26] = 52, + [2][1][2][0][RTW89_MKK][0][26] = 12, + [2][1][2][0][RTW89_IC][1][26] = 20, + [2][1][2][0][RTW89_KCC][1][26] = 38, + [2][1][2][0][RTW89_KCC][0][26] = 12, + [2][1][2][0][RTW89_ACMA][1][26] = 54, + [2][1][2][0][RTW89_ACMA][0][26] = 16, + [2][1][2][0][RTW89_CHILE][1][26] = 20, + [2][1][2][0][RTW89_QATAR][1][26] = 54, + [2][1][2][0][RTW89_QATAR][0][26] = 16, + [2][1][2][0][RTW89_UK][1][26] = 54, + [2][1][2][0][RTW89_UK][0][26] = 16, + [2][1][2][0][RTW89_FCC][1][33] = 20, + [2][1][2][0][RTW89_FCC][2][33] = 60, + [2][1][2][0][RTW89_ETSI][1][33] = 54, + [2][1][2][0][RTW89_ETSI][0][33] = 16, + [2][1][2][0][RTW89_MKK][1][33] = 48, + [2][1][2][0][RTW89_MKK][0][33] = 12, + [2][1][2][0][RTW89_IC][1][33] = 20, + [2][1][2][0][RTW89_KCC][1][33] = 38, + [2][1][2][0][RTW89_KCC][0][33] = 12, + [2][1][2][0][RTW89_ACMA][1][33] = 54, + [2][1][2][0][RTW89_ACMA][0][33] = 16, + [2][1][2][0][RTW89_CHILE][1][33] = 20, + [2][1][2][0][RTW89_QATAR][1][33] = 54, + [2][1][2][0][RTW89_QATAR][0][33] = 16, + [2][1][2][0][RTW89_UK][1][33] = 54, + [2][1][2][0][RTW89_UK][0][33] = 16, + [2][1][2][0][RTW89_FCC][1][41] = 22, + [2][1][2][0][RTW89_FCC][2][41] = 60, + [2][1][2][0][RTW89_ETSI][1][41] = 54, + [2][1][2][0][RTW89_ETSI][0][41] = 18, + [2][1][2][0][RTW89_MKK][1][41] = 48, + [2][1][2][0][RTW89_MKK][0][41] = 12, + [2][1][2][0][RTW89_IC][1][41] = 22, + [2][1][2][0][RTW89_KCC][1][41] = 38, + [2][1][2][0][RTW89_KCC][0][41] = 12, + [2][1][2][0][RTW89_ACMA][1][41] = 54, + [2][1][2][0][RTW89_ACMA][0][41] = 18, + [2][1][2][0][RTW89_CHILE][1][41] = 22, + [2][1][2][0][RTW89_QATAR][1][41] = 54, + [2][1][2][0][RTW89_QATAR][0][41] = 18, + [2][1][2][0][RTW89_UK][1][41] = 54, + [2][1][2][0][RTW89_UK][0][41] = 18, + [2][1][2][0][RTW89_FCC][1][48] = 22, + [2][1][2][0][RTW89_FCC][2][48] = 127, + [2][1][2][0][RTW89_ETSI][1][48] = 127, + [2][1][2][0][RTW89_ETSI][0][48] = 127, + [2][1][2][0][RTW89_MKK][1][48] = 127, + [2][1][2][0][RTW89_MKK][0][48] = 127, + [2][1][2][0][RTW89_IC][1][48] = 22, + [2][1][2][0][RTW89_KCC][1][48] = 38, + [2][1][2][0][RTW89_KCC][0][48] = 127, + [2][1][2][0][RTW89_ACMA][1][48] = 127, + [2][1][2][0][RTW89_ACMA][0][48] = 127, + [2][1][2][0][RTW89_CHILE][1][48] = 22, + [2][1][2][0][RTW89_QATAR][1][48] = 127, + [2][1][2][0][RTW89_QATAR][0][48] = 127, + [2][1][2][0][RTW89_UK][1][48] = 127, + [2][1][2][0][RTW89_UK][0][48] = 127, + [2][1][2][0][RTW89_FCC][1][56] = 20, + [2][1][2][0][RTW89_FCC][2][56] = 127, + [2][1][2][0][RTW89_ETSI][1][56] = 127, + [2][1][2][0][RTW89_ETSI][0][56] = 127, + [2][1][2][0][RTW89_MKK][1][56] = 127, + [2][1][2][0][RTW89_MKK][0][56] = 127, + [2][1][2][0][RTW89_IC][1][56] = 20, + [2][1][2][0][RTW89_KCC][1][56] = 38, + [2][1][2][0][RTW89_KCC][0][56] = 127, + [2][1][2][0][RTW89_ACMA][1][56] = 127, + [2][1][2][0][RTW89_ACMA][0][56] = 127, + [2][1][2][0][RTW89_CHILE][1][56] = 20, + [2][1][2][0][RTW89_QATAR][1][56] = 127, + [2][1][2][0][RTW89_QATAR][0][56] = 127, + [2][1][2][0][RTW89_UK][1][56] = 127, + [2][1][2][0][RTW89_UK][0][56] = 127, + [2][1][2][0][RTW89_FCC][1][63] = 22, + [2][1][2][0][RTW89_FCC][2][63] = 58, + [2][1][2][0][RTW89_ETSI][1][63] = 127, + [2][1][2][0][RTW89_ETSI][0][63] = 127, + [2][1][2][0][RTW89_MKK][1][63] = 127, + [2][1][2][0][RTW89_MKK][0][63] = 127, + [2][1][2][0][RTW89_IC][1][63] = 22, + [2][1][2][0][RTW89_KCC][1][63] = 38, + [2][1][2][0][RTW89_KCC][0][63] = 127, + [2][1][2][0][RTW89_ACMA][1][63] = 127, + [2][1][2][0][RTW89_ACMA][0][63] = 127, + [2][1][2][0][RTW89_CHILE][1][63] = 22, + [2][1][2][0][RTW89_QATAR][1][63] = 127, + [2][1][2][0][RTW89_QATAR][0][63] = 127, + [2][1][2][0][RTW89_UK][1][63] = 127, + [2][1][2][0][RTW89_UK][0][63] = 127, + [2][1][2][0][RTW89_FCC][1][71] = 20, + [2][1][2][0][RTW89_FCC][2][71] = 58, + [2][1][2][0][RTW89_ETSI][1][71] = 127, + [2][1][2][0][RTW89_ETSI][0][71] = 127, + [2][1][2][0][RTW89_MKK][1][71] = 127, + [2][1][2][0][RTW89_MKK][0][71] = 127, + [2][1][2][0][RTW89_IC][1][71] = 20, + [2][1][2][0][RTW89_KCC][1][71] = 38, + [2][1][2][0][RTW89_KCC][0][71] = 127, + [2][1][2][0][RTW89_ACMA][1][71] = 127, + [2][1][2][0][RTW89_ACMA][0][71] = 127, + [2][1][2][0][RTW89_CHILE][1][71] = 20, + [2][1][2][0][RTW89_QATAR][1][71] = 127, + [2][1][2][0][RTW89_QATAR][0][71] = 127, + [2][1][2][0][RTW89_UK][1][71] = 127, + [2][1][2][0][RTW89_UK][0][71] = 127, + [2][1][2][0][RTW89_FCC][1][78] = 20, + [2][1][2][0][RTW89_FCC][2][78] = 58, + [2][1][2][0][RTW89_ETSI][1][78] = 127, + [2][1][2][0][RTW89_ETSI][0][78] = 127, + [2][1][2][0][RTW89_MKK][1][78] = 127, + [2][1][2][0][RTW89_MKK][0][78] = 127, + [2][1][2][0][RTW89_IC][1][78] = 20, + [2][1][2][0][RTW89_KCC][1][78] = 38, + [2][1][2][0][RTW89_KCC][0][78] = 127, + [2][1][2][0][RTW89_ACMA][1][78] = 127, + [2][1][2][0][RTW89_ACMA][0][78] = 127, + [2][1][2][0][RTW89_CHILE][1][78] = 20, + [2][1][2][0][RTW89_QATAR][1][78] = 127, + [2][1][2][0][RTW89_QATAR][0][78] = 127, + [2][1][2][0][RTW89_UK][1][78] = 127, + [2][1][2][0][RTW89_UK][0][78] = 127, + [2][1][2][0][RTW89_FCC][1][86] = 20, + [2][1][2][0][RTW89_FCC][2][86] = 127, + [2][1][2][0][RTW89_ETSI][1][86] = 127, + [2][1][2][0][RTW89_ETSI][0][86] = 127, + [2][1][2][0][RTW89_MKK][1][86] = 127, + [2][1][2][0][RTW89_MKK][0][86] = 127, + [2][1][2][0][RTW89_IC][1][86] = 20, + [2][1][2][0][RTW89_KCC][1][86] = 38, + [2][1][2][0][RTW89_KCC][0][86] = 127, + [2][1][2][0][RTW89_ACMA][1][86] = 127, + [2][1][2][0][RTW89_ACMA][0][86] = 127, + [2][1][2][0][RTW89_CHILE][1][86] = 20, + [2][1][2][0][RTW89_QATAR][1][86] = 127, + [2][1][2][0][RTW89_QATAR][0][86] = 127, + [2][1][2][0][RTW89_UK][1][86] = 127, + [2][1][2][0][RTW89_UK][0][86] = 127, + [2][1][2][0][RTW89_FCC][1][93] = 22, + [2][1][2][0][RTW89_FCC][2][93] = 127, + [2][1][2][0][RTW89_ETSI][1][93] = 127, + [2][1][2][0][RTW89_ETSI][0][93] = 127, + [2][1][2][0][RTW89_MKK][1][93] = 127, + [2][1][2][0][RTW89_MKK][0][93] = 127, + [2][1][2][0][RTW89_IC][1][93] = 22, + [2][1][2][0][RTW89_KCC][1][93] = 38, + [2][1][2][0][RTW89_KCC][0][93] = 127, + [2][1][2][0][RTW89_ACMA][1][93] = 127, + [2][1][2][0][RTW89_ACMA][0][93] = 127, + [2][1][2][0][RTW89_CHILE][1][93] = 22, + [2][1][2][0][RTW89_QATAR][1][93] = 127, + [2][1][2][0][RTW89_QATAR][0][93] = 127, + [2][1][2][0][RTW89_UK][1][93] = 127, + [2][1][2][0][RTW89_UK][0][93] = 127, + [2][1][2][0][RTW89_FCC][1][101] = 22, + [2][1][2][0][RTW89_FCC][2][101] = 127, + [2][1][2][0][RTW89_ETSI][1][101] = 127, + [2][1][2][0][RTW89_ETSI][0][101] = 127, + [2][1][2][0][RTW89_MKK][1][101] = 127, + [2][1][2][0][RTW89_MKK][0][101] = 127, + [2][1][2][0][RTW89_IC][1][101] = 22, + [2][1][2][0][RTW89_KCC][1][101] = 38, + [2][1][2][0][RTW89_KCC][0][101] = 127, + [2][1][2][0][RTW89_ACMA][1][101] = 127, + [2][1][2][0][RTW89_ACMA][0][101] = 127, + [2][1][2][0][RTW89_CHILE][1][101] = 22, + [2][1][2][0][RTW89_QATAR][1][101] = 127, + [2][1][2][0][RTW89_QATAR][0][101] = 127, + [2][1][2][0][RTW89_UK][1][101] = 127, + [2][1][2][0][RTW89_UK][0][101] = 127, + [2][1][2][0][RTW89_FCC][1][108] = 127, + [2][1][2][0][RTW89_FCC][2][108] = 127, + [2][1][2][0][RTW89_ETSI][1][108] = 127, + [2][1][2][0][RTW89_ETSI][0][108] = 127, + [2][1][2][0][RTW89_MKK][1][108] = 127, + [2][1][2][0][RTW89_MKK][0][108] = 127, + [2][1][2][0][RTW89_IC][1][108] = 127, + [2][1][2][0][RTW89_KCC][1][108] = 127, + [2][1][2][0][RTW89_KCC][0][108] = 127, + [2][1][2][0][RTW89_ACMA][1][108] = 127, + [2][1][2][0][RTW89_ACMA][0][108] = 127, + [2][1][2][0][RTW89_CHILE][1][108] = 127, + [2][1][2][0][RTW89_QATAR][1][108] = 127, + [2][1][2][0][RTW89_QATAR][0][108] = 127, + [2][1][2][0][RTW89_UK][1][108] = 127, + [2][1][2][0][RTW89_UK][0][108] = 127, + [2][1][2][0][RTW89_FCC][1][116] = 127, + [2][1][2][0][RTW89_FCC][2][116] = 127, + [2][1][2][0][RTW89_ETSI][1][116] = 127, + [2][1][2][0][RTW89_ETSI][0][116] = 127, + [2][1][2][0][RTW89_MKK][1][116] = 127, + [2][1][2][0][RTW89_MKK][0][116] = 127, + [2][1][2][0][RTW89_IC][1][116] = 127, + [2][1][2][0][RTW89_KCC][1][116] = 127, + [2][1][2][0][RTW89_KCC][0][116] = 127, + [2][1][2][0][RTW89_ACMA][1][116] = 127, + [2][1][2][0][RTW89_ACMA][0][116] = 127, + [2][1][2][0][RTW89_CHILE][1][116] = 127, + [2][1][2][0][RTW89_QATAR][1][116] = 127, + [2][1][2][0][RTW89_QATAR][0][116] = 127, + [2][1][2][0][RTW89_UK][1][116] = 127, + [2][1][2][0][RTW89_UK][0][116] = 127, + [2][1][2][1][RTW89_FCC][1][3] = 22, + [2][1][2][1][RTW89_FCC][2][3] = 50, + [2][1][2][1][RTW89_ETSI][1][3] = 42, + [2][1][2][1][RTW89_ETSI][0][3] = 6, + [2][1][2][1][RTW89_MKK][1][3] = 52, + [2][1][2][1][RTW89_MKK][0][3] = 14, + [2][1][2][1][RTW89_IC][1][3] = 22, + [2][1][2][1][RTW89_KCC][1][3] = 38, + [2][1][2][1][RTW89_KCC][0][3] = 12, + [2][1][2][1][RTW89_ACMA][1][3] = 42, + [2][1][2][1][RTW89_ACMA][0][3] = 6, + [2][1][2][1][RTW89_CHILE][1][3] = 22, + [2][1][2][1][RTW89_QATAR][1][3] = 42, + [2][1][2][1][RTW89_QATAR][0][3] = 6, + [2][1][2][1][RTW89_UK][1][3] = 42, + [2][1][2][1][RTW89_UK][0][3] = 6, + [2][1][2][1][RTW89_FCC][1][11] = 20, + [2][1][2][1][RTW89_FCC][2][11] = 50, + [2][1][2][1][RTW89_ETSI][1][11] = 42, + [2][1][2][1][RTW89_ETSI][0][11] = 6, + [2][1][2][1][RTW89_MKK][1][11] = 52, + [2][1][2][1][RTW89_MKK][0][11] = 12, + [2][1][2][1][RTW89_IC][1][11] = 20, + [2][1][2][1][RTW89_KCC][1][11] = 38, + [2][1][2][1][RTW89_KCC][0][11] = 12, + [2][1][2][1][RTW89_ACMA][1][11] = 42, + [2][1][2][1][RTW89_ACMA][0][11] = 6, + [2][1][2][1][RTW89_CHILE][1][11] = 20, + [2][1][2][1][RTW89_QATAR][1][11] = 42, + [2][1][2][1][RTW89_QATAR][0][11] = 6, + [2][1][2][1][RTW89_UK][1][11] = 42, + [2][1][2][1][RTW89_UK][0][11] = 6, + [2][1][2][1][RTW89_FCC][1][18] = 20, + [2][1][2][1][RTW89_FCC][2][18] = 50, + [2][1][2][1][RTW89_ETSI][1][18] = 42, + [2][1][2][1][RTW89_ETSI][0][18] = 6, + [2][1][2][1][RTW89_MKK][1][18] = 52, + [2][1][2][1][RTW89_MKK][0][18] = 12, + [2][1][2][1][RTW89_IC][1][18] = 20, + [2][1][2][1][RTW89_KCC][1][18] = 38, + [2][1][2][1][RTW89_KCC][0][18] = 12, + [2][1][2][1][RTW89_ACMA][1][18] = 42, + [2][1][2][1][RTW89_ACMA][0][18] = 6, + [2][1][2][1][RTW89_CHILE][1][18] = 20, + [2][1][2][1][RTW89_QATAR][1][18] = 42, + [2][1][2][1][RTW89_QATAR][0][18] = 6, + [2][1][2][1][RTW89_UK][1][18] = 42, + [2][1][2][1][RTW89_UK][0][18] = 6, + [2][1][2][1][RTW89_FCC][1][26] = 20, + [2][1][2][1][RTW89_FCC][2][26] = 60, + [2][1][2][1][RTW89_ETSI][1][26] = 42, + [2][1][2][1][RTW89_ETSI][0][26] = 6, + [2][1][2][1][RTW89_MKK][1][26] = 52, + [2][1][2][1][RTW89_MKK][0][26] = 12, + [2][1][2][1][RTW89_IC][1][26] = 20, + [2][1][2][1][RTW89_KCC][1][26] = 38, + [2][1][2][1][RTW89_KCC][0][26] = 12, + [2][1][2][1][RTW89_ACMA][1][26] = 42, + [2][1][2][1][RTW89_ACMA][0][26] = 6, + [2][1][2][1][RTW89_CHILE][1][26] = 20, + [2][1][2][1][RTW89_QATAR][1][26] = 42, + [2][1][2][1][RTW89_QATAR][0][26] = 6, + [2][1][2][1][RTW89_UK][1][26] = 42, + [2][1][2][1][RTW89_UK][0][26] = 6, + [2][1][2][1][RTW89_FCC][1][33] = 20, + [2][1][2][1][RTW89_FCC][2][33] = 60, + [2][1][2][1][RTW89_ETSI][1][33] = 42, + [2][1][2][1][RTW89_ETSI][0][33] = 6, + [2][1][2][1][RTW89_MKK][1][33] = 48, + [2][1][2][1][RTW89_MKK][0][33] = 12, + [2][1][2][1][RTW89_IC][1][33] = 20, + [2][1][2][1][RTW89_KCC][1][33] = 38, + [2][1][2][1][RTW89_KCC][0][33] = 12, + [2][1][2][1][RTW89_ACMA][1][33] = 42, + [2][1][2][1][RTW89_ACMA][0][33] = 6, + [2][1][2][1][RTW89_CHILE][1][33] = 20, + [2][1][2][1][RTW89_QATAR][1][33] = 42, + [2][1][2][1][RTW89_QATAR][0][33] = 6, + [2][1][2][1][RTW89_UK][1][33] = 42, + [2][1][2][1][RTW89_UK][0][33] = 6, + [2][1][2][1][RTW89_FCC][1][41] = 22, + [2][1][2][1][RTW89_FCC][2][41] = 60, + [2][1][2][1][RTW89_ETSI][1][41] = 42, + [2][1][2][1][RTW89_ETSI][0][41] = 6, + [2][1][2][1][RTW89_MKK][1][41] = 48, + [2][1][2][1][RTW89_MKK][0][41] = 12, + [2][1][2][1][RTW89_IC][1][41] = 22, + [2][1][2][1][RTW89_KCC][1][41] = 38, + [2][1][2][1][RTW89_KCC][0][41] = 12, + [2][1][2][1][RTW89_ACMA][1][41] = 42, + [2][1][2][1][RTW89_ACMA][0][41] = 6, + [2][1][2][1][RTW89_CHILE][1][41] = 22, + [2][1][2][1][RTW89_QATAR][1][41] = 42, + [2][1][2][1][RTW89_QATAR][0][41] = 6, + [2][1][2][1][RTW89_UK][1][41] = 42, + [2][1][2][1][RTW89_UK][0][41] = 6, + [2][1][2][1][RTW89_FCC][1][48] = 22, + [2][1][2][1][RTW89_FCC][2][48] = 127, + [2][1][2][1][RTW89_ETSI][1][48] = 127, + [2][1][2][1][RTW89_ETSI][0][48] = 127, + [2][1][2][1][RTW89_MKK][1][48] = 127, + [2][1][2][1][RTW89_MKK][0][48] = 127, + [2][1][2][1][RTW89_IC][1][48] = 22, + [2][1][2][1][RTW89_KCC][1][48] = 38, + [2][1][2][1][RTW89_KCC][0][48] = 127, + [2][1][2][1][RTW89_ACMA][1][48] = 127, + [2][1][2][1][RTW89_ACMA][0][48] = 127, + [2][1][2][1][RTW89_CHILE][1][48] = 22, + [2][1][2][1][RTW89_QATAR][1][48] = 127, + [2][1][2][1][RTW89_QATAR][0][48] = 127, + [2][1][2][1][RTW89_UK][1][48] = 127, + [2][1][2][1][RTW89_UK][0][48] = 127, + [2][1][2][1][RTW89_FCC][1][56] = 20, + [2][1][2][1][RTW89_FCC][2][56] = 127, + [2][1][2][1][RTW89_ETSI][1][56] = 127, + [2][1][2][1][RTW89_ETSI][0][56] = 127, + [2][1][2][1][RTW89_MKK][1][56] = 127, + [2][1][2][1][RTW89_MKK][0][56] = 127, + [2][1][2][1][RTW89_IC][1][56] = 20, + [2][1][2][1][RTW89_KCC][1][56] = 38, + [2][1][2][1][RTW89_KCC][0][56] = 127, + [2][1][2][1][RTW89_ACMA][1][56] = 127, + [2][1][2][1][RTW89_ACMA][0][56] = 127, + [2][1][2][1][RTW89_CHILE][1][56] = 20, + [2][1][2][1][RTW89_QATAR][1][56] = 127, + [2][1][2][1][RTW89_QATAR][0][56] = 127, + [2][1][2][1][RTW89_UK][1][56] = 127, + [2][1][2][1][RTW89_UK][0][56] = 127, + [2][1][2][1][RTW89_FCC][1][63] = 22, + [2][1][2][1][RTW89_FCC][2][63] = 58, + [2][1][2][1][RTW89_ETSI][1][63] = 127, + [2][1][2][1][RTW89_ETSI][0][63] = 127, + [2][1][2][1][RTW89_MKK][1][63] = 127, + [2][1][2][1][RTW89_MKK][0][63] = 127, + [2][1][2][1][RTW89_IC][1][63] = 22, + [2][1][2][1][RTW89_KCC][1][63] = 38, + [2][1][2][1][RTW89_KCC][0][63] = 127, + [2][1][2][1][RTW89_ACMA][1][63] = 127, + [2][1][2][1][RTW89_ACMA][0][63] = 127, + [2][1][2][1][RTW89_CHILE][1][63] = 22, + [2][1][2][1][RTW89_QATAR][1][63] = 127, + [2][1][2][1][RTW89_QATAR][0][63] = 127, + [2][1][2][1][RTW89_UK][1][63] = 127, + [2][1][2][1][RTW89_UK][0][63] = 127, + [2][1][2][1][RTW89_FCC][1][71] = 20, + [2][1][2][1][RTW89_FCC][2][71] = 58, + [2][1][2][1][RTW89_ETSI][1][71] = 127, + [2][1][2][1][RTW89_ETSI][0][71] = 127, + [2][1][2][1][RTW89_MKK][1][71] = 127, + [2][1][2][1][RTW89_MKK][0][71] = 127, + [2][1][2][1][RTW89_IC][1][71] = 20, + [2][1][2][1][RTW89_KCC][1][71] = 38, + [2][1][2][1][RTW89_KCC][0][71] = 127, + [2][1][2][1][RTW89_ACMA][1][71] = 127, + [2][1][2][1][RTW89_ACMA][0][71] = 127, + [2][1][2][1][RTW89_CHILE][1][71] = 20, + [2][1][2][1][RTW89_QATAR][1][71] = 127, + [2][1][2][1][RTW89_QATAR][0][71] = 127, + [2][1][2][1][RTW89_UK][1][71] = 127, + [2][1][2][1][RTW89_UK][0][71] = 127, + [2][1][2][1][RTW89_FCC][1][78] = 20, + [2][1][2][1][RTW89_FCC][2][78] = 58, + [2][1][2][1][RTW89_ETSI][1][78] = 127, + [2][1][2][1][RTW89_ETSI][0][78] = 127, + [2][1][2][1][RTW89_MKK][1][78] = 127, + [2][1][2][1][RTW89_MKK][0][78] = 127, + [2][1][2][1][RTW89_IC][1][78] = 20, + [2][1][2][1][RTW89_KCC][1][78] = 38, + [2][1][2][1][RTW89_KCC][0][78] = 127, + [2][1][2][1][RTW89_ACMA][1][78] = 127, + [2][1][2][1][RTW89_ACMA][0][78] = 127, + [2][1][2][1][RTW89_CHILE][1][78] = 20, + [2][1][2][1][RTW89_QATAR][1][78] = 127, + [2][1][2][1][RTW89_QATAR][0][78] = 127, + [2][1][2][1][RTW89_UK][1][78] = 127, + [2][1][2][1][RTW89_UK][0][78] = 127, + [2][1][2][1][RTW89_FCC][1][86] = 20, + [2][1][2][1][RTW89_FCC][2][86] = 127, + [2][1][2][1][RTW89_ETSI][1][86] = 127, + [2][1][2][1][RTW89_ETSI][0][86] = 127, + [2][1][2][1][RTW89_MKK][1][86] = 127, + [2][1][2][1][RTW89_MKK][0][86] = 127, + [2][1][2][1][RTW89_IC][1][86] = 20, + [2][1][2][1][RTW89_KCC][1][86] = 38, + [2][1][2][1][RTW89_KCC][0][86] = 127, + [2][1][2][1][RTW89_ACMA][1][86] = 127, + [2][1][2][1][RTW89_ACMA][0][86] = 127, + [2][1][2][1][RTW89_CHILE][1][86] = 20, + [2][1][2][1][RTW89_QATAR][1][86] = 127, + [2][1][2][1][RTW89_QATAR][0][86] = 127, + [2][1][2][1][RTW89_UK][1][86] = 127, + [2][1][2][1][RTW89_UK][0][86] = 127, + [2][1][2][1][RTW89_FCC][1][93] = 22, + [2][1][2][1][RTW89_FCC][2][93] = 127, + [2][1][2][1][RTW89_ETSI][1][93] = 127, + [2][1][2][1][RTW89_ETSI][0][93] = 127, + [2][1][2][1][RTW89_MKK][1][93] = 127, + [2][1][2][1][RTW89_MKK][0][93] = 127, + [2][1][2][1][RTW89_IC][1][93] = 22, + [2][1][2][1][RTW89_KCC][1][93] = 38, + [2][1][2][1][RTW89_KCC][0][93] = 127, + [2][1][2][1][RTW89_ACMA][1][93] = 127, + [2][1][2][1][RTW89_ACMA][0][93] = 127, + [2][1][2][1][RTW89_CHILE][1][93] = 22, + [2][1][2][1][RTW89_QATAR][1][93] = 127, + [2][1][2][1][RTW89_QATAR][0][93] = 127, + [2][1][2][1][RTW89_UK][1][93] = 127, + [2][1][2][1][RTW89_UK][0][93] = 127, + [2][1][2][1][RTW89_FCC][1][101] = 22, + [2][1][2][1][RTW89_FCC][2][101] = 127, + [2][1][2][1][RTW89_ETSI][1][101] = 127, + [2][1][2][1][RTW89_ETSI][0][101] = 127, + [2][1][2][1][RTW89_MKK][1][101] = 127, + [2][1][2][1][RTW89_MKK][0][101] = 127, + [2][1][2][1][RTW89_IC][1][101] = 22, + [2][1][2][1][RTW89_KCC][1][101] = 38, + [2][1][2][1][RTW89_KCC][0][101] = 127, + [2][1][2][1][RTW89_ACMA][1][101] = 127, + [2][1][2][1][RTW89_ACMA][0][101] = 127, + [2][1][2][1][RTW89_CHILE][1][101] = 22, + [2][1][2][1][RTW89_QATAR][1][101] = 127, + [2][1][2][1][RTW89_QATAR][0][101] = 127, + [2][1][2][1][RTW89_UK][1][101] = 127, + [2][1][2][1][RTW89_UK][0][101] = 127, + [2][1][2][1][RTW89_FCC][1][108] = 127, + [2][1][2][1][RTW89_FCC][2][108] = 127, + [2][1][2][1][RTW89_ETSI][1][108] = 127, + [2][1][2][1][RTW89_ETSI][0][108] = 127, + [2][1][2][1][RTW89_MKK][1][108] = 127, + [2][1][2][1][RTW89_MKK][0][108] = 127, + [2][1][2][1][RTW89_IC][1][108] = 127, + [2][1][2][1][RTW89_KCC][1][108] = 127, + [2][1][2][1][RTW89_KCC][0][108] = 127, + [2][1][2][1][RTW89_ACMA][1][108] = 127, + [2][1][2][1][RTW89_ACMA][0][108] = 127, + [2][1][2][1][RTW89_CHILE][1][108] = 127, + [2][1][2][1][RTW89_QATAR][1][108] = 127, + [2][1][2][1][RTW89_QATAR][0][108] = 127, + [2][1][2][1][RTW89_UK][1][108] = 127, + [2][1][2][1][RTW89_UK][0][108] = 127, + [2][1][2][1][RTW89_FCC][1][116] = 127, + [2][1][2][1][RTW89_FCC][2][116] = 127, + [2][1][2][1][RTW89_ETSI][1][116] = 127, + [2][1][2][1][RTW89_ETSI][0][116] = 127, + [2][1][2][1][RTW89_MKK][1][116] = 127, + [2][1][2][1][RTW89_MKK][0][116] = 127, + [2][1][2][1][RTW89_IC][1][116] = 127, + [2][1][2][1][RTW89_KCC][1][116] = 127, + [2][1][2][1][RTW89_KCC][0][116] = 127, + [2][1][2][1][RTW89_ACMA][1][116] = 127, + [2][1][2][1][RTW89_ACMA][0][116] = 127, + [2][1][2][1][RTW89_CHILE][1][116] = 127, + [2][1][2][1][RTW89_QATAR][1][116] = 127, + [2][1][2][1][RTW89_QATAR][0][116] = 127, + [2][1][2][1][RTW89_UK][1][116] = 127, + [2][1][2][1][RTW89_UK][0][116] = 127, + [3][0][2][0][RTW89_FCC][1][7] = 52, + [3][0][2][0][RTW89_FCC][2][7] = 52, + [3][0][2][0][RTW89_ETSI][1][7] = 50, + [3][0][2][0][RTW89_ETSI][0][7] = 30, + [3][0][2][0][RTW89_MKK][1][7] = 50, + [3][0][2][0][RTW89_MKK][0][7] = 22, + [3][0][2][0][RTW89_IC][1][7] = 52, + [3][0][2][0][RTW89_KCC][1][7] = 42, + [3][0][2][0][RTW89_KCC][0][7] = 24, + [3][0][2][0][RTW89_ACMA][1][7] = 50, + [3][0][2][0][RTW89_ACMA][0][7] = 30, + [3][0][2][0][RTW89_CHILE][1][7] = 52, + [3][0][2][0][RTW89_QATAR][1][7] = 50, + [3][0][2][0][RTW89_QATAR][0][7] = 30, + [3][0][2][0][RTW89_UK][1][7] = 50, + [3][0][2][0][RTW89_UK][0][7] = 30, + [3][0][2][0][RTW89_FCC][1][22] = 52, + [3][0][2][0][RTW89_FCC][2][22] = 52, + [3][0][2][0][RTW89_ETSI][1][22] = 50, + [3][0][2][0][RTW89_ETSI][0][22] = 30, + [3][0][2][0][RTW89_MKK][1][22] = 50, + [3][0][2][0][RTW89_MKK][0][22] = 20, + [3][0][2][0][RTW89_IC][1][22] = 52, + [3][0][2][0][RTW89_KCC][1][22] = 42, + [3][0][2][0][RTW89_KCC][0][22] = 24, + [3][0][2][0][RTW89_ACMA][1][22] = 50, + [3][0][2][0][RTW89_ACMA][0][22] = 30, + [3][0][2][0][RTW89_CHILE][1][22] = 52, + [3][0][2][0][RTW89_QATAR][1][22] = 50, + [3][0][2][0][RTW89_QATAR][0][22] = 30, + [3][0][2][0][RTW89_UK][1][22] = 50, + [3][0][2][0][RTW89_UK][0][22] = 30, + [3][0][2][0][RTW89_FCC][1][37] = 52, + [3][0][2][0][RTW89_FCC][2][37] = 52, + [3][0][2][0][RTW89_ETSI][1][37] = 50, + [3][0][2][0][RTW89_ETSI][0][37] = 30, + [3][0][2][0][RTW89_MKK][1][37] = 50, + [3][0][2][0][RTW89_MKK][0][37] = 20, + [3][0][2][0][RTW89_IC][1][37] = 52, + [3][0][2][0][RTW89_KCC][1][37] = 42, + [3][0][2][0][RTW89_KCC][0][37] = 24, + [3][0][2][0][RTW89_ACMA][1][37] = 50, + [3][0][2][0][RTW89_ACMA][0][37] = 30, + [3][0][2][0][RTW89_CHILE][1][37] = 52, + [3][0][2][0][RTW89_QATAR][1][37] = 50, + [3][0][2][0][RTW89_QATAR][0][37] = 30, + [3][0][2][0][RTW89_UK][1][37] = 50, + [3][0][2][0][RTW89_UK][0][37] = 30, + [3][0][2][0][RTW89_FCC][1][52] = 54, + [3][0][2][0][RTW89_FCC][2][52] = 127, + [3][0][2][0][RTW89_ETSI][1][52] = 127, + [3][0][2][0][RTW89_ETSI][0][52] = 127, + [3][0][2][0][RTW89_MKK][1][52] = 127, + [3][0][2][0][RTW89_MKK][0][52] = 127, + [3][0][2][0][RTW89_IC][1][52] = 54, + [3][0][2][0][RTW89_KCC][1][52] = 56, + [3][0][2][0][RTW89_KCC][0][52] = 127, + [3][0][2][0][RTW89_ACMA][1][52] = 127, + [3][0][2][0][RTW89_ACMA][0][52] = 127, + [3][0][2][0][RTW89_CHILE][1][52] = 54, + [3][0][2][0][RTW89_QATAR][1][52] = 127, + [3][0][2][0][RTW89_QATAR][0][52] = 127, + [3][0][2][0][RTW89_UK][1][52] = 127, + [3][0][2][0][RTW89_UK][0][52] = 127, + [3][0][2][0][RTW89_FCC][1][67] = 54, + [3][0][2][0][RTW89_FCC][2][67] = 54, + [3][0][2][0][RTW89_ETSI][1][67] = 127, + [3][0][2][0][RTW89_ETSI][0][67] = 127, + [3][0][2][0][RTW89_MKK][1][67] = 127, + [3][0][2][0][RTW89_MKK][0][67] = 127, + [3][0][2][0][RTW89_IC][1][67] = 54, + [3][0][2][0][RTW89_KCC][1][67] = 54, + [3][0][2][0][RTW89_KCC][0][67] = 127, + [3][0][2][0][RTW89_ACMA][1][67] = 127, + [3][0][2][0][RTW89_ACMA][0][67] = 127, + [3][0][2][0][RTW89_CHILE][1][67] = 54, + [3][0][2][0][RTW89_QATAR][1][67] = 127, + [3][0][2][0][RTW89_QATAR][0][67] = 127, + [3][0][2][0][RTW89_UK][1][67] = 127, + [3][0][2][0][RTW89_UK][0][67] = 127, + [3][0][2][0][RTW89_FCC][1][82] = 46, + [3][0][2][0][RTW89_FCC][2][82] = 127, + [3][0][2][0][RTW89_ETSI][1][82] = 127, + [3][0][2][0][RTW89_ETSI][0][82] = 127, + [3][0][2][0][RTW89_MKK][1][82] = 127, + [3][0][2][0][RTW89_MKK][0][82] = 127, + [3][0][2][0][RTW89_IC][1][82] = 46, + [3][0][2][0][RTW89_KCC][1][82] = 26, + [3][0][2][0][RTW89_KCC][0][82] = 127, + [3][0][2][0][RTW89_ACMA][1][82] = 127, + [3][0][2][0][RTW89_ACMA][0][82] = 127, + [3][0][2][0][RTW89_CHILE][1][82] = 46, + [3][0][2][0][RTW89_QATAR][1][82] = 127, + [3][0][2][0][RTW89_QATAR][0][82] = 127, + [3][0][2][0][RTW89_UK][1][82] = 127, + [3][0][2][0][RTW89_UK][0][82] = 127, + [3][0][2][0][RTW89_FCC][1][97] = 40, + [3][0][2][0][RTW89_FCC][2][97] = 127, + [3][0][2][0][RTW89_ETSI][1][97] = 127, + [3][0][2][0][RTW89_ETSI][0][97] = 127, + [3][0][2][0][RTW89_MKK][1][97] = 127, + [3][0][2][0][RTW89_MKK][0][97] = 127, + [3][0][2][0][RTW89_IC][1][97] = 40, + [3][0][2][0][RTW89_KCC][1][97] = 26, + [3][0][2][0][RTW89_KCC][0][97] = 127, + [3][0][2][0][RTW89_ACMA][1][97] = 127, + [3][0][2][0][RTW89_ACMA][0][97] = 127, + [3][0][2][0][RTW89_CHILE][1][97] = 40, + [3][0][2][0][RTW89_QATAR][1][97] = 127, + [3][0][2][0][RTW89_QATAR][0][97] = 127, + [3][0][2][0][RTW89_UK][1][97] = 127, + [3][0][2][0][RTW89_UK][0][97] = 127, + [3][0][2][0][RTW89_FCC][1][112] = 127, + [3][0][2][0][RTW89_FCC][2][112] = 127, + [3][0][2][0][RTW89_ETSI][1][112] = 127, + [3][0][2][0][RTW89_ETSI][0][112] = 127, + [3][0][2][0][RTW89_MKK][1][112] = 127, + [3][0][2][0][RTW89_MKK][0][112] = 127, + [3][0][2][0][RTW89_IC][1][112] = 127, + [3][0][2][0][RTW89_KCC][1][112] = 127, + [3][0][2][0][RTW89_KCC][0][112] = 127, + [3][0][2][0][RTW89_ACMA][1][112] = 127, + [3][0][2][0][RTW89_ACMA][0][112] = 127, + [3][0][2][0][RTW89_CHILE][1][112] = 127, + [3][0][2][0][RTW89_QATAR][1][112] = 127, + [3][0][2][0][RTW89_QATAR][0][112] = 127, + [3][0][2][0][RTW89_UK][1][112] = 127, + [3][0][2][0][RTW89_UK][0][112] = 127, + [3][1][2][0][RTW89_FCC][1][7] = 32, + [3][1][2][0][RTW89_FCC][2][7] = 46, + [3][1][2][0][RTW89_ETSI][1][7] = 50, + [3][1][2][0][RTW89_ETSI][0][7] = 18, + [3][1][2][0][RTW89_MKK][1][7] = 38, + [3][1][2][0][RTW89_MKK][0][7] = 10, + [3][1][2][0][RTW89_IC][1][7] = 32, + [3][1][2][0][RTW89_KCC][1][7] = 40, + [3][1][2][0][RTW89_KCC][0][7] = 12, + [3][1][2][0][RTW89_ACMA][1][7] = 50, + [3][1][2][0][RTW89_ACMA][0][7] = 18, + [3][1][2][0][RTW89_CHILE][1][7] = 32, + [3][1][2][0][RTW89_QATAR][1][7] = 50, + [3][1][2][0][RTW89_QATAR][0][7] = 18, + [3][1][2][0][RTW89_UK][1][7] = 50, + [3][1][2][0][RTW89_UK][0][7] = 18, + [3][1][2][0][RTW89_FCC][1][22] = 30, + [3][1][2][0][RTW89_FCC][2][22] = 52, + [3][1][2][0][RTW89_ETSI][1][22] = 46, + [3][1][2][0][RTW89_ETSI][0][22] = 16, + [3][1][2][0][RTW89_MKK][1][22] = 48, + [3][1][2][0][RTW89_MKK][0][22] = 8, + [3][1][2][0][RTW89_IC][1][22] = 30, + [3][1][2][0][RTW89_KCC][1][22] = 40, + [3][1][2][0][RTW89_KCC][0][22] = 12, + [3][1][2][0][RTW89_ACMA][1][22] = 46, + [3][1][2][0][RTW89_ACMA][0][22] = 16, + [3][1][2][0][RTW89_CHILE][1][22] = 30, + [3][1][2][0][RTW89_QATAR][1][22] = 46, + [3][1][2][0][RTW89_QATAR][0][22] = 16, + [3][1][2][0][RTW89_UK][1][22] = 46, + [3][1][2][0][RTW89_UK][0][22] = 16, + [3][1][2][0][RTW89_FCC][1][37] = 30, + [3][1][2][0][RTW89_FCC][2][37] = 52, + [3][1][2][0][RTW89_ETSI][1][37] = 46, + [3][1][2][0][RTW89_ETSI][0][37] = 16, + [3][1][2][0][RTW89_MKK][1][37] = 48, + [3][1][2][0][RTW89_MKK][0][37] = 8, + [3][1][2][0][RTW89_IC][1][37] = 30, + [3][1][2][0][RTW89_KCC][1][37] = 40, + [3][1][2][0][RTW89_KCC][0][37] = 12, + [3][1][2][0][RTW89_ACMA][1][37] = 46, + [3][1][2][0][RTW89_ACMA][0][37] = 16, + [3][1][2][0][RTW89_CHILE][1][37] = 30, + [3][1][2][0][RTW89_QATAR][1][37] = 46, + [3][1][2][0][RTW89_QATAR][0][37] = 16, + [3][1][2][0][RTW89_UK][1][37] = 46, + [3][1][2][0][RTW89_UK][0][37] = 16, + [3][1][2][0][RTW89_FCC][1][52] = 30, + [3][1][2][0][RTW89_FCC][2][52] = 127, + [3][1][2][0][RTW89_ETSI][1][52] = 127, + [3][1][2][0][RTW89_ETSI][0][52] = 127, + [3][1][2][0][RTW89_MKK][1][52] = 127, + [3][1][2][0][RTW89_MKK][0][52] = 127, + [3][1][2][0][RTW89_IC][1][52] = 30, + [3][1][2][0][RTW89_KCC][1][52] = 48, + [3][1][2][0][RTW89_KCC][0][52] = 127, + [3][1][2][0][RTW89_ACMA][1][52] = 127, + [3][1][2][0][RTW89_ACMA][0][52] = 127, + [3][1][2][0][RTW89_CHILE][1][52] = 30, + [3][1][2][0][RTW89_QATAR][1][52] = 127, + [3][1][2][0][RTW89_QATAR][0][52] = 127, + [3][1][2][0][RTW89_UK][1][52] = 127, + [3][1][2][0][RTW89_UK][0][52] = 127, + [3][1][2][0][RTW89_FCC][1][67] = 32, + [3][1][2][0][RTW89_FCC][2][67] = 54, + [3][1][2][0][RTW89_ETSI][1][67] = 127, + [3][1][2][0][RTW89_ETSI][0][67] = 127, + [3][1][2][0][RTW89_MKK][1][67] = 127, + [3][1][2][0][RTW89_MKK][0][67] = 127, + [3][1][2][0][RTW89_IC][1][67] = 32, + [3][1][2][0][RTW89_KCC][1][67] = 48, + [3][1][2][0][RTW89_KCC][0][67] = 127, + [3][1][2][0][RTW89_ACMA][1][67] = 127, + [3][1][2][0][RTW89_ACMA][0][67] = 127, + [3][1][2][0][RTW89_CHILE][1][67] = 32, + [3][1][2][0][RTW89_QATAR][1][67] = 127, + [3][1][2][0][RTW89_QATAR][0][67] = 127, + [3][1][2][0][RTW89_UK][1][67] = 127, + [3][1][2][0][RTW89_UK][0][67] = 127, + [3][1][2][0][RTW89_FCC][1][82] = 32, + [3][1][2][0][RTW89_FCC][2][82] = 127, + [3][1][2][0][RTW89_ETSI][1][82] = 127, + [3][1][2][0][RTW89_ETSI][0][82] = 127, + [3][1][2][0][RTW89_MKK][1][82] = 127, + [3][1][2][0][RTW89_MKK][0][82] = 127, + [3][1][2][0][RTW89_IC][1][82] = 32, + [3][1][2][0][RTW89_KCC][1][82] = 24, + [3][1][2][0][RTW89_KCC][0][82] = 127, + [3][1][2][0][RTW89_ACMA][1][82] = 127, + [3][1][2][0][RTW89_ACMA][0][82] = 127, + [3][1][2][0][RTW89_CHILE][1][82] = 32, + [3][1][2][0][RTW89_QATAR][1][82] = 127, + [3][1][2][0][RTW89_QATAR][0][82] = 127, + [3][1][2][0][RTW89_UK][1][82] = 127, + [3][1][2][0][RTW89_UK][0][82] = 127, + [3][1][2][0][RTW89_FCC][1][97] = 32, + [3][1][2][0][RTW89_FCC][2][97] = 127, + [3][1][2][0][RTW89_ETSI][1][97] = 127, + [3][1][2][0][RTW89_ETSI][0][97] = 127, + [3][1][2][0][RTW89_MKK][1][97] = 127, + [3][1][2][0][RTW89_MKK][0][97] = 127, + [3][1][2][0][RTW89_IC][1][97] = 32, + [3][1][2][0][RTW89_KCC][1][97] = 24, + [3][1][2][0][RTW89_KCC][0][97] = 127, + [3][1][2][0][RTW89_ACMA][1][97] = 127, + [3][1][2][0][RTW89_ACMA][0][97] = 127, + [3][1][2][0][RTW89_CHILE][1][97] = 32, + [3][1][2][0][RTW89_QATAR][1][97] = 127, + [3][1][2][0][RTW89_QATAR][0][97] = 127, + [3][1][2][0][RTW89_UK][1][97] = 127, + [3][1][2][0][RTW89_UK][0][97] = 127, + [3][1][2][0][RTW89_FCC][1][112] = 127, + [3][1][2][0][RTW89_FCC][2][112] = 127, + [3][1][2][0][RTW89_ETSI][1][112] = 127, + [3][1][2][0][RTW89_ETSI][0][112] = 127, + [3][1][2][0][RTW89_MKK][1][112] = 127, + [3][1][2][0][RTW89_MKK][0][112] = 127, + [3][1][2][0][RTW89_IC][1][112] = 127, + [3][1][2][0][RTW89_KCC][1][112] = 127, + [3][1][2][0][RTW89_KCC][0][112] = 127, + [3][1][2][0][RTW89_ACMA][1][112] = 127, + [3][1][2][0][RTW89_ACMA][0][112] = 127, + [3][1][2][0][RTW89_CHILE][1][112] = 127, + [3][1][2][0][RTW89_QATAR][1][112] = 127, + [3][1][2][0][RTW89_QATAR][0][112] = 127, + [3][1][2][0][RTW89_UK][1][112] = 127, + [3][1][2][0][RTW89_UK][0][112] = 127, + [3][1][2][1][RTW89_FCC][1][7] = 32, + [3][1][2][1][RTW89_FCC][2][7] = 46, + [3][1][2][1][RTW89_ETSI][1][7] = 42, + [3][1][2][1][RTW89_ETSI][0][7] = 6, + [3][1][2][1][RTW89_MKK][1][7] = 38, + [3][1][2][1][RTW89_MKK][0][7] = 10, + [3][1][2][1][RTW89_IC][1][7] = 32, + [3][1][2][1][RTW89_KCC][1][7] = 40, + [3][1][2][1][RTW89_KCC][0][7] = 12, + [3][1][2][1][RTW89_ACMA][1][7] = 42, + [3][1][2][1][RTW89_ACMA][0][7] = 6, + [3][1][2][1][RTW89_CHILE][1][7] = 32, + [3][1][2][1][RTW89_QATAR][1][7] = 42, + [3][1][2][1][RTW89_QATAR][0][7] = 6, + [3][1][2][1][RTW89_UK][1][7] = 42, + [3][1][2][1][RTW89_UK][0][7] = 6, + [3][1][2][1][RTW89_FCC][1][22] = 30, + [3][1][2][1][RTW89_FCC][2][22] = 52, + [3][1][2][1][RTW89_ETSI][1][22] = 42, + [3][1][2][1][RTW89_ETSI][0][22] = 6, + [3][1][2][1][RTW89_MKK][1][22] = 48, + [3][1][2][1][RTW89_MKK][0][22] = 8, + [3][1][2][1][RTW89_IC][1][22] = 30, + [3][1][2][1][RTW89_KCC][1][22] = 40, + [3][1][2][1][RTW89_KCC][0][22] = 12, + [3][1][2][1][RTW89_ACMA][1][22] = 42, + [3][1][2][1][RTW89_ACMA][0][22] = 6, + [3][1][2][1][RTW89_CHILE][1][22] = 30, + [3][1][2][1][RTW89_QATAR][1][22] = 42, + [3][1][2][1][RTW89_QATAR][0][22] = 6, + [3][1][2][1][RTW89_UK][1][22] = 42, + [3][1][2][1][RTW89_UK][0][22] = 6, + [3][1][2][1][RTW89_FCC][1][37] = 30, + [3][1][2][1][RTW89_FCC][2][37] = 52, + [3][1][2][1][RTW89_ETSI][1][37] = 42, + [3][1][2][1][RTW89_ETSI][0][37] = 6, + [3][1][2][1][RTW89_MKK][1][37] = 48, + [3][1][2][1][RTW89_MKK][0][37] = 8, + [3][1][2][1][RTW89_IC][1][37] = 30, + [3][1][2][1][RTW89_KCC][1][37] = 40, + [3][1][2][1][RTW89_KCC][0][37] = 12, + [3][1][2][1][RTW89_ACMA][1][37] = 42, + [3][1][2][1][RTW89_ACMA][0][37] = 6, + [3][1][2][1][RTW89_CHILE][1][37] = 30, + [3][1][2][1][RTW89_QATAR][1][37] = 42, + [3][1][2][1][RTW89_QATAR][0][37] = 6, + [3][1][2][1][RTW89_UK][1][37] = 42, + [3][1][2][1][RTW89_UK][0][37] = 6, + [3][1][2][1][RTW89_FCC][1][52] = 30, + [3][1][2][1][RTW89_FCC][2][52] = 127, + [3][1][2][1][RTW89_ETSI][1][52] = 127, + [3][1][2][1][RTW89_ETSI][0][52] = 127, + [3][1][2][1][RTW89_MKK][1][52] = 127, + [3][1][2][1][RTW89_MKK][0][52] = 127, + [3][1][2][1][RTW89_IC][1][52] = 30, + [3][1][2][1][RTW89_KCC][1][52] = 48, + [3][1][2][1][RTW89_KCC][0][52] = 127, + [3][1][2][1][RTW89_ACMA][1][52] = 127, + [3][1][2][1][RTW89_ACMA][0][52] = 127, + [3][1][2][1][RTW89_CHILE][1][52] = 30, + [3][1][2][1][RTW89_QATAR][1][52] = 127, + [3][1][2][1][RTW89_QATAR][0][52] = 127, + [3][1][2][1][RTW89_UK][1][52] = 127, + [3][1][2][1][RTW89_UK][0][52] = 127, + [3][1][2][1][RTW89_FCC][1][67] = 32, + [3][1][2][1][RTW89_FCC][2][67] = 54, + [3][1][2][1][RTW89_ETSI][1][67] = 127, + [3][1][2][1][RTW89_ETSI][0][67] = 127, + [3][1][2][1][RTW89_MKK][1][67] = 127, + [3][1][2][1][RTW89_MKK][0][67] = 127, + [3][1][2][1][RTW89_IC][1][67] = 32, + [3][1][2][1][RTW89_KCC][1][67] = 48, + [3][1][2][1][RTW89_KCC][0][67] = 127, + [3][1][2][1][RTW89_ACMA][1][67] = 127, + [3][1][2][1][RTW89_ACMA][0][67] = 127, + [3][1][2][1][RTW89_CHILE][1][67] = 32, + [3][1][2][1][RTW89_QATAR][1][67] = 127, + [3][1][2][1][RTW89_QATAR][0][67] = 127, + [3][1][2][1][RTW89_UK][1][67] = 127, + [3][1][2][1][RTW89_UK][0][67] = 127, + [3][1][2][1][RTW89_FCC][1][82] = 32, + [3][1][2][1][RTW89_FCC][2][82] = 127, + [3][1][2][1][RTW89_ETSI][1][82] = 127, + [3][1][2][1][RTW89_ETSI][0][82] = 127, + [3][1][2][1][RTW89_MKK][1][82] = 127, + [3][1][2][1][RTW89_MKK][0][82] = 127, + [3][1][2][1][RTW89_IC][1][82] = 32, + [3][1][2][1][RTW89_KCC][1][82] = 24, + [3][1][2][1][RTW89_KCC][0][82] = 127, + [3][1][2][1][RTW89_ACMA][1][82] = 127, + [3][1][2][1][RTW89_ACMA][0][82] = 127, + [3][1][2][1][RTW89_CHILE][1][82] = 32, + [3][1][2][1][RTW89_QATAR][1][82] = 127, + [3][1][2][1][RTW89_QATAR][0][82] = 127, + [3][1][2][1][RTW89_UK][1][82] = 127, + [3][1][2][1][RTW89_UK][0][82] = 127, + [3][1][2][1][RTW89_FCC][1][97] = 32, + [3][1][2][1][RTW89_FCC][2][97] = 127, + [3][1][2][1][RTW89_ETSI][1][97] = 127, + [3][1][2][1][RTW89_ETSI][0][97] = 127, + [3][1][2][1][RTW89_MKK][1][97] = 127, + [3][1][2][1][RTW89_MKK][0][97] = 127, + [3][1][2][1][RTW89_IC][1][97] = 32, + [3][1][2][1][RTW89_KCC][1][97] = 24, + [3][1][2][1][RTW89_KCC][0][97] = 127, + [3][1][2][1][RTW89_ACMA][1][97] = 127, + [3][1][2][1][RTW89_ACMA][0][97] = 127, + [3][1][2][1][RTW89_CHILE][1][97] = 32, + [3][1][2][1][RTW89_QATAR][1][97] = 127, + [3][1][2][1][RTW89_QATAR][0][97] = 127, + [3][1][2][1][RTW89_UK][1][97] = 127, + [3][1][2][1][RTW89_UK][0][97] = 127, + [3][1][2][1][RTW89_FCC][1][112] = 127, + [3][1][2][1][RTW89_FCC][2][112] = 127, + [3][1][2][1][RTW89_ETSI][1][112] = 127, + [3][1][2][1][RTW89_ETSI][0][112] = 127, + [3][1][2][1][RTW89_MKK][1][112] = 127, + [3][1][2][1][RTW89_MKK][0][112] = 127, + [3][1][2][1][RTW89_IC][1][112] = 127, + [3][1][2][1][RTW89_KCC][1][112] = 127, + [3][1][2][1][RTW89_KCC][0][112] = 127, + [3][1][2][1][RTW89_ACMA][1][112] = 127, + [3][1][2][1][RTW89_ACMA][0][112] = 127, + [3][1][2][1][RTW89_CHILE][1][112] = 127, + [3][1][2][1][RTW89_QATAR][1][112] = 127, + [3][1][2][1][RTW89_QATAR][0][112] = 127, + [3][1][2][1][RTW89_UK][1][112] = 127, + [3][1][2][1][RTW89_UK][0][112] = 127, }; static @@ -34017,10 +45842,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM] [1][0][RTW89_WW][3] = 44, [1][0][RTW89_WW][4] = 44, [1][0][RTW89_WW][5] = 44, - [1][0][RTW89_WW][6] = 44, - [1][0][RTW89_WW][7] = 44, - [1][0][RTW89_WW][8] = 44, - [1][0][RTW89_WW][9] = 44, + [1][0][RTW89_WW][6] = 40, + [1][0][RTW89_WW][7] = 40, + [1][0][RTW89_WW][8] = 40, + [1][0][RTW89_WW][9] = 40, [1][0][RTW89_WW][10] = 44, [1][0][RTW89_WW][11] = 36, [1][0][RTW89_WW][12] = 4, @@ -34031,24 +45856,24 @@ const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM] [1][1][RTW89_WW][3] = 32, [1][1][RTW89_WW][4] = 32, [1][1][RTW89_WW][5] = 32, - [1][1][RTW89_WW][6] = 32, - [1][1][RTW89_WW][7] = 32, - [1][1][RTW89_WW][8] = 32, - [1][1][RTW89_WW][9] = 32, + [1][1][RTW89_WW][6] = 30, + [1][1][RTW89_WW][7] = 30, + [1][1][RTW89_WW][8] = 30, + [1][1][RTW89_WW][9] = 30, [1][1][RTW89_WW][10] = 32, [1][1][RTW89_WW][11] = 30, [1][1][RTW89_WW][12] = -6, [1][1][RTW89_WW][13] = 0, [2][0][RTW89_WW][0] = 56, - [2][0][RTW89_WW][1] = 56, - [2][0][RTW89_WW][2] = 56, - [2][0][RTW89_WW][3] = 56, - [2][0][RTW89_WW][4] = 56, + [2][0][RTW89_WW][1] = 54, + [2][0][RTW89_WW][2] = 54, + [2][0][RTW89_WW][3] = 54, + [2][0][RTW89_WW][4] = 54, [2][0][RTW89_WW][5] = 56, - [2][0][RTW89_WW][6] = 56, - [2][0][RTW89_WW][7] = 56, - [2][0][RTW89_WW][8] = 56, - [2][0][RTW89_WW][9] = 56, + [2][0][RTW89_WW][6] = 48, + [2][0][RTW89_WW][7] = 48, + [2][0][RTW89_WW][8] = 48, + [2][0][RTW89_WW][9] = 48, [2][0][RTW89_WW][10] = 56, [2][0][RTW89_WW][11] = 48, [2][0][RTW89_WW][12] = 16, @@ -34059,10 +45884,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM] [2][1][RTW89_WW][3] = 44, [2][1][RTW89_WW][4] = 44, [2][1][RTW89_WW][5] = 44, - [2][1][RTW89_WW][6] = 44, - [2][1][RTW89_WW][7] = 44, - [2][1][RTW89_WW][8] = 44, - [2][1][RTW89_WW][9] = 44, + [2][1][RTW89_WW][6] = 42, + [2][1][RTW89_WW][7] = 42, + [2][1][RTW89_WW][8] = 42, + [2][1][RTW89_WW][9] = 42, [2][1][RTW89_WW][10] = 44, [2][1][RTW89_WW][11] = 44, [2][1][RTW89_WW][12] = 6, @@ -34075,6 +45900,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][0][RTW89_ACMA][0] = 34, [0][0][RTW89_CN][0] = 32, [0][0][RTW89_UK][0] = 34, + [0][0][RTW89_MEXICO][0] = 60, + [0][0][RTW89_UKRAINE][0] = 34, + [0][0][RTW89_CHILE][0] = 60, + [0][0][RTW89_QATAR][0] = 34, [0][0][RTW89_FCC][1] = 60, [0][0][RTW89_ETSI][1] = 38, [0][0][RTW89_MKK][1] = 40, @@ -34083,6 +45912,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][0][RTW89_ACMA][1] = 38, [0][0][RTW89_CN][1] = 32, [0][0][RTW89_UK][1] = 38, + [0][0][RTW89_MEXICO][1] = 60, + [0][0][RTW89_UKRAINE][1] = 38, + [0][0][RTW89_CHILE][1] = 50, + [0][0][RTW89_QATAR][1] = 38, [0][0][RTW89_FCC][2] = 64, [0][0][RTW89_ETSI][2] = 38, [0][0][RTW89_MKK][2] = 40, @@ -34091,6 +45924,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][0][RTW89_ACMA][2] = 38, [0][0][RTW89_CN][2] = 32, [0][0][RTW89_UK][2] = 38, + [0][0][RTW89_MEXICO][2] = 64, + [0][0][RTW89_UKRAINE][2] = 38, + [0][0][RTW89_CHILE][2] = 50, + [0][0][RTW89_QATAR][2] = 38, [0][0][RTW89_FCC][3] = 68, [0][0][RTW89_ETSI][3] = 38, [0][0][RTW89_MKK][3] = 40, @@ -34099,78 +45936,118 @@ const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][0][RTW89_ACMA][3] = 38, [0][0][RTW89_CN][3] = 32, [0][0][RTW89_UK][3] = 38, + [0][0][RTW89_MEXICO][3] = 68, + [0][0][RTW89_UKRAINE][3] = 38, + [0][0][RTW89_CHILE][3] = 50, + [0][0][RTW89_QATAR][3] = 38, [0][0][RTW89_FCC][4] = 68, [0][0][RTW89_ETSI][4] = 38, [0][0][RTW89_MKK][4] = 40, [0][0][RTW89_IC][4] = 68, - [0][0][RTW89_KCC][4] = 42, + [0][0][RTW89_KCC][4] = 44, [0][0][RTW89_ACMA][4] = 38, [0][0][RTW89_CN][4] = 32, [0][0][RTW89_UK][4] = 38, + [0][0][RTW89_MEXICO][4] = 68, + [0][0][RTW89_UKRAINE][4] = 38, + [0][0][RTW89_CHILE][4] = 50, + [0][0][RTW89_QATAR][4] = 38, [0][0][RTW89_FCC][5] = 78, [0][0][RTW89_ETSI][5] = 38, [0][0][RTW89_MKK][5] = 40, [0][0][RTW89_IC][5] = 78, - [0][0][RTW89_KCC][5] = 42, + [0][0][RTW89_KCC][5] = 44, [0][0][RTW89_ACMA][5] = 38, [0][0][RTW89_CN][5] = 32, [0][0][RTW89_UK][5] = 38, + [0][0][RTW89_MEXICO][5] = 78, + [0][0][RTW89_UKRAINE][5] = 38, + [0][0][RTW89_CHILE][5] = 78, + [0][0][RTW89_QATAR][5] = 38, [0][0][RTW89_FCC][6] = 54, [0][0][RTW89_ETSI][6] = 38, [0][0][RTW89_MKK][6] = 40, [0][0][RTW89_IC][6] = 54, - [0][0][RTW89_KCC][6] = 42, + [0][0][RTW89_KCC][6] = 44, [0][0][RTW89_ACMA][6] = 38, [0][0][RTW89_CN][6] = 32, [0][0][RTW89_UK][6] = 38, + [0][0][RTW89_MEXICO][6] = 54, + [0][0][RTW89_UKRAINE][6] = 38, + [0][0][RTW89_CHILE][6] = 36, + [0][0][RTW89_QATAR][6] = 38, [0][0][RTW89_FCC][7] = 54, [0][0][RTW89_ETSI][7] = 38, [0][0][RTW89_MKK][7] = 40, [0][0][RTW89_IC][7] = 54, - [0][0][RTW89_KCC][7] = 42, + [0][0][RTW89_KCC][7] = 44, [0][0][RTW89_ACMA][7] = 38, [0][0][RTW89_CN][7] = 32, [0][0][RTW89_UK][7] = 38, + [0][0][RTW89_MEXICO][7] = 54, + [0][0][RTW89_UKRAINE][7] = 38, + [0][0][RTW89_CHILE][7] = 36, + [0][0][RTW89_QATAR][7] = 38, [0][0][RTW89_FCC][8] = 50, [0][0][RTW89_ETSI][8] = 38, [0][0][RTW89_MKK][8] = 40, [0][0][RTW89_IC][8] = 50, - [0][0][RTW89_KCC][8] = 42, + [0][0][RTW89_KCC][8] = 44, [0][0][RTW89_ACMA][8] = 38, [0][0][RTW89_CN][8] = 32, [0][0][RTW89_UK][8] = 38, + [0][0][RTW89_MEXICO][8] = 50, + [0][0][RTW89_UKRAINE][8] = 38, + [0][0][RTW89_CHILE][8] = 36, + [0][0][RTW89_QATAR][8] = 38, [0][0][RTW89_FCC][9] = 46, [0][0][RTW89_ETSI][9] = 38, [0][0][RTW89_MKK][9] = 40, [0][0][RTW89_IC][9] = 46, - [0][0][RTW89_KCC][9] = 40, + [0][0][RTW89_KCC][9] = 42, [0][0][RTW89_ACMA][9] = 38, [0][0][RTW89_CN][9] = 32, [0][0][RTW89_UK][9] = 38, + [0][0][RTW89_MEXICO][9] = 46, + [0][0][RTW89_UKRAINE][9] = 38, + [0][0][RTW89_CHILE][9] = 36, + [0][0][RTW89_QATAR][9] = 38, [0][0][RTW89_FCC][10] = 46, [0][0][RTW89_ETSI][10] = 38, [0][0][RTW89_MKK][10] = 40, [0][0][RTW89_IC][10] = 46, - [0][0][RTW89_KCC][10] = 40, + [0][0][RTW89_KCC][10] = 42, [0][0][RTW89_ACMA][10] = 38, [0][0][RTW89_CN][10] = 32, [0][0][RTW89_UK][10] = 38, + [0][0][RTW89_MEXICO][10] = 46, + [0][0][RTW89_UKRAINE][10] = 38, + [0][0][RTW89_CHILE][10] = 46, + [0][0][RTW89_QATAR][10] = 38, [0][0][RTW89_FCC][11] = 26, [0][0][RTW89_ETSI][11] = 38, [0][0][RTW89_MKK][11] = 40, [0][0][RTW89_IC][11] = 26, - [0][0][RTW89_KCC][11] = 40, + [0][0][RTW89_KCC][11] = 42, [0][0][RTW89_ACMA][11] = 38, [0][0][RTW89_CN][11] = 32, [0][0][RTW89_UK][11] = 38, + [0][0][RTW89_MEXICO][11] = 26, + [0][0][RTW89_UKRAINE][11] = 38, + [0][0][RTW89_CHILE][11] = 26, + [0][0][RTW89_QATAR][11] = 38, [0][0][RTW89_FCC][12] = -20, [0][0][RTW89_ETSI][12] = 34, [0][0][RTW89_MKK][12] = 36, [0][0][RTW89_IC][12] = -20, - [0][0][RTW89_KCC][12] = 40, + [0][0][RTW89_KCC][12] = 42, [0][0][RTW89_ACMA][12] = 34, [0][0][RTW89_CN][12] = 32, [0][0][RTW89_UK][12] = 34, + [0][0][RTW89_MEXICO][12] = -20, + [0][0][RTW89_UKRAINE][12] = 34, + [0][0][RTW89_CHILE][12] = -20, + [0][0][RTW89_QATAR][12] = 34, [0][0][RTW89_FCC][13] = 127, [0][0][RTW89_ETSI][13] = 127, [0][0][RTW89_MKK][13] = 127, @@ -34179,6 +46056,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][0][RTW89_ACMA][13] = 127, [0][0][RTW89_CN][13] = 127, [0][0][RTW89_UK][13] = 127, + [0][0][RTW89_MEXICO][13] = 127, + [0][0][RTW89_UKRAINE][13] = 127, + [0][0][RTW89_CHILE][13] = 127, + [0][0][RTW89_QATAR][13] = 127, [0][1][RTW89_FCC][0] = 56, [0][1][RTW89_ETSI][0] = 22, [0][1][RTW89_MKK][0] = 24, @@ -34187,6 +46068,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][1][RTW89_ACMA][0] = 22, [0][1][RTW89_CN][0] = 20, [0][1][RTW89_UK][0] = 22, + [0][1][RTW89_MEXICO][0] = 56, + [0][1][RTW89_UKRAINE][0] = 22, + [0][1][RTW89_CHILE][0] = 56, + [0][1][RTW89_QATAR][0] = 22, [0][1][RTW89_FCC][1] = 56, [0][1][RTW89_ETSI][1] = 24, [0][1][RTW89_MKK][1] = 30, @@ -34195,6 +46080,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][1][RTW89_ACMA][1] = 24, [0][1][RTW89_CN][1] = 22, [0][1][RTW89_UK][1] = 24, + [0][1][RTW89_MEXICO][1] = 56, + [0][1][RTW89_UKRAINE][1] = 24, + [0][1][RTW89_CHILE][1] = 40, + [0][1][RTW89_QATAR][1] = 24, [0][1][RTW89_FCC][2] = 60, [0][1][RTW89_ETSI][2] = 24, [0][1][RTW89_MKK][2] = 30, @@ -34203,6 +46092,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][1][RTW89_ACMA][2] = 24, [0][1][RTW89_CN][2] = 22, [0][1][RTW89_UK][2] = 24, + [0][1][RTW89_MEXICO][2] = 60, + [0][1][RTW89_UKRAINE][2] = 24, + [0][1][RTW89_CHILE][2] = 40, + [0][1][RTW89_QATAR][2] = 24, [0][1][RTW89_FCC][3] = 64, [0][1][RTW89_ETSI][3] = 24, [0][1][RTW89_MKK][3] = 30, @@ -34211,78 +46104,118 @@ const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][1][RTW89_ACMA][3] = 24, [0][1][RTW89_CN][3] = 22, [0][1][RTW89_UK][3] = 24, + [0][1][RTW89_MEXICO][3] = 64, + [0][1][RTW89_UKRAINE][3] = 24, + [0][1][RTW89_CHILE][3] = 40, + [0][1][RTW89_QATAR][3] = 24, [0][1][RTW89_FCC][4] = 68, [0][1][RTW89_ETSI][4] = 24, [0][1][RTW89_MKK][4] = 30, [0][1][RTW89_IC][4] = 68, - [0][1][RTW89_KCC][4] = 28, + [0][1][RTW89_KCC][4] = 34, [0][1][RTW89_ACMA][4] = 24, [0][1][RTW89_CN][4] = 22, [0][1][RTW89_UK][4] = 24, + [0][1][RTW89_MEXICO][4] = 68, + [0][1][RTW89_UKRAINE][4] = 24, + [0][1][RTW89_CHILE][4] = 40, + [0][1][RTW89_QATAR][4] = 24, [0][1][RTW89_FCC][5] = 76, [0][1][RTW89_ETSI][5] = 24, [0][1][RTW89_MKK][5] = 30, [0][1][RTW89_IC][5] = 76, - [0][1][RTW89_KCC][5] = 28, + [0][1][RTW89_KCC][5] = 34, [0][1][RTW89_ACMA][5] = 24, [0][1][RTW89_CN][5] = 22, [0][1][RTW89_UK][5] = 24, + [0][1][RTW89_MEXICO][5] = 76, + [0][1][RTW89_UKRAINE][5] = 24, + [0][1][RTW89_CHILE][5] = 76, + [0][1][RTW89_QATAR][5] = 24, [0][1][RTW89_FCC][6] = 54, [0][1][RTW89_ETSI][6] = 24, [0][1][RTW89_MKK][6] = 30, [0][1][RTW89_IC][6] = 54, - [0][1][RTW89_KCC][6] = 28, + [0][1][RTW89_KCC][6] = 34, [0][1][RTW89_ACMA][6] = 24, [0][1][RTW89_CN][6] = 22, [0][1][RTW89_UK][6] = 24, + [0][1][RTW89_MEXICO][6] = 54, + [0][1][RTW89_UKRAINE][6] = 24, + [0][1][RTW89_CHILE][6] = 26, + [0][1][RTW89_QATAR][6] = 24, [0][1][RTW89_FCC][7] = 50, [0][1][RTW89_ETSI][7] = 24, [0][1][RTW89_MKK][7] = 30, [0][1][RTW89_IC][7] = 50, - [0][1][RTW89_KCC][7] = 28, + [0][1][RTW89_KCC][7] = 34, [0][1][RTW89_ACMA][7] = 24, [0][1][RTW89_CN][7] = 22, [0][1][RTW89_UK][7] = 24, + [0][1][RTW89_MEXICO][7] = 50, + [0][1][RTW89_UKRAINE][7] = 24, + [0][1][RTW89_CHILE][7] = 26, + [0][1][RTW89_QATAR][7] = 24, [0][1][RTW89_FCC][8] = 46, [0][1][RTW89_ETSI][8] = 24, [0][1][RTW89_MKK][8] = 30, [0][1][RTW89_IC][8] = 46, - [0][1][RTW89_KCC][8] = 28, + [0][1][RTW89_KCC][8] = 34, [0][1][RTW89_ACMA][8] = 24, [0][1][RTW89_CN][8] = 22, [0][1][RTW89_UK][8] = 24, + [0][1][RTW89_MEXICO][8] = 46, + [0][1][RTW89_UKRAINE][8] = 24, + [0][1][RTW89_CHILE][8] = 26, + [0][1][RTW89_QATAR][8] = 24, [0][1][RTW89_FCC][9] = 42, [0][1][RTW89_ETSI][9] = 24, [0][1][RTW89_MKK][9] = 30, [0][1][RTW89_IC][9] = 42, - [0][1][RTW89_KCC][9] = 28, + [0][1][RTW89_KCC][9] = 32, [0][1][RTW89_ACMA][9] = 24, [0][1][RTW89_CN][9] = 22, [0][1][RTW89_UK][9] = 24, + [0][1][RTW89_MEXICO][9] = 42, + [0][1][RTW89_UKRAINE][9] = 24, + [0][1][RTW89_CHILE][9] = 26, + [0][1][RTW89_QATAR][9] = 24, [0][1][RTW89_FCC][10] = 42, [0][1][RTW89_ETSI][10] = 24, [0][1][RTW89_MKK][10] = 30, [0][1][RTW89_IC][10] = 42, - [0][1][RTW89_KCC][10] = 28, + [0][1][RTW89_KCC][10] = 32, [0][1][RTW89_ACMA][10] = 24, [0][1][RTW89_CN][10] = 22, [0][1][RTW89_UK][10] = 24, + [0][1][RTW89_MEXICO][10] = 42, + [0][1][RTW89_UKRAINE][10] = 24, + [0][1][RTW89_CHILE][10] = 42, + [0][1][RTW89_QATAR][10] = 24, [0][1][RTW89_FCC][11] = 22, [0][1][RTW89_ETSI][11] = 24, [0][1][RTW89_MKK][11] = 30, [0][1][RTW89_IC][11] = 22, - [0][1][RTW89_KCC][11] = 28, + [0][1][RTW89_KCC][11] = 32, [0][1][RTW89_ACMA][11] = 24, [0][1][RTW89_CN][11] = 22, [0][1][RTW89_UK][11] = 24, + [0][1][RTW89_MEXICO][11] = 22, + [0][1][RTW89_UKRAINE][11] = 24, + [0][1][RTW89_CHILE][11] = 22, + [0][1][RTW89_QATAR][11] = 24, [0][1][RTW89_FCC][12] = -30, [0][1][RTW89_ETSI][12] = 20, [0][1][RTW89_MKK][12] = 24, [0][1][RTW89_IC][12] = -30, - [0][1][RTW89_KCC][12] = 28, + [0][1][RTW89_KCC][12] = 32, [0][1][RTW89_ACMA][12] = 20, [0][1][RTW89_CN][12] = 20, [0][1][RTW89_UK][12] = 20, + [0][1][RTW89_MEXICO][12] = -30, + [0][1][RTW89_UKRAINE][12] = 20, + [0][1][RTW89_CHILE][12] = -30, + [0][1][RTW89_QATAR][12] = 20, [0][1][RTW89_FCC][13] = 127, [0][1][RTW89_ETSI][13] = 127, [0][1][RTW89_MKK][13] = 127, @@ -34291,110 +46224,166 @@ const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][1][RTW89_ACMA][13] = 127, [0][1][RTW89_CN][13] = 127, [0][1][RTW89_UK][13] = 127, + [0][1][RTW89_MEXICO][13] = 127, + [0][1][RTW89_UKRAINE][13] = 127, + [0][1][RTW89_CHILE][13] = 127, + [0][1][RTW89_QATAR][13] = 127, [1][0][RTW89_FCC][0] = 66, [1][0][RTW89_ETSI][0] = 46, [1][0][RTW89_MKK][0] = 48, [1][0][RTW89_IC][0] = 66, - [1][0][RTW89_KCC][0] = 50, + [1][0][RTW89_KCC][0] = 54, [1][0][RTW89_ACMA][0] = 46, [1][0][RTW89_CN][0] = 42, [1][0][RTW89_UK][0] = 46, + [1][0][RTW89_MEXICO][0] = 66, + [1][0][RTW89_UKRAINE][0] = 46, + [1][0][RTW89_CHILE][0] = 66, + [1][0][RTW89_QATAR][0] = 46, [1][0][RTW89_FCC][1] = 66, [1][0][RTW89_ETSI][1] = 46, [1][0][RTW89_MKK][1] = 48, [1][0][RTW89_IC][1] = 66, - [1][0][RTW89_KCC][1] = 50, + [1][0][RTW89_KCC][1] = 54, [1][0][RTW89_ACMA][1] = 46, [1][0][RTW89_CN][1] = 44, [1][0][RTW89_UK][1] = 46, + [1][0][RTW89_MEXICO][1] = 66, + [1][0][RTW89_UKRAINE][1] = 46, + [1][0][RTW89_CHILE][1] = 54, + [1][0][RTW89_QATAR][1] = 46, [1][0][RTW89_FCC][2] = 70, [1][0][RTW89_ETSI][2] = 46, [1][0][RTW89_MKK][2] = 48, [1][0][RTW89_IC][2] = 70, - [1][0][RTW89_KCC][2] = 50, + [1][0][RTW89_KCC][2] = 54, [1][0][RTW89_ACMA][2] = 46, [1][0][RTW89_CN][2] = 44, [1][0][RTW89_UK][2] = 46, + [1][0][RTW89_MEXICO][2] = 70, + [1][0][RTW89_UKRAINE][2] = 46, + [1][0][RTW89_CHILE][2] = 54, + [1][0][RTW89_QATAR][2] = 46, [1][0][RTW89_FCC][3] = 72, [1][0][RTW89_ETSI][3] = 46, [1][0][RTW89_MKK][3] = 48, [1][0][RTW89_IC][3] = 72, - [1][0][RTW89_KCC][3] = 50, + [1][0][RTW89_KCC][3] = 54, [1][0][RTW89_ACMA][3] = 46, [1][0][RTW89_CN][3] = 44, [1][0][RTW89_UK][3] = 46, + [1][0][RTW89_MEXICO][3] = 72, + [1][0][RTW89_UKRAINE][3] = 46, + [1][0][RTW89_CHILE][3] = 54, + [1][0][RTW89_QATAR][3] = 46, [1][0][RTW89_FCC][4] = 72, [1][0][RTW89_ETSI][4] = 46, [1][0][RTW89_MKK][4] = 48, [1][0][RTW89_IC][4] = 72, - [1][0][RTW89_KCC][4] = 50, + [1][0][RTW89_KCC][4] = 56, [1][0][RTW89_ACMA][4] = 46, [1][0][RTW89_CN][4] = 44, [1][0][RTW89_UK][4] = 46, + [1][0][RTW89_MEXICO][4] = 72, + [1][0][RTW89_UKRAINE][4] = 46, + [1][0][RTW89_CHILE][4] = 54, + [1][0][RTW89_QATAR][4] = 46, [1][0][RTW89_FCC][5] = 82, [1][0][RTW89_ETSI][5] = 46, [1][0][RTW89_MKK][5] = 48, [1][0][RTW89_IC][5] = 82, - [1][0][RTW89_KCC][5] = 50, + [1][0][RTW89_KCC][5] = 56, [1][0][RTW89_ACMA][5] = 46, [1][0][RTW89_CN][5] = 44, [1][0][RTW89_UK][5] = 46, + [1][0][RTW89_MEXICO][5] = 82, + [1][0][RTW89_UKRAINE][5] = 46, + [1][0][RTW89_CHILE][5] = 82, + [1][0][RTW89_QATAR][5] = 46, [1][0][RTW89_FCC][6] = 58, [1][0][RTW89_ETSI][6] = 44, [1][0][RTW89_MKK][6] = 48, [1][0][RTW89_IC][6] = 58, - [1][0][RTW89_KCC][6] = 50, + [1][0][RTW89_KCC][6] = 56, [1][0][RTW89_ACMA][6] = 44, [1][0][RTW89_CN][6] = 44, [1][0][RTW89_UK][6] = 44, + [1][0][RTW89_MEXICO][6] = 58, + [1][0][RTW89_UKRAINE][6] = 44, + [1][0][RTW89_CHILE][6] = 40, + [1][0][RTW89_QATAR][6] = 44, [1][0][RTW89_FCC][7] = 58, [1][0][RTW89_ETSI][7] = 46, [1][0][RTW89_MKK][7] = 48, [1][0][RTW89_IC][7] = 58, - [1][0][RTW89_KCC][7] = 50, + [1][0][RTW89_KCC][7] = 56, [1][0][RTW89_ACMA][7] = 46, [1][0][RTW89_CN][7] = 44, [1][0][RTW89_UK][7] = 46, + [1][0][RTW89_MEXICO][7] = 58, + [1][0][RTW89_UKRAINE][7] = 46, + [1][0][RTW89_CHILE][7] = 40, + [1][0][RTW89_QATAR][7] = 46, [1][0][RTW89_FCC][8] = 58, [1][0][RTW89_ETSI][8] = 46, [1][0][RTW89_MKK][8] = 48, [1][0][RTW89_IC][8] = 58, - [1][0][RTW89_KCC][8] = 50, + [1][0][RTW89_KCC][8] = 56, [1][0][RTW89_ACMA][8] = 46, [1][0][RTW89_CN][8] = 44, [1][0][RTW89_UK][8] = 46, + [1][0][RTW89_MEXICO][8] = 58, + [1][0][RTW89_UKRAINE][8] = 46, + [1][0][RTW89_CHILE][8] = 40, + [1][0][RTW89_QATAR][8] = 46, [1][0][RTW89_FCC][9] = 54, [1][0][RTW89_ETSI][9] = 46, [1][0][RTW89_MKK][9] = 48, [1][0][RTW89_IC][9] = 54, - [1][0][RTW89_KCC][9] = 50, + [1][0][RTW89_KCC][9] = 56, [1][0][RTW89_ACMA][9] = 46, [1][0][RTW89_CN][9] = 44, [1][0][RTW89_UK][9] = 46, + [1][0][RTW89_MEXICO][9] = 54, + [1][0][RTW89_UKRAINE][9] = 46, + [1][0][RTW89_CHILE][9] = 40, + [1][0][RTW89_QATAR][9] = 46, [1][0][RTW89_FCC][10] = 54, [1][0][RTW89_ETSI][10] = 46, [1][0][RTW89_MKK][10] = 48, [1][0][RTW89_IC][10] = 54, - [1][0][RTW89_KCC][10] = 50, + [1][0][RTW89_KCC][10] = 56, [1][0][RTW89_ACMA][10] = 46, [1][0][RTW89_CN][10] = 44, [1][0][RTW89_UK][10] = 46, + [1][0][RTW89_MEXICO][10] = 54, + [1][0][RTW89_UKRAINE][10] = 46, + [1][0][RTW89_CHILE][10] = 54, + [1][0][RTW89_QATAR][10] = 46, [1][0][RTW89_FCC][11] = 36, [1][0][RTW89_ETSI][11] = 46, [1][0][RTW89_MKK][11] = 48, [1][0][RTW89_IC][11] = 36, - [1][0][RTW89_KCC][11] = 50, + [1][0][RTW89_KCC][11] = 56, [1][0][RTW89_ACMA][11] = 46, [1][0][RTW89_CN][11] = 44, [1][0][RTW89_UK][11] = 46, + [1][0][RTW89_MEXICO][11] = 36, + [1][0][RTW89_UKRAINE][11] = 46, + [1][0][RTW89_CHILE][11] = 36, + [1][0][RTW89_QATAR][11] = 46, [1][0][RTW89_FCC][12] = 4, [1][0][RTW89_ETSI][12] = 46, [1][0][RTW89_MKK][12] = 46, [1][0][RTW89_IC][12] = 4, - [1][0][RTW89_KCC][12] = 50, + [1][0][RTW89_KCC][12] = 56, [1][0][RTW89_ACMA][12] = 46, [1][0][RTW89_CN][12] = 42, [1][0][RTW89_UK][12] = 46, + [1][0][RTW89_MEXICO][12] = 4, + [1][0][RTW89_UKRAINE][12] = 46, + [1][0][RTW89_CHILE][12] = 4, + [1][0][RTW89_QATAR][12] = 46, [1][0][RTW89_FCC][13] = 127, [1][0][RTW89_ETSI][13] = 127, [1][0][RTW89_MKK][13] = 127, @@ -34403,110 +46392,166 @@ const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM] [1][0][RTW89_ACMA][13] = 127, [1][0][RTW89_CN][13] = 127, [1][0][RTW89_UK][13] = 127, + [1][0][RTW89_MEXICO][13] = 127, + [1][0][RTW89_UKRAINE][13] = 127, + [1][0][RTW89_CHILE][13] = 127, + [1][0][RTW89_QATAR][13] = 127, [1][1][RTW89_FCC][0] = 58, [1][1][RTW89_ETSI][0] = 32, [1][1][RTW89_MKK][0] = 34, [1][1][RTW89_IC][0] = 58, - [1][1][RTW89_KCC][0] = 38, + [1][1][RTW89_KCC][0] = 42, [1][1][RTW89_ACMA][0] = 32, [1][1][RTW89_CN][0] = 32, [1][1][RTW89_UK][0] = 32, + [1][1][RTW89_MEXICO][0] = 58, + [1][1][RTW89_UKRAINE][0] = 32, + [1][1][RTW89_CHILE][0] = 58, + [1][1][RTW89_QATAR][0] = 32, [1][1][RTW89_FCC][1] = 58, [1][1][RTW89_ETSI][1] = 34, [1][1][RTW89_MKK][1] = 34, [1][1][RTW89_IC][1] = 58, - [1][1][RTW89_KCC][1] = 38, + [1][1][RTW89_KCC][1] = 42, [1][1][RTW89_ACMA][1] = 34, [1][1][RTW89_CN][1] = 32, [1][1][RTW89_UK][1] = 34, + [1][1][RTW89_MEXICO][1] = 58, + [1][1][RTW89_UKRAINE][1] = 34, + [1][1][RTW89_CHILE][1] = 40, + [1][1][RTW89_QATAR][1] = 34, [1][1][RTW89_FCC][2] = 62, [1][1][RTW89_ETSI][2] = 34, [1][1][RTW89_MKK][2] = 34, [1][1][RTW89_IC][2] = 62, - [1][1][RTW89_KCC][2] = 38, + [1][1][RTW89_KCC][2] = 42, [1][1][RTW89_ACMA][2] = 34, [1][1][RTW89_CN][2] = 32, [1][1][RTW89_UK][2] = 34, + [1][1][RTW89_MEXICO][2] = 62, + [1][1][RTW89_UKRAINE][2] = 34, + [1][1][RTW89_CHILE][2] = 40, + [1][1][RTW89_QATAR][2] = 34, [1][1][RTW89_FCC][3] = 66, [1][1][RTW89_ETSI][3] = 34, [1][1][RTW89_MKK][3] = 34, [1][1][RTW89_IC][3] = 66, - [1][1][RTW89_KCC][3] = 38, + [1][1][RTW89_KCC][3] = 42, [1][1][RTW89_ACMA][3] = 34, [1][1][RTW89_CN][3] = 32, [1][1][RTW89_UK][3] = 34, + [1][1][RTW89_MEXICO][3] = 66, + [1][1][RTW89_UKRAINE][3] = 34, + [1][1][RTW89_CHILE][3] = 40, + [1][1][RTW89_QATAR][3] = 34, [1][1][RTW89_FCC][4] = 70, [1][1][RTW89_ETSI][4] = 34, [1][1][RTW89_MKK][4] = 34, [1][1][RTW89_IC][4] = 70, - [1][1][RTW89_KCC][4] = 38, + [1][1][RTW89_KCC][4] = 44, [1][1][RTW89_ACMA][4] = 34, [1][1][RTW89_CN][4] = 32, [1][1][RTW89_UK][4] = 34, + [1][1][RTW89_MEXICO][4] = 70, + [1][1][RTW89_UKRAINE][4] = 34, + [1][1][RTW89_CHILE][4] = 40, + [1][1][RTW89_QATAR][4] = 34, [1][1][RTW89_FCC][5] = 82, [1][1][RTW89_ETSI][5] = 34, [1][1][RTW89_MKK][5] = 34, [1][1][RTW89_IC][5] = 82, - [1][1][RTW89_KCC][5] = 38, + [1][1][RTW89_KCC][5] = 44, [1][1][RTW89_ACMA][5] = 34, [1][1][RTW89_CN][5] = 32, [1][1][RTW89_UK][5] = 34, + [1][1][RTW89_MEXICO][5] = 82, + [1][1][RTW89_UKRAINE][5] = 34, + [1][1][RTW89_CHILE][5] = 78, + [1][1][RTW89_QATAR][5] = 34, [1][1][RTW89_FCC][6] = 60, [1][1][RTW89_ETSI][6] = 34, [1][1][RTW89_MKK][6] = 34, [1][1][RTW89_IC][6] = 60, - [1][1][RTW89_KCC][6] = 38, + [1][1][RTW89_KCC][6] = 44, [1][1][RTW89_ACMA][6] = 34, [1][1][RTW89_CN][6] = 32, [1][1][RTW89_UK][6] = 34, + [1][1][RTW89_MEXICO][6] = 60, + [1][1][RTW89_UKRAINE][6] = 34, + [1][1][RTW89_CHILE][6] = 30, + [1][1][RTW89_QATAR][6] = 34, [1][1][RTW89_FCC][7] = 56, [1][1][RTW89_ETSI][7] = 34, [1][1][RTW89_MKK][7] = 34, [1][1][RTW89_IC][7] = 56, - [1][1][RTW89_KCC][7] = 38, + [1][1][RTW89_KCC][7] = 44, [1][1][RTW89_ACMA][7] = 34, [1][1][RTW89_CN][7] = 32, [1][1][RTW89_UK][7] = 34, + [1][1][RTW89_MEXICO][7] = 56, + [1][1][RTW89_UKRAINE][7] = 34, + [1][1][RTW89_CHILE][7] = 30, + [1][1][RTW89_QATAR][7] = 34, [1][1][RTW89_FCC][8] = 52, [1][1][RTW89_ETSI][8] = 34, [1][1][RTW89_MKK][8] = 34, [1][1][RTW89_IC][8] = 52, - [1][1][RTW89_KCC][8] = 38, + [1][1][RTW89_KCC][8] = 44, [1][1][RTW89_ACMA][8] = 34, [1][1][RTW89_CN][8] = 32, [1][1][RTW89_UK][8] = 34, + [1][1][RTW89_MEXICO][8] = 52, + [1][1][RTW89_UKRAINE][8] = 34, + [1][1][RTW89_CHILE][8] = 30, + [1][1][RTW89_QATAR][8] = 34, [1][1][RTW89_FCC][9] = 48, [1][1][RTW89_ETSI][9] = 34, [1][1][RTW89_MKK][9] = 34, [1][1][RTW89_IC][9] = 48, - [1][1][RTW89_KCC][9] = 38, + [1][1][RTW89_KCC][9] = 44, [1][1][RTW89_ACMA][9] = 34, [1][1][RTW89_CN][9] = 32, [1][1][RTW89_UK][9] = 34, + [1][1][RTW89_MEXICO][9] = 48, + [1][1][RTW89_UKRAINE][9] = 34, + [1][1][RTW89_CHILE][9] = 30, + [1][1][RTW89_QATAR][9] = 34, [1][1][RTW89_FCC][10] = 48, [1][1][RTW89_ETSI][10] = 34, [1][1][RTW89_MKK][10] = 34, [1][1][RTW89_IC][10] = 48, - [1][1][RTW89_KCC][10] = 38, + [1][1][RTW89_KCC][10] = 44, [1][1][RTW89_ACMA][10] = 34, [1][1][RTW89_CN][10] = 32, [1][1][RTW89_UK][10] = 34, + [1][1][RTW89_MEXICO][10] = 48, + [1][1][RTW89_UKRAINE][10] = 34, + [1][1][RTW89_CHILE][10] = 48, + [1][1][RTW89_QATAR][10] = 34, [1][1][RTW89_FCC][11] = 30, [1][1][RTW89_ETSI][11] = 34, [1][1][RTW89_MKK][11] = 34, [1][1][RTW89_IC][11] = 30, - [1][1][RTW89_KCC][11] = 38, + [1][1][RTW89_KCC][11] = 44, [1][1][RTW89_ACMA][11] = 34, [1][1][RTW89_CN][11] = 32, [1][1][RTW89_UK][11] = 34, + [1][1][RTW89_MEXICO][11] = 30, + [1][1][RTW89_UKRAINE][11] = 34, + [1][1][RTW89_CHILE][11] = 30, + [1][1][RTW89_QATAR][11] = 34, [1][1][RTW89_FCC][12] = -6, [1][1][RTW89_ETSI][12] = 34, [1][1][RTW89_MKK][12] = 34, [1][1][RTW89_IC][12] = -6, - [1][1][RTW89_KCC][12] = 38, + [1][1][RTW89_KCC][12] = 44, [1][1][RTW89_ACMA][12] = 34, [1][1][RTW89_CN][12] = 32, [1][1][RTW89_UK][12] = 34, + [1][1][RTW89_MEXICO][12] = -6, + [1][1][RTW89_UKRAINE][12] = 34, + [1][1][RTW89_CHILE][12] = -6, + [1][1][RTW89_QATAR][12] = 34, [1][1][RTW89_FCC][13] = 127, [1][1][RTW89_ETSI][13] = 127, [1][1][RTW89_MKK][13] = 127, @@ -34515,110 +46560,166 @@ const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM] [1][1][RTW89_ACMA][13] = 127, [1][1][RTW89_CN][13] = 127, [1][1][RTW89_UK][13] = 127, + [1][1][RTW89_MEXICO][13] = 127, + [1][1][RTW89_UKRAINE][13] = 127, + [1][1][RTW89_CHILE][13] = 127, + [1][1][RTW89_QATAR][13] = 127, [2][0][RTW89_FCC][0] = 70, [2][0][RTW89_ETSI][0] = 58, [2][0][RTW89_MKK][0] = 58, [2][0][RTW89_IC][0] = 70, - [2][0][RTW89_KCC][0] = 64, + [2][0][RTW89_KCC][0] = 60, [2][0][RTW89_ACMA][0] = 58, [2][0][RTW89_CN][0] = 56, [2][0][RTW89_UK][0] = 58, + [2][0][RTW89_MEXICO][0] = 70, + [2][0][RTW89_UKRAINE][0] = 58, + [2][0][RTW89_CHILE][0] = 70, + [2][0][RTW89_QATAR][0] = 58, [2][0][RTW89_FCC][1] = 70, [2][0][RTW89_ETSI][1] = 58, [2][0][RTW89_MKK][1] = 58, [2][0][RTW89_IC][1] = 70, - [2][0][RTW89_KCC][1] = 64, + [2][0][RTW89_KCC][1] = 60, [2][0][RTW89_ACMA][1] = 58, [2][0][RTW89_CN][1] = 56, [2][0][RTW89_UK][1] = 58, + [2][0][RTW89_MEXICO][1] = 70, + [2][0][RTW89_UKRAINE][1] = 58, + [2][0][RTW89_CHILE][1] = 54, + [2][0][RTW89_QATAR][1] = 58, [2][0][RTW89_FCC][2] = 72, [2][0][RTW89_ETSI][2] = 58, [2][0][RTW89_MKK][2] = 58, [2][0][RTW89_IC][2] = 72, - [2][0][RTW89_KCC][2] = 64, + [2][0][RTW89_KCC][2] = 60, [2][0][RTW89_ACMA][2] = 58, [2][0][RTW89_CN][2] = 56, [2][0][RTW89_UK][2] = 58, + [2][0][RTW89_MEXICO][2] = 72, + [2][0][RTW89_UKRAINE][2] = 58, + [2][0][RTW89_CHILE][2] = 54, + [2][0][RTW89_QATAR][2] = 58, [2][0][RTW89_FCC][3] = 72, [2][0][RTW89_ETSI][3] = 58, [2][0][RTW89_MKK][3] = 58, [2][0][RTW89_IC][3] = 72, - [2][0][RTW89_KCC][3] = 64, + [2][0][RTW89_KCC][3] = 60, [2][0][RTW89_ACMA][3] = 58, [2][0][RTW89_CN][3] = 56, [2][0][RTW89_UK][3] = 58, + [2][0][RTW89_MEXICO][3] = 72, + [2][0][RTW89_UKRAINE][3] = 58, + [2][0][RTW89_CHILE][3] = 54, + [2][0][RTW89_QATAR][3] = 58, [2][0][RTW89_FCC][4] = 72, [2][0][RTW89_ETSI][4] = 58, [2][0][RTW89_MKK][4] = 58, [2][0][RTW89_IC][4] = 72, - [2][0][RTW89_KCC][4] = 64, + [2][0][RTW89_KCC][4] = 60, [2][0][RTW89_ACMA][4] = 58, [2][0][RTW89_CN][4] = 56, [2][0][RTW89_UK][4] = 58, + [2][0][RTW89_MEXICO][4] = 72, + [2][0][RTW89_UKRAINE][4] = 58, + [2][0][RTW89_CHILE][4] = 54, + [2][0][RTW89_QATAR][4] = 58, [2][0][RTW89_FCC][5] = 82, [2][0][RTW89_ETSI][5] = 58, [2][0][RTW89_MKK][5] = 58, [2][0][RTW89_IC][5] = 82, - [2][0][RTW89_KCC][5] = 64, + [2][0][RTW89_KCC][5] = 60, [2][0][RTW89_ACMA][5] = 58, [2][0][RTW89_CN][5] = 56, [2][0][RTW89_UK][5] = 58, + [2][0][RTW89_MEXICO][5] = 82, + [2][0][RTW89_UKRAINE][5] = 58, + [2][0][RTW89_CHILE][5] = 82, + [2][0][RTW89_QATAR][5] = 58, [2][0][RTW89_FCC][6] = 66, [2][0][RTW89_ETSI][6] = 56, [2][0][RTW89_MKK][6] = 58, [2][0][RTW89_IC][6] = 66, - [2][0][RTW89_KCC][6] = 64, + [2][0][RTW89_KCC][6] = 60, [2][0][RTW89_ACMA][6] = 56, [2][0][RTW89_CN][6] = 56, [2][0][RTW89_UK][6] = 56, + [2][0][RTW89_MEXICO][6] = 66, + [2][0][RTW89_UKRAINE][6] = 56, + [2][0][RTW89_CHILE][6] = 48, + [2][0][RTW89_QATAR][6] = 56, [2][0][RTW89_FCC][7] = 66, [2][0][RTW89_ETSI][7] = 58, [2][0][RTW89_MKK][7] = 58, [2][0][RTW89_IC][7] = 66, - [2][0][RTW89_KCC][7] = 64, + [2][0][RTW89_KCC][7] = 60, [2][0][RTW89_ACMA][7] = 58, [2][0][RTW89_CN][7] = 56, [2][0][RTW89_UK][7] = 58, + [2][0][RTW89_MEXICO][7] = 66, + [2][0][RTW89_UKRAINE][7] = 58, + [2][0][RTW89_CHILE][7] = 48, + [2][0][RTW89_QATAR][7] = 58, [2][0][RTW89_FCC][8] = 66, [2][0][RTW89_ETSI][8] = 58, [2][0][RTW89_MKK][8] = 58, [2][0][RTW89_IC][8] = 66, - [2][0][RTW89_KCC][8] = 64, + [2][0][RTW89_KCC][8] = 60, [2][0][RTW89_ACMA][8] = 58, [2][0][RTW89_CN][8] = 56, [2][0][RTW89_UK][8] = 58, + [2][0][RTW89_MEXICO][8] = 66, + [2][0][RTW89_UKRAINE][8] = 58, + [2][0][RTW89_CHILE][8] = 48, + [2][0][RTW89_QATAR][8] = 58, [2][0][RTW89_FCC][9] = 64, [2][0][RTW89_ETSI][9] = 58, [2][0][RTW89_MKK][9] = 58, [2][0][RTW89_IC][9] = 64, - [2][0][RTW89_KCC][9] = 64, + [2][0][RTW89_KCC][9] = 60, [2][0][RTW89_ACMA][9] = 58, [2][0][RTW89_CN][9] = 56, [2][0][RTW89_UK][9] = 58, + [2][0][RTW89_MEXICO][9] = 64, + [2][0][RTW89_UKRAINE][9] = 58, + [2][0][RTW89_CHILE][9] = 48, + [2][0][RTW89_QATAR][9] = 58, [2][0][RTW89_FCC][10] = 64, [2][0][RTW89_ETSI][10] = 58, [2][0][RTW89_MKK][10] = 58, [2][0][RTW89_IC][10] = 64, - [2][0][RTW89_KCC][10] = 64, + [2][0][RTW89_KCC][10] = 60, [2][0][RTW89_ACMA][10] = 58, [2][0][RTW89_CN][10] = 56, [2][0][RTW89_UK][10] = 58, + [2][0][RTW89_MEXICO][10] = 64, + [2][0][RTW89_UKRAINE][10] = 58, + [2][0][RTW89_CHILE][10] = 64, + [2][0][RTW89_QATAR][10] = 58, [2][0][RTW89_FCC][11] = 48, [2][0][RTW89_ETSI][11] = 58, [2][0][RTW89_MKK][11] = 58, [2][0][RTW89_IC][11] = 48, - [2][0][RTW89_KCC][11] = 64, + [2][0][RTW89_KCC][11] = 60, [2][0][RTW89_ACMA][11] = 58, [2][0][RTW89_CN][11] = 56, [2][0][RTW89_UK][11] = 58, + [2][0][RTW89_MEXICO][11] = 48, + [2][0][RTW89_UKRAINE][11] = 58, + [2][0][RTW89_CHILE][11] = 48, + [2][0][RTW89_QATAR][11] = 58, [2][0][RTW89_FCC][12] = 16, [2][0][RTW89_ETSI][12] = 58, [2][0][RTW89_MKK][12] = 58, [2][0][RTW89_IC][12] = 16, - [2][0][RTW89_KCC][12] = 64, + [2][0][RTW89_KCC][12] = 60, [2][0][RTW89_ACMA][12] = 58, [2][0][RTW89_CN][12] = 56, [2][0][RTW89_UK][12] = 58, + [2][0][RTW89_MEXICO][12] = 16, + [2][0][RTW89_UKRAINE][12] = 58, + [2][0][RTW89_CHILE][12] = 16, + [2][0][RTW89_QATAR][12] = 58, [2][0][RTW89_FCC][13] = 127, [2][0][RTW89_ETSI][13] = 127, [2][0][RTW89_MKK][13] = 127, @@ -34627,110 +46728,166 @@ const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM] [2][0][RTW89_ACMA][13] = 127, [2][0][RTW89_CN][13] = 127, [2][0][RTW89_UK][13] = 127, + [2][0][RTW89_MEXICO][13] = 127, + [2][0][RTW89_UKRAINE][13] = 127, + [2][0][RTW89_CHILE][13] = 127, + [2][0][RTW89_QATAR][13] = 127, [2][1][RTW89_FCC][0] = 64, [2][1][RTW89_ETSI][0] = 46, [2][1][RTW89_MKK][0] = 46, [2][1][RTW89_IC][0] = 64, - [2][1][RTW89_KCC][0] = 52, + [2][1][RTW89_KCC][0] = 48, [2][1][RTW89_ACMA][0] = 46, [2][1][RTW89_CN][0] = 44, [2][1][RTW89_UK][0] = 46, + [2][1][RTW89_MEXICO][0] = 64, + [2][1][RTW89_UKRAINE][0] = 46, + [2][1][RTW89_CHILE][0] = 64, + [2][1][RTW89_QATAR][0] = 46, [2][1][RTW89_FCC][1] = 64, [2][1][RTW89_ETSI][1] = 46, [2][1][RTW89_MKK][1] = 46, [2][1][RTW89_IC][1] = 64, - [2][1][RTW89_KCC][1] = 52, + [2][1][RTW89_KCC][1] = 48, [2][1][RTW89_ACMA][1] = 46, [2][1][RTW89_CN][1] = 44, [2][1][RTW89_UK][1] = 46, + [2][1][RTW89_MEXICO][1] = 64, + [2][1][RTW89_UKRAINE][1] = 46, + [2][1][RTW89_CHILE][1] = 44, + [2][1][RTW89_QATAR][1] = 46, [2][1][RTW89_FCC][2] = 68, [2][1][RTW89_ETSI][2] = 46, [2][1][RTW89_MKK][2] = 46, [2][1][RTW89_IC][2] = 68, - [2][1][RTW89_KCC][2] = 52, + [2][1][RTW89_KCC][2] = 48, [2][1][RTW89_ACMA][2] = 46, [2][1][RTW89_CN][2] = 44, [2][1][RTW89_UK][2] = 46, + [2][1][RTW89_MEXICO][2] = 68, + [2][1][RTW89_UKRAINE][2] = 46, + [2][1][RTW89_CHILE][2] = 44, + [2][1][RTW89_QATAR][2] = 46, [2][1][RTW89_FCC][3] = 72, [2][1][RTW89_ETSI][3] = 46, [2][1][RTW89_MKK][3] = 46, [2][1][RTW89_IC][3] = 72, - [2][1][RTW89_KCC][3] = 52, + [2][1][RTW89_KCC][3] = 48, [2][1][RTW89_ACMA][3] = 46, [2][1][RTW89_CN][3] = 44, [2][1][RTW89_UK][3] = 46, + [2][1][RTW89_MEXICO][3] = 72, + [2][1][RTW89_UKRAINE][3] = 46, + [2][1][RTW89_CHILE][3] = 44, + [2][1][RTW89_QATAR][3] = 46, [2][1][RTW89_FCC][4] = 74, [2][1][RTW89_ETSI][4] = 46, [2][1][RTW89_MKK][4] = 46, [2][1][RTW89_IC][4] = 74, - [2][1][RTW89_KCC][4] = 50, + [2][1][RTW89_KCC][4] = 48, [2][1][RTW89_ACMA][4] = 46, [2][1][RTW89_CN][4] = 44, [2][1][RTW89_UK][4] = 46, + [2][1][RTW89_MEXICO][4] = 74, + [2][1][RTW89_UKRAINE][4] = 46, + [2][1][RTW89_CHILE][4] = 44, + [2][1][RTW89_QATAR][4] = 46, [2][1][RTW89_FCC][5] = 82, [2][1][RTW89_ETSI][5] = 46, [2][1][RTW89_MKK][5] = 46, [2][1][RTW89_IC][5] = 82, - [2][1][RTW89_KCC][5] = 50, + [2][1][RTW89_KCC][5] = 48, [2][1][RTW89_ACMA][5] = 46, [2][1][RTW89_CN][5] = 44, [2][1][RTW89_UK][5] = 46, + [2][1][RTW89_MEXICO][5] = 82, + [2][1][RTW89_UKRAINE][5] = 46, + [2][1][RTW89_CHILE][5] = 78, + [2][1][RTW89_QATAR][5] = 46, [2][1][RTW89_FCC][6] = 72, [2][1][RTW89_ETSI][6] = 44, [2][1][RTW89_MKK][6] = 46, [2][1][RTW89_IC][6] = 72, - [2][1][RTW89_KCC][6] = 50, + [2][1][RTW89_KCC][6] = 48, [2][1][RTW89_ACMA][6] = 44, [2][1][RTW89_CN][6] = 44, [2][1][RTW89_UK][6] = 44, + [2][1][RTW89_MEXICO][6] = 72, + [2][1][RTW89_UKRAINE][6] = 44, + [2][1][RTW89_CHILE][6] = 42, + [2][1][RTW89_QATAR][6] = 44, [2][1][RTW89_FCC][7] = 72, [2][1][RTW89_ETSI][7] = 46, [2][1][RTW89_MKK][7] = 46, [2][1][RTW89_IC][7] = 72, - [2][1][RTW89_KCC][7] = 50, + [2][1][RTW89_KCC][7] = 48, [2][1][RTW89_ACMA][7] = 46, [2][1][RTW89_CN][7] = 44, [2][1][RTW89_UK][7] = 46, + [2][1][RTW89_MEXICO][7] = 72, + [2][1][RTW89_UKRAINE][7] = 46, + [2][1][RTW89_CHILE][7] = 42, + [2][1][RTW89_QATAR][7] = 46, [2][1][RTW89_FCC][8] = 68, [2][1][RTW89_ETSI][8] = 46, [2][1][RTW89_MKK][8] = 46, [2][1][RTW89_IC][8] = 68, - [2][1][RTW89_KCC][8] = 50, + [2][1][RTW89_KCC][8] = 48, [2][1][RTW89_ACMA][8] = 46, [2][1][RTW89_CN][8] = 44, [2][1][RTW89_UK][8] = 46, + [2][1][RTW89_MEXICO][8] = 68, + [2][1][RTW89_UKRAINE][8] = 46, + [2][1][RTW89_CHILE][8] = 42, + [2][1][RTW89_QATAR][8] = 46, [2][1][RTW89_FCC][9] = 64, [2][1][RTW89_ETSI][9] = 46, [2][1][RTW89_MKK][9] = 46, [2][1][RTW89_IC][9] = 64, - [2][1][RTW89_KCC][9] = 52, + [2][1][RTW89_KCC][9] = 48, [2][1][RTW89_ACMA][9] = 46, [2][1][RTW89_CN][9] = 44, [2][1][RTW89_UK][9] = 46, + [2][1][RTW89_MEXICO][9] = 64, + [2][1][RTW89_UKRAINE][9] = 46, + [2][1][RTW89_CHILE][9] = 42, + [2][1][RTW89_QATAR][9] = 46, [2][1][RTW89_FCC][10] = 64, [2][1][RTW89_ETSI][10] = 46, [2][1][RTW89_MKK][10] = 46, [2][1][RTW89_IC][10] = 64, - [2][1][RTW89_KCC][10] = 52, + [2][1][RTW89_KCC][10] = 48, [2][1][RTW89_ACMA][10] = 46, [2][1][RTW89_CN][10] = 44, [2][1][RTW89_UK][10] = 46, + [2][1][RTW89_MEXICO][10] = 64, + [2][1][RTW89_UKRAINE][10] = 46, + [2][1][RTW89_CHILE][10] = 64, + [2][1][RTW89_QATAR][10] = 46, [2][1][RTW89_FCC][11] = 46, [2][1][RTW89_ETSI][11] = 46, [2][1][RTW89_MKK][11] = 46, [2][1][RTW89_IC][11] = 46, - [2][1][RTW89_KCC][11] = 52, + [2][1][RTW89_KCC][11] = 48, [2][1][RTW89_ACMA][11] = 46, [2][1][RTW89_CN][11] = 44, [2][1][RTW89_UK][11] = 46, + [2][1][RTW89_MEXICO][11] = 46, + [2][1][RTW89_UKRAINE][11] = 46, + [2][1][RTW89_CHILE][11] = 46, + [2][1][RTW89_QATAR][11] = 46, [2][1][RTW89_FCC][12] = 6, [2][1][RTW89_ETSI][12] = 44, [2][1][RTW89_MKK][12] = 46, [2][1][RTW89_IC][12] = 6, - [2][1][RTW89_KCC][12] = 52, + [2][1][RTW89_KCC][12] = 48, [2][1][RTW89_ACMA][12] = 44, [2][1][RTW89_CN][12] = 42, [2][1][RTW89_UK][12] = 44, + [2][1][RTW89_MEXICO][12] = 6, + [2][1][RTW89_UKRAINE][12] = 44, + [2][1][RTW89_CHILE][12] = 6, + [2][1][RTW89_QATAR][12] = 44, [2][1][RTW89_FCC][13] = 127, [2][1][RTW89_ETSI][13] = 127, [2][1][RTW89_MKK][13] = 127, @@ -34739,6 +46896,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM] [2][1][RTW89_ACMA][13] = 127, [2][1][RTW89_CN][13] = 127, [2][1][RTW89_UK][13] = 127, + [2][1][RTW89_MEXICO][13] = 127, + [2][1][RTW89_UKRAINE][13] = 127, + [2][1][RTW89_CHILE][13] = 127, + [2][1][RTW89_QATAR][13] = 127, }; static @@ -34747,168 +46908,168 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][0][RTW89_WW][0] = 16, [0][0][RTW89_WW][2] = 16, [0][0][RTW89_WW][4] = 16, - [0][0][RTW89_WW][6] = 10, + [0][0][RTW89_WW][6] = 16, [0][0][RTW89_WW][8] = 16, [0][0][RTW89_WW][10] = 16, [0][0][RTW89_WW][12] = 16, [0][0][RTW89_WW][14] = 16, - [0][0][RTW89_WW][15] = 30, - [0][0][RTW89_WW][17] = 30, - [0][0][RTW89_WW][19] = 30, - [0][0][RTW89_WW][21] = 30, - [0][0][RTW89_WW][23] = 30, - [0][0][RTW89_WW][25] = 30, - [0][0][RTW89_WW][27] = 30, - [0][0][RTW89_WW][29] = 30, - [0][0][RTW89_WW][31] = 30, - [0][0][RTW89_WW][33] = 30, - [0][0][RTW89_WW][35] = 30, + [0][0][RTW89_WW][15] = 22, + [0][0][RTW89_WW][17] = 22, + [0][0][RTW89_WW][19] = 22, + [0][0][RTW89_WW][21] = 22, + [0][0][RTW89_WW][23] = 22, + [0][0][RTW89_WW][25] = 22, + [0][0][RTW89_WW][27] = 22, + [0][0][RTW89_WW][29] = 22, + [0][0][RTW89_WW][31] = 22, + [0][0][RTW89_WW][33] = 22, + [0][0][RTW89_WW][35] = 22, [0][0][RTW89_WW][37] = 30, - [0][0][RTW89_WW][38] = 28, - [0][0][RTW89_WW][40] = 28, - [0][0][RTW89_WW][42] = 28, - [0][0][RTW89_WW][44] = 28, - [0][0][RTW89_WW][46] = 28, + [0][0][RTW89_WW][38] = 26, + [0][0][RTW89_WW][40] = 26, + [0][0][RTW89_WW][42] = 26, + [0][0][RTW89_WW][44] = 26, + [0][0][RTW89_WW][46] = 26, [0][0][RTW89_WW][48] = 46, [0][0][RTW89_WW][50] = 44, [0][0][RTW89_WW][52] = 34, [0][1][RTW89_WW][0] = 4, [0][1][RTW89_WW][2] = 4, [0][1][RTW89_WW][4] = 4, - [0][1][RTW89_WW][6] = 1, + [0][1][RTW89_WW][6] = 4, [0][1][RTW89_WW][8] = 4, [0][1][RTW89_WW][10] = 4, [0][1][RTW89_WW][12] = 4, [0][1][RTW89_WW][14] = 4, - [0][1][RTW89_WW][15] = 18, - [0][1][RTW89_WW][17] = 18, - [0][1][RTW89_WW][19] = 18, - [0][1][RTW89_WW][21] = 18, - [0][1][RTW89_WW][23] = 18, - [0][1][RTW89_WW][25] = 18, - [0][1][RTW89_WW][27] = 16, - [0][1][RTW89_WW][29] = 16, - [0][1][RTW89_WW][31] = 16, - [0][1][RTW89_WW][33] = 16, - [0][1][RTW89_WW][35] = 16, + [0][1][RTW89_WW][15] = 10, + [0][1][RTW89_WW][17] = 10, + [0][1][RTW89_WW][19] = 10, + [0][1][RTW89_WW][21] = 10, + [0][1][RTW89_WW][23] = 10, + [0][1][RTW89_WW][25] = 10, + [0][1][RTW89_WW][27] = 10, + [0][1][RTW89_WW][29] = 10, + [0][1][RTW89_WW][31] = 10, + [0][1][RTW89_WW][33] = 10, + [0][1][RTW89_WW][35] = 10, [0][1][RTW89_WW][37] = 18, - [0][1][RTW89_WW][38] = 16, - [0][1][RTW89_WW][40] = 16, - [0][1][RTW89_WW][42] = 16, - [0][1][RTW89_WW][44] = 16, - [0][1][RTW89_WW][46] = 16, + [0][1][RTW89_WW][38] = 14, + [0][1][RTW89_WW][40] = 14, + [0][1][RTW89_WW][42] = 14, + [0][1][RTW89_WW][44] = 14, + [0][1][RTW89_WW][46] = 14, [0][1][RTW89_WW][48] = 20, [0][1][RTW89_WW][50] = 20, [0][1][RTW89_WW][52] = 8, [1][0][RTW89_WW][0] = 26, [1][0][RTW89_WW][2] = 26, [1][0][RTW89_WW][4] = 26, - [1][0][RTW89_WW][6] = 24, + [1][0][RTW89_WW][6] = 26, [1][0][RTW89_WW][8] = 26, [1][0][RTW89_WW][10] = 26, [1][0][RTW89_WW][12] = 26, [1][0][RTW89_WW][14] = 26, - [1][0][RTW89_WW][15] = 40, - [1][0][RTW89_WW][17] = 40, - [1][0][RTW89_WW][19] = 40, - [1][0][RTW89_WW][21] = 40, - [1][0][RTW89_WW][23] = 40, - [1][0][RTW89_WW][25] = 40, - [1][0][RTW89_WW][27] = 42, - [1][0][RTW89_WW][29] = 42, - [1][0][RTW89_WW][31] = 42, - [1][0][RTW89_WW][33] = 42, - [1][0][RTW89_WW][35] = 42, + [1][0][RTW89_WW][15] = 32, + [1][0][RTW89_WW][17] = 32, + [1][0][RTW89_WW][19] = 32, + [1][0][RTW89_WW][21] = 32, + [1][0][RTW89_WW][23] = 32, + [1][0][RTW89_WW][25] = 32, + [1][0][RTW89_WW][27] = 32, + [1][0][RTW89_WW][29] = 32, + [1][0][RTW89_WW][31] = 32, + [1][0][RTW89_WW][33] = 32, + [1][0][RTW89_WW][35] = 32, [1][0][RTW89_WW][37] = 42, - [1][0][RTW89_WW][38] = 28, - [1][0][RTW89_WW][40] = 28, - [1][0][RTW89_WW][42] = 28, - [1][0][RTW89_WW][44] = 28, - [1][0][RTW89_WW][46] = 28, + [1][0][RTW89_WW][38] = 26, + [1][0][RTW89_WW][40] = 26, + [1][0][RTW89_WW][42] = 26, + [1][0][RTW89_WW][44] = 26, + [1][0][RTW89_WW][46] = 26, [1][0][RTW89_WW][48] = 56, [1][0][RTW89_WW][50] = 58, [1][0][RTW89_WW][52] = 56, [1][1][RTW89_WW][0] = 14, [1][1][RTW89_WW][2] = 14, [1][1][RTW89_WW][4] = 14, - [1][1][RTW89_WW][6] = 8, + [1][1][RTW89_WW][6] = 14, [1][1][RTW89_WW][8] = 14, [1][1][RTW89_WW][10] = 14, [1][1][RTW89_WW][12] = 14, [1][1][RTW89_WW][14] = 14, - [1][1][RTW89_WW][15] = 28, - [1][1][RTW89_WW][17] = 28, - [1][1][RTW89_WW][19] = 28, - [1][1][RTW89_WW][21] = 28, - [1][1][RTW89_WW][23] = 28, - [1][1][RTW89_WW][25] = 28, - [1][1][RTW89_WW][27] = 30, - [1][1][RTW89_WW][29] = 30, - [1][1][RTW89_WW][31] = 30, - [1][1][RTW89_WW][33] = 30, - [1][1][RTW89_WW][35] = 30, + [1][1][RTW89_WW][15] = 20, + [1][1][RTW89_WW][17] = 20, + [1][1][RTW89_WW][19] = 20, + [1][1][RTW89_WW][21] = 20, + [1][1][RTW89_WW][23] = 20, + [1][1][RTW89_WW][25] = 20, + [1][1][RTW89_WW][27] = 20, + [1][1][RTW89_WW][29] = 20, + [1][1][RTW89_WW][31] = 20, + [1][1][RTW89_WW][33] = 20, + [1][1][RTW89_WW][35] = 20, [1][1][RTW89_WW][37] = 32, - [1][1][RTW89_WW][38] = 16, - [1][1][RTW89_WW][40] = 16, - [1][1][RTW89_WW][42] = 16, - [1][1][RTW89_WW][44] = 16, - [1][1][RTW89_WW][46] = 16, + [1][1][RTW89_WW][38] = 14, + [1][1][RTW89_WW][40] = 14, + [1][1][RTW89_WW][42] = 14, + [1][1][RTW89_WW][44] = 14, + [1][1][RTW89_WW][46] = 14, [1][1][RTW89_WW][48] = 34, [1][1][RTW89_WW][50] = 34, [1][1][RTW89_WW][52] = 30, [2][0][RTW89_WW][0] = 40, [2][0][RTW89_WW][2] = 40, [2][0][RTW89_WW][4] = 40, - [2][0][RTW89_WW][6] = 36, + [2][0][RTW89_WW][6] = 38, [2][0][RTW89_WW][8] = 40, [2][0][RTW89_WW][10] = 40, [2][0][RTW89_WW][12] = 40, [2][0][RTW89_WW][14] = 40, - [2][0][RTW89_WW][15] = 52, - [2][0][RTW89_WW][17] = 52, - [2][0][RTW89_WW][19] = 52, - [2][0][RTW89_WW][21] = 52, - [2][0][RTW89_WW][23] = 52, - [2][0][RTW89_WW][25] = 52, - [2][0][RTW89_WW][27] = 52, - [2][0][RTW89_WW][29] = 52, - [2][0][RTW89_WW][31] = 52, - [2][0][RTW89_WW][33] = 52, - [2][0][RTW89_WW][35] = 52, + [2][0][RTW89_WW][15] = 46, + [2][0][RTW89_WW][17] = 46, + [2][0][RTW89_WW][19] = 46, + [2][0][RTW89_WW][21] = 46, + [2][0][RTW89_WW][23] = 46, + [2][0][RTW89_WW][25] = 46, + [2][0][RTW89_WW][27] = 46, + [2][0][RTW89_WW][29] = 46, + [2][0][RTW89_WW][31] = 46, + [2][0][RTW89_WW][33] = 46, + [2][0][RTW89_WW][35] = 46, [2][0][RTW89_WW][37] = 52, - [2][0][RTW89_WW][38] = 28, - [2][0][RTW89_WW][40] = 28, - [2][0][RTW89_WW][42] = 28, - [2][0][RTW89_WW][44] = 28, - [2][0][RTW89_WW][46] = 28, + [2][0][RTW89_WW][38] = 26, + [2][0][RTW89_WW][40] = 26, + [2][0][RTW89_WW][42] = 26, + [2][0][RTW89_WW][44] = 26, + [2][0][RTW89_WW][46] = 26, [2][0][RTW89_WW][48] = 64, [2][0][RTW89_WW][50] = 64, [2][0][RTW89_WW][52] = 64, [2][1][RTW89_WW][0] = 26, [2][1][RTW89_WW][2] = 26, [2][1][RTW89_WW][4] = 26, - [2][1][RTW89_WW][6] = 20, + [2][1][RTW89_WW][6] = 26, [2][1][RTW89_WW][8] = 28, [2][1][RTW89_WW][10] = 28, [2][1][RTW89_WW][12] = 28, [2][1][RTW89_WW][14] = 28, - [2][1][RTW89_WW][15] = 40, - [2][1][RTW89_WW][17] = 40, - [2][1][RTW89_WW][19] = 40, - [2][1][RTW89_WW][21] = 40, - [2][1][RTW89_WW][23] = 40, - [2][1][RTW89_WW][25] = 40, - [2][1][RTW89_WW][27] = 40, - [2][1][RTW89_WW][29] = 40, - [2][1][RTW89_WW][31] = 40, - [2][1][RTW89_WW][33] = 40, - [2][1][RTW89_WW][35] = 40, + [2][1][RTW89_WW][15] = 34, + [2][1][RTW89_WW][17] = 34, + [2][1][RTW89_WW][19] = 34, + [2][1][RTW89_WW][21] = 34, + [2][1][RTW89_WW][23] = 34, + [2][1][RTW89_WW][25] = 34, + [2][1][RTW89_WW][27] = 34, + [2][1][RTW89_WW][29] = 34, + [2][1][RTW89_WW][31] = 34, + [2][1][RTW89_WW][33] = 34, + [2][1][RTW89_WW][35] = 34, [2][1][RTW89_WW][37] = 42, - [2][1][RTW89_WW][38] = 16, - [2][1][RTW89_WW][40] = 16, - [2][1][RTW89_WW][42] = 16, - [2][1][RTW89_WW][44] = 16, - [2][1][RTW89_WW][46] = 16, + [2][1][RTW89_WW][38] = 14, + [2][1][RTW89_WW][40] = 14, + [2][1][RTW89_WW][42] = 14, + [2][1][RTW89_WW][44] = 14, + [2][1][RTW89_WW][46] = 14, [2][1][RTW89_WW][48] = 40, [2][1][RTW89_WW][50] = 40, [2][1][RTW89_WW][52] = 40, @@ -34920,6 +47081,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][0][RTW89_ACMA][0] = 30, [0][0][RTW89_CN][0] = 16, [0][0][RTW89_UK][0] = 30, + [0][0][RTW89_MEXICO][0] = 50, + [0][0][RTW89_UKRAINE][0] = 22, + [0][0][RTW89_CHILE][0] = 50, + [0][0][RTW89_QATAR][0] = 30, [0][0][RTW89_FCC][2] = 50, [0][0][RTW89_ETSI][2] = 30, [0][0][RTW89_MKK][2] = 36, @@ -34928,6 +47093,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][0][RTW89_ACMA][2] = 30, [0][0][RTW89_CN][2] = 16, [0][0][RTW89_UK][2] = 30, + [0][0][RTW89_MEXICO][2] = 50, + [0][0][RTW89_UKRAINE][2] = 22, + [0][0][RTW89_CHILE][2] = 50, + [0][0][RTW89_QATAR][2] = 30, [0][0][RTW89_FCC][4] = 50, [0][0][RTW89_ETSI][4] = 30, [0][0][RTW89_MKK][4] = 22, @@ -34936,30 +47105,46 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][0][RTW89_ACMA][4] = 30, [0][0][RTW89_CN][4] = 16, [0][0][RTW89_UK][4] = 30, + [0][0][RTW89_MEXICO][4] = 50, + [0][0][RTW89_UKRAINE][4] = 22, + [0][0][RTW89_CHILE][4] = 50, + [0][0][RTW89_QATAR][4] = 30, [0][0][RTW89_FCC][6] = 50, [0][0][RTW89_ETSI][6] = 30, [0][0][RTW89_MKK][6] = 22, [0][0][RTW89_IC][6] = 32, - [0][0][RTW89_KCC][6] = 10, + [0][0][RTW89_KCC][6] = 18, [0][0][RTW89_ACMA][6] = 30, [0][0][RTW89_CN][6] = 16, [0][0][RTW89_UK][6] = 30, + [0][0][RTW89_MEXICO][6] = 50, + [0][0][RTW89_UKRAINE][6] = 22, + [0][0][RTW89_CHILE][6] = 50, + [0][0][RTW89_QATAR][6] = 30, [0][0][RTW89_FCC][8] = 52, [0][0][RTW89_ETSI][8] = 28, [0][0][RTW89_MKK][8] = 18, [0][0][RTW89_IC][8] = 52, - [0][0][RTW89_KCC][8] = 44, + [0][0][RTW89_KCC][8] = 40, [0][0][RTW89_ACMA][8] = 28, [0][0][RTW89_CN][8] = 16, [0][0][RTW89_UK][8] = 28, + [0][0][RTW89_MEXICO][8] = 52, + [0][0][RTW89_UKRAINE][8] = 22, + [0][0][RTW89_CHILE][8] = 52, + [0][0][RTW89_QATAR][8] = 28, [0][0][RTW89_FCC][10] = 52, [0][0][RTW89_ETSI][10] = 28, [0][0][RTW89_MKK][10] = 18, [0][0][RTW89_IC][10] = 52, - [0][0][RTW89_KCC][10] = 44, + [0][0][RTW89_KCC][10] = 40, [0][0][RTW89_ACMA][10] = 28, [0][0][RTW89_CN][10] = 16, [0][0][RTW89_UK][10] = 28, + [0][0][RTW89_MEXICO][10] = 52, + [0][0][RTW89_UKRAINE][10] = 22, + [0][0][RTW89_CHILE][10] = 52, + [0][0][RTW89_QATAR][10] = 28, [0][0][RTW89_FCC][12] = 52, [0][0][RTW89_ETSI][12] = 28, [0][0][RTW89_MKK][12] = 34, @@ -34968,6 +47153,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][0][RTW89_ACMA][12] = 28, [0][0][RTW89_CN][12] = 16, [0][0][RTW89_UK][12] = 28, + [0][0][RTW89_MEXICO][12] = 52, + [0][0][RTW89_UKRAINE][12] = 22, + [0][0][RTW89_CHILE][12] = 52, + [0][0][RTW89_QATAR][12] = 28, [0][0][RTW89_FCC][14] = 52, [0][0][RTW89_ETSI][14] = 28, [0][0][RTW89_MKK][14] = 34, @@ -34976,70 +47165,106 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][0][RTW89_ACMA][14] = 28, [0][0][RTW89_CN][14] = 16, [0][0][RTW89_UK][14] = 28, + [0][0][RTW89_MEXICO][14] = 52, + [0][0][RTW89_UKRAINE][14] = 22, + [0][0][RTW89_CHILE][14] = 52, + [0][0][RTW89_QATAR][14] = 28, [0][0][RTW89_FCC][15] = 52, [0][0][RTW89_ETSI][15] = 30, [0][0][RTW89_MKK][15] = 56, [0][0][RTW89_IC][15] = 52, - [0][0][RTW89_KCC][15] = 42, + [0][0][RTW89_KCC][15] = 40, [0][0][RTW89_ACMA][15] = 30, [0][0][RTW89_CN][15] = 127, [0][0][RTW89_UK][15] = 30, + [0][0][RTW89_MEXICO][15] = 52, + [0][0][RTW89_UKRAINE][15] = 22, + [0][0][RTW89_CHILE][15] = 52, + [0][0][RTW89_QATAR][15] = 30, [0][0][RTW89_FCC][17] = 52, [0][0][RTW89_ETSI][17] = 30, [0][0][RTW89_MKK][17] = 58, [0][0][RTW89_IC][17] = 52, - [0][0][RTW89_KCC][17] = 42, + [0][0][RTW89_KCC][17] = 40, [0][0][RTW89_ACMA][17] = 30, [0][0][RTW89_CN][17] = 127, [0][0][RTW89_UK][17] = 30, + [0][0][RTW89_MEXICO][17] = 52, + [0][0][RTW89_UKRAINE][17] = 22, + [0][0][RTW89_CHILE][17] = 52, + [0][0][RTW89_QATAR][17] = 30, [0][0][RTW89_FCC][19] = 52, [0][0][RTW89_ETSI][19] = 30, [0][0][RTW89_MKK][19] = 58, [0][0][RTW89_IC][19] = 52, - [0][0][RTW89_KCC][19] = 42, + [0][0][RTW89_KCC][19] = 40, [0][0][RTW89_ACMA][19] = 30, [0][0][RTW89_CN][19] = 127, [0][0][RTW89_UK][19] = 30, + [0][0][RTW89_MEXICO][19] = 52, + [0][0][RTW89_UKRAINE][19] = 22, + [0][0][RTW89_CHILE][19] = 52, + [0][0][RTW89_QATAR][19] = 30, [0][0][RTW89_FCC][21] = 52, [0][0][RTW89_ETSI][21] = 30, [0][0][RTW89_MKK][21] = 58, [0][0][RTW89_IC][21] = 52, - [0][0][RTW89_KCC][21] = 42, + [0][0][RTW89_KCC][21] = 40, [0][0][RTW89_ACMA][21] = 30, [0][0][RTW89_CN][21] = 127, [0][0][RTW89_UK][21] = 30, + [0][0][RTW89_MEXICO][21] = 52, + [0][0][RTW89_UKRAINE][21] = 22, + [0][0][RTW89_CHILE][21] = 52, + [0][0][RTW89_QATAR][21] = 30, [0][0][RTW89_FCC][23] = 52, [0][0][RTW89_ETSI][23] = 30, [0][0][RTW89_MKK][23] = 58, [0][0][RTW89_IC][23] = 52, - [0][0][RTW89_KCC][23] = 42, + [0][0][RTW89_KCC][23] = 40, [0][0][RTW89_ACMA][23] = 30, [0][0][RTW89_CN][23] = 127, [0][0][RTW89_UK][23] = 30, + [0][0][RTW89_MEXICO][23] = 52, + [0][0][RTW89_UKRAINE][23] = 22, + [0][0][RTW89_CHILE][23] = 52, + [0][0][RTW89_QATAR][23] = 30, [0][0][RTW89_FCC][25] = 52, [0][0][RTW89_ETSI][25] = 30, [0][0][RTW89_MKK][25] = 58, [0][0][RTW89_IC][25] = 127, - [0][0][RTW89_KCC][25] = 42, + [0][0][RTW89_KCC][25] = 40, [0][0][RTW89_ACMA][25] = 127, [0][0][RTW89_CN][25] = 127, [0][0][RTW89_UK][25] = 30, + [0][0][RTW89_MEXICO][25] = 52, + [0][0][RTW89_UKRAINE][25] = 22, + [0][0][RTW89_CHILE][25] = 52, + [0][0][RTW89_QATAR][25] = 30, [0][0][RTW89_FCC][27] = 52, [0][0][RTW89_ETSI][27] = 30, [0][0][RTW89_MKK][27] = 58, [0][0][RTW89_IC][27] = 127, - [0][0][RTW89_KCC][27] = 42, + [0][0][RTW89_KCC][27] = 40, [0][0][RTW89_ACMA][27] = 127, [0][0][RTW89_CN][27] = 127, [0][0][RTW89_UK][27] = 30, + [0][0][RTW89_MEXICO][27] = 52, + [0][0][RTW89_UKRAINE][27] = 22, + [0][0][RTW89_CHILE][27] = 52, + [0][0][RTW89_QATAR][27] = 30, [0][0][RTW89_FCC][29] = 52, [0][0][RTW89_ETSI][29] = 30, [0][0][RTW89_MKK][29] = 58, [0][0][RTW89_IC][29] = 127, - [0][0][RTW89_KCC][29] = 42, + [0][0][RTW89_KCC][29] = 40, [0][0][RTW89_ACMA][29] = 127, [0][0][RTW89_CN][29] = 127, [0][0][RTW89_UK][29] = 30, + [0][0][RTW89_MEXICO][29] = 52, + [0][0][RTW89_UKRAINE][29] = 22, + [0][0][RTW89_CHILE][29] = 52, + [0][0][RTW89_QATAR][29] = 30, [0][0][RTW89_FCC][31] = 52, [0][0][RTW89_ETSI][31] = 30, [0][0][RTW89_MKK][31] = 58, @@ -35048,6 +47273,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][0][RTW89_ACMA][31] = 30, [0][0][RTW89_CN][31] = 127, [0][0][RTW89_UK][31] = 30, + [0][0][RTW89_MEXICO][31] = 52, + [0][0][RTW89_UKRAINE][31] = 22, + [0][0][RTW89_CHILE][31] = 52, + [0][0][RTW89_QATAR][31] = 30, [0][0][RTW89_FCC][33] = 44, [0][0][RTW89_ETSI][33] = 30, [0][0][RTW89_MKK][33] = 58, @@ -35056,6 +47285,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][0][RTW89_ACMA][33] = 30, [0][0][RTW89_CN][33] = 127, [0][0][RTW89_UK][33] = 30, + [0][0][RTW89_MEXICO][33] = 44, + [0][0][RTW89_UKRAINE][33] = 22, + [0][0][RTW89_CHILE][33] = 44, + [0][0][RTW89_QATAR][33] = 30, [0][0][RTW89_FCC][35] = 44, [0][0][RTW89_ETSI][35] = 30, [0][0][RTW89_MKK][35] = 58, @@ -35064,6 +47297,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][0][RTW89_ACMA][35] = 30, [0][0][RTW89_CN][35] = 127, [0][0][RTW89_UK][35] = 30, + [0][0][RTW89_MEXICO][35] = 44, + [0][0][RTW89_UKRAINE][35] = 22, + [0][0][RTW89_CHILE][35] = 44, + [0][0][RTW89_QATAR][35] = 30, [0][0][RTW89_FCC][37] = 52, [0][0][RTW89_ETSI][37] = 127, [0][0][RTW89_MKK][37] = 58, @@ -35072,6 +47309,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][0][RTW89_ACMA][37] = 52, [0][0][RTW89_CN][37] = 127, [0][0][RTW89_UK][37] = 30, + [0][0][RTW89_MEXICO][37] = 52, + [0][0][RTW89_UKRAINE][37] = 127, + [0][0][RTW89_CHILE][37] = 52, + [0][0][RTW89_QATAR][37] = 127, [0][0][RTW89_FCC][38] = 64, [0][0][RTW89_ETSI][38] = 28, [0][0][RTW89_MKK][38] = 127, @@ -35080,6 +47321,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][0][RTW89_ACMA][38] = 64, [0][0][RTW89_CN][38] = 54, [0][0][RTW89_UK][38] = 30, + [0][0][RTW89_MEXICO][38] = 64, + [0][0][RTW89_UKRAINE][38] = 26, + [0][0][RTW89_CHILE][38] = 64, + [0][0][RTW89_QATAR][38] = 26, [0][0][RTW89_FCC][40] = 64, [0][0][RTW89_ETSI][40] = 28, [0][0][RTW89_MKK][40] = 127, @@ -35088,6 +47333,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][0][RTW89_ACMA][40] = 64, [0][0][RTW89_CN][40] = 54, [0][0][RTW89_UK][40] = 30, + [0][0][RTW89_MEXICO][40] = 64, + [0][0][RTW89_UKRAINE][40] = 26, + [0][0][RTW89_CHILE][40] = 64, + [0][0][RTW89_QATAR][40] = 26, [0][0][RTW89_FCC][42] = 60, [0][0][RTW89_ETSI][42] = 28, [0][0][RTW89_MKK][42] = 127, @@ -35096,6 +47345,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][0][RTW89_ACMA][42] = 60, [0][0][RTW89_CN][42] = 54, [0][0][RTW89_UK][42] = 30, + [0][0][RTW89_MEXICO][42] = 60, + [0][0][RTW89_UKRAINE][42] = 26, + [0][0][RTW89_CHILE][42] = 60, + [0][0][RTW89_QATAR][42] = 26, [0][0][RTW89_FCC][44] = 60, [0][0][RTW89_ETSI][44] = 28, [0][0][RTW89_MKK][44] = 127, @@ -35104,6 +47357,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][0][RTW89_ACMA][44] = 60, [0][0][RTW89_CN][44] = 54, [0][0][RTW89_UK][44] = 30, + [0][0][RTW89_MEXICO][44] = 60, + [0][0][RTW89_UKRAINE][44] = 26, + [0][0][RTW89_CHILE][44] = 60, + [0][0][RTW89_QATAR][44] = 26, [0][0][RTW89_FCC][46] = 60, [0][0][RTW89_ETSI][46] = 28, [0][0][RTW89_MKK][46] = 127, @@ -35112,6 +47369,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][0][RTW89_ACMA][46] = 60, [0][0][RTW89_CN][46] = 54, [0][0][RTW89_UK][46] = 30, + [0][0][RTW89_MEXICO][46] = 60, + [0][0][RTW89_UKRAINE][46] = 26, + [0][0][RTW89_CHILE][46] = 60, + [0][0][RTW89_QATAR][46] = 26, [0][0][RTW89_FCC][48] = 46, [0][0][RTW89_ETSI][48] = 127, [0][0][RTW89_MKK][48] = 127, @@ -35120,6 +47381,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][0][RTW89_ACMA][48] = 127, [0][0][RTW89_CN][48] = 127, [0][0][RTW89_UK][48] = 127, + [0][0][RTW89_MEXICO][48] = 127, + [0][0][RTW89_UKRAINE][48] = 127, + [0][0][RTW89_CHILE][48] = 127, + [0][0][RTW89_QATAR][48] = 127, [0][0][RTW89_FCC][50] = 44, [0][0][RTW89_ETSI][50] = 127, [0][0][RTW89_MKK][50] = 127, @@ -35128,6 +47393,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][0][RTW89_ACMA][50] = 127, [0][0][RTW89_CN][50] = 127, [0][0][RTW89_UK][50] = 127, + [0][0][RTW89_MEXICO][50] = 127, + [0][0][RTW89_UKRAINE][50] = 127, + [0][0][RTW89_CHILE][50] = 127, + [0][0][RTW89_QATAR][50] = 127, [0][0][RTW89_FCC][52] = 34, [0][0][RTW89_ETSI][52] = 127, [0][0][RTW89_MKK][52] = 127, @@ -35136,38 +47405,58 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][0][RTW89_ACMA][52] = 127, [0][0][RTW89_CN][52] = 127, [0][0][RTW89_UK][52] = 127, + [0][0][RTW89_MEXICO][52] = 127, + [0][0][RTW89_UKRAINE][52] = 127, + [0][0][RTW89_CHILE][52] = 127, + [0][0][RTW89_QATAR][52] = 127, [0][1][RTW89_FCC][0] = 30, [0][1][RTW89_ETSI][0] = 18, [0][1][RTW89_MKK][0] = 20, [0][1][RTW89_IC][0] = 8, - [0][1][RTW89_KCC][0] = 26, + [0][1][RTW89_KCC][0] = 32, [0][1][RTW89_ACMA][0] = 18, [0][1][RTW89_CN][0] = 4, [0][1][RTW89_UK][0] = 18, + [0][1][RTW89_MEXICO][0] = 30, + [0][1][RTW89_UKRAINE][0] = 10, + [0][1][RTW89_CHILE][0] = 30, + [0][1][RTW89_QATAR][0] = 18, [0][1][RTW89_FCC][2] = 32, [0][1][RTW89_ETSI][2] = 18, [0][1][RTW89_MKK][2] = 20, [0][1][RTW89_IC][2] = 8, - [0][1][RTW89_KCC][2] = 26, + [0][1][RTW89_KCC][2] = 32, [0][1][RTW89_ACMA][2] = 18, [0][1][RTW89_CN][2] = 4, [0][1][RTW89_UK][2] = 18, + [0][1][RTW89_MEXICO][2] = 32, + [0][1][RTW89_UKRAINE][2] = 10, + [0][1][RTW89_CHILE][2] = 32, + [0][1][RTW89_QATAR][2] = 18, [0][1][RTW89_FCC][4] = 30, [0][1][RTW89_ETSI][4] = 18, [0][1][RTW89_MKK][4] = 8, [0][1][RTW89_IC][4] = 8, - [0][1][RTW89_KCC][4] = 26, + [0][1][RTW89_KCC][4] = 32, [0][1][RTW89_ACMA][4] = 18, [0][1][RTW89_CN][4] = 4, [0][1][RTW89_UK][4] = 18, + [0][1][RTW89_MEXICO][4] = 30, + [0][1][RTW89_UKRAINE][4] = 10, + [0][1][RTW89_CHILE][4] = 30, + [0][1][RTW89_QATAR][4] = 18, [0][1][RTW89_FCC][6] = 30, [0][1][RTW89_ETSI][6] = 18, [0][1][RTW89_MKK][6] = 8, [0][1][RTW89_IC][6] = 8, - [0][1][RTW89_KCC][6] = 0, + [0][1][RTW89_KCC][6] = 6, [0][1][RTW89_ACMA][6] = 18, [0][1][RTW89_CN][6] = 4, [0][1][RTW89_UK][6] = 18, + [0][1][RTW89_MEXICO][6] = 30, + [0][1][RTW89_UKRAINE][6] = 10, + [0][1][RTW89_CHILE][6] = 30, + [0][1][RTW89_QATAR][6] = 18, [0][1][RTW89_FCC][8] = 30, [0][1][RTW89_ETSI][8] = 16, [0][1][RTW89_MKK][8] = 20, @@ -35176,6 +47465,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][1][RTW89_ACMA][8] = 16, [0][1][RTW89_CN][8] = 4, [0][1][RTW89_UK][8] = 16, + [0][1][RTW89_MEXICO][8] = 30, + [0][1][RTW89_UKRAINE][8] = 10, + [0][1][RTW89_CHILE][8] = 30, + [0][1][RTW89_QATAR][8] = 16, [0][1][RTW89_FCC][10] = 30, [0][1][RTW89_ETSI][10] = 16, [0][1][RTW89_MKK][10] = 20, @@ -35184,22 +47477,34 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][1][RTW89_ACMA][10] = 16, [0][1][RTW89_CN][10] = 4, [0][1][RTW89_UK][10] = 16, + [0][1][RTW89_MEXICO][10] = 30, + [0][1][RTW89_UKRAINE][10] = 10, + [0][1][RTW89_CHILE][10] = 30, + [0][1][RTW89_QATAR][10] = 16, [0][1][RTW89_FCC][12] = 30, [0][1][RTW89_ETSI][12] = 16, [0][1][RTW89_MKK][12] = 34, [0][1][RTW89_IC][12] = 30, - [0][1][RTW89_KCC][12] = 28, + [0][1][RTW89_KCC][12] = 26, [0][1][RTW89_ACMA][12] = 16, [0][1][RTW89_CN][12] = 4, [0][1][RTW89_UK][12] = 16, + [0][1][RTW89_MEXICO][12] = 30, + [0][1][RTW89_UKRAINE][12] = 10, + [0][1][RTW89_CHILE][12] = 30, + [0][1][RTW89_QATAR][12] = 16, [0][1][RTW89_FCC][14] = 30, [0][1][RTW89_ETSI][14] = 16, [0][1][RTW89_MKK][14] = 34, [0][1][RTW89_IC][14] = 30, - [0][1][RTW89_KCC][14] = 28, + [0][1][RTW89_KCC][14] = 26, [0][1][RTW89_ACMA][14] = 16, [0][1][RTW89_CN][14] = 4, [0][1][RTW89_UK][14] = 16, + [0][1][RTW89_MEXICO][14] = 30, + [0][1][RTW89_UKRAINE][14] = 10, + [0][1][RTW89_CHILE][14] = 30, + [0][1][RTW89_QATAR][14] = 16, [0][1][RTW89_FCC][15] = 32, [0][1][RTW89_ETSI][15] = 18, [0][1][RTW89_MKK][15] = 44, @@ -35208,6 +47513,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][1][RTW89_ACMA][15] = 18, [0][1][RTW89_CN][15] = 127, [0][1][RTW89_UK][15] = 18, + [0][1][RTW89_MEXICO][15] = 32, + [0][1][RTW89_UKRAINE][15] = 10, + [0][1][RTW89_CHILE][15] = 32, + [0][1][RTW89_QATAR][15] = 18, [0][1][RTW89_FCC][17] = 32, [0][1][RTW89_ETSI][17] = 18, [0][1][RTW89_MKK][17] = 44, @@ -35216,6 +47525,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][1][RTW89_ACMA][17] = 18, [0][1][RTW89_CN][17] = 127, [0][1][RTW89_UK][17] = 18, + [0][1][RTW89_MEXICO][17] = 32, + [0][1][RTW89_UKRAINE][17] = 10, + [0][1][RTW89_CHILE][17] = 32, + [0][1][RTW89_QATAR][17] = 18, [0][1][RTW89_FCC][19] = 32, [0][1][RTW89_ETSI][19] = 18, [0][1][RTW89_MKK][19] = 44, @@ -35224,6 +47537,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][1][RTW89_ACMA][19] = 18, [0][1][RTW89_CN][19] = 127, [0][1][RTW89_UK][19] = 18, + [0][1][RTW89_MEXICO][19] = 32, + [0][1][RTW89_UKRAINE][19] = 10, + [0][1][RTW89_CHILE][19] = 32, + [0][1][RTW89_QATAR][19] = 18, [0][1][RTW89_FCC][21] = 32, [0][1][RTW89_ETSI][21] = 18, [0][1][RTW89_MKK][21] = 44, @@ -35232,6 +47549,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][1][RTW89_ACMA][21] = 18, [0][1][RTW89_CN][21] = 127, [0][1][RTW89_UK][21] = 18, + [0][1][RTW89_MEXICO][21] = 32, + [0][1][RTW89_UKRAINE][21] = 10, + [0][1][RTW89_CHILE][21] = 32, + [0][1][RTW89_QATAR][21] = 18, [0][1][RTW89_FCC][23] = 32, [0][1][RTW89_ETSI][23] = 18, [0][1][RTW89_MKK][23] = 44, @@ -35240,6 +47561,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][1][RTW89_ACMA][23] = 18, [0][1][RTW89_CN][23] = 127, [0][1][RTW89_UK][23] = 18, + [0][1][RTW89_MEXICO][23] = 32, + [0][1][RTW89_UKRAINE][23] = 10, + [0][1][RTW89_CHILE][23] = 32, + [0][1][RTW89_QATAR][23] = 18, [0][1][RTW89_FCC][25] = 32, [0][1][RTW89_ETSI][25] = 18, [0][1][RTW89_MKK][25] = 44, @@ -35248,6 +47573,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][1][RTW89_ACMA][25] = 127, [0][1][RTW89_CN][25] = 127, [0][1][RTW89_UK][25] = 18, + [0][1][RTW89_MEXICO][25] = 32, + [0][1][RTW89_UKRAINE][25] = 10, + [0][1][RTW89_CHILE][25] = 32, + [0][1][RTW89_QATAR][25] = 18, [0][1][RTW89_FCC][27] = 32, [0][1][RTW89_ETSI][27] = 16, [0][1][RTW89_MKK][27] = 44, @@ -35256,6 +47585,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][1][RTW89_ACMA][27] = 127, [0][1][RTW89_CN][27] = 127, [0][1][RTW89_UK][27] = 16, + [0][1][RTW89_MEXICO][27] = 32, + [0][1][RTW89_UKRAINE][27] = 10, + [0][1][RTW89_CHILE][27] = 32, + [0][1][RTW89_QATAR][27] = 16, [0][1][RTW89_FCC][29] = 32, [0][1][RTW89_ETSI][29] = 16, [0][1][RTW89_MKK][29] = 44, @@ -35264,6 +47597,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][1][RTW89_ACMA][29] = 127, [0][1][RTW89_CN][29] = 127, [0][1][RTW89_UK][29] = 16, + [0][1][RTW89_MEXICO][29] = 32, + [0][1][RTW89_UKRAINE][29] = 10, + [0][1][RTW89_CHILE][29] = 32, + [0][1][RTW89_QATAR][29] = 16, [0][1][RTW89_FCC][31] = 32, [0][1][RTW89_ETSI][31] = 16, [0][1][RTW89_MKK][31] = 44, @@ -35272,6 +47609,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][1][RTW89_ACMA][31] = 16, [0][1][RTW89_CN][31] = 127, [0][1][RTW89_UK][31] = 16, + [0][1][RTW89_MEXICO][31] = 32, + [0][1][RTW89_UKRAINE][31] = 10, + [0][1][RTW89_CHILE][31] = 32, + [0][1][RTW89_QATAR][31] = 16, [0][1][RTW89_FCC][33] = 30, [0][1][RTW89_ETSI][33] = 16, [0][1][RTW89_MKK][33] = 44, @@ -35280,6 +47621,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][1][RTW89_ACMA][33] = 16, [0][1][RTW89_CN][33] = 127, [0][1][RTW89_UK][33] = 16, + [0][1][RTW89_MEXICO][33] = 30, + [0][1][RTW89_UKRAINE][33] = 10, + [0][1][RTW89_CHILE][33] = 30, + [0][1][RTW89_QATAR][33] = 16, [0][1][RTW89_FCC][35] = 30, [0][1][RTW89_ETSI][35] = 16, [0][1][RTW89_MKK][35] = 44, @@ -35288,6 +47633,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][1][RTW89_ACMA][35] = 16, [0][1][RTW89_CN][35] = 127, [0][1][RTW89_UK][35] = 16, + [0][1][RTW89_MEXICO][35] = 30, + [0][1][RTW89_UKRAINE][35] = 10, + [0][1][RTW89_CHILE][35] = 30, + [0][1][RTW89_QATAR][35] = 16, [0][1][RTW89_FCC][37] = 34, [0][1][RTW89_ETSI][37] = 127, [0][1][RTW89_MKK][37] = 44, @@ -35296,46 +47645,70 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][1][RTW89_ACMA][37] = 34, [0][1][RTW89_CN][37] = 127, [0][1][RTW89_UK][37] = 18, + [0][1][RTW89_MEXICO][37] = 34, + [0][1][RTW89_UKRAINE][37] = 127, + [0][1][RTW89_CHILE][37] = 34, + [0][1][RTW89_QATAR][37] = 127, [0][1][RTW89_FCC][38] = 62, [0][1][RTW89_ETSI][38] = 16, [0][1][RTW89_MKK][38] = 127, [0][1][RTW89_IC][38] = 62, - [0][1][RTW89_KCC][38] = 28, + [0][1][RTW89_KCC][38] = 30, [0][1][RTW89_ACMA][38] = 62, [0][1][RTW89_CN][38] = 42, [0][1][RTW89_UK][38] = 18, + [0][1][RTW89_MEXICO][38] = 62, + [0][1][RTW89_UKRAINE][38] = 14, + [0][1][RTW89_CHILE][38] = 62, + [0][1][RTW89_QATAR][38] = 14, [0][1][RTW89_FCC][40] = 62, [0][1][RTW89_ETSI][40] = 16, [0][1][RTW89_MKK][40] = 127, [0][1][RTW89_IC][40] = 62, - [0][1][RTW89_KCC][40] = 28, + [0][1][RTW89_KCC][40] = 30, [0][1][RTW89_ACMA][40] = 62, [0][1][RTW89_CN][40] = 42, [0][1][RTW89_UK][40] = 18, + [0][1][RTW89_MEXICO][40] = 62, + [0][1][RTW89_UKRAINE][40] = 14, + [0][1][RTW89_CHILE][40] = 62, + [0][1][RTW89_QATAR][40] = 14, [0][1][RTW89_FCC][42] = 58, [0][1][RTW89_ETSI][42] = 16, [0][1][RTW89_MKK][42] = 127, [0][1][RTW89_IC][42] = 58, - [0][1][RTW89_KCC][42] = 28, + [0][1][RTW89_KCC][42] = 30, [0][1][RTW89_ACMA][42] = 58, [0][1][RTW89_CN][42] = 42, [0][1][RTW89_UK][42] = 18, + [0][1][RTW89_MEXICO][42] = 58, + [0][1][RTW89_UKRAINE][42] = 14, + [0][1][RTW89_CHILE][42] = 58, + [0][1][RTW89_QATAR][42] = 14, [0][1][RTW89_FCC][44] = 56, [0][1][RTW89_ETSI][44] = 16, [0][1][RTW89_MKK][44] = 127, [0][1][RTW89_IC][44] = 56, - [0][1][RTW89_KCC][44] = 28, + [0][1][RTW89_KCC][44] = 30, [0][1][RTW89_ACMA][44] = 56, [0][1][RTW89_CN][44] = 42, [0][1][RTW89_UK][44] = 18, + [0][1][RTW89_MEXICO][44] = 56, + [0][1][RTW89_UKRAINE][44] = 14, + [0][1][RTW89_CHILE][44] = 56, + [0][1][RTW89_QATAR][44] = 14, [0][1][RTW89_FCC][46] = 56, [0][1][RTW89_ETSI][46] = 16, [0][1][RTW89_MKK][46] = 127, [0][1][RTW89_IC][46] = 56, - [0][1][RTW89_KCC][46] = 28, + [0][1][RTW89_KCC][46] = 30, [0][1][RTW89_ACMA][46] = 56, [0][1][RTW89_CN][46] = 42, [0][1][RTW89_UK][46] = 18, + [0][1][RTW89_MEXICO][46] = 56, + [0][1][RTW89_UKRAINE][46] = 14, + [0][1][RTW89_CHILE][46] = 56, + [0][1][RTW89_QATAR][46] = 14, [0][1][RTW89_FCC][48] = 20, [0][1][RTW89_ETSI][48] = 127, [0][1][RTW89_MKK][48] = 127, @@ -35344,6 +47717,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][1][RTW89_ACMA][48] = 127, [0][1][RTW89_CN][48] = 127, [0][1][RTW89_UK][48] = 127, + [0][1][RTW89_MEXICO][48] = 127, + [0][1][RTW89_UKRAINE][48] = 127, + [0][1][RTW89_CHILE][48] = 127, + [0][1][RTW89_QATAR][48] = 127, [0][1][RTW89_FCC][50] = 20, [0][1][RTW89_ETSI][50] = 127, [0][1][RTW89_MKK][50] = 127, @@ -35352,6 +47729,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][1][RTW89_ACMA][50] = 127, [0][1][RTW89_CN][50] = 127, [0][1][RTW89_UK][50] = 127, + [0][1][RTW89_MEXICO][50] = 127, + [0][1][RTW89_UKRAINE][50] = 127, + [0][1][RTW89_CHILE][50] = 127, + [0][1][RTW89_QATAR][50] = 127, [0][1][RTW89_FCC][52] = 8, [0][1][RTW89_ETSI][52] = 127, [0][1][RTW89_MKK][52] = 127, @@ -35360,70 +47741,106 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][1][RTW89_ACMA][52] = 127, [0][1][RTW89_CN][52] = 127, [0][1][RTW89_UK][52] = 127, + [0][1][RTW89_MEXICO][52] = 127, + [0][1][RTW89_UKRAINE][52] = 127, + [0][1][RTW89_CHILE][52] = 127, + [0][1][RTW89_QATAR][52] = 127, [1][0][RTW89_FCC][0] = 62, [1][0][RTW89_ETSI][0] = 40, [1][0][RTW89_MKK][0] = 48, [1][0][RTW89_IC][0] = 42, - [1][0][RTW89_KCC][0] = 50, + [1][0][RTW89_KCC][0] = 54, [1][0][RTW89_ACMA][0] = 40, [1][0][RTW89_CN][0] = 26, [1][0][RTW89_UK][0] = 40, + [1][0][RTW89_MEXICO][0] = 62, + [1][0][RTW89_UKRAINE][0] = 32, + [1][0][RTW89_CHILE][0] = 62, + [1][0][RTW89_QATAR][0] = 40, [1][0][RTW89_FCC][2] = 62, [1][0][RTW89_ETSI][2] = 40, [1][0][RTW89_MKK][2] = 48, [1][0][RTW89_IC][2] = 42, - [1][0][RTW89_KCC][2] = 50, + [1][0][RTW89_KCC][2] = 54, [1][0][RTW89_ACMA][2] = 40, [1][0][RTW89_CN][2] = 26, [1][0][RTW89_UK][2] = 40, + [1][0][RTW89_MEXICO][2] = 62, + [1][0][RTW89_UKRAINE][2] = 32, + [1][0][RTW89_CHILE][2] = 62, + [1][0][RTW89_QATAR][2] = 40, [1][0][RTW89_FCC][4] = 64, [1][0][RTW89_ETSI][4] = 40, [1][0][RTW89_MKK][4] = 40, [1][0][RTW89_IC][4] = 42, - [1][0][RTW89_KCC][4] = 50, + [1][0][RTW89_KCC][4] = 54, [1][0][RTW89_ACMA][4] = 40, [1][0][RTW89_CN][4] = 26, [1][0][RTW89_UK][4] = 40, + [1][0][RTW89_MEXICO][4] = 64, + [1][0][RTW89_UKRAINE][4] = 32, + [1][0][RTW89_CHILE][4] = 64, + [1][0][RTW89_QATAR][4] = 40, [1][0][RTW89_FCC][6] = 64, [1][0][RTW89_ETSI][6] = 40, [1][0][RTW89_MKK][6] = 40, [1][0][RTW89_IC][6] = 42, - [1][0][RTW89_KCC][6] = 24, + [1][0][RTW89_KCC][6] = 32, [1][0][RTW89_ACMA][6] = 40, [1][0][RTW89_CN][6] = 26, [1][0][RTW89_UK][6] = 40, + [1][0][RTW89_MEXICO][6] = 64, + [1][0][RTW89_UKRAINE][6] = 32, + [1][0][RTW89_CHILE][6] = 64, + [1][0][RTW89_QATAR][6] = 40, [1][0][RTW89_FCC][8] = 62, [1][0][RTW89_ETSI][8] = 40, [1][0][RTW89_MKK][8] = 34, [1][0][RTW89_IC][8] = 62, - [1][0][RTW89_KCC][8] = 52, + [1][0][RTW89_KCC][8] = 50, [1][0][RTW89_ACMA][8] = 40, [1][0][RTW89_CN][8] = 26, [1][0][RTW89_UK][8] = 40, + [1][0][RTW89_MEXICO][8] = 62, + [1][0][RTW89_UKRAINE][8] = 32, + [1][0][RTW89_CHILE][8] = 62, + [1][0][RTW89_QATAR][8] = 40, [1][0][RTW89_FCC][10] = 62, [1][0][RTW89_ETSI][10] = 40, [1][0][RTW89_MKK][10] = 34, [1][0][RTW89_IC][10] = 62, - [1][0][RTW89_KCC][10] = 52, + [1][0][RTW89_KCC][10] = 50, [1][0][RTW89_ACMA][10] = 40, [1][0][RTW89_CN][10] = 26, [1][0][RTW89_UK][10] = 40, + [1][0][RTW89_MEXICO][10] = 62, + [1][0][RTW89_UKRAINE][10] = 32, + [1][0][RTW89_CHILE][10] = 62, + [1][0][RTW89_QATAR][10] = 40, [1][0][RTW89_FCC][12] = 62, [1][0][RTW89_ETSI][12] = 40, [1][0][RTW89_MKK][12] = 46, [1][0][RTW89_IC][12] = 62, - [1][0][RTW89_KCC][12] = 52, + [1][0][RTW89_KCC][12] = 50, [1][0][RTW89_ACMA][12] = 40, [1][0][RTW89_CN][12] = 26, [1][0][RTW89_UK][12] = 40, + [1][0][RTW89_MEXICO][12] = 62, + [1][0][RTW89_UKRAINE][12] = 32, + [1][0][RTW89_CHILE][12] = 62, + [1][0][RTW89_QATAR][12] = 40, [1][0][RTW89_FCC][14] = 62, [1][0][RTW89_ETSI][14] = 40, [1][0][RTW89_MKK][14] = 46, [1][0][RTW89_IC][14] = 62, - [1][0][RTW89_KCC][14] = 52, + [1][0][RTW89_KCC][14] = 50, [1][0][RTW89_ACMA][14] = 40, [1][0][RTW89_CN][14] = 26, [1][0][RTW89_UK][14] = 40, + [1][0][RTW89_MEXICO][14] = 62, + [1][0][RTW89_UKRAINE][14] = 32, + [1][0][RTW89_CHILE][14] = 62, + [1][0][RTW89_QATAR][14] = 40, [1][0][RTW89_FCC][15] = 62, [1][0][RTW89_ETSI][15] = 40, [1][0][RTW89_MKK][15] = 62, @@ -35432,6 +47849,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [1][0][RTW89_ACMA][15] = 40, [1][0][RTW89_CN][15] = 127, [1][0][RTW89_UK][15] = 40, + [1][0][RTW89_MEXICO][15] = 62, + [1][0][RTW89_UKRAINE][15] = 32, + [1][0][RTW89_CHILE][15] = 62, + [1][0][RTW89_QATAR][15] = 40, [1][0][RTW89_FCC][17] = 62, [1][0][RTW89_ETSI][17] = 40, [1][0][RTW89_MKK][17] = 68, @@ -35440,6 +47861,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [1][0][RTW89_ACMA][17] = 40, [1][0][RTW89_CN][17] = 127, [1][0][RTW89_UK][17] = 40, + [1][0][RTW89_MEXICO][17] = 62, + [1][0][RTW89_UKRAINE][17] = 32, + [1][0][RTW89_CHILE][17] = 62, + [1][0][RTW89_QATAR][17] = 40, [1][0][RTW89_FCC][19] = 64, [1][0][RTW89_ETSI][19] = 40, [1][0][RTW89_MKK][19] = 68, @@ -35448,6 +47873,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [1][0][RTW89_ACMA][19] = 40, [1][0][RTW89_CN][19] = 127, [1][0][RTW89_UK][19] = 40, + [1][0][RTW89_MEXICO][19] = 64, + [1][0][RTW89_UKRAINE][19] = 32, + [1][0][RTW89_CHILE][19] = 64, + [1][0][RTW89_QATAR][19] = 40, [1][0][RTW89_FCC][21] = 64, [1][0][RTW89_ETSI][21] = 40, [1][0][RTW89_MKK][21] = 68, @@ -35456,6 +47885,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [1][0][RTW89_ACMA][21] = 40, [1][0][RTW89_CN][21] = 127, [1][0][RTW89_UK][21] = 40, + [1][0][RTW89_MEXICO][21] = 64, + [1][0][RTW89_UKRAINE][21] = 32, + [1][0][RTW89_CHILE][21] = 64, + [1][0][RTW89_QATAR][21] = 40, [1][0][RTW89_FCC][23] = 64, [1][0][RTW89_ETSI][23] = 40, [1][0][RTW89_MKK][23] = 68, @@ -35464,6 +47897,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [1][0][RTW89_ACMA][23] = 40, [1][0][RTW89_CN][23] = 127, [1][0][RTW89_UK][23] = 40, + [1][0][RTW89_MEXICO][23] = 64, + [1][0][RTW89_UKRAINE][23] = 32, + [1][0][RTW89_CHILE][23] = 64, + [1][0][RTW89_QATAR][23] = 40, [1][0][RTW89_FCC][25] = 64, [1][0][RTW89_ETSI][25] = 40, [1][0][RTW89_MKK][25] = 68, @@ -35472,6 +47909,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [1][0][RTW89_ACMA][25] = 127, [1][0][RTW89_CN][25] = 127, [1][0][RTW89_UK][25] = 40, + [1][0][RTW89_MEXICO][25] = 64, + [1][0][RTW89_UKRAINE][25] = 32, + [1][0][RTW89_CHILE][25] = 64, + [1][0][RTW89_QATAR][25] = 40, [1][0][RTW89_FCC][27] = 64, [1][0][RTW89_ETSI][27] = 42, [1][0][RTW89_MKK][27] = 68, @@ -35480,6 +47921,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [1][0][RTW89_ACMA][27] = 127, [1][0][RTW89_CN][27] = 127, [1][0][RTW89_UK][27] = 42, + [1][0][RTW89_MEXICO][27] = 64, + [1][0][RTW89_UKRAINE][27] = 32, + [1][0][RTW89_CHILE][27] = 64, + [1][0][RTW89_QATAR][27] = 42, [1][0][RTW89_FCC][29] = 64, [1][0][RTW89_ETSI][29] = 42, [1][0][RTW89_MKK][29] = 68, @@ -35488,38 +47933,58 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [1][0][RTW89_ACMA][29] = 127, [1][0][RTW89_CN][29] = 127, [1][0][RTW89_UK][29] = 42, + [1][0][RTW89_MEXICO][29] = 64, + [1][0][RTW89_UKRAINE][29] = 32, + [1][0][RTW89_CHILE][29] = 64, + [1][0][RTW89_QATAR][29] = 42, [1][0][RTW89_FCC][31] = 64, [1][0][RTW89_ETSI][31] = 42, [1][0][RTW89_MKK][31] = 68, [1][0][RTW89_IC][31] = 56, - [1][0][RTW89_KCC][31] = 52, + [1][0][RTW89_KCC][31] = 50, [1][0][RTW89_ACMA][31] = 42, [1][0][RTW89_CN][31] = 127, [1][0][RTW89_UK][31] = 42, + [1][0][RTW89_MEXICO][31] = 64, + [1][0][RTW89_UKRAINE][31] = 32, + [1][0][RTW89_CHILE][31] = 64, + [1][0][RTW89_QATAR][31] = 42, [1][0][RTW89_FCC][33] = 56, [1][0][RTW89_ETSI][33] = 42, [1][0][RTW89_MKK][33] = 68, [1][0][RTW89_IC][33] = 56, - [1][0][RTW89_KCC][33] = 52, + [1][0][RTW89_KCC][33] = 50, [1][0][RTW89_ACMA][33] = 42, [1][0][RTW89_CN][33] = 127, [1][0][RTW89_UK][33] = 42, + [1][0][RTW89_MEXICO][33] = 56, + [1][0][RTW89_UKRAINE][33] = 32, + [1][0][RTW89_CHILE][33] = 56, + [1][0][RTW89_QATAR][33] = 42, [1][0][RTW89_FCC][35] = 56, [1][0][RTW89_ETSI][35] = 42, [1][0][RTW89_MKK][35] = 68, [1][0][RTW89_IC][35] = 56, - [1][0][RTW89_KCC][35] = 52, + [1][0][RTW89_KCC][35] = 50, [1][0][RTW89_ACMA][35] = 42, [1][0][RTW89_CN][35] = 127, [1][0][RTW89_UK][35] = 42, + [1][0][RTW89_MEXICO][35] = 56, + [1][0][RTW89_UKRAINE][35] = 32, + [1][0][RTW89_CHILE][35] = 56, + [1][0][RTW89_QATAR][35] = 42, [1][0][RTW89_FCC][37] = 66, [1][0][RTW89_ETSI][37] = 127, [1][0][RTW89_MKK][37] = 68, [1][0][RTW89_IC][37] = 66, - [1][0][RTW89_KCC][37] = 52, + [1][0][RTW89_KCC][37] = 50, [1][0][RTW89_ACMA][37] = 66, [1][0][RTW89_CN][37] = 127, [1][0][RTW89_UK][37] = 42, + [1][0][RTW89_MEXICO][37] = 66, + [1][0][RTW89_UKRAINE][37] = 127, + [1][0][RTW89_CHILE][37] = 66, + [1][0][RTW89_QATAR][37] = 127, [1][0][RTW89_FCC][38] = 76, [1][0][RTW89_ETSI][38] = 28, [1][0][RTW89_MKK][38] = 127, @@ -35528,6 +47993,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [1][0][RTW89_ACMA][38] = 76, [1][0][RTW89_CN][38] = 66, [1][0][RTW89_UK][38] = 44, + [1][0][RTW89_MEXICO][38] = 76, + [1][0][RTW89_UKRAINE][38] = 26, + [1][0][RTW89_CHILE][38] = 76, + [1][0][RTW89_QATAR][38] = 26, [1][0][RTW89_FCC][40] = 76, [1][0][RTW89_ETSI][40] = 28, [1][0][RTW89_MKK][40] = 127, @@ -35536,6 +48005,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [1][0][RTW89_ACMA][40] = 76, [1][0][RTW89_CN][40] = 66, [1][0][RTW89_UK][40] = 44, + [1][0][RTW89_MEXICO][40] = 76, + [1][0][RTW89_UKRAINE][40] = 26, + [1][0][RTW89_CHILE][40] = 76, + [1][0][RTW89_QATAR][40] = 26, [1][0][RTW89_FCC][42] = 68, [1][0][RTW89_ETSI][42] = 28, [1][0][RTW89_MKK][42] = 127, @@ -35544,6 +48017,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [1][0][RTW89_ACMA][42] = 68, [1][0][RTW89_CN][42] = 66, [1][0][RTW89_UK][42] = 44, + [1][0][RTW89_MEXICO][42] = 68, + [1][0][RTW89_UKRAINE][42] = 26, + [1][0][RTW89_CHILE][42] = 68, + [1][0][RTW89_QATAR][42] = 26, [1][0][RTW89_FCC][44] = 70, [1][0][RTW89_ETSI][44] = 28, [1][0][RTW89_MKK][44] = 127, @@ -35552,6 +48029,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [1][0][RTW89_ACMA][44] = 70, [1][0][RTW89_CN][44] = 66, [1][0][RTW89_UK][44] = 42, + [1][0][RTW89_MEXICO][44] = 70, + [1][0][RTW89_UKRAINE][44] = 26, + [1][0][RTW89_CHILE][44] = 70, + [1][0][RTW89_QATAR][44] = 26, [1][0][RTW89_FCC][46] = 70, [1][0][RTW89_ETSI][46] = 28, [1][0][RTW89_MKK][46] = 127, @@ -35560,6 +48041,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [1][0][RTW89_ACMA][46] = 70, [1][0][RTW89_CN][46] = 66, [1][0][RTW89_UK][46] = 42, + [1][0][RTW89_MEXICO][46] = 70, + [1][0][RTW89_UKRAINE][46] = 26, + [1][0][RTW89_CHILE][46] = 70, + [1][0][RTW89_QATAR][46] = 26, [1][0][RTW89_FCC][48] = 56, [1][0][RTW89_ETSI][48] = 127, [1][0][RTW89_MKK][48] = 127, @@ -35568,6 +48053,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [1][0][RTW89_ACMA][48] = 127, [1][0][RTW89_CN][48] = 127, [1][0][RTW89_UK][48] = 127, + [1][0][RTW89_MEXICO][48] = 127, + [1][0][RTW89_UKRAINE][48] = 127, + [1][0][RTW89_CHILE][48] = 127, + [1][0][RTW89_QATAR][48] = 127, [1][0][RTW89_FCC][50] = 58, [1][0][RTW89_ETSI][50] = 127, [1][0][RTW89_MKK][50] = 127, @@ -35576,6 +48065,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [1][0][RTW89_ACMA][50] = 127, [1][0][RTW89_CN][50] = 127, [1][0][RTW89_UK][50] = 127, + [1][0][RTW89_MEXICO][50] = 127, + [1][0][RTW89_UKRAINE][50] = 127, + [1][0][RTW89_CHILE][50] = 127, + [1][0][RTW89_QATAR][50] = 127, [1][0][RTW89_FCC][52] = 56, [1][0][RTW89_ETSI][52] = 127, [1][0][RTW89_MKK][52] = 127, @@ -35584,54 +48077,82 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [1][0][RTW89_ACMA][52] = 127, [1][0][RTW89_CN][52] = 127, [1][0][RTW89_UK][52] = 127, + [1][0][RTW89_MEXICO][52] = 127, + [1][0][RTW89_UKRAINE][52] = 127, + [1][0][RTW89_CHILE][52] = 127, + [1][0][RTW89_QATAR][52] = 127, [1][1][RTW89_FCC][0] = 44, [1][1][RTW89_ETSI][0] = 30, [1][1][RTW89_MKK][0] = 34, [1][1][RTW89_IC][0] = 20, - [1][1][RTW89_KCC][0] = 34, + [1][1][RTW89_KCC][0] = 40, [1][1][RTW89_ACMA][0] = 30, [1][1][RTW89_CN][0] = 14, [1][1][RTW89_UK][0] = 30, + [1][1][RTW89_MEXICO][0] = 44, + [1][1][RTW89_UKRAINE][0] = 20, + [1][1][RTW89_CHILE][0] = 44, + [1][1][RTW89_QATAR][0] = 30, [1][1][RTW89_FCC][2] = 44, [1][1][RTW89_ETSI][2] = 30, [1][1][RTW89_MKK][2] = 34, [1][1][RTW89_IC][2] = 18, - [1][1][RTW89_KCC][2] = 34, + [1][1][RTW89_KCC][2] = 40, [1][1][RTW89_ACMA][2] = 30, [1][1][RTW89_CN][2] = 14, [1][1][RTW89_UK][2] = 30, + [1][1][RTW89_MEXICO][2] = 44, + [1][1][RTW89_UKRAINE][2] = 20, + [1][1][RTW89_CHILE][2] = 44, + [1][1][RTW89_QATAR][2] = 30, [1][1][RTW89_FCC][4] = 46, [1][1][RTW89_ETSI][4] = 30, [1][1][RTW89_MKK][4] = 26, [1][1][RTW89_IC][4] = 20, - [1][1][RTW89_KCC][4] = 34, + [1][1][RTW89_KCC][4] = 40, [1][1][RTW89_ACMA][4] = 30, [1][1][RTW89_CN][4] = 14, [1][1][RTW89_UK][4] = 30, + [1][1][RTW89_MEXICO][4] = 46, + [1][1][RTW89_UKRAINE][4] = 20, + [1][1][RTW89_CHILE][4] = 46, + [1][1][RTW89_QATAR][4] = 30, [1][1][RTW89_FCC][6] = 46, [1][1][RTW89_ETSI][6] = 30, [1][1][RTW89_MKK][6] = 26, [1][1][RTW89_IC][6] = 20, - [1][1][RTW89_KCC][6] = 8, + [1][1][RTW89_KCC][6] = 18, [1][1][RTW89_ACMA][6] = 30, [1][1][RTW89_CN][6] = 14, [1][1][RTW89_UK][6] = 30, + [1][1][RTW89_MEXICO][6] = 46, + [1][1][RTW89_UKRAINE][6] = 20, + [1][1][RTW89_CHILE][6] = 46, + [1][1][RTW89_QATAR][6] = 30, [1][1][RTW89_FCC][8] = 44, [1][1][RTW89_ETSI][8] = 30, [1][1][RTW89_MKK][8] = 20, [1][1][RTW89_IC][8] = 44, - [1][1][RTW89_KCC][8] = 34, + [1][1][RTW89_KCC][8] = 38, [1][1][RTW89_ACMA][8] = 30, [1][1][RTW89_CN][8] = 14, [1][1][RTW89_UK][8] = 30, + [1][1][RTW89_MEXICO][8] = 44, + [1][1][RTW89_UKRAINE][8] = 20, + [1][1][RTW89_CHILE][8] = 44, + [1][1][RTW89_QATAR][8] = 30, [1][1][RTW89_FCC][10] = 44, [1][1][RTW89_ETSI][10] = 30, [1][1][RTW89_MKK][10] = 20, [1][1][RTW89_IC][10] = 44, - [1][1][RTW89_KCC][10] = 34, + [1][1][RTW89_KCC][10] = 38, [1][1][RTW89_ACMA][10] = 30, [1][1][RTW89_CN][10] = 14, [1][1][RTW89_UK][10] = 30, + [1][1][RTW89_MEXICO][10] = 44, + [1][1][RTW89_UKRAINE][10] = 20, + [1][1][RTW89_CHILE][10] = 44, + [1][1][RTW89_QATAR][10] = 30, [1][1][RTW89_FCC][12] = 44, [1][1][RTW89_ETSI][12] = 30, [1][1][RTW89_MKK][12] = 34, @@ -35640,6 +48161,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [1][1][RTW89_ACMA][12] = 30, [1][1][RTW89_CN][12] = 14, [1][1][RTW89_UK][12] = 30, + [1][1][RTW89_MEXICO][12] = 44, + [1][1][RTW89_UKRAINE][12] = 20, + [1][1][RTW89_CHILE][12] = 44, + [1][1][RTW89_QATAR][12] = 30, [1][1][RTW89_FCC][14] = 44, [1][1][RTW89_ETSI][14] = 30, [1][1][RTW89_MKK][14] = 34, @@ -35648,142 +48173,214 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [1][1][RTW89_ACMA][14] = 30, [1][1][RTW89_CN][14] = 14, [1][1][RTW89_UK][14] = 30, + [1][1][RTW89_MEXICO][14] = 44, + [1][1][RTW89_UKRAINE][14] = 20, + [1][1][RTW89_CHILE][14] = 44, + [1][1][RTW89_QATAR][14] = 30, [1][1][RTW89_FCC][15] = 44, [1][1][RTW89_ETSI][15] = 28, [1][1][RTW89_MKK][15] = 56, [1][1][RTW89_IC][15] = 44, - [1][1][RTW89_KCC][15] = 36, + [1][1][RTW89_KCC][15] = 38, [1][1][RTW89_ACMA][15] = 28, [1][1][RTW89_CN][15] = 127, [1][1][RTW89_UK][15] = 28, + [1][1][RTW89_MEXICO][15] = 44, + [1][1][RTW89_UKRAINE][15] = 20, + [1][1][RTW89_CHILE][15] = 44, + [1][1][RTW89_QATAR][15] = 28, [1][1][RTW89_FCC][17] = 44, [1][1][RTW89_ETSI][17] = 28, [1][1][RTW89_MKK][17] = 58, [1][1][RTW89_IC][17] = 44, - [1][1][RTW89_KCC][17] = 36, + [1][1][RTW89_KCC][17] = 38, [1][1][RTW89_ACMA][17] = 28, [1][1][RTW89_CN][17] = 127, [1][1][RTW89_UK][17] = 28, + [1][1][RTW89_MEXICO][17] = 44, + [1][1][RTW89_UKRAINE][17] = 20, + [1][1][RTW89_CHILE][17] = 44, + [1][1][RTW89_QATAR][17] = 28, [1][1][RTW89_FCC][19] = 44, [1][1][RTW89_ETSI][19] = 28, [1][1][RTW89_MKK][19] = 58, [1][1][RTW89_IC][19] = 44, - [1][1][RTW89_KCC][19] = 36, + [1][1][RTW89_KCC][19] = 38, [1][1][RTW89_ACMA][19] = 28, [1][1][RTW89_CN][19] = 127, [1][1][RTW89_UK][19] = 28, + [1][1][RTW89_MEXICO][19] = 44, + [1][1][RTW89_UKRAINE][19] = 20, + [1][1][RTW89_CHILE][19] = 44, + [1][1][RTW89_QATAR][19] = 28, [1][1][RTW89_FCC][21] = 44, [1][1][RTW89_ETSI][21] = 28, [1][1][RTW89_MKK][21] = 58, [1][1][RTW89_IC][21] = 44, - [1][1][RTW89_KCC][21] = 36, + [1][1][RTW89_KCC][21] = 38, [1][1][RTW89_ACMA][21] = 28, [1][1][RTW89_CN][21] = 127, [1][1][RTW89_UK][21] = 28, + [1][1][RTW89_MEXICO][21] = 44, + [1][1][RTW89_UKRAINE][21] = 20, + [1][1][RTW89_CHILE][21] = 44, + [1][1][RTW89_QATAR][21] = 28, [1][1][RTW89_FCC][23] = 44, [1][1][RTW89_ETSI][23] = 28, [1][1][RTW89_MKK][23] = 58, [1][1][RTW89_IC][23] = 44, - [1][1][RTW89_KCC][23] = 36, + [1][1][RTW89_KCC][23] = 38, [1][1][RTW89_ACMA][23] = 28, [1][1][RTW89_CN][23] = 127, [1][1][RTW89_UK][23] = 28, + [1][1][RTW89_MEXICO][23] = 44, + [1][1][RTW89_UKRAINE][23] = 20, + [1][1][RTW89_CHILE][23] = 44, + [1][1][RTW89_QATAR][23] = 28, [1][1][RTW89_FCC][25] = 44, [1][1][RTW89_ETSI][25] = 28, [1][1][RTW89_MKK][25] = 58, [1][1][RTW89_IC][25] = 127, - [1][1][RTW89_KCC][25] = 36, + [1][1][RTW89_KCC][25] = 38, [1][1][RTW89_ACMA][25] = 127, [1][1][RTW89_CN][25] = 127, [1][1][RTW89_UK][25] = 28, + [1][1][RTW89_MEXICO][25] = 44, + [1][1][RTW89_UKRAINE][25] = 20, + [1][1][RTW89_CHILE][25] = 44, + [1][1][RTW89_QATAR][25] = 28, [1][1][RTW89_FCC][27] = 44, [1][1][RTW89_ETSI][27] = 30, [1][1][RTW89_MKK][27] = 58, [1][1][RTW89_IC][27] = 127, - [1][1][RTW89_KCC][27] = 36, + [1][1][RTW89_KCC][27] = 38, [1][1][RTW89_ACMA][27] = 127, [1][1][RTW89_CN][27] = 127, [1][1][RTW89_UK][27] = 30, + [1][1][RTW89_MEXICO][27] = 44, + [1][1][RTW89_UKRAINE][27] = 20, + [1][1][RTW89_CHILE][27] = 44, + [1][1][RTW89_QATAR][27] = 30, [1][1][RTW89_FCC][29] = 44, [1][1][RTW89_ETSI][29] = 30, [1][1][RTW89_MKK][29] = 58, [1][1][RTW89_IC][29] = 127, - [1][1][RTW89_KCC][29] = 36, + [1][1][RTW89_KCC][29] = 38, [1][1][RTW89_ACMA][29] = 127, [1][1][RTW89_CN][29] = 127, [1][1][RTW89_UK][29] = 30, + [1][1][RTW89_MEXICO][29] = 44, + [1][1][RTW89_UKRAINE][29] = 20, + [1][1][RTW89_CHILE][29] = 44, + [1][1][RTW89_QATAR][29] = 30, [1][1][RTW89_FCC][31] = 44, [1][1][RTW89_ETSI][31] = 30, [1][1][RTW89_MKK][31] = 58, [1][1][RTW89_IC][31] = 38, - [1][1][RTW89_KCC][31] = 36, + [1][1][RTW89_KCC][31] = 40, [1][1][RTW89_ACMA][31] = 30, [1][1][RTW89_CN][31] = 127, [1][1][RTW89_UK][31] = 30, + [1][1][RTW89_MEXICO][31] = 44, + [1][1][RTW89_UKRAINE][31] = 20, + [1][1][RTW89_CHILE][31] = 44, + [1][1][RTW89_QATAR][31] = 30, [1][1][RTW89_FCC][33] = 38, [1][1][RTW89_ETSI][33] = 30, [1][1][RTW89_MKK][33] = 58, [1][1][RTW89_IC][33] = 38, - [1][1][RTW89_KCC][33] = 36, + [1][1][RTW89_KCC][33] = 40, [1][1][RTW89_ACMA][33] = 30, [1][1][RTW89_CN][33] = 127, [1][1][RTW89_UK][33] = 30, + [1][1][RTW89_MEXICO][33] = 38, + [1][1][RTW89_UKRAINE][33] = 20, + [1][1][RTW89_CHILE][33] = 38, + [1][1][RTW89_QATAR][33] = 30, [1][1][RTW89_FCC][35] = 38, [1][1][RTW89_ETSI][35] = 30, [1][1][RTW89_MKK][35] = 58, [1][1][RTW89_IC][35] = 38, - [1][1][RTW89_KCC][35] = 36, + [1][1][RTW89_KCC][35] = 40, [1][1][RTW89_ACMA][35] = 30, [1][1][RTW89_CN][35] = 127, [1][1][RTW89_UK][35] = 30, + [1][1][RTW89_MEXICO][35] = 38, + [1][1][RTW89_UKRAINE][35] = 20, + [1][1][RTW89_CHILE][35] = 38, + [1][1][RTW89_QATAR][35] = 30, [1][1][RTW89_FCC][37] = 46, [1][1][RTW89_ETSI][37] = 127, [1][1][RTW89_MKK][37] = 58, [1][1][RTW89_IC][37] = 46, - [1][1][RTW89_KCC][37] = 36, + [1][1][RTW89_KCC][37] = 40, [1][1][RTW89_ACMA][37] = 46, [1][1][RTW89_CN][37] = 127, [1][1][RTW89_UK][37] = 32, + [1][1][RTW89_MEXICO][37] = 46, + [1][1][RTW89_UKRAINE][37] = 127, + [1][1][RTW89_CHILE][37] = 46, + [1][1][RTW89_QATAR][37] = 127, [1][1][RTW89_FCC][38] = 74, [1][1][RTW89_ETSI][38] = 16, [1][1][RTW89_MKK][38] = 127, [1][1][RTW89_IC][38] = 74, - [1][1][RTW89_KCC][38] = 36, + [1][1][RTW89_KCC][38] = 38, [1][1][RTW89_ACMA][38] = 74, [1][1][RTW89_CN][38] = 54, [1][1][RTW89_UK][38] = 30, + [1][1][RTW89_MEXICO][38] = 74, + [1][1][RTW89_UKRAINE][38] = 14, + [1][1][RTW89_CHILE][38] = 72, + [1][1][RTW89_QATAR][38] = 14, [1][1][RTW89_FCC][40] = 74, [1][1][RTW89_ETSI][40] = 16, [1][1][RTW89_MKK][40] = 127, [1][1][RTW89_IC][40] = 74, - [1][1][RTW89_KCC][40] = 36, + [1][1][RTW89_KCC][40] = 38, [1][1][RTW89_ACMA][40] = 74, [1][1][RTW89_CN][40] = 54, [1][1][RTW89_UK][40] = 30, + [1][1][RTW89_MEXICO][40] = 74, + [1][1][RTW89_UKRAINE][40] = 14, + [1][1][RTW89_CHILE][40] = 72, + [1][1][RTW89_QATAR][40] = 14, [1][1][RTW89_FCC][42] = 74, [1][1][RTW89_ETSI][42] = 16, [1][1][RTW89_MKK][42] = 127, [1][1][RTW89_IC][42] = 74, - [1][1][RTW89_KCC][42] = 36, + [1][1][RTW89_KCC][42] = 38, [1][1][RTW89_ACMA][42] = 74, [1][1][RTW89_CN][42] = 54, [1][1][RTW89_UK][42] = 30, + [1][1][RTW89_MEXICO][42] = 74, + [1][1][RTW89_UKRAINE][42] = 14, + [1][1][RTW89_CHILE][42] = 72, + [1][1][RTW89_QATAR][42] = 14, [1][1][RTW89_FCC][44] = 74, [1][1][RTW89_ETSI][44] = 16, [1][1][RTW89_MKK][44] = 127, [1][1][RTW89_IC][44] = 74, - [1][1][RTW89_KCC][44] = 36, + [1][1][RTW89_KCC][44] = 38, [1][1][RTW89_ACMA][44] = 74, [1][1][RTW89_CN][44] = 54, [1][1][RTW89_UK][44] = 30, + [1][1][RTW89_MEXICO][44] = 74, + [1][1][RTW89_UKRAINE][44] = 14, + [1][1][RTW89_CHILE][44] = 72, + [1][1][RTW89_QATAR][44] = 14, [1][1][RTW89_FCC][46] = 74, [1][1][RTW89_ETSI][46] = 16, [1][1][RTW89_MKK][46] = 127, [1][1][RTW89_IC][46] = 74, - [1][1][RTW89_KCC][46] = 36, + [1][1][RTW89_KCC][46] = 38, [1][1][RTW89_ACMA][46] = 74, [1][1][RTW89_CN][46] = 54, [1][1][RTW89_UK][46] = 30, + [1][1][RTW89_MEXICO][46] = 74, + [1][1][RTW89_UKRAINE][46] = 14, + [1][1][RTW89_CHILE][46] = 72, + [1][1][RTW89_QATAR][46] = 14, [1][1][RTW89_FCC][48] = 34, [1][1][RTW89_ETSI][48] = 127, [1][1][RTW89_MKK][48] = 127, @@ -35792,6 +48389,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [1][1][RTW89_ACMA][48] = 127, [1][1][RTW89_CN][48] = 127, [1][1][RTW89_UK][48] = 127, + [1][1][RTW89_MEXICO][48] = 127, + [1][1][RTW89_UKRAINE][48] = 127, + [1][1][RTW89_CHILE][48] = 127, + [1][1][RTW89_QATAR][48] = 127, [1][1][RTW89_FCC][50] = 34, [1][1][RTW89_ETSI][50] = 127, [1][1][RTW89_MKK][50] = 127, @@ -35800,6 +48401,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [1][1][RTW89_ACMA][50] = 127, [1][1][RTW89_CN][50] = 127, [1][1][RTW89_UK][50] = 127, + [1][1][RTW89_MEXICO][50] = 127, + [1][1][RTW89_UKRAINE][50] = 127, + [1][1][RTW89_CHILE][50] = 127, + [1][1][RTW89_QATAR][50] = 127, [1][1][RTW89_FCC][52] = 30, [1][1][RTW89_ETSI][52] = 127, [1][1][RTW89_MKK][52] = 127, @@ -35808,206 +48413,310 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [1][1][RTW89_ACMA][52] = 127, [1][1][RTW89_CN][52] = 127, [1][1][RTW89_UK][52] = 127, + [1][1][RTW89_MEXICO][52] = 127, + [1][1][RTW89_UKRAINE][52] = 127, + [1][1][RTW89_CHILE][52] = 127, + [1][1][RTW89_QATAR][52] = 127, [2][0][RTW89_FCC][0] = 68, [2][0][RTW89_ETSI][0] = 52, [2][0][RTW89_MKK][0] = 60, [2][0][RTW89_IC][0] = 52, - [2][0][RTW89_KCC][0] = 64, + [2][0][RTW89_KCC][0] = 60, [2][0][RTW89_ACMA][0] = 52, [2][0][RTW89_CN][0] = 40, [2][0][RTW89_UK][0] = 52, + [2][0][RTW89_MEXICO][0] = 62, + [2][0][RTW89_UKRAINE][0] = 46, + [2][0][RTW89_CHILE][0] = 68, + [2][0][RTW89_QATAR][0] = 52, [2][0][RTW89_FCC][2] = 64, [2][0][RTW89_ETSI][2] = 52, [2][0][RTW89_MKK][2] = 60, [2][0][RTW89_IC][2] = 50, - [2][0][RTW89_KCC][2] = 64, + [2][0][RTW89_KCC][2] = 60, [2][0][RTW89_ACMA][2] = 52, [2][0][RTW89_CN][2] = 40, [2][0][RTW89_UK][2] = 52, + [2][0][RTW89_MEXICO][2] = 62, + [2][0][RTW89_UKRAINE][2] = 46, + [2][0][RTW89_CHILE][2] = 64, + [2][0][RTW89_QATAR][2] = 52, [2][0][RTW89_FCC][4] = 68, [2][0][RTW89_ETSI][4] = 52, [2][0][RTW89_MKK][4] = 50, [2][0][RTW89_IC][4] = 50, - [2][0][RTW89_KCC][4] = 64, + [2][0][RTW89_KCC][4] = 60, [2][0][RTW89_ACMA][4] = 52, [2][0][RTW89_CN][4] = 40, [2][0][RTW89_UK][4] = 52, + [2][0][RTW89_MEXICO][4] = 62, + [2][0][RTW89_UKRAINE][4] = 46, + [2][0][RTW89_CHILE][4] = 68, + [2][0][RTW89_QATAR][4] = 52, [2][0][RTW89_FCC][6] = 68, [2][0][RTW89_ETSI][6] = 52, [2][0][RTW89_MKK][6] = 50, [2][0][RTW89_IC][6] = 50, - [2][0][RTW89_KCC][6] = 36, + [2][0][RTW89_KCC][6] = 38, [2][0][RTW89_ACMA][6] = 52, [2][0][RTW89_CN][6] = 40, [2][0][RTW89_UK][6] = 52, + [2][0][RTW89_MEXICO][6] = 62, + [2][0][RTW89_UKRAINE][6] = 46, + [2][0][RTW89_CHILE][6] = 68, + [2][0][RTW89_QATAR][6] = 52, [2][0][RTW89_FCC][8] = 68, [2][0][RTW89_ETSI][8] = 52, [2][0][RTW89_MKK][8] = 44, [2][0][RTW89_IC][8] = 64, - [2][0][RTW89_KCC][8] = 62, + [2][0][RTW89_KCC][8] = 56, [2][0][RTW89_ACMA][8] = 52, [2][0][RTW89_CN][8] = 40, [2][0][RTW89_UK][8] = 52, + [2][0][RTW89_MEXICO][8] = 68, + [2][0][RTW89_UKRAINE][8] = 46, + [2][0][RTW89_CHILE][8] = 68, + [2][0][RTW89_QATAR][8] = 52, [2][0][RTW89_FCC][10] = 68, [2][0][RTW89_ETSI][10] = 52, [2][0][RTW89_MKK][10] = 44, [2][0][RTW89_IC][10] = 64, - [2][0][RTW89_KCC][10] = 62, + [2][0][RTW89_KCC][10] = 56, [2][0][RTW89_ACMA][10] = 52, [2][0][RTW89_CN][10] = 40, [2][0][RTW89_UK][10] = 52, + [2][0][RTW89_MEXICO][10] = 68, + [2][0][RTW89_UKRAINE][10] = 46, + [2][0][RTW89_CHILE][10] = 68, + [2][0][RTW89_QATAR][10] = 52, [2][0][RTW89_FCC][12] = 68, [2][0][RTW89_ETSI][12] = 52, [2][0][RTW89_MKK][12] = 58, [2][0][RTW89_IC][12] = 64, - [2][0][RTW89_KCC][12] = 62, + [2][0][RTW89_KCC][12] = 58, [2][0][RTW89_ACMA][12] = 52, [2][0][RTW89_CN][12] = 40, [2][0][RTW89_UK][12] = 52, + [2][0][RTW89_MEXICO][12] = 68, + [2][0][RTW89_UKRAINE][12] = 46, + [2][0][RTW89_CHILE][12] = 68, + [2][0][RTW89_QATAR][12] = 52, [2][0][RTW89_FCC][14] = 68, [2][0][RTW89_ETSI][14] = 52, [2][0][RTW89_MKK][14] = 58, [2][0][RTW89_IC][14] = 64, - [2][0][RTW89_KCC][14] = 62, + [2][0][RTW89_KCC][14] = 58, [2][0][RTW89_ACMA][14] = 52, [2][0][RTW89_CN][14] = 40, [2][0][RTW89_UK][14] = 52, + [2][0][RTW89_MEXICO][14] = 68, + [2][0][RTW89_UKRAINE][14] = 46, + [2][0][RTW89_CHILE][14] = 68, + [2][0][RTW89_QATAR][14] = 52, [2][0][RTW89_FCC][15] = 68, [2][0][RTW89_ETSI][15] = 52, [2][0][RTW89_MKK][15] = 68, [2][0][RTW89_IC][15] = 68, - [2][0][RTW89_KCC][15] = 62, + [2][0][RTW89_KCC][15] = 58, [2][0][RTW89_ACMA][15] = 52, [2][0][RTW89_CN][15] = 127, [2][0][RTW89_UK][15] = 52, + [2][0][RTW89_MEXICO][15] = 68, + [2][0][RTW89_UKRAINE][15] = 46, + [2][0][RTW89_CHILE][15] = 68, + [2][0][RTW89_QATAR][15] = 52, [2][0][RTW89_FCC][17] = 68, [2][0][RTW89_ETSI][17] = 52, [2][0][RTW89_MKK][17] = 74, [2][0][RTW89_IC][17] = 68, - [2][0][RTW89_KCC][17] = 62, + [2][0][RTW89_KCC][17] = 58, [2][0][RTW89_ACMA][17] = 52, [2][0][RTW89_CN][17] = 127, [2][0][RTW89_UK][17] = 52, + [2][0][RTW89_MEXICO][17] = 68, + [2][0][RTW89_UKRAINE][17] = 46, + [2][0][RTW89_CHILE][17] = 68, + [2][0][RTW89_QATAR][17] = 52, [2][0][RTW89_FCC][19] = 70, [2][0][RTW89_ETSI][19] = 52, [2][0][RTW89_MKK][19] = 74, [2][0][RTW89_IC][19] = 70, - [2][0][RTW89_KCC][19] = 62, + [2][0][RTW89_KCC][19] = 58, [2][0][RTW89_ACMA][19] = 52, [2][0][RTW89_CN][19] = 127, [2][0][RTW89_UK][19] = 52, + [2][0][RTW89_MEXICO][19] = 70, + [2][0][RTW89_UKRAINE][19] = 46, + [2][0][RTW89_CHILE][19] = 70, + [2][0][RTW89_QATAR][19] = 52, [2][0][RTW89_FCC][21] = 70, [2][0][RTW89_ETSI][21] = 52, [2][0][RTW89_MKK][21] = 74, [2][0][RTW89_IC][21] = 70, - [2][0][RTW89_KCC][21] = 62, + [2][0][RTW89_KCC][21] = 58, [2][0][RTW89_ACMA][21] = 52, [2][0][RTW89_CN][21] = 127, [2][0][RTW89_UK][21] = 52, + [2][0][RTW89_MEXICO][21] = 70, + [2][0][RTW89_UKRAINE][21] = 46, + [2][0][RTW89_CHILE][21] = 70, + [2][0][RTW89_QATAR][21] = 52, [2][0][RTW89_FCC][23] = 70, [2][0][RTW89_ETSI][23] = 52, [2][0][RTW89_MKK][23] = 74, [2][0][RTW89_IC][23] = 70, - [2][0][RTW89_KCC][23] = 62, + [2][0][RTW89_KCC][23] = 58, [2][0][RTW89_ACMA][23] = 52, [2][0][RTW89_CN][23] = 127, [2][0][RTW89_UK][23] = 52, + [2][0][RTW89_MEXICO][23] = 70, + [2][0][RTW89_UKRAINE][23] = 46, + [2][0][RTW89_CHILE][23] = 70, + [2][0][RTW89_QATAR][23] = 52, [2][0][RTW89_FCC][25] = 70, [2][0][RTW89_ETSI][25] = 52, [2][0][RTW89_MKK][25] = 74, [2][0][RTW89_IC][25] = 127, - [2][0][RTW89_KCC][25] = 62, + [2][0][RTW89_KCC][25] = 58, [2][0][RTW89_ACMA][25] = 127, [2][0][RTW89_CN][25] = 127, [2][0][RTW89_UK][25] = 52, + [2][0][RTW89_MEXICO][25] = 70, + [2][0][RTW89_UKRAINE][25] = 46, + [2][0][RTW89_CHILE][25] = 70, + [2][0][RTW89_QATAR][25] = 52, [2][0][RTW89_FCC][27] = 70, [2][0][RTW89_ETSI][27] = 52, [2][0][RTW89_MKK][27] = 74, [2][0][RTW89_IC][27] = 127, - [2][0][RTW89_KCC][27] = 62, + [2][0][RTW89_KCC][27] = 58, [2][0][RTW89_ACMA][27] = 127, [2][0][RTW89_CN][27] = 127, [2][0][RTW89_UK][27] = 52, + [2][0][RTW89_MEXICO][27] = 70, + [2][0][RTW89_UKRAINE][27] = 46, + [2][0][RTW89_CHILE][27] = 70, + [2][0][RTW89_QATAR][27] = 52, [2][0][RTW89_FCC][29] = 70, [2][0][RTW89_ETSI][29] = 52, [2][0][RTW89_MKK][29] = 74, [2][0][RTW89_IC][29] = 127, - [2][0][RTW89_KCC][29] = 62, + [2][0][RTW89_KCC][29] = 58, [2][0][RTW89_ACMA][29] = 127, [2][0][RTW89_CN][29] = 127, [2][0][RTW89_UK][29] = 52, + [2][0][RTW89_MEXICO][29] = 70, + [2][0][RTW89_UKRAINE][29] = 46, + [2][0][RTW89_CHILE][29] = 70, + [2][0][RTW89_QATAR][29] = 52, [2][0][RTW89_FCC][31] = 70, [2][0][RTW89_ETSI][31] = 52, [2][0][RTW89_MKK][31] = 74, [2][0][RTW89_IC][31] = 62, - [2][0][RTW89_KCC][31] = 62, + [2][0][RTW89_KCC][31] = 56, [2][0][RTW89_ACMA][31] = 52, [2][0][RTW89_CN][31] = 127, [2][0][RTW89_UK][31] = 52, + [2][0][RTW89_MEXICO][31] = 70, + [2][0][RTW89_UKRAINE][31] = 46, + [2][0][RTW89_CHILE][31] = 70, + [2][0][RTW89_QATAR][31] = 52, [2][0][RTW89_FCC][33] = 62, [2][0][RTW89_ETSI][33] = 52, [2][0][RTW89_MKK][33] = 74, [2][0][RTW89_IC][33] = 62, - [2][0][RTW89_KCC][33] = 62, + [2][0][RTW89_KCC][33] = 56, [2][0][RTW89_ACMA][33] = 52, [2][0][RTW89_CN][33] = 127, [2][0][RTW89_UK][33] = 52, + [2][0][RTW89_MEXICO][33] = 62, + [2][0][RTW89_UKRAINE][33] = 46, + [2][0][RTW89_CHILE][33] = 62, + [2][0][RTW89_QATAR][33] = 52, [2][0][RTW89_FCC][35] = 62, [2][0][RTW89_ETSI][35] = 52, [2][0][RTW89_MKK][35] = 74, [2][0][RTW89_IC][35] = 62, - [2][0][RTW89_KCC][35] = 62, + [2][0][RTW89_KCC][35] = 56, [2][0][RTW89_ACMA][35] = 52, [2][0][RTW89_CN][35] = 127, [2][0][RTW89_UK][35] = 52, + [2][0][RTW89_MEXICO][35] = 62, + [2][0][RTW89_UKRAINE][35] = 46, + [2][0][RTW89_CHILE][35] = 62, + [2][0][RTW89_QATAR][35] = 52, [2][0][RTW89_FCC][37] = 70, [2][0][RTW89_ETSI][37] = 127, [2][0][RTW89_MKK][37] = 74, [2][0][RTW89_IC][37] = 70, - [2][0][RTW89_KCC][37] = 62, + [2][0][RTW89_KCC][37] = 56, [2][0][RTW89_ACMA][37] = 70, [2][0][RTW89_CN][37] = 127, [2][0][RTW89_UK][37] = 52, + [2][0][RTW89_MEXICO][37] = 70, + [2][0][RTW89_UKRAINE][37] = 127, + [2][0][RTW89_CHILE][37] = 70, + [2][0][RTW89_QATAR][37] = 127, [2][0][RTW89_FCC][38] = 82, [2][0][RTW89_ETSI][38] = 28, [2][0][RTW89_MKK][38] = 127, [2][0][RTW89_IC][38] = 82, - [2][0][RTW89_KCC][38] = 64, + [2][0][RTW89_KCC][38] = 60, [2][0][RTW89_ACMA][38] = 82, [2][0][RTW89_CN][38] = 68, [2][0][RTW89_UK][38] = 54, + [2][0][RTW89_MEXICO][38] = 82, + [2][0][RTW89_UKRAINE][38] = 26, + [2][0][RTW89_CHILE][38] = 82, + [2][0][RTW89_QATAR][38] = 26, [2][0][RTW89_FCC][40] = 82, [2][0][RTW89_ETSI][40] = 28, [2][0][RTW89_MKK][40] = 127, [2][0][RTW89_IC][40] = 82, - [2][0][RTW89_KCC][40] = 64, + [2][0][RTW89_KCC][40] = 60, [2][0][RTW89_ACMA][40] = 82, [2][0][RTW89_CN][40] = 68, [2][0][RTW89_UK][40] = 54, + [2][0][RTW89_MEXICO][40] = 82, + [2][0][RTW89_UKRAINE][40] = 26, + [2][0][RTW89_CHILE][40] = 82, + [2][0][RTW89_QATAR][40] = 26, [2][0][RTW89_FCC][42] = 76, [2][0][RTW89_ETSI][42] = 28, [2][0][RTW89_MKK][42] = 127, [2][0][RTW89_IC][42] = 76, - [2][0][RTW89_KCC][42] = 64, + [2][0][RTW89_KCC][42] = 60, [2][0][RTW89_ACMA][42] = 76, [2][0][RTW89_CN][42] = 68, [2][0][RTW89_UK][42] = 54, + [2][0][RTW89_MEXICO][42] = 76, + [2][0][RTW89_UKRAINE][42] = 26, + [2][0][RTW89_CHILE][42] = 76, + [2][0][RTW89_QATAR][42] = 26, [2][0][RTW89_FCC][44] = 80, [2][0][RTW89_ETSI][44] = 28, [2][0][RTW89_MKK][44] = 127, [2][0][RTW89_IC][44] = 80, - [2][0][RTW89_KCC][44] = 64, + [2][0][RTW89_KCC][44] = 60, [2][0][RTW89_ACMA][44] = 80, [2][0][RTW89_CN][44] = 68, [2][0][RTW89_UK][44] = 54, + [2][0][RTW89_MEXICO][44] = 80, + [2][0][RTW89_UKRAINE][44] = 26, + [2][0][RTW89_CHILE][44] = 80, + [2][0][RTW89_QATAR][44] = 26, [2][0][RTW89_FCC][46] = 80, [2][0][RTW89_ETSI][46] = 28, [2][0][RTW89_MKK][46] = 127, [2][0][RTW89_IC][46] = 80, - [2][0][RTW89_KCC][46] = 64, + [2][0][RTW89_KCC][46] = 60, [2][0][RTW89_ACMA][46] = 80, [2][0][RTW89_CN][46] = 68, [2][0][RTW89_UK][46] = 54, + [2][0][RTW89_MEXICO][46] = 80, + [2][0][RTW89_UKRAINE][46] = 26, + [2][0][RTW89_CHILE][46] = 80, + [2][0][RTW89_QATAR][46] = 26, [2][0][RTW89_FCC][48] = 64, [2][0][RTW89_ETSI][48] = 127, [2][0][RTW89_MKK][48] = 127, @@ -36016,6 +48725,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [2][0][RTW89_ACMA][48] = 127, [2][0][RTW89_CN][48] = 127, [2][0][RTW89_UK][48] = 127, + [2][0][RTW89_MEXICO][48] = 127, + [2][0][RTW89_UKRAINE][48] = 127, + [2][0][RTW89_CHILE][48] = 127, + [2][0][RTW89_QATAR][48] = 127, [2][0][RTW89_FCC][50] = 64, [2][0][RTW89_ETSI][50] = 127, [2][0][RTW89_MKK][50] = 127, @@ -36024,6 +48737,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [2][0][RTW89_ACMA][50] = 127, [2][0][RTW89_CN][50] = 127, [2][0][RTW89_UK][50] = 127, + [2][0][RTW89_MEXICO][50] = 127, + [2][0][RTW89_UKRAINE][50] = 127, + [2][0][RTW89_CHILE][50] = 127, + [2][0][RTW89_QATAR][50] = 127, [2][0][RTW89_FCC][52] = 64, [2][0][RTW89_ETSI][52] = 127, [2][0][RTW89_MKK][52] = 127, @@ -36032,206 +48749,310 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [2][0][RTW89_ACMA][52] = 127, [2][0][RTW89_CN][52] = 127, [2][0][RTW89_UK][52] = 127, + [2][0][RTW89_MEXICO][52] = 127, + [2][0][RTW89_UKRAINE][52] = 127, + [2][0][RTW89_CHILE][52] = 127, + [2][0][RTW89_QATAR][52] = 127, [2][1][RTW89_FCC][0] = 50, [2][1][RTW89_ETSI][0] = 40, [2][1][RTW89_MKK][0] = 44, [2][1][RTW89_IC][0] = 26, - [2][1][RTW89_KCC][0] = 44, + [2][1][RTW89_KCC][0] = 52, [2][1][RTW89_ACMA][0] = 40, [2][1][RTW89_CN][0] = 28, [2][1][RTW89_UK][0] = 40, + [2][1][RTW89_MEXICO][0] = 50, + [2][1][RTW89_UKRAINE][0] = 34, + [2][1][RTW89_CHILE][0] = 50, + [2][1][RTW89_QATAR][0] = 40, [2][1][RTW89_FCC][2] = 50, [2][1][RTW89_ETSI][2] = 40, [2][1][RTW89_MKK][2] = 44, [2][1][RTW89_IC][2] = 26, - [2][1][RTW89_KCC][2] = 44, + [2][1][RTW89_KCC][2] = 52, [2][1][RTW89_ACMA][2] = 40, [2][1][RTW89_CN][2] = 28, [2][1][RTW89_UK][2] = 40, + [2][1][RTW89_MEXICO][2] = 50, + [2][1][RTW89_UKRAINE][2] = 34, + [2][1][RTW89_CHILE][2] = 50, + [2][1][RTW89_QATAR][2] = 40, [2][1][RTW89_FCC][4] = 50, [2][1][RTW89_ETSI][4] = 40, [2][1][RTW89_MKK][4] = 36, [2][1][RTW89_IC][4] = 26, - [2][1][RTW89_KCC][4] = 44, + [2][1][RTW89_KCC][4] = 52, [2][1][RTW89_ACMA][4] = 40, [2][1][RTW89_CN][4] = 28, [2][1][RTW89_UK][4] = 40, + [2][1][RTW89_MEXICO][4] = 50, + [2][1][RTW89_UKRAINE][4] = 34, + [2][1][RTW89_CHILE][4] = 50, + [2][1][RTW89_QATAR][4] = 40, [2][1][RTW89_FCC][6] = 50, [2][1][RTW89_ETSI][6] = 40, [2][1][RTW89_MKK][6] = 36, [2][1][RTW89_IC][6] = 26, - [2][1][RTW89_KCC][6] = 20, + [2][1][RTW89_KCC][6] = 30, [2][1][RTW89_ACMA][6] = 40, [2][1][RTW89_CN][6] = 28, [2][1][RTW89_UK][6] = 40, + [2][1][RTW89_MEXICO][6] = 50, + [2][1][RTW89_UKRAINE][6] = 34, + [2][1][RTW89_CHILE][6] = 50, + [2][1][RTW89_QATAR][6] = 40, [2][1][RTW89_FCC][8] = 50, [2][1][RTW89_ETSI][8] = 40, [2][1][RTW89_MKK][8] = 32, [2][1][RTW89_IC][8] = 50, - [2][1][RTW89_KCC][8] = 46, + [2][1][RTW89_KCC][8] = 50, [2][1][RTW89_ACMA][8] = 40, [2][1][RTW89_CN][8] = 28, [2][1][RTW89_UK][8] = 40, + [2][1][RTW89_MEXICO][8] = 50, + [2][1][RTW89_UKRAINE][8] = 34, + [2][1][RTW89_CHILE][8] = 50, + [2][1][RTW89_QATAR][8] = 40, [2][1][RTW89_FCC][10] = 50, [2][1][RTW89_ETSI][10] = 40, [2][1][RTW89_MKK][10] = 32, [2][1][RTW89_IC][10] = 50, - [2][1][RTW89_KCC][10] = 46, + [2][1][RTW89_KCC][10] = 50, [2][1][RTW89_ACMA][10] = 40, [2][1][RTW89_CN][10] = 28, [2][1][RTW89_UK][10] = 40, + [2][1][RTW89_MEXICO][10] = 50, + [2][1][RTW89_UKRAINE][10] = 34, + [2][1][RTW89_CHILE][10] = 50, + [2][1][RTW89_QATAR][10] = 40, [2][1][RTW89_FCC][12] = 48, [2][1][RTW89_ETSI][12] = 40, [2][1][RTW89_MKK][12] = 44, [2][1][RTW89_IC][12] = 48, - [2][1][RTW89_KCC][12] = 46, + [2][1][RTW89_KCC][12] = 48, [2][1][RTW89_ACMA][12] = 40, [2][1][RTW89_CN][12] = 28, [2][1][RTW89_UK][12] = 40, + [2][1][RTW89_MEXICO][12] = 48, + [2][1][RTW89_UKRAINE][12] = 34, + [2][1][RTW89_CHILE][12] = 48, + [2][1][RTW89_QATAR][12] = 40, [2][1][RTW89_FCC][14] = 48, [2][1][RTW89_ETSI][14] = 40, [2][1][RTW89_MKK][14] = 44, [2][1][RTW89_IC][14] = 48, - [2][1][RTW89_KCC][14] = 46, + [2][1][RTW89_KCC][14] = 48, [2][1][RTW89_ACMA][14] = 40, [2][1][RTW89_CN][14] = 28, [2][1][RTW89_UK][14] = 40, + [2][1][RTW89_MEXICO][14] = 48, + [2][1][RTW89_UKRAINE][14] = 34, + [2][1][RTW89_CHILE][14] = 48, + [2][1][RTW89_QATAR][14] = 40, [2][1][RTW89_FCC][15] = 50, [2][1][RTW89_ETSI][15] = 40, [2][1][RTW89_MKK][15] = 66, [2][1][RTW89_IC][15] = 50, - [2][1][RTW89_KCC][15] = 46, + [2][1][RTW89_KCC][15] = 48, [2][1][RTW89_ACMA][15] = 40, [2][1][RTW89_CN][15] = 127, [2][1][RTW89_UK][15] = 40, + [2][1][RTW89_MEXICO][15] = 50, + [2][1][RTW89_UKRAINE][15] = 34, + [2][1][RTW89_CHILE][15] = 50, + [2][1][RTW89_QATAR][15] = 40, [2][1][RTW89_FCC][17] = 50, [2][1][RTW89_ETSI][17] = 40, [2][1][RTW89_MKK][17] = 66, [2][1][RTW89_IC][17] = 50, - [2][1][RTW89_KCC][17] = 46, + [2][1][RTW89_KCC][17] = 48, [2][1][RTW89_ACMA][17] = 40, [2][1][RTW89_CN][17] = 127, [2][1][RTW89_UK][17] = 40, + [2][1][RTW89_MEXICO][17] = 50, + [2][1][RTW89_UKRAINE][17] = 34, + [2][1][RTW89_CHILE][17] = 50, + [2][1][RTW89_QATAR][17] = 40, [2][1][RTW89_FCC][19] = 50, [2][1][RTW89_ETSI][19] = 40, [2][1][RTW89_MKK][19] = 66, [2][1][RTW89_IC][19] = 50, - [2][1][RTW89_KCC][19] = 46, + [2][1][RTW89_KCC][19] = 48, [2][1][RTW89_ACMA][19] = 40, [2][1][RTW89_CN][19] = 127, [2][1][RTW89_UK][19] = 40, + [2][1][RTW89_MEXICO][19] = 50, + [2][1][RTW89_UKRAINE][19] = 34, + [2][1][RTW89_CHILE][19] = 50, + [2][1][RTW89_QATAR][19] = 40, [2][1][RTW89_FCC][21] = 50, [2][1][RTW89_ETSI][21] = 40, [2][1][RTW89_MKK][21] = 66, [2][1][RTW89_IC][21] = 50, - [2][1][RTW89_KCC][21] = 46, + [2][1][RTW89_KCC][21] = 48, [2][1][RTW89_ACMA][21] = 40, [2][1][RTW89_CN][21] = 127, [2][1][RTW89_UK][21] = 40, + [2][1][RTW89_MEXICO][21] = 50, + [2][1][RTW89_UKRAINE][21] = 34, + [2][1][RTW89_CHILE][21] = 50, + [2][1][RTW89_QATAR][21] = 40, [2][1][RTW89_FCC][23] = 50, [2][1][RTW89_ETSI][23] = 40, [2][1][RTW89_MKK][23] = 66, [2][1][RTW89_IC][23] = 50, - [2][1][RTW89_KCC][23] = 46, + [2][1][RTW89_KCC][23] = 48, [2][1][RTW89_ACMA][23] = 40, [2][1][RTW89_CN][23] = 127, [2][1][RTW89_UK][23] = 40, + [2][1][RTW89_MEXICO][23] = 50, + [2][1][RTW89_UKRAINE][23] = 34, + [2][1][RTW89_CHILE][23] = 50, + [2][1][RTW89_QATAR][23] = 40, [2][1][RTW89_FCC][25] = 50, [2][1][RTW89_ETSI][25] = 40, [2][1][RTW89_MKK][25] = 66, [2][1][RTW89_IC][25] = 127, - [2][1][RTW89_KCC][25] = 46, + [2][1][RTW89_KCC][25] = 48, [2][1][RTW89_ACMA][25] = 127, [2][1][RTW89_CN][25] = 127, [2][1][RTW89_UK][25] = 40, + [2][1][RTW89_MEXICO][25] = 50, + [2][1][RTW89_UKRAINE][25] = 34, + [2][1][RTW89_CHILE][25] = 50, + [2][1][RTW89_QATAR][25] = 40, [2][1][RTW89_FCC][27] = 50, [2][1][RTW89_ETSI][27] = 40, [2][1][RTW89_MKK][27] = 66, [2][1][RTW89_IC][27] = 127, - [2][1][RTW89_KCC][27] = 46, + [2][1][RTW89_KCC][27] = 48, [2][1][RTW89_ACMA][27] = 127, [2][1][RTW89_CN][27] = 127, [2][1][RTW89_UK][27] = 40, + [2][1][RTW89_MEXICO][27] = 50, + [2][1][RTW89_UKRAINE][27] = 34, + [2][1][RTW89_CHILE][27] = 50, + [2][1][RTW89_QATAR][27] = 40, [2][1][RTW89_FCC][29] = 50, [2][1][RTW89_ETSI][29] = 40, [2][1][RTW89_MKK][29] = 66, [2][1][RTW89_IC][29] = 127, - [2][1][RTW89_KCC][29] = 46, + [2][1][RTW89_KCC][29] = 48, [2][1][RTW89_ACMA][29] = 127, [2][1][RTW89_CN][29] = 127, [2][1][RTW89_UK][29] = 40, + [2][1][RTW89_MEXICO][29] = 50, + [2][1][RTW89_UKRAINE][29] = 34, + [2][1][RTW89_CHILE][29] = 50, + [2][1][RTW89_QATAR][29] = 40, [2][1][RTW89_FCC][31] = 50, [2][1][RTW89_ETSI][31] = 40, [2][1][RTW89_MKK][31] = 66, [2][1][RTW89_IC][31] = 48, - [2][1][RTW89_KCC][31] = 46, + [2][1][RTW89_KCC][31] = 48, [2][1][RTW89_ACMA][31] = 40, [2][1][RTW89_CN][31] = 127, [2][1][RTW89_UK][31] = 40, + [2][1][RTW89_MEXICO][31] = 50, + [2][1][RTW89_UKRAINE][31] = 34, + [2][1][RTW89_CHILE][31] = 50, + [2][1][RTW89_QATAR][31] = 40, [2][1][RTW89_FCC][33] = 48, [2][1][RTW89_ETSI][33] = 40, [2][1][RTW89_MKK][33] = 66, [2][1][RTW89_IC][33] = 48, - [2][1][RTW89_KCC][33] = 46, + [2][1][RTW89_KCC][33] = 48, [2][1][RTW89_ACMA][33] = 40, [2][1][RTW89_CN][33] = 127, [2][1][RTW89_UK][33] = 40, + [2][1][RTW89_MEXICO][33] = 48, + [2][1][RTW89_UKRAINE][33] = 34, + [2][1][RTW89_CHILE][33] = 48, + [2][1][RTW89_QATAR][33] = 40, [2][1][RTW89_FCC][35] = 48, [2][1][RTW89_ETSI][35] = 40, [2][1][RTW89_MKK][35] = 66, [2][1][RTW89_IC][35] = 48, - [2][1][RTW89_KCC][35] = 46, + [2][1][RTW89_KCC][35] = 48, [2][1][RTW89_ACMA][35] = 40, [2][1][RTW89_CN][35] = 127, [2][1][RTW89_UK][35] = 40, + [2][1][RTW89_MEXICO][35] = 48, + [2][1][RTW89_UKRAINE][35] = 34, + [2][1][RTW89_CHILE][35] = 48, + [2][1][RTW89_QATAR][35] = 40, [2][1][RTW89_FCC][37] = 52, [2][1][RTW89_ETSI][37] = 127, [2][1][RTW89_MKK][37] = 66, [2][1][RTW89_IC][37] = 52, - [2][1][RTW89_KCC][37] = 46, + [2][1][RTW89_KCC][37] = 48, [2][1][RTW89_ACMA][37] = 52, [2][1][RTW89_CN][37] = 127, [2][1][RTW89_UK][37] = 42, + [2][1][RTW89_MEXICO][37] = 52, + [2][1][RTW89_UKRAINE][37] = 127, + [2][1][RTW89_CHILE][37] = 52, + [2][1][RTW89_QATAR][37] = 127, [2][1][RTW89_FCC][38] = 78, [2][1][RTW89_ETSI][38] = 16, [2][1][RTW89_MKK][38] = 127, [2][1][RTW89_IC][38] = 78, - [2][1][RTW89_KCC][38] = 46, + [2][1][RTW89_KCC][38] = 50, [2][1][RTW89_ACMA][38] = 78, [2][1][RTW89_CN][38] = 56, [2][1][RTW89_UK][38] = 42, + [2][1][RTW89_MEXICO][38] = 78, + [2][1][RTW89_UKRAINE][38] = 14, + [2][1][RTW89_CHILE][38] = 72, + [2][1][RTW89_QATAR][38] = 14, [2][1][RTW89_FCC][40] = 78, [2][1][RTW89_ETSI][40] = 16, [2][1][RTW89_MKK][40] = 127, [2][1][RTW89_IC][40] = 78, - [2][1][RTW89_KCC][40] = 46, + [2][1][RTW89_KCC][40] = 50, [2][1][RTW89_ACMA][40] = 78, [2][1][RTW89_CN][40] = 56, [2][1][RTW89_UK][40] = 42, + [2][1][RTW89_MEXICO][40] = 78, + [2][1][RTW89_UKRAINE][40] = 14, + [2][1][RTW89_CHILE][40] = 72, + [2][1][RTW89_QATAR][40] = 14, [2][1][RTW89_FCC][42] = 78, [2][1][RTW89_ETSI][42] = 16, [2][1][RTW89_MKK][42] = 127, [2][1][RTW89_IC][42] = 78, - [2][1][RTW89_KCC][42] = 46, + [2][1][RTW89_KCC][42] = 50, [2][1][RTW89_ACMA][42] = 78, [2][1][RTW89_CN][42] = 56, [2][1][RTW89_UK][42] = 42, + [2][1][RTW89_MEXICO][42] = 78, + [2][1][RTW89_UKRAINE][42] = 14, + [2][1][RTW89_CHILE][42] = 72, + [2][1][RTW89_QATAR][42] = 14, [2][1][RTW89_FCC][44] = 74, [2][1][RTW89_ETSI][44] = 16, [2][1][RTW89_MKK][44] = 127, [2][1][RTW89_IC][44] = 74, - [2][1][RTW89_KCC][44] = 46, + [2][1][RTW89_KCC][44] = 50, [2][1][RTW89_ACMA][44] = 74, [2][1][RTW89_CN][44] = 56, [2][1][RTW89_UK][44] = 42, + [2][1][RTW89_MEXICO][44] = 74, + [2][1][RTW89_UKRAINE][44] = 14, + [2][1][RTW89_CHILE][44] = 72, + [2][1][RTW89_QATAR][44] = 14, [2][1][RTW89_FCC][46] = 74, [2][1][RTW89_ETSI][46] = 16, [2][1][RTW89_MKK][46] = 127, [2][1][RTW89_IC][46] = 74, - [2][1][RTW89_KCC][46] = 46, + [2][1][RTW89_KCC][46] = 50, [2][1][RTW89_ACMA][46] = 74, [2][1][RTW89_CN][46] = 56, [2][1][RTW89_UK][46] = 42, + [2][1][RTW89_MEXICO][46] = 74, + [2][1][RTW89_UKRAINE][46] = 14, + [2][1][RTW89_CHILE][46] = 72, + [2][1][RTW89_QATAR][46] = 14, [2][1][RTW89_FCC][48] = 40, [2][1][RTW89_ETSI][48] = 127, [2][1][RTW89_MKK][48] = 127, @@ -36240,6 +49061,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [2][1][RTW89_ACMA][48] = 127, [2][1][RTW89_CN][48] = 127, [2][1][RTW89_UK][48] = 127, + [2][1][RTW89_MEXICO][48] = 127, + [2][1][RTW89_UKRAINE][48] = 127, + [2][1][RTW89_CHILE][48] = 127, + [2][1][RTW89_QATAR][48] = 127, [2][1][RTW89_FCC][50] = 40, [2][1][RTW89_ETSI][50] = 127, [2][1][RTW89_MKK][50] = 127, @@ -36248,6 +49073,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [2][1][RTW89_ACMA][50] = 127, [2][1][RTW89_CN][50] = 127, [2][1][RTW89_UK][50] = 127, + [2][1][RTW89_MEXICO][50] = 127, + [2][1][RTW89_UKRAINE][50] = 127, + [2][1][RTW89_CHILE][50] = 127, + [2][1][RTW89_QATAR][50] = 127, [2][1][RTW89_FCC][52] = 40, [2][1][RTW89_ETSI][52] = 127, [2][1][RTW89_MKK][52] = 127, @@ -36256,1163 +49085,7312 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [2][1][RTW89_ACMA][52] = 127, [2][1][RTW89_CN][52] = 127, [2][1][RTW89_UK][52] = 127, + [2][1][RTW89_MEXICO][52] = 127, + [2][1][RTW89_UKRAINE][52] = 127, + [2][1][RTW89_CHILE][52] = 127, + [2][1][RTW89_QATAR][52] = 127, }; static const s8 rtw89_8852c_txpwr_lmt_ru_6g[RTW89_RU_NUM][RTW89_NTX_NUM] - [RTW89_REGD_NUM][RTW89_6G_CH_NUM] = { - [0][0][RTW89_WW][0] = -16, - [0][0][RTW89_WW][2] = -18, - [0][0][RTW89_WW][4] = -18, - [0][0][RTW89_WW][6] = -18, - [0][0][RTW89_WW][8] = -18, - [0][0][RTW89_WW][10] = -18, - [0][0][RTW89_WW][12] = -18, - [0][0][RTW89_WW][14] = -18, - [0][0][RTW89_WW][15] = -18, - [0][0][RTW89_WW][17] = -18, - [0][0][RTW89_WW][19] = -18, - [0][0][RTW89_WW][21] = -18, - [0][0][RTW89_WW][23] = -18, - [0][0][RTW89_WW][25] = -18, - [0][0][RTW89_WW][27] = -18, - [0][0][RTW89_WW][29] = -18, - [0][0][RTW89_WW][30] = -18, - [0][0][RTW89_WW][32] = -18, - [0][0][RTW89_WW][34] = -18, - [0][0][RTW89_WW][36] = -18, - [0][0][RTW89_WW][38] = -18, - [0][0][RTW89_WW][40] = -18, - [0][0][RTW89_WW][42] = -18, - [0][0][RTW89_WW][44] = -16, - [0][0][RTW89_WW][45] = -16, - [0][0][RTW89_WW][47] = -18, - [0][0][RTW89_WW][49] = -18, - [0][0][RTW89_WW][51] = -18, - [0][0][RTW89_WW][53] = -16, - [0][0][RTW89_WW][55] = -18, - [0][0][RTW89_WW][57] = -18, - [0][0][RTW89_WW][59] = -18, - [0][0][RTW89_WW][60] = -18, - [0][0][RTW89_WW][62] = -18, - [0][0][RTW89_WW][64] = -18, - [0][0][RTW89_WW][66] = -18, - [0][0][RTW89_WW][68] = -18, - [0][0][RTW89_WW][70] = -16, - [0][0][RTW89_WW][72] = -18, - [0][0][RTW89_WW][74] = -18, - [0][0][RTW89_WW][75] = -18, - [0][0][RTW89_WW][77] = -18, - [0][0][RTW89_WW][79] = -18, - [0][0][RTW89_WW][81] = -18, - [0][0][RTW89_WW][83] = -18, - [0][0][RTW89_WW][85] = -18, - [0][0][RTW89_WW][87] = -16, - [0][0][RTW89_WW][89] = -16, - [0][0][RTW89_WW][90] = -16, - [0][0][RTW89_WW][92] = -16, - [0][0][RTW89_WW][94] = -16, - [0][0][RTW89_WW][96] = -16, - [0][0][RTW89_WW][98] = -16, - [0][0][RTW89_WW][100] = -16, - [0][0][RTW89_WW][102] = -16, - [0][0][RTW89_WW][104] = -16, - [0][0][RTW89_WW][105] = -16, - [0][0][RTW89_WW][107] = -12, - [0][0][RTW89_WW][109] = -12, - [0][0][RTW89_WW][111] = 0, - [0][0][RTW89_WW][113] = 0, - [0][0][RTW89_WW][115] = 0, - [0][0][RTW89_WW][117] = 0, - [0][0][RTW89_WW][119] = 0, - [0][1][RTW89_WW][0] = -40, - [0][1][RTW89_WW][2] = -40, - [0][1][RTW89_WW][4] = -40, - [0][1][RTW89_WW][6] = -40, - [0][1][RTW89_WW][8] = -40, - [0][1][RTW89_WW][10] = -40, - [0][1][RTW89_WW][12] = -40, - [0][1][RTW89_WW][14] = -40, - [0][1][RTW89_WW][15] = -40, - [0][1][RTW89_WW][17] = -40, - [0][1][RTW89_WW][19] = -40, - [0][1][RTW89_WW][21] = -40, - [0][1][RTW89_WW][23] = -40, - [0][1][RTW89_WW][25] = -40, - [0][1][RTW89_WW][27] = -40, - [0][1][RTW89_WW][29] = -40, - [0][1][RTW89_WW][30] = -40, - [0][1][RTW89_WW][32] = -40, - [0][1][RTW89_WW][34] = -40, - [0][1][RTW89_WW][36] = -40, - [0][1][RTW89_WW][38] = -40, - [0][1][RTW89_WW][40] = -40, - [0][1][RTW89_WW][42] = -40, - [0][1][RTW89_WW][44] = -40, - [0][1][RTW89_WW][45] = -40, - [0][1][RTW89_WW][47] = -40, - [0][1][RTW89_WW][49] = -40, - [0][1][RTW89_WW][51] = -40, - [0][1][RTW89_WW][53] = -40, - [0][1][RTW89_WW][55] = -40, - [0][1][RTW89_WW][57] = -40, - [0][1][RTW89_WW][59] = -40, - [0][1][RTW89_WW][60] = -40, - [0][1][RTW89_WW][62] = -40, - [0][1][RTW89_WW][64] = -40, - [0][1][RTW89_WW][66] = -40, - [0][1][RTW89_WW][68] = -40, - [0][1][RTW89_WW][70] = -38, - [0][1][RTW89_WW][72] = -38, - [0][1][RTW89_WW][74] = -38, - [0][1][RTW89_WW][75] = -38, - [0][1][RTW89_WW][77] = -38, - [0][1][RTW89_WW][79] = -38, - [0][1][RTW89_WW][81] = -38, - [0][1][RTW89_WW][83] = -38, - [0][1][RTW89_WW][85] = -38, - [0][1][RTW89_WW][87] = -40, - [0][1][RTW89_WW][89] = -38, - [0][1][RTW89_WW][90] = -38, - [0][1][RTW89_WW][92] = -38, - [0][1][RTW89_WW][94] = -38, - [0][1][RTW89_WW][96] = -38, - [0][1][RTW89_WW][98] = -38, - [0][1][RTW89_WW][100] = -38, - [0][1][RTW89_WW][102] = -38, - [0][1][RTW89_WW][104] = -38, - [0][1][RTW89_WW][105] = -38, - [0][1][RTW89_WW][107] = -34, - [0][1][RTW89_WW][109] = -34, - [0][1][RTW89_WW][111] = 0, - [0][1][RTW89_WW][113] = 0, - [0][1][RTW89_WW][115] = 0, - [0][1][RTW89_WW][117] = 0, - [0][1][RTW89_WW][119] = 0, - [1][0][RTW89_WW][0] = -4, - [1][0][RTW89_WW][2] = -4, - [1][0][RTW89_WW][4] = -4, - [1][0][RTW89_WW][6] = -4, - [1][0][RTW89_WW][8] = -4, - [1][0][RTW89_WW][10] = -4, - [1][0][RTW89_WW][12] = -4, - [1][0][RTW89_WW][14] = -4, - [1][0][RTW89_WW][15] = -4, - [1][0][RTW89_WW][17] = -4, - [1][0][RTW89_WW][19] = -4, - [1][0][RTW89_WW][21] = -4, - [1][0][RTW89_WW][23] = -4, - [1][0][RTW89_WW][25] = -4, - [1][0][RTW89_WW][27] = -4, - [1][0][RTW89_WW][29] = -4, - [1][0][RTW89_WW][30] = -4, - [1][0][RTW89_WW][32] = -4, - [1][0][RTW89_WW][34] = -4, - [1][0][RTW89_WW][36] = -4, - [1][0][RTW89_WW][38] = -4, - [1][0][RTW89_WW][40] = -4, - [1][0][RTW89_WW][42] = -4, - [1][0][RTW89_WW][44] = -4, - [1][0][RTW89_WW][45] = -4, - [1][0][RTW89_WW][47] = -4, - [1][0][RTW89_WW][49] = -4, - [1][0][RTW89_WW][51] = -4, - [1][0][RTW89_WW][53] = -4, - [1][0][RTW89_WW][55] = -4, - [1][0][RTW89_WW][57] = -4, - [1][0][RTW89_WW][59] = -4, - [1][0][RTW89_WW][60] = -4, - [1][0][RTW89_WW][62] = -4, - [1][0][RTW89_WW][64] = -4, - [1][0][RTW89_WW][66] = -4, - [1][0][RTW89_WW][68] = -4, - [1][0][RTW89_WW][70] = -4, - [1][0][RTW89_WW][72] = -4, - [1][0][RTW89_WW][74] = -4, - [1][0][RTW89_WW][75] = -4, - [1][0][RTW89_WW][77] = -4, - [1][0][RTW89_WW][79] = -4, - [1][0][RTW89_WW][81] = -4, - [1][0][RTW89_WW][83] = -4, - [1][0][RTW89_WW][85] = -4, - [1][0][RTW89_WW][87] = -4, - [1][0][RTW89_WW][89] = -4, - [1][0][RTW89_WW][90] = -4, - [1][0][RTW89_WW][92] = -4, - [1][0][RTW89_WW][94] = -4, - [1][0][RTW89_WW][96] = -4, - [1][0][RTW89_WW][98] = -4, - [1][0][RTW89_WW][100] = -4, - [1][0][RTW89_WW][102] = -4, - [1][0][RTW89_WW][104] = -4, - [1][0][RTW89_WW][105] = -4, - [1][0][RTW89_WW][107] = 1, - [1][0][RTW89_WW][109] = 2, - [1][0][RTW89_WW][111] = 0, - [1][0][RTW89_WW][113] = 0, - [1][0][RTW89_WW][115] = 0, - [1][0][RTW89_WW][117] = 0, - [1][0][RTW89_WW][119] = 0, - [1][1][RTW89_WW][0] = -26, - [1][1][RTW89_WW][2] = -28, - [1][1][RTW89_WW][4] = -28, - [1][1][RTW89_WW][6] = -28, - [1][1][RTW89_WW][8] = -28, - [1][1][RTW89_WW][10] = -28, - [1][1][RTW89_WW][12] = -28, - [1][1][RTW89_WW][14] = -28, - [1][1][RTW89_WW][15] = -28, - [1][1][RTW89_WW][17] = -28, - [1][1][RTW89_WW][19] = -28, - [1][1][RTW89_WW][21] = -28, - [1][1][RTW89_WW][23] = -28, - [1][1][RTW89_WW][25] = -28, - [1][1][RTW89_WW][27] = -28, - [1][1][RTW89_WW][29] = -28, - [1][1][RTW89_WW][30] = -28, - [1][1][RTW89_WW][32] = -28, - [1][1][RTW89_WW][34] = -28, - [1][1][RTW89_WW][36] = -28, - [1][1][RTW89_WW][38] = -28, - [1][1][RTW89_WW][40] = -28, - [1][1][RTW89_WW][42] = -28, - [1][1][RTW89_WW][44] = -28, - [1][1][RTW89_WW][45] = -26, - [1][1][RTW89_WW][47] = -28, - [1][1][RTW89_WW][49] = -28, - [1][1][RTW89_WW][51] = -28, - [1][1][RTW89_WW][53] = -26, - [1][1][RTW89_WW][55] = -28, - [1][1][RTW89_WW][57] = -28, - [1][1][RTW89_WW][59] = -28, - [1][1][RTW89_WW][60] = -28, - [1][1][RTW89_WW][62] = -28, - [1][1][RTW89_WW][64] = -28, - [1][1][RTW89_WW][66] = -28, - [1][1][RTW89_WW][68] = -28, - [1][1][RTW89_WW][70] = -26, - [1][1][RTW89_WW][72] = -28, - [1][1][RTW89_WW][74] = -28, - [1][1][RTW89_WW][75] = -28, - [1][1][RTW89_WW][77] = -28, - [1][1][RTW89_WW][79] = -28, - [1][1][RTW89_WW][81] = -28, - [1][1][RTW89_WW][83] = -28, - [1][1][RTW89_WW][85] = -28, - [1][1][RTW89_WW][87] = -28, - [1][1][RTW89_WW][89] = -26, - [1][1][RTW89_WW][90] = -26, - [1][1][RTW89_WW][92] = -26, - [1][1][RTW89_WW][94] = -26, - [1][1][RTW89_WW][96] = -26, - [1][1][RTW89_WW][98] = -26, - [1][1][RTW89_WW][100] = -26, - [1][1][RTW89_WW][102] = -26, - [1][1][RTW89_WW][104] = -26, - [1][1][RTW89_WW][105] = -26, - [1][1][RTW89_WW][107] = -22, - [1][1][RTW89_WW][109] = -22, - [1][1][RTW89_WW][111] = 0, - [1][1][RTW89_WW][113] = 0, - [1][1][RTW89_WW][115] = 0, - [1][1][RTW89_WW][117] = 0, - [1][1][RTW89_WW][119] = 0, - [2][0][RTW89_WW][0] = 8, - [2][0][RTW89_WW][2] = 8, - [2][0][RTW89_WW][4] = 8, - [2][0][RTW89_WW][6] = 8, - [2][0][RTW89_WW][8] = 8, - [2][0][RTW89_WW][10] = 8, - [2][0][RTW89_WW][12] = 8, - [2][0][RTW89_WW][14] = 8, - [2][0][RTW89_WW][15] = 8, - [2][0][RTW89_WW][17] = 8, - [2][0][RTW89_WW][19] = 8, - [2][0][RTW89_WW][21] = 8, - [2][0][RTW89_WW][23] = 8, - [2][0][RTW89_WW][25] = 8, - [2][0][RTW89_WW][27] = 8, - [2][0][RTW89_WW][29] = 8, - [2][0][RTW89_WW][30] = 8, - [2][0][RTW89_WW][32] = 8, - [2][0][RTW89_WW][34] = 8, - [2][0][RTW89_WW][36] = 8, - [2][0][RTW89_WW][38] = 8, - [2][0][RTW89_WW][40] = 8, - [2][0][RTW89_WW][42] = 8, - [2][0][RTW89_WW][44] = 8, - [2][0][RTW89_WW][45] = 8, - [2][0][RTW89_WW][47] = 8, - [2][0][RTW89_WW][49] = 8, - [2][0][RTW89_WW][51] = 8, - [2][0][RTW89_WW][53] = 8, - [2][0][RTW89_WW][55] = 8, - [2][0][RTW89_WW][57] = 8, - [2][0][RTW89_WW][59] = 8, - [2][0][RTW89_WW][60] = 8, - [2][0][RTW89_WW][62] = 8, - [2][0][RTW89_WW][64] = 8, - [2][0][RTW89_WW][66] = 8, - [2][0][RTW89_WW][68] = 8, - [2][0][RTW89_WW][70] = 8, - [2][0][RTW89_WW][72] = 8, - [2][0][RTW89_WW][74] = 8, - [2][0][RTW89_WW][75] = 8, - [2][0][RTW89_WW][77] = 8, - [2][0][RTW89_WW][79] = 8, - [2][0][RTW89_WW][81] = 8, - [2][0][RTW89_WW][83] = 8, - [2][0][RTW89_WW][85] = 8, - [2][0][RTW89_WW][87] = 8, - [2][0][RTW89_WW][89] = 8, - [2][0][RTW89_WW][90] = 8, - [2][0][RTW89_WW][92] = 8, - [2][0][RTW89_WW][94] = 8, - [2][0][RTW89_WW][96] = 8, - [2][0][RTW89_WW][98] = 8, - [2][0][RTW89_WW][100] = 8, - [2][0][RTW89_WW][102] = 8, - [2][0][RTW89_WW][104] = 8, - [2][0][RTW89_WW][105] = 8, - [2][0][RTW89_WW][107] = 10, - [2][0][RTW89_WW][109] = 12, - [2][0][RTW89_WW][111] = 0, - [2][0][RTW89_WW][113] = 0, - [2][0][RTW89_WW][115] = 0, - [2][0][RTW89_WW][117] = 0, - [2][0][RTW89_WW][119] = 0, - [2][1][RTW89_WW][0] = -16, - [2][1][RTW89_WW][2] = -16, - [2][1][RTW89_WW][4] = -16, - [2][1][RTW89_WW][6] = -16, - [2][1][RTW89_WW][8] = -16, - [2][1][RTW89_WW][10] = -16, - [2][1][RTW89_WW][12] = -16, - [2][1][RTW89_WW][14] = -16, - [2][1][RTW89_WW][15] = -16, - [2][1][RTW89_WW][17] = -16, - [2][1][RTW89_WW][19] = -16, - [2][1][RTW89_WW][21] = -16, - [2][1][RTW89_WW][23] = -16, - [2][1][RTW89_WW][25] = -16, - [2][1][RTW89_WW][27] = -16, - [2][1][RTW89_WW][29] = -16, - [2][1][RTW89_WW][30] = -16, - [2][1][RTW89_WW][32] = -16, - [2][1][RTW89_WW][34] = -16, - [2][1][RTW89_WW][36] = -16, - [2][1][RTW89_WW][38] = -16, - [2][1][RTW89_WW][40] = -16, - [2][1][RTW89_WW][42] = -16, - [2][1][RTW89_WW][44] = -16, - [2][1][RTW89_WW][45] = -16, - [2][1][RTW89_WW][47] = -16, - [2][1][RTW89_WW][49] = -16, - [2][1][RTW89_WW][51] = -16, - [2][1][RTW89_WW][53] = -16, - [2][1][RTW89_WW][55] = -16, - [2][1][RTW89_WW][57] = -16, - [2][1][RTW89_WW][59] = -16, - [2][1][RTW89_WW][60] = -16, - [2][1][RTW89_WW][62] = -16, - [2][1][RTW89_WW][64] = -16, - [2][1][RTW89_WW][66] = -16, - [2][1][RTW89_WW][68] = -16, - [2][1][RTW89_WW][70] = -16, - [2][1][RTW89_WW][72] = -16, - [2][1][RTW89_WW][74] = -16, - [2][1][RTW89_WW][75] = -16, - [2][1][RTW89_WW][77] = -16, - [2][1][RTW89_WW][79] = -16, - [2][1][RTW89_WW][81] = -16, - [2][1][RTW89_WW][83] = -16, - [2][1][RTW89_WW][85] = -18, - [2][1][RTW89_WW][87] = -16, - [2][1][RTW89_WW][89] = -16, - [2][1][RTW89_WW][90] = -16, - [2][1][RTW89_WW][92] = -16, - [2][1][RTW89_WW][94] = -16, - [2][1][RTW89_WW][96] = -16, - [2][1][RTW89_WW][98] = -16, - [2][1][RTW89_WW][100] = -16, - [2][1][RTW89_WW][102] = -16, - [2][1][RTW89_WW][104] = -16, - [2][1][RTW89_WW][105] = -16, - [2][1][RTW89_WW][107] = -12, - [2][1][RTW89_WW][109] = -10, - [2][1][RTW89_WW][111] = 0, - [2][1][RTW89_WW][113] = 0, - [2][1][RTW89_WW][115] = 0, - [2][1][RTW89_WW][117] = 0, - [2][1][RTW89_WW][119] = 0, - [0][0][RTW89_FCC][0] = -16, - [0][0][RTW89_ETSI][0] = 32, - [0][0][RTW89_FCC][2] = -18, - [0][0][RTW89_ETSI][2] = 32, - [0][0][RTW89_FCC][4] = -18, - [0][0][RTW89_ETSI][4] = 32, - [0][0][RTW89_FCC][6] = -18, - [0][0][RTW89_ETSI][6] = 32, - [0][0][RTW89_FCC][8] = -18, - [0][0][RTW89_ETSI][8] = 32, - [0][0][RTW89_FCC][10] = -18, - [0][0][RTW89_ETSI][10] = 32, - [0][0][RTW89_FCC][12] = -18, - [0][0][RTW89_ETSI][12] = 32, - [0][0][RTW89_FCC][14] = -18, - [0][0][RTW89_ETSI][14] = 32, - [0][0][RTW89_FCC][15] = -18, - [0][0][RTW89_ETSI][15] = 32, - [0][0][RTW89_FCC][17] = -18, - [0][0][RTW89_ETSI][17] = 32, - [0][0][RTW89_FCC][19] = -18, - [0][0][RTW89_ETSI][19] = 32, - [0][0][RTW89_FCC][21] = -18, - [0][0][RTW89_ETSI][21] = 32, - [0][0][RTW89_FCC][23] = -18, - [0][0][RTW89_ETSI][23] = 32, - [0][0][RTW89_FCC][25] = -18, - [0][0][RTW89_ETSI][25] = 32, - [0][0][RTW89_FCC][27] = -18, - [0][0][RTW89_ETSI][27] = 32, - [0][0][RTW89_FCC][29] = -18, - [0][0][RTW89_ETSI][29] = 32, - [0][0][RTW89_FCC][30] = -18, - [0][0][RTW89_ETSI][30] = 32, - [0][0][RTW89_FCC][32] = -18, - [0][0][RTW89_ETSI][32] = 32, - [0][0][RTW89_FCC][34] = -18, - [0][0][RTW89_ETSI][34] = 32, - [0][0][RTW89_FCC][36] = -18, - [0][0][RTW89_ETSI][36] = 32, - [0][0][RTW89_FCC][38] = -18, - [0][0][RTW89_ETSI][38] = 32, - [0][0][RTW89_FCC][40] = -18, - [0][0][RTW89_ETSI][40] = 32, - [0][0][RTW89_FCC][42] = -18, - [0][0][RTW89_ETSI][42] = 32, - [0][0][RTW89_FCC][44] = -16, - [0][0][RTW89_ETSI][44] = 32, - [0][0][RTW89_FCC][45] = -16, - [0][0][RTW89_ETSI][45] = 127, - [0][0][RTW89_FCC][47] = -18, - [0][0][RTW89_ETSI][47] = 127, - [0][0][RTW89_FCC][49] = -18, - [0][0][RTW89_ETSI][49] = 127, - [0][0][RTW89_FCC][51] = -18, - [0][0][RTW89_ETSI][51] = 127, - [0][0][RTW89_FCC][53] = -16, - [0][0][RTW89_ETSI][53] = 127, - [0][0][RTW89_FCC][55] = -18, - [0][0][RTW89_ETSI][55] = 127, - [0][0][RTW89_FCC][57] = -18, - [0][0][RTW89_ETSI][57] = 127, - [0][0][RTW89_FCC][59] = -18, - [0][0][RTW89_ETSI][59] = 127, - [0][0][RTW89_FCC][60] = -18, - [0][0][RTW89_ETSI][60] = 127, - [0][0][RTW89_FCC][62] = -18, - [0][0][RTW89_ETSI][62] = 127, - [0][0][RTW89_FCC][64] = -18, - [0][0][RTW89_ETSI][64] = 127, - [0][0][RTW89_FCC][66] = -18, - [0][0][RTW89_ETSI][66] = 127, - [0][0][RTW89_FCC][68] = -18, - [0][0][RTW89_ETSI][68] = 127, - [0][0][RTW89_FCC][70] = -16, - [0][0][RTW89_ETSI][70] = 127, - [0][0][RTW89_FCC][72] = -18, - [0][0][RTW89_ETSI][72] = 127, - [0][0][RTW89_FCC][74] = -18, - [0][0][RTW89_ETSI][74] = 127, - [0][0][RTW89_FCC][75] = -18, - [0][0][RTW89_ETSI][75] = 127, - [0][0][RTW89_FCC][77] = -18, - [0][0][RTW89_ETSI][77] = 127, - [0][0][RTW89_FCC][79] = -18, - [0][0][RTW89_ETSI][79] = 127, - [0][0][RTW89_FCC][81] = -18, - [0][0][RTW89_ETSI][81] = 127, - [0][0][RTW89_FCC][83] = -18, - [0][0][RTW89_ETSI][83] = 127, - [0][0][RTW89_FCC][85] = -18, - [0][0][RTW89_ETSI][85] = 127, - [0][0][RTW89_FCC][87] = -16, - [0][0][RTW89_ETSI][87] = 127, - [0][0][RTW89_FCC][89] = -16, - [0][0][RTW89_ETSI][89] = 127, - [0][0][RTW89_FCC][90] = -16, - [0][0][RTW89_ETSI][90] = 127, - [0][0][RTW89_FCC][92] = -16, - [0][0][RTW89_ETSI][92] = 127, - [0][0][RTW89_FCC][94] = -16, - [0][0][RTW89_ETSI][94] = 127, - [0][0][RTW89_FCC][96] = -16, - [0][0][RTW89_ETSI][96] = 127, - [0][0][RTW89_FCC][98] = -16, - [0][0][RTW89_ETSI][98] = 127, - [0][0][RTW89_FCC][100] = -16, - [0][0][RTW89_ETSI][100] = 127, - [0][0][RTW89_FCC][102] = -16, - [0][0][RTW89_ETSI][102] = 127, - [0][0][RTW89_FCC][104] = -16, - [0][0][RTW89_ETSI][104] = 127, - [0][0][RTW89_FCC][105] = -16, - [0][0][RTW89_ETSI][105] = 127, - [0][0][RTW89_FCC][107] = -12, - [0][0][RTW89_ETSI][107] = 127, - [0][0][RTW89_FCC][109] = -12, - [0][0][RTW89_ETSI][109] = 127, - [0][0][RTW89_FCC][111] = 127, - [0][0][RTW89_ETSI][111] = 127, - [0][0][RTW89_FCC][113] = 127, - [0][0][RTW89_ETSI][113] = 127, - [0][0][RTW89_FCC][115] = 127, - [0][0][RTW89_ETSI][115] = 127, - [0][0][RTW89_FCC][117] = 127, - [0][0][RTW89_ETSI][117] = 127, - [0][0][RTW89_FCC][119] = 127, - [0][0][RTW89_ETSI][119] = 127, - [0][1][RTW89_FCC][0] = -40, - [0][1][RTW89_ETSI][0] = 20, - [0][1][RTW89_FCC][2] = -40, - [0][1][RTW89_ETSI][2] = 20, - [0][1][RTW89_FCC][4] = -40, - [0][1][RTW89_ETSI][4] = 20, - [0][1][RTW89_FCC][6] = -40, - [0][1][RTW89_ETSI][6] = 20, - [0][1][RTW89_FCC][8] = -40, - [0][1][RTW89_ETSI][8] = 20, - [0][1][RTW89_FCC][10] = -40, - [0][1][RTW89_ETSI][10] = 20, - [0][1][RTW89_FCC][12] = -40, - [0][1][RTW89_ETSI][12] = 20, - [0][1][RTW89_FCC][14] = -40, - [0][1][RTW89_ETSI][14] = 20, - [0][1][RTW89_FCC][15] = -40, - [0][1][RTW89_ETSI][15] = 20, - [0][1][RTW89_FCC][17] = -40, - [0][1][RTW89_ETSI][17] = 20, - [0][1][RTW89_FCC][19] = -40, - [0][1][RTW89_ETSI][19] = 20, - [0][1][RTW89_FCC][21] = -40, - [0][1][RTW89_ETSI][21] = 20, - [0][1][RTW89_FCC][23] = -40, - [0][1][RTW89_ETSI][23] = 20, - [0][1][RTW89_FCC][25] = -40, - [0][1][RTW89_ETSI][25] = 20, - [0][1][RTW89_FCC][27] = -40, - [0][1][RTW89_ETSI][27] = 20, - [0][1][RTW89_FCC][29] = -40, - [0][1][RTW89_ETSI][29] = 20, - [0][1][RTW89_FCC][30] = -40, - [0][1][RTW89_ETSI][30] = 20, - [0][1][RTW89_FCC][32] = -40, - [0][1][RTW89_ETSI][32] = 20, - [0][1][RTW89_FCC][34] = -40, - [0][1][RTW89_ETSI][34] = 20, - [0][1][RTW89_FCC][36] = -40, - [0][1][RTW89_ETSI][36] = 20, - [0][1][RTW89_FCC][38] = -40, - [0][1][RTW89_ETSI][38] = 20, - [0][1][RTW89_FCC][40] = -40, - [0][1][RTW89_ETSI][40] = 20, - [0][1][RTW89_FCC][42] = -40, - [0][1][RTW89_ETSI][42] = 20, - [0][1][RTW89_FCC][44] = -40, - [0][1][RTW89_ETSI][44] = 20, - [0][1][RTW89_FCC][45] = -40, - [0][1][RTW89_ETSI][45] = 127, - [0][1][RTW89_FCC][47] = -40, - [0][1][RTW89_ETSI][47] = 127, - [0][1][RTW89_FCC][49] = -40, - [0][1][RTW89_ETSI][49] = 127, - [0][1][RTW89_FCC][51] = -40, - [0][1][RTW89_ETSI][51] = 127, - [0][1][RTW89_FCC][53] = -40, - [0][1][RTW89_ETSI][53] = 127, - [0][1][RTW89_FCC][55] = -40, - [0][1][RTW89_ETSI][55] = 127, - [0][1][RTW89_FCC][57] = -40, - [0][1][RTW89_ETSI][57] = 127, - [0][1][RTW89_FCC][59] = -40, - [0][1][RTW89_ETSI][59] = 127, - [0][1][RTW89_FCC][60] = -40, - [0][1][RTW89_ETSI][60] = 127, - [0][1][RTW89_FCC][62] = -40, - [0][1][RTW89_ETSI][62] = 127, - [0][1][RTW89_FCC][64] = -40, - [0][1][RTW89_ETSI][64] = 127, - [0][1][RTW89_FCC][66] = -40, - [0][1][RTW89_ETSI][66] = 127, - [0][1][RTW89_FCC][68] = -40, - [0][1][RTW89_ETSI][68] = 127, - [0][1][RTW89_FCC][70] = -38, - [0][1][RTW89_ETSI][70] = 127, - [0][1][RTW89_FCC][72] = -38, - [0][1][RTW89_ETSI][72] = 127, - [0][1][RTW89_FCC][74] = -38, - [0][1][RTW89_ETSI][74] = 127, - [0][1][RTW89_FCC][75] = -38, - [0][1][RTW89_ETSI][75] = 127, - [0][1][RTW89_FCC][77] = -38, - [0][1][RTW89_ETSI][77] = 127, - [0][1][RTW89_FCC][79] = -38, - [0][1][RTW89_ETSI][79] = 127, - [0][1][RTW89_FCC][81] = -38, - [0][1][RTW89_ETSI][81] = 127, - [0][1][RTW89_FCC][83] = -38, - [0][1][RTW89_ETSI][83] = 127, - [0][1][RTW89_FCC][85] = -38, - [0][1][RTW89_ETSI][85] = 127, - [0][1][RTW89_FCC][87] = -40, - [0][1][RTW89_ETSI][87] = 127, - [0][1][RTW89_FCC][89] = -38, - [0][1][RTW89_ETSI][89] = 127, - [0][1][RTW89_FCC][90] = -38, - [0][1][RTW89_ETSI][90] = 127, - [0][1][RTW89_FCC][92] = -38, - [0][1][RTW89_ETSI][92] = 127, - [0][1][RTW89_FCC][94] = -38, - [0][1][RTW89_ETSI][94] = 127, - [0][1][RTW89_FCC][96] = -38, - [0][1][RTW89_ETSI][96] = 127, - [0][1][RTW89_FCC][98] = -38, - [0][1][RTW89_ETSI][98] = 127, - [0][1][RTW89_FCC][100] = -38, - [0][1][RTW89_ETSI][100] = 127, - [0][1][RTW89_FCC][102] = -38, - [0][1][RTW89_ETSI][102] = 127, - [0][1][RTW89_FCC][104] = -38, - [0][1][RTW89_ETSI][104] = 127, - [0][1][RTW89_FCC][105] = -38, - [0][1][RTW89_ETSI][105] = 127, - [0][1][RTW89_FCC][107] = -34, - [0][1][RTW89_ETSI][107] = 127, - [0][1][RTW89_FCC][109] = -34, - [0][1][RTW89_ETSI][109] = 127, - [0][1][RTW89_FCC][111] = 127, - [0][1][RTW89_ETSI][111] = 127, - [0][1][RTW89_FCC][113] = 127, - [0][1][RTW89_ETSI][113] = 127, - [0][1][RTW89_FCC][115] = 127, - [0][1][RTW89_ETSI][115] = 127, - [0][1][RTW89_FCC][117] = 127, - [0][1][RTW89_ETSI][117] = 127, - [0][1][RTW89_FCC][119] = 127, - [0][1][RTW89_ETSI][119] = 127, - [1][0][RTW89_FCC][0] = -4, - [1][0][RTW89_ETSI][0] = 46, - [1][0][RTW89_FCC][2] = -4, - [1][0][RTW89_ETSI][2] = 46, - [1][0][RTW89_FCC][4] = -4, - [1][0][RTW89_ETSI][4] = 46, - [1][0][RTW89_FCC][6] = -4, - [1][0][RTW89_ETSI][6] = 46, - [1][0][RTW89_FCC][8] = -4, - [1][0][RTW89_ETSI][8] = 46, - [1][0][RTW89_FCC][10] = -4, - [1][0][RTW89_ETSI][10] = 46, - [1][0][RTW89_FCC][12] = -4, - [1][0][RTW89_ETSI][12] = 46, - [1][0][RTW89_FCC][14] = -4, - [1][0][RTW89_ETSI][14] = 46, - [1][0][RTW89_FCC][15] = -4, - [1][0][RTW89_ETSI][15] = 46, - [1][0][RTW89_FCC][17] = -4, - [1][0][RTW89_ETSI][17] = 46, - [1][0][RTW89_FCC][19] = -4, - [1][0][RTW89_ETSI][19] = 46, - [1][0][RTW89_FCC][21] = -4, - [1][0][RTW89_ETSI][21] = 46, - [1][0][RTW89_FCC][23] = -4, - [1][0][RTW89_ETSI][23] = 46, - [1][0][RTW89_FCC][25] = -4, - [1][0][RTW89_ETSI][25] = 46, - [1][0][RTW89_FCC][27] = -4, - [1][0][RTW89_ETSI][27] = 46, - [1][0][RTW89_FCC][29] = -4, - [1][0][RTW89_ETSI][29] = 46, - [1][0][RTW89_FCC][30] = -4, - [1][0][RTW89_ETSI][30] = 46, - [1][0][RTW89_FCC][32] = -4, - [1][0][RTW89_ETSI][32] = 46, - [1][0][RTW89_FCC][34] = -4, - [1][0][RTW89_ETSI][34] = 46, - [1][0][RTW89_FCC][36] = -4, - [1][0][RTW89_ETSI][36] = 46, - [1][0][RTW89_FCC][38] = -4, - [1][0][RTW89_ETSI][38] = 46, - [1][0][RTW89_FCC][40] = -4, - [1][0][RTW89_ETSI][40] = 46, - [1][0][RTW89_FCC][42] = -4, - [1][0][RTW89_ETSI][42] = 46, - [1][0][RTW89_FCC][44] = -4, - [1][0][RTW89_ETSI][44] = 46, - [1][0][RTW89_FCC][45] = -4, - [1][0][RTW89_ETSI][45] = 127, - [1][0][RTW89_FCC][47] = -4, - [1][0][RTW89_ETSI][47] = 127, - [1][0][RTW89_FCC][49] = -4, - [1][0][RTW89_ETSI][49] = 127, - [1][0][RTW89_FCC][51] = -4, - [1][0][RTW89_ETSI][51] = 127, - [1][0][RTW89_FCC][53] = -4, - [1][0][RTW89_ETSI][53] = 127, - [1][0][RTW89_FCC][55] = -4, - [1][0][RTW89_ETSI][55] = 127, - [1][0][RTW89_FCC][57] = -4, - [1][0][RTW89_ETSI][57] = 127, - [1][0][RTW89_FCC][59] = -4, - [1][0][RTW89_ETSI][59] = 127, - [1][0][RTW89_FCC][60] = -4, - [1][0][RTW89_ETSI][60] = 127, - [1][0][RTW89_FCC][62] = -4, - [1][0][RTW89_ETSI][62] = 127, - [1][0][RTW89_FCC][64] = -4, - [1][0][RTW89_ETSI][64] = 127, - [1][0][RTW89_FCC][66] = -4, - [1][0][RTW89_ETSI][66] = 127, - [1][0][RTW89_FCC][68] = -4, - [1][0][RTW89_ETSI][68] = 127, - [1][0][RTW89_FCC][70] = -4, - [1][0][RTW89_ETSI][70] = 127, - [1][0][RTW89_FCC][72] = -4, - [1][0][RTW89_ETSI][72] = 127, - [1][0][RTW89_FCC][74] = -4, - [1][0][RTW89_ETSI][74] = 127, - [1][0][RTW89_FCC][75] = -4, - [1][0][RTW89_ETSI][75] = 127, - [1][0][RTW89_FCC][77] = -4, - [1][0][RTW89_ETSI][77] = 127, - [1][0][RTW89_FCC][79] = -4, - [1][0][RTW89_ETSI][79] = 127, - [1][0][RTW89_FCC][81] = -4, - [1][0][RTW89_ETSI][81] = 127, - [1][0][RTW89_FCC][83] = -4, - [1][0][RTW89_ETSI][83] = 127, - [1][0][RTW89_FCC][85] = -4, - [1][0][RTW89_ETSI][85] = 127, - [1][0][RTW89_FCC][87] = -4, - [1][0][RTW89_ETSI][87] = 127, - [1][0][RTW89_FCC][89] = -4, - [1][0][RTW89_ETSI][89] = 127, - [1][0][RTW89_FCC][90] = -4, - [1][0][RTW89_ETSI][90] = 127, - [1][0][RTW89_FCC][92] = -4, - [1][0][RTW89_ETSI][92] = 127, - [1][0][RTW89_FCC][94] = -4, - [1][0][RTW89_ETSI][94] = 127, - [1][0][RTW89_FCC][96] = -4, - [1][0][RTW89_ETSI][96] = 127, - [1][0][RTW89_FCC][98] = -4, - [1][0][RTW89_ETSI][98] = 127, - [1][0][RTW89_FCC][100] = -4, - [1][0][RTW89_ETSI][100] = 127, - [1][0][RTW89_FCC][102] = -4, - [1][0][RTW89_ETSI][102] = 127, - [1][0][RTW89_FCC][104] = -4, - [1][0][RTW89_ETSI][104] = 127, - [1][0][RTW89_FCC][105] = -4, - [1][0][RTW89_ETSI][105] = 127, - [1][0][RTW89_FCC][107] = 0, - [1][0][RTW89_ETSI][107] = 127, - [1][0][RTW89_FCC][109] = 2, - [1][0][RTW89_ETSI][109] = 127, - [1][0][RTW89_FCC][111] = 127, - [1][0][RTW89_ETSI][111] = 127, - [1][0][RTW89_FCC][113] = 127, - [1][0][RTW89_ETSI][113] = 127, - [1][0][RTW89_FCC][115] = 127, - [1][0][RTW89_ETSI][115] = 127, - [1][0][RTW89_FCC][117] = 127, - [1][0][RTW89_ETSI][117] = 127, - [1][0][RTW89_FCC][119] = 127, - [1][0][RTW89_ETSI][119] = 127, - [1][1][RTW89_FCC][0] = -26, - [1][1][RTW89_ETSI][0] = 32, - [1][1][RTW89_FCC][2] = -28, - [1][1][RTW89_ETSI][2] = 32, - [1][1][RTW89_FCC][4] = -28, - [1][1][RTW89_ETSI][4] = 32, - [1][1][RTW89_FCC][6] = -28, - [1][1][RTW89_ETSI][6] = 32, - [1][1][RTW89_FCC][8] = -28, - [1][1][RTW89_ETSI][8] = 32, - [1][1][RTW89_FCC][10] = -28, - [1][1][RTW89_ETSI][10] = 32, - [1][1][RTW89_FCC][12] = -28, - [1][1][RTW89_ETSI][12] = 32, - [1][1][RTW89_FCC][14] = -28, - [1][1][RTW89_ETSI][14] = 32, - [1][1][RTW89_FCC][15] = -28, - [1][1][RTW89_ETSI][15] = 32, - [1][1][RTW89_FCC][17] = -28, - [1][1][RTW89_ETSI][17] = 32, - [1][1][RTW89_FCC][19] = -28, - [1][1][RTW89_ETSI][19] = 32, - [1][1][RTW89_FCC][21] = -28, - [1][1][RTW89_ETSI][21] = 32, - [1][1][RTW89_FCC][23] = -28, - [1][1][RTW89_ETSI][23] = 32, - [1][1][RTW89_FCC][25] = -28, - [1][1][RTW89_ETSI][25] = 32, - [1][1][RTW89_FCC][27] = -28, - [1][1][RTW89_ETSI][27] = 32, - [1][1][RTW89_FCC][29] = -28, - [1][1][RTW89_ETSI][29] = 32, - [1][1][RTW89_FCC][30] = -28, - [1][1][RTW89_ETSI][30] = 32, - [1][1][RTW89_FCC][32] = -28, - [1][1][RTW89_ETSI][32] = 32, - [1][1][RTW89_FCC][34] = -28, - [1][1][RTW89_ETSI][34] = 32, - [1][1][RTW89_FCC][36] = -28, - [1][1][RTW89_ETSI][36] = 32, - [1][1][RTW89_FCC][38] = -28, - [1][1][RTW89_ETSI][38] = 32, - [1][1][RTW89_FCC][40] = -28, - [1][1][RTW89_ETSI][40] = 32, - [1][1][RTW89_FCC][42] = -28, - [1][1][RTW89_ETSI][42] = 32, - [1][1][RTW89_FCC][44] = -28, - [1][1][RTW89_ETSI][44] = 34, - [1][1][RTW89_FCC][45] = -26, - [1][1][RTW89_ETSI][45] = 127, - [1][1][RTW89_FCC][47] = -28, - [1][1][RTW89_ETSI][47] = 127, - [1][1][RTW89_FCC][49] = -28, - [1][1][RTW89_ETSI][49] = 127, - [1][1][RTW89_FCC][51] = -28, - [1][1][RTW89_ETSI][51] = 127, - [1][1][RTW89_FCC][53] = -26, - [1][1][RTW89_ETSI][53] = 127, - [1][1][RTW89_FCC][55] = -28, - [1][1][RTW89_ETSI][55] = 127, - [1][1][RTW89_FCC][57] = -28, - [1][1][RTW89_ETSI][57] = 127, - [1][1][RTW89_FCC][59] = -28, - [1][1][RTW89_ETSI][59] = 127, - [1][1][RTW89_FCC][60] = -28, - [1][1][RTW89_ETSI][60] = 127, - [1][1][RTW89_FCC][62] = -28, - [1][1][RTW89_ETSI][62] = 127, - [1][1][RTW89_FCC][64] = -28, - [1][1][RTW89_ETSI][64] = 127, - [1][1][RTW89_FCC][66] = -28, - [1][1][RTW89_ETSI][66] = 127, - [1][1][RTW89_FCC][68] = -28, - [1][1][RTW89_ETSI][68] = 127, - [1][1][RTW89_FCC][70] = -26, - [1][1][RTW89_ETSI][70] = 127, - [1][1][RTW89_FCC][72] = -28, - [1][1][RTW89_ETSI][72] = 127, - [1][1][RTW89_FCC][74] = -28, - [1][1][RTW89_ETSI][74] = 127, - [1][1][RTW89_FCC][75] = -28, - [1][1][RTW89_ETSI][75] = 127, - [1][1][RTW89_FCC][77] = -28, - [1][1][RTW89_ETSI][77] = 127, - [1][1][RTW89_FCC][79] = -28, - [1][1][RTW89_ETSI][79] = 127, - [1][1][RTW89_FCC][81] = -28, - [1][1][RTW89_ETSI][81] = 127, - [1][1][RTW89_FCC][83] = -28, - [1][1][RTW89_ETSI][83] = 127, - [1][1][RTW89_FCC][85] = -28, - [1][1][RTW89_ETSI][85] = 127, - [1][1][RTW89_FCC][87] = -28, - [1][1][RTW89_ETSI][87] = 127, - [1][1][RTW89_FCC][89] = -26, - [1][1][RTW89_ETSI][89] = 127, - [1][1][RTW89_FCC][90] = -26, - [1][1][RTW89_ETSI][90] = 127, - [1][1][RTW89_FCC][92] = -26, - [1][1][RTW89_ETSI][92] = 127, - [1][1][RTW89_FCC][94] = -26, - [1][1][RTW89_ETSI][94] = 127, - [1][1][RTW89_FCC][96] = -26, - [1][1][RTW89_ETSI][96] = 127, - [1][1][RTW89_FCC][98] = -26, - [1][1][RTW89_ETSI][98] = 127, - [1][1][RTW89_FCC][100] = -26, - [1][1][RTW89_ETSI][100] = 127, - [1][1][RTW89_FCC][102] = -26, - [1][1][RTW89_ETSI][102] = 127, - [1][1][RTW89_FCC][104] = -26, - [1][1][RTW89_ETSI][104] = 127, - [1][1][RTW89_FCC][105] = -26, - [1][1][RTW89_ETSI][105] = 127, - [1][1][RTW89_FCC][107] = -22, - [1][1][RTW89_ETSI][107] = 127, - [1][1][RTW89_FCC][109] = -22, - [1][1][RTW89_ETSI][109] = 127, - [1][1][RTW89_FCC][111] = 127, - [1][1][RTW89_ETSI][111] = 127, - [1][1][RTW89_FCC][113] = 127, - [1][1][RTW89_ETSI][113] = 127, - [1][1][RTW89_FCC][115] = 127, - [1][1][RTW89_ETSI][115] = 127, - [1][1][RTW89_FCC][117] = 127, - [1][1][RTW89_ETSI][117] = 127, - [1][1][RTW89_FCC][119] = 127, - [1][1][RTW89_ETSI][119] = 127, - [2][0][RTW89_FCC][0] = 8, - [2][0][RTW89_ETSI][0] = 56, - [2][0][RTW89_FCC][2] = 8, - [2][0][RTW89_ETSI][2] = 56, - [2][0][RTW89_FCC][4] = 8, - [2][0][RTW89_ETSI][4] = 56, - [2][0][RTW89_FCC][6] = 8, - [2][0][RTW89_ETSI][6] = 56, - [2][0][RTW89_FCC][8] = 8, - [2][0][RTW89_ETSI][8] = 56, - [2][0][RTW89_FCC][10] = 8, - [2][0][RTW89_ETSI][10] = 56, - [2][0][RTW89_FCC][12] = 8, - [2][0][RTW89_ETSI][12] = 56, - [2][0][RTW89_FCC][14] = 8, - [2][0][RTW89_ETSI][14] = 56, - [2][0][RTW89_FCC][15] = 8, - [2][0][RTW89_ETSI][15] = 56, - [2][0][RTW89_FCC][17] = 8, - [2][0][RTW89_ETSI][17] = 56, - [2][0][RTW89_FCC][19] = 8, - [2][0][RTW89_ETSI][19] = 56, - [2][0][RTW89_FCC][21] = 8, - [2][0][RTW89_ETSI][21] = 56, - [2][0][RTW89_FCC][23] = 8, - [2][0][RTW89_ETSI][23] = 56, - [2][0][RTW89_FCC][25] = 8, - [2][0][RTW89_ETSI][25] = 56, - [2][0][RTW89_FCC][27] = 8, - [2][0][RTW89_ETSI][27] = 56, - [2][0][RTW89_FCC][29] = 8, - [2][0][RTW89_ETSI][29] = 56, - [2][0][RTW89_FCC][30] = 8, - [2][0][RTW89_ETSI][30] = 56, - [2][0][RTW89_FCC][32] = 8, - [2][0][RTW89_ETSI][32] = 56, - [2][0][RTW89_FCC][34] = 8, - [2][0][RTW89_ETSI][34] = 56, - [2][0][RTW89_FCC][36] = 8, - [2][0][RTW89_ETSI][36] = 56, - [2][0][RTW89_FCC][38] = 8, - [2][0][RTW89_ETSI][38] = 56, - [2][0][RTW89_FCC][40] = 8, - [2][0][RTW89_ETSI][40] = 56, - [2][0][RTW89_FCC][42] = 8, - [2][0][RTW89_ETSI][42] = 56, - [2][0][RTW89_FCC][44] = 8, - [2][0][RTW89_ETSI][44] = 56, - [2][0][RTW89_FCC][45] = 8, - [2][0][RTW89_ETSI][45] = 127, - [2][0][RTW89_FCC][47] = 8, - [2][0][RTW89_ETSI][47] = 127, - [2][0][RTW89_FCC][49] = 8, - [2][0][RTW89_ETSI][49] = 127, - [2][0][RTW89_FCC][51] = 8, - [2][0][RTW89_ETSI][51] = 127, - [2][0][RTW89_FCC][53] = 8, - [2][0][RTW89_ETSI][53] = 127, - [2][0][RTW89_FCC][55] = 8, - [2][0][RTW89_ETSI][55] = 127, - [2][0][RTW89_FCC][57] = 8, - [2][0][RTW89_ETSI][57] = 127, - [2][0][RTW89_FCC][59] = 8, - [2][0][RTW89_ETSI][59] = 127, - [2][0][RTW89_FCC][60] = 8, - [2][0][RTW89_ETSI][60] = 127, - [2][0][RTW89_FCC][62] = 8, - [2][0][RTW89_ETSI][62] = 127, - [2][0][RTW89_FCC][64] = 8, - [2][0][RTW89_ETSI][64] = 127, - [2][0][RTW89_FCC][66] = 8, - [2][0][RTW89_ETSI][66] = 127, - [2][0][RTW89_FCC][68] = 8, - [2][0][RTW89_ETSI][68] = 127, - [2][0][RTW89_FCC][70] = 8, - [2][0][RTW89_ETSI][70] = 127, - [2][0][RTW89_FCC][72] = 8, - [2][0][RTW89_ETSI][72] = 127, - [2][0][RTW89_FCC][74] = 8, - [2][0][RTW89_ETSI][74] = 127, - [2][0][RTW89_FCC][75] = 8, - [2][0][RTW89_ETSI][75] = 127, - [2][0][RTW89_FCC][77] = 8, - [2][0][RTW89_ETSI][77] = 127, - [2][0][RTW89_FCC][79] = 8, - [2][0][RTW89_ETSI][79] = 127, - [2][0][RTW89_FCC][81] = 8, - [2][0][RTW89_ETSI][81] = 127, - [2][0][RTW89_FCC][83] = 8, - [2][0][RTW89_ETSI][83] = 127, - [2][0][RTW89_FCC][85] = 8, - [2][0][RTW89_ETSI][85] = 127, - [2][0][RTW89_FCC][87] = 8, - [2][0][RTW89_ETSI][87] = 127, - [2][0][RTW89_FCC][89] = 8, - [2][0][RTW89_ETSI][89] = 127, - [2][0][RTW89_FCC][90] = 8, - [2][0][RTW89_ETSI][90] = 127, - [2][0][RTW89_FCC][92] = 8, - [2][0][RTW89_ETSI][92] = 127, - [2][0][RTW89_FCC][94] = 8, - [2][0][RTW89_ETSI][94] = 127, - [2][0][RTW89_FCC][96] = 8, - [2][0][RTW89_ETSI][96] = 127, - [2][0][RTW89_FCC][98] = 8, - [2][0][RTW89_ETSI][98] = 127, - [2][0][RTW89_FCC][100] = 8, - [2][0][RTW89_ETSI][100] = 127, - [2][0][RTW89_FCC][102] = 8, - [2][0][RTW89_ETSI][102] = 127, - [2][0][RTW89_FCC][104] = 8, - [2][0][RTW89_ETSI][104] = 127, - [2][0][RTW89_FCC][105] = 8, - [2][0][RTW89_ETSI][105] = 127, - [2][0][RTW89_FCC][107] = 10, - [2][0][RTW89_ETSI][107] = 127, - [2][0][RTW89_FCC][109] = 12, - [2][0][RTW89_ETSI][109] = 127, - [2][0][RTW89_FCC][111] = 127, - [2][0][RTW89_ETSI][111] = 127, - [2][0][RTW89_FCC][113] = 127, - [2][0][RTW89_ETSI][113] = 127, - [2][0][RTW89_FCC][115] = 127, - [2][0][RTW89_ETSI][115] = 127, - [2][0][RTW89_FCC][117] = 127, - [2][0][RTW89_ETSI][117] = 127, - [2][0][RTW89_FCC][119] = 127, - [2][0][RTW89_ETSI][119] = 127, - [2][1][RTW89_FCC][0] = -16, - [2][1][RTW89_ETSI][0] = 44, - [2][1][RTW89_FCC][2] = -16, - [2][1][RTW89_ETSI][2] = 44, - [2][1][RTW89_FCC][4] = -16, - [2][1][RTW89_ETSI][4] = 44, - [2][1][RTW89_FCC][6] = -16, - [2][1][RTW89_ETSI][6] = 44, - [2][1][RTW89_FCC][8] = -16, - [2][1][RTW89_ETSI][8] = 44, - [2][1][RTW89_FCC][10] = -16, - [2][1][RTW89_ETSI][10] = 44, - [2][1][RTW89_FCC][12] = -16, - [2][1][RTW89_ETSI][12] = 44, - [2][1][RTW89_FCC][14] = -16, - [2][1][RTW89_ETSI][14] = 44, - [2][1][RTW89_FCC][15] = -16, - [2][1][RTW89_ETSI][15] = 44, - [2][1][RTW89_FCC][17] = -16, - [2][1][RTW89_ETSI][17] = 44, - [2][1][RTW89_FCC][19] = -16, - [2][1][RTW89_ETSI][19] = 44, - [2][1][RTW89_FCC][21] = -16, - [2][1][RTW89_ETSI][21] = 44, - [2][1][RTW89_FCC][23] = -16, - [2][1][RTW89_ETSI][23] = 44, - [2][1][RTW89_FCC][25] = -16, - [2][1][RTW89_ETSI][25] = 44, - [2][1][RTW89_FCC][27] = -16, - [2][1][RTW89_ETSI][27] = 44, - [2][1][RTW89_FCC][29] = -16, - [2][1][RTW89_ETSI][29] = 44, - [2][1][RTW89_FCC][30] = -16, - [2][1][RTW89_ETSI][30] = 44, - [2][1][RTW89_FCC][32] = -16, - [2][1][RTW89_ETSI][32] = 44, - [2][1][RTW89_FCC][34] = -16, - [2][1][RTW89_ETSI][34] = 44, - [2][1][RTW89_FCC][36] = -16, - [2][1][RTW89_ETSI][36] = 44, - [2][1][RTW89_FCC][38] = -16, - [2][1][RTW89_ETSI][38] = 44, - [2][1][RTW89_FCC][40] = -16, - [2][1][RTW89_ETSI][40] = 44, - [2][1][RTW89_FCC][42] = -16, - [2][1][RTW89_ETSI][42] = 44, - [2][1][RTW89_FCC][44] = -16, - [2][1][RTW89_ETSI][44] = 44, - [2][1][RTW89_FCC][45] = -16, - [2][1][RTW89_ETSI][45] = 127, - [2][1][RTW89_FCC][47] = -16, - [2][1][RTW89_ETSI][47] = 127, - [2][1][RTW89_FCC][49] = -16, - [2][1][RTW89_ETSI][49] = 127, - [2][1][RTW89_FCC][51] = -16, - [2][1][RTW89_ETSI][51] = 127, - [2][1][RTW89_FCC][53] = -16, - [2][1][RTW89_ETSI][53] = 127, - [2][1][RTW89_FCC][55] = -16, - [2][1][RTW89_ETSI][55] = 127, - [2][1][RTW89_FCC][57] = -16, - [2][1][RTW89_ETSI][57] = 127, - [2][1][RTW89_FCC][59] = -16, - [2][1][RTW89_ETSI][59] = 127, - [2][1][RTW89_FCC][60] = -16, - [2][1][RTW89_ETSI][60] = 127, - [2][1][RTW89_FCC][62] = -16, - [2][1][RTW89_ETSI][62] = 127, - [2][1][RTW89_FCC][64] = -16, - [2][1][RTW89_ETSI][64] = 127, - [2][1][RTW89_FCC][66] = -16, - [2][1][RTW89_ETSI][66] = 127, - [2][1][RTW89_FCC][68] = -16, - [2][1][RTW89_ETSI][68] = 127, - [2][1][RTW89_FCC][70] = -16, - [2][1][RTW89_ETSI][70] = 127, - [2][1][RTW89_FCC][72] = -16, - [2][1][RTW89_ETSI][72] = 127, - [2][1][RTW89_FCC][74] = -16, - [2][1][RTW89_ETSI][74] = 127, - [2][1][RTW89_FCC][75] = -16, - [2][1][RTW89_ETSI][75] = 127, - [2][1][RTW89_FCC][77] = -16, - [2][1][RTW89_ETSI][77] = 127, - [2][1][RTW89_FCC][79] = -16, - [2][1][RTW89_ETSI][79] = 127, - [2][1][RTW89_FCC][81] = -16, - [2][1][RTW89_ETSI][81] = 127, - [2][1][RTW89_FCC][83] = -16, - [2][1][RTW89_ETSI][83] = 127, - [2][1][RTW89_FCC][85] = -18, - [2][1][RTW89_ETSI][85] = 127, - [2][1][RTW89_FCC][87] = -16, - [2][1][RTW89_ETSI][87] = 127, - [2][1][RTW89_FCC][89] = -16, - [2][1][RTW89_ETSI][89] = 127, - [2][1][RTW89_FCC][90] = -16, - [2][1][RTW89_ETSI][90] = 127, - [2][1][RTW89_FCC][92] = -16, - [2][1][RTW89_ETSI][92] = 127, - [2][1][RTW89_FCC][94] = -16, - [2][1][RTW89_ETSI][94] = 127, - [2][1][RTW89_FCC][96] = -16, - [2][1][RTW89_ETSI][96] = 127, - [2][1][RTW89_FCC][98] = -16, - [2][1][RTW89_ETSI][98] = 127, - [2][1][RTW89_FCC][100] = -16, - [2][1][RTW89_ETSI][100] = 127, - [2][1][RTW89_FCC][102] = -16, - [2][1][RTW89_ETSI][102] = 127, - [2][1][RTW89_FCC][104] = -16, - [2][1][RTW89_ETSI][104] = 127, - [2][1][RTW89_FCC][105] = -16, - [2][1][RTW89_ETSI][105] = 127, - [2][1][RTW89_FCC][107] = -12, - [2][1][RTW89_ETSI][107] = 127, - [2][1][RTW89_FCC][109] = -10, - [2][1][RTW89_ETSI][109] = 127, - [2][1][RTW89_FCC][111] = 127, - [2][1][RTW89_ETSI][111] = 127, - [2][1][RTW89_FCC][113] = 127, - [2][1][RTW89_ETSI][113] = 127, - [2][1][RTW89_FCC][115] = 127, - [2][1][RTW89_ETSI][115] = 127, - [2][1][RTW89_FCC][117] = 127, - [2][1][RTW89_ETSI][117] = 127, - [2][1][RTW89_FCC][119] = 127, - [2][1][RTW89_ETSI][119] = 127, + [RTW89_REGD_NUM][NUM_OF_RTW89_REG_6GHZ_POWER] + [RTW89_6G_CH_NUM] = { + [0][0][RTW89_WW][0][0] = -16, + [0][0][RTW89_WW][1][0] = -16, + [0][0][RTW89_WW][2][0] = 44, + [0][0][RTW89_WW][0][2] = -18, + [0][0][RTW89_WW][1][2] = -18, + [0][0][RTW89_WW][2][2] = 44, + [0][0][RTW89_WW][0][4] = -18, + [0][0][RTW89_WW][1][4] = -18, + [0][0][RTW89_WW][2][4] = 44, + [0][0][RTW89_WW][0][6] = -18, + [0][0][RTW89_WW][1][6] = -18, + [0][0][RTW89_WW][2][6] = 44, + [0][0][RTW89_WW][0][8] = -18, + [0][0][RTW89_WW][1][8] = -18, + [0][0][RTW89_WW][2][8] = 44, + [0][0][RTW89_WW][0][10] = -18, + [0][0][RTW89_WW][1][10] = -18, + [0][0][RTW89_WW][2][10] = 44, + [0][0][RTW89_WW][0][12] = -18, + [0][0][RTW89_WW][1][12] = -18, + [0][0][RTW89_WW][2][12] = 44, + [0][0][RTW89_WW][0][14] = -18, + [0][0][RTW89_WW][1][14] = -18, + [0][0][RTW89_WW][2][14] = 44, + [0][0][RTW89_WW][0][15] = -18, + [0][0][RTW89_WW][1][15] = -18, + [0][0][RTW89_WW][2][15] = 44, + [0][0][RTW89_WW][0][17] = -18, + [0][0][RTW89_WW][1][17] = -18, + [0][0][RTW89_WW][2][17] = 44, + [0][0][RTW89_WW][0][19] = -18, + [0][0][RTW89_WW][1][19] = -18, + [0][0][RTW89_WW][2][19] = 44, + [0][0][RTW89_WW][0][21] = -18, + [0][0][RTW89_WW][1][21] = -18, + [0][0][RTW89_WW][2][21] = 44, + [0][0][RTW89_WW][0][23] = -18, + [0][0][RTW89_WW][1][23] = -18, + [0][0][RTW89_WW][2][23] = 54, + [0][0][RTW89_WW][0][25] = -18, + [0][0][RTW89_WW][1][25] = -18, + [0][0][RTW89_WW][2][25] = 54, + [0][0][RTW89_WW][0][27] = -18, + [0][0][RTW89_WW][1][27] = -18, + [0][0][RTW89_WW][2][27] = 54, + [0][0][RTW89_WW][0][29] = -18, + [0][0][RTW89_WW][1][29] = -18, + [0][0][RTW89_WW][2][29] = 54, + [0][0][RTW89_WW][0][30] = -18, + [0][0][RTW89_WW][1][30] = -18, + [0][0][RTW89_WW][2][30] = 54, + [0][0][RTW89_WW][0][32] = -18, + [0][0][RTW89_WW][1][32] = -18, + [0][0][RTW89_WW][2][32] = 54, + [0][0][RTW89_WW][0][34] = -18, + [0][0][RTW89_WW][1][34] = -18, + [0][0][RTW89_WW][2][34] = 54, + [0][0][RTW89_WW][0][36] = -18, + [0][0][RTW89_WW][1][36] = -18, + [0][0][RTW89_WW][2][36] = 54, + [0][0][RTW89_WW][0][38] = -18, + [0][0][RTW89_WW][1][38] = -18, + [0][0][RTW89_WW][2][38] = 54, + [0][0][RTW89_WW][0][40] = -18, + [0][0][RTW89_WW][1][40] = -18, + [0][0][RTW89_WW][2][40] = 54, + [0][0][RTW89_WW][0][42] = -18, + [0][0][RTW89_WW][1][42] = -18, + [0][0][RTW89_WW][2][42] = 54, + [0][0][RTW89_WW][0][44] = -16, + [0][0][RTW89_WW][1][44] = -16, + [0][0][RTW89_WW][2][44] = 56, + [0][0][RTW89_WW][0][45] = -16, + [0][0][RTW89_WW][1][45] = -16, + [0][0][RTW89_WW][2][45] = 0, + [0][0][RTW89_WW][0][47] = -18, + [0][0][RTW89_WW][1][47] = -18, + [0][0][RTW89_WW][2][47] = 0, + [0][0][RTW89_WW][0][49] = -18, + [0][0][RTW89_WW][1][49] = -18, + [0][0][RTW89_WW][2][49] = 0, + [0][0][RTW89_WW][0][51] = -18, + [0][0][RTW89_WW][1][51] = -18, + [0][0][RTW89_WW][2][51] = 0, + [0][0][RTW89_WW][0][53] = -16, + [0][0][RTW89_WW][1][53] = -16, + [0][0][RTW89_WW][2][53] = 0, + [0][0][RTW89_WW][0][55] = -18, + [0][0][RTW89_WW][1][55] = -18, + [0][0][RTW89_WW][2][55] = 56, + [0][0][RTW89_WW][0][57] = -18, + [0][0][RTW89_WW][1][57] = -18, + [0][0][RTW89_WW][2][57] = 56, + [0][0][RTW89_WW][0][59] = -18, + [0][0][RTW89_WW][1][59] = -18, + [0][0][RTW89_WW][2][59] = 56, + [0][0][RTW89_WW][0][60] = -18, + [0][0][RTW89_WW][1][60] = -18, + [0][0][RTW89_WW][2][60] = 56, + [0][0][RTW89_WW][0][62] = -18, + [0][0][RTW89_WW][1][62] = -18, + [0][0][RTW89_WW][2][62] = 56, + [0][0][RTW89_WW][0][64] = -18, + [0][0][RTW89_WW][1][64] = -18, + [0][0][RTW89_WW][2][64] = 56, + [0][0][RTW89_WW][0][66] = -18, + [0][0][RTW89_WW][1][66] = -18, + [0][0][RTW89_WW][2][66] = 56, + [0][0][RTW89_WW][0][68] = -18, + [0][0][RTW89_WW][1][68] = -18, + [0][0][RTW89_WW][2][68] = 56, + [0][0][RTW89_WW][0][70] = -16, + [0][0][RTW89_WW][1][70] = -16, + [0][0][RTW89_WW][2][70] = 56, + [0][0][RTW89_WW][0][72] = -18, + [0][0][RTW89_WW][1][72] = -18, + [0][0][RTW89_WW][2][72] = 56, + [0][0][RTW89_WW][0][74] = -18, + [0][0][RTW89_WW][1][74] = -18, + [0][0][RTW89_WW][2][74] = 56, + [0][0][RTW89_WW][0][75] = -18, + [0][0][RTW89_WW][1][75] = -18, + [0][0][RTW89_WW][2][75] = 56, + [0][0][RTW89_WW][0][77] = -18, + [0][0][RTW89_WW][1][77] = -18, + [0][0][RTW89_WW][2][77] = 56, + [0][0][RTW89_WW][0][79] = -18, + [0][0][RTW89_WW][1][79] = -18, + [0][0][RTW89_WW][2][79] = 56, + [0][0][RTW89_WW][0][81] = -18, + [0][0][RTW89_WW][1][81] = -18, + [0][0][RTW89_WW][2][81] = 56, + [0][0][RTW89_WW][0][83] = -18, + [0][0][RTW89_WW][1][83] = -18, + [0][0][RTW89_WW][2][83] = 56, + [0][0][RTW89_WW][0][85] = -18, + [0][0][RTW89_WW][1][85] = -18, + [0][0][RTW89_WW][2][85] = 56, + [0][0][RTW89_WW][0][87] = -16, + [0][0][RTW89_WW][1][87] = -16, + [0][0][RTW89_WW][2][87] = 0, + [0][0][RTW89_WW][0][89] = -16, + [0][0][RTW89_WW][1][89] = -16, + [0][0][RTW89_WW][2][89] = 0, + [0][0][RTW89_WW][0][90] = -16, + [0][0][RTW89_WW][1][90] = -16, + [0][0][RTW89_WW][2][90] = 0, + [0][0][RTW89_WW][0][92] = -16, + [0][0][RTW89_WW][1][92] = -16, + [0][0][RTW89_WW][2][92] = 0, + [0][0][RTW89_WW][0][94] = -16, + [0][0][RTW89_WW][1][94] = -16, + [0][0][RTW89_WW][2][94] = 0, + [0][0][RTW89_WW][0][96] = -16, + [0][0][RTW89_WW][1][96] = -16, + [0][0][RTW89_WW][2][96] = 0, + [0][0][RTW89_WW][0][98] = -16, + [0][0][RTW89_WW][1][98] = -16, + [0][0][RTW89_WW][2][98] = 0, + [0][0][RTW89_WW][0][100] = -16, + [0][0][RTW89_WW][1][100] = -16, + [0][0][RTW89_WW][2][100] = 0, + [0][0][RTW89_WW][0][102] = -16, + [0][0][RTW89_WW][1][102] = -16, + [0][0][RTW89_WW][2][102] = 0, + [0][0][RTW89_WW][0][104] = -16, + [0][0][RTW89_WW][1][104] = -16, + [0][0][RTW89_WW][2][104] = 0, + [0][0][RTW89_WW][0][105] = -16, + [0][0][RTW89_WW][1][105] = -16, + [0][0][RTW89_WW][2][105] = 0, + [0][0][RTW89_WW][0][107] = -12, + [0][0][RTW89_WW][1][107] = -12, + [0][0][RTW89_WW][2][107] = 0, + [0][0][RTW89_WW][0][109] = -12, + [0][0][RTW89_WW][1][109] = -12, + [0][0][RTW89_WW][2][109] = 0, + [0][0][RTW89_WW][0][111] = 0, + [0][0][RTW89_WW][1][111] = 0, + [0][0][RTW89_WW][2][111] = 0, + [0][0][RTW89_WW][0][113] = 0, + [0][0][RTW89_WW][1][113] = 0, + [0][0][RTW89_WW][2][113] = 0, + [0][0][RTW89_WW][0][115] = 0, + [0][0][RTW89_WW][1][115] = 0, + [0][0][RTW89_WW][2][115] = 0, + [0][0][RTW89_WW][0][117] = 0, + [0][0][RTW89_WW][1][117] = 0, + [0][0][RTW89_WW][2][117] = 0, + [0][0][RTW89_WW][0][119] = 0, + [0][0][RTW89_WW][1][119] = 0, + [0][0][RTW89_WW][2][119] = 0, + [0][1][RTW89_WW][0][0] = -40, + [0][1][RTW89_WW][1][0] = -40, + [0][1][RTW89_WW][2][0] = 32, + [0][1][RTW89_WW][0][2] = -40, + [0][1][RTW89_WW][1][2] = -40, + [0][1][RTW89_WW][2][2] = 32, + [0][1][RTW89_WW][0][4] = -40, + [0][1][RTW89_WW][1][4] = -40, + [0][1][RTW89_WW][2][4] = 32, + [0][1][RTW89_WW][0][6] = -40, + [0][1][RTW89_WW][1][6] = -40, + [0][1][RTW89_WW][2][6] = 32, + [0][1][RTW89_WW][0][8] = -40, + [0][1][RTW89_WW][1][8] = -40, + [0][1][RTW89_WW][2][8] = 32, + [0][1][RTW89_WW][0][10] = -40, + [0][1][RTW89_WW][1][10] = -40, + [0][1][RTW89_WW][2][10] = 32, + [0][1][RTW89_WW][0][12] = -40, + [0][1][RTW89_WW][1][12] = -40, + [0][1][RTW89_WW][2][12] = 32, + [0][1][RTW89_WW][0][14] = -40, + [0][1][RTW89_WW][1][14] = -40, + [0][1][RTW89_WW][2][14] = 32, + [0][1][RTW89_WW][0][15] = -40, + [0][1][RTW89_WW][1][15] = -40, + [0][1][RTW89_WW][2][15] = 32, + [0][1][RTW89_WW][0][17] = -40, + [0][1][RTW89_WW][1][17] = -40, + [0][1][RTW89_WW][2][17] = 32, + [0][1][RTW89_WW][0][19] = -40, + [0][1][RTW89_WW][1][19] = -40, + [0][1][RTW89_WW][2][19] = 32, + [0][1][RTW89_WW][0][21] = -40, + [0][1][RTW89_WW][1][21] = -40, + [0][1][RTW89_WW][2][21] = 32, + [0][1][RTW89_WW][0][23] = -40, + [0][1][RTW89_WW][1][23] = -40, + [0][1][RTW89_WW][2][23] = 32, + [0][1][RTW89_WW][0][25] = -40, + [0][1][RTW89_WW][1][25] = -40, + [0][1][RTW89_WW][2][25] = 32, + [0][1][RTW89_WW][0][27] = -40, + [0][1][RTW89_WW][1][27] = -40, + [0][1][RTW89_WW][2][27] = 32, + [0][1][RTW89_WW][0][29] = -40, + [0][1][RTW89_WW][1][29] = -40, + [0][1][RTW89_WW][2][29] = 32, + [0][1][RTW89_WW][0][30] = -40, + [0][1][RTW89_WW][1][30] = -40, + [0][1][RTW89_WW][2][30] = 32, + [0][1][RTW89_WW][0][32] = -40, + [0][1][RTW89_WW][1][32] = -40, + [0][1][RTW89_WW][2][32] = 32, + [0][1][RTW89_WW][0][34] = -40, + [0][1][RTW89_WW][1][34] = -40, + [0][1][RTW89_WW][2][34] = 32, + [0][1][RTW89_WW][0][36] = -40, + [0][1][RTW89_WW][1][36] = -40, + [0][1][RTW89_WW][2][36] = 32, + [0][1][RTW89_WW][0][38] = -40, + [0][1][RTW89_WW][1][38] = -40, + [0][1][RTW89_WW][2][38] = 32, + [0][1][RTW89_WW][0][40] = -40, + [0][1][RTW89_WW][1][40] = -40, + [0][1][RTW89_WW][2][40] = 32, + [0][1][RTW89_WW][0][42] = -40, + [0][1][RTW89_WW][1][42] = -40, + [0][1][RTW89_WW][2][42] = 32, + [0][1][RTW89_WW][0][44] = -40, + [0][1][RTW89_WW][1][44] = -40, + [0][1][RTW89_WW][2][44] = 32, + [0][1][RTW89_WW][0][45] = -40, + [0][1][RTW89_WW][1][45] = -40, + [0][1][RTW89_WW][2][45] = 0, + [0][1][RTW89_WW][0][47] = -40, + [0][1][RTW89_WW][1][47] = -40, + [0][1][RTW89_WW][2][47] = 0, + [0][1][RTW89_WW][0][49] = -40, + [0][1][RTW89_WW][1][49] = -40, + [0][1][RTW89_WW][2][49] = 0, + [0][1][RTW89_WW][0][51] = -40, + [0][1][RTW89_WW][1][51] = -40, + [0][1][RTW89_WW][2][51] = 0, + [0][1][RTW89_WW][0][53] = -40, + [0][1][RTW89_WW][1][53] = -40, + [0][1][RTW89_WW][2][53] = 0, + [0][1][RTW89_WW][0][55] = -40, + [0][1][RTW89_WW][1][55] = -40, + [0][1][RTW89_WW][2][55] = 30, + [0][1][RTW89_WW][0][57] = -40, + [0][1][RTW89_WW][1][57] = -40, + [0][1][RTW89_WW][2][57] = 30, + [0][1][RTW89_WW][0][59] = -40, + [0][1][RTW89_WW][1][59] = -40, + [0][1][RTW89_WW][2][59] = 30, + [0][1][RTW89_WW][0][60] = -40, + [0][1][RTW89_WW][1][60] = -40, + [0][1][RTW89_WW][2][60] = 30, + [0][1][RTW89_WW][0][62] = -40, + [0][1][RTW89_WW][1][62] = -40, + [0][1][RTW89_WW][2][62] = 30, + [0][1][RTW89_WW][0][64] = -40, + [0][1][RTW89_WW][1][64] = -40, + [0][1][RTW89_WW][2][64] = 30, + [0][1][RTW89_WW][0][66] = -40, + [0][1][RTW89_WW][1][66] = -40, + [0][1][RTW89_WW][2][66] = 30, + [0][1][RTW89_WW][0][68] = -40, + [0][1][RTW89_WW][1][68] = -40, + [0][1][RTW89_WW][2][68] = 30, + [0][1][RTW89_WW][0][70] = -38, + [0][1][RTW89_WW][1][70] = -38, + [0][1][RTW89_WW][2][70] = 30, + [0][1][RTW89_WW][0][72] = -38, + [0][1][RTW89_WW][1][72] = -38, + [0][1][RTW89_WW][2][72] = 30, + [0][1][RTW89_WW][0][74] = -38, + [0][1][RTW89_WW][1][74] = -38, + [0][1][RTW89_WW][2][74] = 30, + [0][1][RTW89_WW][0][75] = -38, + [0][1][RTW89_WW][1][75] = -38, + [0][1][RTW89_WW][2][75] = 30, + [0][1][RTW89_WW][0][77] = -38, + [0][1][RTW89_WW][1][77] = -38, + [0][1][RTW89_WW][2][77] = 30, + [0][1][RTW89_WW][0][79] = -38, + [0][1][RTW89_WW][1][79] = -38, + [0][1][RTW89_WW][2][79] = 30, + [0][1][RTW89_WW][0][81] = -38, + [0][1][RTW89_WW][1][81] = -38, + [0][1][RTW89_WW][2][81] = 30, + [0][1][RTW89_WW][0][83] = -38, + [0][1][RTW89_WW][1][83] = -38, + [0][1][RTW89_WW][2][83] = 30, + [0][1][RTW89_WW][0][85] = -38, + [0][1][RTW89_WW][1][85] = -38, + [0][1][RTW89_WW][2][85] = 30, + [0][1][RTW89_WW][0][87] = -40, + [0][1][RTW89_WW][1][87] = -40, + [0][1][RTW89_WW][2][87] = 0, + [0][1][RTW89_WW][0][89] = -38, + [0][1][RTW89_WW][1][89] = -38, + [0][1][RTW89_WW][2][89] = 0, + [0][1][RTW89_WW][0][90] = -38, + [0][1][RTW89_WW][1][90] = -38, + [0][1][RTW89_WW][2][90] = 0, + [0][1][RTW89_WW][0][92] = -38, + [0][1][RTW89_WW][1][92] = -38, + [0][1][RTW89_WW][2][92] = 0, + [0][1][RTW89_WW][0][94] = -38, + [0][1][RTW89_WW][1][94] = -38, + [0][1][RTW89_WW][2][94] = 0, + [0][1][RTW89_WW][0][96] = -38, + [0][1][RTW89_WW][1][96] = -38, + [0][1][RTW89_WW][2][96] = 0, + [0][1][RTW89_WW][0][98] = -38, + [0][1][RTW89_WW][1][98] = -38, + [0][1][RTW89_WW][2][98] = 0, + [0][1][RTW89_WW][0][100] = -38, + [0][1][RTW89_WW][1][100] = -38, + [0][1][RTW89_WW][2][100] = 0, + [0][1][RTW89_WW][0][102] = -38, + [0][1][RTW89_WW][1][102] = -38, + [0][1][RTW89_WW][2][102] = 0, + [0][1][RTW89_WW][0][104] = -38, + [0][1][RTW89_WW][1][104] = -38, + [0][1][RTW89_WW][2][104] = 0, + [0][1][RTW89_WW][0][105] = -38, + [0][1][RTW89_WW][1][105] = -38, + [0][1][RTW89_WW][2][105] = 0, + [0][1][RTW89_WW][0][107] = -34, + [0][1][RTW89_WW][1][107] = -34, + [0][1][RTW89_WW][2][107] = 0, + [0][1][RTW89_WW][0][109] = -34, + [0][1][RTW89_WW][1][109] = -34, + [0][1][RTW89_WW][2][109] = 0, + [0][1][RTW89_WW][0][111] = 0, + [0][1][RTW89_WW][1][111] = 0, + [0][1][RTW89_WW][2][111] = 0, + [0][1][RTW89_WW][0][113] = 0, + [0][1][RTW89_WW][1][113] = 0, + [0][1][RTW89_WW][2][113] = 0, + [0][1][RTW89_WW][0][115] = 0, + [0][1][RTW89_WW][1][115] = 0, + [0][1][RTW89_WW][2][115] = 0, + [0][1][RTW89_WW][0][117] = 0, + [0][1][RTW89_WW][1][117] = 0, + [0][1][RTW89_WW][2][117] = 0, + [0][1][RTW89_WW][0][119] = 0, + [0][1][RTW89_WW][1][119] = 0, + [0][1][RTW89_WW][2][119] = 0, + [1][0][RTW89_WW][0][0] = -4, + [1][0][RTW89_WW][1][0] = -4, + [1][0][RTW89_WW][2][0] = 52, + [1][0][RTW89_WW][0][2] = -4, + [1][0][RTW89_WW][1][2] = -4, + [1][0][RTW89_WW][2][2] = 52, + [1][0][RTW89_WW][0][4] = -4, + [1][0][RTW89_WW][1][4] = -4, + [1][0][RTW89_WW][2][4] = 52, + [1][0][RTW89_WW][0][6] = -4, + [1][0][RTW89_WW][1][6] = -4, + [1][0][RTW89_WW][2][6] = 52, + [1][0][RTW89_WW][0][8] = -4, + [1][0][RTW89_WW][1][8] = -4, + [1][0][RTW89_WW][2][8] = 52, + [1][0][RTW89_WW][0][10] = -4, + [1][0][RTW89_WW][1][10] = -4, + [1][0][RTW89_WW][2][10] = 52, + [1][0][RTW89_WW][0][12] = -4, + [1][0][RTW89_WW][1][12] = -4, + [1][0][RTW89_WW][2][12] = 52, + [1][0][RTW89_WW][0][14] = -4, + [1][0][RTW89_WW][1][14] = -4, + [1][0][RTW89_WW][2][14] = 52, + [1][0][RTW89_WW][0][15] = -4, + [1][0][RTW89_WW][1][15] = -4, + [1][0][RTW89_WW][2][15] = 52, + [1][0][RTW89_WW][0][17] = -4, + [1][0][RTW89_WW][1][17] = -4, + [1][0][RTW89_WW][2][17] = 52, + [1][0][RTW89_WW][0][19] = -4, + [1][0][RTW89_WW][1][19] = -4, + [1][0][RTW89_WW][2][19] = 52, + [1][0][RTW89_WW][0][21] = -4, + [1][0][RTW89_WW][1][21] = -4, + [1][0][RTW89_WW][2][21] = 52, + [1][0][RTW89_WW][0][23] = -4, + [1][0][RTW89_WW][1][23] = -4, + [1][0][RTW89_WW][2][23] = 66, + [1][0][RTW89_WW][0][25] = -4, + [1][0][RTW89_WW][1][25] = -4, + [1][0][RTW89_WW][2][25] = 66, + [1][0][RTW89_WW][0][27] = -4, + [1][0][RTW89_WW][1][27] = -4, + [1][0][RTW89_WW][2][27] = 66, + [1][0][RTW89_WW][0][29] = -4, + [1][0][RTW89_WW][1][29] = -4, + [1][0][RTW89_WW][2][29] = 66, + [1][0][RTW89_WW][0][30] = -4, + [1][0][RTW89_WW][1][30] = -4, + [1][0][RTW89_WW][2][30] = 66, + [1][0][RTW89_WW][0][32] = -4, + [1][0][RTW89_WW][1][32] = -4, + [1][0][RTW89_WW][2][32] = 66, + [1][0][RTW89_WW][0][34] = -4, + [1][0][RTW89_WW][1][34] = -4, + [1][0][RTW89_WW][2][34] = 66, + [1][0][RTW89_WW][0][36] = -4, + [1][0][RTW89_WW][1][36] = -4, + [1][0][RTW89_WW][2][36] = 66, + [1][0][RTW89_WW][0][38] = -4, + [1][0][RTW89_WW][1][38] = -4, + [1][0][RTW89_WW][2][38] = 66, + [1][0][RTW89_WW][0][40] = -4, + [1][0][RTW89_WW][1][40] = -4, + [1][0][RTW89_WW][2][40] = 66, + [1][0][RTW89_WW][0][42] = -4, + [1][0][RTW89_WW][1][42] = -4, + [1][0][RTW89_WW][2][42] = 66, + [1][0][RTW89_WW][0][44] = -4, + [1][0][RTW89_WW][1][44] = -4, + [1][0][RTW89_WW][2][44] = 66, + [1][0][RTW89_WW][0][45] = -4, + [1][0][RTW89_WW][1][45] = -4, + [1][0][RTW89_WW][2][45] = 0, + [1][0][RTW89_WW][0][47] = -4, + [1][0][RTW89_WW][1][47] = -4, + [1][0][RTW89_WW][2][47] = 0, + [1][0][RTW89_WW][0][49] = -4, + [1][0][RTW89_WW][1][49] = -4, + [1][0][RTW89_WW][2][49] = 0, + [1][0][RTW89_WW][0][51] = -4, + [1][0][RTW89_WW][1][51] = -4, + [1][0][RTW89_WW][2][51] = 0, + [1][0][RTW89_WW][0][53] = -4, + [1][0][RTW89_WW][1][53] = -4, + [1][0][RTW89_WW][2][53] = 0, + [1][0][RTW89_WW][0][55] = -4, + [1][0][RTW89_WW][1][55] = -4, + [1][0][RTW89_WW][2][55] = 68, + [1][0][RTW89_WW][0][57] = -4, + [1][0][RTW89_WW][1][57] = -4, + [1][0][RTW89_WW][2][57] = 68, + [1][0][RTW89_WW][0][59] = -4, + [1][0][RTW89_WW][1][59] = -4, + [1][0][RTW89_WW][2][59] = 68, + [1][0][RTW89_WW][0][60] = -4, + [1][0][RTW89_WW][1][60] = -4, + [1][0][RTW89_WW][2][60] = 68, + [1][0][RTW89_WW][0][62] = -4, + [1][0][RTW89_WW][1][62] = -4, + [1][0][RTW89_WW][2][62] = 68, + [1][0][RTW89_WW][0][64] = -4, + [1][0][RTW89_WW][1][64] = -4, + [1][0][RTW89_WW][2][64] = 68, + [1][0][RTW89_WW][0][66] = -4, + [1][0][RTW89_WW][1][66] = -4, + [1][0][RTW89_WW][2][66] = 68, + [1][0][RTW89_WW][0][68] = -4, + [1][0][RTW89_WW][1][68] = -4, + [1][0][RTW89_WW][2][68] = 68, + [1][0][RTW89_WW][0][70] = -4, + [1][0][RTW89_WW][1][70] = -4, + [1][0][RTW89_WW][2][70] = 68, + [1][0][RTW89_WW][0][72] = -4, + [1][0][RTW89_WW][1][72] = -4, + [1][0][RTW89_WW][2][72] = 68, + [1][0][RTW89_WW][0][74] = -4, + [1][0][RTW89_WW][1][74] = -4, + [1][0][RTW89_WW][2][74] = 68, + [1][0][RTW89_WW][0][75] = -4, + [1][0][RTW89_WW][1][75] = -4, + [1][0][RTW89_WW][2][75] = 68, + [1][0][RTW89_WW][0][77] = -4, + [1][0][RTW89_WW][1][77] = -4, + [1][0][RTW89_WW][2][77] = 68, + [1][0][RTW89_WW][0][79] = -4, + [1][0][RTW89_WW][1][79] = -4, + [1][0][RTW89_WW][2][79] = 68, + [1][0][RTW89_WW][0][81] = -4, + [1][0][RTW89_WW][1][81] = -4, + [1][0][RTW89_WW][2][81] = 68, + [1][0][RTW89_WW][0][83] = -4, + [1][0][RTW89_WW][1][83] = -4, + [1][0][RTW89_WW][2][83] = 68, + [1][0][RTW89_WW][0][85] = -4, + [1][0][RTW89_WW][1][85] = -4, + [1][0][RTW89_WW][2][85] = 68, + [1][0][RTW89_WW][0][87] = -4, + [1][0][RTW89_WW][1][87] = -4, + [1][0][RTW89_WW][2][87] = 0, + [1][0][RTW89_WW][0][89] = -4, + [1][0][RTW89_WW][1][89] = -4, + [1][0][RTW89_WW][2][89] = 0, + [1][0][RTW89_WW][0][90] = -4, + [1][0][RTW89_WW][1][90] = -4, + [1][0][RTW89_WW][2][90] = 0, + [1][0][RTW89_WW][0][92] = -4, + [1][0][RTW89_WW][1][92] = -4, + [1][0][RTW89_WW][2][92] = 0, + [1][0][RTW89_WW][0][94] = -4, + [1][0][RTW89_WW][1][94] = -4, + [1][0][RTW89_WW][2][94] = 0, + [1][0][RTW89_WW][0][96] = -4, + [1][0][RTW89_WW][1][96] = -4, + [1][0][RTW89_WW][2][96] = 0, + [1][0][RTW89_WW][0][98] = -4, + [1][0][RTW89_WW][1][98] = -4, + [1][0][RTW89_WW][2][98] = 0, + [1][0][RTW89_WW][0][100] = -4, + [1][0][RTW89_WW][1][100] = -4, + [1][0][RTW89_WW][2][100] = 0, + [1][0][RTW89_WW][0][102] = -4, + [1][0][RTW89_WW][1][102] = -4, + [1][0][RTW89_WW][2][102] = 0, + [1][0][RTW89_WW][0][104] = -4, + [1][0][RTW89_WW][1][104] = -4, + [1][0][RTW89_WW][2][104] = 0, + [1][0][RTW89_WW][0][105] = -4, + [1][0][RTW89_WW][1][105] = -4, + [1][0][RTW89_WW][2][105] = 0, + [1][0][RTW89_WW][0][107] = -2, + [1][0][RTW89_WW][1][107] = -2, + [1][0][RTW89_WW][2][107] = 0, + [1][0][RTW89_WW][0][109] = 2, + [1][0][RTW89_WW][1][109] = 2, + [1][0][RTW89_WW][2][109] = 0, + [1][0][RTW89_WW][0][111] = 0, + [1][0][RTW89_WW][1][111] = 0, + [1][0][RTW89_WW][2][111] = 0, + [1][0][RTW89_WW][0][113] = 0, + [1][0][RTW89_WW][1][113] = 0, + [1][0][RTW89_WW][2][113] = 0, + [1][0][RTW89_WW][0][115] = 0, + [1][0][RTW89_WW][1][115] = 0, + [1][0][RTW89_WW][2][115] = 0, + [1][0][RTW89_WW][0][117] = 0, + [1][0][RTW89_WW][1][117] = 0, + [1][0][RTW89_WW][2][117] = 0, + [1][0][RTW89_WW][0][119] = 0, + [1][0][RTW89_WW][1][119] = 0, + [1][0][RTW89_WW][2][119] = 0, + [1][1][RTW89_WW][0][0] = -26, + [1][1][RTW89_WW][1][0] = -26, + [1][1][RTW89_WW][2][0] = 44, + [1][1][RTW89_WW][0][2] = -28, + [1][1][RTW89_WW][1][2] = -28, + [1][1][RTW89_WW][2][2] = 44, + [1][1][RTW89_WW][0][4] = -28, + [1][1][RTW89_WW][1][4] = -28, + [1][1][RTW89_WW][2][4] = 44, + [1][1][RTW89_WW][0][6] = -28, + [1][1][RTW89_WW][1][6] = -28, + [1][1][RTW89_WW][2][6] = 44, + [1][1][RTW89_WW][0][8] = -28, + [1][1][RTW89_WW][1][8] = -28, + [1][1][RTW89_WW][2][8] = 44, + [1][1][RTW89_WW][0][10] = -28, + [1][1][RTW89_WW][1][10] = -28, + [1][1][RTW89_WW][2][10] = 44, + [1][1][RTW89_WW][0][12] = -28, + [1][1][RTW89_WW][1][12] = -28, + [1][1][RTW89_WW][2][12] = 44, + [1][1][RTW89_WW][0][14] = -28, + [1][1][RTW89_WW][1][14] = -28, + [1][1][RTW89_WW][2][14] = 44, + [1][1][RTW89_WW][0][15] = -28, + [1][1][RTW89_WW][1][15] = -28, + [1][1][RTW89_WW][2][15] = 44, + [1][1][RTW89_WW][0][17] = -28, + [1][1][RTW89_WW][1][17] = -28, + [1][1][RTW89_WW][2][17] = 44, + [1][1][RTW89_WW][0][19] = -28, + [1][1][RTW89_WW][1][19] = -28, + [1][1][RTW89_WW][2][19] = 44, + [1][1][RTW89_WW][0][21] = -28, + [1][1][RTW89_WW][1][21] = -28, + [1][1][RTW89_WW][2][21] = 44, + [1][1][RTW89_WW][0][23] = -28, + [1][1][RTW89_WW][1][23] = -28, + [1][1][RTW89_WW][2][23] = 44, + [1][1][RTW89_WW][0][25] = -28, + [1][1][RTW89_WW][1][25] = -28, + [1][1][RTW89_WW][2][25] = 44, + [1][1][RTW89_WW][0][27] = -28, + [1][1][RTW89_WW][1][27] = -28, + [1][1][RTW89_WW][2][27] = 44, + [1][1][RTW89_WW][0][29] = -28, + [1][1][RTW89_WW][1][29] = -28, + [1][1][RTW89_WW][2][29] = 44, + [1][1][RTW89_WW][0][30] = -28, + [1][1][RTW89_WW][1][30] = -28, + [1][1][RTW89_WW][2][30] = 44, + [1][1][RTW89_WW][0][32] = -28, + [1][1][RTW89_WW][1][32] = -28, + [1][1][RTW89_WW][2][32] = 44, + [1][1][RTW89_WW][0][34] = -28, + [1][1][RTW89_WW][1][34] = -28, + [1][1][RTW89_WW][2][34] = 44, + [1][1][RTW89_WW][0][36] = -28, + [1][1][RTW89_WW][1][36] = -28, + [1][1][RTW89_WW][2][36] = 44, + [1][1][RTW89_WW][0][38] = -28, + [1][1][RTW89_WW][1][38] = -28, + [1][1][RTW89_WW][2][38] = 44, + [1][1][RTW89_WW][0][40] = -28, + [1][1][RTW89_WW][1][40] = -28, + [1][1][RTW89_WW][2][40] = 44, + [1][1][RTW89_WW][0][42] = -28, + [1][1][RTW89_WW][1][42] = -28, + [1][1][RTW89_WW][2][42] = 44, + [1][1][RTW89_WW][0][44] = -28, + [1][1][RTW89_WW][1][44] = -28, + [1][1][RTW89_WW][2][44] = 44, + [1][1][RTW89_WW][0][45] = -26, + [1][1][RTW89_WW][1][45] = -26, + [1][1][RTW89_WW][2][45] = 0, + [1][1][RTW89_WW][0][47] = -28, + [1][1][RTW89_WW][1][47] = -28, + [1][1][RTW89_WW][2][47] = 0, + [1][1][RTW89_WW][0][49] = -28, + [1][1][RTW89_WW][1][49] = -28, + [1][1][RTW89_WW][2][49] = 0, + [1][1][RTW89_WW][0][51] = -28, + [1][1][RTW89_WW][1][51] = -28, + [1][1][RTW89_WW][2][51] = 0, + [1][1][RTW89_WW][0][53] = -26, + [1][1][RTW89_WW][1][53] = -26, + [1][1][RTW89_WW][2][53] = 0, + [1][1][RTW89_WW][0][55] = -28, + [1][1][RTW89_WW][1][55] = -28, + [1][1][RTW89_WW][2][55] = 44, + [1][1][RTW89_WW][0][57] = -28, + [1][1][RTW89_WW][1][57] = -28, + [1][1][RTW89_WW][2][57] = 44, + [1][1][RTW89_WW][0][59] = -28, + [1][1][RTW89_WW][1][59] = -28, + [1][1][RTW89_WW][2][59] = 44, + [1][1][RTW89_WW][0][60] = -28, + [1][1][RTW89_WW][1][60] = -28, + [1][1][RTW89_WW][2][60] = 44, + [1][1][RTW89_WW][0][62] = -28, + [1][1][RTW89_WW][1][62] = -28, + [1][1][RTW89_WW][2][62] = 44, + [1][1][RTW89_WW][0][64] = -28, + [1][1][RTW89_WW][1][64] = -28, + [1][1][RTW89_WW][2][64] = 44, + [1][1][RTW89_WW][0][66] = -28, + [1][1][RTW89_WW][1][66] = -28, + [1][1][RTW89_WW][2][66] = 44, + [1][1][RTW89_WW][0][68] = -28, + [1][1][RTW89_WW][1][68] = -28, + [1][1][RTW89_WW][2][68] = 44, + [1][1][RTW89_WW][0][70] = -26, + [1][1][RTW89_WW][1][70] = -26, + [1][1][RTW89_WW][2][70] = 44, + [1][1][RTW89_WW][0][72] = -28, + [1][1][RTW89_WW][1][72] = -28, + [1][1][RTW89_WW][2][72] = 44, + [1][1][RTW89_WW][0][74] = -28, + [1][1][RTW89_WW][1][74] = -28, + [1][1][RTW89_WW][2][74] = 44, + [1][1][RTW89_WW][0][75] = -28, + [1][1][RTW89_WW][1][75] = -28, + [1][1][RTW89_WW][2][75] = 44, + [1][1][RTW89_WW][0][77] = -28, + [1][1][RTW89_WW][1][77] = -28, + [1][1][RTW89_WW][2][77] = 44, + [1][1][RTW89_WW][0][79] = -28, + [1][1][RTW89_WW][1][79] = -28, + [1][1][RTW89_WW][2][79] = 44, + [1][1][RTW89_WW][0][81] = -28, + [1][1][RTW89_WW][1][81] = -28, + [1][1][RTW89_WW][2][81] = 44, + [1][1][RTW89_WW][0][83] = -28, + [1][1][RTW89_WW][1][83] = -28, + [1][1][RTW89_WW][2][83] = 44, + [1][1][RTW89_WW][0][85] = -28, + [1][1][RTW89_WW][1][85] = -28, + [1][1][RTW89_WW][2][85] = 44, + [1][1][RTW89_WW][0][87] = -28, + [1][1][RTW89_WW][1][87] = -28, + [1][1][RTW89_WW][2][87] = 0, + [1][1][RTW89_WW][0][89] = -26, + [1][1][RTW89_WW][1][89] = -26, + [1][1][RTW89_WW][2][89] = 0, + [1][1][RTW89_WW][0][90] = -26, + [1][1][RTW89_WW][1][90] = -26, + [1][1][RTW89_WW][2][90] = 0, + [1][1][RTW89_WW][0][92] = -26, + [1][1][RTW89_WW][1][92] = -26, + [1][1][RTW89_WW][2][92] = 0, + [1][1][RTW89_WW][0][94] = -26, + [1][1][RTW89_WW][1][94] = -26, + [1][1][RTW89_WW][2][94] = 0, + [1][1][RTW89_WW][0][96] = -26, + [1][1][RTW89_WW][1][96] = -26, + [1][1][RTW89_WW][2][96] = 0, + [1][1][RTW89_WW][0][98] = -26, + [1][1][RTW89_WW][1][98] = -26, + [1][1][RTW89_WW][2][98] = 0, + [1][1][RTW89_WW][0][100] = -26, + [1][1][RTW89_WW][1][100] = -26, + [1][1][RTW89_WW][2][100] = 0, + [1][1][RTW89_WW][0][102] = -26, + [1][1][RTW89_WW][1][102] = -26, + [1][1][RTW89_WW][2][102] = 0, + [1][1][RTW89_WW][0][104] = -26, + [1][1][RTW89_WW][1][104] = -26, + [1][1][RTW89_WW][2][104] = 0, + [1][1][RTW89_WW][0][105] = -26, + [1][1][RTW89_WW][1][105] = -26, + [1][1][RTW89_WW][2][105] = 0, + [1][1][RTW89_WW][0][107] = -22, + [1][1][RTW89_WW][1][107] = -22, + [1][1][RTW89_WW][2][107] = 0, + [1][1][RTW89_WW][0][109] = -22, + [1][1][RTW89_WW][1][109] = -22, + [1][1][RTW89_WW][2][109] = 0, + [1][1][RTW89_WW][0][111] = 0, + [1][1][RTW89_WW][1][111] = 0, + [1][1][RTW89_WW][2][111] = 0, + [1][1][RTW89_WW][0][113] = 0, + [1][1][RTW89_WW][1][113] = 0, + [1][1][RTW89_WW][2][113] = 0, + [1][1][RTW89_WW][0][115] = 0, + [1][1][RTW89_WW][1][115] = 0, + [1][1][RTW89_WW][2][115] = 0, + [1][1][RTW89_WW][0][117] = 0, + [1][1][RTW89_WW][1][117] = 0, + [1][1][RTW89_WW][2][117] = 0, + [1][1][RTW89_WW][0][119] = 0, + [1][1][RTW89_WW][1][119] = 0, + [1][1][RTW89_WW][2][119] = 0, + [2][0][RTW89_WW][0][0] = -2, + [2][0][RTW89_WW][1][0] = -2, + [2][0][RTW89_WW][2][0] = 60, + [2][0][RTW89_WW][0][2] = -2, + [2][0][RTW89_WW][1][2] = -2, + [2][0][RTW89_WW][2][2] = 60, + [2][0][RTW89_WW][0][4] = -2, + [2][0][RTW89_WW][1][4] = -2, + [2][0][RTW89_WW][2][4] = 60, + [2][0][RTW89_WW][0][6] = -2, + [2][0][RTW89_WW][1][6] = -2, + [2][0][RTW89_WW][2][6] = 60, + [2][0][RTW89_WW][0][8] = -2, + [2][0][RTW89_WW][1][8] = -2, + [2][0][RTW89_WW][2][8] = 60, + [2][0][RTW89_WW][0][10] = -2, + [2][0][RTW89_WW][1][10] = -2, + [2][0][RTW89_WW][2][10] = 60, + [2][0][RTW89_WW][0][12] = -2, + [2][0][RTW89_WW][1][12] = -2, + [2][0][RTW89_WW][2][12] = 60, + [2][0][RTW89_WW][0][14] = -2, + [2][0][RTW89_WW][1][14] = -2, + [2][0][RTW89_WW][2][14] = 60, + [2][0][RTW89_WW][0][15] = -2, + [2][0][RTW89_WW][1][15] = -2, + [2][0][RTW89_WW][2][15] = 60, + [2][0][RTW89_WW][0][17] = -2, + [2][0][RTW89_WW][1][17] = -2, + [2][0][RTW89_WW][2][17] = 60, + [2][0][RTW89_WW][0][19] = -2, + [2][0][RTW89_WW][1][19] = -2, + [2][0][RTW89_WW][2][19] = 60, + [2][0][RTW89_WW][0][21] = -2, + [2][0][RTW89_WW][1][21] = -2, + [2][0][RTW89_WW][2][21] = 60, + [2][0][RTW89_WW][0][23] = -2, + [2][0][RTW89_WW][1][23] = -2, + [2][0][RTW89_WW][2][23] = 78, + [2][0][RTW89_WW][0][25] = -2, + [2][0][RTW89_WW][1][25] = -2, + [2][0][RTW89_WW][2][25] = 78, + [2][0][RTW89_WW][0][27] = -2, + [2][0][RTW89_WW][1][27] = -2, + [2][0][RTW89_WW][2][27] = 78, + [2][0][RTW89_WW][0][29] = -2, + [2][0][RTW89_WW][1][29] = -2, + [2][0][RTW89_WW][2][29] = 78, + [2][0][RTW89_WW][0][30] = -2, + [2][0][RTW89_WW][1][30] = -2, + [2][0][RTW89_WW][2][30] = 78, + [2][0][RTW89_WW][0][32] = -2, + [2][0][RTW89_WW][1][32] = -2, + [2][0][RTW89_WW][2][32] = 78, + [2][0][RTW89_WW][0][34] = -2, + [2][0][RTW89_WW][1][34] = -2, + [2][0][RTW89_WW][2][34] = 78, + [2][0][RTW89_WW][0][36] = -2, + [2][0][RTW89_WW][1][36] = -2, + [2][0][RTW89_WW][2][36] = 78, + [2][0][RTW89_WW][0][38] = -2, + [2][0][RTW89_WW][1][38] = -2, + [2][0][RTW89_WW][2][38] = 78, + [2][0][RTW89_WW][0][40] = -2, + [2][0][RTW89_WW][1][40] = -2, + [2][0][RTW89_WW][2][40] = 78, + [2][0][RTW89_WW][0][42] = -2, + [2][0][RTW89_WW][1][42] = -2, + [2][0][RTW89_WW][2][42] = 78, + [2][0][RTW89_WW][0][44] = -2, + [2][0][RTW89_WW][1][44] = -2, + [2][0][RTW89_WW][2][44] = 78, + [2][0][RTW89_WW][0][45] = -2, + [2][0][RTW89_WW][1][45] = -2, + [2][0][RTW89_WW][2][45] = 0, + [2][0][RTW89_WW][0][47] = -2, + [2][0][RTW89_WW][1][47] = -2, + [2][0][RTW89_WW][2][47] = 0, + [2][0][RTW89_WW][0][49] = -2, + [2][0][RTW89_WW][1][49] = -2, + [2][0][RTW89_WW][2][49] = 0, + [2][0][RTW89_WW][0][51] = -2, + [2][0][RTW89_WW][1][51] = -2, + [2][0][RTW89_WW][2][51] = 0, + [2][0][RTW89_WW][0][53] = -2, + [2][0][RTW89_WW][1][53] = -2, + [2][0][RTW89_WW][2][53] = 0, + [2][0][RTW89_WW][0][55] = -2, + [2][0][RTW89_WW][1][55] = -2, + [2][0][RTW89_WW][2][55] = 78, + [2][0][RTW89_WW][0][57] = -2, + [2][0][RTW89_WW][1][57] = -2, + [2][0][RTW89_WW][2][57] = 78, + [2][0][RTW89_WW][0][59] = -2, + [2][0][RTW89_WW][1][59] = -2, + [2][0][RTW89_WW][2][59] = 78, + [2][0][RTW89_WW][0][60] = -2, + [2][0][RTW89_WW][1][60] = -2, + [2][0][RTW89_WW][2][60] = 78, + [2][0][RTW89_WW][0][62] = -2, + [2][0][RTW89_WW][1][62] = -2, + [2][0][RTW89_WW][2][62] = 78, + [2][0][RTW89_WW][0][64] = -2, + [2][0][RTW89_WW][1][64] = -2, + [2][0][RTW89_WW][2][64] = 78, + [2][0][RTW89_WW][0][66] = -2, + [2][0][RTW89_WW][1][66] = -2, + [2][0][RTW89_WW][2][66] = 78, + [2][0][RTW89_WW][0][68] = -2, + [2][0][RTW89_WW][1][68] = -2, + [2][0][RTW89_WW][2][68] = 78, + [2][0][RTW89_WW][0][70] = -2, + [2][0][RTW89_WW][1][70] = -2, + [2][0][RTW89_WW][2][70] = 78, + [2][0][RTW89_WW][0][72] = -2, + [2][0][RTW89_WW][1][72] = -2, + [2][0][RTW89_WW][2][72] = 78, + [2][0][RTW89_WW][0][74] = -2, + [2][0][RTW89_WW][1][74] = -2, + [2][0][RTW89_WW][2][74] = 78, + [2][0][RTW89_WW][0][75] = -2, + [2][0][RTW89_WW][1][75] = -2, + [2][0][RTW89_WW][2][75] = 78, + [2][0][RTW89_WW][0][77] = -2, + [2][0][RTW89_WW][1][77] = -2, + [2][0][RTW89_WW][2][77] = 78, + [2][0][RTW89_WW][0][79] = -2, + [2][0][RTW89_WW][1][79] = -2, + [2][0][RTW89_WW][2][79] = 78, + [2][0][RTW89_WW][0][81] = -2, + [2][0][RTW89_WW][1][81] = -2, + [2][0][RTW89_WW][2][81] = 78, + [2][0][RTW89_WW][0][83] = -2, + [2][0][RTW89_WW][1][83] = -2, + [2][0][RTW89_WW][2][83] = 78, + [2][0][RTW89_WW][0][85] = -2, + [2][0][RTW89_WW][1][85] = -2, + [2][0][RTW89_WW][2][85] = 78, + [2][0][RTW89_WW][0][87] = -2, + [2][0][RTW89_WW][1][87] = -2, + [2][0][RTW89_WW][2][87] = 0, + [2][0][RTW89_WW][0][89] = -2, + [2][0][RTW89_WW][1][89] = -2, + [2][0][RTW89_WW][2][89] = 0, + [2][0][RTW89_WW][0][90] = -2, + [2][0][RTW89_WW][1][90] = -2, + [2][0][RTW89_WW][2][90] = 0, + [2][0][RTW89_WW][0][92] = -2, + [2][0][RTW89_WW][1][92] = -2, + [2][0][RTW89_WW][2][92] = 0, + [2][0][RTW89_WW][0][94] = -2, + [2][0][RTW89_WW][1][94] = -2, + [2][0][RTW89_WW][2][94] = 0, + [2][0][RTW89_WW][0][96] = -2, + [2][0][RTW89_WW][1][96] = -2, + [2][0][RTW89_WW][2][96] = 0, + [2][0][RTW89_WW][0][98] = -2, + [2][0][RTW89_WW][1][98] = -2, + [2][0][RTW89_WW][2][98] = 0, + [2][0][RTW89_WW][0][100] = -2, + [2][0][RTW89_WW][1][100] = -2, + [2][0][RTW89_WW][2][100] = 0, + [2][0][RTW89_WW][0][102] = -2, + [2][0][RTW89_WW][1][102] = -2, + [2][0][RTW89_WW][2][102] = 0, + [2][0][RTW89_WW][0][104] = -2, + [2][0][RTW89_WW][1][104] = -2, + [2][0][RTW89_WW][2][104] = 0, + [2][0][RTW89_WW][0][105] = -2, + [2][0][RTW89_WW][1][105] = -2, + [2][0][RTW89_WW][2][105] = 0, + [2][0][RTW89_WW][0][107] = -2, + [2][0][RTW89_WW][1][107] = -2, + [2][0][RTW89_WW][2][107] = 0, + [2][0][RTW89_WW][0][109] = 12, + [2][0][RTW89_WW][1][109] = 12, + [2][0][RTW89_WW][2][109] = 0, + [2][0][RTW89_WW][0][111] = 0, + [2][0][RTW89_WW][1][111] = 0, + [2][0][RTW89_WW][2][111] = 0, + [2][0][RTW89_WW][0][113] = 0, + [2][0][RTW89_WW][1][113] = 0, + [2][0][RTW89_WW][2][113] = 0, + [2][0][RTW89_WW][0][115] = 0, + [2][0][RTW89_WW][1][115] = 0, + [2][0][RTW89_WW][2][115] = 0, + [2][0][RTW89_WW][0][117] = 0, + [2][0][RTW89_WW][1][117] = 0, + [2][0][RTW89_WW][2][117] = 0, + [2][0][RTW89_WW][0][119] = 0, + [2][0][RTW89_WW][1][119] = 0, + [2][0][RTW89_WW][2][119] = 0, + [2][1][RTW89_WW][0][0] = -16, + [2][1][RTW89_WW][1][0] = -16, + [2][1][RTW89_WW][2][0] = 54, + [2][1][RTW89_WW][0][2] = -16, + [2][1][RTW89_WW][1][2] = -16, + [2][1][RTW89_WW][2][2] = 54, + [2][1][RTW89_WW][0][4] = -16, + [2][1][RTW89_WW][1][4] = -16, + [2][1][RTW89_WW][2][4] = 54, + [2][1][RTW89_WW][0][6] = -16, + [2][1][RTW89_WW][1][6] = -16, + [2][1][RTW89_WW][2][6] = 54, + [2][1][RTW89_WW][0][8] = -16, + [2][1][RTW89_WW][1][8] = -16, + [2][1][RTW89_WW][2][8] = 54, + [2][1][RTW89_WW][0][10] = -16, + [2][1][RTW89_WW][1][10] = -16, + [2][1][RTW89_WW][2][10] = 54, + [2][1][RTW89_WW][0][12] = -16, + [2][1][RTW89_WW][1][12] = -16, + [2][1][RTW89_WW][2][12] = 54, + [2][1][RTW89_WW][0][14] = -16, + [2][1][RTW89_WW][1][14] = -16, + [2][1][RTW89_WW][2][14] = 54, + [2][1][RTW89_WW][0][15] = -16, + [2][1][RTW89_WW][1][15] = -16, + [2][1][RTW89_WW][2][15] = 54, + [2][1][RTW89_WW][0][17] = -16, + [2][1][RTW89_WW][1][17] = -16, + [2][1][RTW89_WW][2][17] = 54, + [2][1][RTW89_WW][0][19] = -16, + [2][1][RTW89_WW][1][19] = -16, + [2][1][RTW89_WW][2][19] = 54, + [2][1][RTW89_WW][0][21] = -16, + [2][1][RTW89_WW][1][21] = -16, + [2][1][RTW89_WW][2][21] = 54, + [2][1][RTW89_WW][0][23] = -16, + [2][1][RTW89_WW][1][23] = -16, + [2][1][RTW89_WW][2][23] = 54, + [2][1][RTW89_WW][0][25] = -16, + [2][1][RTW89_WW][1][25] = -16, + [2][1][RTW89_WW][2][25] = 54, + [2][1][RTW89_WW][0][27] = -16, + [2][1][RTW89_WW][1][27] = -16, + [2][1][RTW89_WW][2][27] = 54, + [2][1][RTW89_WW][0][29] = -16, + [2][1][RTW89_WW][1][29] = -16, + [2][1][RTW89_WW][2][29] = 54, + [2][1][RTW89_WW][0][30] = -16, + [2][1][RTW89_WW][1][30] = -16, + [2][1][RTW89_WW][2][30] = 54, + [2][1][RTW89_WW][0][32] = -16, + [2][1][RTW89_WW][1][32] = -16, + [2][1][RTW89_WW][2][32] = 54, + [2][1][RTW89_WW][0][34] = -16, + [2][1][RTW89_WW][1][34] = -16, + [2][1][RTW89_WW][2][34] = 54, + [2][1][RTW89_WW][0][36] = -16, + [2][1][RTW89_WW][1][36] = -16, + [2][1][RTW89_WW][2][36] = 54, + [2][1][RTW89_WW][0][38] = -16, + [2][1][RTW89_WW][1][38] = -16, + [2][1][RTW89_WW][2][38] = 54, + [2][1][RTW89_WW][0][40] = -16, + [2][1][RTW89_WW][1][40] = -16, + [2][1][RTW89_WW][2][40] = 54, + [2][1][RTW89_WW][0][42] = -16, + [2][1][RTW89_WW][1][42] = -16, + [2][1][RTW89_WW][2][42] = 54, + [2][1][RTW89_WW][0][44] = -16, + [2][1][RTW89_WW][1][44] = -16, + [2][1][RTW89_WW][2][44] = 54, + [2][1][RTW89_WW][0][45] = -16, + [2][1][RTW89_WW][1][45] = -16, + [2][1][RTW89_WW][2][45] = 0, + [2][1][RTW89_WW][0][47] = -16, + [2][1][RTW89_WW][1][47] = -16, + [2][1][RTW89_WW][2][47] = 0, + [2][1][RTW89_WW][0][49] = -16, + [2][1][RTW89_WW][1][49] = -16, + [2][1][RTW89_WW][2][49] = 0, + [2][1][RTW89_WW][0][51] = -16, + [2][1][RTW89_WW][1][51] = -16, + [2][1][RTW89_WW][2][51] = 0, + [2][1][RTW89_WW][0][53] = -16, + [2][1][RTW89_WW][1][53] = -16, + [2][1][RTW89_WW][2][53] = 0, + [2][1][RTW89_WW][0][55] = -16, + [2][1][RTW89_WW][1][55] = -16, + [2][1][RTW89_WW][2][55] = 54, + [2][1][RTW89_WW][0][57] = -16, + [2][1][RTW89_WW][1][57] = -16, + [2][1][RTW89_WW][2][57] = 54, + [2][1][RTW89_WW][0][59] = -16, + [2][1][RTW89_WW][1][59] = -16, + [2][1][RTW89_WW][2][59] = 54, + [2][1][RTW89_WW][0][60] = -16, + [2][1][RTW89_WW][1][60] = -16, + [2][1][RTW89_WW][2][60] = 54, + [2][1][RTW89_WW][0][62] = -16, + [2][1][RTW89_WW][1][62] = -16, + [2][1][RTW89_WW][2][62] = 54, + [2][1][RTW89_WW][0][64] = -16, + [2][1][RTW89_WW][1][64] = -16, + [2][1][RTW89_WW][2][64] = 54, + [2][1][RTW89_WW][0][66] = -16, + [2][1][RTW89_WW][1][66] = -16, + [2][1][RTW89_WW][2][66] = 54, + [2][1][RTW89_WW][0][68] = -16, + [2][1][RTW89_WW][1][68] = -16, + [2][1][RTW89_WW][2][68] = 54, + [2][1][RTW89_WW][0][70] = -16, + [2][1][RTW89_WW][1][70] = -16, + [2][1][RTW89_WW][2][70] = 56, + [2][1][RTW89_WW][0][72] = -16, + [2][1][RTW89_WW][1][72] = -16, + [2][1][RTW89_WW][2][72] = 56, + [2][1][RTW89_WW][0][74] = -16, + [2][1][RTW89_WW][1][74] = -16, + [2][1][RTW89_WW][2][74] = 56, + [2][1][RTW89_WW][0][75] = -16, + [2][1][RTW89_WW][1][75] = -16, + [2][1][RTW89_WW][2][75] = 56, + [2][1][RTW89_WW][0][77] = -16, + [2][1][RTW89_WW][1][77] = -16, + [2][1][RTW89_WW][2][77] = 56, + [2][1][RTW89_WW][0][79] = -16, + [2][1][RTW89_WW][1][79] = -16, + [2][1][RTW89_WW][2][79] = 56, + [2][1][RTW89_WW][0][81] = -16, + [2][1][RTW89_WW][1][81] = -16, + [2][1][RTW89_WW][2][81] = 56, + [2][1][RTW89_WW][0][83] = -16, + [2][1][RTW89_WW][1][83] = -16, + [2][1][RTW89_WW][2][83] = 56, + [2][1][RTW89_WW][0][85] = -18, + [2][1][RTW89_WW][1][85] = -18, + [2][1][RTW89_WW][2][85] = 56, + [2][1][RTW89_WW][0][87] = -16, + [2][1][RTW89_WW][1][87] = -16, + [2][1][RTW89_WW][2][87] = 0, + [2][1][RTW89_WW][0][89] = -16, + [2][1][RTW89_WW][1][89] = -16, + [2][1][RTW89_WW][2][89] = 0, + [2][1][RTW89_WW][0][90] = -16, + [2][1][RTW89_WW][1][90] = -16, + [2][1][RTW89_WW][2][90] = 0, + [2][1][RTW89_WW][0][92] = -16, + [2][1][RTW89_WW][1][92] = -16, + [2][1][RTW89_WW][2][92] = 0, + [2][1][RTW89_WW][0][94] = -16, + [2][1][RTW89_WW][1][94] = -16, + [2][1][RTW89_WW][2][94] = 0, + [2][1][RTW89_WW][0][96] = -16, + [2][1][RTW89_WW][1][96] = -16, + [2][1][RTW89_WW][2][96] = 0, + [2][1][RTW89_WW][0][98] = -16, + [2][1][RTW89_WW][1][98] = -16, + [2][1][RTW89_WW][2][98] = 0, + [2][1][RTW89_WW][0][100] = -16, + [2][1][RTW89_WW][1][100] = -16, + [2][1][RTW89_WW][2][100] = 0, + [2][1][RTW89_WW][0][102] = -16, + [2][1][RTW89_WW][1][102] = -16, + [2][1][RTW89_WW][2][102] = 0, + [2][1][RTW89_WW][0][104] = -16, + [2][1][RTW89_WW][1][104] = -16, + [2][1][RTW89_WW][2][104] = 0, + [2][1][RTW89_WW][0][105] = -16, + [2][1][RTW89_WW][1][105] = -16, + [2][1][RTW89_WW][2][105] = 0, + [2][1][RTW89_WW][0][107] = -14, + [2][1][RTW89_WW][1][107] = -14, + [2][1][RTW89_WW][2][107] = 0, + [2][1][RTW89_WW][0][109] = -10, + [2][1][RTW89_WW][1][109] = -10, + [2][1][RTW89_WW][2][109] = 0, + [2][1][RTW89_WW][0][111] = 0, + [2][1][RTW89_WW][1][111] = 0, + [2][1][RTW89_WW][2][111] = 0, + [2][1][RTW89_WW][0][113] = 0, + [2][1][RTW89_WW][1][113] = 0, + [2][1][RTW89_WW][2][113] = 0, + [2][1][RTW89_WW][0][115] = 0, + [2][1][RTW89_WW][1][115] = 0, + [2][1][RTW89_WW][2][115] = 0, + [2][1][RTW89_WW][0][117] = 0, + [2][1][RTW89_WW][1][117] = 0, + [2][1][RTW89_WW][2][117] = 0, + [2][1][RTW89_WW][0][119] = 0, + [2][1][RTW89_WW][1][119] = 0, + [2][1][RTW89_WW][2][119] = 0, + [0][0][RTW89_FCC][1][0] = -16, + [0][0][RTW89_FCC][2][0] = 44, + [0][0][RTW89_ETSI][1][0] = 32, + [0][0][RTW89_ETSI][0][0] = -8, + [0][0][RTW89_MKK][1][0] = 30, + [0][0][RTW89_MKK][0][0] = -8, + [0][0][RTW89_IC][1][0] = -16, + [0][0][RTW89_KCC][1][0] = -2, + [0][0][RTW89_KCC][0][0] = -2, + [0][0][RTW89_ACMA][1][0] = 32, + [0][0][RTW89_ACMA][0][0] = -8, + [0][0][RTW89_CHILE][1][0] = -16, + [0][0][RTW89_QATAR][1][0] = 32, + [0][0][RTW89_QATAR][0][0] = -8, + [0][0][RTW89_UK][1][0] = 32, + [0][0][RTW89_UK][0][0] = -8, + [0][0][RTW89_FCC][1][2] = -18, + [0][0][RTW89_FCC][2][2] = 44, + [0][0][RTW89_ETSI][1][2] = 32, + [0][0][RTW89_ETSI][0][2] = -8, + [0][0][RTW89_MKK][1][2] = 30, + [0][0][RTW89_MKK][0][2] = -8, + [0][0][RTW89_IC][1][2] = -18, + [0][0][RTW89_KCC][1][2] = -2, + [0][0][RTW89_KCC][0][2] = -2, + [0][0][RTW89_ACMA][1][2] = 32, + [0][0][RTW89_ACMA][0][2] = -8, + [0][0][RTW89_CHILE][1][2] = -18, + [0][0][RTW89_QATAR][1][2] = 32, + [0][0][RTW89_QATAR][0][2] = -8, + [0][0][RTW89_UK][1][2] = 32, + [0][0][RTW89_UK][0][2] = -8, + [0][0][RTW89_FCC][1][4] = -18, + [0][0][RTW89_FCC][2][4] = 44, + [0][0][RTW89_ETSI][1][4] = 32, + [0][0][RTW89_ETSI][0][4] = -8, + [0][0][RTW89_MKK][1][4] = 30, + [0][0][RTW89_MKK][0][4] = -8, + [0][0][RTW89_IC][1][4] = -18, + [0][0][RTW89_KCC][1][4] = -2, + [0][0][RTW89_KCC][0][4] = -2, + [0][0][RTW89_ACMA][1][4] = 32, + [0][0][RTW89_ACMA][0][4] = -8, + [0][0][RTW89_CHILE][1][4] = -18, + [0][0][RTW89_QATAR][1][4] = 32, + [0][0][RTW89_QATAR][0][4] = -8, + [0][0][RTW89_UK][1][4] = 32, + [0][0][RTW89_UK][0][4] = -8, + [0][0][RTW89_FCC][1][6] = -18, + [0][0][RTW89_FCC][2][6] = 44, + [0][0][RTW89_ETSI][1][6] = 32, + [0][0][RTW89_ETSI][0][6] = -8, + [0][0][RTW89_MKK][1][6] = 30, + [0][0][RTW89_MKK][0][6] = -8, + [0][0][RTW89_IC][1][6] = -18, + [0][0][RTW89_KCC][1][6] = -2, + [0][0][RTW89_KCC][0][6] = -2, + [0][0][RTW89_ACMA][1][6] = 32, + [0][0][RTW89_ACMA][0][6] = -8, + [0][0][RTW89_CHILE][1][6] = -18, + [0][0][RTW89_QATAR][1][6] = 32, + [0][0][RTW89_QATAR][0][6] = -8, + [0][0][RTW89_UK][1][6] = 32, + [0][0][RTW89_UK][0][6] = -8, + [0][0][RTW89_FCC][1][8] = -18, + [0][0][RTW89_FCC][2][8] = 44, + [0][0][RTW89_ETSI][1][8] = 32, + [0][0][RTW89_ETSI][0][8] = -8, + [0][0][RTW89_MKK][1][8] = 30, + [0][0][RTW89_MKK][0][8] = -8, + [0][0][RTW89_IC][1][8] = -18, + [0][0][RTW89_KCC][1][8] = -2, + [0][0][RTW89_KCC][0][8] = -2, + [0][0][RTW89_ACMA][1][8] = 32, + [0][0][RTW89_ACMA][0][8] = -8, + [0][0][RTW89_CHILE][1][8] = -18, + [0][0][RTW89_QATAR][1][8] = 32, + [0][0][RTW89_QATAR][0][8] = -8, + [0][0][RTW89_UK][1][8] = 32, + [0][0][RTW89_UK][0][8] = -8, + [0][0][RTW89_FCC][1][10] = -18, + [0][0][RTW89_FCC][2][10] = 44, + [0][0][RTW89_ETSI][1][10] = 32, + [0][0][RTW89_ETSI][0][10] = -8, + [0][0][RTW89_MKK][1][10] = 30, + [0][0][RTW89_MKK][0][10] = -8, + [0][0][RTW89_IC][1][10] = -18, + [0][0][RTW89_KCC][1][10] = -2, + [0][0][RTW89_KCC][0][10] = -2, + [0][0][RTW89_ACMA][1][10] = 32, + [0][0][RTW89_ACMA][0][10] = -8, + [0][0][RTW89_CHILE][1][10] = -18, + [0][0][RTW89_QATAR][1][10] = 32, + [0][0][RTW89_QATAR][0][10] = -8, + [0][0][RTW89_UK][1][10] = 32, + [0][0][RTW89_UK][0][10] = -8, + [0][0][RTW89_FCC][1][12] = -18, + [0][0][RTW89_FCC][2][12] = 44, + [0][0][RTW89_ETSI][1][12] = 32, + [0][0][RTW89_ETSI][0][12] = -8, + [0][0][RTW89_MKK][1][12] = 30, + [0][0][RTW89_MKK][0][12] = -8, + [0][0][RTW89_IC][1][12] = -18, + [0][0][RTW89_KCC][1][12] = -2, + [0][0][RTW89_KCC][0][12] = -2, + [0][0][RTW89_ACMA][1][12] = 32, + [0][0][RTW89_ACMA][0][12] = -8, + [0][0][RTW89_CHILE][1][12] = -18, + [0][0][RTW89_QATAR][1][12] = 32, + [0][0][RTW89_QATAR][0][12] = -8, + [0][0][RTW89_UK][1][12] = 32, + [0][0][RTW89_UK][0][12] = -8, + [0][0][RTW89_FCC][1][14] = -18, + [0][0][RTW89_FCC][2][14] = 44, + [0][0][RTW89_ETSI][1][14] = 32, + [0][0][RTW89_ETSI][0][14] = -8, + [0][0][RTW89_MKK][1][14] = 30, + [0][0][RTW89_MKK][0][14] = -8, + [0][0][RTW89_IC][1][14] = -18, + [0][0][RTW89_KCC][1][14] = -2, + [0][0][RTW89_KCC][0][14] = -2, + [0][0][RTW89_ACMA][1][14] = 32, + [0][0][RTW89_ACMA][0][14] = -8, + [0][0][RTW89_CHILE][1][14] = -18, + [0][0][RTW89_QATAR][1][14] = 32, + [0][0][RTW89_QATAR][0][14] = -8, + [0][0][RTW89_UK][1][14] = 32, + [0][0][RTW89_UK][0][14] = -8, + [0][0][RTW89_FCC][1][15] = -18, + [0][0][RTW89_FCC][2][15] = 44, + [0][0][RTW89_ETSI][1][15] = 32, + [0][0][RTW89_ETSI][0][15] = -8, + [0][0][RTW89_MKK][1][15] = 30, + [0][0][RTW89_MKK][0][15] = -8, + [0][0][RTW89_IC][1][15] = -18, + [0][0][RTW89_KCC][1][15] = -2, + [0][0][RTW89_KCC][0][15] = -2, + [0][0][RTW89_ACMA][1][15] = 32, + [0][0][RTW89_ACMA][0][15] = -8, + [0][0][RTW89_CHILE][1][15] = -18, + [0][0][RTW89_QATAR][1][15] = 32, + [0][0][RTW89_QATAR][0][15] = -8, + [0][0][RTW89_UK][1][15] = 32, + [0][0][RTW89_UK][0][15] = -8, + [0][0][RTW89_FCC][1][17] = -18, + [0][0][RTW89_FCC][2][17] = 44, + [0][0][RTW89_ETSI][1][17] = 32, + [0][0][RTW89_ETSI][0][17] = -8, + [0][0][RTW89_MKK][1][17] = 30, + [0][0][RTW89_MKK][0][17] = -8, + [0][0][RTW89_IC][1][17] = -18, + [0][0][RTW89_KCC][1][17] = -2, + [0][0][RTW89_KCC][0][17] = -2, + [0][0][RTW89_ACMA][1][17] = 32, + [0][0][RTW89_ACMA][0][17] = -8, + [0][0][RTW89_CHILE][1][17] = -18, + [0][0][RTW89_QATAR][1][17] = 32, + [0][0][RTW89_QATAR][0][17] = -8, + [0][0][RTW89_UK][1][17] = 32, + [0][0][RTW89_UK][0][17] = -8, + [0][0][RTW89_FCC][1][19] = -18, + [0][0][RTW89_FCC][2][19] = 44, + [0][0][RTW89_ETSI][1][19] = 32, + [0][0][RTW89_ETSI][0][19] = -8, + [0][0][RTW89_MKK][1][19] = 30, + [0][0][RTW89_MKK][0][19] = -8, + [0][0][RTW89_IC][1][19] = -18, + [0][0][RTW89_KCC][1][19] = -2, + [0][0][RTW89_KCC][0][19] = -2, + [0][0][RTW89_ACMA][1][19] = 32, + [0][0][RTW89_ACMA][0][19] = -8, + [0][0][RTW89_CHILE][1][19] = -18, + [0][0][RTW89_QATAR][1][19] = 32, + [0][0][RTW89_QATAR][0][19] = -8, + [0][0][RTW89_UK][1][19] = 32, + [0][0][RTW89_UK][0][19] = -8, + [0][0][RTW89_FCC][1][21] = -18, + [0][0][RTW89_FCC][2][21] = 44, + [0][0][RTW89_ETSI][1][21] = 32, + [0][0][RTW89_ETSI][0][21] = -8, + [0][0][RTW89_MKK][1][21] = 30, + [0][0][RTW89_MKK][0][21] = -8, + [0][0][RTW89_IC][1][21] = -18, + [0][0][RTW89_KCC][1][21] = -2, + [0][0][RTW89_KCC][0][21] = -2, + [0][0][RTW89_ACMA][1][21] = 32, + [0][0][RTW89_ACMA][0][21] = -8, + [0][0][RTW89_CHILE][1][21] = -18, + [0][0][RTW89_QATAR][1][21] = 32, + [0][0][RTW89_QATAR][0][21] = -8, + [0][0][RTW89_UK][1][21] = 32, + [0][0][RTW89_UK][0][21] = -8, + [0][0][RTW89_FCC][1][23] = -18, + [0][0][RTW89_FCC][2][23] = 54, + [0][0][RTW89_ETSI][1][23] = 32, + [0][0][RTW89_ETSI][0][23] = -8, + [0][0][RTW89_MKK][1][23] = 30, + [0][0][RTW89_MKK][0][23] = -8, + [0][0][RTW89_IC][1][23] = -18, + [0][0][RTW89_KCC][1][23] = -2, + [0][0][RTW89_KCC][0][23] = -2, + [0][0][RTW89_ACMA][1][23] = 32, + [0][0][RTW89_ACMA][0][23] = -8, + [0][0][RTW89_CHILE][1][23] = -18, + [0][0][RTW89_QATAR][1][23] = 32, + [0][0][RTW89_QATAR][0][23] = -8, + [0][0][RTW89_UK][1][23] = 32, + [0][0][RTW89_UK][0][23] = -8, + [0][0][RTW89_FCC][1][25] = -18, + [0][0][RTW89_FCC][2][25] = 54, + [0][0][RTW89_ETSI][1][25] = 32, + [0][0][RTW89_ETSI][0][25] = -8, + [0][0][RTW89_MKK][1][25] = 30, + [0][0][RTW89_MKK][0][25] = -8, + [0][0][RTW89_IC][1][25] = -18, + [0][0][RTW89_KCC][1][25] = -2, + [0][0][RTW89_KCC][0][25] = -2, + [0][0][RTW89_ACMA][1][25] = 32, + [0][0][RTW89_ACMA][0][25] = -8, + [0][0][RTW89_CHILE][1][25] = -18, + [0][0][RTW89_QATAR][1][25] = 32, + [0][0][RTW89_QATAR][0][25] = -8, + [0][0][RTW89_UK][1][25] = 32, + [0][0][RTW89_UK][0][25] = -8, + [0][0][RTW89_FCC][1][27] = -18, + [0][0][RTW89_FCC][2][27] = 54, + [0][0][RTW89_ETSI][1][27] = 32, + [0][0][RTW89_ETSI][0][27] = -8, + [0][0][RTW89_MKK][1][27] = 30, + [0][0][RTW89_MKK][0][27] = -8, + [0][0][RTW89_IC][1][27] = -18, + [0][0][RTW89_KCC][1][27] = -2, + [0][0][RTW89_KCC][0][27] = -2, + [0][0][RTW89_ACMA][1][27] = 32, + [0][0][RTW89_ACMA][0][27] = -8, + [0][0][RTW89_CHILE][1][27] = -18, + [0][0][RTW89_QATAR][1][27] = 32, + [0][0][RTW89_QATAR][0][27] = -8, + [0][0][RTW89_UK][1][27] = 32, + [0][0][RTW89_UK][0][27] = -8, + [0][0][RTW89_FCC][1][29] = -18, + [0][0][RTW89_FCC][2][29] = 54, + [0][0][RTW89_ETSI][1][29] = 32, + [0][0][RTW89_ETSI][0][29] = -8, + [0][0][RTW89_MKK][1][29] = 30, + [0][0][RTW89_MKK][0][29] = -8, + [0][0][RTW89_IC][1][29] = -18, + [0][0][RTW89_KCC][1][29] = -2, + [0][0][RTW89_KCC][0][29] = -2, + [0][0][RTW89_ACMA][1][29] = 32, + [0][0][RTW89_ACMA][0][29] = -8, + [0][0][RTW89_CHILE][1][29] = -18, + [0][0][RTW89_QATAR][1][29] = 32, + [0][0][RTW89_QATAR][0][29] = -8, + [0][0][RTW89_UK][1][29] = 32, + [0][0][RTW89_UK][0][29] = -8, + [0][0][RTW89_FCC][1][30] = -18, + [0][0][RTW89_FCC][2][30] = 54, + [0][0][RTW89_ETSI][1][30] = 32, + [0][0][RTW89_ETSI][0][30] = -8, + [0][0][RTW89_MKK][1][30] = 30, + [0][0][RTW89_MKK][0][30] = -8, + [0][0][RTW89_IC][1][30] = -18, + [0][0][RTW89_KCC][1][30] = -2, + [0][0][RTW89_KCC][0][30] = -2, + [0][0][RTW89_ACMA][1][30] = 32, + [0][0][RTW89_ACMA][0][30] = -8, + [0][0][RTW89_CHILE][1][30] = -18, + [0][0][RTW89_QATAR][1][30] = 32, + [0][0][RTW89_QATAR][0][30] = -8, + [0][0][RTW89_UK][1][30] = 32, + [0][0][RTW89_UK][0][30] = -8, + [0][0][RTW89_FCC][1][32] = -18, + [0][0][RTW89_FCC][2][32] = 54, + [0][0][RTW89_ETSI][1][32] = 32, + [0][0][RTW89_ETSI][0][32] = -8, + [0][0][RTW89_MKK][1][32] = 30, + [0][0][RTW89_MKK][0][32] = -8, + [0][0][RTW89_IC][1][32] = -18, + [0][0][RTW89_KCC][1][32] = -2, + [0][0][RTW89_KCC][0][32] = -2, + [0][0][RTW89_ACMA][1][32] = 32, + [0][0][RTW89_ACMA][0][32] = -8, + [0][0][RTW89_CHILE][1][32] = -18, + [0][0][RTW89_QATAR][1][32] = 32, + [0][0][RTW89_QATAR][0][32] = -8, + [0][0][RTW89_UK][1][32] = 32, + [0][0][RTW89_UK][0][32] = -8, + [0][0][RTW89_FCC][1][34] = -18, + [0][0][RTW89_FCC][2][34] = 54, + [0][0][RTW89_ETSI][1][34] = 32, + [0][0][RTW89_ETSI][0][34] = -8, + [0][0][RTW89_MKK][1][34] = 30, + [0][0][RTW89_MKK][0][34] = -8, + [0][0][RTW89_IC][1][34] = -18, + [0][0][RTW89_KCC][1][34] = -2, + [0][0][RTW89_KCC][0][34] = -2, + [0][0][RTW89_ACMA][1][34] = 32, + [0][0][RTW89_ACMA][0][34] = -8, + [0][0][RTW89_CHILE][1][34] = -18, + [0][0][RTW89_QATAR][1][34] = 32, + [0][0][RTW89_QATAR][0][34] = -8, + [0][0][RTW89_UK][1][34] = 32, + [0][0][RTW89_UK][0][34] = -8, + [0][0][RTW89_FCC][1][36] = -18, + [0][0][RTW89_FCC][2][36] = 54, + [0][0][RTW89_ETSI][1][36] = 32, + [0][0][RTW89_ETSI][0][36] = -8, + [0][0][RTW89_MKK][1][36] = 30, + [0][0][RTW89_MKK][0][36] = -8, + [0][0][RTW89_IC][1][36] = -18, + [0][0][RTW89_KCC][1][36] = -2, + [0][0][RTW89_KCC][0][36] = -2, + [0][0][RTW89_ACMA][1][36] = 32, + [0][0][RTW89_ACMA][0][36] = -8, + [0][0][RTW89_CHILE][1][36] = -18, + [0][0][RTW89_QATAR][1][36] = 32, + [0][0][RTW89_QATAR][0][36] = -8, + [0][0][RTW89_UK][1][36] = 32, + [0][0][RTW89_UK][0][36] = -8, + [0][0][RTW89_FCC][1][38] = -18, + [0][0][RTW89_FCC][2][38] = 54, + [0][0][RTW89_ETSI][1][38] = 32, + [0][0][RTW89_ETSI][0][38] = -8, + [0][0][RTW89_MKK][1][38] = 30, + [0][0][RTW89_MKK][0][38] = -8, + [0][0][RTW89_IC][1][38] = -18, + [0][0][RTW89_KCC][1][38] = -2, + [0][0][RTW89_KCC][0][38] = -2, + [0][0][RTW89_ACMA][1][38] = 32, + [0][0][RTW89_ACMA][0][38] = -8, + [0][0][RTW89_CHILE][1][38] = -18, + [0][0][RTW89_QATAR][1][38] = 32, + [0][0][RTW89_QATAR][0][38] = -8, + [0][0][RTW89_UK][1][38] = 32, + [0][0][RTW89_UK][0][38] = -8, + [0][0][RTW89_FCC][1][40] = -18, + [0][0][RTW89_FCC][2][40] = 54, + [0][0][RTW89_ETSI][1][40] = 32, + [0][0][RTW89_ETSI][0][40] = -8, + [0][0][RTW89_MKK][1][40] = 30, + [0][0][RTW89_MKK][0][40] = -8, + [0][0][RTW89_IC][1][40] = -18, + [0][0][RTW89_KCC][1][40] = -2, + [0][0][RTW89_KCC][0][40] = -2, + [0][0][RTW89_ACMA][1][40] = 32, + [0][0][RTW89_ACMA][0][40] = -8, + [0][0][RTW89_CHILE][1][40] = -18, + [0][0][RTW89_QATAR][1][40] = 32, + [0][0][RTW89_QATAR][0][40] = -8, + [0][0][RTW89_UK][1][40] = 32, + [0][0][RTW89_UK][0][40] = -8, + [0][0][RTW89_FCC][1][42] = -18, + [0][0][RTW89_FCC][2][42] = 54, + [0][0][RTW89_ETSI][1][42] = 32, + [0][0][RTW89_ETSI][0][42] = -8, + [0][0][RTW89_MKK][1][42] = 30, + [0][0][RTW89_MKK][0][42] = -8, + [0][0][RTW89_IC][1][42] = -18, + [0][0][RTW89_KCC][1][42] = -2, + [0][0][RTW89_KCC][0][42] = -2, + [0][0][RTW89_ACMA][1][42] = 32, + [0][0][RTW89_ACMA][0][42] = -8, + [0][0][RTW89_CHILE][1][42] = -18, + [0][0][RTW89_QATAR][1][42] = 32, + [0][0][RTW89_QATAR][0][42] = -8, + [0][0][RTW89_UK][1][42] = 32, + [0][0][RTW89_UK][0][42] = -8, + [0][0][RTW89_FCC][1][44] = -16, + [0][0][RTW89_FCC][2][44] = 56, + [0][0][RTW89_ETSI][1][44] = 32, + [0][0][RTW89_ETSI][0][44] = -6, + [0][0][RTW89_MKK][1][44] = 8, + [0][0][RTW89_MKK][0][44] = -10, + [0][0][RTW89_IC][1][44] = -16, + [0][0][RTW89_KCC][1][44] = -2, + [0][0][RTW89_KCC][0][44] = -2, + [0][0][RTW89_ACMA][1][44] = 32, + [0][0][RTW89_ACMA][0][44] = -6, + [0][0][RTW89_CHILE][1][44] = -16, + [0][0][RTW89_QATAR][1][44] = 32, + [0][0][RTW89_QATAR][0][44] = -6, + [0][0][RTW89_UK][1][44] = 32, + [0][0][RTW89_UK][0][44] = -6, + [0][0][RTW89_FCC][1][45] = -16, + [0][0][RTW89_FCC][2][45] = 127, + [0][0][RTW89_ETSI][1][45] = 127, + [0][0][RTW89_ETSI][0][45] = 127, + [0][0][RTW89_MKK][1][45] = 127, + [0][0][RTW89_MKK][0][45] = 127, + [0][0][RTW89_IC][1][45] = -16, + [0][0][RTW89_KCC][1][45] = -2, + [0][0][RTW89_KCC][0][45] = 127, + [0][0][RTW89_ACMA][1][45] = 127, + [0][0][RTW89_ACMA][0][45] = 127, + [0][0][RTW89_CHILE][1][45] = 127, + [0][0][RTW89_QATAR][1][45] = 127, + [0][0][RTW89_QATAR][0][45] = 127, + [0][0][RTW89_UK][1][45] = 127, + [0][0][RTW89_UK][0][45] = 127, + [0][0][RTW89_FCC][1][47] = -18, + [0][0][RTW89_FCC][2][47] = 127, + [0][0][RTW89_ETSI][1][47] = 127, + [0][0][RTW89_ETSI][0][47] = 127, + [0][0][RTW89_MKK][1][47] = 127, + [0][0][RTW89_MKK][0][47] = 127, + [0][0][RTW89_IC][1][47] = -18, + [0][0][RTW89_KCC][1][47] = -2, + [0][0][RTW89_KCC][0][47] = 127, + [0][0][RTW89_ACMA][1][47] = 127, + [0][0][RTW89_ACMA][0][47] = 127, + [0][0][RTW89_CHILE][1][47] = 127, + [0][0][RTW89_QATAR][1][47] = 127, + [0][0][RTW89_QATAR][0][47] = 127, + [0][0][RTW89_UK][1][47] = 127, + [0][0][RTW89_UK][0][47] = 127, + [0][0][RTW89_FCC][1][49] = -18, + [0][0][RTW89_FCC][2][49] = 127, + [0][0][RTW89_ETSI][1][49] = 127, + [0][0][RTW89_ETSI][0][49] = 127, + [0][0][RTW89_MKK][1][49] = 127, + [0][0][RTW89_MKK][0][49] = 127, + [0][0][RTW89_IC][1][49] = -18, + [0][0][RTW89_KCC][1][49] = -2, + [0][0][RTW89_KCC][0][49] = 127, + [0][0][RTW89_ACMA][1][49] = 127, + [0][0][RTW89_ACMA][0][49] = 127, + [0][0][RTW89_CHILE][1][49] = 127, + [0][0][RTW89_QATAR][1][49] = 127, + [0][0][RTW89_QATAR][0][49] = 127, + [0][0][RTW89_UK][1][49] = 127, + [0][0][RTW89_UK][0][49] = 127, + [0][0][RTW89_FCC][1][51] = -18, + [0][0][RTW89_FCC][2][51] = 127, + [0][0][RTW89_ETSI][1][51] = 127, + [0][0][RTW89_ETSI][0][51] = 127, + [0][0][RTW89_MKK][1][51] = 127, + [0][0][RTW89_MKK][0][51] = 127, + [0][0][RTW89_IC][1][51] = -18, + [0][0][RTW89_KCC][1][51] = -2, + [0][0][RTW89_KCC][0][51] = 127, + [0][0][RTW89_ACMA][1][51] = 127, + [0][0][RTW89_ACMA][0][51] = 127, + [0][0][RTW89_CHILE][1][51] = 127, + [0][0][RTW89_QATAR][1][51] = 127, + [0][0][RTW89_QATAR][0][51] = 127, + [0][0][RTW89_UK][1][51] = 127, + [0][0][RTW89_UK][0][51] = 127, + [0][0][RTW89_FCC][1][53] = -16, + [0][0][RTW89_FCC][2][53] = 127, + [0][0][RTW89_ETSI][1][53] = 127, + [0][0][RTW89_ETSI][0][53] = 127, + [0][0][RTW89_MKK][1][53] = 127, + [0][0][RTW89_MKK][0][53] = 127, + [0][0][RTW89_IC][1][53] = -16, + [0][0][RTW89_KCC][1][53] = -2, + [0][0][RTW89_KCC][0][53] = 127, + [0][0][RTW89_ACMA][1][53] = 127, + [0][0][RTW89_ACMA][0][53] = 127, + [0][0][RTW89_CHILE][1][53] = 127, + [0][0][RTW89_QATAR][1][53] = 127, + [0][0][RTW89_QATAR][0][53] = 127, + [0][0][RTW89_UK][1][53] = 127, + [0][0][RTW89_UK][0][53] = 127, + [0][0][RTW89_FCC][1][55] = -18, + [0][0][RTW89_FCC][2][55] = 56, + [0][0][RTW89_ETSI][1][55] = 127, + [0][0][RTW89_ETSI][0][55] = 127, + [0][0][RTW89_MKK][1][55] = 127, + [0][0][RTW89_MKK][0][55] = 127, + [0][0][RTW89_IC][1][55] = -18, + [0][0][RTW89_KCC][1][55] = -2, + [0][0][RTW89_KCC][0][55] = 127, + [0][0][RTW89_ACMA][1][55] = 127, + [0][0][RTW89_ACMA][0][55] = 127, + [0][0][RTW89_CHILE][1][55] = 127, + [0][0][RTW89_QATAR][1][55] = 127, + [0][0][RTW89_QATAR][0][55] = 127, + [0][0][RTW89_UK][1][55] = 127, + [0][0][RTW89_UK][0][55] = 127, + [0][0][RTW89_FCC][1][57] = -18, + [0][0][RTW89_FCC][2][57] = 56, + [0][0][RTW89_ETSI][1][57] = 127, + [0][0][RTW89_ETSI][0][57] = 127, + [0][0][RTW89_MKK][1][57] = 127, + [0][0][RTW89_MKK][0][57] = 127, + [0][0][RTW89_IC][1][57] = -18, + [0][0][RTW89_KCC][1][57] = -2, + [0][0][RTW89_KCC][0][57] = 127, + [0][0][RTW89_ACMA][1][57] = 127, + [0][0][RTW89_ACMA][0][57] = 127, + [0][0][RTW89_CHILE][1][57] = 127, + [0][0][RTW89_QATAR][1][57] = 127, + [0][0][RTW89_QATAR][0][57] = 127, + [0][0][RTW89_UK][1][57] = 127, + [0][0][RTW89_UK][0][57] = 127, + [0][0][RTW89_FCC][1][59] = -18, + [0][0][RTW89_FCC][2][59] = 56, + [0][0][RTW89_ETSI][1][59] = 127, + [0][0][RTW89_ETSI][0][59] = 127, + [0][0][RTW89_MKK][1][59] = 127, + [0][0][RTW89_MKK][0][59] = 127, + [0][0][RTW89_IC][1][59] = -18, + [0][0][RTW89_KCC][1][59] = -2, + [0][0][RTW89_KCC][0][59] = 127, + [0][0][RTW89_ACMA][1][59] = 127, + [0][0][RTW89_ACMA][0][59] = 127, + [0][0][RTW89_CHILE][1][59] = 127, + [0][0][RTW89_QATAR][1][59] = 127, + [0][0][RTW89_QATAR][0][59] = 127, + [0][0][RTW89_UK][1][59] = 127, + [0][0][RTW89_UK][0][59] = 127, + [0][0][RTW89_FCC][1][60] = -18, + [0][0][RTW89_FCC][2][60] = 56, + [0][0][RTW89_ETSI][1][60] = 127, + [0][0][RTW89_ETSI][0][60] = 127, + [0][0][RTW89_MKK][1][60] = 127, + [0][0][RTW89_MKK][0][60] = 127, + [0][0][RTW89_IC][1][60] = -18, + [0][0][RTW89_KCC][1][60] = -2, + [0][0][RTW89_KCC][0][60] = 127, + [0][0][RTW89_ACMA][1][60] = 127, + [0][0][RTW89_ACMA][0][60] = 127, + [0][0][RTW89_CHILE][1][60] = 127, + [0][0][RTW89_QATAR][1][60] = 127, + [0][0][RTW89_QATAR][0][60] = 127, + [0][0][RTW89_UK][1][60] = 127, + [0][0][RTW89_UK][0][60] = 127, + [0][0][RTW89_FCC][1][62] = -18, + [0][0][RTW89_FCC][2][62] = 56, + [0][0][RTW89_ETSI][1][62] = 127, + [0][0][RTW89_ETSI][0][62] = 127, + [0][0][RTW89_MKK][1][62] = 127, + [0][0][RTW89_MKK][0][62] = 127, + [0][0][RTW89_IC][1][62] = -18, + [0][0][RTW89_KCC][1][62] = -2, + [0][0][RTW89_KCC][0][62] = 127, + [0][0][RTW89_ACMA][1][62] = 127, + [0][0][RTW89_ACMA][0][62] = 127, + [0][0][RTW89_CHILE][1][62] = 127, + [0][0][RTW89_QATAR][1][62] = 127, + [0][0][RTW89_QATAR][0][62] = 127, + [0][0][RTW89_UK][1][62] = 127, + [0][0][RTW89_UK][0][62] = 127, + [0][0][RTW89_FCC][1][64] = -18, + [0][0][RTW89_FCC][2][64] = 56, + [0][0][RTW89_ETSI][1][64] = 127, + [0][0][RTW89_ETSI][0][64] = 127, + [0][0][RTW89_MKK][1][64] = 127, + [0][0][RTW89_MKK][0][64] = 127, + [0][0][RTW89_IC][1][64] = -18, + [0][0][RTW89_KCC][1][64] = -2, + [0][0][RTW89_KCC][0][64] = 127, + [0][0][RTW89_ACMA][1][64] = 127, + [0][0][RTW89_ACMA][0][64] = 127, + [0][0][RTW89_CHILE][1][64] = 127, + [0][0][RTW89_QATAR][1][64] = 127, + [0][0][RTW89_QATAR][0][64] = 127, + [0][0][RTW89_UK][1][64] = 127, + [0][0][RTW89_UK][0][64] = 127, + [0][0][RTW89_FCC][1][66] = -18, + [0][0][RTW89_FCC][2][66] = 56, + [0][0][RTW89_ETSI][1][66] = 127, + [0][0][RTW89_ETSI][0][66] = 127, + [0][0][RTW89_MKK][1][66] = 127, + [0][0][RTW89_MKK][0][66] = 127, + [0][0][RTW89_IC][1][66] = -18, + [0][0][RTW89_KCC][1][66] = -2, + [0][0][RTW89_KCC][0][66] = 127, + [0][0][RTW89_ACMA][1][66] = 127, + [0][0][RTW89_ACMA][0][66] = 127, + [0][0][RTW89_CHILE][1][66] = 127, + [0][0][RTW89_QATAR][1][66] = 127, + [0][0][RTW89_QATAR][0][66] = 127, + [0][0][RTW89_UK][1][66] = 127, + [0][0][RTW89_UK][0][66] = 127, + [0][0][RTW89_FCC][1][68] = -18, + [0][0][RTW89_FCC][2][68] = 56, + [0][0][RTW89_ETSI][1][68] = 127, + [0][0][RTW89_ETSI][0][68] = 127, + [0][0][RTW89_MKK][1][68] = 127, + [0][0][RTW89_MKK][0][68] = 127, + [0][0][RTW89_IC][1][68] = -18, + [0][0][RTW89_KCC][1][68] = -2, + [0][0][RTW89_KCC][0][68] = 127, + [0][0][RTW89_ACMA][1][68] = 127, + [0][0][RTW89_ACMA][0][68] = 127, + [0][0][RTW89_CHILE][1][68] = 127, + [0][0][RTW89_QATAR][1][68] = 127, + [0][0][RTW89_QATAR][0][68] = 127, + [0][0][RTW89_UK][1][68] = 127, + [0][0][RTW89_UK][0][68] = 127, + [0][0][RTW89_FCC][1][70] = -16, + [0][0][RTW89_FCC][2][70] = 56, + [0][0][RTW89_ETSI][1][70] = 127, + [0][0][RTW89_ETSI][0][70] = 127, + [0][0][RTW89_MKK][1][70] = 127, + [0][0][RTW89_MKK][0][70] = 127, + [0][0][RTW89_IC][1][70] = -16, + [0][0][RTW89_KCC][1][70] = -2, + [0][0][RTW89_KCC][0][70] = 127, + [0][0][RTW89_ACMA][1][70] = 127, + [0][0][RTW89_ACMA][0][70] = 127, + [0][0][RTW89_CHILE][1][70] = 127, + [0][0][RTW89_QATAR][1][70] = 127, + [0][0][RTW89_QATAR][0][70] = 127, + [0][0][RTW89_UK][1][70] = 127, + [0][0][RTW89_UK][0][70] = 127, + [0][0][RTW89_FCC][1][72] = -18, + [0][0][RTW89_FCC][2][72] = 56, + [0][0][RTW89_ETSI][1][72] = 127, + [0][0][RTW89_ETSI][0][72] = 127, + [0][0][RTW89_MKK][1][72] = 127, + [0][0][RTW89_MKK][0][72] = 127, + [0][0][RTW89_IC][1][72] = -18, + [0][0][RTW89_KCC][1][72] = -2, + [0][0][RTW89_KCC][0][72] = 127, + [0][0][RTW89_ACMA][1][72] = 127, + [0][0][RTW89_ACMA][0][72] = 127, + [0][0][RTW89_CHILE][1][72] = 127, + [0][0][RTW89_QATAR][1][72] = 127, + [0][0][RTW89_QATAR][0][72] = 127, + [0][0][RTW89_UK][1][72] = 127, + [0][0][RTW89_UK][0][72] = 127, + [0][0][RTW89_FCC][1][74] = -18, + [0][0][RTW89_FCC][2][74] = 56, + [0][0][RTW89_ETSI][1][74] = 127, + [0][0][RTW89_ETSI][0][74] = 127, + [0][0][RTW89_MKK][1][74] = 127, + [0][0][RTW89_MKK][0][74] = 127, + [0][0][RTW89_IC][1][74] = -18, + [0][0][RTW89_KCC][1][74] = -2, + [0][0][RTW89_KCC][0][74] = 127, + [0][0][RTW89_ACMA][1][74] = 127, + [0][0][RTW89_ACMA][0][74] = 127, + [0][0][RTW89_CHILE][1][74] = 127, + [0][0][RTW89_QATAR][1][74] = 127, + [0][0][RTW89_QATAR][0][74] = 127, + [0][0][RTW89_UK][1][74] = 127, + [0][0][RTW89_UK][0][74] = 127, + [0][0][RTW89_FCC][1][75] = -18, + [0][0][RTW89_FCC][2][75] = 56, + [0][0][RTW89_ETSI][1][75] = 127, + [0][0][RTW89_ETSI][0][75] = 127, + [0][0][RTW89_MKK][1][75] = 127, + [0][0][RTW89_MKK][0][75] = 127, + [0][0][RTW89_IC][1][75] = -18, + [0][0][RTW89_KCC][1][75] = -2, + [0][0][RTW89_KCC][0][75] = 127, + [0][0][RTW89_ACMA][1][75] = 127, + [0][0][RTW89_ACMA][0][75] = 127, + [0][0][RTW89_CHILE][1][75] = 127, + [0][0][RTW89_QATAR][1][75] = 127, + [0][0][RTW89_QATAR][0][75] = 127, + [0][0][RTW89_UK][1][75] = 127, + [0][0][RTW89_UK][0][75] = 127, + [0][0][RTW89_FCC][1][77] = -18, + [0][0][RTW89_FCC][2][77] = 56, + [0][0][RTW89_ETSI][1][77] = 127, + [0][0][RTW89_ETSI][0][77] = 127, + [0][0][RTW89_MKK][1][77] = 127, + [0][0][RTW89_MKK][0][77] = 127, + [0][0][RTW89_IC][1][77] = -18, + [0][0][RTW89_KCC][1][77] = -2, + [0][0][RTW89_KCC][0][77] = 127, + [0][0][RTW89_ACMA][1][77] = 127, + [0][0][RTW89_ACMA][0][77] = 127, + [0][0][RTW89_CHILE][1][77] = 127, + [0][0][RTW89_QATAR][1][77] = 127, + [0][0][RTW89_QATAR][0][77] = 127, + [0][0][RTW89_UK][1][77] = 127, + [0][0][RTW89_UK][0][77] = 127, + [0][0][RTW89_FCC][1][79] = -18, + [0][0][RTW89_FCC][2][79] = 56, + [0][0][RTW89_ETSI][1][79] = 127, + [0][0][RTW89_ETSI][0][79] = 127, + [0][0][RTW89_MKK][1][79] = 127, + [0][0][RTW89_MKK][0][79] = 127, + [0][0][RTW89_IC][1][79] = -18, + [0][0][RTW89_KCC][1][79] = -2, + [0][0][RTW89_KCC][0][79] = 127, + [0][0][RTW89_ACMA][1][79] = 127, + [0][0][RTW89_ACMA][0][79] = 127, + [0][0][RTW89_CHILE][1][79] = 127, + [0][0][RTW89_QATAR][1][79] = 127, + [0][0][RTW89_QATAR][0][79] = 127, + [0][0][RTW89_UK][1][79] = 127, + [0][0][RTW89_UK][0][79] = 127, + [0][0][RTW89_FCC][1][81] = -18, + [0][0][RTW89_FCC][2][81] = 56, + [0][0][RTW89_ETSI][1][81] = 127, + [0][0][RTW89_ETSI][0][81] = 127, + [0][0][RTW89_MKK][1][81] = 127, + [0][0][RTW89_MKK][0][81] = 127, + [0][0][RTW89_IC][1][81] = -18, + [0][0][RTW89_KCC][1][81] = -2, + [0][0][RTW89_KCC][0][81] = 127, + [0][0][RTW89_ACMA][1][81] = 127, + [0][0][RTW89_ACMA][0][81] = 127, + [0][0][RTW89_CHILE][1][81] = 127, + [0][0][RTW89_QATAR][1][81] = 127, + [0][0][RTW89_QATAR][0][81] = 127, + [0][0][RTW89_UK][1][81] = 127, + [0][0][RTW89_UK][0][81] = 127, + [0][0][RTW89_FCC][1][83] = -18, + [0][0][RTW89_FCC][2][83] = 56, + [0][0][RTW89_ETSI][1][83] = 127, + [0][0][RTW89_ETSI][0][83] = 127, + [0][0][RTW89_MKK][1][83] = 127, + [0][0][RTW89_MKK][0][83] = 127, + [0][0][RTW89_IC][1][83] = -18, + [0][0][RTW89_KCC][1][83] = -2, + [0][0][RTW89_KCC][0][83] = 127, + [0][0][RTW89_ACMA][1][83] = 127, + [0][0][RTW89_ACMA][0][83] = 127, + [0][0][RTW89_CHILE][1][83] = 127, + [0][0][RTW89_QATAR][1][83] = 127, + [0][0][RTW89_QATAR][0][83] = 127, + [0][0][RTW89_UK][1][83] = 127, + [0][0][RTW89_UK][0][83] = 127, + [0][0][RTW89_FCC][1][85] = -18, + [0][0][RTW89_FCC][2][85] = 56, + [0][0][RTW89_ETSI][1][85] = 127, + [0][0][RTW89_ETSI][0][85] = 127, + [0][0][RTW89_MKK][1][85] = 127, + [0][0][RTW89_MKK][0][85] = 127, + [0][0][RTW89_IC][1][85] = -18, + [0][0][RTW89_KCC][1][85] = -2, + [0][0][RTW89_KCC][0][85] = 127, + [0][0][RTW89_ACMA][1][85] = 127, + [0][0][RTW89_ACMA][0][85] = 127, + [0][0][RTW89_CHILE][1][85] = 127, + [0][0][RTW89_QATAR][1][85] = 127, + [0][0][RTW89_QATAR][0][85] = 127, + [0][0][RTW89_UK][1][85] = 127, + [0][0][RTW89_UK][0][85] = 127, + [0][0][RTW89_FCC][1][87] = -16, + [0][0][RTW89_FCC][2][87] = 127, + [0][0][RTW89_ETSI][1][87] = 127, + [0][0][RTW89_ETSI][0][87] = 127, + [0][0][RTW89_MKK][1][87] = 127, + [0][0][RTW89_MKK][0][87] = 127, + [0][0][RTW89_IC][1][87] = -16, + [0][0][RTW89_KCC][1][87] = -2, + [0][0][RTW89_KCC][0][87] = 127, + [0][0][RTW89_ACMA][1][87] = 127, + [0][0][RTW89_ACMA][0][87] = 127, + [0][0][RTW89_CHILE][1][87] = 127, + [0][0][RTW89_QATAR][1][87] = 127, + [0][0][RTW89_QATAR][0][87] = 127, + [0][0][RTW89_UK][1][87] = 127, + [0][0][RTW89_UK][0][87] = 127, + [0][0][RTW89_FCC][1][89] = -16, + [0][0][RTW89_FCC][2][89] = 127, + [0][0][RTW89_ETSI][1][89] = 127, + [0][0][RTW89_ETSI][0][89] = 127, + [0][0][RTW89_MKK][1][89] = 127, + [0][0][RTW89_MKK][0][89] = 127, + [0][0][RTW89_IC][1][89] = -16, + [0][0][RTW89_KCC][1][89] = -2, + [0][0][RTW89_KCC][0][89] = 127, + [0][0][RTW89_ACMA][1][89] = 127, + [0][0][RTW89_ACMA][0][89] = 127, + [0][0][RTW89_CHILE][1][89] = 127, + [0][0][RTW89_QATAR][1][89] = 127, + [0][0][RTW89_QATAR][0][89] = 127, + [0][0][RTW89_UK][1][89] = 127, + [0][0][RTW89_UK][0][89] = 127, + [0][0][RTW89_FCC][1][90] = -16, + [0][0][RTW89_FCC][2][90] = 127, + [0][0][RTW89_ETSI][1][90] = 127, + [0][0][RTW89_ETSI][0][90] = 127, + [0][0][RTW89_MKK][1][90] = 127, + [0][0][RTW89_MKK][0][90] = 127, + [0][0][RTW89_IC][1][90] = -16, + [0][0][RTW89_KCC][1][90] = -2, + [0][0][RTW89_KCC][0][90] = 127, + [0][0][RTW89_ACMA][1][90] = 127, + [0][0][RTW89_ACMA][0][90] = 127, + [0][0][RTW89_CHILE][1][90] = 127, + [0][0][RTW89_QATAR][1][90] = 127, + [0][0][RTW89_QATAR][0][90] = 127, + [0][0][RTW89_UK][1][90] = 127, + [0][0][RTW89_UK][0][90] = 127, + [0][0][RTW89_FCC][1][92] = -16, + [0][0][RTW89_FCC][2][92] = 127, + [0][0][RTW89_ETSI][1][92] = 127, + [0][0][RTW89_ETSI][0][92] = 127, + [0][0][RTW89_MKK][1][92] = 127, + [0][0][RTW89_MKK][0][92] = 127, + [0][0][RTW89_IC][1][92] = -16, + [0][0][RTW89_KCC][1][92] = -2, + [0][0][RTW89_KCC][0][92] = 127, + [0][0][RTW89_ACMA][1][92] = 127, + [0][0][RTW89_ACMA][0][92] = 127, + [0][0][RTW89_CHILE][1][92] = 127, + [0][0][RTW89_QATAR][1][92] = 127, + [0][0][RTW89_QATAR][0][92] = 127, + [0][0][RTW89_UK][1][92] = 127, + [0][0][RTW89_UK][0][92] = 127, + [0][0][RTW89_FCC][1][94] = -16, + [0][0][RTW89_FCC][2][94] = 127, + [0][0][RTW89_ETSI][1][94] = 127, + [0][0][RTW89_ETSI][0][94] = 127, + [0][0][RTW89_MKK][1][94] = 127, + [0][0][RTW89_MKK][0][94] = 127, + [0][0][RTW89_IC][1][94] = -16, + [0][0][RTW89_KCC][1][94] = -2, + [0][0][RTW89_KCC][0][94] = 127, + [0][0][RTW89_ACMA][1][94] = 127, + [0][0][RTW89_ACMA][0][94] = 127, + [0][0][RTW89_CHILE][1][94] = 127, + [0][0][RTW89_QATAR][1][94] = 127, + [0][0][RTW89_QATAR][0][94] = 127, + [0][0][RTW89_UK][1][94] = 127, + [0][0][RTW89_UK][0][94] = 127, + [0][0][RTW89_FCC][1][96] = -16, + [0][0][RTW89_FCC][2][96] = 127, + [0][0][RTW89_ETSI][1][96] = 127, + [0][0][RTW89_ETSI][0][96] = 127, + [0][0][RTW89_MKK][1][96] = 127, + [0][0][RTW89_MKK][0][96] = 127, + [0][0][RTW89_IC][1][96] = -16, + [0][0][RTW89_KCC][1][96] = -2, + [0][0][RTW89_KCC][0][96] = 127, + [0][0][RTW89_ACMA][1][96] = 127, + [0][0][RTW89_ACMA][0][96] = 127, + [0][0][RTW89_CHILE][1][96] = 127, + [0][0][RTW89_QATAR][1][96] = 127, + [0][0][RTW89_QATAR][0][96] = 127, + [0][0][RTW89_UK][1][96] = 127, + [0][0][RTW89_UK][0][96] = 127, + [0][0][RTW89_FCC][1][98] = -16, + [0][0][RTW89_FCC][2][98] = 127, + [0][0][RTW89_ETSI][1][98] = 127, + [0][0][RTW89_ETSI][0][98] = 127, + [0][0][RTW89_MKK][1][98] = 127, + [0][0][RTW89_MKK][0][98] = 127, + [0][0][RTW89_IC][1][98] = -16, + [0][0][RTW89_KCC][1][98] = -2, + [0][0][RTW89_KCC][0][98] = 127, + [0][0][RTW89_ACMA][1][98] = 127, + [0][0][RTW89_ACMA][0][98] = 127, + [0][0][RTW89_CHILE][1][98] = 127, + [0][0][RTW89_QATAR][1][98] = 127, + [0][0][RTW89_QATAR][0][98] = 127, + [0][0][RTW89_UK][1][98] = 127, + [0][0][RTW89_UK][0][98] = 127, + [0][0][RTW89_FCC][1][100] = -16, + [0][0][RTW89_FCC][2][100] = 127, + [0][0][RTW89_ETSI][1][100] = 127, + [0][0][RTW89_ETSI][0][100] = 127, + [0][0][RTW89_MKK][1][100] = 127, + [0][0][RTW89_MKK][0][100] = 127, + [0][0][RTW89_IC][1][100] = -16, + [0][0][RTW89_KCC][1][100] = -2, + [0][0][RTW89_KCC][0][100] = 127, + [0][0][RTW89_ACMA][1][100] = 127, + [0][0][RTW89_ACMA][0][100] = 127, + [0][0][RTW89_CHILE][1][100] = 127, + [0][0][RTW89_QATAR][1][100] = 127, + [0][0][RTW89_QATAR][0][100] = 127, + [0][0][RTW89_UK][1][100] = 127, + [0][0][RTW89_UK][0][100] = 127, + [0][0][RTW89_FCC][1][102] = -16, + [0][0][RTW89_FCC][2][102] = 127, + [0][0][RTW89_ETSI][1][102] = 127, + [0][0][RTW89_ETSI][0][102] = 127, + [0][0][RTW89_MKK][1][102] = 127, + [0][0][RTW89_MKK][0][102] = 127, + [0][0][RTW89_IC][1][102] = -16, + [0][0][RTW89_KCC][1][102] = -2, + [0][0][RTW89_KCC][0][102] = 127, + [0][0][RTW89_ACMA][1][102] = 127, + [0][0][RTW89_ACMA][0][102] = 127, + [0][0][RTW89_CHILE][1][102] = 127, + [0][0][RTW89_QATAR][1][102] = 127, + [0][0][RTW89_QATAR][0][102] = 127, + [0][0][RTW89_UK][1][102] = 127, + [0][0][RTW89_UK][0][102] = 127, + [0][0][RTW89_FCC][1][104] = -16, + [0][0][RTW89_FCC][2][104] = 127, + [0][0][RTW89_ETSI][1][104] = 127, + [0][0][RTW89_ETSI][0][104] = 127, + [0][0][RTW89_MKK][1][104] = 127, + [0][0][RTW89_MKK][0][104] = 127, + [0][0][RTW89_IC][1][104] = -16, + [0][0][RTW89_KCC][1][104] = -2, + [0][0][RTW89_KCC][0][104] = 127, + [0][0][RTW89_ACMA][1][104] = 127, + [0][0][RTW89_ACMA][0][104] = 127, + [0][0][RTW89_CHILE][1][104] = 127, + [0][0][RTW89_QATAR][1][104] = 127, + [0][0][RTW89_QATAR][0][104] = 127, + [0][0][RTW89_UK][1][104] = 127, + [0][0][RTW89_UK][0][104] = 127, + [0][0][RTW89_FCC][1][105] = -16, + [0][0][RTW89_FCC][2][105] = 127, + [0][0][RTW89_ETSI][1][105] = 127, + [0][0][RTW89_ETSI][0][105] = 127, + [0][0][RTW89_MKK][1][105] = 127, + [0][0][RTW89_MKK][0][105] = 127, + [0][0][RTW89_IC][1][105] = -16, + [0][0][RTW89_KCC][1][105] = -2, + [0][0][RTW89_KCC][0][105] = 127, + [0][0][RTW89_ACMA][1][105] = 127, + [0][0][RTW89_ACMA][0][105] = 127, + [0][0][RTW89_CHILE][1][105] = 127, + [0][0][RTW89_QATAR][1][105] = 127, + [0][0][RTW89_QATAR][0][105] = 127, + [0][0][RTW89_UK][1][105] = 127, + [0][0][RTW89_UK][0][105] = 127, + [0][0][RTW89_FCC][1][107] = -12, + [0][0][RTW89_FCC][2][107] = 127, + [0][0][RTW89_ETSI][1][107] = 127, + [0][0][RTW89_ETSI][0][107] = 127, + [0][0][RTW89_MKK][1][107] = 127, + [0][0][RTW89_MKK][0][107] = 127, + [0][0][RTW89_IC][1][107] = -12, + [0][0][RTW89_KCC][1][107] = -2, + [0][0][RTW89_KCC][0][107] = 127, + [0][0][RTW89_ACMA][1][107] = 127, + [0][0][RTW89_ACMA][0][107] = 127, + [0][0][RTW89_CHILE][1][107] = 127, + [0][0][RTW89_QATAR][1][107] = 127, + [0][0][RTW89_QATAR][0][107] = 127, + [0][0][RTW89_UK][1][107] = 127, + [0][0][RTW89_UK][0][107] = 127, + [0][0][RTW89_FCC][1][109] = -12, + [0][0][RTW89_FCC][2][109] = 127, + [0][0][RTW89_ETSI][1][109] = 127, + [0][0][RTW89_ETSI][0][109] = 127, + [0][0][RTW89_MKK][1][109] = 127, + [0][0][RTW89_MKK][0][109] = 127, + [0][0][RTW89_IC][1][109] = -12, + [0][0][RTW89_KCC][1][109] = 127, + [0][0][RTW89_KCC][0][109] = 127, + [0][0][RTW89_ACMA][1][109] = 127, + [0][0][RTW89_ACMA][0][109] = 127, + [0][0][RTW89_CHILE][1][109] = 127, + [0][0][RTW89_QATAR][1][109] = 127, + [0][0][RTW89_QATAR][0][109] = 127, + [0][0][RTW89_UK][1][109] = 127, + [0][0][RTW89_UK][0][109] = 127, + [0][0][RTW89_FCC][1][111] = 127, + [0][0][RTW89_FCC][2][111] = 127, + [0][0][RTW89_ETSI][1][111] = 127, + [0][0][RTW89_ETSI][0][111] = 127, + [0][0][RTW89_MKK][1][111] = 127, + [0][0][RTW89_MKK][0][111] = 127, + [0][0][RTW89_IC][1][111] = 127, + [0][0][RTW89_KCC][1][111] = 127, + [0][0][RTW89_KCC][0][111] = 127, + [0][0][RTW89_ACMA][1][111] = 127, + [0][0][RTW89_ACMA][0][111] = 127, + [0][0][RTW89_CHILE][1][111] = 127, + [0][0][RTW89_QATAR][1][111] = 127, + [0][0][RTW89_QATAR][0][111] = 127, + [0][0][RTW89_UK][1][111] = 127, + [0][0][RTW89_UK][0][111] = 127, + [0][0][RTW89_FCC][1][113] = 127, + [0][0][RTW89_FCC][2][113] = 127, + [0][0][RTW89_ETSI][1][113] = 127, + [0][0][RTW89_ETSI][0][113] = 127, + [0][0][RTW89_MKK][1][113] = 127, + [0][0][RTW89_MKK][0][113] = 127, + [0][0][RTW89_IC][1][113] = 127, + [0][0][RTW89_KCC][1][113] = 127, + [0][0][RTW89_KCC][0][113] = 127, + [0][0][RTW89_ACMA][1][113] = 127, + [0][0][RTW89_ACMA][0][113] = 127, + [0][0][RTW89_CHILE][1][113] = 127, + [0][0][RTW89_QATAR][1][113] = 127, + [0][0][RTW89_QATAR][0][113] = 127, + [0][0][RTW89_UK][1][113] = 127, + [0][0][RTW89_UK][0][113] = 127, + [0][0][RTW89_FCC][1][115] = 127, + [0][0][RTW89_FCC][2][115] = 127, + [0][0][RTW89_ETSI][1][115] = 127, + [0][0][RTW89_ETSI][0][115] = 127, + [0][0][RTW89_MKK][1][115] = 127, + [0][0][RTW89_MKK][0][115] = 127, + [0][0][RTW89_IC][1][115] = 127, + [0][0][RTW89_KCC][1][115] = 127, + [0][0][RTW89_KCC][0][115] = 127, + [0][0][RTW89_ACMA][1][115] = 127, + [0][0][RTW89_ACMA][0][115] = 127, + [0][0][RTW89_CHILE][1][115] = 127, + [0][0][RTW89_QATAR][1][115] = 127, + [0][0][RTW89_QATAR][0][115] = 127, + [0][0][RTW89_UK][1][115] = 127, + [0][0][RTW89_UK][0][115] = 127, + [0][0][RTW89_FCC][1][117] = 127, + [0][0][RTW89_FCC][2][117] = 127, + [0][0][RTW89_ETSI][1][117] = 127, + [0][0][RTW89_ETSI][0][117] = 127, + [0][0][RTW89_MKK][1][117] = 127, + [0][0][RTW89_MKK][0][117] = 127, + [0][0][RTW89_IC][1][117] = 127, + [0][0][RTW89_KCC][1][117] = 127, + [0][0][RTW89_KCC][0][117] = 127, + [0][0][RTW89_ACMA][1][117] = 127, + [0][0][RTW89_ACMA][0][117] = 127, + [0][0][RTW89_CHILE][1][117] = 127, + [0][0][RTW89_QATAR][1][117] = 127, + [0][0][RTW89_QATAR][0][117] = 127, + [0][0][RTW89_UK][1][117] = 127, + [0][0][RTW89_UK][0][117] = 127, + [0][0][RTW89_FCC][1][119] = 127, + [0][0][RTW89_FCC][2][119] = 127, + [0][0][RTW89_ETSI][1][119] = 127, + [0][0][RTW89_ETSI][0][119] = 127, + [0][0][RTW89_MKK][1][119] = 127, + [0][0][RTW89_MKK][0][119] = 127, + [0][0][RTW89_IC][1][119] = 127, + [0][0][RTW89_KCC][1][119] = 127, + [0][0][RTW89_KCC][0][119] = 127, + [0][0][RTW89_ACMA][1][119] = 127, + [0][0][RTW89_ACMA][0][119] = 127, + [0][0][RTW89_CHILE][1][119] = 127, + [0][0][RTW89_QATAR][1][119] = 127, + [0][0][RTW89_QATAR][0][119] = 127, + [0][0][RTW89_UK][1][119] = 127, + [0][0][RTW89_UK][0][119] = 127, + [0][1][RTW89_FCC][1][0] = -40, + [0][1][RTW89_FCC][2][0] = 32, + [0][1][RTW89_ETSI][1][0] = 20, + [0][1][RTW89_ETSI][0][0] = -18, + [0][1][RTW89_MKK][1][0] = 18, + [0][1][RTW89_MKK][0][0] = -20, + [0][1][RTW89_IC][1][0] = -40, + [0][1][RTW89_KCC][1][0] = -14, + [0][1][RTW89_KCC][0][0] = -14, + [0][1][RTW89_ACMA][1][0] = 20, + [0][1][RTW89_ACMA][0][0] = -18, + [0][1][RTW89_CHILE][1][0] = -40, + [0][1][RTW89_QATAR][1][0] = 20, + [0][1][RTW89_QATAR][0][0] = -18, + [0][1][RTW89_UK][1][0] = 20, + [0][1][RTW89_UK][0][0] = -18, + [0][1][RTW89_FCC][1][2] = -40, + [0][1][RTW89_FCC][2][2] = 32, + [0][1][RTW89_ETSI][1][2] = 20, + [0][1][RTW89_ETSI][0][2] = -18, + [0][1][RTW89_MKK][1][2] = 18, + [0][1][RTW89_MKK][0][2] = -22, + [0][1][RTW89_IC][1][2] = -40, + [0][1][RTW89_KCC][1][2] = -14, + [0][1][RTW89_KCC][0][2] = -14, + [0][1][RTW89_ACMA][1][2] = 20, + [0][1][RTW89_ACMA][0][2] = -18, + [0][1][RTW89_CHILE][1][2] = -40, + [0][1][RTW89_QATAR][1][2] = 20, + [0][1][RTW89_QATAR][0][2] = -18, + [0][1][RTW89_UK][1][2] = 20, + [0][1][RTW89_UK][0][2] = -18, + [0][1][RTW89_FCC][1][4] = -40, + [0][1][RTW89_FCC][2][4] = 32, + [0][1][RTW89_ETSI][1][4] = 20, + [0][1][RTW89_ETSI][0][4] = -18, + [0][1][RTW89_MKK][1][4] = 18, + [0][1][RTW89_MKK][0][4] = -22, + [0][1][RTW89_IC][1][4] = -40, + [0][1][RTW89_KCC][1][4] = -14, + [0][1][RTW89_KCC][0][4] = -14, + [0][1][RTW89_ACMA][1][4] = 20, + [0][1][RTW89_ACMA][0][4] = -18, + [0][1][RTW89_CHILE][1][4] = -40, + [0][1][RTW89_QATAR][1][4] = 20, + [0][1][RTW89_QATAR][0][4] = -18, + [0][1][RTW89_UK][1][4] = 20, + [0][1][RTW89_UK][0][4] = -18, + [0][1][RTW89_FCC][1][6] = -40, + [0][1][RTW89_FCC][2][6] = 32, + [0][1][RTW89_ETSI][1][6] = 20, + [0][1][RTW89_ETSI][0][6] = -18, + [0][1][RTW89_MKK][1][6] = 18, + [0][1][RTW89_MKK][0][6] = -22, + [0][1][RTW89_IC][1][6] = -40, + [0][1][RTW89_KCC][1][6] = -14, + [0][1][RTW89_KCC][0][6] = -14, + [0][1][RTW89_ACMA][1][6] = 20, + [0][1][RTW89_ACMA][0][6] = -18, + [0][1][RTW89_CHILE][1][6] = -40, + [0][1][RTW89_QATAR][1][6] = 20, + [0][1][RTW89_QATAR][0][6] = -18, + [0][1][RTW89_UK][1][6] = 20, + [0][1][RTW89_UK][0][6] = -18, + [0][1][RTW89_FCC][1][8] = -40, + [0][1][RTW89_FCC][2][8] = 32, + [0][1][RTW89_ETSI][1][8] = 20, + [0][1][RTW89_ETSI][0][8] = -18, + [0][1][RTW89_MKK][1][8] = 18, + [0][1][RTW89_MKK][0][8] = -22, + [0][1][RTW89_IC][1][8] = -40, + [0][1][RTW89_KCC][1][8] = -14, + [0][1][RTW89_KCC][0][8] = -14, + [0][1][RTW89_ACMA][1][8] = 20, + [0][1][RTW89_ACMA][0][8] = -18, + [0][1][RTW89_CHILE][1][8] = -40, + [0][1][RTW89_QATAR][1][8] = 20, + [0][1][RTW89_QATAR][0][8] = -18, + [0][1][RTW89_UK][1][8] = 20, + [0][1][RTW89_UK][0][8] = -18, + [0][1][RTW89_FCC][1][10] = -40, + [0][1][RTW89_FCC][2][10] = 32, + [0][1][RTW89_ETSI][1][10] = 20, + [0][1][RTW89_ETSI][0][10] = -18, + [0][1][RTW89_MKK][1][10] = 18, + [0][1][RTW89_MKK][0][10] = -22, + [0][1][RTW89_IC][1][10] = -40, + [0][1][RTW89_KCC][1][10] = -14, + [0][1][RTW89_KCC][0][10] = -14, + [0][1][RTW89_ACMA][1][10] = 20, + [0][1][RTW89_ACMA][0][10] = -18, + [0][1][RTW89_CHILE][1][10] = -40, + [0][1][RTW89_QATAR][1][10] = 20, + [0][1][RTW89_QATAR][0][10] = -18, + [0][1][RTW89_UK][1][10] = 20, + [0][1][RTW89_UK][0][10] = -18, + [0][1][RTW89_FCC][1][12] = -40, + [0][1][RTW89_FCC][2][12] = 32, + [0][1][RTW89_ETSI][1][12] = 20, + [0][1][RTW89_ETSI][0][12] = -18, + [0][1][RTW89_MKK][1][12] = 18, + [0][1][RTW89_MKK][0][12] = -22, + [0][1][RTW89_IC][1][12] = -40, + [0][1][RTW89_KCC][1][12] = -14, + [0][1][RTW89_KCC][0][12] = -14, + [0][1][RTW89_ACMA][1][12] = 20, + [0][1][RTW89_ACMA][0][12] = -18, + [0][1][RTW89_CHILE][1][12] = -40, + [0][1][RTW89_QATAR][1][12] = 20, + [0][1][RTW89_QATAR][0][12] = -18, + [0][1][RTW89_UK][1][12] = 20, + [0][1][RTW89_UK][0][12] = -18, + [0][1][RTW89_FCC][1][14] = -40, + [0][1][RTW89_FCC][2][14] = 32, + [0][1][RTW89_ETSI][1][14] = 20, + [0][1][RTW89_ETSI][0][14] = -18, + [0][1][RTW89_MKK][1][14] = 18, + [0][1][RTW89_MKK][0][14] = -22, + [0][1][RTW89_IC][1][14] = -40, + [0][1][RTW89_KCC][1][14] = -14, + [0][1][RTW89_KCC][0][14] = -14, + [0][1][RTW89_ACMA][1][14] = 20, + [0][1][RTW89_ACMA][0][14] = -18, + [0][1][RTW89_CHILE][1][14] = -40, + [0][1][RTW89_QATAR][1][14] = 20, + [0][1][RTW89_QATAR][0][14] = -18, + [0][1][RTW89_UK][1][14] = 20, + [0][1][RTW89_UK][0][14] = -18, + [0][1][RTW89_FCC][1][15] = -40, + [0][1][RTW89_FCC][2][15] = 32, + [0][1][RTW89_ETSI][1][15] = 20, + [0][1][RTW89_ETSI][0][15] = -18, + [0][1][RTW89_MKK][1][15] = 18, + [0][1][RTW89_MKK][0][15] = -22, + [0][1][RTW89_IC][1][15] = -40, + [0][1][RTW89_KCC][1][15] = -14, + [0][1][RTW89_KCC][0][15] = -14, + [0][1][RTW89_ACMA][1][15] = 20, + [0][1][RTW89_ACMA][0][15] = -18, + [0][1][RTW89_CHILE][1][15] = -40, + [0][1][RTW89_QATAR][1][15] = 20, + [0][1][RTW89_QATAR][0][15] = -18, + [0][1][RTW89_UK][1][15] = 20, + [0][1][RTW89_UK][0][15] = -18, + [0][1][RTW89_FCC][1][17] = -40, + [0][1][RTW89_FCC][2][17] = 32, + [0][1][RTW89_ETSI][1][17] = 20, + [0][1][RTW89_ETSI][0][17] = -18, + [0][1][RTW89_MKK][1][17] = 18, + [0][1][RTW89_MKK][0][17] = -22, + [0][1][RTW89_IC][1][17] = -40, + [0][1][RTW89_KCC][1][17] = -14, + [0][1][RTW89_KCC][0][17] = -14, + [0][1][RTW89_ACMA][1][17] = 20, + [0][1][RTW89_ACMA][0][17] = -18, + [0][1][RTW89_CHILE][1][17] = -40, + [0][1][RTW89_QATAR][1][17] = 20, + [0][1][RTW89_QATAR][0][17] = -18, + [0][1][RTW89_UK][1][17] = 20, + [0][1][RTW89_UK][0][17] = -18, + [0][1][RTW89_FCC][1][19] = -40, + [0][1][RTW89_FCC][2][19] = 32, + [0][1][RTW89_ETSI][1][19] = 20, + [0][1][RTW89_ETSI][0][19] = -18, + [0][1][RTW89_MKK][1][19] = 18, + [0][1][RTW89_MKK][0][19] = -22, + [0][1][RTW89_IC][1][19] = -40, + [0][1][RTW89_KCC][1][19] = -14, + [0][1][RTW89_KCC][0][19] = -14, + [0][1][RTW89_ACMA][1][19] = 20, + [0][1][RTW89_ACMA][0][19] = -18, + [0][1][RTW89_CHILE][1][19] = -40, + [0][1][RTW89_QATAR][1][19] = 20, + [0][1][RTW89_QATAR][0][19] = -18, + [0][1][RTW89_UK][1][19] = 20, + [0][1][RTW89_UK][0][19] = -18, + [0][1][RTW89_FCC][1][21] = -40, + [0][1][RTW89_FCC][2][21] = 32, + [0][1][RTW89_ETSI][1][21] = 20, + [0][1][RTW89_ETSI][0][21] = -18, + [0][1][RTW89_MKK][1][21] = 18, + [0][1][RTW89_MKK][0][21] = -22, + [0][1][RTW89_IC][1][21] = -40, + [0][1][RTW89_KCC][1][21] = -14, + [0][1][RTW89_KCC][0][21] = -14, + [0][1][RTW89_ACMA][1][21] = 20, + [0][1][RTW89_ACMA][0][21] = -18, + [0][1][RTW89_CHILE][1][21] = -40, + [0][1][RTW89_QATAR][1][21] = 20, + [0][1][RTW89_QATAR][0][21] = -18, + [0][1][RTW89_UK][1][21] = 20, + [0][1][RTW89_UK][0][21] = -18, + [0][1][RTW89_FCC][1][23] = -40, + [0][1][RTW89_FCC][2][23] = 32, + [0][1][RTW89_ETSI][1][23] = 20, + [0][1][RTW89_ETSI][0][23] = -18, + [0][1][RTW89_MKK][1][23] = 18, + [0][1][RTW89_MKK][0][23] = -22, + [0][1][RTW89_IC][1][23] = -40, + [0][1][RTW89_KCC][1][23] = -14, + [0][1][RTW89_KCC][0][23] = -14, + [0][1][RTW89_ACMA][1][23] = 20, + [0][1][RTW89_ACMA][0][23] = -18, + [0][1][RTW89_CHILE][1][23] = -40, + [0][1][RTW89_QATAR][1][23] = 20, + [0][1][RTW89_QATAR][0][23] = -18, + [0][1][RTW89_UK][1][23] = 20, + [0][1][RTW89_UK][0][23] = -18, + [0][1][RTW89_FCC][1][25] = -40, + [0][1][RTW89_FCC][2][25] = 32, + [0][1][RTW89_ETSI][1][25] = 20, + [0][1][RTW89_ETSI][0][25] = -18, + [0][1][RTW89_MKK][1][25] = -4, + [0][1][RTW89_MKK][0][25] = -22, + [0][1][RTW89_IC][1][25] = -40, + [0][1][RTW89_KCC][1][25] = -14, + [0][1][RTW89_KCC][0][25] = -14, + [0][1][RTW89_ACMA][1][25] = 20, + [0][1][RTW89_ACMA][0][25] = -18, + [0][1][RTW89_CHILE][1][25] = -40, + [0][1][RTW89_QATAR][1][25] = 20, + [0][1][RTW89_QATAR][0][25] = -18, + [0][1][RTW89_UK][1][25] = 20, + [0][1][RTW89_UK][0][25] = -18, + [0][1][RTW89_FCC][1][27] = -40, + [0][1][RTW89_FCC][2][27] = 32, + [0][1][RTW89_ETSI][1][27] = 20, + [0][1][RTW89_ETSI][0][27] = -18, + [0][1][RTW89_MKK][1][27] = -4, + [0][1][RTW89_MKK][0][27] = -22, + [0][1][RTW89_IC][1][27] = -40, + [0][1][RTW89_KCC][1][27] = -14, + [0][1][RTW89_KCC][0][27] = -14, + [0][1][RTW89_ACMA][1][27] = 20, + [0][1][RTW89_ACMA][0][27] = -18, + [0][1][RTW89_CHILE][1][27] = -40, + [0][1][RTW89_QATAR][1][27] = 20, + [0][1][RTW89_QATAR][0][27] = -18, + [0][1][RTW89_UK][1][27] = 20, + [0][1][RTW89_UK][0][27] = -18, + [0][1][RTW89_FCC][1][29] = -40, + [0][1][RTW89_FCC][2][29] = 32, + [0][1][RTW89_ETSI][1][29] = 20, + [0][1][RTW89_ETSI][0][29] = -18, + [0][1][RTW89_MKK][1][29] = -4, + [0][1][RTW89_MKK][0][29] = -22, + [0][1][RTW89_IC][1][29] = -40, + [0][1][RTW89_KCC][1][29] = -14, + [0][1][RTW89_KCC][0][29] = -14, + [0][1][RTW89_ACMA][1][29] = 20, + [0][1][RTW89_ACMA][0][29] = -18, + [0][1][RTW89_CHILE][1][29] = -40, + [0][1][RTW89_QATAR][1][29] = 20, + [0][1][RTW89_QATAR][0][29] = -18, + [0][1][RTW89_UK][1][29] = 20, + [0][1][RTW89_UK][0][29] = -18, + [0][1][RTW89_FCC][1][30] = -40, + [0][1][RTW89_FCC][2][30] = 32, + [0][1][RTW89_ETSI][1][30] = 20, + [0][1][RTW89_ETSI][0][30] = -18, + [0][1][RTW89_MKK][1][30] = -4, + [0][1][RTW89_MKK][0][30] = -22, + [0][1][RTW89_IC][1][30] = -40, + [0][1][RTW89_KCC][1][30] = -14, + [0][1][RTW89_KCC][0][30] = -14, + [0][1][RTW89_ACMA][1][30] = 20, + [0][1][RTW89_ACMA][0][30] = -18, + [0][1][RTW89_CHILE][1][30] = -40, + [0][1][RTW89_QATAR][1][30] = 20, + [0][1][RTW89_QATAR][0][30] = -18, + [0][1][RTW89_UK][1][30] = 20, + [0][1][RTW89_UK][0][30] = -18, + [0][1][RTW89_FCC][1][32] = -40, + [0][1][RTW89_FCC][2][32] = 32, + [0][1][RTW89_ETSI][1][32] = 20, + [0][1][RTW89_ETSI][0][32] = -18, + [0][1][RTW89_MKK][1][32] = -4, + [0][1][RTW89_MKK][0][32] = -22, + [0][1][RTW89_IC][1][32] = -40, + [0][1][RTW89_KCC][1][32] = -14, + [0][1][RTW89_KCC][0][32] = -14, + [0][1][RTW89_ACMA][1][32] = 20, + [0][1][RTW89_ACMA][0][32] = -18, + [0][1][RTW89_CHILE][1][32] = -40, + [0][1][RTW89_QATAR][1][32] = 20, + [0][1][RTW89_QATAR][0][32] = -18, + [0][1][RTW89_UK][1][32] = 20, + [0][1][RTW89_UK][0][32] = -18, + [0][1][RTW89_FCC][1][34] = -40, + [0][1][RTW89_FCC][2][34] = 32, + [0][1][RTW89_ETSI][1][34] = 20, + [0][1][RTW89_ETSI][0][34] = -18, + [0][1][RTW89_MKK][1][34] = -4, + [0][1][RTW89_MKK][0][34] = -22, + [0][1][RTW89_IC][1][34] = -40, + [0][1][RTW89_KCC][1][34] = -14, + [0][1][RTW89_KCC][0][34] = -14, + [0][1][RTW89_ACMA][1][34] = 20, + [0][1][RTW89_ACMA][0][34] = -18, + [0][1][RTW89_CHILE][1][34] = -40, + [0][1][RTW89_QATAR][1][34] = 20, + [0][1][RTW89_QATAR][0][34] = -18, + [0][1][RTW89_UK][1][34] = 20, + [0][1][RTW89_UK][0][34] = -18, + [0][1][RTW89_FCC][1][36] = -40, + [0][1][RTW89_FCC][2][36] = 32, + [0][1][RTW89_ETSI][1][36] = 20, + [0][1][RTW89_ETSI][0][36] = -18, + [0][1][RTW89_MKK][1][36] = -4, + [0][1][RTW89_MKK][0][36] = -22, + [0][1][RTW89_IC][1][36] = -40, + [0][1][RTW89_KCC][1][36] = -14, + [0][1][RTW89_KCC][0][36] = -14, + [0][1][RTW89_ACMA][1][36] = 20, + [0][1][RTW89_ACMA][0][36] = -18, + [0][1][RTW89_CHILE][1][36] = -40, + [0][1][RTW89_QATAR][1][36] = 20, + [0][1][RTW89_QATAR][0][36] = -18, + [0][1][RTW89_UK][1][36] = 20, + [0][1][RTW89_UK][0][36] = -18, + [0][1][RTW89_FCC][1][38] = -40, + [0][1][RTW89_FCC][2][38] = 32, + [0][1][RTW89_ETSI][1][38] = 20, + [0][1][RTW89_ETSI][0][38] = -18, + [0][1][RTW89_MKK][1][38] = -4, + [0][1][RTW89_MKK][0][38] = -22, + [0][1][RTW89_IC][1][38] = -40, + [0][1][RTW89_KCC][1][38] = -14, + [0][1][RTW89_KCC][0][38] = -14, + [0][1][RTW89_ACMA][1][38] = 20, + [0][1][RTW89_ACMA][0][38] = -18, + [0][1][RTW89_CHILE][1][38] = -40, + [0][1][RTW89_QATAR][1][38] = 20, + [0][1][RTW89_QATAR][0][38] = -18, + [0][1][RTW89_UK][1][38] = 20, + [0][1][RTW89_UK][0][38] = -18, + [0][1][RTW89_FCC][1][40] = -40, + [0][1][RTW89_FCC][2][40] = 32, + [0][1][RTW89_ETSI][1][40] = 20, + [0][1][RTW89_ETSI][0][40] = -18, + [0][1][RTW89_MKK][1][40] = -4, + [0][1][RTW89_MKK][0][40] = -22, + [0][1][RTW89_IC][1][40] = -40, + [0][1][RTW89_KCC][1][40] = -14, + [0][1][RTW89_KCC][0][40] = -14, + [0][1][RTW89_ACMA][1][40] = 20, + [0][1][RTW89_ACMA][0][40] = -18, + [0][1][RTW89_CHILE][1][40] = -40, + [0][1][RTW89_QATAR][1][40] = 20, + [0][1][RTW89_QATAR][0][40] = -18, + [0][1][RTW89_UK][1][40] = 20, + [0][1][RTW89_UK][0][40] = -18, + [0][1][RTW89_FCC][1][42] = -40, + [0][1][RTW89_FCC][2][42] = 32, + [0][1][RTW89_ETSI][1][42] = 20, + [0][1][RTW89_ETSI][0][42] = -18, + [0][1][RTW89_MKK][1][42] = -4, + [0][1][RTW89_MKK][0][42] = -22, + [0][1][RTW89_IC][1][42] = -40, + [0][1][RTW89_KCC][1][42] = -14, + [0][1][RTW89_KCC][0][42] = -14, + [0][1][RTW89_ACMA][1][42] = 20, + [0][1][RTW89_ACMA][0][42] = -18, + [0][1][RTW89_CHILE][1][42] = -40, + [0][1][RTW89_QATAR][1][42] = 20, + [0][1][RTW89_QATAR][0][42] = -18, + [0][1][RTW89_UK][1][42] = 20, + [0][1][RTW89_UK][0][42] = -18, + [0][1][RTW89_FCC][1][44] = -40, + [0][1][RTW89_FCC][2][44] = 32, + [0][1][RTW89_ETSI][1][44] = 20, + [0][1][RTW89_ETSI][0][44] = -18, + [0][1][RTW89_MKK][1][44] = -4, + [0][1][RTW89_MKK][0][44] = -22, + [0][1][RTW89_IC][1][44] = -40, + [0][1][RTW89_KCC][1][44] = -14, + [0][1][RTW89_KCC][0][44] = -14, + [0][1][RTW89_ACMA][1][44] = 20, + [0][1][RTW89_ACMA][0][44] = -18, + [0][1][RTW89_CHILE][1][44] = -40, + [0][1][RTW89_QATAR][1][44] = 20, + [0][1][RTW89_QATAR][0][44] = -18, + [0][1][RTW89_UK][1][44] = 20, + [0][1][RTW89_UK][0][44] = -18, + [0][1][RTW89_FCC][1][45] = -40, + [0][1][RTW89_FCC][2][45] = 127, + [0][1][RTW89_ETSI][1][45] = 127, + [0][1][RTW89_ETSI][0][45] = 127, + [0][1][RTW89_MKK][1][45] = 127, + [0][1][RTW89_MKK][0][45] = 127, + [0][1][RTW89_IC][1][45] = -40, + [0][1][RTW89_KCC][1][45] = -14, + [0][1][RTW89_KCC][0][45] = 127, + [0][1][RTW89_ACMA][1][45] = 127, + [0][1][RTW89_ACMA][0][45] = 127, + [0][1][RTW89_CHILE][1][45] = 127, + [0][1][RTW89_QATAR][1][45] = 127, + [0][1][RTW89_QATAR][0][45] = 127, + [0][1][RTW89_UK][1][45] = 127, + [0][1][RTW89_UK][0][45] = 127, + [0][1][RTW89_FCC][1][47] = -40, + [0][1][RTW89_FCC][2][47] = 127, + [0][1][RTW89_ETSI][1][47] = 127, + [0][1][RTW89_ETSI][0][47] = 127, + [0][1][RTW89_MKK][1][47] = 127, + [0][1][RTW89_MKK][0][47] = 127, + [0][1][RTW89_IC][1][47] = -40, + [0][1][RTW89_KCC][1][47] = -14, + [0][1][RTW89_KCC][0][47] = 127, + [0][1][RTW89_ACMA][1][47] = 127, + [0][1][RTW89_ACMA][0][47] = 127, + [0][1][RTW89_CHILE][1][47] = 127, + [0][1][RTW89_QATAR][1][47] = 127, + [0][1][RTW89_QATAR][0][47] = 127, + [0][1][RTW89_UK][1][47] = 127, + [0][1][RTW89_UK][0][47] = 127, + [0][1][RTW89_FCC][1][49] = -40, + [0][1][RTW89_FCC][2][49] = 127, + [0][1][RTW89_ETSI][1][49] = 127, + [0][1][RTW89_ETSI][0][49] = 127, + [0][1][RTW89_MKK][1][49] = 127, + [0][1][RTW89_MKK][0][49] = 127, + [0][1][RTW89_IC][1][49] = -40, + [0][1][RTW89_KCC][1][49] = -14, + [0][1][RTW89_KCC][0][49] = 127, + [0][1][RTW89_ACMA][1][49] = 127, + [0][1][RTW89_ACMA][0][49] = 127, + [0][1][RTW89_CHILE][1][49] = 127, + [0][1][RTW89_QATAR][1][49] = 127, + [0][1][RTW89_QATAR][0][49] = 127, + [0][1][RTW89_UK][1][49] = 127, + [0][1][RTW89_UK][0][49] = 127, + [0][1][RTW89_FCC][1][51] = -40, + [0][1][RTW89_FCC][2][51] = 127, + [0][1][RTW89_ETSI][1][51] = 127, + [0][1][RTW89_ETSI][0][51] = 127, + [0][1][RTW89_MKK][1][51] = 127, + [0][1][RTW89_MKK][0][51] = 127, + [0][1][RTW89_IC][1][51] = -40, + [0][1][RTW89_KCC][1][51] = -14, + [0][1][RTW89_KCC][0][51] = 127, + [0][1][RTW89_ACMA][1][51] = 127, + [0][1][RTW89_ACMA][0][51] = 127, + [0][1][RTW89_CHILE][1][51] = 127, + [0][1][RTW89_QATAR][1][51] = 127, + [0][1][RTW89_QATAR][0][51] = 127, + [0][1][RTW89_UK][1][51] = 127, + [0][1][RTW89_UK][0][51] = 127, + [0][1][RTW89_FCC][1][53] = -40, + [0][1][RTW89_FCC][2][53] = 127, + [0][1][RTW89_ETSI][1][53] = 127, + [0][1][RTW89_ETSI][0][53] = 127, + [0][1][RTW89_MKK][1][53] = 127, + [0][1][RTW89_MKK][0][53] = 127, + [0][1][RTW89_IC][1][53] = -40, + [0][1][RTW89_KCC][1][53] = -14, + [0][1][RTW89_KCC][0][53] = 127, + [0][1][RTW89_ACMA][1][53] = 127, + [0][1][RTW89_ACMA][0][53] = 127, + [0][1][RTW89_CHILE][1][53] = 127, + [0][1][RTW89_QATAR][1][53] = 127, + [0][1][RTW89_QATAR][0][53] = 127, + [0][1][RTW89_UK][1][53] = 127, + [0][1][RTW89_UK][0][53] = 127, + [0][1][RTW89_FCC][1][55] = -40, + [0][1][RTW89_FCC][2][55] = 30, + [0][1][RTW89_ETSI][1][55] = 127, + [0][1][RTW89_ETSI][0][55] = 127, + [0][1][RTW89_MKK][1][55] = 127, + [0][1][RTW89_MKK][0][55] = 127, + [0][1][RTW89_IC][1][55] = -40, + [0][1][RTW89_KCC][1][55] = -14, + [0][1][RTW89_KCC][0][55] = 127, + [0][1][RTW89_ACMA][1][55] = 127, + [0][1][RTW89_ACMA][0][55] = 127, + [0][1][RTW89_CHILE][1][55] = 127, + [0][1][RTW89_QATAR][1][55] = 127, + [0][1][RTW89_QATAR][0][55] = 127, + [0][1][RTW89_UK][1][55] = 127, + [0][1][RTW89_UK][0][55] = 127, + [0][1][RTW89_FCC][1][57] = -40, + [0][1][RTW89_FCC][2][57] = 30, + [0][1][RTW89_ETSI][1][57] = 127, + [0][1][RTW89_ETSI][0][57] = 127, + [0][1][RTW89_MKK][1][57] = 127, + [0][1][RTW89_MKK][0][57] = 127, + [0][1][RTW89_IC][1][57] = -40, + [0][1][RTW89_KCC][1][57] = -14, + [0][1][RTW89_KCC][0][57] = 127, + [0][1][RTW89_ACMA][1][57] = 127, + [0][1][RTW89_ACMA][0][57] = 127, + [0][1][RTW89_CHILE][1][57] = 127, + [0][1][RTW89_QATAR][1][57] = 127, + [0][1][RTW89_QATAR][0][57] = 127, + [0][1][RTW89_UK][1][57] = 127, + [0][1][RTW89_UK][0][57] = 127, + [0][1][RTW89_FCC][1][59] = -40, + [0][1][RTW89_FCC][2][59] = 30, + [0][1][RTW89_ETSI][1][59] = 127, + [0][1][RTW89_ETSI][0][59] = 127, + [0][1][RTW89_MKK][1][59] = 127, + [0][1][RTW89_MKK][0][59] = 127, + [0][1][RTW89_IC][1][59] = -40, + [0][1][RTW89_KCC][1][59] = -14, + [0][1][RTW89_KCC][0][59] = 127, + [0][1][RTW89_ACMA][1][59] = 127, + [0][1][RTW89_ACMA][0][59] = 127, + [0][1][RTW89_CHILE][1][59] = 127, + [0][1][RTW89_QATAR][1][59] = 127, + [0][1][RTW89_QATAR][0][59] = 127, + [0][1][RTW89_UK][1][59] = 127, + [0][1][RTW89_UK][0][59] = 127, + [0][1][RTW89_FCC][1][60] = -40, + [0][1][RTW89_FCC][2][60] = 30, + [0][1][RTW89_ETSI][1][60] = 127, + [0][1][RTW89_ETSI][0][60] = 127, + [0][1][RTW89_MKK][1][60] = 127, + [0][1][RTW89_MKK][0][60] = 127, + [0][1][RTW89_IC][1][60] = -40, + [0][1][RTW89_KCC][1][60] = -14, + [0][1][RTW89_KCC][0][60] = 127, + [0][1][RTW89_ACMA][1][60] = 127, + [0][1][RTW89_ACMA][0][60] = 127, + [0][1][RTW89_CHILE][1][60] = 127, + [0][1][RTW89_QATAR][1][60] = 127, + [0][1][RTW89_QATAR][0][60] = 127, + [0][1][RTW89_UK][1][60] = 127, + [0][1][RTW89_UK][0][60] = 127, + [0][1][RTW89_FCC][1][62] = -40, + [0][1][RTW89_FCC][2][62] = 30, + [0][1][RTW89_ETSI][1][62] = 127, + [0][1][RTW89_ETSI][0][62] = 127, + [0][1][RTW89_MKK][1][62] = 127, + [0][1][RTW89_MKK][0][62] = 127, + [0][1][RTW89_IC][1][62] = -40, + [0][1][RTW89_KCC][1][62] = -14, + [0][1][RTW89_KCC][0][62] = 127, + [0][1][RTW89_ACMA][1][62] = 127, + [0][1][RTW89_ACMA][0][62] = 127, + [0][1][RTW89_CHILE][1][62] = 127, + [0][1][RTW89_QATAR][1][62] = 127, + [0][1][RTW89_QATAR][0][62] = 127, + [0][1][RTW89_UK][1][62] = 127, + [0][1][RTW89_UK][0][62] = 127, + [0][1][RTW89_FCC][1][64] = -40, + [0][1][RTW89_FCC][2][64] = 30, + [0][1][RTW89_ETSI][1][64] = 127, + [0][1][RTW89_ETSI][0][64] = 127, + [0][1][RTW89_MKK][1][64] = 127, + [0][1][RTW89_MKK][0][64] = 127, + [0][1][RTW89_IC][1][64] = -40, + [0][1][RTW89_KCC][1][64] = -14, + [0][1][RTW89_KCC][0][64] = 127, + [0][1][RTW89_ACMA][1][64] = 127, + [0][1][RTW89_ACMA][0][64] = 127, + [0][1][RTW89_CHILE][1][64] = 127, + [0][1][RTW89_QATAR][1][64] = 127, + [0][1][RTW89_QATAR][0][64] = 127, + [0][1][RTW89_UK][1][64] = 127, + [0][1][RTW89_UK][0][64] = 127, + [0][1][RTW89_FCC][1][66] = -40, + [0][1][RTW89_FCC][2][66] = 30, + [0][1][RTW89_ETSI][1][66] = 127, + [0][1][RTW89_ETSI][0][66] = 127, + [0][1][RTW89_MKK][1][66] = 127, + [0][1][RTW89_MKK][0][66] = 127, + [0][1][RTW89_IC][1][66] = -40, + [0][1][RTW89_KCC][1][66] = -14, + [0][1][RTW89_KCC][0][66] = 127, + [0][1][RTW89_ACMA][1][66] = 127, + [0][1][RTW89_ACMA][0][66] = 127, + [0][1][RTW89_CHILE][1][66] = 127, + [0][1][RTW89_QATAR][1][66] = 127, + [0][1][RTW89_QATAR][0][66] = 127, + [0][1][RTW89_UK][1][66] = 127, + [0][1][RTW89_UK][0][66] = 127, + [0][1][RTW89_FCC][1][68] = -40, + [0][1][RTW89_FCC][2][68] = 30, + [0][1][RTW89_ETSI][1][68] = 127, + [0][1][RTW89_ETSI][0][68] = 127, + [0][1][RTW89_MKK][1][68] = 127, + [0][1][RTW89_MKK][0][68] = 127, + [0][1][RTW89_IC][1][68] = -40, + [0][1][RTW89_KCC][1][68] = -14, + [0][1][RTW89_KCC][0][68] = 127, + [0][1][RTW89_ACMA][1][68] = 127, + [0][1][RTW89_ACMA][0][68] = 127, + [0][1][RTW89_CHILE][1][68] = 127, + [0][1][RTW89_QATAR][1][68] = 127, + [0][1][RTW89_QATAR][0][68] = 127, + [0][1][RTW89_UK][1][68] = 127, + [0][1][RTW89_UK][0][68] = 127, + [0][1][RTW89_FCC][1][70] = -38, + [0][1][RTW89_FCC][2][70] = 30, + [0][1][RTW89_ETSI][1][70] = 127, + [0][1][RTW89_ETSI][0][70] = 127, + [0][1][RTW89_MKK][1][70] = 127, + [0][1][RTW89_MKK][0][70] = 127, + [0][1][RTW89_IC][1][70] = -38, + [0][1][RTW89_KCC][1][70] = -14, + [0][1][RTW89_KCC][0][70] = 127, + [0][1][RTW89_ACMA][1][70] = 127, + [0][1][RTW89_ACMA][0][70] = 127, + [0][1][RTW89_CHILE][1][70] = 127, + [0][1][RTW89_QATAR][1][70] = 127, + [0][1][RTW89_QATAR][0][70] = 127, + [0][1][RTW89_UK][1][70] = 127, + [0][1][RTW89_UK][0][70] = 127, + [0][1][RTW89_FCC][1][72] = -38, + [0][1][RTW89_FCC][2][72] = 30, + [0][1][RTW89_ETSI][1][72] = 127, + [0][1][RTW89_ETSI][0][72] = 127, + [0][1][RTW89_MKK][1][72] = 127, + [0][1][RTW89_MKK][0][72] = 127, + [0][1][RTW89_IC][1][72] = -38, + [0][1][RTW89_KCC][1][72] = -14, + [0][1][RTW89_KCC][0][72] = 127, + [0][1][RTW89_ACMA][1][72] = 127, + [0][1][RTW89_ACMA][0][72] = 127, + [0][1][RTW89_CHILE][1][72] = 127, + [0][1][RTW89_QATAR][1][72] = 127, + [0][1][RTW89_QATAR][0][72] = 127, + [0][1][RTW89_UK][1][72] = 127, + [0][1][RTW89_UK][0][72] = 127, + [0][1][RTW89_FCC][1][74] = -38, + [0][1][RTW89_FCC][2][74] = 30, + [0][1][RTW89_ETSI][1][74] = 127, + [0][1][RTW89_ETSI][0][74] = 127, + [0][1][RTW89_MKK][1][74] = 127, + [0][1][RTW89_MKK][0][74] = 127, + [0][1][RTW89_IC][1][74] = -38, + [0][1][RTW89_KCC][1][74] = -14, + [0][1][RTW89_KCC][0][74] = 127, + [0][1][RTW89_ACMA][1][74] = 127, + [0][1][RTW89_ACMA][0][74] = 127, + [0][1][RTW89_CHILE][1][74] = 127, + [0][1][RTW89_QATAR][1][74] = 127, + [0][1][RTW89_QATAR][0][74] = 127, + [0][1][RTW89_UK][1][74] = 127, + [0][1][RTW89_UK][0][74] = 127, + [0][1][RTW89_FCC][1][75] = -38, + [0][1][RTW89_FCC][2][75] = 30, + [0][1][RTW89_ETSI][1][75] = 127, + [0][1][RTW89_ETSI][0][75] = 127, + [0][1][RTW89_MKK][1][75] = 127, + [0][1][RTW89_MKK][0][75] = 127, + [0][1][RTW89_IC][1][75] = -38, + [0][1][RTW89_KCC][1][75] = -14, + [0][1][RTW89_KCC][0][75] = 127, + [0][1][RTW89_ACMA][1][75] = 127, + [0][1][RTW89_ACMA][0][75] = 127, + [0][1][RTW89_CHILE][1][75] = 127, + [0][1][RTW89_QATAR][1][75] = 127, + [0][1][RTW89_QATAR][0][75] = 127, + [0][1][RTW89_UK][1][75] = 127, + [0][1][RTW89_UK][0][75] = 127, + [0][1][RTW89_FCC][1][77] = -38, + [0][1][RTW89_FCC][2][77] = 30, + [0][1][RTW89_ETSI][1][77] = 127, + [0][1][RTW89_ETSI][0][77] = 127, + [0][1][RTW89_MKK][1][77] = 127, + [0][1][RTW89_MKK][0][77] = 127, + [0][1][RTW89_IC][1][77] = -38, + [0][1][RTW89_KCC][1][77] = -14, + [0][1][RTW89_KCC][0][77] = 127, + [0][1][RTW89_ACMA][1][77] = 127, + [0][1][RTW89_ACMA][0][77] = 127, + [0][1][RTW89_CHILE][1][77] = 127, + [0][1][RTW89_QATAR][1][77] = 127, + [0][1][RTW89_QATAR][0][77] = 127, + [0][1][RTW89_UK][1][77] = 127, + [0][1][RTW89_UK][0][77] = 127, + [0][1][RTW89_FCC][1][79] = -38, + [0][1][RTW89_FCC][2][79] = 30, + [0][1][RTW89_ETSI][1][79] = 127, + [0][1][RTW89_ETSI][0][79] = 127, + [0][1][RTW89_MKK][1][79] = 127, + [0][1][RTW89_MKK][0][79] = 127, + [0][1][RTW89_IC][1][79] = -38, + [0][1][RTW89_KCC][1][79] = -14, + [0][1][RTW89_KCC][0][79] = 127, + [0][1][RTW89_ACMA][1][79] = 127, + [0][1][RTW89_ACMA][0][79] = 127, + [0][1][RTW89_CHILE][1][79] = 127, + [0][1][RTW89_QATAR][1][79] = 127, + [0][1][RTW89_QATAR][0][79] = 127, + [0][1][RTW89_UK][1][79] = 127, + [0][1][RTW89_UK][0][79] = 127, + [0][1][RTW89_FCC][1][81] = -38, + [0][1][RTW89_FCC][2][81] = 30, + [0][1][RTW89_ETSI][1][81] = 127, + [0][1][RTW89_ETSI][0][81] = 127, + [0][1][RTW89_MKK][1][81] = 127, + [0][1][RTW89_MKK][0][81] = 127, + [0][1][RTW89_IC][1][81] = -38, + [0][1][RTW89_KCC][1][81] = -14, + [0][1][RTW89_KCC][0][81] = 127, + [0][1][RTW89_ACMA][1][81] = 127, + [0][1][RTW89_ACMA][0][81] = 127, + [0][1][RTW89_CHILE][1][81] = 127, + [0][1][RTW89_QATAR][1][81] = 127, + [0][1][RTW89_QATAR][0][81] = 127, + [0][1][RTW89_UK][1][81] = 127, + [0][1][RTW89_UK][0][81] = 127, + [0][1][RTW89_FCC][1][83] = -38, + [0][1][RTW89_FCC][2][83] = 30, + [0][1][RTW89_ETSI][1][83] = 127, + [0][1][RTW89_ETSI][0][83] = 127, + [0][1][RTW89_MKK][1][83] = 127, + [0][1][RTW89_MKK][0][83] = 127, + [0][1][RTW89_IC][1][83] = -38, + [0][1][RTW89_KCC][1][83] = -14, + [0][1][RTW89_KCC][0][83] = 127, + [0][1][RTW89_ACMA][1][83] = 127, + [0][1][RTW89_ACMA][0][83] = 127, + [0][1][RTW89_CHILE][1][83] = 127, + [0][1][RTW89_QATAR][1][83] = 127, + [0][1][RTW89_QATAR][0][83] = 127, + [0][1][RTW89_UK][1][83] = 127, + [0][1][RTW89_UK][0][83] = 127, + [0][1][RTW89_FCC][1][85] = -38, + [0][1][RTW89_FCC][2][85] = 30, + [0][1][RTW89_ETSI][1][85] = 127, + [0][1][RTW89_ETSI][0][85] = 127, + [0][1][RTW89_MKK][1][85] = 127, + [0][1][RTW89_MKK][0][85] = 127, + [0][1][RTW89_IC][1][85] = -38, + [0][1][RTW89_KCC][1][85] = -14, + [0][1][RTW89_KCC][0][85] = 127, + [0][1][RTW89_ACMA][1][85] = 127, + [0][1][RTW89_ACMA][0][85] = 127, + [0][1][RTW89_CHILE][1][85] = 127, + [0][1][RTW89_QATAR][1][85] = 127, + [0][1][RTW89_QATAR][0][85] = 127, + [0][1][RTW89_UK][1][85] = 127, + [0][1][RTW89_UK][0][85] = 127, + [0][1][RTW89_FCC][1][87] = -40, + [0][1][RTW89_FCC][2][87] = 127, + [0][1][RTW89_ETSI][1][87] = 127, + [0][1][RTW89_ETSI][0][87] = 127, + [0][1][RTW89_MKK][1][87] = 127, + [0][1][RTW89_MKK][0][87] = 127, + [0][1][RTW89_IC][1][87] = -40, + [0][1][RTW89_KCC][1][87] = -14, + [0][1][RTW89_KCC][0][87] = 127, + [0][1][RTW89_ACMA][1][87] = 127, + [0][1][RTW89_ACMA][0][87] = 127, + [0][1][RTW89_CHILE][1][87] = 127, + [0][1][RTW89_QATAR][1][87] = 127, + [0][1][RTW89_QATAR][0][87] = 127, + [0][1][RTW89_UK][1][87] = 127, + [0][1][RTW89_UK][0][87] = 127, + [0][1][RTW89_FCC][1][89] = -38, + [0][1][RTW89_FCC][2][89] = 127, + [0][1][RTW89_ETSI][1][89] = 127, + [0][1][RTW89_ETSI][0][89] = 127, + [0][1][RTW89_MKK][1][89] = 127, + [0][1][RTW89_MKK][0][89] = 127, + [0][1][RTW89_IC][1][89] = -38, + [0][1][RTW89_KCC][1][89] = -14, + [0][1][RTW89_KCC][0][89] = 127, + [0][1][RTW89_ACMA][1][89] = 127, + [0][1][RTW89_ACMA][0][89] = 127, + [0][1][RTW89_CHILE][1][89] = 127, + [0][1][RTW89_QATAR][1][89] = 127, + [0][1][RTW89_QATAR][0][89] = 127, + [0][1][RTW89_UK][1][89] = 127, + [0][1][RTW89_UK][0][89] = 127, + [0][1][RTW89_FCC][1][90] = -38, + [0][1][RTW89_FCC][2][90] = 127, + [0][1][RTW89_ETSI][1][90] = 127, + [0][1][RTW89_ETSI][0][90] = 127, + [0][1][RTW89_MKK][1][90] = 127, + [0][1][RTW89_MKK][0][90] = 127, + [0][1][RTW89_IC][1][90] = -38, + [0][1][RTW89_KCC][1][90] = -14, + [0][1][RTW89_KCC][0][90] = 127, + [0][1][RTW89_ACMA][1][90] = 127, + [0][1][RTW89_ACMA][0][90] = 127, + [0][1][RTW89_CHILE][1][90] = 127, + [0][1][RTW89_QATAR][1][90] = 127, + [0][1][RTW89_QATAR][0][90] = 127, + [0][1][RTW89_UK][1][90] = 127, + [0][1][RTW89_UK][0][90] = 127, + [0][1][RTW89_FCC][1][92] = -38, + [0][1][RTW89_FCC][2][92] = 127, + [0][1][RTW89_ETSI][1][92] = 127, + [0][1][RTW89_ETSI][0][92] = 127, + [0][1][RTW89_MKK][1][92] = 127, + [0][1][RTW89_MKK][0][92] = 127, + [0][1][RTW89_IC][1][92] = -38, + [0][1][RTW89_KCC][1][92] = -14, + [0][1][RTW89_KCC][0][92] = 127, + [0][1][RTW89_ACMA][1][92] = 127, + [0][1][RTW89_ACMA][0][92] = 127, + [0][1][RTW89_CHILE][1][92] = 127, + [0][1][RTW89_QATAR][1][92] = 127, + [0][1][RTW89_QATAR][0][92] = 127, + [0][1][RTW89_UK][1][92] = 127, + [0][1][RTW89_UK][0][92] = 127, + [0][1][RTW89_FCC][1][94] = -38, + [0][1][RTW89_FCC][2][94] = 127, + [0][1][RTW89_ETSI][1][94] = 127, + [0][1][RTW89_ETSI][0][94] = 127, + [0][1][RTW89_MKK][1][94] = 127, + [0][1][RTW89_MKK][0][94] = 127, + [0][1][RTW89_IC][1][94] = -38, + [0][1][RTW89_KCC][1][94] = -14, + [0][1][RTW89_KCC][0][94] = 127, + [0][1][RTW89_ACMA][1][94] = 127, + [0][1][RTW89_ACMA][0][94] = 127, + [0][1][RTW89_CHILE][1][94] = 127, + [0][1][RTW89_QATAR][1][94] = 127, + [0][1][RTW89_QATAR][0][94] = 127, + [0][1][RTW89_UK][1][94] = 127, + [0][1][RTW89_UK][0][94] = 127, + [0][1][RTW89_FCC][1][96] = -38, + [0][1][RTW89_FCC][2][96] = 127, + [0][1][RTW89_ETSI][1][96] = 127, + [0][1][RTW89_ETSI][0][96] = 127, + [0][1][RTW89_MKK][1][96] = 127, + [0][1][RTW89_MKK][0][96] = 127, + [0][1][RTW89_IC][1][96] = -38, + [0][1][RTW89_KCC][1][96] = -14, + [0][1][RTW89_KCC][0][96] = 127, + [0][1][RTW89_ACMA][1][96] = 127, + [0][1][RTW89_ACMA][0][96] = 127, + [0][1][RTW89_CHILE][1][96] = 127, + [0][1][RTW89_QATAR][1][96] = 127, + [0][1][RTW89_QATAR][0][96] = 127, + [0][1][RTW89_UK][1][96] = 127, + [0][1][RTW89_UK][0][96] = 127, + [0][1][RTW89_FCC][1][98] = -38, + [0][1][RTW89_FCC][2][98] = 127, + [0][1][RTW89_ETSI][1][98] = 127, + [0][1][RTW89_ETSI][0][98] = 127, + [0][1][RTW89_MKK][1][98] = 127, + [0][1][RTW89_MKK][0][98] = 127, + [0][1][RTW89_IC][1][98] = -38, + [0][1][RTW89_KCC][1][98] = -14, + [0][1][RTW89_KCC][0][98] = 127, + [0][1][RTW89_ACMA][1][98] = 127, + [0][1][RTW89_ACMA][0][98] = 127, + [0][1][RTW89_CHILE][1][98] = 127, + [0][1][RTW89_QATAR][1][98] = 127, + [0][1][RTW89_QATAR][0][98] = 127, + [0][1][RTW89_UK][1][98] = 127, + [0][1][RTW89_UK][0][98] = 127, + [0][1][RTW89_FCC][1][100] = -38, + [0][1][RTW89_FCC][2][100] = 127, + [0][1][RTW89_ETSI][1][100] = 127, + [0][1][RTW89_ETSI][0][100] = 127, + [0][1][RTW89_MKK][1][100] = 127, + [0][1][RTW89_MKK][0][100] = 127, + [0][1][RTW89_IC][1][100] = -38, + [0][1][RTW89_KCC][1][100] = -14, + [0][1][RTW89_KCC][0][100] = 127, + [0][1][RTW89_ACMA][1][100] = 127, + [0][1][RTW89_ACMA][0][100] = 127, + [0][1][RTW89_CHILE][1][100] = 127, + [0][1][RTW89_QATAR][1][100] = 127, + [0][1][RTW89_QATAR][0][100] = 127, + [0][1][RTW89_UK][1][100] = 127, + [0][1][RTW89_UK][0][100] = 127, + [0][1][RTW89_FCC][1][102] = -38, + [0][1][RTW89_FCC][2][102] = 127, + [0][1][RTW89_ETSI][1][102] = 127, + [0][1][RTW89_ETSI][0][102] = 127, + [0][1][RTW89_MKK][1][102] = 127, + [0][1][RTW89_MKK][0][102] = 127, + [0][1][RTW89_IC][1][102] = -38, + [0][1][RTW89_KCC][1][102] = -14, + [0][1][RTW89_KCC][0][102] = 127, + [0][1][RTW89_ACMA][1][102] = 127, + [0][1][RTW89_ACMA][0][102] = 127, + [0][1][RTW89_CHILE][1][102] = 127, + [0][1][RTW89_QATAR][1][102] = 127, + [0][1][RTW89_QATAR][0][102] = 127, + [0][1][RTW89_UK][1][102] = 127, + [0][1][RTW89_UK][0][102] = 127, + [0][1][RTW89_FCC][1][104] = -38, + [0][1][RTW89_FCC][2][104] = 127, + [0][1][RTW89_ETSI][1][104] = 127, + [0][1][RTW89_ETSI][0][104] = 127, + [0][1][RTW89_MKK][1][104] = 127, + [0][1][RTW89_MKK][0][104] = 127, + [0][1][RTW89_IC][1][104] = -38, + [0][1][RTW89_KCC][1][104] = -14, + [0][1][RTW89_KCC][0][104] = 127, + [0][1][RTW89_ACMA][1][104] = 127, + [0][1][RTW89_ACMA][0][104] = 127, + [0][1][RTW89_CHILE][1][104] = 127, + [0][1][RTW89_QATAR][1][104] = 127, + [0][1][RTW89_QATAR][0][104] = 127, + [0][1][RTW89_UK][1][104] = 127, + [0][1][RTW89_UK][0][104] = 127, + [0][1][RTW89_FCC][1][105] = -38, + [0][1][RTW89_FCC][2][105] = 127, + [0][1][RTW89_ETSI][1][105] = 127, + [0][1][RTW89_ETSI][0][105] = 127, + [0][1][RTW89_MKK][1][105] = 127, + [0][1][RTW89_MKK][0][105] = 127, + [0][1][RTW89_IC][1][105] = -38, + [0][1][RTW89_KCC][1][105] = -14, + [0][1][RTW89_KCC][0][105] = 127, + [0][1][RTW89_ACMA][1][105] = 127, + [0][1][RTW89_ACMA][0][105] = 127, + [0][1][RTW89_CHILE][1][105] = 127, + [0][1][RTW89_QATAR][1][105] = 127, + [0][1][RTW89_QATAR][0][105] = 127, + [0][1][RTW89_UK][1][105] = 127, + [0][1][RTW89_UK][0][105] = 127, + [0][1][RTW89_FCC][1][107] = -34, + [0][1][RTW89_FCC][2][107] = 127, + [0][1][RTW89_ETSI][1][107] = 127, + [0][1][RTW89_ETSI][0][107] = 127, + [0][1][RTW89_MKK][1][107] = 127, + [0][1][RTW89_MKK][0][107] = 127, + [0][1][RTW89_IC][1][107] = -34, + [0][1][RTW89_KCC][1][107] = -14, + [0][1][RTW89_KCC][0][107] = 127, + [0][1][RTW89_ACMA][1][107] = 127, + [0][1][RTW89_ACMA][0][107] = 127, + [0][1][RTW89_CHILE][1][107] = 127, + [0][1][RTW89_QATAR][1][107] = 127, + [0][1][RTW89_QATAR][0][107] = 127, + [0][1][RTW89_UK][1][107] = 127, + [0][1][RTW89_UK][0][107] = 127, + [0][1][RTW89_FCC][1][109] = -34, + [0][1][RTW89_FCC][2][109] = 127, + [0][1][RTW89_ETSI][1][109] = 127, + [0][1][RTW89_ETSI][0][109] = 127, + [0][1][RTW89_MKK][1][109] = 127, + [0][1][RTW89_MKK][0][109] = 127, + [0][1][RTW89_IC][1][109] = -34, + [0][1][RTW89_KCC][1][109] = 127, + [0][1][RTW89_KCC][0][109] = 127, + [0][1][RTW89_ACMA][1][109] = 127, + [0][1][RTW89_ACMA][0][109] = 127, + [0][1][RTW89_CHILE][1][109] = 127, + [0][1][RTW89_QATAR][1][109] = 127, + [0][1][RTW89_QATAR][0][109] = 127, + [0][1][RTW89_UK][1][109] = 127, + [0][1][RTW89_UK][0][109] = 127, + [0][1][RTW89_FCC][1][111] = 127, + [0][1][RTW89_FCC][2][111] = 127, + [0][1][RTW89_ETSI][1][111] = 127, + [0][1][RTW89_ETSI][0][111] = 127, + [0][1][RTW89_MKK][1][111] = 127, + [0][1][RTW89_MKK][0][111] = 127, + [0][1][RTW89_IC][1][111] = 127, + [0][1][RTW89_KCC][1][111] = 127, + [0][1][RTW89_KCC][0][111] = 127, + [0][1][RTW89_ACMA][1][111] = 127, + [0][1][RTW89_ACMA][0][111] = 127, + [0][1][RTW89_CHILE][1][111] = 127, + [0][1][RTW89_QATAR][1][111] = 127, + [0][1][RTW89_QATAR][0][111] = 127, + [0][1][RTW89_UK][1][111] = 127, + [0][1][RTW89_UK][0][111] = 127, + [0][1][RTW89_FCC][1][113] = 127, + [0][1][RTW89_FCC][2][113] = 127, + [0][1][RTW89_ETSI][1][113] = 127, + [0][1][RTW89_ETSI][0][113] = 127, + [0][1][RTW89_MKK][1][113] = 127, + [0][1][RTW89_MKK][0][113] = 127, + [0][1][RTW89_IC][1][113] = 127, + [0][1][RTW89_KCC][1][113] = 127, + [0][1][RTW89_KCC][0][113] = 127, + [0][1][RTW89_ACMA][1][113] = 127, + [0][1][RTW89_ACMA][0][113] = 127, + [0][1][RTW89_CHILE][1][113] = 127, + [0][1][RTW89_QATAR][1][113] = 127, + [0][1][RTW89_QATAR][0][113] = 127, + [0][1][RTW89_UK][1][113] = 127, + [0][1][RTW89_UK][0][113] = 127, + [0][1][RTW89_FCC][1][115] = 127, + [0][1][RTW89_FCC][2][115] = 127, + [0][1][RTW89_ETSI][1][115] = 127, + [0][1][RTW89_ETSI][0][115] = 127, + [0][1][RTW89_MKK][1][115] = 127, + [0][1][RTW89_MKK][0][115] = 127, + [0][1][RTW89_IC][1][115] = 127, + [0][1][RTW89_KCC][1][115] = 127, + [0][1][RTW89_KCC][0][115] = 127, + [0][1][RTW89_ACMA][1][115] = 127, + [0][1][RTW89_ACMA][0][115] = 127, + [0][1][RTW89_CHILE][1][115] = 127, + [0][1][RTW89_QATAR][1][115] = 127, + [0][1][RTW89_QATAR][0][115] = 127, + [0][1][RTW89_UK][1][115] = 127, + [0][1][RTW89_UK][0][115] = 127, + [0][1][RTW89_FCC][1][117] = 127, + [0][1][RTW89_FCC][2][117] = 127, + [0][1][RTW89_ETSI][1][117] = 127, + [0][1][RTW89_ETSI][0][117] = 127, + [0][1][RTW89_MKK][1][117] = 127, + [0][1][RTW89_MKK][0][117] = 127, + [0][1][RTW89_IC][1][117] = 127, + [0][1][RTW89_KCC][1][117] = 127, + [0][1][RTW89_KCC][0][117] = 127, + [0][1][RTW89_ACMA][1][117] = 127, + [0][1][RTW89_ACMA][0][117] = 127, + [0][1][RTW89_CHILE][1][117] = 127, + [0][1][RTW89_QATAR][1][117] = 127, + [0][1][RTW89_QATAR][0][117] = 127, + [0][1][RTW89_UK][1][117] = 127, + [0][1][RTW89_UK][0][117] = 127, + [0][1][RTW89_FCC][1][119] = 127, + [0][1][RTW89_FCC][2][119] = 127, + [0][1][RTW89_ETSI][1][119] = 127, + [0][1][RTW89_ETSI][0][119] = 127, + [0][1][RTW89_MKK][1][119] = 127, + [0][1][RTW89_MKK][0][119] = 127, + [0][1][RTW89_IC][1][119] = 127, + [0][1][RTW89_KCC][1][119] = 127, + [0][1][RTW89_KCC][0][119] = 127, + [0][1][RTW89_ACMA][1][119] = 127, + [0][1][RTW89_ACMA][0][119] = 127, + [0][1][RTW89_CHILE][1][119] = 127, + [0][1][RTW89_QATAR][1][119] = 127, + [0][1][RTW89_QATAR][0][119] = 127, + [0][1][RTW89_UK][1][119] = 127, + [0][1][RTW89_UK][0][119] = 127, + [1][0][RTW89_FCC][1][0] = -4, + [1][0][RTW89_FCC][2][0] = 52, + [1][0][RTW89_ETSI][1][0] = 46, + [1][0][RTW89_ETSI][0][0] = 6, + [1][0][RTW89_MKK][1][0] = 42, + [1][0][RTW89_MKK][0][0] = 2, + [1][0][RTW89_IC][1][0] = -4, + [1][0][RTW89_KCC][1][0] = -2, + [1][0][RTW89_KCC][0][0] = -2, + [1][0][RTW89_ACMA][1][0] = 46, + [1][0][RTW89_ACMA][0][0] = 6, + [1][0][RTW89_CHILE][1][0] = -4, + [1][0][RTW89_QATAR][1][0] = 46, + [1][0][RTW89_QATAR][0][0] = 6, + [1][0][RTW89_UK][1][0] = 46, + [1][0][RTW89_UK][0][0] = 6, + [1][0][RTW89_FCC][1][2] = -4, + [1][0][RTW89_FCC][2][2] = 52, + [1][0][RTW89_ETSI][1][2] = 46, + [1][0][RTW89_ETSI][0][2] = 6, + [1][0][RTW89_MKK][1][2] = 42, + [1][0][RTW89_MKK][0][2] = 2, + [1][0][RTW89_IC][1][2] = -4, + [1][0][RTW89_KCC][1][2] = -2, + [1][0][RTW89_KCC][0][2] = -2, + [1][0][RTW89_ACMA][1][2] = 46, + [1][0][RTW89_ACMA][0][2] = 6, + [1][0][RTW89_CHILE][1][2] = -4, + [1][0][RTW89_QATAR][1][2] = 46, + [1][0][RTW89_QATAR][0][2] = 6, + [1][0][RTW89_UK][1][2] = 46, + [1][0][RTW89_UK][0][2] = 6, + [1][0][RTW89_FCC][1][4] = -4, + [1][0][RTW89_FCC][2][4] = 52, + [1][0][RTW89_ETSI][1][4] = 46, + [1][0][RTW89_ETSI][0][4] = 6, + [1][0][RTW89_MKK][1][4] = 42, + [1][0][RTW89_MKK][0][4] = 2, + [1][0][RTW89_IC][1][4] = -4, + [1][0][RTW89_KCC][1][4] = -2, + [1][0][RTW89_KCC][0][4] = -2, + [1][0][RTW89_ACMA][1][4] = 46, + [1][0][RTW89_ACMA][0][4] = 6, + [1][0][RTW89_CHILE][1][4] = -4, + [1][0][RTW89_QATAR][1][4] = 46, + [1][0][RTW89_QATAR][0][4] = 6, + [1][0][RTW89_UK][1][4] = 46, + [1][0][RTW89_UK][0][4] = 6, + [1][0][RTW89_FCC][1][6] = -4, + [1][0][RTW89_FCC][2][6] = 52, + [1][0][RTW89_ETSI][1][6] = 46, + [1][0][RTW89_ETSI][0][6] = 6, + [1][0][RTW89_MKK][1][6] = 42, + [1][0][RTW89_MKK][0][6] = 2, + [1][0][RTW89_IC][1][6] = -4, + [1][0][RTW89_KCC][1][6] = -2, + [1][0][RTW89_KCC][0][6] = -2, + [1][0][RTW89_ACMA][1][6] = 46, + [1][0][RTW89_ACMA][0][6] = 6, + [1][0][RTW89_CHILE][1][6] = -4, + [1][0][RTW89_QATAR][1][6] = 46, + [1][0][RTW89_QATAR][0][6] = 6, + [1][0][RTW89_UK][1][6] = 46, + [1][0][RTW89_UK][0][6] = 6, + [1][0][RTW89_FCC][1][8] = -4, + [1][0][RTW89_FCC][2][8] = 52, + [1][0][RTW89_ETSI][1][8] = 46, + [1][0][RTW89_ETSI][0][8] = 6, + [1][0][RTW89_MKK][1][8] = 42, + [1][0][RTW89_MKK][0][8] = 2, + [1][0][RTW89_IC][1][8] = -4, + [1][0][RTW89_KCC][1][8] = -2, + [1][0][RTW89_KCC][0][8] = -2, + [1][0][RTW89_ACMA][1][8] = 46, + [1][0][RTW89_ACMA][0][8] = 6, + [1][0][RTW89_CHILE][1][8] = -4, + [1][0][RTW89_QATAR][1][8] = 46, + [1][0][RTW89_QATAR][0][8] = 6, + [1][0][RTW89_UK][1][8] = 46, + [1][0][RTW89_UK][0][8] = 6, + [1][0][RTW89_FCC][1][10] = -4, + [1][0][RTW89_FCC][2][10] = 52, + [1][0][RTW89_ETSI][1][10] = 46, + [1][0][RTW89_ETSI][0][10] = 6, + [1][0][RTW89_MKK][1][10] = 42, + [1][0][RTW89_MKK][0][10] = 2, + [1][0][RTW89_IC][1][10] = -4, + [1][0][RTW89_KCC][1][10] = -2, + [1][0][RTW89_KCC][0][10] = -2, + [1][0][RTW89_ACMA][1][10] = 46, + [1][0][RTW89_ACMA][0][10] = 6, + [1][0][RTW89_CHILE][1][10] = -4, + [1][0][RTW89_QATAR][1][10] = 46, + [1][0][RTW89_QATAR][0][10] = 6, + [1][0][RTW89_UK][1][10] = 46, + [1][0][RTW89_UK][0][10] = 6, + [1][0][RTW89_FCC][1][12] = -4, + [1][0][RTW89_FCC][2][12] = 52, + [1][0][RTW89_ETSI][1][12] = 46, + [1][0][RTW89_ETSI][0][12] = 6, + [1][0][RTW89_MKK][1][12] = 42, + [1][0][RTW89_MKK][0][12] = 2, + [1][0][RTW89_IC][1][12] = -4, + [1][0][RTW89_KCC][1][12] = -2, + [1][0][RTW89_KCC][0][12] = -2, + [1][0][RTW89_ACMA][1][12] = 46, + [1][0][RTW89_ACMA][0][12] = 6, + [1][0][RTW89_CHILE][1][12] = -4, + [1][0][RTW89_QATAR][1][12] = 46, + [1][0][RTW89_QATAR][0][12] = 6, + [1][0][RTW89_UK][1][12] = 46, + [1][0][RTW89_UK][0][12] = 6, + [1][0][RTW89_FCC][1][14] = -4, + [1][0][RTW89_FCC][2][14] = 52, + [1][0][RTW89_ETSI][1][14] = 46, + [1][0][RTW89_ETSI][0][14] = 6, + [1][0][RTW89_MKK][1][14] = 42, + [1][0][RTW89_MKK][0][14] = 2, + [1][0][RTW89_IC][1][14] = -4, + [1][0][RTW89_KCC][1][14] = -2, + [1][0][RTW89_KCC][0][14] = -2, + [1][0][RTW89_ACMA][1][14] = 46, + [1][0][RTW89_ACMA][0][14] = 6, + [1][0][RTW89_CHILE][1][14] = -4, + [1][0][RTW89_QATAR][1][14] = 46, + [1][0][RTW89_QATAR][0][14] = 6, + [1][0][RTW89_UK][1][14] = 46, + [1][0][RTW89_UK][0][14] = 6, + [1][0][RTW89_FCC][1][15] = -4, + [1][0][RTW89_FCC][2][15] = 52, + [1][0][RTW89_ETSI][1][15] = 46, + [1][0][RTW89_ETSI][0][15] = 6, + [1][0][RTW89_MKK][1][15] = 42, + [1][0][RTW89_MKK][0][15] = 2, + [1][0][RTW89_IC][1][15] = -4, + [1][0][RTW89_KCC][1][15] = -2, + [1][0][RTW89_KCC][0][15] = -2, + [1][0][RTW89_ACMA][1][15] = 46, + [1][0][RTW89_ACMA][0][15] = 6, + [1][0][RTW89_CHILE][1][15] = -4, + [1][0][RTW89_QATAR][1][15] = 46, + [1][0][RTW89_QATAR][0][15] = 6, + [1][0][RTW89_UK][1][15] = 46, + [1][0][RTW89_UK][0][15] = 6, + [1][0][RTW89_FCC][1][17] = -4, + [1][0][RTW89_FCC][2][17] = 52, + [1][0][RTW89_ETSI][1][17] = 46, + [1][0][RTW89_ETSI][0][17] = 6, + [1][0][RTW89_MKK][1][17] = 42, + [1][0][RTW89_MKK][0][17] = 2, + [1][0][RTW89_IC][1][17] = -4, + [1][0][RTW89_KCC][1][17] = -2, + [1][0][RTW89_KCC][0][17] = -2, + [1][0][RTW89_ACMA][1][17] = 46, + [1][0][RTW89_ACMA][0][17] = 6, + [1][0][RTW89_CHILE][1][17] = -4, + [1][0][RTW89_QATAR][1][17] = 46, + [1][0][RTW89_QATAR][0][17] = 6, + [1][0][RTW89_UK][1][17] = 46, + [1][0][RTW89_UK][0][17] = 6, + [1][0][RTW89_FCC][1][19] = -4, + [1][0][RTW89_FCC][2][19] = 52, + [1][0][RTW89_ETSI][1][19] = 46, + [1][0][RTW89_ETSI][0][19] = 6, + [1][0][RTW89_MKK][1][19] = 42, + [1][0][RTW89_MKK][0][19] = 2, + [1][0][RTW89_IC][1][19] = -4, + [1][0][RTW89_KCC][1][19] = -2, + [1][0][RTW89_KCC][0][19] = -2, + [1][0][RTW89_ACMA][1][19] = 46, + [1][0][RTW89_ACMA][0][19] = 6, + [1][0][RTW89_CHILE][1][19] = -4, + [1][0][RTW89_QATAR][1][19] = 46, + [1][0][RTW89_QATAR][0][19] = 6, + [1][0][RTW89_UK][1][19] = 46, + [1][0][RTW89_UK][0][19] = 6, + [1][0][RTW89_FCC][1][21] = -4, + [1][0][RTW89_FCC][2][21] = 52, + [1][0][RTW89_ETSI][1][21] = 46, + [1][0][RTW89_ETSI][0][21] = 6, + [1][0][RTW89_MKK][1][21] = 42, + [1][0][RTW89_MKK][0][21] = 2, + [1][0][RTW89_IC][1][21] = -4, + [1][0][RTW89_KCC][1][21] = -2, + [1][0][RTW89_KCC][0][21] = -2, + [1][0][RTW89_ACMA][1][21] = 46, + [1][0][RTW89_ACMA][0][21] = 6, + [1][0][RTW89_CHILE][1][21] = -4, + [1][0][RTW89_QATAR][1][21] = 46, + [1][0][RTW89_QATAR][0][21] = 6, + [1][0][RTW89_UK][1][21] = 46, + [1][0][RTW89_UK][0][21] = 6, + [1][0][RTW89_FCC][1][23] = -4, + [1][0][RTW89_FCC][2][23] = 66, + [1][0][RTW89_ETSI][1][23] = 46, + [1][0][RTW89_ETSI][0][23] = 6, + [1][0][RTW89_MKK][1][23] = 42, + [1][0][RTW89_MKK][0][23] = 2, + [1][0][RTW89_IC][1][23] = -4, + [1][0][RTW89_KCC][1][23] = -2, + [1][0][RTW89_KCC][0][23] = -2, + [1][0][RTW89_ACMA][1][23] = 46, + [1][0][RTW89_ACMA][0][23] = 6, + [1][0][RTW89_CHILE][1][23] = -4, + [1][0][RTW89_QATAR][1][23] = 46, + [1][0][RTW89_QATAR][0][23] = 6, + [1][0][RTW89_UK][1][23] = 46, + [1][0][RTW89_UK][0][23] = 6, + [1][0][RTW89_FCC][1][25] = -4, + [1][0][RTW89_FCC][2][25] = 66, + [1][0][RTW89_ETSI][1][25] = 46, + [1][0][RTW89_ETSI][0][25] = 6, + [1][0][RTW89_MKK][1][25] = 42, + [1][0][RTW89_MKK][0][25] = 2, + [1][0][RTW89_IC][1][25] = -4, + [1][0][RTW89_KCC][1][25] = -2, + [1][0][RTW89_KCC][0][25] = -2, + [1][0][RTW89_ACMA][1][25] = 46, + [1][0][RTW89_ACMA][0][25] = 6, + [1][0][RTW89_CHILE][1][25] = -4, + [1][0][RTW89_QATAR][1][25] = 46, + [1][0][RTW89_QATAR][0][25] = 6, + [1][0][RTW89_UK][1][25] = 46, + [1][0][RTW89_UK][0][25] = 6, + [1][0][RTW89_FCC][1][27] = -4, + [1][0][RTW89_FCC][2][27] = 66, + [1][0][RTW89_ETSI][1][27] = 46, + [1][0][RTW89_ETSI][0][27] = 6, + [1][0][RTW89_MKK][1][27] = 42, + [1][0][RTW89_MKK][0][27] = 2, + [1][0][RTW89_IC][1][27] = -4, + [1][0][RTW89_KCC][1][27] = -2, + [1][0][RTW89_KCC][0][27] = -2, + [1][0][RTW89_ACMA][1][27] = 46, + [1][0][RTW89_ACMA][0][27] = 6, + [1][0][RTW89_CHILE][1][27] = -4, + [1][0][RTW89_QATAR][1][27] = 46, + [1][0][RTW89_QATAR][0][27] = 6, + [1][0][RTW89_UK][1][27] = 46, + [1][0][RTW89_UK][0][27] = 6, + [1][0][RTW89_FCC][1][29] = -4, + [1][0][RTW89_FCC][2][29] = 66, + [1][0][RTW89_ETSI][1][29] = 46, + [1][0][RTW89_ETSI][0][29] = 6, + [1][0][RTW89_MKK][1][29] = 42, + [1][0][RTW89_MKK][0][29] = 2, + [1][0][RTW89_IC][1][29] = -4, + [1][0][RTW89_KCC][1][29] = -2, + [1][0][RTW89_KCC][0][29] = -2, + [1][0][RTW89_ACMA][1][29] = 46, + [1][0][RTW89_ACMA][0][29] = 6, + [1][0][RTW89_CHILE][1][29] = -4, + [1][0][RTW89_QATAR][1][29] = 46, + [1][0][RTW89_QATAR][0][29] = 6, + [1][0][RTW89_UK][1][29] = 46, + [1][0][RTW89_UK][0][29] = 6, + [1][0][RTW89_FCC][1][30] = -4, + [1][0][RTW89_FCC][2][30] = 66, + [1][0][RTW89_ETSI][1][30] = 46, + [1][0][RTW89_ETSI][0][30] = 6, + [1][0][RTW89_MKK][1][30] = 42, + [1][0][RTW89_MKK][0][30] = 2, + [1][0][RTW89_IC][1][30] = -4, + [1][0][RTW89_KCC][1][30] = -2, + [1][0][RTW89_KCC][0][30] = -2, + [1][0][RTW89_ACMA][1][30] = 46, + [1][0][RTW89_ACMA][0][30] = 6, + [1][0][RTW89_CHILE][1][30] = -4, + [1][0][RTW89_QATAR][1][30] = 46, + [1][0][RTW89_QATAR][0][30] = 6, + [1][0][RTW89_UK][1][30] = 46, + [1][0][RTW89_UK][0][30] = 6, + [1][0][RTW89_FCC][1][32] = -4, + [1][0][RTW89_FCC][2][32] = 66, + [1][0][RTW89_ETSI][1][32] = 46, + [1][0][RTW89_ETSI][0][32] = 6, + [1][0][RTW89_MKK][1][32] = 42, + [1][0][RTW89_MKK][0][32] = 2, + [1][0][RTW89_IC][1][32] = -4, + [1][0][RTW89_KCC][1][32] = -2, + [1][0][RTW89_KCC][0][32] = -2, + [1][0][RTW89_ACMA][1][32] = 46, + [1][0][RTW89_ACMA][0][32] = 6, + [1][0][RTW89_CHILE][1][32] = -4, + [1][0][RTW89_QATAR][1][32] = 46, + [1][0][RTW89_QATAR][0][32] = 6, + [1][0][RTW89_UK][1][32] = 46, + [1][0][RTW89_UK][0][32] = 6, + [1][0][RTW89_FCC][1][34] = -4, + [1][0][RTW89_FCC][2][34] = 66, + [1][0][RTW89_ETSI][1][34] = 46, + [1][0][RTW89_ETSI][0][34] = 6, + [1][0][RTW89_MKK][1][34] = 42, + [1][0][RTW89_MKK][0][34] = 2, + [1][0][RTW89_IC][1][34] = -4, + [1][0][RTW89_KCC][1][34] = -2, + [1][0][RTW89_KCC][0][34] = -2, + [1][0][RTW89_ACMA][1][34] = 46, + [1][0][RTW89_ACMA][0][34] = 6, + [1][0][RTW89_CHILE][1][34] = -4, + [1][0][RTW89_QATAR][1][34] = 46, + [1][0][RTW89_QATAR][0][34] = 6, + [1][0][RTW89_UK][1][34] = 46, + [1][0][RTW89_UK][0][34] = 6, + [1][0][RTW89_FCC][1][36] = -4, + [1][0][RTW89_FCC][2][36] = 66, + [1][0][RTW89_ETSI][1][36] = 46, + [1][0][RTW89_ETSI][0][36] = 6, + [1][0][RTW89_MKK][1][36] = 42, + [1][0][RTW89_MKK][0][36] = 2, + [1][0][RTW89_IC][1][36] = -4, + [1][0][RTW89_KCC][1][36] = -2, + [1][0][RTW89_KCC][0][36] = -2, + [1][0][RTW89_ACMA][1][36] = 46, + [1][0][RTW89_ACMA][0][36] = 6, + [1][0][RTW89_CHILE][1][36] = -4, + [1][0][RTW89_QATAR][1][36] = 46, + [1][0][RTW89_QATAR][0][36] = 6, + [1][0][RTW89_UK][1][36] = 46, + [1][0][RTW89_UK][0][36] = 6, + [1][0][RTW89_FCC][1][38] = -4, + [1][0][RTW89_FCC][2][38] = 66, + [1][0][RTW89_ETSI][1][38] = 46, + [1][0][RTW89_ETSI][0][38] = 6, + [1][0][RTW89_MKK][1][38] = 42, + [1][0][RTW89_MKK][0][38] = 2, + [1][0][RTW89_IC][1][38] = -4, + [1][0][RTW89_KCC][1][38] = -2, + [1][0][RTW89_KCC][0][38] = -2, + [1][0][RTW89_ACMA][1][38] = 46, + [1][0][RTW89_ACMA][0][38] = 6, + [1][0][RTW89_CHILE][1][38] = -4, + [1][0][RTW89_QATAR][1][38] = 46, + [1][0][RTW89_QATAR][0][38] = 6, + [1][0][RTW89_UK][1][38] = 46, + [1][0][RTW89_UK][0][38] = 6, + [1][0][RTW89_FCC][1][40] = -4, + [1][0][RTW89_FCC][2][40] = 66, + [1][0][RTW89_ETSI][1][40] = 46, + [1][0][RTW89_ETSI][0][40] = 6, + [1][0][RTW89_MKK][1][40] = 42, + [1][0][RTW89_MKK][0][40] = 2, + [1][0][RTW89_IC][1][40] = -4, + [1][0][RTW89_KCC][1][40] = -2, + [1][0][RTW89_KCC][0][40] = -2, + [1][0][RTW89_ACMA][1][40] = 46, + [1][0][RTW89_ACMA][0][40] = 6, + [1][0][RTW89_CHILE][1][40] = -4, + [1][0][RTW89_QATAR][1][40] = 46, + [1][0][RTW89_QATAR][0][40] = 6, + [1][0][RTW89_UK][1][40] = 46, + [1][0][RTW89_UK][0][40] = 6, + [1][0][RTW89_FCC][1][42] = -4, + [1][0][RTW89_FCC][2][42] = 66, + [1][0][RTW89_ETSI][1][42] = 46, + [1][0][RTW89_ETSI][0][42] = 6, + [1][0][RTW89_MKK][1][42] = 42, + [1][0][RTW89_MKK][0][42] = 2, + [1][0][RTW89_IC][1][42] = -4, + [1][0][RTW89_KCC][1][42] = -2, + [1][0][RTW89_KCC][0][42] = -2, + [1][0][RTW89_ACMA][1][42] = 46, + [1][0][RTW89_ACMA][0][42] = 6, + [1][0][RTW89_CHILE][1][42] = -4, + [1][0][RTW89_QATAR][1][42] = 46, + [1][0][RTW89_QATAR][0][42] = 6, + [1][0][RTW89_UK][1][42] = 46, + [1][0][RTW89_UK][0][42] = 6, + [1][0][RTW89_FCC][1][44] = -4, + [1][0][RTW89_FCC][2][44] = 66, + [1][0][RTW89_ETSI][1][44] = 46, + [1][0][RTW89_ETSI][0][44] = 8, + [1][0][RTW89_MKK][1][44] = 22, + [1][0][RTW89_MKK][0][44] = 4, + [1][0][RTW89_IC][1][44] = -4, + [1][0][RTW89_KCC][1][44] = -2, + [1][0][RTW89_KCC][0][44] = -2, + [1][0][RTW89_ACMA][1][44] = 46, + [1][0][RTW89_ACMA][0][44] = 8, + [1][0][RTW89_CHILE][1][44] = -4, + [1][0][RTW89_QATAR][1][44] = 46, + [1][0][RTW89_QATAR][0][44] = 8, + [1][0][RTW89_UK][1][44] = 46, + [1][0][RTW89_UK][0][44] = 8, + [1][0][RTW89_FCC][1][45] = -4, + [1][0][RTW89_FCC][2][45] = 127, + [1][0][RTW89_ETSI][1][45] = 127, + [1][0][RTW89_ETSI][0][45] = 127, + [1][0][RTW89_MKK][1][45] = 127, + [1][0][RTW89_MKK][0][45] = 127, + [1][0][RTW89_IC][1][45] = -4, + [1][0][RTW89_KCC][1][45] = -2, + [1][0][RTW89_KCC][0][45] = 127, + [1][0][RTW89_ACMA][1][45] = 127, + [1][0][RTW89_ACMA][0][45] = 127, + [1][0][RTW89_CHILE][1][45] = 127, + [1][0][RTW89_QATAR][1][45] = 127, + [1][0][RTW89_QATAR][0][45] = 127, + [1][0][RTW89_UK][1][45] = 127, + [1][0][RTW89_UK][0][45] = 127, + [1][0][RTW89_FCC][1][47] = -4, + [1][0][RTW89_FCC][2][47] = 127, + [1][0][RTW89_ETSI][1][47] = 127, + [1][0][RTW89_ETSI][0][47] = 127, + [1][0][RTW89_MKK][1][47] = 127, + [1][0][RTW89_MKK][0][47] = 127, + [1][0][RTW89_IC][1][47] = -4, + [1][0][RTW89_KCC][1][47] = -2, + [1][0][RTW89_KCC][0][47] = 127, + [1][0][RTW89_ACMA][1][47] = 127, + [1][0][RTW89_ACMA][0][47] = 127, + [1][0][RTW89_CHILE][1][47] = 127, + [1][0][RTW89_QATAR][1][47] = 127, + [1][0][RTW89_QATAR][0][47] = 127, + [1][0][RTW89_UK][1][47] = 127, + [1][0][RTW89_UK][0][47] = 127, + [1][0][RTW89_FCC][1][49] = -4, + [1][0][RTW89_FCC][2][49] = 127, + [1][0][RTW89_ETSI][1][49] = 127, + [1][0][RTW89_ETSI][0][49] = 127, + [1][0][RTW89_MKK][1][49] = 127, + [1][0][RTW89_MKK][0][49] = 127, + [1][0][RTW89_IC][1][49] = -4, + [1][0][RTW89_KCC][1][49] = -2, + [1][0][RTW89_KCC][0][49] = 127, + [1][0][RTW89_ACMA][1][49] = 127, + [1][0][RTW89_ACMA][0][49] = 127, + [1][0][RTW89_CHILE][1][49] = 127, + [1][0][RTW89_QATAR][1][49] = 127, + [1][0][RTW89_QATAR][0][49] = 127, + [1][0][RTW89_UK][1][49] = 127, + [1][0][RTW89_UK][0][49] = 127, + [1][0][RTW89_FCC][1][51] = -4, + [1][0][RTW89_FCC][2][51] = 127, + [1][0][RTW89_ETSI][1][51] = 127, + [1][0][RTW89_ETSI][0][51] = 127, + [1][0][RTW89_MKK][1][51] = 127, + [1][0][RTW89_MKK][0][51] = 127, + [1][0][RTW89_IC][1][51] = -4, + [1][0][RTW89_KCC][1][51] = -2, + [1][0][RTW89_KCC][0][51] = 127, + [1][0][RTW89_ACMA][1][51] = 127, + [1][0][RTW89_ACMA][0][51] = 127, + [1][0][RTW89_CHILE][1][51] = 127, + [1][0][RTW89_QATAR][1][51] = 127, + [1][0][RTW89_QATAR][0][51] = 127, + [1][0][RTW89_UK][1][51] = 127, + [1][0][RTW89_UK][0][51] = 127, + [1][0][RTW89_FCC][1][53] = -4, + [1][0][RTW89_FCC][2][53] = 127, + [1][0][RTW89_ETSI][1][53] = 127, + [1][0][RTW89_ETSI][0][53] = 127, + [1][0][RTW89_MKK][1][53] = 127, + [1][0][RTW89_MKK][0][53] = 127, + [1][0][RTW89_IC][1][53] = -4, + [1][0][RTW89_KCC][1][53] = -2, + [1][0][RTW89_KCC][0][53] = 127, + [1][0][RTW89_ACMA][1][53] = 127, + [1][0][RTW89_ACMA][0][53] = 127, + [1][0][RTW89_CHILE][1][53] = 127, + [1][0][RTW89_QATAR][1][53] = 127, + [1][0][RTW89_QATAR][0][53] = 127, + [1][0][RTW89_UK][1][53] = 127, + [1][0][RTW89_UK][0][53] = 127, + [1][0][RTW89_FCC][1][55] = -4, + [1][0][RTW89_FCC][2][55] = 68, + [1][0][RTW89_ETSI][1][55] = 127, + [1][0][RTW89_ETSI][0][55] = 127, + [1][0][RTW89_MKK][1][55] = 127, + [1][0][RTW89_MKK][0][55] = 127, + [1][0][RTW89_IC][1][55] = -4, + [1][0][RTW89_KCC][1][55] = -2, + [1][0][RTW89_KCC][0][55] = 127, + [1][0][RTW89_ACMA][1][55] = 127, + [1][0][RTW89_ACMA][0][55] = 127, + [1][0][RTW89_CHILE][1][55] = 127, + [1][0][RTW89_QATAR][1][55] = 127, + [1][0][RTW89_QATAR][0][55] = 127, + [1][0][RTW89_UK][1][55] = 127, + [1][0][RTW89_UK][0][55] = 127, + [1][0][RTW89_FCC][1][57] = -4, + [1][0][RTW89_FCC][2][57] = 68, + [1][0][RTW89_ETSI][1][57] = 127, + [1][0][RTW89_ETSI][0][57] = 127, + [1][0][RTW89_MKK][1][57] = 127, + [1][0][RTW89_MKK][0][57] = 127, + [1][0][RTW89_IC][1][57] = -4, + [1][0][RTW89_KCC][1][57] = -2, + [1][0][RTW89_KCC][0][57] = 127, + [1][0][RTW89_ACMA][1][57] = 127, + [1][0][RTW89_ACMA][0][57] = 127, + [1][0][RTW89_CHILE][1][57] = 127, + [1][0][RTW89_QATAR][1][57] = 127, + [1][0][RTW89_QATAR][0][57] = 127, + [1][0][RTW89_UK][1][57] = 127, + [1][0][RTW89_UK][0][57] = 127, + [1][0][RTW89_FCC][1][59] = -4, + [1][0][RTW89_FCC][2][59] = 68, + [1][0][RTW89_ETSI][1][59] = 127, + [1][0][RTW89_ETSI][0][59] = 127, + [1][0][RTW89_MKK][1][59] = 127, + [1][0][RTW89_MKK][0][59] = 127, + [1][0][RTW89_IC][1][59] = -4, + [1][0][RTW89_KCC][1][59] = -2, + [1][0][RTW89_KCC][0][59] = 127, + [1][0][RTW89_ACMA][1][59] = 127, + [1][0][RTW89_ACMA][0][59] = 127, + [1][0][RTW89_CHILE][1][59] = 127, + [1][0][RTW89_QATAR][1][59] = 127, + [1][0][RTW89_QATAR][0][59] = 127, + [1][0][RTW89_UK][1][59] = 127, + [1][0][RTW89_UK][0][59] = 127, + [1][0][RTW89_FCC][1][60] = -4, + [1][0][RTW89_FCC][2][60] = 68, + [1][0][RTW89_ETSI][1][60] = 127, + [1][0][RTW89_ETSI][0][60] = 127, + [1][0][RTW89_MKK][1][60] = 127, + [1][0][RTW89_MKK][0][60] = 127, + [1][0][RTW89_IC][1][60] = -4, + [1][0][RTW89_KCC][1][60] = -2, + [1][0][RTW89_KCC][0][60] = 127, + [1][0][RTW89_ACMA][1][60] = 127, + [1][0][RTW89_ACMA][0][60] = 127, + [1][0][RTW89_CHILE][1][60] = 127, + [1][0][RTW89_QATAR][1][60] = 127, + [1][0][RTW89_QATAR][0][60] = 127, + [1][0][RTW89_UK][1][60] = 127, + [1][0][RTW89_UK][0][60] = 127, + [1][0][RTW89_FCC][1][62] = -4, + [1][0][RTW89_FCC][2][62] = 68, + [1][0][RTW89_ETSI][1][62] = 127, + [1][0][RTW89_ETSI][0][62] = 127, + [1][0][RTW89_MKK][1][62] = 127, + [1][0][RTW89_MKK][0][62] = 127, + [1][0][RTW89_IC][1][62] = -4, + [1][0][RTW89_KCC][1][62] = -2, + [1][0][RTW89_KCC][0][62] = 127, + [1][0][RTW89_ACMA][1][62] = 127, + [1][0][RTW89_ACMA][0][62] = 127, + [1][0][RTW89_CHILE][1][62] = 127, + [1][0][RTW89_QATAR][1][62] = 127, + [1][0][RTW89_QATAR][0][62] = 127, + [1][0][RTW89_UK][1][62] = 127, + [1][0][RTW89_UK][0][62] = 127, + [1][0][RTW89_FCC][1][64] = -4, + [1][0][RTW89_FCC][2][64] = 68, + [1][0][RTW89_ETSI][1][64] = 127, + [1][0][RTW89_ETSI][0][64] = 127, + [1][0][RTW89_MKK][1][64] = 127, + [1][0][RTW89_MKK][0][64] = 127, + [1][0][RTW89_IC][1][64] = -4, + [1][0][RTW89_KCC][1][64] = -2, + [1][0][RTW89_KCC][0][64] = 127, + [1][0][RTW89_ACMA][1][64] = 127, + [1][0][RTW89_ACMA][0][64] = 127, + [1][0][RTW89_CHILE][1][64] = 127, + [1][0][RTW89_QATAR][1][64] = 127, + [1][0][RTW89_QATAR][0][64] = 127, + [1][0][RTW89_UK][1][64] = 127, + [1][0][RTW89_UK][0][64] = 127, + [1][0][RTW89_FCC][1][66] = -4, + [1][0][RTW89_FCC][2][66] = 68, + [1][0][RTW89_ETSI][1][66] = 127, + [1][0][RTW89_ETSI][0][66] = 127, + [1][0][RTW89_MKK][1][66] = 127, + [1][0][RTW89_MKK][0][66] = 127, + [1][0][RTW89_IC][1][66] = -4, + [1][0][RTW89_KCC][1][66] = -2, + [1][0][RTW89_KCC][0][66] = 127, + [1][0][RTW89_ACMA][1][66] = 127, + [1][0][RTW89_ACMA][0][66] = 127, + [1][0][RTW89_CHILE][1][66] = 127, + [1][0][RTW89_QATAR][1][66] = 127, + [1][0][RTW89_QATAR][0][66] = 127, + [1][0][RTW89_UK][1][66] = 127, + [1][0][RTW89_UK][0][66] = 127, + [1][0][RTW89_FCC][1][68] = -4, + [1][0][RTW89_FCC][2][68] = 68, + [1][0][RTW89_ETSI][1][68] = 127, + [1][0][RTW89_ETSI][0][68] = 127, + [1][0][RTW89_MKK][1][68] = 127, + [1][0][RTW89_MKK][0][68] = 127, + [1][0][RTW89_IC][1][68] = -4, + [1][0][RTW89_KCC][1][68] = -2, + [1][0][RTW89_KCC][0][68] = 127, + [1][0][RTW89_ACMA][1][68] = 127, + [1][0][RTW89_ACMA][0][68] = 127, + [1][0][RTW89_CHILE][1][68] = 127, + [1][0][RTW89_QATAR][1][68] = 127, + [1][0][RTW89_QATAR][0][68] = 127, + [1][0][RTW89_UK][1][68] = 127, + [1][0][RTW89_UK][0][68] = 127, + [1][0][RTW89_FCC][1][70] = -4, + [1][0][RTW89_FCC][2][70] = 68, + [1][0][RTW89_ETSI][1][70] = 127, + [1][0][RTW89_ETSI][0][70] = 127, + [1][0][RTW89_MKK][1][70] = 127, + [1][0][RTW89_MKK][0][70] = 127, + [1][0][RTW89_IC][1][70] = -4, + [1][0][RTW89_KCC][1][70] = -2, + [1][0][RTW89_KCC][0][70] = 127, + [1][0][RTW89_ACMA][1][70] = 127, + [1][0][RTW89_ACMA][0][70] = 127, + [1][0][RTW89_CHILE][1][70] = 127, + [1][0][RTW89_QATAR][1][70] = 127, + [1][0][RTW89_QATAR][0][70] = 127, + [1][0][RTW89_UK][1][70] = 127, + [1][0][RTW89_UK][0][70] = 127, + [1][0][RTW89_FCC][1][72] = -4, + [1][0][RTW89_FCC][2][72] = 68, + [1][0][RTW89_ETSI][1][72] = 127, + [1][0][RTW89_ETSI][0][72] = 127, + [1][0][RTW89_MKK][1][72] = 127, + [1][0][RTW89_MKK][0][72] = 127, + [1][0][RTW89_IC][1][72] = -4, + [1][0][RTW89_KCC][1][72] = -2, + [1][0][RTW89_KCC][0][72] = 127, + [1][0][RTW89_ACMA][1][72] = 127, + [1][0][RTW89_ACMA][0][72] = 127, + [1][0][RTW89_CHILE][1][72] = 127, + [1][0][RTW89_QATAR][1][72] = 127, + [1][0][RTW89_QATAR][0][72] = 127, + [1][0][RTW89_UK][1][72] = 127, + [1][0][RTW89_UK][0][72] = 127, + [1][0][RTW89_FCC][1][74] = -4, + [1][0][RTW89_FCC][2][74] = 68, + [1][0][RTW89_ETSI][1][74] = 127, + [1][0][RTW89_ETSI][0][74] = 127, + [1][0][RTW89_MKK][1][74] = 127, + [1][0][RTW89_MKK][0][74] = 127, + [1][0][RTW89_IC][1][74] = -4, + [1][0][RTW89_KCC][1][74] = -2, + [1][0][RTW89_KCC][0][74] = 127, + [1][0][RTW89_ACMA][1][74] = 127, + [1][0][RTW89_ACMA][0][74] = 127, + [1][0][RTW89_CHILE][1][74] = 127, + [1][0][RTW89_QATAR][1][74] = 127, + [1][0][RTW89_QATAR][0][74] = 127, + [1][0][RTW89_UK][1][74] = 127, + [1][0][RTW89_UK][0][74] = 127, + [1][0][RTW89_FCC][1][75] = -4, + [1][0][RTW89_FCC][2][75] = 68, + [1][0][RTW89_ETSI][1][75] = 127, + [1][0][RTW89_ETSI][0][75] = 127, + [1][0][RTW89_MKK][1][75] = 127, + [1][0][RTW89_MKK][0][75] = 127, + [1][0][RTW89_IC][1][75] = -4, + [1][0][RTW89_KCC][1][75] = -2, + [1][0][RTW89_KCC][0][75] = 127, + [1][0][RTW89_ACMA][1][75] = 127, + [1][0][RTW89_ACMA][0][75] = 127, + [1][0][RTW89_CHILE][1][75] = 127, + [1][0][RTW89_QATAR][1][75] = 127, + [1][0][RTW89_QATAR][0][75] = 127, + [1][0][RTW89_UK][1][75] = 127, + [1][0][RTW89_UK][0][75] = 127, + [1][0][RTW89_FCC][1][77] = -4, + [1][0][RTW89_FCC][2][77] = 68, + [1][0][RTW89_ETSI][1][77] = 127, + [1][0][RTW89_ETSI][0][77] = 127, + [1][0][RTW89_MKK][1][77] = 127, + [1][0][RTW89_MKK][0][77] = 127, + [1][0][RTW89_IC][1][77] = -4, + [1][0][RTW89_KCC][1][77] = -2, + [1][0][RTW89_KCC][0][77] = 127, + [1][0][RTW89_ACMA][1][77] = 127, + [1][0][RTW89_ACMA][0][77] = 127, + [1][0][RTW89_CHILE][1][77] = 127, + [1][0][RTW89_QATAR][1][77] = 127, + [1][0][RTW89_QATAR][0][77] = 127, + [1][0][RTW89_UK][1][77] = 127, + [1][0][RTW89_UK][0][77] = 127, + [1][0][RTW89_FCC][1][79] = -4, + [1][0][RTW89_FCC][2][79] = 68, + [1][0][RTW89_ETSI][1][79] = 127, + [1][0][RTW89_ETSI][0][79] = 127, + [1][0][RTW89_MKK][1][79] = 127, + [1][0][RTW89_MKK][0][79] = 127, + [1][0][RTW89_IC][1][79] = -4, + [1][0][RTW89_KCC][1][79] = -2, + [1][0][RTW89_KCC][0][79] = 127, + [1][0][RTW89_ACMA][1][79] = 127, + [1][0][RTW89_ACMA][0][79] = 127, + [1][0][RTW89_CHILE][1][79] = 127, + [1][0][RTW89_QATAR][1][79] = 127, + [1][0][RTW89_QATAR][0][79] = 127, + [1][0][RTW89_UK][1][79] = 127, + [1][0][RTW89_UK][0][79] = 127, + [1][0][RTW89_FCC][1][81] = -4, + [1][0][RTW89_FCC][2][81] = 68, + [1][0][RTW89_ETSI][1][81] = 127, + [1][0][RTW89_ETSI][0][81] = 127, + [1][0][RTW89_MKK][1][81] = 127, + [1][0][RTW89_MKK][0][81] = 127, + [1][0][RTW89_IC][1][81] = -4, + [1][0][RTW89_KCC][1][81] = -2, + [1][0][RTW89_KCC][0][81] = 127, + [1][0][RTW89_ACMA][1][81] = 127, + [1][0][RTW89_ACMA][0][81] = 127, + [1][0][RTW89_CHILE][1][81] = 127, + [1][0][RTW89_QATAR][1][81] = 127, + [1][0][RTW89_QATAR][0][81] = 127, + [1][0][RTW89_UK][1][81] = 127, + [1][0][RTW89_UK][0][81] = 127, + [1][0][RTW89_FCC][1][83] = -4, + [1][0][RTW89_FCC][2][83] = 68, + [1][0][RTW89_ETSI][1][83] = 127, + [1][0][RTW89_ETSI][0][83] = 127, + [1][0][RTW89_MKK][1][83] = 127, + [1][0][RTW89_MKK][0][83] = 127, + [1][0][RTW89_IC][1][83] = -4, + [1][0][RTW89_KCC][1][83] = -2, + [1][0][RTW89_KCC][0][83] = 127, + [1][0][RTW89_ACMA][1][83] = 127, + [1][0][RTW89_ACMA][0][83] = 127, + [1][0][RTW89_CHILE][1][83] = 127, + [1][0][RTW89_QATAR][1][83] = 127, + [1][0][RTW89_QATAR][0][83] = 127, + [1][0][RTW89_UK][1][83] = 127, + [1][0][RTW89_UK][0][83] = 127, + [1][0][RTW89_FCC][1][85] = -4, + [1][0][RTW89_FCC][2][85] = 68, + [1][0][RTW89_ETSI][1][85] = 127, + [1][0][RTW89_ETSI][0][85] = 127, + [1][0][RTW89_MKK][1][85] = 127, + [1][0][RTW89_MKK][0][85] = 127, + [1][0][RTW89_IC][1][85] = -4, + [1][0][RTW89_KCC][1][85] = -2, + [1][0][RTW89_KCC][0][85] = 127, + [1][0][RTW89_ACMA][1][85] = 127, + [1][0][RTW89_ACMA][0][85] = 127, + [1][0][RTW89_CHILE][1][85] = 127, + [1][0][RTW89_QATAR][1][85] = 127, + [1][0][RTW89_QATAR][0][85] = 127, + [1][0][RTW89_UK][1][85] = 127, + [1][0][RTW89_UK][0][85] = 127, + [1][0][RTW89_FCC][1][87] = -4, + [1][0][RTW89_FCC][2][87] = 127, + [1][0][RTW89_ETSI][1][87] = 127, + [1][0][RTW89_ETSI][0][87] = 127, + [1][0][RTW89_MKK][1][87] = 127, + [1][0][RTW89_MKK][0][87] = 127, + [1][0][RTW89_IC][1][87] = -4, + [1][0][RTW89_KCC][1][87] = -2, + [1][0][RTW89_KCC][0][87] = 127, + [1][0][RTW89_ACMA][1][87] = 127, + [1][0][RTW89_ACMA][0][87] = 127, + [1][0][RTW89_CHILE][1][87] = 127, + [1][0][RTW89_QATAR][1][87] = 127, + [1][0][RTW89_QATAR][0][87] = 127, + [1][0][RTW89_UK][1][87] = 127, + [1][0][RTW89_UK][0][87] = 127, + [1][0][RTW89_FCC][1][89] = -4, + [1][0][RTW89_FCC][2][89] = 127, + [1][0][RTW89_ETSI][1][89] = 127, + [1][0][RTW89_ETSI][0][89] = 127, + [1][0][RTW89_MKK][1][89] = 127, + [1][0][RTW89_MKK][0][89] = 127, + [1][0][RTW89_IC][1][89] = -4, + [1][0][RTW89_KCC][1][89] = -2, + [1][0][RTW89_KCC][0][89] = 127, + [1][0][RTW89_ACMA][1][89] = 127, + [1][0][RTW89_ACMA][0][89] = 127, + [1][0][RTW89_CHILE][1][89] = 127, + [1][0][RTW89_QATAR][1][89] = 127, + [1][0][RTW89_QATAR][0][89] = 127, + [1][0][RTW89_UK][1][89] = 127, + [1][0][RTW89_UK][0][89] = 127, + [1][0][RTW89_FCC][1][90] = -4, + [1][0][RTW89_FCC][2][90] = 127, + [1][0][RTW89_ETSI][1][90] = 127, + [1][0][RTW89_ETSI][0][90] = 127, + [1][0][RTW89_MKK][1][90] = 127, + [1][0][RTW89_MKK][0][90] = 127, + [1][0][RTW89_IC][1][90] = -4, + [1][0][RTW89_KCC][1][90] = -2, + [1][0][RTW89_KCC][0][90] = 127, + [1][0][RTW89_ACMA][1][90] = 127, + [1][0][RTW89_ACMA][0][90] = 127, + [1][0][RTW89_CHILE][1][90] = 127, + [1][0][RTW89_QATAR][1][90] = 127, + [1][0][RTW89_QATAR][0][90] = 127, + [1][0][RTW89_UK][1][90] = 127, + [1][0][RTW89_UK][0][90] = 127, + [1][0][RTW89_FCC][1][92] = -4, + [1][0][RTW89_FCC][2][92] = 127, + [1][0][RTW89_ETSI][1][92] = 127, + [1][0][RTW89_ETSI][0][92] = 127, + [1][0][RTW89_MKK][1][92] = 127, + [1][0][RTW89_MKK][0][92] = 127, + [1][0][RTW89_IC][1][92] = -4, + [1][0][RTW89_KCC][1][92] = -2, + [1][0][RTW89_KCC][0][92] = 127, + [1][0][RTW89_ACMA][1][92] = 127, + [1][0][RTW89_ACMA][0][92] = 127, + [1][0][RTW89_CHILE][1][92] = 127, + [1][0][RTW89_QATAR][1][92] = 127, + [1][0][RTW89_QATAR][0][92] = 127, + [1][0][RTW89_UK][1][92] = 127, + [1][0][RTW89_UK][0][92] = 127, + [1][0][RTW89_FCC][1][94] = -4, + [1][0][RTW89_FCC][2][94] = 127, + [1][0][RTW89_ETSI][1][94] = 127, + [1][0][RTW89_ETSI][0][94] = 127, + [1][0][RTW89_MKK][1][94] = 127, + [1][0][RTW89_MKK][0][94] = 127, + [1][0][RTW89_IC][1][94] = -4, + [1][0][RTW89_KCC][1][94] = -2, + [1][0][RTW89_KCC][0][94] = 127, + [1][0][RTW89_ACMA][1][94] = 127, + [1][0][RTW89_ACMA][0][94] = 127, + [1][0][RTW89_CHILE][1][94] = 127, + [1][0][RTW89_QATAR][1][94] = 127, + [1][0][RTW89_QATAR][0][94] = 127, + [1][0][RTW89_UK][1][94] = 127, + [1][0][RTW89_UK][0][94] = 127, + [1][0][RTW89_FCC][1][96] = -4, + [1][0][RTW89_FCC][2][96] = 127, + [1][0][RTW89_ETSI][1][96] = 127, + [1][0][RTW89_ETSI][0][96] = 127, + [1][0][RTW89_MKK][1][96] = 127, + [1][0][RTW89_MKK][0][96] = 127, + [1][0][RTW89_IC][1][96] = -4, + [1][0][RTW89_KCC][1][96] = -2, + [1][0][RTW89_KCC][0][96] = 127, + [1][0][RTW89_ACMA][1][96] = 127, + [1][0][RTW89_ACMA][0][96] = 127, + [1][0][RTW89_CHILE][1][96] = 127, + [1][0][RTW89_QATAR][1][96] = 127, + [1][0][RTW89_QATAR][0][96] = 127, + [1][0][RTW89_UK][1][96] = 127, + [1][0][RTW89_UK][0][96] = 127, + [1][0][RTW89_FCC][1][98] = -4, + [1][0][RTW89_FCC][2][98] = 127, + [1][0][RTW89_ETSI][1][98] = 127, + [1][0][RTW89_ETSI][0][98] = 127, + [1][0][RTW89_MKK][1][98] = 127, + [1][0][RTW89_MKK][0][98] = 127, + [1][0][RTW89_IC][1][98] = -4, + [1][0][RTW89_KCC][1][98] = -2, + [1][0][RTW89_KCC][0][98] = 127, + [1][0][RTW89_ACMA][1][98] = 127, + [1][0][RTW89_ACMA][0][98] = 127, + [1][0][RTW89_CHILE][1][98] = 127, + [1][0][RTW89_QATAR][1][98] = 127, + [1][0][RTW89_QATAR][0][98] = 127, + [1][0][RTW89_UK][1][98] = 127, + [1][0][RTW89_UK][0][98] = 127, + [1][0][RTW89_FCC][1][100] = -4, + [1][0][RTW89_FCC][2][100] = 127, + [1][0][RTW89_ETSI][1][100] = 127, + [1][0][RTW89_ETSI][0][100] = 127, + [1][0][RTW89_MKK][1][100] = 127, + [1][0][RTW89_MKK][0][100] = 127, + [1][0][RTW89_IC][1][100] = -4, + [1][0][RTW89_KCC][1][100] = -2, + [1][0][RTW89_KCC][0][100] = 127, + [1][0][RTW89_ACMA][1][100] = 127, + [1][0][RTW89_ACMA][0][100] = 127, + [1][0][RTW89_CHILE][1][100] = 127, + [1][0][RTW89_QATAR][1][100] = 127, + [1][0][RTW89_QATAR][0][100] = 127, + [1][0][RTW89_UK][1][100] = 127, + [1][0][RTW89_UK][0][100] = 127, + [1][0][RTW89_FCC][1][102] = -4, + [1][0][RTW89_FCC][2][102] = 127, + [1][0][RTW89_ETSI][1][102] = 127, + [1][0][RTW89_ETSI][0][102] = 127, + [1][0][RTW89_MKK][1][102] = 127, + [1][0][RTW89_MKK][0][102] = 127, + [1][0][RTW89_IC][1][102] = -4, + [1][0][RTW89_KCC][1][102] = -2, + [1][0][RTW89_KCC][0][102] = 127, + [1][0][RTW89_ACMA][1][102] = 127, + [1][0][RTW89_ACMA][0][102] = 127, + [1][0][RTW89_CHILE][1][102] = 127, + [1][0][RTW89_QATAR][1][102] = 127, + [1][0][RTW89_QATAR][0][102] = 127, + [1][0][RTW89_UK][1][102] = 127, + [1][0][RTW89_UK][0][102] = 127, + [1][0][RTW89_FCC][1][104] = -4, + [1][0][RTW89_FCC][2][104] = 127, + [1][0][RTW89_ETSI][1][104] = 127, + [1][0][RTW89_ETSI][0][104] = 127, + [1][0][RTW89_MKK][1][104] = 127, + [1][0][RTW89_MKK][0][104] = 127, + [1][0][RTW89_IC][1][104] = -4, + [1][0][RTW89_KCC][1][104] = -2, + [1][0][RTW89_KCC][0][104] = 127, + [1][0][RTW89_ACMA][1][104] = 127, + [1][0][RTW89_ACMA][0][104] = 127, + [1][0][RTW89_CHILE][1][104] = 127, + [1][0][RTW89_QATAR][1][104] = 127, + [1][0][RTW89_QATAR][0][104] = 127, + [1][0][RTW89_UK][1][104] = 127, + [1][0][RTW89_UK][0][104] = 127, + [1][0][RTW89_FCC][1][105] = -4, + [1][0][RTW89_FCC][2][105] = 127, + [1][0][RTW89_ETSI][1][105] = 127, + [1][0][RTW89_ETSI][0][105] = 127, + [1][0][RTW89_MKK][1][105] = 127, + [1][0][RTW89_MKK][0][105] = 127, + [1][0][RTW89_IC][1][105] = -4, + [1][0][RTW89_KCC][1][105] = -2, + [1][0][RTW89_KCC][0][105] = 127, + [1][0][RTW89_ACMA][1][105] = 127, + [1][0][RTW89_ACMA][0][105] = 127, + [1][0][RTW89_CHILE][1][105] = 127, + [1][0][RTW89_QATAR][1][105] = 127, + [1][0][RTW89_QATAR][0][105] = 127, + [1][0][RTW89_UK][1][105] = 127, + [1][0][RTW89_UK][0][105] = 127, + [1][0][RTW89_FCC][1][107] = 1, + [1][0][RTW89_FCC][2][107] = 127, + [1][0][RTW89_ETSI][1][107] = 127, + [1][0][RTW89_ETSI][0][107] = 127, + [1][0][RTW89_MKK][1][107] = 127, + [1][0][RTW89_MKK][0][107] = 127, + [1][0][RTW89_IC][1][107] = 1, + [1][0][RTW89_KCC][1][107] = -2, + [1][0][RTW89_KCC][0][107] = 127, + [1][0][RTW89_ACMA][1][107] = 127, + [1][0][RTW89_ACMA][0][107] = 127, + [1][0][RTW89_CHILE][1][107] = 127, + [1][0][RTW89_QATAR][1][107] = 127, + [1][0][RTW89_QATAR][0][107] = 127, + [1][0][RTW89_UK][1][107] = 127, + [1][0][RTW89_UK][0][107] = 127, + [1][0][RTW89_FCC][1][109] = 2, + [1][0][RTW89_FCC][2][109] = 127, + [1][0][RTW89_ETSI][1][109] = 127, + [1][0][RTW89_ETSI][0][109] = 127, + [1][0][RTW89_MKK][1][109] = 127, + [1][0][RTW89_MKK][0][109] = 127, + [1][0][RTW89_IC][1][109] = 2, + [1][0][RTW89_KCC][1][109] = 127, + [1][0][RTW89_KCC][0][109] = 127, + [1][0][RTW89_ACMA][1][109] = 127, + [1][0][RTW89_ACMA][0][109] = 127, + [1][0][RTW89_CHILE][1][109] = 127, + [1][0][RTW89_QATAR][1][109] = 127, + [1][0][RTW89_QATAR][0][109] = 127, + [1][0][RTW89_UK][1][109] = 127, + [1][0][RTW89_UK][0][109] = 127, + [1][0][RTW89_FCC][1][111] = 127, + [1][0][RTW89_FCC][2][111] = 127, + [1][0][RTW89_ETSI][1][111] = 127, + [1][0][RTW89_ETSI][0][111] = 127, + [1][0][RTW89_MKK][1][111] = 127, + [1][0][RTW89_MKK][0][111] = 127, + [1][0][RTW89_IC][1][111] = 127, + [1][0][RTW89_KCC][1][111] = 127, + [1][0][RTW89_KCC][0][111] = 127, + [1][0][RTW89_ACMA][1][111] = 127, + [1][0][RTW89_ACMA][0][111] = 127, + [1][0][RTW89_CHILE][1][111] = 127, + [1][0][RTW89_QATAR][1][111] = 127, + [1][0][RTW89_QATAR][0][111] = 127, + [1][0][RTW89_UK][1][111] = 127, + [1][0][RTW89_UK][0][111] = 127, + [1][0][RTW89_FCC][1][113] = 127, + [1][0][RTW89_FCC][2][113] = 127, + [1][0][RTW89_ETSI][1][113] = 127, + [1][0][RTW89_ETSI][0][113] = 127, + [1][0][RTW89_MKK][1][113] = 127, + [1][0][RTW89_MKK][0][113] = 127, + [1][0][RTW89_IC][1][113] = 127, + [1][0][RTW89_KCC][1][113] = 127, + [1][0][RTW89_KCC][0][113] = 127, + [1][0][RTW89_ACMA][1][113] = 127, + [1][0][RTW89_ACMA][0][113] = 127, + [1][0][RTW89_CHILE][1][113] = 127, + [1][0][RTW89_QATAR][1][113] = 127, + [1][0][RTW89_QATAR][0][113] = 127, + [1][0][RTW89_UK][1][113] = 127, + [1][0][RTW89_UK][0][113] = 127, + [1][0][RTW89_FCC][1][115] = 127, + [1][0][RTW89_FCC][2][115] = 127, + [1][0][RTW89_ETSI][1][115] = 127, + [1][0][RTW89_ETSI][0][115] = 127, + [1][0][RTW89_MKK][1][115] = 127, + [1][0][RTW89_MKK][0][115] = 127, + [1][0][RTW89_IC][1][115] = 127, + [1][0][RTW89_KCC][1][115] = 127, + [1][0][RTW89_KCC][0][115] = 127, + [1][0][RTW89_ACMA][1][115] = 127, + [1][0][RTW89_ACMA][0][115] = 127, + [1][0][RTW89_CHILE][1][115] = 127, + [1][0][RTW89_QATAR][1][115] = 127, + [1][0][RTW89_QATAR][0][115] = 127, + [1][0][RTW89_UK][1][115] = 127, + [1][0][RTW89_UK][0][115] = 127, + [1][0][RTW89_FCC][1][117] = 127, + [1][0][RTW89_FCC][2][117] = 127, + [1][0][RTW89_ETSI][1][117] = 127, + [1][0][RTW89_ETSI][0][117] = 127, + [1][0][RTW89_MKK][1][117] = 127, + [1][0][RTW89_MKK][0][117] = 127, + [1][0][RTW89_IC][1][117] = 127, + [1][0][RTW89_KCC][1][117] = 127, + [1][0][RTW89_KCC][0][117] = 127, + [1][0][RTW89_ACMA][1][117] = 127, + [1][0][RTW89_ACMA][0][117] = 127, + [1][0][RTW89_CHILE][1][117] = 127, + [1][0][RTW89_QATAR][1][117] = 127, + [1][0][RTW89_QATAR][0][117] = 127, + [1][0][RTW89_UK][1][117] = 127, + [1][0][RTW89_UK][0][117] = 127, + [1][0][RTW89_FCC][1][119] = 127, + [1][0][RTW89_FCC][2][119] = 127, + [1][0][RTW89_ETSI][1][119] = 127, + [1][0][RTW89_ETSI][0][119] = 127, + [1][0][RTW89_MKK][1][119] = 127, + [1][0][RTW89_MKK][0][119] = 127, + [1][0][RTW89_IC][1][119] = 127, + [1][0][RTW89_KCC][1][119] = 127, + [1][0][RTW89_KCC][0][119] = 127, + [1][0][RTW89_ACMA][1][119] = 127, + [1][0][RTW89_ACMA][0][119] = 127, + [1][0][RTW89_CHILE][1][119] = 127, + [1][0][RTW89_QATAR][1][119] = 127, + [1][0][RTW89_QATAR][0][119] = 127, + [1][0][RTW89_UK][1][119] = 127, + [1][0][RTW89_UK][0][119] = 127, + [1][1][RTW89_FCC][1][0] = -26, + [1][1][RTW89_FCC][2][0] = 44, + [1][1][RTW89_ETSI][1][0] = 32, + [1][1][RTW89_ETSI][0][0] = -6, + [1][1][RTW89_MKK][1][0] = 30, + [1][1][RTW89_MKK][0][0] = -10, + [1][1][RTW89_IC][1][0] = -26, + [1][1][RTW89_KCC][1][0] = -14, + [1][1][RTW89_KCC][0][0] = -14, + [1][1][RTW89_ACMA][1][0] = 32, + [1][1][RTW89_ACMA][0][0] = -6, + [1][1][RTW89_CHILE][1][0] = -26, + [1][1][RTW89_QATAR][1][0] = 32, + [1][1][RTW89_QATAR][0][0] = -6, + [1][1][RTW89_UK][1][0] = 32, + [1][1][RTW89_UK][0][0] = -6, + [1][1][RTW89_FCC][1][2] = -28, + [1][1][RTW89_FCC][2][2] = 44, + [1][1][RTW89_ETSI][1][2] = 32, + [1][1][RTW89_ETSI][0][2] = -6, + [1][1][RTW89_MKK][1][2] = 30, + [1][1][RTW89_MKK][0][2] = -10, + [1][1][RTW89_IC][1][2] = -28, + [1][1][RTW89_KCC][1][2] = -14, + [1][1][RTW89_KCC][0][2] = -14, + [1][1][RTW89_ACMA][1][2] = 32, + [1][1][RTW89_ACMA][0][2] = -6, + [1][1][RTW89_CHILE][1][2] = -28, + [1][1][RTW89_QATAR][1][2] = 32, + [1][1][RTW89_QATAR][0][2] = -6, + [1][1][RTW89_UK][1][2] = 32, + [1][1][RTW89_UK][0][2] = -6, + [1][1][RTW89_FCC][1][4] = -28, + [1][1][RTW89_FCC][2][4] = 44, + [1][1][RTW89_ETSI][1][4] = 32, + [1][1][RTW89_ETSI][0][4] = -6, + [1][1][RTW89_MKK][1][4] = 30, + [1][1][RTW89_MKK][0][4] = -10, + [1][1][RTW89_IC][1][4] = -28, + [1][1][RTW89_KCC][1][4] = -14, + [1][1][RTW89_KCC][0][4] = -14, + [1][1][RTW89_ACMA][1][4] = 32, + [1][1][RTW89_ACMA][0][4] = -6, + [1][1][RTW89_CHILE][1][4] = -28, + [1][1][RTW89_QATAR][1][4] = 32, + [1][1][RTW89_QATAR][0][4] = -6, + [1][1][RTW89_UK][1][4] = 32, + [1][1][RTW89_UK][0][4] = -6, + [1][1][RTW89_FCC][1][6] = -28, + [1][1][RTW89_FCC][2][6] = 44, + [1][1][RTW89_ETSI][1][6] = 32, + [1][1][RTW89_ETSI][0][6] = -6, + [1][1][RTW89_MKK][1][6] = 30, + [1][1][RTW89_MKK][0][6] = -10, + [1][1][RTW89_IC][1][6] = -28, + [1][1][RTW89_KCC][1][6] = -14, + [1][1][RTW89_KCC][0][6] = -14, + [1][1][RTW89_ACMA][1][6] = 32, + [1][1][RTW89_ACMA][0][6] = -6, + [1][1][RTW89_CHILE][1][6] = -28, + [1][1][RTW89_QATAR][1][6] = 32, + [1][1][RTW89_QATAR][0][6] = -6, + [1][1][RTW89_UK][1][6] = 32, + [1][1][RTW89_UK][0][6] = -6, + [1][1][RTW89_FCC][1][8] = -28, + [1][1][RTW89_FCC][2][8] = 44, + [1][1][RTW89_ETSI][1][8] = 32, + [1][1][RTW89_ETSI][0][8] = -6, + [1][1][RTW89_MKK][1][8] = 30, + [1][1][RTW89_MKK][0][8] = -10, + [1][1][RTW89_IC][1][8] = -28, + [1][1][RTW89_KCC][1][8] = -14, + [1][1][RTW89_KCC][0][8] = -14, + [1][1][RTW89_ACMA][1][8] = 32, + [1][1][RTW89_ACMA][0][8] = -6, + [1][1][RTW89_CHILE][1][8] = -28, + [1][1][RTW89_QATAR][1][8] = 32, + [1][1][RTW89_QATAR][0][8] = -6, + [1][1][RTW89_UK][1][8] = 32, + [1][1][RTW89_UK][0][8] = -6, + [1][1][RTW89_FCC][1][10] = -28, + [1][1][RTW89_FCC][2][10] = 44, + [1][1][RTW89_ETSI][1][10] = 32, + [1][1][RTW89_ETSI][0][10] = -6, + [1][1][RTW89_MKK][1][10] = 30, + [1][1][RTW89_MKK][0][10] = -10, + [1][1][RTW89_IC][1][10] = -28, + [1][1][RTW89_KCC][1][10] = -14, + [1][1][RTW89_KCC][0][10] = -14, + [1][1][RTW89_ACMA][1][10] = 32, + [1][1][RTW89_ACMA][0][10] = -6, + [1][1][RTW89_CHILE][1][10] = -28, + [1][1][RTW89_QATAR][1][10] = 32, + [1][1][RTW89_QATAR][0][10] = -6, + [1][1][RTW89_UK][1][10] = 32, + [1][1][RTW89_UK][0][10] = -6, + [1][1][RTW89_FCC][1][12] = -28, + [1][1][RTW89_FCC][2][12] = 44, + [1][1][RTW89_ETSI][1][12] = 32, + [1][1][RTW89_ETSI][0][12] = -6, + [1][1][RTW89_MKK][1][12] = 30, + [1][1][RTW89_MKK][0][12] = -10, + [1][1][RTW89_IC][1][12] = -28, + [1][1][RTW89_KCC][1][12] = -14, + [1][1][RTW89_KCC][0][12] = -14, + [1][1][RTW89_ACMA][1][12] = 32, + [1][1][RTW89_ACMA][0][12] = -6, + [1][1][RTW89_CHILE][1][12] = -28, + [1][1][RTW89_QATAR][1][12] = 32, + [1][1][RTW89_QATAR][0][12] = -6, + [1][1][RTW89_UK][1][12] = 32, + [1][1][RTW89_UK][0][12] = -6, + [1][1][RTW89_FCC][1][14] = -28, + [1][1][RTW89_FCC][2][14] = 44, + [1][1][RTW89_ETSI][1][14] = 32, + [1][1][RTW89_ETSI][0][14] = -6, + [1][1][RTW89_MKK][1][14] = 30, + [1][1][RTW89_MKK][0][14] = -10, + [1][1][RTW89_IC][1][14] = -28, + [1][1][RTW89_KCC][1][14] = -14, + [1][1][RTW89_KCC][0][14] = -14, + [1][1][RTW89_ACMA][1][14] = 32, + [1][1][RTW89_ACMA][0][14] = -6, + [1][1][RTW89_CHILE][1][14] = -28, + [1][1][RTW89_QATAR][1][14] = 32, + [1][1][RTW89_QATAR][0][14] = -6, + [1][1][RTW89_UK][1][14] = 32, + [1][1][RTW89_UK][0][14] = -6, + [1][1][RTW89_FCC][1][15] = -28, + [1][1][RTW89_FCC][2][15] = 44, + [1][1][RTW89_ETSI][1][15] = 32, + [1][1][RTW89_ETSI][0][15] = -6, + [1][1][RTW89_MKK][1][15] = 30, + [1][1][RTW89_MKK][0][15] = -10, + [1][1][RTW89_IC][1][15] = -28, + [1][1][RTW89_KCC][1][15] = -14, + [1][1][RTW89_KCC][0][15] = -14, + [1][1][RTW89_ACMA][1][15] = 32, + [1][1][RTW89_ACMA][0][15] = -6, + [1][1][RTW89_CHILE][1][15] = -28, + [1][1][RTW89_QATAR][1][15] = 32, + [1][1][RTW89_QATAR][0][15] = -6, + [1][1][RTW89_UK][1][15] = 32, + [1][1][RTW89_UK][0][15] = -6, + [1][1][RTW89_FCC][1][17] = -28, + [1][1][RTW89_FCC][2][17] = 44, + [1][1][RTW89_ETSI][1][17] = 32, + [1][1][RTW89_ETSI][0][17] = -6, + [1][1][RTW89_MKK][1][17] = 30, + [1][1][RTW89_MKK][0][17] = -10, + [1][1][RTW89_IC][1][17] = -28, + [1][1][RTW89_KCC][1][17] = -14, + [1][1][RTW89_KCC][0][17] = -14, + [1][1][RTW89_ACMA][1][17] = 32, + [1][1][RTW89_ACMA][0][17] = -6, + [1][1][RTW89_CHILE][1][17] = -28, + [1][1][RTW89_QATAR][1][17] = 32, + [1][1][RTW89_QATAR][0][17] = -6, + [1][1][RTW89_UK][1][17] = 32, + [1][1][RTW89_UK][0][17] = -6, + [1][1][RTW89_FCC][1][19] = -28, + [1][1][RTW89_FCC][2][19] = 44, + [1][1][RTW89_ETSI][1][19] = 32, + [1][1][RTW89_ETSI][0][19] = -6, + [1][1][RTW89_MKK][1][19] = 30, + [1][1][RTW89_MKK][0][19] = -10, + [1][1][RTW89_IC][1][19] = -28, + [1][1][RTW89_KCC][1][19] = -14, + [1][1][RTW89_KCC][0][19] = -14, + [1][1][RTW89_ACMA][1][19] = 32, + [1][1][RTW89_ACMA][0][19] = -6, + [1][1][RTW89_CHILE][1][19] = -28, + [1][1][RTW89_QATAR][1][19] = 32, + [1][1][RTW89_QATAR][0][19] = -6, + [1][1][RTW89_UK][1][19] = 32, + [1][1][RTW89_UK][0][19] = -6, + [1][1][RTW89_FCC][1][21] = -28, + [1][1][RTW89_FCC][2][21] = 44, + [1][1][RTW89_ETSI][1][21] = 32, + [1][1][RTW89_ETSI][0][21] = -6, + [1][1][RTW89_MKK][1][21] = 30, + [1][1][RTW89_MKK][0][21] = -10, + [1][1][RTW89_IC][1][21] = -28, + [1][1][RTW89_KCC][1][21] = -14, + [1][1][RTW89_KCC][0][21] = -14, + [1][1][RTW89_ACMA][1][21] = 32, + [1][1][RTW89_ACMA][0][21] = -6, + [1][1][RTW89_CHILE][1][21] = -28, + [1][1][RTW89_QATAR][1][21] = 32, + [1][1][RTW89_QATAR][0][21] = -6, + [1][1][RTW89_UK][1][21] = 32, + [1][1][RTW89_UK][0][21] = -6, + [1][1][RTW89_FCC][1][23] = -28, + [1][1][RTW89_FCC][2][23] = 44, + [1][1][RTW89_ETSI][1][23] = 32, + [1][1][RTW89_ETSI][0][23] = -6, + [1][1][RTW89_MKK][1][23] = 32, + [1][1][RTW89_MKK][0][23] = -10, + [1][1][RTW89_IC][1][23] = -28, + [1][1][RTW89_KCC][1][23] = -14, + [1][1][RTW89_KCC][0][23] = -14, + [1][1][RTW89_ACMA][1][23] = 32, + [1][1][RTW89_ACMA][0][23] = -6, + [1][1][RTW89_CHILE][1][23] = -28, + [1][1][RTW89_QATAR][1][23] = 32, + [1][1][RTW89_QATAR][0][23] = -6, + [1][1][RTW89_UK][1][23] = 32, + [1][1][RTW89_UK][0][23] = -6, + [1][1][RTW89_FCC][1][25] = -28, + [1][1][RTW89_FCC][2][25] = 44, + [1][1][RTW89_ETSI][1][25] = 32, + [1][1][RTW89_ETSI][0][25] = -6, + [1][1][RTW89_MKK][1][25] = 32, + [1][1][RTW89_MKK][0][25] = -10, + [1][1][RTW89_IC][1][25] = -28, + [1][1][RTW89_KCC][1][25] = -14, + [1][1][RTW89_KCC][0][25] = -14, + [1][1][RTW89_ACMA][1][25] = 32, + [1][1][RTW89_ACMA][0][25] = -6, + [1][1][RTW89_CHILE][1][25] = -28, + [1][1][RTW89_QATAR][1][25] = 32, + [1][1][RTW89_QATAR][0][25] = -6, + [1][1][RTW89_UK][1][25] = 32, + [1][1][RTW89_UK][0][25] = -6, + [1][1][RTW89_FCC][1][27] = -28, + [1][1][RTW89_FCC][2][27] = 44, + [1][1][RTW89_ETSI][1][27] = 32, + [1][1][RTW89_ETSI][0][27] = -6, + [1][1][RTW89_MKK][1][27] = 32, + [1][1][RTW89_MKK][0][27] = -10, + [1][1][RTW89_IC][1][27] = -28, + [1][1][RTW89_KCC][1][27] = -14, + [1][1][RTW89_KCC][0][27] = -14, + [1][1][RTW89_ACMA][1][27] = 32, + [1][1][RTW89_ACMA][0][27] = -6, + [1][1][RTW89_CHILE][1][27] = -28, + [1][1][RTW89_QATAR][1][27] = 32, + [1][1][RTW89_QATAR][0][27] = -6, + [1][1][RTW89_UK][1][27] = 32, + [1][1][RTW89_UK][0][27] = -6, + [1][1][RTW89_FCC][1][29] = -28, + [1][1][RTW89_FCC][2][29] = 44, + [1][1][RTW89_ETSI][1][29] = 32, + [1][1][RTW89_ETSI][0][29] = -6, + [1][1][RTW89_MKK][1][29] = 32, + [1][1][RTW89_MKK][0][29] = -10, + [1][1][RTW89_IC][1][29] = -28, + [1][1][RTW89_KCC][1][29] = -14, + [1][1][RTW89_KCC][0][29] = -14, + [1][1][RTW89_ACMA][1][29] = 32, + [1][1][RTW89_ACMA][0][29] = -6, + [1][1][RTW89_CHILE][1][29] = -28, + [1][1][RTW89_QATAR][1][29] = 32, + [1][1][RTW89_QATAR][0][29] = -6, + [1][1][RTW89_UK][1][29] = 32, + [1][1][RTW89_UK][0][29] = -6, + [1][1][RTW89_FCC][1][30] = -28, + [1][1][RTW89_FCC][2][30] = 44, + [1][1][RTW89_ETSI][1][30] = 32, + [1][1][RTW89_ETSI][0][30] = -6, + [1][1][RTW89_MKK][1][30] = 32, + [1][1][RTW89_MKK][0][30] = -10, + [1][1][RTW89_IC][1][30] = -28, + [1][1][RTW89_KCC][1][30] = -14, + [1][1][RTW89_KCC][0][30] = -14, + [1][1][RTW89_ACMA][1][30] = 32, + [1][1][RTW89_ACMA][0][30] = -6, + [1][1][RTW89_CHILE][1][30] = -28, + [1][1][RTW89_QATAR][1][30] = 32, + [1][1][RTW89_QATAR][0][30] = -6, + [1][1][RTW89_UK][1][30] = 32, + [1][1][RTW89_UK][0][30] = -6, + [1][1][RTW89_FCC][1][32] = -28, + [1][1][RTW89_FCC][2][32] = 44, + [1][1][RTW89_ETSI][1][32] = 32, + [1][1][RTW89_ETSI][0][32] = -6, + [1][1][RTW89_MKK][1][32] = 32, + [1][1][RTW89_MKK][0][32] = -10, + [1][1][RTW89_IC][1][32] = -28, + [1][1][RTW89_KCC][1][32] = -14, + [1][1][RTW89_KCC][0][32] = -14, + [1][1][RTW89_ACMA][1][32] = 32, + [1][1][RTW89_ACMA][0][32] = -6, + [1][1][RTW89_CHILE][1][32] = -28, + [1][1][RTW89_QATAR][1][32] = 32, + [1][1][RTW89_QATAR][0][32] = -6, + [1][1][RTW89_UK][1][32] = 32, + [1][1][RTW89_UK][0][32] = -6, + [1][1][RTW89_FCC][1][34] = -28, + [1][1][RTW89_FCC][2][34] = 44, + [1][1][RTW89_ETSI][1][34] = 32, + [1][1][RTW89_ETSI][0][34] = -6, + [1][1][RTW89_MKK][1][34] = 32, + [1][1][RTW89_MKK][0][34] = -10, + [1][1][RTW89_IC][1][34] = -28, + [1][1][RTW89_KCC][1][34] = -14, + [1][1][RTW89_KCC][0][34] = -14, + [1][1][RTW89_ACMA][1][34] = 32, + [1][1][RTW89_ACMA][0][34] = -6, + [1][1][RTW89_CHILE][1][34] = -28, + [1][1][RTW89_QATAR][1][34] = 32, + [1][1][RTW89_QATAR][0][34] = -6, + [1][1][RTW89_UK][1][34] = 32, + [1][1][RTW89_UK][0][34] = -6, + [1][1][RTW89_FCC][1][36] = -28, + [1][1][RTW89_FCC][2][36] = 44, + [1][1][RTW89_ETSI][1][36] = 32, + [1][1][RTW89_ETSI][0][36] = -6, + [1][1][RTW89_MKK][1][36] = 32, + [1][1][RTW89_MKK][0][36] = -10, + [1][1][RTW89_IC][1][36] = -28, + [1][1][RTW89_KCC][1][36] = -14, + [1][1][RTW89_KCC][0][36] = -14, + [1][1][RTW89_ACMA][1][36] = 32, + [1][1][RTW89_ACMA][0][36] = -6, + [1][1][RTW89_CHILE][1][36] = -28, + [1][1][RTW89_QATAR][1][36] = 32, + [1][1][RTW89_QATAR][0][36] = -6, + [1][1][RTW89_UK][1][36] = 32, + [1][1][RTW89_UK][0][36] = -6, + [1][1][RTW89_FCC][1][38] = -28, + [1][1][RTW89_FCC][2][38] = 44, + [1][1][RTW89_ETSI][1][38] = 32, + [1][1][RTW89_ETSI][0][38] = -6, + [1][1][RTW89_MKK][1][38] = 32, + [1][1][RTW89_MKK][0][38] = -10, + [1][1][RTW89_IC][1][38] = -28, + [1][1][RTW89_KCC][1][38] = -14, + [1][1][RTW89_KCC][0][38] = -14, + [1][1][RTW89_ACMA][1][38] = 32, + [1][1][RTW89_ACMA][0][38] = -6, + [1][1][RTW89_CHILE][1][38] = -28, + [1][1][RTW89_QATAR][1][38] = 32, + [1][1][RTW89_QATAR][0][38] = -6, + [1][1][RTW89_UK][1][38] = 32, + [1][1][RTW89_UK][0][38] = -6, + [1][1][RTW89_FCC][1][40] = -28, + [1][1][RTW89_FCC][2][40] = 44, + [1][1][RTW89_ETSI][1][40] = 32, + [1][1][RTW89_ETSI][0][40] = -6, + [1][1][RTW89_MKK][1][40] = 32, + [1][1][RTW89_MKK][0][40] = -10, + [1][1][RTW89_IC][1][40] = -28, + [1][1][RTW89_KCC][1][40] = -14, + [1][1][RTW89_KCC][0][40] = -14, + [1][1][RTW89_ACMA][1][40] = 32, + [1][1][RTW89_ACMA][0][40] = -6, + [1][1][RTW89_CHILE][1][40] = -28, + [1][1][RTW89_QATAR][1][40] = 32, + [1][1][RTW89_QATAR][0][40] = -6, + [1][1][RTW89_UK][1][40] = 32, + [1][1][RTW89_UK][0][40] = -6, + [1][1][RTW89_FCC][1][42] = -28, + [1][1][RTW89_FCC][2][42] = 44, + [1][1][RTW89_ETSI][1][42] = 32, + [1][1][RTW89_ETSI][0][42] = -6, + [1][1][RTW89_MKK][1][42] = 32, + [1][1][RTW89_MKK][0][42] = -10, + [1][1][RTW89_IC][1][42] = -28, + [1][1][RTW89_KCC][1][42] = -14, + [1][1][RTW89_KCC][0][42] = -14, + [1][1][RTW89_ACMA][1][42] = 32, + [1][1][RTW89_ACMA][0][42] = -6, + [1][1][RTW89_CHILE][1][42] = -28, + [1][1][RTW89_QATAR][1][42] = 32, + [1][1][RTW89_QATAR][0][42] = -6, + [1][1][RTW89_UK][1][42] = 32, + [1][1][RTW89_UK][0][42] = -6, + [1][1][RTW89_FCC][1][44] = -28, + [1][1][RTW89_FCC][2][44] = 44, + [1][1][RTW89_ETSI][1][44] = 34, + [1][1][RTW89_ETSI][0][44] = -4, + [1][1][RTW89_MKK][1][44] = 4, + [1][1][RTW89_MKK][0][44] = -8, + [1][1][RTW89_IC][1][44] = -28, + [1][1][RTW89_KCC][1][44] = -14, + [1][1][RTW89_KCC][0][44] = -14, + [1][1][RTW89_ACMA][1][44] = 34, + [1][1][RTW89_ACMA][0][44] = -4, + [1][1][RTW89_CHILE][1][44] = -28, + [1][1][RTW89_QATAR][1][44] = 34, + [1][1][RTW89_QATAR][0][44] = -4, + [1][1][RTW89_UK][1][44] = 34, + [1][1][RTW89_UK][0][44] = -4, + [1][1][RTW89_FCC][1][45] = -26, + [1][1][RTW89_FCC][2][45] = 127, + [1][1][RTW89_ETSI][1][45] = 127, + [1][1][RTW89_ETSI][0][45] = 127, + [1][1][RTW89_MKK][1][45] = 127, + [1][1][RTW89_MKK][0][45] = 127, + [1][1][RTW89_IC][1][45] = -26, + [1][1][RTW89_KCC][1][45] = -14, + [1][1][RTW89_KCC][0][45] = 127, + [1][1][RTW89_ACMA][1][45] = 127, + [1][1][RTW89_ACMA][0][45] = 127, + [1][1][RTW89_CHILE][1][45] = 127, + [1][1][RTW89_QATAR][1][45] = 127, + [1][1][RTW89_QATAR][0][45] = 127, + [1][1][RTW89_UK][1][45] = 127, + [1][1][RTW89_UK][0][45] = 127, + [1][1][RTW89_FCC][1][47] = -28, + [1][1][RTW89_FCC][2][47] = 127, + [1][1][RTW89_ETSI][1][47] = 127, + [1][1][RTW89_ETSI][0][47] = 127, + [1][1][RTW89_MKK][1][47] = 127, + [1][1][RTW89_MKK][0][47] = 127, + [1][1][RTW89_IC][1][47] = -28, + [1][1][RTW89_KCC][1][47] = -14, + [1][1][RTW89_KCC][0][47] = 127, + [1][1][RTW89_ACMA][1][47] = 127, + [1][1][RTW89_ACMA][0][47] = 127, + [1][1][RTW89_CHILE][1][47] = 127, + [1][1][RTW89_QATAR][1][47] = 127, + [1][1][RTW89_QATAR][0][47] = 127, + [1][1][RTW89_UK][1][47] = 127, + [1][1][RTW89_UK][0][47] = 127, + [1][1][RTW89_FCC][1][49] = -28, + [1][1][RTW89_FCC][2][49] = 127, + [1][1][RTW89_ETSI][1][49] = 127, + [1][1][RTW89_ETSI][0][49] = 127, + [1][1][RTW89_MKK][1][49] = 127, + [1][1][RTW89_MKK][0][49] = 127, + [1][1][RTW89_IC][1][49] = -28, + [1][1][RTW89_KCC][1][49] = -14, + [1][1][RTW89_KCC][0][49] = 127, + [1][1][RTW89_ACMA][1][49] = 127, + [1][1][RTW89_ACMA][0][49] = 127, + [1][1][RTW89_CHILE][1][49] = 127, + [1][1][RTW89_QATAR][1][49] = 127, + [1][1][RTW89_QATAR][0][49] = 127, + [1][1][RTW89_UK][1][49] = 127, + [1][1][RTW89_UK][0][49] = 127, + [1][1][RTW89_FCC][1][51] = -28, + [1][1][RTW89_FCC][2][51] = 127, + [1][1][RTW89_ETSI][1][51] = 127, + [1][1][RTW89_ETSI][0][51] = 127, + [1][1][RTW89_MKK][1][51] = 127, + [1][1][RTW89_MKK][0][51] = 127, + [1][1][RTW89_IC][1][51] = -28, + [1][1][RTW89_KCC][1][51] = -14, + [1][1][RTW89_KCC][0][51] = 127, + [1][1][RTW89_ACMA][1][51] = 127, + [1][1][RTW89_ACMA][0][51] = 127, + [1][1][RTW89_CHILE][1][51] = 127, + [1][1][RTW89_QATAR][1][51] = 127, + [1][1][RTW89_QATAR][0][51] = 127, + [1][1][RTW89_UK][1][51] = 127, + [1][1][RTW89_UK][0][51] = 127, + [1][1][RTW89_FCC][1][53] = -26, + [1][1][RTW89_FCC][2][53] = 127, + [1][1][RTW89_ETSI][1][53] = 127, + [1][1][RTW89_ETSI][0][53] = 127, + [1][1][RTW89_MKK][1][53] = 127, + [1][1][RTW89_MKK][0][53] = 127, + [1][1][RTW89_IC][1][53] = -26, + [1][1][RTW89_KCC][1][53] = -14, + [1][1][RTW89_KCC][0][53] = 127, + [1][1][RTW89_ACMA][1][53] = 127, + [1][1][RTW89_ACMA][0][53] = 127, + [1][1][RTW89_CHILE][1][53] = 127, + [1][1][RTW89_QATAR][1][53] = 127, + [1][1][RTW89_QATAR][0][53] = 127, + [1][1][RTW89_UK][1][53] = 127, + [1][1][RTW89_UK][0][53] = 127, + [1][1][RTW89_FCC][1][55] = -28, + [1][1][RTW89_FCC][2][55] = 44, + [1][1][RTW89_ETSI][1][55] = 127, + [1][1][RTW89_ETSI][0][55] = 127, + [1][1][RTW89_MKK][1][55] = 127, + [1][1][RTW89_MKK][0][55] = 127, + [1][1][RTW89_IC][1][55] = -28, + [1][1][RTW89_KCC][1][55] = -14, + [1][1][RTW89_KCC][0][55] = 127, + [1][1][RTW89_ACMA][1][55] = 127, + [1][1][RTW89_ACMA][0][55] = 127, + [1][1][RTW89_CHILE][1][55] = 127, + [1][1][RTW89_QATAR][1][55] = 127, + [1][1][RTW89_QATAR][0][55] = 127, + [1][1][RTW89_UK][1][55] = 127, + [1][1][RTW89_UK][0][55] = 127, + [1][1][RTW89_FCC][1][57] = -28, + [1][1][RTW89_FCC][2][57] = 44, + [1][1][RTW89_ETSI][1][57] = 127, + [1][1][RTW89_ETSI][0][57] = 127, + [1][1][RTW89_MKK][1][57] = 127, + [1][1][RTW89_MKK][0][57] = 127, + [1][1][RTW89_IC][1][57] = -28, + [1][1][RTW89_KCC][1][57] = -14, + [1][1][RTW89_KCC][0][57] = 127, + [1][1][RTW89_ACMA][1][57] = 127, + [1][1][RTW89_ACMA][0][57] = 127, + [1][1][RTW89_CHILE][1][57] = 127, + [1][1][RTW89_QATAR][1][57] = 127, + [1][1][RTW89_QATAR][0][57] = 127, + [1][1][RTW89_UK][1][57] = 127, + [1][1][RTW89_UK][0][57] = 127, + [1][1][RTW89_FCC][1][59] = -28, + [1][1][RTW89_FCC][2][59] = 44, + [1][1][RTW89_ETSI][1][59] = 127, + [1][1][RTW89_ETSI][0][59] = 127, + [1][1][RTW89_MKK][1][59] = 127, + [1][1][RTW89_MKK][0][59] = 127, + [1][1][RTW89_IC][1][59] = -28, + [1][1][RTW89_KCC][1][59] = -14, + [1][1][RTW89_KCC][0][59] = 127, + [1][1][RTW89_ACMA][1][59] = 127, + [1][1][RTW89_ACMA][0][59] = 127, + [1][1][RTW89_CHILE][1][59] = 127, + [1][1][RTW89_QATAR][1][59] = 127, + [1][1][RTW89_QATAR][0][59] = 127, + [1][1][RTW89_UK][1][59] = 127, + [1][1][RTW89_UK][0][59] = 127, + [1][1][RTW89_FCC][1][60] = -28, + [1][1][RTW89_FCC][2][60] = 44, + [1][1][RTW89_ETSI][1][60] = 127, + [1][1][RTW89_ETSI][0][60] = 127, + [1][1][RTW89_MKK][1][60] = 127, + [1][1][RTW89_MKK][0][60] = 127, + [1][1][RTW89_IC][1][60] = -28, + [1][1][RTW89_KCC][1][60] = -14, + [1][1][RTW89_KCC][0][60] = 127, + [1][1][RTW89_ACMA][1][60] = 127, + [1][1][RTW89_ACMA][0][60] = 127, + [1][1][RTW89_CHILE][1][60] = 127, + [1][1][RTW89_QATAR][1][60] = 127, + [1][1][RTW89_QATAR][0][60] = 127, + [1][1][RTW89_UK][1][60] = 127, + [1][1][RTW89_UK][0][60] = 127, + [1][1][RTW89_FCC][1][62] = -28, + [1][1][RTW89_FCC][2][62] = 44, + [1][1][RTW89_ETSI][1][62] = 127, + [1][1][RTW89_ETSI][0][62] = 127, + [1][1][RTW89_MKK][1][62] = 127, + [1][1][RTW89_MKK][0][62] = 127, + [1][1][RTW89_IC][1][62] = -28, + [1][1][RTW89_KCC][1][62] = -14, + [1][1][RTW89_KCC][0][62] = 127, + [1][1][RTW89_ACMA][1][62] = 127, + [1][1][RTW89_ACMA][0][62] = 127, + [1][1][RTW89_CHILE][1][62] = 127, + [1][1][RTW89_QATAR][1][62] = 127, + [1][1][RTW89_QATAR][0][62] = 127, + [1][1][RTW89_UK][1][62] = 127, + [1][1][RTW89_UK][0][62] = 127, + [1][1][RTW89_FCC][1][64] = -28, + [1][1][RTW89_FCC][2][64] = 44, + [1][1][RTW89_ETSI][1][64] = 127, + [1][1][RTW89_ETSI][0][64] = 127, + [1][1][RTW89_MKK][1][64] = 127, + [1][1][RTW89_MKK][0][64] = 127, + [1][1][RTW89_IC][1][64] = -28, + [1][1][RTW89_KCC][1][64] = -14, + [1][1][RTW89_KCC][0][64] = 127, + [1][1][RTW89_ACMA][1][64] = 127, + [1][1][RTW89_ACMA][0][64] = 127, + [1][1][RTW89_CHILE][1][64] = 127, + [1][1][RTW89_QATAR][1][64] = 127, + [1][1][RTW89_QATAR][0][64] = 127, + [1][1][RTW89_UK][1][64] = 127, + [1][1][RTW89_UK][0][64] = 127, + [1][1][RTW89_FCC][1][66] = -28, + [1][1][RTW89_FCC][2][66] = 44, + [1][1][RTW89_ETSI][1][66] = 127, + [1][1][RTW89_ETSI][0][66] = 127, + [1][1][RTW89_MKK][1][66] = 127, + [1][1][RTW89_MKK][0][66] = 127, + [1][1][RTW89_IC][1][66] = -28, + [1][1][RTW89_KCC][1][66] = -14, + [1][1][RTW89_KCC][0][66] = 127, + [1][1][RTW89_ACMA][1][66] = 127, + [1][1][RTW89_ACMA][0][66] = 127, + [1][1][RTW89_CHILE][1][66] = 127, + [1][1][RTW89_QATAR][1][66] = 127, + [1][1][RTW89_QATAR][0][66] = 127, + [1][1][RTW89_UK][1][66] = 127, + [1][1][RTW89_UK][0][66] = 127, + [1][1][RTW89_FCC][1][68] = -28, + [1][1][RTW89_FCC][2][68] = 44, + [1][1][RTW89_ETSI][1][68] = 127, + [1][1][RTW89_ETSI][0][68] = 127, + [1][1][RTW89_MKK][1][68] = 127, + [1][1][RTW89_MKK][0][68] = 127, + [1][1][RTW89_IC][1][68] = -28, + [1][1][RTW89_KCC][1][68] = -14, + [1][1][RTW89_KCC][0][68] = 127, + [1][1][RTW89_ACMA][1][68] = 127, + [1][1][RTW89_ACMA][0][68] = 127, + [1][1][RTW89_CHILE][1][68] = 127, + [1][1][RTW89_QATAR][1][68] = 127, + [1][1][RTW89_QATAR][0][68] = 127, + [1][1][RTW89_UK][1][68] = 127, + [1][1][RTW89_UK][0][68] = 127, + [1][1][RTW89_FCC][1][70] = -26, + [1][1][RTW89_FCC][2][70] = 44, + [1][1][RTW89_ETSI][1][70] = 127, + [1][1][RTW89_ETSI][0][70] = 127, + [1][1][RTW89_MKK][1][70] = 127, + [1][1][RTW89_MKK][0][70] = 127, + [1][1][RTW89_IC][1][70] = -26, + [1][1][RTW89_KCC][1][70] = -14, + [1][1][RTW89_KCC][0][70] = 127, + [1][1][RTW89_ACMA][1][70] = 127, + [1][1][RTW89_ACMA][0][70] = 127, + [1][1][RTW89_CHILE][1][70] = 127, + [1][1][RTW89_QATAR][1][70] = 127, + [1][1][RTW89_QATAR][0][70] = 127, + [1][1][RTW89_UK][1][70] = 127, + [1][1][RTW89_UK][0][70] = 127, + [1][1][RTW89_FCC][1][72] = -28, + [1][1][RTW89_FCC][2][72] = 44, + [1][1][RTW89_ETSI][1][72] = 127, + [1][1][RTW89_ETSI][0][72] = 127, + [1][1][RTW89_MKK][1][72] = 127, + [1][1][RTW89_MKK][0][72] = 127, + [1][1][RTW89_IC][1][72] = -28, + [1][1][RTW89_KCC][1][72] = -14, + [1][1][RTW89_KCC][0][72] = 127, + [1][1][RTW89_ACMA][1][72] = 127, + [1][1][RTW89_ACMA][0][72] = 127, + [1][1][RTW89_CHILE][1][72] = 127, + [1][1][RTW89_QATAR][1][72] = 127, + [1][1][RTW89_QATAR][0][72] = 127, + [1][1][RTW89_UK][1][72] = 127, + [1][1][RTW89_UK][0][72] = 127, + [1][1][RTW89_FCC][1][74] = -28, + [1][1][RTW89_FCC][2][74] = 44, + [1][1][RTW89_ETSI][1][74] = 127, + [1][1][RTW89_ETSI][0][74] = 127, + [1][1][RTW89_MKK][1][74] = 127, + [1][1][RTW89_MKK][0][74] = 127, + [1][1][RTW89_IC][1][74] = -28, + [1][1][RTW89_KCC][1][74] = -14, + [1][1][RTW89_KCC][0][74] = 127, + [1][1][RTW89_ACMA][1][74] = 127, + [1][1][RTW89_ACMA][0][74] = 127, + [1][1][RTW89_CHILE][1][74] = 127, + [1][1][RTW89_QATAR][1][74] = 127, + [1][1][RTW89_QATAR][0][74] = 127, + [1][1][RTW89_UK][1][74] = 127, + [1][1][RTW89_UK][0][74] = 127, + [1][1][RTW89_FCC][1][75] = -28, + [1][1][RTW89_FCC][2][75] = 44, + [1][1][RTW89_ETSI][1][75] = 127, + [1][1][RTW89_ETSI][0][75] = 127, + [1][1][RTW89_MKK][1][75] = 127, + [1][1][RTW89_MKK][0][75] = 127, + [1][1][RTW89_IC][1][75] = -28, + [1][1][RTW89_KCC][1][75] = -14, + [1][1][RTW89_KCC][0][75] = 127, + [1][1][RTW89_ACMA][1][75] = 127, + [1][1][RTW89_ACMA][0][75] = 127, + [1][1][RTW89_CHILE][1][75] = 127, + [1][1][RTW89_QATAR][1][75] = 127, + [1][1][RTW89_QATAR][0][75] = 127, + [1][1][RTW89_UK][1][75] = 127, + [1][1][RTW89_UK][0][75] = 127, + [1][1][RTW89_FCC][1][77] = -28, + [1][1][RTW89_FCC][2][77] = 44, + [1][1][RTW89_ETSI][1][77] = 127, + [1][1][RTW89_ETSI][0][77] = 127, + [1][1][RTW89_MKK][1][77] = 127, + [1][1][RTW89_MKK][0][77] = 127, + [1][1][RTW89_IC][1][77] = -28, + [1][1][RTW89_KCC][1][77] = -14, + [1][1][RTW89_KCC][0][77] = 127, + [1][1][RTW89_ACMA][1][77] = 127, + [1][1][RTW89_ACMA][0][77] = 127, + [1][1][RTW89_CHILE][1][77] = 127, + [1][1][RTW89_QATAR][1][77] = 127, + [1][1][RTW89_QATAR][0][77] = 127, + [1][1][RTW89_UK][1][77] = 127, + [1][1][RTW89_UK][0][77] = 127, + [1][1][RTW89_FCC][1][79] = -28, + [1][1][RTW89_FCC][2][79] = 44, + [1][1][RTW89_ETSI][1][79] = 127, + [1][1][RTW89_ETSI][0][79] = 127, + [1][1][RTW89_MKK][1][79] = 127, + [1][1][RTW89_MKK][0][79] = 127, + [1][1][RTW89_IC][1][79] = -28, + [1][1][RTW89_KCC][1][79] = -14, + [1][1][RTW89_KCC][0][79] = 127, + [1][1][RTW89_ACMA][1][79] = 127, + [1][1][RTW89_ACMA][0][79] = 127, + [1][1][RTW89_CHILE][1][79] = 127, + [1][1][RTW89_QATAR][1][79] = 127, + [1][1][RTW89_QATAR][0][79] = 127, + [1][1][RTW89_UK][1][79] = 127, + [1][1][RTW89_UK][0][79] = 127, + [1][1][RTW89_FCC][1][81] = -28, + [1][1][RTW89_FCC][2][81] = 44, + [1][1][RTW89_ETSI][1][81] = 127, + [1][1][RTW89_ETSI][0][81] = 127, + [1][1][RTW89_MKK][1][81] = 127, + [1][1][RTW89_MKK][0][81] = 127, + [1][1][RTW89_IC][1][81] = -28, + [1][1][RTW89_KCC][1][81] = -14, + [1][1][RTW89_KCC][0][81] = 127, + [1][1][RTW89_ACMA][1][81] = 127, + [1][1][RTW89_ACMA][0][81] = 127, + [1][1][RTW89_CHILE][1][81] = 127, + [1][1][RTW89_QATAR][1][81] = 127, + [1][1][RTW89_QATAR][0][81] = 127, + [1][1][RTW89_UK][1][81] = 127, + [1][1][RTW89_UK][0][81] = 127, + [1][1][RTW89_FCC][1][83] = -28, + [1][1][RTW89_FCC][2][83] = 44, + [1][1][RTW89_ETSI][1][83] = 127, + [1][1][RTW89_ETSI][0][83] = 127, + [1][1][RTW89_MKK][1][83] = 127, + [1][1][RTW89_MKK][0][83] = 127, + [1][1][RTW89_IC][1][83] = -28, + [1][1][RTW89_KCC][1][83] = -14, + [1][1][RTW89_KCC][0][83] = 127, + [1][1][RTW89_ACMA][1][83] = 127, + [1][1][RTW89_ACMA][0][83] = 127, + [1][1][RTW89_CHILE][1][83] = 127, + [1][1][RTW89_QATAR][1][83] = 127, + [1][1][RTW89_QATAR][0][83] = 127, + [1][1][RTW89_UK][1][83] = 127, + [1][1][RTW89_UK][0][83] = 127, + [1][1][RTW89_FCC][1][85] = -28, + [1][1][RTW89_FCC][2][85] = 44, + [1][1][RTW89_ETSI][1][85] = 127, + [1][1][RTW89_ETSI][0][85] = 127, + [1][1][RTW89_MKK][1][85] = 127, + [1][1][RTW89_MKK][0][85] = 127, + [1][1][RTW89_IC][1][85] = -28, + [1][1][RTW89_KCC][1][85] = -14, + [1][1][RTW89_KCC][0][85] = 127, + [1][1][RTW89_ACMA][1][85] = 127, + [1][1][RTW89_ACMA][0][85] = 127, + [1][1][RTW89_CHILE][1][85] = 127, + [1][1][RTW89_QATAR][1][85] = 127, + [1][1][RTW89_QATAR][0][85] = 127, + [1][1][RTW89_UK][1][85] = 127, + [1][1][RTW89_UK][0][85] = 127, + [1][1][RTW89_FCC][1][87] = -28, + [1][1][RTW89_FCC][2][87] = 127, + [1][1][RTW89_ETSI][1][87] = 127, + [1][1][RTW89_ETSI][0][87] = 127, + [1][1][RTW89_MKK][1][87] = 127, + [1][1][RTW89_MKK][0][87] = 127, + [1][1][RTW89_IC][1][87] = -28, + [1][1][RTW89_KCC][1][87] = -14, + [1][1][RTW89_KCC][0][87] = 127, + [1][1][RTW89_ACMA][1][87] = 127, + [1][1][RTW89_ACMA][0][87] = 127, + [1][1][RTW89_CHILE][1][87] = 127, + [1][1][RTW89_QATAR][1][87] = 127, + [1][1][RTW89_QATAR][0][87] = 127, + [1][1][RTW89_UK][1][87] = 127, + [1][1][RTW89_UK][0][87] = 127, + [1][1][RTW89_FCC][1][89] = -26, + [1][1][RTW89_FCC][2][89] = 127, + [1][1][RTW89_ETSI][1][89] = 127, + [1][1][RTW89_ETSI][0][89] = 127, + [1][1][RTW89_MKK][1][89] = 127, + [1][1][RTW89_MKK][0][89] = 127, + [1][1][RTW89_IC][1][89] = -26, + [1][1][RTW89_KCC][1][89] = -14, + [1][1][RTW89_KCC][0][89] = 127, + [1][1][RTW89_ACMA][1][89] = 127, + [1][1][RTW89_ACMA][0][89] = 127, + [1][1][RTW89_CHILE][1][89] = 127, + [1][1][RTW89_QATAR][1][89] = 127, + [1][1][RTW89_QATAR][0][89] = 127, + [1][1][RTW89_UK][1][89] = 127, + [1][1][RTW89_UK][0][89] = 127, + [1][1][RTW89_FCC][1][90] = -26, + [1][1][RTW89_FCC][2][90] = 127, + [1][1][RTW89_ETSI][1][90] = 127, + [1][1][RTW89_ETSI][0][90] = 127, + [1][1][RTW89_MKK][1][90] = 127, + [1][1][RTW89_MKK][0][90] = 127, + [1][1][RTW89_IC][1][90] = -26, + [1][1][RTW89_KCC][1][90] = -14, + [1][1][RTW89_KCC][0][90] = 127, + [1][1][RTW89_ACMA][1][90] = 127, + [1][1][RTW89_ACMA][0][90] = 127, + [1][1][RTW89_CHILE][1][90] = 127, + [1][1][RTW89_QATAR][1][90] = 127, + [1][1][RTW89_QATAR][0][90] = 127, + [1][1][RTW89_UK][1][90] = 127, + [1][1][RTW89_UK][0][90] = 127, + [1][1][RTW89_FCC][1][92] = -26, + [1][1][RTW89_FCC][2][92] = 127, + [1][1][RTW89_ETSI][1][92] = 127, + [1][1][RTW89_ETSI][0][92] = 127, + [1][1][RTW89_MKK][1][92] = 127, + [1][1][RTW89_MKK][0][92] = 127, + [1][1][RTW89_IC][1][92] = -26, + [1][1][RTW89_KCC][1][92] = -14, + [1][1][RTW89_KCC][0][92] = 127, + [1][1][RTW89_ACMA][1][92] = 127, + [1][1][RTW89_ACMA][0][92] = 127, + [1][1][RTW89_CHILE][1][92] = 127, + [1][1][RTW89_QATAR][1][92] = 127, + [1][1][RTW89_QATAR][0][92] = 127, + [1][1][RTW89_UK][1][92] = 127, + [1][1][RTW89_UK][0][92] = 127, + [1][1][RTW89_FCC][1][94] = -26, + [1][1][RTW89_FCC][2][94] = 127, + [1][1][RTW89_ETSI][1][94] = 127, + [1][1][RTW89_ETSI][0][94] = 127, + [1][1][RTW89_MKK][1][94] = 127, + [1][1][RTW89_MKK][0][94] = 127, + [1][1][RTW89_IC][1][94] = -26, + [1][1][RTW89_KCC][1][94] = -14, + [1][1][RTW89_KCC][0][94] = 127, + [1][1][RTW89_ACMA][1][94] = 127, + [1][1][RTW89_ACMA][0][94] = 127, + [1][1][RTW89_CHILE][1][94] = 127, + [1][1][RTW89_QATAR][1][94] = 127, + [1][1][RTW89_QATAR][0][94] = 127, + [1][1][RTW89_UK][1][94] = 127, + [1][1][RTW89_UK][0][94] = 127, + [1][1][RTW89_FCC][1][96] = -26, + [1][1][RTW89_FCC][2][96] = 127, + [1][1][RTW89_ETSI][1][96] = 127, + [1][1][RTW89_ETSI][0][96] = 127, + [1][1][RTW89_MKK][1][96] = 127, + [1][1][RTW89_MKK][0][96] = 127, + [1][1][RTW89_IC][1][96] = -26, + [1][1][RTW89_KCC][1][96] = -14, + [1][1][RTW89_KCC][0][96] = 127, + [1][1][RTW89_ACMA][1][96] = 127, + [1][1][RTW89_ACMA][0][96] = 127, + [1][1][RTW89_CHILE][1][96] = 127, + [1][1][RTW89_QATAR][1][96] = 127, + [1][1][RTW89_QATAR][0][96] = 127, + [1][1][RTW89_UK][1][96] = 127, + [1][1][RTW89_UK][0][96] = 127, + [1][1][RTW89_FCC][1][98] = -26, + [1][1][RTW89_FCC][2][98] = 127, + [1][1][RTW89_ETSI][1][98] = 127, + [1][1][RTW89_ETSI][0][98] = 127, + [1][1][RTW89_MKK][1][98] = 127, + [1][1][RTW89_MKK][0][98] = 127, + [1][1][RTW89_IC][1][98] = -26, + [1][1][RTW89_KCC][1][98] = -14, + [1][1][RTW89_KCC][0][98] = 127, + [1][1][RTW89_ACMA][1][98] = 127, + [1][1][RTW89_ACMA][0][98] = 127, + [1][1][RTW89_CHILE][1][98] = 127, + [1][1][RTW89_QATAR][1][98] = 127, + [1][1][RTW89_QATAR][0][98] = 127, + [1][1][RTW89_UK][1][98] = 127, + [1][1][RTW89_UK][0][98] = 127, + [1][1][RTW89_FCC][1][100] = -26, + [1][1][RTW89_FCC][2][100] = 127, + [1][1][RTW89_ETSI][1][100] = 127, + [1][1][RTW89_ETSI][0][100] = 127, + [1][1][RTW89_MKK][1][100] = 127, + [1][1][RTW89_MKK][0][100] = 127, + [1][1][RTW89_IC][1][100] = -26, + [1][1][RTW89_KCC][1][100] = -14, + [1][1][RTW89_KCC][0][100] = 127, + [1][1][RTW89_ACMA][1][100] = 127, + [1][1][RTW89_ACMA][0][100] = 127, + [1][1][RTW89_CHILE][1][100] = 127, + [1][1][RTW89_QATAR][1][100] = 127, + [1][1][RTW89_QATAR][0][100] = 127, + [1][1][RTW89_UK][1][100] = 127, + [1][1][RTW89_UK][0][100] = 127, + [1][1][RTW89_FCC][1][102] = -26, + [1][1][RTW89_FCC][2][102] = 127, + [1][1][RTW89_ETSI][1][102] = 127, + [1][1][RTW89_ETSI][0][102] = 127, + [1][1][RTW89_MKK][1][102] = 127, + [1][1][RTW89_MKK][0][102] = 127, + [1][1][RTW89_IC][1][102] = -26, + [1][1][RTW89_KCC][1][102] = -14, + [1][1][RTW89_KCC][0][102] = 127, + [1][1][RTW89_ACMA][1][102] = 127, + [1][1][RTW89_ACMA][0][102] = 127, + [1][1][RTW89_CHILE][1][102] = 127, + [1][1][RTW89_QATAR][1][102] = 127, + [1][1][RTW89_QATAR][0][102] = 127, + [1][1][RTW89_UK][1][102] = 127, + [1][1][RTW89_UK][0][102] = 127, + [1][1][RTW89_FCC][1][104] = -26, + [1][1][RTW89_FCC][2][104] = 127, + [1][1][RTW89_ETSI][1][104] = 127, + [1][1][RTW89_ETSI][0][104] = 127, + [1][1][RTW89_MKK][1][104] = 127, + [1][1][RTW89_MKK][0][104] = 127, + [1][1][RTW89_IC][1][104] = -26, + [1][1][RTW89_KCC][1][104] = -14, + [1][1][RTW89_KCC][0][104] = 127, + [1][1][RTW89_ACMA][1][104] = 127, + [1][1][RTW89_ACMA][0][104] = 127, + [1][1][RTW89_CHILE][1][104] = 127, + [1][1][RTW89_QATAR][1][104] = 127, + [1][1][RTW89_QATAR][0][104] = 127, + [1][1][RTW89_UK][1][104] = 127, + [1][1][RTW89_UK][0][104] = 127, + [1][1][RTW89_FCC][1][105] = -26, + [1][1][RTW89_FCC][2][105] = 127, + [1][1][RTW89_ETSI][1][105] = 127, + [1][1][RTW89_ETSI][0][105] = 127, + [1][1][RTW89_MKK][1][105] = 127, + [1][1][RTW89_MKK][0][105] = 127, + [1][1][RTW89_IC][1][105] = -26, + [1][1][RTW89_KCC][1][105] = -14, + [1][1][RTW89_KCC][0][105] = 127, + [1][1][RTW89_ACMA][1][105] = 127, + [1][1][RTW89_ACMA][0][105] = 127, + [1][1][RTW89_CHILE][1][105] = 127, + [1][1][RTW89_QATAR][1][105] = 127, + [1][1][RTW89_QATAR][0][105] = 127, + [1][1][RTW89_UK][1][105] = 127, + [1][1][RTW89_UK][0][105] = 127, + [1][1][RTW89_FCC][1][107] = -22, + [1][1][RTW89_FCC][2][107] = 127, + [1][1][RTW89_ETSI][1][107] = 127, + [1][1][RTW89_ETSI][0][107] = 127, + [1][1][RTW89_MKK][1][107] = 127, + [1][1][RTW89_MKK][0][107] = 127, + [1][1][RTW89_IC][1][107] = -22, + [1][1][RTW89_KCC][1][107] = -14, + [1][1][RTW89_KCC][0][107] = 127, + [1][1][RTW89_ACMA][1][107] = 127, + [1][1][RTW89_ACMA][0][107] = 127, + [1][1][RTW89_CHILE][1][107] = 127, + [1][1][RTW89_QATAR][1][107] = 127, + [1][1][RTW89_QATAR][0][107] = 127, + [1][1][RTW89_UK][1][107] = 127, + [1][1][RTW89_UK][0][107] = 127, + [1][1][RTW89_FCC][1][109] = -22, + [1][1][RTW89_FCC][2][109] = 127, + [1][1][RTW89_ETSI][1][109] = 127, + [1][1][RTW89_ETSI][0][109] = 127, + [1][1][RTW89_MKK][1][109] = 127, + [1][1][RTW89_MKK][0][109] = 127, + [1][1][RTW89_IC][1][109] = -22, + [1][1][RTW89_KCC][1][109] = 127, + [1][1][RTW89_KCC][0][109] = 127, + [1][1][RTW89_ACMA][1][109] = 127, + [1][1][RTW89_ACMA][0][109] = 127, + [1][1][RTW89_CHILE][1][109] = 127, + [1][1][RTW89_QATAR][1][109] = 127, + [1][1][RTW89_QATAR][0][109] = 127, + [1][1][RTW89_UK][1][109] = 127, + [1][1][RTW89_UK][0][109] = 127, + [1][1][RTW89_FCC][1][111] = 127, + [1][1][RTW89_FCC][2][111] = 127, + [1][1][RTW89_ETSI][1][111] = 127, + [1][1][RTW89_ETSI][0][111] = 127, + [1][1][RTW89_MKK][1][111] = 127, + [1][1][RTW89_MKK][0][111] = 127, + [1][1][RTW89_IC][1][111] = 127, + [1][1][RTW89_KCC][1][111] = 127, + [1][1][RTW89_KCC][0][111] = 127, + [1][1][RTW89_ACMA][1][111] = 127, + [1][1][RTW89_ACMA][0][111] = 127, + [1][1][RTW89_CHILE][1][111] = 127, + [1][1][RTW89_QATAR][1][111] = 127, + [1][1][RTW89_QATAR][0][111] = 127, + [1][1][RTW89_UK][1][111] = 127, + [1][1][RTW89_UK][0][111] = 127, + [1][1][RTW89_FCC][1][113] = 127, + [1][1][RTW89_FCC][2][113] = 127, + [1][1][RTW89_ETSI][1][113] = 127, + [1][1][RTW89_ETSI][0][113] = 127, + [1][1][RTW89_MKK][1][113] = 127, + [1][1][RTW89_MKK][0][113] = 127, + [1][1][RTW89_IC][1][113] = 127, + [1][1][RTW89_KCC][1][113] = 127, + [1][1][RTW89_KCC][0][113] = 127, + [1][1][RTW89_ACMA][1][113] = 127, + [1][1][RTW89_ACMA][0][113] = 127, + [1][1][RTW89_CHILE][1][113] = 127, + [1][1][RTW89_QATAR][1][113] = 127, + [1][1][RTW89_QATAR][0][113] = 127, + [1][1][RTW89_UK][1][113] = 127, + [1][1][RTW89_UK][0][113] = 127, + [1][1][RTW89_FCC][1][115] = 127, + [1][1][RTW89_FCC][2][115] = 127, + [1][1][RTW89_ETSI][1][115] = 127, + [1][1][RTW89_ETSI][0][115] = 127, + [1][1][RTW89_MKK][1][115] = 127, + [1][1][RTW89_MKK][0][115] = 127, + [1][1][RTW89_IC][1][115] = 127, + [1][1][RTW89_KCC][1][115] = 127, + [1][1][RTW89_KCC][0][115] = 127, + [1][1][RTW89_ACMA][1][115] = 127, + [1][1][RTW89_ACMA][0][115] = 127, + [1][1][RTW89_CHILE][1][115] = 127, + [1][1][RTW89_QATAR][1][115] = 127, + [1][1][RTW89_QATAR][0][115] = 127, + [1][1][RTW89_UK][1][115] = 127, + [1][1][RTW89_UK][0][115] = 127, + [1][1][RTW89_FCC][1][117] = 127, + [1][1][RTW89_FCC][2][117] = 127, + [1][1][RTW89_ETSI][1][117] = 127, + [1][1][RTW89_ETSI][0][117] = 127, + [1][1][RTW89_MKK][1][117] = 127, + [1][1][RTW89_MKK][0][117] = 127, + [1][1][RTW89_IC][1][117] = 127, + [1][1][RTW89_KCC][1][117] = 127, + [1][1][RTW89_KCC][0][117] = 127, + [1][1][RTW89_ACMA][1][117] = 127, + [1][1][RTW89_ACMA][0][117] = 127, + [1][1][RTW89_CHILE][1][117] = 127, + [1][1][RTW89_QATAR][1][117] = 127, + [1][1][RTW89_QATAR][0][117] = 127, + [1][1][RTW89_UK][1][117] = 127, + [1][1][RTW89_UK][0][117] = 127, + [1][1][RTW89_FCC][1][119] = 127, + [1][1][RTW89_FCC][2][119] = 127, + [1][1][RTW89_ETSI][1][119] = 127, + [1][1][RTW89_ETSI][0][119] = 127, + [1][1][RTW89_MKK][1][119] = 127, + [1][1][RTW89_MKK][0][119] = 127, + [1][1][RTW89_IC][1][119] = 127, + [1][1][RTW89_KCC][1][119] = 127, + [1][1][RTW89_KCC][0][119] = 127, + [1][1][RTW89_ACMA][1][119] = 127, + [1][1][RTW89_ACMA][0][119] = 127, + [1][1][RTW89_CHILE][1][119] = 127, + [1][1][RTW89_QATAR][1][119] = 127, + [1][1][RTW89_QATAR][0][119] = 127, + [1][1][RTW89_UK][1][119] = 127, + [1][1][RTW89_UK][0][119] = 127, + [2][0][RTW89_FCC][1][0] = 8, + [2][0][RTW89_FCC][2][0] = 60, + [2][0][RTW89_ETSI][1][0] = 56, + [2][0][RTW89_ETSI][0][0] = 18, + [2][0][RTW89_MKK][1][0] = 54, + [2][0][RTW89_MKK][0][0] = 14, + [2][0][RTW89_IC][1][0] = 8, + [2][0][RTW89_KCC][1][0] = -2, + [2][0][RTW89_KCC][0][0] = -2, + [2][0][RTW89_ACMA][1][0] = 56, + [2][0][RTW89_ACMA][0][0] = 18, + [2][0][RTW89_CHILE][1][0] = 8, + [2][0][RTW89_QATAR][1][0] = 56, + [2][0][RTW89_QATAR][0][0] = 18, + [2][0][RTW89_UK][1][0] = 56, + [2][0][RTW89_UK][0][0] = 18, + [2][0][RTW89_FCC][1][2] = 8, + [2][0][RTW89_FCC][2][2] = 60, + [2][0][RTW89_ETSI][1][2] = 56, + [2][0][RTW89_ETSI][0][2] = 18, + [2][0][RTW89_MKK][1][2] = 54, + [2][0][RTW89_MKK][0][2] = 14, + [2][0][RTW89_IC][1][2] = 8, + [2][0][RTW89_KCC][1][2] = -2, + [2][0][RTW89_KCC][0][2] = -2, + [2][0][RTW89_ACMA][1][2] = 56, + [2][0][RTW89_ACMA][0][2] = 18, + [2][0][RTW89_CHILE][1][2] = 8, + [2][0][RTW89_QATAR][1][2] = 56, + [2][0][RTW89_QATAR][0][2] = 18, + [2][0][RTW89_UK][1][2] = 56, + [2][0][RTW89_UK][0][2] = 18, + [2][0][RTW89_FCC][1][4] = 8, + [2][0][RTW89_FCC][2][4] = 60, + [2][0][RTW89_ETSI][1][4] = 56, + [2][0][RTW89_ETSI][0][4] = 18, + [2][0][RTW89_MKK][1][4] = 54, + [2][0][RTW89_MKK][0][4] = 14, + [2][0][RTW89_IC][1][4] = 8, + [2][0][RTW89_KCC][1][4] = -2, + [2][0][RTW89_KCC][0][4] = -2, + [2][0][RTW89_ACMA][1][4] = 56, + [2][0][RTW89_ACMA][0][4] = 18, + [2][0][RTW89_CHILE][1][4] = 8, + [2][0][RTW89_QATAR][1][4] = 56, + [2][0][RTW89_QATAR][0][4] = 18, + [2][0][RTW89_UK][1][4] = 56, + [2][0][RTW89_UK][0][4] = 18, + [2][0][RTW89_FCC][1][6] = 8, + [2][0][RTW89_FCC][2][6] = 60, + [2][0][RTW89_ETSI][1][6] = 56, + [2][0][RTW89_ETSI][0][6] = 18, + [2][0][RTW89_MKK][1][6] = 54, + [2][0][RTW89_MKK][0][6] = 14, + [2][0][RTW89_IC][1][6] = 8, + [2][0][RTW89_KCC][1][6] = -2, + [2][0][RTW89_KCC][0][6] = -2, + [2][0][RTW89_ACMA][1][6] = 56, + [2][0][RTW89_ACMA][0][6] = 18, + [2][0][RTW89_CHILE][1][6] = 8, + [2][0][RTW89_QATAR][1][6] = 56, + [2][0][RTW89_QATAR][0][6] = 18, + [2][0][RTW89_UK][1][6] = 56, + [2][0][RTW89_UK][0][6] = 18, + [2][0][RTW89_FCC][1][8] = 8, + [2][0][RTW89_FCC][2][8] = 60, + [2][0][RTW89_ETSI][1][8] = 56, + [2][0][RTW89_ETSI][0][8] = 18, + [2][0][RTW89_MKK][1][8] = 54, + [2][0][RTW89_MKK][0][8] = 14, + [2][0][RTW89_IC][1][8] = 8, + [2][0][RTW89_KCC][1][8] = -2, + [2][0][RTW89_KCC][0][8] = -2, + [2][0][RTW89_ACMA][1][8] = 56, + [2][0][RTW89_ACMA][0][8] = 18, + [2][0][RTW89_CHILE][1][8] = 8, + [2][0][RTW89_QATAR][1][8] = 56, + [2][0][RTW89_QATAR][0][8] = 18, + [2][0][RTW89_UK][1][8] = 56, + [2][0][RTW89_UK][0][8] = 18, + [2][0][RTW89_FCC][1][10] = 8, + [2][0][RTW89_FCC][2][10] = 60, + [2][0][RTW89_ETSI][1][10] = 56, + [2][0][RTW89_ETSI][0][10] = 18, + [2][0][RTW89_MKK][1][10] = 54, + [2][0][RTW89_MKK][0][10] = 14, + [2][0][RTW89_IC][1][10] = 8, + [2][0][RTW89_KCC][1][10] = -2, + [2][0][RTW89_KCC][0][10] = -2, + [2][0][RTW89_ACMA][1][10] = 56, + [2][0][RTW89_ACMA][0][10] = 18, + [2][0][RTW89_CHILE][1][10] = 8, + [2][0][RTW89_QATAR][1][10] = 56, + [2][0][RTW89_QATAR][0][10] = 18, + [2][0][RTW89_UK][1][10] = 56, + [2][0][RTW89_UK][0][10] = 18, + [2][0][RTW89_FCC][1][12] = 8, + [2][0][RTW89_FCC][2][12] = 60, + [2][0][RTW89_ETSI][1][12] = 56, + [2][0][RTW89_ETSI][0][12] = 18, + [2][0][RTW89_MKK][1][12] = 54, + [2][0][RTW89_MKK][0][12] = 14, + [2][0][RTW89_IC][1][12] = 8, + [2][0][RTW89_KCC][1][12] = -2, + [2][0][RTW89_KCC][0][12] = -2, + [2][0][RTW89_ACMA][1][12] = 56, + [2][0][RTW89_ACMA][0][12] = 18, + [2][0][RTW89_CHILE][1][12] = 8, + [2][0][RTW89_QATAR][1][12] = 56, + [2][0][RTW89_QATAR][0][12] = 18, + [2][0][RTW89_UK][1][12] = 56, + [2][0][RTW89_UK][0][12] = 18, + [2][0][RTW89_FCC][1][14] = 8, + [2][0][RTW89_FCC][2][14] = 60, + [2][0][RTW89_ETSI][1][14] = 56, + [2][0][RTW89_ETSI][0][14] = 18, + [2][0][RTW89_MKK][1][14] = 54, + [2][0][RTW89_MKK][0][14] = 14, + [2][0][RTW89_IC][1][14] = 8, + [2][0][RTW89_KCC][1][14] = -2, + [2][0][RTW89_KCC][0][14] = -2, + [2][0][RTW89_ACMA][1][14] = 56, + [2][0][RTW89_ACMA][0][14] = 18, + [2][0][RTW89_CHILE][1][14] = 8, + [2][0][RTW89_QATAR][1][14] = 56, + [2][0][RTW89_QATAR][0][14] = 18, + [2][0][RTW89_UK][1][14] = 56, + [2][0][RTW89_UK][0][14] = 18, + [2][0][RTW89_FCC][1][15] = 8, + [2][0][RTW89_FCC][2][15] = 60, + [2][0][RTW89_ETSI][1][15] = 56, + [2][0][RTW89_ETSI][0][15] = 18, + [2][0][RTW89_MKK][1][15] = 54, + [2][0][RTW89_MKK][0][15] = 14, + [2][0][RTW89_IC][1][15] = 8, + [2][0][RTW89_KCC][1][15] = -2, + [2][0][RTW89_KCC][0][15] = -2, + [2][0][RTW89_ACMA][1][15] = 56, + [2][0][RTW89_ACMA][0][15] = 18, + [2][0][RTW89_CHILE][1][15] = 8, + [2][0][RTW89_QATAR][1][15] = 56, + [2][0][RTW89_QATAR][0][15] = 18, + [2][0][RTW89_UK][1][15] = 56, + [2][0][RTW89_UK][0][15] = 18, + [2][0][RTW89_FCC][1][17] = 8, + [2][0][RTW89_FCC][2][17] = 60, + [2][0][RTW89_ETSI][1][17] = 56, + [2][0][RTW89_ETSI][0][17] = 18, + [2][0][RTW89_MKK][1][17] = 54, + [2][0][RTW89_MKK][0][17] = 14, + [2][0][RTW89_IC][1][17] = 8, + [2][0][RTW89_KCC][1][17] = -2, + [2][0][RTW89_KCC][0][17] = -2, + [2][0][RTW89_ACMA][1][17] = 56, + [2][0][RTW89_ACMA][0][17] = 18, + [2][0][RTW89_CHILE][1][17] = 8, + [2][0][RTW89_QATAR][1][17] = 56, + [2][0][RTW89_QATAR][0][17] = 18, + [2][0][RTW89_UK][1][17] = 56, + [2][0][RTW89_UK][0][17] = 18, + [2][0][RTW89_FCC][1][19] = 8, + [2][0][RTW89_FCC][2][19] = 60, + [2][0][RTW89_ETSI][1][19] = 56, + [2][0][RTW89_ETSI][0][19] = 18, + [2][0][RTW89_MKK][1][19] = 54, + [2][0][RTW89_MKK][0][19] = 14, + [2][0][RTW89_IC][1][19] = 8, + [2][0][RTW89_KCC][1][19] = -2, + [2][0][RTW89_KCC][0][19] = -2, + [2][0][RTW89_ACMA][1][19] = 56, + [2][0][RTW89_ACMA][0][19] = 18, + [2][0][RTW89_CHILE][1][19] = 8, + [2][0][RTW89_QATAR][1][19] = 56, + [2][0][RTW89_QATAR][0][19] = 18, + [2][0][RTW89_UK][1][19] = 56, + [2][0][RTW89_UK][0][19] = 18, + [2][0][RTW89_FCC][1][21] = 8, + [2][0][RTW89_FCC][2][21] = 60, + [2][0][RTW89_ETSI][1][21] = 56, + [2][0][RTW89_ETSI][0][21] = 18, + [2][0][RTW89_MKK][1][21] = 54, + [2][0][RTW89_MKK][0][21] = 14, + [2][0][RTW89_IC][1][21] = 8, + [2][0][RTW89_KCC][1][21] = -2, + [2][0][RTW89_KCC][0][21] = -2, + [2][0][RTW89_ACMA][1][21] = 56, + [2][0][RTW89_ACMA][0][21] = 18, + [2][0][RTW89_CHILE][1][21] = 8, + [2][0][RTW89_QATAR][1][21] = 56, + [2][0][RTW89_QATAR][0][21] = 18, + [2][0][RTW89_UK][1][21] = 56, + [2][0][RTW89_UK][0][21] = 18, + [2][0][RTW89_FCC][1][23] = 8, + [2][0][RTW89_FCC][2][23] = 78, + [2][0][RTW89_ETSI][1][23] = 56, + [2][0][RTW89_ETSI][0][23] = 18, + [2][0][RTW89_MKK][1][23] = 56, + [2][0][RTW89_MKK][0][23] = 14, + [2][0][RTW89_IC][1][23] = 8, + [2][0][RTW89_KCC][1][23] = -2, + [2][0][RTW89_KCC][0][23] = -2, + [2][0][RTW89_ACMA][1][23] = 56, + [2][0][RTW89_ACMA][0][23] = 18, + [2][0][RTW89_CHILE][1][23] = 8, + [2][0][RTW89_QATAR][1][23] = 56, + [2][0][RTW89_QATAR][0][23] = 18, + [2][0][RTW89_UK][1][23] = 56, + [2][0][RTW89_UK][0][23] = 18, + [2][0][RTW89_FCC][1][25] = 8, + [2][0][RTW89_FCC][2][25] = 78, + [2][0][RTW89_ETSI][1][25] = 56, + [2][0][RTW89_ETSI][0][25] = 18, + [2][0][RTW89_MKK][1][25] = 56, + [2][0][RTW89_MKK][0][25] = 14, + [2][0][RTW89_IC][1][25] = 8, + [2][0][RTW89_KCC][1][25] = -2, + [2][0][RTW89_KCC][0][25] = -2, + [2][0][RTW89_ACMA][1][25] = 56, + [2][0][RTW89_ACMA][0][25] = 18, + [2][0][RTW89_CHILE][1][25] = 8, + [2][0][RTW89_QATAR][1][25] = 56, + [2][0][RTW89_QATAR][0][25] = 18, + [2][0][RTW89_UK][1][25] = 56, + [2][0][RTW89_UK][0][25] = 18, + [2][0][RTW89_FCC][1][27] = 8, + [2][0][RTW89_FCC][2][27] = 78, + [2][0][RTW89_ETSI][1][27] = 56, + [2][0][RTW89_ETSI][0][27] = 18, + [2][0][RTW89_MKK][1][27] = 56, + [2][0][RTW89_MKK][0][27] = 14, + [2][0][RTW89_IC][1][27] = 8, + [2][0][RTW89_KCC][1][27] = -2, + [2][0][RTW89_KCC][0][27] = -2, + [2][0][RTW89_ACMA][1][27] = 56, + [2][0][RTW89_ACMA][0][27] = 18, + [2][0][RTW89_CHILE][1][27] = 8, + [2][0][RTW89_QATAR][1][27] = 56, + [2][0][RTW89_QATAR][0][27] = 18, + [2][0][RTW89_UK][1][27] = 56, + [2][0][RTW89_UK][0][27] = 18, + [2][0][RTW89_FCC][1][29] = 8, + [2][0][RTW89_FCC][2][29] = 78, + [2][0][RTW89_ETSI][1][29] = 56, + [2][0][RTW89_ETSI][0][29] = 18, + [2][0][RTW89_MKK][1][29] = 56, + [2][0][RTW89_MKK][0][29] = 14, + [2][0][RTW89_IC][1][29] = 8, + [2][0][RTW89_KCC][1][29] = -2, + [2][0][RTW89_KCC][0][29] = -2, + [2][0][RTW89_ACMA][1][29] = 56, + [2][0][RTW89_ACMA][0][29] = 18, + [2][0][RTW89_CHILE][1][29] = 8, + [2][0][RTW89_QATAR][1][29] = 56, + [2][0][RTW89_QATAR][0][29] = 18, + [2][0][RTW89_UK][1][29] = 56, + [2][0][RTW89_UK][0][29] = 18, + [2][0][RTW89_FCC][1][30] = 8, + [2][0][RTW89_FCC][2][30] = 78, + [2][0][RTW89_ETSI][1][30] = 56, + [2][0][RTW89_ETSI][0][30] = 18, + [2][0][RTW89_MKK][1][30] = 56, + [2][0][RTW89_MKK][0][30] = 14, + [2][0][RTW89_IC][1][30] = 8, + [2][0][RTW89_KCC][1][30] = -2, + [2][0][RTW89_KCC][0][30] = -2, + [2][0][RTW89_ACMA][1][30] = 56, + [2][0][RTW89_ACMA][0][30] = 18, + [2][0][RTW89_CHILE][1][30] = 8, + [2][0][RTW89_QATAR][1][30] = 56, + [2][0][RTW89_QATAR][0][30] = 18, + [2][0][RTW89_UK][1][30] = 56, + [2][0][RTW89_UK][0][30] = 18, + [2][0][RTW89_FCC][1][32] = 8, + [2][0][RTW89_FCC][2][32] = 78, + [2][0][RTW89_ETSI][1][32] = 56, + [2][0][RTW89_ETSI][0][32] = 18, + [2][0][RTW89_MKK][1][32] = 56, + [2][0][RTW89_MKK][0][32] = 14, + [2][0][RTW89_IC][1][32] = 8, + [2][0][RTW89_KCC][1][32] = -2, + [2][0][RTW89_KCC][0][32] = -2, + [2][0][RTW89_ACMA][1][32] = 56, + [2][0][RTW89_ACMA][0][32] = 18, + [2][0][RTW89_CHILE][1][32] = 8, + [2][0][RTW89_QATAR][1][32] = 56, + [2][0][RTW89_QATAR][0][32] = 18, + [2][0][RTW89_UK][1][32] = 56, + [2][0][RTW89_UK][0][32] = 18, + [2][0][RTW89_FCC][1][34] = 8, + [2][0][RTW89_FCC][2][34] = 78, + [2][0][RTW89_ETSI][1][34] = 56, + [2][0][RTW89_ETSI][0][34] = 18, + [2][0][RTW89_MKK][1][34] = 56, + [2][0][RTW89_MKK][0][34] = 14, + [2][0][RTW89_IC][1][34] = 8, + [2][0][RTW89_KCC][1][34] = -2, + [2][0][RTW89_KCC][0][34] = -2, + [2][0][RTW89_ACMA][1][34] = 56, + [2][0][RTW89_ACMA][0][34] = 18, + [2][0][RTW89_CHILE][1][34] = 8, + [2][0][RTW89_QATAR][1][34] = 56, + [2][0][RTW89_QATAR][0][34] = 18, + [2][0][RTW89_UK][1][34] = 56, + [2][0][RTW89_UK][0][34] = 18, + [2][0][RTW89_FCC][1][36] = 8, + [2][0][RTW89_FCC][2][36] = 78, + [2][0][RTW89_ETSI][1][36] = 56, + [2][0][RTW89_ETSI][0][36] = 18, + [2][0][RTW89_MKK][1][36] = 56, + [2][0][RTW89_MKK][0][36] = 14, + [2][0][RTW89_IC][1][36] = 8, + [2][0][RTW89_KCC][1][36] = -2, + [2][0][RTW89_KCC][0][36] = -2, + [2][0][RTW89_ACMA][1][36] = 56, + [2][0][RTW89_ACMA][0][36] = 18, + [2][0][RTW89_CHILE][1][36] = 8, + [2][0][RTW89_QATAR][1][36] = 56, + [2][0][RTW89_QATAR][0][36] = 18, + [2][0][RTW89_UK][1][36] = 56, + [2][0][RTW89_UK][0][36] = 18, + [2][0][RTW89_FCC][1][38] = 8, + [2][0][RTW89_FCC][2][38] = 78, + [2][0][RTW89_ETSI][1][38] = 56, + [2][0][RTW89_ETSI][0][38] = 18, + [2][0][RTW89_MKK][1][38] = 56, + [2][0][RTW89_MKK][0][38] = 14, + [2][0][RTW89_IC][1][38] = 8, + [2][0][RTW89_KCC][1][38] = -2, + [2][0][RTW89_KCC][0][38] = -2, + [2][0][RTW89_ACMA][1][38] = 56, + [2][0][RTW89_ACMA][0][38] = 18, + [2][0][RTW89_CHILE][1][38] = 8, + [2][0][RTW89_QATAR][1][38] = 56, + [2][0][RTW89_QATAR][0][38] = 18, + [2][0][RTW89_UK][1][38] = 56, + [2][0][RTW89_UK][0][38] = 18, + [2][0][RTW89_FCC][1][40] = 8, + [2][0][RTW89_FCC][2][40] = 78, + [2][0][RTW89_ETSI][1][40] = 56, + [2][0][RTW89_ETSI][0][40] = 18, + [2][0][RTW89_MKK][1][40] = 56, + [2][0][RTW89_MKK][0][40] = 14, + [2][0][RTW89_IC][1][40] = 8, + [2][0][RTW89_KCC][1][40] = -2, + [2][0][RTW89_KCC][0][40] = -2, + [2][0][RTW89_ACMA][1][40] = 56, + [2][0][RTW89_ACMA][0][40] = 18, + [2][0][RTW89_CHILE][1][40] = 8, + [2][0][RTW89_QATAR][1][40] = 56, + [2][0][RTW89_QATAR][0][40] = 18, + [2][0][RTW89_UK][1][40] = 56, + [2][0][RTW89_UK][0][40] = 18, + [2][0][RTW89_FCC][1][42] = 8, + [2][0][RTW89_FCC][2][42] = 78, + [2][0][RTW89_ETSI][1][42] = 56, + [2][0][RTW89_ETSI][0][42] = 18, + [2][0][RTW89_MKK][1][42] = 56, + [2][0][RTW89_MKK][0][42] = 14, + [2][0][RTW89_IC][1][42] = 8, + [2][0][RTW89_KCC][1][42] = -2, + [2][0][RTW89_KCC][0][42] = -2, + [2][0][RTW89_ACMA][1][42] = 56, + [2][0][RTW89_ACMA][0][42] = 18, + [2][0][RTW89_CHILE][1][42] = 8, + [2][0][RTW89_QATAR][1][42] = 56, + [2][0][RTW89_QATAR][0][42] = 18, + [2][0][RTW89_UK][1][42] = 56, + [2][0][RTW89_UK][0][42] = 18, + [2][0][RTW89_FCC][1][44] = 8, + [2][0][RTW89_FCC][2][44] = 78, + [2][0][RTW89_ETSI][1][44] = 56, + [2][0][RTW89_ETSI][0][44] = 18, + [2][0][RTW89_MKK][1][44] = 32, + [2][0][RTW89_MKK][0][44] = 14, + [2][0][RTW89_IC][1][44] = 8, + [2][0][RTW89_KCC][1][44] = -2, + [2][0][RTW89_KCC][0][44] = -2, + [2][0][RTW89_ACMA][1][44] = 56, + [2][0][RTW89_ACMA][0][44] = 18, + [2][0][RTW89_CHILE][1][44] = 8, + [2][0][RTW89_QATAR][1][44] = 56, + [2][0][RTW89_QATAR][0][44] = 18, + [2][0][RTW89_UK][1][44] = 56, + [2][0][RTW89_UK][0][44] = 18, + [2][0][RTW89_FCC][1][45] = 8, + [2][0][RTW89_FCC][2][45] = 127, + [2][0][RTW89_ETSI][1][45] = 127, + [2][0][RTW89_ETSI][0][45] = 127, + [2][0][RTW89_MKK][1][45] = 127, + [2][0][RTW89_MKK][0][45] = 127, + [2][0][RTW89_IC][1][45] = 8, + [2][0][RTW89_KCC][1][45] = -2, + [2][0][RTW89_KCC][0][45] = 127, + [2][0][RTW89_ACMA][1][45] = 127, + [2][0][RTW89_ACMA][0][45] = 127, + [2][0][RTW89_CHILE][1][45] = 127, + [2][0][RTW89_QATAR][1][45] = 127, + [2][0][RTW89_QATAR][0][45] = 127, + [2][0][RTW89_UK][1][45] = 127, + [2][0][RTW89_UK][0][45] = 127, + [2][0][RTW89_FCC][1][47] = 8, + [2][0][RTW89_FCC][2][47] = 127, + [2][0][RTW89_ETSI][1][47] = 127, + [2][0][RTW89_ETSI][0][47] = 127, + [2][0][RTW89_MKK][1][47] = 127, + [2][0][RTW89_MKK][0][47] = 127, + [2][0][RTW89_IC][1][47] = 8, + [2][0][RTW89_KCC][1][47] = -2, + [2][0][RTW89_KCC][0][47] = 127, + [2][0][RTW89_ACMA][1][47] = 127, + [2][0][RTW89_ACMA][0][47] = 127, + [2][0][RTW89_CHILE][1][47] = 127, + [2][0][RTW89_QATAR][1][47] = 127, + [2][0][RTW89_QATAR][0][47] = 127, + [2][0][RTW89_UK][1][47] = 127, + [2][0][RTW89_UK][0][47] = 127, + [2][0][RTW89_FCC][1][49] = 8, + [2][0][RTW89_FCC][2][49] = 127, + [2][0][RTW89_ETSI][1][49] = 127, + [2][0][RTW89_ETSI][0][49] = 127, + [2][0][RTW89_MKK][1][49] = 127, + [2][0][RTW89_MKK][0][49] = 127, + [2][0][RTW89_IC][1][49] = 8, + [2][0][RTW89_KCC][1][49] = -2, + [2][0][RTW89_KCC][0][49] = 127, + [2][0][RTW89_ACMA][1][49] = 127, + [2][0][RTW89_ACMA][0][49] = 127, + [2][0][RTW89_CHILE][1][49] = 127, + [2][0][RTW89_QATAR][1][49] = 127, + [2][0][RTW89_QATAR][0][49] = 127, + [2][0][RTW89_UK][1][49] = 127, + [2][0][RTW89_UK][0][49] = 127, + [2][0][RTW89_FCC][1][51] = 8, + [2][0][RTW89_FCC][2][51] = 127, + [2][0][RTW89_ETSI][1][51] = 127, + [2][0][RTW89_ETSI][0][51] = 127, + [2][0][RTW89_MKK][1][51] = 127, + [2][0][RTW89_MKK][0][51] = 127, + [2][0][RTW89_IC][1][51] = 8, + [2][0][RTW89_KCC][1][51] = -2, + [2][0][RTW89_KCC][0][51] = 127, + [2][0][RTW89_ACMA][1][51] = 127, + [2][0][RTW89_ACMA][0][51] = 127, + [2][0][RTW89_CHILE][1][51] = 127, + [2][0][RTW89_QATAR][1][51] = 127, + [2][0][RTW89_QATAR][0][51] = 127, + [2][0][RTW89_UK][1][51] = 127, + [2][0][RTW89_UK][0][51] = 127, + [2][0][RTW89_FCC][1][53] = 8, + [2][0][RTW89_FCC][2][53] = 127, + [2][0][RTW89_ETSI][1][53] = 127, + [2][0][RTW89_ETSI][0][53] = 127, + [2][0][RTW89_MKK][1][53] = 127, + [2][0][RTW89_MKK][0][53] = 127, + [2][0][RTW89_IC][1][53] = 8, + [2][0][RTW89_KCC][1][53] = -2, + [2][0][RTW89_KCC][0][53] = 127, + [2][0][RTW89_ACMA][1][53] = 127, + [2][0][RTW89_ACMA][0][53] = 127, + [2][0][RTW89_CHILE][1][53] = 127, + [2][0][RTW89_QATAR][1][53] = 127, + [2][0][RTW89_QATAR][0][53] = 127, + [2][0][RTW89_UK][1][53] = 127, + [2][0][RTW89_UK][0][53] = 127, + [2][0][RTW89_FCC][1][55] = 8, + [2][0][RTW89_FCC][2][55] = 78, + [2][0][RTW89_ETSI][1][55] = 127, + [2][0][RTW89_ETSI][0][55] = 127, + [2][0][RTW89_MKK][1][55] = 127, + [2][0][RTW89_MKK][0][55] = 127, + [2][0][RTW89_IC][1][55] = 8, + [2][0][RTW89_KCC][1][55] = -2, + [2][0][RTW89_KCC][0][55] = 127, + [2][0][RTW89_ACMA][1][55] = 127, + [2][0][RTW89_ACMA][0][55] = 127, + [2][0][RTW89_CHILE][1][55] = 127, + [2][0][RTW89_QATAR][1][55] = 127, + [2][0][RTW89_QATAR][0][55] = 127, + [2][0][RTW89_UK][1][55] = 127, + [2][0][RTW89_UK][0][55] = 127, + [2][0][RTW89_FCC][1][57] = 8, + [2][0][RTW89_FCC][2][57] = 78, + [2][0][RTW89_ETSI][1][57] = 127, + [2][0][RTW89_ETSI][0][57] = 127, + [2][0][RTW89_MKK][1][57] = 127, + [2][0][RTW89_MKK][0][57] = 127, + [2][0][RTW89_IC][1][57] = 8, + [2][0][RTW89_KCC][1][57] = -2, + [2][0][RTW89_KCC][0][57] = 127, + [2][0][RTW89_ACMA][1][57] = 127, + [2][0][RTW89_ACMA][0][57] = 127, + [2][0][RTW89_CHILE][1][57] = 127, + [2][0][RTW89_QATAR][1][57] = 127, + [2][0][RTW89_QATAR][0][57] = 127, + [2][0][RTW89_UK][1][57] = 127, + [2][0][RTW89_UK][0][57] = 127, + [2][0][RTW89_FCC][1][59] = 8, + [2][0][RTW89_FCC][2][59] = 78, + [2][0][RTW89_ETSI][1][59] = 127, + [2][0][RTW89_ETSI][0][59] = 127, + [2][0][RTW89_MKK][1][59] = 127, + [2][0][RTW89_MKK][0][59] = 127, + [2][0][RTW89_IC][1][59] = 8, + [2][0][RTW89_KCC][1][59] = -2, + [2][0][RTW89_KCC][0][59] = 127, + [2][0][RTW89_ACMA][1][59] = 127, + [2][0][RTW89_ACMA][0][59] = 127, + [2][0][RTW89_CHILE][1][59] = 127, + [2][0][RTW89_QATAR][1][59] = 127, + [2][0][RTW89_QATAR][0][59] = 127, + [2][0][RTW89_UK][1][59] = 127, + [2][0][RTW89_UK][0][59] = 127, + [2][0][RTW89_FCC][1][60] = 8, + [2][0][RTW89_FCC][2][60] = 78, + [2][0][RTW89_ETSI][1][60] = 127, + [2][0][RTW89_ETSI][0][60] = 127, + [2][0][RTW89_MKK][1][60] = 127, + [2][0][RTW89_MKK][0][60] = 127, + [2][0][RTW89_IC][1][60] = 8, + [2][0][RTW89_KCC][1][60] = -2, + [2][0][RTW89_KCC][0][60] = 127, + [2][0][RTW89_ACMA][1][60] = 127, + [2][0][RTW89_ACMA][0][60] = 127, + [2][0][RTW89_CHILE][1][60] = 127, + [2][0][RTW89_QATAR][1][60] = 127, + [2][0][RTW89_QATAR][0][60] = 127, + [2][0][RTW89_UK][1][60] = 127, + [2][0][RTW89_UK][0][60] = 127, + [2][0][RTW89_FCC][1][62] = 8, + [2][0][RTW89_FCC][2][62] = 78, + [2][0][RTW89_ETSI][1][62] = 127, + [2][0][RTW89_ETSI][0][62] = 127, + [2][0][RTW89_MKK][1][62] = 127, + [2][0][RTW89_MKK][0][62] = 127, + [2][0][RTW89_IC][1][62] = 8, + [2][0][RTW89_KCC][1][62] = -2, + [2][0][RTW89_KCC][0][62] = 127, + [2][0][RTW89_ACMA][1][62] = 127, + [2][0][RTW89_ACMA][0][62] = 127, + [2][0][RTW89_CHILE][1][62] = 127, + [2][0][RTW89_QATAR][1][62] = 127, + [2][0][RTW89_QATAR][0][62] = 127, + [2][0][RTW89_UK][1][62] = 127, + [2][0][RTW89_UK][0][62] = 127, + [2][0][RTW89_FCC][1][64] = 8, + [2][0][RTW89_FCC][2][64] = 78, + [2][0][RTW89_ETSI][1][64] = 127, + [2][0][RTW89_ETSI][0][64] = 127, + [2][0][RTW89_MKK][1][64] = 127, + [2][0][RTW89_MKK][0][64] = 127, + [2][0][RTW89_IC][1][64] = 8, + [2][0][RTW89_KCC][1][64] = -2, + [2][0][RTW89_KCC][0][64] = 127, + [2][0][RTW89_ACMA][1][64] = 127, + [2][0][RTW89_ACMA][0][64] = 127, + [2][0][RTW89_CHILE][1][64] = 127, + [2][0][RTW89_QATAR][1][64] = 127, + [2][0][RTW89_QATAR][0][64] = 127, + [2][0][RTW89_UK][1][64] = 127, + [2][0][RTW89_UK][0][64] = 127, + [2][0][RTW89_FCC][1][66] = 8, + [2][0][RTW89_FCC][2][66] = 78, + [2][0][RTW89_ETSI][1][66] = 127, + [2][0][RTW89_ETSI][0][66] = 127, + [2][0][RTW89_MKK][1][66] = 127, + [2][0][RTW89_MKK][0][66] = 127, + [2][0][RTW89_IC][1][66] = 8, + [2][0][RTW89_KCC][1][66] = -2, + [2][0][RTW89_KCC][0][66] = 127, + [2][0][RTW89_ACMA][1][66] = 127, + [2][0][RTW89_ACMA][0][66] = 127, + [2][0][RTW89_CHILE][1][66] = 127, + [2][0][RTW89_QATAR][1][66] = 127, + [2][0][RTW89_QATAR][0][66] = 127, + [2][0][RTW89_UK][1][66] = 127, + [2][0][RTW89_UK][0][66] = 127, + [2][0][RTW89_FCC][1][68] = 8, + [2][0][RTW89_FCC][2][68] = 78, + [2][0][RTW89_ETSI][1][68] = 127, + [2][0][RTW89_ETSI][0][68] = 127, + [2][0][RTW89_MKK][1][68] = 127, + [2][0][RTW89_MKK][0][68] = 127, + [2][0][RTW89_IC][1][68] = 8, + [2][0][RTW89_KCC][1][68] = -2, + [2][0][RTW89_KCC][0][68] = 127, + [2][0][RTW89_ACMA][1][68] = 127, + [2][0][RTW89_ACMA][0][68] = 127, + [2][0][RTW89_CHILE][1][68] = 127, + [2][0][RTW89_QATAR][1][68] = 127, + [2][0][RTW89_QATAR][0][68] = 127, + [2][0][RTW89_UK][1][68] = 127, + [2][0][RTW89_UK][0][68] = 127, + [2][0][RTW89_FCC][1][70] = 8, + [2][0][RTW89_FCC][2][70] = 78, + [2][0][RTW89_ETSI][1][70] = 127, + [2][0][RTW89_ETSI][0][70] = 127, + [2][0][RTW89_MKK][1][70] = 127, + [2][0][RTW89_MKK][0][70] = 127, + [2][0][RTW89_IC][1][70] = 8, + [2][0][RTW89_KCC][1][70] = -2, + [2][0][RTW89_KCC][0][70] = 127, + [2][0][RTW89_ACMA][1][70] = 127, + [2][0][RTW89_ACMA][0][70] = 127, + [2][0][RTW89_CHILE][1][70] = 127, + [2][0][RTW89_QATAR][1][70] = 127, + [2][0][RTW89_QATAR][0][70] = 127, + [2][0][RTW89_UK][1][70] = 127, + [2][0][RTW89_UK][0][70] = 127, + [2][0][RTW89_FCC][1][72] = 8, + [2][0][RTW89_FCC][2][72] = 78, + [2][0][RTW89_ETSI][1][72] = 127, + [2][0][RTW89_ETSI][0][72] = 127, + [2][0][RTW89_MKK][1][72] = 127, + [2][0][RTW89_MKK][0][72] = 127, + [2][0][RTW89_IC][1][72] = 8, + [2][0][RTW89_KCC][1][72] = -2, + [2][0][RTW89_KCC][0][72] = 127, + [2][0][RTW89_ACMA][1][72] = 127, + [2][0][RTW89_ACMA][0][72] = 127, + [2][0][RTW89_CHILE][1][72] = 127, + [2][0][RTW89_QATAR][1][72] = 127, + [2][0][RTW89_QATAR][0][72] = 127, + [2][0][RTW89_UK][1][72] = 127, + [2][0][RTW89_UK][0][72] = 127, + [2][0][RTW89_FCC][1][74] = 8, + [2][0][RTW89_FCC][2][74] = 78, + [2][0][RTW89_ETSI][1][74] = 127, + [2][0][RTW89_ETSI][0][74] = 127, + [2][0][RTW89_MKK][1][74] = 127, + [2][0][RTW89_MKK][0][74] = 127, + [2][0][RTW89_IC][1][74] = 8, + [2][0][RTW89_KCC][1][74] = -2, + [2][0][RTW89_KCC][0][74] = 127, + [2][0][RTW89_ACMA][1][74] = 127, + [2][0][RTW89_ACMA][0][74] = 127, + [2][0][RTW89_CHILE][1][74] = 127, + [2][0][RTW89_QATAR][1][74] = 127, + [2][0][RTW89_QATAR][0][74] = 127, + [2][0][RTW89_UK][1][74] = 127, + [2][0][RTW89_UK][0][74] = 127, + [2][0][RTW89_FCC][1][75] = 8, + [2][0][RTW89_FCC][2][75] = 78, + [2][0][RTW89_ETSI][1][75] = 127, + [2][0][RTW89_ETSI][0][75] = 127, + [2][0][RTW89_MKK][1][75] = 127, + [2][0][RTW89_MKK][0][75] = 127, + [2][0][RTW89_IC][1][75] = 8, + [2][0][RTW89_KCC][1][75] = -2, + [2][0][RTW89_KCC][0][75] = 127, + [2][0][RTW89_ACMA][1][75] = 127, + [2][0][RTW89_ACMA][0][75] = 127, + [2][0][RTW89_CHILE][1][75] = 127, + [2][0][RTW89_QATAR][1][75] = 127, + [2][0][RTW89_QATAR][0][75] = 127, + [2][0][RTW89_UK][1][75] = 127, + [2][0][RTW89_UK][0][75] = 127, + [2][0][RTW89_FCC][1][77] = 8, + [2][0][RTW89_FCC][2][77] = 78, + [2][0][RTW89_ETSI][1][77] = 127, + [2][0][RTW89_ETSI][0][77] = 127, + [2][0][RTW89_MKK][1][77] = 127, + [2][0][RTW89_MKK][0][77] = 127, + [2][0][RTW89_IC][1][77] = 8, + [2][0][RTW89_KCC][1][77] = -2, + [2][0][RTW89_KCC][0][77] = 127, + [2][0][RTW89_ACMA][1][77] = 127, + [2][0][RTW89_ACMA][0][77] = 127, + [2][0][RTW89_CHILE][1][77] = 127, + [2][0][RTW89_QATAR][1][77] = 127, + [2][0][RTW89_QATAR][0][77] = 127, + [2][0][RTW89_UK][1][77] = 127, + [2][0][RTW89_UK][0][77] = 127, + [2][0][RTW89_FCC][1][79] = 8, + [2][0][RTW89_FCC][2][79] = 78, + [2][0][RTW89_ETSI][1][79] = 127, + [2][0][RTW89_ETSI][0][79] = 127, + [2][0][RTW89_MKK][1][79] = 127, + [2][0][RTW89_MKK][0][79] = 127, + [2][0][RTW89_IC][1][79] = 8, + [2][0][RTW89_KCC][1][79] = -2, + [2][0][RTW89_KCC][0][79] = 127, + [2][0][RTW89_ACMA][1][79] = 127, + [2][0][RTW89_ACMA][0][79] = 127, + [2][0][RTW89_CHILE][1][79] = 127, + [2][0][RTW89_QATAR][1][79] = 127, + [2][0][RTW89_QATAR][0][79] = 127, + [2][0][RTW89_UK][1][79] = 127, + [2][0][RTW89_UK][0][79] = 127, + [2][0][RTW89_FCC][1][81] = 8, + [2][0][RTW89_FCC][2][81] = 78, + [2][0][RTW89_ETSI][1][81] = 127, + [2][0][RTW89_ETSI][0][81] = 127, + [2][0][RTW89_MKK][1][81] = 127, + [2][0][RTW89_MKK][0][81] = 127, + [2][0][RTW89_IC][1][81] = 8, + [2][0][RTW89_KCC][1][81] = -2, + [2][0][RTW89_KCC][0][81] = 127, + [2][0][RTW89_ACMA][1][81] = 127, + [2][0][RTW89_ACMA][0][81] = 127, + [2][0][RTW89_CHILE][1][81] = 127, + [2][0][RTW89_QATAR][1][81] = 127, + [2][0][RTW89_QATAR][0][81] = 127, + [2][0][RTW89_UK][1][81] = 127, + [2][0][RTW89_UK][0][81] = 127, + [2][0][RTW89_FCC][1][83] = 8, + [2][0][RTW89_FCC][2][83] = 78, + [2][0][RTW89_ETSI][1][83] = 127, + [2][0][RTW89_ETSI][0][83] = 127, + [2][0][RTW89_MKK][1][83] = 127, + [2][0][RTW89_MKK][0][83] = 127, + [2][0][RTW89_IC][1][83] = 8, + [2][0][RTW89_KCC][1][83] = -2, + [2][0][RTW89_KCC][0][83] = 127, + [2][0][RTW89_ACMA][1][83] = 127, + [2][0][RTW89_ACMA][0][83] = 127, + [2][0][RTW89_CHILE][1][83] = 127, + [2][0][RTW89_QATAR][1][83] = 127, + [2][0][RTW89_QATAR][0][83] = 127, + [2][0][RTW89_UK][1][83] = 127, + [2][0][RTW89_UK][0][83] = 127, + [2][0][RTW89_FCC][1][85] = 8, + [2][0][RTW89_FCC][2][85] = 78, + [2][0][RTW89_ETSI][1][85] = 127, + [2][0][RTW89_ETSI][0][85] = 127, + [2][0][RTW89_MKK][1][85] = 127, + [2][0][RTW89_MKK][0][85] = 127, + [2][0][RTW89_IC][1][85] = 8, + [2][0][RTW89_KCC][1][85] = -2, + [2][0][RTW89_KCC][0][85] = 127, + [2][0][RTW89_ACMA][1][85] = 127, + [2][0][RTW89_ACMA][0][85] = 127, + [2][0][RTW89_CHILE][1][85] = 127, + [2][0][RTW89_QATAR][1][85] = 127, + [2][0][RTW89_QATAR][0][85] = 127, + [2][0][RTW89_UK][1][85] = 127, + [2][0][RTW89_UK][0][85] = 127, + [2][0][RTW89_FCC][1][87] = 8, + [2][0][RTW89_FCC][2][87] = 127, + [2][0][RTW89_ETSI][1][87] = 127, + [2][0][RTW89_ETSI][0][87] = 127, + [2][0][RTW89_MKK][1][87] = 127, + [2][0][RTW89_MKK][0][87] = 127, + [2][0][RTW89_IC][1][87] = 8, + [2][0][RTW89_KCC][1][87] = -2, + [2][0][RTW89_KCC][0][87] = 127, + [2][0][RTW89_ACMA][1][87] = 127, + [2][0][RTW89_ACMA][0][87] = 127, + [2][0][RTW89_CHILE][1][87] = 127, + [2][0][RTW89_QATAR][1][87] = 127, + [2][0][RTW89_QATAR][0][87] = 127, + [2][0][RTW89_UK][1][87] = 127, + [2][0][RTW89_UK][0][87] = 127, + [2][0][RTW89_FCC][1][89] = 8, + [2][0][RTW89_FCC][2][89] = 127, + [2][0][RTW89_ETSI][1][89] = 127, + [2][0][RTW89_ETSI][0][89] = 127, + [2][0][RTW89_MKK][1][89] = 127, + [2][0][RTW89_MKK][0][89] = 127, + [2][0][RTW89_IC][1][89] = 8, + [2][0][RTW89_KCC][1][89] = -2, + [2][0][RTW89_KCC][0][89] = 127, + [2][0][RTW89_ACMA][1][89] = 127, + [2][0][RTW89_ACMA][0][89] = 127, + [2][0][RTW89_CHILE][1][89] = 127, + [2][0][RTW89_QATAR][1][89] = 127, + [2][0][RTW89_QATAR][0][89] = 127, + [2][0][RTW89_UK][1][89] = 127, + [2][0][RTW89_UK][0][89] = 127, + [2][0][RTW89_FCC][1][90] = 8, + [2][0][RTW89_FCC][2][90] = 127, + [2][0][RTW89_ETSI][1][90] = 127, + [2][0][RTW89_ETSI][0][90] = 127, + [2][0][RTW89_MKK][1][90] = 127, + [2][0][RTW89_MKK][0][90] = 127, + [2][0][RTW89_IC][1][90] = 8, + [2][0][RTW89_KCC][1][90] = -2, + [2][0][RTW89_KCC][0][90] = 127, + [2][0][RTW89_ACMA][1][90] = 127, + [2][0][RTW89_ACMA][0][90] = 127, + [2][0][RTW89_CHILE][1][90] = 127, + [2][0][RTW89_QATAR][1][90] = 127, + [2][0][RTW89_QATAR][0][90] = 127, + [2][0][RTW89_UK][1][90] = 127, + [2][0][RTW89_UK][0][90] = 127, + [2][0][RTW89_FCC][1][92] = 8, + [2][0][RTW89_FCC][2][92] = 127, + [2][0][RTW89_ETSI][1][92] = 127, + [2][0][RTW89_ETSI][0][92] = 127, + [2][0][RTW89_MKK][1][92] = 127, + [2][0][RTW89_MKK][0][92] = 127, + [2][0][RTW89_IC][1][92] = 8, + [2][0][RTW89_KCC][1][92] = -2, + [2][0][RTW89_KCC][0][92] = 127, + [2][0][RTW89_ACMA][1][92] = 127, + [2][0][RTW89_ACMA][0][92] = 127, + [2][0][RTW89_CHILE][1][92] = 127, + [2][0][RTW89_QATAR][1][92] = 127, + [2][0][RTW89_QATAR][0][92] = 127, + [2][0][RTW89_UK][1][92] = 127, + [2][0][RTW89_UK][0][92] = 127, + [2][0][RTW89_FCC][1][94] = 8, + [2][0][RTW89_FCC][2][94] = 127, + [2][0][RTW89_ETSI][1][94] = 127, + [2][0][RTW89_ETSI][0][94] = 127, + [2][0][RTW89_MKK][1][94] = 127, + [2][0][RTW89_MKK][0][94] = 127, + [2][0][RTW89_IC][1][94] = 8, + [2][0][RTW89_KCC][1][94] = -2, + [2][0][RTW89_KCC][0][94] = 127, + [2][0][RTW89_ACMA][1][94] = 127, + [2][0][RTW89_ACMA][0][94] = 127, + [2][0][RTW89_CHILE][1][94] = 127, + [2][0][RTW89_QATAR][1][94] = 127, + [2][0][RTW89_QATAR][0][94] = 127, + [2][0][RTW89_UK][1][94] = 127, + [2][0][RTW89_UK][0][94] = 127, + [2][0][RTW89_FCC][1][96] = 8, + [2][0][RTW89_FCC][2][96] = 127, + [2][0][RTW89_ETSI][1][96] = 127, + [2][0][RTW89_ETSI][0][96] = 127, + [2][0][RTW89_MKK][1][96] = 127, + [2][0][RTW89_MKK][0][96] = 127, + [2][0][RTW89_IC][1][96] = 8, + [2][0][RTW89_KCC][1][96] = -2, + [2][0][RTW89_KCC][0][96] = 127, + [2][0][RTW89_ACMA][1][96] = 127, + [2][0][RTW89_ACMA][0][96] = 127, + [2][0][RTW89_CHILE][1][96] = 127, + [2][0][RTW89_QATAR][1][96] = 127, + [2][0][RTW89_QATAR][0][96] = 127, + [2][0][RTW89_UK][1][96] = 127, + [2][0][RTW89_UK][0][96] = 127, + [2][0][RTW89_FCC][1][98] = 8, + [2][0][RTW89_FCC][2][98] = 127, + [2][0][RTW89_ETSI][1][98] = 127, + [2][0][RTW89_ETSI][0][98] = 127, + [2][0][RTW89_MKK][1][98] = 127, + [2][0][RTW89_MKK][0][98] = 127, + [2][0][RTW89_IC][1][98] = 8, + [2][0][RTW89_KCC][1][98] = -2, + [2][0][RTW89_KCC][0][98] = 127, + [2][0][RTW89_ACMA][1][98] = 127, + [2][0][RTW89_ACMA][0][98] = 127, + [2][0][RTW89_CHILE][1][98] = 127, + [2][0][RTW89_QATAR][1][98] = 127, + [2][0][RTW89_QATAR][0][98] = 127, + [2][0][RTW89_UK][1][98] = 127, + [2][0][RTW89_UK][0][98] = 127, + [2][0][RTW89_FCC][1][100] = 8, + [2][0][RTW89_FCC][2][100] = 127, + [2][0][RTW89_ETSI][1][100] = 127, + [2][0][RTW89_ETSI][0][100] = 127, + [2][0][RTW89_MKK][1][100] = 127, + [2][0][RTW89_MKK][0][100] = 127, + [2][0][RTW89_IC][1][100] = 8, + [2][0][RTW89_KCC][1][100] = -2, + [2][0][RTW89_KCC][0][100] = 127, + [2][0][RTW89_ACMA][1][100] = 127, + [2][0][RTW89_ACMA][0][100] = 127, + [2][0][RTW89_CHILE][1][100] = 127, + [2][0][RTW89_QATAR][1][100] = 127, + [2][0][RTW89_QATAR][0][100] = 127, + [2][0][RTW89_UK][1][100] = 127, + [2][0][RTW89_UK][0][100] = 127, + [2][0][RTW89_FCC][1][102] = 8, + [2][0][RTW89_FCC][2][102] = 127, + [2][0][RTW89_ETSI][1][102] = 127, + [2][0][RTW89_ETSI][0][102] = 127, + [2][0][RTW89_MKK][1][102] = 127, + [2][0][RTW89_MKK][0][102] = 127, + [2][0][RTW89_IC][1][102] = 8, + [2][0][RTW89_KCC][1][102] = -2, + [2][0][RTW89_KCC][0][102] = 127, + [2][0][RTW89_ACMA][1][102] = 127, + [2][0][RTW89_ACMA][0][102] = 127, + [2][0][RTW89_CHILE][1][102] = 127, + [2][0][RTW89_QATAR][1][102] = 127, + [2][0][RTW89_QATAR][0][102] = 127, + [2][0][RTW89_UK][1][102] = 127, + [2][0][RTW89_UK][0][102] = 127, + [2][0][RTW89_FCC][1][104] = 8, + [2][0][RTW89_FCC][2][104] = 127, + [2][0][RTW89_ETSI][1][104] = 127, + [2][0][RTW89_ETSI][0][104] = 127, + [2][0][RTW89_MKK][1][104] = 127, + [2][0][RTW89_MKK][0][104] = 127, + [2][0][RTW89_IC][1][104] = 8, + [2][0][RTW89_KCC][1][104] = -2, + [2][0][RTW89_KCC][0][104] = 127, + [2][0][RTW89_ACMA][1][104] = 127, + [2][0][RTW89_ACMA][0][104] = 127, + [2][0][RTW89_CHILE][1][104] = 127, + [2][0][RTW89_QATAR][1][104] = 127, + [2][0][RTW89_QATAR][0][104] = 127, + [2][0][RTW89_UK][1][104] = 127, + [2][0][RTW89_UK][0][104] = 127, + [2][0][RTW89_FCC][1][105] = 8, + [2][0][RTW89_FCC][2][105] = 127, + [2][0][RTW89_ETSI][1][105] = 127, + [2][0][RTW89_ETSI][0][105] = 127, + [2][0][RTW89_MKK][1][105] = 127, + [2][0][RTW89_MKK][0][105] = 127, + [2][0][RTW89_IC][1][105] = 8, + [2][0][RTW89_KCC][1][105] = -2, + [2][0][RTW89_KCC][0][105] = 127, + [2][0][RTW89_ACMA][1][105] = 127, + [2][0][RTW89_ACMA][0][105] = 127, + [2][0][RTW89_CHILE][1][105] = 127, + [2][0][RTW89_QATAR][1][105] = 127, + [2][0][RTW89_QATAR][0][105] = 127, + [2][0][RTW89_UK][1][105] = 127, + [2][0][RTW89_UK][0][105] = 127, + [2][0][RTW89_FCC][1][107] = 10, + [2][0][RTW89_FCC][2][107] = 127, + [2][0][RTW89_ETSI][1][107] = 127, + [2][0][RTW89_ETSI][0][107] = 127, + [2][0][RTW89_MKK][1][107] = 127, + [2][0][RTW89_MKK][0][107] = 127, + [2][0][RTW89_IC][1][107] = 10, + [2][0][RTW89_KCC][1][107] = -2, + [2][0][RTW89_KCC][0][107] = 127, + [2][0][RTW89_ACMA][1][107] = 127, + [2][0][RTW89_ACMA][0][107] = 127, + [2][0][RTW89_CHILE][1][107] = 127, + [2][0][RTW89_QATAR][1][107] = 127, + [2][0][RTW89_QATAR][0][107] = 127, + [2][0][RTW89_UK][1][107] = 127, + [2][0][RTW89_UK][0][107] = 127, + [2][0][RTW89_FCC][1][109] = 12, + [2][0][RTW89_FCC][2][109] = 127, + [2][0][RTW89_ETSI][1][109] = 127, + [2][0][RTW89_ETSI][0][109] = 127, + [2][0][RTW89_MKK][1][109] = 127, + [2][0][RTW89_MKK][0][109] = 127, + [2][0][RTW89_IC][1][109] = 12, + [2][0][RTW89_KCC][1][109] = 127, + [2][0][RTW89_KCC][0][109] = 127, + [2][0][RTW89_ACMA][1][109] = 127, + [2][0][RTW89_ACMA][0][109] = 127, + [2][0][RTW89_CHILE][1][109] = 127, + [2][0][RTW89_QATAR][1][109] = 127, + [2][0][RTW89_QATAR][0][109] = 127, + [2][0][RTW89_UK][1][109] = 127, + [2][0][RTW89_UK][0][109] = 127, + [2][0][RTW89_FCC][1][111] = 127, + [2][0][RTW89_FCC][2][111] = 127, + [2][0][RTW89_ETSI][1][111] = 127, + [2][0][RTW89_ETSI][0][111] = 127, + [2][0][RTW89_MKK][1][111] = 127, + [2][0][RTW89_MKK][0][111] = 127, + [2][0][RTW89_IC][1][111] = 127, + [2][0][RTW89_KCC][1][111] = 127, + [2][0][RTW89_KCC][0][111] = 127, + [2][0][RTW89_ACMA][1][111] = 127, + [2][0][RTW89_ACMA][0][111] = 127, + [2][0][RTW89_CHILE][1][111] = 127, + [2][0][RTW89_QATAR][1][111] = 127, + [2][0][RTW89_QATAR][0][111] = 127, + [2][0][RTW89_UK][1][111] = 127, + [2][0][RTW89_UK][0][111] = 127, + [2][0][RTW89_FCC][1][113] = 127, + [2][0][RTW89_FCC][2][113] = 127, + [2][0][RTW89_ETSI][1][113] = 127, + [2][0][RTW89_ETSI][0][113] = 127, + [2][0][RTW89_MKK][1][113] = 127, + [2][0][RTW89_MKK][0][113] = 127, + [2][0][RTW89_IC][1][113] = 127, + [2][0][RTW89_KCC][1][113] = 127, + [2][0][RTW89_KCC][0][113] = 127, + [2][0][RTW89_ACMA][1][113] = 127, + [2][0][RTW89_ACMA][0][113] = 127, + [2][0][RTW89_CHILE][1][113] = 127, + [2][0][RTW89_QATAR][1][113] = 127, + [2][0][RTW89_QATAR][0][113] = 127, + [2][0][RTW89_UK][1][113] = 127, + [2][0][RTW89_UK][0][113] = 127, + [2][0][RTW89_FCC][1][115] = 127, + [2][0][RTW89_FCC][2][115] = 127, + [2][0][RTW89_ETSI][1][115] = 127, + [2][0][RTW89_ETSI][0][115] = 127, + [2][0][RTW89_MKK][1][115] = 127, + [2][0][RTW89_MKK][0][115] = 127, + [2][0][RTW89_IC][1][115] = 127, + [2][0][RTW89_KCC][1][115] = 127, + [2][0][RTW89_KCC][0][115] = 127, + [2][0][RTW89_ACMA][1][115] = 127, + [2][0][RTW89_ACMA][0][115] = 127, + [2][0][RTW89_CHILE][1][115] = 127, + [2][0][RTW89_QATAR][1][115] = 127, + [2][0][RTW89_QATAR][0][115] = 127, + [2][0][RTW89_UK][1][115] = 127, + [2][0][RTW89_UK][0][115] = 127, + [2][0][RTW89_FCC][1][117] = 127, + [2][0][RTW89_FCC][2][117] = 127, + [2][0][RTW89_ETSI][1][117] = 127, + [2][0][RTW89_ETSI][0][117] = 127, + [2][0][RTW89_MKK][1][117] = 127, + [2][0][RTW89_MKK][0][117] = 127, + [2][0][RTW89_IC][1][117] = 127, + [2][0][RTW89_KCC][1][117] = 127, + [2][0][RTW89_KCC][0][117] = 127, + [2][0][RTW89_ACMA][1][117] = 127, + [2][0][RTW89_ACMA][0][117] = 127, + [2][0][RTW89_CHILE][1][117] = 127, + [2][0][RTW89_QATAR][1][117] = 127, + [2][0][RTW89_QATAR][0][117] = 127, + [2][0][RTW89_UK][1][117] = 127, + [2][0][RTW89_UK][0][117] = 127, + [2][0][RTW89_FCC][1][119] = 127, + [2][0][RTW89_FCC][2][119] = 127, + [2][0][RTW89_ETSI][1][119] = 127, + [2][0][RTW89_ETSI][0][119] = 127, + [2][0][RTW89_MKK][1][119] = 127, + [2][0][RTW89_MKK][0][119] = 127, + [2][0][RTW89_IC][1][119] = 127, + [2][0][RTW89_KCC][1][119] = 127, + [2][0][RTW89_KCC][0][119] = 127, + [2][0][RTW89_ACMA][1][119] = 127, + [2][0][RTW89_ACMA][0][119] = 127, + [2][0][RTW89_CHILE][1][119] = 127, + [2][0][RTW89_QATAR][1][119] = 127, + [2][0][RTW89_QATAR][0][119] = 127, + [2][0][RTW89_UK][1][119] = 127, + [2][0][RTW89_UK][0][119] = 127, + [2][1][RTW89_FCC][1][0] = -16, + [2][1][RTW89_FCC][2][0] = 54, + [2][1][RTW89_ETSI][1][0] = 44, + [2][1][RTW89_ETSI][0][0] = 6, + [2][1][RTW89_MKK][1][0] = 42, + [2][1][RTW89_MKK][0][0] = 2, + [2][1][RTW89_IC][1][0] = -16, + [2][1][RTW89_KCC][1][0] = -14, + [2][1][RTW89_KCC][0][0] = -14, + [2][1][RTW89_ACMA][1][0] = 44, + [2][1][RTW89_ACMA][0][0] = 6, + [2][1][RTW89_CHILE][1][0] = -16, + [2][1][RTW89_QATAR][1][0] = 44, + [2][1][RTW89_QATAR][0][0] = 6, + [2][1][RTW89_UK][1][0] = 44, + [2][1][RTW89_UK][0][0] = 6, + [2][1][RTW89_FCC][1][2] = -16, + [2][1][RTW89_FCC][2][2] = 54, + [2][1][RTW89_ETSI][1][2] = 44, + [2][1][RTW89_ETSI][0][2] = 6, + [2][1][RTW89_MKK][1][2] = 40, + [2][1][RTW89_MKK][0][2] = 2, + [2][1][RTW89_IC][1][2] = -16, + [2][1][RTW89_KCC][1][2] = -14, + [2][1][RTW89_KCC][0][2] = -14, + [2][1][RTW89_ACMA][1][2] = 44, + [2][1][RTW89_ACMA][0][2] = 6, + [2][1][RTW89_CHILE][1][2] = -16, + [2][1][RTW89_QATAR][1][2] = 44, + [2][1][RTW89_QATAR][0][2] = 6, + [2][1][RTW89_UK][1][2] = 44, + [2][1][RTW89_UK][0][2] = 6, + [2][1][RTW89_FCC][1][4] = -16, + [2][1][RTW89_FCC][2][4] = 54, + [2][1][RTW89_ETSI][1][4] = 44, + [2][1][RTW89_ETSI][0][4] = 6, + [2][1][RTW89_MKK][1][4] = 40, + [2][1][RTW89_MKK][0][4] = 2, + [2][1][RTW89_IC][1][4] = -16, + [2][1][RTW89_KCC][1][4] = -14, + [2][1][RTW89_KCC][0][4] = -14, + [2][1][RTW89_ACMA][1][4] = 44, + [2][1][RTW89_ACMA][0][4] = 6, + [2][1][RTW89_CHILE][1][4] = -16, + [2][1][RTW89_QATAR][1][4] = 44, + [2][1][RTW89_QATAR][0][4] = 6, + [2][1][RTW89_UK][1][4] = 44, + [2][1][RTW89_UK][0][4] = 6, + [2][1][RTW89_FCC][1][6] = -16, + [2][1][RTW89_FCC][2][6] = 54, + [2][1][RTW89_ETSI][1][6] = 44, + [2][1][RTW89_ETSI][0][6] = 6, + [2][1][RTW89_MKK][1][6] = 40, + [2][1][RTW89_MKK][0][6] = 2, + [2][1][RTW89_IC][1][6] = -16, + [2][1][RTW89_KCC][1][6] = -14, + [2][1][RTW89_KCC][0][6] = -14, + [2][1][RTW89_ACMA][1][6] = 44, + [2][1][RTW89_ACMA][0][6] = 6, + [2][1][RTW89_CHILE][1][6] = -16, + [2][1][RTW89_QATAR][1][6] = 44, + [2][1][RTW89_QATAR][0][6] = 6, + [2][1][RTW89_UK][1][6] = 44, + [2][1][RTW89_UK][0][6] = 6, + [2][1][RTW89_FCC][1][8] = -16, + [2][1][RTW89_FCC][2][8] = 54, + [2][1][RTW89_ETSI][1][8] = 44, + [2][1][RTW89_ETSI][0][8] = 6, + [2][1][RTW89_MKK][1][8] = 40, + [2][1][RTW89_MKK][0][8] = 2, + [2][1][RTW89_IC][1][8] = -16, + [2][1][RTW89_KCC][1][8] = -14, + [2][1][RTW89_KCC][0][8] = -14, + [2][1][RTW89_ACMA][1][8] = 44, + [2][1][RTW89_ACMA][0][8] = 6, + [2][1][RTW89_CHILE][1][8] = -16, + [2][1][RTW89_QATAR][1][8] = 44, + [2][1][RTW89_QATAR][0][8] = 6, + [2][1][RTW89_UK][1][8] = 44, + [2][1][RTW89_UK][0][8] = 6, + [2][1][RTW89_FCC][1][10] = -16, + [2][1][RTW89_FCC][2][10] = 54, + [2][1][RTW89_ETSI][1][10] = 44, + [2][1][RTW89_ETSI][0][10] = 6, + [2][1][RTW89_MKK][1][10] = 40, + [2][1][RTW89_MKK][0][10] = 2, + [2][1][RTW89_IC][1][10] = -16, + [2][1][RTW89_KCC][1][10] = -14, + [2][1][RTW89_KCC][0][10] = -14, + [2][1][RTW89_ACMA][1][10] = 44, + [2][1][RTW89_ACMA][0][10] = 6, + [2][1][RTW89_CHILE][1][10] = -16, + [2][1][RTW89_QATAR][1][10] = 44, + [2][1][RTW89_QATAR][0][10] = 6, + [2][1][RTW89_UK][1][10] = 44, + [2][1][RTW89_UK][0][10] = 6, + [2][1][RTW89_FCC][1][12] = -16, + [2][1][RTW89_FCC][2][12] = 54, + [2][1][RTW89_ETSI][1][12] = 44, + [2][1][RTW89_ETSI][0][12] = 6, + [2][1][RTW89_MKK][1][12] = 40, + [2][1][RTW89_MKK][0][12] = 2, + [2][1][RTW89_IC][1][12] = -16, + [2][1][RTW89_KCC][1][12] = -14, + [2][1][RTW89_KCC][0][12] = -14, + [2][1][RTW89_ACMA][1][12] = 44, + [2][1][RTW89_ACMA][0][12] = 6, + [2][1][RTW89_CHILE][1][12] = -16, + [2][1][RTW89_QATAR][1][12] = 44, + [2][1][RTW89_QATAR][0][12] = 6, + [2][1][RTW89_UK][1][12] = 44, + [2][1][RTW89_UK][0][12] = 6, + [2][1][RTW89_FCC][1][14] = -16, + [2][1][RTW89_FCC][2][14] = 54, + [2][1][RTW89_ETSI][1][14] = 44, + [2][1][RTW89_ETSI][0][14] = 6, + [2][1][RTW89_MKK][1][14] = 40, + [2][1][RTW89_MKK][0][14] = 2, + [2][1][RTW89_IC][1][14] = -16, + [2][1][RTW89_KCC][1][14] = -14, + [2][1][RTW89_KCC][0][14] = -14, + [2][1][RTW89_ACMA][1][14] = 44, + [2][1][RTW89_ACMA][0][14] = 6, + [2][1][RTW89_CHILE][1][14] = -16, + [2][1][RTW89_QATAR][1][14] = 44, + [2][1][RTW89_QATAR][0][14] = 6, + [2][1][RTW89_UK][1][14] = 44, + [2][1][RTW89_UK][0][14] = 6, + [2][1][RTW89_FCC][1][15] = -16, + [2][1][RTW89_FCC][2][15] = 54, + [2][1][RTW89_ETSI][1][15] = 44, + [2][1][RTW89_ETSI][0][15] = 6, + [2][1][RTW89_MKK][1][15] = 40, + [2][1][RTW89_MKK][0][15] = 2, + [2][1][RTW89_IC][1][15] = -16, + [2][1][RTW89_KCC][1][15] = -14, + [2][1][RTW89_KCC][0][15] = -14, + [2][1][RTW89_ACMA][1][15] = 44, + [2][1][RTW89_ACMA][0][15] = 6, + [2][1][RTW89_CHILE][1][15] = -16, + [2][1][RTW89_QATAR][1][15] = 44, + [2][1][RTW89_QATAR][0][15] = 6, + [2][1][RTW89_UK][1][15] = 44, + [2][1][RTW89_UK][0][15] = 6, + [2][1][RTW89_FCC][1][17] = -16, + [2][1][RTW89_FCC][2][17] = 54, + [2][1][RTW89_ETSI][1][17] = 44, + [2][1][RTW89_ETSI][0][17] = 6, + [2][1][RTW89_MKK][1][17] = 40, + [2][1][RTW89_MKK][0][17] = 2, + [2][1][RTW89_IC][1][17] = -16, + [2][1][RTW89_KCC][1][17] = -14, + [2][1][RTW89_KCC][0][17] = -14, + [2][1][RTW89_ACMA][1][17] = 44, + [2][1][RTW89_ACMA][0][17] = 6, + [2][1][RTW89_CHILE][1][17] = -16, + [2][1][RTW89_QATAR][1][17] = 44, + [2][1][RTW89_QATAR][0][17] = 6, + [2][1][RTW89_UK][1][17] = 44, + [2][1][RTW89_UK][0][17] = 6, + [2][1][RTW89_FCC][1][19] = -16, + [2][1][RTW89_FCC][2][19] = 54, + [2][1][RTW89_ETSI][1][19] = 44, + [2][1][RTW89_ETSI][0][19] = 6, + [2][1][RTW89_MKK][1][19] = 40, + [2][1][RTW89_MKK][0][19] = 2, + [2][1][RTW89_IC][1][19] = -16, + [2][1][RTW89_KCC][1][19] = -14, + [2][1][RTW89_KCC][0][19] = -14, + [2][1][RTW89_ACMA][1][19] = 44, + [2][1][RTW89_ACMA][0][19] = 6, + [2][1][RTW89_CHILE][1][19] = -16, + [2][1][RTW89_QATAR][1][19] = 44, + [2][1][RTW89_QATAR][0][19] = 6, + [2][1][RTW89_UK][1][19] = 44, + [2][1][RTW89_UK][0][19] = 6, + [2][1][RTW89_FCC][1][21] = -16, + [2][1][RTW89_FCC][2][21] = 54, + [2][1][RTW89_ETSI][1][21] = 44, + [2][1][RTW89_ETSI][0][21] = 6, + [2][1][RTW89_MKK][1][21] = 40, + [2][1][RTW89_MKK][0][21] = 2, + [2][1][RTW89_IC][1][21] = -16, + [2][1][RTW89_KCC][1][21] = -14, + [2][1][RTW89_KCC][0][21] = -14, + [2][1][RTW89_ACMA][1][21] = 44, + [2][1][RTW89_ACMA][0][21] = 6, + [2][1][RTW89_CHILE][1][21] = -16, + [2][1][RTW89_QATAR][1][21] = 44, + [2][1][RTW89_QATAR][0][21] = 6, + [2][1][RTW89_UK][1][21] = 44, + [2][1][RTW89_UK][0][21] = 6, + [2][1][RTW89_FCC][1][23] = -16, + [2][1][RTW89_FCC][2][23] = 54, + [2][1][RTW89_ETSI][1][23] = 44, + [2][1][RTW89_ETSI][0][23] = 6, + [2][1][RTW89_MKK][1][23] = 40, + [2][1][RTW89_MKK][0][23] = 2, + [2][1][RTW89_IC][1][23] = -16, + [2][1][RTW89_KCC][1][23] = -14, + [2][1][RTW89_KCC][0][23] = -14, + [2][1][RTW89_ACMA][1][23] = 44, + [2][1][RTW89_ACMA][0][23] = 6, + [2][1][RTW89_CHILE][1][23] = -16, + [2][1][RTW89_QATAR][1][23] = 44, + [2][1][RTW89_QATAR][0][23] = 6, + [2][1][RTW89_UK][1][23] = 44, + [2][1][RTW89_UK][0][23] = 6, + [2][1][RTW89_FCC][1][25] = -16, + [2][1][RTW89_FCC][2][25] = 54, + [2][1][RTW89_ETSI][1][25] = 44, + [2][1][RTW89_ETSI][0][25] = 6, + [2][1][RTW89_MKK][1][25] = 40, + [2][1][RTW89_MKK][0][25] = 2, + [2][1][RTW89_IC][1][25] = -16, + [2][1][RTW89_KCC][1][25] = -14, + [2][1][RTW89_KCC][0][25] = -14, + [2][1][RTW89_ACMA][1][25] = 44, + [2][1][RTW89_ACMA][0][25] = 6, + [2][1][RTW89_CHILE][1][25] = -16, + [2][1][RTW89_QATAR][1][25] = 44, + [2][1][RTW89_QATAR][0][25] = 6, + [2][1][RTW89_UK][1][25] = 44, + [2][1][RTW89_UK][0][25] = 6, + [2][1][RTW89_FCC][1][27] = -16, + [2][1][RTW89_FCC][2][27] = 54, + [2][1][RTW89_ETSI][1][27] = 44, + [2][1][RTW89_ETSI][0][27] = 6, + [2][1][RTW89_MKK][1][27] = 40, + [2][1][RTW89_MKK][0][27] = 2, + [2][1][RTW89_IC][1][27] = -16, + [2][1][RTW89_KCC][1][27] = -14, + [2][1][RTW89_KCC][0][27] = -14, + [2][1][RTW89_ACMA][1][27] = 44, + [2][1][RTW89_ACMA][0][27] = 6, + [2][1][RTW89_CHILE][1][27] = -16, + [2][1][RTW89_QATAR][1][27] = 44, + [2][1][RTW89_QATAR][0][27] = 6, + [2][1][RTW89_UK][1][27] = 44, + [2][1][RTW89_UK][0][27] = 6, + [2][1][RTW89_FCC][1][29] = -16, + [2][1][RTW89_FCC][2][29] = 54, + [2][1][RTW89_ETSI][1][29] = 44, + [2][1][RTW89_ETSI][0][29] = 6, + [2][1][RTW89_MKK][1][29] = 40, + [2][1][RTW89_MKK][0][29] = 2, + [2][1][RTW89_IC][1][29] = -16, + [2][1][RTW89_KCC][1][29] = -14, + [2][1][RTW89_KCC][0][29] = -14, + [2][1][RTW89_ACMA][1][29] = 44, + [2][1][RTW89_ACMA][0][29] = 6, + [2][1][RTW89_CHILE][1][29] = -16, + [2][1][RTW89_QATAR][1][29] = 44, + [2][1][RTW89_QATAR][0][29] = 6, + [2][1][RTW89_UK][1][29] = 44, + [2][1][RTW89_UK][0][29] = 6, + [2][1][RTW89_FCC][1][30] = -16, + [2][1][RTW89_FCC][2][30] = 54, + [2][1][RTW89_ETSI][1][30] = 44, + [2][1][RTW89_ETSI][0][30] = 6, + [2][1][RTW89_MKK][1][30] = 40, + [2][1][RTW89_MKK][0][30] = 2, + [2][1][RTW89_IC][1][30] = -16, + [2][1][RTW89_KCC][1][30] = -14, + [2][1][RTW89_KCC][0][30] = -14, + [2][1][RTW89_ACMA][1][30] = 44, + [2][1][RTW89_ACMA][0][30] = 6, + [2][1][RTW89_CHILE][1][30] = -16, + [2][1][RTW89_QATAR][1][30] = 44, + [2][1][RTW89_QATAR][0][30] = 6, + [2][1][RTW89_UK][1][30] = 44, + [2][1][RTW89_UK][0][30] = 6, + [2][1][RTW89_FCC][1][32] = -16, + [2][1][RTW89_FCC][2][32] = 54, + [2][1][RTW89_ETSI][1][32] = 44, + [2][1][RTW89_ETSI][0][32] = 6, + [2][1][RTW89_MKK][1][32] = 40, + [2][1][RTW89_MKK][0][32] = 2, + [2][1][RTW89_IC][1][32] = -16, + [2][1][RTW89_KCC][1][32] = -14, + [2][1][RTW89_KCC][0][32] = -14, + [2][1][RTW89_ACMA][1][32] = 44, + [2][1][RTW89_ACMA][0][32] = 6, + [2][1][RTW89_CHILE][1][32] = -16, + [2][1][RTW89_QATAR][1][32] = 44, + [2][1][RTW89_QATAR][0][32] = 6, + [2][1][RTW89_UK][1][32] = 44, + [2][1][RTW89_UK][0][32] = 6, + [2][1][RTW89_FCC][1][34] = -16, + [2][1][RTW89_FCC][2][34] = 54, + [2][1][RTW89_ETSI][1][34] = 44, + [2][1][RTW89_ETSI][0][34] = 6, + [2][1][RTW89_MKK][1][34] = 40, + [2][1][RTW89_MKK][0][34] = 2, + [2][1][RTW89_IC][1][34] = -16, + [2][1][RTW89_KCC][1][34] = -14, + [2][1][RTW89_KCC][0][34] = -14, + [2][1][RTW89_ACMA][1][34] = 44, + [2][1][RTW89_ACMA][0][34] = 6, + [2][1][RTW89_CHILE][1][34] = -16, + [2][1][RTW89_QATAR][1][34] = 44, + [2][1][RTW89_QATAR][0][34] = 6, + [2][1][RTW89_UK][1][34] = 44, + [2][1][RTW89_UK][0][34] = 6, + [2][1][RTW89_FCC][1][36] = -16, + [2][1][RTW89_FCC][2][36] = 54, + [2][1][RTW89_ETSI][1][36] = 44, + [2][1][RTW89_ETSI][0][36] = 6, + [2][1][RTW89_MKK][1][36] = 40, + [2][1][RTW89_MKK][0][36] = 2, + [2][1][RTW89_IC][1][36] = -16, + [2][1][RTW89_KCC][1][36] = -14, + [2][1][RTW89_KCC][0][36] = -14, + [2][1][RTW89_ACMA][1][36] = 44, + [2][1][RTW89_ACMA][0][36] = 6, + [2][1][RTW89_CHILE][1][36] = -16, + [2][1][RTW89_QATAR][1][36] = 44, + [2][1][RTW89_QATAR][0][36] = 6, + [2][1][RTW89_UK][1][36] = 44, + [2][1][RTW89_UK][0][36] = 6, + [2][1][RTW89_FCC][1][38] = -16, + [2][1][RTW89_FCC][2][38] = 54, + [2][1][RTW89_ETSI][1][38] = 44, + [2][1][RTW89_ETSI][0][38] = 6, + [2][1][RTW89_MKK][1][38] = 40, + [2][1][RTW89_MKK][0][38] = 2, + [2][1][RTW89_IC][1][38] = -16, + [2][1][RTW89_KCC][1][38] = -14, + [2][1][RTW89_KCC][0][38] = -14, + [2][1][RTW89_ACMA][1][38] = 44, + [2][1][RTW89_ACMA][0][38] = 6, + [2][1][RTW89_CHILE][1][38] = -16, + [2][1][RTW89_QATAR][1][38] = 44, + [2][1][RTW89_QATAR][0][38] = 6, + [2][1][RTW89_UK][1][38] = 44, + [2][1][RTW89_UK][0][38] = 6, + [2][1][RTW89_FCC][1][40] = -16, + [2][1][RTW89_FCC][2][40] = 54, + [2][1][RTW89_ETSI][1][40] = 44, + [2][1][RTW89_ETSI][0][40] = 6, + [2][1][RTW89_MKK][1][40] = 40, + [2][1][RTW89_MKK][0][40] = 2, + [2][1][RTW89_IC][1][40] = -16, + [2][1][RTW89_KCC][1][40] = -14, + [2][1][RTW89_KCC][0][40] = -14, + [2][1][RTW89_ACMA][1][40] = 44, + [2][1][RTW89_ACMA][0][40] = 6, + [2][1][RTW89_CHILE][1][40] = -16, + [2][1][RTW89_QATAR][1][40] = 44, + [2][1][RTW89_QATAR][0][40] = 6, + [2][1][RTW89_UK][1][40] = 44, + [2][1][RTW89_UK][0][40] = 6, + [2][1][RTW89_FCC][1][42] = -16, + [2][1][RTW89_FCC][2][42] = 54, + [2][1][RTW89_ETSI][1][42] = 44, + [2][1][RTW89_ETSI][0][42] = 6, + [2][1][RTW89_MKK][1][42] = 40, + [2][1][RTW89_MKK][0][42] = 2, + [2][1][RTW89_IC][1][42] = -16, + [2][1][RTW89_KCC][1][42] = -14, + [2][1][RTW89_KCC][0][42] = -14, + [2][1][RTW89_ACMA][1][42] = 44, + [2][1][RTW89_ACMA][0][42] = 6, + [2][1][RTW89_CHILE][1][42] = -16, + [2][1][RTW89_QATAR][1][42] = 44, + [2][1][RTW89_QATAR][0][42] = 6, + [2][1][RTW89_UK][1][42] = 44, + [2][1][RTW89_UK][0][42] = 6, + [2][1][RTW89_FCC][1][44] = -16, + [2][1][RTW89_FCC][2][44] = 54, + [2][1][RTW89_ETSI][1][44] = 44, + [2][1][RTW89_ETSI][0][44] = 6, + [2][1][RTW89_MKK][1][44] = 16, + [2][1][RTW89_MKK][0][44] = 2, + [2][1][RTW89_IC][1][44] = -16, + [2][1][RTW89_KCC][1][44] = -14, + [2][1][RTW89_KCC][0][44] = -14, + [2][1][RTW89_ACMA][1][44] = 44, + [2][1][RTW89_ACMA][0][44] = 6, + [2][1][RTW89_CHILE][1][44] = -16, + [2][1][RTW89_QATAR][1][44] = 44, + [2][1][RTW89_QATAR][0][44] = 6, + [2][1][RTW89_UK][1][44] = 44, + [2][1][RTW89_UK][0][44] = 6, + [2][1][RTW89_FCC][1][45] = -16, + [2][1][RTW89_FCC][2][45] = 127, + [2][1][RTW89_ETSI][1][45] = 127, + [2][1][RTW89_ETSI][0][45] = 127, + [2][1][RTW89_MKK][1][45] = 127, + [2][1][RTW89_MKK][0][45] = 127, + [2][1][RTW89_IC][1][45] = -16, + [2][1][RTW89_KCC][1][45] = -14, + [2][1][RTW89_KCC][0][45] = 127, + [2][1][RTW89_ACMA][1][45] = 127, + [2][1][RTW89_ACMA][0][45] = 127, + [2][1][RTW89_CHILE][1][45] = 127, + [2][1][RTW89_QATAR][1][45] = 127, + [2][1][RTW89_QATAR][0][45] = 127, + [2][1][RTW89_UK][1][45] = 127, + [2][1][RTW89_UK][0][45] = 127, + [2][1][RTW89_FCC][1][47] = -16, + [2][1][RTW89_FCC][2][47] = 127, + [2][1][RTW89_ETSI][1][47] = 127, + [2][1][RTW89_ETSI][0][47] = 127, + [2][1][RTW89_MKK][1][47] = 127, + [2][1][RTW89_MKK][0][47] = 127, + [2][1][RTW89_IC][1][47] = -16, + [2][1][RTW89_KCC][1][47] = -14, + [2][1][RTW89_KCC][0][47] = 127, + [2][1][RTW89_ACMA][1][47] = 127, + [2][1][RTW89_ACMA][0][47] = 127, + [2][1][RTW89_CHILE][1][47] = 127, + [2][1][RTW89_QATAR][1][47] = 127, + [2][1][RTW89_QATAR][0][47] = 127, + [2][1][RTW89_UK][1][47] = 127, + [2][1][RTW89_UK][0][47] = 127, + [2][1][RTW89_FCC][1][49] = -16, + [2][1][RTW89_FCC][2][49] = 127, + [2][1][RTW89_ETSI][1][49] = 127, + [2][1][RTW89_ETSI][0][49] = 127, + [2][1][RTW89_MKK][1][49] = 127, + [2][1][RTW89_MKK][0][49] = 127, + [2][1][RTW89_IC][1][49] = -16, + [2][1][RTW89_KCC][1][49] = -14, + [2][1][RTW89_KCC][0][49] = 127, + [2][1][RTW89_ACMA][1][49] = 127, + [2][1][RTW89_ACMA][0][49] = 127, + [2][1][RTW89_CHILE][1][49] = 127, + [2][1][RTW89_QATAR][1][49] = 127, + [2][1][RTW89_QATAR][0][49] = 127, + [2][1][RTW89_UK][1][49] = 127, + [2][1][RTW89_UK][0][49] = 127, + [2][1][RTW89_FCC][1][51] = -16, + [2][1][RTW89_FCC][2][51] = 127, + [2][1][RTW89_ETSI][1][51] = 127, + [2][1][RTW89_ETSI][0][51] = 127, + [2][1][RTW89_MKK][1][51] = 127, + [2][1][RTW89_MKK][0][51] = 127, + [2][1][RTW89_IC][1][51] = -16, + [2][1][RTW89_KCC][1][51] = -14, + [2][1][RTW89_KCC][0][51] = 127, + [2][1][RTW89_ACMA][1][51] = 127, + [2][1][RTW89_ACMA][0][51] = 127, + [2][1][RTW89_CHILE][1][51] = 127, + [2][1][RTW89_QATAR][1][51] = 127, + [2][1][RTW89_QATAR][0][51] = 127, + [2][1][RTW89_UK][1][51] = 127, + [2][1][RTW89_UK][0][51] = 127, + [2][1][RTW89_FCC][1][53] = -16, + [2][1][RTW89_FCC][2][53] = 127, + [2][1][RTW89_ETSI][1][53] = 127, + [2][1][RTW89_ETSI][0][53] = 127, + [2][1][RTW89_MKK][1][53] = 127, + [2][1][RTW89_MKK][0][53] = 127, + [2][1][RTW89_IC][1][53] = -16, + [2][1][RTW89_KCC][1][53] = -14, + [2][1][RTW89_KCC][0][53] = 127, + [2][1][RTW89_ACMA][1][53] = 127, + [2][1][RTW89_ACMA][0][53] = 127, + [2][1][RTW89_CHILE][1][53] = 127, + [2][1][RTW89_QATAR][1][53] = 127, + [2][1][RTW89_QATAR][0][53] = 127, + [2][1][RTW89_UK][1][53] = 127, + [2][1][RTW89_UK][0][53] = 127, + [2][1][RTW89_FCC][1][55] = -16, + [2][1][RTW89_FCC][2][55] = 54, + [2][1][RTW89_ETSI][1][55] = 127, + [2][1][RTW89_ETSI][0][55] = 127, + [2][1][RTW89_MKK][1][55] = 127, + [2][1][RTW89_MKK][0][55] = 127, + [2][1][RTW89_IC][1][55] = -16, + [2][1][RTW89_KCC][1][55] = -14, + [2][1][RTW89_KCC][0][55] = 127, + [2][1][RTW89_ACMA][1][55] = 127, + [2][1][RTW89_ACMA][0][55] = 127, + [2][1][RTW89_CHILE][1][55] = 127, + [2][1][RTW89_QATAR][1][55] = 127, + [2][1][RTW89_QATAR][0][55] = 127, + [2][1][RTW89_UK][1][55] = 127, + [2][1][RTW89_UK][0][55] = 127, + [2][1][RTW89_FCC][1][57] = -16, + [2][1][RTW89_FCC][2][57] = 54, + [2][1][RTW89_ETSI][1][57] = 127, + [2][1][RTW89_ETSI][0][57] = 127, + [2][1][RTW89_MKK][1][57] = 127, + [2][1][RTW89_MKK][0][57] = 127, + [2][1][RTW89_IC][1][57] = -16, + [2][1][RTW89_KCC][1][57] = -14, + [2][1][RTW89_KCC][0][57] = 127, + [2][1][RTW89_ACMA][1][57] = 127, + [2][1][RTW89_ACMA][0][57] = 127, + [2][1][RTW89_CHILE][1][57] = 127, + [2][1][RTW89_QATAR][1][57] = 127, + [2][1][RTW89_QATAR][0][57] = 127, + [2][1][RTW89_UK][1][57] = 127, + [2][1][RTW89_UK][0][57] = 127, + [2][1][RTW89_FCC][1][59] = -16, + [2][1][RTW89_FCC][2][59] = 54, + [2][1][RTW89_ETSI][1][59] = 127, + [2][1][RTW89_ETSI][0][59] = 127, + [2][1][RTW89_MKK][1][59] = 127, + [2][1][RTW89_MKK][0][59] = 127, + [2][1][RTW89_IC][1][59] = -16, + [2][1][RTW89_KCC][1][59] = -14, + [2][1][RTW89_KCC][0][59] = 127, + [2][1][RTW89_ACMA][1][59] = 127, + [2][1][RTW89_ACMA][0][59] = 127, + [2][1][RTW89_CHILE][1][59] = 127, + [2][1][RTW89_QATAR][1][59] = 127, + [2][1][RTW89_QATAR][0][59] = 127, + [2][1][RTW89_UK][1][59] = 127, + [2][1][RTW89_UK][0][59] = 127, + [2][1][RTW89_FCC][1][60] = -16, + [2][1][RTW89_FCC][2][60] = 54, + [2][1][RTW89_ETSI][1][60] = 127, + [2][1][RTW89_ETSI][0][60] = 127, + [2][1][RTW89_MKK][1][60] = 127, + [2][1][RTW89_MKK][0][60] = 127, + [2][1][RTW89_IC][1][60] = -16, + [2][1][RTW89_KCC][1][60] = -14, + [2][1][RTW89_KCC][0][60] = 127, + [2][1][RTW89_ACMA][1][60] = 127, + [2][1][RTW89_ACMA][0][60] = 127, + [2][1][RTW89_CHILE][1][60] = 127, + [2][1][RTW89_QATAR][1][60] = 127, + [2][1][RTW89_QATAR][0][60] = 127, + [2][1][RTW89_UK][1][60] = 127, + [2][1][RTW89_UK][0][60] = 127, + [2][1][RTW89_FCC][1][62] = -16, + [2][1][RTW89_FCC][2][62] = 54, + [2][1][RTW89_ETSI][1][62] = 127, + [2][1][RTW89_ETSI][0][62] = 127, + [2][1][RTW89_MKK][1][62] = 127, + [2][1][RTW89_MKK][0][62] = 127, + [2][1][RTW89_IC][1][62] = -16, + [2][1][RTW89_KCC][1][62] = -14, + [2][1][RTW89_KCC][0][62] = 127, + [2][1][RTW89_ACMA][1][62] = 127, + [2][1][RTW89_ACMA][0][62] = 127, + [2][1][RTW89_CHILE][1][62] = 127, + [2][1][RTW89_QATAR][1][62] = 127, + [2][1][RTW89_QATAR][0][62] = 127, + [2][1][RTW89_UK][1][62] = 127, + [2][1][RTW89_UK][0][62] = 127, + [2][1][RTW89_FCC][1][64] = -16, + [2][1][RTW89_FCC][2][64] = 54, + [2][1][RTW89_ETSI][1][64] = 127, + [2][1][RTW89_ETSI][0][64] = 127, + [2][1][RTW89_MKK][1][64] = 127, + [2][1][RTW89_MKK][0][64] = 127, + [2][1][RTW89_IC][1][64] = -16, + [2][1][RTW89_KCC][1][64] = -14, + [2][1][RTW89_KCC][0][64] = 127, + [2][1][RTW89_ACMA][1][64] = 127, + [2][1][RTW89_ACMA][0][64] = 127, + [2][1][RTW89_CHILE][1][64] = 127, + [2][1][RTW89_QATAR][1][64] = 127, + [2][1][RTW89_QATAR][0][64] = 127, + [2][1][RTW89_UK][1][64] = 127, + [2][1][RTW89_UK][0][64] = 127, + [2][1][RTW89_FCC][1][66] = -16, + [2][1][RTW89_FCC][2][66] = 54, + [2][1][RTW89_ETSI][1][66] = 127, + [2][1][RTW89_ETSI][0][66] = 127, + [2][1][RTW89_MKK][1][66] = 127, + [2][1][RTW89_MKK][0][66] = 127, + [2][1][RTW89_IC][1][66] = -16, + [2][1][RTW89_KCC][1][66] = -14, + [2][1][RTW89_KCC][0][66] = 127, + [2][1][RTW89_ACMA][1][66] = 127, + [2][1][RTW89_ACMA][0][66] = 127, + [2][1][RTW89_CHILE][1][66] = 127, + [2][1][RTW89_QATAR][1][66] = 127, + [2][1][RTW89_QATAR][0][66] = 127, + [2][1][RTW89_UK][1][66] = 127, + [2][1][RTW89_UK][0][66] = 127, + [2][1][RTW89_FCC][1][68] = -16, + [2][1][RTW89_FCC][2][68] = 54, + [2][1][RTW89_ETSI][1][68] = 127, + [2][1][RTW89_ETSI][0][68] = 127, + [2][1][RTW89_MKK][1][68] = 127, + [2][1][RTW89_MKK][0][68] = 127, + [2][1][RTW89_IC][1][68] = -16, + [2][1][RTW89_KCC][1][68] = -14, + [2][1][RTW89_KCC][0][68] = 127, + [2][1][RTW89_ACMA][1][68] = 127, + [2][1][RTW89_ACMA][0][68] = 127, + [2][1][RTW89_CHILE][1][68] = 127, + [2][1][RTW89_QATAR][1][68] = 127, + [2][1][RTW89_QATAR][0][68] = 127, + [2][1][RTW89_UK][1][68] = 127, + [2][1][RTW89_UK][0][68] = 127, + [2][1][RTW89_FCC][1][70] = -16, + [2][1][RTW89_FCC][2][70] = 56, + [2][1][RTW89_ETSI][1][70] = 127, + [2][1][RTW89_ETSI][0][70] = 127, + [2][1][RTW89_MKK][1][70] = 127, + [2][1][RTW89_MKK][0][70] = 127, + [2][1][RTW89_IC][1][70] = -16, + [2][1][RTW89_KCC][1][70] = -14, + [2][1][RTW89_KCC][0][70] = 127, + [2][1][RTW89_ACMA][1][70] = 127, + [2][1][RTW89_ACMA][0][70] = 127, + [2][1][RTW89_CHILE][1][70] = 127, + [2][1][RTW89_QATAR][1][70] = 127, + [2][1][RTW89_QATAR][0][70] = 127, + [2][1][RTW89_UK][1][70] = 127, + [2][1][RTW89_UK][0][70] = 127, + [2][1][RTW89_FCC][1][72] = -16, + [2][1][RTW89_FCC][2][72] = 56, + [2][1][RTW89_ETSI][1][72] = 127, + [2][1][RTW89_ETSI][0][72] = 127, + [2][1][RTW89_MKK][1][72] = 127, + [2][1][RTW89_MKK][0][72] = 127, + [2][1][RTW89_IC][1][72] = -16, + [2][1][RTW89_KCC][1][72] = -14, + [2][1][RTW89_KCC][0][72] = 127, + [2][1][RTW89_ACMA][1][72] = 127, + [2][1][RTW89_ACMA][0][72] = 127, + [2][1][RTW89_CHILE][1][72] = 127, + [2][1][RTW89_QATAR][1][72] = 127, + [2][1][RTW89_QATAR][0][72] = 127, + [2][1][RTW89_UK][1][72] = 127, + [2][1][RTW89_UK][0][72] = 127, + [2][1][RTW89_FCC][1][74] = -16, + [2][1][RTW89_FCC][2][74] = 56, + [2][1][RTW89_ETSI][1][74] = 127, + [2][1][RTW89_ETSI][0][74] = 127, + [2][1][RTW89_MKK][1][74] = 127, + [2][1][RTW89_MKK][0][74] = 127, + [2][1][RTW89_IC][1][74] = -16, + [2][1][RTW89_KCC][1][74] = -14, + [2][1][RTW89_KCC][0][74] = 127, + [2][1][RTW89_ACMA][1][74] = 127, + [2][1][RTW89_ACMA][0][74] = 127, + [2][1][RTW89_CHILE][1][74] = 127, + [2][1][RTW89_QATAR][1][74] = 127, + [2][1][RTW89_QATAR][0][74] = 127, + [2][1][RTW89_UK][1][74] = 127, + [2][1][RTW89_UK][0][74] = 127, + [2][1][RTW89_FCC][1][75] = -16, + [2][1][RTW89_FCC][2][75] = 56, + [2][1][RTW89_ETSI][1][75] = 127, + [2][1][RTW89_ETSI][0][75] = 127, + [2][1][RTW89_MKK][1][75] = 127, + [2][1][RTW89_MKK][0][75] = 127, + [2][1][RTW89_IC][1][75] = -16, + [2][1][RTW89_KCC][1][75] = -14, + [2][1][RTW89_KCC][0][75] = 127, + [2][1][RTW89_ACMA][1][75] = 127, + [2][1][RTW89_ACMA][0][75] = 127, + [2][1][RTW89_CHILE][1][75] = 127, + [2][1][RTW89_QATAR][1][75] = 127, + [2][1][RTW89_QATAR][0][75] = 127, + [2][1][RTW89_UK][1][75] = 127, + [2][1][RTW89_UK][0][75] = 127, + [2][1][RTW89_FCC][1][77] = -16, + [2][1][RTW89_FCC][2][77] = 56, + [2][1][RTW89_ETSI][1][77] = 127, + [2][1][RTW89_ETSI][0][77] = 127, + [2][1][RTW89_MKK][1][77] = 127, + [2][1][RTW89_MKK][0][77] = 127, + [2][1][RTW89_IC][1][77] = -16, + [2][1][RTW89_KCC][1][77] = -14, + [2][1][RTW89_KCC][0][77] = 127, + [2][1][RTW89_ACMA][1][77] = 127, + [2][1][RTW89_ACMA][0][77] = 127, + [2][1][RTW89_CHILE][1][77] = 127, + [2][1][RTW89_QATAR][1][77] = 127, + [2][1][RTW89_QATAR][0][77] = 127, + [2][1][RTW89_UK][1][77] = 127, + [2][1][RTW89_UK][0][77] = 127, + [2][1][RTW89_FCC][1][79] = -16, + [2][1][RTW89_FCC][2][79] = 56, + [2][1][RTW89_ETSI][1][79] = 127, + [2][1][RTW89_ETSI][0][79] = 127, + [2][1][RTW89_MKK][1][79] = 127, + [2][1][RTW89_MKK][0][79] = 127, + [2][1][RTW89_IC][1][79] = -16, + [2][1][RTW89_KCC][1][79] = -14, + [2][1][RTW89_KCC][0][79] = 127, + [2][1][RTW89_ACMA][1][79] = 127, + [2][1][RTW89_ACMA][0][79] = 127, + [2][1][RTW89_CHILE][1][79] = 127, + [2][1][RTW89_QATAR][1][79] = 127, + [2][1][RTW89_QATAR][0][79] = 127, + [2][1][RTW89_UK][1][79] = 127, + [2][1][RTW89_UK][0][79] = 127, + [2][1][RTW89_FCC][1][81] = -16, + [2][1][RTW89_FCC][2][81] = 56, + [2][1][RTW89_ETSI][1][81] = 127, + [2][1][RTW89_ETSI][0][81] = 127, + [2][1][RTW89_MKK][1][81] = 127, + [2][1][RTW89_MKK][0][81] = 127, + [2][1][RTW89_IC][1][81] = -16, + [2][1][RTW89_KCC][1][81] = -14, + [2][1][RTW89_KCC][0][81] = 127, + [2][1][RTW89_ACMA][1][81] = 127, + [2][1][RTW89_ACMA][0][81] = 127, + [2][1][RTW89_CHILE][1][81] = 127, + [2][1][RTW89_QATAR][1][81] = 127, + [2][1][RTW89_QATAR][0][81] = 127, + [2][1][RTW89_UK][1][81] = 127, + [2][1][RTW89_UK][0][81] = 127, + [2][1][RTW89_FCC][1][83] = -16, + [2][1][RTW89_FCC][2][83] = 56, + [2][1][RTW89_ETSI][1][83] = 127, + [2][1][RTW89_ETSI][0][83] = 127, + [2][1][RTW89_MKK][1][83] = 127, + [2][1][RTW89_MKK][0][83] = 127, + [2][1][RTW89_IC][1][83] = -16, + [2][1][RTW89_KCC][1][83] = -14, + [2][1][RTW89_KCC][0][83] = 127, + [2][1][RTW89_ACMA][1][83] = 127, + [2][1][RTW89_ACMA][0][83] = 127, + [2][1][RTW89_CHILE][1][83] = 127, + [2][1][RTW89_QATAR][1][83] = 127, + [2][1][RTW89_QATAR][0][83] = 127, + [2][1][RTW89_UK][1][83] = 127, + [2][1][RTW89_UK][0][83] = 127, + [2][1][RTW89_FCC][1][85] = -18, + [2][1][RTW89_FCC][2][85] = 56, + [2][1][RTW89_ETSI][1][85] = 127, + [2][1][RTW89_ETSI][0][85] = 127, + [2][1][RTW89_MKK][1][85] = 127, + [2][1][RTW89_MKK][0][85] = 127, + [2][1][RTW89_IC][1][85] = -18, + [2][1][RTW89_KCC][1][85] = -14, + [2][1][RTW89_KCC][0][85] = 127, + [2][1][RTW89_ACMA][1][85] = 127, + [2][1][RTW89_ACMA][0][85] = 127, + [2][1][RTW89_CHILE][1][85] = 127, + [2][1][RTW89_QATAR][1][85] = 127, + [2][1][RTW89_QATAR][0][85] = 127, + [2][1][RTW89_UK][1][85] = 127, + [2][1][RTW89_UK][0][85] = 127, + [2][1][RTW89_FCC][1][87] = -16, + [2][1][RTW89_FCC][2][87] = 127, + [2][1][RTW89_ETSI][1][87] = 127, + [2][1][RTW89_ETSI][0][87] = 127, + [2][1][RTW89_MKK][1][87] = 127, + [2][1][RTW89_MKK][0][87] = 127, + [2][1][RTW89_IC][1][87] = -16, + [2][1][RTW89_KCC][1][87] = -14, + [2][1][RTW89_KCC][0][87] = 127, + [2][1][RTW89_ACMA][1][87] = 127, + [2][1][RTW89_ACMA][0][87] = 127, + [2][1][RTW89_CHILE][1][87] = 127, + [2][1][RTW89_QATAR][1][87] = 127, + [2][1][RTW89_QATAR][0][87] = 127, + [2][1][RTW89_UK][1][87] = 127, + [2][1][RTW89_UK][0][87] = 127, + [2][1][RTW89_FCC][1][89] = -16, + [2][1][RTW89_FCC][2][89] = 127, + [2][1][RTW89_ETSI][1][89] = 127, + [2][1][RTW89_ETSI][0][89] = 127, + [2][1][RTW89_MKK][1][89] = 127, + [2][1][RTW89_MKK][0][89] = 127, + [2][1][RTW89_IC][1][89] = -16, + [2][1][RTW89_KCC][1][89] = -14, + [2][1][RTW89_KCC][0][89] = 127, + [2][1][RTW89_ACMA][1][89] = 127, + [2][1][RTW89_ACMA][0][89] = 127, + [2][1][RTW89_CHILE][1][89] = 127, + [2][1][RTW89_QATAR][1][89] = 127, + [2][1][RTW89_QATAR][0][89] = 127, + [2][1][RTW89_UK][1][89] = 127, + [2][1][RTW89_UK][0][89] = 127, + [2][1][RTW89_FCC][1][90] = -16, + [2][1][RTW89_FCC][2][90] = 127, + [2][1][RTW89_ETSI][1][90] = 127, + [2][1][RTW89_ETSI][0][90] = 127, + [2][1][RTW89_MKK][1][90] = 127, + [2][1][RTW89_MKK][0][90] = 127, + [2][1][RTW89_IC][1][90] = -16, + [2][1][RTW89_KCC][1][90] = -14, + [2][1][RTW89_KCC][0][90] = 127, + [2][1][RTW89_ACMA][1][90] = 127, + [2][1][RTW89_ACMA][0][90] = 127, + [2][1][RTW89_CHILE][1][90] = 127, + [2][1][RTW89_QATAR][1][90] = 127, + [2][1][RTW89_QATAR][0][90] = 127, + [2][1][RTW89_UK][1][90] = 127, + [2][1][RTW89_UK][0][90] = 127, + [2][1][RTW89_FCC][1][92] = -16, + [2][1][RTW89_FCC][2][92] = 127, + [2][1][RTW89_ETSI][1][92] = 127, + [2][1][RTW89_ETSI][0][92] = 127, + [2][1][RTW89_MKK][1][92] = 127, + [2][1][RTW89_MKK][0][92] = 127, + [2][1][RTW89_IC][1][92] = -16, + [2][1][RTW89_KCC][1][92] = -14, + [2][1][RTW89_KCC][0][92] = 127, + [2][1][RTW89_ACMA][1][92] = 127, + [2][1][RTW89_ACMA][0][92] = 127, + [2][1][RTW89_CHILE][1][92] = 127, + [2][1][RTW89_QATAR][1][92] = 127, + [2][1][RTW89_QATAR][0][92] = 127, + [2][1][RTW89_UK][1][92] = 127, + [2][1][RTW89_UK][0][92] = 127, + [2][1][RTW89_FCC][1][94] = -16, + [2][1][RTW89_FCC][2][94] = 127, + [2][1][RTW89_ETSI][1][94] = 127, + [2][1][RTW89_ETSI][0][94] = 127, + [2][1][RTW89_MKK][1][94] = 127, + [2][1][RTW89_MKK][0][94] = 127, + [2][1][RTW89_IC][1][94] = -16, + [2][1][RTW89_KCC][1][94] = -14, + [2][1][RTW89_KCC][0][94] = 127, + [2][1][RTW89_ACMA][1][94] = 127, + [2][1][RTW89_ACMA][0][94] = 127, + [2][1][RTW89_CHILE][1][94] = 127, + [2][1][RTW89_QATAR][1][94] = 127, + [2][1][RTW89_QATAR][0][94] = 127, + [2][1][RTW89_UK][1][94] = 127, + [2][1][RTW89_UK][0][94] = 127, + [2][1][RTW89_FCC][1][96] = -16, + [2][1][RTW89_FCC][2][96] = 127, + [2][1][RTW89_ETSI][1][96] = 127, + [2][1][RTW89_ETSI][0][96] = 127, + [2][1][RTW89_MKK][1][96] = 127, + [2][1][RTW89_MKK][0][96] = 127, + [2][1][RTW89_IC][1][96] = -16, + [2][1][RTW89_KCC][1][96] = -14, + [2][1][RTW89_KCC][0][96] = 127, + [2][1][RTW89_ACMA][1][96] = 127, + [2][1][RTW89_ACMA][0][96] = 127, + [2][1][RTW89_CHILE][1][96] = 127, + [2][1][RTW89_QATAR][1][96] = 127, + [2][1][RTW89_QATAR][0][96] = 127, + [2][1][RTW89_UK][1][96] = 127, + [2][1][RTW89_UK][0][96] = 127, + [2][1][RTW89_FCC][1][98] = -16, + [2][1][RTW89_FCC][2][98] = 127, + [2][1][RTW89_ETSI][1][98] = 127, + [2][1][RTW89_ETSI][0][98] = 127, + [2][1][RTW89_MKK][1][98] = 127, + [2][1][RTW89_MKK][0][98] = 127, + [2][1][RTW89_IC][1][98] = -16, + [2][1][RTW89_KCC][1][98] = -14, + [2][1][RTW89_KCC][0][98] = 127, + [2][1][RTW89_ACMA][1][98] = 127, + [2][1][RTW89_ACMA][0][98] = 127, + [2][1][RTW89_CHILE][1][98] = 127, + [2][1][RTW89_QATAR][1][98] = 127, + [2][1][RTW89_QATAR][0][98] = 127, + [2][1][RTW89_UK][1][98] = 127, + [2][1][RTW89_UK][0][98] = 127, + [2][1][RTW89_FCC][1][100] = -16, + [2][1][RTW89_FCC][2][100] = 127, + [2][1][RTW89_ETSI][1][100] = 127, + [2][1][RTW89_ETSI][0][100] = 127, + [2][1][RTW89_MKK][1][100] = 127, + [2][1][RTW89_MKK][0][100] = 127, + [2][1][RTW89_IC][1][100] = -16, + [2][1][RTW89_KCC][1][100] = -14, + [2][1][RTW89_KCC][0][100] = 127, + [2][1][RTW89_ACMA][1][100] = 127, + [2][1][RTW89_ACMA][0][100] = 127, + [2][1][RTW89_CHILE][1][100] = 127, + [2][1][RTW89_QATAR][1][100] = 127, + [2][1][RTW89_QATAR][0][100] = 127, + [2][1][RTW89_UK][1][100] = 127, + [2][1][RTW89_UK][0][100] = 127, + [2][1][RTW89_FCC][1][102] = -16, + [2][1][RTW89_FCC][2][102] = 127, + [2][1][RTW89_ETSI][1][102] = 127, + [2][1][RTW89_ETSI][0][102] = 127, + [2][1][RTW89_MKK][1][102] = 127, + [2][1][RTW89_MKK][0][102] = 127, + [2][1][RTW89_IC][1][102] = -16, + [2][1][RTW89_KCC][1][102] = -14, + [2][1][RTW89_KCC][0][102] = 127, + [2][1][RTW89_ACMA][1][102] = 127, + [2][1][RTW89_ACMA][0][102] = 127, + [2][1][RTW89_CHILE][1][102] = 127, + [2][1][RTW89_QATAR][1][102] = 127, + [2][1][RTW89_QATAR][0][102] = 127, + [2][1][RTW89_UK][1][102] = 127, + [2][1][RTW89_UK][0][102] = 127, + [2][1][RTW89_FCC][1][104] = -16, + [2][1][RTW89_FCC][2][104] = 127, + [2][1][RTW89_ETSI][1][104] = 127, + [2][1][RTW89_ETSI][0][104] = 127, + [2][1][RTW89_MKK][1][104] = 127, + [2][1][RTW89_MKK][0][104] = 127, + [2][1][RTW89_IC][1][104] = -16, + [2][1][RTW89_KCC][1][104] = -14, + [2][1][RTW89_KCC][0][104] = 127, + [2][1][RTW89_ACMA][1][104] = 127, + [2][1][RTW89_ACMA][0][104] = 127, + [2][1][RTW89_CHILE][1][104] = 127, + [2][1][RTW89_QATAR][1][104] = 127, + [2][1][RTW89_QATAR][0][104] = 127, + [2][1][RTW89_UK][1][104] = 127, + [2][1][RTW89_UK][0][104] = 127, + [2][1][RTW89_FCC][1][105] = -16, + [2][1][RTW89_FCC][2][105] = 127, + [2][1][RTW89_ETSI][1][105] = 127, + [2][1][RTW89_ETSI][0][105] = 127, + [2][1][RTW89_MKK][1][105] = 127, + [2][1][RTW89_MKK][0][105] = 127, + [2][1][RTW89_IC][1][105] = -16, + [2][1][RTW89_KCC][1][105] = -14, + [2][1][RTW89_KCC][0][105] = 127, + [2][1][RTW89_ACMA][1][105] = 127, + [2][1][RTW89_ACMA][0][105] = 127, + [2][1][RTW89_CHILE][1][105] = 127, + [2][1][RTW89_QATAR][1][105] = 127, + [2][1][RTW89_QATAR][0][105] = 127, + [2][1][RTW89_UK][1][105] = 127, + [2][1][RTW89_UK][0][105] = 127, + [2][1][RTW89_FCC][1][107] = -12, + [2][1][RTW89_FCC][2][107] = 127, + [2][1][RTW89_ETSI][1][107] = 127, + [2][1][RTW89_ETSI][0][107] = 127, + [2][1][RTW89_MKK][1][107] = 127, + [2][1][RTW89_MKK][0][107] = 127, + [2][1][RTW89_IC][1][107] = -12, + [2][1][RTW89_KCC][1][107] = -14, + [2][1][RTW89_KCC][0][107] = 127, + [2][1][RTW89_ACMA][1][107] = 127, + [2][1][RTW89_ACMA][0][107] = 127, + [2][1][RTW89_CHILE][1][107] = 127, + [2][1][RTW89_QATAR][1][107] = 127, + [2][1][RTW89_QATAR][0][107] = 127, + [2][1][RTW89_UK][1][107] = 127, + [2][1][RTW89_UK][0][107] = 127, + [2][1][RTW89_FCC][1][109] = -10, + [2][1][RTW89_FCC][2][109] = 127, + [2][1][RTW89_ETSI][1][109] = 127, + [2][1][RTW89_ETSI][0][109] = 127, + [2][1][RTW89_MKK][1][109] = 127, + [2][1][RTW89_MKK][0][109] = 127, + [2][1][RTW89_IC][1][109] = -10, + [2][1][RTW89_KCC][1][109] = 127, + [2][1][RTW89_KCC][0][109] = 127, + [2][1][RTW89_ACMA][1][109] = 127, + [2][1][RTW89_ACMA][0][109] = 127, + [2][1][RTW89_CHILE][1][109] = 127, + [2][1][RTW89_QATAR][1][109] = 127, + [2][1][RTW89_QATAR][0][109] = 127, + [2][1][RTW89_UK][1][109] = 127, + [2][1][RTW89_UK][0][109] = 127, + [2][1][RTW89_FCC][1][111] = 127, + [2][1][RTW89_FCC][2][111] = 127, + [2][1][RTW89_ETSI][1][111] = 127, + [2][1][RTW89_ETSI][0][111] = 127, + [2][1][RTW89_MKK][1][111] = 127, + [2][1][RTW89_MKK][0][111] = 127, + [2][1][RTW89_IC][1][111] = 127, + [2][1][RTW89_KCC][1][111] = 127, + [2][1][RTW89_KCC][0][111] = 127, + [2][1][RTW89_ACMA][1][111] = 127, + [2][1][RTW89_ACMA][0][111] = 127, + [2][1][RTW89_CHILE][1][111] = 127, + [2][1][RTW89_QATAR][1][111] = 127, + [2][1][RTW89_QATAR][0][111] = 127, + [2][1][RTW89_UK][1][111] = 127, + [2][1][RTW89_UK][0][111] = 127, + [2][1][RTW89_FCC][1][113] = 127, + [2][1][RTW89_FCC][2][113] = 127, + [2][1][RTW89_ETSI][1][113] = 127, + [2][1][RTW89_ETSI][0][113] = 127, + [2][1][RTW89_MKK][1][113] = 127, + [2][1][RTW89_MKK][0][113] = 127, + [2][1][RTW89_IC][1][113] = 127, + [2][1][RTW89_KCC][1][113] = 127, + [2][1][RTW89_KCC][0][113] = 127, + [2][1][RTW89_ACMA][1][113] = 127, + [2][1][RTW89_ACMA][0][113] = 127, + [2][1][RTW89_CHILE][1][113] = 127, + [2][1][RTW89_QATAR][1][113] = 127, + [2][1][RTW89_QATAR][0][113] = 127, + [2][1][RTW89_UK][1][113] = 127, + [2][1][RTW89_UK][0][113] = 127, + [2][1][RTW89_FCC][1][115] = 127, + [2][1][RTW89_FCC][2][115] = 127, + [2][1][RTW89_ETSI][1][115] = 127, + [2][1][RTW89_ETSI][0][115] = 127, + [2][1][RTW89_MKK][1][115] = 127, + [2][1][RTW89_MKK][0][115] = 127, + [2][1][RTW89_IC][1][115] = 127, + [2][1][RTW89_KCC][1][115] = 127, + [2][1][RTW89_KCC][0][115] = 127, + [2][1][RTW89_ACMA][1][115] = 127, + [2][1][RTW89_ACMA][0][115] = 127, + [2][1][RTW89_CHILE][1][115] = 127, + [2][1][RTW89_QATAR][1][115] = 127, + [2][1][RTW89_QATAR][0][115] = 127, + [2][1][RTW89_UK][1][115] = 127, + [2][1][RTW89_UK][0][115] = 127, + [2][1][RTW89_FCC][1][117] = 127, + [2][1][RTW89_FCC][2][117] = 127, + [2][1][RTW89_ETSI][1][117] = 127, + [2][1][RTW89_ETSI][0][117] = 127, + [2][1][RTW89_MKK][1][117] = 127, + [2][1][RTW89_MKK][0][117] = 127, + [2][1][RTW89_IC][1][117] = 127, + [2][1][RTW89_KCC][1][117] = 127, + [2][1][RTW89_KCC][0][117] = 127, + [2][1][RTW89_ACMA][1][117] = 127, + [2][1][RTW89_ACMA][0][117] = 127, + [2][1][RTW89_CHILE][1][117] = 127, + [2][1][RTW89_QATAR][1][117] = 127, + [2][1][RTW89_QATAR][0][117] = 127, + [2][1][RTW89_UK][1][117] = 127, + [2][1][RTW89_UK][0][117] = 127, + [2][1][RTW89_FCC][1][119] = 127, + [2][1][RTW89_FCC][2][119] = 127, + [2][1][RTW89_ETSI][1][119] = 127, + [2][1][RTW89_ETSI][0][119] = 127, + [2][1][RTW89_MKK][1][119] = 127, + [2][1][RTW89_MKK][0][119] = 127, + [2][1][RTW89_IC][1][119] = 127, + [2][1][RTW89_KCC][1][119] = 127, + [2][1][RTW89_KCC][0][119] = 127, + [2][1][RTW89_ACMA][1][119] = 127, + [2][1][RTW89_ACMA][0][119] = 127, + [2][1][RTW89_CHILE][1][119] = 127, + [2][1][RTW89_QATAR][1][119] = 127, + [2][1][RTW89_QATAR][0][119] = 127, + [2][1][RTW89_UK][1][119] = 127, + [2][1][RTW89_UK][0][119] = 127, }; const struct rtw89_phy_table rtw89_8852c_phy_bb_table = { diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852c_table.h b/drivers/net/wireless/realtek/rtw89/rtw8852c_table.h index 6da1849fb1fac74e1bdba624990600fa2d4986ce..3eb0c49951744aa05ddd99c8d6d7ef71c2be0bf1 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852c_table.h +++ b/drivers/net/wireless/realtek/rtw89/rtw8852c_table.h @@ -15,7 +15,7 @@ extern const struct rtw89_phy_table rtw89_8852c_phy_nctl_table; extern const struct rtw89_txpwr_table rtw89_8852c_byr_table; extern const struct rtw89_phy_tssi_dbw_table rtw89_8852c_tssi_dbw_table; extern const struct rtw89_txpwr_track_cfg rtw89_8852c_trk_cfg; -extern const u8 rtw89_8852c_tx_shape[RTW89_BAND_MAX][RTW89_RS_TX_SHAPE_NUM] +extern const u8 rtw89_8852c_tx_shape[RTW89_BAND_NUM][RTW89_RS_TX_SHAPE_NUM] [RTW89_REGD_NUM]; extern const struct rtw89_rfe_parms rtw89_8852c_dflt_parms; diff --git a/drivers/net/wireless/realtek/rtw89/ser.c b/drivers/net/wireless/realtek/rtw89/ser.c index 9e9f6947e7f14874c0dae1192cc41d05b3ab117c..0462ba693f6fdc9a7f1ce40cf09a4afc04dfb7ba 100644 --- a/drivers/net/wireless/realtek/rtw89/ser.c +++ b/drivers/net/wireless/realtek/rtw89/ser.c @@ -20,12 +20,14 @@ enum ser_evt { SER_EV_NONE, SER_EV_STATE_IN, SER_EV_STATE_OUT, + SER_EV_L1_RESET_PREPARE, /* pre-M0 */ SER_EV_L1_RESET, /* M1 */ SER_EV_DO_RECOVERY, /* M3 */ SER_EV_MAC_RESET_DONE, /* M5 */ SER_EV_L2_RESET, SER_EV_L2_RECFG_DONE, SER_EV_L2_RECFG_TIMEOUT, + SER_EV_M1_TIMEOUT, SER_EV_M3_TIMEOUT, SER_EV_FW_M5_TIMEOUT, SER_EV_L0_RESET, @@ -34,6 +36,7 @@ enum ser_evt { enum ser_state { SER_IDLE_ST, + SER_L1_RESET_PRE_ST, SER_RESET_TRX_ST, SER_DO_HCI_ST, SER_L2_RESET_ST, @@ -300,6 +303,7 @@ static void ser_reset_vif(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) rtw89_core_release_bit_map(rtwdev->hw_port, rtwvif->port); rtwvif->net_type = RTW89_NET_TYPE_NO_LINK; rtwvif->trigger = false; + rtwvif->tdls_peer = 0; } static void ser_sta_deinit_cam_iter(void *data, struct ieee80211_sta *sta) @@ -338,6 +342,8 @@ static void ser_reset_mac_binding(struct rtw89_dev *rtwdev) rtw89_core_release_all_bits_map(rtwdev->mac_id_map, RTW89_MAX_MAC_ID_NUM); rtw89_for_each_rtwvif(rtwdev, rtwvif) ser_reset_vif(rtwdev, rtwvif); + + rtwdev->total_sta_assoc = 0; } /* hal function */ @@ -374,6 +380,13 @@ static int hal_stop_dma(struct rtw89_ser *ser) return ret; } +static void hal_send_post_m0_event(struct rtw89_ser *ser) +{ + struct rtw89_dev *rtwdev = container_of(ser, struct rtw89_dev, ser); + + rtw89_mac_set_err_status(rtwdev, MAC_AX_ERR_L1_RESET_START_DMAC); +} + static void hal_send_m2_event(struct rtw89_ser *ser) { struct rtw89_dev *rtwdev = container_of(ser, struct rtw89_dev, ser); @@ -396,8 +409,12 @@ static void ser_idle_st_hdl(struct rtw89_ser *ser, u8 evt) switch (evt) { case SER_EV_STATE_IN: rtw89_hci_recovery_complete(rtwdev); + clear_bit(RTW89_FLAG_SER_HANDLING, rtwdev->flags); clear_bit(RTW89_FLAG_CRASH_SIMULATING, rtwdev->flags); break; + case SER_EV_L1_RESET_PREPARE: + ser_state_goto(ser, SER_L1_RESET_PRE_ST); + break; case SER_EV_L1_RESET: ser_state_goto(ser, SER_RESET_TRX_ST); break; @@ -405,6 +422,7 @@ static void ser_idle_st_hdl(struct rtw89_ser *ser, u8 evt) ser_state_goto(ser, SER_L2_RESET_ST); break; case SER_EV_STATE_OUT: + set_bit(RTW89_FLAG_SER_HANDLING, rtwdev->flags); rtw89_hci_recovery_start(rtwdev); break; default: @@ -412,6 +430,28 @@ static void ser_idle_st_hdl(struct rtw89_ser *ser, u8 evt) } } +static void ser_l1_reset_pre_st_hdl(struct rtw89_ser *ser, u8 evt) +{ + switch (evt) { + case SER_EV_STATE_IN: + ser->prehandle_l1 = true; + hal_send_post_m0_event(ser); + ser_set_alarm(ser, 1000, SER_EV_M1_TIMEOUT); + break; + case SER_EV_L1_RESET: + ser_state_goto(ser, SER_RESET_TRX_ST); + break; + case SER_EV_M1_TIMEOUT: + ser_state_goto(ser, SER_L2_RESET_ST); + break; + case SER_EV_STATE_OUT: + ser_del_alarm(ser); + break; + default: + break; + } +} + static void ser_reset_trx_st_hdl(struct rtw89_ser *ser, u8 evt) { struct rtw89_dev *rtwdev = container_of(ser, struct rtw89_dev, ser); @@ -654,12 +694,14 @@ static const struct event_ent ser_ev_tbl[] = { {SER_EV_NONE, "SER_EV_NONE"}, {SER_EV_STATE_IN, "SER_EV_STATE_IN"}, {SER_EV_STATE_OUT, "SER_EV_STATE_OUT"}, - {SER_EV_L1_RESET, "SER_EV_L1_RESET"}, + {SER_EV_L1_RESET_PREPARE, "SER_EV_L1_RESET_PREPARE pre-m0"}, + {SER_EV_L1_RESET, "SER_EV_L1_RESET m1"}, {SER_EV_DO_RECOVERY, "SER_EV_DO_RECOVERY m3"}, {SER_EV_MAC_RESET_DONE, "SER_EV_MAC_RESET_DONE m5"}, {SER_EV_L2_RESET, "SER_EV_L2_RESET"}, {SER_EV_L2_RECFG_DONE, "SER_EV_L2_RECFG_DONE"}, {SER_EV_L2_RECFG_TIMEOUT, "SER_EV_L2_RECFG_TIMEOUT"}, + {SER_EV_M1_TIMEOUT, "SER_EV_M1_TIMEOUT"}, {SER_EV_M3_TIMEOUT, "SER_EV_M3_TIMEOUT"}, {SER_EV_FW_M5_TIMEOUT, "SER_EV_FW_M5_TIMEOUT"}, {SER_EV_L0_RESET, "SER_EV_L0_RESET"}, @@ -668,6 +710,7 @@ static const struct event_ent ser_ev_tbl[] = { static const struct state_ent ser_st_tbl[] = { {SER_IDLE_ST, "SER_IDLE_ST", ser_idle_st_hdl}, + {SER_L1_RESET_PRE_ST, "SER_L1_RESET_PRE_ST", ser_l1_reset_pre_st_hdl}, {SER_RESET_TRX_ST, "SER_RESET_TRX_ST", ser_reset_trx_st_hdl}, {SER_DO_HCI_ST, "SER_DO_HCI_ST", ser_do_hci_st_hdl}, {SER_L2_RESET_ST, "SER_L2_RESET_ST", ser_l2_reset_st_hdl} @@ -713,6 +756,9 @@ int rtw89_ser_notify(struct rtw89_dev *rtwdev, u32 err) rtw89_info(rtwdev, "SER catches error: 0x%x\n", err); switch (err) { + case MAC_AX_ERR_L1_PREERR_DMAC: /* pre-M0 */ + event = SER_EV_L1_RESET_PREPARE; + break; case MAC_AX_ERR_L1_ERR_DMAC: case MAC_AX_ERR_L0_PROMOTE_TO_L1: event = SER_EV_L1_RESET; /* M1 */ diff --git a/drivers/net/wireless/realtek/rtw89/txrx.h b/drivers/net/wireless/realtek/rtw89/txrx.h index 98eb9607cd2185f0fb0e510d45473fe66e1c3fd6..ec96da36eacc64eb230f8f63f8d56480766d55db 100644 --- a/drivers/net/wireless/realtek/rtw89/txrx.h +++ b/drivers/net/wireless/realtek/rtw89/txrx.h @@ -186,124 +186,64 @@ #define AX_RXD_BIP_KEYID BIT(27) #define AX_RXD_BIP_ENC BIT(28) -/* RX DESC helpers */ -/* Short Descriptor */ -#define RTW89_GET_RXWD_LONG_RXD(rxdesc) \ - le32_get_bits((rxdesc)->dword0, BIT(31)) -#define RTW89_GET_RXWD_DRV_INFO_SIZE(rxdesc) \ - le32_get_bits((rxdesc)->dword0, GENMASK(30, 28)) -#define RTW89_GET_RXWD_RPKT_TYPE(rxdesc) \ - le32_get_bits((rxdesc)->dword0, GENMASK(27, 24)) -#define RTW89_GET_RXWD_MAC_INFO_VALID(rxdesc) \ - le32_get_bits((rxdesc)->dword0, BIT(23)) -#define RTW89_GET_RXWD_BB_SEL(rxdesc) \ - le32_get_bits((rxdesc)->dword0, BIT(22)) -#define RTW89_GET_RXWD_HD_IV_LEN(rxdesc) \ - le32_get_bits((rxdesc)->dword0, GENMASK(21, 16)) -#define RTW89_GET_RXWD_SHIFT(rxdesc) \ - le32_get_bits((rxdesc)->dword0, GENMASK(15, 14)) -#define RTW89_GET_RXWD_PKT_SIZE(rxdesc) \ - le32_get_bits((rxdesc)->dword0, GENMASK(13, 0)) -#define RTW89_GET_RXWD_BW(rxdesc) \ - le32_get_bits((rxdesc)->dword1, GENMASK(31, 30)) -#define RTW89_GET_RXWD_BW_V1(rxdesc) \ - le32_get_bits((rxdesc)->dword1, GENMASK(31, 29)) -#define RTW89_GET_RXWD_GI_LTF(rxdesc) \ - le32_get_bits((rxdesc)->dword1, GENMASK(27, 25)) -#define RTW89_GET_RXWD_DATA_RATE(rxdesc) \ - le32_get_bits((rxdesc)->dword1, GENMASK(24, 16)) -#define RTW89_GET_RXWD_USER_ID(rxdesc) \ - le32_get_bits((rxdesc)->dword1, GENMASK(15, 8)) -#define RTW89_GET_RXWD_SR_EN(rxdesc) \ - le32_get_bits((rxdesc)->dword1, BIT(7)) -#define RTW89_GET_RXWD_PPDU_CNT(rxdesc) \ - le32_get_bits((rxdesc)->dword1, GENMASK(6, 4)) -#define RTW89_GET_RXWD_PPDU_TYPE(rxdesc) \ - le32_get_bits((rxdesc)->dword1, GENMASK(3, 0)) -#define RTW89_GET_RXWD_FREE_RUN_CNT(rxdesc) \ - le32_get_bits((rxdesc)->dword2, GENMASK(31, 0)) -#define RTW89_GET_RXWD_ICV_ERR(rxdesc) \ - le32_get_bits((rxdesc)->dword3, BIT(10)) -#define RTW89_GET_RXWD_CRC32_ERR(rxdesc) \ - le32_get_bits((rxdesc)->dword3, BIT(9)) -#define RTW89_GET_RXWD_HW_DEC(rxdesc) \ - le32_get_bits((rxdesc)->dword3, BIT(2)) -#define RTW89_GET_RXWD_SW_DEC(rxdesc) \ - le32_get_bits((rxdesc)->dword3, BIT(1)) -#define RTW89_GET_RXWD_A1_MATCH(rxdesc) \ - le32_get_bits((rxdesc)->dword3, BIT(0)) - -/* Long Descriptor */ -#define RTW89_GET_RXWD_FRAG(rxdesc) \ - le32_get_bits((rxdesc)->dword4, GENMASK(31, 28)) -#define RTW89_GET_RXWD_SEQ(rxdesc) \ - le32_get_bits((rxdesc)->dword4, GENMASK(27, 16)) -#define RTW89_GET_RXWD_TYPE(rxdesc) \ - le32_get_bits((rxdesc)->dword4, GENMASK(1, 0)) -#define RTW89_GET_RXWD_ADDR_CAM_VLD(rxdesc) \ - le32_get_bits((rxdesc)->dword5, BIT(28)) -#define RTW89_GET_RXWD_RX_PL_ID(rxdesc) \ - le32_get_bits((rxdesc)->dword5, GENMASK(27, 24)) -#define RTW89_GET_RXWD_MAC_ID(rxdesc) \ - le32_get_bits((rxdesc)->dword5, GENMASK(23, 16)) -#define RTW89_GET_RXWD_ADDR_CAM_ID(rxdesc) \ - le32_get_bits((rxdesc)->dword5, GENMASK(15, 8)) -#define RTW89_GET_RXWD_SEC_CAM_ID(rxdesc) \ - le32_get_bits((rxdesc)->dword5, GENMASK(7, 0)) - -#define RTW89_GET_RXINFO_USR_NUM(rpt) \ - le32_get_bits(*((const __le32 *)rpt), GENMASK(3, 0)) -#define RTW89_GET_RXINFO_FW_DEFINE(rpt) \ - le32_get_bits(*((const __le32 *)rpt), GENMASK(15, 8)) -#define RTW89_GET_RXINFO_LSIG_LEN(rpt) \ - le32_get_bits(*((const __le32 *)rpt), GENMASK(27, 16)) -#define RTW89_GET_RXINFO_IS_TO_SELF(rpt) \ - le32_get_bits(*((const __le32 *)rpt), BIT(28)) -#define RTW89_GET_RXINFO_RX_CNT_VLD(rpt) \ - le32_get_bits(*((const __le32 *)rpt), BIT(29)) -#define RTW89_GET_RXINFO_LONG_RXD(rpt) \ - le32_get_bits(*((const __le32 *)rpt), GENMASK(31, 30)) -#define RTW89_GET_RXINFO_SERVICE(rpt) \ - le32_get_bits(*((const __le32 *)(rpt) + 1), GENMASK(15, 0)) -#define RTW89_GET_RXINFO_PLCP_LEN(rpt) \ - le32_get_bits(*((const __le32 *)(rpt) + 1), GENMASK(23, 16)) -#define RTW89_GET_RXINFO_MAC_ID_VALID(rpt, usr) \ - le32_get_bits(*((const __le32 *)(rpt) + (usr) + 2), BIT(0)) -#define RTW89_GET_RXINFO_DATA(rpt, usr) \ - le32_get_bits(*((const __le32 *)(rpt) + (usr) + 2), BIT(1)) -#define RTW89_GET_RXINFO_CTRL(rpt, usr) \ - le32_get_bits(*((const __le32 *)(rpt) + (usr) + 2), BIT(2)) -#define RTW89_GET_RXINFO_MGMT(rpt, usr) \ - le32_get_bits(*((const __le32 *)(rpt) + (usr) + 2), BIT(3)) -#define RTW89_GET_RXINFO_BCM(rpt, usr) \ - le32_get_bits(*((const __le32 *)(rpt) + (usr) + 2), BIT(4)) -#define RTW89_GET_RXINFO_MACID(rpt, usr) \ - le32_get_bits(*((const __le32 *)(rpt) + (usr) + 2), GENMASK(15, 8)) - -#define RTW89_GET_PHY_STS_IE_MAP(sts) \ - le32_get_bits(*((const __le32 *)(sts)), GENMASK(4, 0)) -#define RTW89_GET_PHY_STS_RSSI_A(sts) \ - le32_get_bits(*((const __le32 *)(sts) + 1), GENMASK(7, 0)) -#define RTW89_GET_PHY_STS_RSSI_B(sts) \ - le32_get_bits(*((const __le32 *)(sts) + 1), GENMASK(15, 8)) -#define RTW89_GET_PHY_STS_RSSI_C(sts) \ - le32_get_bits(*((const __le32 *)(sts) + 1), GENMASK(23, 16)) -#define RTW89_GET_PHY_STS_RSSI_D(sts) \ - le32_get_bits(*((const __le32 *)(sts) + 1), GENMASK(31, 24)) -#define RTW89_GET_PHY_STS_LEN(sts) \ - le32_get_bits(*((const __le32 *)sts), GENMASK(15, 8)) -#define RTW89_GET_PHY_STS_RSSI_AVG(sts) \ - le32_get_bits(*((const __le32 *)sts), GENMASK(31, 24)) -#define RTW89_GET_PHY_STS_IE_TYPE(ie) \ - le32_get_bits(*((const __le32 *)ie), GENMASK(4, 0)) -#define RTW89_GET_PHY_STS_IE_LEN(ie) \ - le32_get_bits(*((const __le32 *)ie), GENMASK(11, 5)) -#define RTW89_GET_PHY_STS_IE01_CH_IDX(ie) \ - le32_get_bits(*((const __le32 *)ie), GENMASK(23, 16)) -#define RTW89_GET_PHY_STS_IE01_FD_CFO(ie) \ - le32_get_bits(*((const __le32 *)(ie) + 1), GENMASK(19, 8)) -#define RTW89_GET_PHY_STS_IE01_PREMB_CFO(ie) \ - le32_get_bits(*((const __le32 *)(ie) + 1), GENMASK(31, 20)) +struct rtw89_rxinfo_user { + __le32 w0; +}; + +#define RTW89_RXINFO_USER_MAC_ID_VALID BIT(0) +#define RTW89_RXINFO_USER_DATA BIT(1) +#define RTW89_RXINFO_USER_CTRL BIT(2) +#define RTW89_RXINFO_USER_MGMT BIT(3) +#define RTW89_RXINFO_USER_BCM BIT(4) +#define RTW89_RXINFO_USER_MACID GENMASK(15, 8) + +struct rtw89_rxinfo { + __le32 w0; + __le32 w1; + struct rtw89_rxinfo_user user[]; +} __packed; + +#define RTW89_RXINFO_W0_USR_NUM GENMASK(3, 0) +#define RTW89_RXINFO_W0_FW_DEFINE GENMASK(15, 8) +#define RTW89_RXINFO_W0_LSIG_LEN GENMASK(27, 16) +#define RTW89_RXINFO_W0_IS_TO_SELF BIT(28) +#define RTW89_RXINFO_W0_RX_CNT_VLD BIT(29) +#define RTW89_RXINFO_W0_LONG_RXD GENMASK(31, 30) +#define RTW89_RXINFO_W1_SERVICE GENMASK(15, 0) +#define RTW89_RXINFO_W1_PLCP_LEN GENMASK(23, 16) + +struct rtw89_phy_sts_hdr { + __le32 w0; + __le32 w1; +} __packed; + +#define RTW89_PHY_STS_HDR_W0_IE_MAP GENMASK(4, 0) +#define RTW89_PHY_STS_HDR_W0_LEN GENMASK(15, 8) +#define RTW89_PHY_STS_HDR_W0_RSSI_AVG GENMASK(31, 24) +#define RTW89_PHY_STS_HDR_W1_RSSI_A GENMASK(7, 0) +#define RTW89_PHY_STS_HDR_W1_RSSI_B GENMASK(15, 8) +#define RTW89_PHY_STS_HDR_W1_RSSI_C GENMASK(23, 16) +#define RTW89_PHY_STS_HDR_W1_RSSI_D GENMASK(31, 24) + +struct rtw89_phy_sts_iehdr { + __le32 w0; +}; + +#define RTW89_PHY_STS_IEHDR_TYPE GENMASK(4, 0) +#define RTW89_PHY_STS_IEHDR_LEN GENMASK(11, 5) + +struct rtw89_phy_sts_ie0 { + __le32 w0; + __le32 w1; + __le32 w2; +} __packed; + +#define RTW89_PHY_STS_IE01_W0_CH_IDX GENMASK(23, 16) +#define RTW89_PHY_STS_IE01_W1_FD_CFO GENMASK(19, 8) +#define RTW89_PHY_STS_IE01_W1_PREMB_CFO GENMASK(31, 20) +#define RTW89_PHY_STS_IE01_W2_AVG_SNR GENMASK(5, 0) +#define RTW89_PHY_STS_IE01_W2_EVM_MAX GENMASK(15, 8) +#define RTW89_PHY_STS_IE01_W2_EVM_MIN GENMASK(23, 16) enum rtw89_tx_channel { RTW89_TXCH_ACH0 = 0, diff --git a/drivers/net/wireless/realtek/rtw89/wow.c b/drivers/net/wireless/realtek/rtw89/wow.c index 2ca8abb70f1109df523c39227a154d24ded21a39..364e546221500e2d526b7e6c4c319d1b4b9126e0 100644 --- a/drivers/net/wireless/realtek/rtw89/wow.c +++ b/drivers/net/wireless/realtek/rtw89/wow.c @@ -91,7 +91,7 @@ static void rtw89_wow_show_wakeup_reason(struct rtw89_dev *rtwdev) u32 wow_reason_reg; u8 reason; - if (chip_id == RTL8852A || chip_id == RTL8852B) + if (chip_id == RTL8852A || chip_id == RTL8852B || chip_id == RTL8851B) wow_reason_reg = R_AX_C2HREG_DATA3 + 3; else wow_reason_reg = R_AX_C2HREG_DATA3_V1 + 3; diff --git a/drivers/net/wireless/rsi/rsi_91x_sdio.c b/drivers/net/wireless/rsi/rsi_91x_sdio.c index d09998796ac08bca4255f3f14c8503e9fd3a26af..1911fef3bbad6357060060b0bc5ad4b2417abf89 100644 --- a/drivers/net/wireless/rsi/rsi_91x_sdio.c +++ b/drivers/net/wireless/rsi/rsi_91x_sdio.c @@ -1463,10 +1463,8 @@ static void rsi_shutdown(struct device *dev) rsi_dbg(ERR_ZONE, "SDIO Bus shutdown =====>\n"); - if (hw) { - struct cfg80211_wowlan *wowlan = hw->wiphy->wowlan_config; - - if (rsi_config_wowlan(adapter, wowlan)) + if (hw && hw->wiphy && hw->wiphy->wowlan_config) { + if (rsi_config_wowlan(adapter, hw->wiphy->wowlan_config)) rsi_dbg(ERR_ZONE, "Failed to configure WoWLAN\n"); } @@ -1481,9 +1479,6 @@ static void rsi_shutdown(struct device *dev) if (sdev->write_fail) rsi_dbg(INFO_ZONE, "###### Device is not ready #######\n"); - if (rsi_set_sdio_pm_caps(adapter)) - rsi_dbg(INFO_ZONE, "Setting power management caps failed\n"); - rsi_dbg(INFO_ZONE, "***** RSI module shut down *****\n"); } diff --git a/drivers/net/wireless/virtual/mac80211_hwsim.c b/drivers/net/wireless/virtual/mac80211_hwsim.c index 89c7a1420381d369930cf7e6907d08740638290f..f446fd0e8cd0dd0ca4c4061b69d54b96e68f5a72 100644 --- a/drivers/net/wireless/virtual/mac80211_hwsim.c +++ b/drivers/net/wireless/virtual/mac80211_hwsim.c @@ -4,7 +4,7 @@ * Copyright (c) 2008, Jouni Malinen * Copyright (c) 2011, Javier Lopez * Copyright (c) 2016 - 2017 Intel Deutschland GmbH - * Copyright (C) 2018 - 2022 Intel Corporation + * Copyright (C) 2018 - 2023 Intel Corporation */ /* @@ -582,8 +582,9 @@ static int mac80211_hwsim_vendor_cmd_test(struct wiphy *wiphy, */ /* Add vendor data */ - nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_TEST, val + 1); - + err = nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_TEST, val + 1); + if (err) + return err; /* Send the event - this will call nla_nest_end() */ cfg80211_vendor_event(skb, GFP_KERNEL); } @@ -1859,12 +1860,12 @@ mac80211_hwsim_select_tx_link(struct mac80211_hwsim_data *data, struct hwsim_sta_priv *sp = (void *)sta->drv_priv; int i; - if (!vif->valid_links) + if (!ieee80211_vif_is_mld(vif)) return &vif->bss_conf; WARN_ON(is_multicast_ether_addr(hdr->addr1)); - if (WARN_ON_ONCE(!sta->valid_links)) + if (WARN_ON_ONCE(!sta || !sta->valid_links)) return &vif->bss_conf; for (i = 0; i < ARRAY_SIZE(vif->link_conf); i++) { @@ -1940,7 +1941,14 @@ static void mac80211_hwsim_tx(struct ieee80211_hw *hw, hdr, &link_sta); } - if (WARN_ON(!bss_conf)) { + if (unlikely(!bss_conf)) { + /* if it's an MLO STA, it might have deactivated all + * links temporarily - but we don't handle real PS in + * this code yet, so just drop the frame in that case + */ + WARN(link != IEEE80211_LINK_UNSPECIFIED || !sta || !sta->mlo, + "link:%d, sta:%pM, sta->mlo:%d\n", + link, sta ? sta->addr : NULL, sta ? sta->mlo : -1); ieee80211_free_txskb(hw, skb); return; } @@ -2628,7 +2636,8 @@ static int mac80211_hwsim_sta_state(struct ieee80211_hw *hw, */ if (vif->type == NL80211_IFTYPE_STATION && new_state == IEEE80211_STA_AUTHORIZED && !sta->tdls) - ieee80211_set_active_links_async(vif, vif->valid_links); + ieee80211_set_active_links_async(vif, + ieee80211_vif_usable_links(vif)); return 0; } diff --git a/drivers/net/wwan/iosm/iosm_ipc_imem.c b/drivers/net/wwan/iosm/iosm_ipc_imem.c index 829515a601b379d3acb57927b67076a35ebf16c9..635301d677e1869ee6c1cd70daf7fc2d7662ff58 100644 --- a/drivers/net/wwan/iosm/iosm_ipc_imem.c +++ b/drivers/net/wwan/iosm/iosm_ipc_imem.c @@ -4,6 +4,7 @@ */ #include +#include #include "iosm_ipc_chnl_cfg.h" #include "iosm_ipc_devlink.h" @@ -631,6 +632,11 @@ static void ipc_imem_run_state_worker(struct work_struct *instance) /* Complete all memory stores after setting bit */ smp_mb__after_atomic(); + if (ipc_imem->pcie->pci->device == INTEL_CP_DEVICE_7560_ID) { + pm_runtime_mark_last_busy(ipc_imem->dev); + pm_runtime_put_autosuspend(ipc_imem->dev); + } + return; err_ipc_mux_deinit: @@ -1234,6 +1240,7 @@ void ipc_imem_cleanup(struct iosm_imem *ipc_imem) /* forward MDM_NOT_READY to listeners */ ipc_uevent_send(ipc_imem->dev, UEVENT_MDM_NOT_READY); + pm_runtime_get_sync(ipc_imem->dev); hrtimer_cancel(&ipc_imem->td_alloc_timer); hrtimer_cancel(&ipc_imem->tdupdate_timer); @@ -1419,6 +1426,16 @@ struct iosm_imem *ipc_imem_init(struct iosm_pcie *pcie, unsigned int device_id, set_bit(IOSM_DEVLINK_INIT, &ipc_imem->flag); } + + if (!pm_runtime_enabled(ipc_imem->dev)) + pm_runtime_enable(ipc_imem->dev); + + pm_runtime_set_autosuspend_delay(ipc_imem->dev, + IPC_MEM_AUTO_SUSPEND_DELAY_MS); + pm_runtime_use_autosuspend(ipc_imem->dev); + pm_runtime_allow(ipc_imem->dev); + pm_runtime_mark_last_busy(ipc_imem->dev); + return ipc_imem; devlink_channel_fail: ipc_devlink_deinit(ipc_imem->ipc_devlink); diff --git a/drivers/net/wwan/iosm/iosm_ipc_imem.h b/drivers/net/wwan/iosm/iosm_ipc_imem.h index e700dc8bfe0a905c562bf6ac7487677286e34d7c..0144b45e2afb39a7971ccfa5ecadf9a4ff396a8a 100644 --- a/drivers/net/wwan/iosm/iosm_ipc_imem.h +++ b/drivers/net/wwan/iosm/iosm_ipc_imem.h @@ -103,6 +103,8 @@ struct ipc_chnl_cfg; #define FULLY_FUNCTIONAL 0 #define IOSM_DEVLINK_INIT 1 +#define IPC_MEM_AUTO_SUSPEND_DELAY_MS 5000 + /* List of the supported UL/DL pipes. */ enum ipc_mem_pipes { IPC_MEM_PIPE_0 = 0, @@ -140,17 +142,6 @@ enum ipc_channel_state { IMEM_CHANNEL_CLOSING, }; -/* Time Unit */ -enum ipc_time_unit { - IPC_SEC = 0, - IPC_MILLI_SEC = 1, - IPC_MICRO_SEC = 2, - IPC_NANO_SEC = 3, - IPC_PICO_SEC = 4, - IPC_FEMTO_SEC = 5, - IPC_ATTO_SEC = 6, -}; - /** * enum ipc_ctype - Enum defining supported channel type needed for control * /IP traffic. @@ -204,7 +195,6 @@ enum ipc_hp_identifier { * @pipe_nr: Pipe identification number * @irq: Interrupt vector * @dir: Direction of data stream in pipe - * @td_tag: Unique tag of the buffer queued * @buf_size: Buffer size (in bytes) for preallocated * buffers (for DL pipes) * @nr_of_queued_entries: Aueued number of entries @@ -224,7 +214,6 @@ struct ipc_pipe { u32 pipe_nr; u32 irq; enum ipc_mem_pipe_dir dir; - u32 td_tag; u32 buf_size; u16 nr_of_queued_entries; u8 is_open:1; diff --git a/drivers/net/wwan/iosm/iosm_ipc_mux.h b/drivers/net/wwan/iosm/iosm_ipc_mux.h index 9968bb885c1f3d7333bb320de2013fa123dbce89..17ca8d1f93973fafb6b73c339b96c59eb3d4e095 100644 --- a/drivers/net/wwan/iosm/iosm_ipc_mux.h +++ b/drivers/net/wwan/iosm/iosm_ipc_mux.h @@ -333,9 +333,7 @@ struct mux_acb { * @wwan_q_offset: This will hold the offset of the given instance * Useful while passing or receiving packets from * wwan/imem layer. - * @adb_finish_timer: Timer for forcefully finishing the ADB * @acb_tx_sequence_nr: Sequence number for the ACB header. - * @params: user configurable parameters * @adb_tx_sequence_nr: Sequence number for ADB header * @acc_adb_size: Statistic data for logging * @acc_payload_size: Statistic data for logging @@ -367,9 +365,7 @@ struct iosm_mux { long long ul_data_pend_bytes; struct mux_acb acb; int wwan_q_offset; - struct hrtimer adb_finish_timer; u16 acb_tx_sequence_nr; - struct ipc_params *params; u16 adb_tx_sequence_nr; unsigned long long acc_adb_size; unsigned long long acc_payload_size; diff --git a/drivers/net/wwan/iosm/iosm_ipc_mux_codec.c b/drivers/net/wwan/iosm/iosm_ipc_mux_codec.c index d6b166fc5c0ef5ae86e04ee0f225b583aed0ac7a..bff46f7ca59f3ffa086e2155edcc1990ef214203 100644 --- a/drivers/net/wwan/iosm/iosm_ipc_mux_codec.c +++ b/drivers/net/wwan/iosm/iosm_ipc_mux_codec.c @@ -626,14 +626,12 @@ static void mux_dl_adb_decode(struct iosm_mux *ipc_mux, if (adth->signature != cpu_to_le32(IOSM_AGGR_MUX_SIG_ADTH)) goto adb_decode_err; - if (le16_to_cpu(adth->table_length) < (sizeof(struct mux_adth) - - sizeof(struct mux_adth_dg))) + if (le16_to_cpu(adth->table_length) < sizeof(struct mux_adth)) goto adb_decode_err; /* Calculate the number of datagrams. */ nr_of_dg = (le16_to_cpu(adth->table_length) - - sizeof(struct mux_adth) + - sizeof(struct mux_adth_dg)) / + sizeof(struct mux_adth)) / sizeof(struct mux_adth_dg); /* Is the datagram table empty ? */ @@ -649,7 +647,7 @@ static void mux_dl_adb_decode(struct iosm_mux *ipc_mux, } /* New aggregated datagram table. */ - dg = &adth->dg; + dg = adth->dg; if (mux_dl_process_dg(ipc_mux, adbh, dg, skb, if_id, nr_of_dg) < 0) goto adb_decode_err; @@ -849,7 +847,7 @@ static void ipc_mux_ul_encode_adth(struct iosm_mux *ipc_mux, adth->if_id = i; adth->table_length = cpu_to_le16(adth_dg_size); adth_dg_size -= offsetof(struct mux_adth, dg); - memcpy(&adth->dg, ul_adb->dg[i], adth_dg_size); + memcpy(adth->dg, ul_adb->dg[i], adth_dg_size); ul_adb->if_cnt++; } @@ -1426,14 +1424,13 @@ static int ipc_mux_get_payload_from_adb(struct iosm_mux *ipc_mux, if (adth->signature == cpu_to_le32(IOSM_AGGR_MUX_SIG_ADTH)) { nr_of_dg = (le16_to_cpu(adth->table_length) - - sizeof(struct mux_adth) + - sizeof(struct mux_adth_dg)) / + sizeof(struct mux_adth)) / sizeof(struct mux_adth_dg); if (nr_of_dg <= 0) return payload_size; - dg = &adth->dg; + dg = adth->dg; for (i = 0; i < nr_of_dg; i++, dg++) { if (le32_to_cpu(dg->datagram_index) < diff --git a/drivers/net/wwan/iosm/iosm_ipc_mux_codec.h b/drivers/net/wwan/iosm/iosm_ipc_mux_codec.h index 5d4e3b89542cc42c43f7008cbe4e70feb6b65550..f8df88f816c4cc88bfc61af2093d0b11c5318a07 100644 --- a/drivers/net/wwan/iosm/iosm_ipc_mux_codec.h +++ b/drivers/net/wwan/iosm/iosm_ipc_mux_codec.h @@ -161,7 +161,7 @@ struct mux_adth { u8 opt_ipv4v6; __le32 next_table_index; __le32 reserved2; - struct mux_adth_dg dg; + struct mux_adth_dg dg[]; }; /** diff --git a/drivers/net/wwan/iosm/iosm_ipc_pcie.c b/drivers/net/wwan/iosm/iosm_ipc_pcie.c index 04517bd3325a2abb3871f640aab0666d53467352..3a259c9abefdfaadce0afbac97ab26638aef3dfc 100644 --- a/drivers/net/wwan/iosm/iosm_ipc_pcie.c +++ b/drivers/net/wwan/iosm/iosm_ipc_pcie.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include "iosm_ipc_imem.h" @@ -437,7 +438,8 @@ static int __maybe_unused ipc_pcie_resume_cb(struct device *dev) return 0; } -static SIMPLE_DEV_PM_OPS(iosm_ipc_pm, ipc_pcie_suspend_cb, ipc_pcie_resume_cb); +static DEFINE_RUNTIME_DEV_PM_OPS(iosm_ipc_pm, ipc_pcie_suspend_cb, + ipc_pcie_resume_cb, NULL); static struct pci_driver iosm_ipc_driver = { .name = KBUILD_MODNAME, diff --git a/drivers/net/wwan/iosm/iosm_ipc_port.c b/drivers/net/wwan/iosm/iosm_ipc_port.c index 5d5b4183e14a3a1a50f9f7f9669779e3e8d1dc0d..2ba1ddca3945b2bb62c1f42fdee6f334a2afe35a 100644 --- a/drivers/net/wwan/iosm/iosm_ipc_port.c +++ b/drivers/net/wwan/iosm/iosm_ipc_port.c @@ -3,6 +3,8 @@ * Copyright (C) 2020-21 Intel Corporation. */ +#include + #include "iosm_ipc_chnl_cfg.h" #include "iosm_ipc_imem_ops.h" #include "iosm_ipc_port.h" @@ -13,12 +15,16 @@ static int ipc_port_ctrl_start(struct wwan_port *port) struct iosm_cdev *ipc_port = wwan_port_get_drvdata(port); int ret = 0; + pm_runtime_get_sync(ipc_port->ipc_imem->dev); ipc_port->channel = ipc_imem_sys_port_open(ipc_port->ipc_imem, ipc_port->chl_id, IPC_HP_CDEV_OPEN); if (!ipc_port->channel) ret = -EIO; + pm_runtime_mark_last_busy(ipc_port->ipc_imem->dev); + pm_runtime_put_autosuspend(ipc_port->ipc_imem->dev); + return ret; } @@ -27,15 +33,24 @@ static void ipc_port_ctrl_stop(struct wwan_port *port) { struct iosm_cdev *ipc_port = wwan_port_get_drvdata(port); + pm_runtime_get_sync(ipc_port->ipc_imem->dev); ipc_imem_sys_port_close(ipc_port->ipc_imem, ipc_port->channel); + pm_runtime_mark_last_busy(ipc_port->ipc_imem->dev); + pm_runtime_put_autosuspend(ipc_port->ipc_imem->dev); } /* transfer control data to modem */ static int ipc_port_ctrl_tx(struct wwan_port *port, struct sk_buff *skb) { struct iosm_cdev *ipc_port = wwan_port_get_drvdata(port); + int ret; - return ipc_imem_sys_cdev_write(ipc_port, skb); + pm_runtime_get_sync(ipc_port->ipc_imem->dev); + ret = ipc_imem_sys_cdev_write(ipc_port, skb); + pm_runtime_mark_last_busy(ipc_port->ipc_imem->dev); + pm_runtime_put_autosuspend(ipc_port->ipc_imem->dev); + + return ret; } static const struct wwan_port_ops ipc_wwan_ctrl_ops = { diff --git a/drivers/net/wwan/iosm/iosm_ipc_trace.c b/drivers/net/wwan/iosm/iosm_ipc_trace.c index eeecfa3d10c5abcaaea901280641fb2e39ec7f99..4368373797b69bd92c26b68b2c6eea8ac8e1d4b2 100644 --- a/drivers/net/wwan/iosm/iosm_ipc_trace.c +++ b/drivers/net/wwan/iosm/iosm_ipc_trace.c @@ -3,7 +3,9 @@ * Copyright (C) 2020-2021 Intel Corporation. */ +#include #include + #include "iosm_ipc_trace.h" /* sub buffer size and number of sub buffer */ @@ -97,6 +99,8 @@ static ssize_t ipc_trace_ctrl_file_write(struct file *filp, if (ret) return ret; + pm_runtime_get_sync(ipc_trace->ipc_imem->dev); + mutex_lock(&ipc_trace->trc_mutex); if (val == TRACE_ENABLE && ipc_trace->mode != TRACE_ENABLE) { ipc_trace->channel = ipc_imem_sys_port_open(ipc_trace->ipc_imem, @@ -117,6 +121,10 @@ static ssize_t ipc_trace_ctrl_file_write(struct file *filp, ret = count; unlock: mutex_unlock(&ipc_trace->trc_mutex); + + pm_runtime_mark_last_busy(ipc_trace->ipc_imem->dev); + pm_runtime_put_autosuspend(ipc_trace->ipc_imem->dev); + return ret; } diff --git a/drivers/net/wwan/iosm/iosm_ipc_wwan.c b/drivers/net/wwan/iosm/iosm_ipc_wwan.c index 4c9022a93e01822eedebe18e00e317969c64d936..93d17de08786c209035af9d01cbf484cc9c1662a 100644 --- a/drivers/net/wwan/iosm/iosm_ipc_wwan.c +++ b/drivers/net/wwan/iosm/iosm_ipc_wwan.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -18,8 +19,6 @@ #define IOSM_IP_TYPE_IPV4 0x40 #define IOSM_IP_TYPE_IPV6 0x60 -#define IOSM_IF_ID_PAYLOAD 2 - /** * struct iosm_netdev_priv - netdev WWAN driver specific private data * @ipc_wwan: Pointer to iosm_wwan struct @@ -53,11 +52,13 @@ static int ipc_wwan_link_open(struct net_device *netdev) struct iosm_netdev_priv *priv = wwan_netdev_drvpriv(netdev); struct iosm_wwan *ipc_wwan = priv->ipc_wwan; int if_id = priv->if_id; + int ret = 0; if (if_id < IP_MUX_SESSION_START || if_id >= ARRAY_SIZE(ipc_wwan->sub_netlist)) return -EINVAL; + pm_runtime_get_sync(ipc_wwan->ipc_imem->dev); /* get channel id */ priv->ch_id = ipc_imem_sys_wwan_open(ipc_wwan->ipc_imem, if_id); @@ -65,7 +66,8 @@ static int ipc_wwan_link_open(struct net_device *netdev) dev_err(ipc_wwan->dev, "cannot connect wwan0 & id %d to the IPC mem layer", if_id); - return -ENODEV; + ret = -ENODEV; + goto err_out; } /* enable tx path, DL data may follow */ @@ -74,7 +76,11 @@ static int ipc_wwan_link_open(struct net_device *netdev) dev_dbg(ipc_wwan->dev, "Channel id %d allocated to if_id %d", priv->ch_id, priv->if_id); - return 0; +err_out: + pm_runtime_mark_last_busy(ipc_wwan->ipc_imem->dev); + pm_runtime_put_autosuspend(ipc_wwan->ipc_imem->dev); + + return ret; } /* Bring-down the wwan net link */ @@ -84,9 +90,12 @@ static int ipc_wwan_link_stop(struct net_device *netdev) netif_stop_queue(netdev); + pm_runtime_get_sync(priv->ipc_wwan->ipc_imem->dev); ipc_imem_sys_wwan_close(priv->ipc_wwan->ipc_imem, priv->if_id, priv->ch_id); priv->ch_id = -1; + pm_runtime_mark_last_busy(priv->ipc_wwan->ipc_imem->dev); + pm_runtime_put_autosuspend(priv->ipc_wwan->ipc_imem->dev); return 0; } @@ -108,6 +117,7 @@ static netdev_tx_t ipc_wwan_link_transmit(struct sk_buff *skb, if_id >= ARRAY_SIZE(ipc_wwan->sub_netlist)) return -EINVAL; + pm_runtime_get(ipc_wwan->ipc_imem->dev); /* Send the SKB to device for transmission */ ret = ipc_imem_sys_wwan_transmit(ipc_wwan->ipc_imem, if_id, priv->ch_id, skb); @@ -121,9 +131,14 @@ static netdev_tx_t ipc_wwan_link_transmit(struct sk_buff *skb, ret = NETDEV_TX_BUSY; dev_err(ipc_wwan->dev, "unable to push packets"); } else { + pm_runtime_mark_last_busy(ipc_wwan->ipc_imem->dev); + pm_runtime_put_autosuspend(ipc_wwan->ipc_imem->dev); goto exit; } + pm_runtime_mark_last_busy(ipc_wwan->ipc_imem->dev); + pm_runtime_put_autosuspend(ipc_wwan->ipc_imem->dev); + return ret; exit: diff --git a/drivers/net/wwan/t7xx/t7xx_hif_cldma.c b/drivers/net/wwan/t7xx/t7xx_hif_cldma.c index aec3a18d44bde61c6343d0ed16697a96c2465011..7162bf38a8c906a221fa897f30c10cc497d6f9dc 100644 --- a/drivers/net/wwan/t7xx/t7xx_hif_cldma.c +++ b/drivers/net/wwan/t7xx/t7xx_hif_cldma.c @@ -1293,9 +1293,9 @@ int t7xx_cldma_init(struct cldma_ctrl *md_ctrl) for (i = 0; i < CLDMA_TXQ_NUM; i++) { md_cd_queue_struct_init(&md_ctrl->txq[i], md_ctrl, MTK_TX, i); md_ctrl->txq[i].worker = - alloc_workqueue("md_hif%d_tx%d_worker", - WQ_UNBOUND | WQ_MEM_RECLAIM | (i ? 0 : WQ_HIGHPRI), - 1, md_ctrl->hif_id, i); + alloc_ordered_workqueue("md_hif%d_tx%d_worker", + WQ_MEM_RECLAIM | (i ? 0 : WQ_HIGHPRI), + md_ctrl->hif_id, i); if (!md_ctrl->txq[i].worker) goto err_workqueue; @@ -1306,9 +1306,10 @@ int t7xx_cldma_init(struct cldma_ctrl *md_ctrl) md_cd_queue_struct_init(&md_ctrl->rxq[i], md_ctrl, MTK_RX, i); INIT_WORK(&md_ctrl->rxq[i].cldma_work, t7xx_cldma_rx_done); - md_ctrl->rxq[i].worker = alloc_workqueue("md_hif%d_rx%d_worker", - WQ_UNBOUND | WQ_MEM_RECLAIM, - 1, md_ctrl->hif_id, i); + md_ctrl->rxq[i].worker = + alloc_ordered_workqueue("md_hif%d_rx%d_worker", + WQ_MEM_RECLAIM, + md_ctrl->hif_id, i); if (!md_ctrl->rxq[i].worker) goto err_workqueue; } diff --git a/drivers/net/wwan/t7xx/t7xx_hif_dpmaif_tx.c b/drivers/net/wwan/t7xx/t7xx_hif_dpmaif_tx.c index 46514208d4f9b2f63f1ffddcd293abfeb3398180..8dab025a088a25f3573aa9e92aeb3271bcb32c1c 100644 --- a/drivers/net/wwan/t7xx/t7xx_hif_dpmaif_tx.c +++ b/drivers/net/wwan/t7xx/t7xx_hif_dpmaif_tx.c @@ -618,8 +618,9 @@ int t7xx_dpmaif_txq_init(struct dpmaif_tx_queue *txq) return ret; } - txq->worker = alloc_workqueue("md_dpmaif_tx%d_worker", WQ_UNBOUND | WQ_MEM_RECLAIM | - (txq->index ? 0 : WQ_HIGHPRI), 1, txq->index); + txq->worker = alloc_ordered_workqueue("md_dpmaif_tx%d_worker", + WQ_MEM_RECLAIM | (txq->index ? 0 : WQ_HIGHPRI), + txq->index); if (!txq->worker) return -ENOMEM; diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c index c1501f41e2d825be75cf9b71a38cf1ecc64a2c6c..c8d20cddf65848d36788d44d5449480954e8f085 100644 --- a/drivers/net/xen-netback/netback.c +++ b/drivers/net/xen-netback/netback.c @@ -689,7 +689,7 @@ static void xenvif_fill_frags(struct xenvif_queue *queue, struct sk_buff *skb) prev_pending_idx = pending_idx; txp = &queue->pending_tx_info[pending_idx].req; - page = virt_to_page(idx_to_kaddr(queue, pending_idx)); + page = virt_to_page((void *)idx_to_kaddr(queue, pending_idx)); __skb_fill_page_desc(skb, i, page, txp->offset, txp->size); skb->len += txp->size; skb->data_len += txp->size; @@ -1128,9 +1128,7 @@ static int xenvif_handle_frag_list(struct xenvif_queue *queue, struct sk_buff *s BUG(); offset += len; - __skb_frag_set_page(&frags[i], page); - skb_frag_off_set(&frags[i], 0); - skb_frag_size_set(&frags[i], len); + skb_frag_fill_page_desc(&frags[i], page, 0, len); } /* Release all the original (foreign) frags. */ diff --git a/drivers/nfc/fdp/fdp.c b/drivers/nfc/fdp/fdp.c index f12f903a9dd134bf327744302205dc203ed92f7f..da3e2dce8e70a69ecefac5b6d379d70f941d0ac1 100644 --- a/drivers/nfc/fdp/fdp.c +++ b/drivers/nfc/fdp/fdp.c @@ -762,3 +762,6 @@ EXPORT_SYMBOL(fdp_nci_remove); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("NFC NCI driver for Intel Fields Peak NFC controller"); MODULE_AUTHOR("Robert Dolca "); + +MODULE_FIRMWARE(FDP_OTP_PATCH_NAME); +MODULE_FIRMWARE(FDP_RAM_PATCH_NAME); diff --git a/drivers/nfc/fdp/i2c.c b/drivers/nfc/fdp/i2c.c index 1e0f2297f9c665820aabb2093ebd3c71fc8325aa..c1896a1d978cdcadfbb6699144a50fd08fe934d9 100644 --- a/drivers/nfc/fdp/i2c.c +++ b/drivers/nfc/fdp/i2c.c @@ -359,7 +359,7 @@ static struct i2c_driver fdp_nci_i2c_driver = { .name = FDP_I2C_DRIVER_NAME, .acpi_match_table = fdp_nci_i2c_acpi_match, }, - .probe_new = fdp_nci_i2c_probe, + .probe = fdp_nci_i2c_probe, .remove = fdp_nci_i2c_remove, }; module_i2c_driver(fdp_nci_i2c_driver); diff --git a/drivers/nfc/microread/i2c.c b/drivers/nfc/microread/i2c.c index e72b358a2a1254f88b581cfb1c2c2a16aa9ff918..642df4e0ce24a6697d76e7729fd9683f2907b9db 100644 --- a/drivers/nfc/microread/i2c.c +++ b/drivers/nfc/microread/i2c.c @@ -286,7 +286,7 @@ static struct i2c_driver microread_i2c_driver = { .driver = { .name = MICROREAD_I2C_DRIVER_NAME, }, - .probe_new = microread_i2c_probe, + .probe = microread_i2c_probe, .remove = microread_i2c_remove, .id_table = microread_i2c_id, }; diff --git a/drivers/nfc/nfcmrvl/i2c.c b/drivers/nfc/nfcmrvl/i2c.c index 164e2ab859fd9deba8f422e18d6eac74abf9f94d..74553134c1b1892d67d1439a8c7a29f54885edb7 100644 --- a/drivers/nfc/nfcmrvl/i2c.c +++ b/drivers/nfc/nfcmrvl/i2c.c @@ -258,7 +258,7 @@ static const struct i2c_device_id nfcmrvl_i2c_id_table[] = { MODULE_DEVICE_TABLE(i2c, nfcmrvl_i2c_id_table); static struct i2c_driver nfcmrvl_i2c_driver = { - .probe_new = nfcmrvl_i2c_probe, + .probe = nfcmrvl_i2c_probe, .id_table = nfcmrvl_i2c_id_table, .remove = nfcmrvl_i2c_remove, .driver = { diff --git a/drivers/nfc/nxp-nci/i2c.c b/drivers/nfc/nxp-nci/i2c.c index d4c299be794994c824d01d5b0e8149e1ef070e55..dca25a0c2f33ccbd3ae88a2b4ae1b9ffdffaf72a 100644 --- a/drivers/nfc/nxp-nci/i2c.c +++ b/drivers/nfc/nxp-nci/i2c.c @@ -97,8 +97,8 @@ static int nxp_nci_i2c_fw_read(struct nxp_nci_i2c_phy *phy, struct sk_buff **skb) { struct i2c_client *client = phy->i2c_dev; - u16 header; size_t frame_len; + __be16 header; int r; r = i2c_master_recv(client, (u8 *) &header, NXP_NCI_FW_HDR_LEN); @@ -348,7 +348,7 @@ static struct i2c_driver nxp_nci_i2c_driver = { .acpi_match_table = ACPI_PTR(acpi_id), .of_match_table = of_nxp_nci_i2c_match, }, - .probe_new = nxp_nci_i2c_probe, + .probe = nxp_nci_i2c_probe, .id_table = nxp_nci_i2c_id_table, .remove = nxp_nci_i2c_remove, }; diff --git a/drivers/nfc/pn533/i2c.c b/drivers/nfc/pn533/i2c.c index 1503a98f0405ab8e2a71d3f96ceea9dcaec75f9a..438ab9553f7a185180ec58495aa26d4f958eaff8 100644 --- a/drivers/nfc/pn533/i2c.c +++ b/drivers/nfc/pn533/i2c.c @@ -259,7 +259,7 @@ static struct i2c_driver pn533_i2c_driver = { .name = PN533_I2C_DRIVER_NAME, .of_match_table = of_match_ptr(of_pn533_i2c_match), }, - .probe_new = pn533_i2c_probe, + .probe = pn533_i2c_probe, .id_table = pn533_i2c_id_table, .remove = pn533_i2c_remove, }; diff --git a/drivers/nfc/pn544/i2c.c b/drivers/nfc/pn544/i2c.c index 8b0d910bee06cd7adcd7d0cb1e4f89ced2a1fc5f..3f6d74832bac3b3d059fce0e8a489a35e2bce8da 100644 --- a/drivers/nfc/pn544/i2c.c +++ b/drivers/nfc/pn544/i2c.c @@ -953,7 +953,7 @@ static struct i2c_driver pn544_hci_i2c_driver = { .of_match_table = of_match_ptr(of_pn544_i2c_match), .acpi_match_table = ACPI_PTR(pn544_hci_i2c_acpi_match), }, - .probe_new = pn544_hci_i2c_probe, + .probe = pn544_hci_i2c_probe, .id_table = pn544_hci_i2c_id_table, .remove = pn544_hci_i2c_remove, }; diff --git a/drivers/nfc/s3fwrn5/i2c.c b/drivers/nfc/s3fwrn5/i2c.c index 2517ae71f9a4a94f4c6a753e463bc3f127da3650..720d4a72493c8096d7dea96d19b46e68f9cf5571 100644 --- a/drivers/nfc/s3fwrn5/i2c.c +++ b/drivers/nfc/s3fwrn5/i2c.c @@ -261,7 +261,7 @@ static struct i2c_driver s3fwrn5_i2c_driver = { .name = S3FWRN5_I2C_DRIVER_NAME, .of_match_table = of_match_ptr(of_s3fwrn5_i2c_match), }, - .probe_new = s3fwrn5_i2c_probe, + .probe = s3fwrn5_i2c_probe, .remove = s3fwrn5_i2c_remove, .id_table = s3fwrn5_i2c_id_table, }; diff --git a/drivers/nfc/st-nci/i2c.c b/drivers/nfc/st-nci/i2c.c index 6b5eed8a1fbe133b9f5571139c484fda4f6cad3b..d20a337e90b45631330771640b2ad8610dcd411e 100644 --- a/drivers/nfc/st-nci/i2c.c +++ b/drivers/nfc/st-nci/i2c.c @@ -283,7 +283,7 @@ static struct i2c_driver st_nci_i2c_driver = { .of_match_table = of_match_ptr(of_st_nci_i2c_match), .acpi_match_table = ACPI_PTR(st_nci_i2c_acpi_match), }, - .probe_new = st_nci_i2c_probe, + .probe = st_nci_i2c_probe, .id_table = st_nci_i2c_id_table, .remove = st_nci_i2c_remove, }; diff --git a/drivers/nfc/st21nfca/i2c.c b/drivers/nfc/st21nfca/i2c.c index 55f7a2391bb1abebb910a2a045e64506ae7010f5..064a63db288bdc0bd0b5de2b5dea23d6f84c36fb 100644 --- a/drivers/nfc/st21nfca/i2c.c +++ b/drivers/nfc/st21nfca/i2c.c @@ -597,7 +597,7 @@ static struct i2c_driver st21nfca_hci_i2c_driver = { .of_match_table = of_match_ptr(of_st21nfca_i2c_match), .acpi_match_table = ACPI_PTR(st21nfca_hci_i2c_acpi_match), }, - .probe_new = st21nfca_hci_i2c_probe, + .probe = st21nfca_hci_i2c_probe, .id_table = st21nfca_hci_i2c_id_table, .remove = st21nfca_hci_i2c_remove, }; diff --git a/drivers/ntb/hw/amd/ntb_hw_amd.c b/drivers/ntb/hw/amd/ntb_hw_amd.c index 04550b1f984c628847e2d3bc3a0cafd838c36754..4940b6301d833e5bb655884e90e1208bfb6dfd30 100644 --- a/drivers/ntb/hw/amd/ntb_hw_amd.c +++ b/drivers/ntb/hw/amd/ntb_hw_amd.c @@ -941,7 +941,7 @@ static void ndev_init_debugfs(struct amd_ntb_dev *ndev) ndev->debugfs_dir = debugfs_create_dir(pci_name(ndev->ntb.pdev), debugfs_dir); - if (!ndev->debugfs_dir) + if (IS_ERR(ndev->debugfs_dir)) ndev->debugfs_info = NULL; else ndev->debugfs_info = @@ -1194,7 +1194,6 @@ static int amd_ntb_init_pci(struct amd_ntb_dev *ndev, return 0; err_dma_mask: - pci_clear_master(pdev); pci_release_regions(pdev); err_pci_regions: pci_disable_device(pdev); @@ -1209,7 +1208,6 @@ static void amd_ntb_deinit_pci(struct amd_ntb_dev *ndev) pci_iounmap(pdev, ndev->self_mmio); - pci_clear_master(pdev); pci_release_regions(pdev); pci_disable_device(pdev); pci_set_drvdata(pdev, NULL); @@ -1338,12 +1336,17 @@ static struct pci_driver amd_ntb_pci_driver = { static int __init amd_ntb_pci_driver_init(void) { + int ret; pr_info("%s %s\n", NTB_DESC, NTB_VER); if (debugfs_initialized()) debugfs_dir = debugfs_create_dir(KBUILD_MODNAME, NULL); - return pci_register_driver(&amd_ntb_pci_driver); + ret = pci_register_driver(&amd_ntb_pci_driver); + if (ret) + debugfs_remove_recursive(debugfs_dir); + + return ret; } module_init(amd_ntb_pci_driver_init); diff --git a/drivers/ntb/hw/epf/ntb_hw_epf.c b/drivers/ntb/hw/epf/ntb_hw_epf.c index 3ece49cb18ffa43f13442d555bb090d49829deff..b640aa0bf45e613db7e04093c5b130adeb6bf664 100644 --- a/drivers/ntb/hw/epf/ntb_hw_epf.c +++ b/drivers/ntb/hw/epf/ntb_hw_epf.c @@ -591,7 +591,7 @@ static int ntb_epf_init_pci(struct ntb_epf_dev *ndev, ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32)); if (ret) { dev_err(dev, "Cannot set DMA mask\n"); - goto err_dma_mask; + goto err_pci_regions; } dev_warn(&pdev->dev, "Cannot DMA highmem\n"); } @@ -599,14 +599,14 @@ static int ntb_epf_init_pci(struct ntb_epf_dev *ndev, ndev->ctrl_reg = pci_iomap(pdev, ndev->ctrl_reg_bar, 0); if (!ndev->ctrl_reg) { ret = -EIO; - goto err_dma_mask; + goto err_pci_regions; } if (ndev->peer_spad_reg_bar) { ndev->peer_spad_reg = pci_iomap(pdev, ndev->peer_spad_reg_bar, 0); if (!ndev->peer_spad_reg) { ret = -EIO; - goto err_dma_mask; + goto err_pci_regions; } } else { spad_sz = 4 * readl(ndev->ctrl_reg + NTB_EPF_SPAD_COUNT); @@ -617,14 +617,11 @@ static int ntb_epf_init_pci(struct ntb_epf_dev *ndev, ndev->db_reg = pci_iomap(pdev, ndev->db_reg_bar, 0); if (!ndev->db_reg) { ret = -EIO; - goto err_dma_mask; + goto err_pci_regions; } return 0; -err_dma_mask: - pci_clear_master(pdev); - err_pci_regions: pci_disable_device(pdev); @@ -642,7 +639,6 @@ static void ntb_epf_deinit_pci(struct ntb_epf_dev *ndev) pci_iounmap(pdev, ndev->peer_spad_reg); pci_iounmap(pdev, ndev->db_reg); - pci_clear_master(pdev); pci_release_regions(pdev); pci_disable_device(pdev); pci_set_drvdata(pdev, NULL); diff --git a/drivers/ntb/hw/idt/ntb_hw_idt.c b/drivers/ntb/hw/idt/ntb_hw_idt.c index 0ed6f809ff2eebb41c78a263fa125ad0c2a70db3..48823b53ede3e927988ff36e8f38d158d662201a 100644 --- a/drivers/ntb/hw/idt/ntb_hw_idt.c +++ b/drivers/ntb/hw/idt/ntb_hw_idt.c @@ -2651,20 +2651,18 @@ static int idt_init_pci(struct idt_ntb_dev *ndev) } /* - * Enable the device advanced error reporting. It's not critical to + * The PCI core enables device error reporting. It's not critical to * have AER disabled in the kernel. + * + * Cleanup nonfatal error status before getting to init. */ - ret = pci_enable_pcie_error_reporting(pdev); - if (ret != 0) - dev_warn(&pdev->dev, "PCIe AER capability disabled\n"); - else /* Cleanup nonfatal error status before getting to init */ - pci_aer_clear_nonfatal_status(pdev); + pci_aer_clear_nonfatal_status(pdev); /* First enable the PCI device */ ret = pcim_enable_device(pdev); if (ret != 0) { dev_err(&pdev->dev, "Failed to enable PCIe device\n"); - goto err_disable_aer; + return ret; } /* @@ -2692,8 +2690,6 @@ static int idt_init_pci(struct idt_ntb_dev *ndev) err_clear_master: pci_clear_master(pdev); -err_disable_aer: - (void)pci_disable_pcie_error_reporting(pdev); return ret; } @@ -2714,9 +2710,6 @@ static void idt_deinit_pci(struct idt_ntb_dev *ndev) /* Clear the bus master disabling the Request TLPs translation */ pci_clear_master(pdev); - /* Disable the AER capability */ - (void)pci_disable_pcie_error_reporting(pdev); - dev_dbg(&pdev->dev, "NT-function PCIe interface cleared"); } @@ -2891,6 +2884,7 @@ static struct pci_driver idt_pci_driver = { static int __init idt_pci_driver_init(void) { + int ret; pr_info("%s %s\n", NTB_DESC, NTB_VER); /* Create the top DebugFS directory if the FS is initialized */ @@ -2898,7 +2892,11 @@ static int __init idt_pci_driver_init(void) dbgfs_topdir = debugfs_create_dir(KBUILD_MODNAME, NULL); /* Register the NTB hardware driver to handle the PCI device */ - return pci_register_driver(&idt_pci_driver); + ret = pci_register_driver(&idt_pci_driver); + if (ret) + debugfs_remove_recursive(dbgfs_topdir); + + return ret; } module_init(idt_pci_driver_init); diff --git a/drivers/ntb/hw/intel/ntb_hw_gen1.c b/drivers/ntb/hw/intel/ntb_hw_gen1.c index 84772013812bf5be73bc4b5a929f148429bdc386..9ab836d0d4f12d1f634f0e3a8830deab38fe0df0 100644 --- a/drivers/ntb/hw/intel/ntb_hw_gen1.c +++ b/drivers/ntb/hw/intel/ntb_hw_gen1.c @@ -1791,7 +1791,6 @@ static int intel_ntb_init_pci(struct intel_ntb_dev *ndev, struct pci_dev *pdev) err_mmio: err_dma_mask: - pci_clear_master(pdev); pci_release_regions(pdev); err_pci_regions: pci_disable_device(pdev); @@ -1808,7 +1807,6 @@ static void intel_ntb_deinit_pci(struct intel_ntb_dev *ndev) pci_iounmap(pdev, ndev->peer_mmio); pci_iounmap(pdev, ndev->self_mmio); - pci_clear_master(pdev); pci_release_regions(pdev); pci_disable_device(pdev); pci_set_drvdata(pdev, NULL); @@ -2064,12 +2062,17 @@ static struct pci_driver intel_ntb_pci_driver = { static int __init intel_ntb_pci_driver_init(void) { + int ret; pr_info("%s %s\n", NTB_DESC, NTB_VER); if (debugfs_initialized()) debugfs_dir = debugfs_create_dir(KBUILD_MODNAME, NULL); - return pci_register_driver(&intel_ntb_pci_driver); + ret = pci_register_driver(&intel_ntb_pci_driver); + if (ret) + debugfs_remove_recursive(debugfs_dir); + + return ret; } module_init(intel_ntb_pci_driver_init); diff --git a/drivers/ntb/ntb_transport.c b/drivers/ntb/ntb_transport.c index a9b97ebc71ac5b7b618f18c320250315a7801c35..2abd2235bbcabfc8d6e63281db0b1979c90688fb 100644 --- a/drivers/ntb/ntb_transport.c +++ b/drivers/ntb/ntb_transport.c @@ -410,7 +410,7 @@ int ntb_transport_register_client_dev(char *device_name) rc = device_register(dev); if (rc) { - kfree(client_dev); + put_device(dev); goto err; } diff --git a/drivers/ntb/test/ntb_tool.c b/drivers/ntb/test/ntb_tool.c index 5ee0afa621a9503c34dbcfb32421a990a00abf47..eeeb4b1c97d2c20918ec7ef98bc75ad8bd599c9b 100644 --- a/drivers/ntb/test/ntb_tool.c +++ b/drivers/ntb/test/ntb_tool.c @@ -998,6 +998,8 @@ static int tool_init_mws(struct tool_ctx *tc) tc->peers[pidx].outmws = devm_kcalloc(&tc->ntb->dev, tc->peers[pidx].outmw_cnt, sizeof(*tc->peers[pidx].outmws), GFP_KERNEL); + if (tc->peers[pidx].outmws == NULL) + return -ENOMEM; for (widx = 0; widx < tc->peers[pidx].outmw_cnt; widx++) { tc->peers[pidx].outmws[widx].pidx = pidx; diff --git a/drivers/nubus/nubus.c b/drivers/nubus/nubus.c index f70ba58dbc557b27fd5408c680d330d2c3cd84ff..ab0f32b901c84f52045096a904a5f50996eab30f 100644 --- a/drivers/nubus/nubus.c +++ b/drivers/nubus/nubus.c @@ -32,6 +32,13 @@ /* Globals */ +/* The "nubus.populate_procfs" parameter makes slot resources available in + * procfs. It's deprecated and disabled by default because procfs is no longer + * thought to be suitable for that and some board ROMs make it too expensive. + */ +bool nubus_populate_procfs; +module_param_named(populate_procfs, nubus_populate_procfs, bool, 0); + LIST_HEAD(nubus_func_rsrcs); /* Meaning of "bytelanes": @@ -572,9 +579,9 @@ nubus_get_functional_resource(struct nubus_board *board, int slot, nubus_proc_add_rsrc(dir.procdir, &ent); break; default: - /* Local/Private resources have their own - function */ - nubus_get_private_resource(fres, dir.procdir, &ent); + if (nubus_populate_procfs) + nubus_get_private_resource(fres, dir.procdir, + &ent); } } diff --git a/drivers/nubus/proc.c b/drivers/nubus/proc.c index 1fd667852271fd5495729f3782c97808b92e6fe8..e7a347db708c26a558ab1529deaccdf67a42138a 100644 --- a/drivers/nubus/proc.c +++ b/drivers/nubus/proc.c @@ -55,7 +55,7 @@ struct proc_dir_entry *nubus_proc_add_board(struct nubus_board *board) { char name[2]; - if (!proc_bus_nubus_dir) + if (!proc_bus_nubus_dir || !nubus_populate_procfs) return NULL; snprintf(name, sizeof(name), "%x", board->slot); return proc_mkdir(name, proc_bus_nubus_dir); @@ -72,9 +72,10 @@ struct proc_dir_entry *nubus_proc_add_rsrc_dir(struct proc_dir_entry *procdir, char name[9]; int lanes = board->lanes; - if (!procdir) + if (!procdir || !nubus_populate_procfs) return NULL; snprintf(name, sizeof(name), "%x", ent->type); + remove_proc_subtree(name, procdir); return proc_mkdir_data(name, 0555, procdir, (void *)lanes); } @@ -137,6 +138,18 @@ static int nubus_proc_rsrc_show(struct seq_file *m, void *v) return 0; } +static int nubus_rsrc_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, nubus_proc_rsrc_show, inode); +} + +static const struct proc_ops nubus_rsrc_proc_ops = { + .proc_open = nubus_rsrc_proc_open, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_release = single_release, +}; + void nubus_proc_add_rsrc_mem(struct proc_dir_entry *procdir, const struct nubus_dirent *ent, unsigned int size) @@ -144,7 +157,7 @@ void nubus_proc_add_rsrc_mem(struct proc_dir_entry *procdir, char name[9]; struct nubus_proc_pde_data *pded; - if (!procdir) + if (!procdir || !nubus_populate_procfs) return; snprintf(name, sizeof(name), "%x", ent->type); @@ -152,8 +165,9 @@ void nubus_proc_add_rsrc_mem(struct proc_dir_entry *procdir, pded = nubus_proc_alloc_pde_data(nubus_dirptr(ent), size); else pded = NULL; - proc_create_single_data(name, S_IFREG | 0444, procdir, - nubus_proc_rsrc_show, pded); + remove_proc_subtree(name, procdir); + proc_create_data(name, S_IFREG | 0444, procdir, + &nubus_rsrc_proc_ops, pded); } void nubus_proc_add_rsrc(struct proc_dir_entry *procdir, @@ -162,13 +176,14 @@ void nubus_proc_add_rsrc(struct proc_dir_entry *procdir, char name[9]; unsigned char *data = (unsigned char *)ent->data; - if (!procdir) + if (!procdir || !nubus_populate_procfs) return; snprintf(name, sizeof(name), "%x", ent->type); - proc_create_single_data(name, S_IFREG | 0444, procdir, - nubus_proc_rsrc_show, - nubus_proc_alloc_pde_data(data, 0)); + remove_proc_subtree(name, procdir); + proc_create_data(name, S_IFREG | 0444, procdir, + &nubus_rsrc_proc_ops, + nubus_proc_alloc_pde_data(data, 0)); } /* diff --git a/drivers/nvdimm/bus.c b/drivers/nvdimm/bus.c index 954dbc105fc801a43fd993660a5a3adc5d088d23..5852fe290523b92abd9568b51d08a2f9a6842073 100644 --- a/drivers/nvdimm/bus.c +++ b/drivers/nvdimm/bus.c @@ -25,7 +25,7 @@ int nvdimm_major; static int nvdimm_bus_major; -struct class *nd_class; +static struct class *nd_class; static DEFINE_IDA(nd_ida); static int to_nd_device_type(const struct device *dev) diff --git a/drivers/nvdimm/dimm_devs.c b/drivers/nvdimm/dimm_devs.c index 957f7c3d17ba7f3cea2216b28455b1e5582c92e7..1273873582be7cdbdafc90bc967e1bea3208244a 100644 --- a/drivers/nvdimm/dimm_devs.c +++ b/drivers/nvdimm/dimm_devs.c @@ -349,8 +349,8 @@ static ssize_t available_slots_show(struct device *dev, } static DEVICE_ATTR_RO(available_slots); -ssize_t security_show(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t security_show(struct device *dev, + struct device_attribute *attr, char *buf) { struct nvdimm *nvdimm = to_nvdimm(dev); diff --git a/drivers/nvdimm/pmem.c b/drivers/nvdimm/pmem.c index ceea55f621cc7fdc5d4fbccebe8203bd8384be40..46e094e56159f651ca95dc09c95e4d9d5c88b51e 100644 --- a/drivers/nvdimm/pmem.c +++ b/drivers/nvdimm/pmem.c @@ -260,7 +260,7 @@ __weak long __pmem_direct_access(struct pmem_device *pmem, pgoff_t pgoff, long actual_nr; if (mode != DAX_RECOVERY_WRITE) - return -EIO; + return -EHWPOISON; /* * Set the recovery stride is set to kernel page size because diff --git a/drivers/nvme/host/Makefile b/drivers/nvme/host/Makefile index e27202d22c7d9eb05c509064f0c23656e300ec9d..c7c3cf202d12d8380f61248bd670031cc3b56b9a 100644 --- a/drivers/nvme/host/Makefile +++ b/drivers/nvme/host/Makefile @@ -10,7 +10,7 @@ obj-$(CONFIG_NVME_FC) += nvme-fc.o obj-$(CONFIG_NVME_TCP) += nvme-tcp.o obj-$(CONFIG_NVME_APPLE) += nvme-apple.o -nvme-core-y += core.o ioctl.o +nvme-core-y += core.o ioctl.o sysfs.o pr.o nvme-core-$(CONFIG_NVME_VERBOSE_ERRORS) += constants.o nvme-core-$(CONFIG_TRACING) += trace.o nvme-core-$(CONFIG_NVME_MULTIPATH) += multipath.o diff --git a/drivers/nvme/host/auth.c b/drivers/nvme/host/auth.c index ea16a0aba6799ab74c94bf2223cf01e54a22f332..daf5d144a8eaf79f75feae225af1a57ea586ad81 100644 --- a/drivers/nvme/host/auth.c +++ b/drivers/nvme/host/auth.c @@ -30,18 +30,18 @@ struct nvme_dhchap_queue_context { u32 s2; u16 transaction; u8 status; + u8 dhgroup_id; u8 hash_id; size_t hash_len; - u8 dhgroup_id; u8 c1[64]; u8 c2[64]; u8 response[64]; u8 *host_response; u8 *ctrl_key; - int ctrl_key_len; u8 *host_key; - int host_key_len; u8 *sess_key; + int ctrl_key_len; + int host_key_len; int sess_key_len; }; diff --git a/drivers/nvme/host/constants.c b/drivers/nvme/host/constants.c index 5e4f8848dce08e912d5c4d85b84ae70cf55c14e5..20f46c230885c10f2a82bc87f7091645e2d02db5 100644 --- a/drivers/nvme/host/constants.c +++ b/drivers/nvme/host/constants.c @@ -12,7 +12,7 @@ static const char * const nvme_ops[] = { [nvme_cmd_read] = "Read", [nvme_cmd_write_uncor] = "Write Uncorrectable", [nvme_cmd_compare] = "Compare", - [nvme_cmd_write_zeroes] = "Write Zeros", + [nvme_cmd_write_zeroes] = "Write Zeroes", [nvme_cmd_dsm] = "Dataset Management", [nvme_cmd_verify] = "Verify", [nvme_cmd_resv_register] = "Reservation Register", diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c index 3ec38e2b91732691ae53ac50eb7fc8a45add5465..37b6fa7466620436b2ab23cd00eb0de91309bb30 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c @@ -237,7 +237,7 @@ int nvme_delete_ctrl(struct nvme_ctrl *ctrl) } EXPORT_SYMBOL_GPL(nvme_delete_ctrl); -static void nvme_delete_ctrl_sync(struct nvme_ctrl *ctrl) +void nvme_delete_ctrl_sync(struct nvme_ctrl *ctrl) { /* * Keep a reference until nvme_do_delete_ctrl() complete, @@ -279,7 +279,7 @@ static blk_status_t nvme_error_status(u16 status) case NVME_SC_INVALID_PI: return BLK_STS_PROTECTION; case NVME_SC_RESERVATION_CONFLICT: - return BLK_STS_NEXUS; + return BLK_STS_RESV_CONFLICT; case NVME_SC_HOST_PATH_ERROR: return BLK_STS_TRANSPORT; case NVME_SC_ZONE_TOO_MANY_ACTIVE: @@ -1134,8 +1134,11 @@ void nvme_passthru_end(struct nvme_ctrl *ctrl, struct nvme_ns *ns, u32 effects, mutex_unlock(&ctrl->scan_lock); } if (effects & NVME_CMD_EFFECTS_CCC) { - dev_info(ctrl->device, + if (!test_and_set_bit(NVME_CTRL_DIRTY_CAPABILITY, + &ctrl->flags)) { + dev_info(ctrl->device, "controller capabilities changed, reset may be required to take effect.\n"); + } } if (effects & (NVME_CMD_EFFECTS_NIC | NVME_CMD_EFFECTS_NCC)) { nvme_queue_scan(ctrl); @@ -1635,12 +1638,12 @@ static void nvme_ns_release(struct nvme_ns *ns) nvme_put_ns(ns); } -static int nvme_open(struct block_device *bdev, fmode_t mode) +static int nvme_open(struct gendisk *disk, blk_mode_t mode) { - return nvme_ns_open(bdev->bd_disk->private_data); + return nvme_ns_open(disk->private_data); } -static void nvme_release(struct gendisk *disk, fmode_t mode) +static void nvme_release(struct gendisk *disk) { nvme_ns_release(disk->private_data); } @@ -1879,7 +1882,7 @@ static void nvme_update_disk_info(struct gendisk *disk, struct nvme_ns *ns, struct nvme_id_ns *id) { sector_t capacity = nvme_lba_to_sect(ns, le64_to_cpu(id->nsze)); - unsigned short bs = 1 << ns->lba_shift; + u32 bs = 1U << ns->lba_shift; u32 atomic_bs, phys_bs, io_opt = 0; /* @@ -2105,153 +2108,6 @@ static int nvme_update_ns_info(struct nvme_ns *ns, struct nvme_ns_info *info) } } -static char nvme_pr_type(enum pr_type type) -{ - switch (type) { - case PR_WRITE_EXCLUSIVE: - return 1; - case PR_EXCLUSIVE_ACCESS: - return 2; - case PR_WRITE_EXCLUSIVE_REG_ONLY: - return 3; - case PR_EXCLUSIVE_ACCESS_REG_ONLY: - return 4; - case PR_WRITE_EXCLUSIVE_ALL_REGS: - return 5; - case PR_EXCLUSIVE_ACCESS_ALL_REGS: - return 6; - default: - return 0; - } -} - -static int nvme_send_ns_head_pr_command(struct block_device *bdev, - struct nvme_command *c, u8 data[16]) -{ - struct nvme_ns_head *head = bdev->bd_disk->private_data; - int srcu_idx = srcu_read_lock(&head->srcu); - struct nvme_ns *ns = nvme_find_path(head); - int ret = -EWOULDBLOCK; - - if (ns) { - c->common.nsid = cpu_to_le32(ns->head->ns_id); - ret = nvme_submit_sync_cmd(ns->queue, c, data, 16); - } - srcu_read_unlock(&head->srcu, srcu_idx); - return ret; -} - -static int nvme_send_ns_pr_command(struct nvme_ns *ns, struct nvme_command *c, - u8 data[16]) -{ - c->common.nsid = cpu_to_le32(ns->head->ns_id); - return nvme_submit_sync_cmd(ns->queue, c, data, 16); -} - -static int nvme_sc_to_pr_err(int nvme_sc) -{ - if (nvme_is_path_error(nvme_sc)) - return PR_STS_PATH_FAILED; - - switch (nvme_sc) { - case NVME_SC_SUCCESS: - return PR_STS_SUCCESS; - case NVME_SC_RESERVATION_CONFLICT: - return PR_STS_RESERVATION_CONFLICT; - case NVME_SC_ONCS_NOT_SUPPORTED: - return -EOPNOTSUPP; - case NVME_SC_BAD_ATTRIBUTES: - case NVME_SC_INVALID_OPCODE: - case NVME_SC_INVALID_FIELD: - case NVME_SC_INVALID_NS: - return -EINVAL; - default: - return PR_STS_IOERR; - } -} - -static int nvme_pr_command(struct block_device *bdev, u32 cdw10, - u64 key, u64 sa_key, u8 op) -{ - struct nvme_command c = { }; - u8 data[16] = { 0, }; - int ret; - - put_unaligned_le64(key, &data[0]); - put_unaligned_le64(sa_key, &data[8]); - - c.common.opcode = op; - c.common.cdw10 = cpu_to_le32(cdw10); - - if (IS_ENABLED(CONFIG_NVME_MULTIPATH) && - bdev->bd_disk->fops == &nvme_ns_head_ops) - ret = nvme_send_ns_head_pr_command(bdev, &c, data); - else - ret = nvme_send_ns_pr_command(bdev->bd_disk->private_data, &c, - data); - if (ret < 0) - return ret; - - return nvme_sc_to_pr_err(ret); -} - -static int nvme_pr_register(struct block_device *bdev, u64 old, - u64 new, unsigned flags) -{ - u32 cdw10; - - if (flags & ~PR_FL_IGNORE_KEY) - return -EOPNOTSUPP; - - cdw10 = old ? 2 : 0; - cdw10 |= (flags & PR_FL_IGNORE_KEY) ? 1 << 3 : 0; - cdw10 |= (1 << 30) | (1 << 31); /* PTPL=1 */ - return nvme_pr_command(bdev, cdw10, old, new, nvme_cmd_resv_register); -} - -static int nvme_pr_reserve(struct block_device *bdev, u64 key, - enum pr_type type, unsigned flags) -{ - u32 cdw10; - - if (flags & ~PR_FL_IGNORE_KEY) - return -EOPNOTSUPP; - - cdw10 = nvme_pr_type(type) << 8; - cdw10 |= ((flags & PR_FL_IGNORE_KEY) ? 1 << 3 : 0); - return nvme_pr_command(bdev, cdw10, key, 0, nvme_cmd_resv_acquire); -} - -static int nvme_pr_preempt(struct block_device *bdev, u64 old, u64 new, - enum pr_type type, bool abort) -{ - u32 cdw10 = nvme_pr_type(type) << 8 | (abort ? 2 : 1); - - return nvme_pr_command(bdev, cdw10, old, new, nvme_cmd_resv_acquire); -} - -static int nvme_pr_clear(struct block_device *bdev, u64 key) -{ - u32 cdw10 = 1 | (key ? 0 : 1 << 3); - - return nvme_pr_command(bdev, cdw10, key, 0, nvme_cmd_resv_release); -} - -static int nvme_pr_release(struct block_device *bdev, u64 key, enum pr_type type) -{ - u32 cdw10 = nvme_pr_type(type) << 8 | (key ? 0 : 1 << 3); - - return nvme_pr_command(bdev, cdw10, key, 0, nvme_cmd_resv_release); -} - -const struct pr_ops nvme_pr_ops = { - .pr_register = nvme_pr_register, - .pr_reserve = nvme_pr_reserve, - .pr_release = nvme_pr_release, - .pr_preempt = nvme_pr_preempt, - .pr_clear = nvme_pr_clear, -}; - #ifdef CONFIG_BLK_SED_OPAL static int nvme_sec_submit(void *data, u16 spsp, u8 secp, void *buffer, size_t len, bool send) @@ -2300,7 +2156,7 @@ static int nvme_report_zones(struct gendisk *disk, sector_t sector, #define nvme_report_zones NULL #endif /* CONFIG_BLK_DEV_ZONED */ -static const struct block_device_operations nvme_bdev_ops = { +const struct block_device_operations nvme_bdev_ops = { .owner = THIS_MODULE, .ioctl = nvme_ioctl, .compat_ioctl = blkdev_compat_ptr_ioctl, @@ -2835,75 +2691,6 @@ static struct nvme_subsystem *__nvme_find_get_subsystem(const char *subsysnqn) return NULL; } -#define SUBSYS_ATTR_RO(_name, _mode, _show) \ - struct device_attribute subsys_attr_##_name = \ - __ATTR(_name, _mode, _show, NULL) - -static ssize_t nvme_subsys_show_nqn(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct nvme_subsystem *subsys = - container_of(dev, struct nvme_subsystem, dev); - - return sysfs_emit(buf, "%s\n", subsys->subnqn); -} -static SUBSYS_ATTR_RO(subsysnqn, S_IRUGO, nvme_subsys_show_nqn); - -static ssize_t nvme_subsys_show_type(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct nvme_subsystem *subsys = - container_of(dev, struct nvme_subsystem, dev); - - switch (subsys->subtype) { - case NVME_NQN_DISC: - return sysfs_emit(buf, "discovery\n"); - case NVME_NQN_NVME: - return sysfs_emit(buf, "nvm\n"); - default: - return sysfs_emit(buf, "reserved\n"); - } -} -static SUBSYS_ATTR_RO(subsystype, S_IRUGO, nvme_subsys_show_type); - -#define nvme_subsys_show_str_function(field) \ -static ssize_t subsys_##field##_show(struct device *dev, \ - struct device_attribute *attr, char *buf) \ -{ \ - struct nvme_subsystem *subsys = \ - container_of(dev, struct nvme_subsystem, dev); \ - return sysfs_emit(buf, "%.*s\n", \ - (int)sizeof(subsys->field), subsys->field); \ -} \ -static SUBSYS_ATTR_RO(field, S_IRUGO, subsys_##field##_show); - -nvme_subsys_show_str_function(model); -nvme_subsys_show_str_function(serial); -nvme_subsys_show_str_function(firmware_rev); - -static struct attribute *nvme_subsys_attrs[] = { - &subsys_attr_model.attr, - &subsys_attr_serial.attr, - &subsys_attr_firmware_rev.attr, - &subsys_attr_subsysnqn.attr, - &subsys_attr_subsystype.attr, -#ifdef CONFIG_NVME_MULTIPATH - &subsys_attr_iopolicy.attr, -#endif - NULL, -}; - -static const struct attribute_group nvme_subsys_attrs_group = { - .attrs = nvme_subsys_attrs, -}; - -static const struct attribute_group *nvme_subsys_attrs_groups[] = { - &nvme_subsys_attrs_group, - NULL, -}; - static inline bool nvme_discovery_ctrl(struct nvme_ctrl *ctrl) { return ctrl->opts && ctrl->opts->discovery_nqn; @@ -3108,7 +2895,8 @@ static int nvme_init_non_mdts_limits(struct nvme_ctrl *ctrl) ctrl->max_zeroes_sectors = 0; if (ctrl->subsys->subtype != NVME_NQN_NVME || - nvme_ctrl_limited_cns(ctrl)) + nvme_ctrl_limited_cns(ctrl) || + test_bit(NVME_CTRL_SKIP_ID_CNS_CS, &ctrl->flags)) return 0; id = kzalloc(sizeof(*id), GFP_KERNEL); @@ -3130,6 +2918,8 @@ static int nvme_init_non_mdts_limits(struct nvme_ctrl *ctrl) ctrl->max_zeroes_sectors = nvme_mps_to_sectors(ctrl, id->wzsl); free_data: + if (ret > 0) + set_bit(NVME_CTRL_SKIP_ID_CNS_CS, &ctrl->flags); kfree(id); return ret; } @@ -3390,6 +3180,7 @@ int nvme_init_ctrl_finish(struct nvme_ctrl *ctrl, bool was_suspended) return ret; } + clear_bit(NVME_CTRL_DIRTY_CAPABILITY, &ctrl->flags); ctrl->identified = true; return 0; @@ -3437,586 +3228,6 @@ static const struct file_operations nvme_dev_fops = { .uring_cmd = nvme_dev_uring_cmd, }; -static ssize_t nvme_sysfs_reset(struct device *dev, - struct device_attribute *attr, const char *buf, - size_t count) -{ - struct nvme_ctrl *ctrl = dev_get_drvdata(dev); - int ret; - - ret = nvme_reset_ctrl_sync(ctrl); - if (ret < 0) - return ret; - return count; -} -static DEVICE_ATTR(reset_controller, S_IWUSR, NULL, nvme_sysfs_reset); - -static ssize_t nvme_sysfs_rescan(struct device *dev, - struct device_attribute *attr, const char *buf, - size_t count) -{ - struct nvme_ctrl *ctrl = dev_get_drvdata(dev); - - nvme_queue_scan(ctrl); - return count; -} -static DEVICE_ATTR(rescan_controller, S_IWUSR, NULL, nvme_sysfs_rescan); - -static inline struct nvme_ns_head *dev_to_ns_head(struct device *dev) -{ - struct gendisk *disk = dev_to_disk(dev); - - if (disk->fops == &nvme_bdev_ops) - return nvme_get_ns_from_dev(dev)->head; - else - return disk->private_data; -} - -static ssize_t wwid_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct nvme_ns_head *head = dev_to_ns_head(dev); - struct nvme_ns_ids *ids = &head->ids; - struct nvme_subsystem *subsys = head->subsys; - int serial_len = sizeof(subsys->serial); - int model_len = sizeof(subsys->model); - - if (!uuid_is_null(&ids->uuid)) - return sysfs_emit(buf, "uuid.%pU\n", &ids->uuid); - - if (memchr_inv(ids->nguid, 0, sizeof(ids->nguid))) - return sysfs_emit(buf, "eui.%16phN\n", ids->nguid); - - if (memchr_inv(ids->eui64, 0, sizeof(ids->eui64))) - return sysfs_emit(buf, "eui.%8phN\n", ids->eui64); - - while (serial_len > 0 && (subsys->serial[serial_len - 1] == ' ' || - subsys->serial[serial_len - 1] == '\0')) - serial_len--; - while (model_len > 0 && (subsys->model[model_len - 1] == ' ' || - subsys->model[model_len - 1] == '\0')) - model_len--; - - return sysfs_emit(buf, "nvme.%04x-%*phN-%*phN-%08x\n", subsys->vendor_id, - serial_len, subsys->serial, model_len, subsys->model, - head->ns_id); -} -static DEVICE_ATTR_RO(wwid); - -static ssize_t nguid_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - return sysfs_emit(buf, "%pU\n", dev_to_ns_head(dev)->ids.nguid); -} -static DEVICE_ATTR_RO(nguid); - -static ssize_t uuid_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct nvme_ns_ids *ids = &dev_to_ns_head(dev)->ids; - - /* For backward compatibility expose the NGUID to userspace if - * we have no UUID set - */ - if (uuid_is_null(&ids->uuid)) { - dev_warn_ratelimited(dev, - "No UUID available providing old NGUID\n"); - return sysfs_emit(buf, "%pU\n", ids->nguid); - } - return sysfs_emit(buf, "%pU\n", &ids->uuid); -} -static DEVICE_ATTR_RO(uuid); - -static ssize_t eui_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - return sysfs_emit(buf, "%8ph\n", dev_to_ns_head(dev)->ids.eui64); -} -static DEVICE_ATTR_RO(eui); - -static ssize_t nsid_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - return sysfs_emit(buf, "%d\n", dev_to_ns_head(dev)->ns_id); -} -static DEVICE_ATTR_RO(nsid); - -static struct attribute *nvme_ns_id_attrs[] = { - &dev_attr_wwid.attr, - &dev_attr_uuid.attr, - &dev_attr_nguid.attr, - &dev_attr_eui.attr, - &dev_attr_nsid.attr, -#ifdef CONFIG_NVME_MULTIPATH - &dev_attr_ana_grpid.attr, - &dev_attr_ana_state.attr, -#endif - NULL, -}; - -static umode_t nvme_ns_id_attrs_are_visible(struct kobject *kobj, - struct attribute *a, int n) -{ - struct device *dev = container_of(kobj, struct device, kobj); - struct nvme_ns_ids *ids = &dev_to_ns_head(dev)->ids; - - if (a == &dev_attr_uuid.attr) { - if (uuid_is_null(&ids->uuid) && - !memchr_inv(ids->nguid, 0, sizeof(ids->nguid))) - return 0; - } - if (a == &dev_attr_nguid.attr) { - if (!memchr_inv(ids->nguid, 0, sizeof(ids->nguid))) - return 0; - } - if (a == &dev_attr_eui.attr) { - if (!memchr_inv(ids->eui64, 0, sizeof(ids->eui64))) - return 0; - } -#ifdef CONFIG_NVME_MULTIPATH - if (a == &dev_attr_ana_grpid.attr || a == &dev_attr_ana_state.attr) { - if (dev_to_disk(dev)->fops != &nvme_bdev_ops) /* per-path attr */ - return 0; - if (!nvme_ctrl_use_ana(nvme_get_ns_from_dev(dev)->ctrl)) - return 0; - } -#endif - return a->mode; -} - -static const struct attribute_group nvme_ns_id_attr_group = { - .attrs = nvme_ns_id_attrs, - .is_visible = nvme_ns_id_attrs_are_visible, -}; - -const struct attribute_group *nvme_ns_id_attr_groups[] = { - &nvme_ns_id_attr_group, - NULL, -}; - -#define nvme_show_str_function(field) \ -static ssize_t field##_show(struct device *dev, \ - struct device_attribute *attr, char *buf) \ -{ \ - struct nvme_ctrl *ctrl = dev_get_drvdata(dev); \ - return sysfs_emit(buf, "%.*s\n", \ - (int)sizeof(ctrl->subsys->field), ctrl->subsys->field); \ -} \ -static DEVICE_ATTR(field, S_IRUGO, field##_show, NULL); - -nvme_show_str_function(model); -nvme_show_str_function(serial); -nvme_show_str_function(firmware_rev); - -#define nvme_show_int_function(field) \ -static ssize_t field##_show(struct device *dev, \ - struct device_attribute *attr, char *buf) \ -{ \ - struct nvme_ctrl *ctrl = dev_get_drvdata(dev); \ - return sysfs_emit(buf, "%d\n", ctrl->field); \ -} \ -static DEVICE_ATTR(field, S_IRUGO, field##_show, NULL); - -nvme_show_int_function(cntlid); -nvme_show_int_function(numa_node); -nvme_show_int_function(queue_count); -nvme_show_int_function(sqsize); -nvme_show_int_function(kato); - -static ssize_t nvme_sysfs_delete(struct device *dev, - struct device_attribute *attr, const char *buf, - size_t count) -{ - struct nvme_ctrl *ctrl = dev_get_drvdata(dev); - - if (!test_bit(NVME_CTRL_STARTED_ONCE, &ctrl->flags)) - return -EBUSY; - - if (device_remove_file_self(dev, attr)) - nvme_delete_ctrl_sync(ctrl); - return count; -} -static DEVICE_ATTR(delete_controller, S_IWUSR, NULL, nvme_sysfs_delete); - -static ssize_t nvme_sysfs_show_transport(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct nvme_ctrl *ctrl = dev_get_drvdata(dev); - - return sysfs_emit(buf, "%s\n", ctrl->ops->name); -} -static DEVICE_ATTR(transport, S_IRUGO, nvme_sysfs_show_transport, NULL); - -static ssize_t nvme_sysfs_show_state(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct nvme_ctrl *ctrl = dev_get_drvdata(dev); - static const char *const state_name[] = { - [NVME_CTRL_NEW] = "new", - [NVME_CTRL_LIVE] = "live", - [NVME_CTRL_RESETTING] = "resetting", - [NVME_CTRL_CONNECTING] = "connecting", - [NVME_CTRL_DELETING] = "deleting", - [NVME_CTRL_DELETING_NOIO]= "deleting (no IO)", - [NVME_CTRL_DEAD] = "dead", - }; - - if ((unsigned)ctrl->state < ARRAY_SIZE(state_name) && - state_name[ctrl->state]) - return sysfs_emit(buf, "%s\n", state_name[ctrl->state]); - - return sysfs_emit(buf, "unknown state\n"); -} - -static DEVICE_ATTR(state, S_IRUGO, nvme_sysfs_show_state, NULL); - -static ssize_t nvme_sysfs_show_subsysnqn(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct nvme_ctrl *ctrl = dev_get_drvdata(dev); - - return sysfs_emit(buf, "%s\n", ctrl->subsys->subnqn); -} -static DEVICE_ATTR(subsysnqn, S_IRUGO, nvme_sysfs_show_subsysnqn, NULL); - -static ssize_t nvme_sysfs_show_hostnqn(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct nvme_ctrl *ctrl = dev_get_drvdata(dev); - - return sysfs_emit(buf, "%s\n", ctrl->opts->host->nqn); -} -static DEVICE_ATTR(hostnqn, S_IRUGO, nvme_sysfs_show_hostnqn, NULL); - -static ssize_t nvme_sysfs_show_hostid(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct nvme_ctrl *ctrl = dev_get_drvdata(dev); - - return sysfs_emit(buf, "%pU\n", &ctrl->opts->host->id); -} -static DEVICE_ATTR(hostid, S_IRUGO, nvme_sysfs_show_hostid, NULL); - -static ssize_t nvme_sysfs_show_address(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct nvme_ctrl *ctrl = dev_get_drvdata(dev); - - return ctrl->ops->get_address(ctrl, buf, PAGE_SIZE); -} -static DEVICE_ATTR(address, S_IRUGO, nvme_sysfs_show_address, NULL); - -static ssize_t nvme_ctrl_loss_tmo_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct nvme_ctrl *ctrl = dev_get_drvdata(dev); - struct nvmf_ctrl_options *opts = ctrl->opts; - - if (ctrl->opts->max_reconnects == -1) - return sysfs_emit(buf, "off\n"); - return sysfs_emit(buf, "%d\n", - opts->max_reconnects * opts->reconnect_delay); -} - -static ssize_t nvme_ctrl_loss_tmo_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - struct nvme_ctrl *ctrl = dev_get_drvdata(dev); - struct nvmf_ctrl_options *opts = ctrl->opts; - int ctrl_loss_tmo, err; - - err = kstrtoint(buf, 10, &ctrl_loss_tmo); - if (err) - return -EINVAL; - - if (ctrl_loss_tmo < 0) - opts->max_reconnects = -1; - else - opts->max_reconnects = DIV_ROUND_UP(ctrl_loss_tmo, - opts->reconnect_delay); - return count; -} -static DEVICE_ATTR(ctrl_loss_tmo, S_IRUGO | S_IWUSR, - nvme_ctrl_loss_tmo_show, nvme_ctrl_loss_tmo_store); - -static ssize_t nvme_ctrl_reconnect_delay_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct nvme_ctrl *ctrl = dev_get_drvdata(dev); - - if (ctrl->opts->reconnect_delay == -1) - return sysfs_emit(buf, "off\n"); - return sysfs_emit(buf, "%d\n", ctrl->opts->reconnect_delay); -} - -static ssize_t nvme_ctrl_reconnect_delay_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - struct nvme_ctrl *ctrl = dev_get_drvdata(dev); - unsigned int v; - int err; - - err = kstrtou32(buf, 10, &v); - if (err) - return err; - - ctrl->opts->reconnect_delay = v; - return count; -} -static DEVICE_ATTR(reconnect_delay, S_IRUGO | S_IWUSR, - nvme_ctrl_reconnect_delay_show, nvme_ctrl_reconnect_delay_store); - -static ssize_t nvme_ctrl_fast_io_fail_tmo_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct nvme_ctrl *ctrl = dev_get_drvdata(dev); - - if (ctrl->opts->fast_io_fail_tmo == -1) - return sysfs_emit(buf, "off\n"); - return sysfs_emit(buf, "%d\n", ctrl->opts->fast_io_fail_tmo); -} - -static ssize_t nvme_ctrl_fast_io_fail_tmo_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - struct nvme_ctrl *ctrl = dev_get_drvdata(dev); - struct nvmf_ctrl_options *opts = ctrl->opts; - int fast_io_fail_tmo, err; - - err = kstrtoint(buf, 10, &fast_io_fail_tmo); - if (err) - return -EINVAL; - - if (fast_io_fail_tmo < 0) - opts->fast_io_fail_tmo = -1; - else - opts->fast_io_fail_tmo = fast_io_fail_tmo; - return count; -} -static DEVICE_ATTR(fast_io_fail_tmo, S_IRUGO | S_IWUSR, - nvme_ctrl_fast_io_fail_tmo_show, nvme_ctrl_fast_io_fail_tmo_store); - -static ssize_t cntrltype_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - static const char * const type[] = { - [NVME_CTRL_IO] = "io\n", - [NVME_CTRL_DISC] = "discovery\n", - [NVME_CTRL_ADMIN] = "admin\n", - }; - struct nvme_ctrl *ctrl = dev_get_drvdata(dev); - - if (ctrl->cntrltype > NVME_CTRL_ADMIN || !type[ctrl->cntrltype]) - return sysfs_emit(buf, "reserved\n"); - - return sysfs_emit(buf, type[ctrl->cntrltype]); -} -static DEVICE_ATTR_RO(cntrltype); - -static ssize_t dctype_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - static const char * const type[] = { - [NVME_DCTYPE_NOT_REPORTED] = "none\n", - [NVME_DCTYPE_DDC] = "ddc\n", - [NVME_DCTYPE_CDC] = "cdc\n", - }; - struct nvme_ctrl *ctrl = dev_get_drvdata(dev); - - if (ctrl->dctype > NVME_DCTYPE_CDC || !type[ctrl->dctype]) - return sysfs_emit(buf, "reserved\n"); - - return sysfs_emit(buf, type[ctrl->dctype]); -} -static DEVICE_ATTR_RO(dctype); - -#ifdef CONFIG_NVME_AUTH -static ssize_t nvme_ctrl_dhchap_secret_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct nvme_ctrl *ctrl = dev_get_drvdata(dev); - struct nvmf_ctrl_options *opts = ctrl->opts; - - if (!opts->dhchap_secret) - return sysfs_emit(buf, "none\n"); - return sysfs_emit(buf, "%s\n", opts->dhchap_secret); -} - -static ssize_t nvme_ctrl_dhchap_secret_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - struct nvme_ctrl *ctrl = dev_get_drvdata(dev); - struct nvmf_ctrl_options *opts = ctrl->opts; - char *dhchap_secret; - - if (!ctrl->opts->dhchap_secret) - return -EINVAL; - if (count < 7) - return -EINVAL; - if (memcmp(buf, "DHHC-1:", 7)) - return -EINVAL; - - dhchap_secret = kzalloc(count + 1, GFP_KERNEL); - if (!dhchap_secret) - return -ENOMEM; - memcpy(dhchap_secret, buf, count); - nvme_auth_stop(ctrl); - if (strcmp(dhchap_secret, opts->dhchap_secret)) { - struct nvme_dhchap_key *key, *host_key; - int ret; - - ret = nvme_auth_generate_key(dhchap_secret, &key); - if (ret) - return ret; - kfree(opts->dhchap_secret); - opts->dhchap_secret = dhchap_secret; - host_key = ctrl->host_key; - mutex_lock(&ctrl->dhchap_auth_mutex); - ctrl->host_key = key; - mutex_unlock(&ctrl->dhchap_auth_mutex); - nvme_auth_free_key(host_key); - } - /* Start re-authentication */ - dev_info(ctrl->device, "re-authenticating controller\n"); - queue_work(nvme_wq, &ctrl->dhchap_auth_work); - - return count; -} -static DEVICE_ATTR(dhchap_secret, S_IRUGO | S_IWUSR, - nvme_ctrl_dhchap_secret_show, nvme_ctrl_dhchap_secret_store); - -static ssize_t nvme_ctrl_dhchap_ctrl_secret_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct nvme_ctrl *ctrl = dev_get_drvdata(dev); - struct nvmf_ctrl_options *opts = ctrl->opts; - - if (!opts->dhchap_ctrl_secret) - return sysfs_emit(buf, "none\n"); - return sysfs_emit(buf, "%s\n", opts->dhchap_ctrl_secret); -} - -static ssize_t nvme_ctrl_dhchap_ctrl_secret_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - struct nvme_ctrl *ctrl = dev_get_drvdata(dev); - struct nvmf_ctrl_options *opts = ctrl->opts; - char *dhchap_secret; - - if (!ctrl->opts->dhchap_ctrl_secret) - return -EINVAL; - if (count < 7) - return -EINVAL; - if (memcmp(buf, "DHHC-1:", 7)) - return -EINVAL; - - dhchap_secret = kzalloc(count + 1, GFP_KERNEL); - if (!dhchap_secret) - return -ENOMEM; - memcpy(dhchap_secret, buf, count); - nvme_auth_stop(ctrl); - if (strcmp(dhchap_secret, opts->dhchap_ctrl_secret)) { - struct nvme_dhchap_key *key, *ctrl_key; - int ret; - - ret = nvme_auth_generate_key(dhchap_secret, &key); - if (ret) - return ret; - kfree(opts->dhchap_ctrl_secret); - opts->dhchap_ctrl_secret = dhchap_secret; - ctrl_key = ctrl->ctrl_key; - mutex_lock(&ctrl->dhchap_auth_mutex); - ctrl->ctrl_key = key; - mutex_unlock(&ctrl->dhchap_auth_mutex); - nvme_auth_free_key(ctrl_key); - } - /* Start re-authentication */ - dev_info(ctrl->device, "re-authenticating controller\n"); - queue_work(nvme_wq, &ctrl->dhchap_auth_work); - - return count; -} -static DEVICE_ATTR(dhchap_ctrl_secret, S_IRUGO | S_IWUSR, - nvme_ctrl_dhchap_ctrl_secret_show, nvme_ctrl_dhchap_ctrl_secret_store); -#endif - -static struct attribute *nvme_dev_attrs[] = { - &dev_attr_reset_controller.attr, - &dev_attr_rescan_controller.attr, - &dev_attr_model.attr, - &dev_attr_serial.attr, - &dev_attr_firmware_rev.attr, - &dev_attr_cntlid.attr, - &dev_attr_delete_controller.attr, - &dev_attr_transport.attr, - &dev_attr_subsysnqn.attr, - &dev_attr_address.attr, - &dev_attr_state.attr, - &dev_attr_numa_node.attr, - &dev_attr_queue_count.attr, - &dev_attr_sqsize.attr, - &dev_attr_hostnqn.attr, - &dev_attr_hostid.attr, - &dev_attr_ctrl_loss_tmo.attr, - &dev_attr_reconnect_delay.attr, - &dev_attr_fast_io_fail_tmo.attr, - &dev_attr_kato.attr, - &dev_attr_cntrltype.attr, - &dev_attr_dctype.attr, -#ifdef CONFIG_NVME_AUTH - &dev_attr_dhchap_secret.attr, - &dev_attr_dhchap_ctrl_secret.attr, -#endif - NULL -}; - -static umode_t nvme_dev_attrs_are_visible(struct kobject *kobj, - struct attribute *a, int n) -{ - struct device *dev = container_of(kobj, struct device, kobj); - struct nvme_ctrl *ctrl = dev_get_drvdata(dev); - - if (a == &dev_attr_delete_controller.attr && !ctrl->ops->delete_ctrl) - return 0; - if (a == &dev_attr_address.attr && !ctrl->ops->get_address) - return 0; - if (a == &dev_attr_hostnqn.attr && !ctrl->opts) - return 0; - if (a == &dev_attr_hostid.attr && !ctrl->opts) - return 0; - if (a == &dev_attr_ctrl_loss_tmo.attr && !ctrl->opts) - return 0; - if (a == &dev_attr_reconnect_delay.attr && !ctrl->opts) - return 0; - if (a == &dev_attr_fast_io_fail_tmo.attr && !ctrl->opts) - return 0; -#ifdef CONFIG_NVME_AUTH - if (a == &dev_attr_dhchap_secret.attr && !ctrl->opts) - return 0; - if (a == &dev_attr_dhchap_ctrl_secret.attr && !ctrl->opts) - return 0; -#endif - - return a->mode; -} - -const struct attribute_group nvme_dev_attrs_group = { - .attrs = nvme_dev_attrs, - .is_visible = nvme_dev_attrs_are_visible, -}; -EXPORT_SYMBOL_GPL(nvme_dev_attrs_group); - -static const struct attribute_group *nvme_dev_attr_groups[] = { - &nvme_dev_attrs_group, - NULL, -}; - static struct nvme_ns_head *nvme_find_ns_head(struct nvme_ctrl *ctrl, unsigned nsid) { @@ -4220,10 +3431,40 @@ static int nvme_init_ns_head(struct nvme_ns *ns, struct nvme_ns_info *info) ret = nvme_global_check_duplicate_ids(ctrl->subsys, &info->ids); if (ret) { - dev_err(ctrl->device, - "globally duplicate IDs for nsid %d\n", info->nsid); + /* + * We've found two different namespaces on two different + * subsystems that report the same ID. This is pretty nasty + * for anything that actually requires unique device + * identification. In the kernel we need this for multipathing, + * and in user space the /dev/disk/by-id/ links rely on it. + * + * If the device also claims to be multi-path capable back off + * here now and refuse the probe the second device as this is a + * recipe for data corruption. If not this is probably a + * cheap consumer device if on the PCIe bus, so let the user + * proceed and use the shiny toy, but warn that with changing + * probing order (which due to our async probing could just be + * device taking longer to startup) the other device could show + * up at any time. + */ nvme_print_device_info(ctrl); - return ret; + if ((ns->ctrl->ops->flags & NVME_F_FABRICS) || /* !PCIe */ + ((ns->ctrl->subsys->cmic & NVME_CTRL_CMIC_MULTI_CTRL) && + info->is_shared)) { + dev_err(ctrl->device, + "ignoring nsid %d because of duplicate IDs\n", + info->nsid); + return ret; + } + + dev_err(ctrl->device, + "clearing duplicate IDs for nsid %d\n", info->nsid); + dev_err(ctrl->device, + "use of /dev/disk/by-id/ may cause data corruption\n"); + memset(&info->ids.nguid, 0, sizeof(info->ids.nguid)); + memset(&info->ids.uuid, 0, sizeof(info->ids.uuid)); + memset(&info->ids.eui64, 0, sizeof(info->ids.eui64)); + ctrl->quirks |= NVME_QUIRK_BOGUS_NID; } mutex_lock(&ctrl->subsys->lock); @@ -4256,7 +3497,7 @@ static int nvme_init_ns_head(struct nvme_ns *ns, struct nvme_ns_info *info) goto out_put_ns_head; } - if (!multipath && !list_empty(&head->list)) { + if (!multipath) { dev_warn(ctrl->device, "Found shared namespace %d, but multipathing not supported.\n", info->nsid); @@ -4357,7 +3598,7 @@ static void nvme_alloc_ns(struct nvme_ctrl *ctrl, struct nvme_ns_info *info) * instance as shared namespaces will show up as multiple block * devices. */ - if (ns->head->disk) { + if (nvme_ns_head_multipath(ns->head)) { sprintf(disk->disk_name, "nvme%dc%dn%d", ctrl->subsys->instance, ctrl->instance, ns->head->instance); disk->flags |= GENHD_FL_HIDDEN; @@ -5243,6 +4484,8 @@ int nvme_init_ctrl(struct nvme_ctrl *ctrl, struct device *dev, return 0; out_free_cdev: + nvme_fault_inject_fini(&ctrl->fault_inject); + dev_pm_qos_hide_latency_tolerance(ctrl->device); cdev_device_del(&ctrl->cdev, ctrl->device); out_free_name: nvme_put_ctrl(ctrl); diff --git a/drivers/nvme/host/fabrics.c b/drivers/nvme/host/fabrics.c index 0069ebff85df1ec55dd5a798c9740782784e09c0..8175d49f290901790a62774408e2004280215f2d 100644 --- a/drivers/nvme/host/fabrics.c +++ b/drivers/nvme/host/fabrics.c @@ -21,35 +21,60 @@ static DEFINE_MUTEX(nvmf_hosts_mutex); static struct nvmf_host *nvmf_default_host; -static struct nvmf_host *__nvmf_host_find(const char *hostnqn) +static struct nvmf_host *nvmf_host_alloc(const char *hostnqn, uuid_t *id) { struct nvmf_host *host; - list_for_each_entry(host, &nvmf_hosts, list) { - if (!strcmp(host->nqn, hostnqn)) - return host; - } + host = kmalloc(sizeof(*host), GFP_KERNEL); + if (!host) + return NULL; - return NULL; + kref_init(&host->ref); + uuid_copy(&host->id, id); + strscpy(host->nqn, hostnqn, NVMF_NQN_SIZE); + + return host; } -static struct nvmf_host *nvmf_host_add(const char *hostnqn) +static struct nvmf_host *nvmf_host_add(const char *hostnqn, uuid_t *id) { struct nvmf_host *host; mutex_lock(&nvmf_hosts_mutex); - host = __nvmf_host_find(hostnqn); - if (host) { - kref_get(&host->ref); - goto out_unlock; + + /* + * We have defined a host as how it is perceived by the target. + * Therefore, we don't allow different Host NQNs with the same Host ID. + * Similarly, we do not allow the usage of the same Host NQN with + * different Host IDs. This'll maintain unambiguous host identification. + */ + list_for_each_entry(host, &nvmf_hosts, list) { + bool same_hostnqn = !strcmp(host->nqn, hostnqn); + bool same_hostid = uuid_equal(&host->id, id); + + if (same_hostnqn && same_hostid) { + kref_get(&host->ref); + goto out_unlock; + } + if (same_hostnqn) { + pr_err("found same hostnqn %s but different hostid %pUb\n", + hostnqn, id); + host = ERR_PTR(-EINVAL); + goto out_unlock; + } + if (same_hostid) { + pr_err("found same hostid %pUb but different hostnqn %s\n", + id, hostnqn); + host = ERR_PTR(-EINVAL); + goto out_unlock; + } } - host = kmalloc(sizeof(*host), GFP_KERNEL); - if (!host) + host = nvmf_host_alloc(hostnqn, id); + if (!host) { + host = ERR_PTR(-ENOMEM); goto out_unlock; - - kref_init(&host->ref); - strscpy(host->nqn, hostnqn, NVMF_NQN_SIZE); + } list_add_tail(&host->list, &nvmf_hosts); out_unlock: @@ -60,16 +85,17 @@ static struct nvmf_host *nvmf_host_add(const char *hostnqn) static struct nvmf_host *nvmf_host_default(void) { struct nvmf_host *host; + char nqn[NVMF_NQN_SIZE]; + uuid_t id; - host = kmalloc(sizeof(*host), GFP_KERNEL); + uuid_gen(&id); + snprintf(nqn, NVMF_NQN_SIZE, + "nqn.2014-08.org.nvmexpress:uuid:%pUb", &id); + + host = nvmf_host_alloc(nqn, &id); if (!host) return NULL; - kref_init(&host->ref); - uuid_gen(&host->id); - snprintf(host->nqn, NVMF_NQN_SIZE, - "nqn.2014-08.org.nvmexpress:uuid:%pUb", &host->id); - mutex_lock(&nvmf_hosts_mutex); list_add_tail(&host->list, &nvmf_hosts); mutex_unlock(&nvmf_hosts_mutex); @@ -349,6 +375,45 @@ static void nvmf_log_connect_error(struct nvme_ctrl *ctrl, } } +static struct nvmf_connect_data *nvmf_connect_data_prep(struct nvme_ctrl *ctrl, + u16 cntlid) +{ + struct nvmf_connect_data *data; + + data = kzalloc(sizeof(*data), GFP_KERNEL); + if (!data) + return NULL; + + uuid_copy(&data->hostid, &ctrl->opts->host->id); + data->cntlid = cpu_to_le16(cntlid); + strncpy(data->subsysnqn, ctrl->opts->subsysnqn, NVMF_NQN_SIZE); + strncpy(data->hostnqn, ctrl->opts->host->nqn, NVMF_NQN_SIZE); + + return data; +} + +static void nvmf_connect_cmd_prep(struct nvme_ctrl *ctrl, u16 qid, + struct nvme_command *cmd) +{ + cmd->connect.opcode = nvme_fabrics_command; + cmd->connect.fctype = nvme_fabrics_type_connect; + cmd->connect.qid = cpu_to_le16(qid); + + if (qid) { + cmd->connect.sqsize = cpu_to_le16(ctrl->sqsize); + } else { + cmd->connect.sqsize = cpu_to_le16(NVME_AQ_DEPTH - 1); + + /* + * set keep-alive timeout in seconds granularity (ms * 1000) + */ + cmd->connect.kato = cpu_to_le32(ctrl->kato * 1000); + } + + if (ctrl->opts->disable_sqflow) + cmd->connect.cattr |= NVME_CONNECT_DISABLE_SQFLOW; +} + /** * nvmf_connect_admin_queue() - NVMe Fabrics Admin Queue "Connect" * API function. @@ -377,28 +442,12 @@ int nvmf_connect_admin_queue(struct nvme_ctrl *ctrl) int ret; u32 result; - cmd.connect.opcode = nvme_fabrics_command; - cmd.connect.fctype = nvme_fabrics_type_connect; - cmd.connect.qid = 0; - cmd.connect.sqsize = cpu_to_le16(NVME_AQ_DEPTH - 1); - - /* - * Set keep-alive timeout in seconds granularity (ms * 1000) - */ - cmd.connect.kato = cpu_to_le32(ctrl->kato * 1000); - - if (ctrl->opts->disable_sqflow) - cmd.connect.cattr |= NVME_CONNECT_DISABLE_SQFLOW; + nvmf_connect_cmd_prep(ctrl, 0, &cmd); - data = kzalloc(sizeof(*data), GFP_KERNEL); + data = nvmf_connect_data_prep(ctrl, 0xffff); if (!data) return -ENOMEM; - uuid_copy(&data->hostid, &ctrl->opts->host->id); - data->cntlid = cpu_to_le16(0xffff); - strncpy(data->subsysnqn, ctrl->opts->subsysnqn, NVMF_NQN_SIZE); - strncpy(data->hostnqn, ctrl->opts->host->nqn, NVMF_NQN_SIZE); - ret = __nvme_submit_sync_cmd(ctrl->fabrics_q, &cmd, &res, data, sizeof(*data), NVME_QID_ANY, 1, BLK_MQ_REQ_RESERVED | BLK_MQ_REQ_NOWAIT); @@ -468,23 +517,12 @@ int nvmf_connect_io_queue(struct nvme_ctrl *ctrl, u16 qid) int ret; u32 result; - cmd.connect.opcode = nvme_fabrics_command; - cmd.connect.fctype = nvme_fabrics_type_connect; - cmd.connect.qid = cpu_to_le16(qid); - cmd.connect.sqsize = cpu_to_le16(ctrl->sqsize); + nvmf_connect_cmd_prep(ctrl, qid, &cmd); - if (ctrl->opts->disable_sqflow) - cmd.connect.cattr |= NVME_CONNECT_DISABLE_SQFLOW; - - data = kzalloc(sizeof(*data), GFP_KERNEL); + data = nvmf_connect_data_prep(ctrl, ctrl->cntlid); if (!data) return -ENOMEM; - uuid_copy(&data->hostid, &ctrl->opts->host->id); - data->cntlid = cpu_to_le16(ctrl->cntlid); - strncpy(data->subsysnqn, ctrl->opts->subsysnqn, NVMF_NQN_SIZE); - strncpy(data->hostnqn, ctrl->opts->host->nqn, NVMF_NQN_SIZE); - ret = __nvme_submit_sync_cmd(ctrl->connect_q, &cmd, &res, data, sizeof(*data), qid, 1, BLK_MQ_REQ_RESERVED | BLK_MQ_REQ_NOWAIT); @@ -621,6 +659,7 @@ static int nvmf_parse_options(struct nvmf_ctrl_options *opts, size_t nqnlen = 0; int ctrl_loss_tmo = NVMF_DEF_CTRL_LOSS_TMO; uuid_t hostid; + char hostnqn[NVMF_NQN_SIZE]; /* Set defaults */ opts->queue_size = NVMF_DEF_QUEUE_SIZE; @@ -637,7 +676,9 @@ static int nvmf_parse_options(struct nvmf_ctrl_options *opts, if (!options) return -ENOMEM; - uuid_gen(&hostid); + /* use default host if not given by user space */ + uuid_copy(&hostid, &nvmf_default_host->id); + strscpy(hostnqn, nvmf_default_host->nqn, NVMF_NQN_SIZE); while ((p = strsep(&o, ",\n")) != NULL) { if (!*p) @@ -783,12 +824,8 @@ static int nvmf_parse_options(struct nvmf_ctrl_options *opts, ret = -EINVAL; goto out; } - opts->host = nvmf_host_add(p); + strscpy(hostnqn, p, NVMF_NQN_SIZE); kfree(p); - if (!opts->host) { - ret = -ENOMEM; - goto out; - } break; case NVMF_OPT_RECONNECT_DELAY: if (match_int(args, &token)) { @@ -945,18 +982,94 @@ static int nvmf_parse_options(struct nvmf_ctrl_options *opts, opts->fast_io_fail_tmo, ctrl_loss_tmo); } - if (!opts->host) { - kref_get(&nvmf_default_host->ref); - opts->host = nvmf_default_host; + opts->host = nvmf_host_add(hostnqn, &hostid); + if (IS_ERR(opts->host)) { + ret = PTR_ERR(opts->host); + opts->host = NULL; + goto out; } - uuid_copy(&opts->host->id, &hostid); - out: kfree(options); return ret; } +void nvmf_set_io_queues(struct nvmf_ctrl_options *opts, u32 nr_io_queues, + u32 io_queues[HCTX_MAX_TYPES]) +{ + if (opts->nr_write_queues && opts->nr_io_queues < nr_io_queues) { + /* + * separate read/write queues + * hand out dedicated default queues only after we have + * sufficient read queues. + */ + io_queues[HCTX_TYPE_READ] = opts->nr_io_queues; + nr_io_queues -= io_queues[HCTX_TYPE_READ]; + io_queues[HCTX_TYPE_DEFAULT] = + min(opts->nr_write_queues, nr_io_queues); + nr_io_queues -= io_queues[HCTX_TYPE_DEFAULT]; + } else { + /* + * shared read/write queues + * either no write queues were requested, or we don't have + * sufficient queue count to have dedicated default queues. + */ + io_queues[HCTX_TYPE_DEFAULT] = + min(opts->nr_io_queues, nr_io_queues); + nr_io_queues -= io_queues[HCTX_TYPE_DEFAULT]; + } + + if (opts->nr_poll_queues && nr_io_queues) { + /* map dedicated poll queues only if we have queues left */ + io_queues[HCTX_TYPE_POLL] = + min(opts->nr_poll_queues, nr_io_queues); + } +} +EXPORT_SYMBOL_GPL(nvmf_set_io_queues); + +void nvmf_map_queues(struct blk_mq_tag_set *set, struct nvme_ctrl *ctrl, + u32 io_queues[HCTX_MAX_TYPES]) +{ + struct nvmf_ctrl_options *opts = ctrl->opts; + + if (opts->nr_write_queues && io_queues[HCTX_TYPE_READ]) { + /* separate read/write queues */ + set->map[HCTX_TYPE_DEFAULT].nr_queues = + io_queues[HCTX_TYPE_DEFAULT]; + set->map[HCTX_TYPE_DEFAULT].queue_offset = 0; + set->map[HCTX_TYPE_READ].nr_queues = + io_queues[HCTX_TYPE_READ]; + set->map[HCTX_TYPE_READ].queue_offset = + io_queues[HCTX_TYPE_DEFAULT]; + } else { + /* shared read/write queues */ + set->map[HCTX_TYPE_DEFAULT].nr_queues = + io_queues[HCTX_TYPE_DEFAULT]; + set->map[HCTX_TYPE_DEFAULT].queue_offset = 0; + set->map[HCTX_TYPE_READ].nr_queues = + io_queues[HCTX_TYPE_DEFAULT]; + set->map[HCTX_TYPE_READ].queue_offset = 0; + } + + blk_mq_map_queues(&set->map[HCTX_TYPE_DEFAULT]); + blk_mq_map_queues(&set->map[HCTX_TYPE_READ]); + if (opts->nr_poll_queues && io_queues[HCTX_TYPE_POLL]) { + /* map dedicated poll queues only if we have queues left */ + set->map[HCTX_TYPE_POLL].nr_queues = io_queues[HCTX_TYPE_POLL]; + set->map[HCTX_TYPE_POLL].queue_offset = + io_queues[HCTX_TYPE_DEFAULT] + + io_queues[HCTX_TYPE_READ]; + blk_mq_map_queues(&set->map[HCTX_TYPE_POLL]); + } + + dev_info(ctrl->device, + "mapped %d/%d/%d default/read/poll queues.\n", + io_queues[HCTX_TYPE_DEFAULT], + io_queues[HCTX_TYPE_READ], + io_queues[HCTX_TYPE_POLL]); +} +EXPORT_SYMBOL_GPL(nvmf_map_queues); + static int nvmf_check_required_opts(struct nvmf_ctrl_options *opts, unsigned int required_opts) { diff --git a/drivers/nvme/host/fabrics.h b/drivers/nvme/host/fabrics.h index dcac3df8a5f760427cff2750ac7c0de501fca409..82e7a27ffbde351e72d8fff18923938196f237a1 100644 --- a/drivers/nvme/host/fabrics.h +++ b/drivers/nvme/host/fabrics.h @@ -77,6 +77,9 @@ enum { * with the parsing opts enum. * @mask: Used by the fabrics library to parse through sysfs options * on adding a NVMe controller. + * @max_reconnects: maximum number of allowed reconnect attempts before removing + * the controller, (-1) means reconnect forever, zero means remove + * immediately; * @transport: Holds the fabric transport "technology name" (for a lack of * better description) that will be used by an NVMe controller * being added. @@ -96,9 +99,6 @@ enum { * @discovery_nqn: indicates if the subsysnqn is the well-known discovery NQN. * @kato: Keep-alive timeout. * @host: Virtual NVMe host, contains the NQN and Host ID. - * @max_reconnects: maximum number of allowed reconnect attempts before removing - * the controller, (-1) means reconnect forever, zero means remove - * immediately; * @dhchap_secret: DH-HMAC-CHAP secret * @dhchap_ctrl_secret: DH-HMAC-CHAP controller secret for bi-directional * authentication @@ -112,6 +112,7 @@ enum { */ struct nvmf_ctrl_options { unsigned mask; + int max_reconnects; char *transport; char *subsysnqn; char *traddr; @@ -125,7 +126,6 @@ struct nvmf_ctrl_options { bool duplicate_connect; unsigned int kato; struct nvmf_host *host; - int max_reconnects; char *dhchap_secret; char *dhchap_ctrl_secret; bool disable_sqflow; @@ -181,7 +181,7 @@ nvmf_ctlr_matches_baseopts(struct nvme_ctrl *ctrl, ctrl->state == NVME_CTRL_DEAD || strcmp(opts->subsysnqn, ctrl->opts->subsysnqn) || strcmp(opts->host->nqn, ctrl->opts->host->nqn) || - memcmp(&opts->host->id, &ctrl->opts->host->id, sizeof(uuid_t))) + !uuid_equal(&opts->host->id, &ctrl->opts->host->id)) return false; return true; @@ -203,6 +203,13 @@ static inline void nvmf_complete_timed_out_request(struct request *rq) } } +static inline unsigned int nvmf_nr_io_queues(struct nvmf_ctrl_options *opts) +{ + return min(opts->nr_io_queues, num_online_cpus()) + + min(opts->nr_write_queues, num_online_cpus()) + + min(opts->nr_poll_queues, num_online_cpus()); +} + int nvmf_reg_read32(struct nvme_ctrl *ctrl, u32 off, u32 *val); int nvmf_reg_read64(struct nvme_ctrl *ctrl, u32 off, u64 *val); int nvmf_reg_write32(struct nvme_ctrl *ctrl, u32 off, u32 val); @@ -215,5 +222,9 @@ int nvmf_get_address(struct nvme_ctrl *ctrl, char *buf, int size); bool nvmf_should_reconnect(struct nvme_ctrl *ctrl); bool nvmf_ip_options_match(struct nvme_ctrl *ctrl, struct nvmf_ctrl_options *opts); +void nvmf_set_io_queues(struct nvmf_ctrl_options *opts, u32 nr_io_queues, + u32 io_queues[HCTX_MAX_TYPES]); +void nvmf_map_queues(struct blk_mq_tag_set *set, struct nvme_ctrl *ctrl, + u32 io_queues[HCTX_MAX_TYPES]); #endif /* _NVME_FABRICS_H */ diff --git a/drivers/nvme/host/fault_inject.c b/drivers/nvme/host/fault_inject.c index 83d2e6860d388bfb05be3b8813b8d0ea2733aaf8..1ba10a5c656d1da4545da8f53b963b56d4357bc0 100644 --- a/drivers/nvme/host/fault_inject.c +++ b/drivers/nvme/host/fault_inject.c @@ -27,7 +27,7 @@ void nvme_fault_inject_init(struct nvme_fault_inject *fault_inj, /* create debugfs directory and attribute */ parent = debugfs_create_dir(dev_name, NULL); - if (!parent) { + if (IS_ERR(parent)) { pr_warn("%s: failed to create debugfs directory\n", dev_name); return; } diff --git a/drivers/nvme/host/fc.c b/drivers/nvme/host/fc.c index 2ed75923507dab39e6e1aef5404c8c425bc9261b..1cd2bf82319a988021cbb04d311ebee3dc017bed 100644 --- a/drivers/nvme/host/fc.c +++ b/drivers/nvme/host/fc.c @@ -2548,14 +2548,24 @@ nvme_fc_error_recovery(struct nvme_fc_ctrl *ctrl, char *errmsg) * the controller. Abort any ios on the association and let the * create_association error path resolve things. */ - if (ctrl->ctrl.state == NVME_CTRL_CONNECTING) { - __nvme_fc_abort_outstanding_ios(ctrl, true); + enum nvme_ctrl_state state; + unsigned long flags; + + spin_lock_irqsave(&ctrl->lock, flags); + state = ctrl->ctrl.state; + if (state == NVME_CTRL_CONNECTING) { set_bit(ASSOC_FAILED, &ctrl->flags); + spin_unlock_irqrestore(&ctrl->lock, flags); + __nvme_fc_abort_outstanding_ios(ctrl, true); + dev_warn(ctrl->ctrl.device, + "NVME-FC{%d}: transport error during (re)connect\n", + ctrl->cnum); return; } + spin_unlock_irqrestore(&ctrl->lock, flags); /* Otherwise, only proceed if in LIVE state - e.g. on first error */ - if (ctrl->ctrl.state != NVME_CTRL_LIVE) + if (state != NVME_CTRL_LIVE) return; dev_warn(ctrl->ctrl.device, @@ -2917,8 +2927,8 @@ nvme_fc_create_io_queues(struct nvme_fc_ctrl *ctrl) ret = nvme_alloc_io_tag_set(&ctrl->ctrl, &ctrl->tag_set, &nvme_fc_mq_ops, 1, - struct_size((struct nvme_fcp_op_w_sgl *)NULL, priv, - ctrl->lport->ops->fcprqst_priv_sz)); + struct_size_t(struct nvme_fcp_op_w_sgl, priv, + ctrl->lport->ops->fcprqst_priv_sz)); if (ret) return ret; @@ -3110,7 +3120,9 @@ nvme_fc_create_association(struct nvme_fc_ctrl *ctrl) */ ret = nvme_enable_ctrl(&ctrl->ctrl); - if (ret || test_bit(ASSOC_FAILED, &ctrl->flags)) + if (!ret && test_bit(ASSOC_FAILED, &ctrl->flags)) + ret = -EIO; + if (ret) goto out_disconnect_admin_queue; ctrl->ctrl.max_segments = ctrl->lport->ops->max_sgl_segments; @@ -3120,7 +3132,9 @@ nvme_fc_create_association(struct nvme_fc_ctrl *ctrl) nvme_unquiesce_admin_queue(&ctrl->ctrl); ret = nvme_init_ctrl_finish(&ctrl->ctrl, false); - if (ret || test_bit(ASSOC_FAILED, &ctrl->flags)) + if (!ret && test_bit(ASSOC_FAILED, &ctrl->flags)) + ret = -EIO; + if (ret) goto out_disconnect_admin_queue; /* sanity checks */ @@ -3165,10 +3179,16 @@ nvme_fc_create_association(struct nvme_fc_ctrl *ctrl) else ret = nvme_fc_recreate_io_queues(ctrl); } - if (ret || test_bit(ASSOC_FAILED, &ctrl->flags)) - goto out_term_aen_ops; + spin_lock_irqsave(&ctrl->lock, flags); + if (!ret && test_bit(ASSOC_FAILED, &ctrl->flags)) + ret = -EIO; + if (ret) { + spin_unlock_irqrestore(&ctrl->lock, flags); + goto out_term_aen_ops; + } changed = nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_LIVE); + spin_unlock_irqrestore(&ctrl->lock, flags); ctrl->ctrl.nr_reconnects = 0; @@ -3180,6 +3200,9 @@ nvme_fc_create_association(struct nvme_fc_ctrl *ctrl) out_term_aen_ops: nvme_fc_term_aen_ops(ctrl); out_disconnect_admin_queue: + dev_warn(ctrl->ctrl.device, + "NVME-FC{%d}: create_assoc failed, assoc_id %llx ret %d\n", + ctrl->cnum, ctrl->association_id, ret); /* send a Disconnect(association) LS to fc-nvme target */ nvme_fc_xmt_disconnect_assoc(ctrl); spin_lock_irqsave(&ctrl->lock, flags); @@ -3536,8 +3559,8 @@ nvme_fc_init_ctrl(struct device *dev, struct nvmf_ctrl_options *opts, ret = nvme_alloc_admin_tag_set(&ctrl->ctrl, &ctrl->admin_tag_set, &nvme_fc_admin_mq_ops, - struct_size((struct nvme_fcp_op_w_sgl *)NULL, priv, - ctrl->lport->ops->fcprqst_priv_sz)); + struct_size_t(struct nvme_fcp_op_w_sgl, priv, + ctrl->lport->ops->fcprqst_priv_sz)); if (ret) goto fail_ctrl; diff --git a/drivers/nvme/host/ioctl.c b/drivers/nvme/host/ioctl.c index f15e7330b75ac5c310bf05f88cd1275469461097..5c3250f36ce7764beccef76510a85c6999eb4daa 100644 --- a/drivers/nvme/host/ioctl.c +++ b/drivers/nvme/host/ioctl.c @@ -14,7 +14,7 @@ enum { }; static bool nvme_cmd_allowed(struct nvme_ns *ns, struct nvme_command *c, - unsigned int flags, fmode_t mode) + unsigned int flags, bool open_for_write) { u32 effects; @@ -80,7 +80,7 @@ static bool nvme_cmd_allowed(struct nvme_ns *ns, struct nvme_command *c, * writing. */ if (nvme_is_write(c) || (effects & NVME_CMD_EFFECTS_LBCC)) - return mode & FMODE_WRITE; + return open_for_write; return true; } @@ -337,7 +337,7 @@ static bool nvme_validate_passthru_nsid(struct nvme_ctrl *ctrl, static int nvme_user_cmd(struct nvme_ctrl *ctrl, struct nvme_ns *ns, struct nvme_passthru_cmd __user *ucmd, unsigned int flags, - fmode_t mode) + bool open_for_write) { struct nvme_passthru_cmd cmd; struct nvme_command c; @@ -365,7 +365,7 @@ static int nvme_user_cmd(struct nvme_ctrl *ctrl, struct nvme_ns *ns, c.common.cdw14 = cpu_to_le32(cmd.cdw14); c.common.cdw15 = cpu_to_le32(cmd.cdw15); - if (!nvme_cmd_allowed(ns, &c, 0, mode)) + if (!nvme_cmd_allowed(ns, &c, 0, open_for_write)) return -EACCES; if (cmd.timeout_ms) @@ -385,7 +385,7 @@ static int nvme_user_cmd(struct nvme_ctrl *ctrl, struct nvme_ns *ns, static int nvme_user_cmd64(struct nvme_ctrl *ctrl, struct nvme_ns *ns, struct nvme_passthru_cmd64 __user *ucmd, unsigned int flags, - fmode_t mode) + bool open_for_write) { struct nvme_passthru_cmd64 cmd; struct nvme_command c; @@ -412,7 +412,7 @@ static int nvme_user_cmd64(struct nvme_ctrl *ctrl, struct nvme_ns *ns, c.common.cdw14 = cpu_to_le32(cmd.cdw14); c.common.cdw15 = cpu_to_le32(cmd.cdw15); - if (!nvme_cmd_allowed(ns, &c, flags, mode)) + if (!nvme_cmd_allowed(ns, &c, flags, open_for_write)) return -EACCES; if (cmd.timeout_ms) @@ -505,7 +505,6 @@ static enum rq_end_io_ret nvme_uring_cmd_end_io(struct request *req, { struct io_uring_cmd *ioucmd = req->end_io_data; struct nvme_uring_cmd_pdu *pdu = nvme_uring_cmd_pdu(ioucmd); - void *cookie = READ_ONCE(ioucmd->cookie); req->bio = pdu->bio; if (nvme_req(req)->flags & NVME_REQ_CANCELLED) @@ -518,10 +517,12 @@ static enum rq_end_io_ret nvme_uring_cmd_end_io(struct request *req, * For iopoll, complete it directly. * Otherwise, move the completion to task work. */ - if (cookie != NULL && blk_rq_is_poll(req)) + if (blk_rq_is_poll(req)) { + WRITE_ONCE(ioucmd->cookie, NULL); nvme_uring_task_cb(ioucmd, IO_URING_F_UNLOCKED); - else - io_uring_cmd_complete_in_task(ioucmd, nvme_uring_task_cb); + } else { + io_uring_cmd_do_in_task_lazy(ioucmd, nvme_uring_task_cb); + } return RQ_END_IO_FREE; } @@ -531,7 +532,6 @@ static enum rq_end_io_ret nvme_uring_cmd_end_io_meta(struct request *req, { struct io_uring_cmd *ioucmd = req->end_io_data; struct nvme_uring_cmd_pdu *pdu = nvme_uring_cmd_pdu(ioucmd); - void *cookie = READ_ONCE(ioucmd->cookie); req->bio = pdu->bio; pdu->req = req; @@ -540,10 +540,12 @@ static enum rq_end_io_ret nvme_uring_cmd_end_io_meta(struct request *req, * For iopoll, complete it directly. * Otherwise, move the completion to task work. */ - if (cookie != NULL && blk_rq_is_poll(req)) + if (blk_rq_is_poll(req)) { + WRITE_ONCE(ioucmd->cookie, NULL); nvme_uring_task_meta_cb(ioucmd, IO_URING_F_UNLOCKED); - else - io_uring_cmd_complete_in_task(ioucmd, nvme_uring_task_meta_cb); + } else { + io_uring_cmd_do_in_task_lazy(ioucmd, nvme_uring_task_meta_cb); + } return RQ_END_IO_NONE; } @@ -583,7 +585,7 @@ static int nvme_uring_cmd_io(struct nvme_ctrl *ctrl, struct nvme_ns *ns, c.common.cdw14 = cpu_to_le32(READ_ONCE(cmd->cdw14)); c.common.cdw15 = cpu_to_le32(READ_ONCE(cmd->cdw15)); - if (!nvme_cmd_allowed(ns, &c, 0, ioucmd->file->f_mode)) + if (!nvme_cmd_allowed(ns, &c, 0, ioucmd->file->f_mode & FMODE_WRITE)) return -EACCES; d.metadata = READ_ONCE(cmd->metadata); @@ -599,7 +601,6 @@ static int nvme_uring_cmd_io(struct nvme_ctrl *ctrl, struct nvme_ns *ns, if (issue_flags & IO_URING_F_IOPOLL) rq_flags |= REQ_POLLED; -retry: req = nvme_alloc_user_request(q, &c, rq_flags, blk_flags); if (IS_ERR(req)) return PTR_ERR(req); @@ -613,17 +614,11 @@ static int nvme_uring_cmd_io(struct nvme_ctrl *ctrl, struct nvme_ns *ns, return ret; } - if (issue_flags & IO_URING_F_IOPOLL && rq_flags & REQ_POLLED) { - if (unlikely(!req->bio)) { - /* we can't poll this, so alloc regular req instead */ - blk_mq_free_request(req); - rq_flags &= ~REQ_POLLED; - goto retry; - } else { - WRITE_ONCE(ioucmd->cookie, req->bio); - req->bio->bi_opf |= REQ_POLLED; - } + if (blk_rq_is_poll(req)) { + ioucmd->flags |= IORING_URING_CMD_POLLED; + WRITE_ONCE(ioucmd->cookie, req); } + /* to free bio on completion, as req->bio will be null at that time */ pdu->bio = req->bio; pdu->meta_len = d.metadata_len; @@ -649,13 +644,13 @@ static bool is_ctrl_ioctl(unsigned int cmd) } static int nvme_ctrl_ioctl(struct nvme_ctrl *ctrl, unsigned int cmd, - void __user *argp, fmode_t mode) + void __user *argp, bool open_for_write) { switch (cmd) { case NVME_IOCTL_ADMIN_CMD: - return nvme_user_cmd(ctrl, NULL, argp, 0, mode); + return nvme_user_cmd(ctrl, NULL, argp, 0, open_for_write); case NVME_IOCTL_ADMIN64_CMD: - return nvme_user_cmd64(ctrl, NULL, argp, 0, mode); + return nvme_user_cmd64(ctrl, NULL, argp, 0, open_for_write); default: return sed_ioctl(ctrl->opal_dev, cmd, argp); } @@ -680,14 +675,14 @@ struct nvme_user_io32 { #endif /* COMPAT_FOR_U64_ALIGNMENT */ static int nvme_ns_ioctl(struct nvme_ns *ns, unsigned int cmd, - void __user *argp, unsigned int flags, fmode_t mode) + void __user *argp, unsigned int flags, bool open_for_write) { switch (cmd) { case NVME_IOCTL_ID: force_successful_syscall_return(); return ns->head->ns_id; case NVME_IOCTL_IO_CMD: - return nvme_user_cmd(ns->ctrl, ns, argp, flags, mode); + return nvme_user_cmd(ns->ctrl, ns, argp, flags, open_for_write); /* * struct nvme_user_io can have different padding on some 32-bit ABIs. * Just accept the compat version as all fields that are used are the @@ -702,16 +697,18 @@ static int nvme_ns_ioctl(struct nvme_ns *ns, unsigned int cmd, flags |= NVME_IOCTL_VEC; fallthrough; case NVME_IOCTL_IO64_CMD: - return nvme_user_cmd64(ns->ctrl, ns, argp, flags, mode); + return nvme_user_cmd64(ns->ctrl, ns, argp, flags, + open_for_write); default: return -ENOTTY; } } -int nvme_ioctl(struct block_device *bdev, fmode_t mode, +int nvme_ioctl(struct block_device *bdev, blk_mode_t mode, unsigned int cmd, unsigned long arg) { struct nvme_ns *ns = bdev->bd_disk->private_data; + bool open_for_write = mode & BLK_OPEN_WRITE; void __user *argp = (void __user *)arg; unsigned int flags = 0; @@ -719,19 +716,20 @@ int nvme_ioctl(struct block_device *bdev, fmode_t mode, flags |= NVME_IOCTL_PARTITION; if (is_ctrl_ioctl(cmd)) - return nvme_ctrl_ioctl(ns->ctrl, cmd, argp, mode); - return nvme_ns_ioctl(ns, cmd, argp, flags, mode); + return nvme_ctrl_ioctl(ns->ctrl, cmd, argp, open_for_write); + return nvme_ns_ioctl(ns, cmd, argp, flags, open_for_write); } long nvme_ns_chr_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct nvme_ns *ns = container_of(file_inode(file)->i_cdev, struct nvme_ns, cdev); + bool open_for_write = file->f_mode & FMODE_WRITE; void __user *argp = (void __user *)arg; if (is_ctrl_ioctl(cmd)) - return nvme_ctrl_ioctl(ns->ctrl, cmd, argp, file->f_mode); - return nvme_ns_ioctl(ns, cmd, argp, 0, file->f_mode); + return nvme_ctrl_ioctl(ns->ctrl, cmd, argp, open_for_write); + return nvme_ns_ioctl(ns, cmd, argp, 0, open_for_write); } static int nvme_uring_cmd_checks(unsigned int issue_flags) @@ -782,25 +780,23 @@ int nvme_ns_chr_uring_cmd_iopoll(struct io_uring_cmd *ioucmd, struct io_comp_batch *iob, unsigned int poll_flags) { - struct bio *bio; + struct request *req; int ret = 0; - struct nvme_ns *ns; - struct request_queue *q; + + if (!(ioucmd->flags & IORING_URING_CMD_POLLED)) + return 0; rcu_read_lock(); - bio = READ_ONCE(ioucmd->cookie); - ns = container_of(file_inode(ioucmd->file)->i_cdev, - struct nvme_ns, cdev); - q = ns->queue; - if (test_bit(QUEUE_FLAG_POLL, &q->queue_flags) && bio && bio->bi_bdev) - ret = bio_poll(bio, iob, poll_flags); + req = READ_ONCE(ioucmd->cookie); + if (req && blk_rq_is_poll(req)) + ret = blk_rq_poll(req, iob, poll_flags); rcu_read_unlock(); return ret; } #ifdef CONFIG_NVME_MULTIPATH static int nvme_ns_head_ctrl_ioctl(struct nvme_ns *ns, unsigned int cmd, void __user *argp, struct nvme_ns_head *head, int srcu_idx, - fmode_t mode) + bool open_for_write) __releases(&head->srcu) { struct nvme_ctrl *ctrl = ns->ctrl; @@ -808,16 +804,17 @@ static int nvme_ns_head_ctrl_ioctl(struct nvme_ns *ns, unsigned int cmd, nvme_get_ctrl(ns->ctrl); srcu_read_unlock(&head->srcu, srcu_idx); - ret = nvme_ctrl_ioctl(ns->ctrl, cmd, argp, mode); + ret = nvme_ctrl_ioctl(ns->ctrl, cmd, argp, open_for_write); nvme_put_ctrl(ctrl); return ret; } -int nvme_ns_head_ioctl(struct block_device *bdev, fmode_t mode, +int nvme_ns_head_ioctl(struct block_device *bdev, blk_mode_t mode, unsigned int cmd, unsigned long arg) { struct nvme_ns_head *head = bdev->bd_disk->private_data; + bool open_for_write = mode & BLK_OPEN_WRITE; void __user *argp = (void __user *)arg; struct nvme_ns *ns; int srcu_idx, ret = -EWOULDBLOCK; @@ -838,9 +835,9 @@ int nvme_ns_head_ioctl(struct block_device *bdev, fmode_t mode, */ if (is_ctrl_ioctl(cmd)) return nvme_ns_head_ctrl_ioctl(ns, cmd, argp, head, srcu_idx, - mode); + open_for_write); - ret = nvme_ns_ioctl(ns, cmd, argp, flags, mode); + ret = nvme_ns_ioctl(ns, cmd, argp, flags, open_for_write); out_unlock: srcu_read_unlock(&head->srcu, srcu_idx); return ret; @@ -849,6 +846,7 @@ int nvme_ns_head_ioctl(struct block_device *bdev, fmode_t mode, long nvme_ns_head_chr_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { + bool open_for_write = file->f_mode & FMODE_WRITE; struct cdev *cdev = file_inode(file)->i_cdev; struct nvme_ns_head *head = container_of(cdev, struct nvme_ns_head, cdev); @@ -863,9 +861,9 @@ long nvme_ns_head_chr_ioctl(struct file *file, unsigned int cmd, if (is_ctrl_ioctl(cmd)) return nvme_ns_head_ctrl_ioctl(ns, cmd, argp, head, srcu_idx, - file->f_mode); + open_for_write); - ret = nvme_ns_ioctl(ns, cmd, argp, 0, file->f_mode); + ret = nvme_ns_ioctl(ns, cmd, argp, 0, open_for_write); out_unlock: srcu_read_unlock(&head->srcu, srcu_idx); return ret; @@ -885,31 +883,6 @@ int nvme_ns_head_chr_uring_cmd(struct io_uring_cmd *ioucmd, srcu_read_unlock(&head->srcu, srcu_idx); return ret; } - -int nvme_ns_head_chr_uring_cmd_iopoll(struct io_uring_cmd *ioucmd, - struct io_comp_batch *iob, - unsigned int poll_flags) -{ - struct cdev *cdev = file_inode(ioucmd->file)->i_cdev; - struct nvme_ns_head *head = container_of(cdev, struct nvme_ns_head, cdev); - int srcu_idx = srcu_read_lock(&head->srcu); - struct nvme_ns *ns = nvme_find_path(head); - struct bio *bio; - int ret = 0; - struct request_queue *q; - - if (ns) { - rcu_read_lock(); - bio = READ_ONCE(ioucmd->cookie); - q = ns->queue; - if (test_bit(QUEUE_FLAG_POLL, &q->queue_flags) && bio - && bio->bi_bdev) - ret = bio_poll(bio, iob, poll_flags); - rcu_read_unlock(); - } - srcu_read_unlock(&head->srcu, srcu_idx); - return ret; -} #endif /* CONFIG_NVME_MULTIPATH */ int nvme_dev_uring_cmd(struct io_uring_cmd *ioucmd, unsigned int issue_flags) @@ -940,7 +913,7 @@ int nvme_dev_uring_cmd(struct io_uring_cmd *ioucmd, unsigned int issue_flags) } static int nvme_dev_user_cmd(struct nvme_ctrl *ctrl, void __user *argp, - fmode_t mode) + bool open_for_write) { struct nvme_ns *ns; int ret; @@ -964,7 +937,7 @@ static int nvme_dev_user_cmd(struct nvme_ctrl *ctrl, void __user *argp, kref_get(&ns->kref); up_read(&ctrl->namespaces_rwsem); - ret = nvme_user_cmd(ctrl, ns, argp, 0, mode); + ret = nvme_user_cmd(ctrl, ns, argp, 0, open_for_write); nvme_put_ns(ns); return ret; @@ -976,16 +949,17 @@ static int nvme_dev_user_cmd(struct nvme_ctrl *ctrl, void __user *argp, long nvme_dev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { + bool open_for_write = file->f_mode & FMODE_WRITE; struct nvme_ctrl *ctrl = file->private_data; void __user *argp = (void __user *)arg; switch (cmd) { case NVME_IOCTL_ADMIN_CMD: - return nvme_user_cmd(ctrl, NULL, argp, 0, file->f_mode); + return nvme_user_cmd(ctrl, NULL, argp, 0, open_for_write); case NVME_IOCTL_ADMIN64_CMD: - return nvme_user_cmd64(ctrl, NULL, argp, 0, file->f_mode); + return nvme_user_cmd64(ctrl, NULL, argp, 0, open_for_write); case NVME_IOCTL_IO_CMD: - return nvme_dev_user_cmd(ctrl, argp, file->f_mode); + return nvme_dev_user_cmd(ctrl, argp, open_for_write); case NVME_IOCTL_RESET: if (!capable(CAP_SYS_ADMIN)) return -EACCES; diff --git a/drivers/nvme/host/multipath.c b/drivers/nvme/host/multipath.c index 2bc159a318ff0af19a06aa668aeb94bf8167ff1d..0a88d7bdc5e370b5eea95020988df4a0b708dcda 100644 --- a/drivers/nvme/host/multipath.c +++ b/drivers/nvme/host/multipath.c @@ -106,6 +106,14 @@ void nvme_failover_req(struct request *req) bio->bi_opf &= ~REQ_POLLED; bio->bi_cookie = BLK_QC_T_NONE; } + /* + * The alternate request queue that we may end up submitting + * the bio to may be frozen temporarily, in this case REQ_NOWAIT + * will fail the I/O immediately with EAGAIN to the issuer. + * We are not in the issuer context which cannot block. Clear + * the flag to avoid spurious EAGAIN I/O failures. + */ + bio->bi_opf &= ~REQ_NOWAIT; } blk_steal_bios(&ns->head->requeue_list, req); spin_unlock_irqrestore(&ns->head->requeue_lock, flags); @@ -402,14 +410,14 @@ static void nvme_ns_head_submit_bio(struct bio *bio) srcu_read_unlock(&head->srcu, srcu_idx); } -static int nvme_ns_head_open(struct block_device *bdev, fmode_t mode) +static int nvme_ns_head_open(struct gendisk *disk, blk_mode_t mode) { - if (!nvme_tryget_ns_head(bdev->bd_disk->private_data)) + if (!nvme_tryget_ns_head(disk->private_data)) return -ENXIO; return 0; } -static void nvme_ns_head_release(struct gendisk *disk, fmode_t mode) +static void nvme_ns_head_release(struct gendisk *disk) { nvme_put_ns_head(disk->private_data); } @@ -470,7 +478,7 @@ static const struct file_operations nvme_ns_head_chr_fops = { .unlocked_ioctl = nvme_ns_head_chr_ioctl, .compat_ioctl = compat_ptr_ioctl, .uring_cmd = nvme_ns_head_chr_uring_cmd, - .uring_cmd_iopoll = nvme_ns_head_chr_uring_cmd_iopoll, + .uring_cmd_iopoll = nvme_ns_chr_uring_cmd_iopoll, }; static int nvme_add_ns_head_cdev(struct nvme_ns_head *head) diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h index 8657811f8b8875e21a53732252d7f0738c85d678..f35647c470afad09182a722cd6ae30991562dcb5 100644 --- a/drivers/nvme/host/nvme.h +++ b/drivers/nvme/host/nvme.h @@ -19,6 +19,8 @@ #include +extern const struct pr_ops nvme_pr_ops; + extern unsigned int nvme_io_timeout; #define NVME_IO_TIMEOUT (nvme_io_timeout * HZ) @@ -247,12 +249,14 @@ enum nvme_ctrl_flags { NVME_CTRL_ADMIN_Q_STOPPED = 1, NVME_CTRL_STARTED_ONCE = 2, NVME_CTRL_STOPPED = 3, + NVME_CTRL_SKIP_ID_CNS_CS = 4, + NVME_CTRL_DIRTY_CAPABILITY = 5, }; struct nvme_ctrl { bool comp_seen; - enum nvme_ctrl_state state; bool identified; + enum nvme_ctrl_state state; spinlock_t lock; struct mutex scan_lock; const struct nvme_ctrl_ops *ops; @@ -284,8 +288,8 @@ struct nvme_ctrl { char name[12]; u16 cntlid; - u32 ctrl_config; u16 mtfa; + u32 ctrl_config; u32 queue_count; u64 cap; @@ -359,10 +363,10 @@ struct nvme_ctrl { bool apst_enabled; /* PCIe only: */ + u16 hmmaxd; u32 hmpre; u32 hmmin; u32 hmminds; - u16 hmmaxd; /* Fabrics only */ u32 ioccsz; @@ -842,10 +846,10 @@ void nvme_put_ns_head(struct nvme_ns_head *head); int nvme_cdev_add(struct cdev *cdev, struct device *cdev_device, const struct file_operations *fops, struct module *owner); void nvme_cdev_del(struct cdev *cdev, struct device *cdev_device); -int nvme_ioctl(struct block_device *bdev, fmode_t mode, +int nvme_ioctl(struct block_device *bdev, blk_mode_t mode, unsigned int cmd, unsigned long arg); long nvme_ns_chr_ioctl(struct file *file, unsigned int cmd, unsigned long arg); -int nvme_ns_head_ioctl(struct block_device *bdev, fmode_t mode, +int nvme_ns_head_ioctl(struct block_device *bdev, blk_mode_t mode, unsigned int cmd, unsigned long arg); long nvme_ns_head_chr_ioctl(struct file *file, unsigned int cmd, unsigned long arg); @@ -853,8 +857,6 @@ long nvme_dev_ioctl(struct file *file, unsigned int cmd, unsigned long arg); int nvme_ns_chr_uring_cmd_iopoll(struct io_uring_cmd *ioucmd, struct io_comp_batch *iob, unsigned int poll_flags); -int nvme_ns_head_chr_uring_cmd_iopoll(struct io_uring_cmd *ioucmd, - struct io_comp_batch *iob, unsigned int poll_flags); int nvme_ns_chr_uring_cmd(struct io_uring_cmd *ioucmd, unsigned int issue_flags); int nvme_ns_head_chr_uring_cmd(struct io_uring_cmd *ioucmd, @@ -866,7 +868,11 @@ extern const struct attribute_group *nvme_ns_id_attr_groups[]; extern const struct pr_ops nvme_pr_ops; extern const struct block_device_operations nvme_ns_head_ops; extern const struct attribute_group nvme_dev_attrs_group; +extern const struct attribute_group *nvme_subsys_attrs_groups[]; +extern const struct attribute_group *nvme_dev_attr_groups[]; +extern const struct block_device_operations nvme_bdev_ops; +void nvme_delete_ctrl_sync(struct nvme_ctrl *ctrl); struct nvme_ns *nvme_find_path(struct nvme_ns_head *head); #ifdef CONFIG_NVME_MULTIPATH static inline bool nvme_ctrl_use_ana(struct nvme_ctrl *ctrl) diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c index 492f319ebdf37ad838dacbb5237f1a804b243840..baf69af7ea78efd27e57c1c2cfe763ff17867c4e 100644 --- a/drivers/nvme/host/pci.c +++ b/drivers/nvme/host/pci.c @@ -420,10 +420,9 @@ static int nvme_pci_init_request(struct blk_mq_tag_set *set, struct request *req, unsigned int hctx_idx, unsigned int numa_node) { - struct nvme_dev *dev = to_nvme_dev(set->driver_data); struct nvme_iod *iod = blk_mq_rq_to_pdu(req); - nvme_req(req)->ctrl = &dev->ctrl; + nvme_req(req)->ctrl = set->driver_data; nvme_req(req)->cmd = &iod->cmd; return 0; } @@ -968,7 +967,7 @@ static __always_inline void nvme_pci_unmap_rq(struct request *req) struct nvme_iod *iod = blk_mq_rq_to_pdu(req); dma_unmap_page(dev->dev, iod->meta_dma, - rq_integrity_vec(req)->bv_len, rq_data_dir(req)); + rq_integrity_vec(req)->bv_len, rq_dma_dir(req)); } if (blk_rq_nr_phys_segments(req)) @@ -1299,9 +1298,7 @@ static enum blk_eh_timer_return nvme_timeout(struct request *req) */ if (nvme_should_reset(dev, csts)) { nvme_warn_reset(dev, csts); - nvme_dev_disable(dev, false); - nvme_reset_ctrl(&dev->ctrl); - return BLK_EH_DONE; + goto disable; } /* @@ -1352,10 +1349,7 @@ static enum blk_eh_timer_return nvme_timeout(struct request *req) "I/O %d QID %d timeout, reset controller\n", req->tag, nvmeq->qid); nvme_req(req)->flags |= NVME_REQ_CANCELLED; - nvme_dev_disable(dev, false); - nvme_reset_ctrl(&dev->ctrl); - - return BLK_EH_DONE; + goto disable; } if (atomic_dec_return(&dev->ctrl.abort_limit) < 0) { @@ -1392,6 +1386,15 @@ static enum blk_eh_timer_return nvme_timeout(struct request *req) * as the device then is in a faulty state. */ return BLK_EH_RESET_TIMER; + +disable: + if (!nvme_change_ctrl_state(&dev->ctrl, NVME_CTRL_RESETTING)) + return BLK_EH_DONE; + + nvme_dev_disable(dev, false); + if (nvme_try_sched_reset(&dev->ctrl)) + nvme_unquiesce_io_queues(&dev->ctrl); + return BLK_EH_DONE; } static void nvme_free_queue(struct nvme_queue *nvmeq) @@ -2691,7 +2694,8 @@ static void nvme_reset_work(struct work_struct *work) if (dev->ctrl.state != NVME_CTRL_RESETTING) { dev_warn(dev->ctrl.device, "ctrl state %d is not RESETTING\n", dev->ctrl.state); - return; + result = -ENODEV; + goto out; } /* @@ -2778,7 +2782,9 @@ static void nvme_reset_work(struct work_struct *work) result); nvme_change_ctrl_state(&dev->ctrl, NVME_CTRL_DELETING); nvme_dev_disable(dev, true); + nvme_sync_queues(&dev->ctrl); nvme_mark_namespaces_dead(&dev->ctrl); + nvme_unquiesce_io_queues(&dev->ctrl); nvme_change_ctrl_state(&dev->ctrl, NVME_CTRL_DEAD); } @@ -3276,6 +3282,10 @@ static pci_ers_result_t nvme_error_detected(struct pci_dev *pdev, case pci_channel_io_frozen: dev_warn(dev->ctrl.device, "frozen state error detected, reset controller\n"); + if (!nvme_change_ctrl_state(&dev->ctrl, NVME_CTRL_RESETTING)) { + nvme_dev_disable(dev, true); + return PCI_ERS_RESULT_DISCONNECT; + } nvme_dev_disable(dev, false); return PCI_ERS_RESULT_NEED_RESET; case pci_channel_io_perm_failure: @@ -3292,7 +3302,8 @@ static pci_ers_result_t nvme_slot_reset(struct pci_dev *pdev) dev_info(dev->ctrl.device, "restart after slot reset\n"); pci_restore_state(pdev); - nvme_reset_ctrl(&dev->ctrl); + if (!nvme_try_sched_reset(&dev->ctrl)) + nvme_unquiesce_io_queues(&dev->ctrl); return PCI_ERS_RESULT_RECOVERED; } @@ -3394,6 +3405,8 @@ static const struct pci_device_id nvme_id_table[] = { .driver_data = NVME_QUIRK_DISABLE_WRITE_ZEROES, }, { PCI_DEVICE(0x144d, 0xa809), /* Samsung MZALQ256HBJD 256G */ .driver_data = NVME_QUIRK_DISABLE_WRITE_ZEROES, }, + { PCI_DEVICE(0x144d, 0xa802), /* Samsung SM953 */ + .driver_data = NVME_QUIRK_BOGUS_NID, }, { PCI_DEVICE(0x1cc4, 0x6303), /* UMIS RPJTJ512MGE1QDY 512G */ .driver_data = NVME_QUIRK_DISABLE_WRITE_ZEROES, }, { PCI_DEVICE(0x1cc4, 0x6302), /* UMIS RPJTJ256MGE1QDY 256G */ diff --git a/drivers/nvme/host/pr.c b/drivers/nvme/host/pr.c new file mode 100644 index 0000000000000000000000000000000000000000..391b1465ebfd5e0067dfb698f8bd199a9fe3d148 --- /dev/null +++ b/drivers/nvme/host/pr.c @@ -0,0 +1,315 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2015 Intel Corporation + * Keith Busch + */ +#include +#include +#include + +#include "nvme.h" + +static enum nvme_pr_type nvme_pr_type_from_blk(enum pr_type type) +{ + switch (type) { + case PR_WRITE_EXCLUSIVE: + return NVME_PR_WRITE_EXCLUSIVE; + case PR_EXCLUSIVE_ACCESS: + return NVME_PR_EXCLUSIVE_ACCESS; + case PR_WRITE_EXCLUSIVE_REG_ONLY: + return NVME_PR_WRITE_EXCLUSIVE_REG_ONLY; + case PR_EXCLUSIVE_ACCESS_REG_ONLY: + return NVME_PR_EXCLUSIVE_ACCESS_REG_ONLY; + case PR_WRITE_EXCLUSIVE_ALL_REGS: + return NVME_PR_WRITE_EXCLUSIVE_ALL_REGS; + case PR_EXCLUSIVE_ACCESS_ALL_REGS: + return NVME_PR_EXCLUSIVE_ACCESS_ALL_REGS; + } + + return 0; +} + +static enum pr_type block_pr_type_from_nvme(enum nvme_pr_type type) +{ + switch (type) { + case NVME_PR_WRITE_EXCLUSIVE: + return PR_WRITE_EXCLUSIVE; + case NVME_PR_EXCLUSIVE_ACCESS: + return PR_EXCLUSIVE_ACCESS; + case NVME_PR_WRITE_EXCLUSIVE_REG_ONLY: + return PR_WRITE_EXCLUSIVE_REG_ONLY; + case NVME_PR_EXCLUSIVE_ACCESS_REG_ONLY: + return PR_EXCLUSIVE_ACCESS_REG_ONLY; + case NVME_PR_WRITE_EXCLUSIVE_ALL_REGS: + return PR_WRITE_EXCLUSIVE_ALL_REGS; + case NVME_PR_EXCLUSIVE_ACCESS_ALL_REGS: + return PR_EXCLUSIVE_ACCESS_ALL_REGS; + } + + return 0; +} + +static int nvme_send_ns_head_pr_command(struct block_device *bdev, + struct nvme_command *c, void *data, unsigned int data_len) +{ + struct nvme_ns_head *head = bdev->bd_disk->private_data; + int srcu_idx = srcu_read_lock(&head->srcu); + struct nvme_ns *ns = nvme_find_path(head); + int ret = -EWOULDBLOCK; + + if (ns) { + c->common.nsid = cpu_to_le32(ns->head->ns_id); + ret = nvme_submit_sync_cmd(ns->queue, c, data, data_len); + } + srcu_read_unlock(&head->srcu, srcu_idx); + return ret; +} + +static int nvme_send_ns_pr_command(struct nvme_ns *ns, struct nvme_command *c, + void *data, unsigned int data_len) +{ + c->common.nsid = cpu_to_le32(ns->head->ns_id); + return nvme_submit_sync_cmd(ns->queue, c, data, data_len); +} + +static int nvme_sc_to_pr_err(int nvme_sc) +{ + if (nvme_is_path_error(nvme_sc)) + return PR_STS_PATH_FAILED; + + switch (nvme_sc) { + case NVME_SC_SUCCESS: + return PR_STS_SUCCESS; + case NVME_SC_RESERVATION_CONFLICT: + return PR_STS_RESERVATION_CONFLICT; + case NVME_SC_ONCS_NOT_SUPPORTED: + return -EOPNOTSUPP; + case NVME_SC_BAD_ATTRIBUTES: + case NVME_SC_INVALID_OPCODE: + case NVME_SC_INVALID_FIELD: + case NVME_SC_INVALID_NS: + return -EINVAL; + default: + return PR_STS_IOERR; + } +} + +static int nvme_send_pr_command(struct block_device *bdev, + struct nvme_command *c, void *data, unsigned int data_len) +{ + if (IS_ENABLED(CONFIG_NVME_MULTIPATH) && + bdev->bd_disk->fops == &nvme_ns_head_ops) + return nvme_send_ns_head_pr_command(bdev, c, data, data_len); + + return nvme_send_ns_pr_command(bdev->bd_disk->private_data, c, data, + data_len); +} + +static int nvme_pr_command(struct block_device *bdev, u32 cdw10, + u64 key, u64 sa_key, u8 op) +{ + struct nvme_command c = { }; + u8 data[16] = { 0, }; + int ret; + + put_unaligned_le64(key, &data[0]); + put_unaligned_le64(sa_key, &data[8]); + + c.common.opcode = op; + c.common.cdw10 = cpu_to_le32(cdw10); + + ret = nvme_send_pr_command(bdev, &c, data, sizeof(data)); + if (ret < 0) + return ret; + + return nvme_sc_to_pr_err(ret); +} + +static int nvme_pr_register(struct block_device *bdev, u64 old, + u64 new, unsigned flags) +{ + u32 cdw10; + + if (flags & ~PR_FL_IGNORE_KEY) + return -EOPNOTSUPP; + + cdw10 = old ? 2 : 0; + cdw10 |= (flags & PR_FL_IGNORE_KEY) ? 1 << 3 : 0; + cdw10 |= (1 << 30) | (1 << 31); /* PTPL=1 */ + return nvme_pr_command(bdev, cdw10, old, new, nvme_cmd_resv_register); +} + +static int nvme_pr_reserve(struct block_device *bdev, u64 key, + enum pr_type type, unsigned flags) +{ + u32 cdw10; + + if (flags & ~PR_FL_IGNORE_KEY) + return -EOPNOTSUPP; + + cdw10 = nvme_pr_type_from_blk(type) << 8; + cdw10 |= ((flags & PR_FL_IGNORE_KEY) ? 1 << 3 : 0); + return nvme_pr_command(bdev, cdw10, key, 0, nvme_cmd_resv_acquire); +} + +static int nvme_pr_preempt(struct block_device *bdev, u64 old, u64 new, + enum pr_type type, bool abort) +{ + u32 cdw10 = nvme_pr_type_from_blk(type) << 8 | (abort ? 2 : 1); + + return nvme_pr_command(bdev, cdw10, old, new, nvme_cmd_resv_acquire); +} + +static int nvme_pr_clear(struct block_device *bdev, u64 key) +{ + u32 cdw10 = 1 | (key ? 0 : 1 << 3); + + return nvme_pr_command(bdev, cdw10, key, 0, nvme_cmd_resv_release); +} + +static int nvme_pr_release(struct block_device *bdev, u64 key, enum pr_type type) +{ + u32 cdw10 = nvme_pr_type_from_blk(type) << 8 | (key ? 0 : 1 << 3); + + return nvme_pr_command(bdev, cdw10, key, 0, nvme_cmd_resv_release); +} + +static int nvme_pr_resv_report(struct block_device *bdev, void *data, + u32 data_len, bool *eds) +{ + struct nvme_command c = { }; + int ret; + + c.common.opcode = nvme_cmd_resv_report; + c.common.cdw10 = cpu_to_le32(nvme_bytes_to_numd(data_len)); + c.common.cdw11 = cpu_to_le32(NVME_EXTENDED_DATA_STRUCT); + *eds = true; + +retry: + ret = nvme_send_pr_command(bdev, &c, data, data_len); + if (ret == NVME_SC_HOST_ID_INCONSIST && + c.common.cdw11 == cpu_to_le32(NVME_EXTENDED_DATA_STRUCT)) { + c.common.cdw11 = 0; + *eds = false; + goto retry; + } + + if (ret < 0) + return ret; + + return nvme_sc_to_pr_err(ret); +} + +static int nvme_pr_read_keys(struct block_device *bdev, + struct pr_keys *keys_info) +{ + u32 rse_len, num_keys = keys_info->num_keys; + struct nvme_reservation_status_ext *rse; + int ret, i; + bool eds; + + /* + * Assume we are using 128-bit host IDs and allocate a buffer large + * enough to get enough keys to fill the return keys buffer. + */ + rse_len = struct_size(rse, regctl_eds, num_keys); + rse = kzalloc(rse_len, GFP_KERNEL); + if (!rse) + return -ENOMEM; + + ret = nvme_pr_resv_report(bdev, rse, rse_len, &eds); + if (ret) + goto free_rse; + + keys_info->generation = le32_to_cpu(rse->gen); + keys_info->num_keys = get_unaligned_le16(&rse->regctl); + + num_keys = min(num_keys, keys_info->num_keys); + for (i = 0; i < num_keys; i++) { + if (eds) { + keys_info->keys[i] = + le64_to_cpu(rse->regctl_eds[i].rkey); + } else { + struct nvme_reservation_status *rs; + + rs = (struct nvme_reservation_status *)rse; + keys_info->keys[i] = le64_to_cpu(rs->regctl_ds[i].rkey); + } + } + +free_rse: + kfree(rse); + return ret; +} + +static int nvme_pr_read_reservation(struct block_device *bdev, + struct pr_held_reservation *resv) +{ + struct nvme_reservation_status_ext tmp_rse, *rse; + int ret, i, num_regs; + u32 rse_len; + bool eds; + +get_num_regs: + /* + * Get the number of registrations so we know how big to allocate + * the response buffer. + */ + ret = nvme_pr_resv_report(bdev, &tmp_rse, sizeof(tmp_rse), &eds); + if (ret) + return ret; + + num_regs = get_unaligned_le16(&tmp_rse.regctl); + if (!num_regs) { + resv->generation = le32_to_cpu(tmp_rse.gen); + return 0; + } + + rse_len = struct_size(rse, regctl_eds, num_regs); + rse = kzalloc(rse_len, GFP_KERNEL); + if (!rse) + return -ENOMEM; + + ret = nvme_pr_resv_report(bdev, rse, rse_len, &eds); + if (ret) + goto free_rse; + + if (num_regs != get_unaligned_le16(&rse->regctl)) { + kfree(rse); + goto get_num_regs; + } + + resv->generation = le32_to_cpu(rse->gen); + resv->type = block_pr_type_from_nvme(rse->rtype); + + for (i = 0; i < num_regs; i++) { + if (eds) { + if (rse->regctl_eds[i].rcsts) { + resv->key = le64_to_cpu(rse->regctl_eds[i].rkey); + break; + } + } else { + struct nvme_reservation_status *rs; + + rs = (struct nvme_reservation_status *)rse; + if (rs->regctl_ds[i].rcsts) { + resv->key = le64_to_cpu(rs->regctl_ds[i].rkey); + break; + } + } + } + +free_rse: + kfree(rse); + return ret; +} + +const struct pr_ops nvme_pr_ops = { + .pr_register = nvme_pr_register, + .pr_reserve = nvme_pr_reserve, + .pr_release = nvme_pr_release, + .pr_preempt = nvme_pr_preempt, + .pr_clear = nvme_pr_clear, + .pr_read_keys = nvme_pr_read_keys, + .pr_read_reservation = nvme_pr_read_reservation, +}; diff --git a/drivers/nvme/host/rdma.c b/drivers/nvme/host/rdma.c index 0eb79696fb7365c1195be8b8e26fa36dc0eacccc..d433b2ec07a61fdb8ecafb65ad49ca62c67cd487 100644 --- a/drivers/nvme/host/rdma.c +++ b/drivers/nvme/host/rdma.c @@ -501,7 +501,7 @@ static int nvme_rdma_create_queue_ib(struct nvme_rdma_queue *queue) } ibdev = queue->device->dev; - /* +1 for ib_stop_cq */ + /* +1 for ib_drain_qp */ queue->cq_size = cq_factor * queue->queue_size + 1; ret = nvme_rdma_create_cq(ibdev, queue); @@ -713,18 +713,10 @@ static int nvme_rdma_start_io_queues(struct nvme_rdma_ctrl *ctrl, static int nvme_rdma_alloc_io_queues(struct nvme_rdma_ctrl *ctrl) { struct nvmf_ctrl_options *opts = ctrl->ctrl.opts; - struct ib_device *ibdev = ctrl->device->dev; - unsigned int nr_io_queues, nr_default_queues; - unsigned int nr_read_queues, nr_poll_queues; + unsigned int nr_io_queues; int i, ret; - nr_read_queues = min_t(unsigned int, ibdev->num_comp_vectors, - min(opts->nr_io_queues, num_online_cpus())); - nr_default_queues = min_t(unsigned int, ibdev->num_comp_vectors, - min(opts->nr_write_queues, num_online_cpus())); - nr_poll_queues = min(opts->nr_poll_queues, num_online_cpus()); - nr_io_queues = nr_read_queues + nr_default_queues + nr_poll_queues; - + nr_io_queues = nvmf_nr_io_queues(opts); ret = nvme_set_queue_count(&ctrl->ctrl, &nr_io_queues); if (ret) return ret; @@ -739,34 +731,7 @@ static int nvme_rdma_alloc_io_queues(struct nvme_rdma_ctrl *ctrl) dev_info(ctrl->ctrl.device, "creating %d I/O queues.\n", nr_io_queues); - if (opts->nr_write_queues && nr_read_queues < nr_io_queues) { - /* - * separate read/write queues - * hand out dedicated default queues only after we have - * sufficient read queues. - */ - ctrl->io_queues[HCTX_TYPE_READ] = nr_read_queues; - nr_io_queues -= ctrl->io_queues[HCTX_TYPE_READ]; - ctrl->io_queues[HCTX_TYPE_DEFAULT] = - min(nr_default_queues, nr_io_queues); - nr_io_queues -= ctrl->io_queues[HCTX_TYPE_DEFAULT]; - } else { - /* - * shared read/write queues - * either no write queues were requested, or we don't have - * sufficient queue count to have dedicated default queues. - */ - ctrl->io_queues[HCTX_TYPE_DEFAULT] = - min(nr_read_queues, nr_io_queues); - nr_io_queues -= ctrl->io_queues[HCTX_TYPE_DEFAULT]; - } - - if (opts->nr_poll_queues && nr_io_queues) { - /* map dedicated poll queues only if we have queues left */ - ctrl->io_queues[HCTX_TYPE_POLL] = - min(nr_poll_queues, nr_io_queues); - } - + nvmf_set_io_queues(opts, nr_io_queues, ctrl->io_queues); for (i = 1; i < ctrl->ctrl.queue_count; i++) { ret = nvme_rdma_alloc_queue(ctrl, i, ctrl->ctrl.sqsize + 1); @@ -2138,44 +2103,8 @@ static void nvme_rdma_complete_rq(struct request *rq) static void nvme_rdma_map_queues(struct blk_mq_tag_set *set) { struct nvme_rdma_ctrl *ctrl = to_rdma_ctrl(set->driver_data); - struct nvmf_ctrl_options *opts = ctrl->ctrl.opts; - if (opts->nr_write_queues && ctrl->io_queues[HCTX_TYPE_READ]) { - /* separate read/write queues */ - set->map[HCTX_TYPE_DEFAULT].nr_queues = - ctrl->io_queues[HCTX_TYPE_DEFAULT]; - set->map[HCTX_TYPE_DEFAULT].queue_offset = 0; - set->map[HCTX_TYPE_READ].nr_queues = - ctrl->io_queues[HCTX_TYPE_READ]; - set->map[HCTX_TYPE_READ].queue_offset = - ctrl->io_queues[HCTX_TYPE_DEFAULT]; - } else { - /* shared read/write queues */ - set->map[HCTX_TYPE_DEFAULT].nr_queues = - ctrl->io_queues[HCTX_TYPE_DEFAULT]; - set->map[HCTX_TYPE_DEFAULT].queue_offset = 0; - set->map[HCTX_TYPE_READ].nr_queues = - ctrl->io_queues[HCTX_TYPE_DEFAULT]; - set->map[HCTX_TYPE_READ].queue_offset = 0; - } - blk_mq_map_queues(&set->map[HCTX_TYPE_DEFAULT]); - blk_mq_map_queues(&set->map[HCTX_TYPE_READ]); - - if (opts->nr_poll_queues && ctrl->io_queues[HCTX_TYPE_POLL]) { - /* map dedicated poll queues only if we have queues left */ - set->map[HCTX_TYPE_POLL].nr_queues = - ctrl->io_queues[HCTX_TYPE_POLL]; - set->map[HCTX_TYPE_POLL].queue_offset = - ctrl->io_queues[HCTX_TYPE_DEFAULT] + - ctrl->io_queues[HCTX_TYPE_READ]; - blk_mq_map_queues(&set->map[HCTX_TYPE_POLL]); - } - - dev_info(ctrl->ctrl.device, - "mapped %d/%d/%d default/read/poll queues.\n", - ctrl->io_queues[HCTX_TYPE_DEFAULT], - ctrl->io_queues[HCTX_TYPE_READ], - ctrl->io_queues[HCTX_TYPE_POLL]); + nvmf_map_queues(set, &ctrl->ctrl, ctrl->io_queues); } static const struct blk_mq_ops nvme_rdma_mq_ops = { diff --git a/drivers/nvme/host/sysfs.c b/drivers/nvme/host/sysfs.c new file mode 100644 index 0000000000000000000000000000000000000000..212e1b05d2984f7a9d571612cec4e0f3d3f9f834 --- /dev/null +++ b/drivers/nvme/host/sysfs.c @@ -0,0 +1,668 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Sysfs interface for the NVMe core driver. + * + * Copyright (c) 2011-2014, Intel Corporation. + */ + +#include + +#include "nvme.h" +#include "fabrics.h" + +static ssize_t nvme_sysfs_reset(struct device *dev, + struct device_attribute *attr, const char *buf, + size_t count) +{ + struct nvme_ctrl *ctrl = dev_get_drvdata(dev); + int ret; + + ret = nvme_reset_ctrl_sync(ctrl); + if (ret < 0) + return ret; + return count; +} +static DEVICE_ATTR(reset_controller, S_IWUSR, NULL, nvme_sysfs_reset); + +static ssize_t nvme_sysfs_rescan(struct device *dev, + struct device_attribute *attr, const char *buf, + size_t count) +{ + struct nvme_ctrl *ctrl = dev_get_drvdata(dev); + + nvme_queue_scan(ctrl); + return count; +} +static DEVICE_ATTR(rescan_controller, S_IWUSR, NULL, nvme_sysfs_rescan); + +static inline struct nvme_ns_head *dev_to_ns_head(struct device *dev) +{ + struct gendisk *disk = dev_to_disk(dev); + + if (disk->fops == &nvme_bdev_ops) + return nvme_get_ns_from_dev(dev)->head; + else + return disk->private_data; +} + +static ssize_t wwid_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct nvme_ns_head *head = dev_to_ns_head(dev); + struct nvme_ns_ids *ids = &head->ids; + struct nvme_subsystem *subsys = head->subsys; + int serial_len = sizeof(subsys->serial); + int model_len = sizeof(subsys->model); + + if (!uuid_is_null(&ids->uuid)) + return sysfs_emit(buf, "uuid.%pU\n", &ids->uuid); + + if (memchr_inv(ids->nguid, 0, sizeof(ids->nguid))) + return sysfs_emit(buf, "eui.%16phN\n", ids->nguid); + + if (memchr_inv(ids->eui64, 0, sizeof(ids->eui64))) + return sysfs_emit(buf, "eui.%8phN\n", ids->eui64); + + while (serial_len > 0 && (subsys->serial[serial_len - 1] == ' ' || + subsys->serial[serial_len - 1] == '\0')) + serial_len--; + while (model_len > 0 && (subsys->model[model_len - 1] == ' ' || + subsys->model[model_len - 1] == '\0')) + model_len--; + + return sysfs_emit(buf, "nvme.%04x-%*phN-%*phN-%08x\n", subsys->vendor_id, + serial_len, subsys->serial, model_len, subsys->model, + head->ns_id); +} +static DEVICE_ATTR_RO(wwid); + +static ssize_t nguid_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + return sysfs_emit(buf, "%pU\n", dev_to_ns_head(dev)->ids.nguid); +} +static DEVICE_ATTR_RO(nguid); + +static ssize_t uuid_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct nvme_ns_ids *ids = &dev_to_ns_head(dev)->ids; + + /* For backward compatibility expose the NGUID to userspace if + * we have no UUID set + */ + if (uuid_is_null(&ids->uuid)) { + dev_warn_once(dev, + "No UUID available providing old NGUID\n"); + return sysfs_emit(buf, "%pU\n", ids->nguid); + } + return sysfs_emit(buf, "%pU\n", &ids->uuid); +} +static DEVICE_ATTR_RO(uuid); + +static ssize_t eui_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + return sysfs_emit(buf, "%8ph\n", dev_to_ns_head(dev)->ids.eui64); +} +static DEVICE_ATTR_RO(eui); + +static ssize_t nsid_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + return sysfs_emit(buf, "%d\n", dev_to_ns_head(dev)->ns_id); +} +static DEVICE_ATTR_RO(nsid); + +static struct attribute *nvme_ns_id_attrs[] = { + &dev_attr_wwid.attr, + &dev_attr_uuid.attr, + &dev_attr_nguid.attr, + &dev_attr_eui.attr, + &dev_attr_nsid.attr, +#ifdef CONFIG_NVME_MULTIPATH + &dev_attr_ana_grpid.attr, + &dev_attr_ana_state.attr, +#endif + NULL, +}; + +static umode_t nvme_ns_id_attrs_are_visible(struct kobject *kobj, + struct attribute *a, int n) +{ + struct device *dev = container_of(kobj, struct device, kobj); + struct nvme_ns_ids *ids = &dev_to_ns_head(dev)->ids; + + if (a == &dev_attr_uuid.attr) { + if (uuid_is_null(&ids->uuid) && + !memchr_inv(ids->nguid, 0, sizeof(ids->nguid))) + return 0; + } + if (a == &dev_attr_nguid.attr) { + if (!memchr_inv(ids->nguid, 0, sizeof(ids->nguid))) + return 0; + } + if (a == &dev_attr_eui.attr) { + if (!memchr_inv(ids->eui64, 0, sizeof(ids->eui64))) + return 0; + } +#ifdef CONFIG_NVME_MULTIPATH + if (a == &dev_attr_ana_grpid.attr || a == &dev_attr_ana_state.attr) { + if (dev_to_disk(dev)->fops != &nvme_bdev_ops) /* per-path attr */ + return 0; + if (!nvme_ctrl_use_ana(nvme_get_ns_from_dev(dev)->ctrl)) + return 0; + } +#endif + return a->mode; +} + +static const struct attribute_group nvme_ns_id_attr_group = { + .attrs = nvme_ns_id_attrs, + .is_visible = nvme_ns_id_attrs_are_visible, +}; + +const struct attribute_group *nvme_ns_id_attr_groups[] = { + &nvme_ns_id_attr_group, + NULL, +}; + +#define nvme_show_str_function(field) \ +static ssize_t field##_show(struct device *dev, \ + struct device_attribute *attr, char *buf) \ +{ \ + struct nvme_ctrl *ctrl = dev_get_drvdata(dev); \ + return sysfs_emit(buf, "%.*s\n", \ + (int)sizeof(ctrl->subsys->field), ctrl->subsys->field); \ +} \ +static DEVICE_ATTR(field, S_IRUGO, field##_show, NULL); + +nvme_show_str_function(model); +nvme_show_str_function(serial); +nvme_show_str_function(firmware_rev); + +#define nvme_show_int_function(field) \ +static ssize_t field##_show(struct device *dev, \ + struct device_attribute *attr, char *buf) \ +{ \ + struct nvme_ctrl *ctrl = dev_get_drvdata(dev); \ + return sysfs_emit(buf, "%d\n", ctrl->field); \ +} \ +static DEVICE_ATTR(field, S_IRUGO, field##_show, NULL); + +nvme_show_int_function(cntlid); +nvme_show_int_function(numa_node); +nvme_show_int_function(queue_count); +nvme_show_int_function(sqsize); +nvme_show_int_function(kato); + +static ssize_t nvme_sysfs_delete(struct device *dev, + struct device_attribute *attr, const char *buf, + size_t count) +{ + struct nvme_ctrl *ctrl = dev_get_drvdata(dev); + + if (!test_bit(NVME_CTRL_STARTED_ONCE, &ctrl->flags)) + return -EBUSY; + + if (device_remove_file_self(dev, attr)) + nvme_delete_ctrl_sync(ctrl); + return count; +} +static DEVICE_ATTR(delete_controller, S_IWUSR, NULL, nvme_sysfs_delete); + +static ssize_t nvme_sysfs_show_transport(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct nvme_ctrl *ctrl = dev_get_drvdata(dev); + + return sysfs_emit(buf, "%s\n", ctrl->ops->name); +} +static DEVICE_ATTR(transport, S_IRUGO, nvme_sysfs_show_transport, NULL); + +static ssize_t nvme_sysfs_show_state(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct nvme_ctrl *ctrl = dev_get_drvdata(dev); + static const char *const state_name[] = { + [NVME_CTRL_NEW] = "new", + [NVME_CTRL_LIVE] = "live", + [NVME_CTRL_RESETTING] = "resetting", + [NVME_CTRL_CONNECTING] = "connecting", + [NVME_CTRL_DELETING] = "deleting", + [NVME_CTRL_DELETING_NOIO]= "deleting (no IO)", + [NVME_CTRL_DEAD] = "dead", + }; + + if ((unsigned)ctrl->state < ARRAY_SIZE(state_name) && + state_name[ctrl->state]) + return sysfs_emit(buf, "%s\n", state_name[ctrl->state]); + + return sysfs_emit(buf, "unknown state\n"); +} + +static DEVICE_ATTR(state, S_IRUGO, nvme_sysfs_show_state, NULL); + +static ssize_t nvme_sysfs_show_subsysnqn(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct nvme_ctrl *ctrl = dev_get_drvdata(dev); + + return sysfs_emit(buf, "%s\n", ctrl->subsys->subnqn); +} +static DEVICE_ATTR(subsysnqn, S_IRUGO, nvme_sysfs_show_subsysnqn, NULL); + +static ssize_t nvme_sysfs_show_hostnqn(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct nvme_ctrl *ctrl = dev_get_drvdata(dev); + + return sysfs_emit(buf, "%s\n", ctrl->opts->host->nqn); +} +static DEVICE_ATTR(hostnqn, S_IRUGO, nvme_sysfs_show_hostnqn, NULL); + +static ssize_t nvme_sysfs_show_hostid(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct nvme_ctrl *ctrl = dev_get_drvdata(dev); + + return sysfs_emit(buf, "%pU\n", &ctrl->opts->host->id); +} +static DEVICE_ATTR(hostid, S_IRUGO, nvme_sysfs_show_hostid, NULL); + +static ssize_t nvme_sysfs_show_address(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct nvme_ctrl *ctrl = dev_get_drvdata(dev); + + return ctrl->ops->get_address(ctrl, buf, PAGE_SIZE); +} +static DEVICE_ATTR(address, S_IRUGO, nvme_sysfs_show_address, NULL); + +static ssize_t nvme_ctrl_loss_tmo_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct nvme_ctrl *ctrl = dev_get_drvdata(dev); + struct nvmf_ctrl_options *opts = ctrl->opts; + + if (ctrl->opts->max_reconnects == -1) + return sysfs_emit(buf, "off\n"); + return sysfs_emit(buf, "%d\n", + opts->max_reconnects * opts->reconnect_delay); +} + +static ssize_t nvme_ctrl_loss_tmo_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct nvme_ctrl *ctrl = dev_get_drvdata(dev); + struct nvmf_ctrl_options *opts = ctrl->opts; + int ctrl_loss_tmo, err; + + err = kstrtoint(buf, 10, &ctrl_loss_tmo); + if (err) + return -EINVAL; + + if (ctrl_loss_tmo < 0) + opts->max_reconnects = -1; + else + opts->max_reconnects = DIV_ROUND_UP(ctrl_loss_tmo, + opts->reconnect_delay); + return count; +} +static DEVICE_ATTR(ctrl_loss_tmo, S_IRUGO | S_IWUSR, + nvme_ctrl_loss_tmo_show, nvme_ctrl_loss_tmo_store); + +static ssize_t nvme_ctrl_reconnect_delay_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct nvme_ctrl *ctrl = dev_get_drvdata(dev); + + if (ctrl->opts->reconnect_delay == -1) + return sysfs_emit(buf, "off\n"); + return sysfs_emit(buf, "%d\n", ctrl->opts->reconnect_delay); +} + +static ssize_t nvme_ctrl_reconnect_delay_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct nvme_ctrl *ctrl = dev_get_drvdata(dev); + unsigned int v; + int err; + + err = kstrtou32(buf, 10, &v); + if (err) + return err; + + ctrl->opts->reconnect_delay = v; + return count; +} +static DEVICE_ATTR(reconnect_delay, S_IRUGO | S_IWUSR, + nvme_ctrl_reconnect_delay_show, nvme_ctrl_reconnect_delay_store); + +static ssize_t nvme_ctrl_fast_io_fail_tmo_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct nvme_ctrl *ctrl = dev_get_drvdata(dev); + + if (ctrl->opts->fast_io_fail_tmo == -1) + return sysfs_emit(buf, "off\n"); + return sysfs_emit(buf, "%d\n", ctrl->opts->fast_io_fail_tmo); +} + +static ssize_t nvme_ctrl_fast_io_fail_tmo_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct nvme_ctrl *ctrl = dev_get_drvdata(dev); + struct nvmf_ctrl_options *opts = ctrl->opts; + int fast_io_fail_tmo, err; + + err = kstrtoint(buf, 10, &fast_io_fail_tmo); + if (err) + return -EINVAL; + + if (fast_io_fail_tmo < 0) + opts->fast_io_fail_tmo = -1; + else + opts->fast_io_fail_tmo = fast_io_fail_tmo; + return count; +} +static DEVICE_ATTR(fast_io_fail_tmo, S_IRUGO | S_IWUSR, + nvme_ctrl_fast_io_fail_tmo_show, nvme_ctrl_fast_io_fail_tmo_store); + +static ssize_t cntrltype_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + static const char * const type[] = { + [NVME_CTRL_IO] = "io\n", + [NVME_CTRL_DISC] = "discovery\n", + [NVME_CTRL_ADMIN] = "admin\n", + }; + struct nvme_ctrl *ctrl = dev_get_drvdata(dev); + + if (ctrl->cntrltype > NVME_CTRL_ADMIN || !type[ctrl->cntrltype]) + return sysfs_emit(buf, "reserved\n"); + + return sysfs_emit(buf, type[ctrl->cntrltype]); +} +static DEVICE_ATTR_RO(cntrltype); + +static ssize_t dctype_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + static const char * const type[] = { + [NVME_DCTYPE_NOT_REPORTED] = "none\n", + [NVME_DCTYPE_DDC] = "ddc\n", + [NVME_DCTYPE_CDC] = "cdc\n", + }; + struct nvme_ctrl *ctrl = dev_get_drvdata(dev); + + if (ctrl->dctype > NVME_DCTYPE_CDC || !type[ctrl->dctype]) + return sysfs_emit(buf, "reserved\n"); + + return sysfs_emit(buf, type[ctrl->dctype]); +} +static DEVICE_ATTR_RO(dctype); + +#ifdef CONFIG_NVME_AUTH +static ssize_t nvme_ctrl_dhchap_secret_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct nvme_ctrl *ctrl = dev_get_drvdata(dev); + struct nvmf_ctrl_options *opts = ctrl->opts; + + if (!opts->dhchap_secret) + return sysfs_emit(buf, "none\n"); + return sysfs_emit(buf, "%s\n", opts->dhchap_secret); +} + +static ssize_t nvme_ctrl_dhchap_secret_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct nvme_ctrl *ctrl = dev_get_drvdata(dev); + struct nvmf_ctrl_options *opts = ctrl->opts; + char *dhchap_secret; + + if (!ctrl->opts->dhchap_secret) + return -EINVAL; + if (count < 7) + return -EINVAL; + if (memcmp(buf, "DHHC-1:", 7)) + return -EINVAL; + + dhchap_secret = kzalloc(count + 1, GFP_KERNEL); + if (!dhchap_secret) + return -ENOMEM; + memcpy(dhchap_secret, buf, count); + nvme_auth_stop(ctrl); + if (strcmp(dhchap_secret, opts->dhchap_secret)) { + struct nvme_dhchap_key *key, *host_key; + int ret; + + ret = nvme_auth_generate_key(dhchap_secret, &key); + if (ret) { + kfree(dhchap_secret); + return ret; + } + kfree(opts->dhchap_secret); + opts->dhchap_secret = dhchap_secret; + host_key = ctrl->host_key; + mutex_lock(&ctrl->dhchap_auth_mutex); + ctrl->host_key = key; + mutex_unlock(&ctrl->dhchap_auth_mutex); + nvme_auth_free_key(host_key); + } else + kfree(dhchap_secret); + /* Start re-authentication */ + dev_info(ctrl->device, "re-authenticating controller\n"); + queue_work(nvme_wq, &ctrl->dhchap_auth_work); + + return count; +} + +static DEVICE_ATTR(dhchap_secret, S_IRUGO | S_IWUSR, + nvme_ctrl_dhchap_secret_show, nvme_ctrl_dhchap_secret_store); + +static ssize_t nvme_ctrl_dhchap_ctrl_secret_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct nvme_ctrl *ctrl = dev_get_drvdata(dev); + struct nvmf_ctrl_options *opts = ctrl->opts; + + if (!opts->dhchap_ctrl_secret) + return sysfs_emit(buf, "none\n"); + return sysfs_emit(buf, "%s\n", opts->dhchap_ctrl_secret); +} + +static ssize_t nvme_ctrl_dhchap_ctrl_secret_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct nvme_ctrl *ctrl = dev_get_drvdata(dev); + struct nvmf_ctrl_options *opts = ctrl->opts; + char *dhchap_secret; + + if (!ctrl->opts->dhchap_ctrl_secret) + return -EINVAL; + if (count < 7) + return -EINVAL; + if (memcmp(buf, "DHHC-1:", 7)) + return -EINVAL; + + dhchap_secret = kzalloc(count + 1, GFP_KERNEL); + if (!dhchap_secret) + return -ENOMEM; + memcpy(dhchap_secret, buf, count); + nvme_auth_stop(ctrl); + if (strcmp(dhchap_secret, opts->dhchap_ctrl_secret)) { + struct nvme_dhchap_key *key, *ctrl_key; + int ret; + + ret = nvme_auth_generate_key(dhchap_secret, &key); + if (ret) { + kfree(dhchap_secret); + return ret; + } + kfree(opts->dhchap_ctrl_secret); + opts->dhchap_ctrl_secret = dhchap_secret; + ctrl_key = ctrl->ctrl_key; + mutex_lock(&ctrl->dhchap_auth_mutex); + ctrl->ctrl_key = key; + mutex_unlock(&ctrl->dhchap_auth_mutex); + nvme_auth_free_key(ctrl_key); + } else + kfree(dhchap_secret); + /* Start re-authentication */ + dev_info(ctrl->device, "re-authenticating controller\n"); + queue_work(nvme_wq, &ctrl->dhchap_auth_work); + + return count; +} + +static DEVICE_ATTR(dhchap_ctrl_secret, S_IRUGO | S_IWUSR, + nvme_ctrl_dhchap_ctrl_secret_show, nvme_ctrl_dhchap_ctrl_secret_store); +#endif + +static struct attribute *nvme_dev_attrs[] = { + &dev_attr_reset_controller.attr, + &dev_attr_rescan_controller.attr, + &dev_attr_model.attr, + &dev_attr_serial.attr, + &dev_attr_firmware_rev.attr, + &dev_attr_cntlid.attr, + &dev_attr_delete_controller.attr, + &dev_attr_transport.attr, + &dev_attr_subsysnqn.attr, + &dev_attr_address.attr, + &dev_attr_state.attr, + &dev_attr_numa_node.attr, + &dev_attr_queue_count.attr, + &dev_attr_sqsize.attr, + &dev_attr_hostnqn.attr, + &dev_attr_hostid.attr, + &dev_attr_ctrl_loss_tmo.attr, + &dev_attr_reconnect_delay.attr, + &dev_attr_fast_io_fail_tmo.attr, + &dev_attr_kato.attr, + &dev_attr_cntrltype.attr, + &dev_attr_dctype.attr, +#ifdef CONFIG_NVME_AUTH + &dev_attr_dhchap_secret.attr, + &dev_attr_dhchap_ctrl_secret.attr, +#endif + NULL +}; + +static umode_t nvme_dev_attrs_are_visible(struct kobject *kobj, + struct attribute *a, int n) +{ + struct device *dev = container_of(kobj, struct device, kobj); + struct nvme_ctrl *ctrl = dev_get_drvdata(dev); + + if (a == &dev_attr_delete_controller.attr && !ctrl->ops->delete_ctrl) + return 0; + if (a == &dev_attr_address.attr && !ctrl->ops->get_address) + return 0; + if (a == &dev_attr_hostnqn.attr && !ctrl->opts) + return 0; + if (a == &dev_attr_hostid.attr && !ctrl->opts) + return 0; + if (a == &dev_attr_ctrl_loss_tmo.attr && !ctrl->opts) + return 0; + if (a == &dev_attr_reconnect_delay.attr && !ctrl->opts) + return 0; + if (a == &dev_attr_fast_io_fail_tmo.attr && !ctrl->opts) + return 0; +#ifdef CONFIG_NVME_AUTH + if (a == &dev_attr_dhchap_secret.attr && !ctrl->opts) + return 0; + if (a == &dev_attr_dhchap_ctrl_secret.attr && !ctrl->opts) + return 0; +#endif + + return a->mode; +} + +const struct attribute_group nvme_dev_attrs_group = { + .attrs = nvme_dev_attrs, + .is_visible = nvme_dev_attrs_are_visible, +}; +EXPORT_SYMBOL_GPL(nvme_dev_attrs_group); + +const struct attribute_group *nvme_dev_attr_groups[] = { + &nvme_dev_attrs_group, + NULL, +}; + +#define SUBSYS_ATTR_RO(_name, _mode, _show) \ + struct device_attribute subsys_attr_##_name = \ + __ATTR(_name, _mode, _show, NULL) + +static ssize_t nvme_subsys_show_nqn(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct nvme_subsystem *subsys = + container_of(dev, struct nvme_subsystem, dev); + + return sysfs_emit(buf, "%s\n", subsys->subnqn); +} +static SUBSYS_ATTR_RO(subsysnqn, S_IRUGO, nvme_subsys_show_nqn); + +static ssize_t nvme_subsys_show_type(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct nvme_subsystem *subsys = + container_of(dev, struct nvme_subsystem, dev); + + switch (subsys->subtype) { + case NVME_NQN_DISC: + return sysfs_emit(buf, "discovery\n"); + case NVME_NQN_NVME: + return sysfs_emit(buf, "nvm\n"); + default: + return sysfs_emit(buf, "reserved\n"); + } +} +static SUBSYS_ATTR_RO(subsystype, S_IRUGO, nvme_subsys_show_type); + +#define nvme_subsys_show_str_function(field) \ +static ssize_t subsys_##field##_show(struct device *dev, \ + struct device_attribute *attr, char *buf) \ +{ \ + struct nvme_subsystem *subsys = \ + container_of(dev, struct nvme_subsystem, dev); \ + return sysfs_emit(buf, "%.*s\n", \ + (int)sizeof(subsys->field), subsys->field); \ +} \ +static SUBSYS_ATTR_RO(field, S_IRUGO, subsys_##field##_show); + +nvme_subsys_show_str_function(model); +nvme_subsys_show_str_function(serial); +nvme_subsys_show_str_function(firmware_rev); + +static struct attribute *nvme_subsys_attrs[] = { + &subsys_attr_model.attr, + &subsys_attr_serial.attr, + &subsys_attr_firmware_rev.attr, + &subsys_attr_subsysnqn.attr, + &subsys_attr_subsystype.attr, +#ifdef CONFIG_NVME_MULTIPATH + &subsys_attr_iopolicy.attr, +#endif + NULL, +}; + +static const struct attribute_group nvme_subsys_attrs_group = { + .attrs = nvme_subsys_attrs, +}; + +const struct attribute_group *nvme_subsys_attrs_groups[] = { + &nvme_subsys_attrs_group, + NULL, +}; diff --git a/drivers/nvme/host/tcp.c b/drivers/nvme/host/tcp.c index bf0230442d570842b861eb552063fff3df994a85..9ce417cd32a79b861d3e9ed044325c8ab87757a6 100644 --- a/drivers/nvme/host/tcp.c +++ b/drivers/nvme/host/tcp.c @@ -997,25 +997,28 @@ static int nvme_tcp_try_send_data(struct nvme_tcp_request *req) u32 h2cdata_left = req->h2cdata_left; while (true) { + struct bio_vec bvec; + struct msghdr msg = { + .msg_flags = MSG_DONTWAIT | MSG_SPLICE_PAGES, + }; struct page *page = nvme_tcp_req_cur_page(req); size_t offset = nvme_tcp_req_cur_offset(req); size_t len = nvme_tcp_req_cur_length(req); bool last = nvme_tcp_pdu_last_send(req, len); int req_data_sent = req->data_sent; - int ret, flags = MSG_DONTWAIT; + int ret; if (last && !queue->data_digest && !nvme_tcp_queue_more(queue)) - flags |= MSG_EOR; + msg.msg_flags |= MSG_EOR; else - flags |= MSG_MORE | MSG_SENDPAGE_NOTLAST; + msg.msg_flags |= MSG_MORE; - if (sendpage_ok(page)) { - ret = kernel_sendpage(queue->sock, page, offset, len, - flags); - } else { - ret = sock_no_sendpage(queue->sock, page, offset, len, - flags); - } + if (!sendpage_ok(page)) + msg.msg_flags &= ~MSG_SPLICE_PAGES; + + bvec_set_page(&bvec, page, len, offset); + iov_iter_bvec(&msg.msg_iter, ITER_SOURCE, &bvec, 1, len); + ret = sock_sendmsg(queue->sock, &msg); if (ret <= 0) return ret; @@ -1054,22 +1057,24 @@ static int nvme_tcp_try_send_cmd_pdu(struct nvme_tcp_request *req) { struct nvme_tcp_queue *queue = req->queue; struct nvme_tcp_cmd_pdu *pdu = nvme_tcp_req_cmd_pdu(req); + struct bio_vec bvec; + struct msghdr msg = { .msg_flags = MSG_DONTWAIT | MSG_SPLICE_PAGES, }; bool inline_data = nvme_tcp_has_inline_data(req); u8 hdgst = nvme_tcp_hdgst_len(queue); int len = sizeof(*pdu) + hdgst - req->offset; - int flags = MSG_DONTWAIT; int ret; if (inline_data || nvme_tcp_queue_more(queue)) - flags |= MSG_MORE | MSG_SENDPAGE_NOTLAST; + msg.msg_flags |= MSG_MORE; else - flags |= MSG_EOR; + msg.msg_flags |= MSG_EOR; if (queue->hdr_digest && !req->offset) nvme_tcp_hdgst(queue->snd_hash, pdu, sizeof(*pdu)); - ret = kernel_sendpage(queue->sock, virt_to_page(pdu), - offset_in_page(pdu) + req->offset, len, flags); + bvec_set_virt(&bvec, (void *)pdu + req->offset, len); + iov_iter_bvec(&msg.msg_iter, ITER_SOURCE, &bvec, 1, len); + ret = sock_sendmsg(queue->sock, &msg); if (unlikely(ret <= 0)) return ret; @@ -1093,6 +1098,8 @@ static int nvme_tcp_try_send_data_pdu(struct nvme_tcp_request *req) { struct nvme_tcp_queue *queue = req->queue; struct nvme_tcp_data_pdu *pdu = nvme_tcp_req_data_pdu(req); + struct bio_vec bvec; + struct msghdr msg = { .msg_flags = MSG_DONTWAIT | MSG_MORE, }; u8 hdgst = nvme_tcp_hdgst_len(queue); int len = sizeof(*pdu) - req->offset + hdgst; int ret; @@ -1101,13 +1108,11 @@ static int nvme_tcp_try_send_data_pdu(struct nvme_tcp_request *req) nvme_tcp_hdgst(queue->snd_hash, pdu, sizeof(*pdu)); if (!req->h2cdata_left) - ret = kernel_sendpage(queue->sock, virt_to_page(pdu), - offset_in_page(pdu) + req->offset, len, - MSG_DONTWAIT | MSG_MORE | MSG_SENDPAGE_NOTLAST); - else - ret = sock_no_sendpage(queue->sock, virt_to_page(pdu), - offset_in_page(pdu) + req->offset, len, - MSG_DONTWAIT | MSG_MORE); + msg.msg_flags |= MSG_SPLICE_PAGES; + + bvec_set_virt(&bvec, (void *)pdu + req->offset, len); + iov_iter_bvec(&msg.msg_iter, ITER_SOURCE, &bvec, 1, len); + ret = sock_sendmsg(queue->sock, &msg); if (unlikely(ret <= 0)) return ret; @@ -1802,58 +1807,12 @@ static int __nvme_tcp_alloc_io_queues(struct nvme_ctrl *ctrl) return ret; } -static unsigned int nvme_tcp_nr_io_queues(struct nvme_ctrl *ctrl) -{ - unsigned int nr_io_queues; - - nr_io_queues = min(ctrl->opts->nr_io_queues, num_online_cpus()); - nr_io_queues += min(ctrl->opts->nr_write_queues, num_online_cpus()); - nr_io_queues += min(ctrl->opts->nr_poll_queues, num_online_cpus()); - - return nr_io_queues; -} - -static void nvme_tcp_set_io_queues(struct nvme_ctrl *nctrl, - unsigned int nr_io_queues) -{ - struct nvme_tcp_ctrl *ctrl = to_tcp_ctrl(nctrl); - struct nvmf_ctrl_options *opts = nctrl->opts; - - if (opts->nr_write_queues && opts->nr_io_queues < nr_io_queues) { - /* - * separate read/write queues - * hand out dedicated default queues only after we have - * sufficient read queues. - */ - ctrl->io_queues[HCTX_TYPE_READ] = opts->nr_io_queues; - nr_io_queues -= ctrl->io_queues[HCTX_TYPE_READ]; - ctrl->io_queues[HCTX_TYPE_DEFAULT] = - min(opts->nr_write_queues, nr_io_queues); - nr_io_queues -= ctrl->io_queues[HCTX_TYPE_DEFAULT]; - } else { - /* - * shared read/write queues - * either no write queues were requested, or we don't have - * sufficient queue count to have dedicated default queues. - */ - ctrl->io_queues[HCTX_TYPE_DEFAULT] = - min(opts->nr_io_queues, nr_io_queues); - nr_io_queues -= ctrl->io_queues[HCTX_TYPE_DEFAULT]; - } - - if (opts->nr_poll_queues && nr_io_queues) { - /* map dedicated poll queues only if we have queues left */ - ctrl->io_queues[HCTX_TYPE_POLL] = - min(opts->nr_poll_queues, nr_io_queues); - } -} - static int nvme_tcp_alloc_io_queues(struct nvme_ctrl *ctrl) { unsigned int nr_io_queues; int ret; - nr_io_queues = nvme_tcp_nr_io_queues(ctrl); + nr_io_queues = nvmf_nr_io_queues(ctrl->opts); ret = nvme_set_queue_count(ctrl, &nr_io_queues); if (ret) return ret; @@ -1868,8 +1827,8 @@ static int nvme_tcp_alloc_io_queues(struct nvme_ctrl *ctrl) dev_info(ctrl->device, "creating %d I/O queues.\n", nr_io_queues); - nvme_tcp_set_io_queues(ctrl, nr_io_queues); - + nvmf_set_io_queues(ctrl->opts, nr_io_queues, + to_tcp_ctrl(ctrl)->io_queues); return __nvme_tcp_alloc_io_queues(ctrl); } @@ -2449,44 +2408,8 @@ static blk_status_t nvme_tcp_queue_rq(struct blk_mq_hw_ctx *hctx, static void nvme_tcp_map_queues(struct blk_mq_tag_set *set) { struct nvme_tcp_ctrl *ctrl = to_tcp_ctrl(set->driver_data); - struct nvmf_ctrl_options *opts = ctrl->ctrl.opts; - - if (opts->nr_write_queues && ctrl->io_queues[HCTX_TYPE_READ]) { - /* separate read/write queues */ - set->map[HCTX_TYPE_DEFAULT].nr_queues = - ctrl->io_queues[HCTX_TYPE_DEFAULT]; - set->map[HCTX_TYPE_DEFAULT].queue_offset = 0; - set->map[HCTX_TYPE_READ].nr_queues = - ctrl->io_queues[HCTX_TYPE_READ]; - set->map[HCTX_TYPE_READ].queue_offset = - ctrl->io_queues[HCTX_TYPE_DEFAULT]; - } else { - /* shared read/write queues */ - set->map[HCTX_TYPE_DEFAULT].nr_queues = - ctrl->io_queues[HCTX_TYPE_DEFAULT]; - set->map[HCTX_TYPE_DEFAULT].queue_offset = 0; - set->map[HCTX_TYPE_READ].nr_queues = - ctrl->io_queues[HCTX_TYPE_DEFAULT]; - set->map[HCTX_TYPE_READ].queue_offset = 0; - } - blk_mq_map_queues(&set->map[HCTX_TYPE_DEFAULT]); - blk_mq_map_queues(&set->map[HCTX_TYPE_READ]); - - if (opts->nr_poll_queues && ctrl->io_queues[HCTX_TYPE_POLL]) { - /* map dedicated poll queues only if we have queues left */ - set->map[HCTX_TYPE_POLL].nr_queues = - ctrl->io_queues[HCTX_TYPE_POLL]; - set->map[HCTX_TYPE_POLL].queue_offset = - ctrl->io_queues[HCTX_TYPE_DEFAULT] + - ctrl->io_queues[HCTX_TYPE_READ]; - blk_mq_map_queues(&set->map[HCTX_TYPE_POLL]); - } - - dev_info(ctrl->ctrl.device, - "mapped %d/%d/%d default/read/poll queues.\n", - ctrl->io_queues[HCTX_TYPE_DEFAULT], - ctrl->io_queues[HCTX_TYPE_READ], - ctrl->io_queues[HCTX_TYPE_POLL]); + + nvmf_map_queues(set, &ctrl->ctrl, ctrl->io_queues); } static int nvme_tcp_poll(struct blk_mq_hw_ctx *hctx, struct io_comp_batch *iob) diff --git a/drivers/nvme/host/zns.c b/drivers/nvme/host/zns.c index 12316ab51bda66af875ca9bffb8253702e1c83ba..ec8557810c2102328a84e4b7c97100f503ef55da 100644 --- a/drivers/nvme/host/zns.c +++ b/drivers/nvme/host/zns.c @@ -10,12 +10,11 @@ int nvme_revalidate_zones(struct nvme_ns *ns) { struct request_queue *q = ns->queue; - int ret; - ret = blk_revalidate_disk_zones(ns->disk, NULL); - if (!ret) - blk_queue_max_zone_append_sectors(q, ns->ctrl->max_zone_append); - return ret; + blk_queue_chunk_sectors(q, ns->zsze); + blk_queue_max_zone_append_sectors(q, ns->ctrl->max_zone_append); + + return blk_revalidate_disk_zones(ns->disk, NULL); } static int nvme_set_max_append(struct nvme_ctrl *ctrl) diff --git a/drivers/nvme/target/fabrics-cmd-auth.c b/drivers/nvme/target/fabrics-cmd-auth.c index 7970a7640e5851a045d1e27706e76491e81339ad..586458f765f173b6ffa20b7abc58be5296c9ac91 100644 --- a/drivers/nvme/target/fabrics-cmd-auth.c +++ b/drivers/nvme/target/fabrics-cmd-auth.c @@ -295,13 +295,11 @@ void nvmet_execute_auth_send(struct nvmet_req *req) status = 0; } goto done_kfree; - break; case NVME_AUTH_DHCHAP_MESSAGE_SUCCESS2: req->sq->authenticated = true; pr_debug("%s: ctrl %d qid %d ctrl authenticated\n", __func__, ctrl->cntlid, req->sq->qid); goto done_kfree; - break; case NVME_AUTH_DHCHAP_MESSAGE_FAILURE2: status = nvmet_auth_failure2(d); if (status) { @@ -312,7 +310,6 @@ void nvmet_execute_auth_send(struct nvmet_req *req) status = 0; } goto done_kfree; - break; default: req->sq->dhchap_status = NVME_AUTH_DHCHAP_FAILURE_INCORRECT_MESSAGE; @@ -320,7 +317,6 @@ void nvmet_execute_auth_send(struct nvmet_req *req) NVME_AUTH_DHCHAP_MESSAGE_FAILURE2; req->sq->authenticated = false; goto done_kfree; - break; } done_failure1: req->sq->dhchap_status = NVME_AUTH_DHCHAP_FAILURE_INCORRECT_MESSAGE; @@ -483,15 +479,6 @@ void nvmet_execute_auth_receive(struct nvmet_req *req) status = NVME_SC_INTERNAL; break; } - if (status) { - req->sq->dhchap_status = status; - nvmet_auth_failure1(req, d, al); - pr_warn("ctrl %d qid %d: challenge status (%x)\n", - ctrl->cntlid, req->sq->qid, - req->sq->dhchap_status); - status = 0; - break; - } req->sq->dhchap_step = NVME_AUTH_DHCHAP_MESSAGE_REPLY; break; case NVME_AUTH_DHCHAP_MESSAGE_SUCCESS1: diff --git a/drivers/nvme/target/fcloop.c b/drivers/nvme/target/fcloop.c index e940a7d37a9dc64f631510216d08976f989c9206..c65a73433c05f643654616175d5fc9229af753e7 100644 --- a/drivers/nvme/target/fcloop.c +++ b/drivers/nvme/target/fcloop.c @@ -645,8 +645,6 @@ fcloop_fcp_recv_work(struct work_struct *work) } if (ret) fcloop_call_host_done(fcpreq, tfcp_req, ret); - - return; } static void @@ -1168,7 +1166,8 @@ __wait_localport_unreg(struct fcloop_lport *lport) ret = nvme_fc_unregister_localport(lport->localport); - wait_for_completion(&lport->unreg_done); + if (!ret) + wait_for_completion(&lport->unreg_done); kfree(lport); diff --git a/drivers/nvme/target/io-cmd-bdev.c b/drivers/nvme/target/io-cmd-bdev.c index c2d6cea0236b0a70210a6f9b13f19b57da6c1214..2733e01585854c695c47109fc8d0f15cf337a956 100644 --- a/drivers/nvme/target/io-cmd-bdev.c +++ b/drivers/nvme/target/io-cmd-bdev.c @@ -51,7 +51,7 @@ void nvmet_bdev_set_limits(struct block_device *bdev, struct nvme_id_ns *id) void nvmet_bdev_ns_disable(struct nvmet_ns *ns) { if (ns->bdev) { - blkdev_put(ns->bdev, FMODE_WRITE | FMODE_READ); + blkdev_put(ns->bdev, NULL); ns->bdev = NULL; } } @@ -85,7 +85,7 @@ int nvmet_bdev_ns_enable(struct nvmet_ns *ns) return -ENOTBLK; ns->bdev = blkdev_get_by_path(ns->device_path, - FMODE_READ | FMODE_WRITE, NULL); + BLK_OPEN_READ | BLK_OPEN_WRITE, NULL, NULL); if (IS_ERR(ns->bdev)) { ret = PTR_ERR(ns->bdev); if (ret != -ENOTBLK) { diff --git a/drivers/nvme/target/loop.c b/drivers/nvme/target/loop.c index f2d24b2d992f8721609b59414a4b5beafa33d0ad..48d5df054cd0245e62acf3997be6c2413af9064e 100644 --- a/drivers/nvme/target/loop.c +++ b/drivers/nvme/target/loop.c @@ -373,7 +373,7 @@ static int nvme_loop_configure_admin_queue(struct nvme_loop_ctrl *ctrl) goto out_cleanup_tagset; ctrl->ctrl.max_hw_sectors = - (NVME_LOOP_MAX_SEGMENTS - 1) << (PAGE_SHIFT - 9); + (NVME_LOOP_MAX_SEGMENTS - 1) << PAGE_SECTORS_SHIFT; nvme_unquiesce_admin_queue(&ctrl->ctrl); diff --git a/drivers/nvme/target/nvmet.h b/drivers/nvme/target/nvmet.h index dc60a22646f783eb61655bed66c33e0d7ff5fb14..8cfd60f3b5648f12986a7607cc50630c08841fe7 100644 --- a/drivers/nvme/target/nvmet.h +++ b/drivers/nvme/target/nvmet.h @@ -79,8 +79,8 @@ struct nvmet_ns { struct completion disable_done; mempool_t *bvec_pool; - int use_p2pmem; struct pci_dev *p2p_dev; + int use_p2pmem; int pi_type; int metadata_size; u8 csi; @@ -109,8 +109,8 @@ struct nvmet_sq { u32 sqhd; bool sqhd_disabled; #ifdef CONFIG_NVME_TARGET_AUTH - struct delayed_work auth_expired_work; bool authenticated; + struct delayed_work auth_expired_work; u16 dhchap_tid; u16 dhchap_status; int dhchap_step; diff --git a/drivers/nvme/target/passthru.c b/drivers/nvme/target/passthru.c index 71a9c1cc57f59c265478b8c816c8e4f5a9b65f61..9fe07d7efa96cf1fee3a5ea5ec433fbed93c012b 100644 --- a/drivers/nvme/target/passthru.c +++ b/drivers/nvme/target/passthru.c @@ -102,14 +102,14 @@ static u16 nvmet_passthru_override_id_ctrl(struct nvmet_req *req) * which depends on the host's memory fragementation. To solve this, * ensure mdts is limited to the pages equal to the number of segments. */ - max_hw_sectors = min_not_zero(pctrl->max_segments << (PAGE_SHIFT - 9), + max_hw_sectors = min_not_zero(pctrl->max_segments << PAGE_SECTORS_SHIFT, pctrl->max_hw_sectors); /* * nvmet_passthru_map_sg is limitted to using a single bio so limit * the mdts based on BIO_MAX_VECS as well */ - max_hw_sectors = min_not_zero(BIO_MAX_VECS << (PAGE_SHIFT - 9), + max_hw_sectors = min_not_zero(BIO_MAX_VECS << PAGE_SECTORS_SHIFT, max_hw_sectors); page_shift = NVME_CAP_MPSMIN(ctrl->cap) + 12; diff --git a/drivers/nvme/target/tcp.c b/drivers/nvme/target/tcp.c index ed98df72c76b0c223947da741d858c1419844efc..868aa4de2e4c4ef7bcfc3c704ae10791f1725ff9 100644 --- a/drivers/nvme/target/tcp.c +++ b/drivers/nvme/target/tcp.c @@ -576,13 +576,17 @@ static void nvmet_tcp_execute_request(struct nvmet_tcp_cmd *cmd) static int nvmet_try_send_data_pdu(struct nvmet_tcp_cmd *cmd) { + struct msghdr msg = { + .msg_flags = MSG_DONTWAIT | MSG_MORE | MSG_SPLICE_PAGES, + }; + struct bio_vec bvec; u8 hdgst = nvmet_tcp_hdgst_len(cmd->queue); int left = sizeof(*cmd->data_pdu) - cmd->offset + hdgst; int ret; - ret = kernel_sendpage(cmd->queue->sock, virt_to_page(cmd->data_pdu), - offset_in_page(cmd->data_pdu) + cmd->offset, - left, MSG_DONTWAIT | MSG_MORE | MSG_SENDPAGE_NOTLAST); + bvec_set_virt(&bvec, (void *)cmd->data_pdu + cmd->offset, left); + iov_iter_bvec(&msg.msg_iter, ITER_SOURCE, &bvec, 1, left); + ret = sock_sendmsg(cmd->queue->sock, &msg); if (ret <= 0) return ret; @@ -603,17 +607,21 @@ static int nvmet_try_send_data(struct nvmet_tcp_cmd *cmd, bool last_in_batch) int ret; while (cmd->cur_sg) { + struct msghdr msg = { + .msg_flags = MSG_DONTWAIT | MSG_SPLICE_PAGES, + }; struct page *page = sg_page(cmd->cur_sg); + struct bio_vec bvec; u32 left = cmd->cur_sg->length - cmd->offset; - int flags = MSG_DONTWAIT; if ((!last_in_batch && cmd->queue->send_list_len) || cmd->wbytes_done + left < cmd->req.transfer_len || queue->data_digest || !queue->nvme_sq.sqhd_disabled) - flags |= MSG_MORE | MSG_SENDPAGE_NOTLAST; + msg.msg_flags |= MSG_MORE; - ret = kernel_sendpage(cmd->queue->sock, page, cmd->offset, - left, flags); + bvec_set_page(&bvec, page, left, cmd->offset); + iov_iter_bvec(&msg.msg_iter, ITER_SOURCE, &bvec, 1, left); + ret = sock_sendmsg(cmd->queue->sock, &msg); if (ret <= 0) return ret; @@ -649,18 +657,20 @@ static int nvmet_try_send_data(struct nvmet_tcp_cmd *cmd, bool last_in_batch) static int nvmet_try_send_response(struct nvmet_tcp_cmd *cmd, bool last_in_batch) { + struct msghdr msg = { .msg_flags = MSG_DONTWAIT | MSG_SPLICE_PAGES, }; + struct bio_vec bvec; u8 hdgst = nvmet_tcp_hdgst_len(cmd->queue); int left = sizeof(*cmd->rsp_pdu) - cmd->offset + hdgst; - int flags = MSG_DONTWAIT; int ret; if (!last_in_batch && cmd->queue->send_list_len) - flags |= MSG_MORE | MSG_SENDPAGE_NOTLAST; + msg.msg_flags |= MSG_MORE; else - flags |= MSG_EOR; + msg.msg_flags |= MSG_EOR; - ret = kernel_sendpage(cmd->queue->sock, virt_to_page(cmd->rsp_pdu), - offset_in_page(cmd->rsp_pdu) + cmd->offset, left, flags); + bvec_set_virt(&bvec, (void *)cmd->rsp_pdu + cmd->offset, left); + iov_iter_bvec(&msg.msg_iter, ITER_SOURCE, &bvec, 1, left); + ret = sock_sendmsg(cmd->queue->sock, &msg); if (ret <= 0) return ret; cmd->offset += ret; @@ -677,18 +687,20 @@ static int nvmet_try_send_response(struct nvmet_tcp_cmd *cmd, static int nvmet_try_send_r2t(struct nvmet_tcp_cmd *cmd, bool last_in_batch) { + struct msghdr msg = { .msg_flags = MSG_DONTWAIT | MSG_SPLICE_PAGES, }; + struct bio_vec bvec; u8 hdgst = nvmet_tcp_hdgst_len(cmd->queue); int left = sizeof(*cmd->r2t_pdu) - cmd->offset + hdgst; - int flags = MSG_DONTWAIT; int ret; if (!last_in_batch && cmd->queue->send_list_len) - flags |= MSG_MORE | MSG_SENDPAGE_NOTLAST; + msg.msg_flags |= MSG_MORE; else - flags |= MSG_EOR; + msg.msg_flags |= MSG_EOR; - ret = kernel_sendpage(cmd->queue->sock, virt_to_page(cmd->r2t_pdu), - offset_in_page(cmd->r2t_pdu) + cmd->offset, left, flags); + bvec_set_virt(&bvec, (void *)cmd->r2t_pdu + cmd->offset, left); + iov_iter_bvec(&msg.msg_iter, ITER_SOURCE, &bvec, 1, left); + ret = sock_sendmsg(cmd->queue->sock, &msg); if (ret <= 0) return ret; cmd->offset += ret; diff --git a/drivers/nvmem/Kconfig b/drivers/nvmem/Kconfig index b291b27048c76f8d686c725665a545966d8deff3..da9befa3d6c43bfb2885459f1d2aef58904cfa11 100644 --- a/drivers/nvmem/Kconfig +++ b/drivers/nvmem/Kconfig @@ -55,6 +55,7 @@ config NVMEM_BRCM_NVRAM tristate "Broadcom's NVRAM support" depends on ARCH_BCM_5301X || COMPILE_TEST depends on HAS_IOMEM + select GENERIC_NET_UTILS help This driver provides support for Broadcom's NVRAM that can be accessed using I/O mapping. @@ -82,6 +83,15 @@ config NVMEM_IMX_OCOTP This driver can also be built as a module. If so, the module will be called nvmem-imx-ocotp. +config NVMEM_IMX_OCOTP_ELE + tristate "i.MX On-Chip OTP Controller support" + depends on ARCH_MXC || COMPILE_TEST + depends on HAS_IOMEM + depends on OF + help + This is a driver for the On-Chip OTP Controller (OCOTP) + available on i.MX SoCs which has ELE. + config NVMEM_IMX_OCOTP_SCU tristate "i.MX8 SCU On-Chip OTP Controller support" depends on IMX_SCU diff --git a/drivers/nvmem/Makefile b/drivers/nvmem/Makefile index f82431ec8aef0c2ebdc89b83578a8bbe5a188b58..cc23ce4ffb1f1dd86a81aed84207415bdba2e24b 100644 --- a/drivers/nvmem/Makefile +++ b/drivers/nvmem/Makefile @@ -18,6 +18,8 @@ obj-$(CONFIG_NVMEM_IMX_IIM) += nvmem-imx-iim.o nvmem-imx-iim-y := imx-iim.o obj-$(CONFIG_NVMEM_IMX_OCOTP) += nvmem-imx-ocotp.o nvmem-imx-ocotp-y := imx-ocotp.o +obj-$(CONFIG_NVMEM_IMX_OCOTP_ELE) += nvmem-imx-ocotp-ele.o +nvmem-imx-ocotp-ele-y := imx-ocotp-ele.o obj-$(CONFIG_NVMEM_IMX_OCOTP_SCU) += nvmem-imx-ocotp-scu.o nvmem-imx-ocotp-scu-y := imx-ocotp-scu.o obj-$(CONFIG_NVMEM_JZ4780_EFUSE) += nvmem_jz4780_efuse.o diff --git a/drivers/nvmem/brcm_nvram.c b/drivers/nvmem/brcm_nvram.c index 39aa27942f28b3d49ed91327e574666023c4fd6f..4567c597c87f26c70402bced7d52bf5160094cf8 100644 --- a/drivers/nvmem/brcm_nvram.c +++ b/drivers/nvmem/brcm_nvram.c @@ -4,6 +4,8 @@ */ #include +#include +#include #include #include #include @@ -42,6 +44,25 @@ static int brcm_nvram_read(void *context, unsigned int offset, void *val, return 0; } +static int brcm_nvram_read_post_process_macaddr(void *context, const char *id, int index, + unsigned int offset, void *buf, size_t bytes) +{ + u8 mac[ETH_ALEN]; + + if (bytes != 3 * ETH_ALEN - 1) + return -EINVAL; + + if (!mac_pton(buf, mac)) + return -EINVAL; + + if (index) + eth_addr_add(mac, index); + + ether_addr_copy(buf, mac); + + return 0; +} + static int brcm_nvram_add_cells(struct brcm_nvram *priv, uint8_t *data, size_t len) { @@ -75,6 +96,13 @@ static int brcm_nvram_add_cells(struct brcm_nvram *priv, uint8_t *data, priv->cells[idx].offset = value - (char *)data; priv->cells[idx].bytes = strlen(value); priv->cells[idx].np = of_get_child_by_name(dev->of_node, priv->cells[idx].name); + if (!strcmp(var, "et0macaddr") || + !strcmp(var, "et1macaddr") || + !strcmp(var, "et2macaddr")) { + priv->cells[idx].raw_len = strlen(value); + priv->cells[idx].bytes = ETH_ALEN; + priv->cells[idx].read_post_process = brcm_nvram_read_post_process_macaddr; + } } return 0; diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c index 342cd380b4201e13a48a2ccf8ba9b505ef1f27f5..3f8c7718412b484ba649dd9f540dd6479dbf0ab6 100644 --- a/drivers/nvmem/core.c +++ b/drivers/nvmem/core.c @@ -696,7 +696,7 @@ static int nvmem_validate_keepouts(struct nvmem_device *nvmem) return 0; } -static int nvmem_add_cells_from_of(struct nvmem_device *nvmem) +static int nvmem_add_cells_from_dt(struct nvmem_device *nvmem, struct device_node *np) { struct nvmem_layout *layout = nvmem->layout; struct device *dev = &nvmem->dev; @@ -704,7 +704,7 @@ static int nvmem_add_cells_from_of(struct nvmem_device *nvmem) const __be32 *addr; int len, ret; - for_each_child_of_node(dev->of_node, child) { + for_each_child_of_node(np, child) { struct nvmem_cell_info info = {0}; addr = of_get_property(child, "reg", &len); @@ -742,6 +742,28 @@ static int nvmem_add_cells_from_of(struct nvmem_device *nvmem) return 0; } +static int nvmem_add_cells_from_legacy_of(struct nvmem_device *nvmem) +{ + return nvmem_add_cells_from_dt(nvmem, nvmem->dev.of_node); +} + +static int nvmem_add_cells_from_fixed_layout(struct nvmem_device *nvmem) +{ + struct device_node *layout_np; + int err = 0; + + layout_np = of_nvmem_layout_get_container(nvmem); + if (!layout_np) + return 0; + + if (of_device_is_compatible(layout_np, "fixed-layout")) + err = nvmem_add_cells_from_dt(nvmem, layout_np); + + of_node_put(layout_np); + + return err; +} + int __nvmem_layout_register(struct nvmem_layout *layout, struct module *owner) { layout->owner = owner; @@ -972,7 +994,7 @@ struct nvmem_device *nvmem_register(const struct nvmem_config *config) if (rval) goto err_remove_cells; - rval = nvmem_add_cells_from_of(nvmem); + rval = nvmem_add_cells_from_legacy_of(nvmem); if (rval) goto err_remove_cells; @@ -982,6 +1004,10 @@ struct nvmem_device *nvmem_register(const struct nvmem_config *config) if (rval) goto err_remove_cells; + rval = nvmem_add_cells_from_fixed_layout(nvmem); + if (rval) + goto err_remove_cells; + rval = nvmem_add_cells_from_layout(nvmem); if (rval) goto err_remove_cells; diff --git a/drivers/nvmem/imx-ocotp-ele.c b/drivers/nvmem/imx-ocotp-ele.c new file mode 100644 index 0000000000000000000000000000000000000000..f1cbbc9afeb8a4db366c6635d0e38794db1d8e80 --- /dev/null +++ b/drivers/nvmem/imx-ocotp-ele.c @@ -0,0 +1,175 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * i.MX9 OCOTP fusebox driver + * + * Copyright 2023 NXP + */ + +#include +#include +#include +#include +#include +#include +#include + +enum fuse_type { + FUSE_FSB = 1, + FUSE_ELE = 2, + FUSE_INVALID = -1 +}; + +struct ocotp_map_entry { + u32 start; /* start word */ + u32 num; /* num words */ + enum fuse_type type; +}; + +struct ocotp_devtype_data { + u32 reg_off; + char *name; + u32 size; + u32 num_entry; + u32 flag; + nvmem_reg_read_t reg_read; + struct ocotp_map_entry entry[]; +}; + +struct imx_ocotp_priv { + struct device *dev; + void __iomem *base; + struct nvmem_config config; + struct mutex lock; + const struct ocotp_devtype_data *data; +}; + +static enum fuse_type imx_ocotp_fuse_type(void *context, u32 index) +{ + struct imx_ocotp_priv *priv = context; + const struct ocotp_devtype_data *data = priv->data; + u32 start, end; + int i; + + for (i = 0; i < data->num_entry; i++) { + start = data->entry[i].start; + end = data->entry[i].start + data->entry[i].num; + + if (index >= start && index < end) + return data->entry[i].type; + } + + return FUSE_INVALID; +} + +static int imx_ocotp_reg_read(void *context, unsigned int offset, void *val, size_t bytes) +{ + struct imx_ocotp_priv *priv = context; + void __iomem *reg = priv->base + priv->data->reg_off; + u32 count, index, num_bytes; + enum fuse_type type; + u32 *buf; + void *p; + int i; + + index = offset; + num_bytes = round_up(bytes, 4); + count = num_bytes >> 2; + + if (count > ((priv->data->size >> 2) - index)) + count = (priv->data->size >> 2) - index; + + p = kzalloc(num_bytes, GFP_KERNEL); + if (!p) + return -ENOMEM; + + mutex_lock(&priv->lock); + + buf = p; + + for (i = index; i < (index + count); i++) { + type = imx_ocotp_fuse_type(context, i); + if (type == FUSE_INVALID || type == FUSE_ELE) { + *buf++ = 0; + continue; + } + + *buf++ = readl_relaxed(reg + (i << 2)); + } + + memcpy(val, (u8 *)p, bytes); + + mutex_unlock(&priv->lock); + + kfree(p); + + return 0; +}; + +static int imx_ele_ocotp_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct imx_ocotp_priv *priv; + struct nvmem_device *nvmem; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->data = of_device_get_match_data(dev); + + priv->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(priv->base)) + return PTR_ERR(priv->base); + + priv->config.dev = dev; + priv->config.name = "ELE-OCOTP"; + priv->config.id = NVMEM_DEVID_AUTO; + priv->config.owner = THIS_MODULE; + priv->config.size = priv->data->size; + priv->config.reg_read = priv->data->reg_read; + priv->config.word_size = 4; + priv->config.stride = 1; + priv->config.priv = priv; + priv->config.read_only = true; + mutex_init(&priv->lock); + + nvmem = devm_nvmem_register(dev, &priv->config); + if (IS_ERR(nvmem)) + return PTR_ERR(nvmem); + + return 0; +} + +static const struct ocotp_devtype_data imx93_ocotp_data = { + .reg_off = 0x8000, + .reg_read = imx_ocotp_reg_read, + .size = 2048, + .num_entry = 6, + .entry = { + { 0, 52, FUSE_FSB }, + { 63, 1, FUSE_ELE}, + { 128, 16, FUSE_ELE }, + { 182, 1, FUSE_ELE }, + { 188, 1, FUSE_ELE }, + { 312, 200, FUSE_FSB } + }, +}; + +static const struct of_device_id imx_ele_ocotp_dt_ids[] = { + { .compatible = "fsl,imx93-ocotp", .data = &imx93_ocotp_data, }, + {}, +}; +MODULE_DEVICE_TABLE(of, imx_ele_ocotp_dt_ids); + +static struct platform_driver imx_ele_ocotp_driver = { + .driver = { + .name = "imx_ele_ocotp", + .of_match_table = imx_ele_ocotp_dt_ids, + }, + .probe = imx_ele_ocotp_probe, +}; +module_platform_driver(imx_ele_ocotp_driver); + +MODULE_DESCRIPTION("i.MX OCOTP/ELE driver"); +MODULE_AUTHOR("Peng Fan "); +MODULE_LICENSE("GPL"); diff --git a/drivers/nvmem/imx-ocotp.c b/drivers/nvmem/imx-ocotp.c index ac0edb6398f1eff41e72ae6f0d2e75f0c21cdf32..ab556c011f3e8e2eb441a003094fb296b485119c 100644 --- a/drivers/nvmem/imx-ocotp.c +++ b/drivers/nvmem/imx-ocotp.c @@ -97,7 +97,6 @@ struct ocotp_params { unsigned int bank_address_words; void (*set_timing)(struct ocotp_priv *priv); struct ocotp_ctrl_reg ctrl; - bool reverse_mac_address; }; static int imx_ocotp_wait_for_busy(struct ocotp_priv *priv, u32 flags) @@ -545,7 +544,6 @@ static const struct ocotp_params imx8mq_params = { .bank_address_words = 0, .set_timing = imx_ocotp_set_imx6_timing, .ctrl = IMX_OCOTP_BM_CTRL_DEFAULT, - .reverse_mac_address = true, }; static const struct ocotp_params imx8mm_params = { @@ -553,7 +551,6 @@ static const struct ocotp_params imx8mm_params = { .bank_address_words = 0, .set_timing = imx_ocotp_set_imx6_timing, .ctrl = IMX_OCOTP_BM_CTRL_DEFAULT, - .reverse_mac_address = true, }; static const struct ocotp_params imx8mn_params = { @@ -561,7 +558,6 @@ static const struct ocotp_params imx8mn_params = { .bank_address_words = 0, .set_timing = imx_ocotp_set_imx6_timing, .ctrl = IMX_OCOTP_BM_CTRL_DEFAULT, - .reverse_mac_address = true, }; static const struct ocotp_params imx8mp_params = { @@ -569,7 +565,6 @@ static const struct ocotp_params imx8mp_params = { .bank_address_words = 0, .set_timing = imx_ocotp_set_imx6_timing, .ctrl = IMX_OCOTP_BM_CTRL_8MP, - .reverse_mac_address = true, }; static const struct of_device_id imx_ocotp_dt_ids[] = { @@ -596,7 +591,7 @@ static void imx_ocotp_fixup_cell_info(struct nvmem_device *nvmem, cell->read_post_process = imx_ocotp_cell_pp; } -struct nvmem_layout imx_ocotp_layout = { +static struct nvmem_layout imx_ocotp_layout = { .fixup_cell_info = imx_ocotp_fixup_cell_info, }; @@ -624,8 +619,7 @@ static int imx_ocotp_probe(struct platform_device *pdev) imx_ocotp_nvmem_config.size = 4 * priv->params->nregs; imx_ocotp_nvmem_config.dev = dev; imx_ocotp_nvmem_config.priv = priv; - if (priv->params->reverse_mac_address) - imx_ocotp_nvmem_config.layout = &imx_ocotp_layout; + imx_ocotp_nvmem_config.layout = &imx_ocotp_layout; priv->config = &imx_ocotp_nvmem_config; diff --git a/drivers/nvmem/rmem.c b/drivers/nvmem/rmem.c index 80cb187f14817b2961c6d1de885710387bcd33c4..752d0bf4445eef70c92e417a853a2b05506afbf1 100644 --- a/drivers/nvmem/rmem.c +++ b/drivers/nvmem/rmem.c @@ -71,6 +71,7 @@ static int rmem_probe(struct platform_device *pdev) config.dev = dev; config.priv = priv; config.name = "rmem"; + config.id = NVMEM_DEVID_AUTO; config.size = mem->size; config.reg_read = rmem_read; diff --git a/drivers/nvmem/rockchip-otp.c b/drivers/nvmem/rockchip-otp.c index 9f53bcce2f877ff3fcfd7c850ed7960ef1f3755f..cb9aa5428350abd425639b29eb163f12e898909c 100644 --- a/drivers/nvmem/rockchip-otp.c +++ b/drivers/nvmem/rockchip-otp.c @@ -54,21 +54,32 @@ #define OTPC_TIMEOUT 10000 +/* RK3588 Register */ +#define RK3588_OTPC_AUTO_CTRL 0x04 +#define RK3588_OTPC_AUTO_EN 0x08 +#define RK3588_OTPC_INT_ST 0x84 +#define RK3588_OTPC_DOUT0 0x20 +#define RK3588_NO_SECURE_OFFSET 0x300 +#define RK3588_NBYTES 4 +#define RK3588_BURST_NUM 1 +#define RK3588_BURST_SHIFT 8 +#define RK3588_ADDR_SHIFT 16 +#define RK3588_AUTO_EN BIT(0) +#define RK3588_RD_DONE BIT(1) + +struct rockchip_data { + int size; + const char * const *clks; + int num_clks; + nvmem_reg_read_t reg_read; +}; + struct rockchip_otp { struct device *dev; void __iomem *base; - struct clk_bulk_data *clks; - int num_clks; + struct clk_bulk_data *clks; struct reset_control *rst; -}; - -/* list of required clocks */ -static const char * const rockchip_otp_clocks[] = { - "otp", "apb_pclk", "phy", -}; - -struct rockchip_data { - int size; + const struct rockchip_data *data; }; static int rockchip_otp_reset(struct rockchip_otp *otp) @@ -92,18 +103,19 @@ static int rockchip_otp_reset(struct rockchip_otp *otp) return 0; } -static int rockchip_otp_wait_status(struct rockchip_otp *otp, u32 flag) +static int rockchip_otp_wait_status(struct rockchip_otp *otp, + unsigned int reg, u32 flag) { u32 status = 0; int ret; - ret = readl_poll_timeout_atomic(otp->base + OTPC_INT_STATUS, status, + ret = readl_poll_timeout_atomic(otp->base + reg, status, (status & flag), 1, OTPC_TIMEOUT); if (ret) return ret; /* clean int status */ - writel(flag, otp->base + OTPC_INT_STATUS); + writel(flag, otp->base + reg); return 0; } @@ -125,36 +137,30 @@ static int rockchip_otp_ecc_enable(struct rockchip_otp *otp, bool enable) writel(SBPI_ENABLE_MASK | SBPI_ENABLE, otp->base + OTPC_SBPI_CTRL); - ret = rockchip_otp_wait_status(otp, OTPC_SBPI_DONE); + ret = rockchip_otp_wait_status(otp, OTPC_INT_STATUS, OTPC_SBPI_DONE); if (ret < 0) dev_err(otp->dev, "timeout during ecc_enable\n"); return ret; } -static int rockchip_otp_read(void *context, unsigned int offset, - void *val, size_t bytes) +static int px30_otp_read(void *context, unsigned int offset, + void *val, size_t bytes) { struct rockchip_otp *otp = context; u8 *buf = val; - int ret = 0; - - ret = clk_bulk_prepare_enable(otp->num_clks, otp->clks); - if (ret < 0) { - dev_err(otp->dev, "failed to prepare/enable clks\n"); - return ret; - } + int ret; ret = rockchip_otp_reset(otp); if (ret) { dev_err(otp->dev, "failed to reset otp phy\n"); - goto disable_clks; + return ret; } ret = rockchip_otp_ecc_enable(otp, false); if (ret < 0) { dev_err(otp->dev, "rockchip_otp_ecc_enable err\n"); - goto disable_clks; + return ret; } writel(OTPC_USE_USER | OTPC_USE_USER_MASK, otp->base + OTPC_USER_CTRL); @@ -164,7 +170,7 @@ static int rockchip_otp_read(void *context, unsigned int offset, otp->base + OTPC_USER_ADDR); writel(OTPC_USER_FSM_ENABLE | OTPC_USER_FSM_ENABLE_MASK, otp->base + OTPC_USER_ENABLE); - ret = rockchip_otp_wait_status(otp, OTPC_USER_DONE); + ret = rockchip_otp_wait_status(otp, OTPC_INT_STATUS, OTPC_USER_DONE); if (ret < 0) { dev_err(otp->dev, "timeout during read setup\n"); goto read_end; @@ -174,8 +180,74 @@ static int rockchip_otp_read(void *context, unsigned int offset, read_end: writel(0x0 | OTPC_USE_USER_MASK, otp->base + OTPC_USER_CTRL); -disable_clks: - clk_bulk_disable_unprepare(otp->num_clks, otp->clks); + + return ret; +} + +static int rk3588_otp_read(void *context, unsigned int offset, + void *val, size_t bytes) +{ + struct rockchip_otp *otp = context; + unsigned int addr_start, addr_end, addr_len; + int ret, i = 0; + u32 data; + u8 *buf; + + addr_start = round_down(offset, RK3588_NBYTES) / RK3588_NBYTES; + addr_end = round_up(offset + bytes, RK3588_NBYTES) / RK3588_NBYTES; + addr_len = addr_end - addr_start; + addr_start += RK3588_NO_SECURE_OFFSET; + + buf = kzalloc(array_size(addr_len, RK3588_NBYTES), GFP_KERNEL); + if (!buf) + return -ENOMEM; + + while (addr_len--) { + writel((addr_start << RK3588_ADDR_SHIFT) | + (RK3588_BURST_NUM << RK3588_BURST_SHIFT), + otp->base + RK3588_OTPC_AUTO_CTRL); + writel(RK3588_AUTO_EN, otp->base + RK3588_OTPC_AUTO_EN); + + ret = rockchip_otp_wait_status(otp, RK3588_OTPC_INT_ST, + RK3588_RD_DONE); + if (ret < 0) { + dev_err(otp->dev, "timeout during read setup\n"); + goto read_end; + } + + data = readl(otp->base + RK3588_OTPC_DOUT0); + memcpy(&buf[i], &data, RK3588_NBYTES); + + i += RK3588_NBYTES; + addr_start++; + } + + memcpy(val, buf + offset % RK3588_NBYTES, bytes); + +read_end: + kfree(buf); + + return ret; +} + +static int rockchip_otp_read(void *context, unsigned int offset, + void *val, size_t bytes) +{ + struct rockchip_otp *otp = context; + int ret; + + if (!otp->data || !otp->data->reg_read) + return -EINVAL; + + ret = clk_bulk_prepare_enable(otp->data->num_clks, otp->clks); + if (ret < 0) { + dev_err(otp->dev, "failed to prepare/enable clks\n"); + return ret; + } + + ret = otp->data->reg_read(context, offset, val, bytes); + + clk_bulk_disable_unprepare(otp->data->num_clks, otp->clks); return ret; } @@ -189,18 +261,40 @@ static struct nvmem_config otp_config = { .reg_read = rockchip_otp_read, }; +static const char * const px30_otp_clocks[] = { + "otp", "apb_pclk", "phy", +}; + static const struct rockchip_data px30_data = { .size = 0x40, + .clks = px30_otp_clocks, + .num_clks = ARRAY_SIZE(px30_otp_clocks), + .reg_read = px30_otp_read, +}; + +static const char * const rk3588_otp_clocks[] = { + "otp", "apb_pclk", "phy", "arb", +}; + +static const struct rockchip_data rk3588_data = { + .size = 0x400, + .clks = rk3588_otp_clocks, + .num_clks = ARRAY_SIZE(rk3588_otp_clocks), + .reg_read = rk3588_otp_read, }; static const struct of_device_id rockchip_otp_match[] = { { .compatible = "rockchip,px30-otp", - .data = (void *)&px30_data, + .data = &px30_data, }, { .compatible = "rockchip,rk3308-otp", - .data = (void *)&px30_data, + .data = &px30_data, + }, + { + .compatible = "rockchip,rk3588-otp", + .data = &rk3588_data, }, { /* sentinel */ }, }; @@ -215,44 +309,47 @@ static int rockchip_otp_probe(struct platform_device *pdev) int ret, i; data = of_device_get_match_data(dev); - if (!data) { - dev_err(dev, "failed to get match data\n"); - return -EINVAL; - } + if (!data) + return dev_err_probe(dev, -EINVAL, "failed to get match data\n"); otp = devm_kzalloc(&pdev->dev, sizeof(struct rockchip_otp), GFP_KERNEL); if (!otp) return -ENOMEM; + otp->data = data; otp->dev = dev; otp->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(otp->base)) - return PTR_ERR(otp->base); + return dev_err_probe(dev, PTR_ERR(otp->base), + "failed to ioremap resource\n"); - otp->num_clks = ARRAY_SIZE(rockchip_otp_clocks); - otp->clks = devm_kcalloc(dev, otp->num_clks, - sizeof(*otp->clks), GFP_KERNEL); + otp->clks = devm_kcalloc(dev, data->num_clks, sizeof(*otp->clks), + GFP_KERNEL); if (!otp->clks) return -ENOMEM; - for (i = 0; i < otp->num_clks; ++i) - otp->clks[i].id = rockchip_otp_clocks[i]; + for (i = 0; i < data->num_clks; ++i) + otp->clks[i].id = data->clks[i]; - ret = devm_clk_bulk_get(dev, otp->num_clks, otp->clks); + ret = devm_clk_bulk_get(dev, data->num_clks, otp->clks); if (ret) - return ret; + return dev_err_probe(dev, ret, "failed to get clocks\n"); - otp->rst = devm_reset_control_get(dev, "phy"); + otp->rst = devm_reset_control_array_get_exclusive(dev); if (IS_ERR(otp->rst)) - return PTR_ERR(otp->rst); + return dev_err_probe(dev, PTR_ERR(otp->rst), + "failed to get resets\n"); otp_config.size = data->size; otp_config.priv = otp; otp_config.dev = dev; - nvmem = devm_nvmem_register(dev, &otp_config); - return PTR_ERR_OR_ZERO(nvmem); + nvmem = devm_nvmem_register(dev, &otp_config); + if (IS_ERR(nvmem)) + return dev_err_probe(dev, PTR_ERR(nvmem), + "failed to register nvmem device\n"); + return 0; } static struct platform_driver rockchip_otp_driver = { diff --git a/drivers/nvmem/sunplus-ocotp.c b/drivers/nvmem/sunplus-ocotp.c index 52b928a7a6d580dae75ed0ea3cc104b96be4949f..f85350b17d6725f0b2a633156f9e95291c1c2e2b 100644 --- a/drivers/nvmem/sunplus-ocotp.c +++ b/drivers/nvmem/sunplus-ocotp.c @@ -192,9 +192,11 @@ static int sp_ocotp_probe(struct platform_device *pdev) sp_ocotp_nvmem_config.dev = dev; nvmem = devm_nvmem_register(dev, &sp_ocotp_nvmem_config); - if (IS_ERR(nvmem)) - return dev_err_probe(&pdev->dev, PTR_ERR(nvmem), + if (IS_ERR(nvmem)) { + ret = dev_err_probe(&pdev->dev, PTR_ERR(nvmem), "register nvmem device fail\n"); + goto err; + } platform_set_drvdata(pdev, nvmem); @@ -203,6 +205,9 @@ static int sp_ocotp_probe(struct platform_device *pdev) (int)OTP_WORD_SIZE, (int)QAC628_OTP_SIZE); return 0; +err: + clk_unprepare(otp->clk); + return ret; } static const struct of_device_id sp_ocotp_dt_ids[] = { diff --git a/drivers/nvmem/zynqmp_nvmem.c b/drivers/nvmem/zynqmp_nvmem.c index e28d7b133e11b07bd0f0277b9d6e1d85d9ee5b62..f49bb9a26d0532307d0ced507b1cbc1044160ef4 100644 --- a/drivers/nvmem/zynqmp_nvmem.c +++ b/drivers/nvmem/zynqmp_nvmem.c @@ -76,6 +76,6 @@ static struct platform_driver zynqmp_nvmem_driver = { module_platform_driver(zynqmp_nvmem_driver); -MODULE_AUTHOR("Michal Simek , Nava kishore Manne "); +MODULE_AUTHOR("Michal Simek , Nava kishore Manne "); MODULE_DESCRIPTION("ZynqMP NVMEM driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/of/of_reserved_mem.c b/drivers/of/of_reserved_mem.c index 948efa9f99e3bc907000731db166947f536568ae..7ec94cfcbddb18e3645212e57b6b96d4ee1645c7 100644 --- a/drivers/of/of_reserved_mem.c +++ b/drivers/of/of_reserved_mem.c @@ -77,6 +77,57 @@ void __init fdt_reserved_mem_save_node(unsigned long node, const char *uname, return; } +/* + * __reserved_mem_alloc_in_range() - allocate reserved memory described with + * 'alloc-ranges'. Choose bottom-up/top-down depending on nearby existing + * reserved regions to keep the reserved memory contiguous if possible. + */ +static int __init __reserved_mem_alloc_in_range(phys_addr_t size, + phys_addr_t align, phys_addr_t start, phys_addr_t end, bool nomap, + phys_addr_t *res_base) +{ + bool prev_bottom_up = memblock_bottom_up(); + bool bottom_up = false, top_down = false; + int ret, i; + + for (i = 0; i < reserved_mem_count; i++) { + struct reserved_mem *rmem = &reserved_mem[i]; + + /* Skip regions that were not reserved yet */ + if (rmem->size == 0) + continue; + + /* + * If range starts next to an existing reservation, use bottom-up: + * |....RRRR................RRRRRRRR..............| + * --RRRR------ + */ + if (start >= rmem->base && start <= (rmem->base + rmem->size)) + bottom_up = true; + + /* + * If range ends next to an existing reservation, use top-down: + * |....RRRR................RRRRRRRR..............| + * -------RRRR----- + */ + if (end >= rmem->base && end <= (rmem->base + rmem->size)) + top_down = true; + } + + /* Change setting only if either bottom-up or top-down was selected */ + if (bottom_up != top_down) + memblock_set_bottom_up(bottom_up); + + ret = early_init_dt_alloc_reserved_memory_arch(size, align, + start, end, nomap, res_base); + + /* Restore old setting if needed */ + if (bottom_up != top_down) + memblock_set_bottom_up(prev_bottom_up); + + return ret; +} + /* * __reserved_mem_alloc_size() - allocate reserved memory described by * 'size', 'alignment' and 'alloc-ranges' properties. @@ -137,8 +188,8 @@ static int __init __reserved_mem_alloc_size(unsigned long node, end = start + dt_mem_next_cell(dt_root_size_cells, &prop); - ret = early_init_dt_alloc_reserved_memory_arch(size, - align, start, end, nomap, &base); + ret = __reserved_mem_alloc_in_range(size, align, + start, end, nomap, &base); if (ret == 0) { pr_debug("allocated memory for '%s' node: base %pa, size %lu MiB\n", uname, &base, @@ -217,6 +268,11 @@ static int __init __rmem_cmp(const void *a, const void *b) if (ra->size > rb->size) return 1; + if (ra->fdt_node < rb->fdt_node) + return -1; + if (ra->fdt_node > rb->fdt_node) + return 1; + return 0; } diff --git a/drivers/of/platform.c b/drivers/of/platform.c index 78ae8418744905c9b038378e78699a1aeb111a1c..051e29b7ad2b83ad461119016714c80ed402a0f9 100644 --- a/drivers/of/platform.c +++ b/drivers/of/platform.c @@ -140,8 +140,8 @@ struct platform_device *of_device_alloc(struct device_node *np, } } - dev->dev.of_node = of_node_get(np); - dev->dev.fwnode = &np->fwnode; + /* setup generic device info */ + device_set_node(&dev->dev, of_fwnode_handle(np)); dev->dev.parent = parent ? : &platform_bus; if (bus_id) @@ -239,8 +239,7 @@ static struct amba_device *of_amba_device_create(struct device_node *node, dev->dev.dma_mask = &dev->dev.coherent_dma_mask; /* setup generic device info */ - dev->dev.of_node = of_node_get(node); - dev->dev.fwnode = &node->fwnode; + device_set_node(&dev->dev, of_fwnode_handle(node)); dev->dev.parent = parent ? : &platform_bus; dev->dev.platform_data = platform_data; if (bus_id) diff --git a/drivers/of/unittest.c b/drivers/of/unittest.c index 2191c01365317581e759d0c160524a7d85fc4ded..a406a12eb20804d658cb0adab9841fba31f7c5ff 100644 --- a/drivers/of/unittest.c +++ b/drivers/of/unittest.c @@ -1844,26 +1844,10 @@ static void __init of_unittest_overlay_gpio(void) unittest(overlay_data_apply("overlay_gpio_02b", NULL), "Adding overlay 'overlay_gpio_02b' failed\n"); - /* - * messages are the result of the probes, after the - * driver is registered - */ - - EXPECT_BEGIN(KERN_INFO, - "gpio-<> (line-B-input): hogged as input\n"); - - EXPECT_BEGIN(KERN_INFO, - "gpio-<> (line-A-input): hogged as input\n"); - ret = platform_driver_register(&unittest_gpio_driver); if (unittest(ret == 0, "could not register unittest gpio driver\n")) return; - EXPECT_END(KERN_INFO, - "gpio-<> (line-A-input): hogged as input\n"); - EXPECT_END(KERN_INFO, - "gpio-<> (line-B-input): hogged as input\n"); - unittest(probe_pass_count + 2 == unittest_gpio_probe_pass_count, "unittest_gpio_probe() failed or not called\n"); @@ -1888,17 +1872,11 @@ static void __init of_unittest_overlay_gpio(void) probe_pass_count = unittest_gpio_probe_pass_count; chip_request_count = unittest_gpio_chip_request_count; - EXPECT_BEGIN(KERN_INFO, - "gpio-<> (line-D-input): hogged as input\n"); - /* overlay_gpio_03 contains gpio node and child gpio hog node */ unittest(overlay_data_apply("overlay_gpio_03", NULL), "Adding overlay 'overlay_gpio_03' failed\n"); - EXPECT_END(KERN_INFO, - "gpio-<> (line-D-input): hogged as input\n"); - unittest(probe_pass_count + 1 == unittest_gpio_probe_pass_count, "unittest_gpio_probe() failed or not called\n"); @@ -1935,17 +1913,11 @@ static void __init of_unittest_overlay_gpio(void) * - processing gpio for overlay_gpio_04b */ - EXPECT_BEGIN(KERN_INFO, - "gpio-<> (line-C-input): hogged as input\n"); - /* overlay_gpio_04b contains child gpio hog node */ unittest(overlay_data_apply("overlay_gpio_04b", NULL), "Adding overlay 'overlay_gpio_04b' failed\n"); - EXPECT_END(KERN_INFO, - "gpio-<> (line-C-input): hogged as input\n"); - unittest(chip_request_count + 1 == unittest_gpio_chip_request_count, "unittest_gpio_chip_request() called %d times (expected 1 time)\n", unittest_gpio_chip_request_count - chip_request_count); @@ -2686,7 +2658,7 @@ static struct i2c_driver unittest_i2c_dev_driver = { .driver = { .name = "unittest-i2c-dev", }, - .probe_new = unittest_i2c_dev_probe, + .probe = unittest_i2c_dev_probe, .remove = unittest_i2c_dev_remove, .id_table = unittest_i2c_dev_id, }; @@ -2763,7 +2735,7 @@ static struct i2c_driver unittest_i2c_mux_driver = { .driver = { .name = "unittest-i2c-mux", }, - .probe_new = unittest_i2c_mux_probe, + .probe = unittest_i2c_mux_probe, .remove = unittest_i2c_mux_remove, .id_table = unittest_i2c_mux_id, }; diff --git a/drivers/opp/core.c b/drivers/opp/core.c index 954c94865cf56ef400348f1bc6c6d57aa3a97f19..3f46e499d615f2852622885aa7c40ff3faccb1db 100644 --- a/drivers/opp/core.c +++ b/drivers/opp/core.c @@ -29,9 +29,6 @@ */ LIST_HEAD(opp_tables); -/* OPP tables with uninitialized required OPPs */ -LIST_HEAD(lazy_opp_tables); - /* Lock to allow exclusive modification to the device and opp lists */ DEFINE_MUTEX(opp_table_lock); /* Flag indicating that opp_tables list is being updated at the moment */ @@ -230,17 +227,25 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_get_level); unsigned int dev_pm_opp_get_required_pstate(struct dev_pm_opp *opp, unsigned int index) { + struct opp_table *opp_table = opp->opp_table; + if (IS_ERR_OR_NULL(opp) || !opp->available || - index >= opp->opp_table->required_opp_count) { + index >= opp_table->required_opp_count) { pr_err("%s: Invalid parameters\n", __func__); return 0; } /* required-opps not fully initialized yet */ - if (lazy_linking_pending(opp->opp_table)) + if (lazy_linking_pending(opp_table)) return 0; - return opp->required_opps[index]->pstate; + /* The required OPP table must belong to a genpd */ + if (unlikely(!opp_table->required_opp_tables[index]->is_genpd)) { + pr_err("%s: Performance state is only valid for genpds.\n", __func__); + return 0; + } + + return opp->required_opps[index]->level; } EXPORT_SYMBOL_GPL(dev_pm_opp_get_required_pstate); @@ -938,7 +943,7 @@ static int _set_opp_bw(const struct opp_table *opp_table, static int _set_performance_state(struct device *dev, struct device *pd_dev, struct dev_pm_opp *opp, int i) { - unsigned int pstate = likely(opp) ? opp->required_opps[i]->pstate : 0; + unsigned int pstate = likely(opp) ? opp->required_opps[i]->level: 0; int ret; if (!pd_dev) @@ -1091,7 +1096,7 @@ static int _set_opp(struct device *dev, struct opp_table *opp_table, /* Return early if nothing to do */ if (!forced && old_opp == opp && opp_table->enabled) { - dev_dbg(dev, "%s: OPPs are same, nothing to do\n", __func__); + dev_dbg_ratelimited(dev, "%s: OPPs are same, nothing to do\n", __func__); return 0; } @@ -1358,7 +1363,10 @@ static struct opp_table *_allocate_opp_table(struct device *dev, int index) return opp_table; remove_opp_dev: + _of_clear_opp_table(opp_table); _remove_opp_dev(opp_dev, opp_table); + mutex_destroy(&opp_table->genpd_virt_dev_lock); + mutex_destroy(&opp_table->lock); err: kfree(opp_table); return ERR_PTR(ret); @@ -1522,16 +1530,8 @@ static void _opp_table_kref_release(struct kref *kref) WARN_ON(!list_empty(&opp_table->opp_list)); - list_for_each_entry_safe(opp_dev, temp, &opp_table->dev_list, node) { - /* - * The OPP table is getting removed, drop the performance state - * constraints. - */ - if (opp_table->genpd_performance_state) - dev_pm_genpd_set_performance_state((struct device *)(opp_dev->dev), 0); - + list_for_each_entry_safe(opp_dev, temp, &opp_table->dev_list, node) _remove_opp_dev(opp_dev, opp_table); - } mutex_destroy(&opp_table->genpd_virt_dev_lock); mutex_destroy(&opp_table->lock); @@ -2704,6 +2704,12 @@ int dev_pm_opp_xlate_performance_state(struct opp_table *src_table, if (!src_table || !src_table->required_opp_count) return pstate; + /* Both OPP tables must belong to genpds */ + if (unlikely(!src_table->is_genpd || !dst_table->is_genpd)) { + pr_err("%s: Performance state is only valid for genpds.\n", __func__); + return -EINVAL; + } + /* required-opps not fully initialized yet */ if (lazy_linking_pending(src_table)) return -EBUSY; @@ -2722,8 +2728,8 @@ int dev_pm_opp_xlate_performance_state(struct opp_table *src_table, mutex_lock(&src_table->lock); list_for_each_entry(opp, &src_table->opp_list, node) { - if (opp->pstate == pstate) { - dest_pstate = opp->required_opps[i]->pstate; + if (opp->level == pstate) { + dest_pstate = opp->required_opps[i]->level; goto unlock; } } diff --git a/drivers/opp/debugfs.c b/drivers/opp/debugfs.c index 2c7fb683441effcc7ceedc50296c8a53c8b59f14..17543c0aa5b6810bbe39170b5979ff0da2e2d2ad 100644 --- a/drivers/opp/debugfs.c +++ b/drivers/opp/debugfs.c @@ -152,7 +152,6 @@ void opp_debug_create_one(struct dev_pm_opp *opp, struct opp_table *opp_table) debugfs_create_bool("dynamic", S_IRUGO, d, &opp->dynamic); debugfs_create_bool("turbo", S_IRUGO, d, &opp->turbo); debugfs_create_bool("suspend", S_IRUGO, d, &opp->suspend); - debugfs_create_u32("performance_state", S_IRUGO, d, &opp->pstate); debugfs_create_u32("level", S_IRUGO, d, &opp->level); debugfs_create_ulong("clock_latency_ns", S_IRUGO, d, &opp->clock_latency_ns); diff --git a/drivers/opp/of.c b/drivers/opp/of.c index 8246e9b7afe7f970e94946ec23c7530edee1d5f2..ada4963c7cfae52643ec6d49ad2512be8e9c20e3 100644 --- a/drivers/opp/of.c +++ b/drivers/opp/of.c @@ -21,6 +21,9 @@ #include "opp.h" +/* OPP tables with uninitialized required OPPs, protected by opp_table_lock */ +static LIST_HEAD(lazy_opp_tables); + /* * Returns opp descriptor node for a device node, caller must * do of_node_put(). @@ -145,7 +148,10 @@ static void _opp_table_free_required_tables(struct opp_table *opp_table) opp_table->required_opp_count = 0; opp_table->required_opp_tables = NULL; + + mutex_lock(&opp_table_lock); list_del(&opp_table->lazy); + mutex_unlock(&opp_table_lock); } /* @@ -194,8 +200,15 @@ static void _opp_table_alloc_required_tables(struct opp_table *opp_table, } /* Let's do the linking later on */ - if (lazy) + if (lazy) { + /* + * The OPP table is not held while allocating the table, take it + * now to avoid corruption to the lazy_opp_tables list. + */ + mutex_lock(&opp_table_lock); list_add(&opp_table->lazy, &lazy_opp_tables); + mutex_unlock(&opp_table_lock); + } else _update_set_required_opps(opp_table); @@ -500,11 +513,7 @@ int dev_pm_opp_of_find_icc_paths(struct device *dev, for (i = 0; i < num_paths; i++) { paths[i] = of_icc_get_by_index(dev, i); if (IS_ERR(paths[i])) { - ret = PTR_ERR(paths[i]); - if (ret != -EPROBE_DEFER) { - dev_err(dev, "%s: Unable to get path%d: %d\n", - __func__, i, ret); - } + ret = dev_err_probe(dev, PTR_ERR(paths[i]), "%s: Unable to get path%d\n", __func__, i); goto err; } } @@ -932,9 +941,6 @@ static struct dev_pm_opp *_opp_add_static_v2(struct opp_table *opp_table, if (ret) goto free_required_opps; - if (opp_table->is_genpd) - new_opp->pstate = pm_genpd_opp_to_performance_state(dev, new_opp); - ret = _opp_add(dev, new_opp, opp_table); if (ret) { /* Don't return error for duplicate OPPs */ @@ -1021,14 +1027,6 @@ static int _of_add_opp_table_v2(struct device *dev, struct opp_table *opp_table) goto remove_static_opp; } - list_for_each_entry(opp, &opp_table->opp_list, node) { - /* Any non-zero performance state would enable the feature */ - if (opp->pstate) { - opp_table->genpd_performance_state = true; - break; - } - } - lazy_link_required_opp_table(opp_table); return 0; @@ -1387,9 +1385,15 @@ int of_get_required_opp_performance_state(struct device_node *np, int index) goto put_required_np; } + /* The OPP tables must belong to a genpd */ + if (unlikely(!opp_table->is_genpd)) { + pr_err("%s: Performance state is only valid for genpds.\n", __func__); + goto put_required_np; + } + opp = _find_opp_of_np(opp_table, required_np); if (opp) { - pstate = opp->pstate; + pstate = opp->level; dev_pm_opp_put(opp); } diff --git a/drivers/opp/opp.h b/drivers/opp/opp.h index 2a057c42ddf4d66c209c521596fb44ee46ea619e..8a5ea38f3a3d0c0fbccc4779db4f8e1a6625a104 100644 --- a/drivers/opp/opp.h +++ b/drivers/opp/opp.h @@ -26,7 +26,7 @@ struct regulator; /* Lock to allow exclusive modification to the device and opp lists */ extern struct mutex opp_table_lock; -extern struct list_head opp_tables, lazy_opp_tables; +extern struct list_head opp_tables; /* OPP Config flags */ #define OPP_CONFIG_CLK BIT(0) @@ -78,7 +78,6 @@ struct opp_config_data { * @turbo: true if turbo (boost) OPP * @suspend: true if suspend OPP * @removed: flag indicating that OPP's reference is dropped by OPP core. - * @pstate: Device's power domain's performance state. * @rates: Frequencies in hertz * @level: Performance level * @supplies: Power supplies voltage/current values @@ -101,7 +100,6 @@ struct dev_pm_opp { bool turbo; bool suspend; bool removed; - unsigned int pstate; unsigned long *rates; unsigned int level; @@ -182,7 +180,6 @@ enum opp_table_access { * @paths: Interconnect path handles * @path_count: Number of interconnect paths * @enabled: Set to true if the device's resources are enabled/configured. - * @genpd_performance_state: Device's power domain support performance state. * @is_genpd: Marks if the OPP table belongs to a genpd. * @set_required_opps: Helper responsible to set required OPPs. * @dentry: debugfs dentry pointer of the real device directory (not links). @@ -233,7 +230,6 @@ struct opp_table { struct icc_path **paths; unsigned int path_count; bool enabled; - bool genpd_performance_state; bool is_genpd; int (*set_required_opps)(struct device *dev, struct opp_table *opp_table, struct dev_pm_opp *opp, bool scaling_down); diff --git a/drivers/parisc/ccio-dma.c b/drivers/parisc/ccio-dma.c index a66386043aa6643d87216005c426da904a0408c7..9bf652bd002cf7d47947bbc70c8e4b9bc9d8a4c2 100644 --- a/drivers/parisc/ccio-dma.c +++ b/drivers/parisc/ccio-dma.c @@ -97,7 +97,6 @@ #define DBG_RUN_SG(x...) #endif -#define CCIO_INLINE inline #define WRITE_U32(value, addr) __raw_writel(value, addr) #define READ_U32(addr) __raw_readl(addr) @@ -330,7 +329,8 @@ static int ioc_count; /** * ccio_alloc_range - Allocate pages in the ioc's resource map. * @ioc: The I/O Controller. - * @pages_needed: The requested number of pages to be mapped into the + * @dev: The PCI device. + * @size: The requested number of bytes to be mapped into the * I/O Pdir... * * This function searches the resource map of the ioc to locate a range @@ -552,7 +552,7 @@ static u32 hint_lookup[] = { * (Load Coherence Index) instruction. The 8 bits used for the virtual * index are bits 12:19 of the value returned by LCI. */ -static void CCIO_INLINE +static void ccio_io_pdir_entry(u64 *pdir_ptr, space_t sid, unsigned long vba, unsigned long hints) { @@ -623,7 +623,7 @@ ccio_io_pdir_entry(u64 *pdir_ptr, space_t sid, unsigned long vba, * * FIXME: Can we change the byte_cnt to pages_mapped? */ -static CCIO_INLINE void +static void ccio_clear_io_tlb(struct ioc *ioc, dma_addr_t iovp, size_t byte_cnt) { u32 chain_size = 1 << ioc->chainid_shift; @@ -656,7 +656,7 @@ ccio_clear_io_tlb(struct ioc *ioc, dma_addr_t iovp, size_t byte_cnt) * * FIXME: Can we change byte_cnt to pages_mapped? */ -static CCIO_INLINE void +static void ccio_mark_invalid(struct ioc *ioc, dma_addr_t iova, size_t byte_cnt) { u32 iovp = (u32)CCIO_IOVP(iova); @@ -795,9 +795,10 @@ ccio_map_page(struct device *dev, struct page *page, unsigned long offset, /** * ccio_unmap_page - Unmap an address range from the IOMMU. * @dev: The PCI device. - * @addr: The start address of the DMA region. + * @iova: The start address of the DMA region. * @size: The length of the DMA region. * @direction: The direction of the DMA transaction (to/from device). + * @attrs: attributes */ static void ccio_unmap_page(struct device *dev, dma_addr_t iova, size_t size, @@ -838,6 +839,8 @@ ccio_unmap_page(struct device *dev, dma_addr_t iova, size_t size, * @dev: The PCI device. * @size: The length of the DMA region. * @dma_handle: The DMA address handed back to the device (not the cpu). + * @flag: allocation flags + * @attrs: attributes * * This function implements the pci_alloc_consistent function. */ @@ -872,6 +875,7 @@ ccio_alloc(struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t flag, * @size: The length of the DMA region. * @cpu_addr: The cpu address returned from the ccio_alloc_consistent. * @dma_handle: The device address returned from the ccio_alloc_consistent. + * @attrs: attributes * * This function implements the pci_free_consistent function. */ @@ -901,6 +905,7 @@ ccio_free(struct device *dev, size_t size, void *cpu_addr, * @sglist: The scatter/gather list to be mapped in the IOMMU. * @nents: The number of entries in the scatter/gather list. * @direction: The direction of the DMA transaction (to/from device). + * @attrs: attributes * * This function implements the pci_map_sg function. */ @@ -980,6 +985,7 @@ ccio_map_sg(struct device *dev, struct scatterlist *sglist, int nents, * @sglist: The scatter/gather list to be unmapped from the IOMMU. * @nents: The number of entries in the scatter/gather list. * @direction: The direction of the DMA transaction (to/from device). + * @attrs: attributes * * This function implements the pci_unmap_sg function. */ diff --git a/drivers/parisc/dino.c b/drivers/parisc/dino.c index e33036281327d484c9470772839ede70e7b5e85d..f89f9fb4c84bae6d316d1d03d8b894f81cc8a758 100644 --- a/drivers/parisc/dino.c +++ b/drivers/parisc/dino.c @@ -924,8 +924,6 @@ static const char cujo_vers[][4] = { "2.0" }; -void ccio_cujo20_fixup(struct parisc_device *dev, u32 iovp); - /* ** Determine if dino should claim this chip (return 0) or not (return 1). ** If so, initialize the chip appropriately (card-mode vs bridge mode). @@ -1086,9 +1084,8 @@ static struct parisc_driver dino_driver __refdata = { * This is the only routine which is NOT static. * Must be called exactly once before pci_init(). */ -int __init dino_init(void) +void __init dino_init(void) { register_parisc_driver(&dino_driver); - return 0; } diff --git a/drivers/parisc/eisa.c b/drivers/parisc/eisa.c index f96e5eaee87e6517a55806bf6c8d48d7941cd444..45e487388c6e684f4b1ab24699492fedb81ec505 100644 --- a/drivers/parisc/eisa.c +++ b/drivers/parisc/eisa.c @@ -400,7 +400,7 @@ static struct parisc_driver eisa_driver __refdata = { .probe = eisa_probe, }; -void __init eisa_init(void) +void __init parisc_eisa_init(void) { register_parisc_driver(&eisa_driver); } diff --git a/drivers/parisc/lba_pci.c b/drivers/parisc/lba_pci.c index afc6e66ddc31c93f3263ef9276d9cf81c22d956d..702bfd64e6e1264f9f83ce47abd51f61e8b96c71 100644 --- a/drivers/parisc/lba_pci.c +++ b/drivers/parisc/lba_pci.c @@ -404,7 +404,7 @@ static int elroy_cfg_read(struct pci_bus *bus, unsigned int devfn, int pos, int static void lba_wr_cfg(struct lba_device *d, u32 tok, u8 reg, u32 data, u32 size) { - int error = 0; + int error __maybe_unused = 0; u32 arb_mask = 0; u32 error_config = 0; u32 status_control = 0; @@ -1018,7 +1018,7 @@ static void lba_pat_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev) { unsigned long bytecnt; - long io_count; + long io_count __maybe_unused; long status; /* PDC return status */ long pa_count; pdc_pat_cell_mod_maddr_block_t *pa_pdc_cell; /* PA_VIEW */ @@ -1164,10 +1164,6 @@ lba_pat_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev) #endif /* CONFIG_64BIT */ -extern void sba_distributed_lmmio(struct parisc_device *, struct resource *); -extern void sba_directed_lmmio(struct parisc_device *, struct resource *); - - static void lba_legacy_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev) { diff --git a/drivers/parisc/pdc_stable.c b/drivers/parisc/pdc_stable.c index 2a18f7ba2398bcecf723d1a2be304c09c8a7c15d..633266447e2ffa2fa40ed68f8acfd3307381e7af 100644 --- a/drivers/parisc/pdc_stable.c +++ b/drivers/parisc/pdc_stable.c @@ -509,6 +509,8 @@ static struct pdcspath_entry *pdcspath_entries[] = { /** * pdcs_size_read - Stable Storage size output. + * @kobj: The kobject used to share data with userspace. + * @attr: The kobject attributes. * @buf: The output buffer to write to. */ static ssize_t pdcs_size_read(struct kobject *kobj, @@ -528,6 +530,8 @@ static ssize_t pdcs_size_read(struct kobject *kobj, /** * pdcs_auto_read - Stable Storage autoboot/search flag output. + * @kobj: The kobject used to share data with userspace. + * @attr: The kobject attributes. * @buf: The output buffer to write to. * @knob: The PF_AUTOBOOT or PF_AUTOSEARCH flag */ @@ -554,6 +558,8 @@ static ssize_t pdcs_auto_read(struct kobject *kobj, /** * pdcs_autoboot_read - Stable Storage autoboot flag output. + * @kobj: The kobject used to share data with userspace. + * @attr: The kobject attributes. * @buf: The output buffer to write to. */ static ssize_t pdcs_autoboot_read(struct kobject *kobj, @@ -564,6 +570,8 @@ static ssize_t pdcs_autoboot_read(struct kobject *kobj, /** * pdcs_autosearch_read - Stable Storage autoboot flag output. + * @kobj: The kobject used to share data with userspace. + * @attr: The kobject attributes. * @buf: The output buffer to write to. */ static ssize_t pdcs_autosearch_read(struct kobject *kobj, @@ -574,6 +582,8 @@ static ssize_t pdcs_autosearch_read(struct kobject *kobj, /** * pdcs_timer_read - Stable Storage timer count output (in seconds). + * @kobj: The kobject used to share data with userspace. + * @attr: The kobject attributes. * @buf: The output buffer to write to. * * The value of the timer field correponds to a number of seconds in powers of 2. @@ -601,6 +611,8 @@ static ssize_t pdcs_timer_read(struct kobject *kobj, /** * pdcs_osid_read - Stable Storage OS ID register output. + * @kobj: The kobject used to share data with userspace. + * @attr: The kobject attributes. * @buf: The output buffer to write to. */ static ssize_t pdcs_osid_read(struct kobject *kobj, @@ -619,6 +631,8 @@ static ssize_t pdcs_osid_read(struct kobject *kobj, /** * pdcs_osdep1_read - Stable Storage OS-Dependent data area 1 output. + * @kobj: The kobject used to share data with userspace. + * @attr: The kobject attributes. * @buf: The output buffer to write to. * * This can hold 16 bytes of OS-Dependent data. @@ -645,6 +659,8 @@ static ssize_t pdcs_osdep1_read(struct kobject *kobj, /** * pdcs_diagnostic_read - Stable Storage Diagnostic register output. + * @kobj: The kobject used to share data with userspace. + * @attr: The kobject attributes. * @buf: The output buffer to write to. * * I have NFC how to interpret the content of that register ;-). @@ -669,6 +685,8 @@ static ssize_t pdcs_diagnostic_read(struct kobject *kobj, /** * pdcs_fastsize_read - Stable Storage FastSize register output. + * @kobj: The kobject used to share data with userspace. + * @attr: The kobject attributes. * @buf: The output buffer to write to. * * This register holds the amount of system RAM to be tested during boot sequence. @@ -697,6 +715,8 @@ static ssize_t pdcs_fastsize_read(struct kobject *kobj, /** * pdcs_osdep2_read - Stable Storage OS-Dependent data area 2 output. + * @kobj: The kobject used to share data with userspace. + * @attr: The kobject attributes. * @buf: The output buffer to write to. * * This can hold pdcs_size - 224 bytes of OS-Dependent data, when available. @@ -729,6 +749,8 @@ static ssize_t pdcs_osdep2_read(struct kobject *kobj, /** * pdcs_auto_write - This function handles autoboot/search flag modifying. + * @kobj: The kobject used to share data with userspace. + * @attr: The kobject attributes. * @buf: The input buffer to read from. * @count: The number of bytes to be read. * @knob: The PF_AUTOBOOT or PF_AUTOSEARCH flag @@ -801,6 +823,8 @@ static ssize_t pdcs_auto_write(struct kobject *kobj, /** * pdcs_autoboot_write - This function handles autoboot flag modifying. + * @kobj: The kobject used to share data with userspace. + * @attr: The kobject attributes. * @buf: The input buffer to read from. * @count: The number of bytes to be read. * @@ -817,6 +841,8 @@ static ssize_t pdcs_autoboot_write(struct kobject *kobj, /** * pdcs_autosearch_write - This function handles autosearch flag modifying. + * @kobj: The kobject used to share data with userspace. + * @attr: The kobject attributes. * @buf: The input buffer to read from. * @count: The number of bytes to be read. * @@ -833,6 +859,8 @@ static ssize_t pdcs_autosearch_write(struct kobject *kobj, /** * pdcs_osdep1_write - Stable Storage OS-Dependent data area 1 input. + * @kobj: The kobject used to share data with userspace. + * @attr: The kobject attributes. * @buf: The input buffer to read from. * @count: The number of bytes to be read. * @@ -870,6 +898,8 @@ static ssize_t pdcs_osdep1_write(struct kobject *kobj, /** * pdcs_osdep2_write - Stable Storage OS-Dependent data area 2 input. + * @kobj: The kobject used to share data with userspace. + * @attr: The kobject attributes. * @buf: The input buffer to read from. * @count: The number of bytes to be read. * @@ -1023,7 +1053,7 @@ pdcs_unregister_pathentries(void) static int __init pdc_stable_init(void) { - int rc = 0, error = 0; + int rc = 0, error; u32 result; /* find the size of the stable storage */ @@ -1052,6 +1082,10 @@ pdc_stable_init(void) /* Don't forget the root entries */ error = sysfs_create_group(stable_kobj, &pdcs_attr_group); + if (error) { + rc = -ENOMEM; + goto fail_ksetreg; + } /* register the paths kset as a child of the stable kset */ paths_kset = kset_create_and_add("paths", NULL, stable_kobj); diff --git a/drivers/parisc/sba_iommu.c b/drivers/parisc/sba_iommu.c index ecd870087a3db23cbf2dd680487cde77245188bd..bf3405f4289e8f82ba9dd72d580a0c57902e70a3 100644 --- a/drivers/parisc/sba_iommu.c +++ b/drivers/parisc/sba_iommu.c @@ -95,8 +95,6 @@ #define DBG_RES(x...) #endif -#define SBA_INLINE __inline__ - #define DEFAULT_DMA_HINT_REG 0 struct sba_device *sba_list; @@ -332,13 +330,14 @@ static unsigned long ptr_to_pide(struct ioc *ioc, unsigned long *res_ptr, /** * sba_search_bitmap - find free space in IO PDIR resource bitmap * @ioc: IO MMU structure which owns the pdir we are interested in. + * @dev: device to query the bitmap for * @bits_wanted: number of entries we need. * * Find consecutive free bits in resource bitmap. * Each bit represents one entry in the IO Pdir. * Cool perf optimization: search for log2(size) bits at a time. */ -static SBA_INLINE unsigned long +static unsigned long sba_search_bitmap(struct ioc *ioc, struct device *dev, unsigned long bits_wanted) { @@ -431,6 +430,7 @@ sba_search_bitmap(struct ioc *ioc, struct device *dev, /** * sba_alloc_range - find free bits and mark them in IO PDIR resource bitmap * @ioc: IO MMU structure which owns the pdir we are interested in. + * @dev: device for which pages should be alloced * @size: number of bytes to create a mapping for * * Given a size, find consecutive unmarked and then mark those bits in the @@ -490,7 +490,7 @@ sba_alloc_range(struct ioc *ioc, struct device *dev, size_t size) * * clear bits in the ioc's resource map */ -static SBA_INLINE void +static void sba_free_range(struct ioc *ioc, dma_addr_t iova, size_t size) { unsigned long iovp = SBA_IOVP(ioc, iova); @@ -568,7 +568,7 @@ typedef unsigned long space_t; * IOMMU uses little endian for the pdir. */ -static void SBA_INLINE +static void sba_io_pdir_entry(u64 *pdir_ptr, space_t sid, unsigned long vba, unsigned long hint) { @@ -609,7 +609,7 @@ sba_io_pdir_entry(u64 *pdir_ptr, space_t sid, unsigned long vba, * must be a power of 2. The "Cool perf optimization" in the * allocation routine helps keep that true. */ -static SBA_INLINE void +static void sba_mark_invalid(struct ioc *ioc, dma_addr_t iova, size_t byte_cnt) { u32 iovp = (u32) SBA_IOVP(ioc,iova); @@ -793,6 +793,7 @@ sba_map_page(struct device *dev, struct page *page, unsigned long offset, * @iova: IOVA of driver buffer previously mapped. * @size: number of bytes mapped in driver buffer. * @direction: R/W or both. + * @attrs: attributes * * See Documentation/core-api/dma-api-howto.rst */ @@ -872,6 +873,8 @@ sba_unmap_page(struct device *dev, dma_addr_t iova, size_t size, * @hwdev: instance of PCI owned by the driver that's asking. * @size: number of bytes mapped in driver buffer. * @dma_handle: IOVA of new buffer. + * @gfp: allocation flags + * @attrs: attributes * * See Documentation/core-api/dma-api-howto.rst */ @@ -902,7 +905,8 @@ static void *sba_alloc(struct device *hwdev, size_t size, dma_addr_t *dma_handle * @hwdev: instance of PCI owned by the driver that's asking. * @size: number of bytes mapped in driver buffer. * @vaddr: virtual address IOVA of "consistent" buffer. - * @dma_handler: IO virtual address of "consistent" buffer. + * @dma_handle: IO virtual address of "consistent" buffer. + * @attrs: attributes * * See Documentation/core-api/dma-api-howto.rst */ @@ -938,6 +942,7 @@ int dump_run_sg = 0; * @sglist: array of buffer/length pairs * @nents: number of entries in list * @direction: R/W or both. + * @attrs: attributes * * See Documentation/core-api/dma-api-howto.rst */ @@ -946,7 +951,7 @@ sba_map_sg(struct device *dev, struct scatterlist *sglist, int nents, enum dma_data_direction direction, unsigned long attrs) { struct ioc *ioc; - int coalesced, filled = 0; + int filled = 0; unsigned long flags; DBG_RUN_SG("%s() START %d entries\n", __func__, nents); @@ -985,7 +990,7 @@ sba_map_sg(struct device *dev, struct scatterlist *sglist, int nents, ** w/o this association, we wouldn't have coherent DMA! ** Access to the virtual address is what forces a two pass algorithm. */ - coalesced = iommu_coalesce_chunks(ioc, dev, sglist, nents, sba_alloc_range); + iommu_coalesce_chunks(ioc, dev, sglist, nents, sba_alloc_range); /* ** Program the I/O Pdir @@ -1022,6 +1027,7 @@ sba_map_sg(struct device *dev, struct scatterlist *sglist, int nents, * @sglist: array of buffer/length pairs * @nents: number of entries in list * @direction: R/W or both. + * @attrs: attributes * * See Documentation/core-api/dma-api-howto.rst */ @@ -1229,8 +1235,6 @@ struct ibase_data_struct { static int setup_ibase_imask_callback(struct device *dev, void *data) { - /* lba_set_iregs() is in drivers/parisc/lba_pci.c */ - extern void lba_set_iregs(struct parisc_device *, u32, u32); struct parisc_device *lba = to_parisc_device(dev); struct ibase_data_struct *ibd = data; int rope_num = (lba->hpa.start >> 13) & 0xf; @@ -1992,7 +1996,7 @@ void __init sba_init(void) /** * sba_get_iommu - Assign the iommu pointer for the pci bus controller. - * @dev: The parisc device. + * @pci_hba: The parisc device. * * Returns the appropriate IOMMU data for the given parisc PCI controller. * This is cached and used later for PCI DMA Mapping. @@ -2012,7 +2016,7 @@ void * sba_get_iommu(struct parisc_device *pci_hba) /** * sba_directed_lmmio - return first directed LMMIO range routed to rope - * @pa_dev: The parisc device. + * @pci_hba: The parisc device. * @r: resource PCI host controller wants start/end fields assigned. * * For the given parisc PCI controller, determine if any direct ranges @@ -2054,7 +2058,7 @@ void sba_directed_lmmio(struct parisc_device *pci_hba, struct resource *r) /** * sba_distributed_lmmio - return portion of distributed LMMIO range - * @pa_dev: The parisc device. + * @pci_hba: The parisc device. * @r: resource PCI host controller wants start/end fields assigned. * * For the given parisc PCI controller, return portion of distributed LMMIO diff --git a/drivers/parport/Kconfig b/drivers/parport/Kconfig index 5561362224e254a71857d04a9fb1c0e79bdc0227..631c193fe42c5280e6808f312243ecd770fdb4fb 100644 --- a/drivers/parport/Kconfig +++ b/drivers/parport/Kconfig @@ -42,7 +42,8 @@ if PARPORT config PARPORT_PC tristate "PC-style hardware" - depends on ARCH_MIGHT_HAVE_PC_PARPORT || (PCI && !S390) + depends on ARCH_MIGHT_HAVE_PC_PARPORT || PCI + depends on HAS_IOPORT help You should say Y here if you have a PC-style parallel port. All IBM PC compatible computers and some Alphas have PC-style diff --git a/drivers/parport/procfs.c b/drivers/parport/procfs.c index d740eba3c0999ed77d0f9b78a8d6ee5876f20b46..4e5b972c3e2633527287e1ee663224654f8d55f9 100644 --- a/drivers/parport/procfs.c +++ b/drivers/parport/procfs.c @@ -32,6 +32,13 @@ #define PARPORT_MAX_TIMESLICE_VALUE ((unsigned long) HZ) #define PARPORT_MIN_SPINTIME_VALUE 1 #define PARPORT_MAX_SPINTIME_VALUE 1000 +/* + * PARPORT_BASE_* is the size of the known parts of the sysctl path + * in dev/partport/%s/devices/%s. "dev/parport/"(12), "/devices/"(9 + * and null char(1). + */ +#define PARPORT_BASE_PATH_SIZE 13 +#define PARPORT_BASE_DEVICES_PATH_SIZE 22 static int do_active_device(struct ctl_table *table, int write, void *result, size_t *lenp, loff_t *ppos) @@ -236,13 +243,6 @@ do { \ return 0; } -#define PARPORT_PORT_DIR(CHILD) { .procname = NULL, .mode = 0555, .child = CHILD } -#define PARPORT_PARPORT_DIR(CHILD) { .procname = "parport", \ - .mode = 0555, .child = CHILD } -#define PARPORT_DEV_DIR(CHILD) { .procname = "dev", .mode = 0555, .child = CHILD } -#define PARPORT_DEVICES_ROOT_DIR { .procname = "devices", \ - .mode = 0555, .child = NULL } - static const unsigned long parport_min_timeslice_value = PARPORT_MIN_TIMESLICE_VALUE; @@ -257,17 +257,16 @@ PARPORT_MAX_SPINTIME_VALUE; struct parport_sysctl_table { - struct ctl_table_header *sysctl_header; + struct ctl_table_header *port_header; + struct ctl_table_header *devices_header; struct ctl_table vars[12]; struct ctl_table device_dir[2]; - struct ctl_table port_dir[2]; - struct ctl_table parport_dir[2]; - struct ctl_table dev_dir[2]; }; static const struct parport_sysctl_table parport_sysctl_template = { - .sysctl_header = NULL, - { + .port_header = NULL, + .devices_header = NULL, + { { .procname = "spintime", .data = NULL, @@ -305,7 +304,6 @@ static const struct parport_sysctl_table parport_sysctl_template = { .mode = 0444, .proc_handler = do_hardware_modes }, - PARPORT_DEVICES_ROOT_DIR, #ifdef CONFIG_PARPORT_1284 { .procname = "autoprobe", @@ -355,18 +353,6 @@ static const struct parport_sysctl_table parport_sysctl_template = { }, {} }, - { - PARPORT_PORT_DIR(NULL), - {} - }, - { - PARPORT_PARPORT_DIR(NULL), - {} - }, - { - PARPORT_DEV_DIR(NULL), - {} - } }; struct parport_device_sysctl_table @@ -393,6 +379,7 @@ parport_device_sysctl_template = { .extra1 = (void*) &parport_min_timeslice_value, .extra2 = (void*) &parport_max_timeslice_value }, + {} }, { { @@ -400,25 +387,8 @@ parport_device_sysctl_template = { .data = NULL, .maxlen = 0, .mode = 0555, - .child = NULL }, {} - }, - { - PARPORT_DEVICES_ROOT_DIR, - {} - }, - { - PARPORT_PORT_DIR(NULL), - {} - }, - { - PARPORT_PARPORT_DIR(NULL), - {} - }, - { - PARPORT_DEV_DIR(NULL), - {} } }; @@ -454,30 +424,15 @@ parport_default_sysctl_table = { .extra2 = (void*) &parport_max_spintime_value }, {} - }, - { - { - .procname = "default", - .mode = 0555, - .child = parport_default_sysctl_table.vars - }, - {} - }, - { - PARPORT_PARPORT_DIR(parport_default_sysctl_table.default_dir), - {} - }, - { - PARPORT_DEV_DIR(parport_default_sysctl_table.parport_dir), - {} } }; - int parport_proc_register(struct parport *port) { struct parport_sysctl_table *t; - int i; + char *tmp_dir_path; + size_t tmp_path_len, port_name_len; + int bytes_written, i, err = 0; t = kmemdup(&parport_sysctl_template, sizeof(*t), GFP_KERNEL); if (t == NULL) @@ -485,28 +440,64 @@ int parport_proc_register(struct parport *port) t->device_dir[0].extra1 = port; - for (i = 0; i < 5; i++) + t->vars[0].data = &port->spintime; + for (i = 0; i < 5; i++) { t->vars[i].extra1 = port; + t->vars[5 + i].extra2 = &port->probe_info[i]; + } - t->vars[0].data = &port->spintime; - t->vars[5].child = t->device_dir; - - for (i = 0; i < 5; i++) - t->vars[6 + i].extra2 = &port->probe_info[i]; + port_name_len = strnlen(port->name, PARPORT_NAME_MAX_LEN); + /* + * Allocate a buffer for two paths: dev/parport/PORT and dev/parport/PORT/devices. + * We calculate for the second as that will give us enough for the first. + */ + tmp_path_len = PARPORT_BASE_DEVICES_PATH_SIZE + port_name_len; + tmp_dir_path = kzalloc(tmp_path_len, GFP_KERNEL); + if (!tmp_dir_path) { + err = -ENOMEM; + goto exit_free_t; + } - t->port_dir[0].procname = port->name; + bytes_written = snprintf(tmp_dir_path, tmp_path_len, + "dev/parport/%s/devices", port->name); + if (tmp_path_len <= bytes_written) { + err = -ENOENT; + goto exit_free_tmp_dir_path; + } + t->devices_header = register_sysctl(tmp_dir_path, t->device_dir); + if (t->devices_header == NULL) { + err = -ENOENT; + goto exit_free_tmp_dir_path; + } - t->port_dir[0].child = t->vars; - t->parport_dir[0].child = t->port_dir; - t->dev_dir[0].child = t->parport_dir; + tmp_path_len = PARPORT_BASE_PATH_SIZE + port_name_len; + bytes_written = snprintf(tmp_dir_path, tmp_path_len, + "dev/parport/%s", port->name); + if (tmp_path_len <= bytes_written) { + err = -ENOENT; + goto unregister_devices_h; + } - t->sysctl_header = register_sysctl_table(t->dev_dir); - if (t->sysctl_header == NULL) { - kfree(t); - t = NULL; + t->port_header = register_sysctl(tmp_dir_path, t->vars); + if (t->port_header == NULL) { + err = -ENOENT; + goto unregister_devices_h; } + port->sysctl_table = t; + + kfree(tmp_dir_path); return 0; + +unregister_devices_h: + unregister_sysctl_table(t->devices_header); + +exit_free_tmp_dir_path: + kfree(tmp_dir_path); + +exit_free_t: + kfree(t); + return err; } int parport_proc_unregister(struct parport *port) @@ -514,7 +505,8 @@ int parport_proc_unregister(struct parport *port) if (port->sysctl_table) { struct parport_sysctl_table *t = port->sysctl_table; port->sysctl_table = NULL; - unregister_sysctl_table(t->sysctl_header); + unregister_sysctl_table(t->devices_header); + unregister_sysctl_table(t->port_header); kfree(t); } return 0; @@ -522,30 +514,53 @@ int parport_proc_unregister(struct parport *port) int parport_device_proc_register(struct pardevice *device) { + int bytes_written, err = 0; struct parport_device_sysctl_table *t; struct parport * port = device->port; + size_t port_name_len, device_name_len, tmp_dir_path_len; + char *tmp_dir_path; t = kmemdup(&parport_device_sysctl_template, sizeof(*t), GFP_KERNEL); if (t == NULL) return -ENOMEM; - t->dev_dir[0].child = t->parport_dir; - t->parport_dir[0].child = t->port_dir; - t->port_dir[0].procname = port->name; - t->port_dir[0].child = t->devices_root_dir; - t->devices_root_dir[0].child = t->device_dir; + port_name_len = strnlen(port->name, PARPORT_NAME_MAX_LEN); + device_name_len = strnlen(device->name, PATH_MAX); + + /* Allocate a buffer for two paths: dev/parport/PORT/devices/DEVICE. */ + tmp_dir_path_len = PARPORT_BASE_DEVICES_PATH_SIZE + port_name_len + device_name_len; + tmp_dir_path = kzalloc(tmp_dir_path_len, GFP_KERNEL); + if (!tmp_dir_path) { + err = -ENOMEM; + goto exit_free_t; + } + + bytes_written = snprintf(tmp_dir_path, tmp_dir_path_len, "dev/parport/%s/devices/%s", + port->name, device->name); + if (tmp_dir_path_len <= bytes_written) { + err = -ENOENT; + goto exit_free_path; + } - t->device_dir[0].procname = device->name; - t->device_dir[0].child = t->vars; t->vars[0].data = &device->timeslice; - t->sysctl_header = register_sysctl_table(t->dev_dir); + t->sysctl_header = register_sysctl(tmp_dir_path, t->vars); if (t->sysctl_header == NULL) { kfree(t); t = NULL; } device->sysctl_table = t; + + kfree(tmp_dir_path); return 0; + +exit_free_path: + kfree(tmp_dir_path); + +exit_free_t: + kfree(t); + + return err; } int parport_device_proc_unregister(struct pardevice *device) @@ -564,7 +579,7 @@ static int __init parport_default_proc_register(void) int ret; parport_default_sysctl_table.sysctl_header = - register_sysctl_table(parport_default_sysctl_table.dev_dir); + register_sysctl("dev/parport/default", parport_default_sysctl_table.vars); if (!parport_default_sysctl_table.sysctl_header) return -ENOMEM; ret = parport_bus_init(); diff --git a/drivers/parport/share.c b/drivers/parport/share.c index 62f8407923d4a8e76ae34e8f909b3f226a153e91..2d46b1d4fd6953eb5655c3a062f0a95a6e465ceb 100644 --- a/drivers/parport/share.c +++ b/drivers/parport/share.c @@ -467,7 +467,7 @@ struct parport *parport_register_port(unsigned long base, int irq, int dma, atomic_set(&tmp->ref_count, 1); INIT_LIST_HEAD(&tmp->full_list); - name = kmalloc(15, GFP_KERNEL); + name = kmalloc(PARPORT_NAME_MAX_LEN, GFP_KERNEL); if (!name) { kfree(tmp); return NULL; diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig index 9309f2469b41db5d962af7f1cc447c7257aaf86d..3c07d8d214b389570739e3fb9e908cb3130fc5c2 100644 --- a/drivers/pci/Kconfig +++ b/drivers/pci/Kconfig @@ -168,6 +168,7 @@ config PCI_P2PDMA # depends on 64BIT select GENERIC_ALLOCATOR + select NEED_SG_DMA_FLAGS help Enableѕ drivers to do PCI peer-to-peer transactions to and from BARs that are exposed in other devices that are the part of diff --git a/drivers/pci/controller/cadence/pci-j721e.c b/drivers/pci/controller/cadence/pci-j721e.c index cc83a8925ce03ba3bfee3a9937a72d7961a3f2a9..e70213c9060a24d310abab2307aaba16651cb166 100644 --- a/drivers/pci/controller/cadence/pci-j721e.c +++ b/drivers/pci/controller/cadence/pci-j721e.c @@ -542,7 +542,7 @@ static int j721e_pcie_probe(struct platform_device *pdev) return ret; } -static int j721e_pcie_remove(struct platform_device *pdev) +static void j721e_pcie_remove(struct platform_device *pdev) { struct j721e_pcie *pcie = platform_get_drvdata(pdev); struct cdns_pcie *cdns_pcie = pcie->cdns_pcie; @@ -552,13 +552,11 @@ static int j721e_pcie_remove(struct platform_device *pdev) cdns_pcie_disable_phy(cdns_pcie); pm_runtime_put(dev); pm_runtime_disable(dev); - - return 0; } static struct platform_driver j721e_pcie_driver = { .probe = j721e_pcie_probe, - .remove = j721e_pcie_remove, + .remove_new = j721e_pcie_remove, .driver = { .name = "j721e-pcie", .of_match_table = of_j721e_pcie_match, diff --git a/drivers/pci/controller/cadence/pcie-cadence-host.c b/drivers/pci/controller/cadence/pcie-cadence-host.c index 940c7dd701d689862084b6a1a1fb943f0493340b..5b14f7ee3c798ed8ad6b381ddac92b626c55b03d 100644 --- a/drivers/pci/controller/cadence/pcie-cadence-host.c +++ b/drivers/pci/controller/cadence/pcie-cadence-host.c @@ -12,6 +12,8 @@ #include "pcie-cadence.h" +#define LINK_RETRAIN_TIMEOUT HZ + static u64 bar_max_size[] = { [RP_BAR0] = _ULL(128 * SZ_2G), [RP_BAR1] = SZ_2G, @@ -77,6 +79,27 @@ static struct pci_ops cdns_pcie_host_ops = { .write = pci_generic_config_write, }; +static int cdns_pcie_host_training_complete(struct cdns_pcie *pcie) +{ + u32 pcie_cap_off = CDNS_PCIE_RP_CAP_OFFSET; + unsigned long end_jiffies; + u16 lnk_stat; + + /* Wait for link training to complete. Exit after timeout. */ + end_jiffies = jiffies + LINK_RETRAIN_TIMEOUT; + do { + lnk_stat = cdns_pcie_rp_readw(pcie, pcie_cap_off + PCI_EXP_LNKSTA); + if (!(lnk_stat & PCI_EXP_LNKSTA_LT)) + break; + usleep_range(0, 1000); + } while (time_before(jiffies, end_jiffies)); + + if (!(lnk_stat & PCI_EXP_LNKSTA_LT)) + return 0; + + return -ETIMEDOUT; +} + static int cdns_pcie_host_wait_for_link(struct cdns_pcie *pcie) { struct device *dev = pcie->dev; @@ -118,6 +141,10 @@ static int cdns_pcie_retrain(struct cdns_pcie *pcie) cdns_pcie_rp_writew(pcie, pcie_cap_off + PCI_EXP_LNKCTL, lnk_ctl); + ret = cdns_pcie_host_training_complete(pcie); + if (ret) + return ret; + ret = cdns_pcie_host_wait_for_link(pcie); } return ret; diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c index 52906f999f2bb8fc20e0e216a23d585619281d8e..27aaa2a6bf391d23f6fbeffee533ab90b96508ee 100644 --- a/drivers/pci/controller/dwc/pci-imx6.c +++ b/drivers/pci/controller/dwc/pci-imx6.c @@ -80,6 +80,7 @@ struct imx6_pcie { struct clk *pcie; struct clk *pcie_aux; struct regmap *iomuxc_gpr; + u16 msi_ctrl; u32 controller_id; struct reset_control *pciephy_reset; struct reset_control *apps_reset; @@ -1178,6 +1179,26 @@ static void imx6_pcie_pm_turnoff(struct imx6_pcie *imx6_pcie) usleep_range(1000, 10000); } +static void imx6_pcie_msi_save_restore(struct imx6_pcie *imx6_pcie, bool save) +{ + u8 offset; + u16 val; + struct dw_pcie *pci = imx6_pcie->pci; + + if (pci_msi_enabled()) { + offset = dw_pcie_find_capability(pci, PCI_CAP_ID_MSI); + if (save) { + val = dw_pcie_readw_dbi(pci, offset + PCI_MSI_FLAGS); + imx6_pcie->msi_ctrl = val; + } else { + dw_pcie_dbi_ro_wr_en(pci); + val = imx6_pcie->msi_ctrl; + dw_pcie_writew_dbi(pci, offset + PCI_MSI_FLAGS, val); + dw_pcie_dbi_ro_wr_dis(pci); + } + } +} + static int imx6_pcie_suspend_noirq(struct device *dev) { struct imx6_pcie *imx6_pcie = dev_get_drvdata(dev); @@ -1186,6 +1207,7 @@ static int imx6_pcie_suspend_noirq(struct device *dev) if (!(imx6_pcie->drvdata->flags & IMX6_PCIE_FLAG_SUPPORTS_SUSPEND)) return 0; + imx6_pcie_msi_save_restore(imx6_pcie, true); imx6_pcie_pm_turnoff(imx6_pcie); imx6_pcie_stop_link(imx6_pcie->pci); imx6_pcie_host_exit(pp); @@ -1205,6 +1227,7 @@ static int imx6_pcie_resume_noirq(struct device *dev) ret = imx6_pcie_host_init(pp); if (ret) return ret; + imx6_pcie_msi_save_restore(imx6_pcie, false); dw_pcie_setup_rc(pp); if (imx6_pcie->link_is_up) diff --git a/drivers/pci/controller/dwc/pci-layerscape-ep.c b/drivers/pci/controller/dwc/pci-layerscape-ep.c index c640db60edc6a597440d8ea44ec053f28d2213e5..de4c1758a6c33bc9c7ff91bc1c62785047eb73c0 100644 --- a/drivers/pci/controller/dwc/pci-layerscape-ep.c +++ b/drivers/pci/controller/dwc/pci-layerscape-ep.c @@ -18,6 +18,20 @@ #include "pcie-designware.h" +#define PEX_PF0_CONFIG 0xC0014 +#define PEX_PF0_CFG_READY BIT(0) + +/* PEX PFa PCIE PME and message interrupt registers*/ +#define PEX_PF0_PME_MES_DR 0xC0020 +#define PEX_PF0_PME_MES_DR_LUD BIT(7) +#define PEX_PF0_PME_MES_DR_LDD BIT(9) +#define PEX_PF0_PME_MES_DR_HRD BIT(10) + +#define PEX_PF0_PME_MES_IER 0xC0028 +#define PEX_PF0_PME_MES_IER_LUDIE BIT(7) +#define PEX_PF0_PME_MES_IER_LDDIE BIT(9) +#define PEX_PF0_PME_MES_IER_HRDIE BIT(10) + #define to_ls_pcie_ep(x) dev_get_drvdata((x)->dev) struct ls_pcie_ep_drvdata { @@ -30,8 +44,84 @@ struct ls_pcie_ep { struct dw_pcie *pci; struct pci_epc_features *ls_epc; const struct ls_pcie_ep_drvdata *drvdata; + int irq; + bool big_endian; }; +static u32 ls_lut_readl(struct ls_pcie_ep *pcie, u32 offset) +{ + struct dw_pcie *pci = pcie->pci; + + if (pcie->big_endian) + return ioread32be(pci->dbi_base + offset); + else + return ioread32(pci->dbi_base + offset); +} + +static void ls_lut_writel(struct ls_pcie_ep *pcie, u32 offset, u32 value) +{ + struct dw_pcie *pci = pcie->pci; + + if (pcie->big_endian) + iowrite32be(value, pci->dbi_base + offset); + else + iowrite32(value, pci->dbi_base + offset); +} + +static irqreturn_t ls_pcie_ep_event_handler(int irq, void *dev_id) +{ + struct ls_pcie_ep *pcie = dev_id; + struct dw_pcie *pci = pcie->pci; + u32 val, cfg; + + val = ls_lut_readl(pcie, PEX_PF0_PME_MES_DR); + ls_lut_writel(pcie, PEX_PF0_PME_MES_DR, val); + + if (!val) + return IRQ_NONE; + + if (val & PEX_PF0_PME_MES_DR_LUD) { + cfg = ls_lut_readl(pcie, PEX_PF0_CONFIG); + cfg |= PEX_PF0_CFG_READY; + ls_lut_writel(pcie, PEX_PF0_CONFIG, cfg); + dw_pcie_ep_linkup(&pci->ep); + + dev_dbg(pci->dev, "Link up\n"); + } else if (val & PEX_PF0_PME_MES_DR_LDD) { + dev_dbg(pci->dev, "Link down\n"); + } else if (val & PEX_PF0_PME_MES_DR_HRD) { + dev_dbg(pci->dev, "Hot reset\n"); + } + + return IRQ_HANDLED; +} + +static int ls_pcie_ep_interrupt_init(struct ls_pcie_ep *pcie, + struct platform_device *pdev) +{ + u32 val; + int ret; + + pcie->irq = platform_get_irq_byname(pdev, "pme"); + if (pcie->irq < 0) + return pcie->irq; + + ret = devm_request_irq(&pdev->dev, pcie->irq, ls_pcie_ep_event_handler, + IRQF_SHARED, pdev->name, pcie); + if (ret) { + dev_err(&pdev->dev, "Can't register PCIe IRQ\n"); + return ret; + } + + /* Enable interrupts */ + val = ls_lut_readl(pcie, PEX_PF0_PME_MES_IER); + val |= PEX_PF0_PME_MES_IER_LDDIE | PEX_PF0_PME_MES_IER_HRDIE | + PEX_PF0_PME_MES_IER_LUDIE; + ls_lut_writel(pcie, PEX_PF0_PME_MES_IER, val); + + return 0; +} + static const struct pci_epc_features* ls_pcie_ep_get_features(struct dw_pcie_ep *ep) { @@ -125,6 +215,7 @@ static int __init ls_pcie_ep_probe(struct platform_device *pdev) struct ls_pcie_ep *pcie; struct pci_epc_features *ls_epc; struct resource *dbi_base; + int ret; pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL); if (!pcie) @@ -144,6 +235,7 @@ static int __init ls_pcie_ep_probe(struct platform_device *pdev) pci->ops = pcie->drvdata->dw_pcie_ops; ls_epc->bar_fixed_64bit = (1 << BAR_2) | (1 << BAR_4); + ls_epc->linkup_notifier = true; pcie->pci = pci; pcie->ls_epc = ls_epc; @@ -155,9 +247,15 @@ static int __init ls_pcie_ep_probe(struct platform_device *pdev) pci->ep.ops = &ls_pcie_ep_ops; + pcie->big_endian = of_property_read_bool(dev->of_node, "big-endian"); + platform_set_drvdata(pdev, pcie); - return dw_pcie_ep_init(&pci->ep); + ret = dw_pcie_ep_init(&pci->ep); + if (ret) + return ret; + + return ls_pcie_ep_interrupt_init(pcie, pdev); } static struct platform_driver ls_pcie_ep_driver = { diff --git a/drivers/pci/controller/dwc/pcie-bt1.c b/drivers/pci/controller/dwc/pcie-bt1.c index 95a723a6fd4634fbc17f5d89ff5c1df2fe80ec90..17e696797ff50f92116190059310a4e0ae8e170e 100644 --- a/drivers/pci/controller/dwc/pcie-bt1.c +++ b/drivers/pci/controller/dwc/pcie-bt1.c @@ -617,13 +617,11 @@ static int bt1_pcie_probe(struct platform_device *pdev) return bt1_pcie_add_port(btpci); } -static int bt1_pcie_remove(struct platform_device *pdev) +static void bt1_pcie_remove(struct platform_device *pdev) { struct bt1_pcie *btpci = platform_get_drvdata(pdev); bt1_pcie_del_port(btpci); - - return 0; } static const struct of_device_id bt1_pcie_of_match[] = { @@ -634,7 +632,7 @@ MODULE_DEVICE_TABLE(of, bt1_pcie_of_match); static struct platform_driver bt1_pcie_driver = { .probe = bt1_pcie_probe, - .remove = bt1_pcie_remove, + .remove_new = bt1_pcie_remove, .driver = { .name = "bt1-pcie", .of_match_table = bt1_pcie_of_match, diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c index 9952057c8819c86ac7bb97dfe709f6337ddfa7c6..cf61733bf78d24a99114bb8bdf3262a771d5b44b 100644 --- a/drivers/pci/controller/dwc/pcie-designware-host.c +++ b/drivers/pci/controller/dwc/pcie-designware-host.c @@ -485,14 +485,19 @@ int dw_pcie_host_init(struct dw_pcie_rp *pp) if (ret) goto err_remove_edma; - if (!dw_pcie_link_up(pci)) { + if (dw_pcie_link_up(pci)) { + dw_pcie_print_link_status(pci); + } else { ret = dw_pcie_start_link(pci); if (ret) goto err_remove_edma; - } - /* Ignore errors, the link may come up later */ - dw_pcie_wait_for_link(pci); + if (pci->ops && pci->ops->start_link) { + ret = dw_pcie_wait_for_link(pci); + if (ret) + goto err_stop_link; + } + } bridge->sysdata = pp; diff --git a/drivers/pci/controller/dwc/pcie-designware.c b/drivers/pci/controller/dwc/pcie-designware.c index 8e33e6e59e686b5d5e8462fdc737ca84ea349397..c87848cd8686c0337bbd2db21f9c7b6d66bf9001 100644 --- a/drivers/pci/controller/dwc/pcie-designware.c +++ b/drivers/pci/controller/dwc/pcie-designware.c @@ -644,9 +644,20 @@ void dw_pcie_disable_atu(struct dw_pcie *pci, u32 dir, int index) dw_pcie_writel_atu(pci, dir, index, PCIE_ATU_REGION_CTRL2, 0); } -int dw_pcie_wait_for_link(struct dw_pcie *pci) +void dw_pcie_print_link_status(struct dw_pcie *pci) { u32 offset, val; + + offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP); + val = dw_pcie_readw_dbi(pci, offset + PCI_EXP_LNKSTA); + + dev_info(pci->dev, "PCIe Gen.%u x%u link up\n", + FIELD_GET(PCI_EXP_LNKSTA_CLS, val), + FIELD_GET(PCI_EXP_LNKSTA_NLW, val)); +} + +int dw_pcie_wait_for_link(struct dw_pcie *pci) +{ int retries; /* Check if the link is up or not */ @@ -662,12 +673,7 @@ int dw_pcie_wait_for_link(struct dw_pcie *pci) return -ETIMEDOUT; } - offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP); - val = dw_pcie_readw_dbi(pci, offset + PCI_EXP_LNKSTA); - - dev_info(pci->dev, "PCIe Gen.%u x%u link up\n", - FIELD_GET(PCI_EXP_LNKSTA_CLS, val), - FIELD_GET(PCI_EXP_LNKSTA_NLW, val)); + dw_pcie_print_link_status(pci); return 0; } @@ -828,7 +834,7 @@ static int dw_pcie_edma_irq_vector(struct device *dev, unsigned int nr) return platform_get_irq_byname_optional(pdev, name); } -static struct dw_edma_core_ops dw_pcie_edma_ops = { +static struct dw_edma_plat_ops dw_pcie_edma_ops = { .irq_vector = dw_pcie_edma_irq_vector, }; diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h index 79713ce075cc1b6b3c1eff6b8535813c87837076..615660640801968cf5b76d36b9ceab3c3984d3f1 100644 --- a/drivers/pci/controller/dwc/pcie-designware.h +++ b/drivers/pci/controller/dwc/pcie-designware.h @@ -429,6 +429,7 @@ void dw_pcie_setup(struct dw_pcie *pci); void dw_pcie_iatu_detect(struct dw_pcie *pci); int dw_pcie_edma_detect(struct dw_pcie *pci); void dw_pcie_edma_remove(struct dw_pcie *pci); +void dw_pcie_print_link_status(struct dw_pcie *pci); static inline void dw_pcie_writel_dbi(struct dw_pcie *pci, u32 reg, u32 val) { diff --git a/drivers/pci/controller/dwc/pcie-histb.c b/drivers/pci/controller/dwc/pcie-histb.c index 927ae05dc920151bf11e67d522c8221bd8fefda1..fd484cc7c481dc8e54efeb4e469350aae80bcb7d 100644 --- a/drivers/pci/controller/dwc/pcie-histb.c +++ b/drivers/pci/controller/dwc/pcie-histb.c @@ -421,7 +421,7 @@ static int histb_pcie_probe(struct platform_device *pdev) return 0; } -static int histb_pcie_remove(struct platform_device *pdev) +static void histb_pcie_remove(struct platform_device *pdev) { struct histb_pcie *hipcie = platform_get_drvdata(pdev); @@ -429,8 +429,6 @@ static int histb_pcie_remove(struct platform_device *pdev) if (hipcie->phy) phy_exit(hipcie->phy); - - return 0; } static const struct of_device_id histb_pcie_of_match[] = { @@ -441,7 +439,7 @@ MODULE_DEVICE_TABLE(of, histb_pcie_of_match); static struct platform_driver histb_pcie_platform_driver = { .probe = histb_pcie_probe, - .remove = histb_pcie_remove, + .remove_new = histb_pcie_remove, .driver = { .name = "histb-pcie", .of_match_table = histb_pcie_of_match, diff --git a/drivers/pci/controller/dwc/pcie-intel-gw.c b/drivers/pci/controller/dwc/pcie-intel-gw.c index 333c33d98a7018017b956c316999afab07ba7263..9c7caed9e706db80721322799faafe9f49f24ad0 100644 --- a/drivers/pci/controller/dwc/pcie-intel-gw.c +++ b/drivers/pci/controller/dwc/pcie-intel-gw.c @@ -340,15 +340,13 @@ static void __intel_pcie_remove(struct intel_pcie *pcie) phy_exit(pcie->phy); } -static int intel_pcie_remove(struct platform_device *pdev) +static void intel_pcie_remove(struct platform_device *pdev) { struct intel_pcie *pcie = platform_get_drvdata(pdev); struct dw_pcie_rp *pp = &pcie->pci.pp; dw_pcie_host_deinit(pp); __intel_pcie_remove(pcie); - - return 0; } static int intel_pcie_suspend_noirq(struct device *dev) @@ -443,7 +441,7 @@ static const struct of_device_id of_intel_pcie_match[] = { static struct platform_driver intel_pcie_driver = { .probe = intel_pcie_probe, - .remove = intel_pcie_remove, + .remove_new = intel_pcie_remove, .driver = { .name = "intel-gw-pcie", .of_match_table = of_intel_pcie_match, diff --git a/drivers/pci/controller/dwc/pcie-qcom-ep.c b/drivers/pci/controller/dwc/pcie-qcom-ep.c index 19b32839ea2610ae7cbee6d5870a5582632691e0..0fe7f06f21026d1a85b87324150a40f9d575c0f0 100644 --- a/drivers/pci/controller/dwc/pcie-qcom-ep.c +++ b/drivers/pci/controller/dwc/pcie-qcom-ep.c @@ -569,9 +569,11 @@ static irqreturn_t qcom_pcie_ep_global_irq_thread(int irq, void *data) if (FIELD_GET(PARF_INT_ALL_LINK_DOWN, status)) { dev_dbg(dev, "Received Linkdown event\n"); pcie_ep->link_status = QCOM_PCIE_EP_LINK_DOWN; + pci_epc_linkdown(pci->ep.epc); } else if (FIELD_GET(PARF_INT_ALL_BME, status)) { dev_dbg(dev, "Received BME event. Link is enabled!\n"); pcie_ep->link_status = QCOM_PCIE_EP_LINK_ENABLED; + pci_epc_bme_notify(pci->ep.epc); } else if (FIELD_GET(PARF_INT_ALL_PM_TURNOFF, status)) { dev_dbg(dev, "Received PM Turn-off event! Entering L23\n"); val = readl_relaxed(pcie_ep->parf + PARF_PM_CTRL); @@ -784,7 +786,7 @@ static int qcom_pcie_ep_probe(struct platform_device *pdev) return ret; } -static int qcom_pcie_ep_remove(struct platform_device *pdev) +static void qcom_pcie_ep_remove(struct platform_device *pdev) { struct qcom_pcie_ep *pcie_ep = platform_get_drvdata(pdev); @@ -794,11 +796,9 @@ static int qcom_pcie_ep_remove(struct platform_device *pdev) debugfs_remove_recursive(pcie_ep->debugfs); if (pcie_ep->link_status == QCOM_PCIE_EP_LINK_DISABLED) - return 0; + return; qcom_pcie_disable_resources(pcie_ep); - - return 0; } static const struct of_device_id qcom_pcie_ep_match[] = { @@ -810,7 +810,7 @@ MODULE_DEVICE_TABLE(of, qcom_pcie_ep_match); static struct platform_driver qcom_pcie_ep_driver = { .probe = qcom_pcie_ep_probe, - .remove = qcom_pcie_ep_remove, + .remove_new = qcom_pcie_ep_remove, .driver = { .name = "qcom-pcie-ep", .of_match_table = qcom_pcie_ep_match, diff --git a/drivers/pci/controller/dwc/pcie-qcom.c b/drivers/pci/controller/dwc/pcie-qcom.c index 4ab30892f6efbc70e8cf5b1f3475b9fed16cbccb..7a87a47eb7edbbc4072cedf5f2c5ffa60a101a3e 100644 --- a/drivers/pci/controller/dwc/pcie-qcom.c +++ b/drivers/pci/controller/dwc/pcie-qcom.c @@ -61,7 +61,6 @@ /* DBI registers */ #define AXI_MSTR_RESP_COMP_CTRL0 0x818 #define AXI_MSTR_RESP_COMP_CTRL1 0x81c -#define MISC_CONTROL_1_REG 0x8bc /* MHI registers */ #define PARF_DEBUG_CNT_PM_LINKST_IN_L2 0xc04 @@ -132,9 +131,6 @@ /* AXI_MSTR_RESP_COMP_CTRL1 register fields */ #define CFG_BRIDGE_SB_INIT BIT(0) -/* MISC_CONTROL_1_REG register fields */ -#define DBI_RO_WR_EN 1 - /* PCI_EXP_SLTCAP register fields */ #define PCIE_CAP_SLOT_POWER_LIMIT_VAL FIELD_PREP(PCI_EXP_SLTCAP_SPLV, 250) #define PCIE_CAP_SLOT_POWER_LIMIT_SCALE FIELD_PREP(PCI_EXP_SLTCAP_SPLS, 1) @@ -144,7 +140,6 @@ PCI_EXP_SLTCAP_AIP | \ PCI_EXP_SLTCAP_PIP | \ PCI_EXP_SLTCAP_HPS | \ - PCI_EXP_SLTCAP_HPC | \ PCI_EXP_SLTCAP_EIP | \ PCIE_CAP_SLOT_POWER_LIMIT_VAL | \ PCIE_CAP_SLOT_POWER_LIMIT_SCALE) @@ -274,6 +269,20 @@ static int qcom_pcie_start_link(struct dw_pcie *pci) return 0; } +static void qcom_pcie_clear_hpc(struct dw_pcie *pci) +{ + u16 offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP); + u32 val; + + dw_pcie_dbi_ro_wr_en(pci); + + val = readl(pci->dbi_base + offset + PCI_EXP_SLTCAP); + val &= ~PCI_EXP_SLTCAP_HPC; + writel(val, pci->dbi_base + offset + PCI_EXP_SLTCAP); + + dw_pcie_dbi_ro_wr_dis(pci); +} + static void qcom_pcie_2_1_0_ltssm_enable(struct qcom_pcie *pcie) { u32 val; @@ -429,6 +438,8 @@ static int qcom_pcie_post_init_2_1_0(struct qcom_pcie *pcie) writel(CFG_BRIDGE_SB_INIT, pci->dbi_base + AXI_MSTR_RESP_COMP_CTRL1); + qcom_pcie_clear_hpc(pcie->pci); + return 0; } @@ -512,6 +523,8 @@ static int qcom_pcie_post_init_1_0_0(struct qcom_pcie *pcie) writel(val, pcie->parf + PARF_AXI_MSTR_WR_ADDR_HALT); } + qcom_pcie_clear_hpc(pcie->pci); + return 0; } @@ -607,6 +620,8 @@ static int qcom_pcie_post_init_2_3_2(struct qcom_pcie *pcie) val |= EN; writel(val, pcie->parf + PARF_AXI_MSTR_WR_ADDR_HALT_V2); + qcom_pcie_clear_hpc(pcie->pci); + return 0; } @@ -692,34 +707,6 @@ static int qcom_pcie_init_2_4_0(struct qcom_pcie *pcie) return 0; } -static int qcom_pcie_post_init_2_4_0(struct qcom_pcie *pcie) -{ - u32 val; - - /* enable PCIe clocks and resets */ - val = readl(pcie->parf + PARF_PHY_CTRL); - val &= ~PHY_TEST_PWR_DOWN; - writel(val, pcie->parf + PARF_PHY_CTRL); - - /* change DBI base address */ - writel(0, pcie->parf + PARF_DBI_BASE_ADDR); - - /* MAC PHY_POWERDOWN MUX DISABLE */ - val = readl(pcie->parf + PARF_SYS_CTRL); - val &= ~MAC_PHY_POWERDOWN_IN_P2_D_MUX_EN; - writel(val, pcie->parf + PARF_SYS_CTRL); - - val = readl(pcie->parf + PARF_MHI_CLOCK_RESET_CTRL); - val |= BYPASS; - writel(val, pcie->parf + PARF_MHI_CLOCK_RESET_CTRL); - - val = readl(pcie->parf + PARF_AXI_MSTR_WR_ADDR_HALT_V2); - val |= EN; - writel(val, pcie->parf + PARF_AXI_MSTR_WR_ADDR_HALT_V2); - - return 0; -} - static int qcom_pcie_get_resources_2_3_3(struct qcom_pcie *pcie) { struct qcom_pcie_resources_2_3_3 *res = &pcie->res.v2_3_3; @@ -826,7 +813,9 @@ static int qcom_pcie_post_init_2_3_3(struct qcom_pcie *pcie) writel(0, pcie->parf + PARF_Q2A_FLUSH); writel(PCI_COMMAND_MASTER, pci->dbi_base + PCI_COMMAND); - writel(DBI_RO_WR_EN, pci->dbi_base + MISC_CONTROL_1_REG); + + dw_pcie_dbi_ro_wr_en(pci); + writel(PCIE_CAP_SLOT_VAL, pci->dbi_base + offset + PCI_EXP_SLTCAP); val = readl(pci->dbi_base + offset + PCI_EXP_LNKCAP); @@ -836,6 +825,8 @@ static int qcom_pcie_post_init_2_3_3(struct qcom_pcie *pcie) writel(PCI_EXP_DEVCTL2_COMP_TMOUT_DIS, pci->dbi_base + offset + PCI_EXP_DEVCTL2); + dw_pcie_dbi_ro_wr_dis(pci); + return 0; } @@ -966,6 +957,13 @@ static int qcom_pcie_init_2_7_0(struct qcom_pcie *pcie) return ret; } +static int qcom_pcie_post_init_2_7_0(struct qcom_pcie *pcie) +{ + qcom_pcie_clear_hpc(pcie->pci); + + return 0; +} + static void qcom_pcie_deinit_2_7_0(struct qcom_pcie *pcie) { struct qcom_pcie_resources_2_7_0 *res = &pcie->res.v2_7_0; @@ -1136,6 +1134,7 @@ static int qcom_pcie_post_init_2_9_0(struct qcom_pcie *pcie) writel(0, pcie->parf + PARF_Q2A_FLUSH); dw_pcie_dbi_ro_wr_en(pci); + writel(PCIE_CAP_SLOT_VAL, pci->dbi_base + offset + PCI_EXP_SLTCAP); val = readl(pci->dbi_base + offset + PCI_EXP_LNKCAP); @@ -1145,6 +1144,8 @@ static int qcom_pcie_post_init_2_9_0(struct qcom_pcie *pcie) writel(PCI_EXP_DEVCTL2_COMP_TMOUT_DIS, pci->dbi_base + offset + PCI_EXP_DEVCTL2); + dw_pcie_dbi_ro_wr_dis(pci); + for (i = 0; i < 256; i++) writel(0, pcie->parf + PARF_BDF_TO_SID_TABLE_N + (4 * i)); @@ -1251,7 +1252,7 @@ static const struct qcom_pcie_ops ops_2_3_2 = { static const struct qcom_pcie_ops ops_2_4_0 = { .get_resources = qcom_pcie_get_resources_2_4_0, .init = qcom_pcie_init_2_4_0, - .post_init = qcom_pcie_post_init_2_4_0, + .post_init = qcom_pcie_post_init_2_3_2, .deinit = qcom_pcie_deinit_2_4_0, .ltssm_enable = qcom_pcie_2_3_2_ltssm_enable, }; @@ -1269,6 +1270,7 @@ static const struct qcom_pcie_ops ops_2_3_3 = { static const struct qcom_pcie_ops ops_2_7_0 = { .get_resources = qcom_pcie_get_resources_2_7_0, .init = qcom_pcie_init_2_7_0, + .post_init = qcom_pcie_post_init_2_7_0, .deinit = qcom_pcie_deinit_2_7_0, .ltssm_enable = qcom_pcie_2_3_2_ltssm_enable, }; @@ -1277,6 +1279,7 @@ static const struct qcom_pcie_ops ops_2_7_0 = { static const struct qcom_pcie_ops ops_1_9_0 = { .get_resources = qcom_pcie_get_resources_2_7_0, .init = qcom_pcie_init_2_7_0, + .post_init = qcom_pcie_post_init_2_7_0, .deinit = qcom_pcie_deinit_2_7_0, .ltssm_enable = qcom_pcie_2_3_2_ltssm_enable, .config_sid = qcom_pcie_config_sid_1_9_0, diff --git a/drivers/pci/controller/dwc/pcie-tegra194.c b/drivers/pci/controller/dwc/pcie-tegra194.c index 09825b4a075e5f0740e673421bf404e022478245..e1db909f53ec9b1d834e679676e8dfaab79aed3a 100644 --- a/drivers/pci/controller/dwc/pcie-tegra194.c +++ b/drivers/pci/controller/dwc/pcie-tegra194.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -223,6 +224,7 @@ #define EP_STATE_ENABLED 1 static const unsigned int pcie_gen_freq[] = { + GEN1_CORE_CLK_FREQ, /* PCI_EXP_LNKSTA_CLS == 0; undefined */ GEN1_CORE_CLK_FREQ, GEN2_CORE_CLK_FREQ, GEN3_CORE_CLK_FREQ, @@ -287,6 +289,7 @@ struct tegra_pcie_dw { unsigned int pex_rst_irq; int ep_state; long link_status; + struct icc_path *icc_path; }; static inline struct tegra_pcie_dw *to_tegra_pcie(struct dw_pcie *pci) @@ -309,6 +312,27 @@ struct tegra_pcie_soc { enum dw_pcie_device_mode mode; }; +static void tegra_pcie_icc_set(struct tegra_pcie_dw *pcie) +{ + struct dw_pcie *pci = &pcie->pci; + u32 val, speed, width; + + val = dw_pcie_readw_dbi(pci, pcie->pcie_cap_base + PCI_EXP_LNKSTA); + + speed = FIELD_GET(PCI_EXP_LNKSTA_CLS, val); + width = FIELD_GET(PCI_EXP_LNKSTA_NLW, val); + + val = width * (PCIE_SPEED2MBS_ENC(pcie_link_speed[speed]) / BITS_PER_BYTE); + + if (icc_set_bw(pcie->icc_path, MBps_to_icc(val), 0)) + dev_err(pcie->dev, "can't set bw[%u]\n", val); + + if (speed >= ARRAY_SIZE(pcie_gen_freq)) + speed = 0; + + clk_set_rate(pcie->core_clk, pcie_gen_freq[speed]); +} + static void apply_bad_link_workaround(struct dw_pcie_rp *pp) { struct dw_pcie *pci = to_dw_pcie_from_pp(pp); @@ -452,14 +476,12 @@ static irqreturn_t tegra_pcie_ep_irq_thread(int irq, void *arg) struct tegra_pcie_dw *pcie = arg; struct dw_pcie_ep *ep = &pcie->pci.ep; struct dw_pcie *pci = &pcie->pci; - u32 val, speed; + u32 val; if (test_and_clear_bit(0, &pcie->link_status)) dw_pcie_ep_linkup(ep); - speed = dw_pcie_readw_dbi(pci, pcie->pcie_cap_base + PCI_EXP_LNKSTA) & - PCI_EXP_LNKSTA_CLS; - clk_set_rate(pcie->core_clk, pcie_gen_freq[speed - 1]); + tegra_pcie_icc_set(pcie); if (pcie->of_data->has_ltr_req_fix) return IRQ_HANDLED; @@ -945,9 +967,9 @@ static int tegra_pcie_dw_host_init(struct dw_pcie_rp *pp) static int tegra_pcie_dw_start_link(struct dw_pcie *pci) { - u32 val, offset, speed, tmp; struct tegra_pcie_dw *pcie = to_tegra_pcie(pci); struct dw_pcie_rp *pp = &pci->pp; + u32 val, offset, tmp; bool retry = true; if (pcie->of_data->mode == DW_PCIE_EP_TYPE) { @@ -1018,9 +1040,7 @@ static int tegra_pcie_dw_start_link(struct dw_pcie *pci) goto retry_link; } - speed = dw_pcie_readw_dbi(pci, pcie->pcie_cap_base + PCI_EXP_LNKSTA) & - PCI_EXP_LNKSTA_CLS; - clk_set_rate(pcie->core_clk, pcie_gen_freq[speed - 1]); + tegra_pcie_icc_set(pcie); tegra_pcie_enable_interrupts(pp); @@ -2224,6 +2244,14 @@ static int tegra_pcie_dw_probe(struct platform_device *pdev) platform_set_drvdata(pdev, pcie); + pcie->icc_path = devm_of_icc_get(&pdev->dev, "write"); + ret = PTR_ERR_OR_ZERO(pcie->icc_path); + if (ret) { + tegra_bpmp_put(pcie->bpmp); + dev_err_probe(&pdev->dev, ret, "failed to get write interconnect\n"); + return ret; + } + switch (pcie->of_data->mode) { case DW_PCIE_RC_TYPE: ret = devm_request_irq(dev, pp->irq, tegra_pcie_rp_irq_handler, @@ -2268,13 +2296,13 @@ static int tegra_pcie_dw_probe(struct platform_device *pdev) return ret; } -static int tegra_pcie_dw_remove(struct platform_device *pdev) +static void tegra_pcie_dw_remove(struct platform_device *pdev) { struct tegra_pcie_dw *pcie = platform_get_drvdata(pdev); if (pcie->of_data->mode == DW_PCIE_RC_TYPE) { if (!pcie->link_state) - return 0; + return; debugfs_remove_recursive(pcie->debugfs); tegra_pcie_deinit_controller(pcie); @@ -2288,8 +2316,6 @@ static int tegra_pcie_dw_remove(struct platform_device *pdev) tegra_bpmp_put(pcie->bpmp); if (pcie->pex_refclk_sel_gpiod) gpiod_set_value(pcie->pex_refclk_sel_gpiod, 0); - - return 0; } static int tegra_pcie_dw_suspend_late(struct device *dev) @@ -2483,7 +2509,7 @@ static const struct dev_pm_ops tegra_pcie_dw_pm_ops = { static struct platform_driver tegra_pcie_dw_driver = { .probe = tegra_pcie_dw_probe, - .remove = tegra_pcie_dw_remove, + .remove_new = tegra_pcie_dw_remove, .shutdown = tegra_pcie_dw_shutdown, .driver = { .name = "tegra194-pcie", diff --git a/drivers/pci/controller/pci-aardvark.c b/drivers/pci/controller/pci-aardvark.c index 513d8edf3a5cffb19d6a15697f25dd793d39c0cc..71ecd7ddcc8a24b9c456c4585829cfbe030a0b08 100644 --- a/drivers/pci/controller/pci-aardvark.c +++ b/drivers/pci/controller/pci-aardvark.c @@ -1927,7 +1927,7 @@ static int advk_pcie_probe(struct platform_device *pdev) return 0; } -static int advk_pcie_remove(struct platform_device *pdev) +static void advk_pcie_remove(struct platform_device *pdev) { struct advk_pcie *pcie = platform_get_drvdata(pdev); struct pci_host_bridge *bridge = pci_host_bridge_from_priv(pcie); @@ -1989,8 +1989,6 @@ static int advk_pcie_remove(struct platform_device *pdev) /* Disable phy */ advk_pcie_disable_phy(pcie); - - return 0; } static const struct of_device_id advk_pcie_of_match_table[] = { @@ -2005,7 +2003,7 @@ static struct platform_driver advk_pcie_driver = { .of_match_table = advk_pcie_of_match_table, }, .probe = advk_pcie_probe, - .remove = advk_pcie_remove, + .remove_new = advk_pcie_remove, }; module_platform_driver(advk_pcie_driver); diff --git a/drivers/pci/controller/pci-ftpci100.c b/drivers/pci/controller/pci-ftpci100.c index ecd3009df586d19bd82b031769a9be3d76d27ec0..6e7981d2ed5e1b0e6c695b76da15efe93dc3952c 100644 --- a/drivers/pci/controller/pci-ftpci100.c +++ b/drivers/pci/controller/pci-ftpci100.c @@ -429,22 +429,12 @@ static int faraday_pci_probe(struct platform_device *pdev) p->dev = dev; /* Retrieve and enable optional clocks */ - clk = devm_clk_get(dev, "PCLK"); + clk = devm_clk_get_enabled(dev, "PCLK"); if (IS_ERR(clk)) return PTR_ERR(clk); - ret = clk_prepare_enable(clk); - if (ret) { - dev_err(dev, "could not prepare PCLK\n"); - return ret; - } - p->bus_clk = devm_clk_get(dev, "PCICLK"); + p->bus_clk = devm_clk_get_enabled(dev, "PCICLK"); if (IS_ERR(p->bus_clk)) return PTR_ERR(p->bus_clk); - ret = clk_prepare_enable(p->bus_clk); - if (ret) { - dev_err(dev, "could not prepare PCICLK\n"); - return ret; - } p->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(p->base)) diff --git a/drivers/pci/controller/pci-hyperv.c b/drivers/pci/controller/pci-hyperv.c index bc32662c6bb7fd2de7ffeae661dd53210d6288ac..2d93d0c4f10db8ae9c16223758efe3ec3024017b 100644 --- a/drivers/pci/controller/pci-hyperv.c +++ b/drivers/pci/controller/pci-hyperv.c @@ -489,7 +489,10 @@ struct hv_pcibus_device { struct fwnode_handle *fwnode; /* Protocol version negotiated with the host */ enum pci_protocol_version_t protocol_version; + + struct mutex state_lock; enum hv_pcibus_state state; + struct hv_device *hdev; resource_size_t low_mmio_space; resource_size_t high_mmio_space; @@ -545,19 +548,10 @@ struct hv_dr_state { struct hv_pcidev_description func[]; }; -enum hv_pcichild_state { - hv_pcichild_init = 0, - hv_pcichild_requirements, - hv_pcichild_resourced, - hv_pcichild_ejecting, - hv_pcichild_maximum -}; - struct hv_pci_dev { /* List protected by pci_rescan_remove_lock */ struct list_head list_entry; refcount_t refs; - enum hv_pcichild_state state; struct pci_slot *pci_slot; struct hv_pcidev_description desc; bool reported_missing; @@ -635,6 +629,11 @@ static void hv_arch_irq_unmask(struct irq_data *data) pbus = pdev->bus; hbus = container_of(pbus->sysdata, struct hv_pcibus_device, sysdata); int_desc = data->chip_data; + if (!int_desc) { + dev_warn(&hbus->hdev->device, "%s() can not unmask irq %u\n", + __func__, data->irq); + return; + } local_irq_save(flags); @@ -2004,12 +2003,6 @@ static void hv_compose_msi_msg(struct irq_data *data, struct msi_msg *msg) hv_pci_onchannelcallback(hbus); spin_unlock_irqrestore(&channel->sched_lock, flags); - if (hpdev->state == hv_pcichild_ejecting) { - dev_err_once(&hbus->hdev->device, - "the device is being ejected\n"); - goto enable_tasklet; - } - udelay(100); } @@ -2615,6 +2608,8 @@ static void pci_devices_present_work(struct work_struct *work) if (!dr) return; + mutex_lock(&hbus->state_lock); + /* First, mark all existing children as reported missing. */ spin_lock_irqsave(&hbus->device_list_lock, flags); list_for_each_entry(hpdev, &hbus->children, list_entry) { @@ -2696,6 +2691,8 @@ static void pci_devices_present_work(struct work_struct *work) break; } + mutex_unlock(&hbus->state_lock); + kfree(dr); } @@ -2844,7 +2841,7 @@ static void hv_eject_device_work(struct work_struct *work) hpdev = container_of(work, struct hv_pci_dev, wrk); hbus = hpdev->hbus; - WARN_ON(hpdev->state != hv_pcichild_ejecting); + mutex_lock(&hbus->state_lock); /* * Ejection can come before or after the PCI bus has been set up, so @@ -2882,6 +2879,8 @@ static void hv_eject_device_work(struct work_struct *work) put_pcichild(hpdev); put_pcichild(hpdev); /* hpdev has been freed. Do not use it any more. */ + + mutex_unlock(&hbus->state_lock); } /** @@ -2902,7 +2901,6 @@ static void hv_pci_eject_device(struct hv_pci_dev *hpdev) return; } - hpdev->state = hv_pcichild_ejecting; get_pcichild(hpdev); INIT_WORK(&hpdev->wrk, hv_eject_device_work); queue_work(hbus->wq, &hpdev->wrk); @@ -3331,8 +3329,10 @@ static int hv_pci_enter_d0(struct hv_device *hdev) struct pci_bus_d0_entry *d0_entry; struct hv_pci_compl comp_pkt; struct pci_packet *pkt; + bool retry = true; int ret; +enter_d0_retry: /* * Tell the host that the bus is ready to use, and moved into the * powered-on state. This includes telling the host which region @@ -3359,6 +3359,38 @@ static int hv_pci_enter_d0(struct hv_device *hdev) if (ret) goto exit; + /* + * In certain case (Kdump) the pci device of interest was + * not cleanly shut down and resource is still held on host + * side, the host could return invalid device status. + * We need to explicitly request host to release the resource + * and try to enter D0 again. + */ + if (comp_pkt.completion_status < 0 && retry) { + retry = false; + + dev_err(&hdev->device, "Retrying D0 Entry\n"); + + /* + * Hv_pci_bus_exit() calls hv_send_resource_released() + * to free up resources of its child devices. + * In the kdump kernel we need to set the + * wslot_res_allocated to 255 so it scans all child + * devices to release resources allocated in the + * normal kernel before panic happened. + */ + hbus->wslot_res_allocated = 255; + + ret = hv_pci_bus_exit(hdev, true); + + if (ret == 0) { + kfree(pkt); + goto enter_d0_retry; + } + dev_err(&hdev->device, + "Retrying D0 failed with ret %d\n", ret); + } + if (comp_pkt.completion_status < 0) { dev_err(&hdev->device, "PCI Pass-through VSP failed D0 Entry with status %x\n", @@ -3401,6 +3433,24 @@ static int hv_pci_query_relations(struct hv_device *hdev) if (!ret) ret = wait_for_response(hdev, &comp); + /* + * In the case of fast device addition/removal, it's possible that + * vmbus_sendpacket() or wait_for_response() returns -ENODEV but we + * already got a PCI_BUS_RELATIONS* message from the host and the + * channel callback already scheduled a work to hbus->wq, which can be + * running pci_devices_present_work() -> survey_child_resources() -> + * complete(&hbus->survey_event), even after hv_pci_query_relations() + * exits and the stack variable 'comp' is no longer valid; as a result, + * a hang or a page fault may happen when the complete() calls + * raw_spin_lock_irqsave(). Flush hbus->wq before we exit from + * hv_pci_query_relations() to avoid the issues. Note: if 'ret' is + * -ENODEV, there can't be any more work item scheduled to hbus->wq + * after the flush_workqueue(): see vmbus_onoffer_rescind() -> + * vmbus_reset_channel_cb(), vmbus_rescind_cleanup() -> + * channel->rescind = true. + */ + flush_workqueue(hbus->wq); + return ret; } @@ -3586,7 +3636,6 @@ static int hv_pci_probe(struct hv_device *hdev, struct hv_pcibus_device *hbus; u16 dom_req, dom; char *name; - bool enter_d0_retry = true; int ret; bridge = devm_pci_alloc_host_bridge(&hdev->device, 0); @@ -3598,6 +3647,7 @@ static int hv_pci_probe(struct hv_device *hdev, return -ENOMEM; hbus->bridge = bridge; + mutex_init(&hbus->state_lock); hbus->state = hv_pcibus_init; hbus->wslot_res_allocated = -1; @@ -3703,49 +3753,15 @@ static int hv_pci_probe(struct hv_device *hdev, if (ret) goto free_fwnode; -retry: ret = hv_pci_query_relations(hdev); if (ret) goto free_irq_domain; - ret = hv_pci_enter_d0(hdev); - /* - * In certain case (Kdump) the pci device of interest was - * not cleanly shut down and resource is still held on host - * side, the host could return invalid device status. - * We need to explicitly request host to release the resource - * and try to enter D0 again. - * Since the hv_pci_bus_exit() call releases structures - * of all its child devices, we need to start the retry from - * hv_pci_query_relations() call, requesting host to send - * the synchronous child device relations message before this - * information is needed in hv_send_resources_allocated() - * call later. - */ - if (ret == -EPROTO && enter_d0_retry) { - enter_d0_retry = false; - - dev_err(&hdev->device, "Retrying D0 Entry\n"); - - /* - * Hv_pci_bus_exit() calls hv_send_resources_released() - * to free up resources of its child devices. - * In the kdump kernel we need to set the - * wslot_res_allocated to 255 so it scans all child - * devices to release resources allocated in the - * normal kernel before panic happened. - */ - hbus->wslot_res_allocated = 255; - ret = hv_pci_bus_exit(hdev, true); - - if (ret == 0) - goto retry; + mutex_lock(&hbus->state_lock); - dev_err(&hdev->device, - "Retrying D0 failed with ret %d\n", ret); - } + ret = hv_pci_enter_d0(hdev); if (ret) - goto free_irq_domain; + goto release_state_lock; ret = hv_pci_allocate_bridge_windows(hbus); if (ret) @@ -3763,12 +3779,15 @@ static int hv_pci_probe(struct hv_device *hdev, if (ret) goto free_windows; + mutex_unlock(&hbus->state_lock); return 0; free_windows: hv_pci_free_bridge_windows(hbus); exit_d0: (void) hv_pci_bus_exit(hdev, true); +release_state_lock: + mutex_unlock(&hbus->state_lock); free_irq_domain: irq_domain_remove(hbus->irq_domain); free_fwnode: @@ -4018,20 +4037,26 @@ static int hv_pci_resume(struct hv_device *hdev) if (ret) goto out; + mutex_lock(&hbus->state_lock); + ret = hv_pci_enter_d0(hdev); if (ret) - goto out; + goto release_state_lock; ret = hv_send_resources_allocated(hdev); if (ret) - goto out; + goto release_state_lock; prepopulate_bars(hbus); hv_pci_restore_msi_state(hbus); hbus->state = hv_pcibus_installed; + mutex_unlock(&hbus->state_lock); return 0; + +release_state_lock: + mutex_unlock(&hbus->state_lock); out: vmbus_close(hdev->channel); return ret; diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c index 1dc209f6f53aefa9e013f5290630ff52d21009a7..c931b1b07b1d8b4968bd2aef1ac29894adfee910 100644 --- a/drivers/pci/controller/pci-mvebu.c +++ b/drivers/pci/controller/pci-mvebu.c @@ -1649,7 +1649,7 @@ static int mvebu_pcie_probe(struct platform_device *pdev) return pci_host_probe(bridge); } -static int mvebu_pcie_remove(struct platform_device *pdev) +static void mvebu_pcie_remove(struct platform_device *pdev) { struct mvebu_pcie *pcie = platform_get_drvdata(pdev); struct pci_host_bridge *bridge = pci_host_bridge_from_priv(pcie); @@ -1707,8 +1707,6 @@ static int mvebu_pcie_remove(struct platform_device *pdev) /* Power down card and disable clocks. Must be the last step. */ mvebu_pcie_powerdown(port); } - - return 0; } static const struct of_device_id mvebu_pcie_of_match_table[] = { @@ -1730,7 +1728,7 @@ static struct platform_driver mvebu_pcie_driver = { .pm = &mvebu_pcie_pm_ops, }, .probe = mvebu_pcie_probe, - .remove = mvebu_pcie_remove, + .remove_new = mvebu_pcie_remove, }; module_platform_driver(mvebu_pcie_driver); diff --git a/drivers/pci/controller/pci-tegra.c b/drivers/pci/controller/pci-tegra.c index 79630885b9c823afb09df210b98615d422e0fb06..038d974a318eaf7b859d05cebd77d275dda37e83 100644 --- a/drivers/pci/controller/pci-tegra.c +++ b/drivers/pci/controller/pci-tegra.c @@ -2680,7 +2680,7 @@ static int tegra_pcie_probe(struct platform_device *pdev) return err; } -static int tegra_pcie_remove(struct platform_device *pdev) +static void tegra_pcie_remove(struct platform_device *pdev) { struct tegra_pcie *pcie = platform_get_drvdata(pdev); struct pci_host_bridge *host = pci_host_bridge_from_priv(pcie); @@ -2701,8 +2701,6 @@ static int tegra_pcie_remove(struct platform_device *pdev) list_for_each_entry_safe(port, tmp, &pcie->ports, list) tegra_pcie_port_free(port); - - return 0; } static int tegra_pcie_pm_suspend(struct device *dev) @@ -2808,6 +2806,6 @@ static struct platform_driver tegra_pcie_driver = { .pm = &tegra_pcie_pm_ops, }, .probe = tegra_pcie_probe, - .remove = tegra_pcie_remove, + .remove_new = tegra_pcie_remove, }; module_platform_driver(tegra_pcie_driver); diff --git a/drivers/pci/controller/pci-xgene-msi.c b/drivers/pci/controller/pci-xgene-msi.c index d7987b281f7991581f30c61f6aba363d43535eae..0234e528b9a58aa0b3a85b922ce5961c3089a614 100644 --- a/drivers/pci/controller/pci-xgene-msi.c +++ b/drivers/pci/controller/pci-xgene-msi.c @@ -348,7 +348,7 @@ static void xgene_msi_isr(struct irq_desc *desc) static enum cpuhp_state pci_xgene_online; -static int xgene_msi_remove(struct platform_device *pdev) +static void xgene_msi_remove(struct platform_device *pdev) { struct xgene_msi *msi = platform_get_drvdata(pdev); @@ -362,8 +362,6 @@ static int xgene_msi_remove(struct platform_device *pdev) msi->bitmap = NULL; xgene_free_domains(msi); - - return 0; } static int xgene_msi_hwirq_alloc(unsigned int cpu) @@ -521,7 +519,7 @@ static struct platform_driver xgene_msi_driver = { .of_match_table = xgene_msi_match_table, }, .probe = xgene_msi_probe, - .remove = xgene_msi_remove, + .remove_new = xgene_msi_remove, }; static int __init xgene_pcie_msi_init(void) diff --git a/drivers/pci/controller/pcie-altera-msi.c b/drivers/pci/controller/pcie-altera-msi.c index 65e8a20cc44263451f26564afacb56123b60b967..6ad5427490b524479a36cfabb4c90add52ae9775 100644 --- a/drivers/pci/controller/pcie-altera-msi.c +++ b/drivers/pci/controller/pcie-altera-msi.c @@ -197,7 +197,7 @@ static void altera_free_domains(struct altera_msi *msi) irq_domain_remove(msi->inner_domain); } -static int altera_msi_remove(struct platform_device *pdev) +static void altera_msi_remove(struct platform_device *pdev) { struct altera_msi *msi = platform_get_drvdata(pdev); @@ -207,7 +207,6 @@ static int altera_msi_remove(struct platform_device *pdev) altera_free_domains(msi); platform_set_drvdata(pdev, NULL); - return 0; } static int altera_msi_probe(struct platform_device *pdev) @@ -275,7 +274,7 @@ static struct platform_driver altera_msi_driver = { .of_match_table = altera_msi_of_match, }, .probe = altera_msi_probe, - .remove = altera_msi_remove, + .remove_new = altera_msi_remove, }; static int __init altera_msi_init(void) diff --git a/drivers/pci/controller/pcie-altera.c b/drivers/pci/controller/pcie-altera.c index 18b2361d6462d50adcb7ff44845012f01763922a..c95a29fff8bf611d25749fa2aee85a3a4d658e41 100644 --- a/drivers/pci/controller/pcie-altera.c +++ b/drivers/pci/controller/pcie-altera.c @@ -806,7 +806,7 @@ static int altera_pcie_probe(struct platform_device *pdev) return pci_host_probe(bridge); } -static int altera_pcie_remove(struct platform_device *pdev) +static void altera_pcie_remove(struct platform_device *pdev) { struct altera_pcie *pcie = platform_get_drvdata(pdev); struct pci_host_bridge *bridge = pci_host_bridge_from_priv(pcie); @@ -814,13 +814,11 @@ static int altera_pcie_remove(struct platform_device *pdev) pci_stop_root_bus(bridge->bus); pci_remove_root_bus(bridge->bus); altera_pcie_irq_teardown(pcie); - - return 0; } static struct platform_driver altera_pcie_driver = { .probe = altera_pcie_probe, - .remove = altera_pcie_remove, + .remove_new = altera_pcie_remove, .driver = { .name = "altera-pcie", .of_match_table = altera_pcie_of_match, diff --git a/drivers/pci/controller/pcie-brcmstb.c b/drivers/pci/controller/pcie-brcmstb.c index edf283e2b5dd017cce84488be0bcea3c51cba959..f593a422bd632c8e414100ee694b0a469f68ce35 100644 --- a/drivers/pci/controller/pcie-brcmstb.c +++ b/drivers/pci/controller/pcie-brcmstb.c @@ -1396,7 +1396,7 @@ static void __brcm_pcie_remove(struct brcm_pcie *pcie) clk_disable_unprepare(pcie->clk); } -static int brcm_pcie_remove(struct platform_device *pdev) +static void brcm_pcie_remove(struct platform_device *pdev) { struct brcm_pcie *pcie = platform_get_drvdata(pdev); struct pci_host_bridge *bridge = pci_host_bridge_from_priv(pcie); @@ -1404,8 +1404,6 @@ static int brcm_pcie_remove(struct platform_device *pdev) pci_stop_root_bus(bridge->bus); pci_remove_root_bus(bridge->bus); __brcm_pcie_remove(pcie); - - return 0; } static const int pcie_offsets[] = { @@ -1612,7 +1610,7 @@ static const struct dev_pm_ops brcm_pcie_pm_ops = { static struct platform_driver brcm_pcie_driver = { .probe = brcm_pcie_probe, - .remove = brcm_pcie_remove, + .remove_new = brcm_pcie_remove, .driver = { .name = "brcm-pcie", .of_match_table = brcm_pcie_match, diff --git a/drivers/pci/controller/pcie-hisi-error.c b/drivers/pci/controller/pcie-hisi-error.c index 7d88eb696b062166a1ca0f68cb3843746f97af3d..ad9d5ffcd9e344efc6f26a35d8869ebf7ba78ab8 100644 --- a/drivers/pci/controller/pcie-hisi-error.c +++ b/drivers/pci/controller/pcie-hisi-error.c @@ -299,13 +299,11 @@ static int hisi_pcie_error_handler_probe(struct platform_device *pdev) return 0; } -static int hisi_pcie_error_handler_remove(struct platform_device *pdev) +static void hisi_pcie_error_handler_remove(struct platform_device *pdev) { struct hisi_pcie_error_private *priv = platform_get_drvdata(pdev); ghes_unregister_vendor_record_notifier(&priv->nb); - - return 0; } static const struct acpi_device_id hisi_pcie_acpi_match[] = { @@ -319,7 +317,7 @@ static struct platform_driver hisi_pcie_error_handler_driver = { .acpi_match_table = hisi_pcie_acpi_match, }, .probe = hisi_pcie_error_handler_probe, - .remove = hisi_pcie_error_handler_remove, + .remove_new = hisi_pcie_error_handler_remove, }; module_platform_driver(hisi_pcie_error_handler_driver); diff --git a/drivers/pci/controller/pcie-iproc-platform.c b/drivers/pci/controller/pcie-iproc-platform.c index 4142a73e611d111553d83d8fbff788d2b1e55a5a..acdc583d29802ca3a33e62aec8c7de02b6fbc32c 100644 --- a/drivers/pci/controller/pcie-iproc-platform.c +++ b/drivers/pci/controller/pcie-iproc-platform.c @@ -114,11 +114,11 @@ static int iproc_pltfm_pcie_probe(struct platform_device *pdev) return 0; } -static int iproc_pltfm_pcie_remove(struct platform_device *pdev) +static void iproc_pltfm_pcie_remove(struct platform_device *pdev) { struct iproc_pcie *pcie = platform_get_drvdata(pdev); - return iproc_pcie_remove(pcie); + iproc_pcie_remove(pcie); } static void iproc_pltfm_pcie_shutdown(struct platform_device *pdev) @@ -134,7 +134,7 @@ static struct platform_driver iproc_pltfm_pcie_driver = { .of_match_table = of_match_ptr(iproc_pcie_of_match_table), }, .probe = iproc_pltfm_pcie_probe, - .remove = iproc_pltfm_pcie_remove, + .remove_new = iproc_pltfm_pcie_remove, .shutdown = iproc_pltfm_pcie_shutdown, }; module_platform_driver(iproc_pltfm_pcie_driver); diff --git a/drivers/pci/controller/pcie-iproc.c b/drivers/pci/controller/pcie-iproc.c index 83029bdfd88444966da8215a2d4a2120d254a15f..bd1c98b688516cc9b96a5dc43e4723c4b7de410d 100644 --- a/drivers/pci/controller/pcie-iproc.c +++ b/drivers/pci/controller/pcie-iproc.c @@ -1537,7 +1537,7 @@ int iproc_pcie_setup(struct iproc_pcie *pcie, struct list_head *res) } EXPORT_SYMBOL(iproc_pcie_setup); -int iproc_pcie_remove(struct iproc_pcie *pcie) +void iproc_pcie_remove(struct iproc_pcie *pcie) { struct pci_host_bridge *host = pci_host_bridge_from_priv(pcie); @@ -1548,8 +1548,6 @@ int iproc_pcie_remove(struct iproc_pcie *pcie) phy_power_off(pcie->phy); phy_exit(pcie->phy); - - return 0; } EXPORT_SYMBOL(iproc_pcie_remove); diff --git a/drivers/pci/controller/pcie-iproc.h b/drivers/pci/controller/pcie-iproc.h index dcca315897c8ef83658652095ae3a39da36aab84..969ded03b8c2daf4ebb953b0997ac51c6fa3823c 100644 --- a/drivers/pci/controller/pcie-iproc.h +++ b/drivers/pci/controller/pcie-iproc.h @@ -111,7 +111,7 @@ struct iproc_pcie { }; int iproc_pcie_setup(struct iproc_pcie *pcie, struct list_head *res); -int iproc_pcie_remove(struct iproc_pcie *pcie); +void iproc_pcie_remove(struct iproc_pcie *pcie); int iproc_pcie_shutdown(struct iproc_pcie *pcie); #ifdef CONFIG_PCIE_IPROC_MSI diff --git a/drivers/pci/controller/pcie-mediatek-gen3.c b/drivers/pci/controller/pcie-mediatek-gen3.c index b8612ce5f4d0cf82c23198bf5b802e09d1412145..e0e27645fdf4c8da2ecedaf8f552c1195f1165a2 100644 --- a/drivers/pci/controller/pcie-mediatek-gen3.c +++ b/drivers/pci/controller/pcie-mediatek-gen3.c @@ -943,7 +943,7 @@ static int mtk_pcie_probe(struct platform_device *pdev) return 0; } -static int mtk_pcie_remove(struct platform_device *pdev) +static void mtk_pcie_remove(struct platform_device *pdev) { struct mtk_gen3_pcie *pcie = platform_get_drvdata(pdev); struct pci_host_bridge *host = pci_host_bridge_from_priv(pcie); @@ -955,8 +955,6 @@ static int mtk_pcie_remove(struct platform_device *pdev) mtk_pcie_irq_teardown(pcie); mtk_pcie_power_down(pcie); - - return 0; } static void mtk_pcie_irq_save(struct mtk_gen3_pcie *pcie) @@ -1069,7 +1067,7 @@ MODULE_DEVICE_TABLE(of, mtk_pcie_of_match); static struct platform_driver mtk_pcie_driver = { .probe = mtk_pcie_probe, - .remove = mtk_pcie_remove, + .remove_new = mtk_pcie_remove, .driver = { .name = "mtk-pcie-gen3", .of_match_table = mtk_pcie_of_match, diff --git a/drivers/pci/controller/pcie-mediatek.c b/drivers/pci/controller/pcie-mediatek.c index 31de7a29192c8fda5f78802a55bda5aa73d62312..66a8f73296fc8b7b91ae84d72824550671a45e4d 100644 --- a/drivers/pci/controller/pcie-mediatek.c +++ b/drivers/pci/controller/pcie-mediatek.c @@ -1134,7 +1134,7 @@ static void mtk_pcie_free_resources(struct mtk_pcie *pcie) pci_free_resource_list(windows); } -static int mtk_pcie_remove(struct platform_device *pdev) +static void mtk_pcie_remove(struct platform_device *pdev) { struct mtk_pcie *pcie = platform_get_drvdata(pdev); struct pci_host_bridge *host = pci_host_bridge_from_priv(pcie); @@ -1146,8 +1146,6 @@ static int mtk_pcie_remove(struct platform_device *pdev) mtk_pcie_irq_teardown(pcie); mtk_pcie_put_resources(pcie); - - return 0; } static int mtk_pcie_suspend_noirq(struct device *dev) @@ -1239,7 +1237,7 @@ MODULE_DEVICE_TABLE(of, mtk_pcie_ids); static struct platform_driver mtk_pcie_driver = { .probe = mtk_pcie_probe, - .remove = mtk_pcie_remove, + .remove_new = mtk_pcie_remove, .driver = { .name = "mtk-pcie", .of_match_table = mtk_pcie_ids, diff --git a/drivers/pci/controller/pcie-mt7621.c b/drivers/pci/controller/pcie-mt7621.c index a445ec314375d4a8adcc79e2fd1eab6662c805bd..79e225edb42a014fde25de8ca6f340f528ef1e10 100644 --- a/drivers/pci/controller/pcie-mt7621.c +++ b/drivers/pci/controller/pcie-mt7621.c @@ -524,15 +524,13 @@ static int mt7621_pcie_probe(struct platform_device *pdev) return err; } -static int mt7621_pcie_remove(struct platform_device *pdev) +static void mt7621_pcie_remove(struct platform_device *pdev) { struct mt7621_pcie *pcie = platform_get_drvdata(pdev); struct mt7621_pcie_port *port; list_for_each_entry(port, &pcie->ports, list) reset_control_put(port->pcie_rst); - - return 0; } static const struct of_device_id mt7621_pcie_ids[] = { @@ -543,7 +541,7 @@ MODULE_DEVICE_TABLE(of, mt7621_pcie_ids); static struct platform_driver mt7621_pcie_driver = { .probe = mt7621_pcie_probe, - .remove = mt7621_pcie_remove, + .remove_new = mt7621_pcie_remove, .driver = { .name = "mt7621-pci", .of_match_table = mt7621_pcie_ids, diff --git a/drivers/pci/controller/pcie-rcar-host.c b/drivers/pci/controller/pcie-rcar-host.c index e80e56b2a84243e56f072b2c0ae7ebfa7dba1ed4..88975e40ee2fbf6099a1739d3bb95e6a30325a84 100644 --- a/drivers/pci/controller/pcie-rcar-host.c +++ b/drivers/pci/controller/pcie-rcar-host.c @@ -41,21 +41,6 @@ struct rcar_msi { int irq2; }; -#ifdef CONFIG_ARM -/* - * Here we keep a static copy of the remapped PCIe controller address. - * This is only used on aarch32 systems, all of which have one single - * PCIe controller, to provide quick access to the PCIe controller in - * the L1 link state fixup function, called from the ARM fault handler. - */ -static void __iomem *pcie_base; -/* - * Static copy of PCIe device pointer, so we can check whether the - * device is runtime suspended or not. - */ -static struct device *pcie_dev; -#endif - /* Structure representing the PCIe interface */ struct rcar_pcie_host { struct rcar_pcie pcie; @@ -684,7 +669,7 @@ static void rcar_compose_msi_msg(struct irq_data *data, struct msi_msg *msg) } static struct irq_chip rcar_msi_bottom_chip = { - .name = "Rcar MSI", + .name = "R-Car MSI", .irq_ack = rcar_msi_irq_ack, .irq_mask = rcar_msi_irq_mask, .irq_unmask = rcar_msi_irq_unmask, @@ -813,7 +798,7 @@ static int rcar_pcie_enable_msi(struct rcar_pcie_host *host) /* * Setup MSI data target using RC base address address, which - * is guaranteed to be in the low 32bit range on any RCar HW. + * is guaranteed to be in the low 32bit range on any R-Car HW. */ rcar_pci_write_reg(pcie, lower_32_bits(res.start) | MSIFE, PCIEMSIALR); rcar_pci_write_reg(pcie, upper_32_bits(res.start), PCIEMSIAUR); @@ -879,12 +864,6 @@ static int rcar_pcie_get_resources(struct rcar_pcie_host *host) } host->msi.irq2 = i; -#ifdef CONFIG_ARM - /* Cache static copy for L1 link state fixup hook on aarch32 */ - pcie_base = pcie->base; - pcie_dev = pcie->dev; -#endif - return 0; err_irq2: diff --git a/drivers/pci/controller/pcie-rockchip-ep.c b/drivers/pci/controller/pcie-rockchip-ep.c index d1a200b93b2bf975f29caef425c0b8012fdaa9f1..0af0e965fb57eaafda768bd2e0aed42ed036a362 100644 --- a/drivers/pci/controller/pcie-rockchip-ep.c +++ b/drivers/pci/controller/pcie-rockchip-ep.c @@ -61,70 +61,38 @@ static void rockchip_pcie_clear_ep_ob_atu(struct rockchip_pcie *rockchip, ROCKCHIP_PCIE_AT_OB_REGION_DESC0(region)); rockchip_pcie_write(rockchip, 0, ROCKCHIP_PCIE_AT_OB_REGION_DESC1(region)); - rockchip_pcie_write(rockchip, 0, - ROCKCHIP_PCIE_AT_OB_REGION_CPU_ADDR0(region)); - rockchip_pcie_write(rockchip, 0, - ROCKCHIP_PCIE_AT_OB_REGION_CPU_ADDR1(region)); } static void rockchip_pcie_prog_ep_ob_atu(struct rockchip_pcie *rockchip, u8 fn, - u32 r, u32 type, u64 cpu_addr, - u64 pci_addr, size_t size) + u32 r, u64 cpu_addr, u64 pci_addr, + size_t size) { - u64 sz = 1ULL << fls64(size - 1); - int num_pass_bits = ilog2(sz); - u32 addr0, addr1, desc0, desc1; - bool is_nor_msg = (type == AXI_WRAPPER_NOR_MSG); + int num_pass_bits = fls64(size - 1); + u32 addr0, addr1, desc0; - /* The minimal region size is 1MB */ if (num_pass_bits < 8) num_pass_bits = 8; - cpu_addr -= rockchip->mem_res->start; - addr0 = ((is_nor_msg ? 0x10 : (num_pass_bits - 1)) & - PCIE_CORE_OB_REGION_ADDR0_NUM_BITS) | - (lower_32_bits(cpu_addr) & PCIE_CORE_OB_REGION_ADDR0_LO_ADDR); - addr1 = upper_32_bits(is_nor_msg ? cpu_addr : pci_addr); - desc0 = ROCKCHIP_PCIE_AT_OB_REGION_DESC0_DEVFN(fn) | type; - desc1 = 0; - - if (is_nor_msg) { - rockchip_pcie_write(rockchip, 0, - ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR0(r)); - rockchip_pcie_write(rockchip, 0, - ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR1(r)); - rockchip_pcie_write(rockchip, desc0, - ROCKCHIP_PCIE_AT_OB_REGION_DESC0(r)); - rockchip_pcie_write(rockchip, desc1, - ROCKCHIP_PCIE_AT_OB_REGION_DESC1(r)); - } else { - /* PCI bus address region */ - rockchip_pcie_write(rockchip, addr0, - ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR0(r)); - rockchip_pcie_write(rockchip, addr1, - ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR1(r)); - rockchip_pcie_write(rockchip, desc0, - ROCKCHIP_PCIE_AT_OB_REGION_DESC0(r)); - rockchip_pcie_write(rockchip, desc1, - ROCKCHIP_PCIE_AT_OB_REGION_DESC1(r)); - - addr0 = - ((num_pass_bits - 1) & PCIE_CORE_OB_REGION_ADDR0_NUM_BITS) | - (lower_32_bits(cpu_addr) & - PCIE_CORE_OB_REGION_ADDR0_LO_ADDR); - addr1 = upper_32_bits(cpu_addr); - } + addr0 = ((num_pass_bits - 1) & PCIE_CORE_OB_REGION_ADDR0_NUM_BITS) | + (lower_32_bits(pci_addr) & PCIE_CORE_OB_REGION_ADDR0_LO_ADDR); + addr1 = upper_32_bits(pci_addr); + desc0 = ROCKCHIP_PCIE_AT_OB_REGION_DESC0_DEVFN(fn) | AXI_WRAPPER_MEM_WRITE; - /* CPU bus address region */ + /* PCI bus address region */ rockchip_pcie_write(rockchip, addr0, - ROCKCHIP_PCIE_AT_OB_REGION_CPU_ADDR0(r)); + ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR0(r)); rockchip_pcie_write(rockchip, addr1, - ROCKCHIP_PCIE_AT_OB_REGION_CPU_ADDR1(r)); + ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR1(r)); + rockchip_pcie_write(rockchip, desc0, + ROCKCHIP_PCIE_AT_OB_REGION_DESC0(r)); + rockchip_pcie_write(rockchip, 0, + ROCKCHIP_PCIE_AT_OB_REGION_DESC1(r)); } static int rockchip_pcie_ep_write_header(struct pci_epc *epc, u8 fn, u8 vfn, struct pci_epf_header *hdr) { + u32 reg; struct rockchip_pcie_ep *ep = epc_get_drvdata(epc); struct rockchip_pcie *rockchip = &ep->rockchip; @@ -137,8 +105,9 @@ static int rockchip_pcie_ep_write_header(struct pci_epc *epc, u8 fn, u8 vfn, PCIE_CORE_CONFIG_VENDOR); } - rockchip_pcie_write(rockchip, hdr->deviceid << 16, - ROCKCHIP_PCIE_EP_FUNC_BASE(fn) + PCI_VENDOR_ID); + reg = rockchip_pcie_read(rockchip, PCIE_EP_CONFIG_DID_VID); + reg = (reg & 0xFFFF) | (hdr->deviceid << 16); + rockchip_pcie_write(rockchip, reg, PCIE_EP_CONFIG_DID_VID); rockchip_pcie_write(rockchip, hdr->revid | @@ -256,26 +225,20 @@ static void rockchip_pcie_ep_clear_bar(struct pci_epc *epc, u8 fn, u8 vfn, ROCKCHIP_PCIE_AT_IB_EP_FUNC_BAR_ADDR1(fn, bar)); } +static inline u32 rockchip_ob_region(phys_addr_t addr) +{ + return (addr >> ilog2(SZ_1M)) & 0x1f; +} + static int rockchip_pcie_ep_map_addr(struct pci_epc *epc, u8 fn, u8 vfn, phys_addr_t addr, u64 pci_addr, size_t size) { struct rockchip_pcie_ep *ep = epc_get_drvdata(epc); struct rockchip_pcie *pcie = &ep->rockchip; - u32 r; - - r = find_first_zero_bit(&ep->ob_region_map, BITS_PER_LONG); - /* - * Region 0 is reserved for configuration space and shouldn't - * be used elsewhere per TRM, so leave it out. - */ - if (r >= ep->max_regions - 1) { - dev_err(&epc->dev, "no free outbound region\n"); - return -EINVAL; - } + u32 r = rockchip_ob_region(addr); - rockchip_pcie_prog_ep_ob_atu(pcie, fn, r, AXI_WRAPPER_MEM_WRITE, addr, - pci_addr, size); + rockchip_pcie_prog_ep_ob_atu(pcie, fn, r, addr, pci_addr, size); set_bit(r, &ep->ob_region_map); ep->ob_addr[r] = addr; @@ -290,15 +253,11 @@ static void rockchip_pcie_ep_unmap_addr(struct pci_epc *epc, u8 fn, u8 vfn, struct rockchip_pcie *rockchip = &ep->rockchip; u32 r; - for (r = 0; r < ep->max_regions - 1; r++) + for (r = 0; r < ep->max_regions; r++) if (ep->ob_addr[r] == addr) break; - /* - * Region 0 is reserved for configuration space and shouldn't - * be used elsewhere per TRM, so leave it out. - */ - if (r == ep->max_regions - 1) + if (r == ep->max_regions) return; rockchip_pcie_clear_ep_ob_atu(rockchip, r); @@ -312,15 +271,15 @@ static int rockchip_pcie_ep_set_msi(struct pci_epc *epc, u8 fn, u8 vfn, { struct rockchip_pcie_ep *ep = epc_get_drvdata(epc); struct rockchip_pcie *rockchip = &ep->rockchip; - u16 flags; + u32 flags; flags = rockchip_pcie_read(rockchip, ROCKCHIP_PCIE_EP_FUNC_BASE(fn) + ROCKCHIP_PCIE_EP_MSI_CTRL_REG); flags &= ~ROCKCHIP_PCIE_EP_MSI_CTRL_MMC_MASK; flags |= - ((multi_msg_cap << 1) << ROCKCHIP_PCIE_EP_MSI_CTRL_MMC_OFFSET) | - PCI_MSI_FLAGS_64BIT; + (multi_msg_cap << ROCKCHIP_PCIE_EP_MSI_CTRL_MMC_OFFSET) | + (PCI_MSI_FLAGS_64BIT << ROCKCHIP_PCIE_EP_MSI_FLAGS_OFFSET); flags &= ~ROCKCHIP_PCIE_EP_MSI_CTRL_MASK_MSI_CAP; rockchip_pcie_write(rockchip, flags, ROCKCHIP_PCIE_EP_FUNC_BASE(fn) + @@ -332,7 +291,7 @@ static int rockchip_pcie_ep_get_msi(struct pci_epc *epc, u8 fn, u8 vfn) { struct rockchip_pcie_ep *ep = epc_get_drvdata(epc); struct rockchip_pcie *rockchip = &ep->rockchip; - u16 flags; + u32 flags; flags = rockchip_pcie_read(rockchip, ROCKCHIP_PCIE_EP_FUNC_BASE(fn) + @@ -345,48 +304,25 @@ static int rockchip_pcie_ep_get_msi(struct pci_epc *epc, u8 fn, u8 vfn) } static void rockchip_pcie_ep_assert_intx(struct rockchip_pcie_ep *ep, u8 fn, - u8 intx, bool is_asserted) + u8 intx, bool do_assert) { struct rockchip_pcie *rockchip = &ep->rockchip; - u32 r = ep->max_regions - 1; - u32 offset; - u32 status; - u8 msg_code; - - if (unlikely(ep->irq_pci_addr != ROCKCHIP_PCIE_EP_PCI_LEGACY_IRQ_ADDR || - ep->irq_pci_fn != fn)) { - rockchip_pcie_prog_ep_ob_atu(rockchip, fn, r, - AXI_WRAPPER_NOR_MSG, - ep->irq_phys_addr, 0, 0); - ep->irq_pci_addr = ROCKCHIP_PCIE_EP_PCI_LEGACY_IRQ_ADDR; - ep->irq_pci_fn = fn; - } intx &= 3; - if (is_asserted) { + + if (do_assert) { ep->irq_pending |= BIT(intx); - msg_code = ROCKCHIP_PCIE_MSG_CODE_ASSERT_INTA + intx; + rockchip_pcie_write(rockchip, + PCIE_CLIENT_INT_IN_ASSERT | + PCIE_CLIENT_INT_PEND_ST_PEND, + PCIE_CLIENT_LEGACY_INT_CTRL); } else { ep->irq_pending &= ~BIT(intx); - msg_code = ROCKCHIP_PCIE_MSG_CODE_DEASSERT_INTA + intx; + rockchip_pcie_write(rockchip, + PCIE_CLIENT_INT_IN_DEASSERT | + PCIE_CLIENT_INT_PEND_ST_NORMAL, + PCIE_CLIENT_LEGACY_INT_CTRL); } - - status = rockchip_pcie_read(rockchip, - ROCKCHIP_PCIE_EP_FUNC_BASE(fn) + - ROCKCHIP_PCIE_EP_CMD_STATUS); - status &= ROCKCHIP_PCIE_EP_CMD_STATUS_IS; - - if ((status != 0) ^ (ep->irq_pending != 0)) { - status ^= ROCKCHIP_PCIE_EP_CMD_STATUS_IS; - rockchip_pcie_write(rockchip, status, - ROCKCHIP_PCIE_EP_FUNC_BASE(fn) + - ROCKCHIP_PCIE_EP_CMD_STATUS); - } - - offset = - ROCKCHIP_PCIE_MSG_ROUTING(ROCKCHIP_PCIE_MSG_ROUTING_LOCAL_INTX) | - ROCKCHIP_PCIE_MSG_CODE(msg_code) | ROCKCHIP_PCIE_MSG_NO_DATA; - writel(0, ep->irq_cpu_addr + offset); } static int rockchip_pcie_ep_send_legacy_irq(struct rockchip_pcie_ep *ep, u8 fn, @@ -416,9 +352,10 @@ static int rockchip_pcie_ep_send_msi_irq(struct rockchip_pcie_ep *ep, u8 fn, u8 interrupt_num) { struct rockchip_pcie *rockchip = &ep->rockchip; - u16 flags, mme, data, data_mask; + u32 flags, mme, data, data_mask; u8 msi_count; - u64 pci_addr, pci_addr_mask = 0xff; + u64 pci_addr; + u32 r; /* Check MSI enable bit */ flags = rockchip_pcie_read(&ep->rockchip, @@ -452,21 +389,20 @@ static int rockchip_pcie_ep_send_msi_irq(struct rockchip_pcie_ep *ep, u8 fn, ROCKCHIP_PCIE_EP_FUNC_BASE(fn) + ROCKCHIP_PCIE_EP_MSI_CTRL_REG + PCI_MSI_ADDRESS_LO); - pci_addr &= GENMASK_ULL(63, 2); /* Set the outbound region if needed. */ - if (unlikely(ep->irq_pci_addr != (pci_addr & ~pci_addr_mask) || + if (unlikely(ep->irq_pci_addr != (pci_addr & PCIE_ADDR_MASK) || ep->irq_pci_fn != fn)) { - rockchip_pcie_prog_ep_ob_atu(rockchip, fn, ep->max_regions - 1, - AXI_WRAPPER_MEM_WRITE, + r = rockchip_ob_region(ep->irq_phys_addr); + rockchip_pcie_prog_ep_ob_atu(rockchip, fn, r, ep->irq_phys_addr, - pci_addr & ~pci_addr_mask, - pci_addr_mask + 1); - ep->irq_pci_addr = (pci_addr & ~pci_addr_mask); + pci_addr & PCIE_ADDR_MASK, + ~PCIE_ADDR_MASK + 1); + ep->irq_pci_addr = (pci_addr & PCIE_ADDR_MASK); ep->irq_pci_fn = fn; } - writew(data, ep->irq_cpu_addr + (pci_addr & pci_addr_mask)); + writew(data, ep->irq_cpu_addr + (pci_addr & ~PCIE_ADDR_MASK)); return 0; } @@ -506,6 +442,7 @@ static const struct pci_epc_features rockchip_pcie_epc_features = { .linkup_notifier = false, .msi_capable = true, .msix_capable = false, + .align = 256, }; static const struct pci_epc_features* @@ -547,6 +484,8 @@ static int rockchip_pcie_parse_ep_dt(struct rockchip_pcie *rockchip, if (err < 0 || ep->max_regions > MAX_REGION_LIMIT) ep->max_regions = MAX_REGION_LIMIT; + ep->ob_region_map = 0; + err = of_property_read_u8(dev->of_node, "max-functions", &ep->epc->max_functions); if (err < 0) @@ -567,7 +506,9 @@ static int rockchip_pcie_ep_probe(struct platform_device *pdev) struct rockchip_pcie *rockchip; struct pci_epc *epc; size_t max_regions; - int err; + struct pci_epc_mem_window *windows = NULL; + int err, i; + u32 cfg_msi, cfg_msix_cp; ep = devm_kzalloc(dev, sizeof(*ep), GFP_KERNEL); if (!ep) @@ -614,15 +555,27 @@ static int rockchip_pcie_ep_probe(struct platform_device *pdev) /* Only enable function 0 by default */ rockchip_pcie_write(rockchip, BIT(0), PCIE_CORE_PHY_FUNC_CFG); - err = pci_epc_mem_init(epc, rockchip->mem_res->start, - resource_size(rockchip->mem_res), PAGE_SIZE); + windows = devm_kcalloc(dev, ep->max_regions, + sizeof(struct pci_epc_mem_window), GFP_KERNEL); + if (!windows) { + err = -ENOMEM; + goto err_uninit_port; + } + for (i = 0; i < ep->max_regions; i++) { + windows[i].phys_base = rockchip->mem_res->start + (SZ_1M * i); + windows[i].size = SZ_1M; + windows[i].page_size = SZ_1M; + } + err = pci_epc_multi_mem_init(epc, windows, ep->max_regions); + devm_kfree(dev, windows); + if (err < 0) { dev_err(dev, "failed to initialize the memory space\n"); goto err_uninit_port; } ep->irq_cpu_addr = pci_epc_mem_alloc_addr(epc, &ep->irq_phys_addr, - SZ_128K); + SZ_1M); if (!ep->irq_cpu_addr) { dev_err(dev, "failed to reserve memory space for MSI\n"); err = -ENOMEM; @@ -631,6 +584,32 @@ static int rockchip_pcie_ep_probe(struct platform_device *pdev) ep->irq_pci_addr = ROCKCHIP_PCIE_EP_DUMMY_IRQ_ADDR; + /* + * MSI-X is not supported but the controller still advertises the MSI-X + * capability by default, which can lead to the Root Complex side + * allocating MSI-X vectors which cannot be used. Avoid this by skipping + * the MSI-X capability entry in the PCIe capabilities linked-list: get + * the next pointer from the MSI-X entry and set that in the MSI + * capability entry (which is the previous entry). This way the MSI-X + * entry is skipped (left out of the linked-list) and not advertised. + */ + cfg_msi = rockchip_pcie_read(rockchip, PCIE_EP_CONFIG_BASE + + ROCKCHIP_PCIE_EP_MSI_CTRL_REG); + + cfg_msi &= ~ROCKCHIP_PCIE_EP_MSI_CP1_MASK; + + cfg_msix_cp = rockchip_pcie_read(rockchip, PCIE_EP_CONFIG_BASE + + ROCKCHIP_PCIE_EP_MSIX_CAP_REG) & + ROCKCHIP_PCIE_EP_MSIX_CAP_CP_MASK; + + cfg_msi |= cfg_msix_cp; + + rockchip_pcie_write(rockchip, cfg_msi, + PCIE_EP_CONFIG_BASE + ROCKCHIP_PCIE_EP_MSI_CTRL_REG); + + rockchip_pcie_write(rockchip, PCIE_CLIENT_CONF_ENABLE, + PCIE_CLIENT_CONFIG); + return 0; err_epc_mem_exit: pci_epc_mem_exit(epc); diff --git a/drivers/pci/controller/pcie-rockchip-host.c b/drivers/pci/controller/pcie-rockchip-host.c index c96c0f454570ce06d8dcde3f5b6426382fc86524..2438bc9b3a1aabfd729e2f51b89ca5248807cc10 100644 --- a/drivers/pci/controller/pcie-rockchip-host.c +++ b/drivers/pci/controller/pcie-rockchip-host.c @@ -1009,7 +1009,7 @@ static int rockchip_pcie_probe(struct platform_device *pdev) return err; } -static int rockchip_pcie_remove(struct platform_device *pdev) +static void rockchip_pcie_remove(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct rockchip_pcie *rockchip = dev_get_drvdata(dev); @@ -1029,8 +1029,6 @@ static int rockchip_pcie_remove(struct platform_device *pdev) regulator_disable(rockchip->vpcie3v3); regulator_disable(rockchip->vpcie1v8); regulator_disable(rockchip->vpcie0v9); - - return 0; } static const struct dev_pm_ops rockchip_pcie_pm_ops = { @@ -1051,7 +1049,7 @@ static struct platform_driver rockchip_pcie_driver = { .pm = &rockchip_pcie_pm_ops, }, .probe = rockchip_pcie_probe, - .remove = rockchip_pcie_remove, + .remove_new = rockchip_pcie_remove, }; module_platform_driver(rockchip_pcie_driver); diff --git a/drivers/pci/controller/pcie-rockchip.c b/drivers/pci/controller/pcie-rockchip.c index 990a00e08bc5b6d13f798a93782bd26a6194e75a..1aa84035a8bc7746231bf7d9945e4e91dabc8a79 100644 --- a/drivers/pci/controller/pcie-rockchip.c +++ b/drivers/pci/controller/pcie-rockchip.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -153,6 +154,12 @@ int rockchip_pcie_parse_dt(struct rockchip_pcie *rockchip) } EXPORT_SYMBOL_GPL(rockchip_pcie_parse_dt); +#define rockchip_pcie_read_addr(addr) rockchip_pcie_read(rockchip, addr) +/* 100 ms max wait time for PHY PLLs to lock */ +#define RK_PHY_PLL_LOCK_TIMEOUT_US 100000 +/* Sleep should be less than 20ms */ +#define RK_PHY_PLL_LOCK_SLEEP_US 1000 + int rockchip_pcie_init_port(struct rockchip_pcie *rockchip) { struct device *dev = rockchip->dev; @@ -254,6 +261,16 @@ int rockchip_pcie_init_port(struct rockchip_pcie *rockchip) } } + err = readx_poll_timeout(rockchip_pcie_read_addr, + PCIE_CLIENT_SIDE_BAND_STATUS, + regs, !(regs & PCIE_CLIENT_PHY_ST), + RK_PHY_PLL_LOCK_SLEEP_US, + RK_PHY_PLL_LOCK_TIMEOUT_US); + if (err) { + dev_err(dev, "PHY PLLs could not lock, %d\n", err); + goto err_power_off_phy; + } + /* * Please don't reorder the deassert sequence of the following * four reset pins. diff --git a/drivers/pci/controller/pcie-rockchip.h b/drivers/pci/controller/pcie-rockchip.h index 32c3a859c26b2113911442bd7f4f57da7952cf0b..fe0333778fd93c0a40b0d78f330c7849affb9109 100644 --- a/drivers/pci/controller/pcie-rockchip.h +++ b/drivers/pci/controller/pcie-rockchip.h @@ -38,6 +38,13 @@ #define PCIE_CLIENT_MODE_EP HIWORD_UPDATE(0x0040, 0) #define PCIE_CLIENT_GEN_SEL_1 HIWORD_UPDATE(0x0080, 0) #define PCIE_CLIENT_GEN_SEL_2 HIWORD_UPDATE_BIT(0x0080) +#define PCIE_CLIENT_LEGACY_INT_CTRL (PCIE_CLIENT_BASE + 0x0c) +#define PCIE_CLIENT_INT_IN_ASSERT HIWORD_UPDATE_BIT(0x0002) +#define PCIE_CLIENT_INT_IN_DEASSERT HIWORD_UPDATE(0x0002, 0) +#define PCIE_CLIENT_INT_PEND_ST_PEND HIWORD_UPDATE_BIT(0x0001) +#define PCIE_CLIENT_INT_PEND_ST_NORMAL HIWORD_UPDATE(0x0001, 0) +#define PCIE_CLIENT_SIDE_BAND_STATUS (PCIE_CLIENT_BASE + 0x20) +#define PCIE_CLIENT_PHY_ST BIT(12) #define PCIE_CLIENT_DEBUG_OUT_0 (PCIE_CLIENT_BASE + 0x3c) #define PCIE_CLIENT_DEBUG_LTSSM_MASK GENMASK(5, 0) #define PCIE_CLIENT_DEBUG_LTSSM_L1 0x18 @@ -132,7 +139,10 @@ #define PCIE_RC_RP_ATS_BASE 0x400000 #define PCIE_RC_CONFIG_NORMAL_BASE 0x800000 +#define PCIE_EP_PF_CONFIG_REGS_BASE 0x800000 #define PCIE_RC_CONFIG_BASE 0xa00000 +#define PCIE_EP_CONFIG_BASE 0xa00000 +#define PCIE_EP_CONFIG_DID_VID (PCIE_EP_CONFIG_BASE + 0x00) #define PCIE_RC_CONFIG_RID_CCR (PCIE_RC_CONFIG_BASE + 0x08) #define PCIE_RC_CONFIG_DCR (PCIE_RC_CONFIG_BASE + 0xc4) #define PCIE_RC_CONFIG_DCR_CSPL_SHIFT 18 @@ -148,10 +158,11 @@ #define PCIE_RC_CONFIG_THP_CAP (PCIE_RC_CONFIG_BASE + 0x274) #define PCIE_RC_CONFIG_THP_CAP_NEXT_MASK GENMASK(31, 20) +#define PCIE_ADDR_MASK 0xffffff00 #define PCIE_CORE_AXI_CONF_BASE 0xc00000 #define PCIE_CORE_OB_REGION_ADDR0 (PCIE_CORE_AXI_CONF_BASE + 0x0) #define PCIE_CORE_OB_REGION_ADDR0_NUM_BITS 0x3f -#define PCIE_CORE_OB_REGION_ADDR0_LO_ADDR 0xffffff00 +#define PCIE_CORE_OB_REGION_ADDR0_LO_ADDR PCIE_ADDR_MASK #define PCIE_CORE_OB_REGION_ADDR1 (PCIE_CORE_AXI_CONF_BASE + 0x4) #define PCIE_CORE_OB_REGION_DESC0 (PCIE_CORE_AXI_CONF_BASE + 0x8) #define PCIE_CORE_OB_REGION_DESC1 (PCIE_CORE_AXI_CONF_BASE + 0xc) @@ -159,7 +170,7 @@ #define PCIE_CORE_AXI_INBOUND_BASE 0xc00800 #define PCIE_RP_IB_ADDR0 (PCIE_CORE_AXI_INBOUND_BASE + 0x0) #define PCIE_CORE_IB_REGION_ADDR0_NUM_BITS 0x3f -#define PCIE_CORE_IB_REGION_ADDR0_LO_ADDR 0xffffff00 +#define PCIE_CORE_IB_REGION_ADDR0_LO_ADDR PCIE_ADDR_MASK #define PCIE_RP_IB_ADDR1 (PCIE_CORE_AXI_INBOUND_BASE + 0x4) /* Size of one AXI Region (not Region 0) */ @@ -216,21 +227,28 @@ #define ROCKCHIP_PCIE_EP_CMD_STATUS 0x4 #define ROCKCHIP_PCIE_EP_CMD_STATUS_IS BIT(19) #define ROCKCHIP_PCIE_EP_MSI_CTRL_REG 0x90 +#define ROCKCHIP_PCIE_EP_MSI_CP1_OFFSET 8 +#define ROCKCHIP_PCIE_EP_MSI_CP1_MASK GENMASK(15, 8) +#define ROCKCHIP_PCIE_EP_MSI_FLAGS_OFFSET 16 #define ROCKCHIP_PCIE_EP_MSI_CTRL_MMC_OFFSET 17 #define ROCKCHIP_PCIE_EP_MSI_CTRL_MMC_MASK GENMASK(19, 17) #define ROCKCHIP_PCIE_EP_MSI_CTRL_MME_OFFSET 20 #define ROCKCHIP_PCIE_EP_MSI_CTRL_MME_MASK GENMASK(22, 20) #define ROCKCHIP_PCIE_EP_MSI_CTRL_ME BIT(16) #define ROCKCHIP_PCIE_EP_MSI_CTRL_MASK_MSI_CAP BIT(24) +#define ROCKCHIP_PCIE_EP_MSIX_CAP_REG 0xb0 +#define ROCKCHIP_PCIE_EP_MSIX_CAP_CP_OFFSET 8 +#define ROCKCHIP_PCIE_EP_MSIX_CAP_CP_MASK GENMASK(15, 8) #define ROCKCHIP_PCIE_EP_DUMMY_IRQ_ADDR 0x1 #define ROCKCHIP_PCIE_EP_PCI_LEGACY_IRQ_ADDR 0x3 -#define ROCKCHIP_PCIE_EP_FUNC_BASE(fn) (((fn) << 12) & GENMASK(19, 12)) +#define ROCKCHIP_PCIE_EP_FUNC_BASE(fn) \ + (PCIE_EP_PF_CONFIG_REGS_BASE + (((fn) << 12) & GENMASK(19, 12))) +#define ROCKCHIP_PCIE_EP_VIRT_FUNC_BASE(fn) \ + (PCIE_EP_PF_CONFIG_REGS_BASE + 0x10000 + (((fn) << 12) & GENMASK(19, 12))) #define ROCKCHIP_PCIE_AT_IB_EP_FUNC_BAR_ADDR0(fn, bar) \ - (PCIE_RC_RP_ATS_BASE + 0x0840 + (fn) * 0x0040 + (bar) * 0x0008) + (PCIE_CORE_AXI_CONF_BASE + 0x0828 + (fn) * 0x0040 + (bar) * 0x0008) #define ROCKCHIP_PCIE_AT_IB_EP_FUNC_BAR_ADDR1(fn, bar) \ - (PCIE_RC_RP_ATS_BASE + 0x0844 + (fn) * 0x0040 + (bar) * 0x0008) -#define ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR0(r) \ - (PCIE_RC_RP_ATS_BASE + 0x0000 + ((r) & 0x1f) * 0x0020) + (PCIE_CORE_AXI_CONF_BASE + 0x082c + (fn) * 0x0040 + (bar) * 0x0008) #define ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR0_DEVFN_MASK GENMASK(19, 12) #define ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR0_DEVFN(devfn) \ (((devfn) << 12) & \ @@ -238,20 +256,21 @@ #define ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR0_BUS_MASK GENMASK(27, 20) #define ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR0_BUS(bus) \ (((bus) << 20) & ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR0_BUS_MASK) +#define PCIE_RC_EP_ATR_OB_REGIONS_1_32 (PCIE_CORE_AXI_CONF_BASE + 0x0020) +#define ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR0(r) \ + (PCIE_RC_EP_ATR_OB_REGIONS_1_32 + 0x0000 + ((r) & 0x1f) * 0x0020) #define ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR1(r) \ - (PCIE_RC_RP_ATS_BASE + 0x0004 + ((r) & 0x1f) * 0x0020) + (PCIE_RC_EP_ATR_OB_REGIONS_1_32 + 0x0004 + ((r) & 0x1f) * 0x0020) #define ROCKCHIP_PCIE_AT_OB_REGION_DESC0_HARDCODED_RID BIT(23) #define ROCKCHIP_PCIE_AT_OB_REGION_DESC0_DEVFN_MASK GENMASK(31, 24) #define ROCKCHIP_PCIE_AT_OB_REGION_DESC0_DEVFN(devfn) \ (((devfn) << 24) & ROCKCHIP_PCIE_AT_OB_REGION_DESC0_DEVFN_MASK) #define ROCKCHIP_PCIE_AT_OB_REGION_DESC0(r) \ - (PCIE_RC_RP_ATS_BASE + 0x0008 + ((r) & 0x1f) * 0x0020) -#define ROCKCHIP_PCIE_AT_OB_REGION_DESC1(r) \ - (PCIE_RC_RP_ATS_BASE + 0x000c + ((r) & 0x1f) * 0x0020) -#define ROCKCHIP_PCIE_AT_OB_REGION_CPU_ADDR0(r) \ - (PCIE_RC_RP_ATS_BASE + 0x0018 + ((r) & 0x1f) * 0x0020) -#define ROCKCHIP_PCIE_AT_OB_REGION_CPU_ADDR1(r) \ - (PCIE_RC_RP_ATS_BASE + 0x001c + ((r) & 0x1f) * 0x0020) + (PCIE_RC_EP_ATR_OB_REGIONS_1_32 + 0x0008 + ((r) & 0x1f) * 0x0020) +#define ROCKCHIP_PCIE_AT_OB_REGION_DESC1(r) \ + (PCIE_RC_EP_ATR_OB_REGIONS_1_32 + 0x000c + ((r) & 0x1f) * 0x0020) +#define ROCKCHIP_PCIE_AT_OB_REGION_DESC2(r) \ + (PCIE_RC_EP_ATR_OB_REGIONS_1_32 + 0x0010 + ((r) & 0x1f) * 0x0020) #define ROCKCHIP_PCIE_CORE_EP_FUNC_BAR_CFG0(fn) \ (PCIE_CORE_CTRL_MGMT_BASE + 0x0240 + (fn) * 0x0008) diff --git a/drivers/pci/controller/vmd.c b/drivers/pci/controller/vmd.c index 990630ec57c6a5f3825b3998e73cb3edde302626..e718a816d4814479afddded5b98eb8deaae0869c 100644 --- a/drivers/pci/controller/vmd.c +++ b/drivers/pci/controller/vmd.c @@ -927,7 +927,8 @@ static int vmd_enable_domain(struct vmd_dev *vmd, unsigned long features) if (!list_empty(&child->devices)) { dev = list_first_entry(&child->devices, struct pci_dev, bus_list); - if (pci_reset_bus(dev)) + ret = pci_reset_bus(dev); + if (ret) pci_warn(dev, "can't reset device: %d\n", ret); break; @@ -1036,6 +1037,13 @@ static void vmd_remove(struct pci_dev *dev) ida_simple_remove(&vmd_instance_ida, vmd->instance); } +static void vmd_shutdown(struct pci_dev *dev) +{ + struct vmd_dev *vmd = pci_get_drvdata(dev); + + vmd_remove_irq_domain(vmd); +} + #ifdef CONFIG_PM_SLEEP static int vmd_suspend(struct device *dev) { @@ -1101,6 +1109,7 @@ static struct pci_driver vmd_drv = { .id_table = vmd_ids, .probe = vmd_probe, .remove = vmd_remove, + .shutdown = vmd_shutdown, .driver = { .pm = &vmd_dev_pm_ops, }, diff --git a/drivers/pci/endpoint/functions/Kconfig b/drivers/pci/endpoint/functions/Kconfig index 9fd5608868718df40011f408c9c4d8d9940ab796..0c9cea0698d7bd3d8bd11aa1db0195978d9406b9 100644 --- a/drivers/pci/endpoint/functions/Kconfig +++ b/drivers/pci/endpoint/functions/Kconfig @@ -27,7 +27,7 @@ config PCI_EPF_NTB If in doubt, say "N" to disable Endpoint NTB driver. config PCI_EPF_VNTB - tristate "PCI Endpoint NTB driver" + tristate "PCI Endpoint Virtual NTB driver" depends on PCI_ENDPOINT depends on NTB select CONFIGFS_FS @@ -37,3 +37,13 @@ config PCI_EPF_VNTB between PCI Root Port and PCIe Endpoint. If in doubt, say "N" to disable Endpoint NTB driver. + +config PCI_EPF_MHI + tristate "PCI Endpoint driver for MHI bus" + depends on PCI_ENDPOINT && MHI_BUS_EP + help + Enable this configuration option to enable the PCI Endpoint + driver for Modem Host Interface (MHI) bus in Qualcomm Endpoint + devices such as SDX55. + + If in doubt, say "N" to disable Endpoint driver for MHI bus. diff --git a/drivers/pci/endpoint/functions/Makefile b/drivers/pci/endpoint/functions/Makefile index 5c13001deaba126ca5cf2cf42d2fd339c2d057d1..696473fce50ebe6a738b8a2d51dcad434829357b 100644 --- a/drivers/pci/endpoint/functions/Makefile +++ b/drivers/pci/endpoint/functions/Makefile @@ -6,3 +6,4 @@ obj-$(CONFIG_PCI_EPF_TEST) += pci-epf-test.o obj-$(CONFIG_PCI_EPF_NTB) += pci-epf-ntb.o obj-$(CONFIG_PCI_EPF_VNTB) += pci-epf-vntb.o +obj-$(CONFIG_PCI_EPF_MHI) += pci-epf-mhi.o diff --git a/drivers/pci/endpoint/functions/pci-epf-mhi.c b/drivers/pci/endpoint/functions/pci-epf-mhi.c new file mode 100644 index 0000000000000000000000000000000000000000..9c1f5a154fbd193f039c94c259448787ed98e5da --- /dev/null +++ b/drivers/pci/endpoint/functions/pci-epf-mhi.c @@ -0,0 +1,458 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * PCI EPF driver for MHI Endpoint devices + * + * Copyright (C) 2023 Linaro Ltd. + * Author: Manivannan Sadhasivam + */ + +#include +#include +#include +#include +#include + +#define MHI_VERSION_1_0 0x01000000 + +#define to_epf_mhi(cntrl) container_of(cntrl, struct pci_epf_mhi, cntrl) + +struct pci_epf_mhi_ep_info { + const struct mhi_ep_cntrl_config *config; + struct pci_epf_header *epf_header; + enum pci_barno bar_num; + u32 epf_flags; + u32 msi_count; + u32 mru; +}; + +#define MHI_EP_CHANNEL_CONFIG(ch_num, ch_name, direction) \ + { \ + .num = ch_num, \ + .name = ch_name, \ + .dir = direction, \ + } + +#define MHI_EP_CHANNEL_CONFIG_UL(ch_num, ch_name) \ + MHI_EP_CHANNEL_CONFIG(ch_num, ch_name, DMA_TO_DEVICE) + +#define MHI_EP_CHANNEL_CONFIG_DL(ch_num, ch_name) \ + MHI_EP_CHANNEL_CONFIG(ch_num, ch_name, DMA_FROM_DEVICE) + +static const struct mhi_ep_channel_config mhi_v1_channels[] = { + MHI_EP_CHANNEL_CONFIG_UL(0, "LOOPBACK"), + MHI_EP_CHANNEL_CONFIG_DL(1, "LOOPBACK"), + MHI_EP_CHANNEL_CONFIG_UL(2, "SAHARA"), + MHI_EP_CHANNEL_CONFIG_DL(3, "SAHARA"), + MHI_EP_CHANNEL_CONFIG_UL(4, "DIAG"), + MHI_EP_CHANNEL_CONFIG_DL(5, "DIAG"), + MHI_EP_CHANNEL_CONFIG_UL(6, "SSR"), + MHI_EP_CHANNEL_CONFIG_DL(7, "SSR"), + MHI_EP_CHANNEL_CONFIG_UL(8, "QDSS"), + MHI_EP_CHANNEL_CONFIG_DL(9, "QDSS"), + MHI_EP_CHANNEL_CONFIG_UL(10, "EFS"), + MHI_EP_CHANNEL_CONFIG_DL(11, "EFS"), + MHI_EP_CHANNEL_CONFIG_UL(12, "MBIM"), + MHI_EP_CHANNEL_CONFIG_DL(13, "MBIM"), + MHI_EP_CHANNEL_CONFIG_UL(14, "QMI"), + MHI_EP_CHANNEL_CONFIG_DL(15, "QMI"), + MHI_EP_CHANNEL_CONFIG_UL(16, "QMI"), + MHI_EP_CHANNEL_CONFIG_DL(17, "QMI"), + MHI_EP_CHANNEL_CONFIG_UL(18, "IP-CTRL-1"), + MHI_EP_CHANNEL_CONFIG_DL(19, "IP-CTRL-1"), + MHI_EP_CHANNEL_CONFIG_UL(20, "IPCR"), + MHI_EP_CHANNEL_CONFIG_DL(21, "IPCR"), + MHI_EP_CHANNEL_CONFIG_UL(32, "DUN"), + MHI_EP_CHANNEL_CONFIG_DL(33, "DUN"), + MHI_EP_CHANNEL_CONFIG_UL(46, "IP_SW0"), + MHI_EP_CHANNEL_CONFIG_DL(47, "IP_SW0"), +}; + +static const struct mhi_ep_cntrl_config mhi_v1_config = { + .max_channels = 128, + .num_channels = ARRAY_SIZE(mhi_v1_channels), + .ch_cfg = mhi_v1_channels, + .mhi_version = MHI_VERSION_1_0, +}; + +static struct pci_epf_header sdx55_header = { + .vendorid = PCI_VENDOR_ID_QCOM, + .deviceid = 0x0306, + .baseclass_code = PCI_BASE_CLASS_COMMUNICATION, + .subclass_code = PCI_CLASS_COMMUNICATION_MODEM & 0xff, + .interrupt_pin = PCI_INTERRUPT_INTA, +}; + +static const struct pci_epf_mhi_ep_info sdx55_info = { + .config = &mhi_v1_config, + .epf_header = &sdx55_header, + .bar_num = BAR_0, + .epf_flags = PCI_BASE_ADDRESS_MEM_TYPE_32, + .msi_count = 32, + .mru = 0x8000, +}; + +struct pci_epf_mhi { + const struct pci_epf_mhi_ep_info *info; + struct mhi_ep_cntrl mhi_cntrl; + struct pci_epf *epf; + struct mutex lock; + void __iomem *mmio; + resource_size_t mmio_phys; + u32 mmio_size; + int irq; +}; + +static int __pci_epf_mhi_alloc_map(struct mhi_ep_cntrl *mhi_cntrl, u64 pci_addr, + phys_addr_t *paddr, void __iomem **vaddr, + size_t offset, size_t size) +{ + struct pci_epf_mhi *epf_mhi = to_epf_mhi(mhi_cntrl); + struct pci_epf *epf = epf_mhi->epf; + struct pci_epc *epc = epf->epc; + int ret; + + *vaddr = pci_epc_mem_alloc_addr(epc, paddr, size + offset); + if (!*vaddr) + return -ENOMEM; + + ret = pci_epc_map_addr(epc, epf->func_no, epf->vfunc_no, *paddr, + pci_addr - offset, size + offset); + if (ret) { + pci_epc_mem_free_addr(epc, *paddr, *vaddr, size + offset); + return ret; + } + + *paddr = *paddr + offset; + *vaddr = *vaddr + offset; + + return 0; +} + +static int pci_epf_mhi_alloc_map(struct mhi_ep_cntrl *mhi_cntrl, u64 pci_addr, + phys_addr_t *paddr, void __iomem **vaddr, + size_t size) +{ + struct pci_epf_mhi *epf_mhi = to_epf_mhi(mhi_cntrl); + struct pci_epc *epc = epf_mhi->epf->epc; + size_t offset = pci_addr & (epc->mem->window.page_size - 1); + + return __pci_epf_mhi_alloc_map(mhi_cntrl, pci_addr, paddr, vaddr, + offset, size); +} + +static void __pci_epf_mhi_unmap_free(struct mhi_ep_cntrl *mhi_cntrl, + u64 pci_addr, phys_addr_t paddr, + void __iomem *vaddr, size_t offset, + size_t size) +{ + struct pci_epf_mhi *epf_mhi = to_epf_mhi(mhi_cntrl); + struct pci_epf *epf = epf_mhi->epf; + struct pci_epc *epc = epf->epc; + + pci_epc_unmap_addr(epc, epf->func_no, epf->vfunc_no, paddr - offset); + pci_epc_mem_free_addr(epc, paddr - offset, vaddr - offset, + size + offset); +} + +static void pci_epf_mhi_unmap_free(struct mhi_ep_cntrl *mhi_cntrl, u64 pci_addr, + phys_addr_t paddr, void __iomem *vaddr, + size_t size) +{ + struct pci_epf_mhi *epf_mhi = to_epf_mhi(mhi_cntrl); + struct pci_epf *epf = epf_mhi->epf; + struct pci_epc *epc = epf->epc; + size_t offset = pci_addr & (epc->mem->window.page_size - 1); + + __pci_epf_mhi_unmap_free(mhi_cntrl, pci_addr, paddr, vaddr, offset, + size); +} + +static void pci_epf_mhi_raise_irq(struct mhi_ep_cntrl *mhi_cntrl, u32 vector) +{ + struct pci_epf_mhi *epf_mhi = to_epf_mhi(mhi_cntrl); + struct pci_epf *epf = epf_mhi->epf; + struct pci_epc *epc = epf->epc; + + /* + * MHI supplies 0 based MSI vectors but the API expects the vector + * number to start from 1, so we need to increment the vector by 1. + */ + pci_epc_raise_irq(epc, epf->func_no, epf->vfunc_no, PCI_EPC_IRQ_MSI, + vector + 1); +} + +static int pci_epf_mhi_read_from_host(struct mhi_ep_cntrl *mhi_cntrl, u64 from, + void *to, size_t size) +{ + struct pci_epf_mhi *epf_mhi = to_epf_mhi(mhi_cntrl); + size_t offset = from % SZ_4K; + void __iomem *tre_buf; + phys_addr_t tre_phys; + int ret; + + mutex_lock(&epf_mhi->lock); + + ret = __pci_epf_mhi_alloc_map(mhi_cntrl, from, &tre_phys, &tre_buf, + offset, size); + if (ret) { + mutex_unlock(&epf_mhi->lock); + return ret; + } + + memcpy_fromio(to, tre_buf, size); + + __pci_epf_mhi_unmap_free(mhi_cntrl, from, tre_phys, tre_buf, offset, + size); + + mutex_unlock(&epf_mhi->lock); + + return 0; +} + +static int pci_epf_mhi_write_to_host(struct mhi_ep_cntrl *mhi_cntrl, + void *from, u64 to, size_t size) +{ + struct pci_epf_mhi *epf_mhi = to_epf_mhi(mhi_cntrl); + size_t offset = to % SZ_4K; + void __iomem *tre_buf; + phys_addr_t tre_phys; + int ret; + + mutex_lock(&epf_mhi->lock); + + ret = __pci_epf_mhi_alloc_map(mhi_cntrl, to, &tre_phys, &tre_buf, + offset, size); + if (ret) { + mutex_unlock(&epf_mhi->lock); + return ret; + } + + memcpy_toio(tre_buf, from, size); + + __pci_epf_mhi_unmap_free(mhi_cntrl, to, tre_phys, tre_buf, offset, + size); + + mutex_unlock(&epf_mhi->lock); + + return 0; +} + +static int pci_epf_mhi_core_init(struct pci_epf *epf) +{ + struct pci_epf_mhi *epf_mhi = epf_get_drvdata(epf); + const struct pci_epf_mhi_ep_info *info = epf_mhi->info; + struct pci_epf_bar *epf_bar = &epf->bar[info->bar_num]; + struct pci_epc *epc = epf->epc; + struct device *dev = &epf->dev; + int ret; + + epf_bar->phys_addr = epf_mhi->mmio_phys; + epf_bar->size = epf_mhi->mmio_size; + epf_bar->barno = info->bar_num; + epf_bar->flags = info->epf_flags; + ret = pci_epc_set_bar(epc, epf->func_no, epf->vfunc_no, epf_bar); + if (ret) { + dev_err(dev, "Failed to set BAR: %d\n", ret); + return ret; + } + + ret = pci_epc_set_msi(epc, epf->func_no, epf->vfunc_no, + order_base_2(info->msi_count)); + if (ret) { + dev_err(dev, "Failed to set MSI configuration: %d\n", ret); + return ret; + } + + ret = pci_epc_write_header(epc, epf->func_no, epf->vfunc_no, + epf->header); + if (ret) { + dev_err(dev, "Failed to set Configuration header: %d\n", ret); + return ret; + } + + return 0; +} + +static int pci_epf_mhi_link_up(struct pci_epf *epf) +{ + struct pci_epf_mhi *epf_mhi = epf_get_drvdata(epf); + const struct pci_epf_mhi_ep_info *info = epf_mhi->info; + struct mhi_ep_cntrl *mhi_cntrl = &epf_mhi->mhi_cntrl; + struct pci_epc *epc = epf->epc; + struct device *dev = &epf->dev; + int ret; + + mhi_cntrl->mmio = epf_mhi->mmio; + mhi_cntrl->irq = epf_mhi->irq; + mhi_cntrl->mru = info->mru; + + /* Assign the struct dev of PCI EP as MHI controller device */ + mhi_cntrl->cntrl_dev = epc->dev.parent; + mhi_cntrl->raise_irq = pci_epf_mhi_raise_irq; + mhi_cntrl->alloc_map = pci_epf_mhi_alloc_map; + mhi_cntrl->unmap_free = pci_epf_mhi_unmap_free; + mhi_cntrl->read_from_host = pci_epf_mhi_read_from_host; + mhi_cntrl->write_to_host = pci_epf_mhi_write_to_host; + + /* Register the MHI EP controller */ + ret = mhi_ep_register_controller(mhi_cntrl, info->config); + if (ret) { + dev_err(dev, "Failed to register MHI EP controller: %d\n", ret); + return ret; + } + + return 0; +} + +static int pci_epf_mhi_link_down(struct pci_epf *epf) +{ + struct pci_epf_mhi *epf_mhi = epf_get_drvdata(epf); + struct mhi_ep_cntrl *mhi_cntrl = &epf_mhi->mhi_cntrl; + + if (mhi_cntrl->mhi_dev) { + mhi_ep_power_down(mhi_cntrl); + mhi_ep_unregister_controller(mhi_cntrl); + } + + return 0; +} + +static int pci_epf_mhi_bme(struct pci_epf *epf) +{ + struct pci_epf_mhi *epf_mhi = epf_get_drvdata(epf); + struct mhi_ep_cntrl *mhi_cntrl = &epf_mhi->mhi_cntrl; + struct device *dev = &epf->dev; + int ret; + + /* + * Power up the MHI EP stack if link is up and stack is in power down + * state. + */ + if (!mhi_cntrl->enabled && mhi_cntrl->mhi_dev) { + ret = mhi_ep_power_up(mhi_cntrl); + if (ret) { + dev_err(dev, "Failed to power up MHI EP: %d\n", ret); + mhi_ep_unregister_controller(mhi_cntrl); + } + } + + return 0; +} + +static int pci_epf_mhi_bind(struct pci_epf *epf) +{ + struct pci_epf_mhi *epf_mhi = epf_get_drvdata(epf); + struct pci_epc *epc = epf->epc; + struct platform_device *pdev = to_platform_device(epc->dev.parent); + struct resource *res; + int ret; + + /* Get MMIO base address from Endpoint controller */ + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mmio"); + epf_mhi->mmio_phys = res->start; + epf_mhi->mmio_size = resource_size(res); + + epf_mhi->mmio = ioremap(epf_mhi->mmio_phys, epf_mhi->mmio_size); + if (!epf_mhi->mmio) + return -ENOMEM; + + ret = platform_get_irq_byname(pdev, "doorbell"); + if (ret < 0) { + iounmap(epf_mhi->mmio); + return ret; + } + + epf_mhi->irq = ret; + + return 0; +} + +static void pci_epf_mhi_unbind(struct pci_epf *epf) +{ + struct pci_epf_mhi *epf_mhi = epf_get_drvdata(epf); + const struct pci_epf_mhi_ep_info *info = epf_mhi->info; + struct pci_epf_bar *epf_bar = &epf->bar[info->bar_num]; + struct mhi_ep_cntrl *mhi_cntrl = &epf_mhi->mhi_cntrl; + struct pci_epc *epc = epf->epc; + + /* + * Forcefully power down the MHI EP stack. Only way to bring the MHI EP + * stack back to working state after successive bind is by getting BME + * from host. + */ + if (mhi_cntrl->mhi_dev) { + mhi_ep_power_down(mhi_cntrl); + mhi_ep_unregister_controller(mhi_cntrl); + } + + iounmap(epf_mhi->mmio); + pci_epc_clear_bar(epc, epf->func_no, epf->vfunc_no, epf_bar); +} + +static struct pci_epc_event_ops pci_epf_mhi_event_ops = { + .core_init = pci_epf_mhi_core_init, + .link_up = pci_epf_mhi_link_up, + .link_down = pci_epf_mhi_link_down, + .bme = pci_epf_mhi_bme, +}; + +static int pci_epf_mhi_probe(struct pci_epf *epf, + const struct pci_epf_device_id *id) +{ + struct pci_epf_mhi_ep_info *info = + (struct pci_epf_mhi_ep_info *)id->driver_data; + struct pci_epf_mhi *epf_mhi; + struct device *dev = &epf->dev; + + epf_mhi = devm_kzalloc(dev, sizeof(*epf_mhi), GFP_KERNEL); + if (!epf_mhi) + return -ENOMEM; + + epf->header = info->epf_header; + epf_mhi->info = info; + epf_mhi->epf = epf; + + epf->event_ops = &pci_epf_mhi_event_ops; + + mutex_init(&epf_mhi->lock); + + epf_set_drvdata(epf, epf_mhi); + + return 0; +} + +static const struct pci_epf_device_id pci_epf_mhi_ids[] = { + { + .name = "sdx55", .driver_data = (kernel_ulong_t)&sdx55_info, + }, + {}, +}; + +static struct pci_epf_ops pci_epf_mhi_ops = { + .unbind = pci_epf_mhi_unbind, + .bind = pci_epf_mhi_bind, +}; + +static struct pci_epf_driver pci_epf_mhi_driver = { + .driver.name = "pci_epf_mhi", + .probe = pci_epf_mhi_probe, + .id_table = pci_epf_mhi_ids, + .ops = &pci_epf_mhi_ops, + .owner = THIS_MODULE, +}; + +static int __init pci_epf_mhi_init(void) +{ + return pci_epf_register_driver(&pci_epf_mhi_driver); +} +module_init(pci_epf_mhi_init); + +static void __exit pci_epf_mhi_exit(void) +{ + pci_epf_unregister_driver(&pci_epf_mhi_driver); +} +module_exit(pci_epf_mhi_exit); + +MODULE_DESCRIPTION("PCI EPF driver for MHI Endpoint devices"); +MODULE_AUTHOR("Manivannan Sadhasivam "); +MODULE_LICENSE("GPL"); diff --git a/drivers/pci/endpoint/functions/pci-epf-ntb.c b/drivers/pci/endpoint/functions/pci-epf-ntb.c index 9a00448c7e610ee5aaf824475808810fe0d78f94..9aac2c6f3bb99ddd2c3515a74b59479f77f8ad4b 100644 --- a/drivers/pci/endpoint/functions/pci-epf-ntb.c +++ b/drivers/pci/endpoint/functions/pci-epf-ntb.c @@ -2075,11 +2075,13 @@ static struct config_group *epf_ntb_add_cfs(struct pci_epf *epf, /** * epf_ntb_probe() - Probe NTB function driver * @epf: NTB endpoint function device + * @id: NTB endpoint function device ID * * Probe NTB function driver when endpoint function bus detects a NTB * endpoint function. */ -static int epf_ntb_probe(struct pci_epf *epf) +static int epf_ntb_probe(struct pci_epf *epf, + const struct pci_epf_device_id *id) { struct epf_ntb *ntb; struct device *dev; diff --git a/drivers/pci/endpoint/functions/pci-epf-test.c b/drivers/pci/endpoint/functions/pci-epf-test.c index 0f9d2ec822ac65c5507b74b9bb6f124cb99072bb..1f0d2b84296a34f081648dcc783cdb96fe8accb7 100644 --- a/drivers/pci/endpoint/functions/pci-epf-test.c +++ b/drivers/pci/endpoint/functions/pci-epf-test.c @@ -54,6 +54,9 @@ struct pci_epf_test { struct delayed_work cmd_handler; struct dma_chan *dma_chan_tx; struct dma_chan *dma_chan_rx; + struct dma_chan *transfer_chan; + dma_cookie_t transfer_cookie; + enum dma_status transfer_status; struct completion transfer_complete; bool dma_supported; bool dma_private; @@ -85,8 +88,14 @@ static size_t bar_size[] = { 512, 512, 1024, 16384, 131072, 1048576 }; static void pci_epf_test_dma_callback(void *param) { struct pci_epf_test *epf_test = param; - - complete(&epf_test->transfer_complete); + struct dma_tx_state state; + + epf_test->transfer_status = + dmaengine_tx_status(epf_test->transfer_chan, + epf_test->transfer_cookie, &state); + if (epf_test->transfer_status == DMA_COMPLETE || + epf_test->transfer_status == DMA_ERROR) + complete(&epf_test->transfer_complete); } /** @@ -112,7 +121,7 @@ static int pci_epf_test_data_transfer(struct pci_epf_test *epf_test, size_t len, dma_addr_t dma_remote, enum dma_transfer_direction dir) { - struct dma_chan *chan = (dir == DMA_DEV_TO_MEM) ? + struct dma_chan *chan = (dir == DMA_MEM_TO_DEV) ? epf_test->dma_chan_tx : epf_test->dma_chan_rx; dma_addr_t dma_local = (dir == DMA_MEM_TO_DEV) ? dma_src : dma_dst; enum dma_ctrl_flags flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT; @@ -120,7 +129,6 @@ static int pci_epf_test_data_transfer(struct pci_epf_test *epf_test, struct dma_async_tx_descriptor *tx; struct dma_slave_config sconf = {}; struct device *dev = &epf->dev; - dma_cookie_t cookie; int ret; if (IS_ERR_OR_NULL(chan)) { @@ -151,26 +159,34 @@ static int pci_epf_test_data_transfer(struct pci_epf_test *epf_test, return -EIO; } + reinit_completion(&epf_test->transfer_complete); + epf_test->transfer_chan = chan; tx->callback = pci_epf_test_dma_callback; tx->callback_param = epf_test; - cookie = tx->tx_submit(tx); - reinit_completion(&epf_test->transfer_complete); + epf_test->transfer_cookie = dmaengine_submit(tx); - ret = dma_submit_error(cookie); + ret = dma_submit_error(epf_test->transfer_cookie); if (ret) { - dev_err(dev, "Failed to do DMA tx_submit %d\n", cookie); - return -EIO; + dev_err(dev, "Failed to do DMA tx_submit %d\n", ret); + goto terminate; } dma_async_issue_pending(chan); ret = wait_for_completion_interruptible(&epf_test->transfer_complete); if (ret < 0) { - dmaengine_terminate_sync(chan); - dev_err(dev, "DMA wait_for_completion_timeout\n"); - return -ETIMEDOUT; + dev_err(dev, "DMA wait_for_completion interrupted\n"); + goto terminate; } - return 0; + if (epf_test->transfer_status == DMA_ERROR) { + dev_err(dev, "DMA transfer failed\n"); + ret = -EIO; + } + +terminate: + dmaengine_terminate_sync(chan); + + return ret; } struct epf_dma_filter { @@ -279,40 +295,29 @@ static void pci_epf_test_clean_dma_chan(struct pci_epf_test *epf_test) return; } -static void pci_epf_test_print_rate(const char *ops, u64 size, +static void pci_epf_test_print_rate(struct pci_epf_test *epf_test, + const char *op, u64 size, struct timespec64 *start, struct timespec64 *end, bool dma) { - struct timespec64 ts; - u64 rate, ns; - - ts = timespec64_sub(*end, *start); - - /* convert both size (stored in 'rate') and time in terms of 'ns' */ - ns = timespec64_to_ns(&ts); - rate = size * NSEC_PER_SEC; - - /* Divide both size (stored in 'rate') and ns by a common factor */ - while (ns > UINT_MAX) { - rate >>= 1; - ns >>= 1; - } - - if (!ns) - return; + struct timespec64 ts = timespec64_sub(*end, *start); + u64 rate = 0, ns; /* calculate the rate */ - do_div(rate, (uint32_t)ns); + ns = timespec64_to_ns(&ts); + if (ns) + rate = div64_u64(size * NSEC_PER_SEC, ns * 1000); - pr_info("\n%s => Size: %llu bytes\t DMA: %s\t Time: %llu.%09u seconds\t" - "Rate: %llu KB/s\n", ops, size, dma ? "YES" : "NO", - (u64)ts.tv_sec, (u32)ts.tv_nsec, rate / 1024); + dev_info(&epf_test->epf->dev, + "%s => Size: %llu B, DMA: %s, Time: %llu.%09u s, Rate: %llu KB/s\n", + op, size, dma ? "YES" : "NO", + (u64)ts.tv_sec, (u32)ts.tv_nsec, rate); } -static int pci_epf_test_copy(struct pci_epf_test *epf_test) +static void pci_epf_test_copy(struct pci_epf_test *epf_test, + struct pci_epf_test_reg *reg) { int ret; - bool use_dma; void __iomem *src_addr; void __iomem *dst_addr; phys_addr_t src_phys_addr; @@ -321,8 +326,6 @@ static int pci_epf_test_copy(struct pci_epf_test *epf_test) struct pci_epf *epf = epf_test->epf; struct device *dev = &epf->dev; struct pci_epc *epc = epf->epc; - enum pci_barno test_reg_bar = epf_test->test_reg_bar; - struct pci_epf_test_reg *reg = epf_test->reg[test_reg_bar]; src_addr = pci_epc_mem_alloc_addr(epc, &src_phys_addr, reg->size); if (!src_addr) { @@ -357,14 +360,7 @@ static int pci_epf_test_copy(struct pci_epf_test *epf_test) } ktime_get_ts64(&start); - use_dma = !!(reg->flags & FLAG_USE_DMA); - if (use_dma) { - if (!epf_test->dma_supported) { - dev_err(dev, "Cannot transfer data using DMA\n"); - ret = -EINVAL; - goto err_map_addr; - } - + if (reg->flags & FLAG_USE_DMA) { if (epf_test->dma_private) { dev_err(dev, "Cannot transfer data using DMA\n"); ret = -EINVAL; @@ -390,7 +386,8 @@ static int pci_epf_test_copy(struct pci_epf_test *epf_test) kfree(buf); } ktime_get_ts64(&end); - pci_epf_test_print_rate("COPY", reg->size, &start, &end, use_dma); + pci_epf_test_print_rate(epf_test, "COPY", reg->size, &start, &end, + reg->flags & FLAG_USE_DMA); err_map_addr: pci_epc_unmap_addr(epc, epf->func_no, epf->vfunc_no, dst_phys_addr); @@ -405,16 +402,19 @@ static int pci_epf_test_copy(struct pci_epf_test *epf_test) pci_epc_mem_free_addr(epc, src_phys_addr, src_addr, reg->size); err: - return ret; + if (!ret) + reg->status |= STATUS_COPY_SUCCESS; + else + reg->status |= STATUS_COPY_FAIL; } -static int pci_epf_test_read(struct pci_epf_test *epf_test) +static void pci_epf_test_read(struct pci_epf_test *epf_test, + struct pci_epf_test_reg *reg) { int ret; void __iomem *src_addr; void *buf; u32 crc32; - bool use_dma; phys_addr_t phys_addr; phys_addr_t dst_phys_addr; struct timespec64 start, end; @@ -422,8 +422,6 @@ static int pci_epf_test_read(struct pci_epf_test *epf_test) struct device *dev = &epf->dev; struct pci_epc *epc = epf->epc; struct device *dma_dev = epf->epc->dev.parent; - enum pci_barno test_reg_bar = epf_test->test_reg_bar; - struct pci_epf_test_reg *reg = epf_test->reg[test_reg_bar]; src_addr = pci_epc_mem_alloc_addr(epc, &phys_addr, reg->size); if (!src_addr) { @@ -447,14 +445,7 @@ static int pci_epf_test_read(struct pci_epf_test *epf_test) goto err_map_addr; } - use_dma = !!(reg->flags & FLAG_USE_DMA); - if (use_dma) { - if (!epf_test->dma_supported) { - dev_err(dev, "Cannot transfer data using DMA\n"); - ret = -EINVAL; - goto err_dma_map; - } - + if (reg->flags & FLAG_USE_DMA) { dst_phys_addr = dma_map_single(dma_dev, buf, reg->size, DMA_FROM_DEVICE); if (dma_mapping_error(dma_dev, dst_phys_addr)) { @@ -479,7 +470,8 @@ static int pci_epf_test_read(struct pci_epf_test *epf_test) ktime_get_ts64(&end); } - pci_epf_test_print_rate("READ", reg->size, &start, &end, use_dma); + pci_epf_test_print_rate(epf_test, "READ", reg->size, &start, &end, + reg->flags & FLAG_USE_DMA); crc32 = crc32_le(~0, buf, reg->size); if (crc32 != reg->checksum) @@ -495,15 +487,18 @@ static int pci_epf_test_read(struct pci_epf_test *epf_test) pci_epc_mem_free_addr(epc, phys_addr, src_addr, reg->size); err: - return ret; + if (!ret) + reg->status |= STATUS_READ_SUCCESS; + else + reg->status |= STATUS_READ_FAIL; } -static int pci_epf_test_write(struct pci_epf_test *epf_test) +static void pci_epf_test_write(struct pci_epf_test *epf_test, + struct pci_epf_test_reg *reg) { int ret; void __iomem *dst_addr; void *buf; - bool use_dma; phys_addr_t phys_addr; phys_addr_t src_phys_addr; struct timespec64 start, end; @@ -511,8 +506,6 @@ static int pci_epf_test_write(struct pci_epf_test *epf_test) struct device *dev = &epf->dev; struct pci_epc *epc = epf->epc; struct device *dma_dev = epf->epc->dev.parent; - enum pci_barno test_reg_bar = epf_test->test_reg_bar; - struct pci_epf_test_reg *reg = epf_test->reg[test_reg_bar]; dst_addr = pci_epc_mem_alloc_addr(epc, &phys_addr, reg->size); if (!dst_addr) { @@ -539,14 +532,7 @@ static int pci_epf_test_write(struct pci_epf_test *epf_test) get_random_bytes(buf, reg->size); reg->checksum = crc32_le(~0, buf, reg->size); - use_dma = !!(reg->flags & FLAG_USE_DMA); - if (use_dma) { - if (!epf_test->dma_supported) { - dev_err(dev, "Cannot transfer data using DMA\n"); - ret = -EINVAL; - goto err_dma_map; - } - + if (reg->flags & FLAG_USE_DMA) { src_phys_addr = dma_map_single(dma_dev, buf, reg->size, DMA_TO_DEVICE); if (dma_mapping_error(dma_dev, src_phys_addr)) { @@ -573,7 +559,8 @@ static int pci_epf_test_write(struct pci_epf_test *epf_test) ktime_get_ts64(&end); } - pci_epf_test_print_rate("WRITE", reg->size, &start, &end, use_dma); + pci_epf_test_print_rate(epf_test, "WRITE", reg->size, &start, &end, + reg->flags & FLAG_USE_DMA); /* * wait 1ms inorder for the write to complete. Without this delay L3 @@ -591,32 +578,51 @@ static int pci_epf_test_write(struct pci_epf_test *epf_test) pci_epc_mem_free_addr(epc, phys_addr, dst_addr, reg->size); err: - return ret; + if (!ret) + reg->status |= STATUS_WRITE_SUCCESS; + else + reg->status |= STATUS_WRITE_FAIL; } -static void pci_epf_test_raise_irq(struct pci_epf_test *epf_test, u8 irq_type, - u16 irq) +static void pci_epf_test_raise_irq(struct pci_epf_test *epf_test, + struct pci_epf_test_reg *reg) { struct pci_epf *epf = epf_test->epf; struct device *dev = &epf->dev; struct pci_epc *epc = epf->epc; - enum pci_barno test_reg_bar = epf_test->test_reg_bar; - struct pci_epf_test_reg *reg = epf_test->reg[test_reg_bar]; + u32 status = reg->status | STATUS_IRQ_RAISED; + int count; - reg->status |= STATUS_IRQ_RAISED; + /* + * Set the status before raising the IRQ to ensure that the host sees + * the updated value when it gets the IRQ. + */ + WRITE_ONCE(reg->status, status); - switch (irq_type) { + switch (reg->irq_type) { case IRQ_TYPE_LEGACY: pci_epc_raise_irq(epc, epf->func_no, epf->vfunc_no, PCI_EPC_IRQ_LEGACY, 0); break; case IRQ_TYPE_MSI: + count = pci_epc_get_msi(epc, epf->func_no, epf->vfunc_no); + if (reg->irq_number > count || count <= 0) { + dev_err(dev, "Invalid MSI IRQ number %d / %d\n", + reg->irq_number, count); + return; + } pci_epc_raise_irq(epc, epf->func_no, epf->vfunc_no, - PCI_EPC_IRQ_MSI, irq); + PCI_EPC_IRQ_MSI, reg->irq_number); break; case IRQ_TYPE_MSIX: + count = pci_epc_get_msix(epc, epf->func_no, epf->vfunc_no); + if (reg->irq_number > count || count <= 0) { + dev_err(dev, "Invalid MSIX IRQ number %d / %d\n", + reg->irq_number, count); + return; + } pci_epc_raise_irq(epc, epf->func_no, epf->vfunc_no, - PCI_EPC_IRQ_MSIX, irq); + PCI_EPC_IRQ_MSIX, reg->irq_number); break; default: dev_err(dev, "Failed to raise IRQ, unknown type\n"); @@ -626,87 +632,53 @@ static void pci_epf_test_raise_irq(struct pci_epf_test *epf_test, u8 irq_type, static void pci_epf_test_cmd_handler(struct work_struct *work) { - int ret; - int count; u32 command; struct pci_epf_test *epf_test = container_of(work, struct pci_epf_test, cmd_handler.work); struct pci_epf *epf = epf_test->epf; struct device *dev = &epf->dev; - struct pci_epc *epc = epf->epc; enum pci_barno test_reg_bar = epf_test->test_reg_bar; struct pci_epf_test_reg *reg = epf_test->reg[test_reg_bar]; - command = reg->command; + command = READ_ONCE(reg->command); if (!command) goto reset_handler; - reg->command = 0; - reg->status = 0; + WRITE_ONCE(reg->command, 0); + WRITE_ONCE(reg->status, 0); - if (reg->irq_type > IRQ_TYPE_MSIX) { - dev_err(dev, "Failed to detect IRQ type\n"); + if ((READ_ONCE(reg->flags) & FLAG_USE_DMA) && + !epf_test->dma_supported) { + dev_err(dev, "Cannot transfer data using DMA\n"); goto reset_handler; } - if (command & COMMAND_RAISE_LEGACY_IRQ) { - reg->status = STATUS_IRQ_RAISED; - pci_epc_raise_irq(epc, epf->func_no, epf->vfunc_no, - PCI_EPC_IRQ_LEGACY, 0); - goto reset_handler; - } - - if (command & COMMAND_WRITE) { - ret = pci_epf_test_write(epf_test); - if (ret) - reg->status |= STATUS_WRITE_FAIL; - else - reg->status |= STATUS_WRITE_SUCCESS; - pci_epf_test_raise_irq(epf_test, reg->irq_type, - reg->irq_number); - goto reset_handler; - } - - if (command & COMMAND_READ) { - ret = pci_epf_test_read(epf_test); - if (!ret) - reg->status |= STATUS_READ_SUCCESS; - else - reg->status |= STATUS_READ_FAIL; - pci_epf_test_raise_irq(epf_test, reg->irq_type, - reg->irq_number); - goto reset_handler; - } - - if (command & COMMAND_COPY) { - ret = pci_epf_test_copy(epf_test); - if (!ret) - reg->status |= STATUS_COPY_SUCCESS; - else - reg->status |= STATUS_COPY_FAIL; - pci_epf_test_raise_irq(epf_test, reg->irq_type, - reg->irq_number); - goto reset_handler; - } - - if (command & COMMAND_RAISE_MSI_IRQ) { - count = pci_epc_get_msi(epc, epf->func_no, epf->vfunc_no); - if (reg->irq_number > count || count <= 0) - goto reset_handler; - reg->status = STATUS_IRQ_RAISED; - pci_epc_raise_irq(epc, epf->func_no, epf->vfunc_no, - PCI_EPC_IRQ_MSI, reg->irq_number); + if (reg->irq_type > IRQ_TYPE_MSIX) { + dev_err(dev, "Failed to detect IRQ type\n"); goto reset_handler; } - if (command & COMMAND_RAISE_MSIX_IRQ) { - count = pci_epc_get_msix(epc, epf->func_no, epf->vfunc_no); - if (reg->irq_number > count || count <= 0) - goto reset_handler; - reg->status = STATUS_IRQ_RAISED; - pci_epc_raise_irq(epc, epf->func_no, epf->vfunc_no, - PCI_EPC_IRQ_MSIX, reg->irq_number); - goto reset_handler; + switch (command) { + case COMMAND_RAISE_LEGACY_IRQ: + case COMMAND_RAISE_MSI_IRQ: + case COMMAND_RAISE_MSIX_IRQ: + pci_epf_test_raise_irq(epf_test, reg); + break; + case COMMAND_WRITE: + pci_epf_test_write(epf_test, reg); + pci_epf_test_raise_irq(epf_test, reg); + break; + case COMMAND_READ: + pci_epf_test_read(epf_test, reg); + pci_epf_test_raise_irq(epf_test, reg); + break; + case COMMAND_COPY: + pci_epf_test_copy(epf_test, reg); + pci_epf_test_raise_irq(epf_test, reg); + break; + default: + dev_err(dev, "Invalid command 0x%x\n", command); + break; } reset_handler: @@ -980,7 +952,8 @@ static const struct pci_epf_device_id pci_epf_test_ids[] = { {}, }; -static int pci_epf_test_probe(struct pci_epf *epf) +static int pci_epf_test_probe(struct pci_epf *epf, + const struct pci_epf_device_id *id) { struct pci_epf_test *epf_test; struct device *dev = &epf->dev; diff --git a/drivers/pci/endpoint/functions/pci-epf-vntb.c b/drivers/pci/endpoint/functions/pci-epf-vntb.c index b7c7a8af99f4f02099c2f6308c075dc6fd57df63..c8b423c3c26e94c1c7e37e1328253834fe3543a8 100644 --- a/drivers/pci/endpoint/functions/pci-epf-vntb.c +++ b/drivers/pci/endpoint/functions/pci-epf-vntb.c @@ -84,15 +84,15 @@ enum epf_ntb_bar { * | | * | | * | | - * +-----------------------+--------------------------+ Base+span_offset + * +-----------------------+--------------------------+ Base+spad_offset * | | | - * | Peer Span Space | Span Space | + * | Peer Spad Space | Spad Space | * | | | * | | | - * +-----------------------+--------------------------+ Base+span_offset - * | | | +span_count * 4 + * +-----------------------+--------------------------+ Base+spad_offset + * | | | +spad_count * 4 * | | | - * | Span Space | Peer Span Space | + * | Spad Space | Peer Spad Space | * | | | * +-----------------------+--------------------------+ * Virtual PCI PCIe Endpoint @@ -1285,6 +1285,7 @@ static int pci_vntb_probe(struct pci_dev *pdev, const struct pci_device_id *id) return 0; err_register_dev: + put_device(&ndev->ntb.dev); return -EINVAL; } @@ -1395,13 +1396,15 @@ static struct pci_epf_ops epf_ntb_ops = { /** * epf_ntb_probe() - Probe NTB function driver * @epf: NTB endpoint function device + * @id: NTB endpoint function device ID * * Probe NTB function driver when endpoint function bus detects a NTB * endpoint function. * * Returns: Zero for success, or an error code in case of failure */ -static int epf_ntb_probe(struct pci_epf *epf) +static int epf_ntb_probe(struct pci_epf *epf, + const struct pci_epf_device_id *id) { struct epf_ntb *ntb; struct device *dev; diff --git a/drivers/pci/endpoint/pci-ep-cfs.c b/drivers/pci/endpoint/pci-ep-cfs.c index 4b8ac0ac84d5b5fe1da5167614953e869e5ec713..0ea64e24ed616b4132a1cfa9d9e1ee136b8f2b06 100644 --- a/drivers/pci/endpoint/pci-ep-cfs.c +++ b/drivers/pci/endpoint/pci-ep-cfs.c @@ -23,6 +23,7 @@ struct pci_epf_group { struct config_group group; struct config_group primary_epc_group; struct config_group secondary_epc_group; + struct config_group *type_group; struct delayed_work cfs_work; struct pci_epf *epf; int index; @@ -178,6 +179,9 @@ static ssize_t pci_epc_start_store(struct config_item *item, const char *page, if (kstrtobool(page, &start) < 0) return -EINVAL; + if (start == epc_group->start) + return -EALREADY; + if (!start) { pci_epc_stop(epc); epc_group->start = 0; @@ -502,33 +506,64 @@ static struct configfs_item_operations pci_epf_ops = { .release = pci_epf_release, }; -static struct config_group *pci_epf_type_make(struct config_group *group, - const char *name) +static const struct config_item_type pci_epf_type = { + .ct_item_ops = &pci_epf_ops, + .ct_attrs = pci_epf_attrs, + .ct_owner = THIS_MODULE, +}; + +/** + * pci_epf_type_add_cfs() - Help function drivers to expose function specific + * attributes in configfs + * @epf: the EPF device that has to be configured using configfs + * @group: the parent configfs group (corresponding to entries in + * pci_epf_device_id) + * + * Invoke to expose function specific attributes in configfs. + * + * Return: A pointer to a config_group structure or NULL if the function driver + * does not have anything to expose (attributes configured by user) or if + * the function driver does not implement the add_cfs() method. + * + * Returns an error pointer if this function is called for an unbound EPF device + * or if the EPF driver add_cfs() method fails. + */ +static struct config_group *pci_epf_type_add_cfs(struct pci_epf *epf, + struct config_group *group) { - struct pci_epf_group *epf_group = to_pci_epf_group(&group->cg_item); struct config_group *epf_type_group; - epf_type_group = pci_epf_type_add_cfs(epf_group->epf, group); + if (!epf->driver) { + dev_err(&epf->dev, "epf device not bound to driver\n"); + return ERR_PTR(-ENODEV); + } + + if (!epf->driver->ops->add_cfs) + return NULL; + + mutex_lock(&epf->lock); + epf_type_group = epf->driver->ops->add_cfs(epf, group); + mutex_unlock(&epf->lock); + return epf_type_group; } -static void pci_epf_type_drop(struct config_group *group, - struct config_item *item) +static void pci_ep_cfs_add_type_group(struct pci_epf_group *epf_group) { - config_item_put(item); -} + struct config_group *group; -static struct configfs_group_operations pci_epf_type_group_ops = { - .make_group = &pci_epf_type_make, - .drop_item = &pci_epf_type_drop, -}; + group = pci_epf_type_add_cfs(epf_group->epf, &epf_group->group); + if (!group) + return; -static const struct config_item_type pci_epf_type = { - .ct_group_ops = &pci_epf_type_group_ops, - .ct_item_ops = &pci_epf_ops, - .ct_attrs = pci_epf_attrs, - .ct_owner = THIS_MODULE, -}; + if (IS_ERR(group)) { + dev_err(&epf_group->epf->dev, + "failed to create epf type specific attributes\n"); + return; + } + + configfs_register_group(&epf_group->group, group); +} static void pci_epf_cfs_work(struct work_struct *work) { @@ -547,6 +582,8 @@ static void pci_epf_cfs_work(struct work_struct *work) pr_err("failed to create 'secondary' EPC interface\n"); return; } + + pci_ep_cfs_add_type_group(epf_group); } static struct config_group *pci_epf_make(struct config_group *group, diff --git a/drivers/pci/endpoint/pci-epc-core.c b/drivers/pci/endpoint/pci-epc-core.c index 46c9a5c3ca14b2b5233e0197ac9881747be82062..6c54fa5684d22a1552946d665907f5c91da162c6 100644 --- a/drivers/pci/endpoint/pci-epc-core.c +++ b/drivers/pci/endpoint/pci-epc-core.c @@ -213,7 +213,7 @@ EXPORT_SYMBOL_GPL(pci_epc_start); * @func_no: the physical endpoint function number in the EPC device * @vfunc_no: the virtual endpoint function number in the physical function * @type: specify the type of interrupt; legacy, MSI or MSI-X - * @interrupt_num: the MSI or MSI-X interrupt number + * @interrupt_num: the MSI or MSI-X interrupt number with range (1-N) * * Invoke to raise an legacy, MSI or MSI-X interrupt */ @@ -246,7 +246,7 @@ EXPORT_SYMBOL_GPL(pci_epc_raise_irq); * @func_no: the physical endpoint function number in the EPC device * @vfunc_no: the virtual endpoint function number in the physical function * @phys_addr: the physical address of the outbound region - * @interrupt_num: the MSI interrupt number + * @interrupt_num: the MSI interrupt number with range (1-N) * @entry_size: Size of Outbound address region for each interrupt * @msi_data: the data that should be written in order to raise MSI interrupt * with interrupt number as 'interrupt num' @@ -706,6 +706,32 @@ void pci_epc_linkup(struct pci_epc *epc) } EXPORT_SYMBOL_GPL(pci_epc_linkup); +/** + * pci_epc_linkdown() - Notify the EPF device that EPC device has dropped the + * connection with the Root Complex. + * @epc: the EPC device which has dropped the link with the host + * + * Invoke to Notify the EPF device that the EPC device has dropped the + * connection with the Root Complex. + */ +void pci_epc_linkdown(struct pci_epc *epc) +{ + struct pci_epf *epf; + + if (!epc || IS_ERR(epc)) + return; + + mutex_lock(&epc->list_lock); + list_for_each_entry(epf, &epc->pci_epf, list) { + mutex_lock(&epf->lock); + if (epf->event_ops && epf->event_ops->link_down) + epf->event_ops->link_down(epf); + mutex_unlock(&epf->lock); + } + mutex_unlock(&epc->list_lock); +} +EXPORT_SYMBOL_GPL(pci_epc_linkdown); + /** * pci_epc_init_notify() - Notify the EPF device that EPC device's core * initialization is completed. @@ -732,6 +758,32 @@ void pci_epc_init_notify(struct pci_epc *epc) } EXPORT_SYMBOL_GPL(pci_epc_init_notify); +/** + * pci_epc_bme_notify() - Notify the EPF device that the EPC device has received + * the BME event from the Root complex + * @epc: the EPC device that received the BME event + * + * Invoke to Notify the EPF device that the EPC device has received the Bus + * Master Enable (BME) event from the Root complex + */ +void pci_epc_bme_notify(struct pci_epc *epc) +{ + struct pci_epf *epf; + + if (!epc || IS_ERR(epc)) + return; + + mutex_lock(&epc->list_lock); + list_for_each_entry(epf, &epc->pci_epf, list) { + mutex_lock(&epf->lock); + if (epf->event_ops && epf->event_ops->bme) + epf->event_ops->bme(epf); + mutex_unlock(&epf->lock); + } + mutex_unlock(&epc->list_lock); +} +EXPORT_SYMBOL_GPL(pci_epc_bme_notify); + /** * pci_epc_destroy() - destroy the EPC device * @epc: the EPC device that has to be destroyed diff --git a/drivers/pci/endpoint/pci-epf-core.c b/drivers/pci/endpoint/pci-epf-core.c index 2036e38be093a175ab8496b6fb53b25846d7303a..2c32de66793778d3d99932e362339bc1764451ee 100644 --- a/drivers/pci/endpoint/pci-epf-core.c +++ b/drivers/pci/endpoint/pci-epf-core.c @@ -20,38 +20,6 @@ static DEFINE_MUTEX(pci_epf_mutex); static struct bus_type pci_epf_bus_type; static const struct device_type pci_epf_type; -/** - * pci_epf_type_add_cfs() - Help function drivers to expose function specific - * attributes in configfs - * @epf: the EPF device that has to be configured using configfs - * @group: the parent configfs group (corresponding to entries in - * pci_epf_device_id) - * - * Invoke to expose function specific attributes in configfs. If the function - * driver does not have anything to expose (attributes configured by user), - * return NULL. - */ -struct config_group *pci_epf_type_add_cfs(struct pci_epf *epf, - struct config_group *group) -{ - struct config_group *epf_type_group; - - if (!epf->driver) { - dev_err(&epf->dev, "epf device not bound to driver\n"); - return NULL; - } - - if (!epf->driver->ops->add_cfs) - return NULL; - - mutex_lock(&epf->lock); - epf_type_group = epf->driver->ops->add_cfs(epf, group); - mutex_unlock(&epf->lock); - - return epf_type_group; -} -EXPORT_SYMBOL_GPL(pci_epf_type_add_cfs); - /** * pci_epf_unbind() - Notify the function driver that the binding between the * EPF device and EPC device has been lost @@ -493,16 +461,16 @@ static const struct device_type pci_epf_type = { .release = pci_epf_dev_release, }; -static int +static const struct pci_epf_device_id * pci_epf_match_id(const struct pci_epf_device_id *id, const struct pci_epf *epf) { while (id->name[0]) { if (strcmp(epf->name, id->name) == 0) - return true; + return id; id++; } - return false; + return NULL; } static int pci_epf_device_match(struct device *dev, struct device_driver *drv) @@ -511,7 +479,7 @@ static int pci_epf_device_match(struct device *dev, struct device_driver *drv) struct pci_epf_driver *driver = to_pci_epf_driver(drv); if (driver->id_table) - return pci_epf_match_id(driver->id_table, epf); + return !!pci_epf_match_id(driver->id_table, epf); return !strcmp(epf->name, drv->name); } @@ -526,7 +494,7 @@ static int pci_epf_device_probe(struct device *dev) epf->driver = driver; - return driver->probe(epf); + return driver->probe(epf, pci_epf_match_id(driver->id_table, epf)); } static void pci_epf_device_remove(struct device *dev) diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 5b1f271c6034be045aa446f7e5aacb2d6e3f2e2a..328d1e416014762dcebd78f4187b3e9a1b34cb9e 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -498,7 +498,6 @@ static void enable_slot(struct acpiphp_slot *slot, bool bridge) acpiphp_native_scan_bridge(dev); } } else { - LIST_HEAD(add_list); int max, pass; acpiphp_rescan_slot(slot); @@ -512,12 +511,10 @@ static void enable_slot(struct acpiphp_slot *slot, bool bridge) if (pass && dev->subordinate) { check_hotplug_bridge(slot, dev); pcibios_resource_survey_bus(dev->subordinate); - __pci_bus_size_bridges(dev->subordinate, - &add_list); } } } - __pci_bus_assign_resources(bus, &add_list, NULL); + pci_assign_unassigned_bridge_resources(bus->self); } acpiphp_sanitize_bus(bus); diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c index 529c348084401462090b7667394d0ce0cd4bce96..dcdbfcf404ddf449481055f16d9a4d05b06a9530 100644 --- a/drivers/pci/hotplug/pciehp_ctrl.c +++ b/drivers/pci/hotplug/pciehp_ctrl.c @@ -166,11 +166,11 @@ void pciehp_handle_button_press(struct controller *ctrl) case ON_STATE: if (ctrl->state == ON_STATE) { ctrl->state = BLINKINGOFF_STATE; - ctrl_info(ctrl, "Slot(%s): Powering off due to button press\n", + ctrl_info(ctrl, "Slot(%s): Button press: will power off in 5 sec\n", slot_name(ctrl)); } else { ctrl->state = BLINKINGON_STATE; - ctrl_info(ctrl, "Slot(%s) Powering on due to button press\n", + ctrl_info(ctrl, "Slot(%s): Button press: will power on in 5 sec\n", slot_name(ctrl)); } /* blink power indicator and turn off attention */ @@ -185,22 +185,23 @@ void pciehp_handle_button_press(struct controller *ctrl) * press the attention again before the 5 sec. limit * expires to cancel hot-add or hot-remove */ - ctrl_info(ctrl, "Slot(%s): Button cancel\n", slot_name(ctrl)); cancel_delayed_work(&ctrl->button_work); if (ctrl->state == BLINKINGOFF_STATE) { ctrl->state = ON_STATE; pciehp_set_indicators(ctrl, PCI_EXP_SLTCTL_PWR_IND_ON, PCI_EXP_SLTCTL_ATTN_IND_OFF); + ctrl_info(ctrl, "Slot(%s): Button press: canceling request to power off\n", + slot_name(ctrl)); } else { ctrl->state = OFF_STATE; pciehp_set_indicators(ctrl, PCI_EXP_SLTCTL_PWR_IND_OFF, PCI_EXP_SLTCTL_ATTN_IND_OFF); + ctrl_info(ctrl, "Slot(%s): Button press: canceling request to power on\n", + slot_name(ctrl)); } - ctrl_info(ctrl, "Slot(%s): Action canceled due to button press\n", - slot_name(ctrl)); break; default: - ctrl_err(ctrl, "Slot(%s): Ignoring invalid state %#x\n", + ctrl_err(ctrl, "Slot(%s): Button press: ignoring invalid state %#x\n", slot_name(ctrl), ctrl->state); break; } @@ -256,6 +257,14 @@ void pciehp_handle_presence_or_link_change(struct controller *ctrl, u32 events) present = pciehp_card_present(ctrl); link_active = pciehp_check_link_active(ctrl); if (present <= 0 && link_active <= 0) { + if (ctrl->state == BLINKINGON_STATE) { + ctrl->state = OFF_STATE; + cancel_delayed_work(&ctrl->button_work); + pciehp_set_indicators(ctrl, PCI_EXP_SLTCTL_PWR_IND_OFF, + INDICATOR_NOOP); + ctrl_info(ctrl, "Slot(%s): Card not present\n", + slot_name(ctrl)); + } mutex_unlock(&ctrl->state_lock); return; } diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index f8c70115b6917265d3d9a4fc6da561c4d96ae0f8..8711325605f0a537d72fdb5843e353773333d665 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c @@ -722,11 +722,8 @@ static irqreturn_t pciehp_ist(int irq, void *dev_id) } /* Check Attention Button Pressed */ - if (events & PCI_EXP_SLTSTA_ABP) { - ctrl_info(ctrl, "Slot(%s): Attention button pressed\n", - slot_name(ctrl)); + if (events & PCI_EXP_SLTSTA_ABP) pciehp_handle_button_press(ctrl); - } /* Check Power Fault Detected */ if (events & PCI_EXP_SLTSTA_PFD) { @@ -984,7 +981,7 @@ static inline int pcie_hotplug_depth(struct pci_dev *dev) struct controller *pcie_init(struct pcie_device *dev) { struct controller *ctrl; - u32 slot_cap, slot_cap2, link_cap; + u32 slot_cap, slot_cap2; u8 poweron; struct pci_dev *pdev = dev->port; struct pci_bus *subordinate = pdev->subordinate; @@ -1030,9 +1027,6 @@ struct controller *pcie_init(struct pcie_device *dev) if (dmi_first_match(inband_presence_disabled_dmi_table)) ctrl->inband_presence_disabled = 1; - /* Check if Data Link Layer Link Active Reporting is implemented */ - pcie_capability_read_dword(pdev, PCI_EXP_LNKCAP, &link_cap); - /* Clear all remaining event bits in Slot Status register. */ pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, PCI_EXP_SLTSTA_ABP | PCI_EXP_SLTSTA_PFD | @@ -1051,7 +1045,7 @@ struct controller *pcie_init(struct pcie_device *dev) FLAG(slot_cap, PCI_EXP_SLTCAP_EIP), FLAG(slot_cap, PCI_EXP_SLTCAP_NCCS), FLAG(slot_cap2, PCI_EXP_SLTCAP2_IBPD), - FLAG(link_cap, PCI_EXP_LNKCAP_DLLLARC), + FLAG(pdev->link_active_reporting, true), pdev->broken_cmd_compl ? " (with Cmd Compl erratum)" : ""); /* diff --git a/drivers/pci/of.c b/drivers/pci/of.c index 2c25f4fa0225aeed064b7c103ee0f7c7b801011b..e51219f9f523cd557670e51f7f0929927431ef15 100644 --- a/drivers/pci/of.c +++ b/drivers/pci/of.c @@ -39,16 +39,14 @@ int pci_set_of_node(struct pci_dev *dev) return -ENODEV; } - dev->dev.of_node = node; - dev->dev.fwnode = &node->fwnode; + device_set_node(&dev->dev, of_fwnode_handle(node)); return 0; } void pci_release_of_node(struct pci_dev *dev) { of_node_put(dev->dev.of_node); - dev->dev.of_node = NULL; - dev->dev.fwnode = NULL; + device_set_node(&dev->dev, NULL); } void pci_set_bus_of_node(struct pci_bus *bus) @@ -63,17 +61,13 @@ void pci_set_bus_of_node(struct pci_bus *bus) bus->self->external_facing = true; } - bus->dev.of_node = node; - - if (bus->dev.of_node) - bus->dev.fwnode = &bus->dev.of_node->fwnode; + device_set_node(&bus->dev, of_fwnode_handle(node)); } void pci_release_bus_of_node(struct pci_bus *bus) { of_node_put(bus->dev.of_node); - bus->dev.of_node = NULL; - bus->dev.fwnode = NULL; + device_set_node(&bus->dev, NULL); } struct device_node * __weak pcibios_get_phb_of_node(struct pci_bus *bus) diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index 052a611081ecd926b08b5cd4fbdc7c2c428fb0fa..a05350a4e49cb43699b0f1f817dd67698f1839da 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c @@ -1043,6 +1043,16 @@ bool acpi_pci_bridge_d3(struct pci_dev *dev) return false; } +static void acpi_pci_config_space_access(struct pci_dev *dev, bool enable) +{ + int val = enable ? ACPI_REG_CONNECT : ACPI_REG_DISCONNECT; + int ret = acpi_evaluate_reg(ACPI_HANDLE(&dev->dev), + ACPI_ADR_SPACE_PCI_CONFIG, val); + if (ret) + pci_dbg(dev, "ACPI _REG %s evaluation failed (%d)\n", + enable ? "connect" : "disconnect", ret); +} + int acpi_pci_set_power_state(struct pci_dev *dev, pci_power_t state) { struct acpi_device *adev = ACPI_COMPANION(&dev->dev); @@ -1053,32 +1063,49 @@ int acpi_pci_set_power_state(struct pci_dev *dev, pci_power_t state) [PCI_D3hot] = ACPI_STATE_D3_HOT, [PCI_D3cold] = ACPI_STATE_D3_COLD, }; - int error = -EINVAL; + int error; /* If the ACPI device has _EJ0, ignore the device */ if (!adev || acpi_has_method(adev->handle, "_EJ0")) return -ENODEV; switch (state) { - case PCI_D3cold: - if (dev_pm_qos_flags(&dev->dev, PM_QOS_FLAG_NO_POWER_OFF) == - PM_QOS_FLAGS_ALL) { - error = -EBUSY; - break; - } - fallthrough; case PCI_D0: case PCI_D1: case PCI_D2: case PCI_D3hot: - error = acpi_device_set_power(adev, state_conv[state]); + case PCI_D3cold: + break; + default: + return -EINVAL; + } + + if (state == PCI_D3cold) { + if (dev_pm_qos_flags(&dev->dev, PM_QOS_FLAG_NO_POWER_OFF) == + PM_QOS_FLAGS_ALL) + return -EBUSY; + + /* Notify AML lack of PCI config space availability */ + acpi_pci_config_space_access(dev, false); } - if (!error) - pci_dbg(dev, "power state changed by ACPI to %s\n", - acpi_power_state_string(adev->power.state)); + error = acpi_device_set_power(adev, state_conv[state]); + if (error) + return error; - return error; + pci_dbg(dev, "power state changed by ACPI to %s\n", + acpi_power_state_string(adev->power.state)); + + /* + * Notify AML of PCI config space availability. Config space is + * accessible in all states except D3cold; the only transitions + * that change availability are transitions to D3cold and from + * D3cold to D0. + */ + if (state == PCI_D0) + acpi_pci_config_space_access(dev, true); + + return 0; } pci_power_t acpi_pci_get_power_state(struct pci_dev *dev) diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 5ede93222bc12756ca5d129f208ca29322507b0d..60230da957e0c4b1d4481a191dfa709600f2b48b 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -64,6 +64,13 @@ struct pci_pme_device { #define PME_TIMEOUT 1000 /* How long between PME checks */ +/* + * Following exit from Conventional Reset, devices must be ready within 1 sec + * (PCIe r6.0 sec 6.6.1). A D3cold to D0 transition implies a Conventional + * Reset (PCIe r6.0 sec 5.8). + */ +#define PCI_RESET_WAIT 1000 /* msec */ + /* * Devices may extend the 1 sec period through Request Retry Status * completions (PCIe r6.0 sec 2.3.1). The spec does not provide an upper @@ -1156,7 +1163,14 @@ void pci_resume_bus(struct pci_bus *bus) static int pci_dev_wait(struct pci_dev *dev, char *reset_type, int timeout) { int delay = 1; - u32 id; + bool retrain = false; + struct pci_dev *bridge; + + if (pci_is_pcie(dev)) { + bridge = pci_upstream_bridge(dev); + if (bridge) + retrain = true; + } /* * After reset, the device should not silently discard config @@ -1170,21 +1184,33 @@ static int pci_dev_wait(struct pci_dev *dev, char *reset_type, int timeout) * Command register instead of Vendor ID so we don't have to * contend with the CRS SV value. */ - pci_read_config_dword(dev, PCI_COMMAND, &id); - while (PCI_POSSIBLE_ERROR(id)) { + for (;;) { + u32 id; + + pci_read_config_dword(dev, PCI_COMMAND, &id); + if (!PCI_POSSIBLE_ERROR(id)) + break; + if (delay > timeout) { pci_warn(dev, "not ready %dms after %s; giving up\n", delay - 1, reset_type); return -ENOTTY; } - if (delay > PCI_RESET_WAIT) + if (delay > PCI_RESET_WAIT) { + if (retrain) { + retrain = false; + if (pcie_failed_link_retrain(bridge)) { + delay = 1; + continue; + } + } pci_info(dev, "not ready %dms after %s; waiting\n", delay - 1, reset_type); + } msleep(delay); delay *= 2; - pci_read_config_dword(dev, PCI_COMMAND, &id); } if (delay > PCI_RESET_WAIT) @@ -2949,13 +2975,13 @@ static const struct dmi_system_id bridge_d3_blacklist[] = { { /* * Downstream device is not accessible after putting a root port - * into D3cold and back into D0 on Elo i2. + * into D3cold and back into D0 on Elo Continental Z2 board */ - .ident = "Elo i2", + .ident = "Elo Continental Z2", .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Elo Touch Solutions"), - DMI_MATCH(DMI_PRODUCT_NAME, "Elo i2"), - DMI_MATCH(DMI_PRODUCT_VERSION, "RevB"), + DMI_MATCH(DMI_BOARD_VENDOR, "Elo Touch Solutions"), + DMI_MATCH(DMI_BOARD_NAME, "Geminilake"), + DMI_MATCH(DMI_BOARD_VERSION, "Continental Z2"), }, }, #endif @@ -4856,6 +4882,79 @@ static int pci_pm_reset(struct pci_dev *dev, bool probe) return pci_dev_wait(dev, "PM D3hot->D0", PCIE_RESET_READY_POLL_MS); } +/** + * pcie_wait_for_link_status - Wait for link status change + * @pdev: Device whose link to wait for. + * @use_lt: Use the LT bit if TRUE, or the DLLLA bit if FALSE. + * @active: Waiting for active or inactive? + * + * Return 0 if successful, or -ETIMEDOUT if status has not changed within + * PCIE_LINK_RETRAIN_TIMEOUT_MS milliseconds. + */ +static int pcie_wait_for_link_status(struct pci_dev *pdev, + bool use_lt, bool active) +{ + u16 lnksta_mask, lnksta_match; + unsigned long end_jiffies; + u16 lnksta; + + lnksta_mask = use_lt ? PCI_EXP_LNKSTA_LT : PCI_EXP_LNKSTA_DLLLA; + lnksta_match = active ? lnksta_mask : 0; + + end_jiffies = jiffies + msecs_to_jiffies(PCIE_LINK_RETRAIN_TIMEOUT_MS); + do { + pcie_capability_read_word(pdev, PCI_EXP_LNKSTA, &lnksta); + if ((lnksta & lnksta_mask) == lnksta_match) + return 0; + msleep(1); + } while (time_before(jiffies, end_jiffies)); + + return -ETIMEDOUT; +} + +/** + * pcie_retrain_link - Request a link retrain and wait for it to complete + * @pdev: Device whose link to retrain. + * @use_lt: Use the LT bit if TRUE, or the DLLLA bit if FALSE, for status. + * + * Retrain completion status is retrieved from the Link Status Register + * according to @use_lt. It is not verified whether the use of the DLLLA + * bit is valid. + * + * Return 0 if successful, or -ETIMEDOUT if training has not completed + * within PCIE_LINK_RETRAIN_TIMEOUT_MS milliseconds. + */ +int pcie_retrain_link(struct pci_dev *pdev, bool use_lt) +{ + int rc; + u16 lnkctl; + + /* + * Ensure the updated LNKCTL parameters are used during link + * training by checking that there is no ongoing link training to + * avoid LTSSM race as recommended in Implementation Note at the + * end of PCIe r6.0.1 sec 7.5.3.7. + */ + rc = pcie_wait_for_link_status(pdev, use_lt, !use_lt); + if (rc) + return rc; + + pcie_capability_read_word(pdev, PCI_EXP_LNKCTL, &lnkctl); + lnkctl |= PCI_EXP_LNKCTL_RL; + pcie_capability_write_word(pdev, PCI_EXP_LNKCTL, lnkctl); + if (pdev->clear_retrain_link) { + /* + * Due to an erratum in some devices the Retrain Link bit + * needs to be cleared again manually to allow the link + * training to succeed. + */ + lnkctl &= ~PCI_EXP_LNKCTL_RL; + pcie_capability_write_word(pdev, PCI_EXP_LNKCTL, lnkctl); + } + + return pcie_wait_for_link_status(pdev, use_lt, !use_lt); +} + /** * pcie_wait_for_link_delay - Wait until link is active or inactive * @pdev: Bridge device @@ -4867,16 +4966,14 @@ static int pci_pm_reset(struct pci_dev *dev, bool probe) static bool pcie_wait_for_link_delay(struct pci_dev *pdev, bool active, int delay) { - int timeout = 1000; - bool ret; - u16 lnk_status; + int rc; /* * Some controllers might not implement link active reporting. In this * case, we wait for 1000 ms + any delay requested by the caller. */ if (!pdev->link_active_reporting) { - msleep(timeout + delay); + msleep(PCIE_LINK_RETRAIN_TIMEOUT_MS + delay); return true; } @@ -4891,20 +4988,21 @@ static bool pcie_wait_for_link_delay(struct pci_dev *pdev, bool active, */ if (active) msleep(20); - for (;;) { - pcie_capability_read_word(pdev, PCI_EXP_LNKSTA, &lnk_status); - ret = !!(lnk_status & PCI_EXP_LNKSTA_DLLLA); - if (ret == active) - break; - if (timeout <= 0) - break; - msleep(10); - timeout -= 10; - } - if (active && ret) + rc = pcie_wait_for_link_status(pdev, false, active); + if (active) { + if (rc) + rc = pcie_failed_link_retrain(pdev); + if (rc) + return false; + msleep(delay); + return true; + } + + if (rc) + return false; - return ret == active; + return true; } /** @@ -5011,11 +5109,9 @@ int pci_bridge_wait_for_secondary_bus(struct pci_dev *dev, char *reset_type) * * However, 100 ms is the minimum and the PCIe spec says the * software must allow at least 1s before it can determine that the - * device that did not respond is a broken device. There is - * evidence that 100 ms is not always enough, for example certain - * Titan Ridge xHCI controller does not always respond to - * configuration requests if we only wait for 100 ms (see - * https://bugzilla.kernel.org/show_bug.cgi?id=203885). + * device that did not respond is a broken device. Also device can + * take longer than that to respond if it indicates so through Request + * Retry Status completions. * * Therefore we wait for 100 ms and check for the device presence * until the timeout expires. @@ -5024,16 +5120,36 @@ int pci_bridge_wait_for_secondary_bus(struct pci_dev *dev, char *reset_type) return 0; if (pcie_get_speed_cap(dev) <= PCIE_SPEED_5_0GT) { + u16 status; + pci_dbg(dev, "waiting %d ms for downstream link\n", delay); msleep(delay); - } else { - pci_dbg(dev, "waiting %d ms for downstream link, after activation\n", - delay); - if (!pcie_wait_for_link_delay(dev, true, delay)) { - /* Did not train, no need to wait any further */ - pci_info(dev, "Data Link Layer Link Active not set in 1000 msec\n"); + + if (!pci_dev_wait(child, reset_type, PCI_RESET_WAIT - delay)) + return 0; + + /* + * If the port supports active link reporting we now check + * whether the link is active and if not bail out early with + * the assumption that the device is not present anymore. + */ + if (!dev->link_active_reporting) return -ENOTTY; - } + + pcie_capability_read_word(dev, PCI_EXP_LNKSTA, &status); + if (!(status & PCI_EXP_LNKSTA_DLLLA)) + return -ENOTTY; + + return pci_dev_wait(child, reset_type, + PCIE_RESET_READY_POLL_MS - PCI_RESET_WAIT); + } + + pci_dbg(dev, "waiting %d ms for downstream link, after activation\n", + delay); + if (!pcie_wait_for_link_delay(dev, true, delay)) { + /* Did not train, no need to wait any further */ + pci_info(dev, "Data Link Layer Link Active not set in 1000 msec\n"); + return -ENOTTY; } return pci_dev_wait(child, reset_type, diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 2475098f65182dd2b5cf4aeb41d209034a1a78ae..a4c3974340576812cabb0a9dbd1517397037fd2e 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -11,6 +11,8 @@ #define PCI_VSEC_ID_INTEL_TBT 0x1234 /* Thunderbolt */ +#define PCIE_LINK_RETRAIN_TIMEOUT_MS 1000 + extern const unsigned char pcie_link_speed[]; extern bool pci_early_dump; @@ -64,13 +66,6 @@ struct pci_cap_saved_state *pci_find_saved_ext_cap(struct pci_dev *dev, #define PCI_PM_D3HOT_WAIT 10 /* msec */ #define PCI_PM_D3COLD_WAIT 100 /* msec */ -/* - * Following exit from Conventional Reset, devices must be ready within 1 sec - * (PCIe r6.0 sec 6.6.1). A D3cold to D0 transition implies a Conventional - * Reset (PCIe r6.0 sec 5.8). - */ -#define PCI_RESET_WAIT 1000 /* msec */ - void pci_update_current_state(struct pci_dev *dev, pci_power_t state); void pci_refresh_power_state(struct pci_dev *dev); int pci_power_up(struct pci_dev *dev); @@ -541,6 +536,7 @@ void pci_acs_init(struct pci_dev *dev); int pci_dev_specific_acs_enabled(struct pci_dev *dev, u16 acs_flags); int pci_dev_specific_enable_acs(struct pci_dev *dev); int pci_dev_specific_disable_acs_redir(struct pci_dev *dev); +bool pcie_failed_link_retrain(struct pci_dev *dev); #else static inline int pci_dev_specific_acs_enabled(struct pci_dev *dev, u16 acs_flags) @@ -555,6 +551,10 @@ static inline int pci_dev_specific_disable_acs_redir(struct pci_dev *dev) { return -ENOTTY; } +static inline bool pcie_failed_link_retrain(struct pci_dev *dev) +{ + return false; +} #endif /* PCI error reporting and recovery */ @@ -563,6 +563,7 @@ pci_ers_result_t pcie_do_recovery(struct pci_dev *dev, pci_ers_result_t (*reset_subordinates)(struct pci_dev *pdev)); bool pcie_wait_for_link(struct pci_dev *pdev, bool active); +int pcie_retrain_link(struct pci_dev *pdev, bool use_lt); #ifdef CONFIG_PCIEASPM void pcie_aspm_init_link_state(struct pci_dev *pdev); void pcie_aspm_exit_link_state(struct pci_dev *pdev); @@ -686,6 +687,8 @@ extern const struct attribute_group aer_stats_attr_group; void pci_aer_clear_fatal_status(struct pci_dev *dev); int pci_aer_clear_status(struct pci_dev *dev); int pci_aer_raw_clear_status(struct pci_dev *dev); +void pci_save_aer_state(struct pci_dev *dev); +void pci_restore_aer_state(struct pci_dev *dev); #else static inline void pci_no_aer(void) { } static inline void pci_aer_init(struct pci_dev *d) { } @@ -693,6 +696,8 @@ static inline void pci_aer_exit(struct pci_dev *d) { } static inline void pci_aer_clear_fatal_status(struct pci_dev *dev) { } static inline int pci_aer_clear_status(struct pci_dev *dev) { return -EINVAL; } static inline int pci_aer_raw_clear_status(struct pci_dev *dev) { return -EINVAL; } +static inline void pci_save_aer_state(struct pci_dev *dev) { } +static inline void pci_restore_aer_state(struct pci_dev *dev) { } #endif #ifdef CONFIG_ACPI diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c index 66d7514ca111b01d9cb6502dbc6bf2e6413bc0e3..3dafba0b5f411e4d635dec91d4b70b3b2b1be735 100644 --- a/drivers/pci/pcie/aspm.c +++ b/drivers/pci/pcie/aspm.c @@ -90,8 +90,6 @@ static const char *policy_str[] = { [POLICY_POWER_SUPERSAVE] = "powersupersave" }; -#define LINK_RETRAIN_TIMEOUT HZ - /* * The L1 PM substate capability is only implemented in function 0 in a * multi function device. @@ -193,36 +191,6 @@ static void pcie_clkpm_cap_init(struct pcie_link_state *link, int blacklist) link->clkpm_disable = blacklist ? 1 : 0; } -static bool pcie_retrain_link(struct pcie_link_state *link) -{ - struct pci_dev *parent = link->pdev; - unsigned long end_jiffies; - u16 reg16; - - pcie_capability_read_word(parent, PCI_EXP_LNKCTL, ®16); - reg16 |= PCI_EXP_LNKCTL_RL; - pcie_capability_write_word(parent, PCI_EXP_LNKCTL, reg16); - if (parent->clear_retrain_link) { - /* - * Due to an erratum in some devices the Retrain Link bit - * needs to be cleared again manually to allow the link - * training to succeed. - */ - reg16 &= ~PCI_EXP_LNKCTL_RL; - pcie_capability_write_word(parent, PCI_EXP_LNKCTL, reg16); - } - - /* Wait for link training end. Break out after waiting for timeout */ - end_jiffies = jiffies + LINK_RETRAIN_TIMEOUT; - do { - pcie_capability_read_word(parent, PCI_EXP_LNKSTA, ®16); - if (!(reg16 & PCI_EXP_LNKSTA_LT)) - break; - msleep(1); - } while (time_before(jiffies, end_jiffies)); - return !(reg16 & PCI_EXP_LNKSTA_LT); -} - /* * pcie_aspm_configure_common_clock: check if the 2 ends of a link * could use common clock. If they are, configure them to use the @@ -289,15 +257,15 @@ static void pcie_aspm_configure_common_clock(struct pcie_link_state *link) reg16 &= ~PCI_EXP_LNKCTL_CCC; pcie_capability_write_word(parent, PCI_EXP_LNKCTL, reg16); - if (pcie_retrain_link(link)) - return; + if (pcie_retrain_link(link->pdev, true)) { - /* Training failed. Restore common clock configurations */ - pci_err(parent, "ASPM: Could not configure common clock\n"); - list_for_each_entry(child, &linkbus->devices, bus_list) - pcie_capability_write_word(child, PCI_EXP_LNKCTL, + /* Training failed. Restore common clock configurations */ + pci_err(parent, "ASPM: Could not configure common clock\n"); + list_for_each_entry(child, &linkbus->devices, bus_list) + pcie_capability_write_word(child, PCI_EXP_LNKCTL, child_reg[PCI_FUNC(child->devfn)]); - pcie_capability_write_word(parent, PCI_EXP_LNKCTL, parent_reg); + pcie_capability_write_word(parent, PCI_EXP_LNKCTL, parent_reg); + } } /* Convert L0s latency encoding to ns */ @@ -337,7 +305,7 @@ static u32 calc_l1_acceptable(u32 encoding) } /* Convert L1SS T_pwr encoding to usec */ -static u32 calc_l1ss_pwron(struct pci_dev *pdev, u32 scale, u32 val) +static u32 calc_l12_pwron(struct pci_dev *pdev, u32 scale, u32 val) { switch (scale) { case 0: @@ -471,7 +439,7 @@ static void pci_clear_and_set_dword(struct pci_dev *pdev, int pos, } /* Calculate L1.2 PM substate timing parameters */ -static void aspm_calc_l1ss_info(struct pcie_link_state *link, +static void aspm_calc_l12_info(struct pcie_link_state *link, u32 parent_l1ss_cap, u32 child_l1ss_cap) { struct pci_dev *child = link->downstream, *parent = link->pdev; @@ -481,9 +449,6 @@ static void aspm_calc_l1ss_info(struct pcie_link_state *link, u32 pctl1, pctl2, cctl1, cctl2; u32 pl1_2_enables, cl1_2_enables; - if (!(link->aspm_support & ASPM_STATE_L1_2_MASK)) - return; - /* Choose the greater of the two Port Common_Mode_Restore_Times */ val1 = (parent_l1ss_cap & PCI_L1SS_CAP_CM_RESTORE_TIME) >> 8; val2 = (child_l1ss_cap & PCI_L1SS_CAP_CM_RESTORE_TIME) >> 8; @@ -495,13 +460,13 @@ static void aspm_calc_l1ss_info(struct pcie_link_state *link, val2 = (child_l1ss_cap & PCI_L1SS_CAP_P_PWR_ON_VALUE) >> 19; scale2 = (child_l1ss_cap & PCI_L1SS_CAP_P_PWR_ON_SCALE) >> 16; - if (calc_l1ss_pwron(parent, scale1, val1) > - calc_l1ss_pwron(child, scale2, val2)) { + if (calc_l12_pwron(parent, scale1, val1) > + calc_l12_pwron(child, scale2, val2)) { ctl2 |= scale1 | (val1 << 3); - t_power_on = calc_l1ss_pwron(parent, scale1, val1); + t_power_on = calc_l12_pwron(parent, scale1, val1); } else { ctl2 |= scale2 | (val2 << 3); - t_power_on = calc_l1ss_pwron(child, scale2, val2); + t_power_on = calc_l12_pwron(child, scale2, val2); } /* @@ -616,8 +581,8 @@ static void aspm_l1ss_init(struct pcie_link_state *link) if (parent_l1ss_ctl1 & child_l1ss_ctl1 & PCI_L1SS_CTL1_PCIPM_L1_2) link->aspm_enabled |= ASPM_STATE_L1_2_PCIPM; - if (link->aspm_support & ASPM_STATE_L1SS) - aspm_calc_l1ss_info(link, parent_l1ss_cap, child_l1ss_cap); + if (link->aspm_support & ASPM_STATE_L1_2_MASK) + aspm_calc_l12_info(link, parent_l1ss_cap, child_l1ss_cap); } static void pcie_aspm_cap_init(struct pcie_link_state *link, int blacklist) @@ -1010,21 +975,24 @@ void pcie_aspm_exit_link_state(struct pci_dev *pdev) down_read(&pci_bus_sem); mutex_lock(&aspm_lock); - /* - * All PCIe functions are in one slot, remove one function will remove - * the whole slot, so just wait until we are the last function left. - */ - if (!list_empty(&parent->subordinate->devices)) - goto out; link = parent->link_state; root = link->root; parent_link = link->parent; - /* All functions are removed, so just disable ASPM for the link */ + /* + * link->downstream is a pointer to the pci_dev of function 0. If + * we remove that function, the pci_dev is about to be deallocated, + * so we can't use link->downstream again. Free the link state to + * avoid this. + * + * If we're removing a non-0 function, it's possible we could + * retain the link state, but PCIe r6.0, sec 7.5.3.7, recommends + * programming the same ASPM Control value for all functions of + * multi-function devices, so disable ASPM for all of them. + */ pcie_config_aspm_link(link, 0); list_del(&link->sibling); - /* Clock PM is for endpoint device */ free_link_state(link); /* Recheck latencies and configure upstream links */ @@ -1032,7 +1000,7 @@ void pcie_aspm_exit_link_state(struct pci_dev *pdev) pcie_update_aspm_capable(root); pcie_config_aspm_path(parent_link); } -out: + mutex_unlock(&aspm_lock); up_read(&pci_bus_sem); } @@ -1095,8 +1063,7 @@ static int __pci_disable_link_state(struct pci_dev *pdev, int state, bool sem) if (state & PCIE_LINK_STATE_L0S) link->aspm_disable |= ASPM_STATE_L0S; if (state & PCIE_LINK_STATE_L1) - /* L1 PM substates require L1 */ - link->aspm_disable |= ASPM_STATE_L1 | ASPM_STATE_L1SS; + link->aspm_disable |= ASPM_STATE_L1; if (state & PCIE_LINK_STATE_L1_1) link->aspm_disable |= ASPM_STATE_L1_1; if (state & PCIE_LINK_STATE_L1_2) @@ -1171,16 +1138,16 @@ int pci_enable_link_state(struct pci_dev *pdev, int state) if (state & PCIE_LINK_STATE_L0S) link->aspm_default |= ASPM_STATE_L0S; if (state & PCIE_LINK_STATE_L1) - /* L1 PM substates require L1 */ - link->aspm_default |= ASPM_STATE_L1 | ASPM_STATE_L1SS; + link->aspm_default |= ASPM_STATE_L1; + /* L1 PM substates require L1 */ if (state & PCIE_LINK_STATE_L1_1) - link->aspm_default |= ASPM_STATE_L1_1; + link->aspm_default |= ASPM_STATE_L1_1 | ASPM_STATE_L1; if (state & PCIE_LINK_STATE_L1_2) - link->aspm_default |= ASPM_STATE_L1_2; + link->aspm_default |= ASPM_STATE_L1_2 | ASPM_STATE_L1; if (state & PCIE_LINK_STATE_L1_1_PCIPM) - link->aspm_default |= ASPM_STATE_L1_1_PCIPM; + link->aspm_default |= ASPM_STATE_L1_1_PCIPM | ASPM_STATE_L1; if (state & PCIE_LINK_STATE_L1_2_PCIPM) - link->aspm_default |= ASPM_STATE_L1_2_PCIPM; + link->aspm_default |= ASPM_STATE_L1_2_PCIPM | ASPM_STATE_L1; pcie_config_aspm_link(link, policy_to_aspm_state(link)); link->clkpm_default = (state & PCIE_LINK_STATE_CLKPM) ? 1 : 0; diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 0b2826c4a832d09d9d13c34f9d868fd6d5a2f511..8bac3ce02609c475037a6376780c6ca78dae332e 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -820,7 +820,6 @@ static void pci_set_bus_speed(struct pci_bus *bus) pcie_capability_read_dword(bridge, PCI_EXP_LNKCAP, &linkcap); bus->max_bus_speed = pcie_link_speed[linkcap & PCI_EXP_LNKCAP_SLS]; - bridge->link_active_reporting = !!(linkcap & PCI_EXP_LNKCAP_DLLLARC); pcie_capability_read_word(bridge, PCI_EXP_LNKSTA, &linksta); pcie_update_link_speed(bus, linksta); @@ -997,8 +996,10 @@ static int pci_register_host_bridge(struct pci_host_bridge *bridge) resource_list_for_each_entry_safe(window, n, &resources) { offset = window->offset; res = window->res; - if (!res->flags && !res->start && !res->end) + if (!res->flags && !res->start && !res->end) { + release_resource(res); continue; + } list_move_tail(&window->node, &bridge->windows); @@ -1527,6 +1528,7 @@ void set_pcie_port_type(struct pci_dev *pdev) { int pos; u16 reg16; + u32 reg32; int type; struct pci_dev *parent; @@ -1540,6 +1542,10 @@ void set_pcie_port_type(struct pci_dev *pdev) pci_read_config_dword(pdev, pos + PCI_EXP_DEVCAP, &pdev->devcap); pdev->pcie_mpss = FIELD_GET(PCI_EXP_DEVCAP_PAYLOAD, pdev->devcap); + pcie_capability_read_dword(pdev, PCI_EXP_LNKCAP, ®32); + if (reg32 & PCI_EXP_LNKCAP_DLLLARC) + pdev->link_active_reporting = 1; + parent = pci_upstream_bridge(pdev); if (!parent) return; @@ -2546,6 +2552,8 @@ void pci_device_add(struct pci_dev *dev, struct pci_bus *bus) dma_set_max_seg_size(&dev->dev, 65536); dma_set_seg_boundary(&dev->dev, 0xffffffff); + pcie_failed_link_retrain(dev); + /* Fix up broken headers */ pci_fixup_device(pci_fixup_header, dev); diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index c525867760bf819c0af9ccf601844b2c37d0ca49..321156ca273d5747ed1a72e28b85233ba3fcd368 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -33,6 +33,99 @@ #include #include "pci.h" +/* + * Retrain the link of a downstream PCIe port by hand if necessary. + * + * This is needed at least where a downstream port of the ASMedia ASM2824 + * Gen 3 switch is wired to the upstream port of the Pericom PI7C9X2G304 + * Gen 2 switch, and observed with the Delock Riser Card PCI Express x1 > + * 2 x PCIe x1 device, P/N 41433, plugged into the SiFive HiFive Unmatched + * board. + * + * In such a configuration the switches are supposed to negotiate the link + * speed of preferably 5.0GT/s, falling back to 2.5GT/s. However the link + * continues switching between the two speeds indefinitely and the data + * link layer never reaches the active state, with link training reported + * repeatedly active ~84% of the time. Forcing the target link speed to + * 2.5GT/s with the upstream ASM2824 device makes the two switches talk to + * each other correctly however. And more interestingly retraining with a + * higher target link speed afterwards lets the two successfully negotiate + * 5.0GT/s. + * + * With the ASM2824 we can rely on the otherwise optional Data Link Layer + * Link Active status bit and in the failed link training scenario it will + * be off along with the Link Bandwidth Management Status indicating that + * hardware has changed the link speed or width in an attempt to correct + * unreliable link operation. For a port that has been left unconnected + * both bits will be clear. So use this information to detect the problem + * rather than polling the Link Training bit and watching out for flips or + * at least the active status. + * + * Since the exact nature of the problem isn't known and in principle this + * could trigger where an ASM2824 device is downstream rather upstream, + * apply this erratum workaround to any downstream ports as long as they + * support Link Active reporting and have the Link Control 2 register. + * Restrict the speed to 2.5GT/s then with the Target Link Speed field, + * request a retrain and wait 200ms for the data link to go up. + * + * If this turns out successful and we know by the Vendor:Device ID it is + * safe to do so, then lift the restriction, letting the devices negotiate + * a higher speed. Also check for a similar 2.5GT/s speed restriction the + * firmware may have already arranged and lift it with ports that already + * report their data link being up. + * + * Return TRUE if the link has been successfully retrained, otherwise FALSE. + */ +bool pcie_failed_link_retrain(struct pci_dev *dev) +{ + static const struct pci_device_id ids[] = { + { PCI_VDEVICE(ASMEDIA, 0x2824) }, /* ASMedia ASM2824 */ + {} + }; + u16 lnksta, lnkctl2; + + if (!pci_is_pcie(dev) || !pcie_downstream_port(dev) || + !pcie_cap_has_lnkctl2(dev) || !dev->link_active_reporting) + return false; + + pcie_capability_read_word(dev, PCI_EXP_LNKCTL2, &lnkctl2); + pcie_capability_read_word(dev, PCI_EXP_LNKSTA, &lnksta); + if ((lnksta & (PCI_EXP_LNKSTA_LBMS | PCI_EXP_LNKSTA_DLLLA)) == + PCI_EXP_LNKSTA_LBMS) { + pci_info(dev, "broken device, retraining non-functional downstream link at 2.5GT/s\n"); + + lnkctl2 &= ~PCI_EXP_LNKCTL2_TLS; + lnkctl2 |= PCI_EXP_LNKCTL2_TLS_2_5GT; + pcie_capability_write_word(dev, PCI_EXP_LNKCTL2, lnkctl2); + + if (pcie_retrain_link(dev, false)) { + pci_info(dev, "retraining failed\n"); + return false; + } + + pcie_capability_read_word(dev, PCI_EXP_LNKSTA, &lnksta); + } + + if ((lnksta & PCI_EXP_LNKSTA_DLLLA) && + (lnkctl2 & PCI_EXP_LNKCTL2_TLS) == PCI_EXP_LNKCTL2_TLS_2_5GT && + pci_match_id(ids, dev)) { + u32 lnkcap; + + pci_info(dev, "removing 2.5GT/s downstream link speed restriction\n"); + pcie_capability_read_dword(dev, PCI_EXP_LNKCAP, &lnkcap); + lnkctl2 &= ~PCI_EXP_LNKCTL2_TLS; + lnkctl2 |= lnkcap & PCI_EXP_LNKCAP_SLS; + pcie_capability_write_word(dev, PCI_EXP_LNKCTL2, lnkctl2); + + if (pcie_retrain_link(dev, false)) { + pci_info(dev, "retraining failed\n"); + return false; + } + } + + return true; +} + static ktime_t fixup_debug_start(struct pci_dev *dev, void (*fn)(struct pci_dev *dev)) { @@ -2420,9 +2513,9 @@ static void quirk_enable_clear_retrain_link(struct pci_dev *dev) dev->clear_retrain_link = 1; pci_info(dev, "Enable PCIe Retrain Link quirk\n"); } -DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_PERICOM, 0xe110, quirk_enable_clear_retrain_link); -DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_PERICOM, 0xe111, quirk_enable_clear_retrain_link); -DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_PERICOM, 0xe130, quirk_enable_clear_retrain_link); +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_PERICOM, 0xe110, quirk_enable_clear_retrain_link); +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_PERICOM, 0xe111, quirk_enable_clear_retrain_link); +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_PERICOM, 0xe130, quirk_enable_clear_retrain_link); static void fixup_rev1_53c810(struct pci_dev *dev) { @@ -3993,10 +4086,11 @@ static int nvme_disable_and_flr(struct pci_dev *dev, bool probe) } /* - * Intel DC P3700 NVMe controller will timeout waiting for ready status - * to change after NVMe enable if the driver starts interacting with the - * device too soon after FLR. A 250ms delay after FLR has heuristically - * proven to produce reliably working results for device assignment cases. + * Some NVMe controllers such as Intel DC P3700 and Solidigm P44 Pro will + * timeout waiting for ready status to change after NVMe enable if the driver + * starts interacting with the device too soon after FLR. A 250ms delay after + * FLR has heuristically proven to produce reliably working results for device + * assignment cases. */ static int delay_250ms_after_flr(struct pci_dev *dev, bool probe) { @@ -4083,6 +4177,7 @@ static const struct pci_dev_reset_methods pci_dev_reset_methods[] = { { PCI_VENDOR_ID_SAMSUNG, 0xa804, nvme_disable_and_flr }, { PCI_VENDOR_ID_INTEL, 0x0953, delay_250ms_after_flr }, { PCI_VENDOR_ID_INTEL, 0x0a54, delay_250ms_after_flr }, + { PCI_VENDOR_ID_SOLIDIGM, 0xf1ac, delay_250ms_after_flr }, { PCI_VENDOR_ID_CHELSIO, PCI_ANY_ID, reset_chelsio_generic_dev }, { PCI_VENDOR_ID_HUAWEI, PCI_DEVICE_ID_HINIC_VF, @@ -4174,6 +4269,8 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL_EXT, 0x9220, /* https://bugzilla.kernel.org/show_bug.cgi?id=42679#c49 */ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL_EXT, 0x9230, quirk_dma_func1_alias); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL_EXT, 0x9235, + quirk_dma_func1_alias); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TTI, 0x0642, quirk_dma_func1_alias); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TTI, 0x0645, diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig index 44c16508ef14fcb7e45b1c894428efc1738cc31c..e72419d7e72e5c5a53909f05d74a078a12d069ac 100644 --- a/drivers/pcmcia/Kconfig +++ b/drivers/pcmcia/Kconfig @@ -5,7 +5,6 @@ menuconfig PCCARD tristate "PCCard (PCMCIA/CardBus) support" - depends on !UML help Say Y here if you want to attach PCMCIA- or PC-cards to your Linux computer. These are credit-card size devices such as network cards, @@ -113,7 +112,7 @@ config YENTA_TOSHIBA config PD6729 tristate "Cirrus PD6729 compatible bridge support" - depends on PCMCIA && PCI + depends on PCMCIA && PCI && HAS_IOPORT select PCCARD_NONSTATIC help This provides support for the Cirrus PD6729 PCI-to-PCMCIA bridge @@ -121,7 +120,7 @@ config PD6729 config I82092 tristate "i82092 compatible bridge support" - depends on PCMCIA && PCI + depends on PCMCIA && PCI && HAS_IOPORT select PCCARD_NONSTATIC help This provides support for the Intel I82092AA PCI-to-PCMCIA bridge device, diff --git a/drivers/pcmcia/rsrc_nonstatic.c b/drivers/pcmcia/rsrc_nonstatic.c index 471e0c5815f390fb374f6295cb6ce1cd0a679b08..bf9d070a44966d0a4206a702d94038e52c45b02a 100644 --- a/drivers/pcmcia/rsrc_nonstatic.c +++ b/drivers/pcmcia/rsrc_nonstatic.c @@ -1053,6 +1053,8 @@ static void nonstatic_release_resource_db(struct pcmcia_socket *s) q = p->next; kfree(p); } + + kfree(data); } diff --git a/drivers/perf/Kconfig b/drivers/perf/Kconfig index 711f824000864576b34a364a50bb184631ee6b7a..f4572a5cca72bc5bed907cb94ef3516cf7249f40 100644 --- a/drivers/perf/Kconfig +++ b/drivers/perf/Kconfig @@ -127,6 +127,14 @@ config FSL_IMX8_DDR_PMU can give information about memory throughput and other related events. +config FSL_IMX9_DDR_PMU + tristate "Freescale i.MX9 DDR perf monitor" + depends on ARCH_MXC + help + Provides support for the DDR performance monitor in i.MX9, which + can give information about memory throughput and other related + events. + config QCOM_L2_PMU bool "Qualcomm Technologies L2-cache PMU" depends on ARCH_QCOM && ARM64 && ACPI @@ -213,4 +221,17 @@ source "drivers/perf/arm_cspmu/Kconfig" source "drivers/perf/amlogic/Kconfig" +config CXL_PMU + tristate "CXL Performance Monitoring Unit" + depends on CXL_BUS + help + Support performance monitoring as defined in CXL rev 3.0 + section 13.2: Performance Monitoring. CXL components may have + one or more CXL Performance Monitoring Units (CPMUs). + + Say 'y/m' to enable a driver that will attach to performance + monitoring units and provide standard perf based interfaces. + + If unsure say 'm'. + endmenu diff --git a/drivers/perf/Makefile b/drivers/perf/Makefile index dabc859540ce983666c7da6bf44897496b13ca22..16b3ec4db916d0bcb5f3895a82c7d9b1a77e18a2 100644 --- a/drivers/perf/Makefile +++ b/drivers/perf/Makefile @@ -8,6 +8,7 @@ obj-$(CONFIG_ARM_PMU_ACPI) += arm_pmu_acpi.o obj-$(CONFIG_ARM_PMUV3) += arm_pmuv3.o obj-$(CONFIG_ARM_SMMU_V3_PMU) += arm_smmuv3_pmu.o obj-$(CONFIG_FSL_IMX8_DDR_PMU) += fsl_imx8_ddr_perf.o +obj-$(CONFIG_FSL_IMX9_DDR_PMU) += fsl_imx9_ddr_perf.o obj-$(CONFIG_HISI_PMU) += hisilicon/ obj-$(CONFIG_QCOM_L2_PMU) += qcom_l2_pmu.o obj-$(CONFIG_QCOM_L3_PMU) += qcom_l3_pmu.o @@ -24,3 +25,4 @@ obj-$(CONFIG_APPLE_M1_CPU_PMU) += apple_m1_cpu_pmu.o obj-$(CONFIG_ALIBABA_UNCORE_DRW_PMU) += alibaba_uncore_drw_pmu.o obj-$(CONFIG_ARM_CORESIGHT_PMU_ARCH_SYSTEM_PMU) += arm_cspmu/ obj-$(CONFIG_MESON_DDR_PMU) += amlogic/ +obj-$(CONFIG_CXL_PMU) += cxl_pmu.o diff --git a/drivers/perf/apple_m1_cpu_pmu.c b/drivers/perf/apple_m1_cpu_pmu.c index 8574c6e58c83a66f64a8440a35978cc3a1091115..cd2de44b61b91fddf172aef24efb602baf1486d5 100644 --- a/drivers/perf/apple_m1_cpu_pmu.c +++ b/drivers/perf/apple_m1_cpu_pmu.c @@ -493,6 +493,17 @@ static int m1_pmu_map_event(struct perf_event *event) return armpmu_map_event(event, &m1_pmu_perf_map, NULL, M1_PMU_CFG_EVENT); } +static int m2_pmu_map_event(struct perf_event *event) +{ + /* + * Same deal as the above, except that M2 has 64bit counters. + * Which, as far as we're concerned, actually means 63 bits. + * Yes, this is getting awkward. + */ + event->hw.flags |= ARMPMU_EVT_63BIT; + return armpmu_map_event(event, &m1_pmu_perf_map, NULL, M1_PMU_CFG_EVENT); +} + static void m1_pmu_reset(void *info) { int i; @@ -525,7 +536,7 @@ static int m1_pmu_set_event_filter(struct hw_perf_event *event, return 0; } -static int m1_pmu_init(struct arm_pmu *cpu_pmu) +static int m1_pmu_init(struct arm_pmu *cpu_pmu, u32 flags) { cpu_pmu->handle_irq = m1_pmu_handle_irq; cpu_pmu->enable = m1_pmu_enable_event; @@ -536,7 +547,14 @@ static int m1_pmu_init(struct arm_pmu *cpu_pmu) cpu_pmu->clear_event_idx = m1_pmu_clear_event_idx; cpu_pmu->start = m1_pmu_start; cpu_pmu->stop = m1_pmu_stop; - cpu_pmu->map_event = m1_pmu_map_event; + + if (flags & ARMPMU_EVT_47BIT) + cpu_pmu->map_event = m1_pmu_map_event; + else if (flags & ARMPMU_EVT_63BIT) + cpu_pmu->map_event = m2_pmu_map_event; + else + return WARN_ON(-EINVAL); + cpu_pmu->reset = m1_pmu_reset; cpu_pmu->set_event_filter = m1_pmu_set_event_filter; @@ -550,25 +568,25 @@ static int m1_pmu_init(struct arm_pmu *cpu_pmu) static int m1_pmu_ice_init(struct arm_pmu *cpu_pmu) { cpu_pmu->name = "apple_icestorm_pmu"; - return m1_pmu_init(cpu_pmu); + return m1_pmu_init(cpu_pmu, ARMPMU_EVT_47BIT); } static int m1_pmu_fire_init(struct arm_pmu *cpu_pmu) { cpu_pmu->name = "apple_firestorm_pmu"; - return m1_pmu_init(cpu_pmu); + return m1_pmu_init(cpu_pmu, ARMPMU_EVT_47BIT); } static int m2_pmu_avalanche_init(struct arm_pmu *cpu_pmu) { cpu_pmu->name = "apple_avalanche_pmu"; - return m1_pmu_init(cpu_pmu); + return m1_pmu_init(cpu_pmu, ARMPMU_EVT_63BIT); } static int m2_pmu_blizzard_init(struct arm_pmu *cpu_pmu) { cpu_pmu->name = "apple_blizzard_pmu"; - return m1_pmu_init(cpu_pmu); + return m1_pmu_init(cpu_pmu, ARMPMU_EVT_63BIT); } static const struct of_device_id m1_pmu_of_device_ids[] = { diff --git a/drivers/perf/arm-cci.c b/drivers/perf/arm-cci.c index 03b1309875aeaf3921006c04a872c6d2280d3ab2..998259f1d973ad9bb074e573bf6081036b0b498e 100644 --- a/drivers/perf/arm-cci.c +++ b/drivers/perf/arm-cci.c @@ -645,7 +645,7 @@ static void cci_pmu_sync_counters(struct cci_pmu *cci_pmu) struct cci_pmu_hw_events *cci_hw = &cci_pmu->hw_events; DECLARE_BITMAP(mask, HW_CNTRS_MAX); - bitmap_zero(mask, cci_pmu->num_cntrs); + bitmap_zero(mask, HW_CNTRS_MAX); for_each_set_bit(i, cci_pmu->hw_events.used_mask, cci_pmu->num_cntrs) { struct perf_event *event = cci_hw->events[i]; @@ -656,7 +656,7 @@ static void cci_pmu_sync_counters(struct cci_pmu *cci_pmu) if (event->hw.state & PERF_HES_STOPPED) continue; if (event->hw.state & PERF_HES_ARCH) { - set_bit(i, mask); + __set_bit(i, mask); event->hw.state &= ~PERF_HES_ARCH; } } diff --git a/drivers/perf/arm-cmn.c b/drivers/perf/arm-cmn.c index 47d359f729579b64d2a937b203ec52f12020880a..b8c15878bc86dacd9fa27285243d653cc94e9c25 100644 --- a/drivers/perf/arm-cmn.c +++ b/drivers/perf/arm-cmn.c @@ -44,8 +44,11 @@ #define CMN_MAX_DTMS (CMN_MAX_XPS + (CMN_MAX_DIMENSION - 1) * 4) /* The CFG node has various info besides the discovery tree */ -#define CMN_CFGM_PERIPH_ID_2 0x0010 -#define CMN_CFGM_PID2_REVISION GENMASK(7, 4) +#define CMN_CFGM_PERIPH_ID_01 0x0008 +#define CMN_CFGM_PID0_PART_0 GENMASK_ULL(7, 0) +#define CMN_CFGM_PID1_PART_1 GENMASK_ULL(35, 32) +#define CMN_CFGM_PERIPH_ID_23 0x0010 +#define CMN_CFGM_PID2_REVISION GENMASK_ULL(7, 4) #define CMN_CFGM_INFO_GLOBAL 0x900 #define CMN_INFO_MULTIPLE_DTM_EN BIT_ULL(63) @@ -186,6 +189,7 @@ #define CMN_WP_DOWN 2 +/* Internal values for encoding event support */ enum cmn_model { CMN600 = 1, CMN650 = 2, @@ -197,26 +201,34 @@ enum cmn_model { CMN_650ON = CMN650 | CMN700, }; +/* Actual part numbers and revision IDs defined by the hardware */ +enum cmn_part { + PART_CMN600 = 0x434, + PART_CMN650 = 0x436, + PART_CMN700 = 0x43c, + PART_CI700 = 0x43a, +}; + /* CMN-600 r0px shouldn't exist in silicon, thankfully */ enum cmn_revision { - CMN600_R1P0, - CMN600_R1P1, - CMN600_R1P2, - CMN600_R1P3, - CMN600_R2P0, - CMN600_R3P0, - CMN600_R3P1, - CMN650_R0P0 = 0, - CMN650_R1P0, - CMN650_R1P1, - CMN650_R2P0, - CMN650_R1P2, - CMN700_R0P0 = 0, - CMN700_R1P0, - CMN700_R2P0, - CI700_R0P0 = 0, - CI700_R1P0, - CI700_R2P0, + REV_CMN600_R1P0, + REV_CMN600_R1P1, + REV_CMN600_R1P2, + REV_CMN600_R1P3, + REV_CMN600_R2P0, + REV_CMN600_R3P0, + REV_CMN600_R3P1, + REV_CMN650_R0P0 = 0, + REV_CMN650_R1P0, + REV_CMN650_R1P1, + REV_CMN650_R2P0, + REV_CMN650_R1P2, + REV_CMN700_R0P0 = 0, + REV_CMN700_R1P0, + REV_CMN700_R2P0, + REV_CI700_R0P0 = 0, + REV_CI700_R1P0, + REV_CI700_R2P0, }; enum cmn_node_type { @@ -306,7 +318,7 @@ struct arm_cmn { unsigned int state; enum cmn_revision rev; - enum cmn_model model; + enum cmn_part part; u8 mesh_x; u8 mesh_y; u16 num_xps; @@ -394,19 +406,35 @@ static struct arm_cmn_node *arm_cmn_node(const struct arm_cmn *cmn, return NULL; } +static enum cmn_model arm_cmn_model(const struct arm_cmn *cmn) +{ + switch (cmn->part) { + case PART_CMN600: + return CMN600; + case PART_CMN650: + return CMN650; + case PART_CMN700: + return CMN700; + case PART_CI700: + return CI700; + default: + return 0; + }; +} + static u32 arm_cmn_device_connect_info(const struct arm_cmn *cmn, const struct arm_cmn_node *xp, int port) { int offset = CMN_MXP__CONNECT_INFO(port); if (port >= 2) { - if (cmn->model & (CMN600 | CMN650)) + if (cmn->part == PART_CMN600 || cmn->part == PART_CMN650) return 0; /* * CI-700 may have extra ports, but still has the * mesh_port_connect_info registers in the way. */ - if (cmn->model == CI700) + if (cmn->part == PART_CI700) offset += CI700_CONNECT_INFO_P2_5_OFFSET; } @@ -640,7 +668,7 @@ static umode_t arm_cmn_event_attr_is_visible(struct kobject *kobj, eattr = container_of(attr, typeof(*eattr), attr.attr); - if (!(eattr->model & cmn->model)) + if (!(eattr->model & arm_cmn_model(cmn))) return 0; type = eattr->type; @@ -658,7 +686,7 @@ static umode_t arm_cmn_event_attr_is_visible(struct kobject *kobj, if ((intf & 4) && !(cmn->ports_used & BIT(intf & 3))) return 0; - if (chan == 4 && cmn->model == CMN600) + if (chan == 4 && cmn->part == PART_CMN600) return 0; if ((chan == 5 && cmn->rsp_vc_num < 2) || @@ -669,19 +697,19 @@ static umode_t arm_cmn_event_attr_is_visible(struct kobject *kobj, } /* Revision-specific differences */ - if (cmn->model == CMN600) { - if (cmn->rev < CMN600_R1P3) { + if (cmn->part == PART_CMN600) { + if (cmn->rev < REV_CMN600_R1P3) { if (type == CMN_TYPE_CXRA && eventid > 0x10) return 0; } - if (cmn->rev < CMN600_R1P2) { + if (cmn->rev < REV_CMN600_R1P2) { if (type == CMN_TYPE_HNF && eventid == 0x1b) return 0; if (type == CMN_TYPE_CXRA || type == CMN_TYPE_CXHA) return 0; } - } else if (cmn->model == CMN650) { - if (cmn->rev < CMN650_R2P0 || cmn->rev == CMN650_R1P2) { + } else if (cmn->part == PART_CMN650) { + if (cmn->rev < REV_CMN650_R2P0 || cmn->rev == REV_CMN650_R1P2) { if (type == CMN_TYPE_HNF && eventid > 0x22) return 0; if (type == CMN_TYPE_SBSX && eventid == 0x17) @@ -689,8 +717,8 @@ static umode_t arm_cmn_event_attr_is_visible(struct kobject *kobj, if (type == CMN_TYPE_RNI && eventid > 0x10) return 0; } - } else if (cmn->model == CMN700) { - if (cmn->rev < CMN700_R2P0) { + } else if (cmn->part == PART_CMN700) { + if (cmn->rev < REV_CMN700_R2P0) { if (type == CMN_TYPE_HNF && eventid > 0x2c) return 0; if (type == CMN_TYPE_CCHA && eventid > 0x74) @@ -698,7 +726,7 @@ static umode_t arm_cmn_event_attr_is_visible(struct kobject *kobj, if (type == CMN_TYPE_CCLA && eventid > 0x27) return 0; } - if (cmn->rev < CMN700_R1P0) { + if (cmn->rev < REV_CMN700_R1P0) { if (type == CMN_TYPE_HNF && eventid > 0x2b) return 0; } @@ -1171,19 +1199,31 @@ static ssize_t arm_cmn_cpumask_show(struct device *dev, static struct device_attribute arm_cmn_cpumask_attr = __ATTR(cpumask, 0444, arm_cmn_cpumask_show, NULL); -static struct attribute *arm_cmn_cpumask_attrs[] = { +static ssize_t arm_cmn_identifier_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct arm_cmn *cmn = to_cmn(dev_get_drvdata(dev)); + + return sysfs_emit(buf, "%03x%02x\n", cmn->part, cmn->rev); +} + +static struct device_attribute arm_cmn_identifier_attr = + __ATTR(identifier, 0444, arm_cmn_identifier_show, NULL); + +static struct attribute *arm_cmn_other_attrs[] = { &arm_cmn_cpumask_attr.attr, + &arm_cmn_identifier_attr.attr, NULL, }; -static const struct attribute_group arm_cmn_cpumask_attr_group = { - .attrs = arm_cmn_cpumask_attrs, +static const struct attribute_group arm_cmn_other_attrs_group = { + .attrs = arm_cmn_other_attrs, }; static const struct attribute_group *arm_cmn_attr_groups[] = { &arm_cmn_event_attrs_group, &arm_cmn_format_attrs_group, - &arm_cmn_cpumask_attr_group, + &arm_cmn_other_attrs_group, NULL }; @@ -1200,7 +1240,7 @@ static u32 arm_cmn_wp_config(struct perf_event *event) u32 grp = CMN_EVENT_WP_GRP(event); u32 exc = CMN_EVENT_WP_EXCLUSIVE(event); u32 combine = CMN_EVENT_WP_COMBINE(event); - bool is_cmn600 = to_cmn(event->pmu)->model == CMN600; + bool is_cmn600 = to_cmn(event->pmu)->part == PART_CMN600; config = FIELD_PREP(CMN_DTM_WPn_CONFIG_WP_DEV_SEL, dev) | FIELD_PREP(CMN_DTM_WPn_CONFIG_WP_CHN_SEL, chn) | @@ -1520,14 +1560,14 @@ static int arm_cmn_validate_group(struct arm_cmn *cmn, struct perf_event *event) return ret; } -static enum cmn_filter_select arm_cmn_filter_sel(enum cmn_model model, +static enum cmn_filter_select arm_cmn_filter_sel(const struct arm_cmn *cmn, enum cmn_node_type type, unsigned int eventid) { struct arm_cmn_event_attr *e; - int i; + enum cmn_model model = arm_cmn_model(cmn); - for (i = 0; i < ARRAY_SIZE(arm_cmn_event_attrs) - 1; i++) { + for (int i = 0; i < ARRAY_SIZE(arm_cmn_event_attrs) - 1; i++) { e = container_of(arm_cmn_event_attrs[i], typeof(*e), attr.attr); if (e->model & model && e->type == type && e->eventid == eventid) return e->fsel; @@ -1570,12 +1610,12 @@ static int arm_cmn_event_init(struct perf_event *event) /* ...but the DTM may depend on which port we're watching */ if (cmn->multi_dtm) hw->dtm_offset = CMN_EVENT_WP_DEV_SEL(event) / 2; - } else if (type == CMN_TYPE_XP && cmn->model == CMN700) { + } else if (type == CMN_TYPE_XP && cmn->part == PART_CMN700) { hw->wide_sel = true; } /* This is sufficiently annoying to recalculate, so cache it */ - hw->filter_sel = arm_cmn_filter_sel(cmn->model, type, eventid); + hw->filter_sel = arm_cmn_filter_sel(cmn, type, eventid); bynodeid = CMN_EVENT_BYNODEID(event); nodeid = CMN_EVENT_NODEID(event); @@ -1899,9 +1939,10 @@ static int arm_cmn_init_dtc(struct arm_cmn *cmn, struct arm_cmn_node *dn, int id if (dtc->irq < 0) return dtc->irq; - writel_relaxed(0, dtc->base + CMN_DT_PMCR); + writel_relaxed(CMN_DT_DTC_CTL_DT_EN, dtc->base + CMN_DT_DTC_CTL); + writel_relaxed(CMN_DT_PMCR_PMU_EN | CMN_DT_PMCR_OVFL_INTR_EN, dtc->base + CMN_DT_PMCR); + writeq_relaxed(0, dtc->base + CMN_DT_PMCCNTR); writel_relaxed(0x1ff, dtc->base + CMN_DT_PMOVSR_CLR); - writel_relaxed(CMN_DT_PMCR_OVFL_INTR_EN, dtc->base + CMN_DT_PMCR); return 0; } @@ -1961,7 +2002,7 @@ static int arm_cmn_init_dtcs(struct arm_cmn *cmn) dn->type = CMN_TYPE_CCLA; } - writel_relaxed(CMN_DT_DTC_CTL_DT_EN, cmn->dtc[0].base + CMN_DT_DTC_CTL); + arm_cmn_set_state(cmn, CMN_STATE_DISABLED); return 0; } @@ -2006,6 +2047,7 @@ static int arm_cmn_discover(struct arm_cmn *cmn, unsigned int rgn_offset) void __iomem *cfg_region; struct arm_cmn_node cfg, *dn; struct arm_cmn_dtm *dtm; + enum cmn_part part; u16 child_count, child_poff; u32 xp_offset[CMN_MAX_XPS]; u64 reg; @@ -2017,7 +2059,19 @@ static int arm_cmn_discover(struct arm_cmn *cmn, unsigned int rgn_offset) return -ENODEV; cfg_region = cmn->base + rgn_offset; - reg = readl_relaxed(cfg_region + CMN_CFGM_PERIPH_ID_2); + + reg = readq_relaxed(cfg_region + CMN_CFGM_PERIPH_ID_01); + part = FIELD_GET(CMN_CFGM_PID0_PART_0, reg); + part |= FIELD_GET(CMN_CFGM_PID1_PART_1, reg) << 8; + if (cmn->part && cmn->part != part) + dev_warn(cmn->dev, + "Firmware binding mismatch: expected part number 0x%x, found 0x%x\n", + cmn->part, part); + cmn->part = part; + if (!arm_cmn_model(cmn)) + dev_warn(cmn->dev, "Unknown part number: 0x%x\n", part); + + reg = readl_relaxed(cfg_region + CMN_CFGM_PERIPH_ID_23); cmn->rev = FIELD_GET(CMN_CFGM_PID2_REVISION, reg); reg = readq_relaxed(cfg_region + CMN_CFGM_INFO_GLOBAL); @@ -2081,7 +2135,7 @@ static int arm_cmn_discover(struct arm_cmn *cmn, unsigned int rgn_offset) if (xp->id == (1 << 3)) cmn->mesh_x = xp->logid; - if (cmn->model == CMN600) + if (cmn->part == PART_CMN600) xp->dtc = 0xf; else xp->dtc = 1 << readl_relaxed(xp_region + CMN_DTM_UNIT_INFO); @@ -2201,7 +2255,7 @@ static int arm_cmn_discover(struct arm_cmn *cmn, unsigned int rgn_offset) if (cmn->num_xps == 1) dev_warn(cmn->dev, "1x1 config not fully supported, translate XP events manually\n"); - dev_dbg(cmn->dev, "model %d, periph_id_2 revision %d\n", cmn->model, cmn->rev); + dev_dbg(cmn->dev, "periph_id part 0x%03x revision %d\n", cmn->part, cmn->rev); reg = cmn->ports_used; dev_dbg(cmn->dev, "mesh %dx%d, ID width %d, ports %6pbl%s\n", cmn->mesh_x, cmn->mesh_y, arm_cmn_xyidbits(cmn), ®, @@ -2256,17 +2310,17 @@ static int arm_cmn_probe(struct platform_device *pdev) return -ENOMEM; cmn->dev = &pdev->dev; - cmn->model = (unsigned long)device_get_match_data(cmn->dev); + cmn->part = (unsigned long)device_get_match_data(cmn->dev); platform_set_drvdata(pdev, cmn); - if (cmn->model == CMN600 && has_acpi_companion(cmn->dev)) { + if (cmn->part == PART_CMN600 && has_acpi_companion(cmn->dev)) { rootnode = arm_cmn600_acpi_probe(pdev, cmn); } else { rootnode = 0; cmn->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(cmn->base)) return PTR_ERR(cmn->base); - if (cmn->model == CMN600) + if (cmn->part == PART_CMN600) rootnode = arm_cmn600_of_probe(pdev->dev.of_node); } if (rootnode < 0) @@ -2335,10 +2389,10 @@ static int arm_cmn_remove(struct platform_device *pdev) #ifdef CONFIG_OF static const struct of_device_id arm_cmn_of_match[] = { - { .compatible = "arm,cmn-600", .data = (void *)CMN600 }, - { .compatible = "arm,cmn-650", .data = (void *)CMN650 }, - { .compatible = "arm,cmn-700", .data = (void *)CMN700 }, - { .compatible = "arm,ci-700", .data = (void *)CI700 }, + { .compatible = "arm,cmn-600", .data = (void *)PART_CMN600 }, + { .compatible = "arm,cmn-650" }, + { .compatible = "arm,cmn-700" }, + { .compatible = "arm,ci-700" }, {} }; MODULE_DEVICE_TABLE(of, arm_cmn_of_match); @@ -2346,9 +2400,9 @@ MODULE_DEVICE_TABLE(of, arm_cmn_of_match); #ifdef CONFIG_ACPI static const struct acpi_device_id arm_cmn_acpi_match[] = { - { "ARMHC600", CMN600 }, - { "ARMHC650", CMN650 }, - { "ARMHC700", CMN700 }, + { "ARMHC600", PART_CMN600 }, + { "ARMHC650" }, + { "ARMHC700" }, {} }; MODULE_DEVICE_TABLE(acpi, arm_cmn_acpi_match); diff --git a/drivers/perf/arm_cspmu/Kconfig b/drivers/perf/arm_cspmu/Kconfig index 0b316fe69a45c3c87dd1cdcffb030a83861b14ed..25d25ded098322b38b66e0907fbacc2b4dbc94cb 100644 --- a/drivers/perf/arm_cspmu/Kconfig +++ b/drivers/perf/arm_cspmu/Kconfig @@ -4,8 +4,7 @@ config ARM_CORESIGHT_PMU_ARCH_SYSTEM_PMU tristate "ARM Coresight Architecture PMU" - depends on ARM64 && ACPI - depends on ACPI_APMT || COMPILE_TEST + depends on ARM64 || COMPILE_TEST help Provides support for performance monitoring unit (PMU) devices based on ARM CoreSight PMU architecture. Note that this PMU diff --git a/drivers/perf/arm_cspmu/arm_cspmu.c b/drivers/perf/arm_cspmu/arm_cspmu.c index a3f1c410b4173d44137c6906b128711a871e947e..e2b7827c4563545649991a81cfc7867194abbcd4 100644 --- a/drivers/perf/arm_cspmu/arm_cspmu.c +++ b/drivers/perf/arm_cspmu/arm_cspmu.c @@ -28,7 +28,6 @@ #include #include #include -#include #include "arm_cspmu.h" #include "nvidia_cspmu.h" @@ -101,10 +100,6 @@ #define ARM_CSPMU_ACTIVE_CPU_MASK 0x0 #define ARM_CSPMU_ASSOCIATED_CPU_MASK 0x1 -/* Check if field f in flags is set with value v */ -#define CHECK_APMT_FLAG(flags, f, v) \ - ((flags & (ACPI_APMT_FLAGS_ ## f)) == (ACPI_APMT_FLAGS_ ## f ## _ ## v)) - /* Check and use default if implementer doesn't provide attribute callback */ #define CHECK_DEFAULT_IMPL_OPS(ops, callback) \ do { \ @@ -122,6 +117,11 @@ static unsigned long arm_cspmu_cpuhp_state; +static struct acpi_apmt_node *arm_cspmu_apmt_node(struct device *dev) +{ + return *(struct acpi_apmt_node **)dev_get_platdata(dev); +} + /* * In CoreSight PMU architecture, all of the MMIO registers are 32-bit except * counter register. The counter register can be implemented as 32-bit or 64-bit @@ -156,12 +156,6 @@ static u64 read_reg64_hilohi(const void __iomem *addr, u32 max_poll_count) return val; } -/* Check if PMU supports 64-bit single copy atomic. */ -static inline bool supports_64bit_atomics(const struct arm_cspmu *cspmu) -{ - return CHECK_APMT_FLAG(cspmu->apmt_node->flags, ATOMIC, SUPP); -} - /* Check if cycle counter is supported. */ static inline bool supports_cycle_counter(const struct arm_cspmu *cspmu) { @@ -189,10 +183,10 @@ static inline bool use_64b_counter_reg(const struct arm_cspmu *cspmu) ssize_t arm_cspmu_sysfs_event_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct dev_ext_attribute *eattr = - container_of(attr, struct dev_ext_attribute, attr); - return sysfs_emit(buf, "event=0x%llx\n", - (unsigned long long)eattr->var); + struct perf_pmu_events_attr *pmu_attr; + + pmu_attr = container_of(attr, typeof(*pmu_attr), attr); + return sysfs_emit(buf, "event=0x%llx\n", pmu_attr->id); } EXPORT_SYMBOL_GPL(arm_cspmu_sysfs_event_show); @@ -320,7 +314,7 @@ static const char *arm_cspmu_get_name(const struct arm_cspmu *cspmu) static atomic_t pmu_idx[ACPI_APMT_NODE_TYPE_COUNT] = { 0 }; dev = cspmu->dev; - apmt_node = cspmu->apmt_node; + apmt_node = arm_cspmu_apmt_node(dev); pmu_type = apmt_node->type; if (pmu_type >= ACPI_APMT_NODE_TYPE_COUNT) { @@ -397,8 +391,8 @@ static const struct impl_match impl_match[] = { static int arm_cspmu_init_impl_ops(struct arm_cspmu *cspmu) { int ret; - struct acpi_apmt_node *apmt_node = cspmu->apmt_node; struct arm_cspmu_impl_ops *impl_ops = &cspmu->impl.ops; + struct acpi_apmt_node *apmt_node = arm_cspmu_apmt_node(cspmu->dev); const struct impl_match *match = impl_match; /* @@ -720,7 +714,7 @@ static u64 arm_cspmu_read_counter(struct perf_event *event) offset = counter_offset(sizeof(u64), event->hw.idx); counter_addr = cspmu->base1 + offset; - return supports_64bit_atomics(cspmu) ? + return cspmu->has_atomic_dword ? readq(counter_addr) : read_reg64_hilohi(counter_addr, HILOHI_MAX_POLL); } @@ -911,24 +905,18 @@ static struct arm_cspmu *arm_cspmu_alloc(struct platform_device *pdev) { struct acpi_apmt_node *apmt_node; struct arm_cspmu *cspmu; - struct device *dev; - - dev = &pdev->dev; - apmt_node = *(struct acpi_apmt_node **)dev_get_platdata(dev); - if (!apmt_node) { - dev_err(dev, "failed to get APMT node\n"); - return NULL; - } + struct device *dev = &pdev->dev; cspmu = devm_kzalloc(dev, sizeof(*cspmu), GFP_KERNEL); if (!cspmu) return NULL; cspmu->dev = dev; - cspmu->apmt_node = apmt_node; - platform_set_drvdata(pdev, cspmu); + apmt_node = arm_cspmu_apmt_node(dev); + cspmu->has_atomic_dword = apmt_node->flags & ACPI_APMT_FLAGS_ATOMIC; + return cspmu; } @@ -936,11 +924,9 @@ static int arm_cspmu_init_mmio(struct arm_cspmu *cspmu) { struct device *dev; struct platform_device *pdev; - struct acpi_apmt_node *apmt_node; dev = cspmu->dev; pdev = to_platform_device(dev); - apmt_node = cspmu->apmt_node; /* Base address for page 0. */ cspmu->base0 = devm_platform_ioremap_resource(pdev, 0); @@ -951,7 +937,7 @@ static int arm_cspmu_init_mmio(struct arm_cspmu *cspmu) /* Base address for page 1 if supported. Otherwise point to page 0. */ cspmu->base1 = cspmu->base0; - if (CHECK_APMT_FLAG(apmt_node->flags, DUAL_PAGE, SUPP)) { + if (platform_get_resource(pdev, IORESOURCE_MEM, 1)) { cspmu->base1 = devm_platform_ioremap_resource(pdev, 1); if (IS_ERR(cspmu->base1)) { dev_err(dev, "ioremap failed for page-1 resource\n"); @@ -1048,19 +1034,14 @@ static int arm_cspmu_request_irq(struct arm_cspmu *cspmu) int irq, ret; struct device *dev; struct platform_device *pdev; - struct acpi_apmt_node *apmt_node; dev = cspmu->dev; pdev = to_platform_device(dev); - apmt_node = cspmu->apmt_node; /* Skip IRQ request if the PMU does not support overflow interrupt. */ - if (apmt_node->ovflw_irq == 0) - return 0; - - irq = platform_get_irq(pdev, 0); + irq = platform_get_irq_optional(pdev, 0); if (irq < 0) - return irq; + return irq == -ENXIO ? 0 : irq; ret = devm_request_irq(dev, irq, arm_cspmu_handle_irq, IRQF_NOBALANCING | IRQF_NO_THREAD, dev_name(dev), @@ -1075,6 +1056,9 @@ static int arm_cspmu_request_irq(struct arm_cspmu *cspmu) return 0; } +#if defined(CONFIG_ACPI) && defined(CONFIG_ARM64) +#include + static inline int arm_cspmu_find_cpu_container(int cpu, u32 container_uid) { u32 acpi_uid; @@ -1099,15 +1083,13 @@ static inline int arm_cspmu_find_cpu_container(int cpu, u32 container_uid) return -ENODEV; } -static int arm_cspmu_get_cpus(struct arm_cspmu *cspmu) +static int arm_cspmu_acpi_get_cpus(struct arm_cspmu *cspmu) { - struct device *dev; struct acpi_apmt_node *apmt_node; int affinity_flag; int cpu; - dev = cspmu->pmu.dev; - apmt_node = cspmu->apmt_node; + apmt_node = arm_cspmu_apmt_node(cspmu->dev); affinity_flag = apmt_node->flags & ACPI_APMT_FLAGS_AFFINITY; if (affinity_flag == ACPI_APMT_FLAGS_AFFINITY_PROC) { @@ -1129,12 +1111,23 @@ static int arm_cspmu_get_cpus(struct arm_cspmu *cspmu) } if (cpumask_empty(&cspmu->associated_cpus)) { - dev_dbg(dev, "No cpu associated with the PMU\n"); + dev_dbg(cspmu->dev, "No cpu associated with the PMU\n"); return -ENODEV; } return 0; } +#else +static int arm_cspmu_acpi_get_cpus(struct arm_cspmu *cspmu) +{ + return -ENODEV; +} +#endif + +static int arm_cspmu_get_cpus(struct arm_cspmu *cspmu) +{ + return arm_cspmu_acpi_get_cpus(cspmu); +} static int arm_cspmu_register_pmu(struct arm_cspmu *cspmu) { @@ -1220,6 +1213,12 @@ static int arm_cspmu_device_remove(struct platform_device *pdev) return 0; } +static const struct platform_device_id arm_cspmu_id[] = { + {DRVNAME, 0}, + { }, +}; +MODULE_DEVICE_TABLE(platform, arm_cspmu_id); + static struct platform_driver arm_cspmu_driver = { .driver = { .name = DRVNAME, @@ -1227,12 +1226,14 @@ static struct platform_driver arm_cspmu_driver = { }, .probe = arm_cspmu_device_probe, .remove = arm_cspmu_device_remove, + .id_table = arm_cspmu_id, }; static void arm_cspmu_set_active_cpu(int cpu, struct arm_cspmu *cspmu) { cpumask_set_cpu(cpu, &cspmu->active_cpu); - WARN_ON(irq_set_affinity(cspmu->irq, &cspmu->active_cpu)); + if (cspmu->irq) + WARN_ON(irq_set_affinity(cspmu->irq, &cspmu->active_cpu)); } static int arm_cspmu_cpu_online(unsigned int cpu, struct hlist_node *node) diff --git a/drivers/perf/arm_cspmu/arm_cspmu.h b/drivers/perf/arm_cspmu/arm_cspmu.h index 51323b175a4a304935f5469a5bb74bc1419fbbb7..83df53d1c132cd6a02b6fc0069d6c9665309262f 100644 --- a/drivers/perf/arm_cspmu/arm_cspmu.h +++ b/drivers/perf/arm_cspmu/arm_cspmu.h @@ -8,7 +8,6 @@ #ifndef __ARM_CSPMU_H__ #define __ARM_CSPMU_H__ -#include #include #include #include @@ -118,16 +117,16 @@ struct arm_cspmu_impl { struct arm_cspmu { struct pmu pmu; struct device *dev; - struct acpi_apmt_node *apmt_node; const char *name; const char *identifier; void __iomem *base0; void __iomem *base1; - int irq; cpumask_t associated_cpus; cpumask_t active_cpu; struct hlist_node cpuhp_node; + int irq; + bool has_atomic_dword; u32 pmcfgr; u32 num_logical_ctrs; u32 num_set_clr_reg; diff --git a/drivers/perf/arm_dmc620_pmu.c b/drivers/perf/arm_dmc620_pmu.c index 5de06f9a4dd3fab1186f7667ff8c05ba204a2f67..9d0f01c4455ad61c798e821323033918715878b1 100644 --- a/drivers/perf/arm_dmc620_pmu.c +++ b/drivers/perf/arm_dmc620_pmu.c @@ -227,9 +227,31 @@ static const struct attribute_group dmc620_pmu_format_attr_group = { .attrs = dmc620_pmu_formats_attrs, }; +static ssize_t dmc620_pmu_cpumask_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct dmc620_pmu *dmc620_pmu = to_dmc620_pmu(dev_get_drvdata(dev)); + + return cpumap_print_to_pagebuf(true, buf, + cpumask_of(dmc620_pmu->irq->cpu)); +} + +static struct device_attribute dmc620_pmu_cpumask_attr = + __ATTR(cpumask, 0444, dmc620_pmu_cpumask_show, NULL); + +static struct attribute *dmc620_pmu_cpumask_attrs[] = { + &dmc620_pmu_cpumask_attr.attr, + NULL, +}; + +static const struct attribute_group dmc620_pmu_cpumask_attr_group = { + .attrs = dmc620_pmu_cpumask_attrs, +}; + static const struct attribute_group *dmc620_pmu_attr_groups[] = { &dmc620_pmu_events_attr_group, &dmc620_pmu_format_attr_group, + &dmc620_pmu_cpumask_attr_group, NULL, }; diff --git a/drivers/perf/arm_pmu.c b/drivers/perf/arm_pmu.c index 15bd1e34a88eae1dad9fd770b014161e0f5bb004..f6ccb2cd4dfc9992322b52c5c3c94e1636f4ec8b 100644 --- a/drivers/perf/arm_pmu.c +++ b/drivers/perf/arm_pmu.c @@ -109,6 +109,8 @@ static inline u64 arm_pmu_event_max_period(struct perf_event *event) { if (event->hw.flags & ARMPMU_EVT_64BIT) return GENMASK_ULL(63, 0); + else if (event->hw.flags & ARMPMU_EVT_63BIT) + return GENMASK_ULL(62, 0); else if (event->hw.flags & ARMPMU_EVT_47BIT) return GENMASK_ULL(46, 0); else @@ -687,6 +689,11 @@ static int armpmu_get_cpu_irq(struct arm_pmu *pmu, int cpu) return per_cpu(hw_events->irq, cpu); } +bool arm_pmu_irq_is_nmi(void) +{ + return has_nmi; +} + /* * PMU hardware loses all context when a CPU goes offline. * When a CPU is hotplugged back in, since some hardware registers are diff --git a/drivers/perf/arm_pmuv3.c b/drivers/perf/arm_pmuv3.c index c98e4039386dbcbdb1de1f3c8848dbf038b0ceb9..08b3a1bf0ef62a8ce126b9506507a67a25a81b5f 100644 --- a/drivers/perf/arm_pmuv3.c +++ b/drivers/perf/arm_pmuv3.c @@ -22,6 +22,7 @@ #include #include #include +#include #include @@ -677,9 +678,25 @@ static inline u32 armv8pmu_getreset_flags(void) return value; } +static void update_pmuserenr(u64 val) +{ + lockdep_assert_irqs_disabled(); + + /* + * The current PMUSERENR_EL0 value might be the value for the guest. + * If that's the case, have KVM keep tracking of the register value + * for the host EL0 so that KVM can restore it before returning to + * the host EL0. Otherwise, update the register now. + */ + if (kvm_set_pmuserenr(val)) + return; + + write_pmuserenr(val); +} + static void armv8pmu_disable_user_access(void) { - write_pmuserenr(0); + update_pmuserenr(0); } static void armv8pmu_enable_user_access(struct arm_pmu *cpu_pmu) @@ -695,8 +712,7 @@ static void armv8pmu_enable_user_access(struct arm_pmu *cpu_pmu) armv8pmu_write_evcntr(i, 0); } - write_pmuserenr(0); - write_pmuserenr(ARMV8_PMU_USERENR_ER | ARMV8_PMU_USERENR_CR); + update_pmuserenr(ARMV8_PMU_USERENR_ER | ARMV8_PMU_USERENR_CR); } static void armv8pmu_enable_event(struct perf_event *event) @@ -1348,10 +1364,17 @@ static struct platform_driver armv8_pmu_driver = { static int __init armv8_pmu_driver_init(void) { + int ret; + if (acpi_disabled) - return platform_driver_register(&armv8_pmu_driver); + ret = platform_driver_register(&armv8_pmu_driver); else - return arm_pmu_acpi_probe(armv8_pmuv3_pmu_init); + ret = arm_pmu_acpi_probe(armv8_pmuv3_pmu_init); + + if (!ret) + lockup_detector_retry_init(); + + return ret; } device_initcall(armv8_pmu_driver_init) diff --git a/drivers/perf/cxl_pmu.c b/drivers/perf/cxl_pmu.c new file mode 100644 index 0000000000000000000000000000000000000000..0a8f597e695bccf12c5b1de72386c3eafc07131c --- /dev/null +++ b/drivers/perf/cxl_pmu.c @@ -0,0 +1,990 @@ +// SPDX-License-Identifier: GPL-2.0-only + +/* + * Copyright(c) 2023 Huawei + * + * The CXL 3.0 specification includes a standard Performance Monitoring Unit, + * called the CXL PMU, or CPMU. In order to allow a high degree of + * implementation flexibility the specification provides a wide range of + * options all of which are self describing. + * + * Details in CXL rev 3.0 section 8.2.7 CPMU Register Interface + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../cxl/cxlpci.h" +#include "../cxl/cxl.h" +#include "../cxl/pmu.h" + +#define CXL_PMU_CAP_REG 0x0 +#define CXL_PMU_CAP_NUM_COUNTERS_MSK GENMASK_ULL(4, 0) +#define CXL_PMU_CAP_COUNTER_WIDTH_MSK GENMASK_ULL(15, 8) +#define CXL_PMU_CAP_NUM_EVN_CAP_REG_SUP_MSK GENMASK_ULL(24, 20) +#define CXL_PMU_CAP_FILTERS_SUP_MSK GENMASK_ULL(39, 32) +#define CXL_PMU_FILTER_HDM BIT(0) +#define CXL_PMU_FILTER_CHAN_RANK_BANK BIT(1) +#define CXL_PMU_CAP_MSI_N_MSK GENMASK_ULL(47, 44) +#define CXL_PMU_CAP_WRITEABLE_WHEN_FROZEN BIT_ULL(48) +#define CXL_PMU_CAP_FREEZE BIT_ULL(49) +#define CXL_PMU_CAP_INT BIT_ULL(50) +#define CXL_PMU_CAP_VERSION_MSK GENMASK_ULL(63, 60) + +#define CXL_PMU_OVERFLOW_REG 0x10 +#define CXL_PMU_FREEZE_REG 0x18 +#define CXL_PMU_EVENT_CAP_REG(n) (0x100 + 8 * (n)) +#define CXL_PMU_EVENT_CAP_SUPPORTED_EVENTS_MSK GENMASK_ULL(31, 0) +#define CXL_PMU_EVENT_CAP_GROUP_ID_MSK GENMASK_ULL(47, 32) +#define CXL_PMU_EVENT_CAP_VENDOR_ID_MSK GENMASK_ULL(63, 48) + +#define CXL_PMU_COUNTER_CFG_REG(n) (0x200 + 8 * (n)) +#define CXL_PMU_COUNTER_CFG_TYPE_MSK GENMASK_ULL(1, 0) +#define CXL_PMU_COUNTER_CFG_TYPE_FREE_RUN 0 +#define CXL_PMU_COUNTER_CFG_TYPE_FIXED_FUN 1 +#define CXL_PMU_COUNTER_CFG_TYPE_CONFIGURABLE 2 +#define CXL_PMU_COUNTER_CFG_ENABLE BIT_ULL(8) +#define CXL_PMU_COUNTER_CFG_INT_ON_OVRFLW BIT_ULL(9) +#define CXL_PMU_COUNTER_CFG_FREEZE_ON_OVRFLW BIT_ULL(10) +#define CXL_PMU_COUNTER_CFG_EDGE BIT_ULL(11) +#define CXL_PMU_COUNTER_CFG_INVERT BIT_ULL(12) +#define CXL_PMU_COUNTER_CFG_THRESHOLD_MSK GENMASK_ULL(23, 16) +#define CXL_PMU_COUNTER_CFG_EVENTS_MSK GENMASK_ULL(55, 24) +#define CXL_PMU_COUNTER_CFG_EVENT_GRP_ID_IDX_MSK GENMASK_ULL(63, 59) + +#define CXL_PMU_FILTER_CFG_REG(n, f) (0x400 + 4 * ((f) + (n) * 8)) +#define CXL_PMU_FILTER_CFG_VALUE_MSK GENMASK(15, 0) + +#define CXL_PMU_COUNTER_REG(n) (0xc00 + 8 * (n)) + +/* CXL rev 3.0 Table 13-5 Events under CXL Vendor ID */ +#define CXL_PMU_GID_CLOCK_TICKS 0x00 +#define CXL_PMU_GID_D2H_REQ 0x0010 +#define CXL_PMU_GID_D2H_RSP 0x0011 +#define CXL_PMU_GID_H2D_REQ 0x0012 +#define CXL_PMU_GID_H2D_RSP 0x0013 +#define CXL_PMU_GID_CACHE_DATA 0x0014 +#define CXL_PMU_GID_M2S_REQ 0x0020 +#define CXL_PMU_GID_M2S_RWD 0x0021 +#define CXL_PMU_GID_M2S_BIRSP 0x0022 +#define CXL_PMU_GID_S2M_BISNP 0x0023 +#define CXL_PMU_GID_S2M_NDR 0x0024 +#define CXL_PMU_GID_S2M_DRS 0x0025 +#define CXL_PMU_GID_DDR 0x8000 + +static int cxl_pmu_cpuhp_state_num; + +struct cxl_pmu_ev_cap { + u16 vid; + u16 gid; + u32 msk; + union { + int counter_idx; /* fixed counters */ + int event_idx; /* configurable counters */ + }; + struct list_head node; +}; + +#define CXL_PMU_MAX_COUNTERS 64 +struct cxl_pmu_info { + struct pmu pmu; + void __iomem *base; + struct perf_event **hw_events; + struct list_head event_caps_configurable; + struct list_head event_caps_fixed; + DECLARE_BITMAP(used_counter_bm, CXL_PMU_MAX_COUNTERS); + DECLARE_BITMAP(conf_counter_bm, CXL_PMU_MAX_COUNTERS); + u16 counter_width; + u8 num_counters; + u8 num_event_capabilities; + int on_cpu; + struct hlist_node node; + bool filter_hdm; + int irq; +}; + +#define pmu_to_cxl_pmu_info(_pmu) container_of(_pmu, struct cxl_pmu_info, pmu) + +/* + * All CPMU counters are discoverable via the Event Capabilities Registers. + * Each Event Capability register contains a a VID / GroupID. + * A counter may then count any combination (by summing) of events in + * that group which are in the Supported Events Bitmask. + * However, there are some complexities to the scheme. + * - Fixed function counters refer to an Event Capabilities register. + * That event capability register is not then used for Configurable + * counters. + */ +static int cxl_pmu_parse_caps(struct device *dev, struct cxl_pmu_info *info) +{ + unsigned long fixed_counter_event_cap_bm = 0; + void __iomem *base = info->base; + bool freeze_for_enable; + u64 val, eval; + int i; + + val = readq(base + CXL_PMU_CAP_REG); + freeze_for_enable = FIELD_GET(CXL_PMU_CAP_WRITEABLE_WHEN_FROZEN, val) && + FIELD_GET(CXL_PMU_CAP_FREEZE, val); + if (!freeze_for_enable) { + dev_err(dev, "Counters not writable while frozen\n"); + return -ENODEV; + } + + info->num_counters = FIELD_GET(CXL_PMU_CAP_NUM_COUNTERS_MSK, val) + 1; + info->counter_width = FIELD_GET(CXL_PMU_CAP_COUNTER_WIDTH_MSK, val); + info->num_event_capabilities = FIELD_GET(CXL_PMU_CAP_NUM_EVN_CAP_REG_SUP_MSK, val) + 1; + + info->filter_hdm = FIELD_GET(CXL_PMU_CAP_FILTERS_SUP_MSK, val) & CXL_PMU_FILTER_HDM; + if (FIELD_GET(CXL_PMU_CAP_INT, val)) + info->irq = FIELD_GET(CXL_PMU_CAP_MSI_N_MSK, val); + else + info->irq = -1; + + /* First handle fixed function counters; note if configurable counters found */ + for (i = 0; i < info->num_counters; i++) { + struct cxl_pmu_ev_cap *pmu_ev; + u32 events_msk; + u8 group_idx; + + val = readq(base + CXL_PMU_COUNTER_CFG_REG(i)); + + if (FIELD_GET(CXL_PMU_COUNTER_CFG_TYPE_MSK, val) == + CXL_PMU_COUNTER_CFG_TYPE_CONFIGURABLE) { + set_bit(i, info->conf_counter_bm); + } + + if (FIELD_GET(CXL_PMU_COUNTER_CFG_TYPE_MSK, val) != + CXL_PMU_COUNTER_CFG_TYPE_FIXED_FUN) + continue; + + /* In this case we know which fields are const */ + group_idx = FIELD_GET(CXL_PMU_COUNTER_CFG_EVENT_GRP_ID_IDX_MSK, val); + events_msk = FIELD_GET(CXL_PMU_COUNTER_CFG_EVENTS_MSK, val); + eval = readq(base + CXL_PMU_EVENT_CAP_REG(group_idx)); + pmu_ev = devm_kzalloc(dev, sizeof(*pmu_ev), GFP_KERNEL); + if (!pmu_ev) + return -ENOMEM; + + pmu_ev->vid = FIELD_GET(CXL_PMU_EVENT_CAP_VENDOR_ID_MSK, eval); + pmu_ev->gid = FIELD_GET(CXL_PMU_EVENT_CAP_GROUP_ID_MSK, eval); + /* For a fixed purpose counter use the events mask from the counter CFG */ + pmu_ev->msk = events_msk; + pmu_ev->counter_idx = i; + /* This list add is never unwound as all entries deleted on remove */ + list_add(&pmu_ev->node, &info->event_caps_fixed); + /* + * Configurable counters must not use an Event Capability registers that + * is in use for a Fixed counter + */ + set_bit(group_idx, &fixed_counter_event_cap_bm); + } + + if (!bitmap_empty(info->conf_counter_bm, CXL_PMU_MAX_COUNTERS)) { + struct cxl_pmu_ev_cap *pmu_ev; + int j; + /* Walk event capabilities unused by fixed counters */ + for_each_clear_bit(j, &fixed_counter_event_cap_bm, + info->num_event_capabilities) { + pmu_ev = devm_kzalloc(dev, sizeof(*pmu_ev), GFP_KERNEL); + if (!pmu_ev) + return -ENOMEM; + + eval = readq(base + CXL_PMU_EVENT_CAP_REG(j)); + pmu_ev->vid = FIELD_GET(CXL_PMU_EVENT_CAP_VENDOR_ID_MSK, eval); + pmu_ev->gid = FIELD_GET(CXL_PMU_EVENT_CAP_GROUP_ID_MSK, eval); + pmu_ev->msk = FIELD_GET(CXL_PMU_EVENT_CAP_SUPPORTED_EVENTS_MSK, eval); + pmu_ev->event_idx = j; + list_add(&pmu_ev->node, &info->event_caps_configurable); + } + } + + return 0; +} + +static ssize_t cxl_pmu_format_sysfs_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct dev_ext_attribute *eattr; + + eattr = container_of(attr, struct dev_ext_attribute, attr); + + return sysfs_emit(buf, "%s\n", (char *)eattr->var); +} + +#define CXL_PMU_FORMAT_ATTR(_name, _format)\ + (&((struct dev_ext_attribute[]) { \ + { \ + .attr = __ATTR(_name, 0444, \ + cxl_pmu_format_sysfs_show, NULL), \ + .var = (void *)_format \ + } \ + })[0].attr.attr) + +enum { + cxl_pmu_mask_attr, + cxl_pmu_gid_attr, + cxl_pmu_vid_attr, + cxl_pmu_threshold_attr, + cxl_pmu_invert_attr, + cxl_pmu_edge_attr, + cxl_pmu_hdm_filter_en_attr, + cxl_pmu_hdm_attr, +}; + +static struct attribute *cxl_pmu_format_attr[] = { + [cxl_pmu_mask_attr] = CXL_PMU_FORMAT_ATTR(mask, "config:0-31"), + [cxl_pmu_gid_attr] = CXL_PMU_FORMAT_ATTR(gid, "config:32-47"), + [cxl_pmu_vid_attr] = CXL_PMU_FORMAT_ATTR(vid, "config:48-63"), + [cxl_pmu_threshold_attr] = CXL_PMU_FORMAT_ATTR(threshold, "config1:0-15"), + [cxl_pmu_invert_attr] = CXL_PMU_FORMAT_ATTR(invert, "config1:16"), + [cxl_pmu_edge_attr] = CXL_PMU_FORMAT_ATTR(edge, "config1:17"), + [cxl_pmu_hdm_filter_en_attr] = CXL_PMU_FORMAT_ATTR(hdm_filter_en, "config1:18"), + [cxl_pmu_hdm_attr] = CXL_PMU_FORMAT_ATTR(hdm, "config2:0-15"), + NULL +}; + +#define CXL_PMU_ATTR_CONFIG_MASK_MSK GENMASK_ULL(31, 0) +#define CXL_PMU_ATTR_CONFIG_GID_MSK GENMASK_ULL(47, 32) +#define CXL_PMU_ATTR_CONFIG_VID_MSK GENMASK_ULL(63, 48) +#define CXL_PMU_ATTR_CONFIG1_THRESHOLD_MSK GENMASK_ULL(15, 0) +#define CXL_PMU_ATTR_CONFIG1_INVERT_MSK BIT(16) +#define CXL_PMU_ATTR_CONFIG1_EDGE_MSK BIT(17) +#define CXL_PMU_ATTR_CONFIG1_FILTER_EN_MSK BIT(18) +#define CXL_PMU_ATTR_CONFIG2_HDM_MSK GENMASK(15, 0) + +static umode_t cxl_pmu_format_is_visible(struct kobject *kobj, + struct attribute *attr, int a) +{ + struct device *dev = kobj_to_dev(kobj); + struct cxl_pmu_info *info = dev_get_drvdata(dev); + + /* + * Filter capability at the CPMU level, so hide the attributes if the particular + * filter is not supported. + */ + if (!info->filter_hdm && + (attr == cxl_pmu_format_attr[cxl_pmu_hdm_filter_en_attr] || + attr == cxl_pmu_format_attr[cxl_pmu_hdm_attr])) + return 0; + + return attr->mode; +} + +static const struct attribute_group cxl_pmu_format_group = { + .name = "format", + .attrs = cxl_pmu_format_attr, + .is_visible = cxl_pmu_format_is_visible, +}; + +static u32 cxl_pmu_config_get_mask(struct perf_event *event) +{ + return FIELD_GET(CXL_PMU_ATTR_CONFIG_MASK_MSK, event->attr.config); +} + +static u16 cxl_pmu_config_get_gid(struct perf_event *event) +{ + return FIELD_GET(CXL_PMU_ATTR_CONFIG_GID_MSK, event->attr.config); +} + +static u16 cxl_pmu_config_get_vid(struct perf_event *event) +{ + return FIELD_GET(CXL_PMU_ATTR_CONFIG_VID_MSK, event->attr.config); +} + +static u8 cxl_pmu_config1_get_threshold(struct perf_event *event) +{ + return FIELD_GET(CXL_PMU_ATTR_CONFIG1_THRESHOLD_MSK, event->attr.config1); +} + +static bool cxl_pmu_config1_get_invert(struct perf_event *event) +{ + return FIELD_GET(CXL_PMU_ATTR_CONFIG1_INVERT_MSK, event->attr.config1); +} + +static bool cxl_pmu_config1_get_edge(struct perf_event *event) +{ + return FIELD_GET(CXL_PMU_ATTR_CONFIG1_EDGE_MSK, event->attr.config1); +} + +/* + * CPMU specification allows for 8 filters, each with a 16 bit value... + * So we need to find 8x16bits to store it in. + * As the value used for disable is 0xffff, a separate enable switch + * is needed. + */ + +static bool cxl_pmu_config1_hdm_filter_en(struct perf_event *event) +{ + return FIELD_GET(CXL_PMU_ATTR_CONFIG1_FILTER_EN_MSK, event->attr.config1); +} + +static u16 cxl_pmu_config2_get_hdm_decoder(struct perf_event *event) +{ + return FIELD_GET(CXL_PMU_ATTR_CONFIG2_HDM_MSK, event->attr.config2); +} + +static ssize_t cxl_pmu_event_sysfs_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct perf_pmu_events_attr *pmu_attr = + container_of(attr, struct perf_pmu_events_attr, attr); + + return sysfs_emit(buf, "config=%#llx\n", pmu_attr->id); +} + +#define CXL_PMU_EVENT_ATTR(_name, _vid, _gid, _msk) \ + PMU_EVENT_ATTR_ID(_name, cxl_pmu_event_sysfs_show, \ + ((u64)(_vid) << 48) | ((u64)(_gid) << 32) | (u64)(_msk)) + +/* For CXL spec defined events */ +#define CXL_PMU_EVENT_CXL_ATTR(_name, _gid, _msk) \ + CXL_PMU_EVENT_ATTR(_name, PCI_DVSEC_VENDOR_ID_CXL, _gid, _msk) + +static struct attribute *cxl_pmu_event_attrs[] = { + CXL_PMU_EVENT_CXL_ATTR(clock_ticks, CXL_PMU_GID_CLOCK_TICKS, BIT(0)), + /* CXL rev 3.0 Table 3-17 - Device to Host Requests */ + CXL_PMU_EVENT_CXL_ATTR(d2h_req_rdcurr, CXL_PMU_GID_D2H_REQ, BIT(1)), + CXL_PMU_EVENT_CXL_ATTR(d2h_req_rdown, CXL_PMU_GID_D2H_REQ, BIT(2)), + CXL_PMU_EVENT_CXL_ATTR(d2h_req_rdshared, CXL_PMU_GID_D2H_REQ, BIT(3)), + CXL_PMU_EVENT_CXL_ATTR(d2h_req_rdany, CXL_PMU_GID_D2H_REQ, BIT(4)), + CXL_PMU_EVENT_CXL_ATTR(d2h_req_rdownnodata, CXL_PMU_GID_D2H_REQ, BIT(5)), + CXL_PMU_EVENT_CXL_ATTR(d2h_req_itomwr, CXL_PMU_GID_D2H_REQ, BIT(6)), + CXL_PMU_EVENT_CXL_ATTR(d2h_req_wrcurr, CXL_PMU_GID_D2H_REQ, BIT(7)), + CXL_PMU_EVENT_CXL_ATTR(d2h_req_clflush, CXL_PMU_GID_D2H_REQ, BIT(8)), + CXL_PMU_EVENT_CXL_ATTR(d2h_req_cleanevict, CXL_PMU_GID_D2H_REQ, BIT(9)), + CXL_PMU_EVENT_CXL_ATTR(d2h_req_dirtyevict, CXL_PMU_GID_D2H_REQ, BIT(10)), + CXL_PMU_EVENT_CXL_ATTR(d2h_req_cleanevictnodata, CXL_PMU_GID_D2H_REQ, BIT(11)), + CXL_PMU_EVENT_CXL_ATTR(d2h_req_wowrinv, CXL_PMU_GID_D2H_REQ, BIT(12)), + CXL_PMU_EVENT_CXL_ATTR(d2h_req_wowrinvf, CXL_PMU_GID_D2H_REQ, BIT(13)), + CXL_PMU_EVENT_CXL_ATTR(d2h_req_wrinv, CXL_PMU_GID_D2H_REQ, BIT(14)), + CXL_PMU_EVENT_CXL_ATTR(d2h_req_cacheflushed, CXL_PMU_GID_D2H_REQ, BIT(16)), + /* CXL rev 3.0 Table 3-20 - D2H Repsonse Encodings */ + CXL_PMU_EVENT_CXL_ATTR(d2h_rsp_rspihiti, CXL_PMU_GID_D2H_RSP, BIT(4)), + CXL_PMU_EVENT_CXL_ATTR(d2h_rsp_rspvhitv, CXL_PMU_GID_D2H_RSP, BIT(6)), + CXL_PMU_EVENT_CXL_ATTR(d2h_rsp_rspihitse, CXL_PMU_GID_D2H_RSP, BIT(5)), + CXL_PMU_EVENT_CXL_ATTR(d2h_rsp_rspshitse, CXL_PMU_GID_D2H_RSP, BIT(1)), + CXL_PMU_EVENT_CXL_ATTR(d2h_rsp_rspsfwdm, CXL_PMU_GID_D2H_RSP, BIT(7)), + CXL_PMU_EVENT_CXL_ATTR(d2h_rsp_rspifwdm, CXL_PMU_GID_D2H_RSP, BIT(15)), + CXL_PMU_EVENT_CXL_ATTR(d2h_rsp_rspvfwdv, CXL_PMU_GID_D2H_RSP, BIT(22)), + /* CXL rev 3.0 Table 3-21 - CXL.cache - Mapping of H2D Requests to D2H Responses */ + CXL_PMU_EVENT_CXL_ATTR(h2d_req_snpdata, CXL_PMU_GID_H2D_REQ, BIT(1)), + CXL_PMU_EVENT_CXL_ATTR(h2d_req_snpinv, CXL_PMU_GID_H2D_REQ, BIT(2)), + CXL_PMU_EVENT_CXL_ATTR(h2d_req_snpcur, CXL_PMU_GID_H2D_REQ, BIT(3)), + /* CXL rev 3.0 Table 3-22 - H2D Response Opcode Encodings */ + CXL_PMU_EVENT_CXL_ATTR(h2d_rsp_writepull, CXL_PMU_GID_H2D_RSP, BIT(1)), + CXL_PMU_EVENT_CXL_ATTR(h2d_rsp_go, CXL_PMU_GID_H2D_RSP, BIT(4)), + CXL_PMU_EVENT_CXL_ATTR(h2d_rsp_gowritepull, CXL_PMU_GID_H2D_RSP, BIT(5)), + CXL_PMU_EVENT_CXL_ATTR(h2d_rsp_extcmp, CXL_PMU_GID_H2D_RSP, BIT(6)), + CXL_PMU_EVENT_CXL_ATTR(h2d_rsp_gowritepulldrop, CXL_PMU_GID_H2D_RSP, BIT(8)), + CXL_PMU_EVENT_CXL_ATTR(h2d_rsp_fastgowritepull, CXL_PMU_GID_H2D_RSP, BIT(13)), + CXL_PMU_EVENT_CXL_ATTR(h2d_rsp_goerrwritepull, CXL_PMU_GID_H2D_RSP, BIT(15)), + /* CXL rev 3.0 Table 13-5 directly lists these */ + CXL_PMU_EVENT_CXL_ATTR(cachedata_d2h_data, CXL_PMU_GID_CACHE_DATA, BIT(0)), + CXL_PMU_EVENT_CXL_ATTR(cachedata_h2d_data, CXL_PMU_GID_CACHE_DATA, BIT(1)), + /* CXL rev 3.0 Table 3-29 M2S Req Memory Opcodes */ + CXL_PMU_EVENT_CXL_ATTR(m2s_req_meminv, CXL_PMU_GID_M2S_REQ, BIT(0)), + CXL_PMU_EVENT_CXL_ATTR(m2s_req_memrd, CXL_PMU_GID_M2S_REQ, BIT(1)), + CXL_PMU_EVENT_CXL_ATTR(m2s_req_memrddata, CXL_PMU_GID_M2S_REQ, BIT(2)), + CXL_PMU_EVENT_CXL_ATTR(m2s_req_memrdfwd, CXL_PMU_GID_M2S_REQ, BIT(3)), + CXL_PMU_EVENT_CXL_ATTR(m2s_req_memwrfwd, CXL_PMU_GID_M2S_REQ, BIT(4)), + CXL_PMU_EVENT_CXL_ATTR(m2s_req_memspecrd, CXL_PMU_GID_M2S_REQ, BIT(8)), + CXL_PMU_EVENT_CXL_ATTR(m2s_req_meminvnt, CXL_PMU_GID_M2S_REQ, BIT(9)), + CXL_PMU_EVENT_CXL_ATTR(m2s_req_memcleanevict, CXL_PMU_GID_M2S_REQ, BIT(10)), + /* CXL rev 3.0 Table 3-35 M2S RwD Memory Opcodes */ + CXL_PMU_EVENT_CXL_ATTR(m2s_rwd_memwr, CXL_PMU_GID_M2S_RWD, BIT(1)), + CXL_PMU_EVENT_CXL_ATTR(m2s_rwd_memwrptl, CXL_PMU_GID_M2S_RWD, BIT(2)), + CXL_PMU_EVENT_CXL_ATTR(m2s_rwd_biconflict, CXL_PMU_GID_M2S_RWD, BIT(4)), + /* CXL rev 3.0 Table 3-38 M2S BIRsp Memory Opcodes */ + CXL_PMU_EVENT_CXL_ATTR(m2s_birsp_i, CXL_PMU_GID_M2S_BIRSP, BIT(0)), + CXL_PMU_EVENT_CXL_ATTR(m2s_birsp_s, CXL_PMU_GID_M2S_BIRSP, BIT(1)), + CXL_PMU_EVENT_CXL_ATTR(m2s_birsp_e, CXL_PMU_GID_M2S_BIRSP, BIT(2)), + CXL_PMU_EVENT_CXL_ATTR(m2s_birsp_iblk, CXL_PMU_GID_M2S_BIRSP, BIT(4)), + CXL_PMU_EVENT_CXL_ATTR(m2s_birsp_sblk, CXL_PMU_GID_M2S_BIRSP, BIT(5)), + CXL_PMU_EVENT_CXL_ATTR(m2s_birsp_eblk, CXL_PMU_GID_M2S_BIRSP, BIT(6)), + /* CXL rev 3.0 Table 3-40 S2M BISnp Opcodes */ + CXL_PMU_EVENT_CXL_ATTR(s2m_bisnp_cur, CXL_PMU_GID_S2M_BISNP, BIT(0)), + CXL_PMU_EVENT_CXL_ATTR(s2m_bisnp_data, CXL_PMU_GID_S2M_BISNP, BIT(1)), + CXL_PMU_EVENT_CXL_ATTR(s2m_bisnp_inv, CXL_PMU_GID_S2M_BISNP, BIT(2)), + CXL_PMU_EVENT_CXL_ATTR(s2m_bisnp_curblk, CXL_PMU_GID_S2M_BISNP, BIT(4)), + CXL_PMU_EVENT_CXL_ATTR(s2m_bisnp_datblk, CXL_PMU_GID_S2M_BISNP, BIT(5)), + CXL_PMU_EVENT_CXL_ATTR(s2m_bisnp_invblk, CXL_PMU_GID_S2M_BISNP, BIT(6)), + /* CXL rev 3.0 Table 3-43 S2M NDR Opcopdes */ + CXL_PMU_EVENT_CXL_ATTR(s2m_ndr_cmp, CXL_PMU_GID_S2M_NDR, BIT(0)), + CXL_PMU_EVENT_CXL_ATTR(s2m_ndr_cmps, CXL_PMU_GID_S2M_NDR, BIT(1)), + CXL_PMU_EVENT_CXL_ATTR(s2m_ndr_cmpe, CXL_PMU_GID_S2M_NDR, BIT(2)), + CXL_PMU_EVENT_CXL_ATTR(s2m_ndr_biconflictack, CXL_PMU_GID_S2M_NDR, BIT(3)), + /* CXL rev 3.0 Table 3-46 S2M DRS opcodes */ + CXL_PMU_EVENT_CXL_ATTR(s2m_drs_memdata, CXL_PMU_GID_S2M_DRS, BIT(0)), + CXL_PMU_EVENT_CXL_ATTR(s2m_drs_memdatanxm, CXL_PMU_GID_S2M_DRS, BIT(1)), + /* CXL rev 3.0 Table 13-5 directly lists these */ + CXL_PMU_EVENT_CXL_ATTR(ddr_act, CXL_PMU_GID_DDR, BIT(0)), + CXL_PMU_EVENT_CXL_ATTR(ddr_pre, CXL_PMU_GID_DDR, BIT(1)), + CXL_PMU_EVENT_CXL_ATTR(ddr_casrd, CXL_PMU_GID_DDR, BIT(2)), + CXL_PMU_EVENT_CXL_ATTR(ddr_caswr, CXL_PMU_GID_DDR, BIT(3)), + CXL_PMU_EVENT_CXL_ATTR(ddr_refresh, CXL_PMU_GID_DDR, BIT(4)), + CXL_PMU_EVENT_CXL_ATTR(ddr_selfrefreshent, CXL_PMU_GID_DDR, BIT(5)), + CXL_PMU_EVENT_CXL_ATTR(ddr_rfm, CXL_PMU_GID_DDR, BIT(6)), + NULL +}; + +static struct cxl_pmu_ev_cap *cxl_pmu_find_fixed_counter_ev_cap(struct cxl_pmu_info *info, + int vid, int gid, int msk) +{ + struct cxl_pmu_ev_cap *pmu_ev; + + list_for_each_entry(pmu_ev, &info->event_caps_fixed, node) { + if (vid != pmu_ev->vid || gid != pmu_ev->gid) + continue; + + /* Precise match for fixed counter */ + if (msk == pmu_ev->msk) + return pmu_ev; + } + + return ERR_PTR(-EINVAL); +} + +static struct cxl_pmu_ev_cap *cxl_pmu_find_config_counter_ev_cap(struct cxl_pmu_info *info, + int vid, int gid, int msk) +{ + struct cxl_pmu_ev_cap *pmu_ev; + + list_for_each_entry(pmu_ev, &info->event_caps_configurable, node) { + if (vid != pmu_ev->vid || gid != pmu_ev->gid) + continue; + + /* Request mask must be subset of supported */ + if (msk & ~pmu_ev->msk) + continue; + + return pmu_ev; + } + + return ERR_PTR(-EINVAL); +} + +static umode_t cxl_pmu_event_is_visible(struct kobject *kobj, struct attribute *attr, int a) +{ + struct device_attribute *dev_attr = container_of(attr, struct device_attribute, attr); + struct perf_pmu_events_attr *pmu_attr = + container_of(dev_attr, struct perf_pmu_events_attr, attr); + struct device *dev = kobj_to_dev(kobj); + struct cxl_pmu_info *info = dev_get_drvdata(dev); + int vid = FIELD_GET(CXL_PMU_ATTR_CONFIG_VID_MSK, pmu_attr->id); + int gid = FIELD_GET(CXL_PMU_ATTR_CONFIG_GID_MSK, pmu_attr->id); + int msk = FIELD_GET(CXL_PMU_ATTR_CONFIG_MASK_MSK, pmu_attr->id); + + if (!IS_ERR(cxl_pmu_find_fixed_counter_ev_cap(info, vid, gid, msk))) + return attr->mode; + + if (!IS_ERR(cxl_pmu_find_config_counter_ev_cap(info, vid, gid, msk))) + return attr->mode; + + return 0; +} + +static const struct attribute_group cxl_pmu_events = { + .name = "events", + .attrs = cxl_pmu_event_attrs, + .is_visible = cxl_pmu_event_is_visible, +}; + +static ssize_t cpumask_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct cxl_pmu_info *info = dev_get_drvdata(dev); + + return cpumap_print_to_pagebuf(true, buf, cpumask_of(info->on_cpu)); +} +static DEVICE_ATTR_RO(cpumask); + +static struct attribute *cxl_pmu_cpumask_attrs[] = { + &dev_attr_cpumask.attr, + NULL +}; + +static const struct attribute_group cxl_pmu_cpumask_group = { + .attrs = cxl_pmu_cpumask_attrs, +}; + +static const struct attribute_group *cxl_pmu_attr_groups[] = { + &cxl_pmu_events, + &cxl_pmu_format_group, + &cxl_pmu_cpumask_group, + NULL +}; + +/* If counter_idx == NULL, don't try to allocate a counter. */ +static int cxl_pmu_get_event_idx(struct perf_event *event, int *counter_idx, + int *event_idx) +{ + struct cxl_pmu_info *info = pmu_to_cxl_pmu_info(event->pmu); + DECLARE_BITMAP(configurable_and_free, CXL_PMU_MAX_COUNTERS); + struct cxl_pmu_ev_cap *pmu_ev; + u32 mask; + u16 gid, vid; + int i; + + vid = cxl_pmu_config_get_vid(event); + gid = cxl_pmu_config_get_gid(event); + mask = cxl_pmu_config_get_mask(event); + + pmu_ev = cxl_pmu_find_fixed_counter_ev_cap(info, vid, gid, mask); + if (!IS_ERR(pmu_ev)) { + if (!counter_idx) + return 0; + if (!test_bit(pmu_ev->counter_idx, info->used_counter_bm)) { + *counter_idx = pmu_ev->counter_idx; + return 0; + } + /* Fixed counter is in use, but maybe a configurable one? */ + } + + pmu_ev = cxl_pmu_find_config_counter_ev_cap(info, vid, gid, mask); + if (!IS_ERR(pmu_ev)) { + if (!counter_idx) + return 0; + + bitmap_andnot(configurable_and_free, info->conf_counter_bm, + info->used_counter_bm, CXL_PMU_MAX_COUNTERS); + + i = find_first_bit(configurable_and_free, CXL_PMU_MAX_COUNTERS); + if (i == CXL_PMU_MAX_COUNTERS) + return -EINVAL; + + *counter_idx = i; + return 0; + } + + return -EINVAL; +} + +static int cxl_pmu_event_init(struct perf_event *event) +{ + struct cxl_pmu_info *info = pmu_to_cxl_pmu_info(event->pmu); + int rc; + + /* Top level type sanity check - is this a Hardware Event being requested */ + if (event->attr.type != event->pmu->type) + return -ENOENT; + + if (is_sampling_event(event) || event->attach_state & PERF_ATTACH_TASK) + return -EOPNOTSUPP; + /* TODO: Validation of any filter */ + + /* + * Verify that it is possible to count what was requested. Either must + * be a fixed counter that is a precise match or a configurable counter + * where this is a subset. + */ + rc = cxl_pmu_get_event_idx(event, NULL, NULL); + if (rc < 0) + return rc; + + event->cpu = info->on_cpu; + + return 0; +} + +static void cxl_pmu_enable(struct pmu *pmu) +{ + struct cxl_pmu_info *info = pmu_to_cxl_pmu_info(pmu); + void __iomem *base = info->base; + + /* Can assume frozen at this stage */ + writeq(0, base + CXL_PMU_FREEZE_REG); +} + +static void cxl_pmu_disable(struct pmu *pmu) +{ + struct cxl_pmu_info *info = pmu_to_cxl_pmu_info(pmu); + void __iomem *base = info->base; + + /* + * Whilst bits above number of counters are RsvdZ + * they are unlikely to be repurposed given + * number of counters is allowed to be 64 leaving + * no reserved bits. Hence this is only slightly + * naughty. + */ + writeq(GENMASK_ULL(63, 0), base + CXL_PMU_FREEZE_REG); +} + +static void cxl_pmu_event_start(struct perf_event *event, int flags) +{ + struct cxl_pmu_info *info = pmu_to_cxl_pmu_info(event->pmu); + struct hw_perf_event *hwc = &event->hw; + void __iomem *base = info->base; + u64 cfg; + + /* + * All paths to here should either set these flags directly or + * call cxl_pmu_event_stop() which will ensure the correct state. + */ + if (WARN_ON_ONCE(!(hwc->state & PERF_HES_STOPPED))) + return; + + WARN_ON_ONCE(!(hwc->state & PERF_HES_UPTODATE)); + hwc->state = 0; + + /* + * Currently only hdm filter control is implemnted, this code will + * want generalizing when more filters are added. + */ + if (info->filter_hdm) { + if (cxl_pmu_config1_hdm_filter_en(event)) + cfg = cxl_pmu_config2_get_hdm_decoder(event); + else + cfg = GENMASK(15, 0); /* No filtering if 0xFFFF_FFFF */ + writeq(cfg, base + CXL_PMU_FILTER_CFG_REG(hwc->idx, 0)); + } + + cfg = readq(base + CXL_PMU_COUNTER_CFG_REG(hwc->idx)); + cfg |= FIELD_PREP(CXL_PMU_COUNTER_CFG_INT_ON_OVRFLW, 1); + cfg |= FIELD_PREP(CXL_PMU_COUNTER_CFG_FREEZE_ON_OVRFLW, 1); + cfg |= FIELD_PREP(CXL_PMU_COUNTER_CFG_ENABLE, 1); + cfg |= FIELD_PREP(CXL_PMU_COUNTER_CFG_EDGE, + cxl_pmu_config1_get_edge(event) ? 1 : 0); + cfg |= FIELD_PREP(CXL_PMU_COUNTER_CFG_INVERT, + cxl_pmu_config1_get_invert(event) ? 1 : 0); + + /* Fixed purpose counters have next two fields RO */ + if (test_bit(hwc->idx, info->conf_counter_bm)) { + cfg |= FIELD_PREP(CXL_PMU_COUNTER_CFG_EVENT_GRP_ID_IDX_MSK, + hwc->event_base); + cfg |= FIELD_PREP(CXL_PMU_COUNTER_CFG_EVENTS_MSK, + cxl_pmu_config_get_mask(event)); + } + cfg &= ~CXL_PMU_COUNTER_CFG_THRESHOLD_MSK; + /* + * For events that generate only 1 count per clock the CXL 3.0 spec + * states the threshold shall be set to 1 but if set to 0 it will + * count the raw value anwyay? + * There is no definition of what events will count multiple per cycle + * and hence to which non 1 values of threshold can apply. + * (CXL 3.0 8.2.7.2.1 Counter Configuration - threshold field definition) + */ + cfg |= FIELD_PREP(CXL_PMU_COUNTER_CFG_THRESHOLD_MSK, + cxl_pmu_config1_get_threshold(event)); + writeq(cfg, base + CXL_PMU_COUNTER_CFG_REG(hwc->idx)); + + local64_set(&hwc->prev_count, 0); + writeq(0, base + CXL_PMU_COUNTER_REG(hwc->idx)); + + perf_event_update_userpage(event); +} + +static u64 cxl_pmu_read_counter(struct perf_event *event) +{ + struct cxl_pmu_info *info = pmu_to_cxl_pmu_info(event->pmu); + void __iomem *base = info->base; + + return readq(base + CXL_PMU_COUNTER_REG(event->hw.idx)); +} + +static void __cxl_pmu_read(struct perf_event *event, bool overflow) +{ + struct cxl_pmu_info *info = pmu_to_cxl_pmu_info(event->pmu); + struct hw_perf_event *hwc = &event->hw; + u64 new_cnt, prev_cnt, delta; + + do { + prev_cnt = local64_read(&hwc->prev_count); + new_cnt = cxl_pmu_read_counter(event); + } while (local64_cmpxchg(&hwc->prev_count, prev_cnt, new_cnt) != prev_cnt); + + /* + * If we know an overflow occur then take that into account. + * Note counter is not reset as that would lose events + */ + delta = (new_cnt - prev_cnt) & GENMASK_ULL(info->counter_width - 1, 0); + if (overflow && delta < GENMASK_ULL(info->counter_width - 1, 0)) + delta += (1UL << info->counter_width); + + local64_add(delta, &event->count); +} + +static void cxl_pmu_read(struct perf_event *event) +{ + __cxl_pmu_read(event, false); +} + +static void cxl_pmu_event_stop(struct perf_event *event, int flags) +{ + struct cxl_pmu_info *info = pmu_to_cxl_pmu_info(event->pmu); + void __iomem *base = info->base; + struct hw_perf_event *hwc = &event->hw; + u64 cfg; + + cxl_pmu_read(event); + WARN_ON_ONCE(hwc->state & PERF_HES_STOPPED); + hwc->state |= PERF_HES_STOPPED; + + cfg = readq(base + CXL_PMU_COUNTER_CFG_REG(hwc->idx)); + cfg &= ~(FIELD_PREP(CXL_PMU_COUNTER_CFG_INT_ON_OVRFLW, 1) | + FIELD_PREP(CXL_PMU_COUNTER_CFG_ENABLE, 1)); + writeq(cfg, base + CXL_PMU_COUNTER_CFG_REG(hwc->idx)); + + hwc->state |= PERF_HES_UPTODATE; +} + +static int cxl_pmu_event_add(struct perf_event *event, int flags) +{ + struct cxl_pmu_info *info = pmu_to_cxl_pmu_info(event->pmu); + struct hw_perf_event *hwc = &event->hw; + int idx, rc; + int event_idx = 0; + + hwc->state = PERF_HES_STOPPED | PERF_HES_UPTODATE; + + rc = cxl_pmu_get_event_idx(event, &idx, &event_idx); + if (rc < 0) + return rc; + + hwc->idx = idx; + + /* Only set for configurable counters */ + hwc->event_base = event_idx; + info->hw_events[idx] = event; + set_bit(idx, info->used_counter_bm); + + if (flags & PERF_EF_START) + cxl_pmu_event_start(event, PERF_EF_RELOAD); + + return 0; +} + +static void cxl_pmu_event_del(struct perf_event *event, int flags) +{ + struct cxl_pmu_info *info = pmu_to_cxl_pmu_info(event->pmu); + struct hw_perf_event *hwc = &event->hw; + + cxl_pmu_event_stop(event, PERF_EF_UPDATE); + clear_bit(hwc->idx, info->used_counter_bm); + info->hw_events[hwc->idx] = NULL; + perf_event_update_userpage(event); +} + +static irqreturn_t cxl_pmu_irq(int irq, void *data) +{ + struct cxl_pmu_info *info = data; + void __iomem *base = info->base; + u64 overflowed; + DECLARE_BITMAP(overflowedbm, 64); + int i; + + overflowed = readq(base + CXL_PMU_OVERFLOW_REG); + + /* Interrupt may be shared, so maybe it isn't ours */ + if (!overflowed) + return IRQ_NONE; + + bitmap_from_arr64(overflowedbm, &overflowed, 64); + for_each_set_bit(i, overflowedbm, info->num_counters) { + struct perf_event *event = info->hw_events[i]; + + if (!event) { + dev_dbg(info->pmu.dev, + "overflow but on non enabled counter %d\n", i); + continue; + } + + __cxl_pmu_read(event, true); + } + + writeq(overflowed, base + CXL_PMU_OVERFLOW_REG); + + return IRQ_HANDLED; +} + +static void cxl_pmu_perf_unregister(void *_info) +{ + struct cxl_pmu_info *info = _info; + + perf_pmu_unregister(&info->pmu); +} + +static void cxl_pmu_cpuhp_remove(void *_info) +{ + struct cxl_pmu_info *info = _info; + + cpuhp_state_remove_instance_nocalls(cxl_pmu_cpuhp_state_num, &info->node); +} + +static int cxl_pmu_probe(struct device *dev) +{ + struct cxl_pmu *pmu = to_cxl_pmu(dev); + struct pci_dev *pdev = to_pci_dev(dev->parent); + struct cxl_pmu_info *info; + char *irq_name; + char *dev_name; + int rc, irq; + + info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL); + if (!info) + return -ENOMEM; + + dev_set_drvdata(dev, info); + INIT_LIST_HEAD(&info->event_caps_fixed); + INIT_LIST_HEAD(&info->event_caps_configurable); + + info->base = pmu->base; + + info->on_cpu = -1; + rc = cxl_pmu_parse_caps(dev, info); + if (rc) + return rc; + + info->hw_events = devm_kcalloc(dev, sizeof(*info->hw_events), + info->num_counters, GFP_KERNEL); + if (!info->hw_events) + return -ENOMEM; + + switch (pmu->type) { + case CXL_PMU_MEMDEV: + dev_name = devm_kasprintf(dev, GFP_KERNEL, "cxl_pmu_mem%d.%d", + pmu->assoc_id, pmu->index); + break; + } + if (!dev_name) + return -ENOMEM; + + info->pmu = (struct pmu) { + .name = dev_name, + .parent = dev, + .module = THIS_MODULE, + .event_init = cxl_pmu_event_init, + .pmu_enable = cxl_pmu_enable, + .pmu_disable = cxl_pmu_disable, + .add = cxl_pmu_event_add, + .del = cxl_pmu_event_del, + .start = cxl_pmu_event_start, + .stop = cxl_pmu_event_stop, + .read = cxl_pmu_read, + .task_ctx_nr = perf_invalid_context, + .attr_groups = cxl_pmu_attr_groups, + .capabilities = PERF_PMU_CAP_NO_EXCLUDE, + }; + + if (info->irq <= 0) + return -EINVAL; + + rc = pci_irq_vector(pdev, info->irq); + if (rc < 0) + return rc; + irq = rc; + + irq_name = devm_kasprintf(dev, GFP_KERNEL, "%s_overflow\n", dev_name); + if (!irq_name) + return -ENOMEM; + + rc = devm_request_irq(dev, irq, cxl_pmu_irq, IRQF_SHARED | IRQF_ONESHOT, + irq_name, info); + if (rc) + return rc; + info->irq = irq; + + rc = cpuhp_state_add_instance(cxl_pmu_cpuhp_state_num, &info->node); + if (rc) + return rc; + + rc = devm_add_action_or_reset(dev, cxl_pmu_cpuhp_remove, info); + if (rc) + return rc; + + rc = perf_pmu_register(&info->pmu, info->pmu.name, -1); + if (rc) + return rc; + + rc = devm_add_action_or_reset(dev, cxl_pmu_perf_unregister, info); + if (rc) + return rc; + + return 0; +} + +static struct cxl_driver cxl_pmu_driver = { + .name = "cxl_pmu", + .probe = cxl_pmu_probe, + .id = CXL_DEVICE_PMU, +}; + +static int cxl_pmu_online_cpu(unsigned int cpu, struct hlist_node *node) +{ + struct cxl_pmu_info *info = hlist_entry_safe(node, struct cxl_pmu_info, node); + + if (info->on_cpu != -1) + return 0; + + info->on_cpu = cpu; + /* + * CPU HP lock is held so we should be guaranteed that the CPU hasn't yet + * gone away again. + */ + WARN_ON(irq_set_affinity(info->irq, cpumask_of(cpu))); + + return 0; +} + +static int cxl_pmu_offline_cpu(unsigned int cpu, struct hlist_node *node) +{ + struct cxl_pmu_info *info = hlist_entry_safe(node, struct cxl_pmu_info, node); + unsigned int target; + + if (info->on_cpu != cpu) + return 0; + + info->on_cpu = -1; + target = cpumask_any_but(cpu_online_mask, cpu); + if (target >= nr_cpu_ids) { + dev_err(info->pmu.dev, "Unable to find a suitable CPU\n"); + return 0; + } + + perf_pmu_migrate_context(&info->pmu, cpu, target); + info->on_cpu = target; + /* + * CPU HP lock is held so we should be guaranteed that this CPU hasn't yet + * gone away. + */ + WARN_ON(irq_set_affinity(info->irq, cpumask_of(target))); + + return 0; +} + +static __init int cxl_pmu_init(void) +{ + int rc; + + rc = cpuhp_setup_state_multi(CPUHP_AP_ONLINE_DYN, + "AP_PERF_CXL_PMU_ONLINE", + cxl_pmu_online_cpu, cxl_pmu_offline_cpu); + if (rc < 0) + return rc; + cxl_pmu_cpuhp_state_num = rc; + + rc = cxl_driver_register(&cxl_pmu_driver); + if (rc) + cpuhp_remove_multi_state(cxl_pmu_cpuhp_state_num); + + return rc; +} + +static __exit void cxl_pmu_exit(void) +{ + cxl_driver_unregister(&cxl_pmu_driver); + cpuhp_remove_multi_state(cxl_pmu_cpuhp_state_num); +} + +MODULE_LICENSE("GPL"); +MODULE_IMPORT_NS(CXL); +module_init(cxl_pmu_init); +module_exit(cxl_pmu_exit); +MODULE_ALIAS_CXL(CXL_DEVICE_PMU); diff --git a/drivers/perf/fsl_imx9_ddr_perf.c b/drivers/perf/fsl_imx9_ddr_perf.c new file mode 100644 index 0000000000000000000000000000000000000000..71d5b07e3aff8ce6260fbc75520962fb31b1bb5c --- /dev/null +++ b/drivers/perf/fsl_imx9_ddr_perf.c @@ -0,0 +1,711 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright 2023 NXP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Performance monitor configuration */ +#define PMCFG1 0x00 +#define PMCFG1_RD_TRANS_FILT_EN BIT(31) +#define PMCFG1_WR_TRANS_FILT_EN BIT(30) +#define PMCFG1_RD_BT_FILT_EN BIT(29) +#define PMCFG1_ID_MASK GENMASK(17, 0) + +#define PMCFG2 0x04 +#define PMCFG2_ID GENMASK(17, 0) + +/* Global control register affects all counters and takes priority over local control registers */ +#define PMGC0 0x40 +/* Global control register bits */ +#define PMGC0_FAC BIT(31) +#define PMGC0_PMIE BIT(30) +#define PMGC0_FCECE BIT(29) + +/* + * 64bit counter0 exclusively dedicated to counting cycles + * 32bit counters monitor counter-specific events in addition to counting reference events + */ +#define PMLCA(n) (0x40 + 0x10 + (0x10 * n)) +#define PMLCB(n) (0x40 + 0x14 + (0x10 * n)) +#define PMC(n) (0x40 + 0x18 + (0x10 * n)) +/* Local control register bits */ +#define PMLCA_FC BIT(31) +#define PMLCA_CE BIT(26) +#define PMLCA_EVENT GENMASK(22, 16) + +#define NUM_COUNTERS 11 +#define CYCLES_COUNTER 0 + +#define to_ddr_pmu(p) container_of(p, struct ddr_pmu, pmu) + +#define DDR_PERF_DEV_NAME "imx9_ddr" +#define DDR_CPUHP_CB_NAME DDR_PERF_DEV_NAME "_perf_pmu" + +static DEFINE_IDA(ddr_ida); + +struct imx_ddr_devtype_data { + const char *identifier; /* system PMU identifier for userspace */ +}; + +struct ddr_pmu { + struct pmu pmu; + void __iomem *base; + unsigned int cpu; + struct hlist_node node; + struct device *dev; + struct perf_event *events[NUM_COUNTERS]; + int active_events; + enum cpuhp_state cpuhp_state; + const struct imx_ddr_devtype_data *devtype_data; + int irq; + int id; +}; + +static const struct imx_ddr_devtype_data imx93_devtype_data = { + .identifier = "imx93", +}; + +static const struct of_device_id imx_ddr_pmu_dt_ids[] = { + {.compatible = "fsl,imx93-ddr-pmu", .data = &imx93_devtype_data}, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, imx_ddr_pmu_dt_ids); + +static ssize_t ddr_perf_identifier_show(struct device *dev, + struct device_attribute *attr, + char *page) +{ + struct ddr_pmu *pmu = dev_get_drvdata(dev); + + return sysfs_emit(page, "%s\n", pmu->devtype_data->identifier); +} + +static struct device_attribute ddr_perf_identifier_attr = + __ATTR(identifier, 0444, ddr_perf_identifier_show, NULL); + +static struct attribute *ddr_perf_identifier_attrs[] = { + &ddr_perf_identifier_attr.attr, + NULL, +}; + +static struct attribute_group ddr_perf_identifier_attr_group = { + .attrs = ddr_perf_identifier_attrs, +}; + +static ssize_t ddr_perf_cpumask_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct ddr_pmu *pmu = dev_get_drvdata(dev); + + return cpumap_print_to_pagebuf(true, buf, cpumask_of(pmu->cpu)); +} + +static struct device_attribute ddr_perf_cpumask_attr = + __ATTR(cpumask, 0444, ddr_perf_cpumask_show, NULL); + +static struct attribute *ddr_perf_cpumask_attrs[] = { + &ddr_perf_cpumask_attr.attr, + NULL, +}; + +static const struct attribute_group ddr_perf_cpumask_attr_group = { + .attrs = ddr_perf_cpumask_attrs, +}; + +static ssize_t ddr_pmu_event_show(struct device *dev, + struct device_attribute *attr, char *page) +{ + struct perf_pmu_events_attr *pmu_attr; + + pmu_attr = container_of(attr, struct perf_pmu_events_attr, attr); + return sysfs_emit(page, "event=0x%02llx\n", pmu_attr->id); +} + +#define IMX9_DDR_PMU_EVENT_ATTR(_name, _id) \ + (&((struct perf_pmu_events_attr[]) { \ + { .attr = __ATTR(_name, 0444, ddr_pmu_event_show, NULL),\ + .id = _id, } \ + })[0].attr.attr) + +static struct attribute *ddr_perf_events_attrs[] = { + /* counter0 cycles event */ + IMX9_DDR_PMU_EVENT_ATTR(cycles, 0), + + /* reference events for all normal counters, need assert DEBUG19[21] bit */ + IMX9_DDR_PMU_EVENT_ATTR(ddrc_ddrc1_rmw_for_ecc, 12), + IMX9_DDR_PMU_EVENT_ATTR(eddrtq_pmon_rreorder, 13), + IMX9_DDR_PMU_EVENT_ATTR(eddrtq_pmon_wreorder, 14), + IMX9_DDR_PMU_EVENT_ATTR(ddrc_pm_0, 15), + IMX9_DDR_PMU_EVENT_ATTR(ddrc_pm_1, 16), + IMX9_DDR_PMU_EVENT_ATTR(ddrc_pm_2, 17), + IMX9_DDR_PMU_EVENT_ATTR(ddrc_pm_3, 18), + IMX9_DDR_PMU_EVENT_ATTR(ddrc_pm_4, 19), + IMX9_DDR_PMU_EVENT_ATTR(ddrc_pm_5, 22), + IMX9_DDR_PMU_EVENT_ATTR(ddrc_pm_6, 23), + IMX9_DDR_PMU_EVENT_ATTR(ddrc_pm_7, 24), + IMX9_DDR_PMU_EVENT_ATTR(ddrc_pm_8, 25), + IMX9_DDR_PMU_EVENT_ATTR(ddrc_pm_9, 26), + IMX9_DDR_PMU_EVENT_ATTR(ddrc_pm_10, 27), + IMX9_DDR_PMU_EVENT_ATTR(ddrc_pm_11, 28), + IMX9_DDR_PMU_EVENT_ATTR(ddrc_pm_12, 31), + IMX9_DDR_PMU_EVENT_ATTR(ddrc_pm_13, 59), + IMX9_DDR_PMU_EVENT_ATTR(ddrc_pm_15, 61), + IMX9_DDR_PMU_EVENT_ATTR(ddrc_pm_29, 63), + + /* counter1 specific events */ + IMX9_DDR_PMU_EVENT_ATTR(ddrc_ld_riq_0, 64), + IMX9_DDR_PMU_EVENT_ATTR(ddrc_ld_riq_1, 65), + IMX9_DDR_PMU_EVENT_ATTR(ddrc_ld_riq_2, 66), + IMX9_DDR_PMU_EVENT_ATTR(ddrc_ld_riq_3, 67), + IMX9_DDR_PMU_EVENT_ATTR(ddrc_ld_riq_4, 68), + IMX9_DDR_PMU_EVENT_ATTR(ddrc_ld_riq_5, 69), + IMX9_DDR_PMU_EVENT_ATTR(ddrc_ld_riq_6, 70), + IMX9_DDR_PMU_EVENT_ATTR(ddrc_ld_riq_7, 71), + + /* counter2 specific events */ + IMX9_DDR_PMU_EVENT_ATTR(ddrc_ld_wiq_0, 64), + IMX9_DDR_PMU_EVENT_ATTR(ddrc_ld_wiq_1, 65), + IMX9_DDR_PMU_EVENT_ATTR(ddrc_ld_wiq_2, 66), + IMX9_DDR_PMU_EVENT_ATTR(ddrc_ld_wiq_3, 67), + IMX9_DDR_PMU_EVENT_ATTR(ddrc_ld_wiq_4, 68), + IMX9_DDR_PMU_EVENT_ATTR(ddrc_ld_wiq_5, 69), + IMX9_DDR_PMU_EVENT_ATTR(ddrc_ld_wiq_6, 70), + IMX9_DDR_PMU_EVENT_ATTR(ddrc_ld_wiq_7, 71), + IMX9_DDR_PMU_EVENT_ATTR(eddrtq_pmon_empty, 72), + IMX9_DDR_PMU_EVENT_ATTR(eddrtq_pm_rd_trans_filt, 73), + + /* counter3 specific events */ + IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_row_collision_0, 64), + IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_row_collision_1, 65), + IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_row_collision_2, 66), + IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_row_collision_3, 67), + IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_row_collision_4, 68), + IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_row_collision_5, 69), + IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_row_collision_6, 70), + IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_row_collision_7, 71), + IMX9_DDR_PMU_EVENT_ATTR(eddrtq_pmon_full, 72), + IMX9_DDR_PMU_EVENT_ATTR(eddrtq_pm_wr_trans_filt, 73), + + /* counter4 specific events */ + IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_row_open_0, 64), + IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_row_open_1, 65), + IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_row_open_2, 66), + IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_row_open_3, 67), + IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_row_open_4, 68), + IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_row_open_5, 69), + IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_row_open_6, 70), + IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_row_open_7, 71), + IMX9_DDR_PMU_EVENT_ATTR(eddrtq_pmon_ld_rdq2_rmw, 72), + IMX9_DDR_PMU_EVENT_ATTR(eddrtq_pm_rd_beat_filt, 73), + + /* counter5 specific events */ + IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_valid_start_0, 64), + IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_valid_start_1, 65), + IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_valid_start_2, 66), + IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_valid_start_3, 67), + IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_valid_start_4, 68), + IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_valid_start_5, 69), + IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_valid_start_6, 70), + IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_valid_start_7, 71), + IMX9_DDR_PMU_EVENT_ATTR(eddrtq_pmon_ld_rdq1, 72), + + /* counter6 specific events */ + IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_valid_end_0, 64), + IMX9_DDR_PMU_EVENT_ATTR(eddrtq_pmon_ld_rdq2, 72), + + /* counter7 specific events */ + IMX9_DDR_PMU_EVENT_ATTR(eddrtq_pmon_1_2_full, 64), + IMX9_DDR_PMU_EVENT_ATTR(eddrtq_pmon_ld_wrq0, 65), + + /* counter8 specific events */ + IMX9_DDR_PMU_EVENT_ATTR(eddrtq_pmon_bias_switched, 64), + IMX9_DDR_PMU_EVENT_ATTR(eddrtq_pmon_1_4_full, 65), + + /* counter9 specific events */ + IMX9_DDR_PMU_EVENT_ATTR(eddrtq_pmon_ld_wrq1, 65), + IMX9_DDR_PMU_EVENT_ATTR(eddrtq_pmon_3_4_full, 66), + + /* counter10 specific events */ + IMX9_DDR_PMU_EVENT_ATTR(eddrtq_pmon_misc_mrk, 65), + IMX9_DDR_PMU_EVENT_ATTR(eddrtq_pmon_ld_rdq0, 66), + NULL, +}; + +static const struct attribute_group ddr_perf_events_attr_group = { + .name = "events", + .attrs = ddr_perf_events_attrs, +}; + +PMU_FORMAT_ATTR(event, "config:0-7"); +PMU_FORMAT_ATTR(counter, "config:8-15"); +PMU_FORMAT_ATTR(axi_id, "config1:0-17"); +PMU_FORMAT_ATTR(axi_mask, "config2:0-17"); + +static struct attribute *ddr_perf_format_attrs[] = { + &format_attr_event.attr, + &format_attr_counter.attr, + &format_attr_axi_id.attr, + &format_attr_axi_mask.attr, + NULL, +}; + +static const struct attribute_group ddr_perf_format_attr_group = { + .name = "format", + .attrs = ddr_perf_format_attrs, +}; + +static const struct attribute_group *attr_groups[] = { + &ddr_perf_identifier_attr_group, + &ddr_perf_cpumask_attr_group, + &ddr_perf_events_attr_group, + &ddr_perf_format_attr_group, + NULL, +}; + +static void ddr_perf_clear_counter(struct ddr_pmu *pmu, int counter) +{ + if (counter == CYCLES_COUNTER) { + writel(0, pmu->base + PMC(counter) + 0x4); + writel(0, pmu->base + PMC(counter)); + } else { + writel(0, pmu->base + PMC(counter)); + } +} + +static u64 ddr_perf_read_counter(struct ddr_pmu *pmu, int counter) +{ + u32 val_lower, val_upper; + u64 val; + + if (counter != CYCLES_COUNTER) { + val = readl_relaxed(pmu->base + PMC(counter)); + goto out; + } + + /* special handling for reading 64bit cycle counter */ + do { + val_upper = readl_relaxed(pmu->base + PMC(counter) + 0x4); + val_lower = readl_relaxed(pmu->base + PMC(counter)); + } while (val_upper != readl_relaxed(pmu->base + PMC(counter) + 0x4)); + + val = val_upper; + val = (val << 32); + val |= val_lower; +out: + return val; +} + +static void ddr_perf_counter_global_config(struct ddr_pmu *pmu, bool enable) +{ + u32 ctrl; + + ctrl = readl_relaxed(pmu->base + PMGC0); + + if (enable) { + /* + * The performance monitor must be reset before event counting + * sequences. The performance monitor can be reset by first freezing + * one or more counters and then clearing the freeze condition to + * allow the counters to count according to the settings in the + * performance monitor registers. Counters can be frozen individually + * by setting PMLCAn[FC] bits, or simultaneously by setting PMGC0[FAC]. + * Simply clearing these freeze bits will then allow the performance + * monitor to begin counting based on the register settings. + */ + ctrl |= PMGC0_FAC; + writel(ctrl, pmu->base + PMGC0); + + /* + * Freeze all counters disabled, interrupt enabled, and freeze + * counters on condition enabled. + */ + ctrl &= ~PMGC0_FAC; + ctrl |= PMGC0_PMIE | PMGC0_FCECE; + writel(ctrl, pmu->base + PMGC0); + } else { + ctrl |= PMGC0_FAC; + ctrl &= ~(PMGC0_PMIE | PMGC0_FCECE); + writel(ctrl, pmu->base + PMGC0); + } +} + +static void ddr_perf_counter_local_config(struct ddr_pmu *pmu, int config, + int counter, bool enable) +{ + u32 ctrl_a; + + ctrl_a = readl_relaxed(pmu->base + PMLCA(counter)); + + if (enable) { + ctrl_a |= PMLCA_FC; + writel(ctrl_a, pmu->base + PMLCA(counter)); + + ddr_perf_clear_counter(pmu, counter); + + /* Freeze counter disabled, condition enabled, and program event.*/ + ctrl_a &= ~PMLCA_FC; + ctrl_a |= PMLCA_CE; + ctrl_a &= ~FIELD_PREP(PMLCA_EVENT, 0x7F); + ctrl_a |= FIELD_PREP(PMLCA_EVENT, (config & 0x000000FF)); + writel(ctrl_a, pmu->base + PMLCA(counter)); + } else { + /* Freeze counter. */ + ctrl_a |= PMLCA_FC; + writel(ctrl_a, pmu->base + PMLCA(counter)); + } +} + +static void ddr_perf_monitor_config(struct ddr_pmu *pmu, int cfg, int cfg1, int cfg2) +{ + u32 pmcfg1, pmcfg2; + int event, counter; + + event = cfg & 0x000000FF; + counter = (cfg & 0x0000FF00) >> 8; + + pmcfg1 = readl_relaxed(pmu->base + PMCFG1); + + if (counter == 2 && event == 73) + pmcfg1 |= PMCFG1_RD_TRANS_FILT_EN; + else if (counter == 2 && event != 73) + pmcfg1 &= ~PMCFG1_RD_TRANS_FILT_EN; + + if (counter == 3 && event == 73) + pmcfg1 |= PMCFG1_WR_TRANS_FILT_EN; + else if (counter == 3 && event != 73) + pmcfg1 &= ~PMCFG1_WR_TRANS_FILT_EN; + + if (counter == 4 && event == 73) + pmcfg1 |= PMCFG1_RD_BT_FILT_EN; + else if (counter == 4 && event != 73) + pmcfg1 &= ~PMCFG1_RD_BT_FILT_EN; + + pmcfg1 &= ~FIELD_PREP(PMCFG1_ID_MASK, 0x3FFFF); + pmcfg1 |= FIELD_PREP(PMCFG1_ID_MASK, cfg2); + writel(pmcfg1, pmu->base + PMCFG1); + + pmcfg2 = readl_relaxed(pmu->base + PMCFG2); + pmcfg2 &= ~FIELD_PREP(PMCFG2_ID, 0x3FFFF); + pmcfg2 |= FIELD_PREP(PMCFG2_ID, cfg1); + writel(pmcfg2, pmu->base + PMCFG2); +} + +static void ddr_perf_event_update(struct perf_event *event) +{ + struct ddr_pmu *pmu = to_ddr_pmu(event->pmu); + struct hw_perf_event *hwc = &event->hw; + int counter = hwc->idx; + u64 new_raw_count; + + new_raw_count = ddr_perf_read_counter(pmu, counter); + local64_add(new_raw_count, &event->count); + + /* clear counter's value every time */ + ddr_perf_clear_counter(pmu, counter); +} + +static int ddr_perf_event_init(struct perf_event *event) +{ + struct ddr_pmu *pmu = to_ddr_pmu(event->pmu); + struct hw_perf_event *hwc = &event->hw; + struct perf_event *sibling; + + if (event->attr.type != event->pmu->type) + return -ENOENT; + + if (is_sampling_event(event) || event->attach_state & PERF_ATTACH_TASK) + return -EOPNOTSUPP; + + if (event->cpu < 0) { + dev_warn(pmu->dev, "Can't provide per-task data!\n"); + return -EOPNOTSUPP; + } + + /* + * We must NOT create groups containing mixed PMUs, although software + * events are acceptable (for example to create a CCN group + * periodically read when a hrtimer aka cpu-clock leader triggers). + */ + if (event->group_leader->pmu != event->pmu && + !is_software_event(event->group_leader)) + return -EINVAL; + + for_each_sibling_event(sibling, event->group_leader) { + if (sibling->pmu != event->pmu && + !is_software_event(sibling)) + return -EINVAL; + } + + event->cpu = pmu->cpu; + hwc->idx = -1; + + return 0; +} + +static void ddr_perf_event_start(struct perf_event *event, int flags) +{ + struct ddr_pmu *pmu = to_ddr_pmu(event->pmu); + struct hw_perf_event *hwc = &event->hw; + int counter = hwc->idx; + + local64_set(&hwc->prev_count, 0); + + ddr_perf_counter_local_config(pmu, event->attr.config, counter, true); + hwc->state = 0; +} + +static int ddr_perf_event_add(struct perf_event *event, int flags) +{ + struct ddr_pmu *pmu = to_ddr_pmu(event->pmu); + struct hw_perf_event *hwc = &event->hw; + int cfg = event->attr.config; + int cfg1 = event->attr.config1; + int cfg2 = event->attr.config2; + int counter; + + counter = (cfg & 0x0000FF00) >> 8; + + pmu->events[counter] = event; + pmu->active_events++; + hwc->idx = counter; + hwc->state |= PERF_HES_STOPPED; + + if (flags & PERF_EF_START) + ddr_perf_event_start(event, flags); + + /* read trans, write trans, read beat */ + ddr_perf_monitor_config(pmu, cfg, cfg1, cfg2); + + return 0; +} + +static void ddr_perf_event_stop(struct perf_event *event, int flags) +{ + struct ddr_pmu *pmu = to_ddr_pmu(event->pmu); + struct hw_perf_event *hwc = &event->hw; + int counter = hwc->idx; + + ddr_perf_counter_local_config(pmu, event->attr.config, counter, false); + ddr_perf_event_update(event); + + hwc->state |= PERF_HES_STOPPED; +} + +static void ddr_perf_event_del(struct perf_event *event, int flags) +{ + struct ddr_pmu *pmu = to_ddr_pmu(event->pmu); + struct hw_perf_event *hwc = &event->hw; + + ddr_perf_event_stop(event, PERF_EF_UPDATE); + + pmu->active_events--; + hwc->idx = -1; +} + +static void ddr_perf_pmu_enable(struct pmu *pmu) +{ + struct ddr_pmu *ddr_pmu = to_ddr_pmu(pmu); + + ddr_perf_counter_global_config(ddr_pmu, true); +} + +static void ddr_perf_pmu_disable(struct pmu *pmu) +{ + struct ddr_pmu *ddr_pmu = to_ddr_pmu(pmu); + + ddr_perf_counter_global_config(ddr_pmu, false); +} + +static void ddr_perf_init(struct ddr_pmu *pmu, void __iomem *base, + struct device *dev) +{ + *pmu = (struct ddr_pmu) { + .pmu = (struct pmu) { + .module = THIS_MODULE, + .capabilities = PERF_PMU_CAP_NO_EXCLUDE, + .task_ctx_nr = perf_invalid_context, + .attr_groups = attr_groups, + .event_init = ddr_perf_event_init, + .add = ddr_perf_event_add, + .del = ddr_perf_event_del, + .start = ddr_perf_event_start, + .stop = ddr_perf_event_stop, + .read = ddr_perf_event_update, + .pmu_enable = ddr_perf_pmu_enable, + .pmu_disable = ddr_perf_pmu_disable, + }, + .base = base, + .dev = dev, + }; +} + +static irqreturn_t ddr_perf_irq_handler(int irq, void *p) +{ + struct ddr_pmu *pmu = (struct ddr_pmu *)p; + struct perf_event *event; + int i; + + /* + * Counters can generate an interrupt on an overflow when msb of a + * counter changes from 0 to 1. For the interrupt to be signalled, + * below condition mush be satisfied: + * PMGC0[PMIE] = 1, PMGC0[FCECE] = 1, PMLCAn[CE] = 1 + * When an interrupt is signalled, PMGC0[FAC] is set by hardware and + * all of the registers are frozen. + * Software can clear the interrupt condition by resetting the performance + * monitor and clearing the most significant bit of the counter that + * generate the overflow. + */ + for (i = 0; i < NUM_COUNTERS; i++) { + if (!pmu->events[i]) + continue; + + event = pmu->events[i]; + + ddr_perf_event_update(event); + } + + ddr_perf_counter_global_config(pmu, true); + + return IRQ_HANDLED; +} + +static int ddr_perf_offline_cpu(unsigned int cpu, struct hlist_node *node) +{ + struct ddr_pmu *pmu = hlist_entry_safe(node, struct ddr_pmu, node); + int target; + + if (cpu != pmu->cpu) + return 0; + + target = cpumask_any_but(cpu_online_mask, cpu); + if (target >= nr_cpu_ids) + return 0; + + perf_pmu_migrate_context(&pmu->pmu, cpu, target); + pmu->cpu = target; + + WARN_ON(irq_set_affinity(pmu->irq, cpumask_of(pmu->cpu))); + + return 0; +} + +static int ddr_perf_probe(struct platform_device *pdev) +{ + struct ddr_pmu *pmu; + void __iomem *base; + int ret, irq; + char *name; + + base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(base)) + return PTR_ERR(base); + + pmu = devm_kzalloc(&pdev->dev, sizeof(*pmu), GFP_KERNEL); + if (!pmu) + return -ENOMEM; + + ddr_perf_init(pmu, base, &pdev->dev); + + pmu->devtype_data = of_device_get_match_data(&pdev->dev); + + platform_set_drvdata(pdev, pmu); + + pmu->id = ida_simple_get(&ddr_ida, 0, 0, GFP_KERNEL); + name = devm_kasprintf(&pdev->dev, GFP_KERNEL, DDR_PERF_DEV_NAME "%d", pmu->id); + if (!name) { + ret = -ENOMEM; + goto format_string_err; + } + + pmu->cpu = raw_smp_processor_id(); + ret = cpuhp_setup_state_multi(CPUHP_AP_ONLINE_DYN, DDR_CPUHP_CB_NAME, + NULL, ddr_perf_offline_cpu); + if (ret < 0) { + dev_err(&pdev->dev, "Failed to add callbacks for multi state\n"); + goto cpuhp_state_err; + } + pmu->cpuhp_state = ret; + + /* Register the pmu instance for cpu hotplug */ + ret = cpuhp_state_add_instance_nocalls(pmu->cpuhp_state, &pmu->node); + if (ret) { + dev_err(&pdev->dev, "Error %d registering hotplug\n", ret); + goto cpuhp_instance_err; + } + + /* Request irq */ + irq = platform_get_irq(pdev, 0); + if (irq < 0) { + ret = irq; + goto ddr_perf_err; + } + + ret = devm_request_irq(&pdev->dev, irq, ddr_perf_irq_handler, + IRQF_NOBALANCING | IRQF_NO_THREAD, + DDR_CPUHP_CB_NAME, pmu); + if (ret < 0) { + dev_err(&pdev->dev, "Request irq failed: %d", ret); + goto ddr_perf_err; + } + + pmu->irq = irq; + ret = irq_set_affinity(pmu->irq, cpumask_of(pmu->cpu)); + if (ret) { + dev_err(pmu->dev, "Failed to set interrupt affinity\n"); + goto ddr_perf_err; + } + + ret = perf_pmu_register(&pmu->pmu, name, -1); + if (ret) + goto ddr_perf_err; + + return 0; + +ddr_perf_err: + cpuhp_state_remove_instance_nocalls(pmu->cpuhp_state, &pmu->node); +cpuhp_instance_err: + cpuhp_remove_multi_state(pmu->cpuhp_state); +cpuhp_state_err: +format_string_err: + ida_simple_remove(&ddr_ida, pmu->id); + dev_warn(&pdev->dev, "i.MX9 DDR Perf PMU failed (%d), disabled\n", ret); + return ret; +} + +static int ddr_perf_remove(struct platform_device *pdev) +{ + struct ddr_pmu *pmu = platform_get_drvdata(pdev); + + cpuhp_state_remove_instance_nocalls(pmu->cpuhp_state, &pmu->node); + cpuhp_remove_multi_state(pmu->cpuhp_state); + + perf_pmu_unregister(&pmu->pmu); + + ida_simple_remove(&ddr_ida, pmu->id); + + return 0; +} + +static struct platform_driver imx_ddr_pmu_driver = { + .driver = { + .name = "imx9-ddr-pmu", + .of_match_table = imx_ddr_pmu_dt_ids, + .suppress_bind_attrs = true, + }, + .probe = ddr_perf_probe, + .remove = ddr_perf_remove, +}; +module_platform_driver(imx_ddr_pmu_driver); + +MODULE_AUTHOR("Xu Yang "); +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("DDRC PerfMon for i.MX9 SoCs"); diff --git a/drivers/perf/hisilicon/Makefile b/drivers/perf/hisilicon/Makefile index 4d2c9abe3372fd579dd54ded10139ef04d188849..48dcc8381ea75dcff819ca29dc45ce58fd4c4531 100644 --- a/drivers/perf/hisilicon/Makefile +++ b/drivers/perf/hisilicon/Makefile @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0-only obj-$(CONFIG_HISI_PMU) += hisi_uncore_pmu.o hisi_uncore_l3c_pmu.o \ hisi_uncore_hha_pmu.o hisi_uncore_ddrc_pmu.o hisi_uncore_sllc_pmu.o \ - hisi_uncore_pa_pmu.o hisi_uncore_cpa_pmu.o + hisi_uncore_pa_pmu.o hisi_uncore_cpa_pmu.o hisi_uncore_uc_pmu.o obj-$(CONFIG_HISI_PCIE_PMU) += hisi_pcie_pmu.o obj-$(CONFIG_HNS3_PMU) += hns3_pmu.o diff --git a/drivers/perf/hisilicon/hisi_pcie_pmu.c b/drivers/perf/hisilicon/hisi_pcie_pmu.c index 6fee0b6e163bb5338ebbfde92e483b844aeeb76d..e10fc7cb9493a96f4f340b6fa823198bbce8ceab 100644 --- a/drivers/perf/hisilicon/hisi_pcie_pmu.c +++ b/drivers/perf/hisilicon/hisi_pcie_pmu.c @@ -683,7 +683,7 @@ static int hisi_pcie_pmu_offline_cpu(unsigned int cpu, struct hlist_node *node) pcie_pmu->on_cpu = -1; /* Choose a new CPU from all online cpus. */ - target = cpumask_first(cpu_online_mask); + target = cpumask_any_but(cpu_online_mask, cpu); if (target >= nr_cpu_ids) { pci_err(pcie_pmu->pdev, "There is no CPU to set\n"); return 0; diff --git a/drivers/perf/hisilicon/hisi_uncore_pa_pmu.c b/drivers/perf/hisilicon/hisi_uncore_pa_pmu.c index 71b6687d669606b8f34876d91d0d147f71b75711..d941e746b42483069a59cb0290f33de2d4dc6761 100644 --- a/drivers/perf/hisilicon/hisi_uncore_pa_pmu.c +++ b/drivers/perf/hisilicon/hisi_uncore_pa_pmu.c @@ -22,9 +22,15 @@ #define PA_TT_CTRL 0x1c08 #define PA_TGTID_CTRL 0x1c14 #define PA_SRCID_CTRL 0x1c18 + +/* H32 PA interrupt registers */ #define PA_INT_MASK 0x1c70 #define PA_INT_STATUS 0x1c78 #define PA_INT_CLEAR 0x1c7c + +#define H60PA_INT_STATUS 0x1c70 +#define H60PA_INT_MASK 0x1c74 + #define PA_EVENT_TYPE0 0x1c80 #define PA_PMU_VERSION 0x1cf0 #define PA_EVENT_CNT0_L 0x1d00 @@ -46,6 +52,12 @@ HISI_PMU_EVENT_ATTR_EXTRACTOR(srcid_cmd, config1, 32, 22); HISI_PMU_EVENT_ATTR_EXTRACTOR(srcid_msk, config1, 43, 33); HISI_PMU_EVENT_ATTR_EXTRACTOR(tracetag_en, config1, 44, 44); +struct hisi_pa_pmu_int_regs { + u32 mask_offset; + u32 clear_offset; + u32 status_offset; +}; + static void hisi_pa_pmu_enable_tracetag(struct perf_event *event) { struct hisi_pmu *pa_pmu = to_hisi_pmu(event->pmu); @@ -219,40 +231,40 @@ static void hisi_pa_pmu_disable_counter(struct hisi_pmu *pa_pmu, static void hisi_pa_pmu_enable_counter_int(struct hisi_pmu *pa_pmu, struct hw_perf_event *hwc) { + struct hisi_pa_pmu_int_regs *regs = pa_pmu->dev_info->private; u32 val; /* Write 0 to enable interrupt */ - val = readl(pa_pmu->base + PA_INT_MASK); + val = readl(pa_pmu->base + regs->mask_offset); val &= ~(1 << hwc->idx); - writel(val, pa_pmu->base + PA_INT_MASK); + writel(val, pa_pmu->base + regs->mask_offset); } static void hisi_pa_pmu_disable_counter_int(struct hisi_pmu *pa_pmu, struct hw_perf_event *hwc) { + struct hisi_pa_pmu_int_regs *regs = pa_pmu->dev_info->private; u32 val; /* Write 1 to mask interrupt */ - val = readl(pa_pmu->base + PA_INT_MASK); + val = readl(pa_pmu->base + regs->mask_offset); val |= 1 << hwc->idx; - writel(val, pa_pmu->base + PA_INT_MASK); + writel(val, pa_pmu->base + regs->mask_offset); } static u32 hisi_pa_pmu_get_int_status(struct hisi_pmu *pa_pmu) { - return readl(pa_pmu->base + PA_INT_STATUS); + struct hisi_pa_pmu_int_regs *regs = pa_pmu->dev_info->private; + + return readl(pa_pmu->base + regs->status_offset); } static void hisi_pa_pmu_clear_int_status(struct hisi_pmu *pa_pmu, int idx) { - writel(1 << idx, pa_pmu->base + PA_INT_CLEAR); -} + struct hisi_pa_pmu_int_regs *regs = pa_pmu->dev_info->private; -static const struct acpi_device_id hisi_pa_pmu_acpi_match[] = { - { "HISI0273", }, - {} -}; -MODULE_DEVICE_TABLE(acpi, hisi_pa_pmu_acpi_match); + writel(1 << idx, pa_pmu->base + regs->clear_offset); +} static int hisi_pa_pmu_init_data(struct platform_device *pdev, struct hisi_pmu *pa_pmu) @@ -276,6 +288,10 @@ static int hisi_pa_pmu_init_data(struct platform_device *pdev, pa_pmu->ccl_id = -1; pa_pmu->sccl_id = -1; + pa_pmu->dev_info = device_get_match_data(&pdev->dev); + if (!pa_pmu->dev_info) + return -ENODEV; + pa_pmu->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(pa_pmu->base)) { dev_err(&pdev->dev, "ioremap failed for pa_pmu resource.\n"); @@ -314,6 +330,32 @@ static const struct attribute_group hisi_pa_pmu_v2_events_group = { .attrs = hisi_pa_pmu_v2_events_attr, }; +static struct attribute *hisi_pa_pmu_v3_events_attr[] = { + HISI_PMU_EVENT_ATTR(tx_req, 0x0), + HISI_PMU_EVENT_ATTR(tx_dat, 0x1), + HISI_PMU_EVENT_ATTR(tx_snp, 0x2), + HISI_PMU_EVENT_ATTR(rx_req, 0x7), + HISI_PMU_EVENT_ATTR(rx_dat, 0x8), + HISI_PMU_EVENT_ATTR(rx_snp, 0x9), + NULL +}; + +static const struct attribute_group hisi_pa_pmu_v3_events_group = { + .name = "events", + .attrs = hisi_pa_pmu_v3_events_attr, +}; + +static struct attribute *hisi_h60pa_pmu_events_attr[] = { + HISI_PMU_EVENT_ATTR(rx_flit, 0x50), + HISI_PMU_EVENT_ATTR(tx_flit, 0x65), + NULL +}; + +static const struct attribute_group hisi_h60pa_pmu_events_group = { + .name = "events", + .attrs = hisi_h60pa_pmu_events_attr, +}; + static DEVICE_ATTR(cpumask, 0444, hisi_cpumask_sysfs_show, NULL); static struct attribute *hisi_pa_pmu_cpumask_attrs[] = { @@ -337,6 +379,12 @@ static const struct attribute_group hisi_pa_pmu_identifier_group = { .attrs = hisi_pa_pmu_identifier_attrs, }; +static struct hisi_pa_pmu_int_regs hisi_pa_pmu_regs = { + .mask_offset = PA_INT_MASK, + .clear_offset = PA_INT_CLEAR, + .status_offset = PA_INT_STATUS, +}; + static const struct attribute_group *hisi_pa_pmu_v2_attr_groups[] = { &hisi_pa_pmu_v2_format_group, &hisi_pa_pmu_v2_events_group, @@ -345,6 +393,46 @@ static const struct attribute_group *hisi_pa_pmu_v2_attr_groups[] = { NULL }; +static const struct hisi_pmu_dev_info hisi_h32pa_v2 = { + .name = "pa", + .attr_groups = hisi_pa_pmu_v2_attr_groups, + .private = &hisi_pa_pmu_regs, +}; + +static const struct attribute_group *hisi_pa_pmu_v3_attr_groups[] = { + &hisi_pa_pmu_v2_format_group, + &hisi_pa_pmu_v3_events_group, + &hisi_pa_pmu_cpumask_attr_group, + &hisi_pa_pmu_identifier_group, + NULL +}; + +static const struct hisi_pmu_dev_info hisi_h32pa_v3 = { + .name = "pa", + .attr_groups = hisi_pa_pmu_v3_attr_groups, + .private = &hisi_pa_pmu_regs, +}; + +static struct hisi_pa_pmu_int_regs hisi_h60pa_pmu_regs = { + .mask_offset = H60PA_INT_MASK, + .clear_offset = H60PA_INT_STATUS, /* Clear on write */ + .status_offset = H60PA_INT_STATUS, +}; + +static const struct attribute_group *hisi_h60pa_pmu_attr_groups[] = { + &hisi_pa_pmu_v2_format_group, + &hisi_h60pa_pmu_events_group, + &hisi_pa_pmu_cpumask_attr_group, + &hisi_pa_pmu_identifier_group, + NULL +}; + +static const struct hisi_pmu_dev_info hisi_h60pa = { + .name = "h60pa", + .attr_groups = hisi_h60pa_pmu_attr_groups, + .private = &hisi_h60pa_pmu_regs, +}; + static const struct hisi_uncore_ops hisi_uncore_pa_ops = { .write_evtype = hisi_pa_pmu_write_evtype, .get_event_idx = hisi_uncore_pmu_get_event_idx, @@ -375,7 +463,7 @@ static int hisi_pa_pmu_dev_probe(struct platform_device *pdev, if (ret) return ret; - pa_pmu->pmu_events.attr_groups = hisi_pa_pmu_v2_attr_groups; + pa_pmu->pmu_events.attr_groups = pa_pmu->dev_info->attr_groups; pa_pmu->num_counters = PA_NR_COUNTERS; pa_pmu->ops = &hisi_uncore_pa_ops; pa_pmu->check_event = 0xB0; @@ -400,8 +488,9 @@ static int hisi_pa_pmu_probe(struct platform_device *pdev) if (ret) return ret; - name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "hisi_sicl%u_pa%u", - pa_pmu->sicl_id, pa_pmu->index_id); + name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "hisi_sicl%d_%s%u", + pa_pmu->sicl_id, pa_pmu->dev_info->name, + pa_pmu->index_id); if (!name) return -ENOMEM; @@ -435,6 +524,14 @@ static int hisi_pa_pmu_remove(struct platform_device *pdev) return 0; } +static const struct acpi_device_id hisi_pa_pmu_acpi_match[] = { + { "HISI0273", (kernel_ulong_t)&hisi_h32pa_v2 }, + { "HISI0275", (kernel_ulong_t)&hisi_h32pa_v3 }, + { "HISI0274", (kernel_ulong_t)&hisi_h60pa }, + {} +}; +MODULE_DEVICE_TABLE(acpi, hisi_pa_pmu_acpi_match); + static struct platform_driver hisi_pa_pmu_driver = { .driver = { .name = "hisi_pa_pmu", diff --git a/drivers/perf/hisilicon/hisi_uncore_pmu.c b/drivers/perf/hisilicon/hisi_uncore_pmu.c index 2823f381930daf885e1e4cde96e430b9d6129b05..04031450d5fecae9c5740deb553f4ce0ea574673 100644 --- a/drivers/perf/hisilicon/hisi_uncore_pmu.c +++ b/drivers/perf/hisilicon/hisi_uncore_pmu.c @@ -20,7 +20,6 @@ #include "hisi_uncore_pmu.h" -#define HISI_GET_EVENTID(ev) (ev->hw.config_base & 0xff) #define HISI_MAX_PERIOD(nr) (GENMASK_ULL((nr) - 1, 0)) /* @@ -226,6 +225,9 @@ int hisi_uncore_pmu_event_init(struct perf_event *event) hwc->idx = -1; hwc->config_base = event->attr.config; + if (hisi_pmu->ops->check_filter && hisi_pmu->ops->check_filter(event)) + return -EINVAL; + /* Enforce to use the same CPU for all events in this PMU */ event->cpu = hisi_pmu->on_cpu; diff --git a/drivers/perf/hisilicon/hisi_uncore_pmu.h b/drivers/perf/hisilicon/hisi_uncore_pmu.h index 07890a8e96ca75ef001259ae2188181df36521d1..92402aa69d70f5103f41c278d3e3515f14b8e752 100644 --- a/drivers/perf/hisilicon/hisi_uncore_pmu.h +++ b/drivers/perf/hisilicon/hisi_uncore_pmu.h @@ -43,9 +43,15 @@ return FIELD_GET(GENMASK_ULL(hi, lo), event->attr.config); \ } +#define HISI_GET_EVENTID(ev) (ev->hw.config_base & 0xff) + +#define HISI_PMU_EVTYPE_BITS 8 +#define HISI_PMU_EVTYPE_SHIFT(idx) ((idx) % 4 * HISI_PMU_EVTYPE_BITS) + struct hisi_pmu; struct hisi_uncore_ops { + int (*check_filter)(struct perf_event *event); void (*write_evtype)(struct hisi_pmu *, int, u32); int (*get_event_idx)(struct perf_event *); u64 (*read_counter)(struct hisi_pmu *, struct hw_perf_event *); @@ -62,6 +68,13 @@ struct hisi_uncore_ops { void (*disable_filter)(struct perf_event *event); }; +/* Describes the HISI PMU chip features information */ +struct hisi_pmu_dev_info { + const char *name; + const struct attribute_group **attr_groups; + void *private; +}; + struct hisi_pmu_hwevents { struct perf_event *hw_events[HISI_MAX_COUNTERS]; DECLARE_BITMAP(used_mask, HISI_MAX_COUNTERS); @@ -72,6 +85,7 @@ struct hisi_pmu_hwevents { struct hisi_pmu { struct pmu pmu; const struct hisi_uncore_ops *ops; + const struct hisi_pmu_dev_info *dev_info; struct hisi_pmu_hwevents pmu_events; /* associated_cpus: All CPUs associated with the PMU */ cpumask_t associated_cpus; diff --git a/drivers/perf/hisilicon/hisi_uncore_uc_pmu.c b/drivers/perf/hisilicon/hisi_uncore_uc_pmu.c new file mode 100644 index 0000000000000000000000000000000000000000..63da05e5831c1f98d9aef4ee2fbaddf223ae8297 --- /dev/null +++ b/drivers/perf/hisilicon/hisi_uncore_uc_pmu.c @@ -0,0 +1,578 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * HiSilicon SoC UC (unified cache) uncore Hardware event counters support + * + * Copyright (C) 2023 HiSilicon Limited + * + * This code is based on the uncore PMUs like hisi_uncore_l3c_pmu. + */ +#include +#include +#include +#include +#include +#include + +#include "hisi_uncore_pmu.h" + +/* Dynamic CPU hotplug state used by UC PMU */ +static enum cpuhp_state hisi_uc_pmu_online; + +/* UC register definition */ +#define HISI_UC_INT_MASK_REG 0x0800 +#define HISI_UC_INT_STS_REG 0x0808 +#define HISI_UC_INT_CLEAR_REG 0x080c +#define HISI_UC_TRACETAG_CTRL_REG 0x1b2c +#define HISI_UC_TRACETAG_REQ_MSK GENMASK(9, 7) +#define HISI_UC_TRACETAG_MARK_EN BIT(0) +#define HISI_UC_TRACETAG_REQ_EN (HISI_UC_TRACETAG_MARK_EN | BIT(2)) +#define HISI_UC_TRACETAG_SRCID_EN BIT(3) +#define HISI_UC_SRCID_CTRL_REG 0x1b40 +#define HISI_UC_SRCID_MSK GENMASK(14, 1) +#define HISI_UC_EVENT_CTRL_REG 0x1c00 +#define HISI_UC_EVENT_TRACETAG_EN BIT(29) +#define HISI_UC_EVENT_URING_MSK GENMASK(28, 27) +#define HISI_UC_EVENT_GLB_EN BIT(26) +#define HISI_UC_VERSION_REG 0x1cf0 +#define HISI_UC_EVTYPE_REGn(n) (0x1d00 + (n) * 4) +#define HISI_UC_EVTYPE_MASK GENMASK(7, 0) +#define HISI_UC_CNTR_REGn(n) (0x1e00 + (n) * 8) + +#define HISI_UC_NR_COUNTERS 0x8 +#define HISI_UC_V2_NR_EVENTS 0xFF +#define HISI_UC_CNTR_REG_BITS 64 + +#define HISI_UC_RD_REQ_TRACETAG 0x4 +#define HISI_UC_URING_EVENT_MIN 0x47 +#define HISI_UC_URING_EVENT_MAX 0x59 + +HISI_PMU_EVENT_ATTR_EXTRACTOR(rd_req_en, config1, 0, 0); +HISI_PMU_EVENT_ATTR_EXTRACTOR(uring_channel, config1, 5, 4); +HISI_PMU_EVENT_ATTR_EXTRACTOR(srcid, config1, 19, 6); +HISI_PMU_EVENT_ATTR_EXTRACTOR(srcid_en, config1, 20, 20); + +static int hisi_uc_pmu_check_filter(struct perf_event *event) +{ + struct hisi_pmu *uc_pmu = to_hisi_pmu(event->pmu); + + if (hisi_get_srcid_en(event) && !hisi_get_rd_req_en(event)) { + dev_err(uc_pmu->dev, + "rcid_en depends on rd_req_en being enabled!\n"); + return -EINVAL; + } + + if (!hisi_get_uring_channel(event)) + return 0; + + if ((HISI_GET_EVENTID(event) < HISI_UC_URING_EVENT_MIN) || + (HISI_GET_EVENTID(event) > HISI_UC_URING_EVENT_MAX)) + dev_warn(uc_pmu->dev, + "Only events: [%#x ~ %#x] support channel filtering!", + HISI_UC_URING_EVENT_MIN, HISI_UC_URING_EVENT_MAX); + + return 0; +} + +static void hisi_uc_pmu_config_req_tracetag(struct perf_event *event) +{ + struct hisi_pmu *uc_pmu = to_hisi_pmu(event->pmu); + u32 val; + + if (!hisi_get_rd_req_en(event)) + return; + + val = readl(uc_pmu->base + HISI_UC_TRACETAG_CTRL_REG); + + /* The request-type has been configured */ + if (FIELD_GET(HISI_UC_TRACETAG_REQ_MSK, val) == HISI_UC_RD_REQ_TRACETAG) + return; + + /* Set request-type for tracetag, only read request is supported! */ + val &= ~HISI_UC_TRACETAG_REQ_MSK; + val |= FIELD_PREP(HISI_UC_TRACETAG_REQ_MSK, HISI_UC_RD_REQ_TRACETAG); + val |= HISI_UC_TRACETAG_REQ_EN; + writel(val, uc_pmu->base + HISI_UC_TRACETAG_CTRL_REG); +} + +static void hisi_uc_pmu_clear_req_tracetag(struct perf_event *event) +{ + struct hisi_pmu *uc_pmu = to_hisi_pmu(event->pmu); + u32 val; + + if (!hisi_get_rd_req_en(event)) + return; + + val = readl(uc_pmu->base + HISI_UC_TRACETAG_CTRL_REG); + + /* Do nothing, the request-type tracetag has been cleaned up */ + if (FIELD_GET(HISI_UC_TRACETAG_REQ_MSK, val) == 0) + return; + + /* Clear request-type */ + val &= ~HISI_UC_TRACETAG_REQ_MSK; + val &= ~HISI_UC_TRACETAG_REQ_EN; + writel(val, uc_pmu->base + HISI_UC_TRACETAG_CTRL_REG); +} + +static void hisi_uc_pmu_config_srcid_tracetag(struct perf_event *event) +{ + struct hisi_pmu *uc_pmu = to_hisi_pmu(event->pmu); + u32 val; + + if (!hisi_get_srcid_en(event)) + return; + + val = readl(uc_pmu->base + HISI_UC_TRACETAG_CTRL_REG); + + /* Do nothing, the source id has been configured */ + if (FIELD_GET(HISI_UC_TRACETAG_SRCID_EN, val)) + return; + + /* Enable source id tracetag */ + val |= HISI_UC_TRACETAG_SRCID_EN; + writel(val, uc_pmu->base + HISI_UC_TRACETAG_CTRL_REG); + + val = readl(uc_pmu->base + HISI_UC_SRCID_CTRL_REG); + val &= ~HISI_UC_SRCID_MSK; + val |= FIELD_PREP(HISI_UC_SRCID_MSK, hisi_get_srcid(event)); + writel(val, uc_pmu->base + HISI_UC_SRCID_CTRL_REG); + + /* Depend on request-type tracetag enabled */ + hisi_uc_pmu_config_req_tracetag(event); +} + +static void hisi_uc_pmu_clear_srcid_tracetag(struct perf_event *event) +{ + struct hisi_pmu *uc_pmu = to_hisi_pmu(event->pmu); + u32 val; + + if (!hisi_get_srcid_en(event)) + return; + + val = readl(uc_pmu->base + HISI_UC_TRACETAG_CTRL_REG); + + /* Do nothing, the source id has been cleaned up */ + if (FIELD_GET(HISI_UC_TRACETAG_SRCID_EN, val) == 0) + return; + + hisi_uc_pmu_clear_req_tracetag(event); + + /* Disable source id tracetag */ + val &= ~HISI_UC_TRACETAG_SRCID_EN; + writel(val, uc_pmu->base + HISI_UC_TRACETAG_CTRL_REG); + + val = readl(uc_pmu->base + HISI_UC_SRCID_CTRL_REG); + val &= ~HISI_UC_SRCID_MSK; + writel(val, uc_pmu->base + HISI_UC_SRCID_CTRL_REG); +} + +static void hisi_uc_pmu_config_uring_channel(struct perf_event *event) +{ + struct hisi_pmu *uc_pmu = to_hisi_pmu(event->pmu); + u32 uring_channel = hisi_get_uring_channel(event); + u32 val; + + /* Do nothing if not being set or is set explicitly to zero (default) */ + if (uring_channel == 0) + return; + + val = readl(uc_pmu->base + HISI_UC_EVENT_CTRL_REG); + + /* Do nothing, the uring_channel has been configured */ + if (uring_channel == FIELD_GET(HISI_UC_EVENT_URING_MSK, val)) + return; + + val &= ~HISI_UC_EVENT_URING_MSK; + val |= FIELD_PREP(HISI_UC_EVENT_URING_MSK, uring_channel); + writel(val, uc_pmu->base + HISI_UC_EVENT_CTRL_REG); +} + +static void hisi_uc_pmu_clear_uring_channel(struct perf_event *event) +{ + struct hisi_pmu *uc_pmu = to_hisi_pmu(event->pmu); + u32 val; + + /* Do nothing if not being set or is set explicitly to zero (default) */ + if (hisi_get_uring_channel(event) == 0) + return; + + val = readl(uc_pmu->base + HISI_UC_EVENT_CTRL_REG); + + /* Do nothing, the uring_channel has been cleaned up */ + if (FIELD_GET(HISI_UC_EVENT_URING_MSK, val) == 0) + return; + + val &= ~HISI_UC_EVENT_URING_MSK; + writel(val, uc_pmu->base + HISI_UC_EVENT_CTRL_REG); +} + +static void hisi_uc_pmu_enable_filter(struct perf_event *event) +{ + if (event->attr.config1 == 0) + return; + + hisi_uc_pmu_config_uring_channel(event); + hisi_uc_pmu_config_req_tracetag(event); + hisi_uc_pmu_config_srcid_tracetag(event); +} + +static void hisi_uc_pmu_disable_filter(struct perf_event *event) +{ + if (event->attr.config1 == 0) + return; + + hisi_uc_pmu_clear_srcid_tracetag(event); + hisi_uc_pmu_clear_req_tracetag(event); + hisi_uc_pmu_clear_uring_channel(event); +} + +static void hisi_uc_pmu_write_evtype(struct hisi_pmu *uc_pmu, int idx, u32 type) +{ + u32 val; + + /* + * Select the appropriate event select register. + * There are 2 32-bit event select registers for the + * 8 hardware counters, each event code is 8-bit wide. + */ + val = readl(uc_pmu->base + HISI_UC_EVTYPE_REGn(idx / 4)); + val &= ~(HISI_UC_EVTYPE_MASK << HISI_PMU_EVTYPE_SHIFT(idx)); + val |= (type << HISI_PMU_EVTYPE_SHIFT(idx)); + writel(val, uc_pmu->base + HISI_UC_EVTYPE_REGn(idx / 4)); +} + +static void hisi_uc_pmu_start_counters(struct hisi_pmu *uc_pmu) +{ + u32 val; + + val = readl(uc_pmu->base + HISI_UC_EVENT_CTRL_REG); + val |= HISI_UC_EVENT_GLB_EN; + writel(val, uc_pmu->base + HISI_UC_EVENT_CTRL_REG); +} + +static void hisi_uc_pmu_stop_counters(struct hisi_pmu *uc_pmu) +{ + u32 val; + + val = readl(uc_pmu->base + HISI_UC_EVENT_CTRL_REG); + val &= ~HISI_UC_EVENT_GLB_EN; + writel(val, uc_pmu->base + HISI_UC_EVENT_CTRL_REG); +} + +static void hisi_uc_pmu_enable_counter(struct hisi_pmu *uc_pmu, + struct hw_perf_event *hwc) +{ + u32 val; + + /* Enable counter index */ + val = readl(uc_pmu->base + HISI_UC_EVENT_CTRL_REG); + val |= (1 << hwc->idx); + writel(val, uc_pmu->base + HISI_UC_EVENT_CTRL_REG); +} + +static void hisi_uc_pmu_disable_counter(struct hisi_pmu *uc_pmu, + struct hw_perf_event *hwc) +{ + u32 val; + + /* Clear counter index */ + val = readl(uc_pmu->base + HISI_UC_EVENT_CTRL_REG); + val &= ~(1 << hwc->idx); + writel(val, uc_pmu->base + HISI_UC_EVENT_CTRL_REG); +} + +static u64 hisi_uc_pmu_read_counter(struct hisi_pmu *uc_pmu, + struct hw_perf_event *hwc) +{ + return readq(uc_pmu->base + HISI_UC_CNTR_REGn(hwc->idx)); +} + +static void hisi_uc_pmu_write_counter(struct hisi_pmu *uc_pmu, + struct hw_perf_event *hwc, u64 val) +{ + writeq(val, uc_pmu->base + HISI_UC_CNTR_REGn(hwc->idx)); +} + +static void hisi_uc_pmu_enable_counter_int(struct hisi_pmu *uc_pmu, + struct hw_perf_event *hwc) +{ + u32 val; + + val = readl(uc_pmu->base + HISI_UC_INT_MASK_REG); + val &= ~(1 << hwc->idx); + writel(val, uc_pmu->base + HISI_UC_INT_MASK_REG); +} + +static void hisi_uc_pmu_disable_counter_int(struct hisi_pmu *uc_pmu, + struct hw_perf_event *hwc) +{ + u32 val; + + val = readl(uc_pmu->base + HISI_UC_INT_MASK_REG); + val |= (1 << hwc->idx); + writel(val, uc_pmu->base + HISI_UC_INT_MASK_REG); +} + +static u32 hisi_uc_pmu_get_int_status(struct hisi_pmu *uc_pmu) +{ + return readl(uc_pmu->base + HISI_UC_INT_STS_REG); +} + +static void hisi_uc_pmu_clear_int_status(struct hisi_pmu *uc_pmu, int idx) +{ + writel(1 << idx, uc_pmu->base + HISI_UC_INT_CLEAR_REG); +} + +static int hisi_uc_pmu_init_data(struct platform_device *pdev, + struct hisi_pmu *uc_pmu) +{ + /* + * Use SCCL (Super CPU Cluster) ID and CCL (CPU Cluster) ID to + * identify the topology information of UC PMU devices in the chip. + * They have some CCLs per SCCL and then 4 UC PMU per CCL. + */ + if (device_property_read_u32(&pdev->dev, "hisilicon,scl-id", + &uc_pmu->sccl_id)) { + dev_err(&pdev->dev, "Can not read uc sccl-id!\n"); + return -EINVAL; + } + + if (device_property_read_u32(&pdev->dev, "hisilicon,ccl-id", + &uc_pmu->ccl_id)) { + dev_err(&pdev->dev, "Can not read uc ccl-id!\n"); + return -EINVAL; + } + + if (device_property_read_u32(&pdev->dev, "hisilicon,sub-id", + &uc_pmu->sub_id)) { + dev_err(&pdev->dev, "Can not read sub-id!\n"); + return -EINVAL; + } + + uc_pmu->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(uc_pmu->base)) { + dev_err(&pdev->dev, "ioremap failed for uc_pmu resource\n"); + return PTR_ERR(uc_pmu->base); + } + + uc_pmu->identifier = readl(uc_pmu->base + HISI_UC_VERSION_REG); + + return 0; +} + +static struct attribute *hisi_uc_pmu_format_attr[] = { + HISI_PMU_FORMAT_ATTR(event, "config:0-7"), + HISI_PMU_FORMAT_ATTR(rd_req_en, "config1:0-0"), + HISI_PMU_FORMAT_ATTR(uring_channel, "config1:4-5"), + HISI_PMU_FORMAT_ATTR(srcid, "config1:6-19"), + HISI_PMU_FORMAT_ATTR(srcid_en, "config1:20-20"), + NULL +}; + +static const struct attribute_group hisi_uc_pmu_format_group = { + .name = "format", + .attrs = hisi_uc_pmu_format_attr, +}; + +static struct attribute *hisi_uc_pmu_events_attr[] = { + HISI_PMU_EVENT_ATTR(sq_time, 0x00), + HISI_PMU_EVENT_ATTR(pq_time, 0x01), + HISI_PMU_EVENT_ATTR(hbm_time, 0x02), + HISI_PMU_EVENT_ATTR(iq_comp_time_cring, 0x03), + HISI_PMU_EVENT_ATTR(iq_comp_time_uring, 0x05), + HISI_PMU_EVENT_ATTR(cpu_rd, 0x10), + HISI_PMU_EVENT_ATTR(cpu_rd64, 0x17), + HISI_PMU_EVENT_ATTR(cpu_rs64, 0x19), + HISI_PMU_EVENT_ATTR(cpu_mru, 0x1a), + HISI_PMU_EVENT_ATTR(cycles, 0x9c), + HISI_PMU_EVENT_ATTR(spipe_hit, 0xb3), + HISI_PMU_EVENT_ATTR(hpipe_hit, 0xdb), + HISI_PMU_EVENT_ATTR(cring_rxdat_cnt, 0xfa), + HISI_PMU_EVENT_ATTR(cring_txdat_cnt, 0xfb), + HISI_PMU_EVENT_ATTR(uring_rxdat_cnt, 0xfc), + HISI_PMU_EVENT_ATTR(uring_txdat_cnt, 0xfd), + NULL +}; + +static const struct attribute_group hisi_uc_pmu_events_group = { + .name = "events", + .attrs = hisi_uc_pmu_events_attr, +}; + +static DEVICE_ATTR(cpumask, 0444, hisi_cpumask_sysfs_show, NULL); + +static struct attribute *hisi_uc_pmu_cpumask_attrs[] = { + &dev_attr_cpumask.attr, + NULL, +}; + +static const struct attribute_group hisi_uc_pmu_cpumask_attr_group = { + .attrs = hisi_uc_pmu_cpumask_attrs, +}; + +static struct device_attribute hisi_uc_pmu_identifier_attr = + __ATTR(identifier, 0444, hisi_uncore_pmu_identifier_attr_show, NULL); + +static struct attribute *hisi_uc_pmu_identifier_attrs[] = { + &hisi_uc_pmu_identifier_attr.attr, + NULL +}; + +static const struct attribute_group hisi_uc_pmu_identifier_group = { + .attrs = hisi_uc_pmu_identifier_attrs, +}; + +static const struct attribute_group *hisi_uc_pmu_attr_groups[] = { + &hisi_uc_pmu_format_group, + &hisi_uc_pmu_events_group, + &hisi_uc_pmu_cpumask_attr_group, + &hisi_uc_pmu_identifier_group, + NULL +}; + +static const struct hisi_uncore_ops hisi_uncore_uc_pmu_ops = { + .check_filter = hisi_uc_pmu_check_filter, + .write_evtype = hisi_uc_pmu_write_evtype, + .get_event_idx = hisi_uncore_pmu_get_event_idx, + .start_counters = hisi_uc_pmu_start_counters, + .stop_counters = hisi_uc_pmu_stop_counters, + .enable_counter = hisi_uc_pmu_enable_counter, + .disable_counter = hisi_uc_pmu_disable_counter, + .enable_counter_int = hisi_uc_pmu_enable_counter_int, + .disable_counter_int = hisi_uc_pmu_disable_counter_int, + .write_counter = hisi_uc_pmu_write_counter, + .read_counter = hisi_uc_pmu_read_counter, + .get_int_status = hisi_uc_pmu_get_int_status, + .clear_int_status = hisi_uc_pmu_clear_int_status, + .enable_filter = hisi_uc_pmu_enable_filter, + .disable_filter = hisi_uc_pmu_disable_filter, +}; + +static int hisi_uc_pmu_dev_probe(struct platform_device *pdev, + struct hisi_pmu *uc_pmu) +{ + int ret; + + ret = hisi_uc_pmu_init_data(pdev, uc_pmu); + if (ret) + return ret; + + ret = hisi_uncore_pmu_init_irq(uc_pmu, pdev); + if (ret) + return ret; + + uc_pmu->pmu_events.attr_groups = hisi_uc_pmu_attr_groups; + uc_pmu->check_event = HISI_UC_EVTYPE_MASK; + uc_pmu->ops = &hisi_uncore_uc_pmu_ops; + uc_pmu->counter_bits = HISI_UC_CNTR_REG_BITS; + uc_pmu->num_counters = HISI_UC_NR_COUNTERS; + uc_pmu->dev = &pdev->dev; + uc_pmu->on_cpu = -1; + + return 0; +} + +static void hisi_uc_pmu_remove_cpuhp_instance(void *hotplug_node) +{ + cpuhp_state_remove_instance_nocalls(hisi_uc_pmu_online, hotplug_node); +} + +static void hisi_uc_pmu_unregister_pmu(void *pmu) +{ + perf_pmu_unregister(pmu); +} + +static int hisi_uc_pmu_probe(struct platform_device *pdev) +{ + struct hisi_pmu *uc_pmu; + char *name; + int ret; + + uc_pmu = devm_kzalloc(&pdev->dev, sizeof(*uc_pmu), GFP_KERNEL); + if (!uc_pmu) + return -ENOMEM; + + platform_set_drvdata(pdev, uc_pmu); + + ret = hisi_uc_pmu_dev_probe(pdev, uc_pmu); + if (ret) + return ret; + + name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "hisi_sccl%d_uc%d_%u", + uc_pmu->sccl_id, uc_pmu->ccl_id, uc_pmu->sub_id); + if (!name) + return -ENOMEM; + + ret = cpuhp_state_add_instance(hisi_uc_pmu_online, &uc_pmu->node); + if (ret) + return dev_err_probe(&pdev->dev, ret, "Error registering hotplug\n"); + + ret = devm_add_action_or_reset(&pdev->dev, + hisi_uc_pmu_remove_cpuhp_instance, + &uc_pmu->node); + if (ret) + return ret; + + hisi_pmu_init(uc_pmu, THIS_MODULE); + + ret = perf_pmu_register(&uc_pmu->pmu, name, -1); + if (ret) + return ret; + + return devm_add_action_or_reset(&pdev->dev, + hisi_uc_pmu_unregister_pmu, + &uc_pmu->pmu); +} + +static const struct acpi_device_id hisi_uc_pmu_acpi_match[] = { + { "HISI0291", }, + {} +}; +MODULE_DEVICE_TABLE(acpi, hisi_uc_pmu_acpi_match); + +static struct platform_driver hisi_uc_pmu_driver = { + .driver = { + .name = "hisi_uc_pmu", + .acpi_match_table = hisi_uc_pmu_acpi_match, + /* + * We have not worked out a safe bind/unbind process, + * Forcefully unbinding during sampling will lead to a + * kernel panic, so this is not supported yet. + */ + .suppress_bind_attrs = true, + }, + .probe = hisi_uc_pmu_probe, +}; + +static int __init hisi_uc_pmu_module_init(void) +{ + int ret; + + ret = cpuhp_setup_state_multi(CPUHP_AP_ONLINE_DYN, + "perf/hisi/uc:online", + hisi_uncore_pmu_online_cpu, + hisi_uncore_pmu_offline_cpu); + if (ret < 0) { + pr_err("UC PMU: Error setup hotplug, ret = %d\n", ret); + return ret; + } + hisi_uc_pmu_online = ret; + + ret = platform_driver_register(&hisi_uc_pmu_driver); + if (ret) + cpuhp_remove_multi_state(hisi_uc_pmu_online); + + return ret; +} +module_init(hisi_uc_pmu_module_init); + +static void __exit hisi_uc_pmu_module_exit(void) +{ + platform_driver_unregister(&hisi_uc_pmu_driver); + cpuhp_remove_multi_state(hisi_uc_pmu_online); +} +module_exit(hisi_uc_pmu_module_exit); + +MODULE_DESCRIPTION("HiSilicon SoC UC uncore PMU driver"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Junhao He "); diff --git a/drivers/perf/qcom_l2_pmu.c b/drivers/perf/qcom_l2_pmu.c index aaca6db7d8f6c47f24a43a4831031e4afca1a2c9..3f9a98c17a897d39ad4bd6f3dc797d318ca57abf 100644 --- a/drivers/perf/qcom_l2_pmu.c +++ b/drivers/perf/qcom_l2_pmu.c @@ -857,7 +857,6 @@ static int l2_cache_pmu_probe_cluster(struct device *dev, void *data) return -ENOMEM; INIT_LIST_HEAD(&cluster->next); - list_add(&cluster->next, &l2cache_pmu->clusters); cluster->cluster_id = fw_cluster_id; irq = platform_get_irq(sdev, 0); @@ -883,6 +882,7 @@ static int l2_cache_pmu_probe_cluster(struct device *dev, void *data) spin_lock_init(&cluster->pmu_lock); + list_add(&cluster->next, &l2cache_pmu->clusters); l2cache_pmu->num_pmus++; return 0; diff --git a/drivers/perf/riscv_pmu.c b/drivers/perf/riscv_pmu.c index ebca5eab9c9beeac4393c898bb3dbf272bfacd64..56897d4d4fd3efa339f2e001985112bd752108a5 100644 --- a/drivers/perf/riscv_pmu.c +++ b/drivers/perf/riscv_pmu.c @@ -181,9 +181,6 @@ void riscv_pmu_start(struct perf_event *event, int flags) uint64_t max_period = riscv_pmu_ctr_get_width_mask(event); u64 init_val; - if (WARN_ON_ONCE(!(event->hw.state & PERF_HES_STOPPED))) - return; - if (flags & PERF_EF_RELOAD) WARN_ON_ONCE(!(event->hw.state & PERF_HES_UPTODATE)); diff --git a/drivers/perf/riscv_pmu_sbi.c b/drivers/perf/riscv_pmu_sbi.c index 4f3ac296b3e25afe356cd7662e32c6f6e2cbf2d5..4163ff5174715da102eb8d8ab8b18d6ae784da43 100644 --- a/drivers/perf/riscv_pmu_sbi.c +++ b/drivers/perf/riscv_pmu_sbi.c @@ -739,7 +739,6 @@ static int pmu_sbi_setup_irqs(struct riscv_pmu *pmu, struct platform_device *pde { int ret; struct cpu_hw_events __percpu *hw_events = pmu->hw_events; - struct device_node *cpu, *child; struct irq_domain *domain = NULL; if (riscv_isa_extension_available(NULL, SSCOFPMF)) { @@ -756,20 +755,8 @@ static int pmu_sbi_setup_irqs(struct riscv_pmu *pmu, struct platform_device *pde if (!riscv_pmu_use_irq) return -EOPNOTSUPP; - for_each_of_cpu_node(cpu) { - child = of_get_compatible_child(cpu, "riscv,cpu-intc"); - if (!child) { - pr_err("Failed to find INTC node\n"); - of_node_put(cpu); - return -ENODEV; - } - domain = irq_find_host(child); - of_node_put(child); - if (domain) { - of_node_put(cpu); - break; - } - } + domain = irq_find_matching_fwnode(riscv_get_intc_hwnode(), + DOMAIN_BUS_ANY); if (!domain) { pr_err("Failed to find INTC IRQ root domain\n"); return -ENODEV; @@ -868,6 +855,12 @@ static int pmu_sbi_device_probe(struct platform_device *pdev) goto out_free; } + /* It is possible to get from SBI more than max number of counters */ + if (num_counters > RISCV_MAX_COUNTERS) { + num_counters = RISCV_MAX_COUNTERS; + pr_info("SBI returned more than maximum number of counters. Limiting the number of counters to %d\n", num_counters); + } + /* cache all the information about counters now */ if (pmu_sbi_get_ctrinfo(num_counters, &cmask)) goto out_free; diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig index f46e3148d286dc3c57f4419823215f2996b66c2f..8dba9596408f24c0045584b682436b090355e8a7 100644 --- a/drivers/phy/Kconfig +++ b/drivers/phy/Kconfig @@ -18,6 +18,7 @@ config GENERIC_PHY config GENERIC_PHY_MIPI_DPHY bool + depends on GENERIC_PHY help Generic MIPI D-PHY support. diff --git a/drivers/phy/amlogic/phy-meson-g12a-usb2.c b/drivers/phy/amlogic/phy-meson-g12a-usb2.c index 9d1efa0d93948383c09ae151d3111d71948a3c7c..ec2555bb83d57cae7b3e9c4409f8bc010b26f26d 100644 --- a/drivers/phy/amlogic/phy-meson-g12a-usb2.c +++ b/drivers/phy/amlogic/phy-meson-g12a-usb2.c @@ -172,10 +172,16 @@ static int phy_meson_g12a_usb2_init(struct phy *phy) int ret; unsigned int value; - ret = reset_control_reset(priv->reset); + ret = clk_prepare_enable(priv->clk); if (ret) return ret; + ret = reset_control_reset(priv->reset); + if (ret) { + clk_disable_unprepare(priv->clk); + return ret; + } + udelay(RESET_COMPLETE_TIME); /* usb2_otg_aca_en == 0 */ @@ -277,8 +283,13 @@ static int phy_meson_g12a_usb2_init(struct phy *phy) static int phy_meson_g12a_usb2_exit(struct phy *phy) { struct phy_meson_g12a_usb2_priv *priv = phy_get_drvdata(phy); + int ret; + + ret = reset_control_reset(priv->reset); + if (!ret) + clk_disable_unprepare(priv->clk); - return reset_control_reset(priv->reset); + return ret; } /* set_mode is not needed, mode setting is handled via the UTMI bus */ diff --git a/drivers/phy/broadcom/phy-brcm-usb-init-synopsys.c b/drivers/phy/broadcom/phy-brcm-usb-init-synopsys.c index 76cf4280d7ed943d8f85b9dbf7e001ff7159a67f..4c10cafded4e936d2d738b49eb96a26f463267fc 100644 --- a/drivers/phy/broadcom/phy-brcm-usb-init-synopsys.c +++ b/drivers/phy/broadcom/phy-brcm-usb-init-synopsys.c @@ -59,6 +59,8 @@ #define USB_CTLR_TP_DIAG1_wake_MASK BIT(1) #define USB_CTRL_CTLR_CSHCR 0x50 #define USB_CTRL_CTLR_CSHCR_ctl_pme_en_MASK BIT(18) +#define USB_CTRL_P0_U2PHY_CFG1 0x68 +#define USB_CTRL_P0_U2PHY_CFG1_COMMONONN_MASK BIT(10) /* Register definitions for the USB_PHY block in 7211b0 */ #define USB_PHY_PLL_CTL 0x00 @@ -90,6 +92,8 @@ #define BDC_EC_AXIRDA_RTS_MASK GENMASK(31, 28) #define BDC_EC_AXIRDA_RTS_SHIFT 28 +#define USB_XHCI_GBL_GUSB2PHYCFG 0x100 +#define USB_XHCI_GBL_GUSB2PHYCFG_U2_FREECLK_EXISTS_MASK BIT(30) static void usb_mdio_write_7211b0(struct brcm_usb_init_params *params, uint8_t addr, uint16_t data) @@ -140,13 +144,17 @@ static void xhci_soft_reset(struct brcm_usb_init_params *params, int on_off) { void __iomem *ctrl = params->regs[BRCM_REGS_CTRL]; + void __iomem *xhci_gbl = params->regs[BRCM_REGS_XHCI_GBL]; /* Assert reset */ - if (on_off) + if (on_off) { USB_CTRL_UNSET(ctrl, USB_PM, XHC_SOFT_RESETB); /* De-assert reset */ - else + } else { USB_CTRL_SET(ctrl, USB_PM, XHC_SOFT_RESETB); + /* Required for COMMONONN to be set */ + USB_XHCI_GBL_UNSET(xhci_gbl, GUSB2PHYCFG, U2_FREECLK_EXISTS); + } } static void usb_init_ipp(struct brcm_usb_init_params *params) @@ -320,6 +328,9 @@ static void usb_init_common_7216(struct brcm_usb_init_params *params) /* 1 millisecond - for USB clocks to settle down */ usleep_range(1000, 2000); + /* Disable PHY when port is suspended */ + USB_CTRL_SET(ctrl, P0_U2PHY_CFG1, COMMONONN); + usb_wake_enable_7216(params, false); usb_init_common(params); } diff --git a/drivers/phy/broadcom/phy-brcm-usb-init.c b/drivers/phy/broadcom/phy-brcm-usb-init.c index a1ca83308f98d365c12eb29698b0cea4589d85d1..39536b6d96a9f15b461d368d01ba17a108257e44 100644 --- a/drivers/phy/broadcom/phy-brcm-usb-init.c +++ b/drivers/phy/broadcom/phy-brcm-usb-init.c @@ -35,6 +35,11 @@ #define USB_CTRL_SETUP_STRAP_IPP_SEL_MASK BIT(25) /* option */ #define USB_CTRL_SETUP_CC_DRD_MODE_ENABLE_MASK BIT(26) /* option */ #define USB_CTRL_SETUP_STRAP_CC_DRD_MODE_ENABLE_SEL_MASK BIT(27) /* opt */ +#define USB_CTRL_SETUP_OC_DISABLE_PORT0_MASK BIT(28) +#define USB_CTRL_SETUP_OC_DISABLE_PORT1_MASK BIT(29) +#define USB_CTRL_SETUP_OC_DISABLE_MASK GENMASK(29, 28) /* option */ +#define USB_CTRL_SETUP_OC3_DISABLE_PORT0_MASK BIT(30) +#define USB_CTRL_SETUP_OC3_DISABLE_PORT1_MASK BIT(31) #define USB_CTRL_SETUP_OC3_DISABLE_MASK GENMASK(31, 30) /* option */ #define USB_CTRL_PLL_CTL 0x04 #define USB_CTRL_PLL_CTL_PLL_SUSPEND_EN_MASK BIT(27) @@ -114,6 +119,8 @@ enum { USB_CTRL_SETUP_SCB2_EN_SELECTOR, USB_CTRL_SETUP_SS_EHCI64BIT_EN_SELECTOR, USB_CTRL_SETUP_STRAP_IPP_SEL_SELECTOR, + USB_CTRL_SETUP_OC3_DISABLE_PORT0_SELECTOR, + USB_CTRL_SETUP_OC3_DISABLE_PORT1_SELECTOR, USB_CTRL_SETUP_OC3_DISABLE_SELECTOR, USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_SELECTOR, USB_CTRL_USB_PM_BDC_SOFT_RESETB_SELECTOR, @@ -190,6 +197,8 @@ usb_reg_bits_map_table[BRCM_FAMILY_COUNT][USB_CTRL_SELECTOR_COUNT] = { USB_CTRL_SETUP_SCB2_EN_MASK, USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK, USB_CTRL_SETUP_STRAP_IPP_SEL_MASK, + USB_CTRL_SETUP_OC3_DISABLE_PORT0_MASK, + USB_CTRL_SETUP_OC3_DISABLE_PORT1_MASK, USB_CTRL_SETUP_OC3_DISABLE_MASK, 0, /* USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK */ 0, /* USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK */ @@ -232,6 +241,8 @@ usb_reg_bits_map_table[BRCM_FAMILY_COUNT][USB_CTRL_SELECTOR_COUNT] = { USB_CTRL_SETUP_SCB2_EN_MASK, USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK, 0, /* USB_CTRL_SETUP_STRAP_IPP_SEL_MASK */ + USB_CTRL_SETUP_OC3_DISABLE_PORT0_MASK, + USB_CTRL_SETUP_OC3_DISABLE_PORT1_MASK, USB_CTRL_SETUP_OC3_DISABLE_MASK, USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK, 0, /* USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK */ @@ -253,6 +264,8 @@ usb_reg_bits_map_table[BRCM_FAMILY_COUNT][USB_CTRL_SELECTOR_COUNT] = { 0, /* USB_CTRL_SETUP_SCB2_EN_MASK */ USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK, USB_CTRL_SETUP_STRAP_IPP_SEL_MASK, + USB_CTRL_SETUP_OC3_DISABLE_PORT0_MASK, + USB_CTRL_SETUP_OC3_DISABLE_PORT1_MASK, USB_CTRL_SETUP_OC3_DISABLE_MASK, 0, /* USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK */ USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK, @@ -274,6 +287,8 @@ usb_reg_bits_map_table[BRCM_FAMILY_COUNT][USB_CTRL_SELECTOR_COUNT] = { USB_CTRL_SETUP_SCB2_EN_MASK, USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK, 0, /* USB_CTRL_SETUP_STRAP_IPP_SEL_MASK */ + USB_CTRL_SETUP_OC3_DISABLE_PORT0_MASK, + USB_CTRL_SETUP_OC3_DISABLE_PORT1_MASK, USB_CTRL_SETUP_OC3_DISABLE_MASK, USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK, 0, /* USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK */ @@ -295,6 +310,8 @@ usb_reg_bits_map_table[BRCM_FAMILY_COUNT][USB_CTRL_SELECTOR_COUNT] = { USB_CTRL_SETUP_SCB2_EN_MASK, USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK, 0, /* USB_CTRL_SETUP_STRAP_IPP_SEL_MASK */ + USB_CTRL_SETUP_OC3_DISABLE_PORT0_MASK, + USB_CTRL_SETUP_OC3_DISABLE_PORT1_MASK, USB_CTRL_SETUP_OC3_DISABLE_MASK, 0, /* USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK */ 0, /* USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK */ @@ -316,6 +333,8 @@ usb_reg_bits_map_table[BRCM_FAMILY_COUNT][USB_CTRL_SELECTOR_COUNT] = { USB_CTRL_SETUP_SCB2_EN_MASK, USB_CTRL_SETUP_SS_EHCI64BIT_EN_VAR_MASK, 0, /* USB_CTRL_SETUP_STRAP_IPP_SEL_MASK */ + 0, /* USB_CTRL_SETUP_OC3_DISABLE_PORT0_MASK */ + 0, /* USB_CTRL_SETUP_OC3_DISABLE_PORT1_MASK */ 0, /* USB_CTRL_SETUP_OC3_DISABLE_MASK */ USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK, 0, /* USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK */ @@ -337,6 +356,8 @@ usb_reg_bits_map_table[BRCM_FAMILY_COUNT][USB_CTRL_SELECTOR_COUNT] = { USB_CTRL_SETUP_SCB2_EN_MASK, USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK, USB_CTRL_SETUP_STRAP_IPP_SEL_MASK, + USB_CTRL_SETUP_OC3_DISABLE_PORT0_MASK, + USB_CTRL_SETUP_OC3_DISABLE_PORT1_MASK, USB_CTRL_SETUP_OC3_DISABLE_MASK, 0, /* USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK */ USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK, @@ -358,6 +379,8 @@ usb_reg_bits_map_table[BRCM_FAMILY_COUNT][USB_CTRL_SELECTOR_COUNT] = { USB_CTRL_SETUP_SCB2_EN_MASK, USB_CTRL_SETUP_SS_EHCI64BIT_EN_VAR_MASK, 0, /* USB_CTRL_SETUP_STRAP_IPP_SEL_MASK */ + USB_CTRL_SETUP_OC3_DISABLE_PORT0_MASK, + USB_CTRL_SETUP_OC3_DISABLE_PORT1_MASK, USB_CTRL_SETUP_OC3_DISABLE_MASK, USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK, 0, /* USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK */ @@ -379,6 +402,8 @@ usb_reg_bits_map_table[BRCM_FAMILY_COUNT][USB_CTRL_SELECTOR_COUNT] = { 0, /* USB_CTRL_SETUP_SCB2_EN_MASK */ USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK, USB_CTRL_SETUP_STRAP_IPP_SEL_MASK, + USB_CTRL_SETUP_OC3_DISABLE_PORT0_MASK, + USB_CTRL_SETUP_OC3_DISABLE_PORT1_MASK, USB_CTRL_SETUP_OC3_DISABLE_MASK, 0, /* USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK */ USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK, @@ -400,6 +425,8 @@ usb_reg_bits_map_table[BRCM_FAMILY_COUNT][USB_CTRL_SELECTOR_COUNT] = { 0, /* USB_CTRL_SETUP_SCB2_EN_MASK */ 0, /*USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK */ USB_CTRL_SETUP_STRAP_IPP_SEL_MASK, + USB_CTRL_SETUP_OC3_DISABLE_PORT0_MASK, + USB_CTRL_SETUP_OC3_DISABLE_PORT1_MASK, USB_CTRL_SETUP_OC3_DISABLE_MASK, 0, /* USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK */ USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK, @@ -872,6 +899,13 @@ static void usb_init_common(struct brcm_usb_init_params *params) brcmusb_memc_fix(params); + /* Workaround for false positive OC for 7439b2 in DRD/Device mode */ + if ((params->family_id == 0x74390012) && + (params->supported_port_modes != USB_CTLR_MODE_HOST)) { + USB_CTRL_SET(ctrl, SETUP, OC_DISABLE_PORT1); + USB_CTRL_SET_FAMILY(params, SETUP, OC3_DISABLE_PORT1); + } + if (USB_CTRL_MASK_FAMILY(params, USB_DEVICE_CTL1, PORT_MODE)) { reg = brcm_usb_readl(USB_CTRL_REG(ctrl, USB_DEVICE_CTL1)); reg &= ~USB_CTRL_MASK_FAMILY(params, USB_DEVICE_CTL1, diff --git a/drivers/phy/broadcom/phy-brcm-usb-init.h b/drivers/phy/broadcom/phy-brcm-usb-init.h index f9fbf8fb80e54b236253fcfcd6440c0d1eeb14d3..c1a88f5cd4cd8e4e47bf27a276e80e51970f0abf 100644 --- a/drivers/phy/broadcom/phy-brcm-usb-init.h +++ b/drivers/phy/broadcom/phy-brcm-usb-init.h @@ -34,6 +34,14 @@ enum brcmusb_reg_sel { brcm_usb_ctrl_unset(USB_CTRL_REG(base, reg), \ USB_CTRL_##reg##_##field##_MASK) +#define USB_XHCI_GBL_REG(base, reg) ((void __iomem *)base + USB_XHCI_GBL_##reg) +#define USB_XHCI_GBL_SET(base, reg, field) \ + brcm_usb_ctrl_set(USB_XHCI_GBL_REG(base, reg), \ + USB_XHCI_GBL_##reg##_##field##_MASK) +#define USB_XHCI_GBL_UNSET(base, reg, field) \ + brcm_usb_ctrl_unset(USB_XHCI_GBL_REG(base, reg), \ + USB_XHCI_GBL_##reg##_##field##_MASK) + struct brcm_usb_init_params; struct brcm_usb_init_ops { diff --git a/drivers/phy/cadence/phy-cadence-salvo.c b/drivers/phy/cadence/phy-cadence-salvo.c index e569f5f67578c02732eade5b59f7096f1feb43fb..f461585c84c62ffb3d194bfa01f23570f4c01770 100644 --- a/drivers/phy/cadence/phy-cadence-salvo.c +++ b/drivers/phy/cadence/phy-cadence-salvo.c @@ -6,6 +6,7 @@ * Copyright (c) 2019-2020 NXP */ +#include #include #include #include @@ -15,7 +16,9 @@ #include #include -/* PHY register definition */ +#define USB3_PHY_OFFSET 0x0 +#define USB2_PHY_OFFSET 0x38000 +/* USB3 PHY register definition */ #define PHY_PMA_CMN_CTRL1 0xC800 #define TB_ADDR_CMN_DIAG_HSCLK_SEL 0x01e0 #define TB_ADDR_CMN_PLL0_VCOCAL_INIT_TMR 0x0084 @@ -87,8 +90,35 @@ #define TB_ADDR_XCVR_DIAG_LANE_FCM_EN_MGN_TMR 0x40f2 #define TB_ADDR_TX_RCVDETSC_CTRL 0x4124 +/* USB2 PHY register definition */ +#define UTMI_REG15 0xaf +#define UTMI_AFE_RX_REG0 0x0d +#define UTMI_AFE_RX_REG5 0x12 +#define UTMI_AFE_BC_REG4 0x29 + +/* Align UTMI_AFE_RX_REG0 bit[7:6] define */ +enum usb2_disconn_threshold { + USB2_DISCONN_THRESHOLD_575 = 0x0, + USB2_DISCONN_THRESHOLD_610 = 0x1, + USB2_DISCONN_THRESHOLD_645 = 0x3, +}; + +#define RX_USB2_DISCONN_MASK GENMASK(7, 6) + /* TB_ADDR_TX_RCVDETSC_CTRL */ #define RXDET_IN_P3_32KHZ BIT(0) +/* + * UTMI_REG15 + * + * Gate how many us for the txvalid signal until analog + * HS/FS transmitters have powered up + */ +#define TXVALID_GATE_THRESHOLD_HS_MASK (BIT(4) | BIT(5)) +/* 0us, txvalid is ready just after HS/FS transmitters have powered up */ +#define TXVALID_GATE_THRESHOLD_HS_0US (BIT(4) | BIT(5)) + +#define SET_B_SESSION_VALID (BIT(6) | BIT(5)) +#define CLR_B_SESSION_VALID (BIT(6)) struct cdns_reg_pairs { u16 val; @@ -106,19 +136,27 @@ struct cdns_salvo_phy { struct clk *clk; void __iomem *base; struct cdns_salvo_data *data; + enum usb2_disconn_threshold usb2_disconn; }; static const struct of_device_id cdns_salvo_phy_of_match[]; -static u16 cdns_salvo_read(struct cdns_salvo_phy *salvo_phy, u32 reg) +static const struct cdns_salvo_data cdns_nxp_salvo_data; + +static bool cdns_is_nxp_phy(struct cdns_salvo_phy *salvo_phy) +{ + return salvo_phy->data == &cdns_nxp_salvo_data; +} + +static u16 cdns_salvo_read(struct cdns_salvo_phy *salvo_phy, u32 offset, u32 reg) { - return (u16)readl(salvo_phy->base + + return (u16)readl(salvo_phy->base + offset + reg * (1 << salvo_phy->data->reg_offset_shift)); } -static void cdns_salvo_write(struct cdns_salvo_phy *salvo_phy, +static void cdns_salvo_write(struct cdns_salvo_phy *salvo_phy, u32 offset, u32 reg, u16 val) { - writel(val, salvo_phy->base + + writel(val, salvo_phy->base + offset + reg * (1 << salvo_phy->data->reg_offset_shift)); } @@ -219,15 +257,27 @@ static int cdns_salvo_phy_init(struct phy *phy) for (i = 0; i < data->init_sequence_length; i++) { const struct cdns_reg_pairs *reg_pair = data->init_sequence_val + i; - cdns_salvo_write(salvo_phy, reg_pair->off, reg_pair->val); + cdns_salvo_write(salvo_phy, USB3_PHY_OFFSET, reg_pair->off, reg_pair->val); } /* RXDET_IN_P3_32KHZ, Receiver detect slow clock enable */ - value = cdns_salvo_read(salvo_phy, TB_ADDR_TX_RCVDETSC_CTRL); + value = cdns_salvo_read(salvo_phy, USB3_PHY_OFFSET, TB_ADDR_TX_RCVDETSC_CTRL); value |= RXDET_IN_P3_32KHZ; - cdns_salvo_write(salvo_phy, TB_ADDR_TX_RCVDETSC_CTRL, + cdns_salvo_write(salvo_phy, USB3_PHY_OFFSET, TB_ADDR_TX_RCVDETSC_CTRL, RXDET_IN_P3_32KHZ); + value = cdns_salvo_read(salvo_phy, USB2_PHY_OFFSET, UTMI_REG15); + value &= ~TXVALID_GATE_THRESHOLD_HS_MASK; + cdns_salvo_write(salvo_phy, USB2_PHY_OFFSET, UTMI_REG15, + value | TXVALID_GATE_THRESHOLD_HS_0US); + + cdns_salvo_write(salvo_phy, USB2_PHY_OFFSET, UTMI_AFE_RX_REG5, 0x5); + + value = cdns_salvo_read(salvo_phy, USB2_PHY_OFFSET, UTMI_AFE_RX_REG0); + value &= ~RX_USB2_DISCONN_MASK; + value = FIELD_PREP(RX_USB2_DISCONN_MASK, salvo_phy->usb2_disconn); + cdns_salvo_write(salvo_phy, USB2_PHY_OFFSET, UTMI_AFE_RX_REG0, value); + udelay(10); clk_disable_unprepare(salvo_phy->clk); @@ -251,11 +301,29 @@ static int cdns_salvo_phy_power_off(struct phy *phy) return 0; } +static int cdns_salvo_set_mode(struct phy *phy, enum phy_mode mode, int submode) +{ + struct cdns_salvo_phy *salvo_phy = phy_get_drvdata(phy); + + if (!cdns_is_nxp_phy(salvo_phy)) + return 0; + + if (mode == PHY_MODE_USB_DEVICE) + cdns_salvo_write(salvo_phy, USB2_PHY_OFFSET, UTMI_AFE_BC_REG4, + SET_B_SESSION_VALID); + else + cdns_salvo_write(salvo_phy, USB2_PHY_OFFSET, UTMI_AFE_BC_REG4, + CLR_B_SESSION_VALID); + + return 0; +} + static const struct phy_ops cdns_salvo_phy_ops = { .init = cdns_salvo_phy_init, .power_on = cdns_salvo_phy_power_on, .power_off = cdns_salvo_phy_power_off, .owner = THIS_MODULE, + .set_mode = cdns_salvo_set_mode, }; static int cdns_salvo_phy_probe(struct platform_device *pdev) @@ -264,6 +332,7 @@ static int cdns_salvo_phy_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct cdns_salvo_phy *salvo_phy; struct cdns_salvo_data *data; + u32 val; data = (struct cdns_salvo_data *)of_device_get_match_data(dev); salvo_phy = devm_kzalloc(dev, sizeof(*salvo_phy), GFP_KERNEL); @@ -275,6 +344,16 @@ static int cdns_salvo_phy_probe(struct platform_device *pdev) if (IS_ERR(salvo_phy->clk)) return PTR_ERR(salvo_phy->clk); + if (of_property_read_u32(dev->of_node, "cdns,usb2-disconnect-threshold-microvolt", &val)) + val = 575; + + if (val < 610) + salvo_phy->usb2_disconn = USB2_DISCONN_THRESHOLD_575; + else if (val < 645) + salvo_phy->usb2_disconn = USB2_DISCONN_THRESHOLD_610; + else + salvo_phy->usb2_disconn = USB2_DISCONN_THRESHOLD_645; + salvo_phy->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(salvo_phy->base)) return PTR_ERR(salvo_phy->base); diff --git a/drivers/phy/cadence/phy-cadence-sierra.c b/drivers/phy/cadence/phy-cadence-sierra.c index 13fcd3a65fe91b1b181b1046800243be0f1fa2d5..7df9c79a772aa44f8e46680e56da8accc2584141 100644 --- a/drivers/phy/cadence/phy-cadence-sierra.c +++ b/drivers/phy/cadence/phy-cadence-sierra.c @@ -720,6 +720,7 @@ static int cdns_sierra_pll_mux_set_parent(struct clk_hw *hw, u8 index) } static const struct clk_ops cdns_sierra_pll_mux_ops = { + .determine_rate = __clk_mux_determine_rate, .set_parent = cdns_sierra_pll_mux_set_parent, .get_parent = cdns_sierra_pll_mux_get_parent, }; diff --git a/drivers/phy/cadence/phy-cadence-torrent.c b/drivers/phy/cadence/phy-cadence-torrent.c index 3831f596d50c78d4a6c7c748f34adcc7d6967095..37b6b5c05be859991eef7c74bc0c3b9db31dbb08 100644 --- a/drivers/phy/cadence/phy-cadence-torrent.c +++ b/drivers/phy/cadence/phy-cadence-torrent.c @@ -38,6 +38,9 @@ #define POLL_TIMEOUT_US 5000 #define PLL_LOCK_TIMEOUT 100000 +#define DP_PLL0 BIT(0) +#define DP_PLL1 BIT(1) + #define TORRENT_COMMON_CDB_OFFSET 0x0 #define TORRENT_TX_LANE_CDB_OFFSET(ln, block_offset, reg_offset) \ @@ -66,16 +69,11 @@ */ #define PHY_AUX_CTRL 0x04 #define PHY_RESET 0x20 -#define PMA_TX_ELEC_IDLE_MASK 0xF0U #define PMA_TX_ELEC_IDLE_SHIFT 4 -#define PHY_L00_RESET_N_MASK 0x01U #define PHY_PMA_XCVR_PLLCLK_EN 0x24 #define PHY_PMA_XCVR_PLLCLK_EN_ACK 0x28 #define PHY_PMA_XCVR_POWER_STATE_REQ 0x2c -#define PHY_POWER_STATE_LN_0 0x0000 -#define PHY_POWER_STATE_LN_1 0x0008 -#define PHY_POWER_STATE_LN_2 0x0010 -#define PHY_POWER_STATE_LN_3 0x0018 +#define PHY_POWER_STATE_LN(ln) ((ln) * 8) #define PMA_XCVR_POWER_STATE_REQ_LN_MASK 0x3FU #define PHY_PMA_XCVR_POWER_STATE_ACK 0x30 #define PHY_PMA_CMN_READY 0x34 @@ -323,6 +321,7 @@ struct cdns_torrent_phy { void __iomem *base; /* DPTX registers base */ void __iomem *sd_base; /* SD0801 registers base */ u32 max_bit_rate; /* Maximum link bit rate to use (in Mbps) */ + u32 dp_pll; struct reset_control *phy_rst; struct reset_control *apb_rst; struct device *dev; @@ -905,88 +904,129 @@ void cdns_torrent_dp_pma_cmn_vco_cfg_100mhz(struct cdns_torrent_phy *cdns_phy, /* Setting VCO for 10.8GHz */ case 2700: case 5400: - cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_PADJ_M0, 0x0028); - cdns_torrent_phy_write(regmap, CMN_PLL0_DSM_FBH_OVRD_M0, 0x0022); - cdns_torrent_phy_write(regmap, CMN_PLL1_DSM_FBH_OVRD_M0, 0x0022); - cdns_torrent_phy_write(regmap, CMN_PLL1_DSM_FBL_OVRD_M0, 0x000C); + if (cdns_phy->dp_pll & DP_PLL0) + cdns_torrent_phy_write(regmap, CMN_PLL0_DSM_FBH_OVRD_M0, 0x0022); + + if (cdns_phy->dp_pll & DP_PLL1) { + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_PADJ_M0, 0x0028); + cdns_torrent_phy_write(regmap, CMN_PLL1_DSM_FBH_OVRD_M0, 0x0022); + cdns_torrent_phy_write(regmap, CMN_PLL1_DSM_FBL_OVRD_M0, 0x000C); + } break; /* Setting VCO for 9.72GHz */ case 1620: case 2430: case 3240: - cdns_torrent_phy_write(regmap, CMN_PLL0_DSM_DIAG_M0, 0x0004); - cdns_torrent_phy_write(regmap, CMN_PLL1_DSM_DIAG_M0, 0x0004); - cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CP_PADJ_M0, 0x0509); - cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_PADJ_M0, 0x0509); - cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CP_IADJ_M0, 0x0F00); - cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_IADJ_M0, 0x0F00); - cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_FILT_PADJ_M0, 0x0F08); - cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_FILT_PADJ_M0, 0x0F08); - cdns_torrent_phy_write(regmap, CMN_PLL0_INTDIV_M0, 0x0061); - cdns_torrent_phy_write(regmap, CMN_PLL1_INTDIV_M0, 0x0061); - cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVL_M0, 0x3333); - cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVL_M0, 0x3333); - cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVH_M0, 0x0002); - cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVH_M0, 0x0002); - cdns_torrent_phy_write(regmap, CMN_PLL0_HIGH_THR_M0, 0x0042); - cdns_torrent_phy_write(regmap, CMN_PLL1_HIGH_THR_M0, 0x0042); - cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CTRL_M0, 0x0002); - cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CTRL_M0, 0x0002); + if (cdns_phy->dp_pll & DP_PLL0) { + cdns_torrent_phy_write(regmap, CMN_PLL0_DSM_DIAG_M0, 0x0004); + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CP_PADJ_M0, 0x0509); + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CP_IADJ_M0, 0x0F00); + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_FILT_PADJ_M0, 0x0F08); + cdns_torrent_phy_write(regmap, CMN_PLL0_INTDIV_M0, 0x0061); + cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVL_M0, 0x3333); + cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVH_M0, 0x0002); + cdns_torrent_phy_write(regmap, CMN_PLL0_HIGH_THR_M0, 0x0042); + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CTRL_M0, 0x0002); + } + if (cdns_phy->dp_pll & DP_PLL1) { + cdns_torrent_phy_write(regmap, CMN_PLL1_DSM_DIAG_M0, 0x0004); + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_PADJ_M0, 0x0509); + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_IADJ_M0, 0x0F00); + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_FILT_PADJ_M0, 0x0F08); + cdns_torrent_phy_write(regmap, CMN_PLL1_INTDIV_M0, 0x0061); + cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVL_M0, 0x3333); + cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVH_M0, 0x0002); + cdns_torrent_phy_write(regmap, CMN_PLL1_HIGH_THR_M0, 0x0042); + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CTRL_M0, 0x0002); + } break; /* Setting VCO for 8.64GHz */ case 2160: case 4320: - cdns_torrent_phy_write(regmap, CMN_PLL0_DSM_DIAG_M0, 0x0004); - cdns_torrent_phy_write(regmap, CMN_PLL1_DSM_DIAG_M0, 0x0004); - cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CP_PADJ_M0, 0x0509); - cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_PADJ_M0, 0x0509); - cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CP_IADJ_M0, 0x0F00); - cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_IADJ_M0, 0x0F00); - cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_FILT_PADJ_M0, 0x0F08); - cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_FILT_PADJ_M0, 0x0F08); - cdns_torrent_phy_write(regmap, CMN_PLL0_INTDIV_M0, 0x0056); - cdns_torrent_phy_write(regmap, CMN_PLL1_INTDIV_M0, 0x0056); - cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVL_M0, 0x6666); - cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVL_M0, 0x6666); - cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVH_M0, 0x0002); - cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVH_M0, 0x0002); - cdns_torrent_phy_write(regmap, CMN_PLL0_HIGH_THR_M0, 0x003A); - cdns_torrent_phy_write(regmap, CMN_PLL1_HIGH_THR_M0, 0x003A); - cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CTRL_M0, 0x0002); - cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CTRL_M0, 0x0002); + if (cdns_phy->dp_pll & DP_PLL0) { + cdns_torrent_phy_write(regmap, CMN_PLL0_DSM_DIAG_M0, 0x0004); + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CP_PADJ_M0, 0x0509); + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CP_IADJ_M0, 0x0F00); + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_FILT_PADJ_M0, 0x0F08); + cdns_torrent_phy_write(regmap, CMN_PLL0_INTDIV_M0, 0x0056); + cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVL_M0, 0x6666); + cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVH_M0, 0x0002); + cdns_torrent_phy_write(regmap, CMN_PLL0_HIGH_THR_M0, 0x003A); + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CTRL_M0, 0x0002); + } + if (cdns_phy->dp_pll & DP_PLL1) { + cdns_torrent_phy_write(regmap, CMN_PLL1_DSM_DIAG_M0, 0x0004); + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_PADJ_M0, 0x0509); + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_IADJ_M0, 0x0F00); + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_FILT_PADJ_M0, 0x0F08); + cdns_torrent_phy_write(regmap, CMN_PLL1_INTDIV_M0, 0x0056); + cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVL_M0, 0x6666); + cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVH_M0, 0x0002); + cdns_torrent_phy_write(regmap, CMN_PLL1_HIGH_THR_M0, 0x003A); + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CTRL_M0, 0x0002); + } break; /* Setting VCO for 8.1GHz */ case 8100: - cdns_torrent_phy_write(regmap, CMN_PLL0_DSM_DIAG_M0, 0x0004); - cdns_torrent_phy_write(regmap, CMN_PLL1_DSM_DIAG_M0, 0x0004); - cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CP_PADJ_M0, 0x0509); - cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_PADJ_M0, 0x0509); - cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CP_IADJ_M0, 0x0F00); - cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_IADJ_M0, 0x0F00); - cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_FILT_PADJ_M0, 0x0F08); - cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_FILT_PADJ_M0, 0x0F08); - cdns_torrent_phy_write(regmap, CMN_PLL0_INTDIV_M0, 0x0051); - cdns_torrent_phy_write(regmap, CMN_PLL1_INTDIV_M0, 0x0051); - cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVH_M0, 0x0002); - cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVH_M0, 0x0002); - cdns_torrent_phy_write(regmap, CMN_PLL0_HIGH_THR_M0, 0x0036); - cdns_torrent_phy_write(regmap, CMN_PLL1_HIGH_THR_M0, 0x0036); - cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CTRL_M0, 0x0002); - cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CTRL_M0, 0x0002); + if (cdns_phy->dp_pll & DP_PLL0) { + cdns_torrent_phy_write(regmap, CMN_PLL0_DSM_DIAG_M0, 0x0004); + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CP_PADJ_M0, 0x0509); + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CP_IADJ_M0, 0x0F00); + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_FILT_PADJ_M0, 0x0F08); + cdns_torrent_phy_write(regmap, CMN_PLL0_INTDIV_M0, 0x0051); + cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVH_M0, 0x0002); + cdns_torrent_phy_write(regmap, CMN_PLL0_HIGH_THR_M0, 0x0036); + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CTRL_M0, 0x0002); + } + if (cdns_phy->dp_pll & DP_PLL1) { + cdns_torrent_phy_write(regmap, CMN_PLL1_DSM_DIAG_M0, 0x0004); + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_PADJ_M0, 0x0509); + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_IADJ_M0, 0x0F00); + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_FILT_PADJ_M0, 0x0F08); + cdns_torrent_phy_write(regmap, CMN_PLL1_INTDIV_M0, 0x0051); + cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVH_M0, 0x0002); + cdns_torrent_phy_write(regmap, CMN_PLL1_HIGH_THR_M0, 0x0036); + cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CTRL_M0, 0x0002); + } break; } } +/* Set PLL used for DP configuration */ +static int cdns_torrent_dp_get_pll(struct cdns_torrent_phy *cdns_phy, + enum cdns_torrent_phy_type phy_t2) +{ + switch (phy_t2) { + case TYPE_PCIE: + case TYPE_USB: + cdns_phy->dp_pll = DP_PLL1; + break; + case TYPE_SGMII: + case TYPE_QSGMII: + cdns_phy->dp_pll = DP_PLL0; + break; + case TYPE_NONE: + cdns_phy->dp_pll = DP_PLL0 | DP_PLL1; + break; + default: + dev_err(cdns_phy->dev, "Unsupported PHY configuration\n"); + return -EINVAL; + } + + return 0; +} + /* * Enable or disable PLL for selected lanes. */ static int cdns_torrent_dp_set_pll_en(struct cdns_torrent_phy *cdns_phy, + struct cdns_torrent_inst *inst, struct phy_configure_opts_dp *dp, bool enable) { - u32 rd_val; - u32 ret; struct regmap *regmap = cdns_phy->regmap_dptx_phy_reg; + u32 rd_val, pll_ack_val; + int ret; /* * Used to determine, which bits to check for or enable in @@ -996,28 +1036,18 @@ static int cdns_torrent_dp_set_pll_en(struct cdns_torrent_phy *cdns_phy, /* Used to enable or disable lanes. */ u32 pll_val; - /* Select values of registers and mask, depending on enabled lane - * count. - */ - switch (dp->lanes) { - /* lane 0 */ - case (1): - pll_bits = 0x00000001; - break; - /* lanes 0-1 */ - case (2): - pll_bits = 0x00000003; - break; - /* lanes 0-3, all */ - default: - pll_bits = 0x0000000F; - break; - } + /* Select values of registers and mask, depending on enabled lane count. */ + pll_val = cdns_torrent_dp_read(regmap, PHY_PMA_XCVR_PLLCLK_EN); - if (enable) - pll_val = pll_bits; - else - pll_val = 0x00000000; + if (enable) { + pll_bits = ((1 << dp->lanes) - 1); + pll_val |= pll_bits; + pll_ack_val = pll_bits; + } else { + pll_bits = ((1 << inst->num_lanes) - 1); + pll_val &= (~pll_bits); + pll_ack_val = 0; + } cdns_torrent_dp_write(regmap, PHY_PMA_XCVR_PLLCLK_EN, pll_val); @@ -1025,22 +1055,23 @@ static int cdns_torrent_dp_set_pll_en(struct cdns_torrent_phy *cdns_phy, ret = regmap_read_poll_timeout(regmap, PHY_PMA_XCVR_PLLCLK_EN_ACK, rd_val, - (rd_val & pll_bits) == pll_val, + (rd_val & pll_bits) == pll_ack_val, 0, POLL_TIMEOUT_US); ndelay(100); return ret; } static int cdns_torrent_dp_set_power_state(struct cdns_torrent_phy *cdns_phy, + struct cdns_torrent_inst *inst, u32 num_lanes, enum phy_powerstate powerstate) { /* Register value for power state for a single byte. */ - u32 value_part; - u32 value; - u32 mask; + u32 value_part, i; + u32 value = 0; + u32 mask = 0; u32 read_val; - u32 ret; + int ret; struct regmap *regmap = cdns_phy->regmap_dptx_phy_reg; switch (powerstate) { @@ -1056,29 +1087,11 @@ static int cdns_torrent_dp_set_power_state(struct cdns_torrent_phy *cdns_phy, break; } - /* Select values of registers and mask, depending on enabled - * lane count. - */ - switch (num_lanes) { - /* lane 0 */ - case (1): - value = value_part; - mask = 0x0000003FU; - break; - /* lanes 0-1 */ - case (2): - value = (value_part - | (value_part << 8)); - mask = 0x00003F3FU; - break; - /* lanes 0-3, all */ - default: - value = (value_part - | (value_part << 8) - | (value_part << 16) - | (value_part << 24)); - mask = 0x3F3F3F3FU; - break; + /* Select values of registers and mask, depending on enabled lane count. */ + + for (i = 0; i < num_lanes; i++) { + value |= (value_part << PHY_POWER_STATE_LN(i)); + mask |= (PMA_XCVR_POWER_STATE_REQ_LN_MASK << PHY_POWER_STATE_LN(i)); } /* Set power state A. */ @@ -1093,7 +1106,8 @@ static int cdns_torrent_dp_set_power_state(struct cdns_torrent_phy *cdns_phy, return ret; } -static int cdns_torrent_dp_run(struct cdns_torrent_phy *cdns_phy, u32 num_lanes) +static int cdns_torrent_dp_run(struct cdns_torrent_phy *cdns_phy, + struct cdns_torrent_inst *inst, u32 num_lanes) { unsigned int read_val; int ret; @@ -1114,12 +1128,12 @@ static int cdns_torrent_dp_run(struct cdns_torrent_phy *cdns_phy, u32 num_lanes) ndelay(100); - ret = cdns_torrent_dp_set_power_state(cdns_phy, num_lanes, + ret = cdns_torrent_dp_set_power_state(cdns_phy, inst, num_lanes, POWERSTATE_A2); if (ret) return ret; - ret = cdns_torrent_dp_set_power_state(cdns_phy, num_lanes, + ret = cdns_torrent_dp_set_power_state(cdns_phy, inst, num_lanes, POWERSTATE_A0); return ret; @@ -1143,6 +1157,7 @@ static int cdns_torrent_dp_wait_pma_cmn_ready(struct cdns_torrent_phy *cdns_phy) } static void cdns_torrent_dp_pma_cmn_rate(struct cdns_torrent_phy *cdns_phy, + struct cdns_torrent_inst *inst, u32 rate, u32 num_lanes) { unsigned int clk_sel_val = 0; @@ -1175,14 +1190,17 @@ static void cdns_torrent_dp_pma_cmn_rate(struct cdns_torrent_phy *cdns_phy, break; } - cdns_torrent_phy_write(cdns_phy->regmap_common_cdb, - CMN_PDIAG_PLL0_CLK_SEL_M0, clk_sel_val); - cdns_torrent_phy_write(cdns_phy->regmap_common_cdb, - CMN_PDIAG_PLL1_CLK_SEL_M0, clk_sel_val); + if (cdns_phy->dp_pll & DP_PLL0) + cdns_torrent_phy_write(cdns_phy->regmap_common_cdb, + CMN_PDIAG_PLL0_CLK_SEL_M0, clk_sel_val); + + if (cdns_phy->dp_pll & DP_PLL1) + cdns_torrent_phy_write(cdns_phy->regmap_common_cdb, + CMN_PDIAG_PLL1_CLK_SEL_M0, clk_sel_val); /* PMA lane configuration to deal with multi-link operation */ for (i = 0; i < num_lanes; i++) - cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[i], + cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[inst->mlane + i], XCVR_DIAG_HSCLK_DIV, hsclk_div_val); } @@ -1191,23 +1209,44 @@ static void cdns_torrent_dp_pma_cmn_rate(struct cdns_torrent_phy *cdns_phy, * set and PLL disable request was processed. */ static int cdns_torrent_dp_configure_rate(struct cdns_torrent_phy *cdns_phy, + struct cdns_torrent_inst *inst, struct phy_configure_opts_dp *dp) { - u32 read_val, ret; + u32 read_val, field_val; + int ret; - /* Disable the cmn_pll0_en before re-programming the new data rate. */ - regmap_field_write(cdns_phy->phy_pma_pll_raw_ctrl, 0x0); + /* + * Disable the associated PLL (cmn_pll0_en or cmn_pll1_en) before + * re-programming the new data rate. + */ + ret = regmap_field_read(cdns_phy->phy_pma_pll_raw_ctrl, &field_val); + if (ret) + return ret; + field_val &= ~(cdns_phy->dp_pll); + regmap_field_write(cdns_phy->phy_pma_pll_raw_ctrl, field_val); /* * Wait for PLL ready de-assertion. * For PLL0 - PHY_PMA_CMN_CTRL2[2] == 1 + * For PLL1 - PHY_PMA_CMN_CTRL2[3] == 1 */ - ret = regmap_field_read_poll_timeout(cdns_phy->phy_pma_cmn_ctrl_2, - read_val, - ((read_val >> 2) & 0x01) != 0, - 0, POLL_TIMEOUT_US); - if (ret) - return ret; + if (cdns_phy->dp_pll & DP_PLL0) { + ret = regmap_field_read_poll_timeout(cdns_phy->phy_pma_cmn_ctrl_2, + read_val, + ((read_val >> 2) & 0x01) != 0, + 0, POLL_TIMEOUT_US); + if (ret) + return ret; + } + + if ((cdns_phy->dp_pll & DP_PLL1) && cdns_phy->nsubnodes != 1) { + ret = regmap_field_read_poll_timeout(cdns_phy->phy_pma_cmn_ctrl_2, + read_val, + ((read_val >> 3) & 0x01) != 0, + 0, POLL_TIMEOUT_US); + if (ret) + return ret; + } ndelay(200); /* DP Rate Change - VCO Output settings. */ @@ -1221,19 +1260,35 @@ static int cdns_torrent_dp_configure_rate(struct cdns_torrent_phy *cdns_phy, /* PMA common configuration 100MHz */ cdns_torrent_dp_pma_cmn_vco_cfg_100mhz(cdns_phy, dp->link_rate, dp->ssc); - cdns_torrent_dp_pma_cmn_rate(cdns_phy, dp->link_rate, dp->lanes); + cdns_torrent_dp_pma_cmn_rate(cdns_phy, inst, dp->link_rate, dp->lanes); - /* Enable the cmn_pll0_en. */ - regmap_field_write(cdns_phy->phy_pma_pll_raw_ctrl, 0x3); + /* Enable the associated PLL (cmn_pll0_en or cmn_pll1_en) */ + ret = regmap_field_read(cdns_phy->phy_pma_pll_raw_ctrl, &field_val); + if (ret) + return ret; + field_val |= cdns_phy->dp_pll; + regmap_field_write(cdns_phy->phy_pma_pll_raw_ctrl, field_val); /* * Wait for PLL ready assertion. * For PLL0 - PHY_PMA_CMN_CTRL2[0] == 1 + * For PLL1 - PHY_PMA_CMN_CTRL2[1] == 1 */ - ret = regmap_field_read_poll_timeout(cdns_phy->phy_pma_cmn_ctrl_2, - read_val, - (read_val & 0x01) != 0, - 0, POLL_TIMEOUT_US); + if (cdns_phy->dp_pll & DP_PLL0) { + ret = regmap_field_read_poll_timeout(cdns_phy->phy_pma_cmn_ctrl_2, + read_val, + (read_val & 0x01) != 0, + 0, POLL_TIMEOUT_US); + if (ret) + return ret; + } + + if ((cdns_phy->dp_pll & DP_PLL1) && cdns_phy->nsubnodes != 1) + ret = regmap_field_read_poll_timeout(cdns_phy->phy_pma_cmn_ctrl_2, + read_val, + ((read_val >> 1) & 0x01) != 0, + 0, POLL_TIMEOUT_US); + return ret; } @@ -1301,6 +1356,7 @@ static int cdns_torrent_dp_verify_config(struct cdns_torrent_inst *inst, /* Set power state A0 and PLL clock enable to 0 on enabled lanes. */ static void cdns_torrent_dp_set_a0_pll(struct cdns_torrent_phy *cdns_phy, + struct cdns_torrent_inst *inst, u32 num_lanes) { struct regmap *regmap = cdns_phy->regmap_dptx_phy_reg; @@ -1308,27 +1364,13 @@ static void cdns_torrent_dp_set_a0_pll(struct cdns_torrent_phy *cdns_phy, PHY_PMA_XCVR_POWER_STATE_REQ); u32 pll_clk_en = cdns_torrent_dp_read(regmap, PHY_PMA_XCVR_PLLCLK_EN); + u32 i; - /* Lane 0 is always enabled. */ - pwr_state &= ~(PMA_XCVR_POWER_STATE_REQ_LN_MASK << - PHY_POWER_STATE_LN_0); - pll_clk_en &= ~0x01U; - - if (num_lanes > 1) { - /* lane 1 */ - pwr_state &= ~(PMA_XCVR_POWER_STATE_REQ_LN_MASK << - PHY_POWER_STATE_LN_1); - pll_clk_en &= ~(0x01U << 1); - } + for (i = 0; i < num_lanes; i++) { + pwr_state &= ~(PMA_XCVR_POWER_STATE_REQ_LN_MASK + << PHY_POWER_STATE_LN(inst->mlane + i)); - if (num_lanes > 2) { - /* lanes 2 and 3 */ - pwr_state &= ~(PMA_XCVR_POWER_STATE_REQ_LN_MASK << - PHY_POWER_STATE_LN_2); - pwr_state &= ~(PMA_XCVR_POWER_STATE_REQ_LN_MASK << - PHY_POWER_STATE_LN_3); - pll_clk_en &= ~(0x01U << 2); - pll_clk_en &= ~(0x01U << 3); + pll_clk_en &= ~(0x01U << (inst->mlane + i)); } cdns_torrent_dp_write(regmap, PHY_PMA_XCVR_POWER_STATE_REQ, pwr_state); @@ -1337,36 +1379,57 @@ static void cdns_torrent_dp_set_a0_pll(struct cdns_torrent_phy *cdns_phy, /* Configure lane count as required. */ static int cdns_torrent_dp_set_lanes(struct cdns_torrent_phy *cdns_phy, + struct cdns_torrent_inst *inst, struct phy_configure_opts_dp *dp) { - u32 value; - u32 ret; + u32 value, i; + int ret; struct regmap *regmap = cdns_phy->regmap_dptx_phy_reg; u8 lane_mask = (1 << dp->lanes) - 1; + u8 pma_tx_elec_idle_mask = 0; + u32 clane = inst->mlane; + + lane_mask <<= clane; value = cdns_torrent_dp_read(regmap, PHY_RESET); /* clear pma_tx_elec_idle_ln_* bits. */ - value &= ~PMA_TX_ELEC_IDLE_MASK; + pma_tx_elec_idle_mask = ((1 << inst->num_lanes) - 1) << clane; + + pma_tx_elec_idle_mask <<= PMA_TX_ELEC_IDLE_SHIFT; + + value &= ~pma_tx_elec_idle_mask; + /* Assert pma_tx_elec_idle_ln_* for disabled lanes. */ value |= ((~lane_mask) << PMA_TX_ELEC_IDLE_SHIFT) & - PMA_TX_ELEC_IDLE_MASK; + pma_tx_elec_idle_mask; + cdns_torrent_dp_write(regmap, PHY_RESET, value); - /* reset the link by asserting phy_l00_reset_n low */ + /* reset the link by asserting master lane phy_l0*_reset_n low */ cdns_torrent_dp_write(regmap, PHY_RESET, - value & (~PHY_L00_RESET_N_MASK)); + value & (~(1 << clane))); /* - * Assert lane reset on unused lanes and lane 0 so they remain in reset + * Assert lane reset on unused lanes and master lane so they remain in reset * and powered down when re-enabling the link */ - value = (value & 0x0000FFF0) | (0x0000000E & lane_mask); + for (i = 0; i < inst->num_lanes; i++) + value &= (~(1 << (clane + i))); + + for (i = 1; i < inst->num_lanes; i++) + value |= ((1 << (clane + i)) & lane_mask); + cdns_torrent_dp_write(regmap, PHY_RESET, value); - cdns_torrent_dp_set_a0_pll(cdns_phy, dp->lanes); + cdns_torrent_dp_set_a0_pll(cdns_phy, inst, dp->lanes); /* release phy_l0*_reset_n based on used laneCount */ - value = (value & 0x0000FFF0) | (0x0000000F & lane_mask); + for (i = 0; i < inst->num_lanes; i++) + value &= (~(1 << (clane + i))); + + for (i = 0; i < inst->num_lanes; i++) + value |= ((1 << (clane + i)) & lane_mask); + cdns_torrent_dp_write(regmap, PHY_RESET, value); /* Wait, until PHY gets ready after releasing PHY reset signal. */ @@ -1377,41 +1440,44 @@ static int cdns_torrent_dp_set_lanes(struct cdns_torrent_phy *cdns_phy, ndelay(100); /* release pma_xcvr_pllclk_en_ln_*, only for the master lane */ - cdns_torrent_dp_write(regmap, PHY_PMA_XCVR_PLLCLK_EN, 0x0001); + value = cdns_torrent_dp_read(regmap, PHY_PMA_XCVR_PLLCLK_EN); + value |= (1 << clane); + cdns_torrent_dp_write(regmap, PHY_PMA_XCVR_PLLCLK_EN, value); - ret = cdns_torrent_dp_run(cdns_phy, dp->lanes); + ret = cdns_torrent_dp_run(cdns_phy, inst, dp->lanes); return ret; } /* Configure link rate as required. */ static int cdns_torrent_dp_set_rate(struct cdns_torrent_phy *cdns_phy, + struct cdns_torrent_inst *inst, struct phy_configure_opts_dp *dp) { - u32 ret; + int ret; - ret = cdns_torrent_dp_set_power_state(cdns_phy, dp->lanes, + ret = cdns_torrent_dp_set_power_state(cdns_phy, inst, dp->lanes, POWERSTATE_A3); if (ret) return ret; - ret = cdns_torrent_dp_set_pll_en(cdns_phy, dp, false); + ret = cdns_torrent_dp_set_pll_en(cdns_phy, inst, dp, false); if (ret) return ret; ndelay(200); - ret = cdns_torrent_dp_configure_rate(cdns_phy, dp); + ret = cdns_torrent_dp_configure_rate(cdns_phy, inst, dp); if (ret) return ret; ndelay(200); - ret = cdns_torrent_dp_set_pll_en(cdns_phy, dp, true); + ret = cdns_torrent_dp_set_pll_en(cdns_phy, inst, dp, true); if (ret) return ret; - ret = cdns_torrent_dp_set_power_state(cdns_phy, dp->lanes, + ret = cdns_torrent_dp_set_power_state(cdns_phy, inst, dp->lanes, POWERSTATE_A2); if (ret) return ret; - ret = cdns_torrent_dp_set_power_state(cdns_phy, dp->lanes, + ret = cdns_torrent_dp_set_power_state(cdns_phy, inst, dp->lanes, POWERSTATE_A0); if (ret) return ret; @@ -1422,44 +1488,45 @@ static int cdns_torrent_dp_set_rate(struct cdns_torrent_phy *cdns_phy, /* Configure voltage swing and pre-emphasis for all enabled lanes. */ static void cdns_torrent_dp_set_voltages(struct cdns_torrent_phy *cdns_phy, + struct cdns_torrent_inst *inst, struct phy_configure_opts_dp *dp) { u8 lane; u16 val; for (lane = 0; lane < dp->lanes; lane++) { - val = cdns_torrent_phy_read(cdns_phy->regmap_tx_lane_cdb[lane], + val = cdns_torrent_phy_read(cdns_phy->regmap_tx_lane_cdb[inst->mlane + lane], TX_DIAG_ACYA); /* * Write 1 to register bit TX_DIAG_ACYA[0] to freeze the * current state of the analog TX driver. */ val |= TX_DIAG_ACYA_HBDC_MASK; - cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[lane], + cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[inst->mlane + lane], TX_DIAG_ACYA, val); - cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[lane], + cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[inst->mlane + lane], TX_TXCC_CTRL, 0x08A4); val = vltg_coeff[dp->voltage[lane]][dp->pre[lane]].diag_tx_drv; - cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[lane], + cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[inst->mlane + lane], DRV_DIAG_TX_DRV, val); val = vltg_coeff[dp->voltage[lane]][dp->pre[lane]].mgnfs_mult; - cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[lane], + cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[inst->mlane + lane], TX_TXCC_MGNFS_MULT_000, val); val = vltg_coeff[dp->voltage[lane]][dp->pre[lane]].cpost_mult; - cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[lane], + cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[inst->mlane + lane], TX_TXCC_CPOST_MULT_00, val); - val = cdns_torrent_phy_read(cdns_phy->regmap_tx_lane_cdb[lane], + val = cdns_torrent_phy_read(cdns_phy->regmap_tx_lane_cdb[inst->mlane + lane], TX_DIAG_ACYA); /* * Write 0 to register bit TX_DIAG_ACYA[0] to allow the state of * analog TX driver to reflect the new programmed one. */ val &= ~TX_DIAG_ACYA_HBDC_MASK; - cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[lane], + cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[inst->mlane + lane], TX_DIAG_ACYA, val); } }; @@ -1478,7 +1545,7 @@ static int cdns_torrent_dp_configure(struct phy *phy, } if (opts->dp.set_lanes) { - ret = cdns_torrent_dp_set_lanes(cdns_phy, &opts->dp); + ret = cdns_torrent_dp_set_lanes(cdns_phy, inst, &opts->dp); if (ret) { dev_err(&phy->dev, "cdns_torrent_dp_set_lanes failed\n"); return ret; @@ -1486,7 +1553,7 @@ static int cdns_torrent_dp_configure(struct phy *phy, } if (opts->dp.set_rate) { - ret = cdns_torrent_dp_set_rate(cdns_phy, &opts->dp); + ret = cdns_torrent_dp_set_rate(cdns_phy, inst, &opts->dp); if (ret) { dev_err(&phy->dev, "cdns_torrent_dp_set_rate failed\n"); return ret; @@ -1494,7 +1561,7 @@ static int cdns_torrent_dp_configure(struct phy *phy, } if (opts->dp.set_voltages) - cdns_torrent_dp_set_voltages(cdns_phy, &opts->dp); + cdns_torrent_dp_set_voltages(cdns_phy, inst, &opts->dp); return ret; } @@ -1562,6 +1629,7 @@ static void cdns_torrent_dp_common_init(struct cdns_torrent_phy *cdns_phy, { struct regmap *regmap = cdns_phy->regmap_dptx_phy_reg; unsigned char lane_bits; + u32 val; cdns_torrent_dp_write(regmap, PHY_AUX_CTRL, 0x0003); /* enable AUX */ @@ -1569,18 +1637,23 @@ static void cdns_torrent_dp_common_init(struct cdns_torrent_phy *cdns_phy, * Set lines power state to A0 * Set lines pll clk enable to 0 */ - cdns_torrent_dp_set_a0_pll(cdns_phy, inst->num_lanes); + cdns_torrent_dp_set_a0_pll(cdns_phy, inst, inst->num_lanes); /* * release phy_l0*_reset_n and pma_tx_elec_idle_ln_* based on * used lanes */ lane_bits = (1 << inst->num_lanes) - 1; - cdns_torrent_dp_write(regmap, PHY_RESET, - ((0xF & ~lane_bits) << 4) | (0xF & lane_bits)); + + val = cdns_torrent_dp_read(regmap, PHY_RESET); + val |= (0xF & lane_bits); + val &= ~(lane_bits << 4); + cdns_torrent_dp_write(regmap, PHY_RESET, val); /* release pma_xcvr_pllclk_en_ln_*, only for the master lane */ - cdns_torrent_dp_write(regmap, PHY_PMA_XCVR_PLLCLK_EN, 0x0001); + val = cdns_torrent_dp_read(regmap, PHY_PMA_XCVR_PLLCLK_EN); + val |= 1; + cdns_torrent_dp_write(regmap, PHY_PMA_XCVR_PLLCLK_EN, val); /* * PHY PMA registers configuration functions @@ -1599,7 +1672,7 @@ static void cdns_torrent_dp_common_init(struct cdns_torrent_phy *cdns_phy, cdns_phy->max_bit_rate, false); - cdns_torrent_dp_pma_cmn_rate(cdns_phy, cdns_phy->max_bit_rate, + cdns_torrent_dp_pma_cmn_rate(cdns_phy, inst, cdns_phy->max_bit_rate, inst->num_lanes); /* take out of reset */ @@ -1612,13 +1685,15 @@ static int cdns_torrent_dp_start(struct cdns_torrent_phy *cdns_phy, { int ret; - cdns_torrent_phy_on(phy); + ret = cdns_torrent_phy_on(phy); + if (ret) + return ret; ret = cdns_torrent_dp_wait_pma_cmn_ready(cdns_phy); if (ret) return ret; - ret = cdns_torrent_dp_run(cdns_phy, inst->num_lanes); + ret = cdns_torrent_dp_run(cdns_phy, inst, inst->num_lanes); return ret; } @@ -1627,6 +1702,7 @@ static int cdns_torrent_dp_init(struct phy *phy) { struct cdns_torrent_inst *inst = phy_get_drvdata(phy); struct cdns_torrent_phy *cdns_phy = dev_get_drvdata(phy->dev.parent); + int ret; switch (cdns_phy->ref_clk_rate) { case CLK_19_2_MHZ: @@ -1639,6 +1715,24 @@ static int cdns_torrent_dp_init(struct phy *phy) return -EINVAL; } + ret = cdns_torrent_dp_get_pll(cdns_phy, TYPE_NONE); + if (ret) + return ret; + + cdns_torrent_dp_common_init(cdns_phy, inst); + + return cdns_torrent_dp_start(cdns_phy, inst, phy); +} + +static int cdns_torrent_dp_multilink_init(struct cdns_torrent_phy *cdns_phy, + struct cdns_torrent_inst *inst, + struct phy *phy) +{ + if (cdns_phy->ref_clk_rate != CLK_100_MHZ) { + dev_err(cdns_phy->dev, "Unsupported Ref Clock Rate\n"); + return -EINVAL; + } + cdns_torrent_dp_common_init(cdns_phy, inst); return cdns_torrent_dp_start(cdns_phy, inst, phy); @@ -1861,6 +1955,7 @@ static const struct clk_ops cdns_torrent_refclk_driver_ops = { .enable = cdns_torrent_refclk_driver_enable, .disable = cdns_torrent_refclk_driver_disable, .is_enabled = cdns_torrent_refclk_driver_is_enabled, + .determine_rate = __clk_mux_determine_rate, .set_parent = cdns_torrent_refclk_driver_set_parent, .get_parent = cdns_torrent_refclk_driver_get_parent, }; @@ -2155,8 +2250,11 @@ static int cdns_torrent_phy_init(struct phy *phy) u32 num_regs; int i, j; - if (cdns_phy->nsubnodes > 1) + if (cdns_phy->nsubnodes > 1) { + if (phy_type == TYPE_DP) + return cdns_torrent_dp_multilink_init(cdns_phy, inst, phy); return 0; + } /** * Spread spectrum generation is not required or supported @@ -2398,6 +2496,12 @@ int cdns_torrent_phy_configure_multilink(struct cdns_torrent_phy *cdns_phy) } } + if (phy_t1 == TYPE_DP) { + ret = cdns_torrent_dp_get_pll(cdns_phy, phy_t2); + if (ret) + return ret; + } + reset_control_deassert(cdns_phy->phys[node].lnk_rst); } @@ -2793,6 +2897,109 @@ static void cdns_torrent_phy_remove(struct platform_device *pdev) cdns_torrent_clk_cleanup(cdns_phy); } +/* USB and DP link configuration */ +static struct cdns_reg_pairs usb_dp_link_cmn_regs[] = { + {0x0002, PHY_PLL_CFG}, + {0x8600, CMN_PDIAG_PLL0_CLK_SEL_M0} +}; + +static struct cdns_reg_pairs usb_dp_xcvr_diag_ln_regs[] = { + {0x0000, XCVR_DIAG_HSCLK_SEL}, + {0x0001, XCVR_DIAG_HSCLK_DIV}, + {0x0041, XCVR_DIAG_PLLDRC_CTRL} +}; + +static struct cdns_reg_pairs dp_usb_xcvr_diag_ln_regs[] = { + {0x0001, XCVR_DIAG_HSCLK_SEL}, + {0x0009, XCVR_DIAG_PLLDRC_CTRL} +}; + +static struct cdns_torrent_vals usb_dp_link_cmn_vals = { + .reg_pairs = usb_dp_link_cmn_regs, + .num_regs = ARRAY_SIZE(usb_dp_link_cmn_regs), +}; + +static struct cdns_torrent_vals usb_dp_xcvr_diag_ln_vals = { + .reg_pairs = usb_dp_xcvr_diag_ln_regs, + .num_regs = ARRAY_SIZE(usb_dp_xcvr_diag_ln_regs), +}; + +static struct cdns_torrent_vals dp_usb_xcvr_diag_ln_vals = { + .reg_pairs = dp_usb_xcvr_diag_ln_regs, + .num_regs = ARRAY_SIZE(dp_usb_xcvr_diag_ln_regs), +}; + +/* PCIe and DP link configuration */ +static struct cdns_reg_pairs pcie_dp_link_cmn_regs[] = { + {0x0003, PHY_PLL_CFG}, + {0x0601, CMN_PDIAG_PLL0_CLK_SEL_M0}, + {0x0400, CMN_PDIAG_PLL0_CLK_SEL_M1} +}; + +static struct cdns_reg_pairs pcie_dp_xcvr_diag_ln_regs[] = { + {0x0000, XCVR_DIAG_HSCLK_SEL}, + {0x0001, XCVR_DIAG_HSCLK_DIV}, + {0x0012, XCVR_DIAG_PLLDRC_CTRL} +}; + +static struct cdns_reg_pairs dp_pcie_xcvr_diag_ln_regs[] = { + {0x0001, XCVR_DIAG_HSCLK_SEL}, + {0x0009, XCVR_DIAG_PLLDRC_CTRL} +}; + +static struct cdns_torrent_vals pcie_dp_link_cmn_vals = { + .reg_pairs = pcie_dp_link_cmn_regs, + .num_regs = ARRAY_SIZE(pcie_dp_link_cmn_regs), +}; + +static struct cdns_torrent_vals pcie_dp_xcvr_diag_ln_vals = { + .reg_pairs = pcie_dp_xcvr_diag_ln_regs, + .num_regs = ARRAY_SIZE(pcie_dp_xcvr_diag_ln_regs), +}; + +static struct cdns_torrent_vals dp_pcie_xcvr_diag_ln_vals = { + .reg_pairs = dp_pcie_xcvr_diag_ln_regs, + .num_regs = ARRAY_SIZE(dp_pcie_xcvr_diag_ln_regs), +}; + +/* DP Multilink, 100 MHz Ref clk, no SSC */ +static struct cdns_reg_pairs dp_100_no_ssc_cmn_regs[] = { + {0x007F, CMN_TXPUCAL_TUNE}, + {0x007F, CMN_TXPDCAL_TUNE} +}; + +static struct cdns_reg_pairs dp_100_no_ssc_tx_ln_regs[] = { + {0x00FB, TX_PSC_A0}, + {0x04AA, TX_PSC_A2}, + {0x04AA, TX_PSC_A3}, + {0x000F, XCVR_DIAG_BIDI_CTRL} +}; + +static struct cdns_reg_pairs dp_100_no_ssc_rx_ln_regs[] = { + {0x0000, RX_PSC_A0}, + {0x0000, RX_PSC_A2}, + {0x0000, RX_PSC_A3}, + {0x0000, RX_PSC_CAL}, + {0x0000, RX_REE_GCSM1_CTRL}, + {0x0000, RX_REE_GCSM2_CTRL}, + {0x0000, RX_REE_PERGCSM_CTRL} +}; + +static struct cdns_torrent_vals dp_100_no_ssc_cmn_vals = { + .reg_pairs = dp_100_no_ssc_cmn_regs, + .num_regs = ARRAY_SIZE(dp_100_no_ssc_cmn_regs), +}; + +static struct cdns_torrent_vals dp_100_no_ssc_tx_ln_vals = { + .reg_pairs = dp_100_no_ssc_tx_ln_regs, + .num_regs = ARRAY_SIZE(dp_100_no_ssc_tx_ln_regs), +}; + +static struct cdns_torrent_vals dp_100_no_ssc_rx_ln_vals = { + .reg_pairs = dp_100_no_ssc_rx_ln_regs, + .num_regs = ARRAY_SIZE(dp_100_no_ssc_rx_ln_regs), +}; + /* Single DisplayPort(DP) link configuration */ static struct cdns_reg_pairs sl_dp_link_cmn_regs[] = { {0x0000, PHY_PLL_CFG}, @@ -3735,6 +3942,12 @@ static const struct cdns_torrent_data cdns_map_torrent = { [TYPE_NONE] = { [NO_SSC] = &sl_dp_link_cmn_vals, }, + [TYPE_PCIE] = { + [NO_SSC] = &pcie_dp_link_cmn_vals, + }, + [TYPE_USB] = { + [NO_SSC] = &usb_dp_link_cmn_vals, + }, }, [TYPE_PCIE] = { [TYPE_NONE] = { @@ -3757,6 +3970,9 @@ static const struct cdns_torrent_data cdns_map_torrent = { [EXTERNAL_SSC] = &pcie_usb_link_cmn_vals, [INTERNAL_SSC] = &pcie_usb_link_cmn_vals, }, + [TYPE_DP] = { + [NO_SSC] = &pcie_dp_link_cmn_vals, + }, }, [TYPE_SGMII] = { [TYPE_NONE] = { @@ -3809,6 +4025,9 @@ static const struct cdns_torrent_data cdns_map_torrent = { [EXTERNAL_SSC] = &usb_sgmii_link_cmn_vals, [INTERNAL_SSC] = &usb_sgmii_link_cmn_vals, }, + [TYPE_DP] = { + [NO_SSC] = &usb_dp_link_cmn_vals, + }, }, }, .xcvr_diag_vals = { @@ -3816,6 +4035,12 @@ static const struct cdns_torrent_data cdns_map_torrent = { [TYPE_NONE] = { [NO_SSC] = &sl_dp_xcvr_diag_ln_vals, }, + [TYPE_PCIE] = { + [NO_SSC] = &dp_pcie_xcvr_diag_ln_vals, + }, + [TYPE_USB] = { + [NO_SSC] = &dp_usb_xcvr_diag_ln_vals, + }, }, [TYPE_PCIE] = { [TYPE_NONE] = { @@ -3838,6 +4063,9 @@ static const struct cdns_torrent_data cdns_map_torrent = { [EXTERNAL_SSC] = &pcie_usb_xcvr_diag_ln_vals, [INTERNAL_SSC] = &pcie_usb_xcvr_diag_ln_vals, }, + [TYPE_DP] = { + [NO_SSC] = &pcie_dp_xcvr_diag_ln_vals, + }, }, [TYPE_SGMII] = { [TYPE_NONE] = { @@ -3890,6 +4118,9 @@ static const struct cdns_torrent_data cdns_map_torrent = { [EXTERNAL_SSC] = &usb_sgmii_xcvr_diag_ln_vals, [INTERNAL_SSC] = &usb_sgmii_xcvr_diag_ln_vals, }, + [TYPE_DP] = { + [NO_SSC] = &usb_dp_xcvr_diag_ln_vals, + }, }, }, .pcs_cmn_vals = { @@ -3914,6 +4145,9 @@ static const struct cdns_torrent_data cdns_map_torrent = { [EXTERNAL_SSC] = &usb_phy_pcs_cmn_vals, [INTERNAL_SSC] = &usb_phy_pcs_cmn_vals, }, + [TYPE_DP] = { + [NO_SSC] = &usb_phy_pcs_cmn_vals, + }, }, }, .cmn_vals = { @@ -3936,6 +4170,12 @@ static const struct cdns_torrent_data cdns_map_torrent = { [TYPE_NONE] = { [NO_SSC] = &sl_dp_100_no_ssc_cmn_vals, }, + [TYPE_PCIE] = { + [NO_SSC] = &dp_100_no_ssc_cmn_vals, + }, + [TYPE_USB] = { + [NO_SSC] = &sl_dp_100_no_ssc_cmn_vals, + }, }, [TYPE_PCIE] = { [TYPE_NONE] = { @@ -3958,6 +4198,9 @@ static const struct cdns_torrent_data cdns_map_torrent = { [EXTERNAL_SSC] = &pcie_100_no_ssc_cmn_vals, [INTERNAL_SSC] = &pcie_100_int_ssc_cmn_vals, }, + [TYPE_DP] = { + [NO_SSC] = NULL, + }, }, [TYPE_SGMII] = { [TYPE_NONE] = { @@ -4010,6 +4253,9 @@ static const struct cdns_torrent_data cdns_map_torrent = { [EXTERNAL_SSC] = &sl_usb_100_no_ssc_cmn_vals, [INTERNAL_SSC] = &sl_usb_100_int_ssc_cmn_vals, }, + [TYPE_DP] = { + [NO_SSC] = &usb_100_no_ssc_cmn_vals, + }, }, }, }, @@ -4033,6 +4279,12 @@ static const struct cdns_torrent_data cdns_map_torrent = { [TYPE_NONE] = { [NO_SSC] = &sl_dp_100_no_ssc_tx_ln_vals, }, + [TYPE_PCIE] = { + [NO_SSC] = &dp_100_no_ssc_tx_ln_vals, + }, + [TYPE_USB] = { + [NO_SSC] = &dp_100_no_ssc_tx_ln_vals, + }, }, [TYPE_PCIE] = { [TYPE_NONE] = { @@ -4055,6 +4307,9 @@ static const struct cdns_torrent_data cdns_map_torrent = { [EXTERNAL_SSC] = NULL, [INTERNAL_SSC] = NULL, }, + [TYPE_DP] = { + [NO_SSC] = NULL, + }, }, [TYPE_SGMII] = { [TYPE_NONE] = { @@ -4107,6 +4362,9 @@ static const struct cdns_torrent_data cdns_map_torrent = { [EXTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals, [INTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals, }, + [TYPE_DP] = { + [NO_SSC] = &usb_100_no_ssc_tx_ln_vals, + }, }, }, }, @@ -4130,6 +4388,12 @@ static const struct cdns_torrent_data cdns_map_torrent = { [TYPE_NONE] = { [NO_SSC] = &sl_dp_100_no_ssc_rx_ln_vals, }, + [TYPE_PCIE] = { + [NO_SSC] = &dp_100_no_ssc_rx_ln_vals, + }, + [TYPE_USB] = { + [NO_SSC] = &dp_100_no_ssc_rx_ln_vals, + }, }, [TYPE_PCIE] = { [TYPE_NONE] = { @@ -4152,6 +4416,9 @@ static const struct cdns_torrent_data cdns_map_torrent = { [EXTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals, [INTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals, }, + [TYPE_DP] = { + [NO_SSC] = &pcie_100_no_ssc_rx_ln_vals, + }, }, [TYPE_SGMII] = { [TYPE_NONE] = { @@ -4204,6 +4471,9 @@ static const struct cdns_torrent_data cdns_map_torrent = { [EXTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals, [INTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals, }, + [TYPE_DP] = { + [NO_SSC] = &usb_100_no_ssc_rx_ln_vals, + }, }, }, }, @@ -4217,6 +4487,12 @@ static const struct cdns_torrent_data ti_j721e_map_torrent = { [TYPE_NONE] = { [NO_SSC] = &sl_dp_link_cmn_vals, }, + [TYPE_PCIE] = { + [NO_SSC] = &pcie_dp_link_cmn_vals, + }, + [TYPE_USB] = { + [NO_SSC] = &usb_dp_link_cmn_vals, + }, }, [TYPE_PCIE] = { [TYPE_NONE] = { @@ -4239,6 +4515,9 @@ static const struct cdns_torrent_data ti_j721e_map_torrent = { [EXTERNAL_SSC] = &pcie_usb_link_cmn_vals, [INTERNAL_SSC] = &pcie_usb_link_cmn_vals, }, + [TYPE_DP] = { + [NO_SSC] = &pcie_dp_link_cmn_vals, + }, }, [TYPE_SGMII] = { [TYPE_NONE] = { @@ -4291,6 +4570,9 @@ static const struct cdns_torrent_data ti_j721e_map_torrent = { [EXTERNAL_SSC] = &usb_sgmii_link_cmn_vals, [INTERNAL_SSC] = &usb_sgmii_link_cmn_vals, }, + [TYPE_DP] = { + [NO_SSC] = &usb_dp_link_cmn_vals, + }, }, }, .xcvr_diag_vals = { @@ -4298,6 +4580,12 @@ static const struct cdns_torrent_data ti_j721e_map_torrent = { [TYPE_NONE] = { [NO_SSC] = &sl_dp_xcvr_diag_ln_vals, }, + [TYPE_PCIE] = { + [NO_SSC] = &dp_pcie_xcvr_diag_ln_vals, + }, + [TYPE_USB] = { + [NO_SSC] = &dp_usb_xcvr_diag_ln_vals, + }, }, [TYPE_PCIE] = { [TYPE_NONE] = { @@ -4320,6 +4608,9 @@ static const struct cdns_torrent_data ti_j721e_map_torrent = { [EXTERNAL_SSC] = &pcie_usb_xcvr_diag_ln_vals, [INTERNAL_SSC] = &pcie_usb_xcvr_diag_ln_vals, }, + [TYPE_DP] = { + [NO_SSC] = &pcie_dp_xcvr_diag_ln_vals, + }, }, [TYPE_SGMII] = { [TYPE_NONE] = { @@ -4372,6 +4663,9 @@ static const struct cdns_torrent_data ti_j721e_map_torrent = { [EXTERNAL_SSC] = &usb_sgmii_xcvr_diag_ln_vals, [INTERNAL_SSC] = &usb_sgmii_xcvr_diag_ln_vals, }, + [TYPE_DP] = { + [NO_SSC] = &usb_dp_xcvr_diag_ln_vals, + }, }, }, .pcs_cmn_vals = { @@ -4396,6 +4690,9 @@ static const struct cdns_torrent_data ti_j721e_map_torrent = { [EXTERNAL_SSC] = &usb_phy_pcs_cmn_vals, [INTERNAL_SSC] = &usb_phy_pcs_cmn_vals, }, + [TYPE_DP] = { + [NO_SSC] = &usb_phy_pcs_cmn_vals, + }, }, }, .cmn_vals = { @@ -4418,6 +4715,12 @@ static const struct cdns_torrent_data ti_j721e_map_torrent = { [TYPE_NONE] = { [NO_SSC] = &sl_dp_100_no_ssc_cmn_vals, }, + [TYPE_PCIE] = { + [NO_SSC] = &dp_100_no_ssc_cmn_vals, + }, + [TYPE_USB] = { + [NO_SSC] = &sl_dp_100_no_ssc_cmn_vals, + }, }, [TYPE_PCIE] = { [TYPE_NONE] = { @@ -4440,6 +4743,9 @@ static const struct cdns_torrent_data ti_j721e_map_torrent = { [EXTERNAL_SSC] = &pcie_100_no_ssc_cmn_vals, [INTERNAL_SSC] = &pcie_100_int_ssc_cmn_vals, }, + [TYPE_DP] = { + [NO_SSC] = NULL, + }, }, [TYPE_SGMII] = { [TYPE_NONE] = { @@ -4492,6 +4798,9 @@ static const struct cdns_torrent_data ti_j721e_map_torrent = { [EXTERNAL_SSC] = &sl_usb_100_no_ssc_cmn_vals, [INTERNAL_SSC] = &sl_usb_100_int_ssc_cmn_vals, }, + [TYPE_DP] = { + [NO_SSC] = &usb_100_no_ssc_cmn_vals, + }, }, }, }, @@ -4515,6 +4824,12 @@ static const struct cdns_torrent_data ti_j721e_map_torrent = { [TYPE_NONE] = { [NO_SSC] = &sl_dp_100_no_ssc_tx_ln_vals, }, + [TYPE_PCIE] = { + [NO_SSC] = &dp_100_no_ssc_tx_ln_vals, + }, + [TYPE_USB] = { + [NO_SSC] = &dp_100_no_ssc_tx_ln_vals, + }, }, [TYPE_PCIE] = { [TYPE_NONE] = { @@ -4537,6 +4852,9 @@ static const struct cdns_torrent_data ti_j721e_map_torrent = { [EXTERNAL_SSC] = NULL, [INTERNAL_SSC] = NULL, }, + [TYPE_DP] = { + [NO_SSC] = NULL, + }, }, [TYPE_SGMII] = { [TYPE_NONE] = { @@ -4589,6 +4907,9 @@ static const struct cdns_torrent_data ti_j721e_map_torrent = { [EXTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals, [INTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals, }, + [TYPE_DP] = { + [NO_SSC] = &usb_100_no_ssc_tx_ln_vals, + }, }, }, }, @@ -4612,6 +4933,12 @@ static const struct cdns_torrent_data ti_j721e_map_torrent = { [TYPE_NONE] = { [NO_SSC] = &sl_dp_100_no_ssc_rx_ln_vals, }, + [TYPE_PCIE] = { + [NO_SSC] = &dp_100_no_ssc_rx_ln_vals, + }, + [TYPE_USB] = { + [NO_SSC] = &dp_100_no_ssc_rx_ln_vals, + }, }, [TYPE_PCIE] = { [TYPE_NONE] = { @@ -4634,6 +4961,9 @@ static const struct cdns_torrent_data ti_j721e_map_torrent = { [EXTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals, [INTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals, }, + [TYPE_DP] = { + [NO_SSC] = &pcie_100_no_ssc_rx_ln_vals, + }, }, [TYPE_SGMII] = { [TYPE_NONE] = { @@ -4686,6 +5016,9 @@ static const struct cdns_torrent_data ti_j721e_map_torrent = { [EXTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals, [INTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals, }, + [TYPE_DP] = { + [NO_SSC] = &usb_100_no_ssc_rx_ln_vals, + }, }, }, }, diff --git a/drivers/phy/freescale/phy-fsl-imx8m-pcie.c b/drivers/phy/freescale/phy-fsl-imx8m-pcie.c index afc63552ecaf7994738f9cfad53ef852fde9aa3b..d4c92498ad1e30485dc6bc682836abdd3794565b 100644 --- a/drivers/phy/freescale/phy-fsl-imx8m-pcie.c +++ b/drivers/phy/freescale/phy-fsl-imx8m-pcie.c @@ -206,7 +206,6 @@ static int imx8_pcie_phy_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct device_node *np = dev->of_node; struct imx8_pcie_phy *imx8_phy; - struct resource *res; imx8_phy = devm_kzalloc(dev, sizeof(*imx8_phy), GFP_KERNEL); if (!imx8_phy) @@ -259,8 +258,7 @@ static int imx8_pcie_phy_probe(struct platform_device *pdev) "Failed to get PCIE PHY PERST control\n"); } - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - imx8_phy->base = devm_ioremap_resource(dev, res); + imx8_phy->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(imx8_phy->base)) return PTR_ERR(imx8_phy->base); diff --git a/drivers/phy/freescale/phy-fsl-imx8mq-usb.c b/drivers/phy/freescale/phy-fsl-imx8mq-usb.c index a29b4a6f7c249bae07e86eb466afd8fccb84d155..88826ceb72f8d36ee1bdd07d1aa50f33078a3e34 100644 --- a/drivers/phy/freescale/phy-fsl-imx8mq-usb.c +++ b/drivers/phy/freescale/phy-fsl-imx8mq-usb.c @@ -27,17 +27,231 @@ #define PHY_CTRL2_TXENABLEN0 BIT(8) #define PHY_CTRL2_OTG_DISABLE BIT(9) +#define PHY_CTRL3 0xc +#define PHY_CTRL3_COMPDISTUNE_MASK GENMASK(2, 0) +#define PHY_CTRL3_TXPREEMP_TUNE_MASK GENMASK(16, 15) +#define PHY_CTRL3_TXRISE_TUNE_MASK GENMASK(21, 20) +#define PHY_CTRL3_TXVREF_TUNE_MASK GENMASK(25, 22) +#define PHY_CTRL3_TX_VBOOST_LEVEL_MASK GENMASK(31, 29) + +#define PHY_CTRL4 0x10 +#define PHY_CTRL4_PCS_TX_DEEMPH_3P5DB_MASK GENMASK(20, 15) + +#define PHY_CTRL5 0x14 +#define PHY_CTRL5_DMPWD_OVERRIDE_SEL BIT(23) +#define PHY_CTRL5_DMPWD_OVERRIDE BIT(22) +#define PHY_CTRL5_DPPWD_OVERRIDE_SEL BIT(21) +#define PHY_CTRL5_DPPWD_OVERRIDE BIT(20) +#define PHY_CTRL5_PCS_TX_SWING_FULL_MASK GENMASK(6, 0) + #define PHY_CTRL6 0x18 #define PHY_CTRL6_ALT_CLK_EN BIT(1) #define PHY_CTRL6_ALT_CLK_SEL BIT(0) +#define PHY_TUNE_DEFAULT 0xffffffff + struct imx8mq_usb_phy { struct phy *phy; struct clk *clk; void __iomem *base; struct regulator *vbus; + u32 pcs_tx_swing_full; + u32 pcs_tx_deemph_3p5db; + u32 tx_vref_tune; + u32 tx_rise_tune; + u32 tx_preemp_amp_tune; + u32 tx_vboost_level; + u32 comp_dis_tune; }; +static u32 phy_tx_vref_tune_from_property(u32 percent) +{ + percent = clamp(percent, 94U, 124U); + + return DIV_ROUND_CLOSEST(percent - 94U, 2); +} + +static u32 phy_tx_rise_tune_from_property(u32 percent) +{ + switch (percent) { + case 0 ... 98: + return 3; + case 99: + return 2; + case 100 ... 101: + return 1; + default: + return 0; + } +} + +static u32 phy_tx_preemp_amp_tune_from_property(u32 microamp) +{ + microamp = min(microamp, 1800U); + + return microamp / 600; +} + +static u32 phy_tx_vboost_level_from_property(u32 microvolt) +{ + switch (microvolt) { + case 0 ... 960: + return 0; + case 961 ... 1160: + return 2; + default: + return 3; + } +} + +static u32 phy_pcs_tx_deemph_3p5db_from_property(u32 decibel) +{ + return min(decibel, 36U); +} + +static u32 phy_comp_dis_tune_from_property(u32 percent) +{ + switch (percent) { + case 0 ... 92: + return 0; + case 93 ... 95: + return 1; + case 96 ... 97: + return 2; + case 98 ... 102: + return 3; + case 103 ... 105: + return 4; + case 106 ... 109: + return 5; + case 110 ... 113: + return 6; + default: + return 7; + } +} +static u32 phy_pcs_tx_swing_full_from_property(u32 percent) +{ + percent = min(percent, 100U); + + return (percent * 127) / 100; +} + +static void imx8m_get_phy_tuning_data(struct imx8mq_usb_phy *imx_phy) +{ + struct device *dev = imx_phy->phy->dev.parent; + + if (device_property_read_u32(dev, "fsl,phy-tx-vref-tune-percent", + &imx_phy->tx_vref_tune)) + imx_phy->tx_vref_tune = PHY_TUNE_DEFAULT; + else + imx_phy->tx_vref_tune = + phy_tx_vref_tune_from_property(imx_phy->tx_vref_tune); + + if (device_property_read_u32(dev, "fsl,phy-tx-rise-tune-percent", + &imx_phy->tx_rise_tune)) + imx_phy->tx_rise_tune = PHY_TUNE_DEFAULT; + else + imx_phy->tx_rise_tune = + phy_tx_rise_tune_from_property(imx_phy->tx_rise_tune); + + if (device_property_read_u32(dev, "fsl,phy-tx-preemp-amp-tune-microamp", + &imx_phy->tx_preemp_amp_tune)) + imx_phy->tx_preemp_amp_tune = PHY_TUNE_DEFAULT; + else + imx_phy->tx_preemp_amp_tune = + phy_tx_preemp_amp_tune_from_property(imx_phy->tx_preemp_amp_tune); + + if (device_property_read_u32(dev, "fsl,phy-tx-vboost-level-microvolt", + &imx_phy->tx_vboost_level)) + imx_phy->tx_vboost_level = PHY_TUNE_DEFAULT; + else + imx_phy->tx_vboost_level = + phy_tx_vboost_level_from_property(imx_phy->tx_vboost_level); + + if (device_property_read_u32(dev, "fsl,phy-comp-dis-tune-percent", + &imx_phy->comp_dis_tune)) + imx_phy->comp_dis_tune = PHY_TUNE_DEFAULT; + else + imx_phy->comp_dis_tune = + phy_comp_dis_tune_from_property(imx_phy->comp_dis_tune); + + if (device_property_read_u32(dev, "fsl,pcs-tx-deemph-3p5db-attenuation-db", + &imx_phy->pcs_tx_deemph_3p5db)) + imx_phy->pcs_tx_deemph_3p5db = PHY_TUNE_DEFAULT; + else + imx_phy->pcs_tx_deemph_3p5db = + phy_pcs_tx_deemph_3p5db_from_property(imx_phy->pcs_tx_deemph_3p5db); + + if (device_property_read_u32(dev, "fsl,phy-pcs-tx-swing-full-percent", + &imx_phy->pcs_tx_swing_full)) + imx_phy->pcs_tx_swing_full = PHY_TUNE_DEFAULT; + else + imx_phy->pcs_tx_swing_full = + phy_pcs_tx_swing_full_from_property(imx_phy->pcs_tx_swing_full); +} + +static void imx8m_phy_tune(struct imx8mq_usb_phy *imx_phy) +{ + u32 value; + + /* PHY tuning */ + if (imx_phy->pcs_tx_deemph_3p5db != PHY_TUNE_DEFAULT) { + value = readl(imx_phy->base + PHY_CTRL4); + value &= ~PHY_CTRL4_PCS_TX_DEEMPH_3P5DB_MASK; + value |= FIELD_PREP(PHY_CTRL4_PCS_TX_DEEMPH_3P5DB_MASK, + imx_phy->pcs_tx_deemph_3p5db); + writel(value, imx_phy->base + PHY_CTRL4); + } + + if (imx_phy->pcs_tx_swing_full != PHY_TUNE_DEFAULT) { + value = readl(imx_phy->base + PHY_CTRL5); + value |= FIELD_PREP(PHY_CTRL5_PCS_TX_SWING_FULL_MASK, + imx_phy->pcs_tx_swing_full); + writel(value, imx_phy->base + PHY_CTRL5); + } + + if ((imx_phy->tx_vref_tune & imx_phy->tx_rise_tune & + imx_phy->tx_preemp_amp_tune & imx_phy->comp_dis_tune & + imx_phy->tx_vboost_level) == PHY_TUNE_DEFAULT) + /* If all are the default values, no need update. */ + return; + + value = readl(imx_phy->base + PHY_CTRL3); + + if (imx_phy->tx_vref_tune != PHY_TUNE_DEFAULT) { + value &= ~PHY_CTRL3_TXVREF_TUNE_MASK; + value |= FIELD_PREP(PHY_CTRL3_TXVREF_TUNE_MASK, + imx_phy->tx_vref_tune); + } + + if (imx_phy->tx_rise_tune != PHY_TUNE_DEFAULT) { + value &= ~PHY_CTRL3_TXRISE_TUNE_MASK; + value |= FIELD_PREP(PHY_CTRL3_TXRISE_TUNE_MASK, + imx_phy->tx_rise_tune); + } + + if (imx_phy->tx_preemp_amp_tune != PHY_TUNE_DEFAULT) { + value &= ~PHY_CTRL3_TXPREEMP_TUNE_MASK; + value |= FIELD_PREP(PHY_CTRL3_TXPREEMP_TUNE_MASK, + imx_phy->tx_preemp_amp_tune); + } + + if (imx_phy->comp_dis_tune != PHY_TUNE_DEFAULT) { + value &= ~PHY_CTRL3_COMPDISTUNE_MASK; + value |= FIELD_PREP(PHY_CTRL3_COMPDISTUNE_MASK, + imx_phy->comp_dis_tune); + } + + if (imx_phy->tx_vboost_level != PHY_TUNE_DEFAULT) { + value &= ~PHY_CTRL3_TX_VBOOST_LEVEL_MASK; + value |= FIELD_PREP(PHY_CTRL3_TX_VBOOST_LEVEL_MASK, + imx_phy->tx_vboost_level); + } + + writel(value, imx_phy->base + PHY_CTRL3); +} + static int imx8mq_usb_phy_init(struct phy *phy) { struct imx8mq_usb_phy *imx_phy = phy_get_drvdata(phy); @@ -99,6 +313,8 @@ static int imx8mp_usb_phy_init(struct phy *phy) value &= ~(PHY_CTRL1_RESET | PHY_CTRL1_ATERESET); writel(value, imx_phy->base + PHY_CTRL1); + imx8m_phy_tune(imx_phy); + return 0; } @@ -182,6 +398,8 @@ static int imx8mq_usb_phy_probe(struct platform_device *pdev) phy_set_drvdata(imx_phy->phy, imx_phy); + imx8m_get_phy_tuning_data(imx_phy); + phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); return PTR_ERR_OR_ZERO(phy_provider); diff --git a/drivers/phy/hisilicon/Kconfig b/drivers/phy/hisilicon/Kconfig index d3b92c2885544876e3999d7df9c8b29d7fb08585..6c89136fc8c2d1c41d05e12fc856a19115c8e9fc 100644 --- a/drivers/phy/hisilicon/Kconfig +++ b/drivers/phy/hisilicon/Kconfig @@ -54,7 +54,7 @@ config PHY_HISTB_COMBPHY config PHY_HISI_INNO_USB2 tristate "HiSilicon INNO USB2 PHY support" - depends on (ARCH_HISI && ARM64) || COMPILE_TEST + depends on ARCH_HISI || COMPILE_TEST select GENERIC_PHY select MFD_SYSCON help diff --git a/drivers/phy/hisilicon/phy-hisi-inno-usb2.c b/drivers/phy/hisilicon/phy-hisi-inno-usb2.c index b133ae06757ab61d4816675c0dba3e65b54a9f61..15dafe359552c9242a1596225a7191e81d1b745f 100644 --- a/drivers/phy/hisilicon/phy-hisi-inno-usb2.c +++ b/drivers/phy/hisilicon/phy-hisi-inno-usb2.c @@ -9,7 +9,7 @@ #include #include #include -#include +#include #include #include @@ -20,12 +20,25 @@ #define PHY_CLK_STABLE_TIME 2 /* unit:ms */ #define UTMI_RST_COMPLETE_TIME 2 /* unit:ms */ #define POR_RST_COMPLETE_TIME 300 /* unit:us */ + +#define PHY_TYPE_0 0 +#define PHY_TYPE_1 1 + #define PHY_TEST_DATA GENMASK(7, 0) -#define PHY_TEST_ADDR GENMASK(15, 8) -#define PHY_TEST_PORT GENMASK(18, 16) -#define PHY_TEST_WREN BIT(21) -#define PHY_TEST_CLK BIT(22) /* rising edge active */ -#define PHY_TEST_RST BIT(23) /* low active */ +#define PHY_TEST_ADDR_OFFSET 8 +#define PHY0_TEST_ADDR GENMASK(15, 8) +#define PHY0_TEST_PORT_OFFSET 16 +#define PHY0_TEST_PORT GENMASK(18, 16) +#define PHY0_TEST_WREN BIT(21) +#define PHY0_TEST_CLK BIT(22) /* rising edge active */ +#define PHY0_TEST_RST BIT(23) /* low active */ +#define PHY1_TEST_ADDR GENMASK(11, 8) +#define PHY1_TEST_PORT_OFFSET 12 +#define PHY1_TEST_PORT BIT(12) +#define PHY1_TEST_WREN BIT(13) +#define PHY1_TEST_CLK BIT(14) /* rising edge active */ +#define PHY1_TEST_RST BIT(15) /* low active */ + #define PHY_CLK_ENABLE BIT(2) struct hisi_inno_phy_port { @@ -37,6 +50,7 @@ struct hisi_inno_phy_priv { void __iomem *mmio; struct clk *ref_clk; struct reset_control *por_rst; + unsigned int type; struct hisi_inno_phy_port ports[INNO_PHY_PORT_NUM]; }; @@ -45,17 +59,27 @@ static void hisi_inno_phy_write_reg(struct hisi_inno_phy_priv *priv, { void __iomem *reg = priv->mmio; u32 val; - - val = (data & PHY_TEST_DATA) | - ((addr << 8) & PHY_TEST_ADDR) | - ((port << 16) & PHY_TEST_PORT) | - PHY_TEST_WREN | PHY_TEST_RST; + u32 value; + + if (priv->type == PHY_TYPE_0) + val = (data & PHY_TEST_DATA) | + ((addr << PHY_TEST_ADDR_OFFSET) & PHY0_TEST_ADDR) | + ((port << PHY0_TEST_PORT_OFFSET) & PHY0_TEST_PORT) | + PHY0_TEST_WREN | PHY0_TEST_RST; + else + val = (data & PHY_TEST_DATA) | + ((addr << PHY_TEST_ADDR_OFFSET) & PHY1_TEST_ADDR) | + ((port << PHY1_TEST_PORT_OFFSET) & PHY1_TEST_PORT) | + PHY1_TEST_WREN | PHY1_TEST_RST; writel(val, reg); - val |= PHY_TEST_CLK; - writel(val, reg); + value = val; + if (priv->type == PHY_TYPE_0) + value |= PHY0_TEST_CLK; + else + value |= PHY1_TEST_CLK; + writel(value, reg); - val &= ~PHY_TEST_CLK; writel(val, reg); } @@ -135,6 +159,8 @@ static int hisi_inno_phy_probe(struct platform_device *pdev) if (IS_ERR(priv->por_rst)) return PTR_ERR(priv->por_rst); + priv->type = (uintptr_t) of_device_get_match_data(dev); + for_each_child_of_node(np, child) { struct reset_control *rst; struct phy *phy; @@ -170,8 +196,12 @@ static int hisi_inno_phy_probe(struct platform_device *pdev) } static const struct of_device_id hisi_inno_phy_of_match[] = { - { .compatible = "hisilicon,inno-usb2-phy", }, - { .compatible = "hisilicon,hi3798cv200-usb2-phy", }, + { .compatible = "hisilicon,inno-usb2-phy", + .data = (void *) PHY_TYPE_0 }, + { .compatible = "hisilicon,hi3798cv200-usb2-phy", + .data = (void *) PHY_TYPE_0 }, + { .compatible = "hisilicon,hi3798mv100-usb2-phy", + .data = (void *) PHY_TYPE_1 }, { }, }; MODULE_DEVICE_TABLE(of, hisi_inno_phy_of_match); diff --git a/drivers/phy/mediatek/phy-mtk-tphy.c b/drivers/phy/mediatek/phy-mtk-tphy.c index e906a82791bdaad9e5ac0ce1aecc278d576c03e4..0d110e50bbfd0e8c465aa35120b67f16849b1bb7 100644 --- a/drivers/phy/mediatek/phy-mtk-tphy.c +++ b/drivers/phy/mediatek/phy-mtk-tphy.c @@ -7,6 +7,7 @@ #include #include +#include #include #include #include @@ -264,6 +265,8 @@ #define TPHY_CLKS_CNT 2 +#define USER_BUF_LEN(count) min_t(size_t, 8, (count)) + enum mtk_phy_version { MTK_PHY_V1 = 1, MTK_PHY_V2, @@ -336,6 +339,358 @@ struct mtk_tphy { int src_coef; /* coefficient for slew rate calibrate */ }; +#if IS_ENABLED(CONFIG_DEBUG_FS) + +enum u2_phy_params { + U2P_EYE_VRT = 0, + U2P_EYE_TERM, + U2P_EFUSE_EN, + U2P_EFUSE_INTR, + U2P_DISCTH, + U2P_PRE_EMPHASIS, +}; + +enum u3_phy_params { + U3P_EFUSE_EN = 0, + U3P_EFUSE_INTR, + U3P_EFUSE_TX_IMP, + U3P_EFUSE_RX_IMP, +}; + +static const char *const u2_phy_files[] = { + [U2P_EYE_VRT] = "vrt", + [U2P_EYE_TERM] = "term", + [U2P_EFUSE_EN] = "efuse", + [U2P_EFUSE_INTR] = "intr", + [U2P_DISCTH] = "discth", + [U2P_PRE_EMPHASIS] = "preemph", +}; + +static const char *const u3_phy_files[] = { + [U3P_EFUSE_EN] = "efuse", + [U3P_EFUSE_INTR] = "intr", + [U3P_EFUSE_TX_IMP] = "tx-imp", + [U3P_EFUSE_RX_IMP] = "rx-imp", +}; + +static int u2_phy_params_show(struct seq_file *sf, void *unused) +{ + struct mtk_phy_instance *inst = sf->private; + const char *fname = file_dentry(sf->file)->d_iname; + struct u2phy_banks *u2_banks = &inst->u2_banks; + void __iomem *com = u2_banks->com; + u32 max = 0; + u32 tmp = 0; + u32 val = 0; + int ret; + + ret = match_string(u2_phy_files, ARRAY_SIZE(u2_phy_files), fname); + if (ret < 0) + return ret; + + switch (ret) { + case U2P_EYE_VRT: + tmp = readl(com + U3P_USBPHYACR1); + val = FIELD_GET(PA1_RG_VRT_SEL, tmp); + max = FIELD_MAX(PA1_RG_VRT_SEL); + break; + + case U2P_EYE_TERM: + tmp = readl(com + U3P_USBPHYACR1); + val = FIELD_GET(PA1_RG_TERM_SEL, tmp); + max = FIELD_MAX(PA1_RG_TERM_SEL); + break; + + case U2P_EFUSE_EN: + if (u2_banks->misc) { + tmp = readl(u2_banks->misc + U3P_MISC_REG1); + max = 1; + } + + val = !!(tmp & MR1_EFUSE_AUTO_LOAD_DIS); + break; + + case U2P_EFUSE_INTR: + tmp = readl(com + U3P_USBPHYACR1); + val = FIELD_GET(PA1_RG_INTR_CAL, tmp); + max = FIELD_MAX(PA1_RG_INTR_CAL); + break; + + case U2P_DISCTH: + tmp = readl(com + U3P_USBPHYACR6); + val = FIELD_GET(PA6_RG_U2_DISCTH, tmp); + max = FIELD_MAX(PA6_RG_U2_DISCTH); + break; + + case U2P_PRE_EMPHASIS: + tmp = readl(com + U3P_USBPHYACR6); + val = FIELD_GET(PA6_RG_U2_PRE_EMP, tmp); + max = FIELD_MAX(PA6_RG_U2_PRE_EMP); + break; + + default: + seq_printf(sf, "invalid, %d\n", ret); + break; + } + + seq_printf(sf, "%s : %d [0, %d]\n", fname, val, max); + + return 0; +} + +static int u2_phy_params_open(struct inode *inode, struct file *file) +{ + return single_open(file, u2_phy_params_show, inode->i_private); +} + +static ssize_t u2_phy_params_write(struct file *file, const char __user *ubuf, + size_t count, loff_t *ppos) +{ + const char *fname = file_dentry(file)->d_iname; + struct seq_file *sf = file->private_data; + struct mtk_phy_instance *inst = sf->private; + struct u2phy_banks *u2_banks = &inst->u2_banks; + void __iomem *com = u2_banks->com; + ssize_t rc; + u32 val; + int ret; + + rc = kstrtouint_from_user(ubuf, USER_BUF_LEN(count), 0, &val); + if (rc) + return rc; + + ret = match_string(u2_phy_files, ARRAY_SIZE(u2_phy_files), fname); + if (ret < 0) + return (ssize_t)ret; + + switch (ret) { + case U2P_EYE_VRT: + mtk_phy_update_field(com + U3P_USBPHYACR1, PA1_RG_VRT_SEL, val); + break; + + case U2P_EYE_TERM: + mtk_phy_update_field(com + U3P_USBPHYACR1, PA1_RG_TERM_SEL, val); + break; + + case U2P_EFUSE_EN: + if (u2_banks->misc) + mtk_phy_update_field(u2_banks->misc + U3P_MISC_REG1, + MR1_EFUSE_AUTO_LOAD_DIS, !!val); + break; + + case U2P_EFUSE_INTR: + mtk_phy_update_field(com + U3P_USBPHYACR1, PA1_RG_INTR_CAL, val); + break; + + case U2P_DISCTH: + mtk_phy_update_field(com + U3P_USBPHYACR6, PA6_RG_U2_DISCTH, val); + break; + + case U2P_PRE_EMPHASIS: + mtk_phy_update_field(com + U3P_USBPHYACR6, PA6_RG_U2_PRE_EMP, val); + break; + + default: + break; + } + + return count; +} + +static const struct file_operations u2_phy_fops = { + .open = u2_phy_params_open, + .write = u2_phy_params_write, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static void u2_phy_dbgfs_files_create(struct mtk_phy_instance *inst) +{ + u32 count = ARRAY_SIZE(u2_phy_files); + int i; + + for (i = 0; i < count; i++) + debugfs_create_file(u2_phy_files[i], 0644, inst->phy->debugfs, + inst, &u2_phy_fops); +} + +static int u3_phy_params_show(struct seq_file *sf, void *unused) +{ + struct mtk_phy_instance *inst = sf->private; + const char *fname = file_dentry(sf->file)->d_iname; + struct u3phy_banks *u3_banks = &inst->u3_banks; + u32 val = 0; + u32 max = 0; + u32 tmp; + int ret; + + ret = match_string(u3_phy_files, ARRAY_SIZE(u3_phy_files), fname); + if (ret < 0) + return ret; + + switch (ret) { + case U3P_EFUSE_EN: + tmp = readl(u3_banks->phyd + U3P_U3_PHYD_RSV); + val = !!(tmp & P3D_RG_EFUSE_AUTO_LOAD_DIS); + max = 1; + break; + + case U3P_EFUSE_INTR: + tmp = readl(u3_banks->phya + U3P_U3_PHYA_REG0); + val = FIELD_GET(P3A_RG_IEXT_INTR, tmp); + max = FIELD_MAX(P3A_RG_IEXT_INTR); + break; + + case U3P_EFUSE_TX_IMP: + tmp = readl(u3_banks->phyd + U3P_U3_PHYD_IMPCAL0); + val = FIELD_GET(P3D_RG_TX_IMPEL, tmp); + max = FIELD_MAX(P3D_RG_TX_IMPEL); + break; + + case U3P_EFUSE_RX_IMP: + tmp = readl(u3_banks->phyd + U3P_U3_PHYD_IMPCAL1); + val = FIELD_GET(P3D_RG_RX_IMPEL, tmp); + max = FIELD_MAX(P3D_RG_RX_IMPEL); + break; + + default: + seq_printf(sf, "invalid, %d\n", ret); + break; + } + + seq_printf(sf, "%s : %d [0, %d]\n", fname, val, max); + + return 0; +} + +static int u3_phy_params_open(struct inode *inode, struct file *file) +{ + return single_open(file, u3_phy_params_show, inode->i_private); +} + +static ssize_t u3_phy_params_write(struct file *file, const char __user *ubuf, + size_t count, loff_t *ppos) +{ + const char *fname = file_dentry(file)->d_iname; + struct seq_file *sf = file->private_data; + struct mtk_phy_instance *inst = sf->private; + struct u3phy_banks *u3_banks = &inst->u3_banks; + void __iomem *phyd = u3_banks->phyd; + ssize_t rc; + u32 val; + int ret; + + rc = kstrtouint_from_user(ubuf, USER_BUF_LEN(count), 0, &val); + if (rc) + return rc; + + ret = match_string(u3_phy_files, ARRAY_SIZE(u3_phy_files), fname); + if (ret < 0) + return (ssize_t)ret; + + switch (ret) { + case U3P_EFUSE_EN: + mtk_phy_update_field(phyd + U3P_U3_PHYD_RSV, + P3D_RG_EFUSE_AUTO_LOAD_DIS, !!val); + break; + + case U3P_EFUSE_INTR: + mtk_phy_update_field(u3_banks->phya + U3P_U3_PHYA_REG0, + P3A_RG_IEXT_INTR, val); + break; + + case U3P_EFUSE_TX_IMP: + mtk_phy_update_field(phyd + U3P_U3_PHYD_IMPCAL0, P3D_RG_TX_IMPEL, val); + mtk_phy_set_bits(phyd + U3P_U3_PHYD_IMPCAL0, P3D_RG_FORCE_TX_IMPEL); + break; + + case U3P_EFUSE_RX_IMP: + mtk_phy_update_field(phyd + U3P_U3_PHYD_IMPCAL1, P3D_RG_RX_IMPEL, val); + mtk_phy_set_bits(phyd + U3P_U3_PHYD_IMPCAL1, P3D_RG_FORCE_RX_IMPEL); + break; + + default: + break; + } + + return count; +} + +static const struct file_operations u3_phy_fops = { + .open = u3_phy_params_open, + .write = u3_phy_params_write, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static void u3_phy_dbgfs_files_create(struct mtk_phy_instance *inst) +{ + u32 count = ARRAY_SIZE(u3_phy_files); + int i; + + for (i = 0; i < count; i++) + debugfs_create_file(u3_phy_files[i], 0644, inst->phy->debugfs, + inst, &u3_phy_fops); +} + +static int phy_type_show(struct seq_file *sf, void *unused) +{ + struct mtk_phy_instance *inst = sf->private; + const char *type; + + switch (inst->type) { + case PHY_TYPE_USB2: + type = "USB2"; + break; + case PHY_TYPE_USB3: + type = "USB3"; + break; + case PHY_TYPE_PCIE: + type = "PCIe"; + break; + case PHY_TYPE_SGMII: + type = "SGMII"; + break; + case PHY_TYPE_SATA: + type = "SATA"; + break; + default: + type = ""; + } + + seq_printf(sf, "%s\n", type); + + return 0; +} +DEFINE_SHOW_ATTRIBUTE(phy_type); + +/* these files will be removed when phy is released by phy core */ +static void phy_debugfs_init(struct mtk_phy_instance *inst) +{ + debugfs_create_file("type", 0444, inst->phy->debugfs, inst, &phy_type_fops); + + switch (inst->type) { + case PHY_TYPE_USB2: + u2_phy_dbgfs_files_create(inst); + break; + case PHY_TYPE_USB3: + case PHY_TYPE_PCIE: + u3_phy_dbgfs_files_create(inst); + break; + default: + break; + } +} + +#else + +static void phy_debugfs_init(struct mtk_phy_instance *inst) +{} + +#endif + static void hs_slew_rate_calibrate(struct mtk_tphy *tphy, struct mtk_phy_instance *instance) { @@ -1140,6 +1495,7 @@ static struct phy *mtk_phy_xlate(struct device *dev, phy_parse_property(tphy, instance); phy_type_set(instance); + phy_debugfs_init(instance); return instance->phy; } diff --git a/drivers/phy/microchip/sparx5_serdes.c b/drivers/phy/microchip/sparx5_serdes.c index ab1b0986aa67167f9e773f64179e0b25b20d331e..01bd5ea620c5b7d26abb100909cfb67ce689a273 100644 --- a/drivers/phy/microchip/sparx5_serdes.c +++ b/drivers/phy/microchip/sparx5_serdes.c @@ -25,12 +25,17 @@ #define SPX5_SERDES_10G_START 13 #define SPX5_SERDES_25G_START 25 +#define SPX5_SERDES_6G10G_CNT SPX5_SERDES_25G_START + +/* Optimal power settings from GUC */ +#define SPX5_SERDES_QUIET_MODE_VAL 0x01ef4e0c enum sparx5_10g28cmu_mode { SPX5_SD10G28_CMU_MAIN = 0, SPX5_SD10G28_CMU_AUX1 = 1, SPX5_SD10G28_CMU_AUX2 = 3, SPX5_SD10G28_CMU_NONE = 4, + SPX5_SD10G28_CMU_MAX, }; enum sparx5_sd25g28_mode_preset_type { @@ -922,6 +927,222 @@ static void sparx5_sd10g28_get_params(struct sparx5_serdes_macro *macro, *params = init; } +static int sparx5_cmu_apply_cfg(struct sparx5_serdes_private *priv, + u32 cmu_idx, + void __iomem *cmu_tgt, + void __iomem *cmu_cfg_tgt, + u32 spd10g) +{ + void __iomem **regs = priv->regs; + struct device *dev = priv->dev; + int value; + + cmu_tgt = sdx5_inst_get(priv, TARGET_SD_CMU, cmu_idx); + cmu_cfg_tgt = sdx5_inst_get(priv, TARGET_SD_CMU_CFG, cmu_idx); + + if (cmu_idx == 1 || cmu_idx == 4 || cmu_idx == 7 || + cmu_idx == 10 || cmu_idx == 13) { + spd10g = 0; + } + + sdx5_inst_rmw(SD_CMU_CFG_SD_CMU_CFG_EXT_CFG_RST_SET(1), + SD_CMU_CFG_SD_CMU_CFG_EXT_CFG_RST, + cmu_cfg_tgt, + SD_CMU_CFG_SD_CMU_CFG(cmu_idx)); + + sdx5_inst_rmw(SD_CMU_CFG_SD_CMU_CFG_EXT_CFG_RST_SET(0), + SD_CMU_CFG_SD_CMU_CFG_EXT_CFG_RST, + cmu_cfg_tgt, + SD_CMU_CFG_SD_CMU_CFG(cmu_idx)); + + sdx5_inst_rmw(SD_CMU_CFG_SD_CMU_CFG_CMU_RST_SET(1), + SD_CMU_CFG_SD_CMU_CFG_CMU_RST, + cmu_cfg_tgt, + SD_CMU_CFG_SD_CMU_CFG(cmu_idx)); + + sdx5_inst_rmw(SD_CMU_CMU_45_R_DWIDTHCTRL_FROM_HWT_SET(0x1) | + SD_CMU_CMU_45_R_REFCK_SSC_EN_FROM_HWT_SET(0x1) | + SD_CMU_CMU_45_R_LINK_BUF_EN_FROM_HWT_SET(0x1) | + SD_CMU_CMU_45_R_BIAS_EN_FROM_HWT_SET(0x1) | + SD_CMU_CMU_45_R_EN_RATECHG_CTRL_SET(0x0), + SD_CMU_CMU_45_R_DWIDTHCTRL_FROM_HWT | + SD_CMU_CMU_45_R_REFCK_SSC_EN_FROM_HWT | + SD_CMU_CMU_45_R_LINK_BUF_EN_FROM_HWT | + SD_CMU_CMU_45_R_BIAS_EN_FROM_HWT | + SD_CMU_CMU_45_R_EN_RATECHG_CTRL, + cmu_tgt, + SD_CMU_CMU_45(cmu_idx)); + + sdx5_inst_rmw(SD_CMU_CMU_47_R_PCS2PMA_PHYMODE_4_0_SET(0), + SD_CMU_CMU_47_R_PCS2PMA_PHYMODE_4_0, + cmu_tgt, + SD_CMU_CMU_47(cmu_idx)); + + sdx5_inst_rmw(SD_CMU_CMU_1B_CFG_RESERVE_7_0_SET(0), + SD_CMU_CMU_1B_CFG_RESERVE_7_0, + cmu_tgt, + SD_CMU_CMU_1B(cmu_idx)); + + sdx5_inst_rmw(SD_CMU_CMU_0D_CFG_JC_BYP_SET(0x1), + SD_CMU_CMU_0D_CFG_JC_BYP, + cmu_tgt, + SD_CMU_CMU_0D(cmu_idx)); + + sdx5_inst_rmw(SD_CMU_CMU_1F_CFG_VTUNE_SEL_SET(1), + SD_CMU_CMU_1F_CFG_VTUNE_SEL, + cmu_tgt, + SD_CMU_CMU_1F(cmu_idx)); + + sdx5_inst_rmw(SD_CMU_CMU_00_CFG_PLL_TP_SEL_1_0_SET(3), + SD_CMU_CMU_00_CFG_PLL_TP_SEL_1_0, + cmu_tgt, + SD_CMU_CMU_00(cmu_idx)); + + sdx5_inst_rmw(SD_CMU_CMU_05_CFG_BIAS_TP_SEL_1_0_SET(3), + SD_CMU_CMU_05_CFG_BIAS_TP_SEL_1_0, + cmu_tgt, + SD_CMU_CMU_05(cmu_idx)); + + sdx5_inst_rmw(SD_CMU_CMU_30_R_PLL_DLOL_EN_SET(1), + SD_CMU_CMU_30_R_PLL_DLOL_EN, + cmu_tgt, + SD_CMU_CMU_30(cmu_idx)); + + sdx5_inst_rmw(SD_CMU_CMU_09_CFG_SW_10G_SET(spd10g), + SD_CMU_CMU_09_CFG_SW_10G, + cmu_tgt, + SD_CMU_CMU_09(cmu_idx)); + + sdx5_inst_rmw(SD_CMU_CFG_SD_CMU_CFG_CMU_RST_SET(0), + SD_CMU_CFG_SD_CMU_CFG_CMU_RST, + cmu_cfg_tgt, + SD_CMU_CFG_SD_CMU_CFG(cmu_idx)); + + msleep(20); + + sdx5_inst_rmw(SD_CMU_CMU_44_R_PLL_RSTN_SET(0), + SD_CMU_CMU_44_R_PLL_RSTN, + cmu_tgt, + SD_CMU_CMU_44(cmu_idx)); + + sdx5_inst_rmw(SD_CMU_CMU_44_R_PLL_RSTN_SET(1), + SD_CMU_CMU_44_R_PLL_RSTN, + cmu_tgt, + SD_CMU_CMU_44(cmu_idx)); + + msleep(20); + + value = readl(sdx5_addr(regs, SD_CMU_CMU_E0(cmu_idx))); + value = SD_CMU_CMU_E0_PLL_LOL_UDL_GET(value); + + if (value) { + dev_err(dev, "CMU PLL Loss of Lock: 0x%x\n", value); + return -EINVAL; + } + sdx5_inst_rmw(SD_CMU_CMU_0D_CFG_PMA_TX_CK_PD_SET(0), + SD_CMU_CMU_0D_CFG_PMA_TX_CK_PD, + cmu_tgt, + SD_CMU_CMU_0D(cmu_idx)); + return 0; +} + +static int sparx5_cmu_cfg(struct sparx5_serdes_private *priv, u32 cmu_idx) +{ + void __iomem *cmu_tgt, *cmu_cfg_tgt; + u32 spd10g = 1; + + if (cmu_idx == 1 || cmu_idx == 4 || cmu_idx == 7 || + cmu_idx == 10 || cmu_idx == 13) { + spd10g = 0; + } + + cmu_tgt = sdx5_inst_get(priv, TARGET_SD_CMU, cmu_idx); + cmu_cfg_tgt = sdx5_inst_get(priv, TARGET_SD_CMU_CFG, cmu_idx); + + return sparx5_cmu_apply_cfg(priv, cmu_idx, cmu_tgt, cmu_cfg_tgt, spd10g); +} + +/* Map of 6G/10G serdes mode and index to CMU index. */ +static const int +sparx5_serdes_cmu_map[SPX5_SD10G28_CMU_MAX][SPX5_SERDES_6G10G_CNT] = { + [SPX5_SD10G28_CMU_MAIN] = { 2, 2, 2, 2, 2, + 2, 2, 2, 5, 5, + 5, 5, 5, 5, 5, + 5, 8, 11, 11, 11, + 11, 11, 11, 11, 11 }, + [SPX5_SD10G28_CMU_AUX1] = { 0, 0, 3, 3, 3, + 3, 3, 3, 3, 3, + 6, 6, 6, 6, 6, + 6, 6, 9, 9, 12, + 12, 12, 12, 12, 12 }, + [SPX5_SD10G28_CMU_AUX2] = { 1, 1, 1, 1, 4, + 4, 4, 4, 4, 4, + 4, 4, 7, 7, 7, + 7, 7, 10, 10, 10, + 10, 13, 13, 13, 13 }, + [SPX5_SD10G28_CMU_NONE] = { 1, 1, 1, 1, 4, + 4, 4, 4, 4, 4, + 4, 4, 7, 7, 7, + 7, 7, 10, 10, 10, + 10, 13, 13, 13, 13 }, +}; + +/* Get the index of the CMU which provides the clock for the specified serdes + * mode and index. + */ +static int sparx5_serdes_cmu_get(enum sparx5_10g28cmu_mode mode, int sd_index) +{ + return sparx5_serdes_cmu_map[mode][sd_index]; +} + +static void sparx5_serdes_cmu_power_off(struct sparx5_serdes_private *priv) +{ + void __iomem *cmu_inst, *cmu_cfg_inst; + int i; + + /* Power down each CMU */ + for (i = 0; i < SPX5_CMU_MAX; i++) { + cmu_inst = sdx5_inst_get(priv, TARGET_SD_CMU, i); + cmu_cfg_inst = sdx5_inst_get(priv, TARGET_SD_CMU_CFG, i); + + sdx5_inst_rmw(SD_CMU_CFG_SD_CMU_CFG_EXT_CFG_RST_SET(0), + SD_CMU_CFG_SD_CMU_CFG_EXT_CFG_RST, cmu_cfg_inst, + SD_CMU_CFG_SD_CMU_CFG(0)); + + sdx5_inst_rmw(SD_CMU_CMU_05_CFG_REFCK_TERM_EN_SET(0), + SD_CMU_CMU_05_CFG_REFCK_TERM_EN, cmu_inst, + SD_CMU_CMU_05(0)); + + sdx5_inst_rmw(SD_CMU_CMU_09_CFG_EN_TX_CK_DN_SET(0), + SD_CMU_CMU_09_CFG_EN_TX_CK_DN, cmu_inst, + SD_CMU_CMU_09(0)); + + sdx5_inst_rmw(SD_CMU_CMU_06_CFG_VCO_PD_SET(1), + SD_CMU_CMU_06_CFG_VCO_PD, cmu_inst, + SD_CMU_CMU_06(0)); + + sdx5_inst_rmw(SD_CMU_CMU_09_CFG_EN_TX_CK_UP_SET(0), + SD_CMU_CMU_09_CFG_EN_TX_CK_UP, cmu_inst, + SD_CMU_CMU_09(0)); + + sdx5_inst_rmw(SD_CMU_CMU_08_CFG_CK_TREE_PD_SET(1), + SD_CMU_CMU_08_CFG_CK_TREE_PD, cmu_inst, + SD_CMU_CMU_08(0)); + + sdx5_inst_rmw(SD_CMU_CMU_0D_CFG_REFCK_PD_SET(1) | + SD_CMU_CMU_0D_CFG_PD_DIV64_SET(1) | + SD_CMU_CMU_0D_CFG_PD_DIV66_SET(1), + SD_CMU_CMU_0D_CFG_REFCK_PD | + SD_CMU_CMU_0D_CFG_PD_DIV64 | + SD_CMU_CMU_0D_CFG_PD_DIV66, cmu_inst, + SD_CMU_CMU_0D(0)); + + sdx5_inst_rmw(SD_CMU_CMU_06_CFG_CTRL_LOGIC_PD_SET(1), + SD_CMU_CMU_06_CFG_CTRL_LOGIC_PD, cmu_inst, + SD_CMU_CMU_06(0)); + } +} + static void sparx5_sd25g28_reset(void __iomem *regs[], struct sparx5_sd25g28_params *params, u32 sd_index) @@ -1422,7 +1643,17 @@ static int sparx5_sd10g28_apply_params(struct sparx5_serdes_macro *macro, u32 lane_index = macro->sidx; u32 sd_index = macro->stpidx; void __iomem *sd_inst; - u32 value; + u32 value, cmu_idx; + int err; + + /* Do not configure serdes if CMU is not to be configured too */ + if (params->skip_cmu_cfg) + return 0; + + cmu_idx = sparx5_serdes_cmu_get(params->cmu_sel, lane_index); + err = sparx5_cmu_cfg(priv, cmu_idx); + if (err) + return err; if (params->is_6g) sd_inst = sdx5_inst_get(priv, TARGET_SD6G_LANE, sd_index); @@ -1884,6 +2115,7 @@ static int sparx5_sd10g28_config(struct sparx5_serdes_macro *macro, bool reset) .rxinvert = 1, .txswing = 240, .reg_rst = reset, + .skip_cmu_cfg = reset, }; int err; @@ -1899,7 +2131,7 @@ static int sparx5_sd10g28_config(struct sparx5_serdes_macro *macro, bool reset) static int sparx5_serdes_power_save(struct sparx5_serdes_macro *macro, u32 pwdn) { struct sparx5_serdes_private *priv = macro->priv; - void __iomem *sd_inst; + void __iomem *sd_inst, *sd_lane_inst; if (macro->serdestype == SPX5_SDT_6G) sd_inst = sdx5_inst_get(priv, TARGET_SD6G_LANE, macro->stpidx); @@ -1909,12 +2141,36 @@ static int sparx5_serdes_power_save(struct sparx5_serdes_macro *macro, u32 pwdn) sd_inst = sdx5_inst_get(priv, TARGET_SD25G_LANE, macro->stpidx); if (macro->serdestype == SPX5_SDT_25G) { + sd_lane_inst = sdx5_inst_get(priv, TARGET_SD_LANE_25G, + macro->stpidx); + /* Take serdes out of reset */ + sdx5_inst_rmw(SD_LANE_25G_SD_LANE_CFG_EXT_CFG_RST_SET(0), + SD_LANE_25G_SD_LANE_CFG_EXT_CFG_RST, sd_lane_inst, + SD_LANE_25G_SD_LANE_CFG(0)); + + /* Configure optimal settings for quiet mode */ + sdx5_inst_rmw(SD_LANE_25G_QUIET_MODE_6G_QUIET_MODE_SET(SPX5_SERDES_QUIET_MODE_VAL), + SD_LANE_25G_QUIET_MODE_6G_QUIET_MODE, + sd_lane_inst, SD_LANE_25G_QUIET_MODE_6G(0)); + sdx5_inst_rmw(SD25G_LANE_LANE_04_LN_CFG_PD_DRIVER_SET(pwdn), SD25G_LANE_LANE_04_LN_CFG_PD_DRIVER, sd_inst, SD25G_LANE_LANE_04(0)); } else { /* 6G and 10G */ + sd_lane_inst = sdx5_inst_get(priv, TARGET_SD_LANE, macro->sidx); + + /* Take serdes out of reset */ + sdx5_inst_rmw(SD_LANE_SD_LANE_CFG_EXT_CFG_RST_SET(0), + SD_LANE_SD_LANE_CFG_EXT_CFG_RST, sd_lane_inst, + SD_LANE_SD_LANE_CFG(0)); + + /* Configure optimal settings for quiet mode */ + sdx5_inst_rmw(SD_LANE_QUIET_MODE_6G_QUIET_MODE_SET(SPX5_SERDES_QUIET_MODE_VAL), + SD_LANE_QUIET_MODE_6G_QUIET_MODE, sd_lane_inst, + SD_LANE_QUIET_MODE_6G(0)); + sdx5_inst_rmw(SD10G_LANE_LANE_06_CFG_PD_DRIVER_SET(pwdn), SD10G_LANE_LANE_06_CFG_PD_DRIVER, sd_inst, @@ -1939,159 +2195,6 @@ static int sparx5_serdes_clock_config(struct sparx5_serdes_macro *macro) return 0; } -static int sparx5_cmu_apply_cfg(struct sparx5_serdes_private *priv, - u32 cmu_idx, - void __iomem *cmu_tgt, - void __iomem *cmu_cfg_tgt, - u32 spd10g) -{ - void __iomem **regs = priv->regs; - struct device *dev = priv->dev; - int value; - - cmu_tgt = sdx5_inst_get(priv, TARGET_SD_CMU, cmu_idx); - cmu_cfg_tgt = sdx5_inst_get(priv, TARGET_SD_CMU_CFG, cmu_idx); - - if (cmu_idx == 1 || cmu_idx == 4 || cmu_idx == 7 || - cmu_idx == 10 || cmu_idx == 13) { - spd10g = 0; - } - - sdx5_inst_rmw(SD_CMU_CFG_SD_CMU_CFG_EXT_CFG_RST_SET(1), - SD_CMU_CFG_SD_CMU_CFG_EXT_CFG_RST, - cmu_cfg_tgt, - SD_CMU_CFG_SD_CMU_CFG(cmu_idx)); - - sdx5_inst_rmw(SD_CMU_CFG_SD_CMU_CFG_EXT_CFG_RST_SET(0), - SD_CMU_CFG_SD_CMU_CFG_EXT_CFG_RST, - cmu_cfg_tgt, - SD_CMU_CFG_SD_CMU_CFG(cmu_idx)); - - sdx5_inst_rmw(SD_CMU_CFG_SD_CMU_CFG_CMU_RST_SET(1), - SD_CMU_CFG_SD_CMU_CFG_CMU_RST, - cmu_cfg_tgt, - SD_CMU_CFG_SD_CMU_CFG(cmu_idx)); - - sdx5_inst_rmw(SD_CMU_CMU_45_R_DWIDTHCTRL_FROM_HWT_SET(0x1) | - SD_CMU_CMU_45_R_REFCK_SSC_EN_FROM_HWT_SET(0x1) | - SD_CMU_CMU_45_R_LINK_BUF_EN_FROM_HWT_SET(0x1) | - SD_CMU_CMU_45_R_BIAS_EN_FROM_HWT_SET(0x1) | - SD_CMU_CMU_45_R_EN_RATECHG_CTRL_SET(0x0), - SD_CMU_CMU_45_R_DWIDTHCTRL_FROM_HWT | - SD_CMU_CMU_45_R_REFCK_SSC_EN_FROM_HWT | - SD_CMU_CMU_45_R_LINK_BUF_EN_FROM_HWT | - SD_CMU_CMU_45_R_BIAS_EN_FROM_HWT | - SD_CMU_CMU_45_R_EN_RATECHG_CTRL, - cmu_tgt, - SD_CMU_CMU_45(cmu_idx)); - - sdx5_inst_rmw(SD_CMU_CMU_47_R_PCS2PMA_PHYMODE_4_0_SET(0), - SD_CMU_CMU_47_R_PCS2PMA_PHYMODE_4_0, - cmu_tgt, - SD_CMU_CMU_47(cmu_idx)); - - sdx5_inst_rmw(SD_CMU_CMU_1B_CFG_RESERVE_7_0_SET(0), - SD_CMU_CMU_1B_CFG_RESERVE_7_0, - cmu_tgt, - SD_CMU_CMU_1B(cmu_idx)); - - sdx5_inst_rmw(SD_CMU_CMU_0D_CFG_JC_BYP_SET(0x1), - SD_CMU_CMU_0D_CFG_JC_BYP, - cmu_tgt, - SD_CMU_CMU_0D(cmu_idx)); - - sdx5_inst_rmw(SD_CMU_CMU_1F_CFG_VTUNE_SEL_SET(1), - SD_CMU_CMU_1F_CFG_VTUNE_SEL, - cmu_tgt, - SD_CMU_CMU_1F(cmu_idx)); - - sdx5_inst_rmw(SD_CMU_CMU_00_CFG_PLL_TP_SEL_1_0_SET(3), - SD_CMU_CMU_00_CFG_PLL_TP_SEL_1_0, - cmu_tgt, - SD_CMU_CMU_00(cmu_idx)); - - sdx5_inst_rmw(SD_CMU_CMU_05_CFG_BIAS_TP_SEL_1_0_SET(3), - SD_CMU_CMU_05_CFG_BIAS_TP_SEL_1_0, - cmu_tgt, - SD_CMU_CMU_05(cmu_idx)); - - sdx5_inst_rmw(SD_CMU_CMU_30_R_PLL_DLOL_EN_SET(1), - SD_CMU_CMU_30_R_PLL_DLOL_EN, - cmu_tgt, - SD_CMU_CMU_30(cmu_idx)); - - sdx5_inst_rmw(SD_CMU_CMU_09_CFG_SW_10G_SET(spd10g), - SD_CMU_CMU_09_CFG_SW_10G, - cmu_tgt, - SD_CMU_CMU_09(cmu_idx)); - - sdx5_inst_rmw(SD_CMU_CFG_SD_CMU_CFG_CMU_RST_SET(0), - SD_CMU_CFG_SD_CMU_CFG_CMU_RST, - cmu_cfg_tgt, - SD_CMU_CFG_SD_CMU_CFG(cmu_idx)); - - msleep(20); - - sdx5_inst_rmw(SD_CMU_CMU_44_R_PLL_RSTN_SET(0), - SD_CMU_CMU_44_R_PLL_RSTN, - cmu_tgt, - SD_CMU_CMU_44(cmu_idx)); - - sdx5_inst_rmw(SD_CMU_CMU_44_R_PLL_RSTN_SET(1), - SD_CMU_CMU_44_R_PLL_RSTN, - cmu_tgt, - SD_CMU_CMU_44(cmu_idx)); - - msleep(20); - - value = readl(sdx5_addr(regs, SD_CMU_CMU_E0(cmu_idx))); - value = SD_CMU_CMU_E0_PLL_LOL_UDL_GET(value); - - if (value) { - dev_err(dev, "CMU PLL Loss of Lock: 0x%x\n", value); - return -EINVAL; - } - sdx5_inst_rmw(SD_CMU_CMU_0D_CFG_PMA_TX_CK_PD_SET(0), - SD_CMU_CMU_0D_CFG_PMA_TX_CK_PD, - cmu_tgt, - SD_CMU_CMU_0D(cmu_idx)); - return 0; -} - -static int sparx5_cmu_cfg(struct sparx5_serdes_private *priv, u32 cmu_idx) -{ - void __iomem *cmu_tgt, *cmu_cfg_tgt; - u32 spd10g = 1; - - if (cmu_idx == 1 || cmu_idx == 4 || cmu_idx == 7 || - cmu_idx == 10 || cmu_idx == 13) { - spd10g = 0; - } - - cmu_tgt = sdx5_inst_get(priv, TARGET_SD_CMU, cmu_idx); - cmu_cfg_tgt = sdx5_inst_get(priv, TARGET_SD_CMU_CFG, cmu_idx); - - return sparx5_cmu_apply_cfg(priv, cmu_idx, cmu_tgt, cmu_cfg_tgt, spd10g); -} - -static int sparx5_serdes_cmu_enable(struct sparx5_serdes_private *priv) -{ - int idx, err = 0; - - if (!priv->cmu_enabled) { - for (idx = 0; idx < SPX5_CMU_MAX; idx++) { - err = sparx5_cmu_cfg(priv, idx); - if (err) { - dev_err(priv->dev, "CMU %u, error: %d\n", idx, err); - goto leave; - } - } - priv->cmu_enabled = true; - } -leave: - return err; -} - static int sparx5_serdes_get_serdesmode(phy_interface_t portmode, int speed) { switch (portmode) { @@ -2120,10 +2223,6 @@ static int sparx5_serdes_config(struct sparx5_serdes_macro *macro) int serdesmode; int err; - err = sparx5_serdes_cmu_enable(macro->priv); - if (err) - return err; - serdesmode = sparx5_serdes_get_serdesmode(macro->portmode, macro->speed); if (serdesmode < 0) { dev_err(dev, "SerDes %u, interface not supported: %s\n", @@ -2215,9 +2314,6 @@ static int sparx5_serdes_reset(struct phy *phy) struct sparx5_serdes_macro *macro = phy_get_drvdata(phy); int err; - err = sparx5_serdes_cmu_enable(macro->priv); - if (err) - return err; if (macro->serdestype == SPX5_SDT_25G) err = sparx5_sd25g28_config(macro, true); else @@ -2308,6 +2404,9 @@ static int sparx5_phy_create(struct sparx5_serdes_private *priv, phy_set_drvdata(*phy, macro); + /* Power off serdes by default */ + sparx5_serdes_power_off(*phy); + return 0; } @@ -2491,6 +2590,9 @@ static int sparx5_serdes_probe(struct platform_device *pdev) return err; } + /* Power down all CMUs by default */ + sparx5_serdes_cmu_power_off(priv); + provider = devm_of_phy_provider_register(priv->dev, sparx5_serdes_xlate); return PTR_ERR_OR_ZERO(provider); diff --git a/drivers/phy/microchip/sparx5_serdes.h b/drivers/phy/microchip/sparx5_serdes.h index 0a3e496e6210ccbfcdef12d5004ac09b02221c59..13f94a29225a40c533af45fcb98bfa943964c8d9 100644 --- a/drivers/phy/microchip/sparx5_serdes.h +++ b/drivers/phy/microchip/sparx5_serdes.h @@ -30,7 +30,6 @@ struct sparx5_serdes_private { struct device *dev; void __iomem *regs[NUM_TARGETS]; struct phy *phys[SPX5_SERDES_MAX]; - bool cmu_enabled; unsigned long coreclock; }; diff --git a/drivers/phy/microchip/sparx5_serdes_regs.h b/drivers/phy/microchip/sparx5_serdes_regs.h index b96386a4df5a26b05c732e5048269df441bace7f..d0543fd3dc94d268f510b50d04adf5abebfb544b 100644 --- a/drivers/phy/microchip/sparx5_serdes_regs.h +++ b/drivers/phy/microchip/sparx5_serdes_regs.h @@ -2149,6 +2149,92 @@ enum sparx5_serdes_target { #define SD_CMU_CMU_05_CFG_BIAS_TP_SEL_1_0_GET(x)\ FIELD_GET(SD_CMU_CMU_05_CFG_BIAS_TP_SEL_1_0, x) +/* SD10G_CMU_TARGET:CMU_GRP_1:CMU_06 */ +#define SD_CMU_CMU_06(t) \ + __REG(TARGET_SD_CMU, t, 14, 20, 0, 1, 72, 4, 0, 1, 4) + +#define SD_CMU_CMU_06_CFG_DISLOS BIT(0) +#define SD_CMU_CMU_06_CFG_DISLOS_SET(x)\ + FIELD_PREP(SD_CMU_CMU_06_CFG_DISLOS, x) +#define SD_CMU_CMU_06_CFG_DISLOS_GET(x)\ + FIELD_GET(SD_CMU_CMU_06_CFG_DISLOS, x) + +#define SD_CMU_CMU_06_CFG_DISLOL BIT(1) +#define SD_CMU_CMU_06_CFG_DISLOL_SET(x)\ + FIELD_PREP(SD_CMU_CMU_06_CFG_DISLOL, x) +#define SD_CMU_CMU_06_CFG_DISLOL_GET(x)\ + FIELD_GET(SD_CMU_CMU_06_CFG_DISLOL, x) + +#define SD_CMU_CMU_06_CFG_DCLOL BIT(2) +#define SD_CMU_CMU_06_CFG_DCLOL_SET(x)\ + FIELD_PREP(SD_CMU_CMU_06_CFG_DCLOL, x) +#define SD_CMU_CMU_06_CFG_DCLOL_GET(x)\ + FIELD_GET(SD_CMU_CMU_06_CFG_DCLOL, x) + +#define SD_CMU_CMU_06_CFG_FORCE_RX_FILT BIT(3) +#define SD_CMU_CMU_06_CFG_FORCE_RX_FILT_SET(x)\ + FIELD_PREP(SD_CMU_CMU_06_CFG_FORCE_RX_FILT, x) +#define SD_CMU_CMU_06_CFG_FORCE_RX_FILT_GET(x)\ + FIELD_GET(SD_CMU_CMU_06_CFG_FORCE_RX_FILT, x) + +#define SD_CMU_CMU_06_CFG_CTRL_LOGIC_PD BIT(4) +#define SD_CMU_CMU_06_CFG_CTRL_LOGIC_PD_SET(x)\ + FIELD_PREP(SD_CMU_CMU_06_CFG_CTRL_LOGIC_PD, x) +#define SD_CMU_CMU_06_CFG_CTRL_LOGIC_PD_GET(x)\ + FIELD_GET(SD_CMU_CMU_06_CFG_CTRL_LOGIC_PD, x) + +#define SD_CMU_CMU_06_CFG_VCO_PD BIT(5) +#define SD_CMU_CMU_06_CFG_VCO_PD_SET(x)\ + FIELD_PREP(SD_CMU_CMU_06_CFG_VCO_PD, x) +#define SD_CMU_CMU_06_CFG_VCO_PD_GET(x)\ + FIELD_GET(SD_CMU_CMU_06_CFG_VCO_PD, x) + +#define SD_CMU_CMU_06_CFG_VCO_CAL_RESETN BIT(6) +#define SD_CMU_CMU_06_CFG_VCO_CAL_RESETN_SET(x)\ + FIELD_PREP(SD_CMU_CMU_06_CFG_VCO_CAL_RESETN, x) +#define SD_CMU_CMU_06_CFG_VCO_CAL_RESETN_GET(x)\ + FIELD_GET(SD_CMU_CMU_06_CFG_VCO_CAL_RESETN, x) + +#define SD_CMU_CMU_06_CFG_VCO_CAL_BYP BIT(7) +#define SD_CMU_CMU_06_CFG_VCO_CAL_BYP_SET(x)\ + FIELD_PREP(SD_CMU_CMU_06_CFG_VCO_CAL_BYP, x) +#define SD_CMU_CMU_06_CFG_VCO_CAL_BYP_GET(x)\ + FIELD_GET(SD_CMU_CMU_06_CFG_VCO_CAL_BYP, x) + +/* SD10G_CMU_TARGET:CMU_GRP_1:CMU_08 */ +#define SD_CMU_CMU_08(t) \ + __REG(TARGET_SD_CMU, t, 14, 20, 0, 1, 72, 12, 0, 1, 4) + +#define SD_CMU_CMU_08_CFG_VFILT2PAD BIT(0) +#define SD_CMU_CMU_08_CFG_VFILT2PAD_SET(x)\ + FIELD_PREP(SD_CMU_CMU_08_CFG_VFILT2PAD, x) +#define SD_CMU_CMU_08_CFG_VFILT2PAD_GET(x)\ + FIELD_GET(SD_CMU_CMU_08_CFG_VFILT2PAD, x) + +#define SD_CMU_CMU_08_CFG_EN_DUMMY BIT(1) +#define SD_CMU_CMU_08_CFG_EN_DUMMY_SET(x)\ + FIELD_PREP(SD_CMU_CMU_08_CFG_EN_DUMMY, x) +#define SD_CMU_CMU_08_CFG_EN_DUMMY_GET(x)\ + FIELD_GET(SD_CMU_CMU_08_CFG_EN_DUMMY, x) + +#define SD_CMU_CMU_08_CFG_CK_TREE_PD BIT(2) +#define SD_CMU_CMU_08_CFG_CK_TREE_PD_SET(x)\ + FIELD_PREP(SD_CMU_CMU_08_CFG_CK_TREE_PD, x) +#define SD_CMU_CMU_08_CFG_CK_TREE_PD_GET(x)\ + FIELD_GET(SD_CMU_CMU_08_CFG_CK_TREE_PD, x) + +#define SD_CMU_CMU_08_CFG_RST_TREE_PD_MAN BIT(3) +#define SD_CMU_CMU_08_CFG_RST_TREE_PD_MAN_SET(x)\ + FIELD_PREP(SD_CMU_CMU_08_CFG_RST_TREE_PD_MAN, x) +#define SD_CMU_CMU_08_CFG_RST_TREE_PD_MAN_GET(x)\ + FIELD_GET(SD_CMU_CMU_08_CFG_RST_TREE_PD_MAN, x) + +#define SD_CMU_CMU_08_CFG_RST_TREE_PD_MAN_EN BIT(4) +#define SD_CMU_CMU_08_CFG_RST_TREE_PD_MAN_EN_SET(x)\ + FIELD_PREP(SD_CMU_CMU_08_CFG_RST_TREE_PD_MAN_EN, x) +#define SD_CMU_CMU_08_CFG_RST_TREE_PD_MAN_EN_GET(x)\ + FIELD_GET(SD_CMU_CMU_08_CFG_RST_TREE_PD_MAN_EN, x) + /* SD10G_CMU_TARGET:CMU_GRP_1:CMU_09 */ #define SD_CMU_CMU_09(t) __REG(TARGET_SD_CMU, t, 14, 20, 0, 1, 72, 16, 0, 1, 4) @@ -2443,6 +2529,16 @@ enum sparx5_serdes_target { #define SD_LANE_SD_LANE_STAT_DBG_OBS_GET(x)\ FIELD_GET(SD_LANE_SD_LANE_STAT_DBG_OBS, x) +/* SD_LANE_TARGET:SD_PWR_CFG:QUIET_MODE_6G */ +#define SD_LANE_QUIET_MODE_6G(t) \ + __REG(TARGET_SD_LANE, t, 25, 24, 0, 1, 8, 4, 0, 1, 4) + +#define SD_LANE_QUIET_MODE_6G_QUIET_MODE GENMASK(24, 0) +#define SD_LANE_QUIET_MODE_6G_QUIET_MODE_SET(x)\ + FIELD_PREP(SD_LANE_QUIET_MODE_6G_QUIET_MODE, x) +#define SD_LANE_QUIET_MODE_6G_QUIET_MODE_GET(x)\ + FIELD_GET(SD_LANE_QUIET_MODE_6G_QUIET_MODE, x) + /* SD_LANE_TARGET:CFG_STAT_FX100:MISC */ #define SD_LANE_MISC(t) __REG(TARGET_SD_LANE, t, 25, 56, 0, 1, 56, 0, 0, 1, 4) @@ -2692,4 +2788,14 @@ enum sparx5_serdes_target { #define SD_LANE_25G_SD_LANE_STAT_DBG_OBS_GET(x)\ FIELD_GET(SD_LANE_25G_SD_LANE_STAT_DBG_OBS, x) +/* SD25G_CFG_TARGET:SD_PWR_CFG:QUIET_MODE_6G */ +#define SD_LANE_25G_QUIET_MODE_6G(t) \ + __REG(TARGET_SD_LANE_25G, t, 8, 28, 0, 1, 8, 4, 0, 1, 4) + +#define SD_LANE_25G_QUIET_MODE_6G_QUIET_MODE GENMASK(24, 0) +#define SD_LANE_25G_QUIET_MODE_6G_QUIET_MODE_SET(x)\ + FIELD_PREP(SD_LANE_25G_QUIET_MODE_6G_QUIET_MODE, x) +#define SD_LANE_25G_QUIET_MODE_6G_QUIET_MODE_GET(x)\ + FIELD_GET(SD_LANE_25G_QUIET_MODE_6G_QUIET_MODE, x) + #endif /* _SPARX5_SERDES_REGS_H_ */ diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c index 6464dcb56d56d09f3e12eb94b6875990c177ce06..96a0b1e111f34997f664d63151038cf582c2fb67 100644 --- a/drivers/phy/phy-core.c +++ b/drivers/phy/phy-core.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -20,6 +21,7 @@ #include static struct class *phy_class; +static struct dentry *phy_debugfs_root; static DEFINE_MUTEX(phy_provider_mutex); static LIST_HEAD(phy_provider_list); static LIST_HEAD(phys); @@ -996,6 +998,8 @@ struct phy *phy_create(struct device *dev, struct device_node *node, pm_runtime_no_callbacks(&phy->dev); } + phy->debugfs = debugfs_create_dir(dev_name(&phy->dev), phy_debugfs_root); + return phy; put_dev: @@ -1226,6 +1230,7 @@ static void phy_release(struct device *dev) phy = to_phy(dev); dev_vdbg(dev, "releasing '%s'\n", dev_name(dev)); + debugfs_remove_recursive(phy->debugfs); regulator_put(phy->pwr); ida_simple_remove(&phy_ida, phy->id); kfree(phy); @@ -1242,6 +1247,15 @@ static int __init phy_core_init(void) phy_class->dev_release = phy_release; + phy_debugfs_root = debugfs_create_dir("phy", NULL); + return 0; } device_initcall(phy_core_init); + +static void __exit phy_core_exit(void) +{ + debugfs_remove_recursive(phy_debugfs_root); + class_destroy(phy_class); +} +module_exit(phy_core_exit); diff --git a/drivers/phy/qualcomm/Kconfig b/drivers/phy/qualcomm/Kconfig index 4850d48f31fa192580a81f7f21529a4af969027b..97ca5952e34e3cb37389b7386fb668c97999798c 100644 --- a/drivers/phy/qualcomm/Kconfig +++ b/drivers/phy/qualcomm/Kconfig @@ -59,8 +59,11 @@ if PHY_QCOM_QMP config PHY_QCOM_QMP_COMBO tristate "Qualcomm QMP Combo PHY Driver" default PHY_QCOM_QMP + depends on TYPEC || TYPEC=n + depends on DRM || DRM=n select GENERIC_PHY select MFD_SYSCON + select DRM_PANEL_BRIDGE if DRM help Enable this to support the QMP Combo PHY transceiver that is used with USB3 and DisplayPort controllers on Qualcomm chips. @@ -185,3 +188,12 @@ config PHY_QCOM_IPQ806X_USB This option enables support for the Synopsis PHYs present inside the Qualcomm USB3.0 DWC3 controller on ipq806x SoC. This driver supports both HS and SS PHY controllers. + +config PHY_QCOM_SGMII_ETH + tristate "Qualcomm DWMAC SGMII SerDes/PHY driver" + depends on OF && (ARCH_QCOM || COMPILE_TEST) + depends on HAS_IOMEM + select GENERIC_PHY + help + Enable this to support the internal SerDes/SGMII PHY on various + Qualcomm chipsets. diff --git a/drivers/phy/qualcomm/Makefile b/drivers/phy/qualcomm/Makefile index de3dc9ccf067d29ffc99600d2281bc619fc4bd56..b030858e0f8d6e3a5b14a523c0f5843d60dbc304 100644 --- a/drivers/phy/qualcomm/Makefile +++ b/drivers/phy/qualcomm/Makefile @@ -20,4 +20,5 @@ obj-$(CONFIG_PHY_QCOM_USB_HSIC) += phy-qcom-usb-hsic.o obj-$(CONFIG_PHY_QCOM_USB_HS_28NM) += phy-qcom-usb-hs-28nm.o obj-$(CONFIG_PHY_QCOM_USB_SS) += phy-qcom-usb-ss.o obj-$(CONFIG_PHY_QCOM_USB_SNPS_FEMTO_V2)+= phy-qcom-snps-femto-v2.o -obj-$(CONFIG_PHY_QCOM_IPQ806X_USB) += phy-qcom-ipq806x-usb.o +obj-$(CONFIG_PHY_QCOM_IPQ806X_USB) += phy-qcom-ipq806x-usb.o +obj-$(CONFIG_PHY_QCOM_SGMII_ETH) += phy-qcom-sgmii-eth.o diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c index 87b17e5877ab8c6d9ed1ab082cda5ba974ab617b..bebce8c591a301c6cbc9b576baa0efe7b164beab 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c +++ b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c @@ -19,6 +19,10 @@ #include #include #include +#include +#include + +#include #include @@ -63,6 +67,10 @@ /* QPHY_V3_PCS_MISC_CLAMP_ENABLE register bits */ #define CLAMP_EN BIT(0) /* enables i/o clamp_n */ +/* QPHY_V3_DP_COM_TYPEC_CTRL register bits */ +#define SW_PORTSELECT_VAL BIT(0) +#define SW_PORTSELECT_MUX BIT(1) + #define PHY_INIT_COMPLETE_TIMEOUT 10000 struct qmp_phy_init_tbl { @@ -1315,14 +1323,21 @@ struct qmp_combo { struct phy *usb_phy; enum phy_mode mode; + unsigned int usb_init_count; struct phy *dp_phy; unsigned int dp_aux_cfg; struct phy_configure_opts_dp dp_opts; + unsigned int dp_init_count; struct clk_fixed_rate pipe_clk_fixed; struct clk_hw dp_link_hw; struct clk_hw dp_pixel_hw; + + struct drm_bridge bridge; + + struct typec_switch_dev *sw; + enum typec_orientation orientation; }; static void qmp_v3_dp_aux_init(struct qmp_combo *qmp); @@ -1954,30 +1969,24 @@ static void qmp_v3_configure_dp_tx(struct qmp_combo *qmp) static bool qmp_combo_configure_dp_mode(struct qmp_combo *qmp) { + bool reverse = (qmp->orientation == TYPEC_ORIENTATION_REVERSE); + const struct phy_configure_opts_dp *dp_opts = &qmp->dp_opts; u32 val; - bool reverse = false; val = DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN | DP_PHY_PD_CTL_PLL_PWRDN | DP_PHY_PD_CTL_DP_CLAMP_EN; - /* - * TODO: Assume orientation is CC1 for now and two lanes, need to - * use type-c connector to understand orientation and lanes. - * - * Otherwise val changes to be like below if this code understood - * the orientation of the type-c cable. - * - * if (lane_cnt == 4 || orientation == ORIENTATION_CC2) - * val |= DP_PHY_PD_CTL_LANE_0_1_PWRDN; - * if (lane_cnt == 4 || orientation == ORIENTATION_CC1) - * val |= DP_PHY_PD_CTL_LANE_2_3_PWRDN; - * if (orientation == ORIENTATION_CC2) - * writel(0x4c, qmp->dp_dp_phy + QSERDES_V3_DP_PHY_MODE); - */ - val |= DP_PHY_PD_CTL_LANE_2_3_PWRDN; + if (dp_opts->lanes == 4 || reverse) + val |= DP_PHY_PD_CTL_LANE_0_1_PWRDN; + if (dp_opts->lanes == 4 || !reverse) + val |= DP_PHY_PD_CTL_LANE_2_3_PWRDN; + writel(val, qmp->dp_dp_phy + QSERDES_DP_PHY_PD_CTL); - writel(0x5c, qmp->dp_dp_phy + QSERDES_DP_PHY_MODE); + if (reverse) + writel(0x4c, qmp->pcs + QSERDES_DP_PHY_MODE); + else + writel(0x5c, qmp->pcs + QSERDES_DP_PHY_MODE); return reverse; } @@ -2142,6 +2151,7 @@ static void qmp_v4_configure_dp_tx(struct qmp_combo *qmp) static int qmp_v456_configure_dp_phy(struct qmp_combo *qmp, unsigned int com_resetm_ctrl_reg, unsigned int com_c_ready_status_reg, + unsigned int com_cmn_status_reg, unsigned int dp_phy_status_reg) { const struct phy_configure_opts_dp *dp_opts = &qmp->dp_opts; @@ -2198,14 +2208,14 @@ static int qmp_v456_configure_dp_phy(struct qmp_combo *qmp, 10000)) return -ETIMEDOUT; - if (readl_poll_timeout(qmp->dp_serdes + QSERDES_V4_COM_CMN_STATUS, + if (readl_poll_timeout(qmp->dp_serdes + com_cmn_status_reg, status, ((status & BIT(0)) > 0), 500, 10000)) return -ETIMEDOUT; - if (readl_poll_timeout(qmp->dp_serdes + QSERDES_V4_COM_CMN_STATUS, + if (readl_poll_timeout(qmp->dp_serdes + com_cmn_status_reg, status, ((status & BIT(1)) > 0), 500, @@ -2233,14 +2243,15 @@ static int qmp_v456_configure_dp_phy(struct qmp_combo *qmp, static int qmp_v4_configure_dp_phy(struct qmp_combo *qmp) { + bool reverse = (qmp->orientation == TYPEC_ORIENTATION_REVERSE); const struct phy_configure_opts_dp *dp_opts = &qmp->dp_opts; u32 bias0_en, drvr0_en, bias1_en, drvr1_en; - bool reverse = false; u32 status; int ret; ret = qmp_v456_configure_dp_phy(qmp, QSERDES_V4_COM_RESETSM_CNTRL, QSERDES_V4_COM_C_READY_STATUS, + QSERDES_V4_COM_CMN_STATUS, QSERDES_V4_DP_PHY_STATUS); if (ret < 0) return ret; @@ -2297,14 +2308,15 @@ static int qmp_v4_configure_dp_phy(struct qmp_combo *qmp) static int qmp_v5_configure_dp_phy(struct qmp_combo *qmp) { + bool reverse = (qmp->orientation == TYPEC_ORIENTATION_REVERSE); const struct phy_configure_opts_dp *dp_opts = &qmp->dp_opts; u32 bias0_en, drvr0_en, bias1_en, drvr1_en; - bool reverse = false; u32 status; int ret; ret = qmp_v456_configure_dp_phy(qmp, QSERDES_V4_COM_RESETSM_CNTRL, QSERDES_V4_COM_C_READY_STATUS, + QSERDES_V4_COM_CMN_STATUS, QSERDES_V4_DP_PHY_STATUS); if (ret < 0) return ret; @@ -2356,14 +2368,15 @@ static int qmp_v5_configure_dp_phy(struct qmp_combo *qmp) static int qmp_v6_configure_dp_phy(struct qmp_combo *qmp) { + bool reverse = (qmp->orientation == TYPEC_ORIENTATION_REVERSE); const struct phy_configure_opts_dp *dp_opts = &qmp->dp_opts; u32 bias0_en, drvr0_en, bias1_en, drvr1_en; - bool reverse = false; u32 status; int ret; ret = qmp_v456_configure_dp_phy(qmp, QSERDES_V6_COM_RESETSM_CNTRL, QSERDES_V6_COM_C_READY_STATUS, + QSERDES_V6_COM_CMN_STATUS, QSERDES_V6_DP_PHY_STATUS); if (ret < 0) return ret; @@ -2437,12 +2450,16 @@ static int qmp_combo_dp_configure(struct phy *phy, union phy_configure_opts *opt struct qmp_combo *qmp = phy_get_drvdata(phy); const struct qmp_phy_cfg *cfg = qmp->cfg; + mutex_lock(&qmp->phy_mutex); + memcpy(&qmp->dp_opts, dp_opts, sizeof(*dp_opts)); if (qmp->dp_opts.set_voltages) { cfg->configure_dp_tx(qmp); qmp->dp_opts.set_voltages = 0; } + mutex_unlock(&qmp->phy_mutex); + return 0; } @@ -2450,24 +2467,27 @@ static int qmp_combo_dp_calibrate(struct phy *phy) { struct qmp_combo *qmp = phy_get_drvdata(phy); const struct qmp_phy_cfg *cfg = qmp->cfg; + int ret = 0; + + mutex_lock(&qmp->phy_mutex); if (cfg->calibrate_dp_phy) - return cfg->calibrate_dp_phy(qmp); + ret = cfg->calibrate_dp_phy(qmp); - return 0; + mutex_unlock(&qmp->phy_mutex); + + return ret; } -static int qmp_combo_com_init(struct qmp_combo *qmp) +static int qmp_combo_com_init(struct qmp_combo *qmp, bool force) { const struct qmp_phy_cfg *cfg = qmp->cfg; void __iomem *com = qmp->com; int ret; + u32 val; - mutex_lock(&qmp->phy_mutex); - if (qmp->init_count++) { - mutex_unlock(&qmp->phy_mutex); + if (!force && qmp->init_count++) return 0; - } ret = regulator_bulk_enable(cfg->num_vregs, qmp->vregs); if (ret) { @@ -2498,10 +2518,12 @@ static int qmp_combo_com_init(struct qmp_combo *qmp) SW_DPPHY_RESET_MUX | SW_DPPHY_RESET | SW_USB3PHY_RESET_MUX | SW_USB3PHY_RESET); - /* Default type-c orientation, i.e CC1 */ - qphy_setbits(com, QPHY_V3_DP_COM_TYPEC_CTRL, 0x02); - - qphy_setbits(com, QPHY_V3_DP_COM_PHY_MODE_CTRL, USB3_MODE | DP_MODE); + /* Use software based port select and switch on typec orientation */ + val = SW_PORTSELECT_MUX; + if (qmp->orientation == TYPEC_ORIENTATION_REVERSE) + val |= SW_PORTSELECT_VAL; + writel(val, com + QPHY_V3_DP_COM_TYPEC_CTRL); + writel(USB3_MODE | DP_MODE, com + QPHY_V3_DP_COM_PHY_MODE_CTRL); /* bring both QMP USB and QMP DP PHYs PCS block out of reset */ qphy_clrbits(com, QPHY_V3_DP_COM_RESET_OVRD_CTRL, @@ -2514,8 +2536,6 @@ static int qmp_combo_com_init(struct qmp_combo *qmp) qphy_setbits(qmp->pcs, cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL], SW_PWRDN); - mutex_unlock(&qmp->phy_mutex); - return 0; err_assert_reset: @@ -2524,20 +2544,16 @@ static int qmp_combo_com_init(struct qmp_combo *qmp) regulator_bulk_disable(cfg->num_vregs, qmp->vregs); err_decrement_count: qmp->init_count--; - mutex_unlock(&qmp->phy_mutex); return ret; } -static int qmp_combo_com_exit(struct qmp_combo *qmp) +static int qmp_combo_com_exit(struct qmp_combo *qmp, bool force) { const struct qmp_phy_cfg *cfg = qmp->cfg; - mutex_lock(&qmp->phy_mutex); - if (--qmp->init_count) { - mutex_unlock(&qmp->phy_mutex); + if (!force && --qmp->init_count) return 0; - } reset_control_bulk_assert(cfg->num_resets, qmp->resets); @@ -2545,8 +2561,6 @@ static int qmp_combo_com_exit(struct qmp_combo *qmp) regulator_bulk_disable(cfg->num_vregs, qmp->vregs); - mutex_unlock(&qmp->phy_mutex); - return 0; } @@ -2556,20 +2570,32 @@ static int qmp_combo_dp_init(struct phy *phy) const struct qmp_phy_cfg *cfg = qmp->cfg; int ret; - ret = qmp_combo_com_init(qmp); + mutex_lock(&qmp->phy_mutex); + + ret = qmp_combo_com_init(qmp, false); if (ret) - return ret; + goto out_unlock; cfg->dp_aux_init(qmp); - return 0; + qmp->dp_init_count++; + +out_unlock: + mutex_unlock(&qmp->phy_mutex); + return ret; } static int qmp_combo_dp_exit(struct phy *phy) { struct qmp_combo *qmp = phy_get_drvdata(phy); - qmp_combo_com_exit(qmp); + mutex_lock(&qmp->phy_mutex); + + qmp_combo_com_exit(qmp, false); + + qmp->dp_init_count--; + + mutex_unlock(&qmp->phy_mutex); return 0; } @@ -2581,6 +2607,8 @@ static int qmp_combo_dp_power_on(struct phy *phy) void __iomem *tx = qmp->dp_tx; void __iomem *tx2 = qmp->dp_tx2; + mutex_lock(&qmp->phy_mutex); + qmp_combo_dp_serdes_init(qmp); qmp_combo_configure_lane(tx, cfg->dp_tx_tbl, cfg->dp_tx_tbl_num, 1); @@ -2592,6 +2620,8 @@ static int qmp_combo_dp_power_on(struct phy *phy) /* Configure link rate, swing, etc. */ cfg->configure_dp_phy(qmp); + mutex_unlock(&qmp->phy_mutex); + return 0; } @@ -2599,9 +2629,13 @@ static int qmp_combo_dp_power_off(struct phy *phy) { struct qmp_combo *qmp = phy_get_drvdata(phy); + mutex_lock(&qmp->phy_mutex); + /* Assert DP PHY power down */ writel(DP_PHY_PD_CTL_PSR_PWRDN, qmp->dp_dp_phy + QSERDES_DP_PHY_PD_CTL); + mutex_unlock(&qmp->phy_mutex); + return 0; } @@ -2687,14 +2721,21 @@ static int qmp_combo_usb_init(struct phy *phy) struct qmp_combo *qmp = phy_get_drvdata(phy); int ret; - ret = qmp_combo_com_init(qmp); + mutex_lock(&qmp->phy_mutex); + ret = qmp_combo_com_init(qmp, false); if (ret) - return ret; + goto out_unlock; ret = qmp_combo_usb_power_on(phy); - if (ret) - qmp_combo_com_exit(qmp); + if (ret) { + qmp_combo_com_exit(qmp, false); + goto out_unlock; + } + + qmp->usb_init_count++; +out_unlock: + mutex_unlock(&qmp->phy_mutex); return ret; } @@ -2703,11 +2744,20 @@ static int qmp_combo_usb_exit(struct phy *phy) struct qmp_combo *qmp = phy_get_drvdata(phy); int ret; + mutex_lock(&qmp->phy_mutex); ret = qmp_combo_usb_power_off(phy); if (ret) - return ret; + goto out_unlock; + + ret = qmp_combo_com_exit(qmp, false); + if (ret) + goto out_unlock; + + qmp->usb_init_count--; - return qmp_combo_com_exit(qmp); +out_unlock: + mutex_unlock(&qmp->phy_mutex); + return ret; } static int qmp_combo_usb_set_mode(struct phy *phy, enum phy_mode mode, int submode) @@ -3173,6 +3223,103 @@ static int qmp_combo_register_clocks(struct qmp_combo *qmp, struct device_node * return devm_add_action_or_reset(qmp->dev, phy_clk_release_provider, dp_np); } +#if IS_ENABLED(CONFIG_TYPEC) +static int qmp_combo_typec_switch_set(struct typec_switch_dev *sw, + enum typec_orientation orientation) +{ + struct qmp_combo *qmp = typec_switch_get_drvdata(sw); + const struct qmp_phy_cfg *cfg = qmp->cfg; + + if (orientation == qmp->orientation || orientation == TYPEC_ORIENTATION_NONE) + return 0; + + mutex_lock(&qmp->phy_mutex); + qmp->orientation = orientation; + + if (qmp->init_count) { + if (qmp->usb_init_count) + qmp_combo_usb_power_off(qmp->usb_phy); + qmp_combo_com_exit(qmp, true); + + qmp_combo_com_init(qmp, true); + if (qmp->usb_init_count) + qmp_combo_usb_power_on(qmp->usb_phy); + if (qmp->dp_init_count) + cfg->dp_aux_init(qmp); + } + mutex_unlock(&qmp->phy_mutex); + + return 0; +} + +static void qmp_combo_typec_unregister(void *data) +{ + struct qmp_combo *qmp = data; + + typec_switch_unregister(qmp->sw); +} + +static int qmp_combo_typec_switch_register(struct qmp_combo *qmp) +{ + struct typec_switch_desc sw_desc = {}; + struct device *dev = qmp->dev; + + sw_desc.drvdata = qmp; + sw_desc.fwnode = dev->fwnode; + sw_desc.set = qmp_combo_typec_switch_set; + qmp->sw = typec_switch_register(dev, &sw_desc); + if (IS_ERR(qmp->sw)) { + dev_err(dev, "Unable to register typec switch: %pe\n", qmp->sw); + return PTR_ERR(qmp->sw); + } + + return devm_add_action_or_reset(dev, qmp_combo_typec_unregister, qmp); +} +#else +static int qmp_combo_typec_switch_register(struct qmp_combo *qmp) +{ + return 0; +} +#endif + +#if IS_ENABLED(CONFIG_DRM) +static int qmp_combo_bridge_attach(struct drm_bridge *bridge, + enum drm_bridge_attach_flags flags) +{ + struct qmp_combo *qmp = container_of(bridge, struct qmp_combo, bridge); + struct drm_bridge *next_bridge; + + if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)) + return -EINVAL; + + next_bridge = devm_drm_of_get_bridge(qmp->dev, qmp->dev->of_node, 0, 0); + if (IS_ERR(next_bridge)) { + dev_err(qmp->dev, "failed to acquire drm_bridge: %pe\n", next_bridge); + return PTR_ERR(next_bridge); + } + + return drm_bridge_attach(bridge->encoder, next_bridge, bridge, + DRM_BRIDGE_ATTACH_NO_CONNECTOR); +} + +static const struct drm_bridge_funcs qmp_combo_bridge_funcs = { + .attach = qmp_combo_bridge_attach, +}; + +static int qmp_combo_dp_register_bridge(struct qmp_combo *qmp) +{ + qmp->bridge.funcs = &qmp_combo_bridge_funcs; + qmp->bridge.of_node = qmp->dev->of_node; + + return devm_drm_bridge_add(qmp->dev, &qmp->bridge); +} +#else +static int qmp_combo_dp_register_bridge(struct qmp_combo *qmp) +{ + return 0; +} +#endif + static int qmp_combo_parse_dt_lecacy_dp(struct qmp_combo *qmp, struct device_node *np) { struct device *dev = qmp->dev; @@ -3353,6 +3500,8 @@ static int qmp_combo_probe(struct platform_device *pdev) qmp->dev = dev; + qmp->orientation = TYPEC_ORIENTATION_NORMAL; + qmp->cfg = of_device_get_match_data(dev); if (!qmp->cfg) return -EINVAL; @@ -3371,6 +3520,14 @@ static int qmp_combo_probe(struct platform_device *pdev) if (ret) return ret; + ret = qmp_combo_typec_switch_register(qmp); + if (ret) + return ret; + + ret = qmp_combo_dp_register_bridge(qmp); + if (ret) + return ret; + /* Check for legacy binding with child nodes. */ usb_np = of_get_child_by_name(dev->of_node, "usb3-phy"); if (usb_np) { diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-usb.c b/drivers/phy/qualcomm/phy-qcom-qmp-usb.c index a49711c5a63d803384022d3ae3b9c42ebcc40b15..466f0a56c82e1da6de8d78771d1c57c66c8e9496 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp-usb.c +++ b/drivers/phy/qualcomm/phy-qcom-qmp-usb.c @@ -139,6 +139,88 @@ static const unsigned int qmp_v5_usb3phy_regs_layout[QPHY_LAYOUT_SIZE] = { [QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR] = QPHY_V5_PCS_USB3_LFPS_RXTERM_IRQ_CLEAR, }; +static const struct qmp_phy_init_tbl ipq9574_usb3_serdes_tbl[] = { + QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_EN_SEL, 0x1a), + QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x08), + QMP_PHY_INIT_CFG(QSERDES_COM_CLK_SELECT, 0x30), + QMP_PHY_INIT_CFG(QSERDES_COM_BG_TRIM, 0x0f), + QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_FASTLOCK_FO_GAIN, 0x0b), + QMP_PHY_INIT_CFG(QSERDES_COM_SVS_MODE_CLK_SEL, 0x01), + QMP_PHY_INIT_CFG(QSERDES_COM_HSCLK_SEL, 0x00), + QMP_PHY_INIT_CFG(QSERDES_COM_CMN_CONFIG, 0x06), + QMP_PHY_INIT_CFG(QSERDES_COM_PLL_IVCO, 0x0f), + QMP_PHY_INIT_CFG(QSERDES_COM_SYS_CLK_CTRL, 0x06), + /* PLL and Loop filter settings */ + QMP_PHY_INIT_CFG(QSERDES_COM_DEC_START_MODE0, 0x68), + QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START1_MODE0, 0xab), + QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START2_MODE0, 0xaa), + QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START3_MODE0, 0x02), + QMP_PHY_INIT_CFG(QSERDES_COM_CP_CTRL_MODE0, 0x09), + QMP_PHY_INIT_CFG(QSERDES_COM_PLL_RCTRL_MODE0, 0x16), + QMP_PHY_INIT_CFG(QSERDES_COM_PLL_CCTRL_MODE0, 0x28), + QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN0_MODE0, 0xa0), + QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP1_MODE0, 0xaa), + QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP2_MODE0, 0x29), + QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP3_MODE0, 0x00), + QMP_PHY_INIT_CFG(QSERDES_COM_CORE_CLK_EN, 0x00), + QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_CFG, 0x00), + QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_MAP, 0x00), + QMP_PHY_INIT_CFG(QSERDES_COM_BG_TIMER, 0x0a), + /* SSC settings */ + QMP_PHY_INIT_CFG(QSERDES_COM_SSC_EN_CENTER, 0x01), + QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER1, 0x7d), + QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER2, 0x01), + QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER1, 0x00), + QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER2, 0x00), + QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE1, 0x0a), + QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE2, 0x05), +}; + +static const struct qmp_phy_init_tbl ipq9574_usb3_tx_tbl[] = { + QMP_PHY_INIT_CFG(QSERDES_TX_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN, 0x45), + QMP_PHY_INIT_CFG(QSERDES_TX_RCV_DETECT_LVL_2, 0x12), + QMP_PHY_INIT_CFG(QSERDES_TX_LANE_MODE, 0x06), +}; + +static const struct qmp_phy_init_tbl ipq9574_usb3_rx_tbl[] = { + QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SO_GAIN, 0x06), + QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2, 0x02), + QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL3, 0x6c), + QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4c), + QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL4, 0xb8), + QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x77), + QMP_PHY_INIT_CFG(QSERDES_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80), + QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_CNTRL, 0x03), + QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_DEGLITCH_CNTRL, 0x16), + QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_ENABLES, 0x0c), +}; + +static const struct qmp_phy_init_tbl ipq9574_usb3_pcs_tbl[] = { + QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V0, 0x15), + QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V0, 0x0e), + QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL2, 0x83), + QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL1, 0x02), + QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_L, 0x09), + QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_H_TOL, 0xa2), + QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_MAN_CODE, 0x85), + QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG1, 0xd1), + QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG2, 0x1f), + QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG3, 0x47), + QMP_PHY_INIT_CFG(QPHY_V3_PCS_POWER_STATE_CONFIG2, 0x1b), + QMP_PHY_INIT_CFG(QPHY_V3_PCS_RXEQTRAINING_WAIT_TIME, 0x75), + QMP_PHY_INIT_CFG(QPHY_V3_PCS_RXEQTRAINING_RUN_TIME, 0x13), + QMP_PHY_INIT_CFG(QPHY_V3_PCS_LFPS_TX_ECSTART_EQTLOCK, 0x86), + QMP_PHY_INIT_CFG(QPHY_V3_PCS_PWRUP_RESET_DLY_TIME_AUXCLK, 0x04), + QMP_PHY_INIT_CFG(QPHY_V3_PCS_TSYNC_RSYNC_TIME, 0x44), + QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_P1U2_L, 0xe7), + QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_P1U2_H, 0x03), + QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_U3_L, 0x40), + QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_U3_H, 0x00), + QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_SIGDET_LVL, 0x88), + QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V0, 0x17), + QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V0, 0x0f), +}; + static const struct qmp_phy_init_tbl ipq8074_usb3_serdes_tbl[] = { QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_EN_SEL, 0x1a), QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x08), @@ -1408,12 +1490,36 @@ static const struct qmp_phy_init_tbl sc8280xp_usb3_uniphy_pcs_tbl[] = { QMP_PHY_INIT_CFG(QPHY_V5_PCS_REFGEN_REQ_CONFIG1, 0x21), }; +static const struct qmp_phy_init_tbl sa8775p_usb3_uniphy_pcs_tbl[] = { + QMP_PHY_INIT_CFG(QPHY_V5_PCS_LOCK_DETECT_CONFIG1, 0xc4), + QMP_PHY_INIT_CFG(QPHY_V5_PCS_LOCK_DETECT_CONFIG2, 0x89), + QMP_PHY_INIT_CFG(QPHY_V5_PCS_LOCK_DETECT_CONFIG3, 0x20), + QMP_PHY_INIT_CFG(QPHY_V5_PCS_LOCK_DETECT_CONFIG6, 0x13), + QMP_PHY_INIT_CFG(QPHY_V5_PCS_RCVR_DTCT_DLY_P1U2_L, 0xe7), + QMP_PHY_INIT_CFG(QPHY_V5_PCS_RCVR_DTCT_DLY_P1U2_H, 0x03), + QMP_PHY_INIT_CFG(QPHY_V5_PCS_RX_SIGDET_LVL, 0xaa), + QMP_PHY_INIT_CFG(QPHY_V5_PCS_PCS_TX_RX_CONFIG, 0x0c), + QMP_PHY_INIT_CFG(QPHY_V5_PCS_USB3_RXEQTRAINING_DFE_TIME_S2, 0x07), + QMP_PHY_INIT_CFG(QPHY_V5_PCS_USB3_LFPS_DET_HIGH_COUNT_VAL, 0xf8), + QMP_PHY_INIT_CFG(QPHY_V5_PCS_USB3_POWER_STATE_CONFIG1, 0x6f), + QMP_PHY_INIT_CFG(QPHY_V5_PCS_CDR_RESET_TIME, 0x0a), + QMP_PHY_INIT_CFG(QPHY_V5_PCS_ALIGN_DETECT_CONFIG1, 0x88), + QMP_PHY_INIT_CFG(QPHY_V5_PCS_ALIGN_DETECT_CONFIG2, 0x13), + QMP_PHY_INIT_CFG(QPHY_V5_PCS_EQ_CONFIG1, 0x4b), + QMP_PHY_INIT_CFG(QPHY_V5_PCS_EQ_CONFIG5, 0x10), + QMP_PHY_INIT_CFG(QPHY_V5_PCS_REFGEN_REQ_CONFIG1, 0x21), +}; + struct qmp_usb_offsets { u16 serdes; u16 pcs; + u16 pcs_misc; u16 pcs_usb; u16 tx; u16 rx; + /* for PHYs with >= 2 lanes */ + u16 tx2; + u16 rx2; }; /* struct qmp_phy_cfg - per-PHY initialization config */ @@ -1558,6 +1664,24 @@ static const char * const qmp_phy_vreg_l[] = { "vdda-phy", "vdda-pll", }; +static const struct qmp_usb_offsets qmp_usb_offsets_ipq9574 = { + .serdes = 0, + .pcs = 0x800, + .pcs_usb = 0x800, + .tx = 0x200, + .rx = 0x400, +}; + +static const struct qmp_usb_offsets qmp_usb_offsets_v3 = { + .serdes = 0, + .pcs = 0xc00, + .pcs_misc = 0xa00, + .tx = 0x200, + .rx = 0x400, + .tx2 = 0x600, + .rx2 = 0x800, +}; + static const struct qmp_usb_offsets qmp_usb_offsets_v5 = { .serdes = 0, .pcs = 0x0200, @@ -1586,6 +1710,28 @@ static const struct qmp_phy_cfg ipq8074_usb3phy_cfg = { .regs = qmp_v3_usb3phy_regs_layout, }; +static const struct qmp_phy_cfg ipq9574_usb3phy_cfg = { + .lanes = 1, + + .offsets = &qmp_usb_offsets_ipq9574, + + .serdes_tbl = ipq9574_usb3_serdes_tbl, + .serdes_tbl_num = ARRAY_SIZE(ipq9574_usb3_serdes_tbl), + .tx_tbl = ipq9574_usb3_tx_tbl, + .tx_tbl_num = ARRAY_SIZE(ipq9574_usb3_tx_tbl), + .rx_tbl = ipq9574_usb3_rx_tbl, + .rx_tbl_num = ARRAY_SIZE(ipq9574_usb3_rx_tbl), + .pcs_tbl = ipq9574_usb3_pcs_tbl, + .pcs_tbl_num = ARRAY_SIZE(ipq9574_usb3_pcs_tbl), + .clk_list = msm8996_phy_clk_l, + .num_clks = ARRAY_SIZE(msm8996_phy_clk_l), + .reset_list = qcm2290_usb3phy_reset_l, + .num_resets = ARRAY_SIZE(qcm2290_usb3phy_reset_l), + .vreg_list = qmp_phy_vreg_l, + .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), + .regs = qmp_v3_usb3phy_regs_layout, +}; + static const struct qmp_phy_cfg msm8996_usb3phy_cfg = { .lanes = 1, @@ -1629,6 +1775,28 @@ static const struct qmp_phy_cfg qmp_v3_usb3phy_cfg = { .has_phy_dp_com_ctrl = true, }; +static const struct qmp_phy_cfg sa8775p_usb3_uniphy_cfg = { + .lanes = 1, + + .offsets = &qmp_usb_offsets_v5, + + .serdes_tbl = sc8280xp_usb3_uniphy_serdes_tbl, + .serdes_tbl_num = ARRAY_SIZE(sc8280xp_usb3_uniphy_serdes_tbl), + .tx_tbl = sc8280xp_usb3_uniphy_tx_tbl, + .tx_tbl_num = ARRAY_SIZE(sc8280xp_usb3_uniphy_tx_tbl), + .rx_tbl = sc8280xp_usb3_uniphy_rx_tbl, + .rx_tbl_num = ARRAY_SIZE(sc8280xp_usb3_uniphy_rx_tbl), + .pcs_tbl = sa8775p_usb3_uniphy_pcs_tbl, + .pcs_tbl_num = ARRAY_SIZE(sa8775p_usb3_uniphy_pcs_tbl), + .clk_list = qmp_v4_phy_clk_l, + .num_clks = ARRAY_SIZE(qmp_v4_phy_clk_l), + .reset_list = qcm2290_usb3phy_reset_l, + .num_resets = ARRAY_SIZE(qcm2290_usb3phy_reset_l), + .vreg_list = qmp_phy_vreg_l, + .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), + .regs = qmp_v5_usb3phy_regs_layout, +}; + static const struct qmp_phy_cfg sc7180_usb3phy_cfg = { .lanes = 2, @@ -1922,6 +2090,8 @@ static const struct qmp_phy_cfg sm8350_usb3_uniphy_cfg = { static const struct qmp_phy_cfg qcm2290_usb3phy_cfg = { .lanes = 2, + .offsets = &qmp_usb_offsets_v3, + .serdes_tbl = qcm2290_usb3_serdes_tbl, .serdes_tbl_num = ARRAY_SIZE(qcm2290_usb3_serdes_tbl), .tx_tbl = qcm2290_usb3_tx_tbl, @@ -2493,10 +2663,16 @@ static int qmp_usb_parse_dt(struct qmp_usb *qmp) qmp->serdes = base + offs->serdes; qmp->pcs = base + offs->pcs; + qmp->pcs_misc = base + offs->pcs_misc; qmp->pcs_usb = base + offs->pcs_usb; qmp->tx = base + offs->tx; qmp->rx = base + offs->rx; + if (cfg->lanes >= 2) { + qmp->tx2 = base + offs->tx2; + qmp->rx2 = base + offs->rx2; + } + qmp->pipe_clk = devm_clk_get(dev, "pipe"); if (IS_ERR(qmp->pipe_clk)) { return dev_err_probe(dev, PTR_ERR(qmp->pipe_clk), @@ -2588,6 +2764,9 @@ static const struct of_device_id qmp_usb_of_match_table[] = { }, { .compatible = "qcom,ipq8074-qmp-usb3-phy", .data = &ipq8074_usb3phy_cfg, + }, { + .compatible = "qcom,ipq9574-qmp-usb3-phy", + .data = &ipq9574_usb3phy_cfg, }, { .compatible = "qcom,msm8996-qmp-usb3-phy", .data = &msm8996_usb3phy_cfg, @@ -2597,6 +2776,9 @@ static const struct of_device_id qmp_usb_of_match_table[] = { }, { .compatible = "qcom,qcm2290-qmp-usb3-phy", .data = &qcm2290_usb3phy_cfg, + }, { + .compatible = "qcom,sa8775p-qmp-usb3-uni-phy", + .data = &sa8775p_usb3_uniphy_cfg, }, { .compatible = "qcom,sc7180-qmp-usb3-phy", .data = &sc7180_usb3phy_cfg, diff --git a/drivers/phy/qualcomm/phy-qcom-qusb2.c b/drivers/phy/qualcomm/phy-qcom-qusb2.c index 2ef638b32e8f08bc655adb504fe20a8a0723940a..bec6e40d5280f11c2a646102b321cb877910af32 100644 --- a/drivers/phy/qualcomm/phy-qcom-qusb2.c +++ b/drivers/phy/qualcomm/phy-qcom-qusb2.c @@ -911,6 +911,9 @@ static const struct of_device_id qusb2_phy_of_match_table[] = { }, { .compatible = "qcom,ipq8074-qusb2-phy", .data = &msm8996_phy_cfg, + }, { + .compatible = "qcom,ipq9574-qusb2-phy", + .data = &ipq6018_phy_cfg, }, { .compatible = "qcom,msm8953-qusb2-phy", .data = &msm8996_phy_cfg, diff --git a/drivers/phy/qualcomm/phy-qcom-sgmii-eth.c b/drivers/phy/qualcomm/phy-qcom-sgmii-eth.c new file mode 100644 index 0000000000000000000000000000000000000000..03dc753f0de1f9c3898ba8a7bcefd4ee0b7b0e21 --- /dev/null +++ b/drivers/phy/qualcomm/phy-qcom-sgmii-eth.c @@ -0,0 +1,451 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2023, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include + +#define QSERDES_QMP_PLL 0x0 +#define QSERDES_COM_BIN_VCOCAL_CMP_CODE1_MODE0 (QSERDES_QMP_PLL + 0x1ac) +#define QSERDES_COM_BIN_VCOCAL_CMP_CODE2_MODE0 (QSERDES_QMP_PLL + 0x1b0) +#define QSERDES_COM_BIN_VCOCAL_HSCLK_SEL (QSERDES_QMP_PLL + 0x1bc) +#define QSERDES_COM_CORE_CLK_EN (QSERDES_QMP_PLL + 0x174) +#define QSERDES_COM_CORECLK_DIV_MODE0 (QSERDES_QMP_PLL + 0x168) +#define QSERDES_COM_CP_CTRL_MODE0 (QSERDES_QMP_PLL + 0x74) +#define QSERDES_COM_DEC_START_MODE0 (QSERDES_QMP_PLL + 0xbc) +#define QSERDES_COM_DIV_FRAC_START1_MODE0 (QSERDES_QMP_PLL + 0xcc) +#define QSERDES_COM_DIV_FRAC_START2_MODE0 (QSERDES_QMP_PLL + 0xd0) +#define QSERDES_COM_DIV_FRAC_START3_MODE0 (QSERDES_QMP_PLL + 0xd4) +#define QSERDES_COM_HSCLK_HS_SWITCH_SEL (QSERDES_QMP_PLL + 0x15c) +#define QSERDES_COM_HSCLK_SEL (QSERDES_QMP_PLL + 0x158) +#define QSERDES_COM_LOCK_CMP1_MODE0 (QSERDES_QMP_PLL + 0xac) +#define QSERDES_COM_LOCK_CMP2_MODE0 (QSERDES_QMP_PLL + 0xb0) +#define QSERDES_COM_PLL_CCTRL_MODE0 (QSERDES_QMP_PLL + 0x84) +#define QSERDES_COM_PLL_IVCO (QSERDES_QMP_PLL + 0x58) +#define QSERDES_COM_PLL_RCTRL_MODE0 (QSERDES_QMP_PLL + 0x7c) +#define QSERDES_COM_SYSCLK_EN_SEL (QSERDES_QMP_PLL + 0x94) +#define QSERDES_COM_VCO_TUNE1_MODE0 (QSERDES_QMP_PLL + 0x110) +#define QSERDES_COM_VCO_TUNE2_MODE0 (QSERDES_QMP_PLL + 0x114) +#define QSERDES_COM_VCO_TUNE_INITVAL2 (QSERDES_QMP_PLL + 0x124) +#define QSERDES_COM_C_READY_STATUS (QSERDES_QMP_PLL + 0x178) +#define QSERDES_COM_CMN_STATUS (QSERDES_QMP_PLL + 0x140) + +#define QSERDES_RX 0x600 +#define QSERDES_RX_UCDR_FO_GAIN (QSERDES_RX + 0x8) +#define QSERDES_RX_UCDR_SO_GAIN (QSERDES_RX + 0x14) +#define QSERDES_RX_UCDR_FASTLOCK_FO_GAIN (QSERDES_RX + 0x30) +#define QSERDES_RX_UCDR_SO_SATURATION_AND_ENABLE (QSERDES_RX + 0x34) +#define QSERDES_RX_UCDR_FASTLOCK_COUNT_LOW (QSERDES_RX + 0x3c) +#define QSERDES_RX_UCDR_FASTLOCK_COUNT_HIGH (QSERDES_RX + 0x40) +#define QSERDES_RX_UCDR_PI_CONTROLS (QSERDES_RX + 0x44) +#define QSERDES_RX_UCDR_PI_CTRL2 (QSERDES_RX + 0x48) +#define QSERDES_RX_RX_TERM_BW (QSERDES_RX + 0x80) +#define QSERDES_RX_VGA_CAL_CNTRL2 (QSERDES_RX + 0xd8) +#define QSERDES_RX_GM_CAL (QSERDES_RX + 0xdc) +#define QSERDES_RX_RX_EQU_ADAPTOR_CNTRL1 (QSERDES_RX + 0xe8) +#define QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2 (QSERDES_RX + 0xec) +#define QSERDES_RX_RX_EQU_ADAPTOR_CNTRL3 (QSERDES_RX + 0xf0) +#define QSERDES_RX_RX_EQU_ADAPTOR_CNTRL4 (QSERDES_RX + 0xf4) +#define QSERDES_RX_RX_IDAC_TSETTLE_LOW (QSERDES_RX + 0xf8) +#define QSERDES_RX_RX_IDAC_TSETTLE_HIGH (QSERDES_RX + 0xfc) +#define QSERDES_RX_RX_IDAC_MEASURE_TIME (QSERDES_RX + 0x100) +#define QSERDES_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1 (QSERDES_RX + 0x110) +#define QSERDES_RX_RX_OFFSET_ADAPTOR_CNTRL2 (QSERDES_RX + 0x114) +#define QSERDES_RX_SIGDET_CNTRL (QSERDES_RX + 0x11c) +#define QSERDES_RX_SIGDET_DEGLITCH_CNTRL (QSERDES_RX + 0x124) +#define QSERDES_RX_RX_BAND (QSERDES_RX + 0x128) +#define QSERDES_RX_RX_MODE_00_LOW (QSERDES_RX + 0x15c) +#define QSERDES_RX_RX_MODE_00_HIGH (QSERDES_RX + 0x160) +#define QSERDES_RX_RX_MODE_00_HIGH2 (QSERDES_RX + 0x164) +#define QSERDES_RX_RX_MODE_00_HIGH3 (QSERDES_RX + 0x168) +#define QSERDES_RX_RX_MODE_00_HIGH4 (QSERDES_RX + 0x16c) +#define QSERDES_RX_RX_MODE_01_LOW (QSERDES_RX + 0x170) +#define QSERDES_RX_RX_MODE_01_HIGH (QSERDES_RX + 0x174) +#define QSERDES_RX_RX_MODE_01_HIGH2 (QSERDES_RX + 0x178) +#define QSERDES_RX_RX_MODE_01_HIGH3 (QSERDES_RX + 0x17c) +#define QSERDES_RX_RX_MODE_01_HIGH4 (QSERDES_RX + 0x180) +#define QSERDES_RX_RX_MODE_10_LOW (QSERDES_RX + 0x184) +#define QSERDES_RX_RX_MODE_10_HIGH (QSERDES_RX + 0x188) +#define QSERDES_RX_RX_MODE_10_HIGH2 (QSERDES_RX + 0x18c) +#define QSERDES_RX_RX_MODE_10_HIGH3 (QSERDES_RX + 0x190) +#define QSERDES_RX_RX_MODE_10_HIGH4 (QSERDES_RX + 0x194) +#define QSERDES_RX_DCC_CTRL1 (QSERDES_RX + 0x1a8) + +#define QSERDES_TX 0x400 +#define QSERDES_TX_TX_BAND (QSERDES_TX + 0x24) +#define QSERDES_TX_SLEW_CNTL (QSERDES_TX + 0x28) +#define QSERDES_TX_RES_CODE_LANE_OFFSET_TX (QSERDES_TX + 0x3c) +#define QSERDES_TX_RES_CODE_LANE_OFFSET_RX (QSERDES_TX + 0x40) +#define QSERDES_TX_LANE_MODE_1 (QSERDES_TX + 0x84) +#define QSERDES_TX_LANE_MODE_3 (QSERDES_TX + 0x8c) +#define QSERDES_TX_RCV_DETECT_LVL_2 (QSERDES_TX + 0xa4) +#define QSERDES_TX_TRAN_DRVR_EMP_EN (QSERDES_TX + 0xc0) + +#define QSERDES_PCS 0xC00 +#define QSERDES_PCS_PHY_START (QSERDES_PCS + 0x0) +#define QSERDES_PCS_POWER_DOWN_CONTROL (QSERDES_PCS + 0x4) +#define QSERDES_PCS_SW_RESET (QSERDES_PCS + 0x8) +#define QSERDES_PCS_LINE_RESET_TIME (QSERDES_PCS + 0xc) +#define QSERDES_PCS_TX_LARGE_AMP_DRV_LVL (QSERDES_PCS + 0x20) +#define QSERDES_PCS_TX_SMALL_AMP_DRV_LVL (QSERDES_PCS + 0x28) +#define QSERDES_PCS_TX_MID_TERM_CTRL1 (QSERDES_PCS + 0xd8) +#define QSERDES_PCS_TX_MID_TERM_CTRL2 (QSERDES_PCS + 0xdc) +#define QSERDES_PCS_SGMII_MISC_CTRL8 (QSERDES_PCS + 0x118) +#define QSERDES_PCS_PCS_READY_STATUS (QSERDES_PCS + 0x94) + +#define QSERDES_COM_C_READY BIT(0) +#define QSERDES_PCS_READY BIT(0) +#define QSERDES_PCS_SGMIIPHY_READY BIT(7) +#define QSERDES_COM_C_PLL_LOCKED BIT(1) + +struct qcom_dwmac_sgmii_phy_data { + struct regmap *regmap; + struct clk *refclk; + int speed; +}; + +static void qcom_dwmac_sgmii_phy_init_1g(struct regmap *regmap) +{ + regmap_write(regmap, QSERDES_PCS_SW_RESET, 0x01); + regmap_write(regmap, QSERDES_PCS_POWER_DOWN_CONTROL, 0x01); + + regmap_write(regmap, QSERDES_COM_PLL_IVCO, 0x0F); + regmap_write(regmap, QSERDES_COM_CP_CTRL_MODE0, 0x06); + regmap_write(regmap, QSERDES_COM_PLL_RCTRL_MODE0, 0x16); + regmap_write(regmap, QSERDES_COM_PLL_CCTRL_MODE0, 0x36); + regmap_write(regmap, QSERDES_COM_SYSCLK_EN_SEL, 0x1A); + regmap_write(regmap, QSERDES_COM_LOCK_CMP1_MODE0, 0x0A); + regmap_write(regmap, QSERDES_COM_LOCK_CMP2_MODE0, 0x1A); + regmap_write(regmap, QSERDES_COM_DEC_START_MODE0, 0x82); + regmap_write(regmap, QSERDES_COM_DIV_FRAC_START1_MODE0, 0x55); + regmap_write(regmap, QSERDES_COM_DIV_FRAC_START2_MODE0, 0x55); + regmap_write(regmap, QSERDES_COM_DIV_FRAC_START3_MODE0, 0x03); + regmap_write(regmap, QSERDES_COM_VCO_TUNE1_MODE0, 0x24); + + regmap_write(regmap, QSERDES_COM_VCO_TUNE2_MODE0, 0x02); + regmap_write(regmap, QSERDES_COM_VCO_TUNE_INITVAL2, 0x00); + regmap_write(regmap, QSERDES_COM_HSCLK_SEL, 0x04); + regmap_write(regmap, QSERDES_COM_HSCLK_HS_SWITCH_SEL, 0x00); + regmap_write(regmap, QSERDES_COM_CORECLK_DIV_MODE0, 0x0A); + regmap_write(regmap, QSERDES_COM_CORE_CLK_EN, 0x00); + regmap_write(regmap, QSERDES_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0xB9); + regmap_write(regmap, QSERDES_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x1E); + regmap_write(regmap, QSERDES_COM_BIN_VCOCAL_HSCLK_SEL, 0x11); + + regmap_write(regmap, QSERDES_TX_TX_BAND, 0x05); + regmap_write(regmap, QSERDES_TX_SLEW_CNTL, 0x0A); + regmap_write(regmap, QSERDES_TX_RES_CODE_LANE_OFFSET_TX, 0x09); + regmap_write(regmap, QSERDES_TX_RES_CODE_LANE_OFFSET_RX, 0x09); + regmap_write(regmap, QSERDES_TX_LANE_MODE_1, 0x05); + regmap_write(regmap, QSERDES_TX_LANE_MODE_3, 0x00); + regmap_write(regmap, QSERDES_TX_RCV_DETECT_LVL_2, 0x12); + regmap_write(regmap, QSERDES_TX_TRAN_DRVR_EMP_EN, 0x0C); + + regmap_write(regmap, QSERDES_RX_UCDR_FO_GAIN, 0x0A); + regmap_write(regmap, QSERDES_RX_UCDR_SO_GAIN, 0x06); + regmap_write(regmap, QSERDES_RX_UCDR_FASTLOCK_FO_GAIN, 0x0A); + regmap_write(regmap, QSERDES_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x7F); + regmap_write(regmap, QSERDES_RX_UCDR_FASTLOCK_COUNT_LOW, 0x00); + regmap_write(regmap, QSERDES_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x01); + regmap_write(regmap, QSERDES_RX_UCDR_PI_CONTROLS, 0x81); + regmap_write(regmap, QSERDES_RX_UCDR_PI_CTRL2, 0x80); + regmap_write(regmap, QSERDES_RX_RX_TERM_BW, 0x04); + regmap_write(regmap, QSERDES_RX_VGA_CAL_CNTRL2, 0x08); + regmap_write(regmap, QSERDES_RX_GM_CAL, 0x0F); + regmap_write(regmap, QSERDES_RX_RX_EQU_ADAPTOR_CNTRL1, 0x04); + regmap_write(regmap, QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2, 0x00); + regmap_write(regmap, QSERDES_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4A); + regmap_write(regmap, QSERDES_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0A); + regmap_write(regmap, QSERDES_RX_RX_IDAC_TSETTLE_LOW, 0x80); + regmap_write(regmap, QSERDES_RX_RX_IDAC_TSETTLE_HIGH, 0x01); + regmap_write(regmap, QSERDES_RX_RX_IDAC_MEASURE_TIME, 0x20); + regmap_write(regmap, QSERDES_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x17); + regmap_write(regmap, QSERDES_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x00); + regmap_write(regmap, QSERDES_RX_SIGDET_CNTRL, 0x0F); + regmap_write(regmap, QSERDES_RX_SIGDET_DEGLITCH_CNTRL, 0x1E); + regmap_write(regmap, QSERDES_RX_RX_BAND, 0x05); + regmap_write(regmap, QSERDES_RX_RX_MODE_00_LOW, 0xE0); + regmap_write(regmap, QSERDES_RX_RX_MODE_00_HIGH, 0xC8); + regmap_write(regmap, QSERDES_RX_RX_MODE_00_HIGH2, 0xC8); + regmap_write(regmap, QSERDES_RX_RX_MODE_00_HIGH3, 0x09); + regmap_write(regmap, QSERDES_RX_RX_MODE_00_HIGH4, 0xB1); + regmap_write(regmap, QSERDES_RX_RX_MODE_01_LOW, 0xE0); + regmap_write(regmap, QSERDES_RX_RX_MODE_01_HIGH, 0xC8); + regmap_write(regmap, QSERDES_RX_RX_MODE_01_HIGH2, 0xC8); + regmap_write(regmap, QSERDES_RX_RX_MODE_01_HIGH3, 0x09); + regmap_write(regmap, QSERDES_RX_RX_MODE_01_HIGH4, 0xB1); + regmap_write(regmap, QSERDES_RX_RX_MODE_10_LOW, 0xE0); + regmap_write(regmap, QSERDES_RX_RX_MODE_10_HIGH, 0xC8); + regmap_write(regmap, QSERDES_RX_RX_MODE_10_HIGH2, 0xC8); + regmap_write(regmap, QSERDES_RX_RX_MODE_10_HIGH3, 0x3B); + regmap_write(regmap, QSERDES_RX_RX_MODE_10_HIGH4, 0xB7); + regmap_write(regmap, QSERDES_RX_DCC_CTRL1, 0x0C); + + regmap_write(regmap, QSERDES_PCS_LINE_RESET_TIME, 0x0C); + regmap_write(regmap, QSERDES_PCS_TX_LARGE_AMP_DRV_LVL, 0x1F); + regmap_write(regmap, QSERDES_PCS_TX_SMALL_AMP_DRV_LVL, 0x03); + regmap_write(regmap, QSERDES_PCS_TX_MID_TERM_CTRL1, 0x83); + regmap_write(regmap, QSERDES_PCS_TX_MID_TERM_CTRL2, 0x08); + regmap_write(regmap, QSERDES_PCS_SGMII_MISC_CTRL8, 0x0C); + regmap_write(regmap, QSERDES_PCS_SW_RESET, 0x00); + + regmap_write(regmap, QSERDES_PCS_PHY_START, 0x01); +} + +static void qcom_dwmac_sgmii_phy_init_2p5g(struct regmap *regmap) +{ + regmap_write(regmap, QSERDES_PCS_SW_RESET, 0x01); + regmap_write(regmap, QSERDES_PCS_POWER_DOWN_CONTROL, 0x01); + + regmap_write(regmap, QSERDES_COM_PLL_IVCO, 0x0F); + regmap_write(regmap, QSERDES_COM_CP_CTRL_MODE0, 0x06); + regmap_write(regmap, QSERDES_COM_PLL_RCTRL_MODE0, 0x16); + regmap_write(regmap, QSERDES_COM_PLL_CCTRL_MODE0, 0x36); + regmap_write(regmap, QSERDES_COM_SYSCLK_EN_SEL, 0x1A); + regmap_write(regmap, QSERDES_COM_LOCK_CMP1_MODE0, 0x1A); + regmap_write(regmap, QSERDES_COM_LOCK_CMP2_MODE0, 0x41); + regmap_write(regmap, QSERDES_COM_DEC_START_MODE0, 0x7A); + regmap_write(regmap, QSERDES_COM_DIV_FRAC_START1_MODE0, 0x00); + regmap_write(regmap, QSERDES_COM_DIV_FRAC_START2_MODE0, 0x20); + regmap_write(regmap, QSERDES_COM_DIV_FRAC_START3_MODE0, 0x01); + regmap_write(regmap, QSERDES_COM_VCO_TUNE1_MODE0, 0xA1); + + regmap_write(regmap, QSERDES_COM_VCO_TUNE2_MODE0, 0x02); + regmap_write(regmap, QSERDES_COM_VCO_TUNE_INITVAL2, 0x00); + regmap_write(regmap, QSERDES_COM_HSCLK_SEL, 0x03); + regmap_write(regmap, QSERDES_COM_HSCLK_HS_SWITCH_SEL, 0x00); + regmap_write(regmap, QSERDES_COM_CORECLK_DIV_MODE0, 0x05); + regmap_write(regmap, QSERDES_COM_CORE_CLK_EN, 0x00); + regmap_write(regmap, QSERDES_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0xCD); + regmap_write(regmap, QSERDES_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x1C); + regmap_write(regmap, QSERDES_COM_BIN_VCOCAL_HSCLK_SEL, 0x11); + + regmap_write(regmap, QSERDES_TX_TX_BAND, 0x04); + regmap_write(regmap, QSERDES_TX_SLEW_CNTL, 0x0A); + regmap_write(regmap, QSERDES_TX_RES_CODE_LANE_OFFSET_TX, 0x09); + regmap_write(regmap, QSERDES_TX_RES_CODE_LANE_OFFSET_RX, 0x02); + regmap_write(regmap, QSERDES_TX_LANE_MODE_1, 0x05); + regmap_write(regmap, QSERDES_TX_LANE_MODE_3, 0x00); + regmap_write(regmap, QSERDES_TX_RCV_DETECT_LVL_2, 0x12); + regmap_write(regmap, QSERDES_TX_TRAN_DRVR_EMP_EN, 0x0C); + + regmap_write(regmap, QSERDES_RX_UCDR_FO_GAIN, 0x0A); + regmap_write(regmap, QSERDES_RX_UCDR_SO_GAIN, 0x06); + regmap_write(regmap, QSERDES_RX_UCDR_FASTLOCK_FO_GAIN, 0x0A); + regmap_write(regmap, QSERDES_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x7F); + regmap_write(regmap, QSERDES_RX_UCDR_FASTLOCK_COUNT_LOW, 0x00); + regmap_write(regmap, QSERDES_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x01); + regmap_write(regmap, QSERDES_RX_UCDR_PI_CONTROLS, 0x81); + regmap_write(regmap, QSERDES_RX_UCDR_PI_CTRL2, 0x80); + regmap_write(regmap, QSERDES_RX_RX_TERM_BW, 0x00); + regmap_write(regmap, QSERDES_RX_VGA_CAL_CNTRL2, 0x08); + regmap_write(regmap, QSERDES_RX_GM_CAL, 0x0F); + regmap_write(regmap, QSERDES_RX_RX_EQU_ADAPTOR_CNTRL1, 0x04); + regmap_write(regmap, QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2, 0x00); + regmap_write(regmap, QSERDES_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4A); + regmap_write(regmap, QSERDES_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0A); + regmap_write(regmap, QSERDES_RX_RX_IDAC_TSETTLE_LOW, 0x80); + regmap_write(regmap, QSERDES_RX_RX_IDAC_TSETTLE_HIGH, 0x01); + regmap_write(regmap, QSERDES_RX_RX_IDAC_MEASURE_TIME, 0x20); + regmap_write(regmap, QSERDES_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x17); + regmap_write(regmap, QSERDES_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x00); + regmap_write(regmap, QSERDES_RX_SIGDET_CNTRL, 0x0F); + regmap_write(regmap, QSERDES_RX_SIGDET_DEGLITCH_CNTRL, 0x1E); + regmap_write(regmap, QSERDES_RX_RX_BAND, 0x18); + regmap_write(regmap, QSERDES_RX_RX_MODE_00_LOW, 0x18); + regmap_write(regmap, QSERDES_RX_RX_MODE_00_HIGH, 0xC8); + regmap_write(regmap, QSERDES_RX_RX_MODE_00_HIGH2, 0xC8); + regmap_write(regmap, QSERDES_RX_RX_MODE_00_HIGH3, 0x0C); + regmap_write(regmap, QSERDES_RX_RX_MODE_00_HIGH4, 0xB8); + regmap_write(regmap, QSERDES_RX_RX_MODE_01_LOW, 0xE0); + regmap_write(regmap, QSERDES_RX_RX_MODE_01_HIGH, 0xC8); + regmap_write(regmap, QSERDES_RX_RX_MODE_01_HIGH2, 0xC8); + regmap_write(regmap, QSERDES_RX_RX_MODE_01_HIGH3, 0x09); + regmap_write(regmap, QSERDES_RX_RX_MODE_01_HIGH4, 0xB1); + regmap_write(regmap, QSERDES_RX_RX_MODE_10_LOW, 0xE0); + regmap_write(regmap, QSERDES_RX_RX_MODE_10_HIGH, 0xC8); + regmap_write(regmap, QSERDES_RX_RX_MODE_10_HIGH2, 0xC8); + regmap_write(regmap, QSERDES_RX_RX_MODE_10_HIGH3, 0x3B); + regmap_write(regmap, QSERDES_RX_RX_MODE_10_HIGH4, 0xB7); + regmap_write(regmap, QSERDES_RX_DCC_CTRL1, 0x0C); + + regmap_write(regmap, QSERDES_PCS_LINE_RESET_TIME, 0x0C); + regmap_write(regmap, QSERDES_PCS_TX_LARGE_AMP_DRV_LVL, 0x1F); + regmap_write(regmap, QSERDES_PCS_TX_SMALL_AMP_DRV_LVL, 0x03); + regmap_write(regmap, QSERDES_PCS_TX_MID_TERM_CTRL1, 0x83); + regmap_write(regmap, QSERDES_PCS_TX_MID_TERM_CTRL2, 0x08); + regmap_write(regmap, QSERDES_PCS_SGMII_MISC_CTRL8, 0x8C); + regmap_write(regmap, QSERDES_PCS_SW_RESET, 0x00); + + regmap_write(regmap, QSERDES_PCS_PHY_START, 0x01); +} + +static inline int +qcom_dwmac_sgmii_phy_poll_status(struct regmap *regmap, unsigned int reg, + unsigned int bit) +{ + unsigned int val; + + return regmap_read_poll_timeout(regmap, reg, val, + val & bit, 1500, 750000); +} + +static int qcom_dwmac_sgmii_phy_calibrate(struct phy *phy) +{ + struct qcom_dwmac_sgmii_phy_data *data = phy_get_drvdata(phy); + struct device *dev = phy->dev.parent; + + switch (data->speed) { + case SPEED_10: + case SPEED_100: + case SPEED_1000: + qcom_dwmac_sgmii_phy_init_1g(data->regmap); + break; + case SPEED_2500: + qcom_dwmac_sgmii_phy_init_2p5g(data->regmap); + break; + } + + if (qcom_dwmac_sgmii_phy_poll_status(data->regmap, + QSERDES_COM_C_READY_STATUS, + QSERDES_COM_C_READY)) { + dev_err(dev, "QSERDES_COM_C_READY_STATUS timed-out"); + return -ETIMEDOUT; + } + + if (qcom_dwmac_sgmii_phy_poll_status(data->regmap, + QSERDES_PCS_PCS_READY_STATUS, + QSERDES_PCS_READY)) { + dev_err(dev, "PCS_READY timed-out"); + return -ETIMEDOUT; + } + + if (qcom_dwmac_sgmii_phy_poll_status(data->regmap, + QSERDES_PCS_PCS_READY_STATUS, + QSERDES_PCS_SGMIIPHY_READY)) { + dev_err(dev, "SGMIIPHY_READY timed-out"); + return -ETIMEDOUT; + } + + if (qcom_dwmac_sgmii_phy_poll_status(data->regmap, + QSERDES_COM_CMN_STATUS, + QSERDES_COM_C_PLL_LOCKED)) { + dev_err(dev, "PLL Lock Status timed-out"); + return -ETIMEDOUT; + } + + return 0; +} + +static int qcom_dwmac_sgmii_phy_power_on(struct phy *phy) +{ + struct qcom_dwmac_sgmii_phy_data *data = phy_get_drvdata(phy); + + return clk_prepare_enable(data->refclk); +} + +static int qcom_dwmac_sgmii_phy_power_off(struct phy *phy) +{ + struct qcom_dwmac_sgmii_phy_data *data = phy_get_drvdata(phy); + + regmap_write(data->regmap, QSERDES_PCS_TX_MID_TERM_CTRL2, 0x08); + regmap_write(data->regmap, QSERDES_PCS_SW_RESET, 0x01); + udelay(100); + regmap_write(data->regmap, QSERDES_PCS_SW_RESET, 0x00); + regmap_write(data->regmap, QSERDES_PCS_PHY_START, 0x01); + + clk_disable_unprepare(data->refclk); + + return 0; +} + +static int qcom_dwmac_sgmii_phy_set_speed(struct phy *phy, int speed) +{ + struct qcom_dwmac_sgmii_phy_data *data = phy_get_drvdata(phy); + + if (speed != data->speed) + data->speed = speed; + + return qcom_dwmac_sgmii_phy_calibrate(phy); +} + +static const struct phy_ops qcom_dwmac_sgmii_phy_ops = { + .power_on = qcom_dwmac_sgmii_phy_power_on, + .power_off = qcom_dwmac_sgmii_phy_power_off, + .set_speed = qcom_dwmac_sgmii_phy_set_speed, + .calibrate = qcom_dwmac_sgmii_phy_calibrate, + .owner = THIS_MODULE, +}; + +static const struct regmap_config qcom_dwmac_sgmii_phy_regmap_cfg = { + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, + .use_relaxed_mmio = true, + .disable_locking = true, +}; + +static int qcom_dwmac_sgmii_phy_probe(struct platform_device *pdev) +{ + struct qcom_dwmac_sgmii_phy_data *data; + struct device *dev = &pdev->dev; + struct phy_provider *provider; + void __iomem *base; + struct phy *phy; + + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + data->speed = SPEED_10; + + base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(base)) + return PTR_ERR(base); + + data->regmap = devm_regmap_init_mmio(dev, base, + &qcom_dwmac_sgmii_phy_regmap_cfg); + if (IS_ERR(data->regmap)) + return PTR_ERR(data->regmap); + + phy = devm_phy_create(dev, NULL, &qcom_dwmac_sgmii_phy_ops); + if (IS_ERR(phy)) + return PTR_ERR(phy); + + data->refclk = devm_clk_get(dev, "sgmi_ref"); + if (IS_ERR(data->refclk)) + return PTR_ERR(data->refclk); + + provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); + if (IS_ERR(provider)) + return PTR_ERR(provider); + + phy_set_drvdata(phy, data); + + return 0; +} + +static const struct of_device_id qcom_dwmac_sgmii_phy_of_match[] = { + { .compatible = "qcom,sa8775p-dwmac-sgmii-phy" }, + { }, +}; +MODULE_DEVICE_TABLE(of, qcom_dwmac_sgmii_phy_of_match); + +static struct platform_driver qcom_dwmac_sgmii_phy_driver = { + .probe = qcom_dwmac_sgmii_phy_probe, + .driver = { + .name = "qcom-dwmac-sgmii-phy", + .of_match_table = qcom_dwmac_sgmii_phy_of_match, + } +}; + +module_platform_driver(qcom_dwmac_sgmii_phy_driver); + +MODULE_DESCRIPTION("Qualcomm DWMAC SGMII PHY driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/phy/samsung/Kconfig b/drivers/phy/samsung/Kconfig index 3ccaabf2850a8930998a785b08396c63eb81aaff..f10afa3d7ff5176fce5cf68bd91f0d1a2c289679 100644 --- a/drivers/phy/samsung/Kconfig +++ b/drivers/phy/samsung/Kconfig @@ -59,7 +59,7 @@ config PHY_EXYNOS4210_USB2 config PHY_EXYNOS4X12_USB2 bool depends on PHY_SAMSUNG_USB2 - default SOC_EXYNOS3250 || SOC_EXYNOS4412 + default SOC_EXYNOS3250 || SOC_EXYNOS4212 || SOC_EXYNOS4412 config PHY_EXYNOS5250_USB2 bool diff --git a/drivers/phy/tegra/xusb.c b/drivers/phy/tegra/xusb.c index b55d4e9f42b5cdbe248895c974014aeff9fefb3f..a296b87dced18f626a417b2c2584504e28f11a88 100644 --- a/drivers/phy/tegra/xusb.c +++ b/drivers/phy/tegra/xusb.c @@ -568,6 +568,7 @@ static void tegra_xusb_port_unregister(struct tegra_xusb_port *port) usb_role_switch_unregister(port->usb_role_sw); cancel_work_sync(&port->usb_phy_work); usb_remove_phy(&port->usb_phy); + port->usb_phy.dev->driver = NULL; } if (port->ops->remove) @@ -675,6 +676,9 @@ static int tegra_xusb_setup_usb_role_switch(struct tegra_xusb_port *port) port->dev.driver = devm_kzalloc(&port->dev, sizeof(struct device_driver), GFP_KERNEL); + if (!port->dev.driver) + return -ENOMEM; + port->dev.driver->owner = THIS_MODULE; port->usb_role_sw = usb_role_switch_register(&port->dev, diff --git a/drivers/phy/ti/phy-am654-serdes.c b/drivers/phy/ti/phy-am654-serdes.c index 4ed2d951d3df90eb72eff12b081aec7cfd07e42d..3f1d43e8b7ad1fbcfd3399db0150c59eb6e96ad4 100644 --- a/drivers/phy/ti/phy-am654-serdes.c +++ b/drivers/phy/ti/phy-am654-serdes.c @@ -634,6 +634,7 @@ static int serdes_am654_clk_mux_set_parent(struct clk_hw *hw, u8 index) } static const struct clk_ops serdes_am654_clk_mux_ops = { + .determine_rate = __clk_mux_determine_rate, .set_parent = serdes_am654_clk_mux_set_parent, .get_parent = serdes_am654_clk_mux_get_parent, }; diff --git a/drivers/phy/ti/phy-gmii-sel.c b/drivers/phy/ti/phy-gmii-sel.c index 8c667819c39a10b0fe3186f7f65197ffb4b21f2f..6286cf25a426496b7ec215b300a43c75bbf168ac 100644 --- a/drivers/phy/ti/phy-gmii-sel.c +++ b/drivers/phy/ti/phy-gmii-sel.c @@ -23,7 +23,9 @@ #define AM33XX_GMII_SEL_MODE_RGMII 2 /* J72xx SoC specific definitions for the CONTROL port */ +#define J72XX_GMII_SEL_MODE_SGMII 3 #define J72XX_GMII_SEL_MODE_QSGMII 4 +#define J72XX_GMII_SEL_MODE_USXGMII 5 #define J72XX_GMII_SEL_MODE_QSGMII_SUB 6 #define PHY_GMII_PORT(n) BIT((n) - 1) @@ -106,6 +108,20 @@ static int phy_gmii_sel_mode(struct phy *phy, enum phy_mode mode, int submode) gmii_sel_mode = J72XX_GMII_SEL_MODE_QSGMII_SUB; break; + case PHY_INTERFACE_MODE_SGMII: + if (!(soc_data->extra_modes & BIT(PHY_INTERFACE_MODE_SGMII))) + goto unsupported; + else + gmii_sel_mode = J72XX_GMII_SEL_MODE_SGMII; + break; + + case PHY_INTERFACE_MODE_USXGMII: + if (!(soc_data->extra_modes & BIT(PHY_INTERFACE_MODE_USXGMII))) + goto unsupported; + else + gmii_sel_mode = J72XX_GMII_SEL_MODE_USXGMII; + break; + default: goto unsupported; } @@ -213,7 +229,7 @@ static const struct phy_gmii_sel_soc_data phy_gmii_sel_cpsw5g_soc_j7200 = { .use_of_data = true, .regfields = phy_gmii_sel_fields_am654, - .extra_modes = BIT(PHY_INTERFACE_MODE_QSGMII), + .extra_modes = BIT(PHY_INTERFACE_MODE_QSGMII) | BIT(PHY_INTERFACE_MODE_SGMII), .num_ports = 4, .num_qsgmii_main_ports = 1, }; @@ -222,7 +238,17 @@ static const struct phy_gmii_sel_soc_data phy_gmii_sel_cpsw9g_soc_j721e = { .use_of_data = true, .regfields = phy_gmii_sel_fields_am654, - .extra_modes = BIT(PHY_INTERFACE_MODE_QSGMII), + .extra_modes = BIT(PHY_INTERFACE_MODE_QSGMII) | BIT(PHY_INTERFACE_MODE_SGMII), + .num_ports = 8, + .num_qsgmii_main_ports = 2, +}; + +static const +struct phy_gmii_sel_soc_data phy_gmii_sel_cpsw9g_soc_j784s4 = { + .use_of_data = true, + .regfields = phy_gmii_sel_fields_am654, + .extra_modes = BIT(PHY_INTERFACE_MODE_QSGMII) | + BIT(PHY_INTERFACE_MODE_USXGMII), .num_ports = 8, .num_qsgmii_main_ports = 2, }; @@ -256,6 +282,10 @@ static const struct of_device_id phy_gmii_sel_id_table[] = { .compatible = "ti,j721e-cpsw9g-phy-gmii-sel", .data = &phy_gmii_sel_cpsw9g_soc_j721e, }, + { + .compatible = "ti,j784s4-cpsw9g-phy-gmii-sel", + .data = &phy_gmii_sel_cpsw9g_soc_j784s4, + }, {} }; MODULE_DEVICE_TABLE(of, phy_gmii_sel_id_table); diff --git a/drivers/phy/ti/phy-j721e-wiz.c b/drivers/phy/ti/phy-j721e-wiz.c index d91923799df25496dcf1928be5ddba9218488f26..fc3cd98c60ff42e1a0aa30698e68319b49009063 100644 --- a/drivers/phy/ti/phy-j721e-wiz.c +++ b/drivers/phy/ti/phy-j721e-wiz.c @@ -801,6 +801,7 @@ static int wiz_clk_mux_set_parent(struct clk_hw *hw, u8 index) } static const struct clk_ops wiz_clk_mux_ops = { + .determine_rate = __clk_mux_determine_rate, .set_parent = wiz_clk_mux_set_parent, .get_parent = wiz_clk_mux_get_parent, }; diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index 5787c579dcf672c3072f11791b0ad3e172edb73d..57d57af1f624ecdec18a80ea0d66b5ee4b133592 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -407,7 +407,7 @@ config PINCTRL_PISTACHIO config PINCTRL_RK805 tristate "Pinctrl and GPIO driver for RK805 PMIC" - depends on MFD_RK808 + depends on MFD_RK8XX select GPIOLIB select PINMUX select GENERIC_PINCONF @@ -510,7 +510,6 @@ config PINCTRL_MLXBF3 select PINMUX select GPIOLIB select GPIOLIB_IRQCHIP - select GPIO_MLXBF3 help Say Y to select the pinctrl driver for BlueField-3 SoCs. This pin controller allows selecting the mux function for diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile index e196c6e324adc8956741f3da0f6cbf2e2b96512f..482b391b5debb6e800a55e0f64f7e3b1ba3be577 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile @@ -66,7 +66,7 @@ obj-y += nomadik/ obj-y += nuvoton/ obj-y += nxp/ obj-$(CONFIG_PINCTRL_PXA) += pxa/ -obj-$(CONFIG_ARCH_QCOM) += qcom/ +obj-y += qcom/ obj-$(CONFIG_PINCTRL_RENESAS) += renesas/ obj-$(CONFIG_PINCTRL_SAMSUNG) += samsung/ obj-$(CONFIG_PINCTRL_SPEAR) += spear/ diff --git a/drivers/pinctrl/bcm/pinctrl-bcm2835.c b/drivers/pinctrl/bcm/pinctrl-bcm2835.c index 7435173e10f43105078bd07a8a1529359dbd98dd..1489191a213fed7d27fed523ec1fc44bf28d6f5c 100644 --- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c +++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c @@ -376,10 +376,8 @@ static int bcm2835_add_pin_ranges_fallback(struct gpio_chip *gc) if (!pctldev) return 0; - gpiochip_add_pin_range(gc, pinctrl_dev_get_devname(pctldev), 0, 0, - gc->ngpio); - - return 0; + return gpiochip_add_pin_range(gc, pinctrl_dev_get_devname(pctldev), 0, 0, + gc->ngpio); } static const struct gpio_chip bcm2835_gpio_chip = { diff --git a/drivers/pinctrl/freescale/pinctrl-scu.c b/drivers/pinctrl/freescale/pinctrl-scu.c index ea261b6e74581fc8e406a8e9452c437baa302f95..3b252d684d723af99ed5deb54a198b9b64457f57 100644 --- a/drivers/pinctrl/freescale/pinctrl-scu.c +++ b/drivers/pinctrl/freescale/pinctrl-scu.c @@ -90,7 +90,7 @@ int imx_pinconf_set_scu(struct pinctrl_dev *pctldev, unsigned pin_id, struct imx_sc_msg_req_pad_set msg; struct imx_sc_rpc_msg *hdr = &msg.hdr; unsigned int mux = configs[0]; - unsigned int conf = configs[1]; + unsigned int conf; unsigned int val; int ret; @@ -115,6 +115,7 @@ int imx_pinconf_set_scu(struct pinctrl_dev *pctldev, unsigned pin_id, * Set mux and conf together in one IPC call */ WARN_ON(num_configs != 2); + conf = configs[1]; val = conf | BM_PAD_CTL_IFMUX_ENABLE | BM_PAD_CTL_GP_ENABLE; val |= mux << BP_PAD_CTL_IFMUX; diff --git a/drivers/pinctrl/intel/pinctrl-baytrail.c b/drivers/pinctrl/intel/pinctrl-baytrail.c index 770a2723ef81739befbc3e75c9533d6dd4900df7..27aef62fc7c0473d01b557dab084c1e05ab69484 100644 --- a/drivers/pinctrl/intel/pinctrl-baytrail.c +++ b/drivers/pinctrl/intel/pinctrl-baytrail.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -52,10 +53,9 @@ #define BYT_PULL_STR_10K (1 << BYT_PULL_STR_SHIFT) #define BYT_PULL_STR_20K (2 << BYT_PULL_STR_SHIFT) #define BYT_PULL_STR_40K (3 << BYT_PULL_STR_SHIFT) -#define BYT_PULL_ASSIGN_SHIFT 7 #define BYT_PULL_ASSIGN_MASK GENMASK(8, 7) -#define BYT_PULL_ASSIGN_UP (1 << BYT_PULL_ASSIGN_SHIFT) -#define BYT_PULL_ASSIGN_DOWN (2 << BYT_PULL_ASSIGN_SHIFT) +#define BYT_PULL_ASSIGN_DOWN BIT(8) +#define BYT_PULL_ASSIGN_UP BIT(7) #define BYT_PIN_MUX GENMASK(2, 0) /* BYT_VAL_REG register bits */ @@ -668,8 +668,7 @@ static void byt_set_group_simple_mux(struct intel_pinctrl *vg, padcfg0 = byt_gpio_reg(vg, group.grp.pins[i], BYT_CONF0_REG); if (!padcfg0) { - dev_warn(vg->dev, - "Group %s, pin %i not muxed (no padcfg0)\n", + dev_warn(vg->dev, "Group %s, pin %i not muxed (can't retrieve CONF0)\n", group.grp.name, i); continue; } @@ -698,8 +697,7 @@ static void byt_set_group_mixed_mux(struct intel_pinctrl *vg, padcfg0 = byt_gpio_reg(vg, group.grp.pins[i], BYT_CONF0_REG); if (!padcfg0) { - dev_warn(vg->dev, - "Group %s, pin %i not muxed (no padcfg0)\n", + dev_warn(vg->dev, "Group %s, pin %i not muxed (can't retrieve CONF0)\n", group.grp.name, i); continue; } @@ -755,9 +753,7 @@ static void byt_gpio_clear_triggering(struct intel_pinctrl *vg, unsigned int off value = readl(reg); /* Do not clear direct-irq enabled IRQs (from gpio_disable_free) */ - if (value & BYT_DIRECT_IRQ_EN) - /* nothing to do */ ; - else + if (!(value & BYT_DIRECT_IRQ_EN)) value &= ~(BYT_TRIG_POS | BYT_TRIG_NEG | BYT_TRIG_LVL); writel(value, reg); @@ -791,7 +787,7 @@ static int byt_gpio_request_enable(struct pinctrl_dev *pctl_dev, value |= gpio_mux; writel(value, reg); - dev_warn(vg->dev, FW_BUG "pin %u forcibly re-configured as GPIO\n", offset); + dev_warn(vg->dev, FW_BUG "Pin %i: forcibly re-configured as GPIO\n", offset); } raw_spin_unlock_irqrestore(&byt_lock, flags); @@ -823,7 +819,9 @@ static void byt_gpio_direct_irq_check(struct intel_pinctrl *vg, * themselves in the foot. */ if (readl(conf_reg) & BYT_DIRECT_IRQ_EN) - dev_info_once(vg->dev, "Potential Error: Setting GPIO with direct_irq_en to output"); + dev_info_once(vg->dev, + "Potential Error: Pin %i: forcibly set GPIO with DIRECT_IRQ_EN to output\n", + offset); } static int byt_gpio_set_direction(struct pinctrl_dev *pctl_dev, @@ -1026,9 +1024,7 @@ static int byt_pin_config_set(struct pinctrl_dev *pctl_dev, if (val & BYT_INPUT_EN) { val &= ~BYT_INPUT_EN; writel(val, val_reg); - dev_warn(vg->dev, - "pin %u forcibly set to input mode\n", - offset); + dev_warn(vg->dev, "Pin %i: forcibly set to input mode\n", offset); } conf &= ~BYT_PULL_ASSIGN_MASK; @@ -1048,9 +1044,7 @@ static int byt_pin_config_set(struct pinctrl_dev *pctl_dev, if (val & BYT_INPUT_EN) { val &= ~BYT_INPUT_EN; writel(val, val_reg); - dev_warn(vg->dev, - "pin %u forcibly set to input mode\n", - offset); + dev_warn(vg->dev, "Pin %i: forcibly set to input mode\n", offset); } conf &= ~BYT_PULL_ASSIGN_MASK; @@ -1245,39 +1239,35 @@ static void byt_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) for (i = 0; i < vg->soc->npins; i++) { const struct intel_community *comm; + void __iomem *conf_reg, *val_reg; const char *pull_str = NULL; const char *pull = NULL; - void __iomem *reg; unsigned long flags; const char *label; unsigned int pin; - raw_spin_lock_irqsave(&byt_lock, flags); pin = vg->soc->pins[i].number; - reg = byt_gpio_reg(vg, pin, BYT_CONF0_REG); - if (!reg) { - seq_printf(s, - "Could not retrieve pin %i conf0 reg\n", - pin); - raw_spin_unlock_irqrestore(&byt_lock, flags); + + conf_reg = byt_gpio_reg(vg, pin, BYT_CONF0_REG); + if (!conf_reg) { + seq_printf(s, "Pin %i: can't retrieve CONF0\n", pin); continue; } - conf0 = readl(reg); - reg = byt_gpio_reg(vg, pin, BYT_VAL_REG); - if (!reg) { - seq_printf(s, - "Could not retrieve pin %i val reg\n", pin); - raw_spin_unlock_irqrestore(&byt_lock, flags); + val_reg = byt_gpio_reg(vg, pin, BYT_VAL_REG); + if (!val_reg) { + seq_printf(s, "Pin %i: can't retrieve VAL\n", pin); continue; } - val = readl(reg); + + raw_spin_lock_irqsave(&byt_lock, flags); + conf0 = readl(conf_reg); + val = readl(val_reg); raw_spin_unlock_irqrestore(&byt_lock, flags); comm = byt_get_community(vg, pin); if (!comm) { - seq_printf(s, - "Could not get community for pin %i\n", pin); + seq_printf(s, "Pin %i: can't retrieve community\n", pin); continue; } label = gpiochip_is_requested(chip, i); @@ -1314,7 +1304,7 @@ static void byt_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) label, val & BYT_INPUT_EN ? " " : "in", val & BYT_OUTPUT_EN ? " " : "out", - val & BYT_LEVEL ? "hi" : "lo", + str_hi_lo(val & BYT_LEVEL), comm->pad_map[i], comm->pad_map[i] * 16, conf0 & 0x7, conf0 & BYT_TRIG_NEG ? " fall" : " ", @@ -1429,7 +1419,7 @@ static int byt_irq_type(struct irq_data *d, unsigned int type) value = readl(reg); WARN(value & BYT_DIRECT_IRQ_EN, - "Bad pad config for io mode, force direct_irq_en bit clearing"); + "Bad pad config for IO mode, force DIRECT_IRQ_EN bit clearing"); /* For level trigges the BYT_TRIG_POS and BYT_TRIG_NEG bits * are used to indicate high and low level triggering @@ -1476,9 +1466,7 @@ static void byt_gpio_irq_handler(struct irq_desc *desc) reg = byt_gpio_reg(vg, base, BYT_INT_STAT_REG); if (!reg) { - dev_warn(vg->dev, - "Pin %i: could not retrieve interrupt status register\n", - base); + dev_warn(vg->dev, "Pin %i: can't retrieve INT_STAT%u\n", base / 32, base); continue; } @@ -1501,7 +1489,7 @@ static bool byt_direct_irq_sanity_check(struct intel_pinctrl *vg, int pin, u32 c sizeof(direct_irq_mux)); match = memchr(direct_irq_mux, pin, sizeof(direct_irq_mux)); if (!match) { - dev_warn(vg->dev, FW_BUG "pin %i: direct_irq_en set but no IRQ assigned, clearing\n", pin); + dev_warn(vg->dev, FW_BUG "Pin %i: DIRECT_IRQ_EN set but no IRQ assigned, clearing\n", pin); return false; } @@ -1528,7 +1516,8 @@ static bool byt_direct_irq_sanity_check(struct intel_pinctrl *vg, int pin, u32 c trig = conf0 & BYT_TRIG_MASK; if (trig != (BYT_TRIG_POS | BYT_TRIG_LVL) && trig != (BYT_TRIG_NEG | BYT_TRIG_LVL)) { - dev_warn(vg->dev, FW_BUG "pin %i: direct_irq_en set without trigger (conf0: %xh), clearing\n", + dev_warn(vg->dev, + FW_BUG "Pin %i: DIRECT_IRQ_EN set without trigger (CONF0: %#08x), clearing\n", pin, conf0); return false; } @@ -1555,9 +1544,7 @@ static void byt_init_irq_valid_mask(struct gpio_chip *chip, reg = byt_gpio_reg(vg, pin, BYT_CONF0_REG); if (!reg) { - dev_warn(vg->dev, - "Pin %i: could not retrieve conf0 register\n", - i); + dev_warn(vg->dev, "Pin %i: could not retrieve CONF0\n", i); continue; } @@ -1588,9 +1575,7 @@ static int byt_gpio_irq_init_hw(struct gpio_chip *chip) reg = byt_gpio_reg(vg, base, BYT_INT_STAT_REG); if (!reg) { - dev_warn(vg->dev, - "Pin %i: could not retrieve irq status reg\n", - base); + dev_warn(vg->dev, "Pin %i: can't retrieve INT_STAT%u\n", base / 32, base); continue; } @@ -1600,7 +1585,7 @@ static int byt_gpio_irq_init_hw(struct gpio_chip *chip) value = readl(reg); if (value) dev_err(vg->dev, - "GPIO interrupt error, pins misconfigured. INT_STAT%u: 0x%08x\n", + "GPIO interrupt error, pins misconfigured. INT_STAT%u: %#08x\n", base / 32, value); } @@ -1764,15 +1749,17 @@ static int byt_gpio_suspend(struct device *dev) reg = byt_gpio_reg(vg, pin, BYT_CONF0_REG); if (!reg) { - dev_warn(vg->dev, - "Pin %i: could not retrieve conf0 register\n", - i); + dev_warn(vg->dev, "Pin %i: can't retrieve CONF0\n", i); continue; } value = readl(reg) & BYT_CONF0_RESTORE_MASK; vg->context.pads[i].conf0 = value; reg = byt_gpio_reg(vg, pin, BYT_VAL_REG); + if (!reg) { + dev_warn(vg->dev, "Pin %i: can't retrieve VAL\n", i); + continue; + } value = readl(reg) & BYT_VAL_RESTORE_MASK; vg->context.pads[i].val = value; } @@ -1796,9 +1783,7 @@ static int byt_gpio_resume(struct device *dev) reg = byt_gpio_reg(vg, pin, BYT_CONF0_REG); if (!reg) { - dev_warn(vg->dev, - "Pin %i: could not retrieve conf0 register\n", - i); + dev_warn(vg->dev, "Pin %i: can't retrieve CONF0\n", i); continue; } value = readl(reg); @@ -1807,10 +1792,14 @@ static int byt_gpio_resume(struct device *dev) value &= ~BYT_CONF0_RESTORE_MASK; value |= vg->context.pads[i].conf0; writel(value, reg); - dev_info(dev, "restored pin %d conf0 %#08x", i, value); + dev_info(dev, "restored pin %d CONF0 %#08x", i, value); } reg = byt_gpio_reg(vg, pin, BYT_VAL_REG); + if (!reg) { + dev_warn(vg->dev, "Pin %i: can't retrieve VAL\n", i); + continue; + } value = readl(reg); if ((value & BYT_VAL_RESTORE_MASK) != vg->context.pads[i].val) { @@ -1820,8 +1809,7 @@ static int byt_gpio_resume(struct device *dev) v |= vg->context.pads[i].val; if (v != value) { writel(v, reg); - dev_dbg(dev, "restored pin %d val %#08x\n", - i, v); + dev_dbg(dev, "restored pin %d VAL %#08x\n", i, v); } } } diff --git a/drivers/pinctrl/intel/pinctrl-cherryview.c b/drivers/pinctrl/intel/pinctrl-cherryview.c index 722990e27836142760c7a8e7e37110d207bed84b..eee0f9bc3d323938779e863100234f99659b5fc5 100644 --- a/drivers/pinctrl/intel/pinctrl-cherryview.c +++ b/drivers/pinctrl/intel/pinctrl-cherryview.c @@ -75,7 +75,7 @@ struct intel_pad_context { u32 padctrl1; }; -#define CHV_INVALID_HWIRQ ((unsigned int)INVALID_HWIRQ) +#define CHV_INVALID_HWIRQ (~0U) /** * struct intel_community_context - community context for Cherryview @@ -949,11 +949,6 @@ static int chv_config_get(struct pinctrl_dev *pctldev, unsigned int pin, break; - case PIN_CONFIG_DRIVE_OPEN_DRAIN: - if (!(ctrl1 & CHV_PADCTRL1_ODEN)) - return -EINVAL; - break; - case PIN_CONFIG_BIAS_HIGH_IMPEDANCE: { u32 cfg; @@ -963,6 +958,16 @@ static int chv_config_get(struct pinctrl_dev *pctldev, unsigned int pin, return -EINVAL; break; + + case PIN_CONFIG_DRIVE_PUSH_PULL: + if (ctrl1 & CHV_PADCTRL1_ODEN) + return -EINVAL; + break; + + case PIN_CONFIG_DRIVE_OPEN_DRAIN: + if (!(ctrl1 & CHV_PADCTRL1_ODEN)) + return -EINVAL; + break; } default: @@ -1408,8 +1413,10 @@ static int chv_gpio_irq_type(struct irq_data *d, unsigned int type) raw_spin_lock_irqsave(&chv_lock, flags); ret = chv_gpio_set_intr_line(pctrl, hwirq); - if (ret) - goto out_unlock; + if (ret) { + raw_spin_unlock_irqrestore(&chv_lock, flags); + return ret; + } /* * Pins which can be used as shared interrupt are configured in @@ -1450,10 +1457,9 @@ static int chv_gpio_irq_type(struct irq_data *d, unsigned int type) else if (type & IRQ_TYPE_LEVEL_MASK) irq_set_handler_locked(d, handle_level_irq); -out_unlock: raw_spin_unlock_irqrestore(&chv_lock, flags); - return ret; + return 0; } static const struct irq_chip chv_gpio_irq_chip = { diff --git a/drivers/pinctrl/intel/pinctrl-intel.c b/drivers/pinctrl/intel/pinctrl-intel.c index c7a71c49df0a7cea1934c2f4e688fc5662bc3d54..64c3e62b43481037292a47dfb8f880990e536eb4 100644 --- a/drivers/pinctrl/intel/pinctrl-intel.c +++ b/drivers/pinctrl/intel/pinctrl-intel.c @@ -55,12 +55,11 @@ /* Offset from pad_regs */ #define PADCFG0 0x000 -#define PADCFG0_RXEVCFG_SHIFT 25 #define PADCFG0_RXEVCFG_MASK GENMASK(26, 25) -#define PADCFG0_RXEVCFG_LEVEL 0 -#define PADCFG0_RXEVCFG_EDGE 1 -#define PADCFG0_RXEVCFG_DISABLED 2 -#define PADCFG0_RXEVCFG_EDGE_BOTH 3 +#define PADCFG0_RXEVCFG_LEVEL (0 << 25) +#define PADCFG0_RXEVCFG_EDGE (1 << 25) +#define PADCFG0_RXEVCFG_DISABLED (2 << 25) +#define PADCFG0_RXEVCFG_EDGE_BOTH (3 << 25) #define PADCFG0_PREGFRXSEL BIT(24) #define PADCFG0_RXINV BIT(23) #define PADCFG0_GPIROUTIOXAPIC BIT(20) @@ -411,18 +410,19 @@ static int intel_pinmux_set_mux(struct pinctrl_dev *pctldev, /* Now enable the mux setting for each pin in the group */ for (i = 0; i < grp->grp.npins; i++) { void __iomem *padcfg0; - u32 value; + u32 value, pmode; padcfg0 = intel_get_padcfg(pctrl, grp->grp.pins[i], PADCFG0); - value = readl(padcfg0); + value = readl(padcfg0); value &= ~PADCFG0_PMODE_MASK; if (grp->modes) - value |= grp->modes[i] << PADCFG0_PMODE_SHIFT; + pmode = grp->modes[i]; else - value |= grp->mode << PADCFG0_PMODE_SHIFT; + pmode = grp->mode; + value |= pmode << PADCFG0_PMODE_SHIFT; writel(value, padcfg0); } @@ -1126,9 +1126,9 @@ static int intel_gpio_irq_type(struct irq_data *d, unsigned int type) struct gpio_chip *gc = irq_data_get_irq_chip_data(d); struct intel_pinctrl *pctrl = gpiochip_get_data(gc); unsigned int pin = intel_gpio_to_pin(pctrl, irqd_to_hwirq(d), NULL, NULL); + u32 rxevcfg, rxinv, value; unsigned long flags; void __iomem *reg; - u32 value; reg = intel_get_padcfg(pctrl, pin, PADCFG0); if (!reg) @@ -1144,28 +1144,32 @@ static int intel_gpio_irq_type(struct irq_data *d, unsigned int type) return -EPERM; } - raw_spin_lock_irqsave(&pctrl->lock, flags); - - intel_gpio_set_gpio_mode(reg); - - value = readl(reg); - - value &= ~(PADCFG0_RXEVCFG_MASK | PADCFG0_RXINV); - if ((type & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH) { - value |= PADCFG0_RXEVCFG_EDGE_BOTH << PADCFG0_RXEVCFG_SHIFT; + rxevcfg = PADCFG0_RXEVCFG_EDGE_BOTH; } else if (type & IRQ_TYPE_EDGE_FALLING) { - value |= PADCFG0_RXEVCFG_EDGE << PADCFG0_RXEVCFG_SHIFT; - value |= PADCFG0_RXINV; + rxevcfg = PADCFG0_RXEVCFG_EDGE; } else if (type & IRQ_TYPE_EDGE_RISING) { - value |= PADCFG0_RXEVCFG_EDGE << PADCFG0_RXEVCFG_SHIFT; + rxevcfg = PADCFG0_RXEVCFG_EDGE; } else if (type & IRQ_TYPE_LEVEL_MASK) { - if (type & IRQ_TYPE_LEVEL_LOW) - value |= PADCFG0_RXINV; + rxevcfg = PADCFG0_RXEVCFG_LEVEL; } else { - value |= PADCFG0_RXEVCFG_DISABLED << PADCFG0_RXEVCFG_SHIFT; + rxevcfg = PADCFG0_RXEVCFG_DISABLED; } + if (type == IRQ_TYPE_EDGE_FALLING || type == IRQ_TYPE_LEVEL_LOW) + rxinv = PADCFG0_RXINV; + else + rxinv = 0; + + raw_spin_lock_irqsave(&pctrl->lock, flags); + + intel_gpio_set_gpio_mode(reg); + + value = readl(reg); + + value = (value & ~PADCFG0_RXEVCFG_MASK) | rxevcfg; + value = (value & ~PADCFG0_RXINV) | rxinv; + writel(value, reg); if (type & IRQ_TYPE_EDGE_BOTH) diff --git a/drivers/pinctrl/intel/pinctrl-merrifield.c b/drivers/pinctrl/intel/pinctrl-merrifield.c index 365c391c97a3fb012e3e8cef77de0a1670de9398..fb6de38b1c5016dd431ba08c32c7d09ac46f7899 100644 --- a/drivers/pinctrl/intel/pinctrl-merrifield.c +++ b/drivers/pinctrl/intel/pinctrl-merrifield.c @@ -549,7 +549,7 @@ static void mrfld_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s, } mode = (value & BUFCFG_PINMODE_MASK) >> BUFCFG_PINMODE_SHIFT; - if (!mode) + if (mode == BUFCFG_PINMODE_GPIO) seq_puts(s, "GPIO "); else seq_printf(s, "mode %d ", mode); @@ -710,6 +710,11 @@ static int mrfld_config_get(struct pinctrl_dev *pctldev, unsigned int pin, break; + case PIN_CONFIG_DRIVE_PUSH_PULL: + if (value & BUFCFG_OD_EN) + return -EINVAL; + break; + case PIN_CONFIG_DRIVE_OPEN_DRAIN: if (!(value & BUFCFG_OD_EN)) return -EINVAL; @@ -791,10 +796,14 @@ static int mrfld_config_set_pin(struct mrfld_pinctrl *mp, unsigned int pin, break; + case PIN_CONFIG_DRIVE_PUSH_PULL: + mask |= BUFCFG_OD_EN; + bits &= ~BUFCFG_OD_EN; + break; + case PIN_CONFIG_DRIVE_OPEN_DRAIN: mask |= BUFCFG_OD_EN; - if (arg) - bits |= BUFCFG_OD_EN; + bits |= BUFCFG_OD_EN; break; case PIN_CONFIG_SLEW_RATE: @@ -826,6 +835,7 @@ static int mrfld_config_set(struct pinctrl_dev *pctldev, unsigned int pin, case PIN_CONFIG_BIAS_DISABLE: case PIN_CONFIG_BIAS_PULL_UP: case PIN_CONFIG_BIAS_PULL_DOWN: + case PIN_CONFIG_DRIVE_PUSH_PULL: case PIN_CONFIG_DRIVE_OPEN_DRAIN: case PIN_CONFIG_SLEW_RATE: ret = mrfld_config_set_pin(mp, pin, configs[i]); diff --git a/drivers/pinctrl/intel/pinctrl-meteorlake.c b/drivers/pinctrl/intel/pinctrl-meteorlake.c index a82f6754c45bf43e36e7b99e2ca15b2a2d71cefc..9a11f729bec8dd72d6671393e59014503b1fdc31 100644 --- a/drivers/pinctrl/intel/pinctrl-meteorlake.c +++ b/drivers/pinctrl/intel/pinctrl-meteorlake.c @@ -20,6 +20,12 @@ #define MTL_P_GPI_IS 0x200 #define MTL_P_GPI_IE 0x210 +#define MTL_S_PAD_OWN 0x0b0 +#define MTL_S_PADCFGLOCK 0x0f0 +#define MTL_S_HOSTSW_OWN 0x110 +#define MTL_S_GPI_IS 0x200 +#define MTL_S_GPI_IE 0x210 + #define MTL_GPP(r, s, e, g) \ { \ .reg_num = (r), \ @@ -28,9 +34,12 @@ .gpio_base = (g), \ } -#define MTL_COMMUNITY(b, s, e, g) \ +#define MTL_P_COMMUNITY(b, s, e, g) \ INTEL_COMMUNITY_GPPS(b, s, e, g, MTL_P) +#define MTL_S_COMMUNITY(b, s, e, g) \ + INTEL_COMMUNITY_GPPS(b, s, e, g, MTL_S) + /* Meteor Lake-P */ static const struct pinctrl_pin_desc mtlp_pins[] = { /* CPU */ @@ -369,11 +378,11 @@ static const struct intel_padgroup mtlp_community5_gpps[] = { }; static const struct intel_community mtlp_communities[] = { - MTL_COMMUNITY(0, 0, 52, mtlp_community0_gpps), - MTL_COMMUNITY(1, 53, 102, mtlp_community1_gpps), - MTL_COMMUNITY(2, 103, 183, mtlp_community3_gpps), - MTL_COMMUNITY(3, 184, 203, mtlp_community4_gpps), - MTL_COMMUNITY(4, 204, 288, mtlp_community5_gpps), + MTL_P_COMMUNITY(0, 0, 52, mtlp_community0_gpps), + MTL_P_COMMUNITY(1, 53, 102, mtlp_community1_gpps), + MTL_P_COMMUNITY(2, 103, 183, mtlp_community3_gpps), + MTL_P_COMMUNITY(3, 184, 203, mtlp_community4_gpps), + MTL_P_COMMUNITY(4, 204, 288, mtlp_community5_gpps), }; static const struct intel_pinctrl_soc_data mtlp_soc_data = { @@ -383,8 +392,199 @@ static const struct intel_pinctrl_soc_data mtlp_soc_data = { .ncommunities = ARRAY_SIZE(mtlp_communities), }; +/* Meteor Lake-S */ +static const struct pinctrl_pin_desc mtls_pins[] = { + /* GPP_A */ + PINCTRL_PIN(0, "DIR_ESPI_IO_0"), + PINCTRL_PIN(1, "DIR_ESPI_IO_1"), + PINCTRL_PIN(2, "DIR_ESPI_IO_2"), + PINCTRL_PIN(3, "DIR_ESPI_IO_3"), + PINCTRL_PIN(4, "DIR_ESPI_CS0_B"), + PINCTRL_PIN(5, "DIR_ESPI_CLK"), + PINCTRL_PIN(6, "DIR_ESPI_RCLK"), + PINCTRL_PIN(7, "DIR_ESPI_RESET_B"), + PINCTRL_PIN(8, "SLP_S0_B"), + PINCTRL_PIN(9, "DMI_PERSTB"), + PINCTRL_PIN(10, "CATERR_B"), + PINCTRL_PIN(11, "THERMTRIP_B"), + PINCTRL_PIN(12, "CPU_C10_GATE_B"), + PINCTRL_PIN(13, "PS_ONB"), + PINCTRL_PIN(14, "GPP_SA_14"), + PINCTRL_PIN(15, "GPP_SA_15"), + PINCTRL_PIN(16, "GPP_SA_16"), + PINCTRL_PIN(17, "GPP_SA_17"), + PINCTRL_PIN(18, "GPP_SA_18"), + PINCTRL_PIN(19, "GPP_SA_19"), + PINCTRL_PIN(20, "GPP_SA_20"), + PINCTRL_PIN(21, "GPP_SA_21"), + PINCTRL_PIN(22, "FUSA_DIAGTEST_EN"), + PINCTRL_PIN(23, "FUSA_DIAGTEST_MODE"), + PINCTRL_PIN(24, "RTCCLKIN"), + PINCTRL_PIN(25, "RESET_SYNC_B"), + PINCTRL_PIN(26, "PCH_PWROK"), + PINCTRL_PIN(27, "DIR_ESPI_CLK_LOOPBACK"), + /* vGPIO_0 */ + PINCTRL_PIN(28, "LPC_ME_FTPM_ENABLE"), + PINCTRL_PIN(29, "LPC_DTFUS_CORE_SPITPM_DIS"), + PINCTRL_PIN(30, "LPC_SPI_STRAP_TOS"), + PINCTRL_PIN(31, "ITSS_KU1_SHTDWN"), + PINCTRL_PIN(32, "LPC_PRR_TS_OVR"), + PINCTRL_PIN(33, "ESPI_PMC_EC_SCI"), + PINCTRL_PIN(34, "ESPI_PMC_EC_SCI1"), + PINCTRL_PIN(35, "vGPIO_SPARE0"), + PINCTRL_PIN(36, "vGPIO_SPARE1"), + PINCTRL_PIN(37, "vGPIO_SPARE2"), + PINCTRL_PIN(38, "vGPIO_SPARE3"), + PINCTRL_PIN(39, "vGPIO_SPARE8"), + PINCTRL_PIN(40, "vGPIO_SPARE9"), + PINCTRL_PIN(41, "vGPIO_SPARE10"), + PINCTRL_PIN(42, "vGPIO_SPARE11"), + PINCTRL_PIN(43, "vGPIO_SPARE12"), + PINCTRL_PIN(44, "vGPIO_SPARE13"), + PINCTRL_PIN(45, "vGPIO_SPARE14"), + PINCTRL_PIN(46, "vGPIO_SPARE15"), + /* GPP_C */ + PINCTRL_PIN(47, "GPP_SC_0"), + PINCTRL_PIN(48, "GPP_SC_1"), + PINCTRL_PIN(49, "GPP_SC_2"), + PINCTRL_PIN(50, "GPP_SC_3"), + PINCTRL_PIN(51, "GPP_SC_4"), + PINCTRL_PIN(52, "GPP_SC_5"), + PINCTRL_PIN(53, "GPP_SC_6"), + PINCTRL_PIN(54, "GPP_SC_7"), + PINCTRL_PIN(55, "GPP_SC_8"), + PINCTRL_PIN(56, "GPP_SC_9"), + PINCTRL_PIN(57, "GPP_SC_10"), + PINCTRL_PIN(58, "GPP_SC_11"), + PINCTRL_PIN(59, "GPP_SC_12"), + PINCTRL_PIN(60, "GPP_SC_13"), + PINCTRL_PIN(61, "GPP_SC_14"), + PINCTRL_PIN(62, "GPP_SC_15"), + PINCTRL_PIN(63, "GPP_SC_16"), + PINCTRL_PIN(64, "GPP_SC_17"), + PINCTRL_PIN(65, "GPP_SC_18"), + PINCTRL_PIN(66, "GPP_SC_19"), + PINCTRL_PIN(67, "GPP_SC_20"), + PINCTRL_PIN(68, "GPP_SC_21"), + PINCTRL_PIN(69, "GPP_SC_22"), + PINCTRL_PIN(70, "GPP_SC_23"), + PINCTRL_PIN(71, "GPP_SC_24"), + PINCTRL_PIN(72, "GPP_SC_25"), + PINCTRL_PIN(73, "GPP_SC_26"), + /* GPP_B */ + PINCTRL_PIN(74, "GPP_SB_0"), + PINCTRL_PIN(75, "GPP_SB_1"), + PINCTRL_PIN(76, "GPP_SB_2"), + PINCTRL_PIN(77, "GPP_SB_3"), + PINCTRL_PIN(78, "GPP_SB_4"), + PINCTRL_PIN(79, "GPP_SB_5"), + PINCTRL_PIN(80, "GPP_SB_6"), + PINCTRL_PIN(81, "GPP_SB_7"), + PINCTRL_PIN(82, "GPP_SB_8"), + PINCTRL_PIN(83, "GPP_SB_9"), + PINCTRL_PIN(84, "GPP_SB_10"), + PINCTRL_PIN(85, "GPP_SB_11"), + PINCTRL_PIN(86, "GPP_SB_12"), + PINCTRL_PIN(87, "GPP_SB_13"), + PINCTRL_PIN(88, "GPP_SB_14"), + PINCTRL_PIN(89, "GPP_SB_15"), + PINCTRL_PIN(90, "GPP_SB_16"), + PINCTRL_PIN(91, "PROCHOT_B"), + PINCTRL_PIN(92, "BPKI3C_SDA"), + PINCTRL_PIN(93, "BPKI3C_SCL"), + /* vGPIO_3 */ + PINCTRL_PIN(94, "TS0_IN_INT"), + PINCTRL_PIN(95, "TS1_IN_INT"), + /* GPP_D */ + PINCTRL_PIN(96, "TIME_SYNC_0"), + PINCTRL_PIN(97, "TIME_SYNC_1"), + PINCTRL_PIN(98, "DSI_DE_TE_2_GENLOCK_REF"), + PINCTRL_PIN(99, "DSI_DE_TE_1_DISP_UTILS"), + PINCTRL_PIN(100, "DSI_GENLOCK_2"), + PINCTRL_PIN(101, "DSI_GENLOCK_3"), + PINCTRL_PIN(102, "SRCCLKREQ2_B"), + PINCTRL_PIN(103, "SRCCLKREQ3_B"), + PINCTRL_PIN(104, "GPP_SD_8"), + PINCTRL_PIN(105, "GPP_SD_9"), + PINCTRL_PIN(106, "GPP_SD_10"), + PINCTRL_PIN(107, "GPP_SD_11"), + PINCTRL_PIN(108, "GPP_SD_12"), + PINCTRL_PIN(109, "GPP_SD_13"), + PINCTRL_PIN(110, "GPP_SD_14"), + PINCTRL_PIN(111, "GPP_SD_15"), + PINCTRL_PIN(112, "GPP_SD_16"), + PINCTRL_PIN(113, "GPP_SD_17"), + PINCTRL_PIN(114, "BOOTHALT_B"), + PINCTRL_PIN(115, "GPP_SD_19"), + PINCTRL_PIN(116, "GPP_SD_20"), + PINCTRL_PIN(117, "AUDCLK"), + PINCTRL_PIN(118, "AUDIN"), + PINCTRL_PIN(119, "AUDOUT"), + /* JTAG_CPU */ + PINCTRL_PIN(120, "PECI"), + PINCTRL_PIN(121, "VIDSOUT"), + PINCTRL_PIN(122, "VIDSCK"), + PINCTRL_PIN(123, "VIDALERT_B"), + PINCTRL_PIN(124, "JTAG_MBPB0"), + PINCTRL_PIN(125, "JTAG_MBPB1"), + PINCTRL_PIN(126, "JTAG_MBPB2"), + PINCTRL_PIN(127, "JTAG_MBPB3"), + PINCTRL_PIN(128, "JTAG_TDO"), + PINCTRL_PIN(129, "PRDY_B"), + PINCTRL_PIN(130, "PREQ_B"), + PINCTRL_PIN(131, "JTAG_TDI"), + PINCTRL_PIN(132, "JTAG_TMS"), + PINCTRL_PIN(133, "JTAG_TCK"), + PINCTRL_PIN(134, "DBG_PMODE"), + PINCTRL_PIN(135, "JTAG_TRST_B"), + /* vGPIO_4 */ + PINCTRL_PIN(136, "ISCLK_ESPI_XTAL_CLKREQ"), + PINCTRL_PIN(137, "ESPI_ISCLK_XTAL_CLKACK"), + PINCTRL_PIN(138, "vGPIO_SPARE4"), + PINCTRL_PIN(139, "vGPIO_SPARE5"), + PINCTRL_PIN(140, "vGPIO_SPARE6"), + PINCTRL_PIN(141, "vGPIO_SPARE7"), + PINCTRL_PIN(142, "vGPIO_SPARE16"), + PINCTRL_PIN(143, "vGPIO_SPARE17"), + PINCTRL_PIN(144, "vGPIO_SPARE18"), + PINCTRL_PIN(145, "vGPIO_SPARE19"), + PINCTRL_PIN(146, "vGPIO_SPARE20"), + PINCTRL_PIN(147, "vGPIO_SPARE21"), +}; + +static const struct intel_padgroup mtls_community0_gpps[] = { + MTL_GPP(0, 0, 27, 0), /* GPP_A */ + MTL_GPP(1, 28, 46, 32), /* vGPIO_0 */ + MTL_GPP(2, 47, 73, 64), /* GPP_C */ +}; + +static const struct intel_padgroup mtls_community1_gpps[] = { + MTL_GPP(0, 74, 93, 96), /* GPP_B */ + MTL_GPP(1, 94, 95, 128), /* vGPIO_3 */ + MTL_GPP(2, 96, 119, 160), /* GPP_D */ +}; + +static const struct intel_padgroup mtls_community3_gpps[] = { + MTL_GPP(0, 120, 135, 192), /* JTAG_CPU */ + MTL_GPP(1, 136, 147, 224), /* vGPIO_4 */ +}; + +static const struct intel_community mtls_communities[] = { + MTL_S_COMMUNITY(0, 0, 73, mtls_community0_gpps), + MTL_S_COMMUNITY(1, 74, 119, mtls_community1_gpps), + MTL_S_COMMUNITY(2, 120, 147, mtls_community3_gpps), +}; + +static const struct intel_pinctrl_soc_data mtls_soc_data = { + .pins = mtls_pins, + .npins = ARRAY_SIZE(mtls_pins), + .communities = mtls_communities, + .ncommunities = ARRAY_SIZE(mtls_communities), +}; + static const struct acpi_device_id mtl_pinctrl_acpi_match[] = { { "INTC1083", (kernel_ulong_t)&mtlp_soc_data }, + { "INTC1082", (kernel_ulong_t)&mtls_soc_data }, { } }; MODULE_DEVICE_TABLE(acpi, mtl_pinctrl_acpi_match); diff --git a/drivers/pinctrl/intel/pinctrl-moorefield.c b/drivers/pinctrl/intel/pinctrl-moorefield.c index 3c9a8484b4427ea27274565fdbb50754858207d8..2d38d953f360dcb686e2e1bad7411102fe4b5e70 100644 --- a/drivers/pinctrl/intel/pinctrl-moorefield.c +++ b/drivers/pinctrl/intel/pinctrl-moorefield.c @@ -504,7 +504,7 @@ static void mofld_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s, } mode = (value & BUFCFG_PINMODE_MASK) >> BUFCFG_PINMODE_SHIFT; - if (!mode) + if (mode == BUFCFG_PINMODE_GPIO) seq_puts(s, "GPIO "); else seq_printf(s, "mode %d ", mode); @@ -661,6 +661,11 @@ static int mofld_config_get(struct pinctrl_dev *pctldev, unsigned int pin, break; + case PIN_CONFIG_DRIVE_PUSH_PULL: + if (value & BUFCFG_OD_EN) + return -EINVAL; + break; + case PIN_CONFIG_DRIVE_OPEN_DRAIN: if (!(value & BUFCFG_OD_EN)) return -EINVAL; @@ -734,10 +739,14 @@ static int mofld_config_set_pin(struct mofld_pinctrl *mp, unsigned int pin, break; + case PIN_CONFIG_DRIVE_PUSH_PULL: + mask |= BUFCFG_OD_EN; + bits &= ~BUFCFG_OD_EN; + break; + case PIN_CONFIG_DRIVE_OPEN_DRAIN: mask |= BUFCFG_OD_EN; - if (arg) - bits |= BUFCFG_OD_EN; + bits |= BUFCFG_OD_EN; break; case PIN_CONFIG_SLEW_RATE: @@ -769,6 +778,7 @@ static int mofld_config_set(struct pinctrl_dev *pctldev, unsigned int pin, case PIN_CONFIG_BIAS_DISABLE: case PIN_CONFIG_BIAS_PULL_UP: case PIN_CONFIG_BIAS_PULL_DOWN: + case PIN_CONFIG_DRIVE_PUSH_PULL: case PIN_CONFIG_DRIVE_OPEN_DRAIN: case PIN_CONFIG_SLEW_RATE: ret = mofld_config_set_pin(mp, pin, configs[i]); diff --git a/drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c b/drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c index 21e61c2a379881cb15c732da694783aacea8ba46..843ffcd9687747744c10eb5711c7895978594b00 100644 --- a/drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c +++ b/drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c @@ -1884,6 +1884,8 @@ static int npcm7xx_gpio_of(struct npcm7xx_pinctrl *pctrl) } pctrl->gpio_bank[id].base = ioremap(res.start, resource_size(&res)); + if (!pctrl->gpio_bank[id].base) + return -EINVAL; ret = bgpio_init(&pctrl->gpio_bank[id].gc, dev, 4, pctrl->gpio_bank[id].base + NPCM7XX_GP_N_DIN, diff --git a/drivers/pinctrl/nxp/pinctrl-s32.h b/drivers/pinctrl/nxp/pinctrl-s32.h index 2f7aecd462e49448da36b6476a26b88b2ab65a4b..add3c77ddfedbec3541941e50634b7effaed8e4a 100644 --- a/drivers/pinctrl/nxp/pinctrl-s32.h +++ b/drivers/pinctrl/nxp/pinctrl-s32.h @@ -34,24 +34,28 @@ struct s32_pin_range { unsigned int end; }; -struct s32_pinctrl_soc_info { - struct device *dev; +struct s32_pinctrl_soc_data { const struct pinctrl_pin_desc *pins; unsigned int npins; + const struct s32_pin_range *mem_pin_ranges; + unsigned int mem_regions; +}; + +struct s32_pinctrl_soc_info { + struct device *dev; + const struct s32_pinctrl_soc_data *soc_data; struct s32_pin_group *groups; unsigned int ngroups; struct pinfunction *functions; unsigned int nfunctions; unsigned int grp_index; - const struct s32_pin_range *mem_pin_ranges; - unsigned int mem_regions; }; #define S32_PINCTRL_PIN(pin) PINCTRL_PIN(pin, #pin) #define S32_PIN_RANGE(_start, _end) { .start = _start, .end = _end } int s32_pinctrl_probe(struct platform_device *pdev, - struct s32_pinctrl_soc_info *info); + const struct s32_pinctrl_soc_data *soc_data); int s32_pinctrl_resume(struct device *dev); int s32_pinctrl_suspend(struct device *dev); #endif /* __DRIVERS_PINCTRL_S32_H */ diff --git a/drivers/pinctrl/nxp/pinctrl-s32cc.c b/drivers/pinctrl/nxp/pinctrl-s32cc.c index 8373468719b6a61de7075172d80ac8ebf0509d62..3ae043b274633b5e949f8b39811eb3298c4f6fb9 100644 --- a/drivers/pinctrl/nxp/pinctrl-s32cc.c +++ b/drivers/pinctrl/nxp/pinctrl-s32cc.c @@ -106,7 +106,7 @@ s32_get_region(struct pinctrl_dev *pctldev, unsigned int pin) { struct s32_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev); const struct s32_pin_range *pin_range; - unsigned int mem_regions = ipctl->info->mem_regions; + unsigned int mem_regions = ipctl->info->soc_data->mem_regions; unsigned int i; for (i = 0; i < mem_regions; i++) { @@ -279,8 +279,10 @@ static int s32_dt_node_to_map(struct pinctrl_dev *pctldev, ret = s32_dt_group_node_to_map(pctldev, np, map, &reserved_maps, num_maps, np_config->name); - if (ret < 0) + if (ret < 0) { + of_node_put(np); break; + } } if (ret) @@ -688,8 +690,8 @@ int s32_pinctrl_suspend(struct device *dev) int ret; unsigned int config; - for (i = 0; i < info->npins; i++) { - pin = &info->pins[i]; + for (i = 0; i < info->soc_data->npins; i++) { + pin = &info->soc_data->pins[i]; if (!s32_pinctrl_should_save(ipctl, pin->number)) continue; @@ -713,8 +715,8 @@ int s32_pinctrl_resume(struct device *dev) struct s32_pinctrl_context *saved_context = &ipctl->saved_context; int ret, i; - for (i = 0; i < info->npins; i++) { - pin = &info->pins[i]; + for (i = 0; i < info->soc_data->npins; i++) { + pin = &info->soc_data->pins[i]; if (!s32_pinctrl_should_save(ipctl, pin->number)) continue; @@ -812,8 +814,10 @@ static int s32_pinctrl_parse_functions(struct device_node *np, groups[i] = child->name; grp = &info->groups[info->grp_index++]; ret = s32_pinctrl_parse_groups(child, grp, info); - if (ret) + if (ret) { + of_node_put(child); return ret; + } i++; } @@ -831,7 +835,7 @@ static int s32_pinctrl_probe_dt(struct platform_device *pdev, struct resource *res; struct regmap *map; void __iomem *base; - int mem_regions = info->mem_regions; + unsigned int mem_regions = info->soc_data->mem_regions; int ret; u32 nfuncs = 0; u32 i = 0; @@ -869,7 +873,7 @@ static int s32_pinctrl_probe_dt(struct platform_device *pdev, } ipctl->regions[i].map = map; - ipctl->regions[i].pin_range = &info->mem_pin_ranges[i]; + ipctl->regions[i].pin_range = &info->soc_data->mem_pin_ranges[i]; } nfuncs = of_get_child_count(np); @@ -896,28 +900,36 @@ static int s32_pinctrl_probe_dt(struct platform_device *pdev, i = 0; for_each_child_of_node(np, child) { ret = s32_pinctrl_parse_functions(child, info, i++); - if (ret) + if (ret) { + of_node_put(child); return ret; + } } return 0; } int s32_pinctrl_probe(struct platform_device *pdev, - struct s32_pinctrl_soc_info *info) + const struct s32_pinctrl_soc_data *soc_data) { struct s32_pinctrl *ipctl; int ret; struct pinctrl_desc *s32_pinctrl_desc; + struct s32_pinctrl_soc_info *info; #ifdef CONFIG_PM_SLEEP struct s32_pinctrl_context *saved_context; #endif - if (!info || !info->pins || !info->npins) { + if (!soc_data || !soc_data->pins || !soc_data->npins) { dev_err(&pdev->dev, "wrong pinctrl info\n"); return -EINVAL; } + info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL); + if (!info) + return -ENOMEM; + + info->soc_data = soc_data; info->dev = &pdev->dev; /* Create state holders etc for this driver */ @@ -938,8 +950,8 @@ int s32_pinctrl_probe(struct platform_device *pdev, return -ENOMEM; s32_pinctrl_desc->name = dev_name(&pdev->dev); - s32_pinctrl_desc->pins = info->pins; - s32_pinctrl_desc->npins = info->npins; + s32_pinctrl_desc->pins = info->soc_data->pins; + s32_pinctrl_desc->npins = info->soc_data->npins; s32_pinctrl_desc->pctlops = &s32_pctrl_ops; s32_pinctrl_desc->pmxops = &s32_pmx_ops; s32_pinctrl_desc->confops = &s32_pinconf_ops; @@ -960,7 +972,7 @@ int s32_pinctrl_probe(struct platform_device *pdev, #ifdef CONFIG_PM_SLEEP saved_context = &ipctl->saved_context; saved_context->pads = - devm_kcalloc(&pdev->dev, info->npins, + devm_kcalloc(&pdev->dev, info->soc_data->npins, sizeof(*saved_context->pads), GFP_KERNEL); if (!saved_context->pads) diff --git a/drivers/pinctrl/nxp/pinctrl-s32g2.c b/drivers/pinctrl/nxp/pinctrl-s32g2.c index d9f3ff6794ea95a1e70b8c21cf7a63037b042a50..224a12ce70edbe5d2fe08a40f958f5e3daf71daa 100644 --- a/drivers/pinctrl/nxp/pinctrl-s32g2.c +++ b/drivers/pinctrl/nxp/pinctrl-s32g2.c @@ -721,7 +721,7 @@ static const struct s32_pin_range s32_pin_ranges_siul2[] = { S32_PIN_RANGE(942, 1007), }; -static struct s32_pinctrl_soc_info s32_pinctrl_info = { +static const struct s32_pinctrl_soc_data s32_pinctrl_data = { .pins = s32_pinctrl_pads_siul2, .npins = ARRAY_SIZE(s32_pinctrl_pads_siul2), .mem_pin_ranges = s32_pin_ranges_siul2, @@ -730,9 +730,8 @@ static struct s32_pinctrl_soc_info s32_pinctrl_info = { static const struct of_device_id s32_pinctrl_of_match[] = { { - .compatible = "nxp,s32g2-siul2-pinctrl", - .data = (void *) &s32_pinctrl_info, + .data = &s32_pinctrl_data, }, { /* sentinel */ } }; @@ -740,14 +739,11 @@ MODULE_DEVICE_TABLE(of, s32_pinctrl_of_match); static int s32g_pinctrl_probe(struct platform_device *pdev) { - const struct of_device_id *of_id = - of_match_device(s32_pinctrl_of_match, &pdev->dev); + const struct s32_pinctrl_soc_data *soc_data; - if (!of_id) - return -ENODEV; + soc_data = of_device_get_match_data(&pdev->dev); - return s32_pinctrl_probe - (pdev, (struct s32_pinctrl_soc_info *) of_id->data); + return s32_pinctrl_probe(pdev, soc_data); } static const struct dev_pm_ops s32g_pinctrl_pm_ops = { diff --git a/drivers/pinctrl/pinctrl-amd.c b/drivers/pinctrl/pinctrl-amd.c index f279b360c20d38fbfb2a43829fefb80bba7d03d1..4a8c1b57a90d6300591a76d5af3a4f5b1c6034e1 100644 --- a/drivers/pinctrl/pinctrl-amd.c +++ b/drivers/pinctrl/pinctrl-amd.c @@ -30,6 +30,7 @@ #include #include #include +#include #include "core.h" #include "pinctrl-utils.h" @@ -115,16 +116,20 @@ static void amd_gpio_set_value(struct gpio_chip *gc, unsigned offset, int value) raw_spin_unlock_irqrestore(&gpio_dev->lock, flags); } -static int amd_gpio_set_debounce(struct gpio_chip *gc, unsigned offset, - unsigned debounce) +static int amd_gpio_set_debounce(struct amd_gpio *gpio_dev, unsigned int offset, + unsigned int debounce) { u32 time; u32 pin_reg; int ret = 0; - unsigned long flags; - struct amd_gpio *gpio_dev = gpiochip_get_data(gc); - raw_spin_lock_irqsave(&gpio_dev->lock, flags); + /* Use special handling for Pin0 debounce */ + if (offset == 0) { + pin_reg = readl(gpio_dev->base + WAKE_INT_MASTER_REG); + if (pin_reg & INTERNAL_GPIO0_DEBOUNCE) + debounce = 0; + } + pin_reg = readl(gpio_dev->base + offset * 4); if (debounce) { @@ -175,23 +180,10 @@ static int amd_gpio_set_debounce(struct gpio_chip *gc, unsigned offset, pin_reg &= ~(DB_CNTRl_MASK << DB_CNTRL_OFF); } writel(pin_reg, gpio_dev->base + offset * 4); - raw_spin_unlock_irqrestore(&gpio_dev->lock, flags); return ret; } -static int amd_gpio_set_config(struct gpio_chip *gc, unsigned offset, - unsigned long config) -{ - u32 debounce; - - if (pinconf_to_config_param(config) != PIN_CONFIG_INPUT_DEBOUNCE) - return -ENOTSUPP; - - debounce = pinconf_to_config_argument(config); - return amd_gpio_set_debounce(gc, offset, debounce); -} - #ifdef CONFIG_DEBUG_FS static void amd_gpio_dbg_show(struct seq_file *s, struct gpio_chip *gc) { @@ -213,12 +205,12 @@ static void amd_gpio_dbg_show(struct seq_file *s, struct gpio_chip *gc) char *pin_sts; char *interrupt_sts; char *wake_sts; - char *pull_up_sel; char *orientation; char debounce_value[40]; char *debounce_enable; char *wake_cntrlz; + seq_printf(s, "WAKE_INT_MASTER_REG: 0x%08x\n", readl(gpio_dev->base + WAKE_INT_MASTER_REG)); for (bank = 0; bank < gpio_dev->hwbank_num; bank++) { unsigned int time = 0; unsigned int unit = 0; @@ -320,14 +312,9 @@ static void amd_gpio_dbg_show(struct seq_file *s, struct gpio_chip *gc) seq_printf(s, " %s|", wake_sts); if (pin_reg & BIT(PULL_UP_ENABLE_OFF)) { - if (pin_reg & BIT(PULL_UP_SEL_OFF)) - pull_up_sel = "8k"; - else - pull_up_sel = "4k"; - seq_printf(s, "%s ↑|", - pull_up_sel); + seq_puts(s, " ↑ |"); } else if (pin_reg & BIT(PULL_DOWN_ENABLE_OFF)) { - seq_puts(s, " ↓|"); + seq_puts(s, " ↓ |"); } else { seq_puts(s, " |"); } @@ -636,9 +623,8 @@ static bool do_amd_gpio_irq_handler(int irq, void *dev_id) regval = readl(regs + i); if (regval & PIN_IRQ_PENDING) - dev_dbg(&gpio_dev->pdev->dev, - "GPIO %d is active: 0x%x", - irqnr + i, regval); + pm_pr_dbg("GPIO %d is active: 0x%x", + irqnr + i, regval); /* caused wake on resume context for shared IRQ */ if (irq < 0 && (regval & BIT(WAKE_STS_OFF))) @@ -653,21 +639,21 @@ static bool do_amd_gpio_irq_handler(int irq, void *dev_id) * We must read the pin register again, in case the * value was changed while executing * generic_handle_domain_irq() above. - * If we didn't find a mapping for the interrupt, - * disable it in order to avoid a system hang caused - * by an interrupt storm. + * If the line is not an irq, disable it in order to + * avoid a system hang caused by an interrupt storm. */ raw_spin_lock_irqsave(&gpio_dev->lock, flags); regval = readl(regs + i); - if (irq == 0) { - regval &= ~BIT(INTERRUPT_ENABLE_OFF); + if (!gpiochip_line_is_irq(gc, irqnr + i)) { + regval &= ~BIT(INTERRUPT_MASK_OFF); dev_dbg(&gpio_dev->pdev->dev, "Disabling spurious GPIO IRQ %d\n", irqnr + i); + } else { + ret = true; } writel(regval, regs + i); raw_spin_unlock_irqrestore(&gpio_dev->lock, flags); - ret = true; } } /* did not cause wake on resume context for shared IRQ */ @@ -754,7 +740,7 @@ static int amd_pinconf_get(struct pinctrl_dev *pctldev, break; case PIN_CONFIG_BIAS_PULL_UP: - arg = (pin_reg >> PULL_UP_SEL_OFF) & (BIT(0) | BIT(1)); + arg = (pin_reg >> PULL_UP_ENABLE_OFF) & BIT(0); break; case PIN_CONFIG_DRIVE_STRENGTH: @@ -773,7 +759,7 @@ static int amd_pinconf_get(struct pinctrl_dev *pctldev, } static int amd_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin, - unsigned long *configs, unsigned num_configs) + unsigned long *configs, unsigned int num_configs) { int i; u32 arg; @@ -791,9 +777,8 @@ static int amd_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin, switch (param) { case PIN_CONFIG_INPUT_DEBOUNCE: - pin_reg &= ~DB_TMR_OUT_MASK; - pin_reg |= arg & DB_TMR_OUT_MASK; - break; + ret = amd_gpio_set_debounce(gpio_dev, pin, arg); + goto out_unlock; case PIN_CONFIG_BIAS_PULL_DOWN: pin_reg &= ~BIT(PULL_DOWN_ENABLE_OFF); @@ -801,10 +786,8 @@ static int amd_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin, break; case PIN_CONFIG_BIAS_PULL_UP: - pin_reg &= ~BIT(PULL_UP_SEL_OFF); - pin_reg |= (arg & BIT(0)) << PULL_UP_SEL_OFF; pin_reg &= ~BIT(PULL_UP_ENABLE_OFF); - pin_reg |= ((arg>>1) & BIT(0)) << PULL_UP_ENABLE_OFF; + pin_reg |= (arg & BIT(0)) << PULL_UP_ENABLE_OFF; break; case PIN_CONFIG_DRIVE_STRENGTH: @@ -822,6 +805,7 @@ static int amd_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin, writel(pin_reg, gpio_dev->base + pin*4); } +out_unlock: raw_spin_unlock_irqrestore(&gpio_dev->lock, flags); return ret; @@ -863,6 +847,14 @@ static int amd_pinconf_group_set(struct pinctrl_dev *pctldev, return 0; } +static int amd_gpio_set_config(struct gpio_chip *gc, unsigned int pin, + unsigned long config) +{ + struct amd_gpio *gpio_dev = gpiochip_get_data(gc); + + return amd_pinconf_set(gpio_dev->pctrl, pin, &config, 1); +} + static const struct pinconf_ops amd_pinconf_ops = { .pin_config_get = amd_pinconf_get, .pin_config_set = amd_pinconf_set, @@ -870,34 +862,6 @@ static const struct pinconf_ops amd_pinconf_ops = { .pin_config_group_set = amd_pinconf_group_set, }; -static void amd_gpio_irq_init(struct amd_gpio *gpio_dev) -{ - struct pinctrl_desc *desc = gpio_dev->pctrl->desc; - unsigned long flags; - u32 pin_reg, mask; - int i; - - mask = BIT(WAKE_CNTRL_OFF_S0I3) | BIT(WAKE_CNTRL_OFF_S3) | - BIT(INTERRUPT_MASK_OFF) | BIT(INTERRUPT_ENABLE_OFF) | - BIT(WAKE_CNTRL_OFF_S4); - - for (i = 0; i < desc->npins; i++) { - int pin = desc->pins[i].number; - const struct pin_desc *pd = pin_desc_get(gpio_dev->pctrl, pin); - - if (!pd) - continue; - - raw_spin_lock_irqsave(&gpio_dev->lock, flags); - - pin_reg = readl(gpio_dev->base + i * 4); - pin_reg &= ~mask; - writel(pin_reg, gpio_dev->base + i * 4); - - raw_spin_unlock_irqrestore(&gpio_dev->lock, flags); - } -} - #ifdef CONFIG_PM_SLEEP static bool amd_gpio_should_save(struct amd_gpio *gpio_dev, unsigned int pin) { @@ -1135,9 +1099,6 @@ static int amd_gpio_probe(struct platform_device *pdev) return PTR_ERR(gpio_dev->pctrl); } - /* Disable and mask interrupts */ - amd_gpio_irq_init(gpio_dev); - girq = &gpio_dev->gc.irq; gpio_irq_chip_set_chip(girq, &amd_gpio_irqchip); /* This will let us handle the parent IRQ in the driver */ diff --git a/drivers/pinctrl/pinctrl-amd.h b/drivers/pinctrl/pinctrl-amd.h index 81ae8319a1f0af6fbb39e1a8b808f8d97eaff4cf..34c5c3e71fb261cdeb8c6c5ffdfe59c126db8ae0 100644 --- a/drivers/pinctrl/pinctrl-amd.h +++ b/drivers/pinctrl/pinctrl-amd.h @@ -17,6 +17,7 @@ #define AMD_GPIO_PINS_BANK3 32 #define WAKE_INT_MASTER_REG 0xfc +#define INTERNAL_GPIO0_DEBOUNCE (1 << 15) #define EOI_MASK (1 << 29) #define WAKE_INT_STATUS_REG0 0x2f8 @@ -35,7 +36,6 @@ #define WAKE_CNTRL_OFF_S4 15 #define PIN_STS_OFF 16 #define DRV_STRENGTH_SEL_OFF 17 -#define PULL_UP_SEL_OFF 19 #define PULL_UP_ENABLE_OFF 20 #define PULL_DOWN_ENABLE_OFF 21 #define OUTPUT_VALUE_OFF 22 diff --git a/drivers/pinctrl/pinctrl-at91-pio4.c b/drivers/pinctrl/pinctrl-at91-pio4.c index 2fe40acb6a3e52377ab4bf6af9b6cd864a1b9d0a..5d360ba3abc2ec03e6a5d87f6e72af37866b8945 100644 --- a/drivers/pinctrl/pinctrl-at91-pio4.c +++ b/drivers/pinctrl/pinctrl-at91-pio4.c @@ -762,6 +762,11 @@ static int atmel_conf_pin_config_group_get(struct pinctrl_dev *pctldev, return -EINVAL; arg = 1; break; + case PIN_CONFIG_DRIVE_PUSH_PULL: + if (res & ATMEL_PIO_OPD_MASK) + return -EINVAL; + arg = 1; + break; case PIN_CONFIG_INPUT_SCHMITT_ENABLE: if (!(res & ATMEL_PIO_SCHMITT_MASK)) return -EINVAL; @@ -827,10 +832,10 @@ static int atmel_conf_pin_config_group_set(struct pinctrl_dev *pctldev, conf &= (~ATMEL_PIO_PUEN_MASK); break; case PIN_CONFIG_DRIVE_OPEN_DRAIN: - if (arg == 0) - conf &= (~ATMEL_PIO_OPD_MASK); - else - conf |= ATMEL_PIO_OPD_MASK; + conf |= ATMEL_PIO_OPD_MASK; + break; + case PIN_CONFIG_DRIVE_PUSH_PULL: + conf &= ~ATMEL_PIO_OPD_MASK; break; case PIN_CONFIG_INPUT_SCHMITT_ENABLE: if (arg == 0) @@ -948,6 +953,8 @@ static void atmel_conf_pin_config_dbg_show(struct pinctrl_dev *pctldev, seq_printf(s, "%s ", "debounce"); if (conf & ATMEL_PIO_OPD_MASK) seq_printf(s, "%s ", "open-drain"); + else + seq_printf(s, "%s ", "push-pull"); if (conf & ATMEL_PIO_SCHMITT_MASK) seq_printf(s, "%s ", "schmitt"); if (atmel_pioctrl->slew_rate_support && (conf & ATMEL_PIO_SR_MASK)) @@ -1146,6 +1153,8 @@ static int atmel_pinctrl_probe(struct platform_device *pdev) /* Pin naming convention: P(bank_name)(bank_pin_number). */ pin_desc[i].name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "P%c%u", bank + 'A', line); + if (!pin_desc[i].name) + return -ENOMEM; group->name = group_names[i] = pin_desc[i].name; group->pin = pin_desc[i].number; diff --git a/drivers/pinctrl/pinctrl-at91.c b/drivers/pinctrl/pinctrl-at91.c index 871209c2415325d116a34e4a40bf645a524be908..39956d821ad751b051b33416f7e3dd1dfd66b726 100644 --- a/drivers/pinctrl/pinctrl-at91.c +++ b/drivers/pinctrl/pinctrl-at91.c @@ -1389,8 +1389,8 @@ static int at91_pinctrl_probe(struct platform_device *pdev) char **names; names = devm_kasprintf_strarray(dev, "pio", MAX_NB_GPIO_PER_BANK); - if (!names) - return -ENOMEM; + if (IS_ERR(names)) + return PTR_ERR(names); for (j = 0; j < MAX_NB_GPIO_PER_BANK; j++, k++) { char *name = names[j]; @@ -1870,8 +1870,8 @@ static int at91_gpio_probe(struct platform_device *pdev) } names = devm_kasprintf_strarray(dev, "pio", chip->ngpio); - if (!names) - return -ENOMEM; + if (IS_ERR(names)) + return PTR_ERR(names); for (i = 0; i < chip->ngpio; i++) strreplace(names[i], '-', alias_idx + 'A'); diff --git a/drivers/pinctrl/pinctrl-axp209.c b/drivers/pinctrl/pinctrl-axp209.c index 0bc1b381a2b8ef33a4bc323b1b8b23fbabb90d27..b3ba25435c346ca816e6e2fd3b8a2086950fadf3 100644 --- a/drivers/pinctrl/pinctrl-axp209.c +++ b/drivers/pinctrl/pinctrl-axp209.c @@ -30,6 +30,11 @@ #define AXP20X_GPIO_FUNCTION_OUT_HIGH 1 #define AXP20X_GPIO_FUNCTION_INPUT 2 +#define AXP20X_GPIO3_FUNCTIONS GENMASK(2, 1) +#define AXP20X_GPIO3_FUNCTION_OUT_LOW 0 +#define AXP20X_GPIO3_FUNCTION_OUT_HIGH 2 +#define AXP20X_GPIO3_FUNCTION_INPUT 4 + #define AXP20X_FUNC_GPIO_OUT 0 #define AXP20X_FUNC_GPIO_IN 1 #define AXP20X_FUNC_LDO 2 @@ -73,6 +78,7 @@ static const struct pinctrl_pin_desc axp209_pins[] = { PINCTRL_PIN(0, "GPIO0"), PINCTRL_PIN(1, "GPIO1"), PINCTRL_PIN(2, "GPIO2"), + PINCTRL_PIN(3, "GPIO3"), }; static const struct pinctrl_pin_desc axp22x_pins[] = { @@ -130,6 +136,14 @@ static int axp20x_gpio_get(struct gpio_chip *chip, unsigned int offset) unsigned int val; int ret; + /* AXP209 has GPIO3 status sharing the settings register */ + if (offset == 3) { + ret = regmap_read(pctl->regmap, AXP20X_GPIO3_CTRL, &val); + if (ret) + return ret; + return !!(val & BIT(0)); + } + ret = regmap_read(pctl->regmap, AXP20X_GPIO20_SS, &val); if (ret) return ret; @@ -144,6 +158,17 @@ static int axp20x_gpio_get_direction(struct gpio_chip *chip, unsigned int val; int reg, ret; + /* AXP209 GPIO3 settings have a different layout */ + if (offset == 3) { + ret = regmap_read(pctl->regmap, AXP20X_GPIO3_CTRL, &val); + if (ret) + return ret; + if (val & AXP20X_GPIO3_FUNCTION_INPUT) + return GPIO_LINE_DIRECTION_IN; + + return GPIO_LINE_DIRECTION_OUT; + } + reg = axp20x_gpio_get_reg(offset); if (reg < 0) return reg; @@ -184,6 +209,15 @@ static void axp20x_gpio_set(struct gpio_chip *chip, unsigned int offset, struct axp20x_pctl *pctl = gpiochip_get_data(chip); int reg; + /* AXP209 has GPIO3 status sharing the settings register */ + if (offset == 3) { + regmap_update_bits(pctl->regmap, AXP20X_GPIO3_CTRL, + AXP20X_GPIO3_FUNCTIONS, + value ? AXP20X_GPIO3_FUNCTION_OUT_HIGH : + AXP20X_GPIO3_FUNCTION_OUT_LOW); + return; + } + reg = axp20x_gpio_get_reg(offset); if (reg < 0) return; @@ -200,6 +234,14 @@ static int axp20x_pmx_set(struct pinctrl_dev *pctldev, unsigned int offset, struct axp20x_pctl *pctl = pinctrl_dev_get_drvdata(pctldev); int reg; + /* AXP209 GPIO3 settings have a different layout */ + if (offset == 3) { + return regmap_update_bits(pctl->regmap, AXP20X_GPIO3_CTRL, + AXP20X_GPIO3_FUNCTIONS, + config == AXP20X_MUX_GPIO_OUT ? AXP20X_GPIO3_FUNCTION_OUT_LOW : + AXP20X_GPIO3_FUNCTION_INPUT); + } + reg = axp20x_gpio_get_reg(offset); if (reg < 0) return reg; diff --git a/drivers/pinctrl/pinctrl-cy8c95x0.c b/drivers/pinctrl/pinctrl-cy8c95x0.c index 564fbaabcdb806f77774e72f60ade9de4b7a83df..2ecc96691c559f88a7b160e8d27eb7e12cdc8322 100644 --- a/drivers/pinctrl/pinctrl-cy8c95x0.c +++ b/drivers/pinctrl/pinctrl-cy8c95x0.c @@ -1442,7 +1442,7 @@ static struct i2c_driver cy8c95x0_driver = { .of_match_table = cy8c95x0_dt_ids, .acpi_match_table = cy8c95x0_acpi_ids, }, - .probe_new = cy8c95x0_probe, + .probe = cy8c95x0_probe, .remove = cy8c95x0_remove, .id_table = cy8c95x0_id, .detect = cy8c95x0_detect, diff --git a/drivers/pinctrl/pinctrl-falcon.c b/drivers/pinctrl/pinctrl-falcon.c index 2eab14f86fa3f0816845d4519c9a0f775179eed3..0bf9ffbcc79f204708fa91134944629c2a724e3b 100644 --- a/drivers/pinctrl/pinctrl-falcon.c +++ b/drivers/pinctrl/pinctrl-falcon.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/pinctrl/pinctrl-mcp23s08_i2c.c b/drivers/pinctrl/pinctrl-mcp23s08_i2c.c index b635c5737e0c535426109290d8e6d90dcf9265ab..3dd1bd8e73ebc26cd5be69c4a7da8a4706798b3b 100644 --- a/drivers/pinctrl/pinctrl-mcp23s08_i2c.c +++ b/drivers/pinctrl/pinctrl-mcp23s08_i2c.c @@ -101,7 +101,7 @@ static struct i2c_driver mcp230xx_driver = { .name = "mcp230xx", .of_match_table = mcp23s08_i2c_of_match, }, - .probe_new = mcp230xx_probe, + .probe = mcp230xx_probe, .id_table = mcp230xx_id, }; diff --git a/drivers/pinctrl/pinctrl-microchip-sgpio.c b/drivers/pinctrl/pinctrl-microchip-sgpio.c index 4794602316e7dbff1cd9b2eccc2f138331bdf5ae..a60db93b61b19297ffa90617d127a40eae497bf2 100644 --- a/drivers/pinctrl/pinctrl-microchip-sgpio.c +++ b/drivers/pinctrl/pinctrl-microchip-sgpio.c @@ -719,8 +719,6 @@ static void microchip_sgpio_irq_ack(struct irq_data *data) static int microchip_sgpio_irq_set_type(struct irq_data *data, unsigned int type) { - type &= IRQ_TYPE_SENSE_MASK; - switch (type) { case IRQ_TYPE_EDGE_BOTH: irq_set_handler_locked(data, handle_edge_irq); @@ -818,6 +816,9 @@ static int microchip_sgpio_register_bank(struct device *dev, pctl_desc->name = devm_kasprintf(dev, GFP_KERNEL, "%s-%sput", dev_name(dev), bank->is_input ? "in" : "out"); + if (!pctl_desc->name) + return -ENOMEM; + pctl_desc->pctlops = &sgpio_pctl_ops; pctl_desc->pmxops = &sgpio_pmx_ops; pctl_desc->confops = &sgpio_confops; diff --git a/drivers/pinctrl/pinctrl-rk805.c b/drivers/pinctrl/pinctrl-rk805.c index 7c1f7408fb9af9e5e418e053767e501717743c4b..2639a9ee82cd0fa150c021cfa089551bafd7a096 100644 --- a/drivers/pinctrl/pinctrl-rk805.c +++ b/drivers/pinctrl/pinctrl-rk805.c @@ -1,10 +1,12 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* - * Pinctrl driver for Rockchip RK805 PMIC + * Pinctrl driver for Rockchip RK805/RK806 PMIC * * Copyright (c) 2017, Fuzhou Rockchip Electronics Co., Ltd + * Copyright (c) 2021 Rockchip Electronics Co., Ltd. * * Author: Joseph Chen + * Author: Xu Shengfei * * Based on the pinctrl-as3722 driver */ @@ -44,6 +46,7 @@ struct rk805_pin_group { /* * @reg: gpio setting register; + * @fun_reg: functions select register; * @fun_mask: functions select mask value, when set is gpio; * @dir_mask: input or output mask value, when set is output, otherwise input; * @val_mask: gpio set value, when set is level high, otherwise low; @@ -56,6 +59,7 @@ struct rk805_pin_group { */ struct rk805_pin_config { u8 reg; + u8 fun_reg; u8 fun_msk; u8 dir_msk; u8 val_msk; @@ -80,22 +84,50 @@ enum rk805_pinmux_option { RK805_PINMUX_GPIO, }; +enum rk806_pinmux_option { + RK806_PINMUX_FUN0 = 0, + RK806_PINMUX_FUN1, + RK806_PINMUX_FUN2, + RK806_PINMUX_FUN3, + RK806_PINMUX_FUN4, + RK806_PINMUX_FUN5, +}; + enum { RK805_GPIO0, RK805_GPIO1, }; +enum { + RK806_GPIO_DVS1, + RK806_GPIO_DVS2, + RK806_GPIO_DVS3 +}; + static const char *const rk805_gpio_groups[] = { "gpio0", "gpio1", }; +static const char *const rk806_gpio_groups[] = { + "gpio_pwrctrl1", + "gpio_pwrctrl2", + "gpio_pwrctrl3", +}; + /* RK805: 2 output only GPIOs */ static const struct pinctrl_pin_desc rk805_pins_desc[] = { PINCTRL_PIN(RK805_GPIO0, "gpio0"), PINCTRL_PIN(RK805_GPIO1, "gpio1"), }; +/* RK806 */ +static const struct pinctrl_pin_desc rk806_pins_desc[] = { + PINCTRL_PIN(RK806_GPIO_DVS1, "gpio_pwrctrl1"), + PINCTRL_PIN(RK806_GPIO_DVS2, "gpio_pwrctrl2"), + PINCTRL_PIN(RK806_GPIO_DVS3, "gpio_pwrctrl3"), +}; + static const struct rk805_pin_function rk805_pin_functions[] = { { .name = "gpio", @@ -105,6 +137,45 @@ static const struct rk805_pin_function rk805_pin_functions[] = { }, }; +static const struct rk805_pin_function rk806_pin_functions[] = { + { + .name = "pin_fun0", + .groups = rk806_gpio_groups, + .ngroups = ARRAY_SIZE(rk806_gpio_groups), + .mux_option = RK806_PINMUX_FUN0, + }, + { + .name = "pin_fun1", + .groups = rk806_gpio_groups, + .ngroups = ARRAY_SIZE(rk806_gpio_groups), + .mux_option = RK806_PINMUX_FUN1, + }, + { + .name = "pin_fun2", + .groups = rk806_gpio_groups, + .ngroups = ARRAY_SIZE(rk806_gpio_groups), + .mux_option = RK806_PINMUX_FUN2, + }, + { + .name = "pin_fun3", + .groups = rk806_gpio_groups, + .ngroups = ARRAY_SIZE(rk806_gpio_groups), + .mux_option = RK806_PINMUX_FUN3, + }, + { + .name = "pin_fun4", + .groups = rk806_gpio_groups, + .ngroups = ARRAY_SIZE(rk806_gpio_groups), + .mux_option = RK806_PINMUX_FUN4, + }, + { + .name = "pin_fun5", + .groups = rk806_gpio_groups, + .ngroups = ARRAY_SIZE(rk806_gpio_groups), + .mux_option = RK806_PINMUX_FUN5, + }, +}; + static const struct rk805_pin_group rk805_pin_groups[] = { { .name = "gpio0", @@ -118,6 +189,24 @@ static const struct rk805_pin_group rk805_pin_groups[] = { }, }; +static const struct rk805_pin_group rk806_pin_groups[] = { + { + .name = "gpio_pwrctrl1", + .pins = { RK806_GPIO_DVS1 }, + .npins = 1, + }, + { + .name = "gpio_pwrctrl2", + .pins = { RK806_GPIO_DVS2 }, + .npins = 1, + }, + { + .name = "gpio_pwrctrl3", + .pins = { RK806_GPIO_DVS3 }, + .npins = 1, + } +}; + #define RK805_GPIO0_VAL_MSK BIT(0) #define RK805_GPIO1_VAL_MSK BIT(1) @@ -132,6 +221,40 @@ static const struct rk805_pin_config rk805_gpio_cfgs[] = { }, }; +#define RK806_PWRCTRL1_DR BIT(0) +#define RK806_PWRCTRL2_DR BIT(1) +#define RK806_PWRCTRL3_DR BIT(2) +#define RK806_PWRCTRL1_DATA BIT(4) +#define RK806_PWRCTRL2_DATA BIT(5) +#define RK806_PWRCTRL3_DATA BIT(6) +#define RK806_PWRCTRL1_FUN GENMASK(2, 0) +#define RK806_PWRCTRL2_FUN GENMASK(6, 4) +#define RK806_PWRCTRL3_FUN GENMASK(2, 0) + +static struct rk805_pin_config rk806_gpio_cfgs[] = { + { + .fun_reg = RK806_SLEEP_CONFIG0, + .fun_msk = RK806_PWRCTRL1_FUN, + .reg = RK806_SLEEP_GPIO, + .val_msk = RK806_PWRCTRL1_DATA, + .dir_msk = RK806_PWRCTRL1_DR, + }, + { + .fun_reg = RK806_SLEEP_CONFIG0, + .fun_msk = RK806_PWRCTRL2_FUN, + .reg = RK806_SLEEP_GPIO, + .val_msk = RK806_PWRCTRL2_DATA, + .dir_msk = RK806_PWRCTRL2_DR, + }, + { + .fun_reg = RK806_SLEEP_CONFIG1, + .fun_msk = RK806_PWRCTRL3_FUN, + .reg = RK806_SLEEP_GPIO, + .val_msk = RK806_PWRCTRL3_DATA, + .dir_msk = RK806_PWRCTRL3_DR, + } +}; + /* generic gpio chip */ static int rk805_gpio_get(struct gpio_chip *chip, unsigned int offset) { @@ -289,19 +412,13 @@ static int _rk805_pinctrl_set_mux(struct pinctrl_dev *pctldev, if (!pci->pin_cfg[offset].fun_msk) return 0; - if (mux == RK805_PINMUX_GPIO) { - ret = regmap_update_bits(pci->rk808->regmap, - pci->pin_cfg[offset].reg, - pci->pin_cfg[offset].fun_msk, - pci->pin_cfg[offset].fun_msk); - if (ret) { - dev_err(pci->dev, "set gpio%d GPIO failed\n", offset); - return ret; - } - } else { - dev_err(pci->dev, "Couldn't find function mux %d\n", mux); - return -EINVAL; - } + mux <<= ffs(pci->pin_cfg[offset].fun_msk) - 1; + ret = regmap_update_bits(pci->rk808->regmap, + pci->pin_cfg[offset].fun_reg, + pci->pin_cfg[offset].fun_msk, mux); + + if (ret) + dev_err(pci->dev, "set gpio%d func%d failed\n", offset, mux); return 0; } @@ -317,6 +434,22 @@ static int rk805_pinctrl_set_mux(struct pinctrl_dev *pctldev, return _rk805_pinctrl_set_mux(pctldev, offset, mux); } +static int rk805_pinctrl_gpio_request_enable(struct pinctrl_dev *pctldev, + struct pinctrl_gpio_range *range, + unsigned int offset) +{ + struct rk805_pctrl_info *pci = pinctrl_dev_get_drvdata(pctldev); + + switch (pci->rk808->variant) { + case RK805_ID: + return _rk805_pinctrl_set_mux(pctldev, offset, RK805_PINMUX_GPIO); + case RK806_ID: + return _rk805_pinctrl_set_mux(pctldev, offset, RK806_PINMUX_FUN5); + } + + return -ENOTSUPP; +} + static int rk805_pmx_gpio_set_direction(struct pinctrl_dev *pctldev, struct pinctrl_gpio_range *range, unsigned int offset, bool input) @@ -324,13 +457,6 @@ static int rk805_pmx_gpio_set_direction(struct pinctrl_dev *pctldev, struct rk805_pctrl_info *pci = pinctrl_dev_get_drvdata(pctldev); int ret; - /* switch to gpio function */ - ret = _rk805_pinctrl_set_mux(pctldev, offset, RK805_PINMUX_GPIO); - if (ret) { - dev_err(pci->dev, "set gpio%d mux failed\n", offset); - return ret; - } - /* set direction */ if (!pci->pin_cfg[offset].dir_msk) return 0; @@ -352,6 +478,7 @@ static const struct pinmux_ops rk805_pinmux_ops = { .get_function_name = rk805_pinctrl_get_func_name, .get_function_groups = rk805_pinctrl_get_func_groups, .set_mux = rk805_pinctrl_set_mux, + .gpio_request_enable = rk805_pinctrl_gpio_request_enable, .gpio_set_direction = rk805_pmx_gpio_set_direction, }; @@ -364,6 +491,7 @@ static int rk805_pinconf_get(struct pinctrl_dev *pctldev, switch (param) { case PIN_CONFIG_OUTPUT: + case PIN_CONFIG_INPUT_ENABLE: arg = rk805_gpio_get(&pci->gpio_chip, pin); break; default: @@ -393,6 +521,12 @@ static int rk805_pinconf_set(struct pinctrl_dev *pctldev, rk805_gpio_set(&pci->gpio_chip, pin, arg); rk805_pmx_gpio_set_direction(pctldev, NULL, pin, false); break; + case PIN_CONFIG_INPUT_ENABLE: + if (pci->rk808->variant != RK805_ID && arg) { + rk805_pmx_gpio_set_direction(pctldev, NULL, pin, true); + break; + } + fallthrough; default: dev_err(pci->dev, "Properties not supported\n"); return -ENOTSUPP; @@ -448,6 +582,18 @@ static int rk805_pinctrl_probe(struct platform_device *pdev) pci->pin_cfg = rk805_gpio_cfgs; pci->gpio_chip.ngpio = ARRAY_SIZE(rk805_gpio_cfgs); break; + case RK806_ID: + pci->pins = rk806_pins_desc; + pci->num_pins = ARRAY_SIZE(rk806_pins_desc); + pci->functions = rk806_pin_functions; + pci->num_functions = ARRAY_SIZE(rk806_pin_functions); + pci->groups = rk806_pin_groups; + pci->num_pin_groups = ARRAY_SIZE(rk806_pin_groups); + pci->pinctrl_desc.pins = rk806_pins_desc; + pci->pinctrl_desc.npins = ARRAY_SIZE(rk806_pins_desc); + pci->pin_cfg = rk806_gpio_cfgs; + pci->gpio_chip.ngpio = ARRAY_SIZE(rk806_gpio_cfgs); + break; default: dev_err(&pdev->dev, "unsupported RK805 ID %lu\n", pci->rk808->variant); @@ -488,5 +634,6 @@ static struct platform_driver rk805_pinctrl_driver = { module_platform_driver(rk805_pinctrl_driver); MODULE_DESCRIPTION("RK805 pin control and GPIO driver"); +MODULE_AUTHOR("Xu Shengfei "); MODULE_AUTHOR("Joseph Chen "); MODULE_LICENSE("GPL v2"); diff --git a/drivers/pinctrl/pinctrl-sx150x.c b/drivers/pinctrl/pinctrl-sx150x.c index 7632ffc3946f2650c1cf3afb00086a0486980ba2..35faea8dfb0bee8797d2a9e5e66334db373703af 100644 --- a/drivers/pinctrl/pinctrl-sx150x.c +++ b/drivers/pinctrl/pinctrl-sx150x.c @@ -1262,7 +1262,7 @@ static struct i2c_driver sx150x_driver = { .name = "sx150x-pinctrl", .of_match_table = sx150x_of_match, }, - .probe_new = sx150x_probe, + .probe = sx150x_probe, .id_table = sx150x_id, }; diff --git a/drivers/pinctrl/pinctrl-xway.c b/drivers/pinctrl/pinctrl-xway.c index 858abb23b337819a148fdf9b6179af14c90c44c1..cf0383f575d9c9b67a5bddef13ecffc9c9e17b91 100644 --- a/drivers/pinctrl/pinctrl-xway.c +++ b/drivers/pinctrl/pinctrl-xway.c @@ -8,11 +8,11 @@ */ #include +#include #include #include #include #include -#include #include #include #include diff --git a/drivers/pinctrl/pinmux.c b/drivers/pinctrl/pinmux.c index 021382632608063c30dcec2343d9fe796c1395b0..82c750a3195236665e8f1b80694a663c244bc7a8 100644 --- a/drivers/pinctrl/pinmux.c +++ b/drivers/pinctrl/pinmux.c @@ -677,7 +677,6 @@ void pinmux_show_setting(struct seq_file *s, DEFINE_SHOW_ATTRIBUTE(pinmux_functions); DEFINE_SHOW_ATTRIBUTE(pinmux_pins); -#define PINMUX_SELECT_MAX 128 static ssize_t pinmux_select(struct file *file, const char __user *user_buf, size_t len, loff_t *ppos) { @@ -689,17 +688,9 @@ static ssize_t pinmux_select(struct file *file, const char __user *user_buf, unsigned int num_groups; int fsel, gsel, ret; - if (len > PINMUX_SELECT_MAX) - return -ENOMEM; - - buf = kzalloc(PINMUX_SELECT_MAX, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - ret = strncpy_from_user(buf, user_buf, PINMUX_SELECT_MAX); - if (ret < 0) - goto exit_free_buf; - buf[len-1] = '\0'; + buf = memdup_user_nul(user_buf, len); + if (IS_ERR(buf)) + return PTR_ERR(buf); /* remove leading and trailing spaces of input buffer */ gname = strstrip(buf); diff --git a/drivers/pinctrl/qcom/Kconfig b/drivers/pinctrl/qcom/Kconfig index e52cfab8d5ae3f66fc6762f7ec80e2988a524163..634c75336983e9fa4406ec83ee4bcec5044f7224 100644 --- a/drivers/pinctrl/qcom/Kconfig +++ b/drivers/pinctrl/qcom/Kconfig @@ -4,6 +4,8 @@ if (ARCH_QCOM || COMPILE_TEST) config PINCTRL_MSM tristate "Qualcomm core pin controller driver" depends on GPIOLIB + # OF for pinconf_generic_dt_node_to_map_group() from GENERIC_PINCONF + depends on OF select QCOM_SCM select PINMUX select PINCONF @@ -12,231 +14,7 @@ config PINCTRL_MSM select IRQ_DOMAIN_HIERARCHY select IRQ_FASTEOI_HIERARCHY_HANDLERS -config PINCTRL_APQ8064 - tristate "Qualcomm APQ8064 pin controller driver" - depends on OF - depends on ARM || COMPILE_TEST - depends on PINCTRL_MSM - help - This is the pinctrl, pinmux, pinconf and gpiolib driver for the - Qualcomm TLMM block found in the Qualcomm APQ8064 platform. - -config PINCTRL_APQ8084 - tristate "Qualcomm APQ8084 pin controller driver" - depends on OF - depends on ARM || COMPILE_TEST - depends on PINCTRL_MSM - help - This is the pinctrl, pinmux, pinconf and gpiolib driver for the - Qualcomm TLMM block found in the Qualcomm APQ8084 platform. - -config PINCTRL_IPQ4019 - tristate "Qualcomm IPQ4019 pin controller driver" - depends on OF - depends on ARM || COMPILE_TEST - depends on PINCTRL_MSM - help - This is the pinctrl, pinmux, pinconf and gpiolib driver for the - Qualcomm TLMM block found in the Qualcomm IPQ4019 platform. - -config PINCTRL_IPQ8064 - tristate "Qualcomm IPQ8064 pin controller driver" - depends on OF - depends on ARM || COMPILE_TEST - depends on PINCTRL_MSM - help - This is the pinctrl, pinmux, pinconf and gpiolib driver for the - Qualcomm TLMM block found in the Qualcomm IPQ8064 platform. - -config PINCTRL_IPQ5332 - tristate "Qualcomm Technologies Inc IPQ5332 pin controller driver" - depends on OF - depends on ARM64 || COMPILE_TEST - depends on PINCTRL_MSM - help - This is the pinctrl, pinmux, pinconf and gpiolib driver for the - Qualcomm Technologies Inc TLMM block found on the Qualcomm - Technologies Inc IPQ5332 platform. - -config PINCTRL_IPQ8074 - tristate "Qualcomm Technologies, Inc. IPQ8074 pin controller driver" - depends on OF - depends on ARM64 || COMPILE_TEST - depends on PINCTRL_MSM - help - This is the pinctrl, pinmux, pinconf and gpiolib driver for - the Qualcomm Technologies Inc. TLMM block found on the - Qualcomm Technologies Inc. IPQ8074 platform. Select this for - IPQ8074. - -config PINCTRL_IPQ6018 - tristate "Qualcomm Technologies, Inc. IPQ6018 pin controller driver" - depends on OF - depends on ARM64 || COMPILE_TEST - depends on PINCTRL_MSM - help - This is the pinctrl, pinmux, pinconf and gpiolib driver for - the Qualcomm Technologies Inc. TLMM block found on the - Qualcomm Technologies Inc. IPQ6018 platform. Select this for - IPQ6018. - -config PINCTRL_IPQ9574 - tristate "Qualcomm Technologies, Inc. IPQ9574 pin controller driver" - depends on OF || COMPILE_TEST - depends on ARM64 || COMPILE_TEST - depends on PINCTRL_MSM - help - This is the pinctrl, pinmux, pinconf and gpiolib driver for - the Qualcomm Technologies Inc. TLMM block found on the - Qualcomm Technologies Inc. IPQ9574 platform. Select this for - IPQ9574. - -config PINCTRL_MSM8226 - tristate "Qualcomm 8226 pin controller driver" - depends on OF - depends on ARM || COMPILE_TEST - depends on PINCTRL_MSM - help - This is the pinctrl, pinmux, pinconf and gpiolib driver for the - Qualcomm Technologies Inc TLMM block found on the Qualcomm - Technologies Inc MSM8226 platform. - -config PINCTRL_MSM8660 - tristate "Qualcomm 8660 pin controller driver" - depends on OF - depends on ARM || COMPILE_TEST - depends on PINCTRL_MSM - help - This is the pinctrl, pinmux, pinconf and gpiolib driver for the - Qualcomm TLMM block found in the Qualcomm 8660 platform. - -config PINCTRL_MSM8960 - tristate "Qualcomm 8960 pin controller driver" - depends on OF - depends on ARM || COMPILE_TEST - depends on PINCTRL_MSM - help - This is the pinctrl, pinmux, pinconf and gpiolib driver for the - Qualcomm TLMM block found in the Qualcomm 8960 platform. - -config PINCTRL_MDM9607 - tristate "Qualcomm 9607 pin controller driver" - depends on GPIOLIB && OF - depends on PINCTRL_MSM - help - This is the pinctrl, pinmux, pinconf and gpiolib driver for the - Qualcomm TLMM block found in the Qualcomm 9607 platform. - -config PINCTRL_MDM9615 - tristate "Qualcomm 9615 pin controller driver" - depends on OF - depends on ARM || COMPILE_TEST - depends on PINCTRL_MSM - help - This is the pinctrl, pinmux, pinconf and gpiolib driver for the - Qualcomm TLMM block found in the Qualcomm 9615 platform. - -config PINCTRL_MSM8X74 - tristate "Qualcomm 8x74 pin controller driver" - depends on OF - depends on ARM || COMPILE_TEST - depends on PINCTRL_MSM - help - This is the pinctrl, pinmux, pinconf and gpiolib driver for the - Qualcomm TLMM block found in the Qualcomm 8974 platform. - -config PINCTRL_MSM8909 - tristate "Qualcomm 8909 pin controller driver" - depends on OF - depends on ARM || COMPILE_TEST - depends on PINCTRL_MSM - help - This is the pinctrl, pinmux, pinconf and gpiolib driver for the - Qualcomm TLMM block found on the Qualcomm MSM8909 platform. - -config PINCTRL_MSM8916 - tristate "Qualcomm 8916 pin controller driver" - depends on OF - depends on PINCTRL_MSM - help - This is the pinctrl, pinmux, pinconf and gpiolib driver for the - Qualcomm TLMM block found on the Qualcomm 8916 platform. - -config PINCTRL_MSM8953 - tristate "Qualcomm 8953 pin controller driver" - depends on OF - depends on ARM64 || COMPILE_TEST - depends on PINCTRL_MSM - help - This is the pinctrl, pinmux, pinconf and gpiolib driver for the - Qualcomm TLMM block found on the Qualcomm MSM8953 platform. - The Qualcomm APQ8053, SDM450, SDM632 platforms are also - supported by this driver. - -config PINCTRL_MSM8976 - tristate "Qualcomm 8976 pin controller driver" - depends on OF - depends on ARM64 || COMPILE_TEST - depends on PINCTRL_MSM - help - This is the pinctrl, pinmux, pinconf and gpiolib driver for the - Qualcomm TLMM block found on the Qualcomm MSM8976 platform. - The Qualcomm MSM8956, APQ8056, APQ8076 platforms are also - supported by this driver. - -config PINCTRL_MSM8994 - tristate "Qualcomm 8994 pin controller driver" - depends on OF - depends on ARM64 || COMPILE_TEST - depends on PINCTRL_MSM - help - This is the pinctrl, pinmux, pinconf and gpiolib driver for the - Qualcomm TLMM block found in the Qualcomm 8994 platform. The - Qualcomm 8992 platform is also supported by this driver. - -config PINCTRL_MSM8996 - tristate "Qualcomm MSM8996 pin controller driver" - depends on OF - depends on ARM64 || COMPILE_TEST - depends on PINCTRL_MSM - help - This is the pinctrl, pinmux, pinconf and gpiolib driver for the - Qualcomm TLMM block found in the Qualcomm MSM8996 platform. - -config PINCTRL_MSM8998 - tristate "Qualcomm MSM8998 pin controller driver" - depends on OF - depends on ARM64 || COMPILE_TEST - depends on PINCTRL_MSM - help - This is the pinctrl, pinmux, pinconf and gpiolib driver for the - Qualcomm TLMM block found in the Qualcomm MSM8998 platform. - -config PINCTRL_QCM2290 - tristate "Qualcomm QCM2290 pin controller driver" - depends on OF - depends on ARM64 || COMPILE_TEST - depends on PINCTRL_MSM - help - This is the pinctrl, pinmux, pinconf and gpiolib driver for the - TLMM block found in the Qualcomm QCM2290 platform. - -config PINCTRL_QCS404 - tristate "Qualcomm QCS404 pin controller driver" - depends on OF - depends on ARM64 || COMPILE_TEST - depends on PINCTRL_MSM - help - This is the pinctrl, pinmux, pinconf and gpiolib driver for the - TLMM block found in the Qualcomm QCS404 platform. - -config PINCTRL_QDF2XXX - tristate "Qualcomm Technologies QDF2xxx pin controller driver" - depends on ACPI - depends on PINCTRL_MSM - help - This is the GPIO driver for the TLMM block found on the - Qualcomm Technologies QDF2xxx SOCs. +source "drivers/pinctrl/qcom/Kconfig.msm" config PINCTRL_QCOM_SPMI_PMIC tristate "Qualcomm SPMI PMIC pin controller driver" @@ -245,7 +23,7 @@ config PINCTRL_QCOM_SPMI_PMIC select PINMUX select PINCONF select GENERIC_PINCONF - select GPIOLIB + select GPIOLIB select GPIOLIB_IRQCHIP select IRQ_DOMAIN_HIERARCHY help @@ -260,7 +38,7 @@ config PINCTRL_QCOM_SSBI_PMIC select PINMUX select PINCONF select GENERIC_PINCONF - select GPIOLIB + select GPIOLIB select GPIOLIB_IRQCHIP select IRQ_DOMAIN_HIERARCHY help @@ -269,48 +47,20 @@ config PINCTRL_QCOM_SSBI_PMIC which are using SSBI for communication with SoC. Example PMIC's devices are pm8058 and pm8921. -config PINCTRL_QDU1000 - tristate "Qualcomm Tehcnologies Inc QDU1000/QRU1000 pin controller driver" - depends on GPIOLIB && OF - depends on ARM64 || COMPILE_TEST - depends on PINCTRL_MSM - help - This is the pinctrl, pinmux, pinconf, and gpiolib driver for the - Qualcomm Technologies Inc TLMM block found on the Qualcomm - Technologies Inc QDU1000 and QRU1000 platforms. - -config PINCTRL_SA8775P - tristate "Qualcomm Technologies Inc SA8775P pin controller driver" - depends on OF - depends on ARM64 || COMPILE_TEST - depends on PINCTRL_MSM - help - This is the pinctrl, pinmux and pinconf driver for the Qualcomm - TLMM block found on the Qualcomm SA8775P platforms. - -config PINCTRL_SC7180 - tristate "Qualcomm Technologies Inc SC7180 pin controller driver" - depends on OF - depends on ARM64 || COMPILE_TEST - depends on PINCTRL_MSM - help - This is the pinctrl, pinmux, pinconf and gpiolib driver for the - Qualcomm Technologies Inc TLMM block found on the Qualcomm - Technologies Inc SC7180 platform. - -config PINCTRL_SC7280 - tristate "Qualcomm Technologies Inc SC7280 pin controller driver" - depends on OF - depends on ARM64 || COMPILE_TEST - depends on PINCTRL_MSM +config PINCTRL_LPASS_LPI + tristate "Qualcomm Technologies Inc LPASS LPI pin controller driver" + select PINMUX + select PINCONF + select GENERIC_PINCONF + select GENERIC_PINCTRL_GROUPS + depends on GPIOLIB help This is the pinctrl, pinmux, pinconf and gpiolib driver for the - Qualcomm Technologies Inc TLMM block found on the Qualcomm - Technologies Inc SC7280 platform. + Qualcomm Technologies Inc LPASS (Low Power Audio SubSystem) LPI + (Low Power Island) found on the Qualcomm Technologies Inc SoCs. config PINCTRL_SC7280_LPASS_LPI tristate "Qualcomm Technologies Inc SC7280 LPASS LPI pin controller driver" - depends on GPIOLIB depends on ARM64 || COMPILE_TEST depends on PINCTRL_LPASS_LPI help @@ -318,149 +68,8 @@ config PINCTRL_SC7280_LPASS_LPI Qualcomm Technologies Inc LPASS (Low Power Audio SubSystem) LPI (Low Power Island) found on the Qualcomm Technologies Inc SC7280 platform. -config PINCTRL_SC8180X - tristate "Qualcomm Technologies Inc SC8180x pin controller driver" - depends on (OF || ACPI) - depends on ARM64 || COMPILE_TEST - depends on PINCTRL_MSM - help - This is the pinctrl, pinmux, pinconf and gpiolib driver for the - Qualcomm Technologies Inc TLMM block found on the Qualcomm - Technologies Inc SC8180x platform. - -config PINCTRL_SC8280XP - tristate "Qualcomm Technologies Inc SC8280xp pin controller driver" - depends on OF - depends on ARM64 || COMPILE_TEST - depends on PINCTRL_MSM - help - This is the pinctrl, pinmux, pinconf and gpiolib driver for the - Qualcomm Technologies Inc TLMM block found on the Qualcomm - Technologies Inc SC8280xp platform. - -config PINCTRL_SDM660 - tristate "Qualcomm Technologies Inc SDM660 pin controller driver" - depends on OF - depends on ARM64 || COMPILE_TEST - depends on PINCTRL_MSM - help - This is the pinctrl, pinmux, pinconf and gpiolib driver for the - Qualcomm Technologies Inc TLMM block found on the Qualcomm - Technologies Inc SDM660 platform. - -config PINCTRL_SDM670 - tristate "Qualcomm Technologies Inc SDM670 pin controller driver" - depends on OF - depends on ARM64 || COMPILE_TEST - depends on PINCTRL_MSM - help - This is the pinctrl, pinmux, pinconf and gpiolib driver for the - Qualcomm Technologies Inc TLMM block found on the Qualcomm - Technologies Inc SDM670 platform. - -config PINCTRL_SDM845 - tristate "Qualcomm Technologies Inc SDM845 pin controller driver" - depends on (OF || ACPI) - depends on ARM64 || COMPILE_TEST - depends on PINCTRL_MSM - help - This is the pinctrl, pinmux, pinconf and gpiolib driver for the - Qualcomm Technologies Inc TLMM block found on the Qualcomm - Technologies Inc SDM845 platform. - -config PINCTRL_SDX55 - tristate "Qualcomm Technologies Inc SDX55 pin controller driver" - depends on OF - depends on ARM || COMPILE_TEST - depends on PINCTRL_MSM - help - This is the pinctrl, pinmux, pinconf and gpiolib driver for the - Qualcomm Technologies Inc TLMM block found on the Qualcomm - Technologies Inc SDX55 platform. - -config PINCTRL_SM6115 - tristate "Qualcomm Technologies Inc SM6115,SM4250 pin controller driver" - depends on GPIOLIB && OF - depends on ARM64 || COMPILE_TEST - depends on PINCTRL_MSM - help - This is the pinctrl, pinmux, pinconf and gpiolib driver for the - Qualcomm Technologies Inc TLMM block found on the Qualcomm - Technologies Inc SM6115 and SM4250 platforms. - -config PINCTRL_SM6125 - tristate "Qualcomm Technologies Inc SM6125 pin controller driver" - depends on OF - depends on ARM64 || COMPILE_TEST - depends on PINCTRL_MSM - help - This is the pinctrl, pinmux, pinconf and gpiolib driver for the - Qualcomm Technologies Inc TLMM block found on the Qualcomm - Technologies Inc SM6125 platform. - -config PINCTRL_SM6350 - tristate "Qualcomm Technologies Inc SM6350 pin controller driver" - depends on GPIOLIB && OF - depends on ARM64 || COMPILE_TEST - depends on PINCTRL_MSM - help - This is the pinctrl, pinmux, pinconf and gpiolib driver for the - Qualcomm Technologies Inc TLMM block found on the Qualcomm - Technologies Inc SM6350 platform. - -config PINCTRL_SM6375 - tristate "Qualcomm Technologies Inc SM6375 pin controller driver" - depends on GPIOLIB && OF - depends on ARM64 || COMPILE_TEST - depends on PINCTRL_MSM - help - This is the pinctrl, pinmux, pinconf and gpiolib driver for the - Qualcomm Technologies Inc TLMM block found on the Qualcomm - Technologies Inc SM6375 platform. - -config PINCTRL_SDX65 - tristate "Qualcomm Technologies Inc SDX65 pin controller driver" - depends on GPIOLIB && OF - depends on ARM || COMPILE_TEST - depends on PINCTRL_MSM - help - This is the pinctrl, pinmux, pinconf and gpiolib driver for the - Qualcomm Technologies Inc TLMM block found on the Qualcomm - Technologies Inc SDX65 platform. - -config PINCTRL_SM7150 - tristate "Qualcomm Technologies Inc SM7150 pin controller driver" - depends on OF - depends on ARM64 || COMPILE_TEST - depends on PINCTRL_MSM - help - This is the pinctrl, pinmux, pinconf and gpiolib driver for the - Qualcomm Technologies Inc TLMM block found on the Qualcomm - Technologies Inc SM7150 platform. - -config PINCTRL_SM8150 - tristate "Qualcomm Technologies Inc SM8150 pin controller driver" - depends on OF - depends on ARM64 || COMPILE_TEST - depends on PINCTRL_MSM - help - This is the pinctrl, pinmux, pinconf and gpiolib driver for the - Qualcomm Technologies Inc TLMM block found on the Qualcomm - Technologies Inc SM8150 platform. - -config PINCTRL_SM8250 - tristate "Qualcomm Technologies Inc SM8250 pin controller driver" - depends on OF - depends on ARM64 || COMPILE_TEST - depends on PINCTRL_MSM - help - This is the pinctrl, pinmux, pinconf and gpiolib driver for the - Qualcomm Technologies Inc TLMM block found on the Qualcomm - Technologies Inc SM8250 platform. - config PINCTRL_SM8250_LPASS_LPI tristate "Qualcomm Technologies Inc SM8250 LPASS LPI pin controller driver" - depends on GPIOLIB depends on ARM64 || COMPILE_TEST depends on PINCTRL_LPASS_LPI help @@ -468,28 +77,8 @@ config PINCTRL_SM8250_LPASS_LPI Qualcomm Technologies Inc LPASS (Low Power Audio SubSystem) LPI (Low Power Island) found on the Qualcomm Technologies Inc SM8250 platform. -config PINCTRL_SM8350 - tristate "Qualcomm Technologies Inc SM8350 pin controller driver" - depends on ARM64 || COMPILE_TEST - depends on PINCTRL_MSM - help - This is the pinctrl, pinmux, pinconf and gpiolib driver for the - Qualcomm Technologies Inc TLMM block found on the Qualcomm - Technologies Inc SM8350 platform. - -config PINCTRL_SM8450 - tristate "Qualcomm Technologies Inc SM8450 pin controller driver" - depends on GPIOLIB && OF - depends on ARM64 || COMPILE_TEST - depends on PINCTRL_MSM - help - This is the pinctrl, pinmux, pinconf and gpiolib driver for the - Qualcomm Technologies Inc TLMM block found on the Qualcomm - Technologies Inc SM8450 platform. - config PINCTRL_SM8450_LPASS_LPI tristate "Qualcomm Technologies Inc SM8450 LPASS LPI pin controller driver" - depends on GPIOLIB depends on ARM64 || COMPILE_TEST depends on PINCTRL_LPASS_LPI help @@ -499,7 +88,6 @@ config PINCTRL_SM8450_LPASS_LPI config PINCTRL_SC8280XP_LPASS_LPI tristate "Qualcomm Technologies Inc SC8280XP LPASS LPI pin controller driver" - depends on GPIOLIB depends on ARM64 || COMPILE_TEST depends on PINCTRL_LPASS_LPI help @@ -507,19 +95,8 @@ config PINCTRL_SC8280XP_LPASS_LPI Qualcomm Technologies Inc LPASS (Low Power Audio SubSystem) LPI (Low Power Island) found on the Qualcomm Technologies Inc SC8280XP platform. -config PINCTRL_SM8550 - tristate "Qualcomm Technologies Inc SM8550 pin controller driver" - depends on GPIOLIB - depends on ARM64 || COMPILE_TEST - depends on PINCTRL_MSM - help - This is the pinctrl, pinmux, pinconf and gpiolib driver for the - Qualcomm Technologies Inc TLMM block found on the Qualcomm - Technologies Inc SM8550 platform. - config PINCTRL_SM8550_LPASS_LPI tristate "Qualcomm Technologies Inc SM8550 LPASS LPI pin controller driver" - depends on GPIOLIB depends on ARM64 || COMPILE_TEST depends on PINCTRL_LPASS_LPI help @@ -528,16 +105,4 @@ config PINCTRL_SM8550_LPASS_LPI (Low Power Island) found on the Qualcomm Technologies Inc SM8550 platform. -config PINCTRL_LPASS_LPI - tristate "Qualcomm Technologies Inc LPASS LPI pin controller driver" - select PINMUX - select PINCONF - select GENERIC_PINCONF - select GENERIC_PINCTRL_GROUPS - depends on GPIOLIB - help - This is the pinctrl, pinmux, pinconf and gpiolib driver for the - Qualcomm Technologies Inc LPASS (Low Power Audio SubSystem) LPI - (Low Power Island) found on the Qualcomm Technologies Inc SoCs. - endif diff --git a/drivers/pinctrl/qcom/Kconfig.msm b/drivers/pinctrl/qcom/Kconfig.msm new file mode 100644 index 0000000000000000000000000000000000000000..01dd7b1343541eefcb67e04c1abe6ff85ef4806b --- /dev/null +++ b/drivers/pinctrl/qcom/Kconfig.msm @@ -0,0 +1,369 @@ +# SPDX-License-Identifier: GPL-2.0-only +if PINCTRL_MSM + +config PINCTRL_APQ8064 + tristate "Qualcomm APQ8064 pin controller driver" + depends on ARM || COMPILE_TEST + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the + Qualcomm TLMM block found in the Qualcomm APQ8064 platform. + +config PINCTRL_APQ8084 + tristate "Qualcomm APQ8084 pin controller driver" + depends on ARM || COMPILE_TEST + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the + Qualcomm TLMM block found in the Qualcomm APQ8084 platform. + +config PINCTRL_IPQ4019 + tristate "Qualcomm IPQ4019 pin controller driver" + depends on ARM || COMPILE_TEST + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the + Qualcomm TLMM block found in the Qualcomm IPQ4019 platform. + +config PINCTRL_IPQ5018 + tristate "Qualcomm Technologies, Inc. IPQ5018 pin controller driver" + depends on ARM64 || COMPILE_TEST + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for + the Qualcomm Technologies Inc. TLMM block found on the + Qualcomm Technologies Inc. IPQ5018 platform. Select this for + IPQ5018. + +config PINCTRL_IPQ8064 + tristate "Qualcomm IPQ8064 pin controller driver" + depends on ARM || COMPILE_TEST + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the + Qualcomm TLMM block found in the Qualcomm IPQ8064 platform. + +config PINCTRL_IPQ5332 + tristate "Qualcomm Technologies Inc IPQ5332 pin controller driver" + depends on ARM64 || COMPILE_TEST + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the + Qualcomm Technologies Inc TLMM block found on the Qualcomm + Technologies Inc IPQ5332 platform. + +config PINCTRL_IPQ8074 + tristate "Qualcomm Technologies, Inc. IPQ8074 pin controller driver" + depends on ARM64 || COMPILE_TEST + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for + the Qualcomm Technologies Inc. TLMM block found on the + Qualcomm Technologies Inc. IPQ8074 platform. Select this for + IPQ8074. + +config PINCTRL_IPQ6018 + tristate "Qualcomm Technologies, Inc. IPQ6018 pin controller driver" + depends on ARM64 || COMPILE_TEST + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for + the Qualcomm Technologies Inc. TLMM block found on the + Qualcomm Technologies Inc. IPQ6018 platform. Select this for + IPQ6018. + +config PINCTRL_IPQ9574 + tristate "Qualcomm Technologies, Inc. IPQ9574 pin controller driver" + depends on ARM64 || COMPILE_TEST + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for + the Qualcomm Technologies Inc. TLMM block found on the + Qualcomm Technologies Inc. IPQ9574 platform. Select this for + IPQ9574. + +config PINCTRL_MSM8226 + tristate "Qualcomm 8226 pin controller driver" + depends on ARM || COMPILE_TEST + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the + Qualcomm Technologies Inc TLMM block found on the Qualcomm + Technologies Inc MSM8226 platform. + +config PINCTRL_MSM8660 + tristate "Qualcomm 8660 pin controller driver" + depends on ARM || COMPILE_TEST + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the + Qualcomm TLMM block found in the Qualcomm 8660 platform. + +config PINCTRL_MSM8960 + tristate "Qualcomm 8960 pin controller driver" + depends on ARM || COMPILE_TEST + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the + Qualcomm TLMM block found in the Qualcomm 8960 platform. + +config PINCTRL_MDM9607 + tristate "Qualcomm 9607 pin controller driver" + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the + Qualcomm TLMM block found in the Qualcomm 9607 platform. + +config PINCTRL_MDM9615 + tristate "Qualcomm 9615 pin controller driver" + depends on ARM || COMPILE_TEST + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the + Qualcomm TLMM block found in the Qualcomm 9615 platform. + +config PINCTRL_MSM8X74 + tristate "Qualcomm 8x74 pin controller driver" + depends on ARM || COMPILE_TEST + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the + Qualcomm TLMM block found in the Qualcomm 8974 platform. + +config PINCTRL_MSM8909 + tristate "Qualcomm 8909 pin controller driver" + depends on ARM || COMPILE_TEST + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the + Qualcomm TLMM block found on the Qualcomm MSM8909 platform. + +config PINCTRL_MSM8916 + tristate "Qualcomm 8916 pin controller driver" + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the + Qualcomm TLMM block found on the Qualcomm 8916 platform. + +config PINCTRL_MSM8953 + tristate "Qualcomm 8953 pin controller driver" + depends on ARM64 || COMPILE_TEST + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the + Qualcomm TLMM block found on the Qualcomm MSM8953 platform. + The Qualcomm APQ8053, SDM450, SDM632 platforms are also + supported by this driver. + +config PINCTRL_MSM8976 + tristate "Qualcomm 8976 pin controller driver" + depends on ARM64 || COMPILE_TEST + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the + Qualcomm TLMM block found on the Qualcomm MSM8976 platform. + The Qualcomm MSM8956, APQ8056, APQ8076 platforms are also + supported by this driver. + +config PINCTRL_MSM8994 + tristate "Qualcomm 8994 pin controller driver" + depends on ARM64 || COMPILE_TEST + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the + Qualcomm TLMM block found in the Qualcomm 8994 platform. The + Qualcomm 8992 platform is also supported by this driver. + +config PINCTRL_MSM8996 + tristate "Qualcomm MSM8996 pin controller driver" + depends on ARM64 || COMPILE_TEST + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the + Qualcomm TLMM block found in the Qualcomm MSM8996 platform. + +config PINCTRL_MSM8998 + tristate "Qualcomm MSM8998 pin controller driver" + depends on ARM64 || COMPILE_TEST + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the + Qualcomm TLMM block found in the Qualcomm MSM8998 platform. + +config PINCTRL_QCM2290 + tristate "Qualcomm QCM2290 pin controller driver" + depends on ARM64 || COMPILE_TEST + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the + TLMM block found in the Qualcomm QCM2290 platform. + +config PINCTRL_QCS404 + tristate "Qualcomm QCS404 pin controller driver" + depends on ARM64 || COMPILE_TEST + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the + TLMM block found in the Qualcomm QCS404 platform. + +config PINCTRL_QDF2XXX + tristate "Qualcomm Technologies QDF2xxx pin controller driver" + depends on ACPI + help + This is the GPIO driver for the TLMM block found on the + Qualcomm Technologies QDF2xxx SOCs. + +config PINCTRL_QDU1000 + tristate "Qualcomm Technologies Inc QDU1000/QRU1000 pin controller driver" + depends on ARM64 || COMPILE_TEST + help + This is the pinctrl, pinmux, pinconf, and gpiolib driver for the + Qualcomm Technologies Inc TLMM block found on the Qualcomm + Technologies Inc QDU1000 and QRU1000 platforms. + +config PINCTRL_SA8775P + tristate "Qualcomm Technologies Inc SA8775P pin controller driver" + depends on ARM64 || COMPILE_TEST + help + This is the pinctrl, pinmux and pinconf driver for the Qualcomm + TLMM block found on the Qualcomm SA8775P platforms. + +config PINCTRL_SC7180 + tristate "Qualcomm Technologies Inc SC7180 pin controller driver" + depends on ARM64 || COMPILE_TEST + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the + Qualcomm Technologies Inc TLMM block found on the Qualcomm + Technologies Inc SC7180 platform. + +config PINCTRL_SC7280 + tristate "Qualcomm Technologies Inc SC7280 pin controller driver" + depends on ARM64 || COMPILE_TEST + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the + Qualcomm Technologies Inc TLMM block found on the Qualcomm + Technologies Inc SC7280 platform. + +config PINCTRL_SC8180X + tristate "Qualcomm Technologies Inc SC8180x pin controller driver" + depends on (OF || ACPI) + depends on ARM64 || COMPILE_TEST + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the + Qualcomm Technologies Inc TLMM block found on the Qualcomm + Technologies Inc SC8180x platform. + +config PINCTRL_SC8280XP + tristate "Qualcomm Technologies Inc SC8280xp pin controller driver" + depends on ARM64 || COMPILE_TEST + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the + Qualcomm Technologies Inc TLMM block found on the Qualcomm + Technologies Inc SC8280xp platform. + +config PINCTRL_SDM660 + tristate "Qualcomm Technologies Inc SDM660 pin controller driver" + depends on ARM64 || COMPILE_TEST + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the + Qualcomm Technologies Inc TLMM block found on the Qualcomm + Technologies Inc SDM660 platform. + +config PINCTRL_SDM670 + tristate "Qualcomm Technologies Inc SDM670 pin controller driver" + depends on ARM64 || COMPILE_TEST + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the + Qualcomm Technologies Inc TLMM block found on the Qualcomm + Technologies Inc SDM670 platform. + +config PINCTRL_SDM845 + tristate "Qualcomm Technologies Inc SDM845 pin controller driver" + depends on (OF || ACPI) + depends on ARM64 || COMPILE_TEST + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the + Qualcomm Technologies Inc TLMM block found on the Qualcomm + Technologies Inc SDM845 platform. + +config PINCTRL_SDX55 + tristate "Qualcomm Technologies Inc SDX55 pin controller driver" + depends on ARM || COMPILE_TEST + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the + Qualcomm Technologies Inc TLMM block found on the Qualcomm + Technologies Inc SDX55 platform. + +config PINCTRL_SDX65 + tristate "Qualcomm Technologies Inc SDX65 pin controller driver" + depends on ARM || COMPILE_TEST + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the + Qualcomm Technologies Inc TLMM block found on the Qualcomm + Technologies Inc SDX65 platform. + +config PINCTRL_SDX75 + tristate "Qualcomm Technologies Inc SDX75 pin controller driver" + depends on ARM64 || COMPILE_TEST + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the + Qualcomm Technologies Inc TLMM block found on the Qualcomm + Technologies Inc SDX75 platform. + +config PINCTRL_SM6115 + tristate "Qualcomm Technologies Inc SM6115,SM4250 pin controller driver" + depends on ARM64 || COMPILE_TEST + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the + Qualcomm Technologies Inc TLMM block found on the Qualcomm + Technologies Inc SM6115 and SM4250 platforms. + +config PINCTRL_SM6125 + tristate "Qualcomm Technologies Inc SM6125 pin controller driver" + depends on ARM64 || COMPILE_TEST + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the + Qualcomm Technologies Inc TLMM block found on the Qualcomm + Technologies Inc SM6125 platform. + +config PINCTRL_SM6350 + tristate "Qualcomm Technologies Inc SM6350 pin controller driver" + depends on ARM64 || COMPILE_TEST + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the + Qualcomm Technologies Inc TLMM block found on the Qualcomm + Technologies Inc SM6350 platform. + +config PINCTRL_SM6375 + tristate "Qualcomm Technologies Inc SM6375 pin controller driver" + depends on ARM64 || COMPILE_TEST + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the + Qualcomm Technologies Inc TLMM block found on the Qualcomm + Technologies Inc SM6375 platform. + +config PINCTRL_SM7150 + tristate "Qualcomm Technologies Inc SM7150 pin controller driver" + depends on ARM64 || COMPILE_TEST + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the + Qualcomm Technologies Inc TLMM block found on the Qualcomm + Technologies Inc SM7150 platform. + +config PINCTRL_SM8150 + tristate "Qualcomm Technologies Inc SM8150 pin controller driver" + depends on ARM64 || COMPILE_TEST + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the + Qualcomm Technologies Inc TLMM block found on the Qualcomm + Technologies Inc SM8150 platform. + +config PINCTRL_SM8250 + tristate "Qualcomm Technologies Inc SM8250 pin controller driver" + depends on ARM64 || COMPILE_TEST + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the + Qualcomm Technologies Inc TLMM block found on the Qualcomm + Technologies Inc SM8250 platform. + +config PINCTRL_SM8350 + tristate "Qualcomm Technologies Inc SM8350 pin controller driver" + depends on ARM64 || COMPILE_TEST + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the + Qualcomm Technologies Inc TLMM block found on the Qualcomm + Technologies Inc SM8350 platform. + +config PINCTRL_SM8450 + tristate "Qualcomm Technologies Inc SM8450 pin controller driver" + depends on ARM64 || COMPILE_TEST + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the + Qualcomm Technologies Inc TLMM block found on the Qualcomm + Technologies Inc SM8450 platform. + +config PINCTRL_SM8550 + tristate "Qualcomm Technologies Inc SM8550 pin controller driver" + depends on ARM64 || COMPILE_TEST + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the + Qualcomm Technologies Inc TLMM block found on the Qualcomm + Technologies Inc SM8550 platform. + +endif diff --git a/drivers/pinctrl/qcom/Makefile b/drivers/pinctrl/qcom/Makefile index 521b021b74babecffa9b7ca31a92783bc188f169..426ddbf35f32396bac7db8a30170d1d6272b79a1 100644 --- a/drivers/pinctrl/qcom/Makefile +++ b/drivers/pinctrl/qcom/Makefile @@ -4,6 +4,7 @@ obj-$(CONFIG_PINCTRL_MSM) += pinctrl-msm.o obj-$(CONFIG_PINCTRL_APQ8064) += pinctrl-apq8064.o obj-$(CONFIG_PINCTRL_APQ8084) += pinctrl-apq8084.o obj-$(CONFIG_PINCTRL_IPQ4019) += pinctrl-ipq4019.o +obj-$(CONFIG_PINCTRL_IPQ5018) += pinctrl-ipq5018.o obj-$(CONFIG_PINCTRL_IPQ8064) += pinctrl-ipq8064.o obj-$(CONFIG_PINCTRL_IPQ5332) += pinctrl-ipq5332.o obj-$(CONFIG_PINCTRL_IPQ8074) += pinctrl-ipq8074.o @@ -40,11 +41,12 @@ obj-$(CONFIG_PINCTRL_SDM660) += pinctrl-sdm660.o obj-$(CONFIG_PINCTRL_SDM670) += pinctrl-sdm670.o obj-$(CONFIG_PINCTRL_SDM845) += pinctrl-sdm845.o obj-$(CONFIG_PINCTRL_SDX55) += pinctrl-sdx55.o +obj-$(CONFIG_PINCTRL_SDX65) += pinctrl-sdx65.o +obj-$(CONFIG_PINCTRL_SDX75) += pinctrl-sdx75.o obj-$(CONFIG_PINCTRL_SM6115) += pinctrl-sm6115.o obj-$(CONFIG_PINCTRL_SM6125) += pinctrl-sm6125.o obj-$(CONFIG_PINCTRL_SM6350) += pinctrl-sm6350.o obj-$(CONFIG_PINCTRL_SM6375) += pinctrl-sm6375.o -obj-$(CONFIG_PINCTRL_SDX65) += pinctrl-sdx65.o obj-$(CONFIG_PINCTRL_SM7150) += pinctrl-sm7150.o obj-$(CONFIG_PINCTRL_SM8150) += pinctrl-sm8150.o obj-$(CONFIG_PINCTRL_SM8250) += pinctrl-sm8250.o diff --git a/drivers/pinctrl/qcom/pinctrl-apq8064.c b/drivers/pinctrl/qcom/pinctrl-apq8064.c index d40ad4ea38191c7e38411b9926592010784e28c8..20c3b9025044515477f39bc25f0202dcca561743 100644 --- a/drivers/pinctrl/qcom/pinctrl-apq8064.c +++ b/drivers/pinctrl/qcom/pinctrl-apq8064.c @@ -6,7 +6,6 @@ #include #include #include -#include #include "pinctrl-msm.h" @@ -209,18 +208,11 @@ static const unsigned int sdc3_clk_pins[] = { 93 }; static const unsigned int sdc3_cmd_pins[] = { 94 }; static const unsigned int sdc3_data_pins[] = { 95 }; -#define FUNCTION(fname) \ - [APQ_MUX_##fname] = { \ - .name = #fname, \ - .groups = fname##_groups, \ - .ngroups = ARRAY_SIZE(fname##_groups), \ - } - #define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10) \ { \ - .name = "gpio" #id, \ - .pins = gpio##id##_pins, \ - .npins = ARRAY_SIZE(gpio##id##_pins), \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ .funcs = (int[]){ \ APQ_MUX_gpio, \ APQ_MUX_##f1, \ @@ -259,9 +251,9 @@ static const unsigned int sdc3_data_pins[] = { 95 }; #define SDC_PINGROUP(pg_name, ctl, pull, drv) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = ctl, \ .io_reg = 0, \ .intr_cfg_reg = 0, \ @@ -464,48 +456,48 @@ static const char * const usb2_hsic_groups[] = { "gpio88", "gpio89" }; -static const struct msm_function apq8064_functions[] = { - FUNCTION(cam_mclk), - FUNCTION(codec_mic_i2s), - FUNCTION(codec_spkr_i2s), - FUNCTION(gp_clk_0a), - FUNCTION(gp_clk_0b), - FUNCTION(gp_clk_1a), - FUNCTION(gp_clk_1b), - FUNCTION(gp_clk_2a), - FUNCTION(gp_clk_2b), - FUNCTION(gpio), - FUNCTION(gsbi1), - FUNCTION(gsbi2), - FUNCTION(gsbi3), - FUNCTION(gsbi4), - FUNCTION(gsbi4_cam_i2c), - FUNCTION(gsbi5), - FUNCTION(gsbi5_spi_cs1), - FUNCTION(gsbi5_spi_cs2), - FUNCTION(gsbi5_spi_cs3), - FUNCTION(gsbi6), - FUNCTION(gsbi6_spi_cs1), - FUNCTION(gsbi6_spi_cs2), - FUNCTION(gsbi6_spi_cs3), - FUNCTION(gsbi7), - FUNCTION(gsbi7_spi_cs1), - FUNCTION(gsbi7_spi_cs2), - FUNCTION(gsbi7_spi_cs3), - FUNCTION(gsbi_cam_i2c), - FUNCTION(hdmi), - FUNCTION(mi2s), - FUNCTION(riva_bt), - FUNCTION(riva_fm), - FUNCTION(riva_wlan), - FUNCTION(sdc2), - FUNCTION(sdc4), - FUNCTION(slimbus), - FUNCTION(spkr_i2s), - FUNCTION(tsif1), - FUNCTION(tsif2), - FUNCTION(usb2_hsic), - FUNCTION(ps_hold), +static const struct pinfunction apq8064_functions[] = { + APQ_PIN_FUNCTION(cam_mclk), + APQ_PIN_FUNCTION(codec_mic_i2s), + APQ_PIN_FUNCTION(codec_spkr_i2s), + APQ_PIN_FUNCTION(gp_clk_0a), + APQ_PIN_FUNCTION(gp_clk_0b), + APQ_PIN_FUNCTION(gp_clk_1a), + APQ_PIN_FUNCTION(gp_clk_1b), + APQ_PIN_FUNCTION(gp_clk_2a), + APQ_PIN_FUNCTION(gp_clk_2b), + APQ_PIN_FUNCTION(gpio), + APQ_PIN_FUNCTION(gsbi1), + APQ_PIN_FUNCTION(gsbi2), + APQ_PIN_FUNCTION(gsbi3), + APQ_PIN_FUNCTION(gsbi4), + APQ_PIN_FUNCTION(gsbi4_cam_i2c), + APQ_PIN_FUNCTION(gsbi5), + APQ_PIN_FUNCTION(gsbi5_spi_cs1), + APQ_PIN_FUNCTION(gsbi5_spi_cs2), + APQ_PIN_FUNCTION(gsbi5_spi_cs3), + APQ_PIN_FUNCTION(gsbi6), + APQ_PIN_FUNCTION(gsbi6_spi_cs1), + APQ_PIN_FUNCTION(gsbi6_spi_cs2), + APQ_PIN_FUNCTION(gsbi6_spi_cs3), + APQ_PIN_FUNCTION(gsbi7), + APQ_PIN_FUNCTION(gsbi7_spi_cs1), + APQ_PIN_FUNCTION(gsbi7_spi_cs2), + APQ_PIN_FUNCTION(gsbi7_spi_cs3), + APQ_PIN_FUNCTION(gsbi_cam_i2c), + APQ_PIN_FUNCTION(hdmi), + APQ_PIN_FUNCTION(mi2s), + APQ_PIN_FUNCTION(riva_bt), + APQ_PIN_FUNCTION(riva_fm), + APQ_PIN_FUNCTION(riva_wlan), + APQ_PIN_FUNCTION(sdc2), + APQ_PIN_FUNCTION(sdc4), + APQ_PIN_FUNCTION(slimbus), + APQ_PIN_FUNCTION(spkr_i2s), + APQ_PIN_FUNCTION(tsif1), + APQ_PIN_FUNCTION(tsif2), + APQ_PIN_FUNCTION(usb2_hsic), + APQ_PIN_FUNCTION(ps_hold), }; static const struct msm_pingroup apq8064_groups[] = { diff --git a/drivers/pinctrl/qcom/pinctrl-apq8084.c b/drivers/pinctrl/qcom/pinctrl-apq8084.c index f83153a1d62258f65a6a1913f1033f74edd8ecc6..3fc0a40762b631ad3dc15c9a7624ab705f367e74 100644 --- a/drivers/pinctrl/qcom/pinctrl-apq8084.c +++ b/drivers/pinctrl/qcom/pinctrl-apq8084.c @@ -6,7 +6,6 @@ #include #include #include -#include #include "pinctrl-msm.h" @@ -324,18 +323,11 @@ static const unsigned int sdc2_clk_pins[] = { 150 }; static const unsigned int sdc2_cmd_pins[] = { 151 }; static const unsigned int sdc2_data_pins[] = { 152 }; -#define FUNCTION(fname) \ - [APQ_MUX_##fname] = { \ - .name = #fname, \ - .groups = fname##_groups, \ - .ngroups = ARRAY_SIZE(fname##_groups), \ - } - #define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7) \ { \ - .name = "gpio" #id, \ - .pins = gpio##id##_pins, \ - .npins = ARRAY_SIZE(gpio##id##_pins), \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ .funcs = (int[]){ \ APQ_MUX_gpio, \ APQ_MUX_##f1, \ @@ -371,9 +363,9 @@ static const unsigned int sdc2_data_pins[] = { 152 }; #define SDC_PINGROUP(pg_name, ctl, pull, drv) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = ctl, \ .io_reg = 0, \ .intr_cfg_reg = 0, \ @@ -906,128 +898,128 @@ static const char * const uim_groups[] = { static const char * const uim_batt_alarm_groups[] = { "gpio102" }; -static const struct msm_function apq8084_functions[] = { - FUNCTION(adsp_ext), - FUNCTION(audio_ref), - FUNCTION(blsp_i2c1), - FUNCTION(blsp_i2c2), - FUNCTION(blsp_i2c3), - FUNCTION(blsp_i2c4), - FUNCTION(blsp_i2c5), - FUNCTION(blsp_i2c6), - FUNCTION(blsp_i2c7), - FUNCTION(blsp_i2c8), - FUNCTION(blsp_i2c9), - FUNCTION(blsp_i2c10), - FUNCTION(blsp_i2c11), - FUNCTION(blsp_i2c12), - FUNCTION(blsp_spi1), - FUNCTION(blsp_spi1_cs1), - FUNCTION(blsp_spi1_cs2), - FUNCTION(blsp_spi1_cs3), - FUNCTION(blsp_spi2), - FUNCTION(blsp_spi3), - FUNCTION(blsp_spi3_cs1), - FUNCTION(blsp_spi3_cs2), - FUNCTION(blsp_spi3_cs3), - FUNCTION(blsp_spi4), - FUNCTION(blsp_spi5), - FUNCTION(blsp_spi6), - FUNCTION(blsp_spi7), - FUNCTION(blsp_spi8), - FUNCTION(blsp_spi9), - FUNCTION(blsp_spi10), - FUNCTION(blsp_spi10_cs1), - FUNCTION(blsp_spi10_cs2), - FUNCTION(blsp_spi10_cs3), - FUNCTION(blsp_spi11), - FUNCTION(blsp_spi12), - FUNCTION(blsp_uart1), - FUNCTION(blsp_uart2), - FUNCTION(blsp_uart3), - FUNCTION(blsp_uart4), - FUNCTION(blsp_uart5), - FUNCTION(blsp_uart6), - FUNCTION(blsp_uart7), - FUNCTION(blsp_uart8), - FUNCTION(blsp_uart9), - FUNCTION(blsp_uart10), - FUNCTION(blsp_uart11), - FUNCTION(blsp_uart12), - FUNCTION(blsp_uim1), - FUNCTION(blsp_uim2), - FUNCTION(blsp_uim3), - FUNCTION(blsp_uim4), - FUNCTION(blsp_uim5), - FUNCTION(blsp_uim6), - FUNCTION(blsp_uim7), - FUNCTION(blsp_uim8), - FUNCTION(blsp_uim9), - FUNCTION(blsp_uim10), - FUNCTION(blsp_uim11), - FUNCTION(blsp_uim12), - FUNCTION(cam_mclk0), - FUNCTION(cam_mclk1), - FUNCTION(cam_mclk2), - FUNCTION(cam_mclk3), - FUNCTION(cci_async), - FUNCTION(cci_async_in0), - FUNCTION(cci_i2c0), - FUNCTION(cci_i2c1), - FUNCTION(cci_timer0), - FUNCTION(cci_timer1), - FUNCTION(cci_timer2), - FUNCTION(cci_timer3), - FUNCTION(cci_timer4), - FUNCTION(edp_hpd), - FUNCTION(gcc_gp1), - FUNCTION(gcc_gp2), - FUNCTION(gcc_gp3), - FUNCTION(gcc_obt), - FUNCTION(gcc_vtt), - FUNCTION(gp_mn), - FUNCTION(gp_pdm0), - FUNCTION(gp_pdm1), - FUNCTION(gp_pdm2), - FUNCTION(gp0_clk), - FUNCTION(gp1_clk), - FUNCTION(gpio), - FUNCTION(hdmi_cec), - FUNCTION(hdmi_ddc), - FUNCTION(hdmi_dtest), - FUNCTION(hdmi_hpd), - FUNCTION(hdmi_rcv), - FUNCTION(hsic), - FUNCTION(ldo_en), - FUNCTION(ldo_update), - FUNCTION(mdp_vsync), - FUNCTION(pci_e0), - FUNCTION(pci_e0_n), - FUNCTION(pci_e0_rst), - FUNCTION(pci_e1), - FUNCTION(pci_e1_rst), - FUNCTION(pci_e1_rst_n), - FUNCTION(pci_e1_clkreq_n), - FUNCTION(pri_mi2s), - FUNCTION(qua_mi2s), - FUNCTION(sata_act), - FUNCTION(sata_devsleep), - FUNCTION(sata_devsleep_n), - FUNCTION(sd_write), - FUNCTION(sdc_emmc_mode), - FUNCTION(sdc3), - FUNCTION(sdc4), - FUNCTION(sec_mi2s), - FUNCTION(slimbus), - FUNCTION(spdif_tx), - FUNCTION(spkr_i2s), - FUNCTION(spkr_i2s_ws), - FUNCTION(spss_geni), - FUNCTION(ter_mi2s), - FUNCTION(tsif1), - FUNCTION(tsif2), - FUNCTION(uim), - FUNCTION(uim_batt_alarm), +static const struct pinfunction apq8084_functions[] = { + APQ_PIN_FUNCTION(adsp_ext), + APQ_PIN_FUNCTION(audio_ref), + APQ_PIN_FUNCTION(blsp_i2c1), + APQ_PIN_FUNCTION(blsp_i2c2), + APQ_PIN_FUNCTION(blsp_i2c3), + APQ_PIN_FUNCTION(blsp_i2c4), + APQ_PIN_FUNCTION(blsp_i2c5), + APQ_PIN_FUNCTION(blsp_i2c6), + APQ_PIN_FUNCTION(blsp_i2c7), + APQ_PIN_FUNCTION(blsp_i2c8), + APQ_PIN_FUNCTION(blsp_i2c9), + APQ_PIN_FUNCTION(blsp_i2c10), + APQ_PIN_FUNCTION(blsp_i2c11), + APQ_PIN_FUNCTION(blsp_i2c12), + APQ_PIN_FUNCTION(blsp_spi1), + APQ_PIN_FUNCTION(blsp_spi1_cs1), + APQ_PIN_FUNCTION(blsp_spi1_cs2), + APQ_PIN_FUNCTION(blsp_spi1_cs3), + APQ_PIN_FUNCTION(blsp_spi2), + APQ_PIN_FUNCTION(blsp_spi3), + APQ_PIN_FUNCTION(blsp_spi3_cs1), + APQ_PIN_FUNCTION(blsp_spi3_cs2), + APQ_PIN_FUNCTION(blsp_spi3_cs3), + APQ_PIN_FUNCTION(blsp_spi4), + APQ_PIN_FUNCTION(blsp_spi5), + APQ_PIN_FUNCTION(blsp_spi6), + APQ_PIN_FUNCTION(blsp_spi7), + APQ_PIN_FUNCTION(blsp_spi8), + APQ_PIN_FUNCTION(blsp_spi9), + APQ_PIN_FUNCTION(blsp_spi10), + APQ_PIN_FUNCTION(blsp_spi10_cs1), + APQ_PIN_FUNCTION(blsp_spi10_cs2), + APQ_PIN_FUNCTION(blsp_spi10_cs3), + APQ_PIN_FUNCTION(blsp_spi11), + APQ_PIN_FUNCTION(blsp_spi12), + APQ_PIN_FUNCTION(blsp_uart1), + APQ_PIN_FUNCTION(blsp_uart2), + APQ_PIN_FUNCTION(blsp_uart3), + APQ_PIN_FUNCTION(blsp_uart4), + APQ_PIN_FUNCTION(blsp_uart5), + APQ_PIN_FUNCTION(blsp_uart6), + APQ_PIN_FUNCTION(blsp_uart7), + APQ_PIN_FUNCTION(blsp_uart8), + APQ_PIN_FUNCTION(blsp_uart9), + APQ_PIN_FUNCTION(blsp_uart10), + APQ_PIN_FUNCTION(blsp_uart11), + APQ_PIN_FUNCTION(blsp_uart12), + APQ_PIN_FUNCTION(blsp_uim1), + APQ_PIN_FUNCTION(blsp_uim2), + APQ_PIN_FUNCTION(blsp_uim3), + APQ_PIN_FUNCTION(blsp_uim4), + APQ_PIN_FUNCTION(blsp_uim5), + APQ_PIN_FUNCTION(blsp_uim6), + APQ_PIN_FUNCTION(blsp_uim7), + APQ_PIN_FUNCTION(blsp_uim8), + APQ_PIN_FUNCTION(blsp_uim9), + APQ_PIN_FUNCTION(blsp_uim10), + APQ_PIN_FUNCTION(blsp_uim11), + APQ_PIN_FUNCTION(blsp_uim12), + APQ_PIN_FUNCTION(cam_mclk0), + APQ_PIN_FUNCTION(cam_mclk1), + APQ_PIN_FUNCTION(cam_mclk2), + APQ_PIN_FUNCTION(cam_mclk3), + APQ_PIN_FUNCTION(cci_async), + APQ_PIN_FUNCTION(cci_async_in0), + APQ_PIN_FUNCTION(cci_i2c0), + APQ_PIN_FUNCTION(cci_i2c1), + APQ_PIN_FUNCTION(cci_timer0), + APQ_PIN_FUNCTION(cci_timer1), + APQ_PIN_FUNCTION(cci_timer2), + APQ_PIN_FUNCTION(cci_timer3), + APQ_PIN_FUNCTION(cci_timer4), + APQ_PIN_FUNCTION(edp_hpd), + APQ_PIN_FUNCTION(gcc_gp1), + APQ_PIN_FUNCTION(gcc_gp2), + APQ_PIN_FUNCTION(gcc_gp3), + APQ_PIN_FUNCTION(gcc_obt), + APQ_PIN_FUNCTION(gcc_vtt), + APQ_PIN_FUNCTION(gp_mn), + APQ_PIN_FUNCTION(gp_pdm0), + APQ_PIN_FUNCTION(gp_pdm1), + APQ_PIN_FUNCTION(gp_pdm2), + APQ_PIN_FUNCTION(gp0_clk), + APQ_PIN_FUNCTION(gp1_clk), + APQ_PIN_FUNCTION(gpio), + APQ_PIN_FUNCTION(hdmi_cec), + APQ_PIN_FUNCTION(hdmi_ddc), + APQ_PIN_FUNCTION(hdmi_dtest), + APQ_PIN_FUNCTION(hdmi_hpd), + APQ_PIN_FUNCTION(hdmi_rcv), + APQ_PIN_FUNCTION(hsic), + APQ_PIN_FUNCTION(ldo_en), + APQ_PIN_FUNCTION(ldo_update), + APQ_PIN_FUNCTION(mdp_vsync), + APQ_PIN_FUNCTION(pci_e0), + APQ_PIN_FUNCTION(pci_e0_n), + APQ_PIN_FUNCTION(pci_e0_rst), + APQ_PIN_FUNCTION(pci_e1), + APQ_PIN_FUNCTION(pci_e1_rst), + APQ_PIN_FUNCTION(pci_e1_rst_n), + APQ_PIN_FUNCTION(pci_e1_clkreq_n), + APQ_PIN_FUNCTION(pri_mi2s), + APQ_PIN_FUNCTION(qua_mi2s), + APQ_PIN_FUNCTION(sata_act), + APQ_PIN_FUNCTION(sata_devsleep), + APQ_PIN_FUNCTION(sata_devsleep_n), + APQ_PIN_FUNCTION(sd_write), + APQ_PIN_FUNCTION(sdc_emmc_mode), + APQ_PIN_FUNCTION(sdc3), + APQ_PIN_FUNCTION(sdc4), + APQ_PIN_FUNCTION(sec_mi2s), + APQ_PIN_FUNCTION(slimbus), + APQ_PIN_FUNCTION(spdif_tx), + APQ_PIN_FUNCTION(spkr_i2s), + APQ_PIN_FUNCTION(spkr_i2s_ws), + APQ_PIN_FUNCTION(spss_geni), + APQ_PIN_FUNCTION(ter_mi2s), + APQ_PIN_FUNCTION(tsif1), + APQ_PIN_FUNCTION(tsif2), + APQ_PIN_FUNCTION(uim), + APQ_PIN_FUNCTION(uim_batt_alarm), }; static const struct msm_pingroup apq8084_groups[] = { diff --git a/drivers/pinctrl/qcom/pinctrl-ipq4019.c b/drivers/pinctrl/qcom/pinctrl-ipq4019.c index 63915cb210ffbd9b0d9db4414c60863e38043629..1f7944dd829d1b9cb8c445ee075e0e29a12294b9 100644 --- a/drivers/pinctrl/qcom/pinctrl-ipq4019.c +++ b/drivers/pinctrl/qcom/pinctrl-ipq4019.c @@ -6,7 +6,6 @@ #include #include #include -#include #include "pinctrl-msm.h" @@ -216,18 +215,11 @@ DECLARE_QCA_GPIO_PINS(97); DECLARE_QCA_GPIO_PINS(98); DECLARE_QCA_GPIO_PINS(99); -#define FUNCTION(fname) \ - [qca_mux_##fname] = { \ - .name = #fname, \ - .groups = fname##_groups, \ - .ngroups = ARRAY_SIZE(fname##_groups), \ - } - #define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14) \ { \ - .name = "gpio" #id, \ - .pins = gpio##id##_pins, \ - .npins = (unsigned)ARRAY_SIZE(gpio##id##_pins), \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ .funcs = (int[]){ \ qca_mux_gpio, /* gpio mode */ \ qca_mux_##f1, \ @@ -478,51 +470,51 @@ static const char * const wifi1_groups[] = { "gpio53", "gpio56", "gpio57", "gpio58", "gpio98", }; -static const struct msm_function ipq4019_functions[] = { - FUNCTION(aud_pin), - FUNCTION(audio_pwm), - FUNCTION(blsp_i2c0), - FUNCTION(blsp_i2c1), - FUNCTION(blsp_spi0), - FUNCTION(blsp_spi1), - FUNCTION(blsp_uart0), - FUNCTION(blsp_uart1), - FUNCTION(chip_rst), - FUNCTION(gpio), - FUNCTION(i2s_rx), - FUNCTION(i2s_spdif_in), - FUNCTION(i2s_spdif_out), - FUNCTION(i2s_td), - FUNCTION(i2s_tx), - FUNCTION(jtag), - FUNCTION(led0), - FUNCTION(led1), - FUNCTION(led2), - FUNCTION(led3), - FUNCTION(led4), - FUNCTION(led5), - FUNCTION(led6), - FUNCTION(led7), - FUNCTION(led8), - FUNCTION(led9), - FUNCTION(led10), - FUNCTION(led11), - FUNCTION(mdc), - FUNCTION(mdio), - FUNCTION(pcie), - FUNCTION(pmu), - FUNCTION(prng_rosc), - FUNCTION(qpic), - FUNCTION(rgmii), - FUNCTION(rmii), - FUNCTION(sdio), - FUNCTION(smart0), - FUNCTION(smart1), - FUNCTION(smart2), - FUNCTION(smart3), - FUNCTION(tm), - FUNCTION(wifi0), - FUNCTION(wifi1), +static const struct pinfunction ipq4019_functions[] = { + QCA_PIN_FUNCTION(aud_pin), + QCA_PIN_FUNCTION(audio_pwm), + QCA_PIN_FUNCTION(blsp_i2c0), + QCA_PIN_FUNCTION(blsp_i2c1), + QCA_PIN_FUNCTION(blsp_spi0), + QCA_PIN_FUNCTION(blsp_spi1), + QCA_PIN_FUNCTION(blsp_uart0), + QCA_PIN_FUNCTION(blsp_uart1), + QCA_PIN_FUNCTION(chip_rst), + QCA_PIN_FUNCTION(gpio), + QCA_PIN_FUNCTION(i2s_rx), + QCA_PIN_FUNCTION(i2s_spdif_in), + QCA_PIN_FUNCTION(i2s_spdif_out), + QCA_PIN_FUNCTION(i2s_td), + QCA_PIN_FUNCTION(i2s_tx), + QCA_PIN_FUNCTION(jtag), + QCA_PIN_FUNCTION(led0), + QCA_PIN_FUNCTION(led1), + QCA_PIN_FUNCTION(led2), + QCA_PIN_FUNCTION(led3), + QCA_PIN_FUNCTION(led4), + QCA_PIN_FUNCTION(led5), + QCA_PIN_FUNCTION(led6), + QCA_PIN_FUNCTION(led7), + QCA_PIN_FUNCTION(led8), + QCA_PIN_FUNCTION(led9), + QCA_PIN_FUNCTION(led10), + QCA_PIN_FUNCTION(led11), + QCA_PIN_FUNCTION(mdc), + QCA_PIN_FUNCTION(mdio), + QCA_PIN_FUNCTION(pcie), + QCA_PIN_FUNCTION(pmu), + QCA_PIN_FUNCTION(prng_rosc), + QCA_PIN_FUNCTION(qpic), + QCA_PIN_FUNCTION(rgmii), + QCA_PIN_FUNCTION(rmii), + QCA_PIN_FUNCTION(sdio), + QCA_PIN_FUNCTION(smart0), + QCA_PIN_FUNCTION(smart1), + QCA_PIN_FUNCTION(smart2), + QCA_PIN_FUNCTION(smart3), + QCA_PIN_FUNCTION(tm), + QCA_PIN_FUNCTION(wifi0), + QCA_PIN_FUNCTION(wifi1), }; static const struct msm_pingroup ipq4019_groups[] = { diff --git a/drivers/pinctrl/qcom/pinctrl-ipq5018.c b/drivers/pinctrl/qcom/pinctrl-ipq5018.c new file mode 100644 index 0000000000000000000000000000000000000000..ed58f750f1eb7fd8370f18fbaec228f79521bfb0 --- /dev/null +++ b/drivers/pinctrl/qcom/pinctrl-ipq5018.c @@ -0,0 +1,783 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2019-2021, 2023 The Linux Foundation. All rights reserved. + */ + +#include +#include +#include + +#include "pinctrl-msm.h" + +#define REG_SIZE 0x1000 +#define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9) \ + { \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ + .funcs = (int[]){ \ + msm_mux_gpio, /* gpio mode */ \ + msm_mux_##f1, \ + msm_mux_##f2, \ + msm_mux_##f3, \ + msm_mux_##f4, \ + msm_mux_##f5, \ + msm_mux_##f6, \ + msm_mux_##f7, \ + msm_mux_##f8, \ + msm_mux_##f9 \ + }, \ + .nfuncs = 10, \ + .ctl_reg = REG_SIZE * id, \ + .io_reg = 0x4 + REG_SIZE * id, \ + .intr_cfg_reg = 0x8 + REG_SIZE * id, \ + .intr_status_reg = 0xc + REG_SIZE * id, \ + .intr_target_reg = 0x8 + REG_SIZE * id, \ + .mux_bit = 2, \ + .pull_bit = 0, \ + .drv_bit = 6, \ + .oe_bit = 9, \ + .in_bit = 0, \ + .out_bit = 1, \ + .intr_enable_bit = 0, \ + .intr_status_bit = 0, \ + .intr_target_bit = 5, \ + .intr_target_kpss_val = 3, \ + .intr_raw_status_bit = 4, \ + .intr_polarity_bit = 1, \ + .intr_detection_bit = 2, \ + .intr_detection_width = 2, \ + } + +static const struct pinctrl_pin_desc ipq5018_pins[] = { + PINCTRL_PIN(0, "GPIO_0"), + PINCTRL_PIN(1, "GPIO_1"), + PINCTRL_PIN(2, "GPIO_2"), + PINCTRL_PIN(3, "GPIO_3"), + PINCTRL_PIN(4, "GPIO_4"), + PINCTRL_PIN(5, "GPIO_5"), + PINCTRL_PIN(6, "GPIO_6"), + PINCTRL_PIN(7, "GPIO_7"), + PINCTRL_PIN(8, "GPIO_8"), + PINCTRL_PIN(9, "GPIO_9"), + PINCTRL_PIN(10, "GPIO_10"), + PINCTRL_PIN(11, "GPIO_11"), + PINCTRL_PIN(12, "GPIO_12"), + PINCTRL_PIN(13, "GPIO_13"), + PINCTRL_PIN(14, "GPIO_14"), + PINCTRL_PIN(15, "GPIO_15"), + PINCTRL_PIN(16, "GPIO_16"), + PINCTRL_PIN(17, "GPIO_17"), + PINCTRL_PIN(18, "GPIO_18"), + PINCTRL_PIN(19, "GPIO_19"), + PINCTRL_PIN(20, "GPIO_20"), + PINCTRL_PIN(21, "GPIO_21"), + PINCTRL_PIN(22, "GPIO_22"), + PINCTRL_PIN(23, "GPIO_23"), + PINCTRL_PIN(24, "GPIO_24"), + PINCTRL_PIN(25, "GPIO_25"), + PINCTRL_PIN(26, "GPIO_26"), + PINCTRL_PIN(27, "GPIO_27"), + PINCTRL_PIN(28, "GPIO_28"), + PINCTRL_PIN(29, "GPIO_29"), + PINCTRL_PIN(30, "GPIO_30"), + PINCTRL_PIN(31, "GPIO_31"), + PINCTRL_PIN(32, "GPIO_32"), + PINCTRL_PIN(33, "GPIO_33"), + PINCTRL_PIN(34, "GPIO_34"), + PINCTRL_PIN(35, "GPIO_35"), + PINCTRL_PIN(36, "GPIO_36"), + PINCTRL_PIN(37, "GPIO_37"), + PINCTRL_PIN(38, "GPIO_38"), + PINCTRL_PIN(39, "GPIO_39"), + PINCTRL_PIN(40, "GPIO_40"), + PINCTRL_PIN(41, "GPIO_41"), + PINCTRL_PIN(42, "GPIO_42"), + PINCTRL_PIN(43, "GPIO_43"), + PINCTRL_PIN(44, "GPIO_44"), + PINCTRL_PIN(45, "GPIO_45"), + PINCTRL_PIN(46, "GPIO_46"), +}; + +#define DECLARE_MSM_GPIO_PINS(pin) \ + static const unsigned int gpio##pin##_pins[] = { pin } +DECLARE_MSM_GPIO_PINS(0); +DECLARE_MSM_GPIO_PINS(1); +DECLARE_MSM_GPIO_PINS(2); +DECLARE_MSM_GPIO_PINS(3); +DECLARE_MSM_GPIO_PINS(4); +DECLARE_MSM_GPIO_PINS(5); +DECLARE_MSM_GPIO_PINS(6); +DECLARE_MSM_GPIO_PINS(7); +DECLARE_MSM_GPIO_PINS(8); +DECLARE_MSM_GPIO_PINS(9); +DECLARE_MSM_GPIO_PINS(10); +DECLARE_MSM_GPIO_PINS(11); +DECLARE_MSM_GPIO_PINS(12); +DECLARE_MSM_GPIO_PINS(13); +DECLARE_MSM_GPIO_PINS(14); +DECLARE_MSM_GPIO_PINS(15); +DECLARE_MSM_GPIO_PINS(16); +DECLARE_MSM_GPIO_PINS(17); +DECLARE_MSM_GPIO_PINS(18); +DECLARE_MSM_GPIO_PINS(19); +DECLARE_MSM_GPIO_PINS(20); +DECLARE_MSM_GPIO_PINS(21); +DECLARE_MSM_GPIO_PINS(22); +DECLARE_MSM_GPIO_PINS(23); +DECLARE_MSM_GPIO_PINS(24); +DECLARE_MSM_GPIO_PINS(25); +DECLARE_MSM_GPIO_PINS(26); +DECLARE_MSM_GPIO_PINS(27); +DECLARE_MSM_GPIO_PINS(28); +DECLARE_MSM_GPIO_PINS(29); +DECLARE_MSM_GPIO_PINS(30); +DECLARE_MSM_GPIO_PINS(31); +DECLARE_MSM_GPIO_PINS(32); +DECLARE_MSM_GPIO_PINS(33); +DECLARE_MSM_GPIO_PINS(34); +DECLARE_MSM_GPIO_PINS(35); +DECLARE_MSM_GPIO_PINS(36); +DECLARE_MSM_GPIO_PINS(37); +DECLARE_MSM_GPIO_PINS(38); +DECLARE_MSM_GPIO_PINS(39); +DECLARE_MSM_GPIO_PINS(40); +DECLARE_MSM_GPIO_PINS(41); +DECLARE_MSM_GPIO_PINS(42); +DECLARE_MSM_GPIO_PINS(43); +DECLARE_MSM_GPIO_PINS(44); +DECLARE_MSM_GPIO_PINS(45); +DECLARE_MSM_GPIO_PINS(46); + +enum ipq5018_functions { + msm_mux_atest_char, + msm_mux_audio_pdm0, + msm_mux_audio_pdm1, + msm_mux_audio_rxbclk, + msm_mux_audio_rxd, + msm_mux_audio_rxfsync, + msm_mux_audio_rxmclk, + msm_mux_audio_txbclk, + msm_mux_audio_txd, + msm_mux_audio_txfsync, + msm_mux_audio_txmclk, + msm_mux_blsp0_i2c, + msm_mux_blsp0_spi, + msm_mux_blsp0_uart0, + msm_mux_blsp0_uart1, + msm_mux_blsp1_i2c0, + msm_mux_blsp1_i2c1, + msm_mux_blsp1_spi0, + msm_mux_blsp1_spi1, + msm_mux_blsp1_uart0, + msm_mux_blsp1_uart1, + msm_mux_blsp1_uart2, + msm_mux_blsp2_i2c0, + msm_mux_blsp2_i2c1, + msm_mux_blsp2_spi, + msm_mux_blsp2_spi0, + msm_mux_blsp2_spi1, + msm_mux_btss, + msm_mux_burn0, + msm_mux_burn1, + msm_mux_cri_trng, + msm_mux_cri_trng0, + msm_mux_cri_trng1, + msm_mux_cxc_clk, + msm_mux_cxc_data, + msm_mux_dbg_out, + msm_mux_eud_gpio, + msm_mux_gcc_plltest, + msm_mux_gcc_tlmm, + msm_mux_gpio, + msm_mux_led0, + msm_mux_led2, + msm_mux_mac0, + msm_mux_mac1, + msm_mux_mdc, + msm_mux_mdio, + msm_mux_pcie0_clk, + msm_mux_pcie0_wake, + msm_mux_pcie1_clk, + msm_mux_pcie1_wake, + msm_mux_pll_test, + msm_mux_prng_rosc, + msm_mux_pwm0, + msm_mux_pwm1, + msm_mux_pwm2, + msm_mux_pwm3, + msm_mux_qdss_cti_trig_in_a0, + msm_mux_qdss_cti_trig_in_a1, + msm_mux_qdss_cti_trig_in_b0, + msm_mux_qdss_cti_trig_in_b1, + msm_mux_qdss_cti_trig_out_a0, + msm_mux_qdss_cti_trig_out_a1, + msm_mux_qdss_cti_trig_out_b0, + msm_mux_qdss_cti_trig_out_b1, + msm_mux_qdss_traceclk_a, + msm_mux_qdss_traceclk_b, + msm_mux_qdss_tracectl_a, + msm_mux_qdss_tracectl_b, + msm_mux_qdss_tracedata_a, + msm_mux_qdss_tracedata_b, + msm_mux_qspi_clk, + msm_mux_qspi_cs, + msm_mux_qspi_data, + msm_mux_reset_out, + msm_mux_sdc1_clk, + msm_mux_sdc1_cmd, + msm_mux_sdc1_data, + msm_mux_wci_txd, + msm_mux_wci_rxd, + msm_mux_wsa_swrm, + msm_mux_wsi_clk3, + msm_mux_wsi_data3, + msm_mux_wsis_reset, + msm_mux_xfem, + msm_mux__, +}; + +static const char * const atest_char_groups[] = { + "gpio0", "gpio1", "gpio2", "gpio3", "gpio37", +}; + +static const char * const _groups[] = { + "gpio0", "gpio1", "gpio2", "gpio3", "gpio4", "gpio5", "gpio6", "gpio7", + "gpio8", "gpio9", "gpio10", "gpio11", "gpio12", "gpio13", "gpio14", + "gpio15", "gpio16", "gpio17", "gpio18", "gpio19", "gpio20", "gpio21", + "gpio22", "gpio23", "gpio24", "gpio25", "gpio26", "gpio27", "gpio28", + "gpio29", "gpio30", "gpio31", "gpio32", "gpio33", "gpio34", "gpio35", + "gpio36", "gpio37", "gpio38", "gpio39", "gpio40", "gpio41", "gpio42", + "gpio43", "gpio44", "gpio45", "gpio46", +}; + +static const char * const wci_txd_groups[] = { + "gpio0", "gpio1", "gpio2", "gpio3", + "gpio42", "gpio43", "gpio44", "gpio45", +}; + +static const char * const wci_rxd_groups[] = { + "gpio0", "gpio1", "gpio2", "gpio3", + "gpio42", "gpio43", "gpio44", "gpio45", +}; + +static const char * const xfem_groups[] = { + "gpio0", "gpio1", "gpio2", "gpio3", + "gpio42", "gpio43", "gpio44", "gpio45", +}; + +static const char * const qdss_cti_trig_out_a0_groups[] = { + "gpio0", +}; + +static const char * const qdss_cti_trig_in_a0_groups[] = { + "gpio1", +}; + +static const char * const qdss_cti_trig_out_a1_groups[] = { + "gpio2", +}; + +static const char * const qdss_cti_trig_in_a1_groups[] = { + "gpio3", +}; + +static const char * const sdc1_data_groups[] = { + "gpio4", "gpio5", "gpio6", "gpio7", +}; + +static const char * const qspi_data_groups[] = { + "gpio4", + "gpio5", + "gpio6", + "gpio7", +}; + +static const char * const blsp1_spi1_groups[] = { + "gpio4", "gpio5", "gpio6", "gpio7", +}; + +static const char * const btss_groups[] = { + "gpio4", "gpio5", "gpio6", "gpio7", "gpio8", "gpio17", "gpio18", + "gpio19", "gpio23", "gpio24", "gpio25", "gpio26", "gpio27", "gpio28", +}; + +static const char * const dbg_out_groups[] = { + "gpio4", +}; + +static const char * const qdss_traceclk_a_groups[] = { + "gpio4", +}; + +static const char * const burn0_groups[] = { + "gpio4", +}; + +static const char * const cxc_clk_groups[] = { + "gpio5", +}; + +static const char * const blsp1_i2c1_groups[] = { + "gpio5", "gpio6", +}; + +static const char * const qdss_tracectl_a_groups[] = { + "gpio5", +}; + +static const char * const burn1_groups[] = { + "gpio5", +}; + +static const char * const cxc_data_groups[] = { + "gpio6", +}; + +static const char * const qdss_tracedata_a_groups[] = { + "gpio6", "gpio7", "gpio8", "gpio9", "gpio10", "gpio11", "gpio12", + "gpio13", "gpio14", "gpio15", "gpio16", "gpio17", "gpio18", "gpio19", + "gpio20", "gpio21", +}; + +static const char * const mac0_groups[] = { + "gpio7", +}; + +static const char * const sdc1_cmd_groups[] = { + "gpio8", +}; + +static const char * const qspi_cs_groups[] = { + "gpio8", +}; + +static const char * const mac1_groups[] = { + "gpio8", +}; + +static const char * const sdc1_clk_groups[] = { + "gpio9", +}; + +static const char * const qspi_clk_groups[] = { + "gpio9", +}; + +static const char * const blsp0_spi_groups[] = { + "gpio10", "gpio11", "gpio12", "gpio13", +}; + +static const char * const blsp1_uart0_groups[] = { + "gpio10", "gpio11", "gpio12", "gpio13", +}; + +static const char * const gcc_plltest_groups[] = { + "gpio10", "gpio12", +}; + +static const char * const gcc_tlmm_groups[] = { + "gpio11", +}; + +static const char * const blsp0_i2c_groups[] = { + "gpio12", "gpio13", +}; + +static const char * const pcie0_clk_groups[] = { + "gpio14", +}; + +static const char * const cri_trng0_groups[] = { + "gpio14", +}; + +static const char * const cri_trng1_groups[] = { + "gpio15", +}; + +static const char * const pcie0_wake_groups[] = { + "gpio16", +}; + +static const char * const cri_trng_groups[] = { + "gpio16", +}; + +static const char * const pcie1_clk_groups[] = { + "gpio17", +}; + +static const char * const prng_rosc_groups[] = { + "gpio17", +}; + +static const char * const blsp1_spi0_groups[] = { + "gpio18", "gpio19", "gpio20", "gpio21", +}; + +static const char * const pcie1_wake_groups[] = { + "gpio19", +}; + +static const char * const blsp1_i2c0_groups[] = { + "gpio19", "gpio20", +}; + +static const char * const blsp0_uart0_groups[] = { + "gpio20", "gpio21", +}; + +static const char * const pll_test_groups[] = { + "gpio22", +}; + +static const char * const eud_gpio_groups[] = { + "gpio22", "gpio31", "gpio32", "gpio33", "gpio34", "gpio35", +}; + +static const char * const audio_rxmclk_groups[] = { + "gpio23", "gpio23", +}; + +static const char * const audio_pdm0_groups[] = { + "gpio23", "gpio24", +}; + +static const char * const blsp2_spi1_groups[] = { + "gpio23", "gpio24", "gpio25", "gpio26", +}; + +static const char * const blsp1_uart2_groups[] = { + "gpio23", "gpio24", "gpio25", "gpio26", +}; + +static const char * const qdss_tracedata_b_groups[] = { + "gpio23", "gpio24", "gpio25", "gpio26", "gpio27", "gpio28", "gpio29", + "gpio30", "gpio31", "gpio32", "gpio33", "gpio34", "gpio35", "gpio36", + "gpio37", "gpio38", +}; + +static const char * const audio_rxbclk_groups[] = { + "gpio24", +}; + +static const char * const audio_rxfsync_groups[] = { + "gpio25", +}; + +static const char * const audio_pdm1_groups[] = { + "gpio25", "gpio26", +}; + +static const char * const blsp2_i2c1_groups[] = { + "gpio25", "gpio26", +}; + +static const char * const audio_rxd_groups[] = { + "gpio26", +}; + +static const char * const audio_txmclk_groups[] = { + "gpio27", "gpio27", +}; + +static const char * const wsa_swrm_groups[] = { + "gpio27", "gpio28", +}; + +static const char * const blsp2_spi_groups[] = { + "gpio27", +}; + +static const char * const audio_txbclk_groups[] = { + "gpio28", +}; + +static const char * const blsp0_uart1_groups[] = { + "gpio28", "gpio29", +}; + +static const char * const audio_txfsync_groups[] = { + "gpio29", +}; + +static const char * const audio_txd_groups[] = { + "gpio30", +}; + +static const char * const wsis_reset_groups[] = { + "gpio30", +}; + +static const char * const blsp2_spi0_groups[] = { + "gpio31", "gpio32", "gpio33", "gpio34", +}; + +static const char * const blsp1_uart1_groups[] = { + "gpio31", "gpio32", "gpio33", "gpio34", +}; + +static const char * const blsp2_i2c0_groups[] = { + "gpio33", "gpio34", +}; + +static const char * const mdc_groups[] = { + "gpio36", +}; + +static const char * const wsi_clk3_groups[] = { + "gpio36", +}; + +static const char * const mdio_groups[] = { + "gpio37", +}; + +static const char * const wsi_data3_groups[] = { + "gpio37", +}; + +static const char * const qdss_traceclk_b_groups[] = { + "gpio39", +}; + +static const char * const reset_out_groups[] = { + "gpio40", +}; + +static const char * const qdss_tracectl_b_groups[] = { + "gpio40", +}; + +static const char * const pwm0_groups[] = { + "gpio42", +}; + +static const char * const qdss_cti_trig_out_b0_groups[] = { + "gpio42", +}; + +static const char * const pwm1_groups[] = { + "gpio43", +}; + +static const char * const qdss_cti_trig_in_b0_groups[] = { + "gpio43", +}; + +static const char * const pwm2_groups[] = { + "gpio44", +}; + +static const char * const qdss_cti_trig_out_b1_groups[] = { + "gpio44", +}; + +static const char * const pwm3_groups[] = { + "gpio45", +}; + +static const char * const qdss_cti_trig_in_b1_groups[] = { + "gpio45", +}; + +static const char * const led0_groups[] = { + "gpio46", "gpio30", "gpio10", +}; + +static const char * const led2_groups[] = { + "gpio30", +}; + +static const char * const gpio_groups[] = { + "gpio0", "gpio1", "gpio2", "gpio3", "gpio4", "gpio5", "gpio6", "gpio7", + "gpio8", "gpio9", "gpio10", "gpio11", "gpio12", "gpio13", "gpio14", + "gpio15", "gpio16", "gpio17", "gpio18", "gpio19", "gpio20", "gpio21", + "gpio22", "gpio23", "gpio24", "gpio25", "gpio26", "gpio27", "gpio28", + "gpio29", "gpio30", "gpio31", "gpio32", "gpio33", "gpio34", "gpio35", + "gpio36", "gpio37", "gpio38", "gpio39", "gpio40", "gpio41", "gpio42", + "gpio43", "gpio44", "gpio45", "gpio46", +}; + +static const struct pinfunction ipq5018_functions[] = { + MSM_PIN_FUNCTION(atest_char), + MSM_PIN_FUNCTION(audio_pdm0), + MSM_PIN_FUNCTION(audio_pdm1), + MSM_PIN_FUNCTION(audio_rxbclk), + MSM_PIN_FUNCTION(audio_rxd), + MSM_PIN_FUNCTION(audio_rxfsync), + MSM_PIN_FUNCTION(audio_rxmclk), + MSM_PIN_FUNCTION(audio_txbclk), + MSM_PIN_FUNCTION(audio_txd), + MSM_PIN_FUNCTION(audio_txfsync), + MSM_PIN_FUNCTION(audio_txmclk), + MSM_PIN_FUNCTION(blsp0_i2c), + MSM_PIN_FUNCTION(blsp0_spi), + MSM_PIN_FUNCTION(blsp0_uart0), + MSM_PIN_FUNCTION(blsp0_uart1), + MSM_PIN_FUNCTION(blsp1_i2c0), + MSM_PIN_FUNCTION(blsp1_i2c1), + MSM_PIN_FUNCTION(blsp1_spi0), + MSM_PIN_FUNCTION(blsp1_spi1), + MSM_PIN_FUNCTION(blsp1_uart0), + MSM_PIN_FUNCTION(blsp1_uart1), + MSM_PIN_FUNCTION(blsp1_uart2), + MSM_PIN_FUNCTION(blsp2_i2c0), + MSM_PIN_FUNCTION(blsp2_i2c1), + MSM_PIN_FUNCTION(blsp2_spi), + MSM_PIN_FUNCTION(blsp2_spi0), + MSM_PIN_FUNCTION(blsp2_spi1), + MSM_PIN_FUNCTION(btss), + MSM_PIN_FUNCTION(burn0), + MSM_PIN_FUNCTION(burn1), + MSM_PIN_FUNCTION(cri_trng), + MSM_PIN_FUNCTION(cri_trng0), + MSM_PIN_FUNCTION(cri_trng1), + MSM_PIN_FUNCTION(cxc_clk), + MSM_PIN_FUNCTION(cxc_data), + MSM_PIN_FUNCTION(dbg_out), + MSM_PIN_FUNCTION(eud_gpio), + MSM_PIN_FUNCTION(gcc_plltest), + MSM_PIN_FUNCTION(gcc_tlmm), + MSM_PIN_FUNCTION(gpio), + MSM_PIN_FUNCTION(led0), + MSM_PIN_FUNCTION(led2), + MSM_PIN_FUNCTION(mac0), + MSM_PIN_FUNCTION(mac1), + MSM_PIN_FUNCTION(mdc), + MSM_PIN_FUNCTION(mdio), + MSM_PIN_FUNCTION(pcie0_clk), + MSM_PIN_FUNCTION(pcie0_wake), + MSM_PIN_FUNCTION(pcie1_clk), + MSM_PIN_FUNCTION(pcie1_wake), + MSM_PIN_FUNCTION(pll_test), + MSM_PIN_FUNCTION(prng_rosc), + MSM_PIN_FUNCTION(pwm0), + MSM_PIN_FUNCTION(pwm1), + MSM_PIN_FUNCTION(pwm2), + MSM_PIN_FUNCTION(pwm3), + MSM_PIN_FUNCTION(qdss_cti_trig_in_a0), + MSM_PIN_FUNCTION(qdss_cti_trig_in_a1), + MSM_PIN_FUNCTION(qdss_cti_trig_in_b0), + MSM_PIN_FUNCTION(qdss_cti_trig_in_b1), + MSM_PIN_FUNCTION(qdss_cti_trig_out_a0), + MSM_PIN_FUNCTION(qdss_cti_trig_out_a1), + MSM_PIN_FUNCTION(qdss_cti_trig_out_b0), + MSM_PIN_FUNCTION(qdss_cti_trig_out_b1), + MSM_PIN_FUNCTION(qdss_traceclk_a), + MSM_PIN_FUNCTION(qdss_traceclk_b), + MSM_PIN_FUNCTION(qdss_tracectl_a), + MSM_PIN_FUNCTION(qdss_tracectl_b), + MSM_PIN_FUNCTION(qdss_tracedata_a), + MSM_PIN_FUNCTION(qdss_tracedata_b), + MSM_PIN_FUNCTION(qspi_clk), + MSM_PIN_FUNCTION(qspi_cs), + MSM_PIN_FUNCTION(qspi_data), + MSM_PIN_FUNCTION(reset_out), + MSM_PIN_FUNCTION(sdc1_clk), + MSM_PIN_FUNCTION(sdc1_cmd), + MSM_PIN_FUNCTION(sdc1_data), + MSM_PIN_FUNCTION(wci_txd), + MSM_PIN_FUNCTION(wci_rxd), + MSM_PIN_FUNCTION(wsa_swrm), + MSM_PIN_FUNCTION(wsi_clk3), + MSM_PIN_FUNCTION(wsi_data3), + MSM_PIN_FUNCTION(wsis_reset), + MSM_PIN_FUNCTION(xfem), +}; + +static const struct msm_pingroup ipq5018_groups[] = { + PINGROUP(0, atest_char, _, qdss_cti_trig_out_a0, wci_txd, wci_rxd, xfem, _, _, _), + PINGROUP(1, atest_char, _, qdss_cti_trig_in_a0, wci_txd, wci_rxd, xfem, _, _, _), + PINGROUP(2, atest_char, _, qdss_cti_trig_out_a1, wci_txd, wci_rxd, xfem, _, _, _), + PINGROUP(3, atest_char, _, qdss_cti_trig_in_a1, wci_txd, wci_rxd, xfem, _, _, _), + PINGROUP(4, sdc1_data, qspi_data, blsp1_spi1, btss, dbg_out, qdss_traceclk_a, _, burn0, _), + PINGROUP(5, sdc1_data, qspi_data, cxc_clk, blsp1_spi1, blsp1_i2c1, btss, _, qdss_tracectl_a, _), + PINGROUP(6, sdc1_data, qspi_data, cxc_data, blsp1_spi1, blsp1_i2c1, btss, _, qdss_tracedata_a, _), + PINGROUP(7, sdc1_data, qspi_data, mac0, blsp1_spi1, btss, _, qdss_tracedata_a, _, _), + PINGROUP(8, sdc1_cmd, qspi_cs, mac1, btss, _, qdss_tracedata_a, _, _, _), + PINGROUP(9, sdc1_clk, qspi_clk, _, qdss_tracedata_a, _, _, _, _, _), + PINGROUP(10, blsp0_spi, blsp1_uart0, led0, gcc_plltest, qdss_tracedata_a, _, _, _, _), + PINGROUP(11, blsp0_spi, blsp1_uart0, _, gcc_tlmm, qdss_tracedata_a, _, _, _, _), + PINGROUP(12, blsp0_spi, blsp0_i2c, blsp1_uart0, _, gcc_plltest, qdss_tracedata_a, _, _, _), + PINGROUP(13, blsp0_spi, blsp0_i2c, blsp1_uart0, _, qdss_tracedata_a, _, _, _, _), + PINGROUP(14, pcie0_clk, _, _, cri_trng0, qdss_tracedata_a, _, _, _, _), + PINGROUP(15, _, _, cri_trng1, qdss_tracedata_a, _, _, _, _, _), + PINGROUP(16, pcie0_wake, _, _, cri_trng, qdss_tracedata_a, _, _, _, _), + PINGROUP(17, pcie1_clk, btss, _, prng_rosc, qdss_tracedata_a, _, _, _, _), + PINGROUP(18, blsp1_spi0, btss, _, qdss_tracedata_a, _, _, _, _, _), + PINGROUP(19, pcie1_wake, blsp1_spi0, blsp1_i2c0, btss, _, qdss_tracedata_a, _, _, _), + PINGROUP(20, blsp0_uart0, blsp1_spi0, blsp1_i2c0, _, qdss_tracedata_a, _, _, _, _), + PINGROUP(21, blsp0_uart0, blsp1_spi0, _, qdss_tracedata_a, _, _, _, _, _), + PINGROUP(22, _, pll_test, eud_gpio, _, _, _, _, _, _), + PINGROUP(23, audio_rxmclk, audio_pdm0, audio_rxmclk, blsp2_spi1, blsp1_uart2, btss, _, qdss_tracedata_b, _), + PINGROUP(24, audio_rxbclk, audio_pdm0, blsp2_spi1, blsp1_uart2, btss, _, qdss_tracedata_b, _, _), + PINGROUP(25, audio_rxfsync, audio_pdm1, blsp2_i2c1, blsp2_spi1, blsp1_uart2, btss, _, qdss_tracedata_b, _), + PINGROUP(26, audio_rxd, audio_pdm1, blsp2_i2c1, blsp2_spi1, blsp1_uart2, btss, _, qdss_tracedata_b, _), + PINGROUP(27, audio_txmclk, wsa_swrm, audio_txmclk, blsp2_spi, btss, _, qdss_tracedata_b, _, _), + PINGROUP(28, audio_txbclk, wsa_swrm, blsp0_uart1, btss, qdss_tracedata_b, _, _, _, _), + PINGROUP(29, audio_txfsync, _, blsp0_uart1, _, qdss_tracedata_b, _, _, _, _), + PINGROUP(30, audio_txd, led2, led0, _, _, _, _, _, _), + PINGROUP(31, blsp2_spi0, blsp1_uart1, _, qdss_tracedata_b, eud_gpio, _, _, _, _), + PINGROUP(32, blsp2_spi0, blsp1_uart1, _, qdss_tracedata_b, eud_gpio, _, _, _, _), + PINGROUP(33, blsp2_i2c0, blsp2_spi0, blsp1_uart1, _, qdss_tracedata_b, eud_gpio, _, _, _), + PINGROUP(34, blsp2_i2c0, blsp2_spi0, blsp1_uart1, _, qdss_tracedata_b, eud_gpio, _, _, _), + PINGROUP(35, _, qdss_tracedata_b, eud_gpio, _, _, _, _, _, _), + PINGROUP(36, mdc, qdss_tracedata_b, _, wsi_clk3, _, _, _, _, _), + PINGROUP(37, mdio, atest_char, qdss_tracedata_b, _, wsi_data3, _, _, _, _), + PINGROUP(38, qdss_tracedata_b, _, _, _, _, _, _, _, _), + PINGROUP(39, qdss_traceclk_b, _, _, _, _, _, _, _, _), + PINGROUP(40, reset_out, qdss_tracectl_b, _, _, _, _, _, _, _), + PINGROUP(41, _, _, _, _, _, _, _, _, _), + PINGROUP(42, pwm0, qdss_cti_trig_out_b0, wci_txd, wci_rxd, xfem, _, _, _, _), + PINGROUP(43, pwm1, qdss_cti_trig_in_b0, wci_txd, wci_rxd, xfem, _, _, _, _), + PINGROUP(44, pwm2, qdss_cti_trig_out_b1, wci_txd, wci_rxd, xfem, _, _, _, _), + PINGROUP(45, pwm3, qdss_cti_trig_in_b1, wci_txd, wci_rxd, xfem, _, _, _, _), + PINGROUP(46, led0, _, _, _, _, _, _, _, _), +}; + +static const struct msm_pinctrl_soc_data ipq5018_pinctrl = { + .pins = ipq5018_pins, + .npins = ARRAY_SIZE(ipq5018_pins), + .functions = ipq5018_functions, + .nfunctions = ARRAY_SIZE(ipq5018_functions), + .groups = ipq5018_groups, + .ngroups = ARRAY_SIZE(ipq5018_groups), + .ngpios = 47, +}; + +static int ipq5018_pinctrl_probe(struct platform_device *pdev) +{ + return msm_pinctrl_probe(pdev, &ipq5018_pinctrl); +} + +static const struct of_device_id ipq5018_pinctrl_of_match[] = { + { .compatible = "qcom,ipq5018-tlmm", }, + { } +}; +MODULE_DEVICE_TABLE(of, ipq5018_pinctrl_of_match); + +static struct platform_driver ipq5018_pinctrl_driver = { + .driver = { + .name = "ipq5018-tlmm", + .of_match_table = ipq5018_pinctrl_of_match, + }, + .probe = ipq5018_pinctrl_probe, + .remove = msm_pinctrl_remove, +}; + +static int __init ipq5018_pinctrl_init(void) +{ + return platform_driver_register(&ipq5018_pinctrl_driver); +} +arch_initcall(ipq5018_pinctrl_init); + +static void __exit ipq5018_pinctrl_exit(void) +{ + platform_driver_unregister(&ipq5018_pinctrl_driver); +} +module_exit(ipq5018_pinctrl_exit); + +MODULE_DESCRIPTION("Qualcomm Technologies Inc ipq5018 pinctrl driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/pinctrl/qcom/pinctrl-ipq5332.c b/drivers/pinctrl/qcom/pinctrl-ipq5332.c index e78d11292f424d1f7ac12fc271a0e16fc31d11a5..625f8014051f6acf8e6f91d48d0406b8c2bd8caf 100644 --- a/drivers/pinctrl/qcom/pinctrl-ipq5332.c +++ b/drivers/pinctrl/qcom/pinctrl-ipq5332.c @@ -6,23 +6,15 @@ #include #include #include -#include #include "pinctrl-msm.h" -#define FUNCTION(fname) \ - [msm_mux_##fname] = { \ - .name = #fname, \ - .groups = fname##_groups, \ - .ngroups = ARRAY_SIZE(fname##_groups), \ - } - #define REG_SIZE 0x1000 #define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9) \ { \ - .name = "gpio" #id, \ - .pins = gpio##id##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(gpio##id##_pins), \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ .funcs = (int[]){ \ msm_mux_gpio, /* gpio mode */ \ msm_mux_##f1, \ @@ -661,102 +653,102 @@ static const char * const xfem_groups[] = { "gpio0", "gpio1", "gpio2", "gpio3", "gpio4", "gpio5", "gpio6", "gpio7", }; -static const struct msm_function ipq5332_functions[] = { - FUNCTION(atest_char), - FUNCTION(atest_char0), - FUNCTION(atest_char1), - FUNCTION(atest_char2), - FUNCTION(atest_char3), - FUNCTION(atest_tic), - FUNCTION(audio_pri), - FUNCTION(audio_pri0), - FUNCTION(audio_pri1), - FUNCTION(audio_sec), - FUNCTION(audio_sec0), - FUNCTION(audio_sec1), - FUNCTION(blsp0_i2c), - FUNCTION(blsp0_spi), - FUNCTION(blsp0_uart0), - FUNCTION(blsp0_uart1), - FUNCTION(blsp1_i2c0), - FUNCTION(blsp1_i2c1), - FUNCTION(blsp1_spi0), - FUNCTION(blsp1_spi1), - FUNCTION(blsp1_uart0), - FUNCTION(blsp1_uart1), - FUNCTION(blsp1_uart2), - FUNCTION(blsp2_i2c0), - FUNCTION(blsp2_i2c1), - FUNCTION(blsp2_spi), - FUNCTION(blsp2_spi0), - FUNCTION(blsp2_spi1), - FUNCTION(core_voltage), - FUNCTION(cri_trng0), - FUNCTION(cri_trng1), - FUNCTION(cri_trng2), - FUNCTION(cri_trng3), - FUNCTION(cxc_clk), - FUNCTION(cxc_data), - FUNCTION(dbg_out), - FUNCTION(gcc_plltest), - FUNCTION(gcc_tlmm), - FUNCTION(gpio), - FUNCTION(lock_det), - FUNCTION(mac0), - FUNCTION(mac1), - FUNCTION(mdc0), - FUNCTION(mdc1), - FUNCTION(mdio0), - FUNCTION(mdio1), - FUNCTION(pc), - FUNCTION(pcie0_clk), - FUNCTION(pcie0_wake), - FUNCTION(pcie1_clk), - FUNCTION(pcie1_wake), - FUNCTION(pcie2_clk), - FUNCTION(pcie2_wake), - FUNCTION(pll_test), - FUNCTION(prng_rosc0), - FUNCTION(prng_rosc1), - FUNCTION(prng_rosc2), - FUNCTION(prng_rosc3), - FUNCTION(pta), - FUNCTION(pwm0), - FUNCTION(pwm1), - FUNCTION(pwm2), - FUNCTION(pwm3), - FUNCTION(qdss_cti_trig_in_a0), - FUNCTION(qdss_cti_trig_in_a1), - FUNCTION(qdss_cti_trig_in_b0), - FUNCTION(qdss_cti_trig_in_b1), - FUNCTION(qdss_cti_trig_out_a0), - FUNCTION(qdss_cti_trig_out_a1), - FUNCTION(qdss_cti_trig_out_b0), - FUNCTION(qdss_cti_trig_out_b1), - FUNCTION(qdss_traceclk_a), - FUNCTION(qdss_traceclk_b), - FUNCTION(qdss_tracectl_a), - FUNCTION(qdss_tracectl_b), - FUNCTION(qdss_tracedata_a), - FUNCTION(qdss_tracedata_b), - FUNCTION(qspi_data), - FUNCTION(qspi_clk), - FUNCTION(qspi_cs), - FUNCTION(resout), - FUNCTION(rx0), - FUNCTION(rx1), - FUNCTION(sdc_data), - FUNCTION(sdc_clk), - FUNCTION(sdc_cmd), - FUNCTION(tsens_max), - FUNCTION(wci_txd), - FUNCTION(wci_rxd), - FUNCTION(wsi_clk), - FUNCTION(wsi_clk3), - FUNCTION(wsi_data), - FUNCTION(wsi_data3), - FUNCTION(wsis_reset), - FUNCTION(xfem), +static const struct pinfunction ipq5332_functions[] = { + MSM_PIN_FUNCTION(atest_char), + MSM_PIN_FUNCTION(atest_char0), + MSM_PIN_FUNCTION(atest_char1), + MSM_PIN_FUNCTION(atest_char2), + MSM_PIN_FUNCTION(atest_char3), + MSM_PIN_FUNCTION(atest_tic), + MSM_PIN_FUNCTION(audio_pri), + MSM_PIN_FUNCTION(audio_pri0), + MSM_PIN_FUNCTION(audio_pri1), + MSM_PIN_FUNCTION(audio_sec), + MSM_PIN_FUNCTION(audio_sec0), + MSM_PIN_FUNCTION(audio_sec1), + MSM_PIN_FUNCTION(blsp0_i2c), + MSM_PIN_FUNCTION(blsp0_spi), + MSM_PIN_FUNCTION(blsp0_uart0), + MSM_PIN_FUNCTION(blsp0_uart1), + MSM_PIN_FUNCTION(blsp1_i2c0), + MSM_PIN_FUNCTION(blsp1_i2c1), + MSM_PIN_FUNCTION(blsp1_spi0), + MSM_PIN_FUNCTION(blsp1_spi1), + MSM_PIN_FUNCTION(blsp1_uart0), + MSM_PIN_FUNCTION(blsp1_uart1), + MSM_PIN_FUNCTION(blsp1_uart2), + MSM_PIN_FUNCTION(blsp2_i2c0), + MSM_PIN_FUNCTION(blsp2_i2c1), + MSM_PIN_FUNCTION(blsp2_spi), + MSM_PIN_FUNCTION(blsp2_spi0), + MSM_PIN_FUNCTION(blsp2_spi1), + MSM_PIN_FUNCTION(core_voltage), + MSM_PIN_FUNCTION(cri_trng0), + MSM_PIN_FUNCTION(cri_trng1), + MSM_PIN_FUNCTION(cri_trng2), + MSM_PIN_FUNCTION(cri_trng3), + MSM_PIN_FUNCTION(cxc_clk), + MSM_PIN_FUNCTION(cxc_data), + MSM_PIN_FUNCTION(dbg_out), + MSM_PIN_FUNCTION(gcc_plltest), + MSM_PIN_FUNCTION(gcc_tlmm), + MSM_PIN_FUNCTION(gpio), + MSM_PIN_FUNCTION(lock_det), + MSM_PIN_FUNCTION(mac0), + MSM_PIN_FUNCTION(mac1), + MSM_PIN_FUNCTION(mdc0), + MSM_PIN_FUNCTION(mdc1), + MSM_PIN_FUNCTION(mdio0), + MSM_PIN_FUNCTION(mdio1), + MSM_PIN_FUNCTION(pc), + MSM_PIN_FUNCTION(pcie0_clk), + MSM_PIN_FUNCTION(pcie0_wake), + MSM_PIN_FUNCTION(pcie1_clk), + MSM_PIN_FUNCTION(pcie1_wake), + MSM_PIN_FUNCTION(pcie2_clk), + MSM_PIN_FUNCTION(pcie2_wake), + MSM_PIN_FUNCTION(pll_test), + MSM_PIN_FUNCTION(prng_rosc0), + MSM_PIN_FUNCTION(prng_rosc1), + MSM_PIN_FUNCTION(prng_rosc2), + MSM_PIN_FUNCTION(prng_rosc3), + MSM_PIN_FUNCTION(pta), + MSM_PIN_FUNCTION(pwm0), + MSM_PIN_FUNCTION(pwm1), + MSM_PIN_FUNCTION(pwm2), + MSM_PIN_FUNCTION(pwm3), + MSM_PIN_FUNCTION(qdss_cti_trig_in_a0), + MSM_PIN_FUNCTION(qdss_cti_trig_in_a1), + MSM_PIN_FUNCTION(qdss_cti_trig_in_b0), + MSM_PIN_FUNCTION(qdss_cti_trig_in_b1), + MSM_PIN_FUNCTION(qdss_cti_trig_out_a0), + MSM_PIN_FUNCTION(qdss_cti_trig_out_a1), + MSM_PIN_FUNCTION(qdss_cti_trig_out_b0), + MSM_PIN_FUNCTION(qdss_cti_trig_out_b1), + MSM_PIN_FUNCTION(qdss_traceclk_a), + MSM_PIN_FUNCTION(qdss_traceclk_b), + MSM_PIN_FUNCTION(qdss_tracectl_a), + MSM_PIN_FUNCTION(qdss_tracectl_b), + MSM_PIN_FUNCTION(qdss_tracedata_a), + MSM_PIN_FUNCTION(qdss_tracedata_b), + MSM_PIN_FUNCTION(qspi_data), + MSM_PIN_FUNCTION(qspi_clk), + MSM_PIN_FUNCTION(qspi_cs), + MSM_PIN_FUNCTION(resout), + MSM_PIN_FUNCTION(rx0), + MSM_PIN_FUNCTION(rx1), + MSM_PIN_FUNCTION(sdc_data), + MSM_PIN_FUNCTION(sdc_clk), + MSM_PIN_FUNCTION(sdc_cmd), + MSM_PIN_FUNCTION(tsens_max), + MSM_PIN_FUNCTION(wci_txd), + MSM_PIN_FUNCTION(wci_rxd), + MSM_PIN_FUNCTION(wsi_clk), + MSM_PIN_FUNCTION(wsi_clk3), + MSM_PIN_FUNCTION(wsi_data), + MSM_PIN_FUNCTION(wsi_data3), + MSM_PIN_FUNCTION(wsis_reset), + MSM_PIN_FUNCTION(xfem), }; static const struct msm_pingroup ipq5332_groups[] = { diff --git a/drivers/pinctrl/qcom/pinctrl-ipq6018.c b/drivers/pinctrl/qcom/pinctrl-ipq6018.c index ec50a3b4bd1615e7c02ed64d8dfbe91d83b4eca0..0ad08647dbcdf0b1fa21a618310f150a1bde2fae 100644 --- a/drivers/pinctrl/qcom/pinctrl-ipq6018.c +++ b/drivers/pinctrl/qcom/pinctrl-ipq6018.c @@ -6,23 +6,15 @@ #include #include #include -#include #include "pinctrl-msm.h" -#define FUNCTION(fname) \ - [msm_mux_##fname] = { \ - .name = #fname, \ - .groups = fname##_groups, \ - .ngroups = ARRAY_SIZE(fname##_groups), \ - } - #define REG_SIZE 0x1000 #define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9) \ { \ - .name = "gpio" #id, \ - .pins = gpio##id##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(gpio##id##_pins), \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ .funcs = (int[]){ \ msm_mux_gpio, /* gpio mode */ \ msm_mux_##f1, \ @@ -854,129 +846,129 @@ static const char * const gpio_groups[] = { "gpio78", "gpio79", }; -static const struct msm_function ipq6018_functions[] = { - FUNCTION(atest_char), - FUNCTION(atest_char0), - FUNCTION(atest_char1), - FUNCTION(atest_char2), - FUNCTION(atest_char3), - FUNCTION(audio0), - FUNCTION(audio1), - FUNCTION(audio2), - FUNCTION(audio3), - FUNCTION(audio_rxbclk), - FUNCTION(audio_rxfsync), - FUNCTION(audio_rxmclk), - FUNCTION(audio_rxmclkin), - FUNCTION(audio_txbclk), - FUNCTION(audio_txfsync), - FUNCTION(audio_txmclk), - FUNCTION(audio_txmclkin), - FUNCTION(blsp0_i2c), - FUNCTION(blsp0_spi), - FUNCTION(blsp0_uart), - FUNCTION(blsp1_i2c), - FUNCTION(blsp1_spi), - FUNCTION(blsp1_uart), - FUNCTION(blsp2_i2c), - FUNCTION(blsp2_spi), - FUNCTION(blsp2_uart), - FUNCTION(blsp3_i2c), - FUNCTION(blsp3_spi), - FUNCTION(blsp3_uart), - FUNCTION(blsp4_i2c), - FUNCTION(blsp4_spi), - FUNCTION(blsp4_uart), - FUNCTION(blsp5_i2c), - FUNCTION(blsp5_uart), - FUNCTION(burn0), - FUNCTION(burn1), - FUNCTION(cri_trng), - FUNCTION(cri_trng0), - FUNCTION(cri_trng1), - FUNCTION(cxc0), - FUNCTION(cxc1), - FUNCTION(dbg_out), - FUNCTION(gcc_plltest), - FUNCTION(gcc_tlmm), - FUNCTION(gpio), - FUNCTION(lpass_aud), - FUNCTION(lpass_aud0), - FUNCTION(lpass_aud1), - FUNCTION(lpass_aud2), - FUNCTION(lpass_pcm), - FUNCTION(lpass_pdm), - FUNCTION(mac00), - FUNCTION(mac01), - FUNCTION(mac10), - FUNCTION(mac11), - FUNCTION(mac12), - FUNCTION(mac13), - FUNCTION(mac20), - FUNCTION(mac21), - FUNCTION(mdc), - FUNCTION(mdio), - FUNCTION(pcie0_clk), - FUNCTION(pcie0_rst), - FUNCTION(pcie0_wake), - FUNCTION(prng_rosc), - FUNCTION(pta1_0), - FUNCTION(pta1_1), - FUNCTION(pta1_2), - FUNCTION(pta2_0), - FUNCTION(pta2_1), - FUNCTION(pta2_2), - FUNCTION(pwm00), - FUNCTION(pwm01), - FUNCTION(pwm02), - FUNCTION(pwm03), - FUNCTION(pwm04), - FUNCTION(pwm10), - FUNCTION(pwm11), - FUNCTION(pwm12), - FUNCTION(pwm13), - FUNCTION(pwm14), - FUNCTION(pwm20), - FUNCTION(pwm21), - FUNCTION(pwm22), - FUNCTION(pwm23), - FUNCTION(pwm24), - FUNCTION(pwm30), - FUNCTION(pwm31), - FUNCTION(pwm32), - FUNCTION(pwm33), - FUNCTION(qdss_cti_trig_in_a0), - FUNCTION(qdss_cti_trig_in_a1), - FUNCTION(qdss_cti_trig_out_a0), - FUNCTION(qdss_cti_trig_out_a1), - FUNCTION(qdss_cti_trig_in_b0), - FUNCTION(qdss_cti_trig_in_b1), - FUNCTION(qdss_cti_trig_out_b0), - FUNCTION(qdss_cti_trig_out_b1), - FUNCTION(qdss_traceclk_a), - FUNCTION(qdss_tracectl_a), - FUNCTION(qdss_tracedata_a), - FUNCTION(qdss_traceclk_b), - FUNCTION(qdss_tracectl_b), - FUNCTION(qdss_tracedata_b), - FUNCTION(qpic_pad), - FUNCTION(rx0), - FUNCTION(rx1), - FUNCTION(rx_swrm), - FUNCTION(rx_swrm0), - FUNCTION(rx_swrm1), - FUNCTION(sd_card), - FUNCTION(sd_write), - FUNCTION(tsens_max), - FUNCTION(tx_swrm), - FUNCTION(tx_swrm0), - FUNCTION(tx_swrm1), - FUNCTION(tx_swrm2), - FUNCTION(wci20), - FUNCTION(wci21), - FUNCTION(wci22), - FUNCTION(wci23), - FUNCTION(wsa_swrm), +static const struct pinfunction ipq6018_functions[] = { + MSM_PIN_FUNCTION(atest_char), + MSM_PIN_FUNCTION(atest_char0), + MSM_PIN_FUNCTION(atest_char1), + MSM_PIN_FUNCTION(atest_char2), + MSM_PIN_FUNCTION(atest_char3), + MSM_PIN_FUNCTION(audio0), + MSM_PIN_FUNCTION(audio1), + MSM_PIN_FUNCTION(audio2), + MSM_PIN_FUNCTION(audio3), + MSM_PIN_FUNCTION(audio_rxbclk), + MSM_PIN_FUNCTION(audio_rxfsync), + MSM_PIN_FUNCTION(audio_rxmclk), + MSM_PIN_FUNCTION(audio_rxmclkin), + MSM_PIN_FUNCTION(audio_txbclk), + MSM_PIN_FUNCTION(audio_txfsync), + MSM_PIN_FUNCTION(audio_txmclk), + MSM_PIN_FUNCTION(audio_txmclkin), + MSM_PIN_FUNCTION(blsp0_i2c), + MSM_PIN_FUNCTION(blsp0_spi), + MSM_PIN_FUNCTION(blsp0_uart), + MSM_PIN_FUNCTION(blsp1_i2c), + MSM_PIN_FUNCTION(blsp1_spi), + MSM_PIN_FUNCTION(blsp1_uart), + MSM_PIN_FUNCTION(blsp2_i2c), + MSM_PIN_FUNCTION(blsp2_spi), + MSM_PIN_FUNCTION(blsp2_uart), + MSM_PIN_FUNCTION(blsp3_i2c), + MSM_PIN_FUNCTION(blsp3_spi), + MSM_PIN_FUNCTION(blsp3_uart), + MSM_PIN_FUNCTION(blsp4_i2c), + MSM_PIN_FUNCTION(blsp4_spi), + MSM_PIN_FUNCTION(blsp4_uart), + MSM_PIN_FUNCTION(blsp5_i2c), + MSM_PIN_FUNCTION(blsp5_uart), + MSM_PIN_FUNCTION(burn0), + MSM_PIN_FUNCTION(burn1), + MSM_PIN_FUNCTION(cri_trng), + MSM_PIN_FUNCTION(cri_trng0), + MSM_PIN_FUNCTION(cri_trng1), + MSM_PIN_FUNCTION(cxc0), + MSM_PIN_FUNCTION(cxc1), + MSM_PIN_FUNCTION(dbg_out), + MSM_PIN_FUNCTION(gcc_plltest), + MSM_PIN_FUNCTION(gcc_tlmm), + MSM_PIN_FUNCTION(gpio), + MSM_PIN_FUNCTION(lpass_aud), + MSM_PIN_FUNCTION(lpass_aud0), + MSM_PIN_FUNCTION(lpass_aud1), + MSM_PIN_FUNCTION(lpass_aud2), + MSM_PIN_FUNCTION(lpass_pcm), + MSM_PIN_FUNCTION(lpass_pdm), + MSM_PIN_FUNCTION(mac00), + MSM_PIN_FUNCTION(mac01), + MSM_PIN_FUNCTION(mac10), + MSM_PIN_FUNCTION(mac11), + MSM_PIN_FUNCTION(mac12), + MSM_PIN_FUNCTION(mac13), + MSM_PIN_FUNCTION(mac20), + MSM_PIN_FUNCTION(mac21), + MSM_PIN_FUNCTION(mdc), + MSM_PIN_FUNCTION(mdio), + MSM_PIN_FUNCTION(pcie0_clk), + MSM_PIN_FUNCTION(pcie0_rst), + MSM_PIN_FUNCTION(pcie0_wake), + MSM_PIN_FUNCTION(prng_rosc), + MSM_PIN_FUNCTION(pta1_0), + MSM_PIN_FUNCTION(pta1_1), + MSM_PIN_FUNCTION(pta1_2), + MSM_PIN_FUNCTION(pta2_0), + MSM_PIN_FUNCTION(pta2_1), + MSM_PIN_FUNCTION(pta2_2), + MSM_PIN_FUNCTION(pwm00), + MSM_PIN_FUNCTION(pwm01), + MSM_PIN_FUNCTION(pwm02), + MSM_PIN_FUNCTION(pwm03), + MSM_PIN_FUNCTION(pwm04), + MSM_PIN_FUNCTION(pwm10), + MSM_PIN_FUNCTION(pwm11), + MSM_PIN_FUNCTION(pwm12), + MSM_PIN_FUNCTION(pwm13), + MSM_PIN_FUNCTION(pwm14), + MSM_PIN_FUNCTION(pwm20), + MSM_PIN_FUNCTION(pwm21), + MSM_PIN_FUNCTION(pwm22), + MSM_PIN_FUNCTION(pwm23), + MSM_PIN_FUNCTION(pwm24), + MSM_PIN_FUNCTION(pwm30), + MSM_PIN_FUNCTION(pwm31), + MSM_PIN_FUNCTION(pwm32), + MSM_PIN_FUNCTION(pwm33), + MSM_PIN_FUNCTION(qdss_cti_trig_in_a0), + MSM_PIN_FUNCTION(qdss_cti_trig_in_a1), + MSM_PIN_FUNCTION(qdss_cti_trig_out_a0), + MSM_PIN_FUNCTION(qdss_cti_trig_out_a1), + MSM_PIN_FUNCTION(qdss_cti_trig_in_b0), + MSM_PIN_FUNCTION(qdss_cti_trig_in_b1), + MSM_PIN_FUNCTION(qdss_cti_trig_out_b0), + MSM_PIN_FUNCTION(qdss_cti_trig_out_b1), + MSM_PIN_FUNCTION(qdss_traceclk_a), + MSM_PIN_FUNCTION(qdss_tracectl_a), + MSM_PIN_FUNCTION(qdss_tracedata_a), + MSM_PIN_FUNCTION(qdss_traceclk_b), + MSM_PIN_FUNCTION(qdss_tracectl_b), + MSM_PIN_FUNCTION(qdss_tracedata_b), + MSM_PIN_FUNCTION(qpic_pad), + MSM_PIN_FUNCTION(rx0), + MSM_PIN_FUNCTION(rx1), + MSM_PIN_FUNCTION(rx_swrm), + MSM_PIN_FUNCTION(rx_swrm0), + MSM_PIN_FUNCTION(rx_swrm1), + MSM_PIN_FUNCTION(sd_card), + MSM_PIN_FUNCTION(sd_write), + MSM_PIN_FUNCTION(tsens_max), + MSM_PIN_FUNCTION(tx_swrm), + MSM_PIN_FUNCTION(tx_swrm0), + MSM_PIN_FUNCTION(tx_swrm1), + MSM_PIN_FUNCTION(tx_swrm2), + MSM_PIN_FUNCTION(wci20), + MSM_PIN_FUNCTION(wci21), + MSM_PIN_FUNCTION(wci22), + MSM_PIN_FUNCTION(wci23), + MSM_PIN_FUNCTION(wsa_swrm), }; static const struct msm_pingroup ipq6018_groups[] = { diff --git a/drivers/pinctrl/qcom/pinctrl-ipq8064.c b/drivers/pinctrl/qcom/pinctrl-ipq8064.c index ac717ee38416a6f1eb26394a9a0cf8423d40f180..e2bb94e86aef6e0055860794a1c64649c722aebc 100644 --- a/drivers/pinctrl/qcom/pinctrl-ipq8064.c +++ b/drivers/pinctrl/qcom/pinctrl-ipq8064.c @@ -6,7 +6,6 @@ #include #include #include -#include #include "pinctrl-msm.h" @@ -161,18 +160,11 @@ static const unsigned int sdc3_clk_pins[] = { 69 }; static const unsigned int sdc3_cmd_pins[] = { 70 }; static const unsigned int sdc3_data_pins[] = { 71 }; -#define FUNCTION(fname) \ - [IPQ_MUX_##fname] = { \ - .name = #fname, \ - .groups = fname##_groups, \ - .ngroups = ARRAY_SIZE(fname##_groups), \ - } - #define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10) \ { \ - .name = "gpio" #id, \ - .pins = gpio##id##_pins, \ - .npins = ARRAY_SIZE(gpio##id##_pins), \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ .funcs = (int[]){ \ IPQ_MUX_gpio, \ IPQ_MUX_##f1, \ @@ -211,9 +203,9 @@ static const unsigned int sdc3_data_pins[] = { 71 }; #define SDC_PINGROUP(pg_name, ctl, pull, drv) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = ctl, \ .io_reg = 0, \ .intr_cfg_reg = 0, \ @@ -487,53 +479,53 @@ static const char * const ps_hold_groups[] = { "gpio26", }; -static const struct msm_function ipq8064_functions[] = { - FUNCTION(gpio), - FUNCTION(mdio), - FUNCTION(ssbi), - FUNCTION(spmi), - FUNCTION(mi2s), - FUNCTION(pdm), - FUNCTION(audio_pcm), - FUNCTION(gsbi1), - FUNCTION(gsbi2), - FUNCTION(gsbi4), - FUNCTION(gsbi5), - FUNCTION(gsbi5_spi_cs1), - FUNCTION(gsbi5_spi_cs2), - FUNCTION(gsbi5_spi_cs3), - FUNCTION(gsbi6), - FUNCTION(gsbi7), - FUNCTION(nss_spi), - FUNCTION(sdc1), - FUNCTION(spdif), - FUNCTION(nand), - FUNCTION(tsif1), - FUNCTION(tsif2), - FUNCTION(usb_fs_n), - FUNCTION(usb_fs), - FUNCTION(usb2_hsic), - FUNCTION(rgmii2), - FUNCTION(sata), - FUNCTION(pcie1_rst), - FUNCTION(pcie1_prsnt), - FUNCTION(pcie1_pwren_n), - FUNCTION(pcie1_pwren), - FUNCTION(pcie1_pwrflt), - FUNCTION(pcie1_clk_req), - FUNCTION(pcie2_rst), - FUNCTION(pcie2_prsnt), - FUNCTION(pcie2_pwren_n), - FUNCTION(pcie2_pwren), - FUNCTION(pcie2_pwrflt), - FUNCTION(pcie2_clk_req), - FUNCTION(pcie3_rst), - FUNCTION(pcie3_prsnt), - FUNCTION(pcie3_pwren_n), - FUNCTION(pcie3_pwren), - FUNCTION(pcie3_pwrflt), - FUNCTION(pcie3_clk_req), - FUNCTION(ps_hold), +static const struct pinfunction ipq8064_functions[] = { + IPQ_PIN_FUNCTION(gpio), + IPQ_PIN_FUNCTION(mdio), + IPQ_PIN_FUNCTION(ssbi), + IPQ_PIN_FUNCTION(spmi), + IPQ_PIN_FUNCTION(mi2s), + IPQ_PIN_FUNCTION(pdm), + IPQ_PIN_FUNCTION(audio_pcm), + IPQ_PIN_FUNCTION(gsbi1), + IPQ_PIN_FUNCTION(gsbi2), + IPQ_PIN_FUNCTION(gsbi4), + IPQ_PIN_FUNCTION(gsbi5), + IPQ_PIN_FUNCTION(gsbi5_spi_cs1), + IPQ_PIN_FUNCTION(gsbi5_spi_cs2), + IPQ_PIN_FUNCTION(gsbi5_spi_cs3), + IPQ_PIN_FUNCTION(gsbi6), + IPQ_PIN_FUNCTION(gsbi7), + IPQ_PIN_FUNCTION(nss_spi), + IPQ_PIN_FUNCTION(sdc1), + IPQ_PIN_FUNCTION(spdif), + IPQ_PIN_FUNCTION(nand), + IPQ_PIN_FUNCTION(tsif1), + IPQ_PIN_FUNCTION(tsif2), + IPQ_PIN_FUNCTION(usb_fs_n), + IPQ_PIN_FUNCTION(usb_fs), + IPQ_PIN_FUNCTION(usb2_hsic), + IPQ_PIN_FUNCTION(rgmii2), + IPQ_PIN_FUNCTION(sata), + IPQ_PIN_FUNCTION(pcie1_rst), + IPQ_PIN_FUNCTION(pcie1_prsnt), + IPQ_PIN_FUNCTION(pcie1_pwren_n), + IPQ_PIN_FUNCTION(pcie1_pwren), + IPQ_PIN_FUNCTION(pcie1_pwrflt), + IPQ_PIN_FUNCTION(pcie1_clk_req), + IPQ_PIN_FUNCTION(pcie2_rst), + IPQ_PIN_FUNCTION(pcie2_prsnt), + IPQ_PIN_FUNCTION(pcie2_pwren_n), + IPQ_PIN_FUNCTION(pcie2_pwren), + IPQ_PIN_FUNCTION(pcie2_pwrflt), + IPQ_PIN_FUNCTION(pcie2_clk_req), + IPQ_PIN_FUNCTION(pcie3_rst), + IPQ_PIN_FUNCTION(pcie3_prsnt), + IPQ_PIN_FUNCTION(pcie3_pwren_n), + IPQ_PIN_FUNCTION(pcie3_pwren), + IPQ_PIN_FUNCTION(pcie3_pwrflt), + IPQ_PIN_FUNCTION(pcie3_clk_req), + IPQ_PIN_FUNCTION(ps_hold), }; static const struct msm_pingroup ipq8064_groups[] = { diff --git a/drivers/pinctrl/qcom/pinctrl-ipq8074.c b/drivers/pinctrl/qcom/pinctrl-ipq8074.c index aec68b1c9f5345c061ee2773c9c6928b1cdf54fd..337f3a1c92c19285f16f59a79f3e2b20561ae19a 100644 --- a/drivers/pinctrl/qcom/pinctrl-ipq8074.c +++ b/drivers/pinctrl/qcom/pinctrl-ipq8074.c @@ -6,23 +6,15 @@ #include #include #include -#include #include "pinctrl-msm.h" -#define FUNCTION(fname) \ - [msm_mux_##fname] = { \ - .name = #fname, \ - .groups = fname##_groups, \ - .ngroups = ARRAY_SIZE(fname##_groups), \ - } - #define REG_SIZE 0x1000 #define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9) \ { \ - .name = "gpio" #id, \ - .pins = gpio##id##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(gpio##id##_pins), \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ .funcs = (int[]){ \ msm_mux_gpio, /* gpio mode */ \ msm_mux_##f1, \ @@ -797,119 +789,119 @@ static const char * const gpio_groups[] = { "gpio64", "gpio65", "gpio66", "gpio67", "gpio68", "gpio69", }; -static const struct msm_function ipq8074_functions[] = { - FUNCTION(atest_char), - FUNCTION(atest_char0), - FUNCTION(atest_char1), - FUNCTION(atest_char2), - FUNCTION(atest_char3), - FUNCTION(audio_rxbclk), - FUNCTION(audio_rxd), - FUNCTION(audio_rxfsync), - FUNCTION(audio_rxmclk), - FUNCTION(audio_txbclk), - FUNCTION(audio_txd), - FUNCTION(audio_txfsync), - FUNCTION(audio_txmclk), - FUNCTION(blsp0_i2c), - FUNCTION(blsp0_spi), - FUNCTION(blsp0_uart), - FUNCTION(blsp1_i2c), - FUNCTION(blsp1_spi), - FUNCTION(blsp1_uart), - FUNCTION(blsp2_i2c), - FUNCTION(blsp2_spi), - FUNCTION(blsp2_uart), - FUNCTION(blsp3_i2c), - FUNCTION(blsp3_spi), - FUNCTION(blsp3_spi0), - FUNCTION(blsp3_spi1), - FUNCTION(blsp3_spi2), - FUNCTION(blsp3_spi3), - FUNCTION(blsp3_uart), - FUNCTION(blsp4_i2c0), - FUNCTION(blsp4_i2c1), - FUNCTION(blsp4_spi0), - FUNCTION(blsp4_spi1), - FUNCTION(blsp4_uart0), - FUNCTION(blsp4_uart1), - FUNCTION(blsp5_i2c), - FUNCTION(blsp5_spi), - FUNCTION(blsp5_uart), - FUNCTION(burn0), - FUNCTION(burn1), - FUNCTION(cri_trng), - FUNCTION(cri_trng0), - FUNCTION(cri_trng1), - FUNCTION(cxc0), - FUNCTION(cxc1), - FUNCTION(dbg_out), - FUNCTION(gcc_plltest), - FUNCTION(gcc_tlmm), - FUNCTION(gpio), - FUNCTION(ldo_en), - FUNCTION(ldo_update), - FUNCTION(led0), - FUNCTION(led1), - FUNCTION(led2), - FUNCTION(mac0_sa0), - FUNCTION(mac0_sa1), - FUNCTION(mac1_sa0), - FUNCTION(mac1_sa1), - FUNCTION(mac1_sa2), - FUNCTION(mac1_sa3), - FUNCTION(mac2_sa0), - FUNCTION(mac2_sa1), - FUNCTION(mdc), - FUNCTION(mdio), - FUNCTION(pcie0_clk), - FUNCTION(pcie0_rst), - FUNCTION(pcie0_wake), - FUNCTION(pcie1_clk), - FUNCTION(pcie1_rst), - FUNCTION(pcie1_wake), - FUNCTION(pcm_drx), - FUNCTION(pcm_dtx), - FUNCTION(pcm_fsync), - FUNCTION(pcm_pclk), - FUNCTION(pcm_zsi0), - FUNCTION(pcm_zsi1), - FUNCTION(prng_rosc), - FUNCTION(pta1_0), - FUNCTION(pta1_1), - FUNCTION(pta1_2), - FUNCTION(pta2_0), - FUNCTION(pta2_1), - FUNCTION(pta2_2), - FUNCTION(pwm0), - FUNCTION(pwm1), - FUNCTION(pwm2), - FUNCTION(pwm3), - FUNCTION(qdss_cti_trig_in_a0), - FUNCTION(qdss_cti_trig_in_a1), - FUNCTION(qdss_cti_trig_in_b0), - FUNCTION(qdss_cti_trig_in_b1), - FUNCTION(qdss_cti_trig_out_a0), - FUNCTION(qdss_cti_trig_out_a1), - FUNCTION(qdss_cti_trig_out_b0), - FUNCTION(qdss_cti_trig_out_b1), - FUNCTION(qdss_traceclk_a), - FUNCTION(qdss_traceclk_b), - FUNCTION(qdss_tracectl_a), - FUNCTION(qdss_tracectl_b), - FUNCTION(qdss_tracedata_a), - FUNCTION(qdss_tracedata_b), - FUNCTION(qpic), - FUNCTION(rx0), - FUNCTION(rx1), - FUNCTION(rx2), - FUNCTION(sd_card), - FUNCTION(sd_write), - FUNCTION(tsens_max), - FUNCTION(wci2a), - FUNCTION(wci2b), - FUNCTION(wci2c), - FUNCTION(wci2d), +static const struct pinfunction ipq8074_functions[] = { + MSM_PIN_FUNCTION(atest_char), + MSM_PIN_FUNCTION(atest_char0), + MSM_PIN_FUNCTION(atest_char1), + MSM_PIN_FUNCTION(atest_char2), + MSM_PIN_FUNCTION(atest_char3), + MSM_PIN_FUNCTION(audio_rxbclk), + MSM_PIN_FUNCTION(audio_rxd), + MSM_PIN_FUNCTION(audio_rxfsync), + MSM_PIN_FUNCTION(audio_rxmclk), + MSM_PIN_FUNCTION(audio_txbclk), + MSM_PIN_FUNCTION(audio_txd), + MSM_PIN_FUNCTION(audio_txfsync), + MSM_PIN_FUNCTION(audio_txmclk), + MSM_PIN_FUNCTION(blsp0_i2c), + MSM_PIN_FUNCTION(blsp0_spi), + MSM_PIN_FUNCTION(blsp0_uart), + MSM_PIN_FUNCTION(blsp1_i2c), + MSM_PIN_FUNCTION(blsp1_spi), + MSM_PIN_FUNCTION(blsp1_uart), + MSM_PIN_FUNCTION(blsp2_i2c), + MSM_PIN_FUNCTION(blsp2_spi), + MSM_PIN_FUNCTION(blsp2_uart), + MSM_PIN_FUNCTION(blsp3_i2c), + MSM_PIN_FUNCTION(blsp3_spi), + MSM_PIN_FUNCTION(blsp3_spi0), + MSM_PIN_FUNCTION(blsp3_spi1), + MSM_PIN_FUNCTION(blsp3_spi2), + MSM_PIN_FUNCTION(blsp3_spi3), + MSM_PIN_FUNCTION(blsp3_uart), + MSM_PIN_FUNCTION(blsp4_i2c0), + MSM_PIN_FUNCTION(blsp4_i2c1), + MSM_PIN_FUNCTION(blsp4_spi0), + MSM_PIN_FUNCTION(blsp4_spi1), + MSM_PIN_FUNCTION(blsp4_uart0), + MSM_PIN_FUNCTION(blsp4_uart1), + MSM_PIN_FUNCTION(blsp5_i2c), + MSM_PIN_FUNCTION(blsp5_spi), + MSM_PIN_FUNCTION(blsp5_uart), + MSM_PIN_FUNCTION(burn0), + MSM_PIN_FUNCTION(burn1), + MSM_PIN_FUNCTION(cri_trng), + MSM_PIN_FUNCTION(cri_trng0), + MSM_PIN_FUNCTION(cri_trng1), + MSM_PIN_FUNCTION(cxc0), + MSM_PIN_FUNCTION(cxc1), + MSM_PIN_FUNCTION(dbg_out), + MSM_PIN_FUNCTION(gcc_plltest), + MSM_PIN_FUNCTION(gcc_tlmm), + MSM_PIN_FUNCTION(gpio), + MSM_PIN_FUNCTION(ldo_en), + MSM_PIN_FUNCTION(ldo_update), + MSM_PIN_FUNCTION(led0), + MSM_PIN_FUNCTION(led1), + MSM_PIN_FUNCTION(led2), + MSM_PIN_FUNCTION(mac0_sa0), + MSM_PIN_FUNCTION(mac0_sa1), + MSM_PIN_FUNCTION(mac1_sa0), + MSM_PIN_FUNCTION(mac1_sa1), + MSM_PIN_FUNCTION(mac1_sa2), + MSM_PIN_FUNCTION(mac1_sa3), + MSM_PIN_FUNCTION(mac2_sa0), + MSM_PIN_FUNCTION(mac2_sa1), + MSM_PIN_FUNCTION(mdc), + MSM_PIN_FUNCTION(mdio), + MSM_PIN_FUNCTION(pcie0_clk), + MSM_PIN_FUNCTION(pcie0_rst), + MSM_PIN_FUNCTION(pcie0_wake), + MSM_PIN_FUNCTION(pcie1_clk), + MSM_PIN_FUNCTION(pcie1_rst), + MSM_PIN_FUNCTION(pcie1_wake), + MSM_PIN_FUNCTION(pcm_drx), + MSM_PIN_FUNCTION(pcm_dtx), + MSM_PIN_FUNCTION(pcm_fsync), + MSM_PIN_FUNCTION(pcm_pclk), + MSM_PIN_FUNCTION(pcm_zsi0), + MSM_PIN_FUNCTION(pcm_zsi1), + MSM_PIN_FUNCTION(prng_rosc), + MSM_PIN_FUNCTION(pta1_0), + MSM_PIN_FUNCTION(pta1_1), + MSM_PIN_FUNCTION(pta1_2), + MSM_PIN_FUNCTION(pta2_0), + MSM_PIN_FUNCTION(pta2_1), + MSM_PIN_FUNCTION(pta2_2), + MSM_PIN_FUNCTION(pwm0), + MSM_PIN_FUNCTION(pwm1), + MSM_PIN_FUNCTION(pwm2), + MSM_PIN_FUNCTION(pwm3), + MSM_PIN_FUNCTION(qdss_cti_trig_in_a0), + MSM_PIN_FUNCTION(qdss_cti_trig_in_a1), + MSM_PIN_FUNCTION(qdss_cti_trig_in_b0), + MSM_PIN_FUNCTION(qdss_cti_trig_in_b1), + MSM_PIN_FUNCTION(qdss_cti_trig_out_a0), + MSM_PIN_FUNCTION(qdss_cti_trig_out_a1), + MSM_PIN_FUNCTION(qdss_cti_trig_out_b0), + MSM_PIN_FUNCTION(qdss_cti_trig_out_b1), + MSM_PIN_FUNCTION(qdss_traceclk_a), + MSM_PIN_FUNCTION(qdss_traceclk_b), + MSM_PIN_FUNCTION(qdss_tracectl_a), + MSM_PIN_FUNCTION(qdss_tracectl_b), + MSM_PIN_FUNCTION(qdss_tracedata_a), + MSM_PIN_FUNCTION(qdss_tracedata_b), + MSM_PIN_FUNCTION(qpic), + MSM_PIN_FUNCTION(rx0), + MSM_PIN_FUNCTION(rx1), + MSM_PIN_FUNCTION(rx2), + MSM_PIN_FUNCTION(sd_card), + MSM_PIN_FUNCTION(sd_write), + MSM_PIN_FUNCTION(tsens_max), + MSM_PIN_FUNCTION(wci2a), + MSM_PIN_FUNCTION(wci2b), + MSM_PIN_FUNCTION(wci2c), + MSM_PIN_FUNCTION(wci2d), }; static const struct msm_pingroup ipq8074_groups[] = { diff --git a/drivers/pinctrl/qcom/pinctrl-ipq9574.c b/drivers/pinctrl/qcom/pinctrl-ipq9574.c index 7f057b62475ff52b7da7028ea183f4f505b1b5c7..e2491617b2364a64169297426351e723c37f030c 100644 --- a/drivers/pinctrl/qcom/pinctrl-ipq9574.c +++ b/drivers/pinctrl/qcom/pinctrl-ipq9574.c @@ -6,23 +6,15 @@ #include #include #include -#include #include "pinctrl-msm.h" -#define FUNCTION(fname) \ - [msm_mux_##fname] = { \ - .name = #fname, \ - .groups = fname##_groups, \ - .ngroups = ARRAY_SIZE(fname##_groups), \ - } - #define REG_SIZE 0x1000 #define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9) \ { \ - .name = "gpio" #id, \ - .pins = gpio##id##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(gpio##id##_pins), \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ .funcs = (int[]){ \ msm_mux_gpio, /* gpio mode */ \ msm_mux_##f1, \ @@ -623,87 +615,87 @@ static const char * const tsens_max_groups[] = { "gpio64", }; -static const struct msm_function ipq9574_functions[] = { - FUNCTION(atest_char), - FUNCTION(atest_char0), - FUNCTION(atest_char1), - FUNCTION(atest_char2), - FUNCTION(atest_char3), - FUNCTION(audio_pdm0), - FUNCTION(audio_pdm1), - FUNCTION(audio_pri), - FUNCTION(audio_sec), - FUNCTION(blsp0_spi), - FUNCTION(blsp0_uart), - FUNCTION(blsp1_i2c), - FUNCTION(blsp1_spi), - FUNCTION(blsp1_uart), - FUNCTION(blsp2_i2c), - FUNCTION(blsp2_spi), - FUNCTION(blsp2_uart), - FUNCTION(blsp3_i2c), - FUNCTION(blsp3_spi), - FUNCTION(blsp3_uart), - FUNCTION(blsp4_i2c), - FUNCTION(blsp4_spi), - FUNCTION(blsp4_uart), - FUNCTION(blsp5_i2c), - FUNCTION(blsp5_uart), - FUNCTION(cri_trng0), - FUNCTION(cri_trng1), - FUNCTION(cri_trng2), - FUNCTION(cri_trng3), - FUNCTION(cxc0), - FUNCTION(cxc1), - FUNCTION(dbg_out), - FUNCTION(dwc_ddrphy), - FUNCTION(gcc_plltest), - FUNCTION(gcc_tlmm), - FUNCTION(gpio), - FUNCTION(mac), - FUNCTION(mdc), - FUNCTION(mdio), - FUNCTION(pcie0_clk), - FUNCTION(pcie0_wake), - FUNCTION(pcie1_clk), - FUNCTION(pcie1_wake), - FUNCTION(pcie2_clk), - FUNCTION(pcie2_wake), - FUNCTION(pcie3_clk), - FUNCTION(pcie3_wake), - FUNCTION(prng_rosc0), - FUNCTION(prng_rosc1), - FUNCTION(prng_rosc2), - FUNCTION(prng_rosc3), - FUNCTION(pta), - FUNCTION(pwm), - FUNCTION(qdss_cti_trig_in_a0), - FUNCTION(qdss_cti_trig_in_a1), - FUNCTION(qdss_cti_trig_in_b0), - FUNCTION(qdss_cti_trig_in_b1), - FUNCTION(qdss_cti_trig_out_a0), - FUNCTION(qdss_cti_trig_out_a1), - FUNCTION(qdss_cti_trig_out_b0), - FUNCTION(qdss_cti_trig_out_b1), - FUNCTION(qdss_traceclk_a), - FUNCTION(qdss_traceclk_b), - FUNCTION(qdss_tracectl_a), - FUNCTION(qdss_tracectl_b), - FUNCTION(qdss_tracedata_a), - FUNCTION(qdss_tracedata_b), - FUNCTION(qspi_data), - FUNCTION(qspi_clk), - FUNCTION(qspi_cs), - FUNCTION(rx0), - FUNCTION(rx1), - FUNCTION(sdc_data), - FUNCTION(sdc_clk), - FUNCTION(sdc_cmd), - FUNCTION(sdc_rclk), - FUNCTION(tsens_max), - FUNCTION(wci20), - FUNCTION(wci21), - FUNCTION(wsa_swrm), +static const struct pinfunction ipq9574_functions[] = { + MSM_PIN_FUNCTION(atest_char), + MSM_PIN_FUNCTION(atest_char0), + MSM_PIN_FUNCTION(atest_char1), + MSM_PIN_FUNCTION(atest_char2), + MSM_PIN_FUNCTION(atest_char3), + MSM_PIN_FUNCTION(audio_pdm0), + MSM_PIN_FUNCTION(audio_pdm1), + MSM_PIN_FUNCTION(audio_pri), + MSM_PIN_FUNCTION(audio_sec), + MSM_PIN_FUNCTION(blsp0_spi), + MSM_PIN_FUNCTION(blsp0_uart), + MSM_PIN_FUNCTION(blsp1_i2c), + MSM_PIN_FUNCTION(blsp1_spi), + MSM_PIN_FUNCTION(blsp1_uart), + MSM_PIN_FUNCTION(blsp2_i2c), + MSM_PIN_FUNCTION(blsp2_spi), + MSM_PIN_FUNCTION(blsp2_uart), + MSM_PIN_FUNCTION(blsp3_i2c), + MSM_PIN_FUNCTION(blsp3_spi), + MSM_PIN_FUNCTION(blsp3_uart), + MSM_PIN_FUNCTION(blsp4_i2c), + MSM_PIN_FUNCTION(blsp4_spi), + MSM_PIN_FUNCTION(blsp4_uart), + MSM_PIN_FUNCTION(blsp5_i2c), + MSM_PIN_FUNCTION(blsp5_uart), + MSM_PIN_FUNCTION(cri_trng0), + MSM_PIN_FUNCTION(cri_trng1), + MSM_PIN_FUNCTION(cri_trng2), + MSM_PIN_FUNCTION(cri_trng3), + MSM_PIN_FUNCTION(cxc0), + MSM_PIN_FUNCTION(cxc1), + MSM_PIN_FUNCTION(dbg_out), + MSM_PIN_FUNCTION(dwc_ddrphy), + MSM_PIN_FUNCTION(gcc_plltest), + MSM_PIN_FUNCTION(gcc_tlmm), + MSM_PIN_FUNCTION(gpio), + MSM_PIN_FUNCTION(mac), + MSM_PIN_FUNCTION(mdc), + MSM_PIN_FUNCTION(mdio), + MSM_PIN_FUNCTION(pcie0_clk), + MSM_PIN_FUNCTION(pcie0_wake), + MSM_PIN_FUNCTION(pcie1_clk), + MSM_PIN_FUNCTION(pcie1_wake), + MSM_PIN_FUNCTION(pcie2_clk), + MSM_PIN_FUNCTION(pcie2_wake), + MSM_PIN_FUNCTION(pcie3_clk), + MSM_PIN_FUNCTION(pcie3_wake), + MSM_PIN_FUNCTION(prng_rosc0), + MSM_PIN_FUNCTION(prng_rosc1), + MSM_PIN_FUNCTION(prng_rosc2), + MSM_PIN_FUNCTION(prng_rosc3), + MSM_PIN_FUNCTION(pta), + MSM_PIN_FUNCTION(pwm), + MSM_PIN_FUNCTION(qdss_cti_trig_in_a0), + MSM_PIN_FUNCTION(qdss_cti_trig_in_a1), + MSM_PIN_FUNCTION(qdss_cti_trig_in_b0), + MSM_PIN_FUNCTION(qdss_cti_trig_in_b1), + MSM_PIN_FUNCTION(qdss_cti_trig_out_a0), + MSM_PIN_FUNCTION(qdss_cti_trig_out_a1), + MSM_PIN_FUNCTION(qdss_cti_trig_out_b0), + MSM_PIN_FUNCTION(qdss_cti_trig_out_b1), + MSM_PIN_FUNCTION(qdss_traceclk_a), + MSM_PIN_FUNCTION(qdss_traceclk_b), + MSM_PIN_FUNCTION(qdss_tracectl_a), + MSM_PIN_FUNCTION(qdss_tracectl_b), + MSM_PIN_FUNCTION(qdss_tracedata_a), + MSM_PIN_FUNCTION(qdss_tracedata_b), + MSM_PIN_FUNCTION(qspi_data), + MSM_PIN_FUNCTION(qspi_clk), + MSM_PIN_FUNCTION(qspi_cs), + MSM_PIN_FUNCTION(rx0), + MSM_PIN_FUNCTION(rx1), + MSM_PIN_FUNCTION(sdc_data), + MSM_PIN_FUNCTION(sdc_clk), + MSM_PIN_FUNCTION(sdc_cmd), + MSM_PIN_FUNCTION(sdc_rclk), + MSM_PIN_FUNCTION(tsens_max), + MSM_PIN_FUNCTION(wci20), + MSM_PIN_FUNCTION(wci21), + MSM_PIN_FUNCTION(wsa_swrm), }; static const struct msm_pingroup ipq9574_groups[] = { diff --git a/drivers/pinctrl/qcom/pinctrl-mdm9607.c b/drivers/pinctrl/qcom/pinctrl-mdm9607.c index d622b3df0fe749332672676e5951d8a8ae3e0ead..e7cd3ef1cf3e815ae25aa9e0c6872fbbd2c8ac79 100644 --- a/drivers/pinctrl/qcom/pinctrl-mdm9607.c +++ b/drivers/pinctrl/qcom/pinctrl-mdm9607.c @@ -8,7 +8,6 @@ #include #include #include -#include #include "pinctrl-msm.h" @@ -204,18 +203,11 @@ static const unsigned int qdsd_data1_pins[] = { 89 }; static const unsigned int qdsd_data2_pins[] = { 90 }; static const unsigned int qdsd_data3_pins[] = { 91 }; -#define FUNCTION(fname) \ - [msm_mux_##fname] = { \ - .name = #fname, \ - .groups = fname##_groups, \ - .ngroups = ARRAY_SIZE(fname##_groups), \ - } - #define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9) \ { \ - .name = "gpio" #id, \ - .pins = gpio##id##_pins, \ - .npins = ARRAY_SIZE(gpio##id##_pins), \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ .funcs = (int[]){ \ msm_mux_gpio, \ msm_mux_##f1, \ @@ -252,9 +244,9 @@ static const unsigned int qdsd_data3_pins[] = { 91 }; #define SDC_PINGROUP(pg_name, ctl, pull, drv) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = ctl, \ .io_reg = 0, \ .intr_cfg_reg = 0, \ @@ -806,134 +798,134 @@ static const char * const pwr_crypto_enabled_b_groups[] = { "gpio79", }; -static const struct msm_function mdm9607_functions[] = { - FUNCTION(adsp_ext), - FUNCTION(atest_bbrx0), - FUNCTION(atest_bbrx1), - FUNCTION(atest_char), - FUNCTION(atest_char0), - FUNCTION(atest_char1), - FUNCTION(atest_char2), - FUNCTION(atest_char3), - FUNCTION(atest_combodac_to_gpio_native), - FUNCTION(atest_gpsadc_dtest0_native), - FUNCTION(atest_gpsadc_dtest1_native), - FUNCTION(atest_tsens), - FUNCTION(backlight_en_b), - FUNCTION(bimc_dte0), - FUNCTION(bimc_dte1), - FUNCTION(blsp1_spi), - FUNCTION(blsp2_spi), - FUNCTION(blsp3_spi), - FUNCTION(blsp_i2c1), - FUNCTION(blsp_i2c2), - FUNCTION(blsp_i2c3), - FUNCTION(blsp_i2c4), - FUNCTION(blsp_i2c5), - FUNCTION(blsp_i2c6), - FUNCTION(blsp_spi1), - FUNCTION(blsp_spi2), - FUNCTION(blsp_spi3), - FUNCTION(blsp_spi4), - FUNCTION(blsp_spi5), - FUNCTION(blsp_spi6), - FUNCTION(blsp_uart1), - FUNCTION(blsp_uart2), - FUNCTION(blsp_uart3), - FUNCTION(blsp_uart4), - FUNCTION(blsp_uart5), - FUNCTION(blsp_uart6), - FUNCTION(blsp_uim1), - FUNCTION(blsp_uim2), - FUNCTION(codec_int), - FUNCTION(codec_rst), - FUNCTION(coex_uart), - FUNCTION(cri_trng), - FUNCTION(cri_trng0), - FUNCTION(cri_trng1), - FUNCTION(dbg_out), - FUNCTION(ebi0_wrcdc), - FUNCTION(ebi2_a), - FUNCTION(ebi2_a_d_8_b), - FUNCTION(ebi2_lcd), - FUNCTION(ebi2_lcd_cs_n_b), - FUNCTION(ebi2_lcd_te_b), - FUNCTION(eth_irq), - FUNCTION(eth_rst), - FUNCTION(gcc_gp1_clk_a), - FUNCTION(gcc_gp1_clk_b), - FUNCTION(gcc_gp2_clk_a), - FUNCTION(gcc_gp2_clk_b), - FUNCTION(gcc_gp3_clk_a), - FUNCTION(gcc_gp3_clk_b), - FUNCTION(gcc_plltest), - FUNCTION(gcc_tlmm), - FUNCTION(gmac_mdio), - FUNCTION(gpio), - FUNCTION(gsm0_tx), - FUNCTION(lcd_rst), - FUNCTION(ldo_en), - FUNCTION(ldo_update), - FUNCTION(m_voc), - FUNCTION(modem_tsync), - FUNCTION(nav_ptp_pps_in_a), - FUNCTION(nav_ptp_pps_in_b), - FUNCTION(nav_tsync_out_a), - FUNCTION(nav_tsync_out_b), - FUNCTION(pa_indicator), - FUNCTION(pbs0), - FUNCTION(pbs1), - FUNCTION(pbs2), - FUNCTION(pri_mi2s_data0_a), - FUNCTION(pri_mi2s_data1_a), - FUNCTION(pri_mi2s_mclk_a), - FUNCTION(pri_mi2s_sck_a), - FUNCTION(pri_mi2s_ws_a), - FUNCTION(prng_rosc), - FUNCTION(ptp_pps_out_a), - FUNCTION(ptp_pps_out_b), - FUNCTION(pwr_crypto_enabled_a), - FUNCTION(pwr_crypto_enabled_b), - FUNCTION(pwr_modem_enabled_a), - FUNCTION(pwr_modem_enabled_b), - FUNCTION(pwr_nav_enabled_a), - FUNCTION(pwr_nav_enabled_b), - FUNCTION(qdss_cti_trig_in_a0), - FUNCTION(qdss_cti_trig_in_a1), - FUNCTION(qdss_cti_trig_in_b0), - FUNCTION(qdss_cti_trig_in_b1), - FUNCTION(qdss_cti_trig_out_a0), - FUNCTION(qdss_cti_trig_out_a1), - FUNCTION(qdss_cti_trig_out_b0), - FUNCTION(qdss_cti_trig_out_b1), - FUNCTION(qdss_traceclk_a), - FUNCTION(qdss_traceclk_b), - FUNCTION(qdss_tracectl_a), - FUNCTION(qdss_tracectl_b), - FUNCTION(qdss_tracedata_a), - FUNCTION(qdss_tracedata_b), - FUNCTION(rcm_marker1), - FUNCTION(rcm_marker2), - FUNCTION(sd_write), - FUNCTION(sec_mi2s), - FUNCTION(sensor_en), - FUNCTION(sensor_int2), - FUNCTION(sensor_int3), - FUNCTION(sensor_rst), - FUNCTION(ssbi1), - FUNCTION(ssbi2), - FUNCTION(touch_rst), - FUNCTION(ts_int), - FUNCTION(uim1_clk), - FUNCTION(uim1_data), - FUNCTION(uim1_present), - FUNCTION(uim1_reset), - FUNCTION(uim2_clk), - FUNCTION(uim2_data), - FUNCTION(uim2_present), - FUNCTION(uim2_reset), - FUNCTION(uim_batt), - FUNCTION(wlan_en1) +static const struct pinfunction mdm9607_functions[] = { + MSM_PIN_FUNCTION(adsp_ext), + MSM_PIN_FUNCTION(atest_bbrx0), + MSM_PIN_FUNCTION(atest_bbrx1), + MSM_PIN_FUNCTION(atest_char), + MSM_PIN_FUNCTION(atest_char0), + MSM_PIN_FUNCTION(atest_char1), + MSM_PIN_FUNCTION(atest_char2), + MSM_PIN_FUNCTION(atest_char3), + MSM_PIN_FUNCTION(atest_combodac_to_gpio_native), + MSM_PIN_FUNCTION(atest_gpsadc_dtest0_native), + MSM_PIN_FUNCTION(atest_gpsadc_dtest1_native), + MSM_PIN_FUNCTION(atest_tsens), + MSM_PIN_FUNCTION(backlight_en_b), + MSM_PIN_FUNCTION(bimc_dte0), + MSM_PIN_FUNCTION(bimc_dte1), + MSM_PIN_FUNCTION(blsp1_spi), + MSM_PIN_FUNCTION(blsp2_spi), + MSM_PIN_FUNCTION(blsp3_spi), + MSM_PIN_FUNCTION(blsp_i2c1), + MSM_PIN_FUNCTION(blsp_i2c2), + MSM_PIN_FUNCTION(blsp_i2c3), + MSM_PIN_FUNCTION(blsp_i2c4), + MSM_PIN_FUNCTION(blsp_i2c5), + MSM_PIN_FUNCTION(blsp_i2c6), + MSM_PIN_FUNCTION(blsp_spi1), + MSM_PIN_FUNCTION(blsp_spi2), + MSM_PIN_FUNCTION(blsp_spi3), + MSM_PIN_FUNCTION(blsp_spi4), + MSM_PIN_FUNCTION(blsp_spi5), + MSM_PIN_FUNCTION(blsp_spi6), + MSM_PIN_FUNCTION(blsp_uart1), + MSM_PIN_FUNCTION(blsp_uart2), + MSM_PIN_FUNCTION(blsp_uart3), + MSM_PIN_FUNCTION(blsp_uart4), + MSM_PIN_FUNCTION(blsp_uart5), + MSM_PIN_FUNCTION(blsp_uart6), + MSM_PIN_FUNCTION(blsp_uim1), + MSM_PIN_FUNCTION(blsp_uim2), + MSM_PIN_FUNCTION(codec_int), + MSM_PIN_FUNCTION(codec_rst), + MSM_PIN_FUNCTION(coex_uart), + MSM_PIN_FUNCTION(cri_trng), + MSM_PIN_FUNCTION(cri_trng0), + MSM_PIN_FUNCTION(cri_trng1), + MSM_PIN_FUNCTION(dbg_out), + MSM_PIN_FUNCTION(ebi0_wrcdc), + MSM_PIN_FUNCTION(ebi2_a), + MSM_PIN_FUNCTION(ebi2_a_d_8_b), + MSM_PIN_FUNCTION(ebi2_lcd), + MSM_PIN_FUNCTION(ebi2_lcd_cs_n_b), + MSM_PIN_FUNCTION(ebi2_lcd_te_b), + MSM_PIN_FUNCTION(eth_irq), + MSM_PIN_FUNCTION(eth_rst), + MSM_PIN_FUNCTION(gcc_gp1_clk_a), + MSM_PIN_FUNCTION(gcc_gp1_clk_b), + MSM_PIN_FUNCTION(gcc_gp2_clk_a), + MSM_PIN_FUNCTION(gcc_gp2_clk_b), + MSM_PIN_FUNCTION(gcc_gp3_clk_a), + MSM_PIN_FUNCTION(gcc_gp3_clk_b), + MSM_PIN_FUNCTION(gcc_plltest), + MSM_PIN_FUNCTION(gcc_tlmm), + MSM_PIN_FUNCTION(gmac_mdio), + MSM_PIN_FUNCTION(gpio), + MSM_PIN_FUNCTION(gsm0_tx), + MSM_PIN_FUNCTION(lcd_rst), + MSM_PIN_FUNCTION(ldo_en), + MSM_PIN_FUNCTION(ldo_update), + MSM_PIN_FUNCTION(m_voc), + MSM_PIN_FUNCTION(modem_tsync), + MSM_PIN_FUNCTION(nav_ptp_pps_in_a), + MSM_PIN_FUNCTION(nav_ptp_pps_in_b), + MSM_PIN_FUNCTION(nav_tsync_out_a), + MSM_PIN_FUNCTION(nav_tsync_out_b), + MSM_PIN_FUNCTION(pa_indicator), + MSM_PIN_FUNCTION(pbs0), + MSM_PIN_FUNCTION(pbs1), + MSM_PIN_FUNCTION(pbs2), + MSM_PIN_FUNCTION(pri_mi2s_data0_a), + MSM_PIN_FUNCTION(pri_mi2s_data1_a), + MSM_PIN_FUNCTION(pri_mi2s_mclk_a), + MSM_PIN_FUNCTION(pri_mi2s_sck_a), + MSM_PIN_FUNCTION(pri_mi2s_ws_a), + MSM_PIN_FUNCTION(prng_rosc), + MSM_PIN_FUNCTION(ptp_pps_out_a), + MSM_PIN_FUNCTION(ptp_pps_out_b), + MSM_PIN_FUNCTION(pwr_crypto_enabled_a), + MSM_PIN_FUNCTION(pwr_crypto_enabled_b), + MSM_PIN_FUNCTION(pwr_modem_enabled_a), + MSM_PIN_FUNCTION(pwr_modem_enabled_b), + MSM_PIN_FUNCTION(pwr_nav_enabled_a), + MSM_PIN_FUNCTION(pwr_nav_enabled_b), + MSM_PIN_FUNCTION(qdss_cti_trig_in_a0), + MSM_PIN_FUNCTION(qdss_cti_trig_in_a1), + MSM_PIN_FUNCTION(qdss_cti_trig_in_b0), + MSM_PIN_FUNCTION(qdss_cti_trig_in_b1), + MSM_PIN_FUNCTION(qdss_cti_trig_out_a0), + MSM_PIN_FUNCTION(qdss_cti_trig_out_a1), + MSM_PIN_FUNCTION(qdss_cti_trig_out_b0), + MSM_PIN_FUNCTION(qdss_cti_trig_out_b1), + MSM_PIN_FUNCTION(qdss_traceclk_a), + MSM_PIN_FUNCTION(qdss_traceclk_b), + MSM_PIN_FUNCTION(qdss_tracectl_a), + MSM_PIN_FUNCTION(qdss_tracectl_b), + MSM_PIN_FUNCTION(qdss_tracedata_a), + MSM_PIN_FUNCTION(qdss_tracedata_b), + MSM_PIN_FUNCTION(rcm_marker1), + MSM_PIN_FUNCTION(rcm_marker2), + MSM_PIN_FUNCTION(sd_write), + MSM_PIN_FUNCTION(sec_mi2s), + MSM_PIN_FUNCTION(sensor_en), + MSM_PIN_FUNCTION(sensor_int2), + MSM_PIN_FUNCTION(sensor_int3), + MSM_PIN_FUNCTION(sensor_rst), + MSM_PIN_FUNCTION(ssbi1), + MSM_PIN_FUNCTION(ssbi2), + MSM_PIN_FUNCTION(touch_rst), + MSM_PIN_FUNCTION(ts_int), + MSM_PIN_FUNCTION(uim1_clk), + MSM_PIN_FUNCTION(uim1_data), + MSM_PIN_FUNCTION(uim1_present), + MSM_PIN_FUNCTION(uim1_reset), + MSM_PIN_FUNCTION(uim2_clk), + MSM_PIN_FUNCTION(uim2_data), + MSM_PIN_FUNCTION(uim2_present), + MSM_PIN_FUNCTION(uim2_reset), + MSM_PIN_FUNCTION(uim_batt), + MSM_PIN_FUNCTION(wlan_en1) }; static const struct msm_pingroup mdm9607_groups[] = { diff --git a/drivers/pinctrl/qcom/pinctrl-mdm9615.c b/drivers/pinctrl/qcom/pinctrl-mdm9615.c index 24a4e439edd414419553c114c999c1549400ff67..0a2ae383d3d57bd4101efb7a2093b68b8920b426 100644 --- a/drivers/pinctrl/qcom/pinctrl-mdm9615.c +++ b/drivers/pinctrl/qcom/pinctrl-mdm9615.c @@ -8,7 +8,6 @@ #include #include #include -#include #include #include "pinctrl-msm.h" @@ -195,31 +194,24 @@ DECLARE_MSM_GPIO_PINS(85); DECLARE_MSM_GPIO_PINS(86); DECLARE_MSM_GPIO_PINS(87); -#define FUNCTION(fname) \ - [MSM_MUX_##fname] = { \ - .name = #fname, \ - .groups = fname##_groups, \ - .ngroups = ARRAY_SIZE(fname##_groups), \ - } - #define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11) \ { \ - .name = "gpio" #id, \ - .pins = gpio##id##_pins, \ - .npins = ARRAY_SIZE(gpio##id##_pins), \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ .funcs = (int[]){ \ - MSM_MUX_gpio, \ - MSM_MUX_##f1, \ - MSM_MUX_##f2, \ - MSM_MUX_##f3, \ - MSM_MUX_##f4, \ - MSM_MUX_##f5, \ - MSM_MUX_##f6, \ - MSM_MUX_##f7, \ - MSM_MUX_##f8, \ - MSM_MUX_##f9, \ - MSM_MUX_##f10, \ - MSM_MUX_##f11 \ + msm_mux_gpio, \ + msm_mux_##f1, \ + msm_mux_##f2, \ + msm_mux_##f3, \ + msm_mux_##f4, \ + msm_mux_##f5, \ + msm_mux_##f6, \ + msm_mux_##f7, \ + msm_mux_##f8, \ + msm_mux_##f9, \ + msm_mux_##f10, \ + msm_mux_##f11 \ }, \ .nfuncs = 12, \ .ctl_reg = 0x1000 + 0x10 * id, \ @@ -245,19 +237,19 @@ DECLARE_MSM_GPIO_PINS(87); } enum mdm9615_functions { - MSM_MUX_gpio, - MSM_MUX_gsbi2_i2c, - MSM_MUX_gsbi3, - MSM_MUX_gsbi4, - MSM_MUX_gsbi5_i2c, - MSM_MUX_gsbi5_uart, - MSM_MUX_sdc2, - MSM_MUX_ebi2_lcdc, - MSM_MUX_ps_hold, - MSM_MUX_prim_audio, - MSM_MUX_sec_audio, - MSM_MUX_cdc_mclk, - MSM_MUX_NA, + msm_mux_gpio, + msm_mux_gsbi2_i2c, + msm_mux_gsbi3, + msm_mux_gsbi4, + msm_mux_gsbi5_i2c, + msm_mux_gsbi5_uart, + msm_mux_sdc2, + msm_mux_ebi2_lcdc, + msm_mux_ps_hold, + msm_mux_prim_audio, + msm_mux_sec_audio, + msm_mux_cdc_mclk, + msm_mux_NA, }; static const char * const gpio_groups[] = { @@ -320,19 +312,19 @@ static const char * const cdc_mclk_groups[] = { "gpio24", }; -static const struct msm_function mdm9615_functions[] = { - FUNCTION(gpio), - FUNCTION(gsbi2_i2c), - FUNCTION(gsbi3), - FUNCTION(gsbi4), - FUNCTION(gsbi5_i2c), - FUNCTION(gsbi5_uart), - FUNCTION(sdc2), - FUNCTION(ebi2_lcdc), - FUNCTION(ps_hold), - FUNCTION(prim_audio), - FUNCTION(sec_audio), - FUNCTION(cdc_mclk), +static const struct pinfunction mdm9615_functions[] = { + MSM_PIN_FUNCTION(gpio), + MSM_PIN_FUNCTION(gsbi2_i2c), + MSM_PIN_FUNCTION(gsbi3), + MSM_PIN_FUNCTION(gsbi4), + MSM_PIN_FUNCTION(gsbi5_i2c), + MSM_PIN_FUNCTION(gsbi5_uart), + MSM_PIN_FUNCTION(sdc2), + MSM_PIN_FUNCTION(ebi2_lcdc), + MSM_PIN_FUNCTION(ps_hold), + MSM_PIN_FUNCTION(prim_audio), + MSM_PIN_FUNCTION(sec_audio), + MSM_PIN_FUNCTION(cdc_mclk), }; static const struct msm_pingroup mdm9615_groups[] = { diff --git a/drivers/pinctrl/qcom/pinctrl-msm.c b/drivers/pinctrl/qcom/pinctrl-msm.c index c5f52d4f7781bab207d8c917efbd7fdba6f74411..2585ef2b2793505342905ff44cebc2f07a9d28fb 100644 --- a/drivers/pinctrl/qcom/pinctrl-msm.c +++ b/drivers/pinctrl/qcom/pinctrl-msm.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include @@ -121,7 +120,7 @@ static const char *msm_get_group_name(struct pinctrl_dev *pctldev, { struct msm_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); - return pctrl->soc->groups[group].name; + return pctrl->soc->groups[group].grp.name; } static int msm_get_group_pins(struct pinctrl_dev *pctldev, @@ -131,8 +130,8 @@ static int msm_get_group_pins(struct pinctrl_dev *pctldev, { struct msm_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); - *pins = pctrl->soc->groups[group].pins; - *num_pins = pctrl->soc->groups[group].npins; + *pins = pctrl->soc->groups[group].grp.pins; + *num_pins = pctrl->soc->groups[group].grp.npins; return 0; } @@ -706,11 +705,11 @@ static void msm_gpio_dbg_show_one(struct seq_file *s, val = !!(io_reg & BIT(g->in_bit)); if (egpio_enable) { - seq_printf(s, " %-8s: egpio\n", g->name); + seq_printf(s, " %-8s: egpio\n", g->grp.name); return; } - seq_printf(s, " %-8s: %-3s", g->name, is_out ? "out" : "in"); + seq_printf(s, " %-8s: %-3s", g->grp.name, is_out ? "out" : "in"); seq_printf(s, " %-4s func%d", val ? "high" : "low", func); seq_printf(s, " %dmA", msm_regval_to_drive(drive)); if (pctrl->soc->pull_no_keeper) @@ -1442,7 +1441,7 @@ static void msm_ps_hold_poweroff(void) static void msm_pinctrl_setup_pm_reset(struct msm_pinctrl *pctrl) { int i; - const struct msm_function *func = pctrl->soc->functions; + const struct pinfunction *func = pctrl->soc->functions; for (i = 0; i < pctrl->soc->nfunctions; i++) if (!strcmp(func[i].name, "ps_hold")) { diff --git a/drivers/pinctrl/qcom/pinctrl-msm.h b/drivers/pinctrl/qcom/pinctrl-msm.h index 985eceda2517357a7a8bc7872cc53fa340d49c39..5e4410bed8237dc029c3ac9986a9a5ceb12a0d4b 100644 --- a/drivers/pinctrl/qcom/pinctrl-msm.h +++ b/drivers/pinctrl/qcom/pinctrl-msm.h @@ -8,27 +8,35 @@ #include #include +#include + struct platform_device; struct pinctrl_pin_desc; -/** - * struct msm_function - a pinmux function - * @name: Name of the pinmux function. - * @groups: List of pingroups for this function. - * @ngroups: Number of entries in @groups. - */ -struct msm_function { - const char *name; - const char * const *groups; - unsigned ngroups; -}; +#define APQ_PIN_FUNCTION(fname) \ + [APQ_MUX_##fname] = PINCTRL_PINFUNCTION(#fname, \ + fname##_groups, \ + ARRAY_SIZE(fname##_groups)) + +#define IPQ_PIN_FUNCTION(fname) \ + [IPQ_MUX_##fname] = PINCTRL_PINFUNCTION(#fname, \ + fname##_groups, \ + ARRAY_SIZE(fname##_groups)) + +#define MSM_PIN_FUNCTION(fname) \ + [msm_mux_##fname] = PINCTRL_PINFUNCTION(#fname, \ + fname##_groups, \ + ARRAY_SIZE(fname##_groups)) + +#define QCA_PIN_FUNCTION(fname) \ + [qca_mux_##fname] = PINCTRL_PINFUNCTION(#fname, \ + fname##_groups, \ + ARRAY_SIZE(fname##_groups)) /** * struct msm_pingroup - Qualcomm pingroup definition - * @name: Name of the pingroup. - * @pins: A list of pins assigned to this pingroup. - * @npins: Number of entries in @pins. + * @grp: Generic data of the pin group (name and pins) * @funcs: A list of pinmux functions that can be selected for * this group. The index of the selected function is used * for programming the function selector. @@ -61,9 +69,7 @@ struct msm_function { * otherwise 1. */ struct msm_pingroup { - const char *name; - const unsigned *pins; - unsigned npins; + struct pingroup grp; unsigned *funcs; unsigned nfuncs; @@ -138,7 +144,7 @@ struct msm_gpio_wakeirq_map { struct msm_pinctrl_soc_data { const struct pinctrl_pin_desc *pins; unsigned npins; - const struct msm_function *functions; + const struct pinfunction *functions; unsigned nfunctions; const struct msm_pingroup *groups; unsigned ngroups; diff --git a/drivers/pinctrl/qcom/pinctrl-msm8226.c b/drivers/pinctrl/qcom/pinctrl-msm8226.c index 0f05725e0a2112ce376112f12e9dd1262f585f17..994619840a706c810c340e55371849f6159f46c7 100644 --- a/drivers/pinctrl/qcom/pinctrl-msm8226.c +++ b/drivers/pinctrl/qcom/pinctrl-msm8226.c @@ -6,7 +6,6 @@ #include #include #include -#include #include "pinctrl-msm.h" @@ -263,27 +262,20 @@ static const unsigned int sdc2_clk_pins[] = { 120 }; static const unsigned int sdc2_cmd_pins[] = { 121 }; static const unsigned int sdc2_data_pins[] = { 122 }; -#define FUNCTION(fname) \ - [MSM_MUX_##fname] = { \ - .name = #fname, \ - .groups = fname##_groups, \ - .ngroups = ARRAY_SIZE(fname##_groups), \ - } - #define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7) \ { \ - .name = "gpio" #id, \ - .pins = gpio##id##_pins, \ - .npins = ARRAY_SIZE(gpio##id##_pins), \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ .funcs = (int[]){ \ - MSM_MUX_gpio, \ - MSM_MUX_##f1, \ - MSM_MUX_##f2, \ - MSM_MUX_##f3, \ - MSM_MUX_##f4, \ - MSM_MUX_##f5, \ - MSM_MUX_##f6, \ - MSM_MUX_##f7 \ + msm_mux_gpio, \ + msm_mux_##f1, \ + msm_mux_##f2, \ + msm_mux_##f3, \ + msm_mux_##f4, \ + msm_mux_##f5, \ + msm_mux_##f6, \ + msm_mux_##f7 \ }, \ .nfuncs = 8, \ .ctl_reg = 0x1000 + 0x10 * id, \ @@ -309,9 +301,9 @@ static const unsigned int sdc2_data_pins[] = { 122 }; #define SDC_PINGROUP(pg_name, ctl, pull, drv) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = ctl, \ .io_reg = 0, \ .intr_cfg_reg = 0, \ @@ -338,36 +330,36 @@ static const unsigned int sdc2_data_pins[] = { 122 }; * the pingroup table below. */ enum msm8226_functions { - MSM_MUX_audio_pcm, - MSM_MUX_blsp_i2c1, - MSM_MUX_blsp_i2c2, - MSM_MUX_blsp_i2c3, - MSM_MUX_blsp_i2c4, - MSM_MUX_blsp_i2c5, - MSM_MUX_blsp_spi1, - MSM_MUX_blsp_spi2, - MSM_MUX_blsp_spi3, - MSM_MUX_blsp_spi4, - MSM_MUX_blsp_spi5, - MSM_MUX_blsp_uart1, - MSM_MUX_blsp_uart2, - MSM_MUX_blsp_uart3, - MSM_MUX_blsp_uart4, - MSM_MUX_blsp_uart5, - MSM_MUX_blsp_uim1, - MSM_MUX_blsp_uim2, - MSM_MUX_blsp_uim3, - MSM_MUX_blsp_uim4, - MSM_MUX_blsp_uim5, - MSM_MUX_cam_mclk0, - MSM_MUX_cam_mclk1, - MSM_MUX_cci_i2c0, - MSM_MUX_gp0_clk, - MSM_MUX_gp1_clk, - MSM_MUX_gpio, - MSM_MUX_sdc3, - MSM_MUX_wlan, - MSM_MUX_NA, + msm_mux_audio_pcm, + msm_mux_blsp_i2c1, + msm_mux_blsp_i2c2, + msm_mux_blsp_i2c3, + msm_mux_blsp_i2c4, + msm_mux_blsp_i2c5, + msm_mux_blsp_spi1, + msm_mux_blsp_spi2, + msm_mux_blsp_spi3, + msm_mux_blsp_spi4, + msm_mux_blsp_spi5, + msm_mux_blsp_uart1, + msm_mux_blsp_uart2, + msm_mux_blsp_uart3, + msm_mux_blsp_uart4, + msm_mux_blsp_uart5, + msm_mux_blsp_uim1, + msm_mux_blsp_uim2, + msm_mux_blsp_uim3, + msm_mux_blsp_uim4, + msm_mux_blsp_uim5, + msm_mux_cam_mclk0, + msm_mux_cam_mclk1, + msm_mux_cci_i2c0, + msm_mux_gp0_clk, + msm_mux_gp1_clk, + msm_mux_gpio, + msm_mux_sdc3, + msm_mux_wlan, + msm_mux_NA, }; static const char * const gpio_groups[] = { @@ -460,36 +452,36 @@ static const char * const wlan_groups[] = { "gpio40", "gpio41", "gpio42", "gpio43", "gpio44" }; -static const struct msm_function msm8226_functions[] = { - FUNCTION(audio_pcm), - FUNCTION(blsp_i2c1), - FUNCTION(blsp_i2c2), - FUNCTION(blsp_i2c3), - FUNCTION(blsp_i2c4), - FUNCTION(blsp_i2c5), - FUNCTION(blsp_spi1), - FUNCTION(blsp_spi2), - FUNCTION(blsp_spi3), - FUNCTION(blsp_spi4), - FUNCTION(blsp_spi5), - FUNCTION(blsp_uart1), - FUNCTION(blsp_uart2), - FUNCTION(blsp_uart3), - FUNCTION(blsp_uart4), - FUNCTION(blsp_uart5), - FUNCTION(blsp_uim1), - FUNCTION(blsp_uim2), - FUNCTION(blsp_uim3), - FUNCTION(blsp_uim4), - FUNCTION(blsp_uim5), - FUNCTION(cam_mclk0), - FUNCTION(cam_mclk1), - FUNCTION(cci_i2c0), - FUNCTION(gp0_clk), - FUNCTION(gp1_clk), - FUNCTION(gpio), - FUNCTION(sdc3), - FUNCTION(wlan), +static const struct pinfunction msm8226_functions[] = { + MSM_PIN_FUNCTION(audio_pcm), + MSM_PIN_FUNCTION(blsp_i2c1), + MSM_PIN_FUNCTION(blsp_i2c2), + MSM_PIN_FUNCTION(blsp_i2c3), + MSM_PIN_FUNCTION(blsp_i2c4), + MSM_PIN_FUNCTION(blsp_i2c5), + MSM_PIN_FUNCTION(blsp_spi1), + MSM_PIN_FUNCTION(blsp_spi2), + MSM_PIN_FUNCTION(blsp_spi3), + MSM_PIN_FUNCTION(blsp_spi4), + MSM_PIN_FUNCTION(blsp_spi5), + MSM_PIN_FUNCTION(blsp_uart1), + MSM_PIN_FUNCTION(blsp_uart2), + MSM_PIN_FUNCTION(blsp_uart3), + MSM_PIN_FUNCTION(blsp_uart4), + MSM_PIN_FUNCTION(blsp_uart5), + MSM_PIN_FUNCTION(blsp_uim1), + MSM_PIN_FUNCTION(blsp_uim2), + MSM_PIN_FUNCTION(blsp_uim3), + MSM_PIN_FUNCTION(blsp_uim4), + MSM_PIN_FUNCTION(blsp_uim5), + MSM_PIN_FUNCTION(cam_mclk0), + MSM_PIN_FUNCTION(cam_mclk1), + MSM_PIN_FUNCTION(cci_i2c0), + MSM_PIN_FUNCTION(gp0_clk), + MSM_PIN_FUNCTION(gp1_clk), + MSM_PIN_FUNCTION(gpio), + MSM_PIN_FUNCTION(sdc3), + MSM_PIN_FUNCTION(wlan), }; static const struct msm_pingroup msm8226_groups[] = { diff --git a/drivers/pinctrl/qcom/pinctrl-msm8660.c b/drivers/pinctrl/qcom/pinctrl-msm8660.c index 16e562eaad17a295c04380c3275e1228f8f899bc..999a5f867eb5081232443a893773d73c8dc65d1b 100644 --- a/drivers/pinctrl/qcom/pinctrl-msm8660.c +++ b/drivers/pinctrl/qcom/pinctrl-msm8660.c @@ -6,7 +6,6 @@ #include #include #include -#include #include "pinctrl-msm.h" @@ -375,27 +374,20 @@ static const unsigned int sdc3_clk_pins[] = { 176 }; static const unsigned int sdc3_cmd_pins[] = { 177 }; static const unsigned int sdc3_data_pins[] = { 178 }; -#define FUNCTION(fname) \ - [MSM_MUX_##fname] = { \ - .name = #fname, \ - .groups = fname##_groups, \ - .ngroups = ARRAY_SIZE(fname##_groups), \ - } - #define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7) \ { \ - .name = "gpio" #id, \ - .pins = gpio##id##_pins, \ - .npins = ARRAY_SIZE(gpio##id##_pins), \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ .funcs = (int[]){ \ - MSM_MUX_gpio, \ - MSM_MUX_##f1, \ - MSM_MUX_##f2, \ - MSM_MUX_##f3, \ - MSM_MUX_##f4, \ - MSM_MUX_##f5, \ - MSM_MUX_##f6, \ - MSM_MUX_##f7, \ + msm_mux_gpio, \ + msm_mux_##f1, \ + msm_mux_##f2, \ + msm_mux_##f3, \ + msm_mux_##f4, \ + msm_mux_##f5, \ + msm_mux_##f6, \ + msm_mux_##f7, \ }, \ .nfuncs = 8, \ .ctl_reg = 0x1000 + 0x10 * id, \ @@ -422,9 +414,9 @@ static const unsigned int sdc3_data_pins[] = { 178 }; #define SDC_PINGROUP(pg_name, ctl, pull, drv) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = ctl, \ .io_reg = 0, \ .intr_cfg_reg = 0, \ @@ -447,60 +439,60 @@ static const unsigned int sdc3_data_pins[] = { 178 }; } enum msm8660_functions { - MSM_MUX_gpio, - MSM_MUX_cam_mclk, - MSM_MUX_dsub, - MSM_MUX_ext_gps, - MSM_MUX_gp_clk_0a, - MSM_MUX_gp_clk_0b, - MSM_MUX_gp_clk_1a, - MSM_MUX_gp_clk_1b, - MSM_MUX_gp_clk_2a, - MSM_MUX_gp_clk_2b, - MSM_MUX_gp_mn, - MSM_MUX_gsbi1, - MSM_MUX_gsbi1_spi_cs1_n, - MSM_MUX_gsbi1_spi_cs2a_n, - MSM_MUX_gsbi1_spi_cs2b_n, - MSM_MUX_gsbi1_spi_cs3_n, - MSM_MUX_gsbi2, - MSM_MUX_gsbi2_spi_cs1_n, - MSM_MUX_gsbi2_spi_cs2_n, - MSM_MUX_gsbi2_spi_cs3_n, - MSM_MUX_gsbi3, - MSM_MUX_gsbi3_spi_cs1_n, - MSM_MUX_gsbi3_spi_cs2_n, - MSM_MUX_gsbi3_spi_cs3_n, - MSM_MUX_gsbi4, - MSM_MUX_gsbi5, - MSM_MUX_gsbi6, - MSM_MUX_gsbi7, - MSM_MUX_gsbi8, - MSM_MUX_gsbi9, - MSM_MUX_gsbi10, - MSM_MUX_gsbi11, - MSM_MUX_gsbi12, - MSM_MUX_hdmi, - MSM_MUX_i2s, - MSM_MUX_lcdc, - MSM_MUX_mdp_vsync, - MSM_MUX_mi2s, - MSM_MUX_pcm, - MSM_MUX_ps_hold, - MSM_MUX_sdc1, - MSM_MUX_sdc2, - MSM_MUX_sdc5, - MSM_MUX_tsif1, - MSM_MUX_tsif2, - MSM_MUX_usb_fs1, - MSM_MUX_usb_fs1_oe_n, - MSM_MUX_usb_fs2, - MSM_MUX_usb_fs2_oe_n, - MSM_MUX_vfe, - MSM_MUX_vsens_alarm, - MSM_MUX_ebi2cs, - MSM_MUX_ebi2, - MSM_MUX__, + msm_mux_gpio, + msm_mux_cam_mclk, + msm_mux_dsub, + msm_mux_ext_gps, + msm_mux_gp_clk_0a, + msm_mux_gp_clk_0b, + msm_mux_gp_clk_1a, + msm_mux_gp_clk_1b, + msm_mux_gp_clk_2a, + msm_mux_gp_clk_2b, + msm_mux_gp_mn, + msm_mux_gsbi1, + msm_mux_gsbi1_spi_cs1_n, + msm_mux_gsbi1_spi_cs2a_n, + msm_mux_gsbi1_spi_cs2b_n, + msm_mux_gsbi1_spi_cs3_n, + msm_mux_gsbi2, + msm_mux_gsbi2_spi_cs1_n, + msm_mux_gsbi2_spi_cs2_n, + msm_mux_gsbi2_spi_cs3_n, + msm_mux_gsbi3, + msm_mux_gsbi3_spi_cs1_n, + msm_mux_gsbi3_spi_cs2_n, + msm_mux_gsbi3_spi_cs3_n, + msm_mux_gsbi4, + msm_mux_gsbi5, + msm_mux_gsbi6, + msm_mux_gsbi7, + msm_mux_gsbi8, + msm_mux_gsbi9, + msm_mux_gsbi10, + msm_mux_gsbi11, + msm_mux_gsbi12, + msm_mux_hdmi, + msm_mux_i2s, + msm_mux_lcdc, + msm_mux_mdp_vsync, + msm_mux_mi2s, + msm_mux_pcm, + msm_mux_ps_hold, + msm_mux_sdc1, + msm_mux_sdc2, + msm_mux_sdc5, + msm_mux_tsif1, + msm_mux_tsif2, + msm_mux_usb_fs1, + msm_mux_usb_fs1_oe_n, + msm_mux_usb_fs2, + msm_mux_usb_fs2_oe_n, + msm_mux_vfe, + msm_mux_vsens_alarm, + msm_mux_ebi2cs, + msm_mux_ebi2, + msm_mux__, }; static const char * const gpio_groups[] = { @@ -721,60 +713,60 @@ static const char * const ebi2_groups[] = { "gpio158", /* busy */ }; -static const struct msm_function msm8660_functions[] = { - FUNCTION(gpio), - FUNCTION(cam_mclk), - FUNCTION(dsub), - FUNCTION(ext_gps), - FUNCTION(gp_clk_0a), - FUNCTION(gp_clk_0b), - FUNCTION(gp_clk_1a), - FUNCTION(gp_clk_1b), - FUNCTION(gp_clk_2a), - FUNCTION(gp_clk_2b), - FUNCTION(gp_mn), - FUNCTION(gsbi1), - FUNCTION(gsbi1_spi_cs1_n), - FUNCTION(gsbi1_spi_cs2a_n), - FUNCTION(gsbi1_spi_cs2b_n), - FUNCTION(gsbi1_spi_cs3_n), - FUNCTION(gsbi2), - FUNCTION(gsbi2_spi_cs1_n), - FUNCTION(gsbi2_spi_cs2_n), - FUNCTION(gsbi2_spi_cs3_n), - FUNCTION(gsbi3), - FUNCTION(gsbi3_spi_cs1_n), - FUNCTION(gsbi3_spi_cs2_n), - FUNCTION(gsbi3_spi_cs3_n), - FUNCTION(gsbi4), - FUNCTION(gsbi5), - FUNCTION(gsbi6), - FUNCTION(gsbi7), - FUNCTION(gsbi8), - FUNCTION(gsbi9), - FUNCTION(gsbi10), - FUNCTION(gsbi11), - FUNCTION(gsbi12), - FUNCTION(hdmi), - FUNCTION(i2s), - FUNCTION(lcdc), - FUNCTION(mdp_vsync), - FUNCTION(mi2s), - FUNCTION(pcm), - FUNCTION(ps_hold), - FUNCTION(sdc1), - FUNCTION(sdc2), - FUNCTION(sdc5), - FUNCTION(tsif1), - FUNCTION(tsif2), - FUNCTION(usb_fs1), - FUNCTION(usb_fs1_oe_n), - FUNCTION(usb_fs2), - FUNCTION(usb_fs2_oe_n), - FUNCTION(vfe), - FUNCTION(vsens_alarm), - FUNCTION(ebi2cs), /* for EBI2 chip selects */ - FUNCTION(ebi2), /* for general EBI2 pins */ +static const struct pinfunction msm8660_functions[] = { + MSM_PIN_FUNCTION(gpio), + MSM_PIN_FUNCTION(cam_mclk), + MSM_PIN_FUNCTION(dsub), + MSM_PIN_FUNCTION(ext_gps), + MSM_PIN_FUNCTION(gp_clk_0a), + MSM_PIN_FUNCTION(gp_clk_0b), + MSM_PIN_FUNCTION(gp_clk_1a), + MSM_PIN_FUNCTION(gp_clk_1b), + MSM_PIN_FUNCTION(gp_clk_2a), + MSM_PIN_FUNCTION(gp_clk_2b), + MSM_PIN_FUNCTION(gp_mn), + MSM_PIN_FUNCTION(gsbi1), + MSM_PIN_FUNCTION(gsbi1_spi_cs1_n), + MSM_PIN_FUNCTION(gsbi1_spi_cs2a_n), + MSM_PIN_FUNCTION(gsbi1_spi_cs2b_n), + MSM_PIN_FUNCTION(gsbi1_spi_cs3_n), + MSM_PIN_FUNCTION(gsbi2), + MSM_PIN_FUNCTION(gsbi2_spi_cs1_n), + MSM_PIN_FUNCTION(gsbi2_spi_cs2_n), + MSM_PIN_FUNCTION(gsbi2_spi_cs3_n), + MSM_PIN_FUNCTION(gsbi3), + MSM_PIN_FUNCTION(gsbi3_spi_cs1_n), + MSM_PIN_FUNCTION(gsbi3_spi_cs2_n), + MSM_PIN_FUNCTION(gsbi3_spi_cs3_n), + MSM_PIN_FUNCTION(gsbi4), + MSM_PIN_FUNCTION(gsbi5), + MSM_PIN_FUNCTION(gsbi6), + MSM_PIN_FUNCTION(gsbi7), + MSM_PIN_FUNCTION(gsbi8), + MSM_PIN_FUNCTION(gsbi9), + MSM_PIN_FUNCTION(gsbi10), + MSM_PIN_FUNCTION(gsbi11), + MSM_PIN_FUNCTION(gsbi12), + MSM_PIN_FUNCTION(hdmi), + MSM_PIN_FUNCTION(i2s), + MSM_PIN_FUNCTION(lcdc), + MSM_PIN_FUNCTION(mdp_vsync), + MSM_PIN_FUNCTION(mi2s), + MSM_PIN_FUNCTION(pcm), + MSM_PIN_FUNCTION(ps_hold), + MSM_PIN_FUNCTION(sdc1), + MSM_PIN_FUNCTION(sdc2), + MSM_PIN_FUNCTION(sdc5), + MSM_PIN_FUNCTION(tsif1), + MSM_PIN_FUNCTION(tsif2), + MSM_PIN_FUNCTION(usb_fs1), + MSM_PIN_FUNCTION(usb_fs1_oe_n), + MSM_PIN_FUNCTION(usb_fs2), + MSM_PIN_FUNCTION(usb_fs2_oe_n), + MSM_PIN_FUNCTION(vfe), + MSM_PIN_FUNCTION(vsens_alarm), + MSM_PIN_FUNCTION(ebi2cs), /* for EBI2 chip selects */ + MSM_PIN_FUNCTION(ebi2), /* for general EBI2 pins */ }; static const struct msm_pingroup msm8660_groups[] = { diff --git a/drivers/pinctrl/qcom/pinctrl-msm8909.c b/drivers/pinctrl/qcom/pinctrl-msm8909.c index 6dd15b910632e216b52846bf0d354e864a039bb5..756856d20d6b5f2d4e764ff32f2493de24ca677c 100644 --- a/drivers/pinctrl/qcom/pinctrl-msm8909.c +++ b/drivers/pinctrl/qcom/pinctrl-msm8909.c @@ -7,23 +7,15 @@ #include #include #include -#include #include "pinctrl-msm.h" -#define FUNCTION(fname) \ - [msm_mux_##fname] = { \ - .name = #fname, \ - .groups = fname##_groups, \ - .ngroups = ARRAY_SIZE(fname##_groups), \ - } - #define REG_SIZE 0x1000 #define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9) \ { \ - .name = "gpio" #id, \ - .pins = gpio##id##_pins, \ - .npins = ARRAY_SIZE(gpio##id##_pins), \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ .funcs = (int[]){ \ msm_mux_gpio, \ msm_mux_##f1, \ @@ -60,9 +52,9 @@ #define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = ctl, \ .io_reg = 0, \ .intr_cfg_reg = 0, \ @@ -643,130 +635,130 @@ static const char * const wcss_wlan_groups[] = { "gpio40", "gpio41", "gpio42", "gpio43", "gpio44" }; -static const struct msm_function msm8909_functions[] = { - FUNCTION(adsp_ext), - FUNCTION(atest_bbrx0), - FUNCTION(atest_bbrx1), - FUNCTION(atest_char), - FUNCTION(atest_char0), - FUNCTION(atest_char1), - FUNCTION(atest_char2), - FUNCTION(atest_char3), - FUNCTION(atest_combodac), - FUNCTION(atest_gpsadc0), - FUNCTION(atest_gpsadc1), - FUNCTION(atest_wlan0), - FUNCTION(atest_wlan1), - FUNCTION(bimc_dte0), - FUNCTION(bimc_dte1), - FUNCTION(blsp_i2c1), - FUNCTION(blsp_i2c2), - FUNCTION(blsp_i2c3), - FUNCTION(blsp_i2c4), - FUNCTION(blsp_i2c5), - FUNCTION(blsp_i2c6), - FUNCTION(blsp_spi1), - FUNCTION(blsp_spi1_cs1), - FUNCTION(blsp_spi1_cs2), - FUNCTION(blsp_spi1_cs3), - FUNCTION(blsp_spi2), - FUNCTION(blsp_spi2_cs1), - FUNCTION(blsp_spi2_cs2), - FUNCTION(blsp_spi2_cs3), - FUNCTION(blsp_spi3), - FUNCTION(blsp_spi3_cs1), - FUNCTION(blsp_spi3_cs2), - FUNCTION(blsp_spi3_cs3), - FUNCTION(blsp_spi4), - FUNCTION(blsp_spi5), - FUNCTION(blsp_spi6), - FUNCTION(blsp_uart1), - FUNCTION(blsp_uart2), - FUNCTION(blsp_uim1), - FUNCTION(blsp_uim2), - FUNCTION(cam_mclk), - FUNCTION(cci_async), - FUNCTION(cci_timer0), - FUNCTION(cci_timer1), - FUNCTION(cci_timer2), - FUNCTION(cdc_pdm0), - FUNCTION(dbg_out), - FUNCTION(dmic0_clk), - FUNCTION(dmic0_data), - FUNCTION(ebi0_wrcdc), - FUNCTION(ebi2_a), - FUNCTION(ebi2_lcd), - FUNCTION(ext_lpass), - FUNCTION(gcc_gp1_clk_a), - FUNCTION(gcc_gp1_clk_b), - FUNCTION(gcc_gp2_clk_a), - FUNCTION(gcc_gp2_clk_b), - FUNCTION(gcc_gp3_clk_a), - FUNCTION(gcc_gp3_clk_b), - FUNCTION(gcc_plltest), - FUNCTION(gpio), - FUNCTION(gsm0_tx), - FUNCTION(ldo_en), - FUNCTION(ldo_update), - FUNCTION(m_voc), - FUNCTION(mdp_vsync), - FUNCTION(modem_tsync), - FUNCTION(nav_pps), - FUNCTION(nav_tsync), - FUNCTION(pa_indicator), - FUNCTION(pbs0), - FUNCTION(pbs1), - FUNCTION(pbs2), - FUNCTION(pri_mi2s_data0_a), - FUNCTION(pri_mi2s_data0_b), - FUNCTION(pri_mi2s_data1_a), - FUNCTION(pri_mi2s_data1_b), - FUNCTION(pri_mi2s_mclk_a), - FUNCTION(pri_mi2s_mclk_b), - FUNCTION(pri_mi2s_sck_a), - FUNCTION(pri_mi2s_sck_b), - FUNCTION(pri_mi2s_ws_a), - FUNCTION(pri_mi2s_ws_b), - FUNCTION(prng_rosc), - FUNCTION(pwr_crypto_enabled_a), - FUNCTION(pwr_crypto_enabled_b), - FUNCTION(pwr_modem_enabled_a), - FUNCTION(pwr_modem_enabled_b), - FUNCTION(pwr_nav_enabled_a), - FUNCTION(pwr_nav_enabled_b), - FUNCTION(qdss_cti_trig_in_a0), - FUNCTION(qdss_cti_trig_in_a1), - FUNCTION(qdss_cti_trig_in_b0), - FUNCTION(qdss_cti_trig_in_b1), - FUNCTION(qdss_cti_trig_out_a0), - FUNCTION(qdss_cti_trig_out_a1), - FUNCTION(qdss_cti_trig_out_b0), - FUNCTION(qdss_cti_trig_out_b1), - FUNCTION(qdss_traceclk_a), - FUNCTION(qdss_tracectl_a), - FUNCTION(qdss_tracedata_a), - FUNCTION(qdss_tracedata_b), - FUNCTION(sd_write), - FUNCTION(sec_mi2s), - FUNCTION(smb_int), - FUNCTION(ssbi0), - FUNCTION(ssbi1), - FUNCTION(uim1_clk), - FUNCTION(uim1_data), - FUNCTION(uim1_present), - FUNCTION(uim1_reset), - FUNCTION(uim2_clk), - FUNCTION(uim2_data), - FUNCTION(uim2_present), - FUNCTION(uim2_reset), - FUNCTION(uim3_clk), - FUNCTION(uim3_data), - FUNCTION(uim3_present), - FUNCTION(uim3_reset), - FUNCTION(uim_batt), - FUNCTION(wcss_bt), - FUNCTION(wcss_fm), - FUNCTION(wcss_wlan), +static const struct pinfunction msm8909_functions[] = { + MSM_PIN_FUNCTION(adsp_ext), + MSM_PIN_FUNCTION(atest_bbrx0), + MSM_PIN_FUNCTION(atest_bbrx1), + MSM_PIN_FUNCTION(atest_char), + MSM_PIN_FUNCTION(atest_char0), + MSM_PIN_FUNCTION(atest_char1), + MSM_PIN_FUNCTION(atest_char2), + MSM_PIN_FUNCTION(atest_char3), + MSM_PIN_FUNCTION(atest_combodac), + MSM_PIN_FUNCTION(atest_gpsadc0), + MSM_PIN_FUNCTION(atest_gpsadc1), + MSM_PIN_FUNCTION(atest_wlan0), + MSM_PIN_FUNCTION(atest_wlan1), + MSM_PIN_FUNCTION(bimc_dte0), + MSM_PIN_FUNCTION(bimc_dte1), + MSM_PIN_FUNCTION(blsp_i2c1), + MSM_PIN_FUNCTION(blsp_i2c2), + MSM_PIN_FUNCTION(blsp_i2c3), + MSM_PIN_FUNCTION(blsp_i2c4), + MSM_PIN_FUNCTION(blsp_i2c5), + MSM_PIN_FUNCTION(blsp_i2c6), + MSM_PIN_FUNCTION(blsp_spi1), + MSM_PIN_FUNCTION(blsp_spi1_cs1), + MSM_PIN_FUNCTION(blsp_spi1_cs2), + MSM_PIN_FUNCTION(blsp_spi1_cs3), + MSM_PIN_FUNCTION(blsp_spi2), + MSM_PIN_FUNCTION(blsp_spi2_cs1), + MSM_PIN_FUNCTION(blsp_spi2_cs2), + MSM_PIN_FUNCTION(blsp_spi2_cs3), + MSM_PIN_FUNCTION(blsp_spi3), + MSM_PIN_FUNCTION(blsp_spi3_cs1), + MSM_PIN_FUNCTION(blsp_spi3_cs2), + MSM_PIN_FUNCTION(blsp_spi3_cs3), + MSM_PIN_FUNCTION(blsp_spi4), + MSM_PIN_FUNCTION(blsp_spi5), + MSM_PIN_FUNCTION(blsp_spi6), + MSM_PIN_FUNCTION(blsp_uart1), + MSM_PIN_FUNCTION(blsp_uart2), + MSM_PIN_FUNCTION(blsp_uim1), + MSM_PIN_FUNCTION(blsp_uim2), + MSM_PIN_FUNCTION(cam_mclk), + MSM_PIN_FUNCTION(cci_async), + MSM_PIN_FUNCTION(cci_timer0), + MSM_PIN_FUNCTION(cci_timer1), + MSM_PIN_FUNCTION(cci_timer2), + MSM_PIN_FUNCTION(cdc_pdm0), + MSM_PIN_FUNCTION(dbg_out), + MSM_PIN_FUNCTION(dmic0_clk), + MSM_PIN_FUNCTION(dmic0_data), + MSM_PIN_FUNCTION(ebi0_wrcdc), + MSM_PIN_FUNCTION(ebi2_a), + MSM_PIN_FUNCTION(ebi2_lcd), + MSM_PIN_FUNCTION(ext_lpass), + MSM_PIN_FUNCTION(gcc_gp1_clk_a), + MSM_PIN_FUNCTION(gcc_gp1_clk_b), + MSM_PIN_FUNCTION(gcc_gp2_clk_a), + MSM_PIN_FUNCTION(gcc_gp2_clk_b), + MSM_PIN_FUNCTION(gcc_gp3_clk_a), + MSM_PIN_FUNCTION(gcc_gp3_clk_b), + MSM_PIN_FUNCTION(gcc_plltest), + MSM_PIN_FUNCTION(gpio), + MSM_PIN_FUNCTION(gsm0_tx), + MSM_PIN_FUNCTION(ldo_en), + MSM_PIN_FUNCTION(ldo_update), + MSM_PIN_FUNCTION(m_voc), + MSM_PIN_FUNCTION(mdp_vsync), + MSM_PIN_FUNCTION(modem_tsync), + MSM_PIN_FUNCTION(nav_pps), + MSM_PIN_FUNCTION(nav_tsync), + MSM_PIN_FUNCTION(pa_indicator), + MSM_PIN_FUNCTION(pbs0), + MSM_PIN_FUNCTION(pbs1), + MSM_PIN_FUNCTION(pbs2), + MSM_PIN_FUNCTION(pri_mi2s_data0_a), + MSM_PIN_FUNCTION(pri_mi2s_data0_b), + MSM_PIN_FUNCTION(pri_mi2s_data1_a), + MSM_PIN_FUNCTION(pri_mi2s_data1_b), + MSM_PIN_FUNCTION(pri_mi2s_mclk_a), + MSM_PIN_FUNCTION(pri_mi2s_mclk_b), + MSM_PIN_FUNCTION(pri_mi2s_sck_a), + MSM_PIN_FUNCTION(pri_mi2s_sck_b), + MSM_PIN_FUNCTION(pri_mi2s_ws_a), + MSM_PIN_FUNCTION(pri_mi2s_ws_b), + MSM_PIN_FUNCTION(prng_rosc), + MSM_PIN_FUNCTION(pwr_crypto_enabled_a), + MSM_PIN_FUNCTION(pwr_crypto_enabled_b), + MSM_PIN_FUNCTION(pwr_modem_enabled_a), + MSM_PIN_FUNCTION(pwr_modem_enabled_b), + MSM_PIN_FUNCTION(pwr_nav_enabled_a), + MSM_PIN_FUNCTION(pwr_nav_enabled_b), + MSM_PIN_FUNCTION(qdss_cti_trig_in_a0), + MSM_PIN_FUNCTION(qdss_cti_trig_in_a1), + MSM_PIN_FUNCTION(qdss_cti_trig_in_b0), + MSM_PIN_FUNCTION(qdss_cti_trig_in_b1), + MSM_PIN_FUNCTION(qdss_cti_trig_out_a0), + MSM_PIN_FUNCTION(qdss_cti_trig_out_a1), + MSM_PIN_FUNCTION(qdss_cti_trig_out_b0), + MSM_PIN_FUNCTION(qdss_cti_trig_out_b1), + MSM_PIN_FUNCTION(qdss_traceclk_a), + MSM_PIN_FUNCTION(qdss_tracectl_a), + MSM_PIN_FUNCTION(qdss_tracedata_a), + MSM_PIN_FUNCTION(qdss_tracedata_b), + MSM_PIN_FUNCTION(sd_write), + MSM_PIN_FUNCTION(sec_mi2s), + MSM_PIN_FUNCTION(smb_int), + MSM_PIN_FUNCTION(ssbi0), + MSM_PIN_FUNCTION(ssbi1), + MSM_PIN_FUNCTION(uim1_clk), + MSM_PIN_FUNCTION(uim1_data), + MSM_PIN_FUNCTION(uim1_present), + MSM_PIN_FUNCTION(uim1_reset), + MSM_PIN_FUNCTION(uim2_clk), + MSM_PIN_FUNCTION(uim2_data), + MSM_PIN_FUNCTION(uim2_present), + MSM_PIN_FUNCTION(uim2_reset), + MSM_PIN_FUNCTION(uim3_clk), + MSM_PIN_FUNCTION(uim3_data), + MSM_PIN_FUNCTION(uim3_present), + MSM_PIN_FUNCTION(uim3_reset), + MSM_PIN_FUNCTION(uim_batt), + MSM_PIN_FUNCTION(wcss_bt), + MSM_PIN_FUNCTION(wcss_fm), + MSM_PIN_FUNCTION(wcss_wlan), }; static const struct msm_pingroup msm8909_groups[] = { diff --git a/drivers/pinctrl/qcom/pinctrl-msm8916.c b/drivers/pinctrl/qcom/pinctrl-msm8916.c index bf68913ba8212bea9e2fb260f9cf54fdf2a711d4..cea5c54f92fec1829c5378a8441eb8710fd500f0 100644 --- a/drivers/pinctrl/qcom/pinctrl-msm8916.c +++ b/drivers/pinctrl/qcom/pinctrl-msm8916.c @@ -6,7 +6,6 @@ #include #include #include -#include #include "pinctrl-msm.h" @@ -286,29 +285,22 @@ static const unsigned int qdsd_data1_pins[] = { 131 }; static const unsigned int qdsd_data2_pins[] = { 132 }; static const unsigned int qdsd_data3_pins[] = { 133 }; -#define FUNCTION(fname) \ - [MSM_MUX_##fname] = { \ - .name = #fname, \ - .groups = fname##_groups, \ - .ngroups = ARRAY_SIZE(fname##_groups), \ - } - #define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9) \ { \ - .name = "gpio" #id, \ - .pins = gpio##id##_pins, \ - .npins = ARRAY_SIZE(gpio##id##_pins), \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ .funcs = (int[]){ \ - MSM_MUX_gpio, \ - MSM_MUX_##f1, \ - MSM_MUX_##f2, \ - MSM_MUX_##f3, \ - MSM_MUX_##f4, \ - MSM_MUX_##f5, \ - MSM_MUX_##f6, \ - MSM_MUX_##f7, \ - MSM_MUX_##f8, \ - MSM_MUX_##f9 \ + msm_mux_gpio, \ + msm_mux_##f1, \ + msm_mux_##f2, \ + msm_mux_##f3, \ + msm_mux_##f4, \ + msm_mux_##f5, \ + msm_mux_##f6, \ + msm_mux_##f7, \ + msm_mux_##f8, \ + msm_mux_##f9 \ }, \ .nfuncs = 10, \ .ctl_reg = 0x1000 * id, \ @@ -334,9 +326,9 @@ static const unsigned int qdsd_data3_pins[] = { 133 }; #define SDC_PINGROUP(pg_name, ctl, pull, drv) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = ctl, \ .io_reg = 0, \ .intr_cfg_reg = 0, \ @@ -359,135 +351,135 @@ static const unsigned int qdsd_data3_pins[] = { 133 }; } enum msm8916_functions { - MSM_MUX_adsp_ext, - MSM_MUX_alsp_int, - MSM_MUX_atest_bbrx0, - MSM_MUX_atest_bbrx1, - MSM_MUX_atest_char, - MSM_MUX_atest_char0, - MSM_MUX_atest_char1, - MSM_MUX_atest_char2, - MSM_MUX_atest_char3, - MSM_MUX_atest_combodac, - MSM_MUX_atest_gpsadc0, - MSM_MUX_atest_gpsadc1, - MSM_MUX_atest_tsens, - MSM_MUX_atest_wlan0, - MSM_MUX_atest_wlan1, - MSM_MUX_backlight_en, - MSM_MUX_bimc_dte0, - MSM_MUX_bimc_dte1, - MSM_MUX_blsp_i2c1, - MSM_MUX_blsp_i2c2, - MSM_MUX_blsp_i2c3, - MSM_MUX_blsp_i2c4, - MSM_MUX_blsp_i2c5, - MSM_MUX_blsp_i2c6, - MSM_MUX_blsp_spi1, - MSM_MUX_blsp_spi1_cs1, - MSM_MUX_blsp_spi1_cs2, - MSM_MUX_blsp_spi1_cs3, - MSM_MUX_blsp_spi2, - MSM_MUX_blsp_spi2_cs1, - MSM_MUX_blsp_spi2_cs2, - MSM_MUX_blsp_spi2_cs3, - MSM_MUX_blsp_spi3, - MSM_MUX_blsp_spi3_cs1, - MSM_MUX_blsp_spi3_cs2, - MSM_MUX_blsp_spi3_cs3, - MSM_MUX_blsp_spi4, - MSM_MUX_blsp_spi5, - MSM_MUX_blsp_spi6, - MSM_MUX_blsp_uart1, - MSM_MUX_blsp_uart2, - MSM_MUX_blsp_uim1, - MSM_MUX_blsp_uim2, - MSM_MUX_cam1_rst, - MSM_MUX_cam1_standby, - MSM_MUX_cam_mclk0, - MSM_MUX_cam_mclk1, - MSM_MUX_cci_async, - MSM_MUX_cci_i2c, - MSM_MUX_cci_timer0, - MSM_MUX_cci_timer1, - MSM_MUX_cci_timer2, - MSM_MUX_cdc_pdm0, - MSM_MUX_codec_mad, - MSM_MUX_dbg_out, - MSM_MUX_display_5v, - MSM_MUX_dmic0_clk, - MSM_MUX_dmic0_data, - MSM_MUX_dsi_rst, - MSM_MUX_ebi0_wrcdc, - MSM_MUX_euro_us, - MSM_MUX_ext_lpass, - MSM_MUX_flash_strobe, - MSM_MUX_gcc_gp1_clk_a, - MSM_MUX_gcc_gp1_clk_b, - MSM_MUX_gcc_gp2_clk_a, - MSM_MUX_gcc_gp2_clk_b, - MSM_MUX_gcc_gp3_clk_a, - MSM_MUX_gcc_gp3_clk_b, - MSM_MUX_gpio, - MSM_MUX_gsm0_tx0, - MSM_MUX_gsm0_tx1, - MSM_MUX_gsm1_tx0, - MSM_MUX_gsm1_tx1, - MSM_MUX_gyro_accl, - MSM_MUX_kpsns0, - MSM_MUX_kpsns1, - MSM_MUX_kpsns2, - MSM_MUX_ldo_en, - MSM_MUX_ldo_update, - MSM_MUX_mag_int, - MSM_MUX_mdp_vsync, - MSM_MUX_modem_tsync, - MSM_MUX_m_voc, - MSM_MUX_nav_pps, - MSM_MUX_nav_tsync, - MSM_MUX_pa_indicator, - MSM_MUX_pbs0, - MSM_MUX_pbs1, - MSM_MUX_pbs2, - MSM_MUX_pri_mi2s, - MSM_MUX_pri_mi2s_ws, - MSM_MUX_prng_rosc, - MSM_MUX_pwr_crypto_enabled_a, - MSM_MUX_pwr_crypto_enabled_b, - MSM_MUX_pwr_modem_enabled_a, - MSM_MUX_pwr_modem_enabled_b, - MSM_MUX_pwr_nav_enabled_a, - MSM_MUX_pwr_nav_enabled_b, - MSM_MUX_qdss_ctitrig_in_a0, - MSM_MUX_qdss_ctitrig_in_a1, - MSM_MUX_qdss_ctitrig_in_b0, - MSM_MUX_qdss_ctitrig_in_b1, - MSM_MUX_qdss_ctitrig_out_a0, - MSM_MUX_qdss_ctitrig_out_a1, - MSM_MUX_qdss_ctitrig_out_b0, - MSM_MUX_qdss_ctitrig_out_b1, - MSM_MUX_qdss_traceclk_a, - MSM_MUX_qdss_traceclk_b, - MSM_MUX_qdss_tracectl_a, - MSM_MUX_qdss_tracectl_b, - MSM_MUX_qdss_tracedata_a, - MSM_MUX_qdss_tracedata_b, - MSM_MUX_reset_n, - MSM_MUX_sd_card, - MSM_MUX_sd_write, - MSM_MUX_sec_mi2s, - MSM_MUX_smb_int, - MSM_MUX_ssbi_wtr0, - MSM_MUX_ssbi_wtr1, - MSM_MUX_uim1, - MSM_MUX_uim2, - MSM_MUX_uim3, - MSM_MUX_uim_batt, - MSM_MUX_wcss_bt, - MSM_MUX_wcss_fm, - MSM_MUX_wcss_wlan, - MSM_MUX_webcam1_rst, - MSM_MUX_NA, + msm_mux_adsp_ext, + msm_mux_alsp_int, + msm_mux_atest_bbrx0, + msm_mux_atest_bbrx1, + msm_mux_atest_char, + msm_mux_atest_char0, + msm_mux_atest_char1, + msm_mux_atest_char2, + msm_mux_atest_char3, + msm_mux_atest_combodac, + msm_mux_atest_gpsadc0, + msm_mux_atest_gpsadc1, + msm_mux_atest_tsens, + msm_mux_atest_wlan0, + msm_mux_atest_wlan1, + msm_mux_backlight_en, + msm_mux_bimc_dte0, + msm_mux_bimc_dte1, + msm_mux_blsp_i2c1, + msm_mux_blsp_i2c2, + msm_mux_blsp_i2c3, + msm_mux_blsp_i2c4, + msm_mux_blsp_i2c5, + msm_mux_blsp_i2c6, + msm_mux_blsp_spi1, + msm_mux_blsp_spi1_cs1, + msm_mux_blsp_spi1_cs2, + msm_mux_blsp_spi1_cs3, + msm_mux_blsp_spi2, + msm_mux_blsp_spi2_cs1, + msm_mux_blsp_spi2_cs2, + msm_mux_blsp_spi2_cs3, + msm_mux_blsp_spi3, + msm_mux_blsp_spi3_cs1, + msm_mux_blsp_spi3_cs2, + msm_mux_blsp_spi3_cs3, + msm_mux_blsp_spi4, + msm_mux_blsp_spi5, + msm_mux_blsp_spi6, + msm_mux_blsp_uart1, + msm_mux_blsp_uart2, + msm_mux_blsp_uim1, + msm_mux_blsp_uim2, + msm_mux_cam1_rst, + msm_mux_cam1_standby, + msm_mux_cam_mclk0, + msm_mux_cam_mclk1, + msm_mux_cci_async, + msm_mux_cci_i2c, + msm_mux_cci_timer0, + msm_mux_cci_timer1, + msm_mux_cci_timer2, + msm_mux_cdc_pdm0, + msm_mux_codec_mad, + msm_mux_dbg_out, + msm_mux_display_5v, + msm_mux_dmic0_clk, + msm_mux_dmic0_data, + msm_mux_dsi_rst, + msm_mux_ebi0_wrcdc, + msm_mux_euro_us, + msm_mux_ext_lpass, + msm_mux_flash_strobe, + msm_mux_gcc_gp1_clk_a, + msm_mux_gcc_gp1_clk_b, + msm_mux_gcc_gp2_clk_a, + msm_mux_gcc_gp2_clk_b, + msm_mux_gcc_gp3_clk_a, + msm_mux_gcc_gp3_clk_b, + msm_mux_gpio, + msm_mux_gsm0_tx0, + msm_mux_gsm0_tx1, + msm_mux_gsm1_tx0, + msm_mux_gsm1_tx1, + msm_mux_gyro_accl, + msm_mux_kpsns0, + msm_mux_kpsns1, + msm_mux_kpsns2, + msm_mux_ldo_en, + msm_mux_ldo_update, + msm_mux_mag_int, + msm_mux_mdp_vsync, + msm_mux_modem_tsync, + msm_mux_m_voc, + msm_mux_nav_pps, + msm_mux_nav_tsync, + msm_mux_pa_indicator, + msm_mux_pbs0, + msm_mux_pbs1, + msm_mux_pbs2, + msm_mux_pri_mi2s, + msm_mux_pri_mi2s_ws, + msm_mux_prng_rosc, + msm_mux_pwr_crypto_enabled_a, + msm_mux_pwr_crypto_enabled_b, + msm_mux_pwr_modem_enabled_a, + msm_mux_pwr_modem_enabled_b, + msm_mux_pwr_nav_enabled_a, + msm_mux_pwr_nav_enabled_b, + msm_mux_qdss_ctitrig_in_a0, + msm_mux_qdss_ctitrig_in_a1, + msm_mux_qdss_ctitrig_in_b0, + msm_mux_qdss_ctitrig_in_b1, + msm_mux_qdss_ctitrig_out_a0, + msm_mux_qdss_ctitrig_out_a1, + msm_mux_qdss_ctitrig_out_b0, + msm_mux_qdss_ctitrig_out_b1, + msm_mux_qdss_traceclk_a, + msm_mux_qdss_traceclk_b, + msm_mux_qdss_tracectl_a, + msm_mux_qdss_tracectl_b, + msm_mux_qdss_tracedata_a, + msm_mux_qdss_tracedata_b, + msm_mux_reset_n, + msm_mux_sd_card, + msm_mux_sd_write, + msm_mux_sec_mi2s, + msm_mux_smb_int, + msm_mux_ssbi_wtr0, + msm_mux_ssbi_wtr1, + msm_mux_uim1, + msm_mux_uim2, + msm_mux_uim3, + msm_mux_uim_batt, + msm_mux_wcss_bt, + msm_mux_wcss_fm, + msm_mux_wcss_wlan, + msm_mux_webcam1_rst, + msm_mux_NA, }; static const char * const gpio_groups[] = { @@ -681,135 +673,135 @@ static const char * const wcss_wlan_groups[] = { }; static const char * const webcam1_rst_groups[] = { "gpio28" }; -static const struct msm_function msm8916_functions[] = { - FUNCTION(adsp_ext), - FUNCTION(alsp_int), - FUNCTION(atest_bbrx0), - FUNCTION(atest_bbrx1), - FUNCTION(atest_char), - FUNCTION(atest_char0), - FUNCTION(atest_char1), - FUNCTION(atest_char2), - FUNCTION(atest_char3), - FUNCTION(atest_combodac), - FUNCTION(atest_gpsadc0), - FUNCTION(atest_gpsadc1), - FUNCTION(atest_tsens), - FUNCTION(atest_wlan0), - FUNCTION(atest_wlan1), - FUNCTION(backlight_en), - FUNCTION(bimc_dte0), - FUNCTION(bimc_dte1), - FUNCTION(blsp_i2c1), - FUNCTION(blsp_i2c2), - FUNCTION(blsp_i2c3), - FUNCTION(blsp_i2c4), - FUNCTION(blsp_i2c5), - FUNCTION(blsp_i2c6), - FUNCTION(blsp_spi1), - FUNCTION(blsp_spi1_cs1), - FUNCTION(blsp_spi1_cs2), - FUNCTION(blsp_spi1_cs3), - FUNCTION(blsp_spi2), - FUNCTION(blsp_spi2_cs1), - FUNCTION(blsp_spi2_cs2), - FUNCTION(blsp_spi2_cs3), - FUNCTION(blsp_spi3), - FUNCTION(blsp_spi3_cs1), - FUNCTION(blsp_spi3_cs2), - FUNCTION(blsp_spi3_cs3), - FUNCTION(blsp_spi4), - FUNCTION(blsp_spi5), - FUNCTION(blsp_spi6), - FUNCTION(blsp_uart1), - FUNCTION(blsp_uart2), - FUNCTION(blsp_uim1), - FUNCTION(blsp_uim2), - FUNCTION(cam1_rst), - FUNCTION(cam1_standby), - FUNCTION(cam_mclk0), - FUNCTION(cam_mclk1), - FUNCTION(cci_async), - FUNCTION(cci_i2c), - FUNCTION(cci_timer0), - FUNCTION(cci_timer1), - FUNCTION(cci_timer2), - FUNCTION(cdc_pdm0), - FUNCTION(codec_mad), - FUNCTION(dbg_out), - FUNCTION(display_5v), - FUNCTION(dmic0_clk), - FUNCTION(dmic0_data), - FUNCTION(dsi_rst), - FUNCTION(ebi0_wrcdc), - FUNCTION(euro_us), - FUNCTION(ext_lpass), - FUNCTION(flash_strobe), - FUNCTION(gcc_gp1_clk_a), - FUNCTION(gcc_gp1_clk_b), - FUNCTION(gcc_gp2_clk_a), - FUNCTION(gcc_gp2_clk_b), - FUNCTION(gcc_gp3_clk_a), - FUNCTION(gcc_gp3_clk_b), - FUNCTION(gpio), - FUNCTION(gsm0_tx0), - FUNCTION(gsm0_tx1), - FUNCTION(gsm1_tx0), - FUNCTION(gsm1_tx1), - FUNCTION(gyro_accl), - FUNCTION(kpsns0), - FUNCTION(kpsns1), - FUNCTION(kpsns2), - FUNCTION(ldo_en), - FUNCTION(ldo_update), - FUNCTION(mag_int), - FUNCTION(mdp_vsync), - FUNCTION(modem_tsync), - FUNCTION(m_voc), - FUNCTION(nav_pps), - FUNCTION(nav_tsync), - FUNCTION(pa_indicator), - FUNCTION(pbs0), - FUNCTION(pbs1), - FUNCTION(pbs2), - FUNCTION(pri_mi2s), - FUNCTION(pri_mi2s_ws), - FUNCTION(prng_rosc), - FUNCTION(pwr_crypto_enabled_a), - FUNCTION(pwr_crypto_enabled_b), - FUNCTION(pwr_modem_enabled_a), - FUNCTION(pwr_modem_enabled_b), - FUNCTION(pwr_nav_enabled_a), - FUNCTION(pwr_nav_enabled_b), - FUNCTION(qdss_ctitrig_in_a0), - FUNCTION(qdss_ctitrig_in_a1), - FUNCTION(qdss_ctitrig_in_b0), - FUNCTION(qdss_ctitrig_in_b1), - FUNCTION(qdss_ctitrig_out_a0), - FUNCTION(qdss_ctitrig_out_a1), - FUNCTION(qdss_ctitrig_out_b0), - FUNCTION(qdss_ctitrig_out_b1), - FUNCTION(qdss_traceclk_a), - FUNCTION(qdss_traceclk_b), - FUNCTION(qdss_tracectl_a), - FUNCTION(qdss_tracectl_b), - FUNCTION(qdss_tracedata_a), - FUNCTION(qdss_tracedata_b), - FUNCTION(reset_n), - FUNCTION(sd_card), - FUNCTION(sd_write), - FUNCTION(sec_mi2s), - FUNCTION(smb_int), - FUNCTION(ssbi_wtr0), - FUNCTION(ssbi_wtr1), - FUNCTION(uim1), - FUNCTION(uim2), - FUNCTION(uim3), - FUNCTION(uim_batt), - FUNCTION(wcss_bt), - FUNCTION(wcss_fm), - FUNCTION(wcss_wlan), - FUNCTION(webcam1_rst) +static const struct pinfunction msm8916_functions[] = { + MSM_PIN_FUNCTION(adsp_ext), + MSM_PIN_FUNCTION(alsp_int), + MSM_PIN_FUNCTION(atest_bbrx0), + MSM_PIN_FUNCTION(atest_bbrx1), + MSM_PIN_FUNCTION(atest_char), + MSM_PIN_FUNCTION(atest_char0), + MSM_PIN_FUNCTION(atest_char1), + MSM_PIN_FUNCTION(atest_char2), + MSM_PIN_FUNCTION(atest_char3), + MSM_PIN_FUNCTION(atest_combodac), + MSM_PIN_FUNCTION(atest_gpsadc0), + MSM_PIN_FUNCTION(atest_gpsadc1), + MSM_PIN_FUNCTION(atest_tsens), + MSM_PIN_FUNCTION(atest_wlan0), + MSM_PIN_FUNCTION(atest_wlan1), + MSM_PIN_FUNCTION(backlight_en), + MSM_PIN_FUNCTION(bimc_dte0), + MSM_PIN_FUNCTION(bimc_dte1), + MSM_PIN_FUNCTION(blsp_i2c1), + MSM_PIN_FUNCTION(blsp_i2c2), + MSM_PIN_FUNCTION(blsp_i2c3), + MSM_PIN_FUNCTION(blsp_i2c4), + MSM_PIN_FUNCTION(blsp_i2c5), + MSM_PIN_FUNCTION(blsp_i2c6), + MSM_PIN_FUNCTION(blsp_spi1), + MSM_PIN_FUNCTION(blsp_spi1_cs1), + MSM_PIN_FUNCTION(blsp_spi1_cs2), + MSM_PIN_FUNCTION(blsp_spi1_cs3), + MSM_PIN_FUNCTION(blsp_spi2), + MSM_PIN_FUNCTION(blsp_spi2_cs1), + MSM_PIN_FUNCTION(blsp_spi2_cs2), + MSM_PIN_FUNCTION(blsp_spi2_cs3), + MSM_PIN_FUNCTION(blsp_spi3), + MSM_PIN_FUNCTION(blsp_spi3_cs1), + MSM_PIN_FUNCTION(blsp_spi3_cs2), + MSM_PIN_FUNCTION(blsp_spi3_cs3), + MSM_PIN_FUNCTION(blsp_spi4), + MSM_PIN_FUNCTION(blsp_spi5), + MSM_PIN_FUNCTION(blsp_spi6), + MSM_PIN_FUNCTION(blsp_uart1), + MSM_PIN_FUNCTION(blsp_uart2), + MSM_PIN_FUNCTION(blsp_uim1), + MSM_PIN_FUNCTION(blsp_uim2), + MSM_PIN_FUNCTION(cam1_rst), + MSM_PIN_FUNCTION(cam1_standby), + MSM_PIN_FUNCTION(cam_mclk0), + MSM_PIN_FUNCTION(cam_mclk1), + MSM_PIN_FUNCTION(cci_async), + MSM_PIN_FUNCTION(cci_i2c), + MSM_PIN_FUNCTION(cci_timer0), + MSM_PIN_FUNCTION(cci_timer1), + MSM_PIN_FUNCTION(cci_timer2), + MSM_PIN_FUNCTION(cdc_pdm0), + MSM_PIN_FUNCTION(codec_mad), + MSM_PIN_FUNCTION(dbg_out), + MSM_PIN_FUNCTION(display_5v), + MSM_PIN_FUNCTION(dmic0_clk), + MSM_PIN_FUNCTION(dmic0_data), + MSM_PIN_FUNCTION(dsi_rst), + MSM_PIN_FUNCTION(ebi0_wrcdc), + MSM_PIN_FUNCTION(euro_us), + MSM_PIN_FUNCTION(ext_lpass), + MSM_PIN_FUNCTION(flash_strobe), + MSM_PIN_FUNCTION(gcc_gp1_clk_a), + MSM_PIN_FUNCTION(gcc_gp1_clk_b), + MSM_PIN_FUNCTION(gcc_gp2_clk_a), + MSM_PIN_FUNCTION(gcc_gp2_clk_b), + MSM_PIN_FUNCTION(gcc_gp3_clk_a), + MSM_PIN_FUNCTION(gcc_gp3_clk_b), + MSM_PIN_FUNCTION(gpio), + MSM_PIN_FUNCTION(gsm0_tx0), + MSM_PIN_FUNCTION(gsm0_tx1), + MSM_PIN_FUNCTION(gsm1_tx0), + MSM_PIN_FUNCTION(gsm1_tx1), + MSM_PIN_FUNCTION(gyro_accl), + MSM_PIN_FUNCTION(kpsns0), + MSM_PIN_FUNCTION(kpsns1), + MSM_PIN_FUNCTION(kpsns2), + MSM_PIN_FUNCTION(ldo_en), + MSM_PIN_FUNCTION(ldo_update), + MSM_PIN_FUNCTION(mag_int), + MSM_PIN_FUNCTION(mdp_vsync), + MSM_PIN_FUNCTION(modem_tsync), + MSM_PIN_FUNCTION(m_voc), + MSM_PIN_FUNCTION(nav_pps), + MSM_PIN_FUNCTION(nav_tsync), + MSM_PIN_FUNCTION(pa_indicator), + MSM_PIN_FUNCTION(pbs0), + MSM_PIN_FUNCTION(pbs1), + MSM_PIN_FUNCTION(pbs2), + MSM_PIN_FUNCTION(pri_mi2s), + MSM_PIN_FUNCTION(pri_mi2s_ws), + MSM_PIN_FUNCTION(prng_rosc), + MSM_PIN_FUNCTION(pwr_crypto_enabled_a), + MSM_PIN_FUNCTION(pwr_crypto_enabled_b), + MSM_PIN_FUNCTION(pwr_modem_enabled_a), + MSM_PIN_FUNCTION(pwr_modem_enabled_b), + MSM_PIN_FUNCTION(pwr_nav_enabled_a), + MSM_PIN_FUNCTION(pwr_nav_enabled_b), + MSM_PIN_FUNCTION(qdss_ctitrig_in_a0), + MSM_PIN_FUNCTION(qdss_ctitrig_in_a1), + MSM_PIN_FUNCTION(qdss_ctitrig_in_b0), + MSM_PIN_FUNCTION(qdss_ctitrig_in_b1), + MSM_PIN_FUNCTION(qdss_ctitrig_out_a0), + MSM_PIN_FUNCTION(qdss_ctitrig_out_a1), + MSM_PIN_FUNCTION(qdss_ctitrig_out_b0), + MSM_PIN_FUNCTION(qdss_ctitrig_out_b1), + MSM_PIN_FUNCTION(qdss_traceclk_a), + MSM_PIN_FUNCTION(qdss_traceclk_b), + MSM_PIN_FUNCTION(qdss_tracectl_a), + MSM_PIN_FUNCTION(qdss_tracectl_b), + MSM_PIN_FUNCTION(qdss_tracedata_a), + MSM_PIN_FUNCTION(qdss_tracedata_b), + MSM_PIN_FUNCTION(reset_n), + MSM_PIN_FUNCTION(sd_card), + MSM_PIN_FUNCTION(sd_write), + MSM_PIN_FUNCTION(sec_mi2s), + MSM_PIN_FUNCTION(smb_int), + MSM_PIN_FUNCTION(ssbi_wtr0), + MSM_PIN_FUNCTION(ssbi_wtr1), + MSM_PIN_FUNCTION(uim1), + MSM_PIN_FUNCTION(uim2), + MSM_PIN_FUNCTION(uim3), + MSM_PIN_FUNCTION(uim_batt), + MSM_PIN_FUNCTION(wcss_bt), + MSM_PIN_FUNCTION(wcss_fm), + MSM_PIN_FUNCTION(wcss_wlan), + MSM_PIN_FUNCTION(webcam1_rst) }; static const struct msm_pingroup msm8916_groups[] = { diff --git a/drivers/pinctrl/qcom/pinctrl-msm8953.c b/drivers/pinctrl/qcom/pinctrl-msm8953.c index e0c939ff3d54f1b1e734d1094fb9716dfcbb625a..998351bdfee1369fe0f369648d66a1a05493c8fb 100644 --- a/drivers/pinctrl/qcom/pinctrl-msm8953.c +++ b/drivers/pinctrl/qcom/pinctrl-msm8953.c @@ -4,22 +4,14 @@ #include #include #include -#include #include "pinctrl-msm.h" -#define FUNCTION(fname) \ - [msm_mux_##fname] = { \ - .name = #fname, \ - .groups = fname##_groups, \ - .ngroups = ARRAY_SIZE(fname##_groups), \ - } - #define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9) \ { \ - .name = "gpio" #id, \ - .pins = gpio##id##_pins, \ - .npins = ARRAY_SIZE(gpio##id##_pins), \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ .funcs = (int[]){ \ msm_mux_gpio, /* gpio mode */ \ msm_mux_##f1, \ @@ -56,9 +48,9 @@ #define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = ctl, \ .io_reg = 0, \ .intr_cfg_reg = 0, \ @@ -1431,208 +1423,208 @@ static const char * const wsa_irq_groups[] = { "gpio97", }; -static const struct msm_function msm8953_functions[] = { - FUNCTION(accel_int), - FUNCTION(adsp_ext), - FUNCTION(alsp_int), - FUNCTION(atest_bbrx0), - FUNCTION(atest_bbrx1), - FUNCTION(atest_char), - FUNCTION(atest_char0), - FUNCTION(atest_char1), - FUNCTION(atest_char2), - FUNCTION(atest_char3), - FUNCTION(atest_gpsadc_dtest0_native), - FUNCTION(atest_gpsadc_dtest1_native), - FUNCTION(atest_tsens), - FUNCTION(atest_wlan0), - FUNCTION(atest_wlan1), - FUNCTION(bimc_dte0), - FUNCTION(bimc_dte1), - FUNCTION(blsp1_spi), - FUNCTION(blsp3_spi), - FUNCTION(blsp6_spi), - FUNCTION(blsp7_spi), - FUNCTION(blsp_i2c1), - FUNCTION(blsp_i2c2), - FUNCTION(blsp_i2c3), - FUNCTION(blsp_i2c4), - FUNCTION(blsp_i2c5), - FUNCTION(blsp_i2c6), - FUNCTION(blsp_i2c7), - FUNCTION(blsp_i2c8), - FUNCTION(blsp_spi1), - FUNCTION(blsp_spi2), - FUNCTION(blsp_spi3), - FUNCTION(blsp_spi4), - FUNCTION(blsp_spi5), - FUNCTION(blsp_spi6), - FUNCTION(blsp_spi7), - FUNCTION(blsp_spi8), - FUNCTION(blsp_uart2), - FUNCTION(blsp_uart4), - FUNCTION(blsp_uart5), - FUNCTION(blsp_uart6), - FUNCTION(cam0_ldo), - FUNCTION(cam1_ldo), - FUNCTION(cam1_rst), - FUNCTION(cam1_standby), - FUNCTION(cam2_rst), - FUNCTION(cam2_standby), - FUNCTION(cam3_rst), - FUNCTION(cam3_standby), - FUNCTION(cam_irq), - FUNCTION(cam_mclk), - FUNCTION(cap_int), - FUNCTION(cci_async), - FUNCTION(cci_i2c), - FUNCTION(cci_timer0), - FUNCTION(cci_timer1), - FUNCTION(cci_timer2), - FUNCTION(cci_timer3), - FUNCTION(cci_timer4), - FUNCTION(cdc_pdm0), - FUNCTION(codec_int1), - FUNCTION(codec_int2), - FUNCTION(codec_reset), - FUNCTION(cri_trng), - FUNCTION(cri_trng0), - FUNCTION(cri_trng1), - FUNCTION(dac_calib0), - FUNCTION(dac_calib1), - FUNCTION(dac_calib10), - FUNCTION(dac_calib11), - FUNCTION(dac_calib12), - FUNCTION(dac_calib13), - FUNCTION(dac_calib14), - FUNCTION(dac_calib15), - FUNCTION(dac_calib16), - FUNCTION(dac_calib17), - FUNCTION(dac_calib18), - FUNCTION(dac_calib19), - FUNCTION(dac_calib2), - FUNCTION(dac_calib20), - FUNCTION(dac_calib21), - FUNCTION(dac_calib22), - FUNCTION(dac_calib23), - FUNCTION(dac_calib24), - FUNCTION(dac_calib25), - FUNCTION(dac_calib3), - FUNCTION(dac_calib4), - FUNCTION(dac_calib5), - FUNCTION(dac_calib6), - FUNCTION(dac_calib7), - FUNCTION(dac_calib8), - FUNCTION(dac_calib9), - FUNCTION(dbg_out), - FUNCTION(ddr_bist), - FUNCTION(dmic0_clk), - FUNCTION(dmic0_data), - FUNCTION(ebi_cdc), - FUNCTION(ebi_ch0), - FUNCTION(ext_lpass), - FUNCTION(flash_strobe), - FUNCTION(fp_int), - FUNCTION(gcc_gp1_clk_a), - FUNCTION(gcc_gp1_clk_b), - FUNCTION(gcc_gp2_clk_a), - FUNCTION(gcc_gp2_clk_b), - FUNCTION(gcc_gp3_clk_a), - FUNCTION(gcc_gp3_clk_b), - FUNCTION(gcc_plltest), - FUNCTION(gcc_tlmm), - FUNCTION(gpio), - FUNCTION(gsm0_tx), - FUNCTION(gsm1_tx), - FUNCTION(gyro_int), - FUNCTION(hall_int), - FUNCTION(hdmi_int), - FUNCTION(key_focus), - FUNCTION(key_home), - FUNCTION(key_snapshot), - FUNCTION(key_volp), - FUNCTION(ldo_en), - FUNCTION(ldo_update), - FUNCTION(lpass_slimbus), - FUNCTION(lpass_slimbus0), - FUNCTION(lpass_slimbus1), - FUNCTION(m_voc), - FUNCTION(mag_int), - FUNCTION(mdp_vsync), - FUNCTION(mipi_dsi0), - FUNCTION(modem_tsync), - FUNCTION(mss_lte), - FUNCTION(nav_pps), - FUNCTION(nav_pps_in_a), - FUNCTION(nav_pps_in_b), - FUNCTION(nav_tsync), - FUNCTION(nfc_disable), - FUNCTION(nfc_dwl), - FUNCTION(nfc_irq), - FUNCTION(ois_sync), - FUNCTION(pa_indicator), - FUNCTION(pbs0), - FUNCTION(pbs1), - FUNCTION(pbs2), - FUNCTION(pressure_int), - FUNCTION(pri_mi2s), - FUNCTION(pri_mi2s_mclk_a), - FUNCTION(pri_mi2s_mclk_b), - FUNCTION(pri_mi2s_ws), - FUNCTION(prng_rosc), - FUNCTION(pwr_crypto_enabled_a), - FUNCTION(pwr_crypto_enabled_b), - FUNCTION(pwr_down), - FUNCTION(pwr_modem_enabled_a), - FUNCTION(pwr_modem_enabled_b), - FUNCTION(pwr_nav_enabled_a), - FUNCTION(pwr_nav_enabled_b), - FUNCTION(qdss_cti_trig_in_a0), - FUNCTION(qdss_cti_trig_in_a1), - FUNCTION(qdss_cti_trig_in_b0), - FUNCTION(qdss_cti_trig_in_b1), - FUNCTION(qdss_cti_trig_out_a0), - FUNCTION(qdss_cti_trig_out_a1), - FUNCTION(qdss_cti_trig_out_b0), - FUNCTION(qdss_cti_trig_out_b1), - FUNCTION(qdss_traceclk_a), - FUNCTION(qdss_traceclk_b), - FUNCTION(qdss_tracectl_a), - FUNCTION(qdss_tracectl_b), - FUNCTION(qdss_tracedata_a), - FUNCTION(qdss_tracedata_b), - FUNCTION(sd_write), - FUNCTION(sdcard_det), - FUNCTION(sec_mi2s), - FUNCTION(sec_mi2s_mclk_a), - FUNCTION(sec_mi2s_mclk_b), - FUNCTION(smb_int), - FUNCTION(ss_switch), - FUNCTION(ssbi_wtr1), - FUNCTION(ts_resout), - FUNCTION(ts_sample), - FUNCTION(ts_xvdd), - FUNCTION(tsens_max), - FUNCTION(uim1_clk), - FUNCTION(uim1_data), - FUNCTION(uim1_present), - FUNCTION(uim1_reset), - FUNCTION(uim2_clk), - FUNCTION(uim2_data), - FUNCTION(uim2_present), - FUNCTION(uim2_reset), - FUNCTION(uim_batt), - FUNCTION(us_emitter), - FUNCTION(us_euro), - FUNCTION(wcss_bt), - FUNCTION(wcss_fm), - FUNCTION(wcss_wlan), - FUNCTION(wcss_wlan0), - FUNCTION(wcss_wlan1), - FUNCTION(wcss_wlan2), - FUNCTION(wsa_en), - FUNCTION(wsa_io), - FUNCTION(wsa_irq), +static const struct pinfunction msm8953_functions[] = { + MSM_PIN_FUNCTION(accel_int), + MSM_PIN_FUNCTION(adsp_ext), + MSM_PIN_FUNCTION(alsp_int), + MSM_PIN_FUNCTION(atest_bbrx0), + MSM_PIN_FUNCTION(atest_bbrx1), + MSM_PIN_FUNCTION(atest_char), + MSM_PIN_FUNCTION(atest_char0), + MSM_PIN_FUNCTION(atest_char1), + MSM_PIN_FUNCTION(atest_char2), + MSM_PIN_FUNCTION(atest_char3), + MSM_PIN_FUNCTION(atest_gpsadc_dtest0_native), + MSM_PIN_FUNCTION(atest_gpsadc_dtest1_native), + MSM_PIN_FUNCTION(atest_tsens), + MSM_PIN_FUNCTION(atest_wlan0), + MSM_PIN_FUNCTION(atest_wlan1), + MSM_PIN_FUNCTION(bimc_dte0), + MSM_PIN_FUNCTION(bimc_dte1), + MSM_PIN_FUNCTION(blsp1_spi), + MSM_PIN_FUNCTION(blsp3_spi), + MSM_PIN_FUNCTION(blsp6_spi), + MSM_PIN_FUNCTION(blsp7_spi), + MSM_PIN_FUNCTION(blsp_i2c1), + MSM_PIN_FUNCTION(blsp_i2c2), + MSM_PIN_FUNCTION(blsp_i2c3), + MSM_PIN_FUNCTION(blsp_i2c4), + MSM_PIN_FUNCTION(blsp_i2c5), + MSM_PIN_FUNCTION(blsp_i2c6), + MSM_PIN_FUNCTION(blsp_i2c7), + MSM_PIN_FUNCTION(blsp_i2c8), + MSM_PIN_FUNCTION(blsp_spi1), + MSM_PIN_FUNCTION(blsp_spi2), + MSM_PIN_FUNCTION(blsp_spi3), + MSM_PIN_FUNCTION(blsp_spi4), + MSM_PIN_FUNCTION(blsp_spi5), + MSM_PIN_FUNCTION(blsp_spi6), + MSM_PIN_FUNCTION(blsp_spi7), + MSM_PIN_FUNCTION(blsp_spi8), + MSM_PIN_FUNCTION(blsp_uart2), + MSM_PIN_FUNCTION(blsp_uart4), + MSM_PIN_FUNCTION(blsp_uart5), + MSM_PIN_FUNCTION(blsp_uart6), + MSM_PIN_FUNCTION(cam0_ldo), + MSM_PIN_FUNCTION(cam1_ldo), + MSM_PIN_FUNCTION(cam1_rst), + MSM_PIN_FUNCTION(cam1_standby), + MSM_PIN_FUNCTION(cam2_rst), + MSM_PIN_FUNCTION(cam2_standby), + MSM_PIN_FUNCTION(cam3_rst), + MSM_PIN_FUNCTION(cam3_standby), + MSM_PIN_FUNCTION(cam_irq), + MSM_PIN_FUNCTION(cam_mclk), + MSM_PIN_FUNCTION(cap_int), + MSM_PIN_FUNCTION(cci_async), + MSM_PIN_FUNCTION(cci_i2c), + MSM_PIN_FUNCTION(cci_timer0), + MSM_PIN_FUNCTION(cci_timer1), + MSM_PIN_FUNCTION(cci_timer2), + MSM_PIN_FUNCTION(cci_timer3), + MSM_PIN_FUNCTION(cci_timer4), + MSM_PIN_FUNCTION(cdc_pdm0), + MSM_PIN_FUNCTION(codec_int1), + MSM_PIN_FUNCTION(codec_int2), + MSM_PIN_FUNCTION(codec_reset), + MSM_PIN_FUNCTION(cri_trng), + MSM_PIN_FUNCTION(cri_trng0), + MSM_PIN_FUNCTION(cri_trng1), + MSM_PIN_FUNCTION(dac_calib0), + MSM_PIN_FUNCTION(dac_calib1), + MSM_PIN_FUNCTION(dac_calib10), + MSM_PIN_FUNCTION(dac_calib11), + MSM_PIN_FUNCTION(dac_calib12), + MSM_PIN_FUNCTION(dac_calib13), + MSM_PIN_FUNCTION(dac_calib14), + MSM_PIN_FUNCTION(dac_calib15), + MSM_PIN_FUNCTION(dac_calib16), + MSM_PIN_FUNCTION(dac_calib17), + MSM_PIN_FUNCTION(dac_calib18), + MSM_PIN_FUNCTION(dac_calib19), + MSM_PIN_FUNCTION(dac_calib2), + MSM_PIN_FUNCTION(dac_calib20), + MSM_PIN_FUNCTION(dac_calib21), + MSM_PIN_FUNCTION(dac_calib22), + MSM_PIN_FUNCTION(dac_calib23), + MSM_PIN_FUNCTION(dac_calib24), + MSM_PIN_FUNCTION(dac_calib25), + MSM_PIN_FUNCTION(dac_calib3), + MSM_PIN_FUNCTION(dac_calib4), + MSM_PIN_FUNCTION(dac_calib5), + MSM_PIN_FUNCTION(dac_calib6), + MSM_PIN_FUNCTION(dac_calib7), + MSM_PIN_FUNCTION(dac_calib8), + MSM_PIN_FUNCTION(dac_calib9), + MSM_PIN_FUNCTION(dbg_out), + MSM_PIN_FUNCTION(ddr_bist), + MSM_PIN_FUNCTION(dmic0_clk), + MSM_PIN_FUNCTION(dmic0_data), + MSM_PIN_FUNCTION(ebi_cdc), + MSM_PIN_FUNCTION(ebi_ch0), + MSM_PIN_FUNCTION(ext_lpass), + MSM_PIN_FUNCTION(flash_strobe), + MSM_PIN_FUNCTION(fp_int), + MSM_PIN_FUNCTION(gcc_gp1_clk_a), + MSM_PIN_FUNCTION(gcc_gp1_clk_b), + MSM_PIN_FUNCTION(gcc_gp2_clk_a), + MSM_PIN_FUNCTION(gcc_gp2_clk_b), + MSM_PIN_FUNCTION(gcc_gp3_clk_a), + MSM_PIN_FUNCTION(gcc_gp3_clk_b), + MSM_PIN_FUNCTION(gcc_plltest), + MSM_PIN_FUNCTION(gcc_tlmm), + MSM_PIN_FUNCTION(gpio), + MSM_PIN_FUNCTION(gsm0_tx), + MSM_PIN_FUNCTION(gsm1_tx), + MSM_PIN_FUNCTION(gyro_int), + MSM_PIN_FUNCTION(hall_int), + MSM_PIN_FUNCTION(hdmi_int), + MSM_PIN_FUNCTION(key_focus), + MSM_PIN_FUNCTION(key_home), + MSM_PIN_FUNCTION(key_snapshot), + MSM_PIN_FUNCTION(key_volp), + MSM_PIN_FUNCTION(ldo_en), + MSM_PIN_FUNCTION(ldo_update), + MSM_PIN_FUNCTION(lpass_slimbus), + MSM_PIN_FUNCTION(lpass_slimbus0), + MSM_PIN_FUNCTION(lpass_slimbus1), + MSM_PIN_FUNCTION(m_voc), + MSM_PIN_FUNCTION(mag_int), + MSM_PIN_FUNCTION(mdp_vsync), + MSM_PIN_FUNCTION(mipi_dsi0), + MSM_PIN_FUNCTION(modem_tsync), + MSM_PIN_FUNCTION(mss_lte), + MSM_PIN_FUNCTION(nav_pps), + MSM_PIN_FUNCTION(nav_pps_in_a), + MSM_PIN_FUNCTION(nav_pps_in_b), + MSM_PIN_FUNCTION(nav_tsync), + MSM_PIN_FUNCTION(nfc_disable), + MSM_PIN_FUNCTION(nfc_dwl), + MSM_PIN_FUNCTION(nfc_irq), + MSM_PIN_FUNCTION(ois_sync), + MSM_PIN_FUNCTION(pa_indicator), + MSM_PIN_FUNCTION(pbs0), + MSM_PIN_FUNCTION(pbs1), + MSM_PIN_FUNCTION(pbs2), + MSM_PIN_FUNCTION(pressure_int), + MSM_PIN_FUNCTION(pri_mi2s), + MSM_PIN_FUNCTION(pri_mi2s_mclk_a), + MSM_PIN_FUNCTION(pri_mi2s_mclk_b), + MSM_PIN_FUNCTION(pri_mi2s_ws), + MSM_PIN_FUNCTION(prng_rosc), + MSM_PIN_FUNCTION(pwr_crypto_enabled_a), + MSM_PIN_FUNCTION(pwr_crypto_enabled_b), + MSM_PIN_FUNCTION(pwr_down), + MSM_PIN_FUNCTION(pwr_modem_enabled_a), + MSM_PIN_FUNCTION(pwr_modem_enabled_b), + MSM_PIN_FUNCTION(pwr_nav_enabled_a), + MSM_PIN_FUNCTION(pwr_nav_enabled_b), + MSM_PIN_FUNCTION(qdss_cti_trig_in_a0), + MSM_PIN_FUNCTION(qdss_cti_trig_in_a1), + MSM_PIN_FUNCTION(qdss_cti_trig_in_b0), + MSM_PIN_FUNCTION(qdss_cti_trig_in_b1), + MSM_PIN_FUNCTION(qdss_cti_trig_out_a0), + MSM_PIN_FUNCTION(qdss_cti_trig_out_a1), + MSM_PIN_FUNCTION(qdss_cti_trig_out_b0), + MSM_PIN_FUNCTION(qdss_cti_trig_out_b1), + MSM_PIN_FUNCTION(qdss_traceclk_a), + MSM_PIN_FUNCTION(qdss_traceclk_b), + MSM_PIN_FUNCTION(qdss_tracectl_a), + MSM_PIN_FUNCTION(qdss_tracectl_b), + MSM_PIN_FUNCTION(qdss_tracedata_a), + MSM_PIN_FUNCTION(qdss_tracedata_b), + MSM_PIN_FUNCTION(sd_write), + MSM_PIN_FUNCTION(sdcard_det), + MSM_PIN_FUNCTION(sec_mi2s), + MSM_PIN_FUNCTION(sec_mi2s_mclk_a), + MSM_PIN_FUNCTION(sec_mi2s_mclk_b), + MSM_PIN_FUNCTION(smb_int), + MSM_PIN_FUNCTION(ss_switch), + MSM_PIN_FUNCTION(ssbi_wtr1), + MSM_PIN_FUNCTION(ts_resout), + MSM_PIN_FUNCTION(ts_sample), + MSM_PIN_FUNCTION(ts_xvdd), + MSM_PIN_FUNCTION(tsens_max), + MSM_PIN_FUNCTION(uim1_clk), + MSM_PIN_FUNCTION(uim1_data), + MSM_PIN_FUNCTION(uim1_present), + MSM_PIN_FUNCTION(uim1_reset), + MSM_PIN_FUNCTION(uim2_clk), + MSM_PIN_FUNCTION(uim2_data), + MSM_PIN_FUNCTION(uim2_present), + MSM_PIN_FUNCTION(uim2_reset), + MSM_PIN_FUNCTION(uim_batt), + MSM_PIN_FUNCTION(us_emitter), + MSM_PIN_FUNCTION(us_euro), + MSM_PIN_FUNCTION(wcss_bt), + MSM_PIN_FUNCTION(wcss_fm), + MSM_PIN_FUNCTION(wcss_wlan), + MSM_PIN_FUNCTION(wcss_wlan0), + MSM_PIN_FUNCTION(wcss_wlan1), + MSM_PIN_FUNCTION(wcss_wlan2), + MSM_PIN_FUNCTION(wsa_en), + MSM_PIN_FUNCTION(wsa_io), + MSM_PIN_FUNCTION(wsa_irq), }; static const struct msm_pingroup msm8953_groups[] = { diff --git a/drivers/pinctrl/qcom/pinctrl-msm8960.c b/drivers/pinctrl/qcom/pinctrl-msm8960.c index e3928f5f8d5b42bafbfcf441038292b425105626..ebe230b3b437ccc63535fdf51639e64a67fe05eb 100644 --- a/drivers/pinctrl/qcom/pinctrl-msm8960.c +++ b/drivers/pinctrl/qcom/pinctrl-msm8960.c @@ -6,7 +6,6 @@ #include #include #include -#include #include #include "pinctrl-msm.h" @@ -334,31 +333,24 @@ static const unsigned int sdc3_clk_pins[] = { 155 }; static const unsigned int sdc3_cmd_pins[] = { 156 }; static const unsigned int sdc3_data_pins[] = { 157 }; -#define FUNCTION(fname) \ - [MSM_MUX_##fname] = { \ - .name = #fname, \ - .groups = fname##_groups, \ - .ngroups = ARRAY_SIZE(fname##_groups), \ - } - #define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11) \ { \ - .name = "gpio" #id, \ - .pins = gpio##id##_pins, \ - .npins = ARRAY_SIZE(gpio##id##_pins), \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ .funcs = (int[]){ \ - MSM_MUX_gpio, \ - MSM_MUX_##f1, \ - MSM_MUX_##f2, \ - MSM_MUX_##f3, \ - MSM_MUX_##f4, \ - MSM_MUX_##f5, \ - MSM_MUX_##f6, \ - MSM_MUX_##f7, \ - MSM_MUX_##f8, \ - MSM_MUX_##f9, \ - MSM_MUX_##f10, \ - MSM_MUX_##f11 \ + msm_mux_gpio, \ + msm_mux_##f1, \ + msm_mux_##f2, \ + msm_mux_##f3, \ + msm_mux_##f4, \ + msm_mux_##f5, \ + msm_mux_##f6, \ + msm_mux_##f7, \ + msm_mux_##f8, \ + msm_mux_##f9, \ + msm_mux_##f10, \ + msm_mux_##f11 \ }, \ .nfuncs = 12, \ .ctl_reg = 0x1000 + 0x10 * id, \ @@ -385,9 +377,9 @@ static const unsigned int sdc3_data_pins[] = { 157 }; #define SDC_PINGROUP(pg_name, ctl, pull, drv) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = ctl, \ .io_reg = 0, \ .intr_cfg_reg = 0, \ @@ -410,111 +402,111 @@ static const unsigned int sdc3_data_pins[] = { 157 }; } enum msm8960_functions { - MSM_MUX_audio_pcm, - MSM_MUX_bt, - MSM_MUX_cam_mclk0, - MSM_MUX_cam_mclk1, - MSM_MUX_cam_mclk2, - MSM_MUX_codec_mic_i2s, - MSM_MUX_codec_spkr_i2s, - MSM_MUX_ext_gps, - MSM_MUX_fm, - MSM_MUX_gps_blanking, - MSM_MUX_gps_pps_in, - MSM_MUX_gps_pps_out, - MSM_MUX_gp_clk_0a, - MSM_MUX_gp_clk_0b, - MSM_MUX_gp_clk_1a, - MSM_MUX_gp_clk_1b, - MSM_MUX_gp_clk_2a, - MSM_MUX_gp_clk_2b, - MSM_MUX_gp_mn, - MSM_MUX_gp_pdm_0a, - MSM_MUX_gp_pdm_0b, - MSM_MUX_gp_pdm_1a, - MSM_MUX_gp_pdm_1b, - MSM_MUX_gp_pdm_2a, - MSM_MUX_gp_pdm_2b, - MSM_MUX_gpio, - MSM_MUX_gsbi1, - MSM_MUX_gsbi1_spi_cs1_n, - MSM_MUX_gsbi1_spi_cs2a_n, - MSM_MUX_gsbi1_spi_cs2b_n, - MSM_MUX_gsbi1_spi_cs3_n, - MSM_MUX_gsbi2, - MSM_MUX_gsbi2_spi_cs1_n, - MSM_MUX_gsbi2_spi_cs2_n, - MSM_MUX_gsbi2_spi_cs3_n, - MSM_MUX_gsbi3, - MSM_MUX_gsbi4, - MSM_MUX_gsbi4_3d_cam_i2c_l, - MSM_MUX_gsbi4_3d_cam_i2c_r, - MSM_MUX_gsbi5, - MSM_MUX_gsbi5_3d_cam_i2c_l, - MSM_MUX_gsbi5_3d_cam_i2c_r, - MSM_MUX_gsbi6, - MSM_MUX_gsbi7, - MSM_MUX_gsbi8, - MSM_MUX_gsbi9, - MSM_MUX_gsbi10, - MSM_MUX_gsbi11, - MSM_MUX_gsbi11_spi_cs1a_n, - MSM_MUX_gsbi11_spi_cs1b_n, - MSM_MUX_gsbi11_spi_cs2a_n, - MSM_MUX_gsbi11_spi_cs2b_n, - MSM_MUX_gsbi11_spi_cs3_n, - MSM_MUX_gsbi12, - MSM_MUX_hdmi_cec, - MSM_MUX_hdmi_ddc_clock, - MSM_MUX_hdmi_ddc_data, - MSM_MUX_hdmi_hot_plug_detect, - MSM_MUX_hsic, - MSM_MUX_mdp_vsync, - MSM_MUX_mi2s, - MSM_MUX_mic_i2s, - MSM_MUX_pmb_clk, - MSM_MUX_pmb_ext_ctrl, - MSM_MUX_ps_hold, - MSM_MUX_rpm_wdog, - MSM_MUX_sdc2, - MSM_MUX_sdc4, - MSM_MUX_sdc5, - MSM_MUX_slimbus1, - MSM_MUX_slimbus2, - MSM_MUX_spkr_i2s, - MSM_MUX_ssbi1, - MSM_MUX_ssbi2, - MSM_MUX_ssbi_ext_gps, - MSM_MUX_ssbi_pmic2, - MSM_MUX_ssbi_qpa1, - MSM_MUX_ssbi_ts, - MSM_MUX_tsif1, - MSM_MUX_tsif2, - MSM_MUX_ts_eoc, - MSM_MUX_usb_fs1, - MSM_MUX_usb_fs1_oe, - MSM_MUX_usb_fs1_oe_n, - MSM_MUX_usb_fs2, - MSM_MUX_usb_fs2_oe, - MSM_MUX_usb_fs2_oe_n, - MSM_MUX_vfe_camif_timer1_a, - MSM_MUX_vfe_camif_timer1_b, - MSM_MUX_vfe_camif_timer2, - MSM_MUX_vfe_camif_timer3_a, - MSM_MUX_vfe_camif_timer3_b, - MSM_MUX_vfe_camif_timer4_a, - MSM_MUX_vfe_camif_timer4_b, - MSM_MUX_vfe_camif_timer4_c, - MSM_MUX_vfe_camif_timer5_a, - MSM_MUX_vfe_camif_timer5_b, - MSM_MUX_vfe_camif_timer6_a, - MSM_MUX_vfe_camif_timer6_b, - MSM_MUX_vfe_camif_timer6_c, - MSM_MUX_vfe_camif_timer7_a, - MSM_MUX_vfe_camif_timer7_b, - MSM_MUX_vfe_camif_timer7_c, - MSM_MUX_wlan, - MSM_MUX_NA, + msm_mux_audio_pcm, + msm_mux_bt, + msm_mux_cam_mclk0, + msm_mux_cam_mclk1, + msm_mux_cam_mclk2, + msm_mux_codec_mic_i2s, + msm_mux_codec_spkr_i2s, + msm_mux_ext_gps, + msm_mux_fm, + msm_mux_gps_blanking, + msm_mux_gps_pps_in, + msm_mux_gps_pps_out, + msm_mux_gp_clk_0a, + msm_mux_gp_clk_0b, + msm_mux_gp_clk_1a, + msm_mux_gp_clk_1b, + msm_mux_gp_clk_2a, + msm_mux_gp_clk_2b, + msm_mux_gp_mn, + msm_mux_gp_pdm_0a, + msm_mux_gp_pdm_0b, + msm_mux_gp_pdm_1a, + msm_mux_gp_pdm_1b, + msm_mux_gp_pdm_2a, + msm_mux_gp_pdm_2b, + msm_mux_gpio, + msm_mux_gsbi1, + msm_mux_gsbi1_spi_cs1_n, + msm_mux_gsbi1_spi_cs2a_n, + msm_mux_gsbi1_spi_cs2b_n, + msm_mux_gsbi1_spi_cs3_n, + msm_mux_gsbi2, + msm_mux_gsbi2_spi_cs1_n, + msm_mux_gsbi2_spi_cs2_n, + msm_mux_gsbi2_spi_cs3_n, + msm_mux_gsbi3, + msm_mux_gsbi4, + msm_mux_gsbi4_3d_cam_i2c_l, + msm_mux_gsbi4_3d_cam_i2c_r, + msm_mux_gsbi5, + msm_mux_gsbi5_3d_cam_i2c_l, + msm_mux_gsbi5_3d_cam_i2c_r, + msm_mux_gsbi6, + msm_mux_gsbi7, + msm_mux_gsbi8, + msm_mux_gsbi9, + msm_mux_gsbi10, + msm_mux_gsbi11, + msm_mux_gsbi11_spi_cs1a_n, + msm_mux_gsbi11_spi_cs1b_n, + msm_mux_gsbi11_spi_cs2a_n, + msm_mux_gsbi11_spi_cs2b_n, + msm_mux_gsbi11_spi_cs3_n, + msm_mux_gsbi12, + msm_mux_hdmi_cec, + msm_mux_hdmi_ddc_clock, + msm_mux_hdmi_ddc_data, + msm_mux_hdmi_hot_plug_detect, + msm_mux_hsic, + msm_mux_mdp_vsync, + msm_mux_mi2s, + msm_mux_mic_i2s, + msm_mux_pmb_clk, + msm_mux_pmb_ext_ctrl, + msm_mux_ps_hold, + msm_mux_rpm_wdog, + msm_mux_sdc2, + msm_mux_sdc4, + msm_mux_sdc5, + msm_mux_slimbus1, + msm_mux_slimbus2, + msm_mux_spkr_i2s, + msm_mux_ssbi1, + msm_mux_ssbi2, + msm_mux_ssbi_ext_gps, + msm_mux_ssbi_pmic2, + msm_mux_ssbi_qpa1, + msm_mux_ssbi_ts, + msm_mux_tsif1, + msm_mux_tsif2, + msm_mux_ts_eoc, + msm_mux_usb_fs1, + msm_mux_usb_fs1_oe, + msm_mux_usb_fs1_oe_n, + msm_mux_usb_fs2, + msm_mux_usb_fs2_oe, + msm_mux_usb_fs2_oe_n, + msm_mux_vfe_camif_timer1_a, + msm_mux_vfe_camif_timer1_b, + msm_mux_vfe_camif_timer2, + msm_mux_vfe_camif_timer3_a, + msm_mux_vfe_camif_timer3_b, + msm_mux_vfe_camif_timer4_a, + msm_mux_vfe_camif_timer4_b, + msm_mux_vfe_camif_timer4_c, + msm_mux_vfe_camif_timer5_a, + msm_mux_vfe_camif_timer5_b, + msm_mux_vfe_camif_timer6_a, + msm_mux_vfe_camif_timer6_b, + msm_mux_vfe_camif_timer6_c, + msm_mux_vfe_camif_timer7_a, + msm_mux_vfe_camif_timer7_b, + msm_mux_vfe_camif_timer7_c, + msm_mux_wlan, + msm_mux_NA, }; static const char * const audio_pcm_groups[] = { @@ -956,111 +948,111 @@ static const char * const wlan_groups[] = { "gpio84", "gpio85", "gpio86", "gpio87", "gpio88" }; -static const struct msm_function msm8960_functions[] = { - FUNCTION(audio_pcm), - FUNCTION(bt), - FUNCTION(cam_mclk0), - FUNCTION(cam_mclk1), - FUNCTION(cam_mclk2), - FUNCTION(codec_mic_i2s), - FUNCTION(codec_spkr_i2s), - FUNCTION(ext_gps), - FUNCTION(fm), - FUNCTION(gps_blanking), - FUNCTION(gps_pps_in), - FUNCTION(gps_pps_out), - FUNCTION(gp_clk_0a), - FUNCTION(gp_clk_0b), - FUNCTION(gp_clk_1a), - FUNCTION(gp_clk_1b), - FUNCTION(gp_clk_2a), - FUNCTION(gp_clk_2b), - FUNCTION(gp_mn), - FUNCTION(gp_pdm_0a), - FUNCTION(gp_pdm_0b), - FUNCTION(gp_pdm_1a), - FUNCTION(gp_pdm_1b), - FUNCTION(gp_pdm_2a), - FUNCTION(gp_pdm_2b), - FUNCTION(gpio), - FUNCTION(gsbi1), - FUNCTION(gsbi1_spi_cs1_n), - FUNCTION(gsbi1_spi_cs2a_n), - FUNCTION(gsbi1_spi_cs2b_n), - FUNCTION(gsbi1_spi_cs3_n), - FUNCTION(gsbi2), - FUNCTION(gsbi2_spi_cs1_n), - FUNCTION(gsbi2_spi_cs2_n), - FUNCTION(gsbi2_spi_cs3_n), - FUNCTION(gsbi3), - FUNCTION(gsbi4), - FUNCTION(gsbi4_3d_cam_i2c_l), - FUNCTION(gsbi4_3d_cam_i2c_r), - FUNCTION(gsbi5), - FUNCTION(gsbi5_3d_cam_i2c_l), - FUNCTION(gsbi5_3d_cam_i2c_r), - FUNCTION(gsbi6), - FUNCTION(gsbi7), - FUNCTION(gsbi8), - FUNCTION(gsbi9), - FUNCTION(gsbi10), - FUNCTION(gsbi11), - FUNCTION(gsbi11_spi_cs1a_n), - FUNCTION(gsbi11_spi_cs1b_n), - FUNCTION(gsbi11_spi_cs2a_n), - FUNCTION(gsbi11_spi_cs2b_n), - FUNCTION(gsbi11_spi_cs3_n), - FUNCTION(gsbi12), - FUNCTION(hdmi_cec), - FUNCTION(hdmi_ddc_clock), - FUNCTION(hdmi_ddc_data), - FUNCTION(hdmi_hot_plug_detect), - FUNCTION(hsic), - FUNCTION(mdp_vsync), - FUNCTION(mi2s), - FUNCTION(mic_i2s), - FUNCTION(pmb_clk), - FUNCTION(pmb_ext_ctrl), - FUNCTION(ps_hold), - FUNCTION(rpm_wdog), - FUNCTION(sdc2), - FUNCTION(sdc4), - FUNCTION(sdc5), - FUNCTION(slimbus1), - FUNCTION(slimbus2), - FUNCTION(spkr_i2s), - FUNCTION(ssbi1), - FUNCTION(ssbi2), - FUNCTION(ssbi_ext_gps), - FUNCTION(ssbi_pmic2), - FUNCTION(ssbi_qpa1), - FUNCTION(ssbi_ts), - FUNCTION(tsif1), - FUNCTION(tsif2), - FUNCTION(ts_eoc), - FUNCTION(usb_fs1), - FUNCTION(usb_fs1_oe), - FUNCTION(usb_fs1_oe_n), - FUNCTION(usb_fs2), - FUNCTION(usb_fs2_oe), - FUNCTION(usb_fs2_oe_n), - FUNCTION(vfe_camif_timer1_a), - FUNCTION(vfe_camif_timer1_b), - FUNCTION(vfe_camif_timer2), - FUNCTION(vfe_camif_timer3_a), - FUNCTION(vfe_camif_timer3_b), - FUNCTION(vfe_camif_timer4_a), - FUNCTION(vfe_camif_timer4_b), - FUNCTION(vfe_camif_timer4_c), - FUNCTION(vfe_camif_timer5_a), - FUNCTION(vfe_camif_timer5_b), - FUNCTION(vfe_camif_timer6_a), - FUNCTION(vfe_camif_timer6_b), - FUNCTION(vfe_camif_timer6_c), - FUNCTION(vfe_camif_timer7_a), - FUNCTION(vfe_camif_timer7_b), - FUNCTION(vfe_camif_timer7_c), - FUNCTION(wlan), +static const struct pinfunction msm8960_functions[] = { + MSM_PIN_FUNCTION(audio_pcm), + MSM_PIN_FUNCTION(bt), + MSM_PIN_FUNCTION(cam_mclk0), + MSM_PIN_FUNCTION(cam_mclk1), + MSM_PIN_FUNCTION(cam_mclk2), + MSM_PIN_FUNCTION(codec_mic_i2s), + MSM_PIN_FUNCTION(codec_spkr_i2s), + MSM_PIN_FUNCTION(ext_gps), + MSM_PIN_FUNCTION(fm), + MSM_PIN_FUNCTION(gps_blanking), + MSM_PIN_FUNCTION(gps_pps_in), + MSM_PIN_FUNCTION(gps_pps_out), + MSM_PIN_FUNCTION(gp_clk_0a), + MSM_PIN_FUNCTION(gp_clk_0b), + MSM_PIN_FUNCTION(gp_clk_1a), + MSM_PIN_FUNCTION(gp_clk_1b), + MSM_PIN_FUNCTION(gp_clk_2a), + MSM_PIN_FUNCTION(gp_clk_2b), + MSM_PIN_FUNCTION(gp_mn), + MSM_PIN_FUNCTION(gp_pdm_0a), + MSM_PIN_FUNCTION(gp_pdm_0b), + MSM_PIN_FUNCTION(gp_pdm_1a), + MSM_PIN_FUNCTION(gp_pdm_1b), + MSM_PIN_FUNCTION(gp_pdm_2a), + MSM_PIN_FUNCTION(gp_pdm_2b), + MSM_PIN_FUNCTION(gpio), + MSM_PIN_FUNCTION(gsbi1), + MSM_PIN_FUNCTION(gsbi1_spi_cs1_n), + MSM_PIN_FUNCTION(gsbi1_spi_cs2a_n), + MSM_PIN_FUNCTION(gsbi1_spi_cs2b_n), + MSM_PIN_FUNCTION(gsbi1_spi_cs3_n), + MSM_PIN_FUNCTION(gsbi2), + MSM_PIN_FUNCTION(gsbi2_spi_cs1_n), + MSM_PIN_FUNCTION(gsbi2_spi_cs2_n), + MSM_PIN_FUNCTION(gsbi2_spi_cs3_n), + MSM_PIN_FUNCTION(gsbi3), + MSM_PIN_FUNCTION(gsbi4), + MSM_PIN_FUNCTION(gsbi4_3d_cam_i2c_l), + MSM_PIN_FUNCTION(gsbi4_3d_cam_i2c_r), + MSM_PIN_FUNCTION(gsbi5), + MSM_PIN_FUNCTION(gsbi5_3d_cam_i2c_l), + MSM_PIN_FUNCTION(gsbi5_3d_cam_i2c_r), + MSM_PIN_FUNCTION(gsbi6), + MSM_PIN_FUNCTION(gsbi7), + MSM_PIN_FUNCTION(gsbi8), + MSM_PIN_FUNCTION(gsbi9), + MSM_PIN_FUNCTION(gsbi10), + MSM_PIN_FUNCTION(gsbi11), + MSM_PIN_FUNCTION(gsbi11_spi_cs1a_n), + MSM_PIN_FUNCTION(gsbi11_spi_cs1b_n), + MSM_PIN_FUNCTION(gsbi11_spi_cs2a_n), + MSM_PIN_FUNCTION(gsbi11_spi_cs2b_n), + MSM_PIN_FUNCTION(gsbi11_spi_cs3_n), + MSM_PIN_FUNCTION(gsbi12), + MSM_PIN_FUNCTION(hdmi_cec), + MSM_PIN_FUNCTION(hdmi_ddc_clock), + MSM_PIN_FUNCTION(hdmi_ddc_data), + MSM_PIN_FUNCTION(hdmi_hot_plug_detect), + MSM_PIN_FUNCTION(hsic), + MSM_PIN_FUNCTION(mdp_vsync), + MSM_PIN_FUNCTION(mi2s), + MSM_PIN_FUNCTION(mic_i2s), + MSM_PIN_FUNCTION(pmb_clk), + MSM_PIN_FUNCTION(pmb_ext_ctrl), + MSM_PIN_FUNCTION(ps_hold), + MSM_PIN_FUNCTION(rpm_wdog), + MSM_PIN_FUNCTION(sdc2), + MSM_PIN_FUNCTION(sdc4), + MSM_PIN_FUNCTION(sdc5), + MSM_PIN_FUNCTION(slimbus1), + MSM_PIN_FUNCTION(slimbus2), + MSM_PIN_FUNCTION(spkr_i2s), + MSM_PIN_FUNCTION(ssbi1), + MSM_PIN_FUNCTION(ssbi2), + MSM_PIN_FUNCTION(ssbi_ext_gps), + MSM_PIN_FUNCTION(ssbi_pmic2), + MSM_PIN_FUNCTION(ssbi_qpa1), + MSM_PIN_FUNCTION(ssbi_ts), + MSM_PIN_FUNCTION(tsif1), + MSM_PIN_FUNCTION(tsif2), + MSM_PIN_FUNCTION(ts_eoc), + MSM_PIN_FUNCTION(usb_fs1), + MSM_PIN_FUNCTION(usb_fs1_oe), + MSM_PIN_FUNCTION(usb_fs1_oe_n), + MSM_PIN_FUNCTION(usb_fs2), + MSM_PIN_FUNCTION(usb_fs2_oe), + MSM_PIN_FUNCTION(usb_fs2_oe_n), + MSM_PIN_FUNCTION(vfe_camif_timer1_a), + MSM_PIN_FUNCTION(vfe_camif_timer1_b), + MSM_PIN_FUNCTION(vfe_camif_timer2), + MSM_PIN_FUNCTION(vfe_camif_timer3_a), + MSM_PIN_FUNCTION(vfe_camif_timer3_b), + MSM_PIN_FUNCTION(vfe_camif_timer4_a), + MSM_PIN_FUNCTION(vfe_camif_timer4_b), + MSM_PIN_FUNCTION(vfe_camif_timer4_c), + MSM_PIN_FUNCTION(vfe_camif_timer5_a), + MSM_PIN_FUNCTION(vfe_camif_timer5_b), + MSM_PIN_FUNCTION(vfe_camif_timer6_a), + MSM_PIN_FUNCTION(vfe_camif_timer6_b), + MSM_PIN_FUNCTION(vfe_camif_timer6_c), + MSM_PIN_FUNCTION(vfe_camif_timer7_a), + MSM_PIN_FUNCTION(vfe_camif_timer7_b), + MSM_PIN_FUNCTION(vfe_camif_timer7_c), + MSM_PIN_FUNCTION(wlan), }; static const struct msm_pingroup msm8960_groups[] = { diff --git a/drivers/pinctrl/qcom/pinctrl-msm8976.c b/drivers/pinctrl/qcom/pinctrl-msm8976.c index e11d8458471905280774863f842a294ee255a32a..c30d80e4e98ca68ccede66001445967a47d6ec8f 100644 --- a/drivers/pinctrl/qcom/pinctrl-msm8976.c +++ b/drivers/pinctrl/qcom/pinctrl-msm8976.c @@ -8,24 +8,16 @@ #include #include #include -#include #include "pinctrl-msm.h" -#define FUNCTION(fname) \ - [msm_mux_##fname] = { \ - .name = #fname, \ - .groups = fname##_groups, \ - .ngroups = ARRAY_SIZE(fname##_groups), \ - } - #define REG_BASE 0x0 #define REG_SIZE 0x1000 #define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9) \ { \ - .name = "gpio" #id, \ - .pins = gpio##id##_pins, \ - .npins = ARRAY_SIZE(gpio##id##_pins), \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ .funcs = (int[]){ \ msm_mux_gpio, /* gpio mode */ \ msm_mux_##f1, \ @@ -62,9 +54,9 @@ #define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = ctl, \ .io_reg = 0, \ .intr_cfg_reg = 0, \ @@ -819,102 +811,102 @@ static const char * const ss_switch_groups[] = { "gpio139", }; -static const struct msm_function msm8976_functions[] = { - FUNCTION(gpio), - FUNCTION(blsp_spi1), - FUNCTION(smb_int), - FUNCTION(blsp_i2c1), - FUNCTION(blsp_spi2), - FUNCTION(blsp_uart1), - FUNCTION(blsp_uart2), - FUNCTION(blsp_i2c2), - FUNCTION(gcc_gp1_clk_b), - FUNCTION(blsp_spi3), - FUNCTION(qdss_tracedata_b), - FUNCTION(blsp_i2c3), - FUNCTION(gcc_gp2_clk_b), - FUNCTION(gcc_gp3_clk_b), - FUNCTION(blsp_spi4), - FUNCTION(cap_int), - FUNCTION(blsp_i2c4), - FUNCTION(blsp_spi5), - FUNCTION(blsp_uart5), - FUNCTION(qdss_traceclk_a), - FUNCTION(m_voc), - FUNCTION(blsp_i2c5), - FUNCTION(qdss_tracectl_a), - FUNCTION(qdss_tracedata_a), - FUNCTION(blsp_spi6), - FUNCTION(blsp_uart6), - FUNCTION(qdss_tracectl_b), - FUNCTION(blsp_i2c6), - FUNCTION(qdss_traceclk_b), - FUNCTION(mdp_vsync), - FUNCTION(pri_mi2s_mclk_a), - FUNCTION(sec_mi2s_mclk_a), - FUNCTION(cam_mclk), - FUNCTION(cci0_i2c), - FUNCTION(cci1_i2c), - FUNCTION(blsp1_spi), - FUNCTION(blsp3_spi), - FUNCTION(gcc_gp1_clk_a), - FUNCTION(gcc_gp2_clk_a), - FUNCTION(gcc_gp3_clk_a), - FUNCTION(uim_batt), - FUNCTION(sd_write), - FUNCTION(uim1_data), - FUNCTION(uim1_clk), - FUNCTION(uim1_reset), - FUNCTION(uim1_present), - FUNCTION(uim2_data), - FUNCTION(uim2_clk), - FUNCTION(uim2_reset), - FUNCTION(uim2_present), - FUNCTION(ts_xvdd), - FUNCTION(mipi_dsi0), - FUNCTION(us_euro), - FUNCTION(ts_resout), - FUNCTION(ts_sample), - FUNCTION(sec_mi2s_mclk_b), - FUNCTION(pri_mi2s), - FUNCTION(codec_reset), - FUNCTION(cdc_pdm0), - FUNCTION(us_emitter), - FUNCTION(pri_mi2s_mclk_b), - FUNCTION(pri_mi2s_mclk_c), - FUNCTION(lpass_slimbus), - FUNCTION(lpass_slimbus0), - FUNCTION(lpass_slimbus1), - FUNCTION(codec_int1), - FUNCTION(codec_int2), - FUNCTION(wcss_bt), - FUNCTION(sdc3), - FUNCTION(wcss_wlan2), - FUNCTION(wcss_wlan1), - FUNCTION(wcss_wlan0), - FUNCTION(wcss_wlan), - FUNCTION(wcss_fm), - FUNCTION(key_volp), - FUNCTION(key_snapshot), - FUNCTION(key_focus), - FUNCTION(key_home), - FUNCTION(pwr_down), - FUNCTION(dmic0_clk), - FUNCTION(hdmi_int), - FUNCTION(dmic0_data), - FUNCTION(wsa_vi), - FUNCTION(wsa_en), - FUNCTION(blsp_spi8), - FUNCTION(wsa_irq), - FUNCTION(blsp_i2c8), - FUNCTION(pa_indicator), - FUNCTION(modem_tsync), - FUNCTION(ssbi_wtr1), - FUNCTION(gsm1_tx), - FUNCTION(gsm0_tx), - FUNCTION(sdcard_det), - FUNCTION(sec_mi2s), - FUNCTION(ss_switch), +static const struct pinfunction msm8976_functions[] = { + MSM_PIN_FUNCTION(gpio), + MSM_PIN_FUNCTION(blsp_spi1), + MSM_PIN_FUNCTION(smb_int), + MSM_PIN_FUNCTION(blsp_i2c1), + MSM_PIN_FUNCTION(blsp_spi2), + MSM_PIN_FUNCTION(blsp_uart1), + MSM_PIN_FUNCTION(blsp_uart2), + MSM_PIN_FUNCTION(blsp_i2c2), + MSM_PIN_FUNCTION(gcc_gp1_clk_b), + MSM_PIN_FUNCTION(blsp_spi3), + MSM_PIN_FUNCTION(qdss_tracedata_b), + MSM_PIN_FUNCTION(blsp_i2c3), + MSM_PIN_FUNCTION(gcc_gp2_clk_b), + MSM_PIN_FUNCTION(gcc_gp3_clk_b), + MSM_PIN_FUNCTION(blsp_spi4), + MSM_PIN_FUNCTION(cap_int), + MSM_PIN_FUNCTION(blsp_i2c4), + MSM_PIN_FUNCTION(blsp_spi5), + MSM_PIN_FUNCTION(blsp_uart5), + MSM_PIN_FUNCTION(qdss_traceclk_a), + MSM_PIN_FUNCTION(m_voc), + MSM_PIN_FUNCTION(blsp_i2c5), + MSM_PIN_FUNCTION(qdss_tracectl_a), + MSM_PIN_FUNCTION(qdss_tracedata_a), + MSM_PIN_FUNCTION(blsp_spi6), + MSM_PIN_FUNCTION(blsp_uart6), + MSM_PIN_FUNCTION(qdss_tracectl_b), + MSM_PIN_FUNCTION(blsp_i2c6), + MSM_PIN_FUNCTION(qdss_traceclk_b), + MSM_PIN_FUNCTION(mdp_vsync), + MSM_PIN_FUNCTION(pri_mi2s_mclk_a), + MSM_PIN_FUNCTION(sec_mi2s_mclk_a), + MSM_PIN_FUNCTION(cam_mclk), + MSM_PIN_FUNCTION(cci0_i2c), + MSM_PIN_FUNCTION(cci1_i2c), + MSM_PIN_FUNCTION(blsp1_spi), + MSM_PIN_FUNCTION(blsp3_spi), + MSM_PIN_FUNCTION(gcc_gp1_clk_a), + MSM_PIN_FUNCTION(gcc_gp2_clk_a), + MSM_PIN_FUNCTION(gcc_gp3_clk_a), + MSM_PIN_FUNCTION(uim_batt), + MSM_PIN_FUNCTION(sd_write), + MSM_PIN_FUNCTION(uim1_data), + MSM_PIN_FUNCTION(uim1_clk), + MSM_PIN_FUNCTION(uim1_reset), + MSM_PIN_FUNCTION(uim1_present), + MSM_PIN_FUNCTION(uim2_data), + MSM_PIN_FUNCTION(uim2_clk), + MSM_PIN_FUNCTION(uim2_reset), + MSM_PIN_FUNCTION(uim2_present), + MSM_PIN_FUNCTION(ts_xvdd), + MSM_PIN_FUNCTION(mipi_dsi0), + MSM_PIN_FUNCTION(us_euro), + MSM_PIN_FUNCTION(ts_resout), + MSM_PIN_FUNCTION(ts_sample), + MSM_PIN_FUNCTION(sec_mi2s_mclk_b), + MSM_PIN_FUNCTION(pri_mi2s), + MSM_PIN_FUNCTION(codec_reset), + MSM_PIN_FUNCTION(cdc_pdm0), + MSM_PIN_FUNCTION(us_emitter), + MSM_PIN_FUNCTION(pri_mi2s_mclk_b), + MSM_PIN_FUNCTION(pri_mi2s_mclk_c), + MSM_PIN_FUNCTION(lpass_slimbus), + MSM_PIN_FUNCTION(lpass_slimbus0), + MSM_PIN_FUNCTION(lpass_slimbus1), + MSM_PIN_FUNCTION(codec_int1), + MSM_PIN_FUNCTION(codec_int2), + MSM_PIN_FUNCTION(wcss_bt), + MSM_PIN_FUNCTION(sdc3), + MSM_PIN_FUNCTION(wcss_wlan2), + MSM_PIN_FUNCTION(wcss_wlan1), + MSM_PIN_FUNCTION(wcss_wlan0), + MSM_PIN_FUNCTION(wcss_wlan), + MSM_PIN_FUNCTION(wcss_fm), + MSM_PIN_FUNCTION(key_volp), + MSM_PIN_FUNCTION(key_snapshot), + MSM_PIN_FUNCTION(key_focus), + MSM_PIN_FUNCTION(key_home), + MSM_PIN_FUNCTION(pwr_down), + MSM_PIN_FUNCTION(dmic0_clk), + MSM_PIN_FUNCTION(hdmi_int), + MSM_PIN_FUNCTION(dmic0_data), + MSM_PIN_FUNCTION(wsa_vi), + MSM_PIN_FUNCTION(wsa_en), + MSM_PIN_FUNCTION(blsp_spi8), + MSM_PIN_FUNCTION(wsa_irq), + MSM_PIN_FUNCTION(blsp_i2c8), + MSM_PIN_FUNCTION(pa_indicator), + MSM_PIN_FUNCTION(modem_tsync), + MSM_PIN_FUNCTION(ssbi_wtr1), + MSM_PIN_FUNCTION(gsm1_tx), + MSM_PIN_FUNCTION(gsm0_tx), + MSM_PIN_FUNCTION(sdcard_det), + MSM_PIN_FUNCTION(sec_mi2s), + MSM_PIN_FUNCTION(ss_switch), }; static const struct msm_pingroup msm8976_groups[] = { diff --git a/drivers/pinctrl/qcom/pinctrl-msm8994.c b/drivers/pinctrl/qcom/pinctrl-msm8994.c index 0ec886563f45a8876c77da3b60927adc423b2033..b1a6759ab4a5e70501aba4325e80db2359251204 100644 --- a/drivers/pinctrl/qcom/pinctrl-msm8994.c +++ b/drivers/pinctrl/qcom/pinctrl-msm8994.c @@ -6,35 +6,27 @@ #include #include #include -#include #include "pinctrl-msm.h" -#define FUNCTION(fname) \ - [MSM_MUX_##fname] = { \ - .name = #fname, \ - .groups = fname##_groups, \ - .ngroups = ARRAY_SIZE(fname##_groups), \ - } - #define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11) \ { \ - .name = "gpio" #id, \ - .pins = gpio##id##_pins, \ - .npins = ARRAY_SIZE(gpio##id##_pins), \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ .funcs = (int[]){ \ - MSM_MUX_gpio, \ - MSM_MUX_##f1, \ - MSM_MUX_##f2, \ - MSM_MUX_##f3, \ - MSM_MUX_##f4, \ - MSM_MUX_##f5, \ - MSM_MUX_##f6, \ - MSM_MUX_##f7, \ - MSM_MUX_##f8, \ - MSM_MUX_##f9, \ - MSM_MUX_##f10, \ - MSM_MUX_##f11 \ + msm_mux_gpio, \ + msm_mux_##f1, \ + msm_mux_##f2, \ + msm_mux_##f3, \ + msm_mux_##f4, \ + msm_mux_##f5, \ + msm_mux_##f6, \ + msm_mux_##f7, \ + msm_mux_##f8, \ + msm_mux_##f9, \ + msm_mux_##f10, \ + msm_mux_##f11 \ }, \ .nfuncs = 12, \ .ctl_reg = 0x1000 + 0x10 * id, \ @@ -60,9 +52,9 @@ #define SDC_PINGROUP(pg_name, ctl, pull, drv) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = ctl, \ .io_reg = 0, \ .intr_cfg_reg = 0, \ @@ -403,136 +395,136 @@ static const unsigned int sdc3_cmd_pins[] = { 154 }; static const unsigned int sdc3_data_pins[] = { 155 }; enum msm8994_functions { - MSM_MUX_audio_ref_clk, - MSM_MUX_blsp_i2c1, - MSM_MUX_blsp_i2c2, - MSM_MUX_blsp_i2c3, - MSM_MUX_blsp_i2c4, - MSM_MUX_blsp_i2c5, - MSM_MUX_blsp_i2c6, - MSM_MUX_blsp_i2c7, - MSM_MUX_blsp_i2c8, - MSM_MUX_blsp_i2c9, - MSM_MUX_blsp_i2c10, - MSM_MUX_blsp_i2c11, - MSM_MUX_blsp_i2c12, - MSM_MUX_blsp_spi1, - MSM_MUX_blsp_spi1_cs1, - MSM_MUX_blsp_spi1_cs2, - MSM_MUX_blsp_spi1_cs3, - MSM_MUX_blsp_spi2, - MSM_MUX_blsp_spi2_cs1, - MSM_MUX_blsp_spi2_cs2, - MSM_MUX_blsp_spi2_cs3, - MSM_MUX_blsp_spi3, - MSM_MUX_blsp_spi4, - MSM_MUX_blsp_spi5, - MSM_MUX_blsp_spi6, - MSM_MUX_blsp_spi7, - MSM_MUX_blsp_spi8, - MSM_MUX_blsp_spi9, - MSM_MUX_blsp_spi10, - MSM_MUX_blsp_spi10_cs1, - MSM_MUX_blsp_spi10_cs2, - MSM_MUX_blsp_spi10_cs3, - MSM_MUX_blsp_spi11, - MSM_MUX_blsp_spi12, - MSM_MUX_blsp_uart1, - MSM_MUX_blsp_uart2, - MSM_MUX_blsp_uart3, - MSM_MUX_blsp_uart4, - MSM_MUX_blsp_uart5, - MSM_MUX_blsp_uart6, - MSM_MUX_blsp_uart7, - MSM_MUX_blsp_uart8, - MSM_MUX_blsp_uart9, - MSM_MUX_blsp_uart10, - MSM_MUX_blsp_uart11, - MSM_MUX_blsp_uart12, - MSM_MUX_blsp_uim1, - MSM_MUX_blsp_uim2, - MSM_MUX_blsp_uim3, - MSM_MUX_blsp_uim4, - MSM_MUX_blsp_uim5, - MSM_MUX_blsp_uim6, - MSM_MUX_blsp_uim7, - MSM_MUX_blsp_uim8, - MSM_MUX_blsp_uim9, - MSM_MUX_blsp_uim10, - MSM_MUX_blsp_uim11, - MSM_MUX_blsp_uim12, - MSM_MUX_blsp11_i2c_scl_b, - MSM_MUX_blsp11_i2c_sda_b, - MSM_MUX_blsp11_uart_rx_b, - MSM_MUX_blsp11_uart_tx_b, - MSM_MUX_cam_mclk0, - MSM_MUX_cam_mclk1, - MSM_MUX_cam_mclk2, - MSM_MUX_cam_mclk3, - MSM_MUX_cci_async_in0, - MSM_MUX_cci_async_in1, - MSM_MUX_cci_async_in2, - MSM_MUX_cci_i2c0, - MSM_MUX_cci_i2c1, - MSM_MUX_cci_timer0, - MSM_MUX_cci_timer1, - MSM_MUX_cci_timer2, - MSM_MUX_cci_timer3, - MSM_MUX_cci_timer4, - MSM_MUX_gcc_gp1_clk_a, - MSM_MUX_gcc_gp1_clk_b, - MSM_MUX_gcc_gp2_clk_a, - MSM_MUX_gcc_gp2_clk_b, - MSM_MUX_gcc_gp3_clk_a, - MSM_MUX_gcc_gp3_clk_b, - MSM_MUX_gp_mn, - MSM_MUX_gp_pdm0, - MSM_MUX_gp_pdm1, - MSM_MUX_gp_pdm2, - MSM_MUX_gp0_clk, - MSM_MUX_gp1_clk, - MSM_MUX_gps_tx, - MSM_MUX_gsm_tx, - MSM_MUX_hdmi_cec, - MSM_MUX_hdmi_ddc, - MSM_MUX_hdmi_hpd, - MSM_MUX_hdmi_rcv, - MSM_MUX_mdp_vsync, - MSM_MUX_mss_lte, - MSM_MUX_nav_pps, - MSM_MUX_nav_tsync, - MSM_MUX_qdss_cti_trig_in_a, - MSM_MUX_qdss_cti_trig_in_b, - MSM_MUX_qdss_cti_trig_in_c, - MSM_MUX_qdss_cti_trig_in_d, - MSM_MUX_qdss_cti_trig_out_a, - MSM_MUX_qdss_cti_trig_out_b, - MSM_MUX_qdss_cti_trig_out_c, - MSM_MUX_qdss_cti_trig_out_d, - MSM_MUX_qdss_traceclk_a, - MSM_MUX_qdss_traceclk_b, - MSM_MUX_qdss_tracectl_a, - MSM_MUX_qdss_tracectl_b, - MSM_MUX_qdss_tracedata_a, - MSM_MUX_qdss_tracedata_b, - MSM_MUX_qua_mi2s, - MSM_MUX_pci_e0, - MSM_MUX_pci_e1, - MSM_MUX_pri_mi2s, - MSM_MUX_sdc4, - MSM_MUX_sec_mi2s, - MSM_MUX_slimbus, - MSM_MUX_spkr_i2s, - MSM_MUX_ter_mi2s, - MSM_MUX_tsif1, - MSM_MUX_tsif2, - MSM_MUX_uim1, - MSM_MUX_uim2, - MSM_MUX_uim3, - MSM_MUX_uim4, - MSM_MUX_uim_batt_alarm, - MSM_MUX_gpio, - MSM_MUX_NA, + msm_mux_audio_ref_clk, + msm_mux_blsp_i2c1, + msm_mux_blsp_i2c2, + msm_mux_blsp_i2c3, + msm_mux_blsp_i2c4, + msm_mux_blsp_i2c5, + msm_mux_blsp_i2c6, + msm_mux_blsp_i2c7, + msm_mux_blsp_i2c8, + msm_mux_blsp_i2c9, + msm_mux_blsp_i2c10, + msm_mux_blsp_i2c11, + msm_mux_blsp_i2c12, + msm_mux_blsp_spi1, + msm_mux_blsp_spi1_cs1, + msm_mux_blsp_spi1_cs2, + msm_mux_blsp_spi1_cs3, + msm_mux_blsp_spi2, + msm_mux_blsp_spi2_cs1, + msm_mux_blsp_spi2_cs2, + msm_mux_blsp_spi2_cs3, + msm_mux_blsp_spi3, + msm_mux_blsp_spi4, + msm_mux_blsp_spi5, + msm_mux_blsp_spi6, + msm_mux_blsp_spi7, + msm_mux_blsp_spi8, + msm_mux_blsp_spi9, + msm_mux_blsp_spi10, + msm_mux_blsp_spi10_cs1, + msm_mux_blsp_spi10_cs2, + msm_mux_blsp_spi10_cs3, + msm_mux_blsp_spi11, + msm_mux_blsp_spi12, + msm_mux_blsp_uart1, + msm_mux_blsp_uart2, + msm_mux_blsp_uart3, + msm_mux_blsp_uart4, + msm_mux_blsp_uart5, + msm_mux_blsp_uart6, + msm_mux_blsp_uart7, + msm_mux_blsp_uart8, + msm_mux_blsp_uart9, + msm_mux_blsp_uart10, + msm_mux_blsp_uart11, + msm_mux_blsp_uart12, + msm_mux_blsp_uim1, + msm_mux_blsp_uim2, + msm_mux_blsp_uim3, + msm_mux_blsp_uim4, + msm_mux_blsp_uim5, + msm_mux_blsp_uim6, + msm_mux_blsp_uim7, + msm_mux_blsp_uim8, + msm_mux_blsp_uim9, + msm_mux_blsp_uim10, + msm_mux_blsp_uim11, + msm_mux_blsp_uim12, + msm_mux_blsp11_i2c_scl_b, + msm_mux_blsp11_i2c_sda_b, + msm_mux_blsp11_uart_rx_b, + msm_mux_blsp11_uart_tx_b, + msm_mux_cam_mclk0, + msm_mux_cam_mclk1, + msm_mux_cam_mclk2, + msm_mux_cam_mclk3, + msm_mux_cci_async_in0, + msm_mux_cci_async_in1, + msm_mux_cci_async_in2, + msm_mux_cci_i2c0, + msm_mux_cci_i2c1, + msm_mux_cci_timer0, + msm_mux_cci_timer1, + msm_mux_cci_timer2, + msm_mux_cci_timer3, + msm_mux_cci_timer4, + msm_mux_gcc_gp1_clk_a, + msm_mux_gcc_gp1_clk_b, + msm_mux_gcc_gp2_clk_a, + msm_mux_gcc_gp2_clk_b, + msm_mux_gcc_gp3_clk_a, + msm_mux_gcc_gp3_clk_b, + msm_mux_gp_mn, + msm_mux_gp_pdm0, + msm_mux_gp_pdm1, + msm_mux_gp_pdm2, + msm_mux_gp0_clk, + msm_mux_gp1_clk, + msm_mux_gps_tx, + msm_mux_gsm_tx, + msm_mux_hdmi_cec, + msm_mux_hdmi_ddc, + msm_mux_hdmi_hpd, + msm_mux_hdmi_rcv, + msm_mux_mdp_vsync, + msm_mux_mss_lte, + msm_mux_nav_pps, + msm_mux_nav_tsync, + msm_mux_qdss_cti_trig_in_a, + msm_mux_qdss_cti_trig_in_b, + msm_mux_qdss_cti_trig_in_c, + msm_mux_qdss_cti_trig_in_d, + msm_mux_qdss_cti_trig_out_a, + msm_mux_qdss_cti_trig_out_b, + msm_mux_qdss_cti_trig_out_c, + msm_mux_qdss_cti_trig_out_d, + msm_mux_qdss_traceclk_a, + msm_mux_qdss_traceclk_b, + msm_mux_qdss_tracectl_a, + msm_mux_qdss_tracectl_b, + msm_mux_qdss_tracedata_a, + msm_mux_qdss_tracedata_b, + msm_mux_qua_mi2s, + msm_mux_pci_e0, + msm_mux_pci_e1, + msm_mux_pri_mi2s, + msm_mux_sdc4, + msm_mux_sec_mi2s, + msm_mux_slimbus, + msm_mux_spkr_i2s, + msm_mux_ter_mi2s, + msm_mux_tsif1, + msm_mux_tsif2, + msm_mux_uim1, + msm_mux_uim2, + msm_mux_uim3, + msm_mux_uim4, + msm_mux_uim_batt_alarm, + msm_mux_gpio, + msm_mux_NA, }; static const char * const gpio_groups[] = { @@ -950,136 +942,136 @@ static const char * const mss_lte_groups[] = { "gpio134", "gpio135" }; -static const struct msm_function msm8994_functions[] = { - FUNCTION(audio_ref_clk), - FUNCTION(blsp_i2c1), - FUNCTION(blsp_i2c2), - FUNCTION(blsp_i2c3), - FUNCTION(blsp_i2c4), - FUNCTION(blsp_i2c5), - FUNCTION(blsp_i2c6), - FUNCTION(blsp_i2c7), - FUNCTION(blsp_i2c8), - FUNCTION(blsp_i2c9), - FUNCTION(blsp_i2c10), - FUNCTION(blsp_i2c11), - FUNCTION(blsp_i2c12), - FUNCTION(blsp_spi1), - FUNCTION(blsp_spi1_cs1), - FUNCTION(blsp_spi1_cs2), - FUNCTION(blsp_spi1_cs3), - FUNCTION(blsp_spi2), - FUNCTION(blsp_spi2_cs1), - FUNCTION(blsp_spi2_cs2), - FUNCTION(blsp_spi2_cs3), - FUNCTION(blsp_spi3), - FUNCTION(blsp_spi4), - FUNCTION(blsp_spi5), - FUNCTION(blsp_spi6), - FUNCTION(blsp_spi7), - FUNCTION(blsp_spi8), - FUNCTION(blsp_spi9), - FUNCTION(blsp_spi10), - FUNCTION(blsp_spi10_cs1), - FUNCTION(blsp_spi10_cs2), - FUNCTION(blsp_spi10_cs3), - FUNCTION(blsp_spi11), - FUNCTION(blsp_spi12), - FUNCTION(blsp_uart1), - FUNCTION(blsp_uart2), - FUNCTION(blsp_uart3), - FUNCTION(blsp_uart4), - FUNCTION(blsp_uart5), - FUNCTION(blsp_uart6), - FUNCTION(blsp_uart7), - FUNCTION(blsp_uart8), - FUNCTION(blsp_uart9), - FUNCTION(blsp_uart10), - FUNCTION(blsp_uart11), - FUNCTION(blsp_uart12), - FUNCTION(blsp_uim1), - FUNCTION(blsp_uim2), - FUNCTION(blsp_uim3), - FUNCTION(blsp_uim4), - FUNCTION(blsp_uim5), - FUNCTION(blsp_uim6), - FUNCTION(blsp_uim7), - FUNCTION(blsp_uim8), - FUNCTION(blsp_uim9), - FUNCTION(blsp_uim10), - FUNCTION(blsp_uim11), - FUNCTION(blsp_uim12), - FUNCTION(blsp11_i2c_scl_b), - FUNCTION(blsp11_i2c_sda_b), - FUNCTION(blsp11_uart_rx_b), - FUNCTION(blsp11_uart_tx_b), - FUNCTION(cam_mclk0), - FUNCTION(cam_mclk1), - FUNCTION(cam_mclk2), - FUNCTION(cam_mclk3), - FUNCTION(cci_async_in0), - FUNCTION(cci_async_in1), - FUNCTION(cci_async_in2), - FUNCTION(cci_i2c0), - FUNCTION(cci_i2c1), - FUNCTION(cci_timer0), - FUNCTION(cci_timer1), - FUNCTION(cci_timer2), - FUNCTION(cci_timer3), - FUNCTION(cci_timer4), - FUNCTION(gcc_gp1_clk_a), - FUNCTION(gcc_gp1_clk_b), - FUNCTION(gcc_gp2_clk_a), - FUNCTION(gcc_gp2_clk_b), - FUNCTION(gcc_gp3_clk_a), - FUNCTION(gcc_gp3_clk_b), - FUNCTION(gp_mn), - FUNCTION(gp_pdm0), - FUNCTION(gp_pdm1), - FUNCTION(gp_pdm2), - FUNCTION(gp0_clk), - FUNCTION(gp1_clk), - FUNCTION(gps_tx), - FUNCTION(gsm_tx), - FUNCTION(hdmi_cec), - FUNCTION(hdmi_ddc), - FUNCTION(hdmi_hpd), - FUNCTION(hdmi_rcv), - FUNCTION(mdp_vsync), - FUNCTION(mss_lte), - FUNCTION(nav_pps), - FUNCTION(nav_tsync), - FUNCTION(qdss_cti_trig_in_a), - FUNCTION(qdss_cti_trig_in_b), - FUNCTION(qdss_cti_trig_in_c), - FUNCTION(qdss_cti_trig_in_d), - FUNCTION(qdss_cti_trig_out_a), - FUNCTION(qdss_cti_trig_out_b), - FUNCTION(qdss_cti_trig_out_c), - FUNCTION(qdss_cti_trig_out_d), - FUNCTION(qdss_traceclk_a), - FUNCTION(qdss_traceclk_b), - FUNCTION(qdss_tracectl_a), - FUNCTION(qdss_tracectl_b), - FUNCTION(qdss_tracedata_a), - FUNCTION(qdss_tracedata_b), - FUNCTION(qua_mi2s), - FUNCTION(pci_e0), - FUNCTION(pci_e1), - FUNCTION(pri_mi2s), - FUNCTION(sdc4), - FUNCTION(sec_mi2s), - FUNCTION(slimbus), - FUNCTION(spkr_i2s), - FUNCTION(ter_mi2s), - FUNCTION(tsif1), - FUNCTION(tsif2), - FUNCTION(uim_batt_alarm), - FUNCTION(uim1), - FUNCTION(uim2), - FUNCTION(uim3), - FUNCTION(uim4), - FUNCTION(gpio), +static const struct pinfunction msm8994_functions[] = { + MSM_PIN_FUNCTION(audio_ref_clk), + MSM_PIN_FUNCTION(blsp_i2c1), + MSM_PIN_FUNCTION(blsp_i2c2), + MSM_PIN_FUNCTION(blsp_i2c3), + MSM_PIN_FUNCTION(blsp_i2c4), + MSM_PIN_FUNCTION(blsp_i2c5), + MSM_PIN_FUNCTION(blsp_i2c6), + MSM_PIN_FUNCTION(blsp_i2c7), + MSM_PIN_FUNCTION(blsp_i2c8), + MSM_PIN_FUNCTION(blsp_i2c9), + MSM_PIN_FUNCTION(blsp_i2c10), + MSM_PIN_FUNCTION(blsp_i2c11), + MSM_PIN_FUNCTION(blsp_i2c12), + MSM_PIN_FUNCTION(blsp_spi1), + MSM_PIN_FUNCTION(blsp_spi1_cs1), + MSM_PIN_FUNCTION(blsp_spi1_cs2), + MSM_PIN_FUNCTION(blsp_spi1_cs3), + MSM_PIN_FUNCTION(blsp_spi2), + MSM_PIN_FUNCTION(blsp_spi2_cs1), + MSM_PIN_FUNCTION(blsp_spi2_cs2), + MSM_PIN_FUNCTION(blsp_spi2_cs3), + MSM_PIN_FUNCTION(blsp_spi3), + MSM_PIN_FUNCTION(blsp_spi4), + MSM_PIN_FUNCTION(blsp_spi5), + MSM_PIN_FUNCTION(blsp_spi6), + MSM_PIN_FUNCTION(blsp_spi7), + MSM_PIN_FUNCTION(blsp_spi8), + MSM_PIN_FUNCTION(blsp_spi9), + MSM_PIN_FUNCTION(blsp_spi10), + MSM_PIN_FUNCTION(blsp_spi10_cs1), + MSM_PIN_FUNCTION(blsp_spi10_cs2), + MSM_PIN_FUNCTION(blsp_spi10_cs3), + MSM_PIN_FUNCTION(blsp_spi11), + MSM_PIN_FUNCTION(blsp_spi12), + MSM_PIN_FUNCTION(blsp_uart1), + MSM_PIN_FUNCTION(blsp_uart2), + MSM_PIN_FUNCTION(blsp_uart3), + MSM_PIN_FUNCTION(blsp_uart4), + MSM_PIN_FUNCTION(blsp_uart5), + MSM_PIN_FUNCTION(blsp_uart6), + MSM_PIN_FUNCTION(blsp_uart7), + MSM_PIN_FUNCTION(blsp_uart8), + MSM_PIN_FUNCTION(blsp_uart9), + MSM_PIN_FUNCTION(blsp_uart10), + MSM_PIN_FUNCTION(blsp_uart11), + MSM_PIN_FUNCTION(blsp_uart12), + MSM_PIN_FUNCTION(blsp_uim1), + MSM_PIN_FUNCTION(blsp_uim2), + MSM_PIN_FUNCTION(blsp_uim3), + MSM_PIN_FUNCTION(blsp_uim4), + MSM_PIN_FUNCTION(blsp_uim5), + MSM_PIN_FUNCTION(blsp_uim6), + MSM_PIN_FUNCTION(blsp_uim7), + MSM_PIN_FUNCTION(blsp_uim8), + MSM_PIN_FUNCTION(blsp_uim9), + MSM_PIN_FUNCTION(blsp_uim10), + MSM_PIN_FUNCTION(blsp_uim11), + MSM_PIN_FUNCTION(blsp_uim12), + MSM_PIN_FUNCTION(blsp11_i2c_scl_b), + MSM_PIN_FUNCTION(blsp11_i2c_sda_b), + MSM_PIN_FUNCTION(blsp11_uart_rx_b), + MSM_PIN_FUNCTION(blsp11_uart_tx_b), + MSM_PIN_FUNCTION(cam_mclk0), + MSM_PIN_FUNCTION(cam_mclk1), + MSM_PIN_FUNCTION(cam_mclk2), + MSM_PIN_FUNCTION(cam_mclk3), + MSM_PIN_FUNCTION(cci_async_in0), + MSM_PIN_FUNCTION(cci_async_in1), + MSM_PIN_FUNCTION(cci_async_in2), + MSM_PIN_FUNCTION(cci_i2c0), + MSM_PIN_FUNCTION(cci_i2c1), + MSM_PIN_FUNCTION(cci_timer0), + MSM_PIN_FUNCTION(cci_timer1), + MSM_PIN_FUNCTION(cci_timer2), + MSM_PIN_FUNCTION(cci_timer3), + MSM_PIN_FUNCTION(cci_timer4), + MSM_PIN_FUNCTION(gcc_gp1_clk_a), + MSM_PIN_FUNCTION(gcc_gp1_clk_b), + MSM_PIN_FUNCTION(gcc_gp2_clk_a), + MSM_PIN_FUNCTION(gcc_gp2_clk_b), + MSM_PIN_FUNCTION(gcc_gp3_clk_a), + MSM_PIN_FUNCTION(gcc_gp3_clk_b), + MSM_PIN_FUNCTION(gp_mn), + MSM_PIN_FUNCTION(gp_pdm0), + MSM_PIN_FUNCTION(gp_pdm1), + MSM_PIN_FUNCTION(gp_pdm2), + MSM_PIN_FUNCTION(gp0_clk), + MSM_PIN_FUNCTION(gp1_clk), + MSM_PIN_FUNCTION(gps_tx), + MSM_PIN_FUNCTION(gsm_tx), + MSM_PIN_FUNCTION(hdmi_cec), + MSM_PIN_FUNCTION(hdmi_ddc), + MSM_PIN_FUNCTION(hdmi_hpd), + MSM_PIN_FUNCTION(hdmi_rcv), + MSM_PIN_FUNCTION(mdp_vsync), + MSM_PIN_FUNCTION(mss_lte), + MSM_PIN_FUNCTION(nav_pps), + MSM_PIN_FUNCTION(nav_tsync), + MSM_PIN_FUNCTION(qdss_cti_trig_in_a), + MSM_PIN_FUNCTION(qdss_cti_trig_in_b), + MSM_PIN_FUNCTION(qdss_cti_trig_in_c), + MSM_PIN_FUNCTION(qdss_cti_trig_in_d), + MSM_PIN_FUNCTION(qdss_cti_trig_out_a), + MSM_PIN_FUNCTION(qdss_cti_trig_out_b), + MSM_PIN_FUNCTION(qdss_cti_trig_out_c), + MSM_PIN_FUNCTION(qdss_cti_trig_out_d), + MSM_PIN_FUNCTION(qdss_traceclk_a), + MSM_PIN_FUNCTION(qdss_traceclk_b), + MSM_PIN_FUNCTION(qdss_tracectl_a), + MSM_PIN_FUNCTION(qdss_tracectl_b), + MSM_PIN_FUNCTION(qdss_tracedata_a), + MSM_PIN_FUNCTION(qdss_tracedata_b), + MSM_PIN_FUNCTION(qua_mi2s), + MSM_PIN_FUNCTION(pci_e0), + MSM_PIN_FUNCTION(pci_e1), + MSM_PIN_FUNCTION(pri_mi2s), + MSM_PIN_FUNCTION(sdc4), + MSM_PIN_FUNCTION(sec_mi2s), + MSM_PIN_FUNCTION(slimbus), + MSM_PIN_FUNCTION(spkr_i2s), + MSM_PIN_FUNCTION(ter_mi2s), + MSM_PIN_FUNCTION(tsif1), + MSM_PIN_FUNCTION(tsif2), + MSM_PIN_FUNCTION(uim_batt_alarm), + MSM_PIN_FUNCTION(uim1), + MSM_PIN_FUNCTION(uim2), + MSM_PIN_FUNCTION(uim3), + MSM_PIN_FUNCTION(uim4), + MSM_PIN_FUNCTION(gpio), }; static const struct msm_pingroup msm8994_groups[] = { diff --git a/drivers/pinctrl/qcom/pinctrl-msm8996.c b/drivers/pinctrl/qcom/pinctrl-msm8996.c index 05812dfdb368636182166109aaf6eec48a89d43d..46cc0b49dbab52bdff9012715ef7776edfe6b908 100644 --- a/drivers/pinctrl/qcom/pinctrl-msm8996.c +++ b/drivers/pinctrl/qcom/pinctrl-msm8996.c @@ -6,24 +6,16 @@ #include #include #include -#include #include "pinctrl-msm.h" -#define FUNCTION(fname) \ - [msm_mux_##fname] = { \ - .name = #fname, \ - .groups = fname##_groups, \ - .ngroups = ARRAY_SIZE(fname##_groups), \ - } - #define REG_BASE 0x0 #define REG_SIZE 0x1000 #define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9) \ { \ - .name = "gpio" #id, \ - .pins = gpio##id##_pins, \ - .npins = (unsigned)ARRAY_SIZE(gpio##id##_pins), \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ .funcs = (int[]){ \ msm_mux_gpio, /* gpio mode */ \ msm_mux_##f1, \ @@ -60,9 +52,9 @@ #define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = (unsigned)ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = ctl, \ .io_reg = 0, \ .intr_cfg_reg = 0, \ @@ -1409,250 +1401,250 @@ static const char * const qspi3_groups[] = { "gpio149", }; -static const struct msm_function msm8996_functions[] = { - FUNCTION(adsp_ext), - FUNCTION(atest_bbrx0), - FUNCTION(atest_bbrx1), - FUNCTION(atest_char), - FUNCTION(atest_char0), - FUNCTION(atest_char1), - FUNCTION(atest_char2), - FUNCTION(atest_char3), - FUNCTION(atest_gpsadc0), - FUNCTION(atest_gpsadc1), - FUNCTION(atest_tsens), - FUNCTION(atest_tsens2), - FUNCTION(atest_usb1), - FUNCTION(atest_usb10), - FUNCTION(atest_usb11), - FUNCTION(atest_usb12), - FUNCTION(atest_usb13), - FUNCTION(atest_usb2), - FUNCTION(atest_usb20), - FUNCTION(atest_usb21), - FUNCTION(atest_usb22), - FUNCTION(atest_usb23), - FUNCTION(audio_ref), - FUNCTION(bimc_dte0), - FUNCTION(bimc_dte1), - FUNCTION(blsp10_spi), - FUNCTION(blsp11_i2c_scl_b), - FUNCTION(blsp11_i2c_sda_b), - FUNCTION(blsp11_uart_rx_b), - FUNCTION(blsp11_uart_tx_b), - FUNCTION(blsp1_spi), - FUNCTION(blsp2_spi), - FUNCTION(blsp_i2c1), - FUNCTION(blsp_i2c10), - FUNCTION(blsp_i2c11), - FUNCTION(blsp_i2c12), - FUNCTION(blsp_i2c2), - FUNCTION(blsp_i2c3), - FUNCTION(blsp_i2c4), - FUNCTION(blsp_i2c5), - FUNCTION(blsp_i2c6), - FUNCTION(blsp_i2c7), - FUNCTION(blsp_i2c8), - FUNCTION(blsp_i2c9), - FUNCTION(blsp_spi1), - FUNCTION(blsp_spi10), - FUNCTION(blsp_spi11), - FUNCTION(blsp_spi12), - FUNCTION(blsp_spi2), - FUNCTION(blsp_spi3), - FUNCTION(blsp_spi4), - FUNCTION(blsp_spi5), - FUNCTION(blsp_spi6), - FUNCTION(blsp_spi7), - FUNCTION(blsp_spi8), - FUNCTION(blsp_spi9), - FUNCTION(blsp_uart1), - FUNCTION(blsp_uart10), - FUNCTION(blsp_uart11), - FUNCTION(blsp_uart12), - FUNCTION(blsp_uart2), - FUNCTION(blsp_uart3), - FUNCTION(blsp_uart4), - FUNCTION(blsp_uart5), - FUNCTION(blsp_uart6), - FUNCTION(blsp_uart7), - FUNCTION(blsp_uart8), - FUNCTION(blsp_uart9), - FUNCTION(blsp_uim1), - FUNCTION(blsp_uim10), - FUNCTION(blsp_uim11), - FUNCTION(blsp_uim12), - FUNCTION(blsp_uim2), - FUNCTION(blsp_uim3), - FUNCTION(blsp_uim4), - FUNCTION(blsp_uim5), - FUNCTION(blsp_uim6), - FUNCTION(blsp_uim7), - FUNCTION(blsp_uim8), - FUNCTION(blsp_uim9), - FUNCTION(btfm_slimbus), - FUNCTION(cam_mclk), - FUNCTION(cci_async), - FUNCTION(cci_i2c), - FUNCTION(cci_timer0), - FUNCTION(cci_timer1), - FUNCTION(cci_timer2), - FUNCTION(cci_timer3), - FUNCTION(cci_timer4), - FUNCTION(cri_trng), - FUNCTION(cri_trng0), - FUNCTION(cri_trng1), - FUNCTION(dac_calib0), - FUNCTION(dac_calib1), - FUNCTION(dac_calib10), - FUNCTION(dac_calib11), - FUNCTION(dac_calib12), - FUNCTION(dac_calib13), - FUNCTION(dac_calib14), - FUNCTION(dac_calib15), - FUNCTION(dac_calib16), - FUNCTION(dac_calib17), - FUNCTION(dac_calib18), - FUNCTION(dac_calib19), - FUNCTION(dac_calib2), - FUNCTION(dac_calib20), - FUNCTION(dac_calib21), - FUNCTION(dac_calib22), - FUNCTION(dac_calib23), - FUNCTION(dac_calib24), - FUNCTION(dac_calib25), - FUNCTION(dac_calib26), - FUNCTION(dac_calib3), - FUNCTION(dac_calib4), - FUNCTION(dac_calib5), - FUNCTION(dac_calib6), - FUNCTION(dac_calib7), - FUNCTION(dac_calib8), - FUNCTION(dac_calib9), - FUNCTION(dac_gpio), - FUNCTION(dbg_out), - FUNCTION(ddr_bist), - FUNCTION(edp_hot), - FUNCTION(edp_lcd), - FUNCTION(gcc_gp1_clk_a), - FUNCTION(gcc_gp1_clk_b), - FUNCTION(gcc_gp2_clk_a), - FUNCTION(gcc_gp2_clk_b), - FUNCTION(gcc_gp3_clk_a), - FUNCTION(gcc_gp3_clk_b), - FUNCTION(gpio), - FUNCTION(gsm_tx), - FUNCTION(hdmi_cec), - FUNCTION(hdmi_ddc), - FUNCTION(hdmi_hot), - FUNCTION(hdmi_rcv), - FUNCTION(isense_dbg), - FUNCTION(ldo_en), - FUNCTION(ldo_update), - FUNCTION(lpass_slimbus), - FUNCTION(m_voc), - FUNCTION(mdp_vsync), - FUNCTION(mdp_vsync_p_b), - FUNCTION(mdp_vsync_s_b), - FUNCTION(modem_tsync), - FUNCTION(mss_lte), - FUNCTION(nav_dr), - FUNCTION(nav_pps), - FUNCTION(pa_indicator), - FUNCTION(pci_e0), - FUNCTION(pci_e1), - FUNCTION(pci_e2), - FUNCTION(pll_bypassnl), - FUNCTION(pll_reset), - FUNCTION(pri_mi2s), - FUNCTION(prng_rosc), - FUNCTION(pwr_crypto), - FUNCTION(pwr_modem), - FUNCTION(pwr_nav), - FUNCTION(qdss_cti), - FUNCTION(qdss_cti_trig_in_a), - FUNCTION(qdss_cti_trig_in_b), - FUNCTION(qdss_cti_trig_out_a), - FUNCTION(qdss_cti_trig_out_b), - FUNCTION(qdss_stm0), - FUNCTION(qdss_stm1), - FUNCTION(qdss_stm10), - FUNCTION(qdss_stm11), - FUNCTION(qdss_stm12), - FUNCTION(qdss_stm13), - FUNCTION(qdss_stm14), - FUNCTION(qdss_stm15), - FUNCTION(qdss_stm16), - FUNCTION(qdss_stm17), - FUNCTION(qdss_stm18), - FUNCTION(qdss_stm19), - FUNCTION(qdss_stm2), - FUNCTION(qdss_stm20), - FUNCTION(qdss_stm21), - FUNCTION(qdss_stm22), - FUNCTION(qdss_stm23), - FUNCTION(qdss_stm24), - FUNCTION(qdss_stm25), - FUNCTION(qdss_stm26), - FUNCTION(qdss_stm27), - FUNCTION(qdss_stm28), - FUNCTION(qdss_stm29), - FUNCTION(qdss_stm3), - FUNCTION(qdss_stm30), - FUNCTION(qdss_stm31), - FUNCTION(qdss_stm4), - FUNCTION(qdss_stm5), - FUNCTION(qdss_stm6), - FUNCTION(qdss_stm7), - FUNCTION(qdss_stm8), - FUNCTION(qdss_stm9), - FUNCTION(qdss_traceclk_a), - FUNCTION(qdss_traceclk_b), - FUNCTION(qdss_tracectl_a), - FUNCTION(qdss_tracectl_b), - FUNCTION(qdss_tracedata_11), - FUNCTION(qdss_tracedata_12), - FUNCTION(qdss_tracedata_a), - FUNCTION(qdss_tracedata_b), - FUNCTION(qspi0), - FUNCTION(qspi1), - FUNCTION(qspi2), - FUNCTION(qspi3), - FUNCTION(qspi_clk), - FUNCTION(qspi_cs), - FUNCTION(qua_mi2s), - FUNCTION(sd_card), - FUNCTION(sd_write), - FUNCTION(sdc40), - FUNCTION(sdc41), - FUNCTION(sdc42), - FUNCTION(sdc43), - FUNCTION(sdc4_clk), - FUNCTION(sdc4_cmd), - FUNCTION(sec_mi2s), - FUNCTION(spkr_i2s), - FUNCTION(ssbi1), - FUNCTION(ssbi2), - FUNCTION(ssc_irq), - FUNCTION(ter_mi2s), - FUNCTION(tsense_pwm1), - FUNCTION(tsense_pwm2), - FUNCTION(tsif1_clk), - FUNCTION(tsif1_data), - FUNCTION(tsif1_en), - FUNCTION(tsif1_error), - FUNCTION(tsif1_sync), - FUNCTION(tsif2_clk), - FUNCTION(tsif2_data), - FUNCTION(tsif2_en), - FUNCTION(tsif2_error), - FUNCTION(tsif2_sync), - FUNCTION(uim1), - FUNCTION(uim2), - FUNCTION(uim3), - FUNCTION(uim4), - FUNCTION(uim_batt), - FUNCTION(vfr_1), +static const struct pinfunction msm8996_functions[] = { + MSM_PIN_FUNCTION(adsp_ext), + MSM_PIN_FUNCTION(atest_bbrx0), + MSM_PIN_FUNCTION(atest_bbrx1), + MSM_PIN_FUNCTION(atest_char), + MSM_PIN_FUNCTION(atest_char0), + MSM_PIN_FUNCTION(atest_char1), + MSM_PIN_FUNCTION(atest_char2), + MSM_PIN_FUNCTION(atest_char3), + MSM_PIN_FUNCTION(atest_gpsadc0), + MSM_PIN_FUNCTION(atest_gpsadc1), + MSM_PIN_FUNCTION(atest_tsens), + MSM_PIN_FUNCTION(atest_tsens2), + MSM_PIN_FUNCTION(atest_usb1), + MSM_PIN_FUNCTION(atest_usb10), + MSM_PIN_FUNCTION(atest_usb11), + MSM_PIN_FUNCTION(atest_usb12), + MSM_PIN_FUNCTION(atest_usb13), + MSM_PIN_FUNCTION(atest_usb2), + MSM_PIN_FUNCTION(atest_usb20), + MSM_PIN_FUNCTION(atest_usb21), + MSM_PIN_FUNCTION(atest_usb22), + MSM_PIN_FUNCTION(atest_usb23), + MSM_PIN_FUNCTION(audio_ref), + MSM_PIN_FUNCTION(bimc_dte0), + MSM_PIN_FUNCTION(bimc_dte1), + MSM_PIN_FUNCTION(blsp10_spi), + MSM_PIN_FUNCTION(blsp11_i2c_scl_b), + MSM_PIN_FUNCTION(blsp11_i2c_sda_b), + MSM_PIN_FUNCTION(blsp11_uart_rx_b), + MSM_PIN_FUNCTION(blsp11_uart_tx_b), + MSM_PIN_FUNCTION(blsp1_spi), + MSM_PIN_FUNCTION(blsp2_spi), + MSM_PIN_FUNCTION(blsp_i2c1), + MSM_PIN_FUNCTION(blsp_i2c10), + MSM_PIN_FUNCTION(blsp_i2c11), + MSM_PIN_FUNCTION(blsp_i2c12), + MSM_PIN_FUNCTION(blsp_i2c2), + MSM_PIN_FUNCTION(blsp_i2c3), + MSM_PIN_FUNCTION(blsp_i2c4), + MSM_PIN_FUNCTION(blsp_i2c5), + MSM_PIN_FUNCTION(blsp_i2c6), + MSM_PIN_FUNCTION(blsp_i2c7), + MSM_PIN_FUNCTION(blsp_i2c8), + MSM_PIN_FUNCTION(blsp_i2c9), + MSM_PIN_FUNCTION(blsp_spi1), + MSM_PIN_FUNCTION(blsp_spi10), + MSM_PIN_FUNCTION(blsp_spi11), + MSM_PIN_FUNCTION(blsp_spi12), + MSM_PIN_FUNCTION(blsp_spi2), + MSM_PIN_FUNCTION(blsp_spi3), + MSM_PIN_FUNCTION(blsp_spi4), + MSM_PIN_FUNCTION(blsp_spi5), + MSM_PIN_FUNCTION(blsp_spi6), + MSM_PIN_FUNCTION(blsp_spi7), + MSM_PIN_FUNCTION(blsp_spi8), + MSM_PIN_FUNCTION(blsp_spi9), + MSM_PIN_FUNCTION(blsp_uart1), + MSM_PIN_FUNCTION(blsp_uart10), + MSM_PIN_FUNCTION(blsp_uart11), + MSM_PIN_FUNCTION(blsp_uart12), + MSM_PIN_FUNCTION(blsp_uart2), + MSM_PIN_FUNCTION(blsp_uart3), + MSM_PIN_FUNCTION(blsp_uart4), + MSM_PIN_FUNCTION(blsp_uart5), + MSM_PIN_FUNCTION(blsp_uart6), + MSM_PIN_FUNCTION(blsp_uart7), + MSM_PIN_FUNCTION(blsp_uart8), + MSM_PIN_FUNCTION(blsp_uart9), + MSM_PIN_FUNCTION(blsp_uim1), + MSM_PIN_FUNCTION(blsp_uim10), + MSM_PIN_FUNCTION(blsp_uim11), + MSM_PIN_FUNCTION(blsp_uim12), + MSM_PIN_FUNCTION(blsp_uim2), + MSM_PIN_FUNCTION(blsp_uim3), + MSM_PIN_FUNCTION(blsp_uim4), + MSM_PIN_FUNCTION(blsp_uim5), + MSM_PIN_FUNCTION(blsp_uim6), + MSM_PIN_FUNCTION(blsp_uim7), + MSM_PIN_FUNCTION(blsp_uim8), + MSM_PIN_FUNCTION(blsp_uim9), + MSM_PIN_FUNCTION(btfm_slimbus), + MSM_PIN_FUNCTION(cam_mclk), + MSM_PIN_FUNCTION(cci_async), + MSM_PIN_FUNCTION(cci_i2c), + MSM_PIN_FUNCTION(cci_timer0), + MSM_PIN_FUNCTION(cci_timer1), + MSM_PIN_FUNCTION(cci_timer2), + MSM_PIN_FUNCTION(cci_timer3), + MSM_PIN_FUNCTION(cci_timer4), + MSM_PIN_FUNCTION(cri_trng), + MSM_PIN_FUNCTION(cri_trng0), + MSM_PIN_FUNCTION(cri_trng1), + MSM_PIN_FUNCTION(dac_calib0), + MSM_PIN_FUNCTION(dac_calib1), + MSM_PIN_FUNCTION(dac_calib10), + MSM_PIN_FUNCTION(dac_calib11), + MSM_PIN_FUNCTION(dac_calib12), + MSM_PIN_FUNCTION(dac_calib13), + MSM_PIN_FUNCTION(dac_calib14), + MSM_PIN_FUNCTION(dac_calib15), + MSM_PIN_FUNCTION(dac_calib16), + MSM_PIN_FUNCTION(dac_calib17), + MSM_PIN_FUNCTION(dac_calib18), + MSM_PIN_FUNCTION(dac_calib19), + MSM_PIN_FUNCTION(dac_calib2), + MSM_PIN_FUNCTION(dac_calib20), + MSM_PIN_FUNCTION(dac_calib21), + MSM_PIN_FUNCTION(dac_calib22), + MSM_PIN_FUNCTION(dac_calib23), + MSM_PIN_FUNCTION(dac_calib24), + MSM_PIN_FUNCTION(dac_calib25), + MSM_PIN_FUNCTION(dac_calib26), + MSM_PIN_FUNCTION(dac_calib3), + MSM_PIN_FUNCTION(dac_calib4), + MSM_PIN_FUNCTION(dac_calib5), + MSM_PIN_FUNCTION(dac_calib6), + MSM_PIN_FUNCTION(dac_calib7), + MSM_PIN_FUNCTION(dac_calib8), + MSM_PIN_FUNCTION(dac_calib9), + MSM_PIN_FUNCTION(dac_gpio), + MSM_PIN_FUNCTION(dbg_out), + MSM_PIN_FUNCTION(ddr_bist), + MSM_PIN_FUNCTION(edp_hot), + MSM_PIN_FUNCTION(edp_lcd), + MSM_PIN_FUNCTION(gcc_gp1_clk_a), + MSM_PIN_FUNCTION(gcc_gp1_clk_b), + MSM_PIN_FUNCTION(gcc_gp2_clk_a), + MSM_PIN_FUNCTION(gcc_gp2_clk_b), + MSM_PIN_FUNCTION(gcc_gp3_clk_a), + MSM_PIN_FUNCTION(gcc_gp3_clk_b), + MSM_PIN_FUNCTION(gpio), + MSM_PIN_FUNCTION(gsm_tx), + MSM_PIN_FUNCTION(hdmi_cec), + MSM_PIN_FUNCTION(hdmi_ddc), + MSM_PIN_FUNCTION(hdmi_hot), + MSM_PIN_FUNCTION(hdmi_rcv), + MSM_PIN_FUNCTION(isense_dbg), + MSM_PIN_FUNCTION(ldo_en), + MSM_PIN_FUNCTION(ldo_update), + MSM_PIN_FUNCTION(lpass_slimbus), + MSM_PIN_FUNCTION(m_voc), + MSM_PIN_FUNCTION(mdp_vsync), + MSM_PIN_FUNCTION(mdp_vsync_p_b), + MSM_PIN_FUNCTION(mdp_vsync_s_b), + MSM_PIN_FUNCTION(modem_tsync), + MSM_PIN_FUNCTION(mss_lte), + MSM_PIN_FUNCTION(nav_dr), + MSM_PIN_FUNCTION(nav_pps), + MSM_PIN_FUNCTION(pa_indicator), + MSM_PIN_FUNCTION(pci_e0), + MSM_PIN_FUNCTION(pci_e1), + MSM_PIN_FUNCTION(pci_e2), + MSM_PIN_FUNCTION(pll_bypassnl), + MSM_PIN_FUNCTION(pll_reset), + MSM_PIN_FUNCTION(pri_mi2s), + MSM_PIN_FUNCTION(prng_rosc), + MSM_PIN_FUNCTION(pwr_crypto), + MSM_PIN_FUNCTION(pwr_modem), + MSM_PIN_FUNCTION(pwr_nav), + MSM_PIN_FUNCTION(qdss_cti), + MSM_PIN_FUNCTION(qdss_cti_trig_in_a), + MSM_PIN_FUNCTION(qdss_cti_trig_in_b), + MSM_PIN_FUNCTION(qdss_cti_trig_out_a), + MSM_PIN_FUNCTION(qdss_cti_trig_out_b), + MSM_PIN_FUNCTION(qdss_stm0), + MSM_PIN_FUNCTION(qdss_stm1), + MSM_PIN_FUNCTION(qdss_stm10), + MSM_PIN_FUNCTION(qdss_stm11), + MSM_PIN_FUNCTION(qdss_stm12), + MSM_PIN_FUNCTION(qdss_stm13), + MSM_PIN_FUNCTION(qdss_stm14), + MSM_PIN_FUNCTION(qdss_stm15), + MSM_PIN_FUNCTION(qdss_stm16), + MSM_PIN_FUNCTION(qdss_stm17), + MSM_PIN_FUNCTION(qdss_stm18), + MSM_PIN_FUNCTION(qdss_stm19), + MSM_PIN_FUNCTION(qdss_stm2), + MSM_PIN_FUNCTION(qdss_stm20), + MSM_PIN_FUNCTION(qdss_stm21), + MSM_PIN_FUNCTION(qdss_stm22), + MSM_PIN_FUNCTION(qdss_stm23), + MSM_PIN_FUNCTION(qdss_stm24), + MSM_PIN_FUNCTION(qdss_stm25), + MSM_PIN_FUNCTION(qdss_stm26), + MSM_PIN_FUNCTION(qdss_stm27), + MSM_PIN_FUNCTION(qdss_stm28), + MSM_PIN_FUNCTION(qdss_stm29), + MSM_PIN_FUNCTION(qdss_stm3), + MSM_PIN_FUNCTION(qdss_stm30), + MSM_PIN_FUNCTION(qdss_stm31), + MSM_PIN_FUNCTION(qdss_stm4), + MSM_PIN_FUNCTION(qdss_stm5), + MSM_PIN_FUNCTION(qdss_stm6), + MSM_PIN_FUNCTION(qdss_stm7), + MSM_PIN_FUNCTION(qdss_stm8), + MSM_PIN_FUNCTION(qdss_stm9), + MSM_PIN_FUNCTION(qdss_traceclk_a), + MSM_PIN_FUNCTION(qdss_traceclk_b), + MSM_PIN_FUNCTION(qdss_tracectl_a), + MSM_PIN_FUNCTION(qdss_tracectl_b), + MSM_PIN_FUNCTION(qdss_tracedata_11), + MSM_PIN_FUNCTION(qdss_tracedata_12), + MSM_PIN_FUNCTION(qdss_tracedata_a), + MSM_PIN_FUNCTION(qdss_tracedata_b), + MSM_PIN_FUNCTION(qspi0), + MSM_PIN_FUNCTION(qspi1), + MSM_PIN_FUNCTION(qspi2), + MSM_PIN_FUNCTION(qspi3), + MSM_PIN_FUNCTION(qspi_clk), + MSM_PIN_FUNCTION(qspi_cs), + MSM_PIN_FUNCTION(qua_mi2s), + MSM_PIN_FUNCTION(sd_card), + MSM_PIN_FUNCTION(sd_write), + MSM_PIN_FUNCTION(sdc40), + MSM_PIN_FUNCTION(sdc41), + MSM_PIN_FUNCTION(sdc42), + MSM_PIN_FUNCTION(sdc43), + MSM_PIN_FUNCTION(sdc4_clk), + MSM_PIN_FUNCTION(sdc4_cmd), + MSM_PIN_FUNCTION(sec_mi2s), + MSM_PIN_FUNCTION(spkr_i2s), + MSM_PIN_FUNCTION(ssbi1), + MSM_PIN_FUNCTION(ssbi2), + MSM_PIN_FUNCTION(ssc_irq), + MSM_PIN_FUNCTION(ter_mi2s), + MSM_PIN_FUNCTION(tsense_pwm1), + MSM_PIN_FUNCTION(tsense_pwm2), + MSM_PIN_FUNCTION(tsif1_clk), + MSM_PIN_FUNCTION(tsif1_data), + MSM_PIN_FUNCTION(tsif1_en), + MSM_PIN_FUNCTION(tsif1_error), + MSM_PIN_FUNCTION(tsif1_sync), + MSM_PIN_FUNCTION(tsif2_clk), + MSM_PIN_FUNCTION(tsif2_data), + MSM_PIN_FUNCTION(tsif2_en), + MSM_PIN_FUNCTION(tsif2_error), + MSM_PIN_FUNCTION(tsif2_sync), + MSM_PIN_FUNCTION(uim1), + MSM_PIN_FUNCTION(uim2), + MSM_PIN_FUNCTION(uim3), + MSM_PIN_FUNCTION(uim4), + MSM_PIN_FUNCTION(uim_batt), + MSM_PIN_FUNCTION(vfr_1), }; static const struct msm_pingroup msm8996_groups[] = { diff --git a/drivers/pinctrl/qcom/pinctrl-msm8998.c b/drivers/pinctrl/qcom/pinctrl-msm8998.c index 1a061bc9b8fa978090100932cbad3d482cd451b9..b7cbf32b3125a91081c6644cd3d343e08499dd1f 100644 --- a/drivers/pinctrl/qcom/pinctrl-msm8998.c +++ b/drivers/pinctrl/qcom/pinctrl-msm8998.c @@ -6,7 +6,6 @@ #include #include #include -#include #include "pinctrl-msm.h" @@ -14,18 +13,11 @@ #define WEST 0x100000 #define EAST 0x900000 -#define FUNCTION(fname) \ - [msm_mux_##fname] = { \ - .name = #fname, \ - .groups = fname##_groups, \ - .ngroups = ARRAY_SIZE(fname##_groups), \ - } - #define PINGROUP(id, base, f1, f2, f3, f4, f5, f6, f7, f8, f9) \ { \ - .name = "gpio" #id, \ - .pins = gpio##id##_pins, \ - .npins = ARRAY_SIZE(gpio##id##_pins), \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ .funcs = (int[]){ \ msm_mux_gpio, /* gpio mode */ \ msm_mux_##f1, \ @@ -62,9 +54,9 @@ #define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = ctl, \ .io_reg = 0, \ .intr_cfg_reg = 0, \ @@ -87,9 +79,9 @@ #define UFS_RESET(pg_name, offset) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = offset, \ .io_reg = offset + 0x4, \ .intr_cfg_reg = 0, \ @@ -1167,183 +1159,183 @@ static const char * const mss_lte_groups[] = { "gpio144", "gpio145", }; -static const struct msm_function msm8998_functions[] = { - FUNCTION(gpio), - FUNCTION(adsp_ext), - FUNCTION(agera_pll), - FUNCTION(atest_char), - FUNCTION(atest_gpsadc0), - FUNCTION(atest_gpsadc1), - FUNCTION(atest_tsens), - FUNCTION(atest_tsens2), - FUNCTION(atest_usb1), - FUNCTION(atest_usb10), - FUNCTION(atest_usb11), - FUNCTION(atest_usb12), - FUNCTION(atest_usb13), - FUNCTION(audio_ref), - FUNCTION(bimc_dte0), - FUNCTION(bimc_dte1), - FUNCTION(blsp10_spi), - FUNCTION(blsp10_spi_a), - FUNCTION(blsp10_spi_b), - FUNCTION(blsp11_i2c), - FUNCTION(blsp1_spi), - FUNCTION(blsp1_spi_a), - FUNCTION(blsp1_spi_b), - FUNCTION(blsp2_spi), - FUNCTION(blsp9_spi), - FUNCTION(blsp_i2c1), - FUNCTION(blsp_i2c2), - FUNCTION(blsp_i2c3), - FUNCTION(blsp_i2c4), - FUNCTION(blsp_i2c5), - FUNCTION(blsp_i2c6), - FUNCTION(blsp_i2c7), - FUNCTION(blsp_i2c8), - FUNCTION(blsp_i2c9), - FUNCTION(blsp_i2c10), - FUNCTION(blsp_i2c11), - FUNCTION(blsp_i2c12), - FUNCTION(blsp_spi1), - FUNCTION(blsp_spi2), - FUNCTION(blsp_spi3), - FUNCTION(blsp_spi4), - FUNCTION(blsp_spi5), - FUNCTION(blsp_spi6), - FUNCTION(blsp_spi7), - FUNCTION(blsp_spi8), - FUNCTION(blsp_spi9), - FUNCTION(blsp_spi10), - FUNCTION(blsp_spi11), - FUNCTION(blsp_spi12), - FUNCTION(blsp_uart1_a), - FUNCTION(blsp_uart1_b), - FUNCTION(blsp_uart2_a), - FUNCTION(blsp_uart2_b), - FUNCTION(blsp_uart3_a), - FUNCTION(blsp_uart3_b), - FUNCTION(blsp_uart7_a), - FUNCTION(blsp_uart7_b), - FUNCTION(blsp_uart8), - FUNCTION(blsp_uart8_a), - FUNCTION(blsp_uart8_b), - FUNCTION(blsp_uart9_a), - FUNCTION(blsp_uart9_b), - FUNCTION(blsp_uim1_a), - FUNCTION(blsp_uim1_b), - FUNCTION(blsp_uim2_a), - FUNCTION(blsp_uim2_b), - FUNCTION(blsp_uim3_a), - FUNCTION(blsp_uim3_b), - FUNCTION(blsp_uim7_a), - FUNCTION(blsp_uim7_b), - FUNCTION(blsp_uim8_a), - FUNCTION(blsp_uim8_b), - FUNCTION(blsp_uim9_a), - FUNCTION(blsp_uim9_b), - FUNCTION(bt_reset), - FUNCTION(btfm_slimbus), - FUNCTION(cam_mclk), - FUNCTION(cci_async), - FUNCTION(cci_i2c), - FUNCTION(cci_timer0), - FUNCTION(cci_timer1), - FUNCTION(cci_timer2), - FUNCTION(cci_timer3), - FUNCTION(cci_timer4), - FUNCTION(cri_trng), - FUNCTION(cri_trng0), - FUNCTION(cri_trng1), - FUNCTION(dbg_out), - FUNCTION(ddr_bist), - FUNCTION(edp_hot), - FUNCTION(edp_lcd), - FUNCTION(gcc_gp1_a), - FUNCTION(gcc_gp1_b), - FUNCTION(gcc_gp2_a), - FUNCTION(gcc_gp2_b), - FUNCTION(gcc_gp3_a), - FUNCTION(gcc_gp3_b), - FUNCTION(hdmi_cec), - FUNCTION(hdmi_ddc), - FUNCTION(hdmi_hot), - FUNCTION(hdmi_rcv), - FUNCTION(isense_dbg), - FUNCTION(jitter_bist), - FUNCTION(ldo_en), - FUNCTION(ldo_update), - FUNCTION(lpass_slimbus), - FUNCTION(m_voc), - FUNCTION(mdp_vsync), - FUNCTION(mdp_vsync0), - FUNCTION(mdp_vsync1), - FUNCTION(mdp_vsync2), - FUNCTION(mdp_vsync3), - FUNCTION(mdp_vsync_a), - FUNCTION(mdp_vsync_b), - FUNCTION(modem_tsync), - FUNCTION(mss_lte), - FUNCTION(nav_dr), - FUNCTION(nav_pps), - FUNCTION(pa_indicator), - FUNCTION(pci_e0), - FUNCTION(phase_flag), - FUNCTION(pll_bypassnl), - FUNCTION(pll_reset), - FUNCTION(pri_mi2s), - FUNCTION(pri_mi2s_ws), - FUNCTION(prng_rosc), - FUNCTION(pwr_crypto), - FUNCTION(pwr_modem), - FUNCTION(pwr_nav), - FUNCTION(qdss_cti0_a), - FUNCTION(qdss_cti0_b), - FUNCTION(qdss_cti1_a), - FUNCTION(qdss_cti1_b), - FUNCTION(qdss), - FUNCTION(qlink_enable), - FUNCTION(qlink_request), - FUNCTION(qua_mi2s), - FUNCTION(sd_card), - FUNCTION(sd_write), - FUNCTION(sdc40), - FUNCTION(sdc41), - FUNCTION(sdc42), - FUNCTION(sdc43), - FUNCTION(sdc4_clk), - FUNCTION(sdc4_cmd), - FUNCTION(sec_mi2s), - FUNCTION(sp_cmu), - FUNCTION(spkr_i2s), - FUNCTION(ssbi1), - FUNCTION(ssc_irq), - FUNCTION(ter_mi2s), - FUNCTION(tgu_ch0), - FUNCTION(tgu_ch1), - FUNCTION(tsense_pwm1), - FUNCTION(tsense_pwm2), - FUNCTION(tsif0), - FUNCTION(tsif1), - FUNCTION(uim1_clk), - FUNCTION(uim1_data), - FUNCTION(uim1_present), - FUNCTION(uim1_reset), - FUNCTION(uim2_clk), - FUNCTION(uim2_data), - FUNCTION(uim2_present), - FUNCTION(uim2_reset), - FUNCTION(uim_batt), - FUNCTION(usb_phy), - FUNCTION(vfr_1), - FUNCTION(vsense_clkout), - FUNCTION(vsense_data0), - FUNCTION(vsense_data1), - FUNCTION(vsense_mode), - FUNCTION(wlan1_adc0), - FUNCTION(wlan1_adc1), - FUNCTION(wlan2_adc0), - FUNCTION(wlan2_adc1), +static const struct pinfunction msm8998_functions[] = { + MSM_PIN_FUNCTION(gpio), + MSM_PIN_FUNCTION(adsp_ext), + MSM_PIN_FUNCTION(agera_pll), + MSM_PIN_FUNCTION(atest_char), + MSM_PIN_FUNCTION(atest_gpsadc0), + MSM_PIN_FUNCTION(atest_gpsadc1), + MSM_PIN_FUNCTION(atest_tsens), + MSM_PIN_FUNCTION(atest_tsens2), + MSM_PIN_FUNCTION(atest_usb1), + MSM_PIN_FUNCTION(atest_usb10), + MSM_PIN_FUNCTION(atest_usb11), + MSM_PIN_FUNCTION(atest_usb12), + MSM_PIN_FUNCTION(atest_usb13), + MSM_PIN_FUNCTION(audio_ref), + MSM_PIN_FUNCTION(bimc_dte0), + MSM_PIN_FUNCTION(bimc_dte1), + MSM_PIN_FUNCTION(blsp10_spi), + MSM_PIN_FUNCTION(blsp10_spi_a), + MSM_PIN_FUNCTION(blsp10_spi_b), + MSM_PIN_FUNCTION(blsp11_i2c), + MSM_PIN_FUNCTION(blsp1_spi), + MSM_PIN_FUNCTION(blsp1_spi_a), + MSM_PIN_FUNCTION(blsp1_spi_b), + MSM_PIN_FUNCTION(blsp2_spi), + MSM_PIN_FUNCTION(blsp9_spi), + MSM_PIN_FUNCTION(blsp_i2c1), + MSM_PIN_FUNCTION(blsp_i2c2), + MSM_PIN_FUNCTION(blsp_i2c3), + MSM_PIN_FUNCTION(blsp_i2c4), + MSM_PIN_FUNCTION(blsp_i2c5), + MSM_PIN_FUNCTION(blsp_i2c6), + MSM_PIN_FUNCTION(blsp_i2c7), + MSM_PIN_FUNCTION(blsp_i2c8), + MSM_PIN_FUNCTION(blsp_i2c9), + MSM_PIN_FUNCTION(blsp_i2c10), + MSM_PIN_FUNCTION(blsp_i2c11), + MSM_PIN_FUNCTION(blsp_i2c12), + MSM_PIN_FUNCTION(blsp_spi1), + MSM_PIN_FUNCTION(blsp_spi2), + MSM_PIN_FUNCTION(blsp_spi3), + MSM_PIN_FUNCTION(blsp_spi4), + MSM_PIN_FUNCTION(blsp_spi5), + MSM_PIN_FUNCTION(blsp_spi6), + MSM_PIN_FUNCTION(blsp_spi7), + MSM_PIN_FUNCTION(blsp_spi8), + MSM_PIN_FUNCTION(blsp_spi9), + MSM_PIN_FUNCTION(blsp_spi10), + MSM_PIN_FUNCTION(blsp_spi11), + MSM_PIN_FUNCTION(blsp_spi12), + MSM_PIN_FUNCTION(blsp_uart1_a), + MSM_PIN_FUNCTION(blsp_uart1_b), + MSM_PIN_FUNCTION(blsp_uart2_a), + MSM_PIN_FUNCTION(blsp_uart2_b), + MSM_PIN_FUNCTION(blsp_uart3_a), + MSM_PIN_FUNCTION(blsp_uart3_b), + MSM_PIN_FUNCTION(blsp_uart7_a), + MSM_PIN_FUNCTION(blsp_uart7_b), + MSM_PIN_FUNCTION(blsp_uart8), + MSM_PIN_FUNCTION(blsp_uart8_a), + MSM_PIN_FUNCTION(blsp_uart8_b), + MSM_PIN_FUNCTION(blsp_uart9_a), + MSM_PIN_FUNCTION(blsp_uart9_b), + MSM_PIN_FUNCTION(blsp_uim1_a), + MSM_PIN_FUNCTION(blsp_uim1_b), + MSM_PIN_FUNCTION(blsp_uim2_a), + MSM_PIN_FUNCTION(blsp_uim2_b), + MSM_PIN_FUNCTION(blsp_uim3_a), + MSM_PIN_FUNCTION(blsp_uim3_b), + MSM_PIN_FUNCTION(blsp_uim7_a), + MSM_PIN_FUNCTION(blsp_uim7_b), + MSM_PIN_FUNCTION(blsp_uim8_a), + MSM_PIN_FUNCTION(blsp_uim8_b), + MSM_PIN_FUNCTION(blsp_uim9_a), + MSM_PIN_FUNCTION(blsp_uim9_b), + MSM_PIN_FUNCTION(bt_reset), + MSM_PIN_FUNCTION(btfm_slimbus), + MSM_PIN_FUNCTION(cam_mclk), + MSM_PIN_FUNCTION(cci_async), + MSM_PIN_FUNCTION(cci_i2c), + MSM_PIN_FUNCTION(cci_timer0), + MSM_PIN_FUNCTION(cci_timer1), + MSM_PIN_FUNCTION(cci_timer2), + MSM_PIN_FUNCTION(cci_timer3), + MSM_PIN_FUNCTION(cci_timer4), + MSM_PIN_FUNCTION(cri_trng), + MSM_PIN_FUNCTION(cri_trng0), + MSM_PIN_FUNCTION(cri_trng1), + MSM_PIN_FUNCTION(dbg_out), + MSM_PIN_FUNCTION(ddr_bist), + MSM_PIN_FUNCTION(edp_hot), + MSM_PIN_FUNCTION(edp_lcd), + MSM_PIN_FUNCTION(gcc_gp1_a), + MSM_PIN_FUNCTION(gcc_gp1_b), + MSM_PIN_FUNCTION(gcc_gp2_a), + MSM_PIN_FUNCTION(gcc_gp2_b), + MSM_PIN_FUNCTION(gcc_gp3_a), + MSM_PIN_FUNCTION(gcc_gp3_b), + MSM_PIN_FUNCTION(hdmi_cec), + MSM_PIN_FUNCTION(hdmi_ddc), + MSM_PIN_FUNCTION(hdmi_hot), + MSM_PIN_FUNCTION(hdmi_rcv), + MSM_PIN_FUNCTION(isense_dbg), + MSM_PIN_FUNCTION(jitter_bist), + MSM_PIN_FUNCTION(ldo_en), + MSM_PIN_FUNCTION(ldo_update), + MSM_PIN_FUNCTION(lpass_slimbus), + MSM_PIN_FUNCTION(m_voc), + MSM_PIN_FUNCTION(mdp_vsync), + MSM_PIN_FUNCTION(mdp_vsync0), + MSM_PIN_FUNCTION(mdp_vsync1), + MSM_PIN_FUNCTION(mdp_vsync2), + MSM_PIN_FUNCTION(mdp_vsync3), + MSM_PIN_FUNCTION(mdp_vsync_a), + MSM_PIN_FUNCTION(mdp_vsync_b), + MSM_PIN_FUNCTION(modem_tsync), + MSM_PIN_FUNCTION(mss_lte), + MSM_PIN_FUNCTION(nav_dr), + MSM_PIN_FUNCTION(nav_pps), + MSM_PIN_FUNCTION(pa_indicator), + MSM_PIN_FUNCTION(pci_e0), + MSM_PIN_FUNCTION(phase_flag), + MSM_PIN_FUNCTION(pll_bypassnl), + MSM_PIN_FUNCTION(pll_reset), + MSM_PIN_FUNCTION(pri_mi2s), + MSM_PIN_FUNCTION(pri_mi2s_ws), + MSM_PIN_FUNCTION(prng_rosc), + MSM_PIN_FUNCTION(pwr_crypto), + MSM_PIN_FUNCTION(pwr_modem), + MSM_PIN_FUNCTION(pwr_nav), + MSM_PIN_FUNCTION(qdss_cti0_a), + MSM_PIN_FUNCTION(qdss_cti0_b), + MSM_PIN_FUNCTION(qdss_cti1_a), + MSM_PIN_FUNCTION(qdss_cti1_b), + MSM_PIN_FUNCTION(qdss), + MSM_PIN_FUNCTION(qlink_enable), + MSM_PIN_FUNCTION(qlink_request), + MSM_PIN_FUNCTION(qua_mi2s), + MSM_PIN_FUNCTION(sd_card), + MSM_PIN_FUNCTION(sd_write), + MSM_PIN_FUNCTION(sdc40), + MSM_PIN_FUNCTION(sdc41), + MSM_PIN_FUNCTION(sdc42), + MSM_PIN_FUNCTION(sdc43), + MSM_PIN_FUNCTION(sdc4_clk), + MSM_PIN_FUNCTION(sdc4_cmd), + MSM_PIN_FUNCTION(sec_mi2s), + MSM_PIN_FUNCTION(sp_cmu), + MSM_PIN_FUNCTION(spkr_i2s), + MSM_PIN_FUNCTION(ssbi1), + MSM_PIN_FUNCTION(ssc_irq), + MSM_PIN_FUNCTION(ter_mi2s), + MSM_PIN_FUNCTION(tgu_ch0), + MSM_PIN_FUNCTION(tgu_ch1), + MSM_PIN_FUNCTION(tsense_pwm1), + MSM_PIN_FUNCTION(tsense_pwm2), + MSM_PIN_FUNCTION(tsif0), + MSM_PIN_FUNCTION(tsif1), + MSM_PIN_FUNCTION(uim1_clk), + MSM_PIN_FUNCTION(uim1_data), + MSM_PIN_FUNCTION(uim1_present), + MSM_PIN_FUNCTION(uim1_reset), + MSM_PIN_FUNCTION(uim2_clk), + MSM_PIN_FUNCTION(uim2_data), + MSM_PIN_FUNCTION(uim2_present), + MSM_PIN_FUNCTION(uim2_reset), + MSM_PIN_FUNCTION(uim_batt), + MSM_PIN_FUNCTION(usb_phy), + MSM_PIN_FUNCTION(vfr_1), + MSM_PIN_FUNCTION(vsense_clkout), + MSM_PIN_FUNCTION(vsense_data0), + MSM_PIN_FUNCTION(vsense_data1), + MSM_PIN_FUNCTION(vsense_mode), + MSM_PIN_FUNCTION(wlan1_adc0), + MSM_PIN_FUNCTION(wlan1_adc1), + MSM_PIN_FUNCTION(wlan2_adc0), + MSM_PIN_FUNCTION(wlan2_adc1), }; static const struct msm_pingroup msm8998_groups[] = { diff --git a/drivers/pinctrl/qcom/pinctrl-msm8x74.c b/drivers/pinctrl/qcom/pinctrl-msm8x74.c index 3d193acee6a374c0d2bcf104686b79f6fc4f9850..d5fe62992849c994bb958f19dffe0dff4da7995e 100644 --- a/drivers/pinctrl/qcom/pinctrl-msm8x74.c +++ b/drivers/pinctrl/qcom/pinctrl-msm8x74.c @@ -6,7 +6,6 @@ #include #include #include -#include #include "pinctrl-msm.h" @@ -325,27 +324,20 @@ static const unsigned int sdc2_data_pins[] = { 151 }; static const unsigned int hsic_strobe_pins[] = { 152 }; static const unsigned int hsic_data_pins[] = { 153 }; -#define FUNCTION(fname) \ - [MSM_MUX_##fname] = { \ - .name = #fname, \ - .groups = fname##_groups, \ - .ngroups = ARRAY_SIZE(fname##_groups), \ - } - #define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7) \ { \ - .name = "gpio" #id, \ - .pins = gpio##id##_pins, \ - .npins = ARRAY_SIZE(gpio##id##_pins), \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ .funcs = (int[]){ \ - MSM_MUX_gpio, \ - MSM_MUX_##f1, \ - MSM_MUX_##f2, \ - MSM_MUX_##f3, \ - MSM_MUX_##f4, \ - MSM_MUX_##f5, \ - MSM_MUX_##f6, \ - MSM_MUX_##f7 \ + msm_mux_gpio, \ + msm_mux_##f1, \ + msm_mux_##f2, \ + msm_mux_##f3, \ + msm_mux_##f4, \ + msm_mux_##f5, \ + msm_mux_##f6, \ + msm_mux_##f7 \ }, \ .nfuncs = 8, \ .ctl_reg = 0x1000 + 0x10 * id, \ @@ -371,9 +363,9 @@ static const unsigned int hsic_data_pins[] = { 153 }; #define SDC_PINGROUP(pg_name, ctl, pull, drv) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = ctl, \ .io_reg = 0, \ .intr_cfg_reg = 0, \ @@ -397,12 +389,12 @@ static const unsigned int hsic_data_pins[] = { 153 }; #define HSIC_PINGROUP(pg_name, ctl) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .funcs = (int[]){ \ - MSM_MUX_gpio, \ - MSM_MUX_hsic_ctl, \ + msm_mux_gpio, \ + msm_mux_hsic_ctl, \ }, \ .nfuncs = 2, \ .ctl_reg = ctl, \ @@ -431,113 +423,113 @@ static const unsigned int hsic_data_pins[] = { 153 }; * the pingroup table below. */ enum msm8x74_functions { - MSM_MUX_gpio, - MSM_MUX_cci_i2c0, - MSM_MUX_cci_i2c1, - MSM_MUX_blsp_i2c1, - MSM_MUX_blsp_i2c2, - MSM_MUX_blsp_i2c3, - MSM_MUX_blsp_i2c4, - MSM_MUX_blsp_i2c5, - MSM_MUX_blsp_i2c6, - MSM_MUX_blsp_i2c7, - MSM_MUX_blsp_i2c8, - MSM_MUX_blsp_i2c9, - MSM_MUX_blsp_i2c10, - MSM_MUX_blsp_i2c11, - MSM_MUX_blsp_i2c12, - MSM_MUX_blsp_spi1, - MSM_MUX_blsp_spi1_cs1, - MSM_MUX_blsp_spi1_cs2, - MSM_MUX_blsp_spi1_cs3, - MSM_MUX_blsp_spi2, - MSM_MUX_blsp_spi2_cs1, - MSM_MUX_blsp_spi2_cs2, - MSM_MUX_blsp_spi2_cs3, - MSM_MUX_blsp_spi3, - MSM_MUX_blsp_spi4, - MSM_MUX_blsp_spi5, - MSM_MUX_blsp_spi6, - MSM_MUX_blsp_spi7, - MSM_MUX_blsp_spi8, - MSM_MUX_blsp_spi9, - MSM_MUX_blsp_spi10, - MSM_MUX_blsp_spi10_cs1, - MSM_MUX_blsp_spi10_cs2, - MSM_MUX_blsp_spi10_cs3, - MSM_MUX_blsp_spi11, - MSM_MUX_blsp_spi12, - MSM_MUX_blsp_uart1, - MSM_MUX_blsp_uart2, - MSM_MUX_blsp_uart3, - MSM_MUX_blsp_uart4, - MSM_MUX_blsp_uart5, - MSM_MUX_blsp_uart6, - MSM_MUX_blsp_uart7, - MSM_MUX_blsp_uart8, - MSM_MUX_blsp_uart9, - MSM_MUX_blsp_uart10, - MSM_MUX_blsp_uart11, - MSM_MUX_blsp_uart12, - MSM_MUX_blsp_uim1, - MSM_MUX_blsp_uim2, - MSM_MUX_blsp_uim3, - MSM_MUX_blsp_uim4, - MSM_MUX_blsp_uim5, - MSM_MUX_blsp_uim6, - MSM_MUX_blsp_uim7, - MSM_MUX_blsp_uim8, - MSM_MUX_blsp_uim9, - MSM_MUX_blsp_uim10, - MSM_MUX_blsp_uim11, - MSM_MUX_blsp_uim12, - MSM_MUX_uim1, - MSM_MUX_uim2, - MSM_MUX_uim_batt_alarm, - MSM_MUX_sdc3, - MSM_MUX_sdc4, - MSM_MUX_gcc_gp_clk1, - MSM_MUX_gcc_gp_clk2, - MSM_MUX_gcc_gp_clk3, - MSM_MUX_qua_mi2s, - MSM_MUX_pri_mi2s, - MSM_MUX_spkr_mi2s, - MSM_MUX_ter_mi2s, - MSM_MUX_sec_mi2s, - MSM_MUX_hdmi_cec, - MSM_MUX_hdmi_ddc, - MSM_MUX_hdmi_hpd, - MSM_MUX_edp_hpd, - MSM_MUX_mdp_vsync, - MSM_MUX_cam_mclk0, - MSM_MUX_cam_mclk1, - MSM_MUX_cam_mclk2, - MSM_MUX_cam_mclk3, - MSM_MUX_cci_timer0, - MSM_MUX_cci_timer1, - MSM_MUX_cci_timer2, - MSM_MUX_cci_timer3, - MSM_MUX_cci_timer4, - MSM_MUX_cci_async_in0, - MSM_MUX_cci_async_in1, - MSM_MUX_cci_async_in2, - MSM_MUX_gp_pdm0, - MSM_MUX_gp_pdm1, - MSM_MUX_gp_pdm2, - MSM_MUX_gp0_clk, - MSM_MUX_gp1_clk, - MSM_MUX_gp_mn, - MSM_MUX_tsif1, - MSM_MUX_tsif2, - MSM_MUX_hsic, - MSM_MUX_grfc, - MSM_MUX_audio_ref_clk, - MSM_MUX_bt, - MSM_MUX_fm, - MSM_MUX_wlan, - MSM_MUX_slimbus, - MSM_MUX_hsic_ctl, - MSM_MUX_NA, + msm_mux_gpio, + msm_mux_cci_i2c0, + msm_mux_cci_i2c1, + msm_mux_blsp_i2c1, + msm_mux_blsp_i2c2, + msm_mux_blsp_i2c3, + msm_mux_blsp_i2c4, + msm_mux_blsp_i2c5, + msm_mux_blsp_i2c6, + msm_mux_blsp_i2c7, + msm_mux_blsp_i2c8, + msm_mux_blsp_i2c9, + msm_mux_blsp_i2c10, + msm_mux_blsp_i2c11, + msm_mux_blsp_i2c12, + msm_mux_blsp_spi1, + msm_mux_blsp_spi1_cs1, + msm_mux_blsp_spi1_cs2, + msm_mux_blsp_spi1_cs3, + msm_mux_blsp_spi2, + msm_mux_blsp_spi2_cs1, + msm_mux_blsp_spi2_cs2, + msm_mux_blsp_spi2_cs3, + msm_mux_blsp_spi3, + msm_mux_blsp_spi4, + msm_mux_blsp_spi5, + msm_mux_blsp_spi6, + msm_mux_blsp_spi7, + msm_mux_blsp_spi8, + msm_mux_blsp_spi9, + msm_mux_blsp_spi10, + msm_mux_blsp_spi10_cs1, + msm_mux_blsp_spi10_cs2, + msm_mux_blsp_spi10_cs3, + msm_mux_blsp_spi11, + msm_mux_blsp_spi12, + msm_mux_blsp_uart1, + msm_mux_blsp_uart2, + msm_mux_blsp_uart3, + msm_mux_blsp_uart4, + msm_mux_blsp_uart5, + msm_mux_blsp_uart6, + msm_mux_blsp_uart7, + msm_mux_blsp_uart8, + msm_mux_blsp_uart9, + msm_mux_blsp_uart10, + msm_mux_blsp_uart11, + msm_mux_blsp_uart12, + msm_mux_blsp_uim1, + msm_mux_blsp_uim2, + msm_mux_blsp_uim3, + msm_mux_blsp_uim4, + msm_mux_blsp_uim5, + msm_mux_blsp_uim6, + msm_mux_blsp_uim7, + msm_mux_blsp_uim8, + msm_mux_blsp_uim9, + msm_mux_blsp_uim10, + msm_mux_blsp_uim11, + msm_mux_blsp_uim12, + msm_mux_uim1, + msm_mux_uim2, + msm_mux_uim_batt_alarm, + msm_mux_sdc3, + msm_mux_sdc4, + msm_mux_gcc_gp_clk1, + msm_mux_gcc_gp_clk2, + msm_mux_gcc_gp_clk3, + msm_mux_qua_mi2s, + msm_mux_pri_mi2s, + msm_mux_spkr_mi2s, + msm_mux_ter_mi2s, + msm_mux_sec_mi2s, + msm_mux_hdmi_cec, + msm_mux_hdmi_ddc, + msm_mux_hdmi_hpd, + msm_mux_edp_hpd, + msm_mux_mdp_vsync, + msm_mux_cam_mclk0, + msm_mux_cam_mclk1, + msm_mux_cam_mclk2, + msm_mux_cam_mclk3, + msm_mux_cci_timer0, + msm_mux_cci_timer1, + msm_mux_cci_timer2, + msm_mux_cci_timer3, + msm_mux_cci_timer4, + msm_mux_cci_async_in0, + msm_mux_cci_async_in1, + msm_mux_cci_async_in2, + msm_mux_gp_pdm0, + msm_mux_gp_pdm1, + msm_mux_gp_pdm2, + msm_mux_gp0_clk, + msm_mux_gp1_clk, + msm_mux_gp_mn, + msm_mux_tsif1, + msm_mux_tsif2, + msm_mux_hsic, + msm_mux_grfc, + msm_mux_audio_ref_clk, + msm_mux_bt, + msm_mux_fm, + msm_mux_wlan, + msm_mux_slimbus, + msm_mux_hsic_ctl, + msm_mux_NA, }; static const char * const gpio_groups[] = { @@ -785,113 +777,113 @@ static const char * const wlan_groups[] = { static const char * const slimbus_groups[] = { "gpio70", "gpio71" }; static const char * const hsic_ctl_groups[] = { "hsic_strobe", "hsic_data" }; -static const struct msm_function msm8x74_functions[] = { - FUNCTION(gpio), - FUNCTION(cci_i2c0), - FUNCTION(cci_i2c1), - FUNCTION(uim1), - FUNCTION(uim2), - FUNCTION(uim_batt_alarm), - FUNCTION(blsp_uim1), - FUNCTION(blsp_uim2), - FUNCTION(blsp_uim3), - FUNCTION(blsp_uim4), - FUNCTION(blsp_uim5), - FUNCTION(blsp_uim6), - FUNCTION(blsp_uim7), - FUNCTION(blsp_uim8), - FUNCTION(blsp_uim9), - FUNCTION(blsp_uim10), - FUNCTION(blsp_uim11), - FUNCTION(blsp_uim12), - FUNCTION(blsp_i2c1), - FUNCTION(blsp_i2c2), - FUNCTION(blsp_i2c3), - FUNCTION(blsp_i2c4), - FUNCTION(blsp_i2c5), - FUNCTION(blsp_i2c6), - FUNCTION(blsp_i2c7), - FUNCTION(blsp_i2c8), - FUNCTION(blsp_i2c9), - FUNCTION(blsp_i2c10), - FUNCTION(blsp_i2c11), - FUNCTION(blsp_i2c12), - FUNCTION(blsp_spi1), - FUNCTION(blsp_spi1_cs1), - FUNCTION(blsp_spi1_cs2), - FUNCTION(blsp_spi1_cs3), - FUNCTION(blsp_spi2), - FUNCTION(blsp_spi2_cs1), - FUNCTION(blsp_spi2_cs2), - FUNCTION(blsp_spi2_cs3), - FUNCTION(blsp_spi3), - FUNCTION(blsp_spi4), - FUNCTION(blsp_spi5), - FUNCTION(blsp_spi6), - FUNCTION(blsp_spi7), - FUNCTION(blsp_spi8), - FUNCTION(blsp_spi9), - FUNCTION(blsp_spi10), - FUNCTION(blsp_spi10_cs1), - FUNCTION(blsp_spi10_cs2), - FUNCTION(blsp_spi10_cs3), - FUNCTION(blsp_spi11), - FUNCTION(blsp_spi12), - FUNCTION(blsp_uart1), - FUNCTION(blsp_uart2), - FUNCTION(blsp_uart3), - FUNCTION(blsp_uart4), - FUNCTION(blsp_uart5), - FUNCTION(blsp_uart6), - FUNCTION(blsp_uart7), - FUNCTION(blsp_uart8), - FUNCTION(blsp_uart9), - FUNCTION(blsp_uart10), - FUNCTION(blsp_uart11), - FUNCTION(blsp_uart12), - FUNCTION(sdc3), - FUNCTION(sdc4), - FUNCTION(gcc_gp_clk1), - FUNCTION(gcc_gp_clk2), - FUNCTION(gcc_gp_clk3), - FUNCTION(qua_mi2s), - FUNCTION(pri_mi2s), - FUNCTION(spkr_mi2s), - FUNCTION(ter_mi2s), - FUNCTION(sec_mi2s), - FUNCTION(mdp_vsync), - FUNCTION(cam_mclk0), - FUNCTION(cam_mclk1), - FUNCTION(cam_mclk2), - FUNCTION(cam_mclk3), - FUNCTION(cci_timer0), - FUNCTION(cci_timer1), - FUNCTION(cci_timer2), - FUNCTION(cci_timer3), - FUNCTION(cci_timer4), - FUNCTION(cci_async_in0), - FUNCTION(cci_async_in1), - FUNCTION(cci_async_in2), - FUNCTION(hdmi_cec), - FUNCTION(hdmi_ddc), - FUNCTION(hdmi_hpd), - FUNCTION(edp_hpd), - FUNCTION(gp_pdm0), - FUNCTION(gp_pdm1), - FUNCTION(gp_pdm2), - FUNCTION(gp0_clk), - FUNCTION(gp1_clk), - FUNCTION(gp_mn), - FUNCTION(tsif1), - FUNCTION(tsif2), - FUNCTION(hsic), - FUNCTION(grfc), - FUNCTION(audio_ref_clk), - FUNCTION(bt), - FUNCTION(fm), - FUNCTION(wlan), - FUNCTION(slimbus), - FUNCTION(hsic_ctl), +static const struct pinfunction msm8x74_functions[] = { + MSM_PIN_FUNCTION(gpio), + MSM_PIN_FUNCTION(cci_i2c0), + MSM_PIN_FUNCTION(cci_i2c1), + MSM_PIN_FUNCTION(uim1), + MSM_PIN_FUNCTION(uim2), + MSM_PIN_FUNCTION(uim_batt_alarm), + MSM_PIN_FUNCTION(blsp_uim1), + MSM_PIN_FUNCTION(blsp_uim2), + MSM_PIN_FUNCTION(blsp_uim3), + MSM_PIN_FUNCTION(blsp_uim4), + MSM_PIN_FUNCTION(blsp_uim5), + MSM_PIN_FUNCTION(blsp_uim6), + MSM_PIN_FUNCTION(blsp_uim7), + MSM_PIN_FUNCTION(blsp_uim8), + MSM_PIN_FUNCTION(blsp_uim9), + MSM_PIN_FUNCTION(blsp_uim10), + MSM_PIN_FUNCTION(blsp_uim11), + MSM_PIN_FUNCTION(blsp_uim12), + MSM_PIN_FUNCTION(blsp_i2c1), + MSM_PIN_FUNCTION(blsp_i2c2), + MSM_PIN_FUNCTION(blsp_i2c3), + MSM_PIN_FUNCTION(blsp_i2c4), + MSM_PIN_FUNCTION(blsp_i2c5), + MSM_PIN_FUNCTION(blsp_i2c6), + MSM_PIN_FUNCTION(blsp_i2c7), + MSM_PIN_FUNCTION(blsp_i2c8), + MSM_PIN_FUNCTION(blsp_i2c9), + MSM_PIN_FUNCTION(blsp_i2c10), + MSM_PIN_FUNCTION(blsp_i2c11), + MSM_PIN_FUNCTION(blsp_i2c12), + MSM_PIN_FUNCTION(blsp_spi1), + MSM_PIN_FUNCTION(blsp_spi1_cs1), + MSM_PIN_FUNCTION(blsp_spi1_cs2), + MSM_PIN_FUNCTION(blsp_spi1_cs3), + MSM_PIN_FUNCTION(blsp_spi2), + MSM_PIN_FUNCTION(blsp_spi2_cs1), + MSM_PIN_FUNCTION(blsp_spi2_cs2), + MSM_PIN_FUNCTION(blsp_spi2_cs3), + MSM_PIN_FUNCTION(blsp_spi3), + MSM_PIN_FUNCTION(blsp_spi4), + MSM_PIN_FUNCTION(blsp_spi5), + MSM_PIN_FUNCTION(blsp_spi6), + MSM_PIN_FUNCTION(blsp_spi7), + MSM_PIN_FUNCTION(blsp_spi8), + MSM_PIN_FUNCTION(blsp_spi9), + MSM_PIN_FUNCTION(blsp_spi10), + MSM_PIN_FUNCTION(blsp_spi10_cs1), + MSM_PIN_FUNCTION(blsp_spi10_cs2), + MSM_PIN_FUNCTION(blsp_spi10_cs3), + MSM_PIN_FUNCTION(blsp_spi11), + MSM_PIN_FUNCTION(blsp_spi12), + MSM_PIN_FUNCTION(blsp_uart1), + MSM_PIN_FUNCTION(blsp_uart2), + MSM_PIN_FUNCTION(blsp_uart3), + MSM_PIN_FUNCTION(blsp_uart4), + MSM_PIN_FUNCTION(blsp_uart5), + MSM_PIN_FUNCTION(blsp_uart6), + MSM_PIN_FUNCTION(blsp_uart7), + MSM_PIN_FUNCTION(blsp_uart8), + MSM_PIN_FUNCTION(blsp_uart9), + MSM_PIN_FUNCTION(blsp_uart10), + MSM_PIN_FUNCTION(blsp_uart11), + MSM_PIN_FUNCTION(blsp_uart12), + MSM_PIN_FUNCTION(sdc3), + MSM_PIN_FUNCTION(sdc4), + MSM_PIN_FUNCTION(gcc_gp_clk1), + MSM_PIN_FUNCTION(gcc_gp_clk2), + MSM_PIN_FUNCTION(gcc_gp_clk3), + MSM_PIN_FUNCTION(qua_mi2s), + MSM_PIN_FUNCTION(pri_mi2s), + MSM_PIN_FUNCTION(spkr_mi2s), + MSM_PIN_FUNCTION(ter_mi2s), + MSM_PIN_FUNCTION(sec_mi2s), + MSM_PIN_FUNCTION(mdp_vsync), + MSM_PIN_FUNCTION(cam_mclk0), + MSM_PIN_FUNCTION(cam_mclk1), + MSM_PIN_FUNCTION(cam_mclk2), + MSM_PIN_FUNCTION(cam_mclk3), + MSM_PIN_FUNCTION(cci_timer0), + MSM_PIN_FUNCTION(cci_timer1), + MSM_PIN_FUNCTION(cci_timer2), + MSM_PIN_FUNCTION(cci_timer3), + MSM_PIN_FUNCTION(cci_timer4), + MSM_PIN_FUNCTION(cci_async_in0), + MSM_PIN_FUNCTION(cci_async_in1), + MSM_PIN_FUNCTION(cci_async_in2), + MSM_PIN_FUNCTION(hdmi_cec), + MSM_PIN_FUNCTION(hdmi_ddc), + MSM_PIN_FUNCTION(hdmi_hpd), + MSM_PIN_FUNCTION(edp_hpd), + MSM_PIN_FUNCTION(gp_pdm0), + MSM_PIN_FUNCTION(gp_pdm1), + MSM_PIN_FUNCTION(gp_pdm2), + MSM_PIN_FUNCTION(gp0_clk), + MSM_PIN_FUNCTION(gp1_clk), + MSM_PIN_FUNCTION(gp_mn), + MSM_PIN_FUNCTION(tsif1), + MSM_PIN_FUNCTION(tsif2), + MSM_PIN_FUNCTION(hsic), + MSM_PIN_FUNCTION(grfc), + MSM_PIN_FUNCTION(audio_ref_clk), + MSM_PIN_FUNCTION(bt), + MSM_PIN_FUNCTION(fm), + MSM_PIN_FUNCTION(wlan), + MSM_PIN_FUNCTION(slimbus), + MSM_PIN_FUNCTION(hsic_ctl), }; static const struct msm_pingroup msm8x74_groups[] = { diff --git a/drivers/pinctrl/qcom/pinctrl-qcm2290.c b/drivers/pinctrl/qcom/pinctrl-qcm2290.c index aa9325f333fba6c1d13b0f6fafcbe5d0a6d76048..ba699eac9ee8b2cb2172f3591a32709518eeb92e 100644 --- a/drivers/pinctrl/qcom/pinctrl-qcm2290.c +++ b/drivers/pinctrl/qcom/pinctrl-qcm2290.c @@ -6,24 +6,16 @@ #include #include #include -#include #include "pinctrl-msm.h" -#define FUNCTION(fname) \ - [msm_mux_##fname] = { \ - .name = #fname, \ - .groups = fname##_groups, \ - .ngroups = ARRAY_SIZE(fname##_groups), \ - } - #define REG_SIZE 0x1000 #define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9) \ { \ - .name = "gpio" #id, \ - .pins = gpio##id##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(gpio##id##_pins), \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ .funcs = (int[]){ \ msm_mux_gpio, /* gpio mode */ \ msm_mux_##f1, \ @@ -60,9 +52,9 @@ #define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = ctl, \ .io_reg = 0, \ .intr_cfg_reg = 0, \ @@ -85,9 +77,9 @@ #define UFS_RESET(pg_name, offset) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = offset, \ .io_reg = offset + 0x4, \ .intr_cfg_reg = 0, \ @@ -837,108 +829,108 @@ static const char * const pwm_9_groups[] = { "gpio115", }; -static const struct msm_function qcm2290_functions[] = { - FUNCTION(adsp_ext), - FUNCTION(agera_pll), - FUNCTION(atest), - FUNCTION(cam_mclk), - FUNCTION(cci_async), - FUNCTION(cci_i2c), - FUNCTION(cci_timer0), - FUNCTION(cci_timer1), - FUNCTION(cci_timer2), - FUNCTION(cci_timer3), - FUNCTION(char_exec), - FUNCTION(cri_trng), - FUNCTION(cri_trng0), - FUNCTION(cri_trng1), - FUNCTION(dac_calib), - FUNCTION(dbg_out), - FUNCTION(ddr_bist), - FUNCTION(ddr_pxi0), - FUNCTION(ddr_pxi1), - FUNCTION(ddr_pxi2), - FUNCTION(ddr_pxi3), - FUNCTION(gcc_gp1), - FUNCTION(gcc_gp2), - FUNCTION(gcc_gp3), - FUNCTION(gpio), - FUNCTION(gp_pdm0), - FUNCTION(gp_pdm1), - FUNCTION(gp_pdm2), - FUNCTION(gsm0_tx), - FUNCTION(gsm1_tx), - FUNCTION(jitter_bist), - FUNCTION(mdp_vsync), - FUNCTION(mdp_vsync_out_0), - FUNCTION(mdp_vsync_out_1), - FUNCTION(mpm_pwr), - FUNCTION(mss_lte), - FUNCTION(m_voc), - FUNCTION(nav_gpio), - FUNCTION(pa_indicator), - FUNCTION(pbs0), - FUNCTION(pbs1), - FUNCTION(pbs2), - FUNCTION(pbs3), - FUNCTION(pbs4), - FUNCTION(pbs5), - FUNCTION(pbs6), - FUNCTION(pbs7), - FUNCTION(pbs8), - FUNCTION(pbs9), - FUNCTION(pbs10), - FUNCTION(pbs11), - FUNCTION(pbs12), - FUNCTION(pbs13), - FUNCTION(pbs14), - FUNCTION(pbs15), - FUNCTION(pbs_out), - FUNCTION(phase_flag), - FUNCTION(pll_bist), - FUNCTION(pll_bypassnl), - FUNCTION(pll_reset), - FUNCTION(prng_rosc), - FUNCTION(pwm_0), - FUNCTION(pwm_1), - FUNCTION(pwm_2), - FUNCTION(pwm_3), - FUNCTION(pwm_4), - FUNCTION(pwm_5), - FUNCTION(pwm_6), - FUNCTION(pwm_7), - FUNCTION(pwm_8), - FUNCTION(pwm_9), - FUNCTION(qdss_cti), - FUNCTION(qdss_gpio), - FUNCTION(qup0), - FUNCTION(qup1), - FUNCTION(qup2), - FUNCTION(qup3), - FUNCTION(qup4), - FUNCTION(qup5), - FUNCTION(sdc1_tb), - FUNCTION(sdc2_tb), - FUNCTION(sd_write), - FUNCTION(ssbi_wtr1), - FUNCTION(tgu_ch0), - FUNCTION(tgu_ch1), - FUNCTION(tgu_ch2), - FUNCTION(tgu_ch3), - FUNCTION(tsense_pwm), - FUNCTION(uim1_clk), - FUNCTION(uim1_data), - FUNCTION(uim1_present), - FUNCTION(uim1_reset), - FUNCTION(uim2_clk), - FUNCTION(uim2_data), - FUNCTION(uim2_present), - FUNCTION(uim2_reset), - FUNCTION(usb_phy), - FUNCTION(vfr_1), - FUNCTION(vsense_trigger), - FUNCTION(wlan1_adc0), - FUNCTION(wlan1_adc1), +static const struct pinfunction qcm2290_functions[] = { + MSM_PIN_FUNCTION(adsp_ext), + MSM_PIN_FUNCTION(agera_pll), + MSM_PIN_FUNCTION(atest), + MSM_PIN_FUNCTION(cam_mclk), + MSM_PIN_FUNCTION(cci_async), + MSM_PIN_FUNCTION(cci_i2c), + MSM_PIN_FUNCTION(cci_timer0), + MSM_PIN_FUNCTION(cci_timer1), + MSM_PIN_FUNCTION(cci_timer2), + MSM_PIN_FUNCTION(cci_timer3), + MSM_PIN_FUNCTION(char_exec), + MSM_PIN_FUNCTION(cri_trng), + MSM_PIN_FUNCTION(cri_trng0), + MSM_PIN_FUNCTION(cri_trng1), + MSM_PIN_FUNCTION(dac_calib), + MSM_PIN_FUNCTION(dbg_out), + MSM_PIN_FUNCTION(ddr_bist), + MSM_PIN_FUNCTION(ddr_pxi0), + MSM_PIN_FUNCTION(ddr_pxi1), + MSM_PIN_FUNCTION(ddr_pxi2), + MSM_PIN_FUNCTION(ddr_pxi3), + MSM_PIN_FUNCTION(gcc_gp1), + MSM_PIN_FUNCTION(gcc_gp2), + MSM_PIN_FUNCTION(gcc_gp3), + MSM_PIN_FUNCTION(gpio), + MSM_PIN_FUNCTION(gp_pdm0), + MSM_PIN_FUNCTION(gp_pdm1), + MSM_PIN_FUNCTION(gp_pdm2), + MSM_PIN_FUNCTION(gsm0_tx), + MSM_PIN_FUNCTION(gsm1_tx), + MSM_PIN_FUNCTION(jitter_bist), + MSM_PIN_FUNCTION(mdp_vsync), + MSM_PIN_FUNCTION(mdp_vsync_out_0), + MSM_PIN_FUNCTION(mdp_vsync_out_1), + MSM_PIN_FUNCTION(mpm_pwr), + MSM_PIN_FUNCTION(mss_lte), + MSM_PIN_FUNCTION(m_voc), + MSM_PIN_FUNCTION(nav_gpio), + MSM_PIN_FUNCTION(pa_indicator), + MSM_PIN_FUNCTION(pbs0), + MSM_PIN_FUNCTION(pbs1), + MSM_PIN_FUNCTION(pbs2), + MSM_PIN_FUNCTION(pbs3), + MSM_PIN_FUNCTION(pbs4), + MSM_PIN_FUNCTION(pbs5), + MSM_PIN_FUNCTION(pbs6), + MSM_PIN_FUNCTION(pbs7), + MSM_PIN_FUNCTION(pbs8), + MSM_PIN_FUNCTION(pbs9), + MSM_PIN_FUNCTION(pbs10), + MSM_PIN_FUNCTION(pbs11), + MSM_PIN_FUNCTION(pbs12), + MSM_PIN_FUNCTION(pbs13), + MSM_PIN_FUNCTION(pbs14), + MSM_PIN_FUNCTION(pbs15), + MSM_PIN_FUNCTION(pbs_out), + MSM_PIN_FUNCTION(phase_flag), + MSM_PIN_FUNCTION(pll_bist), + MSM_PIN_FUNCTION(pll_bypassnl), + MSM_PIN_FUNCTION(pll_reset), + MSM_PIN_FUNCTION(prng_rosc), + MSM_PIN_FUNCTION(pwm_0), + MSM_PIN_FUNCTION(pwm_1), + MSM_PIN_FUNCTION(pwm_2), + MSM_PIN_FUNCTION(pwm_3), + MSM_PIN_FUNCTION(pwm_4), + MSM_PIN_FUNCTION(pwm_5), + MSM_PIN_FUNCTION(pwm_6), + MSM_PIN_FUNCTION(pwm_7), + MSM_PIN_FUNCTION(pwm_8), + MSM_PIN_FUNCTION(pwm_9), + MSM_PIN_FUNCTION(qdss_cti), + MSM_PIN_FUNCTION(qdss_gpio), + MSM_PIN_FUNCTION(qup0), + MSM_PIN_FUNCTION(qup1), + MSM_PIN_FUNCTION(qup2), + MSM_PIN_FUNCTION(qup3), + MSM_PIN_FUNCTION(qup4), + MSM_PIN_FUNCTION(qup5), + MSM_PIN_FUNCTION(sdc1_tb), + MSM_PIN_FUNCTION(sdc2_tb), + MSM_PIN_FUNCTION(sd_write), + MSM_PIN_FUNCTION(ssbi_wtr1), + MSM_PIN_FUNCTION(tgu_ch0), + MSM_PIN_FUNCTION(tgu_ch1), + MSM_PIN_FUNCTION(tgu_ch2), + MSM_PIN_FUNCTION(tgu_ch3), + MSM_PIN_FUNCTION(tsense_pwm), + MSM_PIN_FUNCTION(uim1_clk), + MSM_PIN_FUNCTION(uim1_data), + MSM_PIN_FUNCTION(uim1_present), + MSM_PIN_FUNCTION(uim1_reset), + MSM_PIN_FUNCTION(uim2_clk), + MSM_PIN_FUNCTION(uim2_data), + MSM_PIN_FUNCTION(uim2_present), + MSM_PIN_FUNCTION(uim2_reset), + MSM_PIN_FUNCTION(usb_phy), + MSM_PIN_FUNCTION(vfr_1), + MSM_PIN_FUNCTION(vsense_trigger), + MSM_PIN_FUNCTION(wlan1_adc0), + MSM_PIN_FUNCTION(wlan1_adc1), }; /* Every pin is maintained as a single group, and missing or non-existing pin diff --git a/drivers/pinctrl/qcom/pinctrl-qcs404.c b/drivers/pinctrl/qcom/pinctrl-qcs404.c index 1c6ba978c69f6f96375d4a0201da4df3ffa61dda..ae7224012f8aa00a41350b3ce670511aa8ce18bd 100644 --- a/drivers/pinctrl/qcom/pinctrl-qcs404.c +++ b/drivers/pinctrl/qcom/pinctrl-qcs404.c @@ -6,7 +6,6 @@ #include #include #include -#include #include "pinctrl-msm.h" @@ -22,18 +21,11 @@ enum { EAST }; -#define FUNCTION(fname) \ - [msm_mux_##fname] = { \ - .name = #fname, \ - .groups = fname##_groups, \ - .ngroups = ARRAY_SIZE(fname##_groups), \ - } - #define PINGROUP(id, _tile, f1, f2, f3, f4, f5, f6, f7, f8, f9) \ { \ - .name = "gpio" #id, \ - .pins = gpio##id##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(gpio##id##_pins), \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ .funcs = (int[]){ \ msm_mux_gpio, /* gpio mode */ \ msm_mux_##f1, \ @@ -71,9 +63,9 @@ enum { #define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = ctl, \ .io_reg = 0, \ .intr_cfg_reg = 0, \ @@ -1303,190 +1295,190 @@ static const char * const i2s_3_ws_a_groups[] = { "gpio105", }; -static const struct msm_function qcs404_functions[] = { - FUNCTION(gpio), - FUNCTION(hdmi_tx), - FUNCTION(hdmi_ddc), - FUNCTION(blsp_uart_tx_a2), - FUNCTION(blsp_spi2), - FUNCTION(m_voc), - FUNCTION(qdss_cti_trig_in_a0), - FUNCTION(blsp_uart_rx_a2), - FUNCTION(qdss_tracectl_a), - FUNCTION(blsp_uart2), - FUNCTION(aud_cdc), - FUNCTION(blsp_i2c_sda_a2), - FUNCTION(qdss_tracedata_a), - FUNCTION(blsp_i2c_scl_a2), - FUNCTION(qdss_tracectl_b), - FUNCTION(qdss_cti_trig_in_b0), - FUNCTION(blsp_uart1), - FUNCTION(blsp_spi_mosi_a1), - FUNCTION(blsp_spi_miso_a1), - FUNCTION(qdss_tracedata_b), - FUNCTION(blsp_i2c1), - FUNCTION(blsp_spi_cs_n_a1), - FUNCTION(gcc_plltest), - FUNCTION(blsp_spi_clk_a1), - FUNCTION(rgb_data0), - FUNCTION(blsp_uart5), - FUNCTION(blsp_spi5), - FUNCTION(adsp_ext), - FUNCTION(rgb_data1), - FUNCTION(prng_rosc), - FUNCTION(rgb_data2), - FUNCTION(blsp_i2c5), - FUNCTION(gcc_gp1_clk_b), - FUNCTION(rgb_data3), - FUNCTION(gcc_gp2_clk_b), - FUNCTION(blsp_spi0), - FUNCTION(blsp_uart0), - FUNCTION(gcc_gp3_clk_b), - FUNCTION(blsp_i2c0), - FUNCTION(qdss_traceclk_b), - FUNCTION(pcie_clk), - FUNCTION(nfc_irq), - FUNCTION(blsp_spi4), - FUNCTION(nfc_dwl), - FUNCTION(audio_ts), - FUNCTION(rgb_data4), - FUNCTION(spi_lcd), - FUNCTION(blsp_uart_tx_b2), - FUNCTION(gcc_gp3_clk_a), - FUNCTION(rgb_data5), - FUNCTION(blsp_uart_rx_b2), - FUNCTION(blsp_i2c_sda_b2), - FUNCTION(blsp_i2c_scl_b2), - FUNCTION(pwm_led11), - FUNCTION(i2s_3_data0_a), - FUNCTION(ebi2_lcd), - FUNCTION(i2s_3_data1_a), - FUNCTION(i2s_3_data2_a), - FUNCTION(atest_char), - FUNCTION(pwm_led3), - FUNCTION(i2s_3_data3_a), - FUNCTION(pwm_led4), - FUNCTION(i2s_4), - FUNCTION(ebi2_a), - FUNCTION(dsd_clk_b), - FUNCTION(pwm_led5), - FUNCTION(pwm_led6), - FUNCTION(pwm_led7), - FUNCTION(pwm_led8), - FUNCTION(pwm_led24), - FUNCTION(spkr_dac0), - FUNCTION(blsp_i2c4), - FUNCTION(pwm_led9), - FUNCTION(pwm_led10), - FUNCTION(spdifrx_opt), - FUNCTION(pwm_led12), - FUNCTION(pwm_led13), - FUNCTION(pwm_led14), - FUNCTION(wlan1_adc1), - FUNCTION(rgb_data_b0), - FUNCTION(pwm_led15), - FUNCTION(blsp_spi_mosi_b1), - FUNCTION(wlan1_adc0), - FUNCTION(rgb_data_b1), - FUNCTION(pwm_led16), - FUNCTION(blsp_spi_miso_b1), - FUNCTION(qdss_cti_trig_out_b0), - FUNCTION(wlan2_adc1), - FUNCTION(rgb_data_b2), - FUNCTION(pwm_led17), - FUNCTION(blsp_spi_cs_n_b1), - FUNCTION(wlan2_adc0), - FUNCTION(rgb_data_b3), - FUNCTION(pwm_led18), - FUNCTION(blsp_spi_clk_b1), - FUNCTION(rgb_data_b4), - FUNCTION(pwm_led19), - FUNCTION(ext_mclk1_b), - FUNCTION(qdss_traceclk_a), - FUNCTION(rgb_data_b5), - FUNCTION(pwm_led20), - FUNCTION(atest_char3), - FUNCTION(i2s_3_sck_b), - FUNCTION(ldo_update), - FUNCTION(bimc_dte0), - FUNCTION(rgb_hsync), - FUNCTION(pwm_led21), - FUNCTION(i2s_3_ws_b), - FUNCTION(dbg_out), - FUNCTION(rgb_vsync), - FUNCTION(i2s_3_data0_b), - FUNCTION(ldo_en), - FUNCTION(hdmi_dtest), - FUNCTION(rgb_de), - FUNCTION(i2s_3_data1_b), - FUNCTION(hdmi_lbk9), - FUNCTION(rgb_clk), - FUNCTION(atest_char1), - FUNCTION(i2s_3_data2_b), - FUNCTION(ebi_cdc), - FUNCTION(hdmi_lbk8), - FUNCTION(rgb_mdp), - FUNCTION(atest_char0), - FUNCTION(i2s_3_data3_b), - FUNCTION(hdmi_lbk7), - FUNCTION(rgb_data_b6), - FUNCTION(rgb_data_b7), - FUNCTION(hdmi_lbk6), - FUNCTION(rgmii_int), - FUNCTION(cri_trng1), - FUNCTION(rgmii_wol), - FUNCTION(cri_trng0), - FUNCTION(gcc_tlmm), - FUNCTION(rgmii_ck), - FUNCTION(rgmii_tx), - FUNCTION(hdmi_lbk5), - FUNCTION(hdmi_pixel), - FUNCTION(hdmi_rcv), - FUNCTION(hdmi_lbk4), - FUNCTION(rgmii_ctl), - FUNCTION(ext_lpass), - FUNCTION(rgmii_rx), - FUNCTION(cri_trng), - FUNCTION(hdmi_lbk3), - FUNCTION(hdmi_lbk2), - FUNCTION(qdss_cti_trig_out_b1), - FUNCTION(rgmii_mdio), - FUNCTION(hdmi_lbk1), - FUNCTION(rgmii_mdc), - FUNCTION(hdmi_lbk0), - FUNCTION(ir_in), - FUNCTION(wsa_en), - FUNCTION(rgb_data6), - FUNCTION(rgb_data7), - FUNCTION(atest_char2), - FUNCTION(ebi_ch0), - FUNCTION(blsp_uart3), - FUNCTION(blsp_spi3), - FUNCTION(sd_write), - FUNCTION(blsp_i2c3), - FUNCTION(gcc_gp1_clk_a), - FUNCTION(qdss_cti_trig_in_b1), - FUNCTION(gcc_gp2_clk_a), - FUNCTION(ext_mclk0), - FUNCTION(mclk_in1), - FUNCTION(i2s_1), - FUNCTION(dsd_clk_a), - FUNCTION(qdss_cti_trig_in_a1), - FUNCTION(rgmi_dll1), - FUNCTION(pwm_led22), - FUNCTION(pwm_led23), - FUNCTION(qdss_cti_trig_out_a0), - FUNCTION(rgmi_dll2), - FUNCTION(pwm_led1), - FUNCTION(qdss_cti_trig_out_a1), - FUNCTION(pwm_led2), - FUNCTION(i2s_2), - FUNCTION(pll_bist), - FUNCTION(ext_mclk1_a), - FUNCTION(mclk_in2), - FUNCTION(bimc_dte1), - FUNCTION(i2s_3_sck_a), - FUNCTION(i2s_3_ws_a), +static const struct pinfunction qcs404_functions[] = { + MSM_PIN_FUNCTION(gpio), + MSM_PIN_FUNCTION(hdmi_tx), + MSM_PIN_FUNCTION(hdmi_ddc), + MSM_PIN_FUNCTION(blsp_uart_tx_a2), + MSM_PIN_FUNCTION(blsp_spi2), + MSM_PIN_FUNCTION(m_voc), + MSM_PIN_FUNCTION(qdss_cti_trig_in_a0), + MSM_PIN_FUNCTION(blsp_uart_rx_a2), + MSM_PIN_FUNCTION(qdss_tracectl_a), + MSM_PIN_FUNCTION(blsp_uart2), + MSM_PIN_FUNCTION(aud_cdc), + MSM_PIN_FUNCTION(blsp_i2c_sda_a2), + MSM_PIN_FUNCTION(qdss_tracedata_a), + MSM_PIN_FUNCTION(blsp_i2c_scl_a2), + MSM_PIN_FUNCTION(qdss_tracectl_b), + MSM_PIN_FUNCTION(qdss_cti_trig_in_b0), + MSM_PIN_FUNCTION(blsp_uart1), + MSM_PIN_FUNCTION(blsp_spi_mosi_a1), + MSM_PIN_FUNCTION(blsp_spi_miso_a1), + MSM_PIN_FUNCTION(qdss_tracedata_b), + MSM_PIN_FUNCTION(blsp_i2c1), + MSM_PIN_FUNCTION(blsp_spi_cs_n_a1), + MSM_PIN_FUNCTION(gcc_plltest), + MSM_PIN_FUNCTION(blsp_spi_clk_a1), + MSM_PIN_FUNCTION(rgb_data0), + MSM_PIN_FUNCTION(blsp_uart5), + MSM_PIN_FUNCTION(blsp_spi5), + MSM_PIN_FUNCTION(adsp_ext), + MSM_PIN_FUNCTION(rgb_data1), + MSM_PIN_FUNCTION(prng_rosc), + MSM_PIN_FUNCTION(rgb_data2), + MSM_PIN_FUNCTION(blsp_i2c5), + MSM_PIN_FUNCTION(gcc_gp1_clk_b), + MSM_PIN_FUNCTION(rgb_data3), + MSM_PIN_FUNCTION(gcc_gp2_clk_b), + MSM_PIN_FUNCTION(blsp_spi0), + MSM_PIN_FUNCTION(blsp_uart0), + MSM_PIN_FUNCTION(gcc_gp3_clk_b), + MSM_PIN_FUNCTION(blsp_i2c0), + MSM_PIN_FUNCTION(qdss_traceclk_b), + MSM_PIN_FUNCTION(pcie_clk), + MSM_PIN_FUNCTION(nfc_irq), + MSM_PIN_FUNCTION(blsp_spi4), + MSM_PIN_FUNCTION(nfc_dwl), + MSM_PIN_FUNCTION(audio_ts), + MSM_PIN_FUNCTION(rgb_data4), + MSM_PIN_FUNCTION(spi_lcd), + MSM_PIN_FUNCTION(blsp_uart_tx_b2), + MSM_PIN_FUNCTION(gcc_gp3_clk_a), + MSM_PIN_FUNCTION(rgb_data5), + MSM_PIN_FUNCTION(blsp_uart_rx_b2), + MSM_PIN_FUNCTION(blsp_i2c_sda_b2), + MSM_PIN_FUNCTION(blsp_i2c_scl_b2), + MSM_PIN_FUNCTION(pwm_led11), + MSM_PIN_FUNCTION(i2s_3_data0_a), + MSM_PIN_FUNCTION(ebi2_lcd), + MSM_PIN_FUNCTION(i2s_3_data1_a), + MSM_PIN_FUNCTION(i2s_3_data2_a), + MSM_PIN_FUNCTION(atest_char), + MSM_PIN_FUNCTION(pwm_led3), + MSM_PIN_FUNCTION(i2s_3_data3_a), + MSM_PIN_FUNCTION(pwm_led4), + MSM_PIN_FUNCTION(i2s_4), + MSM_PIN_FUNCTION(ebi2_a), + MSM_PIN_FUNCTION(dsd_clk_b), + MSM_PIN_FUNCTION(pwm_led5), + MSM_PIN_FUNCTION(pwm_led6), + MSM_PIN_FUNCTION(pwm_led7), + MSM_PIN_FUNCTION(pwm_led8), + MSM_PIN_FUNCTION(pwm_led24), + MSM_PIN_FUNCTION(spkr_dac0), + MSM_PIN_FUNCTION(blsp_i2c4), + MSM_PIN_FUNCTION(pwm_led9), + MSM_PIN_FUNCTION(pwm_led10), + MSM_PIN_FUNCTION(spdifrx_opt), + MSM_PIN_FUNCTION(pwm_led12), + MSM_PIN_FUNCTION(pwm_led13), + MSM_PIN_FUNCTION(pwm_led14), + MSM_PIN_FUNCTION(wlan1_adc1), + MSM_PIN_FUNCTION(rgb_data_b0), + MSM_PIN_FUNCTION(pwm_led15), + MSM_PIN_FUNCTION(blsp_spi_mosi_b1), + MSM_PIN_FUNCTION(wlan1_adc0), + MSM_PIN_FUNCTION(rgb_data_b1), + MSM_PIN_FUNCTION(pwm_led16), + MSM_PIN_FUNCTION(blsp_spi_miso_b1), + MSM_PIN_FUNCTION(qdss_cti_trig_out_b0), + MSM_PIN_FUNCTION(wlan2_adc1), + MSM_PIN_FUNCTION(rgb_data_b2), + MSM_PIN_FUNCTION(pwm_led17), + MSM_PIN_FUNCTION(blsp_spi_cs_n_b1), + MSM_PIN_FUNCTION(wlan2_adc0), + MSM_PIN_FUNCTION(rgb_data_b3), + MSM_PIN_FUNCTION(pwm_led18), + MSM_PIN_FUNCTION(blsp_spi_clk_b1), + MSM_PIN_FUNCTION(rgb_data_b4), + MSM_PIN_FUNCTION(pwm_led19), + MSM_PIN_FUNCTION(ext_mclk1_b), + MSM_PIN_FUNCTION(qdss_traceclk_a), + MSM_PIN_FUNCTION(rgb_data_b5), + MSM_PIN_FUNCTION(pwm_led20), + MSM_PIN_FUNCTION(atest_char3), + MSM_PIN_FUNCTION(i2s_3_sck_b), + MSM_PIN_FUNCTION(ldo_update), + MSM_PIN_FUNCTION(bimc_dte0), + MSM_PIN_FUNCTION(rgb_hsync), + MSM_PIN_FUNCTION(pwm_led21), + MSM_PIN_FUNCTION(i2s_3_ws_b), + MSM_PIN_FUNCTION(dbg_out), + MSM_PIN_FUNCTION(rgb_vsync), + MSM_PIN_FUNCTION(i2s_3_data0_b), + MSM_PIN_FUNCTION(ldo_en), + MSM_PIN_FUNCTION(hdmi_dtest), + MSM_PIN_FUNCTION(rgb_de), + MSM_PIN_FUNCTION(i2s_3_data1_b), + MSM_PIN_FUNCTION(hdmi_lbk9), + MSM_PIN_FUNCTION(rgb_clk), + MSM_PIN_FUNCTION(atest_char1), + MSM_PIN_FUNCTION(i2s_3_data2_b), + MSM_PIN_FUNCTION(ebi_cdc), + MSM_PIN_FUNCTION(hdmi_lbk8), + MSM_PIN_FUNCTION(rgb_mdp), + MSM_PIN_FUNCTION(atest_char0), + MSM_PIN_FUNCTION(i2s_3_data3_b), + MSM_PIN_FUNCTION(hdmi_lbk7), + MSM_PIN_FUNCTION(rgb_data_b6), + MSM_PIN_FUNCTION(rgb_data_b7), + MSM_PIN_FUNCTION(hdmi_lbk6), + MSM_PIN_FUNCTION(rgmii_int), + MSM_PIN_FUNCTION(cri_trng1), + MSM_PIN_FUNCTION(rgmii_wol), + MSM_PIN_FUNCTION(cri_trng0), + MSM_PIN_FUNCTION(gcc_tlmm), + MSM_PIN_FUNCTION(rgmii_ck), + MSM_PIN_FUNCTION(rgmii_tx), + MSM_PIN_FUNCTION(hdmi_lbk5), + MSM_PIN_FUNCTION(hdmi_pixel), + MSM_PIN_FUNCTION(hdmi_rcv), + MSM_PIN_FUNCTION(hdmi_lbk4), + MSM_PIN_FUNCTION(rgmii_ctl), + MSM_PIN_FUNCTION(ext_lpass), + MSM_PIN_FUNCTION(rgmii_rx), + MSM_PIN_FUNCTION(cri_trng), + MSM_PIN_FUNCTION(hdmi_lbk3), + MSM_PIN_FUNCTION(hdmi_lbk2), + MSM_PIN_FUNCTION(qdss_cti_trig_out_b1), + MSM_PIN_FUNCTION(rgmii_mdio), + MSM_PIN_FUNCTION(hdmi_lbk1), + MSM_PIN_FUNCTION(rgmii_mdc), + MSM_PIN_FUNCTION(hdmi_lbk0), + MSM_PIN_FUNCTION(ir_in), + MSM_PIN_FUNCTION(wsa_en), + MSM_PIN_FUNCTION(rgb_data6), + MSM_PIN_FUNCTION(rgb_data7), + MSM_PIN_FUNCTION(atest_char2), + MSM_PIN_FUNCTION(ebi_ch0), + MSM_PIN_FUNCTION(blsp_uart3), + MSM_PIN_FUNCTION(blsp_spi3), + MSM_PIN_FUNCTION(sd_write), + MSM_PIN_FUNCTION(blsp_i2c3), + MSM_PIN_FUNCTION(gcc_gp1_clk_a), + MSM_PIN_FUNCTION(qdss_cti_trig_in_b1), + MSM_PIN_FUNCTION(gcc_gp2_clk_a), + MSM_PIN_FUNCTION(ext_mclk0), + MSM_PIN_FUNCTION(mclk_in1), + MSM_PIN_FUNCTION(i2s_1), + MSM_PIN_FUNCTION(dsd_clk_a), + MSM_PIN_FUNCTION(qdss_cti_trig_in_a1), + MSM_PIN_FUNCTION(rgmi_dll1), + MSM_PIN_FUNCTION(pwm_led22), + MSM_PIN_FUNCTION(pwm_led23), + MSM_PIN_FUNCTION(qdss_cti_trig_out_a0), + MSM_PIN_FUNCTION(rgmi_dll2), + MSM_PIN_FUNCTION(pwm_led1), + MSM_PIN_FUNCTION(qdss_cti_trig_out_a1), + MSM_PIN_FUNCTION(pwm_led2), + MSM_PIN_FUNCTION(i2s_2), + MSM_PIN_FUNCTION(pll_bist), + MSM_PIN_FUNCTION(ext_mclk1_a), + MSM_PIN_FUNCTION(mclk_in2), + MSM_PIN_FUNCTION(bimc_dte1), + MSM_PIN_FUNCTION(i2s_3_sck_a), + MSM_PIN_FUNCTION(i2s_3_ws_a), }; /* Every pin is maintained as a single group, and missing or non-existing pin diff --git a/drivers/pinctrl/qcom/pinctrl-qdf2xxx.c b/drivers/pinctrl/qcom/pinctrl-qdf2xxx.c index 43bd15f16377d5717dba03afa5009f41cfc85b70..b5808fcfb13cdebd04c0c71b24043b924094a683 100644 --- a/drivers/pinctrl/qcom/pinctrl-qdf2xxx.c +++ b/drivers/pinctrl/qcom/pinctrl-qdf2xxx.c @@ -90,17 +90,17 @@ static int qdf2xxx_pinctrl_probe(struct platform_device *pdev) */ for (i = 0; i < num_gpios; i++) { pins[i].number = i; - groups[i].pins = &pins[i].number; + groups[i].grp.pins = &pins[i].number; } /* Populate the entries that are meant to be exposed as GPIOs. */ for (i = 0; i < avail_gpios; i++) { unsigned int gpio = gpios[i]; - groups[gpio].npins = 1; + groups[gpio].grp.npins = 1; snprintf(names[i], NAME_SIZE, "gpio%u", gpio); pins[gpio].name = names[i]; - groups[gpio].name = names[i]; + groups[gpio].grp.name = names[i]; groups[gpio].ctl_reg = 0x10000 * gpio; groups[gpio].io_reg = 0x04 + 0x10000 * gpio; @@ -142,7 +142,7 @@ MODULE_DEVICE_TABLE(acpi, qdf2xxx_acpi_ids); static struct platform_driver qdf2xxx_pinctrl_driver = { .driver = { .name = "qdf2xxx-pinctrl", - .acpi_match_table = ACPI_PTR(qdf2xxx_acpi_ids), + .acpi_match_table = qdf2xxx_acpi_ids, }, .probe = qdf2xxx_pinctrl_probe, .remove = msm_pinctrl_remove, diff --git a/drivers/pinctrl/qcom/pinctrl-qdu1000.c b/drivers/pinctrl/qcom/pinctrl-qdu1000.c index b1d7674a2bec6deb09084b1ea7a0980251deebf9..47bc529ef550d2ab9a13341295eacc08faed24c4 100644 --- a/drivers/pinctrl/qcom/pinctrl-qdu1000.c +++ b/drivers/pinctrl/qcom/pinctrl-qdu1000.c @@ -7,24 +7,17 @@ #include #include #include -#include #include "pinctrl-msm.h" -#define FUNCTION(fname) \ - [msm_mux_##fname] = { \ - .name = #fname, \ - .groups = fname##_groups, \ - .ngroups = ARRAY_SIZE(fname##_groups), \ - } - #define REG_BASE 0x100000 #define REG_SIZE 0x1000 + #define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9) \ { \ - .name = "gpio" #id, \ - .pins = gpio##id##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(gpio##id##_pins), \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ .funcs = (int[]){ \ msm_mux_gpio, /* gpio mode */ \ msm_mux_##f1, \ @@ -61,9 +54,9 @@ #define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = REG_BASE + ctl, \ .io_reg = 0, \ .intr_cfg_reg = 0, \ @@ -86,9 +79,9 @@ #define UFS_RESET(pg_name, offset) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = offset, \ .io_reg = offset + 0x4, \ .intr_cfg_reg = 0, \ @@ -910,117 +903,117 @@ static const char * const vsense_trigger_groups[] = { "gpio135", }; -static const struct msm_function qdu1000_functions[] = { - FUNCTION(gpio), - FUNCTION(cmo_pri), - FUNCTION(si5518_int), - FUNCTION(atest_char), - FUNCTION(atest_usb), - FUNCTION(char_exec), - FUNCTION(cmu_rng), - FUNCTION(dbg_out_clk), - FUNCTION(ddr_bist), - FUNCTION(ddr_pxi0), - FUNCTION(ddr_pxi1), - FUNCTION(ddr_pxi2), - FUNCTION(ddr_pxi3), - FUNCTION(ddr_pxi4), - FUNCTION(ddr_pxi5), - FUNCTION(ddr_pxi6), - FUNCTION(ddr_pxi7), - FUNCTION(eth012_int_n), - FUNCTION(eth345_int_n), - FUNCTION(eth6_int_n), - FUNCTION(gcc_gp1), - FUNCTION(gcc_gp2), - FUNCTION(gcc_gp3), - FUNCTION(gps_pps_in), - FUNCTION(hardsync_pps_in), - FUNCTION(intr_c), - FUNCTION(jitter_bist_ref), - FUNCTION(pcie_clkreqn), - FUNCTION(phase_flag), - FUNCTION(pll_bist), - FUNCTION(pll_clk), - FUNCTION(prng_rosc), - FUNCTION(qdss_cti), - FUNCTION(qdss_gpio), - FUNCTION(qlink0_enable), - FUNCTION(qlink0_request), - FUNCTION(qlink0_wmss), - FUNCTION(qlink1_enable), - FUNCTION(qlink1_request), - FUNCTION(qlink1_wmss), - FUNCTION(qlink2_enable), - FUNCTION(qlink2_request), - FUNCTION(qlink2_wmss), - FUNCTION(qlink3_enable), - FUNCTION(qlink3_request), - FUNCTION(qlink3_wmss), - FUNCTION(qlink4_enable), - FUNCTION(qlink4_request), - FUNCTION(qlink4_wmss), - FUNCTION(qlink5_enable), - FUNCTION(qlink5_request), - FUNCTION(qlink5_wmss), - FUNCTION(qlink6_enable), - FUNCTION(qlink6_request), - FUNCTION(qlink6_wmss), - FUNCTION(qlink7_enable), - FUNCTION(qlink7_request), - FUNCTION(qlink7_wmss), - FUNCTION(qspi0), - FUNCTION(qspi1), - FUNCTION(qspi2), - FUNCTION(qspi3), - FUNCTION(qspi_clk), - FUNCTION(qspi_cs), - FUNCTION(qup00), - FUNCTION(qup01), - FUNCTION(qup02), - FUNCTION(qup03), - FUNCTION(qup04), - FUNCTION(qup05), - FUNCTION(qup06), - FUNCTION(qup07), - FUNCTION(qup08), - FUNCTION(qup10), - FUNCTION(qup11), - FUNCTION(qup12), - FUNCTION(qup13), - FUNCTION(qup14), - FUNCTION(qup15), - FUNCTION(qup16), - FUNCTION(qup17), - FUNCTION(qup20), - FUNCTION(qup21), - FUNCTION(qup22), - FUNCTION(smb_alert), - FUNCTION(smb_clk), - FUNCTION(smb_dat), - FUNCTION(tb_trig), - FUNCTION(tgu_ch0), - FUNCTION(tgu_ch1), - FUNCTION(tgu_ch2), - FUNCTION(tgu_ch3), - FUNCTION(tgu_ch4), - FUNCTION(tgu_ch5), - FUNCTION(tgu_ch6), - FUNCTION(tgu_ch7), - FUNCTION(tmess_prng0), - FUNCTION(tmess_prng1), - FUNCTION(tmess_prng2), - FUNCTION(tmess_prng3), - FUNCTION(tod_pps_in), - FUNCTION(tsense_pwm1), - FUNCTION(tsense_pwm2), - FUNCTION(usb2phy_ac), - FUNCTION(usb_con_det), - FUNCTION(usb_dfp_en), - FUNCTION(usb_phy), - FUNCTION(vfr_0), - FUNCTION(vfr_1), - FUNCTION(vsense_trigger), +static const struct pinfunction qdu1000_functions[] = { + MSM_PIN_FUNCTION(gpio), + MSM_PIN_FUNCTION(cmo_pri), + MSM_PIN_FUNCTION(si5518_int), + MSM_PIN_FUNCTION(atest_char), + MSM_PIN_FUNCTION(atest_usb), + MSM_PIN_FUNCTION(char_exec), + MSM_PIN_FUNCTION(cmu_rng), + MSM_PIN_FUNCTION(dbg_out_clk), + MSM_PIN_FUNCTION(ddr_bist), + MSM_PIN_FUNCTION(ddr_pxi0), + MSM_PIN_FUNCTION(ddr_pxi1), + MSM_PIN_FUNCTION(ddr_pxi2), + MSM_PIN_FUNCTION(ddr_pxi3), + MSM_PIN_FUNCTION(ddr_pxi4), + MSM_PIN_FUNCTION(ddr_pxi5), + MSM_PIN_FUNCTION(ddr_pxi6), + MSM_PIN_FUNCTION(ddr_pxi7), + MSM_PIN_FUNCTION(eth012_int_n), + MSM_PIN_FUNCTION(eth345_int_n), + MSM_PIN_FUNCTION(eth6_int_n), + MSM_PIN_FUNCTION(gcc_gp1), + MSM_PIN_FUNCTION(gcc_gp2), + MSM_PIN_FUNCTION(gcc_gp3), + MSM_PIN_FUNCTION(gps_pps_in), + MSM_PIN_FUNCTION(hardsync_pps_in), + MSM_PIN_FUNCTION(intr_c), + MSM_PIN_FUNCTION(jitter_bist_ref), + MSM_PIN_FUNCTION(pcie_clkreqn), + MSM_PIN_FUNCTION(phase_flag), + MSM_PIN_FUNCTION(pll_bist), + MSM_PIN_FUNCTION(pll_clk), + MSM_PIN_FUNCTION(prng_rosc), + MSM_PIN_FUNCTION(qdss_cti), + MSM_PIN_FUNCTION(qdss_gpio), + MSM_PIN_FUNCTION(qlink0_enable), + MSM_PIN_FUNCTION(qlink0_request), + MSM_PIN_FUNCTION(qlink0_wmss), + MSM_PIN_FUNCTION(qlink1_enable), + MSM_PIN_FUNCTION(qlink1_request), + MSM_PIN_FUNCTION(qlink1_wmss), + MSM_PIN_FUNCTION(qlink2_enable), + MSM_PIN_FUNCTION(qlink2_request), + MSM_PIN_FUNCTION(qlink2_wmss), + MSM_PIN_FUNCTION(qlink3_enable), + MSM_PIN_FUNCTION(qlink3_request), + MSM_PIN_FUNCTION(qlink3_wmss), + MSM_PIN_FUNCTION(qlink4_enable), + MSM_PIN_FUNCTION(qlink4_request), + MSM_PIN_FUNCTION(qlink4_wmss), + MSM_PIN_FUNCTION(qlink5_enable), + MSM_PIN_FUNCTION(qlink5_request), + MSM_PIN_FUNCTION(qlink5_wmss), + MSM_PIN_FUNCTION(qlink6_enable), + MSM_PIN_FUNCTION(qlink6_request), + MSM_PIN_FUNCTION(qlink6_wmss), + MSM_PIN_FUNCTION(qlink7_enable), + MSM_PIN_FUNCTION(qlink7_request), + MSM_PIN_FUNCTION(qlink7_wmss), + MSM_PIN_FUNCTION(qspi0), + MSM_PIN_FUNCTION(qspi1), + MSM_PIN_FUNCTION(qspi2), + MSM_PIN_FUNCTION(qspi3), + MSM_PIN_FUNCTION(qspi_clk), + MSM_PIN_FUNCTION(qspi_cs), + MSM_PIN_FUNCTION(qup00), + MSM_PIN_FUNCTION(qup01), + MSM_PIN_FUNCTION(qup02), + MSM_PIN_FUNCTION(qup03), + MSM_PIN_FUNCTION(qup04), + MSM_PIN_FUNCTION(qup05), + MSM_PIN_FUNCTION(qup06), + MSM_PIN_FUNCTION(qup07), + MSM_PIN_FUNCTION(qup08), + MSM_PIN_FUNCTION(qup10), + MSM_PIN_FUNCTION(qup11), + MSM_PIN_FUNCTION(qup12), + MSM_PIN_FUNCTION(qup13), + MSM_PIN_FUNCTION(qup14), + MSM_PIN_FUNCTION(qup15), + MSM_PIN_FUNCTION(qup16), + MSM_PIN_FUNCTION(qup17), + MSM_PIN_FUNCTION(qup20), + MSM_PIN_FUNCTION(qup21), + MSM_PIN_FUNCTION(qup22), + MSM_PIN_FUNCTION(smb_alert), + MSM_PIN_FUNCTION(smb_clk), + MSM_PIN_FUNCTION(smb_dat), + MSM_PIN_FUNCTION(tb_trig), + MSM_PIN_FUNCTION(tgu_ch0), + MSM_PIN_FUNCTION(tgu_ch1), + MSM_PIN_FUNCTION(tgu_ch2), + MSM_PIN_FUNCTION(tgu_ch3), + MSM_PIN_FUNCTION(tgu_ch4), + MSM_PIN_FUNCTION(tgu_ch5), + MSM_PIN_FUNCTION(tgu_ch6), + MSM_PIN_FUNCTION(tgu_ch7), + MSM_PIN_FUNCTION(tmess_prng0), + MSM_PIN_FUNCTION(tmess_prng1), + MSM_PIN_FUNCTION(tmess_prng2), + MSM_PIN_FUNCTION(tmess_prng3), + MSM_PIN_FUNCTION(tod_pps_in), + MSM_PIN_FUNCTION(tsense_pwm1), + MSM_PIN_FUNCTION(tsense_pwm2), + MSM_PIN_FUNCTION(usb2phy_ac), + MSM_PIN_FUNCTION(usb_con_det), + MSM_PIN_FUNCTION(usb_dfp_en), + MSM_PIN_FUNCTION(usb_phy), + MSM_PIN_FUNCTION(vfr_0), + MSM_PIN_FUNCTION(vfr_1), + MSM_PIN_FUNCTION(vsense_trigger), }; /* diff --git a/drivers/pinctrl/qcom/pinctrl-sa8775p.c b/drivers/pinctrl/qcom/pinctrl-sa8775p.c index 2ae7cdca65d3e8b7f72205e8a19df03306356e30..8a5cd15512b971bc1d08c344fb0d5110906c46fc 100644 --- a/drivers/pinctrl/qcom/pinctrl-sa8775p.c +++ b/drivers/pinctrl/qcom/pinctrl-sa8775p.c @@ -7,24 +7,16 @@ #include #include #include -#include #include "pinctrl-msm.h" -#define FUNCTION(fname) \ - [msm_mux_##fname] = { \ - .name = #fname, \ - .groups = fname##_groups, \ - .ngroups = ARRAY_SIZE(fname##_groups), \ - } - #define REG_BASE 0x100000 #define REG_SIZE 0x1000 #define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9)\ { \ - .name = "gpio" #id, \ - .pins = gpio##id##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(gpio##id##_pins), \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ .funcs = (int[]){ \ msm_mux_gpio, /* gpio mode */ \ msm_mux_##f1, \ @@ -63,9 +55,9 @@ #define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = ctl, \ .io_reg = 0, \ .intr_cfg_reg = 0, \ @@ -88,9 +80,9 @@ #define UFS_RESET(pg_name, offset) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = offset, \ .io_reg = offset + 0x4, \ .intr_cfg_reg = 0, \ @@ -1179,147 +1171,147 @@ static const char * const vsense_trigger_groups[] = { "gpio111", }; -static const struct msm_function sa8775p_functions[] = { - FUNCTION(gpio), - FUNCTION(atest_char), - FUNCTION(atest_usb2), - FUNCTION(audio_ref), - FUNCTION(cam_mclk), - FUNCTION(cci_async), - FUNCTION(cci_i2c), - FUNCTION(cci_timer0), - FUNCTION(cci_timer1), - FUNCTION(cci_timer2), - FUNCTION(cci_timer3), - FUNCTION(cci_timer4), - FUNCTION(cci_timer5), - FUNCTION(cci_timer6), - FUNCTION(cci_timer7), - FUNCTION(cci_timer8), - FUNCTION(cci_timer9), - FUNCTION(cri_trng), - FUNCTION(cri_trng0), - FUNCTION(cri_trng1), - FUNCTION(dbg_out), - FUNCTION(ddr_bist), - FUNCTION(ddr_pxi0), - FUNCTION(ddr_pxi1), - FUNCTION(ddr_pxi2), - FUNCTION(ddr_pxi3), - FUNCTION(ddr_pxi4), - FUNCTION(ddr_pxi5), - FUNCTION(edp0_hot), - FUNCTION(edp0_lcd), - FUNCTION(edp1_hot), - FUNCTION(edp1_lcd), - FUNCTION(edp2_hot), - FUNCTION(edp2_lcd), - FUNCTION(edp3_hot), - FUNCTION(edp3_lcd), - FUNCTION(emac0_mcg0), - FUNCTION(emac0_mcg1), - FUNCTION(emac0_mcg2), - FUNCTION(emac0_mcg3), - FUNCTION(emac0_mdc), - FUNCTION(emac0_mdio), - FUNCTION(emac0_ptp_aux), - FUNCTION(emac0_ptp_pps), - FUNCTION(emac1_mcg0), - FUNCTION(emac1_mcg1), - FUNCTION(emac1_mcg2), - FUNCTION(emac1_mcg3), - FUNCTION(emac1_mdc), - FUNCTION(emac1_mdio), - FUNCTION(emac1_ptp_aux), - FUNCTION(emac1_ptp_pps), - FUNCTION(gcc_gp1), - FUNCTION(gcc_gp2), - FUNCTION(gcc_gp3), - FUNCTION(gcc_gp4), - FUNCTION(gcc_gp5), - FUNCTION(hs0_mi2s), - FUNCTION(hs1_mi2s), - FUNCTION(hs2_mi2s), - FUNCTION(ibi_i3c), - FUNCTION(jitter_bist), - FUNCTION(mdp0_vsync0), - FUNCTION(mdp0_vsync1), - FUNCTION(mdp0_vsync2), - FUNCTION(mdp0_vsync3), - FUNCTION(mdp0_vsync4), - FUNCTION(mdp0_vsync5), - FUNCTION(mdp0_vsync6), - FUNCTION(mdp0_vsync7), - FUNCTION(mdp0_vsync8), - FUNCTION(mdp1_vsync0), - FUNCTION(mdp1_vsync1), - FUNCTION(mdp1_vsync2), - FUNCTION(mdp1_vsync3), - FUNCTION(mdp1_vsync4), - FUNCTION(mdp1_vsync5), - FUNCTION(mdp1_vsync6), - FUNCTION(mdp1_vsync7), - FUNCTION(mdp1_vsync8), - FUNCTION(mdp_vsync), - FUNCTION(mi2s1_data0), - FUNCTION(mi2s1_data1), - FUNCTION(mi2s1_sck), - FUNCTION(mi2s1_ws), - FUNCTION(mi2s2_data0), - FUNCTION(mi2s2_data1), - FUNCTION(mi2s2_sck), - FUNCTION(mi2s2_ws), - FUNCTION(mi2s_mclk0), - FUNCTION(mi2s_mclk1), - FUNCTION(pcie0_clkreq), - FUNCTION(pcie1_clkreq), - FUNCTION(phase_flag), - FUNCTION(pll_bist), - FUNCTION(pll_clk), - FUNCTION(prng_rosc0), - FUNCTION(prng_rosc1), - FUNCTION(prng_rosc2), - FUNCTION(prng_rosc3), - FUNCTION(qdss_cti), - FUNCTION(qdss_gpio), - FUNCTION(qup0_se0), - FUNCTION(qup0_se1), - FUNCTION(qup0_se2), - FUNCTION(qup0_se3), - FUNCTION(qup0_se4), - FUNCTION(qup0_se5), - FUNCTION(qup1_se0), - FUNCTION(qup1_se1), - FUNCTION(qup1_se2), - FUNCTION(qup1_se3), - FUNCTION(qup1_se4), - FUNCTION(qup1_se5), - FUNCTION(qup1_se6), - FUNCTION(qup2_se0), - FUNCTION(qup2_se1), - FUNCTION(qup2_se2), - FUNCTION(qup2_se3), - FUNCTION(qup2_se4), - FUNCTION(qup2_se5), - FUNCTION(qup2_se6), - FUNCTION(qup3_se0), - FUNCTION(sail_top), - FUNCTION(sailss_emac0), - FUNCTION(sailss_ospi), - FUNCTION(sgmii_phy), - FUNCTION(tb_trig), - FUNCTION(tgu_ch0), - FUNCTION(tgu_ch1), - FUNCTION(tgu_ch2), - FUNCTION(tgu_ch3), - FUNCTION(tgu_ch4), - FUNCTION(tgu_ch5), - FUNCTION(tsense_pwm1), - FUNCTION(tsense_pwm2), - FUNCTION(tsense_pwm3), - FUNCTION(tsense_pwm4), - FUNCTION(usb2phy_ac), - FUNCTION(vsense_trigger), +static const struct pinfunction sa8775p_functions[] = { + MSM_PIN_FUNCTION(gpio), + MSM_PIN_FUNCTION(atest_char), + MSM_PIN_FUNCTION(atest_usb2), + MSM_PIN_FUNCTION(audio_ref), + MSM_PIN_FUNCTION(cam_mclk), + MSM_PIN_FUNCTION(cci_async), + MSM_PIN_FUNCTION(cci_i2c), + MSM_PIN_FUNCTION(cci_timer0), + MSM_PIN_FUNCTION(cci_timer1), + MSM_PIN_FUNCTION(cci_timer2), + MSM_PIN_FUNCTION(cci_timer3), + MSM_PIN_FUNCTION(cci_timer4), + MSM_PIN_FUNCTION(cci_timer5), + MSM_PIN_FUNCTION(cci_timer6), + MSM_PIN_FUNCTION(cci_timer7), + MSM_PIN_FUNCTION(cci_timer8), + MSM_PIN_FUNCTION(cci_timer9), + MSM_PIN_FUNCTION(cri_trng), + MSM_PIN_FUNCTION(cri_trng0), + MSM_PIN_FUNCTION(cri_trng1), + MSM_PIN_FUNCTION(dbg_out), + MSM_PIN_FUNCTION(ddr_bist), + MSM_PIN_FUNCTION(ddr_pxi0), + MSM_PIN_FUNCTION(ddr_pxi1), + MSM_PIN_FUNCTION(ddr_pxi2), + MSM_PIN_FUNCTION(ddr_pxi3), + MSM_PIN_FUNCTION(ddr_pxi4), + MSM_PIN_FUNCTION(ddr_pxi5), + MSM_PIN_FUNCTION(edp0_hot), + MSM_PIN_FUNCTION(edp0_lcd), + MSM_PIN_FUNCTION(edp1_hot), + MSM_PIN_FUNCTION(edp1_lcd), + MSM_PIN_FUNCTION(edp2_hot), + MSM_PIN_FUNCTION(edp2_lcd), + MSM_PIN_FUNCTION(edp3_hot), + MSM_PIN_FUNCTION(edp3_lcd), + MSM_PIN_FUNCTION(emac0_mcg0), + MSM_PIN_FUNCTION(emac0_mcg1), + MSM_PIN_FUNCTION(emac0_mcg2), + MSM_PIN_FUNCTION(emac0_mcg3), + MSM_PIN_FUNCTION(emac0_mdc), + MSM_PIN_FUNCTION(emac0_mdio), + MSM_PIN_FUNCTION(emac0_ptp_aux), + MSM_PIN_FUNCTION(emac0_ptp_pps), + MSM_PIN_FUNCTION(emac1_mcg0), + MSM_PIN_FUNCTION(emac1_mcg1), + MSM_PIN_FUNCTION(emac1_mcg2), + MSM_PIN_FUNCTION(emac1_mcg3), + MSM_PIN_FUNCTION(emac1_mdc), + MSM_PIN_FUNCTION(emac1_mdio), + MSM_PIN_FUNCTION(emac1_ptp_aux), + MSM_PIN_FUNCTION(emac1_ptp_pps), + MSM_PIN_FUNCTION(gcc_gp1), + MSM_PIN_FUNCTION(gcc_gp2), + MSM_PIN_FUNCTION(gcc_gp3), + MSM_PIN_FUNCTION(gcc_gp4), + MSM_PIN_FUNCTION(gcc_gp5), + MSM_PIN_FUNCTION(hs0_mi2s), + MSM_PIN_FUNCTION(hs1_mi2s), + MSM_PIN_FUNCTION(hs2_mi2s), + MSM_PIN_FUNCTION(ibi_i3c), + MSM_PIN_FUNCTION(jitter_bist), + MSM_PIN_FUNCTION(mdp0_vsync0), + MSM_PIN_FUNCTION(mdp0_vsync1), + MSM_PIN_FUNCTION(mdp0_vsync2), + MSM_PIN_FUNCTION(mdp0_vsync3), + MSM_PIN_FUNCTION(mdp0_vsync4), + MSM_PIN_FUNCTION(mdp0_vsync5), + MSM_PIN_FUNCTION(mdp0_vsync6), + MSM_PIN_FUNCTION(mdp0_vsync7), + MSM_PIN_FUNCTION(mdp0_vsync8), + MSM_PIN_FUNCTION(mdp1_vsync0), + MSM_PIN_FUNCTION(mdp1_vsync1), + MSM_PIN_FUNCTION(mdp1_vsync2), + MSM_PIN_FUNCTION(mdp1_vsync3), + MSM_PIN_FUNCTION(mdp1_vsync4), + MSM_PIN_FUNCTION(mdp1_vsync5), + MSM_PIN_FUNCTION(mdp1_vsync6), + MSM_PIN_FUNCTION(mdp1_vsync7), + MSM_PIN_FUNCTION(mdp1_vsync8), + MSM_PIN_FUNCTION(mdp_vsync), + MSM_PIN_FUNCTION(mi2s1_data0), + MSM_PIN_FUNCTION(mi2s1_data1), + MSM_PIN_FUNCTION(mi2s1_sck), + MSM_PIN_FUNCTION(mi2s1_ws), + MSM_PIN_FUNCTION(mi2s2_data0), + MSM_PIN_FUNCTION(mi2s2_data1), + MSM_PIN_FUNCTION(mi2s2_sck), + MSM_PIN_FUNCTION(mi2s2_ws), + MSM_PIN_FUNCTION(mi2s_mclk0), + MSM_PIN_FUNCTION(mi2s_mclk1), + MSM_PIN_FUNCTION(pcie0_clkreq), + MSM_PIN_FUNCTION(pcie1_clkreq), + MSM_PIN_FUNCTION(phase_flag), + MSM_PIN_FUNCTION(pll_bist), + MSM_PIN_FUNCTION(pll_clk), + MSM_PIN_FUNCTION(prng_rosc0), + MSM_PIN_FUNCTION(prng_rosc1), + MSM_PIN_FUNCTION(prng_rosc2), + MSM_PIN_FUNCTION(prng_rosc3), + MSM_PIN_FUNCTION(qdss_cti), + MSM_PIN_FUNCTION(qdss_gpio), + MSM_PIN_FUNCTION(qup0_se0), + MSM_PIN_FUNCTION(qup0_se1), + MSM_PIN_FUNCTION(qup0_se2), + MSM_PIN_FUNCTION(qup0_se3), + MSM_PIN_FUNCTION(qup0_se4), + MSM_PIN_FUNCTION(qup0_se5), + MSM_PIN_FUNCTION(qup1_se0), + MSM_PIN_FUNCTION(qup1_se1), + MSM_PIN_FUNCTION(qup1_se2), + MSM_PIN_FUNCTION(qup1_se3), + MSM_PIN_FUNCTION(qup1_se4), + MSM_PIN_FUNCTION(qup1_se5), + MSM_PIN_FUNCTION(qup1_se6), + MSM_PIN_FUNCTION(qup2_se0), + MSM_PIN_FUNCTION(qup2_se1), + MSM_PIN_FUNCTION(qup2_se2), + MSM_PIN_FUNCTION(qup2_se3), + MSM_PIN_FUNCTION(qup2_se4), + MSM_PIN_FUNCTION(qup2_se5), + MSM_PIN_FUNCTION(qup2_se6), + MSM_PIN_FUNCTION(qup3_se0), + MSM_PIN_FUNCTION(sail_top), + MSM_PIN_FUNCTION(sailss_emac0), + MSM_PIN_FUNCTION(sailss_ospi), + MSM_PIN_FUNCTION(sgmii_phy), + MSM_PIN_FUNCTION(tb_trig), + MSM_PIN_FUNCTION(tgu_ch0), + MSM_PIN_FUNCTION(tgu_ch1), + MSM_PIN_FUNCTION(tgu_ch2), + MSM_PIN_FUNCTION(tgu_ch3), + MSM_PIN_FUNCTION(tgu_ch4), + MSM_PIN_FUNCTION(tgu_ch5), + MSM_PIN_FUNCTION(tsense_pwm1), + MSM_PIN_FUNCTION(tsense_pwm2), + MSM_PIN_FUNCTION(tsense_pwm3), + MSM_PIN_FUNCTION(tsense_pwm4), + MSM_PIN_FUNCTION(usb2phy_ac), + MSM_PIN_FUNCTION(vsense_trigger), }; /* @@ -1491,6 +1483,23 @@ static const struct msm_pingroup sa8775p_groups[] = { [153] = SDC_QDSD_PINGROUP(sdc1_data, 0x199000, 9, 0), }; +static const struct msm_gpio_wakeirq_map sa8775p_pdc_map[] = { + { 0, 169 }, { 1, 174 }, { 2, 170 }, { 3, 175 }, { 4, 171 }, { 5, 173 }, + { 6, 172 }, { 7, 182 }, { 10, 220 }, { 11, 213 }, { 12, 221 }, + { 16, 230 }, { 19, 231 }, { 20, 232 }, { 23, 233 }, { 24, 234 }, + { 26, 223 }, { 27, 235 }, { 28, 209 }, { 29, 176 }, { 30, 200 }, + { 31, 201 }, { 32, 212 }, { 35, 177 }, { 36, 178 }, { 39, 184 }, + { 40, 185 }, { 41, 227 }, { 42, 186 }, { 43, 228 }, { 45, 187 }, + { 47, 188 }, { 48, 194 }, { 51, 195 }, { 52, 196 }, { 55, 197 }, + { 56, 198 }, { 57, 236 }, { 58, 192 }, { 59, 193 }, { 72, 179 }, + { 73, 180 }, { 74, 181 }, { 75, 202 }, { 76, 183 }, { 77, 189 }, + { 78, 190 }, { 79, 191 }, { 80, 199 }, { 83, 204 }, { 84, 205 }, + { 85, 229 }, { 86, 206 }, { 89, 207 }, { 91, 208 }, { 94, 214 }, + { 95, 215 }, { 96, 237 }, { 97, 216 }, { 98, 238 }, { 99, 217 }, + { 100, 239 }, { 105, 219 }, { 106, 210 }, { 107, 211 }, { 108, 222 }, + { 109, 203 }, { 145, 225 }, { 146, 226 }, +}; + static const struct msm_pinctrl_soc_data sa8775p_pinctrl = { .pins = sa8775p_pins, .npins = ARRAY_SIZE(sa8775p_pins), @@ -1499,6 +1508,8 @@ static const struct msm_pinctrl_soc_data sa8775p_pinctrl = { .groups = sa8775p_groups, .ngroups = ARRAY_SIZE(sa8775p_groups), .ngpios = 150, + .wakeirq_map = sa8775p_pdc_map, + .nwakeirq_map = ARRAY_SIZE(sa8775p_pdc_map), }; static int sa8775p_pinctrl_probe(struct platform_device *pdev) diff --git a/drivers/pinctrl/qcom/pinctrl-sc7180.c b/drivers/pinctrl/qcom/pinctrl-sc7180.c index 1d9acad3c1ce2a895f63d9207a8b53c62bbd20c8..6eb0c73791c0bc9883bf0b740b8930fe7c7fced0 100644 --- a/drivers/pinctrl/qcom/pinctrl-sc7180.c +++ b/drivers/pinctrl/qcom/pinctrl-sc7180.c @@ -4,7 +4,6 @@ #include #include #include -#include #include "pinctrl-msm.h" @@ -20,18 +19,11 @@ enum { WEST }; -#define FUNCTION(fname) \ - [msm_mux_##fname] = { \ - .name = #fname, \ - .groups = fname##_groups, \ - .ngroups = ARRAY_SIZE(fname##_groups), \ - } - #define PINGROUP(id, _tile, f1, f2, f3, f4, f5, f6, f7, f8, f9) \ { \ - .name = "gpio" #id, \ - .pins = gpio##id##_pins, \ - .npins = ARRAY_SIZE(gpio##id##_pins), \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ .funcs = (int[]){ \ msm_mux_gpio, /* gpio mode */ \ msm_mux_##f1, \ @@ -69,9 +61,9 @@ enum { #define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = ctl, \ .io_reg = 0, \ .intr_cfg_reg = 0, \ @@ -95,9 +87,9 @@ enum { #define UFS_RESET(pg_name, offset) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = offset, \ .io_reg = offset + 0x4, \ .intr_cfg_reg = 0, \ @@ -868,120 +860,120 @@ static const char * const qup04_uart_groups[] = { "gpio115", "gpio116", }; -static const struct msm_function sc7180_functions[] = { - FUNCTION(adsp_ext), - FUNCTION(agera_pll), - FUNCTION(aoss_cti), - FUNCTION(atest_char), - FUNCTION(atest_char0), - FUNCTION(atest_char1), - FUNCTION(atest_char2), - FUNCTION(atest_char3), - FUNCTION(atest_tsens), - FUNCTION(atest_tsens2), - FUNCTION(atest_usb1), - FUNCTION(atest_usb2), - FUNCTION(atest_usb10), - FUNCTION(atest_usb11), - FUNCTION(atest_usb12), - FUNCTION(atest_usb13), - FUNCTION(atest_usb20), - FUNCTION(atest_usb21), - FUNCTION(atest_usb22), - FUNCTION(atest_usb23), - FUNCTION(audio_ref), - FUNCTION(btfm_slimbus), - FUNCTION(cam_mclk), - FUNCTION(cci_async), - FUNCTION(cci_i2c), - FUNCTION(cci_timer0), - FUNCTION(cci_timer1), - FUNCTION(cci_timer2), - FUNCTION(cci_timer3), - FUNCTION(cci_timer4), - FUNCTION(cri_trng), - FUNCTION(dbg_out), - FUNCTION(ddr_bist), - FUNCTION(ddr_pxi0), - FUNCTION(ddr_pxi1), - FUNCTION(ddr_pxi2), - FUNCTION(ddr_pxi3), - FUNCTION(dp_hot), - FUNCTION(edp_lcd), - FUNCTION(gcc_gp1), - FUNCTION(gcc_gp2), - FUNCTION(gcc_gp3), - FUNCTION(gpio), - FUNCTION(gp_pdm0), - FUNCTION(gp_pdm1), - FUNCTION(gp_pdm2), - FUNCTION(gps_tx), - FUNCTION(jitter_bist), - FUNCTION(ldo_en), - FUNCTION(ldo_update), - FUNCTION(lpass_ext), - FUNCTION(mdp_vsync), - FUNCTION(mdp_vsync0), - FUNCTION(mdp_vsync1), - FUNCTION(mdp_vsync2), - FUNCTION(mdp_vsync3), - FUNCTION(mi2s_0), - FUNCTION(mi2s_1), - FUNCTION(mi2s_2), - FUNCTION(mss_lte), - FUNCTION(m_voc), - FUNCTION(pa_indicator), - FUNCTION(phase_flag), - FUNCTION(PLL_BIST), - FUNCTION(pll_bypassnl), - FUNCTION(pll_reset), - FUNCTION(prng_rosc), - FUNCTION(qdss), - FUNCTION(qdss_cti), - FUNCTION(qlink_enable), - FUNCTION(qlink_request), - FUNCTION(qspi_clk), - FUNCTION(qspi_cs), - FUNCTION(qspi_data), - FUNCTION(qup00), - FUNCTION(qup01), - FUNCTION(qup02_i2c), - FUNCTION(qup02_uart), - FUNCTION(qup03), - FUNCTION(qup04_i2c), - FUNCTION(qup04_uart), - FUNCTION(qup05), - FUNCTION(qup10), - FUNCTION(qup11_i2c), - FUNCTION(qup11_uart), - FUNCTION(qup12), - FUNCTION(qup13_i2c), - FUNCTION(qup13_uart), - FUNCTION(qup14), - FUNCTION(qup15), - FUNCTION(sdc1_tb), - FUNCTION(sdc2_tb), - FUNCTION(sd_write), - FUNCTION(sp_cmu), - FUNCTION(tgu_ch0), - FUNCTION(tgu_ch1), - FUNCTION(tgu_ch2), - FUNCTION(tgu_ch3), - FUNCTION(tsense_pwm1), - FUNCTION(tsense_pwm2), - FUNCTION(uim1), - FUNCTION(uim2), - FUNCTION(uim_batt), - FUNCTION(usb_phy), - FUNCTION(vfr_1), - FUNCTION(_V_GPIO), - FUNCTION(_V_PPS_IN), - FUNCTION(_V_PPS_OUT), - FUNCTION(vsense_trigger), - FUNCTION(wlan1_adc0), - FUNCTION(wlan1_adc1), - FUNCTION(wlan2_adc0), - FUNCTION(wlan2_adc1), +static const struct pinfunction sc7180_functions[] = { + MSM_PIN_FUNCTION(adsp_ext), + MSM_PIN_FUNCTION(agera_pll), + MSM_PIN_FUNCTION(aoss_cti), + MSM_PIN_FUNCTION(atest_char), + MSM_PIN_FUNCTION(atest_char0), + MSM_PIN_FUNCTION(atest_char1), + MSM_PIN_FUNCTION(atest_char2), + MSM_PIN_FUNCTION(atest_char3), + MSM_PIN_FUNCTION(atest_tsens), + MSM_PIN_FUNCTION(atest_tsens2), + MSM_PIN_FUNCTION(atest_usb1), + MSM_PIN_FUNCTION(atest_usb2), + MSM_PIN_FUNCTION(atest_usb10), + MSM_PIN_FUNCTION(atest_usb11), + MSM_PIN_FUNCTION(atest_usb12), + MSM_PIN_FUNCTION(atest_usb13), + MSM_PIN_FUNCTION(atest_usb20), + MSM_PIN_FUNCTION(atest_usb21), + MSM_PIN_FUNCTION(atest_usb22), + MSM_PIN_FUNCTION(atest_usb23), + MSM_PIN_FUNCTION(audio_ref), + MSM_PIN_FUNCTION(btfm_slimbus), + MSM_PIN_FUNCTION(cam_mclk), + MSM_PIN_FUNCTION(cci_async), + MSM_PIN_FUNCTION(cci_i2c), + MSM_PIN_FUNCTION(cci_timer0), + MSM_PIN_FUNCTION(cci_timer1), + MSM_PIN_FUNCTION(cci_timer2), + MSM_PIN_FUNCTION(cci_timer3), + MSM_PIN_FUNCTION(cci_timer4), + MSM_PIN_FUNCTION(cri_trng), + MSM_PIN_FUNCTION(dbg_out), + MSM_PIN_FUNCTION(ddr_bist), + MSM_PIN_FUNCTION(ddr_pxi0), + MSM_PIN_FUNCTION(ddr_pxi1), + MSM_PIN_FUNCTION(ddr_pxi2), + MSM_PIN_FUNCTION(ddr_pxi3), + MSM_PIN_FUNCTION(dp_hot), + MSM_PIN_FUNCTION(edp_lcd), + MSM_PIN_FUNCTION(gcc_gp1), + MSM_PIN_FUNCTION(gcc_gp2), + MSM_PIN_FUNCTION(gcc_gp3), + MSM_PIN_FUNCTION(gpio), + MSM_PIN_FUNCTION(gp_pdm0), + MSM_PIN_FUNCTION(gp_pdm1), + MSM_PIN_FUNCTION(gp_pdm2), + MSM_PIN_FUNCTION(gps_tx), + MSM_PIN_FUNCTION(jitter_bist), + MSM_PIN_FUNCTION(ldo_en), + MSM_PIN_FUNCTION(ldo_update), + MSM_PIN_FUNCTION(lpass_ext), + MSM_PIN_FUNCTION(mdp_vsync), + MSM_PIN_FUNCTION(mdp_vsync0), + MSM_PIN_FUNCTION(mdp_vsync1), + MSM_PIN_FUNCTION(mdp_vsync2), + MSM_PIN_FUNCTION(mdp_vsync3), + MSM_PIN_FUNCTION(mi2s_0), + MSM_PIN_FUNCTION(mi2s_1), + MSM_PIN_FUNCTION(mi2s_2), + MSM_PIN_FUNCTION(mss_lte), + MSM_PIN_FUNCTION(m_voc), + MSM_PIN_FUNCTION(pa_indicator), + MSM_PIN_FUNCTION(phase_flag), + MSM_PIN_FUNCTION(PLL_BIST), + MSM_PIN_FUNCTION(pll_bypassnl), + MSM_PIN_FUNCTION(pll_reset), + MSM_PIN_FUNCTION(prng_rosc), + MSM_PIN_FUNCTION(qdss), + MSM_PIN_FUNCTION(qdss_cti), + MSM_PIN_FUNCTION(qlink_enable), + MSM_PIN_FUNCTION(qlink_request), + MSM_PIN_FUNCTION(qspi_clk), + MSM_PIN_FUNCTION(qspi_cs), + MSM_PIN_FUNCTION(qspi_data), + MSM_PIN_FUNCTION(qup00), + MSM_PIN_FUNCTION(qup01), + MSM_PIN_FUNCTION(qup02_i2c), + MSM_PIN_FUNCTION(qup02_uart), + MSM_PIN_FUNCTION(qup03), + MSM_PIN_FUNCTION(qup04_i2c), + MSM_PIN_FUNCTION(qup04_uart), + MSM_PIN_FUNCTION(qup05), + MSM_PIN_FUNCTION(qup10), + MSM_PIN_FUNCTION(qup11_i2c), + MSM_PIN_FUNCTION(qup11_uart), + MSM_PIN_FUNCTION(qup12), + MSM_PIN_FUNCTION(qup13_i2c), + MSM_PIN_FUNCTION(qup13_uart), + MSM_PIN_FUNCTION(qup14), + MSM_PIN_FUNCTION(qup15), + MSM_PIN_FUNCTION(sdc1_tb), + MSM_PIN_FUNCTION(sdc2_tb), + MSM_PIN_FUNCTION(sd_write), + MSM_PIN_FUNCTION(sp_cmu), + MSM_PIN_FUNCTION(tgu_ch0), + MSM_PIN_FUNCTION(tgu_ch1), + MSM_PIN_FUNCTION(tgu_ch2), + MSM_PIN_FUNCTION(tgu_ch3), + MSM_PIN_FUNCTION(tsense_pwm1), + MSM_PIN_FUNCTION(tsense_pwm2), + MSM_PIN_FUNCTION(uim1), + MSM_PIN_FUNCTION(uim2), + MSM_PIN_FUNCTION(uim_batt), + MSM_PIN_FUNCTION(usb_phy), + MSM_PIN_FUNCTION(vfr_1), + MSM_PIN_FUNCTION(_V_GPIO), + MSM_PIN_FUNCTION(_V_PPS_IN), + MSM_PIN_FUNCTION(_V_PPS_OUT), + MSM_PIN_FUNCTION(vsense_trigger), + MSM_PIN_FUNCTION(wlan1_adc0), + MSM_PIN_FUNCTION(wlan1_adc1), + MSM_PIN_FUNCTION(wlan2_adc0), + MSM_PIN_FUNCTION(wlan2_adc1), }; /* Every pin is maintained as a single group, and missing or non-existing pin diff --git a/drivers/pinctrl/qcom/pinctrl-sc7280.c b/drivers/pinctrl/qcom/pinctrl-sc7280.c index 31df55c79cb3848e4f9ba206989c6f417a1d968d..0c10eeb60b55e742a73dfd43d647f7009471b1b0 100644 --- a/drivers/pinctrl/qcom/pinctrl-sc7280.c +++ b/drivers/pinctrl/qcom/pinctrl-sc7280.c @@ -6,22 +6,14 @@ #include #include #include -#include #include "pinctrl-msm.h" -#define FUNCTION(fname) \ - [msm_mux_##fname] = { \ - .name = #fname, \ - .groups = fname##_groups, \ - .ngroups = ARRAY_SIZE(fname##_groups), \ - } - #define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9) \ { \ - .name = "gpio" #id, \ - .pins = gpio##id##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(gpio##id##_pins), \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ .funcs = (int[]){ \ msm_mux_gpio, /* gpio mode */ \ msm_mux_##f1, \ @@ -60,9 +52,9 @@ #define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = ctl, \ .io_reg = 0, \ .intr_cfg_reg = 0, \ @@ -85,9 +77,9 @@ #define UFS_RESET(pg_name, offset) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = offset, \ .io_reg = offset + 0x4, \ .intr_cfg_reg = 0, \ @@ -1120,154 +1112,154 @@ static const char * const vsense_trigger_groups[] = { "gpio100", }; -static const struct msm_function sc7280_functions[] = { - FUNCTION(atest_char), - FUNCTION(atest_char0), - FUNCTION(atest_char1), - FUNCTION(atest_char2), - FUNCTION(atest_char3), - FUNCTION(atest_usb0), - FUNCTION(atest_usb00), - FUNCTION(atest_usb01), - FUNCTION(atest_usb02), - FUNCTION(atest_usb03), - FUNCTION(atest_usb1), - FUNCTION(atest_usb10), - FUNCTION(atest_usb11), - FUNCTION(atest_usb12), - FUNCTION(atest_usb13), - FUNCTION(audio_ref), - FUNCTION(cam_mclk), - FUNCTION(cci_async), - FUNCTION(cci_i2c), - FUNCTION(cci_timer0), - FUNCTION(cci_timer1), - FUNCTION(cci_timer2), - FUNCTION(cci_timer3), - FUNCTION(cci_timer4), - FUNCTION(cmu_rng0), - FUNCTION(cmu_rng1), - FUNCTION(cmu_rng2), - FUNCTION(cmu_rng3), - FUNCTION(coex_uart1), - FUNCTION(cri_trng), - FUNCTION(cri_trng0), - FUNCTION(cri_trng1), - FUNCTION(dbg_out), - FUNCTION(ddr_bist), - FUNCTION(ddr_pxi0), - FUNCTION(ddr_pxi1), - FUNCTION(dp_hot), - FUNCTION(dp_lcd), - FUNCTION(edp_hot), - FUNCTION(edp_lcd), - FUNCTION(egpio), - FUNCTION(gcc_gp1), - FUNCTION(gcc_gp2), - FUNCTION(gcc_gp3), - FUNCTION(gpio), - FUNCTION(host2wlan_sol), - FUNCTION(ibi_i3c), - FUNCTION(jitter_bist), - FUNCTION(lpass_slimbus), - FUNCTION(mdp_vsync), - FUNCTION(mdp_vsync0), - FUNCTION(mdp_vsync1), - FUNCTION(mdp_vsync2), - FUNCTION(mdp_vsync3), - FUNCTION(mdp_vsync4), - FUNCTION(mdp_vsync5), - FUNCTION(mi2s0_data0), - FUNCTION(mi2s0_data1), - FUNCTION(mi2s0_sck), - FUNCTION(mi2s0_ws), - FUNCTION(mi2s1_data0), - FUNCTION(mi2s1_data1), - FUNCTION(mi2s1_sck), - FUNCTION(mi2s1_ws), - FUNCTION(mi2s2_data0), - FUNCTION(mi2s2_data1), - FUNCTION(mi2s2_sck), - FUNCTION(mi2s2_ws), - FUNCTION(mss_grfc0), - FUNCTION(mss_grfc1), - FUNCTION(mss_grfc10), - FUNCTION(mss_grfc11), - FUNCTION(mss_grfc12), - FUNCTION(mss_grfc2), - FUNCTION(mss_grfc3), - FUNCTION(mss_grfc4), - FUNCTION(mss_grfc5), - FUNCTION(mss_grfc6), - FUNCTION(mss_grfc7), - FUNCTION(mss_grfc8), - FUNCTION(mss_grfc9), - FUNCTION(nav_gpio0), - FUNCTION(nav_gpio1), - FUNCTION(nav_gpio2), - FUNCTION(pa_indicator), - FUNCTION(pcie0_clkreqn), - FUNCTION(pcie1_clkreqn), - FUNCTION(phase_flag), - FUNCTION(pll_bist), - FUNCTION(pll_bypassnl), - FUNCTION(pll_clk), - FUNCTION(pll_reset), - FUNCTION(pri_mi2s), - FUNCTION(prng_rosc), - FUNCTION(qdss), - FUNCTION(qdss_cti), - FUNCTION(qlink0_enable), - FUNCTION(qlink0_request), - FUNCTION(qlink0_wmss), - FUNCTION(qlink1_enable), - FUNCTION(qlink1_request), - FUNCTION(qlink1_wmss), - FUNCTION(qspi_clk), - FUNCTION(qspi_cs), - FUNCTION(qspi_data), - FUNCTION(qup00), - FUNCTION(qup01), - FUNCTION(qup02), - FUNCTION(qup03), - FUNCTION(qup04), - FUNCTION(qup05), - FUNCTION(qup06), - FUNCTION(qup07), - FUNCTION(qup10), - FUNCTION(qup11), - FUNCTION(qup12), - FUNCTION(qup13), - FUNCTION(qup14), - FUNCTION(qup15), - FUNCTION(qup16), - FUNCTION(qup17), - FUNCTION(sdc40), - FUNCTION(sdc41), - FUNCTION(sdc42), - FUNCTION(sdc43), - FUNCTION(sdc4_clk), - FUNCTION(sdc4_cmd), - FUNCTION(sd_write), - FUNCTION(sec_mi2s), - FUNCTION(tb_trig), - FUNCTION(tgu_ch0), - FUNCTION(tgu_ch1), - FUNCTION(tsense_pwm1), - FUNCTION(tsense_pwm2), - FUNCTION(uim0_clk), - FUNCTION(uim0_data), - FUNCTION(uim0_present), - FUNCTION(uim0_reset), - FUNCTION(uim1_clk), - FUNCTION(uim1_data), - FUNCTION(uim1_present), - FUNCTION(uim1_reset), - FUNCTION(usb2phy_ac), - FUNCTION(usb_phy), - FUNCTION(vfr_0), - FUNCTION(vfr_1), - FUNCTION(vsense_trigger), +static const struct pinfunction sc7280_functions[] = { + MSM_PIN_FUNCTION(atest_char), + MSM_PIN_FUNCTION(atest_char0), + MSM_PIN_FUNCTION(atest_char1), + MSM_PIN_FUNCTION(atest_char2), + MSM_PIN_FUNCTION(atest_char3), + MSM_PIN_FUNCTION(atest_usb0), + MSM_PIN_FUNCTION(atest_usb00), + MSM_PIN_FUNCTION(atest_usb01), + MSM_PIN_FUNCTION(atest_usb02), + MSM_PIN_FUNCTION(atest_usb03), + MSM_PIN_FUNCTION(atest_usb1), + MSM_PIN_FUNCTION(atest_usb10), + MSM_PIN_FUNCTION(atest_usb11), + MSM_PIN_FUNCTION(atest_usb12), + MSM_PIN_FUNCTION(atest_usb13), + MSM_PIN_FUNCTION(audio_ref), + MSM_PIN_FUNCTION(cam_mclk), + MSM_PIN_FUNCTION(cci_async), + MSM_PIN_FUNCTION(cci_i2c), + MSM_PIN_FUNCTION(cci_timer0), + MSM_PIN_FUNCTION(cci_timer1), + MSM_PIN_FUNCTION(cci_timer2), + MSM_PIN_FUNCTION(cci_timer3), + MSM_PIN_FUNCTION(cci_timer4), + MSM_PIN_FUNCTION(cmu_rng0), + MSM_PIN_FUNCTION(cmu_rng1), + MSM_PIN_FUNCTION(cmu_rng2), + MSM_PIN_FUNCTION(cmu_rng3), + MSM_PIN_FUNCTION(coex_uart1), + MSM_PIN_FUNCTION(cri_trng), + MSM_PIN_FUNCTION(cri_trng0), + MSM_PIN_FUNCTION(cri_trng1), + MSM_PIN_FUNCTION(dbg_out), + MSM_PIN_FUNCTION(ddr_bist), + MSM_PIN_FUNCTION(ddr_pxi0), + MSM_PIN_FUNCTION(ddr_pxi1), + MSM_PIN_FUNCTION(dp_hot), + MSM_PIN_FUNCTION(dp_lcd), + MSM_PIN_FUNCTION(edp_hot), + MSM_PIN_FUNCTION(edp_lcd), + MSM_PIN_FUNCTION(egpio), + MSM_PIN_FUNCTION(gcc_gp1), + MSM_PIN_FUNCTION(gcc_gp2), + MSM_PIN_FUNCTION(gcc_gp3), + MSM_PIN_FUNCTION(gpio), + MSM_PIN_FUNCTION(host2wlan_sol), + MSM_PIN_FUNCTION(ibi_i3c), + MSM_PIN_FUNCTION(jitter_bist), + MSM_PIN_FUNCTION(lpass_slimbus), + MSM_PIN_FUNCTION(mdp_vsync), + MSM_PIN_FUNCTION(mdp_vsync0), + MSM_PIN_FUNCTION(mdp_vsync1), + MSM_PIN_FUNCTION(mdp_vsync2), + MSM_PIN_FUNCTION(mdp_vsync3), + MSM_PIN_FUNCTION(mdp_vsync4), + MSM_PIN_FUNCTION(mdp_vsync5), + MSM_PIN_FUNCTION(mi2s0_data0), + MSM_PIN_FUNCTION(mi2s0_data1), + MSM_PIN_FUNCTION(mi2s0_sck), + MSM_PIN_FUNCTION(mi2s0_ws), + MSM_PIN_FUNCTION(mi2s1_data0), + MSM_PIN_FUNCTION(mi2s1_data1), + MSM_PIN_FUNCTION(mi2s1_sck), + MSM_PIN_FUNCTION(mi2s1_ws), + MSM_PIN_FUNCTION(mi2s2_data0), + MSM_PIN_FUNCTION(mi2s2_data1), + MSM_PIN_FUNCTION(mi2s2_sck), + MSM_PIN_FUNCTION(mi2s2_ws), + MSM_PIN_FUNCTION(mss_grfc0), + MSM_PIN_FUNCTION(mss_grfc1), + MSM_PIN_FUNCTION(mss_grfc10), + MSM_PIN_FUNCTION(mss_grfc11), + MSM_PIN_FUNCTION(mss_grfc12), + MSM_PIN_FUNCTION(mss_grfc2), + MSM_PIN_FUNCTION(mss_grfc3), + MSM_PIN_FUNCTION(mss_grfc4), + MSM_PIN_FUNCTION(mss_grfc5), + MSM_PIN_FUNCTION(mss_grfc6), + MSM_PIN_FUNCTION(mss_grfc7), + MSM_PIN_FUNCTION(mss_grfc8), + MSM_PIN_FUNCTION(mss_grfc9), + MSM_PIN_FUNCTION(nav_gpio0), + MSM_PIN_FUNCTION(nav_gpio1), + MSM_PIN_FUNCTION(nav_gpio2), + MSM_PIN_FUNCTION(pa_indicator), + MSM_PIN_FUNCTION(pcie0_clkreqn), + MSM_PIN_FUNCTION(pcie1_clkreqn), + MSM_PIN_FUNCTION(phase_flag), + MSM_PIN_FUNCTION(pll_bist), + MSM_PIN_FUNCTION(pll_bypassnl), + MSM_PIN_FUNCTION(pll_clk), + MSM_PIN_FUNCTION(pll_reset), + MSM_PIN_FUNCTION(pri_mi2s), + MSM_PIN_FUNCTION(prng_rosc), + MSM_PIN_FUNCTION(qdss), + MSM_PIN_FUNCTION(qdss_cti), + MSM_PIN_FUNCTION(qlink0_enable), + MSM_PIN_FUNCTION(qlink0_request), + MSM_PIN_FUNCTION(qlink0_wmss), + MSM_PIN_FUNCTION(qlink1_enable), + MSM_PIN_FUNCTION(qlink1_request), + MSM_PIN_FUNCTION(qlink1_wmss), + MSM_PIN_FUNCTION(qspi_clk), + MSM_PIN_FUNCTION(qspi_cs), + MSM_PIN_FUNCTION(qspi_data), + MSM_PIN_FUNCTION(qup00), + MSM_PIN_FUNCTION(qup01), + MSM_PIN_FUNCTION(qup02), + MSM_PIN_FUNCTION(qup03), + MSM_PIN_FUNCTION(qup04), + MSM_PIN_FUNCTION(qup05), + MSM_PIN_FUNCTION(qup06), + MSM_PIN_FUNCTION(qup07), + MSM_PIN_FUNCTION(qup10), + MSM_PIN_FUNCTION(qup11), + MSM_PIN_FUNCTION(qup12), + MSM_PIN_FUNCTION(qup13), + MSM_PIN_FUNCTION(qup14), + MSM_PIN_FUNCTION(qup15), + MSM_PIN_FUNCTION(qup16), + MSM_PIN_FUNCTION(qup17), + MSM_PIN_FUNCTION(sdc40), + MSM_PIN_FUNCTION(sdc41), + MSM_PIN_FUNCTION(sdc42), + MSM_PIN_FUNCTION(sdc43), + MSM_PIN_FUNCTION(sdc4_clk), + MSM_PIN_FUNCTION(sdc4_cmd), + MSM_PIN_FUNCTION(sd_write), + MSM_PIN_FUNCTION(sec_mi2s), + MSM_PIN_FUNCTION(tb_trig), + MSM_PIN_FUNCTION(tgu_ch0), + MSM_PIN_FUNCTION(tgu_ch1), + MSM_PIN_FUNCTION(tsense_pwm1), + MSM_PIN_FUNCTION(tsense_pwm2), + MSM_PIN_FUNCTION(uim0_clk), + MSM_PIN_FUNCTION(uim0_data), + MSM_PIN_FUNCTION(uim0_present), + MSM_PIN_FUNCTION(uim0_reset), + MSM_PIN_FUNCTION(uim1_clk), + MSM_PIN_FUNCTION(uim1_data), + MSM_PIN_FUNCTION(uim1_present), + MSM_PIN_FUNCTION(uim1_reset), + MSM_PIN_FUNCTION(usb2phy_ac), + MSM_PIN_FUNCTION(usb_phy), + MSM_PIN_FUNCTION(vfr_0), + MSM_PIN_FUNCTION(vfr_1), + MSM_PIN_FUNCTION(vsense_trigger), }; /* Every pin is maintained as a single group, and missing or non-existing pin diff --git a/drivers/pinctrl/qcom/pinctrl-sc8180x.c b/drivers/pinctrl/qcom/pinctrl-sc8180x.c index 704a99d2f93cebe91e21e14ac51655bde2de9a3b..d6a79ad41a40a804c503d97a6279db4b533f0047 100644 --- a/drivers/pinctrl/qcom/pinctrl-sc8180x.c +++ b/drivers/pinctrl/qcom/pinctrl-sc8180x.c @@ -7,7 +7,6 @@ #include #include #include -#include #include "pinctrl-msm.h" @@ -38,19 +37,12 @@ static const struct tile_info sc8180x_tile_info[] = { { 0x00100000, 0x00300000, }, }; -#define FUNCTION(fname) \ - [msm_mux_##fname] = { \ - .name = #fname, \ - .groups = fname##_groups, \ - .ngroups = ARRAY_SIZE(fname##_groups), \ - } - #define REG_SIZE 0x1000 #define PINGROUP_OFFSET(id, _tile, offset, f1, f2, f3, f4, f5, f6, f7, f8, f9) \ { \ - .name = "gpio" #id, \ - .pins = gpio##id##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(gpio##id##_pins), \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ .funcs = (int[]){ \ msm_mux_gpio, /* gpio mode */ \ msm_mux_##f1, \ @@ -91,9 +83,9 @@ static const struct tile_info sc8180x_tile_info[] = { #define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = ctl, \ .io_reg = 0, \ .intr_cfg_reg = 0, \ @@ -117,9 +109,9 @@ static const struct tile_info sc8180x_tile_info[] = { #define UFS_RESET(pg_name) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = 0xb6000, \ .io_reg = 0xb6004, \ .intr_cfg_reg = 0, \ @@ -1238,136 +1230,136 @@ static const char * const wmss_reset_groups[] = { "gpio63", }; -static const struct msm_function sc8180x_functions[] = { - FUNCTION(adsp_ext), - FUNCTION(agera_pll), - FUNCTION(aoss_cti), - FUNCTION(atest_char), - FUNCTION(atest_tsens), - FUNCTION(atest_tsens2), - FUNCTION(atest_usb0), - FUNCTION(atest_usb1), - FUNCTION(atest_usb2), - FUNCTION(atest_usb3), - FUNCTION(atest_usb4), - FUNCTION(audio_ref), - FUNCTION(btfm_slimbus), - FUNCTION(cam_mclk), - FUNCTION(cci_async), - FUNCTION(cci_i2c), - FUNCTION(cci_timer0), - FUNCTION(cci_timer1), - FUNCTION(cci_timer2), - FUNCTION(cci_timer3), - FUNCTION(cci_timer4), - FUNCTION(cci_timer5), - FUNCTION(cci_timer6), - FUNCTION(cci_timer7), - FUNCTION(cci_timer8), - FUNCTION(cci_timer9), - FUNCTION(cri_trng), - FUNCTION(dbg_out), - FUNCTION(ddr_bist), - FUNCTION(ddr_pxi), - FUNCTION(debug_hot), - FUNCTION(dp_hot), - FUNCTION(edp_hot), - FUNCTION(edp_lcd), - FUNCTION(emac_phy), - FUNCTION(emac_pps), - FUNCTION(gcc_gp1), - FUNCTION(gcc_gp2), - FUNCTION(gcc_gp3), - FUNCTION(gcc_gp4), - FUNCTION(gcc_gp5), - FUNCTION(gpio), - FUNCTION(gps), - FUNCTION(grfc), - FUNCTION(hs1_mi2s), - FUNCTION(hs2_mi2s), - FUNCTION(hs3_mi2s), - FUNCTION(jitter_bist), - FUNCTION(lpass_slimbus), - FUNCTION(m_voc), - FUNCTION(mdp_vsync), - FUNCTION(mdp_vsync0), - FUNCTION(mdp_vsync1), - FUNCTION(mdp_vsync2), - FUNCTION(mdp_vsync3), - FUNCTION(mdp_vsync4), - FUNCTION(mdp_vsync5), - FUNCTION(mss_lte), - FUNCTION(nav_pps), - FUNCTION(pa_indicator), - FUNCTION(pci_e0), - FUNCTION(pci_e1), - FUNCTION(pci_e2), - FUNCTION(pci_e3), - FUNCTION(phase_flag), - FUNCTION(pll_bist), - FUNCTION(pll_bypassnl), - FUNCTION(pll_reset), - FUNCTION(pri_mi2s), - FUNCTION(pri_mi2s_ws), - FUNCTION(prng_rosc), - FUNCTION(qdss_cti), - FUNCTION(qdss_gpio), - FUNCTION(qlink), - FUNCTION(qspi0), - FUNCTION(qspi0_clk), - FUNCTION(qspi0_cs), - FUNCTION(qspi1), - FUNCTION(qspi1_clk), - FUNCTION(qspi1_cs), - FUNCTION(qua_mi2s), - FUNCTION(qup0), - FUNCTION(qup1), - FUNCTION(qup2), - FUNCTION(qup3), - FUNCTION(qup4), - FUNCTION(qup5), - FUNCTION(qup6), - FUNCTION(qup7), - FUNCTION(qup8), - FUNCTION(qup9), - FUNCTION(qup10), - FUNCTION(qup11), - FUNCTION(qup12), - FUNCTION(qup13), - FUNCTION(qup14), - FUNCTION(qup15), - FUNCTION(qup16), - FUNCTION(qup17), - FUNCTION(qup18), - FUNCTION(qup19), - FUNCTION(qup_l4), - FUNCTION(qup_l5), - FUNCTION(qup_l6), - FUNCTION(rgmii), - FUNCTION(sd_write), - FUNCTION(sdc4), - FUNCTION(sdc4_clk), - FUNCTION(sdc4_cmd), - FUNCTION(sec_mi2s), - FUNCTION(sp_cmu), - FUNCTION(spkr_i2s), - FUNCTION(ter_mi2s), - FUNCTION(tgu), - FUNCTION(tsense_pwm1), - FUNCTION(tsense_pwm2), - FUNCTION(tsif1), - FUNCTION(tsif2), - FUNCTION(uim1), - FUNCTION(uim2), - FUNCTION(uim_batt), - FUNCTION(usb0_phy), - FUNCTION(usb1_phy), - FUNCTION(usb2phy_ac), - FUNCTION(vfr_1), - FUNCTION(vsense_trigger), - FUNCTION(wlan1_adc), - FUNCTION(wlan2_adc), - FUNCTION(wmss_reset), +static const struct pinfunction sc8180x_functions[] = { + MSM_PIN_FUNCTION(adsp_ext), + MSM_PIN_FUNCTION(agera_pll), + MSM_PIN_FUNCTION(aoss_cti), + MSM_PIN_FUNCTION(atest_char), + MSM_PIN_FUNCTION(atest_tsens), + MSM_PIN_FUNCTION(atest_tsens2), + MSM_PIN_FUNCTION(atest_usb0), + MSM_PIN_FUNCTION(atest_usb1), + MSM_PIN_FUNCTION(atest_usb2), + MSM_PIN_FUNCTION(atest_usb3), + MSM_PIN_FUNCTION(atest_usb4), + MSM_PIN_FUNCTION(audio_ref), + MSM_PIN_FUNCTION(btfm_slimbus), + MSM_PIN_FUNCTION(cam_mclk), + MSM_PIN_FUNCTION(cci_async), + MSM_PIN_FUNCTION(cci_i2c), + MSM_PIN_FUNCTION(cci_timer0), + MSM_PIN_FUNCTION(cci_timer1), + MSM_PIN_FUNCTION(cci_timer2), + MSM_PIN_FUNCTION(cci_timer3), + MSM_PIN_FUNCTION(cci_timer4), + MSM_PIN_FUNCTION(cci_timer5), + MSM_PIN_FUNCTION(cci_timer6), + MSM_PIN_FUNCTION(cci_timer7), + MSM_PIN_FUNCTION(cci_timer8), + MSM_PIN_FUNCTION(cci_timer9), + MSM_PIN_FUNCTION(cri_trng), + MSM_PIN_FUNCTION(dbg_out), + MSM_PIN_FUNCTION(ddr_bist), + MSM_PIN_FUNCTION(ddr_pxi), + MSM_PIN_FUNCTION(debug_hot), + MSM_PIN_FUNCTION(dp_hot), + MSM_PIN_FUNCTION(edp_hot), + MSM_PIN_FUNCTION(edp_lcd), + MSM_PIN_FUNCTION(emac_phy), + MSM_PIN_FUNCTION(emac_pps), + MSM_PIN_FUNCTION(gcc_gp1), + MSM_PIN_FUNCTION(gcc_gp2), + MSM_PIN_FUNCTION(gcc_gp3), + MSM_PIN_FUNCTION(gcc_gp4), + MSM_PIN_FUNCTION(gcc_gp5), + MSM_PIN_FUNCTION(gpio), + MSM_PIN_FUNCTION(gps), + MSM_PIN_FUNCTION(grfc), + MSM_PIN_FUNCTION(hs1_mi2s), + MSM_PIN_FUNCTION(hs2_mi2s), + MSM_PIN_FUNCTION(hs3_mi2s), + MSM_PIN_FUNCTION(jitter_bist), + MSM_PIN_FUNCTION(lpass_slimbus), + MSM_PIN_FUNCTION(m_voc), + MSM_PIN_FUNCTION(mdp_vsync), + MSM_PIN_FUNCTION(mdp_vsync0), + MSM_PIN_FUNCTION(mdp_vsync1), + MSM_PIN_FUNCTION(mdp_vsync2), + MSM_PIN_FUNCTION(mdp_vsync3), + MSM_PIN_FUNCTION(mdp_vsync4), + MSM_PIN_FUNCTION(mdp_vsync5), + MSM_PIN_FUNCTION(mss_lte), + MSM_PIN_FUNCTION(nav_pps), + MSM_PIN_FUNCTION(pa_indicator), + MSM_PIN_FUNCTION(pci_e0), + MSM_PIN_FUNCTION(pci_e1), + MSM_PIN_FUNCTION(pci_e2), + MSM_PIN_FUNCTION(pci_e3), + MSM_PIN_FUNCTION(phase_flag), + MSM_PIN_FUNCTION(pll_bist), + MSM_PIN_FUNCTION(pll_bypassnl), + MSM_PIN_FUNCTION(pll_reset), + MSM_PIN_FUNCTION(pri_mi2s), + MSM_PIN_FUNCTION(pri_mi2s_ws), + MSM_PIN_FUNCTION(prng_rosc), + MSM_PIN_FUNCTION(qdss_cti), + MSM_PIN_FUNCTION(qdss_gpio), + MSM_PIN_FUNCTION(qlink), + MSM_PIN_FUNCTION(qspi0), + MSM_PIN_FUNCTION(qspi0_clk), + MSM_PIN_FUNCTION(qspi0_cs), + MSM_PIN_FUNCTION(qspi1), + MSM_PIN_FUNCTION(qspi1_clk), + MSM_PIN_FUNCTION(qspi1_cs), + MSM_PIN_FUNCTION(qua_mi2s), + MSM_PIN_FUNCTION(qup0), + MSM_PIN_FUNCTION(qup1), + MSM_PIN_FUNCTION(qup2), + MSM_PIN_FUNCTION(qup3), + MSM_PIN_FUNCTION(qup4), + MSM_PIN_FUNCTION(qup5), + MSM_PIN_FUNCTION(qup6), + MSM_PIN_FUNCTION(qup7), + MSM_PIN_FUNCTION(qup8), + MSM_PIN_FUNCTION(qup9), + MSM_PIN_FUNCTION(qup10), + MSM_PIN_FUNCTION(qup11), + MSM_PIN_FUNCTION(qup12), + MSM_PIN_FUNCTION(qup13), + MSM_PIN_FUNCTION(qup14), + MSM_PIN_FUNCTION(qup15), + MSM_PIN_FUNCTION(qup16), + MSM_PIN_FUNCTION(qup17), + MSM_PIN_FUNCTION(qup18), + MSM_PIN_FUNCTION(qup19), + MSM_PIN_FUNCTION(qup_l4), + MSM_PIN_FUNCTION(qup_l5), + MSM_PIN_FUNCTION(qup_l6), + MSM_PIN_FUNCTION(rgmii), + MSM_PIN_FUNCTION(sd_write), + MSM_PIN_FUNCTION(sdc4), + MSM_PIN_FUNCTION(sdc4_clk), + MSM_PIN_FUNCTION(sdc4_cmd), + MSM_PIN_FUNCTION(sec_mi2s), + MSM_PIN_FUNCTION(sp_cmu), + MSM_PIN_FUNCTION(spkr_i2s), + MSM_PIN_FUNCTION(ter_mi2s), + MSM_PIN_FUNCTION(tgu), + MSM_PIN_FUNCTION(tsense_pwm1), + MSM_PIN_FUNCTION(tsense_pwm2), + MSM_PIN_FUNCTION(tsif1), + MSM_PIN_FUNCTION(tsif2), + MSM_PIN_FUNCTION(uim1), + MSM_PIN_FUNCTION(uim2), + MSM_PIN_FUNCTION(uim_batt), + MSM_PIN_FUNCTION(usb0_phy), + MSM_PIN_FUNCTION(usb1_phy), + MSM_PIN_FUNCTION(usb2phy_ac), + MSM_PIN_FUNCTION(vfr_1), + MSM_PIN_FUNCTION(vsense_trigger), + MSM_PIN_FUNCTION(wlan1_adc), + MSM_PIN_FUNCTION(wlan2_adc), + MSM_PIN_FUNCTION(wmss_reset), }; /* Every pin is maintained as a single group, and missing or non-existing pin @@ -1630,7 +1622,8 @@ static const struct msm_pinctrl_soc_data sc8180x_acpi_pinctrl = { static int sc8180x_pinctrl_add_tile_resources(struct platform_device *pdev) { int nres_num = pdev->num_resources + ARRAY_SIZE(sc8180x_tiles) - 1; - struct resource *mres, *nres, *res; + struct resource *mres = NULL; + struct resource *nres, *res; int i, ret; /* @@ -1657,6 +1650,9 @@ static int sc8180x_pinctrl_add_tile_resources(struct platform_device *pdev) *res++ = *r; } + if (!mres) + return -EINVAL; + /* Append tile memory resources */ for (i = 0; i < ARRAY_SIZE(sc8180x_tiles); i++, res++) { const struct tile_info *info = &sc8180x_tile_info[i]; diff --git a/drivers/pinctrl/qcom/pinctrl-sc8280xp.c b/drivers/pinctrl/qcom/pinctrl-sc8280xp.c index e96c00686a25bc1f68a179f7d9db3c9c647afc85..96f4fb5a5d297f784e63f4335e294ebdee5f487f 100644 --- a/drivers/pinctrl/qcom/pinctrl-sc8280xp.c +++ b/drivers/pinctrl/qcom/pinctrl-sc8280xp.c @@ -7,23 +7,15 @@ #include #include #include -#include #include "pinctrl-msm.h" -#define FUNCTION(fname) \ - [msm_mux_##fname] = { \ - .name = #fname, \ - .groups = fname##_groups, \ - .ngroups = ARRAY_SIZE(fname##_groups), \ - } - #define REG_SIZE 0x1000 #define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7) \ { \ - .name = "gpio" #id, \ - .pins = gpio##id##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(gpio##id##_pins), \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ .funcs = (int[]){ \ msm_mux_gpio, /* gpio mode */ \ msm_mux_##f1, \ @@ -60,9 +52,9 @@ #define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = ctl, \ .io_reg = 0, \ .intr_cfg_reg = 0, \ @@ -85,9 +77,9 @@ #define UFS_RESET(pg_name, offset) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = offset, \ .io_reg = offset + 0x4, \ .intr_cfg_reg = 0, \ @@ -1476,172 +1468,172 @@ static const char * const vsense_trigger_groups[] = { "gpio81", }; -static const struct msm_function sc8280xp_functions[] = { - FUNCTION(atest_char), - FUNCTION(atest_usb), - FUNCTION(audio_ref), - FUNCTION(cam_mclk), - FUNCTION(cci_async), - FUNCTION(cci_i2c), - FUNCTION(cci_timer0), - FUNCTION(cci_timer1), - FUNCTION(cci_timer2), - FUNCTION(cci_timer3), - FUNCTION(cci_timer4), - FUNCTION(cci_timer5), - FUNCTION(cci_timer6), - FUNCTION(cci_timer7), - FUNCTION(cci_timer8), - FUNCTION(cci_timer9), - FUNCTION(cmu_rng), - FUNCTION(cri_trng), - FUNCTION(cri_trng0), - FUNCTION(cri_trng1), - FUNCTION(dbg_out), - FUNCTION(ddr_bist), - FUNCTION(ddr_pxi0), - FUNCTION(ddr_pxi1), - FUNCTION(ddr_pxi2), - FUNCTION(ddr_pxi3), - FUNCTION(ddr_pxi4), - FUNCTION(ddr_pxi5), - FUNCTION(ddr_pxi6), - FUNCTION(ddr_pxi7), - FUNCTION(dp2_hot), - FUNCTION(dp3_hot), - FUNCTION(edp0_lcd), - FUNCTION(edp1_lcd), - FUNCTION(edp2_lcd), - FUNCTION(edp3_lcd), - FUNCTION(edp_hot), - FUNCTION(egpio), - FUNCTION(emac0_dll), - FUNCTION(emac0_mcg0), - FUNCTION(emac0_mcg1), - FUNCTION(emac0_mcg2), - FUNCTION(emac0_mcg3), - FUNCTION(emac0_phy), - FUNCTION(emac0_ptp), - FUNCTION(emac1_dll0), - FUNCTION(emac1_dll1), - FUNCTION(emac1_mcg0), - FUNCTION(emac1_mcg1), - FUNCTION(emac1_mcg2), - FUNCTION(emac1_mcg3), - FUNCTION(emac1_phy), - FUNCTION(emac1_ptp), - FUNCTION(gcc_gp1), - FUNCTION(gcc_gp2), - FUNCTION(gcc_gp3), - FUNCTION(gcc_gp4), - FUNCTION(gcc_gp5), - FUNCTION(gpio), - FUNCTION(hs1_mi2s), - FUNCTION(hs2_mi2s), - FUNCTION(hs3_mi2s), - FUNCTION(ibi_i3c), - FUNCTION(jitter_bist), - FUNCTION(lpass_slimbus), - FUNCTION(mdp0_vsync0), - FUNCTION(mdp0_vsync1), - FUNCTION(mdp0_vsync2), - FUNCTION(mdp0_vsync3), - FUNCTION(mdp0_vsync4), - FUNCTION(mdp0_vsync5), - FUNCTION(mdp0_vsync6), - FUNCTION(mdp0_vsync7), - FUNCTION(mdp0_vsync8), - FUNCTION(mdp1_vsync0), - FUNCTION(mdp1_vsync1), - FUNCTION(mdp1_vsync2), - FUNCTION(mdp1_vsync3), - FUNCTION(mdp1_vsync4), - FUNCTION(mdp1_vsync5), - FUNCTION(mdp1_vsync6), - FUNCTION(mdp1_vsync7), - FUNCTION(mdp1_vsync8), - FUNCTION(mdp_vsync), - FUNCTION(mi2s0_data0), - FUNCTION(mi2s0_data1), - FUNCTION(mi2s0_sck), - FUNCTION(mi2s0_ws), - FUNCTION(mi2s1_data0), - FUNCTION(mi2s1_data1), - FUNCTION(mi2s1_sck), - FUNCTION(mi2s1_ws), - FUNCTION(mi2s2_data0), - FUNCTION(mi2s2_data1), - FUNCTION(mi2s2_sck), - FUNCTION(mi2s2_ws), - FUNCTION(mi2s_mclk1), - FUNCTION(mi2s_mclk2), - FUNCTION(pcie2a_clkreq), - FUNCTION(pcie2b_clkreq), - FUNCTION(pcie3a_clkreq), - FUNCTION(pcie3b_clkreq), - FUNCTION(pcie4_clkreq), - FUNCTION(phase_flag), - FUNCTION(pll_bist), - FUNCTION(pll_clk), - FUNCTION(prng_rosc0), - FUNCTION(prng_rosc1), - FUNCTION(prng_rosc2), - FUNCTION(prng_rosc3), - FUNCTION(qdss_cti), - FUNCTION(qdss_gpio), - FUNCTION(qspi), - FUNCTION(qspi_clk), - FUNCTION(qspi_cs), - FUNCTION(qup0), - FUNCTION(qup1), - FUNCTION(qup2), - FUNCTION(qup3), - FUNCTION(qup4), - FUNCTION(qup5), - FUNCTION(qup6), - FUNCTION(qup7), - FUNCTION(qup8), - FUNCTION(qup9), - FUNCTION(qup10), - FUNCTION(qup11), - FUNCTION(qup12), - FUNCTION(qup13), - FUNCTION(qup14), - FUNCTION(qup15), - FUNCTION(qup16), - FUNCTION(qup17), - FUNCTION(qup18), - FUNCTION(qup19), - FUNCTION(qup20), - FUNCTION(qup21), - FUNCTION(qup22), - FUNCTION(qup23), - FUNCTION(rgmii_0), - FUNCTION(rgmii_1), - FUNCTION(sd_write), - FUNCTION(sdc40), - FUNCTION(sdc42), - FUNCTION(sdc43), - FUNCTION(sdc4_clk), - FUNCTION(sdc4_cmd), - FUNCTION(tb_trig), - FUNCTION(tgu), - FUNCTION(tsense_pwm1), - FUNCTION(tsense_pwm2), - FUNCTION(tsense_pwm3), - FUNCTION(tsense_pwm4), - FUNCTION(usb0_dp), - FUNCTION(usb0_phy), - FUNCTION(usb0_sbrx), - FUNCTION(usb0_sbtx), - FUNCTION(usb0_usb4), - FUNCTION(usb1_dp), - FUNCTION(usb1_phy), - FUNCTION(usb1_sbrx), - FUNCTION(usb1_sbtx), - FUNCTION(usb1_usb4), - FUNCTION(usb2phy_ac), - FUNCTION(vsense_trigger), +static const struct pinfunction sc8280xp_functions[] = { + MSM_PIN_FUNCTION(atest_char), + MSM_PIN_FUNCTION(atest_usb), + MSM_PIN_FUNCTION(audio_ref), + MSM_PIN_FUNCTION(cam_mclk), + MSM_PIN_FUNCTION(cci_async), + MSM_PIN_FUNCTION(cci_i2c), + MSM_PIN_FUNCTION(cci_timer0), + MSM_PIN_FUNCTION(cci_timer1), + MSM_PIN_FUNCTION(cci_timer2), + MSM_PIN_FUNCTION(cci_timer3), + MSM_PIN_FUNCTION(cci_timer4), + MSM_PIN_FUNCTION(cci_timer5), + MSM_PIN_FUNCTION(cci_timer6), + MSM_PIN_FUNCTION(cci_timer7), + MSM_PIN_FUNCTION(cci_timer8), + MSM_PIN_FUNCTION(cci_timer9), + MSM_PIN_FUNCTION(cmu_rng), + MSM_PIN_FUNCTION(cri_trng), + MSM_PIN_FUNCTION(cri_trng0), + MSM_PIN_FUNCTION(cri_trng1), + MSM_PIN_FUNCTION(dbg_out), + MSM_PIN_FUNCTION(ddr_bist), + MSM_PIN_FUNCTION(ddr_pxi0), + MSM_PIN_FUNCTION(ddr_pxi1), + MSM_PIN_FUNCTION(ddr_pxi2), + MSM_PIN_FUNCTION(ddr_pxi3), + MSM_PIN_FUNCTION(ddr_pxi4), + MSM_PIN_FUNCTION(ddr_pxi5), + MSM_PIN_FUNCTION(ddr_pxi6), + MSM_PIN_FUNCTION(ddr_pxi7), + MSM_PIN_FUNCTION(dp2_hot), + MSM_PIN_FUNCTION(dp3_hot), + MSM_PIN_FUNCTION(edp0_lcd), + MSM_PIN_FUNCTION(edp1_lcd), + MSM_PIN_FUNCTION(edp2_lcd), + MSM_PIN_FUNCTION(edp3_lcd), + MSM_PIN_FUNCTION(edp_hot), + MSM_PIN_FUNCTION(egpio), + MSM_PIN_FUNCTION(emac0_dll), + MSM_PIN_FUNCTION(emac0_mcg0), + MSM_PIN_FUNCTION(emac0_mcg1), + MSM_PIN_FUNCTION(emac0_mcg2), + MSM_PIN_FUNCTION(emac0_mcg3), + MSM_PIN_FUNCTION(emac0_phy), + MSM_PIN_FUNCTION(emac0_ptp), + MSM_PIN_FUNCTION(emac1_dll0), + MSM_PIN_FUNCTION(emac1_dll1), + MSM_PIN_FUNCTION(emac1_mcg0), + MSM_PIN_FUNCTION(emac1_mcg1), + MSM_PIN_FUNCTION(emac1_mcg2), + MSM_PIN_FUNCTION(emac1_mcg3), + MSM_PIN_FUNCTION(emac1_phy), + MSM_PIN_FUNCTION(emac1_ptp), + MSM_PIN_FUNCTION(gcc_gp1), + MSM_PIN_FUNCTION(gcc_gp2), + MSM_PIN_FUNCTION(gcc_gp3), + MSM_PIN_FUNCTION(gcc_gp4), + MSM_PIN_FUNCTION(gcc_gp5), + MSM_PIN_FUNCTION(gpio), + MSM_PIN_FUNCTION(hs1_mi2s), + MSM_PIN_FUNCTION(hs2_mi2s), + MSM_PIN_FUNCTION(hs3_mi2s), + MSM_PIN_FUNCTION(ibi_i3c), + MSM_PIN_FUNCTION(jitter_bist), + MSM_PIN_FUNCTION(lpass_slimbus), + MSM_PIN_FUNCTION(mdp0_vsync0), + MSM_PIN_FUNCTION(mdp0_vsync1), + MSM_PIN_FUNCTION(mdp0_vsync2), + MSM_PIN_FUNCTION(mdp0_vsync3), + MSM_PIN_FUNCTION(mdp0_vsync4), + MSM_PIN_FUNCTION(mdp0_vsync5), + MSM_PIN_FUNCTION(mdp0_vsync6), + MSM_PIN_FUNCTION(mdp0_vsync7), + MSM_PIN_FUNCTION(mdp0_vsync8), + MSM_PIN_FUNCTION(mdp1_vsync0), + MSM_PIN_FUNCTION(mdp1_vsync1), + MSM_PIN_FUNCTION(mdp1_vsync2), + MSM_PIN_FUNCTION(mdp1_vsync3), + MSM_PIN_FUNCTION(mdp1_vsync4), + MSM_PIN_FUNCTION(mdp1_vsync5), + MSM_PIN_FUNCTION(mdp1_vsync6), + MSM_PIN_FUNCTION(mdp1_vsync7), + MSM_PIN_FUNCTION(mdp1_vsync8), + MSM_PIN_FUNCTION(mdp_vsync), + MSM_PIN_FUNCTION(mi2s0_data0), + MSM_PIN_FUNCTION(mi2s0_data1), + MSM_PIN_FUNCTION(mi2s0_sck), + MSM_PIN_FUNCTION(mi2s0_ws), + MSM_PIN_FUNCTION(mi2s1_data0), + MSM_PIN_FUNCTION(mi2s1_data1), + MSM_PIN_FUNCTION(mi2s1_sck), + MSM_PIN_FUNCTION(mi2s1_ws), + MSM_PIN_FUNCTION(mi2s2_data0), + MSM_PIN_FUNCTION(mi2s2_data1), + MSM_PIN_FUNCTION(mi2s2_sck), + MSM_PIN_FUNCTION(mi2s2_ws), + MSM_PIN_FUNCTION(mi2s_mclk1), + MSM_PIN_FUNCTION(mi2s_mclk2), + MSM_PIN_FUNCTION(pcie2a_clkreq), + MSM_PIN_FUNCTION(pcie2b_clkreq), + MSM_PIN_FUNCTION(pcie3a_clkreq), + MSM_PIN_FUNCTION(pcie3b_clkreq), + MSM_PIN_FUNCTION(pcie4_clkreq), + MSM_PIN_FUNCTION(phase_flag), + MSM_PIN_FUNCTION(pll_bist), + MSM_PIN_FUNCTION(pll_clk), + MSM_PIN_FUNCTION(prng_rosc0), + MSM_PIN_FUNCTION(prng_rosc1), + MSM_PIN_FUNCTION(prng_rosc2), + MSM_PIN_FUNCTION(prng_rosc3), + MSM_PIN_FUNCTION(qdss_cti), + MSM_PIN_FUNCTION(qdss_gpio), + MSM_PIN_FUNCTION(qspi), + MSM_PIN_FUNCTION(qspi_clk), + MSM_PIN_FUNCTION(qspi_cs), + MSM_PIN_FUNCTION(qup0), + MSM_PIN_FUNCTION(qup1), + MSM_PIN_FUNCTION(qup2), + MSM_PIN_FUNCTION(qup3), + MSM_PIN_FUNCTION(qup4), + MSM_PIN_FUNCTION(qup5), + MSM_PIN_FUNCTION(qup6), + MSM_PIN_FUNCTION(qup7), + MSM_PIN_FUNCTION(qup8), + MSM_PIN_FUNCTION(qup9), + MSM_PIN_FUNCTION(qup10), + MSM_PIN_FUNCTION(qup11), + MSM_PIN_FUNCTION(qup12), + MSM_PIN_FUNCTION(qup13), + MSM_PIN_FUNCTION(qup14), + MSM_PIN_FUNCTION(qup15), + MSM_PIN_FUNCTION(qup16), + MSM_PIN_FUNCTION(qup17), + MSM_PIN_FUNCTION(qup18), + MSM_PIN_FUNCTION(qup19), + MSM_PIN_FUNCTION(qup20), + MSM_PIN_FUNCTION(qup21), + MSM_PIN_FUNCTION(qup22), + MSM_PIN_FUNCTION(qup23), + MSM_PIN_FUNCTION(rgmii_0), + MSM_PIN_FUNCTION(rgmii_1), + MSM_PIN_FUNCTION(sd_write), + MSM_PIN_FUNCTION(sdc40), + MSM_PIN_FUNCTION(sdc42), + MSM_PIN_FUNCTION(sdc43), + MSM_PIN_FUNCTION(sdc4_clk), + MSM_PIN_FUNCTION(sdc4_cmd), + MSM_PIN_FUNCTION(tb_trig), + MSM_PIN_FUNCTION(tgu), + MSM_PIN_FUNCTION(tsense_pwm1), + MSM_PIN_FUNCTION(tsense_pwm2), + MSM_PIN_FUNCTION(tsense_pwm3), + MSM_PIN_FUNCTION(tsense_pwm4), + MSM_PIN_FUNCTION(usb0_dp), + MSM_PIN_FUNCTION(usb0_phy), + MSM_PIN_FUNCTION(usb0_sbrx), + MSM_PIN_FUNCTION(usb0_sbtx), + MSM_PIN_FUNCTION(usb0_usb4), + MSM_PIN_FUNCTION(usb1_dp), + MSM_PIN_FUNCTION(usb1_phy), + MSM_PIN_FUNCTION(usb1_sbrx), + MSM_PIN_FUNCTION(usb1_sbtx), + MSM_PIN_FUNCTION(usb1_usb4), + MSM_PIN_FUNCTION(usb2phy_ac), + MSM_PIN_FUNCTION(vsense_trigger), }; static const struct msm_pingroup sc8280xp_groups[] = { diff --git a/drivers/pinctrl/qcom/pinctrl-sdm660.c b/drivers/pinctrl/qcom/pinctrl-sdm660.c index 1bfb0ae6b387967001b147ff99fc3e63975fafec..c2e0d5c034acf6af28fe267175c705ae25391672 100644 --- a/drivers/pinctrl/qcom/pinctrl-sdm660.c +++ b/drivers/pinctrl/qcom/pinctrl-sdm660.c @@ -7,7 +7,6 @@ #include #include #include -#include #include "pinctrl-msm.h" @@ -25,19 +24,11 @@ enum { #define REG_SIZE 0x1000 -#define FUNCTION(fname) \ - [msm_mux_##fname] = { \ - .name = #fname, \ - .groups = fname##_groups, \ - .ngroups = ARRAY_SIZE(fname##_groups), \ - } - - #define PINGROUP(id, _tile, f1, f2, f3, f4, f5, f6, f7, f8, f9) \ { \ - .name = "gpio" #id, \ - .pins = gpio##id##_pins, \ - .npins = (unsigned)ARRAY_SIZE(gpio##id##_pins), \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ .funcs = (int[]){ \ msm_mux_gpio, /* gpio mode */ \ msm_mux_##f1, \ @@ -75,9 +66,9 @@ enum { #define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = (unsigned)ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = ctl, \ .io_reg = 0, \ .intr_cfg_reg = 0, \ @@ -1099,189 +1090,189 @@ static const char * const wlan2_adc1_groups[] = { "gpio10", }; -static const struct msm_function sdm660_functions[] = { - FUNCTION(adsp_ext), - FUNCTION(agera_pll), - FUNCTION(atest_char), - FUNCTION(atest_char0), - FUNCTION(atest_char1), - FUNCTION(atest_char2), - FUNCTION(atest_char3), - FUNCTION(atest_gpsadc0), - FUNCTION(atest_gpsadc1), - FUNCTION(atest_tsens), - FUNCTION(atest_tsens2), - FUNCTION(atest_usb1), - FUNCTION(atest_usb10), - FUNCTION(atest_usb11), - FUNCTION(atest_usb12), - FUNCTION(atest_usb13), - FUNCTION(atest_usb2), - FUNCTION(atest_usb20), - FUNCTION(atest_usb21), - FUNCTION(atest_usb22), - FUNCTION(atest_usb23), - FUNCTION(audio_ref), - FUNCTION(bimc_dte0), - FUNCTION(bimc_dte1), - FUNCTION(blsp_i2c1), - FUNCTION(blsp_i2c2), - FUNCTION(blsp_i2c3), - FUNCTION(blsp_i2c4), - FUNCTION(blsp_i2c5), - FUNCTION(blsp_i2c6), - FUNCTION(blsp_i2c7), - FUNCTION(blsp_i2c8_a), - FUNCTION(blsp_i2c8_b), - FUNCTION(blsp_spi1), - FUNCTION(blsp_spi2), - FUNCTION(blsp_spi3), - FUNCTION(blsp_spi3_cs1), - FUNCTION(blsp_spi3_cs2), - FUNCTION(blsp_spi4), - FUNCTION(blsp_spi5), - FUNCTION(blsp_spi6), - FUNCTION(blsp_spi7), - FUNCTION(blsp_spi8_a), - FUNCTION(blsp_spi8_b), - FUNCTION(blsp_spi8_cs1), - FUNCTION(blsp_spi8_cs2), - FUNCTION(blsp_uart1), - FUNCTION(blsp_uart2), - FUNCTION(blsp_uart5), - FUNCTION(blsp_uart6_a), - FUNCTION(blsp_uart6_b), - FUNCTION(blsp_uim1), - FUNCTION(blsp_uim2), - FUNCTION(blsp_uim5), - FUNCTION(blsp_uim6), - FUNCTION(cam_mclk), - FUNCTION(cci_async), - FUNCTION(cci_i2c), - FUNCTION(cri_trng), - FUNCTION(cri_trng0), - FUNCTION(cri_trng1), - FUNCTION(dbg_out), - FUNCTION(ddr_bist), - FUNCTION(gcc_gp1), - FUNCTION(gcc_gp2), - FUNCTION(gcc_gp3), - FUNCTION(gpio), - FUNCTION(gps_tx_a), - FUNCTION(gps_tx_b), - FUNCTION(gps_tx_c), - FUNCTION(isense_dbg), - FUNCTION(jitter_bist), - FUNCTION(ldo_en), - FUNCTION(ldo_update), - FUNCTION(m_voc), - FUNCTION(mdp_vsync), - FUNCTION(mdss_vsync0), - FUNCTION(mdss_vsync1), - FUNCTION(mdss_vsync2), - FUNCTION(mdss_vsync3), - FUNCTION(mss_lte), - FUNCTION(nav_pps_a), - FUNCTION(nav_pps_b), - FUNCTION(nav_pps_c), - FUNCTION(pa_indicator), - FUNCTION(phase_flag0), - FUNCTION(phase_flag1), - FUNCTION(phase_flag2), - FUNCTION(phase_flag3), - FUNCTION(phase_flag4), - FUNCTION(phase_flag5), - FUNCTION(phase_flag6), - FUNCTION(phase_flag7), - FUNCTION(phase_flag8), - FUNCTION(phase_flag9), - FUNCTION(phase_flag10), - FUNCTION(phase_flag11), - FUNCTION(phase_flag12), - FUNCTION(phase_flag13), - FUNCTION(phase_flag14), - FUNCTION(phase_flag15), - FUNCTION(phase_flag16), - FUNCTION(phase_flag17), - FUNCTION(phase_flag18), - FUNCTION(phase_flag19), - FUNCTION(phase_flag20), - FUNCTION(phase_flag21), - FUNCTION(phase_flag22), - FUNCTION(phase_flag23), - FUNCTION(phase_flag24), - FUNCTION(phase_flag25), - FUNCTION(phase_flag26), - FUNCTION(phase_flag27), - FUNCTION(phase_flag28), - FUNCTION(phase_flag29), - FUNCTION(phase_flag30), - FUNCTION(phase_flag31), - FUNCTION(pll_bypassnl), - FUNCTION(pll_reset), - FUNCTION(pri_mi2s), - FUNCTION(pri_mi2s_ws), - FUNCTION(prng_rosc), - FUNCTION(pwr_crypto), - FUNCTION(pwr_modem), - FUNCTION(pwr_nav), - FUNCTION(qdss_cti0_a), - FUNCTION(qdss_cti0_b), - FUNCTION(qdss_cti1_a), - FUNCTION(qdss_cti1_b), - FUNCTION(qdss_gpio), - FUNCTION(qdss_gpio0), - FUNCTION(qdss_gpio1), - FUNCTION(qdss_gpio10), - FUNCTION(qdss_gpio11), - FUNCTION(qdss_gpio12), - FUNCTION(qdss_gpio13), - FUNCTION(qdss_gpio14), - FUNCTION(qdss_gpio15), - FUNCTION(qdss_gpio2), - FUNCTION(qdss_gpio3), - FUNCTION(qdss_gpio4), - FUNCTION(qdss_gpio5), - FUNCTION(qdss_gpio6), - FUNCTION(qdss_gpio7), - FUNCTION(qdss_gpio8), - FUNCTION(qdss_gpio9), - FUNCTION(qlink_enable), - FUNCTION(qlink_request), - FUNCTION(qspi_clk), - FUNCTION(qspi_cs), - FUNCTION(qspi_data0), - FUNCTION(qspi_data1), - FUNCTION(qspi_data2), - FUNCTION(qspi_data3), - FUNCTION(qspi_resetn), - FUNCTION(sec_mi2s), - FUNCTION(sndwire_clk), - FUNCTION(sndwire_data), - FUNCTION(sp_cmu), - FUNCTION(ssc_irq), - FUNCTION(tgu_ch0), - FUNCTION(tgu_ch1), - FUNCTION(tsense_pwm1), - FUNCTION(tsense_pwm2), - FUNCTION(uim1_clk), - FUNCTION(uim1_data), - FUNCTION(uim1_present), - FUNCTION(uim1_reset), - FUNCTION(uim2_clk), - FUNCTION(uim2_data), - FUNCTION(uim2_present), - FUNCTION(uim2_reset), - FUNCTION(uim_batt), - FUNCTION(vfr_1), - FUNCTION(vsense_clkout), - FUNCTION(vsense_data0), - FUNCTION(vsense_data1), - FUNCTION(vsense_mode), - FUNCTION(wlan1_adc0), - FUNCTION(wlan1_adc1), - FUNCTION(wlan2_adc0), - FUNCTION(wlan2_adc1), +static const struct pinfunction sdm660_functions[] = { + MSM_PIN_FUNCTION(adsp_ext), + MSM_PIN_FUNCTION(agera_pll), + MSM_PIN_FUNCTION(atest_char), + MSM_PIN_FUNCTION(atest_char0), + MSM_PIN_FUNCTION(atest_char1), + MSM_PIN_FUNCTION(atest_char2), + MSM_PIN_FUNCTION(atest_char3), + MSM_PIN_FUNCTION(atest_gpsadc0), + MSM_PIN_FUNCTION(atest_gpsadc1), + MSM_PIN_FUNCTION(atest_tsens), + MSM_PIN_FUNCTION(atest_tsens2), + MSM_PIN_FUNCTION(atest_usb1), + MSM_PIN_FUNCTION(atest_usb10), + MSM_PIN_FUNCTION(atest_usb11), + MSM_PIN_FUNCTION(atest_usb12), + MSM_PIN_FUNCTION(atest_usb13), + MSM_PIN_FUNCTION(atest_usb2), + MSM_PIN_FUNCTION(atest_usb20), + MSM_PIN_FUNCTION(atest_usb21), + MSM_PIN_FUNCTION(atest_usb22), + MSM_PIN_FUNCTION(atest_usb23), + MSM_PIN_FUNCTION(audio_ref), + MSM_PIN_FUNCTION(bimc_dte0), + MSM_PIN_FUNCTION(bimc_dte1), + MSM_PIN_FUNCTION(blsp_i2c1), + MSM_PIN_FUNCTION(blsp_i2c2), + MSM_PIN_FUNCTION(blsp_i2c3), + MSM_PIN_FUNCTION(blsp_i2c4), + MSM_PIN_FUNCTION(blsp_i2c5), + MSM_PIN_FUNCTION(blsp_i2c6), + MSM_PIN_FUNCTION(blsp_i2c7), + MSM_PIN_FUNCTION(blsp_i2c8_a), + MSM_PIN_FUNCTION(blsp_i2c8_b), + MSM_PIN_FUNCTION(blsp_spi1), + MSM_PIN_FUNCTION(blsp_spi2), + MSM_PIN_FUNCTION(blsp_spi3), + MSM_PIN_FUNCTION(blsp_spi3_cs1), + MSM_PIN_FUNCTION(blsp_spi3_cs2), + MSM_PIN_FUNCTION(blsp_spi4), + MSM_PIN_FUNCTION(blsp_spi5), + MSM_PIN_FUNCTION(blsp_spi6), + MSM_PIN_FUNCTION(blsp_spi7), + MSM_PIN_FUNCTION(blsp_spi8_a), + MSM_PIN_FUNCTION(blsp_spi8_b), + MSM_PIN_FUNCTION(blsp_spi8_cs1), + MSM_PIN_FUNCTION(blsp_spi8_cs2), + MSM_PIN_FUNCTION(blsp_uart1), + MSM_PIN_FUNCTION(blsp_uart2), + MSM_PIN_FUNCTION(blsp_uart5), + MSM_PIN_FUNCTION(blsp_uart6_a), + MSM_PIN_FUNCTION(blsp_uart6_b), + MSM_PIN_FUNCTION(blsp_uim1), + MSM_PIN_FUNCTION(blsp_uim2), + MSM_PIN_FUNCTION(blsp_uim5), + MSM_PIN_FUNCTION(blsp_uim6), + MSM_PIN_FUNCTION(cam_mclk), + MSM_PIN_FUNCTION(cci_async), + MSM_PIN_FUNCTION(cci_i2c), + MSM_PIN_FUNCTION(cri_trng), + MSM_PIN_FUNCTION(cri_trng0), + MSM_PIN_FUNCTION(cri_trng1), + MSM_PIN_FUNCTION(dbg_out), + MSM_PIN_FUNCTION(ddr_bist), + MSM_PIN_FUNCTION(gcc_gp1), + MSM_PIN_FUNCTION(gcc_gp2), + MSM_PIN_FUNCTION(gcc_gp3), + MSM_PIN_FUNCTION(gpio), + MSM_PIN_FUNCTION(gps_tx_a), + MSM_PIN_FUNCTION(gps_tx_b), + MSM_PIN_FUNCTION(gps_tx_c), + MSM_PIN_FUNCTION(isense_dbg), + MSM_PIN_FUNCTION(jitter_bist), + MSM_PIN_FUNCTION(ldo_en), + MSM_PIN_FUNCTION(ldo_update), + MSM_PIN_FUNCTION(m_voc), + MSM_PIN_FUNCTION(mdp_vsync), + MSM_PIN_FUNCTION(mdss_vsync0), + MSM_PIN_FUNCTION(mdss_vsync1), + MSM_PIN_FUNCTION(mdss_vsync2), + MSM_PIN_FUNCTION(mdss_vsync3), + MSM_PIN_FUNCTION(mss_lte), + MSM_PIN_FUNCTION(nav_pps_a), + MSM_PIN_FUNCTION(nav_pps_b), + MSM_PIN_FUNCTION(nav_pps_c), + MSM_PIN_FUNCTION(pa_indicator), + MSM_PIN_FUNCTION(phase_flag0), + MSM_PIN_FUNCTION(phase_flag1), + MSM_PIN_FUNCTION(phase_flag2), + MSM_PIN_FUNCTION(phase_flag3), + MSM_PIN_FUNCTION(phase_flag4), + MSM_PIN_FUNCTION(phase_flag5), + MSM_PIN_FUNCTION(phase_flag6), + MSM_PIN_FUNCTION(phase_flag7), + MSM_PIN_FUNCTION(phase_flag8), + MSM_PIN_FUNCTION(phase_flag9), + MSM_PIN_FUNCTION(phase_flag10), + MSM_PIN_FUNCTION(phase_flag11), + MSM_PIN_FUNCTION(phase_flag12), + MSM_PIN_FUNCTION(phase_flag13), + MSM_PIN_FUNCTION(phase_flag14), + MSM_PIN_FUNCTION(phase_flag15), + MSM_PIN_FUNCTION(phase_flag16), + MSM_PIN_FUNCTION(phase_flag17), + MSM_PIN_FUNCTION(phase_flag18), + MSM_PIN_FUNCTION(phase_flag19), + MSM_PIN_FUNCTION(phase_flag20), + MSM_PIN_FUNCTION(phase_flag21), + MSM_PIN_FUNCTION(phase_flag22), + MSM_PIN_FUNCTION(phase_flag23), + MSM_PIN_FUNCTION(phase_flag24), + MSM_PIN_FUNCTION(phase_flag25), + MSM_PIN_FUNCTION(phase_flag26), + MSM_PIN_FUNCTION(phase_flag27), + MSM_PIN_FUNCTION(phase_flag28), + MSM_PIN_FUNCTION(phase_flag29), + MSM_PIN_FUNCTION(phase_flag30), + MSM_PIN_FUNCTION(phase_flag31), + MSM_PIN_FUNCTION(pll_bypassnl), + MSM_PIN_FUNCTION(pll_reset), + MSM_PIN_FUNCTION(pri_mi2s), + MSM_PIN_FUNCTION(pri_mi2s_ws), + MSM_PIN_FUNCTION(prng_rosc), + MSM_PIN_FUNCTION(pwr_crypto), + MSM_PIN_FUNCTION(pwr_modem), + MSM_PIN_FUNCTION(pwr_nav), + MSM_PIN_FUNCTION(qdss_cti0_a), + MSM_PIN_FUNCTION(qdss_cti0_b), + MSM_PIN_FUNCTION(qdss_cti1_a), + MSM_PIN_FUNCTION(qdss_cti1_b), + MSM_PIN_FUNCTION(qdss_gpio), + MSM_PIN_FUNCTION(qdss_gpio0), + MSM_PIN_FUNCTION(qdss_gpio1), + MSM_PIN_FUNCTION(qdss_gpio10), + MSM_PIN_FUNCTION(qdss_gpio11), + MSM_PIN_FUNCTION(qdss_gpio12), + MSM_PIN_FUNCTION(qdss_gpio13), + MSM_PIN_FUNCTION(qdss_gpio14), + MSM_PIN_FUNCTION(qdss_gpio15), + MSM_PIN_FUNCTION(qdss_gpio2), + MSM_PIN_FUNCTION(qdss_gpio3), + MSM_PIN_FUNCTION(qdss_gpio4), + MSM_PIN_FUNCTION(qdss_gpio5), + MSM_PIN_FUNCTION(qdss_gpio6), + MSM_PIN_FUNCTION(qdss_gpio7), + MSM_PIN_FUNCTION(qdss_gpio8), + MSM_PIN_FUNCTION(qdss_gpio9), + MSM_PIN_FUNCTION(qlink_enable), + MSM_PIN_FUNCTION(qlink_request), + MSM_PIN_FUNCTION(qspi_clk), + MSM_PIN_FUNCTION(qspi_cs), + MSM_PIN_FUNCTION(qspi_data0), + MSM_PIN_FUNCTION(qspi_data1), + MSM_PIN_FUNCTION(qspi_data2), + MSM_PIN_FUNCTION(qspi_data3), + MSM_PIN_FUNCTION(qspi_resetn), + MSM_PIN_FUNCTION(sec_mi2s), + MSM_PIN_FUNCTION(sndwire_clk), + MSM_PIN_FUNCTION(sndwire_data), + MSM_PIN_FUNCTION(sp_cmu), + MSM_PIN_FUNCTION(ssc_irq), + MSM_PIN_FUNCTION(tgu_ch0), + MSM_PIN_FUNCTION(tgu_ch1), + MSM_PIN_FUNCTION(tsense_pwm1), + MSM_PIN_FUNCTION(tsense_pwm2), + MSM_PIN_FUNCTION(uim1_clk), + MSM_PIN_FUNCTION(uim1_data), + MSM_PIN_FUNCTION(uim1_present), + MSM_PIN_FUNCTION(uim1_reset), + MSM_PIN_FUNCTION(uim2_clk), + MSM_PIN_FUNCTION(uim2_data), + MSM_PIN_FUNCTION(uim2_present), + MSM_PIN_FUNCTION(uim2_reset), + MSM_PIN_FUNCTION(uim_batt), + MSM_PIN_FUNCTION(vfr_1), + MSM_PIN_FUNCTION(vsense_clkout), + MSM_PIN_FUNCTION(vsense_data0), + MSM_PIN_FUNCTION(vsense_data1), + MSM_PIN_FUNCTION(vsense_mode), + MSM_PIN_FUNCTION(wlan1_adc0), + MSM_PIN_FUNCTION(wlan1_adc1), + MSM_PIN_FUNCTION(wlan2_adc0), + MSM_PIN_FUNCTION(wlan2_adc1), }; static const struct msm_pingroup sdm660_groups[] = { diff --git a/drivers/pinctrl/qcom/pinctrl-sdm670.c b/drivers/pinctrl/qcom/pinctrl-sdm670.c index b888bca7ecd7b93af7ec74fb3859f8230d958b0a..cc3cce077de4e61934a114c263ebd1fd96432dfb 100644 --- a/drivers/pinctrl/qcom/pinctrl-sdm670.c +++ b/drivers/pinctrl/qcom/pinctrl-sdm670.c @@ -7,17 +7,9 @@ #include #include #include -#include #include "pinctrl-msm.h" -#define FUNCTION(fname) \ - [msm_mux_##fname] = { \ - .name = #fname, \ - .groups = fname##_groups, \ - .ngroups = ARRAY_SIZE(fname##_groups), \ - } - #define NORTH 0x00500000 #define SOUTH 0x00900000 #define WEST 0x00100000 @@ -25,9 +17,9 @@ #define REG_SIZE 0x1000 #define PINGROUP(id, base, f1, f2, f3, f4, f5, f6, f7, f8, f9) \ { \ - .name = "gpio" #id, \ - .pins = gpio##id##_pins, \ - .npins = ARRAY_SIZE(gpio##id##_pins), \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ .funcs = (int[]){ \ msm_mux_gpio, /* gpio mode */ \ msm_mux_##f1, \ @@ -68,9 +60,9 @@ */ #define PINGROUP_DUMMY(id) \ { \ - .name = "gpio" #id, \ - .pins = gpio##id##_pins, \ - .npins = ARRAY_SIZE(gpio##id##_pins), \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ .ctl_reg = 0, \ .io_reg = 0, \ .intr_cfg_reg = 0, \ @@ -93,9 +85,9 @@ #define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = ctl, \ .io_reg = 0, \ .intr_cfg_reg = 0, \ @@ -118,9 +110,9 @@ #define UFS_RESET(pg_name, offset) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = offset, \ .io_reg = offset + 0x4, \ .intr_cfg_reg = 0, \ @@ -998,132 +990,132 @@ static const char * const mss_lte_groups[] = { "gpio144", "gpio145", }; -static const struct msm_function sdm670_functions[] = { - FUNCTION(gpio), - FUNCTION(adsp_ext), - FUNCTION(agera_pll), - FUNCTION(atest_char), - FUNCTION(atest_tsens), - FUNCTION(atest_tsens2), - FUNCTION(atest_usb1), - FUNCTION(atest_usb10), - FUNCTION(atest_usb11), - FUNCTION(atest_usb12), - FUNCTION(atest_usb13), - FUNCTION(atest_usb2), - FUNCTION(atest_usb20), - FUNCTION(atest_usb21), - FUNCTION(atest_usb22), - FUNCTION(atest_usb23), - FUNCTION(cam_mclk), - FUNCTION(cci_async), - FUNCTION(cci_i2c), - FUNCTION(cci_timer0), - FUNCTION(cci_timer1), - FUNCTION(cci_timer2), - FUNCTION(cci_timer3), - FUNCTION(cci_timer4), - FUNCTION(copy_gp), - FUNCTION(copy_phase), - FUNCTION(dbg_out), - FUNCTION(ddr_bist), - FUNCTION(ddr_pxi0), - FUNCTION(ddr_pxi1), - FUNCTION(ddr_pxi2), - FUNCTION(ddr_pxi3), - FUNCTION(edp_hot), - FUNCTION(edp_lcd), - FUNCTION(gcc_gp1), - FUNCTION(gcc_gp2), - FUNCTION(gcc_gp3), - FUNCTION(gp_pdm0), - FUNCTION(gp_pdm1), - FUNCTION(gp_pdm2), - FUNCTION(gps_tx), - FUNCTION(jitter_bist), - FUNCTION(ldo_en), - FUNCTION(ldo_update), - FUNCTION(lpass_slimbus), - FUNCTION(m_voc), - FUNCTION(mdp_vsync), - FUNCTION(mdp_vsync0), - FUNCTION(mdp_vsync1), - FUNCTION(mdp_vsync2), - FUNCTION(mdp_vsync3), - FUNCTION(mss_lte), - FUNCTION(nav_pps), - FUNCTION(pa_indicator), - FUNCTION(pci_e0), - FUNCTION(pci_e1), - FUNCTION(phase_flag), - FUNCTION(pll_bist), - FUNCTION(pll_bypassnl), - FUNCTION(pll_reset), - FUNCTION(pri_mi2s), - FUNCTION(pri_mi2s_ws), - FUNCTION(prng_rosc), - FUNCTION(qdss_cti), - FUNCTION(qdss), - FUNCTION(qlink_enable), - FUNCTION(qlink_request), - FUNCTION(qua_mi2s), - FUNCTION(qup0), - FUNCTION(qup1), - FUNCTION(qup10), - FUNCTION(qup11), - FUNCTION(qup12), - FUNCTION(qup13), - FUNCTION(qup14), - FUNCTION(qup15), - FUNCTION(qup2), - FUNCTION(qup3), - FUNCTION(qup4), - FUNCTION(qup5), - FUNCTION(qup6), - FUNCTION(qup7), - FUNCTION(qup8), - FUNCTION(qup9), - FUNCTION(qup_l4), - FUNCTION(qup_l5), - FUNCTION(qup_l6), - FUNCTION(sdc4_clk), - FUNCTION(sdc4_cmd), - FUNCTION(sdc4_data), - FUNCTION(sd_write), - FUNCTION(sec_mi2s), - FUNCTION(ter_mi2s), - FUNCTION(tgu_ch0), - FUNCTION(tgu_ch1), - FUNCTION(tgu_ch2), - FUNCTION(tgu_ch3), - FUNCTION(tsif1_clk), - FUNCTION(tsif1_data), - FUNCTION(tsif1_en), - FUNCTION(tsif1_error), - FUNCTION(tsif1_sync), - FUNCTION(tsif2_clk), - FUNCTION(tsif2_data), - FUNCTION(tsif2_en), - FUNCTION(tsif2_error), - FUNCTION(tsif2_sync), - FUNCTION(uim1_clk), - FUNCTION(uim1_data), - FUNCTION(uim1_present), - FUNCTION(uim1_reset), - FUNCTION(uim2_clk), - FUNCTION(uim2_data), - FUNCTION(uim2_present), - FUNCTION(uim2_reset), - FUNCTION(uim_batt), - FUNCTION(usb_phy), - FUNCTION(vfr_1), - FUNCTION(vsense_trigger), - FUNCTION(wlan1_adc0), - FUNCTION(wlan1_adc1), - FUNCTION(wlan2_adc0), - FUNCTION(wlan2_adc1), - FUNCTION(wsa_clk), - FUNCTION(wsa_data), +static const struct pinfunction sdm670_functions[] = { + MSM_PIN_FUNCTION(gpio), + MSM_PIN_FUNCTION(adsp_ext), + MSM_PIN_FUNCTION(agera_pll), + MSM_PIN_FUNCTION(atest_char), + MSM_PIN_FUNCTION(atest_tsens), + MSM_PIN_FUNCTION(atest_tsens2), + MSM_PIN_FUNCTION(atest_usb1), + MSM_PIN_FUNCTION(atest_usb10), + MSM_PIN_FUNCTION(atest_usb11), + MSM_PIN_FUNCTION(atest_usb12), + MSM_PIN_FUNCTION(atest_usb13), + MSM_PIN_FUNCTION(atest_usb2), + MSM_PIN_FUNCTION(atest_usb20), + MSM_PIN_FUNCTION(atest_usb21), + MSM_PIN_FUNCTION(atest_usb22), + MSM_PIN_FUNCTION(atest_usb23), + MSM_PIN_FUNCTION(cam_mclk), + MSM_PIN_FUNCTION(cci_async), + MSM_PIN_FUNCTION(cci_i2c), + MSM_PIN_FUNCTION(cci_timer0), + MSM_PIN_FUNCTION(cci_timer1), + MSM_PIN_FUNCTION(cci_timer2), + MSM_PIN_FUNCTION(cci_timer3), + MSM_PIN_FUNCTION(cci_timer4), + MSM_PIN_FUNCTION(copy_gp), + MSM_PIN_FUNCTION(copy_phase), + MSM_PIN_FUNCTION(dbg_out), + MSM_PIN_FUNCTION(ddr_bist), + MSM_PIN_FUNCTION(ddr_pxi0), + MSM_PIN_FUNCTION(ddr_pxi1), + MSM_PIN_FUNCTION(ddr_pxi2), + MSM_PIN_FUNCTION(ddr_pxi3), + MSM_PIN_FUNCTION(edp_hot), + MSM_PIN_FUNCTION(edp_lcd), + MSM_PIN_FUNCTION(gcc_gp1), + MSM_PIN_FUNCTION(gcc_gp2), + MSM_PIN_FUNCTION(gcc_gp3), + MSM_PIN_FUNCTION(gp_pdm0), + MSM_PIN_FUNCTION(gp_pdm1), + MSM_PIN_FUNCTION(gp_pdm2), + MSM_PIN_FUNCTION(gps_tx), + MSM_PIN_FUNCTION(jitter_bist), + MSM_PIN_FUNCTION(ldo_en), + MSM_PIN_FUNCTION(ldo_update), + MSM_PIN_FUNCTION(lpass_slimbus), + MSM_PIN_FUNCTION(m_voc), + MSM_PIN_FUNCTION(mdp_vsync), + MSM_PIN_FUNCTION(mdp_vsync0), + MSM_PIN_FUNCTION(mdp_vsync1), + MSM_PIN_FUNCTION(mdp_vsync2), + MSM_PIN_FUNCTION(mdp_vsync3), + MSM_PIN_FUNCTION(mss_lte), + MSM_PIN_FUNCTION(nav_pps), + MSM_PIN_FUNCTION(pa_indicator), + MSM_PIN_FUNCTION(pci_e0), + MSM_PIN_FUNCTION(pci_e1), + MSM_PIN_FUNCTION(phase_flag), + MSM_PIN_FUNCTION(pll_bist), + MSM_PIN_FUNCTION(pll_bypassnl), + MSM_PIN_FUNCTION(pll_reset), + MSM_PIN_FUNCTION(pri_mi2s), + MSM_PIN_FUNCTION(pri_mi2s_ws), + MSM_PIN_FUNCTION(prng_rosc), + MSM_PIN_FUNCTION(qdss_cti), + MSM_PIN_FUNCTION(qdss), + MSM_PIN_FUNCTION(qlink_enable), + MSM_PIN_FUNCTION(qlink_request), + MSM_PIN_FUNCTION(qua_mi2s), + MSM_PIN_FUNCTION(qup0), + MSM_PIN_FUNCTION(qup1), + MSM_PIN_FUNCTION(qup10), + MSM_PIN_FUNCTION(qup11), + MSM_PIN_FUNCTION(qup12), + MSM_PIN_FUNCTION(qup13), + MSM_PIN_FUNCTION(qup14), + MSM_PIN_FUNCTION(qup15), + MSM_PIN_FUNCTION(qup2), + MSM_PIN_FUNCTION(qup3), + MSM_PIN_FUNCTION(qup4), + MSM_PIN_FUNCTION(qup5), + MSM_PIN_FUNCTION(qup6), + MSM_PIN_FUNCTION(qup7), + MSM_PIN_FUNCTION(qup8), + MSM_PIN_FUNCTION(qup9), + MSM_PIN_FUNCTION(qup_l4), + MSM_PIN_FUNCTION(qup_l5), + MSM_PIN_FUNCTION(qup_l6), + MSM_PIN_FUNCTION(sdc4_clk), + MSM_PIN_FUNCTION(sdc4_cmd), + MSM_PIN_FUNCTION(sdc4_data), + MSM_PIN_FUNCTION(sd_write), + MSM_PIN_FUNCTION(sec_mi2s), + MSM_PIN_FUNCTION(ter_mi2s), + MSM_PIN_FUNCTION(tgu_ch0), + MSM_PIN_FUNCTION(tgu_ch1), + MSM_PIN_FUNCTION(tgu_ch2), + MSM_PIN_FUNCTION(tgu_ch3), + MSM_PIN_FUNCTION(tsif1_clk), + MSM_PIN_FUNCTION(tsif1_data), + MSM_PIN_FUNCTION(tsif1_en), + MSM_PIN_FUNCTION(tsif1_error), + MSM_PIN_FUNCTION(tsif1_sync), + MSM_PIN_FUNCTION(tsif2_clk), + MSM_PIN_FUNCTION(tsif2_data), + MSM_PIN_FUNCTION(tsif2_en), + MSM_PIN_FUNCTION(tsif2_error), + MSM_PIN_FUNCTION(tsif2_sync), + MSM_PIN_FUNCTION(uim1_clk), + MSM_PIN_FUNCTION(uim1_data), + MSM_PIN_FUNCTION(uim1_present), + MSM_PIN_FUNCTION(uim1_reset), + MSM_PIN_FUNCTION(uim2_clk), + MSM_PIN_FUNCTION(uim2_data), + MSM_PIN_FUNCTION(uim2_present), + MSM_PIN_FUNCTION(uim2_reset), + MSM_PIN_FUNCTION(uim_batt), + MSM_PIN_FUNCTION(usb_phy), + MSM_PIN_FUNCTION(vfr_1), + MSM_PIN_FUNCTION(vsense_trigger), + MSM_PIN_FUNCTION(wlan1_adc0), + MSM_PIN_FUNCTION(wlan1_adc1), + MSM_PIN_FUNCTION(wlan2_adc0), + MSM_PIN_FUNCTION(wlan2_adc1), + MSM_PIN_FUNCTION(wsa_clk), + MSM_PIN_FUNCTION(wsa_data), }; /* diff --git a/drivers/pinctrl/qcom/pinctrl-sdm845.c b/drivers/pinctrl/qcom/pinctrl-sdm845.c index fdfd7b8f3a76d7d66659291bfdb497c1f21a8810..cc05c415ed15512f1f99a598650d3adfdc795a6d 100644 --- a/drivers/pinctrl/qcom/pinctrl-sdm845.c +++ b/drivers/pinctrl/qcom/pinctrl-sdm845.c @@ -7,26 +7,18 @@ #include #include #include -#include #include "pinctrl-msm.h" -#define FUNCTION(fname) \ - [msm_mux_##fname] = { \ - .name = #fname, \ - .groups = fname##_groups, \ - .ngroups = ARRAY_SIZE(fname##_groups), \ - } - #define NORTH 0x00500000 #define SOUTH 0x00900000 #define EAST 0x00100000 #define REG_SIZE 0x1000 #define PINGROUP(id, base, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10) \ { \ - .name = "gpio" #id, \ - .pins = gpio##id##_pins, \ - .npins = ARRAY_SIZE(gpio##id##_pins), \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ .funcs = (int[]){ \ msm_mux_gpio, /* gpio mode */ \ msm_mux_##f1, \ @@ -64,9 +56,9 @@ #define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = ctl, \ .io_reg = 0, \ .intr_cfg_reg = 0, \ @@ -89,9 +81,9 @@ #define UFS_RESET(pg_name, offset) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = offset, \ .io_reg = offset + 0x4, \ .intr_cfg_reg = 0, \ @@ -983,136 +975,136 @@ static const char * const tsif1_sync_groups[] = { "gpio12", }; -static const struct msm_function sdm845_functions[] = { - FUNCTION(gpio), - FUNCTION(adsp_ext), - FUNCTION(agera_pll), - FUNCTION(atest_char), - FUNCTION(atest_tsens), - FUNCTION(atest_tsens2), - FUNCTION(atest_usb1), - FUNCTION(atest_usb10), - FUNCTION(atest_usb11), - FUNCTION(atest_usb12), - FUNCTION(atest_usb13), - FUNCTION(atest_usb2), - FUNCTION(atest_usb20), - FUNCTION(atest_usb21), - FUNCTION(atest_usb22), - FUNCTION(atest_usb23), - FUNCTION(audio_ref), - FUNCTION(btfm_slimbus), - FUNCTION(cam_mclk), - FUNCTION(cci_async), - FUNCTION(cci_i2c), - FUNCTION(cci_timer0), - FUNCTION(cci_timer1), - FUNCTION(cci_timer2), - FUNCTION(cci_timer3), - FUNCTION(cci_timer4), - FUNCTION(cri_trng), - FUNCTION(cri_trng0), - FUNCTION(cri_trng1), - FUNCTION(dbg_out), - FUNCTION(ddr_bist), - FUNCTION(ddr_pxi0), - FUNCTION(ddr_pxi1), - FUNCTION(ddr_pxi2), - FUNCTION(ddr_pxi3), - FUNCTION(edp_hot), - FUNCTION(edp_lcd), - FUNCTION(gcc_gp1), - FUNCTION(gcc_gp2), - FUNCTION(gcc_gp3), - FUNCTION(jitter_bist), - FUNCTION(ldo_en), - FUNCTION(ldo_update), - FUNCTION(lpass_slimbus), - FUNCTION(m_voc), - FUNCTION(mdp_vsync), - FUNCTION(mdp_vsync0), - FUNCTION(mdp_vsync1), - FUNCTION(mdp_vsync2), - FUNCTION(mdp_vsync3), - FUNCTION(mss_lte), - FUNCTION(nav_pps), - FUNCTION(pa_indicator), - FUNCTION(pci_e0), - FUNCTION(pci_e1), - FUNCTION(phase_flag), - FUNCTION(pll_bist), - FUNCTION(pll_bypassnl), - FUNCTION(pll_reset), - FUNCTION(pri_mi2s), - FUNCTION(pri_mi2s_ws), - FUNCTION(prng_rosc), - FUNCTION(qdss_cti), - FUNCTION(qdss), - FUNCTION(qlink_enable), - FUNCTION(qlink_request), - FUNCTION(qspi_clk), - FUNCTION(qspi_cs), - FUNCTION(qspi_data), - FUNCTION(qua_mi2s), - FUNCTION(qup0), - FUNCTION(qup1), - FUNCTION(qup10), - FUNCTION(qup11), - FUNCTION(qup12), - FUNCTION(qup13), - FUNCTION(qup14), - FUNCTION(qup15), - FUNCTION(qup2), - FUNCTION(qup3), - FUNCTION(qup4), - FUNCTION(qup5), - FUNCTION(qup6), - FUNCTION(qup7), - FUNCTION(qup8), - FUNCTION(qup9), - FUNCTION(qup_l4), - FUNCTION(qup_l5), - FUNCTION(qup_l6), - FUNCTION(sd_write), - FUNCTION(sdc4_clk), - FUNCTION(sdc4_cmd), - FUNCTION(sdc4_data), - FUNCTION(sec_mi2s), - FUNCTION(sp_cmu), - FUNCTION(spkr_i2s), - FUNCTION(ter_mi2s), - FUNCTION(tgu_ch0), - FUNCTION(tgu_ch1), - FUNCTION(tgu_ch2), - FUNCTION(tgu_ch3), - FUNCTION(tsense_pwm1), - FUNCTION(tsense_pwm2), - FUNCTION(tsif1_clk), - FUNCTION(tsif1_data), - FUNCTION(tsif1_en), - FUNCTION(tsif1_error), - FUNCTION(tsif1_sync), - FUNCTION(tsif2_clk), - FUNCTION(tsif2_data), - FUNCTION(tsif2_en), - FUNCTION(tsif2_error), - FUNCTION(tsif2_sync), - FUNCTION(uim1_clk), - FUNCTION(uim1_data), - FUNCTION(uim1_present), - FUNCTION(uim1_reset), - FUNCTION(uim2_clk), - FUNCTION(uim2_data), - FUNCTION(uim2_present), - FUNCTION(uim2_reset), - FUNCTION(uim_batt), - FUNCTION(usb_phy), - FUNCTION(vfr_1), - FUNCTION(vsense_trigger), - FUNCTION(wlan1_adc0), - FUNCTION(wlan1_adc1), - FUNCTION(wlan2_adc0), - FUNCTION(wlan2_adc1), +static const struct pinfunction sdm845_functions[] = { + MSM_PIN_FUNCTION(gpio), + MSM_PIN_FUNCTION(adsp_ext), + MSM_PIN_FUNCTION(agera_pll), + MSM_PIN_FUNCTION(atest_char), + MSM_PIN_FUNCTION(atest_tsens), + MSM_PIN_FUNCTION(atest_tsens2), + MSM_PIN_FUNCTION(atest_usb1), + MSM_PIN_FUNCTION(atest_usb10), + MSM_PIN_FUNCTION(atest_usb11), + MSM_PIN_FUNCTION(atest_usb12), + MSM_PIN_FUNCTION(atest_usb13), + MSM_PIN_FUNCTION(atest_usb2), + MSM_PIN_FUNCTION(atest_usb20), + MSM_PIN_FUNCTION(atest_usb21), + MSM_PIN_FUNCTION(atest_usb22), + MSM_PIN_FUNCTION(atest_usb23), + MSM_PIN_FUNCTION(audio_ref), + MSM_PIN_FUNCTION(btfm_slimbus), + MSM_PIN_FUNCTION(cam_mclk), + MSM_PIN_FUNCTION(cci_async), + MSM_PIN_FUNCTION(cci_i2c), + MSM_PIN_FUNCTION(cci_timer0), + MSM_PIN_FUNCTION(cci_timer1), + MSM_PIN_FUNCTION(cci_timer2), + MSM_PIN_FUNCTION(cci_timer3), + MSM_PIN_FUNCTION(cci_timer4), + MSM_PIN_FUNCTION(cri_trng), + MSM_PIN_FUNCTION(cri_trng0), + MSM_PIN_FUNCTION(cri_trng1), + MSM_PIN_FUNCTION(dbg_out), + MSM_PIN_FUNCTION(ddr_bist), + MSM_PIN_FUNCTION(ddr_pxi0), + MSM_PIN_FUNCTION(ddr_pxi1), + MSM_PIN_FUNCTION(ddr_pxi2), + MSM_PIN_FUNCTION(ddr_pxi3), + MSM_PIN_FUNCTION(edp_hot), + MSM_PIN_FUNCTION(edp_lcd), + MSM_PIN_FUNCTION(gcc_gp1), + MSM_PIN_FUNCTION(gcc_gp2), + MSM_PIN_FUNCTION(gcc_gp3), + MSM_PIN_FUNCTION(jitter_bist), + MSM_PIN_FUNCTION(ldo_en), + MSM_PIN_FUNCTION(ldo_update), + MSM_PIN_FUNCTION(lpass_slimbus), + MSM_PIN_FUNCTION(m_voc), + MSM_PIN_FUNCTION(mdp_vsync), + MSM_PIN_FUNCTION(mdp_vsync0), + MSM_PIN_FUNCTION(mdp_vsync1), + MSM_PIN_FUNCTION(mdp_vsync2), + MSM_PIN_FUNCTION(mdp_vsync3), + MSM_PIN_FUNCTION(mss_lte), + MSM_PIN_FUNCTION(nav_pps), + MSM_PIN_FUNCTION(pa_indicator), + MSM_PIN_FUNCTION(pci_e0), + MSM_PIN_FUNCTION(pci_e1), + MSM_PIN_FUNCTION(phase_flag), + MSM_PIN_FUNCTION(pll_bist), + MSM_PIN_FUNCTION(pll_bypassnl), + MSM_PIN_FUNCTION(pll_reset), + MSM_PIN_FUNCTION(pri_mi2s), + MSM_PIN_FUNCTION(pri_mi2s_ws), + MSM_PIN_FUNCTION(prng_rosc), + MSM_PIN_FUNCTION(qdss_cti), + MSM_PIN_FUNCTION(qdss), + MSM_PIN_FUNCTION(qlink_enable), + MSM_PIN_FUNCTION(qlink_request), + MSM_PIN_FUNCTION(qspi_clk), + MSM_PIN_FUNCTION(qspi_cs), + MSM_PIN_FUNCTION(qspi_data), + MSM_PIN_FUNCTION(qua_mi2s), + MSM_PIN_FUNCTION(qup0), + MSM_PIN_FUNCTION(qup1), + MSM_PIN_FUNCTION(qup10), + MSM_PIN_FUNCTION(qup11), + MSM_PIN_FUNCTION(qup12), + MSM_PIN_FUNCTION(qup13), + MSM_PIN_FUNCTION(qup14), + MSM_PIN_FUNCTION(qup15), + MSM_PIN_FUNCTION(qup2), + MSM_PIN_FUNCTION(qup3), + MSM_PIN_FUNCTION(qup4), + MSM_PIN_FUNCTION(qup5), + MSM_PIN_FUNCTION(qup6), + MSM_PIN_FUNCTION(qup7), + MSM_PIN_FUNCTION(qup8), + MSM_PIN_FUNCTION(qup9), + MSM_PIN_FUNCTION(qup_l4), + MSM_PIN_FUNCTION(qup_l5), + MSM_PIN_FUNCTION(qup_l6), + MSM_PIN_FUNCTION(sd_write), + MSM_PIN_FUNCTION(sdc4_clk), + MSM_PIN_FUNCTION(sdc4_cmd), + MSM_PIN_FUNCTION(sdc4_data), + MSM_PIN_FUNCTION(sec_mi2s), + MSM_PIN_FUNCTION(sp_cmu), + MSM_PIN_FUNCTION(spkr_i2s), + MSM_PIN_FUNCTION(ter_mi2s), + MSM_PIN_FUNCTION(tgu_ch0), + MSM_PIN_FUNCTION(tgu_ch1), + MSM_PIN_FUNCTION(tgu_ch2), + MSM_PIN_FUNCTION(tgu_ch3), + MSM_PIN_FUNCTION(tsense_pwm1), + MSM_PIN_FUNCTION(tsense_pwm2), + MSM_PIN_FUNCTION(tsif1_clk), + MSM_PIN_FUNCTION(tsif1_data), + MSM_PIN_FUNCTION(tsif1_en), + MSM_PIN_FUNCTION(tsif1_error), + MSM_PIN_FUNCTION(tsif1_sync), + MSM_PIN_FUNCTION(tsif2_clk), + MSM_PIN_FUNCTION(tsif2_data), + MSM_PIN_FUNCTION(tsif2_en), + MSM_PIN_FUNCTION(tsif2_error), + MSM_PIN_FUNCTION(tsif2_sync), + MSM_PIN_FUNCTION(uim1_clk), + MSM_PIN_FUNCTION(uim1_data), + MSM_PIN_FUNCTION(uim1_present), + MSM_PIN_FUNCTION(uim1_reset), + MSM_PIN_FUNCTION(uim2_clk), + MSM_PIN_FUNCTION(uim2_data), + MSM_PIN_FUNCTION(uim2_present), + MSM_PIN_FUNCTION(uim2_reset), + MSM_PIN_FUNCTION(uim_batt), + MSM_PIN_FUNCTION(usb_phy), + MSM_PIN_FUNCTION(vfr_1), + MSM_PIN_FUNCTION(vsense_trigger), + MSM_PIN_FUNCTION(wlan1_adc0), + MSM_PIN_FUNCTION(wlan1_adc1), + MSM_PIN_FUNCTION(wlan2_adc0), + MSM_PIN_FUNCTION(wlan2_adc1), }; /* Every pin is maintained as a single group, and missing or non-existing pin diff --git a/drivers/pinctrl/qcom/pinctrl-sdx55.c b/drivers/pinctrl/qcom/pinctrl-sdx55.c index 0bb4931cec59e520c70a89cd8a0787b9e7244ce2..8826db9d21d04cecca844b0607984e21a500f15b 100644 --- a/drivers/pinctrl/qcom/pinctrl-sdx55.c +++ b/drivers/pinctrl/qcom/pinctrl-sdx55.c @@ -6,24 +6,16 @@ #include #include #include -#include #include "pinctrl-msm.h" -#define FUNCTION(fname) \ - [msm_mux_##fname] = { \ - .name = #fname, \ - .groups = fname##_groups, \ - .ngroups = ARRAY_SIZE(fname##_groups), \ - } - #define REG_SIZE 0x1000 #define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9) \ { \ - .name = "gpio" #id, \ - .pins = gpio##id##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(gpio##id##_pins), \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ .funcs = (int[]){ \ msm_mux_gpio, /* gpio mode */ \ msm_mux_##f1, \ @@ -60,9 +52,9 @@ #define SDC_PINGROUP(pg_name, ctl, pull, drv) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = ctl, \ .io_reg = 0, \ .intr_cfg_reg = 0, \ @@ -765,91 +757,91 @@ static const char * const spmi_coex_groups[] = { "gpio44", "gpio45", }; -static const struct msm_function sdx55_functions[] = { - FUNCTION(adsp_ext), - FUNCTION(atest), - FUNCTION(audio_ref), - FUNCTION(bimc_dte0), - FUNCTION(bimc_dte1), - FUNCTION(blsp_i2c1), - FUNCTION(blsp_i2c2), - FUNCTION(blsp_i2c3), - FUNCTION(blsp_i2c4), - FUNCTION(blsp_spi1), - FUNCTION(blsp_spi2), - FUNCTION(blsp_spi3), - FUNCTION(blsp_spi4), - FUNCTION(blsp_uart1), - FUNCTION(blsp_uart2), - FUNCTION(blsp_uart3), - FUNCTION(blsp_uart4), - FUNCTION(char_exec), - FUNCTION(coex_uart), - FUNCTION(coex_uart2), - FUNCTION(cri_trng), - FUNCTION(cri_trng0), - FUNCTION(cri_trng1), - FUNCTION(dbg_out), - FUNCTION(ddr_bist), - FUNCTION(ddr_pxi0), - FUNCTION(ebi0_wrcdc), - FUNCTION(ebi2_a), - FUNCTION(ebi2_lcd), - FUNCTION(emac_gcc0), - FUNCTION(emac_gcc1), - FUNCTION(emac_pps0), - FUNCTION(emac_pps1), - FUNCTION(ext_dbg), - FUNCTION(gcc_gp1), - FUNCTION(gcc_gp2), - FUNCTION(gcc_gp3), - FUNCTION(gcc_plltest), - FUNCTION(gpio), - FUNCTION(i2s_mclk), - FUNCTION(jitter_bist), - FUNCTION(ldo_en), - FUNCTION(ldo_update), - FUNCTION(mgpi_clk), - FUNCTION(m_voc), - FUNCTION(native_char), - FUNCTION(native_char0), - FUNCTION(native_char1), - FUNCTION(native_char2), - FUNCTION(native_char3), - FUNCTION(native_tsens), - FUNCTION(native_tsense), - FUNCTION(nav_gpio), - FUNCTION(pa_indicator), - FUNCTION(pcie_clkreq), - FUNCTION(pci_e), - FUNCTION(pll_bist), - FUNCTION(pll_ref), - FUNCTION(pll_test), - FUNCTION(pri_mi2s), - FUNCTION(prng_rosc), - FUNCTION(qdss_cti), - FUNCTION(qdss_gpio), - FUNCTION(qdss_stm), - FUNCTION(qlink0_en), - FUNCTION(qlink0_req), - FUNCTION(qlink0_wmss), - FUNCTION(qlink1_en), - FUNCTION(qlink1_req), - FUNCTION(qlink1_wmss), - FUNCTION(spmi_coex), - FUNCTION(sec_mi2s), - FUNCTION(spmi_vgi), - FUNCTION(tgu_ch0), - FUNCTION(uim1_clk), - FUNCTION(uim1_data), - FUNCTION(uim1_present), - FUNCTION(uim1_reset), - FUNCTION(uim2_clk), - FUNCTION(uim2_data), - FUNCTION(uim2_present), - FUNCTION(uim2_reset), - FUNCTION(usb2phy_ac), - FUNCTION(vsense_trigger), +static const struct pinfunction sdx55_functions[] = { + MSM_PIN_FUNCTION(adsp_ext), + MSM_PIN_FUNCTION(atest), + MSM_PIN_FUNCTION(audio_ref), + MSM_PIN_FUNCTION(bimc_dte0), + MSM_PIN_FUNCTION(bimc_dte1), + MSM_PIN_FUNCTION(blsp_i2c1), + MSM_PIN_FUNCTION(blsp_i2c2), + MSM_PIN_FUNCTION(blsp_i2c3), + MSM_PIN_FUNCTION(blsp_i2c4), + MSM_PIN_FUNCTION(blsp_spi1), + MSM_PIN_FUNCTION(blsp_spi2), + MSM_PIN_FUNCTION(blsp_spi3), + MSM_PIN_FUNCTION(blsp_spi4), + MSM_PIN_FUNCTION(blsp_uart1), + MSM_PIN_FUNCTION(blsp_uart2), + MSM_PIN_FUNCTION(blsp_uart3), + MSM_PIN_FUNCTION(blsp_uart4), + MSM_PIN_FUNCTION(char_exec), + MSM_PIN_FUNCTION(coex_uart), + MSM_PIN_FUNCTION(coex_uart2), + MSM_PIN_FUNCTION(cri_trng), + MSM_PIN_FUNCTION(cri_trng0), + MSM_PIN_FUNCTION(cri_trng1), + MSM_PIN_FUNCTION(dbg_out), + MSM_PIN_FUNCTION(ddr_bist), + MSM_PIN_FUNCTION(ddr_pxi0), + MSM_PIN_FUNCTION(ebi0_wrcdc), + MSM_PIN_FUNCTION(ebi2_a), + MSM_PIN_FUNCTION(ebi2_lcd), + MSM_PIN_FUNCTION(emac_gcc0), + MSM_PIN_FUNCTION(emac_gcc1), + MSM_PIN_FUNCTION(emac_pps0), + MSM_PIN_FUNCTION(emac_pps1), + MSM_PIN_FUNCTION(ext_dbg), + MSM_PIN_FUNCTION(gcc_gp1), + MSM_PIN_FUNCTION(gcc_gp2), + MSM_PIN_FUNCTION(gcc_gp3), + MSM_PIN_FUNCTION(gcc_plltest), + MSM_PIN_FUNCTION(gpio), + MSM_PIN_FUNCTION(i2s_mclk), + MSM_PIN_FUNCTION(jitter_bist), + MSM_PIN_FUNCTION(ldo_en), + MSM_PIN_FUNCTION(ldo_update), + MSM_PIN_FUNCTION(mgpi_clk), + MSM_PIN_FUNCTION(m_voc), + MSM_PIN_FUNCTION(native_char), + MSM_PIN_FUNCTION(native_char0), + MSM_PIN_FUNCTION(native_char1), + MSM_PIN_FUNCTION(native_char2), + MSM_PIN_FUNCTION(native_char3), + MSM_PIN_FUNCTION(native_tsens), + MSM_PIN_FUNCTION(native_tsense), + MSM_PIN_FUNCTION(nav_gpio), + MSM_PIN_FUNCTION(pa_indicator), + MSM_PIN_FUNCTION(pcie_clkreq), + MSM_PIN_FUNCTION(pci_e), + MSM_PIN_FUNCTION(pll_bist), + MSM_PIN_FUNCTION(pll_ref), + MSM_PIN_FUNCTION(pll_test), + MSM_PIN_FUNCTION(pri_mi2s), + MSM_PIN_FUNCTION(prng_rosc), + MSM_PIN_FUNCTION(qdss_cti), + MSM_PIN_FUNCTION(qdss_gpio), + MSM_PIN_FUNCTION(qdss_stm), + MSM_PIN_FUNCTION(qlink0_en), + MSM_PIN_FUNCTION(qlink0_req), + MSM_PIN_FUNCTION(qlink0_wmss), + MSM_PIN_FUNCTION(qlink1_en), + MSM_PIN_FUNCTION(qlink1_req), + MSM_PIN_FUNCTION(qlink1_wmss), + MSM_PIN_FUNCTION(spmi_coex), + MSM_PIN_FUNCTION(sec_mi2s), + MSM_PIN_FUNCTION(spmi_vgi), + MSM_PIN_FUNCTION(tgu_ch0), + MSM_PIN_FUNCTION(uim1_clk), + MSM_PIN_FUNCTION(uim1_data), + MSM_PIN_FUNCTION(uim1_present), + MSM_PIN_FUNCTION(uim1_reset), + MSM_PIN_FUNCTION(uim2_clk), + MSM_PIN_FUNCTION(uim2_data), + MSM_PIN_FUNCTION(uim2_present), + MSM_PIN_FUNCTION(uim2_reset), + MSM_PIN_FUNCTION(usb2phy_ac), + MSM_PIN_FUNCTION(vsense_trigger), }; /* Every pin is maintained as a single group, and missing or non-existing pin diff --git a/drivers/pinctrl/qcom/pinctrl-sdx65.c b/drivers/pinctrl/qcom/pinctrl-sdx65.c index e793ea71396563e23f7d67ef30dcd0ea8214c046..f6f319c997fc7a39d672872c0df1fa2ea821b2d9 100644 --- a/drivers/pinctrl/qcom/pinctrl-sdx65.c +++ b/drivers/pinctrl/qcom/pinctrl-sdx65.c @@ -6,24 +6,16 @@ #include #include #include -#include #include "pinctrl-msm.h" -#define FUNCTION(fname) \ - [msm_mux_##fname] = { \ - .name = #fname, \ - .groups = fname##_groups, \ - .ngroups = ARRAY_SIZE(fname##_groups), \ - } - #define REG_BASE 0x0 #define REG_SIZE 0x1000 #define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9) \ { \ - .name = "gpio" #id, \ - .pins = gpio##id##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(gpio##id##_pins), \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ .funcs = (int[]){ \ msm_mux_gpio, /* gpio mode */ \ msm_mux_##f1, \ @@ -60,9 +52,9 @@ #define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = ctl, \ .io_reg = 0, \ .intr_cfg_reg = 0, \ @@ -85,9 +77,9 @@ #define UFS_RESET(pg_name, offset) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = offset, \ .io_reg = offset + 0x4, \ .intr_cfg_reg = 0, \ @@ -700,90 +692,90 @@ static const char * const sdc1_tb_groups[] = { "gpio106", }; -static const struct msm_function sdx65_functions[] = { - FUNCTION(qlink0_wmss), - FUNCTION(adsp_ext), - FUNCTION(atest_char), - FUNCTION(atest_char0), - FUNCTION(atest_char1), - FUNCTION(atest_char2), - FUNCTION(atest_char3), - FUNCTION(audio_ref), - FUNCTION(bimc_dte0), - FUNCTION(bimc_dte1), - FUNCTION(blsp_i2c1), - FUNCTION(blsp_i2c2), - FUNCTION(blsp_i2c3), - FUNCTION(blsp_i2c4), - FUNCTION(blsp_spi1), - FUNCTION(blsp_spi2), - FUNCTION(blsp_spi3), - FUNCTION(blsp_spi4), - FUNCTION(blsp_uart1), - FUNCTION(blsp_uart2), - FUNCTION(blsp_uart3), - FUNCTION(blsp_uart4), - FUNCTION(char_exec), - FUNCTION(coex_uart), - FUNCTION(coex_uart2), - FUNCTION(cri_trng), - FUNCTION(cri_trng0), - FUNCTION(cri_trng1), - FUNCTION(dbg_out), - FUNCTION(ddr_bist), - FUNCTION(ddr_pxi0), - FUNCTION(ebi0_wrcdc), - FUNCTION(ebi2_a), - FUNCTION(ebi2_lcd), - FUNCTION(ext_dbg), - FUNCTION(gcc_gp1), - FUNCTION(gcc_gp2), - FUNCTION(gcc_gp3), - FUNCTION(gcc_plltest), - FUNCTION(gpio), - FUNCTION(i2s_mclk), - FUNCTION(jitter_bist), - FUNCTION(ldo_en), - FUNCTION(ldo_update), - FUNCTION(m_voc), - FUNCTION(mgpi_clk), - FUNCTION(native_char), - FUNCTION(native_tsens), - FUNCTION(native_tsense), - FUNCTION(nav_gpio), - FUNCTION(pa_indicator), - FUNCTION(pci_e), - FUNCTION(pcie_clkreq), - FUNCTION(pll_bist), - FUNCTION(pll_ref), - FUNCTION(pri_mi2s), - FUNCTION(pri_mi2s_ws), - FUNCTION(prng_rosc), - FUNCTION(qdss_cti), - FUNCTION(qdss_gpio), - FUNCTION(qlink0_en), - FUNCTION(qlink0_req), - FUNCTION(qlink1_en), - FUNCTION(qlink1_req), - FUNCTION(qlink1_wmss), - FUNCTION(qlink2_en), - FUNCTION(qlink2_req), - FUNCTION(qlink2_wmss), - FUNCTION(sdc1_tb), - FUNCTION(sec_mi2s), - FUNCTION(spmi_coex), - FUNCTION(spmi_vgi), - FUNCTION(tgu_ch0), - FUNCTION(uim1_clk), - FUNCTION(uim1_data), - FUNCTION(uim1_present), - FUNCTION(uim1_reset), - FUNCTION(uim2_clk), - FUNCTION(uim2_data), - FUNCTION(uim2_present), - FUNCTION(uim2_reset), - FUNCTION(usb2phy_ac), - FUNCTION(vsense_trigger), +static const struct pinfunction sdx65_functions[] = { + MSM_PIN_FUNCTION(qlink0_wmss), + MSM_PIN_FUNCTION(adsp_ext), + MSM_PIN_FUNCTION(atest_char), + MSM_PIN_FUNCTION(atest_char0), + MSM_PIN_FUNCTION(atest_char1), + MSM_PIN_FUNCTION(atest_char2), + MSM_PIN_FUNCTION(atest_char3), + MSM_PIN_FUNCTION(audio_ref), + MSM_PIN_FUNCTION(bimc_dte0), + MSM_PIN_FUNCTION(bimc_dte1), + MSM_PIN_FUNCTION(blsp_i2c1), + MSM_PIN_FUNCTION(blsp_i2c2), + MSM_PIN_FUNCTION(blsp_i2c3), + MSM_PIN_FUNCTION(blsp_i2c4), + MSM_PIN_FUNCTION(blsp_spi1), + MSM_PIN_FUNCTION(blsp_spi2), + MSM_PIN_FUNCTION(blsp_spi3), + MSM_PIN_FUNCTION(blsp_spi4), + MSM_PIN_FUNCTION(blsp_uart1), + MSM_PIN_FUNCTION(blsp_uart2), + MSM_PIN_FUNCTION(blsp_uart3), + MSM_PIN_FUNCTION(blsp_uart4), + MSM_PIN_FUNCTION(char_exec), + MSM_PIN_FUNCTION(coex_uart), + MSM_PIN_FUNCTION(coex_uart2), + MSM_PIN_FUNCTION(cri_trng), + MSM_PIN_FUNCTION(cri_trng0), + MSM_PIN_FUNCTION(cri_trng1), + MSM_PIN_FUNCTION(dbg_out), + MSM_PIN_FUNCTION(ddr_bist), + MSM_PIN_FUNCTION(ddr_pxi0), + MSM_PIN_FUNCTION(ebi0_wrcdc), + MSM_PIN_FUNCTION(ebi2_a), + MSM_PIN_FUNCTION(ebi2_lcd), + MSM_PIN_FUNCTION(ext_dbg), + MSM_PIN_FUNCTION(gcc_gp1), + MSM_PIN_FUNCTION(gcc_gp2), + MSM_PIN_FUNCTION(gcc_gp3), + MSM_PIN_FUNCTION(gcc_plltest), + MSM_PIN_FUNCTION(gpio), + MSM_PIN_FUNCTION(i2s_mclk), + MSM_PIN_FUNCTION(jitter_bist), + MSM_PIN_FUNCTION(ldo_en), + MSM_PIN_FUNCTION(ldo_update), + MSM_PIN_FUNCTION(m_voc), + MSM_PIN_FUNCTION(mgpi_clk), + MSM_PIN_FUNCTION(native_char), + MSM_PIN_FUNCTION(native_tsens), + MSM_PIN_FUNCTION(native_tsense), + MSM_PIN_FUNCTION(nav_gpio), + MSM_PIN_FUNCTION(pa_indicator), + MSM_PIN_FUNCTION(pci_e), + MSM_PIN_FUNCTION(pcie_clkreq), + MSM_PIN_FUNCTION(pll_bist), + MSM_PIN_FUNCTION(pll_ref), + MSM_PIN_FUNCTION(pri_mi2s), + MSM_PIN_FUNCTION(pri_mi2s_ws), + MSM_PIN_FUNCTION(prng_rosc), + MSM_PIN_FUNCTION(qdss_cti), + MSM_PIN_FUNCTION(qdss_gpio), + MSM_PIN_FUNCTION(qlink0_en), + MSM_PIN_FUNCTION(qlink0_req), + MSM_PIN_FUNCTION(qlink1_en), + MSM_PIN_FUNCTION(qlink1_req), + MSM_PIN_FUNCTION(qlink1_wmss), + MSM_PIN_FUNCTION(qlink2_en), + MSM_PIN_FUNCTION(qlink2_req), + MSM_PIN_FUNCTION(qlink2_wmss), + MSM_PIN_FUNCTION(sdc1_tb), + MSM_PIN_FUNCTION(sec_mi2s), + MSM_PIN_FUNCTION(spmi_coex), + MSM_PIN_FUNCTION(spmi_vgi), + MSM_PIN_FUNCTION(tgu_ch0), + MSM_PIN_FUNCTION(uim1_clk), + MSM_PIN_FUNCTION(uim1_data), + MSM_PIN_FUNCTION(uim1_present), + MSM_PIN_FUNCTION(uim1_reset), + MSM_PIN_FUNCTION(uim2_clk), + MSM_PIN_FUNCTION(uim2_data), + MSM_PIN_FUNCTION(uim2_present), + MSM_PIN_FUNCTION(uim2_reset), + MSM_PIN_FUNCTION(usb2phy_ac), + MSM_PIN_FUNCTION(vsense_trigger), }; /* Every pin is maintained as a single group, and missing or non-existing pin diff --git a/drivers/pinctrl/qcom/pinctrl-sdx75.c b/drivers/pinctrl/qcom/pinctrl-sdx75.c new file mode 100644 index 0000000000000000000000000000000000000000..2ade7866dbc5946d914a25a3b7ddc3fcece36766 --- /dev/null +++ b/drivers/pinctrl/qcom/pinctrl-sdx75.c @@ -0,0 +1,1144 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#include +#include +#include +#include +#include "pinctrl-msm.h" + +#define REG_BASE 0x100000 +#define REG_SIZE 0x1000 + +#define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10) \ + { \ + .grp = PINCTRL_PINGROUP("gpio"#id, gpio##id##_pins, \ + (unsigned int)ARRAY_SIZE(gpio##id##_pins)), \ + .ctl_reg = REG_BASE + REG_SIZE * id, \ + .io_reg = REG_BASE + 0x4 + REG_SIZE * id, \ + .intr_cfg_reg = REG_BASE + 0x8 + REG_SIZE * id, \ + .intr_status_reg = REG_BASE + 0xc + REG_SIZE * id, \ + .intr_target_reg = REG_BASE + 0x8 + REG_SIZE * id, \ + .mux_bit = 2, \ + .pull_bit = 0, \ + .drv_bit = 6, \ + .egpio_enable = 12, \ + .egpio_present = 11, \ + .oe_bit = 9, \ + .in_bit = 0, \ + .out_bit = 1, \ + .intr_enable_bit = 0, \ + .intr_status_bit = 0, \ + .intr_target_bit = 5, \ + .intr_target_kpss_val = 3, \ + .intr_raw_status_bit = 4, \ + .intr_polarity_bit = 1, \ + .intr_detection_bit = 2, \ + .intr_detection_width = 2, \ + .funcs = (int[]){ \ + msm_mux_gpio, /* gpio mode */ \ + msm_mux_##f1, \ + msm_mux_##f2, \ + msm_mux_##f3, \ + msm_mux_##f4, \ + msm_mux_##f5, \ + msm_mux_##f6, \ + msm_mux_##f7, \ + msm_mux_##f8, \ + msm_mux_##f9, \ + msm_mux_##f10 \ + }, \ + .nfuncs = 11, \ + } + +#define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv) \ + { \ + .grp = PINCTRL_PINGROUP(#pg_name, pg_name##_pins, \ + (unsigned int)ARRAY_SIZE(pg_name##_pins)), \ + .ctl_reg = ctl, \ + .io_reg = 0, \ + .intr_cfg_reg = 0, \ + .intr_status_reg = 0, \ + .intr_target_reg = 0, \ + .mux_bit = -1, \ + .pull_bit = pull, \ + .drv_bit = drv, \ + .oe_bit = -1, \ + .in_bit = -1, \ + .out_bit = -1, \ + .intr_enable_bit = -1, \ + .intr_status_bit = -1, \ + .intr_target_bit = -1, \ + .intr_raw_status_bit = -1, \ + .intr_polarity_bit = -1, \ + .intr_detection_bit = -1, \ + .intr_detection_width = -1, \ + } + +static const struct pinctrl_pin_desc sdx75_pins[] = { + PINCTRL_PIN(0, "GPIO_0"), + PINCTRL_PIN(1, "GPIO_1"), + PINCTRL_PIN(2, "GPIO_2"), + PINCTRL_PIN(3, "GPIO_3"), + PINCTRL_PIN(4, "GPIO_4"), + PINCTRL_PIN(5, "GPIO_5"), + PINCTRL_PIN(6, "GPIO_6"), + PINCTRL_PIN(7, "GPIO_7"), + PINCTRL_PIN(8, "GPIO_8"), + PINCTRL_PIN(9, "GPIO_9"), + PINCTRL_PIN(10, "GPIO_10"), + PINCTRL_PIN(11, "GPIO_11"), + PINCTRL_PIN(12, "GPIO_12"), + PINCTRL_PIN(13, "GPIO_13"), + PINCTRL_PIN(14, "GPIO_14"), + PINCTRL_PIN(15, "GPIO_15"), + PINCTRL_PIN(16, "GPIO_16"), + PINCTRL_PIN(17, "GPIO_17"), + PINCTRL_PIN(18, "GPIO_18"), + PINCTRL_PIN(19, "GPIO_19"), + PINCTRL_PIN(20, "GPIO_20"), + PINCTRL_PIN(21, "GPIO_21"), + PINCTRL_PIN(22, "GPIO_22"), + PINCTRL_PIN(23, "GPIO_23"), + PINCTRL_PIN(24, "GPIO_24"), + PINCTRL_PIN(25, "GPIO_25"), + PINCTRL_PIN(26, "GPIO_26"), + PINCTRL_PIN(27, "GPIO_27"), + PINCTRL_PIN(28, "GPIO_28"), + PINCTRL_PIN(29, "GPIO_29"), + PINCTRL_PIN(30, "GPIO_30"), + PINCTRL_PIN(31, "GPIO_31"), + PINCTRL_PIN(32, "GPIO_32"), + PINCTRL_PIN(33, "GPIO_33"), + PINCTRL_PIN(34, "GPIO_34"), + PINCTRL_PIN(35, "GPIO_35"), + PINCTRL_PIN(36, "GPIO_36"), + PINCTRL_PIN(37, "GPIO_37"), + PINCTRL_PIN(38, "GPIO_38"), + PINCTRL_PIN(39, "GPIO_39"), + PINCTRL_PIN(40, "GPIO_40"), + PINCTRL_PIN(41, "GPIO_41"), + PINCTRL_PIN(42, "GPIO_42"), + PINCTRL_PIN(43, "GPIO_43"), + PINCTRL_PIN(44, "GPIO_44"), + PINCTRL_PIN(45, "GPIO_45"), + PINCTRL_PIN(46, "GPIO_46"), + PINCTRL_PIN(47, "GPIO_47"), + PINCTRL_PIN(48, "GPIO_48"), + PINCTRL_PIN(49, "GPIO_49"), + PINCTRL_PIN(50, "GPIO_50"), + PINCTRL_PIN(51, "GPIO_51"), + PINCTRL_PIN(52, "GPIO_52"), + PINCTRL_PIN(53, "GPIO_53"), + PINCTRL_PIN(54, "GPIO_54"), + PINCTRL_PIN(55, "GPIO_55"), + PINCTRL_PIN(56, "GPIO_56"), + PINCTRL_PIN(57, "GPIO_57"), + PINCTRL_PIN(58, "GPIO_58"), + PINCTRL_PIN(59, "GPIO_59"), + PINCTRL_PIN(60, "GPIO_60"), + PINCTRL_PIN(61, "GPIO_61"), + PINCTRL_PIN(62, "GPIO_62"), + PINCTRL_PIN(63, "GPIO_63"), + PINCTRL_PIN(64, "GPIO_64"), + PINCTRL_PIN(65, "GPIO_65"), + PINCTRL_PIN(66, "GPIO_66"), + PINCTRL_PIN(67, "GPIO_67"), + PINCTRL_PIN(68, "GPIO_68"), + PINCTRL_PIN(69, "GPIO_69"), + PINCTRL_PIN(70, "GPIO_70"), + PINCTRL_PIN(71, "GPIO_71"), + PINCTRL_PIN(72, "GPIO_72"), + PINCTRL_PIN(73, "GPIO_73"), + PINCTRL_PIN(74, "GPIO_74"), + PINCTRL_PIN(75, "GPIO_75"), + PINCTRL_PIN(76, "GPIO_76"), + PINCTRL_PIN(77, "GPIO_77"), + PINCTRL_PIN(78, "GPIO_78"), + PINCTRL_PIN(79, "GPIO_79"), + PINCTRL_PIN(80, "GPIO_80"), + PINCTRL_PIN(81, "GPIO_81"), + PINCTRL_PIN(82, "GPIO_82"), + PINCTRL_PIN(83, "GPIO_83"), + PINCTRL_PIN(84, "GPIO_84"), + PINCTRL_PIN(85, "GPIO_85"), + PINCTRL_PIN(86, "GPIO_86"), + PINCTRL_PIN(87, "GPIO_87"), + PINCTRL_PIN(88, "GPIO_88"), + PINCTRL_PIN(89, "GPIO_89"), + PINCTRL_PIN(90, "GPIO_90"), + PINCTRL_PIN(91, "GPIO_91"), + PINCTRL_PIN(92, "GPIO_92"), + PINCTRL_PIN(93, "GPIO_93"), + PINCTRL_PIN(94, "GPIO_94"), + PINCTRL_PIN(95, "GPIO_95"), + PINCTRL_PIN(96, "GPIO_96"), + PINCTRL_PIN(97, "GPIO_97"), + PINCTRL_PIN(98, "GPIO_98"), + PINCTRL_PIN(99, "GPIO_99"), + PINCTRL_PIN(100, "GPIO_100"), + PINCTRL_PIN(101, "GPIO_101"), + PINCTRL_PIN(102, "GPIO_102"), + PINCTRL_PIN(103, "GPIO_103"), + PINCTRL_PIN(104, "GPIO_104"), + PINCTRL_PIN(105, "GPIO_105"), + PINCTRL_PIN(106, "GPIO_106"), + PINCTRL_PIN(107, "GPIO_107"), + PINCTRL_PIN(108, "GPIO_108"), + PINCTRL_PIN(109, "GPIO_109"), + PINCTRL_PIN(110, "GPIO_110"), + PINCTRL_PIN(111, "GPIO_111"), + PINCTRL_PIN(112, "GPIO_112"), + PINCTRL_PIN(113, "GPIO_113"), + PINCTRL_PIN(114, "GPIO_114"), + PINCTRL_PIN(115, "GPIO_115"), + PINCTRL_PIN(116, "GPIO_116"), + PINCTRL_PIN(117, "GPIO_117"), + PINCTRL_PIN(118, "GPIO_118"), + PINCTRL_PIN(119, "GPIO_119"), + PINCTRL_PIN(120, "GPIO_120"), + PINCTRL_PIN(121, "GPIO_121"), + PINCTRL_PIN(122, "GPIO_122"), + PINCTRL_PIN(123, "GPIO_123"), + PINCTRL_PIN(124, "GPIO_124"), + PINCTRL_PIN(125, "GPIO_125"), + PINCTRL_PIN(126, "GPIO_126"), + PINCTRL_PIN(127, "GPIO_127"), + PINCTRL_PIN(128, "GPIO_128"), + PINCTRL_PIN(129, "GPIO_129"), + PINCTRL_PIN(130, "GPIO_130"), + PINCTRL_PIN(131, "GPIO_131"), + PINCTRL_PIN(132, "GPIO_132"), + PINCTRL_PIN(133, "SDC1_RCLK"), + PINCTRL_PIN(134, "SDC1_CLK"), + PINCTRL_PIN(135, "SDC1_CMD"), + PINCTRL_PIN(136, "SDC1_DATA"), + PINCTRL_PIN(137, "SDC2_CLK"), + PINCTRL_PIN(138, "SDC2_CMD"), + PINCTRL_PIN(139, "SDC2_DATA"), +}; + +#define DECLARE_MSM_GPIO_PINS(pin) \ + static const unsigned int gpio##pin##_pins[] = {pin} +DECLARE_MSM_GPIO_PINS(0); +DECLARE_MSM_GPIO_PINS(1); +DECLARE_MSM_GPIO_PINS(2); +DECLARE_MSM_GPIO_PINS(3); +DECLARE_MSM_GPIO_PINS(4); +DECLARE_MSM_GPIO_PINS(5); +DECLARE_MSM_GPIO_PINS(6); +DECLARE_MSM_GPIO_PINS(7); +DECLARE_MSM_GPIO_PINS(8); +DECLARE_MSM_GPIO_PINS(9); +DECLARE_MSM_GPIO_PINS(10); +DECLARE_MSM_GPIO_PINS(11); +DECLARE_MSM_GPIO_PINS(12); +DECLARE_MSM_GPIO_PINS(13); +DECLARE_MSM_GPIO_PINS(14); +DECLARE_MSM_GPIO_PINS(15); +DECLARE_MSM_GPIO_PINS(16); +DECLARE_MSM_GPIO_PINS(17); +DECLARE_MSM_GPIO_PINS(18); +DECLARE_MSM_GPIO_PINS(19); +DECLARE_MSM_GPIO_PINS(20); +DECLARE_MSM_GPIO_PINS(21); +DECLARE_MSM_GPIO_PINS(22); +DECLARE_MSM_GPIO_PINS(23); +DECLARE_MSM_GPIO_PINS(24); +DECLARE_MSM_GPIO_PINS(25); +DECLARE_MSM_GPIO_PINS(26); +DECLARE_MSM_GPIO_PINS(27); +DECLARE_MSM_GPIO_PINS(28); +DECLARE_MSM_GPIO_PINS(29); +DECLARE_MSM_GPIO_PINS(30); +DECLARE_MSM_GPIO_PINS(31); +DECLARE_MSM_GPIO_PINS(32); +DECLARE_MSM_GPIO_PINS(33); +DECLARE_MSM_GPIO_PINS(34); +DECLARE_MSM_GPIO_PINS(35); +DECLARE_MSM_GPIO_PINS(36); +DECLARE_MSM_GPIO_PINS(37); +DECLARE_MSM_GPIO_PINS(38); +DECLARE_MSM_GPIO_PINS(39); +DECLARE_MSM_GPIO_PINS(40); +DECLARE_MSM_GPIO_PINS(41); +DECLARE_MSM_GPIO_PINS(42); +DECLARE_MSM_GPIO_PINS(43); +DECLARE_MSM_GPIO_PINS(44); +DECLARE_MSM_GPIO_PINS(45); +DECLARE_MSM_GPIO_PINS(46); +DECLARE_MSM_GPIO_PINS(47); +DECLARE_MSM_GPIO_PINS(48); +DECLARE_MSM_GPIO_PINS(49); +DECLARE_MSM_GPIO_PINS(50); +DECLARE_MSM_GPIO_PINS(51); +DECLARE_MSM_GPIO_PINS(52); +DECLARE_MSM_GPIO_PINS(53); +DECLARE_MSM_GPIO_PINS(54); +DECLARE_MSM_GPIO_PINS(55); +DECLARE_MSM_GPIO_PINS(56); +DECLARE_MSM_GPIO_PINS(57); +DECLARE_MSM_GPIO_PINS(58); +DECLARE_MSM_GPIO_PINS(59); +DECLARE_MSM_GPIO_PINS(60); +DECLARE_MSM_GPIO_PINS(61); +DECLARE_MSM_GPIO_PINS(62); +DECLARE_MSM_GPIO_PINS(63); +DECLARE_MSM_GPIO_PINS(64); +DECLARE_MSM_GPIO_PINS(65); +DECLARE_MSM_GPIO_PINS(66); +DECLARE_MSM_GPIO_PINS(67); +DECLARE_MSM_GPIO_PINS(68); +DECLARE_MSM_GPIO_PINS(69); +DECLARE_MSM_GPIO_PINS(70); +DECLARE_MSM_GPIO_PINS(71); +DECLARE_MSM_GPIO_PINS(72); +DECLARE_MSM_GPIO_PINS(73); +DECLARE_MSM_GPIO_PINS(74); +DECLARE_MSM_GPIO_PINS(75); +DECLARE_MSM_GPIO_PINS(76); +DECLARE_MSM_GPIO_PINS(77); +DECLARE_MSM_GPIO_PINS(78); +DECLARE_MSM_GPIO_PINS(79); +DECLARE_MSM_GPIO_PINS(80); +DECLARE_MSM_GPIO_PINS(81); +DECLARE_MSM_GPIO_PINS(82); +DECLARE_MSM_GPIO_PINS(83); +DECLARE_MSM_GPIO_PINS(84); +DECLARE_MSM_GPIO_PINS(85); +DECLARE_MSM_GPIO_PINS(86); +DECLARE_MSM_GPIO_PINS(87); +DECLARE_MSM_GPIO_PINS(88); +DECLARE_MSM_GPIO_PINS(89); +DECLARE_MSM_GPIO_PINS(90); +DECLARE_MSM_GPIO_PINS(91); +DECLARE_MSM_GPIO_PINS(92); +DECLARE_MSM_GPIO_PINS(93); +DECLARE_MSM_GPIO_PINS(94); +DECLARE_MSM_GPIO_PINS(95); +DECLARE_MSM_GPIO_PINS(96); +DECLARE_MSM_GPIO_PINS(97); +DECLARE_MSM_GPIO_PINS(98); +DECLARE_MSM_GPIO_PINS(99); +DECLARE_MSM_GPIO_PINS(100); +DECLARE_MSM_GPIO_PINS(101); +DECLARE_MSM_GPIO_PINS(102); +DECLARE_MSM_GPIO_PINS(103); +DECLARE_MSM_GPIO_PINS(104); +DECLARE_MSM_GPIO_PINS(105); +DECLARE_MSM_GPIO_PINS(106); +DECLARE_MSM_GPIO_PINS(107); +DECLARE_MSM_GPIO_PINS(108); +DECLARE_MSM_GPIO_PINS(109); +DECLARE_MSM_GPIO_PINS(110); +DECLARE_MSM_GPIO_PINS(111); +DECLARE_MSM_GPIO_PINS(112); +DECLARE_MSM_GPIO_PINS(113); +DECLARE_MSM_GPIO_PINS(114); +DECLARE_MSM_GPIO_PINS(115); +DECLARE_MSM_GPIO_PINS(116); +DECLARE_MSM_GPIO_PINS(117); +DECLARE_MSM_GPIO_PINS(118); +DECLARE_MSM_GPIO_PINS(119); +DECLARE_MSM_GPIO_PINS(120); +DECLARE_MSM_GPIO_PINS(121); +DECLARE_MSM_GPIO_PINS(122); +DECLARE_MSM_GPIO_PINS(123); +DECLARE_MSM_GPIO_PINS(124); +DECLARE_MSM_GPIO_PINS(125); +DECLARE_MSM_GPIO_PINS(126); +DECLARE_MSM_GPIO_PINS(127); +DECLARE_MSM_GPIO_PINS(128); +DECLARE_MSM_GPIO_PINS(129); +DECLARE_MSM_GPIO_PINS(130); +DECLARE_MSM_GPIO_PINS(131); +DECLARE_MSM_GPIO_PINS(132); + +static const unsigned int sdc1_rclk_pins[] = {133}; +static const unsigned int sdc1_clk_pins[] = {134}; +static const unsigned int sdc1_cmd_pins[] = {135}; +static const unsigned int sdc1_data_pins[] = {136}; +static const unsigned int sdc2_clk_pins[] = {137}; +static const unsigned int sdc2_cmd_pins[] = {138}; +static const unsigned int sdc2_data_pins[] = {139}; + +enum sdx75_functions { + msm_mux_adsp_ext, + msm_mux_atest_char, + msm_mux_audio_ref_clk, + msm_mux_bimc_dte, + msm_mux_char_exec, + msm_mux_coex_uart2, + msm_mux_coex_uart, + msm_mux_cri_trng, + msm_mux_cri_trng0, + msm_mux_cri_trng1, + msm_mux_dbg_out_clk, + msm_mux_ddr_bist, + msm_mux_ddr_pxi0, + msm_mux_ebi0_wrcdc, + msm_mux_ebi2_a, + msm_mux_ebi2_lcd, + msm_mux_ebi2_lcd_te, + msm_mux_emac0_mcg, + msm_mux_emac0_ptp, + msm_mux_emac1_mcg, + msm_mux_emac1_ptp, + msm_mux_emac_cdc, + msm_mux_emac_pps_in, + msm_mux_eth0_mdc, + msm_mux_eth0_mdio, + msm_mux_eth1_mdc, + msm_mux_eth1_mdio, + msm_mux_ext_dbg, + msm_mux_gcc_125_clk, + msm_mux_gcc_gp1_clk, + msm_mux_gcc_gp2_clk, + msm_mux_gcc_gp3_clk, + msm_mux_gcc_plltest, + msm_mux_gpio, + msm_mux_i2s_mclk, + msm_mux_jitter_bist, + msm_mux_ldo_en, + msm_mux_ldo_update, + msm_mux_m_voc, + msm_mux_mgpi_clk, + msm_mux_native_char, + msm_mux_native_tsens, + msm_mux_native_tsense, + msm_mux_nav_dr_sync, + msm_mux_nav_gpio, + msm_mux_pa_indicator, + msm_mux_pci_e, + msm_mux_pcie0_clkreq_n, + msm_mux_pcie1_clkreq_n, + msm_mux_pcie2_clkreq_n, + msm_mux_pll_bist_sync, + msm_mux_pll_clk_aux, + msm_mux_pll_ref_clk, + msm_mux_pri_mi2s, + msm_mux_prng_rosc, + msm_mux_qdss_cti, + msm_mux_qdss_gpio, + msm_mux_qlink0_b_en, + msm_mux_qlink0_b_req, + msm_mux_qlink0_l_en, + msm_mux_qlink0_l_req, + msm_mux_qlink0_wmss, + msm_mux_qlink1_l_en, + msm_mux_qlink1_l_req, + msm_mux_qlink1_wmss, + msm_mux_qup_se0, + msm_mux_qup_se1_l2_mira, + msm_mux_qup_se1_l2_mirb, + msm_mux_qup_se1_l3_mira, + msm_mux_qup_se1_l3_mirb, + msm_mux_qup_se2, + msm_mux_qup_se3, + msm_mux_qup_se4, + msm_mux_qup_se5, + msm_mux_qup_se6, + msm_mux_qup_se7, + msm_mux_qup_se8, + msm_mux_rgmii_rx_ctl, + msm_mux_rgmii_rxc, + msm_mux_rgmii_rxd, + msm_mux_rgmii_tx_ctl, + msm_mux_rgmii_txc, + msm_mux_rgmii_txd, + msm_mux_sd_card, + msm_mux_sdc1_tb, + msm_mux_sdc2_tb_trig, + msm_mux_sec_mi2s, + msm_mux_sgmii_phy_intr0_n, + msm_mux_sgmii_phy_intr1_n, + msm_mux_spmi_coex, + msm_mux_spmi_vgi, + msm_mux_tgu_ch0_trigout, + msm_mux_tmess_prng0, + msm_mux_tmess_prng1, + msm_mux_tmess_prng2, + msm_mux_tmess_prng3, + msm_mux_tri_mi2s, + msm_mux_uim1_clk, + msm_mux_uim1_data, + msm_mux_uim1_present, + msm_mux_uim1_reset, + msm_mux_uim2_clk, + msm_mux_uim2_data, + msm_mux_uim2_present, + msm_mux_uim2_reset, + msm_mux_usb2phy_ac_en, + msm_mux_vsense_trigger_mirnat, + msm_mux__, +}; + +static const char *const gpio_groups[] = { + "gpio0", "gpio1", "gpio2", "gpio3", "gpio4", "gpio5", "gpio6", + "gpio7", "gpio8", "gpio9", "gpio10", "gpio11", "gpio12", "gpio13", + "gpio14", "gpio15", "gpio16", "gpio17", "gpio18", "gpio19", "gpio20", + "gpio21", "gpio22", "gpio23", "gpio24", "gpio25", "gpio26", "gpio27", + "gpio28", "gpio29", "gpio30", "gpio31", "gpio32", "gpio33", "gpio34", + "gpio35", "gpio36", "gpio37", "gpio38", "gpio39", "gpio40", "gpio41", + "gpio42", "gpio43", "gpio44", "gpio45", "gpio46", "gpio47", "gpio48", + "gpio49", "gpio50", "gpio51", "gpio52", "gpio53", "gpio54", "gpio55", + "gpio56", "gpio57", "gpio58", "gpio59", "gpio60", "gpio61", "gpio62", + "gpio63", "gpio64", "gpio65", "gpio66", "gpio67", "gpio68", "gpio69", + "gpio70", "gpio71", "gpio72", "gpio73", "gpio74", "gpio75", "gpio76", + "gpio77", "gpio78", "gpio79", "gpio80", "gpio81", "gpio82", "gpio83", + "gpio84", "gpio85", "gpio86", "gpio87", "gpio88", "gpio89", "gpio90", + "gpio91", "gpio92", "gpio93", "gpio94", "gpio95", "gpio96", "gpio97", + "gpio98", "gpio99", "gpio100", "gpio101", "gpio102", "gpio103", "gpio104", + "gpio105", "gpio106", "gpio107", "gpio108", "gpio109", "gpio110", "gpio111", + "gpio112", "gpio113", "gpio114", "gpio115", "gpio116", "gpio117", "gpio118", + "gpio119", "gpio120", "gpio121", "gpio122", "gpio123", "gpio124", "gpio125", + "gpio126", "gpio127", "gpio128", "gpio129", "gpio130", "gpio131", "gpio132", +}; +static const char *const adsp_ext_groups[] = { + "gpio59", "gpio68", +}; +static const char *const atest_char_groups[] = { + "gpio24", "gpio25", "gpio26", "gpio41", "gpio63", +}; +static const char *const audio_ref_clk_groups[] = { + "gpio126", +}; +static const char *const bimc_dte_groups[] = { + "gpio14", "gpio15", "gpio61", "gpio59", +}; +static const char *const char_exec_groups[] = { + "gpio6", "gpio7", +}; +static const char *const coex_uart2_groups[] = { + "gpio48", "gpio49", "gpio90", "gpio91", +}; +static const char *const coex_uart_groups[] = { + "gpio46", "gpio47", +}; +static const char *const cri_trng_groups[] = { + "gpio36", +}; +static const char *const cri_trng0_groups[] = { + "gpio31", +}; +static const char *const cri_trng1_groups[] = { + "gpio32", +}; +static const char *const dbg_out_clk_groups[] = { + "gpio26", +}; +static const char *const ddr_bist_groups[] = { + "gpio46", "gpio47", "gpio48", "gpio49", +}; +static const char *const ddr_pxi0_groups[] = { + "gpio45", "gpio46", +}; +static const char *const ebi0_wrcdc_groups[] = { + "gpio0", "gpio2", +}; +static const char *const ebi2_a_groups[] = { + "gpio100", +}; +static const char *const ebi2_lcd_groups[] = { + "gpio99", "gpio101", +}; +static const char *const ebi2_lcd_te_groups[] = { + "gpio98", +}; +static const char *const emac0_mcg_groups[] = { + "gpio83", "gpio84", "gpio85", "gpio89", +}; +static const char *const emac0_ptp_groups[] = { + "gpio35", "gpio83", "gpio84", "gpio85", "gpio89", "gpio119", "gpio123", +}; +static const char *const emac1_mcg_groups[] = { + "gpio90", "gpio92", "gpio93", "gpio122", +}; +static const char *const emac1_ptp_groups[] = { + "gpio112", "gpio113", "gpio114", "gpio115", +}; +static const char *const emac_cdc_groups[] = { + "gpio38", "gpio39", +}; +static const char *const emac_pps_in_groups[] = { + "gpio127", +}; +static const char *const eth0_mdc_groups[] = { + "gpio94", +}; +static const char *const eth0_mdio_groups[] = { + "gpio95", +}; +static const char *const eth1_mdc_groups[] = { + "gpio106", +}; +static const char *const eth1_mdio_groups[] = { + "gpio107", +}; +static const char *const ext_dbg_groups[] = { + "gpio12", "gpio13", "gpio14", "gpio15", +}; +static const char *const gcc_125_clk_groups[] = { + "gpio25", +}; +static const char *const gcc_gp1_clk_groups[] = { + "gpio39", +}; +static const char *const gcc_gp2_clk_groups[] = { + "gpio40", +}; +static const char *const gcc_gp3_clk_groups[] = { + "gpio41", +}; +static const char *const gcc_plltest_groups[] = { + "gpio81", "gpio82", +}; +static const char *const i2s_mclk_groups[] = { + "gpio74", +}; +static const char *const jitter_bist_groups[] = { + "gpio41", +}; +static const char *const ldo_en_groups[] = { + "gpio8", +}; +static const char *const ldo_update_groups[] = { + "gpio62", +}; +static const char *const m_voc_groups[] = { + "gpio62", "gpio63", "gpio64", "gpio65", "gpio71", +}; +static const char *const mgpi_clk_groups[] = { + "gpio39", "gpio40", +}; +static const char *const native_char_groups[] = { + "gpio29", "gpio33", "gpio57", "gpio66", "gpio67", +}; +static const char *const native_tsens_groups[] = { + "gpio38", +}; +static const char *const native_tsense_groups[] = { + "gpio64", "gpio76", +}; +static const char *const nav_dr_sync_groups[] = { + "gpio36", +}; +static const char *const nav_gpio_groups[] = { + "gpio35", "gpio36", "gpio104", +}; +static const char *const pa_indicator_groups[] = { + "gpio58", +}; +static const char *const pci_e_groups[] = { + "gpio42", +}; +static const char *const pcie0_clkreq_n_groups[] = { + "gpio43", +}; +static const char *const pcie1_clkreq_n_groups[] = { + "gpio124", +}; +static const char *const pcie2_clkreq_n_groups[] = { + "gpio121", +}; +static const char *const pll_bist_sync_groups[] = { + "gpio38", +}; +static const char *const pll_clk_aux_groups[] = { + "gpio40", +}; +static const char *const pll_ref_clk_groups[] = { + "gpio37", +}; +static const char *const pri_mi2s_groups[] = { + "gpio16", "gpio17", "gpio18", "gpio19", +}; +static const char *const prng_rosc_groups[] = { + "gpio27", "gpio36", "gpio37", "gpio38", +}; +static const char *const qdss_cti_groups[] = { + "gpio16", "gpio17", "gpio52", "gpio53", "gpio56", + "gpio57", "gpio59", "gpio60", "gpio78", "gpio79", +}; +static const char *const qdss_gpio_groups[] = { + "gpio82", "gpio83", "gpio84", "gpio85", "gpio94", + "gpio95", "gpio96", "gpio97", "gpio110", "gpio111", + "gpio112", "gpio113", "gpio114", "gpio115", "gpio116", + "gpio117", "gpio118", "gpio119", +}; +static const char *const qlink0_b_en_groups[] = { + "gpio40", +}; +static const char *const qlink0_b_req_groups[] = { + "gpio41", +}; +static const char *const qlink0_l_en_groups[] = { + "gpio37", +}; +static const char *const qlink0_l_req_groups[] = { + "gpio38", +}; +static const char *const qlink0_wmss_groups[] = { + "gpio39", +}; +static const char *const qlink1_l_en_groups[] = { + "gpio26", +}; +static const char *const qlink1_l_req_groups[] = { + "gpio27", +}; +static const char *const qlink1_wmss_groups[] = { + "gpio28", +}; +static const char *const qup_se0_groups[] = { + "gpio8", "gpio9", "gpio10", "gpio11", +}; +static const char *const qup_se1_l2_mira_groups[] = { + "gpio12", +}; +static const char *const qup_se1_l2_mirb_groups[] = { + "gpio16", +}; +static const char *const qup_se1_l3_mira_groups[] = { + "gpio13", +}; +static const char *const qup_se1_l3_mirb_groups[] = { + "gpio17", +}; +static const char *const qup_se2_groups[] = { + "gpio14", "gpio15", "gpio16", "gpio17", +}; +static const char *const qup_se3_groups[] = { + "gpio52", "gpio53", "gpio54", "gpio55", +}; +static const char *const qup_se4_groups[] = { + "gpio64", "gpio65", +}; +static const char *const qup_se5_groups[] = { + "gpio110", "gpio111", +}; +static const char *const qup_se6_groups[] = { + "gpio112", "gpio113", "gpio114", "gpio115", +}; +static const char *const qup_se7_groups[] = { + "gpio116", "gpio117", "gpio118", "gpio119", +}; +static const char *const qup_se8_groups[] = { + "gpio124", "gpio125", +}; +static const char *const rgmii_rx_ctl_groups[] = { + "gpio93", +}; +static const char *const rgmii_rxc_groups[] = { + "gpio88", +}; +static const char *const rgmii_rxd_groups[] = { + "gpio89", "gpio90", "gpio91", "gpio92", +}; +static const char *const rgmii_tx_ctl_groups[] = { + "gpio87", +}; +static const char *const rgmii_txc_groups[] = { + "gpio82", +}; +static const char *const rgmii_txd_groups[] = { + "gpio83", "gpio84", "gpio85", "gpio86", +}; +static const char *const sd_card_groups[] = { + "gpio105", +}; +static const char *const sdc1_tb_groups[] = { + "gpio84", "gpio130", +}; +static const char *const sdc2_tb_trig_groups[] = { + "gpio129", +}; +static const char *const sec_mi2s_groups[] = { + "gpio20", "gpio21", "gpio22", "gpio23", +}; +static const char *const sgmii_phy_intr0_n_groups[] = { + "gpio97", +}; +static const char *const sgmii_phy_intr1_n_groups[] = { + "gpio109", +}; +static const char *const spmi_coex_groups[] = { + "gpio48", "gpio49", +}; +static const char *const spmi_vgi_groups[] = { + "gpio50", "gpio51", +}; +static const char *const tgu_ch0_trigout_groups[] = { + "gpio55", +}; +static const char *const tmess_prng0_groups[] = { + "gpio28", +}; +static const char *const tmess_prng1_groups[] = { + "gpio29", +}; +static const char *const tmess_prng2_groups[] = { + "gpio30", +}; +static const char *const tmess_prng3_groups[] = { + "gpio31", +}; +static const char *const tri_mi2s_groups[] = { + "gpio98", "gpio99", "gpio100", "gpio101", +}; +static const char *const uim1_clk_groups[] = { + "gpio7", +}; +static const char *const uim1_data_groups[] = { + "gpio4", +}; +static const char *const uim1_present_groups[] = { + "gpio5", +}; +static const char *const uim1_reset_groups[] = { + "gpio6", +}; +static const char *const uim2_clk_groups[] = { + "gpio3", +}; +static const char *const uim2_data_groups[] = { + "gpio0", +}; +static const char *const uim2_present_groups[] = { + "gpio1", +}; +static const char *const uim2_reset_groups[] = { + "gpio2", +}; +static const char *const usb2phy_ac_en_groups[] = { + "gpio80", +}; +static const char *const vsense_trigger_mirnat_groups[] = { + "gpio37", +}; + +static const struct pinfunction sdx75_functions[] = { + MSM_PIN_FUNCTION(adsp_ext), + MSM_PIN_FUNCTION(atest_char), + MSM_PIN_FUNCTION(audio_ref_clk), + MSM_PIN_FUNCTION(bimc_dte), + MSM_PIN_FUNCTION(char_exec), + MSM_PIN_FUNCTION(coex_uart2), + MSM_PIN_FUNCTION(coex_uart), + MSM_PIN_FUNCTION(cri_trng), + MSM_PIN_FUNCTION(cri_trng0), + MSM_PIN_FUNCTION(cri_trng1), + MSM_PIN_FUNCTION(dbg_out_clk), + MSM_PIN_FUNCTION(ddr_bist), + MSM_PIN_FUNCTION(ddr_pxi0), + MSM_PIN_FUNCTION(ebi0_wrcdc), + MSM_PIN_FUNCTION(ebi2_a), + MSM_PIN_FUNCTION(ebi2_lcd), + MSM_PIN_FUNCTION(ebi2_lcd_te), + MSM_PIN_FUNCTION(emac0_mcg), + MSM_PIN_FUNCTION(emac0_ptp), + MSM_PIN_FUNCTION(emac1_mcg), + MSM_PIN_FUNCTION(emac1_ptp), + MSM_PIN_FUNCTION(emac_cdc), + MSM_PIN_FUNCTION(emac_pps_in), + MSM_PIN_FUNCTION(eth0_mdc), + MSM_PIN_FUNCTION(eth0_mdio), + MSM_PIN_FUNCTION(eth1_mdc), + MSM_PIN_FUNCTION(eth1_mdio), + MSM_PIN_FUNCTION(ext_dbg), + MSM_PIN_FUNCTION(gcc_125_clk), + MSM_PIN_FUNCTION(gcc_gp1_clk), + MSM_PIN_FUNCTION(gcc_gp2_clk), + MSM_PIN_FUNCTION(gcc_gp3_clk), + MSM_PIN_FUNCTION(gcc_plltest), + MSM_PIN_FUNCTION(gpio), + MSM_PIN_FUNCTION(i2s_mclk), + MSM_PIN_FUNCTION(jitter_bist), + MSM_PIN_FUNCTION(ldo_en), + MSM_PIN_FUNCTION(ldo_update), + MSM_PIN_FUNCTION(m_voc), + MSM_PIN_FUNCTION(mgpi_clk), + MSM_PIN_FUNCTION(native_char), + MSM_PIN_FUNCTION(native_tsens), + MSM_PIN_FUNCTION(native_tsense), + MSM_PIN_FUNCTION(nav_dr_sync), + MSM_PIN_FUNCTION(nav_gpio), + MSM_PIN_FUNCTION(pa_indicator), + MSM_PIN_FUNCTION(pci_e), + MSM_PIN_FUNCTION(pcie0_clkreq_n), + MSM_PIN_FUNCTION(pcie1_clkreq_n), + MSM_PIN_FUNCTION(pcie2_clkreq_n), + MSM_PIN_FUNCTION(pll_bist_sync), + MSM_PIN_FUNCTION(pll_clk_aux), + MSM_PIN_FUNCTION(pll_ref_clk), + MSM_PIN_FUNCTION(pri_mi2s), + MSM_PIN_FUNCTION(prng_rosc), + MSM_PIN_FUNCTION(qdss_cti), + MSM_PIN_FUNCTION(qdss_gpio), + MSM_PIN_FUNCTION(qlink0_b_en), + MSM_PIN_FUNCTION(qlink0_b_req), + MSM_PIN_FUNCTION(qlink0_l_en), + MSM_PIN_FUNCTION(qlink0_l_req), + MSM_PIN_FUNCTION(qlink1_l_en), + MSM_PIN_FUNCTION(qlink1_l_req), + MSM_PIN_FUNCTION(qlink0_wmss), + MSM_PIN_FUNCTION(qlink1_wmss), + MSM_PIN_FUNCTION(qup_se0), + MSM_PIN_FUNCTION(qup_se1_l2_mira), + MSM_PIN_FUNCTION(qup_se1_l2_mirb), + MSM_PIN_FUNCTION(qup_se1_l3_mira), + MSM_PIN_FUNCTION(qup_se1_l3_mirb), + MSM_PIN_FUNCTION(qup_se2), + MSM_PIN_FUNCTION(qup_se3), + MSM_PIN_FUNCTION(qup_se4), + MSM_PIN_FUNCTION(qup_se5), + MSM_PIN_FUNCTION(qup_se6), + MSM_PIN_FUNCTION(qup_se7), + MSM_PIN_FUNCTION(qup_se8), + MSM_PIN_FUNCTION(rgmii_rx_ctl), + MSM_PIN_FUNCTION(rgmii_rxc), + MSM_PIN_FUNCTION(rgmii_rxd), + MSM_PIN_FUNCTION(rgmii_tx_ctl), + MSM_PIN_FUNCTION(rgmii_txc), + MSM_PIN_FUNCTION(rgmii_txd), + MSM_PIN_FUNCTION(sd_card), + MSM_PIN_FUNCTION(sdc1_tb), + MSM_PIN_FUNCTION(sdc2_tb_trig), + MSM_PIN_FUNCTION(sec_mi2s), + MSM_PIN_FUNCTION(sgmii_phy_intr0_n), + MSM_PIN_FUNCTION(sgmii_phy_intr1_n), + MSM_PIN_FUNCTION(spmi_coex), + MSM_PIN_FUNCTION(spmi_vgi), + MSM_PIN_FUNCTION(tgu_ch0_trigout), + MSM_PIN_FUNCTION(tmess_prng0), + MSM_PIN_FUNCTION(tmess_prng1), + MSM_PIN_FUNCTION(tmess_prng2), + MSM_PIN_FUNCTION(tmess_prng3), + MSM_PIN_FUNCTION(tri_mi2s), + MSM_PIN_FUNCTION(uim1_clk), + MSM_PIN_FUNCTION(uim1_data), + MSM_PIN_FUNCTION(uim1_present), + MSM_PIN_FUNCTION(uim1_reset), + MSM_PIN_FUNCTION(uim2_clk), + MSM_PIN_FUNCTION(uim2_data), + MSM_PIN_FUNCTION(uim2_present), + MSM_PIN_FUNCTION(uim2_reset), + MSM_PIN_FUNCTION(usb2phy_ac_en), + MSM_PIN_FUNCTION(vsense_trigger_mirnat), +}; + +static const struct msm_pingroup sdx75_groups[] = { + [0] = PINGROUP(0, uim2_data, ebi0_wrcdc, _, _, _, _, _, _, _, _), + [1] = PINGROUP(1, uim2_present, _, _, _, _, _, _, _, _, _), + [2] = PINGROUP(2, uim2_reset, ebi0_wrcdc, _, _, _, _, _, _, _, _), + [3] = PINGROUP(3, uim2_clk, _, _, _, _, _, _, _, _, _), + [4] = PINGROUP(4, uim1_data, _, _, _, _, _, _, _, _, _), + [5] = PINGROUP(5, uim1_present, _, _, _, _, _, _, _, _, _), + [6] = PINGROUP(6, uim1_reset, char_exec, _, _, _, _, _, _, _, _), + [7] = PINGROUP(7, uim1_clk, char_exec, _, _, _, _, _, _, _, _), + [8] = PINGROUP(8, qup_se0, ldo_en, _, _, _, _, _, _, _, _), + [9] = PINGROUP(9, qup_se0, _, _, _, _, _, _, _, _, _), + [10] = PINGROUP(10, qup_se0, _, _, _, _, _, _, _, _, _), + [11] = PINGROUP(11, qup_se0, _, _, _, _, _, _, _, _, _), + [12] = PINGROUP(12, qup_se1_l2_mira, ext_dbg, _, _, _, _, _, _, _, _), + [13] = PINGROUP(13, qup_se1_l3_mira, ext_dbg, _, _, _, _, _, _, _, _), + [14] = PINGROUP(14, qup_se2, ext_dbg, bimc_dte, _, _, _, _, _, _, _), + [15] = PINGROUP(15, qup_se2, ext_dbg, bimc_dte, _, _, _, _, _, _, _), + [16] = PINGROUP(16, pri_mi2s, qup_se2, qup_se1_l2_mirb, qdss_cti, qdss_cti, _, _, _, _, _), + [17] = PINGROUP(17, pri_mi2s, qup_se2, qup_se1_l3_mirb, qdss_cti, qdss_cti, _, _, _, _, _), + [18] = PINGROUP(18, pri_mi2s, _, _, _, _, _, _, _, _, _), + [19] = PINGROUP(19, pri_mi2s, _, _, _, _, _, _, _, _, _), + [20] = PINGROUP(20, sec_mi2s, _, _, _, _, _, _, _, _, _), + [21] = PINGROUP(21, sec_mi2s, _, _, _, _, _, _, _, _, _), + [22] = PINGROUP(22, sec_mi2s, _, _, _, _, _, _, _, _, _), + [23] = PINGROUP(23, sec_mi2s, _, _, _, _, _, _, _, _, _), + [24] = PINGROUP(24, _, atest_char, _, _, _, _, _, _, _, _), + [25] = PINGROUP(25, gcc_125_clk, _, atest_char, _, _, _, _, _, _, _), + [26] = PINGROUP(26, _, _, qlink1_l_en, dbg_out_clk, atest_char, _, _, _, _, _), + [27] = PINGROUP(27, _, _, qlink1_l_req, prng_rosc, _, _, _, _, _, _), + [28] = PINGROUP(28, _, qlink1_wmss, tmess_prng0, _, _, _, _, _, _, _), + [29] = PINGROUP(29, _, _, _, native_char, tmess_prng1, _, _, _, _, _), + [30] = PINGROUP(30, _, _, _, tmess_prng2, _, _, _, _, _, _), + [31] = PINGROUP(31, _, _, cri_trng0, _, tmess_prng3, _, _, _, _, _), + [32] = PINGROUP(32, _, _, cri_trng1, _, _, _, _, _, _, _), + [33] = PINGROUP(33, _, _, native_char, _, _, _, _, _, _, _), + [34] = PINGROUP(34, _, _, _, _, _, _, _, _, _, _), + [35] = PINGROUP(35, nav_gpio, emac0_ptp, emac0_ptp, _, _, _, _, _, _, _), + [36] = PINGROUP(36, nav_gpio, nav_dr_sync, nav_gpio, cri_trng, prng_rosc, _, _, _, _, _), + [37] = PINGROUP(37, qlink0_l_en, _, pll_ref_clk, prng_rosc, vsense_trigger_mirnat, _, _, _, _, _), + [38] = PINGROUP(38, qlink0_l_req, _, pll_bist_sync, prng_rosc, _, emac_cdc, _, native_tsens, _, _), + [39] = PINGROUP(39, qlink0_wmss, _, mgpi_clk, gcc_gp1_clk, _, emac_cdc, _, _, _, _), + [40] = PINGROUP(40, qlink0_b_en, _, mgpi_clk, pll_clk_aux, gcc_gp2_clk, _, _, _, _, _), + [41] = PINGROUP(41, qlink0_b_req, _, jitter_bist, gcc_gp3_clk, _, _, atest_char, _, _, _), + [42] = PINGROUP(42, pci_e, _, _, _, _, _, _, _, _, _), + [43] = PINGROUP(43, pcie0_clkreq_n, _, _, _, _, _, _, _, _, _), + [44] = PINGROUP(44, _, _, _, _, _, _, _, _, _, _), + [45] = PINGROUP(45, ddr_pxi0, _, _, _, _, _, _, _, _, _), + [46] = PINGROUP(46, coex_uart, ddr_bist, ddr_pxi0, _, _, _, _, _, _, _), + [47] = PINGROUP(47, coex_uart, ddr_bist, _, _, _, _, _, _, _, _), + [48] = PINGROUP(48, coex_uart2, spmi_coex, ddr_bist, _, _, _, _, _, _, _), + [49] = PINGROUP(49, coex_uart2, spmi_coex, ddr_bist, _, _, _, _, _, _, _), + [50] = PINGROUP(50, spmi_vgi, _, _, _, _, _, _, _, _, _), + [51] = PINGROUP(51, spmi_vgi, _, _, _, _, _, _, _, _, _), + [52] = PINGROUP(52, qup_se3, qdss_cti, qdss_cti, _, _, _, _, _, _, _), + [53] = PINGROUP(53, qup_se3, qdss_cti, qdss_cti, _, _, _, _, _, _, _), + [54] = PINGROUP(54, qup_se3, _, _, _, _, _, _, _, _, _), + [55] = PINGROUP(55, qup_se3, tgu_ch0_trigout, _, _, _, _, _, _, _, _), + [56] = PINGROUP(56, qdss_cti, qdss_cti, _, _, _, _, _, _, _, _), + [57] = PINGROUP(57, qdss_cti, qdss_cti, _, native_char, _, _, _, _, _, _), + [58] = PINGROUP(58, _, pa_indicator, _, _, _, _, _, _, _, _), + [59] = PINGROUP(59, adsp_ext, qdss_cti, _, bimc_dte, _, _, _, _, _, _), + [60] = PINGROUP(60, qdss_cti, _, _, _, _, _, _, _, _, _), + [61] = PINGROUP(61, _, bimc_dte, _, _, _, _, _, _, _, _), + [62] = PINGROUP(62, m_voc, ldo_update, _, _, _, _, _, _, _, _), + [63] = PINGROUP(63, m_voc, _, atest_char, _, _, _, _, _, _, _), + [64] = PINGROUP(64, qup_se4, m_voc, _, native_tsense, _, _, _, _, _, _), + [65] = PINGROUP(65, qup_se4, m_voc, _, _, _, _, _, _, _, _), + [66] = PINGROUP(66, _, native_char, _, _, _, _, _, _, _, _), + [67] = PINGROUP(67, _, native_char, _, _, _, _, _, _, _, _), + [68] = PINGROUP(68, adsp_ext, _, _, _, _, _, _, _, _, _), + [69] = PINGROUP(69, _, _, _, _, _, _, _, _, _, _), + [70] = PINGROUP(70, _, _, _, _, _, _, _, _, _, _), + [71] = PINGROUP(71, m_voc, _, _, _, _, _, _, _, _, _), + [72] = PINGROUP(72, _, _, _, _, _, _, _, _, _, _), + [73] = PINGROUP(73, _, _, _, _, _, _, _, _, _, _), + [74] = PINGROUP(74, i2s_mclk, _, _, _, _, _, _, _, _, _), + [75] = PINGROUP(75, _, _, _, _, _, _, _, _, _, _), + [76] = PINGROUP(76, native_tsense, _, _, _, _, _, _, _, _, _), + [77] = PINGROUP(77, _, _, _, _, _, _, _, _, _, _), + [78] = PINGROUP(78, qdss_cti, qdss_cti, _, _, _, _, _, _, _, _), + [79] = PINGROUP(79, qdss_cti, qdss_cti, _, _, _, _, _, _, _, _), + [80] = PINGROUP(80, usb2phy_ac_en, _, _, _, _, _, _, _, _, _), + [81] = PINGROUP(81, gcc_plltest, _, _, _, _, _, _, _, _, _), + [82] = PINGROUP(82, rgmii_txc, gcc_plltest, qdss_gpio, _, _, _, _, _, _, _), + [83] = PINGROUP(83, rgmii_txd, emac0_ptp, emac0_ptp, emac0_mcg, qdss_gpio, _, _, _, _, _), + [84] = PINGROUP(84, rgmii_txd, emac0_ptp, emac0_mcg, qdss_gpio, _, sdc1_tb, _, _, _, _), + [85] = PINGROUP(85, rgmii_txd, emac0_ptp, emac0_mcg, qdss_gpio, _, _, _, _, _, _), + [86] = PINGROUP(86, rgmii_txd, _, _, _, _, _, _, _, _, _), + [87] = PINGROUP(87, rgmii_tx_ctl, _, _, _, _, _, _, _, _, _), + [88] = PINGROUP(88, rgmii_rxc, _, _, _, _, _, _, _, _, _), + [89] = PINGROUP(89, rgmii_rxd, emac0_ptp, emac0_ptp, emac0_mcg, _, _, _, _, _, _), + [90] = PINGROUP(90, rgmii_rxd, coex_uart2, emac1_mcg, _, _, _, _, _, _, _), + [91] = PINGROUP(91, rgmii_rxd, coex_uart2, _, _, _, _, _, _, _, _), + [92] = PINGROUP(92, rgmii_rxd, emac1_mcg, _, _, _, _, _, _, _, _), + [93] = PINGROUP(93, rgmii_rx_ctl, emac1_mcg, _, _, _, _, _, _, _, _), + [94] = PINGROUP(94, eth0_mdc, qdss_gpio, _, _, _, _, _, _, _, _), + [95] = PINGROUP(95, eth0_mdio, qdss_gpio, _, _, _, _, _, _, _, _), + [96] = PINGROUP(96, qdss_gpio, _, _, _, _, _, _, _, _, _), + [97] = PINGROUP(97, sgmii_phy_intr0_n, _, qdss_gpio, _, _, _, _, _, _, _), + [98] = PINGROUP(98, tri_mi2s, ebi2_lcd_te, _, _, _, _, _, _, _, _), + [99] = PINGROUP(99, tri_mi2s, ebi2_lcd, _, _, _, _, _, _, _, _), + [100] = PINGROUP(100, tri_mi2s, ebi2_a, _, _, _, _, _, _, _, _), + [101] = PINGROUP(101, tri_mi2s, ebi2_lcd, _, _, _, _, _, _, _, _), + [102] = PINGROUP(102, _, _, _, _, _, _, _, _, _, _), + [103] = PINGROUP(103, _, _, _, _, _, _, _, _, _, _), + [104] = PINGROUP(104, nav_gpio, _, _, _, _, _, _, _, _, _), + [105] = PINGROUP(105, sd_card, _, _, _, _, _, _, _, _, _), + [106] = PINGROUP(106, eth1_mdc, _, _, _, _, _, _, _, _, _), + [107] = PINGROUP(107, eth1_mdio, _, _, _, _, _, _, _, _, _), + [108] = PINGROUP(108, _, _, _, _, _, _, _, _, _, _), + [109] = PINGROUP(109, sgmii_phy_intr1_n, _, _, _, _, _, _, _, _, _), + [110] = PINGROUP(110, qup_se5, qdss_gpio, _, _, _, _, _, _, _, _), + [111] = PINGROUP(111, qup_se5, qdss_gpio, _, _, _, _, _, _, _, _), + [112] = PINGROUP(112, qup_se6, emac1_ptp, emac1_ptp, qdss_gpio, _, _, _, _, _, _), + [113] = PINGROUP(113, qup_se6, emac1_ptp, emac1_ptp, qdss_gpio, _, _, _, _, _, _), + [114] = PINGROUP(114, qup_se6, emac1_ptp, emac1_ptp, qdss_gpio, _, _, _, _, _, _), + [115] = PINGROUP(115, qup_se6, emac1_ptp, emac1_ptp, qdss_gpio, _, _, _, _, _, _), + [116] = PINGROUP(116, qup_se7, qdss_gpio, _, _, _, _, _, _, _, _), + [117] = PINGROUP(117, qup_se7, qdss_gpio, _, _, _, _, _, _, _, _), + [118] = PINGROUP(118, qup_se7, qdss_gpio, _, _, _, _, _, _, _, _), + [119] = PINGROUP(119, qup_se7, emac0_ptp, qdss_gpio, _, _, _, _, _, _, _), + [120] = PINGROUP(120, _, _, _, _, _, _, _, _, _, _), + [121] = PINGROUP(121, pcie2_clkreq_n, _, _, _, _, _, _, _, _, _), + [122] = PINGROUP(122, emac1_mcg, _, _, _, _, _, _, _, _, _), + [123] = PINGROUP(123, emac0_ptp, emac0_ptp, emac0_ptp, emac0_ptp, _, _, _, _, _, _), + [124] = PINGROUP(124, pcie1_clkreq_n, qup_se8, _, _, _, _, _, _, _, _), + [125] = PINGROUP(125, qup_se8, _, _, _, _, _, _, _, _, _), + [126] = PINGROUP(126, audio_ref_clk, _, _, _, _, _, _, _, _, _), + [127] = PINGROUP(127, emac_pps_in, _, _, _, _, _, _, _, _, _), + [128] = PINGROUP(128, _, _, _, _, _, _, _, _, _, _), + [129] = PINGROUP(129, sdc2_tb_trig, _, _, _, _, _, _, _, _, _), + [130] = PINGROUP(130, sdc1_tb, _, _, _, _, _, _, _, _, _), + [131] = PINGROUP(131, _, _, _, _, _, _, _, _, _, _), + [132] = PINGROUP(132, _, _, _, _, _, _, _, _, _, _), + [133] = SDC_QDSD_PINGROUP(sdc1_rclk, 0x19a000, 16, 0), + [134] = SDC_QDSD_PINGROUP(sdc1_clk, 0x19a000, 14, 6), + [135] = SDC_QDSD_PINGROUP(sdc1_cmd, 0x19a000, 11, 3), + [136] = SDC_QDSD_PINGROUP(sdc1_data, 0x19a000, 9, 0), + [137] = SDC_QDSD_PINGROUP(sdc2_clk, 0x19b000, 14, 6), + [138] = SDC_QDSD_PINGROUP(sdc2_cmd, 0x19b000, 11, 3), + [139] = SDC_QDSD_PINGROUP(sdc2_data, 0x19b000, 9, 0), +}; + +static const struct msm_gpio_wakeirq_map sdx75_pdc_map[] = { + { 1, 57 }, { 2, 91 }, {5, 52 }, { 6, 109 }, { 9, 129 }, { 11, 62 }, + { 13, 84 }, { 15, 87 }, { 17, 88 }, { 18, 89 }, { 19, 90 }, { 20, 92 }, + { 21, 93 }, { 22, 94 }, { 23, 95 }, { 25, 96 }, { 27, 97 }, { 35, 58 }, + { 36, 53 }, { 38, 98 }, { 39, 99 }, { 40, 100 }, { 41, 101 }, { 42, 54 }, + { 43, 56 }, { 44, 71 }, { 46, 60 }, { 47, 61 }, { 49, 47 }, { 50, 126 }, + { 51, 55 }, { 52, 102 }, { 53, 141 }, { 54, 104 }, { 55, 105 }, { 56, 106 }, + { 57, 107 }, { 59, 108 }, { 60, 110 }, { 62, 111 }, { 63, 112 }, { 64, 113 }, + { 65, 114 }, { 67, 115 }, { 68, 116 }, { 69, 117 }, { 70, 118 }, { 71, 119 }, + { 72, 120 }, { 75, 121 }, { 76, 122 }, { 78, 123 }, { 79, 124 }, { 80, 125 }, + { 81, 50 }, { 85, 127 }, { 87, 128 }, { 91, 130 }, { 92, 131 }, { 93, 132 }, + { 94, 133 }, { 95, 134 }, { 97, 135 }, { 98, 136 }, { 101, 64 }, { 103, 51 }, + { 105, 65 }, { 106, 66 }, { 107, 67 }, { 108, 68 }, { 109, 69 }, { 111, 70 }, + { 113, 59 }, { 115, 72 }, { 116, 73 }, { 117, 74 }, { 118, 75 }, { 119, 76 }, + { 120, 77 }, { 121, 78 }, { 123, 79 }, { 124, 80 }, { 125, 63 }, { 127, 81 }, + { 128, 82 }, { 129, 83 }, { 130, 85 }, { 132, 86 }, +}; + +static const struct msm_pinctrl_soc_data sdx75_pinctrl = { + .pins = sdx75_pins, + .npins = ARRAY_SIZE(sdx75_pins), + .functions = sdx75_functions, + .nfunctions = ARRAY_SIZE(sdx75_functions), + .groups = sdx75_groups, + .ngroups = ARRAY_SIZE(sdx75_groups), + .ngpios = 133, + .wakeirq_map = sdx75_pdc_map, + .nwakeirq_map = ARRAY_SIZE(sdx75_pdc_map), +}; + +static const struct of_device_id sdx75_pinctrl_of_match[] = { + { .compatible = "qcom,sdx75-tlmm", .data = &sdx75_pinctrl }, + { } +}; +MODULE_DEVICE_TABLE(of, sdx75_pinctrl_of_match); + +static int sdx75_pinctrl_probe(struct platform_device *pdev) +{ + const struct msm_pinctrl_soc_data *pinctrl_data; + + pinctrl_data = of_device_get_match_data(&pdev->dev); + if (!pinctrl_data) + return -EINVAL; + + return msm_pinctrl_probe(pdev, pinctrl_data); +} + +static struct platform_driver sdx75_pinctrl_driver = { + .driver = { + .name = "sdx75-tlmm", + .of_match_table = sdx75_pinctrl_of_match, + }, + .probe = sdx75_pinctrl_probe, + .remove = msm_pinctrl_remove, +}; + +static int __init sdx75_pinctrl_init(void) +{ + return platform_driver_register(&sdx75_pinctrl_driver); +} +arch_initcall(sdx75_pinctrl_init); + +static void __exit sdx75_pinctrl_exit(void) +{ + platform_driver_unregister(&sdx75_pinctrl_driver); +} +module_exit(sdx75_pinctrl_exit); + +MODULE_DESCRIPTION("QTI sdx75 pinctrl driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/pinctrl/qcom/pinctrl-sm6115.c b/drivers/pinctrl/qcom/pinctrl-sm6115.c index b3a0161ca377a95b49ff5d7eb28959db1e4c67cd..2a06025f48858426c9bb5a9bd2d7eba279a98d46 100644 --- a/drivers/pinctrl/qcom/pinctrl-sm6115.c +++ b/drivers/pinctrl/qcom/pinctrl-sm6115.c @@ -6,7 +6,6 @@ #include #include #include -#include #include "pinctrl-msm.h" @@ -22,18 +21,11 @@ enum { WEST }; -#define FUNCTION(fname) \ - [msm_mux_##fname] = { \ - .name = #fname, \ - .groups = fname##_groups, \ - .ngroups = ARRAY_SIZE(fname##_groups), \ - } - #define PINGROUP(id, _tile, f1, f2, f3, f4, f5, f6, f7, f8, f9) \ { \ - .name = "gpio" #id, \ - .pins = gpio##id##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(gpio##id##_pins), \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ .funcs = (int[]){ \ msm_mux_gpio, /* gpio mode */ \ msm_mux_##f1, \ @@ -71,9 +63,9 @@ enum { #define SDC_QDSD_PINGROUP(pg_name, _tile, ctl, pull, drv) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = ctl, \ .io_reg = 0, \ .intr_cfg_reg = 0, \ @@ -97,9 +89,9 @@ enum { #define UFS_RESET(pg_name, offset) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = offset, \ .io_reg = offset + 0x4, \ .intr_cfg_reg = 0, \ @@ -676,74 +668,74 @@ static const char * const ddr_pxi3_groups[] = { "gpio104", "gpio105", }; -static const struct msm_function sm6115_functions[] = { - FUNCTION(adsp_ext), - FUNCTION(agera_pll), - FUNCTION(atest), - FUNCTION(cam_mclk), - FUNCTION(cci_async), - FUNCTION(cci_i2c), - FUNCTION(cci_timer), - FUNCTION(cri_trng), - FUNCTION(dac_calib), - FUNCTION(dbg_out), - FUNCTION(ddr_bist), - FUNCTION(ddr_pxi0), - FUNCTION(ddr_pxi1), - FUNCTION(ddr_pxi2), - FUNCTION(ddr_pxi3), - FUNCTION(gcc_gp1), - FUNCTION(gcc_gp2), - FUNCTION(gcc_gp3), - FUNCTION(gpio), - FUNCTION(gp_pdm0), - FUNCTION(gp_pdm1), - FUNCTION(gp_pdm2), - FUNCTION(gsm0_tx), - FUNCTION(gsm1_tx), - FUNCTION(jitter_bist), - FUNCTION(mdp_vsync), - FUNCTION(mdp_vsync_out_0), - FUNCTION(mdp_vsync_out_1), - FUNCTION(mpm_pwr), - FUNCTION(mss_lte), - FUNCTION(m_voc), - FUNCTION(nav_gpio), - FUNCTION(pa_indicator), - FUNCTION(pbs), - FUNCTION(pbs_out), - FUNCTION(phase_flag), - FUNCTION(pll_bist), - FUNCTION(pll_bypassnl), - FUNCTION(pll_reset), - FUNCTION(prng_rosc), - FUNCTION(qdss_cti), - FUNCTION(qdss_gpio), - FUNCTION(qup0), - FUNCTION(qup1), - FUNCTION(qup2), - FUNCTION(qup3), - FUNCTION(qup4), - FUNCTION(qup5), - FUNCTION(sdc1_tb), - FUNCTION(sdc2_tb), - FUNCTION(sd_write), - FUNCTION(ssbi_wtr1), - FUNCTION(tgu), - FUNCTION(tsense_pwm), - FUNCTION(uim1_clk), - FUNCTION(uim1_data), - FUNCTION(uim1_present), - FUNCTION(uim1_reset), - FUNCTION(uim2_clk), - FUNCTION(uim2_data), - FUNCTION(uim2_present), - FUNCTION(uim2_reset), - FUNCTION(usb_phy), - FUNCTION(vfr_1), - FUNCTION(vsense_trigger), - FUNCTION(wlan1_adc0), - FUNCTION(wlan1_adc1), +static const struct pinfunction sm6115_functions[] = { + MSM_PIN_FUNCTION(adsp_ext), + MSM_PIN_FUNCTION(agera_pll), + MSM_PIN_FUNCTION(atest), + MSM_PIN_FUNCTION(cam_mclk), + MSM_PIN_FUNCTION(cci_async), + MSM_PIN_FUNCTION(cci_i2c), + MSM_PIN_FUNCTION(cci_timer), + MSM_PIN_FUNCTION(cri_trng), + MSM_PIN_FUNCTION(dac_calib), + MSM_PIN_FUNCTION(dbg_out), + MSM_PIN_FUNCTION(ddr_bist), + MSM_PIN_FUNCTION(ddr_pxi0), + MSM_PIN_FUNCTION(ddr_pxi1), + MSM_PIN_FUNCTION(ddr_pxi2), + MSM_PIN_FUNCTION(ddr_pxi3), + MSM_PIN_FUNCTION(gcc_gp1), + MSM_PIN_FUNCTION(gcc_gp2), + MSM_PIN_FUNCTION(gcc_gp3), + MSM_PIN_FUNCTION(gpio), + MSM_PIN_FUNCTION(gp_pdm0), + MSM_PIN_FUNCTION(gp_pdm1), + MSM_PIN_FUNCTION(gp_pdm2), + MSM_PIN_FUNCTION(gsm0_tx), + MSM_PIN_FUNCTION(gsm1_tx), + MSM_PIN_FUNCTION(jitter_bist), + MSM_PIN_FUNCTION(mdp_vsync), + MSM_PIN_FUNCTION(mdp_vsync_out_0), + MSM_PIN_FUNCTION(mdp_vsync_out_1), + MSM_PIN_FUNCTION(mpm_pwr), + MSM_PIN_FUNCTION(mss_lte), + MSM_PIN_FUNCTION(m_voc), + MSM_PIN_FUNCTION(nav_gpio), + MSM_PIN_FUNCTION(pa_indicator), + MSM_PIN_FUNCTION(pbs), + MSM_PIN_FUNCTION(pbs_out), + MSM_PIN_FUNCTION(phase_flag), + MSM_PIN_FUNCTION(pll_bist), + MSM_PIN_FUNCTION(pll_bypassnl), + MSM_PIN_FUNCTION(pll_reset), + MSM_PIN_FUNCTION(prng_rosc), + MSM_PIN_FUNCTION(qdss_cti), + MSM_PIN_FUNCTION(qdss_gpio), + MSM_PIN_FUNCTION(qup0), + MSM_PIN_FUNCTION(qup1), + MSM_PIN_FUNCTION(qup2), + MSM_PIN_FUNCTION(qup3), + MSM_PIN_FUNCTION(qup4), + MSM_PIN_FUNCTION(qup5), + MSM_PIN_FUNCTION(sdc1_tb), + MSM_PIN_FUNCTION(sdc2_tb), + MSM_PIN_FUNCTION(sd_write), + MSM_PIN_FUNCTION(ssbi_wtr1), + MSM_PIN_FUNCTION(tgu), + MSM_PIN_FUNCTION(tsense_pwm), + MSM_PIN_FUNCTION(uim1_clk), + MSM_PIN_FUNCTION(uim1_data), + MSM_PIN_FUNCTION(uim1_present), + MSM_PIN_FUNCTION(uim1_reset), + MSM_PIN_FUNCTION(uim2_clk), + MSM_PIN_FUNCTION(uim2_data), + MSM_PIN_FUNCTION(uim2_present), + MSM_PIN_FUNCTION(uim2_reset), + MSM_PIN_FUNCTION(usb_phy), + MSM_PIN_FUNCTION(vfr_1), + MSM_PIN_FUNCTION(vsense_trigger), + MSM_PIN_FUNCTION(wlan1_adc0), + MSM_PIN_FUNCTION(wlan1_adc1), }; /* Every pin is maintained as a single group, and missing or non-existing pin diff --git a/drivers/pinctrl/qcom/pinctrl-sm6125.c b/drivers/pinctrl/qcom/pinctrl-sm6125.c index 170d4ffbb919980dee634345e2d9bc554b3d1e21..d5e2b896954c220c13da2835aa32f5e288903205 100644 --- a/drivers/pinctrl/qcom/pinctrl-sm6125.c +++ b/drivers/pinctrl/qcom/pinctrl-sm6125.c @@ -3,7 +3,6 @@ #include #include #include -#include #include "pinctrl-msm.h" @@ -19,18 +18,11 @@ enum { WEST }; -#define FUNCTION(fname) \ - [msm_mux_##fname] = { \ - .name = #fname, \ - .groups = fname##_groups, \ - .ngroups = ARRAY_SIZE(fname##_groups), \ - } - #define PINGROUP(id, _tile, f1, f2, f3, f4, f5, f6, f7, f8, f9) \ { \ - .name = "gpio" #id, \ - .pins = gpio##id##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(gpio##id##_pins), \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ .funcs = (int[]){ \ msm_mux_gpio, /* gpio mode */ \ msm_mux_##f1, \ @@ -68,9 +60,9 @@ enum { #define SDC_QDSD_PINGROUP(pg_name, _tile, ctl, pull, drv) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = ctl, \ .io_reg = 0, \ .intr_cfg_reg = 0, \ @@ -94,9 +86,9 @@ enum { #define UFS_RESET(pg_name, offset) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = offset, \ .io_reg = offset + 0x4, \ .intr_cfg_reg = 0, \ @@ -949,134 +941,134 @@ static const char * const dmic1_data_groups[] = { "gpio128", }; -static const struct msm_function sm6125_functions[] = { - FUNCTION(qup00), - FUNCTION(gpio), - FUNCTION(qdss), - FUNCTION(qup01), - FUNCTION(qup02), - FUNCTION(ddr_pxi0), - FUNCTION(ddr_bist), - FUNCTION(atest_tsens2), - FUNCTION(vsense_trigger), - FUNCTION(atest_usb1), - FUNCTION(gp_pdm1), - FUNCTION(phase_flag), - FUNCTION(dbg_out), - FUNCTION(qup14), - FUNCTION(atest_usb11), - FUNCTION(ddr_pxi2), - FUNCTION(atest_usb10), - FUNCTION(jitter_bist), - FUNCTION(ddr_pxi3), - FUNCTION(pll_bypassnl), - FUNCTION(pll_bist), - FUNCTION(qup03), - FUNCTION(pll_reset), - FUNCTION(agera_pll), - FUNCTION(qdss_cti), - FUNCTION(qup04), - FUNCTION(wlan2_adc1), - FUNCTION(wlan2_adc0), - FUNCTION(wsa_clk), - FUNCTION(qup13), - FUNCTION(ter_mi2s), - FUNCTION(wsa_data), - FUNCTION(qup10), - FUNCTION(gcc_gp3), - FUNCTION(qup12), - FUNCTION(sd_write), - FUNCTION(qup11), - FUNCTION(cam_mclk), - FUNCTION(atest_tsens), - FUNCTION(cci_i2c), - FUNCTION(cci_timer2), - FUNCTION(cci_timer1), - FUNCTION(gcc_gp2), - FUNCTION(cci_async), - FUNCTION(cci_timer4), - FUNCTION(cci_timer0), - FUNCTION(gcc_gp1), - FUNCTION(cci_timer3), - FUNCTION(wlan1_adc1), - FUNCTION(wlan1_adc0), - FUNCTION(qlink_request), - FUNCTION(qlink_enable), - FUNCTION(pa_indicator), - FUNCTION(nav_pps), - FUNCTION(gps_tx), - FUNCTION(gp_pdm0), - FUNCTION(atest_usb13), - FUNCTION(ddr_pxi1), - FUNCTION(atest_usb12), - FUNCTION(cri_trng0), - FUNCTION(cri_trng), - FUNCTION(cri_trng1), - FUNCTION(gp_pdm2), - FUNCTION(sp_cmu), - FUNCTION(atest_usb2), - FUNCTION(atest_usb23), - FUNCTION(uim2_data), - FUNCTION(uim2_clk), - FUNCTION(uim2_reset), - FUNCTION(atest_usb22), - FUNCTION(uim2_present), - FUNCTION(atest_usb21), - FUNCTION(uim1_data), - FUNCTION(atest_usb20), - FUNCTION(uim1_clk), - FUNCTION(uim1_reset), - FUNCTION(uim1_present), - FUNCTION(mdp_vsync), - FUNCTION(copy_gp), - FUNCTION(tsense_pwm), - FUNCTION(mpm_pwr), - FUNCTION(tgu_ch3), - FUNCTION(mdp_vsync0), - FUNCTION(mdp_vsync1), - FUNCTION(mdp_vsync2), - FUNCTION(mdp_vsync3), - FUNCTION(mdp_vsync4), - FUNCTION(mdp_vsync5), - FUNCTION(tgu_ch0), - FUNCTION(tgu_ch1), - FUNCTION(atest_char1), - FUNCTION(vfr_1), - FUNCTION(tgu_ch2), - FUNCTION(atest_char0), - FUNCTION(atest_char2), - FUNCTION(atest_char3), - FUNCTION(ldo_en), - FUNCTION(ldo_update), - FUNCTION(prng_rosc), - FUNCTION(dp_hot), - FUNCTION(debug_hot), - FUNCTION(copy_phase), - FUNCTION(usb_phy), - FUNCTION(atest_char), - FUNCTION(unused1), - FUNCTION(qua_mi2s), - FUNCTION(mss_lte), - FUNCTION(swr_tx), - FUNCTION(aud_sb), - FUNCTION(unused2), - FUNCTION(swr_rx), - FUNCTION(edp_hot), - FUNCTION(audio_ref), - FUNCTION(pri_mi2s), - FUNCTION(pri_mi2s_ws), - FUNCTION(adsp_ext), - FUNCTION(edp_lcd), - FUNCTION(mclk2), - FUNCTION(m_voc), - FUNCTION(mclk1), - FUNCTION(qca_sb), - FUNCTION(qui_mi2s), - FUNCTION(dmic0_clk), - FUNCTION(sec_mi2s), - FUNCTION(dmic0_data), - FUNCTION(dmic1_clk), - FUNCTION(dmic1_data), +static const struct pinfunction sm6125_functions[] = { + MSM_PIN_FUNCTION(qup00), + MSM_PIN_FUNCTION(gpio), + MSM_PIN_FUNCTION(qdss), + MSM_PIN_FUNCTION(qup01), + MSM_PIN_FUNCTION(qup02), + MSM_PIN_FUNCTION(ddr_pxi0), + MSM_PIN_FUNCTION(ddr_bist), + MSM_PIN_FUNCTION(atest_tsens2), + MSM_PIN_FUNCTION(vsense_trigger), + MSM_PIN_FUNCTION(atest_usb1), + MSM_PIN_FUNCTION(gp_pdm1), + MSM_PIN_FUNCTION(phase_flag), + MSM_PIN_FUNCTION(dbg_out), + MSM_PIN_FUNCTION(qup14), + MSM_PIN_FUNCTION(atest_usb11), + MSM_PIN_FUNCTION(ddr_pxi2), + MSM_PIN_FUNCTION(atest_usb10), + MSM_PIN_FUNCTION(jitter_bist), + MSM_PIN_FUNCTION(ddr_pxi3), + MSM_PIN_FUNCTION(pll_bypassnl), + MSM_PIN_FUNCTION(pll_bist), + MSM_PIN_FUNCTION(qup03), + MSM_PIN_FUNCTION(pll_reset), + MSM_PIN_FUNCTION(agera_pll), + MSM_PIN_FUNCTION(qdss_cti), + MSM_PIN_FUNCTION(qup04), + MSM_PIN_FUNCTION(wlan2_adc1), + MSM_PIN_FUNCTION(wlan2_adc0), + MSM_PIN_FUNCTION(wsa_clk), + MSM_PIN_FUNCTION(qup13), + MSM_PIN_FUNCTION(ter_mi2s), + MSM_PIN_FUNCTION(wsa_data), + MSM_PIN_FUNCTION(qup10), + MSM_PIN_FUNCTION(gcc_gp3), + MSM_PIN_FUNCTION(qup12), + MSM_PIN_FUNCTION(sd_write), + MSM_PIN_FUNCTION(qup11), + MSM_PIN_FUNCTION(cam_mclk), + MSM_PIN_FUNCTION(atest_tsens), + MSM_PIN_FUNCTION(cci_i2c), + MSM_PIN_FUNCTION(cci_timer2), + MSM_PIN_FUNCTION(cci_timer1), + MSM_PIN_FUNCTION(gcc_gp2), + MSM_PIN_FUNCTION(cci_async), + MSM_PIN_FUNCTION(cci_timer4), + MSM_PIN_FUNCTION(cci_timer0), + MSM_PIN_FUNCTION(gcc_gp1), + MSM_PIN_FUNCTION(cci_timer3), + MSM_PIN_FUNCTION(wlan1_adc1), + MSM_PIN_FUNCTION(wlan1_adc0), + MSM_PIN_FUNCTION(qlink_request), + MSM_PIN_FUNCTION(qlink_enable), + MSM_PIN_FUNCTION(pa_indicator), + MSM_PIN_FUNCTION(nav_pps), + MSM_PIN_FUNCTION(gps_tx), + MSM_PIN_FUNCTION(gp_pdm0), + MSM_PIN_FUNCTION(atest_usb13), + MSM_PIN_FUNCTION(ddr_pxi1), + MSM_PIN_FUNCTION(atest_usb12), + MSM_PIN_FUNCTION(cri_trng0), + MSM_PIN_FUNCTION(cri_trng), + MSM_PIN_FUNCTION(cri_trng1), + MSM_PIN_FUNCTION(gp_pdm2), + MSM_PIN_FUNCTION(sp_cmu), + MSM_PIN_FUNCTION(atest_usb2), + MSM_PIN_FUNCTION(atest_usb23), + MSM_PIN_FUNCTION(uim2_data), + MSM_PIN_FUNCTION(uim2_clk), + MSM_PIN_FUNCTION(uim2_reset), + MSM_PIN_FUNCTION(atest_usb22), + MSM_PIN_FUNCTION(uim2_present), + MSM_PIN_FUNCTION(atest_usb21), + MSM_PIN_FUNCTION(uim1_data), + MSM_PIN_FUNCTION(atest_usb20), + MSM_PIN_FUNCTION(uim1_clk), + MSM_PIN_FUNCTION(uim1_reset), + MSM_PIN_FUNCTION(uim1_present), + MSM_PIN_FUNCTION(mdp_vsync), + MSM_PIN_FUNCTION(copy_gp), + MSM_PIN_FUNCTION(tsense_pwm), + MSM_PIN_FUNCTION(mpm_pwr), + MSM_PIN_FUNCTION(tgu_ch3), + MSM_PIN_FUNCTION(mdp_vsync0), + MSM_PIN_FUNCTION(mdp_vsync1), + MSM_PIN_FUNCTION(mdp_vsync2), + MSM_PIN_FUNCTION(mdp_vsync3), + MSM_PIN_FUNCTION(mdp_vsync4), + MSM_PIN_FUNCTION(mdp_vsync5), + MSM_PIN_FUNCTION(tgu_ch0), + MSM_PIN_FUNCTION(tgu_ch1), + MSM_PIN_FUNCTION(atest_char1), + MSM_PIN_FUNCTION(vfr_1), + MSM_PIN_FUNCTION(tgu_ch2), + MSM_PIN_FUNCTION(atest_char0), + MSM_PIN_FUNCTION(atest_char2), + MSM_PIN_FUNCTION(atest_char3), + MSM_PIN_FUNCTION(ldo_en), + MSM_PIN_FUNCTION(ldo_update), + MSM_PIN_FUNCTION(prng_rosc), + MSM_PIN_FUNCTION(dp_hot), + MSM_PIN_FUNCTION(debug_hot), + MSM_PIN_FUNCTION(copy_phase), + MSM_PIN_FUNCTION(usb_phy), + MSM_PIN_FUNCTION(atest_char), + MSM_PIN_FUNCTION(unused1), + MSM_PIN_FUNCTION(qua_mi2s), + MSM_PIN_FUNCTION(mss_lte), + MSM_PIN_FUNCTION(swr_tx), + MSM_PIN_FUNCTION(aud_sb), + MSM_PIN_FUNCTION(unused2), + MSM_PIN_FUNCTION(swr_rx), + MSM_PIN_FUNCTION(edp_hot), + MSM_PIN_FUNCTION(audio_ref), + MSM_PIN_FUNCTION(pri_mi2s), + MSM_PIN_FUNCTION(pri_mi2s_ws), + MSM_PIN_FUNCTION(adsp_ext), + MSM_PIN_FUNCTION(edp_lcd), + MSM_PIN_FUNCTION(mclk2), + MSM_PIN_FUNCTION(m_voc), + MSM_PIN_FUNCTION(mclk1), + MSM_PIN_FUNCTION(qca_sb), + MSM_PIN_FUNCTION(qui_mi2s), + MSM_PIN_FUNCTION(dmic0_clk), + MSM_PIN_FUNCTION(sec_mi2s), + MSM_PIN_FUNCTION(dmic0_data), + MSM_PIN_FUNCTION(dmic1_clk), + MSM_PIN_FUNCTION(dmic1_data), }; /* diff --git a/drivers/pinctrl/qcom/pinctrl-sm6350.c b/drivers/pinctrl/qcom/pinctrl-sm6350.c index a91a86628f2f87fec7d2cecca8e60b0967f27448..f3828c07b134500e4307db1d42aabae389a03360 100644 --- a/drivers/pinctrl/qcom/pinctrl-sm6350.c +++ b/drivers/pinctrl/qcom/pinctrl-sm6350.c @@ -7,23 +7,15 @@ #include #include #include -#include #include "pinctrl-msm.h" -#define FUNCTION(fname) \ - [msm_mux_##fname] = { \ - .name = #fname, \ - .groups = fname##_groups, \ - .ngroups = ARRAY_SIZE(fname##_groups), \ - } - #define REG_SIZE 0x1000 #define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9) \ { \ - .name = "gpio" #id, \ - .pins = gpio##id##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(gpio##id##_pins), \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ .funcs = (int[]){ \ msm_mux_gpio, /* gpio mode */ \ msm_mux_##f1, \ @@ -60,9 +52,9 @@ #define SDC_PINGROUP(pg_name, ctl, pull, drv) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = ctl, \ .io_reg = 0, \ .intr_cfg_reg = 0, \ @@ -85,9 +77,9 @@ #define UFS_RESET(pg_name, offset) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = offset, \ .io_reg = offset + 0x4, \ .intr_cfg_reg = 0, \ @@ -1016,141 +1008,141 @@ static const char * const usb_phy_groups[] = { "gpio124", }; -static const struct msm_function sm6350_functions[] = { - FUNCTION(adsp_ext), - FUNCTION(agera_pll), - FUNCTION(atest_char), - FUNCTION(atest_char0), - FUNCTION(atest_char1), - FUNCTION(atest_char2), - FUNCTION(atest_char3), - FUNCTION(atest_tsens), - FUNCTION(atest_tsens2), - FUNCTION(atest_usb), - FUNCTION(audio_ref), - FUNCTION(btfm_slimbus), - FUNCTION(cam_mclk0), - FUNCTION(cam_mclk1), - FUNCTION(cam_mclk2), - FUNCTION(cam_mclk3), - FUNCTION(cam_mclk4), - FUNCTION(cci_async), - FUNCTION(cci_i2c), - FUNCTION(cci_timer0), - FUNCTION(cci_timer1), - FUNCTION(cci_timer2), - FUNCTION(cci_timer3), - FUNCTION(cci_timer4), - FUNCTION(cri_trng), - FUNCTION(dbg_out), - FUNCTION(ddr_bist), - FUNCTION(ddr_pxi0), - FUNCTION(ddr_pxi1), - FUNCTION(ddr_pxi2), - FUNCTION(ddr_pxi3), - FUNCTION(dp_hot), - FUNCTION(edp_lcd), - FUNCTION(gcc_gp1), - FUNCTION(gcc_gp2), - FUNCTION(gcc_gp3), - FUNCTION(gp_pdm0), - FUNCTION(gp_pdm1), - FUNCTION(gp_pdm2), - FUNCTION(gpio), - FUNCTION(gps_tx), - FUNCTION(ibi_i3c), - FUNCTION(jitter_bist), - FUNCTION(ldo_en), - FUNCTION(ldo_update), - FUNCTION(lpass_ext), - FUNCTION(m_voc), - FUNCTION(mclk), - FUNCTION(mdp_vsync), - FUNCTION(mdp_vsync0), - FUNCTION(mdp_vsync1), - FUNCTION(mdp_vsync2), - FUNCTION(mdp_vsync3), - FUNCTION(mi2s_0), - FUNCTION(mi2s_1), - FUNCTION(mi2s_2), - FUNCTION(mss_lte), - FUNCTION(nav_gpio), - FUNCTION(nav_pps), - FUNCTION(pa_indicator), - FUNCTION(pcie0_clk), - FUNCTION(phase_flag), - FUNCTION(pll_bist), - FUNCTION(pll_bypassnl), - FUNCTION(pll_reset), - FUNCTION(prng_rosc), - FUNCTION(qdss_cti), - FUNCTION(qdss_gpio), - FUNCTION(qdss_gpio0), - FUNCTION(qdss_gpio1), - FUNCTION(qdss_gpio10), - FUNCTION(qdss_gpio11), - FUNCTION(qdss_gpio12), - FUNCTION(qdss_gpio13), - FUNCTION(qdss_gpio14), - FUNCTION(qdss_gpio15), - FUNCTION(qdss_gpio2), - FUNCTION(qdss_gpio3), - FUNCTION(qdss_gpio4), - FUNCTION(qdss_gpio5), - FUNCTION(qdss_gpio6), - FUNCTION(qdss_gpio7), - FUNCTION(qdss_gpio8), - FUNCTION(qdss_gpio9), - FUNCTION(qlink0_enable), - FUNCTION(qlink0_request), - FUNCTION(qlink0_wmss), - FUNCTION(qlink1_enable), - FUNCTION(qlink1_request), - FUNCTION(qlink1_wmss), - FUNCTION(qup00), - FUNCTION(qup01), - FUNCTION(qup02), - FUNCTION(qup10), - FUNCTION(qup11), - FUNCTION(qup12), - FUNCTION(qup13_f1), - FUNCTION(qup13_f2), - FUNCTION(qup14), - FUNCTION(rffe0_clk), - FUNCTION(rffe0_data), - FUNCTION(rffe1_clk), - FUNCTION(rffe1_data), - FUNCTION(rffe2_clk), - FUNCTION(rffe2_data), - FUNCTION(rffe3_clk), - FUNCTION(rffe3_data), - FUNCTION(rffe4_clk), - FUNCTION(rffe4_data), - FUNCTION(sd_write), - FUNCTION(sdc1_tb), - FUNCTION(sdc2_tb), - FUNCTION(sp_cmu), - FUNCTION(tgu_ch0), - FUNCTION(tgu_ch1), - FUNCTION(tgu_ch2), - FUNCTION(tgu_ch3), - FUNCTION(tsense_pwm1), - FUNCTION(tsense_pwm2), - FUNCTION(uim1_clk), - FUNCTION(uim1_data), - FUNCTION(uim1_present), - FUNCTION(uim1_reset), - FUNCTION(uim2_clk), - FUNCTION(uim2_data), - FUNCTION(uim2_present), - FUNCTION(uim2_reset), - FUNCTION(usb_phy), - FUNCTION(vfr_1), - FUNCTION(vsense_trigger), - FUNCTION(wlan1_adc0), - FUNCTION(wlan1_adc1), - FUNCTION(wlan2_adc0), - FUNCTION(wlan2_adc1), +static const struct pinfunction sm6350_functions[] = { + MSM_PIN_FUNCTION(adsp_ext), + MSM_PIN_FUNCTION(agera_pll), + MSM_PIN_FUNCTION(atest_char), + MSM_PIN_FUNCTION(atest_char0), + MSM_PIN_FUNCTION(atest_char1), + MSM_PIN_FUNCTION(atest_char2), + MSM_PIN_FUNCTION(atest_char3), + MSM_PIN_FUNCTION(atest_tsens), + MSM_PIN_FUNCTION(atest_tsens2), + MSM_PIN_FUNCTION(atest_usb), + MSM_PIN_FUNCTION(audio_ref), + MSM_PIN_FUNCTION(btfm_slimbus), + MSM_PIN_FUNCTION(cam_mclk0), + MSM_PIN_FUNCTION(cam_mclk1), + MSM_PIN_FUNCTION(cam_mclk2), + MSM_PIN_FUNCTION(cam_mclk3), + MSM_PIN_FUNCTION(cam_mclk4), + MSM_PIN_FUNCTION(cci_async), + MSM_PIN_FUNCTION(cci_i2c), + MSM_PIN_FUNCTION(cci_timer0), + MSM_PIN_FUNCTION(cci_timer1), + MSM_PIN_FUNCTION(cci_timer2), + MSM_PIN_FUNCTION(cci_timer3), + MSM_PIN_FUNCTION(cci_timer4), + MSM_PIN_FUNCTION(cri_trng), + MSM_PIN_FUNCTION(dbg_out), + MSM_PIN_FUNCTION(ddr_bist), + MSM_PIN_FUNCTION(ddr_pxi0), + MSM_PIN_FUNCTION(ddr_pxi1), + MSM_PIN_FUNCTION(ddr_pxi2), + MSM_PIN_FUNCTION(ddr_pxi3), + MSM_PIN_FUNCTION(dp_hot), + MSM_PIN_FUNCTION(edp_lcd), + MSM_PIN_FUNCTION(gcc_gp1), + MSM_PIN_FUNCTION(gcc_gp2), + MSM_PIN_FUNCTION(gcc_gp3), + MSM_PIN_FUNCTION(gp_pdm0), + MSM_PIN_FUNCTION(gp_pdm1), + MSM_PIN_FUNCTION(gp_pdm2), + MSM_PIN_FUNCTION(gpio), + MSM_PIN_FUNCTION(gps_tx), + MSM_PIN_FUNCTION(ibi_i3c), + MSM_PIN_FUNCTION(jitter_bist), + MSM_PIN_FUNCTION(ldo_en), + MSM_PIN_FUNCTION(ldo_update), + MSM_PIN_FUNCTION(lpass_ext), + MSM_PIN_FUNCTION(m_voc), + MSM_PIN_FUNCTION(mclk), + MSM_PIN_FUNCTION(mdp_vsync), + MSM_PIN_FUNCTION(mdp_vsync0), + MSM_PIN_FUNCTION(mdp_vsync1), + MSM_PIN_FUNCTION(mdp_vsync2), + MSM_PIN_FUNCTION(mdp_vsync3), + MSM_PIN_FUNCTION(mi2s_0), + MSM_PIN_FUNCTION(mi2s_1), + MSM_PIN_FUNCTION(mi2s_2), + MSM_PIN_FUNCTION(mss_lte), + MSM_PIN_FUNCTION(nav_gpio), + MSM_PIN_FUNCTION(nav_pps), + MSM_PIN_FUNCTION(pa_indicator), + MSM_PIN_FUNCTION(pcie0_clk), + MSM_PIN_FUNCTION(phase_flag), + MSM_PIN_FUNCTION(pll_bist), + MSM_PIN_FUNCTION(pll_bypassnl), + MSM_PIN_FUNCTION(pll_reset), + MSM_PIN_FUNCTION(prng_rosc), + MSM_PIN_FUNCTION(qdss_cti), + MSM_PIN_FUNCTION(qdss_gpio), + MSM_PIN_FUNCTION(qdss_gpio0), + MSM_PIN_FUNCTION(qdss_gpio1), + MSM_PIN_FUNCTION(qdss_gpio10), + MSM_PIN_FUNCTION(qdss_gpio11), + MSM_PIN_FUNCTION(qdss_gpio12), + MSM_PIN_FUNCTION(qdss_gpio13), + MSM_PIN_FUNCTION(qdss_gpio14), + MSM_PIN_FUNCTION(qdss_gpio15), + MSM_PIN_FUNCTION(qdss_gpio2), + MSM_PIN_FUNCTION(qdss_gpio3), + MSM_PIN_FUNCTION(qdss_gpio4), + MSM_PIN_FUNCTION(qdss_gpio5), + MSM_PIN_FUNCTION(qdss_gpio6), + MSM_PIN_FUNCTION(qdss_gpio7), + MSM_PIN_FUNCTION(qdss_gpio8), + MSM_PIN_FUNCTION(qdss_gpio9), + MSM_PIN_FUNCTION(qlink0_enable), + MSM_PIN_FUNCTION(qlink0_request), + MSM_PIN_FUNCTION(qlink0_wmss), + MSM_PIN_FUNCTION(qlink1_enable), + MSM_PIN_FUNCTION(qlink1_request), + MSM_PIN_FUNCTION(qlink1_wmss), + MSM_PIN_FUNCTION(qup00), + MSM_PIN_FUNCTION(qup01), + MSM_PIN_FUNCTION(qup02), + MSM_PIN_FUNCTION(qup10), + MSM_PIN_FUNCTION(qup11), + MSM_PIN_FUNCTION(qup12), + MSM_PIN_FUNCTION(qup13_f1), + MSM_PIN_FUNCTION(qup13_f2), + MSM_PIN_FUNCTION(qup14), + MSM_PIN_FUNCTION(rffe0_clk), + MSM_PIN_FUNCTION(rffe0_data), + MSM_PIN_FUNCTION(rffe1_clk), + MSM_PIN_FUNCTION(rffe1_data), + MSM_PIN_FUNCTION(rffe2_clk), + MSM_PIN_FUNCTION(rffe2_data), + MSM_PIN_FUNCTION(rffe3_clk), + MSM_PIN_FUNCTION(rffe3_data), + MSM_PIN_FUNCTION(rffe4_clk), + MSM_PIN_FUNCTION(rffe4_data), + MSM_PIN_FUNCTION(sd_write), + MSM_PIN_FUNCTION(sdc1_tb), + MSM_PIN_FUNCTION(sdc2_tb), + MSM_PIN_FUNCTION(sp_cmu), + MSM_PIN_FUNCTION(tgu_ch0), + MSM_PIN_FUNCTION(tgu_ch1), + MSM_PIN_FUNCTION(tgu_ch2), + MSM_PIN_FUNCTION(tgu_ch3), + MSM_PIN_FUNCTION(tsense_pwm1), + MSM_PIN_FUNCTION(tsense_pwm2), + MSM_PIN_FUNCTION(uim1_clk), + MSM_PIN_FUNCTION(uim1_data), + MSM_PIN_FUNCTION(uim1_present), + MSM_PIN_FUNCTION(uim1_reset), + MSM_PIN_FUNCTION(uim2_clk), + MSM_PIN_FUNCTION(uim2_data), + MSM_PIN_FUNCTION(uim2_present), + MSM_PIN_FUNCTION(uim2_reset), + MSM_PIN_FUNCTION(usb_phy), + MSM_PIN_FUNCTION(vfr_1), + MSM_PIN_FUNCTION(vsense_trigger), + MSM_PIN_FUNCTION(wlan1_adc0), + MSM_PIN_FUNCTION(wlan1_adc1), + MSM_PIN_FUNCTION(wlan2_adc0), + MSM_PIN_FUNCTION(wlan2_adc1), }; /* diff --git a/drivers/pinctrl/qcom/pinctrl-sm6375.c b/drivers/pinctrl/qcom/pinctrl-sm6375.c index 1138e683e6f49c5870f78e871fc9bd069f56a66f..c82c8516932ea2e1880284fa86bdaf3683f024cc 100644 --- a/drivers/pinctrl/qcom/pinctrl-sm6375.c +++ b/drivers/pinctrl/qcom/pinctrl-sm6375.c @@ -7,24 +7,16 @@ #include #include #include -#include #include "pinctrl-msm.h" -#define FUNCTION(fname) \ - [msm_mux_##fname] = { \ - .name = #fname, \ - .groups = fname##_groups, \ - .ngroups = ARRAY_SIZE(fname##_groups), \ - } - #define REG_BASE 0x100000 #define REG_SIZE 0x1000 #define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9) \ { \ - .name = "gpio" #id, \ - .pins = gpio##id##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(gpio##id##_pins), \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ .funcs = (int[]){ \ msm_mux_gpio, /* gpio mode */ \ msm_mux_##f1, \ @@ -63,9 +55,9 @@ #define SDC_PINGROUP(pg_name, ctl, pull, drv) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = ctl, \ .io_reg = 0, \ .intr_cfg_reg = 0, \ @@ -88,9 +80,9 @@ #define UFS_RESET(pg_name, offset) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = offset, \ .io_reg = offset + 0x4, \ .intr_cfg_reg = 0, \ @@ -1135,172 +1127,172 @@ static const char * const wlan2_adc1_groups[] = { "gpio93", }; -static const struct msm_function sm6375_functions[] = { - FUNCTION(adsp_ext), - FUNCTION(agera_pll), - FUNCTION(atest_char), - FUNCTION(atest_char0), - FUNCTION(atest_char1), - FUNCTION(atest_char2), - FUNCTION(atest_char3), - FUNCTION(atest_tsens), - FUNCTION(atest_tsens2), - FUNCTION(atest_usb1), - FUNCTION(atest_usb10), - FUNCTION(atest_usb11), - FUNCTION(atest_usb12), - FUNCTION(atest_usb13), - FUNCTION(atest_usb2), - FUNCTION(atest_usb20), - FUNCTION(atest_usb21), - FUNCTION(atest_usb22), - FUNCTION(atest_usb23), - FUNCTION(audio_ref), - FUNCTION(btfm_slimbus), - FUNCTION(cam_mclk), - FUNCTION(cci_async), - FUNCTION(cci_i2c), - FUNCTION(cci_timer0), - FUNCTION(cci_timer1), - FUNCTION(cci_timer2), - FUNCTION(cci_timer3), - FUNCTION(cci_timer4), - FUNCTION(cri_trng), - FUNCTION(dbg_out), - FUNCTION(ddr_bist), - FUNCTION(ddr_pxi0), - FUNCTION(ddr_pxi1), - FUNCTION(ddr_pxi2), - FUNCTION(ddr_pxi3), - FUNCTION(dp_hot), - FUNCTION(edp_lcd), - FUNCTION(gcc_gp1), - FUNCTION(gcc_gp2), - FUNCTION(gcc_gp3), - FUNCTION(gp_pdm0), - FUNCTION(gp_pdm1), - FUNCTION(gp_pdm2), - FUNCTION(gpio), - FUNCTION(gps_tx), - FUNCTION(ibi_i3c), - FUNCTION(jitter_bist), - FUNCTION(ldo_en), - FUNCTION(ldo_update), - FUNCTION(lpass_ext), - FUNCTION(m_voc), - FUNCTION(mclk), - FUNCTION(mdp_vsync), - FUNCTION(mdp_vsync0), - FUNCTION(mdp_vsync1), - FUNCTION(mdp_vsync2), - FUNCTION(mdp_vsync3), - FUNCTION(mi2s_0), - FUNCTION(mi2s_1), - FUNCTION(mi2s_2), - FUNCTION(mss_lte), - FUNCTION(nav_gpio), - FUNCTION(nav_pps), - FUNCTION(pa_indicator), - FUNCTION(phase_flag0), - FUNCTION(phase_flag1), - FUNCTION(phase_flag10), - FUNCTION(phase_flag11), - FUNCTION(phase_flag12), - FUNCTION(phase_flag13), - FUNCTION(phase_flag14), - FUNCTION(phase_flag15), - FUNCTION(phase_flag16), - FUNCTION(phase_flag17), - FUNCTION(phase_flag18), - FUNCTION(phase_flag19), - FUNCTION(phase_flag2), - FUNCTION(phase_flag20), - FUNCTION(phase_flag21), - FUNCTION(phase_flag22), - FUNCTION(phase_flag23), - FUNCTION(phase_flag24), - FUNCTION(phase_flag25), - FUNCTION(phase_flag26), - FUNCTION(phase_flag27), - FUNCTION(phase_flag28), - FUNCTION(phase_flag29), - FUNCTION(phase_flag3), - FUNCTION(phase_flag30), - FUNCTION(phase_flag31), - FUNCTION(phase_flag4), - FUNCTION(phase_flag5), - FUNCTION(phase_flag6), - FUNCTION(phase_flag7), - FUNCTION(phase_flag8), - FUNCTION(phase_flag9), - FUNCTION(pll_bist), - FUNCTION(pll_bypassnl), - FUNCTION(pll_clk), - FUNCTION(pll_reset), - FUNCTION(prng_rosc0), - FUNCTION(prng_rosc1), - FUNCTION(prng_rosc2), - FUNCTION(prng_rosc3), - FUNCTION(qdss_cti), - FUNCTION(qdss_gpio), - FUNCTION(qdss_gpio0), - FUNCTION(qdss_gpio1), - FUNCTION(qdss_gpio10), - FUNCTION(qdss_gpio11), - FUNCTION(qdss_gpio12), - FUNCTION(qdss_gpio13), - FUNCTION(qdss_gpio14), - FUNCTION(qdss_gpio15), - FUNCTION(qdss_gpio2), - FUNCTION(qdss_gpio3), - FUNCTION(qdss_gpio4), - FUNCTION(qdss_gpio5), - FUNCTION(qdss_gpio6), - FUNCTION(qdss_gpio7), - FUNCTION(qdss_gpio8), - FUNCTION(qdss_gpio9), - FUNCTION(qlink0_enable), - FUNCTION(qlink0_request), - FUNCTION(qlink0_wmss), - FUNCTION(qlink1_enable), - FUNCTION(qlink1_request), - FUNCTION(qlink1_wmss), - FUNCTION(qup00), - FUNCTION(qup01), - FUNCTION(qup02), - FUNCTION(qup10), - FUNCTION(qup11_f1), - FUNCTION(qup11_f2), - FUNCTION(qup12), - FUNCTION(qup13_f1), - FUNCTION(qup13_f2), - FUNCTION(qup14), - FUNCTION(sd_write), - FUNCTION(sdc1_tb), - FUNCTION(sdc2_tb), - FUNCTION(sp_cmu), - FUNCTION(tgu_ch0), - FUNCTION(tgu_ch1), - FUNCTION(tgu_ch2), - FUNCTION(tgu_ch3), - FUNCTION(tsense_pwm1), - FUNCTION(tsense_pwm2), - FUNCTION(uim1_clk), - FUNCTION(uim1_data), - FUNCTION(uim1_present), - FUNCTION(uim1_reset), - FUNCTION(uim2_clk), - FUNCTION(uim2_data), - FUNCTION(uim2_present), - FUNCTION(uim2_reset), - FUNCTION(usb2phy_ac), - FUNCTION(usb_phy), - FUNCTION(vfr_1), - FUNCTION(vsense_trigger), - FUNCTION(wlan1_adc0), - FUNCTION(wlan1_adc1), - FUNCTION(wlan2_adc0), - FUNCTION(wlan2_adc1), +static const struct pinfunction sm6375_functions[] = { + MSM_PIN_FUNCTION(adsp_ext), + MSM_PIN_FUNCTION(agera_pll), + MSM_PIN_FUNCTION(atest_char), + MSM_PIN_FUNCTION(atest_char0), + MSM_PIN_FUNCTION(atest_char1), + MSM_PIN_FUNCTION(atest_char2), + MSM_PIN_FUNCTION(atest_char3), + MSM_PIN_FUNCTION(atest_tsens), + MSM_PIN_FUNCTION(atest_tsens2), + MSM_PIN_FUNCTION(atest_usb1), + MSM_PIN_FUNCTION(atest_usb10), + MSM_PIN_FUNCTION(atest_usb11), + MSM_PIN_FUNCTION(atest_usb12), + MSM_PIN_FUNCTION(atest_usb13), + MSM_PIN_FUNCTION(atest_usb2), + MSM_PIN_FUNCTION(atest_usb20), + MSM_PIN_FUNCTION(atest_usb21), + MSM_PIN_FUNCTION(atest_usb22), + MSM_PIN_FUNCTION(atest_usb23), + MSM_PIN_FUNCTION(audio_ref), + MSM_PIN_FUNCTION(btfm_slimbus), + MSM_PIN_FUNCTION(cam_mclk), + MSM_PIN_FUNCTION(cci_async), + MSM_PIN_FUNCTION(cci_i2c), + MSM_PIN_FUNCTION(cci_timer0), + MSM_PIN_FUNCTION(cci_timer1), + MSM_PIN_FUNCTION(cci_timer2), + MSM_PIN_FUNCTION(cci_timer3), + MSM_PIN_FUNCTION(cci_timer4), + MSM_PIN_FUNCTION(cri_trng), + MSM_PIN_FUNCTION(dbg_out), + MSM_PIN_FUNCTION(ddr_bist), + MSM_PIN_FUNCTION(ddr_pxi0), + MSM_PIN_FUNCTION(ddr_pxi1), + MSM_PIN_FUNCTION(ddr_pxi2), + MSM_PIN_FUNCTION(ddr_pxi3), + MSM_PIN_FUNCTION(dp_hot), + MSM_PIN_FUNCTION(edp_lcd), + MSM_PIN_FUNCTION(gcc_gp1), + MSM_PIN_FUNCTION(gcc_gp2), + MSM_PIN_FUNCTION(gcc_gp3), + MSM_PIN_FUNCTION(gp_pdm0), + MSM_PIN_FUNCTION(gp_pdm1), + MSM_PIN_FUNCTION(gp_pdm2), + MSM_PIN_FUNCTION(gpio), + MSM_PIN_FUNCTION(gps_tx), + MSM_PIN_FUNCTION(ibi_i3c), + MSM_PIN_FUNCTION(jitter_bist), + MSM_PIN_FUNCTION(ldo_en), + MSM_PIN_FUNCTION(ldo_update), + MSM_PIN_FUNCTION(lpass_ext), + MSM_PIN_FUNCTION(m_voc), + MSM_PIN_FUNCTION(mclk), + MSM_PIN_FUNCTION(mdp_vsync), + MSM_PIN_FUNCTION(mdp_vsync0), + MSM_PIN_FUNCTION(mdp_vsync1), + MSM_PIN_FUNCTION(mdp_vsync2), + MSM_PIN_FUNCTION(mdp_vsync3), + MSM_PIN_FUNCTION(mi2s_0), + MSM_PIN_FUNCTION(mi2s_1), + MSM_PIN_FUNCTION(mi2s_2), + MSM_PIN_FUNCTION(mss_lte), + MSM_PIN_FUNCTION(nav_gpio), + MSM_PIN_FUNCTION(nav_pps), + MSM_PIN_FUNCTION(pa_indicator), + MSM_PIN_FUNCTION(phase_flag0), + MSM_PIN_FUNCTION(phase_flag1), + MSM_PIN_FUNCTION(phase_flag10), + MSM_PIN_FUNCTION(phase_flag11), + MSM_PIN_FUNCTION(phase_flag12), + MSM_PIN_FUNCTION(phase_flag13), + MSM_PIN_FUNCTION(phase_flag14), + MSM_PIN_FUNCTION(phase_flag15), + MSM_PIN_FUNCTION(phase_flag16), + MSM_PIN_FUNCTION(phase_flag17), + MSM_PIN_FUNCTION(phase_flag18), + MSM_PIN_FUNCTION(phase_flag19), + MSM_PIN_FUNCTION(phase_flag2), + MSM_PIN_FUNCTION(phase_flag20), + MSM_PIN_FUNCTION(phase_flag21), + MSM_PIN_FUNCTION(phase_flag22), + MSM_PIN_FUNCTION(phase_flag23), + MSM_PIN_FUNCTION(phase_flag24), + MSM_PIN_FUNCTION(phase_flag25), + MSM_PIN_FUNCTION(phase_flag26), + MSM_PIN_FUNCTION(phase_flag27), + MSM_PIN_FUNCTION(phase_flag28), + MSM_PIN_FUNCTION(phase_flag29), + MSM_PIN_FUNCTION(phase_flag3), + MSM_PIN_FUNCTION(phase_flag30), + MSM_PIN_FUNCTION(phase_flag31), + MSM_PIN_FUNCTION(phase_flag4), + MSM_PIN_FUNCTION(phase_flag5), + MSM_PIN_FUNCTION(phase_flag6), + MSM_PIN_FUNCTION(phase_flag7), + MSM_PIN_FUNCTION(phase_flag8), + MSM_PIN_FUNCTION(phase_flag9), + MSM_PIN_FUNCTION(pll_bist), + MSM_PIN_FUNCTION(pll_bypassnl), + MSM_PIN_FUNCTION(pll_clk), + MSM_PIN_FUNCTION(pll_reset), + MSM_PIN_FUNCTION(prng_rosc0), + MSM_PIN_FUNCTION(prng_rosc1), + MSM_PIN_FUNCTION(prng_rosc2), + MSM_PIN_FUNCTION(prng_rosc3), + MSM_PIN_FUNCTION(qdss_cti), + MSM_PIN_FUNCTION(qdss_gpio), + MSM_PIN_FUNCTION(qdss_gpio0), + MSM_PIN_FUNCTION(qdss_gpio1), + MSM_PIN_FUNCTION(qdss_gpio10), + MSM_PIN_FUNCTION(qdss_gpio11), + MSM_PIN_FUNCTION(qdss_gpio12), + MSM_PIN_FUNCTION(qdss_gpio13), + MSM_PIN_FUNCTION(qdss_gpio14), + MSM_PIN_FUNCTION(qdss_gpio15), + MSM_PIN_FUNCTION(qdss_gpio2), + MSM_PIN_FUNCTION(qdss_gpio3), + MSM_PIN_FUNCTION(qdss_gpio4), + MSM_PIN_FUNCTION(qdss_gpio5), + MSM_PIN_FUNCTION(qdss_gpio6), + MSM_PIN_FUNCTION(qdss_gpio7), + MSM_PIN_FUNCTION(qdss_gpio8), + MSM_PIN_FUNCTION(qdss_gpio9), + MSM_PIN_FUNCTION(qlink0_enable), + MSM_PIN_FUNCTION(qlink0_request), + MSM_PIN_FUNCTION(qlink0_wmss), + MSM_PIN_FUNCTION(qlink1_enable), + MSM_PIN_FUNCTION(qlink1_request), + MSM_PIN_FUNCTION(qlink1_wmss), + MSM_PIN_FUNCTION(qup00), + MSM_PIN_FUNCTION(qup01), + MSM_PIN_FUNCTION(qup02), + MSM_PIN_FUNCTION(qup10), + MSM_PIN_FUNCTION(qup11_f1), + MSM_PIN_FUNCTION(qup11_f2), + MSM_PIN_FUNCTION(qup12), + MSM_PIN_FUNCTION(qup13_f1), + MSM_PIN_FUNCTION(qup13_f2), + MSM_PIN_FUNCTION(qup14), + MSM_PIN_FUNCTION(sd_write), + MSM_PIN_FUNCTION(sdc1_tb), + MSM_PIN_FUNCTION(sdc2_tb), + MSM_PIN_FUNCTION(sp_cmu), + MSM_PIN_FUNCTION(tgu_ch0), + MSM_PIN_FUNCTION(tgu_ch1), + MSM_PIN_FUNCTION(tgu_ch2), + MSM_PIN_FUNCTION(tgu_ch3), + MSM_PIN_FUNCTION(tsense_pwm1), + MSM_PIN_FUNCTION(tsense_pwm2), + MSM_PIN_FUNCTION(uim1_clk), + MSM_PIN_FUNCTION(uim1_data), + MSM_PIN_FUNCTION(uim1_present), + MSM_PIN_FUNCTION(uim1_reset), + MSM_PIN_FUNCTION(uim2_clk), + MSM_PIN_FUNCTION(uim2_data), + MSM_PIN_FUNCTION(uim2_present), + MSM_PIN_FUNCTION(uim2_reset), + MSM_PIN_FUNCTION(usb2phy_ac), + MSM_PIN_FUNCTION(usb_phy), + MSM_PIN_FUNCTION(vfr_1), + MSM_PIN_FUNCTION(vsense_trigger), + MSM_PIN_FUNCTION(wlan1_adc0), + MSM_PIN_FUNCTION(wlan1_adc1), + MSM_PIN_FUNCTION(wlan2_adc0), + MSM_PIN_FUNCTION(wlan2_adc1), }; /* diff --git a/drivers/pinctrl/qcom/pinctrl-sm7150.c b/drivers/pinctrl/qcom/pinctrl-sm7150.c index 2a87e3f144fdcfe45899bfd7b4c4c627b1865135..33657cf98fb9d571de8031100e6fad17c6807504 100644 --- a/drivers/pinctrl/qcom/pinctrl-sm7150.c +++ b/drivers/pinctrl/qcom/pinctrl-sm7150.c @@ -23,20 +23,13 @@ enum { WEST }; -#define FUNCTION(fname) \ - [msm_mux_##fname] = { \ - .name = #fname, \ - .groups = fname##_groups, \ - .ngroups = ARRAY_SIZE(fname##_groups), \ - } - #define REG_SIZE 0x1000 #define PINGROUP(id, _tile, f1, f2, f3, f4, f5, f6, f7, f8, f9) \ { \ - .name = "gpio" #id, \ - .pins = gpio##id##_pins, \ - .npins = ARRAY_SIZE(gpio##id##_pins), \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ .funcs = (int[]){ \ msm_mux_gpio, /* gpio mode */ \ msm_mux_##f1, \ @@ -74,9 +67,9 @@ enum { #define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = ctl, \ .io_reg = 0, \ .intr_cfg_reg = 0, \ @@ -100,9 +93,9 @@ enum { #define UFS_RESET(pg_name, offset) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = offset, \ .io_reg = offset + 0x4, \ .intr_cfg_reg = 0, \ @@ -966,117 +959,117 @@ static const char * const wsa_data_groups[] = { "gpio50", }; -static const struct msm_function sm7150_functions[] = { - FUNCTION(gpio), - FUNCTION(adsp_ext), - FUNCTION(agera_pll), - FUNCTION(aoss_cti), - FUNCTION(atest_char), - FUNCTION(atest_tsens), - FUNCTION(atest_tsens2), - FUNCTION(atest_usb1), - FUNCTION(atest_usb2), - FUNCTION(cam_mclk), - FUNCTION(cci_async), - FUNCTION(cci_i2c), - FUNCTION(cci_timer0), - FUNCTION(cci_timer1), - FUNCTION(cci_timer2), - FUNCTION(cci_timer3), - FUNCTION(cci_timer4), - FUNCTION(dbg_out), - FUNCTION(ddr_bist), - FUNCTION(ddr_pxi0), - FUNCTION(ddr_pxi1), - FUNCTION(ddr_pxi2), - FUNCTION(ddr_pxi3), - FUNCTION(edp_hot), - FUNCTION(edp_lcd), - FUNCTION(gcc_gp1), - FUNCTION(gcc_gp2), - FUNCTION(gcc_gp3), - FUNCTION(gp_pdm0), - FUNCTION(gp_pdm1), - FUNCTION(gp_pdm2), - FUNCTION(gps_tx), - FUNCTION(jitter_bist), - FUNCTION(ldo_en), - FUNCTION(ldo_update), - FUNCTION(m_voc), - FUNCTION(mdp_vsync), - FUNCTION(mdp_vsync0), - FUNCTION(mdp_vsync1), - FUNCTION(mdp_vsync2), - FUNCTION(mdp_vsync3), - FUNCTION(mss_lte), - FUNCTION(nav_pps_in), - FUNCTION(nav_pps_out), - FUNCTION(pa_indicator), - FUNCTION(pci_e), - FUNCTION(phase_flag), - FUNCTION(pll_bist), - FUNCTION(pll_bypassnl), - FUNCTION(pll_reset), - FUNCTION(pri_mi2s), - FUNCTION(pri_mi2s_ws), - FUNCTION(prng_rosc), - FUNCTION(qdss_cti), - FUNCTION(qdss), - FUNCTION(qlink_enable), - FUNCTION(qlink_request), - FUNCTION(qua_mi2s), - FUNCTION(qup00), - FUNCTION(qup01), - FUNCTION(qup02), - FUNCTION(qup03), - FUNCTION(qup04), - FUNCTION(qup10), - FUNCTION(qup11), - FUNCTION(qup12), - FUNCTION(qup13), - FUNCTION(qup14), - FUNCTION(qup15), - FUNCTION(sd_write), - FUNCTION(sdc40), - FUNCTION(sdc41), - FUNCTION(sdc42), - FUNCTION(sdc43), - FUNCTION(sdc4_clk), - FUNCTION(sdc4_cmd), - FUNCTION(sec_mi2s), - FUNCTION(ter_mi2s), - FUNCTION(tgu_ch0), - FUNCTION(tgu_ch1), - FUNCTION(tgu_ch2), - FUNCTION(tgu_ch3), - FUNCTION(tsif1_clk), - FUNCTION(tsif1_data), - FUNCTION(tsif1_en), - FUNCTION(tsif1_error), - FUNCTION(tsif1_sync), - FUNCTION(tsif2_clk), - FUNCTION(tsif2_data), - FUNCTION(tsif2_en), - FUNCTION(tsif2_error), - FUNCTION(tsif2_sync), - FUNCTION(uim1_clk), - FUNCTION(uim1_data), - FUNCTION(uim1_present), - FUNCTION(uim1_reset), - FUNCTION(uim2_clk), - FUNCTION(uim2_data), - FUNCTION(uim2_present), - FUNCTION(uim2_reset), - FUNCTION(uim_batt), - FUNCTION(usb_phy), - FUNCTION(vfr_1), - FUNCTION(vsense_trigger), - FUNCTION(wlan1_adc0), - FUNCTION(wlan1_adc1), - FUNCTION(wlan2_adc0), - FUNCTION(wlan2_adc1), - FUNCTION(wsa_clk), - FUNCTION(wsa_data), +static const struct pinfunction sm7150_functions[] = { + MSM_PIN_FUNCTION(gpio), + MSM_PIN_FUNCTION(adsp_ext), + MSM_PIN_FUNCTION(agera_pll), + MSM_PIN_FUNCTION(aoss_cti), + MSM_PIN_FUNCTION(atest_char), + MSM_PIN_FUNCTION(atest_tsens), + MSM_PIN_FUNCTION(atest_tsens2), + MSM_PIN_FUNCTION(atest_usb1), + MSM_PIN_FUNCTION(atest_usb2), + MSM_PIN_FUNCTION(cam_mclk), + MSM_PIN_FUNCTION(cci_async), + MSM_PIN_FUNCTION(cci_i2c), + MSM_PIN_FUNCTION(cci_timer0), + MSM_PIN_FUNCTION(cci_timer1), + MSM_PIN_FUNCTION(cci_timer2), + MSM_PIN_FUNCTION(cci_timer3), + MSM_PIN_FUNCTION(cci_timer4), + MSM_PIN_FUNCTION(dbg_out), + MSM_PIN_FUNCTION(ddr_bist), + MSM_PIN_FUNCTION(ddr_pxi0), + MSM_PIN_FUNCTION(ddr_pxi1), + MSM_PIN_FUNCTION(ddr_pxi2), + MSM_PIN_FUNCTION(ddr_pxi3), + MSM_PIN_FUNCTION(edp_hot), + MSM_PIN_FUNCTION(edp_lcd), + MSM_PIN_FUNCTION(gcc_gp1), + MSM_PIN_FUNCTION(gcc_gp2), + MSM_PIN_FUNCTION(gcc_gp3), + MSM_PIN_FUNCTION(gp_pdm0), + MSM_PIN_FUNCTION(gp_pdm1), + MSM_PIN_FUNCTION(gp_pdm2), + MSM_PIN_FUNCTION(gps_tx), + MSM_PIN_FUNCTION(jitter_bist), + MSM_PIN_FUNCTION(ldo_en), + MSM_PIN_FUNCTION(ldo_update), + MSM_PIN_FUNCTION(m_voc), + MSM_PIN_FUNCTION(mdp_vsync), + MSM_PIN_FUNCTION(mdp_vsync0), + MSM_PIN_FUNCTION(mdp_vsync1), + MSM_PIN_FUNCTION(mdp_vsync2), + MSM_PIN_FUNCTION(mdp_vsync3), + MSM_PIN_FUNCTION(mss_lte), + MSM_PIN_FUNCTION(nav_pps_in), + MSM_PIN_FUNCTION(nav_pps_out), + MSM_PIN_FUNCTION(pa_indicator), + MSM_PIN_FUNCTION(pci_e), + MSM_PIN_FUNCTION(phase_flag), + MSM_PIN_FUNCTION(pll_bist), + MSM_PIN_FUNCTION(pll_bypassnl), + MSM_PIN_FUNCTION(pll_reset), + MSM_PIN_FUNCTION(pri_mi2s), + MSM_PIN_FUNCTION(pri_mi2s_ws), + MSM_PIN_FUNCTION(prng_rosc), + MSM_PIN_FUNCTION(qdss_cti), + MSM_PIN_FUNCTION(qdss), + MSM_PIN_FUNCTION(qlink_enable), + MSM_PIN_FUNCTION(qlink_request), + MSM_PIN_FUNCTION(qua_mi2s), + MSM_PIN_FUNCTION(qup00), + MSM_PIN_FUNCTION(qup01), + MSM_PIN_FUNCTION(qup02), + MSM_PIN_FUNCTION(qup03), + MSM_PIN_FUNCTION(qup04), + MSM_PIN_FUNCTION(qup10), + MSM_PIN_FUNCTION(qup11), + MSM_PIN_FUNCTION(qup12), + MSM_PIN_FUNCTION(qup13), + MSM_PIN_FUNCTION(qup14), + MSM_PIN_FUNCTION(qup15), + MSM_PIN_FUNCTION(sd_write), + MSM_PIN_FUNCTION(sdc40), + MSM_PIN_FUNCTION(sdc41), + MSM_PIN_FUNCTION(sdc42), + MSM_PIN_FUNCTION(sdc43), + MSM_PIN_FUNCTION(sdc4_clk), + MSM_PIN_FUNCTION(sdc4_cmd), + MSM_PIN_FUNCTION(sec_mi2s), + MSM_PIN_FUNCTION(ter_mi2s), + MSM_PIN_FUNCTION(tgu_ch0), + MSM_PIN_FUNCTION(tgu_ch1), + MSM_PIN_FUNCTION(tgu_ch2), + MSM_PIN_FUNCTION(tgu_ch3), + MSM_PIN_FUNCTION(tsif1_clk), + MSM_PIN_FUNCTION(tsif1_data), + MSM_PIN_FUNCTION(tsif1_en), + MSM_PIN_FUNCTION(tsif1_error), + MSM_PIN_FUNCTION(tsif1_sync), + MSM_PIN_FUNCTION(tsif2_clk), + MSM_PIN_FUNCTION(tsif2_data), + MSM_PIN_FUNCTION(tsif2_en), + MSM_PIN_FUNCTION(tsif2_error), + MSM_PIN_FUNCTION(tsif2_sync), + MSM_PIN_FUNCTION(uim1_clk), + MSM_PIN_FUNCTION(uim1_data), + MSM_PIN_FUNCTION(uim1_present), + MSM_PIN_FUNCTION(uim1_reset), + MSM_PIN_FUNCTION(uim2_clk), + MSM_PIN_FUNCTION(uim2_data), + MSM_PIN_FUNCTION(uim2_present), + MSM_PIN_FUNCTION(uim2_reset), + MSM_PIN_FUNCTION(uim_batt), + MSM_PIN_FUNCTION(usb_phy), + MSM_PIN_FUNCTION(vfr_1), + MSM_PIN_FUNCTION(vsense_trigger), + MSM_PIN_FUNCTION(wlan1_adc0), + MSM_PIN_FUNCTION(wlan1_adc1), + MSM_PIN_FUNCTION(wlan2_adc0), + MSM_PIN_FUNCTION(wlan2_adc1), + MSM_PIN_FUNCTION(wsa_clk), + MSM_PIN_FUNCTION(wsa_data), }; /* diff --git a/drivers/pinctrl/qcom/pinctrl-sm8150.c b/drivers/pinctrl/qcom/pinctrl-sm8150.c index 1cc622694553d6d3506e085732cd605405c7907a..01aea9c70b7a78168ee063f5ac88afc0d7290bcb 100644 --- a/drivers/pinctrl/qcom/pinctrl-sm8150.c +++ b/drivers/pinctrl/qcom/pinctrl-sm8150.c @@ -4,7 +4,6 @@ #include #include #include -#include #include "pinctrl-msm.h" @@ -22,18 +21,11 @@ enum { WEST }; -#define FUNCTION(fname) \ - [msm_mux_##fname] = { \ - .name = #fname, \ - .groups = fname##_groups, \ - .ngroups = ARRAY_SIZE(fname##_groups), \ - } - #define PINGROUP(id, _tile, f1, f2, f3, f4, f5, f6, f7, f8, f9) \ { \ - .name = "gpio" #id, \ - .pins = gpio##id##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(gpio##id##_pins), \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ .funcs = (int[]){ \ msm_mux_gpio, /* gpio mode */ \ msm_mux_##f1, \ @@ -71,9 +63,9 @@ enum { #define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = ctl, \ .io_reg = 0, \ .intr_cfg_reg = 0, \ @@ -97,9 +89,9 @@ enum { #define UFS_RESET(pg_name, offset) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = offset, \ .io_reg = offset + 0x4, \ .intr_cfg_reg = 0, \ @@ -1180,136 +1172,136 @@ static const char * const mss_lte_groups[] = { "gpio69", "gpio70", }; -static const struct msm_function sm8150_functions[] = { - FUNCTION(adsp_ext), - FUNCTION(agera_pll), - FUNCTION(aoss_cti), - FUNCTION(ddr_pxi2), - FUNCTION(atest_char), - FUNCTION(atest_char0), - FUNCTION(atest_char1), - FUNCTION(atest_char2), - FUNCTION(atest_char3), - FUNCTION(audio_ref), - FUNCTION(atest_usb1), - FUNCTION(atest_usb2), - FUNCTION(atest_usb10), - FUNCTION(atest_usb11), - FUNCTION(atest_usb12), - FUNCTION(atest_usb13), - FUNCTION(atest_usb20), - FUNCTION(atest_usb21), - FUNCTION(atest_usb22), - FUNCTION(atest_usb23), - FUNCTION(btfm_slimbus), - FUNCTION(cam_mclk), - FUNCTION(cci_async), - FUNCTION(cci_i2c), - FUNCTION(cci_timer0), - FUNCTION(cci_timer1), - FUNCTION(cci_timer2), - FUNCTION(cci_timer3), - FUNCTION(cci_timer4), - FUNCTION(cri_trng), - FUNCTION(cri_trng0), - FUNCTION(cri_trng1), - FUNCTION(dbg_out), - FUNCTION(ddr_bist), - FUNCTION(ddr_pxi0), - FUNCTION(ddr_pxi1), - FUNCTION(ddr_pxi3), - FUNCTION(edp_hot), - FUNCTION(edp_lcd), - FUNCTION(emac_phy), - FUNCTION(emac_pps), - FUNCTION(gcc_gp1), - FUNCTION(gcc_gp2), - FUNCTION(gcc_gp3), - FUNCTION(gpio), - FUNCTION(hs1_mi2s), - FUNCTION(hs2_mi2s), - FUNCTION(hs3_mi2s), - FUNCTION(jitter_bist), - FUNCTION(lpass_slimbus), - FUNCTION(mdp_vsync), - FUNCTION(mdp_vsync0), - FUNCTION(mdp_vsync1), - FUNCTION(mdp_vsync2), - FUNCTION(mdp_vsync3), - FUNCTION(mss_lte), - FUNCTION(m_voc), - FUNCTION(nav_pps), - FUNCTION(pa_indicator), - FUNCTION(pci_e0), - FUNCTION(phase_flag), - FUNCTION(pll_bypassnl), - FUNCTION(pll_bist), - FUNCTION(pci_e1), - FUNCTION(pll_reset), - FUNCTION(pri_mi2s), - FUNCTION(pri_mi2s_ws), - FUNCTION(prng_rosc), - FUNCTION(qdss), - FUNCTION(qdss_cti), - FUNCTION(qlink_request), - FUNCTION(qlink_enable), - FUNCTION(qspi0), - FUNCTION(qspi1), - FUNCTION(qspi2), - FUNCTION(qspi3), - FUNCTION(qspi_clk), - FUNCTION(qspi_cs), - FUNCTION(qua_mi2s), - FUNCTION(qup0), - FUNCTION(qup1), - FUNCTION(qup2), - FUNCTION(qup3), - FUNCTION(qup4), - FUNCTION(qup5), - FUNCTION(qup6), - FUNCTION(qup7), - FUNCTION(qup8), - FUNCTION(qup9), - FUNCTION(qup10), - FUNCTION(qup11), - FUNCTION(qup12), - FUNCTION(qup13), - FUNCTION(qup14), - FUNCTION(qup15), - FUNCTION(qup16), - FUNCTION(qup17), - FUNCTION(qup18), - FUNCTION(qup19), - FUNCTION(qup_l4), - FUNCTION(qup_l5), - FUNCTION(qup_l6), - FUNCTION(rgmii), - FUNCTION(sdc4), - FUNCTION(sd_write), - FUNCTION(sec_mi2s), - FUNCTION(spkr_i2s), - FUNCTION(sp_cmu), - FUNCTION(ter_mi2s), - FUNCTION(tgu_ch0), - FUNCTION(tgu_ch1), - FUNCTION(tgu_ch2), - FUNCTION(tgu_ch3), - FUNCTION(tsense_pwm1), - FUNCTION(tsense_pwm2), - FUNCTION(tsif1), - FUNCTION(tsif2), - FUNCTION(uim1), - FUNCTION(uim2), - FUNCTION(uim_batt), - FUNCTION(usb2phy_ac), - FUNCTION(usb_phy), - FUNCTION(vfr_1), - FUNCTION(vsense_trigger), - FUNCTION(wlan1_adc0), - FUNCTION(wlan1_adc1), - FUNCTION(wlan2_adc0), - FUNCTION(wlan2_adc1), - FUNCTION(wmss_reset), +static const struct pinfunction sm8150_functions[] = { + MSM_PIN_FUNCTION(adsp_ext), + MSM_PIN_FUNCTION(agera_pll), + MSM_PIN_FUNCTION(aoss_cti), + MSM_PIN_FUNCTION(ddr_pxi2), + MSM_PIN_FUNCTION(atest_char), + MSM_PIN_FUNCTION(atest_char0), + MSM_PIN_FUNCTION(atest_char1), + MSM_PIN_FUNCTION(atest_char2), + MSM_PIN_FUNCTION(atest_char3), + MSM_PIN_FUNCTION(audio_ref), + MSM_PIN_FUNCTION(atest_usb1), + MSM_PIN_FUNCTION(atest_usb2), + MSM_PIN_FUNCTION(atest_usb10), + MSM_PIN_FUNCTION(atest_usb11), + MSM_PIN_FUNCTION(atest_usb12), + MSM_PIN_FUNCTION(atest_usb13), + MSM_PIN_FUNCTION(atest_usb20), + MSM_PIN_FUNCTION(atest_usb21), + MSM_PIN_FUNCTION(atest_usb22), + MSM_PIN_FUNCTION(atest_usb23), + MSM_PIN_FUNCTION(btfm_slimbus), + MSM_PIN_FUNCTION(cam_mclk), + MSM_PIN_FUNCTION(cci_async), + MSM_PIN_FUNCTION(cci_i2c), + MSM_PIN_FUNCTION(cci_timer0), + MSM_PIN_FUNCTION(cci_timer1), + MSM_PIN_FUNCTION(cci_timer2), + MSM_PIN_FUNCTION(cci_timer3), + MSM_PIN_FUNCTION(cci_timer4), + MSM_PIN_FUNCTION(cri_trng), + MSM_PIN_FUNCTION(cri_trng0), + MSM_PIN_FUNCTION(cri_trng1), + MSM_PIN_FUNCTION(dbg_out), + MSM_PIN_FUNCTION(ddr_bist), + MSM_PIN_FUNCTION(ddr_pxi0), + MSM_PIN_FUNCTION(ddr_pxi1), + MSM_PIN_FUNCTION(ddr_pxi3), + MSM_PIN_FUNCTION(edp_hot), + MSM_PIN_FUNCTION(edp_lcd), + MSM_PIN_FUNCTION(emac_phy), + MSM_PIN_FUNCTION(emac_pps), + MSM_PIN_FUNCTION(gcc_gp1), + MSM_PIN_FUNCTION(gcc_gp2), + MSM_PIN_FUNCTION(gcc_gp3), + MSM_PIN_FUNCTION(gpio), + MSM_PIN_FUNCTION(hs1_mi2s), + MSM_PIN_FUNCTION(hs2_mi2s), + MSM_PIN_FUNCTION(hs3_mi2s), + MSM_PIN_FUNCTION(jitter_bist), + MSM_PIN_FUNCTION(lpass_slimbus), + MSM_PIN_FUNCTION(mdp_vsync), + MSM_PIN_FUNCTION(mdp_vsync0), + MSM_PIN_FUNCTION(mdp_vsync1), + MSM_PIN_FUNCTION(mdp_vsync2), + MSM_PIN_FUNCTION(mdp_vsync3), + MSM_PIN_FUNCTION(mss_lte), + MSM_PIN_FUNCTION(m_voc), + MSM_PIN_FUNCTION(nav_pps), + MSM_PIN_FUNCTION(pa_indicator), + MSM_PIN_FUNCTION(pci_e0), + MSM_PIN_FUNCTION(phase_flag), + MSM_PIN_FUNCTION(pll_bypassnl), + MSM_PIN_FUNCTION(pll_bist), + MSM_PIN_FUNCTION(pci_e1), + MSM_PIN_FUNCTION(pll_reset), + MSM_PIN_FUNCTION(pri_mi2s), + MSM_PIN_FUNCTION(pri_mi2s_ws), + MSM_PIN_FUNCTION(prng_rosc), + MSM_PIN_FUNCTION(qdss), + MSM_PIN_FUNCTION(qdss_cti), + MSM_PIN_FUNCTION(qlink_request), + MSM_PIN_FUNCTION(qlink_enable), + MSM_PIN_FUNCTION(qspi0), + MSM_PIN_FUNCTION(qspi1), + MSM_PIN_FUNCTION(qspi2), + MSM_PIN_FUNCTION(qspi3), + MSM_PIN_FUNCTION(qspi_clk), + MSM_PIN_FUNCTION(qspi_cs), + MSM_PIN_FUNCTION(qua_mi2s), + MSM_PIN_FUNCTION(qup0), + MSM_PIN_FUNCTION(qup1), + MSM_PIN_FUNCTION(qup2), + MSM_PIN_FUNCTION(qup3), + MSM_PIN_FUNCTION(qup4), + MSM_PIN_FUNCTION(qup5), + MSM_PIN_FUNCTION(qup6), + MSM_PIN_FUNCTION(qup7), + MSM_PIN_FUNCTION(qup8), + MSM_PIN_FUNCTION(qup9), + MSM_PIN_FUNCTION(qup10), + MSM_PIN_FUNCTION(qup11), + MSM_PIN_FUNCTION(qup12), + MSM_PIN_FUNCTION(qup13), + MSM_PIN_FUNCTION(qup14), + MSM_PIN_FUNCTION(qup15), + MSM_PIN_FUNCTION(qup16), + MSM_PIN_FUNCTION(qup17), + MSM_PIN_FUNCTION(qup18), + MSM_PIN_FUNCTION(qup19), + MSM_PIN_FUNCTION(qup_l4), + MSM_PIN_FUNCTION(qup_l5), + MSM_PIN_FUNCTION(qup_l6), + MSM_PIN_FUNCTION(rgmii), + MSM_PIN_FUNCTION(sdc4), + MSM_PIN_FUNCTION(sd_write), + MSM_PIN_FUNCTION(sec_mi2s), + MSM_PIN_FUNCTION(spkr_i2s), + MSM_PIN_FUNCTION(sp_cmu), + MSM_PIN_FUNCTION(ter_mi2s), + MSM_PIN_FUNCTION(tgu_ch0), + MSM_PIN_FUNCTION(tgu_ch1), + MSM_PIN_FUNCTION(tgu_ch2), + MSM_PIN_FUNCTION(tgu_ch3), + MSM_PIN_FUNCTION(tsense_pwm1), + MSM_PIN_FUNCTION(tsense_pwm2), + MSM_PIN_FUNCTION(tsif1), + MSM_PIN_FUNCTION(tsif2), + MSM_PIN_FUNCTION(uim1), + MSM_PIN_FUNCTION(uim2), + MSM_PIN_FUNCTION(uim_batt), + MSM_PIN_FUNCTION(usb2phy_ac), + MSM_PIN_FUNCTION(usb_phy), + MSM_PIN_FUNCTION(vfr_1), + MSM_PIN_FUNCTION(vsense_trigger), + MSM_PIN_FUNCTION(wlan1_adc0), + MSM_PIN_FUNCTION(wlan1_adc1), + MSM_PIN_FUNCTION(wlan2_adc0), + MSM_PIN_FUNCTION(wlan2_adc1), + MSM_PIN_FUNCTION(wmss_reset), }; /* diff --git a/drivers/pinctrl/qcom/pinctrl-sm8250.c b/drivers/pinctrl/qcom/pinctrl-sm8250.c index 3bd7f9fedcc340e4ea41dfc5e6755800d8c0366d..e9961a49ff9811bfa3ed3c6c1a8f1cf90afa1d29 100644 --- a/drivers/pinctrl/qcom/pinctrl-sm8250.c +++ b/drivers/pinctrl/qcom/pinctrl-sm8250.c @@ -6,7 +6,6 @@ #include #include #include -#include #include "pinctrl-msm.h" @@ -22,19 +21,12 @@ enum { NORTH, }; -#define FUNCTION(fname) \ - [msm_mux_##fname] = { \ - .name = #fname, \ - .groups = fname##_groups, \ - .ngroups = ARRAY_SIZE(fname##_groups), \ - } - #define REG_SIZE 0x1000 #define PINGROUP(id, _tile, f1, f2, f3, f4, f5, f6, f7, f8, f9) \ { \ - .name = "gpio" #id, \ - .pins = gpio##id##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(gpio##id##_pins), \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ .funcs = (int[]){ \ msm_mux_gpio, /* gpio mode */ \ msm_mux_##f1, \ @@ -72,9 +64,9 @@ enum { #define SDC_PINGROUP(pg_name, ctl, pull, drv) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = ctl, \ .io_reg = 0, \ .intr_cfg_reg = 0, \ @@ -98,9 +90,9 @@ enum { #define UFS_RESET(pg_name, offset) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = offset, \ .io_reg = offset + 0x4, \ .intr_cfg_reg = 0, \ @@ -1003,122 +995,122 @@ static const char * const sdc42_groups[] = { "gpio74", }; -static const struct msm_function sm8250_functions[] = { - FUNCTION(aoss_cti), - FUNCTION(atest), - FUNCTION(audio_ref), - FUNCTION(cam_mclk), - FUNCTION(cci_async), - FUNCTION(cci_i2c), - FUNCTION(cci_timer0), - FUNCTION(cci_timer1), - FUNCTION(cci_timer2), - FUNCTION(cci_timer3), - FUNCTION(cci_timer4), - FUNCTION(cri_trng), - FUNCTION(cri_trng0), - FUNCTION(cri_trng1), - FUNCTION(dbg_out), - FUNCTION(ddr_bist), - FUNCTION(ddr_pxi0), - FUNCTION(ddr_pxi1), - FUNCTION(ddr_pxi2), - FUNCTION(ddr_pxi3), - FUNCTION(dp_hot), - FUNCTION(dp_lcd), - FUNCTION(gcc_gp1), - FUNCTION(gcc_gp2), - FUNCTION(gcc_gp3), - FUNCTION(gpio), - FUNCTION(ibi_i3c), - FUNCTION(jitter_bist), - FUNCTION(lpass_slimbus), - FUNCTION(mdp_vsync), - FUNCTION(mdp_vsync0), - FUNCTION(mdp_vsync1), - FUNCTION(mdp_vsync2), - FUNCTION(mdp_vsync3), - FUNCTION(mi2s0_data0), - FUNCTION(mi2s0_data1), - FUNCTION(mi2s0_sck), - FUNCTION(mi2s0_ws), - FUNCTION(mi2s1_data0), - FUNCTION(mi2s1_data1), - FUNCTION(mi2s1_sck), - FUNCTION(mi2s1_ws), - FUNCTION(mi2s2_data0), - FUNCTION(mi2s2_data1), - FUNCTION(mi2s2_sck), - FUNCTION(mi2s2_ws), - FUNCTION(pci_e0), - FUNCTION(pci_e1), - FUNCTION(pci_e2), - FUNCTION(phase_flag), - FUNCTION(pll_bist), - FUNCTION(pll_bypassnl), - FUNCTION(pll_clk), - FUNCTION(pll_reset), - FUNCTION(pri_mi2s), - FUNCTION(prng_rosc), - FUNCTION(qdss_cti), - FUNCTION(qdss_gpio), - FUNCTION(qspi0), - FUNCTION(qspi1), - FUNCTION(qspi2), - FUNCTION(qspi3), - FUNCTION(qspi_clk), - FUNCTION(qspi_cs), - FUNCTION(qup0), - FUNCTION(qup1), - FUNCTION(qup10), - FUNCTION(qup11), - FUNCTION(qup12), - FUNCTION(qup13), - FUNCTION(qup14), - FUNCTION(qup15), - FUNCTION(qup16), - FUNCTION(qup17), - FUNCTION(qup18), - FUNCTION(qup19), - FUNCTION(qup2), - FUNCTION(qup3), - FUNCTION(qup4), - FUNCTION(qup5), - FUNCTION(qup6), - FUNCTION(qup7), - FUNCTION(qup8), - FUNCTION(qup9), - FUNCTION(qup_l4), - FUNCTION(qup_l5), - FUNCTION(qup_l6), - FUNCTION(sd_write), - FUNCTION(sdc40), - FUNCTION(sdc41), - FUNCTION(sdc42), - FUNCTION(sdc43), - FUNCTION(sdc4_clk), - FUNCTION(sdc4_cmd), - FUNCTION(sec_mi2s), - FUNCTION(sp_cmu), - FUNCTION(tgu_ch0), - FUNCTION(tgu_ch1), - FUNCTION(tgu_ch2), - FUNCTION(tgu_ch3), - FUNCTION(tsense_pwm1), - FUNCTION(tsense_pwm2), - FUNCTION(tsif0_clk), - FUNCTION(tsif0_data), - FUNCTION(tsif0_en), - FUNCTION(tsif0_error), - FUNCTION(tsif0_sync), - FUNCTION(tsif1_clk), - FUNCTION(tsif1_data), - FUNCTION(tsif1_en), - FUNCTION(tsif1_error), - FUNCTION(tsif1_sync), - FUNCTION(usb2phy_ac), - FUNCTION(usb_phy), - FUNCTION(vsense_trigger), +static const struct pinfunction sm8250_functions[] = { + MSM_PIN_FUNCTION(aoss_cti), + MSM_PIN_FUNCTION(atest), + MSM_PIN_FUNCTION(audio_ref), + MSM_PIN_FUNCTION(cam_mclk), + MSM_PIN_FUNCTION(cci_async), + MSM_PIN_FUNCTION(cci_i2c), + MSM_PIN_FUNCTION(cci_timer0), + MSM_PIN_FUNCTION(cci_timer1), + MSM_PIN_FUNCTION(cci_timer2), + MSM_PIN_FUNCTION(cci_timer3), + MSM_PIN_FUNCTION(cci_timer4), + MSM_PIN_FUNCTION(cri_trng), + MSM_PIN_FUNCTION(cri_trng0), + MSM_PIN_FUNCTION(cri_trng1), + MSM_PIN_FUNCTION(dbg_out), + MSM_PIN_FUNCTION(ddr_bist), + MSM_PIN_FUNCTION(ddr_pxi0), + MSM_PIN_FUNCTION(ddr_pxi1), + MSM_PIN_FUNCTION(ddr_pxi2), + MSM_PIN_FUNCTION(ddr_pxi3), + MSM_PIN_FUNCTION(dp_hot), + MSM_PIN_FUNCTION(dp_lcd), + MSM_PIN_FUNCTION(gcc_gp1), + MSM_PIN_FUNCTION(gcc_gp2), + MSM_PIN_FUNCTION(gcc_gp3), + MSM_PIN_FUNCTION(gpio), + MSM_PIN_FUNCTION(ibi_i3c), + MSM_PIN_FUNCTION(jitter_bist), + MSM_PIN_FUNCTION(lpass_slimbus), + MSM_PIN_FUNCTION(mdp_vsync), + MSM_PIN_FUNCTION(mdp_vsync0), + MSM_PIN_FUNCTION(mdp_vsync1), + MSM_PIN_FUNCTION(mdp_vsync2), + MSM_PIN_FUNCTION(mdp_vsync3), + MSM_PIN_FUNCTION(mi2s0_data0), + MSM_PIN_FUNCTION(mi2s0_data1), + MSM_PIN_FUNCTION(mi2s0_sck), + MSM_PIN_FUNCTION(mi2s0_ws), + MSM_PIN_FUNCTION(mi2s1_data0), + MSM_PIN_FUNCTION(mi2s1_data1), + MSM_PIN_FUNCTION(mi2s1_sck), + MSM_PIN_FUNCTION(mi2s1_ws), + MSM_PIN_FUNCTION(mi2s2_data0), + MSM_PIN_FUNCTION(mi2s2_data1), + MSM_PIN_FUNCTION(mi2s2_sck), + MSM_PIN_FUNCTION(mi2s2_ws), + MSM_PIN_FUNCTION(pci_e0), + MSM_PIN_FUNCTION(pci_e1), + MSM_PIN_FUNCTION(pci_e2), + MSM_PIN_FUNCTION(phase_flag), + MSM_PIN_FUNCTION(pll_bist), + MSM_PIN_FUNCTION(pll_bypassnl), + MSM_PIN_FUNCTION(pll_clk), + MSM_PIN_FUNCTION(pll_reset), + MSM_PIN_FUNCTION(pri_mi2s), + MSM_PIN_FUNCTION(prng_rosc), + MSM_PIN_FUNCTION(qdss_cti), + MSM_PIN_FUNCTION(qdss_gpio), + MSM_PIN_FUNCTION(qspi0), + MSM_PIN_FUNCTION(qspi1), + MSM_PIN_FUNCTION(qspi2), + MSM_PIN_FUNCTION(qspi3), + MSM_PIN_FUNCTION(qspi_clk), + MSM_PIN_FUNCTION(qspi_cs), + MSM_PIN_FUNCTION(qup0), + MSM_PIN_FUNCTION(qup1), + MSM_PIN_FUNCTION(qup10), + MSM_PIN_FUNCTION(qup11), + MSM_PIN_FUNCTION(qup12), + MSM_PIN_FUNCTION(qup13), + MSM_PIN_FUNCTION(qup14), + MSM_PIN_FUNCTION(qup15), + MSM_PIN_FUNCTION(qup16), + MSM_PIN_FUNCTION(qup17), + MSM_PIN_FUNCTION(qup18), + MSM_PIN_FUNCTION(qup19), + MSM_PIN_FUNCTION(qup2), + MSM_PIN_FUNCTION(qup3), + MSM_PIN_FUNCTION(qup4), + MSM_PIN_FUNCTION(qup5), + MSM_PIN_FUNCTION(qup6), + MSM_PIN_FUNCTION(qup7), + MSM_PIN_FUNCTION(qup8), + MSM_PIN_FUNCTION(qup9), + MSM_PIN_FUNCTION(qup_l4), + MSM_PIN_FUNCTION(qup_l5), + MSM_PIN_FUNCTION(qup_l6), + MSM_PIN_FUNCTION(sd_write), + MSM_PIN_FUNCTION(sdc40), + MSM_PIN_FUNCTION(sdc41), + MSM_PIN_FUNCTION(sdc42), + MSM_PIN_FUNCTION(sdc43), + MSM_PIN_FUNCTION(sdc4_clk), + MSM_PIN_FUNCTION(sdc4_cmd), + MSM_PIN_FUNCTION(sec_mi2s), + MSM_PIN_FUNCTION(sp_cmu), + MSM_PIN_FUNCTION(tgu_ch0), + MSM_PIN_FUNCTION(tgu_ch1), + MSM_PIN_FUNCTION(tgu_ch2), + MSM_PIN_FUNCTION(tgu_ch3), + MSM_PIN_FUNCTION(tsense_pwm1), + MSM_PIN_FUNCTION(tsense_pwm2), + MSM_PIN_FUNCTION(tsif0_clk), + MSM_PIN_FUNCTION(tsif0_data), + MSM_PIN_FUNCTION(tsif0_en), + MSM_PIN_FUNCTION(tsif0_error), + MSM_PIN_FUNCTION(tsif0_sync), + MSM_PIN_FUNCTION(tsif1_clk), + MSM_PIN_FUNCTION(tsif1_data), + MSM_PIN_FUNCTION(tsif1_en), + MSM_PIN_FUNCTION(tsif1_error), + MSM_PIN_FUNCTION(tsif1_sync), + MSM_PIN_FUNCTION(usb2phy_ac), + MSM_PIN_FUNCTION(usb_phy), + MSM_PIN_FUNCTION(vsense_trigger), }; /* Every pin is maintained as a single group, and missing or non-existing pin diff --git a/drivers/pinctrl/qcom/pinctrl-sm8350.c b/drivers/pinctrl/qcom/pinctrl-sm8350.c index 1c042d39380c6dab558ef12816061ba305c8d20c..9c69458bd9109119e7a88d1a92f633bbf188ed0c 100644 --- a/drivers/pinctrl/qcom/pinctrl-sm8350.c +++ b/drivers/pinctrl/qcom/pinctrl-sm8350.c @@ -7,24 +7,16 @@ #include #include #include -#include #include "pinctrl-msm.h" -#define FUNCTION(fname) \ - [msm_mux_##fname] = { \ - .name = #fname, \ - .groups = fname##_groups, \ - .ngroups = ARRAY_SIZE(fname##_groups), \ - } - #define REG_SIZE 0x1000 #define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9) \ { \ - .name = "gpio" #id, \ - .pins = gpio##id##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(gpio##id##_pins), \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ .funcs = (int[]){ \ msm_mux_gpio, /* gpio mode */ \ msm_mux_##f1, \ @@ -61,9 +53,9 @@ #define SDC_PINGROUP(pg_name, ctl, pull, drv) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = ctl, \ .io_reg = 0, \ .intr_cfg_reg = 0, \ @@ -86,9 +78,9 @@ #define UFS_RESET(pg_name, offset) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = offset, \ .io_reg = offset + 0x4, \ .intr_cfg_reg = 0, \ @@ -1250,142 +1242,142 @@ static const char * const vsense_trigger_groups[] = { "gpio78", }; -static const struct msm_function sm8350_functions[] = { - FUNCTION(atest_char), - FUNCTION(atest_usb), - FUNCTION(audio_ref), - FUNCTION(cam_mclk), - FUNCTION(cci_async), - FUNCTION(cci_i2c), - FUNCTION(cci_timer), - FUNCTION(cmu_rng), - FUNCTION(coex_uart1), - FUNCTION(coex_uart2), - FUNCTION(cri_trng), - FUNCTION(cri_trng0), - FUNCTION(cri_trng1), - FUNCTION(dbg_out), - FUNCTION(ddr_bist), - FUNCTION(ddr_pxi0), - FUNCTION(ddr_pxi1), - FUNCTION(ddr_pxi2), - FUNCTION(ddr_pxi3), - FUNCTION(dp_hot), - FUNCTION(dp_lcd), - FUNCTION(gcc_gp1), - FUNCTION(gcc_gp2), - FUNCTION(gcc_gp3), - FUNCTION(gpio), - FUNCTION(ibi_i3c), - FUNCTION(jitter_bist), - FUNCTION(lpass_slimbus), - FUNCTION(mdp_vsync), - FUNCTION(mdp_vsync0), - FUNCTION(mdp_vsync1), - FUNCTION(mdp_vsync2), - FUNCTION(mdp_vsync3), - FUNCTION(mi2s0_data0), - FUNCTION(mi2s0_data1), - FUNCTION(mi2s0_sck), - FUNCTION(mi2s0_ws), - FUNCTION(mi2s1_data0), - FUNCTION(mi2s1_data1), - FUNCTION(mi2s1_sck), - FUNCTION(mi2s1_ws), - FUNCTION(mi2s2_data0), - FUNCTION(mi2s2_data1), - FUNCTION(mi2s2_sck), - FUNCTION(mi2s2_ws), - FUNCTION(mss_grfc0), - FUNCTION(mss_grfc1), - FUNCTION(mss_grfc10), - FUNCTION(mss_grfc11), - FUNCTION(mss_grfc12), - FUNCTION(mss_grfc2), - FUNCTION(mss_grfc3), - FUNCTION(mss_grfc4), - FUNCTION(mss_grfc5), - FUNCTION(mss_grfc6), - FUNCTION(mss_grfc7), - FUNCTION(mss_grfc8), - FUNCTION(mss_grfc9), - FUNCTION(nav_gpio), - FUNCTION(pa_indicator), - FUNCTION(pcie0_clkreqn), - FUNCTION(pcie1_clkreqn), - FUNCTION(phase_flag), - FUNCTION(pll_bist), - FUNCTION(pll_clk), - FUNCTION(pri_mi2s), - FUNCTION(prng_rosc), - FUNCTION(qdss_cti), - FUNCTION(qdss_gpio), - FUNCTION(qlink0_enable), - FUNCTION(qlink0_request), - FUNCTION(qlink0_wmss), - FUNCTION(qlink1_enable), - FUNCTION(qlink1_request), - FUNCTION(qlink1_wmss), - FUNCTION(qlink2_enable), - FUNCTION(qlink2_request), - FUNCTION(qlink2_wmss), - FUNCTION(qspi0), - FUNCTION(qspi1), - FUNCTION(qspi2), - FUNCTION(qspi3), - FUNCTION(qspi_clk), - FUNCTION(qspi_cs), - FUNCTION(qup0), - FUNCTION(qup1), - FUNCTION(qup10), - FUNCTION(qup11), - FUNCTION(qup12), - FUNCTION(qup13), - FUNCTION(qup14), - FUNCTION(qup15), - FUNCTION(qup16), - FUNCTION(qup17), - FUNCTION(qup18), - FUNCTION(qup19), - FUNCTION(qup2), - FUNCTION(qup3), - FUNCTION(qup4), - FUNCTION(qup5), - FUNCTION(qup6), - FUNCTION(qup7), - FUNCTION(qup8), - FUNCTION(qup9), - FUNCTION(qup_l4), - FUNCTION(qup_l5), - FUNCTION(qup_l6), - FUNCTION(sd_write), - FUNCTION(sdc40), - FUNCTION(sdc41), - FUNCTION(sdc42), - FUNCTION(sdc43), - FUNCTION(sdc4_clk), - FUNCTION(sdc4_cmd), - FUNCTION(sec_mi2s), - FUNCTION(tb_trig), - FUNCTION(tgu_ch0), - FUNCTION(tgu_ch1), - FUNCTION(tgu_ch2), - FUNCTION(tgu_ch3), - FUNCTION(tsense_pwm1), - FUNCTION(tsense_pwm2), - FUNCTION(uim0_clk), - FUNCTION(uim0_data), - FUNCTION(uim0_present), - FUNCTION(uim0_reset), - FUNCTION(uim1_clk), - FUNCTION(uim1_data), - FUNCTION(uim1_present), - FUNCTION(uim1_reset), - FUNCTION(usb2phy_ac), - FUNCTION(usb_phy), - FUNCTION(vfr_0), - FUNCTION(vfr_1), - FUNCTION(vsense_trigger), +static const struct pinfunction sm8350_functions[] = { + MSM_PIN_FUNCTION(atest_char), + MSM_PIN_FUNCTION(atest_usb), + MSM_PIN_FUNCTION(audio_ref), + MSM_PIN_FUNCTION(cam_mclk), + MSM_PIN_FUNCTION(cci_async), + MSM_PIN_FUNCTION(cci_i2c), + MSM_PIN_FUNCTION(cci_timer), + MSM_PIN_FUNCTION(cmu_rng), + MSM_PIN_FUNCTION(coex_uart1), + MSM_PIN_FUNCTION(coex_uart2), + MSM_PIN_FUNCTION(cri_trng), + MSM_PIN_FUNCTION(cri_trng0), + MSM_PIN_FUNCTION(cri_trng1), + MSM_PIN_FUNCTION(dbg_out), + MSM_PIN_FUNCTION(ddr_bist), + MSM_PIN_FUNCTION(ddr_pxi0), + MSM_PIN_FUNCTION(ddr_pxi1), + MSM_PIN_FUNCTION(ddr_pxi2), + MSM_PIN_FUNCTION(ddr_pxi3), + MSM_PIN_FUNCTION(dp_hot), + MSM_PIN_FUNCTION(dp_lcd), + MSM_PIN_FUNCTION(gcc_gp1), + MSM_PIN_FUNCTION(gcc_gp2), + MSM_PIN_FUNCTION(gcc_gp3), + MSM_PIN_FUNCTION(gpio), + MSM_PIN_FUNCTION(ibi_i3c), + MSM_PIN_FUNCTION(jitter_bist), + MSM_PIN_FUNCTION(lpass_slimbus), + MSM_PIN_FUNCTION(mdp_vsync), + MSM_PIN_FUNCTION(mdp_vsync0), + MSM_PIN_FUNCTION(mdp_vsync1), + MSM_PIN_FUNCTION(mdp_vsync2), + MSM_PIN_FUNCTION(mdp_vsync3), + MSM_PIN_FUNCTION(mi2s0_data0), + MSM_PIN_FUNCTION(mi2s0_data1), + MSM_PIN_FUNCTION(mi2s0_sck), + MSM_PIN_FUNCTION(mi2s0_ws), + MSM_PIN_FUNCTION(mi2s1_data0), + MSM_PIN_FUNCTION(mi2s1_data1), + MSM_PIN_FUNCTION(mi2s1_sck), + MSM_PIN_FUNCTION(mi2s1_ws), + MSM_PIN_FUNCTION(mi2s2_data0), + MSM_PIN_FUNCTION(mi2s2_data1), + MSM_PIN_FUNCTION(mi2s2_sck), + MSM_PIN_FUNCTION(mi2s2_ws), + MSM_PIN_FUNCTION(mss_grfc0), + MSM_PIN_FUNCTION(mss_grfc1), + MSM_PIN_FUNCTION(mss_grfc10), + MSM_PIN_FUNCTION(mss_grfc11), + MSM_PIN_FUNCTION(mss_grfc12), + MSM_PIN_FUNCTION(mss_grfc2), + MSM_PIN_FUNCTION(mss_grfc3), + MSM_PIN_FUNCTION(mss_grfc4), + MSM_PIN_FUNCTION(mss_grfc5), + MSM_PIN_FUNCTION(mss_grfc6), + MSM_PIN_FUNCTION(mss_grfc7), + MSM_PIN_FUNCTION(mss_grfc8), + MSM_PIN_FUNCTION(mss_grfc9), + MSM_PIN_FUNCTION(nav_gpio), + MSM_PIN_FUNCTION(pa_indicator), + MSM_PIN_FUNCTION(pcie0_clkreqn), + MSM_PIN_FUNCTION(pcie1_clkreqn), + MSM_PIN_FUNCTION(phase_flag), + MSM_PIN_FUNCTION(pll_bist), + MSM_PIN_FUNCTION(pll_clk), + MSM_PIN_FUNCTION(pri_mi2s), + MSM_PIN_FUNCTION(prng_rosc), + MSM_PIN_FUNCTION(qdss_cti), + MSM_PIN_FUNCTION(qdss_gpio), + MSM_PIN_FUNCTION(qlink0_enable), + MSM_PIN_FUNCTION(qlink0_request), + MSM_PIN_FUNCTION(qlink0_wmss), + MSM_PIN_FUNCTION(qlink1_enable), + MSM_PIN_FUNCTION(qlink1_request), + MSM_PIN_FUNCTION(qlink1_wmss), + MSM_PIN_FUNCTION(qlink2_enable), + MSM_PIN_FUNCTION(qlink2_request), + MSM_PIN_FUNCTION(qlink2_wmss), + MSM_PIN_FUNCTION(qspi0), + MSM_PIN_FUNCTION(qspi1), + MSM_PIN_FUNCTION(qspi2), + MSM_PIN_FUNCTION(qspi3), + MSM_PIN_FUNCTION(qspi_clk), + MSM_PIN_FUNCTION(qspi_cs), + MSM_PIN_FUNCTION(qup0), + MSM_PIN_FUNCTION(qup1), + MSM_PIN_FUNCTION(qup10), + MSM_PIN_FUNCTION(qup11), + MSM_PIN_FUNCTION(qup12), + MSM_PIN_FUNCTION(qup13), + MSM_PIN_FUNCTION(qup14), + MSM_PIN_FUNCTION(qup15), + MSM_PIN_FUNCTION(qup16), + MSM_PIN_FUNCTION(qup17), + MSM_PIN_FUNCTION(qup18), + MSM_PIN_FUNCTION(qup19), + MSM_PIN_FUNCTION(qup2), + MSM_PIN_FUNCTION(qup3), + MSM_PIN_FUNCTION(qup4), + MSM_PIN_FUNCTION(qup5), + MSM_PIN_FUNCTION(qup6), + MSM_PIN_FUNCTION(qup7), + MSM_PIN_FUNCTION(qup8), + MSM_PIN_FUNCTION(qup9), + MSM_PIN_FUNCTION(qup_l4), + MSM_PIN_FUNCTION(qup_l5), + MSM_PIN_FUNCTION(qup_l6), + MSM_PIN_FUNCTION(sd_write), + MSM_PIN_FUNCTION(sdc40), + MSM_PIN_FUNCTION(sdc41), + MSM_PIN_FUNCTION(sdc42), + MSM_PIN_FUNCTION(sdc43), + MSM_PIN_FUNCTION(sdc4_clk), + MSM_PIN_FUNCTION(sdc4_cmd), + MSM_PIN_FUNCTION(sec_mi2s), + MSM_PIN_FUNCTION(tb_trig), + MSM_PIN_FUNCTION(tgu_ch0), + MSM_PIN_FUNCTION(tgu_ch1), + MSM_PIN_FUNCTION(tgu_ch2), + MSM_PIN_FUNCTION(tgu_ch3), + MSM_PIN_FUNCTION(tsense_pwm1), + MSM_PIN_FUNCTION(tsense_pwm2), + MSM_PIN_FUNCTION(uim0_clk), + MSM_PIN_FUNCTION(uim0_data), + MSM_PIN_FUNCTION(uim0_present), + MSM_PIN_FUNCTION(uim0_reset), + MSM_PIN_FUNCTION(uim1_clk), + MSM_PIN_FUNCTION(uim1_data), + MSM_PIN_FUNCTION(uim1_present), + MSM_PIN_FUNCTION(uim1_reset), + MSM_PIN_FUNCTION(usb2phy_ac), + MSM_PIN_FUNCTION(usb_phy), + MSM_PIN_FUNCTION(vfr_0), + MSM_PIN_FUNCTION(vfr_1), + MSM_PIN_FUNCTION(vsense_trigger), }; /* Every pin is maintained as a single group, and missing or non-existing pin diff --git a/drivers/pinctrl/qcom/pinctrl-sm8450.c b/drivers/pinctrl/qcom/pinctrl-sm8450.c index 3110d7bf5698a3aea00f2bb3e6eae1530919db01..d11bb1ee9e3d8dfbb1e810051d5c854a959b428b 100644 --- a/drivers/pinctrl/qcom/pinctrl-sm8450.c +++ b/drivers/pinctrl/qcom/pinctrl-sm8450.c @@ -7,24 +7,16 @@ #include #include #include -#include #include "pinctrl-msm.h" -#define FUNCTION(fname) \ - [msm_mux_##fname] = { \ - .name = #fname, \ - .groups = fname##_groups, \ - .ngroups = ARRAY_SIZE(fname##_groups), \ - } - #define REG_SIZE 0x1000 #define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9) \ { \ - .name = "gpio" #id, \ - .pins = gpio##id##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(gpio##id##_pins), \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ .funcs = (int[]){ \ msm_mux_gpio, /* gpio mode */ \ msm_mux_##f1, \ @@ -63,9 +55,9 @@ #define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = ctl, \ .io_reg = 0, \ .intr_cfg_reg = 0, \ @@ -88,9 +80,9 @@ #define UFS_RESET(pg_name, offset) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = offset, \ .io_reg = offset + 0x4, \ .intr_cfg_reg = 0, \ @@ -1276,143 +1268,143 @@ static const char * const vsense_trigger_groups[] = { "gpio18", }; -static const struct msm_function sm8450_functions[] = { - FUNCTION(gpio), - FUNCTION(aon_cam), - FUNCTION(atest_char), - FUNCTION(atest_usb), - FUNCTION(audio_ref), - FUNCTION(cam_mclk), - FUNCTION(cci_async), - FUNCTION(cci_i2c), - FUNCTION(cci_timer), - FUNCTION(cmu_rng), - FUNCTION(coex_uart1), - FUNCTION(coex_uart2), - FUNCTION(cri_trng), - FUNCTION(cri_trng0), - FUNCTION(cri_trng1), - FUNCTION(dbg_out), - FUNCTION(ddr_bist), - FUNCTION(ddr_pxi0), - FUNCTION(ddr_pxi1), - FUNCTION(ddr_pxi2), - FUNCTION(ddr_pxi3), - FUNCTION(dp_hot), - FUNCTION(egpio), - FUNCTION(gcc_gp1), - FUNCTION(gcc_gp2), - FUNCTION(gcc_gp3), - FUNCTION(ibi_i3c), - FUNCTION(jitter_bist), - FUNCTION(mdp_vsync), - FUNCTION(mdp_vsync0), - FUNCTION(mdp_vsync1), - FUNCTION(mdp_vsync2), - FUNCTION(mdp_vsync3), - FUNCTION(mi2s0_data0), - FUNCTION(mi2s0_data1), - FUNCTION(mi2s0_sck), - FUNCTION(mi2s0_ws), - FUNCTION(mi2s2_data0), - FUNCTION(mi2s2_data1), - FUNCTION(mi2s2_sck), - FUNCTION(mi2s2_ws), - FUNCTION(mss_grfc0), - FUNCTION(mss_grfc1), - FUNCTION(mss_grfc10), - FUNCTION(mss_grfc11), - FUNCTION(mss_grfc12), - FUNCTION(mss_grfc2), - FUNCTION(mss_grfc3), - FUNCTION(mss_grfc4), - FUNCTION(mss_grfc5), - FUNCTION(mss_grfc6), - FUNCTION(mss_grfc7), - FUNCTION(mss_grfc8), - FUNCTION(mss_grfc9), - FUNCTION(nav), - FUNCTION(pcie0_clkreqn), - FUNCTION(pcie1_clkreqn), - FUNCTION(phase_flag), - FUNCTION(pll_bist), - FUNCTION(pll_clk), - FUNCTION(pri_mi2s), - FUNCTION(prng_rosc), - FUNCTION(qdss_cti), - FUNCTION(qdss_gpio), - FUNCTION(qlink0_enable), - FUNCTION(qlink0_request), - FUNCTION(qlink0_wmss), - FUNCTION(qlink1_enable), - FUNCTION(qlink1_request), - FUNCTION(qlink1_wmss), - FUNCTION(qlink2_enable), - FUNCTION(qlink2_request), - FUNCTION(qlink2_wmss), - FUNCTION(qspi0), - FUNCTION(qspi1), - FUNCTION(qspi2), - FUNCTION(qspi3), - FUNCTION(qspi_clk), - FUNCTION(qspi_cs), - FUNCTION(qup0), - FUNCTION(qup1), - FUNCTION(qup10), - FUNCTION(qup11), - FUNCTION(qup12), - FUNCTION(qup13), - FUNCTION(qup14), - FUNCTION(qup15), - FUNCTION(qup16), - FUNCTION(qup17), - FUNCTION(qup18), - FUNCTION(qup19), - FUNCTION(qup2), - FUNCTION(qup20), - FUNCTION(qup21), - FUNCTION(qup3), - FUNCTION(qup4), - FUNCTION(qup5), - FUNCTION(qup6), - FUNCTION(qup7), - FUNCTION(qup8), - FUNCTION(qup9), - FUNCTION(qup_l4), - FUNCTION(qup_l5), - FUNCTION(qup_l6), - FUNCTION(sd_write), - FUNCTION(sdc40), - FUNCTION(sdc41), - FUNCTION(sdc42), - FUNCTION(sdc43), - FUNCTION(sdc4_clk), - FUNCTION(sdc4_cmd), - FUNCTION(sec_mi2s), - FUNCTION(tb_trig), - FUNCTION(tgu_ch0), - FUNCTION(tgu_ch1), - FUNCTION(tgu_ch2), - FUNCTION(tgu_ch3), - FUNCTION(tmess_prng0), - FUNCTION(tmess_prng1), - FUNCTION(tmess_prng2), - FUNCTION(tmess_prng3), - FUNCTION(tsense_pwm1), - FUNCTION(tsense_pwm2), - FUNCTION(uim0_clk), - FUNCTION(uim0_data), - FUNCTION(uim0_present), - FUNCTION(uim0_reset), - FUNCTION(uim1_clk), - FUNCTION(uim1_data), - FUNCTION(uim1_present), - FUNCTION(uim1_reset), - FUNCTION(usb2phy_ac), - FUNCTION(usb_phy), - FUNCTION(vfr_0), - FUNCTION(vfr_1), - FUNCTION(vsense_trigger), +static const struct pinfunction sm8450_functions[] = { + MSM_PIN_FUNCTION(gpio), + MSM_PIN_FUNCTION(aon_cam), + MSM_PIN_FUNCTION(atest_char), + MSM_PIN_FUNCTION(atest_usb), + MSM_PIN_FUNCTION(audio_ref), + MSM_PIN_FUNCTION(cam_mclk), + MSM_PIN_FUNCTION(cci_async), + MSM_PIN_FUNCTION(cci_i2c), + MSM_PIN_FUNCTION(cci_timer), + MSM_PIN_FUNCTION(cmu_rng), + MSM_PIN_FUNCTION(coex_uart1), + MSM_PIN_FUNCTION(coex_uart2), + MSM_PIN_FUNCTION(cri_trng), + MSM_PIN_FUNCTION(cri_trng0), + MSM_PIN_FUNCTION(cri_trng1), + MSM_PIN_FUNCTION(dbg_out), + MSM_PIN_FUNCTION(ddr_bist), + MSM_PIN_FUNCTION(ddr_pxi0), + MSM_PIN_FUNCTION(ddr_pxi1), + MSM_PIN_FUNCTION(ddr_pxi2), + MSM_PIN_FUNCTION(ddr_pxi3), + MSM_PIN_FUNCTION(dp_hot), + MSM_PIN_FUNCTION(egpio), + MSM_PIN_FUNCTION(gcc_gp1), + MSM_PIN_FUNCTION(gcc_gp2), + MSM_PIN_FUNCTION(gcc_gp3), + MSM_PIN_FUNCTION(ibi_i3c), + MSM_PIN_FUNCTION(jitter_bist), + MSM_PIN_FUNCTION(mdp_vsync), + MSM_PIN_FUNCTION(mdp_vsync0), + MSM_PIN_FUNCTION(mdp_vsync1), + MSM_PIN_FUNCTION(mdp_vsync2), + MSM_PIN_FUNCTION(mdp_vsync3), + MSM_PIN_FUNCTION(mi2s0_data0), + MSM_PIN_FUNCTION(mi2s0_data1), + MSM_PIN_FUNCTION(mi2s0_sck), + MSM_PIN_FUNCTION(mi2s0_ws), + MSM_PIN_FUNCTION(mi2s2_data0), + MSM_PIN_FUNCTION(mi2s2_data1), + MSM_PIN_FUNCTION(mi2s2_sck), + MSM_PIN_FUNCTION(mi2s2_ws), + MSM_PIN_FUNCTION(mss_grfc0), + MSM_PIN_FUNCTION(mss_grfc1), + MSM_PIN_FUNCTION(mss_grfc10), + MSM_PIN_FUNCTION(mss_grfc11), + MSM_PIN_FUNCTION(mss_grfc12), + MSM_PIN_FUNCTION(mss_grfc2), + MSM_PIN_FUNCTION(mss_grfc3), + MSM_PIN_FUNCTION(mss_grfc4), + MSM_PIN_FUNCTION(mss_grfc5), + MSM_PIN_FUNCTION(mss_grfc6), + MSM_PIN_FUNCTION(mss_grfc7), + MSM_PIN_FUNCTION(mss_grfc8), + MSM_PIN_FUNCTION(mss_grfc9), + MSM_PIN_FUNCTION(nav), + MSM_PIN_FUNCTION(pcie0_clkreqn), + MSM_PIN_FUNCTION(pcie1_clkreqn), + MSM_PIN_FUNCTION(phase_flag), + MSM_PIN_FUNCTION(pll_bist), + MSM_PIN_FUNCTION(pll_clk), + MSM_PIN_FUNCTION(pri_mi2s), + MSM_PIN_FUNCTION(prng_rosc), + MSM_PIN_FUNCTION(qdss_cti), + MSM_PIN_FUNCTION(qdss_gpio), + MSM_PIN_FUNCTION(qlink0_enable), + MSM_PIN_FUNCTION(qlink0_request), + MSM_PIN_FUNCTION(qlink0_wmss), + MSM_PIN_FUNCTION(qlink1_enable), + MSM_PIN_FUNCTION(qlink1_request), + MSM_PIN_FUNCTION(qlink1_wmss), + MSM_PIN_FUNCTION(qlink2_enable), + MSM_PIN_FUNCTION(qlink2_request), + MSM_PIN_FUNCTION(qlink2_wmss), + MSM_PIN_FUNCTION(qspi0), + MSM_PIN_FUNCTION(qspi1), + MSM_PIN_FUNCTION(qspi2), + MSM_PIN_FUNCTION(qspi3), + MSM_PIN_FUNCTION(qspi_clk), + MSM_PIN_FUNCTION(qspi_cs), + MSM_PIN_FUNCTION(qup0), + MSM_PIN_FUNCTION(qup1), + MSM_PIN_FUNCTION(qup10), + MSM_PIN_FUNCTION(qup11), + MSM_PIN_FUNCTION(qup12), + MSM_PIN_FUNCTION(qup13), + MSM_PIN_FUNCTION(qup14), + MSM_PIN_FUNCTION(qup15), + MSM_PIN_FUNCTION(qup16), + MSM_PIN_FUNCTION(qup17), + MSM_PIN_FUNCTION(qup18), + MSM_PIN_FUNCTION(qup19), + MSM_PIN_FUNCTION(qup2), + MSM_PIN_FUNCTION(qup20), + MSM_PIN_FUNCTION(qup21), + MSM_PIN_FUNCTION(qup3), + MSM_PIN_FUNCTION(qup4), + MSM_PIN_FUNCTION(qup5), + MSM_PIN_FUNCTION(qup6), + MSM_PIN_FUNCTION(qup7), + MSM_PIN_FUNCTION(qup8), + MSM_PIN_FUNCTION(qup9), + MSM_PIN_FUNCTION(qup_l4), + MSM_PIN_FUNCTION(qup_l5), + MSM_PIN_FUNCTION(qup_l6), + MSM_PIN_FUNCTION(sd_write), + MSM_PIN_FUNCTION(sdc40), + MSM_PIN_FUNCTION(sdc41), + MSM_PIN_FUNCTION(sdc42), + MSM_PIN_FUNCTION(sdc43), + MSM_PIN_FUNCTION(sdc4_clk), + MSM_PIN_FUNCTION(sdc4_cmd), + MSM_PIN_FUNCTION(sec_mi2s), + MSM_PIN_FUNCTION(tb_trig), + MSM_PIN_FUNCTION(tgu_ch0), + MSM_PIN_FUNCTION(tgu_ch1), + MSM_PIN_FUNCTION(tgu_ch2), + MSM_PIN_FUNCTION(tgu_ch3), + MSM_PIN_FUNCTION(tmess_prng0), + MSM_PIN_FUNCTION(tmess_prng1), + MSM_PIN_FUNCTION(tmess_prng2), + MSM_PIN_FUNCTION(tmess_prng3), + MSM_PIN_FUNCTION(tsense_pwm1), + MSM_PIN_FUNCTION(tsense_pwm2), + MSM_PIN_FUNCTION(uim0_clk), + MSM_PIN_FUNCTION(uim0_data), + MSM_PIN_FUNCTION(uim0_present), + MSM_PIN_FUNCTION(uim0_reset), + MSM_PIN_FUNCTION(uim1_clk), + MSM_PIN_FUNCTION(uim1_data), + MSM_PIN_FUNCTION(uim1_present), + MSM_PIN_FUNCTION(uim1_reset), + MSM_PIN_FUNCTION(usb2phy_ac), + MSM_PIN_FUNCTION(usb_phy), + MSM_PIN_FUNCTION(vfr_0), + MSM_PIN_FUNCTION(vfr_1), + MSM_PIN_FUNCTION(vsense_trigger), }; /* Every pin is maintained as a single group, and missing or non-existing pin diff --git a/drivers/pinctrl/qcom/pinctrl-sm8550.c b/drivers/pinctrl/qcom/pinctrl-sm8550.c index c9d038098f2cad8fa7f4f6d060d8e5dcf6eb213c..3c847d9cb5d93bbc7bb5a9b0b2ee707e14de6387 100644 --- a/drivers/pinctrl/qcom/pinctrl-sm8550.c +++ b/drivers/pinctrl/qcom/pinctrl-sm8550.c @@ -8,24 +8,16 @@ #include #include #include -#include #include "pinctrl-msm.h" -#define FUNCTION(fname) \ - [msm_mux_##fname] = { \ - .name = #fname, \ - .groups = fname##_groups, \ - .ngroups = ARRAY_SIZE(fname##_groups), \ - } - #define REG_SIZE 0x1000 #define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9) \ { \ - .name = "gpio" #id, \ - .pins = gpio##id##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(gpio##id##_pins), \ + .grp = PINCTRL_PINGROUP("gpio" #id, \ + gpio##id##_pins, \ + ARRAY_SIZE(gpio##id##_pins)), \ .funcs = (int[]){ \ msm_mux_gpio, /* gpio mode */ \ msm_mux_##f1, \ @@ -65,9 +57,9 @@ #define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = ctl, \ .io_reg = 0, \ .intr_cfg_reg = 0, \ @@ -90,9 +82,9 @@ #define UFS_RESET(pg_name, offset) \ { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ + ARRAY_SIZE(pg_name##_pins)), \ .ctl_reg = offset, \ .io_reg = offset + 0x4, \ .intr_cfg_reg = 0, \ @@ -1347,153 +1339,153 @@ static const char *const vsense_trigger_mirnat_groups[] = { "gpio24", }; -static const struct msm_function sm8550_functions[] = { - FUNCTION(gpio), - FUNCTION(aon_cci), - FUNCTION(aoss_cti), - FUNCTION(atest_char), - FUNCTION(atest_usb), - FUNCTION(audio_ext_mclk0), - FUNCTION(audio_ext_mclk1), - FUNCTION(audio_ref_clk), - FUNCTION(cam_aon_mclk4), - FUNCTION(cam_mclk), - FUNCTION(cci_async_in), - FUNCTION(cci_i2c_scl), - FUNCTION(cci_i2c_sda), - FUNCTION(cci_timer), - FUNCTION(cmu_rng), - FUNCTION(coex_uart1_rx), - FUNCTION(coex_uart1_tx), - FUNCTION(coex_uart2_rx), - FUNCTION(coex_uart2_tx), - FUNCTION(cri_trng), - FUNCTION(dbg_out_clk), - FUNCTION(ddr_bist_complete), - FUNCTION(ddr_bist_fail), - FUNCTION(ddr_bist_start), - FUNCTION(ddr_bist_stop), - FUNCTION(ddr_pxi0), - FUNCTION(ddr_pxi1), - FUNCTION(ddr_pxi2), - FUNCTION(ddr_pxi3), - FUNCTION(dp_hot), - FUNCTION(gcc_gp1), - FUNCTION(gcc_gp2), - FUNCTION(gcc_gp3), - FUNCTION(i2chub0_se0), - FUNCTION(i2chub0_se1), - FUNCTION(i2chub0_se2), - FUNCTION(i2chub0_se3), - FUNCTION(i2chub0_se4), - FUNCTION(i2chub0_se5), - FUNCTION(i2chub0_se6), - FUNCTION(i2chub0_se7), - FUNCTION(i2chub0_se8), - FUNCTION(i2chub0_se9), - FUNCTION(i2s0_data0), - FUNCTION(i2s0_data1), - FUNCTION(i2s0_sck), - FUNCTION(i2s0_ws), - FUNCTION(i2s1_data0), - FUNCTION(i2s1_data1), - FUNCTION(i2s1_sck), - FUNCTION(i2s1_ws), - FUNCTION(ibi_i3c), - FUNCTION(jitter_bist), - FUNCTION(mdp_vsync), - FUNCTION(mdp_vsync0_out), - FUNCTION(mdp_vsync1_out), - FUNCTION(mdp_vsync2_out), - FUNCTION(mdp_vsync3_out), - FUNCTION(mdp_vsync_e), - FUNCTION(nav_gpio0), - FUNCTION(nav_gpio1), - FUNCTION(nav_gpio2), - FUNCTION(pcie0_clk_req_n), - FUNCTION(pcie1_clk_req_n), - FUNCTION(phase_flag), - FUNCTION(pll_bist_sync), - FUNCTION(pll_clk_aux), - FUNCTION(prng_rosc0), - FUNCTION(prng_rosc1), - FUNCTION(prng_rosc2), - FUNCTION(prng_rosc3), - FUNCTION(qdss_cti), - FUNCTION(qdss_gpio), - FUNCTION(qlink0_enable), - FUNCTION(qlink0_request), - FUNCTION(qlink0_wmss), - FUNCTION(qlink1_enable), - FUNCTION(qlink1_request), - FUNCTION(qlink1_wmss), - FUNCTION(qlink2_enable), - FUNCTION(qlink2_request), - FUNCTION(qlink2_wmss), - FUNCTION(qspi0), - FUNCTION(qspi1), - FUNCTION(qspi2), - FUNCTION(qspi3), - FUNCTION(qspi_clk), - FUNCTION(qspi_cs), - FUNCTION(qup1_se0), - FUNCTION(qup1_se1), - FUNCTION(qup1_se2), - FUNCTION(qup1_se3), - FUNCTION(qup1_se4), - FUNCTION(qup1_se5), - FUNCTION(qup1_se6), - FUNCTION(qup1_se7), - FUNCTION(qup2_se0), - FUNCTION(qup2_se0_l0_mira), - FUNCTION(qup2_se0_l0_mirb), - FUNCTION(qup2_se0_l1_mira), - FUNCTION(qup2_se0_l1_mirb), - FUNCTION(qup2_se0_l2_mira), - FUNCTION(qup2_se0_l2_mirb), - FUNCTION(qup2_se0_l3_mira), - FUNCTION(qup2_se0_l3_mirb), - FUNCTION(qup2_se1), - FUNCTION(qup2_se2), - FUNCTION(qup2_se3), - FUNCTION(qup2_se4), - FUNCTION(qup2_se5), - FUNCTION(qup2_se6), - FUNCTION(qup2_se7), - FUNCTION(resout_n), - FUNCTION(sd_write_protect), - FUNCTION(sdc40), - FUNCTION(sdc41), - FUNCTION(sdc42), - FUNCTION(sdc43), - FUNCTION(sdc4_clk), - FUNCTION(sdc4_cmd), - FUNCTION(tb_trig_sdc2), - FUNCTION(tb_trig_sdc4), - FUNCTION(tgu_ch0_trigout), - FUNCTION(tgu_ch1_trigout), - FUNCTION(tgu_ch2_trigout), - FUNCTION(tgu_ch3_trigout), - FUNCTION(tmess_prng0), - FUNCTION(tmess_prng1), - FUNCTION(tmess_prng2), - FUNCTION(tmess_prng3), - FUNCTION(tsense_pwm1), - FUNCTION(tsense_pwm2), - FUNCTION(tsense_pwm3), - FUNCTION(uim0_clk), - FUNCTION(uim0_data), - FUNCTION(uim0_present), - FUNCTION(uim0_reset), - FUNCTION(uim1_clk), - FUNCTION(uim1_data), - FUNCTION(uim1_present), - FUNCTION(uim1_reset), - FUNCTION(usb1_hs), - FUNCTION(usb_phy), - FUNCTION(vfr_0), - FUNCTION(vfr_1), - FUNCTION(vsense_trigger_mirnat), +static const struct pinfunction sm8550_functions[] = { + MSM_PIN_FUNCTION(gpio), + MSM_PIN_FUNCTION(aon_cci), + MSM_PIN_FUNCTION(aoss_cti), + MSM_PIN_FUNCTION(atest_char), + MSM_PIN_FUNCTION(atest_usb), + MSM_PIN_FUNCTION(audio_ext_mclk0), + MSM_PIN_FUNCTION(audio_ext_mclk1), + MSM_PIN_FUNCTION(audio_ref_clk), + MSM_PIN_FUNCTION(cam_aon_mclk4), + MSM_PIN_FUNCTION(cam_mclk), + MSM_PIN_FUNCTION(cci_async_in), + MSM_PIN_FUNCTION(cci_i2c_scl), + MSM_PIN_FUNCTION(cci_i2c_sda), + MSM_PIN_FUNCTION(cci_timer), + MSM_PIN_FUNCTION(cmu_rng), + MSM_PIN_FUNCTION(coex_uart1_rx), + MSM_PIN_FUNCTION(coex_uart1_tx), + MSM_PIN_FUNCTION(coex_uart2_rx), + MSM_PIN_FUNCTION(coex_uart2_tx), + MSM_PIN_FUNCTION(cri_trng), + MSM_PIN_FUNCTION(dbg_out_clk), + MSM_PIN_FUNCTION(ddr_bist_complete), + MSM_PIN_FUNCTION(ddr_bist_fail), + MSM_PIN_FUNCTION(ddr_bist_start), + MSM_PIN_FUNCTION(ddr_bist_stop), + MSM_PIN_FUNCTION(ddr_pxi0), + MSM_PIN_FUNCTION(ddr_pxi1), + MSM_PIN_FUNCTION(ddr_pxi2), + MSM_PIN_FUNCTION(ddr_pxi3), + MSM_PIN_FUNCTION(dp_hot), + MSM_PIN_FUNCTION(gcc_gp1), + MSM_PIN_FUNCTION(gcc_gp2), + MSM_PIN_FUNCTION(gcc_gp3), + MSM_PIN_FUNCTION(i2chub0_se0), + MSM_PIN_FUNCTION(i2chub0_se1), + MSM_PIN_FUNCTION(i2chub0_se2), + MSM_PIN_FUNCTION(i2chub0_se3), + MSM_PIN_FUNCTION(i2chub0_se4), + MSM_PIN_FUNCTION(i2chub0_se5), + MSM_PIN_FUNCTION(i2chub0_se6), + MSM_PIN_FUNCTION(i2chub0_se7), + MSM_PIN_FUNCTION(i2chub0_se8), + MSM_PIN_FUNCTION(i2chub0_se9), + MSM_PIN_FUNCTION(i2s0_data0), + MSM_PIN_FUNCTION(i2s0_data1), + MSM_PIN_FUNCTION(i2s0_sck), + MSM_PIN_FUNCTION(i2s0_ws), + MSM_PIN_FUNCTION(i2s1_data0), + MSM_PIN_FUNCTION(i2s1_data1), + MSM_PIN_FUNCTION(i2s1_sck), + MSM_PIN_FUNCTION(i2s1_ws), + MSM_PIN_FUNCTION(ibi_i3c), + MSM_PIN_FUNCTION(jitter_bist), + MSM_PIN_FUNCTION(mdp_vsync), + MSM_PIN_FUNCTION(mdp_vsync0_out), + MSM_PIN_FUNCTION(mdp_vsync1_out), + MSM_PIN_FUNCTION(mdp_vsync2_out), + MSM_PIN_FUNCTION(mdp_vsync3_out), + MSM_PIN_FUNCTION(mdp_vsync_e), + MSM_PIN_FUNCTION(nav_gpio0), + MSM_PIN_FUNCTION(nav_gpio1), + MSM_PIN_FUNCTION(nav_gpio2), + MSM_PIN_FUNCTION(pcie0_clk_req_n), + MSM_PIN_FUNCTION(pcie1_clk_req_n), + MSM_PIN_FUNCTION(phase_flag), + MSM_PIN_FUNCTION(pll_bist_sync), + MSM_PIN_FUNCTION(pll_clk_aux), + MSM_PIN_FUNCTION(prng_rosc0), + MSM_PIN_FUNCTION(prng_rosc1), + MSM_PIN_FUNCTION(prng_rosc2), + MSM_PIN_FUNCTION(prng_rosc3), + MSM_PIN_FUNCTION(qdss_cti), + MSM_PIN_FUNCTION(qdss_gpio), + MSM_PIN_FUNCTION(qlink0_enable), + MSM_PIN_FUNCTION(qlink0_request), + MSM_PIN_FUNCTION(qlink0_wmss), + MSM_PIN_FUNCTION(qlink1_enable), + MSM_PIN_FUNCTION(qlink1_request), + MSM_PIN_FUNCTION(qlink1_wmss), + MSM_PIN_FUNCTION(qlink2_enable), + MSM_PIN_FUNCTION(qlink2_request), + MSM_PIN_FUNCTION(qlink2_wmss), + MSM_PIN_FUNCTION(qspi0), + MSM_PIN_FUNCTION(qspi1), + MSM_PIN_FUNCTION(qspi2), + MSM_PIN_FUNCTION(qspi3), + MSM_PIN_FUNCTION(qspi_clk), + MSM_PIN_FUNCTION(qspi_cs), + MSM_PIN_FUNCTION(qup1_se0), + MSM_PIN_FUNCTION(qup1_se1), + MSM_PIN_FUNCTION(qup1_se2), + MSM_PIN_FUNCTION(qup1_se3), + MSM_PIN_FUNCTION(qup1_se4), + MSM_PIN_FUNCTION(qup1_se5), + MSM_PIN_FUNCTION(qup1_se6), + MSM_PIN_FUNCTION(qup1_se7), + MSM_PIN_FUNCTION(qup2_se0), + MSM_PIN_FUNCTION(qup2_se0_l0_mira), + MSM_PIN_FUNCTION(qup2_se0_l0_mirb), + MSM_PIN_FUNCTION(qup2_se0_l1_mira), + MSM_PIN_FUNCTION(qup2_se0_l1_mirb), + MSM_PIN_FUNCTION(qup2_se0_l2_mira), + MSM_PIN_FUNCTION(qup2_se0_l2_mirb), + MSM_PIN_FUNCTION(qup2_se0_l3_mira), + MSM_PIN_FUNCTION(qup2_se0_l3_mirb), + MSM_PIN_FUNCTION(qup2_se1), + MSM_PIN_FUNCTION(qup2_se2), + MSM_PIN_FUNCTION(qup2_se3), + MSM_PIN_FUNCTION(qup2_se4), + MSM_PIN_FUNCTION(qup2_se5), + MSM_PIN_FUNCTION(qup2_se6), + MSM_PIN_FUNCTION(qup2_se7), + MSM_PIN_FUNCTION(resout_n), + MSM_PIN_FUNCTION(sd_write_protect), + MSM_PIN_FUNCTION(sdc40), + MSM_PIN_FUNCTION(sdc41), + MSM_PIN_FUNCTION(sdc42), + MSM_PIN_FUNCTION(sdc43), + MSM_PIN_FUNCTION(sdc4_clk), + MSM_PIN_FUNCTION(sdc4_cmd), + MSM_PIN_FUNCTION(tb_trig_sdc2), + MSM_PIN_FUNCTION(tb_trig_sdc4), + MSM_PIN_FUNCTION(tgu_ch0_trigout), + MSM_PIN_FUNCTION(tgu_ch1_trigout), + MSM_PIN_FUNCTION(tgu_ch2_trigout), + MSM_PIN_FUNCTION(tgu_ch3_trigout), + MSM_PIN_FUNCTION(tmess_prng0), + MSM_PIN_FUNCTION(tmess_prng1), + MSM_PIN_FUNCTION(tmess_prng2), + MSM_PIN_FUNCTION(tmess_prng3), + MSM_PIN_FUNCTION(tsense_pwm1), + MSM_PIN_FUNCTION(tsense_pwm2), + MSM_PIN_FUNCTION(tsense_pwm3), + MSM_PIN_FUNCTION(uim0_clk), + MSM_PIN_FUNCTION(uim0_data), + MSM_PIN_FUNCTION(uim0_present), + MSM_PIN_FUNCTION(uim0_reset), + MSM_PIN_FUNCTION(uim1_clk), + MSM_PIN_FUNCTION(uim1_data), + MSM_PIN_FUNCTION(uim1_present), + MSM_PIN_FUNCTION(uim1_reset), + MSM_PIN_FUNCTION(usb1_hs), + MSM_PIN_FUNCTION(usb_phy), + MSM_PIN_FUNCTION(vfr_0), + MSM_PIN_FUNCTION(vfr_1), + MSM_PIN_FUNCTION(vsense_trigger_mirnat), }; /* diff --git a/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c b/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c index 43c7857c06a504b7ac981c4cd2fcaf32c0b62717..b4cd66886f290e1ad826fbdce35b02830ca87d02 100644 --- a/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c +++ b/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c @@ -1229,6 +1229,8 @@ static const struct of_device_id pmic_gpio_of_match[] = { { .compatible = "qcom,pm8941-gpio", .data = (void *) 36 }, /* pm8950 has 8 GPIOs with holes on 3 */ { .compatible = "qcom,pm8950-gpio", .data = (void *) 8 }, + /* pm8953 has 8 GPIOs with holes on 3 and 6 */ + { .compatible = "qcom,pm8953-gpio", .data = (void *) 8 }, { .compatible = "qcom,pm8994-gpio", .data = (void *) 22 }, { .compatible = "qcom,pm8998-gpio", .data = (void *) 26 }, { .compatible = "qcom,pma8084-gpio", .data = (void *) 22 }, diff --git a/drivers/pinctrl/renesas/pfc-r8a77970.c b/drivers/pinctrl/renesas/pfc-r8a77970.c index 5b66d7b1af9513375b2a3959b034cf4c05df1bb8..e1b3e3b38ec3b86499810a8d27d31bceb7879ab5 100644 --- a/drivers/pinctrl/renesas/pfc-r8a77970.c +++ b/drivers/pinctrl/renesas/pfc-r8a77970.c @@ -171,7 +171,7 @@ #define IP0_31_28 FM(DU_DG3) FM(MSIOF3_SS2) F_(0, 0) FM(A7) FM(PWMFSW0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP1_3_0 FM(DU_DG4) F_(0, 0) F_(0, 0) FM(A8) FM(FSO_CFE_0_N_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP1_7_4 FM(DU_DG5) F_(0, 0) F_(0, 0) FM(A9) FM(FSO_CFE_1_N_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) -#define IP1_11_8 FM(DU_DG6) F_(0, 0) F_(0, 0) FM(A10) FM(FSO_TOE_N_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP1_11_8 FM(DU_DG6) F_(0, 0) F_(0, 0) FM(A10) FM(FSO_TOE_N_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP1_15_12 FM(DU_DG7) F_(0, 0) F_(0, 0) FM(A11) FM(IRQ1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP1_19_16 FM(DU_DB2) F_(0, 0) F_(0, 0) FM(A12) FM(IRQ2) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP1_23_20 FM(DU_DB3) F_(0, 0) F_(0, 0) FM(A13) FM(FXR_CLKOUT1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) diff --git a/drivers/pinctrl/renesas/pfc-r8a77980.c b/drivers/pinctrl/renesas/pfc-r8a77980.c index 384faa0d6937b1bf4de21edea1971c08b438ac86..877134d78c7e50c6948c81438822583bad06b3c2 100644 --- a/drivers/pinctrl/renesas/pfc-r8a77980.c +++ b/drivers/pinctrl/renesas/pfc-r8a77980.c @@ -99,7 +99,7 @@ #define GPSR1_0 F_(IRQ0, IP2_27_24) /* GPSR2 */ -#define GPSR2_29 F_(FSO_TOE_N, IP10_19_16) +#define GPSR2_29 F_(FSO_TOE_N, IP10_19_16) #define GPSR2_28 F_(FSO_CFE_1_N, IP10_15_12) #define GPSR2_27 F_(FSO_CFE_0_N, IP10_11_8) #define GPSR2_26 F_(SDA3, IP10_7_4) @@ -264,11 +264,11 @@ #define IP8_11_8 FM(CANFD0_RX_A) FM(RXDA_EXTFXR) FM(PWM1_B) FM(DU_CDE) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP8_15_12 FM(CANFD1_TX) FM(FXR_TXDB) FM(PWM2_B) FM(TCLK1_B) FM(TX1_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP8_19_16 FM(CANFD1_RX) FM(RXDB_EXTFXR) FM(PWM3_B) FM(TCLK2_B) FM(RX1_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) -#define IP8_23_20 FM(CANFD_CLK_A) FM(CLK_EXTFXR) FM(PWM4_B) FM(SPEEDIN_B) FM(SCIF_CLK_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP8_23_20 FM(CANFD_CLK_A) FM(CLK_EXTFXR) FM(PWM4_B) FM(SPEEDIN_B) FM(SCIF_CLK_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP8_27_24 FM(DIGRF_CLKIN) FM(DIGRF_CLKEN_IN) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP8_31_28 FM(DIGRF_CLKOUT) FM(DIGRF_CLKEN_OUT) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP9_3_0 FM(IRQ4) F_(0, 0) F_(0, 0) FM(VI0_DATA12) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) -#define IP9_7_4 FM(IRQ5) F_(0, 0) F_(0, 0) FM(VI0_DATA13) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +#define IP9_7_4 FM(IRQ5) F_(0, 0) F_(0, 0) FM(VI0_DATA13) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP9_11_8 FM(MSIOF0_RXD) FM(DU_DR0) F_(0, 0) FM(VI0_DATA14) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP9_15_12 FM(MSIOF0_TXD) FM(DU_DR1) F_(0, 0) FM(VI0_DATA15) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP9_19_16 FM(MSIOF0_SCK) FM(DU_DG0) F_(0, 0) FM(VI0_DATA16) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) diff --git a/drivers/pinctrl/renesas/pinctrl-rzg2l.c b/drivers/pinctrl/renesas/pinctrl-rzg2l.c index 9511d920565e975220320bc9df86ff610136937c..b53d26167da52ec26ad7ba43260bdec70dba7999 100644 --- a/drivers/pinctrl/renesas/pinctrl-rzg2l.c +++ b/drivers/pinctrl/renesas/pinctrl-rzg2l.c @@ -249,6 +249,7 @@ static int rzg2l_map_add_config(struct pinctrl_map *map, static int rzg2l_dt_subnode_to_map(struct pinctrl_dev *pctldev, struct device_node *np, + struct device_node *parent, struct pinctrl_map **map, unsigned int *num_maps, unsigned int *index) @@ -266,6 +267,7 @@ static int rzg2l_dt_subnode_to_map(struct pinctrl_dev *pctldev, struct property *prop; int ret, gsel, fsel; const char **pin_fn; + const char *name; const char *pin; pinmux = of_find_property(np, "pinmux", NULL); @@ -349,8 +351,19 @@ static int rzg2l_dt_subnode_to_map(struct pinctrl_dev *pctldev, psel_val[i] = MUX_FUNC(value); } + if (parent) { + name = devm_kasprintf(pctrl->dev, GFP_KERNEL, "%pOFn.%pOFn", + parent, np); + if (!name) { + ret = -ENOMEM; + goto done; + } + } else { + name = np->name; + } + /* Register a single pin group listing all the pins we read from DT */ - gsel = pinctrl_generic_add_group(pctldev, np->name, pins, num_pinmux, NULL); + gsel = pinctrl_generic_add_group(pctldev, name, pins, num_pinmux, NULL); if (gsel < 0) { ret = gsel; goto done; @@ -360,17 +373,16 @@ static int rzg2l_dt_subnode_to_map(struct pinctrl_dev *pctldev, * Register a single group function where the 'data' is an array PSEL * register values read from DT. */ - pin_fn[0] = np->name; - fsel = pinmux_generic_add_function(pctldev, np->name, pin_fn, 1, - psel_val); + pin_fn[0] = name; + fsel = pinmux_generic_add_function(pctldev, name, pin_fn, 1, psel_val); if (fsel < 0) { ret = fsel; goto remove_group; } maps[idx].type = PIN_MAP_TYPE_MUX_GROUP; - maps[idx].data.mux.group = np->name; - maps[idx].data.mux.function = np->name; + maps[idx].data.mux.group = name; + maps[idx].data.mux.function = name; idx++; dev_dbg(pctrl->dev, "Parsed %pOF with %d pins\n", np, num_pinmux); @@ -417,7 +429,7 @@ static int rzg2l_dt_node_to_map(struct pinctrl_dev *pctldev, index = 0; for_each_child_of_node(np, child) { - ret = rzg2l_dt_subnode_to_map(pctldev, child, map, + ret = rzg2l_dt_subnode_to_map(pctldev, child, np, map, num_maps, &index); if (ret < 0) { of_node_put(child); @@ -426,7 +438,7 @@ static int rzg2l_dt_node_to_map(struct pinctrl_dev *pctldev, } if (*num_maps == 0) { - ret = rzg2l_dt_subnode_to_map(pctldev, np, map, + ret = rzg2l_dt_subnode_to_map(pctldev, np, NULL, map, num_maps, &index); if (ret < 0) goto done; diff --git a/drivers/pinctrl/renesas/pinctrl-rzv2m.c b/drivers/pinctrl/renesas/pinctrl-rzv2m.c index e5472293bc7fb2472d57dadeef6acffea849ee2c..35b23c1a5684d3e461fc3665f6f3369d6be3aee9 100644 --- a/drivers/pinctrl/renesas/pinctrl-rzv2m.c +++ b/drivers/pinctrl/renesas/pinctrl-rzv2m.c @@ -209,6 +209,7 @@ static int rzv2m_map_add_config(struct pinctrl_map *map, static int rzv2m_dt_subnode_to_map(struct pinctrl_dev *pctldev, struct device_node *np, + struct device_node *parent, struct pinctrl_map **map, unsigned int *num_maps, unsigned int *index) @@ -226,6 +227,7 @@ static int rzv2m_dt_subnode_to_map(struct pinctrl_dev *pctldev, struct property *prop; int ret, gsel, fsel; const char **pin_fn; + const char *name; const char *pin; pinmux = of_find_property(np, "pinmux", NULL); @@ -309,8 +311,19 @@ static int rzv2m_dt_subnode_to_map(struct pinctrl_dev *pctldev, psel_val[i] = MUX_FUNC(value); } + if (parent) { + name = devm_kasprintf(pctrl->dev, GFP_KERNEL, "%pOFn.%pOFn", + parent, np); + if (!name) { + ret = -ENOMEM; + goto done; + } + } else { + name = np->name; + } + /* Register a single pin group listing all the pins we read from DT */ - gsel = pinctrl_generic_add_group(pctldev, np->name, pins, num_pinmux, NULL); + gsel = pinctrl_generic_add_group(pctldev, name, pins, num_pinmux, NULL); if (gsel < 0) { ret = gsel; goto done; @@ -320,17 +333,16 @@ static int rzv2m_dt_subnode_to_map(struct pinctrl_dev *pctldev, * Register a single group function where the 'data' is an array PSEL * register values read from DT. */ - pin_fn[0] = np->name; - fsel = pinmux_generic_add_function(pctldev, np->name, pin_fn, 1, - psel_val); + pin_fn[0] = name; + fsel = pinmux_generic_add_function(pctldev, name, pin_fn, 1, psel_val); if (fsel < 0) { ret = fsel; goto remove_group; } maps[idx].type = PIN_MAP_TYPE_MUX_GROUP; - maps[idx].data.mux.group = np->name; - maps[idx].data.mux.function = np->name; + maps[idx].data.mux.group = name; + maps[idx].data.mux.function = name; idx++; dev_dbg(pctrl->dev, "Parsed %pOF with %d pins\n", np, num_pinmux); @@ -377,7 +389,7 @@ static int rzv2m_dt_node_to_map(struct pinctrl_dev *pctldev, index = 0; for_each_child_of_node(np, child) { - ret = rzv2m_dt_subnode_to_map(pctldev, child, map, + ret = rzv2m_dt_subnode_to_map(pctldev, child, np, map, num_maps, &index); if (ret < 0) { of_node_put(child); @@ -386,7 +398,7 @@ static int rzv2m_dt_node_to_map(struct pinctrl_dev *pctldev, } if (*num_maps == 0) { - ret = rzv2m_dt_subnode_to_map(pctldev, np, map, + ret = rzv2m_dt_subnode_to_map(pctldev, np, NULL, map, num_maps, &index); if (ret < 0) goto done; diff --git a/drivers/pinctrl/spear/pinctrl-spear.c b/drivers/pinctrl/spear/pinctrl-spear.c index 18de2e70ea503590e6d277eb931aba38ace1f084..b8caaa5a2d4ee7663fc5c7f89fe5da17e4e35fbf 100644 --- a/drivers/pinctrl/spear/pinctrl-spear.c +++ b/drivers/pinctrl/spear/pinctrl-spear.c @@ -18,7 +18,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/pinctrl/stm32/Kconfig b/drivers/pinctrl/stm32/Kconfig index d532f3c6f670de63c1a6b85c90b94ad8ed048a6e..2656d3d3ae4025507765c54079ef6894ef5628c0 100644 --- a/drivers/pinctrl/stm32/Kconfig +++ b/drivers/pinctrl/stm32/Kconfig @@ -51,4 +51,10 @@ config PINCTRL_STM32MP157 depends on OF && HAS_IOMEM default MACH_STM32MP157 select PINCTRL_STM32 + +config PINCTRL_STM32MP257 + bool "STMicroelectronics STM32MP257 pin control" if COMPILE_TEST && !MACH_STM32MP25 + depends on OF && HAS_IOMEM + default MACH_STM32MP25 + select PINCTRL_STM32 endif diff --git a/drivers/pinctrl/stm32/Makefile b/drivers/pinctrl/stm32/Makefile index 619629ee9944da73a75719cf0d739bb9b4fbefe5..7b17464d8de1d5c2077ab58db51fd1774c6d8cbd 100644 --- a/drivers/pinctrl/stm32/Makefile +++ b/drivers/pinctrl/stm32/Makefile @@ -10,3 +10,4 @@ obj-$(CONFIG_PINCTRL_STM32F769) += pinctrl-stm32f769.o obj-$(CONFIG_PINCTRL_STM32H743) += pinctrl-stm32h743.o obj-$(CONFIG_PINCTRL_STM32MP135) += pinctrl-stm32mp135.o obj-$(CONFIG_PINCTRL_STM32MP157) += pinctrl-stm32mp157.o +obj-$(CONFIG_PINCTRL_STM32MP257) += pinctrl-stm32mp257.o diff --git a/drivers/pinctrl/stm32/pinctrl-stm32.h b/drivers/pinctrl/stm32/pinctrl-stm32.h index e0c31c4c8bca8fa4e0e7015838a444b2d19c9887..5e5de92ddd58cb0e0e31a9eef4c5d9a7c72c1d16 100644 --- a/drivers/pinctrl/stm32/pinctrl-stm32.h +++ b/drivers/pinctrl/stm32/pinctrl-stm32.h @@ -24,6 +24,9 @@ #define STM32MP_PKG_AB BIT(1) #define STM32MP_PKG_AC BIT(2) #define STM32MP_PKG_AD BIT(3) +#define STM32MP_PKG_AI BIT(8) +#define STM32MP_PKG_AK BIT(10) +#define STM32MP_PKG_AL BIT(11) struct stm32_desc_function { const char *name; diff --git a/drivers/pinctrl/stm32/pinctrl-stm32mp257.c b/drivers/pinctrl/stm32/pinctrl-stm32mp257.c new file mode 100644 index 0000000000000000000000000000000000000000..73f091cd827e69edae7e2c0f4743e54c6db14b40 --- /dev/null +++ b/drivers/pinctrl/stm32/pinctrl-stm32mp257.c @@ -0,0 +1,2581 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) STMicroelectronics 2023 - All Rights Reserved + * Author: Alexandre Torgue for STMicroelectronics. + */ +#include +#include +#include + +#include "pinctrl-stm32.h" + +static const struct stm32_desc_pin stm32mp257_pins[] = { + STM32_PIN_PKG( + PINCTRL_PIN(0, "PA0"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOA0"), + STM32_FUNCTION(2, "LPTIM1_CH2"), + STM32_FUNCTION(3, "SPI5_RDY"), + STM32_FUNCTION(4, "UART8_CTS"), + STM32_FUNCTION(5, "SAI2_MCLK_B"), + STM32_FUNCTION(6, "UART5_TX"), + STM32_FUNCTION(7, "USART3_TX"), + STM32_FUNCTION(8, "TIM3_ETR"), + STM32_FUNCTION(9, "TIM5_CH2"), + STM32_FUNCTION(11, "ETH2_MII_RXD2 ETH2_RGMII_RXD2"), + STM32_FUNCTION(13, "FMC_NL"), + STM32_FUNCTION(15, "DCMI_D9 PSSI_D9 DCMIPP_D9"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(1, "PA1"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOA1"), + STM32_FUNCTION(3, "SPI6_MISO"), + STM32_FUNCTION(5, "SAI3_SD_A"), + STM32_FUNCTION(6, "USART1_RTS"), + STM32_FUNCTION(7, "USART6_CK"), + STM32_FUNCTION(8, "TIM4_CH2"), + STM32_FUNCTION(9, "I2C4_SDA"), + STM32_FUNCTION(10, "I2C6_SDA"), + STM32_FUNCTION(12, "LCD_R3"), + STM32_FUNCTION(14, "DCMI_D5 PSSI_D5 DCMIPP_D5"), + STM32_FUNCTION(15, "ETH3_PHY_INTN"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(2, "PA2"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOA2"), + STM32_FUNCTION(2, "LPTIM2_IN1"), + STM32_FUNCTION(3, "SPI7_MISO"), + STM32_FUNCTION(6, "MDF1_SDI7"), + STM32_FUNCTION(7, "USART1_RX"), + STM32_FUNCTION(9, "I3C1_SDA"), + STM32_FUNCTION(11, "I2C1_SDA"), + STM32_FUNCTION(12, "LCD_B0"), + STM32_FUNCTION(14, "DCMI_D3 PSSI_D3 DCMIPP_D3"), + STM32_FUNCTION(15, "ETH3_RGMII_RX_CTL ETH3_RMII_CRS_DV"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(3, "PA3"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOA3"), + STM32_FUNCTION(2, "LPTIM2_ETR"), + STM32_FUNCTION(3, "SPI7_MOSI"), + STM32_FUNCTION(6, "MDF1_CKI7"), + STM32_FUNCTION(7, "USART1_TX"), + STM32_FUNCTION(9, "I3C1_SCL"), + STM32_FUNCTION(10, "I2C7_SMBA"), + STM32_FUNCTION(11, "I2C1_SCL"), + STM32_FUNCTION(12, "LCD_B1"), + STM32_FUNCTION(14, "DCMI_D2 PSSI_D2 DCMIPP_D2"), + STM32_FUNCTION(15, "ETH3_RGMII_TX_CTL ETH3_RMII_TX_EN"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(4, "PA4"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOA4"), + STM32_FUNCTION(7, "USART2_TX"), + STM32_FUNCTION(8, "FDCAN2_TX"), + STM32_FUNCTION(9, "TIM2_CH1"), + STM32_FUNCTION(11, "LCD_R1"), + STM32_FUNCTION(14, "ETH1_PTP_AUX_TS"), + STM32_FUNCTION(15, "ETH3_PPS_OUT"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(5, "PA5"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOA5"), + STM32_FUNCTION(4, "SPI4_MOSI"), + STM32_FUNCTION(5, "SAI2_MCLK_B"), + STM32_FUNCTION(6, "SAI2_SD_B"), + STM32_FUNCTION(7, "USART2_RTS"), + STM32_FUNCTION(8, "FDCAN2_RX"), + STM32_FUNCTION(9, "TIM2_CH4"), + STM32_FUNCTION(11, "LCD_G0"), + STM32_FUNCTION(13, "FMC_A0"), + STM32_FUNCTION(14, "DCMI_D13 PSSI_D13 DCMIPP_D13"), + STM32_FUNCTION(15, "ETH3_RGMII_RX_CLK ETH3_RMII_REF_CLK"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(6, "PA6"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOA6"), + STM32_FUNCTION(4, "SPI4_SCK"), + STM32_FUNCTION(5, "SAI2_FS_B"), + STM32_FUNCTION(6, "MDF1_SDI6"), + STM32_FUNCTION(7, "USART2_CK"), + STM32_FUNCTION(8, "TIM13_CH1"), + STM32_FUNCTION(9, "TIM2_ETR"), + STM32_FUNCTION(11, "LCD_G4"), + STM32_FUNCTION(13, "FMC_NE1"), + STM32_FUNCTION(14, "DCMI_D12 PSSI_D12 DCMIPP_D12"), + STM32_FUNCTION(15, "ETH3_RGMII_TXD0 ETH3_RMII_TXD0"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(7, "PA7"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOA7"), + STM32_FUNCTION(3, "AUDIOCLK"), + STM32_FUNCTION(4, "SPI6_RDY"), + STM32_FUNCTION(5, "PCIE_CLKREQN"), + STM32_FUNCTION(6, "MDF1_CCK0"), + STM32_FUNCTION(7, "USART1_CTS"), + STM32_FUNCTION(8, "TIM4_ETR"), + STM32_FUNCTION(9, "I2C2_SMBA"), + STM32_FUNCTION(10, "I2C6_SMBA"), + STM32_FUNCTION(11, "LCD_B5"), + STM32_FUNCTION(12, "I2C3_SMBA"), + STM32_FUNCTION(13, "I2C4_SMBA"), + STM32_FUNCTION(14, "DCMI_D6 PSSI_D6 DCMIPP_D6"), + STM32_FUNCTION(15, "ETH3_RGMII_TXD1 ETH3_RMII_TXD1"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(8, "PA8"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOA8"), + STM32_FUNCTION(2, "LPTIM2_CH2"), + STM32_FUNCTION(3, "SPI7_NSS"), + STM32_FUNCTION(5, "SAI1_FS_B"), + STM32_FUNCTION(7, "USART1_CK"), + STM32_FUNCTION(9, "USART2_RX"), + STM32_FUNCTION(10, "I2C5_SCL"), + STM32_FUNCTION(13, "LCD_B2"), + STM32_FUNCTION(14, "DCMI_D4 PSSI_D4 DCMIPP_D4"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(9, "PA9"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOA9"), + STM32_FUNCTION(4, "SPI4_NSS"), + STM32_FUNCTION(5, "SAI2_SCK_B"), + STM32_FUNCTION(7, "USART2_CTS"), + STM32_FUNCTION(8, "LPTIM5_ETR"), + STM32_FUNCTION(9, "TIM2_CH3"), + STM32_FUNCTION(11, "ETH1_MDC"), + STM32_FUNCTION(13, "LCD_G7"), + STM32_FUNCTION(14, "PSSI_D14 DCMIPP_D14"), + STM32_FUNCTION(15, "ETH3_RGMII_RXD0 ETH3_RMII_RXD0"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(10, "PA10"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOA10"), + STM32_FUNCTION(4, "SPI4_MISO"), + STM32_FUNCTION(5, "SAI2_SD_B"), + STM32_FUNCTION(7, "USART2_RX"), + STM32_FUNCTION(8, "LPTIM5_IN1"), + STM32_FUNCTION(9, "TIM2_CH2"), + STM32_FUNCTION(11, "ETH1_MDIO"), + STM32_FUNCTION(13, "LCD_R6"), + STM32_FUNCTION(14, "PSSI_D15 DCMIPP_D15"), + STM32_FUNCTION(15, "ETH3_RGMII_RXD1 ETH3_RMII_RXD1"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(11, "PA11"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOA11"), + STM32_FUNCTION(2, "SPI8_SCK"), + STM32_FUNCTION(3, "LPTIM2_CH1"), + STM32_FUNCTION(5, "SAI4_SD_B"), + STM32_FUNCTION(6, "MDF1_SDI4"), + STM32_FUNCTION(11, "ETH1_MII_RX_DV ETH1_RGMII_RX_CTL ETH1_RMII_CRS_DV"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(12, "PA12"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOA12"), + STM32_FUNCTION(3, "SPI6_MOSI"), + STM32_FUNCTION(5, "SAI3_FS_A"), + STM32_FUNCTION(8, "TIM4_CH1"), + STM32_FUNCTION(9, "I2C4_SCL"), + STM32_FUNCTION(10, "I2C6_SCL"), + STM32_FUNCTION(11, "ETH1_PHY_INTN"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(13, "PA13"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOA13"), + STM32_FUNCTION(2, "SPI8_RDY"), + STM32_FUNCTION(3, "I2S3_MCK"), + STM32_FUNCTION(4, "LPTIM2_ETR"), + STM32_FUNCTION(6, "MDF1_CKI3"), + STM32_FUNCTION(7, "USART2_CTS"), + STM32_FUNCTION(10, "I2C7_SMBA"), + STM32_FUNCTION(11, "ETH1_MII_TX_EN ETH1_RGMII_TX_CTL ETH1_RMII_TX_EN"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(14, "PA14"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOA14"), + STM32_FUNCTION(2, "SPI8_NSS"), + STM32_FUNCTION(3, "LPTIM2_CH2"), + STM32_FUNCTION(5, "SAI4_FS_B"), + STM32_FUNCTION(6, "MDF1_CCK1"), + STM32_FUNCTION(11, "ETH1_MII_RX_CLK ETH1_RGMII_RX_CLK ETH1_RMII_REF_CLK"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(15, "PA15"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOA15"), + STM32_FUNCTION(3, "SPI3_MISO I2S3_SDI"), + STM32_FUNCTION(7, "USART2_RX"), + STM32_FUNCTION(10, "I2C7_SDA"), + STM32_FUNCTION(11, "ETH1_MII_TXD0 ETH1_RGMII_TXD0 ETH1_RMII_TXD0"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(16, "PB0"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOB0"), + STM32_FUNCTION(3, "SPI2_SCK I2S2_CK"), + STM32_FUNCTION(7, "USART1_CK"), + STM32_FUNCTION(8, "TIM16_CH1"), + STM32_FUNCTION(9, "TIM20_CH4N"), + STM32_FUNCTION(11, "OCTOSPIM_P2_IO0"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(17, "PB1"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOB1"), + STM32_FUNCTION(2, "SPI3_NSS I2S3_WS"), + STM32_FUNCTION(8, "TIM16_CH1N"), + STM32_FUNCTION(9, "TIM20_CH3N"), + STM32_FUNCTION(11, "OCTOSPIM_P2_IO1"), + STM32_FUNCTION(13, "FMC_NCE4"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(18, "PB2"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOB2"), + STM32_FUNCTION(3, "SPI2_MOSI I2S2_SDO"), + STM32_FUNCTION(6, "MDF1_CKI3"), + STM32_FUNCTION(7, "TIM17_BKIN"), + STM32_FUNCTION(8, "TIM16_BKIN"), + STM32_FUNCTION(9, "TIM20_CH2N"), + STM32_FUNCTION(11, "OCTOSPIM_P2_IO2"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(19, "PB3"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOB3"), + STM32_FUNCTION(3, "SPI2_NSS I2S2_WS"), + STM32_FUNCTION(6, "MDF1_SDI3"), + STM32_FUNCTION(9, "TIM20_CH3"), + STM32_FUNCTION(11, "OCTOSPIM_P2_IO3"), + STM32_FUNCTION(13, "FMC_NCE3"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(20, "PB4"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOB4"), + STM32_FUNCTION(3, "SPI2_RDY"), + STM32_FUNCTION(4, "UART4_CTS"), + STM32_FUNCTION(5, "SAI4_FS_B"), + STM32_FUNCTION(6, "MDF1_SDI4"), + STM32_FUNCTION(7, "TIM14_CH1"), + STM32_FUNCTION(9, "TIM20_CH2"), + STM32_FUNCTION(10, "I2C2_SDA"), + STM32_FUNCTION(11, "OCTOSPIM_P2_IO4"), + STM32_FUNCTION(14, "I3C2_SDA"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(21, "PB5"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOB5"), + STM32_FUNCTION(3, "I2S2_MCK"), + STM32_FUNCTION(4, "UART4_RTS"), + STM32_FUNCTION(5, "SAI4_SD_B"), + STM32_FUNCTION(6, "MDF1_CKI4"), + STM32_FUNCTION(9, "TIM20_CH1"), + STM32_FUNCTION(10, "I2C2_SCL"), + STM32_FUNCTION(11, "OCTOSPIM_P2_IO5"), + STM32_FUNCTION(13, "FMC_AD8 FMC_D8"), + STM32_FUNCTION(14, "I3C2_SCL"), + STM32_FUNCTION(15, "SDMMC3_D123DIR"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(22, "PB6"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOB6"), + STM32_FUNCTION(3, "SPI2_MISO I2S2_SDI"), + STM32_FUNCTION(4, "UART4_RX"), + STM32_FUNCTION(5, "SAI4_SCK_B"), + STM32_FUNCTION(9, "TIM20_CH1N"), + STM32_FUNCTION(11, "OCTOSPIM_P2_IO6"), + STM32_FUNCTION(13, "FMC_AD9 FMC_D9"), + STM32_FUNCTION(15, "SDMMC3_D0DIR"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(23, "PB7"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOB7"), + STM32_FUNCTION(2, "SPI3_SCK I2S3_CK"), + STM32_FUNCTION(4, "UART4_TX"), + STM32_FUNCTION(5, "SAI4_MCLK_B"), + STM32_FUNCTION(9, "TIM20_ETR"), + STM32_FUNCTION(10, "TIM12_CH1"), + STM32_FUNCTION(11, "OCTOSPIM_P2_IO7"), + STM32_FUNCTION(13, "FMC_AD10 FMC_D10"), + STM32_FUNCTION(15, "SDMMC3_CDIR"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(24, "PB8"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOB8"), + STM32_FUNCTION(2, "SPI3_MOSI I2S3_SDO"), + STM32_FUNCTION(5, "PCIE_CLKREQN"), + STM32_FUNCTION(7, "USART1_TX"), + STM32_FUNCTION(8, "TIM17_CH1"), + STM32_FUNCTION(9, "TIM20_CH4"), + STM32_FUNCTION(11, "OCTOSPIM_P2_NCS1"), + STM32_FUNCTION(13, "FMC_AD12 FMC_D12"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(25, "PB9"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOB9"), + STM32_FUNCTION(2, "SPI3_RDY"), + STM32_FUNCTION(7, "USART1_RTS"), + STM32_FUNCTION(8, "FDCAN1_TX"), + STM32_FUNCTION(9, "TIM20_BKIN"), + STM32_FUNCTION(10, "TIM10_CH1"), + STM32_FUNCTION(11, "OCTOSPIM_P2_DQS"), + STM32_FUNCTION(12, "OCTOSPIM_P2_NCS2"), + STM32_FUNCTION(13, "FMC_AD13 FMC_D13"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(26, "PB10"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOB10"), + STM32_FUNCTION(2, "SPI3_MISO I2S3_SDI"), + STM32_FUNCTION(7, "USART1_RX"), + STM32_FUNCTION(8, "TIM17_CH1N"), + STM32_FUNCTION(11, "OCTOSPIM_P2_CLK"), + STM32_FUNCTION(13, "FMC_AD15 FMC_D15"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(27, "PB11"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOB11"), + STM32_FUNCTION(2, "I2S3_MCK"), + STM32_FUNCTION(7, "USART1_CTS"), + STM32_FUNCTION(8, "FDCAN1_RX"), + STM32_FUNCTION(9, "TIM20_BKIN2"), + STM32_FUNCTION(10, "TIM12_CH2"), + STM32_FUNCTION(11, "OCTOSPIM_P2_NCLK"), + STM32_FUNCTION(12, "OCTOSPIM_P2_NCS2"), + STM32_FUNCTION(13, "FMC_AD14 FMC_D14"), + STM32_FUNCTION(14, "OCTOSPIM_P1_NCS2"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(28, "PB12"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOB12"), + STM32_FUNCTION(6, "UART8_CTS"), + STM32_FUNCTION(8, "TIM13_CH1"), + STM32_FUNCTION(10, "DSI_TE"), + STM32_FUNCTION(11, "SDMMC3_D2"), + STM32_FUNCTION(12, "FMC_NWAIT"), + STM32_FUNCTION(15, "DCMI_D12 PSSI_D12 DCMIPP_D12"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(29, "PB13"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOB13"), + STM32_FUNCTION(3, "SPI7_SCK"), + STM32_FUNCTION(5, "SAI1_SD_B"), + STM32_FUNCTION(6, "UART8_RX"), + STM32_FUNCTION(11, "SDMMC3_CK"), + STM32_FUNCTION(12, "FMC_AD5 FMC_D5"), + STM32_FUNCTION(13, "FMC_AD0 FMC_D0"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(30, "PB14"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOB14"), + STM32_FUNCTION(3, "SPI2_SCK I2S2_CK"), + STM32_FUNCTION(6, "MDF1_CKI7"), + STM32_FUNCTION(7, "UART9_RX"), + STM32_FUNCTION(10, "TIM4_CH2"), + STM32_FUNCTION(11, "SDMMC3_D0"), + STM32_FUNCTION(12, "FMC_AD7 FMC_D7"), + STM32_FUNCTION(13, "FMC_AD2 FMC_D2"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(31, "PB15"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOB15"), + STM32_FUNCTION(2, "LPTIM1_IN2"), + STM32_FUNCTION(3, "SPI5_SCK"), + STM32_FUNCTION(4, "UART8_RTS"), + STM32_FUNCTION(5, "SAI2_SD_B"), + STM32_FUNCTION(6, "UART5_RX"), + STM32_FUNCTION(8, "TIM3_CH2"), + STM32_FUNCTION(9, "TIM5_CH1"), + STM32_FUNCTION(11, "ETH1_PPS_OUT"), + STM32_FUNCTION(13, "FMC_A18"), + STM32_FUNCTION(14, "LCD_R4"), + STM32_FUNCTION(15, "DCMI_D8 PSSI_D8 DCMIPP_D8"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(32, "PC0"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOC0"), + STM32_FUNCTION(2, "LPTIM1_CH1"), + STM32_FUNCTION(4, "SPI6_SCK"), + STM32_FUNCTION(5, "SAI3_MCLK_B"), + STM32_FUNCTION(6, "USART6_TX"), + STM32_FUNCTION(10, "DCMI_D0 PSSI_D0 DCMIPP_D0"), + STM32_FUNCTION(11, "ETH2_MII_RX_CLK ETH2_RGMII_RX_CLK ETH2_RMII_REF_CLK"), + STM32_FUNCTION(12, "ETH1_MII_TX_CLK"), + STM32_FUNCTION(13, "ETH1_RGMII_GTX_CLK"), + STM32_FUNCTION(14, "LCD_G7"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(33, "PC1"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOC1"), + STM32_FUNCTION(3, "SPI3_MOSI I2S3_SDO"), + STM32_FUNCTION(7, "USART2_TX"), + STM32_FUNCTION(10, "I2C7_SCL"), + STM32_FUNCTION(11, "ETH1_MII_TXD1 ETH1_RGMII_TXD1 ETH1_RMII_TXD1"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(34, "PC2"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOC2"), + STM32_FUNCTION(2, "SPI8_MOSI"), + STM32_FUNCTION(3, "LPTIM2_IN1"), + STM32_FUNCTION(5, "SAI4_MCLK_B"), + STM32_FUNCTION(6, "MDF1_SDI3"), + STM32_FUNCTION(7, "USART2_RTS"), + STM32_FUNCTION(11, "ETH1_MII_RXD1 ETH1_RGMII_RXD1 ETH1_RMII_RXD1"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(35, "PC3"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOC3"), + STM32_FUNCTION(2, "LPTIM1_IN2"), + STM32_FUNCTION(3, "SPI3_NSS I2S3_WS"), + STM32_FUNCTION(4, "SPI6_RDY"), + STM32_FUNCTION(7, "USART6_RTS"), + STM32_FUNCTION(8, "FDCAN2_TX"), + STM32_FUNCTION(11, "ETH2_MII_RX_DV ETH2_RGMII_RX_CTL ETH2_RMII_CRS_DV"), + STM32_FUNCTION(12, "ETH1_MII_RX_ER"), + STM32_FUNCTION(14, "LCD_G6"), + STM32_FUNCTION(15, "DCMI_D3 PSSI_D3 DCMIPP_D3"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(36, "PC4"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOC4"), + STM32_FUNCTION(4, "SPI6_MISO"), + STM32_FUNCTION(5, "SAI3_FS_B"), + STM32_FUNCTION(11, "ETH2_MII_TX_EN ETH2_RGMII_TX_CTL ETH2_RMII_TX_EN"), + STM32_FUNCTION(13, "ETH1_RGMII_CLK125"), + STM32_FUNCTION(14, "LCD_R0"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(37, "PC5"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOC5"), + STM32_FUNCTION(3, "SPDIFRX1_IN1"), + STM32_FUNCTION(6, "MDF1_SDI1"), + STM32_FUNCTION(9, "TIM8_CH1N"), + STM32_FUNCTION(10, "I2C4_SDA"), + STM32_FUNCTION(11, "ETH2_MDIO"), + STM32_FUNCTION(12, "ETH1_MII_COL"), + STM32_FUNCTION(13, "FMC_A25"), + STM32_FUNCTION(14, "ETH1_PPS_OUT"), + STM32_FUNCTION(15, "LCD_DE"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(38, "PC6"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOC6"), + STM32_FUNCTION(2, "RTC_REFIN"), + STM32_FUNCTION(3, "SPDIFRX1_IN0"), + STM32_FUNCTION(6, "MDF1_CKI1"), + STM32_FUNCTION(9, "TIM8_CH1"), + STM32_FUNCTION(10, "I2C4_SCL"), + STM32_FUNCTION(11, "ETH2_MDC"), + STM32_FUNCTION(12, "ETH1_MII_CRS"), + STM32_FUNCTION(13, "FMC_A24"), + STM32_FUNCTION(14, "ETH1_PHY_INTN"), + STM32_FUNCTION(15, "LCD_CLK"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(39, "PC7"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOC7"), + STM32_FUNCTION(4, "SPI6_MOSI"), + STM32_FUNCTION(5, "SAI3_SD_B"), + STM32_FUNCTION(9, "TIM8_CH2N"), + STM32_FUNCTION(11, "ETH2_MII_TXD0 ETH2_RGMII_TXD0 ETH2_RMII_TXD0"), + STM32_FUNCTION(12, "ETH1_MII_TXD2 ETH1_RGMII_TXD2"), + STM32_FUNCTION(14, "LCD_B4"), + STM32_FUNCTION(15, "DCMI_D1 PSSI_D1 DCMIPP_D1"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(40, "PC8"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOC8"), + STM32_FUNCTION(2, "LPTIM1_ETR"), + STM32_FUNCTION(4, "SPI6_NSS"), + STM32_FUNCTION(5, "SAI3_SCK_B"), + STM32_FUNCTION(7, "USART6_CTS"), + STM32_FUNCTION(9, "TIM8_CH2"), + STM32_FUNCTION(11, "ETH2_MII_TXD1 ETH2_RGMII_TXD1 ETH2_RMII_TXD1"), + STM32_FUNCTION(12, "ETH1_MII_TXD3 ETH1_RGMII_TXD3"), + STM32_FUNCTION(14, "LCD_B3"), + STM32_FUNCTION(15, "DCMI_D2 PSSI_D2 DCMIPP_D2"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(41, "PC9"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOC9"), + STM32_FUNCTION(2, "MCO1"), + STM32_FUNCTION(3, "SPI3_MISO I2S3_SDI"), + STM32_FUNCTION(5, "SAI2_SCK_A"), + STM32_FUNCTION(8, "TIM13_CH1"), + STM32_FUNCTION(9, "TIM8_CH4N"), + STM32_FUNCTION(10, "USBH_HS_OVRCUR"), + STM32_FUNCTION(11, "ETH2_MII_TXD2 ETH2_RGMII_TXD2"), + STM32_FUNCTION(12, "USB3DR_OVRCUR"), + STM32_FUNCTION(13, "FMC_A22"), + STM32_FUNCTION(14, "LCD_G2"), + STM32_FUNCTION(15, "DCMI_D7 PSSI_D7 DCMIPP_D7"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(42, "PC10"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOC10"), + STM32_FUNCTION(3, "SPI3_MOSI I2S3_SDO"), + STM32_FUNCTION(8, "LPTIM4_ETR"), + STM32_FUNCTION(9, "TIM8_CH4"), + STM32_FUNCTION(10, "USBH_HS_VBUSEN"), + STM32_FUNCTION(11, "ETH2_MII_TXD3 ETH2_RGMII_TXD3"), + STM32_FUNCTION(12, "USB3DR_VBUSEN"), + STM32_FUNCTION(13, "FMC_A23"), + STM32_FUNCTION(14, "LCD_G3"), + STM32_FUNCTION(15, "DCMI_D6 PSSI_D6 DCMIPP_D6"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(43, "PC11"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOC11"), + STM32_FUNCTION(2, "LPTIM1_CH1"), + STM32_FUNCTION(3, "SPI5_NSS"), + STM32_FUNCTION(5, "SAI2_MCLK_A"), + STM32_FUNCTION(6, "UART5_RTS"), + STM32_FUNCTION(7, "USART3_RTS"), + STM32_FUNCTION(8, "TIM3_CH1"), + STM32_FUNCTION(9, "TIM5_ETR"), + STM32_FUNCTION(11, "ETH2_MII_RXD3 ETH2_RGMII_RXD3"), + STM32_FUNCTION(13, "FMC_NBL1"), + STM32_FUNCTION(14, "LCD_R2"), + STM32_FUNCTION(15, "DCMI_D10 PSSI_D10 DCMIPP_D10"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(44, "PC12"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOC12"), + STM32_FUNCTION(2, "LPTIM1_CH2"), + STM32_FUNCTION(4, "I3C3_SCL"), + STM32_FUNCTION(6, "MDF1_CKI2"), + STM32_FUNCTION(9, "TIM8_CH3"), + STM32_FUNCTION(10, "I2C3_SCL"), + STM32_FUNCTION(11, "ETH2_MII_RXD1 ETH2_RGMII_RXD1 ETH2_RMII_RXD1"), + STM32_FUNCTION(12, "ETH1_MII_RXD3 ETH1_RGMII_RXD3"), + STM32_FUNCTION(14, "LCD_G1"), + STM32_FUNCTION(15, "DCMI_D5 PSSI_D5 DCMIPP_D5"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(45, "PC13"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOC13"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(48, "PD0"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOD0"), + STM32_FUNCTION(1, "TRACECLK"), + STM32_FUNCTION(2, "HDP0"), + STM32_FUNCTION(3, "SPI7_RDY"), + STM32_FUNCTION(4, "SAI1_D2"), + STM32_FUNCTION(6, "SAI4_FS_A"), + STM32_FUNCTION(7, "UART7_RX"), + STM32_FUNCTION(8, "TIM15_CH2"), + STM32_FUNCTION(10, "SDVSEL1"), + STM32_FUNCTION(11, "OCTOSPIM_P1_CLK"), + STM32_FUNCTION(14, "DCMI_PIXCLK PSSI_PDCK DCMIPP_PIXCLK"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(49, "PD1"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOD1"), + STM32_FUNCTION(2, "HDP1"), + STM32_FUNCTION(3, "SPI1_MISO I2S1_SDI"), + STM32_FUNCTION(4, "SAI1_CK2"), + STM32_FUNCTION(6, "SAI4_SD_A"), + STM32_FUNCTION(7, "UART7_RTS"), + STM32_FUNCTION(8, "TIM15_CH1"), + STM32_FUNCTION(9, "TIM1_BKIN"), + STM32_FUNCTION(10, "FDCAN3_RX"), + STM32_FUNCTION(11, "OCTOSPIM_P1_NCLK"), + STM32_FUNCTION(12, "OCTOSPIM_P1_NCS2"), + STM32_FUNCTION(13, "OCTOSPIM_P2_NCS2"), + STM32_FUNCTION(14, "DCMI_HSYNC PSSI_DE DCMIPP_HSYNC"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(50, "PD2"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOD2"), + STM32_FUNCTION(2, "HDP2"), + STM32_FUNCTION(3, "SPI1_NSS I2S1_WS"), + STM32_FUNCTION(4, "SAI1_CK1"), + STM32_FUNCTION(6, "SAI4_SCK_A"), + STM32_FUNCTION(7, "UART7_CTS"), + STM32_FUNCTION(8, "TIM15_BKIN"), + STM32_FUNCTION(9, "TIM1_ETR"), + STM32_FUNCTION(10, "FDCAN3_TX"), + STM32_FUNCTION(11, "OCTOSPIM_P1_DQS"), + STM32_FUNCTION(12, "OCTOSPIM_P1_NCS2"), + STM32_FUNCTION(14, "DCMI_VSYNC PSSI_RDY DCMIPP_VSYNC"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(51, "PD3"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOD3"), + STM32_FUNCTION(2, "SAI1_MCLK_A"), + STM32_FUNCTION(3, "SPI2_SCK I2S2_CK"), + STM32_FUNCTION(4, "SAI1_D1"), + STM32_FUNCTION(6, "SAI4_MCLK_A"), + STM32_FUNCTION(7, "UART7_TX"), + STM32_FUNCTION(8, "TIM15_CH1N"), + STM32_FUNCTION(9, "TIM1_BKIN2"), + STM32_FUNCTION(10, "SDVSEL2"), + STM32_FUNCTION(11, "OCTOSPIM_P1_NCS1"), + STM32_FUNCTION(14, "PSSI_D15 DCMIPP_D15"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(52, "PD4"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOD4"), + STM32_FUNCTION(1, "TRACED0"), + STM32_FUNCTION(2, "SPI4_MISO"), + STM32_FUNCTION(3, "HDP3"), + STM32_FUNCTION(4, "SAI1_D3"), + STM32_FUNCTION(5, "SAI1_SD_B"), + STM32_FUNCTION(9, "TIM1_CH4N"), + STM32_FUNCTION(10, "TIM4_CH1"), + STM32_FUNCTION(11, "OCTOSPIM_P1_IO0"), + STM32_FUNCTION(14, "PSSI_D14 DCMIPP_D14"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(53, "PD5"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOD5"), + STM32_FUNCTION(1, "TRACED1"), + STM32_FUNCTION(2, "SPI4_NSS"), + STM32_FUNCTION(3, "HDP4"), + STM32_FUNCTION(4, "SAI1_D4"), + STM32_FUNCTION(5, "SAI1_FS_B"), + STM32_FUNCTION(9, "TIM1_CH3N"), + STM32_FUNCTION(10, "TIM4_CH2"), + STM32_FUNCTION(11, "OCTOSPIM_P1_IO1"), + STM32_FUNCTION(14, "DCMI_D13 PSSI_D13 DCMIPP_D13"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(54, "PD6"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOD6"), + STM32_FUNCTION(1, "TRACED2"), + STM32_FUNCTION(2, "SPI4_MOSI"), + STM32_FUNCTION(3, "HDP5"), + STM32_FUNCTION(5, "SAI1_SCK_B"), + STM32_FUNCTION(6, "MDF1_SDI2"), + STM32_FUNCTION(9, "TIM1_CH2N"), + STM32_FUNCTION(10, "TIM4_CH3"), + STM32_FUNCTION(11, "OCTOSPIM_P1_IO2"), + STM32_FUNCTION(14, "DCMI_D12 PSSI_D12 DCMIPP_D12"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(55, "PD7"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOD7"), + STM32_FUNCTION(1, "TRACED3"), + STM32_FUNCTION(2, "SPI4_SCK"), + STM32_FUNCTION(3, "SPI1_RDY"), + STM32_FUNCTION(5, "SAI1_MCLK_B"), + STM32_FUNCTION(6, "MDF1_CKI2"), + STM32_FUNCTION(9, "TIM1_CH1N"), + STM32_FUNCTION(10, "TIM4_CH4"), + STM32_FUNCTION(11, "OCTOSPIM_P1_IO3"), + STM32_FUNCTION(14, "DCMI_D11 PSSI_D11 DCMIPP_D11"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(56, "PD8"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOD8"), + STM32_FUNCTION(1, "TRACED4"), + STM32_FUNCTION(2, "SPI4_RDY"), + STM32_FUNCTION(3, "I2S1_MCK"), + STM32_FUNCTION(4, "SAI1_FS_A"), + STM32_FUNCTION(5, "UART4_CTS"), + STM32_FUNCTION(6, "MDF1_SDI1"), + STM32_FUNCTION(9, "TIM1_CH4"), + STM32_FUNCTION(10, "TIM4_ETR"), + STM32_FUNCTION(11, "OCTOSPIM_P1_IO4"), + STM32_FUNCTION(12, "SDMMC1_D7"), + STM32_FUNCTION(13, "SDMMC1_D123DIR"), + STM32_FUNCTION(14, "DCMI_D10 PSSI_D10 DCMIPP_D10"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(57, "PD9"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOD9"), + STM32_FUNCTION(1, "TRACED5"), + STM32_FUNCTION(2, "HDP6"), + STM32_FUNCTION(3, "SPI1_MOSI I2S1_SDO"), + STM32_FUNCTION(4, "SAI1_SD_A"), + STM32_FUNCTION(5, "UART4_RTS"), + STM32_FUNCTION(6, "MDF1_CKI1"), + STM32_FUNCTION(9, "TIM1_CH3"), + STM32_FUNCTION(11, "OCTOSPIM_P1_IO5"), + STM32_FUNCTION(12, "SDMMC1_D6"), + STM32_FUNCTION(13, "SDMMC1_D0DIR"), + STM32_FUNCTION(14, "DCMI_D9 PSSI_D9 DCMIPP_D9"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(58, "PD10"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOD10"), + STM32_FUNCTION(1, "TRACED6"), + STM32_FUNCTION(2, "HDP7"), + STM32_FUNCTION(4, "SAI1_SCK_A"), + STM32_FUNCTION(5, "UART4_RX"), + STM32_FUNCTION(6, "MDF1_SDI0"), + STM32_FUNCTION(7, "I2C4_SDA"), + STM32_FUNCTION(9, "TIM1_CH2"), + STM32_FUNCTION(10, "TIM14_CH1"), + STM32_FUNCTION(11, "OCTOSPIM_P1_IO6"), + STM32_FUNCTION(12, "SDMMC1_D5"), + STM32_FUNCTION(13, "SDMMC1_CDIR"), + STM32_FUNCTION(14, "DCMI_D8 PSSI_D8 DCMIPP_D8"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(59, "PD11"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOD11"), + STM32_FUNCTION(1, "TRACED7"), + STM32_FUNCTION(3, "SPI1_SCK I2S1_CK"), + STM32_FUNCTION(4, "SAI1_MCLK_A"), + STM32_FUNCTION(5, "UART4_TX"), + STM32_FUNCTION(6, "MDF1_CKI0"), + STM32_FUNCTION(7, "I2C4_SCL"), + STM32_FUNCTION(9, "TIM1_CH1"), + STM32_FUNCTION(10, "SDVSEL1"), + STM32_FUNCTION(11, "OCTOSPIM_P1_IO7"), + STM32_FUNCTION(12, "SDMMC1_D4"), + STM32_FUNCTION(13, "SDMMC1_CKIN"), + STM32_FUNCTION(14, "DCMI_D7 PSSI_D7 DCMIPP_D7"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(60, "PD12"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOD12"), + STM32_FUNCTION(2, "SPI7_MISO"), + STM32_FUNCTION(3, "SPI2_MISO I2S2_SDI"), + STM32_FUNCTION(4, "SPDIFRX1_IN2"), + STM32_FUNCTION(6, "UART8_RTS"), + STM32_FUNCTION(10, "TIM4_ETR"), + STM32_FUNCTION(11, "SDMMC3_CMD"), + STM32_FUNCTION(12, "FMC_AD6 FMC_D6"), + STM32_FUNCTION(13, "FMC_AD1 FMC_D1"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(61, "PD13"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOD13"), + STM32_FUNCTION(3, "SPI2_NSS I2S2_WS"), + STM32_FUNCTION(6, "MDF1_SDI7"), + STM32_FUNCTION(7, "UART9_TX"), + STM32_FUNCTION(10, "TIM4_CH4"), + STM32_FUNCTION(11, "SDMMC3_D1"), + STM32_FUNCTION(12, "FMC_AD11 FMC_D11"), + STM32_FUNCTION(13, "FMC_NWE"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(62, "PD14"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOD14"), + STM32_FUNCTION(3, "I2S1_MCK"), + STM32_FUNCTION(8, "FDCAN1_RX"), + STM32_FUNCTION(9, "TIM11_CH1"), + STM32_FUNCTION(11, "I2C7_SDA"), + STM32_FUNCTION(12, "FMC_AD4 FMC_D4"), + STM32_FUNCTION(13, "SDMMC3_D3"), + STM32_FUNCTION(14, "DCMI_D1 PSSI_D1 DCMIPP_D1"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(63, "PD15"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOD15"), + STM32_FUNCTION(2, "SPI1_RDY"), + STM32_FUNCTION(6, "DSI_TE"), + STM32_FUNCTION(7, "I2C5_SDA"), + STM32_FUNCTION(8, "FDCAN1_TX"), + STM32_FUNCTION(9, "TIM1_BKIN2"), + STM32_FUNCTION(10, "TIM5_ETR"), + STM32_FUNCTION(11, "I2C7_SCL"), + STM32_FUNCTION(12, "FMC_AD3 FMC_D3"), + STM32_FUNCTION(13, "SDMMC3_CKIN"), + STM32_FUNCTION(14, "DCMI_D0 PSSI_D0 DCMIPP_D0"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(64, "PE0"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOE0"), + STM32_FUNCTION(1, "TRACED2"), + STM32_FUNCTION(2, "LPTIM2_CH1"), + STM32_FUNCTION(3, "SPI1_SCK I2S1_CK"), + STM32_FUNCTION(4, "SPI3_RDY"), + STM32_FUNCTION(7, "USART3_CK"), + STM32_FUNCTION(11, "SDMMC1_D2"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(65, "PE1"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOE1"), + STM32_FUNCTION(1, "TRACED3"), + STM32_FUNCTION(2, "LPTIM2_CH2"), + STM32_FUNCTION(3, "I2S1_MCK"), + STM32_FUNCTION(4, "I2S3_MCK"), + STM32_FUNCTION(7, "USART3_RX"), + STM32_FUNCTION(11, "SDMMC1_D3"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(66, "PE2"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOE2"), + STM32_FUNCTION(2, "LPTIM2_ETR"), + STM32_FUNCTION(3, "SPI1_MISO I2S1_SDI"), + STM32_FUNCTION(4, "SPI3_MOSI I2S3_SDO"), + STM32_FUNCTION(5, "SAI1_SCK_B"), + STM32_FUNCTION(9, "TIM10_CH1"), + STM32_FUNCTION(11, "SDMMC1_CMD"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(67, "PE3"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOE3"), + STM32_FUNCTION(1, "TRACECLK"), + STM32_FUNCTION(3, "SPI1_RDY"), + STM32_FUNCTION(4, "SPI3_SCK I2S3_CK"), + STM32_FUNCTION(5, "SAI1_MCLK_B"), + STM32_FUNCTION(7, "USART3_TX"), + STM32_FUNCTION(9, "TIM11_CH1"), + STM32_FUNCTION(11, "SDMMC1_CK"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(68, "PE4"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOE4"), + STM32_FUNCTION(1, "TRACED0"), + STM32_FUNCTION(2, "LPTIM2_IN1"), + STM32_FUNCTION(3, "SPI1_MOSI I2S1_SDO"), + STM32_FUNCTION(4, "SPI3_MISO I2S3_SDI"), + STM32_FUNCTION(5, "SAI1_SD_B"), + STM32_FUNCTION(7, "USART3_CTS"), + STM32_FUNCTION(8, "FDCAN1_TX"), + STM32_FUNCTION(11, "SDMMC1_D0"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(69, "PE5"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOE5"), + STM32_FUNCTION(1, "TRACED1"), + STM32_FUNCTION(2, "LPTIM2_IN2"), + STM32_FUNCTION(3, "SPI1_NSS I2S1_WS"), + STM32_FUNCTION(4, "SPI3_NSS I2S3_WS"), + STM32_FUNCTION(5, "SAI1_FS_B"), + STM32_FUNCTION(7, "USART3_RTS"), + STM32_FUNCTION(8, "FDCAN1_RX"), + STM32_FUNCTION(11, "SDMMC1_D1"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(70, "PE6"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOE6"), + STM32_FUNCTION(2, "SPI4_RDY"), + STM32_FUNCTION(5, "SPDIFRX1_IN2"), + STM32_FUNCTION(7, "USART1_TX"), + STM32_FUNCTION(9, "TIM1_ETR"), + STM32_FUNCTION(12, "FMC_AD1 FMC_D1"), + STM32_FUNCTION(13, "SDMMC2_D6"), + STM32_FUNCTION(14, "SDMMC2_D0DIR"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(71, "PE7"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOE7"), + STM32_FUNCTION(4, "SAI4_D4"), + STM32_FUNCTION(5, "SPDIFRX1_IN3"), + STM32_FUNCTION(7, "USART1_RX"), + STM32_FUNCTION(9, "TIM1_CH4N"), + STM32_FUNCTION(11, "TIM14_CH1"), + STM32_FUNCTION(12, "FMC_AD2 FMC_D2"), + STM32_FUNCTION(13, "SDMMC2_D7"), + STM32_FUNCTION(14, "SDMMC2_D123DIR"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(72, "PE8"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOE8"), + STM32_FUNCTION(2, "SPI4_MOSI"), + STM32_FUNCTION(4, "SAI4_CK1"), + STM32_FUNCTION(5, "SAI4_MCLK_A"), + STM32_FUNCTION(6, "MDF1_CKI0"), + STM32_FUNCTION(9, "TIM1_CH1"), + STM32_FUNCTION(12, "FMC_A17 FMC_ALE"), + STM32_FUNCTION(13, "SDMMC2_D2"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(73, "PE9"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOE9"), + STM32_FUNCTION(2, "SPI4_MISO"), + STM32_FUNCTION(4, "SAI4_D2"), + STM32_FUNCTION(5, "SAI4_FS_A"), + STM32_FUNCTION(7, "USART1_CK"), + STM32_FUNCTION(9, "TIM1_CH4"), + STM32_FUNCTION(12, "FMC_AD0 FMC_D0"), + STM32_FUNCTION(13, "SDMMC2_D5"), + STM32_FUNCTION(14, "SDMMC2_CDIR"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(74, "PE10"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOE10"), + STM32_FUNCTION(2, "SPI4_SCK"), + STM32_FUNCTION(4, "SAI4_D1"), + STM32_FUNCTION(5, "SAI4_SD_A"), + STM32_FUNCTION(7, "USART1_CTS"), + STM32_FUNCTION(9, "TIM1_CH3"), + STM32_FUNCTION(11, "FMC_NE3"), + STM32_FUNCTION(12, "FMC_NCE2"), + STM32_FUNCTION(13, "SDMMC2_D4"), + STM32_FUNCTION(14, "SDMMC2_CKIN"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(75, "PE11"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOE11"), + STM32_FUNCTION(3, "SPI7_SCK"), + STM32_FUNCTION(4, "SAI4_D3"), + STM32_FUNCTION(5, "SAI1_FS_A"), + STM32_FUNCTION(8, "TIM15_CH2"), + STM32_FUNCTION(9, "TIM1_CH3N"), + STM32_FUNCTION(12, "FMC_A16 FMC_CLE"), + STM32_FUNCTION(13, "SDMMC2_D1"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(76, "PE12"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOE12"), + STM32_FUNCTION(2, "SPI4_NSS"), + STM32_FUNCTION(4, "SAI4_CK2"), + STM32_FUNCTION(5, "SAI4_SCK_A"), + STM32_FUNCTION(6, "MDF1_SDI0"), + STM32_FUNCTION(7, "USART1_RTS"), + STM32_FUNCTION(9, "TIM1_CH2"), + STM32_FUNCTION(11, "FMC_NE2"), + STM32_FUNCTION(12, "FMC_NCE1"), + STM32_FUNCTION(13, "SDMMC2_D3"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(77, "PE13"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOE13"), + STM32_FUNCTION(3, "SPI7_MISO"), + STM32_FUNCTION(5, "SAI1_SD_A"), + STM32_FUNCTION(8, "TIM15_CH1"), + STM32_FUNCTION(9, "TIM1_CH2N"), + STM32_FUNCTION(12, "FMC_RNB"), + STM32_FUNCTION(13, "SDMMC2_D0"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(78, "PE14"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOE14"), + STM32_FUNCTION(3, "SPI7_NSS"), + STM32_FUNCTION(5, "SAI1_MCLK_A"), + STM32_FUNCTION(6, "MDF1_CKI6"), + STM32_FUNCTION(8, "TIM15_BKIN"), + STM32_FUNCTION(9, "TIM1_BKIN"), + STM32_FUNCTION(12, "FMC_NWE"), + STM32_FUNCTION(13, "SDMMC2_CK"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(79, "PE15"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOE15"), + STM32_FUNCTION(3, "SPI7_MOSI"), + STM32_FUNCTION(5, "SAI1_SCK_A"), + STM32_FUNCTION(6, "MDF1_SDI6"), + STM32_FUNCTION(8, "TIM15_CH1N"), + STM32_FUNCTION(9, "TIM1_CH1N"), + STM32_FUNCTION(12, "FMC_NOE"), + STM32_FUNCTION(13, "SDMMC2_CMD"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(80, "PF0"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOF0"), + STM32_FUNCTION(3, "SPI3_SCK I2S3_CK"), + STM32_FUNCTION(8, "FDCAN2_RX"), + STM32_FUNCTION(9, "TIM12_CH2"), + STM32_FUNCTION(10, "I2C2_SDA"), + STM32_FUNCTION(11, "ETH1_MDC"), + STM32_FUNCTION(12, "ETH2_MII_CRS"), + STM32_FUNCTION(14, "I3C2_SDA"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(81, "PF1"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOF1"), + STM32_FUNCTION(2, "SPI8_MISO"), + STM32_FUNCTION(3, "LPTIM2_IN2"), + STM32_FUNCTION(5, "SAI4_SCK_B"), + STM32_FUNCTION(6, "MDF1_CKI4"), + STM32_FUNCTION(7, "USART2_CK"), + STM32_FUNCTION(11, "ETH1_MII_RXD0 ETH1_RGMII_RXD0 ETH1_RMII_RXD0"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(82, "PF2"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOF2"), + STM32_FUNCTION(3, "SPI3_RDY"), + STM32_FUNCTION(7, "I2C4_SMBA"), + STM32_FUNCTION(9, "TIM12_CH1"), + STM32_FUNCTION(10, "I2C2_SCL"), + STM32_FUNCTION(11, "ETH1_MDIO"), + STM32_FUNCTION(12, "ETH2_MII_COL"), + STM32_FUNCTION(13, "FMC_NE4"), + STM32_FUNCTION(14, "I3C2_SCL"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(83, "PF3"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOF3"), + STM32_FUNCTION(4, "UART8_RX"), + STM32_FUNCTION(5, "SAI2_SCK_B"), + STM32_FUNCTION(6, "MDF1_CCK0"), + STM32_FUNCTION(8, "TIM3_CH4"), + STM32_FUNCTION(9, "TIM8_BKIN2"), + STM32_FUNCTION(10, "ETH1_CLK"), + STM32_FUNCTION(11, "ETH2_PPS_OUT"), + STM32_FUNCTION(13, "FMC_A20"), + STM32_FUNCTION(14, "LCD_R6"), + STM32_FUNCTION(15, "DCMI_HSYNC PSSI_DE DCMIPP_HSYNC"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(84, "PF4"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOF4"), + STM32_FUNCTION(2, "RTC_OUT2"), + STM32_FUNCTION(3, "SPI6_NSS"), + STM32_FUNCTION(5, "SAI3_SCK_A"), + STM32_FUNCTION(7, "USART6_RX"), + STM32_FUNCTION(8, "TIM4_CH4"), + STM32_FUNCTION(9, "ETH1_MDC"), + STM32_FUNCTION(10, "ETH2_CLK"), + STM32_FUNCTION(11, "ETH2_PPS_OUT"), + STM32_FUNCTION(12, "ETH1_PPS_OUT"), + STM32_FUNCTION(14, "LCD_B7"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(85, "PF5"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOF5"), + STM32_FUNCTION(3, "SPI6_SCK"), + STM32_FUNCTION(5, "SAI3_MCLK_A"), + STM32_FUNCTION(7, "USART6_TX"), + STM32_FUNCTION(8, "TIM4_CH3"), + STM32_FUNCTION(9, "ETH1_MDIO"), + STM32_FUNCTION(10, "ETH1_CLK"), + STM32_FUNCTION(11, "ETH2_PHY_INTN"), + STM32_FUNCTION(12, "ETH1_PHY_INTN"), + STM32_FUNCTION(14, "LCD_B6"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(86, "PF6"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOF6"), + STM32_FUNCTION(2, "RTC_OUT2"), + STM32_FUNCTION(4, "SAI3_MCLK_B"), + STM32_FUNCTION(7, "USART6_CK"), + STM32_FUNCTION(8, "TIM12_CH1"), + STM32_FUNCTION(10, "I2C3_SMBA"), + STM32_FUNCTION(11, "ETH2_MII_RX_CLK ETH2_RGMII_RX_CLK ETH2_RMII_REF_CLK"), + STM32_FUNCTION(14, "LCD_B0"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(87, "PF7"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOF7"), + STM32_FUNCTION(3, "SPDIFRX1_IN1"), + STM32_FUNCTION(4, "SPI6_SCK"), + STM32_FUNCTION(5, "SAI3_SD_A"), + STM32_FUNCTION(8, "TIM2_ETR"), + STM32_FUNCTION(11, "ETH2_RGMII_GTX_CLK"), + STM32_FUNCTION(12, "ETH2_MII_TX_CLK"), + STM32_FUNCTION(14, "LCD_R1"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(88, "PF8"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOF8"), + STM32_FUNCTION(2, "RTC_REFIN"), + STM32_FUNCTION(4, "SAI3_SCK_B"), + STM32_FUNCTION(7, "USART3_RX"), + STM32_FUNCTION(8, "TIM12_CH2"), + STM32_FUNCTION(10, "ETH1_CLK"), + STM32_FUNCTION(11, "ETH2_RGMII_CLK125"), + STM32_FUNCTION(12, "ETH2_MII_RX_ER"), + STM32_FUNCTION(13, "ETH2_MII_RX_DV ETH2_RGMII_RX_CTL ETH2_RMII_CRS_DV"), + STM32_FUNCTION(14, "LCD_G0"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(89, "PF9"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOF9"), + STM32_FUNCTION(4, "SAI3_SD_B"), + STM32_FUNCTION(5, "SAI2_SD_A"), + STM32_FUNCTION(6, "MDF1_SDI5"), + STM32_FUNCTION(7, "UART8_RTS"), + STM32_FUNCTION(8, "TIM2_CH2"), + STM32_FUNCTION(11, "ETH2_MII_RXD2 ETH2_RGMII_RXD2"), + STM32_FUNCTION(12, "ETH2_MDIO"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(90, "PF10"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOF10"), + STM32_FUNCTION(2, "MCO2"), + STM32_FUNCTION(3, "SPI3_RDY"), + STM32_FUNCTION(5, "SAI2_MCLK_A"), + STM32_FUNCTION(6, "MDF1_CKI6"), + STM32_FUNCTION(7, "UART8_TX"), + STM32_FUNCTION(8, "TIM2_CH3"), + STM32_FUNCTION(11, "ETH2_MII_TXD2 ETH2_RGMII_TXD2"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(91, "PF11"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOF11"), + STM32_FUNCTION(2, "MCO1"), + STM32_FUNCTION(3, "SPDIFRX1_IN0"), + STM32_FUNCTION(4, "SPI6_RDY"), + STM32_FUNCTION(5, "SAI2_SCK_A"), + STM32_FUNCTION(6, "MDF1_SDI6"), + STM32_FUNCTION(7, "UART8_RX"), + STM32_FUNCTION(8, "TIM2_CH4"), + STM32_FUNCTION(11, "ETH2_MII_TXD3 ETH2_RGMII_TXD3"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(92, "PF12"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOF12"), + STM32_FUNCTION(1, "TRACECLK"), + STM32_FUNCTION(3, "SPI5_MISO"), + STM32_FUNCTION(4, "SPI1_MISO I2S1_SDI"), + STM32_FUNCTION(7, "UART9_RTS"), + STM32_FUNCTION(9, "TIM5_CH1"), + STM32_FUNCTION(14, "LCD_CLK"), + STM32_FUNCTION(15, "DCMI_D0 PSSI_D0 DCMIPP_D0"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(93, "PF13"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOF13"), + STM32_FUNCTION(1, "TRACED0"), + STM32_FUNCTION(2, "HDP0"), + STM32_FUNCTION(3, "AUDIOCLK"), + STM32_FUNCTION(4, "USART6_TX"), + STM32_FUNCTION(5, "SPI2_NSS I2S2_WS"), + STM32_FUNCTION(6, "MDF1_CKI7"), + STM32_FUNCTION(7, "USART3_CTS"), + STM32_FUNCTION(8, "FDCAN3_TX"), + STM32_FUNCTION(9, "TIM3_CH3"), + STM32_FUNCTION(14, "LCD_R2"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(94, "PF14"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOF14"), + STM32_FUNCTION(1, "TRACED1"), + STM32_FUNCTION(2, "HDP1"), + STM32_FUNCTION(4, "USART6_RX"), + STM32_FUNCTION(6, "MDF1_SDI7"), + STM32_FUNCTION(7, "USART3_RTS"), + STM32_FUNCTION(8, "FDCAN3_RX"), + STM32_FUNCTION(9, "TIM3_CH4"), + STM32_FUNCTION(14, "LCD_R3"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(95, "PF15"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOF15"), + STM32_FUNCTION(1, "TRACED2"), + STM32_FUNCTION(2, "HDP2"), + STM32_FUNCTION(3, "SPI2_RDY"), + STM32_FUNCTION(4, "USART6_CTS"), + STM32_FUNCTION(5, "SPI2_SCK I2S2_CK"), + STM32_FUNCTION(7, "USART3_CK"), + STM32_FUNCTION(8, "TIM2_CH2"), + STM32_FUNCTION(9, "TIM3_ETR"), + STM32_FUNCTION(10, "I2C6_SMBA"), + STM32_FUNCTION(14, "LCD_R4"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(96, "PG0"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOG0"), + STM32_FUNCTION(2, "LPTIM1_IN1"), + STM32_FUNCTION(4, "I3C3_SDA"), + STM32_FUNCTION(6, "MDF1_SDI2"), + STM32_FUNCTION(9, "TIM8_CH3N"), + STM32_FUNCTION(10, "I2C3_SDA"), + STM32_FUNCTION(11, "ETH2_MII_RXD0 ETH2_RGMII_RXD0 ETH2_RMII_RXD0"), + STM32_FUNCTION(12, "ETH1_MII_RXD2 ETH1_RGMII_RXD2"), + STM32_FUNCTION(14, "LCD_G5"), + STM32_FUNCTION(15, "DCMI_D4 PSSI_D4 DCMIPP_D4"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(97, "PG1"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOG1"), + STM32_FUNCTION(2, "LPTIM1_IN1"), + STM32_FUNCTION(3, "I2S3_MCK"), + STM32_FUNCTION(4, "I3C3_SCL"), + STM32_FUNCTION(5, "SAI2_SD_A"), + STM32_FUNCTION(6, "UART5_CTS"), + STM32_FUNCTION(7, "USART3_CTS"), + STM32_FUNCTION(9, "TIM5_CH4"), + STM32_FUNCTION(10, "I2C3_SCL"), + STM32_FUNCTION(11, "ETH2_MII_RX_ER"), + STM32_FUNCTION(12, "ETH2_MII_RXD3 ETH2_RGMII_RXD3"), + STM32_FUNCTION(13, "FMC_NBL0"), + STM32_FUNCTION(14, "LCD_VSYNC"), + STM32_FUNCTION(15, "DCMI_D11 PSSI_D11 DCMIPP_D11"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(98, "PG2"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOG2"), + STM32_FUNCTION(2, "RTC_REFIN"), + STM32_FUNCTION(3, "I2S3_MCK"), + STM32_FUNCTION(4, "I3C3_SDA"), + STM32_FUNCTION(5, "SAI2_FS_A"), + STM32_FUNCTION(7, "USART3_CK"), + STM32_FUNCTION(9, "TIM5_CH3"), + STM32_FUNCTION(10, "I2C3_SDA"), + STM32_FUNCTION(11, "ETH2_MII_TX_CLK"), + STM32_FUNCTION(12, "ETH2_RGMII_CLK125"), + STM32_FUNCTION(13, "FMC_CLK"), + STM32_FUNCTION(14, "LCD_HSYNC"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(99, "PG3"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOG3"), + STM32_FUNCTION(2, "LPTIM1_ETR"), + STM32_FUNCTION(3, "SPI5_MOSI"), + STM32_FUNCTION(4, "UART8_TX"), + STM32_FUNCTION(5, "SAI2_FS_B"), + STM32_FUNCTION(8, "TIM3_CH3"), + STM32_FUNCTION(9, "TIM8_ETR"), + STM32_FUNCTION(10, "ETH2_CLK"), + STM32_FUNCTION(11, "ETH2_PHY_INTN"), + STM32_FUNCTION(13, "FMC_A19"), + STM32_FUNCTION(14, "LCD_R5"), + STM32_FUNCTION(15, "DCMI_PIXCLK PSSI_PDCK DCMIPP_PIXCLK"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(100, "PG4"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOG4"), + STM32_FUNCTION(3, "SPI5_MISO"), + STM32_FUNCTION(4, "SAI3_FS_B"), + STM32_FUNCTION(8, "LPTIM4_IN1"), + STM32_FUNCTION(9, "TIM8_BKIN"), + STM32_FUNCTION(11, "ETH2_PPS_OUT"), + STM32_FUNCTION(12, "ETH2_MDC"), + STM32_FUNCTION(13, "FMC_A21"), + STM32_FUNCTION(14, "LCD_R7"), + STM32_FUNCTION(15, "DCMI_VSYNC PSSI_RDY DCMIPP_VSYNC"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(101, "PG5"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOG5"), + STM32_FUNCTION(1, "TRACED3"), + STM32_FUNCTION(2, "HDP3"), + STM32_FUNCTION(4, "USART6_RTS"), + STM32_FUNCTION(8, "TIM2_CH3"), + STM32_FUNCTION(10, "I2C6_SDA"), + STM32_FUNCTION(14, "LCD_R5"), + STM32_FUNCTION(15, "DCMI_PIXCLK PSSI_PDCK DCMIPP_PIXCLK"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(102, "PG6"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOG6"), + STM32_FUNCTION(1, "TRACED4"), + STM32_FUNCTION(2, "HDP4"), + STM32_FUNCTION(3, "SPI5_SCK"), + STM32_FUNCTION(4, "SPI1_SCK I2S1_CK"), + STM32_FUNCTION(8, "TIM2_CH4"), + STM32_FUNCTION(10, "I2C6_SCL"), + STM32_FUNCTION(14, "LCD_R6"), + STM32_FUNCTION(15, "DCMI_HSYNC PSSI_DE DCMIPP_HSYNC"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(103, "PG7"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOG7"), + STM32_FUNCTION(1, "TRACED5"), + STM32_FUNCTION(2, "HDP5"), + STM32_FUNCTION(3, "SPI5_NSS"), + STM32_FUNCTION(4, "SPI1_NSS I2S1_WS"), + STM32_FUNCTION(7, "UART9_CTS"), + STM32_FUNCTION(9, "TIM5_ETR"), + STM32_FUNCTION(14, "LCD_R7"), + STM32_FUNCTION(15, "DCMI_VSYNC PSSI_RDY DCMIPP_VSYNC"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(104, "PG8"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOG8"), + STM32_FUNCTION(1, "TRACED6"), + STM32_FUNCTION(2, "HDP6"), + STM32_FUNCTION(3, "SPI5_RDY"), + STM32_FUNCTION(4, "SPI1_RDY"), + STM32_FUNCTION(5, "USART6_CK"), + STM32_FUNCTION(6, "UART5_RTS"), + STM32_FUNCTION(7, "UART9_TX"), + STM32_FUNCTION(9, "TIM5_CH3"), + STM32_FUNCTION(14, "LCD_G2"), + STM32_FUNCTION(15, "DCMI_D2 PSSI_D2 DCMIPP_D2"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(105, "PG9"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOG9"), + STM32_FUNCTION(1, "TRACED7"), + STM32_FUNCTION(6, "UART5_TX"), + STM32_FUNCTION(9, "TIM5_CH4"), + STM32_FUNCTION(14, "LCD_G3"), + STM32_FUNCTION(15, "DCMI_D3 PSSI_D3 DCMIPP_D3"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(106, "PG10"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOG10"), + STM32_FUNCTION(1, "TRACED8"), + STM32_FUNCTION(2, "HDP0"), + STM32_FUNCTION(6, "UART5_RX"), + STM32_FUNCTION(9, "TIM8_CH4N"), + STM32_FUNCTION(14, "LCD_G4"), + STM32_FUNCTION(15, "DCMI_D4 PSSI_D4 DCMIPP_D4"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(107, "PG11"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOG11"), + STM32_FUNCTION(1, "TRACED9"), + STM32_FUNCTION(2, "HDP1"), + STM32_FUNCTION(3, "SPI7_MOSI"), + STM32_FUNCTION(8, "FDCAN1_TX"), + STM32_FUNCTION(9, "TIM8_CH4"), + STM32_FUNCTION(14, "LCD_G5"), + STM32_FUNCTION(15, "DCMI_D5 PSSI_D5 DCMIPP_D5"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(108, "PG12"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOG12"), + STM32_FUNCTION(1, "TRACED10"), + STM32_FUNCTION(2, "HDP2"), + STM32_FUNCTION(3, "SPI7_MISO"), + STM32_FUNCTION(8, "FDCAN1_RX"), + STM32_FUNCTION(9, "TIM8_CH1N"), + STM32_FUNCTION(14, "LCD_G6"), + STM32_FUNCTION(15, "DCMI_D6 PSSI_D6 DCMIPP_D6"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(109, "PG13"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOG13"), + STM32_FUNCTION(1, "TRACED11"), + STM32_FUNCTION(2, "HDP3"), + STM32_FUNCTION(3, "SPI7_SCK"), + STM32_FUNCTION(6, "MDF1_CKI6"), + STM32_FUNCTION(9, "TIM8_CH2N"), + STM32_FUNCTION(10, "I2C1_SCL"), + STM32_FUNCTION(11, "I3C1_SCL"), + STM32_FUNCTION(14, "LCD_G7"), + STM32_FUNCTION(15, "DCMI_D7 PSSI_D7 DCMIPP_D7"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(110, "PG14"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOG14"), + STM32_FUNCTION(1, "TRACED12"), + STM32_FUNCTION(2, "HDP4"), + STM32_FUNCTION(3, "SPI7_RDY"), + STM32_FUNCTION(6, "MDF1_CKI5"), + STM32_FUNCTION(7, "USART1_TX"), + STM32_FUNCTION(9, "TIM8_BKIN2"), + STM32_FUNCTION(14, "LCD_B1"), + STM32_FUNCTION(15, "DCMI_D9 PSSI_D9 DCMIPP_D9"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(111, "PG15"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOG15"), + STM32_FUNCTION(1, "TRACED13"), + STM32_FUNCTION(2, "HDP5"), + STM32_FUNCTION(4, "LPTIM1_CH2"), + STM32_FUNCTION(6, "MDF1_SDI5"), + STM32_FUNCTION(7, "USART1_RX"), + STM32_FUNCTION(9, "TIM8_ETR"), + STM32_FUNCTION(14, "LCD_B2"), + STM32_FUNCTION(15, "DCMI_D10 PSSI_D10 DCMIPP_D10"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(114, "PH2"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOH2"), + STM32_FUNCTION(2, "LPTIM2_CH1"), + STM32_FUNCTION(3, "SPI7_RDY"), + STM32_FUNCTION(4, "SPDIFRX1_IN3"), + STM32_FUNCTION(5, "SAI1_SCK_B"), + STM32_FUNCTION(6, "I3C3_SDA"), + STM32_FUNCTION(8, "TIM16_CH1"), + STM32_FUNCTION(9, "I2C5_SDA"), + STM32_FUNCTION(10, "I2C3_SDA"), + STM32_FUNCTION(15, "ETH3_RGMII_GTX_CLK"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(115, "PH3"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOH3"), + STM32_FUNCTION(3, "SPI1_NSS I2S1_WS"), + STM32_FUNCTION(7, "UART7_RX"), + STM32_FUNCTION(8, "TIM17_CH1N"), + STM32_FUNCTION(10, "TIM5_CH3"), + STM32_FUNCTION(11, "I2C7_SCL"), + STM32_FUNCTION(15, "ETH3_RGMII_TXD3"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(116, "PH4"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOH4"), + STM32_FUNCTION(7, "UART7_TX"), + STM32_FUNCTION(8, "TIM17_BKIN"), + STM32_FUNCTION(10, "TIM5_CH2"), + STM32_FUNCTION(11, "LCD_R0"), + STM32_FUNCTION(12, "USB3DR_OVRCUR"), + STM32_FUNCTION(13, "USBH_HS_OVRCUR"), + STM32_FUNCTION(14, "ETH1_PTP_AUX_TS"), + STM32_FUNCTION(15, "ETH3_PPS_OUT"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(117, "PH5"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOH5"), + STM32_FUNCTION(5, "SAI2_FS_A"), + STM32_FUNCTION(7, "UART8_CTS"), + STM32_FUNCTION(8, "TIM2_CH1"), + STM32_FUNCTION(9, "UART7_RX"), + STM32_FUNCTION(11, "LCD_G1"), + STM32_FUNCTION(12, "USB3DR_VBUSEN"), + STM32_FUNCTION(13, "USBH_HS_VBUSEN"), + STM32_FUNCTION(14, "ETH2_PTP_AUX_TS"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(118, "PH6"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOH6"), + STM32_FUNCTION(2, "LPTIM2_IN2"), + STM32_FUNCTION(5, "SAI1_MCLK_B"), + STM32_FUNCTION(6, "I3C3_SCL"), + STM32_FUNCTION(8, "TIM16_CH1N"), + STM32_FUNCTION(9, "I2C5_SCL"), + STM32_FUNCTION(10, "I2C3_SCL"), + STM32_FUNCTION(11, "I2C1_SMBA"), + STM32_FUNCTION(15, "ETH3_RGMII_TXD2"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(119, "PH7"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOH7"), + STM32_FUNCTION(3, "SPI1_MOSI I2S1_SDO"), + STM32_FUNCTION(5, "UART4_TX"), + STM32_FUNCTION(7, "UART7_RTS"), + STM32_FUNCTION(8, "TIM17_CH1"), + STM32_FUNCTION(10, "TIM5_CH4"), + STM32_FUNCTION(11, "I2C7_SDA"), + STM32_FUNCTION(15, "ETH3_RGMII_RXD2"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(120, "PH8"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOH8"), + STM32_FUNCTION(3, "SPI1_MISO I2S1_SDI"), + STM32_FUNCTION(4, "SPDIFRX1_IN3"), + STM32_FUNCTION(5, "UART4_RX"), + STM32_FUNCTION(7, "UART7_CTS"), + STM32_FUNCTION(10, "TIM5_CH1"), + STM32_FUNCTION(11, "I2C3_SMBA"), + STM32_FUNCTION(12, "I2C5_SMBA"), + STM32_FUNCTION(15, "ETH3_RGMII_RXD3"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(121, "PH9"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOH9"), + STM32_FUNCTION(4, "SPI6_NSS"), + STM32_FUNCTION(5, "SAI3_MCLK_A"), + STM32_FUNCTION(7, "USART6_RX"), + STM32_FUNCTION(8, "TIM15_CH1N"), + STM32_FUNCTION(11, "ETH1_RGMII_CLK125"), + STM32_FUNCTION(12, "ETH1_MII_RX_ER"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(122, "PH10"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOH10"), + STM32_FUNCTION(3, "SPI1_SCK I2S1_CK"), + STM32_FUNCTION(4, "SPI6_MOSI"), + STM32_FUNCTION(5, "SAI3_SCK_A"), + STM32_FUNCTION(8, "TIM15_CH1"), + STM32_FUNCTION(10, "ETH2_MDC"), + STM32_FUNCTION(11, "ETH1_MII_TXD2 ETH1_RGMII_TXD2"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(123, "PH11"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOH11"), + STM32_FUNCTION(4, "SPI6_MISO"), + STM32_FUNCTION(5, "SAI3_FS_A"), + STM32_FUNCTION(8, "TIM15_CH2"), + STM32_FUNCTION(10, "ETH2_MDIO"), + STM32_FUNCTION(11, "ETH1_MII_TXD3 ETH1_RGMII_TXD3"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(124, "PH12"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOH12"), + STM32_FUNCTION(3, "SPI3_NSS I2S3_WS"), + STM32_FUNCTION(4, "SPI6_MISO"), + STM32_FUNCTION(9, "TIM10_CH1"), + STM32_FUNCTION(11, "ETH1_MII_RXD2 ETH1_RGMII_RXD2"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(125, "PH13"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOH13"), + STM32_FUNCTION(3, "SPI3_SCK I2S3_CK"), + STM32_FUNCTION(4, "SPI6_MOSI"), + STM32_FUNCTION(8, "TIM15_BKIN"), + STM32_FUNCTION(9, "TIM11_CH1"), + STM32_FUNCTION(11, "ETH1_MII_RXD3 ETH1_RGMII_RXD3"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(128, "PI0"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOI0"), + STM32_FUNCTION(1, "TRACED14"), + STM32_FUNCTION(2, "HDP6"), + STM32_FUNCTION(4, "LPTIM1_IN1"), + STM32_FUNCTION(5, "SAI4_MCLK_B"), + STM32_FUNCTION(7, "USART1_CK"), + STM32_FUNCTION(9, "TIM8_BKIN"), + STM32_FUNCTION(14, "LCD_B3"), + STM32_FUNCTION(15, "DCMI_D11 PSSI_D11 DCMIPP_D11"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(129, "PI1"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOI1"), + STM32_FUNCTION(1, "TRACED15"), + STM32_FUNCTION(2, "HDP7"), + STM32_FUNCTION(3, "SPI7_NSS"), + STM32_FUNCTION(6, "MDF1_SDI6"), + STM32_FUNCTION(9, "TIM8_CH3N"), + STM32_FUNCTION(10, "I2C1_SDA"), + STM32_FUNCTION(11, "I3C1_SDA"), + STM32_FUNCTION(14, "LCD_B4"), + STM32_FUNCTION(15, "DCMI_D8 PSSI_D8 DCMIPP_D8"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(130, "PI2"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOI2"), + STM32_FUNCTION(4, "LPTIM1_ETR"), + STM32_FUNCTION(5, "SAI4_SCK_B"), + STM32_FUNCTION(7, "USART1_RTS"), + STM32_FUNCTION(9, "TIM8_CH1"), + STM32_FUNCTION(14, "LCD_B5"), + STM32_FUNCTION(15, "DCMI_D13 PSSI_D13 DCMIPP_D13"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(131, "PI3"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOI3"), + STM32_FUNCTION(4, "LPTIM1_IN2"), + STM32_FUNCTION(5, "SAI4_SD_B"), + STM32_FUNCTION(7, "USART1_CTS"), + STM32_FUNCTION(9, "TIM8_CH2"), + STM32_FUNCTION(14, "LCD_B6"), + STM32_FUNCTION(15, "PSSI_D14 DCMIPP_D14"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(132, "PI4"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOI4"), + STM32_FUNCTION(4, "LPTIM1_CH1"), + STM32_FUNCTION(5, "SAI4_FS_B"), + STM32_FUNCTION(9, "TIM8_CH3"), + STM32_FUNCTION(14, "LCD_B7"), + STM32_FUNCTION(15, "PSSI_D15 DCMIPP_D15"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(133, "PI5"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOI5"), + STM32_FUNCTION(3, "SPI5_MOSI"), + STM32_FUNCTION(4, "SPI1_MOSI I2S1_SDO"), + STM32_FUNCTION(6, "UART5_CTS"), + STM32_FUNCTION(7, "UART9_RX"), + STM32_FUNCTION(9, "TIM5_CH2"), + STM32_FUNCTION(14, "LCD_DE"), + STM32_FUNCTION(15, "DCMI_D1 PSSI_D1 DCMIPP_D1"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(134, "PI6"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOI6"), + STM32_FUNCTION(2, "MCO1"), + STM32_FUNCTION(7, "USART3_TX"), + STM32_FUNCTION(8, "TIM2_ETR"), + STM32_FUNCTION(9, "TIM3_CH1"), + STM32_FUNCTION(14, "LCD_VSYNC"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(135, "PI7"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOI7"), + STM32_FUNCTION(7, "USART3_RX"), + STM32_FUNCTION(8, "TIM2_CH1"), + STM32_FUNCTION(9, "TIM3_CH2"), + STM32_FUNCTION(14, "LCD_HSYNC"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(136, "PI8"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOI8"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(137, "PI9"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOI9"), + STM32_FUNCTION(2, "SPI7_MOSI"), + STM32_FUNCTION(3, "SPI2_MOSI I2S2_SDO"), + STM32_FUNCTION(5, "FDCAN2_TX"), + STM32_FUNCTION(7, "UART9_CTS"), + STM32_FUNCTION(9, "TIM16_BKIN"), + STM32_FUNCTION(10, "SDVSEL2"), + STM32_FUNCTION(11, "FMC_NWAIT"), + STM32_FUNCTION(13, "DSI_TE"), + STM32_FUNCTION(14, "LCD_B0"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(138, "PI10"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOI10"), + STM32_FUNCTION(2, "SAI1_SCK_A"), + STM32_FUNCTION(3, "SPI1_SCK I2S1_CK"), + STM32_FUNCTION(4, "SPDIFRX1_IN0"), + STM32_FUNCTION(5, "FDCAN2_RX"), + STM32_FUNCTION(6, "MDF1_CCK0"), + STM32_FUNCTION(9, "TIM4_CH1"), + STM32_FUNCTION(10, "SDVSEL1"), + STM32_FUNCTION(13, "FMC_AD12 FMC_D12"), + STM32_FUNCTION(14, "DSI_TE"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(139, "PI11"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOI11"), + STM32_FUNCTION(3, "I2S2_MCK"), + STM32_FUNCTION(6, "UART8_TX"), + STM32_FUNCTION(7, "UART9_RTS"), + STM32_FUNCTION(10, "TIM4_CH3"), + STM32_FUNCTION(11, "SDMMC3_D3"), + STM32_FUNCTION(12, "FMC_AD15 FMC_D15"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(140, "PI12"), + STM32MP_PKG_AI, + STM32_FUNCTION(0, "GPIOI12"), + STM32_FUNCTION(3, "SPI4_NSS"), + STM32_FUNCTION(8, "FDCAN3_RX"), + STM32_FUNCTION(9, "TIM11_CH1"), + STM32_FUNCTION(13, "FMC_A2"), + STM32_FUNCTION(14, "LCD_G0"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(141, "PI13"), + STM32MP_PKG_AI, + STM32_FUNCTION(0, "GPIOI13"), + STM32_FUNCTION(3, "SPI4_MOSI"), + STM32_FUNCTION(5, "FDCAN2_RX"), + STM32_FUNCTION(9, "TIM10_CH1"), + STM32_FUNCTION(13, "FMC_A3"), + STM32_FUNCTION(14, "LCD_G1"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(142, "PI14"), + STM32MP_PKG_AI, + STM32_FUNCTION(0, "GPIOI14"), + STM32_FUNCTION(3, "SPI2_NSS I2S2_WS"), + STM32_FUNCTION(6, "MDF1_SDI1"), + STM32_FUNCTION(8, "TIM20_CH3"), + STM32_FUNCTION(9, "TIM1_CH3N"), + STM32_FUNCTION(11, "FMC_NWAIT"), + STM32_FUNCTION(13, "FMC_AD10 FMC_D10"), + STM32_FUNCTION(14, "DCMI_D4 PSSI_D4 DCMIPP_D4"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(143, "PI15"), + STM32MP_PKG_AI, + STM32_FUNCTION(0, "GPIOI15"), + STM32_FUNCTION(3, "I2S2_MCK"), + STM32_FUNCTION(4, "UART4_RX"), + STM32_FUNCTION(6, "MDF1_CKI2"), + STM32_FUNCTION(8, "TIM20_BKIN2"), + STM32_FUNCTION(9, "TIM1_BKIN2"), + STM32_FUNCTION(10, "SDVSEL1"), + STM32_FUNCTION(11, "SDMMC3_CDIR"), + STM32_FUNCTION(14, "DCMI_D9 PSSI_D9 DCMIPP_D9"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(144, "PJ0"), + STM32MP_PKG_AI, + STM32_FUNCTION(0, "GPIOJ0"), + STM32_FUNCTION(3, "SPI5_MOSI"), + STM32_FUNCTION(5, "PCIE_CLKREQN"), + STM32_FUNCTION(6, "SAI4_D2"), + STM32_FUNCTION(7, "USART6_CTS"), + STM32_FUNCTION(10, "USBH_HS_VBUSEN"), + STM32_FUNCTION(12, "ETH2_PTP_AUX_TS"), + STM32_FUNCTION(13, "FMC_A11"), + STM32_FUNCTION(14, "ETH3_PPS_OUT"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(145, "PJ1"), + STM32MP_PKG_AI, + STM32_FUNCTION(0, "GPIOJ1"), + STM32_FUNCTION(7, "USART6_RX"), + STM32_FUNCTION(9, "TIM8_CH1N"), + STM32_FUNCTION(10, "I2C1_SCL"), + STM32_FUNCTION(11, "I3C1_SCL"), + STM32_FUNCTION(13, "FMC_A7"), + STM32_FUNCTION(15, "DCMI_VSYNC PSSI_RDY DCMIPP_VSYNC"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(146, "PJ2"), + STM32MP_PKG_AI, + STM32_FUNCTION(0, "GPIOJ2"), + STM32_FUNCTION(5, "SAI2_SD_B"), + STM32_FUNCTION(7, "UART9_RTS"), + STM32_FUNCTION(9, "TIM8_CH4N"), + STM32_FUNCTION(10, "USBH_HS_OVRCUR"), + STM32_FUNCTION(13, "FMC_A14"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(147, "PJ3"), + STM32MP_PKG_AI, + STM32_FUNCTION(0, "GPIOJ3"), + STM32_FUNCTION(3, "SPI5_NSS"), + STM32_FUNCTION(4, "SAI2_FS_A"), + STM32_FUNCTION(6, "SAI4_D1"), + STM32_FUNCTION(7, "USART6_RTS"), + STM32_FUNCTION(9, "TIM8_CH3"), + STM32_FUNCTION(13, "FMC_A10"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(148, "PJ4"), + STM32MP_PKG_AI, + STM32_FUNCTION(0, "GPIOJ4"), + STM32_FUNCTION(4, "SAI2_FS_B"), + STM32_FUNCTION(6, "MDF1_CCK1"), + STM32_FUNCTION(7, "USART6_CK"), + STM32_FUNCTION(9, "TIM8_CH4"), + STM32_FUNCTION(10, "I2C2_SMBA"), + STM32_FUNCTION(11, "I2C5_SMBA"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(149, "PJ5"), + STM32MP_PKG_AI, + STM32_FUNCTION(0, "GPIOJ5"), + STM32_FUNCTION(3, "SPI5_MISO"), + STM32_FUNCTION(4, "SAI2_SCK_B"), + STM32_FUNCTION(6, "SAI4_CK1"), + STM32_FUNCTION(7, "USART6_TX"), + STM32_FUNCTION(9, "TIM8_CH1"), + STM32_FUNCTION(13, "FMC_A8"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(150, "PJ6"), + STM32MP_PKG_AI, + STM32_FUNCTION(0, "GPIOJ6"), + STM32_FUNCTION(3, "SPI7_MOSI"), + STM32_FUNCTION(5, "SAI4_SD_A"), + STM32_FUNCTION(7, "USART2_CK"), + STM32_FUNCTION(8, "TIM20_CH1N"), + STM32_FUNCTION(9, "TIM1_CH1"), + STM32_FUNCTION(10, "I2C6_SMBA"), + STM32_FUNCTION(14, "DCMI_D7 PSSI_D7 DCMIPP_D7"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(151, "PJ7"), + STM32MP_PKG_AI, + STM32_FUNCTION(0, "GPIOJ7"), + STM32_FUNCTION(3, "SPI5_MISO"), + STM32_FUNCTION(5, "SAI2_MCLK_B"), + STM32_FUNCTION(6, "SAI4_D3"), + STM32_FUNCTION(7, "USART6_CK"), + STM32_FUNCTION(9, "TIM8_CH2N"), + STM32_FUNCTION(10, "I2C1_SMBA"), + STM32_FUNCTION(13, "FMC_A12"), + STM32_FUNCTION(15, "DCMI_D0 PSSI_D0 DCMIPP_D0"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(152, "PJ8"), + STM32MP_PKG_AI, + STM32_FUNCTION(0, "GPIOJ8"), + STM32_FUNCTION(3, "SPI5_SCK"), + STM32_FUNCTION(6, "SAI4_CK2"), + STM32_FUNCTION(7, "USART6_RX"), + STM32_FUNCTION(9, "TIM8_CH2"), + STM32_FUNCTION(13, "FMC_A9"), + STM32_FUNCTION(15, "PSSI_D14 DCMIPP_D14"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(153, "PJ9"), + STM32MP_PKG_AI, + STM32_FUNCTION(0, "GPIOJ9"), + STM32_FUNCTION(3, "SPI4_RDY"), + STM32_FUNCTION(8, "TIM12_CH1"), + STM32_FUNCTION(9, "TIM8_BKIN"), + STM32_FUNCTION(13, "FMC_A5"), + STM32_FUNCTION(15, "DCMI_PIXCLK PSSI_PDCK DCMIPP_PIXCLK"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(154, "PJ10"), + STM32MP_PKG_AI, + STM32_FUNCTION(0, "GPIOJ10"), + STM32_FUNCTION(8, "TIM12_CH2"), + STM32_FUNCTION(9, "TIM8_ETR"), + STM32_FUNCTION(10, "I2C1_SDA"), + STM32_FUNCTION(11, "I3C1_SDA"), + STM32_FUNCTION(13, "FMC_A6"), + STM32_FUNCTION(15, "DCMI_HSYNC PSSI_DE DCMIPP_HSYNC"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(155, "PJ11"), + STM32MP_PKG_AI, + STM32_FUNCTION(0, "GPIOJ11"), + STM32_FUNCTION(3, "SPI5_RDY"), + STM32_FUNCTION(4, "SAI2_SCK_A"), + STM32_FUNCTION(6, "SAI4_D4"), + STM32_FUNCTION(7, "UART9_CTS"), + STM32_FUNCTION(9, "TIM8_CH3N"), + STM32_FUNCTION(13, "FMC_A13"), + STM32_FUNCTION(15, "DCMI_D12 PSSI_D12 DCMIPP_D12"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(156, "PJ12"), + STM32MP_PKG_AI, + STM32_FUNCTION(0, "GPIOJ12"), + STM32_FUNCTION(4, "SAI2_SD_A"), + STM32_FUNCTION(7, "UART9_RX"), + STM32_FUNCTION(8, "FDCAN1_TX"), + STM32_FUNCTION(9, "TIM8_BKIN2"), + STM32_FUNCTION(10, "I2C2_SCL"), + STM32_FUNCTION(11, "I3C2_SCL"), + STM32_FUNCTION(13, "FMC_A15"), + STM32_FUNCTION(15, "DCMI_D13 PSSI_D13 DCMIPP_D13"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(157, "PJ13"), + STM32MP_PKG_AI, + STM32_FUNCTION(0, "GPIOJ13"), + STM32_FUNCTION(4, "SAI2_MCLK_A"), + STM32_FUNCTION(7, "UART9_TX"), + STM32_FUNCTION(8, "FDCAN1_RX"), + STM32_FUNCTION(9, "TIM10_CH1"), + STM32_FUNCTION(10, "I2C2_SDA"), + STM32_FUNCTION(11, "I3C2_SDA"), + STM32_FUNCTION(15, "PSSI_D15 DCMIPP_D15"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(158, "PJ14"), + STM32MP_PKG_AI, + STM32_FUNCTION(0, "GPIOJ14"), + STM32_FUNCTION(3, "SPI4_SCK"), + STM32_FUNCTION(8, "FDCAN3_TX"), + STM32_FUNCTION(13, "FMC_A1"), + STM32_FUNCTION(14, "LCD_R0"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(159, "PJ15"), + STM32MP_PKG_AI, + STM32_FUNCTION(0, "GPIOJ15"), + STM32_FUNCTION(1, "TRACED7"), + STM32_FUNCTION(2, "HDP7"), + STM32_FUNCTION(3, "SPI4_MISO"), + STM32_FUNCTION(5, "FDCAN2_TX"), + STM32_FUNCTION(9, "TIM11_CH1"), + STM32_FUNCTION(13, "FMC_A4"), + STM32_FUNCTION(14, "LCD_R1"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(160, "PK0"), + STM32MP_PKG_AI, + STM32_FUNCTION(0, "GPIOK0"), + STM32_FUNCTION(3, "SPI2_MISO I2S2_SDI"), + STM32_FUNCTION(4, "SPDIFRX1_IN2"), + STM32_FUNCTION(6, "MDF1_CCK0"), + STM32_FUNCTION(8, "TIM20_ETR"), + STM32_FUNCTION(9, "TIM1_ETR"), + STM32_FUNCTION(11, "SDMMC3_D123DIR"), + STM32_FUNCTION(13, "FMC_AD11 FMC_D11"), + STM32_FUNCTION(14, "DCMI_D11 PSSI_D11 DCMIPP_D11"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(161, "PK1"), + STM32MP_PKG_AI, + STM32_FUNCTION(0, "GPIOK1"), + STM32_FUNCTION(3, "SPI2_MOSI I2S2_SDO"), + STM32_FUNCTION(6, "MDF1_SDI2"), + STM32_FUNCTION(8, "TIM20_BKIN"), + STM32_FUNCTION(9, "TIM1_BKIN"), + STM32_FUNCTION(10, "SDVSEL2"), + STM32_FUNCTION(11, "SDMMC3_D0DIR"), + STM32_FUNCTION(13, "FMC_AD13 FMC_D13"), + STM32_FUNCTION(14, "DCMI_D10 PSSI_D10 DCMIPP_D10"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(162, "PK2"), + STM32MP_PKG_AI, + STM32_FUNCTION(0, "GPIOK2"), + STM32_FUNCTION(3, "SPI7_NSS"), + STM32_FUNCTION(5, "SAI4_SCK_A"), + STM32_FUNCTION(7, "USART1_RTS"), + STM32_FUNCTION(8, "TIM20_CH2"), + STM32_FUNCTION(9, "TIM1_CH2N"), + STM32_FUNCTION(10, "I2C6_SDA"), + STM32_FUNCTION(13, "FMC_NCE3"), + STM32_FUNCTION(14, "DCMI_D6 PSSI_D6 DCMIPP_D6"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(163, "PK3"), + STM32MP_PKG_AI, + STM32_FUNCTION(0, "GPIOK3"), + STM32_FUNCTION(3, "SPI7_RDY"), + STM32_FUNCTION(6, "MDF1_CKI1"), + STM32_FUNCTION(8, "TIM20_CH3N"), + STM32_FUNCTION(9, "TIM1_CH3"), + STM32_FUNCTION(13, "FMC_AD8 FMC_D8"), + STM32_FUNCTION(14, "DCMI_D3 PSSI_D3 DCMIPP_D3"), + STM32_FUNCTION(15, "FMC_NCE4"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(164, "PK4"), + STM32MP_PKG_AI, + STM32_FUNCTION(0, "GPIOK4"), + STM32_FUNCTION(3, "SPI7_MISO"), + STM32_FUNCTION(4, "UART4_TX"), + STM32_FUNCTION(5, "SAI4_FS_A"), + STM32_FUNCTION(8, "TIM20_CH1"), + STM32_FUNCTION(9, "TIM1_CH1N"), + STM32_FUNCTION(11, "SDMMC3_CKIN"), + STM32_FUNCTION(13, "FMC_AD9 FMC_D9"), + STM32_FUNCTION(14, "DCMI_D8 PSSI_D8 DCMIPP_D8"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(165, "PK5"), + STM32MP_PKG_AI, + STM32_FUNCTION(0, "GPIOK5"), + STM32_FUNCTION(3, "SPI2_RDY"), + STM32_FUNCTION(6, "MDF1_CKI0"), + STM32_FUNCTION(7, "USART1_TX"), + STM32_FUNCTION(8, "TIM20_CH4N"), + STM32_FUNCTION(9, "TIM1_CH4"), + STM32_FUNCTION(11, "I2C5_SCL"), + STM32_FUNCTION(13, "FMC_AD5 FMC_D5"), + STM32_FUNCTION(14, "DCMI_D1 PSSI_D1 DCMIPP_D1"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(166, "PK6"), + STM32MP_PKG_AI, + STM32_FUNCTION(0, "GPIOK6"), + STM32_FUNCTION(3, "SPI7_SCK"), + STM32_FUNCTION(5, "SAI4_MCLK_A"), + STM32_FUNCTION(7, "USART1_CTS"), + STM32_FUNCTION(8, "TIM20_CH2N"), + STM32_FUNCTION(9, "TIM1_CH2"), + STM32_FUNCTION(10, "I2C6_SCL"), + STM32_FUNCTION(12, "FMC_AD14 FMC_D14"), + STM32_FUNCTION(13, "FMC_AD7 FMC_D7"), + STM32_FUNCTION(14, "DCMI_D5 PSSI_D5 DCMIPP_D5"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(167, "PK7"), + STM32MP_PKG_AI, + STM32_FUNCTION(0, "GPIOK7"), + STM32_FUNCTION(6, "MDF1_SDI0"), + STM32_FUNCTION(7, "USART1_RX"), + STM32_FUNCTION(8, "TIM20_CH4"), + STM32_FUNCTION(9, "TIM1_CH4N"), + STM32_FUNCTION(11, "I2C5_SDA"), + STM32_FUNCTION(12, "FMC_NCE4"), + STM32_FUNCTION(13, "FMC_AD6 FMC_D6"), + STM32_FUNCTION(14, "DCMI_D2 PSSI_D2 DCMIPP_D2"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), +}; + +static const struct stm32_desc_pin stm32mp257_z_pins[] = { + STM32_PIN_PKG( + PINCTRL_PIN(400, "PZ0"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOZ0"), + STM32_FUNCTION(3, "LPTIM3_IN1"), + STM32_FUNCTION(4, "SPI8_MOSI"), + STM32_FUNCTION(5, "TIM8_CH1"), + STM32_FUNCTION(7, "LPUART1_TX"), + STM32_FUNCTION(8, "LPTIM5_OUT"), + STM32_FUNCTION(9, "I2C8_SDA"), + STM32_FUNCTION(11, "LPTIM3_CH2"), + STM32_FUNCTION(12, "I3C4_SDA"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(401, "PZ1"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOZ1"), + STM32_FUNCTION(3, "LPTIM3_CH1"), + STM32_FUNCTION(4, "SPI8_MISO"), + STM32_FUNCTION(5, "TIM8_CH2"), + STM32_FUNCTION(7, "LPUART1_RX"), + STM32_FUNCTION(8, "LPTIM5_ETR"), + STM32_FUNCTION(9, "I2C8_SCL"), + STM32_FUNCTION(10, "I2C8_SMBA"), + STM32_FUNCTION(12, "I3C4_SCL"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(402, "PZ2"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOZ2"), + STM32_FUNCTION(3, "LPTIM3_CH1"), + STM32_FUNCTION(4, "SPI8_SCK"), + STM32_FUNCTION(6, "ADF1_CCK0"), + STM32_FUNCTION(7, "LPUART1_RTS"), + STM32_FUNCTION(8, "LPTIM4_ETR"), + STM32_FUNCTION(9, "I2C8_SCL"), + STM32_FUNCTION(12, "I3C4_SCL"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(403, "PZ3"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOZ3"), + STM32_FUNCTION(1, "DBTRGI"), + STM32_FUNCTION(2, "DBTRGO"), + STM32_FUNCTION(3, "LPTIM3_ETR"), + STM32_FUNCTION(4, "SPI8_NSS"), + STM32_FUNCTION(5, "MDF1_SDI5"), + STM32_FUNCTION(6, "ADF1_SDI0"), + STM32_FUNCTION(7, "LPUART1_CTS"), + STM32_FUNCTION(8, "LPTIM4_IN1"), + STM32_FUNCTION(9, "I2C8_SDA"), + STM32_FUNCTION(11, "LPTIM4_CH2"), + STM32_FUNCTION(12, "I3C4_SDA"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(404, "PZ4"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOZ4"), + STM32_FUNCTION(1, "DBTRGI"), + STM32_FUNCTION(2, "DBTRGO"), + STM32_FUNCTION(3, "MCO2"), + STM32_FUNCTION(4, "SPI8_RDY"), + STM32_FUNCTION(5, "MDF1_CCK1"), + STM32_FUNCTION(6, "ADF1_CCK1"), + STM32_FUNCTION(7, "LPUART1_RX"), + STM32_FUNCTION(8, "LPTIM4_CH1"), + STM32_FUNCTION(9, "I2C8_SCL"), + STM32_FUNCTION(12, "I3C4_SCL"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(405, "PZ5"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOZ5"), + STM32_FUNCTION(2, "MCO1"), + STM32_FUNCTION(3, "LPTIM3_ETR"), + STM32_FUNCTION(4, "SPI8_SCK"), + STM32_FUNCTION(6, "ADF1_CCK0"), + STM32_FUNCTION(7, "LPUART1_RTS"), + STM32_FUNCTION(8, "LPTIM5_IN1"), + STM32_FUNCTION(11, "LPTIM4_CH2"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(406, "PZ6"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOZ6"), + STM32_FUNCTION(1, "DBTRGI"), + STM32_FUNCTION(2, "DBTRGO"), + STM32_FUNCTION(4, "SPI8_NSS"), + STM32_FUNCTION(5, "TIM8_CH3"), + STM32_FUNCTION(6, "ADF1_SDI0"), + STM32_FUNCTION(7, "LPUART1_CTS"), + STM32_FUNCTION(8, "LPTIM5_OUT"), + STM32_FUNCTION(11, "LPTIM4_CH2"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(407, "PZ7"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOZ7"), + STM32_FUNCTION(4, "SPI8_MOSI"), + STM32_FUNCTION(5, "MDF1_CCK1"), + STM32_FUNCTION(6, "ADF1_CCK1"), + STM32_FUNCTION(7, "LPUART1_TX"), + STM32_FUNCTION(8, "LPTIM5_IN1"), + STM32_FUNCTION(11, "LPTIM3_CH2"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(408, "PZ8"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOZ8"), + STM32_FUNCTION(3, "LPTIM3_IN1"), + STM32_FUNCTION(4, "SPI8_MISO"), + STM32_FUNCTION(5, "MDF1_SDI5"), + STM32_FUNCTION(6, "ADF1_SDI0"), + STM32_FUNCTION(7, "LPUART1_RX"), + STM32_FUNCTION(8, "LPTIM4_CH1"), + STM32_FUNCTION(9, "I2C8_SMBA"), + STM32_FUNCTION(10, "LPTIM5_ETR"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN_PKG( + PINCTRL_PIN(409, "PZ9"), + STM32MP_PKG_AI | STM32MP_PKG_AK | STM32MP_PKG_AL, + STM32_FUNCTION(0, "GPIOZ9"), + STM32_FUNCTION(2, "MCO2"), + STM32_FUNCTION(4, "SPI8_RDY"), + STM32_FUNCTION(5, "MDF1_CKI5"), + STM32_FUNCTION(7, "LPUART1_TX"), + STM32_FUNCTION(8, "LPTIM4_ETR"), + STM32_FUNCTION(9, "I2C8_SDA"), + STM32_FUNCTION(11, "LPTIM3_CH2"), + STM32_FUNCTION(12, "I3C4_SDA"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), +}; + +static struct stm32_pinctrl_match_data stm32mp257_match_data = { + .pins = stm32mp257_pins, + .npins = ARRAY_SIZE(stm32mp257_pins), +}; + +static struct stm32_pinctrl_match_data stm32mp257_z_match_data = { + .pins = stm32mp257_z_pins, + .npins = ARRAY_SIZE(stm32mp257_z_pins), +}; + +static const struct of_device_id stm32mp257_pctrl_match[] = { + { + .compatible = "st,stm32mp257-pinctrl", + .data = &stm32mp257_match_data, + }, + { + .compatible = "st,stm32mp257-z-pinctrl", + .data = &stm32mp257_z_match_data, + }, + { } +}; + +static const struct dev_pm_ops stm32_pinctrl_dev_pm_ops = { + SET_LATE_SYSTEM_SLEEP_PM_OPS(NULL, stm32_pinctrl_resume) +}; + +static struct platform_driver stm32mp257_pinctrl_driver = { + .probe = stm32_pctl_probe, + .driver = { + .name = "stm32mp257-pinctrl", + .of_match_table = stm32mp257_pctrl_match, + .pm = &stm32_pinctrl_dev_pm_ops, + }, +}; + +static int __init stm32mp257_pinctrl_init(void) +{ + return platform_driver_register(&stm32mp257_pinctrl_driver); +} +arch_initcall(stm32mp257_pinctrl_init); diff --git a/drivers/pinctrl/sunplus/sppctl.c b/drivers/pinctrl/sunplus/sppctl.c index 6bbbab3a6fdf3f015c1c732c437e61ff905e134b..150996949ede7e35ed1dd1e441fff94db2f5ea6e 100644 --- a/drivers/pinctrl/sunplus/sppctl.c +++ b/drivers/pinctrl/sunplus/sppctl.c @@ -834,11 +834,6 @@ static int sppctl_dt_node_to_map(struct pinctrl_dev *pctldev, struct device_node int i, size = 0; list = of_get_property(np_config, "sunplus,pins", &size); - - if (nmG <= 0) - nmG = 0; - - parent = of_get_parent(np_config); *num_maps = size / sizeof(*list); /* @@ -866,10 +861,14 @@ static int sppctl_dt_node_to_map(struct pinctrl_dev *pctldev, struct device_node } } + if (nmG <= 0) + nmG = 0; + *map = kcalloc(*num_maps + nmG, sizeof(**map), GFP_KERNEL); - if (*map == NULL) + if (!(*map)) return -ENOMEM; + parent = of_get_parent(np_config); for (i = 0; i < (*num_maps); i++) { dt_pin = be32_to_cpu(list[i]); pin_num = FIELD_GET(GENMASK(31, 24), dt_pin); @@ -883,6 +882,8 @@ static int sppctl_dt_node_to_map(struct pinctrl_dev *pctldev, struct device_node (*map)[i].data.configs.num_configs = 1; (*map)[i].data.configs.group_or_pin = pin_get_name(pctldev, pin_num); configs = kmalloc(sizeof(*configs), GFP_KERNEL); + if (!configs) + goto sppctl_map_err; *configs = FIELD_GET(GENMASK(7, 0), dt_pin); (*map)[i].data.configs.configs = configs; @@ -896,6 +897,8 @@ static int sppctl_dt_node_to_map(struct pinctrl_dev *pctldev, struct device_node (*map)[i].data.configs.num_configs = 1; (*map)[i].data.configs.group_or_pin = pin_get_name(pctldev, pin_num); configs = kmalloc(sizeof(*configs), GFP_KERNEL); + if (!configs) + goto sppctl_map_err; *configs = SPPCTL_IOP_CONFIGS; (*map)[i].data.configs.configs = configs; @@ -965,6 +968,14 @@ static int sppctl_dt_node_to_map(struct pinctrl_dev *pctldev, struct device_node of_node_put(parent); dev_dbg(pctldev->dev, "%d pins mapped\n", *num_maps); return 0; + +sppctl_map_err: + for (i = 0; i < (*num_maps); i++) + if ((*map)[i].type == PIN_MAP_TYPE_CONFIGS_PIN) + kfree((*map)[i].data.configs.configs); + kfree(*map); + of_node_put(parent); + return -ENOMEM; } static const struct pinctrl_ops sppctl_pctl_ops = { diff --git a/drivers/pinctrl/tegra/Kconfig b/drivers/pinctrl/tegra/Kconfig index a67d0d9ae8cd29fca810d9bc2fe51d392b5afc82..4e87d19323ba88980e0cd1b1571c5e9414330172 100644 --- a/drivers/pinctrl/tegra/Kconfig +++ b/drivers/pinctrl/tegra/Kconfig @@ -28,6 +28,10 @@ config PINCTRL_TEGRA194 bool select PINCTRL_TEGRA +config PINCTRL_TEGRA234 + bool + select PINCTRL_TEGRA + config PINCTRL_TEGRA_XUSB def_bool y if ARCH_TEGRA select GENERIC_PHY diff --git a/drivers/pinctrl/tegra/Makefile b/drivers/pinctrl/tegra/Makefile index ead4e10097d00e0928c701a57094f82b325da44d..a93973701d4cced61cc806d70510218372959fed 100644 --- a/drivers/pinctrl/tegra/Makefile +++ b/drivers/pinctrl/tegra/Makefile @@ -6,4 +6,5 @@ obj-$(CONFIG_PINCTRL_TEGRA114) += pinctrl-tegra114.o obj-$(CONFIG_PINCTRL_TEGRA124) += pinctrl-tegra124.o obj-$(CONFIG_PINCTRL_TEGRA210) += pinctrl-tegra210.o obj-$(CONFIG_PINCTRL_TEGRA194) += pinctrl-tegra194.o +obj-$(CONFIG_PINCTRL_TEGRA234) += pinctrl-tegra234.o obj-$(CONFIG_PINCTRL_TEGRA_XUSB) += pinctrl-tegra-xusb.o diff --git a/drivers/pinctrl/tegra/pinctrl-tegra.c b/drivers/pinctrl/tegra/pinctrl-tegra.c index 1729b7ddfa946a7835cc86239eec98d7218509cf..4547cf66d03b9fea7385c2cd14dcc3fdceec290f 100644 --- a/drivers/pinctrl/tegra/pinctrl-tegra.c +++ b/drivers/pinctrl/tegra/pinctrl-tegra.c @@ -232,7 +232,7 @@ static const char *tegra_pinctrl_get_func_name(struct pinctrl_dev *pctldev, { struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev); - return pmx->soc->functions[function].name; + return pmx->functions[function].name; } static int tegra_pinctrl_get_func_groups(struct pinctrl_dev *pctldev, @@ -242,8 +242,8 @@ static int tegra_pinctrl_get_func_groups(struct pinctrl_dev *pctldev, { struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev); - *groups = pmx->soc->functions[function].groups; - *num_groups = pmx->soc->functions[function].ngroups; + *groups = pmx->functions[function].groups; + *num_groups = pmx->functions[function].ngroups; return 0; } @@ -789,20 +789,26 @@ int tegra_pinctrl_probe(struct platform_device *pdev, * Each mux group will appear in 4 functions' list of groups. * This over-allocates slightly, since not all groups are mux groups. */ - pmx->group_pins = devm_kcalloc(&pdev->dev, - soc_data->ngroups * 4, sizeof(*pmx->group_pins), - GFP_KERNEL); + pmx->group_pins = devm_kcalloc(&pdev->dev, pmx->soc->ngroups * 4, + sizeof(*pmx->group_pins), GFP_KERNEL); if (!pmx->group_pins) return -ENOMEM; + pmx->functions = devm_kcalloc(&pdev->dev, pmx->soc->nfunctions, + sizeof(*pmx->functions), GFP_KERNEL); + if (!pmx->functions) + return -ENOMEM; + group_pins = pmx->group_pins; - for (fn = 0; fn < soc_data->nfunctions; fn++) { - struct tegra_function *func = &soc_data->functions[fn]; + for (fn = 0; fn < pmx->soc->nfunctions; fn++) { + struct tegra_function *func = &pmx->functions[fn]; + + func->name = pmx->soc->functions[fn]; func->groups = group_pins; - for (gn = 0; gn < soc_data->ngroups; gn++) { - const struct tegra_pingroup *g = &soc_data->groups[gn]; + for (gn = 0; gn < pmx->soc->ngroups; gn++) { + const struct tegra_pingroup *g = &pmx->soc->groups[gn]; if (g->mux_reg == -1) continue; @@ -814,7 +820,7 @@ int tegra_pinctrl_probe(struct platform_device *pdev, continue; BUG_ON(group_pins - pmx->group_pins >= - soc_data->ngroups * 4); + pmx->soc->ngroups * 4); *group_pins++ = g->name; func->ngroups++; } diff --git a/drivers/pinctrl/tegra/pinctrl-tegra.h b/drivers/pinctrl/tegra/pinctrl-tegra.h index 6130cba7cce54870cc07c9e8a193681943388b41..b3289bdf727d8291ff6d23931eeb0b61ceae6576 100644 --- a/drivers/pinctrl/tegra/pinctrl-tegra.h +++ b/drivers/pinctrl/tegra/pinctrl-tegra.h @@ -13,6 +13,7 @@ struct tegra_pmx { struct pinctrl_dev *pctl; const struct tegra_pinctrl_soc_data *soc; + struct tegra_function *functions; const char **group_pins; struct pinctrl_gpio_range gpio_range; @@ -191,7 +192,7 @@ struct tegra_pinctrl_soc_data { const char *gpio_compatible; const struct pinctrl_pin_desc *pins; unsigned npins; - struct tegra_function *functions; + const char * const *functions; unsigned nfunctions; const struct tegra_pingroup *groups; unsigned ngroups; diff --git a/drivers/pinctrl/tegra/pinctrl-tegra114.c b/drivers/pinctrl/tegra/pinctrl-tegra114.c index e72ab1eb23983289961c6c913c7d56c1e02d39d0..3d425b2018e78967890e4330ff02c1aaa3517b0b 100644 --- a/drivers/pinctrl/tegra/pinctrl-tegra114.c +++ b/drivers/pinctrl/tegra/pinctrl-tegra114.c @@ -1452,12 +1452,9 @@ enum tegra_mux { TEGRA_MUX_VI_ALT3, }; -#define FUNCTION(fname) \ - { \ - .name = #fname, \ - } +#define FUNCTION(fname) #fname -static struct tegra_function tegra114_functions[] = { +static const char * const tegra114_functions[] = { FUNCTION(blink), FUNCTION(cec), FUNCTION(cldvfs), diff --git a/drivers/pinctrl/tegra/pinctrl-tegra124.c b/drivers/pinctrl/tegra/pinctrl-tegra124.c index 26096c6b967e2f7ff8ac307c30c371adbe2ac35b..2a50c5c7516c379e8355e60987a44cce3619d421 100644 --- a/drivers/pinctrl/tegra/pinctrl-tegra124.c +++ b/drivers/pinctrl/tegra/pinctrl-tegra124.c @@ -1611,12 +1611,9 @@ enum tegra_mux { TEGRA_MUX_VIMCLK2_ALT, }; -#define FUNCTION(fname) \ - { \ - .name = #fname, \ - } +#define FUNCTION(fname) #fname -static struct tegra_function tegra124_functions[] = { +static const char * const tegra124_functions[] = { FUNCTION(blink), FUNCTION(ccla), FUNCTION(cec), diff --git a/drivers/pinctrl/tegra/pinctrl-tegra194.c b/drivers/pinctrl/tegra/pinctrl-tegra194.c index 277973c884344b2394cd6c6a431c870756371250..69f58df6289779233fc91373d97d1958d835167b 100644 --- a/drivers/pinctrl/tegra/pinctrl-tegra194.c +++ b/drivers/pinctrl/tegra/pinctrl-tegra194.c @@ -1189,12 +1189,9 @@ enum tegra_mux_dt { }; /* Make list of each function name */ -#define TEGRA_PIN_FUNCTION(lid) \ - { \ - .name = #lid, \ - } +#define TEGRA_PIN_FUNCTION(lid) #lid -static struct tegra_function tegra194_functions[] = { +static const char * const tegra194_functions[] = { TEGRA_PIN_FUNCTION(rsvd0), TEGRA_PIN_FUNCTION(rsvd1), TEGRA_PIN_FUNCTION(rsvd2), diff --git a/drivers/pinctrl/tegra/pinctrl-tegra20.c b/drivers/pinctrl/tegra/pinctrl-tegra20.c index 0dc2cf0d05b1ec83c8907cb25ed0a7c85f21d55a..737fc2000f66b91c595f17299d6555eae66f399d 100644 --- a/drivers/pinctrl/tegra/pinctrl-tegra20.c +++ b/drivers/pinctrl/tegra/pinctrl-tegra20.c @@ -1889,12 +1889,9 @@ enum tegra_mux { TEGRA_MUX_XIO, }; -#define FUNCTION(fname) \ - { \ - .name = #fname, \ - } +#define FUNCTION(fname) #fname -static struct tegra_function tegra20_functions[] = { +static const char * const tegra20_functions[] = { FUNCTION(ahb_clk), FUNCTION(apb_clk), FUNCTION(audio_sync), diff --git a/drivers/pinctrl/tegra/pinctrl-tegra210.c b/drivers/pinctrl/tegra/pinctrl-tegra210.c index b480f607fa16fc50d55a568f98006ad195be694a..9bb29146dfff7bd524e799b92e97020b47b7ec44 100644 --- a/drivers/pinctrl/tegra/pinctrl-tegra210.c +++ b/drivers/pinctrl/tegra/pinctrl-tegra210.c @@ -1185,12 +1185,9 @@ enum tegra_mux { TEGRA_MUX_VIMCLK2, }; -#define FUNCTION(fname) \ - { \ - .name = #fname, \ - } +#define FUNCTION(fname) #fname -static struct tegra_function tegra210_functions[] = { +static const char * const tegra210_functions[] = { FUNCTION(aud), FUNCTION(bcl), FUNCTION(blink), diff --git a/drivers/pinctrl/tegra/pinctrl-tegra234.c b/drivers/pinctrl/tegra/pinctrl-tegra234.c new file mode 100644 index 0000000000000000000000000000000000000000..86c2b84e792d9d31256602e5c5028a57f227d97f --- /dev/null +++ b/drivers/pinctrl/tegra/pinctrl-tegra234.c @@ -0,0 +1,1960 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Pinctrl data for the NVIDIA Tegra234 pinmux + * + * Copyright (c) 2021-2023, NVIDIA CORPORATION. All rights reserved. + */ + +#include +#include +#include +#include + +#include +#include + +#include "pinctrl-tegra.h" + +/* Define unique ID for each pins */ +enum { + TEGRA_PIN_DAP6_SCLK_PA0, + TEGRA_PIN_DAP6_DOUT_PA1, + TEGRA_PIN_DAP6_DIN_PA2, + TEGRA_PIN_DAP6_FS_PA3, + TEGRA_PIN_DAP4_SCLK_PA4, + TEGRA_PIN_DAP4_DOUT_PA5, + TEGRA_PIN_DAP4_DIN_PA6, + TEGRA_PIN_DAP4_FS_PA7, + TEGRA_PIN_SOC_GPIO08_PB0, + TEGRA_PIN_QSPI0_SCK_PC0, + TEGRA_PIN_QSPI0_CS_N_PC1, + TEGRA_PIN_QSPI0_IO0_PC2, + TEGRA_PIN_QSPI0_IO1_PC3, + TEGRA_PIN_QSPI0_IO2_PC4, + TEGRA_PIN_QSPI0_IO3_PC5, + TEGRA_PIN_QSPI1_SCK_PC6, + TEGRA_PIN_QSPI1_CS_N_PC7, + TEGRA_PIN_QSPI1_IO0_PD0, + TEGRA_PIN_QSPI1_IO1_PD1, + TEGRA_PIN_QSPI1_IO2_PD2, + TEGRA_PIN_QSPI1_IO3_PD3, + TEGRA_PIN_EQOS_TXC_PE0, + TEGRA_PIN_EQOS_TD0_PE1, + TEGRA_PIN_EQOS_TD1_PE2, + TEGRA_PIN_EQOS_TD2_PE3, + TEGRA_PIN_EQOS_TD3_PE4, + TEGRA_PIN_EQOS_TX_CTL_PE5, + TEGRA_PIN_EQOS_RD0_PE6, + TEGRA_PIN_EQOS_RD1_PE7, + TEGRA_PIN_EQOS_RD2_PF0, + TEGRA_PIN_EQOS_RD3_PF1, + TEGRA_PIN_EQOS_RX_CTL_PF2, + TEGRA_PIN_EQOS_RXC_PF3, + TEGRA_PIN_EQOS_SMA_MDIO_PF4, + TEGRA_PIN_EQOS_SMA_MDC_PF5, + TEGRA_PIN_SOC_GPIO13_PG0, + TEGRA_PIN_SOC_GPIO14_PG1, + TEGRA_PIN_SOC_GPIO15_PG2, + TEGRA_PIN_SOC_GPIO16_PG3, + TEGRA_PIN_SOC_GPIO17_PG4, + TEGRA_PIN_SOC_GPIO18_PG5, + TEGRA_PIN_SOC_GPIO19_PG6, + TEGRA_PIN_SOC_GPIO20_PG7, + TEGRA_PIN_SOC_GPIO21_PH0, + TEGRA_PIN_SOC_GPIO22_PH1, + TEGRA_PIN_SOC_GPIO06_PH2, + TEGRA_PIN_UART4_TX_PH3, + TEGRA_PIN_UART4_RX_PH4, + TEGRA_PIN_UART4_RTS_PH5, + TEGRA_PIN_UART4_CTS_PH6, + TEGRA_PIN_SOC_GPIO41_PH7, + TEGRA_PIN_SOC_GPIO42_PI0, + TEGRA_PIN_SOC_GPIO43_PI1, + TEGRA_PIN_SOC_GPIO44_PI2, + TEGRA_PIN_GEN1_I2C_SCL_PI3, + TEGRA_PIN_GEN1_I2C_SDA_PI4, + TEGRA_PIN_CPU_PWR_REQ_PI5, + TEGRA_PIN_SOC_GPIO07_PI6, + TEGRA_PIN_SDMMC1_CLK_PJ0, + TEGRA_PIN_SDMMC1_CMD_PJ1, + TEGRA_PIN_SDMMC1_DAT0_PJ2, + TEGRA_PIN_SDMMC1_DAT1_PJ3, + TEGRA_PIN_SDMMC1_DAT2_PJ4, + TEGRA_PIN_SDMMC1_DAT3_PJ5, + TEGRA_PIN_PEX_L0_CLKREQ_N_PK0, + TEGRA_PIN_PEX_L0_RST_N_PK1, + TEGRA_PIN_PEX_L1_CLKREQ_N_PK2, + TEGRA_PIN_PEX_L1_RST_N_PK3, + TEGRA_PIN_PEX_L2_CLKREQ_N_PK4, + TEGRA_PIN_PEX_L2_RST_N_PK5, + TEGRA_PIN_PEX_L3_CLKREQ_N_PK6, + TEGRA_PIN_PEX_L3_RST_N_PK7, + TEGRA_PIN_PEX_L4_CLKREQ_N_PL0, + TEGRA_PIN_PEX_L4_RST_N_PL1, + TEGRA_PIN_PEX_WAKE_N_PL2, + TEGRA_PIN_SOC_GPIO34_PL3, + TEGRA_PIN_DP_AUX_CH0_HPD_PM0, + TEGRA_PIN_DP_AUX_CH1_HPD_PM1, + TEGRA_PIN_DP_AUX_CH2_HPD_PM2, + TEGRA_PIN_DP_AUX_CH3_HPD_PM3, + TEGRA_PIN_SOC_GPIO55_PM4, + TEGRA_PIN_SOC_GPIO36_PM5, + TEGRA_PIN_SOC_GPIO53_PM6, + TEGRA_PIN_SOC_GPIO38_PM7, + TEGRA_PIN_DP_AUX_CH3_N_PN0, + TEGRA_PIN_SOC_GPIO39_PN1, + TEGRA_PIN_SOC_GPIO40_PN2, + TEGRA_PIN_DP_AUX_CH1_P_PN3, + TEGRA_PIN_DP_AUX_CH1_N_PN4, + TEGRA_PIN_DP_AUX_CH2_P_PN5, + TEGRA_PIN_DP_AUX_CH2_N_PN6, + TEGRA_PIN_DP_AUX_CH3_P_PN7, + TEGRA_PIN_EXTPERIPH1_CLK_PP0, + TEGRA_PIN_EXTPERIPH2_CLK_PP1, + TEGRA_PIN_CAM_I2C_SCL_PP2, + TEGRA_PIN_CAM_I2C_SDA_PP3, + TEGRA_PIN_SOC_GPIO23_PP4, + TEGRA_PIN_SOC_GPIO24_PP5, + TEGRA_PIN_SOC_GPIO25_PP6, + TEGRA_PIN_PWR_I2C_SCL_PP7, + TEGRA_PIN_PWR_I2C_SDA_PQ0, + TEGRA_PIN_SOC_GPIO28_PQ1, + TEGRA_PIN_SOC_GPIO29_PQ2, + TEGRA_PIN_SOC_GPIO30_PQ3, + TEGRA_PIN_SOC_GPIO31_PQ4, + TEGRA_PIN_SOC_GPIO32_PQ5, + TEGRA_PIN_SOC_GPIO33_PQ6, + TEGRA_PIN_SOC_GPIO35_PQ7, + TEGRA_PIN_SOC_GPIO37_PR0, + TEGRA_PIN_SOC_GPIO56_PR1, + TEGRA_PIN_UART1_TX_PR2, + TEGRA_PIN_UART1_RX_PR3, + TEGRA_PIN_UART1_RTS_PR4, + TEGRA_PIN_UART1_CTS_PR5, + TEGRA_PIN_GPU_PWR_REQ_PX0, + TEGRA_PIN_CV_PWR_REQ_PX1, + TEGRA_PIN_GP_PWM2_PX2, + TEGRA_PIN_GP_PWM3_PX3, + TEGRA_PIN_UART2_TX_PX4, + TEGRA_PIN_UART2_RX_PX5, + TEGRA_PIN_UART2_RTS_PX6, + TEGRA_PIN_UART2_CTS_PX7, + TEGRA_PIN_SPI3_SCK_PY0, + TEGRA_PIN_SPI3_MISO_PY1, + TEGRA_PIN_SPI3_MOSI_PY2, + TEGRA_PIN_SPI3_CS0_PY3, + TEGRA_PIN_SPI3_CS1_PY4, + TEGRA_PIN_UART5_TX_PY5, + TEGRA_PIN_UART5_RX_PY6, + TEGRA_PIN_UART5_RTS_PY7, + TEGRA_PIN_UART5_CTS_PZ0, + TEGRA_PIN_USB_VBUS_EN0_PZ1, + TEGRA_PIN_USB_VBUS_EN1_PZ2, + TEGRA_PIN_SPI1_SCK_PZ3, + TEGRA_PIN_SPI1_MISO_PZ4, + TEGRA_PIN_SPI1_MOSI_PZ5, + TEGRA_PIN_SPI1_CS0_PZ6, + TEGRA_PIN_SPI1_CS1_PZ7, + TEGRA_PIN_SPI5_SCK_PAC0, + TEGRA_PIN_SPI5_MISO_PAC1, + TEGRA_PIN_SPI5_MOSI_PAC2, + TEGRA_PIN_SPI5_CS0_PAC3, + TEGRA_PIN_SOC_GPIO57_PAC4, + TEGRA_PIN_SOC_GPIO58_PAC5, + TEGRA_PIN_SOC_GPIO59_PAC6, + TEGRA_PIN_SOC_GPIO60_PAC7, + TEGRA_PIN_SOC_GPIO45_PAD0, + TEGRA_PIN_SOC_GPIO46_PAD1, + TEGRA_PIN_SOC_GPIO47_PAD2, + TEGRA_PIN_SOC_GPIO48_PAD3, + TEGRA_PIN_UFS0_REF_CLK_PAE0, + TEGRA_PIN_UFS0_RST_N_PAE1, + TEGRA_PIN_PEX_L5_CLKREQ_N_PAF0, + TEGRA_PIN_PEX_L5_RST_N_PAF1, + TEGRA_PIN_PEX_L6_CLKREQ_N_PAF2, + TEGRA_PIN_PEX_L6_RST_N_PAF3, + TEGRA_PIN_PEX_L7_CLKREQ_N_PAG0, + TEGRA_PIN_PEX_L7_RST_N_PAG1, + TEGRA_PIN_PEX_L8_CLKREQ_N_PAG2, + TEGRA_PIN_PEX_L8_RST_N_PAG3, + TEGRA_PIN_PEX_L9_CLKREQ_N_PAG4, + TEGRA_PIN_PEX_L9_RST_N_PAG5, + TEGRA_PIN_PEX_L10_CLKREQ_N_PAG6, + TEGRA_PIN_PEX_L10_RST_N_PAG7, + TEGRA_PIN_EQOS_COMP, + TEGRA_PIN_QSPI_COMP, + TEGRA_PIN_SDMMC1_COMP, +}; + +enum { + TEGRA_PIN_CAN0_DOUT_PAA0, + TEGRA_PIN_CAN0_DIN_PAA1, + TEGRA_PIN_CAN1_DOUT_PAA2, + TEGRA_PIN_CAN1_DIN_PAA3, + TEGRA_PIN_CAN0_STB_PAA4, + TEGRA_PIN_CAN0_EN_PAA5, + TEGRA_PIN_SOC_GPIO49_PAA6, + TEGRA_PIN_CAN0_ERR_PAA7, + TEGRA_PIN_CAN1_STB_PBB0, + TEGRA_PIN_CAN1_EN_PBB1, + TEGRA_PIN_SOC_GPIO50_PBB2, + TEGRA_PIN_CAN1_ERR_PBB3, + TEGRA_PIN_SPI2_SCK_PCC0, + TEGRA_PIN_SPI2_MISO_PCC1, + TEGRA_PIN_SPI2_MOSI_PCC2, + TEGRA_PIN_SPI2_CS0_PCC3, + TEGRA_PIN_TOUCH_CLK_PCC4, + TEGRA_PIN_UART3_TX_PCC5, + TEGRA_PIN_UART3_RX_PCC6, + TEGRA_PIN_GEN2_I2C_SCL_PCC7, + TEGRA_PIN_GEN2_I2C_SDA_PDD0, + TEGRA_PIN_GEN8_I2C_SCL_PDD1, + TEGRA_PIN_GEN8_I2C_SDA_PDD2, + TEGRA_PIN_SCE_ERROR_PEE0, + TEGRA_PIN_VCOMP_ALERT_PEE1, + TEGRA_PIN_AO_RETENTION_N_PEE2, + TEGRA_PIN_BATT_OC_PEE3, + TEGRA_PIN_POWER_ON_PEE4, + TEGRA_PIN_SOC_GPIO26_PEE5, + TEGRA_PIN_SOC_GPIO27_PEE6, + TEGRA_PIN_BOOTV_CTL_N_PEE7, + TEGRA_PIN_HDMI_CEC_PGG0, +}; + +/* Table for pin descriptor */ +static const struct pinctrl_pin_desc tegra234_pins[] = { + PINCTRL_PIN(TEGRA_PIN_DAP6_SCLK_PA0, "DAP6_SCLK_PA0"), + PINCTRL_PIN(TEGRA_PIN_DAP6_DOUT_PA1, "DAP6_DOUT_PA1"), + PINCTRL_PIN(TEGRA_PIN_DAP6_DIN_PA2, "DAP6_DIN_PA2"), + PINCTRL_PIN(TEGRA_PIN_DAP6_FS_PA3, "DAP6_FS_PA3"), + PINCTRL_PIN(TEGRA_PIN_DAP4_SCLK_PA4, "DAP4_SCLK_PA4"), + PINCTRL_PIN(TEGRA_PIN_DAP4_DOUT_PA5, "DAP4_DOUT_PA5"), + PINCTRL_PIN(TEGRA_PIN_DAP4_DIN_PA6, "DAP4_DIN_PA6"), + PINCTRL_PIN(TEGRA_PIN_DAP4_FS_PA7, "DAP4_FS_PA7"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO08_PB0, "SOC_GPIO08_PB0"), + PINCTRL_PIN(TEGRA_PIN_QSPI0_SCK_PC0, "QSPI0_SCK_PC0"), + PINCTRL_PIN(TEGRA_PIN_QSPI0_CS_N_PC1, "QSPI0_CS_N_PC1"), + PINCTRL_PIN(TEGRA_PIN_QSPI0_IO0_PC2, "QSPI0_IO0_PC2"), + PINCTRL_PIN(TEGRA_PIN_QSPI0_IO1_PC3, "QSPI0_IO1_PC3"), + PINCTRL_PIN(TEGRA_PIN_QSPI0_IO2_PC4, "QSPI0_IO2_PC4"), + PINCTRL_PIN(TEGRA_PIN_QSPI0_IO3_PC5, "QSPI0_IO3_PC5"), + PINCTRL_PIN(TEGRA_PIN_QSPI1_SCK_PC6, "QSPI1_SCK_PC6"), + PINCTRL_PIN(TEGRA_PIN_QSPI1_CS_N_PC7, "QSPI1_CS_N_PC7"), + PINCTRL_PIN(TEGRA_PIN_QSPI1_IO0_PD0, "QSPI1_IO0_PD0"), + PINCTRL_PIN(TEGRA_PIN_QSPI1_IO1_PD1, "QSPI1_IO1_PD1"), + PINCTRL_PIN(TEGRA_PIN_QSPI1_IO2_PD2, "QSPI1_IO2_PD2"), + PINCTRL_PIN(TEGRA_PIN_QSPI1_IO3_PD3, "QSPI1_IO3_PD3"), + PINCTRL_PIN(TEGRA_PIN_EQOS_TXC_PE0, "EQOS_TXC_PE0"), + PINCTRL_PIN(TEGRA_PIN_EQOS_TD0_PE1, "EQOS_TD0_PE1"), + PINCTRL_PIN(TEGRA_PIN_EQOS_TD1_PE2, "EQOS_TD1_PE2"), + PINCTRL_PIN(TEGRA_PIN_EQOS_TD2_PE3, "EQOS_TD2_PE3"), + PINCTRL_PIN(TEGRA_PIN_EQOS_TD3_PE4, "EQOS_TD3_PE4"), + PINCTRL_PIN(TEGRA_PIN_EQOS_TX_CTL_PE5, "EQOS_TX_CTL_PE5"), + PINCTRL_PIN(TEGRA_PIN_EQOS_RD0_PE6, "EQOS_RD0_PE6"), + PINCTRL_PIN(TEGRA_PIN_EQOS_RD1_PE7, "EQOS_RD1_PE7"), + PINCTRL_PIN(TEGRA_PIN_EQOS_RD2_PF0, "EQOS_RD2_PF0"), + PINCTRL_PIN(TEGRA_PIN_EQOS_RD3_PF1, "EQOS_RD3_PF1"), + PINCTRL_PIN(TEGRA_PIN_EQOS_RX_CTL_PF2, "EQOS_RX_CTL_PF2"), + PINCTRL_PIN(TEGRA_PIN_EQOS_RXC_PF3, "EQOS_RXC_PF3"), + PINCTRL_PIN(TEGRA_PIN_EQOS_SMA_MDIO_PF4, "EQOS_SMA_MDIO_PF4"), + PINCTRL_PIN(TEGRA_PIN_EQOS_SMA_MDC_PF5, "EQOS_SMA_MDC_PF5"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO13_PG0, "SOC_GPIO13_PG0"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO14_PG1, "SOC_GPIO14_PG1"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO15_PG2, "SOC_GPIO15_PG2"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO16_PG3, "SOC_GPIO16_PG3"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO17_PG4, "SOC_GPIO17_PG4"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO18_PG5, "SOC_GPIO18_PG5"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO19_PG6, "SOC_GPIO19_PG6"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO20_PG7, "SOC_GPIO20_PG7"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO21_PH0, "SOC_GPIO21_PH0"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO22_PH1, "SOC_GPIO22_PH1"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO06_PH2, "SOC_GPIO06_PH2"), + PINCTRL_PIN(TEGRA_PIN_UART4_TX_PH3, "UART4_TX_PH3"), + PINCTRL_PIN(TEGRA_PIN_UART4_RX_PH4, "UART4_RX_PH4"), + PINCTRL_PIN(TEGRA_PIN_UART4_RTS_PH5, "UART4_RTS_PH5"), + PINCTRL_PIN(TEGRA_PIN_UART4_CTS_PH6, "UART4_CTS_PH6"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO41_PH7, "SOC_GPIO41_PH7"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO42_PI0, "SOC_GPIO42_PI0"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO43_PI1, "SOC_GPIO43_PI1"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO44_PI2, "SOC_GPIO44_PI2"), + PINCTRL_PIN(TEGRA_PIN_GEN1_I2C_SCL_PI3, "GEN1_I2C_SCL_PI3"), + PINCTRL_PIN(TEGRA_PIN_GEN1_I2C_SDA_PI4, "GEN1_I2C_SDA_PI4"), + PINCTRL_PIN(TEGRA_PIN_CPU_PWR_REQ_PI5, "CPU_PWR_REQ_PI5"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO07_PI6, "SOC_GPIO07_PI6"), + PINCTRL_PIN(TEGRA_PIN_SDMMC1_CLK_PJ0, "SDMMC1_CLK_PJ0"), + PINCTRL_PIN(TEGRA_PIN_SDMMC1_CMD_PJ1, "SDMMC1_CMD_PJ1"), + PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT0_PJ2, "SDMMC1_DAT0_PJ2"), + PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT1_PJ3, "SDMMC1_DAT1_PJ3"), + PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT2_PJ4, "SDMMC1_DAT2_PJ4"), + PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT3_PJ5, "SDMMC1_DAT3_PJ5"), + PINCTRL_PIN(TEGRA_PIN_PEX_L0_CLKREQ_N_PK0, "PEX_L0_CLKREQ_N_PK0"), + PINCTRL_PIN(TEGRA_PIN_PEX_L0_RST_N_PK1, "PEX_L0_RST_N_PK1"), + PINCTRL_PIN(TEGRA_PIN_PEX_L1_CLKREQ_N_PK2, "PEX_L1_CLKREQ_N_PK2"), + PINCTRL_PIN(TEGRA_PIN_PEX_L1_RST_N_PK3, "PEX_L1_RST_N_PK3"), + PINCTRL_PIN(TEGRA_PIN_PEX_L2_CLKREQ_N_PK4, "PEX_L2_CLKREQ_N_PK4"), + PINCTRL_PIN(TEGRA_PIN_PEX_L2_RST_N_PK5, "PEX_L2_RST_N_PK5"), + PINCTRL_PIN(TEGRA_PIN_PEX_L3_CLKREQ_N_PK6, "PEX_L3_CLKREQ_N_PK6"), + PINCTRL_PIN(TEGRA_PIN_PEX_L3_RST_N_PK7, "PEX_L3_RST_N_PK7"), + PINCTRL_PIN(TEGRA_PIN_PEX_L4_CLKREQ_N_PL0, "PEX_L4_CLKREQ_N_PL0"), + PINCTRL_PIN(TEGRA_PIN_PEX_L4_RST_N_PL1, "PEX_L4_RST_N_PL1"), + PINCTRL_PIN(TEGRA_PIN_PEX_WAKE_N_PL2, "PEX_WAKE_N_PL2"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO34_PL3, "SOC_GPIO34_PL3"), + PINCTRL_PIN(TEGRA_PIN_DP_AUX_CH0_HPD_PM0, "DP_AUX_CH0_HPD_PM0"), + PINCTRL_PIN(TEGRA_PIN_DP_AUX_CH1_HPD_PM1, "DP_AUX_CH1_HPD_PM1"), + PINCTRL_PIN(TEGRA_PIN_DP_AUX_CH2_HPD_PM2, "DP_AUX_CH2_HPD_PM2"), + PINCTRL_PIN(TEGRA_PIN_DP_AUX_CH3_HPD_PM3, "DP_AUX_CH3_HPD_PM3"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO55_PM4, "SOC_GPIO55_PM4"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO36_PM5, "SOC_GPIO36_PM5"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO53_PM6, "SOC_GPIO53_PM6"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO38_PM7, "SOC_GPIO38_PM7"), + PINCTRL_PIN(TEGRA_PIN_DP_AUX_CH3_N_PN0, "DP_AUX_CH3_N_PN0"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO39_PN1, "SOC_GPIO39_PN1"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO40_PN2, "SOC_GPIO40_PN2"), + PINCTRL_PIN(TEGRA_PIN_DP_AUX_CH1_P_PN3, "DP_AUX_CH1_P_PN3"), + PINCTRL_PIN(TEGRA_PIN_DP_AUX_CH1_N_PN4, "DP_AUX_CH1_N_PN4"), + PINCTRL_PIN(TEGRA_PIN_DP_AUX_CH2_P_PN5, "DP_AUX_CH2_P_PN5"), + PINCTRL_PIN(TEGRA_PIN_DP_AUX_CH2_N_PN6, "DP_AUX_CH2_N_PN6"), + PINCTRL_PIN(TEGRA_PIN_DP_AUX_CH3_P_PN7, "DP_AUX_CH3_P_PN7"), + PINCTRL_PIN(TEGRA_PIN_EXTPERIPH1_CLK_PP0, "EXTPERIPH1_CLK_PP0"), + PINCTRL_PIN(TEGRA_PIN_EXTPERIPH2_CLK_PP1, "EXTPERIPH2_CLK_PP1"), + PINCTRL_PIN(TEGRA_PIN_CAM_I2C_SCL_PP2, "CAM_I2C_SCL_PP2"), + PINCTRL_PIN(TEGRA_PIN_CAM_I2C_SDA_PP3, "CAM_I2C_SDA_PP3"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO23_PP4, "SOC_GPIO23_PP4"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO24_PP5, "SOC_GPIO24_PP5"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO25_PP6, "SOC_GPIO25_PP6"), + PINCTRL_PIN(TEGRA_PIN_PWR_I2C_SCL_PP7, "PWR_I2C_SCL_PP7"), + PINCTRL_PIN(TEGRA_PIN_PWR_I2C_SDA_PQ0, "PWR_I2C_SDA_PQ0"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO28_PQ1, "SOC_GPIO28_PQ1"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO29_PQ2, "SOC_GPIO29_PQ2"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO30_PQ3, "SOC_GPIO30_PQ3"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO31_PQ4, "SOC_GPIO31_PQ4"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO32_PQ5, "SOC_GPIO32_PQ5"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO33_PQ6, "SOC_GPIO33_PQ6"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO35_PQ7, "SOC_GPIO35_PQ7"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO37_PR0, "SOC_GPIO37_PR0"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO56_PR1, "SOC_GPIO56_PR1"), + PINCTRL_PIN(TEGRA_PIN_UART1_TX_PR2, "UART1_TX_PR2"), + PINCTRL_PIN(TEGRA_PIN_UART1_RX_PR3, "UART1_RX_PR3"), + PINCTRL_PIN(TEGRA_PIN_UART1_RTS_PR4, "UART1_RTS_PR4"), + PINCTRL_PIN(TEGRA_PIN_UART1_CTS_PR5, "UART1_CTS_PR5"), + PINCTRL_PIN(TEGRA_PIN_GPU_PWR_REQ_PX0, "GPU_PWR_REQ_PX0"), + PINCTRL_PIN(TEGRA_PIN_CV_PWR_REQ_PX1, "CV_PWR_REQ_PX1"), + PINCTRL_PIN(TEGRA_PIN_GP_PWM2_PX2, "GP_PWM2_PX2"), + PINCTRL_PIN(TEGRA_PIN_GP_PWM3_PX3, "GP_PWM3_PX3"), + PINCTRL_PIN(TEGRA_PIN_UART2_TX_PX4, "UART2_TX_PX4"), + PINCTRL_PIN(TEGRA_PIN_UART2_RX_PX5, "UART2_RX_PX5"), + PINCTRL_PIN(TEGRA_PIN_UART2_RTS_PX6, "UART2_RTS_PX6"), + PINCTRL_PIN(TEGRA_PIN_UART2_CTS_PX7, "UART2_CTS_PX7"), + PINCTRL_PIN(TEGRA_PIN_SPI3_SCK_PY0, "SPI3_SCK_PY0"), + PINCTRL_PIN(TEGRA_PIN_SPI3_MISO_PY1, "SPI3_MISO_PY1"), + PINCTRL_PIN(TEGRA_PIN_SPI3_MOSI_PY2, "SPI3_MOSI_PY2"), + PINCTRL_PIN(TEGRA_PIN_SPI3_CS0_PY3, "SPI3_CS0_PY3"), + PINCTRL_PIN(TEGRA_PIN_SPI3_CS1_PY4, "SPI3_CS1_PY4"), + PINCTRL_PIN(TEGRA_PIN_UART5_TX_PY5, "UART5_TX_PY5"), + PINCTRL_PIN(TEGRA_PIN_UART5_RX_PY6, "UART5_RX_PY6"), + PINCTRL_PIN(TEGRA_PIN_UART5_RTS_PY7, "UART5_RTS_PY7"), + PINCTRL_PIN(TEGRA_PIN_UART5_CTS_PZ0, "UART5_CTS_PZ0"), + PINCTRL_PIN(TEGRA_PIN_USB_VBUS_EN0_PZ1, "USB_VBUS_EN0_PZ1"), + PINCTRL_PIN(TEGRA_PIN_USB_VBUS_EN1_PZ2, "USB_VBUS_EN1_PZ2"), + PINCTRL_PIN(TEGRA_PIN_SPI1_SCK_PZ3, "SPI1_SCK_PZ3"), + PINCTRL_PIN(TEGRA_PIN_SPI1_MISO_PZ4, "SPI1_MISO_PZ4"), + PINCTRL_PIN(TEGRA_PIN_SPI1_MOSI_PZ5, "SPI1_MOSI_PZ5"), + PINCTRL_PIN(TEGRA_PIN_SPI1_CS0_PZ6, "SPI1_CS0_PZ6"), + PINCTRL_PIN(TEGRA_PIN_SPI1_CS1_PZ7, "SPI1_CS1_PZ7"), + PINCTRL_PIN(TEGRA_PIN_SPI5_SCK_PAC0, "SPI5_SCK_PAC0"), + PINCTRL_PIN(TEGRA_PIN_SPI5_MISO_PAC1, "SPI5_MISO_PAC1"), + PINCTRL_PIN(TEGRA_PIN_SPI5_MOSI_PAC2, "SPI5_MOSI_PAC2"), + PINCTRL_PIN(TEGRA_PIN_SPI5_CS0_PAC3, "SPI5_CS0_PAC3"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO57_PAC4, "SOC_GPIO57_PAC4"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO58_PAC5, "SOC_GPIO58_PAC5"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO59_PAC6, "SOC_GPIO59_PAC6"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO60_PAC7, "SOC_GPIO60_PAC7"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO45_PAD0, "SOC_GPIO45_PAD0"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO46_PAD1, "SOC_GPIO46_PAD1"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO47_PAD2, "SOC_GPIO47_PAD2"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO48_PAD3, "SOC_GPIO48_PAD3"), + PINCTRL_PIN(TEGRA_PIN_UFS0_REF_CLK_PAE0, "UFS0_REF_CLK_PAE0"), + PINCTRL_PIN(TEGRA_PIN_UFS0_RST_N_PAE1, "UFS0_RST_N_PAE1"), + PINCTRL_PIN(TEGRA_PIN_PEX_L5_CLKREQ_N_PAF0, "PEX_L5_CLKREQ_N_PAF0"), + PINCTRL_PIN(TEGRA_PIN_PEX_L5_RST_N_PAF1, "PEX_L5_RST_N_PAF1"), + PINCTRL_PIN(TEGRA_PIN_PEX_L6_CLKREQ_N_PAF2, "PEX_L6_CLKREQ_N_PAF2"), + PINCTRL_PIN(TEGRA_PIN_PEX_L6_RST_N_PAF3, "PEX_L6_RST_N_PAF3"), + PINCTRL_PIN(TEGRA_PIN_PEX_L7_CLKREQ_N_PAG0, "PEX_L7_CLKREQ_N_PAG0"), + PINCTRL_PIN(TEGRA_PIN_PEX_L7_RST_N_PAG1, "PEX_L7_RST_N_PAG1"), + PINCTRL_PIN(TEGRA_PIN_PEX_L8_CLKREQ_N_PAG2, "PEX_L8_CLKREQ_N_PAG2"), + PINCTRL_PIN(TEGRA_PIN_PEX_L8_RST_N_PAG3, "PEX_L8_RST_N_PAG3"), + PINCTRL_PIN(TEGRA_PIN_PEX_L9_CLKREQ_N_PAG4, "PEX_L9_CLKREQ_N_PAG4"), + PINCTRL_PIN(TEGRA_PIN_PEX_L9_RST_N_PAG5, "PEX_L9_RST_N_PAG5"), + PINCTRL_PIN(TEGRA_PIN_PEX_L10_CLKREQ_N_PAG6, "PEX_L10_CLKREQ_N_PAG6"), + PINCTRL_PIN(TEGRA_PIN_PEX_L10_RST_N_PAG7, "PEX_L10_RST_N_PAG7"), + PINCTRL_PIN(TEGRA_PIN_EQOS_COMP, "EQOS_COMP"), + PINCTRL_PIN(TEGRA_PIN_QSPI_COMP, "QSPI_COMP"), + PINCTRL_PIN(TEGRA_PIN_SDMMC1_COMP, "SDMMC1_COMP"), +}; + +static const unsigned int dap6_sclk_pa0_pins[] = { + TEGRA_PIN_DAP6_SCLK_PA0, +}; + +static const unsigned int dap6_dout_pa1_pins[] = { + TEGRA_PIN_DAP6_DOUT_PA1, +}; + +static const unsigned int dap6_din_pa2_pins[] = { + TEGRA_PIN_DAP6_DIN_PA2, +}; + +static const unsigned int dap6_fs_pa3_pins[] = { + TEGRA_PIN_DAP6_FS_PA3, +}; + +static const unsigned int dap4_sclk_pa4_pins[] = { + TEGRA_PIN_DAP4_SCLK_PA4, +}; + +static const unsigned int dap4_dout_pa5_pins[] = { + TEGRA_PIN_DAP4_DOUT_PA5, +}; + +static const unsigned int dap4_din_pa6_pins[] = { + TEGRA_PIN_DAP4_DIN_PA6, +}; + +static const unsigned int dap4_fs_pa7_pins[] = { + TEGRA_PIN_DAP4_FS_PA7, +}; + +static const unsigned int soc_gpio08_pb0_pins[] = { + TEGRA_PIN_SOC_GPIO08_PB0, +}; + +static const unsigned int qspi0_sck_pc0_pins[] = { + TEGRA_PIN_QSPI0_SCK_PC0, +}; + +static const unsigned int qspi0_cs_n_pc1_pins[] = { + TEGRA_PIN_QSPI0_CS_N_PC1, +}; + +static const unsigned int qspi0_io0_pc2_pins[] = { + TEGRA_PIN_QSPI0_IO0_PC2, +}; + +static const unsigned int qspi0_io1_pc3_pins[] = { + TEGRA_PIN_QSPI0_IO1_PC3, +}; + +static const unsigned int qspi0_io2_pc4_pins[] = { + TEGRA_PIN_QSPI0_IO2_PC4, +}; + +static const unsigned int qspi0_io3_pc5_pins[] = { + TEGRA_PIN_QSPI0_IO3_PC5, +}; + +static const unsigned int qspi1_sck_pc6_pins[] = { + TEGRA_PIN_QSPI1_SCK_PC6, +}; + +static const unsigned int qspi1_cs_n_pc7_pins[] = { + TEGRA_PIN_QSPI1_CS_N_PC7, +}; + +static const unsigned int qspi1_io0_pd0_pins[] = { + TEGRA_PIN_QSPI1_IO0_PD0, +}; + +static const unsigned int qspi1_io1_pd1_pins[] = { + TEGRA_PIN_QSPI1_IO1_PD1, +}; + +static const unsigned int qspi1_io2_pd2_pins[] = { + TEGRA_PIN_QSPI1_IO2_PD2, +}; + +static const unsigned int qspi1_io3_pd3_pins[] = { + TEGRA_PIN_QSPI1_IO3_PD3, +}; + +static const unsigned int eqos_txc_pe0_pins[] = { + TEGRA_PIN_EQOS_TXC_PE0, +}; + +static const unsigned int eqos_td0_pe1_pins[] = { + TEGRA_PIN_EQOS_TD0_PE1, +}; + +static const unsigned int eqos_td1_pe2_pins[] = { + TEGRA_PIN_EQOS_TD1_PE2, +}; + +static const unsigned int eqos_td2_pe3_pins[] = { + TEGRA_PIN_EQOS_TD2_PE3, +}; + +static const unsigned int eqos_td3_pe4_pins[] = { + TEGRA_PIN_EQOS_TD3_PE4, +}; + +static const unsigned int eqos_tx_ctl_pe5_pins[] = { + TEGRA_PIN_EQOS_TX_CTL_PE5, +}; + +static const unsigned int eqos_rd0_pe6_pins[] = { + TEGRA_PIN_EQOS_RD0_PE6, +}; + +static const unsigned int eqos_rd1_pe7_pins[] = { + TEGRA_PIN_EQOS_RD1_PE7, +}; + +static const unsigned int eqos_rd2_pf0_pins[] = { + TEGRA_PIN_EQOS_RD2_PF0, +}; + +static const unsigned int eqos_rd3_pf1_pins[] = { + TEGRA_PIN_EQOS_RD3_PF1, +}; + +static const unsigned int eqos_rx_ctl_pf2_pins[] = { + TEGRA_PIN_EQOS_RX_CTL_PF2, +}; + +static const unsigned int eqos_rxc_pf3_pins[] = { + TEGRA_PIN_EQOS_RXC_PF3, +}; + +static const unsigned int eqos_sma_mdio_pf4_pins[] = { + TEGRA_PIN_EQOS_SMA_MDIO_PF4, +}; + +static const unsigned int eqos_sma_mdc_pf5_pins[] = { + TEGRA_PIN_EQOS_SMA_MDC_PF5, +}; + +static const unsigned int soc_gpio13_pg0_pins[] = { + TEGRA_PIN_SOC_GPIO13_PG0, +}; + +static const unsigned int soc_gpio14_pg1_pins[] = { + TEGRA_PIN_SOC_GPIO14_PG1, +}; + +static const unsigned int soc_gpio15_pg2_pins[] = { + TEGRA_PIN_SOC_GPIO15_PG2, +}; + +static const unsigned int soc_gpio16_pg3_pins[] = { + TEGRA_PIN_SOC_GPIO16_PG3, +}; + +static const unsigned int soc_gpio17_pg4_pins[] = { + TEGRA_PIN_SOC_GPIO17_PG4, +}; + +static const unsigned int soc_gpio18_pg5_pins[] = { + TEGRA_PIN_SOC_GPIO18_PG5, +}; + +static const unsigned int soc_gpio19_pg6_pins[] = { + TEGRA_PIN_SOC_GPIO19_PG6, +}; + +static const unsigned int soc_gpio20_pg7_pins[] = { + TEGRA_PIN_SOC_GPIO20_PG7, +}; + +static const unsigned int soc_gpio21_ph0_pins[] = { + TEGRA_PIN_SOC_GPIO21_PH0, +}; + +static const unsigned int soc_gpio22_ph1_pins[] = { + TEGRA_PIN_SOC_GPIO22_PH1, +}; + +static const unsigned int soc_gpio06_ph2_pins[] = { + TEGRA_PIN_SOC_GPIO06_PH2, +}; + +static const unsigned int uart4_tx_ph3_pins[] = { + TEGRA_PIN_UART4_TX_PH3, +}; + +static const unsigned int uart4_rx_ph4_pins[] = { + TEGRA_PIN_UART4_RX_PH4, +}; + +static const unsigned int uart4_rts_ph5_pins[] = { + TEGRA_PIN_UART4_RTS_PH5, +}; + +static const unsigned int uart4_cts_ph6_pins[] = { + TEGRA_PIN_UART4_CTS_PH6, +}; + +static const unsigned int soc_gpio41_ph7_pins[] = { + TEGRA_PIN_SOC_GPIO41_PH7, +}; + +static const unsigned int soc_gpio42_pi0_pins[] = { + TEGRA_PIN_SOC_GPIO42_PI0, +}; + +static const unsigned int soc_gpio43_pi1_pins[] = { + TEGRA_PIN_SOC_GPIO43_PI1, +}; + +static const unsigned int soc_gpio44_pi2_pins[] = { + TEGRA_PIN_SOC_GPIO44_PI2, +}; + +static const unsigned int gen1_i2c_scl_pi3_pins[] = { + TEGRA_PIN_GEN1_I2C_SCL_PI3, +}; + +static const unsigned int gen1_i2c_sda_pi4_pins[] = { + TEGRA_PIN_GEN1_I2C_SDA_PI4, +}; + +static const unsigned int cpu_pwr_req_pi5_pins[] = { + TEGRA_PIN_CPU_PWR_REQ_PI5, +}; + +static const unsigned int soc_gpio07_pi6_pins[] = { + TEGRA_PIN_SOC_GPIO07_PI6, +}; + +static const unsigned int sdmmc1_clk_pj0_pins[] = { + TEGRA_PIN_SDMMC1_CLK_PJ0, +}; + +static const unsigned int sdmmc1_cmd_pj1_pins[] = { + TEGRA_PIN_SDMMC1_CMD_PJ1, +}; + +static const unsigned int sdmmc1_dat0_pj2_pins[] = { + TEGRA_PIN_SDMMC1_DAT0_PJ2, +}; + +static const unsigned int sdmmc1_dat1_pj3_pins[] = { + TEGRA_PIN_SDMMC1_DAT1_PJ3, +}; + +static const unsigned int sdmmc1_dat2_pj4_pins[] = { + TEGRA_PIN_SDMMC1_DAT2_PJ4, +}; + +static const unsigned int sdmmc1_dat3_pj5_pins[] = { + TEGRA_PIN_SDMMC1_DAT3_PJ5, +}; + +static const unsigned int pex_l0_clkreq_n_pk0_pins[] = { + TEGRA_PIN_PEX_L0_CLKREQ_N_PK0, +}; + +static const unsigned int pex_l0_rst_n_pk1_pins[] = { + TEGRA_PIN_PEX_L0_RST_N_PK1, +}; + +static const unsigned int pex_l1_clkreq_n_pk2_pins[] = { + TEGRA_PIN_PEX_L1_CLKREQ_N_PK2, +}; + +static const unsigned int pex_l1_rst_n_pk3_pins[] = { + TEGRA_PIN_PEX_L1_RST_N_PK3, +}; + +static const unsigned int pex_l2_clkreq_n_pk4_pins[] = { + TEGRA_PIN_PEX_L2_CLKREQ_N_PK4, +}; + +static const unsigned int pex_l2_rst_n_pk5_pins[] = { + TEGRA_PIN_PEX_L2_RST_N_PK5, +}; + +static const unsigned int pex_l3_clkreq_n_pk6_pins[] = { + TEGRA_PIN_PEX_L3_CLKREQ_N_PK6, +}; + +static const unsigned int pex_l3_rst_n_pk7_pins[] = { + TEGRA_PIN_PEX_L3_RST_N_PK7, +}; + +static const unsigned int pex_l4_clkreq_n_pl0_pins[] = { + TEGRA_PIN_PEX_L4_CLKREQ_N_PL0, +}; + +static const unsigned int pex_l4_rst_n_pl1_pins[] = { + TEGRA_PIN_PEX_L4_RST_N_PL1, +}; + +static const unsigned int pex_wake_n_pl2_pins[] = { + TEGRA_PIN_PEX_WAKE_N_PL2, +}; + +static const unsigned int soc_gpio34_pl3_pins[] = { + TEGRA_PIN_SOC_GPIO34_PL3, +}; + +static const unsigned int dp_aux_ch0_hpd_pm0_pins[] = { + TEGRA_PIN_DP_AUX_CH0_HPD_PM0, +}; + +static const unsigned int dp_aux_ch1_hpd_pm1_pins[] = { + TEGRA_PIN_DP_AUX_CH1_HPD_PM1, +}; + +static const unsigned int dp_aux_ch2_hpd_pm2_pins[] = { + TEGRA_PIN_DP_AUX_CH2_HPD_PM2, +}; + +static const unsigned int dp_aux_ch3_hpd_pm3_pins[] = { + TEGRA_PIN_DP_AUX_CH3_HPD_PM3, +}; + +static const unsigned int soc_gpio55_pm4_pins[] = { + TEGRA_PIN_SOC_GPIO55_PM4, +}; + +static const unsigned int soc_gpio36_pm5_pins[] = { + TEGRA_PIN_SOC_GPIO36_PM5, +}; + +static const unsigned int soc_gpio53_pm6_pins[] = { + TEGRA_PIN_SOC_GPIO53_PM6, +}; + +static const unsigned int soc_gpio38_pm7_pins[] = { + TEGRA_PIN_SOC_GPIO38_PM7, +}; + +static const unsigned int dp_aux_ch3_n_pn0_pins[] = { + TEGRA_PIN_DP_AUX_CH3_N_PN0, +}; + +static const unsigned int soc_gpio39_pn1_pins[] = { + TEGRA_PIN_SOC_GPIO39_PN1, +}; + +static const unsigned int soc_gpio40_pn2_pins[] = { + TEGRA_PIN_SOC_GPIO40_PN2, +}; + +static const unsigned int dp_aux_ch1_p_pn3_pins[] = { + TEGRA_PIN_DP_AUX_CH1_P_PN3, +}; + +static const unsigned int dp_aux_ch1_n_pn4_pins[] = { + TEGRA_PIN_DP_AUX_CH1_N_PN4, +}; + +static const unsigned int dp_aux_ch2_p_pn5_pins[] = { + TEGRA_PIN_DP_AUX_CH2_P_PN5, +}; + +static const unsigned int dp_aux_ch2_n_pn6_pins[] = { + TEGRA_PIN_DP_AUX_CH2_N_PN6, +}; + +static const unsigned int dp_aux_ch3_p_pn7_pins[] = { + TEGRA_PIN_DP_AUX_CH3_P_PN7, +}; + +static const unsigned int extperiph1_clk_pp0_pins[] = { + TEGRA_PIN_EXTPERIPH1_CLK_PP0, +}; + +static const unsigned int extperiph2_clk_pp1_pins[] = { + TEGRA_PIN_EXTPERIPH2_CLK_PP1, +}; + +static const unsigned int cam_i2c_scl_pp2_pins[] = { + TEGRA_PIN_CAM_I2C_SCL_PP2, +}; + +static const unsigned int cam_i2c_sda_pp3_pins[] = { + TEGRA_PIN_CAM_I2C_SDA_PP3, +}; + +static const unsigned int soc_gpio23_pp4_pins[] = { + TEGRA_PIN_SOC_GPIO23_PP4, +}; + +static const unsigned int soc_gpio24_pp5_pins[] = { + TEGRA_PIN_SOC_GPIO24_PP5, +}; + +static const unsigned int soc_gpio25_pp6_pins[] = { + TEGRA_PIN_SOC_GPIO25_PP6, +}; + +static const unsigned int pwr_i2c_scl_pp7_pins[] = { + TEGRA_PIN_PWR_I2C_SCL_PP7, +}; + +static const unsigned int pwr_i2c_sda_pq0_pins[] = { + TEGRA_PIN_PWR_I2C_SDA_PQ0, +}; + +static const unsigned int soc_gpio28_pq1_pins[] = { + TEGRA_PIN_SOC_GPIO28_PQ1, +}; + +static const unsigned int soc_gpio29_pq2_pins[] = { + TEGRA_PIN_SOC_GPIO29_PQ2, +}; + +static const unsigned int soc_gpio30_pq3_pins[] = { + TEGRA_PIN_SOC_GPIO30_PQ3, +}; + +static const unsigned int soc_gpio31_pq4_pins[] = { + TEGRA_PIN_SOC_GPIO31_PQ4, +}; + +static const unsigned int soc_gpio32_pq5_pins[] = { + TEGRA_PIN_SOC_GPIO32_PQ5, +}; + +static const unsigned int soc_gpio33_pq6_pins[] = { + TEGRA_PIN_SOC_GPIO33_PQ6, +}; + +static const unsigned int soc_gpio35_pq7_pins[] = { + TEGRA_PIN_SOC_GPIO35_PQ7, +}; + +static const unsigned int soc_gpio37_pr0_pins[] = { + TEGRA_PIN_SOC_GPIO37_PR0, +}; + +static const unsigned int soc_gpio56_pr1_pins[] = { + TEGRA_PIN_SOC_GPIO56_PR1, +}; + +static const unsigned int uart1_tx_pr2_pins[] = { + TEGRA_PIN_UART1_TX_PR2, +}; + +static const unsigned int uart1_rx_pr3_pins[] = { + TEGRA_PIN_UART1_RX_PR3, +}; + +static const unsigned int uart1_rts_pr4_pins[] = { + TEGRA_PIN_UART1_RTS_PR4, +}; + +static const unsigned int uart1_cts_pr5_pins[] = { + TEGRA_PIN_UART1_CTS_PR5, +}; + +static const unsigned int gpu_pwr_req_px0_pins[] = { + TEGRA_PIN_GPU_PWR_REQ_PX0, +}; + +static const unsigned int cv_pwr_req_px1_pins[] = { + TEGRA_PIN_CV_PWR_REQ_PX1, +}; + +static const unsigned int gp_pwm2_px2_pins[] = { + TEGRA_PIN_GP_PWM2_PX2, +}; + +static const unsigned int gp_pwm3_px3_pins[] = { + TEGRA_PIN_GP_PWM3_PX3, +}; + +static const unsigned int uart2_tx_px4_pins[] = { + TEGRA_PIN_UART2_TX_PX4, +}; + +static const unsigned int uart2_rx_px5_pins[] = { + TEGRA_PIN_UART2_RX_PX5, +}; + +static const unsigned int uart2_rts_px6_pins[] = { + TEGRA_PIN_UART2_RTS_PX6, +}; + +static const unsigned int uart2_cts_px7_pins[] = { + TEGRA_PIN_UART2_CTS_PX7, +}; + +static const unsigned int spi3_sck_py0_pins[] = { + TEGRA_PIN_SPI3_SCK_PY0, +}; + +static const unsigned int spi3_miso_py1_pins[] = { + TEGRA_PIN_SPI3_MISO_PY1, +}; + +static const unsigned int spi3_mosi_py2_pins[] = { + TEGRA_PIN_SPI3_MOSI_PY2, +}; + +static const unsigned int spi3_cs0_py3_pins[] = { + TEGRA_PIN_SPI3_CS0_PY3, +}; + +static const unsigned int spi3_cs1_py4_pins[] = { + TEGRA_PIN_SPI3_CS1_PY4, +}; + +static const unsigned int uart5_tx_py5_pins[] = { + TEGRA_PIN_UART5_TX_PY5, +}; + +static const unsigned int uart5_rx_py6_pins[] = { + TEGRA_PIN_UART5_RX_PY6, +}; + +static const unsigned int uart5_rts_py7_pins[] = { + TEGRA_PIN_UART5_RTS_PY7, +}; + +static const unsigned int uart5_cts_pz0_pins[] = { + TEGRA_PIN_UART5_CTS_PZ0, +}; + +static const unsigned int usb_vbus_en0_pz1_pins[] = { + TEGRA_PIN_USB_VBUS_EN0_PZ1, +}; + +static const unsigned int usb_vbus_en1_pz2_pins[] = { + TEGRA_PIN_USB_VBUS_EN1_PZ2, +}; + +static const unsigned int spi1_sck_pz3_pins[] = { + TEGRA_PIN_SPI1_SCK_PZ3, +}; + +static const unsigned int spi1_miso_pz4_pins[] = { + TEGRA_PIN_SPI1_MISO_PZ4, +}; + +static const unsigned int spi1_mosi_pz5_pins[] = { + TEGRA_PIN_SPI1_MOSI_PZ5, +}; + +static const unsigned int spi1_cs0_pz6_pins[] = { + TEGRA_PIN_SPI1_CS0_PZ6, +}; + +static const unsigned int spi1_cs1_pz7_pins[] = { + TEGRA_PIN_SPI1_CS1_PZ7, +}; + +static const unsigned int can0_dout_paa0_pins[] = { + TEGRA_PIN_CAN0_DOUT_PAA0, +}; + +static const unsigned int can0_din_paa1_pins[] = { + TEGRA_PIN_CAN0_DIN_PAA1, +}; + +static const unsigned int can1_dout_paa2_pins[] = { + TEGRA_PIN_CAN1_DOUT_PAA2, +}; + +static const unsigned int can1_din_paa3_pins[] = { + TEGRA_PIN_CAN1_DIN_PAA3, +}; + +static const unsigned int can0_stb_paa4_pins[] = { + TEGRA_PIN_CAN0_STB_PAA4, +}; + +static const unsigned int can0_en_paa5_pins[] = { + TEGRA_PIN_CAN0_EN_PAA5, +}; + +static const unsigned int soc_gpio49_paa6_pins[] = { + TEGRA_PIN_SOC_GPIO49_PAA6, +}; + +static const unsigned int can0_err_paa7_pins[] = { + TEGRA_PIN_CAN0_ERR_PAA7, +}; + +static const unsigned int spi5_sck_pac0_pins[] = { + TEGRA_PIN_SPI5_SCK_PAC0, +}; + +static const unsigned int spi5_miso_pac1_pins[] = { + TEGRA_PIN_SPI5_MISO_PAC1, +}; + +static const unsigned int spi5_mosi_pac2_pins[] = { + TEGRA_PIN_SPI5_MOSI_PAC2, +}; + +static const unsigned int spi5_cs0_pac3_pins[] = { + TEGRA_PIN_SPI5_CS0_PAC3, +}; + +static const unsigned int soc_gpio57_pac4_pins[] = { + TEGRA_PIN_SOC_GPIO57_PAC4, +}; + +static const unsigned int soc_gpio58_pac5_pins[] = { + TEGRA_PIN_SOC_GPIO58_PAC5, +}; + +static const unsigned int soc_gpio59_pac6_pins[] = { + TEGRA_PIN_SOC_GPIO59_PAC6, +}; + +static const unsigned int soc_gpio60_pac7_pins[] = { + TEGRA_PIN_SOC_GPIO60_PAC7, +}; + +static const unsigned int soc_gpio45_pad0_pins[] = { + TEGRA_PIN_SOC_GPIO45_PAD0, +}; + +static const unsigned int soc_gpio46_pad1_pins[] = { + TEGRA_PIN_SOC_GPIO46_PAD1, +}; + +static const unsigned int soc_gpio47_pad2_pins[] = { + TEGRA_PIN_SOC_GPIO47_PAD2, +}; + +static const unsigned int soc_gpio48_pad3_pins[] = { + TEGRA_PIN_SOC_GPIO48_PAD3, +}; + +static const unsigned int ufs0_ref_clk_pae0_pins[] = { + TEGRA_PIN_UFS0_REF_CLK_PAE0, +}; + +static const unsigned int ufs0_rst_n_pae1_pins[] = { + TEGRA_PIN_UFS0_RST_N_PAE1, +}; + +static const unsigned int pex_l5_clkreq_n_paf0_pins[] = { + TEGRA_PIN_PEX_L5_CLKREQ_N_PAF0, +}; + +static const unsigned int pex_l5_rst_n_paf1_pins[] = { + TEGRA_PIN_PEX_L5_RST_N_PAF1, +}; + +static const unsigned int pex_l6_clkreq_n_paf2_pins[] = { + TEGRA_PIN_PEX_L6_CLKREQ_N_PAF2, +}; + +static const unsigned int pex_l6_rst_n_paf3_pins[] = { + TEGRA_PIN_PEX_L6_RST_N_PAF3, +}; + +static const unsigned int pex_l7_clkreq_n_pag0_pins[] = { + TEGRA_PIN_PEX_L7_CLKREQ_N_PAG0, +}; + +static const unsigned int pex_l7_rst_n_pag1_pins[] = { + TEGRA_PIN_PEX_L7_RST_N_PAG1, +}; + +static const unsigned int pex_l8_clkreq_n_pag2_pins[] = { + TEGRA_PIN_PEX_L8_CLKREQ_N_PAG2, +}; + +static const unsigned int pex_l8_rst_n_pag3_pins[] = { + TEGRA_PIN_PEX_L8_RST_N_PAG3, +}; + +static const unsigned int pex_l9_clkreq_n_pag4_pins[] = { + TEGRA_PIN_PEX_L9_CLKREQ_N_PAG4, +}; + +static const unsigned int pex_l9_rst_n_pag5_pins[] = { + TEGRA_PIN_PEX_L9_RST_N_PAG5, +}; + +static const unsigned int pex_l10_clkreq_n_pag6_pins[] = { + TEGRA_PIN_PEX_L10_CLKREQ_N_PAG6, +}; + +static const unsigned int pex_l10_rst_n_pag7_pins[] = { + TEGRA_PIN_PEX_L10_RST_N_PAG7, +}; + +static const unsigned int can1_stb_pbb0_pins[] = { + TEGRA_PIN_CAN1_STB_PBB0, +}; + +static const unsigned int can1_en_pbb1_pins[] = { + TEGRA_PIN_CAN1_EN_PBB1, +}; + +static const unsigned int soc_gpio50_pbb2_pins[] = { + TEGRA_PIN_SOC_GPIO50_PBB2, +}; + +static const unsigned int can1_err_pbb3_pins[] = { + TEGRA_PIN_CAN1_ERR_PBB3, +}; + +static const unsigned int spi2_sck_pcc0_pins[] = { + TEGRA_PIN_SPI2_SCK_PCC0, +}; + +static const unsigned int spi2_miso_pcc1_pins[] = { + TEGRA_PIN_SPI2_MISO_PCC1, +}; + +static const unsigned int spi2_mosi_pcc2_pins[] = { + TEGRA_PIN_SPI2_MOSI_PCC2, +}; + +static const unsigned int spi2_cs0_pcc3_pins[] = { + TEGRA_PIN_SPI2_CS0_PCC3, +}; + +static const unsigned int touch_clk_pcc4_pins[] = { + TEGRA_PIN_TOUCH_CLK_PCC4, +}; + +static const unsigned int uart3_tx_pcc5_pins[] = { + TEGRA_PIN_UART3_TX_PCC5, +}; + +static const unsigned int uart3_rx_pcc6_pins[] = { + TEGRA_PIN_UART3_RX_PCC6, +}; + +static const unsigned int gen2_i2c_scl_pcc7_pins[] = { + TEGRA_PIN_GEN2_I2C_SCL_PCC7, +}; + +static const unsigned int gen2_i2c_sda_pdd0_pins[] = { + TEGRA_PIN_GEN2_I2C_SDA_PDD0, +}; + +static const unsigned int gen8_i2c_scl_pdd1_pins[] = { + TEGRA_PIN_GEN8_I2C_SCL_PDD1, +}; + +static const unsigned int gen8_i2c_sda_pdd2_pins[] = { + TEGRA_PIN_GEN8_I2C_SDA_PDD2, +}; + +static const unsigned int sce_error_pee0_pins[] = { + TEGRA_PIN_SCE_ERROR_PEE0, +}; + +static const unsigned int vcomp_alert_pee1_pins[] = { + TEGRA_PIN_VCOMP_ALERT_PEE1, +}; + +static const unsigned int ao_retention_n_pee2_pins[] = { + TEGRA_PIN_AO_RETENTION_N_PEE2, +}; + +static const unsigned int batt_oc_pee3_pins[] = { + TEGRA_PIN_BATT_OC_PEE3, +}; + +static const unsigned int power_on_pee4_pins[] = { + TEGRA_PIN_POWER_ON_PEE4, +}; + +static const unsigned int soc_gpio26_pee5_pins[] = { + TEGRA_PIN_SOC_GPIO26_PEE5, +}; + +static const unsigned int soc_gpio27_pee6_pins[] = { + TEGRA_PIN_SOC_GPIO27_PEE6, +}; + +static const unsigned int bootv_ctl_n_pee7_pins[] = { + TEGRA_PIN_BOOTV_CTL_N_PEE7, +}; + +static const unsigned int hdmi_cec_pgg0_pins[] = { + TEGRA_PIN_HDMI_CEC_PGG0, +}; + +static const unsigned int eqos_comp_pins[] = { + TEGRA_PIN_EQOS_COMP, +}; + +static const unsigned int qspi_comp_pins[] = { + TEGRA_PIN_QSPI_COMP, +}; + +static const unsigned int sdmmc1_comp_pins[] = { + TEGRA_PIN_SDMMC1_COMP, +}; + +/* Define unique ID for each function */ +enum tegra_mux_dt { + TEGRA_MUX_GP, + TEGRA_MUX_UARTC, + TEGRA_MUX_I2C8, + TEGRA_MUX_SPI2, + TEGRA_MUX_I2C2, + TEGRA_MUX_CAN1, + TEGRA_MUX_CAN0, + TEGRA_MUX_RSVD0, + TEGRA_MUX_ETH0, + TEGRA_MUX_ETH2, + TEGRA_MUX_ETH1, + TEGRA_MUX_DP, + TEGRA_MUX_ETH3, + TEGRA_MUX_I2C4, + TEGRA_MUX_I2C7, + TEGRA_MUX_I2C9, + TEGRA_MUX_EQOS, + TEGRA_MUX_PE2, + TEGRA_MUX_PE1, + TEGRA_MUX_PE0, + TEGRA_MUX_PE3, + TEGRA_MUX_PE4, + TEGRA_MUX_PE5, + TEGRA_MUX_PE6, + TEGRA_MUX_PE10, + TEGRA_MUX_PE7, + TEGRA_MUX_PE8, + TEGRA_MUX_PE9, + TEGRA_MUX_QSPI0, + TEGRA_MUX_QSPI1, + TEGRA_MUX_QSPI, + TEGRA_MUX_SDMMC1, + TEGRA_MUX_SCE, + TEGRA_MUX_SOC, + TEGRA_MUX_GPIO, + TEGRA_MUX_HDMI, + TEGRA_MUX_UFS0, + TEGRA_MUX_SPI3, + TEGRA_MUX_SPI1, + TEGRA_MUX_UARTB, + TEGRA_MUX_UARTE, + TEGRA_MUX_USB, + TEGRA_MUX_EXTPERIPH2, + TEGRA_MUX_EXTPERIPH1, + TEGRA_MUX_I2C3, + TEGRA_MUX_VI0, + TEGRA_MUX_I2C5, + TEGRA_MUX_UARTA, + TEGRA_MUX_UARTD, + TEGRA_MUX_I2C1, + TEGRA_MUX_I2S4, + TEGRA_MUX_I2S6, + TEGRA_MUX_AUD, + TEGRA_MUX_SPI5, + TEGRA_MUX_TOUCH, + TEGRA_MUX_UARTJ, + TEGRA_MUX_RSVD1, + TEGRA_MUX_WDT, + TEGRA_MUX_TSC, + TEGRA_MUX_DMIC3, + TEGRA_MUX_LED, + TEGRA_MUX_VI0_ALT, + TEGRA_MUX_I2S5, + TEGRA_MUX_NV, + TEGRA_MUX_EXTPERIPH3, + TEGRA_MUX_EXTPERIPH4, + TEGRA_MUX_SPI4, + TEGRA_MUX_CCLA, + TEGRA_MUX_I2S2, + TEGRA_MUX_I2S1, + TEGRA_MUX_I2S8, + TEGRA_MUX_I2S3, + TEGRA_MUX_RSVD2, + TEGRA_MUX_DMIC5, + TEGRA_MUX_DCA, + TEGRA_MUX_DISPLAYB, + TEGRA_MUX_DISPLAYA, + TEGRA_MUX_VI1, + TEGRA_MUX_DCB, + TEGRA_MUX_DMIC1, + TEGRA_MUX_DMIC4, + TEGRA_MUX_I2S7, + TEGRA_MUX_DMIC2, + TEGRA_MUX_DSPK0, + TEGRA_MUX_RSVD3, + TEGRA_MUX_TSC_ALT, + TEGRA_MUX_ISTCTRL, + TEGRA_MUX_VI1_ALT, + TEGRA_MUX_DSPK1, + TEGRA_MUX_IGPU, +}; + +/* Make list of each function name */ +#define TEGRA_PIN_FUNCTION(lid) #lid + +static const char * const tegra234_functions[] = { + TEGRA_PIN_FUNCTION(gp), + TEGRA_PIN_FUNCTION(uartc), + TEGRA_PIN_FUNCTION(i2c8), + TEGRA_PIN_FUNCTION(spi2), + TEGRA_PIN_FUNCTION(i2c2), + TEGRA_PIN_FUNCTION(can1), + TEGRA_PIN_FUNCTION(can0), + TEGRA_PIN_FUNCTION(rsvd0), + TEGRA_PIN_FUNCTION(eth0), + TEGRA_PIN_FUNCTION(eth2), + TEGRA_PIN_FUNCTION(eth1), + TEGRA_PIN_FUNCTION(dp), + TEGRA_PIN_FUNCTION(eth3), + TEGRA_PIN_FUNCTION(i2c4), + TEGRA_PIN_FUNCTION(i2c7), + TEGRA_PIN_FUNCTION(i2c9), + TEGRA_PIN_FUNCTION(eqos), + TEGRA_PIN_FUNCTION(pe2), + TEGRA_PIN_FUNCTION(pe1), + TEGRA_PIN_FUNCTION(pe0), + TEGRA_PIN_FUNCTION(pe3), + TEGRA_PIN_FUNCTION(pe4), + TEGRA_PIN_FUNCTION(pe5), + TEGRA_PIN_FUNCTION(pe6), + TEGRA_PIN_FUNCTION(pe10), + TEGRA_PIN_FUNCTION(pe7), + TEGRA_PIN_FUNCTION(pe8), + TEGRA_PIN_FUNCTION(pe9), + TEGRA_PIN_FUNCTION(qspi0), + TEGRA_PIN_FUNCTION(qspi1), + TEGRA_PIN_FUNCTION(qspi), + TEGRA_PIN_FUNCTION(sdmmc1), + TEGRA_PIN_FUNCTION(sce), + TEGRA_PIN_FUNCTION(soc), + TEGRA_PIN_FUNCTION(gpio), + TEGRA_PIN_FUNCTION(hdmi), + TEGRA_PIN_FUNCTION(ufs0), + TEGRA_PIN_FUNCTION(spi3), + TEGRA_PIN_FUNCTION(spi1), + TEGRA_PIN_FUNCTION(uartb), + TEGRA_PIN_FUNCTION(uarte), + TEGRA_PIN_FUNCTION(usb), + TEGRA_PIN_FUNCTION(extperiph2), + TEGRA_PIN_FUNCTION(extperiph1), + TEGRA_PIN_FUNCTION(i2c3), + TEGRA_PIN_FUNCTION(vi0), + TEGRA_PIN_FUNCTION(i2c5), + TEGRA_PIN_FUNCTION(uarta), + TEGRA_PIN_FUNCTION(uartd), + TEGRA_PIN_FUNCTION(i2c1), + TEGRA_PIN_FUNCTION(i2s4), + TEGRA_PIN_FUNCTION(i2s6), + TEGRA_PIN_FUNCTION(aud), + TEGRA_PIN_FUNCTION(spi5), + TEGRA_PIN_FUNCTION(touch), + TEGRA_PIN_FUNCTION(uartj), + TEGRA_PIN_FUNCTION(rsvd1), + TEGRA_PIN_FUNCTION(wdt), + TEGRA_PIN_FUNCTION(tsc), + TEGRA_PIN_FUNCTION(dmic3), + TEGRA_PIN_FUNCTION(led), + TEGRA_PIN_FUNCTION(vi0_alt), + TEGRA_PIN_FUNCTION(i2s5), + TEGRA_PIN_FUNCTION(nv), + TEGRA_PIN_FUNCTION(extperiph3), + TEGRA_PIN_FUNCTION(extperiph4), + TEGRA_PIN_FUNCTION(spi4), + TEGRA_PIN_FUNCTION(ccla), + TEGRA_PIN_FUNCTION(i2s2), + TEGRA_PIN_FUNCTION(i2s1), + TEGRA_PIN_FUNCTION(i2s8), + TEGRA_PIN_FUNCTION(i2s3), + TEGRA_PIN_FUNCTION(rsvd2), + TEGRA_PIN_FUNCTION(dmic5), + TEGRA_PIN_FUNCTION(dca), + TEGRA_PIN_FUNCTION(displayb), + TEGRA_PIN_FUNCTION(displaya), + TEGRA_PIN_FUNCTION(vi1), + TEGRA_PIN_FUNCTION(dcb), + TEGRA_PIN_FUNCTION(dmic1), + TEGRA_PIN_FUNCTION(dmic4), + TEGRA_PIN_FUNCTION(i2s7), + TEGRA_PIN_FUNCTION(dmic2), + TEGRA_PIN_FUNCTION(dspk0), + TEGRA_PIN_FUNCTION(rsvd3), + TEGRA_PIN_FUNCTION(tsc_alt), + TEGRA_PIN_FUNCTION(istctrl), + TEGRA_PIN_FUNCTION(vi1_alt), + TEGRA_PIN_FUNCTION(dspk1), + TEGRA_PIN_FUNCTION(igpu), +}; + +#define PINGROUP_REG_Y(r) ((r)) +#define PINGROUP_REG_N(r) -1 + +#define DRV_PINGROUP_Y(r) ((r)) +#define DRV_PINGROUP_N(r) -1 + +#define DRV_PINGROUP_ENTRY_N(pg_name) \ + .drv_reg = -1, \ + .drv_bank = -1, \ + .drvdn_bit = -1, \ + .drvup_bit = -1, \ + .slwr_bit = -1, \ + .slwf_bit = -1 + +#define DRV_PINGROUP_ENTRY_Y(r, drvdn_b, drvdn_w, drvup_b, \ + drvup_w, slwr_b, slwr_w, slwf_b, \ + slwf_w, bank) \ + .drv_reg = DRV_PINGROUP_Y(r), \ + .drv_bank = bank, \ + .drvdn_bit = drvdn_b, \ + .drvdn_width = drvdn_w, \ + .drvup_bit = drvup_b, \ + .drvup_width = drvup_w, \ + .slwr_bit = slwr_b, \ + .slwr_width = slwr_w, \ + .slwf_bit = slwf_b, \ + .slwf_width = slwf_w + +#define PIN_PINGROUP_ENTRY_N(pg_name) \ + .mux_reg = -1, \ + .pupd_reg = -1, \ + .tri_reg = -1, \ + .einput_bit = -1, \ + .e_io_hv_bit = -1, \ + .odrain_bit = -1, \ + .lock_bit = -1, \ + .parked_bit = -1, \ + .lpmd_bit = -1, \ + .drvtype_bit = -1, \ + .lpdr_bit = -1, \ + .pbias_buf_bit = -1, \ + .preemp_bit = -1, \ + .rfu_in_bit = -1 + +#define PIN_PINGROUP_ENTRY_Y(r, bank, pupd, e_io_hv, e_lpbk, e_input, \ + e_lpdr, e_pbias_buf, gpio_sfio_sel, \ + schmitt_b) \ + .mux_reg = PINGROUP_REG_Y(r), \ + .lpmd_bit = -1, \ + .lock_bit = -1, \ + .hsm_bit = -1, \ + .mux_bank = bank, \ + .mux_bit = 0, \ + .pupd_reg = PINGROUP_REG_##pupd(r), \ + .pupd_bank = bank, \ + .pupd_bit = 2, \ + .tri_reg = PINGROUP_REG_Y(r), \ + .tri_bank = bank, \ + .tri_bit = 4, \ + .einput_bit = e_input, \ + .sfsel_bit = gpio_sfio_sel, \ + .schmitt_bit = schmitt_b, \ + .drvtype_bit = 13, \ + .lpdr_bit = e_lpdr, \ + +/* main drive pin groups */ +#define drive_soc_gpio08_pb0 DRV_PINGROUP_ENTRY_Y(0x500c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_soc_gpio36_pm5 DRV_PINGROUP_ENTRY_Y(0x10004, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_soc_gpio53_pm6 DRV_PINGROUP_ENTRY_Y(0x1000c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_soc_gpio55_pm4 DRV_PINGROUP_ENTRY_Y(0x10014, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_soc_gpio38_pm7 DRV_PINGROUP_ENTRY_Y(0x1001c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_soc_gpio39_pn1 DRV_PINGROUP_ENTRY_Y(0x10024, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_soc_gpio40_pn2 DRV_PINGROUP_ENTRY_Y(0x1002c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_dp_aux_ch0_hpd_pm0 DRV_PINGROUP_ENTRY_Y(0x10034, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_dp_aux_ch1_hpd_pm1 DRV_PINGROUP_ENTRY_Y(0x1003c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_dp_aux_ch2_hpd_pm2 DRV_PINGROUP_ENTRY_Y(0x10044, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_dp_aux_ch3_hpd_pm3 DRV_PINGROUP_ENTRY_Y(0x1004c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_dp_aux_ch1_p_pn3 DRV_PINGROUP_ENTRY_Y(0x10054, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_dp_aux_ch1_n_pn4 DRV_PINGROUP_ENTRY_Y(0x1005c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_dp_aux_ch2_p_pn5 DRV_PINGROUP_ENTRY_Y(0x10064, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_dp_aux_ch2_n_pn6 DRV_PINGROUP_ENTRY_Y(0x1006c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_dp_aux_ch3_p_pn7 DRV_PINGROUP_ENTRY_Y(0x10074, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_dp_aux_ch3_n_pn0 DRV_PINGROUP_ENTRY_Y(0x1007c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_pex_l2_clkreq_n_pk4 DRV_PINGROUP_ENTRY_Y(0x7004, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_pex_wake_n_pl2 DRV_PINGROUP_ENTRY_Y(0x700c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_pex_l1_clkreq_n_pk2 DRV_PINGROUP_ENTRY_Y(0x7014, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_pex_l1_rst_n_pk3 DRV_PINGROUP_ENTRY_Y(0x701c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_pex_l0_clkreq_n_pk0 DRV_PINGROUP_ENTRY_Y(0x7024, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_pex_l0_rst_n_pk1 DRV_PINGROUP_ENTRY_Y(0x702c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_pex_l2_rst_n_pk5 DRV_PINGROUP_ENTRY_Y(0x7034, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_pex_l3_clkreq_n_pk6 DRV_PINGROUP_ENTRY_Y(0x703c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_pex_l3_rst_n_pk7 DRV_PINGROUP_ENTRY_Y(0x7044, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_pex_l4_clkreq_n_pl0 DRV_PINGROUP_ENTRY_Y(0x704c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_pex_l4_rst_n_pl1 DRV_PINGROUP_ENTRY_Y(0x7054, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_soc_gpio34_pl3 DRV_PINGROUP_ENTRY_Y(0x705c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_pex_l5_clkreq_n_paf0 DRV_PINGROUP_ENTRY_Y(0x14004, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_pex_l5_rst_n_paf1 DRV_PINGROUP_ENTRY_Y(0x1400c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_pex_l6_clkreq_n_paf2 DRV_PINGROUP_ENTRY_Y(0x14014, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_pex_l6_rst_n_paf3 DRV_PINGROUP_ENTRY_Y(0x1401c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_pex_l10_clkreq_n_pag6 DRV_PINGROUP_ENTRY_Y(0x19004, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_pex_l10_rst_n_pag7 DRV_PINGROUP_ENTRY_Y(0x1900c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_pex_l7_clkreq_n_pag0 DRV_PINGROUP_ENTRY_Y(0x19014, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_pex_l7_rst_n_pag1 DRV_PINGROUP_ENTRY_Y(0x1901c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_pex_l8_clkreq_n_pag2 DRV_PINGROUP_ENTRY_Y(0x19024, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_pex_l8_rst_n_pag3 DRV_PINGROUP_ENTRY_Y(0x1902c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_pex_l9_clkreq_n_pag4 DRV_PINGROUP_ENTRY_Y(0x19034, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_pex_l9_rst_n_pag5 DRV_PINGROUP_ENTRY_Y(0x1903c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_sdmmc1_clk_pj0 DRV_PINGROUP_ENTRY_Y(0x8004, 28, 2, 30, 2, -1, -1, -1, -1, 0) +#define drive_sdmmc1_cmd_pj1 DRV_PINGROUP_ENTRY_Y(0x800c, 28, 2, 30, 2, -1, -1, -1, -1, 0) +#define drive_sdmmc1_dat3_pj5 DRV_PINGROUP_ENTRY_Y(0x801c, 28, 2, 30, 2, -1, -1, -1, -1, 0) +#define drive_sdmmc1_dat2_pj4 DRV_PINGROUP_ENTRY_Y(0x8024, 28, 2, 30, 2, -1, -1, -1, -1, 0) +#define drive_sdmmc1_dat1_pj3 DRV_PINGROUP_ENTRY_Y(0x802c, 28, 2, 30, 2, -1, -1, -1, -1, 0) +#define drive_sdmmc1_dat0_pj2 DRV_PINGROUP_ENTRY_Y(0x8034, 28, 2, 30, 2, -1, -1, -1, -1, 0) +#define drive_ufs0_rst_n_pae1 DRV_PINGROUP_ENTRY_Y(0x11004, 12, 5, 24, 5, -1, -1, -1, -1, 0) +#define drive_ufs0_ref_clk_pae0 DRV_PINGROUP_ENTRY_Y(0x1100c, 12, 5, 24, 5, -1, -1, -1, -1, 0) +#define drive_spi3_miso_py1 DRV_PINGROUP_ENTRY_Y(0xd004, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_spi1_cs0_pz6 DRV_PINGROUP_ENTRY_Y(0xd00c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_spi3_cs0_py3 DRV_PINGROUP_ENTRY_Y(0xd014, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_spi1_miso_pz4 DRV_PINGROUP_ENTRY_Y(0xd01c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_spi3_cs1_py4 DRV_PINGROUP_ENTRY_Y(0xd024, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_spi1_sck_pz3 DRV_PINGROUP_ENTRY_Y(0xd02c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_spi3_sck_py0 DRV_PINGROUP_ENTRY_Y(0xd034, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_spi1_cs1_pz7 DRV_PINGROUP_ENTRY_Y(0xd03c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_spi1_mosi_pz5 DRV_PINGROUP_ENTRY_Y(0xd044, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_spi3_mosi_py2 DRV_PINGROUP_ENTRY_Y(0xd04c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_uart2_tx_px4 DRV_PINGROUP_ENTRY_Y(0xd054, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_uart2_rx_px5 DRV_PINGROUP_ENTRY_Y(0xd05c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_uart2_rts_px6 DRV_PINGROUP_ENTRY_Y(0xd064, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_uart2_cts_px7 DRV_PINGROUP_ENTRY_Y(0xd06c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_uart5_tx_py5 DRV_PINGROUP_ENTRY_Y(0xd074, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_uart5_rx_py6 DRV_PINGROUP_ENTRY_Y(0xd07c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_uart5_rts_py7 DRV_PINGROUP_ENTRY_Y(0xd084, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_uart5_cts_pz0 DRV_PINGROUP_ENTRY_Y(0xd08c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_gpu_pwr_req_px0 DRV_PINGROUP_ENTRY_Y(0xd094, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_gp_pwm3_px3 DRV_PINGROUP_ENTRY_Y(0xd09c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_gp_pwm2_px2 DRV_PINGROUP_ENTRY_Y(0xd0a4, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_cv_pwr_req_px1 DRV_PINGROUP_ENTRY_Y(0xd0ac, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_usb_vbus_en0_pz1 DRV_PINGROUP_ENTRY_Y(0xd0b4, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_usb_vbus_en1_pz2 DRV_PINGROUP_ENTRY_Y(0xd0bc, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_extperiph2_clk_pp1 DRV_PINGROUP_ENTRY_Y(0x0004, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_extperiph1_clk_pp0 DRV_PINGROUP_ENTRY_Y(0x000c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_cam_i2c_sda_pp3 DRV_PINGROUP_ENTRY_Y(0x0014, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_cam_i2c_scl_pp2 DRV_PINGROUP_ENTRY_Y(0x001c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_soc_gpio23_pp4 DRV_PINGROUP_ENTRY_Y(0x0024, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_soc_gpio24_pp5 DRV_PINGROUP_ENTRY_Y(0x002c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_soc_gpio25_pp6 DRV_PINGROUP_ENTRY_Y(0x0034, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_pwr_i2c_scl_pp7 DRV_PINGROUP_ENTRY_Y(0x003c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_pwr_i2c_sda_pq0 DRV_PINGROUP_ENTRY_Y(0x0044, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_soc_gpio28_pq1 DRV_PINGROUP_ENTRY_Y(0x004c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_soc_gpio29_pq2 DRV_PINGROUP_ENTRY_Y(0x0054, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_soc_gpio30_pq3 DRV_PINGROUP_ENTRY_Y(0x005c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_soc_gpio31_pq4 DRV_PINGROUP_ENTRY_Y(0x0064, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_soc_gpio32_pq5 DRV_PINGROUP_ENTRY_Y(0x006c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_soc_gpio33_pq6 DRV_PINGROUP_ENTRY_Y(0x0074, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_soc_gpio35_pq7 DRV_PINGROUP_ENTRY_Y(0x007c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_soc_gpio37_pr0 DRV_PINGROUP_ENTRY_Y(0x0084, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_soc_gpio56_pr1 DRV_PINGROUP_ENTRY_Y(0x008c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_uart1_cts_pr5 DRV_PINGROUP_ENTRY_Y(0x0094, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_uart1_rts_pr4 DRV_PINGROUP_ENTRY_Y(0x009c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_uart1_rx_pr3 DRV_PINGROUP_ENTRY_Y(0x00a4, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_uart1_tx_pr2 DRV_PINGROUP_ENTRY_Y(0x00ac, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_cpu_pwr_req_pi5 DRV_PINGROUP_ENTRY_Y(0x4004, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_uart4_cts_ph6 DRV_PINGROUP_ENTRY_Y(0x400c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_uart4_rts_ph5 DRV_PINGROUP_ENTRY_Y(0x4014, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_uart4_rx_ph4 DRV_PINGROUP_ENTRY_Y(0x401c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_uart4_tx_ph3 DRV_PINGROUP_ENTRY_Y(0x4024, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_gen1_i2c_scl_pi3 DRV_PINGROUP_ENTRY_Y(0x402c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_gen1_i2c_sda_pi4 DRV_PINGROUP_ENTRY_Y(0x4034, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_soc_gpio20_pg7 DRV_PINGROUP_ENTRY_Y(0x403c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_soc_gpio21_ph0 DRV_PINGROUP_ENTRY_Y(0x4044, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_soc_gpio22_ph1 DRV_PINGROUP_ENTRY_Y(0x404c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_soc_gpio13_pg0 DRV_PINGROUP_ENTRY_Y(0x4054, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_soc_gpio14_pg1 DRV_PINGROUP_ENTRY_Y(0x405c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_soc_gpio15_pg2 DRV_PINGROUP_ENTRY_Y(0x4064, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_soc_gpio16_pg3 DRV_PINGROUP_ENTRY_Y(0x406c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_soc_gpio17_pg4 DRV_PINGROUP_ENTRY_Y(0x4074, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_soc_gpio18_pg5 DRV_PINGROUP_ENTRY_Y(0x407c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_soc_gpio19_pg6 DRV_PINGROUP_ENTRY_Y(0x4084, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_soc_gpio41_ph7 DRV_PINGROUP_ENTRY_Y(0x408c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_soc_gpio42_pi0 DRV_PINGROUP_ENTRY_Y(0x4094, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_soc_gpio43_pi1 DRV_PINGROUP_ENTRY_Y(0x409c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_soc_gpio44_pi2 DRV_PINGROUP_ENTRY_Y(0x40a4, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_soc_gpio06_ph2 DRV_PINGROUP_ENTRY_Y(0x40ac, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_soc_gpio07_pi6 DRV_PINGROUP_ENTRY_Y(0x40b4, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_dap4_sclk_pa4 DRV_PINGROUP_ENTRY_Y(0x2004, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_dap4_dout_pa5 DRV_PINGROUP_ENTRY_Y(0x200c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_dap4_din_pa6 DRV_PINGROUP_ENTRY_Y(0x2014, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_dap4_fs_pa7 DRV_PINGROUP_ENTRY_Y(0x201c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_dap6_sclk_pa0 DRV_PINGROUP_ENTRY_Y(0x2024, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_dap6_dout_pa1 DRV_PINGROUP_ENTRY_Y(0x202c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_dap6_din_pa2 DRV_PINGROUP_ENTRY_Y(0x2034, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_dap6_fs_pa3 DRV_PINGROUP_ENTRY_Y(0x203c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_soc_gpio45_pad0 DRV_PINGROUP_ENTRY_Y(0x18004, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_soc_gpio46_pad1 DRV_PINGROUP_ENTRY_Y(0x1800c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_soc_gpio47_pad2 DRV_PINGROUP_ENTRY_Y(0x18014, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_soc_gpio48_pad3 DRV_PINGROUP_ENTRY_Y(0x1801c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_soc_gpio57_pac4 DRV_PINGROUP_ENTRY_Y(0x18024, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_soc_gpio58_pac5 DRV_PINGROUP_ENTRY_Y(0x1802c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_soc_gpio59_pac6 DRV_PINGROUP_ENTRY_Y(0x18034, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_soc_gpio60_pac7 DRV_PINGROUP_ENTRY_Y(0x1803c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_spi5_cs0_pac3 DRV_PINGROUP_ENTRY_Y(0x18044, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_spi5_miso_pac1 DRV_PINGROUP_ENTRY_Y(0x1804c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_spi5_mosi_pac2 DRV_PINGROUP_ENTRY_Y(0x18054, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_spi5_sck_pac0 DRV_PINGROUP_ENTRY_Y(0x1805c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_eqos_td3_pe4 DRV_PINGROUP_ENTRY_N(no_entry) +#define drive_eqos_td2_pe3 DRV_PINGROUP_ENTRY_N(no_entry) +#define drive_eqos_td1_pe2 DRV_PINGROUP_ENTRY_N(no_entry) +#define drive_eqos_td0_pe1 DRV_PINGROUP_ENTRY_N(no_entry) +#define drive_eqos_rd3_pf1 DRV_PINGROUP_ENTRY_N(no_entry) +#define drive_eqos_rd2_pf0 DRV_PINGROUP_ENTRY_N(no_entry) +#define drive_eqos_rd1_pe7 DRV_PINGROUP_ENTRY_N(no_entry) +#define drive_eqos_sma_mdio_pf4 DRV_PINGROUP_ENTRY_N(no_entry) +#define drive_eqos_rd0_pe6 DRV_PINGROUP_ENTRY_N(no_entry) +#define drive_eqos_sma_mdc_pf5 DRV_PINGROUP_ENTRY_N(no_entry) +#define drive_eqos_comp DRV_PINGROUP_ENTRY_N(no_entry) +#define drive_eqos_txc_pe0 DRV_PINGROUP_ENTRY_N(no_entry) +#define drive_eqos_rxc_pf3 DRV_PINGROUP_ENTRY_N(no_entry) +#define drive_eqos_tx_ctl_pe5 DRV_PINGROUP_ENTRY_N(no_entry) +#define drive_eqos_rx_ctl_pf2 DRV_PINGROUP_ENTRY_N(no_entry) +#define drive_qspi0_io3_pc5 DRV_PINGROUP_ENTRY_N(no_entry) +#define drive_qspi0_io2_pc4 DRV_PINGROUP_ENTRY_N(no_entry) +#define drive_qspi0_io1_pc3 DRV_PINGROUP_ENTRY_N(no_entry) +#define drive_qspi0_io0_pc2 DRV_PINGROUP_ENTRY_N(no_entry) +#define drive_qspi0_sck_pc0 DRV_PINGROUP_ENTRY_N(no_entry) +#define drive_qspi0_cs_n_pc1 DRV_PINGROUP_ENTRY_N(no_entry) +#define drive_qspi1_io3_pd3 DRV_PINGROUP_ENTRY_N(no_entry) +#define drive_qspi1_io2_pd2 DRV_PINGROUP_ENTRY_N(no_entry) +#define drive_qspi1_io1_pd1 DRV_PINGROUP_ENTRY_N(no_entry) +#define drive_qspi1_io0_pd0 DRV_PINGROUP_ENTRY_N(no_entry) +#define drive_qspi1_sck_pc6 DRV_PINGROUP_ENTRY_N(no_entry) +#define drive_qspi1_cs_n_pc7 DRV_PINGROUP_ENTRY_N(no_entry) +#define drive_qspi_comp DRV_PINGROUP_ENTRY_N(no_entry) +#define drive_sdmmc1_comp DRV_PINGROUP_ENTRY_N(no_entry) + +#define PINGROUP(pg_name, f0, f1, f2, f3, r, bank, pupd, e_io_hv, e_lpbk, e_input, e_lpdr, e_pbias_buf, \ + gpio_sfio_sel, schmitt_b) \ + { \ + .name = #pg_name, \ + .pins = pg_name##_pins, \ + .npins = ARRAY_SIZE(pg_name##_pins), \ + .funcs = { \ + TEGRA_MUX_##f0, \ + TEGRA_MUX_##f1, \ + TEGRA_MUX_##f2, \ + TEGRA_MUX_##f3, \ + }, \ + PIN_PINGROUP_ENTRY_Y(r, bank, pupd, e_io_hv, e_lpbk, \ + e_input, e_lpdr, e_pbias_buf, \ + gpio_sfio_sel, schmitt_b) \ + drive_##pg_name, \ + } + +static const struct tegra_pingroup tegra234_groups[] = { + PINGROUP(soc_gpio08_pb0, RSVD0, RSVD1, RSVD2, RSVD3, 0x5008, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(soc_gpio36_pm5, ETH0, RSVD1, DCA, RSVD3, 0x10000, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(soc_gpio53_pm6, ETH0, RSVD1, DCA, RSVD3, 0x10008, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(soc_gpio55_pm4, ETH2, RSVD1, RSVD2, RSVD3, 0x10010, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(soc_gpio38_pm7, ETH1, RSVD1, RSVD2, RSVD3, 0x10018, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(soc_gpio39_pn1, GP, RSVD1, RSVD2, RSVD3, 0x10020, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(soc_gpio40_pn2, ETH1, RSVD1, RSVD2, RSVD3, 0x10028, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(dp_aux_ch0_hpd_pm0, DP, RSVD1, RSVD2, RSVD3, 0x10030, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(dp_aux_ch1_hpd_pm1, ETH3, RSVD1, RSVD2, RSVD3, 0x10038, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(dp_aux_ch2_hpd_pm2, ETH3, RSVD1, DISPLAYB, RSVD3, 0x10040, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(dp_aux_ch3_hpd_pm3, ETH2, RSVD1, DISPLAYA, RSVD3, 0x10048, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(dp_aux_ch1_p_pn3, I2C4, RSVD1, RSVD2, RSVD3, 0x10050, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(dp_aux_ch1_n_pn4, I2C4, RSVD1, RSVD2, RSVD3, 0x10058, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(dp_aux_ch2_p_pn5, I2C7, RSVD1, RSVD2, RSVD3, 0x10060, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(dp_aux_ch2_n_pn6, I2C7, RSVD1, RSVD2, RSVD3, 0x10068, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(dp_aux_ch3_p_pn7, I2C9, RSVD1, RSVD2, RSVD3, 0x10070, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(dp_aux_ch3_n_pn0, I2C9, RSVD1, RSVD2, RSVD3, 0x10078, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(eqos_td3_pe4, EQOS, RSVD1, RSVD2, RSVD3, 0x15000, 0, Y, -1, 5, 6, -1, -1, 10, 12), + PINGROUP(eqos_td2_pe3, EQOS, RSVD1, RSVD2, RSVD3, 0x15008, 0, Y, -1, 5, 6, -1, -1, 10, 12), + PINGROUP(eqos_td1_pe2, EQOS, RSVD1, RSVD2, RSVD3, 0x15010, 0, Y, -1, 5, 6, -1, -1, 10, 12), + PINGROUP(eqos_td0_pe1, EQOS, RSVD1, RSVD2, RSVD3, 0x15018, 0, Y, -1, 5, 6, -1, -1, 10, 12), + PINGROUP(eqos_rd3_pf1, EQOS, RSVD1, RSVD2, RSVD3, 0x15020, 0, Y, -1, 5, 6, -1, -1, 10, 12), + PINGROUP(eqos_rd2_pf0, EQOS, RSVD1, RSVD2, RSVD3, 0x15028, 0, Y, -1, 5, 6, -1, -1, 10, 12), + PINGROUP(eqos_rd1_pe7, EQOS, RSVD1, RSVD2, RSVD3, 0x15030, 0, Y, -1, 5, 6, -1, -1, 10, 12), + PINGROUP(eqos_sma_mdio_pf4, EQOS, RSVD1, RSVD2, RSVD3, 0x15038, 0, Y, -1, 5, 6, -1, -1, 10, 12), + PINGROUP(eqos_rd0_pe6, EQOS, RSVD1, RSVD2, RSVD3, 0x15040, 0, Y, -1, 5, 6, -1, -1, 10, 12), + PINGROUP(eqos_sma_mdc_pf5, EQOS, RSVD1, RSVD2, RSVD3, 0x15048, 0, Y, -1, 5, 6, -1, -1, 10, 12), + PINGROUP(eqos_comp, EQOS, RSVD1, RSVD2, RSVD3, 0x15050, 0, N, -1, -1, -1, -1, -1, -1, -1), + PINGROUP(eqos_txc_pe0, EQOS, RSVD1, RSVD2, RSVD3, 0x15058, 0, Y, -1, 5, 6, -1, -1, 10, 12), + PINGROUP(eqos_rxc_pf3, EQOS, RSVD1, RSVD2, RSVD3, 0x15060, 0, Y, -1, 5, 6, -1, -1, 10, 12), + PINGROUP(eqos_tx_ctl_pe5, EQOS, RSVD1, RSVD2, RSVD3, 0x15068, 0, Y, -1, 5, 6, -1, -1, 10, 12), + PINGROUP(eqos_rx_ctl_pf2, EQOS, RSVD1, RSVD2, RSVD3, 0x15070, 0, Y, -1, 5, 6, -1, -1, 10, 12), + PINGROUP(pex_l2_clkreq_n_pk4, PE2, RSVD1, RSVD2, RSVD3, 0x7000, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(pex_wake_n_pl2, RSVD0, RSVD1, RSVD2, RSVD3, 0x7008, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(pex_l1_clkreq_n_pk2, PE1, RSVD1, RSVD2, RSVD3, 0x7010, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(pex_l1_rst_n_pk3, PE1, RSVD1, RSVD2, RSVD3, 0x7018, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(pex_l0_clkreq_n_pk0, PE0, RSVD1, RSVD2, RSVD3, 0x7020, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(pex_l0_rst_n_pk1, PE0, RSVD1, RSVD2, RSVD3, 0x7028, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(pex_l2_rst_n_pk5, PE2, RSVD1, RSVD2, RSVD3, 0x7030, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(pex_l3_clkreq_n_pk6, PE3, RSVD1, RSVD2, RSVD3, 0x7038, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(pex_l3_rst_n_pk7, PE3, RSVD1, RSVD2, RSVD3, 0x7040, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(pex_l4_clkreq_n_pl0, PE4, RSVD1, RSVD2, RSVD3, 0x7048, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(pex_l4_rst_n_pl1, PE4, RSVD1, RSVD2, RSVD3, 0x7050, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(soc_gpio34_pl3, RSVD0, RSVD1, RSVD2, RSVD3, 0x7058, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(pex_l5_clkreq_n_paf0, PE5, RSVD1, RSVD2, RSVD3, 0x14000, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(pex_l5_rst_n_paf1, PE5, RSVD1, RSVD2, RSVD3, 0x14008, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(pex_l6_clkreq_n_paf2, PE6, RSVD1, RSVD2, RSVD3, 0x14010, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(pex_l6_rst_n_paf3, PE6, RSVD1, RSVD2, RSVD3, 0x14018, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(pex_l10_clkreq_n_pag6, PE10, RSVD1, RSVD2, RSVD3, 0x19000, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(pex_l10_rst_n_pag7, PE10, RSVD1, RSVD2, RSVD3, 0x19008, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(pex_l7_clkreq_n_pag0, PE7, RSVD1, RSVD2, RSVD3, 0x19010, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(pex_l7_rst_n_pag1, PE7, RSVD1, RSVD2, RSVD3, 0x19018, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(pex_l8_clkreq_n_pag2, PE8, RSVD1, RSVD2, RSVD3, 0x19020, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(pex_l8_rst_n_pag3, PE8, RSVD1, RSVD2, RSVD3, 0x19028, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(pex_l9_clkreq_n_pag4, PE9, RSVD1, RSVD2, RSVD3, 0x19030, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(pex_l9_rst_n_pag5, PE9, RSVD1, RSVD2, RSVD3, 0x19038, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(qspi0_io3_pc5, QSPI0, RSVD1, RSVD2, RSVD3, 0xB000, 0, Y, -1, 5, 6, -1, -1, 10, 12), + PINGROUP(qspi0_io2_pc4, QSPI0, RSVD1, RSVD2, RSVD3, 0xB008, 0, Y, -1, 5, 6, -1, -1, 10, 12), + PINGROUP(qspi0_io1_pc3, QSPI0, RSVD1, RSVD2, RSVD3, 0xB010, 0, Y, -1, 5, 6, -1, -1, 10, 12), + PINGROUP(qspi0_io0_pc2, QSPI0, RSVD1, RSVD2, RSVD3, 0xB018, 0, Y, -1, 5, 6, -1, -1, 10, 12), + PINGROUP(qspi0_sck_pc0, QSPI0, RSVD1, RSVD2, RSVD3, 0xB020, 0, Y, -1, 5, 6, -1, -1, 10, 12), + PINGROUP(qspi0_cs_n_pc1, QSPI0, RSVD1, RSVD2, RSVD3, 0xB028, 0, Y, -1, 5, 6, -1, -1, 10, 12), + PINGROUP(qspi1_io3_pd3, QSPI1, RSVD1, RSVD2, RSVD3, 0xB030, 0, Y, -1, 5, 6, -1, -1, 10, 12), + PINGROUP(qspi1_io2_pd2, QSPI1, RSVD1, RSVD2, RSVD3, 0xB038, 0, Y, -1, 5, 6, -1, -1, 10, 12), + PINGROUP(qspi1_io1_pd1, QSPI1, RSVD1, RSVD2, RSVD3, 0xB040, 0, Y, -1, 5, 6, -1, -1, 10, 12), + PINGROUP(qspi1_io0_pd0, QSPI1, RSVD1, RSVD2, RSVD3, 0xB048, 0, Y, -1, 5, 6, -1, -1, 10, 12), + PINGROUP(qspi1_sck_pc6, QSPI1, RSVD1, RSVD2, RSVD3, 0xB050, 0, Y, -1, 5, 6, -1, -1, 10, 12), + PINGROUP(qspi1_cs_n_pc7, QSPI1, RSVD1, RSVD2, RSVD3, 0xB058, 0, Y, -1, 5, 6, -1, -1, 10, 12), + PINGROUP(qspi_comp, QSPI, RSVD1, RSVD2, RSVD3, 0xB060, 0, N, -1, -1, -1, -1, -1, -1, -1), + PINGROUP(sdmmc1_clk_pj0, SDMMC1, RSVD1, RSVD2, RSVD3, 0x8000, 0, Y, -1, 5, 6, -1, 9, 10, 12), + PINGROUP(sdmmc1_cmd_pj1, SDMMC1, RSVD1, RSVD2, RSVD3, 0x8008, 0, Y, -1, 5, 6, -1, 9, 10, 12), + PINGROUP(sdmmc1_comp, SDMMC1, RSVD1, RSVD2, RSVD3, 0x8010, 0, N, -1, -1, -1, -1, -1, -1, -1), + PINGROUP(sdmmc1_dat3_pj5, SDMMC1, RSVD1, RSVD2, RSVD3, 0x8018, 0, Y, -1, 5, 6, -1, 9, 10, 12), + PINGROUP(sdmmc1_dat2_pj4, SDMMC1, RSVD1, RSVD2, RSVD3, 0x8020, 0, Y, -1, 5, 6, -1, 9, 10, 12), + PINGROUP(sdmmc1_dat1_pj3, SDMMC1, RSVD1, RSVD2, RSVD3, 0x8028, 0, Y, -1, 5, 6, -1, 9, 10, 12), + PINGROUP(sdmmc1_dat0_pj2, SDMMC1, RSVD1, RSVD2, RSVD3, 0x8030, 0, Y, -1, 5, 6, -1, 9, 10, 12), + PINGROUP(ufs0_rst_n_pae1, UFS0, RSVD1, RSVD2, RSVD3, 0x11000, 0, Y, -1, 5, 6, -1, -1, 10, 12), + PINGROUP(ufs0_ref_clk_pae0, UFS0, RSVD1, RSVD2, RSVD3, 0x11008, 0, Y, -1, 5, 6, -1, -1, 10, 12), + PINGROUP(spi3_miso_py1, SPI3, RSVD1, RSVD2, RSVD3, 0xD000, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(spi1_cs0_pz6, SPI1, RSVD1, RSVD2, RSVD3, 0xD008, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(spi3_cs0_py3, SPI3, RSVD1, RSVD2, RSVD3, 0xD010, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(spi1_miso_pz4, SPI1, RSVD1, RSVD2, RSVD3, 0xD018, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(spi3_cs1_py4, SPI3, RSVD1, RSVD2, RSVD3, 0xD020, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(spi1_sck_pz3, SPI1, RSVD1, RSVD2, RSVD3, 0xD028, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(spi3_sck_py0, SPI3, RSVD1, RSVD2, RSVD3, 0xD030, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(spi1_cs1_pz7, SPI1, RSVD1, RSVD2, RSVD3, 0xD038, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(spi1_mosi_pz5, SPI1, RSVD1, RSVD2, RSVD3, 0xD040, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(spi3_mosi_py2, SPI3, RSVD1, RSVD2, RSVD3, 0xD048, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(uart2_tx_px4, UARTB, RSVD1, RSVD2, RSVD3, 0xD050, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(uart2_rx_px5, UARTB, RSVD1, RSVD2, RSVD3, 0xD058, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(uart2_rts_px6, UARTB, RSVD1, RSVD2, RSVD3, 0xD060, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(uart2_cts_px7, UARTB, RSVD1, RSVD2, RSVD3, 0xD068, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(uart5_tx_py5, UARTE, RSVD1, RSVD2, RSVD3, 0xD070, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(uart5_rx_py6, UARTE, RSVD1, RSVD2, RSVD3, 0xD078, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(uart5_rts_py7, UARTE, RSVD1, RSVD2, RSVD3, 0xD080, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(uart5_cts_pz0, UARTE, RSVD1, RSVD2, RSVD3, 0xD088, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(gpu_pwr_req_px0, RSVD0, RSVD1, RSVD2, RSVD3, 0xD090, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(gp_pwm3_px3, GP, RSVD1, RSVD2, RSVD3, 0xD098, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(gp_pwm2_px2, GP, RSVD1, RSVD2, RSVD3, 0xD0A0, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(cv_pwr_req_px1, RSVD0, RSVD1, RSVD2, RSVD3, 0xD0A8, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(usb_vbus_en0_pz1, USB, RSVD1, RSVD2, RSVD3, 0xD0B0, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(usb_vbus_en1_pz2, USB, RSVD1, RSVD2, RSVD3, 0xD0B8, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(extperiph2_clk_pp1, EXTPERIPH2, RSVD1, RSVD2, RSVD3, 0x0000, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(extperiph1_clk_pp0, EXTPERIPH1, RSVD1, RSVD2, RSVD3, 0x0008, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(cam_i2c_sda_pp3, I2C3, VI0, RSVD2, VI1, 0x0010, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(cam_i2c_scl_pp2, I2C3, VI0, VI0_ALT, VI1, 0x0018, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(soc_gpio23_pp4, VI0, VI0_ALT, VI1, VI1_ALT, 0x0020, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(soc_gpio24_pp5, VI0, SOC, VI1, VI1_ALT, 0x0028, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(soc_gpio25_pp6, VI0, I2S5, VI1, DMIC1, 0x0030, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(pwr_i2c_scl_pp7, I2C5, RSVD1, RSVD2, RSVD3, 0x0038, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(pwr_i2c_sda_pq0, I2C5, RSVD1, RSVD2, RSVD3, 0x0040, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(soc_gpio28_pq1, VI0, RSVD1, VI1, RSVD3, 0x0048, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(soc_gpio29_pq2, RSVD0, NV, RSVD2, RSVD3, 0x0050, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(soc_gpio30_pq3, RSVD0, WDT, RSVD2, RSVD3, 0x0058, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(soc_gpio31_pq4, RSVD0, RSVD1, RSVD2, RSVD3, 0x0060, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(soc_gpio32_pq5, RSVD0, EXTPERIPH3, DCB, RSVD3, 0x0068, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(soc_gpio33_pq6, RSVD0, EXTPERIPH4, DCB, RSVD3, 0x0070, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(soc_gpio35_pq7, RSVD0, I2S5, DMIC1, RSVD3, 0x0078, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(soc_gpio37_pr0, GP, I2S5, DMIC4, DSPK1, 0x0080, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(soc_gpio56_pr1, RSVD0, I2S5, DMIC4, DSPK1, 0x0088, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(uart1_cts_pr5, UARTA, RSVD1, RSVD2, RSVD3, 0x0090, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(uart1_rts_pr4, UARTA, RSVD1, RSVD2, RSVD3, 0x0098, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(uart1_rx_pr3, UARTA, RSVD1, RSVD2, RSVD3, 0x00A0, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(uart1_tx_pr2, UARTA, RSVD1, RSVD2, RSVD3, 0x00A8, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(cpu_pwr_req_pi5, RSVD0, RSVD1, RSVD2, RSVD3, 0x4000, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(uart4_cts_ph6, UARTD, RSVD1, I2S7, RSVD3, 0x4008, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(uart4_rts_ph5, UARTD, SPI4, RSVD2, RSVD3, 0x4010, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(uart4_rx_ph4, UARTD, RSVD1, I2S7, RSVD3, 0x4018, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(uart4_tx_ph3, UARTD, SPI4, RSVD2, RSVD3, 0x4020, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(gen1_i2c_scl_pi3, I2C1, RSVD1, RSVD2, RSVD3, 0x4028, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(gen1_i2c_sda_pi4, I2C1, RSVD1, RSVD2, RSVD3, 0x4030, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(soc_gpio20_pg7, RSVD0, SDMMC1, RSVD2, RSVD3, 0x4038, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(soc_gpio21_ph0, RSVD0, GP, I2S7, RSVD3, 0x4040, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(soc_gpio22_ph1, RSVD0, RSVD1, I2S7, RSVD3, 0x4048, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(soc_gpio13_pg0, RSVD0, RSVD1, RSVD2, RSVD3, 0x4050, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(soc_gpio14_pg1, RSVD0, SPI4, RSVD2, RSVD3, 0x4058, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(soc_gpio15_pg2, RSVD0, SPI4, RSVD2, RSVD3, 0x4060, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(soc_gpio16_pg3, RSVD0, SPI4, RSVD2, RSVD3, 0x4068, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(soc_gpio17_pg4, RSVD0, CCLA, RSVD2, RSVD3, 0x4070, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(soc_gpio18_pg5, RSVD0, RSVD1, RSVD2, RSVD3, 0x4078, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(soc_gpio19_pg6, GP, RSVD1, RSVD2, RSVD3, 0x4080, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(soc_gpio41_ph7, RSVD0, I2S2, RSVD2, RSVD3, 0x4088, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(soc_gpio42_pi0, RSVD0, I2S2, RSVD2, RSVD3, 0x4090, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(soc_gpio43_pi1, RSVD0, I2S2, RSVD2, RSVD3, 0x4098, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(soc_gpio44_pi2, RSVD0, I2S2, RSVD2, RSVD3, 0x40A0, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(soc_gpio06_ph2, RSVD0, RSVD1, RSVD2, RSVD3, 0x40A8, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(soc_gpio07_pi6, GP, RSVD1, RSVD2, RSVD3, 0x40B0, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(dap4_sclk_pa4, I2S4, RSVD1, RSVD2, RSVD3, 0x2000, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(dap4_dout_pa5, I2S4, RSVD1, RSVD2, RSVD3, 0x2008, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(dap4_din_pa6, I2S4, RSVD1, RSVD2, RSVD3, 0x2010, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(dap4_fs_pa7, I2S4, RSVD1, RSVD2, RSVD3, 0x2018, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(dap6_sclk_pa0, I2S6, RSVD1, RSVD2, RSVD3, 0x2020, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(dap6_dout_pa1, I2S6, RSVD1, RSVD2, RSVD3, 0x2028, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(dap6_din_pa2, I2S6, RSVD1, RSVD2, RSVD3, 0x2030, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(dap6_fs_pa3, I2S6, RSVD1, RSVD2, RSVD3, 0x2038, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(soc_gpio45_pad0, RSVD0, I2S1, RSVD2, RSVD3, 0x18000, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(soc_gpio46_pad1, RSVD0, I2S1, RSVD2, RSVD3, 0x18008, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(soc_gpio47_pad2, RSVD0, I2S1, RSVD2, RSVD3, 0x18010, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(soc_gpio48_pad3, RSVD0, I2S1, RSVD2, RSVD3, 0x18018, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(soc_gpio57_pac4, RSVD0, I2S8, RSVD2, SDMMC1, 0x18020, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(soc_gpio58_pac5, RSVD0, I2S8, RSVD2, SDMMC1, 0x18028, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(soc_gpio59_pac6, AUD, I2S8, RSVD2, RSVD3, 0x18030, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(soc_gpio60_pac7, RSVD0, I2S8, NV, IGPU, 0x18038, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(spi5_cs0_pac3, SPI5, I2S3, DMIC2, RSVD3, 0x18040, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(spi5_miso_pac1, SPI5, I2S3, DSPK0, RSVD3, 0x18048, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(spi5_mosi_pac2, SPI5, I2S3, DMIC2, RSVD3, 0x18050, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(spi5_sck_pac0, SPI5, I2S3, DSPK0, RSVD3, 0x18058, 0, Y, -1, 7, 6, 8, -1, 10, 12), + +}; + +static const struct tegra_pinctrl_soc_data tegra234_pinctrl = { + .pins = tegra234_pins, + .npins = ARRAY_SIZE(tegra234_pins), + .functions = tegra234_functions, + .nfunctions = ARRAY_SIZE(tegra234_functions), + .groups = tegra234_groups, + .ngroups = ARRAY_SIZE(tegra234_groups), + .hsm_in_mux = false, + .schmitt_in_mux = true, + .drvtype_in_mux = true, + .sfsel_in_mux = true, +}; + +static const struct pinctrl_pin_desc tegra234_aon_pins[] = { + PINCTRL_PIN(TEGRA_PIN_CAN0_DOUT_PAA0, "CAN0_DOUT_PAA0"), + PINCTRL_PIN(TEGRA_PIN_CAN0_DIN_PAA1, "CAN0_DIN_PAA1"), + PINCTRL_PIN(TEGRA_PIN_CAN1_DOUT_PAA2, "CAN1_DOUT_PAA2"), + PINCTRL_PIN(TEGRA_PIN_CAN1_DIN_PAA3, "CAN1_DIN_PAA3"), + PINCTRL_PIN(TEGRA_PIN_CAN0_STB_PAA4, "CAN0_STB_PAA4"), + PINCTRL_PIN(TEGRA_PIN_CAN0_EN_PAA5, "CAN0_EN_PAA5"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO49_PAA6, "SOC_GPIO49_PAA6"), + PINCTRL_PIN(TEGRA_PIN_CAN0_ERR_PAA7, "CAN0_ERR_PAA7"), + PINCTRL_PIN(TEGRA_PIN_CAN1_STB_PBB0, "CAN1_STB_PBB0"), + PINCTRL_PIN(TEGRA_PIN_CAN1_EN_PBB1, "CAN1_EN_PBB1"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO50_PBB2, "SOC_GPIO50_PBB2"), + PINCTRL_PIN(TEGRA_PIN_CAN1_ERR_PBB3, "CAN1_ERR_PBB3"), + PINCTRL_PIN(TEGRA_PIN_SPI2_SCK_PCC0, "SPI2_SCK_PCC0"), + PINCTRL_PIN(TEGRA_PIN_SPI2_MISO_PCC1, "SPI2_MISO_PCC1"), + PINCTRL_PIN(TEGRA_PIN_SPI2_MOSI_PCC2, "SPI2_MOSI_PCC2"), + PINCTRL_PIN(TEGRA_PIN_SPI2_CS0_PCC3, "SPI2_CS0_PCC3"), + PINCTRL_PIN(TEGRA_PIN_TOUCH_CLK_PCC4, "TOUCH_CLK_PCC4"), + PINCTRL_PIN(TEGRA_PIN_UART3_TX_PCC5, "UART3_TX_PCC5"), + PINCTRL_PIN(TEGRA_PIN_UART3_RX_PCC6, "UART3_RX_PCC6"), + PINCTRL_PIN(TEGRA_PIN_GEN2_I2C_SCL_PCC7, "GEN2_I2C_SCL_PCC7"), + PINCTRL_PIN(TEGRA_PIN_GEN2_I2C_SDA_PDD0, "GEN2_I2C_SDA_PDD0"), + PINCTRL_PIN(TEGRA_PIN_GEN8_I2C_SCL_PDD1, "GEN8_I2C_SCL_PDD1"), + PINCTRL_PIN(TEGRA_PIN_GEN8_I2C_SDA_PDD2, "GEN8_I2C_SDA_PDD2"), + PINCTRL_PIN(TEGRA_PIN_SCE_ERROR_PEE0, "SCE_ERROR_PEE0"), + PINCTRL_PIN(TEGRA_PIN_VCOMP_ALERT_PEE1, "VCOMP_ALERT_PEE1"), + PINCTRL_PIN(TEGRA_PIN_AO_RETENTION_N_PEE2, "AO_RETENTION_N_PEE2"), + PINCTRL_PIN(TEGRA_PIN_BATT_OC_PEE3, "BATT_OC_PEE3"), + PINCTRL_PIN(TEGRA_PIN_POWER_ON_PEE4, "POWER_ON_PEE4"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO26_PEE5, "SOC_GPIO26_PEE5"), + PINCTRL_PIN(TEGRA_PIN_SOC_GPIO27_PEE6, "SOC_GPIO27_PEE6"), + PINCTRL_PIN(TEGRA_PIN_BOOTV_CTL_N_PEE7, "BOOTV_CTL_N_PEE7"), + PINCTRL_PIN(TEGRA_PIN_HDMI_CEC_PGG0, "HDMI_CEC_PGG0"), +}; + +/* AON drive pin groups */ +#define drive_touch_clk_pcc4 DRV_PINGROUP_ENTRY_Y(0x2004, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_uart3_rx_pcc6 DRV_PINGROUP_ENTRY_Y(0x200c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_uart3_tx_pcc5 DRV_PINGROUP_ENTRY_Y(0x2014, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_gen8_i2c_sda_pdd2 DRV_PINGROUP_ENTRY_Y(0x201c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_gen8_i2c_scl_pdd1 DRV_PINGROUP_ENTRY_Y(0x2024, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_spi2_mosi_pcc2 DRV_PINGROUP_ENTRY_Y(0x202c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_gen2_i2c_scl_pcc7 DRV_PINGROUP_ENTRY_Y(0x2034, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_spi2_cs0_pcc3 DRV_PINGROUP_ENTRY_Y(0x203c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_gen2_i2c_sda_pdd0 DRV_PINGROUP_ENTRY_Y(0x2044, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_spi2_sck_pcc0 DRV_PINGROUP_ENTRY_Y(0x204c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_spi2_miso_pcc1 DRV_PINGROUP_ENTRY_Y(0x2054, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_can1_dout_paa2 DRV_PINGROUP_ENTRY_Y(0x3004, 28, 2, 30, 2, -1, -1, -1, -1, 0) +#define drive_can1_din_paa3 DRV_PINGROUP_ENTRY_Y(0x300c, 28, 2, 30, 2, -1, -1, -1, -1, 0) +#define drive_can0_dout_paa0 DRV_PINGROUP_ENTRY_Y(0x3014, 28, 2, 30, 2, -1, -1, -1, -1, 0) +#define drive_can0_din_paa1 DRV_PINGROUP_ENTRY_Y(0x301c, 28, 2, 30, 2, -1, -1, -1, -1, 0) +#define drive_can0_stb_paa4 DRV_PINGROUP_ENTRY_Y(0x3024, 28, 2, 30, 2, -1, -1, -1, -1, 0) +#define drive_can0_en_paa5 DRV_PINGROUP_ENTRY_Y(0x302c, 28, 2, 30, 2, -1, -1, -1, -1, 0) +#define drive_soc_gpio49_paa6 DRV_PINGROUP_ENTRY_Y(0x3034, 28, 2, 30, 2, -1, -1, -1, -1, 0) +#define drive_can0_err_paa7 DRV_PINGROUP_ENTRY_Y(0x303c, 28, 2, 30, 2, -1, -1, -1, -1, 0) +#define drive_can1_stb_pbb0 DRV_PINGROUP_ENTRY_Y(0x3044, 28, 2, 30, 2, -1, -1, -1, -1, 0) +#define drive_can1_en_pbb1 DRV_PINGROUP_ENTRY_Y(0x304c, 28, 2, 30, 2, -1, -1, -1, -1, 0) +#define drive_soc_gpio50_pbb2 DRV_PINGROUP_ENTRY_Y(0x3054, 28, 2, 30, 2, -1, -1, -1, -1, 0) +#define drive_can1_err_pbb3 DRV_PINGROUP_ENTRY_Y(0x305c, 28, 2, 30, 2, -1, -1, -1, -1, 0) +#define drive_sce_error_pee0 DRV_PINGROUP_ENTRY_Y(0x1014, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_batt_oc_pee3 DRV_PINGROUP_ENTRY_Y(0x1024, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_bootv_ctl_n_pee7 DRV_PINGROUP_ENTRY_Y(0x102c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_power_on_pee4 DRV_PINGROUP_ENTRY_Y(0x103c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_soc_gpio26_pee5 DRV_PINGROUP_ENTRY_Y(0x1044, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_soc_gpio27_pee6 DRV_PINGROUP_ENTRY_Y(0x104c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_ao_retention_n_pee2 DRV_PINGROUP_ENTRY_Y(0x1054, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_vcomp_alert_pee1 DRV_PINGROUP_ENTRY_Y(0x105c, 12, 5, 20, 5, -1, -1, -1, -1, 0) +#define drive_hdmi_cec_pgg0 DRV_PINGROUP_ENTRY_Y(0x1064, 12, 5, 20, 5, -1, -1, -1, -1, 0) + +static const struct tegra_pingroup tegra234_aon_groups[] = { + PINGROUP(touch_clk_pcc4, GP, TOUCH, RSVD2, RSVD3, 0x2000, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(uart3_rx_pcc6, UARTC, UARTJ, RSVD2, RSVD3, 0x2008, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(uart3_tx_pcc5, UARTC, UARTJ, RSVD2, RSVD3, 0x2010, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(gen8_i2c_sda_pdd2, I2C8, RSVD1, RSVD2, RSVD3, 0x2018, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(gen8_i2c_scl_pdd1, I2C8, RSVD1, RSVD2, RSVD3, 0x2020, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(spi2_mosi_pcc2, SPI2, RSVD1, RSVD2, RSVD3, 0x2028, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(gen2_i2c_scl_pcc7, I2C2, RSVD1, RSVD2, RSVD3, 0x2030, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(spi2_cs0_pcc3, SPI2, RSVD1, RSVD2, RSVD3, 0x2038, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(gen2_i2c_sda_pdd0, I2C2, RSVD1, RSVD2, RSVD3, 0x2040, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(spi2_sck_pcc0, SPI2, RSVD1, RSVD2, RSVD3, 0x2048, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(spi2_miso_pcc1, SPI2, RSVD1, RSVD2, RSVD3, 0x2050, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(can1_dout_paa2, CAN1, RSVD1, RSVD2, RSVD3, 0x3000, 0, Y, -1, 5, 6, -1, 9, 10, 12), + PINGROUP(can1_din_paa3, CAN1, RSVD1, RSVD2, RSVD3, 0x3008, 0, Y, -1, 5, 6, -1, 9, 10, 12), + PINGROUP(can0_dout_paa0, CAN0, RSVD1, RSVD2, RSVD3, 0x3010, 0, Y, -1, 5, 6, -1, 9, 10, 12), + PINGROUP(can0_din_paa1, CAN0, RSVD1, RSVD2, RSVD3, 0x3018, 0, Y, -1, 5, 6, -1, 9, 10, 12), + PINGROUP(can0_stb_paa4, RSVD0, WDT, TSC, TSC_ALT, 0x3020, 0, Y, -1, 5, 6, -1, 9, 10, 12), + PINGROUP(can0_en_paa5, RSVD0, RSVD1, RSVD2, RSVD3, 0x3028, 0, Y, -1, 5, 6, -1, 9, 10, 12), + PINGROUP(soc_gpio49_paa6, RSVD0, RSVD1, RSVD2, RSVD3, 0x3030, 0, Y, -1, 5, 6, -1, 9, 10, 12), + PINGROUP(can0_err_paa7, RSVD0, TSC, RSVD2, TSC_ALT, 0x3038, 0, Y, -1, 5, 6, -1, 9, 10, 12), + PINGROUP(can1_stb_pbb0, RSVD0, DMIC3, DMIC5, RSVD3, 0x3040, 0, Y, -1, 5, 6, -1, 9, 10, 12), + PINGROUP(can1_en_pbb1, RSVD0, DMIC3, DMIC5, RSVD3, 0x3048, 0, Y, -1, 5, 6, -1, 9, 10, 12), + PINGROUP(soc_gpio50_pbb2, RSVD0, TSC, RSVD2, TSC_ALT, 0x3050, 0, Y, -1, 5, 6, -1, 9, 10, 12), + PINGROUP(can1_err_pbb3, RSVD0, TSC, RSVD2, TSC_ALT, 0x3058, 0, Y, -1, 5, 6, -1, 9, 10, 12), + PINGROUP(sce_error_pee0, SCE, RSVD1, RSVD2, RSVD3, 0x1010, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(batt_oc_pee3, SOC, RSVD1, RSVD2, RSVD3, 0x1020, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(bootv_ctl_n_pee7, RSVD0, RSVD1, RSVD2, RSVD3, 0x1028, 0, Y, -1, 7, 6, 8, -1, 10, 12), + PINGROUP(power_on_pee4, RSVD0, RSVD1, RSVD2, RSVD3, 0x1038, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(soc_gpio26_pee5, RSVD0, RSVD1, RSVD2, RSVD3, 0x1040, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(soc_gpio27_pee6, RSVD0, RSVD1, RSVD2, RSVD3, 0x1048, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(ao_retention_n_pee2, GPIO, LED, RSVD2, ISTCTRL, 0x1050, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(vcomp_alert_pee1, SOC, RSVD1, RSVD2, RSVD3, 0x1058, 0, Y, 5, 7, 6, 8, -1, 10, 12), + PINGROUP(hdmi_cec_pgg0, HDMI, RSVD1, RSVD2, RSVD3, 0x1060, 0, Y, 5, 7, 6, 8, -1, 10, 12), +}; + +static const struct tegra_pinctrl_soc_data tegra234_pinctrl_aon = { + .pins = tegra234_aon_pins, + .npins = ARRAY_SIZE(tegra234_aon_pins), + .functions = tegra234_functions, + .nfunctions = ARRAY_SIZE(tegra234_functions), + .groups = tegra234_aon_groups, + .ngroups = ARRAY_SIZE(tegra234_aon_groups), + .hsm_in_mux = false, + .schmitt_in_mux = true, + .drvtype_in_mux = true, + .sfsel_in_mux = true, +}; + +static int tegra234_pinctrl_probe(struct platform_device *pdev) +{ + const struct tegra_pinctrl_soc_data *soc = device_get_match_data(&pdev->dev); + + return tegra_pinctrl_probe(pdev, soc); +} + +static const struct of_device_id tegra234_pinctrl_of_match[] = { + { .compatible = "nvidia,tegra234-pinmux", .data = &tegra234_pinctrl}, + { .compatible = "nvidia,tegra234-pinmux-aon", .data = &tegra234_pinctrl_aon }, + { } +}; +MODULE_DEVICE_TABLE(of, tegra234_pinctrl_of_match); + +static struct platform_driver tegra234_pinctrl_driver = { + .driver = { + .name = "tegra234-pinctrl", + .of_match_table = tegra234_pinctrl_of_match, + }, + .probe = tegra234_pinctrl_probe, +}; + +static int __init tegra234_pinctrl_init(void) +{ + return platform_driver_register(&tegra234_pinctrl_driver); +} +arch_initcall(tegra234_pinctrl_init); diff --git a/drivers/pinctrl/tegra/pinctrl-tegra30.c b/drivers/pinctrl/tegra/pinctrl-tegra30.c index 7299a371827f1892d8b2be7c6eb8d1b6e50df712..de5aa2d4d28d38f696cec733dafaa6ab68031bc8 100644 --- a/drivers/pinctrl/tegra/pinctrl-tegra30.c +++ b/drivers/pinctrl/tegra/pinctrl-tegra30.c @@ -2010,12 +2010,9 @@ enum tegra_mux { TEGRA_MUX_VI_ALT3, }; -#define FUNCTION(fname) \ - { \ - .name = #fname, \ - } +#define FUNCTION(fname) #fname -static struct tegra_function tegra30_functions[] = { +static const char * const tegra30_functions[] = { FUNCTION(blink), FUNCTION(cec), FUNCTION(clk_12m_out), diff --git a/drivers/platform/chrome/cros_ec_i2c.c b/drivers/platform/chrome/cros_ec_i2c.c index dbe698f33128518482014ef30074e69351184a0b..e29c51cbfd71b46bea6801499e72754ee93a0060 100644 --- a/drivers/platform/chrome/cros_ec_i2c.c +++ b/drivers/platform/chrome/cros_ec_i2c.c @@ -372,7 +372,7 @@ static struct i2c_driver cros_ec_driver = { .of_match_table = of_match_ptr(cros_ec_i2c_of_match), .pm = &cros_ec_i2c_pm_ops, }, - .probe_new = cros_ec_i2c_probe, + .probe = cros_ec_i2c_probe, .remove = cros_ec_i2c_remove, .id_table = cros_ec_i2c_id, }; diff --git a/drivers/platform/chrome/cros_ec_lpc.c b/drivers/platform/chrome/cros_ec_lpc.c index 68bba0fcafab37144041e05a9eaec161098c0ad2..500a61b093e47f8abc35b4a9dc2cf50a8c647ac0 100644 --- a/drivers/platform/chrome/cros_ec_lpc.c +++ b/drivers/platform/chrome/cros_ec_lpc.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -315,6 +316,7 @@ static int cros_ec_lpc_readmem(struct cros_ec_device *ec, unsigned int offset, static void cros_ec_lpc_acpi_notify(acpi_handle device, u32 value, void *data) { + static const char *env[] = { "ERROR=PANIC", NULL }; struct cros_ec_device *ec_dev = data; bool ec_has_more_events; int ret; @@ -324,6 +326,7 @@ static void cros_ec_lpc_acpi_notify(acpi_handle device, u32 value, void *data) if (value == ACPI_NOTIFY_CROS_EC_PANIC) { dev_emerg(ec_dev->dev, "CrOS EC Panic Reported. Shutdown is imminent!"); blocking_notifier_call_chain(&ec_dev->panic_notifier, 0, ec_dev); + kobject_uevent_env(&ec_dev->dev->kobj, KOBJ_CHANGE, (char **)env); /* Begin orderly shutdown. Force shutdown after 1 second. */ hw_protection_shutdown("CrOS EC Panic", 1000); /* Do not query for other events after a panic is reported */ @@ -543,23 +546,25 @@ static const struct dmi_system_id cros_ec_lpc_dmi_table[] __initconst = { MODULE_DEVICE_TABLE(dmi, cros_ec_lpc_dmi_table); #ifdef CONFIG_PM_SLEEP -static int cros_ec_lpc_suspend(struct device *dev) +static int cros_ec_lpc_prepare(struct device *dev) { struct cros_ec_device *ec_dev = dev_get_drvdata(dev); return cros_ec_suspend(ec_dev); } -static int cros_ec_lpc_resume(struct device *dev) +static void cros_ec_lpc_complete(struct device *dev) { struct cros_ec_device *ec_dev = dev_get_drvdata(dev); - - return cros_ec_resume(ec_dev); + cros_ec_resume(ec_dev); } #endif static const struct dev_pm_ops cros_ec_lpc_pm_ops = { - SET_LATE_SYSTEM_SLEEP_PM_OPS(cros_ec_lpc_suspend, cros_ec_lpc_resume) +#ifdef CONFIG_PM_SLEEP + .prepare = cros_ec_lpc_prepare, + .complete = cros_ec_lpc_complete +#endif }; static struct platform_driver cros_ec_lpc_driver = { diff --git a/drivers/platform/chrome/cros_ec_spi.c b/drivers/platform/chrome/cros_ec_spi.c index 21143dba8970472890cee4f91f305035552952a5..3e88cc92e819223e5e26778ce26a64643028ccda 100644 --- a/drivers/platform/chrome/cros_ec_spi.c +++ b/drivers/platform/chrome/cros_ec_spi.c @@ -104,13 +104,7 @@ static void debug_packet(struct device *dev, const char *name, u8 *ptr, int len) { #ifdef DEBUG - int i; - - dev_dbg(dev, "%s: ", name); - for (i = 0; i < len; i++) - pr_cont(" %02x", ptr[i]); - - pr_cont("\n"); + dev_dbg(dev, "%s: %*ph\n", name, len, ptr); #endif } diff --git a/drivers/platform/chrome/cros_ec_typec.c b/drivers/platform/chrome/cros_ec_typec.c index a673c334247067ea7612175a000d83be11bf4e0c..25f9767c28e82ee516b34846f88dcfa8a27a6f79 100644 --- a/drivers/platform/chrome/cros_ec_typec.c +++ b/drivers/platform/chrome/cros_ec_typec.c @@ -77,7 +77,7 @@ static int cros_typec_get_switch_handles(struct cros_typec_port *port, { int ret = 0; - port->mux = fwnode_typec_mux_get(fwnode, NULL); + port->mux = fwnode_typec_mux_get(fwnode); if (IS_ERR(port->mux)) { ret = PTR_ERR(port->mux); dev_dbg(dev, "Mux handle not found: %d.\n", ret); diff --git a/drivers/platform/chrome/cros_hps_i2c.c b/drivers/platform/chrome/cros_hps_i2c.c index 62ccb1acb5de0fd0d6573d88c74c172169f863a8..b31313080332430280a3c6f7ae3921626d1e7dab 100644 --- a/drivers/platform/chrome/cros_hps_i2c.c +++ b/drivers/platform/chrome/cros_hps_i2c.c @@ -143,7 +143,7 @@ MODULE_DEVICE_TABLE(acpi, hps_acpi_id); #endif /* CONFIG_ACPI */ static struct i2c_driver hps_i2c_driver = { - .probe_new = hps_i2c_probe, + .probe = hps_i2c_probe, .remove = hps_i2c_remove, .id_table = hps_i2c_id, .driver = { diff --git a/drivers/platform/chrome/cros_typec_switch.c b/drivers/platform/chrome/cros_typec_switch.c index 752720483753de5a2e8453159787563f4b4b326e..0eefdcf14d63f6f26746554ac22203962bb59a42 100644 --- a/drivers/platform/chrome/cros_typec_switch.c +++ b/drivers/platform/chrome/cros_typec_switch.c @@ -51,13 +51,18 @@ static int cros_typec_cmd_mux_set(struct cros_typec_switch_data *sdata, int port static int cros_typec_get_mux_state(unsigned long mode, struct typec_altmode *alt) { int ret = -EOPNOTSUPP; + u8 pin_assign; - if (mode == TYPEC_STATE_SAFE) + if (mode == TYPEC_STATE_SAFE) { ret = USB_PD_MUX_SAFE_MODE; - else if (mode == TYPEC_STATE_USB) + } else if (mode == TYPEC_STATE_USB) { ret = USB_PD_MUX_USB_ENABLED; - else if (alt && alt->svid == USB_TYPEC_DP_SID) + } else if (alt && alt->svid == USB_TYPEC_DP_SID) { ret = USB_PD_MUX_DP_ENABLED; + pin_assign = mode - TYPEC_STATE_MODAL; + if (pin_assign & DP_PIN_ASSIGN_D) + ret |= USB_PD_MUX_USB_ENABLED; + } return ret; } diff --git a/drivers/platform/mellanox/mlxbf-bootctl.c b/drivers/platform/mellanox/mlxbf-bootctl.c index 1bad1d2786722a25715eabb41abe14fc4f5c4127..fb9f7815c6cd48aa005ea8d37eeea1408f8bbb7a 100644 --- a/drivers/platform/mellanox/mlxbf-bootctl.c +++ b/drivers/platform/mellanox/mlxbf-bootctl.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -45,10 +46,39 @@ static const char * const mlxbf_bootctl_lifecycle_states[] = { [3] = "RMA", }; +/* Log header format. */ +#define MLXBF_RSH_LOG_TYPE_MASK GENMASK_ULL(59, 56) +#define MLXBF_RSH_LOG_LEN_MASK GENMASK_ULL(54, 48) +#define MLXBF_RSH_LOG_LEVEL_MASK GENMASK_ULL(7, 0) + +/* Log module ID and type (only MSG type in Linux driver for now). */ +#define MLXBF_RSH_LOG_TYPE_MSG 0x04ULL + +/* Log ctl/data register offset. */ +#define MLXBF_RSH_SCRATCH_BUF_CTL_OFF 0 +#define MLXBF_RSH_SCRATCH_BUF_DATA_OFF 0x10 + +/* Log message levels. */ +enum { + MLXBF_RSH_LOG_INFO, + MLXBF_RSH_LOG_WARN, + MLXBF_RSH_LOG_ERR, + MLXBF_RSH_LOG_ASSERT +}; + /* Mapped pointer for RSH_BOOT_FIFO_DATA and RSH_BOOT_FIFO_COUNT register. */ static void __iomem *mlxbf_rsh_boot_data; static void __iomem *mlxbf_rsh_boot_cnt; +/* Mapped pointer for rsh log semaphore/ctrl/data register. */ +static void __iomem *mlxbf_rsh_semaphore; +static void __iomem *mlxbf_rsh_scratch_buf_ctl; +static void __iomem *mlxbf_rsh_scratch_buf_data; + +/* Rsh log levels. */ +static const char * const mlxbf_rsh_log_level[] = { + "INFO", "WARN", "ERR", "ASSERT"}; + /* ARM SMC call which is atomic and no need for lock. */ static int mlxbf_bootctl_smc(unsigned int smc_op, int smc_arg) { @@ -266,12 +296,108 @@ static ssize_t fw_reset_store(struct device *dev, return count; } +/* Size(8-byte words) of the log buffer. */ +#define RSH_SCRATCH_BUF_CTL_IDX_MASK 0x7f + +/* 100ms timeout */ +#define RSH_SCRATCH_BUF_POLL_TIMEOUT 100000 + +static int mlxbf_rsh_log_sem_lock(void) +{ + unsigned long reg; + + return readq_poll_timeout(mlxbf_rsh_semaphore, reg, !reg, 0, + RSH_SCRATCH_BUF_POLL_TIMEOUT); +} + +static void mlxbf_rsh_log_sem_unlock(void) +{ + writeq(0, mlxbf_rsh_semaphore); +} + +static ssize_t rsh_log_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + int rc, idx, num, len, level = MLXBF_RSH_LOG_INFO; + size_t size = count; + u64 data; + + if (!size) + return -EINVAL; + + if (!mlxbf_rsh_semaphore || !mlxbf_rsh_scratch_buf_ctl) + return -EOPNOTSUPP; + + /* Ignore line break at the end. */ + if (buf[size - 1] == '\n') + size--; + + /* Check the message prefix. */ + for (idx = 0; idx < ARRAY_SIZE(mlxbf_rsh_log_level); idx++) { + len = strlen(mlxbf_rsh_log_level[idx]); + if (len + 1 < size && + !strncmp(buf, mlxbf_rsh_log_level[idx], len)) { + buf += len; + size -= len; + level = idx; + break; + } + } + + /* Ignore leading spaces. */ + while (size > 0 && buf[0] == ' ') { + size--; + buf++; + } + + /* Take the semaphore. */ + rc = mlxbf_rsh_log_sem_lock(); + if (rc) + return rc; + + /* Calculate how many words are available. */ + idx = readq(mlxbf_rsh_scratch_buf_ctl); + num = min((int)DIV_ROUND_UP(size, sizeof(u64)), + RSH_SCRATCH_BUF_CTL_IDX_MASK - idx - 1); + if (num <= 0) + goto done; + + /* Write Header. */ + data = FIELD_PREP(MLXBF_RSH_LOG_TYPE_MASK, MLXBF_RSH_LOG_TYPE_MSG); + data |= FIELD_PREP(MLXBF_RSH_LOG_LEN_MASK, num); + data |= FIELD_PREP(MLXBF_RSH_LOG_LEVEL_MASK, level); + writeq(data, mlxbf_rsh_scratch_buf_data); + + /* Write message. */ + for (idx = 0; idx < num && size > 0; idx++) { + if (size < sizeof(u64)) { + data = 0; + memcpy(&data, buf, size); + size = 0; + } else { + memcpy(&data, buf, sizeof(u64)); + size -= sizeof(u64); + buf += sizeof(u64); + } + writeq(data, mlxbf_rsh_scratch_buf_data); + } + +done: + /* Release the semaphore. */ + mlxbf_rsh_log_sem_unlock(); + + /* Ignore the rest if no more space. */ + return count; +} + static DEVICE_ATTR_RW(post_reset_wdog); static DEVICE_ATTR_RW(reset_action); static DEVICE_ATTR_RW(second_reset_action); static DEVICE_ATTR_RO(lifecycle_state); static DEVICE_ATTR_RO(secure_boot_fuse_state); static DEVICE_ATTR_WO(fw_reset); +static DEVICE_ATTR_WO(rsh_log); static struct attribute *mlxbf_bootctl_attrs[] = { &dev_attr_post_reset_wdog.attr, @@ -280,6 +406,7 @@ static struct attribute *mlxbf_bootctl_attrs[] = { &dev_attr_lifecycle_state.attr, &dev_attr_secure_boot_fuse_state.attr, &dev_attr_fw_reset.attr, + &dev_attr_rsh_log.attr, NULL }; @@ -345,19 +472,32 @@ static bool mlxbf_bootctl_guid_match(const guid_t *guid, static int mlxbf_bootctl_probe(struct platform_device *pdev) { struct arm_smccc_res res = { 0 }; + void __iomem *reg; guid_t guid; int ret; - /* Get the resource of the bootfifo data register. */ + /* Map the resource of the bootfifo data register. */ mlxbf_rsh_boot_data = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(mlxbf_rsh_boot_data)) return PTR_ERR(mlxbf_rsh_boot_data); - /* Get the resource of the bootfifo counter register. */ + /* Map the resource of the bootfifo counter register. */ mlxbf_rsh_boot_cnt = devm_platform_ioremap_resource(pdev, 1); if (IS_ERR(mlxbf_rsh_boot_cnt)) return PTR_ERR(mlxbf_rsh_boot_cnt); + /* Map the resource of the rshim semaphore register. */ + mlxbf_rsh_semaphore = devm_platform_ioremap_resource(pdev, 2); + if (IS_ERR(mlxbf_rsh_semaphore)) + return PTR_ERR(mlxbf_rsh_semaphore); + + /* Map the resource of the scratch buffer (log) registers. */ + reg = devm_platform_ioremap_resource(pdev, 3); + if (IS_ERR(reg)) + return PTR_ERR(reg); + mlxbf_rsh_scratch_buf_ctl = reg + MLXBF_RSH_SCRATCH_BUF_CTL_OFF; + mlxbf_rsh_scratch_buf_data = reg + MLXBF_RSH_SCRATCH_BUF_DATA_OFF; + /* Ensure we have the UUID we expect for this service. */ arm_smccc_smc(MLXBF_BOOTCTL_SIP_SVC_UID, 0, 0, 0, 0, 0, 0, 0, &res); guid_parse(mlxbf_bootctl_svc_uuid_str, &guid); diff --git a/drivers/platform/surface/aggregator/Kconfig b/drivers/platform/surface/aggregator/Kconfig index c114f9dd5fe1ce96d55d1f337efa2aaf31367259..88afc38ffdc5c2823fbf0fb4058b06d271aee4a9 100644 --- a/drivers/platform/surface/aggregator/Kconfig +++ b/drivers/platform/surface/aggregator/Kconfig @@ -4,7 +4,7 @@ menuconfig SURFACE_AGGREGATOR tristate "Microsoft Surface System Aggregator Module Subsystem and Drivers" depends on SERIAL_DEV_BUS - depends on ACPI + depends on ACPI && !RISCV select CRC_CCITT help The Surface System Aggregator Module (Surface SAM or SSAM) is an diff --git a/drivers/platform/surface/surface3_power.c b/drivers/platform/surface/surface3_power.c index 73961a24c849f44c1d2c705fab5be29856e7f241..4c0f92562a794fd72737ba255918b99c8bb31886 100644 --- a/drivers/platform/surface/surface3_power.c +++ b/drivers/platform/surface/surface3_power.c @@ -573,7 +573,7 @@ static const struct acpi_device_id mshw0011_acpi_match[] = { MODULE_DEVICE_TABLE(acpi, mshw0011_acpi_match); static struct i2c_driver mshw0011_driver = { - .probe_new = mshw0011_probe, + .probe = mshw0011_probe, .remove = mshw0011_remove, .driver = { .name = "mshw0011", diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index 22052031c7190097996f778197733a4bf9ad7165..49c2c4cd8d00059f6a32a2bfd5f11095ad585644 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -43,8 +43,8 @@ config WMI_BMOF default ACPI_WMI help Say Y here if you want to be able to read a firmware-embedded - WMI Binary MOF data. Using this requires userspace tools and may be - rather tedious. + WMI Binary MOF (Managed Object Format) data. Using this requires + userspace tools and may be rather tedious. To compile this driver as a module, choose M here: the module will be called wmi-bmof. @@ -121,10 +121,11 @@ config GIGABYTE_WMI To compile this driver as a module, choose M here: the module will be called gigabyte-wmi. -config YOGABOOK_WMI - tristate "Lenovo Yoga Book tablet WMI key driver" +config YOGABOOK + tristate "Lenovo Yoga Book tablet key driver" depends on ACPI_WMI depends on INPUT + depends on I2C select LEDS_CLASS select NEW_LEDS help @@ -132,7 +133,7 @@ config YOGABOOK_WMI control on the Lenovo Yoga Book tablets. To compile this driver as a module, choose M here: the module will - be called lenovo-yogabook-wmi. + be called lenovo-yogabook. config ACERHDF tristate "Acer Aspire One temperature and fan driver" diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile index 2cafe51ec4d8e87b4dcbba093fca42ce8425ecee..52dfdf574ac2ddbecb1a433a996b51bcf476e8ef 100644 --- a/drivers/platform/x86/Makefile +++ b/drivers/platform/x86/Makefile @@ -14,7 +14,6 @@ obj-$(CONFIG_MXM_WMI) += mxm-wmi.o obj-$(CONFIG_NVIDIA_WMI_EC_BACKLIGHT) += nvidia-wmi-ec-backlight.o obj-$(CONFIG_XIAOMI_WMI) += xiaomi-wmi.o obj-$(CONFIG_GIGABYTE_WMI) += gigabyte-wmi.o -obj-$(CONFIG_YOGABOOK_WMI) += lenovo-yogabook-wmi.o # Acer obj-$(CONFIG_ACERHDF) += acerhdf.o @@ -66,6 +65,7 @@ obj-$(CONFIG_LENOVO_YMC) += lenovo-ymc.o obj-$(CONFIG_SENSORS_HDAPS) += hdaps.o obj-$(CONFIG_THINKPAD_ACPI) += thinkpad_acpi.o obj-$(CONFIG_THINKPAD_LMI) += think-lmi.o +obj-$(CONFIG_YOGABOOK) += lenovo-yogabook.o # Intel obj-y += intel/ diff --git a/drivers/platform/x86/amd/Makefile b/drivers/platform/x86/amd/Makefile index 2c229198e24c967e0f73015ee0bad82b70e0beb6..65732f0a3913f1b4271519bc42b0a5588bbcdc78 100644 --- a/drivers/platform/x86/amd/Makefile +++ b/drivers/platform/x86/amd/Makefile @@ -4,7 +4,7 @@ # AMD x86 Platform-Specific Drivers # -amd-pmc-y := pmc.o +amd-pmc-y := pmc.o pmc-quirks.o obj-$(CONFIG_AMD_PMC) += amd-pmc.o amd_hsmp-y := hsmp.o obj-$(CONFIG_AMD_HSMP) += amd_hsmp.o diff --git a/drivers/platform/x86/amd/pmc-quirks.c b/drivers/platform/x86/amd/pmc-quirks.c new file mode 100644 index 0000000000000000000000000000000000000000..362e7c0097d77c98978a8ffd4d1ab711699e3e49 --- /dev/null +++ b/drivers/platform/x86/amd/pmc-quirks.c @@ -0,0 +1,176 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * AMD SoC Power Management Controller Driver Quirks + * + * Copyright (c) 2023, Advanced Micro Devices, Inc. + * All Rights Reserved. + * + * Author: Mario Limonciello + */ + +#include +#include +#include +#include + +#include "pmc.h" + +struct quirk_entry { + u32 s2idle_bug_mmio; +}; + +static struct quirk_entry quirk_s2idle_bug = { + .s2idle_bug_mmio = 0xfed80380, +}; + +static const struct dmi_system_id fwbug_list[] = { + { + .ident = "L14 Gen2 AMD", + .driver_data = &quirk_s2idle_bug, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "20X5"), + } + }, + { + .ident = "T14s Gen2 AMD", + .driver_data = &quirk_s2idle_bug, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "20XF"), + } + }, + { + .ident = "X13 Gen2 AMD", + .driver_data = &quirk_s2idle_bug, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "20XH"), + } + }, + { + .ident = "T14 Gen2 AMD", + .driver_data = &quirk_s2idle_bug, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "20XK"), + } + }, + { + .ident = "T14 Gen1 AMD", + .driver_data = &quirk_s2idle_bug, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "20UD"), + } + }, + { + .ident = "T14 Gen1 AMD", + .driver_data = &quirk_s2idle_bug, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "20UE"), + } + }, + { + .ident = "T14s Gen1 AMD", + .driver_data = &quirk_s2idle_bug, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "20UH"), + } + }, + { + .ident = "T14s Gen1 AMD", + .driver_data = &quirk_s2idle_bug, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "20UJ"), + } + }, + { + .ident = "P14s Gen1 AMD", + .driver_data = &quirk_s2idle_bug, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "20Y1"), + } + }, + { + .ident = "P14s Gen2 AMD", + .driver_data = &quirk_s2idle_bug, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "21A0"), + } + }, + { + .ident = "P14s Gen2 AMD", + .driver_data = &quirk_s2idle_bug, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "21A1"), + } + }, + /* https://gitlab.freedesktop.org/drm/amd/-/issues/2684 */ + { + .ident = "HP Laptop 15s-eq2xxx", + .driver_data = &quirk_s2idle_bug, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "HP"), + DMI_MATCH(DMI_PRODUCT_NAME, "HP Laptop 15s-eq2xxx"), + } + }, + {} +}; + +/* + * Laptops that run a SMI handler during the D3->D0 transition that occurs + * specifically when exiting suspend to idle which can cause + * large delays during resume when the IOMMU translation layer is enabled (the default + * behavior) for NVME devices: + * + * To avoid this firmware problem, skip the SMI handler on these machines before the + * D0 transition occurs. + */ +static void amd_pmc_skip_nvme_smi_handler(u32 s2idle_bug_mmio) +{ + struct resource *res; + void __iomem *addr; + u8 val; + + res = request_mem_region_muxed(s2idle_bug_mmio, 1, "amd_pmc_pm80"); + if (!res) + return; + + addr = ioremap(s2idle_bug_mmio, 1); + if (!addr) + goto cleanup_resource; + + val = ioread8(addr); + iowrite8(val & ~BIT(0), addr); + + iounmap(addr); +cleanup_resource: + release_resource(res); + kfree(res); +} + +void amd_pmc_process_restore_quirks(struct amd_pmc_dev *dev) +{ + if (dev->quirks && dev->quirks->s2idle_bug_mmio) + amd_pmc_skip_nvme_smi_handler(dev->quirks->s2idle_bug_mmio); +} + +void amd_pmc_quirks_init(struct amd_pmc_dev *dev) +{ + const struct dmi_system_id *dmi_id; + + dmi_id = dmi_first_match(fwbug_list); + if (!dmi_id) + return; + dev->quirks = dmi_id->driver_data; + if (dev->quirks->s2idle_bug_mmio) + pr_info("Using s2idle quirk to avoid %s platform firmware bug\n", + dmi_id->ident); +} diff --git a/drivers/platform/x86/amd/pmc.c b/drivers/platform/x86/amd/pmc.c index 427905714f79cd025a1ae4d49b55d8f091485a6c..c1e788b67a74831fa6ae3bb88b203932b08c3512 100644 --- a/drivers/platform/x86/amd/pmc.c +++ b/drivers/platform/x86/amd/pmc.c @@ -28,6 +28,8 @@ #include #include +#include "pmc.h" + /* SMU communication registers */ #define AMD_PMC_REGISTER_MESSAGE 0x538 #define AMD_PMC_REGISTER_RESPONSE 0x980 @@ -45,7 +47,6 @@ #define AMD_PMC_STB_DUMMY_PC 0xC6000007 /* STB S2D(Spill to DRAM) has different message port offset */ -#define STB_SPILL_TO_DRAM 0xBE #define AMD_S2D_REGISTER_MESSAGE 0xA20 #define AMD_S2D_REGISTER_RESPONSE 0xA80 #define AMD_S2D_REGISTER_ARGUMENT 0xA88 @@ -95,11 +96,11 @@ #define AMD_CPU_ID_CB 0x14D8 #define AMD_CPU_ID_PS 0x14E8 #define AMD_CPU_ID_SP 0x14A4 +#define PCI_DEVICE_ID_AMD_1AH_M20H_ROOT 0x1507 #define PMC_MSG_DELAY_MIN_US 50 #define RESPONSE_REGISTER_LOOP_MAX 20000 -#define SOC_SUBSYSTEM_IP_MAX 12 #define DELAY_MIN_US 2000 #define DELAY_MAX_US 3000 #define FIFO_SIZE 4096 @@ -115,6 +116,7 @@ enum s2d_arg { S2D_PHYS_ADDR_LOW, S2D_PHYS_ADDR_HIGH, S2D_NUM_SAMPLES, + S2D_DRAM_SIZE, }; struct amd_pmc_bit_map { @@ -132,32 +134,21 @@ static const struct amd_pmc_bit_map soc15_ip_blk[] = { {"ISP", BIT(6)}, {"NBIO", BIT(7)}, {"DF", BIT(8)}, - {"USB0", BIT(9)}, - {"USB1", BIT(10)}, + {"USB3_0", BIT(9)}, + {"USB3_1", BIT(10)}, {"LAPIC", BIT(11)}, + {"USB3_2", BIT(12)}, + {"USB3_3", BIT(13)}, + {"USB3_4", BIT(14)}, + {"USB4_0", BIT(15)}, + {"USB4_1", BIT(16)}, + {"MPM", BIT(17)}, + {"JPEG", BIT(18)}, + {"IPU", BIT(19)}, + {"UMSCH", BIT(20)}, {} }; -struct amd_pmc_dev { - void __iomem *regbase; - void __iomem *smu_virt_addr; - void __iomem *stb_virt_addr; - void __iomem *fch_virt_addr; - bool msg_port; - u32 base_addr; - u32 cpu_id; - u32 active_ips; -/* SMU version information */ - u8 smu_program; - u8 major; - u8 minor; - u8 rev; - struct device *dev; - struct pci_dev *rdev; - struct mutex lock; /* generic mutex lock */ - struct dentry *dbgfs_dir; -}; - static bool enable_stb; module_param(enable_stb, bool, 0644); MODULE_PARM_DESC(enable_stb, "Enable the STB debug mechanism"); @@ -194,8 +185,8 @@ struct smu_metrics { u64 timein_s0i3_totaltime; u64 timein_swdrips_lastcapture; u64 timein_swdrips_totaltime; - u64 timecondition_notmet_lastcapture[SOC_SUBSYSTEM_IP_MAX]; - u64 timecondition_notmet_totaltime[SOC_SUBSYSTEM_IP_MAX]; + u64 timecondition_notmet_lastcapture[32]; + u64 timecondition_notmet_totaltime[32]; } __packed; static int amd_pmc_stb_debugfs_open(struct inode *inode, struct file *filp) @@ -261,7 +252,7 @@ static int amd_pmc_stb_debugfs_open_v2(struct inode *inode, struct file *filp) dev->msg_port = 1; /* Get the num_samples to calculate the last push location */ - ret = amd_pmc_send_cmd(dev, S2D_NUM_SAMPLES, &num_samples, STB_SPILL_TO_DRAM, 1); + ret = amd_pmc_send_cmd(dev, S2D_NUM_SAMPLES, &num_samples, dev->s2d_msg_id, true); /* Clear msg_port for other SMU operation */ dev->msg_port = 0; if (ret) { @@ -308,6 +299,23 @@ static const struct file_operations amd_pmc_stb_debugfs_fops_v2 = { .release = amd_pmc_stb_debugfs_release_v2, }; +static void amd_pmc_get_ip_info(struct amd_pmc_dev *dev) +{ + switch (dev->cpu_id) { + case AMD_CPU_ID_PCO: + case AMD_CPU_ID_RN: + case AMD_CPU_ID_YC: + case AMD_CPU_ID_CB: + dev->num_ips = 12; + dev->s2d_msg_id = 0xBE; + break; + case AMD_CPU_ID_PS: + dev->num_ips = 21; + dev->s2d_msg_id = 0x85; + break; + } +} + static int amd_pmc_setup_smu_logging(struct amd_pmc_dev *dev) { if (dev->cpu_id == AMD_CPU_ID_PCO) { @@ -317,15 +325,15 @@ static int amd_pmc_setup_smu_logging(struct amd_pmc_dev *dev) /* Get Active devices list from SMU */ if (!dev->active_ips) - amd_pmc_send_cmd(dev, 0, &dev->active_ips, SMU_MSG_GET_SUP_CONSTRAINTS, 1); + amd_pmc_send_cmd(dev, 0, &dev->active_ips, SMU_MSG_GET_SUP_CONSTRAINTS, true); /* Get dram address */ if (!dev->smu_virt_addr) { u32 phys_addr_low, phys_addr_hi; u64 smu_phys_addr; - amd_pmc_send_cmd(dev, 0, &phys_addr_low, SMU_MSG_LOG_GETDRAM_ADDR_LO, 1); - amd_pmc_send_cmd(dev, 0, &phys_addr_hi, SMU_MSG_LOG_GETDRAM_ADDR_HI, 1); + amd_pmc_send_cmd(dev, 0, &phys_addr_low, SMU_MSG_LOG_GETDRAM_ADDR_LO, true); + amd_pmc_send_cmd(dev, 0, &phys_addr_hi, SMU_MSG_LOG_GETDRAM_ADDR_HI, true); smu_phys_addr = ((u64)phys_addr_hi << 32 | phys_addr_low); dev->smu_virt_addr = devm_ioremap(dev->dev, smu_phys_addr, @@ -335,8 +343,8 @@ static int amd_pmc_setup_smu_logging(struct amd_pmc_dev *dev) } /* Start the logging */ - amd_pmc_send_cmd(dev, 0, NULL, SMU_MSG_LOG_RESET, 0); - amd_pmc_send_cmd(dev, 0, NULL, SMU_MSG_LOG_START, 0); + amd_pmc_send_cmd(dev, 0, NULL, SMU_MSG_LOG_RESET, false); + amd_pmc_send_cmd(dev, 0, NULL, SMU_MSG_LOG_START, false); return 0; } @@ -377,7 +385,7 @@ static int amd_pmc_get_smu_version(struct amd_pmc_dev *dev) if (dev->cpu_id == AMD_CPU_ID_PCO) return -ENODEV; - rc = amd_pmc_send_cmd(dev, 0, &val, SMU_MSG_GETSMUVERSION, 1); + rc = amd_pmc_send_cmd(dev, 0, &val, SMU_MSG_GETSMUVERSION, true); if (rc) return rc; @@ -469,7 +477,7 @@ static int smu_fw_info_show(struct seq_file *s, void *unused) table.timeto_resume_to_os_lastcapture); seq_puts(s, "\n=== Active time (in us) ===\n"); - for (idx = 0 ; idx < SOC_SUBSYSTEM_IP_MAX ; idx++) { + for (idx = 0 ; idx < dev->num_ips ; idx++) { if (soc15_ip_blk[idx].bit_mask & dev->active_ips) seq_printf(s, "%-8s : %lld\n", soc15_ip_blk[idx].name, table.timecondition_notmet_lastcapture[idx]); @@ -543,7 +551,7 @@ static int amd_pmc_idlemask_read(struct amd_pmc_dev *pdev, struct device *dev, } if (dev) - dev_dbg(pdev->dev, "SMU idlemask s0i3: 0x%x\n", val); + pm_pr_dbg("SMU idlemask s0i3: 0x%x\n", val); if (s) seq_printf(s, "SMU idlemask : 0x%x\n", val); @@ -562,6 +570,18 @@ static void amd_pmc_dbgfs_unregister(struct amd_pmc_dev *dev) debugfs_remove_recursive(dev->dbgfs_dir); } +static bool amd_pmc_is_stb_supported(struct amd_pmc_dev *dev) +{ + switch (dev->cpu_id) { + case AMD_CPU_ID_YC: + case AMD_CPU_ID_CB: + case AMD_CPU_ID_PS: + return true; + default: + return false; + } +} + static void amd_pmc_dbgfs_register(struct amd_pmc_dev *dev) { dev->dbgfs_dir = debugfs_create_dir("amd_pmc", NULL); @@ -573,8 +593,7 @@ static void amd_pmc_dbgfs_register(struct amd_pmc_dev *dev) &amd_pmc_idlemask_fops); /* Enable STB only when the module_param is set */ if (enable_stb) { - if (dev->cpu_id == AMD_CPU_ID_YC || dev->cpu_id == AMD_CPU_ID_CB || - dev->cpu_id == AMD_CPU_ID_PS) + if (amd_pmc_is_stb_supported(dev)) debugfs_create_file("stb_read", 0644, dev->dbgfs_dir, dev, &amd_pmc_stb_debugfs_fops_v2); else @@ -769,7 +788,7 @@ static int amd_pmc_verify_czn_rtc(struct amd_pmc_dev *pdev, u32 *arg) *arg |= (duration << 16); rc = rtc_alarm_irq_enable(rtc_device, 0); - dev_dbg(pdev->dev, "wakeup timer programmed for %lld seconds\n", duration); + pm_pr_dbg("wakeup timer programmed for %lld seconds\n", duration); return rc; } @@ -794,7 +813,7 @@ static void amd_pmc_s2idle_prepare(void) } msg = amd_pmc_get_os_hint(pdev); - rc = amd_pmc_send_cmd(pdev, arg, NULL, msg, 0); + rc = amd_pmc_send_cmd(pdev, arg, NULL, msg, false); if (rc) { dev_err(pdev->dev, "suspend failed: %d\n", rc); return; @@ -829,7 +848,7 @@ static int amd_pmc_dump_data(struct amd_pmc_dev *pdev) if (pdev->cpu_id == AMD_CPU_ID_PCO) return -ENODEV; - return amd_pmc_send_cmd(pdev, 0, NULL, SMU_MSG_LOG_DUMP_DATA, 0); + return amd_pmc_send_cmd(pdev, 0, NULL, SMU_MSG_LOG_DUMP_DATA, false); } static void amd_pmc_s2idle_restore(void) @@ -839,7 +858,7 @@ static void amd_pmc_s2idle_restore(void) u8 msg; msg = amd_pmc_get_os_hint(pdev); - rc = amd_pmc_send_cmd(pdev, 0, NULL, msg, 0); + rc = amd_pmc_send_cmd(pdev, 0, NULL, msg, false); if (rc) dev_err(pdev->dev, "resume failed: %d\n", rc); @@ -852,6 +871,8 @@ static void amd_pmc_s2idle_restore(void) /* Notify on failed entry */ amd_pmc_validate_deepest(pdev); + + amd_pmc_process_restore_quirks(pdev); } static struct acpi_s2idle_dev_ops amd_pmc_s2idle_dev_ops = { @@ -887,32 +908,69 @@ static const struct pci_device_id pmc_pci_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_AMD, AMD_CPU_ID_PCO) }, { PCI_DEVICE(PCI_VENDOR_ID_AMD, AMD_CPU_ID_RV) }, { PCI_DEVICE(PCI_VENDOR_ID_AMD, AMD_CPU_ID_SP) }, + { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_1AH_M20H_ROOT) }, { } }; +static int amd_pmc_get_dram_size(struct amd_pmc_dev *dev) +{ + int ret; + + switch (dev->cpu_id) { + case AMD_CPU_ID_YC: + if (!(dev->major > 90 || (dev->major == 90 && dev->minor > 39))) { + ret = -EINVAL; + goto err_dram_size; + } + break; + default: + ret = -EINVAL; + goto err_dram_size; + } + + ret = amd_pmc_send_cmd(dev, S2D_DRAM_SIZE, &dev->dram_size, dev->s2d_msg_id, true); + if (ret || !dev->dram_size) + goto err_dram_size; + + return 0; + +err_dram_size: + dev_err(dev->dev, "DRAM size command not supported for this platform\n"); + return ret; +} + static int amd_pmc_s2d_init(struct amd_pmc_dev *dev) { u32 phys_addr_low, phys_addr_hi; u64 stb_phys_addr; u32 size = 0; + int ret; /* Spill to DRAM feature uses separate SMU message port */ dev->msg_port = 1; - amd_pmc_send_cmd(dev, S2D_TELEMETRY_SIZE, &size, STB_SPILL_TO_DRAM, 1); + /* Get num of IP blocks within the SoC */ + amd_pmc_get_ip_info(dev); + + amd_pmc_send_cmd(dev, S2D_TELEMETRY_SIZE, &size, dev->s2d_msg_id, true); if (size != S2D_TELEMETRY_BYTES_MAX) return -EIO; + /* Get DRAM size */ + ret = amd_pmc_get_dram_size(dev); + if (ret) + dev->dram_size = S2D_TELEMETRY_DRAMBYTES_MAX; + /* Get STB DRAM address */ - amd_pmc_send_cmd(dev, S2D_PHYS_ADDR_LOW, &phys_addr_low, STB_SPILL_TO_DRAM, 1); - amd_pmc_send_cmd(dev, S2D_PHYS_ADDR_HIGH, &phys_addr_hi, STB_SPILL_TO_DRAM, 1); + amd_pmc_send_cmd(dev, S2D_PHYS_ADDR_LOW, &phys_addr_low, dev->s2d_msg_id, true); + amd_pmc_send_cmd(dev, S2D_PHYS_ADDR_HIGH, &phys_addr_hi, dev->s2d_msg_id, true); stb_phys_addr = ((u64)phys_addr_hi << 32 | phys_addr_low); /* Clear msg_port for other SMU operation */ dev->msg_port = 0; - dev->stb_virt_addr = devm_ioremap(dev->dev, stb_phys_addr, S2D_TELEMETRY_DRAMBYTES_MAX); + dev->stb_virt_addr = devm_ioremap(dev->dev, stb_phys_addr, dev->dram_size); if (!dev->stb_virt_addr) return -ENOMEM; @@ -1001,7 +1059,7 @@ static int amd_pmc_probe(struct platform_device *pdev) mutex_init(&dev->lock); - if (enable_stb && (dev->cpu_id == AMD_CPU_ID_YC || dev->cpu_id == AMD_CPU_ID_CB)) { + if (enable_stb && amd_pmc_is_stb_supported(dev)) { err = amd_pmc_s2d_init(dev); if (err) goto err_pci_dev_put; @@ -1012,6 +1070,8 @@ static int amd_pmc_probe(struct platform_device *pdev) err = acpi_register_lps0_dev(&amd_pmc_s2idle_dev_ops); if (err) dev_warn(dev->dev, "failed to register LPS0 sleep handler, expect increased power consumption\n"); + if (!disable_workarounds) + amd_pmc_quirks_init(dev); } amd_pmc_dbgfs_register(dev); @@ -1040,6 +1100,7 @@ static const struct acpi_device_id amd_pmc_acpi_ids[] = { {"AMDI0007", 0}, {"AMDI0008", 0}, {"AMDI0009", 0}, + {"AMDI000A", 0}, {"AMD0004", 0}, {"AMD0005", 0}, { } diff --git a/drivers/platform/x86/amd/pmc.h b/drivers/platform/x86/amd/pmc.h new file mode 100644 index 0000000000000000000000000000000000000000..c27bd6a5642f48cc819e25d1de6314df57868f29 --- /dev/null +++ b/drivers/platform/x86/amd/pmc.h @@ -0,0 +1,44 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * AMD SoC Power Management Controller Driver + * + * Copyright (c) 2023, Advanced Micro Devices, Inc. + * All Rights Reserved. + * + * Author: Mario Limonciello + */ + +#ifndef PMC_H +#define PMC_H + +#include +#include + +struct amd_pmc_dev { + void __iomem *regbase; + void __iomem *smu_virt_addr; + void __iomem *stb_virt_addr; + void __iomem *fch_virt_addr; + bool msg_port; + u32 base_addr; + u32 cpu_id; + u32 active_ips; + u32 dram_size; + u32 num_ips; + u32 s2d_msg_id; +/* SMU version information */ + u8 smu_program; + u8 major; + u8 minor; + u8 rev; + struct device *dev; + struct pci_dev *rdev; + struct mutex lock; /* generic mutex lock */ + struct dentry *dbgfs_dir; + struct quirk_entry *quirks; +}; + +void amd_pmc_process_restore_quirks(struct amd_pmc_dev *dev); +void amd_pmc_quirks_init(struct amd_pmc_dev *dev); + +#endif /* PMC_H */ diff --git a/drivers/platform/x86/amd/pmf/Kconfig b/drivers/platform/x86/amd/pmf/Kconfig index d87986adf91e160267921640446c2e04d96f636f..3064bc8ea167ae59f4ae2114866e1ca51e446e43 100644 --- a/drivers/platform/x86/amd/pmf/Kconfig +++ b/drivers/platform/x86/amd/pmf/Kconfig @@ -16,3 +16,14 @@ config AMD_PMF To compile this driver as a module, choose M here: the module will be called amd_pmf. + +config AMD_PMF_DEBUG + bool "PMF debug information" + depends on AMD_PMF + help + Enabling this option would give more debug information on the OEM fed + power setting values for each of the PMF feature. PMF driver gets this + information after evaluating a ACPI method and the information is stored + in the PMF config store. + + Say Y here to enable more debug logs and Say N here if you are not sure. diff --git a/drivers/platform/x86/amd/pmf/auto-mode.c b/drivers/platform/x86/amd/pmf/auto-mode.c index 96a8e1832c05e9cbc9f50bb1305e7bfb92318213..02ff68be10d0124a77760fb726b9d2d604c97f3a 100644 --- a/drivers/platform/x86/amd/pmf/auto-mode.c +++ b/drivers/platform/x86/amd/pmf/auto-mode.c @@ -15,6 +15,100 @@ static struct auto_mode_mode_config config_store; static const char *state_as_str(unsigned int state); +#ifdef CONFIG_AMD_PMF_DEBUG +static void amd_pmf_dump_auto_mode_defaults(struct auto_mode_mode_config *data) +{ + struct auto_mode_mode_settings *its_mode; + + pr_debug("Auto Mode Data - BEGIN\n"); + + /* time constant */ + pr_debug("balanced_to_perf: %u ms\n", + data->transition[AUTO_TRANSITION_TO_PERFORMANCE].time_constant); + pr_debug("perf_to_balanced: %u ms\n", + data->transition[AUTO_TRANSITION_FROM_PERFORMANCE_TO_BALANCE].time_constant); + pr_debug("quiet_to_balanced: %u ms\n", + data->transition[AUTO_TRANSITION_FROM_QUIET_TO_BALANCE].time_constant); + pr_debug("balanced_to_quiet: %u ms\n", + data->transition[AUTO_TRANSITION_TO_QUIET].time_constant); + + /* power floor */ + pr_debug("pfloor_perf: %u mW\n", data->mode_set[AUTO_PERFORMANCE].power_floor); + pr_debug("pfloor_balanced: %u mW\n", data->mode_set[AUTO_BALANCE].power_floor); + pr_debug("pfloor_quiet: %u mW\n", data->mode_set[AUTO_QUIET].power_floor); + + /* Power delta for mode change */ + pr_debug("pd_balanced_to_perf: %u mW\n", + data->transition[AUTO_TRANSITION_TO_PERFORMANCE].power_delta); + pr_debug("pd_perf_to_balanced: %u mW\n", + data->transition[AUTO_TRANSITION_FROM_PERFORMANCE_TO_BALANCE].power_delta); + pr_debug("pd_quiet_to_balanced: %u mW\n", + data->transition[AUTO_TRANSITION_FROM_QUIET_TO_BALANCE].power_delta); + pr_debug("pd_balanced_to_quiet: %u mW\n", + data->transition[AUTO_TRANSITION_TO_QUIET].power_delta); + + /* skin temperature limits */ + its_mode = &data->mode_set[AUTO_PERFORMANCE_ON_LAP]; + pr_debug("stt_apu_perf_on_lap: %u C\n", + its_mode->power_control.stt_skin_temp[STT_TEMP_APU]); + pr_debug("stt_hs2_perf_on_lap: %u C\n", + its_mode->power_control.stt_skin_temp[STT_TEMP_HS2]); + pr_debug("stt_min_limit_perf_on_lap: %u mW\n", its_mode->power_control.stt_min); + + its_mode = &data->mode_set[AUTO_PERFORMANCE]; + pr_debug("stt_apu_perf: %u C\n", its_mode->power_control.stt_skin_temp[STT_TEMP_APU]); + pr_debug("stt_hs2_perf: %u C\n", its_mode->power_control.stt_skin_temp[STT_TEMP_HS2]); + pr_debug("stt_min_limit_perf: %u mW\n", its_mode->power_control.stt_min); + + its_mode = &data->mode_set[AUTO_BALANCE]; + pr_debug("stt_apu_balanced: %u C\n", its_mode->power_control.stt_skin_temp[STT_TEMP_APU]); + pr_debug("stt_hs2_balanced: %u C\n", its_mode->power_control.stt_skin_temp[STT_TEMP_HS2]); + pr_debug("stt_min_limit_balanced: %u mW\n", its_mode->power_control.stt_min); + + its_mode = &data->mode_set[AUTO_QUIET]; + pr_debug("stt_apu_quiet: %u C\n", its_mode->power_control.stt_skin_temp[STT_TEMP_APU]); + pr_debug("stt_hs2_quiet: %u C\n", its_mode->power_control.stt_skin_temp[STT_TEMP_HS2]); + pr_debug("stt_min_limit_quiet: %u mW\n", its_mode->power_control.stt_min); + + /* SPL based power limits */ + its_mode = &data->mode_set[AUTO_PERFORMANCE_ON_LAP]; + pr_debug("fppt_perf_on_lap: %u mW\n", its_mode->power_control.fppt); + pr_debug("sppt_perf_on_lap: %u mW\n", its_mode->power_control.sppt); + pr_debug("spl_perf_on_lap: %u mW\n", its_mode->power_control.spl); + pr_debug("sppt_apu_only_perf_on_lap: %u mW\n", its_mode->power_control.sppt_apu_only); + + its_mode = &data->mode_set[AUTO_PERFORMANCE]; + pr_debug("fppt_perf: %u mW\n", its_mode->power_control.fppt); + pr_debug("sppt_perf: %u mW\n", its_mode->power_control.sppt); + pr_debug("spl_perf: %u mW\n", its_mode->power_control.spl); + pr_debug("sppt_apu_only_perf: %u mW\n", its_mode->power_control.sppt_apu_only); + + its_mode = &data->mode_set[AUTO_BALANCE]; + pr_debug("fppt_balanced: %u mW\n", its_mode->power_control.fppt); + pr_debug("sppt_balanced: %u mW\n", its_mode->power_control.sppt); + pr_debug("spl_balanced: %u mW\n", its_mode->power_control.spl); + pr_debug("sppt_apu_only_balanced: %u mW\n", its_mode->power_control.sppt_apu_only); + + its_mode = &data->mode_set[AUTO_QUIET]; + pr_debug("fppt_quiet: %u mW\n", its_mode->power_control.fppt); + pr_debug("sppt_quiet: %u mW\n", its_mode->power_control.sppt); + pr_debug("spl_quiet: %u mW\n", its_mode->power_control.spl); + pr_debug("sppt_apu_only_quiet: %u mW\n", its_mode->power_control.sppt_apu_only); + + /* Fan ID */ + pr_debug("fan_id_perf: %lu\n", + data->mode_set[AUTO_PERFORMANCE].fan_control.fan_id); + pr_debug("fan_id_balanced: %lu\n", + data->mode_set[AUTO_BALANCE].fan_control.fan_id); + pr_debug("fan_id_quiet: %lu\n", + data->mode_set[AUTO_QUIET].fan_control.fan_id); + + pr_debug("Auto Mode Data - END\n"); +} +#else +static void amd_pmf_dump_auto_mode_defaults(struct auto_mode_mode_config *data) {} +#endif + static void amd_pmf_set_automode(struct amd_pmf_dev *dev, int idx, struct auto_mode_mode_config *table) { @@ -85,11 +179,34 @@ void amd_pmf_trans_automode(struct amd_pmf_dev *dev, int socket_power, ktime_t t config_store.transition[i].applied = false; update = true; } + +#ifdef CONFIG_AMD_PMF_DEBUG + dev_dbg(dev->dev, "[AUTO MODE] average_power : %d mW mode: %s\n", avg_power, + state_as_str(config_store.current_mode)); + + dev_dbg(dev->dev, "[AUTO MODE] time: %lld ms timer: %u ms tc: %u ms\n", + time_elapsed_ms, config_store.transition[i].timer, + config_store.transition[i].time_constant); + + dev_dbg(dev->dev, "[AUTO MODE] shiftup: %u pt: %u mW pf: %u mW pd: %u mW\n", + config_store.transition[i].shifting_up, + config_store.transition[i].power_threshold, + config_store.mode_set[i].power_floor, + config_store.transition[i].power_delta); +#endif } dev_dbg(dev->dev, "[AUTO_MODE] avg power: %u mW mode: %s\n", avg_power, state_as_str(config_store.current_mode)); +#ifdef CONFIG_AMD_PMF_DEBUG + dev_dbg(dev->dev, "[AUTO MODE] priority1: %u priority2: %u priority3: %u priority4: %u\n", + config_store.transition[0].applied, + config_store.transition[1].applied, + config_store.transition[2].applied, + config_store.transition[3].applied); +#endif + if (update) { for (j = 0; j < AUTO_TRANSITION_MAX; j++) { /* Apply the mode with highest priority indentified */ @@ -140,6 +257,30 @@ static void amd_pmf_get_power_threshold(void) config_store.transition[AUTO_TRANSITION_FROM_PERFORMANCE_TO_BALANCE].power_threshold = config_store.mode_set[AUTO_PERFORMANCE].power_floor - config_store.transition[AUTO_TRANSITION_FROM_PERFORMANCE_TO_BALANCE].power_delta; + +#ifdef CONFIG_AMD_PMF_DEBUG + pr_debug("[AUTO MODE TO_QUIET] pt: %u mW pf: %u mW pd: %u mW\n", + config_store.transition[AUTO_TRANSITION_TO_QUIET].power_threshold, + config_store.mode_set[AUTO_BALANCE].power_floor, + config_store.transition[AUTO_TRANSITION_TO_QUIET].power_delta); + + pr_debug("[AUTO MODE TO_PERFORMANCE] pt: %u mW pf: %u mW pd: %u mW\n", + config_store.transition[AUTO_TRANSITION_TO_PERFORMANCE].power_threshold, + config_store.mode_set[AUTO_BALANCE].power_floor, + config_store.transition[AUTO_TRANSITION_TO_PERFORMANCE].power_delta); + + pr_debug("[AUTO MODE QUIET_TO_BALANCE] pt: %u mW pf: %u mW pd: %u mW\n", + config_store.transition[AUTO_TRANSITION_FROM_QUIET_TO_BALANCE] + .power_threshold, + config_store.mode_set[AUTO_QUIET].power_floor, + config_store.transition[AUTO_TRANSITION_FROM_QUIET_TO_BALANCE].power_delta); + + pr_debug("[AUTO MODE PERFORMANCE_TO_BALANCE] pt: %u mW pf: %u mW pd: %u mW\n", + config_store.transition[AUTO_TRANSITION_FROM_PERFORMANCE_TO_BALANCE] + .power_threshold, + config_store.mode_set[AUTO_PERFORMANCE].power_floor, + config_store.transition[AUTO_TRANSITION_FROM_PERFORMANCE_TO_BALANCE].power_delta); +#endif } static const char *state_as_str(unsigned int state) @@ -262,6 +403,8 @@ static void amd_pmf_load_defaults_auto_mode(struct amd_pmf_dev *dev) /* set to initial default values */ config_store.current_mode = AUTO_BALANCE; dev->socket_power_history_idx = -1; + + amd_pmf_dump_auto_mode_defaults(&config_store); } int amd_pmf_reset_amt(struct amd_pmf_dev *dev) diff --git a/drivers/platform/x86/amd/pmf/cnqf.c b/drivers/platform/x86/amd/pmf/cnqf.c index 4beb22a194667d9f4d0bb67fb20c1de510a63eb9..539b186e90276c6d0bc1bed37b0438fbb256d968 100644 --- a/drivers/platform/x86/amd/pmf/cnqf.c +++ b/drivers/platform/x86/amd/pmf/cnqf.c @@ -13,6 +13,61 @@ static struct cnqf_config config_store; +#ifdef CONFIG_AMD_PMF_DEBUG +static const char *state_as_str_cnqf(unsigned int state) +{ + switch (state) { + case APMF_CNQF_TURBO: + return "turbo"; + case APMF_CNQF_PERFORMANCE: + return "performance"; + case APMF_CNQF_BALANCE: + return "balance"; + case APMF_CNQF_QUIET: + return "quiet"; + default: + return "Unknown CnQF State"; + } +} + +static void amd_pmf_cnqf_dump_defaults(struct apmf_dyn_slider_output *data, int idx) +{ + int i; + + pr_debug("Dynamic Slider %s Defaults - BEGIN\n", idx ? "DC" : "AC"); + pr_debug("size: %u\n", data->size); + pr_debug("flags: 0x%x\n", data->flags); + + /* Time constants */ + pr_debug("t_perf_to_turbo: %u ms\n", data->t_perf_to_turbo); + pr_debug("t_balanced_to_perf: %u ms\n", data->t_balanced_to_perf); + pr_debug("t_quiet_to_balanced: %u ms\n", data->t_quiet_to_balanced); + pr_debug("t_balanced_to_quiet: %u ms\n", data->t_balanced_to_quiet); + pr_debug("t_perf_to_balanced: %u ms\n", data->t_perf_to_balanced); + pr_debug("t_turbo_to_perf: %u ms\n", data->t_turbo_to_perf); + + for (i = 0 ; i < CNQF_MODE_MAX ; i++) { + pr_debug("pfloor_%s: %u mW\n", state_as_str_cnqf(i), data->ps[i].pfloor); + pr_debug("fppt_%s: %u mW\n", state_as_str_cnqf(i), data->ps[i].fppt); + pr_debug("sppt_%s: %u mW\n", state_as_str_cnqf(i), data->ps[i].sppt); + pr_debug("sppt_apuonly_%s: %u mW\n", + state_as_str_cnqf(i), data->ps[i].sppt_apu_only); + pr_debug("spl_%s: %u mW\n", state_as_str_cnqf(i), data->ps[i].spl); + pr_debug("stt_minlimit_%s: %u mW\n", + state_as_str_cnqf(i), data->ps[i].stt_min_limit); + pr_debug("stt_skintemp_apu_%s: %u C\n", state_as_str_cnqf(i), + data->ps[i].stt_skintemp[STT_TEMP_APU]); + pr_debug("stt_skintemp_hs2_%s: %u C\n", state_as_str_cnqf(i), + data->ps[i].stt_skintemp[STT_TEMP_HS2]); + pr_debug("fan_id_%s: %u\n", state_as_str_cnqf(i), data->ps[i].fan_id); + } + + pr_debug("Dynamic Slider %s Defaults - END\n", idx ? "DC" : "AC"); +} +#else +static void amd_pmf_cnqf_dump_defaults(struct apmf_dyn_slider_output *data, int idx) {} +#endif + static int amd_pmf_set_cnqf(struct amd_pmf_dev *dev, int src, int idx, struct cnqf_config *table) { @@ -120,6 +175,13 @@ int amd_pmf_trans_cnqf(struct amd_pmf_dev *dev, int socket_power, ktime_t time_l config_store.trans_param[src][i].count++; tp = &config_store.trans_param[src][i]; + +#ifdef CONFIG_AMD_PMF_DEBUG + dev_dbg(dev->dev, "avg_power: %u mW total_power: %u mW count: %u timer: %u ms\n", + avg_power, config_store.trans_param[src][i].total_power, + config_store.trans_param[src][i].count, + config_store.trans_param[src][i].timer); +#endif if (tp->timer >= tp->time_constant && tp->count) { avg_power = tp->total_power / tp->count; @@ -140,6 +202,18 @@ int amd_pmf_trans_cnqf(struct amd_pmf_dev *dev, int socket_power, ktime_t time_l dev_dbg(dev->dev, "[CNQF] Avg power: %u mW socket power: %u mW mode:%s\n", avg_power, socket_power, state_as_str(config_store.current_mode)); +#ifdef CONFIG_AMD_PMF_DEBUG + dev_dbg(dev->dev, "[CNQF] priority1: %u priority2: %u priority3: %u\n", + config_store.trans_param[src][0].priority, + config_store.trans_param[src][1].priority, + config_store.trans_param[src][2].priority); + + dev_dbg(dev->dev, "[CNQF] priority4: %u priority5: %u priority6: %u\n", + config_store.trans_param[src][3].priority, + config_store.trans_param[src][4].priority, + config_store.trans_param[src][5].priority); +#endif + for (j = 0; j < CNQF_TRANSITION_MAX; j++) { /* apply the highest priority */ if (config_store.trans_param[src][j].priority) { @@ -284,6 +358,7 @@ static int amd_pmf_load_defaults_cnqf(struct amd_pmf_dev *dev) return ret; } + amd_pmf_cnqf_dump_defaults(&out, i); amd_pmf_update_mode_set(i, &out); amd_pmf_update_trans_data(i, &out); amd_pmf_update_power_threshold(i); diff --git a/drivers/platform/x86/amd/pmf/core.c b/drivers/platform/x86/amd/pmf/core.c index ee5f124f78b6d712a58e944fe114f817e6c76ae3..d8732557f9db163290cf3814dcf7006dd3e42521 100644 --- a/drivers/platform/x86/amd/pmf/core.c +++ b/drivers/platform/x86/amd/pmf/core.c @@ -40,6 +40,7 @@ /* List of supported CPU ids */ #define AMD_CPU_ID_RMB 0x14b5 #define AMD_CPU_ID_PS 0x14e8 +#define PCI_DEVICE_ID_AMD_1AH_M20H_ROOT 0x1507 #define PMF_MSG_DELAY_MIN_US 50 #define RESPONSE_REGISTER_LOOP_MAX 20000 @@ -242,6 +243,7 @@ int amd_pmf_send_cmd(struct amd_pmf_dev *dev, u8 message, bool get, u32 arg, u32 static const struct pci_device_id pmf_pci_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_AMD, AMD_CPU_ID_RMB) }, { PCI_DEVICE(PCI_VENDOR_ID_AMD, AMD_CPU_ID_PS) }, + { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_1AH_M20H_ROOT) }, { } }; @@ -297,6 +299,8 @@ static void amd_pmf_init_features(struct amd_pmf_dev *dev) /* Enable Static Slider */ if (is_apmf_func_supported(dev, APMF_FUNC_STATIC_SLIDER_GRANULAR)) { amd_pmf_init_sps(dev); + dev->pwr_src_notifier.notifier_call = amd_pmf_pwr_src_notify_call; + power_supply_reg_notifier(&dev->pwr_src_notifier); dev_dbg(dev->dev, "SPS enabled and Platform Profiles registered\n"); } @@ -315,8 +319,10 @@ static void amd_pmf_init_features(struct amd_pmf_dev *dev) static void amd_pmf_deinit_features(struct amd_pmf_dev *dev) { - if (is_apmf_func_supported(dev, APMF_FUNC_STATIC_SLIDER_GRANULAR)) + if (is_apmf_func_supported(dev, APMF_FUNC_STATIC_SLIDER_GRANULAR)) { + power_supply_unreg_notifier(&dev->pwr_src_notifier); amd_pmf_deinit_sps(dev); + } if (is_apmf_func_supported(dev, APMF_FUNC_AUTO_MODE)) { amd_pmf_deinit_auto_mode(dev); @@ -329,6 +335,7 @@ static void amd_pmf_deinit_features(struct amd_pmf_dev *dev) static const struct acpi_device_id amd_pmf_acpi_ids[] = { {"AMDI0100", 0x100}, {"AMDI0102", 0}, + {"AMDI0103", 0}, { } }; MODULE_DEVICE_TABLE(acpi, amd_pmf_acpi_ids); @@ -399,9 +406,6 @@ static int amd_pmf_probe(struct platform_device *pdev) apmf_install_handler(dev); amd_pmf_dbgfs_register(dev); - dev->pwr_src_notifier.notifier_call = amd_pmf_pwr_src_notify_call; - power_supply_reg_notifier(&dev->pwr_src_notifier); - dev_info(dev->dev, "registered PMF device successfully\n"); return 0; @@ -411,7 +415,6 @@ static void amd_pmf_remove(struct platform_device *pdev) { struct amd_pmf_dev *dev = platform_get_drvdata(pdev); - power_supply_unreg_notifier(&dev->pwr_src_notifier); amd_pmf_deinit_features(dev); apmf_acpi_deinit(dev); amd_pmf_dbgfs_unregister(dev); diff --git a/drivers/platform/x86/amd/pmf/sps.c b/drivers/platform/x86/amd/pmf/sps.c index bed762d47a14a5edcf39e78387041834d4c2033f..445ff053b4dfa5de0aa9375c18fe6d8b431c22ef 100644 --- a/drivers/platform/x86/amd/pmf/sps.c +++ b/drivers/platform/x86/amd/pmf/sps.c @@ -12,6 +12,60 @@ static struct amd_pmf_static_slider_granular config_store; +#ifdef CONFIG_AMD_PMF_DEBUG +static const char *slider_as_str(unsigned int state) +{ + switch (state) { + case POWER_MODE_PERFORMANCE: + return "PERFORMANCE"; + case POWER_MODE_BALANCED_POWER: + return "BALANCED_POWER"; + case POWER_MODE_POWER_SAVER: + return "POWER_SAVER"; + default: + return "Unknown Slider State"; + } +} + +static const char *source_as_str(unsigned int state) +{ + switch (state) { + case POWER_SOURCE_AC: + return "AC"; + case POWER_SOURCE_DC: + return "DC"; + default: + return "Unknown Power State"; + } +} + +static void amd_pmf_dump_sps_defaults(struct amd_pmf_static_slider_granular *data) +{ + int i, j; + + pr_debug("Static Slider Data - BEGIN\n"); + + for (i = 0; i < POWER_SOURCE_MAX; i++) { + for (j = 0; j < POWER_MODE_MAX; j++) { + pr_debug("--- Source:%s Mode:%s ---\n", source_as_str(i), slider_as_str(j)); + pr_debug("SPL: %u mW\n", data->prop[i][j].spl); + pr_debug("SPPT: %u mW\n", data->prop[i][j].sppt); + pr_debug("SPPT_ApuOnly: %u mW\n", data->prop[i][j].sppt_apu_only); + pr_debug("FPPT: %u mW\n", data->prop[i][j].fppt); + pr_debug("STTMinLimit: %u mW\n", data->prop[i][j].stt_min); + pr_debug("STT_SkinTempLimit_APU: %u C\n", + data->prop[i][j].stt_skin_temp[STT_TEMP_APU]); + pr_debug("STT_SkinTempLimit_HS2: %u C\n", + data->prop[i][j].stt_skin_temp[STT_TEMP_HS2]); + } + } + + pr_debug("Static Slider Data - END\n"); +} +#else +static void amd_pmf_dump_sps_defaults(struct amd_pmf_static_slider_granular *data) {} +#endif + static void amd_pmf_load_defaults_sps(struct amd_pmf_dev *dev) { struct apmf_static_slider_granular_output output; @@ -36,6 +90,7 @@ static void amd_pmf_load_defaults_sps(struct amd_pmf_dev *dev) idx++; } } + amd_pmf_dump_sps_defaults(&config_store); } void amd_pmf_update_slider(struct amd_pmf_dev *dev, bool op, int idx, diff --git a/drivers/platform/x86/apple-gmux.c b/drivers/platform/x86/apple-gmux.c index e02b4aea4f1e4a0e9087810d70d1041a6b74f937..cadbb557a108b81014fefc07775117554b2d4bb8 100644 --- a/drivers/platform/x86/apple-gmux.c +++ b/drivers/platform/x86/apple-gmux.c @@ -278,7 +278,7 @@ static u32 gmux_mmio_read32(struct apple_gmux_data *gmux_data, int port) iowrite8(GMUX_MMIO_READ | sizeof(val), gmux_data->iomem_base + GMUX_MMIO_COMMAND_SEND); gmux_mmio_wait(gmux_data); - val = be32_to_cpu(ioread32(gmux_data->iomem_base)); + val = ioread32be(gmux_data->iomem_base); mutex_unlock(&gmux_data->index_lock); return val; @@ -288,7 +288,7 @@ static void gmux_mmio_write32(struct apple_gmux_data *gmux_data, int port, u32 val) { mutex_lock(&gmux_data->index_lock); - iowrite32(cpu_to_be32(val), gmux_data->iomem_base); + iowrite32be(val, gmux_data->iomem_base); iowrite8(port & 0xff, gmux_data->iomem_base + GMUX_MMIO_PORT_SELECT); iowrite8(GMUX_MMIO_WRITE | sizeof(val), gmux_data->iomem_base + GMUX_MMIO_COMMAND_SEND); diff --git a/drivers/platform/x86/asus-tf103c-dock.c b/drivers/platform/x86/asus-tf103c-dock.c index aeb1138464dfe8d9a82fefe3ade8a83b49913ad6..8f0f87637c5fb5aff2eb655bfb316bb68161277f 100644 --- a/drivers/platform/x86/asus-tf103c-dock.c +++ b/drivers/platform/x86/asus-tf103c-dock.c @@ -933,7 +933,7 @@ static struct i2c_driver tf103c_dock_driver = { .pm = &tf103c_dock_pm_ops, .acpi_match_table = tf103c_dock_acpi_match, }, - .probe_new = tf103c_dock_probe, + .probe = tf103c_dock_probe, .remove = tf103c_dock_remove, }; module_i2c_driver(tf103c_dock_driver); diff --git a/drivers/platform/x86/dell/dell-rbtn.c b/drivers/platform/x86/dell/dell-rbtn.c index aa0e6c90749426c1ecd337c6674b74f8b7fcab62..c8fcb537fd65db7283ac37567e192fbe2c0588ee 100644 --- a/drivers/platform/x86/dell/dell-rbtn.c +++ b/drivers/platform/x86/dell/dell-rbtn.c @@ -395,16 +395,16 @@ static int rbtn_add(struct acpi_device *device) return -EINVAL; } + rbtn_data = devm_kzalloc(&device->dev, sizeof(*rbtn_data), GFP_KERNEL); + if (!rbtn_data) + return -ENOMEM; + ret = rbtn_acquire(device, true); if (ret < 0) { dev_err(&device->dev, "Cannot enable device\n"); return ret; } - rbtn_data = devm_kzalloc(&device->dev, sizeof(*rbtn_data), GFP_KERNEL); - if (!rbtn_data) - return -ENOMEM; - rbtn_data->type = type; device->driver_data = rbtn_data; @@ -420,10 +420,12 @@ static int rbtn_add(struct acpi_device *device) break; default: ret = -EINVAL; + break; } + if (ret) + rbtn_acquire(device, false); return ret; - } static void rbtn_remove(struct acpi_device *device) @@ -442,7 +444,6 @@ static void rbtn_remove(struct acpi_device *device) } rbtn_acquire(device, false); - device->driver_data = NULL; } static void rbtn_notify(struct acpi_device *device, u32 event) diff --git a/drivers/platform/x86/dell/dell-wmi-ddv.c b/drivers/platform/x86/dell/dell-wmi-ddv.c index 2750dee99c3e255a8821b591139775c1d4c641cf..db1e9240dd02c27e07926dd865222288632e3d4e 100644 --- a/drivers/platform/x86/dell/dell-wmi-ddv.c +++ b/drivers/platform/x86/dell/dell-wmi-ddv.c @@ -616,7 +616,8 @@ static int dell_wmi_ddv_hwmon_add(struct dell_wmi_ddv_data *data) } if (index < 2) { - ret = -ENODEV; + /* Finding no available sensors is not an error */ + ret = 0; goto err_release; } @@ -841,13 +842,13 @@ static int dell_wmi_ddv_probe(struct wmi_device *wdev, const void *context) if (IS_REACHABLE(CONFIG_ACPI_BATTERY)) { ret = dell_wmi_ddv_battery_add(data); - if (ret < 0 && ret != -ENODEV) + if (ret < 0) dev_warn(&wdev->dev, "Unable to register ACPI battery hook: %d\n", ret); } if (IS_REACHABLE(CONFIG_HWMON)) { ret = dell_wmi_ddv_hwmon_add(data); - if (ret < 0 && ret != -ENODEV) + if (ret < 0) dev_warn(&wdev->dev, "Unable to register hwmon interface: %d\n", ret); } diff --git a/drivers/platform/x86/dell/dell-wmi-sysman/sysman.c b/drivers/platform/x86/dell/dell-wmi-sysman/sysman.c index 0285b47d99d13d1d4deb49956571d3ed25e5dcda..b68dd11cb8924a741341250c49cde15335a4e8d6 100644 --- a/drivers/platform/x86/dell/dell-wmi-sysman/sysman.c +++ b/drivers/platform/x86/dell/dell-wmi-sysman/sysman.c @@ -303,16 +303,13 @@ union acpi_object *get_wmiobj_pointer(int instance_id, const char *guid_string) */ int get_instance_count(const char *guid_string) { - union acpi_object *wmi_obj = NULL; - int i = 0; + int ret; - do { - kfree(wmi_obj); - wmi_obj = get_wmiobj_pointer(i, guid_string); - i++; - } while (wmi_obj); + ret = wmi_instance_count(guid_string); + if (ret < 0) + return 0; - return (i-1); + return ret; } /** diff --git a/drivers/platform/x86/gigabyte-wmi.c b/drivers/platform/x86/gigabyte-wmi.c index 2a426040f749efec340301127caa9baf57adf17a..f6ba88baee4da8734809013067a8ecbd17ff7d3d 100644 --- a/drivers/platform/x86/gigabyte-wmi.c +++ b/drivers/platform/x86/gigabyte-wmi.c @@ -5,7 +5,6 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include -#include #include #include #include @@ -13,10 +12,6 @@ #define GIGABYTE_WMI_GUID "DEADBEEF-2001-0000-00A0-C90629100000" #define NUM_TEMPERATURE_SENSORS 6 -static bool force_load; -module_param(force_load, bool, 0444); -MODULE_PARM_DESC(force_load, "Force loading on unknown platform"); - static u8 usable_sensors_mask; enum gigabyte_wmi_commandtype { @@ -99,7 +94,7 @@ static umode_t gigabyte_wmi_hwmon_is_visible(const void *data, enum hwmon_sensor return usable_sensors_mask & BIT(channel) ? 0444 : 0; } -static const struct hwmon_channel_info *gigabyte_wmi_hwmon_info[] = { +static const struct hwmon_channel_info * const gigabyte_wmi_hwmon_info[] = { HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT, HWMON_T_INPUT, @@ -133,49 +128,10 @@ static u8 gigabyte_wmi_detect_sensor_usability(struct wmi_device *wdev) return r; } -#define DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME(name) \ - { .matches = { \ - DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "Gigabyte Technology Co., Ltd."), \ - DMI_EXACT_MATCH(DMI_BOARD_NAME, name), \ - }} - -static const struct dmi_system_id gigabyte_wmi_known_working_platforms[] = { - DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("A320M-S2H V2-CF"), - DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B450M DS3H-CF"), - DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B450M DS3H WIFI-CF"), - DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B450M S2H V2"), - DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B550 AORUS ELITE AX V2"), - DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B550 AORUS ELITE"), - DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B550 AORUS ELITE V2"), - DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B550 GAMING X V2"), - DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B550I AORUS PRO AX"), - DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B550M AORUS PRO-P"), - DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B550M DS3H"), - DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B650 AORUS ELITE AX"), - DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B660 GAMING X DDR4"), - DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B660I AORUS PRO DDR4"), - DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("Z390 I AORUS PRO WIFI-CF"), - DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("Z490 AORUS ELITE AC"), - DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("X570 AORUS ELITE"), - DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("X570 AORUS ELITE WIFI"), - DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("X570 GAMING X"), - DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("X570 I AORUS PRO WIFI"), - DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("X570 UD"), - DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("X570S AORUS ELITE"), - DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("Z690M AORUS ELITE AX DDR4"), - { } -}; - static int gigabyte_wmi_probe(struct wmi_device *wdev, const void *context) { struct device *hwmon_dev; - if (!dmi_check_system(gigabyte_wmi_known_working_platforms)) { - if (!force_load) - return -ENODEV; - dev_warn(&wdev->dev, "Forcing load on unknown platform"); - } - usable_sensors_mask = gigabyte_wmi_detect_sensor_usability(wdev); if (!usable_sensors_mask) { dev_info(&wdev->dev, "No temperature sensors usable"); diff --git a/drivers/platform/x86/hp/hp-wmi.c b/drivers/platform/x86/hp/hp-wmi.c index 6364ae2627058384a71da53504693e067687f204..e76e5458db35095a55204848f3c7bdc8907fe09c 100644 --- a/drivers/platform/x86/hp/hp-wmi.c +++ b/drivers/platform/x86/hp/hp-wmi.c @@ -66,6 +66,11 @@ static const char *const omen_thermal_profile_force_v0_boards[] = { "8607", "8746", "8747", "8749", "874A", "8748" }; +/* DMI Board names of Victus laptops */ +static const char * const victus_thermal_profile_boards[] = { + "8A25" +}; + enum hp_wmi_radio { HPWMI_WIFI = 0x0, HPWMI_BLUETOOTH = 0x1, @@ -90,6 +95,7 @@ enum hp_wmi_event_ids { HPWMI_PEAKSHIFT_PERIOD = 0x0F, HPWMI_BATTERY_CHARGE_PERIOD = 0x10, HPWMI_SANITIZATION_MODE = 0x17, + HPWMI_CAMERA_TOGGLE = 0x1A, HPWMI_OMEN_KEY = 0x1D, HPWMI_SMART_EXPERIENCE_APP = 0x21, }; @@ -176,6 +182,12 @@ enum hp_thermal_profile_omen_v1 { HP_OMEN_V1_THERMAL_PROFILE_COOL = 0x50, }; +enum hp_thermal_profile_victus { + HP_VICTUS_THERMAL_PROFILE_DEFAULT = 0x00, + HP_VICTUS_THERMAL_PROFILE_PERFORMANCE = 0x01, + HP_VICTUS_THERMAL_PROFILE_QUIET = 0x03, +}; + enum hp_thermal_profile { HP_THERMAL_PROFILE_PERFORMANCE = 0x00, HP_THERMAL_PROFILE_DEFAULT = 0x01, @@ -222,6 +234,7 @@ static const struct key_entry hp_wmi_keymap[] = { { KE_IGNORE, 0x121a4, }, /* Win Lock Off */ { KE_KEY, 0x21a5, { KEY_PROG2 } }, /* HP Omen Key */ { KE_KEY, 0x21a7, { KEY_FN_ESC } }, + { KE_KEY, 0x21a8, { KEY_PROG2 } }, /* HP Envy x360 programmable key */ { KE_KEY, 0x21a9, { KEY_TOUCHPAD_OFF } }, { KE_KEY, 0x121a9, { KEY_TOUCHPAD_ON } }, { KE_KEY, 0x231b, { KEY_HELP } }, @@ -229,6 +242,7 @@ static const struct key_entry hp_wmi_keymap[] = { }; static struct input_dev *hp_wmi_input_dev; +static struct input_dev *camera_shutter_input_dev; static struct platform_device *hp_wmi_platform_dev; static struct platform_profile_handler platform_profile_handler; static bool platform_profile_support; @@ -740,6 +754,33 @@ static ssize_t postcode_store(struct device *dev, struct device_attribute *attr, return count; } +static int camera_shutter_input_setup(void) +{ + int err; + + camera_shutter_input_dev = input_allocate_device(); + if (!camera_shutter_input_dev) + return -ENOMEM; + + camera_shutter_input_dev->name = "HP WMI camera shutter"; + camera_shutter_input_dev->phys = "wmi/input1"; + camera_shutter_input_dev->id.bustype = BUS_HOST; + + __set_bit(EV_SW, camera_shutter_input_dev->evbit); + __set_bit(SW_CAMERA_LENS_COVER, camera_shutter_input_dev->swbit); + + err = input_register_device(camera_shutter_input_dev); + if (err) + goto err_free_dev; + + return 0; + + err_free_dev: + input_free_device(camera_shutter_input_dev); + camera_shutter_input_dev = NULL; + return err; +} + static DEVICE_ATTR_RO(display); static DEVICE_ATTR_RO(hddtemp); static DEVICE_ATTR_RW(als); @@ -816,11 +857,20 @@ static void hp_wmi_notify(u32 value, void *context) case HPWMI_SMART_ADAPTER: break; case HPWMI_BEZEL_BUTTON: - case HPWMI_OMEN_KEY: key_code = hp_wmi_read_int(HPWMI_HOTKEY_QUERY); if (key_code < 0) break; + if (!sparse_keymap_report_event(hp_wmi_input_dev, + key_code, 1, true)) + pr_info("Unknown key code - 0x%x\n", key_code); + break; + case HPWMI_OMEN_KEY: + if (event_data) /* Only should be true for HP Omen */ + key_code = event_data; + else + key_code = hp_wmi_read_int(HPWMI_HOTKEY_QUERY); + if (!sparse_keymap_report_event(hp_wmi_input_dev, key_code, 1, true)) pr_info("Unknown key code - 0x%x\n", key_code); @@ -867,6 +917,20 @@ static void hp_wmi_notify(u32 value, void *context) break; case HPWMI_SANITIZATION_MODE: break; + case HPWMI_CAMERA_TOGGLE: + if (!camera_shutter_input_dev) + if (camera_shutter_input_setup()) { + pr_err("Failed to setup camera shutter input device\n"); + break; + } + if (event_data == 0xff) + input_report_switch(camera_shutter_input_dev, SW_CAMERA_LENS_COVER, 1); + else if (event_data == 0xfe) + input_report_switch(camera_shutter_input_dev, SW_CAMERA_LENS_COVER, 0); + else + pr_warn("Unknown camera shutter state - 0x%x\n", event_data); + input_sync(camera_shutter_input_dev); + break; case HPWMI_SMART_EXPERIENCE_APP: break; default: @@ -1246,6 +1310,70 @@ static int hp_wmi_platform_profile_set(struct platform_profile_handler *pprof, return 0; } +static bool is_victus_thermal_profile(void) +{ + const char *board_name = dmi_get_system_info(DMI_BOARD_NAME); + + if (!board_name) + return false; + + return match_string(victus_thermal_profile_boards, + ARRAY_SIZE(victus_thermal_profile_boards), + board_name) >= 0; +} + +static int platform_profile_victus_get(struct platform_profile_handler *pprof, + enum platform_profile_option *profile) +{ + int tp; + + tp = omen_thermal_profile_get(); + if (tp < 0) + return tp; + + switch (tp) { + case HP_VICTUS_THERMAL_PROFILE_PERFORMANCE: + *profile = PLATFORM_PROFILE_PERFORMANCE; + break; + case HP_VICTUS_THERMAL_PROFILE_DEFAULT: + *profile = PLATFORM_PROFILE_BALANCED; + break; + case HP_VICTUS_THERMAL_PROFILE_QUIET: + *profile = PLATFORM_PROFILE_QUIET; + break; + default: + return -EOPNOTSUPP; + } + + return 0; +} + +static int platform_profile_victus_set(struct platform_profile_handler *pprof, + enum platform_profile_option profile) +{ + int err, tp; + + switch (profile) { + case PLATFORM_PROFILE_PERFORMANCE: + tp = HP_VICTUS_THERMAL_PROFILE_PERFORMANCE; + break; + case PLATFORM_PROFILE_BALANCED: + tp = HP_VICTUS_THERMAL_PROFILE_DEFAULT; + break; + case PLATFORM_PROFILE_QUIET: + tp = HP_VICTUS_THERMAL_PROFILE_QUIET; + break; + default: + return -EOPNOTSUPP; + } + + err = omen_thermal_profile_set(tp); + if (err < 0) + return err; + + return 0; +} + static int thermal_profile_setup(void) { int err, tp; @@ -1266,6 +1394,25 @@ static int thermal_profile_setup(void) platform_profile_handler.profile_get = platform_profile_omen_get; platform_profile_handler.profile_set = platform_profile_omen_set; + + set_bit(PLATFORM_PROFILE_COOL, platform_profile_handler.choices); + } else if (is_victus_thermal_profile()) { + tp = omen_thermal_profile_get(); + if (tp < 0) + return tp; + + /* + * call thermal profile write command to ensure that the + * firmware correctly sets the OEM variables + */ + err = omen_thermal_profile_set(tp); + if (err < 0) + return err; + + platform_profile_handler.profile_get = platform_profile_victus_get; + platform_profile_handler.profile_set = platform_profile_victus_set; + + set_bit(PLATFORM_PROFILE_QUIET, platform_profile_handler.choices); } else { tp = thermal_profile_get(); @@ -1284,9 +1431,9 @@ static int thermal_profile_setup(void) platform_profile_handler.profile_set = hp_wmi_platform_profile_set; set_bit(PLATFORM_PROFILE_QUIET, platform_profile_handler.choices); + set_bit(PLATFORM_PROFILE_COOL, platform_profile_handler.choices); } - set_bit(PLATFORM_PROFILE_COOL, platform_profile_handler.choices); set_bit(PLATFORM_PROFILE_BALANCED, platform_profile_handler.choices); set_bit(PLATFORM_PROFILE_PERFORMANCE, platform_profile_handler.choices); @@ -1483,7 +1630,7 @@ static int hp_wmi_hwmon_write(struct device *dev, enum hwmon_sensor_types type, } } -static const struct hwmon_channel_info *info[] = { +static const struct hwmon_channel_info * const info[] = { HWMON_CHANNEL_INFO(fan, HWMON_F_INPUT, HWMON_F_INPUT), HWMON_CHANNEL_INFO(pwm, HWMON_PWM_ENABLE), NULL @@ -1565,6 +1712,9 @@ static void __exit hp_wmi_exit(void) if (wmi_has_guid(HPWMI_EVENT_GUID)) hp_wmi_input_destroy(); + if (camera_shutter_input_dev) + input_unregister_device(camera_shutter_input_dev); + if (hp_wmi_platform_dev) { platform_device_unregister(hp_wmi_platform_dev); platform_driver_unregister(&hp_wmi_driver); diff --git a/drivers/platform/x86/intel/int3472/clk_and_regulator.c b/drivers/platform/x86/intel/int3472/clk_and_regulator.c index 399f0623ca1b5ca817db2a30e5e4b425ef37cbed..ef4b3141efcdc0ad47ba3cbad9d61d06bcf3be2e 100644 --- a/drivers/platform/x86/intel/int3472/clk_and_regulator.c +++ b/drivers/platform/x86/intel/int3472/clk_and_regulator.c @@ -5,12 +5,48 @@ #include #include #include +#include #include #include #include #include "common.h" +/* + * 82c0d13a-78c5-4244-9bb1-eb8b539a8d11 + * This _DSM GUID allows controlling the sensor clk when it is not controlled + * through a GPIO. + */ +static const guid_t img_clk_guid = + GUID_INIT(0x82c0d13a, 0x78c5, 0x4244, + 0x9b, 0xb1, 0xeb, 0x8b, 0x53, 0x9a, 0x8d, 0x11); + +static void skl_int3472_enable_clk(struct int3472_clock *clk, int enable) +{ + struct int3472_discrete_device *int3472 = to_int3472_device(clk); + union acpi_object args[3]; + union acpi_object argv4; + + if (clk->ena_gpio) { + gpiod_set_value_cansleep(clk->ena_gpio, enable); + return; + } + + args[0].integer.type = ACPI_TYPE_INTEGER; + args[0].integer.value = clk->imgclk_index; + args[1].integer.type = ACPI_TYPE_INTEGER; + args[1].integer.value = enable; + args[2].integer.type = ACPI_TYPE_INTEGER; + args[2].integer.value = 1; + + argv4.type = ACPI_TYPE_PACKAGE; + argv4.package.count = 3; + argv4.package.elements = args; + + acpi_evaluate_dsm(acpi_device_handle(int3472->adev), &img_clk_guid, + 0, 1, &argv4); +} + /* * The regulators have to have .ops to be valid, but the only ops we actually * support are .enable and .disable which are handled via .ena_gpiod. Pass an @@ -20,17 +56,13 @@ static const struct regulator_ops int3472_gpio_regulator_ops; static int skl_int3472_clk_prepare(struct clk_hw *hw) { - struct int3472_gpio_clock *clk = to_int3472_clk(hw); - - gpiod_set_value_cansleep(clk->ena_gpio, 1); + skl_int3472_enable_clk(to_int3472_clk(hw), 1); return 0; } static void skl_int3472_clk_unprepare(struct clk_hw *hw) { - struct int3472_gpio_clock *clk = to_int3472_clk(hw); - - gpiod_set_value_cansleep(clk->ena_gpio, 0); + skl_int3472_enable_clk(to_int3472_clk(hw), 0); } static int skl_int3472_clk_enable(struct clk_hw *hw) @@ -73,7 +105,7 @@ static unsigned int skl_int3472_get_clk_frequency(struct int3472_discrete_device static unsigned long skl_int3472_clk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { - struct int3472_gpio_clock *clk = to_int3472_clk(hw); + struct int3472_clock *clk = to_int3472_clk(hw); return clk->frequency; } @@ -86,8 +118,51 @@ static const struct clk_ops skl_int3472_clock_ops = { .recalc_rate = skl_int3472_clk_recalc_rate, }; -int skl_int3472_register_clock(struct int3472_discrete_device *int3472, - struct acpi_resource_gpio *agpio, u32 polarity) +int skl_int3472_register_dsm_clock(struct int3472_discrete_device *int3472) +{ + struct acpi_device *adev = int3472->adev; + struct clk_init_data init = { + .ops = &skl_int3472_clock_ops, + .flags = CLK_GET_RATE_NOCACHE, + }; + int ret; + + if (int3472->clock.cl) + return 0; /* A GPIO controlled clk has already been registered */ + + if (!acpi_check_dsm(adev->handle, &img_clk_guid, 0, BIT(1))) + return 0; /* DSM clock control is not available */ + + init.name = kasprintf(GFP_KERNEL, "%s-clk", acpi_dev_name(adev)); + if (!init.name) + return -ENOMEM; + + int3472->clock.frequency = skl_int3472_get_clk_frequency(int3472); + int3472->clock.clk_hw.init = &init; + int3472->clock.clk = clk_register(&adev->dev, &int3472->clock.clk_hw); + if (IS_ERR(int3472->clock.clk)) { + ret = PTR_ERR(int3472->clock.clk); + goto out_free_init_name; + } + + int3472->clock.cl = clkdev_create(int3472->clock.clk, NULL, int3472->sensor_name); + if (!int3472->clock.cl) { + ret = -ENOMEM; + goto err_unregister_clk; + } + + kfree(init.name); + return 0; + +err_unregister_clk: + clk_unregister(int3472->clock.clk); +out_free_init_name: + kfree(init.name); + return ret; +} + +int skl_int3472_register_gpio_clock(struct int3472_discrete_device *int3472, + struct acpi_resource_gpio *agpio, u32 polarity) { char *path = agpio->resource_source.string_ptr; struct clk_init_data init = { @@ -160,32 +235,73 @@ void skl_int3472_unregister_clock(struct int3472_discrete_device *int3472) gpiod_put(int3472->clock.ena_gpio); } +/* + * The INT3472 device is going to be the only supplier of a regulator for + * the sensor device. But unlike the clk framework the regulator framework + * does not allow matching by consumer-device-name only. + * + * Ideally all sensor drivers would use "avdd" as supply-id. But for drivers + * where this cannot be changed because another supply-id is already used in + * e.g. DeviceTree files an alias for the other supply-id can be added here. + * + * Do not forget to update GPIO_REGULATOR_SUPPLY_MAP_COUNT when changing this. + */ +static const char * const skl_int3472_regulator_map_supplies[] = { + "avdd", + "AVDD", +}; + +static_assert(ARRAY_SIZE(skl_int3472_regulator_map_supplies) == + GPIO_REGULATOR_SUPPLY_MAP_COUNT); + +/* + * On some models there is a single GPIO regulator which is shared between + * sensors and only listed in the ACPI resources of one sensor. + * This DMI table contains the name of the second sensor. This is used to add + * entries for the second sensor to the supply_map. + */ +static const struct dmi_system_id skl_int3472_regulator_second_sensor[] = { + { + /* Lenovo Miix 510-12IKB */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_VERSION, "MIIX 510-12IKB"), + }, + .driver_data = "i2c-OVTI2680:00", + }, + { } +}; + int skl_int3472_register_regulator(struct int3472_discrete_device *int3472, struct acpi_resource_gpio *agpio) { - const struct int3472_sensor_config *sensor_config; char *path = agpio->resource_source.string_ptr; - struct regulator_consumer_supply supply_map; struct regulator_init_data init_data = { }; struct regulator_config cfg = { }; - int ret; - - sensor_config = int3472->sensor_config; - if (IS_ERR(sensor_config)) { - dev_err(int3472->dev, "No sensor module config\n"); - return PTR_ERR(sensor_config); - } - - if (!sensor_config->supply_map.supply) { - dev_err(int3472->dev, "No supply name defined\n"); - return -ENODEV; + const char *second_sensor = NULL; + const struct dmi_system_id *id; + int i, j, ret; + + id = dmi_first_match(skl_int3472_regulator_second_sensor); + if (id) + second_sensor = id->driver_data; + + for (i = 0, j = 0; i < ARRAY_SIZE(skl_int3472_regulator_map_supplies); i++) { + int3472->regulator.supply_map[j].supply = skl_int3472_regulator_map_supplies[i]; + int3472->regulator.supply_map[j].dev_name = int3472->sensor_name; + j++; + + if (second_sensor) { + int3472->regulator.supply_map[j].supply = + skl_int3472_regulator_map_supplies[i]; + int3472->regulator.supply_map[j].dev_name = second_sensor; + j++; + } } init_data.constraints.valid_ops_mask = REGULATOR_CHANGE_STATUS; - init_data.num_consumer_supplies = 1; - supply_map = sensor_config->supply_map; - supply_map.dev_name = int3472->sensor_name; - init_data.consumer_supplies = &supply_map; + init_data.consumer_supplies = int3472->regulator.supply_map; + init_data.num_consumer_supplies = j; snprintf(int3472->regulator.regulator_name, sizeof(int3472->regulator.regulator_name), "%s-regulator", diff --git a/drivers/platform/x86/intel/int3472/common.h b/drivers/platform/x86/intel/int3472/common.h index 61688e450ce5890e3d2103b15465d56b07bff6be..9f29baa138609f46a7ede03ef2943f4ba9a457e0 100644 --- a/drivers/platform/x86/intel/int3472/common.h +++ b/drivers/platform/x86/intel/int3472/common.h @@ -28,6 +28,7 @@ #define GPIO_REGULATOR_NAME_LENGTH 21 #define GPIO_REGULATOR_SUPPLY_NAME_LENGTH 9 +#define GPIO_REGULATOR_SUPPLY_MAP_COUNT 2 #define INT3472_LED_MAX_NAME_LEN 32 @@ -43,7 +44,7 @@ } #define to_int3472_clk(hw) \ - container_of(hw, struct int3472_gpio_clock, clk_hw) + container_of(hw, struct int3472_clock, clk_hw) #define to_int3472_device(clk) \ container_of(clk, struct int3472_discrete_device, clock) @@ -64,18 +65,9 @@ struct int3472_cldb { u8 control_logic_type; u8 control_logic_id; u8 sensor_card_sku; - u8 reserved[28]; -}; - -struct int3472_gpio_function_remap { - const char *documented; - const char *actual; -}; - -struct int3472_sensor_config { - const char *sensor_module_name; - struct regulator_consumer_supply supply_map; - const struct int3472_gpio_function_remap *function_maps; + u8 reserved[10]; + u8 clock_source; + u8 reserved2[17]; }; struct int3472_discrete_device { @@ -87,6 +79,8 @@ struct int3472_discrete_device { const struct int3472_sensor_config *sensor_config; struct int3472_gpio_regulator { + /* SUPPLY_MAP_COUNT * 2 to make room for second sensor mappings */ + struct regulator_consumer_supply supply_map[GPIO_REGULATOR_SUPPLY_MAP_COUNT * 2]; char regulator_name[GPIO_REGULATOR_NAME_LENGTH]; char supply_name[GPIO_REGULATOR_SUPPLY_NAME_LENGTH]; struct gpio_desc *gpio; @@ -94,12 +88,13 @@ struct int3472_discrete_device { struct regulator_desc rdesc; } regulator; - struct int3472_gpio_clock { + struct int3472_clock { struct clk *clk; struct clk_hw clk_hw; struct clk_lookup *cl; struct gpio_desc *ena_gpio; u32 frequency; + u8 imgclk_index; } clock; struct int3472_pled { @@ -121,8 +116,9 @@ int skl_int3472_get_sensor_adev_and_name(struct device *dev, struct acpi_device **sensor_adev_ret, const char **name_ret); -int skl_int3472_register_clock(struct int3472_discrete_device *int3472, - struct acpi_resource_gpio *agpio, u32 polarity); +int skl_int3472_register_gpio_clock(struct int3472_discrete_device *int3472, + struct acpi_resource_gpio *agpio, u32 polarity); +int skl_int3472_register_dsm_clock(struct int3472_discrete_device *int3472); void skl_int3472_unregister_clock(struct int3472_discrete_device *int3472); int skl_int3472_register_regulator(struct int3472_discrete_device *int3472, diff --git a/drivers/platform/x86/intel/int3472/discrete.c b/drivers/platform/x86/intel/int3472/discrete.c index ef020e23e5968558ecdf124c14a9f1cb9cd6513e..e33c2d75975cf5b4e754c887a133760d089a5c60 100644 --- a/drivers/platform/x86/intel/int3472/discrete.c +++ b/drivers/platform/x86/intel/int3472/discrete.c @@ -2,6 +2,7 @@ /* Author: Dan Scally */ #include +#include #include #include #include @@ -25,6 +26,10 @@ static const guid_t int3472_gpio_guid = GUID_INIT(0x79234640, 0x9e10, 0x4fea, 0xa5, 0xc1, 0xb5, 0xaa, 0x8b, 0x19, 0x75, 0x6f); +#define INT3472_GPIO_DSM_TYPE GENMASK(7, 0) +#define INT3472_GPIO_DSM_PIN GENMASK(15, 8) +#define INT3472_GPIO_DSM_SENSOR_ON_VAL GENMASK(31, 24) + /* * 822ace8f-2814-4174-a56b-5f029fe079ee * This _DSM GUID returns a string from the sensor device, which acts as a @@ -34,69 +39,23 @@ static const guid_t cio2_sensor_module_guid = GUID_INIT(0x822ace8f, 0x2814, 0x4174, 0xa5, 0x6b, 0x5f, 0x02, 0x9f, 0xe0, 0x79, 0xee); -/* - * Here follows platform specific mapping information that we can pass to - * the functions mapping resources to the sensors. Where the sensors have - * a power enable pin defined in DSDT we need to provide a supply name so - * the sensor drivers can find the regulator. The device name will be derived - * from the sensor's ACPI device within the code. Optionally, we can provide a - * NULL terminated array of function name mappings to deal with any platform - * specific deviations from the documented behaviour of GPIOs. - * - * Map a GPIO function name to NULL to prevent the driver from mapping that - * GPIO at all. - */ - -static const struct int3472_gpio_function_remap ov2680_gpio_function_remaps[] = { - { "reset", NULL }, - { "powerdown", "reset" }, - { } -}; - -static const struct int3472_sensor_config int3472_sensor_configs[] = { - /* Lenovo Miix 510-12ISK - OV2680, Front */ - { "GNDF140809R", { 0 }, ov2680_gpio_function_remaps }, - /* Lenovo Miix 510-12ISK - OV5648, Rear */ - { "GEFF150023R", REGULATOR_SUPPLY("avdd", NULL), NULL }, - /* Surface Go 1&2 - OV5693, Front */ - { "YHCU", REGULATOR_SUPPLY("avdd", NULL), NULL }, -}; - -static const struct int3472_sensor_config * -skl_int3472_get_sensor_module_config(struct int3472_discrete_device *int3472) +static void skl_int3472_log_sensor_module_name(struct int3472_discrete_device *int3472) { union acpi_object *obj; - unsigned int i; obj = acpi_evaluate_dsm_typed(int3472->sensor->handle, &cio2_sensor_module_guid, 0x00, 0x01, NULL, ACPI_TYPE_STRING); - - if (!obj) { - dev_err(int3472->dev, - "Failed to get sensor module string from _DSM\n"); - return ERR_PTR(-ENODEV); + if (obj) { + dev_dbg(int3472->dev, "Sensor module id: '%s'\n", obj->string.pointer); + ACPI_FREE(obj); } - - for (i = 0; i < ARRAY_SIZE(int3472_sensor_configs); i++) { - if (!strcmp(int3472_sensor_configs[i].sensor_module_name, - obj->string.pointer)) - break; - } - - ACPI_FREE(obj); - - if (i >= ARRAY_SIZE(int3472_sensor_configs)) - return ERR_PTR(-EINVAL); - - return &int3472_sensor_configs[i]; } static int skl_int3472_map_gpio_to_sensor(struct int3472_discrete_device *int3472, struct acpi_resource_gpio *agpio, const char *func, u32 polarity) { - const struct int3472_sensor_config *sensor_config; char *path = agpio->resource_source.string_ptr; struct gpiod_lookup *table_entry; struct acpi_device *adev; @@ -108,22 +67,6 @@ static int skl_int3472_map_gpio_to_sensor(struct int3472_discrete_device *int347 return -EINVAL; } - sensor_config = int3472->sensor_config; - if (!IS_ERR(sensor_config) && sensor_config->function_maps) { - const struct int3472_gpio_function_remap *remap; - - for (remap = sensor_config->function_maps; remap->documented; remap++) { - if (!strcmp(func, remap->documented)) { - func = remap->actual; - break; - } - } - } - - /* Functions mapped to NULL should not be mapped to the sensor */ - if (!func) - return 0; - status = acpi_get_handle(NULL, path, &handle); if (ACPI_FAILURE(status)) return -EINVAL; @@ -211,8 +154,8 @@ static int skl_int3472_handle_gpio_resources(struct acpi_resource *ares, { struct int3472_discrete_device *int3472 = data; struct acpi_resource_gpio *agpio; + u8 active_value, pin, type; union acpi_object *obj; - u8 active_value, type; const char *err_msg; const char *func; u32 polarity; @@ -236,12 +179,17 @@ static int skl_int3472_handle_gpio_resources(struct acpi_resource *ares, return 1; } - type = obj->integer.value & 0xff; + type = FIELD_GET(INT3472_GPIO_DSM_TYPE, obj->integer.value); int3472_get_func_and_polarity(type, &func, &polarity); - /* If bits 31-24 of the _DSM entry are all 0 then the signal is inverted */ - active_value = obj->integer.value >> 24; + pin = FIELD_GET(INT3472_GPIO_DSM_PIN, obj->integer.value); + if (pin != agpio->pin_table[0]) + dev_warn(int3472->dev, "%s %s pin number mismatch _DSM %d resource %d\n", + func, agpio->resource_source.string_ptr, pin, + agpio->pin_table[0]); + + active_value = FIELD_GET(INT3472_GPIO_DSM_SENSOR_ON_VAL, obj->integer.value); if (!active_value) polarity ^= GPIO_ACTIVE_LOW; @@ -258,7 +206,7 @@ static int skl_int3472_handle_gpio_resources(struct acpi_resource *ares, break; case INT3472_GPIO_TYPE_CLK_ENABLE: - ret = skl_int3472_register_clock(int3472, agpio, polarity); + ret = skl_int3472_register_gpio_clock(int3472, agpio, polarity); if (ret) err_msg = "Failed to register clock\n"; @@ -297,11 +245,7 @@ static int skl_int3472_parse_crs(struct int3472_discrete_device *int3472) LIST_HEAD(resource_list); int ret; - /* - * No error check, because not having a sensor config is not necessarily - * a failure mode. - */ - int3472->sensor_config = skl_int3472_get_sensor_module_config(int3472); + skl_int3472_log_sensor_module_name(int3472); ret = acpi_dev_get_resources(int3472->adev, &resource_list, skl_int3472_handle_gpio_resources, @@ -311,6 +255,11 @@ static int skl_int3472_parse_crs(struct int3472_discrete_device *int3472) acpi_dev_free_resource_list(&resource_list); + /* Register _DSM based clock (no-op if a GPIO clock was already registered) */ + ret = skl_int3472_register_dsm_clock(int3472); + if (ret < 0) + return ret; + int3472->gpios.dev_id = int3472->sensor_name; gpiod_add_lookup_table(&int3472->gpios); @@ -356,6 +305,7 @@ static int skl_int3472_discrete_probe(struct platform_device *pdev) int3472->adev = adev; int3472->dev = &pdev->dev; platform_set_drvdata(pdev, int3472); + int3472->clock.imgclk_index = cldb.clock_source; ret = skl_int3472_get_sensor_adev_and_name(&pdev->dev, &int3472->sensor, &int3472->sensor_name); diff --git a/drivers/platform/x86/intel/int3472/tps68470.c b/drivers/platform/x86/intel/int3472/tps68470.c index 5b8d1a9620a5d06e0193fa16a9d832e17775dbc3..1e107fd49f828c78aa2a30bae197cc31660ce602 100644 --- a/drivers/platform/x86/intel/int3472/tps68470.c +++ b/drivers/platform/x86/intel/int3472/tps68470.c @@ -250,7 +250,7 @@ static struct i2c_driver int3472_tps68470 = { .name = "int3472-tps68470", .acpi_match_table = int3472_device_id, }, - .probe_new = skl_int3472_tps68470_probe, + .probe = skl_int3472_tps68470_probe, .remove = skl_int3472_tps68470_remove, }; module_i2c_driver(int3472_tps68470); diff --git a/drivers/platform/x86/intel/pmc/Makefile b/drivers/platform/x86/intel/pmc/Makefile index f96bc2e19503423d66efeeeee4f61b849f3fe038..3a4cf1cbc1cacd95119fa5b7f0ef34daca7a57e5 100644 --- a/drivers/platform/x86/intel/pmc/Makefile +++ b/drivers/platform/x86/intel/pmc/Makefile @@ -3,8 +3,8 @@ # Intel x86 Platform-Specific Drivers # -intel_pmc_core-y := core.o spt.o cnp.o icl.o tgl.o \ - adl.o mtl.o +intel_pmc_core-y := core.o core_ssram.o spt.o cnp.o \ + icl.o tgl.o adl.o mtl.o obj-$(CONFIG_INTEL_PMC_CORE) += intel_pmc_core.o intel_pmc_core_pltdrv-y := pltdrv.o obj-$(CONFIG_INTEL_PMC_CORE) += intel_pmc_core_pltdrv.o diff --git a/drivers/platform/x86/intel/pmc/adl.c b/drivers/platform/x86/intel/pmc/adl.c index 5cbd40979f2aa13f72baaeb0fa82d14c71a9850b..5006008e01bea274ba2f61be9d8c5e931b9778f6 100644 --- a/drivers/platform/x86/intel/pmc/adl.c +++ b/drivers/platform/x86/intel/pmc/adl.c @@ -309,17 +309,21 @@ const struct pmc_reg_map adl_reg_map = { .lpm_live_status_offset = ADL_LPM_LIVE_STATUS_OFFSET, }; -void adl_core_configure(struct pmc_dev *pmcdev) +int adl_core_init(struct pmc_dev *pmcdev) { + struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN]; + int ret; + + pmc->map = &adl_reg_map; + ret = get_primary_reg_base(pmc); + if (ret) + return ret; + /* Due to a hardware limitation, the GBE LTR blocks PC10 * when a cable is attached. Tell the PMC to ignore it. */ dev_dbg(&pmcdev->pdev->dev, "ignoring GBE LTR\n"); pmc_core_send_ltr_ignore(pmcdev, 3); -} -void adl_core_init(struct pmc_dev *pmcdev) -{ - pmcdev->map = &adl_reg_map; - pmcdev->core_configure = adl_core_configure; + return 0; } diff --git a/drivers/platform/x86/intel/pmc/cnp.c b/drivers/platform/x86/intel/pmc/cnp.c index 7fb38815c4ebe42986370d83167faf53454ca757..420aaa1d7c76977bbc0cd59b43ba8a2bb40ef02f 100644 --- a/drivers/platform/x86/intel/pmc/cnp.c +++ b/drivers/platform/x86/intel/pmc/cnp.c @@ -204,7 +204,21 @@ const struct pmc_reg_map cnp_reg_map = { .etr3_offset = ETR3_OFFSET, }; -void cnp_core_init(struct pmc_dev *pmcdev) +int cnp_core_init(struct pmc_dev *pmcdev) { - pmcdev->map = &cnp_reg_map; + struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN]; + int ret; + + pmc->map = &cnp_reg_map; + ret = get_primary_reg_base(pmc); + if (ret) + return ret; + + /* Due to a hardware limitation, the GBE LTR blocks PC10 + * when a cable is attached. Tell the PMC to ignore it. + */ + dev_dbg(&pmcdev->pdev->dev, "ignoring GBE LTR\n"); + pmc_core_send_ltr_ignore(pmcdev, 3); + + return 0; } diff --git a/drivers/platform/x86/intel/pmc/core.c b/drivers/platform/x86/intel/pmc/core.c index da6e7206d38b5a571e2889665cd675f51c343d5e..5a36b3f77bc57292e1a4fabc0f5314a343f01947 100644 --- a/drivers/platform/x86/intel/pmc/core.c +++ b/drivers/platform/x86/intel/pmc/core.c @@ -53,18 +53,18 @@ const struct pmc_bit_map msr_map[] = { {} }; -static inline u32 pmc_core_reg_read(struct pmc_dev *pmcdev, int reg_offset) +static inline u32 pmc_core_reg_read(struct pmc *pmc, int reg_offset) { - return readl(pmcdev->regbase + reg_offset); + return readl(pmc->regbase + reg_offset); } -static inline void pmc_core_reg_write(struct pmc_dev *pmcdev, int reg_offset, +static inline void pmc_core_reg_write(struct pmc *pmc, int reg_offset, u32 val) { - writel(val, pmcdev->regbase + reg_offset); + writel(val, pmc->regbase + reg_offset); } -static inline u64 pmc_core_adjust_slp_s0_step(struct pmc_dev *pmcdev, u32 value) +static inline u64 pmc_core_adjust_slp_s0_step(struct pmc *pmc, u32 value) { /* * ADL PCH does not have the SLP_S0 counter and LPM Residency counters are @@ -72,17 +72,18 @@ static inline u64 pmc_core_adjust_slp_s0_step(struct pmc_dev *pmcdev, u32 value) * programs have the legacy SLP_S0 residency counter that is using the 122 * usec tick. */ - const int lpm_adj_x2 = pmcdev->map->lpm_res_counter_step_x2; + const int lpm_adj_x2 = pmc->map->lpm_res_counter_step_x2; - if (pmcdev->map == &adl_reg_map) + if (pmc->map == &adl_reg_map) return (u64)value * GET_X2_COUNTER((u64)lpm_adj_x2); else - return (u64)value * pmcdev->map->slp_s0_res_counter_step; + return (u64)value * pmc->map->slp_s0_res_counter_step; } static int set_etr3(struct pmc_dev *pmcdev) { - const struct pmc_reg_map *map = pmcdev->map; + struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN]; + const struct pmc_reg_map *map = pmc->map; u32 reg; int err; @@ -92,7 +93,7 @@ static int set_etr3(struct pmc_dev *pmcdev) mutex_lock(&pmcdev->lock); /* check if CF9 is locked */ - reg = pmc_core_reg_read(pmcdev, map->etr3_offset); + reg = pmc_core_reg_read(pmc, map->etr3_offset); if (reg & ETR3_CF9LOCK) { err = -EACCES; goto out_unlock; @@ -100,9 +101,9 @@ static int set_etr3(struct pmc_dev *pmcdev) /* write CF9 global reset bit */ reg |= ETR3_CF9GR; - pmc_core_reg_write(pmcdev, map->etr3_offset, reg); + pmc_core_reg_write(pmc, map->etr3_offset, reg); - reg = pmc_core_reg_read(pmcdev, map->etr3_offset); + reg = pmc_core_reg_read(pmc, map->etr3_offset); if (!(reg & ETR3_CF9GR)) { err = -EIO; goto out_unlock; @@ -120,11 +121,12 @@ static umode_t etr3_is_visible(struct kobject *kobj, { struct device *dev = kobj_to_dev(kobj); struct pmc_dev *pmcdev = dev_get_drvdata(dev); - const struct pmc_reg_map *map = pmcdev->map; + struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN]; + const struct pmc_reg_map *map = pmc->map; u32 reg; mutex_lock(&pmcdev->lock); - reg = pmc_core_reg_read(pmcdev, map->etr3_offset); + reg = pmc_core_reg_read(pmc, map->etr3_offset); mutex_unlock(&pmcdev->lock); return reg & ETR3_CF9LOCK ? attr->mode & (SYSFS_PREALLOC | 0444) : attr->mode; @@ -134,7 +136,8 @@ static ssize_t etr3_show(struct device *dev, struct device_attribute *attr, char *buf) { struct pmc_dev *pmcdev = dev_get_drvdata(dev); - const struct pmc_reg_map *map = pmcdev->map; + struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN]; + const struct pmc_reg_map *map = pmc->map; u32 reg; if (!map->etr3_offset) @@ -142,7 +145,7 @@ static ssize_t etr3_show(struct device *dev, mutex_lock(&pmcdev->lock); - reg = pmc_core_reg_read(pmcdev, map->etr3_offset); + reg = pmc_core_reg_read(pmc, map->etr3_offset); reg &= ETR3_CF9GR | ETR3_CF9LOCK; mutex_unlock(&pmcdev->lock); @@ -191,37 +194,37 @@ static const struct attribute_group *pmc_dev_groups[] = { static int pmc_core_dev_state_get(void *data, u64 *val) { - struct pmc_dev *pmcdev = data; - const struct pmc_reg_map *map = pmcdev->map; + struct pmc *pmc = data; + const struct pmc_reg_map *map = pmc->map; u32 value; - value = pmc_core_reg_read(pmcdev, map->slp_s0_offset); - *val = pmc_core_adjust_slp_s0_step(pmcdev, value); + value = pmc_core_reg_read(pmc, map->slp_s0_offset); + *val = pmc_core_adjust_slp_s0_step(pmc, value); return 0; } DEFINE_DEBUGFS_ATTRIBUTE(pmc_core_dev_state, pmc_core_dev_state_get, NULL, "%llu\n"); -static int pmc_core_check_read_lock_bit(struct pmc_dev *pmcdev) +static int pmc_core_check_read_lock_bit(struct pmc *pmc) { u32 value; - value = pmc_core_reg_read(pmcdev, pmcdev->map->pm_cfg_offset); - return value & BIT(pmcdev->map->pm_read_disable_bit); + value = pmc_core_reg_read(pmc, pmc->map->pm_cfg_offset); + return value & BIT(pmc->map->pm_read_disable_bit); } -static void pmc_core_slps0_display(struct pmc_dev *pmcdev, struct device *dev, +static void pmc_core_slps0_display(struct pmc *pmc, struct device *dev, struct seq_file *s) { - const struct pmc_bit_map **maps = pmcdev->map->slps0_dbg_maps; + const struct pmc_bit_map **maps = pmc->map->slps0_dbg_maps; const struct pmc_bit_map *map; - int offset = pmcdev->map->slps0_dbg_offset; + int offset = pmc->map->slps0_dbg_offset; u32 data; while (*maps) { map = *maps; - data = pmc_core_reg_read(pmcdev, offset); + data = pmc_core_reg_read(pmc, offset); offset += 4; while (map->name) { if (dev) @@ -248,8 +251,8 @@ static int pmc_core_lpm_get_arr_size(const struct pmc_bit_map **maps) return idx; } -static void pmc_core_lpm_display(struct pmc_dev *pmcdev, struct device *dev, - struct seq_file *s, u32 offset, +static void pmc_core_lpm_display(struct pmc *pmc, struct device *dev, + struct seq_file *s, u32 offset, int pmc_index, const char *str, const struct pmc_bit_map **maps) { @@ -262,25 +265,25 @@ static void pmc_core_lpm_display(struct pmc_dev *pmcdev, struct device *dev, return; for (index = 0; index < arr_size; index++) { - lpm_regs[index] = pmc_core_reg_read(pmcdev, offset); + lpm_regs[index] = pmc_core_reg_read(pmc, offset); offset += 4; } for (idx = 0; idx < arr_size; idx++) { if (dev) - dev_info(dev, "\nLPM_%s_%d:\t0x%x\n", str, idx, + dev_info(dev, "\nPMC%d:LPM_%s_%d:\t0x%x\n", pmc_index, str, idx, lpm_regs[idx]); if (s) - seq_printf(s, "\nLPM_%s_%d:\t0x%x\n", str, idx, + seq_printf(s, "\nPMC%d:LPM_%s_%d:\t0x%x\n", pmc_index, str, idx, lpm_regs[idx]); for (index = 0; maps[idx][index].name && index < len; index++) { bit_mask = maps[idx][index].bit_mask; if (dev) - dev_info(dev, "%-30s %-30d\n", + dev_info(dev, "PMC%d:%-30s %-30d\n", pmc_index, maps[idx][index].name, lpm_regs[idx] & bit_mask ? 1 : 0); if (s) - seq_printf(s, "%-30s %-30d\n", + seq_printf(s, "PMC%d:%-30s %-30d\n", pmc_index, maps[idx][index].name, lpm_regs[idx] & bit_mask ? 1 : 0); } @@ -291,37 +294,46 @@ static void pmc_core_lpm_display(struct pmc_dev *pmcdev, struct device *dev, static bool slps0_dbg_latch; -static inline u8 pmc_core_reg_read_byte(struct pmc_dev *pmcdev, int offset) +static inline u8 pmc_core_reg_read_byte(struct pmc *pmc, int offset) { - return readb(pmcdev->regbase + offset); + return readb(pmc->regbase + offset); } static void pmc_core_display_map(struct seq_file *s, int index, int idx, int ip, - u8 pf_reg, const struct pmc_bit_map **pf_map) + int pmc_index, u8 pf_reg, const struct pmc_bit_map **pf_map) { - seq_printf(s, "PCH IP: %-2d - %-32s\tState: %s\n", - ip, pf_map[idx][index].name, + seq_printf(s, "PMC%d:PCH IP: %-2d - %-32s\tState: %s\n", + pmc_index, ip, pf_map[idx][index].name, pf_map[idx][index].bit_mask & pf_reg ? "Off" : "On"); } static int pmc_core_ppfear_show(struct seq_file *s, void *unused) { struct pmc_dev *pmcdev = s->private; - const struct pmc_bit_map **maps = pmcdev->map->pfear_sts; - u8 pf_regs[PPFEAR_MAX_NUM_ENTRIES]; - int index, iter, idx, ip = 0; + int i; - iter = pmcdev->map->ppfear0_offset; + for (i = 0; i < ARRAY_SIZE(pmcdev->pmcs); ++i) { + struct pmc *pmc = pmcdev->pmcs[i]; + const struct pmc_bit_map **maps; + u8 pf_regs[PPFEAR_MAX_NUM_ENTRIES]; + int index, iter, idx, ip = 0; - for (index = 0; index < pmcdev->map->ppfear_buckets && - index < PPFEAR_MAX_NUM_ENTRIES; index++, iter++) - pf_regs[index] = pmc_core_reg_read_byte(pmcdev, iter); + if (!pmc) + continue; + + maps = pmc->map->pfear_sts; + iter = pmc->map->ppfear0_offset; + + for (index = 0; index < pmc->map->ppfear_buckets && + index < PPFEAR_MAX_NUM_ENTRIES; index++, iter++) + pf_regs[index] = pmc_core_reg_read_byte(pmc, iter); - for (idx = 0; maps[idx]; idx++) { - for (index = 0; maps[idx][index].name && - index < pmcdev->map->ppfear_buckets * 8; ip++, index++) - pmc_core_display_map(s, index, idx, ip, - pf_regs[index / 8], maps); + for (idx = 0; maps[idx]; idx++) { + for (index = 0; maps[idx][index].name && + index < pmc->map->ppfear_buckets * 8; ip++, index++) + pmc_core_display_map(s, index, idx, ip, i, + pf_regs[index / 8], maps); + } } return 0; @@ -329,37 +341,38 @@ static int pmc_core_ppfear_show(struct seq_file *s, void *unused) DEFINE_SHOW_ATTRIBUTE(pmc_core_ppfear); /* This function should return link status, 0 means ready */ -static int pmc_core_mtpmc_link_status(struct pmc_dev *pmcdev) +static int pmc_core_mtpmc_link_status(struct pmc *pmc) { u32 value; - value = pmc_core_reg_read(pmcdev, SPT_PMC_PM_STS_OFFSET); + value = pmc_core_reg_read(pmc, SPT_PMC_PM_STS_OFFSET); return value & BIT(SPT_PMC_MSG_FULL_STS_BIT); } -static int pmc_core_send_msg(struct pmc_dev *pmcdev, u32 *addr_xram) +static int pmc_core_send_msg(struct pmc *pmc, u32 *addr_xram) { u32 dest; int timeout; for (timeout = NUM_RETRIES; timeout > 0; timeout--) { - if (pmc_core_mtpmc_link_status(pmcdev) == 0) + if (pmc_core_mtpmc_link_status(pmc) == 0) break; msleep(5); } - if (timeout <= 0 && pmc_core_mtpmc_link_status(pmcdev)) + if (timeout <= 0 && pmc_core_mtpmc_link_status(pmc)) return -EBUSY; dest = (*addr_xram & MTPMC_MASK) | (1U << 1); - pmc_core_reg_write(pmcdev, SPT_PMC_MTPMC_OFFSET, dest); + pmc_core_reg_write(pmc, SPT_PMC_MTPMC_OFFSET, dest); return 0; } static int pmc_core_mphy_pg_show(struct seq_file *s, void *unused) { struct pmc_dev *pmcdev = s->private; - const struct pmc_bit_map *map = pmcdev->map->mphy_sts; + struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN]; + const struct pmc_bit_map *map = pmc->map->mphy_sts; u32 mphy_core_reg_low, mphy_core_reg_high; u32 val_low, val_high; int index, err = 0; @@ -374,21 +387,21 @@ static int pmc_core_mphy_pg_show(struct seq_file *s, void *unused) mutex_lock(&pmcdev->lock); - if (pmc_core_send_msg(pmcdev, &mphy_core_reg_low) != 0) { + if (pmc_core_send_msg(pmc, &mphy_core_reg_low) != 0) { err = -EBUSY; goto out_unlock; } msleep(10); - val_low = pmc_core_reg_read(pmcdev, SPT_PMC_MFPMC_OFFSET); + val_low = pmc_core_reg_read(pmc, SPT_PMC_MFPMC_OFFSET); - if (pmc_core_send_msg(pmcdev, &mphy_core_reg_high) != 0) { + if (pmc_core_send_msg(pmc, &mphy_core_reg_high) != 0) { err = -EBUSY; goto out_unlock; } msleep(10); - val_high = pmc_core_reg_read(pmcdev, SPT_PMC_MFPMC_OFFSET); + val_high = pmc_core_reg_read(pmc, SPT_PMC_MFPMC_OFFSET); for (index = 0; index < 8 && map[index].name; index++) { seq_printf(s, "%-32s\tState: %s\n", @@ -413,7 +426,8 @@ DEFINE_SHOW_ATTRIBUTE(pmc_core_mphy_pg); static int pmc_core_pll_show(struct seq_file *s, void *unused) { struct pmc_dev *pmcdev = s->private; - const struct pmc_bit_map *map = pmcdev->map->pll_sts; + struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN]; + const struct pmc_bit_map *map = pmc->map->pll_sts; u32 mphy_common_reg, val; int index, err = 0; @@ -425,14 +439,14 @@ static int pmc_core_pll_show(struct seq_file *s, void *unused) mphy_common_reg = (SPT_PMC_MPHY_COM_STS_0 << 16); mutex_lock(&pmcdev->lock); - if (pmc_core_send_msg(pmcdev, &mphy_common_reg) != 0) { + if (pmc_core_send_msg(pmc, &mphy_common_reg) != 0) { err = -EBUSY; goto out_unlock; } /* Observed PMC HW response latency for MTPMC-MFPMC is ~10 ms */ msleep(10); - val = pmc_core_reg_read(pmcdev, SPT_PMC_MFPMC_OFFSET); + val = pmc_core_reg_read(pmc, SPT_PMC_MFPMC_OFFSET); for (index = 0; map[index].name ; index++) { seq_printf(s, "%-32s\tState: %s\n", @@ -448,25 +462,48 @@ DEFINE_SHOW_ATTRIBUTE(pmc_core_pll); int pmc_core_send_ltr_ignore(struct pmc_dev *pmcdev, u32 value) { - const struct pmc_reg_map *map = pmcdev->map; + struct pmc *pmc; + const struct pmc_reg_map *map; u32 reg; - int err = 0; + int pmc_index, ltr_index; - mutex_lock(&pmcdev->lock); + ltr_index = value; + /* For platforms with multiple pmcs, ltr index value given by user + * is based on the contiguous indexes from ltr_show output. + * pmc index and ltr index needs to be calculated from it. + */ + for (pmc_index = 0; pmc_index < ARRAY_SIZE(pmcdev->pmcs) && ltr_index > 0; pmc_index++) { + pmc = pmcdev->pmcs[pmc_index]; - if (value > map->ltr_ignore_max) { - err = -EINVAL; - goto out_unlock; + if (!pmc) + continue; + + map = pmc->map; + if (ltr_index <= map->ltr_ignore_max) + break; + + /* Along with IP names, ltr_show map includes CURRENT_PLATFORM + * and AGGREGATED_SYSTEM values per PMC. Take these two index + * values into account in ltr_index calculation. Also, to start + * ltr index from zero for next pmc, subtract it by 1. + */ + ltr_index = ltr_index - (map->ltr_ignore_max + 2) - 1; } - reg = pmc_core_reg_read(pmcdev, map->ltr_ignore_offset); - reg |= BIT(value); - pmc_core_reg_write(pmcdev, map->ltr_ignore_offset, reg); + if (pmc_index >= ARRAY_SIZE(pmcdev->pmcs) || ltr_index < 0) + return -EINVAL; + + pr_debug("ltr_ignore for pmc%d: ltr_index:%d\n", pmc_index, ltr_index); + + mutex_lock(&pmcdev->lock); + + reg = pmc_core_reg_read(pmc, map->ltr_ignore_offset); + reg |= BIT(ltr_index); + pmc_core_reg_write(pmc, map->ltr_ignore_offset, reg); -out_unlock: mutex_unlock(&pmcdev->lock); - return err; + return 0; } static ssize_t pmc_core_ltr_ignore_write(struct file *file, @@ -509,7 +546,8 @@ static const struct file_operations pmc_core_ltr_ignore_ops = { static void pmc_core_slps0_dbg_latch(struct pmc_dev *pmcdev, bool reset) { - const struct pmc_reg_map *map = pmcdev->map; + struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN]; + const struct pmc_reg_map *map = pmc->map; u32 fd; mutex_lock(&pmcdev->lock); @@ -517,12 +555,12 @@ static void pmc_core_slps0_dbg_latch(struct pmc_dev *pmcdev, bool reset) if (!reset && !slps0_dbg_latch) goto out_unlock; - fd = pmc_core_reg_read(pmcdev, map->slps0_dbg_offset); + fd = pmc_core_reg_read(pmc, map->slps0_dbg_offset); if (reset) fd &= ~CNP_PMC_LATCH_SLPS0_EVENTS; else fd |= CNP_PMC_LATCH_SLPS0_EVENTS; - pmc_core_reg_write(pmcdev, map->slps0_dbg_offset, fd); + pmc_core_reg_write(pmc, map->slps0_dbg_offset, fd); slps0_dbg_latch = false; @@ -535,7 +573,7 @@ static int pmc_core_slps0_dbg_show(struct seq_file *s, void *unused) struct pmc_dev *pmcdev = s->private; pmc_core_slps0_dbg_latch(pmcdev, false); - pmc_core_slps0_display(pmcdev, NULL, s); + pmc_core_slps0_display(pmcdev->pmcs[PMC_IDX_MAIN], NULL, s); pmc_core_slps0_dbg_latch(pmcdev, true); return 0; @@ -579,44 +617,52 @@ static u32 convert_ltr_scale(u32 val) static int pmc_core_ltr_show(struct seq_file *s, void *unused) { struct pmc_dev *pmcdev = s->private; - const struct pmc_bit_map *map = pmcdev->map->ltr_show_sts; u64 decoded_snoop_ltr, decoded_non_snoop_ltr; u32 ltr_raw_data, scale, val; u16 snoop_ltr, nonsnoop_ltr; - int index; + int i, index, ltr_index = 0; - for (index = 0; map[index].name ; index++) { - decoded_snoop_ltr = decoded_non_snoop_ltr = 0; - ltr_raw_data = pmc_core_reg_read(pmcdev, - map[index].bit_mask); - snoop_ltr = ltr_raw_data & ~MTPMC_MASK; - nonsnoop_ltr = (ltr_raw_data >> 0x10) & ~MTPMC_MASK; - - if (FIELD_GET(LTR_REQ_NONSNOOP, ltr_raw_data)) { - scale = FIELD_GET(LTR_DECODED_SCALE, nonsnoop_ltr); - val = FIELD_GET(LTR_DECODED_VAL, nonsnoop_ltr); - decoded_non_snoop_ltr = val * convert_ltr_scale(scale); - } + for (i = 0; i < ARRAY_SIZE(pmcdev->pmcs); ++i) { + struct pmc *pmc = pmcdev->pmcs[i]; + const struct pmc_bit_map *map; - if (FIELD_GET(LTR_REQ_SNOOP, ltr_raw_data)) { - scale = FIELD_GET(LTR_DECODED_SCALE, snoop_ltr); - val = FIELD_GET(LTR_DECODED_VAL, snoop_ltr); - decoded_snoop_ltr = val * convert_ltr_scale(scale); - } + if (!pmc) + continue; + + map = pmc->map->ltr_show_sts; + for (index = 0; map[index].name; index++) { + decoded_snoop_ltr = decoded_non_snoop_ltr = 0; + ltr_raw_data = pmc_core_reg_read(pmc, + map[index].bit_mask); + snoop_ltr = ltr_raw_data & ~MTPMC_MASK; + nonsnoop_ltr = (ltr_raw_data >> 0x10) & ~MTPMC_MASK; + + if (FIELD_GET(LTR_REQ_NONSNOOP, ltr_raw_data)) { + scale = FIELD_GET(LTR_DECODED_SCALE, nonsnoop_ltr); + val = FIELD_GET(LTR_DECODED_VAL, nonsnoop_ltr); + decoded_non_snoop_ltr = val * convert_ltr_scale(scale); + } + if (FIELD_GET(LTR_REQ_SNOOP, ltr_raw_data)) { + scale = FIELD_GET(LTR_DECODED_SCALE, snoop_ltr); + val = FIELD_GET(LTR_DECODED_VAL, snoop_ltr); + decoded_snoop_ltr = val * convert_ltr_scale(scale); + } - seq_printf(s, "%-32s\tLTR: RAW: 0x%-16x\tNon-Snoop(ns): %-16llu\tSnoop(ns): %-16llu\n", - map[index].name, ltr_raw_data, - decoded_non_snoop_ltr, - decoded_snoop_ltr); + seq_printf(s, "%d\tPMC%d:%-32s\tLTR: RAW: 0x%-16x\tNon-Snoop(ns): %-16llu\tSnoop(ns): %-16llu\n", + ltr_index, i, map[index].name, ltr_raw_data, + decoded_non_snoop_ltr, + decoded_snoop_ltr); + ltr_index++; + } } return 0; } DEFINE_SHOW_ATTRIBUTE(pmc_core_ltr); -static inline u64 adjust_lpm_residency(struct pmc_dev *pmcdev, u32 offset, +static inline u64 adjust_lpm_residency(struct pmc *pmc, u32 offset, const int lpm_adj_x2) { - u64 lpm_res = pmc_core_reg_read(pmcdev, offset); + u64 lpm_res = pmc_core_reg_read(pmc, offset); return GET_X2_COUNTER((u64)lpm_adj_x2 * lpm_res); } @@ -624,15 +670,16 @@ static inline u64 adjust_lpm_residency(struct pmc_dev *pmcdev, u32 offset, static int pmc_core_substate_res_show(struct seq_file *s, void *unused) { struct pmc_dev *pmcdev = s->private; - const int lpm_adj_x2 = pmcdev->map->lpm_res_counter_step_x2; - u32 offset = pmcdev->map->lpm_residency_offset; + struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN]; + const int lpm_adj_x2 = pmc->map->lpm_res_counter_step_x2; + u32 offset = pmc->map->lpm_residency_offset; int i, mode; seq_printf(s, "%-10s %-15s\n", "Substate", "Residency"); pmc_for_each_mode(i, mode, pmcdev) { seq_printf(s, "%-10s %-15llu\n", pmc_lpm_modes[mode], - adjust_lpm_residency(pmcdev, offset + (4 * mode), lpm_adj_x2)); + adjust_lpm_residency(pmc, offset + (4 * mode), lpm_adj_x2)); } return 0; @@ -642,10 +689,19 @@ DEFINE_SHOW_ATTRIBUTE(pmc_core_substate_res); static int pmc_core_substate_sts_regs_show(struct seq_file *s, void *unused) { struct pmc_dev *pmcdev = s->private; - const struct pmc_bit_map **maps = pmcdev->map->lpm_sts; - u32 offset = pmcdev->map->lpm_status_offset; + int i; - pmc_core_lpm_display(pmcdev, NULL, s, offset, "STATUS", maps); + for (i = 0; i < ARRAY_SIZE(pmcdev->pmcs); ++i) { + struct pmc *pmc = pmcdev->pmcs[i]; + const struct pmc_bit_map **maps; + u32 offset; + + if (!pmc) + continue; + maps = pmc->map->lpm_sts; + offset = pmc->map->lpm_status_offset; + pmc_core_lpm_display(pmc, NULL, s, offset, i, "STATUS", maps); + } return 0; } @@ -654,10 +710,19 @@ DEFINE_SHOW_ATTRIBUTE(pmc_core_substate_sts_regs); static int pmc_core_substate_l_sts_regs_show(struct seq_file *s, void *unused) { struct pmc_dev *pmcdev = s->private; - const struct pmc_bit_map **maps = pmcdev->map->lpm_sts; - u32 offset = pmcdev->map->lpm_live_status_offset; + int i; - pmc_core_lpm_display(pmcdev, NULL, s, offset, "LIVE_STATUS", maps); + for (i = 0; i < ARRAY_SIZE(pmcdev->pmcs); ++i) { + struct pmc *pmc = pmcdev->pmcs[i]; + const struct pmc_bit_map **maps; + u32 offset; + + if (!pmc) + continue; + maps = pmc->map->lpm_sts; + offset = pmc->map->lpm_live_status_offset; + pmc_core_lpm_display(pmc, NULL, s, offset, i, "LIVE_STATUS", maps); + } return 0; } @@ -678,11 +743,12 @@ static void pmc_core_substate_req_header_show(struct seq_file *s) static int pmc_core_substate_req_regs_show(struct seq_file *s, void *unused) { struct pmc_dev *pmcdev = s->private; - const struct pmc_bit_map **maps = pmcdev->map->lpm_sts; + struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN]; + const struct pmc_bit_map **maps = pmc->map->lpm_sts; const struct pmc_bit_map *map; - const int num_maps = pmcdev->map->lpm_num_maps; - u32 sts_offset = pmcdev->map->lpm_status_offset; - u32 *lpm_req_regs = pmcdev->lpm_req_regs; + const int num_maps = pmc->map->lpm_num_maps; + u32 sts_offset = pmc->map->lpm_status_offset; + u32 *lpm_req_regs = pmc->lpm_req_regs; int mp; /* Display the header */ @@ -703,7 +769,7 @@ static int pmc_core_substate_req_regs_show(struct seq_file *s, void *unused) req_mask |= lpm_req_regs[mp + (mode * num_maps)]; /* Get the last latched status for this map */ - lpm_status = pmc_core_reg_read(pmcdev, sts_offset + (mp * 4)); + lpm_status = pmc_core_reg_read(pmc, sts_offset + (mp * 4)); /* Loop over elements in this map */ map = maps[mp]; @@ -746,11 +812,12 @@ DEFINE_SHOW_ATTRIBUTE(pmc_core_substate_req_regs); static int pmc_core_lpm_latch_mode_show(struct seq_file *s, void *unused) { struct pmc_dev *pmcdev = s->private; + struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN]; bool c10; u32 reg; int idx, mode; - reg = pmc_core_reg_read(pmcdev, pmcdev->map->lpm_sts_latch_en_offset); + reg = pmc_core_reg_read(pmc, pmc->map->lpm_sts_latch_en_offset); if (reg & LPM_STS_LATCH_MODE) { seq_puts(s, "c10"); c10 = false; @@ -777,6 +844,7 @@ static ssize_t pmc_core_lpm_latch_mode_write(struct file *file, { struct seq_file *s = file->private_data; struct pmc_dev *pmcdev = s->private; + struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN]; bool clear = false, c10 = false; unsigned char buf[8]; int idx, m, mode; @@ -813,9 +881,9 @@ static ssize_t pmc_core_lpm_latch_mode_write(struct file *file, if (clear) { mutex_lock(&pmcdev->lock); - reg = pmc_core_reg_read(pmcdev, pmcdev->map->etr3_offset); + reg = pmc_core_reg_read(pmc, pmc->map->etr3_offset); reg |= ETR3_CLEAR_LPM_EVENTS; - pmc_core_reg_write(pmcdev, pmcdev->map->etr3_offset, reg); + pmc_core_reg_write(pmc, pmc->map->etr3_offset, reg); mutex_unlock(&pmcdev->lock); @@ -825,9 +893,9 @@ static ssize_t pmc_core_lpm_latch_mode_write(struct file *file, if (c10) { mutex_lock(&pmcdev->lock); - reg = pmc_core_reg_read(pmcdev, pmcdev->map->lpm_sts_latch_en_offset); + reg = pmc_core_reg_read(pmc, pmc->map->lpm_sts_latch_en_offset); reg &= ~LPM_STS_LATCH_MODE; - pmc_core_reg_write(pmcdev, pmcdev->map->lpm_sts_latch_en_offset, reg); + pmc_core_reg_write(pmc, pmc->map->lpm_sts_latch_en_offset, reg); mutex_unlock(&pmcdev->lock); @@ -840,7 +908,7 @@ static ssize_t pmc_core_lpm_latch_mode_write(struct file *file, */ reg = LPM_STS_LATCH_MODE | BIT(mode); mutex_lock(&pmcdev->lock); - pmc_core_reg_write(pmcdev, pmcdev->map->lpm_sts_latch_en_offset, reg); + pmc_core_reg_write(pmc, pmc->map->lpm_sts_latch_en_offset, reg); mutex_unlock(&pmcdev->lock); return count; @@ -849,8 +917,8 @@ DEFINE_PMC_CORE_ATTR_WRITE(pmc_core_lpm_latch_mode); static int pmc_core_pkgc_show(struct seq_file *s, void *unused) { - struct pmc_dev *pmcdev = s->private; - const struct pmc_bit_map *map = pmcdev->map->msr_sts; + struct pmc *pmc = s->private; + const struct pmc_bit_map *map = pmc->map->msr_sts; u64 pcstate_count; int index; @@ -901,6 +969,7 @@ static bool pmc_core_pri_verify(u32 lpm_pri, u8 *mode_order) static void pmc_core_get_low_power_modes(struct platform_device *pdev) { struct pmc_dev *pmcdev = platform_get_drvdata(pdev); + struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN]; u8 pri_order[LPM_MAX_NUM_MODES] = LPM_DEFAULT_PRI; u8 mode_order[LPM_MAX_NUM_MODES]; u32 lpm_pri; @@ -908,10 +977,10 @@ static void pmc_core_get_low_power_modes(struct platform_device *pdev) int mode, i, p; /* Use LPM Maps to indicate support for substates */ - if (!pmcdev->map->lpm_num_maps) + if (!pmc->map->lpm_num_maps) return; - lpm_en = pmc_core_reg_read(pmcdev, pmcdev->map->lpm_en_offset); + lpm_en = pmc_core_reg_read(pmc, pmc->map->lpm_en_offset); /* For MTL, BIT 31 is not an lpm mode but a enable bit. * Lower byte is enough to cover the number of lpm modes for all * platforms and hence mask the upper 3 bytes. @@ -919,7 +988,7 @@ static void pmc_core_get_low_power_modes(struct platform_device *pdev) pmcdev->num_lpm_modes = hweight32(lpm_en & 0xFF); /* Read 32 bit LPM_PRI register */ - lpm_pri = pmc_core_reg_read(pmcdev, pmcdev->map->lpm_priority_offset); + lpm_pri = pmc_core_reg_read(pmc, pmc->map->lpm_priority_offset); /* @@ -948,6 +1017,25 @@ static void pmc_core_get_low_power_modes(struct platform_device *pdev) } } +int get_primary_reg_base(struct pmc *pmc) +{ + u64 slp_s0_addr; + + if (lpit_read_residency_count_address(&slp_s0_addr)) { + pmc->base_addr = PMC_BASE_ADDR_DEFAULT; + + if (page_is_ram(PHYS_PFN(pmc->base_addr))) + return -ENODEV; + } else { + pmc->base_addr = slp_s0_addr - pmc->map->slp_s0_offset; + } + + pmc->regbase = ioremap(pmc->base_addr, pmc->map->regmap_length); + if (!pmc->regbase) + return -ENOMEM; + return 0; +} + static void pmc_core_dbgfs_unregister(struct pmc_dev *pmcdev) { debugfs_remove_recursive(pmcdev->dbgfs_dir); @@ -955,15 +1043,16 @@ static void pmc_core_dbgfs_unregister(struct pmc_dev *pmcdev) static void pmc_core_dbgfs_register(struct pmc_dev *pmcdev) { + struct pmc *primary_pmc = pmcdev->pmcs[PMC_IDX_MAIN]; struct dentry *dir; dir = debugfs_create_dir("pmc_core", NULL); pmcdev->dbgfs_dir = dir; - debugfs_create_file("slp_s0_residency_usec", 0444, dir, pmcdev, + debugfs_create_file("slp_s0_residency_usec", 0444, dir, primary_pmc, &pmc_core_dev_state); - if (pmcdev->map->pfear_sts) + if (primary_pmc->map->pfear_sts) debugfs_create_file("pch_ip_power_gating_status", 0444, dir, pmcdev, &pmc_core_ppfear_fops); @@ -972,19 +1061,19 @@ static void pmc_core_dbgfs_register(struct pmc_dev *pmcdev) debugfs_create_file("ltr_show", 0444, dir, pmcdev, &pmc_core_ltr_fops); - debugfs_create_file("package_cstate_show", 0444, dir, pmcdev, + debugfs_create_file("package_cstate_show", 0444, dir, primary_pmc, &pmc_core_pkgc_fops); - if (pmcdev->map->pll_sts) + if (primary_pmc->map->pll_sts) debugfs_create_file("pll_status", 0444, dir, pmcdev, &pmc_core_pll_fops); - if (pmcdev->map->mphy_sts) + if (primary_pmc->map->mphy_sts) debugfs_create_file("mphy_core_lanes_power_gating_status", 0444, dir, pmcdev, &pmc_core_mphy_pg_fops); - if (pmcdev->map->slps0_dbg_maps) { + if (primary_pmc->map->slps0_dbg_maps) { debugfs_create_file("slp_s0_debug_status", 0444, dir, pmcdev, &pmc_core_slps0_dbg_fops); @@ -993,13 +1082,13 @@ static void pmc_core_dbgfs_register(struct pmc_dev *pmcdev) dir, &slps0_dbg_latch); } - if (pmcdev->map->lpm_en_offset) { + if (primary_pmc->map->lpm_en_offset) { debugfs_create_file("substate_residencies", 0444, pmcdev->dbgfs_dir, pmcdev, &pmc_core_substate_res_fops); } - if (pmcdev->map->lpm_status_offset) { + if (primary_pmc->map->lpm_status_offset) { debugfs_create_file("substate_status_registers", 0444, pmcdev->dbgfs_dir, pmcdev, &pmc_core_substate_sts_regs_fops); @@ -1011,7 +1100,7 @@ static void pmc_core_dbgfs_register(struct pmc_dev *pmcdev) &pmc_core_lpm_latch_mode_fops); } - if (pmcdev->lpm_req_regs) { + if (primary_pmc->lpm_req_regs) { debugfs_create_file("substate_requirements", 0444, pmcdev->dbgfs_dir, pmcdev, &pmc_core_substate_req_regs_fops); @@ -1039,7 +1128,6 @@ static const struct x86_cpu_id intel_pmc_core_ids[] = { X86_MATCH_INTEL_FAM6_MODEL(RAPTORLAKE_P, tgl_core_init), X86_MATCH_INTEL_FAM6_MODEL(RAPTORLAKE, adl_core_init), X86_MATCH_INTEL_FAM6_MODEL(RAPTORLAKE_S, adl_core_init), - X86_MATCH_INTEL_FAM6_MODEL(METEORLAKE, mtl_core_init), X86_MATCH_INTEL_FAM6_MODEL(METEORLAKE_L, mtl_core_init), {} }; @@ -1063,16 +1151,16 @@ static int quirk_xtal_ignore(const struct dmi_system_id *id) return 0; } -static void pmc_core_xtal_ignore(struct pmc_dev *pmcdev) +static void pmc_core_xtal_ignore(struct pmc *pmc) { u32 value; - value = pmc_core_reg_read(pmcdev, pmcdev->map->pm_vric1_offset); + value = pmc_core_reg_read(pmc, pmc->map->pm_vric1_offset); /* 24MHz Crystal Shutdown Qualification Disable */ value |= SPT_PMC_VRIC1_XTALSDQDIS; /* Low Voltage Mode Enable */ value &= ~SPT_PMC_VRIC1_SLPS0LVEN; - pmc_core_reg_write(pmcdev, pmcdev->map->pm_vric1_offset, value); + pmc_core_reg_write(pmc, pmc->map->pm_vric1_offset, value); } static const struct dmi_system_id pmc_core_dmi_table[] = { @@ -1087,12 +1175,32 @@ static const struct dmi_system_id pmc_core_dmi_table[] = { {} }; -static void pmc_core_do_dmi_quirks(struct pmc_dev *pmcdev) +static void pmc_core_do_dmi_quirks(struct pmc *pmc) { dmi_check_system(pmc_core_dmi_table); if (xtal_ignore) - pmc_core_xtal_ignore(pmcdev); + pmc_core_xtal_ignore(pmc); +} + +static void pmc_core_clean_structure(struct platform_device *pdev) +{ + struct pmc_dev *pmcdev = platform_get_drvdata(pdev); + int i; + + for (i = 0; i < ARRAY_SIZE(pmcdev->pmcs); ++i) { + struct pmc *pmc = pmcdev->pmcs[i]; + + if (pmc) + iounmap(pmc->regbase); + } + + if (pmcdev->ssram_pcidev) { + pci_dev_put(pmcdev->ssram_pcidev); + pci_disable_device(pmcdev->ssram_pcidev); + } + platform_set_drvdata(pdev, NULL); + mutex_destroy(&pmcdev->lock); } static int pmc_core_probe(struct platform_device *pdev) @@ -1100,8 +1208,9 @@ static int pmc_core_probe(struct platform_device *pdev) static bool device_initialized; struct pmc_dev *pmcdev; const struct x86_cpu_id *cpu_id; - void (*core_init)(struct pmc_dev *pmcdev); - u64 slp_s0_addr; + int (*core_init)(struct pmc_dev *pmcdev); + struct pmc *primary_pmc; + int ret; if (device_initialized) return -ENODEV; @@ -1117,7 +1226,13 @@ static int pmc_core_probe(struct platform_device *pdev) if (!cpu_id) return -ENODEV; - core_init = (void (*)(struct pmc_dev *))cpu_id->driver_data; + core_init = (int (*)(struct pmc_dev *))cpu_id->driver_data; + + /* Primary PMC */ + primary_pmc = devm_kzalloc(&pdev->dev, sizeof(*primary_pmc), GFP_KERNEL); + if (!primary_pmc) + return -ENOMEM; + pmcdev->pmcs[PMC_IDX_MAIN] = primary_pmc; /* * Coffee Lake has CPU ID of Kaby Lake and Cannon Lake PCH. So here @@ -1128,33 +1243,19 @@ static int pmc_core_probe(struct platform_device *pdev) core_init = cnp_core_init; mutex_init(&pmcdev->lock); - core_init(pmcdev); - - - if (lpit_read_residency_count_address(&slp_s0_addr)) { - pmcdev->base_addr = PMC_BASE_ADDR_DEFAULT; - - if (page_is_ram(PHYS_PFN(pmcdev->base_addr))) - return -ENODEV; - } else { - pmcdev->base_addr = slp_s0_addr - pmcdev->map->slp_s0_offset; + ret = core_init(pmcdev); + if (ret) { + pmc_core_clean_structure(pdev); + return ret; } - pmcdev->regbase = ioremap(pmcdev->base_addr, - pmcdev->map->regmap_length); - if (!pmcdev->regbase) - return -ENOMEM; - - if (pmcdev->core_configure) - pmcdev->core_configure(pmcdev); - - pmcdev->pmc_xram_read_bit = pmc_core_check_read_lock_bit(pmcdev); + pmcdev->pmc_xram_read_bit = pmc_core_check_read_lock_bit(primary_pmc); pmc_core_get_low_power_modes(pdev); - pmc_core_do_dmi_quirks(pmcdev); + pmc_core_do_dmi_quirks(primary_pmc); pmc_core_dbgfs_register(pmcdev); pm_report_max_hw_sleep(FIELD_MAX(SLP_S0_RES_COUNTER_MASK) * - pmc_core_adjust_slp_s0_step(pmcdev, 1)); + pmc_core_adjust_slp_s0_step(primary_pmc, 1)); device_initialized = true; dev_info(&pdev->dev, " initialized\n"); @@ -1165,11 +1266,8 @@ static int pmc_core_probe(struct platform_device *pdev) static void pmc_core_remove(struct platform_device *pdev) { struct pmc_dev *pmcdev = platform_get_drvdata(pdev); - pmc_core_dbgfs_unregister(pmcdev); - platform_set_drvdata(pdev, NULL); - mutex_destroy(&pmcdev->lock); - iounmap(pmcdev->regbase); + pmc_core_clean_structure(pdev); } static bool warn_on_s0ix_failures; @@ -1179,6 +1277,7 @@ MODULE_PARM_DESC(warn_on_s0ix_failures, "Check and warn for S0ix failures"); static __maybe_unused int pmc_core_suspend(struct device *dev) { struct pmc_dev *pmcdev = dev_get_drvdata(dev); + struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN]; /* Check if the syspend will actually use S0ix */ if (pm_suspend_via_firmware()) @@ -1189,7 +1288,7 @@ static __maybe_unused int pmc_core_suspend(struct device *dev) return -EIO; /* Save S0ix residency for checking later */ - if (pmc_core_dev_state_get(pmcdev, &pmcdev->s0ix_counter)) + if (pmc_core_dev_state_get(pmc, &pmcdev->s0ix_counter)) return -EIO; return 0; @@ -1212,7 +1311,7 @@ static inline bool pmc_core_is_s0ix_failed(struct pmc_dev *pmcdev) { u64 s0ix_counter; - if (pmc_core_dev_state_get(pmcdev, &s0ix_counter)) + if (pmc_core_dev_state_get(pmcdev->pmcs[PMC_IDX_MAIN], &s0ix_counter)) return false; pm_report_hw_sleep_time((u32)(s0ix_counter - pmcdev->s0ix_counter)); @@ -1223,11 +1322,13 @@ static inline bool pmc_core_is_s0ix_failed(struct pmc_dev *pmcdev) return false; } -static __maybe_unused int pmc_core_resume(struct device *dev) +int pmc_core_resume_common(struct pmc_dev *pmcdev) { - struct pmc_dev *pmcdev = dev_get_drvdata(dev); - const struct pmc_bit_map **maps = pmcdev->map->lpm_sts; - int offset = pmcdev->map->lpm_status_offset; + struct device *dev = &pmcdev->pdev->dev; + struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN]; + const struct pmc_bit_map **maps = pmc->map->lpm_sts; + int offset = pmc->map->lpm_status_offset; + int i; /* Check if the syspend used S0ix */ if (pm_suspend_via_firmware()) @@ -1249,14 +1350,32 @@ static __maybe_unused int pmc_core_resume(struct device *dev) /* The real interesting case - S0ix failed - lets ask PMC why. */ dev_warn(dev, "CPU did not enter SLP_S0!!! (S0ix cnt=%llu)\n", pmcdev->s0ix_counter); - if (pmcdev->map->slps0_dbg_maps) - pmc_core_slps0_display(pmcdev, dev, NULL); - if (pmcdev->map->lpm_sts) - pmc_core_lpm_display(pmcdev, dev, NULL, offset, "STATUS", maps); + + if (pmc->map->slps0_dbg_maps) + pmc_core_slps0_display(pmc, dev, NULL); + + for (i = 0; i < ARRAY_SIZE(pmcdev->pmcs); ++i) { + struct pmc *pmc = pmcdev->pmcs[i]; + + if (!pmc) + continue; + if (pmc->map->lpm_sts) + pmc_core_lpm_display(pmc, dev, NULL, offset, i, "STATUS", maps); + } return 0; } +static __maybe_unused int pmc_core_resume(struct device *dev) +{ + struct pmc_dev *pmcdev = dev_get_drvdata(dev); + + if (pmcdev->resume) + return pmcdev->resume(pmcdev); + + return pmc_core_resume_common(pmcdev); +} + static const struct dev_pm_ops pmc_core_pm_ops = { SET_LATE_SYSTEM_SLEEP_PM_OPS(pmc_core_suspend, pmc_core_resume) }; diff --git a/drivers/platform/x86/intel/pmc/core.h b/drivers/platform/x86/intel/pmc/core.h index 9ca9b974671939964d4a53045d15977590f2a265..0729f593c6a7591b331194d95acb25b31398b089 100644 --- a/drivers/platform/x86/intel/pmc/core.h +++ b/drivers/platform/x86/intel/pmc/core.h @@ -19,6 +19,7 @@ #define SLP_S0_RES_COUNTER_MASK GENMASK(31, 0) #define PMC_BASE_ADDR_DEFAULT 0xFE000000 +#define MAX_NUM_PMC 3 /* Sunrise Point Power Management Controller PCI Device ID */ #define SPT_PMC_PCI_DEVICE_ID 0x9d21 @@ -249,6 +250,17 @@ enum ppfear_regs { #define MTL_LPM_STATUS_LATCH_EN_OFFSET 0x16F8 #define MTL_LPM_STATUS_OFFSET 0x1700 #define MTL_LPM_LIVE_STATUS_OFFSET 0x175C +#define MTL_PMC_LTR_IOE_PMC 0x1C0C +#define MTL_PMC_LTR_ESE 0x1BAC +#define MTL_PMC_LTR_RESERVED 0x1BA4 +#define MTL_IOE_PMC_MMIO_REG_LEN 0x23A4 +#define MTL_SOCM_NUM_IP_IGN_ALLOWED 25 +#define MTL_SOC_PMC_MMIO_REG_LEN 0x2708 +#define MTL_PMC_LTR_SPG 0x1B74 + +/* Meteor Lake PGD PFET Enable Ack Status */ +#define MTL_SOCM_PPFEAR_NUM_ENTRIES 8 +#define MTL_IOE_PPFEAR_NUM_ENTRIES 10 extern const char *pmc_lpm_modes[]; @@ -311,12 +323,38 @@ struct pmc_reg_map { }; /** - * struct pmc_dev - pmc device structure + * struct pmc_info - Structure to keep pmc info + * @devid: device id of the pmc device + * @map: pointer to a pmc_reg_map struct that contains platform + * specific attributes + */ +struct pmc_info { + u16 devid; + const struct pmc_reg_map *map; +}; + +/** + * struct pmc - pmc private info structure * @base_addr: contains pmc base address * @regbase: pointer to io-remapped memory location * @map: pointer to pmc_reg_map struct that contains platform * specific attributes + * @lpm_req_regs: List of substate requirements + * + * pmc contains info about one power management controller device. + */ +struct pmc { + u64 base_addr; + void __iomem *regbase; + const struct pmc_reg_map *map; + u32 *lpm_req_regs; +}; + +/** + * struct pmc_dev - pmc device structure + * @devs: pointer to an array of pmc pointers * @pdev: pointer to platform_device struct + * @ssram_pcidev: pointer to pci device struct for the PMC SSRAM * @dbgfs_dir: path to debugfs interface * @pmc_xram_read_bit: flag to indicate whether PMC XRAM shadow registers * used to read MPHY PG and PLL status are available @@ -325,17 +363,15 @@ struct pmc_reg_map { * @s0ix_counter: S0ix residency (step adjusted) * @num_lpm_modes: Count of enabled modes * @lpm_en_modes: Array of enabled modes from lowest to highest priority - * @lpm_req_regs: List of substate requirements - * @core_configure: Function pointer to configure the platform + * @resume: Function to perform platform specific resume * * pmc_dev contains info about power management controller device. */ struct pmc_dev { - u32 base_addr; - void __iomem *regbase; - const struct pmc_reg_map *map; + struct pmc *pmcs[MAX_NUM_PMC]; struct dentry *dbgfs_dir; struct platform_device *pdev; + struct pci_dev *ssram_pcidev; int pmc_xram_read_bit; struct mutex lock; /* generic mutex lock for PMC Core */ @@ -343,8 +379,20 @@ struct pmc_dev { u64 s0ix_counter; int num_lpm_modes; int lpm_en_modes[LPM_MAX_NUM_MODES]; - u32 *lpm_req_regs; - void (*core_configure)(struct pmc_dev *pmcdev); + int (*resume)(struct pmc_dev *pmcdev); + + bool has_die_c6; + u32 die_c6_offset; + struct telem_endpoint *punit_ep; + struct pmc_info *regmap_list; +}; + +enum pmc_index { + PMC_IDX_MAIN, + PMC_IDX_SOC = PMC_IDX_MAIN, + PMC_IDX_IOE, + PMC_IDX_PCH, + PMC_IDX_MAX }; extern const struct pmc_bit_map msr_map[]; @@ -393,20 +441,64 @@ extern const struct pmc_bit_map adl_vnn_req_status_3_map[]; extern const struct pmc_bit_map adl_vnn_misc_status_map[]; extern const struct pmc_bit_map *adl_lpm_maps[]; extern const struct pmc_reg_map adl_reg_map; -extern const struct pmc_reg_map mtl_reg_map; +extern const struct pmc_bit_map mtl_socm_pfear_map[]; +extern const struct pmc_bit_map *ext_mtl_socm_pfear_map[]; +extern const struct pmc_bit_map mtl_socm_ltr_show_map[]; +extern const struct pmc_bit_map mtl_socm_clocksource_status_map[]; +extern const struct pmc_bit_map mtl_socm_power_gating_status_0_map[]; +extern const struct pmc_bit_map mtl_socm_power_gating_status_1_map[]; +extern const struct pmc_bit_map mtl_socm_power_gating_status_2_map[]; +extern const struct pmc_bit_map mtl_socm_d3_status_0_map[]; +extern const struct pmc_bit_map mtl_socm_d3_status_1_map[]; +extern const struct pmc_bit_map mtl_socm_d3_status_2_map[]; +extern const struct pmc_bit_map mtl_socm_d3_status_3_map[]; +extern const struct pmc_bit_map mtl_socm_vnn_req_status_0_map[]; +extern const struct pmc_bit_map mtl_socm_vnn_req_status_1_map[]; +extern const struct pmc_bit_map mtl_socm_vnn_req_status_2_map[]; +extern const struct pmc_bit_map mtl_socm_vnn_req_status_3_map[]; +extern const struct pmc_bit_map mtl_socm_vnn_misc_status_map[]; +extern const struct pmc_bit_map mtl_socm_signal_status_map[]; +extern const struct pmc_bit_map *mtl_socm_lpm_maps[]; +extern const struct pmc_reg_map mtl_socm_reg_map; +extern const struct pmc_bit_map mtl_ioep_pfear_map[]; +extern const struct pmc_bit_map *ext_mtl_ioep_pfear_map[]; +extern const struct pmc_bit_map mtl_ioep_ltr_show_map[]; +extern const struct pmc_bit_map mtl_ioep_clocksource_status_map[]; +extern const struct pmc_bit_map mtl_ioep_power_gating_status_0_map[]; +extern const struct pmc_bit_map mtl_ioep_power_gating_status_1_map[]; +extern const struct pmc_bit_map mtl_ioep_power_gating_status_2_map[]; +extern const struct pmc_bit_map mtl_ioep_d3_status_0_map[]; +extern const struct pmc_bit_map mtl_ioep_d3_status_1_map[]; +extern const struct pmc_bit_map mtl_ioep_d3_status_2_map[]; +extern const struct pmc_bit_map mtl_ioep_d3_status_3_map[]; +extern const struct pmc_bit_map mtl_ioep_vnn_req_status_0_map[]; +extern const struct pmc_bit_map mtl_ioep_vnn_req_status_1_map[]; +extern const struct pmc_bit_map mtl_ioep_vnn_req_status_2_map[]; +extern const struct pmc_bit_map mtl_ioep_vnn_req_status_3_map[]; +extern const struct pmc_bit_map mtl_ioep_vnn_misc_status_map[]; +extern const struct pmc_bit_map *mtl_ioep_lpm_maps[]; +extern const struct pmc_reg_map mtl_ioep_reg_map; +extern const struct pmc_bit_map mtl_ioem_pfear_map[]; +extern const struct pmc_bit_map *ext_mtl_ioem_pfear_map[]; +extern const struct pmc_bit_map mtl_ioem_power_gating_status_1_map[]; +extern const struct pmc_bit_map mtl_ioem_vnn_req_status_1_map[]; +extern const struct pmc_bit_map *mtl_ioem_lpm_maps[]; +extern const struct pmc_reg_map mtl_ioem_reg_map; extern void pmc_core_get_tgl_lpm_reqs(struct platform_device *pdev); extern int pmc_core_send_ltr_ignore(struct pmc_dev *pmcdev, u32 value); -void spt_core_init(struct pmc_dev *pmcdev); -void cnp_core_init(struct pmc_dev *pmcdev); -void icl_core_init(struct pmc_dev *pmcdev); -void tgl_core_init(struct pmc_dev *pmcdev); -void adl_core_init(struct pmc_dev *pmcdev); -void mtl_core_init(struct pmc_dev *pmcdev); -void tgl_core_configure(struct pmc_dev *pmcdev); -void adl_core_configure(struct pmc_dev *pmcdev); -void mtl_core_configure(struct pmc_dev *pmcdev); +int pmc_core_resume_common(struct pmc_dev *pmcdev); +int get_primary_reg_base(struct pmc *pmc); + +extern void pmc_core_ssram_init(struct pmc_dev *pmcdev); + +int spt_core_init(struct pmc_dev *pmcdev); +int cnp_core_init(struct pmc_dev *pmcdev); +int icl_core_init(struct pmc_dev *pmcdev); +int tgl_core_init(struct pmc_dev *pmcdev); +int adl_core_init(struct pmc_dev *pmcdev); +int mtl_core_init(struct pmc_dev *pmcdev); #define pmc_for_each_mode(i, mode, pmcdev) \ for (i = 0, mode = pmcdev->lpm_en_modes[i]; \ diff --git a/drivers/platform/x86/intel/pmc/core_ssram.c b/drivers/platform/x86/intel/pmc/core_ssram.c new file mode 100644 index 0000000000000000000000000000000000000000..13fa16f0d52e73feecfe6f562a836022ab1e3be3 --- /dev/null +++ b/drivers/platform/x86/intel/pmc/core_ssram.c @@ -0,0 +1,133 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * This file contains functions to handle discovery of PMC metrics located + * in the PMC SSRAM PCI device. + * + * Copyright (c) 2023, Intel Corporation. + * All Rights Reserved. + * + */ + +#include +#include + +#include "core.h" + +#define SSRAM_HDR_SIZE 0x100 +#define SSRAM_PWRM_OFFSET 0x14 +#define SSRAM_DVSEC_OFFSET 0x1C +#define SSRAM_DVSEC_SIZE 0x10 +#define SSRAM_PCH_OFFSET 0x60 +#define SSRAM_IOE_OFFSET 0x68 +#define SSRAM_DEVID_OFFSET 0x70 + +static const struct pmc_reg_map *pmc_core_find_regmap(struct pmc_info *list, u16 devid) +{ + for (; list->map; ++list) + if (devid == list->devid) + return list->map; + + return NULL; +} + +static inline u64 get_base(void __iomem *addr, u32 offset) +{ + return lo_hi_readq(addr + offset) & GENMASK_ULL(63, 3); +} + +static void +pmc_core_pmc_add(struct pmc_dev *pmcdev, u64 pwrm_base, + const struct pmc_reg_map *reg_map, int pmc_index) +{ + struct pmc *pmc = pmcdev->pmcs[pmc_index]; + + if (!pwrm_base) + return; + + /* Memory for primary PMC has been allocated in core.c */ + if (!pmc) { + pmc = devm_kzalloc(&pmcdev->pdev->dev, sizeof(*pmc), GFP_KERNEL); + if (!pmc) + return; + } + + pmc->map = reg_map; + pmc->base_addr = pwrm_base; + pmc->regbase = ioremap(pmc->base_addr, pmc->map->regmap_length); + + if (!pmc->regbase) { + devm_kfree(&pmcdev->pdev->dev, pmc); + return; + } + + pmcdev->pmcs[pmc_index] = pmc; +} + +static void +pmc_core_ssram_get_pmc(struct pmc_dev *pmcdev, void __iomem *ssram, u32 offset, + int pmc_idx) +{ + u64 pwrm_base; + u16 devid; + + if (pmc_idx != PMC_IDX_SOC) { + u64 ssram_base = get_base(ssram, offset); + + if (!ssram_base) + return; + + ssram = ioremap(ssram_base, SSRAM_HDR_SIZE); + if (!ssram) + return; + } + + pwrm_base = get_base(ssram, SSRAM_PWRM_OFFSET); + devid = readw(ssram + SSRAM_DEVID_OFFSET); + + if (pmcdev->regmap_list) { + const struct pmc_reg_map *map; + + map = pmc_core_find_regmap(pmcdev->regmap_list, devid); + if (map) + pmc_core_pmc_add(pmcdev, pwrm_base, map, pmc_idx); + } + + if (pmc_idx != PMC_IDX_SOC) + iounmap(ssram); +} + +void pmc_core_ssram_init(struct pmc_dev *pmcdev) +{ + void __iomem *ssram; + struct pci_dev *pcidev; + u64 ssram_base; + int ret; + + pcidev = pci_get_domain_bus_and_slot(0, 0, PCI_DEVFN(20, 2)); + if (!pcidev) + goto out; + + ret = pcim_enable_device(pcidev); + if (ret) + goto release_dev; + + ssram_base = pcidev->resource[0].start; + ssram = ioremap(ssram_base, SSRAM_HDR_SIZE); + if (!ssram) + goto disable_dev; + + pmcdev->ssram_pcidev = pcidev; + + pmc_core_ssram_get_pmc(pmcdev, ssram, 0, PMC_IDX_SOC); + pmc_core_ssram_get_pmc(pmcdev, ssram, SSRAM_IOE_OFFSET, PMC_IDX_IOE); + pmc_core_ssram_get_pmc(pmcdev, ssram, SSRAM_PCH_OFFSET, PMC_IDX_PCH); + + iounmap(ssram); +out: + return; + +disable_dev: + pci_disable_device(pcidev); +release_dev: + pci_dev_put(pcidev); +} diff --git a/drivers/platform/x86/intel/pmc/icl.c b/drivers/platform/x86/intel/pmc/icl.c index 2f11b1a6daebae5f712c292ee297ad6de2c43422..d08e3174230d25cbc0f920a2ae774140ecefd097 100644 --- a/drivers/platform/x86/intel/pmc/icl.c +++ b/drivers/platform/x86/intel/pmc/icl.c @@ -50,7 +50,10 @@ const struct pmc_reg_map icl_reg_map = { .etr3_offset = ETR3_OFFSET, }; -void icl_core_init(struct pmc_dev *pmcdev) +int icl_core_init(struct pmc_dev *pmcdev) { - pmcdev->map = &icl_reg_map; + struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN]; + + pmc->map = &icl_reg_map; + return get_primary_reg_base(pmc); } diff --git a/drivers/platform/x86/intel/pmc/mtl.c b/drivers/platform/x86/intel/pmc/mtl.c index e8cc156412ce56a758d9f2e14cb87a68138b276e..2204bc666980edce05da3eb73feb92851016e85a 100644 --- a/drivers/platform/x86/intel/pmc/mtl.c +++ b/drivers/platform/x86/intel/pmc/mtl.c @@ -11,40 +11,937 @@ #include #include "core.h" -const struct pmc_reg_map mtl_reg_map = { - .pfear_sts = ext_tgl_pfear_map, +/* + * Die Mapping to Product. + * Product SOCDie IOEDie PCHDie + * MTL-M SOC-M IOE-M None + * MTL-P SOC-M IOE-P None + * MTL-S SOC-S IOE-P PCH-S + */ + +const struct pmc_bit_map mtl_socm_pfear_map[] = { + {"PMC", BIT(0)}, + {"OPI", BIT(1)}, + {"SPI", BIT(2)}, + {"XHCI", BIT(3)}, + {"SPA", BIT(4)}, + {"SPB", BIT(5)}, + {"SPC", BIT(6)}, + {"GBE", BIT(7)}, + + {"SATA", BIT(0)}, + {"DSP0", BIT(1)}, + {"DSP1", BIT(2)}, + {"DSP2", BIT(3)}, + {"DSP3", BIT(4)}, + {"SPD", BIT(5)}, + {"LPSS", BIT(6)}, + {"LPC", BIT(7)}, + + {"SMB", BIT(0)}, + {"ISH", BIT(1)}, + {"P2SB", BIT(2)}, + {"NPK_VNN", BIT(3)}, + {"SDX", BIT(4)}, + {"SPE", BIT(5)}, + {"FUSE", BIT(6)}, + {"SBR8", BIT(7)}, + + {"RSVD24", BIT(0)}, + {"OTG", BIT(1)}, + {"EXI", BIT(2)}, + {"CSE", BIT(3)}, + {"CSME_KVM", BIT(4)}, + {"CSME_PMT", BIT(5)}, + {"CSME_CLINK", BIT(6)}, + {"CSME_PTIO", BIT(7)}, + + {"CSME_USBR", BIT(0)}, + {"CSME_SUSRAM", BIT(1)}, + {"CSME_SMT1", BIT(2)}, + {"RSVD35", BIT(3)}, + {"CSME_SMS2", BIT(4)}, + {"CSME_SMS", BIT(5)}, + {"CSME_RTC", BIT(6)}, + {"CSME_PSF", BIT(7)}, + + {"SBR0", BIT(0)}, + {"SBR1", BIT(1)}, + {"SBR2", BIT(2)}, + {"SBR3", BIT(3)}, + {"SBR4", BIT(4)}, + {"SBR5", BIT(5)}, + {"RSVD46", BIT(6)}, + {"PSF1", BIT(7)}, + + {"PSF2", BIT(0)}, + {"PSF3", BIT(1)}, + {"PSF4", BIT(2)}, + {"CNVI", BIT(3)}, + {"UFSX2", BIT(4)}, + {"EMMC", BIT(5)}, + {"SPF", BIT(6)}, + {"SBR6", BIT(7)}, + + {"SBR7", BIT(0)}, + {"NPK_AON", BIT(1)}, + {"HDA4", BIT(2)}, + {"HDA5", BIT(3)}, + {"HDA6", BIT(4)}, + {"PSF6", BIT(5)}, + {"RSVD62", BIT(6)}, + {"RSVD63", BIT(7)}, + {} +}; + +const struct pmc_bit_map *ext_mtl_socm_pfear_map[] = { + mtl_socm_pfear_map, + NULL +}; + +const struct pmc_bit_map mtl_socm_ltr_show_map[] = { + {"SOUTHPORT_A", CNP_PMC_LTR_SPA}, + {"SOUTHPORT_B", CNP_PMC_LTR_SPB}, + {"SATA", CNP_PMC_LTR_SATA}, + {"GIGABIT_ETHERNET", CNP_PMC_LTR_GBE}, + {"XHCI", CNP_PMC_LTR_XHCI}, + {"SOUTHPORT_F", ADL_PMC_LTR_SPF}, + {"ME", CNP_PMC_LTR_ME}, + {"SATA1", CNP_PMC_LTR_EVA}, + {"SOUTHPORT_C", CNP_PMC_LTR_SPC}, + {"HD_AUDIO", CNP_PMC_LTR_AZ}, + {"CNV", CNP_PMC_LTR_CNV}, + {"LPSS", CNP_PMC_LTR_LPSS}, + {"SOUTHPORT_D", CNP_PMC_LTR_SPD}, + {"SOUTHPORT_E", CNP_PMC_LTR_SPE}, + {"SATA2", CNP_PMC_LTR_CAM}, + {"ESPI", CNP_PMC_LTR_ESPI}, + {"SCC", CNP_PMC_LTR_SCC}, + {"ISH", CNP_PMC_LTR_ISH}, + {"UFSX2", CNP_PMC_LTR_UFSX2}, + {"EMMC", CNP_PMC_LTR_EMMC}, + {"WIGIG", ICL_PMC_LTR_WIGIG}, + {"THC0", TGL_PMC_LTR_THC0}, + {"THC1", TGL_PMC_LTR_THC1}, + {"SOUTHPORT_G", MTL_PMC_LTR_SPG}, + {"ESE", MTL_PMC_LTR_ESE}, + {"IOE_PMC", MTL_PMC_LTR_IOE_PMC}, + + /* Below two cannot be used for LTR_IGNORE */ + {"CURRENT_PLATFORM", CNP_PMC_LTR_CUR_PLT}, + {"AGGREGATED_SYSTEM", CNP_PMC_LTR_CUR_ASLT}, + {} +}; + +const struct pmc_bit_map mtl_socm_clocksource_status_map[] = { + {"AON2_OFF_STS", BIT(0)}, + {"AON3_OFF_STS", BIT(1)}, + {"AON4_OFF_STS", BIT(2)}, + {"AON5_OFF_STS", BIT(3)}, + {"AON1_OFF_STS", BIT(4)}, + {"XTAL_LVM_OFF_STS", BIT(5)}, + {"MPFPW1_0_PLL_OFF_STS", BIT(6)}, + {"MPFPW1_1_PLL_OFF_STS", BIT(7)}, + {"USB3_PLL_OFF_STS", BIT(8)}, + {"AON3_SPL_OFF_STS", BIT(9)}, + {"MPFPW2_0_PLL_OFF_STS", BIT(12)}, + {"MPFPW3_0_PLL_OFF_STS", BIT(13)}, + {"XTAL_AGGR_OFF_STS", BIT(17)}, + {"USB2_PLL_OFF_STS", BIT(18)}, + {"FILTER_PLL_OFF_STS", BIT(22)}, + {"ACE_PLL_OFF_STS", BIT(24)}, + {"FABRIC_PLL_OFF_STS", BIT(25)}, + {"SOC_PLL_OFF_STS", BIT(26)}, + {"PCIFAB_PLL_OFF_STS", BIT(27)}, + {"REF_PLL_OFF_STS", BIT(28)}, + {"IMG_PLL_OFF_STS", BIT(29)}, + {"RTC_PLL_OFF_STS", BIT(31)}, + {} +}; + +const struct pmc_bit_map mtl_socm_power_gating_status_0_map[] = { + {"PMC_PGD0_PG_STS", BIT(0)}, + {"DMI_PGD0_PG_STS", BIT(1)}, + {"ESPISPI_PGD0_PG_STS", BIT(2)}, + {"XHCI_PGD0_PG_STS", BIT(3)}, + {"SPA_PGD0_PG_STS", BIT(4)}, + {"SPB_PGD0_PG_STS", BIT(5)}, + {"SPC_PGD0_PG_STS", BIT(6)}, + {"GBE_PGD0_PG_STS", BIT(7)}, + {"SATA_PGD0_PG_STS", BIT(8)}, + {"PSF13_PGD0_PG_STS", BIT(9)}, + {"SOC_D2D_PGD3_PG_STS", BIT(10)}, + {"MPFPW3_PGD0_PG_STS", BIT(11)}, + {"ESE_PGD0_PG_STS", BIT(12)}, + {"SPD_PGD0_PG_STS", BIT(13)}, + {"LPSS_PGD0_PG_STS", BIT(14)}, + {"LPC_PGD0_PG_STS", BIT(15)}, + {"SMB_PGD0_PG_STS", BIT(16)}, + {"ISH_PGD0_PG_STS", BIT(17)}, + {"P2S_PGD0_PG_STS", BIT(18)}, + {"NPK_PGD0_PG_STS", BIT(19)}, + {"DBG_SBR_PGD0_PG_STS", BIT(20)}, + {"SBRG_PGD0_PG_STS", BIT(21)}, + {"FUSE_PGD0_PG_STS", BIT(22)}, + {"SBR8_PGD0_PG_STS", BIT(23)}, + {"SOC_D2D_PGD2_PG_STS", BIT(24)}, + {"XDCI_PGD0_PG_STS", BIT(25)}, + {"EXI_PGD0_PG_STS", BIT(26)}, + {"CSE_PGD0_PG_STS", BIT(27)}, + {"KVMCC_PGD0_PG_STS", BIT(28)}, + {"PMT_PGD0_PG_STS", BIT(29)}, + {"CLINK_PGD0_PG_STS", BIT(30)}, + {"PTIO_PGD0_PG_STS", BIT(31)}, + {} +}; + +const struct pmc_bit_map mtl_socm_power_gating_status_1_map[] = { + {"USBR0_PGD0_PG_STS", BIT(0)}, + {"SUSRAM_PGD0_PG_STS", BIT(1)}, + {"SMT1_PGD0_PG_STS", BIT(2)}, + {"FIACPCB_U_PGD0_PG_STS", BIT(3)}, + {"SMS2_PGD0_PG_STS", BIT(4)}, + {"SMS1_PGD0_PG_STS", BIT(5)}, + {"CSMERTC_PGD0_PG_STS", BIT(6)}, + {"CSMEPSF_PGD0_PG_STS", BIT(7)}, + {"SBR0_PGD0_PG_STS", BIT(8)}, + {"SBR1_PGD0_PG_STS", BIT(9)}, + {"SBR2_PGD0_PG_STS", BIT(10)}, + {"SBR3_PGD0_PG_STS", BIT(11)}, + {"U3FPW1_PGD0_PG_STS", BIT(12)}, + {"SBR5_PGD0_PG_STS", BIT(13)}, + {"MPFPW1_PGD0_PG_STS", BIT(14)}, + {"UFSPW1_PGD0_PG_STS", BIT(15)}, + {"FIA_X_PGD0_PG_STS", BIT(16)}, + {"SOC_D2D_PGD0_PG_STS", BIT(17)}, + {"MPFPW2_PGD0_PG_STS", BIT(18)}, + {"CNVI_PGD0_PG_STS", BIT(19)}, + {"UFSX2_PGD0_PG_STS", BIT(20)}, + {"ENDBG_PGD0_PG_STS", BIT(21)}, + {"DBG_PSF_PGD0_PG_STS", BIT(22)}, + {"SBR6_PGD0_PG_STS", BIT(23)}, + {"SBR7_PGD0_PG_STS", BIT(24)}, + {"NPK_PGD1_PG_STS", BIT(25)}, + {"FIACPCB_X_PGD0_PG_STS", BIT(26)}, + {"DBC_PGD0_PG_STS", BIT(27)}, + {"FUSEGPSB_PGD0_PG_STS", BIT(28)}, + {"PSF6_PGD0_PG_STS", BIT(29)}, + {"PSF7_PGD0_PG_STS", BIT(30)}, + {"GBETSN1_PGD0_PG_STS", BIT(31)}, + {} +}; + +const struct pmc_bit_map mtl_socm_power_gating_status_2_map[] = { + {"PSF8_PGD0_PG_STS", BIT(0)}, + {"FIA_PGD0_PG_STS", BIT(1)}, + {"SOC_D2D_PGD1_PG_STS", BIT(2)}, + {"FIA_U_PGD0_PG_STS", BIT(3)}, + {"TAM_PGD0_PG_STS", BIT(4)}, + {"GBETSN_PGD0_PG_STS", BIT(5)}, + {"TBTLSX_PGD0_PG_STS", BIT(6)}, + {"THC0_PGD0_PG_STS", BIT(7)}, + {"THC1_PGD0_PG_STS", BIT(8)}, + {"PMC_PGD1_PG_STS", BIT(9)}, + {"GNA_PGD0_PG_STS", BIT(10)}, + {"ACE_PGD0_PG_STS", BIT(11)}, + {"ACE_PGD1_PG_STS", BIT(12)}, + {"ACE_PGD2_PG_STS", BIT(13)}, + {"ACE_PGD3_PG_STS", BIT(14)}, + {"ACE_PGD4_PG_STS", BIT(15)}, + {"ACE_PGD5_PG_STS", BIT(16)}, + {"ACE_PGD6_PG_STS", BIT(17)}, + {"ACE_PGD7_PG_STS", BIT(18)}, + {"ACE_PGD8_PG_STS", BIT(19)}, + {"FIA_PGS_PGD0_PG_STS", BIT(20)}, + {"FIACPCB_PGS_PGD0_PG_STS", BIT(21)}, + {"FUSEPMSB_PGD0_PG_STS", BIT(22)}, + {} +}; + +const struct pmc_bit_map mtl_socm_d3_status_0_map[] = { + {"LPSS_D3_STS", BIT(3)}, + {"XDCI_D3_STS", BIT(4)}, + {"XHCI_D3_STS", BIT(5)}, + {"SPA_D3_STS", BIT(12)}, + {"SPB_D3_STS", BIT(13)}, + {"SPC_D3_STS", BIT(14)}, + {"SPD_D3_STS", BIT(15)}, + {"ESPISPI_D3_STS", BIT(18)}, + {"SATA_D3_STS", BIT(20)}, + {"PSTH_D3_STS", BIT(21)}, + {"DMI_D3_STS", BIT(22)}, + {} +}; + +const struct pmc_bit_map mtl_socm_d3_status_1_map[] = { + {"GBETSN1_D3_STS", BIT(14)}, + {"GBE_D3_STS", BIT(19)}, + {"ITSS_D3_STS", BIT(23)}, + {"P2S_D3_STS", BIT(24)}, + {"CNVI_D3_STS", BIT(27)}, + {"UFSX2_D3_STS", BIT(28)}, + {} +}; + +const struct pmc_bit_map mtl_socm_d3_status_2_map[] = { + {"GNA_D3_STS", BIT(0)}, + {"CSMERTC_D3_STS", BIT(1)}, + {"SUSRAM_D3_STS", BIT(2)}, + {"CSE_D3_STS", BIT(4)}, + {"KVMCC_D3_STS", BIT(5)}, + {"USBR0_D3_STS", BIT(6)}, + {"ISH_D3_STS", BIT(7)}, + {"SMT1_D3_STS", BIT(8)}, + {"SMT2_D3_STS", BIT(9)}, + {"SMT3_D3_STS", BIT(10)}, + {"CLINK_D3_STS", BIT(14)}, + {"PTIO_D3_STS", BIT(16)}, + {"PMT_D3_STS", BIT(17)}, + {"SMS1_D3_STS", BIT(18)}, + {"SMS2_D3_STS", BIT(19)}, + {} +}; + +const struct pmc_bit_map mtl_socm_d3_status_3_map[] = { + {"ESE_D3_STS", BIT(2)}, + {"GBETSN_D3_STS", BIT(13)}, + {"THC0_D3_STS", BIT(14)}, + {"THC1_D3_STS", BIT(15)}, + {"ACE_D3_STS", BIT(23)}, + {} +}; + +const struct pmc_bit_map mtl_socm_vnn_req_status_0_map[] = { + {"LPSS_VNN_REQ_STS", BIT(3)}, + {"FIA_VNN_REQ_STS", BIT(17)}, + {"ESPISPI_VNN_REQ_STS", BIT(18)}, + {} +}; + +const struct pmc_bit_map mtl_socm_vnn_req_status_1_map[] = { + {"NPK_VNN_REQ_STS", BIT(4)}, + {"DFXAGG_VNN_REQ_STS", BIT(8)}, + {"EXI_VNN_REQ_STS", BIT(9)}, + {"P2D_VNN_REQ_STS", BIT(18)}, + {"GBE_VNN_REQ_STS", BIT(19)}, + {"SMB_VNN_REQ_STS", BIT(25)}, + {"LPC_VNN_REQ_STS", BIT(26)}, + {} +}; + +const struct pmc_bit_map mtl_socm_vnn_req_status_2_map[] = { + {"CSMERTC_VNN_REQ_STS", BIT(1)}, + {"CSE_VNN_REQ_STS", BIT(4)}, + {"ISH_VNN_REQ_STS", BIT(7)}, + {"SMT1_VNN_REQ_STS", BIT(8)}, + {"CLINK_VNN_REQ_STS", BIT(14)}, + {"SMS1_VNN_REQ_STS", BIT(18)}, + {"SMS2_VNN_REQ_STS", BIT(19)}, + {"GPIOCOM4_VNN_REQ_STS", BIT(20)}, + {"GPIOCOM3_VNN_REQ_STS", BIT(21)}, + {"GPIOCOM2_VNN_REQ_STS", BIT(22)}, + {"GPIOCOM1_VNN_REQ_STS", BIT(23)}, + {"GPIOCOM0_VNN_REQ_STS", BIT(24)}, + {} +}; + +const struct pmc_bit_map mtl_socm_vnn_req_status_3_map[] = { + {"ESE_VNN_REQ_STS", BIT(2)}, + {"DTS0_VNN_REQ_STS", BIT(7)}, + {"GPIOCOM5_VNN_REQ_STS", BIT(11)}, + {} +}; + +const struct pmc_bit_map mtl_socm_vnn_misc_status_map[] = { + {"CPU_C10_REQ_STS", BIT(0)}, + {"TS_OFF_REQ_STS", BIT(1)}, + {"PNDE_MET_REQ_STS", BIT(2)}, + {"PCIE_DEEP_PM_REQ_STS", BIT(3)}, + {"PMC_CLK_THROTTLE_EN_REQ_STS", BIT(4)}, + {"NPK_VNNAON_REQ_STS", BIT(5)}, + {"VNN_SOC_REQ_STS", BIT(6)}, + {"ISH_VNNAON_REQ_STS", BIT(7)}, + {"IOE_COND_MET_S02I2_0_REQ_STS", BIT(8)}, + {"IOE_COND_MET_S02I2_1_REQ_STS", BIT(9)}, + {"IOE_COND_MET_S02I2_2_REQ_STS", BIT(10)}, + {"PLT_GREATER_REQ_STS", BIT(11)}, + {"PCIE_CLKREQ_REQ_STS", BIT(12)}, + {"PMC_IDLE_FB_OCP_REQ_STS", BIT(13)}, + {"PM_SYNC_STATES_REQ_STS", BIT(14)}, + {"EA_REQ_STS", BIT(15)}, + {"MPHY_CORE_OFF_REQ_STS", BIT(16)}, + {"BRK_EV_EN_REQ_STS", BIT(17)}, + {"AUTO_DEMO_EN_REQ_STS", BIT(18)}, + {"ITSS_CLK_SRC_REQ_STS", BIT(19)}, + {"LPC_CLK_SRC_REQ_STS", BIT(20)}, + {"ARC_IDLE_REQ_STS", BIT(21)}, + {"MPHY_SUS_REQ_STS", BIT(22)}, + {"FIA_DEEP_PM_REQ_STS", BIT(23)}, + {"UXD_CONNECTED_REQ_STS", BIT(24)}, + {"ARC_INTERRUPT_WAKE_REQ_STS", BIT(25)}, + {"USB2_VNNAON_ACT_REQ_STS", BIT(26)}, + {"PRE_WAKE0_REQ_STS", BIT(27)}, + {"PRE_WAKE1_REQ_STS", BIT(28)}, + {"PRE_WAKE2_EN_REQ_STS", BIT(29)}, + {"WOV_REQ_STS", BIT(30)}, + {"CNVI_V1P05_REQ_STS", BIT(31)}, + {} +}; + +const struct pmc_bit_map mtl_socm_signal_status_map[] = { + {"LSX_Wake0_En_STS", BIT(0)}, + {"LSX_Wake0_Pol_STS", BIT(1)}, + {"LSX_Wake1_En_STS", BIT(2)}, + {"LSX_Wake1_Pol_STS", BIT(3)}, + {"LSX_Wake2_En_STS", BIT(4)}, + {"LSX_Wake2_Pol_STS", BIT(5)}, + {"LSX_Wake3_En_STS", BIT(6)}, + {"LSX_Wake3_Pol_STS", BIT(7)}, + {"LSX_Wake4_En_STS", BIT(8)}, + {"LSX_Wake4_Pol_STS", BIT(9)}, + {"LSX_Wake5_En_STS", BIT(10)}, + {"LSX_Wake5_Pol_STS", BIT(11)}, + {"LSX_Wake6_En_STS", BIT(12)}, + {"LSX_Wake6_Pol_STS", BIT(13)}, + {"LSX_Wake7_En_STS", BIT(14)}, + {"LSX_Wake7_Pol_STS", BIT(15)}, + {"LPSS_Wake0_En_STS", BIT(16)}, + {"LPSS_Wake0_Pol_STS", BIT(17)}, + {"LPSS_Wake1_En_STS", BIT(18)}, + {"LPSS_Wake1_Pol_STS", BIT(19)}, + {"Int_Timer_SS_Wake0_En_STS", BIT(20)}, + {"Int_Timer_SS_Wake0_Pol_STS", BIT(21)}, + {"Int_Timer_SS_Wake1_En_STS", BIT(22)}, + {"Int_Timer_SS_Wake1_Pol_STS", BIT(23)}, + {"Int_Timer_SS_Wake2_En_STS", BIT(24)}, + {"Int_Timer_SS_Wake2_Pol_STS", BIT(25)}, + {"Int_Timer_SS_Wake3_En_STS", BIT(26)}, + {"Int_Timer_SS_Wake3_Pol_STS", BIT(27)}, + {"Int_Timer_SS_Wake4_En_STS", BIT(28)}, + {"Int_Timer_SS_Wake4_Pol_STS", BIT(29)}, + {"Int_Timer_SS_Wake5_En_STS", BIT(30)}, + {"Int_Timer_SS_Wake5_Pol_STS", BIT(31)}, + {} +}; + +const struct pmc_bit_map *mtl_socm_lpm_maps[] = { + mtl_socm_clocksource_status_map, + mtl_socm_power_gating_status_0_map, + mtl_socm_power_gating_status_1_map, + mtl_socm_power_gating_status_2_map, + mtl_socm_d3_status_0_map, + mtl_socm_d3_status_1_map, + mtl_socm_d3_status_2_map, + mtl_socm_d3_status_3_map, + mtl_socm_vnn_req_status_0_map, + mtl_socm_vnn_req_status_1_map, + mtl_socm_vnn_req_status_2_map, + mtl_socm_vnn_req_status_3_map, + mtl_socm_vnn_misc_status_map, + mtl_socm_signal_status_map, + NULL +}; + +const struct pmc_reg_map mtl_socm_reg_map = { + .pfear_sts = ext_mtl_socm_pfear_map, .slp_s0_offset = CNP_PMC_SLP_S0_RES_COUNTER_OFFSET, .slp_s0_res_counter_step = TGL_PMC_SLP_S0_RES_COUNTER_STEP, - .ltr_show_sts = adl_ltr_show_map, + .ltr_show_sts = mtl_socm_ltr_show_map, .msr_sts = msr_map, .ltr_ignore_offset = CNP_PMC_LTR_IGNORE_OFFSET, - .regmap_length = CNP_PMC_MMIO_REG_LEN, + .regmap_length = MTL_SOC_PMC_MMIO_REG_LEN, .ppfear0_offset = CNP_PMC_HOST_PPFEAR0A, - .ppfear_buckets = ICL_PPFEAR_NUM_ENTRIES, + .ppfear_buckets = MTL_SOCM_PPFEAR_NUM_ENTRIES, .pm_cfg_offset = CNP_PMC_PM_CFG_OFFSET, .pm_read_disable_bit = CNP_PMC_READ_DISABLE_BIT, - .ltr_ignore_max = ADL_NUM_IP_IGN_ALLOWED, - .lpm_num_modes = ADL_LPM_NUM_MODES, .lpm_num_maps = ADL_LPM_NUM_MAPS, + .ltr_ignore_max = MTL_SOCM_NUM_IP_IGN_ALLOWED, .lpm_res_counter_step_x2 = TGL_PMC_LPM_RES_COUNTER_STEP_X2, .etr3_offset = ETR3_OFFSET, .lpm_sts_latch_en_offset = MTL_LPM_STATUS_LATCH_EN_OFFSET, .lpm_priority_offset = MTL_LPM_PRI_OFFSET, .lpm_en_offset = MTL_LPM_EN_OFFSET, .lpm_residency_offset = MTL_LPM_RESIDENCY_OFFSET, - .lpm_sts = adl_lpm_maps, + .lpm_sts = mtl_socm_lpm_maps, .lpm_status_offset = MTL_LPM_STATUS_OFFSET, .lpm_live_status_offset = MTL_LPM_LIVE_STATUS_OFFSET, }; -void mtl_core_configure(struct pmc_dev *pmcdev) -{ - /* Due to a hardware limitation, the GBE LTR blocks PC10 - * when a cable is attached. Tell the PMC to ignore it. - */ - dev_dbg(&pmcdev->pdev->dev, "ignoring GBE LTR\n"); - pmc_core_send_ltr_ignore(pmcdev, 3); -} +const struct pmc_bit_map mtl_ioep_pfear_map[] = { + {"PMC_0", BIT(0)}, + {"OPI", BIT(1)}, + {"TCSS", BIT(2)}, + {"RSVD3", BIT(3)}, + {"SPA", BIT(4)}, + {"SPB", BIT(5)}, + {"SPC", BIT(6)}, + {"IOE_D2D_3", BIT(7)}, + + {"RSVD8", BIT(0)}, + {"RSVD9", BIT(1)}, + {"SPE", BIT(2)}, + {"RSVD11", BIT(3)}, + {"RSVD12", BIT(4)}, + {"SPD", BIT(5)}, + {"ACE_7", BIT(6)}, + {"RSVD15", BIT(7)}, + + {"ACE_0", BIT(0)}, + {"FIACPCB_P", BIT(1)}, + {"P2S", BIT(2)}, + {"RSVD19", BIT(3)}, + {"ACE_8", BIT(4)}, + {"IOE_D2D_0", BIT(5)}, + {"FUSE", BIT(6)}, + {"RSVD23", BIT(7)}, + + {"FIACPCB_P5", BIT(0)}, + {"ACE_3", BIT(1)}, + {"RSF5", BIT(2)}, + {"ACE_2", BIT(3)}, + {"ACE_4", BIT(4)}, + {"RSVD29", BIT(5)}, + {"RSF10", BIT(6)}, + {"MPFPW5", BIT(7)}, + + {"PSF9", BIT(0)}, + {"MPFPW4", BIT(1)}, + {"RSVD34", BIT(2)}, + {"RSVD35", BIT(3)}, + {"RSVD36", BIT(4)}, + {"RSVD37", BIT(5)}, + {"RSVD38", BIT(6)}, + {"RSVD39", BIT(7)}, + + {"SBR0", BIT(0)}, + {"SBR1", BIT(1)}, + {"SBR2", BIT(2)}, + {"SBR3", BIT(3)}, + {"SBR4", BIT(4)}, + {"SBR5", BIT(5)}, + {"RSVD46", BIT(6)}, + {"RSVD47", BIT(7)}, + + {"RSVD48", BIT(0)}, + {"FIA_P5", BIT(1)}, + {"RSVD50", BIT(2)}, + {"RSVD51", BIT(3)}, + {"RSVD52", BIT(4)}, + {"RSVD53", BIT(5)}, + {"RSVD54", BIT(6)}, + {"ACE_1", BIT(7)}, + + {"RSVD56", BIT(0)}, + {"ACE_5", BIT(1)}, + {"RSVD58", BIT(2)}, + {"G5FPW1", BIT(3)}, + {"RSVD60", BIT(4)}, + {"ACE_6", BIT(5)}, + {"RSVD62", BIT(6)}, + {"GBETSN1", BIT(7)}, + + {"RSVD64", BIT(0)}, + {"FIA", BIT(1)}, + {"RSVD66", BIT(2)}, + {"FIA_P", BIT(3)}, + {"TAM", BIT(4)}, + {"GBETSN", BIT(5)}, + {"IOE_D2D_2", BIT(6)}, + {"IOE_D2D_1", BIT(7)}, + + {"SPF", BIT(0)}, + {"PMC_1", BIT(1)}, + {} +}; + +const struct pmc_bit_map *ext_mtl_ioep_pfear_map[] = { + mtl_ioep_pfear_map, + NULL +}; + +const struct pmc_bit_map mtl_ioep_ltr_show_map[] = { + {"SOUTHPORT_A", CNP_PMC_LTR_SPA}, + {"SOUTHPORT_B", CNP_PMC_LTR_SPB}, + {"SATA", CNP_PMC_LTR_SATA}, + {"GIGABIT_ETHERNET", CNP_PMC_LTR_GBE}, + {"XHCI", CNP_PMC_LTR_XHCI}, + {"SOUTHPORT_F", ADL_PMC_LTR_SPF}, + {"ME", CNP_PMC_LTR_ME}, + {"SATA1", CNP_PMC_LTR_EVA}, + {"SOUTHPORT_C", CNP_PMC_LTR_SPC}, + {"HD_AUDIO", CNP_PMC_LTR_AZ}, + {"CNV", CNP_PMC_LTR_CNV}, + {"LPSS", CNP_PMC_LTR_LPSS}, + {"SOUTHPORT_D", CNP_PMC_LTR_SPD}, + {"SOUTHPORT_E", CNP_PMC_LTR_SPE}, + {"SATA2", CNP_PMC_LTR_CAM}, + {"ESPI", CNP_PMC_LTR_ESPI}, + {"SCC", CNP_PMC_LTR_SCC}, + {"Reserved", MTL_PMC_LTR_RESERVED}, + {"UFSX2", CNP_PMC_LTR_UFSX2}, + {"EMMC", CNP_PMC_LTR_EMMC}, + {"WIGIG", ICL_PMC_LTR_WIGIG}, + {"THC0", TGL_PMC_LTR_THC0}, + {"THC1", TGL_PMC_LTR_THC1}, + {"SOUTHPORT_G", MTL_PMC_LTR_SPG}, + + /* Below two cannot be used for LTR_IGNORE */ + {"CURRENT_PLATFORM", CNP_PMC_LTR_CUR_PLT}, + {"AGGREGATED_SYSTEM", CNP_PMC_LTR_CUR_ASLT}, + {} +}; + +const struct pmc_bit_map mtl_ioep_clocksource_status_map[] = { + {"AON2_OFF_STS", BIT(0)}, + {"AON3_OFF_STS", BIT(1)}, + {"AON4_OFF_STS", BIT(2)}, + {"AON5_OFF_STS", BIT(3)}, + {"AON1_OFF_STS", BIT(4)}, + {"TBT_PLL_OFF_STS", BIT(5)}, + {"TMU_PLL_OFF_STS", BIT(6)}, + {"BCLK_PLL_OFF_STS", BIT(7)}, + {"D2D_PLL_OFF_STS", BIT(8)}, + {"AON3_SPL_OFF_STS", BIT(9)}, + {"MPFPW4_0_PLL_OFF_STS", BIT(12)}, + {"MPFPW5_0_PLL_OFF_STS", BIT(13)}, + {"G5FPW_0_PLL_OFF_STS", BIT(14)}, + {"G5FPW_1_PLL_OFF_STS", BIT(15)}, + {"XTAL_AGGR_OFF_STS", BIT(17)}, + {"FABRIC_PLL_OFF_STS", BIT(25)}, + {"SOC_PLL_OFF_STS", BIT(26)}, + {"REF_PLL_OFF_STS", BIT(28)}, + {"RTC_PLL_OFF_STS", BIT(31)}, + {} +}; + +const struct pmc_bit_map mtl_ioep_power_gating_status_0_map[] = { + {"PMC_PGD0_PG_STS", BIT(0)}, + {"DMI_PGD0_PG_STS", BIT(1)}, + {"TCSS_PGD0_PG_STS", BIT(2)}, + {"SPA_PGD0_PG_STS", BIT(4)}, + {"SPB_PGD0_PG_STS", BIT(5)}, + {"SPC_PGD0_PG_STS", BIT(6)}, + {"IOE_D2D_PGD3_PG_STS", BIT(7)}, + {"SPE_PGD0_PG_STS", BIT(10)}, + {"SPD_PGD0_PG_STS", BIT(13)}, + {"ACE_PGD7_PG_STS", BIT(14)}, + {"ACE_PGD0_PG_STS", BIT(16)}, + {"FIACPCB_P_PGD0_PG_STS", BIT(17)}, + {"P2S_PGD0_PG_STS", BIT(18)}, + {"ACE_PGD8_PG_STS", BIT(20)}, + {"IOE_D2D_PGD0_PG_STS", BIT(21)}, + {"FUSE_PGD0_PG_STS", BIT(22)}, + {"FIACPCB_P5_PGD0_PG_STS", BIT(24)}, + {"ACE_PGD3_PG_STS", BIT(25)}, + {"PSF5_PGD0_PG_STS", BIT(26)}, + {"ACE_PGD2_PG_STS", BIT(27)}, + {"ACE_PGD4_PG_STS", BIT(28)}, + {"PSF10_PGD0_PG_STS", BIT(30)}, + {"MPFPW5_PGD0_PG_STS", BIT(31)}, + {} +}; + +const struct pmc_bit_map mtl_ioep_power_gating_status_1_map[] = { + {"PSF9_PGD0_PG_STS", BIT(0)}, + {"MPFPW4_PGD0_PG_STS", BIT(1)}, + {"SBR0_PGD0_PG_STS", BIT(8)}, + {"SBR1_PGD0_PG_STS", BIT(9)}, + {"SBR2_PGD0_PG_STS", BIT(10)}, + {"SBR3_PGD0_PG_STS", BIT(11)}, + {"SBR4_PGD0_PG_STS", BIT(12)}, + {"SBR5_PGD0_PG_STS", BIT(13)}, + {"FIA_P5_PGD0_PG_STS", BIT(17)}, + {"ACE_PGD1_PGD0_PG_STS", BIT(23)}, + {"ACE_PGD5_PGD1_PG_STS", BIT(25)}, + {"G5FPW1_PGD0_PG_STS", BIT(27)}, + {"ACE_PGD6_PG_STS", BIT(29)}, + {"GBETSN1_PGD0_PG_STS", BIT(31)}, + {} +}; + +const struct pmc_bit_map mtl_ioep_power_gating_status_2_map[] = { + {"FIA_PGD0_PG_STS", BIT(1)}, + {"FIA_P_PGD0_PG_STS", BIT(3)}, + {"TAM_PGD0_PG_STS", BIT(4)}, + {"GBETSN_PGD0_PG_STS", BIT(5)}, + {"IOE_D2D_PGD2_PG_STS", BIT(6)}, + {"IOE_D2D_PGD1_PG_STS", BIT(7)}, + {"SPF_PGD0_PG_STS", BIT(8)}, + {"PMC_PGD1_PG_STS", BIT(9)}, + {} +}; + +const struct pmc_bit_map mtl_ioep_d3_status_0_map[] = { + {"SPF_D3_STS", BIT(0)}, + {"SPA_D3_STS", BIT(12)}, + {"SPB_D3_STS", BIT(13)}, + {"SPC_D3_STS", BIT(14)}, + {"SPD_D3_STS", BIT(15)}, + {"SPE_D3_STS", BIT(16)}, + {"DMI_D3_STS", BIT(22)}, + {} +}; + +const struct pmc_bit_map mtl_ioep_d3_status_1_map[] = { + {"GBETSN1_D3_STS", BIT(14)}, + {"P2S_D3_STS", BIT(24)}, + {} +}; + +const struct pmc_bit_map mtl_ioep_d3_status_2_map[] = { + {} +}; + +const struct pmc_bit_map mtl_ioep_d3_status_3_map[] = { + {"GBETSN_D3_STS", BIT(13)}, + {"ACE_D3_STS", BIT(23)}, + {} +}; + +const struct pmc_bit_map mtl_ioep_vnn_req_status_0_map[] = { + {"FIA_VNN_REQ_STS", BIT(17)}, + {} +}; + +const struct pmc_bit_map mtl_ioep_vnn_req_status_1_map[] = { + {"DFXAGG_VNN_REQ_STS", BIT(8)}, + {} +}; + +const struct pmc_bit_map mtl_ioep_vnn_req_status_2_map[] = { + {} +}; + +const struct pmc_bit_map mtl_ioep_vnn_req_status_3_map[] = { + {"DTS0_VNN_REQ_STS", BIT(7)}, + {"DISP_VNN_REQ_STS", BIT(19)}, + {} +}; + +const struct pmc_bit_map mtl_ioep_vnn_misc_status_map[] = { + {"CPU_C10_REQ_STS", BIT(0)}, + {"TS_OFF_REQ_STS", BIT(1)}, + {"PNDE_MET_REQ_STS", BIT(2)}, + {"PCIE_DEEP_PM_REQ_STS", BIT(3)}, + {"PMC_CLK_THROTTLE_EN_REQ_STS", BIT(4)}, + {"NPK_VNNAON_REQ_STS", BIT(5)}, + {"VNN_SOC_REQ_STS", BIT(6)}, + {"USB_DEVICE_ATTACHED_REQ_STS", BIT(8)}, + {"FIA_EXIT_REQ_STS", BIT(9)}, + {"USB2_SUS_PG_REQ_STS", BIT(10)}, + {"PLT_GREATER_REQ_STS", BIT(11)}, + {"PCIE_CLKREQ_REQ_STS", BIT(12)}, + {"PMC_IDLE_FB_OCP_REQ_STS", BIT(13)}, + {"PM_SYNC_STATES_REQ_STS", BIT(14)}, + {"EA_REQ_STS", BIT(15)}, + {"MPHY_CORE_OFF_REQ_STS", BIT(16)}, + {"BRK_EV_EN_REQ_STS", BIT(17)}, + {"AUTO_DEMO_EN_REQ_STS", BIT(18)}, + {"ITSS_CLK_SRC_REQ_STS", BIT(19)}, + {"LPC_CLK_SRC_REQ_STS", BIT(20)}, + {"ARC_IDLE_REQ_STS", BIT(21)}, + {"MPHY_SUS_REQ_STS", BIT(22)}, + {"FIA_DEEP_PM_REQ_STS", BIT(23)}, + {"UXD_CONNECTED_REQ_STS", BIT(24)}, + {"ARC_INTERRUPT_WAKE_REQ_STS", BIT(25)}, + {"USB2_VNNAON_ACT_REQ_STS", BIT(26)}, + {"PRE_WAKE0_REQ_STS", BIT(27)}, + {"PRE_WAKE1_REQ_STS", BIT(28)}, + {"PRE_WAKE2_EN_REQ_STS", BIT(29)}, + {"WOV_REQ_STS", BIT(30)}, + {"CNVI_V1P05_REQ_STS", BIT(31)}, + {} +}; + +const struct pmc_bit_map *mtl_ioep_lpm_maps[] = { + mtl_ioep_clocksource_status_map, + mtl_ioep_power_gating_status_0_map, + mtl_ioep_power_gating_status_1_map, + mtl_ioep_power_gating_status_2_map, + mtl_ioep_d3_status_0_map, + mtl_ioep_d3_status_1_map, + mtl_ioep_d3_status_2_map, + mtl_ioep_d3_status_3_map, + mtl_ioep_vnn_req_status_0_map, + mtl_ioep_vnn_req_status_1_map, + mtl_ioep_vnn_req_status_2_map, + mtl_ioep_vnn_req_status_3_map, + mtl_ioep_vnn_misc_status_map, + mtl_socm_signal_status_map, + NULL +}; + +const struct pmc_reg_map mtl_ioep_reg_map = { + .regmap_length = MTL_IOE_PMC_MMIO_REG_LEN, + .pfear_sts = ext_mtl_ioep_pfear_map, + .ppfear0_offset = CNP_PMC_HOST_PPFEAR0A, + .ppfear_buckets = MTL_IOE_PPFEAR_NUM_ENTRIES, + .lpm_status_offset = MTL_LPM_STATUS_OFFSET, + .lpm_live_status_offset = MTL_LPM_LIVE_STATUS_OFFSET, + .lpm_sts = mtl_ioep_lpm_maps, + .ltr_show_sts = mtl_ioep_ltr_show_map, + .ltr_ignore_offset = CNP_PMC_LTR_IGNORE_OFFSET, + .ltr_ignore_max = ADL_NUM_IP_IGN_ALLOWED, +}; + +const struct pmc_bit_map mtl_ioem_pfear_map[] = { + {"PMC_0", BIT(0)}, + {"OPI", BIT(1)}, + {"TCSS", BIT(2)}, + {"RSVD3", BIT(3)}, + {"SPA", BIT(4)}, + {"SPB", BIT(5)}, + {"SPC", BIT(6)}, + {"IOE_D2D_3", BIT(7)}, + + {"RSVD8", BIT(0)}, + {"RSVD9", BIT(1)}, + {"SPE", BIT(2)}, + {"RSVD11", BIT(3)}, + {"RSVD12", BIT(4)}, + {"SPD", BIT(5)}, + {"ACE_7", BIT(6)}, + {"RSVD15", BIT(7)}, + + {"ACE_0", BIT(0)}, + {"FIACPCB_P", BIT(1)}, + {"P2S", BIT(2)}, + {"RSVD19", BIT(3)}, + {"ACE_8", BIT(4)}, + {"IOE_D2D_0", BIT(5)}, + {"FUSE", BIT(6)}, + {"RSVD23", BIT(7)}, + + {"FIACPCB_P5", BIT(0)}, + {"ACE_3", BIT(1)}, + {"RSF5", BIT(2)}, + {"ACE_2", BIT(3)}, + {"ACE_4", BIT(4)}, + {"RSVD29", BIT(5)}, + {"RSF10", BIT(6)}, + {"MPFPW5", BIT(7)}, + + {"PSF9", BIT(0)}, + {"MPFPW4", BIT(1)}, + {"RSVD34", BIT(2)}, + {"RSVD35", BIT(3)}, + {"RSVD36", BIT(4)}, + {"RSVD37", BIT(5)}, + {"RSVD38", BIT(6)}, + {"RSVD39", BIT(7)}, + + {"SBR0", BIT(0)}, + {"SBR1", BIT(1)}, + {"SBR2", BIT(2)}, + {"SBR3", BIT(3)}, + {"SBR4", BIT(4)}, + {"RSVD45", BIT(5)}, + {"RSVD46", BIT(6)}, + {"RSVD47", BIT(7)}, + + {"RSVD48", BIT(0)}, + {"FIA_P5", BIT(1)}, + {"RSVD50", BIT(2)}, + {"RSVD51", BIT(3)}, + {"RSVD52", BIT(4)}, + {"RSVD53", BIT(5)}, + {"RSVD54", BIT(6)}, + {"ACE_1", BIT(7)}, + + {"RSVD56", BIT(0)}, + {"ACE_5", BIT(1)}, + {"RSVD58", BIT(2)}, + {"G5FPW1", BIT(3)}, + {"RSVD60", BIT(4)}, + {"ACE_6", BIT(5)}, + {"RSVD62", BIT(6)}, + {"GBETSN1", BIT(7)}, + + {"RSVD64", BIT(0)}, + {"FIA", BIT(1)}, + {"RSVD66", BIT(2)}, + {"FIA_P", BIT(3)}, + {"TAM", BIT(4)}, + {"GBETSN", BIT(5)}, + {"IOE_D2D_2", BIT(6)}, + {"IOE_D2D_1", BIT(7)}, + + {"SPF", BIT(0)}, + {"PMC_1", BIT(1)}, + {} +}; + +const struct pmc_bit_map *ext_mtl_ioem_pfear_map[] = { + mtl_ioem_pfear_map, + NULL +}; + +const struct pmc_bit_map mtl_ioem_power_gating_status_1_map[] = { + {"PSF9_PGD0_PG_STS", BIT(0)}, + {"MPFPW4_PGD0_PG_STS", BIT(1)}, + {"SBR0_PGD0_PG_STS", BIT(8)}, + {"SBR1_PGD0_PG_STS", BIT(9)}, + {"SBR2_PGD0_PG_STS", BIT(10)}, + {"SBR3_PGD0_PG_STS", BIT(11)}, + {"SBR4_PGD0_PG_STS", BIT(12)}, + {"FIA_P5_PGD0_PG_STS", BIT(17)}, + {"ACE_PGD1_PGD0_PG_STS", BIT(23)}, + {"ACE_PGD5_PGD1_PG_STS", BIT(25)}, + {"G5FPW1_PGD0_PG_STS", BIT(27)}, + {"ACE_PGD6_PG_STS", BIT(29)}, + {"GBETSN1_PGD0_PG_STS", BIT(31)}, + {} +}; + +const struct pmc_bit_map *mtl_ioem_lpm_maps[] = { + mtl_ioep_clocksource_status_map, + mtl_ioep_power_gating_status_0_map, + mtl_ioem_power_gating_status_1_map, + mtl_ioep_power_gating_status_2_map, + mtl_ioep_d3_status_0_map, + mtl_ioep_d3_status_1_map, + mtl_ioep_d3_status_2_map, + mtl_ioep_d3_status_3_map, + mtl_ioep_vnn_req_status_0_map, + mtl_ioep_vnn_req_status_1_map, + mtl_ioep_vnn_req_status_2_map, + mtl_ioep_vnn_req_status_3_map, + mtl_ioep_vnn_misc_status_map, + mtl_socm_signal_status_map, + NULL +}; + +const struct pmc_reg_map mtl_ioem_reg_map = { + .regmap_length = MTL_IOE_PMC_MMIO_REG_LEN, + .pfear_sts = ext_mtl_ioem_pfear_map, + .ppfear0_offset = CNP_PMC_HOST_PPFEAR0A, + .ppfear_buckets = MTL_IOE_PPFEAR_NUM_ENTRIES, + .lpm_status_offset = MTL_LPM_STATUS_OFFSET, + .lpm_live_status_offset = MTL_LPM_LIVE_STATUS_OFFSET, + .lpm_sts = mtl_ioem_lpm_maps, + .ltr_show_sts = mtl_ioep_ltr_show_map, + .ltr_ignore_offset = CNP_PMC_LTR_IGNORE_OFFSET, + .ltr_ignore_max = ADL_NUM_IP_IGN_ALLOWED, +}; + +#define PMC_DEVID_SOCM 0x7e7f +#define PMC_DEVID_IOEP 0x7ecf +#define PMC_DEVID_IOEM 0x7ebf +static struct pmc_info mtl_pmc_info_list[] = { + { + .devid = PMC_DEVID_SOCM, + .map = &mtl_socm_reg_map, + }, + { + .devid = PMC_DEVID_IOEP, + .map = &mtl_ioep_reg_map, + }, + { + .devid = PMC_DEVID_IOEM, + .map = &mtl_ioem_reg_map + }, + {} +}; #define MTL_GNA_PCI_DEV 0x7e4c #define MTL_IPU_PCI_DEV 0x7d19 @@ -68,16 +965,48 @@ static void mtl_set_device_d3(unsigned int device) } } -void mtl_core_init(struct pmc_dev *pmcdev) +/* + * Set power state of select devices that do not have drivers to D3 + * so that they do not block Package C entry. + */ +static void mtl_d3_fixup(void) { - pmcdev->map = &mtl_reg_map; - pmcdev->core_configure = mtl_core_configure; - - /* - * Set power state of select devices that do not have drivers to D3 - * so that they do not block Package C entry. - */ mtl_set_device_d3(MTL_GNA_PCI_DEV); mtl_set_device_d3(MTL_IPU_PCI_DEV); mtl_set_device_d3(MTL_VPU_PCI_DEV); } + +static int mtl_resume(struct pmc_dev *pmcdev) +{ + mtl_d3_fixup(); + return pmc_core_resume_common(pmcdev); +} + +int mtl_core_init(struct pmc_dev *pmcdev) +{ + struct pmc *pmc = pmcdev->pmcs[PMC_IDX_SOC]; + int ret = 0; + + mtl_d3_fixup(); + + pmcdev->resume = mtl_resume; + + pmcdev->regmap_list = mtl_pmc_info_list; + pmc_core_ssram_init(pmcdev); + + /* If regbase not assigned, set map and discover using legacy method */ + if (!pmc->regbase) { + pmc->map = &mtl_socm_reg_map; + ret = get_primary_reg_base(pmc); + if (ret) + return ret; + } + + /* Due to a hardware limitation, the GBE LTR blocks PC10 + * when a cable is attached. Tell the PMC to ignore it. + */ + dev_dbg(&pmcdev->pdev->dev, "ignoring GBE LTR\n"); + pmc_core_send_ltr_ignore(pmcdev, 3); + + return 0; +} diff --git a/drivers/platform/x86/intel/pmc/spt.c b/drivers/platform/x86/intel/pmc/spt.c index e16982236778ee9e814e2571ed9bf8590c7348c9..4b6f5cbda16c0acb7adc65f24a502872146df69c 100644 --- a/drivers/platform/x86/intel/pmc/spt.c +++ b/drivers/platform/x86/intel/pmc/spt.c @@ -134,7 +134,10 @@ const struct pmc_reg_map spt_reg_map = { .pm_vric1_offset = SPT_PMC_VRIC1_OFFSET, }; -void spt_core_init(struct pmc_dev *pmcdev) +int spt_core_init(struct pmc_dev *pmcdev) { - pmcdev->map = &spt_reg_map; + struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN]; + + pmc->map = &spt_reg_map; + return get_primary_reg_base(pmc); } diff --git a/drivers/platform/x86/intel/pmc/tgl.c b/drivers/platform/x86/intel/pmc/tgl.c index c245ada849d0ab3b15e12b3d84369f45c82a82b1..2449940102db4f68e3e09f0defc647016b60dc0d 100644 --- a/drivers/platform/x86/intel/pmc/tgl.c +++ b/drivers/platform/x86/intel/pmc/tgl.c @@ -208,7 +208,8 @@ const struct pmc_reg_map tgl_reg_map = { void pmc_core_get_tgl_lpm_reqs(struct platform_device *pdev) { struct pmc_dev *pmcdev = platform_get_drvdata(pdev); - const int num_maps = pmcdev->map->lpm_num_maps; + struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN]; + const int num_maps = pmc->map->lpm_num_maps; u32 lpm_size = LPM_MAX_NUM_MODES * num_maps * 4; union acpi_object *out_obj; struct acpi_device *adev; @@ -246,24 +247,28 @@ void pmc_core_get_tgl_lpm_reqs(struct platform_device *pdev) goto free_acpi_obj; memcpy(lpm_req_regs, addr, lpm_size); - pmcdev->lpm_req_regs = lpm_req_regs; + pmc->lpm_req_regs = lpm_req_regs; free_acpi_obj: ACPI_FREE(out_obj); } -void tgl_core_configure(struct pmc_dev *pmcdev) +int tgl_core_init(struct pmc_dev *pmcdev) { + struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN]; + int ret; + + pmc->map = &tgl_reg_map; + ret = get_primary_reg_base(pmc); + if (ret) + return ret; + pmc_core_get_tgl_lpm_reqs(pmcdev->pdev); /* Due to a hardware limitation, the GBE LTR blocks PC10 * when a cable is attached. Tell the PMC to ignore it. */ dev_dbg(&pmcdev->pdev->dev, "ignoring GBE LTR\n"); pmc_core_send_ltr_ignore(pmcdev, 3); -} -void tgl_core_init(struct pmc_dev *pmcdev) -{ - pmcdev->map = &tgl_reg_map; - pmcdev->core_configure = tgl_core_configure; + return 0; } 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 02fe360a59c7cf427c7293f5a0f3d89c78fe92ae..1f59ac55c5f7290ab0bc39bbbf237a8ced6a179d 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 @@ -829,6 +829,7 @@ void isst_if_cdev_unregister(int device_type) { isst_misc_unreg(); mutex_lock(&punit_misc_dev_open_lock); + punit_callbacks[device_type].def_ioctl = NULL; punit_callbacks[device_type].registered = 0; if (device_type == ISST_IF_DEV_MBOX) isst_delete_hash(); diff --git a/drivers/platform/x86/intel/speed_select_if/isst_tpmi_core.c b/drivers/platform/x86/intel/speed_select_if/isst_tpmi_core.c index 664d2ee60385a3eb52752699466f36b0578600f1..63faa2ea8327b2c7d64857ad47ddd31c43d022cd 100644 --- a/drivers/platform/x86/intel/speed_select_if/isst_tpmi_core.c +++ b/drivers/platform/x86/intel/speed_select_if/isst_tpmi_core.c @@ -1414,6 +1414,8 @@ int tpmi_sst_init(void) ret = isst_if_cdev_register(ISST_IF_DEV_TPMI, &cb); if (ret) kfree(isst_common.sst_inst); + else + ++isst_core_usage_count; init_done: mutex_unlock(&isst_tpmi_dev_lock); return ret; diff --git a/drivers/platform/x86/intel/tpmi.c b/drivers/platform/x86/intel/tpmi.c index a5227951decce90f3eaf95aedfa0383a1c2bf957..d1fd6e69401c2d81c9f0dfb9fb7734da8aa08cdb 100644 --- a/drivers/platform/x86/intel/tpmi.c +++ b/drivers/platform/x86/intel/tpmi.c @@ -222,7 +222,7 @@ static int tpmi_create_device(struct intel_tpmi_info *tpmi_info, snprintf(feature_id_name, sizeof(feature_id_name), "tpmi-%s", name); for (i = 0, tmp = res; i < pfs->pfs_header.num_entries; i++, tmp++) { - u64 entry_size_bytes = pfs->pfs_header.entry_size * 4; + u64 entry_size_bytes = pfs->pfs_header.entry_size * sizeof(u32); tmp->start = pfs->vsec_offset + entry_size_bytes * i; tmp->end = tmp->start + entry_size_bytes - 1; @@ -277,7 +277,7 @@ static int tpmi_process_info(struct intel_tpmi_info *tpmi_info, void __iomem *info_mem; info_mem = ioremap(pfs->vsec_offset + TPMI_INFO_BUS_INFO_OFFSET, - pfs->pfs_header.entry_size * 4 - TPMI_INFO_BUS_INFO_OFFSET); + pfs->pfs_header.entry_size * sizeof(u32) - TPMI_INFO_BUS_INFO_OFFSET); if (!info_mem) return -ENOMEM; @@ -308,6 +308,8 @@ static int tpmi_fetch_pfs_header(struct intel_tpmi_pm_feature *pfs, u64 start, i return 0; } +#define TPMI_CAP_OFFSET_UNIT 1024 + static int intel_vsec_tpmi_init(struct auxiliary_device *auxdev) { struct intel_vsec_device *vsec_dev = auxdev_to_ivdev(auxdev); @@ -354,9 +356,7 @@ static int intel_vsec_tpmi_init(struct auxiliary_device *auxdev) if (!pfs_start) pfs_start = res_start; - pfs->pfs_header.cap_offset *= 1024; - - pfs->vsec_offset = pfs_start + pfs->pfs_header.cap_offset; + pfs->vsec_offset = pfs_start + pfs->pfs_header.cap_offset * TPMI_CAP_OFFSET_UNIT; /* * Process TPMI_INFO to get PCI device to CPU package ID. diff --git a/drivers/platform/x86/intel/uncore-frequency/Kconfig b/drivers/platform/x86/intel/uncore-frequency/Kconfig index 21b209124916ac8f9a887073d49a77698a43e927..a56d55056927a8151807452e93f6cfa73f8825ca 100644 --- a/drivers/platform/x86/intel/uncore-frequency/Kconfig +++ b/drivers/platform/x86/intel/uncore-frequency/Kconfig @@ -6,9 +6,13 @@ menu "Intel Uncore Frequency Control" depends on X86_64 || COMPILE_TEST +config INTEL_UNCORE_FREQ_CONTROL_TPMI + tristate + config INTEL_UNCORE_FREQ_CONTROL tristate "Intel Uncore frequency control driver" depends on X86_64 + select INTEL_UNCORE_FREQ_CONTROL_TPMI if INTEL_TPMI help This driver allows control of Uncore frequency limits on supported server platforms. diff --git a/drivers/platform/x86/intel/uncore-frequency/Makefile b/drivers/platform/x86/intel/uncore-frequency/Makefile index e0f7968e82852b3cd7058fac20dbe9b2299c12fd..08ff57492b286d3b643620a6100c0c46fd0dbb6d 100644 --- a/drivers/platform/x86/intel/uncore-frequency/Makefile +++ b/drivers/platform/x86/intel/uncore-frequency/Makefile @@ -7,3 +7,5 @@ obj-$(CONFIG_INTEL_UNCORE_FREQ_CONTROL) += intel-uncore-frequency.o intel-uncore-frequency-y := uncore-frequency.o obj-$(CONFIG_INTEL_UNCORE_FREQ_CONTROL) += intel-uncore-frequency-common.o intel-uncore-frequency-common-y := uncore-frequency-common.o +obj-$(CONFIG_INTEL_UNCORE_FREQ_CONTROL_TPMI) += intel-uncore-frequency-tpmi.o +intel-uncore-frequency-tpmi-y := uncore-frequency-tpmi.o diff --git a/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-common.c b/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-common.c index 064f186ae81b30573695e91e34c4061416cdec66..1152deaa0078e9b07d3c6051e795e8a6914f762b 100644 --- a/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-common.c +++ b/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-common.c @@ -16,11 +16,34 @@ static struct kobject *uncore_root_kobj; /* uncore instance count */ static int uncore_instance_count; +static DEFINE_IDA(intel_uncore_ida); + /* callbacks for actual HW read/write */ static int (*uncore_read)(struct uncore_data *data, unsigned int *min, unsigned int *max); static int (*uncore_write)(struct uncore_data *data, unsigned int input, unsigned int min_max); static int (*uncore_read_freq)(struct uncore_data *data, unsigned int *freq); +static ssize_t show_domain_id(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct uncore_data *data = container_of(attr, struct uncore_data, domain_id_dev_attr); + + return sprintf(buf, "%u\n", data->domain_id); +} + +static ssize_t show_fabric_cluster_id(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct uncore_data *data = container_of(attr, struct uncore_data, fabric_cluster_id_dev_attr); + + return sprintf(buf, "%u\n", data->cluster_id); +} + +static ssize_t show_package_id(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct uncore_data *data = container_of(attr, struct uncore_data, package_id_dev_attr); + + return sprintf(buf, "%u\n", data->package_id); +} + static ssize_t show_min_max_freq_khz(struct uncore_data *data, char *buf, int min_max) { @@ -161,6 +184,15 @@ static int create_attr_group(struct uncore_data *data, char *name) init_attribute_ro(initial_max_freq_khz); init_attribute_root_ro(current_freq_khz); + if (data->domain_id != UNCORE_DOMAIN_ID_INVALID) { + init_attribute_root_ro(domain_id); + data->uncore_attrs[index++] = &data->domain_id_dev_attr.attr; + init_attribute_root_ro(fabric_cluster_id); + data->uncore_attrs[index++] = &data->fabric_cluster_id_dev_attr.attr; + init_attribute_root_ro(package_id); + data->uncore_attrs[index++] = &data->package_id_dev_attr.attr; + } + data->uncore_attrs[index++] = &data->max_freq_khz_dev_attr.attr; data->uncore_attrs[index++] = &data->min_freq_khz_dev_attr.attr; data->uncore_attrs[index++] = &data->initial_min_freq_khz_dev_attr.attr; @@ -191,12 +223,24 @@ int uncore_freq_add_entry(struct uncore_data *data, int cpu) goto uncore_unlock; } - sprintf(data->name, "package_%02d_die_%02d", data->package_id, data->die_id); + if (data->domain_id != UNCORE_DOMAIN_ID_INVALID) { + ret = ida_alloc(&intel_uncore_ida, GFP_KERNEL); + if (ret < 0) + goto uncore_unlock; + + data->instance_id = ret; + sprintf(data->name, "uncore%02d", ret); + } else { + sprintf(data->name, "package_%02d_die_%02d", data->package_id, data->die_id); + } uncore_read(data, &data->initial_min_freq_khz, &data->initial_max_freq_khz); ret = create_attr_group(data, data->name); - if (!ret) { + if (ret) { + if (data->domain_id != UNCORE_DOMAIN_ID_INVALID) + ida_free(&intel_uncore_ida, data->instance_id); + } else { data->control_cpu = cpu; data->valid = true; } @@ -214,6 +258,9 @@ void uncore_freq_remove_die_entry(struct uncore_data *data) delete_attr_group(data, data->name); data->control_cpu = -1; data->valid = false; + if (data->domain_id != UNCORE_DOMAIN_ID_INVALID) + ida_free(&intel_uncore_ida, data->instance_id); + mutex_unlock(&uncore_lock); } EXPORT_SYMBOL_NS_GPL(uncore_freq_remove_die_entry, INTEL_UNCORE_FREQUENCY); diff --git a/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-common.h b/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-common.h index f5dcfa2fb2857d5328c0acc565a7dbc4cc4362a9..7afb69977c7e8c80b0db3ba819799434e41ff60a 100644 --- a/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-common.h +++ b/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-common.h @@ -21,6 +21,9 @@ * @valid: Mark the data valid/invalid * @package_id: Package id for this instance * @die_id: Die id for this instance + * @domain_id: Power domain id for this instance + * @cluster_id: cluster id in a domain + * @instance_id: Unique instance id to append to directory name * @name: Sysfs entry name for this instance * @uncore_attr_group: Attribute group storage * @max_freq_khz_dev_attr: Storage for device attribute max_freq_khz @@ -28,6 +31,9 @@ * @initial_max_freq_khz_dev_attr: Storage for device attribute initial_max_freq_khz * @initial_min_freq_khz_dev_attr: Storage for device attribute initial_min_freq_khz * @current_freq_khz_dev_attr: Storage for device attribute current_freq_khz + * @domain_id_dev_attr: Storage for device attribute domain_id + * @fabric_cluster_id_dev_attr: Storage for device attribute fabric_cluster_id + * @package_id_dev_attr: Storage for device attribute package_id * @uncore_attrs: Attribute storage for group creation * * This structure is used to encapsulate all data related to uncore sysfs @@ -41,6 +47,9 @@ struct uncore_data { bool valid; int package_id; int die_id; + int domain_id; + int cluster_id; + int instance_id; char name[32]; struct attribute_group uncore_attr_group; @@ -49,9 +58,14 @@ struct uncore_data { struct device_attribute initial_max_freq_khz_dev_attr; struct device_attribute initial_min_freq_khz_dev_attr; struct device_attribute current_freq_khz_dev_attr; - struct attribute *uncore_attrs[6]; + struct device_attribute domain_id_dev_attr; + struct device_attribute fabric_cluster_id_dev_attr; + struct device_attribute package_id_dev_attr; + struct attribute *uncore_attrs[9]; }; +#define UNCORE_DOMAIN_ID_INVALID -1 + int uncore_freq_common_init(int (*read_control_freq)(struct uncore_data *data, unsigned int *min, unsigned int *max), int (*write_control_freq)(struct uncore_data *data, unsigned int input, unsigned int min_max), int (*uncore_read_freq)(struct uncore_data *data, unsigned int *freq)); diff --git a/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-tpmi.c b/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-tpmi.c new file mode 100644 index 0000000000000000000000000000000000000000..7d0a67f8b517a785284226889b3b63bdea1ba086 --- /dev/null +++ b/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-tpmi.c @@ -0,0 +1,413 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * uncore-frquency-tpmi: Uncore frequency scaling using TPMI + * + * Copyright (c) 2023, Intel Corporation. + * All Rights Reserved. + * + * The hardware interface to read/write is basically substitution of + * MSR 0x620 and 0x621. + * There are specific MMIO offset and bits to get/set minimum and + * maximum uncore ratio, similar to MSRs. + * The scope of the uncore MSRs was package scope. But TPMI allows + * new gen CPUs to have multiple uncore controls at uncore-cluster + * level. Each package can have multiple power domains which further + * can have multiple clusters. + * Here number of power domains = number of resources in this aux + * device. There are offsets and bits to discover number of clusters + * and offset for each cluster level controls. + * + */ + +#include +#include +#include +#include +#include +#include + +#include "uncore-frequency-common.h" + +#define UNCORE_HEADER_VERSION 1 +#define UNCORE_HEADER_INDEX 0 +#define UNCORE_FABRIC_CLUSTER_OFFSET 8 + +/* status + control + adv_ctl1 + adv_ctl2 */ +#define UNCORE_FABRIC_CLUSTER_SIZE (4 * 8) + +#define UNCORE_STATUS_INDEX 0 +#define UNCORE_CONTROL_INDEX 8 + +#define UNCORE_FREQ_KHZ_MULTIPLIER 100000 + +struct tpmi_uncore_struct; + +/* Information for each cluster */ +struct tpmi_uncore_cluster_info { + bool root_domain; + u8 __iomem *cluster_base; + struct uncore_data uncore_data; + struct tpmi_uncore_struct *uncore_root; +}; + +/* Information for each power domain */ +struct tpmi_uncore_power_domain_info { + u8 __iomem *uncore_base; + int ufs_header_ver; + int cluster_count; + struct tpmi_uncore_cluster_info *cluster_infos; +}; + +/* Information for all power domains in a package */ +struct tpmi_uncore_struct { + int power_domain_count; + int max_ratio; + int min_ratio; + struct tpmi_uncore_power_domain_info *pd_info; + struct tpmi_uncore_cluster_info root_cluster; +}; + +#define UNCORE_GENMASK_MIN_RATIO GENMASK_ULL(21, 15) +#define UNCORE_GENMASK_MAX_RATIO GENMASK_ULL(14, 8) +#define UNCORE_GENMASK_CURRENT_RATIO GENMASK_ULL(6, 0) + +/* Helper function to read MMIO offset for max/min control frequency */ +static void read_control_freq(struct tpmi_uncore_cluster_info *cluster_info, + unsigned int *min, unsigned int *max) +{ + u64 control; + + control = readq(cluster_info->cluster_base + UNCORE_CONTROL_INDEX); + *max = FIELD_GET(UNCORE_GENMASK_MAX_RATIO, control) * UNCORE_FREQ_KHZ_MULTIPLIER; + *min = FIELD_GET(UNCORE_GENMASK_MIN_RATIO, control) * UNCORE_FREQ_KHZ_MULTIPLIER; +} + +#define UNCORE_MAX_RATIO FIELD_MAX(UNCORE_GENMASK_MAX_RATIO) + +/* Callback for sysfs read for max/min frequencies. Called under mutex locks */ +static int uncore_read_control_freq(struct uncore_data *data, unsigned int *min, + unsigned int *max) +{ + struct tpmi_uncore_cluster_info *cluster_info; + + cluster_info = container_of(data, struct tpmi_uncore_cluster_info, uncore_data); + + if (cluster_info->root_domain) { + struct tpmi_uncore_struct *uncore_root = cluster_info->uncore_root; + int i, _min = 0, _max = 0; + + *min = UNCORE_MAX_RATIO * UNCORE_FREQ_KHZ_MULTIPLIER; + *max = 0; + + /* + * Get the max/min by looking at each cluster. Get the lowest + * min and highest max. + */ + for (i = 0; i < uncore_root->power_domain_count; ++i) { + int j; + + for (j = 0; j < uncore_root->pd_info[i].cluster_count; ++j) { + read_control_freq(&uncore_root->pd_info[i].cluster_infos[j], + &_min, &_max); + if (*min > _min) + *min = _min; + if (*max < _max) + *max = _max; + } + } + return 0; + } + + read_control_freq(cluster_info, min, max); + + return 0; +} + +/* Helper function to write MMIO offset for max/min control frequency */ +static void write_control_freq(struct tpmi_uncore_cluster_info *cluster_info, unsigned int input, + unsigned int min_max) +{ + u64 control; + + control = readq(cluster_info->cluster_base + UNCORE_CONTROL_INDEX); + + if (min_max) { + control &= ~UNCORE_GENMASK_MAX_RATIO; + control |= FIELD_PREP(UNCORE_GENMASK_MAX_RATIO, input); + } else { + control &= ~UNCORE_GENMASK_MIN_RATIO; + control |= FIELD_PREP(UNCORE_GENMASK_MIN_RATIO, input); + } + + writeq(control, (cluster_info->cluster_base + UNCORE_CONTROL_INDEX)); +} + +/* Callback for sysfs write for max/min frequencies. Called under mutex locks */ +static int uncore_write_control_freq(struct uncore_data *data, unsigned int input, + unsigned int min_max) +{ + struct tpmi_uncore_cluster_info *cluster_info; + struct tpmi_uncore_struct *uncore_root; + + input /= UNCORE_FREQ_KHZ_MULTIPLIER; + if (!input || input > UNCORE_MAX_RATIO) + return -EINVAL; + + cluster_info = container_of(data, struct tpmi_uncore_cluster_info, uncore_data); + uncore_root = cluster_info->uncore_root; + + /* Update each cluster in a package */ + if (cluster_info->root_domain) { + struct tpmi_uncore_struct *uncore_root = cluster_info->uncore_root; + int i; + + for (i = 0; i < uncore_root->power_domain_count; ++i) { + int j; + + for (j = 0; j < uncore_root->pd_info[i].cluster_count; ++j) + write_control_freq(&uncore_root->pd_info[i].cluster_infos[j], + input, min_max); + } + + if (min_max) + uncore_root->max_ratio = input; + else + uncore_root->min_ratio = input; + + return 0; + } + + if (min_max && uncore_root->max_ratio && uncore_root->max_ratio < input) + return -EINVAL; + + if (!min_max && uncore_root->min_ratio && uncore_root->min_ratio > input) + return -EINVAL; + + write_control_freq(cluster_info, input, min_max); + + return 0; +} + +/* Callback for sysfs read for the current uncore frequency. Called under mutex locks */ +static int uncore_read_freq(struct uncore_data *data, unsigned int *freq) +{ + struct tpmi_uncore_cluster_info *cluster_info; + u64 status; + + cluster_info = container_of(data, struct tpmi_uncore_cluster_info, uncore_data); + if (cluster_info->root_domain) + return -ENODATA; + + status = readq((u8 __iomem *)cluster_info->cluster_base + UNCORE_STATUS_INDEX); + *freq = FIELD_GET(UNCORE_GENMASK_CURRENT_RATIO, status) * UNCORE_FREQ_KHZ_MULTIPLIER; + + return 0; +} + +static void remove_cluster_entries(struct tpmi_uncore_struct *tpmi_uncore) +{ + int i; + + for (i = 0; i < tpmi_uncore->power_domain_count; ++i) { + struct tpmi_uncore_power_domain_info *pd_info; + int j; + + pd_info = &tpmi_uncore->pd_info[i]; + if (!pd_info->uncore_base) + continue; + + for (j = 0; j < pd_info->cluster_count; ++j) { + struct tpmi_uncore_cluster_info *cluster_info; + + cluster_info = &pd_info->cluster_infos[j]; + uncore_freq_remove_die_entry(&cluster_info->uncore_data); + } + } +} + +#define UNCORE_VERSION_MASK GENMASK_ULL(7, 0) +#define UNCORE_LOCAL_FABRIC_CLUSTER_ID_MASK GENMASK_ULL(15, 8) +#define UNCORE_CLUSTER_OFF_MASK GENMASK_ULL(7, 0) +#define UNCORE_MAX_CLUSTER_PER_DOMAIN 8 + +static int uncore_probe(struct auxiliary_device *auxdev, const struct auxiliary_device_id *id) +{ + struct intel_tpmi_plat_info *plat_info; + struct tpmi_uncore_struct *tpmi_uncore; + int ret, i, pkg = 0; + int num_resources; + + /* Get number of power domains, which is equal to number of resources */ + num_resources = tpmi_get_resource_count(auxdev); + if (!num_resources) + return -EINVAL; + + /* Register callbacks to uncore core */ + ret = uncore_freq_common_init(uncore_read_control_freq, uncore_write_control_freq, + uncore_read_freq); + if (ret) + return ret; + + /* Allocate uncore instance per package */ + tpmi_uncore = devm_kzalloc(&auxdev->dev, sizeof(*tpmi_uncore), GFP_KERNEL); + if (!tpmi_uncore) { + ret = -ENOMEM; + goto err_rem_common; + } + + /* Allocate memory for all power domains in a package */ + tpmi_uncore->pd_info = devm_kcalloc(&auxdev->dev, num_resources, + sizeof(*tpmi_uncore->pd_info), + GFP_KERNEL); + if (!tpmi_uncore->pd_info) { + ret = -ENOMEM; + goto err_rem_common; + } + + tpmi_uncore->power_domain_count = num_resources; + + /* Get the package ID from the TPMI core */ + plat_info = tpmi_get_platform_data(auxdev); + if (plat_info) + pkg = plat_info->package_id; + else + dev_info(&auxdev->dev, "Platform information is NULL\n"); + + for (i = 0; i < num_resources; ++i) { + struct tpmi_uncore_power_domain_info *pd_info; + struct resource *res; + u64 cluster_offset; + u8 cluster_mask; + int mask, j; + u64 header; + + res = tpmi_get_resource_at_index(auxdev, i); + if (!res) + continue; + + pd_info = &tpmi_uncore->pd_info[i]; + + pd_info->uncore_base = devm_ioremap_resource(&auxdev->dev, res); + if (IS_ERR(pd_info->uncore_base)) { + ret = PTR_ERR(pd_info->uncore_base); + /* + * Set to NULL so that clean up can still remove other + * entries already created if any by + * remove_cluster_entries() + */ + pd_info->uncore_base = NULL; + goto remove_clusters; + } + + /* Check for version and skip this resource if there is mismatch */ + header = readq(pd_info->uncore_base); + pd_info->ufs_header_ver = header & UNCORE_VERSION_MASK; + if (pd_info->ufs_header_ver != UNCORE_HEADER_VERSION) { + dev_info(&auxdev->dev, "Uncore: Unsupported version:%d\n", + pd_info->ufs_header_ver); + continue; + } + + /* Get Cluster ID Mask */ + cluster_mask = FIELD_GET(UNCORE_LOCAL_FABRIC_CLUSTER_ID_MASK, header); + if (!cluster_mask) { + dev_info(&auxdev->dev, "Uncore: Invalid cluster mask:%x\n", cluster_mask); + continue; + } + + /* Find out number of clusters in this resource */ + pd_info->cluster_count = hweight8(cluster_mask); + + pd_info->cluster_infos = devm_kcalloc(&auxdev->dev, pd_info->cluster_count, + sizeof(struct tpmi_uncore_cluster_info), + GFP_KERNEL); + if (!pd_info->cluster_infos) { + ret = -ENOMEM; + goto remove_clusters; + } + /* + * Each byte in the register point to status and control + * registers belonging to cluster id 0-8. + */ + cluster_offset = readq(pd_info->uncore_base + + UNCORE_FABRIC_CLUSTER_OFFSET); + + for (j = 0; j < pd_info->cluster_count; ++j) { + struct tpmi_uncore_cluster_info *cluster_info; + + /* Get the offset for this cluster */ + mask = (cluster_offset & UNCORE_CLUSTER_OFF_MASK); + /* Offset in QWORD, so change to bytes */ + mask <<= 3; + + cluster_info = &pd_info->cluster_infos[j]; + + cluster_info->cluster_base = pd_info->uncore_base + mask; + + cluster_info->uncore_data.package_id = pkg; + /* There are no dies like Cascade Lake */ + cluster_info->uncore_data.die_id = 0; + cluster_info->uncore_data.domain_id = i; + cluster_info->uncore_data.cluster_id = j; + + cluster_info->uncore_root = tpmi_uncore; + + ret = uncore_freq_add_entry(&cluster_info->uncore_data, 0); + if (ret) { + cluster_info->cluster_base = NULL; + goto remove_clusters; + } + /* Point to next cluster offset */ + cluster_offset >>= UNCORE_MAX_CLUSTER_PER_DOMAIN; + } + } + + auxiliary_set_drvdata(auxdev, tpmi_uncore); + + tpmi_uncore->root_cluster.root_domain = true; + tpmi_uncore->root_cluster.uncore_root = tpmi_uncore; + + tpmi_uncore->root_cluster.uncore_data.package_id = pkg; + tpmi_uncore->root_cluster.uncore_data.domain_id = UNCORE_DOMAIN_ID_INVALID; + ret = uncore_freq_add_entry(&tpmi_uncore->root_cluster.uncore_data, 0); + if (ret) + goto remove_clusters; + + return 0; + +remove_clusters: + remove_cluster_entries(tpmi_uncore); +err_rem_common: + uncore_freq_common_exit(); + + return ret; +} + +static void uncore_remove(struct auxiliary_device *auxdev) +{ + struct tpmi_uncore_struct *tpmi_uncore = auxiliary_get_drvdata(auxdev); + + uncore_freq_remove_die_entry(&tpmi_uncore->root_cluster.uncore_data); + remove_cluster_entries(tpmi_uncore); + + uncore_freq_common_exit(); +} + +static const struct auxiliary_device_id intel_uncore_id_table[] = { + { .name = "intel_vsec.tpmi-uncore" }, + {} +}; +MODULE_DEVICE_TABLE(auxiliary, intel_uncore_id_table); + +static struct auxiliary_driver intel_uncore_aux_driver = { + .id_table = intel_uncore_id_table, + .remove = uncore_remove, + .probe = uncore_probe, +}; + +module_auxiliary_driver(intel_uncore_aux_driver); + +MODULE_IMPORT_NS(INTEL_TPMI); +MODULE_IMPORT_NS(INTEL_UNCORE_FREQUENCY); +MODULE_DESCRIPTION("Intel TPMI UFS Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/platform/x86/intel/uncore-frequency/uncore-frequency.c b/drivers/platform/x86/intel/uncore-frequency/uncore-frequency.c index 32e2515ee366e141b2cb21b4ba23777c31e207ef..a3b25253b6fdebe0e3d29f9af3ac95bab7cf9915 100644 --- a/drivers/platform/x86/intel/uncore-frequency/uncore-frequency.c +++ b/drivers/platform/x86/intel/uncore-frequency/uncore-frequency.c @@ -136,6 +136,7 @@ static int uncore_event_cpu_online(unsigned int cpu) data->package_id = topology_physical_package_id(cpu); data->die_id = topology_die_id(cpu); + data->domain_id = UNCORE_DOMAIN_ID_INVALID; return uncore_freq_add_entry(data, cpu); } diff --git a/drivers/platform/x86/lenovo-yogabook-wmi.c b/drivers/platform/x86/lenovo-yogabook-wmi.c deleted file mode 100644 index 5f4bd1eec38a9b3a21e5cec255ecdc09c3ac4512..0000000000000000000000000000000000000000 --- a/drivers/platform/x86/lenovo-yogabook-wmi.c +++ /dev/null @@ -1,408 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* WMI driver for Lenovo Yoga Book YB1-X90* / -X91* tablets */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define YB_MBTN_EVENT_GUID "243FEC1D-1963-41C1-8100-06A9D82A94B4" -#define YB_MBTN_METHOD_GUID "742B0CA1-0B20-404B-9CAA-AEFCABF30CE0" - -#define YB_PAD_ENABLE 1 -#define YB_PAD_DISABLE 2 -#define YB_LIGHTUP_BTN 3 - -#define YB_KBD_BL_DEFAULT 128 - -/* flags */ -enum { - YB_KBD_IS_ON, - YB_DIGITIZER_IS_ON, - YB_DIGITIZER_MODE, - YB_TABLET_MODE, - YB_SUSPENDED, -}; - -struct yogabook_wmi { - struct wmi_device *wdev; - struct acpi_device *kbd_adev; - struct acpi_device *dig_adev; - struct device *kbd_dev; - struct device *dig_dev; - struct gpio_desc *backside_hall_gpio; - int backside_hall_irq; - struct work_struct work; - struct led_classdev kbd_bl_led; - unsigned long flags; - uint8_t brightness; -}; - -static int yogabook_wmi_do_action(struct wmi_device *wdev, int action) -{ - struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; - struct acpi_buffer input; - acpi_status status; - u32 dummy_arg = 0; - - dev_dbg(&wdev->dev, "Do action: %d\n", action); - - input.pointer = &dummy_arg; - input.length = sizeof(dummy_arg); - - status = wmi_evaluate_method(YB_MBTN_METHOD_GUID, 0, action, &input, - &output); - if (ACPI_FAILURE(status)) { - dev_err(&wdev->dev, "Calling WMI method failure: 0x%x\n", - status); - return status; - } - - kfree(output.pointer); - - return 0; -} - -/* - * To control keyboard backlight, call the method KBLC() of the TCS1 ACPI - * device (Goodix touchpad acts as virtual sensor keyboard). - */ -static int yogabook_wmi_set_kbd_backlight(struct wmi_device *wdev, - uint8_t level) -{ - struct yogabook_wmi *data = dev_get_drvdata(&wdev->dev); - struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; - struct acpi_object_list input; - union acpi_object param; - acpi_status status; - - if (data->kbd_adev->power.state != ACPI_STATE_D0) { - dev_warn(&wdev->dev, "keyboard touchscreen not in D0, cannot set brightness\n"); - return -ENXIO; - } - - dev_dbg(&wdev->dev, "Set KBLC level to %u\n", level); - - input.count = 1; - input.pointer = ¶m; - - param.type = ACPI_TYPE_INTEGER; - param.integer.value = 255 - level; - - status = acpi_evaluate_object(acpi_device_handle(data->kbd_adev), "KBLC", - &input, &output); - if (ACPI_FAILURE(status)) { - dev_err(&wdev->dev, "Failed to call KBLC method: 0x%x\n", status); - return status; - } - - kfree(output.pointer); - return 0; -} - -static void yogabook_wmi_work(struct work_struct *work) -{ - struct yogabook_wmi *data = container_of(work, struct yogabook_wmi, work); - struct device *dev = &data->wdev->dev; - bool kbd_on, digitizer_on; - int r; - - if (test_bit(YB_SUSPENDED, &data->flags)) - return; - - if (test_bit(YB_TABLET_MODE, &data->flags)) { - kbd_on = false; - digitizer_on = false; - } else if (test_bit(YB_DIGITIZER_MODE, &data->flags)) { - digitizer_on = true; - kbd_on = false; - } else { - kbd_on = true; - digitizer_on = false; - } - - if (!kbd_on && test_bit(YB_KBD_IS_ON, &data->flags)) { - /* - * Must be done before releasing the keyboard touchscreen driver, - * so that the keyboard touchscreen dev is still in D0. - */ - yogabook_wmi_set_kbd_backlight(data->wdev, 0); - device_release_driver(data->kbd_dev); - clear_bit(YB_KBD_IS_ON, &data->flags); - } - - if (!digitizer_on && test_bit(YB_DIGITIZER_IS_ON, &data->flags)) { - yogabook_wmi_do_action(data->wdev, YB_PAD_DISABLE); - device_release_driver(data->dig_dev); - clear_bit(YB_DIGITIZER_IS_ON, &data->flags); - } - - if (kbd_on && !test_bit(YB_KBD_IS_ON, &data->flags)) { - r = device_reprobe(data->kbd_dev); - if (r) - dev_warn(dev, "Reprobe of keyboard touchscreen failed: %d\n", r); - - yogabook_wmi_set_kbd_backlight(data->wdev, data->brightness); - set_bit(YB_KBD_IS_ON, &data->flags); - } - - if (digitizer_on && !test_bit(YB_DIGITIZER_IS_ON, &data->flags)) { - r = device_reprobe(data->dig_dev); - if (r) - dev_warn(dev, "Reprobe of digitizer failed: %d\n", r); - - yogabook_wmi_do_action(data->wdev, YB_PAD_ENABLE); - set_bit(YB_DIGITIZER_IS_ON, &data->flags); - } -} - -static void yogabook_wmi_notify(struct wmi_device *wdev, union acpi_object *dummy) -{ - struct yogabook_wmi *data = dev_get_drvdata(&wdev->dev); - - if (test_bit(YB_SUSPENDED, &data->flags)) - return; - - if (test_bit(YB_DIGITIZER_MODE, &data->flags)) - clear_bit(YB_DIGITIZER_MODE, &data->flags); - else - set_bit(YB_DIGITIZER_MODE, &data->flags); - - /* - * We are called from the ACPI core and the driver [un]binding which is - * done also needs ACPI functions, use a workqueue to avoid deadlocking. - */ - schedule_work(&data->work); -} - -static irqreturn_t yogabook_backside_hall_irq(int irq, void *_data) -{ - struct yogabook_wmi *data = _data; - - if (gpiod_get_value(data->backside_hall_gpio)) - set_bit(YB_TABLET_MODE, &data->flags); - else - clear_bit(YB_TABLET_MODE, &data->flags); - - schedule_work(&data->work); - - return IRQ_HANDLED; -} - -static enum led_brightness kbd_brightness_get(struct led_classdev *cdev) -{ - struct yogabook_wmi *data = - container_of(cdev, struct yogabook_wmi, kbd_bl_led); - - return data->brightness; -} - -static int kbd_brightness_set(struct led_classdev *cdev, - enum led_brightness value) -{ - struct yogabook_wmi *data = - container_of(cdev, struct yogabook_wmi, kbd_bl_led); - struct wmi_device *wdev = data->wdev; - - if ((value < 0) || (value > 255)) - return -EINVAL; - - data->brightness = value; - - if (data->kbd_adev->power.state != ACPI_STATE_D0) - return 0; - - return yogabook_wmi_set_kbd_backlight(wdev, data->brightness); -} - -static struct gpiod_lookup_table yogabook_wmi_gpios = { - .dev_id = "243FEC1D-1963-41C1-8100-06A9D82A94B4", - .table = { - GPIO_LOOKUP("INT33FF:02", 18, "backside_hall_sw", GPIO_ACTIVE_LOW), - {} - }, -}; - -static void yogabook_wmi_rm_gpio_lookup(void *unused) -{ - gpiod_remove_lookup_table(&yogabook_wmi_gpios); -} - -static int yogabook_wmi_probe(struct wmi_device *wdev, const void *context) -{ - struct yogabook_wmi *data; - int r; - - data = devm_kzalloc(&wdev->dev, sizeof(struct yogabook_wmi), GFP_KERNEL); - if (data == NULL) - return -ENOMEM; - - dev_set_drvdata(&wdev->dev, data); - - data->wdev = wdev; - data->brightness = YB_KBD_BL_DEFAULT; - set_bit(YB_KBD_IS_ON, &data->flags); - set_bit(YB_DIGITIZER_IS_ON, &data->flags); - - r = devm_work_autocancel(&wdev->dev, &data->work, yogabook_wmi_work); - if (r) - return r; - - data->kbd_adev = acpi_dev_get_first_match_dev("GDIX1001", NULL, -1); - if (!data->kbd_adev) { - dev_err(&wdev->dev, "Cannot find the touchpad device in ACPI tables\n"); - return -ENODEV; - } - - data->dig_adev = acpi_dev_get_first_match_dev("WCOM0019", NULL, -1); - if (!data->dig_adev) { - dev_err(&wdev->dev, "Cannot find the digitizer device in ACPI tables\n"); - r = -ENODEV; - goto error_put_devs; - } - - data->kbd_dev = get_device(acpi_get_first_physical_node(data->kbd_adev)); - if (!data->kbd_dev || !data->kbd_dev->driver) { - r = -EPROBE_DEFER; - goto error_put_devs; - } - - data->dig_dev = get_device(acpi_get_first_physical_node(data->dig_adev)); - if (!data->dig_dev || !data->dig_dev->driver) { - r = -EPROBE_DEFER; - goto error_put_devs; - } - - gpiod_add_lookup_table(&yogabook_wmi_gpios); - - r = devm_add_action_or_reset(&wdev->dev, yogabook_wmi_rm_gpio_lookup, NULL); - if (r) - goto error_put_devs; - - data->backside_hall_gpio = - devm_gpiod_get(&wdev->dev, "backside_hall_sw", GPIOD_IN); - if (IS_ERR(data->backside_hall_gpio)) { - r = PTR_ERR(data->backside_hall_gpio); - dev_err_probe(&wdev->dev, r, "Getting backside_hall_sw GPIO\n"); - goto error_put_devs; - } - - r = gpiod_to_irq(data->backside_hall_gpio); - if (r < 0) { - dev_err_probe(&wdev->dev, r, "Getting backside_hall_sw IRQ\n"); - goto error_put_devs; - } - data->backside_hall_irq = r; - - r = devm_request_irq(&wdev->dev, data->backside_hall_irq, - yogabook_backside_hall_irq, - IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, - "backside_hall_sw", data); - if (r) { - dev_err_probe(&wdev->dev, r, "Requesting backside_hall_sw IRQ\n"); - goto error_put_devs; - } - - schedule_work(&data->work); - - data->kbd_bl_led.name = "ybwmi::kbd_backlight"; - data->kbd_bl_led.brightness_set_blocking = kbd_brightness_set; - data->kbd_bl_led.brightness_get = kbd_brightness_get; - data->kbd_bl_led.max_brightness = 255; - - r = devm_led_classdev_register(&wdev->dev, &data->kbd_bl_led); - if (r < 0) { - dev_err_probe(&wdev->dev, r, "Registering backlight LED device\n"); - goto error_put_devs; - } - - return 0; - -error_put_devs: - put_device(data->dig_dev); - put_device(data->kbd_dev); - acpi_dev_put(data->dig_adev); - acpi_dev_put(data->kbd_adev); - return r; -} - -static void yogabook_wmi_remove(struct wmi_device *wdev) -{ - struct yogabook_wmi *data = dev_get_drvdata(&wdev->dev); - - put_device(data->dig_dev); - put_device(data->kbd_dev); - acpi_dev_put(data->dig_adev); - acpi_dev_put(data->kbd_adev); -} - -static int __maybe_unused yogabook_wmi_suspend(struct device *dev) -{ - struct wmi_device *wdev = container_of(dev, struct wmi_device, dev); - struct yogabook_wmi *data = dev_get_drvdata(dev); - - set_bit(YB_SUSPENDED, &data->flags); - - flush_work(&data->work); - - /* Turn off the pen button at sleep */ - if (test_bit(YB_DIGITIZER_IS_ON, &data->flags)) - yogabook_wmi_do_action(wdev, YB_PAD_DISABLE); - - return 0; -} - -static int __maybe_unused yogabook_wmi_resume(struct device *dev) -{ - struct wmi_device *wdev = container_of(dev, struct wmi_device, dev); - struct yogabook_wmi *data = dev_get_drvdata(dev); - - if (test_bit(YB_KBD_IS_ON, &data->flags)) { - /* Ensure keyboard touchpad is on before we call KBLC() */ - acpi_device_set_power(data->kbd_adev, ACPI_STATE_D0); - yogabook_wmi_set_kbd_backlight(wdev, data->brightness); - } - - if (test_bit(YB_DIGITIZER_IS_ON, &data->flags)) - yogabook_wmi_do_action(wdev, YB_PAD_ENABLE); - - clear_bit(YB_SUSPENDED, &data->flags); - - /* Check for YB_TABLET_MODE changes made during suspend */ - schedule_work(&data->work); - - return 0; -} - -static const struct wmi_device_id yogabook_wmi_id_table[] = { - { - .guid_string = YB_MBTN_EVENT_GUID, - }, - { } /* Terminating entry */ -}; - -static SIMPLE_DEV_PM_OPS(yogabook_wmi_pm_ops, - yogabook_wmi_suspend, yogabook_wmi_resume); - -static struct wmi_driver yogabook_wmi_driver = { - .driver = { - .name = "yogabook-wmi", - .pm = &yogabook_wmi_pm_ops, - }, - .no_notify_data = true, - .id_table = yogabook_wmi_id_table, - .probe = yogabook_wmi_probe, - .remove = yogabook_wmi_remove, - .notify = yogabook_wmi_notify, -}; -module_wmi_driver(yogabook_wmi_driver); - -MODULE_DEVICE_TABLE(wmi, yogabook_wmi_id_table); -MODULE_AUTHOR("Yauhen Kharuzhy"); -MODULE_DESCRIPTION("Lenovo Yoga Book WMI driver"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/platform/x86/lenovo-yogabook.c b/drivers/platform/x86/lenovo-yogabook.c new file mode 100644 index 0000000000000000000000000000000000000000..b8d0239192cbf58d50a233a7606cfdb1a8907d24 --- /dev/null +++ b/drivers/platform/x86/lenovo-yogabook.c @@ -0,0 +1,573 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Platform driver for Lenovo Yoga Book YB1-X90F/L tablets (Android model) + * WMI driver for Lenovo Yoga Book YB1-X91F/L tablets (Windows model) + * + * The keyboard half of the YB1 models can function as both a capacitive + * touch keyboard or as a Wacom digitizer, but not at the same time. + * + * This driver takes care of switching between the 2 functions. + * + * Copyright 2023 Hans de Goede + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define YB_MBTN_EVENT_GUID "243FEC1D-1963-41C1-8100-06A9D82A94B4" + +#define YB_KBD_BL_DEFAULT 128 +#define YB_KBD_BL_MAX 255 +#define YB_KBD_BL_PWM_PERIOD 13333 + +#define YB_PDEV_NAME "yogabook-touch-kbd-digitizer-switch" + +/* flags */ +enum { + YB_KBD_IS_ON, + YB_DIGITIZER_IS_ON, + YB_DIGITIZER_MODE, + YB_TABLET_MODE, + YB_SUSPENDED, +}; + +struct yogabook_data { + struct device *dev; + struct acpi_device *kbd_adev; + struct acpi_device *dig_adev; + struct device *kbd_dev; + struct device *dig_dev; + struct led_classdev *pen_led; + struct gpio_desc *pen_touch_event; + struct gpio_desc *kbd_bl_led_enable; + struct gpio_desc *backside_hall_gpio; + struct pwm_device *kbd_bl_pwm; + int (*set_kbd_backlight)(struct yogabook_data *data, uint8_t level); + int pen_touch_irq; + int backside_hall_irq; + struct work_struct work; + struct led_classdev kbd_bl_led; + unsigned long flags; + uint8_t brightness; +}; + +static void yogabook_work(struct work_struct *work) +{ + struct yogabook_data *data = container_of(work, struct yogabook_data, work); + bool kbd_on, digitizer_on; + int r; + + if (test_bit(YB_SUSPENDED, &data->flags)) + return; + + if (test_bit(YB_TABLET_MODE, &data->flags)) { + kbd_on = false; + digitizer_on = false; + } else if (test_bit(YB_DIGITIZER_MODE, &data->flags)) { + digitizer_on = true; + kbd_on = false; + } else { + kbd_on = true; + digitizer_on = false; + } + + if (!kbd_on && test_bit(YB_KBD_IS_ON, &data->flags)) { + /* + * Must be done before releasing the keyboard touchscreen driver, + * so that the keyboard touchscreen dev is still in D0. + */ + data->set_kbd_backlight(data, 0); + device_release_driver(data->kbd_dev); + clear_bit(YB_KBD_IS_ON, &data->flags); + } + + if (!digitizer_on && test_bit(YB_DIGITIZER_IS_ON, &data->flags)) { + led_set_brightness(data->pen_led, LED_OFF); + device_release_driver(data->dig_dev); + clear_bit(YB_DIGITIZER_IS_ON, &data->flags); + } + + if (kbd_on && !test_bit(YB_KBD_IS_ON, &data->flags)) { + r = device_reprobe(data->kbd_dev); + if (r) + dev_warn(data->dev, "Reprobe of keyboard touchscreen failed: %d\n", r); + + data->set_kbd_backlight(data, data->brightness); + set_bit(YB_KBD_IS_ON, &data->flags); + } + + if (digitizer_on && !test_bit(YB_DIGITIZER_IS_ON, &data->flags)) { + r = device_reprobe(data->dig_dev); + if (r) + dev_warn(data->dev, "Reprobe of digitizer failed: %d\n", r); + + led_set_brightness(data->pen_led, LED_FULL); + set_bit(YB_DIGITIZER_IS_ON, &data->flags); + } +} + +static void yogabook_toggle_digitizer_mode(struct yogabook_data *data) +{ + if (test_bit(YB_SUSPENDED, &data->flags)) + return; + + if (test_bit(YB_DIGITIZER_MODE, &data->flags)) + clear_bit(YB_DIGITIZER_MODE, &data->flags); + else + set_bit(YB_DIGITIZER_MODE, &data->flags); + + /* + * We are called from the ACPI core and the driver [un]binding which is + * done also needs ACPI functions, use a workqueue to avoid deadlocking. + */ + schedule_work(&data->work); +} + +static irqreturn_t yogabook_backside_hall_irq(int irq, void *_data) +{ + struct yogabook_data *data = _data; + + if (gpiod_get_value(data->backside_hall_gpio)) + set_bit(YB_TABLET_MODE, &data->flags); + else + clear_bit(YB_TABLET_MODE, &data->flags); + + schedule_work(&data->work); + + return IRQ_HANDLED; +} + +#define kbd_led_to_yogabook(cdev) container_of(cdev, struct yogabook_data, kbd_bl_led) + +static enum led_brightness kbd_brightness_get(struct led_classdev *cdev) +{ + struct yogabook_data *data = kbd_led_to_yogabook(cdev); + + return data->brightness; +} + +static int kbd_brightness_set(struct led_classdev *cdev, + enum led_brightness value) +{ + struct yogabook_data *data = kbd_led_to_yogabook(cdev); + + if ((value < 0) || (value > YB_KBD_BL_MAX)) + return -EINVAL; + + data->brightness = value; + + if (!test_bit(YB_KBD_IS_ON, &data->flags)) + return 0; + + return data->set_kbd_backlight(data, data->brightness); +} + +static struct gpiod_lookup_table yogabook_gpios = { + .table = { + GPIO_LOOKUP("INT33FF:02", 18, "backside_hall_sw", GPIO_ACTIVE_LOW), + {} + }, +}; + +static struct led_lookup_data yogabook_pen_led = { + .provider = "platform::indicator", + .con_id = "pen-icon-led", +}; + +static int yogabook_probe(struct device *dev, struct yogabook_data *data, + const char *kbd_bl_led_name) +{ + int r; + + data->dev = dev; + data->brightness = YB_KBD_BL_DEFAULT; + set_bit(YB_KBD_IS_ON, &data->flags); + set_bit(YB_DIGITIZER_IS_ON, &data->flags); + INIT_WORK(&data->work, yogabook_work); + + yogabook_pen_led.dev_id = dev_name(dev); + led_add_lookup(&yogabook_pen_led); + data->pen_led = devm_led_get(dev, "pen-icon-led"); + led_remove_lookup(&yogabook_pen_led); + + if (IS_ERR(data->pen_led)) + return dev_err_probe(dev, PTR_ERR(data->pen_led), "Getting pen icon LED\n"); + + yogabook_gpios.dev_id = dev_name(dev); + gpiod_add_lookup_table(&yogabook_gpios); + data->backside_hall_gpio = devm_gpiod_get(dev, "backside_hall_sw", GPIOD_IN); + gpiod_remove_lookup_table(&yogabook_gpios); + + if (IS_ERR(data->backside_hall_gpio)) + return dev_err_probe(dev, PTR_ERR(data->backside_hall_gpio), + "Getting backside_hall_sw GPIO\n"); + + r = gpiod_to_irq(data->backside_hall_gpio); + if (r < 0) + return dev_err_probe(dev, r, "Getting backside_hall_sw IRQ\n"); + + data->backside_hall_irq = r; + + /* Set default brightness before enabling the IRQ */ + data->set_kbd_backlight(data, YB_KBD_BL_DEFAULT); + + r = request_irq(data->backside_hall_irq, yogabook_backside_hall_irq, + IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, + "backside_hall_sw", data); + if (r) + return dev_err_probe(dev, r, "Requesting backside_hall_sw IRQ\n"); + + schedule_work(&data->work); + + data->kbd_bl_led.name = kbd_bl_led_name; + data->kbd_bl_led.brightness_set_blocking = kbd_brightness_set; + data->kbd_bl_led.brightness_get = kbd_brightness_get; + data->kbd_bl_led.max_brightness = YB_KBD_BL_MAX; + + r = devm_led_classdev_register(dev, &data->kbd_bl_led); + if (r < 0) { + dev_err_probe(dev, r, "Registering backlight LED device\n"); + goto error_free_irq; + } + + dev_set_drvdata(dev, data); + return 0; + +error_free_irq: + free_irq(data->backside_hall_irq, data); + cancel_work_sync(&data->work); + return r; +} + +static void yogabook_remove(struct yogabook_data *data) +{ + int r = 0; + + free_irq(data->backside_hall_irq, data); + cancel_work_sync(&data->work); + + if (!test_bit(YB_KBD_IS_ON, &data->flags)) + r |= device_reprobe(data->kbd_dev); + + if (!test_bit(YB_DIGITIZER_IS_ON, &data->flags)) + r |= device_reprobe(data->dig_dev); + + if (r) + dev_warn(data->dev, "Reprobe of devices failed\n"); +} + +static int yogabook_suspend(struct device *dev) +{ + struct yogabook_data *data = dev_get_drvdata(dev); + + set_bit(YB_SUSPENDED, &data->flags); + flush_work(&data->work); + + if (test_bit(YB_KBD_IS_ON, &data->flags)) + data->set_kbd_backlight(data, 0); + + return 0; +} + +static int yogabook_resume(struct device *dev) +{ + struct yogabook_data *data = dev_get_drvdata(dev); + + if (test_bit(YB_KBD_IS_ON, &data->flags)) + data->set_kbd_backlight(data, data->brightness); + + clear_bit(YB_SUSPENDED, &data->flags); + + /* Check for YB_TABLET_MODE changes made during suspend */ + schedule_work(&data->work); + + return 0; +} + +static DEFINE_SIMPLE_DEV_PM_OPS(yogabook_pm_ops, yogabook_suspend, yogabook_resume); + +/********** WMI driver code **********/ + +/* + * To control keyboard backlight, call the method KBLC() of the TCS1 ACPI + * device (Goodix touchpad acts as virtual sensor keyboard). + */ +static int yogabook_wmi_set_kbd_backlight(struct yogabook_data *data, + uint8_t level) +{ + struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; + struct acpi_object_list input; + union acpi_object param; + acpi_status status; + + dev_dbg(data->dev, "Set KBLC level to %u\n", level); + + /* Ensure keyboard touchpad is on before we call KBLC() */ + acpi_device_set_power(data->kbd_adev, ACPI_STATE_D0); + + input.count = 1; + input.pointer = ¶m; + + param.type = ACPI_TYPE_INTEGER; + param.integer.value = YB_KBD_BL_MAX - level; + + status = acpi_evaluate_object(acpi_device_handle(data->kbd_adev), "KBLC", + &input, &output); + if (ACPI_FAILURE(status)) { + dev_err(data->dev, "Failed to call KBLC method: 0x%x\n", status); + return status; + } + + kfree(output.pointer); + return 0; +} + +static int yogabook_wmi_probe(struct wmi_device *wdev, const void *context) +{ + struct device *dev = &wdev->dev; + struct yogabook_data *data; + int r; + + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); + if (data == NULL) + return -ENOMEM; + + data->kbd_adev = acpi_dev_get_first_match_dev("GDIX1001", NULL, -1); + if (!data->kbd_adev) + return dev_err_probe(dev, -ENODEV, "Cannot find the touchpad device in ACPI tables\n"); + + data->dig_adev = acpi_dev_get_first_match_dev("WCOM0019", NULL, -1); + if (!data->dig_adev) { + r = dev_err_probe(dev, -ENODEV, "Cannot find the digitizer device in ACPI tables\n"); + goto error_put_devs; + } + + data->kbd_dev = get_device(acpi_get_first_physical_node(data->kbd_adev)); + if (!data->kbd_dev || !data->kbd_dev->driver) { + r = -EPROBE_DEFER; + goto error_put_devs; + } + + data->dig_dev = get_device(acpi_get_first_physical_node(data->dig_adev)); + if (!data->dig_dev || !data->dig_dev->driver) { + r = -EPROBE_DEFER; + goto error_put_devs; + } + + data->set_kbd_backlight = yogabook_wmi_set_kbd_backlight; + + r = yogabook_probe(dev, data, "ybwmi::kbd_backlight"); + if (r) + goto error_put_devs; + + return 0; + +error_put_devs: + put_device(data->dig_dev); + put_device(data->kbd_dev); + acpi_dev_put(data->dig_adev); + acpi_dev_put(data->kbd_adev); + return r; +} + +static void yogabook_wmi_remove(struct wmi_device *wdev) +{ + struct yogabook_data *data = dev_get_drvdata(&wdev->dev); + + yogabook_remove(data); + + put_device(data->dig_dev); + put_device(data->kbd_dev); + acpi_dev_put(data->dig_adev); + acpi_dev_put(data->kbd_adev); +} + +static void yogabook_wmi_notify(struct wmi_device *wdev, union acpi_object *dummy) +{ + yogabook_toggle_digitizer_mode(dev_get_drvdata(&wdev->dev)); +} + +static const struct wmi_device_id yogabook_wmi_id_table[] = { + { + .guid_string = YB_MBTN_EVENT_GUID, + }, + { } /* Terminating entry */ +}; +MODULE_DEVICE_TABLE(wmi, yogabook_wmi_id_table); + +static struct wmi_driver yogabook_wmi_driver = { + .driver = { + .name = "yogabook-wmi", + .pm = pm_sleep_ptr(&yogabook_pm_ops), + }, + .no_notify_data = true, + .id_table = yogabook_wmi_id_table, + .probe = yogabook_wmi_probe, + .remove = yogabook_wmi_remove, + .notify = yogabook_wmi_notify, +}; + +/********** platform driver code **********/ + +static struct gpiod_lookup_table yogabook_pdev_gpios = { + .dev_id = YB_PDEV_NAME, + .table = { + GPIO_LOOKUP("INT33FF:00", 95, "pen_touch_event", GPIO_ACTIVE_HIGH), + GPIO_LOOKUP("INT33FF:03", 52, "enable_keyboard_led", GPIO_ACTIVE_HIGH), + {} + }, +}; + +static int yogabook_pdev_set_kbd_backlight(struct yogabook_data *data, u8 level) +{ + struct pwm_state state = { + .period = YB_KBD_BL_PWM_PERIOD, + .duty_cycle = YB_KBD_BL_PWM_PERIOD * level / YB_KBD_BL_MAX, + .enabled = level, + }; + + pwm_apply_state(data->kbd_bl_pwm, &state); + gpiod_set_value(data->kbd_bl_led_enable, level ? 1 : 0); + return 0; +} + +static irqreturn_t yogabook_pen_touch_irq(int irq, void *data) +{ + yogabook_toggle_digitizer_mode(data); + return IRQ_HANDLED; +} + +static int yogabook_pdev_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct yogabook_data *data; + int r; + + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); + if (data == NULL) + return -ENOMEM; + + data->kbd_dev = bus_find_device_by_name(&i2c_bus_type, NULL, "i2c-goodix_ts"); + if (!data->kbd_dev || !data->kbd_dev->driver) { + r = -EPROBE_DEFER; + goto error_put_devs; + } + + data->dig_dev = bus_find_device_by_name(&i2c_bus_type, NULL, "i2c-wacom"); + if (!data->dig_dev || !data->dig_dev->driver) { + r = -EPROBE_DEFER; + goto error_put_devs; + } + + gpiod_add_lookup_table(&yogabook_pdev_gpios); + data->pen_touch_event = devm_gpiod_get(dev, "pen_touch_event", GPIOD_IN); + data->kbd_bl_led_enable = devm_gpiod_get(dev, "enable_keyboard_led", GPIOD_OUT_HIGH); + gpiod_remove_lookup_table(&yogabook_pdev_gpios); + + if (IS_ERR(data->pen_touch_event)) { + r = dev_err_probe(dev, PTR_ERR(data->pen_touch_event), + "Getting pen_touch_event GPIO\n"); + goto error_put_devs; + } + + if (IS_ERR(data->kbd_bl_led_enable)) { + r = dev_err_probe(dev, PTR_ERR(data->kbd_bl_led_enable), + "Getting enable_keyboard_led GPIO\n"); + goto error_put_devs; + } + + data->kbd_bl_pwm = devm_pwm_get(dev, "pwm_soc_lpss_2"); + if (IS_ERR(data->kbd_bl_pwm)) { + r = dev_err_probe(dev, PTR_ERR(data->kbd_bl_pwm), + "Getting keyboard backlight PWM\n"); + goto error_put_devs; + } + + r = gpiod_to_irq(data->pen_touch_event); + if (r < 0) { + dev_err_probe(dev, r, "Getting pen_touch_event IRQ\n"); + goto error_put_devs; + } + data->pen_touch_irq = r; + + r = request_irq(data->pen_touch_irq, yogabook_pen_touch_irq, IRQF_TRIGGER_FALLING, + "pen_touch_event", data); + if (r) { + dev_err_probe(dev, r, "Requesting pen_touch_event IRQ\n"); + goto error_put_devs; + } + + data->set_kbd_backlight = yogabook_pdev_set_kbd_backlight; + + r = yogabook_probe(dev, data, "yogabook::kbd_backlight"); + if (r) + goto error_free_irq; + + return 0; + +error_free_irq: + free_irq(data->pen_touch_irq, data); + cancel_work_sync(&data->work); +error_put_devs: + put_device(data->dig_dev); + put_device(data->kbd_dev); + return r; +} + +static void yogabook_pdev_remove(struct platform_device *pdev) +{ + struct yogabook_data *data = platform_get_drvdata(pdev); + + yogabook_remove(data); + free_irq(data->pen_touch_irq, data); + cancel_work_sync(&data->work); + put_device(data->dig_dev); + put_device(data->kbd_dev); +} + +static struct platform_driver yogabook_pdev_driver = { + .probe = yogabook_pdev_probe, + .remove_new = yogabook_pdev_remove, + .driver = { + .name = YB_PDEV_NAME, + .pm = pm_sleep_ptr(&yogabook_pm_ops), + }, +}; + +static int __init yogabook_module_init(void) +{ + int r; + + r = wmi_driver_register(&yogabook_wmi_driver); + if (r) + return r; + + r = platform_driver_register(&yogabook_pdev_driver); + if (r) + wmi_driver_unregister(&yogabook_wmi_driver); + + return r; +} + +static void __exit yogabook_module_exit(void) +{ + platform_driver_unregister(&yogabook_pdev_driver); + wmi_driver_unregister(&yogabook_wmi_driver); +} + +module_init(yogabook_module_init); +module_exit(yogabook_module_exit); + +MODULE_ALIAS("platform:" YB_PDEV_NAME); +MODULE_AUTHOR("Yauhen Kharuzhy"); +MODULE_DESCRIPTION("Lenovo Yoga Book driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/platform/x86/simatic-ipc.c b/drivers/platform/x86/simatic-ipc.c index b3622419cd1a4860b31f053c4f27ec57ded772b5..c773995b230d4daf797ff6580e65e1edc8b616e7 100644 --- a/drivers/platform/x86/simatic-ipc.c +++ b/drivers/platform/x86/simatic-ipc.c @@ -68,9 +68,10 @@ static int register_platform_devices(u32 station_id) } if (ledmode != SIMATIC_IPC_DEVICE_NONE) { - if (ledmode == SIMATIC_IPC_DEVICE_127E || - ledmode == SIMATIC_IPC_DEVICE_227G) - pdevname = KBUILD_MODNAME "_leds_gpio"; + if (ledmode == SIMATIC_IPC_DEVICE_127E) + pdevname = KBUILD_MODNAME "_leds_gpio_apollolake"; + if (ledmode == SIMATIC_IPC_DEVICE_227G) + pdevname = KBUILD_MODNAME "_leds_gpio_f7188x"; platform_data.devmode = ledmode; ipc_led_platform_device = platform_device_register_data(NULL, diff --git a/drivers/platform/x86/system76_acpi.c b/drivers/platform/x86/system76_acpi.c index 97f5a8255b91ee098b213b66ee840aa5e962db91..fc4708fa6ebeaaca22b8166efab215d306108f21 100644 --- a/drivers/platform/x86/system76_acpi.c +++ b/drivers/platform/x86/system76_acpi.c @@ -581,7 +581,7 @@ static const struct hwmon_ops thermal_ops = { }; // Allocate up to 8 fans and temperatures -static const struct hwmon_channel_info *thermal_channel_info[] = { +static const struct hwmon_channel_info * const thermal_channel_info[] = { HWMON_CHANNEL_INFO(fan, HWMON_F_INPUT | HWMON_F_LABEL, HWMON_F_INPUT | HWMON_F_LABEL, diff --git a/drivers/platform/x86/think-lmi.c b/drivers/platform/x86/think-lmi.c index 1138f770149d9274bed6ba6f33b480104f1b0f1d..52d1ce8dfe44a2aa94ea7b3a3344026ee1994125 100644 --- a/drivers/platform/x86/think-lmi.c +++ b/drivers/platform/x86/think-lmi.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -168,11 +169,11 @@ MODULE_PARM_DESC(debug_support, "Enable debug command support"); */ #define LENOVO_CERT_THUMBPRINT_GUID "C59119ED-1C0D-4806-A8E9-59AA318176C4" -#define TLMI_POP_PWD (1 << 0) -#define TLMI_PAP_PWD (1 << 1) -#define TLMI_HDD_PWD (1 << 2) -#define TLMI_SYS_PWD (1 << 3) -#define TLMI_CERT (1 << 7) +#define TLMI_POP_PWD BIT(0) /* Supervisor */ +#define TLMI_PAP_PWD BIT(1) /* Power-on */ +#define TLMI_HDD_PWD BIT(2) /* HDD/NVME */ +#define TLMI_SMP_PWD BIT(6) /* System Management */ +#define TLMI_CERT BIT(7) /* Certificate Based */ #define to_tlmi_pwd_setting(kobj) container_of(kobj, struct tlmi_pwd_setting, kobj) #define to_tlmi_attr_setting(kobj) container_of(kobj, struct tlmi_attr_setting, kobj) @@ -195,6 +196,7 @@ static const char * const level_options[] = { }; static struct think_lmi tlmi_priv; static struct class *fw_attr_class; +static DEFINE_MUTEX(tlmi_mutex); /* ------ Utility functions ------------*/ /* Strip out CR if one is present */ @@ -437,6 +439,9 @@ static ssize_t new_password_store(struct kobject *kobj, /* Strip out CR if one is present, setting password won't work if it is present */ strip_cr(new_pwd); + /* Use lock in case multiple WMI operations needed */ + mutex_lock(&tlmi_mutex); + pwdlen = strlen(new_pwd); /* pwdlen == 0 is allowed to clear the password */ if (pwdlen && ((pwdlen < setting->minlen) || (pwdlen > setting->maxlen))) { @@ -456,9 +461,9 @@ static ssize_t new_password_store(struct kobject *kobj, sprintf(pwd_type, "mhdp%d", setting->index); } else if (setting == tlmi_priv.pwd_nvme) { if (setting->level == TLMI_LEVEL_USER) - sprintf(pwd_type, "unvp%d", setting->index); + sprintf(pwd_type, "udrp%d", setting->index); else - sprintf(pwd_type, "mnvp%d", setting->index); + sprintf(pwd_type, "adrp%d", setting->index); } else { sprintf(pwd_type, "%s", setting->pwd_type); } @@ -493,6 +498,7 @@ static ssize_t new_password_store(struct kobject *kobj, kfree(auth_str); } out: + mutex_unlock(&tlmi_mutex); kfree(new_pwd); return ret ?: count; } @@ -879,6 +885,11 @@ static umode_t auth_attr_is_visible(struct kobject *kobj, return 0; } + /* Don't display un-needed settings if opcode available */ + if ((attr == &auth_encoding.attr || attr == &auth_kbdlang.attr) && + tlmi_priv.opcode_support) + return 0; + return attr->mode; } @@ -981,6 +992,9 @@ static ssize_t current_value_store(struct kobject *kobj, /* Strip out CR if one is present */ strip_cr(new_setting); + /* Use lock in case multiple WMI operations needed */ + mutex_lock(&tlmi_mutex); + /* Check if certificate authentication is enabled and active */ if (tlmi_priv.certificate_support && tlmi_priv.pwd_admin->cert_installed) { if (!tlmi_priv.pwd_admin->signature || !tlmi_priv.pwd_admin->save_signature) { @@ -1001,7 +1015,33 @@ static ssize_t current_value_store(struct kobject *kobj, tlmi_priv.pwd_admin->save_signature); if (ret) goto out; - } else { /* Non certiifcate based authentication */ + } else if (tlmi_priv.opcode_support) { + /* + * If opcode support is present use that interface. + * Note - this sets the variable and then the password as separate + * WMI calls. Function tlmi_save_bios_settings will error if the + * password is incorrect. + */ + set_str = kasprintf(GFP_KERNEL, "%s,%s;", setting->display_name, + new_setting); + if (!set_str) { + ret = -ENOMEM; + goto out; + } + + ret = tlmi_simple_call(LENOVO_SET_BIOS_SETTINGS_GUID, set_str); + if (ret) + goto out; + + if (tlmi_priv.pwd_admin->valid && tlmi_priv.pwd_admin->password[0]) { + ret = tlmi_opcode_setting("WmiOpcodePasswordAdmin", + tlmi_priv.pwd_admin->password); + if (ret) + goto out; + } + + ret = tlmi_save_bios_settings(""); + } else { /* old non-opcode based authentication method (deprecated) */ if (tlmi_priv.pwd_admin->valid && tlmi_priv.pwd_admin->password[0]) { auth_str = kasprintf(GFP_KERNEL, "%s,%s,%s;", tlmi_priv.pwd_admin->password, @@ -1039,6 +1079,7 @@ static ssize_t current_value_store(struct kobject *kobj, kobject_uevent(&tlmi_priv.class_dev->kobj, KOBJ_CHANGE); } out: + mutex_unlock(&tlmi_mutex); kfree(auth_str); kfree(set_str); kfree(new_setting); @@ -1483,11 +1524,11 @@ static int tlmi_analyze(void) tlmi_priv.pwd_power->valid = true; if (tlmi_priv.opcode_support) { - tlmi_priv.pwd_system = tlmi_create_auth("sys", "system"); + tlmi_priv.pwd_system = tlmi_create_auth("smp", "system"); if (!tlmi_priv.pwd_system) goto fail_clear_attr; - if (tlmi_priv.pwdcfg.core.password_state & TLMI_SYS_PWD) + if (tlmi_priv.pwdcfg.core.password_state & TLMI_SMP_PWD) tlmi_priv.pwd_system->valid = true; tlmi_priv.pwd_hdd = tlmi_create_auth("hdd", "hdd"); @@ -1498,6 +1539,10 @@ static int tlmi_analyze(void) if (!tlmi_priv.pwd_nvme) goto fail_clear_attr; + /* Set default hdd/nvme index to 1 as there is no device 0 */ + tlmi_priv.pwd_hdd->index = 1; + tlmi_priv.pwd_nvme->index = 1; + if (tlmi_priv.pwdcfg.core.password_state & TLMI_HDD_PWD) { /* Check if PWD is configured and set index to first drive found */ if (tlmi_priv.pwdcfg.ext.hdd_user_password || diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index b3808ad77278d957ba5a2ab5d2e0dda6b91a155d..ad460417f901af56c23dd68c3f4689f6b1d74eaf 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -315,17 +315,12 @@ struct ibm_init_struct { /* DMI Quirks */ struct quirk_entry { bool btusb_bug; - u32 s2idle_bug_mmio; }; static struct quirk_entry quirk_btusb_bug = { .btusb_bug = true, }; -static struct quirk_entry quirk_s2idle_bug = { - .s2idle_bug_mmio = 0xfed80380, -}; - static struct { u32 bluetooth:1; u32 hotkey:1; @@ -4422,136 +4417,9 @@ static const struct dmi_system_id fwbug_list[] __initconst = { DMI_MATCH(DMI_BOARD_NAME, "20MV"), }, }, - { - .ident = "L14 Gen2 AMD", - .driver_data = &quirk_s2idle_bug, - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_NAME, "20X5"), - } - }, - { - .ident = "T14s Gen2 AMD", - .driver_data = &quirk_s2idle_bug, - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_NAME, "20XF"), - } - }, - { - .ident = "X13 Gen2 AMD", - .driver_data = &quirk_s2idle_bug, - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_NAME, "20XH"), - } - }, - { - .ident = "T14 Gen2 AMD", - .driver_data = &quirk_s2idle_bug, - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_NAME, "20XK"), - } - }, - { - .ident = "T14 Gen1 AMD", - .driver_data = &quirk_s2idle_bug, - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_NAME, "20UD"), - } - }, - { - .ident = "T14 Gen1 AMD", - .driver_data = &quirk_s2idle_bug, - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_NAME, "20UE"), - } - }, - { - .ident = "T14s Gen1 AMD", - .driver_data = &quirk_s2idle_bug, - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_NAME, "20UH"), - } - }, - { - .ident = "T14s Gen1 AMD", - .driver_data = &quirk_s2idle_bug, - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_NAME, "20UJ"), - } - }, - { - .ident = "P14s Gen1 AMD", - .driver_data = &quirk_s2idle_bug, - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_NAME, "20Y1"), - } - }, - { - .ident = "P14s Gen2 AMD", - .driver_data = &quirk_s2idle_bug, - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_NAME, "21A0"), - } - }, - { - .ident = "P14s Gen2 AMD", - .driver_data = &quirk_s2idle_bug, - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_NAME, "21A1"), - } - }, {} }; -#ifdef CONFIG_SUSPEND -/* - * Lenovo laptops from a variety of generations run a SMI handler during the D3->D0 - * transition that occurs specifically when exiting suspend to idle which can cause - * large delays during resume when the IOMMU translation layer is enabled (the default - * behavior) for NVME devices: - * - * To avoid this firmware problem, skip the SMI handler on these machines before the - * D0 transition occurs. - */ -static void thinkpad_acpi_amd_s2idle_restore(void) -{ - struct resource *res; - void __iomem *addr; - u8 val; - - res = request_mem_region_muxed(tp_features.quirks->s2idle_bug_mmio, 1, - "thinkpad_acpi_pm80"); - if (!res) - return; - - addr = ioremap(tp_features.quirks->s2idle_bug_mmio, 1); - if (!addr) - goto cleanup_resource; - - val = ioread8(addr); - iowrite8(val & ~BIT(0), addr); - - iounmap(addr); -cleanup_resource: - release_resource(res); - kfree(res); -} - -static struct acpi_s2idle_dev_ops thinkpad_acpi_s2idle_dev_ops = { - .restore = thinkpad_acpi_amd_s2idle_restore, -}; -#endif - static const struct pci_device_id fwbug_cards_ids[] __initconst = { { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x24F3) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x24FD) }, @@ -10524,8 +10392,8 @@ static int dytc_profile_set(struct platform_profile_handler *pprof, static void dytc_profile_refresh(void) { enum platform_profile_option profile; - int output, err = 0; - int perfmode, funcmode; + int output = 0, err = 0; + int perfmode, funcmode = 0; mutex_lock(&dytc_mutex); if (dytc_capabilities & BIT(DYTC_FC_MMC)) { @@ -10538,6 +10406,8 @@ static void dytc_profile_refresh(void) err = dytc_command(DYTC_CMD_GET, &output); /* Check if we are PSC mode, or have AMT enabled */ funcmode = (output >> DYTC_GET_FUNCTION_BIT) & 0xF; + } else { /* Unknown profile mode */ + err = -ENODEV; } mutex_unlock(&dytc_mutex); if (err) @@ -11666,10 +11536,6 @@ static void thinkpad_acpi_module_exit(void) tpacpi_lifecycle = TPACPI_LIFE_EXITING; -#ifdef CONFIG_SUSPEND - if (tp_features.quirks && tp_features.quirks->s2idle_bug_mmio) - acpi_unregister_lps0_dev(&thinkpad_acpi_s2idle_dev_ops); -#endif if (tpacpi_hwmon) hwmon_device_unregister(tpacpi_hwmon); if (tp_features.sensors_pdrv_registered) @@ -11859,13 +11725,6 @@ static int __init thinkpad_acpi_module_init(void) tp_features.input_device_registered = 1; } -#ifdef CONFIG_SUSPEND - if (tp_features.quirks && tp_features.quirks->s2idle_bug_mmio) { - if (!acpi_register_lps0_dev(&thinkpad_acpi_s2idle_dev_ops)) - pr_info("Using s2idle quirk to avoid %s platform firmware bug\n", - (dmi_id && dmi_id->ident) ? dmi_id->ident : ""); - } -#endif return 0; } diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c index b34984bbee3345d6fec3c4c17ef9ad59f0d89434..291f14ef67024a35befa2ab2418e69b8c94c8302 100644 --- a/drivers/platform/x86/toshiba_acpi.c +++ b/drivers/platform/x86/toshiba_acpi.c @@ -3037,7 +3037,7 @@ static int toshiba_acpi_hwmon_read(struct device *dev, enum hwmon_sensor_types t return -EOPNOTSUPP; } -static const struct hwmon_channel_info *toshiba_acpi_hwmon_info[] = { +static const struct hwmon_channel_info * const toshiba_acpi_hwmon_info[] = { HWMON_CHANNEL_INFO(fan, HWMON_F_INPUT), NULL }; diff --git a/drivers/platform/x86/touchscreen_dmi.c b/drivers/platform/x86/touchscreen_dmi.c index 68e66b60445c3e40946308d3be7cc5421543d5a3..a5b687eed8f3896201c04c9d1da36361d5423485 100644 --- a/drivers/platform/x86/touchscreen_dmi.c +++ b/drivers/platform/x86/touchscreen_dmi.c @@ -26,6 +26,21 @@ struct ts_dmi_data { /* NOTE: Please keep all entries sorted alphabetically */ +static const struct property_entry archos_101_cesium_educ_props[] = { + PROPERTY_ENTRY_U32("touchscreen-size-x", 1280), + PROPERTY_ENTRY_U32("touchscreen-size-y", 1850), + PROPERTY_ENTRY_BOOL("touchscreen-inverted-x"), + PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"), + PROPERTY_ENTRY_U32("silead,max-fingers", 10), + PROPERTY_ENTRY_STRING("firmware-name", "gsl1680-archos-101-cesium-educ.fw"), + { } +}; + +static const struct ts_dmi_data archos_101_cesium_educ_data = { + .acpi_name = "MSSL1680:00", + .properties = archos_101_cesium_educ_props, +}; + static const struct property_entry chuwi_hi8_props[] = { PROPERTY_ENTRY_U32("touchscreen-size-x", 1665), PROPERTY_ENTRY_U32("touchscreen-size-y", 1140), @@ -1047,6 +1062,13 @@ static const struct ts_dmi_data vinga_twizzle_j116_data = { /* NOTE: Please keep this table sorted alphabetically */ const struct dmi_system_id touchscreen_dmi_table[] = { + { + /* Archos 101 Cesium Educ */ + .driver_data = (void *)&archos_101_cesium_educ_data, + .matches = { + DMI_MATCH(DMI_PRODUCT_NAME, "ARCHOS 101 Cesium Educ"), + }, + }, { /* Chuwi Hi8 */ .driver_data = (void *)&chuwi_hi8_data, diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c index d81319a502efcf904b6b962eb71451643f44834b..a78ddd83cda02fe68fd941339bb7f29355226f8c 100644 --- a/drivers/platform/x86/wmi.c +++ b/drivers/platform/x86/wmi.c @@ -136,6 +136,16 @@ static acpi_status find_guid(const char *guid_string, struct wmi_block **out) return AE_NOT_FOUND; } +static bool guid_parse_and_compare(const char *string, const guid_t *guid) +{ + guid_t guid_input; + + if (guid_parse(string, &guid_input)) + return false; + + return guid_equal(&guid_input, guid); +} + static const void *find_guid_context(struct wmi_block *wblock, struct wmi_driver *wdriver) { @@ -146,11 +156,7 @@ static const void *find_guid_context(struct wmi_block *wblock, return NULL; while (*id->guid_string) { - guid_t guid_input; - - if (guid_parse(id->guid_string, &guid_input)) - continue; - if (guid_equal(&wblock->gblock.guid, &guid_input)) + if (guid_parse_and_compare(id->guid_string, &wblock->gblock.guid)) return id->context; id++; } @@ -248,7 +254,9 @@ static acpi_status get_event_data(const struct wmi_block *wblock, struct acpi_bu * @wdev: A wmi bus device from a driver * @length: Required buffer size * - * Allocates memory needed for buffer, stores the buffer size in that memory + * Allocates memory needed for buffer, stores the buffer size in that memory. + * + * Return: 0 on success or a negative error code for failure. */ int set_required_buffer_size(struct wmi_device *wdev, u64 length) { @@ -262,14 +270,57 @@ int set_required_buffer_size(struct wmi_device *wdev, u64 length) EXPORT_SYMBOL_GPL(set_required_buffer_size); /** - * wmi_evaluate_method - Evaluate a WMI method + * wmi_instance_count - Get number of WMI object instances + * @guid_string: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba + * + * Get the number of WMI object instances. + * + * Returns: Number of WMI object instances or negative error code. + */ +int wmi_instance_count(const char *guid_string) +{ + struct wmi_block *wblock; + acpi_status status; + + status = find_guid(guid_string, &wblock); + if (ACPI_FAILURE(status)) { + if (status == AE_BAD_PARAMETER) + return -EINVAL; + + return -ENODEV; + } + + return wmidev_instance_count(&wblock->dev); +} +EXPORT_SYMBOL_GPL(wmi_instance_count); + +/** + * wmidev_instance_count - Get number of WMI object instances + * @wdev: A wmi bus device from a driver + * + * Get the number of WMI object instances. + * + * Returns: Number of WMI object instances. + */ +u8 wmidev_instance_count(struct wmi_device *wdev) +{ + struct wmi_block *wblock = container_of(wdev, struct wmi_block, dev); + + return wblock->gblock.instance_count; +} +EXPORT_SYMBOL_GPL(wmidev_instance_count); + +/** + * wmi_evaluate_method - Evaluate a WMI method (deprecated) * @guid_string: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba * @instance: Instance index * @method_id: Method ID to call * @in: Buffer containing input for the method call * @out: Empty buffer to return the method results * - * Call an ACPI-WMI method + * Call an ACPI-WMI method, the caller must free @out. + * + * Return: acpi_status signaling success or error. */ acpi_status wmi_evaluate_method(const char *guid_string, u8 instance, u32 method_id, const struct acpi_buffer *in, struct acpi_buffer *out) @@ -294,7 +345,9 @@ EXPORT_SYMBOL_GPL(wmi_evaluate_method); * @in: Buffer containing input for the method call * @out: Empty buffer to return the method results * - * Call an ACPI-WMI method + * Call an ACPI-WMI method, the caller must free @out. + * + * Return: acpi_status signaling success or error. */ acpi_status wmidev_evaluate_method(struct wmi_device *wdev, u8 instance, u32 method_id, const struct acpi_buffer *in, struct acpi_buffer *out) @@ -411,7 +464,9 @@ static acpi_status __query_block(struct wmi_block *wblock, u8 instance, * @instance: Instance index * @out: Empty buffer to return the contents of the data block to * - * Return the contents of an ACPI-WMI data block to a buffer + * Query a ACPI-WMI block, the caller must free @out. + * + * Return: ACPI object containing the content of the WMI block. */ acpi_status wmi_query_block(const char *guid_string, u8 instance, struct acpi_buffer *out) @@ -427,6 +482,15 @@ acpi_status wmi_query_block(const char *guid_string, u8 instance, } EXPORT_SYMBOL_GPL(wmi_query_block); +/** + * wmidev_block_query - Return contents of a WMI block + * @wdev: A wmi bus device from a driver + * @instance: Instance index + * + * Query an ACPI-WMI block, the caller must free the result. + * + * Return: ACPI object containing the content of the WMI block. + */ union acpi_object *wmidev_block_query(struct wmi_device *wdev, u8 instance) { struct acpi_buffer out = { ACPI_ALLOCATE_BUFFER, NULL }; @@ -440,12 +504,14 @@ union acpi_object *wmidev_block_query(struct wmi_device *wdev, u8 instance) EXPORT_SYMBOL_GPL(wmidev_block_query); /** - * wmi_set_block - Write to a WMI block + * wmi_set_block - Write to a WMI block (deprecated) * @guid_string: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba * @instance: Instance index * @in: Buffer containing new values for the data block * - * Write the contents of the input buffer to an ACPI-WMI data block + * Write the contents of the input buffer to an ACPI-WMI data block. + * + * Return: acpi_status signaling success or error. */ acpi_status wmi_set_block(const char *guid_string, u8 instance, const struct acpi_buffer *in) @@ -549,12 +615,14 @@ static void wmi_notify_debug(u32 value, void *context) } /** - * wmi_install_notify_handler - Register handler for WMI events + * wmi_install_notify_handler - Register handler for WMI events (deprecated) * @guid: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba * @handler: Function to handle notifications * @data: Data to be returned to handler when event is fired * * Register a handler for events sent to the ACPI-WMI mapper device. + * + * Return: acpi_status signaling success or error. */ acpi_status wmi_install_notify_handler(const char *guid, wmi_notify_handler handler, @@ -593,10 +661,12 @@ acpi_status wmi_install_notify_handler(const char *guid, EXPORT_SYMBOL_GPL(wmi_install_notify_handler); /** - * wmi_remove_notify_handler - Unregister handler for WMI events + * wmi_remove_notify_handler - Unregister handler for WMI events (deprecated) * @guid: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba * * Unregister handler for events sent to the ACPI-WMI mapper device. + * + * Return: acpi_status signaling success or error. */ acpi_status wmi_remove_notify_handler(const char *guid) { @@ -638,12 +708,14 @@ acpi_status wmi_remove_notify_handler(const char *guid) EXPORT_SYMBOL_GPL(wmi_remove_notify_handler); /** - * wmi_get_event_data - Get WMI data associated with an event + * wmi_get_event_data - Get WMI data associated with an event (deprecated) * * @event: Event to find - * @out: Buffer to hold event data. out->pointer should be freed with kfree() + * @out: Buffer to hold event data + * + * Get extra data associated with an WMI event, the caller needs to free @out. * - * Returns extra data associated with an event in WMI. + * Return: acpi_status signaling success or error. */ acpi_status wmi_get_event_data(u32 event, struct acpi_buffer *out) { @@ -664,7 +736,9 @@ EXPORT_SYMBOL_GPL(wmi_get_event_data); * wmi_has_guid - Check if a GUID is available * @guid_string: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba * - * Check if a given GUID is defined by _WDG + * Check if a given GUID is defined by _WDG. + * + * Return: True if GUID is available, false otherwise. */ bool wmi_has_guid(const char *guid_string) { @@ -673,12 +747,12 @@ bool wmi_has_guid(const char *guid_string) EXPORT_SYMBOL_GPL(wmi_has_guid); /** - * wmi_get_acpi_device_uid() - Get _UID name of ACPI device that defines GUID + * wmi_get_acpi_device_uid() - Get _UID name of ACPI device that defines GUID (deprecated) * @guid_string: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba * * Find the _UID of ACPI device associated with this WMI GUID. * - * Return: The ACPI _UID field value or NULL if the WMI GUID was not found + * Return: The ACPI _UID field value or NULL if the WMI GUID was not found. */ char *wmi_get_acpi_device_uid(const char *guid_string) { @@ -827,11 +901,7 @@ static int wmi_dev_match(struct device *dev, struct device_driver *driver) return 0; while (*id->guid_string) { - guid_t driver_guid; - - if (WARN_ON(guid_parse(id->guid_string, &driver_guid))) - continue; - if (guid_equal(&driver_guid, &wblock->gblock.guid)) + if (guid_parse_and_compare(id->guid_string, &wblock->gblock.guid)) return 1; id++; @@ -1171,11 +1241,7 @@ static bool guid_already_parsed_for_legacy(struct acpi_device *device, const gui list_for_each_entry(wblock, &wmi_block_list, list) { /* skip warning and register if we know the driver will use struct wmi_driver */ for (int i = 0; allow_duplicates[i] != NULL; i++) { - guid_t tmp; - - if (guid_parse(allow_duplicates[i], &tmp)) - continue; - if (guid_equal(&tmp, guid)) + if (guid_parse_and_compare(allow_duplicates[i], guid)) return false; } if (guid_equal(&wblock->gblock.guid, guid)) { @@ -1454,6 +1520,12 @@ int __must_check __wmi_driver_register(struct wmi_driver *driver, } EXPORT_SYMBOL(__wmi_driver_register); +/** + * wmi_driver_unregister() - Unregister a WMI driver + * @driver: WMI driver to unregister + * + * Unregisters a WMI driver from the WMI bus. + */ void wmi_driver_unregister(struct wmi_driver *driver) { driver_unregister(&driver->driver); diff --git a/drivers/platform/x86/x86-android-tablets/asus.c b/drivers/platform/x86/x86-android-tablets/asus.c index cfa038b44b4334b0de3450a3b143f1a11dc5fced..f9c4083be86d8bd27109bead0b1b90a875b41eac 100644 --- a/drivers/platform/x86/x86-android-tablets/asus.c +++ b/drivers/platform/x86/x86-android-tablets/asus.c @@ -24,7 +24,7 @@ static struct gpiod_lookup_table int3496_gpo2_pin22_gpios = { }, }; -static struct x86_gpio_button asus_me176c_tf103c_lid = { +static const struct x86_gpio_button asus_me176c_tf103c_lid __initconst = { .button = { .code = SW_LID, .active_low = true, @@ -175,10 +175,10 @@ const struct x86_dev_info asus_me176c_info __initconst = { .serdev_info = asus_me176c_serdevs, .serdev_count = ARRAY_SIZE(asus_me176c_serdevs), .gpio_button = &asus_me176c_tf103c_lid, + .gpio_button_count = 1, .gpiod_lookup_tables = asus_me176c_gpios, .bat_swnode = &generic_lipo_hv_4v35_battery_node, .modules = bq24190_modules, - .invalid_aei_gpiochip = "INT33FC:02", }; /* Asus TF103C tablets have an Android factory img with everything hardcoded */ @@ -318,8 +318,8 @@ const struct x86_dev_info asus_tf103c_info __initconst = { .pdev_info = int3496_pdevs, .pdev_count = 1, .gpio_button = &asus_me176c_tf103c_lid, + .gpio_button_count = 1, .gpiod_lookup_tables = asus_tf103c_gpios, .bat_swnode = &asus_tf103c_battery_node, .modules = bq24190_modules, - .invalid_aei_gpiochip = "INT33FC:02", }; diff --git a/drivers/platform/x86/x86-android-tablets/core.c b/drivers/platform/x86/x86-android-tablets/core.c index 245167674aa2666a8dc709d9c32d22c2a67d2d9c..2fd6060a31bb0bb96b942b87ff6bde8a3057e04b 100644 --- a/drivers/platform/x86/x86-android-tablets/core.c +++ b/drivers/platform/x86/x86-android-tablets/core.c @@ -124,6 +124,7 @@ static int serdev_count; static struct i2c_client **i2c_clients; static struct platform_device **pdevs; static struct serdev_device **serdevs; +static struct gpio_keys_button *buttons; static struct gpiod_lookup_table * const *gpiod_lookup_tables; static const struct software_node *bat_swnode; static void (*exit_handler)(void); @@ -238,6 +239,7 @@ static void x86_android_tablet_cleanup(void) platform_device_unregister(pdevs[i]); kfree(pdevs); + kfree(buttons); for (i = 0; i < i2c_client_count; i++) i2c_unregister_device(i2c_clients[i]); @@ -353,22 +355,30 @@ static __init int x86_android_tablet_init(void) } } - if (dev_info->gpio_button) { - struct gpio_keys_platform_data pdata = { - .buttons = &dev_info->gpio_button->button, - .nbuttons = 1, - }; + if (dev_info->gpio_button_count) { + struct gpio_keys_platform_data pdata = { }; struct gpio_desc *gpiod; - /* Get GPIO for the gpio-button */ - ret = x86_android_tablet_get_gpiod(dev_info->gpio_button->chip, - dev_info->gpio_button->pin, &gpiod); - if (ret < 0) { + buttons = kcalloc(dev_info->gpio_button_count, sizeof(*buttons), GFP_KERNEL); + if (!buttons) { x86_android_tablet_cleanup(); - return ret; + return -ENOMEM; + } + + for (i = 0; i < dev_info->gpio_button_count; i++) { + ret = x86_android_tablet_get_gpiod(dev_info->gpio_button[i].chip, + dev_info->gpio_button[i].pin, &gpiod); + if (ret < 0) { + x86_android_tablet_cleanup(); + return ret; + } + + buttons[i] = dev_info->gpio_button[i].button; + buttons[i].gpio = desc_to_gpio(gpiod); } - dev_info->gpio_button->button.gpio = desc_to_gpio(gpiod); + pdata.buttons = buttons; + pdata.nbuttons = dev_info->gpio_button_count; pdevs[pdev_count] = platform_device_register_data(NULL, "gpio-keys", PLATFORM_DEVID_AUTO, diff --git a/drivers/platform/x86/x86-android-tablets/dmi.c b/drivers/platform/x86/x86-android-tablets/dmi.c index 23e640b7003d977136cd8b1e8579109f9aa55741..5d6c12494f082a90337640fe1f018fcea2d5c151 100644 --- a/drivers/platform/x86/x86-android-tablets/dmi.c +++ b/drivers/platform/x86/x86-android-tablets/dmi.c @@ -58,6 +58,17 @@ const struct dmi_system_id x86_android_tablet_ids[] __initconst = { }, .driver_data = (void *)&chuwi_hi8_info, }, + { + /* Cyberbook T116 Android version */ + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Default string"), + DMI_MATCH(DMI_BOARD_NAME, "Cherry Trail CR"), + /* Above strings are much too generic, also match on SKU + BIOS date */ + DMI_MATCH(DMI_PRODUCT_SKU, "20170531"), + DMI_MATCH(DMI_BIOS_DATE, "07/12/2017"), + }, + .driver_data = (void *)&cyberbook_t116_info, + }, { /* CZC P10T */ .ident = "CZC ODEON TPC-10 (\"P10T\")", @@ -127,13 +138,22 @@ const struct dmi_system_id x86_android_tablet_ids[] __initconst = { .driver_data = (void *)&medion_lifetab_s10346_info, }, { - /* Nextbook Ares 8 */ + /* Nextbook Ares 8 (BYT version) */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Insyde"), DMI_MATCH(DMI_PRODUCT_NAME, "M890BAP"), }, .driver_data = (void *)&nextbook_ares8_info, }, + { + /* Nextbook Ares 8A (CHT version)*/ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Insyde"), + DMI_MATCH(DMI_PRODUCT_NAME, "CherryTrail"), + DMI_MATCH(DMI_BIOS_VERSION, "M882"), + }, + .driver_data = (void *)&nextbook_ares8a_info, + }, { /* Peaq C1010 */ .matches = { diff --git a/drivers/platform/x86/x86-android-tablets/lenovo.c b/drivers/platform/x86/x86-android-tablets/lenovo.c index 65cfccaa2894a42695ad38e57c67a83179a63e4b..26a4ef670ad7ca424fda9efb38e4e4b89f01ecbe 100644 --- a/drivers/platform/x86/x86-android-tablets/lenovo.c +++ b/drivers/platform/x86/x86-android-tablets/lenovo.c @@ -147,6 +147,32 @@ static const struct platform_device_info lenovo_yb1_x90_pdevs[] __initconst = { }, }; +/* + * DSDT says UART path is "\\_SB.PCIO.URT1" with a letter 'O' instead of + * the number '0' add the link manually. + */ +static const struct x86_serdev_info lenovo_yb1_x90_serdevs[] __initconst = { + { + .ctrl_hid = "8086228A", + .ctrl_uid = "1", + .ctrl_devname = "serial0", + .serdev_hid = "BCM2E1A", + }, +}; + +static const struct x86_gpio_button lenovo_yb1_x90_lid __initconst = { + .button = { + .code = SW_LID, + .active_low = true, + .desc = "lid_sw", + .type = EV_SW, + .wakeup = true, + .debounce_interval = 50, + }, + .chip = "INT33FF:02", + .pin = 19, +}; + static struct gpiod_lookup_table lenovo_yb1_x90_goodix_gpios = { .dev_id = "i2c-goodix_ts", .table = { @@ -203,6 +229,10 @@ const struct x86_dev_info lenovo_yogabook_x90_info __initconst = { .i2c_client_count = ARRAY_SIZE(lenovo_yb1_x90_i2c_clients), .pdev_info = lenovo_yb1_x90_pdevs, .pdev_count = ARRAY_SIZE(lenovo_yb1_x90_pdevs), + .serdev_info = lenovo_yb1_x90_serdevs, + .serdev_count = ARRAY_SIZE(lenovo_yb1_x90_serdevs), + .gpio_button = &lenovo_yb1_x90_lid, + .gpio_button_count = 1, .gpiod_lookup_tables = lenovo_yb1_x90_gpios, .init = lenovo_yb1_x90_init, }; @@ -239,7 +269,7 @@ static const struct software_node lenovo_yoga_tab2_830_1050_bq24190_node = { .properties = lenovo_yoga_tab2_830_1050_bq24190_props, }; -static struct x86_gpio_button lenovo_yoga_tab2_830_1050_lid = { +static const struct x86_gpio_button lenovo_yoga_tab2_830_1050_lid __initconst = { .button = { .code = SW_LID, .active_low = true, @@ -267,6 +297,14 @@ static struct x86_i2c_client_info lenovo_yoga_tab2_830_1050_i2c_clients[] __init .dev_name = "lsm303d", }, .adapter_path = "\\_SB_.I2C5", + }, { + /* AL3320A ambient light sensor */ + .board_info = { + .type = "al3320a", + .addr = 0x1c, + .dev_name = "al3320a", + }, + .adapter_path = "\\_SB_.I2C5", }, { /* bq24292i battery charger */ .board_info = { @@ -357,6 +395,7 @@ const struct x86_dev_info lenovo_yoga_tab2_830_1050_info __initconst = { .pdev_info = int3496_pdevs, .pdev_count = 1, .gpio_button = &lenovo_yoga_tab2_830_1050_lid, + .gpio_button_count = 1, .gpiod_lookup_tables = lenovo_yoga_tab2_830_1050_gpios, .bat_swnode = &generic_lipo_hv_4v35_battery_node, .modules = bq24190_modules, diff --git a/drivers/platform/x86/x86-android-tablets/other.c b/drivers/platform/x86/x86-android-tablets/other.c index 83cd7e16c84c4bed9209aef808d162def11bec44..e79549c6aae17412fa80117ac298a7ede00883e3 100644 --- a/drivers/platform/x86/x86-android-tablets/other.c +++ b/drivers/platform/x86/x86-android-tablets/other.c @@ -94,7 +94,7 @@ const struct x86_dev_info acer_b1_750_info __initconst = { * which is not described in the ACPI tables in anyway. * Use the x86-android-tablets infra to create a gpio-button device for this. */ -static struct x86_gpio_button advantech_mica_071_button = { +static const struct x86_gpio_button advantech_mica_071_button __initconst = { .button = { .code = KEY_PROG1, .active_low = true, @@ -109,6 +109,7 @@ static struct x86_gpio_button advantech_mica_071_button = { const struct x86_dev_info advantech_mica_071_info __initconst = { .gpio_button = &advantech_mica_071_button, + .gpio_button_count = 1, }; /* @@ -196,6 +197,45 @@ const struct x86_dev_info chuwi_hi8_info __initconst = { .init = chuwi_hi8_init, }; +/* + * Cyberbook T116 Android version + * This comes in both Windows and Android versions and even on Android + * the DSDT is mostly sane. This tablet has 2 extra general purpose buttons + * in the button row with the power + volume-buttons labeled P and F. + * Use the x86-android-tablets infra to create a gpio-button device for these. + */ +static const struct x86_gpio_button cyberbook_t116_buttons[] __initconst = { + { + .button = { + .code = KEY_PROG1, + .active_low = true, + .desc = "prog1_key", + .type = EV_KEY, + .wakeup = false, + .debounce_interval = 50, + }, + .chip = "INT33FF:00", + .pin = 30, + }, + { + .button = { + .code = KEY_PROG2, + .active_low = true, + .desc = "prog2_key", + .type = EV_KEY, + .wakeup = false, + .debounce_interval = 50, + }, + .chip = "INT33FF:03", + .pin = 48, + }, +}; + +const struct x86_dev_info cyberbook_t116_info __initconst = { + .gpio_button = cyberbook_t116_buttons, + .gpio_button_count = ARRAY_SIZE(cyberbook_t116_buttons), +}; + #define CZC_EC_EXTRA_PORT 0x68 #define CZC_EC_ANDROID_KEYS 0x63 @@ -311,7 +351,7 @@ const struct x86_dev_info medion_lifetab_s10346_info __initconst = { .gpiod_lookup_tables = medion_lifetab_s10346_gpios, }; -/* Nextbook Ares 8 tablets have an Android factory img with everything hardcoded */ +/* Nextbook Ares 8 (BYT) tablets have an Android factory img with everything hardcoded */ static const char * const nextbook_ares8_accel_mount_matrix[] = { "0", "-1", "0", "-1", "0", "0", @@ -377,7 +417,70 @@ const struct x86_dev_info nextbook_ares8_info __initconst = { .pdev_info = int3496_pdevs, .pdev_count = 1, .gpiod_lookup_tables = nextbook_ares8_gpios, - .invalid_aei_gpiochip = "INT33FC:02", +}; + +/* Nextbook Ares 8A (CHT) tablets have an Android factory img with everything hardcoded */ +static const char * const nextbook_ares8a_accel_mount_matrix[] = { + "1", "0", "0", + "0", "-1", "0", + "0", "0", "1" +}; + +static const struct property_entry nextbook_ares8a_accel_props[] = { + PROPERTY_ENTRY_STRING_ARRAY("mount-matrix", nextbook_ares8a_accel_mount_matrix), + { } +}; + +static const struct software_node nextbook_ares8a_accel_node = { + .properties = nextbook_ares8a_accel_props, +}; + +static const struct x86_i2c_client_info nextbook_ares8a_i2c_clients[] __initconst = { + { + /* Freescale MMA8653FC accel */ + .board_info = { + .type = "mma8653", + .addr = 0x1d, + .dev_name = "mma8653", + .swnode = &nextbook_ares8a_accel_node, + }, + .adapter_path = "\\_SB_.PCI0.I2C3", + }, { + /* FT5416DQ9 touchscreen controller */ + .board_info = { + .type = "edt-ft5x06", + .addr = 0x38, + .dev_name = "ft5416", + .swnode = &nextbook_ares8_touchscreen_node, + }, + .adapter_path = "\\_SB_.PCI0.I2C6", + .irq_data = { + .type = X86_ACPI_IRQ_TYPE_GPIOINT, + .chip = "INT33FF:01", + .index = 17, + .trigger = ACPI_EDGE_SENSITIVE, + .polarity = ACPI_ACTIVE_LOW, + }, + }, +}; + +static struct gpiod_lookup_table nextbook_ares8a_ft5416_gpios = { + .dev_id = "i2c-ft5416", + .table = { + GPIO_LOOKUP("INT33FF:01", 25, "reset", GPIO_ACTIVE_LOW), + { } + }, +}; + +static struct gpiod_lookup_table * const nextbook_ares8a_gpios[] = { + &nextbook_ares8a_ft5416_gpios, + NULL +}; + +const struct x86_dev_info nextbook_ares8a_info __initconst = { + .i2c_client_info = nextbook_ares8a_i2c_clients, + .i2c_client_count = ARRAY_SIZE(nextbook_ares8a_i2c_clients), + .gpiod_lookup_tables = nextbook_ares8a_gpios, }; /* @@ -386,7 +489,7 @@ const struct x86_dev_info nextbook_ares8_info __initconst = { * This button has a WMI interface, but that is broken. Instead of trying to * use the broken WMI interface, instantiate a gpio_keys device for this. */ -static struct x86_gpio_button peaq_c1010_button = { +static const struct x86_gpio_button peaq_c1010_button __initconst = { .button = { .code = KEY_SOUND, .active_low = true, @@ -401,6 +504,7 @@ static struct x86_gpio_button peaq_c1010_button = { const struct x86_dev_info peaq_c1010_info __initconst = { .gpio_button = &peaq_c1010_button, + .gpio_button_count = 1, /* * Move the ACPI event handler used by the broken WMI interface out of * the way. This is the only event handler on INT33FC:00. diff --git a/drivers/platform/x86/x86-android-tablets/x86-android-tablets.h b/drivers/platform/x86/x86-android-tablets/x86-android-tablets.h index b6802d75dbdd05ab255e445a20c9a5c294091d02..e46e1128acc81ce5ae8b1c67c5d766aee58b8367 100644 --- a/drivers/platform/x86/x86-android-tablets/x86-android-tablets.h +++ b/drivers/platform/x86/x86-android-tablets/x86-android-tablets.h @@ -73,10 +73,11 @@ struct x86_dev_info { const struct x86_i2c_client_info *i2c_client_info; const struct platform_device_info *pdev_info; const struct x86_serdev_info *serdev_info; - struct x86_gpio_button *gpio_button; + const struct x86_gpio_button *gpio_button; int i2c_client_count; int pdev_count; int serdev_count; + int gpio_button_count; int (*init)(void); void (*exit)(void); }; @@ -93,6 +94,7 @@ extern const struct x86_dev_info advantech_mica_071_info; extern const struct x86_dev_info asus_me176c_info; extern const struct x86_dev_info asus_tf103c_info; extern const struct x86_dev_info chuwi_hi8_info; +extern const struct x86_dev_info cyberbook_t116_info; extern const struct x86_dev_info czc_p10t; extern const struct x86_dev_info lenovo_yogabook_x90_info; extern const struct x86_dev_info lenovo_yogabook_x91_info; @@ -100,6 +102,7 @@ extern const struct x86_dev_info lenovo_yoga_tab2_830_1050_info; extern const struct x86_dev_info lenovo_yt3_info; extern const struct x86_dev_info medion_lifetab_s10346_info; extern const struct x86_dev_info nextbook_ares8_info; +extern const struct x86_dev_info nextbook_ares8a_info; extern const struct x86_dev_info peaq_c1010_info; extern const struct x86_dev_info whitelabel_tm800a550l_info; extern const struct x86_dev_info xiaomi_mipad2_info; diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig index 8c87eeda0feca09b043ae8785e55a707d55ce75b..fff07b2bd77b9c757f1b7270fed64d9e0e02c6cf 100644 --- a/drivers/power/reset/Kconfig +++ b/drivers/power/reset/Kconfig @@ -158,6 +158,7 @@ config POWER_RESET_OXNAS config POWER_RESET_PIIX4_POWEROFF tristate "Intel PIIX4 power-off driver" depends on PCI + depends on HAS_IOPORT depends on MIPS || COMPILE_TEST help This driver supports powering off a system using the Intel PIIX4 diff --git a/drivers/power/reset/at91-reset.c b/drivers/power/reset/at91-reset.c index 741e44a017c3fc3d859dd73666afbeae443156b9..d6884841a6dc66fd52e4dc41629f8c127907cc49 100644 --- a/drivers/power/reset/at91-reset.c +++ b/drivers/power/reset/at91-reset.c @@ -149,11 +149,10 @@ static int at91_reset(struct notifier_block *this, unsigned long mode, return NOTIFY_DONE; } -static void __init at91_reset_status(struct platform_device *pdev, - void __iomem *base) +static const char * __init at91_reset_reason(struct at91_reset *reset) { + u32 reg = readl(reset->rstc_base + AT91_RSTC_SR); const char *reason; - u32 reg = readl(base + AT91_RSTC_SR); switch ((reg & AT91_RSTC_RSTTYP) >> 8) { case RESET_TYPE_GENERAL: @@ -185,7 +184,7 @@ static void __init at91_reset_status(struct platform_device *pdev, break; } - dev_info(&pdev->dev, "Starting after %s\n", reason); + return reason; } static const struct of_device_id at91_ramc_of_match[] = { @@ -392,7 +391,7 @@ static int __init at91_reset_probe(struct platform_device *pdev) if (ret) goto disable_clk; - at91_reset_status(pdev, reset->rstc_base); + dev_info(&pdev->dev, "Starting after %s\n", at91_reset_reason(reset)); return 0; diff --git a/drivers/power/reset/gpio-restart.c b/drivers/power/reset/gpio-restart.c index 35d981d5e6c8f7aa11d8f9c3282cd3b45a22e7dd..a479d3536eb1cc18c37776a49b28937fd077259c 100644 --- a/drivers/power/reset/gpio-restart.c +++ b/drivers/power/reset/gpio-restart.c @@ -105,7 +105,7 @@ static int gpio_restart_probe(struct platform_device *pdev) return 0; } -static int gpio_restart_remove(struct platform_device *pdev) +static void gpio_restart_remove(struct platform_device *pdev) { struct gpio_restart *gpio_restart = platform_get_drvdata(pdev); int ret; @@ -115,10 +115,7 @@ static int gpio_restart_remove(struct platform_device *pdev) dev_err(&pdev->dev, "%s: cannot unregister restart handler, %d\n", __func__, ret); - return -ENODEV; } - - return 0; } static const struct of_device_id of_gpio_restart_match[] = { @@ -128,7 +125,7 @@ static const struct of_device_id of_gpio_restart_match[] = { static struct platform_driver gpio_restart_driver = { .probe = gpio_restart_probe, - .remove = gpio_restart_remove, + .remove_new = gpio_restart_remove, .driver = { .name = "restart-gpio", .of_match_table = of_gpio_restart_match, diff --git a/drivers/power/reset/qcom-pon.c b/drivers/power/reset/qcom-pon.c index ebdcfb28c4a0de2adb0c0b8f375a6b61e5c9464f..1344b361a47514c92bddca85a1844003d6533d1e 100644 --- a/drivers/power/reset/qcom-pon.c +++ b/drivers/power/reset/qcom-pon.c @@ -17,6 +17,8 @@ #define GEN1_REASON_SHIFT 2 #define GEN2_REASON_SHIFT 1 +#define NO_REASON_SHIFT 0 + struct pm8916_pon { struct device *dev; struct regmap *regmap; @@ -45,6 +47,7 @@ static int pm8916_reboot_mode_write(struct reboot_mode_driver *reboot, static int pm8916_pon_probe(struct platform_device *pdev) { struct pm8916_pon *pon; + long reason_shift; int error; pon = devm_kzalloc(&pdev->dev, sizeof(*pon), GFP_KERNEL); @@ -64,13 +67,17 @@ static int pm8916_pon_probe(struct platform_device *pdev) if (error) return error; - pon->reboot_mode.dev = &pdev->dev; - pon->reason_shift = (long)of_device_get_match_data(&pdev->dev); - pon->reboot_mode.write = pm8916_reboot_mode_write; - error = devm_reboot_mode_register(&pdev->dev, &pon->reboot_mode); - if (error) { - dev_err(&pdev->dev, "can't register reboot mode\n"); - return error; + reason_shift = (long)of_device_get_match_data(&pdev->dev); + + if (reason_shift != NO_REASON_SHIFT) { + pon->reboot_mode.dev = &pdev->dev; + pon->reason_shift = reason_shift; + pon->reboot_mode.write = pm8916_reboot_mode_write; + error = devm_reboot_mode_register(&pdev->dev, &pon->reboot_mode); + if (error) { + dev_err(&pdev->dev, "can't register reboot mode\n"); + return error; + } } platform_set_drvdata(pdev, pon); @@ -80,6 +87,7 @@ static int pm8916_pon_probe(struct platform_device *pdev) static const struct of_device_id pm8916_pon_id_table[] = { { .compatible = "qcom,pm8916-pon", .data = (void *)GEN1_REASON_SHIFT }, + { .compatible = "qcom,pm8941-pon", .data = (void *)NO_REASON_SHIFT }, { .compatible = "qcom,pms405-pon", .data = (void *)GEN1_REASON_SHIFT }, { .compatible = "qcom,pm8998-pon", .data = (void *)GEN2_REASON_SHIFT }, { .compatible = "qcom,pmk8350-pon", .data = (void *)GEN2_REASON_SHIFT }, diff --git a/drivers/power/supply/Kconfig b/drivers/power/supply/Kconfig index c78be9f322e6c6002fb06f87db1e0dd1c15b99c4..663a1c4238066eddacbab1a1f2ade63cc1e79807 100644 --- a/drivers/power/supply/Kconfig +++ b/drivers/power/supply/Kconfig @@ -706,7 +706,7 @@ config CHARGER_BQ256XX config CHARGER_RK817 tristate "Rockchip RK817 PMIC Battery Charger" - depends on MFD_RK808 + depends on MFD_RK8XX help Say Y to include support for Rockchip RK817 Battery Charger. @@ -766,6 +766,14 @@ config BATTERY_RT5033 The fuelgauge calculates and determines the battery state of charge according to battery open circuit voltage. +config CHARGER_RT5033 + tristate "RT5033 battery charger support" + depends on MFD_RT5033 + help + This adds support for battery charger in Richtek RT5033 PMIC. + The device supports pre-charge mode, fast charge mode and + constant voltage mode. + config CHARGER_RT9455 tristate "Richtek RT9455 battery charger driver" depends on I2C @@ -934,4 +942,13 @@ config BATTERY_UG3105 device is off or suspended, the functionality of this driver is limited to reporting capacity only. +config CHARGER_QCOM_SMB2 + tristate "Qualcomm PMI8998 PMIC charger driver" + depends on MFD_SPMI_PMIC + depends on IIO + help + Say Y here to enable the Qualcomm PMIC Charger driver. This + adds support for the SMB2 switch mode battery charger found + in PMI8998 and related PMICs. + endif # POWER_SUPPLY diff --git a/drivers/power/supply/Makefile b/drivers/power/supply/Makefile index 4adbfba02d054a8a8ae7e47318d3313abe1645cc..a8a9fa6de1e9a039c397bb18a67387ca919b090c 100644 --- a/drivers/power/supply/Makefile +++ b/drivers/power/supply/Makefile @@ -54,6 +54,7 @@ obj-$(CONFIG_BATTERY_MAX17040) += max17040_battery.o obj-$(CONFIG_BATTERY_MAX17042) += max17042_battery.o obj-$(CONFIG_BATTERY_MAX1721X) += max1721x_battery.o obj-$(CONFIG_BATTERY_RT5033) += rt5033_battery.o +obj-$(CONFIG_CHARGER_RT5033) += rt5033_charger.o obj-$(CONFIG_CHARGER_RT9455) += rt9455_charger.o obj-$(CONFIG_CHARGER_RT9467) += rt9467-charger.o obj-$(CONFIG_CHARGER_RT9471) += rt9471.o @@ -109,3 +110,4 @@ obj-$(CONFIG_BATTERY_ACER_A500) += acer_a500_battery.o obj-$(CONFIG_BATTERY_SURFACE) += surface_battery.o obj-$(CONFIG_CHARGER_SURFACE) += surface_charger.o obj-$(CONFIG_BATTERY_UG3105) += ug3105_battery.o +obj-$(CONFIG_CHARGER_QCOM_SMB2) += qcom_pmi8998_charger.o diff --git a/drivers/power/supply/adp5061.c b/drivers/power/supply/adp5061.c index 840db629a46c34cdec1b8940065f1db34699aa3f..3e3a0d118ce5a5f6427b9e1f70d14cf897f3c419 100644 --- a/drivers/power/supply/adp5061.c +++ b/drivers/power/supply/adp5061.c @@ -736,7 +736,7 @@ static struct i2c_driver adp5061_driver = { .driver = { .name = KBUILD_MODNAME, }, - .probe_new = adp5061_probe, + .probe = adp5061_probe, .id_table = adp5061_id, }; module_i2c_driver(adp5061_driver); diff --git a/drivers/power/supply/axp20x_usb_power.c b/drivers/power/supply/axp20x_usb_power.c index a1e6d1d448086cf557c4c4e1505d2adee47c511a..51c3f9b6458d19d54962e416f1ec14c1230591c5 100644 --- a/drivers/power/supply/axp20x_usb_power.c +++ b/drivers/power/supply/axp20x_usb_power.c @@ -26,45 +26,48 @@ #define DRVNAME "axp20x-usb-power-supply" +#define AXP192_USB_OTG_STATUS 0x04 + #define AXP20X_PWR_STATUS_VBUS_PRESENT BIT(5) #define AXP20X_PWR_STATUS_VBUS_USED BIT(4) #define AXP20X_USB_STATUS_VBUS_VALID BIT(2) -#define AXP20X_VBUS_PATH_SEL BIT(7) -#define AXP20X_VBUS_PATH_SEL_OFFSET 7 - #define AXP20X_VBUS_VHOLD_uV(b) (4000000 + (((b) >> 3) & 7) * 100000) #define AXP20X_VBUS_VHOLD_MASK GENMASK(5, 3) #define AXP20X_VBUS_VHOLD_OFFSET 3 -#define AXP20X_VBUS_CLIMIT_MASK 3 -#define AXP20X_VBUS_CLIMIT_900mA 0 -#define AXP20X_VBUS_CLIMIT_500mA 1 -#define AXP20X_VBUS_CLIMIT_100mA 2 -#define AXP20X_VBUS_CLIMIT_NONE 3 - -#define AXP813_VBUS_CLIMIT_900mA 0 -#define AXP813_VBUS_CLIMIT_1500mA 1 -#define AXP813_VBUS_CLIMIT_2000mA 2 -#define AXP813_VBUS_CLIMIT_2500mA 3 #define AXP20X_ADC_EN1_VBUS_CURR BIT(2) #define AXP20X_ADC_EN1_VBUS_VOLT BIT(3) -#define AXP20X_VBUS_MON_VBUS_VALID BIT(3) - -#define AXP813_BC_EN BIT(0) - /* * Note do not raise the debounce time, we must report Vusb high within * 100ms otherwise we get Vbus errors in musb. */ #define DEBOUNCE_TIME msecs_to_jiffies(50) +struct axp_data { + const struct power_supply_desc *power_desc; + const char * const *irq_names; + unsigned int num_irq_names; + const int *curr_lim_table; + struct reg_field curr_lim_fld; + struct reg_field vbus_valid_bit; + struct reg_field vbus_mon_bit; + struct reg_field usb_bc_en_bit; + struct reg_field vbus_disable_bit; + bool vbus_needs_polling: 1; +}; + struct axp20x_usb_power { struct regmap *regmap; + struct regmap_field *curr_lim_fld; + struct regmap_field *vbus_valid_bit; + struct regmap_field *vbus_mon_bit; + struct regmap_field *usb_bc_en_bit; + struct regmap_field *vbus_disable_bit; struct power_supply *supply; - enum axp20x_variants axp20x_id; + const struct axp_data *axp_data; struct iio_channel *vbus_v; struct iio_channel *vbus_i; struct delayed_work vbus_detect; @@ -81,7 +84,7 @@ static bool axp20x_usb_vbus_needs_polling(struct axp20x_usb_power *power) * present->absent transition implies an online->offline transition * and will trigger the VBUS_REMOVAL IRQ. */ - if (power->axp20x_id >= AXP221_ID && !power->online) + if (power->axp_data->vbus_needs_polling && !power->online) return true; return false; @@ -121,60 +124,6 @@ static void axp20x_usb_power_poll_vbus(struct work_struct *work) mod_delayed_work(system_power_efficient_wq, &power->vbus_detect, DEBOUNCE_TIME); } -static int axp20x_get_current_max(struct axp20x_usb_power *power, int *val) -{ - unsigned int v; - int ret = regmap_read(power->regmap, AXP20X_VBUS_IPSOUT_MGMT, &v); - - if (ret) - return ret; - - switch (v & AXP20X_VBUS_CLIMIT_MASK) { - case AXP20X_VBUS_CLIMIT_100mA: - if (power->axp20x_id == AXP221_ID) - *val = -1; /* No 100mA limit */ - else - *val = 100000; - break; - case AXP20X_VBUS_CLIMIT_500mA: - *val = 500000; - break; - case AXP20X_VBUS_CLIMIT_900mA: - *val = 900000; - break; - case AXP20X_VBUS_CLIMIT_NONE: - *val = -1; - break; - } - - return 0; -} - -static int axp813_get_current_max(struct axp20x_usb_power *power, int *val) -{ - unsigned int v; - int ret = regmap_read(power->regmap, AXP20X_VBUS_IPSOUT_MGMT, &v); - - if (ret) - return ret; - - switch (v & AXP20X_VBUS_CLIMIT_MASK) { - case AXP813_VBUS_CLIMIT_900mA: - *val = 900000; - break; - case AXP813_VBUS_CLIMIT_1500mA: - *val = 1500000; - break; - case AXP813_VBUS_CLIMIT_2000mA: - *val = 2000000; - break; - case AXP813_VBUS_CLIMIT_2500mA: - *val = 2500000; - break; - } - return 0; -} - static int axp20x_usb_power_get_property(struct power_supply *psy, enum power_supply_property psp, union power_supply_propval *val) { @@ -213,9 +162,12 @@ static int axp20x_usb_power_get_property(struct power_supply *psy, val->intval = ret * 1700; /* 1 step = 1.7 mV */ return 0; case POWER_SUPPLY_PROP_CURRENT_MAX: - if (power->axp20x_id == AXP813_ID) - return axp813_get_current_max(power, &val->intval); - return axp20x_get_current_max(power, &val->intval); + ret = regmap_field_read(power->curr_lim_fld, &v); + if (ret) + return ret; + + val->intval = power->axp_data->curr_lim_table[v]; + return 0; case POWER_SUPPLY_PROP_CURRENT_NOW: if (IS_ENABLED(CONFIG_AXP20X_ADC)) { ret = iio_read_channel_processed(power->vbus_i, @@ -256,16 +208,15 @@ static int axp20x_usb_power_get_property(struct power_supply *psy, val->intval = POWER_SUPPLY_HEALTH_GOOD; - if (power->axp20x_id == AXP202_ID) { - ret = regmap_read(power->regmap, - AXP20X_USB_OTG_STATUS, &v); + if (power->vbus_valid_bit) { + ret = regmap_field_read(power->vbus_valid_bit, &v); if (ret) return ret; - if (!(v & AXP20X_USB_STATUS_VBUS_VALID)) - val->intval = - POWER_SUPPLY_HEALTH_UNSPEC_FAILURE; + if (v == 0) + val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE; } + break; case POWER_SUPPLY_PROP_PRESENT: val->intval = !!(input & AXP20X_PWR_STATUS_VBUS_PRESENT); @@ -280,16 +231,6 @@ static int axp20x_usb_power_get_property(struct power_supply *psy, return 0; } -static int axp813_usb_power_set_online(struct axp20x_usb_power *power, - int intval) -{ - int val = !intval << AXP20X_VBUS_PATH_SEL_OFFSET; - - return regmap_update_bits(power->regmap, - AXP20X_VBUS_IPSOUT_MGMT, - AXP20X_VBUS_PATH_SEL, val); -} - static int axp20x_usb_power_set_voltage_min(struct axp20x_usb_power *power, int intval) { @@ -316,50 +257,17 @@ static int axp20x_usb_power_set_voltage_min(struct axp20x_usb_power *power, return -EINVAL; } -static int axp813_usb_power_set_current_max(struct axp20x_usb_power *power, - int intval) +static int axp20x_usb_power_set_current_max(struct axp20x_usb_power *power, int intval) { - int val; + const unsigned int max = GENMASK(power->axp_data->curr_lim_fld.msb, + power->axp_data->curr_lim_fld.lsb); - switch (intval) { - case 900000: - return regmap_update_bits(power->regmap, - AXP20X_VBUS_IPSOUT_MGMT, - AXP20X_VBUS_CLIMIT_MASK, - AXP813_VBUS_CLIMIT_900mA); - case 1500000: - case 2000000: - case 2500000: - val = (intval - 1000000) / 500000; - return regmap_update_bits(power->regmap, - AXP20X_VBUS_IPSOUT_MGMT, - AXP20X_VBUS_CLIMIT_MASK, val); - default: + if (intval == -1) return -EINVAL; - } - - return -EINVAL; -} - -static int axp20x_usb_power_set_current_max(struct axp20x_usb_power *power, - int intval) -{ - int val; - switch (intval) { - case 100000: - if (power->axp20x_id == AXP221_ID) - return -EINVAL; - fallthrough; - case 500000: - case 900000: - val = (900000 - intval) / 400000; - return regmap_update_bits(power->regmap, - AXP20X_VBUS_IPSOUT_MGMT, - AXP20X_VBUS_CLIMIT_MASK, val); - default: - return -EINVAL; - } + for (unsigned int i = 0; i <= max; ++i) + if (power->axp_data->curr_lim_table[i] == intval) + return regmap_field_write(power->curr_lim_fld, i); return -EINVAL; } @@ -372,17 +280,15 @@ static int axp20x_usb_power_set_property(struct power_supply *psy, switch (psp) { case POWER_SUPPLY_PROP_ONLINE: - if (power->axp20x_id != AXP813_ID) + if (!power->vbus_disable_bit) return -EINVAL; - return axp813_usb_power_set_online(power, val->intval); + + return regmap_field_write(power->vbus_disable_bit, !val->intval); case POWER_SUPPLY_PROP_VOLTAGE_MIN: return axp20x_usb_power_set_voltage_min(power, val->intval); case POWER_SUPPLY_PROP_CURRENT_MAX: - if (power->axp20x_id == AXP813_ID) - return axp813_usb_power_set_current_max(power, - val->intval); return axp20x_usb_power_set_current_max(power, val->intval); default: @@ -405,7 +311,7 @@ static int axp20x_usb_power_prop_writeable(struct power_supply *psy, * the VBUS input offline. */ if (psp == POWER_SUPPLY_PROP_ONLINE) - return power->axp20x_id == AXP813_ID; + return power->vbus_disable_bit != NULL; return psp == POWER_SUPPLY_PROP_VOLTAGE_MIN || psp == POWER_SUPPLY_PROP_CURRENT_MAX; @@ -461,39 +367,81 @@ static const char * const axp22x_irq_names[] = { "VBUS_REMOVAL", }; -struct axp_data { - const struct power_supply_desc *power_desc; - const char * const *irq_names; - unsigned int num_irq_names; - enum axp20x_variants axp20x_id; +static int axp192_usb_curr_lim_table[] = { + -1, + -1, + 500000, + 100000, +}; + +static int axp20x_usb_curr_lim_table[] = { + 900000, + 500000, + 100000, + -1, +}; + +static int axp221_usb_curr_lim_table[] = { + 900000, + 500000, + -1, + -1, +}; + +static int axp813_usb_curr_lim_table[] = { + 900000, + 1500000, + 2000000, + 2500000, +}; + +static const struct axp_data axp192_data = { + .power_desc = &axp20x_usb_power_desc, + .irq_names = axp20x_irq_names, + .num_irq_names = ARRAY_SIZE(axp20x_irq_names), + .curr_lim_table = axp192_usb_curr_lim_table, + .curr_lim_fld = REG_FIELD(AXP20X_VBUS_IPSOUT_MGMT, 0, 1), + .vbus_valid_bit = REG_FIELD(AXP192_USB_OTG_STATUS, 2, 2), + .vbus_mon_bit = REG_FIELD(AXP20X_VBUS_MON, 3, 3), }; static const struct axp_data axp202_data = { .power_desc = &axp20x_usb_power_desc, .irq_names = axp20x_irq_names, .num_irq_names = ARRAY_SIZE(axp20x_irq_names), - .axp20x_id = AXP202_ID, + .curr_lim_table = axp20x_usb_curr_lim_table, + .curr_lim_fld = REG_FIELD(AXP20X_VBUS_IPSOUT_MGMT, 0, 1), + .vbus_valid_bit = REG_FIELD(AXP20X_USB_OTG_STATUS, 2, 2), + .vbus_mon_bit = REG_FIELD(AXP20X_VBUS_MON, 3, 3), }; static const struct axp_data axp221_data = { .power_desc = &axp22x_usb_power_desc, .irq_names = axp22x_irq_names, .num_irq_names = ARRAY_SIZE(axp22x_irq_names), - .axp20x_id = AXP221_ID, + .curr_lim_table = axp221_usb_curr_lim_table, + .curr_lim_fld = REG_FIELD(AXP20X_VBUS_IPSOUT_MGMT, 0, 1), + .vbus_needs_polling = true, }; static const struct axp_data axp223_data = { .power_desc = &axp22x_usb_power_desc, .irq_names = axp22x_irq_names, .num_irq_names = ARRAY_SIZE(axp22x_irq_names), - .axp20x_id = AXP223_ID, + .curr_lim_table = axp20x_usb_curr_lim_table, + .curr_lim_fld = REG_FIELD(AXP20X_VBUS_IPSOUT_MGMT, 0, 1), + .vbus_needs_polling = true, }; static const struct axp_data axp813_data = { .power_desc = &axp22x_usb_power_desc, .irq_names = axp22x_irq_names, .num_irq_names = ARRAY_SIZE(axp22x_irq_names), - .axp20x_id = AXP813_ID, + .curr_lim_table = axp813_usb_curr_lim_table, + .curr_lim_fld = REG_FIELD(AXP20X_VBUS_IPSOUT_MGMT, 0, 1), + .usb_bc_en_bit = REG_FIELD(AXP288_BC_GLOBAL, 0, 0), + .vbus_disable_bit = REG_FIELD(AXP20X_VBUS_IPSOUT_MGMT, 7, 7), + .vbus_needs_polling = true, }; #ifdef CONFIG_PM_SLEEP @@ -565,6 +513,26 @@ static int configure_adc_registers(struct axp20x_usb_power *power) AXP20X_ADC_EN1_VBUS_VOLT); } +static int axp20x_regmap_field_alloc_optional(struct device *dev, + struct regmap *regmap, + struct reg_field fdesc, + struct regmap_field **fieldp) +{ + struct regmap_field *field; + + if (fdesc.reg == 0) { + *fieldp = NULL; + return 0; + } + + field = devm_regmap_field_alloc(dev, regmap, fdesc); + if (IS_ERR(field)) + return PTR_ERR(field); + + *fieldp = field; + return 0; +} + static int axp20x_usb_power_probe(struct platform_device *pdev) { struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent); @@ -591,20 +559,47 @@ static int axp20x_usb_power_probe(struct platform_device *pdev) platform_set_drvdata(pdev, power); - power->axp20x_id = axp_data->axp20x_id; + power->axp_data = axp_data; power->regmap = axp20x->regmap; power->num_irqs = axp_data->num_irq_names; + power->curr_lim_fld = devm_regmap_field_alloc(&pdev->dev, power->regmap, + axp_data->curr_lim_fld); + if (IS_ERR(power->curr_lim_fld)) + return PTR_ERR(power->curr_lim_fld); + + ret = axp20x_regmap_field_alloc_optional(&pdev->dev, power->regmap, + axp_data->vbus_valid_bit, + &power->vbus_valid_bit); + if (ret) + return ret; + + ret = axp20x_regmap_field_alloc_optional(&pdev->dev, power->regmap, + axp_data->vbus_mon_bit, + &power->vbus_mon_bit); + if (ret) + return ret; + + ret = axp20x_regmap_field_alloc_optional(&pdev->dev, power->regmap, + axp_data->usb_bc_en_bit, + &power->usb_bc_en_bit); + if (ret) + return ret; + + ret = axp20x_regmap_field_alloc_optional(&pdev->dev, power->regmap, + axp_data->vbus_disable_bit, + &power->vbus_disable_bit); + if (ret) + return ret; + ret = devm_delayed_work_autocancel(&pdev->dev, &power->vbus_detect, axp20x_usb_power_poll_vbus); if (ret) return ret; - if (power->axp20x_id == AXP202_ID) { + if (power->vbus_mon_bit) { /* Enable vbus valid checking */ - ret = regmap_update_bits(power->regmap, AXP20X_VBUS_MON, - AXP20X_VBUS_MON_VBUS_VALID, - AXP20X_VBUS_MON_VBUS_VALID); + ret = regmap_field_write(power->vbus_mon_bit, 1); if (ret) return ret; @@ -617,10 +612,9 @@ static int axp20x_usb_power_probe(struct platform_device *pdev) return ret; } - if (power->axp20x_id == AXP813_ID) { + if (power->usb_bc_en_bit) { /* Enable USB Battery Charging specification detection */ - ret = regmap_update_bits(axp20x->regmap, AXP288_BC_GLOBAL, - AXP813_BC_EN, AXP813_BC_EN); + ret = regmap_field_write(power->usb_bc_en_bit, 1); if (ret) return ret; } @@ -659,6 +653,9 @@ static int axp20x_usb_power_probe(struct platform_device *pdev) static const struct of_device_id axp20x_usb_power_match[] = { { + .compatible = "x-powers,axp192-usb-power-supply", + .data = &axp192_data, + }, { .compatible = "x-powers,axp202-usb-power-supply", .data = &axp202_data, }, { diff --git a/drivers/power/supply/bd99954-charger.c b/drivers/power/supply/bd99954-charger.c index 250362e15c98ba2c18e23f5dccf4f3e23a8fcc56..086dcf4033c178fedf1459b6420aea93764c60f4 100644 --- a/drivers/power/supply/bd99954-charger.c +++ b/drivers/power/supply/bd99954-charger.c @@ -1077,7 +1077,7 @@ static struct i2c_driver bd9995x_driver = { .name = "bd9995x-charger", .of_match_table = bd9995x_of_match, }, - .probe_new = bd9995x_probe, + .probe = bd9995x_probe, }; module_i2c_driver(bd9995x_driver); diff --git a/drivers/power/supply/bq2415x_charger.c b/drivers/power/supply/bq2415x_charger.c index 349b69d634e66dfc266a2f679cd4f09f5904839b..6a4798a62588b4fbb9f86dbcfdda9cfe2cb22f59 100644 --- a/drivers/power/supply/bq2415x_charger.c +++ b/drivers/power/supply/bq2415x_charger.c @@ -1780,7 +1780,7 @@ static struct i2c_driver bq2415x_driver = { .of_match_table = of_match_ptr(bq2415x_of_match_table), .acpi_match_table = ACPI_PTR(bq2415x_i2c_acpi_match), }, - .probe_new = bq2415x_probe, + .probe = bq2415x_probe, .remove = bq2415x_remove, .id_table = bq2415x_i2c_id_table, }; diff --git a/drivers/power/supply/bq24190_charger.c b/drivers/power/supply/bq24190_charger.c index dc33f00fcc0682a3c69ead86186df4219a1cd879..ef8235848f569255dc99627a382cf59dab67d4a7 100644 --- a/drivers/power/supply/bq24190_charger.c +++ b/drivers/power/supply/bq24190_charger.c @@ -2034,7 +2034,7 @@ static const struct of_device_id bq24190_of_match[] = { MODULE_DEVICE_TABLE(of, bq24190_of_match); static struct i2c_driver bq24190_driver = { - .probe_new = bq24190_probe, + .probe = bq24190_probe, .remove = bq24190_remove, .shutdown = bq24190_shutdown, .id_table = bq24190_i2c_ids, diff --git a/drivers/power/supply/bq24257_charger.c b/drivers/power/supply/bq24257_charger.c index 45e4ba30da98c8bbcd233180e5c1a692ba29e9fd..2852860abf861c80cc207a1be8ab272f1184dfaa 100644 --- a/drivers/power/supply/bq24257_charger.c +++ b/drivers/power/supply/bq24257_charger.c @@ -1165,7 +1165,7 @@ static struct i2c_driver bq24257_driver = { .acpi_match_table = ACPI_PTR(bq24257_acpi_match), .pm = &bq24257_pm, }, - .probe_new = bq24257_probe, + .probe = bq24257_probe, .remove = bq24257_remove, .id_table = bq24257_i2c_ids, }; diff --git a/drivers/power/supply/bq24735-charger.c b/drivers/power/supply/bq24735-charger.c index cfca3a82d5a8d0d0bddf4a277f8b81ab0eb9a494..8efceeae864c81beda3b8c62198ab2769c81cdee 100644 --- a/drivers/power/supply/bq24735-charger.c +++ b/drivers/power/supply/bq24735-charger.c @@ -505,7 +505,7 @@ static struct i2c_driver bq24735_charger_driver = { .name = "bq24735-charger", .of_match_table = bq24735_match_ids, }, - .probe_new = bq24735_charger_probe, + .probe = bq24735_charger_probe, .id_table = bq24735_charger_id, }; diff --git a/drivers/power/supply/bq2515x_charger.c b/drivers/power/supply/bq2515x_charger.c index da224ae8dc6155e6e1b97bbd5e1cd5f1e6864efa..1dbacc9b015d75209067d457394853fdb4838d6d 100644 --- a/drivers/power/supply/bq2515x_charger.c +++ b/drivers/power/supply/bq2515x_charger.c @@ -1158,7 +1158,7 @@ static struct i2c_driver bq2515x_driver = { .name = "bq2515x-charger", .of_match_table = bq2515x_of_match, }, - .probe_new = bq2515x_probe, + .probe = bq2515x_probe, .id_table = bq2515x_i2c_ids, }; module_i2c_driver(bq2515x_driver); diff --git a/drivers/power/supply/bq256xx_charger.c b/drivers/power/supply/bq256xx_charger.c index e624834ae66ce98bccd57f3c5c5841c8db9efcc9..82d3cd5ee2f92f27f135469d8fe8f9468f7dee8f 100644 --- a/drivers/power/supply/bq256xx_charger.c +++ b/drivers/power/supply/bq256xx_charger.c @@ -41,6 +41,9 @@ #define BQ256XX_IINDPM_MAX_uA 3200000 #define BQ256XX_IINDPM_DEF_uA 2400000 +#define BQ256XX_TS_IGNORE BIT(6) +#define BQ256XX_TS_IGNORE_SHIFT 6 + #define BQ256XX_VINDPM_MASK GENMASK(3, 0) #define BQ256XX_VINDPM_STEP_uV 100000 #define BQ256XX_VINDPM_OFFSET_uV 3900000 @@ -156,6 +159,7 @@ * @vindpm: input voltage limit * @ichg_max: maximum fast charge current * @vbatreg_max: maximum charge voltage + * @ts_ignore: TS_IGNORE flag */ struct bq256xx_init_data { u32 ichg; @@ -166,6 +170,7 @@ struct bq256xx_init_data { u32 vindpm; u32 ichg_max; u32 vbatreg_max; + bool ts_ignore; }; /** @@ -263,6 +268,7 @@ struct bq256xx_device { * @bq256xx_set_iprechg: pointer to instance specific set_iprechg function * @bq256xx_set_vindpm: pointer to instance specific set_vindpm function * @bq256xx_set_charge_type: pointer to instance specific set_charge_type function + * @bq256xx_set_ts_ignore: pointer to instance specific set_ts_ignore function * * @bq256xx_def_ichg: default ichg value in microamps * @bq256xx_def_iindpm: default iindpm value in microamps @@ -295,6 +301,7 @@ struct bq256xx_chip_info { int (*bq256xx_set_iprechg)(struct bq256xx_device *bq, int iprechg); int (*bq256xx_set_vindpm)(struct bq256xx_device *bq, int vindpm); int (*bq256xx_set_charge_type)(struct bq256xx_device *bq, int type); + int (*bq256xx_set_ts_ignore)(struct bq256xx_device *bq, bool ts_ignore); int bq256xx_def_ichg; int bq256xx_def_iindpm; @@ -696,6 +703,12 @@ static int bq25601d_set_chrg_volt(struct bq256xx_device *bq, int vbatreg) BQ256XX_VBATREG_BIT_SHIFT); } +static int bq256xx_set_ts_ignore(struct bq256xx_device *bq, bool ts_ignore) +{ + return regmap_update_bits(bq->regmap, BQ256XX_INPUT_CURRENT_LIMIT, + BQ256XX_TS_IGNORE, (ts_ignore ? 1 : 0) << BQ256XX_TS_IGNORE_SHIFT); +} + static int bq256xx_get_prechrg_curr(struct bq256xx_device *bq) { unsigned int prechg_and_term_curr_lim; @@ -1312,6 +1325,7 @@ static const struct bq256xx_chip_info bq256xx_chip_info_tbl[] = { .bq256xx_get_iterm = bq256xx_get_term_curr, .bq256xx_get_iprechg = bq256xx_get_prechrg_curr, .bq256xx_get_vindpm = bq256xx_get_input_volt_lim, + .bq256xx_set_ts_ignore = NULL, .bq256xx_set_ichg = bq256xx_set_ichg_curr, .bq256xx_set_iindpm = bq256xx_set_input_curr_lim, @@ -1351,6 +1365,7 @@ static const struct bq256xx_chip_info bq256xx_chip_info_tbl[] = { .bq256xx_set_iprechg = bq256xx_set_prechrg_curr, .bq256xx_set_vindpm = bq256xx_set_input_volt_lim, .bq256xx_set_charge_type = bq256xx_set_charge_type, + .bq256xx_set_ts_ignore = NULL, .bq256xx_def_ichg = BQ2560X_ICHG_DEF_uA, .bq256xx_def_iindpm = BQ256XX_IINDPM_DEF_uA, @@ -1382,6 +1397,7 @@ static const struct bq256xx_chip_info bq256xx_chip_info_tbl[] = { .bq256xx_set_iprechg = bq256xx_set_prechrg_curr, .bq256xx_set_vindpm = bq256xx_set_input_volt_lim, .bq256xx_set_charge_type = bq256xx_set_charge_type, + .bq256xx_set_ts_ignore = NULL, .bq256xx_def_ichg = BQ2560X_ICHG_DEF_uA, .bq256xx_def_iindpm = BQ256XX_IINDPM_DEF_uA, @@ -1413,6 +1429,7 @@ static const struct bq256xx_chip_info bq256xx_chip_info_tbl[] = { .bq256xx_set_iprechg = bq256xx_set_prechrg_curr, .bq256xx_set_vindpm = bq256xx_set_input_volt_lim, .bq256xx_set_charge_type = bq256xx_set_charge_type, + .bq256xx_set_ts_ignore = NULL, .bq256xx_def_ichg = BQ2560X_ICHG_DEF_uA, .bq256xx_def_iindpm = BQ256XX_IINDPM_DEF_uA, @@ -1444,6 +1461,7 @@ static const struct bq256xx_chip_info bq256xx_chip_info_tbl[] = { .bq256xx_set_iprechg = bq256xx_set_prechrg_curr, .bq256xx_set_vindpm = bq256xx_set_input_volt_lim, .bq256xx_set_charge_type = bq256xx_set_charge_type, + .bq256xx_set_ts_ignore = bq256xx_set_ts_ignore, .bq256xx_def_ichg = BQ25611D_ICHG_DEF_uA, .bq256xx_def_iindpm = BQ256XX_IINDPM_DEF_uA, @@ -1475,6 +1493,7 @@ static const struct bq256xx_chip_info bq256xx_chip_info_tbl[] = { .bq256xx_set_iprechg = bq25618_619_set_prechrg_curr, .bq256xx_set_vindpm = bq256xx_set_input_volt_lim, .bq256xx_set_charge_type = bq256xx_set_charge_type, + .bq256xx_set_ts_ignore = bq256xx_set_ts_ignore, .bq256xx_def_ichg = BQ25618_ICHG_DEF_uA, .bq256xx_def_iindpm = BQ256XX_IINDPM_DEF_uA, @@ -1506,6 +1525,7 @@ static const struct bq256xx_chip_info bq256xx_chip_info_tbl[] = { .bq256xx_set_iprechg = bq25618_619_set_prechrg_curr, .bq256xx_set_vindpm = bq256xx_set_input_volt_lim, .bq256xx_set_charge_type = bq256xx_set_charge_type, + .bq256xx_set_ts_ignore = bq256xx_set_ts_ignore, .bq256xx_def_ichg = BQ25618_ICHG_DEF_uA, .bq256xx_def_iindpm = BQ256XX_IINDPM_DEF_uA, @@ -1622,6 +1642,12 @@ static int bq256xx_hw_init(struct bq256xx_device *bq) if (ret) return ret; + if (bq->chip_info->bq256xx_set_ts_ignore) { + ret = bq->chip_info->bq256xx_set_ts_ignore(bq, bq->init_data.ts_ignore); + if (ret) + return ret; + } + power_supply_put_battery_info(bq->charger, bat_info); return 0; @@ -1656,6 +1682,8 @@ static int bq256xx_parse_dt(struct bq256xx_device *bq, if (ret) bq->init_data.iindpm = bq->chip_info->bq256xx_def_iindpm; + bq->init_data.ts_ignore = device_property_read_bool(bq->dev, "ti,no-thermistor"); + return 0; } @@ -1784,7 +1812,7 @@ static struct i2c_driver bq256xx_driver = { .of_match_table = bq256xx_of_match, .acpi_match_table = bq256xx_acpi_match, }, - .probe_new = bq256xx_probe, + .probe = bq256xx_probe, .id_table = bq256xx_i2c_ids, }; module_i2c_driver(bq256xx_driver); diff --git a/drivers/power/supply/bq25890_charger.c b/drivers/power/supply/bq25890_charger.c index f8636cf86505a7749eb7835eb422eda819137cf6..03fa11a1c9b63a97ad727a135560eee75a9c64f2 100644 --- a/drivers/power/supply/bq25890_charger.c +++ b/drivers/power/supply/bq25890_charger.c @@ -1649,7 +1649,7 @@ static struct i2c_driver bq25890_driver = { .acpi_match_table = ACPI_PTR(bq25890_acpi_match), .pm = &bq25890_pm, }, - .probe_new = bq25890_probe, + .probe = bq25890_probe, .remove = bq25890_remove, .shutdown = bq25890_shutdown, .id_table = bq25890_i2c_ids, diff --git a/drivers/power/supply/bq25980_charger.c b/drivers/power/supply/bq25980_charger.c index a59d9762bc91684aa73fa3bd49d40bb5c7fa0eb1..d8411722266f518a5e1894e93e70b04c0d245661 100644 --- a/drivers/power/supply/bq25980_charger.c +++ b/drivers/power/supply/bq25980_charger.c @@ -1287,7 +1287,7 @@ static struct i2c_driver bq25980_driver = { .name = "bq25980-charger", .of_match_table = bq25980_of_match, }, - .probe_new = bq25980_probe, + .probe = bq25980_probe, .id_table = bq25980_i2c_ids, }; module_i2c_driver(bq25980_driver); diff --git a/drivers/power/supply/bq27xxx_battery_i2c.c b/drivers/power/supply/bq27xxx_battery_i2c.c index 6d3c748763390675f759388cc1ceef3d73afee02..9b5475590518fb23153acdc2a9ceea403bc73fef 100644 --- a/drivers/power/supply/bq27xxx_battery_i2c.c +++ b/drivers/power/supply/bq27xxx_battery_i2c.c @@ -296,7 +296,7 @@ static struct i2c_driver bq27xxx_battery_i2c_driver = { .name = "bq27xxx-battery", .of_match_table = of_match_ptr(bq27xxx_battery_i2c_of_match_table), }, - .probe_new = bq27xxx_battery_i2c_probe, + .probe = bq27xxx_battery_i2c_probe, .remove = bq27xxx_battery_i2c_remove, .id_table = bq27xxx_i2c_id_table, }; diff --git a/drivers/power/supply/cros_peripheral_charger.c b/drivers/power/supply/cros_peripheral_charger.c index 1379afd9698dfe88eb2c2aba56ace36ecf5a5f99..a204f2355be48afac9a1dca84e20906c800b4579 100644 --- a/drivers/power/supply/cros_peripheral_charger.c +++ b/drivers/power/supply/cros_peripheral_charger.c @@ -227,8 +227,7 @@ static int cros_pchg_get_prop(struct power_supply *psy, return 0; } -static int cros_pchg_event(const struct charger_data *charger, - unsigned long host_event) +static int cros_pchg_event(const struct charger_data *charger) { int i; @@ -256,7 +255,7 @@ static int cros_ec_notify(struct notifier_block *nb, if (!(host_event & EC_MKBP_PCHG_DEVICE_EVENT)) return NOTIFY_DONE; - return cros_pchg_event(charger, host_event); + return cros_pchg_event(charger); } static int cros_pchg_probe(struct platform_device *pdev) @@ -281,6 +280,8 @@ static int cros_pchg_probe(struct platform_device *pdev) charger->ec_dev = ec_dev; charger->ec_device = ec_device; + platform_set_drvdata(pdev, charger); + ret = cros_pchg_port_count(charger); if (ret <= 0) { /* @@ -349,9 +350,27 @@ static int cros_pchg_probe(struct platform_device *pdev) return 0; } +#ifdef CONFIG_PM_SLEEP +static int __maybe_unused cros_pchg_resume(struct device *dev) +{ + struct charger_data *charger = dev_get_drvdata(dev); + + /* + * Sync all ports on resume in case reports from EC are lost during + * the last suspend. + */ + cros_pchg_event(charger); + + return 0; +} +#endif + +static SIMPLE_DEV_PM_OPS(cros_pchg_pm_ops, NULL, cros_pchg_resume); + static struct platform_driver cros_pchg_driver = { .driver = { .name = DRV_NAME, + .pm = &cros_pchg_pm_ops, }, .probe = cros_pchg_probe }; diff --git a/drivers/power/supply/cw2015_battery.c b/drivers/power/supply/cw2015_battery.c index 473522b4326adc5f84aebfbf8962e2b7e2ef1089..bb29e9ebd24a8eb2b96f5a1513f02419aa14d043 100644 --- a/drivers/power/supply/cw2015_battery.c +++ b/drivers/power/supply/cw2015_battery.c @@ -747,7 +747,7 @@ static struct i2c_driver cw_bat_driver = { .of_match_table = cw2015_of_match, .pm = &cw_bat_pm_ops, }, - .probe_new = cw_bat_probe, + .probe = cw_bat_probe, .id_table = cw_bat_id_table, }; diff --git a/drivers/power/supply/ds2782_battery.c b/drivers/power/supply/ds2782_battery.c index 9b9619246902c66e5541302b19e7693a558155c6..85aa9c465aa4e18536e9e7bfdd2ad2f353d442b3 100644 --- a/drivers/power/supply/ds2782_battery.c +++ b/drivers/power/supply/ds2782_battery.c @@ -458,7 +458,7 @@ static struct i2c_driver ds278x_battery_driver = { .name = "ds2782-battery", .pm = &ds278x_battery_pm_ops, }, - .probe_new = ds278x_battery_probe, + .probe = ds278x_battery_probe, .remove = ds278x_battery_remove, .id_table = ds278x_id, }; diff --git a/drivers/power/supply/ip5xxx_power.c b/drivers/power/supply/ip5xxx_power.c index 00221e9c0bfccf90a95880e9832e8152788103c7..82263646ddc61f00794081f3fd1e63cee923a6a6 100644 --- a/drivers/power/supply/ip5xxx_power.c +++ b/drivers/power/supply/ip5xxx_power.c @@ -625,7 +625,7 @@ static const struct of_device_id ip5xxx_power_of_match[] = { MODULE_DEVICE_TABLE(of, ip5xxx_power_of_match); static struct i2c_driver ip5xxx_power_driver = { - .probe_new = ip5xxx_power_probe, + .probe = ip5xxx_power_probe, .driver = { .name = "ip5xxx-power", .of_match_table = ip5xxx_power_of_match, diff --git a/drivers/power/supply/lp8727_charger.c b/drivers/power/supply/lp8727_charger.c index dc42d354b892daf641e1a7c6c1cd02d6b9949bb9..0875391f7ac6b4e11be854c74ad6dba0a3bbfcbd 100644 --- a/drivers/power/supply/lp8727_charger.c +++ b/drivers/power/supply/lp8727_charger.c @@ -615,7 +615,7 @@ static struct i2c_driver lp8727_driver = { .name = "lp8727", .of_match_table = of_match_ptr(lp8727_dt_ids), }, - .probe_new = lp8727_probe, + .probe = lp8727_probe, .remove = lp8727_remove, .id_table = lp8727_ids, }; diff --git a/drivers/power/supply/ltc2941-battery-gauge.c b/drivers/power/supply/ltc2941-battery-gauge.c index d3fb42825983939fdd9335a6f0fc0174f43662a4..cad39a8f829dd1f25e81e333ac6286df4eae7847 100644 --- a/drivers/power/supply/ltc2941-battery-gauge.c +++ b/drivers/power/supply/ltc2941-battery-gauge.c @@ -635,7 +635,7 @@ static struct i2c_driver ltc294x_driver = { .of_match_table = ltc294x_i2c_of_match, .pm = LTC294X_PM_OPS, }, - .probe_new = ltc294x_i2c_probe, + .probe = ltc294x_i2c_probe, .shutdown = ltc294x_i2c_shutdown, .id_table = ltc294x_i2c_id, }; diff --git a/drivers/power/supply/ltc4162-l-charger.c b/drivers/power/supply/ltc4162-l-charger.c index 285580845e2f9544bb019b480570a38ea12bac0a..ec5b4a20ad43d799871a1d22a7409a83cc065225 100644 --- a/drivers/power/supply/ltc4162-l-charger.c +++ b/drivers/power/supply/ltc4162-l-charger.c @@ -915,7 +915,7 @@ static const struct of_device_id ltc4162l_of_match[] __maybe_unused = { MODULE_DEVICE_TABLE(of, ltc4162l_of_match); static struct i2c_driver ltc4162l_driver = { - .probe_new = ltc4162l_probe, + .probe = ltc4162l_probe, .alert = ltc4162l_alert, .id_table = ltc4162l_i2c_id_table, .driver = { diff --git a/drivers/power/supply/max14656_charger_detector.c b/drivers/power/supply/max14656_charger_detector.c index 0d0180fcfa63bb8918432bd10df331df2e8d1070..fbdf12cf64ebd4c9738008b46211244c06a676cb 100644 --- a/drivers/power/supply/max14656_charger_detector.c +++ b/drivers/power/supply/max14656_charger_detector.c @@ -316,7 +316,7 @@ static struct i2c_driver max14656_i2c_driver = { .name = "max14656", .of_match_table = max14656_match_table, }, - .probe_new = max14656_probe, + .probe = max14656_probe, .id_table = max14656_id, }; module_i2c_driver(max14656_i2c_driver); diff --git a/drivers/power/supply/max17040_battery.c b/drivers/power/supply/max17040_battery.c index d1075959dd466b402730e0e16e04d9662fb65631..22ea7de47a5370657c1085fabf9fff4772925c24 100644 --- a/drivers/power/supply/max17040_battery.c +++ b/drivers/power/supply/max17040_battery.c @@ -599,7 +599,7 @@ static struct i2c_driver max17040_i2c_driver = { .of_match_table = max17040_of_match, .pm = MAX17040_PM_OPS, }, - .probe_new = max17040_probe, + .probe = max17040_probe, .id_table = max17040_id, }; module_i2c_driver(max17040_i2c_driver); diff --git a/drivers/power/supply/max17042_battery.c b/drivers/power/supply/max17042_battery.c index 89cabe8ed3b06edc9b3c755ec03f43ea12a5ee8c..17ac2ab78c4e4c3782298749840a478e6c769f13 100644 --- a/drivers/power/supply/max17042_battery.c +++ b/drivers/power/supply/max17042_battery.c @@ -499,11 +499,6 @@ static int max17042_property_is_writeable(struct power_supply *psy, return ret; } -static void max17042_external_power_changed(struct power_supply *psy) -{ - power_supply_changed(psy); -} - static int max17042_write_verify_reg(struct regmap *map, u8 reg, u32 value) { int retries = 8; @@ -1016,7 +1011,7 @@ static const struct power_supply_desc max17042_psy_desc = { .get_property = max17042_get_property, .set_property = max17042_set_property, .property_is_writeable = max17042_property_is_writeable, - .external_power_changed = max17042_external_power_changed, + .external_power_changed = power_supply_changed, .properties = max17042_battery_props, .num_properties = ARRAY_SIZE(max17042_battery_props), }; @@ -1220,7 +1215,7 @@ static struct i2c_driver max17042_i2c_driver = { .of_match_table = of_match_ptr(max17042_dt_match), .pm = &max17042_pm_ops, }, - .probe_new = max17042_probe, + .probe = max17042_probe, .id_table = max17042_id, }; module_i2c_driver(max17042_i2c_driver); diff --git a/drivers/power/supply/max77976_charger.c b/drivers/power/supply/max77976_charger.c index 4fed745119312532f7f42bc838cbc62357a92578..99659dc8f5a6df48e0e9bd26960f0e4448f41f34 100644 --- a/drivers/power/supply/max77976_charger.c +++ b/drivers/power/supply/max77976_charger.c @@ -499,7 +499,7 @@ static struct i2c_driver max77976_driver = { .name = MAX77976_DRIVER_NAME, .of_match_table = max77976_of_id, }, - .probe_new = max77976_probe, + .probe = max77976_probe, .id_table = max77976_i2c_id, }; module_i2c_driver(max77976_driver); diff --git a/drivers/power/supply/power_supply_hwmon.c b/drivers/power/supply/power_supply_hwmon.c index a48aa4afb828dba652655db6cd4783f93a4e9d23..c97893d4c25eb183a7857316aca481752bd4c009 100644 --- a/drivers/power/supply/power_supply_hwmon.c +++ b/drivers/power/supply/power_supply_hwmon.c @@ -293,7 +293,7 @@ static const struct hwmon_ops power_supply_hwmon_ops = { .read_string = power_supply_hwmon_read_string, }; -static const struct hwmon_channel_info *power_supply_hwmon_info[] = { +static const struct hwmon_channel_info * const power_supply_hwmon_info[] = { HWMON_CHANNEL_INFO(temp, HWMON_T_LABEL | HWMON_T_INPUT | diff --git a/drivers/power/supply/power_supply_leds.c b/drivers/power/supply/power_supply_leds.c index 0674483279d77c2b7bd1e8e687839332074d1ca8..c7db29d5fcb80567edb4749c89ef4f8724dd67e5 100644 --- a/drivers/power/supply/power_supply_leds.c +++ b/drivers/power/supply/power_supply_leds.c @@ -22,8 +22,6 @@ static void power_supply_update_bat_leds(struct power_supply *psy) { union power_supply_propval status; - unsigned long delay_on = 0; - unsigned long delay_off = 0; if (power_supply_get_property(psy, POWER_SUPPLY_PROP_STATUS, &status)) return; @@ -43,8 +41,7 @@ static void power_supply_update_bat_leds(struct power_supply *psy) led_trigger_event(psy->charging_full_trig, LED_FULL); led_trigger_event(psy->charging_trig, LED_FULL); led_trigger_event(psy->full_trig, LED_OFF); - led_trigger_blink(psy->charging_blink_full_solid_trig, - &delay_on, &delay_off); + led_trigger_blink(psy->charging_blink_full_solid_trig, 0, 0); break; default: led_trigger_event(psy->charging_full_trig, LED_OFF); diff --git a/drivers/power/supply/qcom_pmi8998_charger.c b/drivers/power/supply/qcom_pmi8998_charger.c new file mode 100644 index 0000000000000000000000000000000000000000..d16c5ee172496507700a3d8107d6f350dd7e020e --- /dev/null +++ b/drivers/power/supply/qcom_pmi8998_charger.c @@ -0,0 +1,1059 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2023, Linaro Ltd. + * Author: Caleb Connolly + * + * This driver is for the switch-mode battery charger and boost + * hardware found in pmi8998 and related PMICs. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* clang-format off */ +#define BATTERY_CHARGER_STATUS_1 0x06 +#define BVR_INITIAL_RAMP_BIT BIT(7) +#define CC_SOFT_TERMINATE_BIT BIT(6) +#define STEP_CHARGING_STATUS_SHIFT 3 +#define STEP_CHARGING_STATUS_MASK GENMASK(5, 3) +#define BATTERY_CHARGER_STATUS_MASK GENMASK(2, 0) + +#define BATTERY_CHARGER_STATUS_2 0x07 +#define INPUT_CURRENT_LIMITED_BIT BIT(7) +#define CHARGER_ERROR_STATUS_SFT_EXPIRE_BIT BIT(6) +#define CHARGER_ERROR_STATUS_BAT_OV_BIT BIT(5) +#define CHARGER_ERROR_STATUS_BAT_TERM_MISSING_BIT BIT(4) +#define BAT_TEMP_STATUS_MASK GENMASK(3, 0) +#define BAT_TEMP_STATUS_SOFT_LIMIT_MASK GENMASK(3, 2) +#define BAT_TEMP_STATUS_HOT_SOFT_LIMIT_BIT BIT(3) +#define BAT_TEMP_STATUS_COLD_SOFT_LIMIT_BIT BIT(2) +#define BAT_TEMP_STATUS_TOO_HOT_BIT BIT(1) +#define BAT_TEMP_STATUS_TOO_COLD_BIT BIT(0) + +#define BATTERY_CHARGER_STATUS_4 0x0A +#define CHARGE_CURRENT_POST_JEITA_MASK GENMASK(7, 0) + +#define BATTERY_CHARGER_STATUS_7 0x0D +#define ENABLE_TRICKLE_BIT BIT(7) +#define ENABLE_PRE_CHARGING_BIT BIT(6) +#define ENABLE_FAST_CHARGING_BIT BIT(5) +#define ENABLE_FULLON_MODE_BIT BIT(4) +#define TOO_COLD_ADC_BIT BIT(3) +#define TOO_HOT_ADC_BIT BIT(2) +#define HOT_SL_ADC_BIT BIT(1) +#define COLD_SL_ADC_BIT BIT(0) + +#define CHARGING_ENABLE_CMD 0x42 +#define CHARGING_ENABLE_CMD_BIT BIT(0) + +#define CHGR_CFG2 0x51 +#define CHG_EN_SRC_BIT BIT(7) +#define CHG_EN_POLARITY_BIT BIT(6) +#define PRETOFAST_TRANSITION_CFG_BIT BIT(5) +#define BAT_OV_ECC_BIT BIT(4) +#define I_TERM_BIT BIT(3) +#define AUTO_RECHG_BIT BIT(2) +#define EN_ANALOG_DROP_IN_VBATT_BIT BIT(1) +#define CHARGER_INHIBIT_BIT BIT(0) + +#define PRE_CHARGE_CURRENT_CFG 0x60 +#define PRE_CHARGE_CURRENT_SETTING_MASK GENMASK(5, 0) + +#define FAST_CHARGE_CURRENT_CFG 0x61 +#define FAST_CHARGE_CURRENT_SETTING_MASK GENMASK(7, 0) + +#define FLOAT_VOLTAGE_CFG 0x70 +#define FLOAT_VOLTAGE_SETTING_MASK GENMASK(7, 0) + +#define FG_UPDATE_CFG_2_SEL 0x7D +#define SOC_LT_OTG_THRESH_SEL_BIT BIT(3) +#define SOC_LT_CHG_RECHARGE_THRESH_SEL_BIT BIT(2) +#define VBT_LT_CHG_RECHARGE_THRESH_SEL_BIT BIT(1) +#define IBT_LT_CHG_TERM_THRESH_SEL_BIT BIT(0) + +#define JEITA_EN_CFG 0x90 +#define JEITA_EN_HARDLIMIT_BIT BIT(4) +#define JEITA_EN_HOT_SL_FCV_BIT BIT(3) +#define JEITA_EN_COLD_SL_FCV_BIT BIT(2) +#define JEITA_EN_HOT_SL_CCC_BIT BIT(1) +#define JEITA_EN_COLD_SL_CCC_BIT BIT(0) + +#define INT_RT_STS 0x310 +#define TYPE_C_CHANGE_RT_STS_BIT BIT(7) +#define USBIN_ICL_CHANGE_RT_STS_BIT BIT(6) +#define USBIN_SOURCE_CHANGE_RT_STS_BIT BIT(5) +#define USBIN_PLUGIN_RT_STS_BIT BIT(4) +#define USBIN_OV_RT_STS_BIT BIT(3) +#define USBIN_UV_RT_STS_BIT BIT(2) +#define USBIN_LT_3P6V_RT_STS_BIT BIT(1) +#define USBIN_COLLAPSE_RT_STS_BIT BIT(0) + +#define OTG_CFG 0x153 +#define OTG_RESERVED_MASK GENMASK(7, 6) +#define DIS_OTG_ON_TLIM_BIT BIT(5) +#define QUICKSTART_OTG_FASTROLESWAP_BIT BIT(4) +#define INCREASE_DFP_TIME_BIT BIT(3) +#define ENABLE_OTG_IN_DEBUG_MODE_BIT BIT(2) +#define OTG_EN_SRC_CFG_BIT BIT(1) +#define CONCURRENT_MODE_CFG_BIT BIT(0) + +#define OTG_ENG_OTG_CFG 0x1C0 +#define ENG_BUCKBOOST_HALT1_8_MODE_BIT BIT(0) + +#define APSD_STATUS 0x307 +#define APSD_STATUS_7_BIT BIT(7) +#define HVDCP_CHECK_TIMEOUT_BIT BIT(6) +#define SLOW_PLUGIN_TIMEOUT_BIT BIT(5) +#define ENUMERATION_DONE_BIT BIT(4) +#define VADP_CHANGE_DONE_AFTER_AUTH_BIT BIT(3) +#define QC_AUTH_DONE_STATUS_BIT BIT(2) +#define QC_CHARGER_BIT BIT(1) +#define APSD_DTC_STATUS_DONE_BIT BIT(0) + +#define APSD_RESULT_STATUS 0x308 +#define ICL_OVERRIDE_LATCH_BIT BIT(7) +#define APSD_RESULT_STATUS_MASK GENMASK(6, 0) +#define QC_3P0_BIT BIT(6) +#define QC_2P0_BIT BIT(5) +#define FLOAT_CHARGER_BIT BIT(4) +#define DCP_CHARGER_BIT BIT(3) +#define CDP_CHARGER_BIT BIT(2) +#define OCP_CHARGER_BIT BIT(1) +#define SDP_CHARGER_BIT BIT(0) + +#define TYPE_C_STATUS_1 0x30B +#define UFP_TYPEC_MASK GENMASK(7, 5) +#define UFP_TYPEC_RDSTD_BIT BIT(7) +#define UFP_TYPEC_RD1P5_BIT BIT(6) +#define UFP_TYPEC_RD3P0_BIT BIT(5) +#define UFP_TYPEC_FMB_255K_BIT BIT(4) +#define UFP_TYPEC_FMB_301K_BIT BIT(3) +#define UFP_TYPEC_FMB_523K_BIT BIT(2) +#define UFP_TYPEC_FMB_619K_BIT BIT(1) +#define UFP_TYPEC_OPEN_OPEN_BIT BIT(0) + +#define TYPE_C_STATUS_2 0x30C +#define DFP_RA_OPEN_BIT BIT(7) +#define TIMER_STAGE_BIT BIT(6) +#define EXIT_UFP_MODE_BIT BIT(5) +#define EXIT_DFP_MODE_BIT BIT(4) +#define DFP_TYPEC_MASK GENMASK(3, 0) +#define DFP_RD_OPEN_BIT BIT(3) +#define DFP_RD_RA_VCONN_BIT BIT(2) +#define DFP_RD_RD_BIT BIT(1) +#define DFP_RA_RA_BIT BIT(0) + +#define TYPE_C_STATUS_3 0x30D +#define ENABLE_BANDGAP_BIT BIT(7) +#define U_USB_GND_NOVBUS_BIT BIT(6) +#define U_USB_FLOAT_NOVBUS_BIT BIT(5) +#define U_USB_GND_BIT BIT(4) +#define U_USB_FMB1_BIT BIT(3) +#define U_USB_FLOAT1_BIT BIT(2) +#define U_USB_FMB2_BIT BIT(1) +#define U_USB_FLOAT2_BIT BIT(0) + +#define TYPE_C_STATUS_4 0x30E +#define UFP_DFP_MODE_STATUS_BIT BIT(7) +#define TYPEC_VBUS_STATUS_BIT BIT(6) +#define TYPEC_VBUS_ERROR_STATUS_BIT BIT(5) +#define TYPEC_DEBOUNCE_DONE_STATUS_BIT BIT(4) +#define TYPEC_UFP_AUDIO_ADAPT_STATUS_BIT BIT(3) +#define TYPEC_VCONN_OVERCURR_STATUS_BIT BIT(2) +#define CC_ORIENTATION_BIT BIT(1) +#define CC_ATTACHED_BIT BIT(0) + +#define TYPE_C_STATUS_5 0x30F +#define TRY_SOURCE_FAILED_BIT BIT(6) +#define TRY_SINK_FAILED_BIT BIT(5) +#define TIMER_STAGE_2_BIT BIT(4) +#define TYPEC_LEGACY_CABLE_STATUS_BIT BIT(3) +#define TYPEC_NONCOMP_LEGACY_CABLE_STATUS_BIT BIT(2) +#define TYPEC_TRYSOURCE_DETECT_STATUS_BIT BIT(1) +#define TYPEC_TRYSINK_DETECT_STATUS_BIT BIT(0) + +#define CMD_APSD 0x341 +#define ICL_OVERRIDE_BIT BIT(1) +#define APSD_RERUN_BIT BIT(0) + +#define TYPE_C_CFG 0x358 +#define APSD_START_ON_CC_BIT BIT(7) +#define WAIT_FOR_APSD_BIT BIT(6) +#define FACTORY_MODE_DETECTION_EN_BIT BIT(5) +#define FACTORY_MODE_ICL_3A_4A_BIT BIT(4) +#define FACTORY_MODE_DIS_CHGING_CFG_BIT BIT(3) +#define SUSPEND_NON_COMPLIANT_CFG_BIT BIT(2) +#define VCONN_OC_CFG_BIT BIT(1) +#define TYPE_C_OR_U_USB_BIT BIT(0) + +#define TYPE_C_CFG_2 0x359 +#define TYPE_C_DFP_CURRSRC_MODE_BIT BIT(7) +#define DFP_CC_1P4V_OR_1P6V_BIT BIT(6) +#define VCONN_SOFTSTART_CFG_MASK GENMASK(5, 4) +#define EN_TRY_SOURCE_MODE_BIT BIT(3) +#define USB_FACTORY_MODE_ENABLE_BIT BIT(2) +#define TYPE_C_UFP_MODE_BIT BIT(1) +#define EN_80UA_180UA_CUR_SOURCE_BIT BIT(0) + +#define TYPE_C_CFG_3 0x35A +#define TVBUS_DEBOUNCE_BIT BIT(7) +#define TYPEC_LEGACY_CABLE_INT_EN_BIT BIT(6) +#define TYPEC_NONCOMPLIANT_LEGACY_CABLE_INT_EN_B BIT(5) +#define TYPEC_TRYSOURCE_DETECT_INT_EN_BIT BIT(4) +#define TYPEC_TRYSINK_DETECT_INT_EN_BIT BIT(3) +#define EN_TRYSINK_MODE_BIT BIT(2) +#define EN_LEGACY_CABLE_DETECTION_BIT BIT(1) +#define ALLOW_PD_DRING_UFP_TCCDB_BIT BIT(0) + +#define USBIN_OPTIONS_1_CFG 0x362 +#define CABLE_R_SEL_BIT BIT(7) +#define HVDCP_AUTH_ALG_EN_CFG_BIT BIT(6) +#define HVDCP_AUTONOMOUS_MODE_EN_CFG_BIT BIT(5) +#define INPUT_PRIORITY_BIT BIT(4) +#define AUTO_SRC_DETECT_BIT BIT(3) +#define HVDCP_EN_BIT BIT(2) +#define VADP_INCREMENT_VOLTAGE_LIMIT_BIT BIT(1) +#define VADP_TAPER_TIMER_EN_BIT BIT(0) + +#define USBIN_OPTIONS_2_CFG 0x363 +#define WIPWR_RST_EUD_CFG_BIT BIT(7) +#define SWITCHER_START_CFG_BIT BIT(6) +#define DCD_TIMEOUT_SEL_BIT BIT(5) +#define OCD_CURRENT_SEL_BIT BIT(4) +#define SLOW_PLUGIN_TIMER_EN_CFG_BIT BIT(3) +#define FLOAT_OPTIONS_MASK GENMASK(2, 0) +#define FLOAT_DIS_CHGING_CFG_BIT BIT(2) +#define SUSPEND_FLOAT_CFG_BIT BIT(1) +#define FORCE_FLOAT_SDP_CFG_BIT BIT(0) + +#define TAPER_TIMER_SEL_CFG 0x364 +#define TYPEC_SPARE_CFG_BIT BIT(7) +#define TYPEC_DRP_DFP_TIME_CFG_BIT BIT(5) +#define TAPER_TIMER_SEL_MASK GENMASK(1, 0) + +#define USBIN_LOAD_CFG 0x365 +#define USBIN_OV_CH_LOAD_OPTION_BIT BIT(7) +#define ICL_OVERRIDE_AFTER_APSD_BIT BIT(4) + +#define USBIN_ICL_OPTIONS 0x366 +#define CFG_USB3P0_SEL_BIT BIT(2) +#define USB51_MODE_BIT BIT(1) +#define USBIN_MODE_CHG_BIT BIT(0) + +#define TYPE_C_INTRPT_ENB_SOFTWARE_CTRL 0x368 +#define EXIT_SNK_BASED_ON_CC_BIT BIT(7) +#define VCONN_EN_ORIENTATION_BIT BIT(6) +#define TYPEC_VCONN_OVERCURR_INT_EN_BIT BIT(5) +#define VCONN_EN_SRC_BIT BIT(4) +#define VCONN_EN_VALUE_BIT BIT(3) +#define TYPEC_POWER_ROLE_CMD_MASK GENMASK(2, 0) +#define UFP_EN_CMD_BIT BIT(2) +#define DFP_EN_CMD_BIT BIT(1) +#define TYPEC_DISABLE_CMD_BIT BIT(0) + +#define USBIN_CURRENT_LIMIT_CFG 0x370 +#define USBIN_CURRENT_LIMIT_MASK GENMASK(7, 0) + +#define USBIN_AICL_OPTIONS_CFG 0x380 +#define SUSPEND_ON_COLLAPSE_USBIN_BIT BIT(7) +#define USBIN_AICL_HDC_EN_BIT BIT(6) +#define USBIN_AICL_START_AT_MAX_BIT BIT(5) +#define USBIN_AICL_RERUN_EN_BIT BIT(4) +#define USBIN_AICL_ADC_EN_BIT BIT(3) +#define USBIN_AICL_EN_BIT BIT(2) +#define USBIN_HV_COLLAPSE_RESPONSE_BIT BIT(1) +#define USBIN_LV_COLLAPSE_RESPONSE_BIT BIT(0) + +#define USBIN_5V_AICL_THRESHOLD_CFG 0x381 +#define USBIN_5V_AICL_THRESHOLD_CFG_MASK GENMASK(2, 0) + +#define USBIN_CONT_AICL_THRESHOLD_CFG 0x384 +#define USBIN_CONT_AICL_THRESHOLD_CFG_MASK GENMASK(5, 0) + +#define DC_ENG_SSUPPLY_CFG2 0x4C1 +#define ENG_SSUPPLY_IVREF_OTG_SS_MASK GENMASK(2, 0) +#define OTG_SS_SLOW 0x3 + +#define DCIN_AICL_REF_SEL_CFG 0x481 +#define DCIN_CONT_AICL_THRESHOLD_CFG_MASK GENMASK(5, 0) + +#define WI_PWR_OPTIONS 0x495 +#define CHG_OK_BIT BIT(7) +#define WIPWR_UVLO_IRQ_OPT_BIT BIT(6) +#define BUCK_HOLDOFF_ENABLE_BIT BIT(5) +#define CHG_OK_HW_SW_SELECT_BIT BIT(4) +#define WIPWR_RST_ENABLE_BIT BIT(3) +#define DCIN_WIPWR_IRQ_SELECT_BIT BIT(2) +#define AICL_SWITCH_ENABLE_BIT BIT(1) +#define ZIN_ICL_ENABLE_BIT BIT(0) + +#define ICL_STATUS 0x607 +#define INPUT_CURRENT_LIMIT_MASK GENMASK(7, 0) + +#define POWER_PATH_STATUS 0x60B +#define P_PATH_INPUT_SS_DONE_BIT BIT(7) +#define P_PATH_USBIN_SUSPEND_STS_BIT BIT(6) +#define P_PATH_DCIN_SUSPEND_STS_BIT BIT(5) +#define P_PATH_USE_USBIN_BIT BIT(4) +#define P_PATH_USE_DCIN_BIT BIT(3) +#define P_PATH_POWER_PATH_MASK GENMASK(2, 1) +#define P_PATH_VALID_INPUT_POWER_SOURCE_STS_BIT BIT(0) + +#define BARK_BITE_WDOG_PET 0x643 +#define BARK_BITE_WDOG_PET_BIT BIT(0) + +#define WD_CFG 0x651 +#define WATCHDOG_TRIGGER_AFP_EN_BIT BIT(7) +#define BARK_WDOG_INT_EN_BIT BIT(6) +#define BITE_WDOG_INT_EN_BIT BIT(5) +#define SFT_AFTER_WDOG_IRQ_MASK GENMASK(4, 3) +#define WDOG_IRQ_SFT_BIT BIT(2) +#define WDOG_TIMER_EN_ON_PLUGIN_BIT BIT(1) +#define WDOG_TIMER_EN_BIT BIT(0) + +#define SNARL_BARK_BITE_WD_CFG 0x653 +#define BITE_WDOG_DISABLE_CHARGING_CFG_BIT BIT(7) +#define SNARL_WDOG_TIMEOUT_MASK GENMASK(6, 4) +#define BARK_WDOG_TIMEOUT_MASK GENMASK(3, 2) +#define BITE_WDOG_TIMEOUT_MASK GENMASK(1, 0) + +#define AICL_RERUN_TIME_CFG 0x661 +#define AICL_RERUN_TIME_MASK GENMASK(1, 0) + +#define STAT_CFG 0x690 +#define STAT_SW_OVERRIDE_VALUE_BIT BIT(7) +#define STAT_SW_OVERRIDE_CFG_BIT BIT(6) +#define STAT_PARALLEL_OFF_DG_CFG_MASK GENMASK(5, 4) +#define STAT_POLARITY_CFG_BIT BIT(3) +#define STAT_PARALLEL_CFG_BIT BIT(2) +#define STAT_FUNCTION_CFG_BIT BIT(1) +#define STAT_IRQ_PULSING_EN_BIT BIT(0) + +#define SDP_CURRENT_UA 500000 +#define CDP_CURRENT_UA 1500000 +#define DCP_CURRENT_UA 1500000 +#define CURRENT_MAX_UA DCP_CURRENT_UA + +/* pmi8998 registers represent current in increments of 1/40th of an amp */ +#define CURRENT_SCALE_FACTOR 25000 +/* clang-format on */ + +enum charger_status { + TRICKLE_CHARGE = 0, + PRE_CHARGE, + FAST_CHARGE, + FULLON_CHARGE, + TAPER_CHARGE, + TERMINATE_CHARGE, + INHIBIT_CHARGE, + DISABLE_CHARGE, +}; + +struct smb2_register { + u16 addr; + u8 mask; + u8 val; +}; + +/** + * struct smb2_chip - smb2 chip structure + * @dev: Device reference for power_supply + * @name: The platform device name + * @base: Base address for smb2 registers + * @regmap: Register map + * @batt_info: Battery data from DT + * @status_change_work: Worker to handle plug/unplug events + * @cable_irq: USB plugin IRQ + * @wakeup_enabled: If the cable IRQ will cause a wakeup + * @usb_in_i_chan: USB_IN current measurement channel + * @usb_in_v_chan: USB_IN voltage measurement channel + * @chg_psy: Charger power supply instance + */ +struct smb2_chip { + struct device *dev; + const char *name; + unsigned int base; + struct regmap *regmap; + struct power_supply_battery_info *batt_info; + + struct delayed_work status_change_work; + int cable_irq; + bool wakeup_enabled; + + struct iio_channel *usb_in_i_chan; + struct iio_channel *usb_in_v_chan; + + struct power_supply *chg_psy; +}; + +static enum power_supply_property smb2_properties[] = { + POWER_SUPPLY_PROP_MANUFACTURER, + POWER_SUPPLY_PROP_MODEL_NAME, + POWER_SUPPLY_PROP_CURRENT_MAX, + POWER_SUPPLY_PROP_CURRENT_NOW, + POWER_SUPPLY_PROP_VOLTAGE_NOW, + POWER_SUPPLY_PROP_STATUS, + POWER_SUPPLY_PROP_HEALTH, + POWER_SUPPLY_PROP_ONLINE, + POWER_SUPPLY_PROP_USB_TYPE, + POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT, + POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX, +}; + +static enum power_supply_usb_type smb2_usb_types[] = { + POWER_SUPPLY_USB_TYPE_UNKNOWN, + POWER_SUPPLY_USB_TYPE_SDP, + POWER_SUPPLY_USB_TYPE_DCP, + POWER_SUPPLY_USB_TYPE_CDP, +}; + +static int smb2_get_prop_usb_online(struct smb2_chip *chip, int *val) +{ + unsigned int stat; + int rc; + + rc = regmap_read(chip->regmap, chip->base + POWER_PATH_STATUS, &stat); + if (rc < 0) { + dev_err(chip->dev, "Couldn't read power path status: %d\n", rc); + return rc; + } + + *val = (stat & P_PATH_USE_USBIN_BIT) && + (stat & P_PATH_VALID_INPUT_POWER_SOURCE_STS_BIT); + return 0; +} + +/* + * Qualcomm "automatic power source detection" aka APSD + * tells us what type of charger we're connected to. + */ +static int smb2_apsd_get_charger_type(struct smb2_chip *chip, int *val) +{ + unsigned int apsd_stat, stat; + int usb_online = 0; + int rc; + + rc = smb2_get_prop_usb_online(chip, &usb_online); + if (!usb_online) { + *val = POWER_SUPPLY_USB_TYPE_UNKNOWN; + return rc; + } + + rc = regmap_read(chip->regmap, chip->base + APSD_STATUS, &apsd_stat); + if (rc < 0) { + dev_err(chip->dev, "Failed to read apsd status, rc = %d", rc); + return rc; + } + if (!(apsd_stat & APSD_DTC_STATUS_DONE_BIT)) { + dev_dbg(chip->dev, "Apsd not ready"); + return -EAGAIN; + } + + rc = regmap_read(chip->regmap, chip->base + APSD_RESULT_STATUS, &stat); + if (rc < 0) { + dev_err(chip->dev, "Failed to read apsd result, rc = %d", rc); + return rc; + } + + stat &= APSD_RESULT_STATUS_MASK; + + if (stat & CDP_CHARGER_BIT) + *val = POWER_SUPPLY_USB_TYPE_CDP; + else if (stat & (DCP_CHARGER_BIT | OCP_CHARGER_BIT | FLOAT_CHARGER_BIT)) + *val = POWER_SUPPLY_USB_TYPE_DCP; + else /* SDP_CHARGER_BIT (or others) */ + *val = POWER_SUPPLY_USB_TYPE_SDP; + + return 0; +} + +static int smb2_get_prop_status(struct smb2_chip *chip, int *val) +{ + unsigned char stat[2]; + int usb_online = 0; + int rc; + + rc = smb2_get_prop_usb_online(chip, &usb_online); + if (!usb_online) { + *val = POWER_SUPPLY_STATUS_DISCHARGING; + return rc; + } + + rc = regmap_bulk_read(chip->regmap, + chip->base + BATTERY_CHARGER_STATUS_1, &stat, 2); + if (rc < 0) { + dev_err(chip->dev, "Failed to read charging status ret=%d\n", + rc); + return rc; + } + + if (stat[1] & CHARGER_ERROR_STATUS_BAT_OV_BIT) { + *val = POWER_SUPPLY_STATUS_NOT_CHARGING; + return 0; + } + + stat[0] = stat[0] & BATTERY_CHARGER_STATUS_MASK; + + switch (stat[0]) { + case TRICKLE_CHARGE: + case PRE_CHARGE: + case FAST_CHARGE: + case FULLON_CHARGE: + case TAPER_CHARGE: + *val = POWER_SUPPLY_STATUS_CHARGING; + return rc; + case DISABLE_CHARGE: + *val = POWER_SUPPLY_STATUS_NOT_CHARGING; + return rc; + case TERMINATE_CHARGE: + *val = POWER_SUPPLY_STATUS_FULL; + return rc; + case INHIBIT_CHARGE: + default: + *val = POWER_SUPPLY_STATUS_UNKNOWN; + return rc; + } +} + +static inline int smb2_get_current_limit(struct smb2_chip *chip, + unsigned int *val) +{ + int rc = regmap_read(chip->regmap, chip->base + ICL_STATUS, val); + + if (rc >= 0) + *val *= CURRENT_SCALE_FACTOR; + return rc; +} + +static int smb2_set_current_limit(struct smb2_chip *chip, unsigned int val) +{ + unsigned char val_raw; + + if (val > 4800000) { + dev_err(chip->dev, + "Can't set current limit higher than 4800000uA"); + return -EINVAL; + } + val_raw = val / CURRENT_SCALE_FACTOR; + + return regmap_write(chip->regmap, chip->base + USBIN_CURRENT_LIMIT_CFG, + val_raw); +} + +static void smb2_status_change_work(struct work_struct *work) +{ + unsigned int charger_type, current_ua; + int usb_online, count, rc; + struct smb2_chip *chip; + + chip = container_of(work, struct smb2_chip, status_change_work.work); + + smb2_get_prop_usb_online(chip, &usb_online); + if (!usb_online) + return; + + for (count = 0; count < 3; count++) { + dev_dbg(chip->dev, "get charger type retry %d\n", count); + rc = smb2_apsd_get_charger_type(chip, &charger_type); + if (rc != -EAGAIN) + break; + msleep(100); + } + + if (rc < 0 && rc != -EAGAIN) { + dev_err(chip->dev, "get charger type failed: %d\n", rc); + return; + } + + if (rc < 0) { + rc = regmap_update_bits(chip->regmap, chip->base + CMD_APSD, + APSD_RERUN_BIT, APSD_RERUN_BIT); + schedule_delayed_work(&chip->status_change_work, + msecs_to_jiffies(1000)); + dev_dbg(chip->dev, "get charger type failed, rerun apsd\n"); + return; + } + + switch (charger_type) { + case POWER_SUPPLY_USB_TYPE_CDP: + current_ua = CDP_CURRENT_UA; + break; + case POWER_SUPPLY_USB_TYPE_DCP: + current_ua = DCP_CURRENT_UA; + break; + case POWER_SUPPLY_USB_TYPE_SDP: + default: + current_ua = SDP_CURRENT_UA; + break; + } + + smb2_set_current_limit(chip, current_ua); + power_supply_changed(chip->chg_psy); +} + +static int smb2_get_iio_chan(struct smb2_chip *chip, struct iio_channel *chan, + int *val) +{ + int rc; + union power_supply_propval status; + + rc = power_supply_get_property(chip->chg_psy, POWER_SUPPLY_PROP_STATUS, + &status); + if (rc < 0 || status.intval != POWER_SUPPLY_STATUS_CHARGING) { + *val = 0; + return 0; + } + + if (IS_ERR(chan)) { + dev_err(chip->dev, "Failed to chan, err = %li", PTR_ERR(chan)); + return PTR_ERR(chan); + } + + return iio_read_channel_processed(chan, val); +} + +static int smb2_get_prop_health(struct smb2_chip *chip, int *val) +{ + int rc; + unsigned int stat; + + rc = regmap_read(chip->regmap, chip->base + BATTERY_CHARGER_STATUS_2, + &stat); + if (rc < 0) { + dev_err(chip->dev, "Couldn't read charger status rc=%d\n", rc); + return rc; + } + + switch (stat) { + case CHARGER_ERROR_STATUS_BAT_OV_BIT: + *val = POWER_SUPPLY_HEALTH_OVERVOLTAGE; + return 0; + case BAT_TEMP_STATUS_TOO_COLD_BIT: + *val = POWER_SUPPLY_HEALTH_COLD; + return 0; + case BAT_TEMP_STATUS_TOO_HOT_BIT: + *val = POWER_SUPPLY_HEALTH_OVERHEAT; + return 0; + case BAT_TEMP_STATUS_COLD_SOFT_LIMIT_BIT: + *val = POWER_SUPPLY_HEALTH_COOL; + return 0; + case BAT_TEMP_STATUS_HOT_SOFT_LIMIT_BIT: + *val = POWER_SUPPLY_HEALTH_WARM; + return 0; + default: + *val = POWER_SUPPLY_HEALTH_GOOD; + return 0; + } +} + +static int smb2_get_property(struct power_supply *psy, + enum power_supply_property psp, + union power_supply_propval *val) +{ + struct smb2_chip *chip = power_supply_get_drvdata(psy); + + switch (psp) { + case POWER_SUPPLY_PROP_MANUFACTURER: + val->strval = "Qualcomm"; + return 0; + case POWER_SUPPLY_PROP_MODEL_NAME: + val->strval = chip->name; + return 0; + case POWER_SUPPLY_PROP_CURRENT_MAX: + case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT: + return smb2_get_current_limit(chip, &val->intval); + case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX: + val->intval = DCP_CURRENT_UA; + return 0; + case POWER_SUPPLY_PROP_CURRENT_NOW: + return smb2_get_iio_chan(chip, chip->usb_in_i_chan, + &val->intval); + case POWER_SUPPLY_PROP_VOLTAGE_NOW: + return smb2_get_iio_chan(chip, chip->usb_in_v_chan, + &val->intval); + case POWER_SUPPLY_PROP_ONLINE: + return smb2_get_prop_usb_online(chip, &val->intval); + case POWER_SUPPLY_PROP_STATUS: + return smb2_get_prop_status(chip, &val->intval); + case POWER_SUPPLY_PROP_HEALTH: + return smb2_get_prop_health(chip, &val->intval); + case POWER_SUPPLY_PROP_USB_TYPE: + return smb2_apsd_get_charger_type(chip, &val->intval); + default: + dev_err(chip->dev, "invalid property: %d\n", psp); + return -EINVAL; + } +} + +static int smb2_set_property(struct power_supply *psy, + enum power_supply_property psp, + const union power_supply_propval *val) +{ + struct smb2_chip *chip = power_supply_get_drvdata(psy); + + switch (psp) { + case POWER_SUPPLY_PROP_CURRENT_MAX: + case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT: + return smb2_set_current_limit(chip, val->intval); + default: + dev_err(chip->dev, "No setter for property: %d\n", psp); + return -EINVAL; + } +} + +static int smb2_property_is_writable(struct power_supply *psy, + enum power_supply_property psp) +{ + switch (psp) { + case POWER_SUPPLY_PROP_CURRENT_MAX: + case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT: + return 1; + default: + return 0; + } +} + +static irqreturn_t smb2_handle_batt_overvoltage(int irq, void *data) +{ + struct smb2_chip *chip = data; + unsigned int status; + + regmap_read(chip->regmap, chip->base + BATTERY_CHARGER_STATUS_2, + &status); + + if (status & CHARGER_ERROR_STATUS_BAT_OV_BIT) { + /* The hardware stops charging automatically */ + dev_err(chip->dev, "battery overvoltage detected\n"); + power_supply_changed(chip->chg_psy); + } + + return IRQ_HANDLED; +} + +static irqreturn_t smb2_handle_usb_plugin(int irq, void *data) +{ + struct smb2_chip *chip = data; + + power_supply_changed(chip->chg_psy); + + schedule_delayed_work(&chip->status_change_work, + msecs_to_jiffies(1500)); + + return IRQ_HANDLED; +} + +static irqreturn_t smb2_handle_usb_icl_change(int irq, void *data) +{ + struct smb2_chip *chip = data; + + power_supply_changed(chip->chg_psy); + + return IRQ_HANDLED; +} + +static irqreturn_t smb2_handle_wdog_bark(int irq, void *data) +{ + struct smb2_chip *chip = data; + int rc; + + power_supply_changed(chip->chg_psy); + + rc = regmap_write(chip->regmap, BARK_BITE_WDOG_PET, + BARK_BITE_WDOG_PET_BIT); + if (rc < 0) + dev_err(chip->dev, "Couldn't pet the dog rc=%d\n", rc); + + return IRQ_HANDLED; +} + +static const struct power_supply_desc smb2_psy_desc = { + .name = "pmi8998_charger", + .type = POWER_SUPPLY_TYPE_USB, + .usb_types = smb2_usb_types, + .num_usb_types = ARRAY_SIZE(smb2_usb_types), + .properties = smb2_properties, + .num_properties = ARRAY_SIZE(smb2_properties), + .get_property = smb2_get_property, + .set_property = smb2_set_property, + .property_is_writeable = smb2_property_is_writable, +}; + +/* Init sequence derived from vendor downstream driver */ +static const struct smb2_register smb2_init_seq[] = { + { .addr = AICL_RERUN_TIME_CFG, .mask = AICL_RERUN_TIME_MASK, .val = 0 }, + /* + * By default configure us as an upstream facing port + * FIXME: This will be handled by the type-c driver + */ + { .addr = TYPE_C_INTRPT_ENB_SOFTWARE_CTRL, + .mask = TYPEC_POWER_ROLE_CMD_MASK | VCONN_EN_SRC_BIT | + VCONN_EN_VALUE_BIT, + .val = VCONN_EN_SRC_BIT }, + /* + * Disable Type-C factory mode and stay in Attached.SRC state when VCONN + * over-current happens + */ + { .addr = TYPE_C_CFG, + .mask = FACTORY_MODE_DETECTION_EN_BIT | VCONN_OC_CFG_BIT, + .val = 0 }, + /* Configure VBUS for software control */ + { .addr = OTG_CFG, .mask = OTG_EN_SRC_CFG_BIT, .val = 0 }, + /* + * Use VBAT to determine the recharge threshold when battery is full + * rather than the state of charge. + */ + { .addr = FG_UPDATE_CFG_2_SEL, + .mask = SOC_LT_CHG_RECHARGE_THRESH_SEL_BIT | + VBT_LT_CHG_RECHARGE_THRESH_SEL_BIT, + .val = VBT_LT_CHG_RECHARGE_THRESH_SEL_BIT }, + /* Enable charging */ + { .addr = USBIN_OPTIONS_1_CFG, .mask = HVDCP_EN_BIT, .val = 0 }, + { .addr = CHARGING_ENABLE_CMD, + .mask = CHARGING_ENABLE_CMD_BIT, + .val = CHARGING_ENABLE_CMD_BIT }, + /* + * Match downstream defaults + * CHG_EN_SRC_BIT - charger enable is controlled by software + * CHG_EN_POLARITY_BIT - polarity of charge enable pin when in HW control + * pulled low on OnePlus 6 and SHIFT6mq + * PRETOFAST_TRANSITION_CFG_BIT - + * BAT_OV_ECC_BIT - + * I_TERM_BIT - Current termination ?? 0 = enabled + * AUTO_RECHG_BIT - Enable automatic recharge when battery is full + * 0 = enabled + * EN_ANALOG_DROP_IN_VBATT_BIT + * CHARGER_INHIBIT_BIT - Inhibit charging based on battery voltage + * instead of ?? + */ + { .addr = CHGR_CFG2, + .mask = CHG_EN_SRC_BIT | CHG_EN_POLARITY_BIT | + PRETOFAST_TRANSITION_CFG_BIT | BAT_OV_ECC_BIT | I_TERM_BIT | + AUTO_RECHG_BIT | EN_ANALOG_DROP_IN_VBATT_BIT | + CHARGER_INHIBIT_BIT, + .val = CHARGER_INHIBIT_BIT }, + /* STAT pin software override, match downstream. Parallell charging? */ + { .addr = STAT_CFG, + .mask = STAT_SW_OVERRIDE_CFG_BIT, + .val = STAT_SW_OVERRIDE_CFG_BIT }, + /* Set the default SDP charger type to a 500ma USB 2.0 port */ + { .addr = USBIN_ICL_OPTIONS, + .mask = USB51_MODE_BIT | USBIN_MODE_CHG_BIT, + .val = USB51_MODE_BIT }, + /* Disable watchdog */ + { .addr = SNARL_BARK_BITE_WD_CFG, .mask = 0xff, .val = 0 }, + { .addr = WD_CFG, + .mask = WATCHDOG_TRIGGER_AFP_EN_BIT | WDOG_TIMER_EN_ON_PLUGIN_BIT | + BARK_WDOG_INT_EN_BIT, + .val = 0 }, + /* These bits aren't documented anywhere */ + { .addr = USBIN_5V_AICL_THRESHOLD_CFG, + .mask = USBIN_5V_AICL_THRESHOLD_CFG_MASK, + .val = 0x3 }, + { .addr = USBIN_CONT_AICL_THRESHOLD_CFG, + .mask = USBIN_CONT_AICL_THRESHOLD_CFG_MASK, + .val = 0x3 }, + /* + * Enable Automatic Input Current Limit, this will slowly ramp up the current + * When connected to a wall charger, and automatically stop when it detects + * the charger current limit (voltage drop?) or it reaches the programmed limit. + */ + { .addr = USBIN_AICL_OPTIONS_CFG, + .mask = USBIN_AICL_START_AT_MAX_BIT | USBIN_AICL_ADC_EN_BIT | + USBIN_AICL_EN_BIT | SUSPEND_ON_COLLAPSE_USBIN_BIT | + USBIN_HV_COLLAPSE_RESPONSE_BIT | + USBIN_LV_COLLAPSE_RESPONSE_BIT, + .val = USBIN_HV_COLLAPSE_RESPONSE_BIT | + USBIN_LV_COLLAPSE_RESPONSE_BIT | USBIN_AICL_EN_BIT }, + /* + * Set pre charge current to default, the OnePlus 6 bootloader + * sets this very conservatively. + */ + { .addr = PRE_CHARGE_CURRENT_CFG, + .mask = PRE_CHARGE_CURRENT_SETTING_MASK, + .val = 500000 / CURRENT_SCALE_FACTOR }, + /* + * This overrides all of the current limit options exposed to userspace + * and prevents the device from pulling more than ~1A. This is done + * to minimise potential fire hazard risks. + */ + { .addr = FAST_CHARGE_CURRENT_CFG, + .mask = FAST_CHARGE_CURRENT_SETTING_MASK, + .val = 1000000 / CURRENT_SCALE_FACTOR }, +}; + +static int smb2_init_hw(struct smb2_chip *chip) +{ + int rc, i; + + for (i = 0; i < ARRAY_SIZE(smb2_init_seq); i++) { + dev_dbg(chip->dev, "%d: Writing 0x%02x to 0x%02x\n", i, + smb2_init_seq[i].val, smb2_init_seq[i].addr); + rc = regmap_update_bits(chip->regmap, + chip->base + smb2_init_seq[i].addr, + smb2_init_seq[i].mask, + smb2_init_seq[i].val); + if (rc < 0) + return dev_err_probe(chip->dev, rc, + "%s: init command %d failed\n", + __func__, i); + } + + return 0; +} + +static int smb2_init_irq(struct smb2_chip *chip, int *irq, const char *name, + irqreturn_t (*handler)(int irq, void *data)) +{ + int irqnum; + int rc; + + irqnum = platform_get_irq_byname(to_platform_device(chip->dev), name); + if (irqnum < 0) + return dev_err_probe(chip->dev, irqnum, + "Couldn't get irq %s byname\n", name); + + rc = devm_request_threaded_irq(chip->dev, irqnum, NULL, handler, + IRQF_ONESHOT, name, chip); + if (rc < 0) + return dev_err_probe(chip->dev, rc, "Couldn't request irq %s\n", + name); + + if (irq) + *irq = irqnum; + + return 0; +} + +static int smb2_probe(struct platform_device *pdev) +{ + struct power_supply_config supply_config = {}; + struct power_supply_desc *desc; + struct smb2_chip *chip; + int rc, irq; + + chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL); + if (!chip) + return -ENOMEM; + + chip->dev = &pdev->dev; + chip->name = pdev->name; + + chip->regmap = dev_get_regmap(pdev->dev.parent, NULL); + if (!chip->regmap) + return dev_err_probe(chip->dev, -ENODEV, + "failed to locate the regmap\n"); + + rc = device_property_read_u32(chip->dev, "reg", &chip->base); + if (rc < 0) + return dev_err_probe(chip->dev, rc, + "Couldn't read base address\n"); + + chip->usb_in_v_chan = devm_iio_channel_get(chip->dev, "usbin_v"); + if (IS_ERR(chip->usb_in_v_chan)) + return dev_err_probe(chip->dev, PTR_ERR(chip->usb_in_v_chan), + "Couldn't get usbin_v IIO channel\n"); + + chip->usb_in_i_chan = devm_iio_channel_get(chip->dev, "usbin_i"); + if (IS_ERR(chip->usb_in_i_chan)) { + return dev_err_probe(chip->dev, PTR_ERR(chip->usb_in_i_chan), + "Couldn't get usbin_i IIO channel\n"); + } + + rc = smb2_init_hw(chip); + if (rc < 0) + return rc; + + supply_config.drv_data = chip; + supply_config.of_node = pdev->dev.of_node; + + desc = devm_kzalloc(chip->dev, sizeof(smb2_psy_desc), GFP_KERNEL); + memcpy(desc, &smb2_psy_desc, sizeof(smb2_psy_desc)); + desc->name = + devm_kasprintf(chip->dev, GFP_KERNEL, "%s-charger", + (const char *)device_get_match_data(chip->dev)); + + chip->chg_psy = + devm_power_supply_register(chip->dev, desc, &supply_config); + if (IS_ERR(chip->chg_psy)) + return dev_err_probe(chip->dev, PTR_ERR(chip->chg_psy), + "failed to register power supply\n"); + + rc = power_supply_get_battery_info(chip->chg_psy, &chip->batt_info); + if (rc) + return dev_err_probe(chip->dev, rc, + "Failed to get battery info\n"); + + rc = devm_delayed_work_autocancel(chip->dev, &chip->status_change_work, + smb2_status_change_work); + if (rc) + return dev_err_probe(chip->dev, rc, + "Failed to init status change work\n"); + + rc = (chip->batt_info->voltage_max_design_uv - 3487500) / 7500 + 1; + rc = regmap_update_bits(chip->regmap, chip->base + FLOAT_VOLTAGE_CFG, + FLOAT_VOLTAGE_SETTING_MASK, rc); + if (rc < 0) + return dev_err_probe(chip->dev, rc, "Couldn't set vbat max\n"); + + rc = smb2_init_irq(chip, &irq, "bat-ov", smb2_handle_batt_overvoltage); + if (rc < 0) + return rc; + + rc = smb2_init_irq(chip, &chip->cable_irq, "usb-plugin", + smb2_handle_usb_plugin); + if (rc < 0) + return rc; + + rc = smb2_init_irq(chip, &irq, "usbin-icl-change", + smb2_handle_usb_icl_change); + if (rc < 0) + return rc; + rc = smb2_init_irq(chip, &irq, "wdog-bark", smb2_handle_wdog_bark); + if (rc < 0) + return rc; + + rc = dev_pm_set_wake_irq(chip->dev, chip->cable_irq); + if (rc < 0) + return dev_err_probe(chip->dev, rc, "Couldn't set wake irq\n"); + + platform_set_drvdata(pdev, chip); + + /* Initialise charger state */ + schedule_delayed_work(&chip->status_change_work, 0); + + return 0; +} + +static const struct of_device_id smb2_match_id_table[] = { + { .compatible = "qcom,pmi8998-charger", .data = "pmi8998" }, + { .compatible = "qcom,pm660-charger", .data = "pm660" }, + { /* sentinal */ } +}; +MODULE_DEVICE_TABLE(of, smb2_match_id_table); + +static struct platform_driver qcom_spmi_smb2 = { + .probe = smb2_probe, + .driver = { + .name = "qcom-pmi8998/pm660-charger", + .of_match_table = smb2_match_id_table, + }, +}; + +module_platform_driver(qcom_spmi_smb2); + +MODULE_AUTHOR("Caleb Connolly "); +MODULE_DESCRIPTION("Qualcomm SMB2 Charger Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/power/supply/rk817_charger.c b/drivers/power/supply/rk817_charger.c index 1a2143641e66d47fdf8211d6f4f6a654b7b62584..8328bcea1a29906e38e7d214d79b1ed3cae5972f 100644 --- a/drivers/power/supply/rk817_charger.c +++ b/drivers/power/supply/rk817_charger.c @@ -1134,7 +1134,7 @@ static int rk817_charger_probe(struct platform_device *pdev) &bat_info); if (ret) { return dev_err_probe(dev, ret, - "Unable to get battery info: %d\n", ret); + "Unable to get battery info\n"); } if ((bat_info->charge_full_design_uah <= 0) || diff --git a/drivers/power/supply/rt5033_battery.c b/drivers/power/supply/rt5033_battery.c index 5c04cf30521931c74d52a39cabd502553011faf0..d90b96df8e73da19a219d828b77a3e089e28a71a 100644 --- a/drivers/power/supply/rt5033_battery.c +++ b/drivers/power/supply/rt5033_battery.c @@ -6,11 +6,33 @@ * Author: Beomho Seo */ +#include #include #include #include +#include #include -#include + +struct rt5033_battery { + struct i2c_client *client; + struct regmap *regmap; + struct power_supply *psy; +}; + +static int rt5033_battery_get_status(struct i2c_client *client) +{ + struct rt5033_battery *battery = i2c_get_clientdata(client); + union power_supply_propval val; + int ret; + + ret = power_supply_get_property_from_supplier(battery->psy, + POWER_SUPPLY_PROP_STATUS, + &val); + if (ret) + val.intval = POWER_SUPPLY_STATUS_UNKNOWN; + + return val.intval; +} static int rt5033_battery_get_capacity(struct i2c_client *client) { @@ -84,6 +106,9 @@ static int rt5033_battery_get_property(struct power_supply *psy, case POWER_SUPPLY_PROP_CAPACITY: val->intval = rt5033_battery_get_capacity(battery->client); break; + case POWER_SUPPLY_PROP_STATUS: + val->intval = rt5033_battery_get_status(battery->client); + break; default: return -EINVAL; } @@ -96,6 +121,7 @@ static enum power_supply_property rt5033_battery_props[] = { POWER_SUPPLY_PROP_VOLTAGE_OCV, POWER_SUPPLY_PROP_PRESENT, POWER_SUPPLY_PROP_CAPACITY, + POWER_SUPPLY_PROP_STATUS, }; static const struct regmap_config rt5033_battery_regmap_config = { @@ -117,7 +143,6 @@ static int rt5033_battery_probe(struct i2c_client *client) struct i2c_adapter *adapter = client->adapter; struct power_supply_config psy_cfg = {}; struct rt5033_battery *battery; - u32 ret; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE)) return -EIO; @@ -135,15 +160,14 @@ static int rt5033_battery_probe(struct i2c_client *client) } i2c_set_clientdata(client, battery); + psy_cfg.of_node = client->dev.of_node; psy_cfg.drv_data = battery; battery->psy = power_supply_register(&client->dev, &rt5033_battery_desc, &psy_cfg); - if (IS_ERR(battery->psy)) { - dev_err(&client->dev, "Failed to register power supply\n"); - ret = PTR_ERR(battery->psy); - return ret; - } + if (IS_ERR(battery->psy)) + return dev_err_probe(&client->dev, PTR_ERR(battery->psy), + "Failed to register power supply\n"); return 0; } @@ -172,7 +196,7 @@ static struct i2c_driver rt5033_battery_driver = { .name = "rt5033-battery", .of_match_table = rt5033_battery_of_match, }, - .probe_new = rt5033_battery_probe, + .probe = rt5033_battery_probe, .remove = rt5033_battery_remove, .id_table = rt5033_battery_id, }; diff --git a/drivers/power/supply/rt5033_charger.c b/drivers/power/supply/rt5033_charger.c new file mode 100644 index 0000000000000000000000000000000000000000..5218dfbf5e1bf97d6375084e2f7282e64557fca9 --- /dev/null +++ b/drivers/power/supply/rt5033_charger.c @@ -0,0 +1,472 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Battery charger driver for RT5033 + * + * Copyright (C) 2014 Samsung Electronics, Co., Ltd. + * Author: Beomho Seo + */ + +#include +#include +#include +#include +#include +#include + +struct rt5033_charger_data { + unsigned int pre_uamp; + unsigned int pre_uvolt; + unsigned int const_uvolt; + unsigned int eoc_uamp; + unsigned int fast_uamp; +}; + +struct rt5033_charger { + struct device *dev; + struct regmap *regmap; + struct power_supply *psy; + struct rt5033_charger_data *chg; +}; + +static int rt5033_get_charger_state(struct rt5033_charger *charger) +{ + struct regmap *regmap = charger->regmap; + unsigned int reg_data; + int state; + + if (!regmap) + return POWER_SUPPLY_STATUS_UNKNOWN; + + regmap_read(regmap, RT5033_REG_CHG_STAT, ®_data); + + switch (reg_data & RT5033_CHG_STAT_MASK) { + case RT5033_CHG_STAT_DISCHARGING: + state = POWER_SUPPLY_STATUS_DISCHARGING; + break; + case RT5033_CHG_STAT_CHARGING: + state = POWER_SUPPLY_STATUS_CHARGING; + break; + case RT5033_CHG_STAT_FULL: + state = POWER_SUPPLY_STATUS_FULL; + break; + case RT5033_CHG_STAT_NOT_CHARGING: + state = POWER_SUPPLY_STATUS_NOT_CHARGING; + break; + default: + state = POWER_SUPPLY_STATUS_UNKNOWN; + } + + return state; +} + +static int rt5033_get_charger_type(struct rt5033_charger *charger) +{ + struct regmap *regmap = charger->regmap; + unsigned int reg_data; + int state; + + regmap_read(regmap, RT5033_REG_CHG_STAT, ®_data); + + switch (reg_data & RT5033_CHG_STAT_TYPE_MASK) { + case RT5033_CHG_STAT_TYPE_FAST: + state = POWER_SUPPLY_CHARGE_TYPE_FAST; + break; + case RT5033_CHG_STAT_TYPE_PRE: + state = POWER_SUPPLY_CHARGE_TYPE_TRICKLE; + break; + default: + state = POWER_SUPPLY_CHARGE_TYPE_NONE; + } + + return state; +} + +static int rt5033_get_charger_current_limit(struct rt5033_charger *charger) +{ + struct regmap *regmap = charger->regmap; + unsigned int state, reg_data, data; + + regmap_read(regmap, RT5033_REG_CHG_CTRL5, ®_data); + + state = (reg_data & RT5033_CHGCTRL5_ICHG_MASK) + >> RT5033_CHGCTRL5_ICHG_SHIFT; + + data = RT5033_CHARGER_FAST_CURRENT_MIN + + RT5033_CHARGER_FAST_CURRENT_STEP_NUM * state; + + return data; +} + +static int rt5033_get_charger_const_voltage(struct rt5033_charger *charger) +{ + struct regmap *regmap = charger->regmap; + unsigned int state, reg_data, data; + + regmap_read(regmap, RT5033_REG_CHG_CTRL2, ®_data); + + state = (reg_data & RT5033_CHGCTRL2_CV_MASK) + >> RT5033_CHGCTRL2_CV_SHIFT; + + data = RT5033_CHARGER_CONST_VOLTAGE_LIMIT_MIN + + RT5033_CHARGER_CONST_VOLTAGE_STEP_NUM * state; + + return data; +} + +static inline int rt5033_init_const_charge(struct rt5033_charger *charger) +{ + struct rt5033_charger_data *chg = charger->chg; + int ret; + unsigned int val; + u8 reg_data; + + /* Set constant voltage mode */ + if (chg->const_uvolt < RT5033_CHARGER_CONST_VOLTAGE_LIMIT_MIN || + chg->const_uvolt > RT5033_CHARGER_CONST_VOLTAGE_LIMIT_MAX) { + dev_err(charger->dev, + "Value 'constant-charge-voltage-max-microvolt' out of range\n"); + return -EINVAL; + } + + if (chg->const_uvolt == RT5033_CHARGER_CONST_VOLTAGE_LIMIT_MIN) + reg_data = 0x00; + else if (chg->const_uvolt == RT5033_CHARGER_CONST_VOLTAGE_LIMIT_MAX) + reg_data = RT5033_CV_MAX_VOLTAGE; + else { + val = chg->const_uvolt; + val -= RT5033_CHARGER_CONST_VOLTAGE_LIMIT_MIN; + val /= RT5033_CHARGER_CONST_VOLTAGE_STEP_NUM; + reg_data = val; + } + + ret = regmap_update_bits(charger->regmap, RT5033_REG_CHG_CTRL2, + RT5033_CHGCTRL2_CV_MASK, + reg_data << RT5033_CHGCTRL2_CV_SHIFT); + if (ret) { + dev_err(charger->dev, "Failed regmap update\n"); + return -EINVAL; + } + + /* Set end of charge current */ + if (chg->eoc_uamp < RT5033_CHARGER_EOC_MIN || + chg->eoc_uamp > RT5033_CHARGER_EOC_MAX) { + dev_err(charger->dev, + "Value 'charge-term-current-microamp' out of range\n"); + return -EINVAL; + } + + if (chg->eoc_uamp == RT5033_CHARGER_EOC_MIN) + reg_data = 0x01; + else if (chg->eoc_uamp == RT5033_CHARGER_EOC_MAX) + reg_data = 0x07; + else { + val = chg->eoc_uamp; + if (val < RT5033_CHARGER_EOC_REF) { + val -= RT5033_CHARGER_EOC_MIN; + val /= RT5033_CHARGER_EOC_STEP_NUM1; + reg_data = 0x01 + val; + } else if (val > RT5033_CHARGER_EOC_REF) { + val -= RT5033_CHARGER_EOC_REF; + val /= RT5033_CHARGER_EOC_STEP_NUM2; + reg_data = 0x04 + val; + } else { + reg_data = 0x04; + } + } + + ret = regmap_update_bits(charger->regmap, RT5033_REG_CHG_CTRL4, + RT5033_CHGCTRL4_EOC_MASK, reg_data); + if (ret) { + dev_err(charger->dev, "Failed regmap update\n"); + return -EINVAL; + } + + return 0; +} + +static inline int rt5033_init_fast_charge(struct rt5033_charger *charger) +{ + struct rt5033_charger_data *chg = charger->chg; + int ret; + unsigned int val; + u8 reg_data; + + /* Set limit input current */ + ret = regmap_update_bits(charger->regmap, RT5033_REG_CHG_CTRL1, + RT5033_CHGCTRL1_IAICR_MASK, RT5033_AICR_2000_MODE); + if (ret) { + dev_err(charger->dev, "Failed regmap update\n"); + return -EINVAL; + } + + /* Set fast-charge mode charging current */ + if (chg->fast_uamp < RT5033_CHARGER_FAST_CURRENT_MIN || + chg->fast_uamp > RT5033_CHARGER_FAST_CURRENT_MAX) { + dev_err(charger->dev, + "Value 'constant-charge-current-max-microamp' out of range\n"); + return -EINVAL; + } + + if (chg->fast_uamp == RT5033_CHARGER_FAST_CURRENT_MIN) + reg_data = 0x00; + else if (chg->fast_uamp == RT5033_CHARGER_FAST_CURRENT_MAX) + reg_data = RT5033_CHG_MAX_CURRENT; + else { + val = chg->fast_uamp; + val -= RT5033_CHARGER_FAST_CURRENT_MIN; + val /= RT5033_CHARGER_FAST_CURRENT_STEP_NUM; + reg_data = val; + } + + ret = regmap_update_bits(charger->regmap, RT5033_REG_CHG_CTRL5, + RT5033_CHGCTRL5_ICHG_MASK, + reg_data << RT5033_CHGCTRL5_ICHG_SHIFT); + if (ret) { + dev_err(charger->dev, "Failed regmap update\n"); + return -EINVAL; + } + + return 0; +} + +static inline int rt5033_init_pre_charge(struct rt5033_charger *charger) +{ + struct rt5033_charger_data *chg = charger->chg; + int ret; + unsigned int val; + u8 reg_data; + + /* Set pre-charge threshold voltage */ + if (chg->pre_uvolt < RT5033_CHARGER_PRE_THRESHOLD_LIMIT_MIN || + chg->pre_uvolt > RT5033_CHARGER_PRE_THRESHOLD_LIMIT_MAX) { + dev_err(charger->dev, + "Value 'precharge-upper-limit-microvolt' out of range\n"); + return -EINVAL; + } + + if (chg->pre_uvolt == RT5033_CHARGER_PRE_THRESHOLD_LIMIT_MIN) + reg_data = 0x00; + else if (chg->pre_uvolt == RT5033_CHARGER_PRE_THRESHOLD_LIMIT_MAX) + reg_data = 0x0f; + else { + val = chg->pre_uvolt; + val -= RT5033_CHARGER_PRE_THRESHOLD_LIMIT_MIN; + val /= RT5033_CHARGER_PRE_THRESHOLD_STEP_NUM; + reg_data = val; + } + + ret = regmap_update_bits(charger->regmap, RT5033_REG_CHG_CTRL5, + RT5033_CHGCTRL5_VPREC_MASK, reg_data); + if (ret) { + dev_err(charger->dev, "Failed regmap update\n"); + return -EINVAL; + } + + /* Set pre-charge mode charging current */ + if (chg->pre_uamp < RT5033_CHARGER_PRE_CURRENT_LIMIT_MIN || + chg->pre_uamp > RT5033_CHARGER_PRE_CURRENT_LIMIT_MAX) { + dev_err(charger->dev, + "Value 'precharge-current-microamp' out of range\n"); + return -EINVAL; + } + + if (chg->pre_uamp == RT5033_CHARGER_PRE_CURRENT_LIMIT_MIN) + reg_data = 0x00; + else if (chg->pre_uamp == RT5033_CHARGER_PRE_CURRENT_LIMIT_MAX) + reg_data = RT5033_CHG_MAX_PRE_CURRENT; + else { + val = chg->pre_uamp; + val -= RT5033_CHARGER_PRE_CURRENT_LIMIT_MIN; + val /= RT5033_CHARGER_PRE_CURRENT_STEP_NUM; + reg_data = val; + } + + ret = regmap_update_bits(charger->regmap, RT5033_REG_CHG_CTRL4, + RT5033_CHGCTRL4_IPREC_MASK, + reg_data << RT5033_CHGCTRL4_IPREC_SHIFT); + if (ret) { + dev_err(charger->dev, "Failed regmap update\n"); + return -EINVAL; + } + + return 0; +} + +static int rt5033_charger_reg_init(struct rt5033_charger *charger) +{ + int ret = 0; + + /* Enable charging termination */ + ret = regmap_update_bits(charger->regmap, RT5033_REG_CHG_CTRL1, + RT5033_CHGCTRL1_TE_EN_MASK, RT5033_TE_ENABLE); + if (ret) { + dev_err(charger->dev, "Failed to enable charging termination.\n"); + return -EINVAL; + } + + /* + * Disable minimum input voltage regulation (MIVR), this improves + * the charging performance. + */ + ret = regmap_update_bits(charger->regmap, RT5033_REG_CHG_CTRL4, + RT5033_CHGCTRL4_MIVR_MASK, RT5033_CHARGER_MIVR_DISABLE); + if (ret) { + dev_err(charger->dev, "Failed to disable MIVR.\n"); + return -EINVAL; + } + + ret = rt5033_init_pre_charge(charger); + if (ret) + return ret; + + ret = rt5033_init_fast_charge(charger); + if (ret) + return ret; + + ret = rt5033_init_const_charge(charger); + if (ret) + return ret; + + return 0; +} + +static enum power_supply_property rt5033_charger_props[] = { + POWER_SUPPLY_PROP_STATUS, + POWER_SUPPLY_PROP_CHARGE_TYPE, + POWER_SUPPLY_PROP_CURRENT_MAX, + POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE, + POWER_SUPPLY_PROP_MODEL_NAME, + POWER_SUPPLY_PROP_MANUFACTURER, + POWER_SUPPLY_PROP_ONLINE, +}; + +static int rt5033_charger_get_property(struct power_supply *psy, + enum power_supply_property psp, + union power_supply_propval *val) +{ + struct rt5033_charger *charger = power_supply_get_drvdata(psy); + + switch (psp) { + case POWER_SUPPLY_PROP_STATUS: + val->intval = rt5033_get_charger_state(charger); + break; + case POWER_SUPPLY_PROP_CHARGE_TYPE: + val->intval = rt5033_get_charger_type(charger); + break; + case POWER_SUPPLY_PROP_CURRENT_MAX: + val->intval = rt5033_get_charger_current_limit(charger); + break; + case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE: + val->intval = rt5033_get_charger_const_voltage(charger); + break; + case POWER_SUPPLY_PROP_MODEL_NAME: + val->strval = RT5033_CHARGER_MODEL; + break; + case POWER_SUPPLY_PROP_MANUFACTURER: + val->strval = RT5033_MANUFACTURER; + break; + case POWER_SUPPLY_PROP_ONLINE: + val->intval = (rt5033_get_charger_state(charger) == + POWER_SUPPLY_STATUS_CHARGING); + break; + default: + return -EINVAL; + } + + return 0; +} + +static struct rt5033_charger_data *rt5033_charger_dt_init( + struct rt5033_charger *charger) +{ + struct rt5033_charger_data *chg; + struct power_supply_battery_info *info; + int ret; + + chg = devm_kzalloc(charger->dev, sizeof(*chg), GFP_KERNEL); + if (!chg) + return ERR_PTR(-ENOMEM); + + ret = power_supply_get_battery_info(charger->psy, &info); + if (ret) + return ERR_PTR(dev_err_probe(charger->dev, -EINVAL, + "missing battery info\n")); + + /* Assign data. Validity will be checked in the init functions. */ + chg->pre_uamp = info->precharge_current_ua; + chg->fast_uamp = info->constant_charge_current_max_ua; + chg->eoc_uamp = info->charge_term_current_ua; + chg->pre_uvolt = info->precharge_voltage_max_uv; + chg->const_uvolt = info->constant_charge_voltage_max_uv; + + return chg; +} + +static const struct power_supply_desc rt5033_charger_desc = { + .name = "rt5033-charger", + .type = POWER_SUPPLY_TYPE_USB, + .properties = rt5033_charger_props, + .num_properties = ARRAY_SIZE(rt5033_charger_props), + .get_property = rt5033_charger_get_property, +}; + +static int rt5033_charger_probe(struct platform_device *pdev) +{ + struct rt5033_charger *charger; + struct power_supply_config psy_cfg = {}; + int ret; + + charger = devm_kzalloc(&pdev->dev, sizeof(*charger), GFP_KERNEL); + if (!charger) + return -ENOMEM; + + platform_set_drvdata(pdev, charger); + charger->dev = &pdev->dev; + charger->regmap = dev_get_regmap(pdev->dev.parent, NULL); + + psy_cfg.of_node = pdev->dev.of_node; + psy_cfg.drv_data = charger; + + charger->psy = devm_power_supply_register(&pdev->dev, + &rt5033_charger_desc, + &psy_cfg); + if (IS_ERR(charger->psy)) + return dev_err_probe(&pdev->dev, PTR_ERR(charger->psy), + "Failed to register power supply\n"); + + charger->chg = rt5033_charger_dt_init(charger); + if (IS_ERR_OR_NULL(charger->chg)) + return PTR_ERR(charger->chg); + + ret = rt5033_charger_reg_init(charger); + if (ret) + return ret; + + return 0; +} + +static const struct platform_device_id rt5033_charger_id[] = { + { "rt5033-charger", }, + { } +}; +MODULE_DEVICE_TABLE(platform, rt5033_charger_id); + +static const struct of_device_id rt5033_charger_of_match[] = { + { .compatible = "richtek,rt5033-charger", }, + { } +}; +MODULE_DEVICE_TABLE(of, rt5033_charger_of_match); + +static struct platform_driver rt5033_charger_driver = { + .driver = { + .name = "rt5033-charger", + .of_match_table = rt5033_charger_of_match, + }, + .probe = rt5033_charger_probe, + .id_table = rt5033_charger_id, +}; +module_platform_driver(rt5033_charger_driver); + +MODULE_DESCRIPTION("Richtek RT5033 charger driver"); +MODULE_AUTHOR("Beomho Seo "); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/power/supply/rt9455_charger.c b/drivers/power/supply/rt9455_charger.c index 0149e00f2bf8a1226927dadf5e31c76af5c8e77f..ff4dcf77c78893c4d65f856b1c2a0feabd44c561 100644 --- a/drivers/power/supply/rt9455_charger.c +++ b/drivers/power/supply/rt9455_charger.c @@ -1737,7 +1737,7 @@ MODULE_DEVICE_TABLE(acpi, rt9455_i2c_acpi_match); #endif static struct i2c_driver rt9455_driver = { - .probe_new = rt9455_probe, + .probe = rt9455_probe, .remove = rt9455_remove, .id_table = rt9455_i2c_id_table, .driver = { diff --git a/drivers/power/supply/rt9467-charger.c b/drivers/power/supply/rt9467-charger.c index ea33693b69779ac0928d112ec8ec5d45dc5a90e3..683adb18253dd92fc05f62c6e7622cbd6f3412ec 100644 --- a/drivers/power/supply/rt9467-charger.c +++ b/drivers/power/supply/rt9467-charger.c @@ -1192,7 +1192,7 @@ static int rt9467_charger_probe(struct i2c_client *i2c) i2c_set_clientdata(i2c, data); /* Default pull charge enable gpio to make 'CHG_EN' by SW control only */ - ceb_gpio = devm_gpiod_get_optional(dev, "charge-enable", GPIOD_OUT_LOW); + ceb_gpio = devm_gpiod_get_optional(dev, "charge-enable", GPIOD_OUT_HIGH); if (IS_ERR(ceb_gpio)) return dev_err_probe(dev, PTR_ERR(ceb_gpio), "Failed to config charge enable gpio\n"); @@ -1272,7 +1272,7 @@ static struct i2c_driver rt9467_charger_driver = { .name = "rt9467-charger", .of_match_table = rt9467_charger_of_match_table, }, - .probe_new = rt9467_charger_probe, + .probe = rt9467_charger_probe, }; module_i2c_driver(rt9467_charger_driver); diff --git a/drivers/power/supply/rt9471.c b/drivers/power/supply/rt9471.c index 1ea40876494bc120317f426000eb485eb034fd9a..868b0703d15c52fc096f3de89002d0f31ee73e3c 100644 --- a/drivers/power/supply/rt9471.c +++ b/drivers/power/supply/rt9471.c @@ -919,7 +919,7 @@ static struct i2c_driver rt9471_driver = { .name = "rt9471", .of_match_table = rt9471_of_device_id, }, - .probe_new = rt9471_probe, + .probe = rt9471_probe, .shutdown = rt9471_shutdown, }; module_i2c_driver(rt9471_driver); diff --git a/drivers/power/supply/sbs-battery.c b/drivers/power/supply/sbs-battery.c index c4a95b01463aef9e0e2ca0fba6ed434fbafa5cc5..62a354e0120455cf18536096a7e8d985b07c1d9a 100644 --- a/drivers/power/supply/sbs-battery.c +++ b/drivers/power/supply/sbs-battery.c @@ -1275,7 +1275,7 @@ static const struct of_device_id sbs_dt_ids[] = { MODULE_DEVICE_TABLE(of, sbs_dt_ids); static struct i2c_driver sbs_battery_driver = { - .probe_new = sbs_probe, + .probe = sbs_probe, .alert = sbs_alert, .id_table = sbs_id, .driver = { diff --git a/drivers/power/supply/sbs-charger.c b/drivers/power/supply/sbs-charger.c index a14e89ac0369cae0a0990775eb41fec84d537c4b..f4adde4492707b3a568a628fb94c512d506185b1 100644 --- a/drivers/power/supply/sbs-charger.c +++ b/drivers/power/supply/sbs-charger.c @@ -240,7 +240,7 @@ static const struct i2c_device_id sbs_id[] = { MODULE_DEVICE_TABLE(i2c, sbs_id); static struct i2c_driver sbs_driver = { - .probe_new = sbs_probe, + .probe = sbs_probe, .id_table = sbs_id, .driver = { .name = "sbs-charger", diff --git a/drivers/power/supply/sbs-manager.c b/drivers/power/supply/sbs-manager.c index bde977391fd4c172304e08c9f2430b3d9c97042d..9e4141cffbf930db67d1128d901eb7d5476d0bf8 100644 --- a/drivers/power/supply/sbs-manager.c +++ b/drivers/power/supply/sbs-manager.c @@ -409,7 +409,7 @@ static struct i2c_driver sbsm_driver = { .name = "sbsm", .of_match_table = of_match_ptr(sbsm_dt_ids), }, - .probe_new = sbsm_probe, + .probe = sbsm_probe, .alert = sbsm_alert, .id_table = sbsm_ids }; diff --git a/drivers/power/supply/smb347-charger.c b/drivers/power/supply/smb347-charger.c index b5f0383102824ebfface63580aae6e9f722801f5..c8392933ee285255438a78f5bbd9429f9f1c6764 100644 --- a/drivers/power/supply/smb347-charger.c +++ b/drivers/power/supply/smb347-charger.c @@ -1629,7 +1629,7 @@ static struct i2c_driver smb347_driver = { .name = "smb347", .of_match_table = smb3xx_of_match, }, - .probe_new = smb347_probe, + .probe = smb347_probe, .remove = smb347_remove, .shutdown = smb347_shutdown, .id_table = smb347_id, diff --git a/drivers/power/supply/twl4030_madc_battery.c b/drivers/power/supply/twl4030_madc_battery.c index 48649dcfe3a94d69f68fee10f14cfad6bef9a23f..7fe029673b2203b792ba24addaa407d12072f696 100644 --- a/drivers/power/supply/twl4030_madc_battery.c +++ b/drivers/power/supply/twl4030_madc_battery.c @@ -168,19 +168,13 @@ static int twl4030_madc_bat_get_property(struct power_supply *psy, return 0; } -static void twl4030_madc_bat_ext_changed(struct power_supply *psy) -{ - power_supply_changed(psy); -} - static const struct power_supply_desc twl4030_madc_bat_desc = { .name = "twl4030_battery", .type = POWER_SUPPLY_TYPE_BATTERY, .properties = twl4030_madc_bat_props, .num_properties = ARRAY_SIZE(twl4030_madc_bat_props), .get_property = twl4030_madc_bat_get_property, - .external_power_changed = twl4030_madc_bat_ext_changed, - + .external_power_changed = power_supply_changed, }; static int twl4030_cmp(const void *a, const void *b) diff --git a/drivers/power/supply/ucs1002_power.c b/drivers/power/supply/ucs1002_power.c index 836d44c9fb74f75cddafc5472d256ef7025cfb69..954feba6600b8aa7751386ee4ee7b515192312a9 100644 --- a/drivers/power/supply/ucs1002_power.c +++ b/drivers/power/supply/ucs1002_power.c @@ -680,7 +680,7 @@ static struct i2c_driver ucs1002_driver = { .name = "ucs1002", .of_match_table = ucs1002_of_match, }, - .probe_new = ucs1002_probe, + .probe = ucs1002_probe, }; module_i2c_driver(ucs1002_driver); diff --git a/drivers/power/supply/ug3105_battery.c b/drivers/power/supply/ug3105_battery.c index fbc9668425094dbfa047b63da8659af1b1ca8394..ccc5c4d2e2308195b40a79f8fe6b4f12663d5ec5 100644 --- a/drivers/power/supply/ug3105_battery.c +++ b/drivers/power/supply/ug3105_battery.c @@ -476,7 +476,7 @@ static struct i2c_driver ug3105_i2c_driver = { .name = "ug3105", .pm = &ug3105_pm_ops, }, - .probe_new = ug3105_probe, + .probe = ug3105_probe, .id_table = ug3105_id, }; module_i2c_driver(ug3105_i2c_driver); diff --git a/drivers/powercap/Kconfig b/drivers/powercap/Kconfig index 90d33cd1b670a63e3ad0366640cde16ba92ac70f..69ef8d081c98bd50f142d8bae3ddd36d1d1200cf 100644 --- a/drivers/powercap/Kconfig +++ b/drivers/powercap/Kconfig @@ -18,10 +18,12 @@ if POWERCAP # Client driver configurations go here. config INTEL_RAPL_CORE tristate + depends on PCI + select IOSF_MBI config INTEL_RAPL tristate "Intel RAPL Support via MSR Interface" - depends on X86 && IOSF_MBI + depends on X86 && PCI select INTEL_RAPL_CORE help This enables support for the Intel Running Average Power Limit (RAPL) @@ -33,6 +35,20 @@ config INTEL_RAPL controller, CPU core (Power Plane 0), graphics uncore (Power Plane 1), etc. +config INTEL_RAPL_TPMI + tristate "Intel RAPL Support via TPMI Interface" + depends on X86 + depends on INTEL_TPMI + select INTEL_RAPL_CORE + help + This enables support for the Intel Running Average Power Limit (RAPL) + technology via TPMI interface, which allows power limits to be enforced + and monitored. + + In RAPL, the platform level settings are divided into domains for + fine grained control. These domains include processor package, DRAM + controller, platform, etc. + config IDLE_INJECT bool "Idle injection framework" depends on CPU_IDLE diff --git a/drivers/powercap/Makefile b/drivers/powercap/Makefile index 4474201b4aa7e2b3894d0230fcfbe7cd2a6f654e..5ab0dce565b9acd60d17043cb154f97de1e621da 100644 --- a/drivers/powercap/Makefile +++ b/drivers/powercap/Makefile @@ -5,5 +5,6 @@ obj-$(CONFIG_DTPM_DEVFREQ) += dtpm_devfreq.o obj-$(CONFIG_POWERCAP) += powercap_sys.o obj-$(CONFIG_INTEL_RAPL_CORE) += intel_rapl_common.o obj-$(CONFIG_INTEL_RAPL) += intel_rapl_msr.o +obj-$(CONFIG_INTEL_RAPL_TPMI) += intel_rapl_tpmi.o obj-$(CONFIG_IDLE_INJECT) += idle_inject.o obj-$(CONFIG_ARM_SCMI_POWERCAP) += arm_scmi_powercap.o diff --git a/drivers/powercap/arm_scmi_powercap.c b/drivers/powercap/arm_scmi_powercap.c index 05d0e516176a54c1764eb703a052622587e834f2..5231f6d52ae3af4d903a5f0d9037462086c91297 100644 --- a/drivers/powercap/arm_scmi_powercap.c +++ b/drivers/powercap/arm_scmi_powercap.c @@ -70,10 +70,26 @@ static int scmi_powercap_get_power_uw(struct powercap_zone *pz, return 0; } +static int scmi_powercap_zone_enable_set(struct powercap_zone *pz, bool mode) +{ + struct scmi_powercap_zone *spz = to_scmi_powercap_zone(pz); + + return powercap_ops->cap_enable_set(spz->ph, spz->info->id, mode); +} + +static int scmi_powercap_zone_enable_get(struct powercap_zone *pz, bool *mode) +{ + struct scmi_powercap_zone *spz = to_scmi_powercap_zone(pz); + + return powercap_ops->cap_enable_get(spz->ph, spz->info->id, mode); +} + static const struct powercap_zone_ops zone_ops = { .get_max_power_range_uw = scmi_powercap_get_max_power_range_uw, .get_power_uw = scmi_powercap_get_power_uw, .release = scmi_powercap_zone_release, + .set_enable = scmi_powercap_zone_enable_set, + .get_enable = scmi_powercap_zone_enable_get, }; static void scmi_powercap_normalize_cap(const struct scmi_powercap_zone *spz, diff --git a/drivers/powercap/intel_rapl_common.c b/drivers/powercap/intel_rapl_common.c index 8970c7b80884066175afa09a385b735bca5025f9..4e646e5e48f6800535817b0ba34499d148fa1ebf 100644 --- a/drivers/powercap/intel_rapl_common.c +++ b/drivers/powercap/intel_rapl_common.c @@ -75,6 +75,15 @@ #define PSYS_TIME_WINDOW1_MASK (0x7FULL<<19) #define PSYS_TIME_WINDOW2_MASK (0x7FULL<<51) +/* bitmasks for RAPL TPMI, used by primitive access functions */ +#define TPMI_POWER_LIMIT_MASK 0x3FFFF +#define TPMI_POWER_LIMIT_ENABLE BIT_ULL(62) +#define TPMI_TIME_WINDOW_MASK (0x7FULL<<18) +#define TPMI_INFO_SPEC_MASK 0x3FFFF +#define TPMI_INFO_MIN_MASK (0x3FFFFULL << 18) +#define TPMI_INFO_MAX_MASK (0x3FFFFULL << 36) +#define TPMI_INFO_MAX_TIME_WIN_MASK (0x7FULL << 54) + /* Non HW constants */ #define RAPL_PRIMITIVE_DERIVED BIT(1) /* not from raw data */ #define RAPL_PRIMITIVE_DUMMY BIT(2) @@ -94,26 +103,120 @@ enum unit_type { #define DOMAIN_STATE_INACTIVE BIT(0) #define DOMAIN_STATE_POWER_LIMIT_SET BIT(1) -#define DOMAIN_STATE_BIOS_LOCKED BIT(2) -static const char pl1_name[] = "long_term"; -static const char pl2_name[] = "short_term"; -static const char pl4_name[] = "peak_power"; +static const char *pl_names[NR_POWER_LIMITS] = { + [POWER_LIMIT1] = "long_term", + [POWER_LIMIT2] = "short_term", + [POWER_LIMIT4] = "peak_power", +}; + +enum pl_prims { + PL_ENABLE, + PL_CLAMP, + PL_LIMIT, + PL_TIME_WINDOW, + PL_MAX_POWER, + PL_LOCK, +}; + +static bool is_pl_valid(struct rapl_domain *rd, int pl) +{ + if (pl < POWER_LIMIT1 || pl > POWER_LIMIT4) + return false; + return rd->rpl[pl].name ? true : false; +} + +static int get_pl_lock_prim(struct rapl_domain *rd, int pl) +{ + if (rd->rp->priv->type == RAPL_IF_TPMI) { + if (pl == POWER_LIMIT1) + return PL1_LOCK; + if (pl == POWER_LIMIT2) + return PL2_LOCK; + if (pl == POWER_LIMIT4) + return PL4_LOCK; + } + + /* MSR/MMIO Interface doesn't have Lock bit for PL4 */ + if (pl == POWER_LIMIT4) + return -EINVAL; + + /* + * Power Limit register that supports two power limits has a different + * bit position for the Lock bit. + */ + if (rd->rp->priv->limits[rd->id] & BIT(POWER_LIMIT2)) + return FW_HIGH_LOCK; + return FW_LOCK; +} + +static int get_pl_prim(struct rapl_domain *rd, int pl, enum pl_prims prim) +{ + switch (pl) { + case POWER_LIMIT1: + if (prim == PL_ENABLE) + return PL1_ENABLE; + if (prim == PL_CLAMP && rd->rp->priv->type != RAPL_IF_TPMI) + return PL1_CLAMP; + if (prim == PL_LIMIT) + return POWER_LIMIT1; + if (prim == PL_TIME_WINDOW) + return TIME_WINDOW1; + if (prim == PL_MAX_POWER) + return THERMAL_SPEC_POWER; + if (prim == PL_LOCK) + return get_pl_lock_prim(rd, pl); + return -EINVAL; + case POWER_LIMIT2: + if (prim == PL_ENABLE) + return PL2_ENABLE; + if (prim == PL_CLAMP && rd->rp->priv->type != RAPL_IF_TPMI) + return PL2_CLAMP; + if (prim == PL_LIMIT) + return POWER_LIMIT2; + if (prim == PL_TIME_WINDOW) + return TIME_WINDOW2; + if (prim == PL_MAX_POWER) + return MAX_POWER; + if (prim == PL_LOCK) + return get_pl_lock_prim(rd, pl); + return -EINVAL; + case POWER_LIMIT4: + if (prim == PL_LIMIT) + return POWER_LIMIT4; + if (prim == PL_ENABLE) + return PL4_ENABLE; + /* PL4 would be around two times PL2, use same prim as PL2. */ + if (prim == PL_MAX_POWER) + return MAX_POWER; + if (prim == PL_LOCK) + return get_pl_lock_prim(rd, pl); + return -EINVAL; + default: + return -EINVAL; + } +} #define power_zone_to_rapl_domain(_zone) \ container_of(_zone, struct rapl_domain, power_zone) struct rapl_defaults { u8 floor_freq_reg_addr; - int (*check_unit)(struct rapl_package *rp, int cpu); + int (*check_unit)(struct rapl_domain *rd); void (*set_floor_freq)(struct rapl_domain *rd, bool mode); - u64 (*compute_time_window)(struct rapl_package *rp, u64 val, + u64 (*compute_time_window)(struct rapl_domain *rd, u64 val, bool to_raw); unsigned int dram_domain_energy_unit; unsigned int psys_domain_energy_unit; bool spr_psys_bits; }; -static struct rapl_defaults *rapl_defaults; +static struct rapl_defaults *defaults_msr; +static const struct rapl_defaults defaults_tpmi; + +static struct rapl_defaults *get_defaults(struct rapl_package *rp) +{ + return rp->priv->defaults; +} /* Sideband MBI registers */ #define IOSF_CPU_POWER_BUDGET_CTL_BYT (0x2) @@ -150,6 +253,12 @@ static int rapl_read_data_raw(struct rapl_domain *rd, static int rapl_write_data_raw(struct rapl_domain *rd, enum rapl_primitives prim, unsigned long long value); +static int rapl_read_pl_data(struct rapl_domain *rd, int pl, + enum pl_prims pl_prim, + bool xlate, u64 *data); +static int rapl_write_pl_data(struct rapl_domain *rd, int pl, + enum pl_prims pl_prim, + unsigned long long value); static u64 rapl_unit_xlate(struct rapl_domain *rd, enum unit_type type, u64 value, int to_raw); static void package_power_limit_irq_save(struct rapl_package *rp); @@ -217,7 +326,7 @@ static int find_nr_power_limit(struct rapl_domain *rd) int i, nr_pl = 0; for (i = 0; i < NR_POWER_LIMITS; i++) { - if (rd->rpl[i].name) + if (is_pl_valid(rd, i)) nr_pl++; } @@ -227,37 +336,35 @@ static int find_nr_power_limit(struct rapl_domain *rd) static int set_domain_enable(struct powercap_zone *power_zone, bool mode) { struct rapl_domain *rd = power_zone_to_rapl_domain(power_zone); - - if (rd->state & DOMAIN_STATE_BIOS_LOCKED) - return -EACCES; + struct rapl_defaults *defaults = get_defaults(rd->rp); + int ret; cpus_read_lock(); - rapl_write_data_raw(rd, PL1_ENABLE, mode); - if (rapl_defaults->set_floor_freq) - rapl_defaults->set_floor_freq(rd, mode); + ret = rapl_write_pl_data(rd, POWER_LIMIT1, PL_ENABLE, mode); + if (!ret && defaults->set_floor_freq) + defaults->set_floor_freq(rd, mode); cpus_read_unlock(); - return 0; + return ret; } static int get_domain_enable(struct powercap_zone *power_zone, bool *mode) { struct rapl_domain *rd = power_zone_to_rapl_domain(power_zone); u64 val; + int ret; - if (rd->state & DOMAIN_STATE_BIOS_LOCKED) { + if (rd->rpl[POWER_LIMIT1].locked) { *mode = false; return 0; } cpus_read_lock(); - if (rapl_read_data_raw(rd, PL1_ENABLE, true, &val)) { - cpus_read_unlock(); - return -EIO; - } - *mode = val; + ret = rapl_read_pl_data(rd, POWER_LIMIT1, PL_ENABLE, true, &val); + if (!ret) + *mode = val; cpus_read_unlock(); - return 0; + return ret; } /* per RAPL domain ops, in the order of rapl_domain_type */ @@ -313,8 +420,8 @@ static int contraint_to_pl(struct rapl_domain *rd, int cid) { int i, j; - for (i = 0, j = 0; i < NR_POWER_LIMITS; i++) { - if ((rd->rpl[i].name) && j++ == cid) { + for (i = POWER_LIMIT1, j = 0; i < NR_POWER_LIMITS; i++) { + if (is_pl_valid(rd, i) && j++ == cid) { pr_debug("%s: index %d\n", __func__, i); return i; } @@ -335,36 +442,11 @@ static int set_power_limit(struct powercap_zone *power_zone, int cid, cpus_read_lock(); rd = power_zone_to_rapl_domain(power_zone); id = contraint_to_pl(rd, cid); - if (id < 0) { - ret = id; - goto set_exit; - } - rp = rd->rp; - if (rd->state & DOMAIN_STATE_BIOS_LOCKED) { - dev_warn(&power_zone->dev, - "%s locked by BIOS, monitoring only\n", rd->name); - ret = -EACCES; - goto set_exit; - } - - switch (rd->rpl[id].prim_id) { - case PL1_ENABLE: - rapl_write_data_raw(rd, POWER_LIMIT1, power_limit); - break; - case PL2_ENABLE: - rapl_write_data_raw(rd, POWER_LIMIT2, power_limit); - break; - case PL4_ENABLE: - rapl_write_data_raw(rd, POWER_LIMIT4, power_limit); - break; - default: - ret = -EINVAL; - } + ret = rapl_write_pl_data(rd, id, PL_LIMIT, power_limit); if (!ret) package_power_limit_irq_save(rp); -set_exit: cpus_read_unlock(); return ret; } @@ -374,38 +456,17 @@ static int get_current_power_limit(struct powercap_zone *power_zone, int cid, { struct rapl_domain *rd; u64 val; - int prim; int ret = 0; int id; cpus_read_lock(); rd = power_zone_to_rapl_domain(power_zone); id = contraint_to_pl(rd, cid); - if (id < 0) { - ret = id; - goto get_exit; - } - switch (rd->rpl[id].prim_id) { - case PL1_ENABLE: - prim = POWER_LIMIT1; - break; - case PL2_ENABLE: - prim = POWER_LIMIT2; - break; - case PL4_ENABLE: - prim = POWER_LIMIT4; - break; - default: - cpus_read_unlock(); - return -EINVAL; - } - if (rapl_read_data_raw(rd, prim, true, &val)) - ret = -EIO; - else + ret = rapl_read_pl_data(rd, id, PL_LIMIT, true, &val); + if (!ret) *data = val; -get_exit: cpus_read_unlock(); return ret; @@ -421,23 +482,9 @@ static int set_time_window(struct powercap_zone *power_zone, int cid, cpus_read_lock(); rd = power_zone_to_rapl_domain(power_zone); id = contraint_to_pl(rd, cid); - if (id < 0) { - ret = id; - goto set_time_exit; - } - switch (rd->rpl[id].prim_id) { - case PL1_ENABLE: - rapl_write_data_raw(rd, TIME_WINDOW1, window); - break; - case PL2_ENABLE: - rapl_write_data_raw(rd, TIME_WINDOW2, window); - break; - default: - ret = -EINVAL; - } + ret = rapl_write_pl_data(rd, id, PL_TIME_WINDOW, window); -set_time_exit: cpus_read_unlock(); return ret; } @@ -453,33 +500,11 @@ static int get_time_window(struct powercap_zone *power_zone, int cid, cpus_read_lock(); rd = power_zone_to_rapl_domain(power_zone); id = contraint_to_pl(rd, cid); - if (id < 0) { - ret = id; - goto get_time_exit; - } - switch (rd->rpl[id].prim_id) { - case PL1_ENABLE: - ret = rapl_read_data_raw(rd, TIME_WINDOW1, true, &val); - break; - case PL2_ENABLE: - ret = rapl_read_data_raw(rd, TIME_WINDOW2, true, &val); - break; - case PL4_ENABLE: - /* - * Time window parameter is not applicable for PL4 entry - * so assigining '0' as default value. - */ - val = 0; - break; - default: - cpus_read_unlock(); - return -EINVAL; - } + ret = rapl_read_pl_data(rd, id, PL_TIME_WINDOW, true, &val); if (!ret) *data = val; -get_time_exit: cpus_read_unlock(); return ret; @@ -499,36 +524,23 @@ static const char *get_constraint_name(struct powercap_zone *power_zone, return NULL; } -static int get_max_power(struct powercap_zone *power_zone, int id, u64 *data) +static int get_max_power(struct powercap_zone *power_zone, int cid, u64 *data) { struct rapl_domain *rd; u64 val; - int prim; int ret = 0; + int id; cpus_read_lock(); rd = power_zone_to_rapl_domain(power_zone); - switch (rd->rpl[id].prim_id) { - case PL1_ENABLE: - prim = THERMAL_SPEC_POWER; - break; - case PL2_ENABLE: - prim = MAX_POWER; - break; - case PL4_ENABLE: - prim = MAX_POWER; - break; - default: - cpus_read_unlock(); - return -EINVAL; - } - if (rapl_read_data_raw(rd, prim, true, &val)) - ret = -EIO; - else + id = contraint_to_pl(rd, cid); + + ret = rapl_read_pl_data(rd, id, PL_MAX_POWER, true, &val); + if (!ret) *data = val; /* As a generalization rule, PL4 would be around two times PL2. */ - if (rd->rpl[id].prim_id == PL4_ENABLE) + if (id == POWER_LIMIT4) *data = *data * 2; cpus_read_unlock(); @@ -545,6 +557,12 @@ static const struct powercap_zone_constraint_ops constraint_ops = { .get_name = get_constraint_name, }; +/* Return the id used for read_raw/write_raw callback */ +static int get_rid(struct rapl_package *rp) +{ + return rp->lead_cpu >= 0 ? rp->lead_cpu : rp->id; +} + /* called after domain detection and package level data are set */ static void rapl_init_domains(struct rapl_package *rp) { @@ -554,6 +572,7 @@ static void rapl_init_domains(struct rapl_package *rp) for (i = 0; i < RAPL_DOMAIN_MAX; i++) { unsigned int mask = rp->domain_map & (1 << i); + int t; if (!mask) continue; @@ -562,51 +581,26 @@ static void rapl_init_domains(struct rapl_package *rp) if (i == RAPL_DOMAIN_PLATFORM && rp->id > 0) { snprintf(rd->name, RAPL_DOMAIN_NAME_LENGTH, "psys-%d", - topology_physical_package_id(rp->lead_cpu)); - } else + rp->lead_cpu >= 0 ? topology_physical_package_id(rp->lead_cpu) : + rp->id); + } else { snprintf(rd->name, RAPL_DOMAIN_NAME_LENGTH, "%s", rapl_domain_names[i]); + } rd->id = i; - rd->rpl[0].prim_id = PL1_ENABLE; - rd->rpl[0].name = pl1_name; - /* - * The PL2 power domain is applicable for limits two - * and limits three - */ - if (rp->priv->limits[i] >= 2) { - rd->rpl[1].prim_id = PL2_ENABLE; - rd->rpl[1].name = pl2_name; - } + /* PL1 is supported by default */ + rp->priv->limits[i] |= BIT(POWER_LIMIT1); - /* Enable PL4 domain if the total power limits are three */ - if (rp->priv->limits[i] == 3) { - rd->rpl[2].prim_id = PL4_ENABLE; - rd->rpl[2].name = pl4_name; + for (t = POWER_LIMIT1; t < NR_POWER_LIMITS; t++) { + if (rp->priv->limits[i] & BIT(t)) + rd->rpl[t].name = pl_names[t]; } for (j = 0; j < RAPL_DOMAIN_REG_MAX; j++) rd->regs[j] = rp->priv->regs[i][j]; - switch (i) { - case RAPL_DOMAIN_DRAM: - rd->domain_energy_unit = - rapl_defaults->dram_domain_energy_unit; - if (rd->domain_energy_unit) - pr_info("DRAM domain energy unit %dpj\n", - rd->domain_energy_unit); - break; - case RAPL_DOMAIN_PLATFORM: - rd->domain_energy_unit = - rapl_defaults->psys_domain_energy_unit; - if (rd->domain_energy_unit) - pr_info("Platform domain energy unit %dpj\n", - rd->domain_energy_unit); - break; - default: - break; - } rd++; } } @@ -615,23 +609,19 @@ static u64 rapl_unit_xlate(struct rapl_domain *rd, enum unit_type type, u64 value, int to_raw) { u64 units = 1; - struct rapl_package *rp = rd->rp; + struct rapl_defaults *defaults = get_defaults(rd->rp); u64 scale = 1; switch (type) { case POWER_UNIT: - units = rp->power_unit; + units = rd->power_unit; break; case ENERGY_UNIT: scale = ENERGY_UNIT_SCALE; - /* per domain unit takes precedence */ - if (rd->domain_energy_unit) - units = rd->domain_energy_unit; - else - units = rp->energy_unit; + units = rd->energy_unit; break; case TIME_UNIT: - return rapl_defaults->compute_time_window(rp, value, to_raw); + return defaults->compute_time_window(rd, value, to_raw); case ARBITRARY_UNIT: default: return value; @@ -645,67 +635,141 @@ static u64 rapl_unit_xlate(struct rapl_domain *rd, enum unit_type type, return div64_u64(value, scale); } -/* in the order of enum rapl_primitives */ -static struct rapl_primitive_info rpi[] = { +/* RAPL primitives for MSR and MMIO I/F */ +static struct rapl_primitive_info rpi_msr[NR_RAPL_PRIMITIVES] = { /* name, mask, shift, msr index, unit divisor */ - PRIMITIVE_INFO_INIT(ENERGY_COUNTER, ENERGY_STATUS_MASK, 0, - RAPL_DOMAIN_REG_STATUS, ENERGY_UNIT, 0), - PRIMITIVE_INFO_INIT(POWER_LIMIT1, POWER_LIMIT1_MASK, 0, + [POWER_LIMIT1] = PRIMITIVE_INFO_INIT(POWER_LIMIT1, POWER_LIMIT1_MASK, 0, RAPL_DOMAIN_REG_LIMIT, POWER_UNIT, 0), - PRIMITIVE_INFO_INIT(POWER_LIMIT2, POWER_LIMIT2_MASK, 32, + [POWER_LIMIT2] = PRIMITIVE_INFO_INIT(POWER_LIMIT2, POWER_LIMIT2_MASK, 32, RAPL_DOMAIN_REG_LIMIT, POWER_UNIT, 0), - PRIMITIVE_INFO_INIT(POWER_LIMIT4, POWER_LIMIT4_MASK, 0, + [POWER_LIMIT4] = PRIMITIVE_INFO_INIT(POWER_LIMIT4, POWER_LIMIT4_MASK, 0, RAPL_DOMAIN_REG_PL4, POWER_UNIT, 0), - PRIMITIVE_INFO_INIT(FW_LOCK, POWER_LOW_LOCK, 31, + [ENERGY_COUNTER] = PRIMITIVE_INFO_INIT(ENERGY_COUNTER, ENERGY_STATUS_MASK, 0, + RAPL_DOMAIN_REG_STATUS, ENERGY_UNIT, 0), + [FW_LOCK] = PRIMITIVE_INFO_INIT(FW_LOCK, POWER_LOW_LOCK, 31, RAPL_DOMAIN_REG_LIMIT, ARBITRARY_UNIT, 0), - PRIMITIVE_INFO_INIT(PL1_ENABLE, POWER_LIMIT1_ENABLE, 15, + [FW_HIGH_LOCK] = PRIMITIVE_INFO_INIT(FW_LOCK, POWER_HIGH_LOCK, 63, RAPL_DOMAIN_REG_LIMIT, ARBITRARY_UNIT, 0), - PRIMITIVE_INFO_INIT(PL1_CLAMP, POWER_LIMIT1_CLAMP, 16, + [PL1_ENABLE] = PRIMITIVE_INFO_INIT(PL1_ENABLE, POWER_LIMIT1_ENABLE, 15, RAPL_DOMAIN_REG_LIMIT, ARBITRARY_UNIT, 0), - PRIMITIVE_INFO_INIT(PL2_ENABLE, POWER_LIMIT2_ENABLE, 47, + [PL1_CLAMP] = PRIMITIVE_INFO_INIT(PL1_CLAMP, POWER_LIMIT1_CLAMP, 16, RAPL_DOMAIN_REG_LIMIT, ARBITRARY_UNIT, 0), - PRIMITIVE_INFO_INIT(PL2_CLAMP, POWER_LIMIT2_CLAMP, 48, + [PL2_ENABLE] = PRIMITIVE_INFO_INIT(PL2_ENABLE, POWER_LIMIT2_ENABLE, 47, RAPL_DOMAIN_REG_LIMIT, ARBITRARY_UNIT, 0), - PRIMITIVE_INFO_INIT(PL4_ENABLE, POWER_LIMIT4_MASK, 0, + [PL2_CLAMP] = PRIMITIVE_INFO_INIT(PL2_CLAMP, POWER_LIMIT2_CLAMP, 48, + RAPL_DOMAIN_REG_LIMIT, ARBITRARY_UNIT, 0), + [PL4_ENABLE] = PRIMITIVE_INFO_INIT(PL4_ENABLE, POWER_LIMIT4_MASK, 0, RAPL_DOMAIN_REG_PL4, ARBITRARY_UNIT, 0), - PRIMITIVE_INFO_INIT(TIME_WINDOW1, TIME_WINDOW1_MASK, 17, + [TIME_WINDOW1] = PRIMITIVE_INFO_INIT(TIME_WINDOW1, TIME_WINDOW1_MASK, 17, RAPL_DOMAIN_REG_LIMIT, TIME_UNIT, 0), - PRIMITIVE_INFO_INIT(TIME_WINDOW2, TIME_WINDOW2_MASK, 49, + [TIME_WINDOW2] = PRIMITIVE_INFO_INIT(TIME_WINDOW2, TIME_WINDOW2_MASK, 49, RAPL_DOMAIN_REG_LIMIT, TIME_UNIT, 0), - PRIMITIVE_INFO_INIT(THERMAL_SPEC_POWER, POWER_INFO_THERMAL_SPEC_MASK, + [THERMAL_SPEC_POWER] = PRIMITIVE_INFO_INIT(THERMAL_SPEC_POWER, POWER_INFO_THERMAL_SPEC_MASK, 0, RAPL_DOMAIN_REG_INFO, POWER_UNIT, 0), - PRIMITIVE_INFO_INIT(MAX_POWER, POWER_INFO_MAX_MASK, 32, + [MAX_POWER] = PRIMITIVE_INFO_INIT(MAX_POWER, POWER_INFO_MAX_MASK, 32, RAPL_DOMAIN_REG_INFO, POWER_UNIT, 0), - PRIMITIVE_INFO_INIT(MIN_POWER, POWER_INFO_MIN_MASK, 16, + [MIN_POWER] = PRIMITIVE_INFO_INIT(MIN_POWER, POWER_INFO_MIN_MASK, 16, RAPL_DOMAIN_REG_INFO, POWER_UNIT, 0), - PRIMITIVE_INFO_INIT(MAX_TIME_WINDOW, POWER_INFO_MAX_TIME_WIN_MASK, 48, + [MAX_TIME_WINDOW] = PRIMITIVE_INFO_INIT(MAX_TIME_WINDOW, POWER_INFO_MAX_TIME_WIN_MASK, 48, RAPL_DOMAIN_REG_INFO, TIME_UNIT, 0), - PRIMITIVE_INFO_INIT(THROTTLED_TIME, PERF_STATUS_THROTTLE_TIME_MASK, 0, + [THROTTLED_TIME] = PRIMITIVE_INFO_INIT(THROTTLED_TIME, PERF_STATUS_THROTTLE_TIME_MASK, 0, RAPL_DOMAIN_REG_PERF, TIME_UNIT, 0), - PRIMITIVE_INFO_INIT(PRIORITY_LEVEL, PP_POLICY_MASK, 0, + [PRIORITY_LEVEL] = PRIMITIVE_INFO_INIT(PRIORITY_LEVEL, PP_POLICY_MASK, 0, RAPL_DOMAIN_REG_POLICY, ARBITRARY_UNIT, 0), - PRIMITIVE_INFO_INIT(PSYS_POWER_LIMIT1, PSYS_POWER_LIMIT1_MASK, 0, + [PSYS_POWER_LIMIT1] = PRIMITIVE_INFO_INIT(PSYS_POWER_LIMIT1, PSYS_POWER_LIMIT1_MASK, 0, RAPL_DOMAIN_REG_LIMIT, POWER_UNIT, 0), - PRIMITIVE_INFO_INIT(PSYS_POWER_LIMIT2, PSYS_POWER_LIMIT2_MASK, 32, + [PSYS_POWER_LIMIT2] = PRIMITIVE_INFO_INIT(PSYS_POWER_LIMIT2, PSYS_POWER_LIMIT2_MASK, 32, RAPL_DOMAIN_REG_LIMIT, POWER_UNIT, 0), - PRIMITIVE_INFO_INIT(PSYS_PL1_ENABLE, PSYS_POWER_LIMIT1_ENABLE, 17, + [PSYS_PL1_ENABLE] = PRIMITIVE_INFO_INIT(PSYS_PL1_ENABLE, PSYS_POWER_LIMIT1_ENABLE, 17, RAPL_DOMAIN_REG_LIMIT, ARBITRARY_UNIT, 0), - PRIMITIVE_INFO_INIT(PSYS_PL2_ENABLE, PSYS_POWER_LIMIT2_ENABLE, 49, + [PSYS_PL2_ENABLE] = PRIMITIVE_INFO_INIT(PSYS_PL2_ENABLE, PSYS_POWER_LIMIT2_ENABLE, 49, RAPL_DOMAIN_REG_LIMIT, ARBITRARY_UNIT, 0), - PRIMITIVE_INFO_INIT(PSYS_TIME_WINDOW1, PSYS_TIME_WINDOW1_MASK, 19, + [PSYS_TIME_WINDOW1] = PRIMITIVE_INFO_INIT(PSYS_TIME_WINDOW1, PSYS_TIME_WINDOW1_MASK, 19, RAPL_DOMAIN_REG_LIMIT, TIME_UNIT, 0), - PRIMITIVE_INFO_INIT(PSYS_TIME_WINDOW2, PSYS_TIME_WINDOW2_MASK, 51, + [PSYS_TIME_WINDOW2] = PRIMITIVE_INFO_INIT(PSYS_TIME_WINDOW2, PSYS_TIME_WINDOW2_MASK, 51, RAPL_DOMAIN_REG_LIMIT, TIME_UNIT, 0), /* non-hardware */ - PRIMITIVE_INFO_INIT(AVERAGE_POWER, 0, 0, 0, POWER_UNIT, + [AVERAGE_POWER] = PRIMITIVE_INFO_INIT(AVERAGE_POWER, 0, 0, 0, POWER_UNIT, RAPL_PRIMITIVE_DERIVED), - {NULL, 0, 0, 0}, }; +/* RAPL primitives for TPMI I/F */ +static struct rapl_primitive_info rpi_tpmi[NR_RAPL_PRIMITIVES] = { + /* name, mask, shift, msr index, unit divisor */ + [POWER_LIMIT1] = PRIMITIVE_INFO_INIT(POWER_LIMIT1, TPMI_POWER_LIMIT_MASK, 0, + RAPL_DOMAIN_REG_LIMIT, POWER_UNIT, 0), + [POWER_LIMIT2] = PRIMITIVE_INFO_INIT(POWER_LIMIT2, TPMI_POWER_LIMIT_MASK, 0, + RAPL_DOMAIN_REG_PL2, POWER_UNIT, 0), + [POWER_LIMIT4] = PRIMITIVE_INFO_INIT(POWER_LIMIT4, TPMI_POWER_LIMIT_MASK, 0, + RAPL_DOMAIN_REG_PL4, POWER_UNIT, 0), + [ENERGY_COUNTER] = PRIMITIVE_INFO_INIT(ENERGY_COUNTER, ENERGY_STATUS_MASK, 0, + RAPL_DOMAIN_REG_STATUS, ENERGY_UNIT, 0), + [PL1_LOCK] = PRIMITIVE_INFO_INIT(PL1_LOCK, POWER_HIGH_LOCK, 63, + RAPL_DOMAIN_REG_LIMIT, ARBITRARY_UNIT, 0), + [PL2_LOCK] = PRIMITIVE_INFO_INIT(PL2_LOCK, POWER_HIGH_LOCK, 63, + RAPL_DOMAIN_REG_PL2, ARBITRARY_UNIT, 0), + [PL4_LOCK] = PRIMITIVE_INFO_INIT(PL4_LOCK, POWER_HIGH_LOCK, 63, + RAPL_DOMAIN_REG_PL4, ARBITRARY_UNIT, 0), + [PL1_ENABLE] = PRIMITIVE_INFO_INIT(PL1_ENABLE, TPMI_POWER_LIMIT_ENABLE, 62, + RAPL_DOMAIN_REG_LIMIT, ARBITRARY_UNIT, 0), + [PL2_ENABLE] = PRIMITIVE_INFO_INIT(PL2_ENABLE, TPMI_POWER_LIMIT_ENABLE, 62, + RAPL_DOMAIN_REG_PL2, ARBITRARY_UNIT, 0), + [PL4_ENABLE] = PRIMITIVE_INFO_INIT(PL4_ENABLE, TPMI_POWER_LIMIT_ENABLE, 62, + RAPL_DOMAIN_REG_PL4, ARBITRARY_UNIT, 0), + [TIME_WINDOW1] = PRIMITIVE_INFO_INIT(TIME_WINDOW1, TPMI_TIME_WINDOW_MASK, 18, + RAPL_DOMAIN_REG_LIMIT, TIME_UNIT, 0), + [TIME_WINDOW2] = PRIMITIVE_INFO_INIT(TIME_WINDOW2, TPMI_TIME_WINDOW_MASK, 18, + RAPL_DOMAIN_REG_PL2, TIME_UNIT, 0), + [THERMAL_SPEC_POWER] = PRIMITIVE_INFO_INIT(THERMAL_SPEC_POWER, TPMI_INFO_SPEC_MASK, 0, + RAPL_DOMAIN_REG_INFO, POWER_UNIT, 0), + [MAX_POWER] = PRIMITIVE_INFO_INIT(MAX_POWER, TPMI_INFO_MAX_MASK, 36, + RAPL_DOMAIN_REG_INFO, POWER_UNIT, 0), + [MIN_POWER] = PRIMITIVE_INFO_INIT(MIN_POWER, TPMI_INFO_MIN_MASK, 18, + RAPL_DOMAIN_REG_INFO, POWER_UNIT, 0), + [MAX_TIME_WINDOW] = PRIMITIVE_INFO_INIT(MAX_TIME_WINDOW, TPMI_INFO_MAX_TIME_WIN_MASK, 54, + RAPL_DOMAIN_REG_INFO, TIME_UNIT, 0), + [THROTTLED_TIME] = PRIMITIVE_INFO_INIT(THROTTLED_TIME, PERF_STATUS_THROTTLE_TIME_MASK, 0, + RAPL_DOMAIN_REG_PERF, TIME_UNIT, 0), + /* non-hardware */ + [AVERAGE_POWER] = PRIMITIVE_INFO_INIT(AVERAGE_POWER, 0, 0, 0, + POWER_UNIT, RAPL_PRIMITIVE_DERIVED), +}; + +static struct rapl_primitive_info *get_rpi(struct rapl_package *rp, int prim) +{ + struct rapl_primitive_info *rpi = rp->priv->rpi; + + if (prim < 0 || prim > NR_RAPL_PRIMITIVES || !rpi) + return NULL; + + return &rpi[prim]; +} + +static int rapl_config(struct rapl_package *rp) +{ + switch (rp->priv->type) { + /* MMIO I/F shares the same register layout as MSR registers */ + case RAPL_IF_MMIO: + case RAPL_IF_MSR: + rp->priv->defaults = (void *)defaults_msr; + rp->priv->rpi = (void *)rpi_msr; + break; + case RAPL_IF_TPMI: + rp->priv->defaults = (void *)&defaults_tpmi; + rp->priv->rpi = (void *)rpi_tpmi; + break; + default: + return -EINVAL; + } + return 0; +} + static enum rapl_primitives prim_fixups(struct rapl_domain *rd, enum rapl_primitives prim) { - if (!rapl_defaults->spr_psys_bits) + struct rapl_defaults *defaults = get_defaults(rd->rp); + + if (!defaults->spr_psys_bits) return prim; if (rd->id != RAPL_DOMAIN_PLATFORM) @@ -747,41 +811,33 @@ static int rapl_read_data_raw(struct rapl_domain *rd, { u64 value; enum rapl_primitives prim_fixed = prim_fixups(rd, prim); - struct rapl_primitive_info *rp = &rpi[prim_fixed]; + struct rapl_primitive_info *rpi = get_rpi(rd->rp, prim_fixed); struct reg_action ra; - int cpu; - if (!rp->name || rp->flag & RAPL_PRIMITIVE_DUMMY) + if (!rpi || !rpi->name || rpi->flag & RAPL_PRIMITIVE_DUMMY) return -EINVAL; - ra.reg = rd->regs[rp->id]; + ra.reg = rd->regs[rpi->id]; if (!ra.reg) return -EINVAL; - cpu = rd->rp->lead_cpu; - - /* domain with 2 limits has different bit */ - if (prim == FW_LOCK && rd->rp->priv->limits[rd->id] == 2) { - rp->mask = POWER_HIGH_LOCK; - rp->shift = 63; - } /* non-hardware data are collected by the polling thread */ - if (rp->flag & RAPL_PRIMITIVE_DERIVED) { + if (rpi->flag & RAPL_PRIMITIVE_DERIVED) { *data = rd->rdd.primitives[prim]; return 0; } - ra.mask = rp->mask; + ra.mask = rpi->mask; - if (rd->rp->priv->read_raw(cpu, &ra)) { - pr_debug("failed to read reg 0x%llx on cpu %d\n", ra.reg, cpu); + if (rd->rp->priv->read_raw(get_rid(rd->rp), &ra)) { + pr_debug("failed to read reg 0x%llx for %s:%s\n", ra.reg, rd->rp->name, rd->name); return -EIO; } - value = ra.value >> rp->shift; + value = ra.value >> rpi->shift; if (xlate) - *data = rapl_unit_xlate(rd, rp->unit, value, 0); + *data = rapl_unit_xlate(rd, rpi->unit, value, 0); else *data = value; @@ -794,28 +850,56 @@ static int rapl_write_data_raw(struct rapl_domain *rd, unsigned long long value) { enum rapl_primitives prim_fixed = prim_fixups(rd, prim); - struct rapl_primitive_info *rp = &rpi[prim_fixed]; - int cpu; + struct rapl_primitive_info *rpi = get_rpi(rd->rp, prim_fixed); u64 bits; struct reg_action ra; int ret; - cpu = rd->rp->lead_cpu; - bits = rapl_unit_xlate(rd, rp->unit, value, 1); - bits <<= rp->shift; - bits &= rp->mask; + if (!rpi || !rpi->name || rpi->flag & RAPL_PRIMITIVE_DUMMY) + return -EINVAL; + + bits = rapl_unit_xlate(rd, rpi->unit, value, 1); + bits <<= rpi->shift; + bits &= rpi->mask; memset(&ra, 0, sizeof(ra)); - ra.reg = rd->regs[rp->id]; - ra.mask = rp->mask; + ra.reg = rd->regs[rpi->id]; + ra.mask = rpi->mask; ra.value = bits; - ret = rd->rp->priv->write_raw(cpu, &ra); + ret = rd->rp->priv->write_raw(get_rid(rd->rp), &ra); return ret; } +static int rapl_read_pl_data(struct rapl_domain *rd, int pl, + enum pl_prims pl_prim, bool xlate, u64 *data) +{ + enum rapl_primitives prim = get_pl_prim(rd, pl, pl_prim); + + if (!is_pl_valid(rd, pl)) + return -EINVAL; + + return rapl_read_data_raw(rd, prim, xlate, data); +} + +static int rapl_write_pl_data(struct rapl_domain *rd, int pl, + enum pl_prims pl_prim, + unsigned long long value) +{ + enum rapl_primitives prim = get_pl_prim(rd, pl, pl_prim); + + if (!is_pl_valid(rd, pl)) + return -EINVAL; + + if (rd->rpl[pl].locked) { + pr_warn("%s:%s:%s locked by BIOS\n", rd->rp->name, rd->name, pl_names[pl]); + return -EACCES; + } + + return rapl_write_data_raw(rd, prim, value); +} /* * Raw RAPL data stored in MSRs are in certain scales. We need to * convert them into standard units based on the units reported in @@ -827,58 +911,58 @@ static int rapl_write_data_raw(struct rapl_domain *rd, * power unit : microWatts : Represented in milliWatts by default * time unit : microseconds: Represented in seconds by default */ -static int rapl_check_unit_core(struct rapl_package *rp, int cpu) +static int rapl_check_unit_core(struct rapl_domain *rd) { struct reg_action ra; u32 value; - ra.reg = rp->priv->reg_unit; + ra.reg = rd->regs[RAPL_DOMAIN_REG_UNIT]; ra.mask = ~0; - if (rp->priv->read_raw(cpu, &ra)) { - pr_err("Failed to read power unit REG 0x%llx on CPU %d, exit.\n", - rp->priv->reg_unit, cpu); + if (rd->rp->priv->read_raw(get_rid(rd->rp), &ra)) { + pr_err("Failed to read power unit REG 0x%llx on %s:%s, exit.\n", + ra.reg, rd->rp->name, rd->name); return -ENODEV; } value = (ra.value & ENERGY_UNIT_MASK) >> ENERGY_UNIT_OFFSET; - rp->energy_unit = ENERGY_UNIT_SCALE * 1000000 / (1 << value); + rd->energy_unit = ENERGY_UNIT_SCALE * 1000000 / (1 << value); value = (ra.value & POWER_UNIT_MASK) >> POWER_UNIT_OFFSET; - rp->power_unit = 1000000 / (1 << value); + rd->power_unit = 1000000 / (1 << value); value = (ra.value & TIME_UNIT_MASK) >> TIME_UNIT_OFFSET; - rp->time_unit = 1000000 / (1 << value); + rd->time_unit = 1000000 / (1 << value); - pr_debug("Core CPU %s energy=%dpJ, time=%dus, power=%duW\n", - rp->name, rp->energy_unit, rp->time_unit, rp->power_unit); + pr_debug("Core CPU %s:%s energy=%dpJ, time=%dus, power=%duW\n", + rd->rp->name, rd->name, rd->energy_unit, rd->time_unit, rd->power_unit); return 0; } -static int rapl_check_unit_atom(struct rapl_package *rp, int cpu) +static int rapl_check_unit_atom(struct rapl_domain *rd) { struct reg_action ra; u32 value; - ra.reg = rp->priv->reg_unit; + ra.reg = rd->regs[RAPL_DOMAIN_REG_UNIT]; ra.mask = ~0; - if (rp->priv->read_raw(cpu, &ra)) { - pr_err("Failed to read power unit REG 0x%llx on CPU %d, exit.\n", - rp->priv->reg_unit, cpu); + if (rd->rp->priv->read_raw(get_rid(rd->rp), &ra)) { + pr_err("Failed to read power unit REG 0x%llx on %s:%s, exit.\n", + ra.reg, rd->rp->name, rd->name); return -ENODEV; } value = (ra.value & ENERGY_UNIT_MASK) >> ENERGY_UNIT_OFFSET; - rp->energy_unit = ENERGY_UNIT_SCALE * 1 << value; + rd->energy_unit = ENERGY_UNIT_SCALE * 1 << value; value = (ra.value & POWER_UNIT_MASK) >> POWER_UNIT_OFFSET; - rp->power_unit = (1 << value) * 1000; + rd->power_unit = (1 << value) * 1000; value = (ra.value & TIME_UNIT_MASK) >> TIME_UNIT_OFFSET; - rp->time_unit = 1000000 / (1 << value); + rd->time_unit = 1000000 / (1 << value); - pr_debug("Atom %s energy=%dpJ, time=%dus, power=%duW\n", - rp->name, rp->energy_unit, rp->time_unit, rp->power_unit); + pr_debug("Atom %s:%s energy=%dpJ, time=%dus, power=%duW\n", + rd->rp->name, rd->name, rd->energy_unit, rd->time_unit, rd->power_unit); return 0; } @@ -910,6 +994,9 @@ static void power_limit_irq_save_cpu(void *info) static void package_power_limit_irq_save(struct rapl_package *rp) { + if (rp->lead_cpu < 0) + return; + if (!boot_cpu_has(X86_FEATURE_PTS) || !boot_cpu_has(X86_FEATURE_PLN)) return; @@ -924,6 +1011,9 @@ static void package_power_limit_irq_restore(struct rapl_package *rp) { u32 l, h; + if (rp->lead_cpu < 0) + return; + if (!boot_cpu_has(X86_FEATURE_PTS) || !boot_cpu_has(X86_FEATURE_PLN)) return; @@ -943,33 +1033,33 @@ static void package_power_limit_irq_restore(struct rapl_package *rp) static void set_floor_freq_default(struct rapl_domain *rd, bool mode) { - int nr_powerlimit = find_nr_power_limit(rd); + int i; /* always enable clamp such that p-state can go below OS requested * range. power capping priority over guranteed frequency. */ - rapl_write_data_raw(rd, PL1_CLAMP, mode); + rapl_write_pl_data(rd, POWER_LIMIT1, PL_CLAMP, mode); - /* some domains have pl2 */ - if (nr_powerlimit > 1) { - rapl_write_data_raw(rd, PL2_ENABLE, mode); - rapl_write_data_raw(rd, PL2_CLAMP, mode); + for (i = POWER_LIMIT2; i < NR_POWER_LIMITS; i++) { + rapl_write_pl_data(rd, i, PL_ENABLE, mode); + rapl_write_pl_data(rd, i, PL_CLAMP, mode); } } static void set_floor_freq_atom(struct rapl_domain *rd, bool enable) { static u32 power_ctrl_orig_val; + struct rapl_defaults *defaults = get_defaults(rd->rp); u32 mdata; - if (!rapl_defaults->floor_freq_reg_addr) { + if (!defaults->floor_freq_reg_addr) { pr_err("Invalid floor frequency config register\n"); return; } if (!power_ctrl_orig_val) iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_CR_READ, - rapl_defaults->floor_freq_reg_addr, + defaults->floor_freq_reg_addr, &power_ctrl_orig_val); mdata = power_ctrl_orig_val; if (enable) { @@ -977,10 +1067,10 @@ static void set_floor_freq_atom(struct rapl_domain *rd, bool enable) mdata |= 1 << 8; } iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_CR_WRITE, - rapl_defaults->floor_freq_reg_addr, mdata); + defaults->floor_freq_reg_addr, mdata); } -static u64 rapl_compute_time_window_core(struct rapl_package *rp, u64 value, +static u64 rapl_compute_time_window_core(struct rapl_domain *rd, u64 value, bool to_raw) { u64 f, y; /* fraction and exp. used for time unit */ @@ -992,12 +1082,12 @@ static u64 rapl_compute_time_window_core(struct rapl_package *rp, u64 value, if (!to_raw) { f = (value & 0x60) >> 5; y = value & 0x1f; - value = (1 << y) * (4 + f) * rp->time_unit / 4; + value = (1 << y) * (4 + f) * rd->time_unit / 4; } else { - if (value < rp->time_unit) + if (value < rd->time_unit) return 0; - do_div(value, rp->time_unit); + do_div(value, rd->time_unit); y = ilog2(value); /* @@ -1013,7 +1103,7 @@ static u64 rapl_compute_time_window_core(struct rapl_package *rp, u64 value, return value; } -static u64 rapl_compute_time_window_atom(struct rapl_package *rp, u64 value, +static u64 rapl_compute_time_window_atom(struct rapl_domain *rd, u64 value, bool to_raw) { /* @@ -1021,13 +1111,56 @@ static u64 rapl_compute_time_window_atom(struct rapl_package *rp, u64 value, * where time_unit is default to 1 sec. Never 0. */ if (!to_raw) - return (value) ? value * rp->time_unit : rp->time_unit; + return (value) ? value * rd->time_unit : rd->time_unit; - value = div64_u64(value, rp->time_unit); + value = div64_u64(value, rd->time_unit); return value; } +/* TPMI Unit register has different layout */ +#define TPMI_POWER_UNIT_OFFSET POWER_UNIT_OFFSET +#define TPMI_POWER_UNIT_MASK POWER_UNIT_MASK +#define TPMI_ENERGY_UNIT_OFFSET 0x06 +#define TPMI_ENERGY_UNIT_MASK 0x7C0 +#define TPMI_TIME_UNIT_OFFSET 0x0C +#define TPMI_TIME_UNIT_MASK 0xF000 + +static int rapl_check_unit_tpmi(struct rapl_domain *rd) +{ + struct reg_action ra; + u32 value; + + ra.reg = rd->regs[RAPL_DOMAIN_REG_UNIT]; + ra.mask = ~0; + if (rd->rp->priv->read_raw(get_rid(rd->rp), &ra)) { + pr_err("Failed to read power unit REG 0x%llx on %s:%s, exit.\n", + ra.reg, rd->rp->name, rd->name); + return -ENODEV; + } + + value = (ra.value & TPMI_ENERGY_UNIT_MASK) >> TPMI_ENERGY_UNIT_OFFSET; + rd->energy_unit = ENERGY_UNIT_SCALE * 1000000 / (1 << value); + + value = (ra.value & TPMI_POWER_UNIT_MASK) >> TPMI_POWER_UNIT_OFFSET; + rd->power_unit = 1000000 / (1 << value); + + value = (ra.value & TPMI_TIME_UNIT_MASK) >> TPMI_TIME_UNIT_OFFSET; + rd->time_unit = 1000000 / (1 << value); + + pr_debug("Core CPU %s:%s energy=%dpJ, time=%dus, power=%duW\n", + rd->rp->name, rd->name, rd->energy_unit, rd->time_unit, rd->power_unit); + + return 0; +} + +static const struct rapl_defaults defaults_tpmi = { + .check_unit = rapl_check_unit_tpmi, + /* Reuse existing logic, ignore the PL_CLAMP failures and enable all Power Limits */ + .set_floor_freq = set_floor_freq_default, + .compute_time_window = rapl_compute_time_window_core, +}; + static const struct rapl_defaults rapl_defaults_core = { .floor_freq_reg_addr = 0, .check_unit = rapl_check_unit_core, @@ -1159,8 +1292,10 @@ static void rapl_update_domain_data(struct rapl_package *rp) rp->domains[dmn].name); /* exclude non-raw primitives */ for (prim = 0; prim < NR_RAW_PRIMITIVES; prim++) { + struct rapl_primitive_info *rpi = get_rpi(rp, prim); + if (!rapl_read_data_raw(&rp->domains[dmn], prim, - rpi[prim].unit, &val)) + rpi->unit, &val)) rp->domains[dmn].rdd.primitives[prim] = val; } } @@ -1239,7 +1374,7 @@ static int rapl_package_register_powercap(struct rapl_package *rp) return ret; } -static int rapl_check_domain(int cpu, int domain, struct rapl_package *rp) +static int rapl_check_domain(int domain, struct rapl_package *rp) { struct reg_action ra; @@ -1260,9 +1395,43 @@ static int rapl_check_domain(int cpu, int domain, struct rapl_package *rp) */ ra.mask = ENERGY_STATUS_MASK; - if (rp->priv->read_raw(cpu, &ra) || !ra.value) + if (rp->priv->read_raw(get_rid(rp), &ra) || !ra.value) + return -ENODEV; + + return 0; +} + +/* + * Get per domain energy/power/time unit. + * RAPL Interfaces without per domain unit register will use the package + * scope unit register to set per domain units. + */ +static int rapl_get_domain_unit(struct rapl_domain *rd) +{ + struct rapl_defaults *defaults = get_defaults(rd->rp); + int ret; + + if (!rd->regs[RAPL_DOMAIN_REG_UNIT]) { + if (!rd->rp->priv->reg_unit) { + pr_err("No valid Unit register found\n"); + return -ENODEV; + } + rd->regs[RAPL_DOMAIN_REG_UNIT] = rd->rp->priv->reg_unit; + } + + if (!defaults->check_unit) { + pr_err("missing .check_unit() callback\n"); return -ENODEV; + } + + ret = defaults->check_unit(rd); + if (ret) + return ret; + if (rd->id == RAPL_DOMAIN_DRAM && defaults->dram_domain_energy_unit) + rd->energy_unit = defaults->dram_domain_energy_unit; + if (rd->id == RAPL_DOMAIN_PLATFORM && defaults->psys_domain_energy_unit) + rd->energy_unit = defaults->psys_domain_energy_unit; return 0; } @@ -1280,19 +1449,16 @@ static void rapl_detect_powerlimit(struct rapl_domain *rd) u64 val64; int i; - /* check if the domain is locked by BIOS, ignore if MSR doesn't exist */ - if (!rapl_read_data_raw(rd, FW_LOCK, false, &val64)) { - if (val64) { - pr_info("RAPL %s domain %s locked by BIOS\n", - rd->rp->name, rd->name); - rd->state |= DOMAIN_STATE_BIOS_LOCKED; + for (i = POWER_LIMIT1; i < NR_POWER_LIMITS; i++) { + if (!rapl_read_pl_data(rd, i, PL_LOCK, false, &val64)) { + if (val64) { + rd->rpl[i].locked = true; + pr_info("%s:%s:%s locked by BIOS\n", + rd->rp->name, rd->name, pl_names[i]); + } } - } - /* check if power limit MSR exists, otherwise domain is monitoring only */ - for (i = 0; i < NR_POWER_LIMITS; i++) { - int prim = rd->rpl[i].prim_id; - if (rapl_read_data_raw(rd, prim, false, &val64)) + if (rapl_read_pl_data(rd, i, PL_ENABLE, false, &val64)) rd->rpl[i].name = NULL; } } @@ -1300,14 +1466,14 @@ static void rapl_detect_powerlimit(struct rapl_domain *rd) /* Detect active and valid domains for the given CPU, caller must * ensure the CPU belongs to the targeted package and CPU hotlug is disabled. */ -static int rapl_detect_domains(struct rapl_package *rp, int cpu) +static int rapl_detect_domains(struct rapl_package *rp) { struct rapl_domain *rd; int i; for (i = 0; i < RAPL_DOMAIN_MAX; i++) { /* use physical package id to read counters */ - if (!rapl_check_domain(cpu, i, rp)) { + if (!rapl_check_domain(i, rp)) { rp->domain_map |= 1 << i; pr_info("Found RAPL domain %s\n", rapl_domain_names[i]); } @@ -1326,8 +1492,10 @@ static int rapl_detect_domains(struct rapl_package *rp, int cpu) rapl_init_domains(rp); - for (rd = rp->domains; rd < rp->domains + rp->nr_domains; rd++) + for (rd = rp->domains; rd < rp->domains + rp->nr_domains; rd++) { + rapl_get_domain_unit(rd); rapl_detect_powerlimit(rd); + } return 0; } @@ -1340,13 +1508,13 @@ void rapl_remove_package(struct rapl_package *rp) package_power_limit_irq_restore(rp); for (rd = rp->domains; rd < rp->domains + rp->nr_domains; rd++) { - rapl_write_data_raw(rd, PL1_ENABLE, 0); - rapl_write_data_raw(rd, PL1_CLAMP, 0); - if (find_nr_power_limit(rd) > 1) { - rapl_write_data_raw(rd, PL2_ENABLE, 0); - rapl_write_data_raw(rd, PL2_CLAMP, 0); - rapl_write_data_raw(rd, PL4_ENABLE, 0); + int i; + + for (i = POWER_LIMIT1; i < NR_POWER_LIMITS; i++) { + rapl_write_pl_data(rd, i, PL_ENABLE, 0); + rapl_write_pl_data(rd, i, PL_CLAMP, 0); } + if (rd->id == RAPL_DOMAIN_PACKAGE) { rd_package = rd; continue; @@ -1365,13 +1533,18 @@ void rapl_remove_package(struct rapl_package *rp) EXPORT_SYMBOL_GPL(rapl_remove_package); /* caller to ensure CPU hotplug lock is held */ -struct rapl_package *rapl_find_package_domain(int cpu, struct rapl_if_priv *priv) +struct rapl_package *rapl_find_package_domain(int id, struct rapl_if_priv *priv, bool id_is_cpu) { - int id = topology_logical_die_id(cpu); struct rapl_package *rp; + int uid; + + if (id_is_cpu) + uid = topology_logical_die_id(id); + else + uid = id; list_for_each_entry(rp, &rapl_packages, plist) { - if (rp->id == id + if (rp->id == uid && rp->priv->control_type == priv->control_type) return rp; } @@ -1381,34 +1554,37 @@ struct rapl_package *rapl_find_package_domain(int cpu, struct rapl_if_priv *priv EXPORT_SYMBOL_GPL(rapl_find_package_domain); /* called from CPU hotplug notifier, hotplug lock held */ -struct rapl_package *rapl_add_package(int cpu, struct rapl_if_priv *priv) +struct rapl_package *rapl_add_package(int id, struct rapl_if_priv *priv, bool id_is_cpu) { - int id = topology_logical_die_id(cpu); struct rapl_package *rp; int ret; - if (!rapl_defaults) - return ERR_PTR(-ENODEV); - rp = kzalloc(sizeof(struct rapl_package), GFP_KERNEL); if (!rp) return ERR_PTR(-ENOMEM); - /* add the new package to the list */ - rp->id = id; - rp->lead_cpu = cpu; - rp->priv = priv; + if (id_is_cpu) { + rp->id = topology_logical_die_id(id); + rp->lead_cpu = id; + if (topology_max_die_per_package() > 1) + snprintf(rp->name, PACKAGE_DOMAIN_NAME_LENGTH, "package-%d-die-%d", + topology_physical_package_id(id), topology_die_id(id)); + else + snprintf(rp->name, PACKAGE_DOMAIN_NAME_LENGTH, "package-%d", + topology_physical_package_id(id)); + } else { + rp->id = id; + rp->lead_cpu = -1; + snprintf(rp->name, PACKAGE_DOMAIN_NAME_LENGTH, "package-%d", id); + } - if (topology_max_die_per_package() > 1) - snprintf(rp->name, PACKAGE_DOMAIN_NAME_LENGTH, - "package-%d-die-%d", - topology_physical_package_id(cpu), topology_die_id(cpu)); - else - snprintf(rp->name, PACKAGE_DOMAIN_NAME_LENGTH, "package-%d", - topology_physical_package_id(cpu)); + rp->priv = priv; + ret = rapl_config(rp); + if (ret) + goto err_free_package; /* check if the package contains valid domains */ - if (rapl_detect_domains(rp, cpu) || rapl_defaults->check_unit(rp, cpu)) { + if (rapl_detect_domains(rp)) { ret = -ENODEV; goto err_free_package; } @@ -1430,38 +1606,18 @@ static void power_limit_state_save(void) { struct rapl_package *rp; struct rapl_domain *rd; - int nr_pl, ret, i; + int ret, i; cpus_read_lock(); list_for_each_entry(rp, &rapl_packages, plist) { if (!rp->power_zone) continue; rd = power_zone_to_rapl_domain(rp->power_zone); - nr_pl = find_nr_power_limit(rd); - for (i = 0; i < nr_pl; i++) { - switch (rd->rpl[i].prim_id) { - case PL1_ENABLE: - ret = rapl_read_data_raw(rd, - POWER_LIMIT1, true, - &rd->rpl[i].last_power_limit); - if (ret) - rd->rpl[i].last_power_limit = 0; - break; - case PL2_ENABLE: - ret = rapl_read_data_raw(rd, - POWER_LIMIT2, true, + for (i = POWER_LIMIT1; i < NR_POWER_LIMITS; i++) { + ret = rapl_read_pl_data(rd, i, PL_LIMIT, true, &rd->rpl[i].last_power_limit); - if (ret) - rd->rpl[i].last_power_limit = 0; - break; - case PL4_ENABLE: - ret = rapl_read_data_raw(rd, - POWER_LIMIT4, true, - &rd->rpl[i].last_power_limit); - if (ret) - rd->rpl[i].last_power_limit = 0; - break; - } + if (ret) + rd->rpl[i].last_power_limit = 0; } } cpus_read_unlock(); @@ -1471,33 +1627,17 @@ static void power_limit_state_restore(void) { struct rapl_package *rp; struct rapl_domain *rd; - int nr_pl, i; + int i; cpus_read_lock(); list_for_each_entry(rp, &rapl_packages, plist) { if (!rp->power_zone) continue; rd = power_zone_to_rapl_domain(rp->power_zone); - nr_pl = find_nr_power_limit(rd); - for (i = 0; i < nr_pl; i++) { - switch (rd->rpl[i].prim_id) { - case PL1_ENABLE: - if (rd->rpl[i].last_power_limit) - rapl_write_data_raw(rd, POWER_LIMIT1, - rd->rpl[i].last_power_limit); - break; - case PL2_ENABLE: - if (rd->rpl[i].last_power_limit) - rapl_write_data_raw(rd, POWER_LIMIT2, - rd->rpl[i].last_power_limit); - break; - case PL4_ENABLE: - if (rd->rpl[i].last_power_limit) - rapl_write_data_raw(rd, POWER_LIMIT4, - rd->rpl[i].last_power_limit); - break; - } - } + for (i = POWER_LIMIT1; i < NR_POWER_LIMITS; i++) + if (rd->rpl[i].last_power_limit) + rapl_write_pl_data(rd, i, PL_LIMIT, + rd->rpl[i].last_power_limit); } cpus_read_unlock(); } @@ -1528,32 +1668,25 @@ static int __init rapl_init(void) int ret; id = x86_match_cpu(rapl_ids); - if (!id) { - pr_err("driver does not support CPU family %d model %d\n", - boot_cpu_data.x86, boot_cpu_data.x86_model); - - return -ENODEV; - } + if (id) { + defaults_msr = (struct rapl_defaults *)id->driver_data; - rapl_defaults = (struct rapl_defaults *)id->driver_data; - - ret = register_pm_notifier(&rapl_pm_notifier); - if (ret) - return ret; + rapl_msr_platdev = platform_device_alloc("intel_rapl_msr", 0); + if (!rapl_msr_platdev) + return -ENOMEM; - rapl_msr_platdev = platform_device_alloc("intel_rapl_msr", 0); - if (!rapl_msr_platdev) { - ret = -ENOMEM; - goto end; + ret = platform_device_add(rapl_msr_platdev); + if (ret) { + platform_device_put(rapl_msr_platdev); + return ret; + } } - ret = platform_device_add(rapl_msr_platdev); - if (ret) + ret = register_pm_notifier(&rapl_pm_notifier); + if (ret && rapl_msr_platdev) { + platform_device_del(rapl_msr_platdev); platform_device_put(rapl_msr_platdev); - -end: - if (ret) - unregister_pm_notifier(&rapl_pm_notifier); + } return ret; } diff --git a/drivers/powercap/intel_rapl_msr.c b/drivers/powercap/intel_rapl_msr.c index a27673706c3d600d1d653493a34bb301bbcc578c..569e25eab1e1b6e4da8cde85fb1a2f774e663214 100644 --- a/drivers/powercap/intel_rapl_msr.c +++ b/drivers/powercap/intel_rapl_msr.c @@ -22,7 +22,6 @@ #include #include -#include #include #include @@ -34,6 +33,7 @@ static struct rapl_if_priv *rapl_msr_priv; static struct rapl_if_priv rapl_msr_priv_intel = { + .type = RAPL_IF_MSR, .reg_unit = MSR_RAPL_POWER_UNIT, .regs[RAPL_DOMAIN_PACKAGE] = { MSR_PKG_POWER_LIMIT, MSR_PKG_ENERGY_STATUS, MSR_PKG_PERF_STATUS, 0, MSR_PKG_POWER_INFO }, @@ -45,11 +45,12 @@ static struct rapl_if_priv rapl_msr_priv_intel = { MSR_DRAM_POWER_LIMIT, MSR_DRAM_ENERGY_STATUS, MSR_DRAM_PERF_STATUS, 0, MSR_DRAM_POWER_INFO }, .regs[RAPL_DOMAIN_PLATFORM] = { MSR_PLATFORM_POWER_LIMIT, MSR_PLATFORM_ENERGY_STATUS, 0, 0, 0}, - .limits[RAPL_DOMAIN_PACKAGE] = 2, - .limits[RAPL_DOMAIN_PLATFORM] = 2, + .limits[RAPL_DOMAIN_PACKAGE] = BIT(POWER_LIMIT2), + .limits[RAPL_DOMAIN_PLATFORM] = BIT(POWER_LIMIT2), }; static struct rapl_if_priv rapl_msr_priv_amd = { + .type = RAPL_IF_MSR, .reg_unit = MSR_AMD_RAPL_POWER_UNIT, .regs[RAPL_DOMAIN_PACKAGE] = { 0, MSR_AMD_PKG_ENERGY_STATUS, 0, 0, 0 }, @@ -68,9 +69,9 @@ static int rapl_cpu_online(unsigned int cpu) { struct rapl_package *rp; - rp = rapl_find_package_domain(cpu, rapl_msr_priv); + rp = rapl_find_package_domain(cpu, rapl_msr_priv, true); if (!rp) { - rp = rapl_add_package(cpu, rapl_msr_priv); + rp = rapl_add_package(cpu, rapl_msr_priv, true); if (IS_ERR(rp)) return PTR_ERR(rp); } @@ -83,7 +84,7 @@ static int rapl_cpu_down_prep(unsigned int cpu) struct rapl_package *rp; int lead_cpu; - rp = rapl_find_package_domain(cpu, rapl_msr_priv); + rp = rapl_find_package_domain(cpu, rapl_msr_priv, true); if (!rp) return 0; @@ -137,14 +138,14 @@ static int rapl_msr_write_raw(int cpu, struct reg_action *ra) /* List of verified CPUs. */ static const struct x86_cpu_id pl4_support_ids[] = { - { X86_VENDOR_INTEL, 6, INTEL_FAM6_TIGERLAKE_L, X86_FEATURE_ANY }, - { X86_VENDOR_INTEL, 6, INTEL_FAM6_ALDERLAKE, X86_FEATURE_ANY }, - { X86_VENDOR_INTEL, 6, INTEL_FAM6_ALDERLAKE_L, X86_FEATURE_ANY }, - { X86_VENDOR_INTEL, 6, INTEL_FAM6_ALDERLAKE_N, X86_FEATURE_ANY }, - { X86_VENDOR_INTEL, 6, INTEL_FAM6_RAPTORLAKE, X86_FEATURE_ANY }, - { X86_VENDOR_INTEL, 6, INTEL_FAM6_RAPTORLAKE_P, X86_FEATURE_ANY }, - { X86_VENDOR_INTEL, 6, INTEL_FAM6_METEORLAKE, X86_FEATURE_ANY }, - { X86_VENDOR_INTEL, 6, INTEL_FAM6_METEORLAKE_L, X86_FEATURE_ANY }, + X86_MATCH_INTEL_FAM6_MODEL(TIGERLAKE_L, NULL), + X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE, NULL), + X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE_L, NULL), + X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE_N, NULL), + X86_MATCH_INTEL_FAM6_MODEL(RAPTORLAKE, NULL), + X86_MATCH_INTEL_FAM6_MODEL(RAPTORLAKE_P, NULL), + X86_MATCH_INTEL_FAM6_MODEL(METEORLAKE, NULL), + X86_MATCH_INTEL_FAM6_MODEL(METEORLAKE_L, NULL), {} }; @@ -169,7 +170,7 @@ static int rapl_msr_probe(struct platform_device *pdev) rapl_msr_priv->write_raw = rapl_msr_write_raw; if (id) { - rapl_msr_priv->limits[RAPL_DOMAIN_PACKAGE] = 3; + rapl_msr_priv->limits[RAPL_DOMAIN_PACKAGE] |= BIT(POWER_LIMIT4); rapl_msr_priv->regs[RAPL_DOMAIN_PACKAGE][RAPL_DOMAIN_REG_PL4] = MSR_VR_CURRENT_CONFIG; pr_info("PL4 support detected.\n"); diff --git a/drivers/powercap/intel_rapl_tpmi.c b/drivers/powercap/intel_rapl_tpmi.c new file mode 100644 index 0000000000000000000000000000000000000000..4f4f13ded225c4f33f1933f1598cf0ca5914840a --- /dev/null +++ b/drivers/powercap/intel_rapl_tpmi.c @@ -0,0 +1,325 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * intel_rapl_tpmi: Intel RAPL driver via TPMI interface + * + * Copyright (c) 2023, Intel Corporation. + * All Rights Reserved. + * + */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include + +#define TPMI_RAPL_VERSION 1 + +/* 1 header + 10 registers + 5 reserved. 8 bytes for each. */ +#define TPMI_RAPL_DOMAIN_SIZE 128 + +enum tpmi_rapl_domain_type { + TPMI_RAPL_DOMAIN_INVALID, + TPMI_RAPL_DOMAIN_SYSTEM, + TPMI_RAPL_DOMAIN_PACKAGE, + TPMI_RAPL_DOMAIN_RESERVED, + TPMI_RAPL_DOMAIN_MEMORY, + TPMI_RAPL_DOMAIN_MAX, +}; + +enum tpmi_rapl_register { + TPMI_RAPL_REG_HEADER, + TPMI_RAPL_REG_UNIT, + TPMI_RAPL_REG_PL1, + TPMI_RAPL_REG_PL2, + TPMI_RAPL_REG_PL3, + TPMI_RAPL_REG_PL4, + TPMI_RAPL_REG_RESERVED, + TPMI_RAPL_REG_ENERGY_STATUS, + TPMI_RAPL_REG_PERF_STATUS, + TPMI_RAPL_REG_POWER_INFO, + TPMI_RAPL_REG_INTERRUPT, + TPMI_RAPL_REG_MAX = 15, +}; + +struct tpmi_rapl_package { + struct rapl_if_priv priv; + struct intel_tpmi_plat_info *tpmi_info; + struct rapl_package *rp; + void __iomem *base; + struct list_head node; +}; + +static LIST_HEAD(tpmi_rapl_packages); +static DEFINE_MUTEX(tpmi_rapl_lock); + +static struct powercap_control_type *tpmi_control_type; + +static int tpmi_rapl_read_raw(int id, struct reg_action *ra) +{ + if (!ra->reg) + return -EINVAL; + + ra->value = readq((void __iomem *)ra->reg); + + ra->value &= ra->mask; + return 0; +} + +static int tpmi_rapl_write_raw(int id, struct reg_action *ra) +{ + u64 val; + + if (!ra->reg) + return -EINVAL; + + val = readq((void __iomem *)ra->reg); + + val &= ~ra->mask; + val |= ra->value; + + writeq(val, (void __iomem *)ra->reg); + return 0; +} + +static struct tpmi_rapl_package *trp_alloc(int pkg_id) +{ + struct tpmi_rapl_package *trp; + int ret; + + mutex_lock(&tpmi_rapl_lock); + + if (list_empty(&tpmi_rapl_packages)) { + tpmi_control_type = powercap_register_control_type(NULL, "intel-rapl", NULL); + if (IS_ERR(tpmi_control_type)) { + ret = PTR_ERR(tpmi_control_type); + goto err_unlock; + } + } + + trp = kzalloc(sizeof(*trp), GFP_KERNEL); + if (!trp) { + ret = -ENOMEM; + goto err_del_powercap; + } + + list_add(&trp->node, &tpmi_rapl_packages); + + mutex_unlock(&tpmi_rapl_lock); + return trp; + +err_del_powercap: + if (list_empty(&tpmi_rapl_packages)) + powercap_unregister_control_type(tpmi_control_type); +err_unlock: + mutex_unlock(&tpmi_rapl_lock); + return ERR_PTR(ret); +} + +static void trp_release(struct tpmi_rapl_package *trp) +{ + mutex_lock(&tpmi_rapl_lock); + list_del(&trp->node); + + if (list_empty(&tpmi_rapl_packages)) + powercap_unregister_control_type(tpmi_control_type); + + kfree(trp); + mutex_unlock(&tpmi_rapl_lock); +} + +static int parse_one_domain(struct tpmi_rapl_package *trp, u32 offset) +{ + u8 tpmi_domain_version; + enum rapl_domain_type domain_type; + enum tpmi_rapl_domain_type tpmi_domain_type; + enum tpmi_rapl_register reg_index; + enum rapl_domain_reg_id reg_id; + int tpmi_domain_size, tpmi_domain_flags; + u64 *tpmi_rapl_regs = trp->base + offset; + u64 tpmi_domain_header = readq((void __iomem *)tpmi_rapl_regs); + + /* Domain Parent bits are ignored for now */ + tpmi_domain_version = tpmi_domain_header & 0xff; + tpmi_domain_type = tpmi_domain_header >> 8 & 0xff; + tpmi_domain_size = tpmi_domain_header >> 16 & 0xff; + tpmi_domain_flags = tpmi_domain_header >> 32 & 0xffff; + + if (tpmi_domain_version != TPMI_RAPL_VERSION) { + pr_warn(FW_BUG "Unsupported version:%d\n", tpmi_domain_version); + return -ENODEV; + } + + /* Domain size: in unit of 128 Bytes */ + if (tpmi_domain_size != 1) { + pr_warn(FW_BUG "Invalid Domain size %d\n", tpmi_domain_size); + return -EINVAL; + } + + /* Unit register and Energy Status register are mandatory for each domain */ + if (!(tpmi_domain_flags & BIT(TPMI_RAPL_REG_UNIT)) || + !(tpmi_domain_flags & BIT(TPMI_RAPL_REG_ENERGY_STATUS))) { + pr_warn(FW_BUG "Invalid Domain flag 0x%x\n", tpmi_domain_flags); + return -EINVAL; + } + + switch (tpmi_domain_type) { + case TPMI_RAPL_DOMAIN_PACKAGE: + domain_type = RAPL_DOMAIN_PACKAGE; + break; + case TPMI_RAPL_DOMAIN_SYSTEM: + domain_type = RAPL_DOMAIN_PLATFORM; + break; + case TPMI_RAPL_DOMAIN_MEMORY: + domain_type = RAPL_DOMAIN_DRAM; + break; + default: + pr_warn(FW_BUG "Unsupported Domain type %d\n", tpmi_domain_type); + return -EINVAL; + } + + if (trp->priv.regs[domain_type][RAPL_DOMAIN_REG_UNIT]) { + pr_warn(FW_BUG "Duplicate Domain type %d\n", tpmi_domain_type); + return -EINVAL; + } + + reg_index = TPMI_RAPL_REG_HEADER; + while (++reg_index != TPMI_RAPL_REG_MAX) { + if (!(tpmi_domain_flags & BIT(reg_index))) + continue; + + switch (reg_index) { + case TPMI_RAPL_REG_UNIT: + reg_id = RAPL_DOMAIN_REG_UNIT; + break; + case TPMI_RAPL_REG_PL1: + reg_id = RAPL_DOMAIN_REG_LIMIT; + trp->priv.limits[domain_type] |= BIT(POWER_LIMIT1); + break; + case TPMI_RAPL_REG_PL2: + reg_id = RAPL_DOMAIN_REG_PL2; + trp->priv.limits[domain_type] |= BIT(POWER_LIMIT2); + break; + case TPMI_RAPL_REG_PL4: + reg_id = RAPL_DOMAIN_REG_PL4; + trp->priv.limits[domain_type] |= BIT(POWER_LIMIT4); + break; + case TPMI_RAPL_REG_ENERGY_STATUS: + reg_id = RAPL_DOMAIN_REG_STATUS; + break; + case TPMI_RAPL_REG_PERF_STATUS: + reg_id = RAPL_DOMAIN_REG_PERF; + break; + case TPMI_RAPL_REG_POWER_INFO: + reg_id = RAPL_DOMAIN_REG_INFO; + break; + default: + continue; + } + trp->priv.regs[domain_type][reg_id] = (u64)&tpmi_rapl_regs[reg_index]; + } + + return 0; +} + +static int intel_rapl_tpmi_probe(struct auxiliary_device *auxdev, + const struct auxiliary_device_id *id) +{ + struct tpmi_rapl_package *trp; + struct intel_tpmi_plat_info *info; + struct resource *res; + u32 offset; + int ret; + + info = tpmi_get_platform_data(auxdev); + if (!info) + return -ENODEV; + + trp = trp_alloc(info->package_id); + if (IS_ERR(trp)) + return PTR_ERR(trp); + + if (tpmi_get_resource_count(auxdev) > 1) { + dev_err(&auxdev->dev, "does not support multiple resources\n"); + ret = -EINVAL; + goto err; + } + + res = tpmi_get_resource_at_index(auxdev, 0); + if (!res) { + dev_err(&auxdev->dev, "can't fetch device resource info\n"); + ret = -EIO; + goto err; + } + + trp->base = devm_ioremap_resource(&auxdev->dev, res); + if (IS_ERR(trp->base)) { + ret = PTR_ERR(trp->base); + goto err; + } + + for (offset = 0; offset < resource_size(res); offset += TPMI_RAPL_DOMAIN_SIZE) { + ret = parse_one_domain(trp, offset); + if (ret) + goto err; + } + + trp->tpmi_info = info; + trp->priv.type = RAPL_IF_TPMI; + trp->priv.read_raw = tpmi_rapl_read_raw; + trp->priv.write_raw = tpmi_rapl_write_raw; + trp->priv.control_type = tpmi_control_type; + + /* RAPL TPMI I/F is per physical package */ + trp->rp = rapl_find_package_domain(info->package_id, &trp->priv, false); + if (trp->rp) { + dev_err(&auxdev->dev, "Domain for Package%d already exists\n", info->package_id); + ret = -EEXIST; + goto err; + } + + trp->rp = rapl_add_package(info->package_id, &trp->priv, false); + if (IS_ERR(trp->rp)) { + dev_err(&auxdev->dev, "Failed to add RAPL Domain for Package%d, %ld\n", + info->package_id, PTR_ERR(trp->rp)); + ret = PTR_ERR(trp->rp); + goto err; + } + + auxiliary_set_drvdata(auxdev, trp); + + return 0; +err: + trp_release(trp); + return ret; +} + +static void intel_rapl_tpmi_remove(struct auxiliary_device *auxdev) +{ + struct tpmi_rapl_package *trp = auxiliary_get_drvdata(auxdev); + + rapl_remove_package(trp->rp); + trp_release(trp); +} + +static const struct auxiliary_device_id intel_rapl_tpmi_ids[] = { + {.name = "intel_vsec.tpmi-rapl" }, + { } +}; + +MODULE_DEVICE_TABLE(auxiliary, intel_rapl_tpmi_ids); + +static struct auxiliary_driver intel_rapl_tpmi_driver = { + .probe = intel_rapl_tpmi_probe, + .remove = intel_rapl_tpmi_remove, + .id_table = intel_rapl_tpmi_ids, +}; + +module_auxiliary_driver(intel_rapl_tpmi_driver) + +MODULE_IMPORT_NS(INTEL_TPMI); + +MODULE_DESCRIPTION("Intel RAPL TPMI Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/ptp/Kconfig b/drivers/ptp/Kconfig index b00201d8131370dc75d3bb2ed2bbd0452a9f1f69..32dff1b4f891b0a6b73c63cab3d3f643d5bc24da 100644 --- a/drivers/ptp/Kconfig +++ b/drivers/ptp/Kconfig @@ -102,7 +102,7 @@ config PTP_1588_CLOCK_INES config PTP_1588_CLOCK_PCH tristate "Intel PCH EG20T as PTP clock" - depends on X86_32 || COMPILE_TEST + depends on MIPS_GENERIC || X86_32 || COMPILE_TEST depends on HAS_IOMEM && PCI depends on NET depends on PTP_1588_CLOCK diff --git a/drivers/ptp/ptp_chardev.c b/drivers/ptp/ptp_chardev.c index af3bc65c4595dd50782ff2e02a2c17d0f6d0b670..362bf756e6b78b5793d0f8da7132def435195e5b 100644 --- a/drivers/ptp/ptp_chardev.c +++ b/drivers/ptp/ptp_chardev.c @@ -136,7 +136,10 @@ long ptp_ioctl(struct posix_clock *pc, unsigned int cmd, unsigned long arg) caps.pps = ptp->info->pps; caps.n_pins = ptp->info->n_pins; caps.cross_timestamping = ptp->info->getcrosststamp != NULL; - caps.adjust_phase = ptp->info->adjphase != NULL; + caps.adjust_phase = ptp->info->adjphase != NULL && + ptp->info->getmaxphase != NULL; + if (caps.adjust_phase) + caps.max_phase_adj = ptp->info->getmaxphase(ptp->info); if (copy_to_user((void __user *)arg, &caps, sizeof(caps))) err = -EFAULT; break; diff --git a/drivers/ptp/ptp_clock.c b/drivers/ptp/ptp_clock.c index 790f9250b3815b27dbf1011d481a0bb31666fc54..80f74e38c2da4b5fac16a560dea2049455829fbe 100644 --- a/drivers/ptp/ptp_clock.c +++ b/drivers/ptp/ptp_clock.c @@ -135,11 +135,15 @@ static int ptp_clock_adjtime(struct posix_clock *pc, struct __kernel_timex *tx) ptp->dialed_frequency = tx->freq; } else if (tx->modes & ADJ_OFFSET) { if (ops->adjphase) { + s32 max_phase_adj = ops->getmaxphase(ops); s32 offset = tx->offset; if (!(tx->modes & ADJ_NANO)) offset *= NSEC_PER_USEC; + if (offset > max_phase_adj || offset < -max_phase_adj) + return -ERANGE; + err = ops->adjphase(ops, offset); } } else if (tx->modes == 0) { diff --git a/drivers/ptp/ptp_clockmatrix.c b/drivers/ptp/ptp_clockmatrix.c index c9d451bf89e2de3913c645cb2c63130112858944..f6f9d4adce04a9d40607d5702be578536a988087 100644 --- a/drivers/ptp/ptp_clockmatrix.c +++ b/drivers/ptp/ptp_clockmatrix.c @@ -1692,14 +1692,23 @@ static int initialize_dco_operating_mode(struct idtcm_channel *channel) /* PTP Hardware Clock interface */ /* - * Maximum absolute value for write phase offset in picoseconds - * - * @channel: channel - * @delta_ns: delta in nanoseconds + * Maximum absolute value for write phase offset in nanoseconds * * Destination signed register is 32-bit register in resolution of 50ps * - * 0x7fffffff * 50 = 2147483647 * 50 = 107374182350 + * 0x7fffffff * 50 = 2147483647 * 50 = 107374182350 ps + * Represent 107374182350 ps as 107374182 ns + */ +static s32 idtcm_getmaxphase(struct ptp_clock_info *ptp __always_unused) +{ + return MAX_ABS_WRITE_PHASE_NANOSECONDS; +} + +/* + * Internal function for implementing support for write phase offset + * + * @channel: channel + * @delta_ns: delta in nanoseconds */ static int _idtcm_adjphase(struct idtcm_channel *channel, s32 delta_ns) { @@ -1708,7 +1717,6 @@ static int _idtcm_adjphase(struct idtcm_channel *channel, s32 delta_ns) u8 i; u8 buf[4] = {0}; s32 phase_50ps; - s64 offset_ps; if (channel->mode != PTP_PLL_MODE_WRITE_PHASE) { err = channel->configure_write_phase(channel); @@ -1716,19 +1724,7 @@ static int _idtcm_adjphase(struct idtcm_channel *channel, s32 delta_ns) return err; } - offset_ps = (s64)delta_ns * 1000; - - /* - * Check for 32-bit signed max * 50: - * - * 0x7fffffff * 50 = 2147483647 * 50 = 107374182350 - */ - if (offset_ps > MAX_ABS_WRITE_PHASE_PICOSECONDS) - offset_ps = MAX_ABS_WRITE_PHASE_PICOSECONDS; - else if (offset_ps < -MAX_ABS_WRITE_PHASE_PICOSECONDS) - offset_ps = -MAX_ABS_WRITE_PHASE_PICOSECONDS; - - phase_50ps = div_s64(offset_ps, 50); + phase_50ps = div_s64((s64)delta_ns * 1000, 50); for (i = 0; i < 4; i++) { buf[i] = phase_50ps & 0xff; @@ -2048,6 +2044,7 @@ static const struct ptp_clock_info idtcm_caps = { .n_ext_ts = MAX_TOD, .n_pins = MAX_REF_CLK, .adjphase = &idtcm_adjphase, + .getmaxphase = &idtcm_getmaxphase, .adjfine = &idtcm_adjfine, .adjtime = &idtcm_adjtime, .gettime64 = &idtcm_gettime, @@ -2064,6 +2061,7 @@ static const struct ptp_clock_info idtcm_caps_deprecated = { .n_ext_ts = MAX_TOD, .n_pins = MAX_REF_CLK, .adjphase = &idtcm_adjphase, + .getmaxphase = &idtcm_getmaxphase, .adjfine = &idtcm_adjfine, .adjtime = &idtcm_adjtime_deprecated, .gettime64 = &idtcm_gettime, diff --git a/drivers/ptp/ptp_clockmatrix.h b/drivers/ptp/ptp_clockmatrix.h index bf1e49409844041d1743cd6d2d9047eacb155dba..7c17c4f7f57352ebab1e7f76ac7a74a4fee55256 100644 --- a/drivers/ptp/ptp_clockmatrix.h +++ b/drivers/ptp/ptp_clockmatrix.h @@ -18,7 +18,7 @@ #define MAX_PLL (8) #define MAX_REF_CLK (16) -#define MAX_ABS_WRITE_PHASE_PICOSECONDS (107374182350LL) +#define MAX_ABS_WRITE_PHASE_NANOSECONDS (107374182L) #define TOD_MASK_ADDR (0xFFA5) #define DEFAULT_TOD_MASK (0x04) diff --git a/drivers/ptp/ptp_idt82p33.c b/drivers/ptp/ptp_idt82p33.c index afc76c22271ad3dd8d4d650abe7408b15f753f54..057190b9cd3d85ae7f579437ff141184c1dc9ad3 100644 --- a/drivers/ptp/ptp_idt82p33.c +++ b/drivers/ptp/ptp_idt82p33.c @@ -978,24 +978,23 @@ static int idt82p33_enable(struct ptp_clock_info *ptp, return err; } +static s32 idt82p33_getmaxphase(__always_unused struct ptp_clock_info *ptp) +{ + return WRITE_PHASE_OFFSET_LIMIT; +} + static int idt82p33_adjwritephase(struct ptp_clock_info *ptp, s32 offset_ns) { struct idt82p33_channel *channel = container_of(ptp, struct idt82p33_channel, caps); struct idt82p33 *idt82p33 = channel->idt82p33; - s64 offset_regval, offset_fs; + s64 offset_regval; u8 val[4] = {0}; int err; - offset_fs = (s64)(-offset_ns) * 1000000; - - if (offset_fs > WRITE_PHASE_OFFSET_LIMIT) - offset_fs = WRITE_PHASE_OFFSET_LIMIT; - else if (offset_fs < -WRITE_PHASE_OFFSET_LIMIT) - offset_fs = -WRITE_PHASE_OFFSET_LIMIT; - /* Convert from phaseoffset_fs to register value */ - offset_regval = div_s64(offset_fs * 1000, IDT_T0DPLL_PHASE_RESOL); + offset_regval = div_s64((s64)(-offset_ns) * 1000000000ll, + IDT_T0DPLL_PHASE_RESOL); val[0] = offset_regval & 0xFF; val[1] = (offset_regval >> 8) & 0xFF; @@ -1175,6 +1174,7 @@ static void idt82p33_caps_init(u32 index, struct ptp_clock_info *caps, caps->n_ext_ts = MAX_PHC_PLL, caps->n_pins = max_pins, caps->adjphase = idt82p33_adjwritephase, + caps->getmaxphase = idt82p33_getmaxphase, caps->adjfine = idt82p33_adjfine; caps->adjtime = idt82p33_adjtime; caps->gettime64 = idt82p33_gettime; diff --git a/drivers/ptp/ptp_idt82p33.h b/drivers/ptp/ptp_idt82p33.h index 8fcb0b17d20782259461d069640d4be7eee3d415..6a63c14b6966b62da0c40d8bb4eef7da5ce4720a 100644 --- a/drivers/ptp/ptp_idt82p33.h +++ b/drivers/ptp/ptp_idt82p33.h @@ -43,9 +43,9 @@ #define DEFAULT_OUTPUT_MASK_PLL1 DEFAULT_OUTPUT_MASK_PLL0 /** - * @brief Maximum absolute value for write phase offset in femtoseconds + * @brief Maximum absolute value for write phase offset in nanoseconds */ -#define WRITE_PHASE_OFFSET_LIMIT (20000052084ll) +#define WRITE_PHASE_OFFSET_LIMIT (20000l) /** @brief Phase offset resolution * diff --git a/drivers/ptp/ptp_ocp.c b/drivers/ptp/ptp_ocp.c index ab8cab4d1560d01bf532dc513dba1bec0ce4e9c4..20a974ced8d6c30d09f6770409c9d49d0f6daa94 100644 --- a/drivers/ptp/ptp_ocp.c +++ b/drivers/ptp/ptp_ocp.c @@ -1124,6 +1124,12 @@ ptp_ocp_null_adjfine(struct ptp_clock_info *ptp_info, long scaled_ppm) return -EOPNOTSUPP; } +static s32 +ptp_ocp_null_getmaxphase(struct ptp_clock_info *ptp_info) +{ + return 0; +} + static int ptp_ocp_null_adjphase(struct ptp_clock_info *ptp_info, s32 phase_ns) { @@ -1239,6 +1245,7 @@ static const struct ptp_clock_info ptp_ocp_clock_info = { .adjtime = ptp_ocp_adjtime, .adjfine = ptp_ocp_null_adjfine, .adjphase = ptp_ocp_null_adjphase, + .getmaxphase = ptp_ocp_null_getmaxphase, .enable = ptp_ocp_enable, .verify = ptp_ocp_verify, .pps = true, diff --git a/drivers/ptp/ptp_sysfs.c b/drivers/ptp/ptp_sysfs.c index f30b0a439470549c77288d3ce20a445072d27b8f..6e4d5456a8851199ed60095ecd92fc4cd45876eb 100644 --- a/drivers/ptp/ptp_sysfs.c +++ b/drivers/ptp/ptp_sysfs.c @@ -18,6 +18,17 @@ static ssize_t clock_name_show(struct device *dev, } static DEVICE_ATTR_RO(clock_name); +static ssize_t max_phase_adjustment_show(struct device *dev, + struct device_attribute *attr, + char *page) +{ + struct ptp_clock *ptp = dev_get_drvdata(dev); + + return snprintf(page, PAGE_SIZE - 1, "%d\n", + ptp->info->getmaxphase(ptp->info)); +} +static DEVICE_ATTR_RO(max_phase_adjustment); + #define PTP_SHOW_INT(name, var) \ static ssize_t var##_show(struct device *dev, \ struct device_attribute *attr, char *page) \ @@ -309,6 +320,7 @@ static struct attribute *ptp_attrs[] = { &dev_attr_clock_name.attr, &dev_attr_max_adjustment.attr, + &dev_attr_max_phase_adjustment.attr, &dev_attr_n_alarms.attr, &dev_attr_n_external_timestamps.attr, &dev_attr_n_periodic_outputs.attr, @@ -346,6 +358,9 @@ static umode_t ptp_is_attribute_visible(struct kobject *kobj, attr == &dev_attr_max_vclocks.attr) { if (ptp->is_virtual_clock) mode = 0; + } else if (attr == &dev_attr_max_phase_adjustment.attr) { + if (!info->adjphase || !info->getmaxphase) + mode = 0; } return mode; diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig index 8df861b1f4a30b599ca955f76e194fc43d643e0e..6210babb0741a8cac70b7e06e975e72aeea0fe2a 100644 --- a/drivers/pwm/Kconfig +++ b/drivers/pwm/Kconfig @@ -405,6 +405,16 @@ config PWM_MEDIATEK To compile this driver as a module, choose M here: the module will be called pwm-mediatek. +config PWM_MICROCHIP_CORE + tristate "Microchip corePWM PWM support" + depends on SOC_MICROCHIP_POLARFIRE || COMPILE_TEST + depends on HAS_IOMEM && OF + help + PWM driver for Microchip FPGA soft IP core. + + To compile this driver as a module, choose M here: the module + will be called pwm-microchip-core. + config PWM_MXS tristate "Freescale MXS PWM support" depends on ARCH_MXS || COMPILE_TEST @@ -493,6 +503,17 @@ config PWM_ROCKCHIP Generic PWM framework driver for the PWM controller found on Rockchip SoCs. +config PWM_RZ_MTU3 + tristate "Renesas RZ/G2L MTU3a PWM Timer support" + depends on RZ_MTU3 || COMPILE_TEST + depends on HAS_IOMEM + help + This driver exposes the MTU3a PWM Timer controller found in Renesas + RZ/G2L like chips through the PWM API. + + To compile this driver as a module, choose M here: the module + will be called pwm-rz-mtu3. + config PWM_SAMSUNG tristate "Samsung PWM support" depends on PLAT_SAMSUNG || ARCH_S5PV210 || ARCH_EXYNOS || COMPILE_TEST diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile index 19899b912e00964ba7c3122339bf0cb0101fd1c5..c822389c2a24c2dd76b106ebb64b4a215f522889 100644 --- a/drivers/pwm/Makefile +++ b/drivers/pwm/Makefile @@ -35,6 +35,7 @@ obj-$(CONFIG_PWM_LPSS_PCI) += pwm-lpss-pci.o obj-$(CONFIG_PWM_LPSS_PLATFORM) += pwm-lpss-platform.o obj-$(CONFIG_PWM_MESON) += pwm-meson.o obj-$(CONFIG_PWM_MEDIATEK) += pwm-mediatek.o +obj-$(CONFIG_PWM_MICROCHIP_CORE) += pwm-microchip-core.o obj-$(CONFIG_PWM_MTK_DISP) += pwm-mtk-disp.o obj-$(CONFIG_PWM_MXS) += pwm-mxs.o obj-$(CONFIG_PWM_NTXEC) += pwm-ntxec.o @@ -45,6 +46,7 @@ obj-$(CONFIG_PWM_RASPBERRYPI_POE) += pwm-raspberrypi-poe.o obj-$(CONFIG_PWM_RCAR) += pwm-rcar.o obj-$(CONFIG_PWM_RENESAS_TPU) += pwm-renesas-tpu.o obj-$(CONFIG_PWM_ROCKCHIP) += pwm-rockchip.o +obj-$(CONFIG_PWM_RZ_MTU3) += pwm-rz-mtu3.o obj-$(CONFIG_PWM_SAMSUNG) += pwm-samsung.o obj-$(CONFIG_PWM_SIFIVE) += pwm-sifive.o obj-$(CONFIG_PWM_SL28CPLD) += pwm-sl28cpld.o diff --git a/drivers/pwm/pwm-ab8500.c b/drivers/pwm/pwm-ab8500.c index 507ff0d5f7bd88fa80d6168330a8efde4b2e5dfc..583a7d69c7415173caca43124b70e8491008a17d 100644 --- a/drivers/pwm/pwm-ab8500.c +++ b/drivers/pwm/pwm-ab8500.c @@ -190,7 +190,7 @@ static int ab8500_pwm_probe(struct platform_device *pdev) int err; if (pdev->id < 1 || pdev->id > 31) - return dev_err_probe(&pdev->dev, EINVAL, "Invalid device id %d\n", pdev->id); + return dev_err_probe(&pdev->dev, -EINVAL, "Invalid device id %d\n", pdev->id); /* * Nothing to be done in probe, this is required to get the diff --git a/drivers/pwm/pwm-atmel.c b/drivers/pwm/pwm-atmel.c index 0c567d9623cd3e51ca105c29a09e9b76977f69a0..5f7d286871cf0ec619f6a04806435f7589d5c05a 100644 --- a/drivers/pwm/pwm-atmel.c +++ b/drivers/pwm/pwm-atmel.c @@ -6,7 +6,7 @@ * Bo Shen * * Links to reference manuals for the supported PWM chips can be found in - * Documentation/arm/microchip.rst. + * Documentation/arch/arm/microchip.rst. * * Limitations: * - Periods start with the inactive level. diff --git a/drivers/pwm/pwm-clk.c b/drivers/pwm/pwm-clk.c index f1da99881adfb22ddcae3fd8c92fb52288c38a1c..0ee4d2aee4df0c31d7878e1527d690f13557e335 100644 --- a/drivers/pwm/pwm-clk.c +++ b/drivers/pwm/pwm-clk.c @@ -89,7 +89,7 @@ static int pwm_clk_probe(struct platform_device *pdev) if (!pcchip) return -ENOMEM; - pcchip->clk = devm_clk_get(&pdev->dev, NULL); + pcchip->clk = devm_clk_get_prepared(&pdev->dev, NULL); if (IS_ERR(pcchip->clk)) return dev_err_probe(&pdev->dev, PTR_ERR(pcchip->clk), "Failed to get clock\n"); @@ -98,15 +98,9 @@ static int pwm_clk_probe(struct platform_device *pdev) pcchip->chip.ops = &pwm_clk_ops; pcchip->chip.npwm = 1; - ret = clk_prepare(pcchip->clk); - if (ret < 0) - return dev_err_probe(&pdev->dev, ret, "Failed to prepare clock\n"); - ret = pwmchip_add(&pcchip->chip); - if (ret < 0) { - clk_unprepare(pcchip->clk); + if (ret < 0) return dev_err_probe(&pdev->dev, ret, "Failed to add pwm chip\n"); - } platform_set_drvdata(pdev, pcchip); return 0; @@ -120,8 +114,6 @@ static void pwm_clk_remove(struct platform_device *pdev) if (pcchip->clk_enabled) clk_disable(pcchip->clk); - - clk_unprepare(pcchip->clk); } static const struct of_device_id pwm_clk_dt_ids[] = { diff --git a/drivers/pwm/pwm-imx-tpm.c b/drivers/pwm/pwm-imx-tpm.c index 5e2b452ee5f2e2800538825f04245e1e699db66b..98ab65c896850ef224febe09506e919f47338b3b 100644 --- a/drivers/pwm/pwm-imx-tpm.c +++ b/drivers/pwm/pwm-imx-tpm.c @@ -397,6 +397,13 @@ static int __maybe_unused pwm_imx_tpm_suspend(struct device *dev) if (tpm->enable_count > 0) return -EBUSY; + /* + * Force 'real_period' to be zero to force period update code + * can be executed after system resume back, since suspend causes + * the period related registers to become their reset values. + */ + tpm->real_period = 0; + clk_disable_unprepare(tpm->clk); return 0; diff --git a/drivers/pwm/pwm-mediatek.c b/drivers/pwm/pwm-mediatek.c index 5b5eeaff35da67b7cafd54ba5435d19ba419fd3a..7a51d210a8778150852aa40cc89e086f59ce1018 100644 --- a/drivers/pwm/pwm-mediatek.c +++ b/drivers/pwm/pwm-mediatek.c @@ -38,6 +38,7 @@ struct pwm_mediatek_of_data { unsigned int num_pwms; bool pwm45_fixup; bool has_ck_26m_sel; + const unsigned int *reg_offset; }; /** @@ -59,10 +60,14 @@ struct pwm_mediatek_chip { const struct pwm_mediatek_of_data *soc; }; -static const unsigned int pwm_mediatek_reg_offset[] = { +static const unsigned int mtk_pwm_reg_offset_v1[] = { 0x0010, 0x0050, 0x0090, 0x00d0, 0x0110, 0x0150, 0x0190, 0x0220 }; +static const unsigned int mtk_pwm_reg_offset_v2[] = { + 0x0080, 0x00c0, 0x0100, 0x0140, 0x0180, 0x01c0, 0x0200, 0x0240 +}; + static inline struct pwm_mediatek_chip * to_pwm_mediatek_chip(struct pwm_chip *chip) { @@ -111,7 +116,7 @@ static inline void pwm_mediatek_writel(struct pwm_mediatek_chip *chip, unsigned int num, unsigned int offset, u32 value) { - writel(value, chip->regs + pwm_mediatek_reg_offset[num] + offset); + writel(value, chip->regs + chip->soc->reg_offset[num] + offset); } static int pwm_mediatek_config(struct pwm_chip *chip, struct pwm_device *pwm, @@ -285,60 +290,77 @@ static const struct pwm_mediatek_of_data mt2712_pwm_data = { .num_pwms = 8, .pwm45_fixup = false, .has_ck_26m_sel = false, + .reg_offset = mtk_pwm_reg_offset_v1, }; static const struct pwm_mediatek_of_data mt6795_pwm_data = { .num_pwms = 7, .pwm45_fixup = false, .has_ck_26m_sel = false, + .reg_offset = mtk_pwm_reg_offset_v1, }; static const struct pwm_mediatek_of_data mt7622_pwm_data = { .num_pwms = 6, .pwm45_fixup = false, .has_ck_26m_sel = true, + .reg_offset = mtk_pwm_reg_offset_v1, }; static const struct pwm_mediatek_of_data mt7623_pwm_data = { .num_pwms = 5, .pwm45_fixup = true, .has_ck_26m_sel = false, + .reg_offset = mtk_pwm_reg_offset_v1, }; static const struct pwm_mediatek_of_data mt7628_pwm_data = { .num_pwms = 4, .pwm45_fixup = true, .has_ck_26m_sel = false, + .reg_offset = mtk_pwm_reg_offset_v1, }; static const struct pwm_mediatek_of_data mt7629_pwm_data = { .num_pwms = 1, .pwm45_fixup = false, .has_ck_26m_sel = false, + .reg_offset = mtk_pwm_reg_offset_v1, }; -static const struct pwm_mediatek_of_data mt8183_pwm_data = { - .num_pwms = 4, +static const struct pwm_mediatek_of_data mt7981_pwm_data = { + .num_pwms = 3, .pwm45_fixup = false, .has_ck_26m_sel = true, + .reg_offset = mtk_pwm_reg_offset_v2, }; -static const struct pwm_mediatek_of_data mt8365_pwm_data = { - .num_pwms = 3, +static const struct pwm_mediatek_of_data mt7986_pwm_data = { + .num_pwms = 2, .pwm45_fixup = false, .has_ck_26m_sel = true, + .reg_offset = mtk_pwm_reg_offset_v1, }; -static const struct pwm_mediatek_of_data mt7986_pwm_data = { - .num_pwms = 2, +static const struct pwm_mediatek_of_data mt8183_pwm_data = { + .num_pwms = 4, + .pwm45_fixup = false, + .has_ck_26m_sel = true, + .reg_offset = mtk_pwm_reg_offset_v1, +}; + +static const struct pwm_mediatek_of_data mt8365_pwm_data = { + .num_pwms = 3, .pwm45_fixup = false, .has_ck_26m_sel = true, + .reg_offset = mtk_pwm_reg_offset_v1, }; static const struct pwm_mediatek_of_data mt8516_pwm_data = { .num_pwms = 5, .pwm45_fixup = false, .has_ck_26m_sel = true, + .reg_offset = mtk_pwm_reg_offset_v1, }; static const struct of_device_id pwm_mediatek_of_match[] = { @@ -348,6 +370,7 @@ static const struct of_device_id pwm_mediatek_of_match[] = { { .compatible = "mediatek,mt7623-pwm", .data = &mt7623_pwm_data }, { .compatible = "mediatek,mt7628-pwm", .data = &mt7628_pwm_data }, { .compatible = "mediatek,mt7629-pwm", .data = &mt7629_pwm_data }, + { .compatible = "mediatek,mt7981-pwm", .data = &mt7981_pwm_data }, { .compatible = "mediatek,mt7986-pwm", .data = &mt7986_pwm_data }, { .compatible = "mediatek,mt8183-pwm", .data = &mt8183_pwm_data }, { .compatible = "mediatek,mt8365-pwm", .data = &mt8365_pwm_data }, diff --git a/drivers/pwm/pwm-meson.c b/drivers/pwm/pwm-meson.c index 5732300eb0046c4a875ec31f568f98a2992a9412..22f54db3ae8ea8d36144b837af5254b354bb51b2 100644 --- a/drivers/pwm/pwm-meson.c +++ b/drivers/pwm/pwm-meson.c @@ -49,9 +49,9 @@ #define PWM_HIGH_MASK GENMASK(31, 16) #define REG_MISC_AB 0x8 -#define MISC_B_CLK_EN BIT(23) -#define MISC_A_CLK_EN BIT(15) -#define MISC_CLK_DIV_MASK 0x7f +#define MISC_B_CLK_EN_SHIFT 23 +#define MISC_A_CLK_EN_SHIFT 15 +#define MISC_CLK_DIV_WIDTH 7 #define MISC_B_CLK_DIV_SHIFT 16 #define MISC_A_CLK_DIV_SHIFT 8 #define MISC_B_CLK_SEL_SHIFT 6 @@ -61,37 +61,39 @@ #define MISC_A_EN BIT(0) #define MESON_NUM_PWMS 2 +#define MESON_MAX_MUX_PARENTS 4 static struct meson_pwm_channel_data { u8 reg_offset; u8 clk_sel_shift; u8 clk_div_shift; - u32 clk_en_mask; + u8 clk_en_shift; u32 pwm_en_mask; } meson_pwm_per_channel_data[MESON_NUM_PWMS] = { { .reg_offset = REG_PWM_A, .clk_sel_shift = MISC_A_CLK_SEL_SHIFT, .clk_div_shift = MISC_A_CLK_DIV_SHIFT, - .clk_en_mask = MISC_A_CLK_EN, + .clk_en_shift = MISC_A_CLK_EN_SHIFT, .pwm_en_mask = MISC_A_EN, }, { .reg_offset = REG_PWM_B, .clk_sel_shift = MISC_B_CLK_SEL_SHIFT, .clk_div_shift = MISC_B_CLK_DIV_SHIFT, - .clk_en_mask = MISC_B_CLK_EN, + .clk_en_shift = MISC_B_CLK_EN_SHIFT, .pwm_en_mask = MISC_B_EN, } }; struct meson_pwm_channel { + unsigned long rate; unsigned int hi; unsigned int lo; - u8 pre_div; - struct clk *clk_parent; struct clk_mux mux; + struct clk_divider div; + struct clk_gate gate; struct clk *clk; }; @@ -124,16 +126,6 @@ static int meson_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm) struct device *dev = chip->dev; int err; - if (channel->clk_parent) { - err = clk_set_parent(channel->clk, channel->clk_parent); - if (err < 0) { - dev_err(dev, "failed to set parent %s for %s: %d\n", - __clk_get_name(channel->clk_parent), - __clk_get_name(channel->clk), err); - return err; - } - } - err = clk_prepare_enable(channel->clk); if (err < 0) { dev_err(dev, "failed to enable clock %s: %d\n", @@ -156,8 +148,9 @@ static int meson_pwm_calc(struct meson_pwm *meson, struct pwm_device *pwm, const struct pwm_state *state) { struct meson_pwm_channel *channel = &meson->channels[pwm->hwpwm]; - unsigned int duty, period, pre_div, cnt, duty_cnt; + unsigned int cnt, duty_cnt; unsigned long fin_freq; + u64 duty, period, freq; duty = state->duty_cycle; period = state->period; @@ -171,7 +164,11 @@ static int meson_pwm_calc(struct meson_pwm *meson, struct pwm_device *pwm, if (state->polarity == PWM_POLARITY_INVERSED) duty = period - duty; - fin_freq = clk_get_rate(channel->clk); + freq = div64_u64(NSEC_PER_SEC * 0xffffULL, period); + if (freq > ULONG_MAX) + freq = ULONG_MAX; + + fin_freq = clk_round_rate(channel->clk, freq); if (fin_freq == 0) { dev_err(meson->chip.dev, "invalid source clock frequency\n"); return -EINVAL; @@ -179,46 +176,31 @@ static int meson_pwm_calc(struct meson_pwm *meson, struct pwm_device *pwm, dev_dbg(meson->chip.dev, "fin_freq: %lu Hz\n", fin_freq); - pre_div = div64_u64(fin_freq * (u64)period, NSEC_PER_SEC * 0xffffLL); - if (pre_div > MISC_CLK_DIV_MASK) { - dev_err(meson->chip.dev, "unable to get period pre_div\n"); - return -EINVAL; - } - - cnt = div64_u64(fin_freq * (u64)period, NSEC_PER_SEC * (pre_div + 1)); + cnt = div_u64(fin_freq * period, NSEC_PER_SEC); if (cnt > 0xffff) { dev_err(meson->chip.dev, "unable to get period cnt\n"); return -EINVAL; } - dev_dbg(meson->chip.dev, "period=%u pre_div=%u cnt=%u\n", period, - pre_div, cnt); + dev_dbg(meson->chip.dev, "period=%llu cnt=%u\n", period, cnt); if (duty == period) { - channel->pre_div = pre_div; channel->hi = cnt; channel->lo = 0; } else if (duty == 0) { - channel->pre_div = pre_div; channel->hi = 0; channel->lo = cnt; } else { - /* Then check is we can have the duty with the same pre_div */ - duty_cnt = div64_u64(fin_freq * (u64)duty, - NSEC_PER_SEC * (pre_div + 1)); - if (duty_cnt > 0xffff) { - dev_err(meson->chip.dev, "unable to get duty cycle\n"); - return -EINVAL; - } + duty_cnt = div_u64(fin_freq * duty, NSEC_PER_SEC); - dev_dbg(meson->chip.dev, "duty=%u pre_div=%u duty_cnt=%u\n", - duty, pre_div, duty_cnt); + dev_dbg(meson->chip.dev, "duty=%llu duty_cnt=%u\n", duty, duty_cnt); - channel->pre_div = pre_div; channel->hi = duty_cnt; channel->lo = cnt - duty_cnt; } + channel->rate = fin_freq; + return 0; } @@ -228,16 +210,15 @@ static void meson_pwm_enable(struct meson_pwm *meson, struct pwm_device *pwm) struct meson_pwm_channel_data *channel_data; unsigned long flags; u32 value; + int err; channel_data = &meson_pwm_per_channel_data[pwm->hwpwm]; - spin_lock_irqsave(&meson->lock, flags); + err = clk_set_rate(channel->clk, channel->rate); + if (err) + dev_err(meson->chip.dev, "setting clock rate failed\n"); - value = readl(meson->base + REG_MISC_AB); - value &= ~(MISC_CLK_DIV_MASK << channel_data->clk_div_shift); - value |= channel->pre_div << channel_data->clk_div_shift; - value |= channel_data->clk_en_mask; - writel(value, meson->base + REG_MISC_AB); + spin_lock_irqsave(&meson->lock, flags); value = FIELD_PREP(PWM_HIGH_MASK, channel->hi) | FIELD_PREP(PWM_LOW_MASK, channel->lo); @@ -276,16 +257,16 @@ static int meson_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, /* * This IP block revision doesn't have an "always high" * setting which we can use for "inverted disabled". - * Instead we achieve this using the same settings - * that we use a pre_div of 0 (to get the shortest - * possible duration for one "count") and - * "period == duty_cycle". This results in a signal + * Instead we achieve this by setting mux parent with + * highest rate and minimum divider value, resulting + * in the shortest possible duration for one "count" + * and "period == duty_cycle". This results in a signal * which is LOW for one "count", while being HIGH for * the rest of the (so the signal is HIGH for slightly * less than 100% of the period, but this is the best * we can achieve). */ - channel->pre_div = 0; + channel->rate = ULONG_MAX; channel->hi = ~0; channel->lo = 0; @@ -304,13 +285,12 @@ static int meson_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, return 0; } -static unsigned int meson_pwm_cnt_to_ns(struct pwm_chip *chip, - struct pwm_device *pwm, u32 cnt) +static u64 meson_pwm_cnt_to_ns(struct pwm_chip *chip, struct pwm_device *pwm, + u32 cnt) { struct meson_pwm *meson = to_meson_pwm(chip); struct meson_pwm_channel *channel; unsigned long fin_freq; - u32 fin_ns; /* to_meson_pwm() can only be used after .get_state() is called */ channel = &meson->channels[pwm->hwpwm]; @@ -319,9 +299,7 @@ static unsigned int meson_pwm_cnt_to_ns(struct pwm_chip *chip, if (fin_freq == 0) return 0; - fin_ns = div_u64(NSEC_PER_SEC, fin_freq); - - return cnt * fin_ns * (channel->pre_div + 1); + return div64_ul(NSEC_PER_SEC * (u64)cnt, fin_freq); } static int meson_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, @@ -330,7 +308,7 @@ static int meson_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, struct meson_pwm *meson = to_meson_pwm(chip); struct meson_pwm_channel_data *channel_data; struct meson_pwm_channel *channel; - u32 value, tmp; + u32 value; if (!state) return 0; @@ -339,30 +317,14 @@ static int meson_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, channel_data = &meson_pwm_per_channel_data[pwm->hwpwm]; value = readl(meson->base + REG_MISC_AB); - - tmp = channel_data->pwm_en_mask | channel_data->clk_en_mask; - state->enabled = (value & tmp) == tmp; - - tmp = value >> channel_data->clk_div_shift; - channel->pre_div = FIELD_GET(MISC_CLK_DIV_MASK, tmp); + state->enabled = value & channel_data->pwm_en_mask; value = readl(meson->base + channel_data->reg_offset); - channel->lo = FIELD_GET(PWM_LOW_MASK, value); channel->hi = FIELD_GET(PWM_HIGH_MASK, value); - if (channel->lo == 0) { - state->period = meson_pwm_cnt_to_ns(chip, pwm, channel->hi); - state->duty_cycle = state->period; - } else if (channel->lo >= channel->hi) { - state->period = meson_pwm_cnt_to_ns(chip, pwm, - channel->lo + channel->hi); - state->duty_cycle = meson_pwm_cnt_to_ns(chip, pwm, - channel->hi); - } else { - state->period = 0; - state->duty_cycle = 0; - } + state->period = meson_pwm_cnt_to_ns(chip, pwm, channel->lo + channel->hi); + state->duty_cycle = meson_pwm_cnt_to_ns(chip, pwm, channel->hi); state->polarity = PWM_POLARITY_NORMAL; @@ -378,7 +340,7 @@ static const struct pwm_ops meson_pwm_ops = { }; static const char * const pwm_meson8b_parent_names[] = { - "xtal", "vid_pll", "fclk_div4", "fclk_div3" + "xtal", NULL, "fclk_div4", "fclk_div3" }; static const struct meson_pwm_data pwm_meson8b_data = { @@ -386,15 +348,6 @@ static const struct meson_pwm_data pwm_meson8b_data = { .num_parents = ARRAY_SIZE(pwm_meson8b_parent_names), }; -static const char * const pwm_gxbb_parent_names[] = { - "xtal", "hdmi_pll", "fclk_div4", "fclk_div3" -}; - -static const struct meson_pwm_data pwm_gxbb_data = { - .parent_names = pwm_gxbb_parent_names, - .num_parents = ARRAY_SIZE(pwm_gxbb_parent_names), -}; - /* * Only the 2 first inputs of the GXBB AO PWMs are valid * The last 2 are grounded @@ -444,15 +397,6 @@ static const struct meson_pwm_data pwm_g12a_ao_cd_data = { .num_parents = ARRAY_SIZE(pwm_g12a_ao_cd_parent_names), }; -static const char * const pwm_g12a_ee_parent_names[] = { - "xtal", "hdmi_pll", "fclk_div4", "fclk_div3" -}; - -static const struct meson_pwm_data pwm_g12a_ee_data = { - .parent_names = pwm_g12a_ee_parent_names, - .num_parents = ARRAY_SIZE(pwm_g12a_ee_parent_names), -}; - static const struct of_device_id meson_pwm_matches[] = { { .compatible = "amlogic,meson8b-pwm", @@ -460,7 +404,7 @@ static const struct of_device_id meson_pwm_matches[] = { }, { .compatible = "amlogic,meson-gxbb-pwm", - .data = &pwm_gxbb_data + .data = &pwm_meson8b_data }, { .compatible = "amlogic,meson-gxbb-ao-pwm", @@ -476,7 +420,7 @@ static const struct of_device_id meson_pwm_matches[] = { }, { .compatible = "amlogic,meson-g12a-ee-pwm", - .data = &pwm_g12a_ee_data + .data = &pwm_meson8b_data }, { .compatible = "amlogic,meson-g12a-ao-pwm-ab", @@ -492,21 +436,28 @@ MODULE_DEVICE_TABLE(of, meson_pwm_matches); static int meson_pwm_init_channels(struct meson_pwm *meson) { + struct clk_parent_data mux_parent_data[MESON_MAX_MUX_PARENTS] = {}; struct device *dev = meson->chip.dev; - struct clk_init_data init; unsigned int i; char name[255]; int err; + for (i = 0; i < meson->data->num_parents; i++) { + mux_parent_data[i].index = -1; + mux_parent_data[i].name = meson->data->parent_names[i]; + } + for (i = 0; i < meson->chip.npwm; i++) { struct meson_pwm_channel *channel = &meson->channels[i]; + struct clk_parent_data div_parent = {}, gate_parent = {}; + struct clk_init_data init = {}; snprintf(name, sizeof(name), "%s#mux%u", dev_name(dev), i); init.name = name; init.ops = &clk_mux_ops; init.flags = 0; - init.parent_names = meson->data->parent_names; + init.parent_data = mux_parent_data; init.num_parents = meson->data->num_parents; channel->mux.reg = meson->base + REG_MISC_AB; @@ -518,18 +469,63 @@ static int meson_pwm_init_channels(struct meson_pwm *meson) channel->mux.table = NULL; channel->mux.hw.init = &init; - channel->clk = devm_clk_register(dev, &channel->mux.hw); - if (IS_ERR(channel->clk)) { - err = PTR_ERR(channel->clk); + err = devm_clk_hw_register(dev, &channel->mux.hw); + if (err) { + dev_err(dev, "failed to register %s: %d\n", name, err); + return err; + } + + snprintf(name, sizeof(name), "%s#div%u", dev_name(dev), i); + + init.name = name; + init.ops = &clk_divider_ops; + init.flags = CLK_SET_RATE_PARENT; + div_parent.index = -1; + div_parent.hw = &channel->mux.hw; + init.parent_data = &div_parent; + init.num_parents = 1; + + channel->div.reg = meson->base + REG_MISC_AB; + channel->div.shift = meson_pwm_per_channel_data[i].clk_div_shift; + channel->div.width = MISC_CLK_DIV_WIDTH; + channel->div.hw.init = &init; + channel->div.flags = 0; + channel->div.lock = &meson->lock; + + err = devm_clk_hw_register(dev, &channel->div.hw); + if (err) { dev_err(dev, "failed to register %s: %d\n", name, err); return err; } - snprintf(name, sizeof(name), "clkin%u", i); + snprintf(name, sizeof(name), "%s#gate%u", dev_name(dev), i); - channel->clk_parent = devm_clk_get_optional(dev, name); - if (IS_ERR(channel->clk_parent)) - return PTR_ERR(channel->clk_parent); + init.name = name; + init.ops = &clk_gate_ops; + init.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED; + gate_parent.index = -1; + gate_parent.hw = &channel->div.hw; + init.parent_data = &gate_parent; + init.num_parents = 1; + + channel->gate.reg = meson->base + REG_MISC_AB; + channel->gate.bit_idx = meson_pwm_per_channel_data[i].clk_en_shift; + channel->gate.hw.init = &init; + channel->gate.flags = 0; + channel->gate.lock = &meson->lock; + + err = devm_clk_hw_register(dev, &channel->gate.hw); + if (err) { + dev_err(dev, "failed to register %s: %d\n", name, err); + return err; + } + + channel->clk = devm_clk_hw_get_clk(dev, &channel->gate.hw, NULL); + if (IS_ERR(channel->clk)) { + err = PTR_ERR(channel->clk); + dev_err(dev, "failed to register %s: %d\n", name, err); + return err; + } } return 0; diff --git a/drivers/pwm/pwm-microchip-core.c b/drivers/pwm/pwm-microchip-core.c new file mode 100644 index 0000000000000000000000000000000000000000..8750b57684a90fb7c131e296042477807788462a --- /dev/null +++ b/drivers/pwm/pwm-microchip-core.c @@ -0,0 +1,507 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * corePWM driver for Microchip "soft" FPGA IP cores. + * + * Copyright (c) 2021-2023 Microchip Corporation. All rights reserved. + * Author: Conor Dooley + * Documentation: + * https://www.microsemi.com/document-portal/doc_download/1245275-corepwm-hb + * + * Limitations: + * - If the IP block is configured without "shadow registers", all register + * writes will take effect immediately, causing glitches on the output. + * If shadow registers *are* enabled, setting the "SYNC_UPDATE" register + * notifies the core that it needs to update the registers defining the + * waveform from the contents of the "shadow registers". Otherwise, changes + * will take effective immediately, even for those channels. + * As setting the period/duty cycle takes 4 register writes, there is a window + * in which this races against the start of a new period. + * - The IP block has no concept of a duty cycle, only rising/falling edges of + * the waveform. Unfortunately, if the rising & falling edges registers have + * the same value written to them the IP block will do whichever of a rising + * or a falling edge is possible. I.E. a 50% waveform at twice the requested + * period. Therefore to get a 0% waveform, the output is set the max high/low + * time depending on polarity. + * If the duty cycle is 0%, and the requested period is less than the + * available period resolution, this will manifest as a ~100% waveform (with + * some output glitches) rather than 50%. + * - The PWM period is set for the whole IP block not per channel. The driver + * will only change the period if no other PWM output is enabled. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MCHPCOREPWM_PRESCALE_MAX 0xff +#define MCHPCOREPWM_PERIOD_STEPS_MAX 0xfe +#define MCHPCOREPWM_PERIOD_MAX 0xff00 + +#define MCHPCOREPWM_PRESCALE 0x00 +#define MCHPCOREPWM_PERIOD 0x04 +#define MCHPCOREPWM_EN(i) (0x08 + 0x04 * (i)) /* 0x08, 0x0c */ +#define MCHPCOREPWM_POSEDGE(i) (0x10 + 0x08 * (i)) /* 0x10, 0x18, ..., 0x88 */ +#define MCHPCOREPWM_NEGEDGE(i) (0x14 + 0x08 * (i)) /* 0x14, 0x1c, ..., 0x8c */ +#define MCHPCOREPWM_SYNC_UPD 0xe4 +#define MCHPCOREPWM_TIMEOUT_MS 100u + +struct mchp_core_pwm_chip { + struct pwm_chip chip; + struct clk *clk; + void __iomem *base; + struct mutex lock; /* protects the shared period */ + ktime_t update_timestamp; + u32 sync_update_mask; + u16 channel_enabled; +}; + +static inline struct mchp_core_pwm_chip *to_mchp_core_pwm(struct pwm_chip *chip) +{ + return container_of(chip, struct mchp_core_pwm_chip, chip); +} + +static void mchp_core_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm, + bool enable, u64 period) +{ + struct mchp_core_pwm_chip *mchp_core_pwm = to_mchp_core_pwm(chip); + u8 channel_enable, reg_offset, shift; + + /* + * There are two adjacent 8 bit control regs, the lower reg controls + * 0-7 and the upper reg 8-15. Check if the pwm is in the upper reg + * and if so, offset by the bus width. + */ + reg_offset = MCHPCOREPWM_EN(pwm->hwpwm >> 3); + shift = pwm->hwpwm & 7; + + channel_enable = readb_relaxed(mchp_core_pwm->base + reg_offset); + channel_enable &= ~(1 << shift); + channel_enable |= (enable << shift); + + writel_relaxed(channel_enable, mchp_core_pwm->base + reg_offset); + mchp_core_pwm->channel_enabled &= ~BIT(pwm->hwpwm); + mchp_core_pwm->channel_enabled |= enable << pwm->hwpwm; + + /* + * The updated values will not appear on the bus until they have been + * applied to the waveform at the beginning of the next period. + * This is a NO-OP if the channel does not have shadow registers. + */ + if (mchp_core_pwm->sync_update_mask & (1 << pwm->hwpwm)) + mchp_core_pwm->update_timestamp = ktime_add_ns(ktime_get(), period); +} + +static void mchp_core_pwm_wait_for_sync_update(struct mchp_core_pwm_chip *mchp_core_pwm, + unsigned int channel) +{ + /* + * If a shadow register is used for this PWM channel, and iff there is + * a pending update to the waveform, we must wait for it to be applied + * before attempting to read its state. Reading the registers yields + * the currently implemented settings & the new ones are only readable + * once the current period has ended. + */ + + if (mchp_core_pwm->sync_update_mask & (1 << channel)) { + ktime_t current_time = ktime_get(); + s64 remaining_ns; + u32 delay_us; + + remaining_ns = ktime_to_ns(ktime_sub(mchp_core_pwm->update_timestamp, + current_time)); + + /* + * If the update has gone through, don't bother waiting for + * obvious reasons. Otherwise wait around for an appropriate + * amount of time for the update to go through. + */ + if (remaining_ns <= 0) + return; + + delay_us = DIV_ROUND_UP_ULL(remaining_ns, NSEC_PER_USEC); + fsleep(delay_us); + } +} + +static u64 mchp_core_pwm_calc_duty(const struct pwm_state *state, u64 clk_rate, + u8 prescale, u8 period_steps) +{ + u64 duty_steps, tmp; + + /* + * Calculate the duty cycle in multiples of the prescaled period: + * duty_steps = duty_in_ns / step_in_ns + * step_in_ns = (prescale * NSEC_PER_SEC) / clk_rate + * The code below is rearranged slightly to only divide once. + */ + tmp = (((u64)prescale) + 1) * NSEC_PER_SEC; + duty_steps = mul_u64_u64_div_u64(state->duty_cycle, clk_rate, tmp); + + return duty_steps; +} + +static void mchp_core_pwm_apply_duty(struct pwm_chip *chip, struct pwm_device *pwm, + const struct pwm_state *state, u64 duty_steps, + u16 period_steps) +{ + struct mchp_core_pwm_chip *mchp_core_pwm = to_mchp_core_pwm(chip); + u8 posedge, negedge; + u8 first_edge = 0, second_edge = duty_steps; + + /* + * Setting posedge == negedge doesn't yield a constant output, + * so that's an unsuitable setting to model duty_steps = 0. + * In that case set the unwanted edge to a value that never + * triggers. + */ + if (duty_steps == 0) + first_edge = period_steps + 1; + + if (state->polarity == PWM_POLARITY_INVERSED) { + negedge = first_edge; + posedge = second_edge; + } else { + posedge = first_edge; + negedge = second_edge; + } + + /* + * Set the sync bit which ensures that periods that already started are + * completed unaltered. At each counter reset event the values are + * updated from the shadow registers. + */ + writel_relaxed(posedge, mchp_core_pwm->base + MCHPCOREPWM_POSEDGE(pwm->hwpwm)); + writel_relaxed(negedge, mchp_core_pwm->base + MCHPCOREPWM_NEGEDGE(pwm->hwpwm)); +} + +static int mchp_core_pwm_calc_period(const struct pwm_state *state, unsigned long clk_rate, + u16 *prescale, u16 *period_steps) +{ + u64 tmp; + + /* + * Calculate the period cycles and prescale values. + * The registers are each 8 bits wide & multiplied to compute the period + * using the formula: + * (prescale + 1) * (period_steps + 1) + * period = ------------------------------------- + * clk_rate + * so the maximum period that can be generated is 0x10000 times the + * period of the input clock. + * However, due to the design of the "hardware", it is not possible to + * attain a 100% duty cycle if the full range of period_steps is used. + * Therefore period_steps is restricted to 0xfe and the maximum multiple + * of the clock period attainable is (0xff + 1) * (0xfe + 1) = 0xff00 + * + * The prescale and period_steps registers operate similarly to + * CLK_DIVIDER_ONE_BASED, where the value used by the hardware is that + * in the register plus one. + * It's therefore not possible to set a period lower than 1/clk_rate, so + * if tmp is 0, abort. Without aborting, we will set a period that is + * greater than that requested and, more importantly, will trigger the + * neg-/pos-edge issue described in the limitations. + */ + tmp = mul_u64_u64_div_u64(state->period, clk_rate, NSEC_PER_SEC); + if (tmp >= MCHPCOREPWM_PERIOD_MAX) { + *prescale = MCHPCOREPWM_PRESCALE_MAX; + *period_steps = MCHPCOREPWM_PERIOD_STEPS_MAX; + + return 0; + } + + /* + * There are multiple strategies that could be used to choose the + * prescale & period_steps values. + * Here the idea is to pick values so that the selection of duty cycles + * is as finegrain as possible, while also keeping the period less than + * that requested. + * + * A simple way to satisfy the first condition is to always set + * period_steps to its maximum value. This neatly also satisfies the + * second condition too, since using the maximum value of period_steps + * to calculate prescale actually calculates its upper bound. + * Integer division will ensure a round down, so the period will thereby + * always be less than that requested. + * + * The downside of this approach is a significant degree of inaccuracy, + * especially as tmp approaches integer multiples of + * MCHPCOREPWM_PERIOD_STEPS_MAX. + * + * As we must produce a period less than that requested, and for the + * sake of creating a simple algorithm, disallow small values of tmp + * that would need special handling. + */ + if (tmp < MCHPCOREPWM_PERIOD_STEPS_MAX + 1) + return -EINVAL; + + /* + * This "optimal" value for prescale is be calculated using the maximum + * permitted value of period_steps, 0xfe. + * + * period * clk_rate + * prescale = ------------------------- - 1 + * NSEC_PER_SEC * (0xfe + 1) + * + * + * period * clk_rate + * ------------------- was precomputed as `tmp` + * NSEC_PER_SEC + */ + *prescale = ((u16)tmp) / (MCHPCOREPWM_PERIOD_STEPS_MAX + 1) - 1; + + /* + * period_steps can be computed from prescale: + * period * clk_rate + * period_steps = ----------------------------- - 1 + * NSEC_PER_SEC * (prescale + 1) + * + * However, in this approximation, we simply use the maximum value that + * was used to compute prescale. + */ + *period_steps = MCHPCOREPWM_PERIOD_STEPS_MAX; + + return 0; +} + +static int mchp_core_pwm_apply_locked(struct pwm_chip *chip, struct pwm_device *pwm, + const struct pwm_state *state) +{ + struct mchp_core_pwm_chip *mchp_core_pwm = to_mchp_core_pwm(chip); + bool period_locked; + unsigned long clk_rate; + u64 duty_steps; + u16 prescale, period_steps; + int ret; + + if (!state->enabled) { + mchp_core_pwm_enable(chip, pwm, false, pwm->state.period); + return 0; + } + + /* + * If clk_rate is too big, the following multiplication might overflow. + * However this is implausible, as the fabric of current FPGAs cannot + * provide clocks at a rate high enough. + */ + clk_rate = clk_get_rate(mchp_core_pwm->clk); + if (clk_rate >= NSEC_PER_SEC) + return -EINVAL; + + ret = mchp_core_pwm_calc_period(state, clk_rate, &prescale, &period_steps); + if (ret) + return ret; + + /* + * If the only thing that has changed is the duty cycle or the polarity, + * we can shortcut the calculations and just compute/apply the new duty + * cycle pos & neg edges + * As all the channels share the same period, do not allow it to be + * changed if any other channels are enabled. + * If the period is locked, it may not be possible to use a period + * less than that requested. In that case, we just abort. + */ + period_locked = mchp_core_pwm->channel_enabled & ~(1 << pwm->hwpwm); + + if (period_locked) { + u16 hw_prescale; + u16 hw_period_steps; + + hw_prescale = readb_relaxed(mchp_core_pwm->base + MCHPCOREPWM_PRESCALE); + hw_period_steps = readb_relaxed(mchp_core_pwm->base + MCHPCOREPWM_PERIOD); + + if ((period_steps + 1) * (prescale + 1) < + (hw_period_steps + 1) * (hw_prescale + 1)) + return -EINVAL; + + /* + * It is possible that something could have set the period_steps + * register to 0xff, which would prevent us from setting a 100% + * or 0% relative duty cycle, as explained above in + * mchp_core_pwm_calc_period(). + * The period is locked and we cannot change this, so we abort. + */ + if (hw_period_steps == MCHPCOREPWM_PERIOD_STEPS_MAX) + return -EINVAL; + + prescale = hw_prescale; + period_steps = hw_period_steps; + } + + duty_steps = mchp_core_pwm_calc_duty(state, clk_rate, prescale, period_steps); + + /* + * Because the period is not per channel, it is possible that the + * requested duty cycle is longer than the period, in which case cap it + * to the period, IOW a 100% duty cycle. + */ + if (duty_steps > period_steps) + duty_steps = period_steps + 1; + + if (!period_locked) { + writel_relaxed(prescale, mchp_core_pwm->base + MCHPCOREPWM_PRESCALE); + writel_relaxed(period_steps, mchp_core_pwm->base + MCHPCOREPWM_PERIOD); + } + + mchp_core_pwm_apply_duty(chip, pwm, state, duty_steps, period_steps); + + mchp_core_pwm_enable(chip, pwm, true, pwm->state.period); + + return 0; +} + +static int mchp_core_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, + const struct pwm_state *state) +{ + struct mchp_core_pwm_chip *mchp_core_pwm = to_mchp_core_pwm(chip); + int ret; + + mutex_lock(&mchp_core_pwm->lock); + + mchp_core_pwm_wait_for_sync_update(mchp_core_pwm, pwm->hwpwm); + + ret = mchp_core_pwm_apply_locked(chip, pwm, state); + + mutex_unlock(&mchp_core_pwm->lock); + + return ret; +} + +static int mchp_core_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, + struct pwm_state *state) +{ + struct mchp_core_pwm_chip *mchp_core_pwm = to_mchp_core_pwm(chip); + u64 rate; + u16 prescale, period_steps; + u8 duty_steps, posedge, negedge; + + mutex_lock(&mchp_core_pwm->lock); + + mchp_core_pwm_wait_for_sync_update(mchp_core_pwm, pwm->hwpwm); + + if (mchp_core_pwm->channel_enabled & (1 << pwm->hwpwm)) + state->enabled = true; + else + state->enabled = false; + + rate = clk_get_rate(mchp_core_pwm->clk); + + /* + * Calculating the period: + * The registers are each 8 bits wide & multiplied to compute the period + * using the formula: + * (prescale + 1) * (period_steps + 1) + * period = ------------------------------------- + * clk_rate + * + * Note: + * The prescale and period_steps registers operate similarly to + * CLK_DIVIDER_ONE_BASED, where the value used by the hardware is that + * in the register plus one. + */ + prescale = readb_relaxed(mchp_core_pwm->base + MCHPCOREPWM_PRESCALE); + period_steps = readb_relaxed(mchp_core_pwm->base + MCHPCOREPWM_PERIOD); + + state->period = (period_steps + 1) * (prescale + 1); + state->period *= NSEC_PER_SEC; + state->period = DIV64_U64_ROUND_UP(state->period, rate); + + posedge = readb_relaxed(mchp_core_pwm->base + MCHPCOREPWM_POSEDGE(pwm->hwpwm)); + negedge = readb_relaxed(mchp_core_pwm->base + MCHPCOREPWM_NEGEDGE(pwm->hwpwm)); + + mutex_unlock(&mchp_core_pwm->lock); + + if (negedge == posedge) { + state->duty_cycle = state->period; + state->period *= 2; + } else { + duty_steps = abs((s16)posedge - (s16)negedge); + state->duty_cycle = duty_steps * (prescale + 1) * NSEC_PER_SEC; + state->duty_cycle = DIV64_U64_ROUND_UP(state->duty_cycle, rate); + } + + state->polarity = negedge < posedge ? PWM_POLARITY_INVERSED : PWM_POLARITY_NORMAL; + + return 0; +} + +static const struct pwm_ops mchp_core_pwm_ops = { + .apply = mchp_core_pwm_apply, + .get_state = mchp_core_pwm_get_state, + .owner = THIS_MODULE, +}; + +static const struct of_device_id mchp_core_of_match[] = { + { + .compatible = "microchip,corepwm-rtl-v4", + }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, mchp_core_of_match); + +static int mchp_core_pwm_probe(struct platform_device *pdev) +{ + struct mchp_core_pwm_chip *mchp_core_pwm; + struct resource *regs; + int ret; + + mchp_core_pwm = devm_kzalloc(&pdev->dev, sizeof(*mchp_core_pwm), GFP_KERNEL); + if (!mchp_core_pwm) + return -ENOMEM; + + mchp_core_pwm->base = devm_platform_get_and_ioremap_resource(pdev, 0, ®s); + if (IS_ERR(mchp_core_pwm->base)) + return PTR_ERR(mchp_core_pwm->base); + + mchp_core_pwm->clk = devm_clk_get_enabled(&pdev->dev, NULL); + if (IS_ERR(mchp_core_pwm->clk)) + return dev_err_probe(&pdev->dev, PTR_ERR(mchp_core_pwm->clk), + "failed to get PWM clock\n"); + + if (of_property_read_u32(pdev->dev.of_node, "microchip,sync-update-mask", + &mchp_core_pwm->sync_update_mask)) + mchp_core_pwm->sync_update_mask = 0; + + mutex_init(&mchp_core_pwm->lock); + + mchp_core_pwm->chip.dev = &pdev->dev; + mchp_core_pwm->chip.ops = &mchp_core_pwm_ops; + mchp_core_pwm->chip.npwm = 16; + + mchp_core_pwm->channel_enabled = readb_relaxed(mchp_core_pwm->base + MCHPCOREPWM_EN(0)); + mchp_core_pwm->channel_enabled |= + readb_relaxed(mchp_core_pwm->base + MCHPCOREPWM_EN(1)) << 8; + + /* + * Enable synchronous update mode for all channels for which shadow + * registers have been synthesised. + */ + writel_relaxed(1U, mchp_core_pwm->base + MCHPCOREPWM_SYNC_UPD); + mchp_core_pwm->update_timestamp = ktime_get(); + + ret = devm_pwmchip_add(&pdev->dev, &mchp_core_pwm->chip); + if (ret) + return dev_err_probe(&pdev->dev, ret, "Failed to add pwmchip\n"); + + return 0; +} + +static struct platform_driver mchp_core_pwm_driver = { + .driver = { + .name = "mchp-core-pwm", + .of_match_table = mchp_core_of_match, + }, + .probe = mchp_core_pwm_probe, +}; +module_platform_driver(mchp_core_pwm_driver); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Conor Dooley "); +MODULE_DESCRIPTION("corePWM driver for Microchip FPGAs"); diff --git a/drivers/pwm/pwm-mtk-disp.c b/drivers/pwm/pwm-mtk-disp.c index 79e321e96f56ab5e5d7d0c1131f863ff7d0ddc09..2401b67332417e3148338ee9531a3f0e4bc4cab1 100644 --- a/drivers/pwm/pwm-mtk-disp.c +++ b/drivers/pwm/pwm-mtk-disp.c @@ -79,14 +79,11 @@ static int mtk_disp_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, if (state->polarity != PWM_POLARITY_NORMAL) return -EINVAL; - if (!state->enabled) { - mtk_disp_pwm_update_bits(mdp, DISP_PWM_EN, mdp->data->enable_mask, - 0x0); - - if (mdp->enabled) { - clk_disable_unprepare(mdp->clk_mm); - clk_disable_unprepare(mdp->clk_main); - } + if (!state->enabled && mdp->enabled) { + mtk_disp_pwm_update_bits(mdp, DISP_PWM_EN, + mdp->data->enable_mask, 0x0); + clk_disable_unprepare(mdp->clk_mm); + clk_disable_unprepare(mdp->clk_main); mdp->enabled = false; return 0; diff --git a/drivers/pwm/pwm-pca9685.c b/drivers/pwm/pwm-pca9685.c index 3ed5a48ca58129285e2e8afa37c8d1daaf44414f..3038a68412a75e1270cd44c5590fcefe765b94e6 100644 --- a/drivers/pwm/pwm-pca9685.c +++ b/drivers/pwm/pwm-pca9685.c @@ -665,7 +665,7 @@ static struct i2c_driver pca9685_i2c_driver = { .of_match_table = of_match_ptr(pca9685_dt_ids), .pm = &pca9685_pwm_pm, }, - .probe_new = pca9685_pwm_probe, + .probe = pca9685_pwm_probe, .remove = pca9685_pwm_remove, .id_table = pca9685_id, }; diff --git a/drivers/pwm/pwm-pxa.c b/drivers/pwm/pwm-pxa.c index 46ed668bd1411b363e56876a14799c412d5b9bed..762429d5647fd5633119528885e281e41e0175ea 100644 --- a/drivers/pwm/pwm-pxa.c +++ b/drivers/pwm/pwm-pxa.c @@ -8,7 +8,7 @@ * eric miao * * Links to reference manuals for some of the supported PWM chips can be found - * in Documentation/arm/marvell.rst. + * in Documentation/arch/arm/marvell.rst. * * Limitations: * - When PWM is stopped, the current PWM period stops abruptly at the next diff --git a/drivers/pwm/pwm-rz-mtu3.c b/drivers/pwm/pwm-rz-mtu3.c new file mode 100644 index 0000000000000000000000000000000000000000..bed8bd671e374f25f118d597ee4fd262989e433c --- /dev/null +++ b/drivers/pwm/pwm-rz-mtu3.c @@ -0,0 +1,551 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Renesas RZ/G2L MTU3a PWM Timer driver + * + * Copyright (C) 2023 Renesas Electronics Corporation + * + * Hardware manual for this IP can be found here + * https://www.renesas.com/eu/en/document/mah/rzg2l-group-rzg2lc-group-users-manual-hardware-0?language=en + * + * Limitations: + * - When PWM is disabled, the output is driven to Hi-Z. + * - While the hardware supports both polarities, the driver (for now) + * only handles normal polarity. + * - HW uses one counter and two match components to configure duty_cycle + * and period. + * - Multi-Function Timer Pulse Unit (a.k.a MTU) has 7 HW channels for PWM + * operations. (The channels are MTU{0..4, 6, 7}.) + * - MTU{1, 2} channels have a single IO, whereas all other HW channels have + * 2 IOs. + * - Each IO is modelled as an independent PWM channel. + * - rz_mtu3_channel_io_map table is used to map the PWM channel to the + * corresponding HW channel as there are difference in number of IOs + * between HW channels. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define RZ_MTU3_MAX_PWM_CHANNELS 12 +#define RZ_MTU3_MAX_HW_CHANNELS 7 + +/** + * struct rz_mtu3_channel_io_map - MTU3 pwm channel map + * + * @base_pwm_number: First PWM of a channel + * @num: number of IOs on the HW channel. + */ +struct rz_mtu3_channel_io_map { + u8 base_pwm_number; + u8 num_channel_ios; +}; + +/** + * struct rz_mtu3_pwm_channel - MTU3 pwm channel data + * + * @mtu: MTU3 channel data + * @map: MTU3 pwm channel map + */ +struct rz_mtu3_pwm_channel { + struct rz_mtu3_channel *mtu; + const struct rz_mtu3_channel_io_map *map; +}; + +/** + * struct rz_mtu3_pwm_chip - MTU3 pwm private data + * + * @chip: MTU3 pwm chip data + * @clk: MTU3 module clock + * @lock: Lock to prevent concurrent access for usage count + * @rate: MTU3 clock rate + * @user_count: MTU3 usage count + * @enable_count: MTU3 enable count + * @prescale: MTU3 prescale + * @channel_data: MTU3 pwm channel data + */ + +struct rz_mtu3_pwm_chip { + struct pwm_chip chip; + struct clk *clk; + struct mutex lock; + unsigned long rate; + u32 user_count[RZ_MTU3_MAX_HW_CHANNELS]; + u32 enable_count[RZ_MTU3_MAX_HW_CHANNELS]; + u8 prescale[RZ_MTU3_MAX_HW_CHANNELS]; + struct rz_mtu3_pwm_channel channel_data[RZ_MTU3_MAX_HW_CHANNELS]; +}; + +/* + * The MTU channels are {0..4, 6, 7} and the number of IO on MTU1 + * and MTU2 channel is 1 compared to 2 on others. + */ +static const struct rz_mtu3_channel_io_map channel_map[] = { + { 0, 2 }, { 2, 1 }, { 3, 1 }, { 4, 2 }, { 6, 2 }, { 8, 2 }, { 10, 2 } +}; + +static inline struct rz_mtu3_pwm_chip *to_rz_mtu3_pwm_chip(struct pwm_chip *chip) +{ + return container_of(chip, struct rz_mtu3_pwm_chip, chip); +} + +static void rz_mtu3_pwm_read_tgr_registers(struct rz_mtu3_pwm_channel *priv, + u16 reg_pv_offset, u16 *pv_val, + u16 reg_dc_offset, u16 *dc_val) +{ + *pv_val = rz_mtu3_16bit_ch_read(priv->mtu, reg_pv_offset); + *dc_val = rz_mtu3_16bit_ch_read(priv->mtu, reg_dc_offset); +} + +static void rz_mtu3_pwm_write_tgr_registers(struct rz_mtu3_pwm_channel *priv, + u16 reg_pv_offset, u16 pv_val, + u16 reg_dc_offset, u16 dc_val) +{ + rz_mtu3_16bit_ch_write(priv->mtu, reg_pv_offset, pv_val); + rz_mtu3_16bit_ch_write(priv->mtu, reg_dc_offset, dc_val); +} + +static u8 rz_mtu3_pwm_calculate_prescale(struct rz_mtu3_pwm_chip *rz_mtu3, + u64 period_cycles) +{ + u32 prescaled_period_cycles; + u8 prescale; + + /* + * Supported prescale values are 1, 4, 16 and 64. + * TODO: Support prescale values 2, 8, 32, 256 and 1024. + */ + prescaled_period_cycles = period_cycles >> 16; + if (prescaled_period_cycles >= 16) + prescale = 3; + else + prescale = (fls(prescaled_period_cycles) + 1) / 2; + + return prescale; +} + +static struct rz_mtu3_pwm_channel * +rz_mtu3_get_channel(struct rz_mtu3_pwm_chip *rz_mtu3_pwm, u32 hwpwm) +{ + struct rz_mtu3_pwm_channel *priv = rz_mtu3_pwm->channel_data; + unsigned int ch; + + for (ch = 0; ch < RZ_MTU3_MAX_HW_CHANNELS; ch++, priv++) { + if (priv->map->base_pwm_number + priv->map->num_channel_ios > hwpwm) + break; + } + + return priv; +} + +static bool rz_mtu3_pwm_is_ch_enabled(struct rz_mtu3_pwm_chip *rz_mtu3_pwm, + u32 hwpwm) +{ + struct rz_mtu3_pwm_channel *priv; + bool is_channel_en; + u8 val; + + priv = rz_mtu3_get_channel(rz_mtu3_pwm, hwpwm); + is_channel_en = rz_mtu3_is_enabled(priv->mtu); + if (!is_channel_en) + return false; + + if (priv->map->base_pwm_number == hwpwm) + val = rz_mtu3_8bit_ch_read(priv->mtu, RZ_MTU3_TIORH); + else + val = rz_mtu3_8bit_ch_read(priv->mtu, RZ_MTU3_TIORL); + + return val & RZ_MTU3_TIOR_IOA; +} + +static int rz_mtu3_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm) +{ + struct rz_mtu3_pwm_chip *rz_mtu3_pwm = to_rz_mtu3_pwm_chip(chip); + struct rz_mtu3_pwm_channel *priv; + bool is_mtu3_channel_available; + u32 ch; + + priv = rz_mtu3_get_channel(rz_mtu3_pwm, pwm->hwpwm); + ch = priv - rz_mtu3_pwm->channel_data; + + mutex_lock(&rz_mtu3_pwm->lock); + /* + * Each channel must be requested only once, so if the channel + * serves two PWMs and the other is already requested, skip over + * rz_mtu3_request_channel() + */ + if (!rz_mtu3_pwm->user_count[ch]) { + is_mtu3_channel_available = rz_mtu3_request_channel(priv->mtu); + if (!is_mtu3_channel_available) { + mutex_unlock(&rz_mtu3_pwm->lock); + return -EBUSY; + } + } + + rz_mtu3_pwm->user_count[ch]++; + mutex_unlock(&rz_mtu3_pwm->lock); + + return 0; +} + +static void rz_mtu3_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm) +{ + struct rz_mtu3_pwm_chip *rz_mtu3_pwm = to_rz_mtu3_pwm_chip(chip); + struct rz_mtu3_pwm_channel *priv; + u32 ch; + + priv = rz_mtu3_get_channel(rz_mtu3_pwm, pwm->hwpwm); + ch = priv - rz_mtu3_pwm->channel_data; + + mutex_lock(&rz_mtu3_pwm->lock); + rz_mtu3_pwm->user_count[ch]--; + if (!rz_mtu3_pwm->user_count[ch]) + rz_mtu3_release_channel(priv->mtu); + + mutex_unlock(&rz_mtu3_pwm->lock); +} + +static int rz_mtu3_pwm_enable(struct rz_mtu3_pwm_chip *rz_mtu3_pwm, + struct pwm_device *pwm) +{ + struct rz_mtu3_pwm_channel *priv; + u32 ch; + u8 val; + int rc; + + rc = pm_runtime_resume_and_get(rz_mtu3_pwm->chip.dev); + if (rc) + return rc; + + priv = rz_mtu3_get_channel(rz_mtu3_pwm, pwm->hwpwm); + ch = priv - rz_mtu3_pwm->channel_data; + val = RZ_MTU3_TIOR_OC_IOB_TOGGLE | RZ_MTU3_TIOR_OC_IOA_H_COMP_MATCH; + + rz_mtu3_8bit_ch_write(priv->mtu, RZ_MTU3_TMDR1, RZ_MTU3_TMDR1_MD_PWMMODE1); + if (priv->map->base_pwm_number == pwm->hwpwm) + rz_mtu3_8bit_ch_write(priv->mtu, RZ_MTU3_TIORH, val); + else + rz_mtu3_8bit_ch_write(priv->mtu, RZ_MTU3_TIORL, val); + + mutex_lock(&rz_mtu3_pwm->lock); + if (!rz_mtu3_pwm->enable_count[ch]) + rz_mtu3_enable(priv->mtu); + + rz_mtu3_pwm->enable_count[ch]++; + mutex_unlock(&rz_mtu3_pwm->lock); + + return 0; +} + +static void rz_mtu3_pwm_disable(struct rz_mtu3_pwm_chip *rz_mtu3_pwm, + struct pwm_device *pwm) +{ + struct rz_mtu3_pwm_channel *priv; + u32 ch; + + priv = rz_mtu3_get_channel(rz_mtu3_pwm, pwm->hwpwm); + ch = priv - rz_mtu3_pwm->channel_data; + + /* Disable output pins of MTU3 channel */ + if (priv->map->base_pwm_number == pwm->hwpwm) + rz_mtu3_8bit_ch_write(priv->mtu, RZ_MTU3_TIORH, RZ_MTU3_TIOR_OC_RETAIN); + else + rz_mtu3_8bit_ch_write(priv->mtu, RZ_MTU3_TIORL, RZ_MTU3_TIOR_OC_RETAIN); + + mutex_lock(&rz_mtu3_pwm->lock); + rz_mtu3_pwm->enable_count[ch]--; + if (!rz_mtu3_pwm->enable_count[ch]) + rz_mtu3_disable(priv->mtu); + + mutex_unlock(&rz_mtu3_pwm->lock); + + pm_runtime_put_sync(rz_mtu3_pwm->chip.dev); +} + +static int rz_mtu3_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, + struct pwm_state *state) +{ + struct rz_mtu3_pwm_chip *rz_mtu3_pwm = to_rz_mtu3_pwm_chip(chip); + int rc; + + rc = pm_runtime_resume_and_get(chip->dev); + if (rc) + return rc; + + state->enabled = rz_mtu3_pwm_is_ch_enabled(rz_mtu3_pwm, pwm->hwpwm); + if (state->enabled) { + struct rz_mtu3_pwm_channel *priv; + u8 prescale, val; + u16 dc, pv; + u64 tmp; + + priv = rz_mtu3_get_channel(rz_mtu3_pwm, pwm->hwpwm); + if (priv->map->base_pwm_number == pwm->hwpwm) + rz_mtu3_pwm_read_tgr_registers(priv, RZ_MTU3_TGRA, &pv, + RZ_MTU3_TGRB, &dc); + else + rz_mtu3_pwm_read_tgr_registers(priv, RZ_MTU3_TGRC, &pv, + RZ_MTU3_TGRD, &dc); + + val = rz_mtu3_8bit_ch_read(priv->mtu, RZ_MTU3_TCR); + prescale = FIELD_GET(RZ_MTU3_TCR_TPCS, val); + + /* With prescale <= 7 and pv <= 0xffff this doesn't overflow. */ + tmp = NSEC_PER_SEC * (u64)pv << (2 * prescale); + state->period = DIV_ROUND_UP_ULL(tmp, rz_mtu3_pwm->rate); + tmp = NSEC_PER_SEC * (u64)dc << (2 * prescale); + state->duty_cycle = DIV_ROUND_UP_ULL(tmp, rz_mtu3_pwm->rate); + + if (state->duty_cycle > state->period) + state->duty_cycle = state->period; + } + + state->polarity = PWM_POLARITY_NORMAL; + pm_runtime_put(chip->dev); + + return 0; +} + +static u16 rz_mtu3_pwm_calculate_pv_or_dc(u64 period_or_duty_cycle, u8 prescale) +{ + return min(period_or_duty_cycle >> (2 * prescale), (u64)U16_MAX); +} + +static int rz_mtu3_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, + const struct pwm_state *state) +{ + struct rz_mtu3_pwm_chip *rz_mtu3_pwm = to_rz_mtu3_pwm_chip(chip); + struct rz_mtu3_pwm_channel *priv; + u64 period_cycles; + u64 duty_cycles; + u8 prescale; + u16 pv, dc; + u8 val; + u32 ch; + + priv = rz_mtu3_get_channel(rz_mtu3_pwm, pwm->hwpwm); + ch = priv - rz_mtu3_pwm->channel_data; + + period_cycles = mul_u64_u32_div(state->period, rz_mtu3_pwm->rate, + NSEC_PER_SEC); + prescale = rz_mtu3_pwm_calculate_prescale(rz_mtu3_pwm, period_cycles); + + /* + * Prescalar is shared by multiple channels, so prescale can + * NOT be modified when there are multiple channels in use with + * different settings. Modify prescalar if other PWM is off or handle + * it, if current prescale value is less than the one we want to set. + */ + if (rz_mtu3_pwm->enable_count[ch] > 1) { + if (rz_mtu3_pwm->prescale[ch] > prescale) + return -EBUSY; + + prescale = rz_mtu3_pwm->prescale[ch]; + } + + pv = rz_mtu3_pwm_calculate_pv_or_dc(period_cycles, prescale); + + duty_cycles = mul_u64_u32_div(state->duty_cycle, rz_mtu3_pwm->rate, + NSEC_PER_SEC); + dc = rz_mtu3_pwm_calculate_pv_or_dc(duty_cycles, prescale); + + /* + * If the PWM channel is disabled, make sure to turn on the clock + * before writing the register. + */ + if (!pwm->state.enabled) { + int rc; + + rc = pm_runtime_resume_and_get(chip->dev); + if (rc) + return rc; + } + + val = RZ_MTU3_TCR_CKEG_RISING | prescale; + + /* Counter must be stopped while updating TCR register */ + if (rz_mtu3_pwm->prescale[ch] != prescale && rz_mtu3_pwm->enable_count[ch]) + rz_mtu3_disable(priv->mtu); + + if (priv->map->base_pwm_number == pwm->hwpwm) { + rz_mtu3_8bit_ch_write(priv->mtu, RZ_MTU3_TCR, + RZ_MTU3_TCR_CCLR_TGRA | val); + rz_mtu3_pwm_write_tgr_registers(priv, RZ_MTU3_TGRA, pv, + RZ_MTU3_TGRB, dc); + } else { + rz_mtu3_8bit_ch_write(priv->mtu, RZ_MTU3_TCR, + RZ_MTU3_TCR_CCLR_TGRC | val); + rz_mtu3_pwm_write_tgr_registers(priv, RZ_MTU3_TGRC, pv, + RZ_MTU3_TGRD, dc); + } + + if (rz_mtu3_pwm->prescale[ch] != prescale) { + /* + * Prescalar is shared by multiple channels, we cache the + * prescalar value from first enabled channel and use the same + * value for both channels. + */ + rz_mtu3_pwm->prescale[ch] = prescale; + + if (rz_mtu3_pwm->enable_count[ch]) + rz_mtu3_enable(priv->mtu); + } + + /* If the PWM is not enabled, turn the clock off again to save power. */ + if (!pwm->state.enabled) + pm_runtime_put(chip->dev); + + return 0; +} + +static int rz_mtu3_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, + const struct pwm_state *state) +{ + struct rz_mtu3_pwm_chip *rz_mtu3_pwm = to_rz_mtu3_pwm_chip(chip); + bool enabled = pwm->state.enabled; + int ret; + + if (state->polarity != PWM_POLARITY_NORMAL) + return -EINVAL; + + if (!state->enabled) { + if (enabled) + rz_mtu3_pwm_disable(rz_mtu3_pwm, pwm); + + return 0; + } + + mutex_lock(&rz_mtu3_pwm->lock); + ret = rz_mtu3_pwm_config(chip, pwm, state); + mutex_unlock(&rz_mtu3_pwm->lock); + if (ret) + return ret; + + if (!enabled) + ret = rz_mtu3_pwm_enable(rz_mtu3_pwm, pwm); + + return ret; +} + +static const struct pwm_ops rz_mtu3_pwm_ops = { + .request = rz_mtu3_pwm_request, + .free = rz_mtu3_pwm_free, + .get_state = rz_mtu3_pwm_get_state, + .apply = rz_mtu3_pwm_apply, + .owner = THIS_MODULE, +}; + +static int rz_mtu3_pwm_pm_runtime_suspend(struct device *dev) +{ + struct rz_mtu3_pwm_chip *rz_mtu3_pwm = dev_get_drvdata(dev); + + clk_disable_unprepare(rz_mtu3_pwm->clk); + + return 0; +} + +static int rz_mtu3_pwm_pm_runtime_resume(struct device *dev) +{ + struct rz_mtu3_pwm_chip *rz_mtu3_pwm = dev_get_drvdata(dev); + + return clk_prepare_enable(rz_mtu3_pwm->clk); +} + +static DEFINE_RUNTIME_DEV_PM_OPS(rz_mtu3_pwm_pm_ops, + rz_mtu3_pwm_pm_runtime_suspend, + rz_mtu3_pwm_pm_runtime_resume, NULL); + +static void rz_mtu3_pwm_pm_disable(void *data) +{ + struct rz_mtu3_pwm_chip *rz_mtu3_pwm = data; + + clk_rate_exclusive_put(rz_mtu3_pwm->clk); + pm_runtime_disable(rz_mtu3_pwm->chip.dev); + pm_runtime_set_suspended(rz_mtu3_pwm->chip.dev); +} + +static int rz_mtu3_pwm_probe(struct platform_device *pdev) +{ + struct rz_mtu3 *parent_ddata = dev_get_drvdata(pdev->dev.parent); + struct rz_mtu3_pwm_chip *rz_mtu3_pwm; + struct device *dev = &pdev->dev; + unsigned int i, j = 0; + int ret; + + rz_mtu3_pwm = devm_kzalloc(&pdev->dev, sizeof(*rz_mtu3_pwm), GFP_KERNEL); + if (!rz_mtu3_pwm) + return -ENOMEM; + + rz_mtu3_pwm->clk = parent_ddata->clk; + + for (i = 0; i < RZ_MTU_NUM_CHANNELS; i++) { + if (i == RZ_MTU3_CHAN_5 || i == RZ_MTU3_CHAN_8) + continue; + + rz_mtu3_pwm->channel_data[j].mtu = &parent_ddata->channels[i]; + rz_mtu3_pwm->channel_data[j].mtu->dev = dev; + rz_mtu3_pwm->channel_data[j].map = &channel_map[j]; + j++; + } + + mutex_init(&rz_mtu3_pwm->lock); + platform_set_drvdata(pdev, rz_mtu3_pwm); + ret = clk_prepare_enable(rz_mtu3_pwm->clk); + if (ret) + return dev_err_probe(dev, ret, "Clock enable failed\n"); + + clk_rate_exclusive_get(rz_mtu3_pwm->clk); + + rz_mtu3_pwm->rate = clk_get_rate(rz_mtu3_pwm->clk); + /* + * Refuse clk rates > 1 GHz to prevent overflow later for computing + * period and duty cycle. + */ + if (rz_mtu3_pwm->rate > NSEC_PER_SEC) { + ret = -EINVAL; + clk_rate_exclusive_put(rz_mtu3_pwm->clk); + goto disable_clock; + } + + pm_runtime_set_active(&pdev->dev); + pm_runtime_enable(&pdev->dev); + rz_mtu3_pwm->chip.dev = &pdev->dev; + ret = devm_add_action_or_reset(&pdev->dev, rz_mtu3_pwm_pm_disable, + rz_mtu3_pwm); + if (ret < 0) + return ret; + + rz_mtu3_pwm->chip.ops = &rz_mtu3_pwm_ops; + rz_mtu3_pwm->chip.npwm = RZ_MTU3_MAX_PWM_CHANNELS; + ret = devm_pwmchip_add(&pdev->dev, &rz_mtu3_pwm->chip); + if (ret) + return dev_err_probe(&pdev->dev, ret, "failed to add PWM chip\n"); + + pm_runtime_idle(&pdev->dev); + + return 0; + +disable_clock: + clk_disable_unprepare(rz_mtu3_pwm->clk); + return ret; +} + +static struct platform_driver rz_mtu3_pwm_driver = { + .driver = { + .name = "pwm-rz-mtu3", + .pm = pm_ptr(&rz_mtu3_pwm_pm_ops), + }, + .probe = rz_mtu3_pwm_probe, +}; +module_platform_driver(rz_mtu3_pwm_driver); + +MODULE_AUTHOR("Biju Das "); +MODULE_ALIAS("platform:pwm-rz-mtu3"); +MODULE_DESCRIPTION("Renesas RZ/G2L MTU3a PWM Timer Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/pwm/pwm-sifive.c b/drivers/pwm/pwm-sifive.c index 5b0574f635f6f8e3ffcf584deb6fe7a8c9c69d62..ae49d67ab2b1a62a6d84d0f031f715146c64d067 100644 --- a/drivers/pwm/pwm-sifive.c +++ b/drivers/pwm/pwm-sifive.c @@ -244,12 +244,12 @@ static int pwm_sifive_probe(struct platform_device *pdev) if (IS_ERR(ddata->regs)) return PTR_ERR(ddata->regs); - ddata->clk = devm_clk_get(dev, NULL); + ddata->clk = devm_clk_get_prepared(dev, NULL); if (IS_ERR(ddata->clk)) return dev_err_probe(dev, PTR_ERR(ddata->clk), "Unable to find controller clock\n"); - ret = clk_prepare_enable(ddata->clk); + ret = clk_enable(ddata->clk); if (ret) { dev_err(dev, "failed to enable clock for pwm: %d\n", ret); return ret; @@ -308,7 +308,6 @@ static int pwm_sifive_probe(struct platform_device *pdev) clk_disable(ddata->clk); --enabled_clks; } - clk_unprepare(ddata->clk); return ret; } @@ -327,8 +326,6 @@ static void pwm_sifive_remove(struct platform_device *dev) if (pwm->state.enabled) clk_disable(ddata->clk); } - - clk_unprepare(ddata->clk); } static const struct of_device_id pwm_sifive_of_match[] = { diff --git a/drivers/pwm/sysfs.c b/drivers/pwm/sysfs.c index 1a106ec3293929444896e8bdd5dc0063711285a4..8d1254761e4dd2ab465008875573c71a7ecfa3e7 100644 --- a/drivers/pwm/sysfs.c +++ b/drivers/pwm/sysfs.c @@ -424,6 +424,13 @@ static int pwm_class_resume_npwm(struct device *parent, unsigned int npwm) if (!export) continue; + /* If pwmchip was not enabled before suspend, do nothing. */ + if (!export->suspend.enabled) { + /* release lock taken in pwm_class_get_state */ + mutex_unlock(&export->lock); + continue; + } + state.enabled = export->suspend.enabled; ret = pwm_class_apply_state(export, pwm, &state); if (ret < 0) @@ -448,7 +455,17 @@ static int pwm_class_suspend(struct device *parent) if (!export) continue; + /* + * If pwmchip was not enabled before suspend, save + * state for resume time and do nothing else. + */ export->suspend = state; + if (!state.enabled) { + /* release lock taken in pwm_class_get_state */ + mutex_unlock(&export->lock); + continue; + } + state.enabled = false; ret = pwm_class_apply_state(export, pwm, &state); if (ret < 0) { diff --git a/drivers/ras/debugfs.c b/drivers/ras/debugfs.c index f0a6391b114628641b3c7eb17af0146517152acd..ffb973c328e36003c6dd729a1d9140a2b18feb8c 100644 --- a/drivers/ras/debugfs.c +++ b/drivers/ras/debugfs.c @@ -46,7 +46,7 @@ int __init ras_add_daemon_trace(void) fentry = debugfs_create_file("daemon_active", S_IRUSR, ras_debugfs_dir, NULL, &trace_fops); - if (!fentry) + if (IS_ERR(fentry)) return -ENODEV; return 0; diff --git a/drivers/regulator/88pg86x.c b/drivers/regulator/88pg86x.c index 74275b681f460b7cc797dc1c85422bace914e9ca..e6598e74ec94e4a7b25edbed233ccc2090f7bed3 100644 --- a/drivers/regulator/88pg86x.c +++ b/drivers/regulator/88pg86x.c @@ -104,7 +104,7 @@ static struct i2c_driver pg86x_regulator_driver = { .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = of_match_ptr(pg86x_dt_ids), }, - .probe_new = pg86x_i2c_probe, + .probe = pg86x_i2c_probe, .id_table = pg86x_i2c_id, }; diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index e5f3613c15fa5b06a9903583c948962db3a9afda..823f8e6e480129458be90ebc6f0272d5323e34d3 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -556,6 +556,17 @@ config REGULATOR_MAX597X The MAX5970/5978 is a smart switch with no output regulation, but fault protection and voltage and current monitoring capabilities. +config REGULATOR_MAX77541 + tristate "Analog Devices MAX77541/77540 Regulator" + depends on MFD_MAX77541 + help + This driver controls a Analog Devices MAX77541/77540 regulators + via I2C bus. Both MAX77540 and MAX77541 are dual-phase + high-efficiency buck converter. Say Y here to + enable the regulator driver. + Say M here if you want to include support for the regulator as a + module. + config REGULATOR_MAX77620 tristate "Maxim 77620/MAX20024 voltage regulator" depends on MFD_MAX77620 || COMPILE_TEST @@ -1033,6 +1044,14 @@ config REGULATOR_QCOM_USB_VBUS Say M here if you want to include support for enabling the VBUS output as a module. The module will be named "qcom_usb_vbus_regulator". +config REGULATOR_RAA215300 + tristate "Renesas RAA215300 driver" + select REGMAP_I2C + depends on COMMON_CLK + depends on I2C + help + Support for the Renesas RAA215300 PMIC. + config REGULATOR_RASPBERRYPI_TOUCHSCREEN_ATTINY tristate "Raspberry Pi 7-inch touchscreen panel ATTINY regulator" depends on BACKLIGHT_CLASS_DEVICE @@ -1056,7 +1075,7 @@ config REGULATOR_RC5T583 config REGULATOR_RK808 tristate "Rockchip RK805/RK808/RK809/RK817/RK818 Power regulators" - depends on MFD_RK808 + depends on MFD_RK8XX help Select this option to enable the power regulator of ROCKCHIP PMIC RK805,RK809&RK817,RK808 and RK818. @@ -1397,6 +1416,17 @@ config REGULATOR_TPS6286X high-frequency synchronous step-down converters with an I2C interface. +config REGULATOR_TPS6287X + tristate "TI TPS6287x Power Regulator" + depends on I2C && OF + select REGMAP_I2C + help + This driver supports TPS6287x voltage regulator chips. These are + pin-to-pin high-frequency synchronous step-down dc-dc converters + with an I2C interface. + + If built as a module it will be called tps6287x-regulator. + config REGULATOR_TPS65023 tristate "TI TPS65023 Power regulators" depends on I2C @@ -1463,6 +1493,19 @@ config REGULATOR_TPS65219 voltage regulators. It supports software based voltage control for different voltage domains. +config REGULATOR_TPS6594 + tristate "TI TPS6594 Power regulators" + depends on MFD_TPS6594 && OF + default MFD_TPS6594 + help + This driver supports TPS6594 voltage regulator chips. + TPS6594 series of PMICs have 5 BUCKs and 4 LDOs + voltage regulators. + BUCKs 1,2,3,4 can be used in single phase or multiphase mode. + Part number defines which single or multiphase mode is i used. + It supports software based voltage control + for different voltage domains. + config REGULATOR_TPS6524X tristate "TI TPS6524X Power regulators" depends on SPI diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index 58dfe0147cd431cd824f27624a6ac683cfb2aed2..15e0d614ff66638ba0a7b677f2c3a775ce94503f 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -68,6 +68,7 @@ obj-$(CONFIG_REGULATOR_LTC3676) += ltc3676.o obj-$(CONFIG_REGULATOR_MAX14577) += max14577-regulator.o obj-$(CONFIG_REGULATOR_MAX1586) += max1586.o obj-$(CONFIG_REGULATOR_MAX597X) += max597x-regulator.o +obj-$(CONFIG_REGULATOR_MAX77541) += max77541-regulator.o obj-$(CONFIG_REGULATOR_MAX77620) += max77620-regulator.o obj-$(CONFIG_REGULATOR_MAX77650) += max77650-regulator.o obj-$(CONFIG_REGULATOR_MAX8649) += max8649.o @@ -124,6 +125,7 @@ obj-$(CONFIG_REGULATOR_TPS51632) += tps51632-regulator.o obj-$(CONFIG_REGULATOR_PBIAS) += pbias-regulator.o obj-$(CONFIG_REGULATOR_PCAP) += pcap-regulator.o obj-$(CONFIG_REGULATOR_PCF50633) += pcf50633-regulator.o +obj-$(CONFIG_REGULATOR_RAA215300) += raa215300.o obj-$(CONFIG_REGULATOR_RASPBERRYPI_TOUCHSCREEN_ATTINY) += rpi-panel-attiny-regulator.o obj-$(CONFIG_REGULATOR_RC5T583) += rc5t583-regulator.o obj-$(CONFIG_REGULATOR_RK808) += rk808-regulator.o @@ -163,6 +165,7 @@ obj-$(CONFIG_REGULATOR_TI_ABB) += ti-abb-regulator.o obj-$(CONFIG_REGULATOR_TPS6105X) += tps6105x-regulator.o obj-$(CONFIG_REGULATOR_TPS62360) += tps62360-regulator.o obj-$(CONFIG_REGULATOR_TPS6286X) += tps6286x-regulator.o +obj-$(CONFIG_REGULATOR_TPS6287X) += tps6287x-regulator.o obj-$(CONFIG_REGULATOR_TPS65023) += tps65023-regulator.o obj-$(CONFIG_REGULATOR_TPS6507X) += tps6507x-regulator.o obj-$(CONFIG_REGULATOR_TPS65086) += tps65086-regulator.o @@ -174,6 +177,7 @@ obj-$(CONFIG_REGULATOR_TPS6524X) += tps6524x-regulator.o obj-$(CONFIG_REGULATOR_TPS6586X) += tps6586x-regulator.o obj-$(CONFIG_REGULATOR_TPS65910) += tps65910-regulator.o obj-$(CONFIG_REGULATOR_TPS65912) += tps65912-regulator.o +obj-$(CONFIG_REGULATOR_TPS6594) += tps6594-regulator.o obj-$(CONFIG_REGULATOR_TPS65132) += tps65132-regulator.o obj-$(CONFIG_REGULATOR_TPS68470) += tps68470-regulator.o obj-$(CONFIG_REGULATOR_TWL4030) += twl-regulator.o twl6030-regulator.o diff --git a/drivers/regulator/act8865-regulator.c b/drivers/regulator/act8865-regulator.c index 5c409ff4aa991bb65b494f293297b92f6ca4f2b3..a504b01dd99c8ffe1735bcf8087c54e85cfd7d03 100644 --- a/drivers/regulator/act8865-regulator.c +++ b/drivers/regulator/act8865-regulator.c @@ -791,7 +791,7 @@ static struct i2c_driver act8865_pmic_driver = { .name = "act8865", .probe_type = PROBE_PREFER_ASYNCHRONOUS, }, - .probe_new = act8865_pmic_probe, + .probe = act8865_pmic_probe, .id_table = act8865_ids, }; diff --git a/drivers/regulator/ad5398.c b/drivers/regulator/ad5398.c index c228cf6956d10aaffd0ded4cddaa659ffa347b83..40f7dba42b5ad7c95a3e2643b3ad6e076cf2cbb4 100644 --- a/drivers/regulator/ad5398.c +++ b/drivers/regulator/ad5398.c @@ -254,7 +254,7 @@ static int ad5398_probe(struct i2c_client *client) } static struct i2c_driver ad5398_driver = { - .probe_new = ad5398_probe, + .probe = ad5398_probe, .driver = { .name = "ad5398", .probe_type = PROBE_PREFER_ASYNCHRONOUS, diff --git a/drivers/regulator/axp20x-regulator.c b/drivers/regulator/axp20x-regulator.c index 943172b197226248c9a687038b7874e07729a287..810f90f3e2a1b3a43e799ed225a491a9948be7e7 100644 --- a/drivers/regulator/axp20x-regulator.c +++ b/drivers/regulator/axp20x-regulator.c @@ -134,6 +134,11 @@ #define AXP22X_PWR_OUT_DLDO4_MASK BIT_MASK(6) #define AXP22X_PWR_OUT_ALDO3_MASK BIT_MASK(7) +#define AXP313A_DCDC1_NUM_VOLTAGES 107 +#define AXP313A_DCDC23_NUM_VOLTAGES 88 +#define AXP313A_DCDC_V_OUT_MASK GENMASK(6, 0) +#define AXP313A_LDO_V_OUT_MASK GENMASK(4, 0) + #define AXP803_PWR_OUT_DCDC1_MASK BIT_MASK(0) #define AXP803_PWR_OUT_DCDC2_MASK BIT_MASK(1) #define AXP803_PWR_OUT_DCDC3_MASK BIT_MASK(2) @@ -270,6 +275,74 @@ #define AXP813_PWR_OUT_DCDC7_MASK BIT_MASK(6) +#define AXP15060_DCDC1_V_CTRL_MASK GENMASK(4, 0) +#define AXP15060_DCDC2_V_CTRL_MASK GENMASK(6, 0) +#define AXP15060_DCDC3_V_CTRL_MASK GENMASK(6, 0) +#define AXP15060_DCDC4_V_CTRL_MASK GENMASK(6, 0) +#define AXP15060_DCDC5_V_CTRL_MASK GENMASK(6, 0) +#define AXP15060_DCDC6_V_CTRL_MASK GENMASK(4, 0) +#define AXP15060_ALDO1_V_CTRL_MASK GENMASK(4, 0) +#define AXP15060_ALDO2_V_CTRL_MASK GENMASK(4, 0) +#define AXP15060_ALDO3_V_CTRL_MASK GENMASK(4, 0) +#define AXP15060_ALDO4_V_CTRL_MASK GENMASK(4, 0) +#define AXP15060_ALDO5_V_CTRL_MASK GENMASK(4, 0) +#define AXP15060_BLDO1_V_CTRL_MASK GENMASK(4, 0) +#define AXP15060_BLDO2_V_CTRL_MASK GENMASK(4, 0) +#define AXP15060_BLDO3_V_CTRL_MASK GENMASK(4, 0) +#define AXP15060_BLDO4_V_CTRL_MASK GENMASK(4, 0) +#define AXP15060_BLDO5_V_CTRL_MASK GENMASK(4, 0) +#define AXP15060_CLDO1_V_CTRL_MASK GENMASK(4, 0) +#define AXP15060_CLDO2_V_CTRL_MASK GENMASK(4, 0) +#define AXP15060_CLDO3_V_CTRL_MASK GENMASK(4, 0) +#define AXP15060_CLDO4_V_CTRL_MASK GENMASK(5, 0) +#define AXP15060_CPUSLDO_V_CTRL_MASK GENMASK(3, 0) + +#define AXP15060_PWR_OUT_DCDC1_MASK BIT_MASK(0) +#define AXP15060_PWR_OUT_DCDC2_MASK BIT_MASK(1) +#define AXP15060_PWR_OUT_DCDC3_MASK BIT_MASK(2) +#define AXP15060_PWR_OUT_DCDC4_MASK BIT_MASK(3) +#define AXP15060_PWR_OUT_DCDC5_MASK BIT_MASK(4) +#define AXP15060_PWR_OUT_DCDC6_MASK BIT_MASK(5) +#define AXP15060_PWR_OUT_ALDO1_MASK BIT_MASK(0) +#define AXP15060_PWR_OUT_ALDO2_MASK BIT_MASK(1) +#define AXP15060_PWR_OUT_ALDO3_MASK BIT_MASK(2) +#define AXP15060_PWR_OUT_ALDO4_MASK BIT_MASK(3) +#define AXP15060_PWR_OUT_ALDO5_MASK BIT_MASK(4) +#define AXP15060_PWR_OUT_BLDO1_MASK BIT_MASK(5) +#define AXP15060_PWR_OUT_BLDO2_MASK BIT_MASK(6) +#define AXP15060_PWR_OUT_BLDO3_MASK BIT_MASK(7) +#define AXP15060_PWR_OUT_BLDO4_MASK BIT_MASK(0) +#define AXP15060_PWR_OUT_BLDO5_MASK BIT_MASK(1) +#define AXP15060_PWR_OUT_CLDO1_MASK BIT_MASK(2) +#define AXP15060_PWR_OUT_CLDO2_MASK BIT_MASK(3) +#define AXP15060_PWR_OUT_CLDO3_MASK BIT_MASK(4) +#define AXP15060_PWR_OUT_CLDO4_MASK BIT_MASK(5) +#define AXP15060_PWR_OUT_CPUSLDO_MASK BIT_MASK(6) +#define AXP15060_PWR_OUT_SW_MASK BIT_MASK(7) + +#define AXP15060_DCDC23_POLYPHASE_DUAL_MASK BIT_MASK(6) +#define AXP15060_DCDC46_POLYPHASE_DUAL_MASK BIT_MASK(7) + +#define AXP15060_DCDC234_500mV_START 0x00 +#define AXP15060_DCDC234_500mV_STEPS 70 +#define AXP15060_DCDC234_500mV_END \ + (AXP15060_DCDC234_500mV_START + AXP15060_DCDC234_500mV_STEPS) +#define AXP15060_DCDC234_1220mV_START 0x47 +#define AXP15060_DCDC234_1220mV_STEPS 16 +#define AXP15060_DCDC234_1220mV_END \ + (AXP15060_DCDC234_1220mV_START + AXP15060_DCDC234_1220mV_STEPS) +#define AXP15060_DCDC234_NUM_VOLTAGES 88 + +#define AXP15060_DCDC5_800mV_START 0x00 +#define AXP15060_DCDC5_800mV_STEPS 32 +#define AXP15060_DCDC5_800mV_END \ + (AXP15060_DCDC5_800mV_START + AXP15060_DCDC5_800mV_STEPS) +#define AXP15060_DCDC5_1140mV_START 0x21 +#define AXP15060_DCDC5_1140mV_STEPS 35 +#define AXP15060_DCDC5_1140mV_END \ + (AXP15060_DCDC5_1140mV_START + AXP15060_DCDC5_1140mV_STEPS) +#define AXP15060_DCDC5_NUM_VOLTAGES 69 + #define AXP_DESC_IO(_family, _id, _match, _supply, _min, _max, _step, _vreg, \ _vmask, _ereg, _emask, _enable_val, _disable_val) \ [_family##_##_id] = { \ @@ -638,6 +711,48 @@ static const struct regulator_desc axp22x_drivevbus_regulator = { .ops = &axp20x_ops_sw, }; +static const struct linear_range axp313a_dcdc1_ranges[] = { + REGULATOR_LINEAR_RANGE(500000, 0, 70, 10000), + REGULATOR_LINEAR_RANGE(1220000, 71, 87, 20000), + REGULATOR_LINEAR_RANGE(1600000, 88, 106, 100000), +}; + +static const struct linear_range axp313a_dcdc2_ranges[] = { + REGULATOR_LINEAR_RANGE(500000, 0, 70, 10000), + REGULATOR_LINEAR_RANGE(1220000, 71, 87, 20000), +}; + +/* + * This is deviating from the datasheet. The values here are taken from the + * BSP driver and have been confirmed by measurements. + */ +static const struct linear_range axp313a_dcdc3_ranges[] = { + REGULATOR_LINEAR_RANGE(500000, 0, 70, 10000), + REGULATOR_LINEAR_RANGE(1220000, 71, 102, 20000), +}; + +static const struct regulator_desc axp313a_regulators[] = { + AXP_DESC_RANGES(AXP313A, DCDC1, "dcdc1", "vin1", + axp313a_dcdc1_ranges, AXP313A_DCDC1_NUM_VOLTAGES, + AXP313A_DCDC1_CONRTOL, AXP313A_DCDC_V_OUT_MASK, + AXP313A_OUTPUT_CONTROL, BIT(0)), + AXP_DESC_RANGES(AXP313A, DCDC2, "dcdc2", "vin2", + axp313a_dcdc2_ranges, AXP313A_DCDC23_NUM_VOLTAGES, + AXP313A_DCDC2_CONRTOL, AXP313A_DCDC_V_OUT_MASK, + AXP313A_OUTPUT_CONTROL, BIT(1)), + AXP_DESC_RANGES(AXP313A, DCDC3, "dcdc3", "vin3", + axp313a_dcdc3_ranges, AXP313A_DCDC23_NUM_VOLTAGES, + AXP313A_DCDC3_CONRTOL, AXP313A_DCDC_V_OUT_MASK, + AXP313A_OUTPUT_CONTROL, BIT(2)), + AXP_DESC(AXP313A, ALDO1, "aldo1", "vin1", 500, 3500, 100, + AXP313A_ALDO1_CONRTOL, AXP313A_LDO_V_OUT_MASK, + AXP313A_OUTPUT_CONTROL, BIT(3)), + AXP_DESC(AXP313A, DLDO1, "dldo1", "vin1", 500, 3500, 100, + AXP313A_DLDO1_CONRTOL, AXP313A_LDO_V_OUT_MASK, + AXP313A_OUTPUT_CONTROL, BIT(4)), + AXP_DESC_FIXED(AXP313A, RTC_LDO, "rtc-ldo", "vin1", 1800), +}; + /* DCDC ranges shared with AXP813 */ static const struct linear_range axp803_dcdc234_ranges[] = { REGULATOR_LINEAR_RANGE(500000, @@ -1001,6 +1116,104 @@ static const struct regulator_desc axp813_regulators[] = { AXP22X_PWR_OUT_CTRL2, AXP22X_PWR_OUT_DC1SW_MASK), }; +static const struct linear_range axp15060_dcdc234_ranges[] = { + REGULATOR_LINEAR_RANGE(500000, + AXP15060_DCDC234_500mV_START, + AXP15060_DCDC234_500mV_END, + 10000), + REGULATOR_LINEAR_RANGE(1220000, + AXP15060_DCDC234_1220mV_START, + AXP15060_DCDC234_1220mV_END, + 20000), +}; + +static const struct linear_range axp15060_dcdc5_ranges[] = { + REGULATOR_LINEAR_RANGE(800000, + AXP15060_DCDC5_800mV_START, + AXP15060_DCDC5_800mV_END, + 10000), + REGULATOR_LINEAR_RANGE(1140000, + AXP15060_DCDC5_1140mV_START, + AXP15060_DCDC5_1140mV_END, + 20000), +}; + +static const struct regulator_desc axp15060_regulators[] = { + AXP_DESC(AXP15060, DCDC1, "dcdc1", "vin1", 1500, 3400, 100, + AXP15060_DCDC1_V_CTRL, AXP15060_DCDC1_V_CTRL_MASK, + AXP15060_PWR_OUT_CTRL1, AXP15060_PWR_OUT_DCDC1_MASK), + AXP_DESC_RANGES(AXP15060, DCDC2, "dcdc2", "vin2", + axp15060_dcdc234_ranges, AXP15060_DCDC234_NUM_VOLTAGES, + AXP15060_DCDC2_V_CTRL, AXP15060_DCDC2_V_CTRL_MASK, + AXP15060_PWR_OUT_CTRL1, AXP15060_PWR_OUT_DCDC2_MASK), + AXP_DESC_RANGES(AXP15060, DCDC3, "dcdc3", "vin3", + axp15060_dcdc234_ranges, AXP15060_DCDC234_NUM_VOLTAGES, + AXP15060_DCDC3_V_CTRL, AXP15060_DCDC3_V_CTRL_MASK, + AXP15060_PWR_OUT_CTRL1, AXP15060_PWR_OUT_DCDC3_MASK), + AXP_DESC_RANGES(AXP15060, DCDC4, "dcdc4", "vin4", + axp15060_dcdc234_ranges, AXP15060_DCDC234_NUM_VOLTAGES, + AXP15060_DCDC4_V_CTRL, AXP15060_DCDC4_V_CTRL_MASK, + AXP15060_PWR_OUT_CTRL1, AXP15060_PWR_OUT_DCDC4_MASK), + AXP_DESC_RANGES(AXP15060, DCDC5, "dcdc5", "vin5", + axp15060_dcdc5_ranges, AXP15060_DCDC5_NUM_VOLTAGES, + AXP15060_DCDC5_V_CTRL, AXP15060_DCDC5_V_CTRL_MASK, + AXP15060_PWR_OUT_CTRL1, AXP15060_PWR_OUT_DCDC5_MASK), + AXP_DESC(AXP15060, DCDC6, "dcdc6", "vin6", 500, 3400, 100, + AXP15060_DCDC6_V_CTRL, AXP15060_DCDC6_V_CTRL_MASK, + AXP15060_PWR_OUT_CTRL1, AXP15060_PWR_OUT_DCDC6_MASK), + AXP_DESC(AXP15060, ALDO1, "aldo1", "aldoin", 700, 3300, 100, + AXP15060_ALDO1_V_CTRL, AXP15060_ALDO1_V_CTRL_MASK, + AXP15060_PWR_OUT_CTRL2, AXP15060_PWR_OUT_ALDO1_MASK), + AXP_DESC(AXP15060, ALDO2, "aldo2", "aldoin", 700, 3300, 100, + AXP15060_ALDO2_V_CTRL, AXP15060_ALDO2_V_CTRL_MASK, + AXP15060_PWR_OUT_CTRL2, AXP15060_PWR_OUT_ALDO2_MASK), + AXP_DESC(AXP15060, ALDO3, "aldo3", "aldoin", 700, 3300, 100, + AXP15060_ALDO3_V_CTRL, AXP15060_ALDO3_V_CTRL_MASK, + AXP15060_PWR_OUT_CTRL2, AXP15060_PWR_OUT_ALDO3_MASK), + AXP_DESC(AXP15060, ALDO4, "aldo4", "aldoin", 700, 3300, 100, + AXP15060_ALDO4_V_CTRL, AXP15060_ALDO4_V_CTRL_MASK, + AXP15060_PWR_OUT_CTRL2, AXP15060_PWR_OUT_ALDO4_MASK), + AXP_DESC(AXP15060, ALDO5, "aldo5", "aldoin", 700, 3300, 100, + AXP15060_ALDO5_V_CTRL, AXP15060_ALDO5_V_CTRL_MASK, + AXP15060_PWR_OUT_CTRL2, AXP15060_PWR_OUT_ALDO5_MASK), + AXP_DESC(AXP15060, BLDO1, "bldo1", "bldoin", 700, 3300, 100, + AXP15060_BLDO1_V_CTRL, AXP15060_BLDO1_V_CTRL_MASK, + AXP15060_PWR_OUT_CTRL2, AXP15060_PWR_OUT_BLDO1_MASK), + AXP_DESC(AXP15060, BLDO2, "bldo2", "bldoin", 700, 3300, 100, + AXP15060_BLDO2_V_CTRL, AXP15060_BLDO2_V_CTRL_MASK, + AXP15060_PWR_OUT_CTRL2, AXP15060_PWR_OUT_BLDO2_MASK), + AXP_DESC(AXP15060, BLDO3, "bldo3", "bldoin", 700, 3300, 100, + AXP15060_BLDO3_V_CTRL, AXP15060_BLDO3_V_CTRL_MASK, + AXP15060_PWR_OUT_CTRL2, AXP15060_PWR_OUT_BLDO3_MASK), + AXP_DESC(AXP15060, BLDO4, "bldo4", "bldoin", 700, 3300, 100, + AXP15060_BLDO4_V_CTRL, AXP15060_BLDO4_V_CTRL_MASK, + AXP15060_PWR_OUT_CTRL3, AXP15060_PWR_OUT_BLDO4_MASK), + AXP_DESC(AXP15060, BLDO5, "bldo5", "bldoin", 700, 3300, 100, + AXP15060_BLDO5_V_CTRL, AXP15060_BLDO5_V_CTRL_MASK, + AXP15060_PWR_OUT_CTRL3, AXP15060_PWR_OUT_BLDO5_MASK), + AXP_DESC(AXP15060, CLDO1, "cldo1", "cldoin", 700, 3300, 100, + AXP15060_CLDO1_V_CTRL, AXP15060_CLDO1_V_CTRL_MASK, + AXP15060_PWR_OUT_CTRL3, AXP15060_PWR_OUT_CLDO1_MASK), + AXP_DESC(AXP15060, CLDO2, "cldo2", "cldoin", 700, 3300, 100, + AXP15060_CLDO2_V_CTRL, AXP15060_CLDO2_V_CTRL_MASK, + AXP15060_PWR_OUT_CTRL3, AXP15060_PWR_OUT_CLDO2_MASK), + AXP_DESC(AXP15060, CLDO3, "cldo3", "cldoin", 700, 3300, 100, + AXP15060_CLDO3_V_CTRL, AXP15060_CLDO3_V_CTRL_MASK, + AXP15060_PWR_OUT_CTRL3, AXP15060_PWR_OUT_CLDO3_MASK), + AXP_DESC(AXP15060, CLDO4, "cldo4", "cldoin", 700, 4200, 100, + AXP15060_CLDO4_V_CTRL, AXP15060_CLDO4_V_CTRL_MASK, + AXP15060_PWR_OUT_CTRL3, AXP15060_PWR_OUT_CLDO4_MASK), + /* Supply comes from DCDC5 */ + AXP_DESC(AXP15060, CPUSLDO, "cpusldo", NULL, 700, 1400, 50, + AXP15060_CPUSLDO_V_CTRL, AXP15060_CPUSLDO_V_CTRL_MASK, + AXP15060_PWR_OUT_CTRL3, AXP15060_PWR_OUT_CPUSLDO_MASK), + /* Supply comes from DCDC1 */ + AXP_DESC_SW(AXP15060, SW, "sw", NULL, + AXP15060_PWR_OUT_CTRL3, AXP15060_PWR_OUT_SW_MASK), + /* Supply comes from ALDO1 */ + AXP_DESC_FIXED(AXP15060, RTC_LDO, "rtc-ldo", NULL, 1800), +}; + static int axp20x_set_dcdc_freq(struct platform_device *pdev, u32 dcdcfreq) { struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent); @@ -1040,6 +1253,16 @@ static int axp20x_set_dcdc_freq(struct platform_device *pdev, u32 dcdcfreq) def = 3000; step = 150; break; + case AXP313A_ID: + case AXP15060_ID: + /* The DCDC PWM frequency seems to be fixed to 3 MHz. */ + if (dcdcfreq != 0) { + dev_err(&pdev->dev, + "DCDC frequency on this PMIC is fixed to 3 MHz.\n"); + return -EINVAL; + } + + return 0; default: dev_err(&pdev->dev, "Setting DCDC frequency for unsupported AXP variant\n"); @@ -1145,6 +1368,15 @@ static int axp20x_set_dcdc_workmode(struct regulator_dev *rdev, int id, u32 work workmode <<= id - AXP813_DCDC1; break; + case AXP15060_ID: + reg = AXP15060_DCDC_MODE_CTRL2; + if (id < AXP15060_DCDC1 || id > AXP15060_DCDC6) + return -EINVAL; + + mask = AXP22X_WORKMODE_DCDCX_MASK(id - AXP15060_DCDC1); + workmode <<= id - AXP15060_DCDC1; + break; + default: /* should not happen */ WARN_ON(1); @@ -1164,7 +1396,7 @@ static bool axp20x_is_polyphase_slave(struct axp20x_dev *axp20x, int id) /* * Currently in our supported AXP variants, only AXP803, AXP806, - * and AXP813 have polyphase regulators. + * AXP813 and AXP15060 have polyphase regulators. */ switch (axp20x->variant) { case AXP803_ID: @@ -1196,6 +1428,17 @@ static bool axp20x_is_polyphase_slave(struct axp20x_dev *axp20x, int id) } break; + case AXP15060_ID: + regmap_read(axp20x->regmap, AXP15060_DCDC_MODE_CTRL1, ®); + + switch (id) { + case AXP15060_DCDC3: + return !!(reg & AXP15060_DCDC23_POLYPHASE_DUAL_MASK); + case AXP15060_DCDC6: + return !!(reg & AXP15060_DCDC46_POLYPHASE_DUAL_MASK); + } + break; + default: return false; } @@ -1217,6 +1460,7 @@ static int axp20x_regulator_probe(struct platform_device *pdev) u32 workmode; const char *dcdc1_name = axp22x_regulators[AXP22X_DCDC1].name; const char *dcdc5_name = axp22x_regulators[AXP22X_DCDC5].name; + const char *aldo1_name = axp15060_regulators[AXP15060_ALDO1].name; bool drivevbus = false; switch (axp20x->variant) { @@ -1232,6 +1476,10 @@ static int axp20x_regulator_probe(struct platform_device *pdev) drivevbus = of_property_read_bool(pdev->dev.parent->of_node, "x-powers,drive-vbus-en"); break; + case AXP313A_ID: + regulators = axp313a_regulators; + nregulators = AXP313A_REG_ID_MAX; + break; case AXP803_ID: regulators = axp803_regulators; nregulators = AXP803_REG_ID_MAX; @@ -1252,6 +1500,10 @@ static int axp20x_regulator_probe(struct platform_device *pdev) drivevbus = of_property_read_bool(pdev->dev.parent->of_node, "x-powers,drive-vbus-en"); break; + case AXP15060_ID: + regulators = axp15060_regulators; + nregulators = AXP15060_REG_ID_MAX; + break; default: dev_err(&pdev->dev, "Unsupported AXP variant: %ld\n", axp20x->variant); @@ -1278,8 +1530,9 @@ static int axp20x_regulator_probe(struct platform_device *pdev) continue; /* - * Regulators DC1SW and DC5LDO are connected internally, - * so we have to handle their supply names separately. + * Regulators DC1SW, DC5LDO and RTCLDO on AXP15060 are + * connected internally, so we have to handle their supply + * names separately. * * We always register the regulators in proper sequence, * so the supply names are correctly read. See the last @@ -1288,7 +1541,8 @@ static int axp20x_regulator_probe(struct platform_device *pdev) */ if ((regulators == axp22x_regulators && i == AXP22X_DC1SW) || (regulators == axp803_regulators && i == AXP803_DC1SW) || - (regulators == axp809_regulators && i == AXP809_DC1SW)) { + (regulators == axp809_regulators && i == AXP809_DC1SW) || + (regulators == axp15060_regulators && i == AXP15060_SW)) { new_desc = devm_kzalloc(&pdev->dev, sizeof(*desc), GFP_KERNEL); if (!new_desc) @@ -1300,7 +1554,8 @@ static int axp20x_regulator_probe(struct platform_device *pdev) } if ((regulators == axp22x_regulators && i == AXP22X_DC5LDO) || - (regulators == axp809_regulators && i == AXP809_DC5LDO)) { + (regulators == axp809_regulators && i == AXP809_DC5LDO) || + (regulators == axp15060_regulators && i == AXP15060_CPUSLDO)) { new_desc = devm_kzalloc(&pdev->dev, sizeof(*desc), GFP_KERNEL); if (!new_desc) @@ -1311,6 +1566,18 @@ static int axp20x_regulator_probe(struct platform_device *pdev) desc = new_desc; } + + if (regulators == axp15060_regulators && i == AXP15060_RTC_LDO) { + new_desc = devm_kzalloc(&pdev->dev, sizeof(*desc), + GFP_KERNEL); + if (!new_desc) + return -ENOMEM; + + *new_desc = regulators[i]; + new_desc->supply_name = aldo1_name; + desc = new_desc; + } + rdev = devm_regulator_register(&pdev->dev, desc, &config); if (IS_ERR(rdev)) { dev_err(&pdev->dev, "Failed to register %s\n", @@ -1329,19 +1596,26 @@ static int axp20x_regulator_probe(struct platform_device *pdev) } /* - * Save AXP22X DCDC1 / DCDC5 regulator names for later. + * Save AXP22X DCDC1 / DCDC5 / AXP15060 ALDO1 regulator names for later. */ if ((regulators == axp22x_regulators && i == AXP22X_DCDC1) || - (regulators == axp809_regulators && i == AXP809_DCDC1)) + (regulators == axp809_regulators && i == AXP809_DCDC1) || + (regulators == axp15060_regulators && i == AXP15060_DCDC1)) of_property_read_string(rdev->dev.of_node, "regulator-name", &dcdc1_name); if ((regulators == axp22x_regulators && i == AXP22X_DCDC5) || - (regulators == axp809_regulators && i == AXP809_DCDC5)) + (regulators == axp809_regulators && i == AXP809_DCDC5) || + (regulators == axp15060_regulators && i == AXP15060_DCDC5)) of_property_read_string(rdev->dev.of_node, "regulator-name", &dcdc5_name); + + if (regulators == axp15060_regulators && i == AXP15060_ALDO1) + of_property_read_string(rdev->dev.of_node, + "regulator-name", + &aldo1_name); } if (drivevbus) { diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 698ab7f5004bf6b74e2e57ac224f6138139f4666..d8e1caaf207e108f124988b7a9f1ee3780a12e8c 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -1911,19 +1911,17 @@ static struct regulator *create_regulator(struct regulator_dev *rdev, if (err != -EEXIST) regulator->debugfs = debugfs_create_dir(supply_name, rdev->debugfs); - if (!regulator->debugfs) { + if (IS_ERR(regulator->debugfs)) rdev_dbg(rdev, "Failed to create debugfs directory\n"); - } else { - 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); - } + + 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 @@ -5256,10 +5254,8 @@ static void rdev_init_debugfs(struct regulator_dev *rdev) } rdev->debugfs = debugfs_create_dir(rname, debugfs_root); - if (IS_ERR(rdev->debugfs)) { - rdev_warn(rdev, "Failed to create debugfs directory\n"); - return; - } + if (IS_ERR(rdev->debugfs)) + rdev_dbg(rdev, "Failed to create debugfs directory\n"); debugfs_create_u32("use_count", 0444, rdev->debugfs, &rdev->use_count); @@ -6179,7 +6175,7 @@ static int __init regulator_init(void) debugfs_root = debugfs_create_dir("regulator", NULL); if (IS_ERR(debugfs_root)) - pr_warn("regulator: Failed to create debugfs directory\n"); + pr_debug("regulator: Failed to create debugfs directory\n"); #ifdef CONFIG_DEBUG_FS debugfs_create_file("supply_map", 0444, debugfs_root, NULL, diff --git a/drivers/regulator/da9121-regulator.c b/drivers/regulator/da9121-regulator.c index 6ce0fdc18b9c1516b8aee94f3eab2d53c171f0c5..122124944749e345f0edf665e5cb57bed6fa9069 100644 --- a/drivers/regulator/da9121-regulator.c +++ b/drivers/regulator/da9121-regulator.c @@ -1197,7 +1197,7 @@ static struct i2c_driver da9121_regulator_driver = { .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = of_match_ptr(da9121_dt_ids), }, - .probe_new = da9121_i2c_probe, + .probe = da9121_i2c_probe, .remove = da9121_i2c_remove, .id_table = da9121_i2c_id, }; diff --git a/drivers/regulator/da9210-regulator.c b/drivers/regulator/da9210-regulator.c index 4332a3b8a6723cda46dc2e7527b864abebfefcd1..252f74ab9bc01c8a056ae8dae3b1856ba22a3c5d 100644 --- a/drivers/regulator/da9210-regulator.c +++ b/drivers/regulator/da9210-regulator.c @@ -224,7 +224,7 @@ static struct i2c_driver da9210_regulator_driver = { .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = of_match_ptr(da9210_dt_ids), }, - .probe_new = da9210_i2c_probe, + .probe = da9210_i2c_probe, .id_table = da9210_i2c_id, }; diff --git a/drivers/regulator/da9211-regulator.c b/drivers/regulator/da9211-regulator.c index a2b4f6f1e34b826bd14df7d6a71401a02a692ff7..af383ff0fe5733a8f3d5d3c57204fdbacb06bd27 100644 --- a/drivers/regulator/da9211-regulator.c +++ b/drivers/regulator/da9211-regulator.c @@ -555,7 +555,7 @@ static struct i2c_driver da9211_regulator_driver = { .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = of_match_ptr(da9211_dt_ids), }, - .probe_new = da9211_i2c_probe, + .probe = da9211_i2c_probe, .id_table = da9211_i2c_id, }; diff --git a/drivers/regulator/fan53555.c b/drivers/regulator/fan53555.c index 130f3dbe98404aa61828841e0c5f3ee33c6be2df..289c06e09f47bdc7bb10146947c87008b64ec0db 100644 --- a/drivers/regulator/fan53555.c +++ b/drivers/regulator/fan53555.c @@ -775,7 +775,7 @@ static struct i2c_driver fan53555_regulator_driver = { .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = of_match_ptr(fan53555_dt_ids), }, - .probe_new = fan53555_regulator_probe, + .probe = fan53555_regulator_probe, .id_table = fan53555_id, }; diff --git a/drivers/regulator/fan53880.c b/drivers/regulator/fan53880.c index a3bebdee570ec6961f95504ecfda5d10071b0795..6cb5656845f9e8dad92f9dd784bdf78faa8fa247 100644 --- a/drivers/regulator/fan53880.c +++ b/drivers/regulator/fan53880.c @@ -175,7 +175,7 @@ static struct i2c_driver fan53880_regulator_driver = { .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = fan53880_dt_ids, }, - .probe_new = fan53880_i2c_probe, + .probe = fan53880_i2c_probe, .id_table = fan53880_i2c_id, }; module_i2c_driver(fan53880_regulator_driver); diff --git a/drivers/regulator/helpers.c b/drivers/regulator/helpers.c index ad2237a95572a7b21d1b11d324da1f5e9e86ad9d..e6c999ba3fa23ff36c02c9d67556f0b2ab69fcc0 100644 --- a/drivers/regulator/helpers.c +++ b/drivers/regulator/helpers.c @@ -902,8 +902,21 @@ bool regulator_is_equal(struct regulator *reg1, struct regulator *reg2) } EXPORT_SYMBOL_GPL(regulator_is_equal); -static int find_closest_bigger(unsigned int target, const unsigned int *table, - unsigned int num_sel, unsigned int *sel) +/** + * regulator_find_closest_bigger - helper to find offset in ramp delay table + * + * @target: targeted ramp_delay + * @table: table with supported ramp delays + * @num_sel: number of entries in the table + * @sel: Pointer to store table offset + * + * This is the internal helper used by regulator_set_ramp_delay_regmap to + * map ramp delay to register value. It should only be used directly if + * regulator_set_ramp_delay_regmap cannot handle a specific device setup + * (e.g. because the value is split over multiple registers). + */ +int regulator_find_closest_bigger(unsigned int target, const unsigned int *table, + unsigned int num_sel, unsigned int *sel) { unsigned int s, tmp, max, maxsel = 0; bool found = false; @@ -933,11 +946,13 @@ static int find_closest_bigger(unsigned int target, const unsigned int *table, return 0; } +EXPORT_SYMBOL_GPL(regulator_find_closest_bigger); /** * regulator_set_ramp_delay_regmap - set_ramp_delay() helper * * @rdev: regulator to operate on + * @ramp_delay: ramp-rate value given in units V/S (uV/uS) * * Regulators that use regmap for their register I/O can set the ramp_reg * and ramp_mask fields in their descriptor and then use this as their @@ -951,8 +966,8 @@ int regulator_set_ramp_delay_regmap(struct regulator_dev *rdev, int ramp_delay) if (WARN_ON(!rdev->desc->n_ramp_values || !rdev->desc->ramp_delay_table)) return -EINVAL; - ret = find_closest_bigger(ramp_delay, rdev->desc->ramp_delay_table, - rdev->desc->n_ramp_values, &sel); + ret = regulator_find_closest_bigger(ramp_delay, rdev->desc->ramp_delay_table, + rdev->desc->n_ramp_values, &sel); if (ret) { dev_warn(rdev_get_dev(rdev), diff --git a/drivers/regulator/isl6271a-regulator.c b/drivers/regulator/isl6271a-regulator.c index 3c37c4de1d82105aa8c1cb3607a8c506e9294235..69b4afe95e66bf2bc5725baad3d8e8f82667245e 100644 --- a/drivers/regulator/isl6271a-regulator.c +++ b/drivers/regulator/isl6271a-regulator.c @@ -149,7 +149,7 @@ static struct i2c_driver isl6271a_i2c_driver = { .name = "isl6271a", .probe_type = PROBE_PREFER_ASYNCHRONOUS, }, - .probe_new = isl6271a_probe, + .probe = isl6271a_probe, .id_table = isl6271a_id, }; diff --git a/drivers/regulator/isl9305.c b/drivers/regulator/isl9305.c index 90bc8d054304a3adb30f21865314d75d7b4d6578..0f7560093091a18a93330c903413e55e97c375dd 100644 --- a/drivers/regulator/isl9305.c +++ b/drivers/regulator/isl9305.c @@ -198,7 +198,7 @@ static struct i2c_driver isl9305_regulator_driver = { .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = of_match_ptr(isl9305_dt_ids), }, - .probe_new = isl9305_i2c_probe, + .probe = isl9305_i2c_probe, .id_table = isl9305_i2c_id, }; diff --git a/drivers/regulator/lp3971.c b/drivers/regulator/lp3971.c index e06f2a092b8935e49c701fe6f3b6d163d27bef37..e1b5c45f97f41b0b59ef08634a86e3b13b558961 100644 --- a/drivers/regulator/lp3971.c +++ b/drivers/regulator/lp3971.c @@ -449,7 +449,7 @@ static struct i2c_driver lp3971_i2c_driver = { .name = "LP3971", .probe_type = PROBE_PREFER_ASYNCHRONOUS, }, - .probe_new = lp3971_i2c_probe, + .probe = lp3971_i2c_probe, .id_table = lp3971_i2c_id, }; diff --git a/drivers/regulator/lp3972.c b/drivers/regulator/lp3972.c index edacca8e14af6b29a886dece71343d9dc8707eda..7bd6f05edd8d914f97d29ffa68f3674eb1560abe 100644 --- a/drivers/regulator/lp3972.c +++ b/drivers/regulator/lp3972.c @@ -547,7 +547,7 @@ static struct i2c_driver lp3972_i2c_driver = { .name = "lp3972", .probe_type = PROBE_PREFER_ASYNCHRONOUS, }, - .probe_new = lp3972_i2c_probe, + .probe = lp3972_i2c_probe, .id_table = lp3972_i2c_id, }; diff --git a/drivers/regulator/lp872x.c b/drivers/regulator/lp872x.c index a8b0969d4f31e84f74810813b41c1f96280ebd69..63aa227b18132b0a5670b51d425dd9dfa9dfed10 100644 --- a/drivers/regulator/lp872x.c +++ b/drivers/regulator/lp872x.c @@ -947,7 +947,7 @@ static struct i2c_driver lp872x_driver = { .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = of_match_ptr(lp872x_dt_ids), }, - .probe_new = lp872x_probe, + .probe = lp872x_probe, .id_table = lp872x_ids, }; diff --git a/drivers/regulator/lp8755.c b/drivers/regulator/lp8755.c index 37b51b94fb5a4bd9f67f8bfb65a0ea46edd912ec..4bc310f972edb431f3f06cfade72af61c3bdfc15 100644 --- a/drivers/regulator/lp8755.c +++ b/drivers/regulator/lp8755.c @@ -442,7 +442,7 @@ static struct i2c_driver lp8755_i2c_driver = { .name = LP8755_NAME, .probe_type = PROBE_PREFER_ASYNCHRONOUS, }, - .probe_new = lp8755_probe, + .probe = lp8755_probe, .remove = lp8755_remove, .id_table = lp8755_id, }; diff --git a/drivers/regulator/ltc3589.c b/drivers/regulator/ltc3589.c index 359b534d8c70f762e2e9170b2f2f6efb21351f0a..e9751c206d951246b485517fa32a77ded412a7fd 100644 --- a/drivers/regulator/ltc3589.c +++ b/drivers/regulator/ltc3589.c @@ -348,7 +348,7 @@ static const struct regmap_config ltc3589_regmap_config = { .num_reg_defaults = ARRAY_SIZE(ltc3589_reg_defaults), .use_single_read = true, .use_single_write = true, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, }; static irqreturn_t ltc3589_isr(int irq, void *dev_id) @@ -477,7 +477,7 @@ static struct i2c_driver ltc3589_driver = { .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = of_match_ptr(ltc3589_of_match), }, - .probe_new = ltc3589_probe, + .probe = ltc3589_probe, .id_table = ltc3589_i2c_id, }; module_i2c_driver(ltc3589_driver); diff --git a/drivers/regulator/ltc3676.c b/drivers/regulator/ltc3676.c index a28e6c3460f167e3f6a8c57b321bfd6c9caed110..73d511eb1c1dceff75217b9dbc702246a1e309c7 100644 --- a/drivers/regulator/ltc3676.c +++ b/drivers/regulator/ltc3676.c @@ -261,7 +261,7 @@ static const struct regmap_config ltc3676_regmap_config = { .max_register = LTC3676_CLIRQ, .use_single_read = true, .use_single_write = true, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, }; static irqreturn_t ltc3676_isr(int irq, void *dev_id) @@ -374,7 +374,7 @@ static struct i2c_driver ltc3676_driver = { .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = of_match_ptr(ltc3676_of_match), }, - .probe_new = ltc3676_regulator_probe, + .probe = ltc3676_regulator_probe, .id_table = ltc3676_i2c_id, }; module_i2c_driver(ltc3676_driver); diff --git a/drivers/regulator/max1586.c b/drivers/regulator/max1586.c index 5d8852b2c168c1112ed78eb4f6ad575928509353..90aa5b723c034b7aa05d96538fbbe639d28206fe 100644 --- a/drivers/regulator/max1586.c +++ b/drivers/regulator/max1586.c @@ -289,7 +289,7 @@ static const struct i2c_device_id max1586_id[] = { MODULE_DEVICE_TABLE(i2c, max1586_id); static struct i2c_driver max1586_pmic_driver = { - .probe_new = max1586_pmic_probe, + .probe = max1586_pmic_probe, .driver = { .name = "max1586", .probe_type = PROBE_PREFER_ASYNCHRONOUS, diff --git a/drivers/regulator/max20086-regulator.c b/drivers/regulator/max20086-regulator.c index ace1d582a191c88169c6ec0c90883c11c43d83bf..fad31f5f435e147dd87b5e37e4aaa9da68e25fe3 100644 --- a/drivers/regulator/max20086-regulator.c +++ b/drivers/regulator/max20086-regulator.c @@ -323,7 +323,7 @@ static struct i2c_driver max20086_regulator_driver = { .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = of_match_ptr(max20086_dt_ids), }, - .probe_new = max20086_i2c_probe, + .probe = max20086_i2c_probe, .id_table = max20086_i2c_id, }; diff --git a/drivers/regulator/max20411-regulator.c b/drivers/regulator/max20411-regulator.c index be8169b86a89301fb133186e7c3ff09527a21ecc..8c09dc71b16db5a92425b97e0e777de4da454f75 100644 --- a/drivers/regulator/max20411-regulator.c +++ b/drivers/regulator/max20411-regulator.c @@ -156,7 +156,7 @@ static struct i2c_driver max20411_i2c_driver = { .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = of_max20411_match_tbl, }, - .probe_new = max20411_probe, + .probe = max20411_probe, .id_table = max20411_id, }; module_i2c_driver(max20411_i2c_driver); diff --git a/drivers/regulator/max77541-regulator.c b/drivers/regulator/max77541-regulator.c new file mode 100644 index 0000000000000000000000000000000000000000..2976f9cb3e2653e0ce9c8dcaaf86d163e0b92c1a --- /dev/null +++ b/drivers/regulator/max77541-regulator.c @@ -0,0 +1,153 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2022 Analog Devices, Inc. + * ADI Regulator driver for the MAX77540 and MAX77541 + */ + +#include +#include +#include +#include +#include + +static const struct regulator_ops max77541_buck_ops = { + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .list_voltage = regulator_list_voltage_pickable_linear_range, + .get_voltage_sel = regulator_get_voltage_sel_pickable_regmap, + .set_voltage_sel = regulator_set_voltage_sel_pickable_regmap, +}; + +static const struct linear_range max77540_buck_ranges[] = { + /* Ranges when VOLT_SEL bits are 0x00 */ + REGULATOR_LINEAR_RANGE(500000, 0x00, 0x8B, 5000), + REGULATOR_LINEAR_RANGE(1200000, 0x8C, 0xFF, 0), + /* Ranges when VOLT_SEL bits are 0x40 */ + REGULATOR_LINEAR_RANGE(1200000, 0x00, 0x8B, 10000), + REGULATOR_LINEAR_RANGE(2400000, 0x8C, 0xFF, 0), + /* Ranges when VOLT_SEL bits are 0x80 */ + REGULATOR_LINEAR_RANGE(2000000, 0x00, 0x9F, 20000), + REGULATOR_LINEAR_RANGE(5200000, 0xA0, 0xFF, 0), +}; + +static const struct linear_range max77541_buck_ranges[] = { + /* Ranges when VOLT_SEL bits are 0x00 */ + REGULATOR_LINEAR_RANGE(300000, 0x00, 0xB3, 5000), + REGULATOR_LINEAR_RANGE(1200000, 0xB4, 0xFF, 0), + /* Ranges when VOLT_SEL bits are 0x40 */ + REGULATOR_LINEAR_RANGE(1200000, 0x00, 0x8B, 10000), + REGULATOR_LINEAR_RANGE(2400000, 0x8C, 0xFF, 0), + /* Ranges when VOLT_SEL bits are 0x80 */ + REGULATOR_LINEAR_RANGE(2000000, 0x00, 0x9F, 20000), + REGULATOR_LINEAR_RANGE(5200000, 0xA0, 0xFF, 0), +}; + +static const unsigned int max77541_buck_volt_range_sel[] = { + 0x00, 0x00, 0x40, 0x40, 0x80, 0x80, +}; + +enum max77541_regulators { + MAX77541_BUCK1 = 1, + MAX77541_BUCK2, +}; + +#define MAX77540_BUCK(_id, _ops) \ + { .id = MAX77541_BUCK ## _id, \ + .name = "buck"#_id, \ + .of_match = "buck"#_id, \ + .regulators_node = "regulators", \ + .enable_reg = MAX77541_REG_EN_CTRL, \ + .enable_mask = MAX77541_BIT_M ## _id ## _EN, \ + .ops = &(_ops), \ + .type = REGULATOR_VOLTAGE, \ + .linear_ranges = max77540_buck_ranges, \ + .n_linear_ranges = ARRAY_SIZE(max77540_buck_ranges), \ + .vsel_reg = MAX77541_REG_M ## _id ## _VOUT, \ + .vsel_mask = MAX77541_BITS_MX_VOUT, \ + .vsel_range_reg = MAX77541_REG_M ## _id ## _CFG1, \ + .vsel_range_mask = MAX77541_BITS_MX_CFG1_RNG, \ + .linear_range_selectors = max77541_buck_volt_range_sel, \ + .owner = THIS_MODULE, \ + } + +#define MAX77541_BUCK(_id, _ops) \ + { .id = MAX77541_BUCK ## _id, \ + .name = "buck"#_id, \ + .of_match = "buck"#_id, \ + .regulators_node = "regulators", \ + .enable_reg = MAX77541_REG_EN_CTRL, \ + .enable_mask = MAX77541_BIT_M ## _id ## _EN, \ + .ops = &(_ops), \ + .type = REGULATOR_VOLTAGE, \ + .linear_ranges = max77541_buck_ranges, \ + .n_linear_ranges = ARRAY_SIZE(max77541_buck_ranges), \ + .vsel_reg = MAX77541_REG_M ## _id ## _VOUT, \ + .vsel_mask = MAX77541_BITS_MX_VOUT, \ + .vsel_range_reg = MAX77541_REG_M ## _id ## _CFG1, \ + .vsel_range_mask = MAX77541_BITS_MX_CFG1_RNG, \ + .linear_range_selectors = max77541_buck_volt_range_sel, \ + .owner = THIS_MODULE, \ + } + +static const struct regulator_desc max77540_regulators_desc[] = { + MAX77540_BUCK(1, max77541_buck_ops), + MAX77540_BUCK(2, max77541_buck_ops), +}; + +static const struct regulator_desc max77541_regulators_desc[] = { + MAX77541_BUCK(1, max77541_buck_ops), + MAX77541_BUCK(2, max77541_buck_ops), +}; + +static int max77541_regulator_probe(struct platform_device *pdev) +{ + struct regulator_config config = {}; + const struct regulator_desc *desc; + struct device *dev = &pdev->dev; + struct regulator_dev *rdev; + struct max77541 *max77541 = dev_get_drvdata(dev->parent); + unsigned int i; + + config.dev = dev->parent; + + switch (max77541->id) { + case MAX77540: + desc = max77540_regulators_desc; + break; + case MAX77541: + desc = max77541_regulators_desc; + break; + default: + return -EINVAL; + } + + for (i = 0; i < MAX77541_MAX_REGULATORS; i++) { + rdev = devm_regulator_register(dev, &desc[i], &config); + if (IS_ERR(rdev)) + return dev_err_probe(dev, PTR_ERR(rdev), + "Failed to register regulator\n"); + } + + return 0; +} + +static const struct platform_device_id max77541_regulator_platform_id[] = { + { "max77540-regulator" }, + { "max77541-regulator" }, + { } +}; +MODULE_DEVICE_TABLE(platform, max77541_regulator_platform_id); + +static struct platform_driver max77541_regulator_driver = { + .driver = { + .name = "max77541-regulator", + }, + .probe = max77541_regulator_probe, + .id_table = max77541_regulator_platform_id, +}; +module_platform_driver(max77541_regulator_driver); + +MODULE_AUTHOR("Okan Sahin "); +MODULE_DESCRIPTION("MAX77540/MAX77541 regulator driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/regulator/max77826-regulator.c b/drivers/regulator/max77826-regulator.c index ea5d4b18b464dd4b7c41e4ead9356b8b22647b8d..3855f5e686d8acd5bc568b8ed2cbe0b402ab9d0d 100644 --- a/drivers/regulator/max77826-regulator.c +++ b/drivers/regulator/max77826-regulator.c @@ -292,7 +292,7 @@ static struct i2c_driver max77826_regulator_driver = { .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = of_match_ptr(max77826_of_match), }, - .probe_new = max77826_i2c_probe, + .probe = max77826_i2c_probe, .id_table = max77826_id, }; module_i2c_driver(max77826_regulator_driver); diff --git a/drivers/regulator/max8649.c b/drivers/regulator/max8649.c index a517fb4e3669b184716338ecbd3a9e0c9211f2e6..24e1dfba78c8b56c27f3050a3a3d5506ceeaf30e 100644 --- a/drivers/regulator/max8649.c +++ b/drivers/regulator/max8649.c @@ -246,7 +246,7 @@ static const struct i2c_device_id max8649_id[] = { MODULE_DEVICE_TABLE(i2c, max8649_id); static struct i2c_driver max8649_driver = { - .probe_new = max8649_regulator_probe, + .probe = max8649_regulator_probe, .driver = { .name = "max8649", .probe_type = PROBE_PREFER_ASYNCHRONOUS, diff --git a/drivers/regulator/max8660.c b/drivers/regulator/max8660.c index d6b89f07ae9ebab56ad6671b1819ab2742024f6a..ede17099b727499713989f1270f2d5284981e8fd 100644 --- a/drivers/regulator/max8660.c +++ b/drivers/regulator/max8660.c @@ -503,7 +503,7 @@ static const struct i2c_device_id max8660_id[] = { MODULE_DEVICE_TABLE(i2c, max8660_id); static struct i2c_driver max8660_driver = { - .probe_new = max8660_probe, + .probe = max8660_probe, .driver = { .name = "max8660", .probe_type = PROBE_PREFER_ASYNCHRONOUS, diff --git a/drivers/regulator/max8893.c b/drivers/regulator/max8893.c index 10ffd77828b784843124377e48fb4c02936cf849..cb0e72948dd41c81e5c64f6e1d639ce0e0e43484 100644 --- a/drivers/regulator/max8893.c +++ b/drivers/regulator/max8893.c @@ -168,7 +168,7 @@ static const struct i2c_device_id max8893_ids[] = { MODULE_DEVICE_TABLE(i2c, max8893_ids); static struct i2c_driver max8893_driver = { - .probe_new = max8893_probe_new, + .probe = max8893_probe_new, .driver = { .name = "max8893", .probe_type = PROBE_PREFER_ASYNCHRONOUS, diff --git a/drivers/regulator/max8952.c b/drivers/regulator/max8952.c index 8ad8fe7fd263e85f89754a437287d5e526270103..0b0b841d214afae28b79bd71e795684d5f486a9b 100644 --- a/drivers/regulator/max8952.c +++ b/drivers/regulator/max8952.c @@ -313,7 +313,7 @@ static const struct i2c_device_id max8952_ids[] = { MODULE_DEVICE_TABLE(i2c, max8952_ids); static struct i2c_driver max8952_pmic_driver = { - .probe_new = max8952_pmic_probe, + .probe = max8952_pmic_probe, .driver = { .name = "max8952", .probe_type = PROBE_PREFER_ASYNCHRONOUS, diff --git a/drivers/regulator/max8973-regulator.c b/drivers/regulator/max8973-regulator.c index a991a884a31bbfafe22fd8c826aa74f91835acd0..8d5193207552360eeadea34bb050402ddb4f6bcb 100644 --- a/drivers/regulator/max8973-regulator.c +++ b/drivers/regulator/max8973-regulator.c @@ -807,7 +807,7 @@ static struct i2c_driver max8973_i2c_driver = { .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = of_max8973_match_tbl, }, - .probe_new = max8973_probe, + .probe = max8973_probe, .id_table = max8973_id, }; diff --git a/drivers/regulator/mcp16502.c b/drivers/regulator/mcp16502.c index 3a6d795569423b85239bdf53ab1660d25f562555..6c6f5a21362bec1414d9da7f45dbbf41a8102b42 100644 --- a/drivers/regulator/mcp16502.c +++ b/drivers/regulator/mcp16502.c @@ -584,7 +584,7 @@ static const struct i2c_device_id mcp16502_i2c_id[] = { MODULE_DEVICE_TABLE(i2c, mcp16502_i2c_id); static struct i2c_driver mcp16502_drv = { - .probe_new = mcp16502_probe, + .probe = mcp16502_probe, .driver = { .name = "mcp16502-regulator", .probe_type = PROBE_PREFER_ASYNCHRONOUS, diff --git a/drivers/regulator/mp5416.c b/drivers/regulator/mp5416.c index 91e9019430b864e1f23ca8a3f7ebc085d85a6c14..3886b252fbe7bad8c4713d094bd5fa30f8c478fc 100644 --- a/drivers/regulator/mp5416.c +++ b/drivers/regulator/mp5416.c @@ -240,7 +240,7 @@ static struct i2c_driver mp5416_regulator_driver = { .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = of_match_ptr(mp5416_of_match), }, - .probe_new = mp5416_i2c_probe, + .probe = mp5416_i2c_probe, .id_table = mp5416_id, }; module_i2c_driver(mp5416_regulator_driver); diff --git a/drivers/regulator/mp8859.c b/drivers/regulator/mp8859.c index b968a682f38a0c9c35b58885ed565f1cbc220de0..b820bd6043e53bf217f0d60f2d57f0355319315b 100644 --- a/drivers/regulator/mp8859.c +++ b/drivers/regulator/mp8859.c @@ -147,7 +147,7 @@ static struct i2c_driver mp8859_regulator_driver = { .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = of_match_ptr(mp8859_dt_id), }, - .probe_new = mp8859_i2c_probe, + .probe = mp8859_i2c_probe, .id_table = mp8859_i2c_id, }; diff --git a/drivers/regulator/mp886x.c b/drivers/regulator/mp886x.c index 250c27e462f15a6a32e9cd718016bd5802c70649..ede1b1e58002614bdb3996af5362d36936ae02fe 100644 --- a/drivers/regulator/mp886x.c +++ b/drivers/regulator/mp886x.c @@ -365,7 +365,7 @@ static struct i2c_driver mp886x_regulator_driver = { .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = mp886x_dt_ids, }, - .probe_new = mp886x_i2c_probe, + .probe = mp886x_i2c_probe, .id_table = mp886x_id, }; module_i2c_driver(mp886x_regulator_driver); diff --git a/drivers/regulator/mpq7920.c b/drivers/regulator/mpq7920.c index 544d41b885144681b167b5c33770a9c6360abf96..bf677c535edc4b3dfb8bc4ed8592fdc81507c9dd 100644 --- a/drivers/regulator/mpq7920.c +++ b/drivers/regulator/mpq7920.c @@ -321,7 +321,7 @@ static struct i2c_driver mpq7920_regulator_driver = { .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = of_match_ptr(mpq7920_of_match), }, - .probe_new = mpq7920_i2c_probe, + .probe = mpq7920_i2c_probe, .id_table = mpq7920_id, }; module_i2c_driver(mpq7920_regulator_driver); diff --git a/drivers/regulator/mt6311-regulator.c b/drivers/regulator/mt6311-regulator.c index a9f0c9f725d42f5e855343b10990634e4a488f2f..b0771770cc2652a8a6aa10b5cbb04022798e475c 100644 --- a/drivers/regulator/mt6311-regulator.c +++ b/drivers/regulator/mt6311-regulator.c @@ -154,7 +154,7 @@ static struct i2c_driver mt6311_regulator_driver = { .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = of_match_ptr(mt6311_dt_ids), }, - .probe_new = mt6311_i2c_probe, + .probe = mt6311_i2c_probe, .id_table = mt6311_i2c_id, }; diff --git a/drivers/regulator/mt6358-regulator.c b/drivers/regulator/mt6358-regulator.c index c9e16bd092f6b988b5fa3d76badc79e3008f15f9..31a16fb28ecde52b8e9af37018db32f19d588e54 100644 --- a/drivers/regulator/mt6358-regulator.c +++ b/drivers/regulator/mt6358-regulator.c @@ -34,8 +34,10 @@ struct mt6358_regulator_info { u32 modeset_mask; }; +#define to_regulator_info(x) container_of((x), struct mt6358_regulator_info, desc) + #define MT6358_BUCK(match, vreg, min, max, step, \ - volt_ranges, vosel_mask, _da_vsel_reg, _da_vsel_mask, \ + vosel_mask, _da_vsel_reg, _da_vsel_mask, \ _modeset_reg, _modeset_shift) \ [MT6358_ID_##vreg] = { \ .desc = { \ @@ -46,8 +48,8 @@ struct mt6358_regulator_info { .id = MT6358_ID_##vreg, \ .owner = THIS_MODULE, \ .n_voltages = ((max) - (min)) / (step) + 1, \ - .linear_ranges = volt_ranges, \ - .n_linear_ranges = ARRAY_SIZE(volt_ranges), \ + .min_uV = (min), \ + .uV_step = (step), \ .vsel_reg = MT6358_BUCK_##vreg##_ELR0, \ .vsel_mask = vosel_mask, \ .enable_reg = MT6358_BUCK_##vreg##_CON0, \ @@ -87,7 +89,7 @@ struct mt6358_regulator_info { } #define MT6358_LDO1(match, vreg, min, max, step, \ - volt_ranges, _da_vsel_reg, _da_vsel_mask, \ + _da_vsel_reg, _da_vsel_mask, \ vosel, vosel_mask) \ [MT6358_ID_##vreg] = { \ .desc = { \ @@ -98,8 +100,8 @@ struct mt6358_regulator_info { .id = MT6358_ID_##vreg, \ .owner = THIS_MODULE, \ .n_voltages = ((max) - (min)) / (step) + 1, \ - .linear_ranges = volt_ranges, \ - .n_linear_ranges = ARRAY_SIZE(volt_ranges), \ + .min_uV = (min), \ + .uV_step = (step), \ .vsel_reg = vosel, \ .vsel_mask = vosel_mask, \ .enable_reg = MT6358_LDO_##vreg##_CON0, \ @@ -131,7 +133,7 @@ struct mt6358_regulator_info { } #define MT6366_BUCK(match, vreg, min, max, step, \ - volt_ranges, vosel_mask, _da_vsel_reg, _da_vsel_mask, \ + vosel_mask, _da_vsel_reg, _da_vsel_mask, \ _modeset_reg, _modeset_shift) \ [MT6366_ID_##vreg] = { \ .desc = { \ @@ -142,8 +144,8 @@ struct mt6358_regulator_info { .id = MT6366_ID_##vreg, \ .owner = THIS_MODULE, \ .n_voltages = ((max) - (min)) / (step) + 1, \ - .linear_ranges = volt_ranges, \ - .n_linear_ranges = ARRAY_SIZE(volt_ranges), \ + .min_uV = (min), \ + .uV_step = (step), \ .vsel_reg = MT6358_BUCK_##vreg##_ELR0, \ .vsel_mask = vosel_mask, \ .enable_reg = MT6358_BUCK_##vreg##_CON0, \ @@ -183,7 +185,7 @@ struct mt6358_regulator_info { } #define MT6366_LDO1(match, vreg, min, max, step, \ - volt_ranges, _da_vsel_reg, _da_vsel_mask, \ + _da_vsel_reg, _da_vsel_mask, \ vosel, vosel_mask) \ [MT6366_ID_##vreg] = { \ .desc = { \ @@ -194,8 +196,8 @@ struct mt6358_regulator_info { .id = MT6366_ID_##vreg, \ .owner = THIS_MODULE, \ .n_voltages = ((max) - (min)) / (step) + 1, \ - .linear_ranges = volt_ranges, \ - .n_linear_ranges = ARRAY_SIZE(volt_ranges), \ + .min_uV = (min), \ + .uV_step = (step), \ .vsel_reg = vosel, \ .vsel_mask = vosel_mask, \ .enable_reg = MT6358_LDO_##vreg##_CON0, \ @@ -226,21 +228,6 @@ struct mt6358_regulator_info { .qi = BIT(15), \ } -static const struct linear_range buck_volt_range1[] = { - REGULATOR_LINEAR_RANGE(500000, 0, 0x7f, 6250), -}; - -static const struct linear_range buck_volt_range2[] = { - REGULATOR_LINEAR_RANGE(500000, 0, 0x7f, 12500), -}; - -static const struct linear_range buck_volt_range3[] = { - REGULATOR_LINEAR_RANGE(500000, 0, 0x3f, 50000), -}; - -static const struct linear_range buck_volt_range4[] = { - REGULATOR_LINEAR_RANGE(1000000, 0, 0x7f, 12500), -}; static const unsigned int vdram2_voltages[] = { 600000, 1800000, @@ -277,7 +264,7 @@ static const unsigned int vcama_voltages[] = { 2800000, 2900000, 3000000, }; -static const unsigned int vcn33_bt_wifi_voltages[] = { +static const unsigned int vcn33_voltages[] = { 3300000, 3400000, 3500000, }; @@ -321,7 +308,7 @@ static const u32 vcama_idx[] = { 0, 7, 9, 10, 11, 12, }; -static const u32 vcn33_bt_wifi_idx[] = { +static const u32 vcn33_idx[] = { 1, 2, 3, }; @@ -342,9 +329,9 @@ static unsigned int mt6358_map_mode(unsigned int mode) static int mt6358_set_voltage_sel(struct regulator_dev *rdev, unsigned int selector) { + const struct mt6358_regulator_info *info = to_regulator_info(rdev->desc); int idx, ret; const u32 *pvol; - struct mt6358_regulator_info *info = rdev_get_drvdata(rdev); pvol = info->index_table; @@ -358,9 +345,9 @@ static int mt6358_set_voltage_sel(struct regulator_dev *rdev, static int mt6358_get_voltage_sel(struct regulator_dev *rdev) { + const struct mt6358_regulator_info *info = to_regulator_info(rdev->desc); int idx, ret; u32 selector; - struct mt6358_regulator_info *info = rdev_get_drvdata(rdev); const u32 *pvol; ret = regmap_read(rdev->regmap, info->desc.vsel_reg, &selector); @@ -384,8 +371,8 @@ static int mt6358_get_voltage_sel(struct regulator_dev *rdev) static int mt6358_get_buck_voltage_sel(struct regulator_dev *rdev) { + const struct mt6358_regulator_info *info = to_regulator_info(rdev->desc); int ret, regval; - struct mt6358_regulator_info *info = rdev_get_drvdata(rdev); ret = regmap_read(rdev->regmap, info->da_vsel_reg, ®val); if (ret != 0) { @@ -402,9 +389,9 @@ static int mt6358_get_buck_voltage_sel(struct regulator_dev *rdev) static int mt6358_get_status(struct regulator_dev *rdev) { + const struct mt6358_regulator_info *info = to_regulator_info(rdev->desc); int ret; u32 regval; - struct mt6358_regulator_info *info = rdev_get_drvdata(rdev); ret = regmap_read(rdev->regmap, info->status_reg, ®val); if (ret != 0) { @@ -418,7 +405,7 @@ static int mt6358_get_status(struct regulator_dev *rdev) static int mt6358_regulator_set_mode(struct regulator_dev *rdev, unsigned int mode) { - struct mt6358_regulator_info *info = rdev_get_drvdata(rdev); + const struct mt6358_regulator_info *info = to_regulator_info(rdev->desc); int val; switch (mode) { @@ -443,7 +430,7 @@ static int mt6358_regulator_set_mode(struct regulator_dev *rdev, static unsigned int mt6358_regulator_get_mode(struct regulator_dev *rdev) { - struct mt6358_regulator_info *info = rdev_get_drvdata(rdev); + const struct mt6358_regulator_info *info = to_regulator_info(rdev->desc); int ret, regval; ret = regmap_read(rdev->regmap, info->modeset_reg, ®val); @@ -464,8 +451,8 @@ static unsigned int mt6358_regulator_get_mode(struct regulator_dev *rdev) } static const struct regulator_ops mt6358_volt_range_ops = { - .list_voltage = regulator_list_voltage_linear_range, - .map_voltage = regulator_map_voltage_linear_range, + .list_voltage = regulator_list_voltage_linear, + .map_voltage = regulator_map_voltage_linear, .set_voltage_sel = regulator_set_voltage_sel_regmap, .get_voltage_sel = mt6358_get_buck_voltage_sel, .set_voltage_time_sel = regulator_set_voltage_time_sel, @@ -498,37 +485,25 @@ static const struct regulator_ops mt6358_volt_fixed_ops = { }; /* The array is indexed by id(MT6358_ID_XXX) */ -static struct mt6358_regulator_info mt6358_regulators[] = { +static const struct mt6358_regulator_info mt6358_regulators[] = { MT6358_BUCK("buck_vdram1", VDRAM1, 500000, 2087500, 12500, - buck_volt_range2, 0x7f, MT6358_BUCK_VDRAM1_DBG0, 0x7f, - MT6358_VDRAM1_ANA_CON0, 8), + 0x7f, MT6358_BUCK_VDRAM1_DBG0, 0x7f, MT6358_VDRAM1_ANA_CON0, 8), MT6358_BUCK("buck_vcore", VCORE, 500000, 1293750, 6250, - buck_volt_range1, 0x7f, MT6358_BUCK_VCORE_DBG0, 0x7f, - MT6358_VCORE_VGPU_ANA_CON0, 1), - MT6358_BUCK("buck_vcore_sshub", VCORE_SSHUB, 500000, 1293750, 6250, - buck_volt_range1, 0x7f, MT6358_BUCK_VCORE_SSHUB_ELR0, 0x7f, - MT6358_VCORE_VGPU_ANA_CON0, 1), + 0x7f, MT6358_BUCK_VCORE_DBG0, 0x7f, MT6358_VCORE_VGPU_ANA_CON0, 1), MT6358_BUCK("buck_vpa", VPA, 500000, 3650000, 50000, - buck_volt_range3, 0x3f, MT6358_BUCK_VPA_DBG0, 0x3f, - MT6358_VPA_ANA_CON0, 3), + 0x3f, MT6358_BUCK_VPA_DBG0, 0x3f, MT6358_VPA_ANA_CON0, 3), MT6358_BUCK("buck_vproc11", VPROC11, 500000, 1293750, 6250, - buck_volt_range1, 0x7f, MT6358_BUCK_VPROC11_DBG0, 0x7f, - MT6358_VPROC_ANA_CON0, 1), + 0x7f, MT6358_BUCK_VPROC11_DBG0, 0x7f, MT6358_VPROC_ANA_CON0, 1), MT6358_BUCK("buck_vproc12", VPROC12, 500000, 1293750, 6250, - buck_volt_range1, 0x7f, MT6358_BUCK_VPROC12_DBG0, 0x7f, - MT6358_VPROC_ANA_CON0, 2), + 0x7f, MT6358_BUCK_VPROC12_DBG0, 0x7f, MT6358_VPROC_ANA_CON0, 2), MT6358_BUCK("buck_vgpu", VGPU, 500000, 1293750, 6250, - buck_volt_range1, 0x7f, MT6358_BUCK_VGPU_ELR0, 0x7f, - MT6358_VCORE_VGPU_ANA_CON0, 2), + 0x7f, MT6358_BUCK_VGPU_ELR0, 0x7f, MT6358_VCORE_VGPU_ANA_CON0, 2), MT6358_BUCK("buck_vs2", VS2, 500000, 2087500, 12500, - buck_volt_range2, 0x7f, MT6358_BUCK_VS2_DBG0, 0x7f, - MT6358_VS2_ANA_CON0, 8), + 0x7f, MT6358_BUCK_VS2_DBG0, 0x7f, MT6358_VS2_ANA_CON0, 8), MT6358_BUCK("buck_vmodem", VMODEM, 500000, 1293750, 6250, - buck_volt_range1, 0x7f, MT6358_BUCK_VMODEM_DBG0, 0x7f, - MT6358_VMODEM_ANA_CON0, 8), + 0x7f, MT6358_BUCK_VMODEM_DBG0, 0x7f, MT6358_VMODEM_ANA_CON0, 8), MT6358_BUCK("buck_vs1", VS1, 1000000, 2587500, 12500, - buck_volt_range4, 0x7f, MT6358_BUCK_VS1_DBG0, 0x7f, - MT6358_VS1_ANA_CON0, 8), + 0x7f, MT6358_BUCK_VS1_DBG0, 0x7f, MT6358_VS1_ANA_CON0, 8), MT6358_REG_FIXED("ldo_vrf12", VRF12, MT6358_LDO_VRF12_CON0, 0, 1200000), MT6358_REG_FIXED("ldo_vio18", VIO18, @@ -566,12 +541,8 @@ static struct mt6358_regulator_info mt6358_regulators[] = { MT6358_LDO_VCAMA1_CON0, 0, MT6358_VCAMA1_ANA_CON0, 0xf00), MT6358_LDO("ldo_vemc", VEMC, vmch_vemc_voltages, vmch_vemc_idx, MT6358_LDO_VEMC_CON0, 0, MT6358_VEMC_ANA_CON0, 0x700), - MT6358_LDO("ldo_vcn33_bt", VCN33_BT, vcn33_bt_wifi_voltages, - vcn33_bt_wifi_idx, MT6358_LDO_VCN33_CON0_0, - 0, MT6358_VCN33_ANA_CON0, 0x300), - MT6358_LDO("ldo_vcn33_wifi", VCN33_WIFI, vcn33_bt_wifi_voltages, - vcn33_bt_wifi_idx, MT6358_LDO_VCN33_CON0_1, - 0, MT6358_VCN33_ANA_CON0, 0x300), + MT6358_LDO("ldo_vcn33", VCN33, vcn33_voltages, vcn33_idx, + MT6358_LDO_VCN33_CON0_0, 0, MT6358_VCN33_ANA_CON0, 0x300), MT6358_LDO("ldo_vcama2", VCAMA2, vcama_voltages, vcama_idx, MT6358_LDO_VCAMA2_CON0, 0, MT6358_VCAMA2_ANA_CON0, 0xf00), MT6358_LDO("ldo_vmc", VMC, vmc_voltages, vmc_idx, @@ -582,55 +553,35 @@ static struct mt6358_regulator_info mt6358_regulators[] = { MT6358_LDO("ldo_vsim2", VSIM2, vsim_voltages, vsim_idx, MT6358_LDO_VSIM2_CON0, 0, MT6358_VSIM2_ANA_CON0, 0xf00), MT6358_LDO1("ldo_vsram_proc11", VSRAM_PROC11, 500000, 1293750, 6250, - buck_volt_range1, MT6358_LDO_VSRAM_PROC11_DBG0, 0x7f00, - MT6358_LDO_VSRAM_CON0, 0x7f), + MT6358_LDO_VSRAM_PROC11_DBG0, 0x7f00, MT6358_LDO_VSRAM_CON0, 0x7f), MT6358_LDO1("ldo_vsram_others", VSRAM_OTHERS, 500000, 1293750, 6250, - buck_volt_range1, MT6358_LDO_VSRAM_OTHERS_DBG0, 0x7f00, - MT6358_LDO_VSRAM_CON2, 0x7f), - MT6358_LDO1("ldo_vsram_others_sshub", VSRAM_OTHERS_SSHUB, 500000, - 1293750, 6250, buck_volt_range1, - MT6358_LDO_VSRAM_OTHERS_SSHUB_CON1, 0x7f, - MT6358_LDO_VSRAM_OTHERS_SSHUB_CON1, 0x7f), + MT6358_LDO_VSRAM_OTHERS_DBG0, 0x7f00, MT6358_LDO_VSRAM_CON2, 0x7f), MT6358_LDO1("ldo_vsram_gpu", VSRAM_GPU, 500000, 1293750, 6250, - buck_volt_range1, MT6358_LDO_VSRAM_GPU_DBG0, 0x7f00, - MT6358_LDO_VSRAM_CON3, 0x7f), + MT6358_LDO_VSRAM_GPU_DBG0, 0x7f00, MT6358_LDO_VSRAM_CON3, 0x7f), MT6358_LDO1("ldo_vsram_proc12", VSRAM_PROC12, 500000, 1293750, 6250, - buck_volt_range1, MT6358_LDO_VSRAM_PROC12_DBG0, 0x7f00, - MT6358_LDO_VSRAM_CON1, 0x7f), + MT6358_LDO_VSRAM_PROC12_DBG0, 0x7f00, MT6358_LDO_VSRAM_CON1, 0x7f), }; /* The array is indexed by id(MT6366_ID_XXX) */ -static struct mt6358_regulator_info mt6366_regulators[] = { +static const struct mt6358_regulator_info mt6366_regulators[] = { MT6366_BUCK("buck_vdram1", VDRAM1, 500000, 2087500, 12500, - buck_volt_range2, 0x7f, MT6358_BUCK_VDRAM1_DBG0, 0x7f, - MT6358_VDRAM1_ANA_CON0, 8), + 0x7f, MT6358_BUCK_VDRAM1_DBG0, 0x7f, MT6358_VDRAM1_ANA_CON0, 8), MT6366_BUCK("buck_vcore", VCORE, 500000, 1293750, 6250, - buck_volt_range1, 0x7f, MT6358_BUCK_VCORE_DBG0, 0x7f, - MT6358_VCORE_VGPU_ANA_CON0, 1), - MT6366_BUCK("buck_vcore_sshub", VCORE_SSHUB, 500000, 1293750, 6250, - buck_volt_range1, 0x7f, MT6358_BUCK_VCORE_SSHUB_ELR0, 0x7f, - MT6358_VCORE_VGPU_ANA_CON0, 1), + 0x7f, MT6358_BUCK_VCORE_DBG0, 0x7f, MT6358_VCORE_VGPU_ANA_CON0, 1), MT6366_BUCK("buck_vpa", VPA, 500000, 3650000, 50000, - buck_volt_range3, 0x3f, MT6358_BUCK_VPA_DBG0, 0x3f, - MT6358_VPA_ANA_CON0, 3), + 0x3f, MT6358_BUCK_VPA_DBG0, 0x3f, MT6358_VPA_ANA_CON0, 3), MT6366_BUCK("buck_vproc11", VPROC11, 500000, 1293750, 6250, - buck_volt_range1, 0x7f, MT6358_BUCK_VPROC11_DBG0, 0x7f, - MT6358_VPROC_ANA_CON0, 1), + 0x7f, MT6358_BUCK_VPROC11_DBG0, 0x7f, MT6358_VPROC_ANA_CON0, 1), MT6366_BUCK("buck_vproc12", VPROC12, 500000, 1293750, 6250, - buck_volt_range1, 0x7f, MT6358_BUCK_VPROC12_DBG0, 0x7f, - MT6358_VPROC_ANA_CON0, 2), + 0x7f, MT6358_BUCK_VPROC12_DBG0, 0x7f, MT6358_VPROC_ANA_CON0, 2), MT6366_BUCK("buck_vgpu", VGPU, 500000, 1293750, 6250, - buck_volt_range1, 0x7f, MT6358_BUCK_VGPU_ELR0, 0x7f, - MT6358_VCORE_VGPU_ANA_CON0, 2), + 0x7f, MT6358_BUCK_VGPU_ELR0, 0x7f, MT6358_VCORE_VGPU_ANA_CON0, 2), MT6366_BUCK("buck_vs2", VS2, 500000, 2087500, 12500, - buck_volt_range2, 0x7f, MT6358_BUCK_VS2_DBG0, 0x7f, - MT6358_VS2_ANA_CON0, 8), + 0x7f, MT6358_BUCK_VS2_DBG0, 0x7f, MT6358_VS2_ANA_CON0, 8), MT6366_BUCK("buck_vmodem", VMODEM, 500000, 1293750, 6250, - buck_volt_range1, 0x7f, MT6358_BUCK_VMODEM_DBG0, 0x7f, - MT6358_VMODEM_ANA_CON0, 8), + 0x7f, MT6358_BUCK_VMODEM_DBG0, 0x7f, MT6358_VMODEM_ANA_CON0, 8), MT6366_BUCK("buck_vs1", VS1, 1000000, 2587500, 12500, - buck_volt_range4, 0x7f, MT6358_BUCK_VS1_DBG0, 0x7f, - MT6358_VS1_ANA_CON0, 8), + 0x7f, MT6358_BUCK_VS1_DBG0, 0x7f, MT6358_VS1_ANA_CON0, 8), MT6366_REG_FIXED("ldo_vrf12", VRF12, MT6358_LDO_VRF12_CON0, 0, 1200000), MT6366_REG_FIXED("ldo_vio18", VIO18, @@ -662,41 +613,72 @@ static struct mt6358_regulator_info mt6366_regulators[] = { MT6358_LDO_VMCH_CON0, 0, MT6358_VMCH_ANA_CON0, 0x700), MT6366_LDO("ldo_vemc", VEMC, vmch_vemc_voltages, vmch_vemc_idx, MT6358_LDO_VEMC_CON0, 0, MT6358_VEMC_ANA_CON0, 0x700), - MT6366_LDO("ldo_vcn33_bt", VCN33_BT, vcn33_bt_wifi_voltages, - vcn33_bt_wifi_idx, MT6358_LDO_VCN33_CON0_0, - 0, MT6358_VCN33_ANA_CON0, 0x300), - MT6366_LDO("ldo_vcn33_wifi", VCN33_WIFI, vcn33_bt_wifi_voltages, - vcn33_bt_wifi_idx, MT6358_LDO_VCN33_CON0_1, - 0, MT6358_VCN33_ANA_CON0, 0x300), + MT6366_LDO("ldo_vcn33", VCN33, vcn33_voltages, vcn33_idx, + MT6358_LDO_VCN33_CON0_0, 0, MT6358_VCN33_ANA_CON0, 0x300), MT6366_LDO("ldo_vmc", VMC, vmc_voltages, vmc_idx, MT6358_LDO_VMC_CON0, 0, MT6358_VMC_ANA_CON0, 0xf00), MT6366_LDO("ldo_vsim2", VSIM2, vsim_voltages, vsim_idx, MT6358_LDO_VSIM2_CON0, 0, MT6358_VSIM2_ANA_CON0, 0xf00), MT6366_LDO1("ldo_vsram_proc11", VSRAM_PROC11, 500000, 1293750, 6250, - buck_volt_range1, MT6358_LDO_VSRAM_PROC11_DBG0, 0x7f00, - MT6358_LDO_VSRAM_CON0, 0x7f), + MT6358_LDO_VSRAM_PROC11_DBG0, 0x7f00, MT6358_LDO_VSRAM_CON0, 0x7f), MT6366_LDO1("ldo_vsram_others", VSRAM_OTHERS, 500000, 1293750, 6250, - buck_volt_range1, MT6358_LDO_VSRAM_OTHERS_DBG0, 0x7f00, - MT6358_LDO_VSRAM_CON2, 0x7f), - MT6366_LDO1("ldo_vsram_others_sshub", VSRAM_OTHERS_SSHUB, 500000, - 1293750, 6250, buck_volt_range1, - MT6358_LDO_VSRAM_OTHERS_SSHUB_CON1, 0x7f, - MT6358_LDO_VSRAM_OTHERS_SSHUB_CON1, 0x7f), + MT6358_LDO_VSRAM_OTHERS_DBG0, 0x7f00, MT6358_LDO_VSRAM_CON2, 0x7f), MT6366_LDO1("ldo_vsram_gpu", VSRAM_GPU, 500000, 1293750, 6250, - buck_volt_range1, MT6358_LDO_VSRAM_GPU_DBG0, 0x7f00, - MT6358_LDO_VSRAM_CON3, 0x7f), + MT6358_LDO_VSRAM_GPU_DBG0, 0x7f00, MT6358_LDO_VSRAM_CON3, 0x7f), MT6366_LDO1("ldo_vsram_proc12", VSRAM_PROC12, 500000, 1293750, 6250, - buck_volt_range1, MT6358_LDO_VSRAM_PROC12_DBG0, 0x7f00, - MT6358_LDO_VSRAM_CON1, 0x7f), + MT6358_LDO_VSRAM_PROC12_DBG0, 0x7f00, MT6358_LDO_VSRAM_CON1, 0x7f), }; +static int mt6358_sync_vcn33_setting(struct device *dev) +{ + struct mt6397_chip *mt6397 = dev_get_drvdata(dev->parent); + unsigned int val; + int ret; + + /* + * VCN33_WIFI and VCN33_BT are two separate enable bits for the same + * regulator. They share the same voltage setting and output pin. + * Instead of having two potentially conflicting regulators, just have + * one VCN33 regulator. Sync the two enable bits and only use one in + * the regulator device. + */ + ret = regmap_read(mt6397->regmap, MT6358_LDO_VCN33_CON0_1, &val); + if (ret) { + dev_err(dev, "Failed to read VCN33_WIFI setting\n"); + return ret; + } + + if (!(val & BIT(0))) + return 0; + + /* Sync VCN33_WIFI enable status to VCN33_BT */ + ret = regmap_update_bits(mt6397->regmap, MT6358_LDO_VCN33_CON0_0, BIT(0), BIT(0)); + if (ret) { + dev_err(dev, "Failed to sync VCN33_WIFI setting to VCN33_BT\n"); + return ret; + } + + /* Disable VCN33_WIFI */ + ret = regmap_update_bits(mt6397->regmap, MT6358_LDO_VCN33_CON0_1, BIT(0), 0); + if (ret) { + dev_err(dev, "Failed to disable VCN33_BT\n"); + return ret; + } + + return 0; +} + static int mt6358_regulator_probe(struct platform_device *pdev) { struct mt6397_chip *mt6397 = dev_get_drvdata(pdev->dev.parent); struct regulator_config config = {}; struct regulator_dev *rdev; - struct mt6358_regulator_info *mt6358_info; - int i, max_regulator; + const struct mt6358_regulator_info *mt6358_info; + int i, max_regulator, ret; + + ret = mt6358_sync_vcn33_setting(&pdev->dev); + if (ret) + return ret; if (mt6397->chip_id == MT6366_CHIP_ID) { max_regulator = MT6366_MAX_REGULATOR; @@ -708,7 +690,6 @@ static int mt6358_regulator_probe(struct platform_device *pdev) for (i = 0; i < max_regulator; i++) { config.dev = &pdev->dev; - config.driver_data = &mt6358_info[i]; config.regmap = mt6397->regmap; rdev = devm_regulator_register(&pdev->dev, diff --git a/drivers/regulator/pca9450-regulator.c b/drivers/regulator/pca9450-regulator.c index e75dd92f86ca728435247b1523a1a3283e0e0efc..91bfb7e026c90b32eec4c1606119cea169d83c49 100644 --- a/drivers/regulator/pca9450-regulator.c +++ b/drivers/regulator/pca9450-regulator.c @@ -875,7 +875,7 @@ static struct i2c_driver pca9450_i2c_driver = { .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = pca9450_of_match, }, - .probe_new = pca9450_i2c_probe, + .probe = pca9450_i2c_probe, }; module_i2c_driver(pca9450_i2c_driver); diff --git a/drivers/regulator/pf8x00-regulator.c b/drivers/regulator/pf8x00-regulator.c index 99a15c3be39656b3278efe741273bf6f90394a28..b0781d9a1058f89dd531d3f22d9ed4fc525257f0 100644 --- a/drivers/regulator/pf8x00-regulator.c +++ b/drivers/regulator/pf8x00-regulator.c @@ -610,7 +610,7 @@ static struct i2c_driver pf8x00_regulator_driver = { .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = pf8x00_dt_ids, }, - .probe_new = pf8x00_i2c_probe, + .probe = pf8x00_i2c_probe, }; module_i2c_driver(pf8x00_regulator_driver); diff --git a/drivers/regulator/pfuze100-regulator.c b/drivers/regulator/pfuze100-regulator.c index a9fcf6a41494a640357e31a09055ff3fc3358334..8d7e6c3233243f0d414a08db93b43ac43f9fa052 100644 --- a/drivers/regulator/pfuze100-regulator.c +++ b/drivers/regulator/pfuze100-regulator.c @@ -848,7 +848,7 @@ static struct i2c_driver pfuze_driver = { .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = pfuze_dt_ids, }, - .probe_new = pfuze100_regulator_probe, + .probe = pfuze100_regulator_probe, }; module_i2c_driver(pfuze_driver); diff --git a/drivers/regulator/pv88060-regulator.c b/drivers/regulator/pv88060-regulator.c index f170e0dd18198562c0e00a71ccf195a2ffc704e0..aa90360fa046af1abce2b9d66327cfe2f01e3f89 100644 --- a/drivers/regulator/pv88060-regulator.c +++ b/drivers/regulator/pv88060-regulator.c @@ -379,7 +379,7 @@ static struct i2c_driver pv88060_regulator_driver = { .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = of_match_ptr(pv88060_dt_ids), }, - .probe_new = pv88060_i2c_probe, + .probe = pv88060_i2c_probe, .id_table = pv88060_i2c_id, }; diff --git a/drivers/regulator/pv88080-regulator.c b/drivers/regulator/pv88080-regulator.c index 133b89d5215c0d42d0be7fe22957629ba3c65682..7ab3e4a9bd28ccf441fe5756ada9cffac7dffe46 100644 --- a/drivers/regulator/pv88080-regulator.c +++ b/drivers/regulator/pv88080-regulator.c @@ -560,7 +560,7 @@ static struct i2c_driver pv88080_regulator_driver = { .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = of_match_ptr(pv88080_dt_ids), }, - .probe_new = pv88080_i2c_probe, + .probe = pv88080_i2c_probe, .id_table = pv88080_i2c_id, }; diff --git a/drivers/regulator/pv88090-regulator.c b/drivers/regulator/pv88090-regulator.c index 1bc33bc1099288caa595cc3e99aa748b0f73905b..f4acde4d56c81c2b4444480f6fe01437f252cca3 100644 --- a/drivers/regulator/pv88090-regulator.c +++ b/drivers/regulator/pv88090-regulator.c @@ -400,7 +400,7 @@ static struct i2c_driver pv88090_regulator_driver = { .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = of_match_ptr(pv88090_dt_ids), }, - .probe_new = pv88090_i2c_probe, + .probe = pv88090_i2c_probe, .id_table = pv88090_i2c_id, }; diff --git a/drivers/regulator/raa215300.c b/drivers/regulator/raa215300.c new file mode 100644 index 0000000000000000000000000000000000000000..24a1c89f5dbc94e7cba8f3a6c8ea6bf421e21d97 --- /dev/null +++ b/drivers/regulator/raa215300.c @@ -0,0 +1,190 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Renesas RAA215300 PMIC driver +// +// Copyright (C) 2023 Renesas Electronics Corporation +// + +#include +#include +#include +#include +#include +#include +#include +#include + +#define RAA215300_FAULT_LATCHED_STATUS_1 0x59 +#define RAA215300_FAULT_LATCHED_STATUS_2 0x5a +#define RAA215300_FAULT_LATCHED_STATUS_3 0x5b +#define RAA215300_FAULT_LATCHED_STATUS_4 0x5c +#define RAA215300_FAULT_LATCHED_STATUS_6 0x5e + +#define RAA215300_INT_MASK_1 0x64 +#define RAA215300_INT_MASK_2 0x65 +#define RAA215300_INT_MASK_3 0x66 +#define RAA215300_INT_MASK_4 0x67 +#define RAA215300_INT_MASK_6 0x68 + +#define RAA215300_REG_BLOCK_EN 0x6c +#define RAA215300_HW_REV 0xf8 + +#define RAA215300_INT_MASK_1_ALL GENMASK(5, 0) +#define RAA215300_INT_MASK_2_ALL GENMASK(3, 0) +#define RAA215300_INT_MASK_3_ALL GENMASK(5, 0) +#define RAA215300_INT_MASK_4_ALL BIT(0) +#define RAA215300_INT_MASK_6_ALL GENMASK(7, 0) + +#define RAA215300_REG_BLOCK_EN_RTC_EN BIT(6) +#define RAA215300_RTC_DEFAULT_ADDR 0x6f + +const char *clkin_name = "clkin"; +const char *xin_name = "xin"; +static struct clk *clk; + +static const struct regmap_config raa215300_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = 0xff, +}; + +static void raa215300_rtc_unregister_device(void *data) +{ + i2c_unregister_device(data); + if (!clk) { + clk_unregister_fixed_rate(clk); + clk = NULL; + } +} + +static int raa215300_clk_present(struct i2c_client *client, const char *name) +{ + struct clk *clk; + + clk = devm_clk_get_optional(&client->dev, name); + if (IS_ERR(clk)) + return PTR_ERR(clk); + + return !!clk; +} + +static int raa215300_i2c_probe(struct i2c_client *client) +{ + struct device *dev = &client->dev; + const char *clk_name = xin_name; + unsigned int pmic_version, val; + struct regmap *regmap; + int ret; + + regmap = devm_regmap_init_i2c(client, &raa215300_regmap_config); + if (IS_ERR(regmap)) + return dev_err_probe(dev, PTR_ERR(regmap), + "regmap i2c init failed\n"); + + ret = regmap_read(regmap, RAA215300_HW_REV, &pmic_version); + if (ret < 0) + return dev_err_probe(dev, ret, "HW rev read failed\n"); + + dev_dbg(dev, "RAA215300 PMIC version 0x%04x\n", pmic_version); + + /* Clear all blocks except RTC, if enabled */ + regmap_read(regmap, RAA215300_REG_BLOCK_EN, &val); + val &= RAA215300_REG_BLOCK_EN_RTC_EN; + regmap_write(regmap, RAA215300_REG_BLOCK_EN, val); + + /*Clear the latched registers */ + regmap_read(regmap, RAA215300_FAULT_LATCHED_STATUS_1, &val); + regmap_write(regmap, RAA215300_FAULT_LATCHED_STATUS_1, val); + regmap_read(regmap, RAA215300_FAULT_LATCHED_STATUS_2, &val); + regmap_write(regmap, RAA215300_FAULT_LATCHED_STATUS_2, val); + regmap_read(regmap, RAA215300_FAULT_LATCHED_STATUS_3, &val); + regmap_write(regmap, RAA215300_FAULT_LATCHED_STATUS_3, val); + regmap_read(regmap, RAA215300_FAULT_LATCHED_STATUS_4, &val); + regmap_write(regmap, RAA215300_FAULT_LATCHED_STATUS_4, val); + regmap_read(regmap, RAA215300_FAULT_LATCHED_STATUS_6, &val); + regmap_write(regmap, RAA215300_FAULT_LATCHED_STATUS_6, val); + + /* Mask all the PMIC interrupts */ + regmap_write(regmap, RAA215300_INT_MASK_1, RAA215300_INT_MASK_1_ALL); + regmap_write(regmap, RAA215300_INT_MASK_2, RAA215300_INT_MASK_2_ALL); + regmap_write(regmap, RAA215300_INT_MASK_3, RAA215300_INT_MASK_3_ALL); + regmap_write(regmap, RAA215300_INT_MASK_4, RAA215300_INT_MASK_4_ALL); + regmap_write(regmap, RAA215300_INT_MASK_6, RAA215300_INT_MASK_6_ALL); + + ret = raa215300_clk_present(client, xin_name); + if (ret < 0) { + return ret; + } else if (!ret) { + ret = raa215300_clk_present(client, clkin_name); + if (ret < 0) + return ret; + + clk_name = clkin_name; + } + + if (ret) { + char *name = pmic_version >= 0x12 ? "isl1208" : "raa215300_a0"; + struct device_node *np = client->dev.of_node; + u32 addr = RAA215300_RTC_DEFAULT_ADDR; + struct i2c_board_info info = {}; + struct i2c_client *rtc_client; + ssize_t size; + + clk = clk_register_fixed_rate(NULL, clk_name, NULL, 0, 32000); + clk_register_clkdev(clk, clk_name, NULL); + + if (np) { + int i; + + i = of_property_match_string(np, "reg-names", "rtc"); + if (i >= 0) + of_property_read_u32_index(np, "reg", i, &addr); + } + + info.addr = addr; + if (client->irq > 0) + info.irq = client->irq; + + size = strscpy(info.type, name, sizeof(info.type)); + if (size < 0) + return dev_err_probe(dev, size, + "Invalid device name: %s\n", name); + + /* Enable RTC block */ + regmap_update_bits(regmap, RAA215300_REG_BLOCK_EN, + RAA215300_REG_BLOCK_EN_RTC_EN, + RAA215300_REG_BLOCK_EN_RTC_EN); + + rtc_client = i2c_new_client_device(client->adapter, &info); + if (IS_ERR(rtc_client)) + return PTR_ERR(rtc_client); + + ret = devm_add_action_or_reset(dev, + raa215300_rtc_unregister_device, + rtc_client); + if (ret < 0) + return ret; + } + + return 0; +} + +static const struct of_device_id raa215300_dt_match[] = { + { .compatible = "renesas,raa215300" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, raa215300_dt_match); + +static struct i2c_driver raa215300_i2c_driver = { + .driver = { + .name = "raa215300", + .of_match_table = raa215300_dt_match, + }, + .probe_new = raa215300_i2c_probe, +}; +module_i2c_driver(raa215300_i2c_driver); + +MODULE_DESCRIPTION("Renesas RAA215300 PMIC driver"); +MODULE_AUTHOR("Fabrizio Castro "); +MODULE_AUTHOR("Biju Das "); +MODULE_LICENSE("GPL"); diff --git a/drivers/regulator/rk808-regulator.c b/drivers/regulator/rk808-regulator.c index 3637e81654a8ecaa9b31db3ae2133a36f6aa52df..460525ed006c70e2bee5eb3647b43faabc1c7292 100644 --- a/drivers/regulator/rk808-regulator.c +++ b/drivers/regulator/rk808-regulator.c @@ -3,9 +3,11 @@ * Regulator driver for Rockchip RK805/RK808/RK818 * * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd + * Copyright (c) 2021 Rockchip Electronics Co., Ltd. * * Author: Chris Zhong * Author: Zhang Qing + * Author: Xu Shengfei * * Copyright (C) 2016 PHYTEC Messtechnik GmbH * @@ -39,6 +41,13 @@ #define RK818_LDO3_ON_VSEL_MASK 0xf #define RK818_BOOST_ON_VSEL_MASK 0xe0 +#define RK806_DCDC_SLP_REG_OFFSET 0x0A +#define RK806_NLDO_SLP_REG_OFFSET 0x05 +#define RK806_PLDO_SLP_REG_OFFSET 0x06 + +#define RK806_BUCK_SEL_CNT 0xff +#define RK806_LDO_SEL_CNT 0xff + /* Ramp rate definitions for buck1 / buck2 only */ #define RK808_RAMP_RATE_OFFSET 3 #define RK808_RAMP_RATE_MASK (3 << RK808_RAMP_RATE_OFFSET) @@ -117,6 +126,34 @@ RK8XX_DESC_COM(_id, _match, _supply, _min, _max, _step, _vreg, \ _vmask, _ereg, _emask, 0, 0, _etime, &rk805_reg_ops) +#define RK806_REGULATOR(_name, _supply_name, _id, _ops,\ + _n_voltages, _vr, _er, _lr, ctrl_bit,\ + _rr, _rm, _rt)\ +[_id] = {\ + .name = _name,\ + .supply_name = _supply_name,\ + .of_match = of_match_ptr(_name),\ + .regulators_node = of_match_ptr("regulators"),\ + .id = _id,\ + .ops = &_ops,\ + .type = REGULATOR_VOLTAGE,\ + .n_voltages = _n_voltages,\ + .linear_ranges = _lr,\ + .n_linear_ranges = ARRAY_SIZE(_lr),\ + .vsel_reg = _vr,\ + .vsel_mask = 0xff,\ + .enable_reg = _er,\ + .enable_mask = ENABLE_MASK(ctrl_bit),\ + .enable_val = ENABLE_MASK(ctrl_bit),\ + .disable_val = DISABLE_VAL(ctrl_bit),\ + .of_map_mode = rk8xx_regulator_of_map_mode,\ + .ramp_reg = _rr,\ + .ramp_mask = _rm,\ + .ramp_delay_table = _rt, \ + .n_ramp_values = ARRAY_SIZE(_rt), \ + .owner = THIS_MODULE,\ + } + #define RK8XX_DESC(_id, _match, _supply, _min, _max, _step, _vreg, \ _vmask, _ereg, _emask, _etime) \ RK8XX_DESC_COM(_id, _match, _supply, _min, _max, _step, _vreg, \ @@ -153,6 +190,17 @@ RKXX_DESC_SWITCH_COM(_id, _match, _supply, _ereg, _emask, \ 0, 0, &rk808_switch_ops) +struct rk8xx_register_bit { + u8 reg; + u8 bit; +}; + +#define RK8XX_REG_BIT(_reg, _bit) \ + { \ + .reg = _reg, \ + .bit = BIT(_bit), \ + } + struct rk808_regulator_data { struct gpio_desc *dvs_gpio[2]; }; @@ -216,6 +264,133 @@ static const unsigned int rk817_buck1_4_ramp_table[] = { 3000, 6300, 12500, 25000 }; +static int rk806_set_mode_dcdc(struct regulator_dev *rdev, unsigned int mode) +{ + int rid = rdev_get_id(rdev); + int ctr_bit, reg; + + reg = RK806_POWER_FPWM_EN0 + rid / 8; + ctr_bit = rid % 8; + + switch (mode) { + case REGULATOR_MODE_FAST: + return regmap_update_bits(rdev->regmap, reg, + PWM_MODE_MSK << ctr_bit, + FPWM_MODE << ctr_bit); + case REGULATOR_MODE_NORMAL: + return regmap_update_bits(rdev->regmap, reg, + PWM_MODE_MSK << ctr_bit, + AUTO_PWM_MODE << ctr_bit); + default: + dev_err(rdev_get_dev(rdev), "mode unsupported: %u\n", mode); + return -EINVAL; + } + + return 0; +} + +static unsigned int rk806_get_mode_dcdc(struct regulator_dev *rdev) +{ + int rid = rdev_get_id(rdev); + int ctr_bit, reg; + unsigned int val; + int err; + + reg = RK806_POWER_FPWM_EN0 + rid / 8; + ctr_bit = rid % 8; + + err = regmap_read(rdev->regmap, reg, &val); + if (err) + return err; + + if ((val >> ctr_bit) & FPWM_MODE) + return REGULATOR_MODE_FAST; + else + return REGULATOR_MODE_NORMAL; +} + +static const struct rk8xx_register_bit rk806_dcdc_rate2[] = { + RK8XX_REG_BIT(0xEB, 0), + RK8XX_REG_BIT(0xEB, 1), + RK8XX_REG_BIT(0xEB, 2), + RK8XX_REG_BIT(0xEB, 3), + RK8XX_REG_BIT(0xEB, 4), + RK8XX_REG_BIT(0xEB, 5), + RK8XX_REG_BIT(0xEB, 6), + RK8XX_REG_BIT(0xEB, 7), + RK8XX_REG_BIT(0xEA, 0), + RK8XX_REG_BIT(0xEA, 1), +}; + +static const unsigned int rk806_ramp_delay_table_dcdc[] = { + 50000, 25000, 12500, 6250, 3125, 1560, 961, 390 +}; + +static int rk806_set_ramp_delay_dcdc(struct regulator_dev *rdev, int ramp_delay) +{ + int rid = rdev_get_id(rdev); + int regval, ramp_value, ret; + + ret = regulator_find_closest_bigger(ramp_delay, rdev->desc->ramp_delay_table, + rdev->desc->n_ramp_values, &ramp_value); + if (ret) { + dev_warn(rdev_get_dev(rdev), + "Can't set ramp-delay %u, setting %u\n", ramp_delay, + rdev->desc->ramp_delay_table[ramp_value]); + } + + regval = ramp_value << (ffs(rdev->desc->ramp_mask) - 1); + + ret = regmap_update_bits(rdev->regmap, rdev->desc->ramp_reg, + rdev->desc->ramp_mask, regval); + if (ret) + return ret; + + /* + * The above is effectively a copy of regulator_set_ramp_delay_regmap(), + * but that only stores the lower 2 bits for rk806 DCDC ramp. The MSB must + * be stored in a separate register, so this open codes the implementation + * to have access to the ramp_value. + */ + + regval = (ramp_value >> 2) & 0x1 ? rk806_dcdc_rate2[rid].bit : 0; + return regmap_update_bits(rdev->regmap, rk806_dcdc_rate2[rid].reg, + rk806_dcdc_rate2[rid].bit, + regval); +} + +static const unsigned int rk806_ramp_delay_table_ldo[] = { + 100000, 50000, 25000, 12500, 6280, 3120, 1900, 780 +}; + +static int rk806_set_suspend_voltage_range(struct regulator_dev *rdev, int reg_offset, int uv) +{ + int sel = regulator_map_voltage_linear_range(rdev, uv, uv); + unsigned int reg; + + if (sel < 0) + return -EINVAL; + + reg = rdev->desc->vsel_reg + reg_offset; + + return regmap_update_bits(rdev->regmap, reg, rdev->desc->vsel_mask, sel); +} + +static int rk806_set_suspend_voltage_range_dcdc(struct regulator_dev *rdev, int uv) +{ + return rk806_set_suspend_voltage_range(rdev, RK806_DCDC_SLP_REG_OFFSET, uv); +} + +static int rk806_set_suspend_voltage_range_nldo(struct regulator_dev *rdev, int uv) +{ + return rk806_set_suspend_voltage_range(rdev, RK806_NLDO_SLP_REG_OFFSET, uv); +} + +static int rk806_set_suspend_voltage_range_pldo(struct regulator_dev *rdev, int uv) +{ + return rk806_set_suspend_voltage_range(rdev, RK806_PLDO_SLP_REG_OFFSET, uv); +} + static int rk808_buck1_2_get_voltage_sel_regmap(struct regulator_dev *rdev) { struct rk808_regulator_data *pdata = rdev_get_drvdata(rdev); @@ -393,6 +568,47 @@ static int rk805_set_suspend_disable(struct regulator_dev *rdev) 0); } +static const struct rk8xx_register_bit rk806_suspend_bits[] = { + RK8XX_REG_BIT(RK806_POWER_SLP_EN0, 0), + RK8XX_REG_BIT(RK806_POWER_SLP_EN0, 1), + RK8XX_REG_BIT(RK806_POWER_SLP_EN0, 2), + RK8XX_REG_BIT(RK806_POWER_SLP_EN0, 3), + RK8XX_REG_BIT(RK806_POWER_SLP_EN0, 4), + RK8XX_REG_BIT(RK806_POWER_SLP_EN0, 5), + RK8XX_REG_BIT(RK806_POWER_SLP_EN0, 6), + RK8XX_REG_BIT(RK806_POWER_SLP_EN0, 7), + RK8XX_REG_BIT(RK806_POWER_SLP_EN1, 6), + RK8XX_REG_BIT(RK806_POWER_SLP_EN1, 7), + RK8XX_REG_BIT(RK806_POWER_SLP_EN1, 0), + RK8XX_REG_BIT(RK806_POWER_SLP_EN1, 1), + RK8XX_REG_BIT(RK806_POWER_SLP_EN1, 2), + RK8XX_REG_BIT(RK806_POWER_SLP_EN1, 3), + RK8XX_REG_BIT(RK806_POWER_SLP_EN1, 4), + RK8XX_REG_BIT(RK806_POWER_SLP_EN2, 1), + RK8XX_REG_BIT(RK806_POWER_SLP_EN2, 2), + RK8XX_REG_BIT(RK806_POWER_SLP_EN2, 3), + RK8XX_REG_BIT(RK806_POWER_SLP_EN2, 4), + RK8XX_REG_BIT(RK806_POWER_SLP_EN2, 5), + RK8XX_REG_BIT(RK806_POWER_SLP_EN2, 0), +}; + +static int rk806_set_suspend_enable(struct regulator_dev *rdev) +{ + int rid = rdev_get_id(rdev); + + return regmap_update_bits(rdev->regmap, rk806_suspend_bits[rid].reg, + rk806_suspend_bits[rid].bit, + rk806_suspend_bits[rid].bit); +} + +static int rk806_set_suspend_disable(struct regulator_dev *rdev) +{ + int rid = rdev_get_id(rdev); + + return regmap_update_bits(rdev->regmap, rk806_suspend_bits[rid].reg, + rk806_suspend_bits[rid].bit, 0); +} + static int rk808_set_suspend_enable(struct regulator_dev *rdev) { unsigned int reg; @@ -561,6 +777,64 @@ static const struct regulator_ops rk805_switch_ops = { .set_suspend_disable = rk805_set_suspend_disable, }; +static const struct regulator_ops rk806_ops_dcdc = { + .list_voltage = regulator_list_voltage_linear_range, + .map_voltage = regulator_map_voltage_linear_range, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .set_voltage_time_sel = regulator_set_voltage_time_sel, + .set_mode = rk806_set_mode_dcdc, + .get_mode = rk806_get_mode_dcdc, + + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = rk8xx_is_enabled_wmsk_regmap, + + .set_suspend_mode = rk806_set_mode_dcdc, + .set_ramp_delay = rk806_set_ramp_delay_dcdc, + + .set_suspend_voltage = rk806_set_suspend_voltage_range_dcdc, + .set_suspend_enable = rk806_set_suspend_enable, + .set_suspend_disable = rk806_set_suspend_disable, +}; + +static const struct regulator_ops rk806_ops_nldo = { + .list_voltage = regulator_list_voltage_linear_range, + .map_voltage = regulator_map_voltage_linear_range, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .set_voltage_time_sel = regulator_set_voltage_time_sel, + + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + + .set_ramp_delay = regulator_set_ramp_delay_regmap, + + .set_suspend_voltage = rk806_set_suspend_voltage_range_nldo, + .set_suspend_enable = rk806_set_suspend_enable, + .set_suspend_disable = rk806_set_suspend_disable, +}; + +static const struct regulator_ops rk806_ops_pldo = { + .list_voltage = regulator_list_voltage_linear_range, + .map_voltage = regulator_map_voltage_linear_range, + + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .set_voltage_time_sel = regulator_set_voltage_time_sel, + + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + + .set_ramp_delay = regulator_set_ramp_delay_regmap, + + .set_suspend_voltage = rk806_set_suspend_voltage_range_pldo, + .set_suspend_enable = rk806_set_suspend_enable, + .set_suspend_disable = rk806_set_suspend_disable, +}; + static const struct regulator_ops rk808_buck1_2_ops = { .list_voltage = regulator_list_voltage_linear, .map_voltage = regulator_map_voltage_linear, @@ -743,6 +1017,112 @@ static const struct regulator_desc rk805_reg[] = { BIT(2), 400), }; +static const struct linear_range rk806_buck_voltage_ranges[] = { + REGULATOR_LINEAR_RANGE(500000, 0, 160, 6250), /* 500mV ~ 1500mV */ + REGULATOR_LINEAR_RANGE(1500000, 161, 237, 25000), /* 1500mV ~ 3400mV */ + REGULATOR_LINEAR_RANGE(3400000, 238, 255, 0), +}; + +static const struct linear_range rk806_ldo_voltage_ranges[] = { + REGULATOR_LINEAR_RANGE(500000, 0, 232, 12500), /* 500mV ~ 3400mV */ + REGULATOR_LINEAR_RANGE(3400000, 233, 255, 0), /* 500mV ~ 3400mV */ +}; + +static const struct regulator_desc rk806_reg[] = { + RK806_REGULATOR("dcdc-reg1", "vcc1", RK806_ID_DCDC1, rk806_ops_dcdc, + RK806_BUCK_SEL_CNT, RK806_BUCK1_ON_VSEL, + RK806_POWER_EN0, rk806_buck_voltage_ranges, 0, + RK806_BUCK1_CONFIG, 0xc0, rk806_ramp_delay_table_dcdc), + RK806_REGULATOR("dcdc-reg2", "vcc2", RK806_ID_DCDC2, rk806_ops_dcdc, + RK806_BUCK_SEL_CNT, RK806_BUCK2_ON_VSEL, + RK806_POWER_EN0, rk806_buck_voltage_ranges, 1, + RK806_BUCK2_CONFIG, 0xc0, rk806_ramp_delay_table_dcdc), + RK806_REGULATOR("dcdc-reg3", "vcc3", RK806_ID_DCDC3, rk806_ops_dcdc, + RK806_BUCK_SEL_CNT, RK806_BUCK3_ON_VSEL, + RK806_POWER_EN0, rk806_buck_voltage_ranges, 2, + RK806_BUCK3_CONFIG, 0xc0, rk806_ramp_delay_table_dcdc), + RK806_REGULATOR("dcdc-reg4", "vcc4", RK806_ID_DCDC4, rk806_ops_dcdc, + RK806_BUCK_SEL_CNT, RK806_BUCK4_ON_VSEL, + RK806_POWER_EN0, rk806_buck_voltage_ranges, 3, + RK806_BUCK4_CONFIG, 0xc0, rk806_ramp_delay_table_dcdc), + + RK806_REGULATOR("dcdc-reg5", "vcc5", RK806_ID_DCDC5, rk806_ops_dcdc, + RK806_BUCK_SEL_CNT, RK806_BUCK5_ON_VSEL, + RK806_POWER_EN1, rk806_buck_voltage_ranges, 0, + RK806_BUCK5_CONFIG, 0xc0, rk806_ramp_delay_table_dcdc), + RK806_REGULATOR("dcdc-reg6", "vcc6", RK806_ID_DCDC6, rk806_ops_dcdc, + RK806_BUCK_SEL_CNT, RK806_BUCK6_ON_VSEL, + RK806_POWER_EN1, rk806_buck_voltage_ranges, 1, + RK806_BUCK6_CONFIG, 0xc0, rk806_ramp_delay_table_dcdc), + RK806_REGULATOR("dcdc-reg7", "vcc7", RK806_ID_DCDC7, rk806_ops_dcdc, + RK806_BUCK_SEL_CNT, RK806_BUCK7_ON_VSEL, + RK806_POWER_EN1, rk806_buck_voltage_ranges, 2, + RK806_BUCK7_CONFIG, 0xc0, rk806_ramp_delay_table_dcdc), + RK806_REGULATOR("dcdc-reg8", "vcc8", RK806_ID_DCDC8, rk806_ops_dcdc, + RK806_BUCK_SEL_CNT, RK806_BUCK8_ON_VSEL, + RK806_POWER_EN1, rk806_buck_voltage_ranges, 3, + RK806_BUCK8_CONFIG, 0xc0, rk806_ramp_delay_table_dcdc), + + RK806_REGULATOR("dcdc-reg9", "vcc9", RK806_ID_DCDC9, rk806_ops_dcdc, + RK806_BUCK_SEL_CNT, RK806_BUCK9_ON_VSEL, + RK806_POWER_EN2, rk806_buck_voltage_ranges, 0, + RK806_BUCK9_CONFIG, 0xc0, rk806_ramp_delay_table_dcdc), + RK806_REGULATOR("dcdc-reg10", "vcc10", RK806_ID_DCDC10, rk806_ops_dcdc, + RK806_BUCK_SEL_CNT, RK806_BUCK10_ON_VSEL, + RK806_POWER_EN2, rk806_buck_voltage_ranges, 1, + RK806_BUCK10_CONFIG, 0xc0, rk806_ramp_delay_table_dcdc), + + RK806_REGULATOR("nldo-reg1", "vcc13", RK806_ID_NLDO1, rk806_ops_nldo, + RK806_LDO_SEL_CNT, RK806_NLDO1_ON_VSEL, + RK806_POWER_EN3, rk806_ldo_voltage_ranges, 0, + 0xEA, 0x38, rk806_ramp_delay_table_ldo), + RK806_REGULATOR("nldo-reg2", "vcc13", RK806_ID_NLDO2, rk806_ops_nldo, + RK806_LDO_SEL_CNT, RK806_NLDO2_ON_VSEL, + RK806_POWER_EN3, rk806_ldo_voltage_ranges, 1, + 0xEA, 0x38, rk806_ramp_delay_table_ldo), + RK806_REGULATOR("nldo-reg3", "vcc13", RK806_ID_NLDO3, rk806_ops_nldo, + RK806_LDO_SEL_CNT, RK806_NLDO3_ON_VSEL, + RK806_POWER_EN3, rk806_ldo_voltage_ranges, 2, + 0xEA, 0x38, rk806_ramp_delay_table_ldo), + RK806_REGULATOR("nldo-reg4", "vcc14", RK806_ID_NLDO4, rk806_ops_nldo, + RK806_LDO_SEL_CNT, RK806_NLDO4_ON_VSEL, + RK806_POWER_EN3, rk806_ldo_voltage_ranges, 3, + 0xEA, 0x38, rk806_ramp_delay_table_ldo), + + RK806_REGULATOR("nldo-reg5", "vcc14", RK806_ID_NLDO5, rk806_ops_nldo, + RK806_LDO_SEL_CNT, RK806_NLDO5_ON_VSEL, + RK806_POWER_EN5, rk806_ldo_voltage_ranges, 2, + 0xEA, 0x38, rk806_ramp_delay_table_ldo), + + RK806_REGULATOR("pldo-reg1", "vcc11", RK806_ID_PLDO1, rk806_ops_pldo, + RK806_LDO_SEL_CNT, RK806_PLDO1_ON_VSEL, + RK806_POWER_EN4, rk806_ldo_voltage_ranges, 1, + 0xEA, 0x38, rk806_ramp_delay_table_ldo), + RK806_REGULATOR("pldo-reg2", "vcc11", RK806_ID_PLDO2, rk806_ops_pldo, + RK806_LDO_SEL_CNT, RK806_PLDO2_ON_VSEL, + RK806_POWER_EN4, rk806_ldo_voltage_ranges, 2, + 0xEA, 0x38, rk806_ramp_delay_table_ldo), + RK806_REGULATOR("pldo-reg3", "vcc11", RK806_ID_PLDO3, rk806_ops_pldo, + RK806_LDO_SEL_CNT, RK806_PLDO3_ON_VSEL, + RK806_POWER_EN4, rk806_ldo_voltage_ranges, 3, + 0xEA, 0x38, rk806_ramp_delay_table_ldo), + + RK806_REGULATOR("pldo-reg4", "vcc12", RK806_ID_PLDO4, rk806_ops_pldo, + RK806_LDO_SEL_CNT, RK806_PLDO4_ON_VSEL, + RK806_POWER_EN5, rk806_ldo_voltage_ranges, 0, + 0xEA, 0x38, rk806_ramp_delay_table_ldo), + RK806_REGULATOR("pldo-reg5", "vcc12", RK806_ID_PLDO5, rk806_ops_pldo, + RK806_LDO_SEL_CNT, RK806_PLDO5_ON_VSEL, + RK806_POWER_EN5, rk806_ldo_voltage_ranges, 1, + 0xEA, 0x38, rk806_ramp_delay_table_ldo), + + RK806_REGULATOR("pldo-reg6", "vcca", RK806_ID_PLDO6, rk806_ops_pldo, + RK806_LDO_SEL_CNT, RK806_PLDO6_ON_VSEL, + RK806_POWER_EN4, rk806_ldo_voltage_ranges, 0, + 0xEA, 0x38, rk806_ramp_delay_table_ldo), +}; + + static const struct regulator_desc rk808_reg[] = { { .name = "DCDC_REG1", @@ -1245,20 +1625,19 @@ static const struct regulator_desc rk818_reg[] = { }; static int rk808_regulator_dt_parse_pdata(struct device *dev, - struct device *client_dev, struct regmap *map, struct rk808_regulator_data *pdata) { struct device_node *np; int tmp, ret = 0, i; - np = of_get_child_by_name(client_dev->of_node, "regulators"); + np = of_get_child_by_name(dev->of_node, "regulators"); if (!np) return -ENXIO; for (i = 0; i < ARRAY_SIZE(pdata->dvs_gpio); i++) { pdata->dvs_gpio[i] = - devm_gpiod_get_index_optional(client_dev, "dvs", i, + devm_gpiod_get_index_optional(dev, "dvs", i, GPIOD_OUT_LOW); if (IS_ERR(pdata->dvs_gpio[i])) { ret = PTR_ERR(pdata->dvs_gpio[i]); @@ -1292,6 +1671,9 @@ static int rk808_regulator_probe(struct platform_device *pdev) struct regmap *regmap; int ret, i, nregulators; + pdev->dev.of_node = pdev->dev.parent->of_node; + pdev->dev.of_node_reused = true; + regmap = dev_get_regmap(pdev->dev.parent, NULL); if (!regmap) return -ENODEV; @@ -1300,8 +1682,7 @@ static int rk808_regulator_probe(struct platform_device *pdev) if (!pdata) return -ENOMEM; - ret = rk808_regulator_dt_parse_pdata(&pdev->dev, pdev->dev.parent, - regmap, pdata); + ret = rk808_regulator_dt_parse_pdata(&pdev->dev, regmap, pdata); if (ret < 0) return ret; @@ -1312,6 +1693,10 @@ static int rk808_regulator_probe(struct platform_device *pdev) regulators = rk805_reg; nregulators = RK805_NUM_REGULATORS; break; + case RK806_ID: + regulators = rk806_reg; + nregulators = ARRAY_SIZE(rk806_reg); + break; case RK808_ID: regulators = rk808_reg; nregulators = RK808_NUM_REGULATORS; @@ -1335,7 +1720,6 @@ static int rk808_regulator_probe(struct platform_device *pdev) } config.dev = &pdev->dev; - config.dev->of_node = pdev->dev.parent->of_node; config.driver_data = pdata; config.regmap = regmap; @@ -1355,7 +1739,7 @@ static struct platform_driver rk808_regulator_driver = { .probe = rk808_regulator_probe, .driver = { .name = "rk808-regulator", - .probe_type = PROBE_PREFER_ASYNCHRONOUS, + .probe_type = PROBE_FORCE_SYNCHRONOUS, }, }; @@ -1366,5 +1750,6 @@ MODULE_AUTHOR("Tony xie "); MODULE_AUTHOR("Chris Zhong "); MODULE_AUTHOR("Zhang Qing "); MODULE_AUTHOR("Wadim Egorov "); +MODULE_AUTHOR("Xu Shengfei "); MODULE_LICENSE("GPL"); MODULE_ALIAS("platform:rk808-regulator"); diff --git a/drivers/regulator/rpi-panel-attiny-regulator.c b/drivers/regulator/rpi-panel-attiny-regulator.c index 9afe961a87f1eb864e83fcc84130721378c627fc..e9719a378a0bc10d9333b8f9674b3496ce2250d5 100644 --- a/drivers/regulator/rpi-panel-attiny-regulator.c +++ b/drivers/regulator/rpi-panel-attiny-regulator.c @@ -399,7 +399,7 @@ static struct i2c_driver attiny_regulator_driver = { .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = of_match_ptr(attiny_dt_ids), }, - .probe_new = attiny_i2c_probe, + .probe = attiny_i2c_probe, .remove = attiny_i2c_remove, }; diff --git a/drivers/regulator/rt4801-regulator.c b/drivers/regulator/rt4801-regulator.c index be3dc981195cfb657a897ff29145e405161ecc14..4955bfea4e844ce41dcaaa24a461f1f8bb081a33 100644 --- a/drivers/regulator/rt4801-regulator.c +++ b/drivers/regulator/rt4801-regulator.c @@ -242,7 +242,7 @@ static struct i2c_driver rt4801_driver = { .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = of_match_ptr(rt4801_of_id), }, - .probe_new = rt4801_probe, + .probe = rt4801_probe, }; module_i2c_driver(rt4801_driver); diff --git a/drivers/regulator/rt5190a-regulator.c b/drivers/regulator/rt5190a-regulator.c index f6c12f87fb8d47103955fb18edcd4160d428170f..a53ed523b5d7d5f02c1d303eaf9ef684af9be514 100644 --- a/drivers/regulator/rt5190a-regulator.c +++ b/drivers/regulator/rt5190a-regulator.c @@ -508,7 +508,7 @@ static struct i2c_driver rt5190a_driver = { .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = rt5190a_device_table, }, - .probe_new = rt5190a_probe, + .probe = rt5190a_probe, }; module_i2c_driver(rt5190a_driver); diff --git a/drivers/regulator/rt5739.c b/drivers/regulator/rt5739.c index 74fc5bf6d87e00e831d1c2a4f4e7b70638df5faa..0ce6a1666752cd3a9bf1364703622943bd88445c 100644 --- a/drivers/regulator/rt5739.c +++ b/drivers/regulator/rt5739.c @@ -282,7 +282,7 @@ static struct i2c_driver rt5739_driver = { .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = rt5739_device_table, }, - .probe_new = rt5739_probe, + .probe = rt5739_probe, }; module_i2c_driver(rt5739_driver); diff --git a/drivers/regulator/rt5759-regulator.c b/drivers/regulator/rt5759-regulator.c index d5a42ad21a9a4797768a3031b68722e0fbc12c02..90555a9ef1b0c2845e1eaf1b3bcf44822880c7fa 100644 --- a/drivers/regulator/rt5759-regulator.c +++ b/drivers/regulator/rt5759-regulator.c @@ -362,7 +362,7 @@ static struct i2c_driver rt5759_driver = { .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = of_match_ptr(rt5759_device_table), }, - .probe_new = rt5759_probe, + .probe = rt5759_probe, }; module_i2c_driver(rt5759_driver); diff --git a/drivers/regulator/rt6160-regulator.c b/drivers/regulator/rt6160-regulator.c index 8990dac234605eb45019510ae53fd1967845b8b1..e2a0eee95c617694d2ea1db2e12c599797285c2e 100644 --- a/drivers/regulator/rt6160-regulator.c +++ b/drivers/regulator/rt6160-regulator.c @@ -311,7 +311,7 @@ static struct i2c_driver rt6160_driver = { .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = rt6160_of_match_table, }, - .probe_new = rt6160_probe, + .probe = rt6160_probe, }; module_i2c_driver(rt6160_driver); diff --git a/drivers/regulator/rt6190-regulator.c b/drivers/regulator/rt6190-regulator.c index ca91a1f6d3c817e8b8e84fd345d8560420988136..3883440295edf8acbe91e2b89d77841ad2c2c302 100644 --- a/drivers/regulator/rt6190-regulator.c +++ b/drivers/regulator/rt6190-regulator.c @@ -487,7 +487,7 @@ static struct i2c_driver rt6190_driver = { .of_match_table = rt6190_of_dev_table, .pm = pm_ptr(&rt6190_dev_pm), }, - .probe_new = rt6190_probe, + .probe = rt6190_probe, }; module_i2c_driver(rt6190_driver); diff --git a/drivers/regulator/rt6245-regulator.c b/drivers/regulator/rt6245-regulator.c index 8721d11c796422019a9be1e1c6f508e480a63888..1843ecec19229f09951be14d89e5b8b8f71da845 100644 --- a/drivers/regulator/rt6245-regulator.c +++ b/drivers/regulator/rt6245-regulator.c @@ -246,7 +246,7 @@ static struct i2c_driver rt6245_driver = { .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = rt6245_of_match_table, }, - .probe_new = rt6245_probe, + .probe = rt6245_probe, }; module_i2c_driver(rt6245_driver); diff --git a/drivers/regulator/rtmv20-regulator.c b/drivers/regulator/rtmv20-regulator.c index 7cbb812477e181e184f3934342ef404e05d94ff2..dfd1522637e433a301ee80d697d68ccc675326da 100644 --- a/drivers/regulator/rtmv20-regulator.c +++ b/drivers/regulator/rtmv20-regulator.c @@ -429,7 +429,7 @@ static struct i2c_driver rtmv20_driver = { .of_match_table = of_match_ptr(rtmv20_of_id), .pm = &rtmv20_pm, }, - .probe_new = rtmv20_probe, + .probe = rtmv20_probe, }; module_i2c_driver(rtmv20_driver); diff --git a/drivers/regulator/rtq2134-regulator.c b/drivers/regulator/rtq2134-regulator.c index ee1577dc3cfc0c8dc58932016b402c0914d2aa41..b7372cb2b97d7e1148e158fdbd84ac55764b2a50 100644 --- a/drivers/regulator/rtq2134-regulator.c +++ b/drivers/regulator/rtq2134-regulator.c @@ -366,7 +366,7 @@ static struct i2c_driver rtq2134_driver = { .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = rtq2134_device_tables, }, - .probe_new = rtq2134_probe, + .probe = rtq2134_probe, }; module_i2c_driver(rtq2134_driver); diff --git a/drivers/regulator/rtq6752-regulator.c b/drivers/regulator/rtq6752-regulator.c index 8559a266a7eb6e96c7fd4879bd176c58d413ec0c..8176e5ab068359d9094a4bcc511e18cd7e6764c1 100644 --- a/drivers/regulator/rtq6752-regulator.c +++ b/drivers/regulator/rtq6752-regulator.c @@ -281,7 +281,7 @@ static struct i2c_driver rtq6752_driver = { .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = rtq6752_device_table, }, - .probe_new = rtq6752_probe, + .probe = rtq6752_probe, }; module_i2c_driver(rtq6752_driver); diff --git a/drivers/regulator/slg51000-regulator.c b/drivers/regulator/slg51000-regulator.c index 559ae031010f23ae75eea00f90f9c142a0251625..59aa16825d8a607fed750e19baa7f5eeb37c7072 100644 --- a/drivers/regulator/slg51000-regulator.c +++ b/drivers/regulator/slg51000-regulator.c @@ -507,7 +507,7 @@ static struct i2c_driver slg51000_regulator_driver = { .name = "slg51000-regulator", .probe_type = PROBE_PREFER_ASYNCHRONOUS, }, - .probe_new = slg51000_i2c_probe, + .probe = slg51000_i2c_probe, .id_table = slg51000_i2c_id, }; diff --git a/drivers/regulator/stm32-pwr.c b/drivers/regulator/stm32-pwr.c index 0e101dff6ddadc069d9a0483393899a1bdc06e72..4c60eddad60d0a392804a6d996911f8bf6f66de6 100644 --- a/drivers/regulator/stm32-pwr.c +++ b/drivers/regulator/stm32-pwr.c @@ -93,7 +93,7 @@ static int stm32_pwr_reg_disable(struct regulator_dev *rdev) writel_relaxed(val, priv->base + REG_PWR_CR3); /* use an arbitrary timeout of 20ms */ - ret = readx_poll_timeout(stm32_pwr_reg_is_ready, rdev, val, !val, + ret = readx_poll_timeout(stm32_pwr_reg_is_enabled, rdev, val, !val, 100, 20 * 1000); if (ret) dev_err(&rdev->dev, "regulator disable timed out!\n"); diff --git a/drivers/regulator/sy8106a-regulator.c b/drivers/regulator/sy8106a-regulator.c index e3c753986309ce729152f633330a2c8c8355a315..1bcfdd6dcfc164d071077bddf03668dabf63b991 100644 --- a/drivers/regulator/sy8106a-regulator.c +++ b/drivers/regulator/sy8106a-regulator.c @@ -141,7 +141,7 @@ static struct i2c_driver sy8106a_regulator_driver = { .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = sy8106a_i2c_of_match, }, - .probe_new = sy8106a_i2c_probe, + .probe = sy8106a_i2c_probe, .id_table = sy8106a_i2c_id, }; diff --git a/drivers/regulator/sy8824x.c b/drivers/regulator/sy8824x.c index c327ad69f676b213c719f52ae9c6eacddeb587fb..d0703105c43993b840356fd70b48b26c459c9261 100644 --- a/drivers/regulator/sy8824x.c +++ b/drivers/regulator/sy8824x.c @@ -236,7 +236,7 @@ static struct i2c_driver sy8824_regulator_driver = { .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = sy8824_dt_ids, }, - .probe_new = sy8824_i2c_probe, + .probe = sy8824_i2c_probe, .id_table = sy8824_id, }; module_i2c_driver(sy8824_regulator_driver); diff --git a/drivers/regulator/sy8827n.c b/drivers/regulator/sy8827n.c index 99ca08cc3a6aef6c6ad9eab1ec13baf08ca9c846..433959b43549137312632793efd784ff08ce1f69 100644 --- a/drivers/regulator/sy8827n.c +++ b/drivers/regulator/sy8827n.c @@ -190,7 +190,7 @@ static struct i2c_driver sy8827n_regulator_driver = { .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = sy8827n_dt_ids, }, - .probe_new = sy8827n_i2c_probe, + .probe = sy8827n_i2c_probe, .id_table = sy8827n_id, }; module_i2c_driver(sy8827n_regulator_driver); diff --git a/drivers/regulator/tps51632-regulator.c b/drivers/regulator/tps51632-regulator.c index 9bd4e72914ed426d5ccb162e052d04fc58bb10df..d8a856c1587a36aeb147da79e5d6e72d008dff35 100644 --- a/drivers/regulator/tps51632-regulator.c +++ b/drivers/regulator/tps51632-regulator.c @@ -354,7 +354,7 @@ static struct i2c_driver tps51632_i2c_driver = { .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = of_match_ptr(tps51632_of_match), }, - .probe_new = tps51632_probe, + .probe = tps51632_probe, .id_table = tps51632_id, }; diff --git a/drivers/regulator/tps62360-regulator.c b/drivers/regulator/tps62360-regulator.c index 65cc08d1a67d644d34cc0f39d5246995aa9f9a1f..32e1a05a57fd6e1e82e35fd9a43706b432cba4e9 100644 --- a/drivers/regulator/tps62360-regulator.c +++ b/drivers/regulator/tps62360-regulator.c @@ -491,7 +491,7 @@ static struct i2c_driver tps62360_i2c_driver = { .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = of_match_ptr(tps62360_of_match), }, - .probe_new = tps62360_probe, + .probe = tps62360_probe, .shutdown = tps62360_shutdown, .id_table = tps62360_id, }; diff --git a/drivers/regulator/tps6286x-regulator.c b/drivers/regulator/tps6286x-regulator.c index f92e7649d0a064048aa2605b41a6f9e81f20220e..b1c4b5120745cc74b84c53432c4337a5a6765e39 100644 --- a/drivers/regulator/tps6286x-regulator.c +++ b/drivers/regulator/tps6286x-regulator.c @@ -150,7 +150,7 @@ static struct i2c_driver tps6286x_regulator_driver = { .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = of_match_ptr(tps6286x_dt_ids), }, - .probe_new = tps6286x_i2c_probe, + .probe = tps6286x_i2c_probe, .id_table = tps6286x_i2c_id, }; diff --git a/drivers/regulator/tps6287x-regulator.c b/drivers/regulator/tps6287x-regulator.c new file mode 100644 index 0000000000000000000000000000000000000000..b1c0963586acefbaaa13c1abe46924a42be3dcc8 --- /dev/null +++ b/drivers/regulator/tps6287x-regulator.c @@ -0,0 +1,189 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2023 Axis Communications AB + * + * Driver for Texas Instruments TPS6287x PMIC. + * Datasheet: https://www.ti.com/lit/ds/symlink/tps62873.pdf + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define TPS6287X_VSET 0x00 +#define TPS6287X_CTRL1 0x01 +#define TPS6287X_CTRL1_VRAMP GENMASK(1, 0) +#define TPS6287X_CTRL1_FPWMEN BIT(4) +#define TPS6287X_CTRL1_SWEN BIT(5) +#define TPS6287X_CTRL2 0x02 +#define TPS6287X_CTRL2_VRANGE GENMASK(3, 2) +#define TPS6287X_CTRL3 0x03 +#define TPS6287X_STATUS 0x04 + +static const struct regmap_config tps6287x_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = TPS6287X_STATUS, +}; + +static const struct linear_range tps6287x_voltage_ranges[] = { + LINEAR_RANGE(400000, 0, 0xFF, 1250), + LINEAR_RANGE(400000, 0, 0xFF, 2500), + LINEAR_RANGE(400000, 0, 0xFF, 5000), + LINEAR_RANGE(800000, 0, 0xFF, 10000), +}; + +static const unsigned int tps6287x_voltage_range_sel[] = { + 0x0, 0x4, 0x8, 0xC +}; + +static const unsigned int tps6287x_ramp_table[] = { + 10000, 5000, 1250, 500 +}; + +static int tps6287x_set_mode(struct regulator_dev *rdev, unsigned int mode) +{ + unsigned int val; + + switch (mode) { + case REGULATOR_MODE_NORMAL: + val = 0; + break; + case REGULATOR_MODE_FAST: + val = TPS6287X_CTRL1_FPWMEN; + break; + default: + return -EINVAL; + } + + return regmap_update_bits(rdev->regmap, TPS6287X_CTRL1, + TPS6287X_CTRL1_FPWMEN, val); +} + +static unsigned int tps6287x_get_mode(struct regulator_dev *rdev) +{ + unsigned int val; + int ret; + + ret = regmap_read(rdev->regmap, TPS6287X_CTRL1, &val); + if (ret < 0) + return 0; + + return (val & TPS6287X_CTRL1_FPWMEN) ? REGULATOR_MODE_FAST : + REGULATOR_MODE_NORMAL; +} + +static unsigned int tps6287x_of_map_mode(unsigned int mode) +{ + switch (mode) { + case REGULATOR_MODE_NORMAL: + case REGULATOR_MODE_FAST: + return mode; + default: + return REGULATOR_MODE_INVALID; + } +} + +static const struct regulator_ops tps6287x_regulator_ops = { + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .set_mode = tps6287x_set_mode, + .get_mode = tps6287x_get_mode, + .is_enabled = regulator_is_enabled_regmap, + .get_voltage_sel = regulator_get_voltage_sel_pickable_regmap, + .set_voltage_sel = regulator_set_voltage_sel_pickable_regmap, + .list_voltage = regulator_list_voltage_pickable_linear_range, + .set_ramp_delay = regulator_set_ramp_delay_regmap, +}; + +static struct regulator_desc tps6287x_reg = { + .name = "tps6287x", + .owner = THIS_MODULE, + .ops = &tps6287x_regulator_ops, + .of_map_mode = tps6287x_of_map_mode, + .type = REGULATOR_VOLTAGE, + .enable_reg = TPS6287X_CTRL1, + .enable_mask = TPS6287X_CTRL1_SWEN, + .vsel_reg = TPS6287X_VSET, + .vsel_mask = 0xFF, + .vsel_range_reg = TPS6287X_CTRL2, + .vsel_range_mask = TPS6287X_CTRL2_VRANGE, + .ramp_reg = TPS6287X_CTRL1, + .ramp_mask = TPS6287X_CTRL1_VRAMP, + .ramp_delay_table = tps6287x_ramp_table, + .n_ramp_values = ARRAY_SIZE(tps6287x_ramp_table), + .n_voltages = 256, + .linear_ranges = tps6287x_voltage_ranges, + .n_linear_ranges = ARRAY_SIZE(tps6287x_voltage_ranges), + .linear_range_selectors = tps6287x_voltage_range_sel, +}; + +static int tps6287x_i2c_probe(struct i2c_client *i2c) +{ + struct device *dev = &i2c->dev; + struct regulator_config config = {}; + struct regulator_dev *rdev; + + config.regmap = devm_regmap_init_i2c(i2c, &tps6287x_regmap_config); + if (IS_ERR(config.regmap)) { + dev_err(dev, "Failed to init i2c\n"); + return PTR_ERR(config.regmap); + } + + config.dev = dev; + config.of_node = dev->of_node; + config.init_data = of_get_regulator_init_data(dev, dev->of_node, + &tps6287x_reg); + + rdev = devm_regulator_register(dev, &tps6287x_reg, &config); + if (IS_ERR(rdev)) { + dev_err(dev, "Failed to register regulator\n"); + return PTR_ERR(rdev); + } + + dev_dbg(dev, "Probed regulator\n"); + + return 0; +} + +static const struct of_device_id tps6287x_dt_ids[] = { + { .compatible = "ti,tps62870", }, + { .compatible = "ti,tps62871", }, + { .compatible = "ti,tps62872", }, + { .compatible = "ti,tps62873", }, + { } +}; + +MODULE_DEVICE_TABLE(of, tps6287x_dt_ids); + +static const struct i2c_device_id tps6287x_i2c_id[] = { + { "tps62870", 0 }, + { "tps62871", 0 }, + { "tps62872", 0 }, + { "tps62873", 0 }, + {}, +}; + +MODULE_DEVICE_TABLE(i2c, tps6287x_i2c_id); + +static struct i2c_driver tps6287x_regulator_driver = { + .driver = { + .name = "tps6287x", + .of_match_table = tps6287x_dt_ids, + }, + .probe = tps6287x_i2c_probe, + .id_table = tps6287x_i2c_id, +}; + +module_i2c_driver(tps6287x_regulator_driver); + +MODULE_AUTHOR("Mårten Lindahl "); +MODULE_DESCRIPTION("Regulator driver for TI TPS6287X PMIC"); +MODULE_LICENSE("GPL"); diff --git a/drivers/regulator/tps65023-regulator.c b/drivers/regulator/tps65023-regulator.c index d87cac63f346a8af13b47c3e18ec005a8c414a06..d5757fd9a65bb1d0ecc1e398482b47288e520263 100644 --- a/drivers/regulator/tps65023-regulator.c +++ b/drivers/regulator/tps65023-regulator.c @@ -337,7 +337,7 @@ static struct i2c_driver tps_65023_i2c_driver = { .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = of_match_ptr(tps65023_of_match), }, - .probe_new = tps_65023_probe, + .probe = tps_65023_probe, .id_table = tps_65023_id, }; diff --git a/drivers/regulator/tps65132-regulator.c b/drivers/regulator/tps65132-regulator.c index d4b02ee791d1386d0dce1ac2873e7cf87f28a29c..a06f5f2d79329d615807fcc51064705accfdcc63 100644 --- a/drivers/regulator/tps65132-regulator.c +++ b/drivers/regulator/tps65132-regulator.c @@ -272,7 +272,7 @@ static struct i2c_driver tps65132_i2c_driver = { .name = "tps65132", .probe_type = PROBE_PREFER_ASYNCHRONOUS, }, - .probe_new = tps65132_probe, + .probe = tps65132_probe, .id_table = tps65132_id, }; diff --git a/drivers/regulator/tps65219-regulator.c b/drivers/regulator/tps65219-regulator.c index b1719ee990ab40b665c87b397fbfe85e14acd04c..8971b507a79ac15b721d237e58dd28a79235ad3f 100644 --- a/drivers/regulator/tps65219-regulator.c +++ b/drivers/regulator/tps65219-regulator.c @@ -289,13 +289,13 @@ static irqreturn_t tps65219_regulator_irq_handler(int irq, void *data) static int tps65219_get_rdev_by_name(const char *regulator_name, struct regulator_dev *rdevtbl[7], - struct regulator_dev *dev) + struct regulator_dev **dev) { int i; for (i = 0; i < ARRAY_SIZE(regulators); i++) { if (strcmp(regulator_name, regulators[i].name) == 0) { - dev = rdevtbl[i]; + *dev = rdevtbl[i]; return 0; } } @@ -348,7 +348,7 @@ static int tps65219_regulator_probe(struct platform_device *pdev) irq_data[i].dev = tps->dev; irq_data[i].type = irq_type; - tps65219_get_rdev_by_name(irq_type->regulator_name, rdevtbl, rdev); + tps65219_get_rdev_by_name(irq_type->regulator_name, rdevtbl, &rdev); if (IS_ERR(rdev)) { dev_err(tps->dev, "Failed to get rdev for %s\n", irq_type->regulator_name); diff --git a/drivers/regulator/tps6594-regulator.c b/drivers/regulator/tps6594-regulator.c new file mode 100644 index 0000000000000000000000000000000000000000..d5a574ec6d12f8007625299ecda4e3fdce110621 --- /dev/null +++ b/drivers/regulator/tps6594-regulator.c @@ -0,0 +1,615 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Regulator driver for tps6594 PMIC +// +// Copyright (C) 2023 BayLibre Incorporated - https://www.baylibre.com/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define BUCK_NB 5 +#define LDO_NB 4 +#define MULTI_PHASE_NB 4 +#define REGS_INT_NB 4 + +enum tps6594_regulator_id { + /* DCDC's */ + TPS6594_BUCK_1, + TPS6594_BUCK_2, + TPS6594_BUCK_3, + TPS6594_BUCK_4, + TPS6594_BUCK_5, + + /* LDOs */ + TPS6594_LDO_1, + TPS6594_LDO_2, + TPS6594_LDO_3, + TPS6594_LDO_4, +}; + +enum tps6594_multi_regulator_id { + /* Multi-phase DCDC's */ + TPS6594_BUCK_12, + TPS6594_BUCK_34, + TPS6594_BUCK_123, + TPS6594_BUCK_1234, +}; + +struct tps6594_regulator_irq_type { + const char *irq_name; + const char *regulator_name; + const char *event_name; + unsigned long event; +}; + +static struct tps6594_regulator_irq_type tps6594_ext_regulator_irq_types[] = { + { TPS6594_IRQ_NAME_VCCA_OV, "VCCA", "overvoltage", REGULATOR_EVENT_OVER_VOLTAGE_WARN }, + { TPS6594_IRQ_NAME_VCCA_UV, "VCCA", "undervoltage", REGULATOR_EVENT_UNDER_VOLTAGE }, + { TPS6594_IRQ_NAME_VMON1_OV, "VMON1", "overvoltage", REGULATOR_EVENT_OVER_VOLTAGE_WARN }, + { TPS6594_IRQ_NAME_VMON1_UV, "VMON1", "undervoltage", REGULATOR_EVENT_UNDER_VOLTAGE }, + { TPS6594_IRQ_NAME_VMON1_RV, "VMON1", "residual voltage", + REGULATOR_EVENT_OVER_VOLTAGE_WARN }, + { TPS6594_IRQ_NAME_VMON2_OV, "VMON2", "overvoltage", REGULATOR_EVENT_OVER_VOLTAGE_WARN }, + { TPS6594_IRQ_NAME_VMON2_UV, "VMON2", "undervoltage", REGULATOR_EVENT_UNDER_VOLTAGE }, + { TPS6594_IRQ_NAME_VMON2_RV, "VMON2", "residual voltage", + REGULATOR_EVENT_OVER_VOLTAGE_WARN }, +}; + +struct tps6594_regulator_irq_data { + struct device *dev; + struct tps6594_regulator_irq_type *type; + struct regulator_dev *rdev; +}; + +struct tps6594_ext_regulator_irq_data { + struct device *dev; + struct tps6594_regulator_irq_type *type; +}; + +#define TPS6594_REGULATOR(_name, _of, _id, _type, _ops, _n, _vr, _vm, _er, \ + _em, _cr, _cm, _lr, _nlr, _delay, _fuv, \ + _ct, _ncl, _bpm) \ + { \ + .name = _name, \ + .of_match = _of, \ + .regulators_node = of_match_ptr("regulators"), \ + .supply_name = _of, \ + .id = _id, \ + .ops = &(_ops), \ + .n_voltages = _n, \ + .type = _type, \ + .owner = THIS_MODULE, \ + .vsel_reg = _vr, \ + .vsel_mask = _vm, \ + .csel_reg = _cr, \ + .csel_mask = _cm, \ + .curr_table = _ct, \ + .n_current_limits = _ncl, \ + .enable_reg = _er, \ + .enable_mask = _em, \ + .volt_table = NULL, \ + .linear_ranges = _lr, \ + .n_linear_ranges = _nlr, \ + .ramp_delay = _delay, \ + .fixed_uV = _fuv, \ + .bypass_reg = _vr, \ + .bypass_mask = _bpm, \ + } \ + +static const struct linear_range bucks_ranges[] = { + REGULATOR_LINEAR_RANGE(300000, 0x0, 0xe, 20000), + REGULATOR_LINEAR_RANGE(600000, 0xf, 0x72, 5000), + REGULATOR_LINEAR_RANGE(1100000, 0x73, 0xaa, 10000), + REGULATOR_LINEAR_RANGE(1660000, 0xab, 0xff, 20000), +}; + +static const struct linear_range ldos_1_2_3_ranges[] = { + REGULATOR_LINEAR_RANGE(600000, 0x4, 0x3a, 50000), +}; + +static const struct linear_range ldos_4_ranges[] = { + REGULATOR_LINEAR_RANGE(1200000, 0x20, 0x74, 25000), +}; + +/* Operations permitted on BUCK1/2/3/4/5 */ +static const struct regulator_ops tps6594_bucks_ops = { + .is_enabled = regulator_is_enabled_regmap, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .list_voltage = regulator_list_voltage_linear_range, + .map_voltage = regulator_map_voltage_linear_range, + .set_voltage_time_sel = regulator_set_voltage_time_sel, + +}; + +/* Operations permitted on LDO1/2/3 */ +static const struct regulator_ops tps6594_ldos_1_2_3_ops = { + .is_enabled = regulator_is_enabled_regmap, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .list_voltage = regulator_list_voltage_linear_range, + .map_voltage = regulator_map_voltage_linear_range, + .set_bypass = regulator_set_bypass_regmap, + .get_bypass = regulator_get_bypass_regmap, +}; + +/* Operations permitted on LDO4 */ +static const struct regulator_ops tps6594_ldos_4_ops = { + .is_enabled = regulator_is_enabled_regmap, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .list_voltage = regulator_list_voltage_linear_range, + .map_voltage = regulator_map_voltage_linear_range, +}; + +static const struct regulator_desc buck_regs[] = { + TPS6594_REGULATOR("BUCK1", "buck1", TPS6594_BUCK_1, + REGULATOR_VOLTAGE, tps6594_bucks_ops, TPS6594_MASK_BUCKS_VSET, + TPS6594_REG_BUCKX_VOUT_1(0), + TPS6594_MASK_BUCKS_VSET, + TPS6594_REG_BUCKX_CTRL(0), + TPS6594_BIT_BUCK_EN, 0, 0, bucks_ranges, + 4, 0, 0, NULL, 0, 0), + TPS6594_REGULATOR("BUCK2", "buck2", TPS6594_BUCK_2, + REGULATOR_VOLTAGE, tps6594_bucks_ops, TPS6594_MASK_BUCKS_VSET, + TPS6594_REG_BUCKX_VOUT_1(1), + TPS6594_MASK_BUCKS_VSET, + TPS6594_REG_BUCKX_CTRL(1), + TPS6594_BIT_BUCK_EN, 0, 0, bucks_ranges, + 4, 0, 0, NULL, 0, 0), + TPS6594_REGULATOR("BUCK3", "buck3", TPS6594_BUCK_3, + REGULATOR_VOLTAGE, tps6594_bucks_ops, TPS6594_MASK_BUCKS_VSET, + TPS6594_REG_BUCKX_VOUT_1(2), + TPS6594_MASK_BUCKS_VSET, + TPS6594_REG_BUCKX_CTRL(2), + TPS6594_BIT_BUCK_EN, 0, 0, bucks_ranges, + 4, 0, 0, NULL, 0, 0), + TPS6594_REGULATOR("BUCK4", "buck4", TPS6594_BUCK_4, + REGULATOR_VOLTAGE, tps6594_bucks_ops, TPS6594_MASK_BUCKS_VSET, + TPS6594_REG_BUCKX_VOUT_1(3), + TPS6594_MASK_BUCKS_VSET, + TPS6594_REG_BUCKX_CTRL(3), + TPS6594_BIT_BUCK_EN, 0, 0, bucks_ranges, + 4, 0, 0, NULL, 0, 0), + TPS6594_REGULATOR("BUCK5", "buck5", TPS6594_BUCK_5, + REGULATOR_VOLTAGE, tps6594_bucks_ops, TPS6594_MASK_BUCKS_VSET, + TPS6594_REG_BUCKX_VOUT_1(4), + TPS6594_MASK_BUCKS_VSET, + TPS6594_REG_BUCKX_CTRL(4), + TPS6594_BIT_BUCK_EN, 0, 0, bucks_ranges, + 4, 0, 0, NULL, 0, 0), +}; + +static struct tps6594_regulator_irq_type tps6594_buck1_irq_types[] = { + { TPS6594_IRQ_NAME_BUCK1_OV, "BUCK1", "overvoltage", REGULATOR_EVENT_OVER_VOLTAGE_WARN }, + { TPS6594_IRQ_NAME_BUCK1_UV, "BUCK1", "undervoltage", REGULATOR_EVENT_UNDER_VOLTAGE }, + { TPS6594_IRQ_NAME_BUCK1_SC, "BUCK1", "short circuit", REGULATOR_EVENT_REGULATION_OUT }, + { TPS6594_IRQ_NAME_BUCK1_ILIM, "BUCK1", "reach ilim, overcurrent", + REGULATOR_EVENT_OVER_CURRENT }, +}; + +static struct tps6594_regulator_irq_type tps6594_buck2_irq_types[] = { + { TPS6594_IRQ_NAME_BUCK2_OV, "BUCK2", "overvoltage", REGULATOR_EVENT_OVER_VOLTAGE_WARN }, + { TPS6594_IRQ_NAME_BUCK2_UV, "BUCK2", "undervoltage", REGULATOR_EVENT_UNDER_VOLTAGE }, + { TPS6594_IRQ_NAME_BUCK2_SC, "BUCK2", "short circuit", REGULATOR_EVENT_REGULATION_OUT }, + { TPS6594_IRQ_NAME_BUCK2_ILIM, "BUCK2", "reach ilim, overcurrent", + REGULATOR_EVENT_OVER_CURRENT }, +}; + +static struct tps6594_regulator_irq_type tps6594_buck3_irq_types[] = { + { TPS6594_IRQ_NAME_BUCK3_OV, "BUCK3", "overvoltage", REGULATOR_EVENT_OVER_VOLTAGE_WARN }, + { TPS6594_IRQ_NAME_BUCK3_UV, "BUCK3", "undervoltage", REGULATOR_EVENT_UNDER_VOLTAGE }, + { TPS6594_IRQ_NAME_BUCK3_SC, "BUCK3", "short circuit", REGULATOR_EVENT_REGULATION_OUT }, + { TPS6594_IRQ_NAME_BUCK3_ILIM, "BUCK3", "reach ilim, overcurrent", + REGULATOR_EVENT_OVER_CURRENT }, +}; + +static struct tps6594_regulator_irq_type tps6594_buck4_irq_types[] = { + { TPS6594_IRQ_NAME_BUCK4_OV, "BUCK4", "overvoltage", REGULATOR_EVENT_OVER_VOLTAGE_WARN }, + { TPS6594_IRQ_NAME_BUCK4_UV, "BUCK4", "undervoltage", REGULATOR_EVENT_UNDER_VOLTAGE }, + { TPS6594_IRQ_NAME_BUCK4_SC, "BUCK4", "short circuit", REGULATOR_EVENT_REGULATION_OUT }, + { TPS6594_IRQ_NAME_BUCK4_ILIM, "BUCK4", "reach ilim, overcurrent", + REGULATOR_EVENT_OVER_CURRENT }, +}; + +static struct tps6594_regulator_irq_type tps6594_buck5_irq_types[] = { + { TPS6594_IRQ_NAME_BUCK5_OV, "BUCK5", "overvoltage", REGULATOR_EVENT_OVER_VOLTAGE_WARN }, + { TPS6594_IRQ_NAME_BUCK5_UV, "BUCK5", "undervoltage", REGULATOR_EVENT_UNDER_VOLTAGE }, + { TPS6594_IRQ_NAME_BUCK5_SC, "BUCK5", "short circuit", REGULATOR_EVENT_REGULATION_OUT }, + { TPS6594_IRQ_NAME_BUCK5_ILIM, "BUCK5", "reach ilim, overcurrent", + REGULATOR_EVENT_OVER_CURRENT }, +}; + +static struct tps6594_regulator_irq_type tps6594_ldo1_irq_types[] = { + { TPS6594_IRQ_NAME_LDO1_OV, "LDO1", "overvoltage", REGULATOR_EVENT_OVER_VOLTAGE_WARN }, + { TPS6594_IRQ_NAME_LDO1_UV, "LDO1", "undervoltage", REGULATOR_EVENT_UNDER_VOLTAGE }, + { TPS6594_IRQ_NAME_LDO1_SC, "LDO1", "short circuit", REGULATOR_EVENT_REGULATION_OUT }, + { TPS6594_IRQ_NAME_LDO1_ILIM, "LDO1", "reach ilim, overcurrent", + REGULATOR_EVENT_OVER_CURRENT }, +}; + +static struct tps6594_regulator_irq_type tps6594_ldo2_irq_types[] = { + { TPS6594_IRQ_NAME_LDO2_OV, "LDO2", "overvoltage", REGULATOR_EVENT_OVER_VOLTAGE_WARN }, + { TPS6594_IRQ_NAME_LDO2_UV, "LDO2", "undervoltage", REGULATOR_EVENT_UNDER_VOLTAGE }, + { TPS6594_IRQ_NAME_LDO2_SC, "LDO2", "short circuit", REGULATOR_EVENT_REGULATION_OUT }, + { TPS6594_IRQ_NAME_LDO2_ILIM, "LDO2", "reach ilim, overcurrent", + REGULATOR_EVENT_OVER_CURRENT }, +}; + +static struct tps6594_regulator_irq_type tps6594_ldo3_irq_types[] = { + { TPS6594_IRQ_NAME_LDO3_OV, "LDO3", "overvoltage", REGULATOR_EVENT_OVER_VOLTAGE_WARN }, + { TPS6594_IRQ_NAME_LDO3_UV, "LDO3", "undervoltage", REGULATOR_EVENT_UNDER_VOLTAGE }, + { TPS6594_IRQ_NAME_LDO3_SC, "LDO3", "short circuit", REGULATOR_EVENT_REGULATION_OUT }, + { TPS6594_IRQ_NAME_LDO3_ILIM, "LDO3", "reach ilim, overcurrent", + REGULATOR_EVENT_OVER_CURRENT }, +}; + +static struct tps6594_regulator_irq_type tps6594_ldo4_irq_types[] = { + { TPS6594_IRQ_NAME_LDO4_OV, "LDO4", "overvoltage", REGULATOR_EVENT_OVER_VOLTAGE_WARN }, + { TPS6594_IRQ_NAME_LDO4_UV, "LDO4", "undervoltage", REGULATOR_EVENT_UNDER_VOLTAGE }, + { TPS6594_IRQ_NAME_LDO4_SC, "LDO4", "short circuit", REGULATOR_EVENT_REGULATION_OUT }, + { TPS6594_IRQ_NAME_LDO4_ILIM, "LDO4", "reach ilim, overcurrent", + REGULATOR_EVENT_OVER_CURRENT }, +}; + +static struct tps6594_regulator_irq_type *tps6594_bucks_irq_types[] = { + tps6594_buck1_irq_types, + tps6594_buck2_irq_types, + tps6594_buck3_irq_types, + tps6594_buck4_irq_types, + tps6594_buck5_irq_types, +}; + +static struct tps6594_regulator_irq_type *tps6594_ldos_irq_types[] = { + tps6594_ldo1_irq_types, + tps6594_ldo2_irq_types, + tps6594_ldo3_irq_types, + tps6594_ldo4_irq_types, +}; + +static const struct regulator_desc multi_regs[] = { + TPS6594_REGULATOR("BUCK12", "buck12", TPS6594_BUCK_1, + REGULATOR_VOLTAGE, tps6594_bucks_ops, TPS6594_MASK_BUCKS_VSET, + TPS6594_REG_BUCKX_VOUT_1(1), + TPS6594_MASK_BUCKS_VSET, + TPS6594_REG_BUCKX_CTRL(1), + TPS6594_BIT_BUCK_EN, 0, 0, bucks_ranges, + 4, 4000, 0, NULL, 0, 0), + TPS6594_REGULATOR("BUCK34", "buck34", TPS6594_BUCK_3, + REGULATOR_VOLTAGE, tps6594_bucks_ops, TPS6594_MASK_BUCKS_VSET, + TPS6594_REG_BUCKX_VOUT_1(3), + TPS6594_MASK_BUCKS_VSET, + TPS6594_REG_BUCKX_CTRL(3), + TPS6594_BIT_BUCK_EN, 0, 0, bucks_ranges, + 4, 0, 0, NULL, 0, 0), + TPS6594_REGULATOR("BUCK123", "buck123", TPS6594_BUCK_1, + REGULATOR_VOLTAGE, tps6594_bucks_ops, TPS6594_MASK_BUCKS_VSET, + TPS6594_REG_BUCKX_VOUT_1(1), + TPS6594_MASK_BUCKS_VSET, + TPS6594_REG_BUCKX_CTRL(1), + TPS6594_BIT_BUCK_EN, 0, 0, bucks_ranges, + 4, 4000, 0, NULL, 0, 0), + TPS6594_REGULATOR("BUCK1234", "buck1234", TPS6594_BUCK_1, + REGULATOR_VOLTAGE, tps6594_bucks_ops, TPS6594_MASK_BUCKS_VSET, + TPS6594_REG_BUCKX_VOUT_1(1), + TPS6594_MASK_BUCKS_VSET, + TPS6594_REG_BUCKX_CTRL(1), + TPS6594_BIT_BUCK_EN, 0, 0, bucks_ranges, + 4, 4000, 0, NULL, 0, 0), +}; + +static const struct regulator_desc ldo_regs[] = { + TPS6594_REGULATOR("LDO1", "ldo1", TPS6594_LDO_1, + REGULATOR_VOLTAGE, tps6594_ldos_1_2_3_ops, TPS6594_MASK_LDO123_VSET, + TPS6594_REG_LDOX_VOUT(0), + TPS6594_MASK_LDO123_VSET, + TPS6594_REG_LDOX_CTRL(0), + TPS6594_BIT_LDO_EN, 0, 0, ldos_1_2_3_ranges, + 1, 0, 0, NULL, 0, TPS6594_BIT_LDO_BYPASS), + TPS6594_REGULATOR("LDO2", "ldo2", TPS6594_LDO_2, + REGULATOR_VOLTAGE, tps6594_ldos_1_2_3_ops, TPS6594_MASK_LDO123_VSET, + TPS6594_REG_LDOX_VOUT(1), + TPS6594_MASK_LDO123_VSET, + TPS6594_REG_LDOX_CTRL(1), + TPS6594_BIT_LDO_EN, 0, 0, ldos_1_2_3_ranges, + 1, 0, 0, NULL, 0, TPS6594_BIT_LDO_BYPASS), + TPS6594_REGULATOR("LDO3", "ldo3", TPS6594_LDO_3, + REGULATOR_VOLTAGE, tps6594_ldos_1_2_3_ops, TPS6594_MASK_LDO123_VSET, + TPS6594_REG_LDOX_VOUT(2), + TPS6594_MASK_LDO123_VSET, + TPS6594_REG_LDOX_CTRL(2), + TPS6594_BIT_LDO_EN, 0, 0, ldos_1_2_3_ranges, + 1, 0, 0, NULL, 0, TPS6594_BIT_LDO_BYPASS), + TPS6594_REGULATOR("LDO4", "ldo4", TPS6594_LDO_4, + REGULATOR_VOLTAGE, tps6594_ldos_4_ops, TPS6594_MASK_LDO4_VSET >> 1, + TPS6594_REG_LDOX_VOUT(3), + TPS6594_MASK_LDO4_VSET, + TPS6594_REG_LDOX_CTRL(3), + TPS6594_BIT_LDO_EN, 0, 0, ldos_4_ranges, + 1, 0, 0, NULL, 0, 0), +}; + +static irqreturn_t tps6594_regulator_irq_handler(int irq, void *data) +{ + struct tps6594_regulator_irq_data *irq_data = data; + + if (irq_data->type->event_name[0] == '\0') { + /* This is the timeout interrupt no specific regulator */ + dev_err(irq_data->dev, + "System was put in shutdown due to timeout during an active or standby transition.\n"); + return IRQ_HANDLED; + } + + dev_err(irq_data->dev, "Error IRQ trap %s for %s\n", + irq_data->type->event_name, irq_data->type->regulator_name); + + regulator_notifier_call_chain(irq_data->rdev, + irq_data->type->event, NULL); + + return IRQ_HANDLED; +} + +static int tps6594_request_reg_irqs(struct platform_device *pdev, + struct regulator_dev *rdev, + struct tps6594_regulator_irq_data *irq_data, + struct tps6594_regulator_irq_type *tps6594_regs_irq_types, + int *irq_idx) +{ + struct tps6594_regulator_irq_type *irq_type; + struct tps6594 *tps = dev_get_drvdata(pdev->dev.parent); + int j; + int irq; + int error; + + for (j = 0; j < REGS_INT_NB; j++) { + irq_type = &tps6594_regs_irq_types[j]; + irq = platform_get_irq_byname(pdev, irq_type->irq_name); + if (irq < 0) + return -EINVAL; + + irq_data[*irq_idx + j].dev = tps->dev; + irq_data[*irq_idx + j].type = irq_type; + irq_data[*irq_idx + j].rdev = rdev; + + error = devm_request_threaded_irq(tps->dev, irq, NULL, + tps6594_regulator_irq_handler, + IRQF_ONESHOT, + irq_type->irq_name, + &irq_data[*irq_idx]); + (*irq_idx)++; + if (error) { + dev_err(tps->dev, "tps6594 failed to request %s IRQ %d: %d\n", + irq_type->irq_name, irq, error); + return error; + } + } + return 0; +} + +static int tps6594_regulator_probe(struct platform_device *pdev) +{ + struct tps6594 *tps = dev_get_drvdata(pdev->dev.parent); + struct regulator_dev *rdev; + struct device_node *np = NULL; + struct device_node *np_pmic_parent = NULL; + struct regulator_config config = {}; + struct tps6594_regulator_irq_data *irq_data; + struct tps6594_ext_regulator_irq_data *irq_ext_reg_data; + struct tps6594_regulator_irq_type *irq_type; + u8 buck_configured[BUCK_NB] = { 0 }; + u8 buck_multi[MULTI_PHASE_NB] = { 0 }; + static const char * const multiphases[] = {"buck12", "buck123", "buck1234", "buck34"}; + static const char *npname; + int error, i, irq, multi, delta; + int irq_idx = 0; + int buck_idx = 0; + int ext_reg_irq_nb = 2; + + enum { + MULTI_BUCK12, + MULTI_BUCK123, + MULTI_BUCK1234, + MULTI_BUCK12_34, + MULTI_FIRST = MULTI_BUCK12, + MULTI_LAST = MULTI_BUCK12_34, + MULTI_NUM = MULTI_LAST - MULTI_FIRST + 1 + }; + + config.dev = tps->dev; + config.driver_data = tps; + config.regmap = tps->regmap; + + /* + * Switch case defines different possible multi phase config + * This is based on dts buck node name. + * Buck node name must be chosen accordingly. + * Default case is no Multiphase buck. + * In case of Multiphase configuration, value should be defined for + * buck_configured to avoid creating bucks for every buck in multiphase + */ + for (multi = MULTI_FIRST; multi < MULTI_NUM; multi++) { + np = of_find_node_by_name(tps->dev->of_node, multiphases[multi]); + npname = of_node_full_name(np); + np_pmic_parent = of_get_parent(of_get_parent(np)); + if (of_node_cmp(of_node_full_name(np_pmic_parent), tps->dev->of_node->full_name)) + continue; + delta = strcmp(npname, multiphases[multi]); + if (!delta) { + switch (multi) { + case MULTI_BUCK12: + buck_multi[0] = 1; + buck_configured[0] = 1; + buck_configured[1] = 1; + break; + /* multiphase buck34 is supported only with buck12 */ + case MULTI_BUCK12_34: + buck_multi[0] = 1; + buck_multi[1] = 1; + buck_configured[0] = 1; + buck_configured[1] = 1; + buck_configured[2] = 1; + buck_configured[3] = 1; + break; + case MULTI_BUCK123: + buck_multi[2] = 1; + buck_configured[0] = 1; + buck_configured[1] = 1; + buck_configured[2] = 1; + break; + case MULTI_BUCK1234: + buck_multi[3] = 1; + buck_configured[0] = 1; + buck_configured[1] = 1; + buck_configured[2] = 1; + buck_configured[3] = 1; + break; + } + } + } + + if (tps->chip_id == LP8764) + /* There is only 4 buck on LP8764 */ + buck_configured[4] = 1; + + irq_data = devm_kmalloc_array(tps->dev, + REGS_INT_NB * sizeof(struct tps6594_regulator_irq_data), + ARRAY_SIZE(tps6594_bucks_irq_types) + + ARRAY_SIZE(tps6594_ldos_irq_types), + GFP_KERNEL); + if (!irq_data) + return -ENOMEM; + + for (i = 0; i < MULTI_PHASE_NB; i++) { + if (buck_multi[i] == 0) + continue; + + rdev = devm_regulator_register(&pdev->dev, &multi_regs[i], &config); + if (IS_ERR(rdev)) + return dev_err_probe(tps->dev, PTR_ERR(rdev), + "failed to register %s regulator\n", + pdev->name); + + /* config multiphase buck12+buck34 */ + if (i == 1) + buck_idx = 2; + error = tps6594_request_reg_irqs(pdev, rdev, irq_data, + tps6594_bucks_irq_types[buck_idx], &irq_idx); + if (error) + return error; + error = tps6594_request_reg_irqs(pdev, rdev, irq_data, + tps6594_bucks_irq_types[buck_idx + 1], &irq_idx); + if (error) + return error; + + if (i == 2 || i == 3) { + error = tps6594_request_reg_irqs(pdev, rdev, irq_data, + tps6594_bucks_irq_types[buck_idx + 2], + &irq_idx); + if (error) + return error; + } + if (i == 3) { + error = tps6594_request_reg_irqs(pdev, rdev, irq_data, + tps6594_bucks_irq_types[buck_idx + 3], + &irq_idx); + if (error) + return error; + } + } + + for (i = 0; i < BUCK_NB; i++) { + if (buck_configured[i] == 1) + continue; + + rdev = devm_regulator_register(&pdev->dev, &buck_regs[i], &config); + if (IS_ERR(rdev)) + return dev_err_probe(tps->dev, PTR_ERR(rdev), + "failed to register %s regulator\n", + pdev->name); + + error = tps6594_request_reg_irqs(pdev, rdev, irq_data, + tps6594_bucks_irq_types[i], &irq_idx); + if (error) + return error; + } + + /* LP8764 dosen't have LDO */ + if (tps->chip_id != LP8764) { + for (i = 0; i < ARRAY_SIZE(ldo_regs); i++) { + rdev = devm_regulator_register(&pdev->dev, &ldo_regs[i], &config); + if (IS_ERR(rdev)) + return dev_err_probe(tps->dev, PTR_ERR(rdev), + "failed to register %s regulator\n", + pdev->name); + + error = tps6594_request_reg_irqs(pdev, rdev, irq_data, + tps6594_ldos_irq_types[i], + &irq_idx); + if (error) + return error; + } + } + + if (tps->chip_id == LP8764) + ext_reg_irq_nb = ARRAY_SIZE(tps6594_ext_regulator_irq_types); + + irq_ext_reg_data = devm_kmalloc_array(tps->dev, + ext_reg_irq_nb, + sizeof(struct tps6594_ext_regulator_irq_data), + GFP_KERNEL); + if (!irq_ext_reg_data) + return -ENOMEM; + + for (i = 0; i < ext_reg_irq_nb; ++i) { + irq_type = &tps6594_ext_regulator_irq_types[i]; + + irq = platform_get_irq_byname(pdev, irq_type->irq_name); + if (irq < 0) + return -EINVAL; + + irq_ext_reg_data[i].dev = tps->dev; + irq_ext_reg_data[i].type = irq_type; + + error = devm_request_threaded_irq(tps->dev, irq, NULL, + tps6594_regulator_irq_handler, + IRQF_ONESHOT, + irq_type->irq_name, + &irq_ext_reg_data[i]); + if (error) + return dev_err_probe(tps->dev, error, + "failed to request %s IRQ %d\n", + irq_type->irq_name, irq); + } + return 0; +} + +static struct platform_driver tps6594_regulator_driver = { + .driver = { + .name = "tps6594-regulator", + }, + .probe = tps6594_regulator_probe, +}; + +module_platform_driver(tps6594_regulator_driver); + +MODULE_ALIAS("platform:tps6594-regulator"); +MODULE_AUTHOR("Jerome Neanne "); +MODULE_DESCRIPTION("TPS6594 voltage regulator driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig index a850e9f486dd63d15091395382988cd3ea092843..48845dc8fa852d097d9ebb1df87b4f10758089f4 100644 --- a/drivers/remoteproc/Kconfig +++ b/drivers/remoteproc/Kconfig @@ -313,7 +313,7 @@ config ST_SLIM_REMOTEPROC config STM32_RPROC tristate "STM32 remoteproc support" - depends on ARCH_STM32 + depends on ARCH_STM32 || COMPILE_TEST depends on REMOTEPROC select MAILBOX help diff --git a/drivers/remoteproc/da8xx_remoteproc.c b/drivers/remoteproc/da8xx_remoteproc.c index 768217f0f5cd9f0ae90e727ba4c4ec4be7a0e3b1..9041a0e07fb257b7d4a3eafccf8febca8d5b8306 100644 --- a/drivers/remoteproc/da8xx_remoteproc.c +++ b/drivers/remoteproc/da8xx_remoteproc.c @@ -357,7 +357,7 @@ static int da8xx_rproc_probe(struct platform_device *pdev) return ret; } -static int da8xx_rproc_remove(struct platform_device *pdev) +static void da8xx_rproc_remove(struct platform_device *pdev) { struct rproc *rproc = platform_get_drvdata(pdev); struct da8xx_rproc *drproc = rproc->priv; @@ -374,8 +374,6 @@ static int da8xx_rproc_remove(struct platform_device *pdev) rproc_free(rproc); if (dev->of_node) of_reserved_mem_device_release(dev); - - return 0; } static const struct of_device_id davinci_rproc_of_match[] __maybe_unused = { @@ -386,7 +384,7 @@ MODULE_DEVICE_TABLE(of, davinci_rproc_of_match); static struct platform_driver da8xx_rproc_driver = { .probe = da8xx_rproc_probe, - .remove = da8xx_rproc_remove, + .remove_new = da8xx_rproc_remove, .driver = { .name = "davinci-rproc", .of_match_table = of_match_ptr(davinci_rproc_of_match), diff --git a/drivers/remoteproc/imx_dsp_rproc.c b/drivers/remoteproc/imx_dsp_rproc.c index cab06dbf37fb7d2b79eea151e5dc392746e3ac81..d95fa558618998b433b8c7467b6a1143cfa5131b 100644 --- a/drivers/remoteproc/imx_dsp_rproc.c +++ b/drivers/remoteproc/imx_dsp_rproc.c @@ -1161,7 +1161,7 @@ static int imx_dsp_rproc_probe(struct platform_device *pdev) return ret; } -static int imx_dsp_rproc_remove(struct platform_device *pdev) +static void imx_dsp_rproc_remove(struct platform_device *pdev) { struct rproc *rproc = platform_get_drvdata(pdev); struct imx_dsp_rproc *priv = rproc->priv; @@ -1170,8 +1170,6 @@ static int imx_dsp_rproc_remove(struct platform_device *pdev) rproc_del(rproc); imx_dsp_detach_pm_domains(priv); rproc_free(rproc); - - return 0; } /* pm runtime functions */ @@ -1243,7 +1241,7 @@ static void imx_dsp_load_firmware(const struct firmware *fw, void *context) release_firmware(fw); } -static __maybe_unused int imx_dsp_suspend(struct device *dev) +static int imx_dsp_suspend(struct device *dev) { struct rproc *rproc = dev_get_drvdata(dev); struct imx_dsp_rproc *priv = rproc->priv; @@ -1278,7 +1276,7 @@ static __maybe_unused int imx_dsp_suspend(struct device *dev) return pm_runtime_force_suspend(dev); } -static __maybe_unused int imx_dsp_resume(struct device *dev) +static int imx_dsp_resume(struct device *dev) { struct rproc *rproc = dev_get_drvdata(dev); int ret = 0; @@ -1312,9 +1310,8 @@ static __maybe_unused int imx_dsp_resume(struct device *dev) } static const struct dev_pm_ops imx_dsp_rproc_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(imx_dsp_suspend, imx_dsp_resume) - SET_RUNTIME_PM_OPS(imx_dsp_runtime_suspend, - imx_dsp_runtime_resume, NULL) + SYSTEM_SLEEP_PM_OPS(imx_dsp_suspend, imx_dsp_resume) + RUNTIME_PM_OPS(imx_dsp_runtime_suspend, imx_dsp_runtime_resume, NULL) }; static const struct of_device_id imx_dsp_rproc_of_match[] = { @@ -1328,11 +1325,11 @@ MODULE_DEVICE_TABLE(of, imx_dsp_rproc_of_match); static struct platform_driver imx_dsp_rproc_driver = { .probe = imx_dsp_rproc_probe, - .remove = imx_dsp_rproc_remove, + .remove_new = imx_dsp_rproc_remove, .driver = { .name = "imx-dsp-rproc", .of_match_table = imx_dsp_rproc_of_match, - .pm = &imx_dsp_rproc_pm_ops, + .pm = pm_ptr(&imx_dsp_rproc_pm_ops), }, }; module_platform_driver(imx_dsp_rproc_driver); diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c index 0ab840dc7e97f7d4bac652f81f4af1fbf6f7d88e..f9874fc5a80ff56cd448156d20e69b2ccc74a84d 100644 --- a/drivers/remoteproc/imx_rproc.c +++ b/drivers/remoteproc/imx_rproc.c @@ -1112,7 +1112,7 @@ static int imx_rproc_probe(struct platform_device *pdev) return ret; } -static int imx_rproc_remove(struct platform_device *pdev) +static void imx_rproc_remove(struct platform_device *pdev) { struct rproc *rproc = platform_get_drvdata(pdev); struct imx_rproc *priv = rproc->priv; @@ -1123,8 +1123,6 @@ static int imx_rproc_remove(struct platform_device *pdev) imx_rproc_free_mbox(rproc); destroy_workqueue(priv->workqueue); rproc_free(rproc); - - return 0; } static const struct of_device_id imx_rproc_of_match[] = { @@ -1145,7 +1143,7 @@ MODULE_DEVICE_TABLE(of, imx_rproc_of_match); static struct platform_driver imx_rproc_driver = { .probe = imx_rproc_probe, - .remove = imx_rproc_remove, + .remove_new = imx_rproc_remove, .driver = { .name = "imx-rproc", .of_match_table = imx_rproc_of_match, diff --git a/drivers/remoteproc/keystone_remoteproc.c b/drivers/remoteproc/keystone_remoteproc.c index 95b39741925dbf88a7f7534548ca86b71d2d3eed..7e57b90bcaf85cc249acb6bf478e77ef3c079efe 100644 --- a/drivers/remoteproc/keystone_remoteproc.c +++ b/drivers/remoteproc/keystone_remoteproc.c @@ -476,7 +476,7 @@ static int keystone_rproc_probe(struct platform_device *pdev) return ret; } -static int keystone_rproc_remove(struct platform_device *pdev) +static void keystone_rproc_remove(struct platform_device *pdev) { struct keystone_rproc *ksproc = platform_get_drvdata(pdev); @@ -486,8 +486,6 @@ static int keystone_rproc_remove(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); rproc_free(ksproc->rproc); of_reserved_mem_device_release(&pdev->dev); - - return 0; } static const struct of_device_id keystone_rproc_of_match[] = { @@ -501,7 +499,7 @@ MODULE_DEVICE_TABLE(of, keystone_rproc_of_match); static struct platform_driver keystone_rproc_driver = { .probe = keystone_rproc_probe, - .remove = keystone_rproc_remove, + .remove_new = keystone_rproc_remove, .driver = { .name = "keystone-rproc", .of_match_table = keystone_rproc_of_match, diff --git a/drivers/remoteproc/meson_mx_ao_arc.c b/drivers/remoteproc/meson_mx_ao_arc.c index 462cddab6518d73790f7ff2322093fdc3c8b2ca3..f6744b53832308a2b2a45455ecab1535ffa20cd8 100644 --- a/drivers/remoteproc/meson_mx_ao_arc.c +++ b/drivers/remoteproc/meson_mx_ao_arc.c @@ -228,15 +228,13 @@ static int meson_mx_ao_arc_rproc_probe(struct platform_device *pdev) return ret; } -static int meson_mx_ao_arc_rproc_remove(struct platform_device *pdev) +static void meson_mx_ao_arc_rproc_remove(struct platform_device *pdev) { struct rproc *rproc = platform_get_drvdata(pdev); struct meson_mx_ao_arc_rproc_priv *priv = rproc->priv; rproc_del(rproc); gen_pool_free(priv->sram_pool, priv->sram_va, priv->sram_size); - - return 0; } static const struct of_device_id meson_mx_ao_arc_rproc_match[] = { @@ -248,7 +246,7 @@ MODULE_DEVICE_TABLE(of, meson_mx_ao_arc_rproc_match); static struct platform_driver meson_mx_ao_arc_rproc_driver = { .probe = meson_mx_ao_arc_rproc_probe, - .remove = meson_mx_ao_arc_rproc_remove, + .remove_new = meson_mx_ao_arc_rproc_remove, .driver = { .name = "meson-mx-ao-arc-rproc", .of_match_table = meson_mx_ao_arc_rproc_match, diff --git a/drivers/remoteproc/mtk_scp.c b/drivers/remoteproc/mtk_scp.c index e1d93e63d7df6d1917bf57aadf5f60b3baa69c95..dcc94ee2458d8ef5f415c0ede6fdc144b7834168 100644 --- a/drivers/remoteproc/mtk_scp.c +++ b/drivers/remoteproc/mtk_scp.c @@ -913,7 +913,7 @@ static int scp_probe(struct platform_device *pdev) return ret; } -static int scp_remove(struct platform_device *pdev) +static void scp_remove(struct platform_device *pdev) { struct mtk_scp *scp = platform_get_drvdata(pdev); int i; @@ -925,8 +925,6 @@ static int scp_remove(struct platform_device *pdev) for (i = 0; i < SCP_IPI_MAX; i++) mutex_destroy(&scp->ipi_desc[i].lock); mutex_destroy(&scp->send_lock); - - return 0; } static const struct mtk_scp_of_data mt8183_of_data = { @@ -1003,7 +1001,7 @@ MODULE_DEVICE_TABLE(of, mtk_scp_of_match); static struct platform_driver mtk_scp_driver = { .probe = scp_probe, - .remove = scp_remove, + .remove_new = scp_remove, .driver = { .name = "mtk-scp", .of_match_table = mtk_scp_of_match, diff --git a/drivers/remoteproc/omap_remoteproc.c b/drivers/remoteproc/omap_remoteproc.c index 430fab0266eda7015825050d1b91228363c0dced..82ed90f03d91bf93f1fc45a6b49a3fddd60c64b0 100644 --- a/drivers/remoteproc/omap_remoteproc.c +++ b/drivers/remoteproc/omap_remoteproc.c @@ -1363,15 +1363,13 @@ static int omap_rproc_probe(struct platform_device *pdev) return ret; } -static int omap_rproc_remove(struct platform_device *pdev) +static void omap_rproc_remove(struct platform_device *pdev) { struct rproc *rproc = platform_get_drvdata(pdev); rproc_del(rproc); rproc_free(rproc); of_reserved_mem_device_release(&pdev->dev); - - return 0; } static const struct dev_pm_ops omap_rproc_pm_ops = { @@ -1382,7 +1380,7 @@ static const struct dev_pm_ops omap_rproc_pm_ops = { static struct platform_driver omap_rproc_driver = { .probe = omap_rproc_probe, - .remove = omap_rproc_remove, + .remove_new = omap_rproc_remove, .driver = { .name = "omap-rproc", .pm = &omap_rproc_pm_ops, diff --git a/drivers/remoteproc/pru_rproc.c b/drivers/remoteproc/pru_rproc.c index 095f66130f48e4972cd02a2e0375a9bb78da7e13..2874c8d324f79cb238eb23d9d1216fb9f9c4b7ec 100644 --- a/drivers/remoteproc/pru_rproc.c +++ b/drivers/remoteproc/pru_rproc.c @@ -81,21 +81,6 @@ enum pru_iomem { PRU_IOMEM_MAX, }; -/** - * enum pru_type - PRU core type identifier - * - * @PRU_TYPE_PRU: Programmable Real-time Unit - * @PRU_TYPE_RTU: Auxiliary Programmable Real-Time Unit - * @PRU_TYPE_TX_PRU: Transmit Programmable Real-Time Unit - * @PRU_TYPE_MAX: just keep this one at the end - */ -enum pru_type { - PRU_TYPE_PRU = 0, - PRU_TYPE_RTU, - PRU_TYPE_TX_PRU, - PRU_TYPE_MAX, -}; - /** * struct pru_private_data - device data for a PRU core * @type: type of the PRU core (PRU, RTU, Tx_PRU) @@ -1071,14 +1056,12 @@ static int pru_rproc_probe(struct platform_device *pdev) return 0; } -static int pru_rproc_remove(struct platform_device *pdev) +static void pru_rproc_remove(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct rproc *rproc = platform_get_drvdata(pdev); dev_dbg(dev, "%s: removing rproc %s\n", __func__, rproc->name); - - return 0; } static const struct pru_private_data pru_data = { @@ -1126,7 +1109,7 @@ static struct platform_driver pru_rproc_driver = { .suppress_bind_attrs = true, }, .probe = pru_rproc_probe, - .remove = pru_rproc_remove, + .remove_new = pru_rproc_remove, }; module_platform_driver(pru_rproc_driver); diff --git a/drivers/remoteproc/qcom_q6v5_adsp.c b/drivers/remoteproc/qcom_q6v5_adsp.c index d546ab9dc1413876a22aca6ac5cb251cd7f2422a..6777a3bd62264c2204bfb508385007cb10fbce9e 100644 --- a/drivers/remoteproc/qcom_q6v5_adsp.c +++ b/drivers/remoteproc/qcom_q6v5_adsp.c @@ -763,7 +763,7 @@ static int adsp_probe(struct platform_device *pdev) return ret; } -static int adsp_remove(struct platform_device *pdev) +static void adsp_remove(struct platform_device *pdev) { struct qcom_adsp *adsp = platform_get_drvdata(pdev); @@ -775,8 +775,6 @@ static int adsp_remove(struct platform_device *pdev) qcom_remove_ssr_subdev(adsp->rproc, &adsp->ssr_subdev); qcom_rproc_pds_detach(adsp, adsp->proxy_pds, adsp->proxy_pd_count); rproc_free(adsp->rproc); - - return 0; } static const struct adsp_pil_data adsp_resource_init = { @@ -859,7 +857,7 @@ MODULE_DEVICE_TABLE(of, adsp_of_match); static struct platform_driver adsp_pil_driver = { .probe = adsp_probe, - .remove = adsp_remove, + .remove_new = adsp_remove, .driver = { .name = "qcom_q6v5_adsp", .of_match_table = adsp_of_match, diff --git a/drivers/remoteproc/qcom_q6v5_mss.c b/drivers/remoteproc/qcom_q6v5_mss.c index 8e15e4f85de13a781bf6672d9bc560c6460b3dce..70bffc9f33f6cc833f4add2ac3b5f2da629ee176 100644 --- a/drivers/remoteproc/qcom_q6v5_mss.c +++ b/drivers/remoteproc/qcom_q6v5_mss.c @@ -2110,7 +2110,7 @@ static int q6v5_probe(struct platform_device *pdev) return ret; } -static int q6v5_remove(struct platform_device *pdev) +static void q6v5_remove(struct platform_device *pdev) { struct q6v5 *qproc = platform_get_drvdata(pdev); struct rproc *rproc = qproc->rproc; @@ -2128,8 +2128,6 @@ static int q6v5_remove(struct platform_device *pdev) q6v5_pds_detach(qproc, qproc->proxy_pds, qproc->proxy_pd_count); rproc_free(rproc); - - return 0; } static const struct rproc_hexagon_res sc7180_mss = { @@ -2482,7 +2480,7 @@ MODULE_DEVICE_TABLE(of, q6v5_of_match); static struct platform_driver q6v5_driver = { .probe = q6v5_probe, - .remove = q6v5_remove, + .remove_new = q6v5_remove, .driver = { .name = "qcom-q6v5-mss", .of_match_table = q6v5_of_match, diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c index e34d82b18a67b6a312c662d4423b2b3c68067be9..3153d82037e717a713dab0d7dd21fa967d583fb5 100644 --- a/drivers/remoteproc/qcom_q6v5_pas.c +++ b/drivers/remoteproc/qcom_q6v5_pas.c @@ -105,7 +105,7 @@ struct qcom_adsp { struct qcom_scm_pas_metadata dtb_pas_metadata; }; -void adsp_segment_dump(struct rproc *rproc, struct rproc_dump_segment *segment, +static void adsp_segment_dump(struct rproc *rproc, struct rproc_dump_segment *segment, void *dest, size_t offset, size_t size) { struct qcom_adsp *adsp = rproc->priv; @@ -754,7 +754,7 @@ static int adsp_probe(struct platform_device *pdev) return ret; } -static int adsp_remove(struct platform_device *pdev) +static void adsp_remove(struct platform_device *pdev) { struct qcom_adsp *adsp = platform_get_drvdata(pdev); @@ -769,8 +769,6 @@ static int adsp_remove(struct platform_device *pdev) adsp_pds_detach(adsp, adsp->proxy_pds, adsp->proxy_pd_count); device_init_wakeup(adsp->dev, false); rproc_free(adsp->rproc); - - return 0; } static const struct adsp_data adsp_resource_init = { @@ -1232,7 +1230,7 @@ MODULE_DEVICE_TABLE(of, adsp_of_match); static struct platform_driver adsp_driver = { .probe = adsp_probe, - .remove = adsp_remove, + .remove_new = adsp_remove, .driver = { .name = "qcom_q6v5_pas", .of_match_table = adsp_of_match, diff --git a/drivers/remoteproc/qcom_q6v5_wcss.c b/drivers/remoteproc/qcom_q6v5_wcss.c index ba24d745b2d65c692f4a611b5e65d72423831481..b437044aa12674b6169eed462b23c44d706877eb 100644 --- a/drivers/remoteproc/qcom_q6v5_wcss.c +++ b/drivers/remoteproc/qcom_q6v5_wcss.c @@ -1074,7 +1074,7 @@ static int q6v5_wcss_probe(struct platform_device *pdev) return ret; } -static int q6v5_wcss_remove(struct platform_device *pdev) +static void q6v5_wcss_remove(struct platform_device *pdev) { struct rproc *rproc = platform_get_drvdata(pdev); struct q6v5_wcss *wcss = rproc->priv; @@ -1082,8 +1082,6 @@ static int q6v5_wcss_remove(struct platform_device *pdev) qcom_q6v5_deinit(&wcss->q6v5); rproc_del(rproc); rproc_free(rproc); - - return 0; } static const struct wcss_data wcss_ipq8074_res_init = { @@ -1117,7 +1115,7 @@ MODULE_DEVICE_TABLE(of, q6v5_wcss_of_match); static struct platform_driver q6v5_wcss_driver = { .probe = q6v5_wcss_probe, - .remove = q6v5_wcss_remove, + .remove_new = q6v5_wcss_remove, .driver = { .name = "qcom-q6v5-wcss-pil", .of_match_table = q6v5_wcss_of_match, diff --git a/drivers/remoteproc/qcom_wcnss.c b/drivers/remoteproc/qcom_wcnss.c index 0fc3172650644c862c341677f2d38790da926c3a..1ed0647bc962d90f7ccdbfcb37aad4c66e026f7d 100644 --- a/drivers/remoteproc/qcom_wcnss.c +++ b/drivers/remoteproc/qcom_wcnss.c @@ -666,7 +666,7 @@ static int wcnss_probe(struct platform_device *pdev) return ret; } -static int wcnss_remove(struct platform_device *pdev) +static void wcnss_remove(struct platform_device *pdev) { struct qcom_wcnss *wcnss = platform_get_drvdata(pdev); @@ -678,8 +678,6 @@ static int wcnss_remove(struct platform_device *pdev) qcom_remove_smd_subdev(wcnss->rproc, &wcnss->smd_subdev); wcnss_release_pds(wcnss); rproc_free(wcnss->rproc); - - return 0; } static const struct of_device_id wcnss_of_match[] = { @@ -693,7 +691,7 @@ MODULE_DEVICE_TABLE(of, wcnss_of_match); static struct platform_driver wcnss_driver = { .probe = wcnss_probe, - .remove = wcnss_remove, + .remove_new = wcnss_remove, .driver = { .name = "qcom-wcnss-pil", .of_match_table = wcnss_of_match, diff --git a/drivers/remoteproc/rcar_rproc.c b/drivers/remoteproc/rcar_rproc.c index 1ff2a73ade90734ae928cff967840f08206bbed3..90e8769d5624869dd53ef9171e9d80cd3873b879 100644 --- a/drivers/remoteproc/rcar_rproc.c +++ b/drivers/remoteproc/rcar_rproc.c @@ -197,13 +197,11 @@ static int rcar_rproc_probe(struct platform_device *pdev) return ret; } -static int rcar_rproc_remove(struct platform_device *pdev) +static void rcar_rproc_remove(struct platform_device *pdev) { struct device *dev = &pdev->dev; pm_runtime_disable(dev); - - return 0; } static const struct of_device_id rcar_rproc_of_match[] = { @@ -215,7 +213,7 @@ MODULE_DEVICE_TABLE(of, rcar_rproc_of_match); static struct platform_driver rcar_rproc_driver = { .probe = rcar_rproc_probe, - .remove = rcar_rproc_remove, + .remove_new = rcar_rproc_remove, .driver = { .name = "rcar-rproc", .of_match_table = rcar_rproc_of_match, diff --git a/drivers/remoteproc/remoteproc_virtio.c b/drivers/remoteproc/remoteproc_virtio.c index 0e95525c1158156cf76b1cb71f78e582ddc74eeb..83d76915a6ad6f28f930b705c274dc82897b36de 100644 --- a/drivers/remoteproc/remoteproc_virtio.c +++ b/drivers/remoteproc/remoteproc_virtio.c @@ -569,7 +569,7 @@ static int rproc_virtio_probe(struct platform_device *pdev) return ret; } -static int rproc_virtio_remove(struct platform_device *pdev) +static void rproc_virtio_remove(struct platform_device *pdev) { struct rproc_vdev *rvdev = dev_get_drvdata(&pdev->dev); struct rproc *rproc = rvdev->rproc; @@ -588,14 +588,12 @@ static int rproc_virtio_remove(struct platform_device *pdev) dma_release_coherent_memory(&pdev->dev); put_device(&rproc->dev); - - return 0; } /* Platform driver */ static struct platform_driver rproc_virtio_driver = { .probe = rproc_virtio_probe, - .remove = rproc_virtio_remove, + .remove_new = rproc_virtio_remove, .driver = { .name = "rproc-virtio", }, diff --git a/drivers/remoteproc/st_remoteproc.c b/drivers/remoteproc/st_remoteproc.c index 3f1b8963639f0fd00bd9d91827a60797b1810f89..e3ce01d98b4c7d0fd710bfab1e8ca62839a656a8 100644 --- a/drivers/remoteproc/st_remoteproc.c +++ b/drivers/remoteproc/st_remoteproc.c @@ -448,7 +448,7 @@ static int st_rproc_probe(struct platform_device *pdev) return ret; } -static int st_rproc_remove(struct platform_device *pdev) +static void st_rproc_remove(struct platform_device *pdev) { struct rproc *rproc = platform_get_drvdata(pdev); struct st_rproc *ddata = rproc->priv; @@ -462,13 +462,11 @@ static int st_rproc_remove(struct platform_device *pdev) mbox_free_channel(ddata->mbox_chan[i]); rproc_free(rproc); - - return 0; } static struct platform_driver st_rproc_driver = { .probe = st_rproc_probe, - .remove = st_rproc_remove, + .remove_new = st_rproc_remove, .driver = { .name = "st-rproc", .of_match_table = of_match_ptr(st_rproc_match), diff --git a/drivers/remoteproc/stm32_rproc.c b/drivers/remoteproc/stm32_rproc.c index 8746cbb1f168d11d3ad6929903559b26139bc73a..cf073bac79f735b443226fa23e9044522198e1ee 100644 --- a/drivers/remoteproc/stm32_rproc.c +++ b/drivers/remoteproc/stm32_rproc.c @@ -79,6 +79,7 @@ struct stm32_mbox { struct stm32_rproc { struct reset_control *rst; + struct reset_control *hold_boot_rst; struct stm32_syscon hold_boot; struct stm32_syscon pdds; struct stm32_syscon m4_state; @@ -88,7 +89,7 @@ struct stm32_rproc { struct stm32_rproc_mem *rmems; struct stm32_mbox mb[MBOX_NB_MBX]; struct workqueue_struct *workqueue; - bool secured_soc; + bool hold_boot_smc; void __iomem *rsc_va; }; @@ -118,10 +119,10 @@ static int stm32_rproc_mem_alloc(struct rproc *rproc, struct device *dev = rproc->dev.parent; void *va; - dev_dbg(dev, "map memory: %pa+%x\n", &mem->dma, mem->len); + dev_dbg(dev, "map memory: %pad+%zx\n", &mem->dma, mem->len); va = ioremap_wc(mem->dma, mem->len); if (IS_ERR_OR_NULL(va)) { - dev_err(dev, "Unable to map memory region: %pa+%x\n", + dev_err(dev, "Unable to map memory region: %pad+0x%zx\n", &mem->dma, mem->len); return -ENOMEM; } @@ -413,13 +414,28 @@ static int stm32_rproc_set_hold_boot(struct rproc *rproc, bool hold) struct arm_smccc_res smc_res; int val, err; + /* + * Three ways to manage the hold boot + * - using SCMI: the hold boot is managed as a reset, + * - using Linux(no SCMI): the hold boot is managed as a syscon register + * - using SMC call (deprecated): use SMC reset interface + */ + val = hold ? HOLD_BOOT : RELEASE_BOOT; - if (IS_ENABLED(CONFIG_HAVE_ARM_SMCCC) && ddata->secured_soc) { + if (ddata->hold_boot_rst) { + /* Use the SCMI reset controller */ + if (!hold) + err = reset_control_deassert(ddata->hold_boot_rst); + else + err = reset_control_assert(ddata->hold_boot_rst); + } else if (IS_ENABLED(CONFIG_HAVE_ARM_SMCCC) && ddata->hold_boot_smc) { + /* Use the SMC call */ arm_smccc_smc(STM32_SMC_RCC, STM32_SMC_REG_WRITE, hold_boot.reg, val, 0, 0, 0, 0, &smc_res); err = smc_res.a0; } else { + /* Use syscon */ err = regmap_update_bits(hold_boot.map, hold_boot.reg, hold_boot.mask, val); } @@ -627,7 +643,7 @@ stm32_rproc_get_loaded_rsc_table(struct rproc *rproc, size_t *table_sz) ddata->rsc_va = devm_ioremap_wc(dev, rsc_pa, RSC_TBL_SIZE); if (IS_ERR_OR_NULL(ddata->rsc_va)) { - dev_err(dev, "Unable to map memory region: %pa+%zx\n", + dev_err(dev, "Unable to map memory region: %pa+%x\n", &rsc_pa, RSC_TBL_SIZE); ddata->rsc_va = NULL; return ERR_PTR(-ENOMEM); @@ -717,34 +733,52 @@ static int stm32_rproc_parse_dt(struct platform_device *pdev, dev_info(dev, "wdg irq registered\n"); } - ddata->rst = devm_reset_control_get_by_index(dev, 0); + ddata->rst = devm_reset_control_get_optional(dev, "mcu_rst"); + if (!ddata->rst) { + /* Try legacy fallback method: get it by index */ + ddata->rst = devm_reset_control_get_by_index(dev, 0); + } if (IS_ERR(ddata->rst)) return dev_err_probe(dev, PTR_ERR(ddata->rst), "failed to get mcu_reset\n"); /* - * if platform is secured the hold boot bit must be written by - * smc call and read normally. - * if not secure the hold boot bit could be read/write normally + * Three ways to manage the hold boot + * - using SCMI: the hold boot is managed as a reset + * The DT "reset-mames" property should be defined with 2 items: + * reset-names = "mcu_rst", "hold_boot"; + * - using SMC call (deprecated): use SMC reset interface + * The DT "reset-mames" property is optional, "st,syscfg-tz" is required + * - default(no SCMI, no SMC): the hold boot is managed as a syscon register + * The DT "reset-mames" property is optional, "st,syscfg-holdboot" is required */ - err = stm32_rproc_get_syscon(np, "st,syscfg-tz", &tz); - if (err) { - dev_err(dev, "failed to get tz syscfg\n"); - return err; - } - err = regmap_read(tz.map, tz.reg, &tzen); - if (err) { - dev_err(dev, "failed to read tzen\n"); - return err; + ddata->hold_boot_rst = devm_reset_control_get_optional(dev, "hold_boot"); + if (IS_ERR(ddata->hold_boot_rst)) + return dev_err_probe(dev, PTR_ERR(ddata->hold_boot_rst), + "failed to get hold_boot reset\n"); + + if (!ddata->hold_boot_rst && IS_ENABLED(CONFIG_HAVE_ARM_SMCCC)) { + /* Manage the MCU_BOOT using SMC call */ + err = stm32_rproc_get_syscon(np, "st,syscfg-tz", &tz); + if (!err) { + err = regmap_read(tz.map, tz.reg, &tzen); + if (err) { + dev_err(dev, "failed to read tzen\n"); + return err; + } + ddata->hold_boot_smc = tzen & tz.mask; + } } - ddata->secured_soc = tzen & tz.mask; - err = stm32_rproc_get_syscon(np, "st,syscfg-holdboot", - &ddata->hold_boot); - if (err) { - dev_err(dev, "failed to get hold boot\n"); - return err; + if (!ddata->hold_boot_rst && !ddata->hold_boot_smc) { + /* Default: hold boot manage it through the syscon controller */ + err = stm32_rproc_get_syscon(np, "st,syscfg-holdboot", + &ddata->hold_boot); + if (err) { + dev_err(dev, "failed to get hold boot\n"); + return err; + } } err = stm32_rproc_get_syscon(np, "st,syscfg-pdds", &ddata->pdds); @@ -867,7 +901,7 @@ static int stm32_rproc_probe(struct platform_device *pdev) return ret; } -static int stm32_rproc_remove(struct platform_device *pdev) +static void stm32_rproc_remove(struct platform_device *pdev) { struct rproc *rproc = platform_get_drvdata(pdev); struct stm32_rproc *ddata = rproc->priv; @@ -885,8 +919,6 @@ static int stm32_rproc_remove(struct platform_device *pdev) device_init_wakeup(dev, false); } rproc_free(rproc); - - return 0; } static int __maybe_unused stm32_rproc_suspend(struct device *dev) @@ -916,7 +948,7 @@ static SIMPLE_DEV_PM_OPS(stm32_rproc_pm_ops, static struct platform_driver stm32_rproc_driver = { .probe = stm32_rproc_probe, - .remove = stm32_rproc_remove, + .remove_new = stm32_rproc_remove, .driver = { .name = "stm32-rproc", .pm = &stm32_rproc_pm_ops, diff --git a/drivers/remoteproc/wkup_m3_rproc.c b/drivers/remoteproc/wkup_m3_rproc.c index a0c204cb09798f822a6e9001d7ba1881ba92b7ea..120dc7d2dac19e5abed0ba3cba22b8d0f4b81eb4 100644 --- a/drivers/remoteproc/wkup_m3_rproc.c +++ b/drivers/remoteproc/wkup_m3_rproc.c @@ -223,7 +223,7 @@ static int wkup_m3_rproc_probe(struct platform_device *pdev) return ret; } -static int wkup_m3_rproc_remove(struct platform_device *pdev) +static void wkup_m3_rproc_remove(struct platform_device *pdev) { struct rproc *rproc = platform_get_drvdata(pdev); @@ -231,8 +231,6 @@ static int wkup_m3_rproc_remove(struct platform_device *pdev) rproc_free(rproc); pm_runtime_put_sync(&pdev->dev); pm_runtime_disable(&pdev->dev); - - return 0; } #ifdef CONFIG_PM @@ -253,7 +251,7 @@ static const struct dev_pm_ops wkup_m3_rproc_pm_ops = { static struct platform_driver wkup_m3_rproc_driver = { .probe = wkup_m3_rproc_probe, - .remove = wkup_m3_rproc_remove, + .remove_new = wkup_m3_rproc_remove, .driver = { .name = "wkup_m3_rproc", .of_match_table = wkup_m3_rproc_of_match, diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig index 6aa8f243b30c66b3afb11e0d453e6d29ff73081c..ccd59ddd76100a51d56beec797d00bfa8156440b 100644 --- a/drivers/reset/Kconfig +++ b/drivers/reset/Kconfig @@ -143,8 +143,12 @@ config RESET_NPCM This enables the reset controller driver for Nuvoton NPCM BMC SoCs. -config RESET_OXNAS - bool +config RESET_NUVOTON_MA35D1 + bool "Nuvoton MA35D1 Reset Driver" + depends on ARCH_MA35 || COMPILE_TEST + default ARCH_MA35 + help + This enables the reset controller driver for Nuvoton MA35D1 SoC. config RESET_PISTACHIO bool "Pistachio Reset Driver" @@ -154,7 +158,8 @@ config RESET_PISTACHIO config RESET_POLARFIRE_SOC bool "Microchip PolarFire SoC (MPFS) Reset Driver" - depends on AUXILIARY_BUS && MCHP_CLK_MPFS + depends on MCHP_CLK_MPFS + select AUXILIARY_BUS default MCHP_CLK_MPFS help This driver supports peripheral reset for the Microchip PolarFire SoC diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile index 7fec5af6c9645011654b2ff0b61de759c1722c6e..8270da8a4baa62a3677eaf50cbd32ffa4c9450f2 100644 --- a/drivers/reset/Makefile +++ b/drivers/reset/Makefile @@ -21,7 +21,7 @@ obj-$(CONFIG_RESET_MCHP_SPARX5) += reset-microchip-sparx5.o obj-$(CONFIG_RESET_MESON) += reset-meson.o obj-$(CONFIG_RESET_MESON_AUDIO_ARB) += reset-meson-audio-arb.o obj-$(CONFIG_RESET_NPCM) += reset-npcm.o -obj-$(CONFIG_RESET_OXNAS) += reset-oxnas.o +obj-$(CONFIG_RESET_NUVOTON_MA35D1) += reset-ma35d1.o obj-$(CONFIG_RESET_PISTACHIO) += reset-pistachio.o obj-$(CONFIG_RESET_POLARFIRE_SOC) += reset-mpfs.o obj-$(CONFIG_RESET_QCOM_AOSS) += reset-qcom-aoss.o diff --git a/drivers/reset/reset-ath79.c b/drivers/reset/reset-ath79.c index e48d8fcb313330165d9523e57be0c3dcf9661dec..a8b8f5ea77ecd28ee8672be526ffdd6ea468b138 100644 --- a/drivers/reset/reset-ath79.c +++ b/drivers/reset/reset-ath79.c @@ -86,7 +86,6 @@ static int ath79_reset_restart_handler(struct notifier_block *nb, static int ath79_reset_probe(struct platform_device *pdev) { struct ath79_reset *ath79_reset; - struct resource *res; int err; ath79_reset = devm_kzalloc(&pdev->dev, @@ -96,8 +95,7 @@ static int ath79_reset_probe(struct platform_device *pdev) platform_set_drvdata(pdev, ath79_reset); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - ath79_reset->base = devm_ioremap_resource(&pdev->dev, res); + ath79_reset->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(ath79_reset->base)) return PTR_ERR(ath79_reset->base); diff --git a/drivers/reset/reset-axs10x.c b/drivers/reset/reset-axs10x.c index a854ef41364d60b9566c5340fa40fac6307d853f..115f69e0db3366f1c9ecdff79a4856812ea8603b 100644 --- a/drivers/reset/reset-axs10x.c +++ b/drivers/reset/reset-axs10x.c @@ -44,14 +44,12 @@ static const struct reset_control_ops axs10x_reset_ops = { static int axs10x_reset_probe(struct platform_device *pdev) { struct axs10x_rst *rst; - struct resource *mem; rst = devm_kzalloc(&pdev->dev, sizeof(*rst), GFP_KERNEL); if (!rst) return -ENOMEM; - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - rst->regs_rst = devm_ioremap_resource(&pdev->dev, mem); + rst->regs_rst = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(rst->regs_rst)) return PTR_ERR(rst->regs_rst); diff --git a/drivers/reset/reset-brcmstb-rescal.c b/drivers/reset/reset-brcmstb-rescal.c index 433fa0c40e477f8770229aeeb48c7c90a63c222e..823317772bacfa6d1695c922f0bb31a223fc6823 100644 --- a/drivers/reset/reset-brcmstb-rescal.c +++ b/drivers/reset/reset-brcmstb-rescal.c @@ -66,14 +66,12 @@ static const struct reset_control_ops brcm_rescal_reset_ops = { static int brcm_rescal_reset_probe(struct platform_device *pdev) { struct brcm_rescal_reset *data; - struct resource *res; data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); if (!data) return -ENOMEM; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - data->base = devm_ioremap_resource(&pdev->dev, res); + data->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(data->base)) return PTR_ERR(data->base); diff --git a/drivers/reset/reset-hsdk.c b/drivers/reset/reset-hsdk.c index 4c7b8647b49cadf14addd94cbd4378d73def3f96..98460e08752c6009bf63d6258b41167f7f4c90d2 100644 --- a/drivers/reset/reset-hsdk.c +++ b/drivers/reset/reset-hsdk.c @@ -92,19 +92,16 @@ static const struct reset_control_ops hsdk_reset_ops = { static int hsdk_reset_probe(struct platform_device *pdev) { struct hsdk_rst *rst; - struct resource *mem; rst = devm_kzalloc(&pdev->dev, sizeof(*rst), GFP_KERNEL); if (!rst) return -ENOMEM; - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - rst->regs_ctl = devm_ioremap_resource(&pdev->dev, mem); + rst->regs_ctl = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(rst->regs_ctl)) return PTR_ERR(rst->regs_ctl); - mem = platform_get_resource(pdev, IORESOURCE_MEM, 1); - rst->regs_rst = devm_ioremap_resource(&pdev->dev, mem); + rst->regs_rst = devm_platform_ioremap_resource(pdev, 1); if (IS_ERR(rst->regs_rst)) return PTR_ERR(rst->regs_rst); diff --git a/drivers/reset/reset-lpc18xx.c b/drivers/reset/reset-lpc18xx.c index 35d8dd4cccfc86c4184dd52305376d66ccb0786e..36ec95518905c4fc4c106ac31a8d5c258025e3fc 100644 --- a/drivers/reset/reset-lpc18xx.c +++ b/drivers/reset/reset-lpc18xx.c @@ -139,7 +139,6 @@ static const struct reset_control_ops lpc18xx_rgu_ops = { static int lpc18xx_rgu_probe(struct platform_device *pdev) { struct lpc18xx_rgu_data *rc; - struct resource *res; u32 fcclk, firc; int ret; @@ -147,8 +146,7 @@ static int lpc18xx_rgu_probe(struct platform_device *pdev) if (!rc) return -ENOMEM; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - rc->base = devm_ioremap_resource(&pdev->dev, res); + rc->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(rc->base)) return PTR_ERR(rc->base); diff --git a/drivers/reset/reset-ma35d1.c b/drivers/reset/reset-ma35d1.c new file mode 100644 index 0000000000000000000000000000000000000000..54e53863c98aaa4cc985e499318b204e889e62ec --- /dev/null +++ b/drivers/reset/reset-ma35d1.c @@ -0,0 +1,235 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2023 Nuvoton Technology Corp. + * Author: Chi-Fang Li + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct ma35d1_reset_data { + struct reset_controller_dev rcdev; + struct notifier_block restart_handler; + void __iomem *base; + /* protect registers against concurrent read-modify-write */ + spinlock_t lock; +}; + +static const struct { + u32 reg_ofs; + u32 bit; +} ma35d1_reset_map[] = { + [MA35D1_RESET_CHIP] = {0x20, 0}, + [MA35D1_RESET_CA35CR0] = {0x20, 1}, + [MA35D1_RESET_CA35CR1] = {0x20, 2}, + [MA35D1_RESET_CM4] = {0x20, 3}, + [MA35D1_RESET_PDMA0] = {0x20, 4}, + [MA35D1_RESET_PDMA1] = {0x20, 5}, + [MA35D1_RESET_PDMA2] = {0x20, 6}, + [MA35D1_RESET_PDMA3] = {0x20, 7}, + [MA35D1_RESET_DISP] = {0x20, 9}, + [MA35D1_RESET_VCAP0] = {0x20, 10}, + [MA35D1_RESET_VCAP1] = {0x20, 11}, + [MA35D1_RESET_GFX] = {0x20, 12}, + [MA35D1_RESET_VDEC] = {0x20, 13}, + [MA35D1_RESET_WHC0] = {0x20, 14}, + [MA35D1_RESET_WHC1] = {0x20, 15}, + [MA35D1_RESET_GMAC0] = {0x20, 16}, + [MA35D1_RESET_GMAC1] = {0x20, 17}, + [MA35D1_RESET_HWSEM] = {0x20, 18}, + [MA35D1_RESET_EBI] = {0x20, 19}, + [MA35D1_RESET_HSUSBH0] = {0x20, 20}, + [MA35D1_RESET_HSUSBH1] = {0x20, 21}, + [MA35D1_RESET_HSUSBD] = {0x20, 22}, + [MA35D1_RESET_USBHL] = {0x20, 23}, + [MA35D1_RESET_SDH0] = {0x20, 24}, + [MA35D1_RESET_SDH1] = {0x20, 25}, + [MA35D1_RESET_NAND] = {0x20, 26}, + [MA35D1_RESET_GPIO] = {0x20, 27}, + [MA35D1_RESET_MCTLP] = {0x20, 28}, + [MA35D1_RESET_MCTLC] = {0x20, 29}, + [MA35D1_RESET_DDRPUB] = {0x20, 30}, + [MA35D1_RESET_TMR0] = {0x24, 2}, + [MA35D1_RESET_TMR1] = {0x24, 3}, + [MA35D1_RESET_TMR2] = {0x24, 4}, + [MA35D1_RESET_TMR3] = {0x24, 5}, + [MA35D1_RESET_I2C0] = {0x24, 8}, + [MA35D1_RESET_I2C1] = {0x24, 9}, + [MA35D1_RESET_I2C2] = {0x24, 10}, + [MA35D1_RESET_I2C3] = {0x24, 11}, + [MA35D1_RESET_QSPI0] = {0x24, 12}, + [MA35D1_RESET_SPI0] = {0x24, 13}, + [MA35D1_RESET_SPI1] = {0x24, 14}, + [MA35D1_RESET_SPI2] = {0x24, 15}, + [MA35D1_RESET_UART0] = {0x24, 16}, + [MA35D1_RESET_UART1] = {0x24, 17}, + [MA35D1_RESET_UART2] = {0x24, 18}, + [MA35D1_RESET_UART3] = {0x24, 19}, + [MA35D1_RESET_UART4] = {0x24, 20}, + [MA35D1_RESET_UART5] = {0x24, 21}, + [MA35D1_RESET_UART6] = {0x24, 22}, + [MA35D1_RESET_UART7] = {0x24, 23}, + [MA35D1_RESET_CANFD0] = {0x24, 24}, + [MA35D1_RESET_CANFD1] = {0x24, 25}, + [MA35D1_RESET_EADC0] = {0x24, 28}, + [MA35D1_RESET_I2S0] = {0x24, 29}, + [MA35D1_RESET_SC0] = {0x28, 0}, + [MA35D1_RESET_SC1] = {0x28, 1}, + [MA35D1_RESET_QSPI1] = {0x28, 4}, + [MA35D1_RESET_SPI3] = {0x28, 6}, + [MA35D1_RESET_EPWM0] = {0x28, 16}, + [MA35D1_RESET_EPWM1] = {0x28, 17}, + [MA35D1_RESET_QEI0] = {0x28, 22}, + [MA35D1_RESET_QEI1] = {0x28, 23}, + [MA35D1_RESET_ECAP0] = {0x28, 26}, + [MA35D1_RESET_ECAP1] = {0x28, 27}, + [MA35D1_RESET_CANFD2] = {0x28, 28}, + [MA35D1_RESET_ADC0] = {0x28, 31}, + [MA35D1_RESET_TMR4] = {0x2C, 0}, + [MA35D1_RESET_TMR5] = {0x2C, 1}, + [MA35D1_RESET_TMR6] = {0x2C, 2}, + [MA35D1_RESET_TMR7] = {0x2C, 3}, + [MA35D1_RESET_TMR8] = {0x2C, 4}, + [MA35D1_RESET_TMR9] = {0x2C, 5}, + [MA35D1_RESET_TMR10] = {0x2C, 6}, + [MA35D1_RESET_TMR11] = {0x2C, 7}, + [MA35D1_RESET_UART8] = {0x2C, 8}, + [MA35D1_RESET_UART9] = {0x2C, 9}, + [MA35D1_RESET_UART10] = {0x2C, 10}, + [MA35D1_RESET_UART11] = {0x2C, 11}, + [MA35D1_RESET_UART12] = {0x2C, 12}, + [MA35D1_RESET_UART13] = {0x2C, 13}, + [MA35D1_RESET_UART14] = {0x2C, 14}, + [MA35D1_RESET_UART15] = {0x2C, 15}, + [MA35D1_RESET_UART16] = {0x2C, 16}, + [MA35D1_RESET_I2S1] = {0x2C, 17}, + [MA35D1_RESET_I2C4] = {0x2C, 18}, + [MA35D1_RESET_I2C5] = {0x2C, 19}, + [MA35D1_RESET_EPWM2] = {0x2C, 20}, + [MA35D1_RESET_ECAP2] = {0x2C, 21}, + [MA35D1_RESET_QEI2] = {0x2C, 22}, + [MA35D1_RESET_CANFD3] = {0x2C, 23}, + [MA35D1_RESET_KPI] = {0x2C, 24}, + [MA35D1_RESET_GIC] = {0x2C, 28}, + [MA35D1_RESET_SSMCC] = {0x2C, 30}, + [MA35D1_RESET_SSPCC] = {0x2C, 31} +}; + +static int ma35d1_restart_handler(struct notifier_block *this, unsigned long mode, void *cmd) +{ + struct ma35d1_reset_data *data = + container_of(this, struct ma35d1_reset_data, restart_handler); + u32 id = MA35D1_RESET_CHIP; + + writel_relaxed(BIT(ma35d1_reset_map[id].bit), + data->base + ma35d1_reset_map[id].reg_ofs); + return 0; +} + +static int ma35d1_reset_update(struct reset_controller_dev *rcdev, unsigned long id, bool assert) +{ + struct ma35d1_reset_data *data = container_of(rcdev, struct ma35d1_reset_data, rcdev); + unsigned long flags; + u32 reg; + + if (WARN_ON_ONCE(id >= ARRAY_SIZE(ma35d1_reset_map))) + return -EINVAL; + + spin_lock_irqsave(&data->lock, flags); + reg = readl_relaxed(data->base + ma35d1_reset_map[id].reg_ofs); + if (assert) + reg |= BIT(ma35d1_reset_map[id].bit); + else + reg &= ~(BIT(ma35d1_reset_map[id].bit)); + writel_relaxed(reg, data->base + ma35d1_reset_map[id].reg_ofs); + spin_unlock_irqrestore(&data->lock, flags); + + return 0; +} + +static int ma35d1_reset_assert(struct reset_controller_dev *rcdev, unsigned long id) +{ + return ma35d1_reset_update(rcdev, id, true); +} + +static int ma35d1_reset_deassert(struct reset_controller_dev *rcdev, unsigned long id) +{ + return ma35d1_reset_update(rcdev, id, false); +} + +static int ma35d1_reset_status(struct reset_controller_dev *rcdev, unsigned long id) +{ + struct ma35d1_reset_data *data = container_of(rcdev, struct ma35d1_reset_data, rcdev); + u32 reg; + + if (WARN_ON_ONCE(id >= ARRAY_SIZE(ma35d1_reset_map))) + return -EINVAL; + + reg = readl_relaxed(data->base + ma35d1_reset_map[id].reg_ofs); + return !!(reg & BIT(ma35d1_reset_map[id].bit)); +} + +static const struct reset_control_ops ma35d1_reset_ops = { + .assert = ma35d1_reset_assert, + .deassert = ma35d1_reset_deassert, + .status = ma35d1_reset_status, +}; + +static const struct of_device_id ma35d1_reset_dt_ids[] = { + { .compatible = "nuvoton,ma35d1-reset" }, + { }, +}; + +static int ma35d1_reset_probe(struct platform_device *pdev) +{ + struct ma35d1_reset_data *reset_data; + struct device *dev = &pdev->dev; + int err; + + if (!pdev->dev.of_node) { + dev_err(&pdev->dev, "Device tree node not found\n"); + return -EINVAL; + } + + reset_data = devm_kzalloc(dev, sizeof(*reset_data), GFP_KERNEL); + if (!reset_data) + return -ENOMEM; + + reset_data->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(reset_data->base)) + return PTR_ERR(reset_data->base); + + reset_data->rcdev.owner = THIS_MODULE; + reset_data->rcdev.nr_resets = MA35D1_RESET_COUNT; + reset_data->rcdev.ops = &ma35d1_reset_ops; + reset_data->rcdev.of_node = dev->of_node; + reset_data->restart_handler.notifier_call = ma35d1_restart_handler; + reset_data->restart_handler.priority = 192; + spin_lock_init(&reset_data->lock); + + err = register_restart_handler(&reset_data->restart_handler); + if (err) + dev_warn(&pdev->dev, "failed to register restart handler\n"); + + return devm_reset_controller_register(dev, &reset_data->rcdev); +} + +static struct platform_driver ma35d1_reset_driver = { + .probe = ma35d1_reset_probe, + .driver = { + .name = "ma35d1-reset", + .of_match_table = ma35d1_reset_dt_ids, + }, +}; + +builtin_platform_driver(ma35d1_reset_driver); diff --git a/drivers/reset/reset-meson-audio-arb.c b/drivers/reset/reset-meson-audio-arb.c index 1dc06e08a8da67f1f8096618c355574dea3a92fb..6a3f6a6a3bbf55bfc9381601694843c760fb4fe7 100644 --- a/drivers/reset/reset-meson-audio-arb.c +++ b/drivers/reset/reset-meson-audio-arb.c @@ -151,11 +151,8 @@ static int meson_audio_arb_probe(struct platform_device *pdev) platform_set_drvdata(pdev, arb); arb->clk = devm_clk_get(dev, NULL); - if (IS_ERR(arb->clk)) { - if (PTR_ERR(arb->clk) != -EPROBE_DEFER) - dev_err(dev, "failed to get clock\n"); - return PTR_ERR(arb->clk); - } + if (IS_ERR(arb->clk)) + return dev_err_probe(dev, PTR_ERR(arb->clk), "failed to get clock\n"); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); arb->regs = devm_ioremap_resource(dev, res); diff --git a/drivers/reset/reset-meson.c b/drivers/reset/reset-meson.c index 26dc5477861516dadda0941667f3c745e14c77f6..13878ca2779d22fde65c85c79c929ec2c376327f 100644 --- a/drivers/reset/reset-meson.c +++ b/drivers/reset/reset-meson.c @@ -116,14 +116,12 @@ MODULE_DEVICE_TABLE(of, meson_reset_dt_ids); static int meson_reset_probe(struct platform_device *pdev) { struct meson_reset *data; - struct resource *res; data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); if (!data) return -ENOMEM; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - data->reg_base = devm_ioremap_resource(&pdev->dev, res); + data->reg_base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(data->reg_base)) return PTR_ERR(data->reg_base); diff --git a/drivers/reset/reset-oxnas.c b/drivers/reset/reset-oxnas.c deleted file mode 100644 index 8209f922dc16930b5d58aa9d2062fdc954ab3225..0000000000000000000000000000000000000000 --- a/drivers/reset/reset-oxnas.c +++ /dev/null @@ -1,114 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Oxford Semiconductor Reset Controller driver - * - * Copyright (C) 2016 Neil Armstrong - * Copyright (C) 2014 Ma Haijun - * Copyright (C) 2009 Oxford Semiconductor Ltd - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Regmap offsets */ -#define RST_SET_REGOFFSET 0x34 -#define RST_CLR_REGOFFSET 0x38 - -struct oxnas_reset { - struct regmap *regmap; - struct reset_controller_dev rcdev; -}; - -static int oxnas_reset_reset(struct reset_controller_dev *rcdev, - unsigned long id) -{ - struct oxnas_reset *data = - container_of(rcdev, struct oxnas_reset, rcdev); - - regmap_write(data->regmap, RST_SET_REGOFFSET, BIT(id)); - msleep(50); - regmap_write(data->regmap, RST_CLR_REGOFFSET, BIT(id)); - - return 0; -} - -static int oxnas_reset_assert(struct reset_controller_dev *rcdev, - unsigned long id) -{ - struct oxnas_reset *data = - container_of(rcdev, struct oxnas_reset, rcdev); - - regmap_write(data->regmap, RST_SET_REGOFFSET, BIT(id)); - - return 0; -} - -static int oxnas_reset_deassert(struct reset_controller_dev *rcdev, - unsigned long id) -{ - struct oxnas_reset *data = - container_of(rcdev, struct oxnas_reset, rcdev); - - regmap_write(data->regmap, RST_CLR_REGOFFSET, BIT(id)); - - return 0; -} - -static const struct reset_control_ops oxnas_reset_ops = { - .reset = oxnas_reset_reset, - .assert = oxnas_reset_assert, - .deassert = oxnas_reset_deassert, -}; - -static const struct of_device_id oxnas_reset_dt_ids[] = { - { .compatible = "oxsemi,ox810se-reset", }, - { .compatible = "oxsemi,ox820-reset", }, - { /* sentinel */ }, -}; - -static int oxnas_reset_probe(struct platform_device *pdev) -{ - struct oxnas_reset *data; - struct device *parent; - - parent = pdev->dev.parent; - if (!parent) { - dev_err(&pdev->dev, "no parent\n"); - return -ENODEV; - } - - data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); - if (!data) - return -ENOMEM; - - data->regmap = syscon_node_to_regmap(parent->of_node); - if (IS_ERR(data->regmap)) { - dev_err(&pdev->dev, "failed to get parent regmap\n"); - return PTR_ERR(data->regmap); - } - - platform_set_drvdata(pdev, data); - - data->rcdev.owner = THIS_MODULE; - data->rcdev.nr_resets = 32; - data->rcdev.ops = &oxnas_reset_ops; - data->rcdev.of_node = pdev->dev.of_node; - - return devm_reset_controller_register(&pdev->dev, &data->rcdev); -} - -static struct platform_driver oxnas_reset_driver = { - .probe = oxnas_reset_probe, - .driver = { - .name = "oxnas-reset", - .of_match_table = oxnas_reset_dt_ids, - }, -}; -builtin_platform_driver(oxnas_reset_driver); diff --git a/drivers/reset/starfive/Kconfig b/drivers/reset/starfive/Kconfig index 1fa706a2c3dcaf6c751d861fd819a66145b8f98c..d832339f61bc0d5c1048d55d0a59fbc6baeae28c 100644 --- a/drivers/reset/starfive/Kconfig +++ b/drivers/reset/starfive/Kconfig @@ -13,7 +13,8 @@ config RESET_STARFIVE_JH7100 config RESET_STARFIVE_JH7110 bool "StarFive JH7110 Reset Driver" - depends on AUXILIARY_BUS && CLK_STARFIVE_JH7110_SYS + depends on CLK_STARFIVE_JH7110_SYS + select AUXILIARY_BUS select RESET_STARFIVE_JH71X0 default ARCH_STARFIVE help diff --git a/drivers/reset/sti/Kconfig b/drivers/reset/sti/Kconfig index 9455e1c7a5aa661fce4d9387bcf2c75d35b416b2..a2622e146b8b3621f659c3ec1ddfa599b120b6a8 100644 --- a/drivers/reset/sti/Kconfig +++ b/drivers/reset/sti/Kconfig @@ -1,11 +1,7 @@ # SPDX-License-Identifier: GPL-2.0-only if ARCH_STI -config STI_RESET_SYSCFG - bool - config STIH407_RESET bool - select STI_RESET_SYSCFG endif diff --git a/drivers/reset/sti/Makefile b/drivers/reset/sti/Makefile index 3eb30f7e8e3dfb5d4ff05a1727e96b78b75758b0..5e833496cee3beeace35ae8d04495c6bf8154f59 100644 --- a/drivers/reset/sti/Makefile +++ b/drivers/reset/sti/Makefile @@ -1,4 +1,2 @@ # SPDX-License-Identifier: GPL-2.0-only -obj-$(CONFIG_STI_RESET_SYSCFG) += reset-syscfg.o - -obj-$(CONFIG_STIH407_RESET) += reset-stih407.o +obj-$(CONFIG_STIH407_RESET) += reset-stih407.o reset-syscfg.o diff --git a/drivers/reset/sti/reset-syscfg.c b/drivers/reset/sti/reset-syscfg.c index b4b46e0f207e907357cf7a3bbab05f4ec34755fa..c1ba04f6f1554b879d11d47829ebb44651ed706b 100644 --- a/drivers/reset/sti/reset-syscfg.c +++ b/drivers/reset/sti/reset-syscfg.c @@ -64,22 +64,12 @@ static int syscfg_reset_program_hw(struct reset_controller_dev *rcdev, return err; if (ch->ack) { - unsigned long timeout = jiffies + msecs_to_jiffies(1000); u32 ack_val; - while (true) { - err = regmap_field_read(ch->ack, &ack_val); - if (err) - return err; - - if (ack_val == ctrl_val) - break; - - if (time_after(jiffies, timeout)) - return -ETIME; - - cpu_relax(); - } + err = regmap_field_read_poll_timeout(ch->ack, ack_val, (ack_val == ctrl_val), + 100, USEC_PER_SEC); + if (err) + return err; } return 0; diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 75387240861564405577aaf05c9150ef6aa91e54..05f4b2d66290dc17be553bfb647568e87bbaa0a3 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -395,7 +395,7 @@ config RTC_DRV_NCT3018Y config RTC_DRV_RK808 tristate "Rockchip RK805/RK808/RK809/RK817/RK818 RTC" - depends on MFD_RK808 + depends on MFD_RK8XX help If you say yes here you will get support for the RTC of RK805, RK809 and RK817, RK808 and RK818 PMIC. @@ -956,6 +956,7 @@ comment "Platform RTC drivers" config RTC_DRV_CMOS tristate "PC-style 'CMOS'" depends on X86 || ARM || PPC || MIPS || SPARC64 + depends on HAS_IOPORT || MACH_DECSTATION default y if X86 select RTC_MC146818_LIB help @@ -976,6 +977,7 @@ config RTC_DRV_CMOS config RTC_DRV_ALPHA bool "Alpha PC-style CMOS" depends on ALPHA + depends on HAS_IOPORT select RTC_MC146818_LIB default y help @@ -1193,7 +1195,7 @@ config RTC_DRV_MSM6242 config RTC_DRV_BQ4802 tristate "TI BQ4802" - depends on HAS_IOMEM + depends on HAS_IOMEM && HAS_IOPORT help If you say Y here you will get support for the TI BQ4802 RTC chip. @@ -1685,6 +1687,19 @@ config RTC_DRV_JZ4740 This driver can also be built as a module. If so, the module will be called rtc-jz4740. +config RTC_DRV_LOONGSON + tristate "Loongson On-chip RTC" + depends on MACH_LOONGSON32 || MACH_LOONGSON64 || COMPILE_TEST + select REGMAP_MMIO + help + This is a driver for the Loongson on-chip Counter0 (Time-Of-Year + counter) to be used as a RTC. + It can be found on Loongson-1 series cpu, Loongson-2K series cpu + and Loongson LS7A bridge chips. + + This driver can also be built as a module. If so, the module + will be called rtc-loongson. + config RTC_DRV_LPC24XX tristate "NXP RTC for LPC178x/18xx/408x/43xx" depends on ARCH_LPC18XX || COMPILE_TEST @@ -1726,16 +1741,6 @@ config RTC_DRV_TEGRA This drive can also be built as a module. If so, the module will be called rtc-tegra. -config RTC_DRV_LOONGSON1 - tristate "loongson1 RTC support" - depends on MACH_LOONGSON32 - help - This is a driver for the loongson1 on-chip Counter0 (Time-Of-Year - counter) to be used as a RTC. - - This driver can also be built as a module. If so, the module - will be called rtc-ls1x. - config RTC_DRV_MXC tristate "Freescale MXC Real Time Clock" depends on ARCH_MXC || COMPILE_TEST diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index ea445d1ebb172898dc71fd7a097e81385e610dc5..fd209883ee2efd118c992f010fde9935c186c816 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -78,7 +78,7 @@ obj-$(CONFIG_RTC_DRV_ISL12022) += rtc-isl12022.o obj-$(CONFIG_RTC_DRV_ISL12026) += rtc-isl12026.o obj-$(CONFIG_RTC_DRV_ISL1208) += rtc-isl1208.o obj-$(CONFIG_RTC_DRV_JZ4740) += rtc-jz4740.o -obj-$(CONFIG_RTC_DRV_LOONGSON1) += rtc-ls1x.o +obj-$(CONFIG_RTC_DRV_LOONGSON) += rtc-loongson.o obj-$(CONFIG_RTC_DRV_LP8788) += rtc-lp8788.o obj-$(CONFIG_RTC_DRV_LPC24XX) += rtc-lpc24xx.o obj-$(CONFIG_RTC_DRV_LPC32XX) += rtc-lpc32xx.o diff --git a/drivers/rtc/rtc-ab-b5ze-s3.c b/drivers/rtc/rtc-ab-b5ze-s3.c index f2b0971d2c65db64e32253a6feef866c03dc015a..100062001831462a5f6f652414333197042c4fc2 100644 --- a/drivers/rtc/rtc-ab-b5ze-s3.c +++ b/drivers/rtc/rtc-ab-b5ze-s3.c @@ -944,7 +944,7 @@ static struct i2c_driver abb5zes3_driver = { .pm = &abb5zes3_rtc_pm_ops, .of_match_table = of_match_ptr(abb5zes3_dt_match), }, - .probe_new = abb5zes3_probe, + .probe = abb5zes3_probe, .id_table = abb5zes3_id, }; module_i2c_driver(abb5zes3_driver); diff --git a/drivers/rtc/rtc-ab-eoz9.c b/drivers/rtc/rtc-ab-eoz9.c index 34611f6dedcba8a7660821f13f3b6b333ed81dff..04e1b8e93bc1cb6d9fde062a1cfe5f979e19048d 100644 --- a/drivers/rtc/rtc-ab-eoz9.c +++ b/drivers/rtc/rtc-ab-eoz9.c @@ -455,7 +455,7 @@ static const struct hwmon_channel_info abeoz9_temp = { .config = abeoz9_temp_config, }; -static const struct hwmon_channel_info *abeoz9_info[] = { +static const struct hwmon_channel_info * const abeoz9_info[] = { &abeoz9_chip, &abeoz9_temp, NULL @@ -584,7 +584,7 @@ static struct i2c_driver abeoz9_driver = { .name = "rtc-ab-eoz9", .of_match_table = of_match_ptr(abeoz9_dt_match), }, - .probe_new = abeoz9_probe, + .probe = abeoz9_probe, .id_table = abeoz9_id, }; diff --git a/drivers/rtc/rtc-abx80x.c b/drivers/rtc/rtc-abx80x.c index f34a2e59cac765380d50a93f7892690cd72afa41..e08d3181bd2a66211d3de01d64983000da3f540b 100644 --- a/drivers/rtc/rtc-abx80x.c +++ b/drivers/rtc/rtc-abx80x.c @@ -992,7 +992,7 @@ static struct i2c_driver abx80x_driver = { .name = "rtc-abx80x", .of_match_table = of_match_ptr(abx80x_of_match), }, - .probe_new = abx80x_probe, + .probe = abx80x_probe, .id_table = abx80x_id, }; diff --git a/drivers/rtc/rtc-bq32k.c b/drivers/rtc/rtc-bq32k.c index 967ddc6bf76d68697d304c3b511d0f224d8056da..591e42391747bacd4e7ac03fabc737c57fd27295 100644 --- a/drivers/rtc/rtc-bq32k.c +++ b/drivers/rtc/rtc-bq32k.c @@ -320,7 +320,7 @@ static struct i2c_driver bq32k_driver = { .name = "bq32k", .of_match_table = of_match_ptr(bq32k_of_match), }, - .probe_new = bq32k_probe, + .probe = bq32k_probe, .remove = bq32k_remove, .id_table = bq32k_id, }; diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c index e86ba84df6cbedd1f14f02410dedeb15f9aa3c06..cb5acecc11aa4e0700a7e0b537493cac0357c061 100644 --- a/drivers/rtc/rtc-ds1307.c +++ b/drivers/rtc/rtc-ds1307.c @@ -2011,7 +2011,7 @@ static struct i2c_driver ds1307_driver = { .name = "rtc-ds1307", .of_match_table = ds1307_of_match, }, - .probe_new = ds1307_probe, + .probe = ds1307_probe, .id_table = ds1307_id, }; diff --git a/drivers/rtc/rtc-ds1374.c b/drivers/rtc/rtc-ds1374.c index 7f089f0661634624ba4958c82aa0eed92338a712..4a5005cb23f5930139b91c20b7cb5ca904b01dd5 100644 --- a/drivers/rtc/rtc-ds1374.c +++ b/drivers/rtc/rtc-ds1374.c @@ -572,7 +572,7 @@ static struct i2c_driver ds1374_driver = { .of_match_table = of_match_ptr(ds1374_of_match), .pm = &ds1374_pm, }, - .probe_new = ds1374_probe, + .probe = ds1374_probe, .remove = ds1374_remove, .id_table = ds1374_id, }; diff --git a/drivers/rtc/rtc-ds1672.c b/drivers/rtc/rtc-ds1672.c index a3bb2cd9c881b2fc4f2f7e771cebe521a3f94739..641799f30baa995278227fe3751f2adc2c106b9a 100644 --- a/drivers/rtc/rtc-ds1672.c +++ b/drivers/rtc/rtc-ds1672.c @@ -149,7 +149,7 @@ static struct i2c_driver ds1672_driver = { .name = "rtc-ds1672", .of_match_table = of_match_ptr(ds1672_of_match), }, - .probe_new = ds1672_probe, + .probe = ds1672_probe, .id_table = ds1672_id, }; diff --git a/drivers/rtc/rtc-ds3232.c b/drivers/rtc/rtc-ds3232.c index dd31a60c1fc69800813f0eeaf99d8883c5be5152..89d7b085f7219954b1a154ef41245e76251e9336 100644 --- a/drivers/rtc/rtc-ds3232.c +++ b/drivers/rtc/rtc-ds3232.c @@ -359,7 +359,7 @@ static const struct hwmon_channel_info ds3232_hwmon_temp = { .config = ds3232_hwmon_temp_config, }; -static const struct hwmon_channel_info *ds3232_hwmon_info[] = { +static const struct hwmon_channel_info * const ds3232_hwmon_info[] = { &ds3232_hwmon_chip, &ds3232_hwmon_temp, NULL @@ -603,7 +603,7 @@ static struct i2c_driver ds3232_driver = { .of_match_table = of_match_ptr(ds3232_of_match), .pm = &ds3232_pm_ops, }, - .probe_new = ds3232_i2c_probe, + .probe = ds3232_i2c_probe, .id_table = ds3232_id, }; diff --git a/drivers/rtc/rtc-em3027.c b/drivers/rtc/rtc-em3027.c index 53f9f9391a5f15452f07dccad6102dc437b325ab..fc772eae5da5f25a4ea1d0a13f56b787ece594e7 100644 --- a/drivers/rtc/rtc-em3027.c +++ b/drivers/rtc/rtc-em3027.c @@ -147,7 +147,7 @@ static struct i2c_driver em3027_driver = { .name = "rtc-em3027", .of_match_table = of_match_ptr(em3027_of_match), }, - .probe_new = em3027_probe, + .probe = em3027_probe, .id_table = em3027_id, }; diff --git a/drivers/rtc/rtc-fm3130.c b/drivers/rtc/rtc-fm3130.c index f59bb81f23c0421877c4e60facd26f1cfa7da552..400ce4ad0c49905d003cbad94234be6cc0a1dde3 100644 --- a/drivers/rtc/rtc-fm3130.c +++ b/drivers/rtc/rtc-fm3130.c @@ -517,7 +517,7 @@ static struct i2c_driver fm3130_driver = { .driver = { .name = "rtc-fm3130", }, - .probe_new = fm3130_probe, + .probe = fm3130_probe, .id_table = fm3130_id, }; diff --git a/drivers/rtc/rtc-hym8563.c b/drivers/rtc/rtc-hym8563.c index 7d5a298a9a3bc678c671ede56880e8f82c2f8e98..b018535c842b376adce85d2f584a8c85b0286e5c 100644 --- a/drivers/rtc/rtc-hym8563.c +++ b/drivers/rtc/rtc-hym8563.c @@ -576,7 +576,7 @@ static struct i2c_driver hym8563_driver = { .pm = &hym8563_pm_ops, .of_match_table = hym8563_dt_idtable, }, - .probe_new = hym8563_probe, + .probe = hym8563_probe, .id_table = hym8563_id, }; diff --git a/drivers/rtc/rtc-isl12022.c b/drivers/rtc/rtc-isl12022.c index e68a79b5e00e586ac2a72b4ea2b0171d21129ebb..a613257d1574d387e80208e092a65e764a3e84c1 100644 --- a/drivers/rtc/rtc-isl12022.c +++ b/drivers/rtc/rtc-isl12022.c @@ -89,7 +89,7 @@ static int isl12022_hwmon_read(struct device *dev, return -EOPNOTSUPP; } -static const struct hwmon_channel_info *isl12022_hwmon_info[] = { +static const struct hwmon_channel_info * const isl12022_hwmon_info[] = { HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT), NULL }; @@ -262,7 +262,7 @@ static struct i2c_driver isl12022_driver = { .name = "rtc-isl12022", .of_match_table = isl12022_dt_match, }, - .probe_new = isl12022_probe, + .probe = isl12022_probe, .id_table = isl12022_id, }; diff --git a/drivers/rtc/rtc-isl12026.c b/drivers/rtc/rtc-isl12026.c index 1bfca39079d40efbe71b60cb7da3cfa2424589d5..5abff5d348acdb6333e3bf1454da6292e2b0466b 100644 --- a/drivers/rtc/rtc-isl12026.c +++ b/drivers/rtc/rtc-isl12026.c @@ -490,7 +490,7 @@ static struct i2c_driver isl12026_driver = { .name = "rtc-isl12026", .of_match_table = isl12026_dt_match, }, - .probe_new = isl12026_probe_new, + .probe = isl12026_probe_new, .remove = isl12026_remove, }; diff --git a/drivers/rtc/rtc-isl1208.c b/drivers/rtc/rtc-isl1208.c index 73cc6aaf9b8b72f84d51a54d42bcf1d0528dbdf2..b0712b4e364891656598d0d764c92398057f346d 100644 --- a/drivers/rtc/rtc-isl1208.c +++ b/drivers/rtc/rtc-isl1208.c @@ -6,6 +6,7 @@ */ #include +#include #include #include #include @@ -68,42 +69,60 @@ static struct i2c_driver isl1208_driver; -/* ISL1208 various variants */ -enum isl1208_id { - TYPE_ISL1208 = 0, - TYPE_ISL1209, - TYPE_ISL1218, - TYPE_ISL1219, - ISL_LAST_ID -}; - /* Chip capabilities table */ -static const struct isl1208_config { - const char name[8]; +struct isl1208_config { unsigned int nvmem_length; unsigned has_tamper:1; unsigned has_timestamp:1; -} isl1208_configs[] = { - [TYPE_ISL1208] = { "isl1208", 2, false, false }, - [TYPE_ISL1209] = { "isl1209", 2, true, false }, - [TYPE_ISL1218] = { "isl1218", 8, false, false }, - [TYPE_ISL1219] = { "isl1219", 2, true, true }, + unsigned has_inverted_osc_bit:1; +}; + +static const struct isl1208_config config_isl1208 = { + .nvmem_length = 2, + .has_tamper = false, + .has_timestamp = false +}; + +static const struct isl1208_config config_isl1209 = { + .nvmem_length = 2, + .has_tamper = true, + .has_timestamp = false +}; + +static const struct isl1208_config config_isl1218 = { + .nvmem_length = 8, + .has_tamper = false, + .has_timestamp = false +}; + +static const struct isl1208_config config_isl1219 = { + .nvmem_length = 2, + .has_tamper = true, + .has_timestamp = true +}; + +static const struct isl1208_config config_raa215300_a0 = { + .nvmem_length = 2, + .has_tamper = false, + .has_timestamp = false, + .has_inverted_osc_bit = true }; static const struct i2c_device_id isl1208_id[] = { - { "isl1208", TYPE_ISL1208 }, - { "isl1209", TYPE_ISL1209 }, - { "isl1218", TYPE_ISL1218 }, - { "isl1219", TYPE_ISL1219 }, + { "isl1208", .driver_data = (kernel_ulong_t)&config_isl1208 }, + { "isl1209", .driver_data = (kernel_ulong_t)&config_isl1209 }, + { "isl1218", .driver_data = (kernel_ulong_t)&config_isl1218 }, + { "isl1219", .driver_data = (kernel_ulong_t)&config_isl1219 }, + { "raa215300_a0", .driver_data = (kernel_ulong_t)&config_raa215300_a0 }, { } }; MODULE_DEVICE_TABLE(i2c, isl1208_id); static const __maybe_unused struct of_device_id isl1208_of_match[] = { - { .compatible = "isil,isl1208", .data = &isl1208_configs[TYPE_ISL1208] }, - { .compatible = "isil,isl1209", .data = &isl1208_configs[TYPE_ISL1209] }, - { .compatible = "isil,isl1218", .data = &isl1208_configs[TYPE_ISL1218] }, - { .compatible = "isil,isl1219", .data = &isl1208_configs[TYPE_ISL1219] }, + { .compatible = "isil,isl1208", .data = &config_isl1208 }, + { .compatible = "isil,isl1209", .data = &config_isl1209 }, + { .compatible = "isil,isl1218", .data = &config_isl1218 }, + { .compatible = "isil,isl1219", .data = &config_isl1219 }, { } }; MODULE_DEVICE_TABLE(of, isl1208_of_match); @@ -166,6 +185,20 @@ isl1208_i2c_validate_client(struct i2c_client *client) return 0; } +static int isl1208_set_xtoscb(struct i2c_client *client, int sr, int xtosb_val) +{ + /* Do nothing if bit is already set to desired value */ + if ((sr & ISL1208_REG_SR_XTOSCB) == xtosb_val) + return 0; + + if (xtosb_val) + sr |= ISL1208_REG_SR_XTOSCB; + else + sr &= ~ISL1208_REG_SR_XTOSCB; + + return i2c_smbus_write_byte_data(client, ISL1208_REG_SR, sr); +} + static int isl1208_i2c_get_sr(struct i2c_client *client) { @@ -502,7 +535,6 @@ isl1208_i2c_set_time(struct i2c_client *client, struct rtc_time const *tm) return 0; } - static int isl1208_rtc_set_time(struct device *dev, struct rtc_time *tm) { @@ -796,12 +828,26 @@ static int isl1208_setup_irq(struct i2c_client *client, int irq) return rc; } +static int +isl1208_clk_present(struct i2c_client *client, const char *name) +{ + struct clk *clk; + + clk = devm_clk_get_optional(&client->dev, name); + if (IS_ERR(clk)) + return PTR_ERR(clk); + + return !!clk; +} + static int isl1208_probe(struct i2c_client *client) { - int rc = 0; struct isl1208_state *isl1208; int evdet_irq = -1; + int xtosb_val = 0; + int rc = 0; + int sr; if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) return -ENODEV; @@ -823,9 +869,22 @@ isl1208_probe(struct i2c_client *client) } else { const struct i2c_device_id *id = i2c_match_id(isl1208_id, client); - if (id->driver_data >= ISL_LAST_ID) + if (!id) return -ENODEV; - isl1208->config = &isl1208_configs[id->driver_data]; + isl1208->config = (struct isl1208_config *)id->driver_data; + } + + rc = isl1208_clk_present(client, "xin"); + if (rc < 0) + return rc; + + if (!rc) { + rc = isl1208_clk_present(client, "clkin"); + if (rc < 0) + return rc; + + if (rc) + xtosb_val = 1; } isl1208->rtc = devm_rtc_allocate_device(&client->dev); @@ -839,13 +898,20 @@ isl1208_probe(struct i2c_client *client) isl1208->nvmem_config.size = isl1208->config->nvmem_length; isl1208->nvmem_config.priv = isl1208; - rc = isl1208_i2c_get_sr(client); - if (rc < 0) { + sr = isl1208_i2c_get_sr(client); + if (sr < 0) { dev_err(&client->dev, "reading status failed\n"); - return rc; + return sr; } - if (rc & ISL1208_REG_SR_RTCF) + if (isl1208->config->has_inverted_osc_bit) + xtosb_val = !xtosb_val; + + rc = isl1208_set_xtoscb(client, sr, xtosb_val); + if (rc) + return rc; + + if (sr & ISL1208_REG_SR_RTCF) dev_warn(&client->dev, "rtc power failure detected, " "please set clock.\n"); @@ -908,7 +974,7 @@ static struct i2c_driver isl1208_driver = { .name = "rtc-isl1208", .of_match_table = of_match_ptr(isl1208_of_match), }, - .probe_new = isl1208_probe, + .probe = isl1208_probe, .id_table = isl1208_id, }; diff --git a/drivers/rtc/rtc-loongson.c b/drivers/rtc/rtc-loongson.c new file mode 100644 index 0000000000000000000000000000000000000000..e8ffc1ab90b02fbf6a383efaa79ea57cee4ae67b --- /dev/null +++ b/drivers/rtc/rtc-loongson.c @@ -0,0 +1,397 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Loongson RTC driver + * + * Maintained out-of-tree by Huacai Chen . + * Rewritten for mainline by WANG Xuerui . + * Binbin Zhou + */ + +#include +#include +#include +#include +#include +#include +#include + +/* Time Of Year(TOY) counters registers */ +#define TOY_TRIM_REG 0x20 /* Must be initialized to 0 */ +#define TOY_WRITE0_REG 0x24 /* TOY low 32-bits value (write-only) */ +#define TOY_WRITE1_REG 0x28 /* TOY high 32-bits value (write-only) */ +#define TOY_READ0_REG 0x2c /* TOY low 32-bits value (read-only) */ +#define TOY_READ1_REG 0x30 /* TOY high 32-bits value (read-only) */ +#define TOY_MATCH0_REG 0x34 /* TOY timing interrupt 0 */ +#define TOY_MATCH1_REG 0x38 /* TOY timing interrupt 1 */ +#define TOY_MATCH2_REG 0x3c /* TOY timing interrupt 2 */ + +/* RTC counters registers */ +#define RTC_CTRL_REG 0x40 /* TOY and RTC control register */ +#define RTC_TRIM_REG 0x60 /* Must be initialized to 0 */ +#define RTC_WRITE0_REG 0x64 /* RTC counters value (write-only) */ +#define RTC_READ0_REG 0x68 /* RTC counters value (read-only) */ +#define RTC_MATCH0_REG 0x6c /* RTC timing interrupt 0 */ +#define RTC_MATCH1_REG 0x70 /* RTC timing interrupt 1 */ +#define RTC_MATCH2_REG 0x74 /* RTC timing interrupt 2 */ + +/* bitmask of TOY_WRITE0_REG */ +#define TOY_MON GENMASK(31, 26) +#define TOY_DAY GENMASK(25, 21) +#define TOY_HOUR GENMASK(20, 16) +#define TOY_MIN GENMASK(15, 10) +#define TOY_SEC GENMASK(9, 4) +#define TOY_MSEC GENMASK(3, 0) + +/* bitmask of TOY_MATCH0/1/2_REG */ +#define TOY_MATCH_YEAR GENMASK(31, 26) +#define TOY_MATCH_MON GENMASK(25, 22) +#define TOY_MATCH_DAY GENMASK(21, 17) +#define TOY_MATCH_HOUR GENMASK(16, 12) +#define TOY_MATCH_MIN GENMASK(11, 6) +#define TOY_MATCH_SEC GENMASK(5, 0) + +/* bitmask of RTC_CTRL_REG */ +#define RTC_ENABLE BIT(13) /* 1: RTC counters enable */ +#define TOY_ENABLE BIT(11) /* 1: TOY counters enable */ +#define OSC_ENABLE BIT(8) /* 1: 32.768k crystal enable */ +#define TOY_ENABLE_MASK (TOY_ENABLE | OSC_ENABLE) + +/* PM domain registers */ +#define PM1_STS_REG 0x0c /* Power management 1 status register */ +#define RTC_STS BIT(10) /* RTC status */ +#define PM1_EN_REG 0x10 /* Power management 1 enable register */ +#define RTC_EN BIT(10) /* RTC event enable */ + +/* + * According to the LS1C manual, RTC_CTRL and alarm-related registers are not defined. + * Accessing the relevant registers will cause the system to hang. + */ +#define LS1C_RTC_CTRL_WORKAROUND BIT(0) + +struct loongson_rtc_config { + u32 pm_offset; /* Offset of PM domain, for RTC alarm wakeup */ + u32 flags; /* Workaround bits */ +}; + +struct loongson_rtc_priv { + spinlock_t lock; /* protects PM registers access */ + u32 fix_year; /* RTC alarm year compensation value */ + struct rtc_device *rtcdev; + struct regmap *regmap; + void __iomem *pm_base; /* PM domain base, for RTC alarm wakeup */ + const struct loongson_rtc_config *config; +}; + +static const struct loongson_rtc_config ls1b_rtc_config = { + .pm_offset = 0, + .flags = 0, +}; + +static const struct loongson_rtc_config ls1c_rtc_config = { + .pm_offset = 0, + .flags = LS1C_RTC_CTRL_WORKAROUND, +}; + +static const struct loongson_rtc_config generic_rtc_config = { + .pm_offset = 0x100, + .flags = 0, +}; + +static const struct loongson_rtc_config ls2k1000_rtc_config = { + .pm_offset = 0x800, + .flags = 0, +}; + +static const struct regmap_config loongson_rtc_regmap_config = { + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, +}; + +/* RTC alarm irq handler */ +static irqreturn_t loongson_rtc_isr(int irq, void *id) +{ + struct loongson_rtc_priv *priv = (struct loongson_rtc_priv *)id; + + rtc_update_irq(priv->rtcdev, 1, RTC_AF | RTC_IRQF); + return IRQ_HANDLED; +} + +/* For ACPI fixed event handler */ +static u32 loongson_rtc_handler(void *id) +{ + struct loongson_rtc_priv *priv = (struct loongson_rtc_priv *)id; + + spin_lock(&priv->lock); + /* Disable RTC alarm wakeup and interrupt */ + writel(readl(priv->pm_base + PM1_EN_REG) & ~RTC_EN, + priv->pm_base + PM1_EN_REG); + + /* Clear RTC interrupt status */ + writel(RTC_STS, priv->pm_base + PM1_STS_REG); + spin_unlock(&priv->lock); + + /* + * The TOY_MATCH0_REG should be cleared 0 here, + * otherwise the interrupt cannot be cleared. + */ + return regmap_write(priv->regmap, TOY_MATCH0_REG, 0); +} + +static int loongson_rtc_set_enabled(struct device *dev) +{ + struct loongson_rtc_priv *priv = dev_get_drvdata(dev); + + if (priv->config->flags & LS1C_RTC_CTRL_WORKAROUND) + return 0; + + /* Enable RTC TOY counters and crystal */ + return regmap_update_bits(priv->regmap, RTC_CTRL_REG, TOY_ENABLE_MASK, + TOY_ENABLE_MASK); +} + +static bool loongson_rtc_get_enabled(struct device *dev) +{ + int ret; + u32 ctrl_data; + struct loongson_rtc_priv *priv = dev_get_drvdata(dev); + + if (priv->config->flags & LS1C_RTC_CTRL_WORKAROUND) + return true; + + ret = regmap_read(priv->regmap, RTC_CTRL_REG, &ctrl_data); + if (ret < 0) + return false; + + return ctrl_data & TOY_ENABLE_MASK; +} + +static int loongson_rtc_read_time(struct device *dev, struct rtc_time *tm) +{ + int ret; + u32 rtc_data[2]; + struct loongson_rtc_priv *priv = dev_get_drvdata(dev); + + if (!loongson_rtc_get_enabled(dev)) + return -EINVAL; + + ret = regmap_bulk_read(priv->regmap, TOY_READ0_REG, rtc_data, + ARRAY_SIZE(rtc_data)); + if (ret < 0) + return ret; + + tm->tm_sec = FIELD_GET(TOY_SEC, rtc_data[0]); + tm->tm_min = FIELD_GET(TOY_MIN, rtc_data[0]); + tm->tm_hour = FIELD_GET(TOY_HOUR, rtc_data[0]); + tm->tm_mday = FIELD_GET(TOY_DAY, rtc_data[0]); + tm->tm_mon = FIELD_GET(TOY_MON, rtc_data[0]) - 1; + tm->tm_year = rtc_data[1]; + + /* Prepare for RTC alarm year compensation value. */ + priv->fix_year = tm->tm_year / 64 * 64; + return 0; +} + +static int loongson_rtc_set_time(struct device *dev, struct rtc_time *tm) +{ + int ret; + u32 rtc_data[2]; + struct loongson_rtc_priv *priv = dev_get_drvdata(dev); + + rtc_data[0] = FIELD_PREP(TOY_SEC, tm->tm_sec) + | FIELD_PREP(TOY_MIN, tm->tm_min) + | FIELD_PREP(TOY_HOUR, tm->tm_hour) + | FIELD_PREP(TOY_DAY, tm->tm_mday) + | FIELD_PREP(TOY_MON, tm->tm_mon + 1); + rtc_data[1] = tm->tm_year; + + ret = regmap_bulk_write(priv->regmap, TOY_WRITE0_REG, rtc_data, + ARRAY_SIZE(rtc_data)); + if (ret < 0) + return ret; + + return loongson_rtc_set_enabled(dev); +} + +static int loongson_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) +{ + int ret; + u32 alarm_data; + struct loongson_rtc_priv *priv = dev_get_drvdata(dev); + + ret = regmap_read(priv->regmap, TOY_MATCH0_REG, &alarm_data); + if (ret < 0) + return ret; + + alrm->time.tm_sec = FIELD_GET(TOY_MATCH_SEC, alarm_data); + alrm->time.tm_min = FIELD_GET(TOY_MATCH_MIN, alarm_data); + alrm->time.tm_hour = FIELD_GET(TOY_MATCH_HOUR, alarm_data); + alrm->time.tm_mday = FIELD_GET(TOY_MATCH_DAY, alarm_data); + alrm->time.tm_mon = FIELD_GET(TOY_MATCH_MON, alarm_data) - 1; + /* + * This is a hardware bug: the year field of SYS_TOYMATCH is only 6 bits, + * making it impossible to save year values larger than 64. + * + * SYS_TOYMATCH is used to match the alarm time value and determine if + * an alarm is triggered, so we must keep the lower 6 bits of the year + * value constant during the value conversion. + * + * In summary, we need to manually add 64(or a multiple of 64) to the + * year value to avoid the invalid alarm prompt at startup. + */ + alrm->time.tm_year = FIELD_GET(TOY_MATCH_YEAR, alarm_data) + priv->fix_year; + + alrm->enabled = !!(readl(priv->pm_base + PM1_EN_REG) & RTC_EN); + return 0; +} + +static int loongson_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) +{ + u32 val; + struct loongson_rtc_priv *priv = dev_get_drvdata(dev); + + spin_lock(&priv->lock); + val = readl(priv->pm_base + PM1_EN_REG); + /* Enable RTC alarm wakeup */ + writel(enabled ? val | RTC_EN : val & ~RTC_EN, + priv->pm_base + PM1_EN_REG); + spin_unlock(&priv->lock); + + return 0; +} + +static int loongson_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) +{ + int ret; + u32 alarm_data; + struct loongson_rtc_priv *priv = dev_get_drvdata(dev); + + alarm_data = FIELD_PREP(TOY_MATCH_SEC, alrm->time.tm_sec) + | FIELD_PREP(TOY_MATCH_MIN, alrm->time.tm_min) + | FIELD_PREP(TOY_MATCH_HOUR, alrm->time.tm_hour) + | FIELD_PREP(TOY_MATCH_DAY, alrm->time.tm_mday) + | FIELD_PREP(TOY_MATCH_MON, alrm->time.tm_mon + 1) + | FIELD_PREP(TOY_MATCH_YEAR, alrm->time.tm_year - priv->fix_year); + + ret = regmap_write(priv->regmap, TOY_MATCH0_REG, alarm_data); + if (ret < 0) + return ret; + + return loongson_rtc_alarm_irq_enable(dev, alrm->enabled); +} + +static const struct rtc_class_ops loongson_rtc_ops = { + .read_time = loongson_rtc_read_time, + .set_time = loongson_rtc_set_time, + .read_alarm = loongson_rtc_read_alarm, + .set_alarm = loongson_rtc_set_alarm, + .alarm_irq_enable = loongson_rtc_alarm_irq_enable, +}; + +static int loongson_rtc_probe(struct platform_device *pdev) +{ + int ret, alarm_irq; + void __iomem *regs; + struct loongson_rtc_priv *priv; + struct device *dev = &pdev->dev; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + regs = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(regs)) + return dev_err_probe(dev, PTR_ERR(regs), + "devm_platform_ioremap_resource failed\n"); + + priv->regmap = devm_regmap_init_mmio(dev, regs, + &loongson_rtc_regmap_config); + if (IS_ERR(priv->regmap)) + return dev_err_probe(dev, PTR_ERR(priv->regmap), + "devm_regmap_init_mmio failed\n"); + + priv->config = device_get_match_data(dev); + spin_lock_init(&priv->lock); + platform_set_drvdata(pdev, priv); + + priv->rtcdev = devm_rtc_allocate_device(dev); + if (IS_ERR(priv->rtcdev)) + return dev_err_probe(dev, PTR_ERR(priv->rtcdev), + "devm_rtc_allocate_device failed\n"); + + /* Get RTC alarm irq */ + alarm_irq = platform_get_irq(pdev, 0); + if (alarm_irq > 0) { + ret = devm_request_irq(dev, alarm_irq, loongson_rtc_isr, + 0, "loongson-alarm", priv); + if (ret < 0) + return dev_err_probe(dev, ret, "Unable to request irq %d\n", + alarm_irq); + + priv->pm_base = regs - priv->config->pm_offset; + device_init_wakeup(dev, 1); + + if (has_acpi_companion(dev)) + acpi_install_fixed_event_handler(ACPI_EVENT_RTC, + loongson_rtc_handler, priv); + } else { + /* Loongson-1C RTC does not support alarm */ + clear_bit(RTC_FEATURE_ALARM, priv->rtcdev->features); + } + + /* Loongson RTC does not support UIE */ + clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, priv->rtcdev->features); + priv->rtcdev->ops = &loongson_rtc_ops; + priv->rtcdev->range_min = RTC_TIMESTAMP_BEGIN_2000; + priv->rtcdev->range_max = RTC_TIMESTAMP_END_2099; + + return devm_rtc_register_device(priv->rtcdev); +} + +static void loongson_rtc_remove(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct loongson_rtc_priv *priv = dev_get_drvdata(dev); + + if (!test_bit(RTC_FEATURE_ALARM, priv->rtcdev->features)) + return; + + if (has_acpi_companion(dev)) + acpi_remove_fixed_event_handler(ACPI_EVENT_RTC, + loongson_rtc_handler); + + device_init_wakeup(dev, 0); + loongson_rtc_alarm_irq_enable(dev, 0); +} + +static const struct of_device_id loongson_rtc_of_match[] = { + { .compatible = "loongson,ls1b-rtc", .data = &ls1b_rtc_config }, + { .compatible = "loongson,ls1c-rtc", .data = &ls1c_rtc_config }, + { .compatible = "loongson,ls7a-rtc", .data = &generic_rtc_config }, + { .compatible = "loongson,ls2k1000-rtc", .data = &ls2k1000_rtc_config }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, loongson_rtc_of_match); + +static const struct acpi_device_id loongson_rtc_acpi_match[] = { + { "LOON0001", .driver_data = (kernel_ulong_t)&generic_rtc_config }, + { } +}; +MODULE_DEVICE_TABLE(acpi, loongson_rtc_acpi_match); + +static struct platform_driver loongson_rtc_driver = { + .probe = loongson_rtc_probe, + .remove_new = loongson_rtc_remove, + .driver = { + .name = "loongson-rtc", + .of_match_table = loongson_rtc_of_match, + .acpi_match_table = loongson_rtc_acpi_match, + }, +}; +module_platform_driver(loongson_rtc_driver); + +MODULE_DESCRIPTION("Loongson RTC driver"); +MODULE_AUTHOR("Binbin Zhou "); +MODULE_AUTHOR("WANG Xuerui "); +MODULE_AUTHOR("Huacai Chen "); +MODULE_LICENSE("GPL"); diff --git a/drivers/rtc/rtc-ls1x.c b/drivers/rtc/rtc-ls1x.c deleted file mode 100644 index 5af26dc5c2a39e46b3db12fd9f6597cf2903d820..0000000000000000000000000000000000000000 --- a/drivers/rtc/rtc-ls1x.c +++ /dev/null @@ -1,192 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * Copyright (c) 2011 Zhao Zhang - * - * Derived from driver/rtc/rtc-au1xxx.c - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define LS1X_RTC_REG_OFFSET (LS1X_RTC_BASE + 0x20) -#define LS1X_RTC_REGS(x) \ - ((void __iomem *)KSEG1ADDR(LS1X_RTC_REG_OFFSET + (x))) - -/*RTC programmable counters 0 and 1*/ -#define SYS_COUNTER_CNTRL (LS1X_RTC_REGS(0x20)) -#define SYS_CNTRL_ERS (1 << 23) -#define SYS_CNTRL_RTS (1 << 20) -#define SYS_CNTRL_RM2 (1 << 19) -#define SYS_CNTRL_RM1 (1 << 18) -#define SYS_CNTRL_RM0 (1 << 17) -#define SYS_CNTRL_RS (1 << 16) -#define SYS_CNTRL_BP (1 << 14) -#define SYS_CNTRL_REN (1 << 13) -#define SYS_CNTRL_BRT (1 << 12) -#define SYS_CNTRL_TEN (1 << 11) -#define SYS_CNTRL_BTT (1 << 10) -#define SYS_CNTRL_E0 (1 << 8) -#define SYS_CNTRL_ETS (1 << 7) -#define SYS_CNTRL_32S (1 << 5) -#define SYS_CNTRL_TTS (1 << 4) -#define SYS_CNTRL_TM2 (1 << 3) -#define SYS_CNTRL_TM1 (1 << 2) -#define SYS_CNTRL_TM0 (1 << 1) -#define SYS_CNTRL_TS (1 << 0) - -/* Programmable Counter 0 Registers */ -#define SYS_TOYTRIM (LS1X_RTC_REGS(0)) -#define SYS_TOYWRITE0 (LS1X_RTC_REGS(4)) -#define SYS_TOYWRITE1 (LS1X_RTC_REGS(8)) -#define SYS_TOYREAD0 (LS1X_RTC_REGS(0xC)) -#define SYS_TOYREAD1 (LS1X_RTC_REGS(0x10)) -#define SYS_TOYMATCH0 (LS1X_RTC_REGS(0x14)) -#define SYS_TOYMATCH1 (LS1X_RTC_REGS(0x18)) -#define SYS_TOYMATCH2 (LS1X_RTC_REGS(0x1C)) - -/* Programmable Counter 1 Registers */ -#define SYS_RTCTRIM (LS1X_RTC_REGS(0x40)) -#define SYS_RTCWRITE0 (LS1X_RTC_REGS(0x44)) -#define SYS_RTCREAD0 (LS1X_RTC_REGS(0x48)) -#define SYS_RTCMATCH0 (LS1X_RTC_REGS(0x4C)) -#define SYS_RTCMATCH1 (LS1X_RTC_REGS(0x50)) -#define SYS_RTCMATCH2 (LS1X_RTC_REGS(0x54)) - -#define LS1X_SEC_OFFSET (4) -#define LS1X_MIN_OFFSET (10) -#define LS1X_HOUR_OFFSET (16) -#define LS1X_DAY_OFFSET (21) -#define LS1X_MONTH_OFFSET (26) - - -#define LS1X_SEC_MASK (0x3f) -#define LS1X_MIN_MASK (0x3f) -#define LS1X_HOUR_MASK (0x1f) -#define LS1X_DAY_MASK (0x1f) -#define LS1X_MONTH_MASK (0x3f) -#define LS1X_YEAR_MASK (0xffffffff) - -#define ls1x_get_sec(t) (((t) >> LS1X_SEC_OFFSET) & LS1X_SEC_MASK) -#define ls1x_get_min(t) (((t) >> LS1X_MIN_OFFSET) & LS1X_MIN_MASK) -#define ls1x_get_hour(t) (((t) >> LS1X_HOUR_OFFSET) & LS1X_HOUR_MASK) -#define ls1x_get_day(t) (((t) >> LS1X_DAY_OFFSET) & LS1X_DAY_MASK) -#define ls1x_get_month(t) (((t) >> LS1X_MONTH_OFFSET) & LS1X_MONTH_MASK) - -#define RTC_CNTR_OK (SYS_CNTRL_E0 | SYS_CNTRL_32S) - -static int ls1x_rtc_read_time(struct device *dev, struct rtc_time *rtm) -{ - unsigned long v; - time64_t t; - - v = readl(SYS_TOYREAD0); - t = readl(SYS_TOYREAD1); - - memset(rtm, 0, sizeof(struct rtc_time)); - t = mktime64((t & LS1X_YEAR_MASK), ls1x_get_month(v), - ls1x_get_day(v), ls1x_get_hour(v), - ls1x_get_min(v), ls1x_get_sec(v)); - rtc_time64_to_tm(t, rtm); - - return 0; -} - -static int ls1x_rtc_set_time(struct device *dev, struct rtc_time *rtm) -{ - unsigned long v, t, c; - int ret = -ETIMEDOUT; - - v = ((rtm->tm_mon + 1) << LS1X_MONTH_OFFSET) - | (rtm->tm_mday << LS1X_DAY_OFFSET) - | (rtm->tm_hour << LS1X_HOUR_OFFSET) - | (rtm->tm_min << LS1X_MIN_OFFSET) - | (rtm->tm_sec << LS1X_SEC_OFFSET); - - writel(v, SYS_TOYWRITE0); - c = 0x10000; - /* add timeout check counter, for more safe */ - while ((readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_TS) && --c) - usleep_range(1000, 3000); - - if (!c) { - dev_err(dev, "set time timeout!\n"); - goto err; - } - - t = rtm->tm_year + 1900; - writel(t, SYS_TOYWRITE1); - c = 0x10000; - while ((readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_TS) && --c) - usleep_range(1000, 3000); - - if (!c) { - dev_err(dev, "set time timeout!\n"); - goto err; - } - return 0; -err: - return ret; -} - -static const struct rtc_class_ops ls1x_rtc_ops = { - .read_time = ls1x_rtc_read_time, - .set_time = ls1x_rtc_set_time, -}; - -static int ls1x_rtc_probe(struct platform_device *pdev) -{ - struct rtc_device *rtcdev; - unsigned long v; - - v = readl(SYS_COUNTER_CNTRL); - if (!(v & RTC_CNTR_OK)) { - dev_err(&pdev->dev, "rtc counters not working\n"); - return -ENODEV; - } - - /* set to 1 HZ if needed */ - if (readl(SYS_TOYTRIM) != 32767) { - v = 0x100000; - while ((readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_TTS) && --v) - usleep_range(1000, 3000); - - if (!v) { - dev_err(&pdev->dev, "time out\n"); - return -ETIMEDOUT; - } - writel(32767, SYS_TOYTRIM); - } - /* this loop coundn't be endless */ - while (readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_TTS) - usleep_range(1000, 3000); - - rtcdev = devm_rtc_allocate_device(&pdev->dev); - if (IS_ERR(rtcdev)) - return PTR_ERR(rtcdev); - - platform_set_drvdata(pdev, rtcdev); - rtcdev->ops = &ls1x_rtc_ops; - rtcdev->range_min = RTC_TIMESTAMP_BEGIN_1900; - rtcdev->range_max = RTC_TIMESTAMP_END_2099; - - return devm_rtc_register_device(rtcdev); -} - -static struct platform_driver ls1x_rtc_driver = { - .driver = { - .name = "ls1x-rtc", - }, - .probe = ls1x_rtc_probe, -}; - -module_platform_driver(ls1x_rtc_driver); - -MODULE_AUTHOR("zhao zhang "); -MODULE_LICENSE("GPL"); diff --git a/drivers/rtc/rtc-m41t80.c b/drivers/rtc/rtc-m41t80.c index c1963f7c424d7032bb13fccc9cf158c7f7e6f2d0..3cc5151e098644aaf4abdfa22c66f2eda14a8c53 100644 --- a/drivers/rtc/rtc-m41t80.c +++ b/drivers/rtc/rtc-m41t80.c @@ -1013,7 +1013,7 @@ static struct i2c_driver m41t80_driver = { .of_match_table = of_match_ptr(m41t80_of_match), .pm = &m41t80_pm, }, - .probe_new = m41t80_probe, + .probe = m41t80_probe, .remove = m41t80_remove, .id_table = m41t80_id, }; diff --git a/drivers/rtc/rtc-max6900.c b/drivers/rtc/rtc-max6900.c index 0a33851cc51f4f60236fec567f84404db4634384..31b910e4d91a89c530dc8abfaab2b5bf11189949 100644 --- a/drivers/rtc/rtc-max6900.c +++ b/drivers/rtc/rtc-max6900.c @@ -224,7 +224,7 @@ static struct i2c_driver max6900_driver = { .driver = { .name = "rtc-max6900", }, - .probe_new = max6900_probe, + .probe = max6900_probe, .id_table = max6900_id, }; diff --git a/drivers/rtc/rtc-nct3018y.c b/drivers/rtc/rtc-nct3018y.c index 0a3b14c95d9027ce770e5a30c2f467655519215a..a4e3f924837e0cf904a8c098ccdff895ae1e3fed 100644 --- a/drivers/rtc/rtc-nct3018y.c +++ b/drivers/rtc/rtc-nct3018y.c @@ -540,7 +540,7 @@ static struct i2c_driver nct3018y_driver = { .name = "rtc-nct3018y", .of_match_table = of_match_ptr(nct3018y_of_match), }, - .probe_new = nct3018y_probe, + .probe = nct3018y_probe, .id_table = nct3018y_id, }; diff --git a/drivers/rtc/rtc-pcf2127.c b/drivers/rtc/rtc-pcf2127.c index 87f4fc9df68b4a66de70c8768611511828780bb4..ee03b04b74baa7c2740e15f672eb90bbb0a8602e 100644 --- a/drivers/rtc/rtc-pcf2127.c +++ b/drivers/rtc/rtc-pcf2127.c @@ -923,7 +923,7 @@ static struct i2c_driver pcf2127_i2c_driver = { .name = "rtc-pcf2127-i2c", .of_match_table = of_match_ptr(pcf2127_of_match), }, - .probe_new = pcf2127_i2c_probe, + .probe = pcf2127_i2c_probe, .id_table = pcf2127_i2c_id, }; diff --git a/drivers/rtc/rtc-pcf85063.c b/drivers/rtc/rtc-pcf85063.c index 71a4563559819473ebd7a5cf430edf90f2ef60ee..e517abfaee2a03d64882add2177e736952b42cfa 100644 --- a/drivers/rtc/rtc-pcf85063.c +++ b/drivers/rtc/rtc-pcf85063.c @@ -681,7 +681,7 @@ static struct i2c_driver pcf85063_driver = { .name = "rtc-pcf85063", .of_match_table = of_match_ptr(pcf85063_of_match), }, - .probe_new = pcf85063_probe, + .probe = pcf85063_probe, .id_table = pcf85063_ids, }; diff --git a/drivers/rtc/rtc-pcf8523.c b/drivers/rtc/rtc-pcf8523.c index e7115ebef70771e2ae8db1641b72e90320e0bd1f..d1efde3e7a8094e01b4f34b66f2f5990258ca3cb 100644 --- a/drivers/rtc/rtc-pcf8523.c +++ b/drivers/rtc/rtc-pcf8523.c @@ -488,7 +488,7 @@ static struct i2c_driver pcf8523_driver = { .name = "rtc-pcf8523", .of_match_table = pcf8523_of_match, }, - .probe_new = pcf8523_probe, + .probe = pcf8523_probe, .id_table = pcf8523_id, }; module_i2c_driver(pcf8523_driver); diff --git a/drivers/rtc/rtc-pcf85363.c b/drivers/rtc/rtc-pcf85363.c index 8958eadf1c3efb0e0281cc910df3bd5ed0c934ed..65b8b1338dbb0b607d651df507bf43097d3debee 100644 --- a/drivers/rtc/rtc-pcf85363.c +++ b/drivers/rtc/rtc-pcf85363.c @@ -475,7 +475,7 @@ static struct i2c_driver pcf85363_driver = { .name = "pcf85363", .of_match_table = of_match_ptr(dev_ids), }, - .probe_new = pcf85363_probe, + .probe = pcf85363_probe, }; module_i2c_driver(pcf85363_driver); diff --git a/drivers/rtc/rtc-pcf8563.c b/drivers/rtc/rtc-pcf8563.c index 7e720472213c7c76e2971880d92d68550875e127..ea82b89d8929f95fb26e1f3e77794d75a094a429 100644 --- a/drivers/rtc/rtc-pcf8563.c +++ b/drivers/rtc/rtc-pcf8563.c @@ -612,7 +612,7 @@ static struct i2c_driver pcf8563_driver = { .name = "rtc-pcf8563", .of_match_table = of_match_ptr(pcf8563_of_match), }, - .probe_new = pcf8563_probe, + .probe = pcf8563_probe, .id_table = pcf8563_id, }; diff --git a/drivers/rtc/rtc-pcf8583.c b/drivers/rtc/rtc-pcf8583.c index 87074d178274e92576fea2dbd94979848672a2dd..a7e0fc360b6a10703d8c4c00073df6a794ac61fb 100644 --- a/drivers/rtc/rtc-pcf8583.c +++ b/drivers/rtc/rtc-pcf8583.c @@ -306,7 +306,7 @@ static struct i2c_driver pcf8583_driver = { .driver = { .name = "pcf8583", }, - .probe_new = pcf8583_probe, + .probe = pcf8583_probe, .id_table = pcf8583_id, }; diff --git a/drivers/rtc/rtc-rs5c372.c b/drivers/rtc/rtc-rs5c372.c index b4c5d016eca32c10838c352859ff1b73fbcb4556..a5a6c8772ecd4beeb57498bf998c3460d13d3ba9 100644 --- a/drivers/rtc/rtc-rs5c372.c +++ b/drivers/rtc/rtc-rs5c372.c @@ -921,7 +921,7 @@ static struct i2c_driver rs5c372_driver = { .name = "rtc-rs5c372", .of_match_table = of_match_ptr(rs5c372_of_match), }, - .probe_new = rs5c372_probe, + .probe = rs5c372_probe, .remove = rs5c372_remove, .id_table = rs5c372_id, }; diff --git a/drivers/rtc/rtc-rv3028.c b/drivers/rtc/rtc-rv3028.c index ec5d7a614e2dd25ba5b5a5e3e76e558ca3fbcf33..076e56f4e01a524e56c34a54f0fd8e7a7d8d5e6c 100644 --- a/drivers/rtc/rtc-rv3028.c +++ b/drivers/rtc/rtc-rv3028.c @@ -994,13 +994,20 @@ static const __maybe_unused struct of_device_id rv3028_of_match[] = { }; MODULE_DEVICE_TABLE(of, rv3028_of_match); +static const struct i2c_device_id rv3028_id_table[] = { + { .name = "rv3028", }, + { } +}; +MODULE_DEVICE_TABLE(i2c, rv3028_id_table); + static struct i2c_driver rv3028_driver = { .driver = { .name = "rtc-rv3028", .acpi_match_table = rv3028_i2c_acpi_match, .of_match_table = of_match_ptr(rv3028_of_match), }, - .probe_new = rv3028_probe, + .id_table = rv3028_id_table, + .probe = rv3028_probe, }; module_i2c_driver(rv3028_driver); diff --git a/drivers/rtc/rtc-rv3029c2.c b/drivers/rtc/rtc-rv3029c2.c index 0852f6709a8591cf374056f932ff99aed9c2e769..4a81feeb00ffde03de8d37a2544541b4fde97850 100644 --- a/drivers/rtc/rtc-rv3029c2.c +++ b/drivers/rtc/rtc-rv3029c2.c @@ -824,7 +824,7 @@ static struct i2c_driver rv3029_driver = { .name = "rv3029", .of_match_table = of_match_ptr(rv3029_of_match), }, - .probe_new = rv3029_i2c_probe, + .probe = rv3029_i2c_probe, .id_table = rv3029_id, }; diff --git a/drivers/rtc/rtc-rv3032.c b/drivers/rtc/rtc-rv3032.c index 1ff4f2e6fa77e78c3f6368ee09e9d9fb2378fbe9..6b8eb2039a33368b3d203e20e1139953fadb250c 100644 --- a/drivers/rtc/rtc-rv3032.c +++ b/drivers/rtc/rtc-rv3032.c @@ -842,7 +842,7 @@ static int rv3032_hwmon_read(struct device *dev, enum hwmon_sensor_types type, return err; } -static const struct hwmon_channel_info *rv3032_hwmon_info[] = { +static const struct hwmon_channel_info * const rv3032_hwmon_info[] = { HWMON_CHANNEL_INFO(chip, HWMON_C_REGISTER_TZ), HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_MAX_HYST), NULL @@ -998,7 +998,7 @@ static struct i2c_driver rv3032_driver = { .acpi_match_table = rv3032_i2c_acpi_match, .of_match_table = of_match_ptr(rv3032_of_match), }, - .probe_new = rv3032_probe, + .probe = rv3032_probe, }; module_i2c_driver(rv3032_driver); diff --git a/drivers/rtc/rtc-rv8803.c b/drivers/rtc/rtc-rv8803.c index 25c3b9e4f515af3dcf6c68d7f689036203935264..98679cae13e8409ae0d080e2e42fa886c3d8e1a1 100644 --- a/drivers/rtc/rtc-rv8803.c +++ b/drivers/rtc/rtc-rv8803.c @@ -739,7 +739,7 @@ static struct i2c_driver rv8803_driver = { .name = "rtc-rv8803", .of_match_table = of_match_ptr(rv8803_of_match), }, - .probe_new = rv8803_probe, + .probe = rv8803_probe, .id_table = rv8803_id, }; module_i2c_driver(rv8803_driver); diff --git a/drivers/rtc/rtc-rx6110.c b/drivers/rtc/rtc-rx6110.c index 37608883a796d5be0349ce6d7675f84f3f5f227a..8702db6096ba4e7cb6c6a5f7a30233bc7395250e 100644 --- a/drivers/rtc/rtc-rx6110.c +++ b/drivers/rtc/rtc-rx6110.c @@ -462,7 +462,7 @@ static struct i2c_driver rx6110_i2c_driver = { .name = RX6110_DRIVER_NAME, .acpi_match_table = rx6110_i2c_acpi_match, }, - .probe_new = rx6110_i2c_probe, + .probe = rx6110_i2c_probe, .id_table = rx6110_i2c_id, }; diff --git a/drivers/rtc/rtc-rx8010.c b/drivers/rtc/rtc-rx8010.c index b9c8dad2620853ff0398f477d02bad2a96bc5426..f44e212c07ded4ff1f8813eab9a7dc207b1df342 100644 --- a/drivers/rtc/rtc-rx8010.c +++ b/drivers/rtc/rtc-rx8010.c @@ -424,7 +424,7 @@ static struct i2c_driver rx8010_driver = { .name = "rtc-rx8010", .of_match_table = of_match_ptr(rx8010_of_match), }, - .probe_new = rx8010_probe, + .probe = rx8010_probe, .id_table = rx8010_id, }; diff --git a/drivers/rtc/rtc-rx8025.c b/drivers/rtc/rtc-rx8025.c index 331c20d4d843c1a3aa234c0083763b1151b8eb59..aabe62c283a150f18810545a05827f54b8ed468f 100644 --- a/drivers/rtc/rtc-rx8025.c +++ b/drivers/rtc/rtc-rx8025.c @@ -581,7 +581,7 @@ static struct i2c_driver rx8025_driver = { .driver = { .name = "rtc-rx8025", }, - .probe_new = rx8025_probe, + .probe = rx8025_probe, .id_table = rx8025_id, }; diff --git a/drivers/rtc/rtc-rx8581.c b/drivers/rtc/rtc-rx8581.c index 14edb7534c97164853dfe970ce79b811341980c8..82881fd2e14a1aa844182ac9cd5d05e481d5f192 100644 --- a/drivers/rtc/rtc-rx8581.c +++ b/drivers/rtc/rtc-rx8581.c @@ -325,7 +325,7 @@ static struct i2c_driver rx8581_driver = { .name = "rtc-rx8581", .of_match_table = of_match_ptr(rx8581_of_match), }, - .probe_new = rx8581_probe, + .probe = rx8581_probe, .id_table = rx8581_id, }; diff --git a/drivers/rtc/rtc-s35390a.c b/drivers/rtc/rtc-s35390a.c index b18daaf72b17dbd87e982362985ea584c454e2c8..90a3028ac57433444ab8d3b091d35c264aceaefa 100644 --- a/drivers/rtc/rtc-s35390a.c +++ b/drivers/rtc/rtc-s35390a.c @@ -499,7 +499,7 @@ static struct i2c_driver s35390a_driver = { .name = "rtc-s35390a", .of_match_table = of_match_ptr(s35390a_of_match), }, - .probe_new = s35390a_probe, + .probe = s35390a_probe, .id_table = s35390a_id, }; diff --git a/drivers/rtc/rtc-sd3078.c b/drivers/rtc/rtc-sd3078.c index e2f90d768ca80dd19f602226aac49e1d10c3ea74..7760394ccd2dfbaac41ac0ccd70180282886bbc2 100644 --- a/drivers/rtc/rtc-sd3078.c +++ b/drivers/rtc/rtc-sd3078.c @@ -217,7 +217,7 @@ static struct i2c_driver sd3078_driver = { .name = "sd3078", .of_match_table = of_match_ptr(rtc_dt_match), }, - .probe_new = sd3078_probe, + .probe = sd3078_probe, .id_table = sd3078_id, }; diff --git a/drivers/rtc/rtc-st-lpc.c b/drivers/rtc/rtc-st-lpc.c index 0f8e4231098ef1b856906a484a17585f8be94e2a..d492a2d26600c1bd64f23738b04ad7cad24409e1 100644 --- a/drivers/rtc/rtc-st-lpc.c +++ b/drivers/rtc/rtc-st-lpc.c @@ -228,17 +228,13 @@ static int st_rtc_probe(struct platform_device *pdev) enable_irq_wake(rtc->irq); disable_irq(rtc->irq); - rtc->clk = clk_get(&pdev->dev, NULL); - if (IS_ERR(rtc->clk)) { - dev_err(&pdev->dev, "Unable to request clock\n"); - return PTR_ERR(rtc->clk); - } - - clk_prepare_enable(rtc->clk); + rtc->clk = devm_clk_get_enabled(&pdev->dev, NULL); + if (IS_ERR(rtc->clk)) + return dev_err_probe(&pdev->dev, PTR_ERR(rtc->clk), + "Unable to request clock\n"); rtc->clkrate = clk_get_rate(rtc->clk); if (!rtc->clkrate) { - clk_disable_unprepare(rtc->clk); dev_err(&pdev->dev, "Unable to fetch clock rate\n"); return -EINVAL; } @@ -252,10 +248,8 @@ static int st_rtc_probe(struct platform_device *pdev) do_div(rtc->rtc_dev->range_max, rtc->clkrate); ret = devm_rtc_register_device(rtc->rtc_dev); - if (ret) { - clk_disable_unprepare(rtc->clk); + if (ret) return ret; - } return 0; } diff --git a/drivers/rtc/rtc-stm32.c b/drivers/rtc/rtc-stm32.c index 229cb2847cc4887a11dfcd5d4e476da4d110ae79..3d36e11cff80c291fc8197612ab4e0f672c59a2f 100644 --- a/drivers/rtc/rtc-stm32.c +++ b/drivers/rtc/rtc-stm32.c @@ -114,7 +114,6 @@ struct stm32_rtc_data { void (*clear_events)(struct stm32_rtc *rtc, unsigned int flags); bool has_pclk; bool need_dbp; - bool has_wakeirq; }; struct stm32_rtc { @@ -127,7 +126,6 @@ struct stm32_rtc { struct clk *rtc_ck; const struct stm32_rtc_data *data; int irq_alarm; - int wakeirq_alarm; }; static void stm32_rtc_wpr_unlock(struct stm32_rtc *rtc) @@ -547,7 +545,6 @@ static void stm32_rtc_clear_events(struct stm32_rtc *rtc, static const struct stm32_rtc_data stm32_rtc_data = { .has_pclk = false, .need_dbp = true, - .has_wakeirq = false, .regs = { .tr = 0x00, .dr = 0x04, @@ -569,7 +566,6 @@ static const struct stm32_rtc_data stm32_rtc_data = { static const struct stm32_rtc_data stm32h7_rtc_data = { .has_pclk = true, .need_dbp = true, - .has_wakeirq = false, .regs = { .tr = 0x00, .dr = 0x04, @@ -600,7 +596,6 @@ static void stm32mp1_rtc_clear_events(struct stm32_rtc *rtc, static const struct stm32_rtc_data stm32mp1_data = { .has_pclk = true, .need_dbp = false, - .has_wakeirq = true, .regs = { .tr = 0x00, .dr = 0x04, @@ -779,19 +774,12 @@ static int stm32_rtc_probe(struct platform_device *pdev) } ret = device_init_wakeup(&pdev->dev, true); - if (rtc->data->has_wakeirq) { - rtc->wakeirq_alarm = platform_get_irq(pdev, 1); - if (rtc->wakeirq_alarm > 0) { - ret = dev_pm_set_dedicated_wake_irq(&pdev->dev, - rtc->wakeirq_alarm); - } else { - ret = rtc->wakeirq_alarm; - if (rtc->wakeirq_alarm == -EPROBE_DEFER) - goto err; - } - } if (ret) - dev_warn(&pdev->dev, "alarm can't wake up the system: %d", ret); + goto err; + + ret = dev_pm_set_wake_irq(&pdev->dev, rtc->irq_alarm); + if (ret) + goto err; platform_set_drvdata(pdev, rtc); @@ -879,9 +867,6 @@ static int stm32_rtc_suspend(struct device *dev) if (rtc->data->has_pclk) clk_disable_unprepare(rtc->pclk); - if (device_may_wakeup(dev)) - return enable_irq_wake(rtc->irq_alarm); - return 0; } @@ -903,9 +888,6 @@ static int stm32_rtc_resume(struct device *dev) return ret; } - if (device_may_wakeup(dev)) - return disable_irq_wake(rtc->irq_alarm); - return ret; } #endif diff --git a/drivers/rtc/rtc-sun6i.c b/drivers/rtc/rtc-sun6i.c index dc76537f1b62a3cee17c4f18ae17438efec07dc3..71548dd59a3a68ab529423db4d65b13b00515dcc 100644 --- a/drivers/rtc/rtc-sun6i.c +++ b/drivers/rtc/rtc-sun6i.c @@ -214,6 +214,7 @@ static int sun6i_rtc_osc_set_parent(struct clk_hw *hw, u8 index) static const struct clk_ops sun6i_rtc_osc_ops = { .recalc_rate = sun6i_rtc_osc_recalc_rate, + .determine_rate = clk_hw_determine_rate_no_reparent, .get_parent = sun6i_rtc_osc_get_parent, .set_parent = sun6i_rtc_osc_set_parent, diff --git a/drivers/rtc/rtc-x1205.c b/drivers/rtc/rtc-x1205.c index f587afa843573d2c7fa69a035f5b5886337c4544..807f953ae0aedc2541bdf58fe0e7bf8eaaa54f5b 100644 --- a/drivers/rtc/rtc-x1205.c +++ b/drivers/rtc/rtc-x1205.c @@ -679,7 +679,7 @@ static struct i2c_driver x1205_driver = { .name = "rtc-x1205", .of_match_table = x1205_dt_ids, }, - .probe_new = x1205_probe, + .probe = x1205_probe, .remove = x1205_remove, .id_table = x1205_id, }; diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index 9fbfce735d56502d5fcdd2e1894d0cc4a97db449..edcbf77852c31ff38f85ede69dbf1aa19d7f008f 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c @@ -2737,7 +2737,12 @@ static void __dasd_cleanup_cqr(struct dasd_ccw_req *cqr) else if (status == 0) { switch (cqr->intrc) { case -EPERM: - error = BLK_STS_NEXUS; + /* + * DASD doesn't implement SCSI/NVMe reservations, but it + * implements a locking scheme similar to them. We + * return this error when we no longer have the lock. + */ + error = BLK_STS_RESV_CONFLICT; break; case -ENOLINK: error = BLK_STS_TRANSPORT; @@ -3234,12 +3239,12 @@ struct blk_mq_ops dasd_mq_ops = { .exit_hctx = dasd_exit_hctx, }; -static int dasd_open(struct block_device *bdev, fmode_t mode) +static int dasd_open(struct gendisk *disk, blk_mode_t mode) { struct dasd_device *base; int rc; - base = dasd_device_from_gendisk(bdev->bd_disk); + base = dasd_device_from_gendisk(disk); if (!base) return -ENODEV; @@ -3268,14 +3273,12 @@ static int dasd_open(struct block_device *bdev, fmode_t mode) rc = -ENODEV; goto out; } - - if ((mode & FMODE_WRITE) && + if ((mode & BLK_OPEN_WRITE) && (test_bit(DASD_FLAG_DEVICE_RO, &base->flags) || (base->features & DASD_FEATURE_READONLY))) { rc = -EROFS; goto out; } - dasd_put_device(base); return 0; @@ -3287,7 +3290,7 @@ static int dasd_open(struct block_device *bdev, fmode_t mode) return rc; } -static void dasd_release(struct gendisk *disk, fmode_t mode) +static void dasd_release(struct gendisk *disk) { struct dasd_device *base = dasd_device_from_gendisk(disk); if (base) { diff --git a/drivers/s390/block/dasd_diag.c b/drivers/s390/block/dasd_diag.c index f956a4ac9881a7cdaf1994ffb2e7b71af4565638..2e4e555b37c33293c7b4dde87d29500748cbd2c3 100644 --- a/drivers/s390/block/dasd_diag.c +++ b/drivers/s390/block/dasd_diag.c @@ -24,7 +24,7 @@ #include #include #include -#include +#include #include #include diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index 113c509bf6d052bf70b3642adcf4bb6ad41ffeea..8587e423169ecd2bfc01acc61119ef600cc4a83d 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c @@ -21,13 +21,13 @@ #include #include #include +#include +#include #include #include #include #include -#include -#include #include #include #include diff --git a/drivers/s390/block/dasd_fba.c b/drivers/s390/block/dasd_fba.c index bcb67fa747a7a5d3eede0104c73bdbfd8023d66f..c06fa2b27120572bca1695c10690ed8fa8f4a9b3 100644 --- a/drivers/s390/block/dasd_fba.c +++ b/drivers/s390/block/dasd_fba.c @@ -16,10 +16,10 @@ #include #include #include +#include #include #include -#include #include #include "dasd_int.h" diff --git a/drivers/s390/block/dasd_genhd.c b/drivers/s390/block/dasd_genhd.c index 998a961e170417ae3fe882a0f80284cbca56b530..fe5108a1b332eaa62d2a213a11a0dccd8d3c8a24 100644 --- a/drivers/s390/block/dasd_genhd.c +++ b/drivers/s390/block/dasd_genhd.c @@ -130,7 +130,8 @@ int dasd_scan_partitions(struct dasd_block *block) struct block_device *bdev; int rc; - bdev = blkdev_get_by_dev(disk_devt(block->gdp), FMODE_READ, NULL); + bdev = blkdev_get_by_dev(disk_devt(block->gdp), BLK_OPEN_READ, NULL, + NULL); if (IS_ERR(bdev)) { DBF_DEV_EVENT(DBF_ERR, block->base, "scan partitions error, blkdev_get returned %ld", @@ -179,7 +180,7 @@ void dasd_destroy_partitions(struct dasd_block *block) mutex_unlock(&bdev->bd_disk->open_mutex); /* Matching blkdev_put to the blkdev_get in dasd_scan_partitions. */ - blkdev_put(bdev, FMODE_READ); + blkdev_put(bdev, NULL); } int dasd_gendisk_init(void) diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h index 33f812f0e5150479beeeee52c7448d007e83ebf5..0aa56351da720ebf8807a581ba9bd1d08b1a0a2b 100644 --- a/drivers/s390/block/dasd_int.h +++ b/drivers/s390/block/dasd_int.h @@ -965,7 +965,8 @@ int dasd_scan_partitions(struct dasd_block *); void dasd_destroy_partitions(struct dasd_block *); /* externals in dasd_ioctl.c */ -int dasd_ioctl(struct block_device *, fmode_t, unsigned int, unsigned long); +int dasd_ioctl(struct block_device *bdev, blk_mode_t mode, unsigned int cmd, + unsigned long arg); int dasd_set_read_only(struct block_device *bdev, bool ro); /* externals in dasd_proc.c */ diff --git a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c index 8fca725b3daeceda4f80be4200d65464349aae9f..513a7e6eee639e2fccd144e62a29817810ba2783 100644 --- a/drivers/s390/block/dasd_ioctl.c +++ b/drivers/s390/block/dasd_ioctl.c @@ -612,7 +612,7 @@ static int dasd_ioctl_readall_cmb(struct dasd_block *block, unsigned int cmd, return ret; } -int dasd_ioctl(struct block_device *bdev, fmode_t mode, +int dasd_ioctl(struct block_device *bdev, blk_mode_t mode, unsigned int cmd, unsigned long arg) { struct dasd_block *block; diff --git a/drivers/s390/block/dcssblk.c b/drivers/s390/block/dcssblk.c index c09f2e053bf86358f303927637fc2c6fffb8bbf6..09acf3853a77e9ea3a7616475b766ae51031966b 100644 --- a/drivers/s390/block/dcssblk.c +++ b/drivers/s390/block/dcssblk.c @@ -20,16 +20,16 @@ #include #include #include +#include #include -#include #define DCSSBLK_NAME "dcssblk" #define DCSSBLK_MINORS_PER_DISK 1 #define DCSSBLK_PARM_LEN 400 #define DCSS_BUS_ID_SIZE 20 -static int dcssblk_open(struct block_device *bdev, fmode_t mode); -static void dcssblk_release(struct gendisk *disk, fmode_t mode); +static int dcssblk_open(struct gendisk *disk, blk_mode_t mode); +static void dcssblk_release(struct gendisk *disk); static void dcssblk_submit_bio(struct bio *bio); static long dcssblk_dax_direct_access(struct dax_device *dax_dev, pgoff_t pgoff, long nr_pages, enum dax_access_mode mode, void **kaddr, @@ -54,7 +54,8 @@ static int dcssblk_dax_zero_page_range(struct dax_device *dax_dev, rc = dax_direct_access(dax_dev, pgoff, nr_pages, DAX_ACCESS, &kaddr, NULL); if (rc < 0) - return rc; + return dax_mem2blk_err(rc); + memset(kaddr, 0, nr_pages << PAGE_SHIFT); dax_flush(dax_dev, kaddr, nr_pages << PAGE_SHIFT); return 0; @@ -809,12 +810,11 @@ dcssblk_remove_store(struct device *dev, struct device_attribute *attr, const ch } static int -dcssblk_open(struct block_device *bdev, fmode_t mode) +dcssblk_open(struct gendisk *disk, blk_mode_t mode) { - struct dcssblk_dev_info *dev_info; + struct dcssblk_dev_info *dev_info = disk->private_data; int rc; - dev_info = bdev->bd_disk->private_data; if (NULL == dev_info) { rc = -ENODEV; goto out; @@ -826,7 +826,7 @@ dcssblk_open(struct block_device *bdev, fmode_t mode) } static void -dcssblk_release(struct gendisk *disk, fmode_t mode) +dcssblk_release(struct gendisk *disk) { struct dcssblk_dev_info *dev_info = disk->private_data; struct segment_info *entry; diff --git a/drivers/s390/char/Kconfig b/drivers/s390/char/Kconfig index 80c4e5101c9712f2421e6ebec01b91153ebeaa82..8a03af5ee5b30015aa60e658c70e663776dd6478 100644 --- a/drivers/s390/char/Kconfig +++ b/drivers/s390/char/Kconfig @@ -96,7 +96,7 @@ config SCLP_OFB config S390_UV_UAPI def_tristate m prompt "Ultravisor userspace API" - depends on S390 + depends on S390 && (KVM || PROTECTED_VIRTUALIZATION_GUEST) help Selecting exposes parts of the UV interface to userspace by providing a misc character device at /dev/uv. diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c index 0b05cd76b7d03f26f74d8ad0f2611f05db314a42..a1fef666c9b08c8404a70a702dc5fa2ee245eb35 100644 --- a/drivers/s390/char/con3215.c +++ b/drivers/s390/char/con3215.c @@ -25,7 +25,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/drivers/s390/char/monwriter.c b/drivers/s390/char/monwriter.c index 9cd1ea92d619b3bfbb2f1971361447272f354f9e..bc5193d81f9c9f4deceab7ed61c5f5f0eec77b88 100644 --- a/drivers/s390/char/monwriter.c +++ b/drivers/s390/char/monwriter.c @@ -22,8 +22,8 @@ #include #include #include +#include #include -#include #include #include diff --git a/drivers/s390/char/uvdevice.c b/drivers/s390/char/uvdevice.c index 1d40457c7b10e9376c771eed3931c73d05002228..144cd2e035909bceac10bd75e00ec9b7b721d6e5 100644 --- a/drivers/s390/char/uvdevice.c +++ b/drivers/s390/char/uvdevice.c @@ -32,6 +32,55 @@ #include #include +#define BIT_UVIO_INTERNAL U32_MAX +/* Mapping from IOCTL-nr to UVC-bit */ +static const u32 ioctl_nr_to_uvc_bit[] __initconst = { + [UVIO_IOCTL_UVDEV_INFO_NR] = BIT_UVIO_INTERNAL, + [UVIO_IOCTL_ATT_NR] = BIT_UVC_CMD_RETR_ATTEST, + [UVIO_IOCTL_ADD_SECRET_NR] = BIT_UVC_CMD_ADD_SECRET, + [UVIO_IOCTL_LIST_SECRETS_NR] = BIT_UVC_CMD_LIST_SECRETS, + [UVIO_IOCTL_LOCK_SECRETS_NR] = BIT_UVC_CMD_LOCK_SECRETS, +}; + +static_assert(ARRAY_SIZE(ioctl_nr_to_uvc_bit) == UVIO_IOCTL_NUM_IOCTLS); + +static struct uvio_uvdev_info uvdev_info = { + .supp_uvio_cmds = GENMASK_ULL(UVIO_IOCTL_NUM_IOCTLS - 1, 0), +}; + +static void __init set_supp_uv_cmds(unsigned long *supp_uv_cmds) +{ + int i; + + for (i = 0; i < UVIO_IOCTL_NUM_IOCTLS; i++) { + if (ioctl_nr_to_uvc_bit[i] == BIT_UVIO_INTERNAL) + continue; + if (!test_bit_inv(ioctl_nr_to_uvc_bit[i], uv_info.inst_calls_list)) + continue; + __set_bit(i, supp_uv_cmds); + } +} + +/** + * uvio_uvdev_info() - get information about the uvdevice + * + * @uv_ioctl: ioctl control block + * + * Lists all IOCTLs that are supported by this uvdevice + */ +static int uvio_uvdev_info(struct uvio_ioctl_cb *uv_ioctl) +{ + void __user *user_buf_arg = (void __user *)uv_ioctl->argument_addr; + + if (uv_ioctl->argument_len < sizeof(uvdev_info)) + return -EINVAL; + if (copy_to_user(user_buf_arg, &uvdev_info, sizeof(uvdev_info))) + return -EFAULT; + + uv_ioctl->uv_rc = UVC_RC_EXECUTED; + return 0; +} + static int uvio_build_uvcb_attest(struct uv_cb_attest *uvcb_attest, u8 *arcb, u8 *meas, u8 *add_data, struct uvio_attest *uvio_attest) { @@ -185,8 +234,161 @@ static int uvio_attestation(struct uvio_ioctl_cb *uv_ioctl) return ret; } -static int uvio_copy_and_check_ioctl(struct uvio_ioctl_cb *ioctl, void __user *argp) +/** uvio_add_secret() - perform an Add Secret UVC + * + * @uv_ioctl: ioctl control block + * + * uvio_add_secret() performs the Add Secret Ultravisor Call. + * + * The given userspace argument address and size are verified to be + * valid but every other check is made by the Ultravisor + * (UV). Therefore UV errors won't result in a negative return + * value. The request is then copied to kernelspace, the UV-call is + * performed and the results are copied back to userspace. + * + * The argument has to point to an Add Secret Request Control Block + * which is an encrypted and cryptographically verified request that + * inserts a protected guest's secrets into the Ultravisor for later + * use. + * + * If the Add Secret UV facility is not present, UV will return + * invalid command rc. This won't be fenced in the driver and does not + * result in a negative return value. + * + * Context: might sleep + * + * Return: 0 on success or a negative error code on error. + */ +static int uvio_add_secret(struct uvio_ioctl_cb *uv_ioctl) { + void __user *user_buf_arg = (void __user *)uv_ioctl->argument_addr; + struct uv_cb_guest_addr uvcb = { + .header.len = sizeof(uvcb), + .header.cmd = UVC_CMD_ADD_SECRET, + }; + void *asrcb = NULL; + int ret; + + if (uv_ioctl->argument_len > UVIO_ADD_SECRET_MAX_LEN) + return -EINVAL; + if (uv_ioctl->argument_len == 0) + return -EINVAL; + + asrcb = kvzalloc(uv_ioctl->argument_len, GFP_KERNEL); + if (!asrcb) + return -ENOMEM; + + ret = -EFAULT; + if (copy_from_user(asrcb, user_buf_arg, uv_ioctl->argument_len)) + goto out; + + ret = 0; + uvcb.addr = (u64)asrcb; + uv_call_sched(0, (u64)&uvcb); + uv_ioctl->uv_rc = uvcb.header.rc; + uv_ioctl->uv_rrc = uvcb.header.rrc; + +out: + kvfree(asrcb); + return ret; +} + +/** uvio_list_secrets() - perform a List Secret UVC + * @uv_ioctl: ioctl control block + * + * uvio_list_secrets() performs the List Secret Ultravisor Call. It verifies + * that the given userspace argument address is valid and its size is sane. + * Every other check is made by the Ultravisor (UV) and won't result in a + * negative return value. It builds the request, performs the UV-call, and + * copies the result to userspace. + * + * The argument specifies the location for the result of the UV-Call. + * + * If the List Secrets UV facility is not present, UV will return invalid + * command rc. This won't be fenced in the driver and does not result in a + * negative return value. + * + * Context: might sleep + * + * Return: 0 on success or a negative error code on error. + */ +static int uvio_list_secrets(struct uvio_ioctl_cb *uv_ioctl) +{ + void __user *user_buf_arg = (void __user *)uv_ioctl->argument_addr; + struct uv_cb_guest_addr uvcb = { + .header.len = sizeof(uvcb), + .header.cmd = UVC_CMD_LIST_SECRETS, + }; + void *secrets = NULL; + int ret = 0; + + if (uv_ioctl->argument_len != UVIO_LIST_SECRETS_LEN) + return -EINVAL; + + secrets = kvzalloc(UVIO_LIST_SECRETS_LEN, GFP_KERNEL); + if (!secrets) + return -ENOMEM; + + uvcb.addr = (u64)secrets; + uv_call_sched(0, (u64)&uvcb); + uv_ioctl->uv_rc = uvcb.header.rc; + uv_ioctl->uv_rrc = uvcb.header.rrc; + + if (copy_to_user(user_buf_arg, secrets, UVIO_LIST_SECRETS_LEN)) + ret = -EFAULT; + + kvfree(secrets); + return ret; +} + +/** uvio_lock_secrets() - perform a Lock Secret Store UVC + * @uv_ioctl: ioctl control block + * + * uvio_lock_secrets() performs the Lock Secret Store Ultravisor Call. It + * performs the UV-call and copies the return codes to the ioctl control block. + * After this call was dispatched successfully every following Add Secret UVC + * and Lock Secrets UVC will fail with return code 0x102. + * + * The argument address and size must be 0. + * + * If the Lock Secrets UV facility is not present, UV will return invalid + * command rc. This won't be fenced in the driver and does not result in a + * negative return value. + * + * Context: might sleep + * + * Return: 0 on success or a negative error code on error. + */ +static int uvio_lock_secrets(struct uvio_ioctl_cb *ioctl) +{ + struct uv_cb_nodata uvcb = { + .header.len = sizeof(uvcb), + .header.cmd = UVC_CMD_LOCK_SECRETS, + }; + + if (ioctl->argument_addr || ioctl->argument_len) + return -EINVAL; + + uv_call(0, (u64)&uvcb); + ioctl->uv_rc = uvcb.header.rc; + ioctl->uv_rrc = uvcb.header.rrc; + + return 0; +} + +static int uvio_copy_and_check_ioctl(struct uvio_ioctl_cb *ioctl, void __user *argp, + unsigned long cmd) +{ + u8 nr = _IOC_NR(cmd); + + if (_IOC_DIR(cmd) != (_IOC_READ | _IOC_WRITE)) + return -ENOIOCTLCMD; + if (_IOC_TYPE(cmd) != UVIO_TYPE_UVC) + return -ENOIOCTLCMD; + if (nr >= UVIO_IOCTL_NUM_IOCTLS) + return -ENOIOCTLCMD; + if (_IOC_SIZE(cmd) != sizeof(*ioctl)) + return -ENOIOCTLCMD; if (copy_from_user(ioctl, argp, sizeof(*ioctl))) return -EFAULT; if (ioctl->flags != 0) @@ -194,7 +396,7 @@ static int uvio_copy_and_check_ioctl(struct uvio_ioctl_cb *ioctl, void __user *a if (memchr_inv(ioctl->reserved14, 0, sizeof(ioctl->reserved14))) return -EINVAL; - return 0; + return nr; } /* @@ -205,14 +407,28 @@ static long uvio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) void __user *argp = (void __user *)arg; struct uvio_ioctl_cb uv_ioctl = { }; long ret; + int nr; - switch (cmd) { - case UVIO_IOCTL_ATT: - ret = uvio_copy_and_check_ioctl(&uv_ioctl, argp); - if (ret) - return ret; + nr = uvio_copy_and_check_ioctl(&uv_ioctl, argp, cmd); + if (nr < 0) + return nr; + + switch (nr) { + case UVIO_IOCTL_UVDEV_INFO_NR: + ret = uvio_uvdev_info(&uv_ioctl); + break; + case UVIO_IOCTL_ATT_NR: ret = uvio_attestation(&uv_ioctl); break; + case UVIO_IOCTL_ADD_SECRET_NR: + ret = uvio_add_secret(&uv_ioctl); + break; + case UVIO_IOCTL_LIST_SECRETS_NR: + ret = uvio_list_secrets(&uv_ioctl); + break; + case UVIO_IOCTL_LOCK_SECRETS_NR: + ret = uvio_lock_secrets(&uv_ioctl); + break; default: ret = -ENOIOCTLCMD; break; @@ -245,6 +461,7 @@ static void __exit uvio_dev_exit(void) static int __init uvio_dev_init(void) { + set_supp_uv_cmds((unsigned long *)&uvdev_info.supp_uv_cmds); return misc_register(&uvio_dev_miscdev); } diff --git a/drivers/s390/char/zcore.c b/drivers/s390/char/zcore.c index 599f547310f8f4412795cc2d0071406d6640d384..942c73a11ca35c6cd3e3898e98632e0a769fce5f 100644 --- a/drivers/s390/char/zcore.c +++ b/drivers/s390/char/zcore.c @@ -51,6 +51,7 @@ static struct dentry *zcore_dir; static struct dentry *zcore_reipl_file; static struct dentry *zcore_hsa_file; static struct ipl_parameter_block *zcore_ipl_block; +static unsigned long os_info_flags; static DEFINE_MUTEX(hsa_buf_mutex); static char hsa_buf[PAGE_SIZE] __aligned(PAGE_SIZE); @@ -139,7 +140,13 @@ static ssize_t zcore_reipl_write(struct file *filp, const char __user *buf, { if (zcore_ipl_block) { diag308(DIAG308_SET, zcore_ipl_block); - diag308(DIAG308_LOAD_CLEAR, NULL); + if (os_info_flags & OS_INFO_FLAG_REIPL_CLEAR) + diag308(DIAG308_LOAD_CLEAR, NULL); + /* Use special diag308 subcode for CCW normal ipl */ + if (zcore_ipl_block->pb0_hdr.pbt == IPL_PBT_CCW) + diag308(DIAG308_LOAD_NORMAL_DUMP, NULL); + else + diag308(DIAG308_LOAD_NORMAL, NULL); } return count; } @@ -212,7 +219,10 @@ static int __init check_sdias(void) */ static int __init zcore_reipl_init(void) { + struct os_info_entry *entry; struct ipib_info ipib_info; + unsigned long os_info_addr; + struct os_info *os_info; int rc; rc = memcpy_hsa_kernel(&ipib_info, __LC_DUMP_REIPL, sizeof(ipib_info)); @@ -234,6 +244,35 @@ static int __init zcore_reipl_init(void) free_page((unsigned long) zcore_ipl_block); zcore_ipl_block = NULL; } + /* + * Read the bit-flags field from os_info flags entry. + * Return zero even for os_info read or entry checksum errors in order + * to continue dump processing, considering that os_info could be + * corrupted on the panicked system. + */ + os_info = (void *)__get_free_page(GFP_KERNEL); + if (!os_info) + return -ENOMEM; + rc = memcpy_hsa_kernel(&os_info_addr, __LC_OS_INFO, sizeof(os_info_addr)); + if (rc) + goto out; + if (os_info_addr < sclp.hsa_size) + rc = memcpy_hsa_kernel(os_info, os_info_addr, PAGE_SIZE); + else + rc = memcpy_real(os_info, os_info_addr, PAGE_SIZE); + if (rc || os_info_csum(os_info) != os_info->csum) + goto out; + entry = &os_info->entry[OS_INFO_FLAGS_ENTRY]; + if (entry->addr && entry->size) { + if (entry->addr < sclp.hsa_size) + rc = memcpy_hsa_kernel(&os_info_flags, entry->addr, sizeof(os_info_flags)); + else + rc = memcpy_real(&os_info_flags, entry->addr, sizeof(os_info_flags)); + if (rc || (__force u32)csum_partial(&os_info_flags, entry->size, 0) != entry->csum) + os_info_flags = 0; + } +out: + free_page((unsigned long)os_info); return 0; } diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c index f0538609dfe429b6caec78c766116de6a8b97d8c..aa3292e57e3838c0e30d2c1302fa4b7dcb36b7e7 100644 --- a/drivers/s390/cio/ccwgroup.c +++ b/drivers/s390/cio/ccwgroup.c @@ -152,7 +152,7 @@ static ssize_t ccwgroup_online_show(struct device *dev, /* * Provide an 'ungroup' attribute so the user can remove group devices no - * longer needed or accidentially created. Saves memory :) + * longer needed or accidentally created. Saves memory :) */ static void ccwgroup_ungroup(struct ccwgroup_device *gdev) { diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index c0d620ffea618e87da0ca248cc2effbc3800cc62..4ca5adce91079b75a6804e96cd0dbc7578a4b078 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c @@ -943,7 +943,7 @@ static int ccw_device_move_to_sch(struct ccw_device *cdev, cdev->private->dev_id.devno, sch->schid.ssid, sch->schib.pmcw.dev, rc); if (old_enabled) { - /* Try to reenable the old subchannel. */ + /* Try to re-enable the old subchannel. */ spin_lock_irq(old_sch->lock); cio_enable_subchannel(old_sch, (u32)virt_to_phys(old_sch)); spin_unlock_irq(old_sch->lock); diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c index 2b2058427a2b120576ea551b6eb2430db4e8456b..c396ac3e3a3272571132e859dbe21666de0c7b0e 100644 --- a/drivers/s390/cio/device_fsm.c +++ b/drivers/s390/cio/device_fsm.c @@ -310,7 +310,7 @@ static void ccw_device_oper_notify(struct ccw_device *cdev) struct subchannel *sch = to_subchannel(cdev->dev.parent); if (ccw_device_notify(cdev, CIO_OPER) == NOTIFY_OK) { - /* Reenable channel measurements, if needed. */ + /* Re-enable channel measurements, if needed. */ ccw_device_sched_todo(cdev, CDEV_TODO_ENABLE_CMF); /* Save indication for new paths. */ cdev->private->path_new_mask = sch->vpm; @@ -947,7 +947,7 @@ void ccw_device_trigger_reprobe(struct ccw_device *cdev) */ sch->lpm = sch->schib.pmcw.pam & sch->opm; /* - * Use the initial configuration since we can't be shure that the old + * Use the initial configuration since we can't be sure that the old * paths are valid. */ io_subchannel_init_config(sch); diff --git a/drivers/s390/cio/vfio_ccw_cp.c b/drivers/s390/cio/vfio_ccw_cp.c index 1c31e81ca8de1c41555285ddf69522260a7f3c7e..aafd66305eadebf66170bc6d7049002e9e31b1f2 100644 --- a/drivers/s390/cio/vfio_ccw_cp.c +++ b/drivers/s390/cio/vfio_ccw_cp.c @@ -672,7 +672,7 @@ static int ccwchain_fetch_ccw(struct ccw1 *ccw, /* * Fetch one ccw. * To reduce memory copy, we'll pin the cda page in memory, - * and to get rid of the cda 2G limitiaion of ccw1, we'll translate + * and to get rid of the cda 2G limitation of ccw1, we'll translate * direct ccws to idal ccws. */ static int ccwchain_fetch_one(struct ccw1 *ccw, @@ -787,7 +787,7 @@ void cp_free(struct channel_program *cp) * program. * * These APIs will copy the ccws into kernel-space buffers, and update - * the guest phsical addresses with their corresponding host physical + * the guest physical addresses with their corresponding host physical * addresses. Then channel I/O device drivers could issue the * translated channel program to real devices to perform an I/O * operation. diff --git a/drivers/s390/cio/vfio_ccw_drv.c b/drivers/s390/cio/vfio_ccw_drv.c index ff538a086fc77e62f96b97b9811ec7bd71322565..43601816ea4e4fdb3a45a7ce90096b375e9ca8d6 100644 --- a/drivers/s390/cio/vfio_ccw_drv.c +++ b/drivers/s390/cio/vfio_ccw_drv.c @@ -171,7 +171,7 @@ static int vfio_ccw_sch_probe(struct subchannel *sch) return -ENODEV; } - parent = kzalloc(sizeof(*parent), GFP_KERNEL); + parent = kzalloc(struct_size(parent, mdev_types, 1), GFP_KERNEL); if (!parent) return -ENOMEM; diff --git a/drivers/s390/cio/vfio_ccw_private.h b/drivers/s390/cio/vfio_ccw_private.h index b441ae6700fd235e6bb2044b6cda33b217c5dfe6..b62bbc5c637692566aad4a0350f8e38203e8580e 100644 --- a/drivers/s390/cio/vfio_ccw_private.h +++ b/drivers/s390/cio/vfio_ccw_private.h @@ -79,7 +79,7 @@ struct vfio_ccw_parent { struct mdev_parent parent; struct mdev_type mdev_type; - struct mdev_type *mdev_types[1]; + struct mdev_type *mdev_types[]; }; /** diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c index 8d6b9a52bf3cbd1a711ab75df24e032acaeb8385..420120be300f592d4ec22f9756dc19be213023c4 100644 --- a/drivers/s390/crypto/ap_bus.c +++ b/drivers/s390/crypto/ap_bus.c @@ -497,7 +497,7 @@ static void ap_tasklet_fn(unsigned long dummy) enum ap_sm_wait wait = AP_SM_WAIT_NONE; /* Reset the indicator if interrupts are used. Thus new interrupts can - * be received. Doing it in the beginning of the tasklet is therefor + * be received. Doing it in the beginning of the tasklet is therefore * important that no requests on any AP get lost. */ if (ap_irq_flag) @@ -2289,7 +2289,7 @@ static int __init ap_module_init(void) timer_setup(&ap_config_timer, ap_config_timeout, 0); /* - * Setup the high resultion poll timer. + * Setup the high resolution poll timer. * If we are running under z/VM adjust polling to z/VM polling rate. */ if (MACHINE_IS_VM) diff --git a/drivers/s390/crypto/ap_bus.h b/drivers/s390/crypto/ap_bus.h index 101fb324476f6130403804ea1bf6e69d3cf36aa3..0d7b7eb374ad1a9121af1a934053ade55bcf70cf 100644 --- a/drivers/s390/crypto/ap_bus.h +++ b/drivers/s390/crypto/ap_bus.h @@ -233,30 +233,6 @@ struct ap_queue { typedef enum ap_sm_wait (ap_func_t)(struct ap_queue *queue); -/* failure injection cmd struct */ -struct ap_fi { - union { - u16 cmd; /* fi flags + action */ - struct { - u8 flags; /* fi flags only */ - u8 action; /* fi action only */ - }; - }; -}; - -/* all currently known fi actions */ -enum ap_fi_actions { - AP_FI_ACTION_CCA_AGENT_FF = 0x01, - AP_FI_ACTION_CCA_DOM_INVAL = 0x02, - AP_FI_ACTION_NQAP_QID_INVAL = 0x03, -}; - -/* all currently known fi flags */ -enum ap_fi_flags { - AP_FI_FLAG_NO_RETRY = 0x01, - AP_FI_FLAG_TOGGLE_SPECIAL = 0x02, -}; - struct ap_message { struct list_head list; /* Request queueing. */ unsigned long psmid; /* Message id. */ @@ -264,7 +240,6 @@ struct ap_message { size_t len; /* actual msg len in msg buffer */ size_t bufsize; /* allocated msg buffer size */ u16 flags; /* Flags, see AP_MSG_FLAG_xxx */ - struct ap_fi fi; /* Failure Injection cmd */ int rc; /* Return code for this message */ void *private; /* ap driver private pointer. */ /* receive is called from tasklet context */ @@ -384,7 +359,7 @@ int ap_apqn_in_matrix_owned_by_def_drv(unsigned long *apm, * like "+1-16,-32,-0x40,+128" where only single bits or ranges of * bits are cleared or set. Distinction is done based on the very * first character which may be '+' or '-' for the relative string - * and othewise assume to be an absolute value string. If parsing fails + * and otherwise assume to be an absolute value string. If parsing fails * a negative errno value is returned. All arguments and bitmaps are * big endian order. */ diff --git a/drivers/s390/crypto/ap_queue.c b/drivers/s390/crypto/ap_queue.c index ed8f813653fe95a2b2b27262bd2e7543ab80e5be..30df83735adf3452508a232c61fc53e5843fdccc 100644 --- a/drivers/s390/crypto/ap_queue.c +++ b/drivers/s390/crypto/ap_queue.c @@ -274,13 +274,6 @@ static enum ap_sm_wait ap_sm_write(struct ap_queue *aq) /* Start the next request on the queue. */ ap_msg = list_entry(aq->requestq.next, struct ap_message, list); -#ifdef CONFIG_ZCRYPT_DEBUG - if (ap_msg->fi.action == AP_FI_ACTION_NQAP_QID_INVAL) { - AP_DBF_WARN("%s fi cmd 0x%04x: forcing invalid qid 0xFF00\n", - __func__, ap_msg->fi.cmd); - qid = 0xFF00; - } -#endif status = __ap_send(qid, ap_msg->psmid, ap_msg->msg, ap_msg->len, ap_msg->flags & AP_MSG_FLAG_SPECIAL); diff --git a/drivers/s390/crypto/pkey_api.c b/drivers/s390/crypto/pkey_api.c index a8def50c149bd433b1324cbd6d3798ea4130bc7e..e58bfd2253231d93203d8fe09b2a926bc7d85cd9 100644 --- a/drivers/s390/crypto/pkey_api.c +++ b/drivers/s390/crypto/pkey_api.c @@ -2,7 +2,8 @@ /* * pkey device driver * - * Copyright IBM Corp. 2017,2019 + * Copyright IBM Corp. 2017, 2023 + * * Author(s): Harald Freudenberger */ @@ -32,8 +33,10 @@ MODULE_AUTHOR("IBM Corporation"); MODULE_DESCRIPTION("s390 protected key interface"); #define KEYBLOBBUFSIZE 8192 /* key buffer size used for internal processing */ +#define MINKEYBLOBBUFSIZE (sizeof(struct keytoken_header)) #define PROTKEYBLOBBUFSIZE 256 /* protected key buffer size used internal */ #define MAXAPQNSINLIST 64 /* max 64 apqns within a apqn list */ +#define AES_WK_VP_SIZE 32 /* Size of WK VP block appended to a prot key */ /* * debug feature data and functions @@ -71,49 +74,106 @@ struct protaeskeytoken { } __packed; /* inside view of a clear key token (type 0x00 version 0x02) */ -struct clearaeskeytoken { - u8 type; /* 0x00 for PAES specific key tokens */ +struct clearkeytoken { + u8 type; /* 0x00 for PAES specific key tokens */ u8 res0[3]; - u8 version; /* 0x02 for clear AES key token */ + u8 version; /* 0x02 for clear key token */ u8 res1[3]; - u32 keytype; /* key type, one of the PKEY_KEYTYPE values */ - u32 len; /* bytes actually stored in clearkey[] */ + u32 keytype; /* key type, one of the PKEY_KEYTYPE_* values */ + u32 len; /* bytes actually stored in clearkey[] */ u8 clearkey[]; /* clear key value */ } __packed; +/* helper function which translates the PKEY_KEYTYPE_AES_* to their keysize */ +static inline u32 pkey_keytype_aes_to_size(u32 keytype) +{ + switch (keytype) { + case PKEY_KEYTYPE_AES_128: + return 16; + case PKEY_KEYTYPE_AES_192: + return 24; + case PKEY_KEYTYPE_AES_256: + return 32; + default: + return 0; + } +} + /* - * Create a protected key from a clear key value. + * Create a protected key from a clear key value via PCKMO instruction. */ -static int pkey_clr2protkey(u32 keytype, - const struct pkey_clrkey *clrkey, - struct pkey_protkey *protkey) +static int pkey_clr2protkey(u32 keytype, const u8 *clrkey, + u8 *protkey, u32 *protkeylen, u32 *protkeytype) { /* mask of available pckmo subfunctions */ static cpacf_mask_t pckmo_functions; - long fc; + u8 paramblock[112]; + u32 pkeytype; int keysize; - u8 paramblock[64]; + long fc; switch (keytype) { case PKEY_KEYTYPE_AES_128: + /* 16 byte key, 32 byte aes wkvp, total 48 bytes */ keysize = 16; + pkeytype = keytype; fc = CPACF_PCKMO_ENC_AES_128_KEY; break; case PKEY_KEYTYPE_AES_192: + /* 24 byte key, 32 byte aes wkvp, total 56 bytes */ keysize = 24; + pkeytype = keytype; fc = CPACF_PCKMO_ENC_AES_192_KEY; break; case PKEY_KEYTYPE_AES_256: + /* 32 byte key, 32 byte aes wkvp, total 64 bytes */ keysize = 32; + pkeytype = keytype; fc = CPACF_PCKMO_ENC_AES_256_KEY; break; + case PKEY_KEYTYPE_ECC_P256: + /* 32 byte key, 32 byte aes wkvp, total 64 bytes */ + keysize = 32; + pkeytype = PKEY_KEYTYPE_ECC; + fc = CPACF_PCKMO_ENC_ECC_P256_KEY; + break; + case PKEY_KEYTYPE_ECC_P384: + /* 48 byte key, 32 byte aes wkvp, total 80 bytes */ + keysize = 48; + pkeytype = PKEY_KEYTYPE_ECC; + fc = CPACF_PCKMO_ENC_ECC_P384_KEY; + break; + case PKEY_KEYTYPE_ECC_P521: + /* 80 byte key, 32 byte aes wkvp, total 112 bytes */ + keysize = 80; + pkeytype = PKEY_KEYTYPE_ECC; + fc = CPACF_PCKMO_ENC_ECC_P521_KEY; + break; + case PKEY_KEYTYPE_ECC_ED25519: + /* 32 byte key, 32 byte aes wkvp, total 64 bytes */ + keysize = 32; + pkeytype = PKEY_KEYTYPE_ECC; + fc = CPACF_PCKMO_ENC_ECC_ED25519_KEY; + break; + case PKEY_KEYTYPE_ECC_ED448: + /* 64 byte key, 32 byte aes wkvp, total 96 bytes */ + keysize = 64; + pkeytype = PKEY_KEYTYPE_ECC; + fc = CPACF_PCKMO_ENC_ECC_ED448_KEY; + break; default: - DEBUG_ERR("%s unknown/unsupported keytype %d\n", + DEBUG_ERR("%s unknown/unsupported keytype %u\n", __func__, keytype); return -EINVAL; } + if (*protkeylen < keysize + AES_WK_VP_SIZE) { + DEBUG_ERR("%s prot key buffer size too small: %u < %d\n", + __func__, *protkeylen, keysize + AES_WK_VP_SIZE); + return -EINVAL; + } + /* Did we already check for PCKMO ? */ if (!pckmo_functions.bytes[0]) { /* no, so check now */ @@ -128,15 +188,15 @@ static int pkey_clr2protkey(u32 keytype, /* prepare param block */ memset(paramblock, 0, sizeof(paramblock)); - memcpy(paramblock, clrkey->clrkey, keysize); + memcpy(paramblock, clrkey, keysize); /* call the pckmo instruction */ cpacf_pckmo(fc, paramblock); - /* copy created protected key */ - protkey->type = keytype; - protkey->len = keysize + 32; - memcpy(protkey->protkey, paramblock, keysize + 32); + /* copy created protected key to key buffer including the wkvp block */ + *protkeylen = keysize + AES_WK_VP_SIZE; + memcpy(protkey, paramblock, *protkeylen); + *protkeytype = pkeytype; return 0; } @@ -144,11 +204,12 @@ static int pkey_clr2protkey(u32 keytype, /* * Find card and transform secure key into protected key. */ -static int pkey_skey2pkey(const u8 *key, struct pkey_protkey *pkey) +static int pkey_skey2pkey(const u8 *key, u8 *protkey, + u32 *protkeylen, u32 *protkeytype) { - int rc, verify; - u16 cardnr, domain; struct keytoken_header *hdr = (struct keytoken_header *)key; + u16 cardnr, domain; + int rc, verify; zcrypt_wait_api_operational(); @@ -167,14 +228,13 @@ static int pkey_skey2pkey(const u8 *key, struct pkey_protkey *pkey) continue; switch (hdr->version) { case TOKVER_CCA_AES: - rc = cca_sec2protkey(cardnr, domain, - key, pkey->protkey, - &pkey->len, &pkey->type); + rc = cca_sec2protkey(cardnr, domain, key, + protkey, protkeylen, protkeytype); break; case TOKVER_CCA_VLSC: - rc = cca_cipher2protkey(cardnr, domain, - key, pkey->protkey, - &pkey->len, &pkey->type); + rc = cca_cipher2protkey(cardnr, domain, key, + protkey, protkeylen, + protkeytype); break; default: return -EINVAL; @@ -195,9 +255,9 @@ static int pkey_skey2pkey(const u8 *key, struct pkey_protkey *pkey) static int pkey_clr2ep11key(const u8 *clrkey, size_t clrkeylen, u8 *keybuf, size_t *keybuflen) { - int i, rc; - u16 card, dom; u32 nr_apqns, *apqns = NULL; + u16 card, dom; + int i, rc; zcrypt_wait_api_operational(); @@ -227,12 +287,13 @@ static int pkey_clr2ep11key(const u8 *clrkey, size_t clrkeylen, /* * Find card and transform EP11 secure key into protected key. */ -static int pkey_ep11key2pkey(const u8 *key, struct pkey_protkey *pkey) +static int pkey_ep11key2pkey(const u8 *key, u8 *protkey, + u32 *protkeylen, u32 *protkeytype) { - int i, rc; - u16 card, dom; - u32 nr_apqns, *apqns = NULL; struct ep11keyblob *kb = (struct ep11keyblob *)key; + u32 nr_apqns, *apqns = NULL; + u16 card, dom; + int i, rc; zcrypt_wait_api_operational(); @@ -246,9 +307,8 @@ static int pkey_ep11key2pkey(const u8 *key, struct pkey_protkey *pkey) for (rc = -ENODEV, i = 0; i < nr_apqns; i++) { card = apqns[i] >> 16; dom = apqns[i] & 0xFFFF; - pkey->len = sizeof(pkey->protkey); rc = ep11_kblob2protkey(card, dom, key, kb->head.len, - pkey->protkey, &pkey->len, &pkey->type); + protkey, protkeylen, protkeytype); if (rc == 0) break; } @@ -306,38 +366,31 @@ static int pkey_verifykey(const struct pkey_seckey *seckey, /* * Generate a random protected key */ -static int pkey_genprotkey(u32 keytype, struct pkey_protkey *protkey) +static int pkey_genprotkey(u32 keytype, u8 *protkey, + u32 *protkeylen, u32 *protkeytype) { - struct pkey_clrkey clrkey; + u8 clrkey[32]; int keysize; int rc; - switch (keytype) { - case PKEY_KEYTYPE_AES_128: - keysize = 16; - break; - case PKEY_KEYTYPE_AES_192: - keysize = 24; - break; - case PKEY_KEYTYPE_AES_256: - keysize = 32; - break; - default: + keysize = pkey_keytype_aes_to_size(keytype); + if (!keysize) { DEBUG_ERR("%s unknown/unsupported keytype %d\n", __func__, keytype); return -EINVAL; } /* generate a dummy random clear key */ - get_random_bytes(clrkey.clrkey, keysize); + get_random_bytes(clrkey, keysize); /* convert it to a dummy protected key */ - rc = pkey_clr2protkey(keytype, &clrkey, protkey); + rc = pkey_clr2protkey(keytype, clrkey, + protkey, protkeylen, protkeytype); if (rc) return rc; /* replace the key part of the protected key with random bytes */ - get_random_bytes(protkey->protkey, keysize); + get_random_bytes(protkey, keysize); return 0; } @@ -345,37 +398,46 @@ static int pkey_genprotkey(u32 keytype, struct pkey_protkey *protkey) /* * Verify if a protected key is still valid */ -static int pkey_verifyprotkey(const struct pkey_protkey *protkey) +static int pkey_verifyprotkey(const u8 *protkey, u32 protkeylen, + u32 protkeytype) { - unsigned long fc; struct { u8 iv[AES_BLOCK_SIZE]; u8 key[MAXPROTKEYSIZE]; } param; u8 null_msg[AES_BLOCK_SIZE]; u8 dest_buf[AES_BLOCK_SIZE]; - unsigned int k; + unsigned int k, pkeylen; + unsigned long fc; - switch (protkey->type) { + switch (protkeytype) { case PKEY_KEYTYPE_AES_128: + pkeylen = 16 + AES_WK_VP_SIZE; fc = CPACF_KMC_PAES_128; break; case PKEY_KEYTYPE_AES_192: + pkeylen = 24 + AES_WK_VP_SIZE; fc = CPACF_KMC_PAES_192; break; case PKEY_KEYTYPE_AES_256: + pkeylen = 32 + AES_WK_VP_SIZE; fc = CPACF_KMC_PAES_256; break; default: - DEBUG_ERR("%s unknown/unsupported keytype %d\n", __func__, - protkey->type); + DEBUG_ERR("%s unknown/unsupported keytype %u\n", __func__, + protkeytype); + return -EINVAL; + } + if (protkeylen != pkeylen) { + DEBUG_ERR("%s invalid protected key size %u for keytype %u\n", + __func__, protkeylen, protkeytype); return -EINVAL; } memset(null_msg, 0, sizeof(null_msg)); memset(param.iv, 0, sizeof(param.iv)); - memcpy(param.key, protkey->protkey, sizeof(param.key)); + memcpy(param.key, protkey, protkeylen); k = cpacf_kmc(fc | CPACF_ENCRYPT, ¶m, null_msg, dest_buf, sizeof(null_msg)); @@ -387,15 +449,119 @@ static int pkey_verifyprotkey(const struct pkey_protkey *protkey) return 0; } +/* Helper for pkey_nonccatok2pkey, handles aes clear key token */ +static int nonccatokaes2pkey(const struct clearkeytoken *t, + u8 *protkey, u32 *protkeylen, u32 *protkeytype) +{ + size_t tmpbuflen = max_t(size_t, SECKEYBLOBSIZE, MAXEP11AESKEYBLOBSIZE); + u8 *tmpbuf = NULL; + u32 keysize; + int rc; + + keysize = pkey_keytype_aes_to_size(t->keytype); + if (!keysize) { + DEBUG_ERR("%s unknown/unsupported keytype %u\n", + __func__, t->keytype); + return -EINVAL; + } + if (t->len != keysize) { + DEBUG_ERR("%s non clear key aes token: invalid key len %u\n", + __func__, t->len); + return -EINVAL; + } + + /* try direct way with the PCKMO instruction */ + rc = pkey_clr2protkey(t->keytype, t->clearkey, + protkey, protkeylen, protkeytype); + if (!rc) + goto out; + + /* PCKMO failed, so try the CCA secure key way */ + tmpbuf = kmalloc(tmpbuflen, GFP_ATOMIC); + if (!tmpbuf) + return -ENOMEM; + zcrypt_wait_api_operational(); + rc = cca_clr2seckey(0xFFFF, 0xFFFF, t->keytype, t->clearkey, tmpbuf); + if (rc) + goto try_via_ep11; + rc = pkey_skey2pkey(tmpbuf, + protkey, protkeylen, protkeytype); + if (!rc) + goto out; + +try_via_ep11: + /* if the CCA way also failed, let's try via EP11 */ + rc = pkey_clr2ep11key(t->clearkey, t->len, + tmpbuf, &tmpbuflen); + if (rc) + goto failure; + rc = pkey_ep11key2pkey(tmpbuf, + protkey, protkeylen, protkeytype); + if (!rc) + goto out; + +failure: + DEBUG_ERR("%s unable to build protected key from clear", __func__); + +out: + kfree(tmpbuf); + return rc; +} + +/* Helper for pkey_nonccatok2pkey, handles ecc clear key token */ +static int nonccatokecc2pkey(const struct clearkeytoken *t, + u8 *protkey, u32 *protkeylen, u32 *protkeytype) +{ + u32 keylen; + int rc; + + switch (t->keytype) { + case PKEY_KEYTYPE_ECC_P256: + keylen = 32; + break; + case PKEY_KEYTYPE_ECC_P384: + keylen = 48; + break; + case PKEY_KEYTYPE_ECC_P521: + keylen = 80; + break; + case PKEY_KEYTYPE_ECC_ED25519: + keylen = 32; + break; + case PKEY_KEYTYPE_ECC_ED448: + keylen = 64; + break; + default: + DEBUG_ERR("%s unknown/unsupported keytype %u\n", + __func__, t->keytype); + return -EINVAL; + } + + if (t->len != keylen) { + DEBUG_ERR("%s non clear key ecc token: invalid key len %u\n", + __func__, t->len); + return -EINVAL; + } + + /* only one path possible: via PCKMO instruction */ + rc = pkey_clr2protkey(t->keytype, t->clearkey, + protkey, protkeylen, protkeytype); + if (rc) { + DEBUG_ERR("%s unable to build protected key from clear", + __func__); + } + + return rc; +} + /* * Transform a non-CCA key token into a protected key */ static int pkey_nonccatok2pkey(const u8 *key, u32 keylen, - struct pkey_protkey *protkey) + u8 *protkey, u32 *protkeylen, u32 *protkeytype) { - int rc = -EINVAL; - u8 *tmpbuf = NULL; struct keytoken_header *hdr = (struct keytoken_header *)key; + int rc = -EINVAL; switch (hdr->version) { case TOKVER_PROTECTED_KEY: { @@ -404,59 +570,40 @@ static int pkey_nonccatok2pkey(const u8 *key, u32 keylen, if (keylen != sizeof(struct protaeskeytoken)) goto out; t = (struct protaeskeytoken *)key; - protkey->len = t->len; - protkey->type = t->keytype; - memcpy(protkey->protkey, t->protkey, - sizeof(protkey->protkey)); - rc = pkey_verifyprotkey(protkey); + rc = pkey_verifyprotkey(t->protkey, t->len, t->keytype); + if (rc) + goto out; + memcpy(protkey, t->protkey, t->len); + *protkeylen = t->len; + *protkeytype = t->keytype; break; } case TOKVER_CLEAR_KEY: { - struct clearaeskeytoken *t; - struct pkey_clrkey ckey; - union u_tmpbuf { - u8 skey[SECKEYBLOBSIZE]; - u8 ep11key[MAXEP11AESKEYBLOBSIZE]; - }; - size_t tmpbuflen = sizeof(union u_tmpbuf); - - if (keylen < sizeof(struct clearaeskeytoken)) - goto out; - t = (struct clearaeskeytoken *)key; - if (keylen != sizeof(*t) + t->len) - goto out; - if ((t->keytype == PKEY_KEYTYPE_AES_128 && t->len == 16) || - (t->keytype == PKEY_KEYTYPE_AES_192 && t->len == 24) || - (t->keytype == PKEY_KEYTYPE_AES_256 && t->len == 32)) - memcpy(ckey.clrkey, t->clearkey, t->len); - else - goto out; - /* alloc temp key buffer space */ - tmpbuf = kmalloc(tmpbuflen, GFP_ATOMIC); - if (!tmpbuf) { - rc = -ENOMEM; + struct clearkeytoken *t = (struct clearkeytoken *)key; + + if (keylen < sizeof(struct clearkeytoken) || + keylen != sizeof(*t) + t->len) goto out; - } - /* try direct way with the PCKMO instruction */ - rc = pkey_clr2protkey(t->keytype, &ckey, protkey); - if (rc == 0) + switch (t->keytype) { + case PKEY_KEYTYPE_AES_128: + case PKEY_KEYTYPE_AES_192: + case PKEY_KEYTYPE_AES_256: + rc = nonccatokaes2pkey(t, protkey, + protkeylen, protkeytype); break; - /* PCKMO failed, so try the CCA secure key way */ - zcrypt_wait_api_operational(); - rc = cca_clr2seckey(0xFFFF, 0xFFFF, t->keytype, - ckey.clrkey, tmpbuf); - if (rc == 0) - rc = pkey_skey2pkey(tmpbuf, protkey); - if (rc == 0) + case PKEY_KEYTYPE_ECC_P256: + case PKEY_KEYTYPE_ECC_P384: + case PKEY_KEYTYPE_ECC_P521: + case PKEY_KEYTYPE_ECC_ED25519: + case PKEY_KEYTYPE_ECC_ED448: + rc = nonccatokecc2pkey(t, protkey, + protkeylen, protkeytype); break; - /* if the CCA way also failed, let's try via EP11 */ - rc = pkey_clr2ep11key(ckey.clrkey, t->len, - tmpbuf, &tmpbuflen); - if (rc == 0) - rc = pkey_ep11key2pkey(tmpbuf, protkey); - /* now we should really have an protected key */ - DEBUG_ERR("%s unable to build protected key from clear", - __func__); + default: + DEBUG_ERR("%s unknown/unsupported non cca clear key type %u\n", + __func__, t->keytype); + return -EINVAL; + } break; } case TOKVER_EP11_AES: { @@ -464,7 +611,8 @@ static int pkey_nonccatok2pkey(const u8 *key, u32 keylen, rc = ep11_check_aes_key(debug_info, 3, key, keylen, 1); if (rc) goto out; - rc = pkey_ep11key2pkey(key, protkey); + rc = pkey_ep11key2pkey(key, + protkey, protkeylen, protkeytype); break; } case TOKVER_EP11_AES_WITH_HEADER: @@ -473,16 +621,14 @@ static int pkey_nonccatok2pkey(const u8 *key, u32 keylen, if (rc) goto out; rc = pkey_ep11key2pkey(key + sizeof(struct ep11kblob_header), - protkey); + protkey, protkeylen, protkeytype); break; default: DEBUG_ERR("%s unknown/unsupported non-CCA token version %d\n", __func__, hdr->version); - rc = -EINVAL; } out: - kfree(tmpbuf); return rc; } @@ -490,7 +636,7 @@ static int pkey_nonccatok2pkey(const u8 *key, u32 keylen, * Transform a CCA internal key token into a protected key */ static int pkey_ccainttok2pkey(const u8 *key, u32 keylen, - struct pkey_protkey *protkey) + u8 *protkey, u32 *protkeylen, u32 *protkeytype) { struct keytoken_header *hdr = (struct keytoken_header *)key; @@ -509,17 +655,17 @@ static int pkey_ccainttok2pkey(const u8 *key, u32 keylen, return -EINVAL; } - return pkey_skey2pkey(key, protkey); + return pkey_skey2pkey(key, protkey, protkeylen, protkeytype); } /* * Transform a key blob (of any type) into a protected key */ int pkey_keyblob2pkey(const u8 *key, u32 keylen, - struct pkey_protkey *protkey) + u8 *protkey, u32 *protkeylen, u32 *protkeytype) { - int rc; struct keytoken_header *hdr = (struct keytoken_header *)key; + int rc; if (keylen < sizeof(struct keytoken_header)) { DEBUG_ERR("%s invalid keylen %d\n", __func__, keylen); @@ -528,10 +674,12 @@ int pkey_keyblob2pkey(const u8 *key, u32 keylen, switch (hdr->type) { case TOKTYPE_NON_CCA: - rc = pkey_nonccatok2pkey(key, keylen, protkey); + rc = pkey_nonccatok2pkey(key, keylen, + protkey, protkeylen, protkeytype); break; case TOKTYPE_CCA_INTERNAL: - rc = pkey_ccainttok2pkey(key, keylen, protkey); + rc = pkey_ccainttok2pkey(key, keylen, + protkey, protkeylen, protkeytype); break; default: DEBUG_ERR("%s unknown/unsupported blob type %d\n", @@ -663,9 +811,9 @@ static int pkey_verifykey2(const u8 *key, size_t keylen, enum pkey_key_type *ktype, enum pkey_key_size *ksize, u32 *flags) { - int rc; - u32 _nr_apqns, *_apqns = NULL; struct keytoken_header *hdr = (struct keytoken_header *)key; + u32 _nr_apqns, *_apqns = NULL; + int rc; if (keylen < sizeof(struct keytoken_header)) return -EINVAL; @@ -771,10 +919,10 @@ static int pkey_verifykey2(const u8 *key, size_t keylen, static int pkey_keyblob2pkey2(const struct pkey_apqn *apqns, size_t nr_apqns, const u8 *key, size_t keylen, - struct pkey_protkey *pkey) + u8 *protkey, u32 *protkeylen, u32 *protkeytype) { - int i, card, dom, rc; struct keytoken_header *hdr = (struct keytoken_header *)key; + int i, card, dom, rc; /* check for at least one apqn given */ if (!apqns || !nr_apqns) @@ -806,7 +954,9 @@ static int pkey_keyblob2pkey2(const struct pkey_apqn *apqns, size_t nr_apqns, if (ep11_check_aes_key(debug_info, 3, key, keylen, 1)) return -EINVAL; } else { - return pkey_nonccatok2pkey(key, keylen, pkey); + return pkey_nonccatok2pkey(key, keylen, + protkey, protkeylen, + protkeytype); } } else { DEBUG_ERR("%s unknown/unsupported blob type %d\n", @@ -822,20 +972,20 @@ static int pkey_keyblob2pkey2(const struct pkey_apqn *apqns, size_t nr_apqns, dom = apqns[i].domain; if (hdr->type == TOKTYPE_CCA_INTERNAL && hdr->version == TOKVER_CCA_AES) { - rc = cca_sec2protkey(card, dom, key, pkey->protkey, - &pkey->len, &pkey->type); + rc = cca_sec2protkey(card, dom, key, + protkey, protkeylen, protkeytype); } else if (hdr->type == TOKTYPE_CCA_INTERNAL && hdr->version == TOKVER_CCA_VLSC) { - rc = cca_cipher2protkey(card, dom, key, pkey->protkey, - &pkey->len, &pkey->type); + rc = cca_cipher2protkey(card, dom, key, + protkey, protkeylen, + protkeytype); } else { /* EP11 AES secure key blob */ struct ep11keyblob *kb = (struct ep11keyblob *)key; - pkey->len = sizeof(pkey->protkey); rc = ep11_kblob2protkey(card, dom, key, kb->head.len, - pkey->protkey, &pkey->len, - &pkey->type); + protkey, protkeylen, + protkeytype); } if (rc == 0) break; @@ -847,9 +997,9 @@ static int pkey_keyblob2pkey2(const struct pkey_apqn *apqns, size_t nr_apqns, static int pkey_apqns4key(const u8 *key, size_t keylen, u32 flags, struct pkey_apqn *apqns, size_t *nr_apqns) { - int rc; - u32 _nr_apqns, *_apqns = NULL; struct keytoken_header *hdr = (struct keytoken_header *)key; + u32 _nr_apqns, *_apqns = NULL; + int rc; if (keylen < sizeof(struct keytoken_header) || flags == 0) return -EINVAL; @@ -860,9 +1010,9 @@ static int pkey_apqns4key(const u8 *key, size_t keylen, u32 flags, (hdr->version == TOKVER_EP11_AES_WITH_HEADER || hdr->version == TOKVER_EP11_ECC_WITH_HEADER) && is_ep11_keyblob(key + sizeof(struct ep11kblob_header))) { - int minhwtype = 0, api = 0; struct ep11keyblob *kb = (struct ep11keyblob *) (key + sizeof(struct ep11kblob_header)); + int minhwtype = 0, api = 0; if (flags != PKEY_FLAGS_MATCH_CUR_MKVP) return -EINVAL; @@ -877,8 +1027,8 @@ static int pkey_apqns4key(const u8 *key, size_t keylen, u32 flags, } else if (hdr->type == TOKTYPE_NON_CCA && hdr->version == TOKVER_EP11_AES && is_ep11_keyblob(key)) { - int minhwtype = 0, api = 0; struct ep11keyblob *kb = (struct ep11keyblob *)key; + int minhwtype = 0, api = 0; if (flags != PKEY_FLAGS_MATCH_CUR_MKVP) return -EINVAL; @@ -891,8 +1041,8 @@ static int pkey_apqns4key(const u8 *key, size_t keylen, u32 flags, if (rc) goto out; } else if (hdr->type == TOKTYPE_CCA_INTERNAL) { - int minhwtype = ZCRYPT_CEX3C; u64 cur_mkvp = 0, old_mkvp = 0; + int minhwtype = ZCRYPT_CEX3C; if (hdr->version == TOKVER_CCA_AES) { struct secaeskeytoken *t = (struct secaeskeytoken *)key; @@ -919,8 +1069,8 @@ static int pkey_apqns4key(const u8 *key, size_t keylen, u32 flags, if (rc) goto out; } else if (hdr->type == TOKTYPE_CCA_INTERNAL_PKA) { - u64 cur_mkvp = 0, old_mkvp = 0; struct eccprivkeytoken *t = (struct eccprivkeytoken *)key; + u64 cur_mkvp = 0, old_mkvp = 0; if (t->secid == 0x20) { if (flags & PKEY_FLAGS_MATCH_CUR_MKVP) @@ -957,8 +1107,8 @@ static int pkey_apqns4keytype(enum pkey_key_type ktype, u8 cur_mkvp[32], u8 alt_mkvp[32], u32 flags, struct pkey_apqn *apqns, size_t *nr_apqns) { - int rc; u32 _nr_apqns, *_apqns = NULL; + int rc; zcrypt_wait_api_operational(); @@ -1020,11 +1170,11 @@ static int pkey_apqns4keytype(enum pkey_key_type ktype, } static int pkey_keyblob2pkey3(const struct pkey_apqn *apqns, size_t nr_apqns, - const u8 *key, size_t keylen, u32 *protkeytype, - u8 *protkey, u32 *protkeylen) + const u8 *key, size_t keylen, + u8 *protkey, u32 *protkeylen, u32 *protkeytype) { - int i, card, dom, rc; struct keytoken_header *hdr = (struct keytoken_header *)key; + int i, card, dom, rc; /* check for at least one apqn given */ if (!apqns || !nr_apqns) @@ -1076,15 +1226,8 @@ static int pkey_keyblob2pkey3(const struct pkey_apqn *apqns, size_t nr_apqns, if (cca_check_sececckeytoken(debug_info, 3, key, keylen, 1)) return -EINVAL; } else if (hdr->type == TOKTYPE_NON_CCA) { - struct pkey_protkey pkey; - - rc = pkey_nonccatok2pkey(key, keylen, &pkey); - if (rc) - return rc; - memcpy(protkey, pkey.protkey, pkey.len); - *protkeylen = pkey.len; - *protkeytype = pkey.type; - return 0; + return pkey_nonccatok2pkey(key, keylen, + protkey, protkeylen, protkeytype); } else { DEBUG_ERR("%s unknown/unsupported blob type %d\n", __func__, hdr->type); @@ -1130,7 +1273,7 @@ static int pkey_keyblob2pkey3(const struct pkey_apqn *apqns, size_t nr_apqns, static void *_copy_key_from_user(void __user *ukey, size_t keylen) { - if (!ukey || keylen < MINKEYBLOBSIZE || keylen > KEYBLOBBUFSIZE) + if (!ukey || keylen < MINKEYBLOBBUFSIZE || keylen > KEYBLOBBUFSIZE) return ERR_PTR(-EINVAL); return memdup_user(ukey, keylen); @@ -1187,6 +1330,7 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd, if (copy_from_user(&ksp, usp, sizeof(ksp))) return -EFAULT; + ksp.protkey.len = sizeof(ksp.protkey.protkey); rc = cca_sec2protkey(ksp.cardnr, ksp.domain, ksp.seckey.seckey, ksp.protkey.protkey, &ksp.protkey.len, &ksp.protkey.type); @@ -1203,8 +1347,10 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd, if (copy_from_user(&kcp, ucp, sizeof(kcp))) return -EFAULT; - rc = pkey_clr2protkey(kcp.keytype, - &kcp.clrkey, &kcp.protkey); + kcp.protkey.len = sizeof(kcp.protkey.protkey); + rc = pkey_clr2protkey(kcp.keytype, kcp.clrkey.clrkey, + kcp.protkey.protkey, + &kcp.protkey.len, &kcp.protkey.type); DEBUG_DBG("%s pkey_clr2protkey()=%d\n", __func__, rc); if (rc) break; @@ -1234,7 +1380,9 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd, if (copy_from_user(&ksp, usp, sizeof(ksp))) return -EFAULT; - rc = pkey_skey2pkey(ksp.seckey.seckey, &ksp.protkey); + ksp.protkey.len = sizeof(ksp.protkey.protkey); + rc = pkey_skey2pkey(ksp.seckey.seckey, ksp.protkey.protkey, + &ksp.protkey.len, &ksp.protkey.type); DEBUG_DBG("%s pkey_skey2pkey()=%d\n", __func__, rc); if (rc) break; @@ -1263,7 +1411,9 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd, if (copy_from_user(&kgp, ugp, sizeof(kgp))) return -EFAULT; - rc = pkey_genprotkey(kgp.keytype, &kgp.protkey); + kgp.protkey.len = sizeof(kgp.protkey.protkey); + rc = pkey_genprotkey(kgp.keytype, kgp.protkey.protkey, + &kgp.protkey.len, &kgp.protkey.type); DEBUG_DBG("%s pkey_genprotkey()=%d\n", __func__, rc); if (rc) break; @@ -1277,7 +1427,8 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd, if (copy_from_user(&kvp, uvp, sizeof(kvp))) return -EFAULT; - rc = pkey_verifyprotkey(&kvp.protkey); + rc = pkey_verifyprotkey(kvp.protkey.protkey, + kvp.protkey.len, kvp.protkey.type); DEBUG_DBG("%s pkey_verifyprotkey()=%d\n", __func__, rc); break; } @@ -1291,7 +1442,9 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd, kkey = _copy_key_from_user(ktp.key, ktp.keylen); if (IS_ERR(kkey)) return PTR_ERR(kkey); - rc = pkey_keyblob2pkey(kkey, ktp.keylen, &ktp.protkey); + ktp.protkey.len = sizeof(ktp.protkey.protkey); + rc = pkey_keyblob2pkey(kkey, ktp.keylen, ktp.protkey.protkey, + &ktp.protkey.len, &ktp.protkey.type); DEBUG_DBG("%s pkey_keyblob2pkey()=%d\n", __func__, rc); memzero_explicit(kkey, ktp.keylen); kfree(kkey); @@ -1303,9 +1456,9 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd, } case PKEY_GENSECK2: { struct pkey_genseck2 __user *ugs = (void __user *)arg; + size_t klen = KEYBLOBBUFSIZE; struct pkey_genseck2 kgs; struct pkey_apqn *apqns; - size_t klen = KEYBLOBBUFSIZE; u8 *kkey; if (copy_from_user(&kgs, ugs, sizeof(kgs))) @@ -1345,9 +1498,9 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd, } case PKEY_CLR2SECK2: { struct pkey_clr2seck2 __user *ucs = (void __user *)arg; + size_t klen = KEYBLOBBUFSIZE; struct pkey_clr2seck2 kcs; struct pkey_apqn *apqns; - size_t klen = KEYBLOBBUFSIZE; u8 *kkey; if (copy_from_user(&kcs, ucs, sizeof(kcs))) @@ -1409,8 +1562,8 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd, } case PKEY_KBLOB2PROTK2: { struct pkey_kblob2pkey2 __user *utp = (void __user *)arg; - struct pkey_kblob2pkey2 ktp; struct pkey_apqn *apqns = NULL; + struct pkey_kblob2pkey2 ktp; u8 *kkey; if (copy_from_user(&ktp, utp, sizeof(ktp))) @@ -1423,8 +1576,11 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd, kfree(apqns); return PTR_ERR(kkey); } + ktp.protkey.len = sizeof(ktp.protkey.protkey); rc = pkey_keyblob2pkey2(apqns, ktp.apqn_entries, - kkey, ktp.keylen, &ktp.protkey); + kkey, ktp.keylen, + ktp.protkey.protkey, &ktp.protkey.len, + &ktp.protkey.type); DEBUG_DBG("%s pkey_keyblob2pkey2()=%d\n", __func__, rc); kfree(apqns); memzero_explicit(kkey, ktp.keylen); @@ -1437,8 +1593,8 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd, } case PKEY_APQNS4K: { struct pkey_apqns4key __user *uak = (void __user *)arg; - struct pkey_apqns4key kak; struct pkey_apqn *apqns = NULL; + struct pkey_apqns4key kak; size_t nr_apqns, len; u8 *kkey; @@ -1486,8 +1642,8 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd, } case PKEY_APQNS4KT: { struct pkey_apqns4keytype __user *uat = (void __user *)arg; - struct pkey_apqns4keytype kat; struct pkey_apqn *apqns = NULL; + struct pkey_apqns4keytype kat; size_t nr_apqns, len; if (copy_from_user(&kat, uat, sizeof(kat))) @@ -1528,9 +1684,9 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd, } case PKEY_KBLOB2PROTK3: { struct pkey_kblob2pkey3 __user *utp = (void __user *)arg; - struct pkey_kblob2pkey3 ktp; - struct pkey_apqn *apqns = NULL; u32 protkeylen = PROTKEYBLOBBUFSIZE; + struct pkey_apqn *apqns = NULL; + struct pkey_kblob2pkey3 ktp; u8 *kkey, *protkey; if (copy_from_user(&ktp, utp, sizeof(ktp))) @@ -1549,9 +1705,9 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd, kfree(kkey); return -ENOMEM; } - rc = pkey_keyblob2pkey3(apqns, ktp.apqn_entries, kkey, - ktp.keylen, &ktp.pkeytype, - protkey, &protkeylen); + rc = pkey_keyblob2pkey3(apqns, ktp.apqn_entries, + kkey, ktp.keylen, + protkey, &protkeylen, &ktp.pkeytype); DEBUG_DBG("%s pkey_keyblob2pkey3()=%d\n", __func__, rc); kfree(apqns); memzero_explicit(kkey, ktp.keylen); @@ -1612,7 +1768,9 @@ static ssize_t pkey_protkey_aes_attr_read(u32 keytype, bool is_xts, char *buf, protkeytoken.version = TOKVER_PROTECTED_KEY; protkeytoken.keytype = keytype; - rc = pkey_genprotkey(protkeytoken.keytype, &protkey); + protkey.len = sizeof(protkey.protkey); + rc = pkey_genprotkey(protkeytoken.keytype, + protkey.protkey, &protkey.len, &protkey.type); if (rc) return rc; @@ -1622,7 +1780,10 @@ static ssize_t pkey_protkey_aes_attr_read(u32 keytype, bool is_xts, char *buf, memcpy(buf, &protkeytoken, sizeof(protkeytoken)); if (is_xts) { - rc = pkey_genprotkey(protkeytoken.keytype, &protkey); + /* xts needs a second protected key, reuse protkey struct */ + protkey.len = sizeof(protkey.protkey); + rc = pkey_genprotkey(protkeytoken.keytype, + protkey.protkey, &protkey.len, &protkey.type); if (rc) return rc; @@ -1717,8 +1878,8 @@ static struct attribute_group protkey_attr_group = { static ssize_t pkey_ccadata_aes_attr_read(u32 keytype, bool is_xts, char *buf, loff_t off, size_t count) { - int rc; struct pkey_seckey *seckey = (struct pkey_seckey *)buf; + int rc; if (off != 0 || count < sizeof(struct secaeskeytoken)) return -EINVAL; @@ -1824,9 +1985,9 @@ static ssize_t pkey_ccacipher_aes_attr_read(enum pkey_key_size keybits, bool is_xts, char *buf, loff_t off, size_t count) { - int i, rc, card, dom; - u32 nr_apqns, *apqns = NULL; size_t keysize = CCACIPHERTOKENSIZE; + u32 nr_apqns, *apqns = NULL; + int i, rc, card, dom; if (off != 0 || count < CCACIPHERTOKENSIZE) return -EINVAL; @@ -1947,9 +2108,9 @@ static ssize_t pkey_ep11_aes_attr_read(enum pkey_key_size keybits, bool is_xts, char *buf, loff_t off, size_t count) { - int i, rc, card, dom; - u32 nr_apqns, *apqns = NULL; size_t keysize = MAXEP11AESKEYBLOBSIZE; + u32 nr_apqns, *apqns = NULL; + int i, rc, card, dom; if (off != 0 || count < MAXEP11AESKEYBLOBSIZE) return -EINVAL; diff --git a/drivers/s390/crypto/vfio_ap_ops.c b/drivers/s390/crypto/vfio_ap_ops.c index cfbcb864ab636d3c2825fdcfecc81beb7ab2fb4c..b441745b041845dd344afdfcf1c6f8924387f9e6 100644 --- a/drivers/s390/crypto/vfio_ap_ops.c +++ b/drivers/s390/crypto/vfio_ap_ops.c @@ -445,7 +445,7 @@ static struct ap_queue_status vfio_ap_irq_enable(struct vfio_ap_queue *q, q->saved_isc = isc; break; case AP_RESPONSE_OTHERWISE_CHANGED: - /* We could not modify IRQ setings: clear new configuration */ + /* We could not modify IRQ settings: clear new configuration */ vfio_unpin_pages(&q->matrix_mdev->vdev, nib, 1); kvm_s390_gisc_unregister(kvm, isc); break; @@ -524,7 +524,7 @@ static void vfio_ap_le_guid_to_be_uuid(guid_t *guid, unsigned long *uuid) * Response.status may be set to following Response Code: * - AP_RESPONSE_Q_NOT_AVAIL: if the queue is not available * - AP_RESPONSE_DECONFIGURED: if the queue is not configured - * - AP_RESPONSE_NORMAL (0) : in case of successs + * - AP_RESPONSE_NORMAL (0) : in case of success * Check vfio_ap_setirq() and vfio_ap_clrirq() for other possible RC. * We take the matrix_dev lock to ensure serialization on queues and * mediated device access. @@ -716,6 +716,7 @@ static int vfio_ap_mdev_probe(struct mdev_device *mdev) ret = vfio_register_emulated_iommu_dev(&matrix_mdev->vdev); if (ret) goto err_put_vdev; + matrix_mdev->req_trigger = NULL; dev_set_drvdata(&mdev->dev, matrix_mdev); mutex_lock(&matrix_dev->mdevs_lock); list_add(&matrix_mdev->node, &matrix_dev->mdev_list); @@ -1735,6 +1736,26 @@ static void vfio_ap_mdev_close_device(struct vfio_device *vdev) vfio_ap_mdev_unset_kvm(matrix_mdev); } +static void vfio_ap_mdev_request(struct vfio_device *vdev, unsigned int count) +{ + struct device *dev = vdev->dev; + struct ap_matrix_mdev *matrix_mdev; + + matrix_mdev = container_of(vdev, struct ap_matrix_mdev, vdev); + + if (matrix_mdev->req_trigger) { + if (!(count % 10)) + dev_notice_ratelimited(dev, + "Relaying device request to user (#%u)\n", + count); + + eventfd_signal(matrix_mdev->req_trigger, 1); + } else if (count == 0) { + dev_notice(dev, + "No device request registered, blocked until released by user\n"); + } +} + static int vfio_ap_mdev_get_device_info(unsigned long arg) { unsigned long minsz; @@ -1750,11 +1771,115 @@ static int vfio_ap_mdev_get_device_info(unsigned long arg) info.flags = VFIO_DEVICE_FLAGS_AP | VFIO_DEVICE_FLAGS_RESET; info.num_regions = 0; - info.num_irqs = 0; + info.num_irqs = VFIO_AP_NUM_IRQS; return copy_to_user((void __user *)arg, &info, minsz) ? -EFAULT : 0; } +static ssize_t vfio_ap_get_irq_info(unsigned long arg) +{ + unsigned long minsz; + struct vfio_irq_info info; + + minsz = offsetofend(struct vfio_irq_info, count); + + if (copy_from_user(&info, (void __user *)arg, minsz)) + return -EFAULT; + + if (info.argsz < minsz || info.index >= VFIO_AP_NUM_IRQS) + return -EINVAL; + + switch (info.index) { + case VFIO_AP_REQ_IRQ_INDEX: + info.count = 1; + info.flags = VFIO_IRQ_INFO_EVENTFD; + break; + default: + return -EINVAL; + } + + return copy_to_user((void __user *)arg, &info, minsz) ? -EFAULT : 0; +} + +static int vfio_ap_irq_set_init(struct vfio_irq_set *irq_set, unsigned long arg) +{ + int ret; + size_t data_size; + unsigned long minsz; + + minsz = offsetofend(struct vfio_irq_set, count); + + if (copy_from_user(irq_set, (void __user *)arg, minsz)) + return -EFAULT; + + ret = vfio_set_irqs_validate_and_prepare(irq_set, 1, VFIO_AP_NUM_IRQS, + &data_size); + if (ret) + return ret; + + if (!(irq_set->flags & VFIO_IRQ_SET_ACTION_TRIGGER)) + return -EINVAL; + + return 0; +} + +static int vfio_ap_set_request_irq(struct ap_matrix_mdev *matrix_mdev, + unsigned long arg) +{ + s32 fd; + void __user *data; + unsigned long minsz; + struct eventfd_ctx *req_trigger; + + minsz = offsetofend(struct vfio_irq_set, count); + data = (void __user *)(arg + minsz); + + if (get_user(fd, (s32 __user *)data)) + return -EFAULT; + + if (fd == -1) { + if (matrix_mdev->req_trigger) + eventfd_ctx_put(matrix_mdev->req_trigger); + matrix_mdev->req_trigger = NULL; + } else if (fd >= 0) { + req_trigger = eventfd_ctx_fdget(fd); + if (IS_ERR(req_trigger)) + return PTR_ERR(req_trigger); + + if (matrix_mdev->req_trigger) + eventfd_ctx_put(matrix_mdev->req_trigger); + + matrix_mdev->req_trigger = req_trigger; + } else { + return -EINVAL; + } + + return 0; +} + +static int vfio_ap_set_irqs(struct ap_matrix_mdev *matrix_mdev, + unsigned long arg) +{ + int ret; + struct vfio_irq_set irq_set; + + ret = vfio_ap_irq_set_init(&irq_set, arg); + if (ret) + return ret; + + switch (irq_set.flags & VFIO_IRQ_SET_DATA_TYPE_MASK) { + case VFIO_IRQ_SET_DATA_EVENTFD: + switch (irq_set.index) { + case VFIO_AP_REQ_IRQ_INDEX: + return vfio_ap_set_request_irq(matrix_mdev, arg); + default: + return -EINVAL; + } + default: + return -EINVAL; + } +} + static ssize_t vfio_ap_mdev_ioctl(struct vfio_device *vdev, unsigned int cmd, unsigned long arg) { @@ -1770,6 +1895,12 @@ static ssize_t vfio_ap_mdev_ioctl(struct vfio_device *vdev, case VFIO_DEVICE_RESET: ret = vfio_ap_mdev_reset_queues(&matrix_mdev->qtable); break; + case VFIO_DEVICE_GET_IRQ_INFO: + ret = vfio_ap_get_irq_info(arg); + break; + case VFIO_DEVICE_SET_IRQS: + ret = vfio_ap_set_irqs(matrix_mdev, arg); + break; default: ret = -EOPNOTSUPP; break; @@ -1844,6 +1975,7 @@ static const struct vfio_device_ops vfio_ap_matrix_dev_ops = { .bind_iommufd = vfio_iommufd_emulated_bind, .unbind_iommufd = vfio_iommufd_emulated_unbind, .attach_ioas = vfio_iommufd_emulated_attach_ioas, + .request = vfio_ap_mdev_request }; static struct mdev_driver vfio_ap_matrix_driver = { diff --git a/drivers/s390/crypto/vfio_ap_private.h b/drivers/s390/crypto/vfio_ap_private.h index 976a65f32e7d10419131fe1e447b647e0569c069..4642bbdbd1b27d4cd48dfabef2e2bb512cbc38a2 100644 --- a/drivers/s390/crypto/vfio_ap_private.h +++ b/drivers/s390/crypto/vfio_ap_private.h @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -103,6 +104,7 @@ struct ap_queue_table { * PQAP(AQIC) instruction. * @mdev: the mediated device * @qtable: table of queues (struct vfio_ap_queue) assigned to the mdev + * @req_trigger eventfd ctx for signaling userspace to return a device * @apm_add: bitmap of APIDs added to the host's AP configuration * @aqm_add: bitmap of APQIs added to the host's AP configuration * @adm_add: bitmap of control domain numbers added to the host's AP @@ -117,6 +119,7 @@ struct ap_matrix_mdev { crypto_hook pqap_hook; struct mdev_device *mdev; struct ap_queue_table qtable; + struct eventfd_ctx *req_trigger; DECLARE_BITMAP(apm_add, AP_DEVICES); DECLARE_BITMAP(aqm_add, AP_DOMAINS); DECLARE_BITMAP(adm_add, AP_DOMAINS); diff --git a/drivers/s390/crypto/zcrypt_api.c b/drivers/s390/crypto/zcrypt_api.c index 444ef95d3f598ad4c6f2953da0113fda17983916..4b23c9f7f3e54102a8ee0b97def8e9aa924a8925 100644 --- a/drivers/s390/crypto/zcrypt_api.c +++ b/drivers/s390/crypto/zcrypt_api.c @@ -111,8 +111,6 @@ EXPORT_SYMBOL(zcrypt_msgtype); * Multi device nodes extension functions. */ -#ifdef CONFIG_ZCRYPT_MULTIDEVNODES - struct zcdn_device; static struct class *zcrypt_class; @@ -477,8 +475,6 @@ static void zcdn_destroy_all(void) mutex_unlock(&ap_perms_mutex); } -#endif - /* * zcrypt_read (): Not supported beyond zcrypt 1.3.1. * @@ -510,7 +506,6 @@ static int zcrypt_open(struct inode *inode, struct file *filp) { struct ap_perms *perms = &ap_perms; -#ifdef CONFIG_ZCRYPT_MULTIDEVNODES if (filp->f_inode->i_cdev == &zcrypt_cdev) { struct zcdn_device *zcdndev; @@ -522,7 +517,6 @@ static int zcrypt_open(struct inode *inode, struct file *filp) if (zcdndev) perms = &zcdndev->perms; } -#endif filp->private_data = (void *)perms; atomic_inc(&zcrypt_open_count); @@ -536,7 +530,6 @@ static int zcrypt_open(struct inode *inode, struct file *filp) */ static int zcrypt_release(struct inode *inode, struct file *filp) { -#ifdef CONFIG_ZCRYPT_MULTIDEVNODES if (filp->f_inode->i_cdev == &zcrypt_cdev) { struct zcdn_device *zcdndev; @@ -549,7 +542,6 @@ static int zcrypt_release(struct inode *inode, struct file *filp) put_device(&zcdndev->device); } } -#endif atomic_dec(&zcrypt_open_count); return 0; @@ -661,11 +653,6 @@ static long zcrypt_rsa_modexpo(struct ap_perms *perms, ap_init_message(&ap_msg); -#ifdef CONFIG_ZCRYPT_DEBUG - if (tr && tr->fi.cmd) - ap_msg.fi.cmd = tr->fi.cmd; -#endif - if (mex->outputdatalength < mex->inputdatalength) { func_code = 0; rc = -EINVAL; @@ -687,7 +674,7 @@ static long zcrypt_rsa_modexpo(struct ap_perms *perms, pref_zq = NULL; spin_lock(&zcrypt_list_lock); for_each_zcrypt_card(zc) { - /* Check for usable accelarator or CCA card */ + /* Check for usable accelerator or CCA card */ if (!zc->online || !zc->card->config || zc->card->chkstop || !(zc->card->functions & 0x18000000)) continue; @@ -771,11 +758,6 @@ static long zcrypt_rsa_crt(struct ap_perms *perms, ap_init_message(&ap_msg); -#ifdef CONFIG_ZCRYPT_DEBUG - if (tr && tr->fi.cmd) - ap_msg.fi.cmd = tr->fi.cmd; -#endif - if (crt->outputdatalength < crt->inputdatalength) { func_code = 0; rc = -EINVAL; @@ -797,7 +779,7 @@ static long zcrypt_rsa_crt(struct ap_perms *perms, pref_zq = NULL; spin_lock(&zcrypt_list_lock); for_each_zcrypt_card(zc) { - /* Check for usable accelarator or CCA card */ + /* Check for usable accelerator or CCA card */ if (!zc->online || !zc->card->config || zc->card->chkstop || !(zc->card->functions & 0x18000000)) continue; @@ -883,16 +865,6 @@ static long _zcrypt_send_cprb(bool userspace, struct ap_perms *perms, xcrb->status = 0; ap_init_message(&ap_msg); -#ifdef CONFIG_ZCRYPT_DEBUG - if (tr && tr->fi.cmd) - ap_msg.fi.cmd = tr->fi.cmd; - if (tr && tr->fi.action == AP_FI_ACTION_CCA_AGENT_FF) { - ZCRYPT_DBF_WARN("%s fi cmd 0x%04x: forcing invalid agent_ID 'FF'\n", - __func__, tr->fi.cmd); - xcrb->agent_ID = 0x4646; - } -#endif - rc = prep_cca_ap_msg(userspace, xcrb, &ap_msg, &func_code, &domain); if (rc) goto out; @@ -982,14 +954,6 @@ static long _zcrypt_send_cprb(bool userspace, struct ap_perms *perms, if (*domain == AUTOSEL_DOM) *domain = AP_QID_QUEUE(qid); -#ifdef CONFIG_ZCRYPT_DEBUG - if (tr && tr->fi.action == AP_FI_ACTION_CCA_DOM_INVAL) { - ZCRYPT_DBF_WARN("%s fi cmd 0x%04x: forcing invalid domain\n", - __func__, tr->fi.cmd); - *domain = 99; - } -#endif - rc = pref_zq->ops->send_cprb(userspace, pref_zq, xcrb, &ap_msg); spin_lock(&zcrypt_list_lock); @@ -1058,11 +1022,6 @@ static long _zcrypt_send_ep11_cprb(bool userspace, struct ap_perms *perms, ap_init_message(&ap_msg); -#ifdef CONFIG_ZCRYPT_DEBUG - if (tr && tr->fi.cmd) - ap_msg.fi.cmd = tr->fi.cmd; -#endif - target_num = (unsigned short)xcrb->targets_num; /* empty list indicates autoselect (all available targets) */ @@ -1473,23 +1432,10 @@ static int icarsamodexpo_ioctl(struct ap_perms *perms, unsigned long arg) if (copy_from_user(&mex, umex, sizeof(mex))) return -EFAULT; -#ifdef CONFIG_ZCRYPT_DEBUG - if (mex.inputdatalength & (1U << 31)) { - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - tr.fi.cmd = (u16)(mex.inputdatalength >> 16); - } - mex.inputdatalength &= 0x0000FFFF; -#endif - do { rc = zcrypt_rsa_modexpo(perms, &tr, &mex); if (rc == -EAGAIN) tr.again_counter++; -#ifdef CONFIG_ZCRYPT_DEBUG - if (rc == -EAGAIN && (tr.fi.flags & AP_FI_FLAG_NO_RETRY)) - break; -#endif } while (rc == -EAGAIN && tr.again_counter < TRACK_AGAIN_MAX); /* on failure: retry once again after a requested rescan */ if ((rc == -ENODEV) && (zcrypt_process_rescan())) @@ -1518,23 +1464,10 @@ static int icarsacrt_ioctl(struct ap_perms *perms, unsigned long arg) if (copy_from_user(&crt, ucrt, sizeof(crt))) return -EFAULT; -#ifdef CONFIG_ZCRYPT_DEBUG - if (crt.inputdatalength & (1U << 31)) { - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - tr.fi.cmd = (u16)(crt.inputdatalength >> 16); - } - crt.inputdatalength &= 0x0000FFFF; -#endif - do { rc = zcrypt_rsa_crt(perms, &tr, &crt); if (rc == -EAGAIN) tr.again_counter++; -#ifdef CONFIG_ZCRYPT_DEBUG - if (rc == -EAGAIN && (tr.fi.flags & AP_FI_FLAG_NO_RETRY)) - break; -#endif } while (rc == -EAGAIN && tr.again_counter < TRACK_AGAIN_MAX); /* on failure: retry once again after a requested rescan */ if ((rc == -ENODEV) && (zcrypt_process_rescan())) @@ -1563,23 +1496,10 @@ static int zsecsendcprb_ioctl(struct ap_perms *perms, unsigned long arg) if (copy_from_user(&xcrb, uxcrb, sizeof(xcrb))) return -EFAULT; -#ifdef CONFIG_ZCRYPT_DEBUG - if ((xcrb.status & 0x8000FFFF) == 0x80004649 /* 'FI' */) { - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - tr.fi.cmd = (u16)(xcrb.status >> 16); - } - xcrb.status = 0; -#endif - do { rc = _zcrypt_send_cprb(true, perms, &tr, &xcrb); if (rc == -EAGAIN) tr.again_counter++; -#ifdef CONFIG_ZCRYPT_DEBUG - if (rc == -EAGAIN && (tr.fi.flags & AP_FI_FLAG_NO_RETRY)) - break; -#endif } while (rc == -EAGAIN && tr.again_counter < TRACK_AGAIN_MAX); /* on failure: retry once again after a requested rescan */ if ((rc == -ENODEV) && (zcrypt_process_rescan())) @@ -1609,23 +1529,10 @@ static int zsendep11cprb_ioctl(struct ap_perms *perms, unsigned long arg) if (copy_from_user(&xcrb, uxcrb, sizeof(xcrb))) return -EFAULT; -#ifdef CONFIG_ZCRYPT_DEBUG - if (xcrb.req_len & (1ULL << 63)) { - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - tr.fi.cmd = (u16)(xcrb.req_len >> 48); - } - xcrb.req_len &= 0x0000FFFFFFFFFFFFULL; -#endif - do { rc = _zcrypt_send_ep11_cprb(true, perms, &tr, &xcrb); if (rc == -EAGAIN) tr.again_counter++; -#ifdef CONFIG_ZCRYPT_DEBUG - if (rc == -EAGAIN && (tr.fi.flags & AP_FI_FLAG_NO_RETRY)) - break; -#endif } while (rc == -EAGAIN && tr.again_counter < TRACK_AGAIN_MAX); /* on failure: retry once again after a requested rescan */ if ((rc == -ENODEV) && (zcrypt_process_rescan())) @@ -1668,14 +1575,16 @@ static long zcrypt_unlocked_ioctl(struct file *filp, unsigned int cmd, size_t total_size = MAX_ZDEV_ENTRIES_EXT * sizeof(struct zcrypt_device_status_ext); - device_status = kzalloc(total_size, GFP_KERNEL); + device_status = kvmalloc_array(MAX_ZDEV_ENTRIES_EXT, + sizeof(struct zcrypt_device_status_ext), + GFP_KERNEL); if (!device_status) return -ENOMEM; zcrypt_device_status_mask_ext(device_status); if (copy_to_user((char __user *)arg, device_status, total_size)) rc = -EFAULT; - kfree(device_status); + kvfree(device_status); return rc; } case ZCRYPT_STATUS_MASK: { @@ -2144,8 +2053,6 @@ void zcrypt_debug_exit(void) debug_unregister(zcrypt_dbf_info); } -#ifdef CONFIG_ZCRYPT_MULTIDEVNODES - static int __init zcdn_init(void) { int rc; @@ -2203,8 +2110,6 @@ static void zcdn_exit(void) class_destroy(zcrypt_class); } -#endif - /* * zcrypt_api_init(): Module initialization. * @@ -2218,11 +2123,9 @@ int __init zcrypt_api_init(void) if (rc) goto out; -#ifdef CONFIG_ZCRYPT_MULTIDEVNODES rc = zcdn_init(); if (rc) goto out; -#endif /* Register the request sprayer. */ rc = misc_register(&zcrypt_misc_device); @@ -2235,9 +2138,7 @@ int __init zcrypt_api_init(void) return 0; out_misc_register_failed: -#ifdef CONFIG_ZCRYPT_MULTIDEVNODES zcdn_exit(); -#endif zcrypt_debug_exit(); out: return rc; @@ -2250,9 +2151,7 @@ int __init zcrypt_api_init(void) */ void __exit zcrypt_api_exit(void) { -#ifdef CONFIG_ZCRYPT_MULTIDEVNODES zcdn_exit(); -#endif misc_deregister(&zcrypt_misc_device); zcrypt_msgtype6_exit(); zcrypt_msgtype50_exit(); diff --git a/drivers/s390/crypto/zcrypt_api.h b/drivers/s390/crypto/zcrypt_api.h index f299deb8b8c7650a4e7564c0d829820ebc8ae3cd..de659954c8f7d21035213ecd42c4e97f9cac8e34 100644 --- a/drivers/s390/crypto/zcrypt_api.h +++ b/drivers/s390/crypto/zcrypt_api.h @@ -60,9 +60,6 @@ struct zcrypt_track { int again_counter; /* retry attempts counter */ int last_qid; /* last qid used */ int last_rc; /* last return code */ -#ifdef CONFIG_ZCRYPT_DEBUG - struct ap_fi fi; /* failure injection cmd */ -#endif }; /* defines related to message tracking */ diff --git a/drivers/s390/crypto/zcrypt_ccamisc.c b/drivers/s390/crypto/zcrypt_ccamisc.c index 8c8808cc68a44fcd161f4df4e39fa78d3eba1275..263fe182648b8427ea7c7f89c92bf3ef15918ef2 100644 --- a/drivers/s390/crypto/zcrypt_ccamisc.c +++ b/drivers/s390/crypto/zcrypt_ccamisc.c @@ -689,7 +689,7 @@ int cca_sec2protkey(u16 cardnr, u16 domain, goto out; } - /* copy the tanslated protected key */ + /* copy the translated protected key */ switch (prepparm->lv3.ckb.len) { case 16 + 32: /* AES 128 protected key */ diff --git a/drivers/s390/crypto/zcrypt_ccamisc.h b/drivers/s390/crypto/zcrypt_ccamisc.h index 78bf5631848e1d16814677e01850c46e5cfe154a..5ddf02f965f97eb50368805dc346a44260fea27e 100644 --- a/drivers/s390/crypto/zcrypt_ccamisc.h +++ b/drivers/s390/crypto/zcrypt_ccamisc.h @@ -115,7 +115,7 @@ struct eccprivkeytoken { u64 mkvp; /* master key verification pattern */ u8 opk[48]; /* encrypted object protection key data */ u16 adatalen; /* associated data length in bytes */ - u16 fseclen; /* formated section length in bytes */ + u16 fseclen; /* formatted section length in bytes */ u8 more_data[]; /* more data follows */ } __packed; @@ -232,7 +232,7 @@ int cca_findcard(const u8 *key, u16 *pcardnr, u16 *pdomain, int verify); * the number of apqns stored into the list is returned in *nr_apqns. One apqn * entry is simple a 32 bit value with 16 bit cardnr and 16 bit domain nr and * may be casted to struct pkey_apqn. The return value is either 0 for success - * or a negative errno value. If no apqn meeting the criterias is found, + * or a negative errno value. If no apqn meeting the criteria is found, * -ENODEV is returned. */ int cca_findcard2(u32 **apqns, u32 *nr_apqns, u16 cardnr, u16 domain, diff --git a/drivers/s390/crypto/zcrypt_ep11misc.c b/drivers/s390/crypto/zcrypt_ep11misc.c index f67d19d08571ba20d182bf9f3d78b5ca72068dd4..958f5ee47f1b093b70c6f4d4500215dec43a988c 100644 --- a/drivers/s390/crypto/zcrypt_ep11misc.c +++ b/drivers/s390/crypto/zcrypt_ep11misc.c @@ -1368,7 +1368,7 @@ int ep11_kblob2protkey(u16 card, u16 dom, const u8 *keyblob, size_t keybloblen, goto out; } - /* copy the tanslated protected key */ + /* copy the translated protected key */ if (wki->pkeysize > *protkeylen) { DEBUG_ERR("%s wk info pkeysize %llu > protkeysize %u\n", __func__, wki->pkeysize, *protkeylen); diff --git a/drivers/s390/crypto/zcrypt_ep11misc.h b/drivers/s390/crypto/zcrypt_ep11misc.h index 07445041869feeca3b246e243b1ff1081dadc799..a3eddf51242dafb32df802f508287f936c27c306 100644 --- a/drivers/s390/crypto/zcrypt_ep11misc.h +++ b/drivers/s390/crypto/zcrypt_ep11misc.h @@ -131,14 +131,14 @@ int ep11_clr2keyblob(u16 cardnr, u16 domain, u32 keybitsize, u32 keygenflags, * - if minapi > 0 only apqns with API_ord_nr >= minapi * - if wkvp != NULL only apqns where the wkvp (EP11_WKVPLEN bytes) matches * to the first EP11_WKVPLEN bytes of the wkvp of the current wrapping - * key for this domain. When a wkvp is given there will aways be a re-fetch + * key for this domain. When a wkvp is given there will always be a re-fetch * of the domain info for the potential apqn - so this triggers an request * reply to each apqn eligible. * The array of apqn entries is allocated with kmalloc and returned in *apqns; * the number of apqns stored into the list is returned in *nr_apqns. One apqn * entry is simple a 32 bit value with 16 bit cardnr and 16 bit domain nr and * may be casted to struct pkey_apqn. The return value is either 0 for success - * or a negative errno value. If no apqn meeting the criterias is found, + * or a negative errno value. If no apqn meeting the criteria is found, * -ENODEV is returned. */ int ep11_findcard2(u32 **apqns, u32 *nr_apqns, u16 cardnr, u16 domain, diff --git a/drivers/s390/crypto/zcrypt_msgtype50.c b/drivers/s390/crypto/zcrypt_msgtype50.c index 05ace18c12b041e46ff65bed9bc6b3c82a4bf192..51f8f7a463f71c4f5a80d8b60592a61865298ddd 100644 --- a/drivers/s390/crypto/zcrypt_msgtype50.c +++ b/drivers/s390/crypto/zcrypt_msgtype50.c @@ -246,11 +246,6 @@ static int ICAMEX_msg_to_type50MEX_msg(struct zcrypt_queue *zq, copy_from_user(inp, mex->inputdata, mod_len)) return -EFAULT; -#ifdef CONFIG_ZCRYPT_DEBUG - if (ap_msg->fi.flags & AP_FI_FLAG_TOGGLE_SPECIAL) - ap_msg->flags ^= AP_MSG_FLAG_SPECIAL; -#endif - return 0; } @@ -338,11 +333,6 @@ static int ICACRT_msg_to_type50CRT_msg(struct zcrypt_queue *zq, copy_from_user(inp, crt->inputdata, mod_len)) return -EFAULT; -#ifdef CONFIG_ZCRYPT_DEBUG - if (ap_msg->fi.flags & AP_FI_FLAG_TOGGLE_SPECIAL) - ap_msg->flags ^= AP_MSG_FLAG_SPECIAL; -#endif - return 0; } diff --git a/drivers/s390/crypto/zcrypt_msgtype6.c b/drivers/s390/crypto/zcrypt_msgtype6.c index 2f9bf23fbb44ebaa1b286f385aad4b2e8c5e7756..67fd2ec9c5a171452063f4dba35b03bf5b96d8bc 100644 --- a/drivers/s390/crypto/zcrypt_msgtype6.c +++ b/drivers/s390/crypto/zcrypt_msgtype6.c @@ -425,11 +425,6 @@ static int xcrb_msg_to_type6cprb_msgx(bool userspace, struct ap_message *ap_msg, memcmp(function_code, "AU", 2) == 0) ap_msg->flags |= AP_MSG_FLAG_SPECIAL; -#ifdef CONFIG_ZCRYPT_DEBUG - if (ap_msg->fi.flags & AP_FI_FLAG_TOGGLE_SPECIAL) - ap_msg->flags ^= AP_MSG_FLAG_SPECIAL; -#endif - /* check CPRB minor version, set info bits in ap_message flag field */ switch (*(unsigned short *)(&msg->cprbx.func_id[0])) { case 0x5432: /* "T2" */ @@ -535,11 +530,6 @@ static int xcrb_msg_to_type6_ep11cprb_msgx(bool userspace, struct ap_message *ap if (msg->cprbx.flags & 0x20) ap_msg->flags |= AP_MSG_FLAG_SPECIAL; -#ifdef CONFIG_ZCRYPT_DEBUG - if (ap_msg->fi.flags & AP_FI_FLAG_TOGGLE_SPECIAL) - ap_msg->flags ^= AP_MSG_FLAG_SPECIAL; -#endif - /* set info bits in ap_message flag field */ if (msg->cprbx.flags & 0x80) ap_msg->flags |= AP_MSG_FLAG_ADMIN; @@ -1143,6 +1133,9 @@ static long zcrypt_msgtype6_send_cprb(bool userspace, struct zcrypt_queue *zq, ap_cancel_message(zq->queue, ap_msg); } + if (rc == -EAGAIN && ap_msg->flags & AP_MSG_FLAG_ADMIN) + rc = -EIO; /* do not retry administrative requests */ + out: if (rc) ZCRYPT_DBF_DBG("%s send cprb at dev=%02x.%04x rc=%d\n", @@ -1263,6 +1256,9 @@ static long zcrypt_msgtype6_send_ep11_cprb(bool userspace, struct zcrypt_queue * ap_cancel_message(zq->queue, ap_msg); } + if (rc == -EAGAIN && ap_msg->flags & AP_MSG_FLAG_ADMIN) + rc = -EIO; /* do not retry administrative requests */ + out: if (rc) ZCRYPT_DBF_DBG("%s send cprb at dev=%02x.%04x rc=%d\n", diff --git a/drivers/s390/net/ctcm_dbug.c b/drivers/s390/net/ctcm_dbug.c index f7ec51db3cd6cd5ea17648d0b90c49c2fbe21626..b6f0e2f114b4ea188638a1ec1c72842baee281cc 100644 --- a/drivers/s390/net/ctcm_dbug.c +++ b/drivers/s390/net/ctcm_dbug.c @@ -70,7 +70,7 @@ void ctcm_dbf_longtext(enum ctcm_dbf_names dbf_nix, int level, char *fmt, ...) if (!debug_level_enabled(ctcm_dbf[dbf_nix].id, level)) return; va_start(args, fmt); - vsnprintf(dbf_txt_buf, sizeof(dbf_txt_buf), fmt, args); + vscnprintf(dbf_txt_buf, sizeof(dbf_txt_buf), fmt, args); va_end(args); debug_text_event(ctcm_dbf[dbf_nix].id, level, dbf_txt_buf); diff --git a/drivers/s390/net/ctcm_main.c b/drivers/s390/net/ctcm_main.c index 28db69d91f17edb10b9584f917d213bf46ff415c..6faf271360244e5360a4eb277bf5a8a0c8dc7fad 100644 --- a/drivers/s390/net/ctcm_main.c +++ b/drivers/s390/net/ctcm_main.c @@ -1333,7 +1333,7 @@ static int add_channel(struct ccw_device *cdev, enum ctcm_channel_types type, goto nomem_return; ch->cdev = cdev; - snprintf(ch->id, CTCM_ID_SIZE, "ch-%s", dev_name(&cdev->dev)); + scnprintf(ch->id, CTCM_ID_SIZE, "ch-%s", dev_name(&cdev->dev)); ch->type = type; /* @@ -1498,8 +1498,8 @@ static int ctcm_new_device(struct ccwgroup_device *cgdev) type = get_channel_type(&cdev0->id); - snprintf(read_id, CTCM_ID_SIZE, "ch-%s", dev_name(&cdev0->dev)); - snprintf(write_id, CTCM_ID_SIZE, "ch-%s", dev_name(&cdev1->dev)); + scnprintf(read_id, CTCM_ID_SIZE, "ch-%s", dev_name(&cdev0->dev)); + scnprintf(write_id, CTCM_ID_SIZE, "ch-%s", dev_name(&cdev1->dev)); ret = add_channel(cdev0, type, priv); if (ret) { diff --git a/drivers/s390/net/ctcm_main.h b/drivers/s390/net/ctcm_main.h index 90bd7b3f80c313b33770fb0a30fc5fa1015337dc..25164e8bf13d4691631aa8f83ba3841c717c1fa3 100644 --- a/drivers/s390/net/ctcm_main.h +++ b/drivers/s390/net/ctcm_main.h @@ -100,6 +100,7 @@ enum ctcm_channel_types { #define CTCM_PROTO_MPC 4 #define CTCM_PROTO_MAX 4 +#define CTCM_STATSIZE_LIMIT 64 #define CTCM_BUFSIZE_LIMIT 65535 #define CTCM_BUFSIZE_DEFAULT 32768 #define MPC_BUFSIZE_DEFAULT CTCM_BUFSIZE_LIMIT diff --git a/drivers/s390/net/ctcm_mpc.c b/drivers/s390/net/ctcm_mpc.c index b8a226c6e1a93db330f33012515fe31662c7d2a3..7a2f34a5e0e09ff95bfd2f5b9248f1bdbf68b771 100644 --- a/drivers/s390/net/ctcm_mpc.c +++ b/drivers/s390/net/ctcm_mpc.c @@ -43,13 +43,13 @@ #include #include -#include /* instead of ok ? */ -#include -#include -#include /* instead of ok ? */ -#include /* instead of ok ? */ +#include +#include +#include #include #include +#include +#include #include #include "ctcm_main.h" @@ -144,9 +144,9 @@ void ctcmpc_dumpit(char *buf, int len) for (ct = 0; ct < len; ct++, ptr++, rptr++) { if (sw == 0) { - sprintf(addr, "%16.16llx", (__u64)rptr); + scnprintf(addr, sizeof(addr), "%16.16llx", (__u64)rptr); - sprintf(boff, "%4.4X", (__u32)ct); + scnprintf(boff, sizeof(boff), "%4.4X", (__u32)ct); bhex[0] = '\0'; basc[0] = '\0'; } @@ -155,7 +155,7 @@ void ctcmpc_dumpit(char *buf, int len) if (sw == 8) strcat(bhex, " "); - sprintf(tbuf, "%2.2llX", (__u64)*ptr); + scnprintf(tbuf, sizeof(tbuf), "%2.2llX", (__u64)*ptr); tbuf[2] = '\0'; strcat(bhex, tbuf); @@ -171,8 +171,8 @@ void ctcmpc_dumpit(char *buf, int len) continue; if ((strcmp(duphex, bhex)) != 0) { if (dup != 0) { - sprintf(tdup, - "Duplicate as above to %s", addr); + scnprintf(tdup, sizeof(tdup), + "Duplicate as above to %s", addr); ctcm_pr_debug(" --- %s ---\n", tdup); } @@ -197,14 +197,16 @@ void ctcmpc_dumpit(char *buf, int len) strcat(basc, " "); } if (dup != 0) { - sprintf(tdup, "Duplicate as above to %s", addr); + scnprintf(tdup, sizeof(tdup), + "Duplicate as above to %s", addr); ctcm_pr_debug(" --- %s ---\n", tdup); } ctcm_pr_debug(" %s (+%s) : %s [%s]\n", addr, boff, bhex, basc); } else { if (dup >= 1) { - sprintf(tdup, "Duplicate as above to %s", addr); + scnprintf(tdup, sizeof(tdup), + "Duplicate as above to %s", addr); ctcm_pr_debug(" --- %s ---\n", tdup); } if (dup != 0) { @@ -291,7 +293,7 @@ static struct net_device *ctcmpc_get_dev(int port_num) struct net_device *dev; struct ctcm_priv *priv; - sprintf(device, "%s%i", MPC_DEVICE_NAME, port_num); + scnprintf(device, sizeof(device), "%s%i", MPC_DEVICE_NAME, port_num); dev = __dev_get_by_name(&init_net, device); diff --git a/drivers/s390/net/ctcm_sysfs.c b/drivers/s390/net/ctcm_sysfs.c index e3813a7aa5e68ff1d3573e50bc6f624f8ef4cc6f..0c5d8a3eaa2e6de170c06e77f9586ff36bb034b8 100644 --- a/drivers/s390/net/ctcm_sysfs.c +++ b/drivers/s390/net/ctcm_sysfs.c @@ -28,7 +28,7 @@ static ssize_t ctcm_buffer_show(struct device *dev, if (!priv) return -ENODEV; - return sprintf(buf, "%d\n", priv->buffer_size); + return sysfs_emit(buf, "%d\n", priv->buffer_size); } static ssize_t ctcm_buffer_write(struct device *dev, @@ -86,24 +86,24 @@ static void ctcm_print_statistics(struct ctcm_priv *priv) return; p = sbuf; - p += sprintf(p, " Device FSM state: %s\n", - fsm_getstate_str(priv->fsm)); - p += sprintf(p, " RX channel FSM state: %s\n", - fsm_getstate_str(priv->channel[CTCM_READ]->fsm)); - p += sprintf(p, " TX channel FSM state: %s\n", - fsm_getstate_str(priv->channel[CTCM_WRITE]->fsm)); - p += sprintf(p, " Max. TX buffer used: %ld\n", - priv->channel[WRITE]->prof.maxmulti); - p += sprintf(p, " Max. chained SKBs: %ld\n", - priv->channel[WRITE]->prof.maxcqueue); - p += sprintf(p, " TX single write ops: %ld\n", - priv->channel[WRITE]->prof.doios_single); - p += sprintf(p, " TX multi write ops: %ld\n", - priv->channel[WRITE]->prof.doios_multi); - p += sprintf(p, " Netto bytes written: %ld\n", - priv->channel[WRITE]->prof.txlen); - p += sprintf(p, " Max. TX IO-time: %u\n", - jiffies_to_usecs(priv->channel[WRITE]->prof.tx_time)); + p += scnprintf(p, CTCM_STATSIZE_LIMIT, " Device FSM state: %s\n", + fsm_getstate_str(priv->fsm)); + p += scnprintf(p, CTCM_STATSIZE_LIMIT, " RX channel FSM state: %s\n", + fsm_getstate_str(priv->channel[CTCM_READ]->fsm)); + p += scnprintf(p, CTCM_STATSIZE_LIMIT, " TX channel FSM state: %s\n", + fsm_getstate_str(priv->channel[CTCM_WRITE]->fsm)); + p += scnprintf(p, CTCM_STATSIZE_LIMIT, " Max. TX buffer used: %ld\n", + priv->channel[WRITE]->prof.maxmulti); + p += scnprintf(p, CTCM_STATSIZE_LIMIT, " Max. chained SKBs: %ld\n", + priv->channel[WRITE]->prof.maxcqueue); + p += scnprintf(p, CTCM_STATSIZE_LIMIT, " TX single write ops: %ld\n", + priv->channel[WRITE]->prof.doios_single); + p += scnprintf(p, CTCM_STATSIZE_LIMIT, " TX multi write ops: %ld\n", + priv->channel[WRITE]->prof.doios_multi); + p += scnprintf(p, CTCM_STATSIZE_LIMIT, " Netto bytes written: %ld\n", + priv->channel[WRITE]->prof.txlen); + p += scnprintf(p, CTCM_STATSIZE_LIMIT, " Max. TX IO-time: %u\n", + jiffies_to_usecs(priv->channel[WRITE]->prof.tx_time)); printk(KERN_INFO "Statistics for %s:\n%s", priv->channel[CTCM_WRITE]->netdev->name, sbuf); @@ -120,7 +120,7 @@ static ssize_t stats_show(struct device *dev, if (!priv || gdev->state != CCWGROUP_ONLINE) return -ENODEV; ctcm_print_statistics(priv); - return sprintf(buf, "0\n"); + return sysfs_emit(buf, "0\n"); } static ssize_t stats_write(struct device *dev, struct device_attribute *attr, @@ -142,7 +142,7 @@ static ssize_t ctcm_proto_show(struct device *dev, if (!priv) return -ENODEV; - return sprintf(buf, "%d\n", priv->protocol); + return sysfs_emit(buf, "%d\n", priv->protocol); } static ssize_t ctcm_proto_store(struct device *dev, @@ -184,8 +184,8 @@ static ssize_t ctcm_type_show(struct device *dev, if (!cgdev) return -ENODEV; - return sprintf(buf, "%s\n", - ctcm_type[cgdev->cdev[0]->id.driver_info]); + return sysfs_emit(buf, "%s\n", + ctcm_type[cgdev->cdev[0]->id.driver_info]); } static DEVICE_ATTR(buffer, 0644, ctcm_buffer_show, ctcm_buffer_write); diff --git a/drivers/s390/net/ism_drv.c b/drivers/s390/net/ism_drv.c index c2096e4bba319960de45c4768943d0aa1634f87a..6df7f377d2f90cabb7aeb76d7f6fa680f1aa5104 100644 --- a/drivers/s390/net/ism_drv.c +++ b/drivers/s390/net/ism_drv.c @@ -36,7 +36,7 @@ static const struct smcd_ops ism_ops; static struct ism_client *clients[MAX_CLIENTS]; /* use an array rather than */ /* a list for fast mapping */ static u8 max_client; -static DEFINE_SPINLOCK(clients_lock); +static DEFINE_MUTEX(clients_lock); struct ism_dev_list { struct list_head list; struct mutex mutex; /* protects ism device list */ @@ -47,14 +47,22 @@ static struct ism_dev_list ism_dev_list = { .mutex = __MUTEX_INITIALIZER(ism_dev_list.mutex), }; +static void ism_setup_forwarding(struct ism_client *client, struct ism_dev *ism) +{ + unsigned long flags; + + spin_lock_irqsave(&ism->lock, flags); + ism->subs[client->id] = client; + spin_unlock_irqrestore(&ism->lock, flags); +} + int ism_register_client(struct ism_client *client) { struct ism_dev *ism; - unsigned long flags; int i, rc = -ENOSPC; mutex_lock(&ism_dev_list.mutex); - spin_lock_irqsave(&clients_lock, flags); + mutex_lock(&clients_lock); for (i = 0; i < MAX_CLIENTS; ++i) { if (!clients[i]) { clients[i] = client; @@ -65,12 +73,14 @@ int ism_register_client(struct ism_client *client) break; } } - spin_unlock_irqrestore(&clients_lock, flags); + mutex_unlock(&clients_lock); + if (i < MAX_CLIENTS) { /* initialize with all devices that we got so far */ list_for_each_entry(ism, &ism_dev_list.list, list) { ism->priv[i] = NULL; client->add(ism); + ism_setup_forwarding(client, ism); } } mutex_unlock(&ism_dev_list.mutex); @@ -86,25 +96,32 @@ int ism_unregister_client(struct ism_client *client) int rc = 0; mutex_lock(&ism_dev_list.mutex); - spin_lock_irqsave(&clients_lock, flags); - clients[client->id] = NULL; - if (client->id + 1 == max_client) - max_client--; - spin_unlock_irqrestore(&clients_lock, flags); list_for_each_entry(ism, &ism_dev_list.list, list) { + spin_lock_irqsave(&ism->lock, flags); + /* Stop forwarding IRQs and events */ + ism->subs[client->id] = NULL; for (int i = 0; i < ISM_NR_DMBS; ++i) { if (ism->sba_client_arr[i] == client->id) { - pr_err("%s: attempt to unregister client '%s'" - "with registered dmb(s)\n", __func__, - client->name); + WARN(1, "%s: attempt to unregister '%s' with registered dmb(s)\n", + __func__, client->name); rc = -EBUSY; - goto out; + goto err_reg_dmb; } } + spin_unlock_irqrestore(&ism->lock, flags); } -out: mutex_unlock(&ism_dev_list.mutex); + mutex_lock(&clients_lock); + clients[client->id] = NULL; + if (client->id + 1 == max_client) + max_client--; + mutex_unlock(&clients_lock); + return rc; + +err_reg_dmb: + spin_unlock_irqrestore(&ism->lock, flags); + mutex_unlock(&ism_dev_list.mutex); return rc; } EXPORT_SYMBOL_GPL(ism_unregister_client); @@ -328,6 +345,7 @@ int ism_register_dmb(struct ism_dev *ism, struct ism_dmb *dmb, struct ism_client *client) { union ism_reg_dmb cmd; + unsigned long flags; int ret; ret = ism_alloc_dmb(ism, dmb); @@ -351,7 +369,9 @@ int ism_register_dmb(struct ism_dev *ism, struct ism_dmb *dmb, goto out; } dmb->dmb_tok = cmd.response.dmb_tok; + spin_lock_irqsave(&ism->lock, flags); ism->sba_client_arr[dmb->sba_idx - ISM_DMB_BIT_OFFSET] = client->id; + spin_unlock_irqrestore(&ism->lock, flags); out: return ret; } @@ -360,6 +380,7 @@ EXPORT_SYMBOL_GPL(ism_register_dmb); int ism_unregister_dmb(struct ism_dev *ism, struct ism_dmb *dmb) { union ism_unreg_dmb cmd; + unsigned long flags; int ret; memset(&cmd, 0, sizeof(cmd)); @@ -368,7 +389,9 @@ int ism_unregister_dmb(struct ism_dev *ism, struct ism_dmb *dmb) cmd.request.dmb_tok = dmb->dmb_tok; + spin_lock_irqsave(&ism->lock, flags); ism->sba_client_arr[dmb->sba_idx - ISM_DMB_BIT_OFFSET] = NO_CLIENT; + spin_unlock_irqrestore(&ism->lock, flags); ret = ism_cmd(ism, &cmd); if (ret && ret != ISM_ERROR) @@ -491,6 +514,7 @@ static u16 ism_get_chid(struct ism_dev *ism) static void ism_handle_event(struct ism_dev *ism) { struct ism_event *entry; + struct ism_client *clt; int i; while ((ism->ieq_idx + 1) != READ_ONCE(ism->ieq->header.idx)) { @@ -499,21 +523,21 @@ static void ism_handle_event(struct ism_dev *ism) entry = &ism->ieq->entry[ism->ieq_idx]; debug_event(ism_debug_info, 2, entry, sizeof(*entry)); - spin_lock(&clients_lock); - for (i = 0; i < max_client; ++i) - if (clients[i]) - clients[i]->handle_event(ism, entry); - spin_unlock(&clients_lock); + for (i = 0; i < max_client; ++i) { + clt = ism->subs[i]; + if (clt) + clt->handle_event(ism, entry); + } } } static irqreturn_t ism_handle_irq(int irq, void *data) { struct ism_dev *ism = data; - struct ism_client *clt; unsigned long bit, end; unsigned long *bv; u16 dmbemask; + u8 client_id; bv = (void *) &ism->sba->dmb_bits[ISM_DMB_WORD_OFFSET]; end = sizeof(ism->sba->dmb_bits) * BITS_PER_BYTE - ISM_DMB_BIT_OFFSET; @@ -530,8 +554,10 @@ static irqreturn_t ism_handle_irq(int irq, void *data) dmbemask = ism->sba->dmbe_mask[bit + ISM_DMB_BIT_OFFSET]; ism->sba->dmbe_mask[bit + ISM_DMB_BIT_OFFSET] = 0; barrier(); - clt = clients[ism->sba_client_arr[bit]]; - clt->handle_irq(ism, bit + ISM_DMB_BIT_OFFSET, dmbemask); + client_id = ism->sba_client_arr[bit]; + if (unlikely(client_id == NO_CLIENT || !ism->subs[client_id])) + continue; + ism->subs[client_id]->handle_irq(ism, bit + ISM_DMB_BIT_OFFSET, dmbemask); } if (ism->sba->e) { @@ -548,20 +574,9 @@ static u64 ism_get_local_gid(struct ism_dev *ism) return ism->local_gid; } -static void ism_dev_add_work_func(struct work_struct *work) -{ - struct ism_client *client = container_of(work, struct ism_client, - add_work); - - client->add(client->tgt_ism); - atomic_dec(&client->tgt_ism->add_dev_cnt); - wake_up(&client->tgt_ism->waitq); -} - static int ism_dev_init(struct ism_dev *ism) { struct pci_dev *pdev = ism->pdev; - unsigned long flags; int i, ret; ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_MSI); @@ -594,25 +609,16 @@ static int ism_dev_init(struct ism_dev *ism) /* hardware is V2 capable */ ism_create_system_eid(); - init_waitqueue_head(&ism->waitq); - atomic_set(&ism->free_clients_cnt, 0); - atomic_set(&ism->add_dev_cnt, 0); - - wait_event(ism->waitq, !atomic_read(&ism->add_dev_cnt)); - spin_lock_irqsave(&clients_lock, flags); - for (i = 0; i < max_client; ++i) + mutex_lock(&ism_dev_list.mutex); + mutex_lock(&clients_lock); + for (i = 0; i < max_client; ++i) { if (clients[i]) { - INIT_WORK(&clients[i]->add_work, - ism_dev_add_work_func); - clients[i]->tgt_ism = ism; - atomic_inc(&ism->add_dev_cnt); - schedule_work(&clients[i]->add_work); + clients[i]->add(ism); + ism_setup_forwarding(clients[i], ism); } - spin_unlock_irqrestore(&clients_lock, flags); - - wait_event(ism->waitq, !atomic_read(&ism->add_dev_cnt)); + } + mutex_unlock(&clients_lock); - mutex_lock(&ism_dev_list.mutex); list_add(&ism->list, &ism_dev_list.list); mutex_unlock(&ism_dev_list.mutex); @@ -660,7 +666,7 @@ static int ism_probe(struct pci_dev *pdev, const struct pci_device_id *id) if (ret) goto err_disable; - ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(64)); + ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); if (ret) goto err_resource; @@ -687,36 +693,24 @@ static int ism_probe(struct pci_dev *pdev, const struct pci_device_id *id) return ret; } -static void ism_dev_remove_work_func(struct work_struct *work) -{ - struct ism_client *client = container_of(work, struct ism_client, - remove_work); - - client->remove(client->tgt_ism); - atomic_dec(&client->tgt_ism->free_clients_cnt); - wake_up(&client->tgt_ism->waitq); -} - -/* Callers must hold ism_dev_list.mutex */ static void ism_dev_exit(struct ism_dev *ism) { struct pci_dev *pdev = ism->pdev; unsigned long flags; int i; - wait_event(ism->waitq, !atomic_read(&ism->free_clients_cnt)); - spin_lock_irqsave(&clients_lock, flags); + spin_lock_irqsave(&ism->lock, flags); for (i = 0; i < max_client; ++i) - if (clients[i]) { - INIT_WORK(&clients[i]->remove_work, - ism_dev_remove_work_func); - clients[i]->tgt_ism = ism; - atomic_inc(&ism->free_clients_cnt); - schedule_work(&clients[i]->remove_work); - } - spin_unlock_irqrestore(&clients_lock, flags); + ism->subs[i] = NULL; + spin_unlock_irqrestore(&ism->lock, flags); - wait_event(ism->waitq, !atomic_read(&ism->free_clients_cnt)); + mutex_lock(&ism_dev_list.mutex); + mutex_lock(&clients_lock); + for (i = 0; i < max_client; ++i) { + if (clients[i]) + clients[i]->remove(ism); + } + mutex_unlock(&clients_lock); if (SYSTEM_EID.serial_number[0] != '0' || SYSTEM_EID.type[0] != '0') @@ -727,15 +721,14 @@ static void ism_dev_exit(struct ism_dev *ism) kfree(ism->sba_client_arr); pci_free_irq_vectors(pdev); list_del_init(&ism->list); + mutex_unlock(&ism_dev_list.mutex); } static void ism_remove(struct pci_dev *pdev) { struct ism_dev *ism = dev_get_drvdata(&pdev->dev); - mutex_lock(&ism_dev_list.mutex); ism_dev_exit(ism); - mutex_unlock(&ism_dev_list.mutex); pci_release_mem_regions(pdev); pci_disable_device(pdev); diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c index 38f312664ce72b3b2cd622f4b2fa94cf9a4bb64d..9fd8e6f07a0339a543e3ba6495e92cad58e56aea 100644 --- a/drivers/s390/net/lcs.c +++ b/drivers/s390/net/lcs.c @@ -1899,14 +1899,14 @@ lcs_open_device(struct net_device *dev) static ssize_t lcs_portno_show (struct device *dev, struct device_attribute *attr, char *buf) { - struct lcs_card *card; + struct lcs_card *card; card = dev_get_drvdata(dev); - if (!card) - return 0; + if (!card) + return 0; - return sprintf(buf, "%d\n", card->portno); + return sysfs_emit(buf, "%d\n", card->portno); } /* @@ -1956,7 +1956,8 @@ lcs_type_show(struct device *dev, struct device_attribute *attr, char *buf) if (!cgdev) return -ENODEV; - return sprintf(buf, "%s\n", lcs_type[cgdev->cdev[0]->id.driver_info]); + return sysfs_emit(buf, "%s\n", + lcs_type[cgdev->cdev[0]->id.driver_info]); } static DEVICE_ATTR(type, 0444, lcs_type_show, NULL); @@ -1968,7 +1969,7 @@ lcs_timeout_show(struct device *dev, struct device_attribute *attr, char *buf) card = dev_get_drvdata(dev); - return card ? sprintf(buf, "%u\n", card->lancmd_timeout) : 0; + return card ? sysfs_emit(buf, "%u\n", card->lancmd_timeout) : 0; } static ssize_t diff --git a/drivers/s390/net/lcs.h b/drivers/s390/net/lcs.h index bd52caa3b11b54b5880ba739fc0108dafd48d374..a2699b70b0502c9fffac2ea4ad31137c983fd227 100644 --- a/drivers/s390/net/lcs.h +++ b/drivers/s390/net/lcs.h @@ -21,7 +21,7 @@ do { \ #define LCS_DBF_TEXT_(level,name,text...) \ do { \ if (debug_level_enabled(lcs_dbf_##name, level)) { \ - sprintf(debug_buffer, text); \ + scnprintf(debug_buffer, sizeof(debug_buffer), text); \ debug_text_event(lcs_dbf_##name, level, debug_buffer); \ } \ } while (0) diff --git a/drivers/s390/net/netiucv.c b/drivers/s390/net/netiucv.c index 66076cada8ae41aa179722558e41ac54a1bf926a..8852b03f943bb9b90cde793e3673cc88cd49c4e2 100644 --- a/drivers/s390/net/netiucv.c +++ b/drivers/s390/net/netiucv.c @@ -47,7 +47,7 @@ #include #include -#include +#include #include #include diff --git a/drivers/s390/net/qeth_l3_sys.c b/drivers/s390/net/qeth_l3_sys.c index 9f90a860ca2c97b2f6e749aa727a0708ef4419c4..a6b64228ead25367197daf39b289afb11e796182 100644 --- a/drivers/s390/net/qeth_l3_sys.c +++ b/drivers/s390/net/qeth_l3_sys.c @@ -625,7 +625,7 @@ static QETH_DEVICE_ATTR(vipa_add4, add4, 0644, static ssize_t qeth_l3_dev_vipa_del4_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - return qeth_l3_vipa_store(dev, buf, true, count, QETH_PROT_IPV4); + return qeth_l3_vipa_store(dev, buf, false, count, QETH_PROT_IPV4); } static QETH_DEVICE_ATTR(vipa_del4, del4, 0200, NULL, diff --git a/drivers/sbus/char/oradax.c b/drivers/sbus/char/oradax.c index aafce8d000004240a774a8d47370d41352195767..a536dd6f4f7cec50c59d40be79f025cafc364b34 100644 --- a/drivers/sbus/char/oradax.c +++ b/drivers/sbus/char/oradax.c @@ -226,8 +226,10 @@ static int dax_ccb_info(u64 ca, struct ccb_info_result *info); static int dax_ccb_kill(u64 ca, u16 *kill_res); static struct cdev c_dev; -static struct class *cl; static dev_t first; +static const struct class cl = { + .name = DAX_NAME, +}; static int max_ccb_version; static int dax_debug; @@ -323,14 +325,11 @@ static int __init dax_attach(void) goto done; } - cl = class_create(DAX_NAME); - if (IS_ERR(cl)) { - dax_err("class_create failed"); - ret = PTR_ERR(cl); + ret = class_register(&cl); + if (ret) goto class_error; - } - if (device_create(cl, NULL, first, NULL, dax_name) == NULL) { + if (device_create(&cl, NULL, first, NULL, dax_name) == NULL) { dax_err("device_create failed"); ret = -ENXIO; goto device_error; @@ -347,9 +346,9 @@ static int __init dax_attach(void) goto done; cdev_error: - device_destroy(cl, first); + device_destroy(&cl, first); device_error: - class_destroy(cl); + class_unregister(&cl); class_error: unregister_chrdev_region(first, 1); done: @@ -362,8 +361,8 @@ static void __exit dax_detach(void) { pr_info("Cleaning up DAX module\n"); cdev_del(&c_dev); - device_destroy(cl, first); - class_destroy(cl); + device_destroy(&cl, first); + class_unregister(&cl); unregister_chrdev_region(first, 1); } module_exit(dax_detach); diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c index 38d20a69ee122d02d0f3842bb9ad6beb0e49a605..f925f8664c2c198ed67f9f26da437ba4733594ee 100644 --- a/drivers/scsi/3w-9xxx.c +++ b/drivers/scsi/3w-9xxx.c @@ -617,7 +617,7 @@ static int twa_check_srl(TW_Device_Extension *tw_dev, int *flashed) } /* Load rest of compatibility struct */ - strlcpy(tw_dev->tw_compat_info.driver_version, TW_DRIVER_VERSION, + strscpy(tw_dev->tw_compat_info.driver_version, TW_DRIVER_VERSION, sizeof(tw_dev->tw_compat_info.driver_version)); tw_dev->tw_compat_info.driver_srl_high = TW_CURRENT_DRIVER_SRL; tw_dev->tw_compat_info.driver_branch_high = TW_CURRENT_DRIVER_BRANCH; diff --git a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c index 36c34ced0cc180227ff40fd742fdd70e8e85b2ef..f39c9ec2e781095abecd4e5e2b359aae83fbddbd 100644 --- a/drivers/scsi/3w-xxxx.c +++ b/drivers/scsi/3w-xxxx.c @@ -2305,8 +2305,10 @@ static int tw_probe(struct pci_dev *pdev, const struct pci_device_id *dev_id) TW_DISABLE_INTERRUPTS(tw_dev); /* Initialize the card */ - if (tw_reset_sequence(tw_dev)) + if (tw_reset_sequence(tw_dev)) { + retval = -EINVAL; goto out_release_mem_region; + } /* Set host specific parameters */ host->max_id = TW_MAX_UNITS; diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 0704809d9d99a551746e13c04e4dcac3b68ea170..4962ce989113a14abd5f84af82121158d04bef68 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -334,7 +334,7 @@ config SGIWD93_SCSI config BLK_DEV_3W_XXXX_RAID tristate "3ware 5/6/7/8xxx ATA-RAID support" - depends on PCI && SCSI + depends on PCI && HAS_IOPORT && SCSI help 3ware is the only hardware ATA-Raid product in Linux to date. This card is 2,4, or 8 channel master mode support only. @@ -381,7 +381,7 @@ config SCSI_3W_SAS config SCSI_ACARD tristate "ACARD SCSI support" - depends on PCI && SCSI + depends on PCI && HAS_IOPORT && SCSI help This driver supports the ACARD SCSI host adapter. Support Chip @@ -462,7 +462,7 @@ config SCSI_MVUMI config SCSI_ADVANSYS tristate "AdvanSys SCSI support" depends on SCSI - depends on ISA || EISA || PCI + depends on (ISA || EISA || PCI) && HAS_IOPORT depends on ISA_DMA_API || !ISA help This is a driver for all SCSI host adapters manufactured by @@ -503,7 +503,7 @@ config SCSI_HPTIOP config SCSI_BUSLOGIC tristate "BusLogic SCSI support" - depends on PCI && SCSI + depends on SCSI && PCI && HAS_IOPORT help This is support for BusLogic MultiMaster and FlashPoint SCSI Host Adapters. Consult the SCSI-HOWTO, available from @@ -518,7 +518,7 @@ config SCSI_BUSLOGIC config SCSI_FLASHPOINT bool "FlashPoint support" - depends on SCSI_BUSLOGIC && PCI + depends on SCSI_BUSLOGIC && PCI && HAS_IOPORT help This option allows you to add FlashPoint support to the BusLogic SCSI driver. The FlashPoint SCCB Manager code is @@ -632,7 +632,7 @@ config SCSI_SNIC_DEBUG_FS config SCSI_DMX3191D tristate "DMX3191D SCSI support" - depends on PCI && SCSI + depends on PCI && HAS_IOPORT && SCSI select SCSI_SPI_ATTRS help This is support for Domex DMX3191D SCSI Host Adapters. @@ -646,7 +646,7 @@ config SCSI_FDOMAIN config SCSI_FDOMAIN_PCI tristate "Future Domain TMC-3260/AHA-2920A PCI SCSI support" - depends on PCI && SCSI + depends on PCI && HAS_IOPORT && SCSI select SCSI_FDOMAIN help This is support for Future Domain's PCI SCSI host adapters (TMC-3260) @@ -699,7 +699,7 @@ config SCSI_GENERIC_NCR5380 config SCSI_IPS tristate "IBM ServeRAID support" - depends on PCI && SCSI + depends on PCI && HAS_IOPORT && SCSI help This is support for the IBM ServeRAID hardware RAID controllers. See @@ -759,7 +759,7 @@ config SCSI_IBMVFC_TRACE config SCSI_INITIO tristate "Initio 9100U(W) support" - depends on PCI && SCSI + depends on PCI && HAS_IOPORT && SCSI help This is support for the Initio 91XXU(W) SCSI host adapter. Please read the SCSI-HOWTO, available from @@ -770,7 +770,7 @@ config SCSI_INITIO config SCSI_INIA100 tristate "Initio INI-A100U2W support" - depends on PCI && SCSI + depends on PCI && HAS_IOPORT && SCSI help This is support for the Initio INI-A100U2W SCSI host adapter. Please read the SCSI-HOWTO, available from @@ -782,6 +782,7 @@ config SCSI_INIA100 config SCSI_PPA tristate "IOMEGA parallel port (ppa - older drives)" depends on SCSI && PARPORT_PC + depends on HAS_IOPORT help This driver supports older versions of IOMEGA's parallel port ZIP drive (a 100 MB removable media device). @@ -1175,7 +1176,7 @@ config SCSI_SIM710 config SCSI_DC395x tristate "Tekram DC395(U/UW/F) and DC315(U) SCSI support" - depends on PCI && SCSI + depends on PCI && HAS_IOPORT && SCSI select SCSI_SPI_ATTRS help This driver supports PCI SCSI host adapters based on the ASIC @@ -1207,7 +1208,7 @@ config SCSI_AM53C974 config SCSI_NSP32 tristate "Workbit NinjaSCSI-32Bi/UDE support" - depends on PCI && SCSI && !64BIT + depends on PCI && SCSI && !64BIT && HAS_IOPORT help This is support for the Workbit NinjaSCSI-32Bi/UDE PCI/Cardbus SCSI host adapter. Please read the SCSI-HOWTO, available from diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index ca85bddb582b468a4573b2858d52cf5acd3c80d9..cea3a79d538e4b537a79915f06f4bc1ce7e2cf7c 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -417,7 +417,7 @@ static int NCR5380_init(struct Scsi_Host *instance, int flags) INIT_WORK(&hostdata->main_task, NCR5380_main); hostdata->work_q = alloc_workqueue("ncr5380_%d", WQ_UNBOUND | WQ_MEM_RECLAIM, - 1, instance->host_no); + 0, instance->host_no); if (!hostdata->work_q) return -ENOMEM; diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c index 24c049eff157a51cb607292bcf55b1cf78a52cf1..70e1cac1975ebedb6608890f756775a0d13b5ffc 100644 --- a/drivers/scsi/aacraid/aachba.c +++ b/drivers/scsi/aacraid/aachba.c @@ -3289,7 +3289,7 @@ static int query_disk(struct aac_dev *dev, void __user *arg) else qd.unmapped = 0; - strlcpy(qd.name, fsa_dev_ptr[qd.cnum].devname, + strscpy(qd.name, fsa_dev_ptr[qd.cnum].devname, min(sizeof(qd.name), sizeof(fsa_dev_ptr[qd.cnum].devname) + 1)); if (copy_to_user(arg, &qd, sizeof (struct aac_query_disk))) diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h index 7c6efde75da664b3819161d5aa96466b0d26aaa1..73b6ac0c01f549a1ab20fcee5172b42a0232a35a 100644 --- a/drivers/scsi/aacraid/aacraid.h +++ b/drivers/scsi/aacraid/aacraid.h @@ -2618,7 +2618,7 @@ struct aac_hba_info { struct aac_aifcmd { __le32 command; /* Tell host what type of notify this is */ __le32 seqnum; /* To allow ordering of reports (if necessary) */ - u8 data[1]; /* Undefined length (from kernel viewpoint) */ + u8 data[]; /* Undefined length (from kernel viewpoint) */ }; /** diff --git a/drivers/scsi/aic7xxx/Kconfig.aic79xx b/drivers/scsi/aic7xxx/Kconfig.aic79xx index a47dbd500e9a5af1f448327225ccb5aa9e3f3217..4bc53eec4c83f7a39fed723fc73f75d1cb8c3c59 100644 --- a/drivers/scsi/aic7xxx/Kconfig.aic79xx +++ b/drivers/scsi/aic7xxx/Kconfig.aic79xx @@ -5,7 +5,7 @@ # config SCSI_AIC79XX tristate "Adaptec AIC79xx U320 support" - depends on PCI && SCSI + depends on PCI && HAS_IOPORT && SCSI select SCSI_SPI_ATTRS help This driver supports all of Adaptec's Ultra 320 PCI-X diff --git a/drivers/scsi/aic7xxx/Kconfig.aic7xxx b/drivers/scsi/aic7xxx/Kconfig.aic7xxx index 0cfd92ce750af5b5b3162d82b9bc522176c7358c..f0425145a5f4d8a878344d02c4f82794dff0f025 100644 --- a/drivers/scsi/aic7xxx/Kconfig.aic7xxx +++ b/drivers/scsi/aic7xxx/Kconfig.aic7xxx @@ -5,7 +5,7 @@ # config SCSI_AIC7XXX tristate "Adaptec AIC7xxx Fast -> U160 support" - depends on (PCI || EISA) && SCSI + depends on (PCI || EISA) && HAS_IOPORT && SCSI select SCSI_SPI_ATTRS help This driver supports all of Adaptec's Fast through Ultra 160 PCI diff --git a/drivers/scsi/aic94xx/Kconfig b/drivers/scsi/aic94xx/Kconfig index 71931c371b1cff1744018a657c60eacfb01f8d5b..aaa8dadc6e1cd0a30f7d3f42edbb2fd7a4dc3591 100644 --- a/drivers/scsi/aic94xx/Kconfig +++ b/drivers/scsi/aic94xx/Kconfig @@ -8,7 +8,7 @@ config SCSI_AIC94XX tristate "Adaptec AIC94xx SAS/SATA support" - depends on PCI + depends on PCI && HAS_IOPORT select SCSI_SAS_LIBSAS select FW_LOADER help diff --git a/drivers/scsi/bfa/bfa_fcbuild.c b/drivers/scsi/bfa/bfa_fcbuild.c index df18d9d2af53e4ce4b3be1e509ee93296503717b..773c84af784c87350a4701e15dbbf6b76c2832e2 100644 --- a/drivers/scsi/bfa/bfa_fcbuild.c +++ b/drivers/scsi/bfa/bfa_fcbuild.c @@ -1134,7 +1134,7 @@ fc_rspnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id, memset(rspnid, 0, sizeof(struct fcgs_rspnid_req_s)); rspnid->dap = s_id; - strlcpy(rspnid->spn, name, sizeof(rspnid->spn)); + strscpy(rspnid->spn, name, sizeof(rspnid->spn)); rspnid->spn_len = (u8) strlen(rspnid->spn); return sizeof(struct fcgs_rspnid_req_s) + sizeof(struct ct_hdr_s); @@ -1155,7 +1155,7 @@ fc_rsnn_nn_build(struct fchs_s *fchs, void *pyld, u32 s_id, memset(rsnn_nn, 0, sizeof(struct fcgs_rsnn_nn_req_s)); rsnn_nn->node_name = node_name; - strlcpy(rsnn_nn->snn, name, sizeof(rsnn_nn->snn)); + strscpy(rsnn_nn->snn, name, sizeof(rsnn_nn->snn)); rsnn_nn->snn_len = (u8) strlen(rsnn_nn->snn); return sizeof(struct fcgs_rsnn_nn_req_s) + sizeof(struct ct_hdr_s); diff --git a/drivers/scsi/bfa/bfa_fcs.c b/drivers/scsi/bfa/bfa_fcs.c index d2d396ca0e9a04a056595e83b77a9d937d3deae8..5023c0ab42777aa06a1fc23e8013aaa9a1c2ad1b 100644 --- a/drivers/scsi/bfa/bfa_fcs.c +++ b/drivers/scsi/bfa/bfa_fcs.c @@ -761,7 +761,7 @@ bfa_fcs_fabric_psymb_init(struct bfa_fcs_fabric_s *fabric) bfa_ioc_get_adapter_model(&fabric->fcs->bfa->ioc, model); /* Model name/number */ - strlcpy(port_cfg->sym_name.symname, model, + strscpy(port_cfg->sym_name.symname, model, BFA_SYMNAME_MAXLEN); strlcat(port_cfg->sym_name.symname, BFA_FCS_PORT_SYMBNAME_SEPARATOR, BFA_SYMNAME_MAXLEN); @@ -822,7 +822,7 @@ bfa_fcs_fabric_nsymb_init(struct bfa_fcs_fabric_s *fabric) bfa_ioc_get_adapter_model(&fabric->fcs->bfa->ioc, model); /* Model name/number */ - strlcpy(port_cfg->node_sym_name.symname, model, + strscpy(port_cfg->node_sym_name.symname, model, BFA_SYMNAME_MAXLEN); strlcat(port_cfg->node_sym_name.symname, BFA_FCS_PORT_SYMBNAME_SEPARATOR, diff --git a/drivers/scsi/bfa/bfa_fcs_lport.c b/drivers/scsi/bfa/bfa_fcs_lport.c index b12afcc4b1894a1fd62b59ae981868b8159c6e44..008afd81708713a7999bde6ba95d20588ed80b29 100644 --- a/drivers/scsi/bfa/bfa_fcs_lport.c +++ b/drivers/scsi/bfa/bfa_fcs_lport.c @@ -2642,10 +2642,10 @@ bfa_fcs_fdmi_get_hbaattr(struct bfa_fcs_lport_fdmi_s *fdmi, bfa_ioc_get_adapter_fw_ver(&port->fcs->bfa->ioc, hba_attr->fw_version); - strlcpy(hba_attr->driver_version, (char *)driver_info->version, + strscpy(hba_attr->driver_version, (char *)driver_info->version, sizeof(hba_attr->driver_version)); - strlcpy(hba_attr->os_name, driver_info->host_os_name, + strscpy(hba_attr->os_name, driver_info->host_os_name, sizeof(hba_attr->os_name)); /* @@ -2663,13 +2663,13 @@ bfa_fcs_fdmi_get_hbaattr(struct bfa_fcs_lport_fdmi_s *fdmi, bfa_fcs_fdmi_get_portattr(fdmi, &fcs_port_attr); hba_attr->max_ct_pyld = fcs_port_attr.max_frm_size; - strlcpy(hba_attr->node_sym_name.symname, + strscpy(hba_attr->node_sym_name.symname, port->port_cfg.node_sym_name.symname, BFA_SYMNAME_MAXLEN); strcpy(hba_attr->vendor_info, "QLogic"); hba_attr->num_ports = cpu_to_be32(bfa_ioc_get_nports(&port->fcs->bfa->ioc)); hba_attr->fabric_name = port->fabric->lps->pr_nwwn; - strlcpy(hba_attr->bios_ver, hba_attr->option_rom_ver, BFA_VERSION_LEN); + strscpy(hba_attr->bios_ver, hba_attr->option_rom_ver, BFA_VERSION_LEN); } @@ -2736,19 +2736,19 @@ bfa_fcs_fdmi_get_portattr(struct bfa_fcs_lport_fdmi_s *fdmi, /* * OS device Name */ - strlcpy(port_attr->os_device_name, driver_info->os_device_name, + strscpy(port_attr->os_device_name, driver_info->os_device_name, sizeof(port_attr->os_device_name)); /* * Host name */ - strlcpy(port_attr->host_name, driver_info->host_machine_name, + strscpy(port_attr->host_name, driver_info->host_machine_name, sizeof(port_attr->host_name)); port_attr->node_name = bfa_fcs_lport_get_nwwn(port); port_attr->port_name = bfa_fcs_lport_get_pwwn(port); - strlcpy(port_attr->port_sym_name.symname, + strscpy(port_attr->port_sym_name.symname, bfa_fcs_lport_get_psym_name(port).symname, BFA_SYMNAME_MAXLEN); bfa_fcs_lport_get_attr(port, &lport_attr); port_attr->port_type = cpu_to_be32(lport_attr.port_type); @@ -3229,7 +3229,7 @@ bfa_fcs_lport_ms_gmal_response(void *fcsarg, struct bfa_fcxp_s *fcxp, rsp_str[gmal_entry->len-1] = 0; /* copy IP Address to fabric */ - strlcpy(bfa_fcs_lport_get_fabric_ipaddr(port), + strscpy(bfa_fcs_lport_get_fabric_ipaddr(port), gmal_entry->ip_addr, BFA_FCS_FABRIC_IPADDR_SZ); break; @@ -4667,7 +4667,7 @@ bfa_fcs_lport_ns_send_rspn_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced) * to that of the base port. */ - strlcpy(symbl, + strscpy(symbl, (char *)&(bfa_fcs_lport_get_psym_name (bfa_fcs_get_base_port(port->fcs))), sizeof(symbl)); @@ -5194,7 +5194,7 @@ bfa_fcs_lport_ns_util_send_rspn_id(void *cbarg, struct bfa_fcxp_s *fcxp_alloced) * For Vports, we append the vport's port symbolic name * to that of the base port. */ - strlcpy(symbl, (char *)&(bfa_fcs_lport_get_psym_name + strscpy(symbl, (char *)&(bfa_fcs_lport_get_psym_name (bfa_fcs_get_base_port(port->fcs))), sizeof(symbl)); diff --git a/drivers/scsi/bfa/bfa_ioc.c b/drivers/scsi/bfa/bfa_ioc.c index 5740302d83ac1db2d7f555dd488bd805f074b0cd..e1ed1424fddb2621ff09d6a1313a3e87f4c428dd 100644 --- a/drivers/scsi/bfa/bfa_ioc.c +++ b/drivers/scsi/bfa/bfa_ioc.c @@ -2788,7 +2788,7 @@ void bfa_ioc_get_adapter_manufacturer(struct bfa_ioc_s *ioc, char *manufacturer) { memset((void *)manufacturer, 0, BFA_ADAPTER_MFG_NAME_LEN); - strlcpy(manufacturer, BFA_MFG_NAME, BFA_ADAPTER_MFG_NAME_LEN); + strscpy(manufacturer, BFA_MFG_NAME, BFA_ADAPTER_MFG_NAME_LEN); } void diff --git a/drivers/scsi/bfa/bfa_svc.c b/drivers/scsi/bfa/bfa_svc.c index 4e3cef02f10facc33c9fe6322144b6740e7f859d..c9745c0b4eee3ad9a8538a67ea7bafa6706b0955 100644 --- a/drivers/scsi/bfa/bfa_svc.c +++ b/drivers/scsi/bfa/bfa_svc.c @@ -330,7 +330,7 @@ bfa_plog_str(struct bfa_plog_s *plog, enum bfa_plog_mid mid, lp.eid = event; lp.log_type = BFA_PL_LOG_TYPE_STRING; lp.misc = misc; - strlcpy(lp.log_entry.string_log, log_str, + strscpy(lp.log_entry.string_log, log_str, BFA_PL_STRING_LOG_SZ); lp.log_entry.string_log[BFA_PL_STRING_LOG_SZ - 1] = '\0'; bfa_plog_add(plog, &lp); diff --git a/drivers/scsi/bfa/bfad.c b/drivers/scsi/bfa/bfad.c index 529b73a83d69340580d03a057ae43cf4edca169c..62cb7a864fd53de5f38143fe67315eda9f7e5dd0 100644 --- a/drivers/scsi/bfa/bfad.c +++ b/drivers/scsi/bfa/bfad.c @@ -965,19 +965,19 @@ bfad_start_ops(struct bfad_s *bfad) { /* Fill the driver_info info to fcs*/ memset(&driver_info, 0, sizeof(driver_info)); - strlcpy(driver_info.version, BFAD_DRIVER_VERSION, + strscpy(driver_info.version, BFAD_DRIVER_VERSION, sizeof(driver_info.version)); if (host_name) - strlcpy(driver_info.host_machine_name, host_name, + strscpy(driver_info.host_machine_name, host_name, sizeof(driver_info.host_machine_name)); if (os_name) - strlcpy(driver_info.host_os_name, os_name, + strscpy(driver_info.host_os_name, os_name, sizeof(driver_info.host_os_name)); if (os_patch) - strlcpy(driver_info.host_os_patch, os_patch, + strscpy(driver_info.host_os_patch, os_patch, sizeof(driver_info.host_os_patch)); - strlcpy(driver_info.os_device_name, bfad->pci_name, + strscpy(driver_info.os_device_name, bfad->pci_name, sizeof(driver_info.os_device_name)); /* FCS driver info init */ diff --git a/drivers/scsi/bfa/bfad_attr.c b/drivers/scsi/bfa/bfad_attr.c index 5a85401e9e2d3b4674c11d0a876b47aa4f6e5855..e96e4b6df2659263f240f354183250c85ed10412 100644 --- a/drivers/scsi/bfa/bfad_attr.c +++ b/drivers/scsi/bfa/bfad_attr.c @@ -834,7 +834,7 @@ bfad_im_symbolic_name_show(struct device *dev, struct device_attribute *attr, char symname[BFA_SYMNAME_MAXLEN]; bfa_fcs_lport_get_attr(&bfad->bfa_fcs.fabric.bport, &port_attr); - strlcpy(symname, port_attr.port_cfg.sym_name.symname, + strscpy(symname, port_attr.port_cfg.sym_name.symname, BFA_SYMNAME_MAXLEN); return sysfs_emit(buf, "%s\n", symname); } diff --git a/drivers/scsi/bfa/bfad_bsg.c b/drivers/scsi/bfa/bfad_bsg.c index 79d4f7ee5bcb05c6073544c936f7e945f1f367b4..520f9152f3bf2d4db20f117b4e65052ea14bc1e1 100644 --- a/drivers/scsi/bfa/bfad_bsg.c +++ b/drivers/scsi/bfa/bfad_bsg.c @@ -119,7 +119,7 @@ bfad_iocmd_ioc_get_attr(struct bfad_s *bfad, void *cmd) /* fill in driver attr info */ strcpy(iocmd->ioc_attr.driver_attr.driver, BFAD_DRIVER_NAME); - strlcpy(iocmd->ioc_attr.driver_attr.driver_ver, + strscpy(iocmd->ioc_attr.driver_attr.driver_ver, BFAD_DRIVER_VERSION, BFA_VERSION_LEN); strcpy(iocmd->ioc_attr.driver_attr.fw_ver, iocmd->ioc_attr.adapter_attr.fw_ver); @@ -307,7 +307,7 @@ bfad_iocmd_port_get_attr(struct bfad_s *bfad, void *cmd) iocmd->attr.port_type = port_attr.port_type; iocmd->attr.loopback = port_attr.loopback; iocmd->attr.authfail = port_attr.authfail; - strlcpy(iocmd->attr.port_symname.symname, + strscpy(iocmd->attr.port_symname.symname, port_attr.port_cfg.sym_name.symname, sizeof(iocmd->attr.port_symname.symname)); diff --git a/drivers/scsi/bfa/bfad_im.c b/drivers/scsi/bfa/bfad_im.c index c335f7a188d22d6785569d0f20822ac1461c5c38..a9d3d8562d3c174d5a70d228a0e41a937f3895a1 100644 --- a/drivers/scsi/bfa/bfad_im.c +++ b/drivers/scsi/bfa/bfad_im.c @@ -1046,7 +1046,7 @@ bfad_fc_host_init(struct bfad_im_port_s *im_port) /* For fibre channel services type 0x20 */ fc_host_supported_fc4s(host)[7] = 1; - strlcpy(symname, bfad->bfa_fcs.fabric.bport.port_cfg.sym_name.symname, + strscpy(symname, bfad->bfa_fcs.fabric.bport.port_cfg.sym_name.symname, BFA_SYMNAME_MAXLEN); sprintf(fc_host_symbolic_name(host), "%s", symname); diff --git a/drivers/scsi/bnx2i/bnx2i_init.c b/drivers/scsi/bnx2i/bnx2i_init.c index 2b3f0c10478e3eb0e2db5a19b348a3bbc0f3c2a9..872ad37e2a6eaf7314ba93e84890da76bdf7304d 100644 --- a/drivers/scsi/bnx2i/bnx2i_init.c +++ b/drivers/scsi/bnx2i/bnx2i_init.c @@ -383,7 +383,7 @@ int bnx2i_get_stats(void *handle) if (!stats) return -ENOMEM; - strlcpy(stats->version, DRV_MODULE_VERSION, sizeof(stats->version)); + strscpy(stats->version, DRV_MODULE_VERSION, sizeof(stats->version)); memcpy(stats->mac_add1 + 2, hba->cnic->mac_addr, ETH_ALEN); stats->max_frame_size = hba->netdev->mtu; diff --git a/drivers/scsi/ch.c b/drivers/scsi/ch.c index ac648bb8f7e7f41481ebdbff5c6c7ae7a36d1a98..cb0a399be1ccee335a307e0a50889a36a4c3fdfb 100644 --- a/drivers/scsi/ch.c +++ b/drivers/scsi/ch.c @@ -877,7 +877,8 @@ static long ch_ioctl(struct file *file, } default: - return scsi_ioctl(ch->device, file->f_mode, cmd, argp); + return scsi_ioctl(ch->device, file->f_mode & FMODE_WRITE, cmd, + argp); } } diff --git a/drivers/scsi/fcoe/fcoe_transport.c b/drivers/scsi/fcoe/fcoe_transport.c index 46b0bf237be1d4f34041f65b51aa3bd3f4a42f25..a48d24af9ac3f27516e5fc19de076a9b5f9b10bc 100644 --- a/drivers/scsi/fcoe/fcoe_transport.c +++ b/drivers/scsi/fcoe/fcoe_transport.c @@ -711,7 +711,7 @@ static struct net_device *fcoe_if_to_netdev(const char *buffer) char ifname[IFNAMSIZ + 2]; if (buffer) { - strlcpy(ifname, buffer, IFNAMSIZ); + strscpy(ifname, buffer, IFNAMSIZ); cp = ifname + strlen(ifname); while (--cp >= ifname && *cp == '\n') *cp = '\0'; diff --git a/drivers/scsi/fnic/fnic_debugfs.c b/drivers/scsi/fnic/fnic_debugfs.c index 6fedc3b7d1ab28516239a7c18a559a825858b1c7..c4d9ed0d7d753f7cc5aa0c40e6ece7ad8693079f 100644 --- a/drivers/scsi/fnic/fnic_debugfs.c +++ b/drivers/scsi/fnic/fnic_debugfs.c @@ -201,25 +201,21 @@ static int fnic_trace_debugfs_open(struct inode *inode, return -ENOMEM; if (*rdata_ptr == fc_trc_flag->fnic_trace) { - fnic_dbg_prt->buffer = vmalloc(array3_size(3, trace_max_pages, + fnic_dbg_prt->buffer = vzalloc(array3_size(3, trace_max_pages, PAGE_SIZE)); if (!fnic_dbg_prt->buffer) { kfree(fnic_dbg_prt); return -ENOMEM; } - memset((void *)fnic_dbg_prt->buffer, 0, - 3 * (trace_max_pages * PAGE_SIZE)); fnic_dbg_prt->buffer_len = fnic_get_trace_data(fnic_dbg_prt); } else { fnic_dbg_prt->buffer = - vmalloc(array3_size(3, fnic_fc_trace_max_pages, + vzalloc(array3_size(3, fnic_fc_trace_max_pages, PAGE_SIZE)); if (!fnic_dbg_prt->buffer) { kfree(fnic_dbg_prt); return -ENOMEM; } - memset((void *)fnic_dbg_prt->buffer, 0, - 3 * (fnic_fc_trace_max_pages * PAGE_SIZE)); fnic_dbg_prt->buffer_len = fnic_fc_trace_get_data(fnic_dbg_prt, *rdata_ptr); } diff --git a/drivers/scsi/fnic/fnic_trace.c b/drivers/scsi/fnic/fnic_trace.c index f3c3a26a1384dbe70dde94e015051c955ccc6d67..be0d7c57b242b28725a65018c7c2a94a982b635b 100644 --- a/drivers/scsi/fnic/fnic_trace.c +++ b/drivers/scsi/fnic/fnic_trace.c @@ -465,7 +465,7 @@ int fnic_trace_buf_init(void) fnic_max_trace_entries = (trace_max_pages * PAGE_SIZE)/ FNIC_ENTRY_SIZE_BYTES; - fnic_trace_buf_p = (unsigned long)vzalloc(trace_max_pages * PAGE_SIZE); + fnic_trace_buf_p = (unsigned long)vcalloc(trace_max_pages, PAGE_SIZE); if (!fnic_trace_buf_p) { printk(KERN_ERR PFX "Failed to allocate memory " "for fnic_trace_buf_p\n"); diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h index fb7c52c119df12bbfa146c96039e67714983a80d..9e73e9cbbcfc6c45fbb17b706aa3003a77ea3821 100644 --- a/drivers/scsi/hisi_sas/hisi_sas.h +++ b/drivers/scsi/hisi_sas/hisi_sas.h @@ -642,7 +642,7 @@ extern void hisi_sas_sata_done(struct sas_task *task, extern int hisi_sas_get_fw_info(struct hisi_hba *hisi_hba); extern int hisi_sas_probe(struct platform_device *pdev, const struct hisi_sas_hw *ops); -extern int hisi_sas_remove(struct platform_device *pdev); +extern void hisi_sas_remove(struct platform_device *pdev); extern int hisi_sas_slave_configure(struct scsi_device *sdev); extern int hisi_sas_slave_alloc(struct scsi_device *sdev); diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c index 412431c901a72aa1126cb8bfa638f99612a2ac9c..8f22ece957bd4d3b5b88a16f3d3ceb5730af64da 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_main.c +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c @@ -2560,7 +2560,7 @@ int hisi_sas_probe(struct platform_device *pdev, } EXPORT_SYMBOL_GPL(hisi_sas_probe); -int hisi_sas_remove(struct platform_device *pdev) +void hisi_sas_remove(struct platform_device *pdev) { struct sas_ha_struct *sha = platform_get_drvdata(pdev); struct hisi_hba *hisi_hba = sha->lldd_ha; @@ -2573,7 +2573,6 @@ int hisi_sas_remove(struct platform_device *pdev) hisi_sas_free(hisi_hba); scsi_host_put(shost); - return 0; } EXPORT_SYMBOL_GPL(hisi_sas_remove); diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c index 0aa8c9c88535559c8d52a58732e6fa86202777ee..94fbbceddc2e6faeb7f9219e7db0cc4ad7e8417d 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c @@ -1790,11 +1790,6 @@ static int hisi_sas_v1_probe(struct platform_device *pdev) return hisi_sas_probe(pdev, &hisi_sas_v1_hw); } -static int hisi_sas_v1_remove(struct platform_device *pdev) -{ - return hisi_sas_remove(pdev); -} - static const struct of_device_id sas_v1_of_match[] = { { .compatible = "hisilicon,hip05-sas-v1",}, {}, @@ -1810,7 +1805,7 @@ MODULE_DEVICE_TABLE(acpi, sas_v1_acpi_match); static struct platform_driver hisi_sas_v1_driver = { .probe = hisi_sas_v1_probe, - .remove = hisi_sas_v1_remove, + .remove_new = hisi_sas_remove, .driver = { .name = DRV_NAME, .of_match_table = sas_v1_of_match, diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c index cd78e4c983aa8d1a251399e6b3a85523f4c68fc4..87d8e408ccd1ced81601292d57eade447bab65a0 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c @@ -3619,11 +3619,6 @@ static int hisi_sas_v2_probe(struct platform_device *pdev) return hisi_sas_probe(pdev, &hisi_sas_v2_hw); } -static int hisi_sas_v2_remove(struct platform_device *pdev) -{ - return hisi_sas_remove(pdev); -} - static const struct of_device_id sas_v2_of_match[] = { { .compatible = "hisilicon,hip06-sas-v2",}, { .compatible = "hisilicon,hip07-sas-v2",}, @@ -3640,7 +3635,7 @@ MODULE_DEVICE_TABLE(acpi, sas_v2_acpi_match); static struct platform_driver hisi_sas_v2_driver = { .probe = hisi_sas_v2_probe, - .remove = hisi_sas_v2_remove, + .remove_new = hisi_sas_remove, .driver = { .name = DRV_NAME, .of_match_table = sas_v2_of_match, diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c index 12d588454f5dea63015aaa9c5a0ab45287728aee..20e1607c62828b4c774ff1be7cabe7e6e7e85e23 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c @@ -30,6 +30,7 @@ #define SATA_INITI_D2H_STORE_ADDR_LO 0x60 #define SATA_INITI_D2H_STORE_ADDR_HI 0x64 #define CFG_MAX_TAG 0x68 +#define TRANS_LOCK_ICT_TIME 0X70 #define HGC_SAS_TX_OPEN_FAIL_RETRY_CTRL 0x84 #define HGC_SAS_TXFAIL_RETRY_CTRL 0x88 #define HGC_GET_ITV_TIME 0x90 @@ -627,13 +628,15 @@ static void interrupt_enable_v3_hw(struct hisi_hba *hisi_hba) static void init_reg_v3_hw(struct hisi_hba *hisi_hba) { + struct pci_dev *pdev = hisi_hba->pci_dev; int i, j; /* Global registers init */ hisi_sas_write32(hisi_hba, DLVRY_QUEUE_ENABLE, (u32)((1ULL << hisi_hba->queue_count) - 1)); - hisi_sas_write32(hisi_hba, SAS_AXI_USER3, 0); hisi_sas_write32(hisi_hba, CFG_MAX_TAG, 0xfff0400); + /* time / CLK_AHB = 2.5s / 2ns = 0x4A817C80 */ + hisi_sas_write32(hisi_hba, TRANS_LOCK_ICT_TIME, 0x4A817C80); hisi_sas_write32(hisi_hba, HGC_SAS_TXFAIL_RETRY_CTRL, 0x108); hisi_sas_write32(hisi_hba, CFG_AGING_TIME, 0x1); hisi_sas_write32(hisi_hba, INT_COAL_EN, 0x1); @@ -652,6 +655,9 @@ static void init_reg_v3_hw(struct hisi_hba *hisi_hba) hisi_sas_write32(hisi_hba, ARQOS_ARCACHE_CFG, 0xf0f0); hisi_sas_write32(hisi_hba, HYPER_STREAM_ID_EN_CFG, 1); + if (pdev->revision < 0x30) + hisi_sas_write32(hisi_hba, SAS_AXI_USER3, 0); + interrupt_enable_v3_hw(hisi_hba); for (i = 0; i < hisi_hba->n_phy; i++) { enum sas_linkrate max; @@ -669,7 +675,6 @@ static void init_reg_v3_hw(struct hisi_hba *hisi_hba) prog_phy_link_rate |= hisi_sas_get_prog_phy_linkrate_mask(max); hisi_sas_phy_write32(hisi_hba, i, PROG_PHY_LINK_RATE, prog_phy_link_rate); - hisi_sas_phy_write32(hisi_hba, i, SERDES_CFG, 0xffc00); hisi_sas_phy_write32(hisi_hba, i, SAS_RX_TRAIN_TIMER, 0x13e80); hisi_sas_phy_write32(hisi_hba, i, CHL_INT0, 0xffffffff); hisi_sas_phy_write32(hisi_hba, i, CHL_INT1, 0xffffffff); @@ -680,13 +685,18 @@ static void init_reg_v3_hw(struct hisi_hba *hisi_hba) hisi_sas_phy_write32(hisi_hba, i, PHYCTRL_OOB_RESTART_MSK, 0x1); hisi_sas_phy_write32(hisi_hba, i, STP_LINK_TIMER, 0x7f7a120); hisi_sas_phy_write32(hisi_hba, i, CON_CFG_DRIVER, 0x2a0a01); - hisi_sas_phy_write32(hisi_hba, i, SAS_SSP_CON_TIMER_CFG, 0x32); hisi_sas_phy_write32(hisi_hba, i, SAS_EC_INT_COAL_TIME, 0x30f4240); - /* used for 12G negotiate */ - hisi_sas_phy_write32(hisi_hba, i, COARSETUNE_TIME, 0x1e); hisi_sas_phy_write32(hisi_hba, i, AIP_LIMIT, 0x2ffff); + /* set value through firmware for 920B and later version */ + if (pdev->revision < 0x30) { + hisi_sas_phy_write32(hisi_hba, i, SAS_SSP_CON_TIMER_CFG, 0x32); + hisi_sas_phy_write32(hisi_hba, i, SERDES_CFG, 0xffc00); + /* used for 12G negotiate */ + hisi_sas_phy_write32(hisi_hba, i, COARSETUNE_TIME, 0x1e); + } + /* get default FFE configuration for BIST */ for (j = 0; j < FFE_CFG_MAX; j++) { u32 val = hisi_sas_phy_read32(hisi_hba, i, @@ -2206,6 +2216,7 @@ slot_err_v3_hw(struct hisi_hba *hisi_hba, struct sas_task *task, u32 trans_tx_fail_type = le32_to_cpu(record->trans_tx_fail_type); u16 sipc_rx_err_type = le16_to_cpu(record->sipc_rx_err_type); u32 dw3 = le32_to_cpu(complete_hdr->dw3); + u32 dw0 = le32_to_cpu(complete_hdr->dw0); switch (task->task_proto) { case SAS_PROTOCOL_SSP: @@ -2215,8 +2226,8 @@ slot_err_v3_hw(struct hisi_hba *hisi_hba, struct sas_task *task, * but I/O information has been written to the host memory, we examine * response IU. */ - if (!(complete_hdr->dw0 & CMPLT_HDR_RSPNS_GOOD_MSK) && - (complete_hdr->dw0 & CMPLT_HDR_RSPNS_XFRD_MSK)) + if (!(dw0 & CMPLT_HDR_RSPNS_GOOD_MSK) && + (dw0 & CMPLT_HDR_RSPNS_XFRD_MSK)) return false; ts->residual = trans_tx_fail_type; @@ -2232,7 +2243,7 @@ slot_err_v3_hw(struct hisi_hba *hisi_hba, struct sas_task *task, case SAS_PROTOCOL_SATA: case SAS_PROTOCOL_STP: case SAS_PROTOCOL_SATA | SAS_PROTOCOL_STP: - if ((complete_hdr->dw0 & CMPLT_HDR_RSPNS_XFRD_MSK) && + if ((dw0 & CMPLT_HDR_RSPNS_XFRD_MSK) && (sipc_rx_err_type & RX_FIS_STATUS_ERR_MSK)) { ts->stat = SAS_PROTO_RESPONSE; } else if (dma_rx_err_type & RX_DATA_LEN_UNDERFLOW_MSK) { @@ -2999,6 +3010,7 @@ static const struct hisi_sas_debugfs_reg_lu debugfs_global_reg_lu[] = { HISI_SAS_DEBUGFS_REG(SATA_INITI_D2H_STORE_ADDR_LO), HISI_SAS_DEBUGFS_REG(SATA_INITI_D2H_STORE_ADDR_HI), HISI_SAS_DEBUGFS_REG(CFG_MAX_TAG), + HISI_SAS_DEBUGFS_REG(TRANS_LOCK_ICT_TIME), HISI_SAS_DEBUGFS_REG(HGC_SAS_TX_OPEN_FAIL_RETRY_CTRL), HISI_SAS_DEBUGFS_REG(HGC_SAS_TXFAIL_RETRY_CTRL), HISI_SAS_DEBUGFS_REG(HGC_GET_ITV_TIME), diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c index f0bc8bbb3938140fe18f32f212b02292779fefaf..198edf03f92977c9b5d149ecb4861abdc1441a3f 100644 --- a/drivers/scsi/hosts.c +++ b/drivers/scsi/hosts.c @@ -441,6 +441,7 @@ struct Scsi_Host *scsi_host_alloc(const struct scsi_host_template *sht, int priv shost->cmd_per_lun = sht->cmd_per_lun; shost->no_write_same = sht->no_write_same; shost->host_tagset = sht->host_tagset; + shost->queuecommand_may_block = sht->queuecommand_may_block; if (shost_eh_deadline == -1 || !sht->eh_host_reset_handler) shost->eh_deadline = -1; diff --git a/drivers/scsi/hptiop.c b/drivers/scsi/hptiop.c index 06ccb51bf6a926d574f02af3c3f33490aa19bca0..f5334ccbf2cac3f1eec7cfa9b3db1ba995d4968a 100644 --- a/drivers/scsi/hptiop.c +++ b/drivers/scsi/hptiop.c @@ -1394,8 +1394,8 @@ static int hptiop_probe(struct pci_dev *pcidev, const struct pci_device_id *id) host->cmd_per_lun = le32_to_cpu(iop_config.max_requests); host->max_cmd_len = 16; - req_size = struct_size((struct hpt_iop_request_scsi_command *)0, - sg_list, hba->max_sg_descriptors); + req_size = struct_size_t(struct hpt_iop_request_scsi_command, + sg_list, hba->max_sg_descriptors); if ((req_size & 0x1f) != 0) req_size = (req_size + 0x1f) & ~0x1f; diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c index 63f32f843e753e8d660462a1c74ea762c7f6c5a5..59599299615d4ccf951d7fea93b91f169d70010c 100644 --- a/drivers/scsi/ibmvscsi/ibmvscsi.c +++ b/drivers/scsi/ibmvscsi/ibmvscsi.c @@ -250,7 +250,7 @@ static void gather_partition_info(void) ppartition_name = of_get_property(of_root, "ibm,partition-name", NULL); if (ppartition_name) - strlcpy(partition_name, ppartition_name, + strscpy(partition_name, ppartition_name, sizeof(partition_name)); p_number_ptr = of_get_property(of_root, "ibm,partition-no", NULL); if (p_number_ptr) @@ -1282,12 +1282,12 @@ static void send_mad_capabilities(struct ibmvscsi_host_data *hostdata) if (hostdata->client_migrated) hostdata->caps.flags |= cpu_to_be32(CLIENT_MIGRATED); - strlcpy(hostdata->caps.name, dev_name(&hostdata->host->shost_gendev), + strscpy(hostdata->caps.name, dev_name(&hostdata->host->shost_gendev), sizeof(hostdata->caps.name)); location = of_get_property(of_node, "ibm,loc-code", NULL); location = location ? location : dev_name(hostdata->dev); - strlcpy(hostdata->caps.loc, location, sizeof(hostdata->caps.loc)); + strscpy(hostdata->caps.loc, location, sizeof(hostdata->caps.loc)); req->common.type = cpu_to_be32(VIOSRP_CAPABILITIES_TYPE); req->buffer = cpu_to_be64(hostdata->caps_addr); diff --git a/drivers/scsi/isci/scu_task_context.h b/drivers/scsi/isci/scu_task_context.h index 869a979eb5b2ea92ca5da13137b769929fa0d2ad..582d22d54689d3a80c1145fb76ee7438c80df00e 100644 --- a/drivers/scsi/isci/scu_task_context.h +++ b/drivers/scsi/isci/scu_task_context.h @@ -845,7 +845,7 @@ struct scu_task_context { /** * This field is used by the SCU TL to determine when to take a snapshot when - * tranmitting read data frames. + * transmitting read data frames. * - 0x00 The entire IO * - 0x01 32k * - 0x02 64k diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index 9637d4bc2bc96340d6ebf6b39c1f857ef02980ea..9ab8555180a3a0bd159b621a57c99bcb8f0413ae 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c @@ -301,35 +301,32 @@ static int iscsi_sw_tcp_xmit_segment(struct iscsi_tcp_conn *tcp_conn, while (!iscsi_tcp_segment_done(tcp_conn, segment, 0, r)) { struct scatterlist *sg; + struct msghdr msg = {}; + struct bio_vec bv; unsigned int offset, copy; - int flags = 0; r = 0; offset = segment->copied; copy = segment->size - offset; if (segment->total_copied + segment->size < segment->total_size) - flags |= MSG_MORE | MSG_SENDPAGE_NOTLAST; + msg.msg_flags |= MSG_MORE; if (tcp_sw_conn->queue_recv) - flags |= MSG_DONTWAIT; + msg.msg_flags |= MSG_DONTWAIT; - /* Use sendpage if we can; else fall back to sendmsg */ if (!segment->data) { + if (!tcp_conn->iscsi_conn->datadgst_en) + msg.msg_flags |= MSG_SPLICE_PAGES; sg = segment->sg; offset += segment->sg_offset + sg->offset; - r = tcp_sw_conn->sendpage(sk, sg_page(sg), offset, - copy, flags); + bvec_set_page(&bv, sg_page(sg), copy, offset); } else { - struct msghdr msg = { .msg_flags = flags }; - struct kvec iov = { - .iov_base = segment->data + offset, - .iov_len = copy - }; - - r = kernel_sendmsg(sk, &msg, &iov, 1, copy); + bvec_set_virt(&bv, segment->data + offset, copy); } + iov_iter_bvec(&msg.msg_iter, ITER_SOURCE, &bv, 1, copy); + r = sock_sendmsg(sk, &msg); if (r < 0) { iscsi_tcp_segment_unmap(segment); return r; @@ -746,7 +743,6 @@ iscsi_sw_tcp_conn_bind(struct iscsi_cls_session *cls_session, sock_no_linger(sk); iscsi_sw_tcp_conn_set_callbacks(conn); - tcp_sw_conn->sendpage = tcp_sw_conn->sock->ops->sendpage; /* * set receive state machine into initial state */ @@ -777,8 +773,6 @@ static int iscsi_sw_tcp_conn_set_param(struct iscsi_cls_conn *cls_conn, return -ENOTCONN; } iscsi_set_param(cls_conn, param, buf, buflen); - tcp_sw_conn->sendpage = conn->datadgst_en ? - sock_no_sendpage : tcp_sw_conn->sock->ops->sendpage; mutex_unlock(&tcp_sw_conn->sock_lock); break; case ISCSI_PARAM_MAX_R2T: diff --git a/drivers/scsi/iscsi_tcp.h b/drivers/scsi/iscsi_tcp.h index 68e14a344904f955960b194497db8f5c12883b12..89a6fc552f0b9a9a3412e08d6e5ee5ca61fe811a 100644 --- a/drivers/scsi/iscsi_tcp.h +++ b/drivers/scsi/iscsi_tcp.h @@ -47,8 +47,6 @@ struct iscsi_sw_tcp_conn { /* MIB custom statistics */ uint32_t sendpage_failures_cnt; uint32_t discontiguous_hdr_cnt; - - ssize_t (*sendpage)(struct socket *, struct page *, int, size_t, int); }; struct iscsi_sw_tcp_host { diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c index dc670304f181fc741ff8a787e9afa3a64ea6cd88..adcac57aaee6446750d645f6b6b09412fb3c0ddb 100644 --- a/drivers/scsi/libsas/sas_expander.c +++ b/drivers/scsi/libsas/sas_expander.c @@ -1198,37 +1198,37 @@ static void sas_print_parent_topology_bug(struct domain_device *child, sas_route_char(child, child_phy)); } +static bool sas_eeds_valid(struct domain_device *parent, + struct domain_device *child) +{ + struct sas_discovery *disc = &parent->port->disc; + + return (SAS_ADDR(disc->eeds_a) == SAS_ADDR(parent->sas_addr) || + SAS_ADDR(disc->eeds_a) == SAS_ADDR(child->sas_addr)) && + (SAS_ADDR(disc->eeds_b) == SAS_ADDR(parent->sas_addr) || + SAS_ADDR(disc->eeds_b) == SAS_ADDR(child->sas_addr)); +} + static int sas_check_eeds(struct domain_device *child, - struct ex_phy *parent_phy, - struct ex_phy *child_phy) + struct ex_phy *parent_phy, + struct ex_phy *child_phy) { int res = 0; struct domain_device *parent = child->parent; + struct sas_discovery *disc = &parent->port->disc; - if (SAS_ADDR(parent->port->disc.fanout_sas_addr) != 0) { + if (SAS_ADDR(disc->fanout_sas_addr) != 0) { res = -ENODEV; pr_warn("edge ex %016llx phy S:%02d <--> edge ex %016llx phy S:%02d, while there is a fanout ex %016llx\n", SAS_ADDR(parent->sas_addr), parent_phy->phy_id, SAS_ADDR(child->sas_addr), child_phy->phy_id, - SAS_ADDR(parent->port->disc.fanout_sas_addr)); - } else if (SAS_ADDR(parent->port->disc.eeds_a) == 0) { - memcpy(parent->port->disc.eeds_a, parent->sas_addr, - SAS_ADDR_SIZE); - memcpy(parent->port->disc.eeds_b, child->sas_addr, - SAS_ADDR_SIZE); - } else if (((SAS_ADDR(parent->port->disc.eeds_a) == - SAS_ADDR(parent->sas_addr)) || - (SAS_ADDR(parent->port->disc.eeds_a) == - SAS_ADDR(child->sas_addr))) - && - ((SAS_ADDR(parent->port->disc.eeds_b) == - SAS_ADDR(parent->sas_addr)) || - (SAS_ADDR(parent->port->disc.eeds_b) == - SAS_ADDR(child->sas_addr)))) - ; - else { + SAS_ADDR(disc->fanout_sas_addr)); + } else if (SAS_ADDR(disc->eeds_a) == 0) { + memcpy(disc->eeds_a, parent->sas_addr, SAS_ADDR_SIZE); + memcpy(disc->eeds_b, child->sas_addr, SAS_ADDR_SIZE); + } else if (!sas_eeds_valid(parent, child)) { res = -ENODEV; pr_warn("edge ex %016llx phy%02d <--> edge ex %016llx phy%02d link forms a third EEDS!\n", SAS_ADDR(parent->sas_addr), @@ -1240,11 +1240,56 @@ static int sas_check_eeds(struct domain_device *child, return res; } -/* Here we spill over 80 columns. It is intentional. - */ -static int sas_check_parent_topology(struct domain_device *child) +static int sas_check_edge_expander_topo(struct domain_device *child, + struct ex_phy *parent_phy) +{ + struct expander_device *child_ex = &child->ex_dev; + struct expander_device *parent_ex = &child->parent->ex_dev; + struct ex_phy *child_phy; + + child_phy = &child_ex->ex_phy[parent_phy->attached_phy_id]; + + if (child->dev_type == SAS_FANOUT_EXPANDER_DEVICE) { + if (parent_phy->routing_attr != SUBTRACTIVE_ROUTING || + child_phy->routing_attr != TABLE_ROUTING) + goto error; + } else if (parent_phy->routing_attr == SUBTRACTIVE_ROUTING) { + if (child_phy->routing_attr == SUBTRACTIVE_ROUTING) + return sas_check_eeds(child, parent_phy, child_phy); + else if (child_phy->routing_attr != TABLE_ROUTING) + goto error; + } else if (parent_phy->routing_attr == TABLE_ROUTING) { + if (child_phy->routing_attr != SUBTRACTIVE_ROUTING && + (child_phy->routing_attr != TABLE_ROUTING || + !child_ex->t2t_supp || !parent_ex->t2t_supp)) + goto error; + } + + return 0; +error: + sas_print_parent_topology_bug(child, parent_phy, child_phy); + return -ENODEV; +} + +static int sas_check_fanout_expander_topo(struct domain_device *child, + struct ex_phy *parent_phy) { struct expander_device *child_ex = &child->ex_dev; + struct ex_phy *child_phy; + + child_phy = &child_ex->ex_phy[parent_phy->attached_phy_id]; + + if (parent_phy->routing_attr == TABLE_ROUTING && + child_phy->routing_attr == SUBTRACTIVE_ROUTING) + return 0; + + sas_print_parent_topology_bug(child, parent_phy, child_phy); + + return -ENODEV; +} + +static int sas_check_parent_topology(struct domain_device *child) +{ struct expander_device *parent_ex; int i; int res = 0; @@ -1259,7 +1304,6 @@ static int sas_check_parent_topology(struct domain_device *child) for (i = 0; i < parent_ex->num_phys; i++) { struct ex_phy *parent_phy = &parent_ex->ex_phy[i]; - struct ex_phy *child_phy; if (parent_phy->phy_state == PHY_VACANT || parent_phy->phy_state == PHY_NOT_PRESENT) @@ -1268,40 +1312,14 @@ static int sas_check_parent_topology(struct domain_device *child) if (!sas_phy_match_dev_addr(child, parent_phy)) continue; - child_phy = &child_ex->ex_phy[parent_phy->attached_phy_id]; - switch (child->parent->dev_type) { case SAS_EDGE_EXPANDER_DEVICE: - if (child->dev_type == SAS_FANOUT_EXPANDER_DEVICE) { - if (parent_phy->routing_attr != SUBTRACTIVE_ROUTING || - child_phy->routing_attr != TABLE_ROUTING) { - sas_print_parent_topology_bug(child, parent_phy, child_phy); - res = -ENODEV; - } - } else if (parent_phy->routing_attr == SUBTRACTIVE_ROUTING) { - if (child_phy->routing_attr == SUBTRACTIVE_ROUTING) { - res = sas_check_eeds(child, parent_phy, child_phy); - } else if (child_phy->routing_attr != TABLE_ROUTING) { - sas_print_parent_topology_bug(child, parent_phy, child_phy); - res = -ENODEV; - } - } else if (parent_phy->routing_attr == TABLE_ROUTING) { - if (child_phy->routing_attr == SUBTRACTIVE_ROUTING || - (child_phy->routing_attr == TABLE_ROUTING && - child_ex->t2t_supp && parent_ex->t2t_supp)) { - /* All good */; - } else { - sas_print_parent_topology_bug(child, parent_phy, child_phy); - res = -ENODEV; - } - } + if (sas_check_edge_expander_topo(child, parent_phy)) + res = -ENODEV; break; case SAS_FANOUT_EXPANDER_DEVICE: - if (parent_phy->routing_attr != TABLE_ROUTING || - child_phy->routing_attr != SUBTRACTIVE_ROUTING) { - sas_print_parent_topology_bug(child, parent_phy, child_phy); + if (sas_check_fanout_expander_topo(child, parent_phy)) res = -ENODEV; - } break; default: break; diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c index a36fa1c128a8412cee130250ac4cf1f456913641..94c5f14f3c16dbaaf54804120bdb34a0da958f7e 100644 --- a/drivers/scsi/libsas/sas_scsi_host.c +++ b/drivers/scsi/libsas/sas_scsi_host.c @@ -872,8 +872,7 @@ int sas_change_queue_depth(struct scsi_device *sdev, int depth) struct domain_device *dev = sdev_to_domain_dev(sdev); if (dev_is_sata(dev)) - return ata_change_queue_depth(dev->sata_dev.ap, - sas_to_ata_dev(dev), sdev, depth); + return ata_change_queue_depth(dev->sata_dev.ap, sdev, depth); if (!sdev->tagged_supported) depth = 1; diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index 5e3a93d13a91d0f66619d224429230e2587768cc..9a89636843693f2d83d8096070333dde4ce0d4c3 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h @@ -429,6 +429,15 @@ struct lpfc_cgn_param { /* Max number of days of congestion data */ #define LPFC_MAX_CGN_DAYS 10 +struct lpfc_cgn_ts { + uint8_t month; + uint8_t day; + uint8_t year; + uint8_t hour; + uint8_t minute; + uint8_t second; +}; + /* Format of congestion buffer info * This structure defines memory thats allocated and registered with * the HBA firmware. When adding or removing fields from this structure @@ -442,6 +451,7 @@ struct lpfc_cgn_info { #define LPFC_CGN_INFO_V1 1 #define LPFC_CGN_INFO_V2 2 #define LPFC_CGN_INFO_V3 3 +#define LPFC_CGN_INFO_V4 4 uint8_t cgn_info_mode; /* 0=off 1=managed 2=monitor only */ uint8_t cgn_info_detect; uint8_t cgn_info_action; @@ -450,12 +460,7 @@ struct lpfc_cgn_info { uint8_t cgn_info_level2; /* Start Time */ - uint8_t cgn_info_month; - uint8_t cgn_info_day; - uint8_t cgn_info_year; - uint8_t cgn_info_hour; - uint8_t cgn_info_minute; - uint8_t cgn_info_second; + struct lpfc_cgn_ts base_time; /* minute / hours / daily indices */ uint8_t cgn_index_minute; @@ -496,45 +501,17 @@ struct lpfc_cgn_info { uint8_t cgn_stat_npm; /* Notifications per minute */ /* Start Time */ - uint8_t cgn_stat_month; - uint8_t cgn_stat_day; - uint8_t cgn_stat_year; - uint8_t cgn_stat_hour; - uint8_t cgn_stat_minute; - uint8_t cgn_pad2[2]; + struct lpfc_cgn_ts stat_start; /* Base time */ + uint8_t cgn_pad2; __le32 cgn_notification; __le32 cgn_peer_notification; __le32 link_integ_notification; __le32 delivery_notification; - - uint8_t cgn_stat_cgn_month; /* Last congestion notification FPIN */ - uint8_t cgn_stat_cgn_day; - uint8_t cgn_stat_cgn_year; - uint8_t cgn_stat_cgn_hour; - uint8_t cgn_stat_cgn_min; - uint8_t cgn_stat_cgn_sec; - - uint8_t cgn_stat_peer_month; /* Last peer congestion FPIN */ - uint8_t cgn_stat_peer_day; - uint8_t cgn_stat_peer_year; - uint8_t cgn_stat_peer_hour; - uint8_t cgn_stat_peer_min; - uint8_t cgn_stat_peer_sec; - - uint8_t cgn_stat_lnk_month; /* Last link integrity FPIN */ - uint8_t cgn_stat_lnk_day; - uint8_t cgn_stat_lnk_year; - uint8_t cgn_stat_lnk_hour; - uint8_t cgn_stat_lnk_min; - uint8_t cgn_stat_lnk_sec; - - uint8_t cgn_stat_del_month; /* Last delivery notification FPIN */ - uint8_t cgn_stat_del_day; - uint8_t cgn_stat_del_year; - uint8_t cgn_stat_del_hour; - uint8_t cgn_stat_del_min; - uint8_t cgn_stat_del_sec; + struct lpfc_cgn_ts stat_fpin; /* Last congestion notification FPIN */ + struct lpfc_cgn_ts stat_peer; /* Last peer congestion FPIN */ + struct lpfc_cgn_ts stat_lnk; /* Last link integrity FPIN */ + struct lpfc_cgn_ts stat_delivery; /* Last delivery notification FPIN */ ); __le32 cgn_info_crc; @@ -932,8 +909,6 @@ struct lpfc_hba { void (*__lpfc_sli_release_iocbq)(struct lpfc_hba *, struct lpfc_iocbq *); int (*lpfc_hba_down_post)(struct lpfc_hba *phba); - void (*lpfc_scsi_cmd_iocb_cmpl) - (struct lpfc_hba *, struct lpfc_iocbq *, struct lpfc_iocbq *); /* MBOX interface function jump table entries */ int (*lpfc_sli_issue_mbox) @@ -1045,8 +1020,6 @@ struct lpfc_hba { * capability */ #define HBA_FLOGI_ISSUED 0x100000 /* FLOGI was issued */ -#define HBA_SHORT_CMF 0x200000 /* shorter CMF timer routine */ -#define HBA_CGN_DAY_WRAP 0x400000 /* HBA Congestion info day wraps */ #define HBA_DEFER_FLOGI 0x800000 /* Defer FLOGI till read_sparm cmpl */ #define HBA_SETUP 0x1000000 /* Signifies HBA setup is completed */ #define HBA_NEEDS_CFG_PORT 0x2000000 /* SLI3 - needs a CONFIG_PORT mbox */ @@ -1529,6 +1502,7 @@ struct lpfc_hba { uint64_t cmf_last_sync_bw; #define LPFC_CMF_BLK_SIZE 512 struct hrtimer cmf_timer; + struct hrtimer cmf_stats_timer; /* 1 minute stats timer */ atomic_t cmf_bw_wait; atomic_t cmf_busy; atomic_t cmf_stop_io; /* To block request and stop IO's */ @@ -1576,12 +1550,11 @@ struct lpfc_hba { atomic_t cgn_sync_alarm_cnt; /* Total alarm events for SYNC wqe */ atomic_t cgn_driver_evt_cnt; /* Total driver cgn events for fmw */ atomic_t cgn_latency_evt_cnt; - struct timespec64 cgn_daily_ts; atomic64_t cgn_latency_evt; /* Avg latency per minute */ unsigned long cgn_evt_timestamp; #define LPFC_CGN_TIMER_TO_MIN 60000 /* ms in a minute */ uint32_t cgn_evt_minute; -#define LPFC_SEC_MIN 60 +#define LPFC_SEC_MIN 60UL #define LPFC_MIN_HOUR 60 #define LPFC_HOUR_DAY 24 #define LPFC_MIN_DAY (LPFC_MIN_HOUR * LPFC_HOUR_DAY) diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index 3863a5341782a519d99dc733d0cc0f678d2c3f7d..21c7ecd3ede55d9a489cd60ce944f29abf9ec541 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -5858,8 +5858,8 @@ int lpfc_fabric_cgn_frequency = 100; /* 100 ms default */ module_param(lpfc_fabric_cgn_frequency, int, 0444); MODULE_PARM_DESC(lpfc_fabric_cgn_frequency, "Congestion signaling fabric freq"); -int lpfc_acqe_cgn_frequency = 10; /* 10 sec default */ -module_param(lpfc_acqe_cgn_frequency, int, 0444); +unsigned char lpfc_acqe_cgn_frequency = 10; /* 10 sec default */ +module_param(lpfc_acqe_cgn_frequency, byte, 0444); MODULE_PARM_DESC(lpfc_acqe_cgn_frequency, "Congestion signaling ACQE freq"); int lpfc_use_cgn_signal = 1; /* 0 - only use FPINs, 1 - Use signals if avail */ diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h index b833b983e69d8c53e929943864051aafb42df490..d4e46a08f94daa4edf6ded66588b178a7e7f5744 100644 --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h @@ -134,7 +134,6 @@ void lpfc_check_nlp_post_devloss(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp); void lpfc_ignore_els_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, struct lpfc_iocbq *rspiocb); -int lpfc_nlp_not_used(struct lpfc_nodelist *ndlp); struct lpfc_nodelist *lpfc_setup_disc_node(struct lpfc_vport *, uint32_t); void lpfc_disc_list_loopmap(struct lpfc_vport *); void lpfc_disc_start(struct lpfc_vport *); @@ -248,6 +247,7 @@ irqreturn_t lpfc_sli_sp_intr_handler(int, void *); irqreturn_t lpfc_sli_fp_intr_handler(int, void *); irqreturn_t lpfc_sli4_intr_handler(int, void *); irqreturn_t lpfc_sli4_hba_intr_handler(int, void *); +irqreturn_t lpfc_sli4_hba_intr_handler_th(int irq, void *dev_id); int lpfc_read_object(struct lpfc_hba *phba, char *s, uint32_t *datap, uint32_t len); @@ -664,7 +664,7 @@ extern int lpfc_enable_nvmet_cnt; extern unsigned long long lpfc_enable_nvmet[]; extern int lpfc_no_hba_reset_cnt; extern unsigned long lpfc_no_hba_reset[]; -extern int lpfc_acqe_cgn_frequency; +extern unsigned char lpfc_acqe_cgn_frequency; extern int lpfc_fabric_cgn_frequency; extern int lpfc_use_cgn_signal; diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c index f3bdcebe67f590e783fb4baacdb73649c3a6f8fa..474834f313a7b5413a89d895bf94289da33218ef 100644 --- a/drivers/scsi/lpfc/lpfc_ct.c +++ b/drivers/scsi/lpfc/lpfc_ct.c @@ -287,7 +287,7 @@ lpfc_ct_handle_mibreq(struct lpfc_hba *phba, struct lpfc_iocbq *ctiocbq) u32 ulp_status = get_job_ulpstatus(phba, ctiocbq); u32 ulp_word4 = get_job_word4(phba, ctiocbq); u32 did; - u32 mi_cmd; + u16 mi_cmd; did = bf_get(els_rsp64_sid, &ctiocbq->wqe.xmit_els_rsp); if (ulp_status) { @@ -311,7 +311,7 @@ lpfc_ct_handle_mibreq(struct lpfc_hba *phba, struct lpfc_iocbq *ctiocbq) ct_req = (struct lpfc_sli_ct_request *)ctiocbq->cmd_dmabuf->virt; - mi_cmd = ct_req->CommandResponse.bits.CmdRsp; + mi_cmd = be16_to_cpu(ct_req->CommandResponse.bits.CmdRsp); lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, "6442 : MI Cmd : x%x Not Supported\n", mi_cmd); lpfc_ct_reject_event(ndlp, ct_req, @@ -486,7 +486,7 @@ lpfc_free_ct_rsp(struct lpfc_hba *phba, struct lpfc_dmabuf *mlist) } static struct lpfc_dmabuf * -lpfc_alloc_ct_rsp(struct lpfc_hba *phba, int cmdcode, struct ulp_bde64 *bpl, +lpfc_alloc_ct_rsp(struct lpfc_hba *phba, __be16 cmdcode, struct ulp_bde64 *bpl, uint32_t size, int *entries) { struct lpfc_dmabuf *mlist = NULL; @@ -507,8 +507,8 @@ lpfc_alloc_ct_rsp(struct lpfc_hba *phba, int cmdcode, struct ulp_bde64 *bpl, INIT_LIST_HEAD(&mp->list); - if (cmdcode == be16_to_cpu(SLI_CTNS_GID_FT) || - cmdcode == be16_to_cpu(SLI_CTNS_GFF_ID)) + if (be16_to_cpu(cmdcode) == SLI_CTNS_GID_FT || + be16_to_cpu(cmdcode) == SLI_CTNS_GFF_ID) mp->virt = lpfc_mbuf_alloc(phba, MEM_PRI, &(mp->phys)); else mp->virt = lpfc_mbuf_alloc(phba, 0, &(mp->phys)); @@ -671,7 +671,7 @@ lpfc_ct_cmd(struct lpfc_vport *vport, struct lpfc_dmabuf *inmp, struct ulp_bde64 *bpl = (struct ulp_bde64 *) bmp->virt; struct lpfc_dmabuf *outmp; int cnt = 0, status; - int cmdcode = ((struct lpfc_sli_ct_request *) inmp->virt)-> + __be16 cmdcode = ((struct lpfc_sli_ct_request *)inmp->virt)-> CommandResponse.bits.CmdRsp; bpl++; /* Skip past ct request */ @@ -1043,8 +1043,8 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, outp, CTreq->un.gid.Fc4Type, get_job_data_placed(phba, rspiocb)); - } else if (CTrsp->CommandResponse.bits.CmdRsp == - be16_to_cpu(SLI_CT_RESPONSE_FS_RJT)) { + } else if (be16_to_cpu(CTrsp->CommandResponse.bits.CmdRsp) == + SLI_CT_RESPONSE_FS_RJT) { /* NameServer Rsp Error */ if ((CTrsp->ReasonCode == SLI_CT_UNABLE_TO_PERFORM_REQ) && (CTrsp->Explanation == SLI_CT_NO_FC4_TYPES)) { @@ -1052,14 +1052,14 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, LOG_DISCOVERY, "0269 No NameServer Entries " "Data: x%x x%x x%x x%x\n", - CTrsp->CommandResponse.bits.CmdRsp, + be16_to_cpu(CTrsp->CommandResponse.bits.CmdRsp), (uint32_t) CTrsp->ReasonCode, (uint32_t) CTrsp->Explanation, vport->fc_flag); lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT, "GID_FT no entry cmd:x%x rsn:x%x exp:x%x", - (uint32_t)CTrsp->CommandResponse.bits.CmdRsp, + be16_to_cpu(CTrsp->CommandResponse.bits.CmdRsp), (uint32_t) CTrsp->ReasonCode, (uint32_t) CTrsp->Explanation); } else { @@ -1067,14 +1067,14 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, LOG_DISCOVERY, "0240 NameServer Rsp Error " "Data: x%x x%x x%x x%x\n", - CTrsp->CommandResponse.bits.CmdRsp, + be16_to_cpu(CTrsp->CommandResponse.bits.CmdRsp), (uint32_t) CTrsp->ReasonCode, (uint32_t) CTrsp->Explanation, vport->fc_flag); lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT, "GID_FT rsp err1 cmd:x%x rsn:x%x exp:x%x", - (uint32_t)CTrsp->CommandResponse.bits.CmdRsp, + be16_to_cpu(CTrsp->CommandResponse.bits.CmdRsp), (uint32_t) CTrsp->ReasonCode, (uint32_t) CTrsp->Explanation); } @@ -1085,14 +1085,14 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "0241 NameServer Rsp Error " "Data: x%x x%x x%x x%x\n", - CTrsp->CommandResponse.bits.CmdRsp, + be16_to_cpu(CTrsp->CommandResponse.bits.CmdRsp), (uint32_t) CTrsp->ReasonCode, (uint32_t) CTrsp->Explanation, vport->fc_flag); lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT, "GID_FT rsp err2 cmd:x%x rsn:x%x exp:x%x", - (uint32_t)CTrsp->CommandResponse.bits.CmdRsp, + be16_to_cpu(CTrsp->CommandResponse.bits.CmdRsp), (uint32_t) CTrsp->ReasonCode, (uint32_t) CTrsp->Explanation); } @@ -1247,8 +1247,8 @@ lpfc_cmpl_ct_cmd_gid_pt(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, /* Good status, continue checking */ CTreq = (struct lpfc_sli_ct_request *)inp->virt; CTrsp = (struct lpfc_sli_ct_request *)outp->virt; - if (CTrsp->CommandResponse.bits.CmdRsp == - cpu_to_be16(SLI_CT_RESPONSE_FS_ACC)) { + if (be16_to_cpu(CTrsp->CommandResponse.bits.CmdRsp) == + SLI_CT_RESPONSE_FS_ACC) { lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, "4105 NameServer Rsp Data: x%x x%x " "x%x x%x sz x%x\n", @@ -1262,8 +1262,8 @@ lpfc_cmpl_ct_cmd_gid_pt(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, outp, CTreq->un.gid.Fc4Type, get_job_data_placed(phba, rspiocb)); - } else if (CTrsp->CommandResponse.bits.CmdRsp == - be16_to_cpu(SLI_CT_RESPONSE_FS_RJT)) { + } else if (be16_to_cpu(CTrsp->CommandResponse.bits.CmdRsp) == + SLI_CT_RESPONSE_FS_RJT) { /* NameServer Rsp Error */ if ((CTrsp->ReasonCode == SLI_CT_UNABLE_TO_PERFORM_REQ) && (CTrsp->Explanation == SLI_CT_NO_FC4_TYPES)) { @@ -1271,7 +1271,7 @@ lpfc_cmpl_ct_cmd_gid_pt(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, vport, KERN_INFO, LOG_DISCOVERY, "4106 No NameServer Entries " "Data: x%x x%x x%x x%x\n", - CTrsp->CommandResponse.bits.CmdRsp, + be16_to_cpu(CTrsp->CommandResponse.bits.CmdRsp), (uint32_t)CTrsp->ReasonCode, (uint32_t)CTrsp->Explanation, vport->fc_flag); @@ -1279,7 +1279,7 @@ lpfc_cmpl_ct_cmd_gid_pt(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, lpfc_debugfs_disc_trc( vport, LPFC_DISC_TRC_CT, "GID_PT no entry cmd:x%x rsn:x%x exp:x%x", - (uint32_t)CTrsp->CommandResponse.bits.CmdRsp, + be16_to_cpu(CTrsp->CommandResponse.bits.CmdRsp), (uint32_t)CTrsp->ReasonCode, (uint32_t)CTrsp->Explanation); } else { @@ -1287,7 +1287,7 @@ lpfc_cmpl_ct_cmd_gid_pt(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, vport, KERN_INFO, LOG_DISCOVERY, "4107 NameServer Rsp Error " "Data: x%x x%x x%x x%x\n", - CTrsp->CommandResponse.bits.CmdRsp, + be16_to_cpu(CTrsp->CommandResponse.bits.CmdRsp), (uint32_t)CTrsp->ReasonCode, (uint32_t)CTrsp->Explanation, vport->fc_flag); @@ -1295,7 +1295,7 @@ lpfc_cmpl_ct_cmd_gid_pt(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, lpfc_debugfs_disc_trc( vport, LPFC_DISC_TRC_CT, "GID_PT rsp err1 cmd:x%x rsn:x%x exp:x%x", - (uint32_t)CTrsp->CommandResponse.bits.CmdRsp, + be16_to_cpu(CTrsp->CommandResponse.bits.CmdRsp), (uint32_t)CTrsp->ReasonCode, (uint32_t)CTrsp->Explanation); } @@ -1304,7 +1304,7 @@ lpfc_cmpl_ct_cmd_gid_pt(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "4109 NameServer Rsp Error " "Data: x%x x%x x%x x%x\n", - CTrsp->CommandResponse.bits.CmdRsp, + be16_to_cpu(CTrsp->CommandResponse.bits.CmdRsp), (uint32_t)CTrsp->ReasonCode, (uint32_t)CTrsp->Explanation, vport->fc_flag); @@ -1312,7 +1312,7 @@ lpfc_cmpl_ct_cmd_gid_pt(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, lpfc_debugfs_disc_trc( vport, LPFC_DISC_TRC_CT, "GID_PT rsp err2 cmd:x%x rsn:x%x exp:x%x", - (uint32_t)CTrsp->CommandResponse.bits.CmdRsp, + be16_to_cpu(CTrsp->CommandResponse.bits.CmdRsp), (uint32_t)CTrsp->ReasonCode, (uint32_t)CTrsp->Explanation); } @@ -1391,8 +1391,8 @@ lpfc_cmpl_ct_cmd_gff_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, (fbits & FC4_FEATURE_INIT) ? "Initiator" : " ", (fbits & FC4_FEATURE_TARGET) ? "Target" : " "); - if (CTrsp->CommandResponse.bits.CmdRsp == - be16_to_cpu(SLI_CT_RESPONSE_FS_ACC)) { + if (be16_to_cpu(CTrsp->CommandResponse.bits.CmdRsp) == + SLI_CT_RESPONSE_FS_ACC) { if ((fbits & FC4_FEATURE_INIT) && !(fbits & FC4_FEATURE_TARGET)) { lpfc_printf_vlog(vport, KERN_INFO, @@ -1631,7 +1631,7 @@ lpfc_cmpl_ct(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, "0209 CT Request completes, latt %d, " "ulp_status x%x CmdRsp x%x, Context x%x, Tag x%x\n", latt, ulp_status, - CTrsp->CommandResponse.bits.CmdRsp, + be16_to_cpu(CTrsp->CommandResponse.bits.CmdRsp), get_job_ulpcontext(phba, cmdiocb), cmdiocb->iotag); lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT, @@ -1681,8 +1681,8 @@ lpfc_cmpl_ct_cmd_rft_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, outp = cmdiocb->rsp_dmabuf; CTrsp = (struct lpfc_sli_ct_request *)outp->virt; - if (CTrsp->CommandResponse.bits.CmdRsp == - be16_to_cpu(SLI_CT_RESPONSE_FS_ACC)) + if (be16_to_cpu(CTrsp->CommandResponse.bits.CmdRsp) == + SLI_CT_RESPONSE_FS_ACC) vport->ct_flags |= FC_CT_RFT_ID; } lpfc_cmpl_ct(phba, cmdiocb, rspiocb); @@ -1702,8 +1702,8 @@ lpfc_cmpl_ct_cmd_rnn_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, outp = cmdiocb->rsp_dmabuf; CTrsp = (struct lpfc_sli_ct_request *) outp->virt; - if (CTrsp->CommandResponse.bits.CmdRsp == - be16_to_cpu(SLI_CT_RESPONSE_FS_ACC)) + if (be16_to_cpu(CTrsp->CommandResponse.bits.CmdRsp) == + SLI_CT_RESPONSE_FS_ACC) vport->ct_flags |= FC_CT_RNN_ID; } lpfc_cmpl_ct(phba, cmdiocb, rspiocb); @@ -1723,8 +1723,8 @@ lpfc_cmpl_ct_cmd_rspn_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, outp = cmdiocb->rsp_dmabuf; CTrsp = (struct lpfc_sli_ct_request *)outp->virt; - if (CTrsp->CommandResponse.bits.CmdRsp == - be16_to_cpu(SLI_CT_RESPONSE_FS_ACC)) + if (be16_to_cpu(CTrsp->CommandResponse.bits.CmdRsp) == + SLI_CT_RESPONSE_FS_ACC) vport->ct_flags |= FC_CT_RSPN_ID; } lpfc_cmpl_ct(phba, cmdiocb, rspiocb); @@ -1744,8 +1744,8 @@ lpfc_cmpl_ct_cmd_rsnn_nn(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, outp = cmdiocb->rsp_dmabuf; CTrsp = (struct lpfc_sli_ct_request *) outp->virt; - if (CTrsp->CommandResponse.bits.CmdRsp == - be16_to_cpu(SLI_CT_RESPONSE_FS_ACC)) + if (be16_to_cpu(CTrsp->CommandResponse.bits.CmdRsp) == + SLI_CT_RESPONSE_FS_ACC) vport->ct_flags |= FC_CT_RSNN_NN; } lpfc_cmpl_ct(phba, cmdiocb, rspiocb); @@ -1777,8 +1777,8 @@ lpfc_cmpl_ct_cmd_rff_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, outp = cmdiocb->rsp_dmabuf; CTrsp = (struct lpfc_sli_ct_request *)outp->virt; - if (CTrsp->CommandResponse.bits.CmdRsp == - be16_to_cpu(SLI_CT_RESPONSE_FS_ACC)) + if (be16_to_cpu(CTrsp->CommandResponse.bits.CmdRsp) == + SLI_CT_RESPONSE_FS_ACC) vport->ct_flags |= FC_CT_RFF_ID; } lpfc_cmpl_ct(phba, cmdiocb, rspiocb); @@ -2217,8 +2217,8 @@ lpfc_cmpl_ct_disc_fdmi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, struct lpfc_dmabuf *outp = cmdiocb->rsp_dmabuf; struct lpfc_sli_ct_request *CTcmd = inp->virt; struct lpfc_sli_ct_request *CTrsp = outp->virt; - uint16_t fdmi_cmd = CTcmd->CommandResponse.bits.CmdRsp; - uint16_t fdmi_rsp = CTrsp->CommandResponse.bits.CmdRsp; + __be16 fdmi_cmd = CTcmd->CommandResponse.bits.CmdRsp; + __be16 fdmi_rsp = CTrsp->CommandResponse.bits.CmdRsp; struct lpfc_nodelist *ndlp, *free_ndlp = NULL; uint32_t latt, cmd, err; u32 ulp_status = get_job_ulpstatus(phba, rspiocb); @@ -2278,7 +2278,7 @@ lpfc_cmpl_ct_disc_fdmi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, /* Check for a CT LS_RJT response */ cmd = be16_to_cpu(fdmi_cmd); - if (fdmi_rsp == cpu_to_be16(SLI_CT_RESPONSE_FS_RJT)) { + if (be16_to_cpu(fdmi_rsp) == SLI_CT_RESPONSE_FS_RJT) { /* FDMI rsp failed */ lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY | LOG_ELS, "0220 FDMI cmd failed FS_RJT Data: x%x", cmd); @@ -3110,7 +3110,7 @@ lpfc_fdmi_vendor_attr_mi(struct lpfc_vport *vport, void *attr) } /* RHBA attribute jump table */ -int (*lpfc_fdmi_hba_action[]) +static int (*lpfc_fdmi_hba_action[]) (struct lpfc_vport *vport, void *attrbuf) = { /* Action routine Mask bit Attribute type */ lpfc_fdmi_hba_attr_wwnn, /* bit0 RHBA_NODENAME */ @@ -3134,7 +3134,7 @@ int (*lpfc_fdmi_hba_action[]) }; /* RPA / RPRT attribute jump table */ -int (*lpfc_fdmi_port_action[]) +static int (*lpfc_fdmi_port_action[]) (struct lpfc_vport *vport, void *attrbuf) = { /* Action routine Mask bit Attribute type */ lpfc_fdmi_port_attr_fc4type, /* bit0 RPRT_SUPPORT_FC4_TYPES */ @@ -3570,7 +3570,7 @@ lpfc_cmpl_ct_cmd_vmid(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, struct lpfc_dmabuf *outp = cmdiocb->rsp_dmabuf; struct lpfc_sli_ct_request *ctcmd = inp->virt; struct lpfc_sli_ct_request *ctrsp = outp->virt; - u16 rsp = ctrsp->CommandResponse.bits.CmdRsp; + __be16 rsp = ctrsp->CommandResponse.bits.CmdRsp; struct app_id_object *app; struct lpfc_nodelist *ndlp = cmdiocb->ndlp; u32 cmd, hash, bucket; @@ -3587,7 +3587,7 @@ lpfc_cmpl_ct_cmd_vmid(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, goto free_res; } /* Check for a CT LS_RJT response */ - if (rsp == be16_to_cpu(SLI_CT_RESPONSE_FS_RJT)) { + if (be16_to_cpu(rsp) == SLI_CT_RESPONSE_FS_RJT) { if (cmd != SLI_CTAS_DALLAPP_ID) lpfc_printf_vlog(vport, KERN_DEBUG, LOG_DISCOVERY, "3306 VMID FS_RJT Data: x%x x%x x%x\n", @@ -3748,7 +3748,7 @@ lpfc_vmid_cmd(struct lpfc_vport *vport, rap->obj[0].entity_id_len = vmid->vmid_len; memcpy(rap->obj[0].entity_id, vmid->host_vmid, vmid->vmid_len); size = RAPP_IDENT_OFFSET + - sizeof(struct lpfc_vmid_rapp_ident_list); + struct_size(rap, obj, be32_to_cpu(rap->no_of_objects)); retry = 1; break; @@ -3767,7 +3767,7 @@ lpfc_vmid_cmd(struct lpfc_vport *vport, dap->obj[0].entity_id_len = vmid->vmid_len; memcpy(dap->obj[0].entity_id, vmid->host_vmid, vmid->vmid_len); size = DAPP_IDENT_OFFSET + - sizeof(struct lpfc_vmid_dapp_ident_list); + struct_size(dap, obj, be32_to_cpu(dap->no_of_objects)); write_lock(&vport->vmid_lock); vmid->flag &= ~LPFC_VMID_REGISTERED; write_unlock(&vport->vmid_lock); diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c index bdf34af4ef36f1706dfe36597b7b1bac38d6da3d..7f9b221e7c34ae25e663ef30d98075f4f1e83446 100644 --- a/drivers/scsi/lpfc/lpfc_debugfs.c +++ b/drivers/scsi/lpfc/lpfc_debugfs.c @@ -2259,11 +2259,15 @@ lpfc_debugfs_ras_log_open(struct inode *inode, struct file *file) goto out; } spin_unlock_irq(&phba->hbalock); - debug = kmalloc(sizeof(*debug), GFP_KERNEL); + + if (check_mul_overflow(LPFC_RAS_MIN_BUFF_POST_SIZE, + phba->cfg_ras_fwlog_buffsize, &size)) + goto out; + + debug = kzalloc(sizeof(*debug), GFP_KERNEL); if (!debug) goto out; - size = LPFC_RAS_MIN_BUFF_POST_SIZE * phba->cfg_ras_fwlog_buffsize; debug->buffer = vmalloc(size); if (!debug->buffer) goto free_debug; diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 6a15f879e5173e5369eca9262ff55782cd73053e..2bad9954c355f66ce0c78b3447c42072a8b1f604 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -5205,14 +5205,9 @@ lpfc_els_free_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *elsiocb) * * This routine is the completion callback function to the Logout (LOGO) * Accept (ACC) Response ELS command. This routine is invoked to indicate - * the completion of the LOGO process. It invokes the lpfc_nlp_not_used() to - * release the ndlp if it has the last reference remaining (reference count - * is 1). If succeeded (meaning ndlp released), it sets the iocb ndlp - * field to NULL to inform the following lpfc_els_free_iocb() routine no - * ndlp reference count needs to be decremented. Otherwise, the ndlp - * reference use-count shall be decremented by the lpfc_els_free_iocb() - * routine. Finally, the lpfc_els_free_iocb() is invoked to release the - * IOCB data structure. + * the completion of the LOGO process. If the node has transitioned to NPR, + * this routine unregisters the RPI if it is still registered. The + * lpfc_els_free_iocb() is invoked to release the IOCB data structure. **/ static void lpfc_cmpl_els_logo_acc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, @@ -5253,19 +5248,9 @@ lpfc_cmpl_els_logo_acc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, (ndlp->nlp_last_elscmd == ELS_CMD_PLOGI)) goto out; - /* NPort Recovery mode or node is just allocated */ - if (!lpfc_nlp_not_used(ndlp)) { - /* A LOGO is completing and the node is in NPR state. - * Just unregister the RPI because the node is still - * required. - */ + if (ndlp->nlp_flag & NLP_RPI_REGISTERED) lpfc_unreg_rpi(vport, ndlp); - } else { - /* Indicate the node has already released, should - * not reference to it from within lpfc_els_free_iocb. - */ - cmdiocb->ndlp = NULL; - } + } out: /* @@ -5285,9 +5270,8 @@ lpfc_cmpl_els_logo_acc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, * RPI (Remote Port Index) mailbox command to the @phba. It simply releases * the associated lpfc Direct Memory Access (DMA) buffer back to the pool and * decrements the ndlp reference count held for this completion callback - * function. After that, it invokes the lpfc_nlp_not_used() to check - * whether there is only one reference left on the ndlp. If so, it will - * perform one more decrement and trigger the release of the ndlp. + * function. After that, it invokes the lpfc_drop_node to check + * whether it is appropriate to release the node. **/ void lpfc_mbx_cmpl_dflt_rpi(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) @@ -5468,9 +5452,19 @@ lpfc_cmpl_els_rsp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, ndlp->nlp_flag &= ~NLP_RELEASE_RPI; spin_unlock_irq(&ndlp->lock); } + lpfc_drop_node(vport, ndlp); + } else if (ndlp->nlp_state != NLP_STE_PLOGI_ISSUE && + ndlp->nlp_state != NLP_STE_REG_LOGIN_ISSUE && + ndlp->nlp_state != NLP_STE_PRLI_ISSUE) { + /* Drop ndlp if there is no planned or outstanding + * issued PRLI. + * + * In cases when the ndlp is acting as both an initiator + * and target function, let our issued PRLI determine + * the final ndlp kref drop. + */ + lpfc_drop_node(vport, ndlp); } - - lpfc_drop_node(vport, ndlp); } /* Release the originating I/O reference. */ diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 5ba3a9ad95016cd52961ff6a94f4e27308b5a00b..fdd7f69d87efebb51ce54b579ac5670fbf6c9bb7 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -458,11 +458,9 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp) if (ndlp->nlp_type & NLP_FABRIC) { spin_lock_irqsave(&ndlp->lock, iflags); - /* In massive vport configuration settings or when the FLOGI - * completes with a sequence timeout, it's possible - * dev_loss_tmo fired during node recovery. The driver has to - * account for this race to allow for recovery and keep - * the reference counting correct. + /* The driver has to account for a race between any fabric + * node that's in recovery when dev_loss_tmo expires. When this + * happens, the driver has to allow node recovery. */ switch (ndlp->nlp_DID) { case Fabric_DID: @@ -489,6 +487,17 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp) ndlp->nlp_state <= NLP_STE_REG_LOGIN_ISSUE) recovering = true; break; + default: + /* Ensure the nlp_DID at least has the correct prefix. + * The fabric domain controller's last three nibbles + * vary so we handle it in the default case. + */ + if (ndlp->nlp_DID & Fabric_DID_MASK) { + if (ndlp->nlp_state >= NLP_STE_PLOGI_ISSUE && + ndlp->nlp_state <= NLP_STE_REG_LOGIN_ISSUE) + recovering = true; + } + break; } spin_unlock_irqrestore(&ndlp->lock, iflags); @@ -556,6 +565,9 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp) ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi); } + spin_lock_irqsave(&ndlp->lock, iflags); + ndlp->nlp_flag &= ~NLP_IN_DEV_LOSS; + spin_unlock_irqrestore(&ndlp->lock, iflags); /* If we are devloss, but we are in the process of rediscovering the * ndlp, don't issue a NLP_EVT_DEVICE_RM event. @@ -565,9 +577,6 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp) return fcf_inuse; } - spin_lock_irqsave(&ndlp->lock, iflags); - ndlp->nlp_flag &= ~NLP_IN_DEV_LOSS; - spin_unlock_irqrestore(&ndlp->lock, iflags); if (!(ndlp->fc4_xpt_flags & NVME_XPT_REGD)) lpfc_disc_state_machine(vport, ndlp, NULL, NLP_EVT_DEVICE_RM); @@ -4333,13 +4342,14 @@ lpfc_mbx_cmpl_ns_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) /* If the node is not registered with the scsi or nvme * transport, remove the fabric node. The failed reg_login - * is terminal. + * is terminal and forces the removal of the last node + * reference. */ if (!(ndlp->fc4_xpt_flags & (SCSI_XPT_REGD | NVME_XPT_REGD))) { spin_lock_irq(&ndlp->lock); ndlp->nlp_flag &= ~NLP_NPR_2B_DISC; spin_unlock_irq(&ndlp->lock); - lpfc_nlp_not_used(ndlp); + lpfc_nlp_put(ndlp); } if (phba->fc_topology == LPFC_TOPOLOGY_LOOP) { @@ -4497,14 +4507,6 @@ lpfc_register_remote_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) if (vport->load_flag & FC_UNLOADING) return; - /* - * Disassociate any older association between this ndlp and rport - */ - if (ndlp->rport) { - rdata = ndlp->rport->dd_data; - rdata->pnode = NULL; - } - ndlp->rport = rport = fc_remote_port_add(shost, 0, &rport_ids); if (!rport) { dev_printk(KERN_WARNING, &phba->pcidev->dev, @@ -4835,7 +4837,7 @@ lpfc_nlp_state_name(char *buffer, size_t size, int state) }; if (state < NLP_STE_MAX_STATE && states[state]) - strlcpy(buffer, states[state], size); + strscpy(buffer, states[state], size); else snprintf(buffer, size, "unknown (%d)", state); return buffer; @@ -6704,25 +6706,6 @@ lpfc_nlp_put(struct lpfc_nodelist *ndlp) return ndlp ? kref_put(&ndlp->kref, lpfc_nlp_release) : 0; } -/* This routine free's the specified nodelist if it is not in use - * by any other discovery thread. This routine returns 1 if the - * ndlp has been freed. A return value of 0 indicates the ndlp is - * not yet been released. - */ -int -lpfc_nlp_not_used(struct lpfc_nodelist *ndlp) -{ - lpfc_debugfs_disc_trc(ndlp->vport, LPFC_DISC_TRC_NODE, - "node not used: did:x%x flg:x%x refcnt:x%x", - ndlp->nlp_DID, ndlp->nlp_flag, - kref_read(&ndlp->kref)); - - if (kref_read(&ndlp->kref) == 1) - if (lpfc_nlp_put(ndlp)) - return 1; - return 0; -} - /** * lpfc_fcf_inuse - Check if FCF can be unregistered. * @phba: Pointer to hba context object. @@ -6961,7 +6944,9 @@ lpfc_unregister_fcf_rescan(struct lpfc_hba *phba) if (rc) return; /* Reset HBA FCF states after successful unregister FCF */ + spin_lock_irq(&phba->hbalock); phba->fcf.fcf_flag = 0; + spin_unlock_irq(&phba->hbalock); phba->fcf.current_rec.flag = 0; /* diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h index 19b2d2754f32778b73bfddf0db8257426e520dee..aaea3e31944d07ab7933bf0e93b1dadd592a5ba3 100644 --- a/drivers/scsi/lpfc/lpfc_hw.h +++ b/drivers/scsi/lpfc/lpfc_hw.h @@ -86,8 +86,8 @@ union CtRevisionId { union CtCommandResponse { /* Structure is in Big Endian format */ struct { - uint32_t CmdRsp:16; - uint32_t Size:16; + __be16 CmdRsp; + __be16 Size; } bits; uint32_t word; }; @@ -124,7 +124,7 @@ struct lpfc_sli_ct_request { #define LPFC_CT_PREAMBLE 20 /* Size of CTReq + 4 up to here */ union { - uint32_t PortID; + __be32 PortID; struct gid { uint8_t PortType; /* for GID_PT requests */ #define GID_PT_N_PORT 1 @@ -365,7 +365,7 @@ struct lpfc_name { uint8_t IEEE[6]; /* FC IEEE address */ } s; uint8_t wwn[8]; - uint64_t name; + uint64_t name __packed __aligned(4); } u; }; @@ -850,7 +850,7 @@ typedef struct _ADISC { /* Structure is in Big Endian format */ struct lpfc_name portName; struct lpfc_name nodeName; uint32_t DID; -} __packed ADISC; +} ADISC; typedef struct _FARP { /* Structure is in Big Endian format */ uint32_t Mflags:8; @@ -880,7 +880,7 @@ typedef struct _FAN { /* Structure is in Big Endian format */ uint32_t Fdid; struct lpfc_name FportName; struct lpfc_name FnodeName; -} __packed FAN; +} FAN; typedef struct _SCR { /* Structure is in Big Endian format */ uint8_t resvd1; @@ -924,7 +924,7 @@ typedef struct _RNID { /* Structure is in Big Endian format */ union { RNID_TOP_DISC topologyDisc; /* topology disc (0xdf) */ } un; -} __packed RNID; +} RNID; struct RLS { /* Structure is in Big Endian format */ uint32_t rls; @@ -1408,19 +1408,19 @@ struct entity_id_object { }; struct app_id_object { - uint32_t port_id; - uint32_t app_id; + __be32 port_id; + __be32 app_id; struct entity_id_object obj; }; struct lpfc_vmid_rapp_ident_list { - uint32_t no_of_objects; - struct entity_id_object obj[1]; + __be32 no_of_objects; + struct entity_id_object obj[]; }; struct lpfc_vmid_dapp_ident_list { - uint32_t no_of_objects; - struct entity_id_object obj[1]; + __be32 no_of_objects; + struct entity_id_object obj[]; }; #define GALLAPPIA_ID_LAST 0x80 @@ -1512,9 +1512,9 @@ struct lpfc_fdmi_hba_ident { * Registered Port List Format */ struct lpfc_fdmi_reg_port_list { - uint32_t EntryCnt; + __be32 EntryCnt; struct lpfc_fdmi_port_entry pe; -} __packed; +}; /* * Register HBA(RHBA) diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h index 58fa39c403a0e3a97091d290268926ffd85bd7cf..5d4f9f27084d6d1fb356d2034bcf22577eb689f5 100644 --- a/drivers/scsi/lpfc/lpfc_hw4.h +++ b/drivers/scsi/lpfc/lpfc_hw4.h @@ -395,9 +395,6 @@ struct lpfc_cqe { #define CQE_STATUS_NEED_BUFF_ENTRY 0xf #define CQE_STATUS_DI_ERROR 0x16 -/* Used when mapping CQE status to IOCB */ -#define LPFC_IOCB_STATUS_MASK 0xf - /* Status returned by hardware (valid only if status = CQE_STATUS_SUCCESS). */ #define CQE_HW_STATUS_NO_ERR 0x0 #define CQE_HW_STATUS_UNDERRUN 0x1 @@ -536,9 +533,9 @@ struct sli4_wcqe_xri_aborted { /* completion queue entry structure for rqe completion */ struct lpfc_rcqe { uint32_t word0; -#define lpfc_rcqe_bindex_SHIFT 16 -#define lpfc_rcqe_bindex_MASK 0x0000FFF -#define lpfc_rcqe_bindex_WORD word0 +#define lpfc_rcqe_iv_SHIFT 31 +#define lpfc_rcqe_iv_MASK 0x00000001 +#define lpfc_rcqe_iv_WORD word0 #define lpfc_rcqe_status_SHIFT 8 #define lpfc_rcqe_status_MASK 0x000000FF #define lpfc_rcqe_status_WORD word0 @@ -546,6 +543,7 @@ struct lpfc_rcqe { #define FC_STATUS_RQ_BUF_LEN_EXCEEDED 0x11 /* payload truncated */ #define FC_STATUS_INSUFF_BUF_NEED_BUF 0x12 /* Insufficient buffers */ #define FC_STATUS_INSUFF_BUF_FRM_DISC 0x13 /* Frame Discard */ +#define FC_STATUS_RQ_DMA_FAILURE 0x14 /* DMA failure */ uint32_t word1; #define lpfc_rcqe_fcf_id_v1_SHIFT 0 #define lpfc_rcqe_fcf_id_v1_MASK 0x0000003F @@ -4813,8 +4811,8 @@ struct cmf_sync_wqe { #define cmf_sync_cqid_WORD word11 uint32_t read_bytes; uint32_t word13; -#define cmf_sync_period_SHIFT 16 -#define cmf_sync_period_MASK 0x0000ffff +#define cmf_sync_period_SHIFT 24 +#define cmf_sync_period_MASK 0x000000ff #define cmf_sync_period_WORD word13 uint32_t word14; uint32_t word15; diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 867b4c788f087e5b854f646a656ed82b81309748..3221a934066bbb7e33159f2d8ed253fc12378586 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -101,6 +101,7 @@ static struct scsi_transport_template *lpfc_vport_transport_template = NULL; static DEFINE_IDR(lpfc_hba_index); #define LPFC_NVMET_BUF_POST 254 static int lpfc_vmid_res_alloc(struct lpfc_hba *phba, struct lpfc_vport *vport); +static void lpfc_cgn_update_tstamp(struct lpfc_hba *phba, struct lpfc_cgn_ts *ts); /** * lpfc_config_port_prep - Perform lpfc initialization prior to config port @@ -1279,7 +1280,7 @@ lpfc_hb_mbox_cmpl(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq) /* * lpfc_idle_stat_delay_work - idle_stat tracking * - * This routine tracks per-cq idle_stat and determines polling decisions. + * This routine tracks per-eq idle_stat and determines polling decisions. * * Return codes: * None @@ -1290,7 +1291,7 @@ lpfc_idle_stat_delay_work(struct work_struct *work) struct lpfc_hba *phba = container_of(to_delayed_work(work), struct lpfc_hba, idle_stat_delay_work); - struct lpfc_queue *cq; + struct lpfc_queue *eq; struct lpfc_sli4_hdw_queue *hdwq; struct lpfc_idle_stat *idle_stat; u32 i, idle_percent; @@ -1306,10 +1307,10 @@ lpfc_idle_stat_delay_work(struct work_struct *work) for_each_present_cpu(i) { hdwq = &phba->sli4_hba.hdwq[phba->sli4_hba.cpu_map[i].hdwq]; - cq = hdwq->io_cq; + eq = hdwq->hba_eq; - /* Skip if we've already handled this cq's primary CPU */ - if (cq->chann != i) + /* Skip if we've already handled this eq's primary CPU */ + if (eq->chann != i) continue; idle_stat = &phba->sli4_hba.idle_stat[i]; @@ -1333,9 +1334,9 @@ lpfc_idle_stat_delay_work(struct work_struct *work) idle_percent = 100 - idle_percent; if (idle_percent < 15) - cq->poll_mode = LPFC_QUEUE_WORK; + eq->poll_mode = LPFC_QUEUE_WORK; else - cq->poll_mode = LPFC_IRQ_POLL; + eq->poll_mode = LPFC_THREADED_IRQ; idle_stat->prev_idle = wall_idle; idle_stat->prev_wall = wall; @@ -3197,6 +3198,7 @@ lpfc_cmf_stop(struct lpfc_hba *phba) "6221 Stop CMF / Cancel Timer\n"); /* Cancel the CMF timer */ + hrtimer_cancel(&phba->cmf_stats_timer); hrtimer_cancel(&phba->cmf_timer); /* Zero CMF counters */ @@ -3283,7 +3285,10 @@ lpfc_cmf_start(struct lpfc_hba *phba) phba->cmf_timer_cnt = 0; hrtimer_start(&phba->cmf_timer, - ktime_set(0, LPFC_CMF_INTERVAL * 1000000), + ktime_set(0, LPFC_CMF_INTERVAL * NSEC_PER_MSEC), + HRTIMER_MODE_REL); + hrtimer_start(&phba->cmf_stats_timer, + ktime_set(0, LPFC_SEC_MIN * NSEC_PER_SEC), HRTIMER_MODE_REL); /* Setup for latency check in IO cmpl routines */ ktime_get_real_ts64(&phba->cmf_latency); @@ -4357,6 +4362,7 @@ lpfc_io_buf_replenish(struct lpfc_hba *phba, struct list_head *cbuf) struct lpfc_sli4_hdw_queue *qp; struct lpfc_io_buf *lpfc_cmd; int idx, cnt; + unsigned long iflags; qp = phba->sli4_hba.hdwq; cnt = 0; @@ -4371,12 +4377,13 @@ lpfc_io_buf_replenish(struct lpfc_hba *phba, struct list_head *cbuf) lpfc_cmd->hdwq_no = idx; lpfc_cmd->hdwq = qp; lpfc_cmd->cur_iocbq.cmd_cmpl = NULL; - spin_lock(&qp->io_buf_list_put_lock); + spin_lock_irqsave(&qp->io_buf_list_put_lock, iflags); list_add_tail(&lpfc_cmd->list, &qp->lpfc_io_buf_list_put); qp->put_io_bufs++; qp->total_io_bufs++; - spin_unlock(&qp->io_buf_list_put_lock); + spin_unlock_irqrestore(&qp->io_buf_list_put_lock, + iflags); } } return cnt; @@ -5593,81 +5600,74 @@ void lpfc_cgn_update_stat(struct lpfc_hba *phba, uint32_t dtag) { struct lpfc_cgn_info *cp; - struct tm broken; - struct timespec64 cur_time; - u32 cnt; u32 value; /* Make sure we have a congestion info buffer */ if (!phba->cgn_i) return; cp = (struct lpfc_cgn_info *)phba->cgn_i->virt; - ktime_get_real_ts64(&cur_time); - time64_to_tm(cur_time.tv_sec, 0, &broken); /* Update congestion statistics */ switch (dtag) { case ELS_DTAG_LNK_INTEGRITY: - cnt = le32_to_cpu(cp->link_integ_notification); - cnt++; - cp->link_integ_notification = cpu_to_le32(cnt); - - cp->cgn_stat_lnk_month = broken.tm_mon + 1; - cp->cgn_stat_lnk_day = broken.tm_mday; - cp->cgn_stat_lnk_year = broken.tm_year - 100; - cp->cgn_stat_lnk_hour = broken.tm_hour; - cp->cgn_stat_lnk_min = broken.tm_min; - cp->cgn_stat_lnk_sec = broken.tm_sec; + le32_add_cpu(&cp->link_integ_notification, 1); + lpfc_cgn_update_tstamp(phba, &cp->stat_lnk); break; case ELS_DTAG_DELIVERY: - cnt = le32_to_cpu(cp->delivery_notification); - cnt++; - cp->delivery_notification = cpu_to_le32(cnt); - - cp->cgn_stat_del_month = broken.tm_mon + 1; - cp->cgn_stat_del_day = broken.tm_mday; - cp->cgn_stat_del_year = broken.tm_year - 100; - cp->cgn_stat_del_hour = broken.tm_hour; - cp->cgn_stat_del_min = broken.tm_min; - cp->cgn_stat_del_sec = broken.tm_sec; + le32_add_cpu(&cp->delivery_notification, 1); + lpfc_cgn_update_tstamp(phba, &cp->stat_delivery); break; case ELS_DTAG_PEER_CONGEST: - cnt = le32_to_cpu(cp->cgn_peer_notification); - cnt++; - cp->cgn_peer_notification = cpu_to_le32(cnt); - - cp->cgn_stat_peer_month = broken.tm_mon + 1; - cp->cgn_stat_peer_day = broken.tm_mday; - cp->cgn_stat_peer_year = broken.tm_year - 100; - cp->cgn_stat_peer_hour = broken.tm_hour; - cp->cgn_stat_peer_min = broken.tm_min; - cp->cgn_stat_peer_sec = broken.tm_sec; + le32_add_cpu(&cp->cgn_peer_notification, 1); + lpfc_cgn_update_tstamp(phba, &cp->stat_peer); break; case ELS_DTAG_CONGESTION: - cnt = le32_to_cpu(cp->cgn_notification); - cnt++; - cp->cgn_notification = cpu_to_le32(cnt); - - cp->cgn_stat_cgn_month = broken.tm_mon + 1; - cp->cgn_stat_cgn_day = broken.tm_mday; - cp->cgn_stat_cgn_year = broken.tm_year - 100; - cp->cgn_stat_cgn_hour = broken.tm_hour; - cp->cgn_stat_cgn_min = broken.tm_min; - cp->cgn_stat_cgn_sec = broken.tm_sec; + le32_add_cpu(&cp->cgn_notification, 1); + lpfc_cgn_update_tstamp(phba, &cp->stat_fpin); } if (phba->cgn_fpin_frequency && phba->cgn_fpin_frequency != LPFC_FPIN_INIT_FREQ) { value = LPFC_CGN_TIMER_TO_MIN / phba->cgn_fpin_frequency; cp->cgn_stat_npm = value; } + value = lpfc_cgn_calc_crc32(cp, LPFC_CGN_INFO_SZ, LPFC_CGN_CRC32_SEED); cp->cgn_info_crc = cpu_to_le32(value); } /** - * lpfc_cgn_save_evt_cnt - Save data into registered congestion buffer + * lpfc_cgn_update_tstamp - Update cmf timestamp * @phba: pointer to lpfc hba data structure. + * @ts: structure to write the timestamp to. + */ +void +lpfc_cgn_update_tstamp(struct lpfc_hba *phba, struct lpfc_cgn_ts *ts) +{ + struct timespec64 cur_time; + struct tm tm_val; + + ktime_get_real_ts64(&cur_time); + time64_to_tm(cur_time.tv_sec, 0, &tm_val); + + ts->month = tm_val.tm_mon + 1; + ts->day = tm_val.tm_mday; + ts->year = tm_val.tm_year - 100; + ts->hour = tm_val.tm_hour; + ts->minute = tm_val.tm_min; + ts->second = tm_val.tm_sec; + + lpfc_printf_log(phba, KERN_INFO, LOG_CGN_MGMT, + "2646 Updated CMF timestamp : " + "%u/%u/%u %u:%u:%u\n", + ts->day, ts->month, + ts->year, ts->hour, + ts->minute, ts->second); +} + +/** + * lpfc_cmf_stats_timer - Save data into registered congestion buffer + * @timer: Timer cookie to access lpfc private data * * Save the congestion event data every minute. * On the hour collapse all the minute data into hour data. Every day @@ -5675,12 +5675,11 @@ lpfc_cgn_update_stat(struct lpfc_hba *phba, uint32_t dtag) * and fabrc congestion event counters that will be saved out * to the registered congestion buffer every minute. */ -static void -lpfc_cgn_save_evt_cnt(struct lpfc_hba *phba) +static enum hrtimer_restart +lpfc_cmf_stats_timer(struct hrtimer *timer) { + struct lpfc_hba *phba; struct lpfc_cgn_info *cp; - struct tm broken; - struct timespec64 cur_time; uint32_t i, index; uint16_t value, mvalue; uint64_t bps; @@ -5691,21 +5690,18 @@ lpfc_cgn_save_evt_cnt(struct lpfc_hba *phba) __le32 *lptr; __le16 *mptr; + phba = container_of(timer, struct lpfc_hba, cmf_stats_timer); /* Make sure we have a congestion info buffer */ if (!phba->cgn_i) - return; + return HRTIMER_NORESTART; cp = (struct lpfc_cgn_info *)phba->cgn_i->virt; - if (time_before(jiffies, phba->cgn_evt_timestamp)) - return; phba->cgn_evt_timestamp = jiffies + msecs_to_jiffies(LPFC_CGN_TIMER_TO_MIN); phba->cgn_evt_minute++; /* We should get to this point in the routine on 1 minute intervals */ - - ktime_get_real_ts64(&cur_time); - time64_to_tm(cur_time.tv_sec, 0, &broken); + lpfc_cgn_update_tstamp(phba, &cp->base_time); if (phba->cgn_fpin_frequency && phba->cgn_fpin_frequency != LPFC_FPIN_INIT_FREQ) { @@ -5858,31 +5854,6 @@ lpfc_cgn_save_evt_cnt(struct lpfc_hba *phba) index = 0; } - /* Anytime we overwrite daily index 0, after we wrap, - * we will be overwriting the oldest day, so we must - * update the congestion data start time for that day. - * That start time should have previously been saved after - * we wrote the last days worth of data. - */ - if ((phba->hba_flag & HBA_CGN_DAY_WRAP) && index == 0) { - time64_to_tm(phba->cgn_daily_ts.tv_sec, 0, &broken); - - cp->cgn_info_month = broken.tm_mon + 1; - cp->cgn_info_day = broken.tm_mday; - cp->cgn_info_year = broken.tm_year - 100; - cp->cgn_info_hour = broken.tm_hour; - cp->cgn_info_minute = broken.tm_min; - cp->cgn_info_second = broken.tm_sec; - - lpfc_printf_log - (phba, KERN_INFO, LOG_CGN_MGMT, - "2646 CGNInfo idx0 Start Time: " - "%d/%d/%d %d:%d:%d\n", - cp->cgn_info_day, cp->cgn_info_month, - cp->cgn_info_year, cp->cgn_info_hour, - cp->cgn_info_minute, cp->cgn_info_second); - } - dvalue = 0; wvalue = 0; lvalue = 0; @@ -5916,15 +5887,6 @@ lpfc_cgn_save_evt_cnt(struct lpfc_hba *phba) "2420 Congestion Info - daily (%d): " "%d %d %d %d %d\n", index, dvalue, wvalue, lvalue, mvalue, avalue); - - /* We just wrote LPFC_MAX_CGN_DAYS of data, - * so we are wrapped on any data after this. - * Save this as the start time for the next day. - */ - if (index == (LPFC_MAX_CGN_DAYS - 1)) { - phba->hba_flag |= HBA_CGN_DAY_WRAP; - ktime_get_real_ts64(&phba->cgn_daily_ts); - } } /* Use the frequency found in the last rcv'ed FPIN */ @@ -5935,6 +5897,10 @@ lpfc_cgn_save_evt_cnt(struct lpfc_hba *phba) lvalue = lpfc_cgn_calc_crc32(cp, LPFC_CGN_INFO_SZ, LPFC_CGN_CRC32_SEED); cp->cgn_info_crc = cpu_to_le32(lvalue); + + hrtimer_forward_now(timer, ktime_set(0, LPFC_SEC_MIN * NSEC_PER_SEC)); + + return HRTIMER_RESTART; } /** @@ -6065,13 +6031,6 @@ lpfc_cmf_timer(struct hrtimer *timer) if (ms && ms < LPFC_CMF_INTERVAL) { cnt = div_u64(total, ms); /* bytes per ms */ cnt *= LPFC_CMF_INTERVAL; /* what total should be */ - - /* If the timeout is scheduled to be shorter, - * this value may skew the data, so cap it at mbpi. - */ - if ((phba->hba_flag & HBA_SHORT_CMF) && cnt > mbpi) - cnt = mbpi; - extra = cnt - total; } lpfc_issue_cmf_sync_wqe(phba, LPFC_CMF_INTERVAL, total + extra); @@ -6141,34 +6100,6 @@ lpfc_cmf_timer(struct hrtimer *timer) } phba->rx_block_cnt += div_u64(rcv, 512); /* save 512 byte block cnt */ - /* Each minute save Fabric and Driver congestion information */ - lpfc_cgn_save_evt_cnt(phba); - - phba->hba_flag &= ~HBA_SHORT_CMF; - - /* Since we need to call lpfc_cgn_save_evt_cnt every minute, on the - * minute, adjust our next timer interval, if needed, to ensure a - * 1 minute granularity when we get the next timer interrupt. - */ - if (time_after(jiffies + msecs_to_jiffies(LPFC_CMF_INTERVAL), - phba->cgn_evt_timestamp)) { - timer_interval = jiffies_to_msecs(phba->cgn_evt_timestamp - - jiffies); - if (timer_interval <= 0) - timer_interval = LPFC_CMF_INTERVAL; - else - phba->hba_flag |= HBA_SHORT_CMF; - - /* If we adjust timer_interval, max_bytes_per_interval - * needs to be adjusted as well. - */ - phba->cmf_link_byte_count = div_u64(phba->cmf_max_line_rate * - timer_interval, 1000); - if (phba->cmf_active_mode == LPFC_CFG_MONITOR) - phba->cmf_max_bytes_per_interval = - phba->cmf_link_byte_count; - } - /* Since total_bytes has already been zero'ed, its okay to unblock * after max_bytes_per_interval is setup. */ @@ -8014,6 +7945,9 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba) /* CMF congestion timer */ hrtimer_init(&phba->cmf_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); phba->cmf_timer.function = lpfc_cmf_timer; + /* CMF 1 minute stats collection timer */ + hrtimer_init(&phba->cmf_stats_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + phba->cmf_stats_timer.function = lpfc_cmf_stats_timer; /* * Control structure for handling external multi-buffer mailbox @@ -13117,8 +13051,10 @@ lpfc_sli4_enable_msix(struct lpfc_hba *phba) } eqhdl->irq = rc; - rc = request_irq(eqhdl->irq, &lpfc_sli4_hba_intr_handler, 0, - name, eqhdl); + rc = request_threaded_irq(eqhdl->irq, + &lpfc_sli4_hba_intr_handler, + &lpfc_sli4_hba_intr_handler_th, + IRQF_ONESHOT, name, eqhdl); if (rc) { lpfc_printf_log(phba, KERN_WARNING, LOG_INIT, "0486 MSI-X fast-path (%d) " @@ -13521,6 +13457,7 @@ lpfc_sli4_hba_unset(struct lpfc_hba *phba) struct pci_dev *pdev = phba->pcidev; lpfc_stop_hba_timers(phba); + hrtimer_cancel(&phba->cmf_stats_timer); hrtimer_cancel(&phba->cmf_timer); if (phba->pport) @@ -13645,8 +13582,6 @@ void lpfc_init_congestion_buf(struct lpfc_hba *phba) { struct lpfc_cgn_info *cp; - struct timespec64 cmpl_time; - struct tm broken; uint16_t size; uint32_t crc; @@ -13666,11 +13601,10 @@ lpfc_init_congestion_buf(struct lpfc_hba *phba) atomic_set(&phba->cgn_latency_evt_cnt, 0); atomic64_set(&phba->cgn_latency_evt, 0); phba->cgn_evt_minute = 0; - phba->hba_flag &= ~HBA_CGN_DAY_WRAP; memset(cp, 0xff, offsetof(struct lpfc_cgn_info, cgn_stat)); cp->cgn_info_size = cpu_to_le16(LPFC_CGN_INFO_SZ); - cp->cgn_info_version = LPFC_CGN_INFO_V3; + cp->cgn_info_version = LPFC_CGN_INFO_V4; /* cgn parameters */ cp->cgn_info_mode = phba->cgn_p.cgn_param_mode; @@ -13678,22 +13612,7 @@ lpfc_init_congestion_buf(struct lpfc_hba *phba) cp->cgn_info_level1 = phba->cgn_p.cgn_param_level1; cp->cgn_info_level2 = phba->cgn_p.cgn_param_level2; - ktime_get_real_ts64(&cmpl_time); - time64_to_tm(cmpl_time.tv_sec, 0, &broken); - - cp->cgn_info_month = broken.tm_mon + 1; - cp->cgn_info_day = broken.tm_mday; - cp->cgn_info_year = broken.tm_year - 100; /* relative to 2000 */ - cp->cgn_info_hour = broken.tm_hour; - cp->cgn_info_minute = broken.tm_min; - cp->cgn_info_second = broken.tm_sec; - - lpfc_printf_log(phba, KERN_INFO, LOG_CGN_MGMT | LOG_INIT, - "2643 CGNInfo Init: Start Time " - "%d/%d/%d %d:%d:%d\n", - cp->cgn_info_day, cp->cgn_info_month, - cp->cgn_info_year, cp->cgn_info_hour, - cp->cgn_info_minute, cp->cgn_info_second); + lpfc_cgn_update_tstamp(phba, &cp->base_time); /* Fill in default LUN qdepth */ if (phba->pport) { @@ -13716,8 +13635,6 @@ void lpfc_init_congestion_stat(struct lpfc_hba *phba) { struct lpfc_cgn_info *cp; - struct timespec64 cmpl_time; - struct tm broken; uint32_t crc; lpfc_printf_log(phba, KERN_INFO, LOG_CGN_MGMT, @@ -13729,22 +13646,7 @@ lpfc_init_congestion_stat(struct lpfc_hba *phba) cp = (struct lpfc_cgn_info *)phba->cgn_i->virt; memset(&cp->cgn_stat, 0, sizeof(cp->cgn_stat)); - ktime_get_real_ts64(&cmpl_time); - time64_to_tm(cmpl_time.tv_sec, 0, &broken); - - cp->cgn_stat_month = broken.tm_mon + 1; - cp->cgn_stat_day = broken.tm_mday; - cp->cgn_stat_year = broken.tm_year - 100; /* relative to 2000 */ - cp->cgn_stat_hour = broken.tm_hour; - cp->cgn_stat_minute = broken.tm_min; - - lpfc_printf_log(phba, KERN_INFO, LOG_CGN_MGMT | LOG_INIT, - "2647 CGNstat Init: Start Time " - "%d/%d/%d %d:%d\n", - cp->cgn_stat_day, cp->cgn_stat_month, - cp->cgn_stat_year, cp->cgn_stat_hour, - cp->cgn_stat_minute); - + lpfc_cgn_update_tstamp(phba, &cp->stat_start); crc = lpfc_cgn_calc_crc32(cp, LPFC_CGN_INFO_SZ, LPFC_CGN_CRC32_SEED); cp->cgn_info_crc = cpu_to_le32(crc); } @@ -14743,10 +14645,10 @@ lpfc_write_firmware(const struct firmware *fw, void *context) INIT_LIST_HEAD(&dma_buffer_list); lpfc_decode_firmware_rev(phba, fwrev, 1); if (strncmp(fwrev, image->revision, strnlen(image->revision, 16))) { - lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, - "3023 Updating Firmware, Current Version:%s " - "New Version:%s\n", - fwrev, image->revision); + lpfc_log_msg(phba, KERN_NOTICE, LOG_INIT | LOG_SLI, + "3023 Updating Firmware, Current Version:%s " + "New Version:%s\n", + fwrev, image->revision); for (i = 0; i < LPFC_MBX_WR_CONFIG_MAX_BDE; i++) { dmabuf = kzalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL); @@ -14793,10 +14695,10 @@ lpfc_write_firmware(const struct firmware *fw, void *context) } rc = offset; } else - lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, - "3029 Skipped Firmware update, Current " - "Version:%s New Version:%s\n", - fwrev, image->revision); + lpfc_log_msg(phba, KERN_NOTICE, LOG_INIT | LOG_SLI, + "3029 Skipped Firmware update, Current " + "Version:%s New Version:%s\n", + fwrev, image->revision); release_out: list_for_each_entry_safe(dmabuf, next, &dma_buffer_list, list) { @@ -14808,11 +14710,11 @@ lpfc_write_firmware(const struct firmware *fw, void *context) release_firmware(fw); out: if (rc < 0) - lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, - "3062 Firmware update error, status %d.\n", rc); + lpfc_log_msg(phba, KERN_ERR, LOG_INIT | LOG_SLI, + "3062 Firmware update error, status %d.\n", rc); else - lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, - "3024 Firmware update success: size %d.\n", rc); + lpfc_log_msg(phba, KERN_NOTICE, LOG_INIT | LOG_SLI, + "3024 Firmware update success: size %d.\n", rc); } /** diff --git a/drivers/scsi/lpfc/lpfc_logmsg.h b/drivers/scsi/lpfc/lpfc_logmsg.h index b39cefcd8703f9a1c9cb490ddb9e8e4c3f659610..f896ec6104332c44bfd5d8106822b4e3940467d8 100644 --- a/drivers/scsi/lpfc/lpfc_logmsg.h +++ b/drivers/scsi/lpfc/lpfc_logmsg.h @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2017-2022 Broadcom. All Rights Reserved. The term * + * Copyright (C) 2017-2023 Broadcom. All Rights Reserved. The term * * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. * * Copyright (C) 2004-2009 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * @@ -55,7 +55,7 @@ void lpfc_dbg_print(struct lpfc_hba *phba, const char *fmt, ...); /* generate message by verbose log setting or severity */ #define lpfc_vlog_msg(vport, level, mask, fmt, arg...) \ -{ if (((mask) & (vport)->cfg_log_verbose) || (level[1] <= '4')) \ +{ if (((mask) & (vport)->cfg_log_verbose) || (level[1] <= '5')) \ dev_printk(level, &((vport)->phba->pcidev)->dev, "%d:(%d):" \ fmt, (vport)->phba->brd_no, vport->vpi, ##arg); } @@ -64,7 +64,7 @@ do { \ { uint32_t log_verbose = (phba)->pport ? \ (phba)->pport->cfg_log_verbose : \ (phba)->cfg_log_verbose; \ - if (((mask) & log_verbose) || (level[1] <= '4')) \ + if (((mask) & log_verbose) || (level[1] <= '5')) \ dev_printk(level, &((phba)->pcidev)->dev, "%d:" \ fmt, phba->brd_no, ##arg); \ } \ diff --git a/drivers/scsi/lpfc/lpfc_nvme.c b/drivers/scsi/lpfc/lpfc_nvme.c index adda70423c7757d0481edd2091bc45b1c463a067..8db7cb99903dbdf45e070f8a1a5e62450e867333 100644 --- a/drivers/scsi/lpfc/lpfc_nvme.c +++ b/drivers/scsi/lpfc/lpfc_nvme.c @@ -310,20 +310,20 @@ lpfc_nvme_handle_lsreq(struct lpfc_hba *phba, * for the LS request. **/ void -__lpfc_nvme_ls_req_cmp(struct lpfc_hba *phba, struct lpfc_vport *vport, +__lpfc_nvme_ls_req_cmp(struct lpfc_hba *phba, struct lpfc_vport *vport, struct lpfc_iocbq *cmdwqe, struct lpfc_wcqe_complete *wcqe) { struct nvmefc_ls_req *pnvme_lsreq; struct lpfc_dmabuf *buf_ptr; struct lpfc_nodelist *ndlp; - uint32_t status; + int status; pnvme_lsreq = cmdwqe->context_un.nvme_lsreq; ndlp = cmdwqe->ndlp; buf_ptr = cmdwqe->bpl_dmabuf; - status = bf_get(lpfc_wcqe_c_status, wcqe) & LPFC_IOCB_STATUS_MASK; + status = bf_get(lpfc_wcqe_c_status, wcqe); lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME_DISC, "6047 NVMEx LS REQ x%px cmpl DID %x Xri: %x " @@ -343,14 +343,17 @@ __lpfc_nvme_ls_req_cmp(struct lpfc_hba *phba, struct lpfc_vport *vport, kfree(buf_ptr); cmdwqe->bpl_dmabuf = NULL; } - if (pnvme_lsreq->done) + if (pnvme_lsreq->done) { + if (status != CQE_STATUS_SUCCESS) + status = -ENXIO; pnvme_lsreq->done(pnvme_lsreq, status); - else + } else { lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "6046 NVMEx cmpl without done call back? " "Data x%px DID %x Xri: %x status %x\n", pnvme_lsreq, ndlp ? ndlp->nlp_DID : 0, cmdwqe->sli4_xritag, status); + } if (ndlp) { lpfc_nlp_put(ndlp); cmdwqe->ndlp = NULL; @@ -367,7 +370,7 @@ lpfc_nvme_ls_req_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe, uint32_t status; struct lpfc_wcqe_complete *wcqe = &rspwqe->wcqe_cmpl; - status = bf_get(lpfc_wcqe_c_status, wcqe) & LPFC_IOCB_STATUS_MASK; + status = bf_get(lpfc_wcqe_c_status, wcqe); if (vport->localport) { lport = (struct lpfc_nvme_lport *)vport->localport->private; @@ -1040,7 +1043,7 @@ lpfc_nvme_io_cmd_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn, nCmd->rcv_rsplen = LPFC_NVME_ERSP_LEN; nCmd->transferred_length = nCmd->payload_length; } else { - lpfc_ncmd->status = (status & LPFC_IOCB_STATUS_MASK); + lpfc_ncmd->status = status; lpfc_ncmd->result = (wcqe->parameter & IOERR_PARAM_MASK); /* For NVME, the only failure path that results in an @@ -1893,38 +1896,38 @@ lpfc_nvme_fcp_abort(struct nvme_fc_local_port *pnvme_lport, pnvme_rport->port_id, pnvme_fcreq); - /* If the hba is getting reset, this flag is set. It is - * cleared when the reset is complete and rings reestablished. - */ - spin_lock_irqsave(&phba->hbalock, flags); - /* driver queued commands are in process of being flushed */ - if (phba->hba_flag & HBA_IOQ_FLUSH) { - spin_unlock_irqrestore(&phba->hbalock, flags); - lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, - "6139 Driver in reset cleanup - flushing " - "NVME Req now. hba_flag x%x\n", - phba->hba_flag); - return; - } - lpfc_nbuf = freqpriv->nvme_buf; if (!lpfc_nbuf) { - spin_unlock_irqrestore(&phba->hbalock, flags); lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "6140 NVME IO req has no matching lpfc nvme " "io buffer. Skipping abort req.\n"); return; } else if (!lpfc_nbuf->nvmeCmd) { - spin_unlock_irqrestore(&phba->hbalock, flags); lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "6141 lpfc NVME IO req has no nvme_fcreq " "io buffer. Skipping abort req.\n"); return; } - nvmereq_wqe = &lpfc_nbuf->cur_iocbq; /* Guard against IO completion being called at same time */ - spin_lock(&lpfc_nbuf->buf_lock); + spin_lock_irqsave(&lpfc_nbuf->buf_lock, flags); + + /* If the hba is getting reset, this flag is set. It is + * cleared when the reset is complete and rings reestablished. + */ + spin_lock(&phba->hbalock); + /* driver queued commands are in process of being flushed */ + if (phba->hba_flag & HBA_IOQ_FLUSH) { + spin_unlock(&phba->hbalock); + spin_unlock_irqrestore(&lpfc_nbuf->buf_lock, flags); + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, + "6139 Driver in reset cleanup - flushing " + "NVME Req now. hba_flag x%x\n", + phba->hba_flag); + return; + } + + nvmereq_wqe = &lpfc_nbuf->cur_iocbq; /* * The lpfc_nbuf and the mapped nvme_fcreq in the driver's @@ -1971,8 +1974,8 @@ lpfc_nvme_fcp_abort(struct nvme_fc_local_port *pnvme_lport, ret_val = lpfc_sli4_issue_abort_iotag(phba, nvmereq_wqe, lpfc_nvme_abort_fcreq_cmpl); - spin_unlock(&lpfc_nbuf->buf_lock); - spin_unlock_irqrestore(&phba->hbalock, flags); + spin_unlock(&phba->hbalock); + spin_unlock_irqrestore(&lpfc_nbuf->buf_lock, flags); /* Make sure HBA is alive */ lpfc_issue_hb_tmo(phba); @@ -1998,8 +2001,8 @@ lpfc_nvme_fcp_abort(struct nvme_fc_local_port *pnvme_lport, return; out_unlock: - spin_unlock(&lpfc_nbuf->buf_lock); - spin_unlock_irqrestore(&phba->hbalock, flags); + spin_unlock(&phba->hbalock); + spin_unlock_irqrestore(&lpfc_nbuf->buf_lock, flags); return; } diff --git a/drivers/scsi/lpfc/lpfc_nvmet.c b/drivers/scsi/lpfc/lpfc_nvmet.c index 7517dd55fe91953375e91054bb72e2cb5f8ab620..dff4584d338bae91746595a5be3c4bf51c9e297e 100644 --- a/drivers/scsi/lpfc/lpfc_nvmet.c +++ b/drivers/scsi/lpfc/lpfc_nvmet.c @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2017-2022 Broadcom. All Rights Reserved. The term * + * Copyright (C) 2017-2023 Broadcom. All Rights Reserved. The term * * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. * * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * @@ -300,7 +300,7 @@ __lpfc_nvme_xmt_ls_rsp_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe, struct nvmefc_ls_rsp *ls_rsp = &axchg->ls_rsp; uint32_t status, result; - status = bf_get(lpfc_wcqe_c_status, wcqe) & LPFC_IOCB_STATUS_MASK; + status = bf_get(lpfc_wcqe_c_status, wcqe); result = wcqe->parameter; if (axchg->state != LPFC_NVME_STE_LS_RSP || axchg->entry_cnt != 2) { @@ -350,7 +350,7 @@ lpfc_nvmet_xmt_ls_rsp_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe, if (!phba->targetport) goto finish; - status = bf_get(lpfc_wcqe_c_status, wcqe) & LPFC_IOCB_STATUS_MASK; + status = bf_get(lpfc_wcqe_c_status, wcqe); result = wcqe->parameter; tgtp = (struct lpfc_nvmet_tgtport *)phba->targetport->private; diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index e989f130434e46a4de876aa08274bee2ec51acf1..a62e091894f6e5951fd4d8a2a26b330ab0e4dd6f 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c @@ -4026,7 +4026,7 @@ lpfc_fcp_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn, struct lpfc_fast_path_event *fast_path_evt; struct Scsi_Host *shost; u32 logit = LOG_FCP; - u32 status, idx; + u32 idx; u32 lat; u8 wait_xb_clr = 0; @@ -4061,8 +4061,7 @@ lpfc_fcp_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn, #endif shost = cmd->device->host; - status = bf_get(lpfc_wcqe_c_status, wcqe); - lpfc_cmd->status = (status & LPFC_IOCB_STATUS_MASK); + lpfc_cmd->status = bf_get(lpfc_wcqe_c_status, wcqe); lpfc_cmd->result = (wcqe->parameter & IOERR_PARAM_MASK); lpfc_cmd->flags &= ~LPFC_SBUF_XBUSY; @@ -4104,11 +4103,6 @@ lpfc_fcp_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn, } #endif if (unlikely(lpfc_cmd->status)) { - if (lpfc_cmd->status == IOSTAT_LOCAL_REJECT && - (lpfc_cmd->result & IOERR_DRVR_MASK)) - lpfc_cmd->status = IOSTAT_DRIVER_REJECT; - else if (lpfc_cmd->status >= IOSTAT_CNT) - lpfc_cmd->status = IOSTAT_DEFAULT; if (lpfc_cmd->status == IOSTAT_FCP_RSP_ERROR && !lpfc_cmd->fcp_rsp->rspStatus3 && (lpfc_cmd->fcp_rsp->rspStatus2 & RESID_UNDER) && @@ -4133,16 +4127,16 @@ lpfc_fcp_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn, } switch (lpfc_cmd->status) { - case IOSTAT_SUCCESS: + case CQE_STATUS_SUCCESS: cmd->result = DID_OK << 16; break; - case IOSTAT_FCP_RSP_ERROR: + case CQE_STATUS_FCP_RSP_FAILURE: lpfc_handle_fcp_err(vport, lpfc_cmd, pwqeIn->wqe.fcp_iread.total_xfer_len - wcqe->total_data_placed); break; - case IOSTAT_NPORT_BSY: - case IOSTAT_FABRIC_BSY: + case CQE_STATUS_NPORT_BSY: + case CQE_STATUS_FABRIC_BSY: cmd->result = DID_TRANSPORT_DISRUPTED << 16; fast_path_evt = lpfc_alloc_fast_evt(phba); if (!fast_path_evt) @@ -4185,7 +4179,27 @@ lpfc_fcp_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn, wcqe->total_data_placed, lpfc_cmd->cur_iocbq.iocb.ulpIoTag); break; - case IOSTAT_REMOTE_STOP: + case CQE_STATUS_DI_ERROR: + if (bf_get(lpfc_wcqe_c_bg_edir, wcqe)) + lpfc_cmd->result = IOERR_RX_DMA_FAILED; + else + lpfc_cmd->result = IOERR_TX_DMA_FAILED; + lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP | LOG_BG, + "9048 DI Error xri x%x status x%x DI ext " + "status x%x data placed x%x\n", + lpfc_cmd->cur_iocbq.sli4_xritag, + lpfc_cmd->status, wcqe->parameter, + wcqe->total_data_placed); + if (scsi_get_prot_op(cmd) != SCSI_PROT_NORMAL) { + /* BG enabled cmd. Parse BG error */ + lpfc_parse_bg_err(phba, lpfc_cmd, pwqeOut); + break; + } + cmd->result = DID_ERROR << 16; + lpfc_printf_vlog(vport, KERN_WARNING, LOG_BG, + "9040 DI Error on unprotected cmd\n"); + break; + case CQE_STATUS_REMOTE_STOP: if (ndlp) { /* This I/O was aborted by the target, we don't * know the rxid and because we did not send the @@ -4196,7 +4210,7 @@ lpfc_fcp_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn, 0, 0); } fallthrough; - case IOSTAT_LOCAL_REJECT: + case CQE_STATUS_LOCAL_REJECT: if (lpfc_cmd->result & IOERR_DRVR_MASK) lpfc_cmd->status = IOSTAT_DRIVER_REJECT; if (lpfc_cmd->result == IOERR_ELXSEC_KEY_UNWRAP_ERROR || @@ -4217,24 +4231,6 @@ lpfc_fcp_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn, cmd->result = DID_TRANSPORT_DISRUPTED << 16; break; } - if ((lpfc_cmd->result == IOERR_RX_DMA_FAILED || - lpfc_cmd->result == IOERR_TX_DMA_FAILED) && - status == CQE_STATUS_DI_ERROR) { - if (scsi_get_prot_op(cmd) != - SCSI_PROT_NORMAL) { - /* - * This is a response for a BG enabled - * cmd. Parse BG error - */ - lpfc_parse_bg_err(phba, lpfc_cmd, pwqeOut); - break; - } else { - lpfc_printf_vlog(vport, KERN_WARNING, - LOG_BG, - "9040 non-zero BGSTAT " - "on unprotected cmd\n"); - } - } lpfc_printf_vlog(vport, KERN_WARNING, logit, "9036 Local Reject FCP cmd x%x failed" " <%d/%lld> " @@ -4253,10 +4249,8 @@ lpfc_fcp_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn, lpfc_cmd->cur_iocbq.iocb.ulpIoTag); fallthrough; default: - if (lpfc_cmd->status >= IOSTAT_CNT) - lpfc_cmd->status = IOSTAT_DEFAULT; cmd->result = DID_ERROR << 16; - lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME_IOERR, + lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP, "9037 FCP Completion Error: xri %x " "status x%x result x%x [x%x] " "placed x%x\n", @@ -4273,7 +4267,8 @@ lpfc_fcp_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn, "x%x SNS x%x x%x LBA x%llx Data: x%x x%x\n", cmd->device->id, cmd->device->lun, cmd, cmd->result, *lp, *(lp + 3), - (u64)scsi_get_lba(cmd), + (cmd->device->sector_size) ? + (u64)scsi_get_lba(cmd) : 0, cmd->retries, scsi_get_resid(cmd)); } @@ -5009,7 +5004,6 @@ lpfc_scsi_api_table_setup(struct lpfc_hba *phba, uint8_t dev_grp) return -ENODEV; } phba->lpfc_rampdown_queue_depth = lpfc_rampdown_queue_depth; - phba->lpfc_scsi_cmd_iocb_cmpl = lpfc_scsi_cmd_iocb_cmpl; return 0; } diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 8693578888f1f10e4e69418f60ca91b71be2a779..58d10f8f75a78fc80fc99767c96f17db6c6092e7 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -82,7 +82,8 @@ static int lpfc_sli4_post_sgl_list(struct lpfc_hba *, struct list_head *, int); static void lpfc_sli4_hba_handle_eqe(struct lpfc_hba *phba, struct lpfc_queue *eq, - struct lpfc_eqe *eqe); + struct lpfc_eqe *eqe, + enum lpfc_poll_mode poll_mode); static bool lpfc_sli4_mbox_completions_pending(struct lpfc_hba *phba); static bool lpfc_sli4_process_missed_mbox_completions(struct lpfc_hba *phba); static struct lpfc_cqe *lpfc_sli4_cq_get(struct lpfc_queue *q); @@ -629,7 +630,7 @@ lpfc_sli4_eqcq_flush(struct lpfc_hba *phba, struct lpfc_queue *eq) static int lpfc_sli4_process_eq(struct lpfc_hba *phba, struct lpfc_queue *eq, - uint8_t rearm) + u8 rearm, enum lpfc_poll_mode poll_mode) { struct lpfc_eqe *eqe; int count = 0, consumed = 0; @@ -639,7 +640,7 @@ lpfc_sli4_process_eq(struct lpfc_hba *phba, struct lpfc_queue *eq, eqe = lpfc_sli4_eq_get(eq); while (eqe) { - lpfc_sli4_hba_handle_eqe(phba, eq, eqe); + lpfc_sli4_hba_handle_eqe(phba, eq, eqe, poll_mode); __lpfc_sli4_consume_eqe(phba, eq, eqe); consumed++; @@ -1931,7 +1932,7 @@ lpfc_issue_cmf_sync_wqe(struct lpfc_hba *phba, u32 ms, u64 total) unsigned long iflags; u32 ret_val; u32 atot, wtot, max; - u16 warn_sync_period = 0; + u8 warn_sync_period = 0; /* First address any alarm / warning activity */ atot = atomic_xchg(&phba->cgn_sync_alarm_cnt, 0); @@ -7957,7 +7958,7 @@ lpfc_config_cgn_signal(struct lpfc_hba *phba) * lpfc_init_idle_stat_hb - Initialize idle_stat tracking * @phba: pointer to lpfc hba data structure. * - * This routine initializes the per-cq idle_stat to dynamically dictate + * This routine initializes the per-eq idle_stat to dynamically dictate * polling decisions. * * Return codes: @@ -7967,16 +7968,16 @@ static void lpfc_init_idle_stat_hb(struct lpfc_hba *phba) { int i; struct lpfc_sli4_hdw_queue *hdwq; - struct lpfc_queue *cq; + struct lpfc_queue *eq; struct lpfc_idle_stat *idle_stat; u64 wall; for_each_present_cpu(i) { hdwq = &phba->sli4_hba.hdwq[phba->sli4_hba.cpu_map[i].hdwq]; - cq = hdwq->io_cq; + eq = hdwq->hba_eq; - /* Skip if we've already handled this cq's primary CPU */ - if (cq->chann != i) + /* Skip if we've already handled this eq's primary CPU */ + if (eq->chann != i) continue; idle_stat = &phba->sli4_hba.idle_stat[i]; @@ -7985,13 +7986,14 @@ static void lpfc_init_idle_stat_hb(struct lpfc_hba *phba) idle_stat->prev_wall = wall; if (phba->nvmet_support || - phba->cmf_active_mode != LPFC_CFG_OFF) - cq->poll_mode = LPFC_QUEUE_WORK; + phba->cmf_active_mode != LPFC_CFG_OFF || + phba->intr_type != MSIX) + eq->poll_mode = LPFC_QUEUE_WORK; else - cq->poll_mode = LPFC_IRQ_POLL; + eq->poll_mode = LPFC_THREADED_IRQ; } - if (!phba->nvmet_support) + if (!phba->nvmet_support && phba->intr_type == MSIX) schedule_delayed_work(&phba->idle_stat_delay_work, msecs_to_jiffies(LPFC_IDLE_STAT_DELAY)); } @@ -9218,7 +9220,8 @@ lpfc_sli4_process_missed_mbox_completions(struct lpfc_hba *phba) if (mbox_pending) /* process and rearm the EQ */ - lpfc_sli4_process_eq(phba, fpeq, LPFC_QUEUE_REARM); + lpfc_sli4_process_eq(phba, fpeq, LPFC_QUEUE_REARM, + LPFC_QUEUE_WORK); else /* Always clear and re-arm the EQ */ sli4_hba->sli4_write_eq_db(phba, fpeq, 0, LPFC_QUEUE_REARM); @@ -11254,7 +11257,8 @@ inline void lpfc_sli4_poll_eq(struct lpfc_queue *eq) * will be handled through a sched from polling timer * function which is currently triggered every 1msec. */ - lpfc_sli4_process_eq(phba, eq, LPFC_QUEUE_NOARM); + lpfc_sli4_process_eq(phba, eq, LPFC_QUEUE_NOARM, + LPFC_QUEUE_WORK); } /** @@ -14682,6 +14686,38 @@ lpfc_sli4_sp_handle_rcqe(struct lpfc_hba *phba, struct lpfc_rcqe *rcqe) spin_unlock_irqrestore(&phba->hbalock, iflags); workposted = true; break; + case FC_STATUS_RQ_DMA_FAILURE: + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, + "2564 RQE DMA Error x%x, x%08x x%08x x%08x " + "x%08x\n", + status, rcqe->word0, rcqe->word1, + rcqe->word2, rcqe->word3); + + /* If IV set, no further recovery */ + if (bf_get(lpfc_rcqe_iv, rcqe)) + break; + + /* recycle consumed resource */ + spin_lock_irqsave(&phba->hbalock, iflags); + lpfc_sli4_rq_release(hrq, drq); + dma_buf = lpfc_sli_hbqbuf_get(&phba->hbqs[0].hbq_buffer_list); + if (!dma_buf) { + hrq->RQ_no_buf_found++; + spin_unlock_irqrestore(&phba->hbalock, iflags); + break; + } + hrq->RQ_rcv_buf++; + hrq->RQ_buf_posted--; + spin_unlock_irqrestore(&phba->hbalock, iflags); + lpfc_in_buf_free(phba, &dma_buf->dbuf); + break; + default: + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, + "2565 Unexpected RQE Status x%x, w0-3 x%08x " + "x%08x x%08x x%08x\n", + status, rcqe->word0, rcqe->word1, + rcqe->word2, rcqe->word3); + break; } out: return workposted; @@ -14803,7 +14839,6 @@ lpfc_sli4_sp_handle_eqe(struct lpfc_hba *phba, struct lpfc_eqe *eqe, * @cq: Pointer to CQ to be processed * @handler: Routine to process each cqe * @delay: Pointer to usdelay to set in case of rescheduling of the handler - * @poll_mode: Polling mode we were called from * * This routine processes completion queue entries in a CQ. While a valid * queue element is found, the handler is called. During processing checks @@ -14821,8 +14856,7 @@ lpfc_sli4_sp_handle_eqe(struct lpfc_hba *phba, struct lpfc_eqe *eqe, static bool __lpfc_sli4_process_cq(struct lpfc_hba *phba, struct lpfc_queue *cq, bool (*handler)(struct lpfc_hba *, struct lpfc_queue *, - struct lpfc_cqe *), unsigned long *delay, - enum lpfc_poll_mode poll_mode) + struct lpfc_cqe *), unsigned long *delay) { struct lpfc_cqe *cqe; bool workposted = false; @@ -14863,10 +14897,6 @@ __lpfc_sli4_process_cq(struct lpfc_hba *phba, struct lpfc_queue *cq, arm = false; } - /* Note: complete the irq_poll softirq before rearming CQ */ - if (poll_mode == LPFC_IRQ_POLL) - irq_poll_complete(&cq->iop); - /* Track the max number of CQEs processed in 1 EQ */ if (count > cq->CQ_max_cqe) cq->CQ_max_cqe = count; @@ -14916,17 +14946,17 @@ __lpfc_sli4_sp_process_cq(struct lpfc_queue *cq) case LPFC_MCQ: workposted |= __lpfc_sli4_process_cq(phba, cq, lpfc_sli4_sp_handle_mcqe, - &delay, LPFC_QUEUE_WORK); + &delay); break; case LPFC_WCQ: if (cq->subtype == LPFC_IO) workposted |= __lpfc_sli4_process_cq(phba, cq, lpfc_sli4_fp_handle_cqe, - &delay, LPFC_QUEUE_WORK); + &delay); else workposted |= __lpfc_sli4_process_cq(phba, cq, lpfc_sli4_sp_handle_cqe, - &delay, LPFC_QUEUE_WORK); + &delay); break; default: lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, @@ -15203,6 +15233,38 @@ lpfc_sli4_nvmet_handle_rcqe(struct lpfc_hba *phba, struct lpfc_queue *cq, hrq->RQ_no_posted_buf++; /* Post more buffers if possible */ break; + case FC_STATUS_RQ_DMA_FAILURE: + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, + "2575 RQE DMA Error x%x, x%08x x%08x x%08x " + "x%08x\n", + status, rcqe->word0, rcqe->word1, + rcqe->word2, rcqe->word3); + + /* If IV set, no further recovery */ + if (bf_get(lpfc_rcqe_iv, rcqe)) + break; + + /* recycle consumed resource */ + spin_lock_irqsave(&phba->hbalock, iflags); + lpfc_sli4_rq_release(hrq, drq); + dma_buf = lpfc_sli_rqbuf_get(phba, hrq); + if (!dma_buf) { + hrq->RQ_no_buf_found++; + spin_unlock_irqrestore(&phba->hbalock, iflags); + break; + } + hrq->RQ_rcv_buf++; + hrq->RQ_buf_posted--; + spin_unlock_irqrestore(&phba->hbalock, iflags); + lpfc_rq_buf_free(phba, &dma_buf->hbuf); + break; + default: + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, + "2576 Unexpected RQE Status x%x, w0-3 x%08x " + "x%08x x%08x x%08x\n", + status, rcqe->word0, rcqe->word1, + rcqe->word2, rcqe->word3); + break; } out: return workposted; @@ -15271,45 +15333,64 @@ lpfc_sli4_fp_handle_cqe(struct lpfc_hba *phba, struct lpfc_queue *cq, } /** - * lpfc_sli4_sched_cq_work - Schedules cq work - * @phba: Pointer to HBA context object. - * @cq: Pointer to CQ - * @cqid: CQ ID - * - * This routine checks the poll mode of the CQ corresponding to - * cq->chann, then either schedules a softirq or queue_work to complete - * cq work. + * __lpfc_sli4_hba_process_cq - Process a fast-path event queue entry + * @cq: Pointer to CQ to be processed * - * queue_work path is taken if in NVMET mode, or if poll_mode is in - * LPFC_QUEUE_WORK mode. Otherwise, softirq path is taken. + * This routine calls the cq processing routine with the handler for + * fast path CQEs. * + * The CQ routine returns two values: the first is the calling status, + * which indicates whether work was queued to the background discovery + * thread. If true, the routine should wakeup the discovery thread; + * the second is the delay parameter. If non-zero, rather than rearming + * the CQ and yet another interrupt, the CQ handler should be queued so + * that it is processed in a subsequent polling action. The value of + * the delay indicates when to reschedule it. **/ -static void lpfc_sli4_sched_cq_work(struct lpfc_hba *phba, - struct lpfc_queue *cq, uint16_t cqid) +static void +__lpfc_sli4_hba_process_cq(struct lpfc_queue *cq) { - int ret = 0; + struct lpfc_hba *phba = cq->phba; + unsigned long delay; + bool workposted = false; + int ret; - switch (cq->poll_mode) { - case LPFC_IRQ_POLL: - /* CGN mgmt is mutually exclusive from softirq processing */ - if (phba->cmf_active_mode == LPFC_CFG_OFF) { - irq_poll_sched(&cq->iop); - break; - } - fallthrough; - case LPFC_QUEUE_WORK: - default: + /* process and rearm the CQ */ + workposted |= __lpfc_sli4_process_cq(phba, cq, lpfc_sli4_fp_handle_cqe, + &delay); + + if (delay) { if (is_kdump_kernel()) - ret = queue_work(phba->wq, &cq->irqwork); + ret = queue_delayed_work(phba->wq, &cq->sched_irqwork, + delay); else - ret = queue_work_on(cq->chann, phba->wq, &cq->irqwork); + ret = queue_delayed_work_on(cq->chann, phba->wq, + &cq->sched_irqwork, delay); if (!ret) lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, - "0383 Cannot schedule queue work " - "for CQ eqcqid=%d, cqid=%d on CPU %d\n", - cqid, cq->queue_id, - raw_smp_processor_id()); + "0367 Cannot schedule queue work " + "for cqid=%d on CPU %d\n", + cq->queue_id, cq->chann); } + + /* wake up worker thread if there are works to be done */ + if (workposted) + lpfc_worker_wake_up(phba); +} + +/** + * lpfc_sli4_hba_process_cq - fast-path work handler when started by + * interrupt + * @work: pointer to work element + * + * translates from the work handler and calls the fast-path handler. + **/ +static void +lpfc_sli4_hba_process_cq(struct work_struct *work) +{ + struct lpfc_queue *cq = container_of(work, struct lpfc_queue, irqwork); + + __lpfc_sli4_hba_process_cq(cq); } /** @@ -15317,6 +15398,7 @@ static void lpfc_sli4_sched_cq_work(struct lpfc_hba *phba, * @phba: Pointer to HBA context object. * @eq: Pointer to the queue structure. * @eqe: Pointer to fast-path event queue entry. + * @poll_mode: poll_mode to execute processing the cq. * * This routine process a event queue entry from the fast-path event queue. * It will check the MajorCode and MinorCode to determine this is for a @@ -15327,11 +15409,12 @@ static void lpfc_sli4_sched_cq_work(struct lpfc_hba *phba, **/ static void lpfc_sli4_hba_handle_eqe(struct lpfc_hba *phba, struct lpfc_queue *eq, - struct lpfc_eqe *eqe) + struct lpfc_eqe *eqe, enum lpfc_poll_mode poll_mode) { struct lpfc_queue *cq = NULL; uint32_t qidx = eq->hdwq; uint16_t cqid, id; + int ret; if (unlikely(bf_get_le32(lpfc_eqe_major_code, eqe) != 0)) { lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, @@ -15391,70 +15474,25 @@ lpfc_sli4_hba_handle_eqe(struct lpfc_hba *phba, struct lpfc_queue *eq, else cq->isr_timestamp = 0; #endif - lpfc_sli4_sched_cq_work(phba, cq, cqid); -} - -/** - * __lpfc_sli4_hba_process_cq - Process a fast-path event queue entry - * @cq: Pointer to CQ to be processed - * @poll_mode: Enum lpfc_poll_state to determine poll mode - * - * This routine calls the cq processing routine with the handler for - * fast path CQEs. - * - * The CQ routine returns two values: the first is the calling status, - * which indicates whether work was queued to the background discovery - * thread. If true, the routine should wakeup the discovery thread; - * the second is the delay parameter. If non-zero, rather than rearming - * the CQ and yet another interrupt, the CQ handler should be queued so - * that it is processed in a subsequent polling action. The value of - * the delay indicates when to reschedule it. - **/ -static void -__lpfc_sli4_hba_process_cq(struct lpfc_queue *cq, - enum lpfc_poll_mode poll_mode) -{ - struct lpfc_hba *phba = cq->phba; - unsigned long delay; - bool workposted = false; - int ret = 0; - - /* process and rearm the CQ */ - workposted |= __lpfc_sli4_process_cq(phba, cq, lpfc_sli4_fp_handle_cqe, - &delay, poll_mode); - if (delay) { + switch (poll_mode) { + case LPFC_THREADED_IRQ: + __lpfc_sli4_hba_process_cq(cq); + break; + case LPFC_QUEUE_WORK: + default: if (is_kdump_kernel()) - ret = queue_delayed_work(phba->wq, &cq->sched_irqwork, - delay); + ret = queue_work(phba->wq, &cq->irqwork); else - ret = queue_delayed_work_on(cq->chann, phba->wq, - &cq->sched_irqwork, delay); + ret = queue_work_on(cq->chann, phba->wq, &cq->irqwork); if (!ret) lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, - "0367 Cannot schedule queue work " - "for cqid=%d on CPU %d\n", - cq->queue_id, cq->chann); + "0383 Cannot schedule queue work " + "for CQ eqcqid=%d, cqid=%d on CPU %d\n", + cqid, cq->queue_id, + raw_smp_processor_id()); + break; } - - /* wake up worker thread if there are works to be done */ - if (workposted) - lpfc_worker_wake_up(phba); -} - -/** - * lpfc_sli4_hba_process_cq - fast-path work handler when started by - * interrupt - * @work: pointer to work element - * - * translates from the work handler and calls the fast-path handler. - **/ -static void -lpfc_sli4_hba_process_cq(struct work_struct *work) -{ - struct lpfc_queue *cq = container_of(work, struct lpfc_queue, irqwork); - - __lpfc_sli4_hba_process_cq(cq, LPFC_QUEUE_WORK); } /** @@ -15469,7 +15507,7 @@ lpfc_sli4_dly_hba_process_cq(struct work_struct *work) struct lpfc_queue *cq = container_of(to_delayed_work(work), struct lpfc_queue, sched_irqwork); - __lpfc_sli4_hba_process_cq(cq, LPFC_QUEUE_WORK); + __lpfc_sli4_hba_process_cq(cq); } /** @@ -15495,8 +15533,9 @@ lpfc_sli4_dly_hba_process_cq(struct work_struct *work) * and returns for these events. This function is called without any lock * held. It gets the hbalock to access and update SLI data structures. * - * This function returns IRQ_HANDLED when interrupt is handled else it - * returns IRQ_NONE. + * This function returns IRQ_HANDLED when interrupt is handled, IRQ_WAKE_THREAD + * when interrupt is scheduled to be handled from a threaded irq context, or + * else returns IRQ_NONE. **/ irqreturn_t lpfc_sli4_hba_intr_handler(int irq, void *dev_id) @@ -15505,8 +15544,8 @@ lpfc_sli4_hba_intr_handler(int irq, void *dev_id) struct lpfc_hba_eq_hdl *hba_eq_hdl; struct lpfc_queue *fpeq; unsigned long iflag; - int ecount = 0; int hba_eqidx; + int ecount = 0; struct lpfc_eq_intr_info *eqi; /* Get the driver's phba structure from the dev_id */ @@ -15535,30 +15574,41 @@ lpfc_sli4_hba_intr_handler(int irq, void *dev_id) return IRQ_NONE; } - eqi = this_cpu_ptr(phba->sli4_hba.eq_info); - eqi->icnt++; - - fpeq->last_cpu = raw_smp_processor_id(); + switch (fpeq->poll_mode) { + case LPFC_THREADED_IRQ: + /* CGN mgmt is mutually exclusive from irq processing */ + if (phba->cmf_active_mode == LPFC_CFG_OFF) + return IRQ_WAKE_THREAD; + fallthrough; + case LPFC_QUEUE_WORK: + default: + eqi = this_cpu_ptr(phba->sli4_hba.eq_info); + eqi->icnt++; - if (eqi->icnt > LPFC_EQD_ISR_TRIGGER && - fpeq->q_flag & HBA_EQ_DELAY_CHK && - phba->cfg_auto_imax && - fpeq->q_mode != LPFC_MAX_AUTO_EQ_DELAY && - phba->sli.sli_flag & LPFC_SLI_USE_EQDR) - lpfc_sli4_mod_hba_eq_delay(phba, fpeq, LPFC_MAX_AUTO_EQ_DELAY); + fpeq->last_cpu = raw_smp_processor_id(); - /* process and rearm the EQ */ - ecount = lpfc_sli4_process_eq(phba, fpeq, LPFC_QUEUE_REARM); + if (eqi->icnt > LPFC_EQD_ISR_TRIGGER && + fpeq->q_flag & HBA_EQ_DELAY_CHK && + phba->cfg_auto_imax && + fpeq->q_mode != LPFC_MAX_AUTO_EQ_DELAY && + phba->sli.sli_flag & LPFC_SLI_USE_EQDR) + lpfc_sli4_mod_hba_eq_delay(phba, fpeq, + LPFC_MAX_AUTO_EQ_DELAY); - if (unlikely(ecount == 0)) { - fpeq->EQ_no_entry++; - if (phba->intr_type == MSIX) - /* MSI-X treated interrupt served as no EQ share INT */ - lpfc_printf_log(phba, KERN_WARNING, LOG_SLI, - "0358 MSI-X interrupt with no EQE\n"); - else - /* Non MSI-X treated on interrupt as EQ share INT */ - return IRQ_NONE; + /* process and rearm the EQ */ + ecount = lpfc_sli4_process_eq(phba, fpeq, LPFC_QUEUE_REARM, + LPFC_QUEUE_WORK); + + if (unlikely(ecount == 0)) { + fpeq->EQ_no_entry++; + if (phba->intr_type == MSIX) + /* MSI-X treated interrupt served as no EQ share INT */ + lpfc_printf_log(phba, KERN_WARNING, LOG_SLI, + "0358 MSI-X interrupt with no EQE\n"); + else + /* Non MSI-X treated on interrupt as EQ share INT */ + return IRQ_NONE; + } } return IRQ_HANDLED; @@ -16115,13 +16165,69 @@ lpfc_eq_create(struct lpfc_hba *phba, struct lpfc_queue *eq, uint32_t imax) return status; } -static int lpfc_cq_poll_hdler(struct irq_poll *iop, int budget) +/** + * lpfc_sli4_hba_intr_handler_th - SLI4 HBA threaded interrupt handler + * @irq: Interrupt number. + * @dev_id: The device context pointer. + * + * This routine is a mirror of lpfc_sli4_hba_intr_handler, but executed within + * threaded irq context. + * + * Returns + * IRQ_HANDLED - interrupt is handled + * IRQ_NONE - otherwise + **/ +irqreturn_t lpfc_sli4_hba_intr_handler_th(int irq, void *dev_id) { - struct lpfc_queue *cq = container_of(iop, struct lpfc_queue, iop); + struct lpfc_hba *phba; + struct lpfc_hba_eq_hdl *hba_eq_hdl; + struct lpfc_queue *fpeq; + int ecount = 0; + int hba_eqidx; + struct lpfc_eq_intr_info *eqi; - __lpfc_sli4_hba_process_cq(cq, LPFC_IRQ_POLL); + /* Get the driver's phba structure from the dev_id */ + hba_eq_hdl = (struct lpfc_hba_eq_hdl *)dev_id; + phba = hba_eq_hdl->phba; + hba_eqidx = hba_eq_hdl->idx; - return 1; + if (unlikely(!phba)) + return IRQ_NONE; + if (unlikely(!phba->sli4_hba.hdwq)) + return IRQ_NONE; + + /* Get to the EQ struct associated with this vector */ + fpeq = phba->sli4_hba.hba_eq_hdl[hba_eqidx].eq; + if (unlikely(!fpeq)) + return IRQ_NONE; + + eqi = per_cpu_ptr(phba->sli4_hba.eq_info, raw_smp_processor_id()); + eqi->icnt++; + + fpeq->last_cpu = raw_smp_processor_id(); + + if (eqi->icnt > LPFC_EQD_ISR_TRIGGER && + fpeq->q_flag & HBA_EQ_DELAY_CHK && + phba->cfg_auto_imax && + fpeq->q_mode != LPFC_MAX_AUTO_EQ_DELAY && + phba->sli.sli_flag & LPFC_SLI_USE_EQDR) + lpfc_sli4_mod_hba_eq_delay(phba, fpeq, LPFC_MAX_AUTO_EQ_DELAY); + + /* process and rearm the EQ */ + ecount = lpfc_sli4_process_eq(phba, fpeq, LPFC_QUEUE_REARM, + LPFC_THREADED_IRQ); + + if (unlikely(ecount == 0)) { + fpeq->EQ_no_entry++; + if (phba->intr_type == MSIX) + /* MSI-X treated interrupt served as no EQ share INT */ + lpfc_printf_log(phba, KERN_WARNING, LOG_SLI, + "3358 MSI-X interrupt with no EQE\n"); + else + /* Non MSI-X treated on interrupt as EQ share INT */ + return IRQ_NONE; + } + return IRQ_HANDLED; } /** @@ -16265,8 +16371,6 @@ lpfc_cq_create(struct lpfc_hba *phba, struct lpfc_queue *cq, if (cq->queue_id > phba->sli4_hba.cq_max) phba->sli4_hba.cq_max = cq->queue_id; - - irq_poll_init(&cq->iop, LPFC_IRQ_POLL_WEIGHT, lpfc_cq_poll_hdler); out: mempool_free(mbox, phba->mbox_mem_pool); return status; @@ -20696,23 +20800,23 @@ lpfc_log_fw_write_cmpl(struct lpfc_hba *phba, u32 shdr_status, if (shdr_add_status == LPFC_ADD_STATUS_INCOMPAT_OBJ) { switch (shdr_add_status_2) { case LPFC_ADD_STATUS_2_INCOMPAT_FLASH: - lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX | LOG_SLI, - "4199 Firmware write failed: " - "image incompatible with flash x%02x\n", - phba->sli4_hba.flash_id); + lpfc_log_msg(phba, KERN_WARNING, LOG_MBOX | LOG_SLI, + "4199 Firmware write failed: " + "image incompatible with flash x%02x\n", + phba->sli4_hba.flash_id); break; case LPFC_ADD_STATUS_2_INCORRECT_ASIC: - lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX | LOG_SLI, - "4200 Firmware write failed: " - "image incompatible with ASIC " - "architecture x%02x\n", - phba->sli4_hba.asic_rev); + lpfc_log_msg(phba, KERN_WARNING, LOG_MBOX | LOG_SLI, + "4200 Firmware write failed: " + "image incompatible with ASIC " + "architecture x%02x\n", + phba->sli4_hba.asic_rev); break; default: - lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX | LOG_SLI, - "4210 Firmware write failed: " - "add_status_2 x%02x\n", - shdr_add_status_2); + lpfc_log_msg(phba, KERN_WARNING, LOG_MBOX | LOG_SLI, + "4210 Firmware write failed: " + "add_status_2 x%02x\n", + shdr_add_status_2); break; } } else if (!shdr_status && !shdr_add_status) { @@ -20725,26 +20829,26 @@ lpfc_log_fw_write_cmpl(struct lpfc_hba *phba, u32 shdr_status, switch (shdr_change_status) { case (LPFC_CHANGE_STATUS_PHYS_DEV_RESET): - lpfc_printf_log(phba, KERN_INFO, LOG_MBOX | LOG_SLI, - "3198 Firmware write complete: System " - "reboot required to instantiate\n"); + lpfc_log_msg(phba, KERN_NOTICE, LOG_MBOX | LOG_SLI, + "3198 Firmware write complete: System " + "reboot required to instantiate\n"); break; case (LPFC_CHANGE_STATUS_FW_RESET): - lpfc_printf_log(phba, KERN_INFO, LOG_MBOX | LOG_SLI, - "3199 Firmware write complete: " - "Firmware reset required to " - "instantiate\n"); + lpfc_log_msg(phba, KERN_NOTICE, LOG_MBOX | LOG_SLI, + "3199 Firmware write complete: " + "Firmware reset required to " + "instantiate\n"); break; case (LPFC_CHANGE_STATUS_PORT_MIGRATION): - lpfc_printf_log(phba, KERN_INFO, LOG_MBOX | LOG_SLI, - "3200 Firmware write complete: Port " - "Migration or PCI Reset required to " - "instantiate\n"); + lpfc_log_msg(phba, KERN_NOTICE, LOG_MBOX | LOG_SLI, + "3200 Firmware write complete: Port " + "Migration or PCI Reset required to " + "instantiate\n"); break; case (LPFC_CHANGE_STATUS_PCI_RESET): - lpfc_printf_log(phba, KERN_INFO, LOG_MBOX | LOG_SLI, - "3201 Firmware write complete: PCI " - "Reset required to instantiate\n"); + lpfc_log_msg(phba, KERN_NOTICE, LOG_MBOX | LOG_SLI, + "3201 Firmware write complete: PCI " + "Reset required to instantiate\n"); break; default: break; diff --git a/drivers/scsi/lpfc/lpfc_sli4.h b/drivers/scsi/lpfc/lpfc_sli4.h index 2a0864e6d7cd7844372ab1fcdfff40de5707b33e..2541a8fba093fa0e0263b211fa7cd29c183d8f65 100644 --- a/drivers/scsi/lpfc/lpfc_sli4.h +++ b/drivers/scsi/lpfc/lpfc_sli4.h @@ -140,7 +140,7 @@ struct lpfc_rqb { enum lpfc_poll_mode { LPFC_QUEUE_WORK, - LPFC_IRQ_POLL + LPFC_THREADED_IRQ, }; struct lpfc_idle_stat { @@ -279,8 +279,6 @@ struct lpfc_queue { struct list_head _poll_list; void **q_pgs; /* array to index entries per page */ -#define LPFC_IRQ_POLL_WEIGHT 256 - struct irq_poll iop; enum lpfc_poll_mode poll_mode; }; diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h index c97411b0992e350ef356e59bd52171ee971c8b4f..6f35491aed0fd1615a50743dbf8e229fb3f86c16 100644 --- a/drivers/scsi/lpfc/lpfc_version.h +++ b/drivers/scsi/lpfc/lpfc_version.h @@ -20,7 +20,7 @@ * included with this package. * *******************************************************************/ -#define LPFC_DRIVER_VERSION "14.2.0.11" +#define LPFC_DRIVER_VERSION "14.2.0.13" #define LPFC_DRIVER_NAME "lpfc" /* Used for SLI 2/3 */ diff --git a/drivers/scsi/megaraid/Kconfig.megaraid b/drivers/scsi/megaraid/Kconfig.megaraid index 2adc2afd9f91c96ab933f2bde5716bff05c363de..3f2ce1eb081c4ebab3c9a5eca15648b3a1a788dc 100644 --- a/drivers/scsi/megaraid/Kconfig.megaraid +++ b/drivers/scsi/megaraid/Kconfig.megaraid @@ -1,13 +1,13 @@ # SPDX-License-Identifier: GPL-2.0-only config MEGARAID_NEWGEN bool "LSI Logic New Generation RAID Device Drivers" - depends on PCI && SCSI + depends on PCI && HAS_IOPORT && SCSI help LSI Logic RAID Device Drivers config MEGARAID_MM tristate "LSI Logic Management Module (New Driver)" - depends on PCI && SCSI && MEGARAID_NEWGEN + depends on PCI && HAS_IOPORT && SCSI && MEGARAID_NEWGEN help Management Module provides ioctl, sysfs support for LSI Logic RAID controllers. @@ -67,7 +67,7 @@ config MEGARAID_MAILBOX config MEGARAID_LEGACY tristate "LSI Logic Legacy MegaRAID Driver" - depends on PCI && SCSI + depends on PCI && HAS_IOPORT && SCSI help This driver supports the LSI MegaRAID 418, 428, 438, 466, 762, 490 and 467 SCSI host adapters. This driver also support the all U320 diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h index 63bac3684c197ddf7b20a3844d429cb77c838a8c..3554f6b07727324ac5a8259be01bd4ecb8db6565 100644 --- a/drivers/scsi/megaraid/megaraid_sas.h +++ b/drivers/scsi/megaraid/megaraid_sas.h @@ -1722,11 +1722,9 @@ struct megasas_sge_skinny { } __packed; union megasas_sgl { - - struct megasas_sge32 sge32[1]; - struct megasas_sge64 sge64[1]; - struct megasas_sge_skinny sge_skinny[1]; - + DECLARE_FLEX_ARRAY(struct megasas_sge32, sge32); + DECLARE_FLEX_ARRAY(struct megasas_sge64, sge64); + DECLARE_FLEX_ARRAY(struct megasas_sge_skinny, sge_skinny); } __attribute__ ((packed)); struct megasas_header { diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index 317c944c68e385168c0afd7cac69f7d8b3591a5a..050eed8e26846f4855c6fe0953240b2e3627d1d8 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c @@ -5153,8 +5153,8 @@ static void megasas_update_ext_vd_details(struct megasas_instance *instance) fusion->max_map_sz = ventura_map_sz; } else { fusion->old_map_sz = - struct_size((struct MR_FW_RAID_MAP *)0, ldSpanMap, - instance->fw_supported_vd_count); + struct_size_t(struct MR_FW_RAID_MAP, ldSpanMap, + instance->fw_supported_vd_count); fusion->new_map_sz = sizeof(struct MR_FW_RAID_MAP_EXT); fusion->max_map_sz = @@ -5789,8 +5789,8 @@ megasas_setup_jbod_map(struct megasas_instance *instance) struct fusion_context *fusion = instance->ctrl_context; size_t pd_seq_map_sz; - pd_seq_map_sz = struct_size((struct MR_PD_CFG_SEQ_NUM_SYNC *)0, seq, - MAX_PHYSICAL_DEVICES); + pd_seq_map_sz = struct_size_t(struct MR_PD_CFG_SEQ_NUM_SYNC, seq, + MAX_PHYSICAL_DEVICES); instance->use_seqnum_jbod_fp = instance->support_seqnum_jbod_fp; @@ -8033,8 +8033,8 @@ static void megasas_detach_one(struct pci_dev *pdev) if (instance->adapter_type != MFI_SERIES) { megasas_release_fusion(instance); pd_seq_map_sz = - struct_size((struct MR_PD_CFG_SEQ_NUM_SYNC *)0, - seq, MAX_PHYSICAL_DEVICES); + struct_size_t(struct MR_PD_CFG_SEQ_NUM_SYNC, + seq, MAX_PHYSICAL_DEVICES); for (i = 0; i < 2 ; i++) { if (fusion->ld_map[i]) dma_free_coherent(&instance->pdev->dev, diff --git a/drivers/scsi/megaraid/megaraid_sas_fp.c b/drivers/scsi/megaraid/megaraid_sas_fp.c index 4463a538102ad6d7fb1b1d266ae8a3273d38a173..b8b388a4e28ff20adc42257bd7a1cf3e9ca89b1f 100644 --- a/drivers/scsi/megaraid/megaraid_sas_fp.c +++ b/drivers/scsi/megaraid/megaraid_sas_fp.c @@ -326,9 +326,9 @@ u8 MR_ValidateMapInfo(struct megasas_instance *instance, u64 map_id) else if (instance->supportmax256vd) expected_size = sizeof(struct MR_FW_RAID_MAP_EXT); else - expected_size = struct_size((struct MR_FW_RAID_MAP *)0, - ldSpanMap, - le16_to_cpu(pDrvRaidMap->ldCount)); + expected_size = struct_size_t(struct MR_FW_RAID_MAP, + ldSpanMap, + le16_to_cpu(pDrvRaidMap->ldCount)); if (le32_to_cpu(pDrvRaidMap->totalSize) != expected_size) { dev_dbg(&instance->pdev->dev, "megasas: map info structure size 0x%x", diff --git a/drivers/scsi/mpi3mr/mpi3mr.h b/drivers/scsi/mpi3mr/mpi3mr.h index dfe6b87fe2885eed239923b76cc5b38d63bfcb5c..0afb687402e15cf02cf515ef5687eeacfeab6920 100644 --- a/drivers/scsi/mpi3mr/mpi3mr.h +++ b/drivers/scsi/mpi3mr/mpi3mr.h @@ -1133,18 +1133,18 @@ struct mpi3mr_ioc { u32 chain_buf_count; struct dma_pool *chain_buf_pool; struct chain_element *chain_sgl_list; - void *chain_bitmap; + unsigned long *chain_bitmap; spinlock_t chain_buf_lock; struct mpi3mr_drv_cmd bsg_cmds; struct mpi3mr_drv_cmd host_tm_cmds; struct mpi3mr_drv_cmd dev_rmhs_cmds[MPI3MR_NUM_DEVRMCMD]; struct mpi3mr_drv_cmd evtack_cmds[MPI3MR_NUM_EVTACKCMD]; - void *devrem_bitmap; + unsigned long *devrem_bitmap; u16 dev_handle_bitmap_bits; - void *removepend_bitmap; + unsigned long *removepend_bitmap; struct list_head delayed_rmhs_list; - void *evtack_cmds_bitmap; + unsigned long *evtack_cmds_bitmap; struct list_head delayed_evtack_cmds_list; u32 ts_update_counter; diff --git a/drivers/scsi/mpi3mr/mpi3mr_fw.c b/drivers/scsi/mpi3mr/mpi3mr_fw.c index 075fa67e95eebe9c20b83c6b059c328622c94412..5fa07d6ee5b8ee5b52b77c826577b66f98c094b2 100644 --- a/drivers/scsi/mpi3mr/mpi3mr_fw.c +++ b/drivers/scsi/mpi3mr/mpi3mr_fw.c @@ -402,6 +402,11 @@ static void mpi3mr_process_admin_reply_desc(struct mpi3mr_ioc *mrioc, memcpy((u8 *)cmdptr->reply, (u8 *)def_reply, mrioc->reply_sz); } + if (sense_buf && cmdptr->sensebuf) { + cmdptr->is_sense = 1; + memcpy(cmdptr->sensebuf, sense_buf, + MPI3MR_SENSE_BUF_SZ); + } if (cmdptr->is_waiting) { complete(&cmdptr->done); cmdptr->is_waiting = 0; @@ -1134,7 +1139,7 @@ static int mpi3mr_issue_and_process_mur(struct mpi3mr_ioc *mrioc, static int mpi3mr_revalidate_factsdata(struct mpi3mr_ioc *mrioc) { - void *removepend_bitmap; + unsigned long *removepend_bitmap; if (mrioc->facts.reply_sz > mrioc->reply_sz) { ioc_err(mrioc, diff --git a/drivers/scsi/mpi3mr/mpi3mr_transport.c b/drivers/scsi/mpi3mr/mpi3mr_transport.c index 4d84d5bd173f5597ebf765a65f3cc66c7327aefd..82b55e95573041387395a3d104df6d4ce5ac058a 100644 --- a/drivers/scsi/mpi3mr/mpi3mr_transport.c +++ b/drivers/scsi/mpi3mr/mpi3mr_transport.c @@ -2058,7 +2058,7 @@ int mpi3mr_expander_add(struct mpi3mr_ioc *mrioc, u16 handle) sas_expander = kzalloc(sizeof(struct mpi3mr_sas_node), GFP_KERNEL); if (!sas_expander) - return -1; + return -ENOMEM; sas_expander->handle = handle; sas_expander->num_phys = expander_pg0.num_phys; diff --git a/drivers/scsi/mvsas/Kconfig b/drivers/scsi/mvsas/Kconfig index 79812b80743b9ab93188d842df6a59523f961a2e..5ac7fd593b17e5117950e6b22cd994f095a5c718 100644 --- a/drivers/scsi/mvsas/Kconfig +++ b/drivers/scsi/mvsas/Kconfig @@ -9,7 +9,7 @@ config SCSI_MVSAS tristate "Marvell 88SE64XX/88SE94XX SAS/SATA support" - depends on PCI + depends on PCI && HAS_IOPORT select SCSI_SAS_LIBSAS select FW_LOADER help diff --git a/drivers/scsi/ncr53c8xx.c b/drivers/scsi/ncr53c8xx.c index 4458449c960bf1c08e94a7d6fbf0f2f934f1d50e..35869b4f9329d3db6d9ecf6bee588ae655bdf97f 100644 --- a/drivers/scsi/ncr53c8xx.c +++ b/drivers/scsi/ncr53c8xx.c @@ -4555,7 +4555,7 @@ static void ncr_detach(struct ncb *np) char inst_name[16]; /* Local copy so we don't access np after freeing it! */ - strlcpy(inst_name, ncr_name(np), sizeof(inst_name)); + strscpy(inst_name, ncr_name(np), sizeof(inst_name)); printk("%s: releasing host resources\n", ncr_name(np)); diff --git a/drivers/scsi/pcmcia/Kconfig b/drivers/scsi/pcmcia/Kconfig index 9696b6b5591f26b9533e0d651e749beba98c88fc..449bd85db7bb4090fbcd55139ceedcf50968c1f7 100644 --- a/drivers/scsi/pcmcia/Kconfig +++ b/drivers/scsi/pcmcia/Kconfig @@ -12,6 +12,7 @@ if SCSI_LOWLEVEL_PCMCIA && SCSI && PCMCIA && m config PCMCIA_AHA152X tristate "Adaptec AHA152X PCMCIA support" + depends on HAS_IOPORT select SCSI_SPI_ATTRS help Say Y here if you intend to attach this type of PCMCIA SCSI host @@ -22,6 +23,7 @@ config PCMCIA_AHA152X config PCMCIA_FDOMAIN tristate "Future Domain PCMCIA support" + depends on HAS_IOPORT select SCSI_FDOMAIN help Say Y here if you intend to attach this type of PCMCIA SCSI host @@ -32,7 +34,7 @@ config PCMCIA_FDOMAIN config PCMCIA_NINJA_SCSI tristate "NinjaSCSI-3 / NinjaSCSI-32Bi (16bit) PCMCIA support" - depends on !64BIT || COMPILE_TEST + depends on (!64BIT || COMPILE_TEST) && HAS_IOPORT help If you intend to attach this type of PCMCIA SCSI host adapter to your computer, say Y here and read @@ -66,6 +68,7 @@ config PCMCIA_NINJA_SCSI config PCMCIA_QLOGIC tristate "Qlogic PCMCIA support" + depends on HAS_IOPORT help Say Y here if you intend to attach this type of PCMCIA SCSI host adapter to your computer. @@ -75,6 +78,7 @@ config PCMCIA_QLOGIC config PCMCIA_SYM53C500 tristate "Symbios 53c500 PCMCIA support" + depends on HAS_IOPORT help Say Y here if you have a New Media Bus Toaster or other PCMCIA SCSI adapter based on the Symbios 53c500 controller. diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c index 8b9490011e36515cbddc51143b6a5af0964aeade..2e886c1d867d4c66d387900b24baabb9b92d26c5 100644 --- a/drivers/scsi/pm8001/pm8001_init.c +++ b/drivers/scsi/pm8001/pm8001_init.c @@ -43,7 +43,8 @@ #include "pm8001_chips.h" #include "pm80xx_hwi.h" -static ulong logging_level = PM8001_FAIL_LOGGING | PM8001_IOERR_LOGGING; +static ulong logging_level = PM8001_FAIL_LOGGING | PM8001_IOERR_LOGGING | + PM8001_EVENT_LOGGING | PM8001_INIT_LOGGING; module_param(logging_level, ulong, 0644); MODULE_PARM_DESC(logging_level, " bits for enabling logging info."); @@ -666,7 +667,7 @@ static void pm8001_post_sas_ha_init(struct Scsi_Host *shost, * Currently we just set the fixed SAS address to our HBA, for manufacture, * it should read from the EEPROM */ -static void pm8001_init_sas_add(struct pm8001_hba_info *pm8001_ha) +static int pm8001_init_sas_add(struct pm8001_hba_info *pm8001_ha) { u8 i, j; u8 sas_add[8]; @@ -679,6 +680,12 @@ static void pm8001_init_sas_add(struct pm8001_hba_info *pm8001_ha) struct pm8001_ioctl_payload payload; u16 deviceid; int rc; + unsigned long time_remaining; + + if (PM8001_CHIP_DISP->fatal_errors(pm8001_ha)) { + pm8001_dbg(pm8001_ha, FAIL, "controller is in fatal error state\n"); + return -EIO; + } pci_read_config_word(pm8001_ha->pdev, PCI_DEVICE_ID, &deviceid); pm8001_ha->nvmd_completion = &completion; @@ -703,16 +710,23 @@ static void pm8001_init_sas_add(struct pm8001_hba_info *pm8001_ha) payload.offset = 0; payload.func_specific = kzalloc(payload.rd_length, GFP_KERNEL); if (!payload.func_specific) { - pm8001_dbg(pm8001_ha, INIT, "mem alloc fail\n"); - return; + pm8001_dbg(pm8001_ha, FAIL, "mem alloc fail\n"); + return -ENOMEM; } rc = PM8001_CHIP_DISP->get_nvmd_req(pm8001_ha, &payload); if (rc) { kfree(payload.func_specific); - pm8001_dbg(pm8001_ha, INIT, "nvmd failed\n"); - return; + pm8001_dbg(pm8001_ha, FAIL, "nvmd failed\n"); + return -EIO; + } + time_remaining = wait_for_completion_timeout(&completion, + msecs_to_jiffies(60*1000)); // 1 min + if (!time_remaining) { + kfree(payload.func_specific); + pm8001_dbg(pm8001_ha, FAIL, "get_nvmd_req timeout\n"); + return -EIO; } - wait_for_completion(&completion); + for (i = 0, j = 0; i <= 7; i++, j++) { if (pm8001_ha->chip_id == chip_8001) { @@ -751,6 +765,7 @@ static void pm8001_init_sas_add(struct pm8001_hba_info *pm8001_ha) memcpy(pm8001_ha->sas_addr, &pm8001_ha->phy[0].dev_sas_addr, SAS_ADDR_SIZE); #endif + return 0; } /* @@ -1166,7 +1181,8 @@ static int pm8001_pci_probe(struct pci_dev *pdev, pm80xx_set_thermal_config(pm8001_ha); } - pm8001_init_sas_add(pm8001_ha); + if (pm8001_init_sas_add(pm8001_ha)) + goto err_out_shost; /* phy setting support for motherboard controller */ rc = pm8001_configure_phy_settings(pm8001_ha); if (rc) diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c index e5673c774f66d7e3be116063fe4a8b31bf55be66..a5a31dfa451228722050c9722bcda79d0a26a813 100644 --- a/drivers/scsi/pm8001/pm8001_sas.c +++ b/drivers/scsi/pm8001/pm8001_sas.c @@ -167,6 +167,17 @@ int pm8001_phy_control(struct asd_sas_phy *sas_phy, enum phy_func func, pm8001_ha = sas_phy->ha->lldd_ha; phy = &pm8001_ha->phy[phy_id]; pm8001_ha->phy[phy_id].enable_completion = &completion; + + if (PM8001_CHIP_DISP->fatal_errors(pm8001_ha)) { + /* + * If the controller is in fatal error state, + * we will not get a response from the controller + */ + pm8001_dbg(pm8001_ha, FAIL, + "Phy control failed due to fatal errors\n"); + return -EFAULT; + } + switch (func) { case PHY_FUNC_SET_LINK_RATE: rates = funcdata; @@ -908,6 +919,17 @@ int pm8001_lu_reset(struct domain_device *dev, u8 *lun) struct pm8001_device *pm8001_dev = dev->lldd_dev; struct pm8001_hba_info *pm8001_ha = pm8001_find_ha_by_dev(dev); DECLARE_COMPLETION_ONSTACK(completion_setstate); + + if (PM8001_CHIP_DISP->fatal_errors(pm8001_ha)) { + /* + * If the controller is in fatal error state, + * we will not get a response from the controller + */ + pm8001_dbg(pm8001_ha, FAIL, + "LUN reset failed due to fatal errors\n"); + return rc; + } + if (dev_is_sata(dev)) { struct sas_phy *phy = sas_get_local_phy(dev); sas_execute_internal_abort_dev(dev, 0, NULL); diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h index dc1f4d958e03d6dc09ffe03c51fe165f5b7fc19f..953572fc0d9eb64e61b826b0d51d9e70523577b7 100644 --- a/drivers/scsi/pm8001/pm8001_sas.h +++ b/drivers/scsi/pm8001/pm8001_sas.h @@ -71,6 +71,7 @@ #define PM8001_DEV_LOGGING 0x80 /* development message logging */ #define PM8001_DEVIO_LOGGING 0x100 /* development io message logging */ #define PM8001_IOERR_LOGGING 0x200 /* development io err message logging */ +#define PM8001_EVENT_LOGGING 0x400 /* HW event logging */ #define pm8001_info(HBA, fmt, ...) \ pr_info("%s:: %s %d: " fmt, \ diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c index 9584cadc420137940c9033d115c89457c6365bfc..39a12ee94a72ffe68d2ff3784af12ae18da1a401 100644 --- a/drivers/scsi/pm8001/pm80xx_hwi.c +++ b/drivers/scsi/pm8001/pm80xx_hwi.c @@ -3239,9 +3239,9 @@ hw_event_sata_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb) struct pm8001_port *port = &pm8001_ha->port[port_id]; struct pm8001_phy *phy = &pm8001_ha->phy[phy_id]; unsigned long flags; - pm8001_dbg(pm8001_ha, DEVIO, - "port id %d, phy id %d link_rate %d portstate 0x%x\n", - port_id, phy_id, link_rate, portstate); + pm8001_dbg(pm8001_ha, EVENT, + "HW_EVENT_SATA_PHY_UP phyid:%#x port_id:%#x link_rate:%d portstate:%#x\n", + phy_id, port_id, link_rate, portstate); phy->port = port; port->port_id = port_id; @@ -3291,10 +3291,14 @@ hw_event_phy_down(struct pm8001_hba_info *pm8001_ha, void *piomb) phy->phy_attached = 0; switch (portstate) { case PORT_VALID: + pm8001_dbg(pm8001_ha, EVENT, + "HW_EVENT_PHY_DOWN phyid:%#x port_id:%#x portstate: PORT_VALID\n", + phy_id, port_id); break; case PORT_INVALID: - pm8001_dbg(pm8001_ha, MSG, " PortInvalid portID %d\n", - port_id); + pm8001_dbg(pm8001_ha, EVENT, + "HW_EVENT_PHY_DOWN phyid:%#x port_id:%#x portstate: PORT_INVALID\n", + phy_id, port_id); pm8001_dbg(pm8001_ha, MSG, " Last phy Down and port invalid\n"); if (port_sata) { @@ -3306,18 +3310,21 @@ hw_event_phy_down(struct pm8001_hba_info *pm8001_ha, void *piomb) sas_phy_disconnected(&phy->sas_phy); break; case PORT_IN_RESET: - pm8001_dbg(pm8001_ha, MSG, " Port In Reset portID %d\n", - port_id); + pm8001_dbg(pm8001_ha, EVENT, + "HW_EVENT_PHY_DOWN phyid:%#x port_id:%#x portstate: PORT_IN_RESET\n", + phy_id, port_id); break; case PORT_NOT_ESTABLISHED: - pm8001_dbg(pm8001_ha, MSG, - " Phy Down and PORT_NOT_ESTABLISHED\n"); + pm8001_dbg(pm8001_ha, EVENT, + "HW_EVENT_PHY_DOWN phyid:%#x port_id:%#x portstate: PORT_NOT_ESTABLISHED\n", + phy_id, port_id); port->port_attached = 0; break; case PORT_LOSTCOMM: - pm8001_dbg(pm8001_ha, MSG, " Phy Down and PORT_LOSTCOMM\n"); - pm8001_dbg(pm8001_ha, MSG, - " Last phy Down and port invalid\n"); + pm8001_dbg(pm8001_ha, EVENT, + "HW_EVENT_PHY_DOWN phyid:%#x port_id:%#x portstate: PORT_LOSTCOMM\n", + phy_id, port_id); + pm8001_dbg(pm8001_ha, MSG, " Last phy Down and port invalid\n"); if (port_sata) { port->port_attached = 0; phy->phy_type = 0; @@ -3328,9 +3335,9 @@ hw_event_phy_down(struct pm8001_hba_info *pm8001_ha, void *piomb) break; default: port->port_attached = 0; - pm8001_dbg(pm8001_ha, DEVIO, - " Phy Down and(default) = 0x%x\n", - portstate); + pm8001_dbg(pm8001_ha, EVENT, + "HW_EVENT_PHY_DOWN phyid:%#x port_id:%#x portstate:%#x\n", + phy_id, port_id, portstate); break; } @@ -3410,6 +3417,7 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb) u8 port_id = (u8)(lr_status_evt_portid & 0x000000FF); u8 phy_id = (u8)((phyid_npip_portstate & 0xFF0000) >> 16); + u8 portstate = (u8)(phyid_npip_portstate & 0x0000000F); u16 eventType = (u16)((lr_status_evt_portid & 0x00FFFF00) >> 8); u8 status = @@ -3425,26 +3433,29 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb) switch (eventType) { case HW_EVENT_SAS_PHY_UP: - pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_PHY_START_STATUS\n"); + pm8001_dbg(pm8001_ha, EVENT, + "HW_EVENT_SAS_PHY_UP phyid:%#x port_id:%#x\n", + phy_id, port_id); hw_event_sas_phy_up(pm8001_ha, piomb); break; case HW_EVENT_SATA_PHY_UP: - pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_SATA_PHY_UP\n"); hw_event_sata_phy_up(pm8001_ha, piomb); break; case HW_EVENT_SATA_SPINUP_HOLD: - pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_SATA_SPINUP_HOLD\n"); + pm8001_dbg(pm8001_ha, EVENT, + "HW_EVENT_SATA_SPINUP_HOLD phyid:%#x port_id:%#x\n", + phy_id, port_id); sas_notify_phy_event(&phy->sas_phy, PHYE_SPINUP_HOLD, GFP_ATOMIC); break; case HW_EVENT_PHY_DOWN: - pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_PHY_DOWN\n"); hw_event_phy_down(pm8001_ha, piomb); - phy->phy_attached = 0; phy->phy_state = PHY_LINK_DISABLE; break; case HW_EVENT_PORT_INVALID: - pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_PORT_INVALID\n"); + pm8001_dbg(pm8001_ha, EVENT, + "HW_EVENT_PORT_INVALID phyid:%#x port_id:%#x\n", + phy_id, port_id); sas_phy_disconnected(sas_phy); phy->phy_attached = 0; sas_notify_port_event(sas_phy, PORTE_LINK_RESET_ERR, @@ -3463,7 +3474,9 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb) GFP_ATOMIC); break; case HW_EVENT_PHY_ERROR: - pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_PHY_ERROR\n"); + pm8001_dbg(pm8001_ha, EVENT, + "HW_EVENT_PHY_ERROR phyid:%#x port_id:%#x\n", + phy_id, port_id); sas_phy_disconnected(&phy->sas_phy); phy->phy_attached = 0; sas_notify_phy_event(&phy->sas_phy, PHYE_OOB_ERROR, GFP_ATOMIC); @@ -3477,34 +3490,39 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb) GFP_ATOMIC); break; case HW_EVENT_LINK_ERR_INVALID_DWORD: - pm8001_dbg(pm8001_ha, MSG, - "HW_EVENT_LINK_ERR_INVALID_DWORD\n"); + pm8001_dbg(pm8001_ha, EVENT, + "HW_EVENT_LINK_ERR_INVALID_DWORD phyid:%#x port_id:%#x\n", + phy_id, port_id); pm80xx_hw_event_ack_req(pm8001_ha, 0, HW_EVENT_LINK_ERR_INVALID_DWORD, port_id, phy_id, 0, 0); break; case HW_EVENT_LINK_ERR_DISPARITY_ERROR: - pm8001_dbg(pm8001_ha, MSG, - "HW_EVENT_LINK_ERR_DISPARITY_ERROR\n"); + pm8001_dbg(pm8001_ha, EVENT, + "HW_EVENT_LINK_ERR_DISPARITY_ERROR phyid:%#x port_id:%#x\n", + phy_id, port_id); pm80xx_hw_event_ack_req(pm8001_ha, 0, HW_EVENT_LINK_ERR_DISPARITY_ERROR, port_id, phy_id, 0, 0); break; case HW_EVENT_LINK_ERR_CODE_VIOLATION: - pm8001_dbg(pm8001_ha, MSG, - "HW_EVENT_LINK_ERR_CODE_VIOLATION\n"); + pm8001_dbg(pm8001_ha, EVENT, + "HW_EVENT_LINK_ERR_CODE_VIOLATION phyid:%#x port_id:%#x\n", + phy_id, port_id); pm80xx_hw_event_ack_req(pm8001_ha, 0, HW_EVENT_LINK_ERR_CODE_VIOLATION, port_id, phy_id, 0, 0); break; case HW_EVENT_LINK_ERR_LOSS_OF_DWORD_SYNCH: - pm8001_dbg(pm8001_ha, MSG, - "HW_EVENT_LINK_ERR_LOSS_OF_DWORD_SYNCH\n"); + pm8001_dbg(pm8001_ha, EVENT, + "HW_EVENT_LINK_ERR_LOSS_OF_DWORD_SYNCH phyid:%#x port_id:%#x\n", + phy_id, port_id); pm80xx_hw_event_ack_req(pm8001_ha, 0, HW_EVENT_LINK_ERR_LOSS_OF_DWORD_SYNCH, port_id, phy_id, 0, 0); break; case HW_EVENT_MALFUNCTION: - pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_MALFUNCTION\n"); + pm8001_dbg(pm8001_ha, EVENT, + "HW_EVENT_MALFUNCTION phyid:%#x\n", phy_id); break; case HW_EVENT_BROADCAST_SES: pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_BROADCAST_SES\n"); @@ -3515,25 +3533,30 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb) GFP_ATOMIC); break; case HW_EVENT_INBOUND_CRC_ERROR: - pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_INBOUND_CRC_ERROR\n"); + pm8001_dbg(pm8001_ha, EVENT, + "HW_EVENT_INBOUND_CRC_ERROR phyid:%#x port_id:%#x\n", + phy_id, port_id); pm80xx_hw_event_ack_req(pm8001_ha, 0, HW_EVENT_INBOUND_CRC_ERROR, port_id, phy_id, 0, 0); break; case HW_EVENT_HARD_RESET_RECEIVED: - pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_HARD_RESET_RECEIVED\n"); + pm8001_dbg(pm8001_ha, EVENT, + "HW_EVENT_HARD_RESET_RECEIVED phyid:%#x\n", phy_id); sas_notify_port_event(sas_phy, PORTE_HARD_RESET, GFP_ATOMIC); break; case HW_EVENT_ID_FRAME_TIMEOUT: - pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_ID_FRAME_TIMEOUT\n"); + pm8001_dbg(pm8001_ha, EVENT, + "HW_EVENT_ID_FRAME_TIMEOUT phyid:%#x\n", phy_id); sas_phy_disconnected(sas_phy); phy->phy_attached = 0; sas_notify_port_event(sas_phy, PORTE_LINK_RESET_ERR, GFP_ATOMIC); break; case HW_EVENT_LINK_ERR_PHY_RESET_FAILED: - pm8001_dbg(pm8001_ha, MSG, - "HW_EVENT_LINK_ERR_PHY_RESET_FAILED\n"); + pm8001_dbg(pm8001_ha, EVENT, + "HW_EVENT_LINK_ERR_PHY_RESET_FAILED phyid:%#x port_id:%#x\n", + phy_id, port_id); pm80xx_hw_event_ack_req(pm8001_ha, 0, HW_EVENT_LINK_ERR_PHY_RESET_FAILED, port_id, phy_id, 0, 0); @@ -3543,13 +3566,16 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb) GFP_ATOMIC); break; case HW_EVENT_PORT_RESET_TIMER_TMO: - pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_PORT_RESET_TIMER_TMO\n"); + pm8001_dbg(pm8001_ha, EVENT, + "HW_EVENT_PORT_RESET_TIMER_TMO phyid:%#x port_id:%#x portstate:%#x\n", + phy_id, port_id, portstate); if (!pm8001_ha->phy[phy_id].reset_completion) { pm80xx_hw_event_ack_req(pm8001_ha, 0, HW_EVENT_PHY_DOWN, port_id, phy_id, 0, 0); } sas_phy_disconnected(sas_phy); phy->phy_attached = 0; + port->port_state = portstate; sas_notify_port_event(sas_phy, PORTE_LINK_RESET_ERR, GFP_ATOMIC); if (pm8001_ha->phy[phy_id].reset_completion) { @@ -3560,8 +3586,9 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb) } break; case HW_EVENT_PORT_RECOVERY_TIMER_TMO: - pm8001_dbg(pm8001_ha, MSG, - "HW_EVENT_PORT_RECOVERY_TIMER_TMO\n"); + pm8001_dbg(pm8001_ha, EVENT, + "HW_EVENT_PORT_RECOVERY_TIMER_TMO phyid:%#x port_id:%#x\n", + phy_id, port_id); pm80xx_hw_event_ack_req(pm8001_ha, 0, HW_EVENT_PORT_RECOVERY_TIMER_TMO, port_id, phy_id, 0, 0); @@ -3575,24 +3602,32 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb) } break; case HW_EVENT_PORT_RECOVER: - pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_PORT_RECOVER\n"); + pm8001_dbg(pm8001_ha, EVENT, + "HW_EVENT_PORT_RECOVER phyid:%#x port_id:%#x\n", + phy_id, port_id); hw_event_port_recover(pm8001_ha, piomb); break; case HW_EVENT_PORT_RESET_COMPLETE: - pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_PORT_RESET_COMPLETE\n"); + pm8001_dbg(pm8001_ha, EVENT, + "HW_EVENT_PORT_RESET_COMPLETE phyid:%#x port_id:%#x portstate:%#x\n", + phy_id, port_id, portstate); if (pm8001_ha->phy[phy_id].reset_completion) { pm8001_ha->phy[phy_id].port_reset_status = PORT_RESET_SUCCESS; complete(pm8001_ha->phy[phy_id].reset_completion); pm8001_ha->phy[phy_id].reset_completion = NULL; } + phy->phy_attached = 1; + phy->phy_state = PHY_STATE_LINK_UP_SPCV; + port->port_state = portstate; break; case EVENT_BROADCAST_ASYNCH_EVENT: pm8001_dbg(pm8001_ha, MSG, "EVENT_BROADCAST_ASYNCH_EVENT\n"); break; default: - pm8001_dbg(pm8001_ha, DEVIO, "Unknown event type 0x%x\n", - eventType); + pm8001_dbg(pm8001_ha, DEVIO, + "Unknown event portid:%d phyid:%d event:0x%x status:0x%x\n", + port_id, phy_id, eventType, status); break; } return 0; @@ -4726,6 +4761,9 @@ static int pm80xx_chip_reg_dev_req(struct pm8001_hba_info *pm8001_ha, memcpy(payload.sas_addr, pm8001_dev->sas_device->sas_addr, SAS_ADDR_SIZE); + pm8001_dbg(pm8001_ha, INIT, + "register device req phy_id 0x%x port_id 0x%x\n", phy_id, + (port->port_id & 0xFF)); rc = pm8001_mpi_build_cmd(pm8001_ha, 0, opc, &payload, sizeof(payload), 0); if (rc) @@ -4815,7 +4853,7 @@ static void mpi_set_phy_profile_req(struct pm8001_hba_info *pm8001_ha, payload.tag = cpu_to_le32(tag); payload.ppc_phyid = cpu_to_le32(((operation & 0xF) << 8) | (phyid & 0xFF)); - pm8001_dbg(pm8001_ha, INIT, + pm8001_dbg(pm8001_ha, DISC, " phy profile command for phy %x ,length is %d\n", le32_to_cpu(payload.ppc_phyid), length); for (i = length; i < (length + PHY_DWORD_LENGTH - 1); i++) { diff --git a/drivers/scsi/qedf/qedf_main.c b/drivers/scsi/qedf/qedf_main.c index 3b64de81ea0d3393eba7e5ab6812de79d12f0ae7..2a31ddc99dde5becdd57278c02e776ca1d35f992 100644 --- a/drivers/scsi/qedf/qedf_main.c +++ b/drivers/scsi/qedf/qedf_main.c @@ -3041,9 +3041,8 @@ static int qedf_alloc_global_queues(struct qedf_ctx *qedf) * addresses of our queues */ if (!qedf->p_cpuq) { - status = -EINVAL; QEDF_ERR(&qedf->dbg_ctx, "p_cpuq is NULL.\n"); - goto mem_alloc_failure; + return -EINVAL; } qedf->global_queues = kzalloc((sizeof(struct global_queue *) diff --git a/drivers/scsi/qedi/qedi_main.c b/drivers/scsi/qedi/qedi_main.c index 45d35955418201386164d0d2161cf4774800de86..450522b204d62b9e78c29069f8a94e6417c50e6f 100644 --- a/drivers/scsi/qedi/qedi_main.c +++ b/drivers/scsi/qedi/qedi_main.c @@ -2593,7 +2593,7 @@ static int __qedi_probe(struct pci_dev *pdev, int mode) sp_params.drv_minor = QEDI_DRIVER_MINOR_VER; sp_params.drv_rev = QEDI_DRIVER_REV_VER; sp_params.drv_eng = QEDI_DRIVER_ENG_VER; - strlcpy(sp_params.name, "qedi iSCSI", QED_DRV_VER_STR_SIZE); + strscpy(sp_params.name, "qedi iSCSI", QED_DRV_VER_STR_SIZE); rc = qedi_ops->common->slowpath_start(qedi->cdev, &sp_params); if (rc) { QEDI_ERR(&qedi->dbg_ctx, "Cannot start slowpath\n"); diff --git a/drivers/scsi/qla2xxx/Kconfig b/drivers/scsi/qla2xxx/Kconfig index 802c373fd6d92aa54bc9498d86984e60adecd5af..a584708d3056f5ec9589d816440f5ee06a347676 100644 --- a/drivers/scsi/qla2xxx/Kconfig +++ b/drivers/scsi/qla2xxx/Kconfig @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0-only config SCSI_QLA_FC tristate "QLogic QLA2XXX Fibre Channel Support" - depends on PCI && SCSI + depends on PCI && HAS_IOPORT && SCSI depends on SCSI_FC_ATTRS depends on NVME_FC || !NVME_FC select FW_LOADER diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index 70cfc94c3d436a084136bd17136d50196d734add..b00222459607a847c9ea3f113b8a3dd7c677a4c5 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -2750,6 +2750,7 @@ static void qla2x00_terminate_rport_io(struct fc_rport *rport) { fc_port_t *fcport = *(fc_port_t **)rport->dd_data; + scsi_qla_host_t *vha; if (!fcport) return; @@ -2759,9 +2760,12 @@ qla2x00_terminate_rport_io(struct fc_rport *rport) if (test_bit(ABORT_ISP_ACTIVE, &fcport->vha->dpc_flags)) return; + vha = fcport->vha; if (unlikely(pci_channel_offline(fcport->vha->hw->pdev))) { qla2x00_abort_all_cmds(fcport->vha, DID_NO_CONNECT << 16); + qla2x00_eh_wait_for_pending_commands(fcport->vha, fcport->d_id.b24, + 0, WAIT_TARGET); return; } /* @@ -2786,6 +2790,15 @@ qla2x00_terminate_rport_io(struct fc_rport *rport) qla2x00_port_logout(fcport->vha, fcport); } } + + /* check for any straggling io left behind */ + if (qla2x00_eh_wait_for_pending_commands(fcport->vha, fcport->d_id.b24, 0, WAIT_TARGET)) { + ql_log(ql_log_warn, vha, 0x300b, + "IO not return. Resetting. \n"); + set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); + qla2xxx_wake_dpc(vha); + qla2x00_wait_for_chip_reset(vha); + } } static int diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c index dba7bba788d769cf0b4b60946e0ed0b38837940f..19bb64bdd88b1931f92df08456001b17efb270f7 100644 --- a/drivers/scsi/qla2xxx/qla_bsg.c +++ b/drivers/scsi/qla2xxx/qla_bsg.c @@ -283,6 +283,10 @@ qla2x00_process_els(struct bsg_job *bsg_job) if (bsg_request->msgcode == FC_BSG_RPT_ELS) { rport = fc_bsg_to_rport(bsg_job); + if (!rport) { + rval = -ENOMEM; + goto done; + } fcport = *(fc_port_t **) rport->dd_data; host = rport_to_shost(rport); vha = shost_priv(host); @@ -2992,6 +2996,8 @@ qla24xx_bsg_request(struct bsg_job *bsg_job) if (bsg_request->msgcode == FC_BSG_RPT_ELS) { rport = fc_bsg_to_rport(bsg_job); + if (!rport) + return ret; host = rport_to_shost(rport); vha = shost_priv(host); } else { diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 84aa3571be6d4de1f8e7cf7e2e0a011a6c4b6fd1..4ae38305c15a115730dfdf4615a21aa2c11f49f9 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -465,6 +465,15 @@ static inline be_id_t port_id_to_be_id(port_id_t port_id) return res; } +struct tmf_arg { + struct qla_qpair *qpair; + struct fc_port *fcport; + struct scsi_qla_host *vha; + u64 lun; + u32 flags; + uint8_t modifier; +}; + struct els_logo_payload { uint8_t opcode; uint8_t rsvd[3]; @@ -544,6 +553,10 @@ struct srb_iocb { uint32_t data; struct completion comp; __le16 comp_status; + + uint8_t modifier; + uint8_t vp_index; + uint16_t loop_id; } tmf; struct { #define SRB_FXDISC_REQ_DMA_VALID BIT_0 @@ -647,6 +660,7 @@ struct srb_iocb { #define SRB_SA_UPDATE 25 #define SRB_ELS_CMD_HST_NOLOGIN 26 #define SRB_SA_REPLACE 27 +#define SRB_MARKER 28 struct qla_els_pt_arg { u8 els_opcode; @@ -689,7 +703,6 @@ typedef struct srb { struct iocb_resource iores; struct kref cmd_kref; /* need to migrate ref_count over to this */ void *priv; - wait_queue_head_t nvme_ls_waitq; struct fc_port *fcport; struct scsi_qla_host *vha; unsigned int start_timer:1; @@ -2528,6 +2541,7 @@ enum rscn_addr_format { typedef struct fc_port { struct list_head list; struct scsi_qla_host *vha; + struct list_head tmf_pending; unsigned int conf_compl_supported:1; unsigned int deleted:2; @@ -2548,6 +2562,8 @@ typedef struct fc_port { unsigned int do_prli_nvme:1; uint8_t nvme_flag; + uint8_t active_tmf; +#define MAX_ACTIVE_TMF 8 uint8_t node_name[WWN_SIZE]; uint8_t port_name[WWN_SIZE]; @@ -3157,12 +3173,12 @@ struct ct_sns_gpnft_rsp { uint8_t vendor_unique; }; /* Assume the largest number of targets for the union */ - struct ct_sns_gpn_ft_data { + DECLARE_FLEX_ARRAY(struct ct_sns_gpn_ft_data { u8 control_byte; u8 port_id[3]; u32 reserved; u8 port_name[8]; - } entries[1]; + }, entries); }; /* CT command response */ @@ -4446,7 +4462,6 @@ struct qla_hw_data { /* n2n */ struct fc_els_flogi plogi_els_payld; -#define LOGIN_TEMPLATE_SIZE (sizeof(struct fc_els_flogi) - 4) void *swl; @@ -5499,4 +5514,8 @@ struct ql_vnd_tgt_stats_resp { _fp->disc_state, _fp->scan_state, _fp->loop_id, _fp->deleted, \ _fp->flags +#define TMF_NOT_READY(_fcport) \ + (!_fcport || IS_SESSION_DELETED(_fcport) || atomic_read(&_fcport->state) != FCS_ONLINE || \ + !_fcport->vha->hw->flags.fw_started) + #endif diff --git a/drivers/scsi/qla2xxx/qla_edif.c b/drivers/scsi/qla2xxx/qla_edif.c index ec0e20255bd3b8bfadb8db5fb4ab5aa1c15d0156..26e6b3e3af4317ca088941bc5bab37c15aebfd32 100644 --- a/drivers/scsi/qla2xxx/qla_edif.c +++ b/drivers/scsi/qla2xxx/qla_edif.c @@ -2361,8 +2361,8 @@ qla24xx_issue_sa_replace_iocb(scsi_qla_host_t *vha, struct qla_work_evt *e) if (!sa_ctl) { ql_dbg(ql_dbg_edif, vha, 0x70e6, "sa_ctl allocation failed\n"); - rval = -ENOMEM; - goto done; + rval = -ENOMEM; + return rval; } fcport = sa_ctl->fcport; diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index 391c8b3623a698dea0bf65570f201fb5f9db4fb6..ba7831f24734f176de8d6575d5d42aa5d9f0478d 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -69,7 +69,7 @@ extern int qla2x00_async_logout(struct scsi_qla_host *, fc_port_t *); extern int qla2x00_async_prlo(struct scsi_qla_host *, fc_port_t *); extern int qla2x00_async_adisc(struct scsi_qla_host *, fc_port_t *, uint16_t *); -extern int qla2x00_async_tm_cmd(fc_port_t *, uint32_t, uint32_t, uint32_t); +extern int qla2x00_async_tm_cmd(fc_port_t *, uint32_t, uint64_t, uint32_t); struct qla_work_evt *qla2x00_alloc_work(struct scsi_qla_host *, enum qla_work_type); extern int qla24xx_async_gnl(struct scsi_qla_host *, fc_port_t *); diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c index 4738f8935f7f9bb8c9dc04d7ecb2263f22f050b0..1cf9d200d563070b53d61df25ae7d5abee50b02a 100644 --- a/drivers/scsi/qla2xxx/qla_gs.c +++ b/drivers/scsi/qla2xxx/qla_gs.c @@ -3776,8 +3776,8 @@ int qla24xx_async_gpnft(scsi_qla_host_t *vha, u8 fc4_type, srb_t *sp) sp->u.iocb_cmd.u.ctarg.req_size = GPN_FT_REQ_SIZE; rspsz = sizeof(struct ct_sns_gpnft_rsp) + - ((vha->hw->max_fibre_devices - 1) * - sizeof(struct ct_sns_gpn_ft_data)); + vha->hw->max_fibre_devices * + sizeof(struct ct_sns_gpn_ft_data); sp->u.iocb_cmd.u.ctarg.rsp = dma_alloc_coherent(&vha->hw->pdev->dev, rspsz, diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 1a955c3ff3d6ce2732e3fd03e65203a5162dbc9a..367fba27fe699310f0b17f1b51a8e87a36522aac 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -1996,6 +1996,11 @@ qla2x00_tmf_iocb_timeout(void *data) int rc, h; unsigned long flags; + if (sp->type == SRB_MARKER) { + complete(&tmf->u.tmf.comp); + return; + } + rc = qla24xx_async_abort_cmd(sp, false); if (rc) { spin_lock_irqsave(sp->qpair->qp_lock_ptr, flags); @@ -2013,24 +2018,131 @@ qla2x00_tmf_iocb_timeout(void *data) } } +static void qla_marker_sp_done(srb_t *sp, int res) +{ + struct srb_iocb *tmf = &sp->u.iocb_cmd; + + if (res != QLA_SUCCESS) + ql_dbg(ql_dbg_taskm, sp->vha, 0x8004, + "Async-marker fail hdl=%x portid=%06x ctrl=%x lun=%lld qp=%d.\n", + sp->handle, sp->fcport->d_id.b24, sp->u.iocb_cmd.u.tmf.flags, + sp->u.iocb_cmd.u.tmf.lun, sp->qpair->id); + + sp->u.iocb_cmd.u.tmf.data = res; + complete(&tmf->u.tmf.comp); +} + +#define START_SP_W_RETRIES(_sp, _rval) \ +{\ + int cnt = 5; \ + do { \ + _rval = qla2x00_start_sp(_sp); \ + if (_rval == EAGAIN) \ + msleep(1); \ + else \ + break; \ + cnt--; \ + } while (cnt); \ +} + +/** + * qla26xx_marker: send marker IOCB and wait for the completion of it. + * @arg: pointer to argument list. + * It is assume caller will provide an fcport pointer and modifier + */ +static int +qla26xx_marker(struct tmf_arg *arg) +{ + struct scsi_qla_host *vha = arg->vha; + struct srb_iocb *tm_iocb; + srb_t *sp; + int rval = QLA_FUNCTION_FAILED; + fc_port_t *fcport = arg->fcport; + + if (TMF_NOT_READY(arg->fcport)) { + ql_dbg(ql_dbg_taskm, vha, 0x8039, + "FC port not ready for marker loop-id=%x portid=%06x modifier=%x lun=%lld qp=%d.\n", + fcport->loop_id, fcport->d_id.b24, + arg->modifier, arg->lun, arg->qpair->id); + return QLA_SUSPENDED; + } + + /* ref: INIT */ + sp = qla2xxx_get_qpair_sp(vha, arg->qpair, fcport, GFP_KERNEL); + if (!sp) + goto done; + + sp->type = SRB_MARKER; + sp->name = "marker"; + qla2x00_init_async_sp(sp, qla2x00_get_async_timeout(vha), qla_marker_sp_done); + sp->u.iocb_cmd.timeout = qla2x00_tmf_iocb_timeout; + + tm_iocb = &sp->u.iocb_cmd; + init_completion(&tm_iocb->u.tmf.comp); + tm_iocb->u.tmf.modifier = arg->modifier; + tm_iocb->u.tmf.lun = arg->lun; + tm_iocb->u.tmf.loop_id = fcport->loop_id; + tm_iocb->u.tmf.vp_index = vha->vp_idx; + + START_SP_W_RETRIES(sp, rval); + + ql_dbg(ql_dbg_taskm, vha, 0x8006, + "Async-marker hdl=%x loop-id=%x portid=%06x modifier=%x lun=%lld qp=%d rval %d.\n", + sp->handle, fcport->loop_id, fcport->d_id.b24, + arg->modifier, arg->lun, sp->qpair->id, rval); + + if (rval != QLA_SUCCESS) { + ql_log(ql_log_warn, vha, 0x8031, + "Marker IOCB send failure (%x).\n", rval); + goto done_free_sp; + } + + wait_for_completion(&tm_iocb->u.tmf.comp); + rval = tm_iocb->u.tmf.data; + + if (rval != QLA_SUCCESS) { + ql_log(ql_log_warn, vha, 0x8019, + "Marker failed hdl=%x loop-id=%x portid=%06x modifier=%x lun=%lld qp=%d rval %d.\n", + sp->handle, fcport->loop_id, fcport->d_id.b24, + arg->modifier, arg->lun, sp->qpair->id, rval); + } + +done_free_sp: + /* ref: INIT */ + kref_put(&sp->cmd_kref, qla2x00_sp_release); +done: + return rval; +} + static void qla2x00_tmf_sp_done(srb_t *sp, int res) { struct srb_iocb *tmf = &sp->u.iocb_cmd; + if (res) + tmf->u.tmf.data = res; complete(&tmf->u.tmf.comp); } -int -qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint32_t lun, - uint32_t tag) +static int +__qla2x00_async_tm_cmd(struct tmf_arg *arg) { - struct scsi_qla_host *vha = fcport->vha; + struct scsi_qla_host *vha = arg->vha; struct srb_iocb *tm_iocb; srb_t *sp; int rval = QLA_FUNCTION_FAILED; + fc_port_t *fcport = arg->fcport; + + if (TMF_NOT_READY(arg->fcport)) { + ql_dbg(ql_dbg_taskm, vha, 0x8032, + "FC port not ready for TM command loop-id=%x portid=%06x modifier=%x lun=%lld qp=%d.\n", + fcport->loop_id, fcport->d_id.b24, + arg->modifier, arg->lun, arg->qpair->id); + return QLA_SUSPENDED; + } + /* ref: INIT */ - sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL); + sp = qla2xxx_get_qpair_sp(vha, arg->qpair, fcport, GFP_KERNEL); if (!sp) goto done; @@ -2043,15 +2155,16 @@ qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint32_t lun, tm_iocb = &sp->u.iocb_cmd; init_completion(&tm_iocb->u.tmf.comp); - tm_iocb->u.tmf.flags = flags; - tm_iocb->u.tmf.lun = lun; + tm_iocb->u.tmf.flags = arg->flags; + tm_iocb->u.tmf.lun = arg->lun; + + START_SP_W_RETRIES(sp, rval); ql_dbg(ql_dbg_taskm, vha, 0x802f, - "Async-tmf hdl=%x loop-id=%x portid=%02x%02x%02x.\n", - sp->handle, fcport->loop_id, fcport->d_id.b.domain, - fcport->d_id.b.area, fcport->d_id.b.al_pa); + "Async-tmf hdl=%x loop-id=%x portid=%06x ctrl=%x lun=%lld qp=%d rval=%x.\n", + sp->handle, fcport->loop_id, fcport->d_id.b24, + arg->flags, arg->lun, sp->qpair->id, rval); - rval = qla2x00_start_sp(sp); if (rval != QLA_SUCCESS) goto done_free_sp; wait_for_completion(&tm_iocb->u.tmf.comp); @@ -2063,15 +2176,8 @@ qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint32_t lun, "TM IOCB failed (%x).\n", rval); } - if (!test_bit(UNLOADING, &vha->dpc_flags) && !IS_QLAFX00(vha->hw)) { - flags = tm_iocb->u.tmf.flags; - lun = (uint16_t)tm_iocb->u.tmf.lun; - - /* Issue Marker IOCB */ - qla2x00_marker(vha, vha->hw->base_qpair, - fcport->loop_id, lun, - flags == TCF_LUN_RESET ? MK_SYNC_ID_LUN : MK_SYNC_ID); - } + if (!test_bit(UNLOADING, &vha->dpc_flags) && !IS_QLAFX00(vha->hw)) + rval = qla26xx_marker(arg); done_free_sp: /* ref: INIT */ @@ -2080,6 +2186,115 @@ qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint32_t lun, return rval; } +static void qla_put_tmf(fc_port_t *fcport) +{ + struct scsi_qla_host *vha = fcport->vha; + struct qla_hw_data *ha = vha->hw; + unsigned long flags; + + spin_lock_irqsave(&ha->tgt.sess_lock, flags); + fcport->active_tmf--; + spin_unlock_irqrestore(&ha->tgt.sess_lock, flags); +} + +static +int qla_get_tmf(fc_port_t *fcport) +{ + struct scsi_qla_host *vha = fcport->vha; + struct qla_hw_data *ha = vha->hw; + unsigned long flags; + int rc = 0; + LIST_HEAD(tmf_elem); + + spin_lock_irqsave(&ha->tgt.sess_lock, flags); + list_add_tail(&tmf_elem, &fcport->tmf_pending); + + while (fcport->active_tmf >= MAX_ACTIVE_TMF) { + spin_unlock_irqrestore(&ha->tgt.sess_lock, flags); + + msleep(1); + + spin_lock_irqsave(&ha->tgt.sess_lock, flags); + if (TMF_NOT_READY(fcport)) { + ql_log(ql_log_warn, vha, 0x802c, + "Unable to acquire TM resource due to disruption.\n"); + rc = EIO; + break; + } + if (fcport->active_tmf < MAX_ACTIVE_TMF && + list_is_first(&tmf_elem, &fcport->tmf_pending)) + break; + } + + list_del(&tmf_elem); + + if (!rc) + fcport->active_tmf++; + + spin_unlock_irqrestore(&ha->tgt.sess_lock, flags); + + return rc; +} + +int +qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint64_t lun, + uint32_t tag) +{ + struct scsi_qla_host *vha = fcport->vha; + struct qla_qpair *qpair; + struct tmf_arg a; + int i, rval = QLA_SUCCESS; + + if (TMF_NOT_READY(fcport)) + return QLA_SUSPENDED; + + a.vha = fcport->vha; + a.fcport = fcport; + a.lun = lun; + if (flags & (TCF_LUN_RESET|TCF_ABORT_TASK_SET|TCF_CLEAR_TASK_SET|TCF_CLEAR_ACA)) { + a.modifier = MK_SYNC_ID_LUN; + + if (qla_get_tmf(fcport)) + return QLA_FUNCTION_FAILED; + } else { + a.modifier = MK_SYNC_ID; + } + + if (vha->hw->mqenable) { + for (i = 0; i < vha->hw->num_qpairs; i++) { + qpair = vha->hw->queue_pair_map[i]; + if (!qpair) + continue; + + if (TMF_NOT_READY(fcport)) { + ql_log(ql_log_warn, vha, 0x8026, + "Unable to send TM due to disruption.\n"); + rval = QLA_SUSPENDED; + break; + } + + a.qpair = qpair; + a.flags = flags|TCF_NOTMCMD_TO_TARGET; + rval = __qla2x00_async_tm_cmd(&a); + if (rval) + break; + } + } + + if (rval) + goto bailout; + + a.qpair = vha->hw->base_qpair; + a.flags = flags; + rval = __qla2x00_async_tm_cmd(&a); + +bailout: + if (a.modifier == MK_SYNC_ID_LUN) + qla_put_tmf(fcport); + + return rval; +} + int qla24xx_async_abort_command(srb_t *sp) { @@ -4861,7 +5076,7 @@ qla2x00_set_model_info(scsi_qla_host_t *vha, uint8_t *model, size_t len, if (use_tbl && ha->pdev->subsystem_vendor == PCI_VENDOR_ID_QLOGIC && index < QLA_MODEL_NAMES) - strlcpy(ha->model_desc, + strscpy(ha->model_desc, qla2x00_model_name[index * 2 + 1], sizeof(ha->model_desc)); } else { @@ -4869,14 +5084,14 @@ qla2x00_set_model_info(scsi_qla_host_t *vha, uint8_t *model, size_t len, if (use_tbl && ha->pdev->subsystem_vendor == PCI_VENDOR_ID_QLOGIC && index < QLA_MODEL_NAMES) { - strlcpy(ha->model_number, + strscpy(ha->model_number, qla2x00_model_name[index * 2], sizeof(ha->model_number)); - strlcpy(ha->model_desc, + strscpy(ha->model_desc, qla2x00_model_name[index * 2 + 1], sizeof(ha->model_desc)); } else { - strlcpy(ha->model_number, def, + strscpy(ha->model_number, def, sizeof(ha->model_number)); } } @@ -5291,6 +5506,7 @@ qla2x00_alloc_fcport(scsi_qla_host_t *vha, gfp_t flags) INIT_WORK(&fcport->reg_work, qla_register_fcport_fn); INIT_LIST_HEAD(&fcport->gnl_entry); INIT_LIST_HEAD(&fcport->list); + INIT_LIST_HEAD(&fcport->tmf_pending); INIT_LIST_HEAD(&fcport->sess_cmd_list); spin_lock_init(&fcport->sess_cmd_lock); @@ -5333,7 +5549,7 @@ static void qla_get_login_template(scsi_qla_host_t *vha) __be32 *q; memset(ha->init_cb, 0, ha->init_cb_size); - sz = min_t(int, sizeof(struct fc_els_flogi), ha->init_cb_size); + sz = min_t(int, sizeof(struct fc_els_csp), ha->init_cb_size); rval = qla24xx_get_port_login_templ(vha, ha->init_cb_dma, ha->init_cb, sz); if (rval != QLA_SUCCESS) { @@ -6004,7 +6220,6 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha) fc_port_t *fcport; uint16_t mb[MAILBOX_REGISTER_COUNT]; uint16_t loop_id; - LIST_HEAD(new_fcports); struct qla_hw_data *ha = vha->hw; int discovery_gen; @@ -8219,7 +8434,7 @@ qla24xx_load_risc_flash(scsi_qla_host_t *vha, uint32_t *srisc_addr, ql_dbg(ql_dbg_init, vha, 0x0163, "-> fwdt%u template allocate template %#x words...\n", j, risc_size); - fwdt->template = vmalloc(risc_size * sizeof(*dcode)); + fwdt->template = vmalloc_array(risc_size, sizeof(*dcode)); if (!fwdt->template) { ql_log(ql_log_warn, vha, 0x0164, "-> fwdt%u failed allocate template.\n", j); @@ -8474,7 +8689,7 @@ qla24xx_load_risc_blob(scsi_qla_host_t *vha, uint32_t *srisc_addr) ql_dbg(ql_dbg_init, vha, 0x0173, "-> fwdt%u template allocate template %#x words...\n", j, risc_size); - fwdt->template = vmalloc(risc_size * sizeof(*dcode)); + fwdt->template = vmalloc_array(risc_size, sizeof(*dcode)); if (!fwdt->template) { ql_log(ql_log_warn, vha, 0x0174, "-> fwdt%u failed allocate template.\n", j); diff --git a/drivers/scsi/qla2xxx/qla_inline.h b/drivers/scsi/qla2xxx/qla_inline.h index 7b42558a8839ad51e0b92ede49c89656a16b03f7..0167e85ba05876d4173514271905c21ff68c92f8 100644 --- a/drivers/scsi/qla2xxx/qla_inline.h +++ b/drivers/scsi/qla2xxx/qla_inline.h @@ -109,11 +109,13 @@ qla2x00_set_fcport_disc_state(fc_port_t *fcport, int state) { int old_val; uint8_t shiftbits, mask; + uint8_t port_dstate_str_sz; /* This will have to change when the max no. of states > 16 */ shiftbits = 4; mask = (1 << shiftbits) - 1; + port_dstate_str_sz = sizeof(port_dstate_str) / sizeof(char *); fcport->disc_state = state; while (1) { old_val = atomic_read(&fcport->shadow_disc_state); @@ -121,7 +123,8 @@ qla2x00_set_fcport_disc_state(fc_port_t *fcport, int state) old_val, (old_val << shiftbits) | state)) { ql_dbg(ql_dbg_disc, fcport->vha, 0x2134, "FCPort %8phC disc_state transition: %s to %s - portid=%06x.\n", - fcport->port_name, port_dstate_str[old_val & mask], + fcport->port_name, (old_val & mask) < port_dstate_str_sz ? + port_dstate_str[old_val & mask] : "Unknown", port_dstate_str[state], fcport->d_id.b24); return; } diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index b9b3e6f80ea9bb5027c6e0078ac0cff65809cdc1..730d8609276c6dd6657685a78d9f20c427bec8a3 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c @@ -522,21 +522,25 @@ __qla2x00_marker(struct scsi_qla_host *vha, struct qla_qpair *qpair, return (QLA_FUNCTION_FAILED); } + mrk24 = (struct mrk_entry_24xx *)mrk; + mrk->entry_type = MARKER_TYPE; mrk->modifier = type; if (type != MK_SYNC_ALL) { if (IS_FWI2_CAPABLE(ha)) { - mrk24 = (struct mrk_entry_24xx *) mrk; mrk24->nport_handle = cpu_to_le16(loop_id); int_to_scsilun(lun, (struct scsi_lun *)&mrk24->lun); host_to_fcp_swap(mrk24->lun, sizeof(mrk24->lun)); mrk24->vp_index = vha->vp_idx; - mrk24->handle = make_handle(req->id, mrk24->handle); } else { SET_TARGET_ID(ha, mrk->target, loop_id); mrk->lun = cpu_to_le16((uint16_t)lun); } } + + if (IS_FWI2_CAPABLE(ha)) + mrk24->handle = QLA_SKIP_HANDLE; + wmb(); qla2x00_start_iocbs(vha, req); @@ -603,7 +607,8 @@ qla24xx_build_scsi_type_6_iocbs(srb_t *sp, struct cmd_type_6 *cmd_pkt, put_unaligned_le32(COMMAND_TYPE_6, &cmd_pkt->entry_type); /* No data transfer */ - if (!scsi_bufflen(cmd) || cmd->sc_data_direction == DMA_NONE) { + if (!scsi_bufflen(cmd) || cmd->sc_data_direction == DMA_NONE || + tot_dsds == 0) { cmd_pkt->byte_count = cpu_to_le32(0); return 0; } @@ -2541,7 +2546,7 @@ qla24xx_tm_iocb(srb_t *sp, struct tsk_mgmt_entry *tsk) scsi_qla_host_t *vha = fcport->vha; struct qla_hw_data *ha = vha->hw; struct srb_iocb *iocb = &sp->u.iocb_cmd; - struct req_que *req = vha->req; + struct req_que *req = sp->qpair->req; flags = iocb->u.tmf.flags; lun = iocb->u.tmf.lun; @@ -2557,7 +2562,8 @@ qla24xx_tm_iocb(srb_t *sp, struct tsk_mgmt_entry *tsk) tsk->port_id[2] = fcport->d_id.b.domain; tsk->vp_index = fcport->vha->vp_idx; - if (flags == TCF_LUN_RESET) { + if (flags & (TCF_LUN_RESET | TCF_ABORT_TASK_SET| + TCF_CLEAR_TASK_SET|TCF_CLEAR_ACA)) { int_to_scsilun(lun, &tsk->lun); host_to_fcp_swap((uint8_t *)&tsk->lun, sizeof(tsk->lun)); @@ -3067,7 +3073,8 @@ qla24xx_els_dcmd2_iocb(scsi_qla_host_t *vha, int els_opcode, memset(ptr, 0, sizeof(struct els_plogi_payload)); memset(resp_ptr, 0, sizeof(struct els_plogi_payload)); memcpy(elsio->u.els_plogi.els_plogi_pyld->data, - &ha->plogi_els_payld.fl_csp, LOGIN_TEMPLATE_SIZE); + (void *)&ha->plogi_els_payld + offsetof(struct fc_els_flogi, fl_csp), + sizeof(ha->plogi_els_payld) - offsetof(struct fc_els_flogi, fl_csp)); elsio->u.els_plogi.els_cmd = els_opcode; elsio->u.els_plogi.els_plogi_pyld->opcode = els_opcode; @@ -3852,9 +3859,9 @@ static int qla_get_iocbs_resource(struct srb *sp) case SRB_NACK_LOGO: case SRB_LOGOUT_CMD: case SRB_CTRL_VP: - push_it_through = true; - fallthrough; + case SRB_MARKER: default: + push_it_through = true; get_exch = false; } @@ -3870,6 +3877,19 @@ static int qla_get_iocbs_resource(struct srb *sp) return qla_get_fw_resources(sp->qpair, &sp->iores); } +static void +qla_marker_iocb(srb_t *sp, struct mrk_entry_24xx *mrk) +{ + mrk->entry_type = MARKER_TYPE; + mrk->modifier = sp->u.iocb_cmd.u.tmf.modifier; + if (sp->u.iocb_cmd.u.tmf.modifier != MK_SYNC_ALL) { + mrk->nport_handle = cpu_to_le16(sp->u.iocb_cmd.u.tmf.loop_id); + int_to_scsilun(sp->u.iocb_cmd.u.tmf.lun, (struct scsi_lun *)&mrk->lun); + host_to_fcp_swap(mrk->lun, sizeof(mrk->lun)); + mrk->vp_index = sp->u.iocb_cmd.u.tmf.vp_index; + } +} + int qla2x00_start_sp(srb_t *sp) { @@ -3892,7 +3912,7 @@ qla2x00_start_sp(srb_t *sp) pkt = __qla2x00_alloc_iocbs(sp->qpair, sp); if (!pkt) { - rval = EAGAIN; + rval = -EAGAIN; ql_log(ql_log_warn, vha, 0x700c, "qla2x00_alloc_iocbs failed.\n"); goto done; @@ -3973,6 +3993,9 @@ qla2x00_start_sp(srb_t *sp) case SRB_SA_REPLACE: qla24xx_sa_replace_iocb(sp, pkt); break; + case SRB_MARKER: + qla_marker_iocb(sp, pkt); + break; default: break; } diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index 245e3a5d81fd33b3040df3000712d5d961ec9d6e..656700f79325981bb4e3b94c55cc73ad39f654f2 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -1862,9 +1862,9 @@ qla2x00_process_completed_request(struct scsi_qla_host *vha, } } -srb_t * -qla2x00_get_sp_from_handle(scsi_qla_host_t *vha, const char *func, - struct req_que *req, void *iocb) +static srb_t * +qla_get_sp_from_handle(scsi_qla_host_t *vha, const char *func, + struct req_que *req, void *iocb, u16 *ret_index) { struct qla_hw_data *ha = vha->hw; sts_entry_t *pkt = iocb; @@ -1899,12 +1899,25 @@ qla2x00_get_sp_from_handle(scsi_qla_host_t *vha, const char *func, return NULL; } - req->outstanding_cmds[index] = NULL; - + *ret_index = index; qla_put_fw_resources(sp->qpair, &sp->iores); return sp; } +srb_t * +qla2x00_get_sp_from_handle(scsi_qla_host_t *vha, const char *func, + struct req_que *req, void *iocb) +{ + uint16_t index; + srb_t *sp; + + sp = qla_get_sp_from_handle(vha, func, req, iocb, &index); + if (sp) + req->outstanding_cmds[index] = NULL; + + return sp; +} + static void qla2x00_mbx_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, struct mbx_entry *mbx) @@ -3237,13 +3250,13 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt) return; } - req->outstanding_cmds[handle] = NULL; cp = GET_CMD_SP(sp); if (cp == NULL) { ql_dbg(ql_dbg_io, vha, 0x3018, "Command already returned (0x%x/%p).\n", sts->handle, sp); + req->outstanding_cmds[handle] = NULL; return; } @@ -3514,6 +3527,9 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt) if (rsp->status_srb == NULL) sp->done(sp, res); + + /* for io's, clearing of outstanding_cmds[handle] means scsi_done was called */ + req->outstanding_cmds[handle] = NULL; } /** @@ -3590,6 +3606,7 @@ qla2x00_error_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, sts_entry_t *pkt) uint16_t que = MSW(pkt->handle); struct req_que *req = NULL; int res = DID_ERROR << 16; + u16 index; ql_dbg(ql_dbg_async, vha, 0x502a, "iocb type %xh with error status %xh, handle %xh, rspq id %d\n", @@ -3608,7 +3625,6 @@ qla2x00_error_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, sts_entry_t *pkt) switch (pkt->entry_type) { case NOTIFY_ACK_TYPE: - case STATUS_TYPE: case STATUS_CONT_TYPE: case LOGINOUT_PORT_IOCB_TYPE: case CT_IOCB_TYPE: @@ -3628,6 +3644,14 @@ qla2x00_error_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, sts_entry_t *pkt) case CTIO_TYPE7: case CTIO_CRC2: return 1; + case STATUS_TYPE: + sp = qla_get_sp_from_handle(vha, func, req, pkt, &index); + if (sp) { + sp->done(sp, res); + req->outstanding_cmds[index] = NULL; + return 0; + } + break; } fatal: ql_log(ql_log_warn, vha, 0x5030, @@ -3750,6 +3774,28 @@ static int qla_chk_cont_iocb_avail(struct scsi_qla_host *vha, return rc; } +static void qla_marker_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, + struct mrk_entry_24xx *pkt) +{ + const char func[] = "MRK-IOCB"; + srb_t *sp; + int res = QLA_SUCCESS; + + if (!IS_FWI2_CAPABLE(vha->hw)) + return; + + sp = qla2x00_get_sp_from_handle(vha, func, req, pkt); + if (!sp) + return; + + if (pkt->entry_status) { + ql_dbg(ql_dbg_taskm, vha, 0x8025, "marker failure.\n"); + res = QLA_COMMAND_ERROR; + } + sp->u.iocb_cmd.u.tmf.data = res; + sp->done(sp, res); +} + /** * qla24xx_process_response_queue() - Process response queue entries. * @vha: SCSI driver HA context @@ -3866,9 +3912,7 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha, (struct nack_to_isp *)pkt); break; case MARKER_TYPE: - /* Do nothing in this case, this check is to prevent it - * from falling into default case - */ + qla_marker_iocb_entry(vha, rsp->req, (struct mrk_entry_24xx *)pkt); break; case ABORT_IOCB_TYPE: qla24xx_abort_iocb_entry(vha, rsp->req, diff --git a/drivers/scsi/qla2xxx/qla_mr.c b/drivers/scsi/qla2xxx/qla_mr.c index f726eb8449c5e6a95059aa2260fe899b7265ae93..083f94e43fba0b51bcf892367c9f1695a345e0db 100644 --- a/drivers/scsi/qla2xxx/qla_mr.c +++ b/drivers/scsi/qla2xxx/qla_mr.c @@ -691,7 +691,7 @@ qlafx00_pci_info_str(struct scsi_qla_host *vha, char *str, size_t str_len) struct qla_hw_data *ha = vha->hw; if (pci_is_pcie(ha->pdev)) - strlcpy(str, "PCIe iSA", str_len); + strscpy(str, "PCIe iSA", str_len); return str; } @@ -1850,21 +1850,21 @@ qlafx00_fx_disc(scsi_qla_host_t *vha, fc_port_t *fcport, uint16_t fx_type) phost_info = &preg_hsi->hsi; memset(preg_hsi, 0, sizeof(struct register_host_info)); phost_info->os_type = OS_TYPE_LINUX; - strlcpy(phost_info->sysname, p_sysid->sysname, + strscpy(phost_info->sysname, p_sysid->sysname, sizeof(phost_info->sysname)); - strlcpy(phost_info->nodename, p_sysid->nodename, + strscpy(phost_info->nodename, p_sysid->nodename, sizeof(phost_info->nodename)); if (!strcmp(phost_info->nodename, "(none)")) ha->mr.host_info_resend = true; - strlcpy(phost_info->release, p_sysid->release, + strscpy(phost_info->release, p_sysid->release, sizeof(phost_info->release)); - strlcpy(phost_info->version, p_sysid->version, + strscpy(phost_info->version, p_sysid->version, sizeof(phost_info->version)); - strlcpy(phost_info->machine, p_sysid->machine, + strscpy(phost_info->machine, p_sysid->machine, sizeof(phost_info->machine)); - strlcpy(phost_info->domainname, p_sysid->domainname, + strscpy(phost_info->domainname, p_sysid->domainname, sizeof(phost_info->domainname)); - strlcpy(phost_info->hostdriver, QLA2XXX_VERSION, + strscpy(phost_info->hostdriver, QLA2XXX_VERSION, sizeof(phost_info->hostdriver)); preg_hsi->utc = (uint64_t)ktime_get_real_seconds(); ql_dbg(ql_dbg_init, vha, 0x0149, @@ -1909,9 +1909,9 @@ qlafx00_fx_disc(scsi_qla_host_t *vha, fc_port_t *fcport, uint16_t fx_type) if (fx_type == FXDISC_GET_CONFIG_INFO) { struct config_info_data *pinfo = (struct config_info_data *) fdisc->u.fxiocb.rsp_addr; - strlcpy(vha->hw->model_number, pinfo->model_num, + strscpy(vha->hw->model_number, pinfo->model_num, ARRAY_SIZE(vha->hw->model_number)); - strlcpy(vha->hw->model_desc, pinfo->model_description, + strscpy(vha->hw->model_desc, pinfo->model_description, ARRAY_SIZE(vha->hw->model_desc)); memcpy(&vha->hw->mr.symbolic_name, pinfo->symbolic_name, sizeof(vha->hw->mr.symbolic_name)); diff --git a/drivers/scsi/qla2xxx/qla_nvme.c b/drivers/scsi/qla2xxx/qla_nvme.c index 648e8f7986065f88fe5fd421490b2da4e3bca2ee..86e85f2f4782f6c1f52febe57645e448c7e111b6 100644 --- a/drivers/scsi/qla2xxx/qla_nvme.c +++ b/drivers/scsi/qla2xxx/qla_nvme.c @@ -360,7 +360,6 @@ static int qla_nvme_ls_req(struct nvme_fc_local_port *lport, if (rval != QLA_SUCCESS) { ql_log(ql_log_warn, vha, 0x700e, "qla2x00_start_sp failed = %d\n", rval); - wake_up(&sp->nvme_ls_waitq); sp->priv = NULL; priv->sp = NULL; qla2x00_rel_sp(sp); @@ -652,7 +651,6 @@ static int qla_nvme_post_cmd(struct nvme_fc_local_port *lport, if (!sp) return -EBUSY; - init_waitqueue_head(&sp->nvme_ls_waitq); kref_init(&sp->cmd_kref); spin_lock_init(&priv->cmd_lock); sp->priv = priv; @@ -671,7 +669,6 @@ static int qla_nvme_post_cmd(struct nvme_fc_local_port *lport, if (rval != QLA_SUCCESS) { ql_log(ql_log_warn, vha, 0x212d, "qla2x00_start_nvme_mq failed = %d\n", rval); - wake_up(&sp->nvme_ls_waitq); sp->priv = NULL; priv->sp = NULL; qla2xxx_rel_qpair_sp(sp->qpair, sp); diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 2fa695bf38b77dd515ccfba420c17a7fad3d9cc0..877e4f446709d5fb6792b670c290fa9519220f13 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -1078,43 +1078,6 @@ qla2xxx_mqueuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd, return 0; } -/* - * qla2x00_eh_wait_on_command - * Waits for the command to be returned by the Firmware for some - * max time. - * - * Input: - * cmd = Scsi Command to wait on. - * - * Return: - * Completed in time : QLA_SUCCESS - * Did not complete in time : QLA_FUNCTION_FAILED - */ -static int -qla2x00_eh_wait_on_command(struct scsi_cmnd *cmd) -{ -#define ABORT_POLLING_PERIOD 1000 -#define ABORT_WAIT_ITER ((2 * 1000) / (ABORT_POLLING_PERIOD)) - unsigned long wait_iter = ABORT_WAIT_ITER; - scsi_qla_host_t *vha = shost_priv(cmd->device->host); - struct qla_hw_data *ha = vha->hw; - srb_t *sp = scsi_cmd_priv(cmd); - int ret = QLA_SUCCESS; - - if (unlikely(pci_channel_offline(ha->pdev)) || ha->flags.eeh_busy) { - ql_dbg(ql_dbg_taskm, vha, 0x8005, - "Return:eh_wait.\n"); - return ret; - } - - while (sp->type && wait_iter--) - msleep(ABORT_POLLING_PERIOD); - if (sp->type) - ret = QLA_FUNCTION_FAILED; - - return ret; -} - /* * qla2x00_wait_for_hba_online * Wait till the HBA is online after going through @@ -1365,6 +1328,9 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) return ret; } +#define ABORT_POLLING_PERIOD 1000 +#define ABORT_WAIT_ITER ((2 * 1000) / (ABORT_POLLING_PERIOD)) + /* * Returns: QLA_SUCCESS or QLA_FUNCTION_FAILED. */ @@ -1378,41 +1344,73 @@ __qla2x00_eh_wait_for_pending_commands(struct qla_qpair *qpair, unsigned int t, struct req_que *req = qpair->req; srb_t *sp; struct scsi_cmnd *cmd; + unsigned long wait_iter = ABORT_WAIT_ITER; + bool found; + struct qla_hw_data *ha = vha->hw; status = QLA_SUCCESS; - spin_lock_irqsave(qpair->qp_lock_ptr, flags); - for (cnt = 1; status == QLA_SUCCESS && - cnt < req->num_outstanding_cmds; cnt++) { - sp = req->outstanding_cmds[cnt]; - if (!sp) - continue; - if (sp->type != SRB_SCSI_CMD) - continue; - if (vha->vp_idx != sp->vha->vp_idx) - continue; - match = 0; - cmd = GET_CMD_SP(sp); - switch (type) { - case WAIT_HOST: - match = 1; - break; - case WAIT_TARGET: - match = cmd->device->id == t; - break; - case WAIT_LUN: - match = (cmd->device->id == t && - cmd->device->lun == l); - break; - } - if (!match) - continue; + while (wait_iter--) { + found = false; - spin_unlock_irqrestore(qpair->qp_lock_ptr, flags); - status = qla2x00_eh_wait_on_command(cmd); spin_lock_irqsave(qpair->qp_lock_ptr, flags); + for (cnt = 1; cnt < req->num_outstanding_cmds; cnt++) { + sp = req->outstanding_cmds[cnt]; + if (!sp) + continue; + if (sp->type != SRB_SCSI_CMD) + continue; + if (vha->vp_idx != sp->vha->vp_idx) + continue; + match = 0; + cmd = GET_CMD_SP(sp); + switch (type) { + case WAIT_HOST: + match = 1; + break; + case WAIT_TARGET: + if (sp->fcport) + match = sp->fcport->d_id.b24 == t; + else + match = 0; + break; + case WAIT_LUN: + if (sp->fcport) + match = (sp->fcport->d_id.b24 == t && + cmd->device->lun == l); + else + match = 0; + break; + } + if (!match) + continue; + + spin_unlock_irqrestore(qpair->qp_lock_ptr, flags); + + if (unlikely(pci_channel_offline(ha->pdev)) || + ha->flags.eeh_busy) { + ql_dbg(ql_dbg_taskm, vha, 0x8005, + "Return:eh_wait.\n"); + return status; + } + + /* + * SRB_SCSI_CMD is still in the outstanding_cmds array. + * it means scsi_done has not called. Wait for it to + * clear from outstanding_cmds. + */ + msleep(ABORT_POLLING_PERIOD); + spin_lock_irqsave(qpair->qp_lock_ptr, flags); + found = true; + } + spin_unlock_irqrestore(qpair->qp_lock_ptr, flags); + + if (!found) + break; } - spin_unlock_irqrestore(qpair->qp_lock_ptr, flags); + + if (wait_iter == -1) + status = QLA_FUNCTION_FAILED; return status; } @@ -5090,7 +5088,8 @@ struct scsi_qla_host *qla2x00_create_host(const struct scsi_host_template *sht, } INIT_DELAYED_WORK(&vha->scan.scan_work, qla_scan_work_fn); - sprintf(vha->host_str, "%s_%lu", QLA2XXX_DRIVER_NAME, vha->host_no); + snprintf(vha->host_str, sizeof(vha->host_str), "%s_%lu", + QLA2XXX_DRIVER_NAME, vha->host_no); ql_dbg(ql_dbg_init, vha, 0x0041, "Allocated the host=%p hw=%p vha=%p dev_name=%s", vha->host, vha->hw, vha, diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h index 42d69d89834fb6666e2fa94d19660e52d18f9add..e3771923b0d7d6cffde7c00275610cddad5fb594 100644 --- a/drivers/scsi/qla2xxx/qla_version.h +++ b/drivers/scsi/qla2xxx/qla_version.h @@ -6,9 +6,9 @@ /* * Driver version */ -#define QLA2XXX_VERSION "10.02.08.200-k" +#define QLA2XXX_VERSION "10.02.08.400-k" #define QLA_DRIVER_MAJOR_VER 10 #define QLA_DRIVER_MINOR_VER 2 #define QLA_DRIVER_PATCH_VER 8 -#define QLA_DRIVER_BETA_VER 200 +#define QLA_DRIVER_BETA_VER 400 diff --git a/drivers/scsi/qla4xxx/ql4_mbx.c b/drivers/scsi/qla4xxx/ql4_mbx.c index cd71074f3abe527e4c61cca6be0ae3185c68f199..249f1d7021d49ea0a9f64230318b1567a845d899 100644 --- a/drivers/scsi/qla4xxx/ql4_mbx.c +++ b/drivers/scsi/qla4xxx/ql4_mbx.c @@ -1611,8 +1611,8 @@ int qla4xxx_get_chap(struct scsi_qla_host *ha, char *username, char *password, goto exit_get_chap; } - strlcpy(password, chap_table->secret, QL4_CHAP_MAX_SECRET_LEN); - strlcpy(username, chap_table->name, QL4_CHAP_MAX_NAME_LEN); + strscpy(password, chap_table->secret, QL4_CHAP_MAX_SECRET_LEN); + strscpy(username, chap_table->name, QL4_CHAP_MAX_NAME_LEN); chap_table->cookie = cpu_to_le16(CHAP_VALID_COOKIE); exit_get_chap: @@ -1732,8 +1732,8 @@ int qla4xxx_get_uni_chap_at_index(struct scsi_qla_host *ha, char *username, goto exit_unlock_uni_chap; } - strlcpy(password, chap_table->secret, MAX_CHAP_SECRET_LEN); - strlcpy(username, chap_table->name, MAX_CHAP_NAME_LEN); + strscpy(password, chap_table->secret, MAX_CHAP_SECRET_LEN); + strscpy(username, chap_table->name, MAX_CHAP_NAME_LEN); rval = QLA_SUCCESS; diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index ee6d784c095c9125efb4904830a6a1a643c672fa..b2a3988e1e1594603307f19dd43d87ec33398d0e 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c @@ -798,9 +798,9 @@ static int qla4xxx_get_chap_list(struct Scsi_Host *shost, uint16_t chap_tbl_idx, continue; chap_rec->chap_tbl_idx = i; - strlcpy(chap_rec->username, chap_table->name, + strscpy(chap_rec->username, chap_table->name, ISCSI_CHAP_AUTH_NAME_MAX_LEN); - strlcpy(chap_rec->password, chap_table->secret, + strscpy(chap_rec->password, chap_table->secret, QL4_CHAP_MAX_SECRET_LEN); chap_rec->password_length = chap_table->secret_len; @@ -6052,8 +6052,8 @@ static int qla4xxx_get_bidi_chap(struct scsi_qla_host *ha, char *username, if (!(chap_table->flags & BIT_6)) /* Not BIDI */ continue; - strlcpy(password, chap_table->secret, QL4_CHAP_MAX_SECRET_LEN); - strlcpy(username, chap_table->name, QL4_CHAP_MAX_NAME_LEN); + strscpy(password, chap_table->secret, QL4_CHAP_MAX_SECRET_LEN); + strscpy(username, chap_table->name, QL4_CHAP_MAX_NAME_LEN); ret = 0; break; } @@ -6281,8 +6281,8 @@ static void qla4xxx_get_param_ddb(struct ddb_entry *ddb_entry, tddb->tpgt = sess->tpgt; tddb->port = conn->persistent_port; - strlcpy(tddb->iscsi_name, sess->targetname, ISCSI_NAME_SIZE); - strlcpy(tddb->ip_addr, conn->persistent_address, DDB_IPADDR_LEN); + strscpy(tddb->iscsi_name, sess->targetname, ISCSI_NAME_SIZE); + strscpy(tddb->ip_addr, conn->persistent_address, DDB_IPADDR_LEN); } static void qla4xxx_convert_param_ddb(struct dev_db_entry *fw_ddb_entry, @@ -7781,7 +7781,7 @@ static int qla4xxx_sysfs_ddb_logout(struct iscsi_bus_flash_session *fnode_sess, goto exit_ddb_logout; } - strlcpy(flash_tddb->iscsi_name, fnode_sess->targetname, + strscpy(flash_tddb->iscsi_name, fnode_sess->targetname, ISCSI_NAME_SIZE); if (!strncmp(fnode_sess->portal_type, PORTAL_TYPE_IPV6, 4)) diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index 09ef0b31dfc09c5d9950bf458c4ae8758862358e..d0911bc28663a8142d0fb0ae69dbad1348efa385 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -504,18 +504,22 @@ void scsi_attach_vpd(struct scsi_device *sdev) } /** - * scsi_report_opcode - Find out if a given command opcode is supported + * scsi_report_opcode - Find out if a given command is supported * @sdev: scsi device to query * @buffer: scratch buffer (must be at least 20 bytes long) * @len: length of buffer - * @opcode: opcode for command to look up - * - * Uses the REPORT SUPPORTED OPERATION CODES to look up the given - * opcode. Returns -EINVAL if RSOC fails, 0 if the command opcode is - * unsupported and 1 if the device claims to support the command. + * @opcode: opcode for the command to look up + * @sa: service action for the command to look up + * + * Uses the REPORT SUPPORTED OPERATION CODES to check support for the + * command identified with @opcode and @sa. If the command does not + * have a service action, @sa must be 0. Returns -EINVAL if RSOC fails, + * 0 if the command is not supported and 1 if the device claims to + * support the command. */ int scsi_report_opcode(struct scsi_device *sdev, unsigned char *buffer, - unsigned int len, unsigned char opcode) + unsigned int len, unsigned char opcode, + unsigned short sa) { unsigned char cmd[16]; struct scsi_sense_hdr sshdr; @@ -539,8 +543,14 @@ int scsi_report_opcode(struct scsi_device *sdev, unsigned char *buffer, memset(cmd, 0, 16); cmd[0] = MAINTENANCE_IN; cmd[1] = MI_REPORT_SUPPORTED_OPERATION_CODES; - cmd[2] = 1; /* One command format */ - cmd[3] = opcode; + if (!sa) { + cmd[2] = 1; /* One command format */ + cmd[3] = opcode; + } else { + cmd[2] = 3; /* One command format with service action */ + cmd[3] = opcode; + put_unaligned_be16(sa, &cmd[4]); + } put_unaligned_be32(request_len, &cmd[6]); memset(buffer, 0, len); @@ -560,6 +570,140 @@ int scsi_report_opcode(struct scsi_device *sdev, unsigned char *buffer, } EXPORT_SYMBOL(scsi_report_opcode); +#define SCSI_CDL_CHECK_BUF_LEN 64 + +static bool scsi_cdl_check_cmd(struct scsi_device *sdev, u8 opcode, u16 sa, + unsigned char *buf) +{ + int ret; + u8 cdlp; + + /* Check operation code */ + ret = scsi_report_opcode(sdev, buf, SCSI_CDL_CHECK_BUF_LEN, opcode, sa); + if (ret <= 0) + return false; + + if ((buf[1] & 0x03) != 0x03) + return false; + + /* + * See SPC-6, One_command parameter data format for + * REPORT SUPPORTED OPERATION CODES. We have the following cases + * depending on rwcdlp (buf[0] & 0x01) value: + * - rwcdlp == 0: then cdlp indicates support for the A mode page when + * it is equal to 1 and for the B mode page when it is + * equal to 2. + * - rwcdlp == 1: then cdlp indicates support for the T2A mode page + * when it is equal to 1 and for the T2B mode page when + * it is equal to 2. + * Overall, to detect support for command duration limits, we only need + * to check that cdlp is 1 or 2. + */ + cdlp = (buf[1] & 0x18) >> 3; + + return cdlp == 0x01 || cdlp == 0x02; +} + +/** + * scsi_cdl_check - Check if a SCSI device supports Command Duration Limits + * @sdev: The device to check + */ +void scsi_cdl_check(struct scsi_device *sdev) +{ + bool cdl_supported; + unsigned char *buf; + + buf = kmalloc(SCSI_CDL_CHECK_BUF_LEN, GFP_KERNEL); + if (!buf) { + sdev->cdl_supported = 0; + return; + } + + /* Check support for READ_16, WRITE_16, READ_32 and WRITE_32 commands */ + cdl_supported = + scsi_cdl_check_cmd(sdev, READ_16, 0, buf) || + scsi_cdl_check_cmd(sdev, WRITE_16, 0, buf) || + scsi_cdl_check_cmd(sdev, VARIABLE_LENGTH_CMD, READ_32, buf) || + scsi_cdl_check_cmd(sdev, VARIABLE_LENGTH_CMD, WRITE_32, buf); + if (cdl_supported) { + /* + * We have CDL support: force the use of READ16/WRITE16. + * READ32 and WRITE32 will be used for devices that support + * the T10_PI_TYPE2_PROTECTION protection type. + */ + sdev->use_16_for_rw = 1; + sdev->use_10_for_rw = 0; + + sdev->cdl_supported = 1; + } else { + sdev->cdl_supported = 0; + } + + kfree(buf); +} + +/** + * scsi_cdl_enable - Enable or disable a SCSI device supports for Command + * Duration Limits + * @sdev: The target device + * @enable: the target state + */ +int scsi_cdl_enable(struct scsi_device *sdev, bool enable) +{ + struct scsi_mode_data data; + struct scsi_sense_hdr sshdr; + struct scsi_vpd *vpd; + bool is_ata = false; + char buf[64]; + int ret; + + if (!sdev->cdl_supported) + return -EOPNOTSUPP; + + rcu_read_lock(); + vpd = rcu_dereference(sdev->vpd_pg89); + if (vpd) + is_ata = true; + rcu_read_unlock(); + + /* + * For ATA devices, CDL needs to be enabled with a SET FEATURES command. + */ + if (is_ata) { + char *buf_data; + int len; + + ret = scsi_mode_sense(sdev, 0x08, 0x0a, 0xf2, buf, sizeof(buf), + 5 * HZ, 3, &data, NULL); + if (ret) + return -EINVAL; + + /* Enable CDL using the ATA feature page */ + len = min_t(size_t, sizeof(buf), + data.length - data.header_length - + data.block_descriptor_length); + buf_data = buf + data.header_length + + data.block_descriptor_length; + if (enable) + buf_data[4] = 0x02; + else + buf_data[4] = 0; + + ret = scsi_mode_select(sdev, 1, 0, buf_data, len, 5 * HZ, 3, + &data, &sshdr); + if (ret) { + if (scsi_sense_valid(&sshdr)) + scsi_print_sense_hdr(sdev, + dev_name(&sdev->sdev_gendev), &sshdr); + return ret; + } + } + + sdev->cdl_enable = enable; + + return 0; +} + /** * scsi_device_get - get an additional reference to a scsi_device * @sdev: device to get a reference to diff --git a/drivers/scsi/scsi_bsg.c b/drivers/scsi/scsi_bsg.c index 96ee35256a168f3b70a4e1eeab0eb8a5cf7b0f49..a9a9ec086a7e3f2ac13a05f80fe3a04bec976a3a 100644 --- a/drivers/scsi/scsi_bsg.c +++ b/drivers/scsi/scsi_bsg.c @@ -10,7 +10,7 @@ #define uptr64(val) ((void __user *)(uintptr_t)(val)) static int scsi_bsg_sg_io_fn(struct request_queue *q, struct sg_io_v4 *hdr, - fmode_t mode, unsigned int timeout) + bool open_for_write, unsigned int timeout) { struct scsi_cmnd *scmd; struct request *rq; @@ -42,7 +42,7 @@ static int scsi_bsg_sg_io_fn(struct request_queue *q, struct sg_io_v4 *hdr, if (copy_from_user(scmd->cmnd, uptr64(hdr->request), scmd->cmd_len)) goto out_put_request; ret = -EPERM; - if (!scsi_cmd_allowed(scmd->cmnd, mode)) + if (!scsi_cmd_allowed(scmd->cmnd, open_for_write)) goto out_put_request; ret = 0; diff --git a/drivers/scsi/scsi_common.c b/drivers/scsi/scsi_common.c index 6e50e81a821668d760f9c1f1324f91bc63bbe6ec..9c14fdf6103706be777f3b54a0ddd715961f54a9 100644 --- a/drivers/scsi/scsi_common.c +++ b/drivers/scsi/scsi_common.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -63,6 +64,48 @@ const char *scsi_device_type(unsigned type) } EXPORT_SYMBOL(scsi_device_type); +enum pr_type scsi_pr_type_to_block(enum scsi_pr_type type) +{ + switch (type) { + case SCSI_PR_WRITE_EXCLUSIVE: + return PR_WRITE_EXCLUSIVE; + case SCSI_PR_EXCLUSIVE_ACCESS: + return PR_EXCLUSIVE_ACCESS; + case SCSI_PR_WRITE_EXCLUSIVE_REG_ONLY: + return PR_WRITE_EXCLUSIVE_REG_ONLY; + case SCSI_PR_EXCLUSIVE_ACCESS_REG_ONLY: + return PR_EXCLUSIVE_ACCESS_REG_ONLY; + case SCSI_PR_WRITE_EXCLUSIVE_ALL_REGS: + return PR_WRITE_EXCLUSIVE_ALL_REGS; + case SCSI_PR_EXCLUSIVE_ACCESS_ALL_REGS: + return PR_EXCLUSIVE_ACCESS_ALL_REGS; + } + + return 0; +} +EXPORT_SYMBOL_GPL(scsi_pr_type_to_block); + +enum scsi_pr_type block_pr_type_to_scsi(enum pr_type type) +{ + switch (type) { + case PR_WRITE_EXCLUSIVE: + return SCSI_PR_WRITE_EXCLUSIVE; + case PR_EXCLUSIVE_ACCESS: + return SCSI_PR_EXCLUSIVE_ACCESS; + case PR_WRITE_EXCLUSIVE_REG_ONLY: + return SCSI_PR_WRITE_EXCLUSIVE_REG_ONLY; + case PR_EXCLUSIVE_ACCESS_REG_ONLY: + return SCSI_PR_EXCLUSIVE_ACCESS_REG_ONLY; + case PR_WRITE_EXCLUSIVE_ALL_REGS: + return SCSI_PR_WRITE_EXCLUSIVE_ALL_REGS; + case PR_EXCLUSIVE_ACCESS_ALL_REGS: + return SCSI_PR_EXCLUSIVE_ACCESS_ALL_REGS; + } + + return 0; +} +EXPORT_SYMBOL_GPL(block_pr_type_to_scsi); + /** * scsilun_to_int - convert a scsi_lun to an int * @scsilun: struct scsi_lun to be converted. @@ -176,8 +219,7 @@ bool scsi_normalize_sense(const u8 *sense_buffer, int sb_len, if (sb_len > 2) sshdr->sense_key = (sense_buffer[2] & 0xf); if (sb_len > 7) { - sb_len = (sb_len < (sense_buffer[7] + 8)) ? - sb_len : (sense_buffer[7] + 8); + sb_len = min(sb_len, sense_buffer[7] + 8); if (sb_len > 12) sshdr->asc = sense_buffer[12]; if (sb_len > 13) diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index 8c58128ad32a29b870039668efcec06fda8aa231..9c0af50501f9ac934b49873899d18e25efe5db5f 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c @@ -841,11 +841,6 @@ static int sdeb_zbc_nr_conv = DEF_ZBC_NR_CONV_ZONES; static int submit_queues = DEF_SUBMIT_QUEUES; /* > 1 for multi-queue (mq) */ static int poll_queues; /* iouring iopoll interface.*/ -static DEFINE_RWLOCK(atomic_rw); -static DEFINE_RWLOCK(atomic_rw2); - -static rwlock_t *ramdisk_lck_a[2]; - static char sdebug_proc_name[] = MY_NAME; static const char *my_name = MY_NAME; @@ -6818,9 +6813,6 @@ static int __init scsi_debug_init(void) int k, ret, hosts_to_add; int idx = -1; - ramdisk_lck_a[0] = &atomic_rw; - ramdisk_lck_a[1] = &atomic_rw2; - if (sdebug_ndelay >= 1000 * 1000 * 1000) { pr_warn("ndelay must be less than 1 second, ignored\n"); sdebug_ndelay = 0; diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 3ec8bfd4090f9eaa7bee047e9664597152a19cbf..c67cdcdc3ba86d94271fe6fe1d9155619ac6d2cd 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -536,6 +536,7 @@ static inline void set_scsi_ml_byte(struct scsi_cmnd *cmd, u8 status) */ enum scsi_disposition scsi_check_sense(struct scsi_cmnd *scmd) { + struct request *req = scsi_cmd_to_rq(scmd); struct scsi_device *sdev = scmd->device; struct scsi_sense_hdr sshdr; @@ -595,6 +596,22 @@ enum scsi_disposition scsi_check_sense(struct scsi_cmnd *scmd) if (sshdr.asc == 0x10) /* DIF */ return SUCCESS; + /* + * Check aborts due to command duration limit policy: + * ABORTED COMMAND additional sense code with the + * COMMAND TIMEOUT BEFORE PROCESSING or + * COMMAND TIMEOUT DURING PROCESSING or + * COMMAND TIMEOUT DURING PROCESSING DUE TO ERROR RECOVERY + * additional sense code qualifiers. + */ + if (sshdr.asc == 0x2e && + sshdr.ascq >= 0x01 && sshdr.ascq <= 0x03) { + set_scsi_ml_byte(scmd, SCSIML_STAT_DL_TIMEOUT); + req->cmd_flags |= REQ_FAILFAST_DEV; + req->rq_flags |= RQF_QUIET; + return SUCCESS; + } + if (sshdr.asc == 0x44 && sdev->sdev_bflags & BLIST_RETRY_ITF) return ADD_TO_MLQUEUE; if (sshdr.asc == 0xc1 && sshdr.ascq == 0x01 && @@ -691,6 +708,14 @@ enum scsi_disposition scsi_check_sense(struct scsi_cmnd *scmd) } return SUCCESS; + case COMPLETED: + if (sshdr.asc == 0x55 && sshdr.ascq == 0x0a) { + set_scsi_ml_byte(scmd, SCSIML_STAT_DL_TIMEOUT); + req->cmd_flags |= REQ_FAILFAST_DEV; + req->rq_flags |= RQF_QUIET; + } + return SUCCESS; + default: return SUCCESS; } @@ -785,6 +810,14 @@ static enum scsi_disposition scsi_eh_completed_normally(struct scsi_cmnd *scmd) switch (get_status_byte(scmd)) { case SAM_STAT_GOOD: scsi_handle_queue_ramp_up(scmd->device); + if (scmd->sense_buffer && SCSI_SENSE_VALID(scmd)) + /* + * If we have sense data, call scsi_check_sense() in + * order to set the correct SCSI ML byte (if any). + * No point in checking the return value, since the + * command has already completed successfully. + */ + scsi_check_sense(scmd); fallthrough; case SAM_STAT_COMMAND_TERMINATED: return SUCCESS; @@ -1807,6 +1840,10 @@ bool scsi_noretry_cmd(struct scsi_cmnd *scmd) return !!(req->cmd_flags & REQ_FAILFAST_DRIVER); } + /* Never retry commands aborted due to a duration limit timeout */ + if (scsi_ml_byte(scmd->result) == SCSIML_STAT_DL_TIMEOUT) + return true; + if (!scsi_status_is_check_condition(scmd->result)) return false; @@ -1966,6 +2003,14 @@ enum scsi_disposition scsi_decide_disposition(struct scsi_cmnd *scmd) if (scmd->cmnd[0] == REPORT_LUNS) scmd->device->sdev_target->expecting_lun_change = 0; scsi_handle_queue_ramp_up(scmd->device); + if (scmd->sense_buffer && SCSI_SENSE_VALID(scmd)) + /* + * If we have sense data, call scsi_check_sense() in + * order to set the correct SCSI ML byte (if any). + * No point in checking the return value, since the + * command has already completed successfully. + */ + scsi_check_sense(scmd); fallthrough; case SAM_STAT_COMMAND_TERMINATED: return SUCCESS; @@ -2165,7 +2210,8 @@ void scsi_eh_flush_done_q(struct list_head *done_q) * scsi_eh_get_sense), scmd->result is already * set, do not set DID_TIME_OUT. */ - if (!scmd->result) + if (!scmd->result && + !(scmd->flags & SCMD_FORCE_EH_SUCCESS)) scmd->result |= (DID_TIME_OUT << 16); SCSI_LOG_ERROR_RECOVERY(3, scmd_printk(KERN_INFO, scmd, diff --git a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c index e3b31d32b6a92e0eaa16bee6ee6a737ca042b716..6f6c5973c3ea95d91af230689084b68e6a8d3f32 100644 --- a/drivers/scsi/scsi_ioctl.c +++ b/drivers/scsi/scsi_ioctl.c @@ -248,7 +248,7 @@ static int scsi_send_start_stop(struct scsi_device *sdev, int data) * Only a subset of commands are allowed for unprivileged users. Commands used * to format the media, update the firmware, etc. are not permitted. */ -bool scsi_cmd_allowed(unsigned char *cmd, fmode_t mode) +bool scsi_cmd_allowed(unsigned char *cmd, bool open_for_write) { /* root can do any command. */ if (capable(CAP_SYS_RAWIO)) @@ -338,7 +338,7 @@ bool scsi_cmd_allowed(unsigned char *cmd, fmode_t mode) case GPCMD_SET_READ_AHEAD: /* ZBC */ case ZBC_OUT: - return (mode & FMODE_WRITE); + return open_for_write; default: return false; } @@ -346,7 +346,7 @@ bool scsi_cmd_allowed(unsigned char *cmd, fmode_t mode) EXPORT_SYMBOL(scsi_cmd_allowed); static int scsi_fill_sghdr_rq(struct scsi_device *sdev, struct request *rq, - struct sg_io_hdr *hdr, fmode_t mode) + struct sg_io_hdr *hdr, bool open_for_write) { struct scsi_cmnd *scmd = blk_mq_rq_to_pdu(rq); @@ -354,7 +354,7 @@ static int scsi_fill_sghdr_rq(struct scsi_device *sdev, struct request *rq, return -EMSGSIZE; if (copy_from_user(scmd->cmnd, hdr->cmdp, hdr->cmd_len)) return -EFAULT; - if (!scsi_cmd_allowed(scmd->cmnd, mode)) + if (!scsi_cmd_allowed(scmd->cmnd, open_for_write)) return -EPERM; scmd->cmd_len = hdr->cmd_len; @@ -407,7 +407,8 @@ static int scsi_complete_sghdr_rq(struct request *rq, struct sg_io_hdr *hdr, return ret; } -static int sg_io(struct scsi_device *sdev, struct sg_io_hdr *hdr, fmode_t mode) +static int sg_io(struct scsi_device *sdev, struct sg_io_hdr *hdr, + bool open_for_write) { unsigned long start_time; ssize_t ret = 0; @@ -448,7 +449,7 @@ static int sg_io(struct scsi_device *sdev, struct sg_io_hdr *hdr, fmode_t mode) goto out_put_request; } - ret = scsi_fill_sghdr_rq(sdev, rq, hdr, mode); + ret = scsi_fill_sghdr_rq(sdev, rq, hdr, open_for_write); if (ret < 0) goto out_put_request; @@ -477,8 +478,7 @@ static int sg_io(struct scsi_device *sdev, struct sg_io_hdr *hdr, fmode_t mode) /** * sg_scsi_ioctl -- handle deprecated SCSI_IOCTL_SEND_COMMAND ioctl * @q: request queue to send scsi commands down - * @mode: mode used to open the file through which the ioctl has been - * submitted + * @open_for_write: is the file / block device opened for writing? * @sic: userspace structure describing the command to perform * * Send down the scsi command described by @sic to the device below @@ -501,7 +501,7 @@ static int sg_io(struct scsi_device *sdev, struct sg_io_hdr *hdr, fmode_t mode) * Positive numbers returned are the compacted SCSI error codes (4 * bytes in one int) where the lowest byte is the SCSI status. */ -static int sg_scsi_ioctl(struct request_queue *q, fmode_t mode, +static int sg_scsi_ioctl(struct request_queue *q, bool open_for_write, struct scsi_ioctl_command __user *sic) { struct request *rq; @@ -554,7 +554,7 @@ static int sg_scsi_ioctl(struct request_queue *q, fmode_t mode, goto error; err = -EPERM; - if (!scsi_cmd_allowed(scmd->cmnd, mode)) + if (!scsi_cmd_allowed(scmd->cmnd, open_for_write)) goto error; /* default. possible overridden later */ @@ -776,7 +776,7 @@ static int scsi_put_cdrom_generic_arg(const struct cdrom_generic_command *cgc, return 0; } -static int scsi_cdrom_send_packet(struct scsi_device *sdev, fmode_t mode, +static int scsi_cdrom_send_packet(struct scsi_device *sdev, bool open_for_write, void __user *arg) { struct cdrom_generic_command cgc; @@ -817,7 +817,7 @@ static int scsi_cdrom_send_packet(struct scsi_device *sdev, fmode_t mode, hdr.cmdp = ((struct cdrom_generic_command __user *) arg)->cmd; hdr.cmd_len = sizeof(cgc.cmd); - err = sg_io(sdev, &hdr, mode); + err = sg_io(sdev, &hdr, open_for_write); if (err == -EFAULT) return -EFAULT; @@ -832,7 +832,7 @@ static int scsi_cdrom_send_packet(struct scsi_device *sdev, fmode_t mode, return err; } -static int scsi_ioctl_sg_io(struct scsi_device *sdev, fmode_t mode, +static int scsi_ioctl_sg_io(struct scsi_device *sdev, bool open_for_write, void __user *argp) { struct sg_io_hdr hdr; @@ -841,7 +841,7 @@ static int scsi_ioctl_sg_io(struct scsi_device *sdev, fmode_t mode, error = get_sg_io_hdr(&hdr, argp); if (error) return error; - error = sg_io(sdev, &hdr, mode); + error = sg_io(sdev, &hdr, open_for_write); if (error == -EFAULT) return error; if (put_sg_io_hdr(&hdr, argp)) @@ -852,7 +852,7 @@ static int scsi_ioctl_sg_io(struct scsi_device *sdev, fmode_t mode, /** * scsi_ioctl - Dispatch ioctl to scsi device * @sdev: scsi device receiving ioctl - * @mode: mode the block/char device is opened with + * @open_for_write: is the file / block device opened for writing? * @cmd: which ioctl is it * @arg: data associated with ioctl * @@ -860,7 +860,7 @@ static int scsi_ioctl_sg_io(struct scsi_device *sdev, fmode_t mode, * does not take a major/minor number as the dev field. Rather, it takes * a pointer to a &struct scsi_device. */ -int scsi_ioctl(struct scsi_device *sdev, fmode_t mode, int cmd, +int scsi_ioctl(struct scsi_device *sdev, bool open_for_write, int cmd, void __user *arg) { struct request_queue *q = sdev->request_queue; @@ -896,11 +896,11 @@ int scsi_ioctl(struct scsi_device *sdev, fmode_t mode, int cmd, case SG_EMULATED_HOST: return sg_emulated_host(q, arg); case SG_IO: - return scsi_ioctl_sg_io(sdev, mode, arg); + return scsi_ioctl_sg_io(sdev, open_for_write, arg); case SCSI_IOCTL_SEND_COMMAND: - return sg_scsi_ioctl(q, mode, arg); + return sg_scsi_ioctl(q, open_for_write, arg); case CDROM_SEND_PACKET: - return scsi_cdrom_send_packet(sdev, mode, arg); + return scsi_cdrom_send_packet(sdev, open_for_write, arg); case CDROMCLOSETRAY: return scsi_send_start_stop(sdev, 3); case CDROMEJECT: diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 0226c9279cef60b0daf3cebfba77c467200975c9..ad9afae49544ab66019655c424ede12471656b01 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -122,11 +122,9 @@ static void scsi_mq_requeue_cmd(struct scsi_cmnd *cmd, unsigned long msecs) WARN_ON_ONCE(true); } - if (msecs) { - blk_mq_requeue_request(rq, false); + blk_mq_requeue_request(rq, false); + if (!scsi_host_in_recovery(cmd->device->host)) blk_mq_delay_kick_requeue_list(rq->q, msecs); - } else - blk_mq_requeue_request(rq, true); } /** @@ -165,7 +163,8 @@ static void __scsi_queue_insert(struct scsi_cmnd *cmd, int reason, bool unbusy) */ cmd->result = 0; - blk_mq_requeue_request(scsi_cmd_to_rq(cmd), true); + blk_mq_requeue_request(scsi_cmd_to_rq(cmd), + !scsi_host_in_recovery(cmd->device->host)); } /** @@ -453,6 +452,7 @@ static void scsi_run_queue(struct request_queue *q) if (!list_empty(&sdev->host->starved_list)) scsi_starved_list_run(sdev->host); + blk_mq_kick_requeue_list(q); blk_mq_run_hw_queues(q, false); } @@ -503,6 +503,9 @@ static void scsi_mq_uninit_cmd(struct scsi_cmnd *cmd) static void scsi_run_queue_async(struct scsi_device *sdev) { + if (scsi_host_in_recovery(sdev->host)) + return; + if (scsi_target(sdev)->single_lun || !list_empty(&sdev->host->starved_list)) { kblockd_schedule_work(&sdev->requeue_work); @@ -578,11 +581,6 @@ static bool scsi_end_request(struct request *req, blk_status_t error, return false; } -static inline u8 get_scsi_ml_byte(int result) -{ - return (result >> 8) & 0xff; -} - /** * scsi_result_to_blk_status - translate a SCSI result code into blk_status_t * @result: scsi error code @@ -595,17 +593,19 @@ static blk_status_t scsi_result_to_blk_status(int result) * Check the scsi-ml byte first in case we converted a host or status * byte. */ - switch (get_scsi_ml_byte(result)) { + switch (scsi_ml_byte(result)) { case SCSIML_STAT_OK: break; case SCSIML_STAT_RESV_CONFLICT: - return BLK_STS_NEXUS; + return BLK_STS_RESV_CONFLICT; case SCSIML_STAT_NOSPC: return BLK_STS_NOSPC; case SCSIML_STAT_MED_ERROR: return BLK_STS_MEDIUM; case SCSIML_STAT_TGT_FAILURE: return BLK_STS_TARGET; + case SCSIML_STAT_DL_TIMEOUT: + return BLK_STS_DURATION_LIMIT; } switch (host_byte(result)) { @@ -803,6 +803,8 @@ static void scsi_io_completion_action(struct scsi_cmnd *cmd, int result) blk_stat = BLK_STS_ZONE_OPEN_RESOURCE; } break; + case COMPLETED: + fallthrough; default: action = ACTION_FAIL; break; @@ -1985,6 +1987,8 @@ int scsi_mq_setup_tags(struct Scsi_Host *shost) tag_set->flags = BLK_MQ_F_SHOULD_MERGE; tag_set->flags |= BLK_ALLOC_POLICY_TO_MQ_FLAG(shost->hostt->tag_alloc_policy); + if (shost->queuecommand_may_block) + tag_set->flags |= BLK_MQ_F_BLOCKING; tag_set->driver_data = shost; if (shost->host_tagset) tag_set->flags |= BLK_MQ_F_TAG_HCTX_SHARED; @@ -2152,6 +2156,7 @@ EXPORT_SYMBOL_GPL(scsi_mode_select); * @sdev: SCSI device to be queried * @dbd: set to prevent mode sense from returning block descriptors * @modepage: mode page being requested + * @subpage: sub-page of the mode page being requested * @buffer: request buffer (may not be smaller than eight bytes) * @len: length of request buffer. * @timeout: command timeout @@ -2163,7 +2168,7 @@ EXPORT_SYMBOL_GPL(scsi_mode_select); * Returns zero if successful, or a negative error number on failure */ int -scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage, +scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage, int subpage, unsigned char *buffer, int len, int timeout, int retries, struct scsi_mode_data *data, struct scsi_sense_hdr *sshdr) { @@ -2183,6 +2188,7 @@ scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage, dbd = sdev->set_dbd_for_ms ? 8 : dbd; cmd[1] = dbd & 0x18; /* allows DBD and LLBA bits */ cmd[2] = modepage; + cmd[3] = subpage; sshdr = exec_args.sshdr; @@ -2728,24 +2734,16 @@ void scsi_start_queue(struct scsi_device *sdev) blk_mq_unquiesce_queue(sdev->request_queue); } -static void scsi_stop_queue(struct scsi_device *sdev, bool nowait) +static void scsi_stop_queue(struct scsi_device *sdev) { /* * The atomic variable of ->queue_stopped covers that * blk_mq_quiesce_queue* is balanced with blk_mq_unquiesce_queue. * - * However, we still need to wait until quiesce is done - * in case that queue has been stopped. + * The caller needs to wait until quiesce is done. */ - if (!cmpxchg(&sdev->queue_stopped, 0, 1)) { - if (nowait) - blk_mq_quiesce_queue_nowait(sdev->request_queue); - else - blk_mq_quiesce_queue(sdev->request_queue); - } else { - if (!nowait) - blk_mq_wait_quiesce_done(sdev->request_queue->tag_set); - } + if (!cmpxchg(&sdev->queue_stopped, 0, 1)) + blk_mq_quiesce_queue_nowait(sdev->request_queue); } /** @@ -2772,19 +2770,19 @@ int scsi_internal_device_block_nowait(struct scsi_device *sdev) * request queue. */ if (!ret) - scsi_stop_queue(sdev, true); + scsi_stop_queue(sdev); return ret; } EXPORT_SYMBOL_GPL(scsi_internal_device_block_nowait); /** - * scsi_internal_device_block - try to transition to the SDEV_BLOCK state + * scsi_device_block - try to transition to the SDEV_BLOCK state * @sdev: device to block + * @data: dummy argument, ignored * - * Pause SCSI command processing on the specified device and wait until all - * ongoing scsi_request_fn() / scsi_queue_rq() calls have finished. May sleep. - * - * Returns zero if successful or a negative error code upon failure. + * Pause SCSI command processing on the specified device. Callers must wait + * until all ongoing scsi_queue_rq() calls have finished after this function + * returns. * * Note: * This routine transitions the device to the SDEV_BLOCK state (which must be @@ -2792,17 +2790,26 @@ EXPORT_SYMBOL_GPL(scsi_internal_device_block_nowait); * is paused until the device leaves the SDEV_BLOCK state. See also * scsi_internal_device_unblock(). */ -static int scsi_internal_device_block(struct scsi_device *sdev) +static void scsi_device_block(struct scsi_device *sdev, void *data) { int err; + enum scsi_device_state state; mutex_lock(&sdev->state_mutex); err = __scsi_internal_device_block_nowait(sdev); + state = sdev->sdev_state; if (err == 0) - scsi_stop_queue(sdev, false); + /* + * scsi_stop_queue() must be called with the state_mutex + * held. Otherwise a simultaneous scsi_start_queue() call + * might unquiesce the queue before we quiesce it. + */ + scsi_stop_queue(sdev); + mutex_unlock(&sdev->state_mutex); - return err; + WARN_ONCE(err, "%s: failed to block %s in state %d\n", + __func__, dev_name(&sdev->sdev_gendev), state); } /** @@ -2885,36 +2892,35 @@ static int scsi_internal_device_unblock(struct scsi_device *sdev, return ret; } -static void -device_block(struct scsi_device *sdev, void *data) -{ - int ret; - - ret = scsi_internal_device_block(sdev); - - WARN_ONCE(ret, "scsi_internal_device_block(%s) failed: ret = %d\n", - dev_name(&sdev->sdev_gendev), ret); -} - static int target_block(struct device *dev, void *data) { if (scsi_is_target_device(dev)) starget_for_each_device(to_scsi_target(dev), NULL, - device_block); + scsi_device_block); return 0; } +/** + * scsi_block_targets - transition all SCSI child devices to SDEV_BLOCK state + * @dev: a parent device of one or more scsi_target devices + * @shost: the Scsi_Host to which this device belongs + * + * Iterate over all children of @dev, which should be scsi_target devices, + * and switch all subordinate scsi devices to SDEV_BLOCK state. Wait for + * ongoing scsi_queue_rq() calls to finish. May sleep. + * + * Note: + * @dev must not itself be a scsi_target device. + */ void -scsi_target_block(struct device *dev) +scsi_block_targets(struct Scsi_Host *shost, struct device *dev) { - if (scsi_is_target_device(dev)) - starget_for_each_device(to_scsi_target(dev), NULL, - device_block); - else - device_for_each_child(dev, NULL, target_block); + WARN_ON_ONCE(scsi_is_target_device(dev)); + device_for_each_child(dev, NULL, target_block); + blk_mq_wait_quiesce_done(&shost->tag_set); } -EXPORT_SYMBOL_GPL(scsi_target_block); +EXPORT_SYMBOL_GPL(scsi_block_targets); static void device_unblock(struct scsi_device *sdev, void *data) @@ -2942,11 +2948,20 @@ scsi_target_unblock(struct device *dev, enum scsi_device_state new_state) } EXPORT_SYMBOL_GPL(scsi_target_unblock); +/** + * scsi_host_block - Try to transition all logical units to the SDEV_BLOCK state + * @shost: device to block + * + * Pause SCSI command processing for all logical units associated with the SCSI + * host and wait until pending scsi_queue_rq() calls have finished. + * + * Returns zero if successful or a negative error code upon failure. + */ int scsi_host_block(struct Scsi_Host *shost) { struct scsi_device *sdev; - int ret = 0; + int ret; /* * Call scsi_internal_device_block_nowait so we can avoid @@ -2958,20 +2973,14 @@ scsi_host_block(struct Scsi_Host *shost) mutex_unlock(&sdev->state_mutex); if (ret) { scsi_device_put(sdev); - break; + return ret; } } - /* - * SCSI never enables blk-mq's BLK_MQ_F_BLOCKING flag so - * calling synchronize_rcu() once is enough. - */ - WARN_ON_ONCE(shost->tag_set.flags & BLK_MQ_F_BLOCKING); - - if (!ret) - synchronize_rcu(); + /* Wait for ongoing scsi_queue_rq() calls to finish. */ + blk_mq_wait_quiesce_done(&shost->tag_set); - return ret; + return 0; } EXPORT_SYMBOL_GPL(scsi_host_block); diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h index 96284a0e13fea26d0d7d35255aa0b6b01585dfa0..f42388ecb02488d3042a63c816ac897e975b1062 100644 --- a/drivers/scsi/scsi_priv.h +++ b/drivers/scsi/scsi_priv.h @@ -27,8 +27,14 @@ enum scsi_ml_status { SCSIML_STAT_NOSPC = 0x02, /* Space allocation on the dev failed */ SCSIML_STAT_MED_ERROR = 0x03, /* Medium error */ SCSIML_STAT_TGT_FAILURE = 0x04, /* Permanent target failure */ + SCSIML_STAT_DL_TIMEOUT = 0x05, /* Command Duration Limit timeout */ }; +static inline u8 scsi_ml_byte(int result) +{ + return (result >> 8) & 0xff; +} + /* * Scsi Error Handler Flags */ diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index d217be323cc690f0736df29349d085bd27575170..aa13feb17c62605a15379cae725514acf2a8a09c 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -1087,6 +1087,8 @@ static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result, if (sdev->scsi_level >= SCSI_3) scsi_attach_vpd(sdev); + scsi_cdl_check(sdev); + sdev->max_queue_depth = sdev->queue_depth; WARN_ON_ONCE(sdev->max_queue_depth > sdev->budget_map.depth); sdev->sdev_bflags = *bflags; @@ -1624,6 +1626,7 @@ void scsi_rescan_device(struct device *dev) device_lock(dev); scsi_attach_vpd(sdev); + scsi_cdl_check(sdev); if (sdev->handler && sdev->handler->rescan) sdev->handler->rescan(sdev); diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index 603e8fcfcb8a0c0a80beeceedd5e3391abd25133..60317676e45f19bf7328d84422cb7f5f079bcb13 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -670,6 +670,7 @@ sdev_rd_attr (scsi_level, "%d\n"); sdev_rd_attr (vendor, "%.8s\n"); sdev_rd_attr (model, "%.16s\n"); sdev_rd_attr (rev, "%.4s\n"); +sdev_rd_attr (cdl_supported, "%d\n"); static ssize_t sdev_show_device_busy(struct device *dev, struct device_attribute *attr, @@ -1221,6 +1222,33 @@ static DEVICE_ATTR(queue_ramp_up_period, S_IRUGO | S_IWUSR, sdev_show_queue_ramp_up_period, sdev_store_queue_ramp_up_period); +static ssize_t sdev_show_cdl_enable(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct scsi_device *sdev = to_scsi_device(dev); + + return sysfs_emit(buf, "%d\n", (int)sdev->cdl_enable); +} + +static ssize_t sdev_store_cdl_enable(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + int ret; + bool v; + + if (kstrtobool(buf, &v)) + return -EINVAL; + + ret = scsi_cdl_enable(to_scsi_device(dev), v); + if (ret) + return ret; + + return count; +} +static DEVICE_ATTR(cdl_enable, S_IRUGO | S_IWUSR, + sdev_show_cdl_enable, sdev_store_cdl_enable); + static umode_t scsi_sdev_attr_is_visible(struct kobject *kobj, struct attribute *attr, int i) { @@ -1300,6 +1328,8 @@ static struct attribute *scsi_sdev_attrs[] = { &dev_attr_preferred_path.attr, #endif &dev_attr_queue_ramp_up_period.attr, + &dev_attr_cdl_supported.attr, + &dev_attr_cdl_enable.attr, REF_EVT(media_change), REF_EVT(inquiry_change_reported), REF_EVT(capacity_change_reported), diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index 64ff2629eaf98c196d67c0b2887cbac961ad30de..b04075f19445dc97c4ec98baaadf1184d004cd18 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c @@ -3451,7 +3451,7 @@ fc_remote_port_delete(struct fc_rport *rport) spin_unlock_irqrestore(shost->host_lock, flags); - scsi_target_block(&rport->dev); + scsi_block_targets(shost, &rport->dev); /* see if we need to kill io faster than waiting for device loss */ if ((rport->fast_io_fail_tmo != -1) && diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index b9b97300e3b3ca6b566813e1d6664da56bfdbc93..e527ece12453a1f0c5eb0df2986432fd11eb8391 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -1943,13 +1943,14 @@ static void __iscsi_block_session(struct work_struct *work) struct iscsi_cls_session *session = container_of(work, struct iscsi_cls_session, block_work); + struct Scsi_Host *shost = iscsi_session_to_shost(session); unsigned long flags; ISCSI_DBG_TRANS_SESSION(session, "Blocking session\n"); spin_lock_irqsave(&session->lock, flags); session->state = ISCSI_SESSION_FAILED; spin_unlock_irqrestore(&session->lock, flags); - scsi_target_block(&session->dev); + scsi_block_targets(shost, &session->dev); ISCSI_DBG_TRANS_SESSION(session, "Completed SCSI target blocking\n"); if (session->recovery_tmo >= 0) queue_delayed_work(session->workq, diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c index 74b99f2b0b74ac5c32ef00fe6ca698b4f5f7f0ae..d704c484a251c5d3ebf112a4b9b68e32a3822d4a 100644 --- a/drivers/scsi/scsi_transport_sas.c +++ b/drivers/scsi/scsi_transport_sas.c @@ -1245,7 +1245,7 @@ int sas_read_port_mode_page(struct scsi_device *sdev) if (!buffer) return -ENOMEM; - error = scsi_mode_sense(sdev, 1, 0x19, buffer, BUF_SIZE, 30*HZ, 3, + error = scsi_mode_sense(sdev, 1, 0x19, 0, buffer, BUF_SIZE, 30*HZ, 3, &mode_data, NULL); if (error) diff --git a/drivers/scsi/scsi_transport_srp.c b/drivers/scsi/scsi_transport_srp.c index 87d0fb8dc50327f33abb7d62a22505559018c30e..64f6b22e8cc0c9663b3b7fb736b7135e7659a539 100644 --- a/drivers/scsi/scsi_transport_srp.c +++ b/drivers/scsi/scsi_transport_srp.c @@ -396,7 +396,7 @@ static void srp_reconnect_work(struct work_struct *work) } /* - * scsi_target_block() must have been called before this function is + * scsi_block_targets() must have been called before this function is * called to guarantee that no .queuecommand() calls are in progress. */ static void __rport_fail_io_fast(struct srp_rport *rport) @@ -480,7 +480,7 @@ static void __srp_start_tl_fail_timers(struct srp_rport *rport) srp_rport_set_state(rport, SRP_RPORT_BLOCKED) == 0) { pr_debug("%s new state: %d\n", dev_name(&shost->shost_gendev), rport->state); - scsi_target_block(&shost->shost_gendev); + scsi_block_targets(shost, &shost->shost_gendev); if (fast_io_fail_tmo >= 0) queue_delayed_work(system_long_wq, &rport->fast_io_fail_work, @@ -548,7 +548,7 @@ int srp_reconnect_rport(struct srp_rport *rport) * later is ok though, scsi_internal_device_unblock_nowait() * treats SDEV_TRANSPORT_OFFLINE like SDEV_BLOCK. */ - scsi_target_block(&shost->shost_gendev); + scsi_block_targets(shost, &shost->shost_gendev); res = rport->state != SRP_RPORT_LOST ? i->f->reconnect(rport) : -ENODEV; pr_debug("%s (state %d): transport.reconnect() returned %d\n", dev_name(&shost->shost_gendev), rport->state, res); diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 1624d528aa1f9c5f525aa704b22314029f73af60..68b12afa07219a7bb692568438816bacd44d3d24 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -67,6 +67,7 @@ #include #include #include +#include #include "sd.h" #include "scsi_priv.h" @@ -183,7 +184,7 @@ cache_type_store(struct device *dev, struct device_attribute *attr, return count; } - if (scsi_mode_sense(sdp, 0x08, 8, buffer, sizeof(buffer), SD_TIMEOUT, + if (scsi_mode_sense(sdp, 0x08, 8, 0, buffer, sizeof(buffer), SD_TIMEOUT, sdkp->max_retries, &data, NULL)) return -EINVAL; len = min_t(size_t, sizeof(buffer), data.length - data.header_length - @@ -1041,13 +1042,14 @@ static blk_status_t sd_setup_flush_cmnd(struct scsi_cmnd *cmd) static blk_status_t sd_setup_rw32_cmnd(struct scsi_cmnd *cmd, bool write, sector_t lba, unsigned int nr_blocks, - unsigned char flags) + unsigned char flags, unsigned int dld) { cmd->cmd_len = SD_EXT_CDB_SIZE; cmd->cmnd[0] = VARIABLE_LENGTH_CMD; cmd->cmnd[7] = 0x18; /* Additional CDB len */ cmd->cmnd[9] = write ? WRITE_32 : READ_32; cmd->cmnd[10] = flags; + cmd->cmnd[11] = dld & 0x07; put_unaligned_be64(lba, &cmd->cmnd[12]); put_unaligned_be32(lba, &cmd->cmnd[20]); /* Expected Indirect LBA */ put_unaligned_be32(nr_blocks, &cmd->cmnd[28]); @@ -1057,12 +1059,12 @@ static blk_status_t sd_setup_rw32_cmnd(struct scsi_cmnd *cmd, bool write, static blk_status_t sd_setup_rw16_cmnd(struct scsi_cmnd *cmd, bool write, sector_t lba, unsigned int nr_blocks, - unsigned char flags) + unsigned char flags, unsigned int dld) { cmd->cmd_len = 16; cmd->cmnd[0] = write ? WRITE_16 : READ_16; - cmd->cmnd[1] = flags; - cmd->cmnd[14] = 0; + cmd->cmnd[1] = flags | ((dld >> 2) & 0x01); + cmd->cmnd[14] = (dld & 0x03) << 6; cmd->cmnd[15] = 0; put_unaligned_be64(lba, &cmd->cmnd[2]); put_unaligned_be32(nr_blocks, &cmd->cmnd[10]); @@ -1114,6 +1116,31 @@ static blk_status_t sd_setup_rw6_cmnd(struct scsi_cmnd *cmd, bool write, return BLK_STS_OK; } +/* + * Check if a command has a duration limit set. If it does, and the target + * device supports CDL and the feature is enabled, return the limit + * descriptor index to use. Return 0 (no limit) otherwise. + */ +static int sd_cdl_dld(struct scsi_disk *sdkp, struct scsi_cmnd *scmd) +{ + struct scsi_device *sdp = sdkp->device; + int hint; + + if (!sdp->cdl_supported || !sdp->cdl_enable) + return 0; + + /* + * Use "no limit" if the request ioprio does not specify a duration + * limit hint. + */ + hint = IOPRIO_PRIO_HINT(req_get_ioprio(scsi_cmd_to_rq(scmd))); + if (hint < IOPRIO_HINT_DEV_DURATION_LIMIT_1 || + hint > IOPRIO_HINT_DEV_DURATION_LIMIT_7) + return 0; + + return (hint - IOPRIO_HINT_DEV_DURATION_LIMIT_1) + 1; +} + static blk_status_t sd_setup_read_write_cmnd(struct scsi_cmnd *cmd) { struct request *rq = scsi_cmd_to_rq(cmd); @@ -1125,6 +1152,7 @@ static blk_status_t sd_setup_read_write_cmnd(struct scsi_cmnd *cmd) unsigned int mask = logical_to_sectors(sdp, 1) - 1; bool write = rq_data_dir(rq) == WRITE; unsigned char protect, fua; + unsigned int dld; blk_status_t ret; unsigned int dif; bool dix; @@ -1174,6 +1202,7 @@ static blk_status_t sd_setup_read_write_cmnd(struct scsi_cmnd *cmd) fua = rq->cmd_flags & REQ_FUA ? 0x8 : 0; dix = scsi_prot_sg_count(cmd); dif = scsi_host_dif_capable(cmd->device->host, sdkp->protection_type); + dld = sd_cdl_dld(sdkp, cmd); if (dif || dix) protect = sd_setup_protect_cmnd(cmd, dix, dif); @@ -1182,10 +1211,10 @@ static blk_status_t sd_setup_read_write_cmnd(struct scsi_cmnd *cmd) if (protect && sdkp->protection_type == T10_PI_TYPE2_PROTECTION) { ret = sd_setup_rw32_cmnd(cmd, write, lba, nr_blocks, - protect | fua); + protect | fua, dld); } else if (sdp->use_16_for_rw || (nr_blocks > 0xffff)) { ret = sd_setup_rw16_cmnd(cmd, write, lba, nr_blocks, - protect | fua); + protect | fua, dld); } else if ((nr_blocks > 0xff) || (lba > 0x1fffff) || sdp->use_10_for_rw || protect) { ret = sd_setup_rw10_cmnd(cmd, write, lba, nr_blocks, @@ -1280,11 +1309,10 @@ static void sd_uninit_command(struct scsi_cmnd *SCpnt) mempool_free(rq->special_vec.bv_page, sd_page_pool); } -static bool sd_need_revalidate(struct block_device *bdev, - struct scsi_disk *sdkp) +static bool sd_need_revalidate(struct gendisk *disk, struct scsi_disk *sdkp) { if (sdkp->device->removable || sdkp->write_prot) { - if (bdev_check_media_change(bdev)) + if (disk_check_media_change(disk)) return true; } @@ -1293,13 +1321,13 @@ static bool sd_need_revalidate(struct block_device *bdev, * nothing to do with partitions, BLKRRPART is used to force a full * revalidate after things like a format for historical reasons. */ - return test_bit(GD_NEED_PART_SCAN, &bdev->bd_disk->state); + return test_bit(GD_NEED_PART_SCAN, &disk->state); } /** * sd_open - open a scsi disk device - * @bdev: Block device of the scsi disk to open - * @mode: FMODE_* mask + * @disk: disk to open + * @mode: open mode * * Returns 0 if successful. Returns a negated errno value in case * of error. @@ -1309,11 +1337,11 @@ static bool sd_need_revalidate(struct block_device *bdev, * In the latter case @inode and @filp carry an abridged amount * of information as noted above. * - * Locking: called with bdev->bd_disk->open_mutex held. + * Locking: called with disk->open_mutex held. **/ -static int sd_open(struct block_device *bdev, fmode_t mode) +static int sd_open(struct gendisk *disk, blk_mode_t mode) { - struct scsi_disk *sdkp = scsi_disk(bdev->bd_disk); + struct scsi_disk *sdkp = scsi_disk(disk); struct scsi_device *sdev = sdkp->device; int retval; @@ -1330,14 +1358,15 @@ static int sd_open(struct block_device *bdev, fmode_t mode) if (!scsi_block_when_processing_errors(sdev)) goto error_out; - if (sd_need_revalidate(bdev, sdkp)) - sd_revalidate_disk(bdev->bd_disk); + if (sd_need_revalidate(disk, sdkp)) + sd_revalidate_disk(disk); /* * If the drive is empty, just let the open fail. */ retval = -ENOMEDIUM; - if (sdev->removable && !sdkp->media_present && !(mode & FMODE_NDELAY)) + if (sdev->removable && !sdkp->media_present && + !(mode & BLK_OPEN_NDELAY)) goto error_out; /* @@ -1345,7 +1374,7 @@ static int sd_open(struct block_device *bdev, fmode_t mode) * if the user expects to be able to write to the thing. */ retval = -EROFS; - if (sdkp->write_prot && (mode & FMODE_WRITE)) + if (sdkp->write_prot && (mode & BLK_OPEN_WRITE)) goto error_out; /* @@ -1374,16 +1403,15 @@ static int sd_open(struct block_device *bdev, fmode_t mode) * sd_release - invoked when the (last) close(2) is called on this * scsi disk. * @disk: disk to release - * @mode: FMODE_* mask * * Returns 0. * * Note: may block (uninterruptible) if error recovery is underway * on this disk. * - * Locking: called with bdev->bd_disk->open_mutex held. + * Locking: called with disk->open_mutex held. **/ -static void sd_release(struct gendisk *disk, fmode_t mode) +static void sd_release(struct gendisk *disk) { struct scsi_disk *sdkp = scsi_disk(disk); struct scsi_device *sdev = sdkp->device; @@ -1426,7 +1454,7 @@ static int sd_getgeo(struct block_device *bdev, struct hd_geometry *geo) /** * sd_ioctl - process an ioctl * @bdev: target block device - * @mode: FMODE_* mask + * @mode: open mode * @cmd: ioctl command number * @arg: this is third argument given to ioctl(2) system call. * Often contains a pointer. @@ -1437,7 +1465,7 @@ static int sd_getgeo(struct block_device *bdev, struct hd_geometry *geo) * Note: most ioctls are forward onto the block subsystem or further * down in the scsi subsystem. **/ -static int sd_ioctl(struct block_device *bdev, fmode_t mode, +static int sd_ioctl(struct block_device *bdev, blk_mode_t mode, unsigned int cmd, unsigned long arg) { struct gendisk *disk = bdev->bd_disk; @@ -1459,13 +1487,13 @@ static int sd_ioctl(struct block_device *bdev, fmode_t mode, * access to the device is prohibited. */ error = scsi_ioctl_block_when_processing_errors(sdp, cmd, - (mode & FMODE_NDELAY) != 0); + (mode & BLK_OPEN_NDELAY)); if (error) return error; if (is_sed_ioctl(cmd)) return sed_ioctl(sdkp->opal_dev, cmd, p); - return scsi_ioctl(sdp, mode, cmd, p); + return scsi_ioctl(sdp, mode & BLK_OPEN_WRITE, cmd, p); } static void set_media_not_present(struct scsi_disk *sdkp) @@ -1691,26 +1719,6 @@ static int sd_get_unique_id(struct gendisk *disk, u8 id[16], return ret; } -static char sd_pr_type(enum pr_type type) -{ - switch (type) { - case PR_WRITE_EXCLUSIVE: - return 0x01; - case PR_EXCLUSIVE_ACCESS: - return 0x03; - case PR_WRITE_EXCLUSIVE_REG_ONLY: - return 0x05; - case PR_EXCLUSIVE_ACCESS_REG_ONLY: - return 0x06; - case PR_WRITE_EXCLUSIVE_ALL_REGS: - return 0x07; - case PR_EXCLUSIVE_ACCESS_ALL_REGS: - return 0x08; - default: - return 0; - } -}; - static int sd_scsi_to_pr_err(struct scsi_sense_hdr *sshdr, int result) { switch (host_byte(result)) { @@ -1741,8 +1749,97 @@ static int sd_scsi_to_pr_err(struct scsi_sense_hdr *sshdr, int result) } } -static int sd_pr_command(struct block_device *bdev, u8 sa, - u64 key, u64 sa_key, u8 type, u8 flags) +static int sd_pr_in_command(struct block_device *bdev, u8 sa, + unsigned char *data, int data_len) +{ + struct scsi_disk *sdkp = scsi_disk(bdev->bd_disk); + struct scsi_device *sdev = sdkp->device; + struct scsi_sense_hdr sshdr; + u8 cmd[10] = { PERSISTENT_RESERVE_IN, sa }; + const struct scsi_exec_args exec_args = { + .sshdr = &sshdr, + }; + int result; + + put_unaligned_be16(data_len, &cmd[7]); + + result = scsi_execute_cmd(sdev, cmd, REQ_OP_DRV_IN, data, data_len, + SD_TIMEOUT, sdkp->max_retries, &exec_args); + if (scsi_status_is_check_condition(result) && + scsi_sense_valid(&sshdr)) { + sdev_printk(KERN_INFO, sdev, "PR command failed: %d\n", result); + scsi_print_sense_hdr(sdev, NULL, &sshdr); + } + + if (result <= 0) + return result; + + return sd_scsi_to_pr_err(&sshdr, result); +} + +static int sd_pr_read_keys(struct block_device *bdev, struct pr_keys *keys_info) +{ + int result, i, data_offset, num_copy_keys; + u32 num_keys = keys_info->num_keys; + int data_len = num_keys * 8 + 8; + u8 *data; + + data = kzalloc(data_len, GFP_KERNEL); + if (!data) + return -ENOMEM; + + result = sd_pr_in_command(bdev, READ_KEYS, data, data_len); + if (result) + goto free_data; + + keys_info->generation = get_unaligned_be32(&data[0]); + keys_info->num_keys = get_unaligned_be32(&data[4]) / 8; + + data_offset = 8; + num_copy_keys = min(num_keys, keys_info->num_keys); + + for (i = 0; i < num_copy_keys; i++) { + keys_info->keys[i] = get_unaligned_be64(&data[data_offset]); + data_offset += 8; + } + +free_data: + kfree(data); + return result; +} + +static int sd_pr_read_reservation(struct block_device *bdev, + struct pr_held_reservation *rsv) +{ + struct scsi_disk *sdkp = scsi_disk(bdev->bd_disk); + struct scsi_device *sdev = sdkp->device; + u8 data[24] = { }; + int result, len; + + result = sd_pr_in_command(bdev, READ_RESERVATION, data, sizeof(data)); + if (result) + return result; + + len = get_unaligned_be32(&data[4]); + if (!len) + return 0; + + /* Make sure we have at least the key and type */ + if (len < 14) { + sdev_printk(KERN_INFO, sdev, + "READ RESERVATION failed due to short return buffer of %d bytes\n", + len); + return -EINVAL; + } + + rsv->generation = get_unaligned_be32(&data[0]); + rsv->key = get_unaligned_be64(&data[8]); + rsv->type = scsi_pr_type_to_block(data[21] & 0x0f); + return 0; +} + +static int sd_pr_out_command(struct block_device *bdev, u8 sa, u64 key, + u64 sa_key, enum scsi_pr_type type, u8 flags) { struct scsi_disk *sdkp = scsi_disk(bdev->bd_disk); struct scsi_device *sdev = sdkp->device; @@ -1784,7 +1881,7 @@ static int sd_pr_register(struct block_device *bdev, u64 old_key, u64 new_key, { if (flags & ~PR_FL_IGNORE_KEY) return -EOPNOTSUPP; - return sd_pr_command(bdev, (flags & PR_FL_IGNORE_KEY) ? 0x06 : 0x00, + return sd_pr_out_command(bdev, (flags & PR_FL_IGNORE_KEY) ? 0x06 : 0x00, old_key, new_key, 0, (1 << 0) /* APTPL */); } @@ -1794,24 +1891,26 @@ static int sd_pr_reserve(struct block_device *bdev, u64 key, enum pr_type type, { if (flags) return -EOPNOTSUPP; - return sd_pr_command(bdev, 0x01, key, 0, sd_pr_type(type), 0); + return sd_pr_out_command(bdev, 0x01, key, 0, + block_pr_type_to_scsi(type), 0); } static int sd_pr_release(struct block_device *bdev, u64 key, enum pr_type type) { - return sd_pr_command(bdev, 0x02, key, 0, sd_pr_type(type), 0); + return sd_pr_out_command(bdev, 0x02, key, 0, + block_pr_type_to_scsi(type), 0); } static int sd_pr_preempt(struct block_device *bdev, u64 old_key, u64 new_key, enum pr_type type, bool abort) { - return sd_pr_command(bdev, abort ? 0x05 : 0x04, old_key, new_key, - sd_pr_type(type), 0); + return sd_pr_out_command(bdev, abort ? 0x05 : 0x04, old_key, new_key, + block_pr_type_to_scsi(type), 0); } static int sd_pr_clear(struct block_device *bdev, u64 key) { - return sd_pr_command(bdev, 0x03, key, 0, 0, 0); + return sd_pr_out_command(bdev, 0x03, key, 0, 0, 0); } static const struct pr_ops sd_pr_ops = { @@ -1820,6 +1919,8 @@ static const struct pr_ops sd_pr_ops = { .pr_release = sd_pr_release, .pr_preempt = sd_pr_preempt, .pr_clear = sd_pr_clear, + .pr_read_keys = sd_pr_read_keys, + .pr_read_reservation = sd_pr_read_reservation, }; static void scsi_disk_free_disk(struct gendisk *disk) @@ -2609,9 +2710,8 @@ sd_do_mode_sense(struct scsi_disk *sdkp, int dbd, int modepage, if (sdkp->device->use_10_for_ms && len < 8) len = 8; - return scsi_mode_sense(sdkp->device, dbd, modepage, buffer, len, - SD_TIMEOUT, sdkp->max_retries, data, - sshdr); + return scsi_mode_sense(sdkp->device, dbd, modepage, 0, buffer, len, + SD_TIMEOUT, sdkp->max_retries, data, sshdr); } /* @@ -2868,7 +2968,7 @@ static void sd_read_app_tag_own(struct scsi_disk *sdkp, unsigned char *buffer) if (sdkp->protection_type == 0) return; - res = scsi_mode_sense(sdp, 1, 0x0a, buffer, 36, SD_TIMEOUT, + res = scsi_mode_sense(sdp, 1, 0x0a, 0, buffer, 36, SD_TIMEOUT, sdkp->max_retries, &data, &sshdr); if (res < 0 || !data.header_length || @@ -3057,7 +3157,7 @@ static void sd_read_write_same(struct scsi_disk *sdkp, unsigned char *buffer) return; } - if (scsi_report_opcode(sdev, buffer, SD_BUF_SIZE, INQUIRY) < 0) { + if (scsi_report_opcode(sdev, buffer, SD_BUF_SIZE, INQUIRY, 0) < 0) { struct scsi_vpd *vpd; sdev->no_report_opcodes = 1; @@ -3073,10 +3173,10 @@ static void sd_read_write_same(struct scsi_disk *sdkp, unsigned char *buffer) rcu_read_unlock(); } - if (scsi_report_opcode(sdev, buffer, SD_BUF_SIZE, WRITE_SAME_16) == 1) + if (scsi_report_opcode(sdev, buffer, SD_BUF_SIZE, WRITE_SAME_16, 0) == 1) sdkp->ws16 = 1; - if (scsi_report_opcode(sdev, buffer, SD_BUF_SIZE, WRITE_SAME) == 1) + if (scsi_report_opcode(sdev, buffer, SD_BUF_SIZE, WRITE_SAME, 0) == 1) sdkp->ws10 = 1; } @@ -3088,9 +3188,9 @@ static void sd_read_security(struct scsi_disk *sdkp, unsigned char *buffer) return; if (scsi_report_opcode(sdev, buffer, SD_BUF_SIZE, - SECURITY_PROTOCOL_IN) == 1 && + SECURITY_PROTOCOL_IN, 0) == 1 && scsi_report_opcode(sdev, buffer, SD_BUF_SIZE, - SECURITY_PROTOCOL_OUT) == 1) + SECURITY_PROTOCOL_OUT, 0) == 1) sdkp->security = 1; } diff --git a/drivers/scsi/sd_zbc.c b/drivers/scsi/sd_zbc.c index 22801c24ea193c795a014a168d0df213a993fdad..a25215507668d8e6ae83b91f2acfd799fa5dcbce 100644 --- a/drivers/scsi/sd_zbc.c +++ b/drivers/scsi/sd_zbc.c @@ -831,7 +831,6 @@ int sd_zbc_revalidate_zones(struct scsi_disk *sdkp) struct request_queue *q = disk->queue; u32 zone_blocks = sdkp->early_zone_info.zone_blocks; unsigned int nr_zones = sdkp->early_zone_info.nr_zones; - u32 max_append; int ret = 0; unsigned int flags; @@ -876,6 +875,11 @@ int sd_zbc_revalidate_zones(struct scsi_disk *sdkp) goto unlock; } + blk_queue_chunk_sectors(q, + logical_to_sectors(sdkp->device, zone_blocks)); + blk_queue_max_zone_append_sectors(q, + q->limits.max_segments << PAGE_SECTORS_SHIFT); + ret = blk_revalidate_disk_zones(disk, sd_zbc_revalidate_zones_cb); memalloc_noio_restore(flags); @@ -888,12 +892,6 @@ int sd_zbc_revalidate_zones(struct scsi_disk *sdkp) goto unlock; } - max_append = min_t(u32, logical_to_sectors(sdkp->device, zone_blocks), - q->limits.max_segments << (PAGE_SHIFT - 9)); - max_append = min_t(u32, max_append, queue_max_hw_sectors(q)); - - blk_queue_max_zone_append_sectors(q, max_append); - sd_zbc_print_zones(sdkp); unlock: diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 037f8c98a6d36481a21a8f758056308848400bb1..89fa046c7158a1fccf342317a89ee345c6279f8d 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -71,7 +71,7 @@ static int sg_proc_init(void); #define SG_ALLOW_DIO_DEF 0 -#define SG_MAX_DEVS 32768 +#define SG_MAX_DEVS (1 << MINORBITS) /* SG_MAX_CDB_SIZE should be 260 (spc4r37 section 3.1.30) however the type * of sg_io_hdr::cmd_len can only represent 255. All SCSI commands greater @@ -237,7 +237,7 @@ static int sg_allow_access(struct file *filp, unsigned char *cmd) if (sfp->parentdp->device->type == TYPE_SCANNER) return 0; - if (!scsi_cmd_allowed(cmd, filp->f_mode)) + if (!scsi_cmd_allowed(cmd, filp->f_mode & FMODE_WRITE)) return -EPERM; return 0; } @@ -1103,7 +1103,8 @@ sg_ioctl_common(struct file *filp, Sg_device *sdp, Sg_fd *sfp, case SCSI_IOCTL_SEND_COMMAND: if (atomic_read(&sdp->detaching)) return -ENODEV; - return scsi_ioctl(sdp->device, filp->f_mode, cmd_in, p); + return scsi_ioctl(sdp->device, filp->f_mode & FMODE_WRITE, + cmd_in, p); case SG_SET_DEBUG: result = get_user(val, ip); if (result) @@ -1159,7 +1160,7 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg) ret = sg_ioctl_common(filp, sdp, sfp, cmd_in, p); if (ret != -ENOIOCTLCMD) return ret; - return scsi_ioctl(sdp->device, filp->f_mode, cmd_in, p); + return scsi_ioctl(sdp->device, filp->f_mode & FMODE_WRITE, cmd_in, p); } static __poll_t @@ -1496,6 +1497,10 @@ sg_add_device(struct device *cl_dev) int error; unsigned long iflags; + error = blk_get_queue(scsidp->request_queue); + if (error) + return error; + error = -ENOMEM; cdev = cdev_alloc(); if (!cdev) { @@ -1553,6 +1558,7 @@ sg_add_device(struct device *cl_dev) out: if (cdev) cdev_del(cdev); + blk_put_queue(scsidp->request_queue); return error; } @@ -1560,6 +1566,7 @@ static void sg_device_destroy(struct kref *kref) { struct sg_device *sdp = container_of(kref, struct sg_device, d_ref); + struct request_queue *q = sdp->device->request_queue; unsigned long flags; /* CAUTION! Note that the device can still be found via idr_find() @@ -1567,6 +1574,9 @@ sg_device_destroy(struct kref *kref) * any other cleanup. */ + blk_trace_remove(q); + blk_put_queue(q); + write_lock_irqsave(&sg_index_lock, flags); idr_remove(&sg_index_idr, sdp->index); write_unlock_irqrestore(&sg_index_lock, flags); diff --git a/drivers/scsi/smartpqi/Kconfig b/drivers/scsi/smartpqi/Kconfig index 973d240649ab59cbcb1816f70c14beb9d13e5b56..789460b0a342ba18f5421280e73158dcc24e421b 100644 --- a/drivers/scsi/smartpqi/Kconfig +++ b/drivers/scsi/smartpqi/Kconfig @@ -1,7 +1,7 @@ # # Kernel configuration file for the SMARTPQI # -# Copyright (c) 2019-2022 Microchip Technology Inc. and its subsidiaries +# Copyright (c) 2019-2023 Microchip Technology Inc. and its subsidiaries # Copyright (c) 2017-2018 Microsemi Corporation # Copyright (c) 2016 Microsemi Corporation # Copyright (c) 2016 PMC-Sierra, Inc. diff --git a/drivers/scsi/smartpqi/smartpqi.h b/drivers/scsi/smartpqi/smartpqi.h index 228838eb3686f5739a75b176d504a4a7b5b90f85..e392eaf5b2bf70cfac506019cad805cf401ca777 100644 --- a/drivers/scsi/smartpqi/smartpqi.h +++ b/drivers/scsi/smartpqi/smartpqi.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 */ /* * driver for Microchip PQI-based storage controllers - * Copyright (c) 2019-2022 Microchip Technology Inc. and its subsidiaries + * Copyright (c) 2019-2023 Microchip Technology Inc. and its subsidiaries * Copyright (c) 2016-2018 Microsemi Corporation * Copyright (c) 2016 PMC-Sierra, Inc. * @@ -982,12 +982,12 @@ struct report_phys_lun_16byte_wwid { struct report_phys_lun_8byte_wwid_list { struct report_lun_header header; - struct report_phys_lun_8byte_wwid lun_entries[1]; + struct report_phys_lun_8byte_wwid lun_entries[]; }; struct report_phys_lun_16byte_wwid_list { struct report_lun_header header; - struct report_phys_lun_16byte_wwid lun_entries[1]; + struct report_phys_lun_16byte_wwid lun_entries[]; }; struct raid_map_disk_data { @@ -1108,6 +1108,7 @@ struct pqi_scsi_dev { u8 volume_offline : 1; u8 rescan : 1; u8 ignore_device : 1; + u8 erase_in_progress : 1; bool aio_enabled; /* only valid for physical disks */ bool in_remove; bool device_offline; @@ -1147,7 +1148,7 @@ struct pqi_scsi_dev { struct pqi_stream_data stream_data[NUM_STREAMS_PER_LUN]; atomic_t scsi_cmds_outstanding[PQI_MAX_LUNS_PER_DEVICE]; - atomic_t raid_bypass_cnt; + unsigned int raid_bypass_cnt; }; /* VPD inquiry pages */ @@ -1357,6 +1358,7 @@ struct pqi_ctrl_info { u32 max_write_raid_5_6; u32 max_write_raid_1_10_2drive; u32 max_write_raid_1_10_3drive; + int numa_node; struct list_head scsi_device_list; spinlock_t scsi_device_list_lock; diff --git a/drivers/scsi/smartpqi/smartpqi_init.c b/drivers/scsi/smartpqi/smartpqi_init.c index 03de97cd72c22c162c52c94e6490b72124feba37..6aaaa7ebca377bf4f1fb50b4bdd8f0d3e8924b34 100644 --- a/drivers/scsi/smartpqi/smartpqi_init.c +++ b/drivers/scsi/smartpqi/smartpqi_init.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 /* * driver for Microchip PQI-based storage controllers - * Copyright (c) 2019-2022 Microchip Technology Inc. and its subsidiaries + * Copyright (c) 2019-2023 Microchip Technology Inc. and its subsidiaries * Copyright (c) 2016-2018 Microsemi Corporation * Copyright (c) 2016 PMC-Sierra, Inc. * @@ -33,11 +33,11 @@ #define BUILD_TIMESTAMP #endif -#define DRIVER_VERSION "2.1.20-035" +#define DRIVER_VERSION "2.1.22-040" #define DRIVER_MAJOR 2 #define DRIVER_MINOR 1 -#define DRIVER_RELEASE 20 -#define DRIVER_REVISION 35 +#define DRIVER_RELEASE 22 +#define DRIVER_REVISION 40 #define DRIVER_NAME "Microchip SmartPQI Driver (v" \ DRIVER_VERSION BUILD_TIMESTAMP ")" @@ -519,6 +519,36 @@ static inline void pqi_clear_soft_reset_status(struct pqi_ctrl_info *ctrl_info) writeb(status, ctrl_info->soft_reset_status); } +static inline bool pqi_is_io_high_priority(struct pqi_scsi_dev *device, struct scsi_cmnd *scmd) +{ + bool io_high_prio; + int priority_class; + + io_high_prio = false; + + if (device->ncq_prio_enable) { + priority_class = + IOPRIO_PRIO_CLASS(req_get_ioprio(scsi_cmd_to_rq(scmd))); + if (priority_class == IOPRIO_CLASS_RT) { + /* Set NCQ priority for read/write commands. */ + switch (scmd->cmnd[0]) { + case WRITE_16: + case READ_16: + case WRITE_12: + case READ_12: + case WRITE_10: + case READ_10: + case WRITE_6: + case READ_6: + io_high_prio = true; + break; + } + } + } + + return io_high_prio; +} + static int pqi_map_single(struct pci_dev *pci_dev, struct pqi_sg_descriptor *sg_descriptor, void *buffer, size_t buffer_length, enum dma_data_direction data_direction) @@ -578,10 +608,6 @@ static int pqi_build_raid_path_request(struct pqi_ctrl_info *ctrl_info, cdb = request->cdb; switch (cmd) { - case TEST_UNIT_READY: - request->data_direction = SOP_READ_FLAG; - cdb[0] = TEST_UNIT_READY; - break; case INQUIRY: request->data_direction = SOP_READ_FLAG; cdb[0] = INQUIRY; @@ -708,7 +734,8 @@ static inline struct pqi_io_request *pqi_alloc_io_request(struct pqi_ctrl_info * } } - pqi_reinit_io_request(io_request); + if (io_request) + pqi_reinit_io_request(io_request); return io_request; } @@ -1176,7 +1203,6 @@ static inline int pqi_report_phys_luns(struct pqi_ctrl_info *ctrl_info, void **b unsigned int i; u8 rpl_response_format; u32 num_physicals; - size_t rpl_16byte_wwid_list_length; void *rpl_list; struct report_lun_header *rpl_header; struct report_phys_lun_8byte_wwid_list *rpl_8byte_wwid_list; @@ -1205,9 +1231,9 @@ static inline int pqi_report_phys_luns(struct pqi_ctrl_info *ctrl_info, void **b rpl_8byte_wwid_list = rpl_list; num_physicals = get_unaligned_be32(&rpl_8byte_wwid_list->header.list_length) / sizeof(rpl_8byte_wwid_list->lun_entries[0]); - rpl_16byte_wwid_list_length = sizeof(struct report_lun_header) + (num_physicals * sizeof(struct report_phys_lun_16byte_wwid)); - rpl_16byte_wwid_list = kmalloc(rpl_16byte_wwid_list_length, GFP_KERNEL); + rpl_16byte_wwid_list = kmalloc(struct_size(rpl_16byte_wwid_list, lun_entries, + num_physicals), GFP_KERNEL); if (!rpl_16byte_wwid_list) return -ENOMEM; @@ -1588,6 +1614,7 @@ static void pqi_get_volume_status(struct pqi_ctrl_info *ctrl_info, #define PQI_DEVICE_NCQ_PRIO_SUPPORTED 0x01 #define PQI_DEVICE_PHY_MAP_SUPPORTED 0x10 +#define PQI_DEVICE_ERASE_IN_PROGRESS 0x10 static int pqi_get_physical_device_info(struct pqi_ctrl_info *ctrl_info, struct pqi_scsi_dev *device, @@ -1636,6 +1663,8 @@ static int pqi_get_physical_device_info(struct pqi_ctrl_info *ctrl_info, ((get_unaligned_le32(&id_phys->misc_drive_flags) >> 16) & PQI_DEVICE_NCQ_PRIO_SUPPORTED); + device->erase_in_progress = !!(get_unaligned_le16(&id_phys->extra_physical_drive_flags) & PQI_DEVICE_ERASE_IN_PROGRESS); + return 0; } @@ -1681,7 +1710,7 @@ static int pqi_get_logical_device_info(struct pqi_ctrl_info *ctrl_info, /* * Prevent adding drive to OS for some corner cases such as a drive - * undergoing a sanitize operation. Some OSes will continue to poll + * undergoing a sanitize (erase) operation. Some OSes will continue to poll * the drive until the sanitize completes, which can take hours, * resulting in long bootup delays. Commands such as TUR, READ_CAP * are allowed, but READ/WRITE cause check condition. So the OS @@ -1689,73 +1718,9 @@ static int pqi_get_logical_device_info(struct pqi_ctrl_info *ctrl_info, * Note: devices that have completed sanitize must be re-enabled * using the management utility. */ -static bool pqi_keep_device_offline(struct pqi_ctrl_info *ctrl_info, - struct pqi_scsi_dev *device) +static inline bool pqi_keep_device_offline(struct pqi_scsi_dev *device) { - u8 scsi_status; - int rc; - enum dma_data_direction dir; - char *buffer; - int buffer_length = 64; - size_t sense_data_length; - struct scsi_sense_hdr sshdr; - struct pqi_raid_path_request request; - struct pqi_raid_error_info error_info; - bool offline = false; /* Assume keep online */ - - /* Do not check controllers. */ - if (pqi_is_hba_lunid(device->scsi3addr)) - return false; - - /* Do not check LVs. */ - if (pqi_is_logical_device(device)) - return false; - - buffer = kmalloc(buffer_length, GFP_KERNEL); - if (!buffer) - return false; /* Assume not offline */ - - /* Check for SANITIZE in progress using TUR */ - rc = pqi_build_raid_path_request(ctrl_info, &request, - TEST_UNIT_READY, RAID_CTLR_LUNID, buffer, - buffer_length, 0, &dir); - if (rc) - goto out; /* Assume not offline */ - - memcpy(request.lun_number, device->scsi3addr, sizeof(request.lun_number)); - - rc = pqi_submit_raid_request_synchronous(ctrl_info, &request.header, 0, &error_info); - - if (rc) - goto out; /* Assume not offline */ - - scsi_status = error_info.status; - sense_data_length = get_unaligned_le16(&error_info.sense_data_length); - if (sense_data_length == 0) - sense_data_length = - get_unaligned_le16(&error_info.response_data_length); - if (sense_data_length) { - if (sense_data_length > sizeof(error_info.data)) - sense_data_length = sizeof(error_info.data); - - /* - * Check for sanitize in progress: asc:0x04, ascq: 0x1b - */ - if (scsi_status == SAM_STAT_CHECK_CONDITION && - scsi_normalize_sense(error_info.data, - sense_data_length, &sshdr) && - sshdr.sense_key == NOT_READY && - sshdr.asc == 0x04 && - sshdr.ascq == 0x1b) { - device->device_offline = true; - offline = true; - goto out; /* Keep device offline */ - } - } - -out: - kfree(buffer); - return offline; + return device->erase_in_progress; } static int pqi_get_device_info_phys_logical(struct pqi_ctrl_info *ctrl_info, @@ -2499,10 +2464,6 @@ static int pqi_update_scsi_devices(struct pqi_ctrl_info *ctrl_info) if (!pqi_is_supported_device(device)) continue; - /* Do not present disks that the OS cannot fully probe */ - if (pqi_keep_device_offline(ctrl_info, device)) - continue; - /* Gather information about the device. */ rc = pqi_get_device_info(ctrl_info, device, id_phys); if (rc == -ENOMEM) { @@ -2525,6 +2486,10 @@ static int pqi_update_scsi_devices(struct pqi_ctrl_info *ctrl_info) continue; } + /* Do not present disks that the OS cannot fully probe. */ + if (pqi_keep_device_offline(device)) + continue; + pqi_assign_bus_target_lun(device); if (device->is_physical_device) { @@ -5015,7 +4980,7 @@ static int pqi_create_queues(struct pqi_ctrl_info *ctrl_info) } #define PQI_REPORT_EVENT_CONFIG_BUFFER_LENGTH \ - struct_size((struct pqi_event_config *)0, descriptors, PQI_MAX_EVENT_DESCRIPTORS) + struct_size_t(struct pqi_event_config, descriptors, PQI_MAX_EVENT_DESCRIPTORS) static int pqi_configure_events(struct pqi_ctrl_info *ctrl_info, bool enable_events) @@ -5504,15 +5469,19 @@ static void pqi_raid_io_complete(struct pqi_io_request *io_request, pqi_scsi_done(scmd); } -static int pqi_raid_submit_scsi_cmd_with_io_request( - struct pqi_ctrl_info *ctrl_info, struct pqi_io_request *io_request, +static int pqi_raid_submit_io(struct pqi_ctrl_info *ctrl_info, struct pqi_scsi_dev *device, struct scsi_cmnd *scmd, - struct pqi_queue_group *queue_group) + struct pqi_queue_group *queue_group, bool io_high_prio) { int rc; size_t cdb_length; + struct pqi_io_request *io_request; struct pqi_raid_path_request *request; + io_request = pqi_alloc_io_request(ctrl_info, scmd); + if (!io_request) + return SCSI_MLQUEUE_HOST_BUSY; + io_request->io_complete_callback = pqi_raid_io_complete; io_request->scmd = scmd; @@ -5522,6 +5491,7 @@ static int pqi_raid_submit_scsi_cmd_with_io_request( request->header.iu_type = PQI_REQUEST_IU_RAID_PATH_IO; put_unaligned_le32(scsi_bufflen(scmd), &request->buffer_length); request->task_attribute = SOP_TASK_ATTRIBUTE_SIMPLE; + request->command_priority = io_high_prio; put_unaligned_le16(io_request->index, &request->request_id); request->error_index = request->request_id; memcpy(request->lun_number, device->scsi3addr, sizeof(request->lun_number)); @@ -5587,14 +5557,11 @@ static inline int pqi_raid_submit_scsi_cmd(struct pqi_ctrl_info *ctrl_info, struct pqi_scsi_dev *device, struct scsi_cmnd *scmd, struct pqi_queue_group *queue_group) { - struct pqi_io_request *io_request; + bool io_high_prio; - io_request = pqi_alloc_io_request(ctrl_info, scmd); - if (!io_request) - return SCSI_MLQUEUE_HOST_BUSY; + io_high_prio = pqi_is_io_high_priority(device, scmd); - return pqi_raid_submit_scsi_cmd_with_io_request(ctrl_info, io_request, - device, scmd, queue_group); + return pqi_raid_submit_io(ctrl_info, device, scmd, queue_group, io_high_prio); } static bool pqi_raid_bypass_retry_needed(struct pqi_io_request *io_request) @@ -5639,44 +5606,13 @@ static void pqi_aio_io_complete(struct pqi_io_request *io_request, pqi_scsi_done(scmd); } -static inline bool pqi_is_io_high_priority(struct pqi_ctrl_info *ctrl_info, - struct pqi_scsi_dev *device, struct scsi_cmnd *scmd) -{ - bool io_high_prio; - int priority_class; - - io_high_prio = false; - - if (device->ncq_prio_enable) { - priority_class = - IOPRIO_PRIO_CLASS(req_get_ioprio(scsi_cmd_to_rq(scmd))); - if (priority_class == IOPRIO_CLASS_RT) { - /* Set NCQ priority for read/write commands. */ - switch (scmd->cmnd[0]) { - case WRITE_16: - case READ_16: - case WRITE_12: - case READ_12: - case WRITE_10: - case READ_10: - case WRITE_6: - case READ_6: - io_high_prio = true; - break; - } - } - } - - return io_high_prio; -} - static inline int pqi_aio_submit_scsi_cmd(struct pqi_ctrl_info *ctrl_info, struct pqi_scsi_dev *device, struct scsi_cmnd *scmd, struct pqi_queue_group *queue_group) { bool io_high_prio; - io_high_prio = pqi_is_io_high_priority(ctrl_info, device, scmd); + io_high_prio = pqi_is_io_high_priority(device, scmd); return pqi_aio_submit_io(ctrl_info, scmd, device->aio_handle, scmd->cmnd, scmd->cmd_len, queue_group, NULL, @@ -5694,10 +5630,10 @@ static int pqi_aio_submit_io(struct pqi_ctrl_info *ctrl_info, struct pqi_aio_path_request *request; struct pqi_scsi_dev *device; - device = scmd->device->hostdata; io_request = pqi_alloc_io_request(ctrl_info, scmd); if (!io_request) return SCSI_MLQUEUE_HOST_BUSY; + io_request->io_complete_callback = pqi_aio_io_complete; io_request->scmd = scmd; io_request->raid_bypass = raid_bypass; @@ -5712,6 +5648,7 @@ static int pqi_aio_submit_io(struct pqi_ctrl_info *ctrl_info, request->command_priority = io_high_prio; put_unaligned_le16(io_request->index, &request->request_id); request->error_index = request->request_id; + device = scmd->device->hostdata; if (!pqi_is_logical_device(device) && ctrl_info->multi_lun_device_supported) put_unaligned_le64(((scmd->device->lun) << 8), &request->lun_number); if (cdb_length > sizeof(request->cdb)) @@ -6052,7 +5989,7 @@ static int pqi_scsi_queue_command(struct Scsi_Host *shost, struct scsi_cmnd *scm rc = pqi_raid_bypass_submit_scsi_cmd(ctrl_info, device, scmd, queue_group); if (rc == 0 || rc == SCSI_MLQUEUE_HOST_BUSY) { raid_bypassed = true; - atomic_inc(&device->raid_bypass_cnt); + device->raid_bypass_cnt++; } } if (!raid_bypassed) @@ -6903,7 +6840,7 @@ static ssize_t pqi_lockup_action_store(struct device *dev, char *action_name; char action_name_buffer[32]; - strlcpy(action_name_buffer, buffer, sizeof(action_name_buffer)); + strscpy(action_name_buffer, buffer, sizeof(action_name_buffer)); action_name = strstrip(action_name_buffer); for (i = 0; i < ARRAY_SIZE(pqi_lockup_actions); i++) { @@ -7288,7 +7225,7 @@ static ssize_t pqi_raid_bypass_cnt_show(struct device *dev, struct scsi_device *sdev; struct pqi_scsi_dev *device; unsigned long flags; - int raid_bypass_cnt; + unsigned int raid_bypass_cnt; sdev = to_scsi_device(dev); ctrl_info = shost_to_hba(sdev->host); @@ -7304,7 +7241,7 @@ static ssize_t pqi_raid_bypass_cnt_show(struct device *dev, return -ENODEV; } - raid_bypass_cnt = atomic_read(&device->raid_bypass_cnt); + raid_bypass_cnt = device->raid_bypass_cnt; spin_unlock_irqrestore(&ctrl_info->scsi_device_list_lock, flags); @@ -7366,8 +7303,7 @@ static ssize_t pqi_sas_ncq_prio_enable_store(struct device *dev, return -ENODEV; } - if (!device->ncq_prio_support || - !device->is_physical_device) { + if (!device->ncq_prio_support) { spin_unlock_irqrestore(&ctrl_info->scsi_device_list_lock, flags); return -EINVAL; } @@ -7379,6 +7315,18 @@ static ssize_t pqi_sas_ncq_prio_enable_store(struct device *dev, return strlen(buf); } +static ssize_t pqi_numa_node_show(struct device *dev, + struct device_attribute *attr, char *buffer) +{ + struct scsi_device *sdev; + struct pqi_ctrl_info *ctrl_info; + + sdev = to_scsi_device(dev); + ctrl_info = shost_to_hba(sdev->host); + + return scnprintf(buffer, PAGE_SIZE, "%d\n", ctrl_info->numa_node); +} + static DEVICE_ATTR(lunid, 0444, pqi_lunid_show, NULL); static DEVICE_ATTR(unique_id, 0444, pqi_unique_id_show, NULL); static DEVICE_ATTR(path_info, 0444, pqi_path_info_show, NULL); @@ -7388,6 +7336,7 @@ static DEVICE_ATTR(raid_level, 0444, pqi_raid_level_show, NULL); static DEVICE_ATTR(raid_bypass_cnt, 0444, pqi_raid_bypass_cnt_show, NULL); static DEVICE_ATTR(sas_ncq_prio_enable, 0644, pqi_sas_ncq_prio_enable_show, pqi_sas_ncq_prio_enable_store); +static DEVICE_ATTR(numa_node, 0444, pqi_numa_node_show, NULL); static struct attribute *pqi_sdev_attrs[] = { &dev_attr_lunid.attr, @@ -7398,6 +7347,7 @@ static struct attribute *pqi_sdev_attrs[] = { &dev_attr_raid_level.attr, &dev_attr_raid_bypass_cnt.attr, &dev_attr_sas_ncq_prio_enable.attr, + &dev_attr_numa_node.attr, NULL }; @@ -7716,8 +7666,8 @@ static int pqi_enable_firmware_features(struct pqi_ctrl_info *ctrl_info, features_requested_iomem_addr + (le16_to_cpu(firmware_features->num_elements) * 2) + sizeof(__le16); - writew(PQI_FIRMWARE_FEATURE_MAXIMUM, - host_max_known_feature_iomem_addr); + writeb(PQI_FIRMWARE_FEATURE_MAXIMUM & 0xFF, host_max_known_feature_iomem_addr); + writeb((PQI_FIRMWARE_FEATURE_MAXIMUM & 0xFF00) >> 8, host_max_known_feature_iomem_addr + 1); } return pqi_config_table_update(ctrl_info, @@ -8560,7 +8510,7 @@ static int pqi_pci_init(struct pqi_ctrl_info *ctrl_info) ctrl_info->iomem_base = ioremap(pci_resource_start( ctrl_info->pci_dev, 0), - sizeof(struct pqi_ctrl_registers)); + pci_resource_len(ctrl_info->pci_dev, 0)); if (!ctrl_info->iomem_base) { dev_err(&ctrl_info->pci_dev->dev, "failed to map memory for controller registers\n"); @@ -9018,6 +8968,7 @@ static int pqi_pci_probe(struct pci_dev *pci_dev, "failed to allocate controller info block\n"); return -ENOMEM; } + ctrl_info->numa_node = node; ctrl_info->pci_dev = pci_dev; @@ -9927,6 +9878,18 @@ static const struct pci_device_id pqi_pci_id_table[] = { PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, 0x1f0c, 0x3161) }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1cf2, 0x0804) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1cf2, 0x0805) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1cf2, 0x0806) + }, { PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, 0x1cf2, 0x5445) @@ -9963,6 +9926,18 @@ static const struct pci_device_id pqi_pci_id_table[] = { PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, 0x1cf2, 0x544f) }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1cf2, 0x54da) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1cf2, 0x54db) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1cf2, 0x54dc) + }, { PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, 0x1cf2, 0x0b27) @@ -10015,6 +9990,10 @@ static const struct pci_device_id pqi_pci_id_table[] = { PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, PCI_VENDOR_ID_LENOVO, 0x0623) }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1014, 0x0718) + }, { PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, 0x1e93, 0x1000) @@ -10027,6 +10006,50 @@ static const struct pci_device_id pqi_pci_id_table[] = { PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, 0x1e93, 0x1002) }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1e93, 0x1005) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1f51, 0x1001) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1f51, 0x1002) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1f51, 0x1003) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1f51, 0x1004) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1f51, 0x1005) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1f51, 0x1006) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1f51, 0x1007) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1f51, 0x1008) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1f51, 0x1009) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1f51, 0x100a) + }, { PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, PCI_ANY_ID, PCI_ANY_ID) diff --git a/drivers/scsi/smartpqi/smartpqi_sas_transport.c b/drivers/scsi/smartpqi/smartpqi_sas_transport.c index 13e8c539010ea86c7171fea244401f641981d64d..a981d037794809f1d6499fad6cd68464813bb5d7 100644 --- a/drivers/scsi/smartpqi/smartpqi_sas_transport.c +++ b/drivers/scsi/smartpqi/smartpqi_sas_transport.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 /* * driver for Microchip PQI-based storage controllers - * Copyright (c) 2019-2022 Microchip Technology Inc. and its subsidiaries + * Copyright (c) 2019-2023 Microchip Technology Inc. and its subsidiaries * Copyright (c) 2016-2018 Microsemi Corporation * Copyright (c) 2016 PMC-Sierra, Inc. * @@ -92,25 +92,23 @@ static int pqi_sas_port_add_rphy(struct pqi_sas_port *pqi_sas_port, identify = &rphy->identify; identify->sas_address = pqi_sas_port->sas_address; + identify->phy_identifier = pqi_sas_port->device->phy_id; identify->initiator_port_protocols = SAS_PROTOCOL_ALL; identify->target_port_protocols = SAS_PROTOCOL_STP; - if (pqi_sas_port->device) { - identify->phy_identifier = pqi_sas_port->device->phy_id; - switch (pqi_sas_port->device->device_type) { - case SA_DEVICE_TYPE_SAS: - case SA_DEVICE_TYPE_SES: - case SA_DEVICE_TYPE_NVME: - identify->target_port_protocols = SAS_PROTOCOL_SSP; - break; - case SA_DEVICE_TYPE_EXPANDER_SMP: - identify->target_port_protocols = SAS_PROTOCOL_SMP; - break; - case SA_DEVICE_TYPE_SATA: - default: - break; - } + switch (pqi_sas_port->device->device_type) { + case SA_DEVICE_TYPE_SAS: + case SA_DEVICE_TYPE_SES: + case SA_DEVICE_TYPE_NVME: + identify->target_port_protocols = SAS_PROTOCOL_SSP; + break; + case SA_DEVICE_TYPE_EXPANDER_SMP: + identify->target_port_protocols = SAS_PROTOCOL_SMP; + break; + case SA_DEVICE_TYPE_SATA: + default: + break; } return sas_rphy_add(rphy); @@ -295,10 +293,12 @@ int pqi_add_sas_device(struct pqi_sas_node *pqi_sas_node, rc = pqi_sas_port_add_rphy(pqi_sas_port, rphy); if (rc) - goto free_sas_port; + goto free_sas_rphy; return 0; +free_sas_rphy: + sas_rphy_free(rphy); free_sas_port: pqi_free_sas_port(pqi_sas_port); device->sas_port = NULL; diff --git a/drivers/scsi/smartpqi/smartpqi_sis.c b/drivers/scsi/smartpqi/smartpqi_sis.c index 5811fb3c22a959592652a2f8aa6b4c15b19d02f8..673437c7152b9d00b129347abb9d7a1ea1d5c726 100644 --- a/drivers/scsi/smartpqi/smartpqi_sis.c +++ b/drivers/scsi/smartpqi/smartpqi_sis.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 /* * driver for Microchip PQI-based storage controllers - * Copyright (c) 2019-2022 Microchip Technology Inc. and its subsidiaries + * Copyright (c) 2019-2023 Microchip Technology Inc. and its subsidiaries * Copyright (c) 2016-2018 Microsemi Corporation * Copyright (c) 2016 PMC-Sierra, Inc. * diff --git a/drivers/scsi/smartpqi/smartpqi_sis.h b/drivers/scsi/smartpqi/smartpqi_sis.h index 9dcbae96a5c66d35024ee7cee5d14f47431306e9..0c97626d87d4d4631b86cc115b1c8e679d866016 100644 --- a/drivers/scsi/smartpqi/smartpqi_sis.h +++ b/drivers/scsi/smartpqi/smartpqi_sis.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 */ /* * driver for Microchip PQI-based storage controllers - * Copyright (c) 2019-2022 Microchip Technology Inc. and its subsidiaries + * Copyright (c) 2019-2023 Microchip Technology Inc. and its subsidiaries * Copyright (c) 2016-2018 Microsemi Corporation * Copyright (c) 2016 PMC-Sierra, Inc. * diff --git a/drivers/scsi/snic/snic_disc.c b/drivers/scsi/snic/snic_disc.c index 8fbf3c1b1311d805173e130101abb6a527ccf3fd..3e2e5783924d03caed2efa21587d485d54c9acc4 100644 --- a/drivers/scsi/snic/snic_disc.c +++ b/drivers/scsi/snic/snic_disc.c @@ -214,7 +214,7 @@ snic_tgt_del(struct work_struct *work) scsi_flush_work(shost); /* Block IOs on child devices, stops new IOs */ - scsi_target_block(&tgt->dev); + scsi_block_targets(shost, &tgt->dev); /* Cleanup IOs */ snic_tgt_scsi_abort_io(tgt); diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index 12869e6d4ebda8d6b74a0b562ce51adf81ee2cc1..07ef3db3d1a144f0225d9c8637a258b9800666e6 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c @@ -484,9 +484,9 @@ static void sr_revalidate_disk(struct scsi_cd *cd) get_sectorsize(cd); } -static int sr_block_open(struct block_device *bdev, fmode_t mode) +static int sr_block_open(struct gendisk *disk, blk_mode_t mode) { - struct scsi_cd *cd = scsi_cd(bdev->bd_disk); + struct scsi_cd *cd = scsi_cd(disk); struct scsi_device *sdev = cd->device; int ret; @@ -494,11 +494,11 @@ static int sr_block_open(struct block_device *bdev, fmode_t mode) return -ENXIO; scsi_autopm_get_device(sdev); - if (bdev_check_media_change(bdev)) + if (disk_check_media_change(disk)) sr_revalidate_disk(cd); mutex_lock(&cd->lock); - ret = cdrom_open(&cd->cdi, bdev, mode); + ret = cdrom_open(&cd->cdi, mode); mutex_unlock(&cd->lock); scsi_autopm_put_device(sdev); @@ -507,19 +507,19 @@ static int sr_block_open(struct block_device *bdev, fmode_t mode) return ret; } -static void sr_block_release(struct gendisk *disk, fmode_t mode) +static void sr_block_release(struct gendisk *disk) { struct scsi_cd *cd = scsi_cd(disk); mutex_lock(&cd->lock); - cdrom_release(&cd->cdi, mode); + cdrom_release(&cd->cdi); mutex_unlock(&cd->lock); scsi_device_put(cd->device); } -static int sr_block_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd, - unsigned long arg) +static int sr_block_ioctl(struct block_device *bdev, blk_mode_t mode, + unsigned cmd, unsigned long arg) { struct scsi_cd *cd = scsi_cd(bdev->bd_disk); struct scsi_device *sdev = cd->device; @@ -532,18 +532,18 @@ static int sr_block_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd, mutex_lock(&cd->lock); ret = scsi_ioctl_block_when_processing_errors(sdev, cmd, - (mode & FMODE_NDELAY) != 0); + (mode & BLK_OPEN_NDELAY)); if (ret) goto out; scsi_autopm_get_device(sdev); if (cmd != CDROMCLOSETRAY && cmd != CDROMEJECT) { - ret = cdrom_ioctl(&cd->cdi, bdev, mode, cmd, arg); + ret = cdrom_ioctl(&cd->cdi, bdev, cmd, arg); if (ret != -ENOSYS) goto put; } - ret = scsi_ioctl(sdev, mode, cmd, argp); + ret = scsi_ioctl(sdev, mode & BLK_OPEN_WRITE, cmd, argp); put: scsi_autopm_put_device(sdev); @@ -825,7 +825,7 @@ static int get_capabilities(struct scsi_cd *cd) scsi_test_unit_ready(cd->device, SR_TIMEOUT, MAX_RETRIES, &sshdr); /* ask for mode page 0x2a */ - rc = scsi_mode_sense(cd->device, 0, 0x2a, buffer, ms_len, + rc = scsi_mode_sense(cd->device, 0, 0x2a, 0, buffer, ms_len, SR_TIMEOUT, 3, &data, NULL); if (rc < 0 || data.length > ms_len || diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index b90a440e135dc493eefac95c8a108629f534f9b3..14d7981ddcdd192ac729ed41f9387d38900e34f6 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c @@ -3832,7 +3832,7 @@ static long st_ioctl(struct file *file, unsigned int cmd_in, unsigned long arg) break; } - retval = scsi_ioctl(STp->device, file->f_mode, cmd_in, p); + retval = scsi_ioctl(STp->device, file->f_mode & FMODE_WRITE, cmd_in, p); if (!retval && cmd_in == SCSI_IOCTL_STOP_UNIT) { /* unload */ STp->rew_at_close = 0; diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index 659196a2f63ad33d3f16e9cb0e26449e78ef46a9..7f12d931fe7c1464c4e39d123666f0444efc5417 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -318,6 +318,7 @@ enum storvsc_request_type { #define SRB_STATUS_INVALID_REQUEST 0x06 #define SRB_STATUS_DATA_OVERRUN 0x12 #define SRB_STATUS_INVALID_LUN 0x20 +#define SRB_STATUS_INTERNAL_ERROR 0x30 #define SRB_STATUS(status) \ (status & ~(SRB_STATUS_AUTOSENSE_VALID | SRB_STATUS_QUEUE_FROZEN)) @@ -978,6 +979,7 @@ static void storvsc_handle_error(struct vmscsi_request *vm_srb, case SRB_STATUS_ERROR: case SRB_STATUS_ABORTED: case SRB_STATUS_INVALID_REQUEST: + case SRB_STATUS_INTERNAL_ERROR: if (vm_srb->srb_status & SRB_STATUS_AUTOSENSE_VALID) { /* Check for capacity change */ if ((asc == 0x2a) && (ascq == 0x9)) { diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c index ee36a9c15d9c2bb4255c100be5012195c1df5bb1..17491ba10439c52a0959b19609723a1d7987200f 100644 --- a/drivers/scsi/sym53c8xx_2/sym_glue.c +++ b/drivers/scsi/sym53c8xx_2/sym_glue.c @@ -1286,7 +1286,7 @@ static struct Scsi_Host *sym_attach(const struct scsi_host_template *tpnt, int u /* * Edit its name. */ - strlcpy(np->s.chip_name, dev->chip.name, sizeof(np->s.chip_name)); + strscpy(np->s.chip_name, dev->chip.name, sizeof(np->s.chip_name)); sprintf(np->s.inst_name, "sym%d", np->s.unit); if ((SYM_CONF_DMA_ADDRESSING_MODE > 0) && (np->features & FE_DAC) && diff --git a/drivers/scsi/virtio_scsi.c b/drivers/scsi/virtio_scsi.c index 58498da9869a03fe6531c02e21eb119f4d362543..bd5633667d01567cd408475f3f9c3c27a98a197e 100644 --- a/drivers/scsi/virtio_scsi.c +++ b/drivers/scsi/virtio_scsi.c @@ -338,10 +338,8 @@ static int virtscsi_rescan_hotunplug(struct virtio_scsi *vscsi) int result, inquiry_len, inq_result_len = 256; char *inq_result = kmalloc(inq_result_len, GFP_KERNEL); - if (!inq_result) { - kfree(inq_result); + if (!inq_result) return -ENOMEM; - } shost_for_each_device(sdev, shost) { inquiry_len = sdev->inquiry_len ? sdev->inquiry_len : 36; diff --git a/drivers/soc/amlogic/meson-secure-pwrc.c b/drivers/soc/amlogic/meson-secure-pwrc.c index e9351876352672f163809b139ccc608589112d66..25b4b71df9b8935451f0f35cae8094104b05c25c 100644 --- a/drivers/soc/amlogic/meson-secure-pwrc.c +++ b/drivers/soc/amlogic/meson-secure-pwrc.c @@ -105,7 +105,7 @@ static struct meson_secure_pwrc_domain_desc a1_pwrc_domains[] = { SEC_PD(ACODEC, 0), SEC_PD(AUDIO, 0), SEC_PD(OTP, 0), - SEC_PD(DMA, 0), + SEC_PD(DMA, GENPD_FLAG_ALWAYS_ON | GENPD_FLAG_IRQ_SAFE), SEC_PD(SD_EMMC, 0), SEC_PD(RAMA, 0), /* SRAMB is used as ATF runtime memory, and should be always on */ diff --git a/drivers/soc/fsl/dpio/dpio-driver.c b/drivers/soc/fsl/dpio/dpio-driver.c index 74eace3109a162e8f356d38b406cb875bc2a0dff..9e3fddd8f5a9129cc54a426c2ea4549b39b10ca4 100644 --- a/drivers/soc/fsl/dpio/dpio-driver.c +++ b/drivers/soc/fsl/dpio/dpio-driver.c @@ -270,7 +270,7 @@ static void dpio_teardown_irqs(struct fsl_mc_device *dpio_dev) fsl_mc_free_irqs(dpio_dev); } -static int dpaa2_dpio_remove(struct fsl_mc_device *dpio_dev) +static void dpaa2_dpio_remove(struct fsl_mc_device *dpio_dev) { struct device *dev; struct dpio_priv *priv; @@ -297,14 +297,8 @@ static int dpaa2_dpio_remove(struct fsl_mc_device *dpio_dev) dpio_close(dpio_dev->mc_io, 0, dpio_dev->mc_handle); - fsl_mc_portal_free(dpio_dev->mc_io); - - return 0; - err_open: fsl_mc_portal_free(dpio_dev->mc_io); - - return err; } static const struct fsl_mc_device_id dpaa2_dpio_match_id_table[] = { diff --git a/drivers/soc/fsl/qe/Kconfig b/drivers/soc/fsl/qe/Kconfig index e0d096607fefbaf4f9ee93921046ec675a9af05f..fa9ffbed0e929b5f59dd981c21f18e8a2d967bca 100644 --- a/drivers/soc/fsl/qe/Kconfig +++ b/drivers/soc/fsl/qe/Kconfig @@ -62,6 +62,7 @@ config QE_TDM config QE_USB bool + depends on QUICC_ENGINE default y if USB_FSL_QE help QE USB Controller support diff --git a/drivers/soc/mediatek/mtk-mutex.c b/drivers/soc/mediatek/mtk-mutex.c index 26f3d9a4149641639b5db6293dca4190d41866f7..4aa0913817ae77fb5234f10b33a0591b8cbe6044 100644 --- a/drivers/soc/mediatek/mtk-mutex.c +++ b/drivers/soc/mediatek/mtk-mutex.c @@ -1051,7 +1051,6 @@ static struct platform_driver mtk_mutex_driver = { .probe = mtk_mutex_probe, .driver = { .name = "mediatek-mutex", - .owner = THIS_MODULE, .of_match_table = mutex_driver_dt_match, }, }; diff --git a/drivers/soc/mediatek/mtk-pmic-wrap.c b/drivers/soc/mediatek/mtk-pmic-wrap.c index 15789a03e6c604f9c0944e832f3f47377ec7b106..11095b8de71ac2f99dbe1914abee85c61a78e4f1 100644 --- a/drivers/soc/mediatek/mtk-pmic-wrap.c +++ b/drivers/soc/mediatek/mtk-pmic-wrap.c @@ -47,6 +47,7 @@ /* macro for device wrapper default value */ #define PWRAP_DEW_READ_TEST_VAL 0x5aa5 +#define PWRAP_DEW_COMP_READ_TEST_VAL 0xa55a #define PWRAP_DEW_WRITE_TEST_VAL 0xa55a /* macro for manual command */ @@ -169,6 +170,40 @@ static const u32 mt6323_regs[] = { [PWRAP_DEW_RDDMY_NO] = 0x01a4, }; +static const u32 mt6331_regs[] = { + [PWRAP_DEW_DIO_EN] = 0x018c, + [PWRAP_DEW_READ_TEST] = 0x018e, + [PWRAP_DEW_WRITE_TEST] = 0x0190, + [PWRAP_DEW_CRC_SWRST] = 0x0192, + [PWRAP_DEW_CRC_EN] = 0x0194, + [PWRAP_DEW_CRC_VAL] = 0x0196, + [PWRAP_DEW_MON_GRP_SEL] = 0x0198, + [PWRAP_DEW_CIPHER_KEY_SEL] = 0x019a, + [PWRAP_DEW_CIPHER_IV_SEL] = 0x019c, + [PWRAP_DEW_CIPHER_EN] = 0x019e, + [PWRAP_DEW_CIPHER_RDY] = 0x01a0, + [PWRAP_DEW_CIPHER_MODE] = 0x01a2, + [PWRAP_DEW_CIPHER_SWRST] = 0x01a4, + [PWRAP_DEW_RDDMY_NO] = 0x01a6, +}; + +static const u32 mt6332_regs[] = { + [PWRAP_DEW_DIO_EN] = 0x80f6, + [PWRAP_DEW_READ_TEST] = 0x80f8, + [PWRAP_DEW_WRITE_TEST] = 0x80fa, + [PWRAP_DEW_CRC_SWRST] = 0x80fc, + [PWRAP_DEW_CRC_EN] = 0x80fe, + [PWRAP_DEW_CRC_VAL] = 0x8100, + [PWRAP_DEW_MON_GRP_SEL] = 0x8102, + [PWRAP_DEW_CIPHER_KEY_SEL] = 0x8104, + [PWRAP_DEW_CIPHER_IV_SEL] = 0x8106, + [PWRAP_DEW_CIPHER_EN] = 0x8108, + [PWRAP_DEW_CIPHER_RDY] = 0x810a, + [PWRAP_DEW_CIPHER_MODE] = 0x810c, + [PWRAP_DEW_CIPHER_SWRST] = 0x810e, + [PWRAP_DEW_RDDMY_NO] = 0x8110, +}; + static const u32 mt6351_regs[] = { [PWRAP_DEW_DIO_EN] = 0x02F2, [PWRAP_DEW_READ_TEST] = 0x02F4, @@ -604,6 +639,91 @@ static int mt6779_regs[] = { [PWRAP_WACS2_VLDCLR] = 0xC28, }; +static int mt6795_regs[] = { + [PWRAP_MUX_SEL] = 0x0, + [PWRAP_WRAP_EN] = 0x4, + [PWRAP_DIO_EN] = 0x8, + [PWRAP_SIDLY] = 0xc, + [PWRAP_RDDMY] = 0x10, + [PWRAP_SI_CK_CON] = 0x14, + [PWRAP_CSHEXT_WRITE] = 0x18, + [PWRAP_CSHEXT_READ] = 0x1c, + [PWRAP_CSLEXT_START] = 0x20, + [PWRAP_CSLEXT_END] = 0x24, + [PWRAP_STAUPD_PRD] = 0x28, + [PWRAP_STAUPD_GRPEN] = 0x2c, + [PWRAP_EINT_STA0_ADR] = 0x30, + [PWRAP_EINT_STA1_ADR] = 0x34, + [PWRAP_STAUPD_MAN_TRIG] = 0x40, + [PWRAP_STAUPD_STA] = 0x44, + [PWRAP_WRAP_STA] = 0x48, + [PWRAP_HARB_INIT] = 0x4c, + [PWRAP_HARB_HPRIO] = 0x50, + [PWRAP_HIPRIO_ARB_EN] = 0x54, + [PWRAP_HARB_STA0] = 0x58, + [PWRAP_HARB_STA1] = 0x5c, + [PWRAP_MAN_EN] = 0x60, + [PWRAP_MAN_CMD] = 0x64, + [PWRAP_MAN_RDATA] = 0x68, + [PWRAP_MAN_VLDCLR] = 0x6c, + [PWRAP_WACS0_EN] = 0x70, + [PWRAP_INIT_DONE0] = 0x74, + [PWRAP_WACS0_CMD] = 0x78, + [PWRAP_WACS0_RDATA] = 0x7c, + [PWRAP_WACS0_VLDCLR] = 0x80, + [PWRAP_WACS1_EN] = 0x84, + [PWRAP_INIT_DONE1] = 0x88, + [PWRAP_WACS1_CMD] = 0x8c, + [PWRAP_WACS1_RDATA] = 0x90, + [PWRAP_WACS1_VLDCLR] = 0x94, + [PWRAP_WACS2_EN] = 0x98, + [PWRAP_INIT_DONE2] = 0x9c, + [PWRAP_WACS2_CMD] = 0xa0, + [PWRAP_WACS2_RDATA] = 0xa4, + [PWRAP_WACS2_VLDCLR] = 0xa8, + [PWRAP_INT_EN] = 0xac, + [PWRAP_INT_FLG_RAW] = 0xb0, + [PWRAP_INT_FLG] = 0xb4, + [PWRAP_INT_CLR] = 0xb8, + [PWRAP_SIG_ADR] = 0xbc, + [PWRAP_SIG_MODE] = 0xc0, + [PWRAP_SIG_VALUE] = 0xc4, + [PWRAP_SIG_ERRVAL] = 0xc8, + [PWRAP_CRC_EN] = 0xcc, + [PWRAP_TIMER_EN] = 0xd0, + [PWRAP_TIMER_STA] = 0xd4, + [PWRAP_WDT_UNIT] = 0xd8, + [PWRAP_WDT_SRC_EN] = 0xdc, + [PWRAP_WDT_FLG] = 0xe0, + [PWRAP_DEBUG_INT_SEL] = 0xe4, + [PWRAP_DVFS_ADR0] = 0xe8, + [PWRAP_DVFS_WDATA0] = 0xec, + [PWRAP_DVFS_ADR1] = 0xf0, + [PWRAP_DVFS_WDATA1] = 0xf4, + [PWRAP_DVFS_ADR2] = 0xf8, + [PWRAP_DVFS_WDATA2] = 0xfc, + [PWRAP_DVFS_ADR3] = 0x100, + [PWRAP_DVFS_WDATA3] = 0x104, + [PWRAP_DVFS_ADR4] = 0x108, + [PWRAP_DVFS_WDATA4] = 0x10c, + [PWRAP_DVFS_ADR5] = 0x110, + [PWRAP_DVFS_WDATA5] = 0x114, + [PWRAP_DVFS_ADR6] = 0x118, + [PWRAP_DVFS_WDATA6] = 0x11c, + [PWRAP_DVFS_ADR7] = 0x120, + [PWRAP_DVFS_WDATA7] = 0x124, + [PWRAP_SPMINF_STA] = 0x128, + [PWRAP_CIPHER_KEY_SEL] = 0x12c, + [PWRAP_CIPHER_IV_SEL] = 0x130, + [PWRAP_CIPHER_EN] = 0x134, + [PWRAP_CIPHER_RDY] = 0x138, + [PWRAP_CIPHER_MODE] = 0x13c, + [PWRAP_CIPHER_SWRST] = 0x140, + [PWRAP_DCM_EN] = 0x144, + [PWRAP_DCM_DBC_PRD] = 0x148, + [PWRAP_EXT_CK] = 0x14c, +}; + static int mt6797_regs[] = { [PWRAP_MUX_SEL] = 0x0, [PWRAP_WRAP_EN] = 0x4, @@ -1181,6 +1301,8 @@ static int mt8186_regs[] = { enum pmic_type { PMIC_MT6323, + PMIC_MT6331, + PMIC_MT6332, PMIC_MT6351, PMIC_MT6357, PMIC_MT6358, @@ -1193,6 +1315,7 @@ enum pwrap_type { PWRAP_MT2701, PWRAP_MT6765, PWRAP_MT6779, + PWRAP_MT6795, PWRAP_MT6797, PWRAP_MT6873, PWRAP_MT7622, @@ -1218,11 +1341,21 @@ struct pwrap_slv_regops { int (*pwrap_write)(struct pmic_wrapper *wrp, u32 adr, u32 wdata); }; +/** + * struct pwrap_slv_type - PMIC device wrapper definitions + * @dew_regs: Device Wrapper (DeW) register offsets + * @type: PMIC Type (model) + * @comp_dew_regs: Device Wrapper (DeW) register offsets for companion device + * @comp_type: Companion PMIC Type (model) + * @regops: Register R/W ops + * @caps: Capability flags for the target device + */ struct pwrap_slv_type { const u32 *dew_regs; enum pmic_type type; + const u32 *comp_dew_regs; + enum pmic_type comp_type; const struct pwrap_slv_regops *regops; - /* Flags indicating the capability for the target slave */ u32 caps; }; @@ -1455,6 +1588,18 @@ static int pwrap_regmap_write(void *context, u32 adr, u32 wdata) return pwrap_write(context, adr, wdata); } +static bool pwrap_pmic_read_test(struct pmic_wrapper *wrp, const u32 *dew_regs, + u16 read_test_val) +{ + bool is_success; + u32 rdata; + + pwrap_read(wrp, dew_regs[PWRAP_DEW_READ_TEST], &rdata); + is_success = ((rdata & U16_MAX) == read_test_val); + + return is_success; +} + static int pwrap_reset_spislave(struct pmic_wrapper *wrp) { bool tmp; @@ -1498,18 +1643,18 @@ static int pwrap_reset_spislave(struct pmic_wrapper *wrp) */ static int pwrap_init_sidly(struct pmic_wrapper *wrp) { - u32 rdata; u32 i; u32 pass = 0; + bool read_ok; signed char dly[16] = { -1, 0, 1, 0, 2, -1, 1, 1, 3, -1, -1, -1, 3, -1, 2, 1 }; for (i = 0; i < 4; i++) { pwrap_writel(wrp, i, PWRAP_SIDLY); - pwrap_read(wrp, wrp->slave->dew_regs[PWRAP_DEW_READ_TEST], - &rdata); - if (rdata == PWRAP_DEW_READ_TEST_VAL) { + read_ok = pwrap_pmic_read_test(wrp, wrp->slave->dew_regs, + PWRAP_DEW_READ_TEST_VAL); + if (read_ok) { dev_dbg(wrp->dev, "[Read Test] pass, SIDLY=%x\n", i); pass |= 1 << i; } @@ -1529,11 +1674,13 @@ static int pwrap_init_sidly(struct pmic_wrapper *wrp) static int pwrap_init_dual_io(struct pmic_wrapper *wrp) { int ret; - bool tmp; - u32 rdata; + bool read_ok, tmp; + bool comp_read_ok = true; /* Enable dual IO mode */ pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_DIO_EN], 1); + if (wrp->slave->comp_dew_regs) + pwrap_write(wrp, wrp->slave->comp_dew_regs[PWRAP_DEW_DIO_EN], 1); /* Check IDLE & INIT_DONE in advance */ ret = readx_poll_timeout(pwrap_is_fsm_idle_and_sync_idle, wrp, tmp, tmp, @@ -1546,12 +1693,15 @@ static int pwrap_init_dual_io(struct pmic_wrapper *wrp) pwrap_writel(wrp, 1, PWRAP_DIO_EN); /* Read Test */ - pwrap_read(wrp, - wrp->slave->dew_regs[PWRAP_DEW_READ_TEST], &rdata); - if (rdata != PWRAP_DEW_READ_TEST_VAL) { - dev_err(wrp->dev, - "Read failed on DIO mode: 0x%04x!=0x%04x\n", - PWRAP_DEW_READ_TEST_VAL, rdata); + read_ok = pwrap_pmic_read_test(wrp, wrp->slave->dew_regs, PWRAP_DEW_READ_TEST_VAL); + if (wrp->slave->comp_dew_regs) + comp_read_ok = pwrap_pmic_read_test(wrp, wrp->slave->comp_dew_regs, + PWRAP_DEW_COMP_READ_TEST_VAL); + if (!read_ok || !comp_read_ok) { + dev_err(wrp->dev, "Read failed on DIO mode. Main PMIC %s%s\n", + !read_ok ? "fail" : "success", + wrp->slave->comp_dew_regs && !comp_read_ok ? + ", Companion PMIC fail" : ""); return -EFAULT; } @@ -1586,6 +1736,20 @@ static void pwrap_init_chip_select_ext(struct pmic_wrapper *wrp, u8 hext_write, static int pwrap_common_init_reg_clock(struct pmic_wrapper *wrp) { switch (wrp->master->type) { + case PWRAP_MT6795: + if (wrp->slave->type == PMIC_MT6331) { + const u32 *dew_regs = wrp->slave->dew_regs; + + pwrap_write(wrp, dew_regs[PWRAP_DEW_RDDMY_NO], 0x8); + + if (wrp->slave->comp_type == PMIC_MT6332) { + dew_regs = wrp->slave->comp_dew_regs; + pwrap_write(wrp, dew_regs[PWRAP_DEW_RDDMY_NO], 0x8); + } + } + pwrap_writel(wrp, 0x88, PWRAP_RDDMY); + pwrap_init_chip_select_ext(wrp, 15, 15, 15, 15); + break; case PWRAP_MT8173: pwrap_init_chip_select_ext(wrp, 0, 4, 2, 2); break; @@ -1626,19 +1790,41 @@ static bool pwrap_is_cipher_ready(struct pmic_wrapper *wrp) return pwrap_readl(wrp, PWRAP_CIPHER_RDY) & 1; } -static bool pwrap_is_pmic_cipher_ready(struct pmic_wrapper *wrp) +static bool __pwrap_is_pmic_cipher_ready(struct pmic_wrapper *wrp, const u32 *dew_regs) { u32 rdata; int ret; - ret = pwrap_read(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_RDY], - &rdata); + ret = pwrap_read(wrp, dew_regs[PWRAP_DEW_CIPHER_RDY], &rdata); if (ret) return false; return rdata == 1; } + +static bool pwrap_is_pmic_cipher_ready(struct pmic_wrapper *wrp) +{ + bool ret = __pwrap_is_pmic_cipher_ready(wrp, wrp->slave->dew_regs); + + if (!ret) + return ret; + + /* If there's any companion, wait for it to be ready too */ + if (wrp->slave->comp_dew_regs) + ret = __pwrap_is_pmic_cipher_ready(wrp, wrp->slave->comp_dew_regs); + + return ret; +} + +static void pwrap_config_cipher(struct pmic_wrapper *wrp, const u32 *dew_regs) +{ + pwrap_write(wrp, dew_regs[PWRAP_DEW_CIPHER_SWRST], 0x1); + pwrap_write(wrp, dew_regs[PWRAP_DEW_CIPHER_SWRST], 0x0); + pwrap_write(wrp, dew_regs[PWRAP_DEW_CIPHER_KEY_SEL], 0x1); + pwrap_write(wrp, dew_regs[PWRAP_DEW_CIPHER_IV_SEL], 0x2); +} + static int pwrap_init_cipher(struct pmic_wrapper *wrp) { int ret; @@ -1658,6 +1844,7 @@ static int pwrap_init_cipher(struct pmic_wrapper *wrp) case PWRAP_MT2701: case PWRAP_MT6765: case PWRAP_MT6779: + case PWRAP_MT6795: case PWRAP_MT6797: case PWRAP_MT8173: case PWRAP_MT8186: @@ -1675,10 +1862,11 @@ static int pwrap_init_cipher(struct pmic_wrapper *wrp) } /* Config cipher mode @PMIC */ - pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_SWRST], 0x1); - pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_SWRST], 0x0); - pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_KEY_SEL], 0x1); - pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_IV_SEL], 0x2); + pwrap_config_cipher(wrp, wrp->slave->dew_regs); + + /* If there is any companion PMIC, configure cipher mode there too */ + if (wrp->slave->comp_type > 0) + pwrap_config_cipher(wrp, wrp->slave->comp_dew_regs); switch (wrp->slave->type) { case PMIC_MT6397: @@ -1740,6 +1928,7 @@ static int pwrap_init_cipher(struct pmic_wrapper *wrp) static int pwrap_init_security(struct pmic_wrapper *wrp) { + u32 crc_val; int ret; /* Enable encryption */ @@ -1748,14 +1937,21 @@ static int pwrap_init_security(struct pmic_wrapper *wrp) return ret; /* Signature checking - using CRC */ - if (pwrap_write(wrp, - wrp->slave->dew_regs[PWRAP_DEW_CRC_EN], 0x1)) - return -EFAULT; + ret = pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CRC_EN], 0x1); + if (ret == 0 && wrp->slave->comp_dew_regs) + ret = pwrap_write(wrp, wrp->slave->comp_dew_regs[PWRAP_DEW_CRC_EN], 0x1); pwrap_writel(wrp, 0x1, PWRAP_CRC_EN); pwrap_writel(wrp, 0x0, PWRAP_SIG_MODE); - pwrap_writel(wrp, wrp->slave->dew_regs[PWRAP_DEW_CRC_VAL], - PWRAP_SIG_ADR); + + /* CRC value */ + crc_val = wrp->slave->dew_regs[PWRAP_DEW_CRC_VAL]; + if (wrp->slave->comp_dew_regs) + crc_val |= wrp->slave->comp_dew_regs[PWRAP_DEW_CRC_VAL] << 16; + + pwrap_writel(wrp, crc_val, PWRAP_SIG_ADR); + + /* PMIC Wrapper Arbiter priority */ pwrap_writel(wrp, wrp->master->arb_en_all, PWRAP_HIPRIO_ARB_EN); @@ -1819,6 +2015,19 @@ static int pwrap_mt2701_init_soc_specific(struct pmic_wrapper *wrp) return 0; } +static int pwrap_mt6795_init_soc_specific(struct pmic_wrapper *wrp) +{ + pwrap_writel(wrp, 0xf, PWRAP_STAUPD_GRPEN); + + if (wrp->slave->type == PMIC_MT6331) + pwrap_writel(wrp, 0x1b4, PWRAP_EINT_STA0_ADR); + + if (wrp->slave->comp_type == PMIC_MT6332) + pwrap_writel(wrp, 0x8112, PWRAP_EINT_STA1_ADR); + + return 0; +} + static int pwrap_mt7622_init_soc_specific(struct pmic_wrapper *wrp) { pwrap_writel(wrp, 0, PWRAP_STAUPD_PRD); @@ -1854,10 +2063,16 @@ static int pwrap_init(struct pmic_wrapper *wrp) if (wrp->rstc_bridge) reset_control_reset(wrp->rstc_bridge); - if (wrp->master->type == PWRAP_MT8173) { + switch (wrp->master->type) { + case PWRAP_MT6795: + fallthrough; + case PWRAP_MT8173: /* Enable DCM */ pwrap_writel(wrp, 3, PWRAP_DCM_EN); pwrap_writel(wrp, 0, PWRAP_DCM_DBC_PRD); + break; + default: + break; } if (HAS_CAP(wrp->slave->caps, PWRAP_SLV_CAP_SPI)) { @@ -1982,6 +2197,16 @@ static const struct pwrap_slv_type pmic_mt6323 = { PWRAP_SLV_CAP_SECURITY, }; +static const struct pwrap_slv_type pmic_mt6331 = { + .dew_regs = mt6331_regs, + .type = PMIC_MT6331, + .comp_dew_regs = mt6332_regs, + .comp_type = PMIC_MT6332, + .regops = &pwrap_regops16, + .caps = PWRAP_SLV_CAP_SPI | PWRAP_SLV_CAP_DUALIO | + PWRAP_SLV_CAP_SECURITY, +}; + static const struct pwrap_slv_type pmic_mt6351 = { .dew_regs = mt6351_regs, .type = PMIC_MT6351, @@ -2027,6 +2252,7 @@ static const struct pwrap_slv_type pmic_mt6397 = { static const struct of_device_id of_slave_match_tbl[] = { { .compatible = "mediatek,mt6323", .data = &pmic_mt6323 }, + { .compatible = "mediatek,mt6331", .data = &pmic_mt6331 }, { .compatible = "mediatek,mt6351", .data = &pmic_mt6351 }, { .compatible = "mediatek,mt6357", .data = &pmic_mt6357 }, { .compatible = "mediatek,mt6358", .data = &pmic_mt6358 }, @@ -2079,6 +2305,19 @@ static const struct pmic_wrapper_type pwrap_mt6779 = { .init_soc_specific = NULL, }; +static const struct pmic_wrapper_type pwrap_mt6795 = { + .regs = mt6795_regs, + .type = PWRAP_MT6795, + .arb_en_all = 0x3f, + .int_en_all = ~(u32)(BIT(31) | BIT(2) | BIT(1)), + .int1_en_all = 0, + .spi_w = PWRAP_MAN_CMD_SPI_WRITE, + .wdt_src = PWRAP_WDT_SRC_MASK_NO_STAUPD, + .caps = PWRAP_CAP_RESET | PWRAP_CAP_DCM, + .init_reg_clock = pwrap_common_init_reg_clock, + .init_soc_specific = pwrap_mt6795_init_soc_specific, +}; + static const struct pmic_wrapper_type pwrap_mt6797 = { .regs = mt6797_regs, .type = PWRAP_MT6797, @@ -2212,6 +2451,7 @@ static const struct of_device_id of_pwrap_match_tbl[] = { { .compatible = "mediatek,mt2701-pwrap", .data = &pwrap_mt2701 }, { .compatible = "mediatek,mt6765-pwrap", .data = &pwrap_mt6765 }, { .compatible = "mediatek,mt6779-pwrap", .data = &pwrap_mt6779 }, + { .compatible = "mediatek,mt6795-pwrap", .data = &pwrap_mt6795 }, { .compatible = "mediatek,mt6797-pwrap", .data = &pwrap_mt6797 }, { .compatible = "mediatek,mt6873-pwrap", .data = &pwrap_mt6873 }, { .compatible = "mediatek,mt7622-pwrap", .data = &pwrap_mt7622 }, diff --git a/drivers/soc/mediatek/mtk-svs.c b/drivers/soc/mediatek/mtk-svs.c index 81585733c8a99401276db4858cd528efff580d09..3a2f97cd5272001bb0e0f953fd571019e7830f1d 100644 --- a/drivers/soc/mediatek/mtk-svs.c +++ b/drivers/soc/mediatek/mtk-svs.c @@ -2061,9 +2061,9 @@ static int svs_mt8192_platform_probe(struct svs_platform *svsp) svsb = &svsp->banks[idx]; if (svsb->type == SVSB_HIGH) - svsb->opp_dev = svs_add_device_link(svsp, "mali"); + svsb->opp_dev = svs_add_device_link(svsp, "gpu"); else if (svsb->type == SVSB_LOW) - svsb->opp_dev = svs_get_subsys_device(svsp, "mali"); + svsb->opp_dev = svs_get_subsys_device(svsp, "gpu"); if (IS_ERR(svsb->opp_dev)) return dev_err_probe(svsp->dev, PTR_ERR(svsb->opp_dev), diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig index a491718f8064f9b0c347e9851e75a7d8cf6fd246..e597799e8121dad29c640ed933a52953458de426 100644 --- a/drivers/soc/qcom/Kconfig +++ b/drivers/soc/qcom/Kconfig @@ -135,6 +135,17 @@ config QCOM_RMTFS_MEM Say y here if you intend to boot the modem remoteproc. +config QCOM_RPM_MASTER_STATS + tristate "Qualcomm RPM Master stats" + depends on ARCH_QCOM || COMPILE_TEST + help + The RPM Master sleep stats driver provides detailed per-subsystem + sleep/wake data, read from the RPM message RAM. It can be used to + assess whether all the low-power modes available are entered as + expected or to check which part of the SoC prevents it from sleeping. + + Say y here if you intend to debug or monitor platform sleep. + config QCOM_RPMH tristate "Qualcomm RPM-Hardened (RPMH) Communication" depends on ARCH_QCOM || COMPILE_TEST diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile index 89b775512befa1cc2d12462a09dd567cf5d6a726..99114c71092baffbbc5ba7f22a75a84fb6487907 100644 --- a/drivers/soc/qcom/Makefile +++ b/drivers/soc/qcom/Makefile @@ -14,6 +14,7 @@ obj-$(CONFIG_QCOM_QMI_HELPERS) += qmi_helpers.o qmi_helpers-y += qmi_encdec.o qmi_interface.o obj-$(CONFIG_QCOM_RAMP_CTRL) += ramp_controller.o obj-$(CONFIG_QCOM_RMTFS_MEM) += rmtfs_mem.o +obj-$(CONFIG_QCOM_RPM_MASTER_STATS) += rpm_master_stats.o obj-$(CONFIG_QCOM_RPMH) += qcom_rpmh.o qcom_rpmh-y += rpmh-rsc.o qcom_rpmh-y += rpmh.o diff --git a/drivers/soc/qcom/icc-bwmon.c b/drivers/soc/qcom/icc-bwmon.c index f65bfeca7ed6b9802e7a2eb038f6fe72710b98af..40068a2859135256f72a36a103f980a2ead7b36e 100644 --- a/drivers/soc/qcom/icc-bwmon.c +++ b/drivers/soc/qcom/icc-bwmon.c @@ -806,7 +806,7 @@ static int bwmon_remove(struct platform_device *pdev) static const struct icc_bwmon_data msm8998_bwmon_data = { .sample_ms = 4, - .count_unit_kb = 64, + .count_unit_kb = 1024, .default_highbw_kbps = 4800 * 1024, /* 4.8 GBps */ .default_medbw_kbps = 512 * 1024, /* 512 MBps */ .default_lowbw_kbps = 0, diff --git a/drivers/soc/qcom/mdt_loader.c b/drivers/soc/qcom/mdt_loader.c index 33dd8c315eb73ca888a5f7c62f69da78b7b18c94..6f177e46fa0f8ec3adff1338c0f0de3a41633cf6 100644 --- a/drivers/soc/qcom/mdt_loader.c +++ b/drivers/soc/qcom/mdt_loader.c @@ -210,6 +210,7 @@ int qcom_mdt_pas_init(struct device *dev, const struct firmware *fw, const struct elf32_hdr *ehdr; phys_addr_t min_addr = PHYS_ADDR_MAX; phys_addr_t max_addr = 0; + bool relocate = false; size_t metadata_len; void *metadata; int ret; @@ -224,6 +225,9 @@ int qcom_mdt_pas_init(struct device *dev, const struct firmware *fw, if (!mdt_phdr_valid(phdr)) continue; + if (phdr->p_flags & QCOM_MDT_RELOCATABLE) + relocate = true; + if (phdr->p_paddr < min_addr) min_addr = phdr->p_paddr; @@ -246,11 +250,13 @@ int qcom_mdt_pas_init(struct device *dev, const struct firmware *fw, goto out; } - ret = qcom_scm_pas_mem_setup(pas_id, mem_phys, max_addr - min_addr); - if (ret) { - /* Unable to set up relocation */ - dev_err(dev, "error %d setting up firmware %s\n", ret, fw_name); - goto out; + if (relocate) { + ret = qcom_scm_pas_mem_setup(pas_id, mem_phys, max_addr - min_addr); + if (ret) { + /* Unable to set up relocation */ + dev_err(dev, "error %d setting up firmware %s\n", ret, fw_name); + goto out; + } } out: @@ -258,6 +264,34 @@ int qcom_mdt_pas_init(struct device *dev, const struct firmware *fw, } EXPORT_SYMBOL_GPL(qcom_mdt_pas_init); +static bool qcom_mdt_bins_are_split(const struct firmware *fw, const char *fw_name) +{ + const struct elf32_phdr *phdrs; + const struct elf32_hdr *ehdr; + uint64_t seg_start, seg_end; + int i; + + ehdr = (struct elf32_hdr *)fw->data; + phdrs = (struct elf32_phdr *)(ehdr + 1); + + for (i = 0; i < ehdr->e_phnum; i++) { + /* + * The size of the MDT file is not padded to include any + * zero-sized segments at the end. Ignore these, as they should + * not affect the decision about image being split or not. + */ + if (!phdrs[i].p_filesz) + continue; + + seg_start = phdrs[i].p_offset; + seg_end = phdrs[i].p_offset + phdrs[i].p_filesz; + if (seg_start > fw->size || seg_end > fw->size) + return true; + } + + return false; +} + static int __qcom_mdt_load(struct device *dev, const struct firmware *fw, const char *fw_name, int pas_id, void *mem_region, phys_addr_t mem_phys, size_t mem_size, @@ -270,6 +304,7 @@ static int __qcom_mdt_load(struct device *dev, const struct firmware *fw, phys_addr_t min_addr = PHYS_ADDR_MAX; ssize_t offset; bool relocate = false; + bool is_split; void *ptr; int ret = 0; int i; @@ -277,6 +312,7 @@ static int __qcom_mdt_load(struct device *dev, const struct firmware *fw, if (!fw || !mem_region || !mem_phys || !mem_size) return -EINVAL; + is_split = qcom_mdt_bins_are_split(fw, fw_name); ehdr = (struct elf32_hdr *)fw->data; phdrs = (struct elf32_phdr *)(ehdr + 1); @@ -330,8 +366,7 @@ static int __qcom_mdt_load(struct device *dev, const struct firmware *fw, ptr = mem_region + offset; - if (phdr->p_filesz && phdr->p_offset < fw->size && - phdr->p_offset + phdr->p_filesz <= fw->size) { + if (phdr->p_filesz && !is_split) { /* Firmware is large enough to be non-split */ if (phdr->p_offset + phdr->p_filesz > fw->size) { dev_err(dev, "file %s segment %d would be truncated\n", diff --git a/drivers/soc/qcom/ocmem.c b/drivers/soc/qcom/ocmem.c index 199fe9872035098d790cace43a800018bc6a5ee0..aaddc3cc53b7f3121c5b27576d053d85beb5b8e1 100644 --- a/drivers/soc/qcom/ocmem.c +++ b/drivers/soc/qcom/ocmem.c @@ -76,6 +76,10 @@ struct ocmem { #define OCMEM_REG_GFX_MPU_START 0x00001004 #define OCMEM_REG_GFX_MPU_END 0x00001008 +#define OCMEM_HW_VERSION_MAJOR(val) FIELD_GET(GENMASK(31, 28), val) +#define OCMEM_HW_VERSION_MINOR(val) FIELD_GET(GENMASK(27, 16), val) +#define OCMEM_HW_VERSION_STEP(val) FIELD_GET(GENMASK(15, 0), val) + #define OCMEM_HW_PROFILE_NUM_PORTS(val) FIELD_PREP(0x0000000f, (val)) #define OCMEM_HW_PROFILE_NUM_MACROS(val) FIELD_PREP(0x00003f00, (val)) @@ -355,6 +359,12 @@ static int ocmem_dev_probe(struct platform_device *pdev) } } + reg = ocmem_read(ocmem, OCMEM_REG_HW_VERSION); + dev_dbg(dev, "OCMEM hardware version: %lu.%lu.%lu\n", + OCMEM_HW_VERSION_MAJOR(reg), + OCMEM_HW_VERSION_MINOR(reg), + OCMEM_HW_VERSION_STEP(reg)); + reg = ocmem_read(ocmem, OCMEM_REG_HW_PROFILE); ocmem->num_ports = OCMEM_HW_PROFILE_NUM_PORTS(reg); ocmem->num_macros = OCMEM_HW_PROFILE_NUM_MACROS(reg); diff --git a/drivers/soc/qcom/pmic_glink.c b/drivers/soc/qcom/pmic_glink.c index 8bf95df0a56ac9f26cf741740d22af40005a0fdc..c87056769ebd89498dd97d19691c47b543241325 100644 --- a/drivers/soc/qcom/pmic_glink.c +++ b/drivers/soc/qcom/pmic_glink.c @@ -338,13 +338,17 @@ static int pmic_glink_remove(struct platform_device *pdev) return 0; } -/* Do not handle altmode for now on those platforms */ static const unsigned long pmic_glink_sm8450_client_mask = BIT(PMIC_GLINK_CLIENT_BATT) | + BIT(PMIC_GLINK_CLIENT_ALTMODE) | + BIT(PMIC_GLINK_CLIENT_UCSI); + +/* Do not handle altmode for now on those platforms */ +static const unsigned long pmic_glink_sm8550_client_mask = BIT(PMIC_GLINK_CLIENT_BATT) | BIT(PMIC_GLINK_CLIENT_UCSI); static const struct of_device_id pmic_glink_of_match[] = { { .compatible = "qcom,sm8450-pmic-glink", .data = &pmic_glink_sm8450_client_mask }, - { .compatible = "qcom,sm8550-pmic-glink", .data = &pmic_glink_sm8450_client_mask }, + { .compatible = "qcom,sm8550-pmic-glink", .data = &pmic_glink_sm8550_client_mask }, { .compatible = "qcom,pmic-glink" }, {} }; diff --git a/drivers/soc/qcom/pmic_glink_altmode.c b/drivers/soc/qcom/pmic_glink_altmode.c index 4d7895bdeaf2f01f96e94bdf33c571bc03589f32..df48fbea4b6862d06d7b09b38f34305ab54d824e 100644 --- a/drivers/soc/qcom/pmic_glink_altmode.c +++ b/drivers/soc/qcom/pmic_glink_altmode.c @@ -369,7 +369,6 @@ static int pmic_glink_altmode_probe(struct auxiliary_device *adev, { struct pmic_glink_altmode_port *alt_port; struct pmic_glink_altmode *altmode; - struct typec_altmode_desc mux_desc = {}; const struct of_device_id *match; struct fwnode_handle *fwnode; struct device *dev = &adev->dev; @@ -427,9 +426,7 @@ static int pmic_glink_altmode_probe(struct auxiliary_device *adev, alt_port->dp_alt.mode = USB_TYPEC_DP_MODE; alt_port->dp_alt.active = 1; - mux_desc.svid = USB_TYPEC_DP_SID; - mux_desc.mode = USB_TYPEC_DP_MODE; - alt_port->typec_mux = fwnode_typec_mux_get(fwnode, &mux_desc); + alt_port->typec_mux = fwnode_typec_mux_get(fwnode); if (IS_ERR(alt_port->typec_mux)) return dev_err_probe(dev, PTR_ERR(alt_port->typec_mux), "failed to acquire mode-switch for port: %d\n", diff --git a/drivers/soc/qcom/qcom-geni-se.c b/drivers/soc/qcom/qcom-geni-se.c index 795a2e1d59b3abc47b9a9a9f9130e607fb00666f..ba788762835fad7738ad968276c9fd5b7b767941 100644 --- a/drivers/soc/qcom/qcom-geni-se.c +++ b/drivers/soc/qcom/qcom-geni-se.c @@ -281,27 +281,14 @@ static void geni_se_select_fifo_mode(struct geni_se *se) geni_se_irq_clear(se); - /* - * The RX path for the UART is asynchronous and so needs more - * complex logic for enabling / disabling its interrupts. - * - * Specific notes: - * - The done and TX-related interrupts are managed manually. - * - We don't RX from the main sequencer (we use the secondary) so - * we don't need the RX-related interrupts enabled in the main - * sequencer for UART. - */ + /* UART driver manages enabling / disabling interrupts internally */ if (proto != GENI_SE_UART) { + /* Non-UART use only primary sequencer so dont bother about S_IRQ */ val_old = val = readl_relaxed(se->base + SE_GENI_M_IRQ_EN); val |= M_CMD_DONE_EN | M_TX_FIFO_WATERMARK_EN; val |= M_RX_FIFO_WATERMARK_EN | M_RX_FIFO_LAST_EN; if (val != val_old) writel_relaxed(val, se->base + SE_GENI_M_IRQ_EN); - - val_old = val = readl_relaxed(se->base + SE_GENI_S_IRQ_EN); - val |= S_CMD_DONE_EN; - if (val != val_old) - writel_relaxed(val, se->base + SE_GENI_S_IRQ_EN); } val_old = val = readl_relaxed(se->base + SE_GENI_DMA_MODE_EN); @@ -317,17 +304,14 @@ static void geni_se_select_dma_mode(struct geni_se *se) geni_se_irq_clear(se); + /* UART driver manages enabling / disabling interrupts internally */ if (proto != GENI_SE_UART) { + /* Non-UART use only primary sequencer so dont bother about S_IRQ */ val_old = val = readl_relaxed(se->base + SE_GENI_M_IRQ_EN); val &= ~(M_CMD_DONE_EN | M_TX_FIFO_WATERMARK_EN); val &= ~(M_RX_FIFO_WATERMARK_EN | M_RX_FIFO_LAST_EN); if (val != val_old) writel_relaxed(val, se->base + SE_GENI_M_IRQ_EN); - - val_old = val = readl_relaxed(se->base + SE_GENI_S_IRQ_EN); - val &= ~S_CMD_DONE_EN; - if (val != val_old) - writel_relaxed(val, se->base + SE_GENI_S_IRQ_EN); } val_old = val = readl_relaxed(se->base + SE_GENI_DMA_MODE_EN); @@ -344,10 +328,6 @@ static void geni_se_select_gpi_mode(struct geni_se *se) writel(0, se->base + SE_IRQ_EN); - val = readl(se->base + SE_GENI_S_IRQ_EN); - val &= ~S_CMD_DONE_EN; - writel(val, se->base + SE_GENI_S_IRQ_EN); - val = readl(se->base + SE_GENI_M_IRQ_EN); val &= ~(M_CMD_DONE_EN | M_TX_FIFO_WATERMARK_EN | M_RX_FIFO_WATERMARK_EN | M_RX_FIFO_LAST_EN); @@ -682,6 +662,30 @@ EXPORT_SYMBOL(geni_se_clk_freq_match); #define GENI_SE_DMA_EOT_EN BIT(1) #define GENI_SE_DMA_AHB_ERR_EN BIT(2) #define GENI_SE_DMA_EOT_BUF BIT(0) + +/** + * geni_se_tx_init_dma() - Initiate TX DMA transfer on the serial engine + * @se: Pointer to the concerned serial engine. + * @iova: Mapped DMA address. + * @len: Length of the TX buffer. + * + * This function is used to initiate DMA TX transfer. + */ +void geni_se_tx_init_dma(struct geni_se *se, dma_addr_t iova, size_t len) +{ + u32 val; + + val = GENI_SE_DMA_DONE_EN; + val |= GENI_SE_DMA_EOT_EN; + val |= GENI_SE_DMA_AHB_ERR_EN; + writel_relaxed(val, se->base + SE_DMA_TX_IRQ_EN_SET); + writel_relaxed(lower_32_bits(iova), se->base + SE_DMA_TX_PTR_L); + writel_relaxed(upper_32_bits(iova), se->base + SE_DMA_TX_PTR_H); + writel_relaxed(GENI_SE_DMA_EOT_BUF, se->base + SE_DMA_TX_ATTR); + writel(len, se->base + SE_DMA_TX_LEN); +} +EXPORT_SYMBOL(geni_se_tx_init_dma); + /** * geni_se_tx_dma_prep() - Prepare the serial engine for TX DMA transfer * @se: Pointer to the concerned serial engine. @@ -697,7 +701,6 @@ int geni_se_tx_dma_prep(struct geni_se *se, void *buf, size_t len, dma_addr_t *iova) { struct geni_wrapper *wrapper = se->wrapper; - u32 val; if (!wrapper) return -EINVAL; @@ -706,17 +709,34 @@ int geni_se_tx_dma_prep(struct geni_se *se, void *buf, size_t len, if (dma_mapping_error(wrapper->dev, *iova)) return -EIO; + geni_se_tx_init_dma(se, *iova, len); + return 0; +} +EXPORT_SYMBOL(geni_se_tx_dma_prep); + +/** + * geni_se_rx_init_dma() - Initiate RX DMA transfer on the serial engine + * @se: Pointer to the concerned serial engine. + * @iova: Mapped DMA address. + * @len: Length of the RX buffer. + * + * This function is used to initiate DMA RX transfer. + */ +void geni_se_rx_init_dma(struct geni_se *se, dma_addr_t iova, size_t len) +{ + u32 val; + val = GENI_SE_DMA_DONE_EN; val |= GENI_SE_DMA_EOT_EN; val |= GENI_SE_DMA_AHB_ERR_EN; - writel_relaxed(val, se->base + SE_DMA_TX_IRQ_EN_SET); - writel_relaxed(lower_32_bits(*iova), se->base + SE_DMA_TX_PTR_L); - writel_relaxed(upper_32_bits(*iova), se->base + SE_DMA_TX_PTR_H); - writel_relaxed(GENI_SE_DMA_EOT_BUF, se->base + SE_DMA_TX_ATTR); - writel(len, se->base + SE_DMA_TX_LEN); - return 0; + writel_relaxed(val, se->base + SE_DMA_RX_IRQ_EN_SET); + writel_relaxed(lower_32_bits(iova), se->base + SE_DMA_RX_PTR_L); + writel_relaxed(upper_32_bits(iova), se->base + SE_DMA_RX_PTR_H); + /* RX does not have EOT buffer type bit. So just reset RX_ATTR */ + writel_relaxed(0, se->base + SE_DMA_RX_ATTR); + writel(len, se->base + SE_DMA_RX_LEN); } -EXPORT_SYMBOL(geni_se_tx_dma_prep); +EXPORT_SYMBOL(geni_se_rx_init_dma); /** * geni_se_rx_dma_prep() - Prepare the serial engine for RX DMA transfer @@ -733,7 +753,6 @@ int geni_se_rx_dma_prep(struct geni_se *se, void *buf, size_t len, dma_addr_t *iova) { struct geni_wrapper *wrapper = se->wrapper; - u32 val; if (!wrapper) return -EINVAL; @@ -742,15 +761,7 @@ int geni_se_rx_dma_prep(struct geni_se *se, void *buf, size_t len, if (dma_mapping_error(wrapper->dev, *iova)) return -EIO; - val = GENI_SE_DMA_DONE_EN; - val |= GENI_SE_DMA_EOT_EN; - val |= GENI_SE_DMA_AHB_ERR_EN; - writel_relaxed(val, se->base + SE_DMA_RX_IRQ_EN_SET); - writel_relaxed(lower_32_bits(*iova), se->base + SE_DMA_RX_PTR_L); - writel_relaxed(upper_32_bits(*iova), se->base + SE_DMA_RX_PTR_H); - /* RX does not have EOT buffer type bit. So just reset RX_ATTR */ - writel_relaxed(0, se->base + SE_DMA_RX_ATTR); - writel(len, se->base + SE_DMA_RX_LEN); + geni_se_rx_init_dma(se, *iova, len); return 0; } EXPORT_SYMBOL(geni_se_rx_dma_prep); diff --git a/drivers/soc/qcom/qmi_interface.c b/drivers/soc/qcom/qmi_interface.c index 820bdd9f8e4686b51fbeb5f5c7b0b3c3c91d0a23..78d7361fdcf2d71f8896d85119412d846f1fa778 100644 --- a/drivers/soc/qcom/qmi_interface.c +++ b/drivers/soc/qcom/qmi_interface.c @@ -650,7 +650,7 @@ int qmi_handle_init(struct qmi_handle *qmi, size_t recv_buf_size, if (!qmi->recv_buf) return -ENOMEM; - qmi->wq = alloc_workqueue("qmi_msg_handler", WQ_UNBOUND, 1); + qmi->wq = alloc_ordered_workqueue("qmi_msg_handler", 0); if (!qmi->wq) { ret = -ENOMEM; goto err_free_recv_buf; diff --git a/drivers/soc/qcom/ramp_controller.c b/drivers/soc/qcom/ramp_controller.c index 5e3ba0be090354fb05d84c450879c8ddb9a2625a..e9a0cca0718924fe7b93d743242cf91b0c911f93 100644 --- a/drivers/soc/qcom/ramp_controller.c +++ b/drivers/soc/qcom/ramp_controller.c @@ -308,12 +308,15 @@ static int qcom_ramp_controller_probe(struct platform_device *pdev) return qcom_ramp_controller_start(qrc); } -static int qcom_ramp_controller_remove(struct platform_device *pdev) +static void qcom_ramp_controller_remove(struct platform_device *pdev) { struct qcom_ramp_controller *qrc = platform_get_drvdata(pdev); + int ret; - return rc_write_cfg(qrc, qrc->desc->cfg_ramp_dis, - RC_DCVS_CFG_SID, qrc->desc->num_ramp_dis); + ret = rc_write_cfg(qrc, qrc->desc->cfg_ramp_dis, + RC_DCVS_CFG_SID, qrc->desc->num_ramp_dis); + if (ret) + dev_err(&pdev->dev, "Failed to send disable sequence\n"); } static const struct of_device_id qcom_ramp_controller_match_table[] = { @@ -329,7 +332,7 @@ static struct platform_driver qcom_ramp_controller_driver = { .suppress_bind_attrs = true, }, .probe = qcom_ramp_controller_probe, - .remove = qcom_ramp_controller_remove, + .remove_new = qcom_ramp_controller_remove, }; static int __init qcom_ramp_controller_init(void) diff --git a/drivers/soc/qcom/rpm_master_stats.c b/drivers/soc/qcom/rpm_master_stats.c new file mode 100644 index 0000000000000000000000000000000000000000..9ca13bcf67d3c047460752b029727b80b307b670 --- /dev/null +++ b/drivers/soc/qcom/rpm_master_stats.c @@ -0,0 +1,163 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2012-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2023, Linaro Limited + * + * This driver supports what is known as "Master Stats v2" in Qualcomm + * downstream kernel terms, which seems to be the only version which has + * ever shipped, all the way from 2013 to 2023. + */ + +#include +#include +#include +#include +#include +#include + +struct master_stats_data { + void __iomem *base; + const char *label; +}; + +struct rpm_master_stats { + u32 active_cores; + u32 num_shutdowns; + u64 shutdown_req; + u64 wakeup_idx; + u64 bringup_req; + u64 bringup_ack; + u32 wakeup_reason; /* 0 = "rude wakeup", 1 = scheduled wakeup */ + u32 last_sleep_trans_dur; + u32 last_wake_trans_dur; + + /* Per-subsystem (*not necessarily* SoC-wide) XO shutdown stats */ + u32 xo_count; + u64 xo_last_enter; + u64 last_exit; + u64 xo_total_dur; +} __packed; + +static int master_stats_show(struct seq_file *s, void *unused) +{ + struct master_stats_data *data = s->private; + struct rpm_master_stats stat; + + memcpy_fromio(&stat, data->base, sizeof(stat)); + + seq_printf(s, "%s:\n", data->label); + + seq_printf(s, "\tLast shutdown @ %llu\n", stat.shutdown_req); + seq_printf(s, "\tLast bringup req @ %llu\n", stat.bringup_req); + seq_printf(s, "\tLast bringup ack @ %llu\n", stat.bringup_ack); + seq_printf(s, "\tLast wakeup idx: %llu\n", stat.wakeup_idx); + seq_printf(s, "\tLast XO shutdown enter @ %llu\n", stat.xo_last_enter); + seq_printf(s, "\tLast XO shutdown exit @ %llu\n", stat.last_exit); + seq_printf(s, "\tXO total duration: %llu\n", stat.xo_total_dur); + seq_printf(s, "\tLast sleep transition duration: %u\n", stat.last_sleep_trans_dur); + seq_printf(s, "\tLast wake transition duration: %u\n", stat.last_wake_trans_dur); + seq_printf(s, "\tXO shutdown count: %u\n", stat.xo_count); + seq_printf(s, "\tWakeup reason: 0x%x\n", stat.wakeup_reason); + seq_printf(s, "\tShutdown count: %u\n", stat.num_shutdowns); + seq_printf(s, "\tActive cores bitmask: 0x%x\n", stat.active_cores); + + return 0; +} +DEFINE_SHOW_ATTRIBUTE(master_stats); + +static int master_stats_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct master_stats_data *data; + struct device_node *msgram_np; + struct dentry *dent, *root; + struct resource res; + int count, i, ret; + + count = of_property_count_strings(dev->of_node, "qcom,master-names"); + if (count < 0) + return count; + + data = devm_kzalloc(dev, count * sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + root = debugfs_create_dir("qcom_rpm_master_stats", NULL); + platform_set_drvdata(pdev, root); + + for (i = 0; i < count; i++) { + msgram_np = of_parse_phandle(dev->of_node, "qcom,rpm-msg-ram", i); + if (!msgram_np) { + debugfs_remove_recursive(root); + return dev_err_probe(dev, -ENODEV, + "Couldn't parse MSG RAM phandle idx %d", i); + } + + /* + * Purposefully skip devm_platform helpers as we're using a + * shared resource. + */ + ret = of_address_to_resource(msgram_np, 0, &res); + of_node_put(msgram_np); + if (ret < 0) { + debugfs_remove_recursive(root); + return ret; + } + + data[i].base = devm_ioremap(dev, res.start, resource_size(&res)); + if (!data[i].base) { + debugfs_remove_recursive(root); + return dev_err_probe(dev, -EINVAL, + "Could not map the MSG RAM slice idx %d!\n", i); + } + + ret = of_property_read_string_index(dev->of_node, "qcom,master-names", i, + &data[i].label); + if (ret < 0) { + debugfs_remove_recursive(root); + return dev_err_probe(dev, ret, + "Could not read name idx %d!\n", i); + } + + /* + * Generally it's not advised to fail on debugfs errors, but this + * driver's only job is exposing data therein. + */ + dent = debugfs_create_file(data[i].label, 0444, root, + &data[i], &master_stats_fops); + if (IS_ERR(dent)) { + debugfs_remove_recursive(root); + return dev_err_probe(dev, PTR_ERR(dent), + "Failed to create debugfs file %s!\n", data[i].label); + } + } + + device_set_pm_not_required(dev); + + return 0; +} + +static void master_stats_remove(struct platform_device *pdev) +{ + struct dentry *root = platform_get_drvdata(pdev); + + debugfs_remove_recursive(root); +} + +static const struct of_device_id rpm_master_table[] = { + { .compatible = "qcom,rpm-master-stats" }, + { }, +}; + +static struct platform_driver master_stats_driver = { + .probe = master_stats_probe, + .remove_new = master_stats_remove, + .driver = { + .name = "qcom_rpm_master_stats", + .of_match_table = rpm_master_table, + }, +}; +module_platform_driver(master_stats_driver); + +MODULE_DESCRIPTION("Qualcomm RPM Master Statistics driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/soc/qcom/rpmpd.c b/drivers/soc/qcom/rpmpd.c index f8397dcb146cf79069282ec62d1cb2d0f7121684..99b017fd76b734e390408dc51d6a727e34254651 100644 --- a/drivers/soc/qcom/rpmpd.c +++ b/drivers/soc/qcom/rpmpd.c @@ -892,8 +892,8 @@ static int rpmpd_set_performance(struct generic_pm_domain *domain, pd->corner = state; /* Always send updates for vfc and vfl */ - if (!pd->enabled && pd->key != KEY_FLOOR_CORNER && - pd->key != KEY_FLOOR_LEVEL) + if (!pd->enabled && pd->key != cpu_to_le32(KEY_FLOOR_CORNER) && + pd->key != cpu_to_le32(KEY_FLOOR_LEVEL)) goto out; ret = rpmpd_aggregate_corner(pd); diff --git a/drivers/soc/qcom/smem.c b/drivers/soc/qcom/smem.c index 6be7ea93c78cfe01777df0fb6f558f90a8f933d8..b0d59e815c3b746e58655034fb037c0f076fd4b5 100644 --- a/drivers/soc/qcom/smem.c +++ b/drivers/soc/qcom/smem.c @@ -14,6 +14,7 @@ #include #include #include +#include /* * The Qualcomm shared memory system is a allocate only heap structure that @@ -500,7 +501,7 @@ int qcom_smem_alloc(unsigned host, unsigned item, size_t size) return ret; } -EXPORT_SYMBOL(qcom_smem_alloc); +EXPORT_SYMBOL_GPL(qcom_smem_alloc); static void *qcom_smem_get_global(struct qcom_smem *smem, unsigned item, @@ -674,7 +675,7 @@ void *qcom_smem_get(unsigned host, unsigned item, size_t *size) return ptr; } -EXPORT_SYMBOL(qcom_smem_get); +EXPORT_SYMBOL_GPL(qcom_smem_get); /** * qcom_smem_get_free_space() - retrieve amount of free space in a partition @@ -719,7 +720,7 @@ int qcom_smem_get_free_space(unsigned host) return ret; } -EXPORT_SYMBOL(qcom_smem_get_free_space); +EXPORT_SYMBOL_GPL(qcom_smem_get_free_space); static bool addr_in_range(void __iomem *base, size_t size, void *addr) { @@ -770,7 +771,29 @@ phys_addr_t qcom_smem_virt_to_phys(void *p) return 0; } -EXPORT_SYMBOL(qcom_smem_virt_to_phys); +EXPORT_SYMBOL_GPL(qcom_smem_virt_to_phys); + +/** + * qcom_smem_get_soc_id() - return the SoC ID + * @id: On success, we return the SoC ID here. + * + * Look up SoC ID from HW/SW build ID and return it. + * + * Return: 0 on success, negative errno on failure. + */ +int qcom_smem_get_soc_id(u32 *id) +{ + struct socinfo *info; + + info = qcom_smem_get(QCOM_SMEM_HOST_ANY, SMEM_HW_SW_BUILD_ID, NULL); + if (IS_ERR(info)) + return PTR_ERR(info); + + *id = __le32_to_cpu(info->id); + + return 0; +} +EXPORT_SYMBOL_GPL(qcom_smem_get_soc_id); static int qcom_smem_get_sbl_version(struct qcom_smem *smem) { diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c index c2e4a57dd6665c7f9736f4762e1519c9b2da5222..4d49945b3a35c6f44e5b999333a0ebd78d0dde23 100644 --- a/drivers/soc/qcom/socinfo.c +++ b/drivers/soc/qcom/socinfo.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -32,15 +33,6 @@ #define qcom_board_id(id) QCOM_ID_ ## id, __stringify(id) #define qcom_board_id_named(id, name) QCOM_ID_ ## id, (name) -#define SMEM_SOCINFO_BUILD_ID_LENGTH 32 -#define SMEM_SOCINFO_CHIP_ID_LENGTH 32 - -/* - * SMEM item id, used to acquire handles to respective - * SMEM region. - */ -#define SMEM_HW_SW_BUILD_ID 137 - #ifdef CONFIG_DEBUG_FS #define SMEM_IMAGE_VERSION_BLOCKS_COUNT 32 #define SMEM_IMAGE_VERSION_SIZE 4096 @@ -126,64 +118,7 @@ static const char *const pmic_models[] = { [58] = "PM8450", [65] = "PM8010", }; -#endif /* CONFIG_DEBUG_FS */ -/* Socinfo SMEM item structure */ -struct socinfo { - __le32 fmt; - __le32 id; - __le32 ver; - char build_id[SMEM_SOCINFO_BUILD_ID_LENGTH]; - /* Version 2 */ - __le32 raw_id; - __le32 raw_ver; - /* Version 3 */ - __le32 hw_plat; - /* Version 4 */ - __le32 plat_ver; - /* Version 5 */ - __le32 accessory_chip; - /* Version 6 */ - __le32 hw_plat_subtype; - /* Version 7 */ - __le32 pmic_model; - __le32 pmic_die_rev; - /* Version 8 */ - __le32 pmic_model_1; - __le32 pmic_die_rev_1; - __le32 pmic_model_2; - __le32 pmic_die_rev_2; - /* Version 9 */ - __le32 foundry_id; - /* Version 10 */ - __le32 serial_num; - /* Version 11 */ - __le32 num_pmics; - __le32 pmic_array_offset; - /* Version 12 */ - __le32 chip_family; - __le32 raw_device_family; - __le32 raw_device_num; - /* Version 13 */ - __le32 nproduct_id; - char chip_id[SMEM_SOCINFO_CHIP_ID_LENGTH]; - /* Version 14 */ - __le32 num_clusters; - __le32 ncluster_array_offset; - __le32 num_defective_parts; - __le32 ndefective_parts_array_offset; - /* Version 15 */ - __le32 nmodem_supported; - /* Version 16 */ - __le32 feature_code; - __le32 pcode; - __le32 npartnamemap_offset; - __le32 nnum_partname_mapping; - /* Version 17 */ - __le32 oem_variant; -}; - -#ifdef CONFIG_DEBUG_FS struct socinfo_params { u32 raw_device_family; u32 hw_plat_subtype; @@ -198,12 +133,15 @@ struct socinfo_params { u32 nproduct_id; u32 num_clusters; u32 ncluster_array_offset; - u32 num_defective_parts; - u32 ndefective_parts_array_offset; + u32 num_subset_parts; + u32 nsubset_parts_array_offset; u32 nmodem_supported; u32 feature_code; u32 pcode; u32 oem_variant; + u32 num_func_clusters; + u32 boot_cluster; + u32 boot_core; }; struct smem_image_version { @@ -434,6 +372,9 @@ static const struct soc_id soc_id[] = { { qcom_board_id(SM8350) }, { qcom_board_id(QCM2290) }, { qcom_board_id(SM6115) }, + { qcom_board_id(IPQ5010) }, + { qcom_board_id(IPQ5018) }, + { qcom_board_id(IPQ5028) }, { qcom_board_id(SC8280XP) }, { qcom_board_id(IPQ6005) }, { qcom_board_id(QRB5165) }, @@ -447,6 +388,9 @@ static const struct soc_id soc_id[] = { { qcom_board_id_named(SM8450_3, "SM8450") }, { qcom_board_id(SC7280) }, { qcom_board_id(SC7180P) }, + { qcom_board_id(IPQ5000) }, + { qcom_board_id(IPQ0509) }, + { qcom_board_id(IPQ0518) }, { qcom_board_id(SM6375) }, { qcom_board_id(IPQ9514) }, { qcom_board_id(IPQ9550) }, @@ -454,6 +398,7 @@ static const struct soc_id soc_id[] = { { qcom_board_id(IPQ9570) }, { qcom_board_id(IPQ9574) }, { qcom_board_id(SM8550) }, + { qcom_board_id(IPQ5016) }, { qcom_board_id(IPQ9510) }, { qcom_board_id(QRB4210) }, { qcom_board_id(QRB2210) }, @@ -461,11 +406,15 @@ static const struct soc_id soc_id[] = { { qcom_board_id(QRU1000) }, { qcom_board_id(QDU1000) }, { qcom_board_id(QDU1010) }, + { qcom_board_id(IPQ5019) }, { qcom_board_id(QRU1032) }, { qcom_board_id(QRU1052) }, { qcom_board_id(QRU1062) }, { qcom_board_id(IPQ5332) }, { qcom_board_id(IPQ5322) }, + { qcom_board_id(IPQ5312) }, + { qcom_board_id(IPQ5302) }, + { qcom_board_id(IPQ5300) }, }; static const char *socinfo_machine(struct device *dev, unsigned int id) @@ -620,6 +569,19 @@ static void socinfo_debugfs_init(struct qcom_socinfo *qcom_socinfo, &qcom_socinfo->info.fmt); switch (qcom_socinfo->info.fmt) { + case SOCINFO_VERSION(0, 19): + qcom_socinfo->info.num_func_clusters = __le32_to_cpu(info->num_func_clusters); + qcom_socinfo->info.boot_cluster = __le32_to_cpu(info->boot_cluster); + qcom_socinfo->info.boot_core = __le32_to_cpu(info->boot_core); + + debugfs_create_u32("num_func_clusters", 0444, qcom_socinfo->dbg_root, + &qcom_socinfo->info.num_func_clusters); + debugfs_create_u32("boot_cluster", 0444, qcom_socinfo->dbg_root, + &qcom_socinfo->info.boot_cluster); + debugfs_create_u32("boot_core", 0444, qcom_socinfo->dbg_root, + &qcom_socinfo->info.boot_core); + fallthrough; + case SOCINFO_VERSION(0, 18): case SOCINFO_VERSION(0, 17): qcom_socinfo->info.oem_variant = __le32_to_cpu(info->oem_variant); debugfs_create_u32("oem_variant", 0444, qcom_socinfo->dbg_root, @@ -643,17 +605,18 @@ static void socinfo_debugfs_init(struct qcom_socinfo *qcom_socinfo, case SOCINFO_VERSION(0, 14): qcom_socinfo->info.num_clusters = __le32_to_cpu(info->num_clusters); qcom_socinfo->info.ncluster_array_offset = __le32_to_cpu(info->ncluster_array_offset); - qcom_socinfo->info.num_defective_parts = __le32_to_cpu(info->num_defective_parts); - qcom_socinfo->info.ndefective_parts_array_offset = __le32_to_cpu(info->ndefective_parts_array_offset); + qcom_socinfo->info.num_subset_parts = __le32_to_cpu(info->num_subset_parts); + qcom_socinfo->info.nsubset_parts_array_offset = + __le32_to_cpu(info->nsubset_parts_array_offset); debugfs_create_u32("num_clusters", 0444, qcom_socinfo->dbg_root, &qcom_socinfo->info.num_clusters); debugfs_create_u32("ncluster_array_offset", 0444, qcom_socinfo->dbg_root, &qcom_socinfo->info.ncluster_array_offset); - debugfs_create_u32("num_defective_parts", 0444, qcom_socinfo->dbg_root, - &qcom_socinfo->info.num_defective_parts); - debugfs_create_u32("ndefective_parts_array_offset", 0444, qcom_socinfo->dbg_root, - &qcom_socinfo->info.ndefective_parts_array_offset); + debugfs_create_u32("num_subset_parts", 0444, qcom_socinfo->dbg_root, + &qcom_socinfo->info.num_subset_parts); + debugfs_create_u32("nsubset_parts_array_offset", 0444, qcom_socinfo->dbg_root, + &qcom_socinfo->info.nsubset_parts_array_offset); fallthrough; case SOCINFO_VERSION(0, 13): qcom_socinfo->info.nproduct_id = __le32_to_cpu(info->nproduct_id); diff --git a/drivers/soc/renesas/rcar-rst.c b/drivers/soc/renesas/rcar-rst.c index e1c7e91f5a86e6c6810710e9ce30d5611de97184..98fd97da6cd4330dcd1673a2f7d775937e80e174 100644 --- a/drivers/soc/renesas/rcar-rst.c +++ b/drivers/soc/renesas/rcar-rst.c @@ -12,6 +12,7 @@ #define WDTRSTCR_RESET 0xA55A0002 #define WDTRSTCR 0x0054 +#define GEN4_WDTRSTCR 0x0010 #define CR7BAR 0x0070 #define CR7BAREN BIT(4) @@ -27,6 +28,12 @@ static int rcar_rst_enable_wdt_reset(void __iomem *base) return 0; } +static int rcar_rst_v3u_enable_wdt_reset(void __iomem *base) +{ + iowrite32(WDTRSTCR_RESET, base + GEN4_WDTRSTCR); + return 0; +} + /* * Most of the R-Car Gen3 SoCs have an ARM Realtime Core. * Firmware boot address has to be set in CR7BAR before @@ -66,6 +73,12 @@ static const struct rst_config rcar_rst_gen3 __initconst = { .set_rproc_boot_addr = rcar_rst_set_gen3_rproc_boot_addr, }; +/* V3U firmware doesn't enable WDT reset and there won't be updates anymore */ +static const struct rst_config rcar_rst_v3u __initconst = { + .modemr = 0x00, /* MODEMR0 and it has CPG related bits */ + .configure = rcar_rst_v3u_enable_wdt_reset, +}; + static const struct rst_config rcar_rst_gen4 __initconst = { .modemr = 0x00, /* MODEMR0 and it has CPG related bits */ }; @@ -101,7 +114,7 @@ static const struct of_device_id rcar_rst_matches[] __initconst = { { .compatible = "renesas,r8a77990-rst", .data = &rcar_rst_gen3 }, { .compatible = "renesas,r8a77995-rst", .data = &rcar_rst_gen3 }, /* R-Car Gen4 */ - { .compatible = "renesas,r8a779a0-rst", .data = &rcar_rst_gen4 }, + { .compatible = "renesas,r8a779a0-rst", .data = &rcar_rst_v3u }, { .compatible = "renesas,r8a779f0-rst", .data = &rcar_rst_gen4 }, { .compatible = "renesas,r8a779g0-rst", .data = &rcar_rst_gen4 }, { /* sentinel */ } diff --git a/drivers/soc/renesas/rmobile-sysc.c b/drivers/soc/renesas/rmobile-sysc.c index 728ebac98e14a5cca82555c57b353783b434c370..912daadaa10d12e10e541656d71bc7cf403ced16 100644 --- a/drivers/soc/renesas/rmobile-sysc.c +++ b/drivers/soc/renesas/rmobile-sysc.c @@ -12,6 +12,8 @@ #include #include #include +#include +#include #include #include #include @@ -19,8 +21,6 @@ #include #include -#include - /* SYSC */ #define SPDCR 0x08 /* SYS Power Down Control Register */ #define SWUCR 0x14 /* SYS Wakeup Control Register */ @@ -47,6 +47,7 @@ static int rmobile_pd_power_down(struct generic_pm_domain *genpd) { struct rmobile_pm_domain *rmobile_pd = to_rmobile_pd(genpd); unsigned int mask = BIT(rmobile_pd->bit_shift); + u32 val; if (rmobile_pd->suspend) { int ret = rmobile_pd->suspend(); @@ -56,14 +57,10 @@ static int rmobile_pd_power_down(struct generic_pm_domain *genpd) } if (readl(rmobile_pd->base + PSTR) & mask) { - unsigned int retry_count; writel(mask, rmobile_pd->base + SPDCR); - for (retry_count = PSTR_RETRIES; retry_count; retry_count--) { - if (!(readl(rmobile_pd->base + SPDCR) & mask)) - break; - cpu_relax(); - } + readl_poll_timeout_atomic(rmobile_pd->base + SPDCR, val, + !(val & mask), 0, PSTR_RETRIES); } pr_debug("%s: Power off, 0x%08x -> PSTR = 0x%08x\n", genpd->name, mask, @@ -74,8 +71,7 @@ static int rmobile_pd_power_down(struct generic_pm_domain *genpd) static int __rmobile_pd_power_up(struct rmobile_pm_domain *rmobile_pd) { - unsigned int mask = BIT(rmobile_pd->bit_shift); - unsigned int retry_count; + unsigned int val, mask = BIT(rmobile_pd->bit_shift); int ret = 0; if (readl(rmobile_pd->base + PSTR) & mask) @@ -83,16 +79,9 @@ static int __rmobile_pd_power_up(struct rmobile_pm_domain *rmobile_pd) writel(mask, rmobile_pd->base + SWUCR); - for (retry_count = 2 * PSTR_RETRIES; retry_count; retry_count--) { - if (!(readl(rmobile_pd->base + SWUCR) & mask)) - break; - if (retry_count > PSTR_RETRIES) - udelay(PSTR_DELAY_US); - else - cpu_relax(); - } - if (!retry_count) - ret = -EIO; + ret = readl_poll_timeout_atomic(rmobile_pd->base + SWUCR, val, + (val & mask), PSTR_DELAY_US, + PSTR_RETRIES * PSTR_DELAY_US); pr_debug("%s: Power on, 0x%08x -> PSTR = 0x%08x\n", rmobile_pd->genpd.name, mask, diff --git a/drivers/soc/rockchip/dtpm.c b/drivers/soc/rockchip/dtpm.c index 5a23784b52215e4c850eaae7dc6122c711bbec3d..b36d4f752c302b58c6860e10e00a6d8ffbea0a95 100644 --- a/drivers/soc/rockchip/dtpm.c +++ b/drivers/soc/rockchip/dtpm.c @@ -12,33 +12,33 @@ #include static struct dtpm_node __initdata rk3399_hierarchy[] = { - [0]{ .name = "rk3399", - .type = DTPM_NODE_VIRTUAL }, - [1]{ .name = "package", - .type = DTPM_NODE_VIRTUAL, - .parent = &rk3399_hierarchy[0] }, - [2]{ .name = "/cpus/cpu@0", - .type = DTPM_NODE_DT, - .parent = &rk3399_hierarchy[1] }, - [3]{ .name = "/cpus/cpu@1", - .type = DTPM_NODE_DT, - .parent = &rk3399_hierarchy[1] }, - [4]{ .name = "/cpus/cpu@2", - .type = DTPM_NODE_DT, - .parent = &rk3399_hierarchy[1] }, - [5]{ .name = "/cpus/cpu@3", - .type = DTPM_NODE_DT, - .parent = &rk3399_hierarchy[1] }, - [6]{ .name = "/cpus/cpu@100", - .type = DTPM_NODE_DT, - .parent = &rk3399_hierarchy[1] }, - [7]{ .name = "/cpus/cpu@101", - .type = DTPM_NODE_DT, - .parent = &rk3399_hierarchy[1] }, - [8]{ .name = "/gpu@ff9a0000", - .type = DTPM_NODE_DT, - .parent = &rk3399_hierarchy[1] }, - [9]{ /* sentinel */ } + [0] = { .name = "rk3399", + .type = DTPM_NODE_VIRTUAL }, + [1] = { .name = "package", + .type = DTPM_NODE_VIRTUAL, + .parent = &rk3399_hierarchy[0] }, + [2] = { .name = "/cpus/cpu@0", + .type = DTPM_NODE_DT, + .parent = &rk3399_hierarchy[1] }, + [3] = { .name = "/cpus/cpu@1", + .type = DTPM_NODE_DT, + .parent = &rk3399_hierarchy[1] }, + [4] = { .name = "/cpus/cpu@2", + .type = DTPM_NODE_DT, + .parent = &rk3399_hierarchy[1] }, + [5] = { .name = "/cpus/cpu@3", + .type = DTPM_NODE_DT, + .parent = &rk3399_hierarchy[1] }, + [6] = { .name = "/cpus/cpu@100", + .type = DTPM_NODE_DT, + .parent = &rk3399_hierarchy[1] }, + [7] = { .name = "/cpus/cpu@101", + .type = DTPM_NODE_DT, + .parent = &rk3399_hierarchy[1] }, + [8] = { .name = "/gpu@ff9a0000", + .type = DTPM_NODE_DT, + .parent = &rk3399_hierarchy[1] }, + [9] = { /* sentinel */ } }; static struct of_device_id __initdata rockchip_dtpm_match_table[] = { diff --git a/drivers/soc/rockchip/pm_domains.c b/drivers/soc/rockchip/pm_domains.c index 84bc022f9e5b71bbb19b2d6129bfac7909d71d4d..e3de49e671dc05d77521a72c473091888c7247f9 100644 --- a/drivers/soc/rockchip/pm_domains.c +++ b/drivers/soc/rockchip/pm_domains.c @@ -43,8 +43,10 @@ struct rockchip_domain_info { bool active_wakeup; int pwr_w_mask; int req_w_mask; + int mem_status_mask; int repair_status_mask; u32 pwr_offset; + u32 mem_offset; u32 req_offset; }; @@ -54,6 +56,9 @@ struct rockchip_pmu_info { u32 req_offset; u32 idle_offset; u32 ack_offset; + u32 mem_pwr_offset; + u32 chain_status_offset; + u32 mem_status_offset; u32 repair_status_offset; u32 core_pwrcnt_offset; @@ -119,13 +124,15 @@ struct rockchip_pmu { .active_wakeup = wakeup, \ } -#define DOMAIN_M_O_R(_name, p_offset, pwr, status, r_status, r_offset, req, idle, ack, wakeup) \ +#define DOMAIN_M_O_R(_name, p_offset, pwr, status, m_offset, m_status, r_status, r_offset, req, idle, ack, wakeup) \ { \ .name = _name, \ .pwr_offset = p_offset, \ .pwr_w_mask = (pwr) << 16, \ .pwr_mask = (pwr), \ .status_mask = (status), \ + .mem_offset = m_offset, \ + .mem_status_mask = (m_status), \ .repair_status_mask = (r_status), \ .req_offset = r_offset, \ .req_w_mask = (req) << 16, \ @@ -269,8 +276,8 @@ void rockchip_pmu_unblock(void) } EXPORT_SYMBOL_GPL(rockchip_pmu_unblock); -#define DOMAIN_RK3588(name, p_offset, pwr, status, r_status, r_offset, req, idle, wakeup) \ - DOMAIN_M_O_R(name, p_offset, pwr, status, r_status, r_offset, req, idle, idle, wakeup) +#define DOMAIN_RK3588(name, p_offset, pwr, status, m_offset, m_status, r_status, r_offset, req, idle, wakeup) \ + DOMAIN_M_O_R(name, p_offset, pwr, status, m_offset, m_status, r_status, r_offset, req, idle, idle, wakeup) static bool rockchip_pmu_domain_is_idle(struct rockchip_pm_domain *pd) { @@ -408,17 +415,92 @@ static bool rockchip_pmu_domain_is_on(struct rockchip_pm_domain *pd) return !(val & pd->info->status_mask); } +static bool rockchip_pmu_domain_is_mem_on(struct rockchip_pm_domain *pd) +{ + struct rockchip_pmu *pmu = pd->pmu; + unsigned int val; + + regmap_read(pmu->regmap, + pmu->info->mem_status_offset + pd->info->mem_offset, &val); + + /* 1'b0: power on, 1'b1: power off */ + return !(val & pd->info->mem_status_mask); +} + +static bool rockchip_pmu_domain_is_chain_on(struct rockchip_pm_domain *pd) +{ + struct rockchip_pmu *pmu = pd->pmu; + unsigned int val; + + regmap_read(pmu->regmap, + pmu->info->chain_status_offset + pd->info->mem_offset, &val); + + /* 1'b1: power on, 1'b0: power off */ + return val & pd->info->mem_status_mask; +} + +static int rockchip_pmu_domain_mem_reset(struct rockchip_pm_domain *pd) +{ + struct rockchip_pmu *pmu = pd->pmu; + struct generic_pm_domain *genpd = &pd->genpd; + bool is_on; + int ret = 0; + + ret = readx_poll_timeout_atomic(rockchip_pmu_domain_is_chain_on, pd, is_on, + is_on == true, 0, 10000); + if (ret) { + dev_err(pmu->dev, + "failed to get chain status '%s', target_on=1, val=%d\n", + genpd->name, is_on); + goto error; + } + + udelay(20); + + regmap_write(pmu->regmap, pmu->info->mem_pwr_offset + pd->info->pwr_offset, + (pd->info->pwr_mask | pd->info->pwr_w_mask)); + wmb(); + + ret = readx_poll_timeout_atomic(rockchip_pmu_domain_is_mem_on, pd, is_on, + is_on == false, 0, 10000); + if (ret) { + dev_err(pmu->dev, + "failed to get mem status '%s', target_on=0, val=%d\n", + genpd->name, is_on); + goto error; + } + + regmap_write(pmu->regmap, pmu->info->mem_pwr_offset + pd->info->pwr_offset, + pd->info->pwr_w_mask); + wmb(); + + ret = readx_poll_timeout_atomic(rockchip_pmu_domain_is_mem_on, pd, is_on, + is_on == true, 0, 10000); + if (ret) { + dev_err(pmu->dev, + "failed to get mem status '%s', target_on=1, val=%d\n", + genpd->name, is_on); + } + +error: + return ret; +} + static void rockchip_do_pmu_set_power_domain(struct rockchip_pm_domain *pd, bool on) { struct rockchip_pmu *pmu = pd->pmu; struct generic_pm_domain *genpd = &pd->genpd; u32 pd_pwr_offset = pd->info->pwr_offset; - bool is_on; + bool is_on, is_mem_on = false; if (pd->info->pwr_mask == 0) return; - else if (pd->info->pwr_w_mask) + + if (on && pd->info->mem_status_mask) + is_mem_on = rockchip_pmu_domain_is_mem_on(pd); + + if (pd->info->pwr_w_mask) regmap_write(pmu->regmap, pmu->info->pwr_offset + pd_pwr_offset, on ? pd->info->pwr_w_mask : (pd->info->pwr_mask | pd->info->pwr_w_mask)); @@ -428,6 +510,9 @@ static void rockchip_do_pmu_set_power_domain(struct rockchip_pm_domain *pd, wmb(); + if (is_mem_on && rockchip_pmu_domain_mem_reset(pd)) + return; + if (readx_poll_timeout_atomic(rockchip_pmu_domain_is_on, pd, is_on, is_on == on, 0, 10000)) { dev_err(pmu->dev, @@ -645,7 +730,9 @@ static int rockchip_pm_add_one_domain(struct rockchip_pmu *pmu, pd->genpd.flags = GENPD_FLAG_PM_CLK; if (pd_info->active_wakeup) pd->genpd.flags |= GENPD_FLAG_ACTIVE_WAKEUP; - pm_genpd_init(&pd->genpd, NULL, !rockchip_pmu_domain_is_on(pd)); + pm_genpd_init(&pd->genpd, NULL, + !rockchip_pmu_domain_is_on(pd) || + (pd->info->mem_status_mask && !rockchip_pmu_domain_is_mem_on(pd))); pmu->genpd_data.domains[id] = &pd->genpd; return 0; @@ -1024,35 +1111,35 @@ static const struct rockchip_domain_info rk3568_pm_domains[] = { }; static const struct rockchip_domain_info rk3588_pm_domains[] = { - [RK3588_PD_GPU] = DOMAIN_RK3588("gpu", 0x0, BIT(0), 0, BIT(1), 0x0, BIT(0), BIT(0), false), - [RK3588_PD_NPU] = DOMAIN_RK3588("npu", 0x0, BIT(1), BIT(1), 0, 0x0, 0, 0, false), - [RK3588_PD_VCODEC] = DOMAIN_RK3588("vcodec", 0x0, BIT(2), BIT(2), 0, 0x0, 0, 0, false), - [RK3588_PD_NPUTOP] = DOMAIN_RK3588("nputop", 0x0, BIT(3), 0, BIT(2), 0x0, BIT(1), BIT(1), false), - [RK3588_PD_NPU1] = DOMAIN_RK3588("npu1", 0x0, BIT(4), 0, BIT(3), 0x0, BIT(2), BIT(2), false), - [RK3588_PD_NPU2] = DOMAIN_RK3588("npu2", 0x0, BIT(5), 0, BIT(4), 0x0, BIT(3), BIT(3), false), - [RK3588_PD_VENC0] = DOMAIN_RK3588("venc0", 0x0, BIT(6), 0, BIT(5), 0x0, BIT(4), BIT(4), false), - [RK3588_PD_VENC1] = DOMAIN_RK3588("venc1", 0x0, BIT(7), 0, BIT(6), 0x0, BIT(5), BIT(5), false), - [RK3588_PD_RKVDEC0] = DOMAIN_RK3588("rkvdec0", 0x0, BIT(8), 0, BIT(7), 0x0, BIT(6), BIT(6), false), - [RK3588_PD_RKVDEC1] = DOMAIN_RK3588("rkvdec1", 0x0, BIT(9), 0, BIT(8), 0x0, BIT(7), BIT(7), false), - [RK3588_PD_VDPU] = DOMAIN_RK3588("vdpu", 0x0, BIT(10), 0, BIT(9), 0x0, BIT(8), BIT(8), false), - [RK3588_PD_RGA30] = DOMAIN_RK3588("rga30", 0x0, BIT(11), 0, BIT(10), 0x0, 0, 0, false), - [RK3588_PD_AV1] = DOMAIN_RK3588("av1", 0x0, BIT(12), 0, BIT(11), 0x0, BIT(9), BIT(9), false), - [RK3588_PD_VI] = DOMAIN_RK3588("vi", 0x0, BIT(13), 0, BIT(12), 0x0, BIT(10), BIT(10), false), - [RK3588_PD_FEC] = DOMAIN_RK3588("fec", 0x0, BIT(14), 0, BIT(13), 0x0, 0, 0, false), - [RK3588_PD_ISP1] = DOMAIN_RK3588("isp1", 0x0, BIT(15), 0, BIT(14), 0x0, BIT(11), BIT(11), false), - [RK3588_PD_RGA31] = DOMAIN_RK3588("rga31", 0x4, BIT(0), 0, BIT(15), 0x0, BIT(12), BIT(12), false), - [RK3588_PD_VOP] = DOMAIN_RK3588("vop", 0x4, BIT(1), 0, BIT(16), 0x0, BIT(13) | BIT(14), BIT(13) | BIT(14), false), - [RK3588_PD_VO0] = DOMAIN_RK3588("vo0", 0x4, BIT(2), 0, BIT(17), 0x0, BIT(15), BIT(15), false), - [RK3588_PD_VO1] = DOMAIN_RK3588("vo1", 0x4, BIT(3), 0, BIT(18), 0x4, BIT(0), BIT(16), false), - [RK3588_PD_AUDIO] = DOMAIN_RK3588("audio", 0x4, BIT(4), 0, BIT(19), 0x4, BIT(1), BIT(17), false), - [RK3588_PD_PHP] = DOMAIN_RK3588("php", 0x4, BIT(5), 0, BIT(20), 0x4, BIT(5), BIT(21), false), - [RK3588_PD_GMAC] = DOMAIN_RK3588("gmac", 0x4, BIT(6), 0, BIT(21), 0x0, 0, 0, false), - [RK3588_PD_PCIE] = DOMAIN_RK3588("pcie", 0x4, BIT(7), 0, BIT(22), 0x0, 0, 0, true), - [RK3588_PD_NVM] = DOMAIN_RK3588("nvm", 0x4, BIT(8), BIT(24), 0, 0x4, BIT(2), BIT(18), false), - [RK3588_PD_NVM0] = DOMAIN_RK3588("nvm0", 0x4, BIT(9), 0, BIT(23), 0x0, 0, 0, false), - [RK3588_PD_SDIO] = DOMAIN_RK3588("sdio", 0x4, BIT(10), 0, BIT(24), 0x4, BIT(3), BIT(19), false), - [RK3588_PD_USB] = DOMAIN_RK3588("usb", 0x4, BIT(11), 0, BIT(25), 0x4, BIT(4), BIT(20), true), - [RK3588_PD_SDMMC] = DOMAIN_RK3588("sdmmc", 0x4, BIT(13), 0, BIT(26), 0x0, 0, 0, false), + [RK3588_PD_GPU] = DOMAIN_RK3588("gpu", 0x0, BIT(0), 0, 0x0, 0, BIT(1), 0x0, BIT(0), BIT(0), false), + [RK3588_PD_NPU] = DOMAIN_RK3588("npu", 0x0, BIT(1), BIT(1), 0x0, 0, 0, 0x0, 0, 0, false), + [RK3588_PD_VCODEC] = DOMAIN_RK3588("vcodec", 0x0, BIT(2), BIT(2), 0x0, 0, 0, 0x0, 0, 0, false), + [RK3588_PD_NPUTOP] = DOMAIN_RK3588("nputop", 0x0, BIT(3), 0, 0x0, BIT(11), BIT(2), 0x0, BIT(1), BIT(1), false), + [RK3588_PD_NPU1] = DOMAIN_RK3588("npu1", 0x0, BIT(4), 0, 0x0, BIT(12), BIT(3), 0x0, BIT(2), BIT(2), false), + [RK3588_PD_NPU2] = DOMAIN_RK3588("npu2", 0x0, BIT(5), 0, 0x0, BIT(13), BIT(4), 0x0, BIT(3), BIT(3), false), + [RK3588_PD_VENC0] = DOMAIN_RK3588("venc0", 0x0, BIT(6), 0, 0x0, BIT(14), BIT(5), 0x0, BIT(4), BIT(4), false), + [RK3588_PD_VENC1] = DOMAIN_RK3588("venc1", 0x0, BIT(7), 0, 0x0, BIT(15), BIT(6), 0x0, BIT(5), BIT(5), false), + [RK3588_PD_RKVDEC0] = DOMAIN_RK3588("rkvdec0", 0x0, BIT(8), 0, 0x0, BIT(16), BIT(7), 0x0, BIT(6), BIT(6), false), + [RK3588_PD_RKVDEC1] = DOMAIN_RK3588("rkvdec1", 0x0, BIT(9), 0, 0x0, BIT(17), BIT(8), 0x0, BIT(7), BIT(7), false), + [RK3588_PD_VDPU] = DOMAIN_RK3588("vdpu", 0x0, BIT(10), 0, 0x0, BIT(18), BIT(9), 0x0, BIT(8), BIT(8), false), + [RK3588_PD_RGA30] = DOMAIN_RK3588("rga30", 0x0, BIT(11), 0, 0x0, BIT(19), BIT(10), 0x0, 0, 0, false), + [RK3588_PD_AV1] = DOMAIN_RK3588("av1", 0x0, BIT(12), 0, 0x0, BIT(20), BIT(11), 0x0, BIT(9), BIT(9), false), + [RK3588_PD_VI] = DOMAIN_RK3588("vi", 0x0, BIT(13), 0, 0x0, BIT(21), BIT(12), 0x0, BIT(10), BIT(10), false), + [RK3588_PD_FEC] = DOMAIN_RK3588("fec", 0x0, BIT(14), 0, 0x0, BIT(22), BIT(13), 0x0, 0, 0, false), + [RK3588_PD_ISP1] = DOMAIN_RK3588("isp1", 0x0, BIT(15), 0, 0x0, BIT(23), BIT(14), 0x0, BIT(11), BIT(11), false), + [RK3588_PD_RGA31] = DOMAIN_RK3588("rga31", 0x4, BIT(0), 0, 0x0, BIT(24), BIT(15), 0x0, BIT(12), BIT(12), false), + [RK3588_PD_VOP] = DOMAIN_RK3588("vop", 0x4, BIT(1), 0, 0x0, BIT(25), BIT(16), 0x0, BIT(13) | BIT(14), BIT(13) | BIT(14), false), + [RK3588_PD_VO0] = DOMAIN_RK3588("vo0", 0x4, BIT(2), 0, 0x0, BIT(26), BIT(17), 0x0, BIT(15), BIT(15), false), + [RK3588_PD_VO1] = DOMAIN_RK3588("vo1", 0x4, BIT(3), 0, 0x0, BIT(27), BIT(18), 0x4, BIT(0), BIT(16), false), + [RK3588_PD_AUDIO] = DOMAIN_RK3588("audio", 0x4, BIT(4), 0, 0x0, BIT(28), BIT(19), 0x4, BIT(1), BIT(17), false), + [RK3588_PD_PHP] = DOMAIN_RK3588("php", 0x4, BIT(5), 0, 0x0, BIT(29), BIT(20), 0x4, BIT(5), BIT(21), false), + [RK3588_PD_GMAC] = DOMAIN_RK3588("gmac", 0x4, BIT(6), 0, 0x0, BIT(30), BIT(21), 0x0, 0, 0, false), + [RK3588_PD_PCIE] = DOMAIN_RK3588("pcie", 0x4, BIT(7), 0, 0x0, BIT(31), BIT(22), 0x0, 0, 0, true), + [RK3588_PD_NVM] = DOMAIN_RK3588("nvm", 0x4, BIT(8), BIT(24), 0x4, 0, 0, 0x4, BIT(2), BIT(18), false), + [RK3588_PD_NVM0] = DOMAIN_RK3588("nvm0", 0x4, BIT(9), 0, 0x4, BIT(1), BIT(23), 0x0, 0, 0, false), + [RK3588_PD_SDIO] = DOMAIN_RK3588("sdio", 0x4, BIT(10), 0, 0x4, BIT(2), BIT(24), 0x4, BIT(3), BIT(19), false), + [RK3588_PD_USB] = DOMAIN_RK3588("usb", 0x4, BIT(11), 0, 0x4, BIT(3), BIT(25), 0x4, BIT(4), BIT(20), true), + [RK3588_PD_SDMMC] = DOMAIN_RK3588("sdmmc", 0x4, BIT(13), 0, 0x4, BIT(5), BIT(26), 0x0, 0, 0, false), }; static const struct rockchip_pmu_info px30_pmu = { @@ -1207,6 +1294,9 @@ static const struct rockchip_pmu_info rk3588_pmu = { .req_offset = 0x10c, .idle_offset = 0x120, .ack_offset = 0x118, + .mem_pwr_offset = 0x1a0, + .chain_status_offset = 0x1f0, + .mem_status_offset = 0x1f8, .repair_status_offset = 0x290, .num_domains = ARRAY_SIZE(rk3588_pm_domains), diff --git a/drivers/soc/samsung/exynos-pmu.c b/drivers/soc/samsung/exynos-pmu.c index 732c86ce2be8a2916039acdf48e385169c63e25c..5b2664da9853a4dd973ca161b74738fa8ca269c5 100644 --- a/drivers/soc/samsung/exynos-pmu.c +++ b/drivers/soc/samsung/exynos-pmu.c @@ -57,6 +57,12 @@ void exynos_sys_powerdown_conf(enum sys_powerdown mode) if (pmu_data->powerdown_conf_extra) pmu_data->powerdown_conf_extra(mode); + + if (pmu_data->pmu_config_extra) { + for (i = 0; pmu_data->pmu_config_extra[i].offset != PMU_TABLE_END; i++) + pmu_raw_writel(pmu_data->pmu_config_extra[i].val[mode], + pmu_data->pmu_config_extra[i].offset); + } } /* @@ -79,6 +85,9 @@ static const struct of_device_id exynos_pmu_of_device_ids[] = { }, { .compatible = "samsung,exynos4210-pmu", .data = exynos_pmu_data_arm_ptr(exynos4210_pmu_data), + }, { + .compatible = "samsung,exynos4212-pmu", + .data = exynos_pmu_data_arm_ptr(exynos4212_pmu_data), }, { .compatible = "samsung,exynos4412-pmu", .data = exynos_pmu_data_arm_ptr(exynos4412_pmu_data), diff --git a/drivers/soc/samsung/exynos-pmu.h b/drivers/soc/samsung/exynos-pmu.h index 5e851f32307e6c495d4c488db322e404cde3a1c2..1c652ffd79b415520a793d57a2813c6300a8dc4f 100644 --- a/drivers/soc/samsung/exynos-pmu.h +++ b/drivers/soc/samsung/exynos-pmu.h @@ -20,6 +20,7 @@ struct exynos_pmu_conf { struct exynos_pmu_data { const struct exynos_pmu_conf *pmu_config; + const struct exynos_pmu_conf *pmu_config_extra; void (*pmu_init)(void); void (*powerdown_conf)(enum sys_powerdown); @@ -32,6 +33,7 @@ extern void __iomem *pmu_base_addr; /* list of all exported SoC specific data */ extern const struct exynos_pmu_data exynos3250_pmu_data; extern const struct exynos_pmu_data exynos4210_pmu_data; +extern const struct exynos_pmu_data exynos4212_pmu_data; extern const struct exynos_pmu_data exynos4412_pmu_data; extern const struct exynos_pmu_data exynos5250_pmu_data; extern const struct exynos_pmu_data exynos5420_pmu_data; diff --git a/drivers/soc/samsung/exynos4-pmu.c b/drivers/soc/samsung/exynos4-pmu.c index cb35103565a6db7bff9ab011e7d339b55c164489..f8092190b9380df6aa155115c9c591e79d909a4f 100644 --- a/drivers/soc/samsung/exynos4-pmu.c +++ b/drivers/soc/samsung/exynos4-pmu.c @@ -86,7 +86,7 @@ static const struct exynos_pmu_conf exynos4210_pmu_config[] = { { PMU_TABLE_END,}, }; -static const struct exynos_pmu_conf exynos4412_pmu_config[] = { +static const struct exynos_pmu_conf exynos4x12_pmu_config[] = { { S5P_ARM_CORE0_LOWPWR, { 0x0, 0x0, 0x2 } }, { S5P_DIS_IRQ_CORE0, { 0x0, 0x0, 0x0 } }, { S5P_DIS_IRQ_CENTRAL0, { 0x0, 0x0, 0x0 } }, @@ -191,6 +191,10 @@ static const struct exynos_pmu_conf exynos4412_pmu_config[] = { { S5P_GPS_ALIVE_LOWPWR, { 0x7, 0x0, 0x0 } }, { S5P_CMU_SYSCLK_ISP_LOWPWR, { 0x1, 0x0, 0x0 } }, { S5P_CMU_SYSCLK_GPS_LOWPWR, { 0x1, 0x0, 0x0 } }, + { PMU_TABLE_END,}, +}; + +static const struct exynos_pmu_conf exynos4412_pmu_config[] = { { S5P_ARM_CORE2_LOWPWR, { 0x0, 0x0, 0x2 } }, { S5P_DIS_IRQ_CORE2, { 0x0, 0x0, 0x0 } }, { S5P_DIS_IRQ_CENTRAL2, { 0x0, 0x0, 0x0 } }, @@ -204,6 +208,11 @@ const struct exynos_pmu_data exynos4210_pmu_data = { .pmu_config = exynos4210_pmu_config, }; +const struct exynos_pmu_data exynos4212_pmu_data = { + .pmu_config = exynos4x12_pmu_config, +}; + const struct exynos_pmu_data exynos4412_pmu_data = { - .pmu_config = exynos4412_pmu_config, + .pmu_config = exynos4x12_pmu_config, + .pmu_config_extra = exynos4412_pmu_config, }; diff --git a/drivers/soc/tegra/Kconfig b/drivers/soc/tegra/Kconfig index 3658fb0f0c5b1e50a657b2413684b5fb20ddef88..6f30988229692ccb12e60233ef9dbe8f9c36c1f8 100644 --- a/drivers/soc/tegra/Kconfig +++ b/drivers/soc/tegra/Kconfig @@ -125,6 +125,7 @@ config ARCH_TEGRA_234_SOC bool "NVIDIA Tegra234 SoC" depends on !CPU_BIG_ENDIAN select MAILBOX + select PINCTRL_TEGRA234 select TEGRA_BPMP select TEGRA_HSP_MBOX select TEGRA_IVC diff --git a/drivers/soc/tegra/fuse/fuse-tegra30.c b/drivers/soc/tegra/fuse/fuse-tegra30.c index 932a03c64534aef8e8bc4edf9f8fe3350e085566..c759fb7c8adc0e0f551d06e7446e3be61651241c 100644 --- a/drivers/soc/tegra/fuse/fuse-tegra30.c +++ b/drivers/soc/tegra/fuse/fuse-tegra30.c @@ -663,7 +663,7 @@ static const struct nvmem_keepout tegra234_fuse_keepouts[] = { static const struct tegra_fuse_info tegra234_fuse_info = { .read = tegra30_fuse_read, - .size = 0x98c, + .size = 0xf90, .spare = 0x280, }; diff --git a/drivers/soc/tegra/fuse/tegra-apbmisc.c b/drivers/soc/tegra/fuse/tegra-apbmisc.c index 4591c5bcb690b030223c691c026ac88f7e38b4af..eb0a1d92452688c7d8ac7bad09e656a019738963 100644 --- a/drivers/soc/tegra/fuse/tegra-apbmisc.c +++ b/drivers/soc/tegra/fuse/tegra-apbmisc.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2014-2023, NVIDIA CORPORATION. All rights reserved. */ #include @@ -62,6 +62,7 @@ bool tegra_is_silicon(void) switch (tegra_get_chip_id()) { case TEGRA194: case TEGRA234: + case TEGRA264: if (tegra_get_platform() == 0) return true; diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c index 5d17799524c901ca74ce27828e29c46ce01ac5b7..162f52456f654e3f3d06ebc0fcc77a43f701ce76 100644 --- a/drivers/soc/tegra/pmc.c +++ b/drivers/soc/tegra/pmc.c @@ -396,7 +396,6 @@ struct tegra_pmc_soc { * @clk: pointer to pclk clock * @soc: pointer to SoC data structure * @tz_only: flag specifying if the PMC can only be accessed via TrustZone - * @debugfs: pointer to debugfs entry * @rate: currently configured rate of pclk * @suspend_mode: lowest suspend mode available * @cpu_good_time: CPU power good time (in microseconds) @@ -431,7 +430,6 @@ struct tegra_pmc { void __iomem *aotag; void __iomem *scratch; struct clk *clk; - struct dentry *debugfs; const struct tegra_pmc_soc *soc; bool tz_only; @@ -1190,16 +1188,6 @@ static int powergate_show(struct seq_file *s, void *data) DEFINE_SHOW_ATTRIBUTE(powergate); -static int tegra_powergate_debugfs_init(void) -{ - pmc->debugfs = debugfs_create_file("powergate", S_IRUGO, NULL, NULL, - &powergate_fops); - if (!pmc->debugfs) - return -ENOMEM; - - return 0; -} - static int tegra_powergate_of_get_clks(struct tegra_powergate *pg, struct device_node *np) { @@ -3004,7 +2992,8 @@ static int tegra_pmc_probe(struct platform_device *pdev) */ if (pmc->clk) { pmc->clk_nb.notifier_call = tegra_pmc_clk_notify_cb; - err = clk_notifier_register(pmc->clk, &pmc->clk_nb); + err = devm_clk_notifier_register(&pdev->dev, pmc->clk, + &pmc->clk_nb); if (err) { dev_err(&pdev->dev, "failed to register clk notifier\n"); @@ -3026,19 +3015,13 @@ static int tegra_pmc_probe(struct platform_device *pdev) tegra_pmc_reset_sysfs_init(pmc); - if (IS_ENABLED(CONFIG_DEBUG_FS)) { - err = tegra_powergate_debugfs_init(); - if (err < 0) - goto cleanup_sysfs; - } - err = tegra_pmc_pinctrl_init(pmc); if (err) - goto cleanup_debugfs; + goto cleanup_sysfs; err = tegra_pmc_regmap_init(pmc); if (err < 0) - goto cleanup_debugfs; + goto cleanup_sysfs; err = tegra_powergate_init(pmc, pdev->dev.of_node); if (err < 0) @@ -3061,16 +3044,15 @@ static int tegra_pmc_probe(struct platform_device *pdev) if (pmc->soc->set_wake_filters) pmc->soc->set_wake_filters(pmc); + debugfs_create_file("powergate", 0444, NULL, NULL, &powergate_fops); + return 0; cleanup_powergates: tegra_powergate_remove_all(pdev->dev.of_node); -cleanup_debugfs: - debugfs_remove(pmc->debugfs); cleanup_sysfs: device_remove_file(&pdev->dev, &dev_attr_reset_reason); device_remove_file(&pdev->dev, &dev_attr_reset_level); - clk_notifier_unregister(pmc->clk, &pmc->clk_nb); return err; } @@ -4250,6 +4232,7 @@ static const struct tegra_wake_event tegra234_wake_events[] = { TEGRA_WAKE_GPIO("power", 29, 1, TEGRA234_AON_GPIO(EE, 4)), TEGRA_WAKE_GPIO("mgbe", 56, 0, TEGRA234_MAIN_GPIO(Y, 3)), TEGRA_WAKE_IRQ("rtc", 73, 10), + TEGRA_WAKE_IRQ("sw-wake", SW_WAKE_ID, 179), }; static const struct tegra_pmc_soc tegra234_pmc_soc = { diff --git a/drivers/soc/ti/Kconfig b/drivers/soc/ti/Kconfig index 8c2a1036bef51e300f5de0cde2afb208e96f8045..2cae17b65fd9306a48bccbaa147aaecbfdcbcd6b 100644 --- a/drivers/soc/ti/Kconfig +++ b/drivers/soc/ti/Kconfig @@ -85,7 +85,7 @@ config TI_K3_SOCINFO config TI_PRUSS tristate "TI PRU-ICSS Subsystem Platform drivers" - depends on SOC_AM33XX || SOC_AM43XX || SOC_DRA7XX || ARCH_KEYSTONE || ARCH_K3 + depends on SOC_AM33XX || SOC_AM43XX || SOC_DRA7XX || ARCH_KEYSTONE || ARCH_K3 || COMPILE_TEST select MFD_SYSCON help TI PRU-ICSS Subsystem platform specific support. diff --git a/drivers/soc/ti/pruss.c b/drivers/soc/ti/pruss.c index 6882c86b3ce541d6039ce213ada5edf0ea3be6d6..7fdefee1ed87b37d7643a7a3dbf2ae26576c4f36 100644 --- a/drivers/soc/ti/pruss.c +++ b/drivers/soc/ti/pruss.c @@ -6,6 +6,7 @@ * Author(s): * Suman Anna * Andrew F. Davis + * Tero Kristo */ #include @@ -18,7 +19,9 @@ #include #include #include +#include #include +#include "pruss.h" /** * struct pruss_private_data - PRUSS driver private data @@ -30,6 +33,257 @@ struct pruss_private_data { bool has_core_mux_clock; }; +/** + * pruss_get() - get the pruss for a given PRU remoteproc + * @rproc: remoteproc handle of a PRU instance + * + * Finds the parent pruss device for a PRU given the @rproc handle of the + * PRU remote processor. This function increments the pruss device's refcount, + * so always use pruss_put() to decrement it back once pruss isn't needed + * anymore. + * + * This API doesn't check if @rproc is valid or not. It is expected the caller + * will have done a pru_rproc_get() on @rproc, before calling this API to make + * sure that @rproc is valid. + * + * Return: pruss handle on success, and an ERR_PTR on failure using one + * of the following error values + * -EINVAL if invalid parameter + * -ENODEV if PRU device or PRUSS device is not found + */ +struct pruss *pruss_get(struct rproc *rproc) +{ + struct pruss *pruss; + struct device *dev; + struct platform_device *ppdev; + + if (IS_ERR_OR_NULL(rproc)) + return ERR_PTR(-EINVAL); + + dev = &rproc->dev; + + /* make sure it is PRU rproc */ + if (!dev->parent || !is_pru_rproc(dev->parent)) + return ERR_PTR(-ENODEV); + + ppdev = to_platform_device(dev->parent->parent); + pruss = platform_get_drvdata(ppdev); + if (!pruss) + return ERR_PTR(-ENODEV); + + get_device(pruss->dev); + + return pruss; +} +EXPORT_SYMBOL_GPL(pruss_get); + +/** + * pruss_put() - decrement pruss device's usecount + * @pruss: pruss handle + * + * Complimentary function for pruss_get(). Needs to be called + * after the PRUSS is used, and only if the pruss_get() succeeds. + */ +void pruss_put(struct pruss *pruss) +{ + if (IS_ERR_OR_NULL(pruss)) + return; + + put_device(pruss->dev); +} +EXPORT_SYMBOL_GPL(pruss_put); + +/** + * pruss_request_mem_region() - request a memory resource + * @pruss: the pruss instance + * @mem_id: the memory resource id + * @region: pointer to memory region structure to be filled in + * + * This function allows a client driver to request a memory resource, + * and if successful, will let the client driver own the particular + * memory region until released using the pruss_release_mem_region() + * API. + * + * Return: 0 if requested memory region is available (in such case pointer to + * memory region is returned via @region), an error otherwise + */ +int pruss_request_mem_region(struct pruss *pruss, enum pruss_mem mem_id, + struct pruss_mem_region *region) +{ + if (!pruss || !region || mem_id >= PRUSS_MEM_MAX) + return -EINVAL; + + mutex_lock(&pruss->lock); + + if (pruss->mem_in_use[mem_id]) { + mutex_unlock(&pruss->lock); + return -EBUSY; + } + + *region = pruss->mem_regions[mem_id]; + pruss->mem_in_use[mem_id] = region; + + mutex_unlock(&pruss->lock); + + return 0; +} +EXPORT_SYMBOL_GPL(pruss_request_mem_region); + +/** + * pruss_release_mem_region() - release a memory resource + * @pruss: the pruss instance + * @region: the memory region to release + * + * This function is the complimentary function to + * pruss_request_mem_region(), and allows the client drivers to + * release back a memory resource. + * + * Return: 0 on success, an error code otherwise + */ +int pruss_release_mem_region(struct pruss *pruss, + struct pruss_mem_region *region) +{ + int id; + + if (!pruss || !region) + return -EINVAL; + + mutex_lock(&pruss->lock); + + /* find out the memory region being released */ + for (id = 0; id < PRUSS_MEM_MAX; id++) { + if (pruss->mem_in_use[id] == region) + break; + } + + if (id == PRUSS_MEM_MAX) { + mutex_unlock(&pruss->lock); + return -EINVAL; + } + + pruss->mem_in_use[id] = NULL; + + mutex_unlock(&pruss->lock); + + return 0; +} +EXPORT_SYMBOL_GPL(pruss_release_mem_region); + +/** + * pruss_cfg_get_gpmux() - get the current GPMUX value for a PRU device + * @pruss: pruss instance + * @pru_id: PRU identifier (0-1) + * @mux: pointer to store the current mux value into + * + * Return: 0 on success, or an error code otherwise + */ +int pruss_cfg_get_gpmux(struct pruss *pruss, enum pruss_pru_id pru_id, u8 *mux) +{ + int ret; + u32 val; + + if (pru_id >= PRUSS_NUM_PRUS || !mux) + return -EINVAL; + + ret = pruss_cfg_read(pruss, PRUSS_CFG_GPCFG(pru_id), &val); + if (!ret) + *mux = (u8)((val & PRUSS_GPCFG_PRU_MUX_SEL_MASK) >> + PRUSS_GPCFG_PRU_MUX_SEL_SHIFT); + return ret; +} +EXPORT_SYMBOL_GPL(pruss_cfg_get_gpmux); + +/** + * pruss_cfg_set_gpmux() - set the GPMUX value for a PRU device + * @pruss: pruss instance + * @pru_id: PRU identifier (0-1) + * @mux: new mux value for PRU + * + * Return: 0 on success, or an error code otherwise + */ +int pruss_cfg_set_gpmux(struct pruss *pruss, enum pruss_pru_id pru_id, u8 mux) +{ + if (mux >= PRUSS_GP_MUX_SEL_MAX || + pru_id >= PRUSS_NUM_PRUS) + return -EINVAL; + + return pruss_cfg_update(pruss, PRUSS_CFG_GPCFG(pru_id), + PRUSS_GPCFG_PRU_MUX_SEL_MASK, + (u32)mux << PRUSS_GPCFG_PRU_MUX_SEL_SHIFT); +} +EXPORT_SYMBOL_GPL(pruss_cfg_set_gpmux); + +/** + * pruss_cfg_gpimode() - set the GPI mode of the PRU + * @pruss: the pruss instance handle + * @pru_id: id of the PRU core within the PRUSS + * @mode: GPI mode to set + * + * Sets the GPI mode for a given PRU by programming the + * corresponding PRUSS_CFG_GPCFGx register + * + * Return: 0 on success, or an error code otherwise + */ +int pruss_cfg_gpimode(struct pruss *pruss, enum pruss_pru_id pru_id, + enum pruss_gpi_mode mode) +{ + if (pru_id >= PRUSS_NUM_PRUS || mode >= PRUSS_GPI_MODE_MAX) + return -EINVAL; + + return pruss_cfg_update(pruss, PRUSS_CFG_GPCFG(pru_id), + PRUSS_GPCFG_PRU_GPI_MODE_MASK, + mode << PRUSS_GPCFG_PRU_GPI_MODE_SHIFT); +} +EXPORT_SYMBOL_GPL(pruss_cfg_gpimode); + +/** + * pruss_cfg_miirt_enable() - Enable/disable MII RT Events + * @pruss: the pruss instance + * @enable: enable/disable + * + * Enable/disable the MII RT Events for the PRUSS. + * + * Return: 0 on success, or an error code otherwise + */ +int pruss_cfg_miirt_enable(struct pruss *pruss, bool enable) +{ + u32 set = enable ? PRUSS_MII_RT_EVENT_EN : 0; + + return pruss_cfg_update(pruss, PRUSS_CFG_MII_RT, + PRUSS_MII_RT_EVENT_EN, set); +} +EXPORT_SYMBOL_GPL(pruss_cfg_miirt_enable); + +/** + * pruss_cfg_xfr_enable() - Enable/disable XIN XOUT shift functionality + * @pruss: the pruss instance + * @pru_type: PRU core type identifier + * @enable: enable/disable + * + * Return: 0 on success, or an error code otherwise + */ +int pruss_cfg_xfr_enable(struct pruss *pruss, enum pru_type pru_type, + bool enable) +{ + u32 mask, set; + + switch (pru_type) { + case PRU_TYPE_PRU: + mask = PRUSS_SPP_XFER_SHIFT_EN; + break; + case PRU_TYPE_RTU: + mask = PRUSS_SPP_RTU_XFR_SHIFT_EN; + break; + default: + return -EINVAL; + } + + set = enable ? mask : 0; + + return pruss_cfg_update(pruss, PRUSS_CFG_SPP, mask, set); +} +EXPORT_SYMBOL_GPL(pruss_cfg_xfr_enable); + static void pruss_of_free_clk_provider(void *data) { struct device_node *clk_mux_np = data; @@ -38,6 +292,11 @@ static void pruss_of_free_clk_provider(void *data) of_node_put(clk_mux_np); } +static void pruss_clk_unregister_mux(void *data) +{ + clk_unregister_mux(data); +} + static int pruss_clk_mux_setup(struct pruss *pruss, struct clk *clk_mux, char *mux_name, struct device_node *clks_np) { @@ -93,8 +352,7 @@ static int pruss_clk_mux_setup(struct pruss *pruss, struct clk *clk_mux, goto put_clk_mux_np; } - ret = devm_add_action_or_reset(dev, (void(*)(void *))clk_unregister_mux, - clk_mux); + ret = devm_add_action_or_reset(dev, pruss_clk_unregister_mux, clk_mux); if (ret) { dev_err(dev, "failed to add clkmux unregister action %d", ret); goto put_clk_mux_np; @@ -232,6 +490,7 @@ static int pruss_probe(struct platform_device *pdev) return -ENOMEM; pruss->dev = dev; + mutex_init(&pruss->lock); child = of_get_child_by_name(np, "memories"); if (!child) { diff --git a/drivers/soc/ti/pruss.h b/drivers/soc/ti/pruss.h new file mode 100644 index 0000000000000000000000000000000000000000..6c55987e0e55f92d210a9a64abdcd513ff5b9ebf --- /dev/null +++ b/drivers/soc/ti/pruss.h @@ -0,0 +1,88 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * PRU-ICSS Subsystem user interfaces + * + * Copyright (C) 2015-2023 Texas Instruments Incorporated - http://www.ti.com + * MD Danish Anwar + */ + +#ifndef _SOC_TI_PRUSS_H_ +#define _SOC_TI_PRUSS_H_ + +#include +#include + +/* + * PRU_ICSS_CFG registers + * SYSCFG, ISRP, ISP, IESP, IECP, SCRP applicable on AMxxxx devices only + */ +#define PRUSS_CFG_REVID 0x00 +#define PRUSS_CFG_SYSCFG 0x04 +#define PRUSS_CFG_GPCFG(x) (0x08 + (x) * 4) +#define PRUSS_CFG_CGR 0x10 +#define PRUSS_CFG_ISRP 0x14 +#define PRUSS_CFG_ISP 0x18 +#define PRUSS_CFG_IESP 0x1C +#define PRUSS_CFG_IECP 0x20 +#define PRUSS_CFG_SCRP 0x24 +#define PRUSS_CFG_PMAO 0x28 +#define PRUSS_CFG_MII_RT 0x2C +#define PRUSS_CFG_IEPCLK 0x30 +#define PRUSS_CFG_SPP 0x34 +#define PRUSS_CFG_PIN_MX 0x40 + +/* PRUSS_GPCFG register bits */ +#define PRUSS_GPCFG_PRU_GPI_MODE_MASK GENMASK(1, 0) +#define PRUSS_GPCFG_PRU_GPI_MODE_SHIFT 0 + +#define PRUSS_GPCFG_PRU_MUX_SEL_SHIFT 26 +#define PRUSS_GPCFG_PRU_MUX_SEL_MASK GENMASK(29, 26) + +/* PRUSS_MII_RT register bits */ +#define PRUSS_MII_RT_EVENT_EN BIT(0) + +/* PRUSS_SPP register bits */ +#define PRUSS_SPP_XFER_SHIFT_EN BIT(1) +#define PRUSS_SPP_PRU1_PAD_HP_EN BIT(0) +#define PRUSS_SPP_RTU_XFR_SHIFT_EN BIT(3) + +/** + * pruss_cfg_read() - read a PRUSS CFG sub-module register + * @pruss: the pruss instance handle + * @reg: register offset within the CFG sub-module + * @val: pointer to return the value in + * + * Reads a given register within the PRUSS CFG sub-module and + * returns it through the passed-in @val pointer + * + * Return: 0 on success, or an error code otherwise + */ +static int pruss_cfg_read(struct pruss *pruss, unsigned int reg, unsigned int *val) +{ + if (IS_ERR_OR_NULL(pruss)) + return -EINVAL; + + return regmap_read(pruss->cfg_regmap, reg, val); +} + +/** + * pruss_cfg_update() - configure a PRUSS CFG sub-module register + * @pruss: the pruss instance handle + * @reg: register offset within the CFG sub-module + * @mask: bit mask to use for programming the @val + * @val: value to write + * + * Programs a given register within the PRUSS CFG sub-module + * + * Return: 0 on success, or an error code otherwise + */ +static int pruss_cfg_update(struct pruss *pruss, unsigned int reg, + unsigned int mask, unsigned int val) +{ + if (IS_ERR_OR_NULL(pruss)) + return -EINVAL; + + return regmap_update_bits(pruss->cfg_regmap, reg, mask, val); +} + +#endif /* _SOC_TI_PRUSS_H_ */ diff --git a/drivers/soc/ti/smartreflex.c b/drivers/soc/ti/smartreflex.c index da7898239a46ae238b7038551f6573f5ab0ac8f3..62b2f1464e46744ef5436a88269bbe92035618f0 100644 --- a/drivers/soc/ti/smartreflex.c +++ b/drivers/soc/ti/smartreflex.c @@ -815,7 +815,6 @@ static int omap_sr_probe(struct platform_device *pdev) { struct omap_sr *sr_info; struct omap_sr_data *pdata = pdev->dev.platform_data; - struct resource *mem; struct dentry *nvalue_dir; int i, ret = 0; @@ -835,8 +834,7 @@ static int omap_sr_probe(struct platform_device *pdev) return -EINVAL; } - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - sr_info->base = devm_ioremap_resource(&pdev->dev, mem); + sr_info->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(sr_info->base)) return PTR_ERR(sr_info->base); diff --git a/drivers/soc/ti/wkup_m3_ipc.c b/drivers/soc/ti/wkup_m3_ipc.c index c9197912ec249dfe8acf65421725153f121b858e..3aff106fc11a00bcb79a39b0a9eec3944afa3dc4 100644 --- a/drivers/soc/ti/wkup_m3_ipc.c +++ b/drivers/soc/ti/wkup_m3_ipc.c @@ -202,7 +202,7 @@ static int wkup_m3_ipc_dbg_init(struct wkup_m3_ipc *m3_ipc) { m3_ipc->dbg_path = debugfs_create_dir("wkup_m3_ipc", NULL); - if (!m3_ipc->dbg_path) + if (IS_ERR(m3_ipc->dbg_path)) return -EINVAL; (void)debugfs_create_file("enable_late_halt", 0644, diff --git a/drivers/soc/xilinx/xlnx_event_manager.c b/drivers/soc/xilinx/xlnx_event_manager.c index c76381899ef4992021a081767207fe0309b7d77a..f9d9b82b562da2d3e3d22367e6ae73bea8caf10a 100644 --- a/drivers/soc/xilinx/xlnx_event_manager.c +++ b/drivers/soc/xilinx/xlnx_event_manager.c @@ -192,11 +192,12 @@ static int xlnx_remove_cb_for_suspend(event_cb_func_t cb_fun) struct registered_event_data *eve_data; struct agent_cb *cb_pos; struct agent_cb *cb_next; + struct hlist_node *tmp; is_need_to_unregister = false; /* Check for existing entry in hash table for given cb_type */ - hash_for_each_possible(reg_driver_map, eve_data, hentry, PM_INIT_SUSPEND_CB) { + hash_for_each_possible_safe(reg_driver_map, eve_data, tmp, hentry, PM_INIT_SUSPEND_CB) { if (eve_data->cb_type == PM_INIT_SUSPEND_CB) { /* Delete the list of callback */ list_for_each_entry_safe(cb_pos, cb_next, &eve_data->cb_list_head, list) { @@ -228,11 +229,12 @@ static int xlnx_remove_cb_for_notify_event(const u32 node_id, const u32 event, u64 key = ((u64)node_id << 32U) | (u64)event; struct agent_cb *cb_pos; struct agent_cb *cb_next; + struct hlist_node *tmp; is_need_to_unregister = false; /* Check for existing entry in hash table for given key id */ - hash_for_each_possible(reg_driver_map, eve_data, hentry, key) { + hash_for_each_possible_safe(reg_driver_map, eve_data, tmp, hentry, key) { if (eve_data->key == key) { /* Delete the list of callback */ list_for_each_entry_safe(cb_pos, cb_next, &eve_data->cb_list_head, list) { diff --git a/drivers/soc/xilinx/zynqmp_power.c b/drivers/soc/xilinx/zynqmp_power.c index 78a8a7545d1eda1dc3949037c5be957b38edee72..641dcc95891164730a8c157149cf3348df4ad8fa 100644 --- a/drivers/soc/xilinx/zynqmp_power.c +++ b/drivers/soc/xilinx/zynqmp_power.c @@ -218,7 +218,7 @@ static int zynqmp_pm_probe(struct platform_device *pdev) } else if (ret != -EACCES && ret != -ENODEV) { dev_err(&pdev->dev, "Failed to Register with Xilinx Event manager %d\n", ret); return ret; - } else if (of_find_property(pdev->dev.of_node, "mboxes", NULL)) { + } else if (of_property_present(pdev->dev.of_node, "mboxes")) { zynqmp_pm_init_suspend_work = devm_kzalloc(&pdev->dev, sizeof(struct zynqmp_pm_work_struct), @@ -240,7 +240,7 @@ static int zynqmp_pm_probe(struct platform_device *pdev) dev_err(&pdev->dev, "Failed to request rx channel\n"); return PTR_ERR(rx_chan); } - } else if (of_find_property(pdev->dev.of_node, "interrupts", NULL)) { + } else if (of_property_present(pdev->dev.of_node, "interrupts")) { irq = platform_get_irq(pdev, 0); if (irq <= 0) return -ENXIO; diff --git a/drivers/soundwire/Kconfig b/drivers/soundwire/Kconfig index fa71c9a36df7a7fdef488e34d8dcfc32098e6d87..4d8f3b7024ae593c2b7ebdf00cd12c7757a18ae1 100644 --- a/drivers/soundwire/Kconfig +++ b/drivers/soundwire/Kconfig @@ -37,6 +37,7 @@ config SOUNDWIRE_INTEL select SOUNDWIRE_GENERIC_ALLOCATION select AUXILIARY_BUS depends on ACPI && SND_SOC + depends on SND_SOC_SOF_HDA_MLINK || !SND_SOC_SOF_HDA_MLINK help SoundWire Intel Master driver. If you have an Intel platform which has a SoundWire Master then diff --git a/drivers/soundwire/Makefile b/drivers/soundwire/Makefile index 925566ff42721bfde1eb62920ea2debc4f15759b..c3d3ab3262d3ab60a063ef28dc8fbd8606f3bb73 100644 --- a/drivers/soundwire/Makefile +++ b/drivers/soundwire/Makefile @@ -24,7 +24,8 @@ soundwire-cadence-y := cadence_master.o obj-$(CONFIG_SOUNDWIRE_CADENCE) += soundwire-cadence.o #Intel driver -soundwire-intel-y := intel.o intel_auxdevice.o intel_init.o dmi-quirks.o \ +soundwire-intel-y := intel.o intel_ace2x.o intel_ace2x_debugfs.o \ + intel_auxdevice.o intel_init.o dmi-quirks.o \ intel_bus_common.o obj-$(CONFIG_SOUNDWIRE_INTEL) += soundwire-intel.o diff --git a/drivers/soundwire/amd_manager.c b/drivers/soundwire/amd_manager.c index 9fb7f91ca182790ccb096e662d2a3292793a8bdc..08aeb7ed00e1ff4581e880ffba5000bb4a6306b4 100644 --- a/drivers/soundwire/amd_manager.c +++ b/drivers/soundwire/amd_manager.c @@ -972,15 +972,18 @@ static int amd_sdw_manager_probe(struct platform_device *pdev) return 0; } -static int amd_sdw_manager_remove(struct platform_device *pdev) +static void amd_sdw_manager_remove(struct platform_device *pdev) { struct amd_sdw_manager *amd_manager = dev_get_drvdata(&pdev->dev); + int ret; pm_runtime_disable(&pdev->dev); cancel_work_sync(&amd_manager->probe_work); amd_disable_sdw_interrupts(amd_manager); sdw_bus_master_delete(&amd_manager->bus); - return amd_disable_sdw_manager(amd_manager); + ret = amd_disable_sdw_manager(amd_manager); + if (ret) + dev_err(&pdev->dev, "Failed to disable device (%pe)\n", ERR_PTR(ret)); } static int amd_sdw_clock_stop(struct amd_sdw_manager *amd_manager) @@ -1194,7 +1197,7 @@ static const struct dev_pm_ops amd_pm = { static struct platform_driver amd_sdw_driver = { .probe = &amd_sdw_manager_probe, - .remove = &amd_sdw_manager_remove, + .remove_new = &amd_sdw_manager_remove, .driver = { .name = "amd_sdw_manager", .pm = &amd_pm, diff --git a/drivers/soundwire/bus.c b/drivers/soundwire/bus.c index 1ea6a64f8c4a5e0a2ba6193fd81dd3a6c9e48fa0..dba920ec88f6fb17c2c9c26140fc192f8ec2f11c 100644 --- a/drivers/soundwire/bus.c +++ b/drivers/soundwire/bus.c @@ -69,8 +69,17 @@ int sdw_bus_master_add(struct sdw_bus *bus, struct device *parent, return -EINVAL; } - mutex_init(&bus->msg_lock); - mutex_init(&bus->bus_lock); + /* + * Give each bus_lock and msg_lock a unique key so that lockdep won't + * trigger a deadlock warning when the locks of several buses are + * grabbed during configuration of a multi-bus stream. + */ + lockdep_register_key(&bus->msg_lock_key); + __mutex_init(&bus->msg_lock, "msg_lock", &bus->msg_lock_key); + + lockdep_register_key(&bus->bus_lock_key); + __mutex_init(&bus->bus_lock, "bus_lock", &bus->bus_lock_key); + INIT_LIST_HEAD(&bus->slaves); INIT_LIST_HEAD(&bus->m_rt_list); @@ -181,6 +190,8 @@ void sdw_bus_master_delete(struct sdw_bus *bus) sdw_master_device_del(bus); sdw_bus_debugfs_exit(bus); + lockdep_unregister_key(&bus->bus_lock_key); + lockdep_unregister_key(&bus->msg_lock_key); ida_free(&sdw_bus_ida, bus->id); } EXPORT_SYMBOL(sdw_bus_master_delete); @@ -769,6 +780,9 @@ static int sdw_assign_device_num(struct sdw_slave *slave) /* After xfer of msg, restore dev_num */ slave->dev_num = slave->dev_num_sticky; + if (bus->ops && bus->ops->new_peripheral_assigned) + bus->ops->new_peripheral_assigned(bus, dev_num); + return 0; } @@ -1588,7 +1602,7 @@ static int sdw_handle_slave_alerts(struct sdw_slave *slave) unsigned long port; bool slave_notify; u8 sdca_cascade = 0; - u8 buf, buf2[2], _buf, _buf2[2]; + u8 buf, buf2[2]; bool parity_check; bool parity_quirk; @@ -1745,9 +1759,9 @@ static int sdw_handle_slave_alerts(struct sdw_slave *slave) "SDW_SCP_INT1 recheck read failed:%d\n", ret); goto io_err; } - _buf = ret; + buf = ret; - ret = sdw_nread_no_pm(slave, SDW_SCP_INTSTAT2, 2, _buf2); + ret = sdw_nread_no_pm(slave, SDW_SCP_INTSTAT2, 2, buf2); if (ret < 0) { dev_err(&slave->dev, "SDW_SCP_INT2/3 recheck read failed:%d\n", ret); @@ -1765,12 +1779,8 @@ static int sdw_handle_slave_alerts(struct sdw_slave *slave) } /* - * Make sure no interrupts are pending, but filter to limit loop - * to interrupts identified in the first status read + * Make sure no interrupts are pending */ - buf &= _buf; - buf2[0] &= _buf2[0]; - buf2[1] &= _buf2[1]; stat = buf || buf2[0] || buf2[1] || sdca_cascade; /* diff --git a/drivers/soundwire/cadence_master.c b/drivers/soundwire/cadence_master.c index 39502bc75712c975cb9de6da501131f59cd9482d..0efc1c3bee5f547ed7b88b7a91fa4dc3091c443f 100644 --- a/drivers/soundwire/cadence_master.c +++ b/drivers/soundwire/cadence_master.c @@ -283,6 +283,29 @@ static int cdns_config_update(struct sdw_cdns *cdns) return ret; } +/** + * sdw_cdns_config_update() - Update configurations + * @cdns: Cadence instance + */ +void sdw_cdns_config_update(struct sdw_cdns *cdns) +{ + /* commit changes */ + cdns_writel(cdns, CDNS_MCP_CONFIG_UPDATE, CDNS_MCP_CONFIG_UPDATE_BIT); +} +EXPORT_SYMBOL(sdw_cdns_config_update); + +/** + * sdw_cdns_config_update_set_wait() - wait until configuration update bit is self-cleared + * @cdns: Cadence instance + */ +int sdw_cdns_config_update_set_wait(struct sdw_cdns *cdns) +{ + /* the hardware recommendation is to wait at least 300us */ + return cdns_set_wait(cdns, CDNS_MCP_CONFIG_UPDATE, + CDNS_MCP_CONFIG_UPDATE_BIT, 0); +} +EXPORT_SYMBOL(sdw_cdns_config_update_set_wait); + /* * debugfs */ @@ -433,9 +456,9 @@ static int cdns_parity_error_injection(void *data, u64 value) CDNS_IP_MCP_CMDCTRL_INSERT_PARITY_ERR); /* commit changes */ - cdns_updatel(cdns, CDNS_MCP_CONFIG_UPDATE, - CDNS_MCP_CONFIG_UPDATE_BIT, - CDNS_MCP_CONFIG_UPDATE_BIT); + ret = cdns_clear_bit(cdns, CDNS_MCP_CONFIG_UPDATE, CDNS_MCP_CONFIG_UPDATE_BIT); + if (ret < 0) + goto unlock; /* do a broadcast dummy read to avoid bus clashes */ ret = sdw_bread_no_pm_unlocked(&cdns->bus, 0xf, SDW_SCP_DEVID_0); @@ -447,16 +470,17 @@ static int cdns_parity_error_injection(void *data, u64 value) 0); /* commit changes */ - cdns_updatel(cdns, CDNS_MCP_CONFIG_UPDATE, - CDNS_MCP_CONFIG_UPDATE_BIT, - CDNS_MCP_CONFIG_UPDATE_BIT); - - /* Continue bus operation with parity error injection disabled */ - mutex_unlock(&bus->bus_lock); + ret = cdns_clear_bit(cdns, CDNS_MCP_CONFIG_UPDATE, CDNS_MCP_CONFIG_UPDATE_BIT); + if (ret < 0) + goto unlock; /* Userspace changed the hardware state behind the kernel's back */ add_taint(TAINT_USER, LOCKDEP_STILL_OK); +unlock: + /* Continue bus operation with parity error injection disabled */ + mutex_unlock(&bus->bus_lock); + /* * allow Master device to enter pm_runtime suspend. This may * also result in Slave devices suspending. @@ -1116,13 +1140,7 @@ int sdw_cdns_exit_reset(struct sdw_cdns *cdns) CDNS_MCP_CONTROL_HW_RST); /* commit changes */ - cdns_updatel(cdns, CDNS_MCP_CONFIG_UPDATE, - CDNS_MCP_CONFIG_UPDATE_BIT, - CDNS_MCP_CONFIG_UPDATE_BIT); - - /* don't wait here */ - return 0; - + return cdns_config_update(cdns); } EXPORT_SYMBOL(sdw_cdns_exit_reset); diff --git a/drivers/soundwire/cadence_master.h b/drivers/soundwire/cadence_master.h index 27c56274217f0ea30c90d93ea9cb13bd702c5a53..bc84435e420f5bb5a62e4225f47c81c98cc6cf49 100644 --- a/drivers/soundwire/cadence_master.h +++ b/drivers/soundwire/cadence_master.h @@ -14,6 +14,8 @@ */ #define CDNS_MCP_IP_MAX_CMD_LEN 32 +#define SDW_CADENCE_MCP_IP_OFFSET 0x4000 + /** * struct sdw_cdns_pdi: PDI (Physical Data Interface) instance * @@ -197,4 +199,7 @@ int cdns_set_sdw_stream(struct snd_soc_dai *dai, void sdw_cdns_check_self_clearing_bits(struct sdw_cdns *cdns, const char *string, bool initial_delay, int reset_iterations); +void sdw_cdns_config_update(struct sdw_cdns *cdns); +int sdw_cdns_config_update_set_wait(struct sdw_cdns *cdns); + #endif /* __SDW_CADENCE_H */ diff --git a/drivers/soundwire/debugfs.c b/drivers/soundwire/debugfs.c index dea782e0edc4be65fe79ee18e78336993c32780c..d1553cb77187471b40e4601f3cd5399e241ad076 100644 --- a/drivers/soundwire/debugfs.c +++ b/drivers/soundwire/debugfs.c @@ -56,8 +56,9 @@ static int sdw_slave_reg_show(struct seq_file *s_file, void *data) if (!buf) return -ENOMEM; - ret = pm_runtime_resume_and_get(&slave->dev); + ret = pm_runtime_get_sync(&slave->dev); if (ret < 0 && ret != -EACCES) { + pm_runtime_put_noidle(&slave->dev); kfree(buf); return ret; } @@ -85,10 +86,17 @@ static int sdw_slave_reg_show(struct seq_file *s_file, void *data) /* SCP registers */ ret += scnprintf(buf + ret, RD_BUF - ret, "\nSCP\n"); - for (i = SDW_SCP_INT1; i <= SDW_SCP_BANKDELAY; i++) + for (i = SDW_SCP_INT1; i <= SDW_SCP_BUS_CLOCK_BASE; i++) ret += sdw_sprintf(slave, buf, ret, i); for (i = SDW_SCP_DEVID_0; i <= SDW_SCP_DEVID_5; i++) ret += sdw_sprintf(slave, buf, ret, i); + for (i = SDW_SCP_FRAMECTRL_B0; i <= SDW_SCP_BUSCLOCK_SCALE_B0; i++) + ret += sdw_sprintf(slave, buf, ret, i); + for (i = SDW_SCP_FRAMECTRL_B1; i <= SDW_SCP_BUSCLOCK_SCALE_B1; i++) + ret += sdw_sprintf(slave, buf, ret, i); + for (i = SDW_SCP_PHY_OUT_CTRL_0; i <= SDW_SCP_PHY_OUT_CTRL_7; i++) + ret += sdw_sprintf(slave, buf, ret, i); + /* * SCP Bank 0/1 registers are read-only and cannot be diff --git a/drivers/soundwire/generic_bandwidth_allocation.c b/drivers/soundwire/generic_bandwidth_allocation.c index 325c475b6a66dd2e950b77712a7dbeb4f9535076..31162f2b563811569dcf1bec7a0fc0757efa72f4 100644 --- a/drivers/soundwire/generic_bandwidth_allocation.c +++ b/drivers/soundwire/generic_bandwidth_allocation.c @@ -139,20 +139,16 @@ static void _sdw_compute_port_params(struct sdw_bus *bus, { struct sdw_master_runtime *m_rt; int hstop = bus->params.col - 1; - int block_offset, port_bo, i; + int port_bo, i; /* Run loop for all groups to compute transport parameters */ for (i = 0; i < count; i++) { port_bo = 1; - block_offset = 1; list_for_each_entry(m_rt, &bus->m_rt_list, bus_node) { - sdw_compute_master_ports(m_rt, ¶ms[i], - port_bo, hstop); + sdw_compute_master_ports(m_rt, ¶ms[i], port_bo, hstop); - block_offset += m_rt->ch_count * - m_rt->stream->params.bps; - port_bo = block_offset; + port_bo += m_rt->ch_count * m_rt->stream->params.bps; } hstop = hstop - params[i].hwidth; diff --git a/drivers/soundwire/intel.c b/drivers/soundwire/intel.c index 238acf5c97a9f8b40eca362dfedca211d1294e65..26d8485427dd210a706bb7980fb23123c845abdb 100644 --- a/drivers/soundwire/intel.c +++ b/drivers/soundwire/intel.c @@ -260,7 +260,7 @@ static void intel_shim_init(struct sdw_intel *sdw) { void __iomem *shim = sdw->link_res->shim; unsigned int link_id = sdw->instance; - u16 ioctl = 0, act = 0; + u16 ioctl = 0, act; /* Initialize Shim */ ioctl |= SDW_SHIM_IOCTL_BKE; @@ -281,6 +281,7 @@ static void intel_shim_init(struct sdw_intel *sdw) intel_shim_glue_to_master_ip(sdw); + act = intel_readw(shim, SDW_SHIM_CTMCTL(link_id)); u16p_replace_bits(&act, 0x1, SDW_SHIM_CTMCTL_DOAIS); act |= SDW_SHIM_CTMCTL_DACTQE; act |= SDW_SHIM_CTMCTL_DODS; @@ -643,7 +644,7 @@ intel_pdi_alh_configure(struct sdw_intel *sdw, struct sdw_cdns_pdi *pdi) } static int intel_params_stream(struct sdw_intel *sdw, - int stream, + struct snd_pcm_substream *substream, struct snd_soc_dai *dai, struct snd_pcm_hw_params *hw_params, int link_id, int alh_stream_id) @@ -651,7 +652,7 @@ static int intel_params_stream(struct sdw_intel *sdw, struct sdw_intel_link_res *res = sdw->link_res; struct sdw_intel_stream_params_data params_data; - params_data.stream = stream; /* direction */ + params_data.substream = substream; params_data.dai = dai; params_data.hw_params = hw_params; params_data.link_id = link_id; @@ -663,25 +664,6 @@ static int intel_params_stream(struct sdw_intel *sdw, return -EIO; } -static int intel_free_stream(struct sdw_intel *sdw, - int stream, - struct snd_soc_dai *dai, - int link_id) -{ - struct sdw_intel_link_res *res = sdw->link_res; - struct sdw_intel_stream_free_data free_data; - - free_data.stream = stream; /* direction */ - free_data.dai = dai; - free_data.link_id = link_id; - - if (res->ops && res->ops->free_stream && res->dev) - return res->ops->free_stream(res->dev, - &free_data); - - return 0; -} - /* * DAI routines */ @@ -727,7 +709,7 @@ static int intel_hw_params(struct snd_pcm_substream *substream, dai_runtime->pdi = pdi; /* Inform DSP about PDI stream number */ - ret = intel_params_stream(sdw, substream->stream, dai, params, + ret = intel_params_stream(sdw, substream, dai, params, sdw->instance, pdi->intel_alh_id); if (ret) @@ -804,7 +786,7 @@ static int intel_prepare(struct snd_pcm_substream *substream, sdw_cdns_config_stream(cdns, ch, dir, dai_runtime->pdi); /* Inform DSP about PDI stream number */ - ret = intel_params_stream(sdw, substream->stream, dai, + ret = intel_params_stream(sdw, substream, dai, hw_params, sdw->instance, dai_runtime->pdi->intel_alh_id); @@ -817,7 +799,6 @@ static int intel_hw_free(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct sdw_cdns *cdns = snd_soc_dai_get_drvdata(dai); - struct sdw_intel *sdw = cdns_to_intel(cdns); struct sdw_cdns_dai_runtime *dai_runtime; int ret; @@ -838,12 +819,6 @@ intel_hw_free(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) return ret; } - ret = intel_free_stream(sdw, substream->stream, dai, sdw->instance); - if (ret < 0) { - dev_err(dai->dev, "intel_free_stream: failed %d\n", ret); - return ret; - } - dai_runtime->pdi = NULL; return 0; @@ -871,19 +846,9 @@ static void *intel_get_sdw_stream(struct snd_soc_dai *dai, static int intel_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { struct sdw_cdns *cdns = snd_soc_dai_get_drvdata(dai); - struct sdw_intel *sdw = cdns_to_intel(cdns); - struct sdw_intel_link_res *res = sdw->link_res; struct sdw_cdns_dai_runtime *dai_runtime; int ret = 0; - /* - * The .trigger callback is used to send required IPC to audio - * firmware. The .free_stream callback will still be called - * by intel_free_stream() in the TRIGGER_SUSPEND case. - */ - if (res->ops && res->ops->trigger) - res->ops->trigger(dai, cmd, substream->stream); - dai_runtime = cdns->dai_runtime_array[dai->id]; if (!dai_runtime) { dev_err(dai->dev, "failed to get dai runtime in %s\n", @@ -903,7 +868,6 @@ static int intel_trigger(struct snd_pcm_substream *substream, int cmd, struct sn dai_runtime->suspended = true; - ret = intel_free_stream(sdw, substream->stream, dai, sdw->instance); break; case SNDRV_PCM_TRIGGER_PAUSE_PUSH: @@ -949,9 +913,7 @@ static int intel_component_dais_suspend(struct snd_soc_component *component) */ for_each_component_dais(component, dai) { struct sdw_cdns *cdns = snd_soc_dai_get_drvdata(dai); - struct sdw_intel *sdw = cdns_to_intel(cdns); struct sdw_cdns_dai_runtime *dai_runtime; - int ret; dai_runtime = cdns->dai_runtime_array[dai->id]; @@ -961,13 +923,8 @@ static int intel_component_dais_suspend(struct snd_soc_component *component) if (dai_runtime->suspended) continue; - if (dai_runtime->paused) { + if (dai_runtime->paused) dai_runtime->suspended = true; - - ret = intel_free_stream(sdw, dai_runtime->direction, dai, sdw->instance); - if (ret < 0) - return ret; - } } return 0; diff --git a/drivers/soundwire/intel.h b/drivers/soundwire/intel.h index 09d479f2c77b91a432166ca2be6e97c336f12418..511932c55216c77da4f34d54fcd40501b0b1e282 100644 --- a/drivers/soundwire/intel.h +++ b/drivers/soundwire/intel.h @@ -4,13 +4,17 @@ #ifndef __SDW_INTEL_LOCAL_H #define __SDW_INTEL_LOCAL_H +struct hdac_bus; + /** * struct sdw_intel_link_res - Soundwire Intel link resource structure, * typically populated by the controller driver. * @hw_ops: platform-specific ops * @mmio_base: mmio base of SoundWire registers * @registers: Link IO registers base + * @ip_offset: offset for MCP_IP registers * @shim: Audio shim pointer + * @shim_vs: Audio vendor-specific shim pointer * @alh: ALH (Audio Link Hub) pointer * @irq: Interrupt line * @ops: Shim callback ops @@ -21,13 +25,16 @@ * @link_mask: global mask needed for power-up/down sequences * @cdns: Cadence master descriptor * @list: used to walk-through all masters exposed by the same controller + * @hbus: hdac_bus pointer, needed for power management */ struct sdw_intel_link_res { const struct sdw_intel_hw_ops *hw_ops; void __iomem *mmio_base; /* not strictly needed, useful for debug */ void __iomem *registers; + u32 ip_offset; void __iomem *shim; + void __iomem *shim_vs; void __iomem *alh; int irq; const struct sdw_intel_ops *ops; @@ -38,6 +45,7 @@ struct sdw_intel_link_res { u32 link_mask; struct sdw_cdns *cdns; struct list_head list; + struct hdac_bus *hbus; }; struct sdw_intel { @@ -87,6 +95,14 @@ static inline void intel_writew(void __iomem *base, int offset, u16 value) (sdw)->link_res->hw_ops->cb) #define SDW_INTEL_OPS(sdw, cb) ((sdw)->link_res->hw_ops->cb) +#ifdef CONFIG_DEBUG_FS +void intel_ace2x_debugfs_init(struct sdw_intel *sdw); +void intel_ace2x_debugfs_exit(struct sdw_intel *sdw); +#else +static inline void intel_ace2x_debugfs_init(struct sdw_intel *sdw) {} +static inline void intel_ace2x_debugfs_exit(struct sdw_intel *sdw) {} +#endif + static inline void sdw_intel_debugfs_init(struct sdw_intel *sdw) { if (SDW_INTEL_CHECK_OPS(sdw, debugfs_init)) diff --git a/drivers/soundwire/intel_ace2x.c b/drivers/soundwire/intel_ace2x.c new file mode 100644 index 0000000000000000000000000000000000000000..1be0bea5f40fa9b8c39cfc16258988e1fdc42e96 --- /dev/null +++ b/drivers/soundwire/intel_ace2x.c @@ -0,0 +1,393 @@ +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) +// Copyright(c) 2023 Intel Corporation. All rights reserved. + +/* + * Soundwire Intel ops for LunarLake + */ + +#include +#include +#include +#include +#include +#include +#include "cadence_master.h" +#include "bus.h" +#include "intel.h" + +/* + * shim vendor-specific (vs) ops + */ + +static void intel_shim_vs_init(struct sdw_intel *sdw) +{ + void __iomem *shim_vs = sdw->link_res->shim_vs; + u16 act = 0; + + u16p_replace_bits(&act, 0x1, SDW_SHIM2_INTEL_VS_ACTMCTL_DOAIS); + act |= SDW_SHIM2_INTEL_VS_ACTMCTL_DACTQE; + act |= SDW_SHIM2_INTEL_VS_ACTMCTL_DODS; + intel_writew(shim_vs, SDW_SHIM2_INTEL_VS_ACTMCTL, act); + usleep_range(10, 15); +} + +static int intel_shim_check_wake(struct sdw_intel *sdw) +{ + void __iomem *shim_vs; + u16 wake_sts; + + shim_vs = sdw->link_res->shim_vs; + wake_sts = intel_readw(shim_vs, SDW_SHIM2_INTEL_VS_WAKESTS); + + return wake_sts & SDW_SHIM2_INTEL_VS_WAKEEN_PWS; +} + +static void intel_shim_wake(struct sdw_intel *sdw, bool wake_enable) +{ + void __iomem *shim_vs = sdw->link_res->shim_vs; + u16 wake_en; + u16 wake_sts; + + wake_en = intel_readw(shim_vs, SDW_SHIM2_INTEL_VS_WAKEEN); + + if (wake_enable) { + /* Enable the wakeup */ + wake_en |= SDW_SHIM2_INTEL_VS_WAKEEN_PWE; + intel_writew(shim_vs, SDW_SHIM2_INTEL_VS_WAKEEN, wake_en); + } else { + /* Disable the wake up interrupt */ + wake_en &= ~SDW_SHIM2_INTEL_VS_WAKEEN_PWE; + intel_writew(shim_vs, SDW_SHIM2_INTEL_VS_WAKEEN, wake_en); + + /* Clear wake status (W1C) */ + wake_sts = intel_readw(shim_vs, SDW_SHIM2_INTEL_VS_WAKESTS); + wake_sts |= SDW_SHIM2_INTEL_VS_WAKEEN_PWS; + intel_writew(shim_vs, SDW_SHIM2_INTEL_VS_WAKESTS, wake_sts); + } +} + +static int intel_link_power_up(struct sdw_intel *sdw) +{ + struct sdw_bus *bus = &sdw->cdns.bus; + struct sdw_master_prop *prop = &bus->prop; + u32 *shim_mask = sdw->link_res->shim_mask; + unsigned int link_id = sdw->instance; + u32 syncprd; + int ret; + + mutex_lock(sdw->link_res->shim_lock); + + if (!*shim_mask) { + /* we first need to program the SyncPRD/CPU registers */ + dev_dbg(sdw->cdns.dev, "first link up, programming SYNCPRD\n"); + + if (prop->mclk_freq % 6000000) + syncprd = SDW_SHIM_SYNC_SYNCPRD_VAL_38_4; + else + syncprd = SDW_SHIM_SYNC_SYNCPRD_VAL_24; + + ret = hdac_bus_eml_sdw_set_syncprd_unlocked(sdw->link_res->hbus, syncprd); + if (ret < 0) { + dev_err(sdw->cdns.dev, "%s: hdac_bus_eml_sdw_set_syncprd failed: %d\n", + __func__, ret); + goto out; + } + } + + ret = hdac_bus_eml_sdw_power_up_unlocked(sdw->link_res->hbus, link_id); + if (ret < 0) { + dev_err(sdw->cdns.dev, "%s: hdac_bus_eml_sdw_power_up failed: %d\n", + __func__, ret); + goto out; + } + + if (!*shim_mask) { + /* SYNCPU will change once link is active */ + ret = hdac_bus_eml_sdw_wait_syncpu_unlocked(sdw->link_res->hbus); + if (ret < 0) { + dev_err(sdw->cdns.dev, "%s: hdac_bus_eml_sdw_wait_syncpu failed: %d\n", + __func__, ret); + goto out; + } + } + + *shim_mask |= BIT(link_id); + + sdw->cdns.link_up = true; + + intel_shim_vs_init(sdw); + +out: + mutex_unlock(sdw->link_res->shim_lock); + + return ret; +} + +static int intel_link_power_down(struct sdw_intel *sdw) +{ + u32 *shim_mask = sdw->link_res->shim_mask; + unsigned int link_id = sdw->instance; + int ret; + + mutex_lock(sdw->link_res->shim_lock); + + sdw->cdns.link_up = false; + + *shim_mask &= ~BIT(link_id); + + ret = hdac_bus_eml_sdw_power_down_unlocked(sdw->link_res->hbus, link_id); + if (ret < 0) { + dev_err(sdw->cdns.dev, "%s: hdac_bus_eml_sdw_power_down failed: %d\n", + __func__, ret); + + /* + * we leave the sdw->cdns.link_up flag as false since we've disabled + * the link at this point and cannot handle interrupts any longer. + */ + } + + mutex_unlock(sdw->link_res->shim_lock); + + return ret; +} + +static void intel_sync_arm(struct sdw_intel *sdw) +{ + unsigned int link_id = sdw->instance; + + mutex_lock(sdw->link_res->shim_lock); + + hdac_bus_eml_sdw_sync_arm_unlocked(sdw->link_res->hbus, link_id); + + mutex_unlock(sdw->link_res->shim_lock); +} + +static int intel_sync_go_unlocked(struct sdw_intel *sdw) +{ + int ret; + + ret = hdac_bus_eml_sdw_sync_go_unlocked(sdw->link_res->hbus); + if (ret < 0) + dev_err(sdw->cdns.dev, "%s: SyncGO clear failed: %d\n", __func__, ret); + + return ret; +} + +static int intel_sync_go(struct sdw_intel *sdw) +{ + int ret; + + mutex_lock(sdw->link_res->shim_lock); + + ret = intel_sync_go_unlocked(sdw); + + mutex_unlock(sdw->link_res->shim_lock); + + return ret; +} + +static bool intel_check_cmdsync_unlocked(struct sdw_intel *sdw) +{ + return hdac_bus_eml_sdw_check_cmdsync_unlocked(sdw->link_res->hbus); +} + +/* + * DAI operations + */ +static const struct snd_soc_dai_ops intel_pcm_dai_ops = { +}; + +static const struct snd_soc_component_driver dai_component = { + .name = "soundwire", +}; + +/* + * PDI routines + */ +static void intel_pdi_init(struct sdw_intel *sdw, + struct sdw_cdns_stream_config *config) +{ + void __iomem *shim = sdw->link_res->shim; + int pcm_cap; + + /* PCM Stream Capability */ + pcm_cap = intel_readw(shim, SDW_SHIM2_PCMSCAP); + + config->pcm_bd = FIELD_GET(SDW_SHIM2_PCMSCAP_BSS, pcm_cap); + config->pcm_in = FIELD_GET(SDW_SHIM2_PCMSCAP_ISS, pcm_cap); + config->pcm_out = FIELD_GET(SDW_SHIM2_PCMSCAP_ISS, pcm_cap); + + dev_dbg(sdw->cdns.dev, "PCM cap bd:%d in:%d out:%d\n", + config->pcm_bd, config->pcm_in, config->pcm_out); +} + +static int +intel_pdi_get_ch_cap(struct sdw_intel *sdw, unsigned int pdi_num) +{ + void __iomem *shim = sdw->link_res->shim; + + /* zero based values for channel count in register */ + return intel_readw(shim, SDW_SHIM2_PCMSYCHC(pdi_num)) + 1; +} + +static void intel_pdi_get_ch_update(struct sdw_intel *sdw, + struct sdw_cdns_pdi *pdi, + unsigned int num_pdi, + unsigned int *num_ch) +{ + int ch_count = 0; + int i; + + for (i = 0; i < num_pdi; i++) { + pdi->ch_count = intel_pdi_get_ch_cap(sdw, pdi->num); + ch_count += pdi->ch_count; + pdi++; + } + + *num_ch = ch_count; +} + +static void intel_pdi_stream_ch_update(struct sdw_intel *sdw, + struct sdw_cdns_streams *stream) +{ + intel_pdi_get_ch_update(sdw, stream->bd, stream->num_bd, + &stream->num_ch_bd); + + intel_pdi_get_ch_update(sdw, stream->in, stream->num_in, + &stream->num_ch_in); + + intel_pdi_get_ch_update(sdw, stream->out, stream->num_out, + &stream->num_ch_out); +} + +static int intel_create_dai(struct sdw_cdns *cdns, + struct snd_soc_dai_driver *dais, + enum intel_pdi_type type, + u32 num, u32 off, u32 max_ch) +{ + int i; + + if (!num) + return 0; + + for (i = off; i < (off + num); i++) { + dais[i].name = devm_kasprintf(cdns->dev, GFP_KERNEL, + "SDW%d Pin%d", + cdns->instance, i); + if (!dais[i].name) + return -ENOMEM; + + if (type == INTEL_PDI_BD || type == INTEL_PDI_OUT) { + dais[i].playback.channels_min = 1; + dais[i].playback.channels_max = max_ch; + } + + if (type == INTEL_PDI_BD || type == INTEL_PDI_IN) { + dais[i].capture.channels_min = 1; + dais[i].capture.channels_max = max_ch; + } + + dais[i].ops = &intel_pcm_dai_ops; + } + + return 0; +} + +static int intel_register_dai(struct sdw_intel *sdw) +{ + struct sdw_cdns_dai_runtime **dai_runtime_array; + struct sdw_cdns_stream_config config; + struct sdw_cdns *cdns = &sdw->cdns; + struct sdw_cdns_streams *stream; + struct snd_soc_dai_driver *dais; + int num_dai; + int ret; + int off = 0; + + /* Read the PDI config and initialize cadence PDI */ + intel_pdi_init(sdw, &config); + ret = sdw_cdns_pdi_init(cdns, config); + if (ret) + return ret; + + intel_pdi_stream_ch_update(sdw, &sdw->cdns.pcm); + + /* DAIs are created based on total number of PDIs supported */ + num_dai = cdns->pcm.num_pdi; + + dai_runtime_array = devm_kcalloc(cdns->dev, num_dai, + sizeof(struct sdw_cdns_dai_runtime *), + GFP_KERNEL); + if (!dai_runtime_array) + return -ENOMEM; + cdns->dai_runtime_array = dai_runtime_array; + + dais = devm_kcalloc(cdns->dev, num_dai, sizeof(*dais), GFP_KERNEL); + if (!dais) + return -ENOMEM; + + /* Create PCM DAIs */ + stream = &cdns->pcm; + + ret = intel_create_dai(cdns, dais, INTEL_PDI_IN, cdns->pcm.num_in, + off, stream->num_ch_in); + if (ret) + return ret; + + off += cdns->pcm.num_in; + ret = intel_create_dai(cdns, dais, INTEL_PDI_OUT, cdns->pcm.num_out, + off, stream->num_ch_out); + if (ret) + return ret; + + off += cdns->pcm.num_out; + ret = intel_create_dai(cdns, dais, INTEL_PDI_BD, cdns->pcm.num_bd, + off, stream->num_ch_bd); + if (ret) + return ret; + + return devm_snd_soc_register_component(cdns->dev, &dai_component, + dais, num_dai); +} + +static void intel_program_sdi(struct sdw_intel *sdw, int dev_num) +{ + int ret; + + ret = hdac_bus_eml_sdw_set_lsdiid(sdw->link_res->hbus, sdw->instance, dev_num); + if (ret < 0) + dev_err(sdw->cdns.dev, "%s: could not set lsdiid for link %d %d\n", + __func__, sdw->instance, dev_num); +} + +const struct sdw_intel_hw_ops sdw_intel_lnl_hw_ops = { + .debugfs_init = intel_ace2x_debugfs_init, + .debugfs_exit = intel_ace2x_debugfs_exit, + + .register_dai = intel_register_dai, + + .check_clock_stop = intel_check_clock_stop, + .start_bus = intel_start_bus, + .start_bus_after_reset = intel_start_bus_after_reset, + .start_bus_after_clock_stop = intel_start_bus_after_clock_stop, + .stop_bus = intel_stop_bus, + + .link_power_up = intel_link_power_up, + .link_power_down = intel_link_power_down, + + .shim_check_wake = intel_shim_check_wake, + .shim_wake = intel_shim_wake, + + .pre_bank_switch = intel_pre_bank_switch, + .post_bank_switch = intel_post_bank_switch, + + .sync_arm = intel_sync_arm, + .sync_go_unlocked = intel_sync_go_unlocked, + .sync_go = intel_sync_go, + .sync_check_cmdsync_unlocked = intel_check_cmdsync_unlocked, + + .program_sdi = intel_program_sdi, +}; +EXPORT_SYMBOL_NS(sdw_intel_lnl_hw_ops, SOUNDWIRE_INTEL); + +MODULE_IMPORT_NS(SND_SOC_SOF_HDA_MLINK); diff --git a/drivers/soundwire/intel_ace2x_debugfs.c b/drivers/soundwire/intel_ace2x_debugfs.c new file mode 100644 index 0000000000000000000000000000000000000000..3d24661ffd370393e1512af9dd5d88df6d06cdf3 --- /dev/null +++ b/drivers/soundwire/intel_ace2x_debugfs.c @@ -0,0 +1,147 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Copyright(c) 2023 Intel Corporation. All rights reserved. + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "bus.h" +#include "cadence_master.h" +#include "intel.h" + +/* + * debugfs + */ +#ifdef CONFIG_DEBUG_FS + +#define RD_BUF (2 * PAGE_SIZE) + +static ssize_t intel_sprintf(void __iomem *mem, bool l, + char *buf, size_t pos, unsigned int reg) +{ + int value; + + if (l) + value = intel_readl(mem, reg); + else + value = intel_readw(mem, reg); + + return scnprintf(buf + pos, RD_BUF - pos, "%4x\t%4x\n", reg, value); +} + +static int intel_reg_show(struct seq_file *s_file, void *data) +{ + struct sdw_intel *sdw = s_file->private; + void __iomem *s = sdw->link_res->shim; + void __iomem *vs_s = sdw->link_res->shim_vs; + ssize_t ret; + u32 pcm_cap; + int pcm_bd; + char *buf; + int j; + + buf = kzalloc(RD_BUF, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + ret = scnprintf(buf, RD_BUF, "Register Value\n"); + ret += scnprintf(buf + ret, RD_BUF - ret, "\nShim\n"); + + ret += intel_sprintf(s, true, buf, ret, SDW_SHIM2_LECAP); + ret += intel_sprintf(s, false, buf, ret, SDW_SHIM2_PCMSCAP); + + pcm_cap = intel_readw(s, SDW_SHIM2_PCMSCAP); + pcm_bd = FIELD_GET(SDW_SHIM2_PCMSCAP_BSS, pcm_cap); + + for (j = 0; j < pcm_bd; j++) { + ret += intel_sprintf(s, false, buf, ret, + SDW_SHIM2_PCMSYCHM(j)); + ret += intel_sprintf(s, false, buf, ret, + SDW_SHIM2_PCMSYCHC(j)); + } + + ret += scnprintf(buf + ret, RD_BUF - ret, "\nVS CLK controls\n"); + ret += intel_sprintf(vs_s, true, buf, ret, SDW_SHIM2_INTEL_VS_LVSCTL); + + ret += scnprintf(buf + ret, RD_BUF - ret, "\nVS Wake registers\n"); + ret += intel_sprintf(vs_s, false, buf, ret, SDW_SHIM2_INTEL_VS_WAKEEN); + ret += intel_sprintf(vs_s, false, buf, ret, SDW_SHIM2_INTEL_VS_WAKESTS); + + ret += scnprintf(buf + ret, RD_BUF - ret, "\nVS IOCTL, ACTMCTL\n"); + ret += intel_sprintf(vs_s, false, buf, ret, SDW_SHIM2_INTEL_VS_IOCTL); + ret += intel_sprintf(vs_s, false, buf, ret, SDW_SHIM2_INTEL_VS_ACTMCTL); + + seq_printf(s_file, "%s", buf); + kfree(buf); + + return 0; +} +DEFINE_SHOW_ATTRIBUTE(intel_reg); + +static int intel_set_m_datamode(void *data, u64 value) +{ + struct sdw_intel *sdw = data; + struct sdw_bus *bus = &sdw->cdns.bus; + + if (value > SDW_PORT_DATA_MODE_STATIC_1) + return -EINVAL; + + /* Userspace changed the hardware state behind the kernel's back */ + add_taint(TAINT_USER, LOCKDEP_STILL_OK); + + bus->params.m_data_mode = value; + + return 0; +} +DEFINE_DEBUGFS_ATTRIBUTE(intel_set_m_datamode_fops, NULL, + intel_set_m_datamode, "%llu\n"); + +static int intel_set_s_datamode(void *data, u64 value) +{ + struct sdw_intel *sdw = data; + struct sdw_bus *bus = &sdw->cdns.bus; + + if (value > SDW_PORT_DATA_MODE_STATIC_1) + return -EINVAL; + + /* Userspace changed the hardware state behind the kernel's back */ + add_taint(TAINT_USER, LOCKDEP_STILL_OK); + + bus->params.s_data_mode = value; + + return 0; +} +DEFINE_DEBUGFS_ATTRIBUTE(intel_set_s_datamode_fops, NULL, + intel_set_s_datamode, "%llu\n"); + +void intel_ace2x_debugfs_init(struct sdw_intel *sdw) +{ + struct dentry *root = sdw->cdns.bus.debugfs; + + if (!root) + return; + + sdw->debugfs = debugfs_create_dir("intel-sdw", root); + + debugfs_create_file("intel-registers", 0400, sdw->debugfs, sdw, + &intel_reg_fops); + + debugfs_create_file("intel-m-datamode", 0200, sdw->debugfs, sdw, + &intel_set_m_datamode_fops); + + debugfs_create_file("intel-s-datamode", 0200, sdw->debugfs, sdw, + &intel_set_s_datamode_fops); + + sdw_cdns_debugfs_init(&sdw->cdns, sdw->debugfs); +} + +void intel_ace2x_debugfs_exit(struct sdw_intel *sdw) +{ + debugfs_remove_recursive(sdw->debugfs); +} +#endif /* CONFIG_DEBUG_FS */ diff --git a/drivers/soundwire/intel_auxdevice.c b/drivers/soundwire/intel_auxdevice.c index b21e86084f7ba429d8a34b9a5d6fbfa9dd05ad7d..0daa6ca9a224e1f92249bb4b3bc95e7e2c7d8fa5 100644 --- a/drivers/soundwire/intel_auxdevice.c +++ b/drivers/soundwire/intel_auxdevice.c @@ -60,6 +60,21 @@ static int generic_post_bank_switch(struct sdw_bus *bus) return sdw->link_res->hw_ops->post_bank_switch(sdw); } +static void generic_new_peripheral_assigned(struct sdw_bus *bus, int dev_num) +{ + struct sdw_cdns *cdns = bus_to_cdns(bus); + struct sdw_intel *sdw = cdns_to_intel(cdns); + + /* paranoia check, this should never happen */ + if (dev_num < INTEL_DEV_NUM_IDA_MIN || dev_num > SDW_MAX_DEVICES) { + dev_err(bus->dev, "%s: invalid dev_num %d\n", __func__, dev_num); + return; + } + + if (sdw->link_res->hw_ops->program_sdi) + sdw->link_res->hw_ops->program_sdi(sdw, dev_num); +} + static int sdw_master_read_intel_prop(struct sdw_bus *bus) { struct sdw_master_prop *prop = &bus->prop; @@ -117,6 +132,7 @@ static struct sdw_master_ops sdw_intel_ops = { .pre_bank_switch = generic_pre_bank_switch, .post_bank_switch = generic_post_bank_switch, .read_ping_status = cdns_read_ping_status, + .new_peripheral_assigned = generic_new_peripheral_assigned, }; /* @@ -144,6 +160,7 @@ static int intel_link_probe(struct auxiliary_device *auxdev, sdw->link_res = &ldev->link_res; cdns->dev = dev; cdns->registers = sdw->link_res->registers; + cdns->ip_offset = sdw->link_res->ip_offset; cdns->instance = sdw->instance; cdns->msg_count = 0; diff --git a/drivers/soundwire/intel_bus_common.c b/drivers/soundwire/intel_bus_common.c index f180e3bea9897c9a41b335d8123d897ef9716de5..e5ac3cc7cb79b1efe899a4c40ae524ae4c96df19 100644 --- a/drivers/soundwire/intel_bus_common.c +++ b/drivers/soundwire/intel_bus_common.c @@ -16,12 +16,6 @@ int intel_start_bus(struct sdw_intel *sdw) struct sdw_bus *bus = &cdns->bus; int ret; - ret = sdw_cdns_enable_interrupt(cdns, true); - if (ret < 0) { - dev_err(dev, "%s: cannot enable interrupts: %d\n", __func__, ret); - return ret; - } - /* * follow recommended programming flows to avoid timeouts when * gsync is enabled @@ -32,30 +26,41 @@ int intel_start_bus(struct sdw_intel *sdw) ret = sdw_cdns_init(cdns); if (ret < 0) { dev_err(dev, "%s: unable to initialize Cadence IP: %d\n", __func__, ret); - goto err_interrupt; + return ret; } - ret = sdw_cdns_exit_reset(cdns); - if (ret < 0) { - dev_err(dev, "%s: unable to exit bus reset sequence: %d\n", __func__, ret); - goto err_interrupt; - } + sdw_cdns_config_update(cdns); if (bus->multi_link) { ret = sdw_intel_sync_go(sdw); if (ret < 0) { dev_err(dev, "%s: sync go failed: %d\n", __func__, ret); - goto err_interrupt; + return ret; } } + + ret = sdw_cdns_config_update_set_wait(cdns); + if (ret < 0) { + dev_err(dev, "%s: CONFIG_UPDATE BIT still set\n", __func__); + return ret; + } + + ret = sdw_cdns_exit_reset(cdns); + if (ret < 0) { + dev_err(dev, "%s: unable to exit bus reset sequence: %d\n", __func__, ret); + return ret; + } + + ret = sdw_cdns_enable_interrupt(cdns, true); + if (ret < 0) { + dev_err(dev, "%s: cannot enable interrupts: %d\n", __func__, ret); + return ret; + } + sdw_cdns_check_self_clearing_bits(cdns, __func__, true, INTEL_MASTER_RESET_ITERATIONS); return 0; - -err_interrupt: - sdw_cdns_enable_interrupt(cdns, false); - return ret; } int intel_start_bus_after_reset(struct sdw_intel *sdw) @@ -86,12 +91,6 @@ int intel_start_bus_after_reset(struct sdw_intel *sdw) status = SDW_UNATTACH_REQUEST_MASTER_RESET; sdw_clear_slave_status(bus, status); - ret = sdw_cdns_enable_interrupt(cdns, true); - if (ret < 0) { - dev_err(dev, "cannot enable interrupts during resume\n"); - return ret; - } - /* * follow recommended programming flows to avoid * timeouts when gsync is enabled @@ -115,31 +114,44 @@ int intel_start_bus_after_reset(struct sdw_intel *sdw) ret = sdw_cdns_clock_restart(cdns, !clock_stop0); if (ret < 0) { dev_err(dev, "unable to restart clock during resume\n"); - goto err_interrupt; + if (!clock_stop0) + sdw_cdns_enable_interrupt(cdns, false); + return ret; } if (!clock_stop0) { - ret = sdw_cdns_exit_reset(cdns); - if (ret < 0) { - dev_err(dev, "unable to exit bus reset sequence during resume\n"); - goto err_interrupt; - } + sdw_cdns_config_update(cdns); if (bus->multi_link) { ret = sdw_intel_sync_go(sdw); if (ret < 0) { dev_err(sdw->cdns.dev, "sync go failed during resume\n"); - goto err_interrupt; + return ret; } } + + ret = sdw_cdns_config_update_set_wait(cdns); + if (ret < 0) { + dev_err(dev, "%s: CONFIG_UPDATE BIT still set\n", __func__); + return ret; + } + + ret = sdw_cdns_exit_reset(cdns); + if (ret < 0) { + dev_err(dev, "unable to exit bus reset sequence during resume\n"); + return ret; + } + + ret = sdw_cdns_enable_interrupt(cdns, true); + if (ret < 0) { + dev_err(dev, "cannot enable interrupts during resume\n"); + return ret; + } + } sdw_cdns_check_self_clearing_bits(cdns, __func__, true, INTEL_MASTER_RESET_ITERATIONS); return 0; - -err_interrupt: - sdw_cdns_enable_interrupt(cdns, false); - return ret; } void intel_check_clock_stop(struct sdw_intel *sdw) @@ -158,21 +170,19 @@ int intel_start_bus_after_clock_stop(struct sdw_intel *sdw) struct sdw_cdns *cdns = &sdw->cdns; int ret; - ret = sdw_cdns_enable_interrupt(cdns, true); + ret = sdw_cdns_clock_restart(cdns, false); if (ret < 0) { - dev_err(dev, "%s: cannot enable interrupts: %d\n", __func__, ret); + dev_err(dev, "%s: unable to restart clock: %d\n", __func__, ret); return ret; } - ret = sdw_cdns_clock_restart(cdns, false); + ret = sdw_cdns_enable_interrupt(cdns, true); if (ret < 0) { - dev_err(dev, "%s: unable to restart clock: %d\n", __func__, ret); - sdw_cdns_enable_interrupt(cdns, false); + dev_err(dev, "%s: cannot enable interrupts: %d\n", __func__, ret); return ret; } - sdw_cdns_check_self_clearing_bits(cdns, "intel_resume_runtime no_quirks", - true, INTEL_MASTER_RESET_ITERATIONS); + sdw_cdns_check_self_clearing_bits(cdns, __func__, true, INTEL_MASTER_RESET_ITERATIONS); return 0; } diff --git a/drivers/soundwire/intel_init.c b/drivers/soundwire/intel_init.c index cbe56b993c6ce9e0b67cf8add703e95af65020da..534c8795e7e85df547a880b11544aee9d34020d7 100644 --- a/drivers/soundwire/intel_init.c +++ b/drivers/soundwire/intel_init.c @@ -63,19 +63,30 @@ static struct sdw_intel_link_dev *intel_link_dev_register(struct sdw_intel_res * link = &ldev->link_res; link->hw_ops = res->hw_ops; link->mmio_base = res->mmio_base; - link->registers = res->mmio_base + SDW_LINK_BASE - + (SDW_LINK_SIZE * link_id); - link->shim = res->mmio_base + res->shim_base; - link->alh = res->mmio_base + res->alh_base; + if (!res->ext) { + link->registers = res->mmio_base + SDW_LINK_BASE + + (SDW_LINK_SIZE * link_id); + link->ip_offset = 0; + link->shim = res->mmio_base + res->shim_base; + link->alh = res->mmio_base + res->alh_base; + link->shim_lock = &ctx->shim_lock; + } else { + link->registers = res->mmio_base + SDW_IP_BASE(link_id); + link->ip_offset = SDW_CADENCE_MCP_IP_OFFSET; + link->shim = res->mmio_base + SDW_SHIM2_GENERIC_BASE(link_id); + link->shim_vs = res->mmio_base + SDW_SHIM2_VS_BASE(link_id); + link->shim_lock = res->eml_lock; + } link->ops = res->ops; link->dev = res->dev; link->clock_stop_quirks = res->clock_stop_quirks; - link->shim_lock = &ctx->shim_lock; link->shim_mask = &ctx->shim_mask; link->link_mask = ctx->link_mask; + link->hbus = res->hbus; + /* now follow the two-step init/add sequence */ ret = auxiliary_device_init(auxdev); if (ret < 0) { diff --git a/drivers/soundwire/qcom.c b/drivers/soundwire/qcom.c index 280455f047a3608ae4689d8126482c25903f8ec5..7970fdb27ba02330555c0a9a0d4c3b5d9e484c98 100644 --- a/drivers/soundwire/qcom.c +++ b/drivers/soundwire/qcom.c @@ -31,6 +31,7 @@ #define SWRM_VERSION_1_3_0 0x01030000 #define SWRM_VERSION_1_5_1 0x01050001 #define SWRM_VERSION_1_7_0 0x01070000 +#define SWRM_VERSION_2_0_0 0x02000000 #define SWRM_COMP_HW_VERSION 0x00 #define SWRM_COMP_CFG_ADDR 0x04 #define SWRM_COMP_CFG_IRQ_LEVEL_OR_PULSE_MSK BIT(1) @@ -41,7 +42,8 @@ #define SWRM_COMP_PARAMS_DOUT_PORTS_MASK GENMASK(4, 0) #define SWRM_COMP_PARAMS_DIN_PORTS_MASK GENMASK(9, 5) #define SWRM_COMP_MASTER_ID 0x104 -#define SWRM_INTERRUPT_STATUS 0x200 +#define SWRM_V1_3_INTERRUPT_STATUS 0x200 +#define SWRM_V2_0_INTERRUPT_STATUS 0x5000 #define SWRM_INTERRUPT_STATUS_RMSK GENMASK(16, 0) #define SWRM_INTERRUPT_STATUS_SLAVE_PEND_IRQ BIT(0) #define SWRM_INTERRUPT_STATUS_NEW_SLAVE_ATTACHED BIT(1) @@ -54,24 +56,32 @@ #define SWRM_INTERRUPT_STATUS_DOUT_PORT_COLLISION BIT(8) #define SWRM_INTERRUPT_STATUS_READ_EN_RD_VALID_MISMATCH BIT(9) #define SWRM_INTERRUPT_STATUS_SPECIAL_CMD_ID_FINISHED BIT(10) -#define SWRM_INTERRUPT_STATUS_BUS_RESET_FINISHED_V2 BIT(13) -#define SWRM_INTERRUPT_STATUS_CLK_STOP_FINISHED_V2 BIT(14) -#define SWRM_INTERRUPT_STATUS_EXT_CLK_STOP_WAKEUP BIT(16) +#define SWRM_INTERRUPT_STATUS_AUTO_ENUM_FAILED BIT(11) +#define SWRM_INTERRUPT_STATUS_AUTO_ENUM_TABLE_IS_FULL BIT(12) +#define SWRM_INTERRUPT_STATUS_BUS_RESET_FINISHED_V2 BIT(13) +#define SWRM_INTERRUPT_STATUS_CLK_STOP_FINISHED_V2 BIT(14) +#define SWRM_INTERRUPT_STATUS_EXT_CLK_STOP_WAKEUP BIT(16) #define SWRM_INTERRUPT_MAX 17 -#define SWRM_INTERRUPT_MASK_ADDR 0x204 -#define SWRM_INTERRUPT_CLEAR 0x208 -#define SWRM_INTERRUPT_CPU_EN 0x210 -#define SWRM_CMD_FIFO_WR_CMD 0x300 -#define SWRM_CMD_FIFO_RD_CMD 0x304 +#define SWRM_V1_3_INTERRUPT_MASK_ADDR 0x204 +#define SWRM_V1_3_INTERRUPT_CLEAR 0x208 +#define SWRM_V2_0_INTERRUPT_CLEAR 0x5008 +#define SWRM_V1_3_INTERRUPT_CPU_EN 0x210 +#define SWRM_V2_0_INTERRUPT_CPU_EN 0x5004 +#define SWRM_V1_3_CMD_FIFO_WR_CMD 0x300 +#define SWRM_V2_0_CMD_FIFO_WR_CMD 0x5020 +#define SWRM_V1_3_CMD_FIFO_RD_CMD 0x304 +#define SWRM_V2_0_CMD_FIFO_RD_CMD 0x5024 #define SWRM_CMD_FIFO_CMD 0x308 #define SWRM_CMD_FIFO_FLUSH 0x1 -#define SWRM_CMD_FIFO_STATUS 0x30C +#define SWRM_V1_3_CMD_FIFO_STATUS 0x30C +#define SWRM_V2_0_CMD_FIFO_STATUS 0x5050 #define SWRM_RD_CMD_FIFO_CNT_MASK GENMASK(20, 16) #define SWRM_WR_CMD_FIFO_CNT_MASK GENMASK(12, 8) #define SWRM_CMD_FIFO_CFG_ADDR 0x314 #define SWRM_CONTINUE_EXEC_ON_CMD_IGNORE BIT(31) #define SWRM_RD_WR_CMD_RETRIES 0x7 -#define SWRM_CMD_FIFO_RD_FIFO_ADDR 0x318 +#define SWRM_V1_3_CMD_FIFO_RD_FIFO_ADDR 0x318 +#define SWRM_V2_0_CMD_FIFO_RD_FIFO_ADDR 0x5040 #define SWRM_RD_FIFO_CMD_ID_MASK GENMASK(11, 8) #define SWRM_ENUMERATOR_CFG_ADDR 0x500 #define SWRM_ENUMERATOR_SLAVE_DEV_ID_1(m) (0x530 + 0x8 * (m)) @@ -95,8 +105,14 @@ #define SWRM_DP_BLOCK_CTRL2_BANK(n, m) (0x1130 + 0x100 * (n - 1) + 0x40 * m) #define SWRM_DP_PORT_HCTRL_BANK(n, m) (0x1134 + 0x100 * (n - 1) + 0x40 * m) #define SWRM_DP_BLOCK_CTRL3_BANK(n, m) (0x1138 + 0x100 * (n - 1) + 0x40 * m) +#define SWRM_DP_SAMPLECTRL2_BANK(n, m) (0x113C + 0x100 * (n - 1) + 0x40 * m) #define SWRM_DIN_DPn_PCM_PORT_CTRL(n) (0x1054 + 0x100 * (n - 1)) -#define SWR_MSTR_MAX_REG_ADDR (0x1740) +#define SWR_V1_3_MSTR_MAX_REG_ADDR 0x1740 +#define SWR_V2_0_MSTR_MAX_REG_ADDR 0x50ac + +#define SWRM_V2_0_CLK_CTRL 0x5060 +#define SWRM_V2_0_CLK_CTRL_CLK_START BIT(0) +#define SWRM_V2_0_LINK_STATUS 0x5064 #define SWRM_DP_PORT_CTRL_EN_CHAN_SHFT 0x18 #define SWRM_DP_PORT_CTRL_OFFSET2_SHFT 0x10 @@ -109,20 +125,20 @@ #define SWRM_REG_VAL_PACK(data, dev, id, reg) \ ((reg) | ((id) << 16) | ((dev) << 20) | ((data) << 24)) -#define MAX_FREQ_NUM 1 -#define TIMEOUT_MS 100 -#define QCOM_SWRM_MAX_RD_LEN 0x1 -#define QCOM_SDW_MAX_PORTS 14 -#define DEFAULT_CLK_FREQ 9600000 -#define SWRM_MAX_DAIS 0xF -#define SWR_INVALID_PARAM 0xFF -#define SWR_HSTOP_MAX_VAL 0xF -#define SWR_HSTART_MIN_VAL 0x0 -#define SWR_BROADCAST_CMD_ID 0x0F -#define SWR_MAX_CMD_ID 14 -#define MAX_FIFO_RD_RETRY 3 -#define SWR_OVERFLOW_RETRY_COUNT 30 -#define SWRM_LINK_STATUS_RETRY_CNT 100 +#define MAX_FREQ_NUM 1 +#define TIMEOUT_MS 100 +#define QCOM_SWRM_MAX_RD_LEN 0x1 +#define QCOM_SDW_MAX_PORTS 14 +#define DEFAULT_CLK_FREQ 9600000 +#define SWRM_MAX_DAIS 0xF +#define SWR_INVALID_PARAM 0xFF +#define SWR_HSTOP_MAX_VAL 0xF +#define SWR_HSTART_MIN_VAL 0x0 +#define SWR_BROADCAST_CMD_ID 0x0F +#define SWR_MAX_CMD_ID 14 +#define MAX_FIFO_RD_RETRY 3 +#define SWR_OVERFLOW_RETRY_COUNT 30 +#define SWRM_LINK_STATUS_RETRY_CNT 100 enum { MASTER_ID_WSA = 1, @@ -131,7 +147,7 @@ enum { }; struct qcom_swrm_port_config { - u8 si; + u16 si; u8 off1; u8 off2; u8 bp_mode; @@ -142,10 +158,28 @@ struct qcom_swrm_port_config { u8 lane_control; }; +/* + * Internal IDs for different register layouts. Only few registers differ per + * each variant, so the list of IDs below does not include all of registers. + */ +enum { + SWRM_REG_FRAME_GEN_ENABLED, + SWRM_REG_INTERRUPT_STATUS, + SWRM_REG_INTERRUPT_MASK_ADDR, + SWRM_REG_INTERRUPT_CLEAR, + SWRM_REG_INTERRUPT_CPU_EN, + SWRM_REG_CMD_FIFO_WR_CMD, + SWRM_REG_CMD_FIFO_RD_CMD, + SWRM_REG_CMD_FIFO_STATUS, + SWRM_REG_CMD_FIFO_RD_FIFO_ADDR, +}; + struct qcom_swrm_ctrl { struct sdw_bus bus; struct device *dev; struct regmap *regmap; + u32 max_reg; + const unsigned int *reg_layout; void __iomem *mmio; struct reset_control *audio_cgcr; #ifdef CONFIG_DEBUG_FS @@ -153,12 +187,9 @@ struct qcom_swrm_ctrl { #endif struct completion broadcast; struct completion enumeration; - struct work_struct slave_work; /* Port alloc/free lock */ struct mutex port_lock; struct clk *hclk; - u8 wr_cmd_id; - u8 rd_cmd_id; int irq; unsigned int version; int wake_irq; @@ -171,7 +202,8 @@ struct qcom_swrm_ctrl { u32 intr_mask; u8 rcmd_id; u8 wcmd_id; - struct qcom_swrm_port_config pconfig[QCOM_SDW_MAX_PORTS]; + /* Port numbers are 1 - 14 */ + struct qcom_swrm_port_config pconfig[QCOM_SDW_MAX_PORTS + 1]; struct sdw_stream_runtime *sruntime[SWRM_MAX_DAIS]; enum sdw_slave_status status[SDW_MAX_DEVICES + 1]; int (*reg_read)(struct qcom_swrm_ctrl *ctrl, int reg, u32 *val); @@ -186,22 +218,62 @@ struct qcom_swrm_data { u32 default_cols; u32 default_rows; bool sw_clk_gate_required; + u32 max_reg; + const unsigned int *reg_layout; +}; + +static const unsigned int swrm_v1_3_reg_layout[] = { + [SWRM_REG_FRAME_GEN_ENABLED] = SWRM_COMP_STATUS, + [SWRM_REG_INTERRUPT_STATUS] = SWRM_V1_3_INTERRUPT_STATUS, + [SWRM_REG_INTERRUPT_MASK_ADDR] = SWRM_V1_3_INTERRUPT_MASK_ADDR, + [SWRM_REG_INTERRUPT_CLEAR] = SWRM_V1_3_INTERRUPT_CLEAR, + [SWRM_REG_INTERRUPT_CPU_EN] = SWRM_V1_3_INTERRUPT_CPU_EN, + [SWRM_REG_CMD_FIFO_WR_CMD] = SWRM_V1_3_CMD_FIFO_WR_CMD, + [SWRM_REG_CMD_FIFO_RD_CMD] = SWRM_V1_3_CMD_FIFO_RD_CMD, + [SWRM_REG_CMD_FIFO_STATUS] = SWRM_V1_3_CMD_FIFO_STATUS, + [SWRM_REG_CMD_FIFO_RD_FIFO_ADDR] = SWRM_V1_3_CMD_FIFO_RD_FIFO_ADDR, }; static const struct qcom_swrm_data swrm_v1_3_data = { .default_rows = 48, .default_cols = 16, + .max_reg = SWR_V1_3_MSTR_MAX_REG_ADDR, + .reg_layout = swrm_v1_3_reg_layout, }; static const struct qcom_swrm_data swrm_v1_5_data = { .default_rows = 50, .default_cols = 16, + .max_reg = SWR_V1_3_MSTR_MAX_REG_ADDR, + .reg_layout = swrm_v1_3_reg_layout, }; static const struct qcom_swrm_data swrm_v1_6_data = { .default_rows = 50, .default_cols = 16, .sw_clk_gate_required = true, + .max_reg = SWR_V1_3_MSTR_MAX_REG_ADDR, + .reg_layout = swrm_v1_3_reg_layout, +}; + +static const unsigned int swrm_v2_0_reg_layout[] = { + [SWRM_REG_FRAME_GEN_ENABLED] = SWRM_V2_0_LINK_STATUS, + [SWRM_REG_INTERRUPT_STATUS] = SWRM_V2_0_INTERRUPT_STATUS, + [SWRM_REG_INTERRUPT_MASK_ADDR] = 0, /* Not present */ + [SWRM_REG_INTERRUPT_CLEAR] = SWRM_V2_0_INTERRUPT_CLEAR, + [SWRM_REG_INTERRUPT_CPU_EN] = SWRM_V2_0_INTERRUPT_CPU_EN, + [SWRM_REG_CMD_FIFO_WR_CMD] = SWRM_V2_0_CMD_FIFO_WR_CMD, + [SWRM_REG_CMD_FIFO_RD_CMD] = SWRM_V2_0_CMD_FIFO_RD_CMD, + [SWRM_REG_CMD_FIFO_STATUS] = SWRM_V2_0_CMD_FIFO_STATUS, + [SWRM_REG_CMD_FIFO_RD_FIFO_ADDR] = SWRM_V2_0_CMD_FIFO_RD_FIFO_ADDR, +}; + +static const struct qcom_swrm_data swrm_v2_0_data = { + .default_rows = 50, + .default_cols = 16, + .sw_clk_gate_required = true, + .max_reg = SWR_V2_0_MSTR_MAX_REG_ADDR, + .reg_layout = swrm_v2_0_reg_layout, }; #define to_qcom_sdw(b) container_of(b, struct qcom_swrm_ctrl, bus) @@ -278,14 +350,15 @@ static u32 swrm_get_packed_reg_val(u8 *cmd_id, u8 cmd_data, return val; } -static int swrm_wait_for_rd_fifo_avail(struct qcom_swrm_ctrl *swrm) +static int swrm_wait_for_rd_fifo_avail(struct qcom_swrm_ctrl *ctrl) { u32 fifo_outstanding_data, value; int fifo_retry_count = SWR_OVERFLOW_RETRY_COUNT; do { /* Check for fifo underflow during read */ - swrm->reg_read(swrm, SWRM_CMD_FIFO_STATUS, &value); + ctrl->reg_read(ctrl, ctrl->reg_layout[SWRM_REG_CMD_FIFO_STATUS], + &value); fifo_outstanding_data = FIELD_GET(SWRM_RD_CMD_FIFO_CNT_MASK, value); /* Check if read data is available in read fifo */ @@ -296,39 +369,66 @@ static int swrm_wait_for_rd_fifo_avail(struct qcom_swrm_ctrl *swrm) } while (fifo_retry_count--); if (fifo_outstanding_data == 0) { - dev_err_ratelimited(swrm->dev, "%s err read underflow\n", __func__); + dev_err_ratelimited(ctrl->dev, "%s err read underflow\n", __func__); return -EIO; } return 0; } -static int swrm_wait_for_wr_fifo_avail(struct qcom_swrm_ctrl *swrm) +static int swrm_wait_for_wr_fifo_avail(struct qcom_swrm_ctrl *ctrl) { u32 fifo_outstanding_cmds, value; int fifo_retry_count = SWR_OVERFLOW_RETRY_COUNT; do { /* Check for fifo overflow during write */ - swrm->reg_read(swrm, SWRM_CMD_FIFO_STATUS, &value); + ctrl->reg_read(ctrl, ctrl->reg_layout[SWRM_REG_CMD_FIFO_STATUS], + &value); fifo_outstanding_cmds = FIELD_GET(SWRM_WR_CMD_FIFO_CNT_MASK, value); /* Check for space in write fifo before writing */ - if (fifo_outstanding_cmds < swrm->wr_fifo_depth) + if (fifo_outstanding_cmds < ctrl->wr_fifo_depth) return 0; usleep_range(500, 510); } while (fifo_retry_count--); - if (fifo_outstanding_cmds == swrm->wr_fifo_depth) { - dev_err_ratelimited(swrm->dev, "%s err write overflow\n", __func__); + if (fifo_outstanding_cmds == ctrl->wr_fifo_depth) { + dev_err_ratelimited(ctrl->dev, "%s err write overflow\n", __func__); return -EIO; } return 0; } -static int qcom_swrm_cmd_fifo_wr_cmd(struct qcom_swrm_ctrl *swrm, u8 cmd_data, +static bool swrm_wait_for_wr_fifo_done(struct qcom_swrm_ctrl *ctrl) +{ + u32 fifo_outstanding_cmds, value; + int fifo_retry_count = SWR_OVERFLOW_RETRY_COUNT; + + /* Check for fifo overflow during write */ + ctrl->reg_read(ctrl, ctrl->reg_layout[SWRM_REG_CMD_FIFO_STATUS], &value); + fifo_outstanding_cmds = FIELD_GET(SWRM_WR_CMD_FIFO_CNT_MASK, value); + + if (fifo_outstanding_cmds) { + while (fifo_retry_count) { + usleep_range(500, 510); + ctrl->reg_read(ctrl, ctrl->reg_layout[SWRM_REG_CMD_FIFO_STATUS], &value); + fifo_outstanding_cmds = FIELD_GET(SWRM_WR_CMD_FIFO_CNT_MASK, value); + fifo_retry_count--; + if (fifo_outstanding_cmds == 0) + return true; + } + } else { + return true; + } + + + return false; +} + +static int qcom_swrm_cmd_fifo_wr_cmd(struct qcom_swrm_ctrl *ctrl, u8 cmd_data, u8 dev_addr, u16 reg_addr) { @@ -341,28 +441,29 @@ static int qcom_swrm_cmd_fifo_wr_cmd(struct qcom_swrm_ctrl *swrm, u8 cmd_data, val = swrm_get_packed_reg_val(&cmd_id, cmd_data, dev_addr, reg_addr); } else { - val = swrm_get_packed_reg_val(&swrm->wcmd_id, cmd_data, + val = swrm_get_packed_reg_val(&ctrl->wcmd_id, cmd_data, dev_addr, reg_addr); } - if (swrm_wait_for_wr_fifo_avail(swrm)) + if (swrm_wait_for_wr_fifo_avail(ctrl)) return SDW_CMD_FAIL_OTHER; if (cmd_id == SWR_BROADCAST_CMD_ID) - reinit_completion(&swrm->broadcast); + reinit_completion(&ctrl->broadcast); /* Its assumed that write is okay as we do not get any status back */ - swrm->reg_write(swrm, SWRM_CMD_FIFO_WR_CMD, val); + ctrl->reg_write(ctrl, ctrl->reg_layout[SWRM_REG_CMD_FIFO_WR_CMD], val); - if (swrm->version <= SWRM_VERSION_1_3_0) + if (ctrl->version <= SWRM_VERSION_1_3_0) usleep_range(150, 155); if (cmd_id == SWR_BROADCAST_CMD_ID) { + swrm_wait_for_wr_fifo_done(ctrl); /* * sleep for 10ms for MSM soundwire variant to allow broadcast * command to complete. */ - ret = wait_for_completion_timeout(&swrm->broadcast, + ret = wait_for_completion_timeout(&ctrl->broadcast, msecs_to_jiffies(TIMEOUT_MS)); if (!ret) ret = SDW_CMD_IGNORED; @@ -375,41 +476,44 @@ static int qcom_swrm_cmd_fifo_wr_cmd(struct qcom_swrm_ctrl *swrm, u8 cmd_data, return ret; } -static int qcom_swrm_cmd_fifo_rd_cmd(struct qcom_swrm_ctrl *swrm, +static int qcom_swrm_cmd_fifo_rd_cmd(struct qcom_swrm_ctrl *ctrl, u8 dev_addr, u16 reg_addr, u32 len, u8 *rval) { u32 cmd_data, cmd_id, val, retry_attempt = 0; - val = swrm_get_packed_reg_val(&swrm->rcmd_id, len, dev_addr, reg_addr); + val = swrm_get_packed_reg_val(&ctrl->rcmd_id, len, dev_addr, reg_addr); /* * Check for outstanding cmd wrt. write fifo depth to avoid * overflow as read will also increase write fifo cnt. */ - swrm_wait_for_wr_fifo_avail(swrm); + swrm_wait_for_wr_fifo_avail(ctrl); /* wait for FIFO RD to complete to avoid overflow */ usleep_range(100, 105); - swrm->reg_write(swrm, SWRM_CMD_FIFO_RD_CMD, val); + ctrl->reg_write(ctrl, ctrl->reg_layout[SWRM_REG_CMD_FIFO_RD_CMD], val); /* wait for FIFO RD CMD complete to avoid overflow */ usleep_range(250, 255); - if (swrm_wait_for_rd_fifo_avail(swrm)) + if (swrm_wait_for_rd_fifo_avail(ctrl)) return SDW_CMD_FAIL_OTHER; do { - swrm->reg_read(swrm, SWRM_CMD_FIFO_RD_FIFO_ADDR, &cmd_data); + ctrl->reg_read(ctrl, ctrl->reg_layout[SWRM_REG_CMD_FIFO_RD_FIFO_ADDR], + &cmd_data); rval[0] = cmd_data & 0xFF; cmd_id = FIELD_GET(SWRM_RD_FIFO_CMD_ID_MASK, cmd_data); - if (cmd_id != swrm->rcmd_id) { + if (cmd_id != ctrl->rcmd_id) { if (retry_attempt < (MAX_FIFO_RD_RETRY - 1)) { /* wait 500 us before retry on fifo read failure */ usleep_range(500, 505); - swrm->reg_write(swrm, SWRM_CMD_FIFO_CMD, + ctrl->reg_write(ctrl, SWRM_CMD_FIFO_CMD, SWRM_CMD_FIFO_FLUSH); - swrm->reg_write(swrm, SWRM_CMD_FIFO_RD_CMD, val); + ctrl->reg_write(ctrl, + ctrl->reg_layout[SWRM_REG_CMD_FIFO_RD_CMD], + val); } retry_attempt++; } else { @@ -418,9 +522,9 @@ static int qcom_swrm_cmd_fifo_rd_cmd(struct qcom_swrm_ctrl *swrm, } while (retry_attempt < MAX_FIFO_RD_RETRY); - dev_err(swrm->dev, "failed to read fifo: reg: 0x%x, rcmd_id: 0x%x,\ + dev_err(ctrl->dev, "failed to read fifo: reg: 0x%x, rcmd_id: 0x%x,\ dev_num: 0x%x, cmd_data: 0x%x\n", - reg_addr, swrm->rcmd_id, dev_addr, cmd_data); + reg_addr, ctrl->rcmd_id, dev_addr, cmd_data); return SDW_CMD_IGNORED; } @@ -511,10 +615,14 @@ static int qcom_swrm_enumerate(struct sdw_bus *bus) sdw_extract_slave_id(bus, addr, &id); found = false; + ctrl->clock_stop_not_supported = false; /* Now compare with entries */ list_for_each_entry_safe(slave, _s, &bus->slaves, node) { if (sdw_compare_devid(slave, id) == 0) { qcom_swrm_set_slave_dev_num(bus, slave, i); + if (slave->prop.clk_stop_mode1) + ctrl->clock_stop_not_supported = true; + found = true; break; } @@ -532,39 +640,41 @@ static int qcom_swrm_enumerate(struct sdw_bus *bus) static irqreturn_t qcom_swrm_wake_irq_handler(int irq, void *dev_id) { - struct qcom_swrm_ctrl *swrm = dev_id; + struct qcom_swrm_ctrl *ctrl = dev_id; int ret; - ret = pm_runtime_resume_and_get(swrm->dev); + ret = pm_runtime_get_sync(ctrl->dev); if (ret < 0 && ret != -EACCES) { - dev_err_ratelimited(swrm->dev, - "pm_runtime_resume_and_get failed in %s, ret %d\n", + dev_err_ratelimited(ctrl->dev, + "pm_runtime_get_sync failed in %s, ret %d\n", __func__, ret); + pm_runtime_put_noidle(ctrl->dev); return ret; } - if (swrm->wake_irq > 0) { - if (!irqd_irq_disabled(irq_get_irq_data(swrm->wake_irq))) - disable_irq_nosync(swrm->wake_irq); + if (ctrl->wake_irq > 0) { + if (!irqd_irq_disabled(irq_get_irq_data(ctrl->wake_irq))) + disable_irq_nosync(ctrl->wake_irq); } - pm_runtime_mark_last_busy(swrm->dev); - pm_runtime_put_autosuspend(swrm->dev); + pm_runtime_mark_last_busy(ctrl->dev); + pm_runtime_put_autosuspend(ctrl->dev); return IRQ_HANDLED; } static irqreturn_t qcom_swrm_irq_handler(int irq, void *dev_id) { - struct qcom_swrm_ctrl *swrm = dev_id; + struct qcom_swrm_ctrl *ctrl = dev_id; u32 value, intr_sts, intr_sts_masked, slave_status; u32 i; int devnum; int ret = IRQ_HANDLED; - clk_prepare_enable(swrm->hclk); + clk_prepare_enable(ctrl->hclk); - swrm->reg_read(swrm, SWRM_INTERRUPT_STATUS, &intr_sts); - intr_sts_masked = intr_sts & swrm->intr_mask; + ctrl->reg_read(ctrl, ctrl->reg_layout[SWRM_REG_INTERRUPT_STATUS], + &intr_sts); + intr_sts_masked = intr_sts & ctrl->intr_mask; do { for (i = 0; i < SWRM_INTERRUPT_MAX; i++) { @@ -574,80 +684,92 @@ static irqreturn_t qcom_swrm_irq_handler(int irq, void *dev_id) switch (value) { case SWRM_INTERRUPT_STATUS_SLAVE_PEND_IRQ: - devnum = qcom_swrm_get_alert_slave_dev_num(swrm); + devnum = qcom_swrm_get_alert_slave_dev_num(ctrl); if (devnum < 0) { - dev_err_ratelimited(swrm->dev, + dev_err_ratelimited(ctrl->dev, "no slave alert found.spurious interrupt\n"); } else { - sdw_handle_slave_status(&swrm->bus, swrm->status); + sdw_handle_slave_status(&ctrl->bus, ctrl->status); } break; case SWRM_INTERRUPT_STATUS_NEW_SLAVE_ATTACHED: case SWRM_INTERRUPT_STATUS_CHANGE_ENUM_SLAVE_STATUS: - dev_dbg_ratelimited(swrm->dev, "SWR new slave attached\n"); - swrm->reg_read(swrm, SWRM_MCP_SLV_STATUS, &slave_status); - if (swrm->slave_status == slave_status) { - dev_dbg(swrm->dev, "Slave status not changed %x\n", + dev_dbg_ratelimited(ctrl->dev, "SWR new slave attached\n"); + ctrl->reg_read(ctrl, SWRM_MCP_SLV_STATUS, &slave_status); + if (ctrl->slave_status == slave_status) { + dev_dbg(ctrl->dev, "Slave status not changed %x\n", slave_status); } else { - qcom_swrm_get_device_status(swrm); - qcom_swrm_enumerate(&swrm->bus); - sdw_handle_slave_status(&swrm->bus, swrm->status); + qcom_swrm_get_device_status(ctrl); + qcom_swrm_enumerate(&ctrl->bus); + sdw_handle_slave_status(&ctrl->bus, ctrl->status); } break; case SWRM_INTERRUPT_STATUS_MASTER_CLASH_DET: - dev_err_ratelimited(swrm->dev, + dev_err_ratelimited(ctrl->dev, "%s: SWR bus clsh detected\n", __func__); - swrm->intr_mask &= ~SWRM_INTERRUPT_STATUS_MASTER_CLASH_DET; - swrm->reg_write(swrm, SWRM_INTERRUPT_CPU_EN, swrm->intr_mask); + ctrl->intr_mask &= ~SWRM_INTERRUPT_STATUS_MASTER_CLASH_DET; + ctrl->reg_write(ctrl, + ctrl->reg_layout[SWRM_REG_INTERRUPT_CPU_EN], + ctrl->intr_mask); break; case SWRM_INTERRUPT_STATUS_RD_FIFO_OVERFLOW: - swrm->reg_read(swrm, SWRM_CMD_FIFO_STATUS, &value); - dev_err_ratelimited(swrm->dev, + ctrl->reg_read(ctrl, + ctrl->reg_layout[SWRM_REG_CMD_FIFO_STATUS], + &value); + dev_err_ratelimited(ctrl->dev, "%s: SWR read FIFO overflow fifo status 0x%x\n", __func__, value); break; case SWRM_INTERRUPT_STATUS_RD_FIFO_UNDERFLOW: - swrm->reg_read(swrm, SWRM_CMD_FIFO_STATUS, &value); - dev_err_ratelimited(swrm->dev, + ctrl->reg_read(ctrl, + ctrl->reg_layout[SWRM_REG_CMD_FIFO_STATUS], + &value); + dev_err_ratelimited(ctrl->dev, "%s: SWR read FIFO underflow fifo status 0x%x\n", __func__, value); break; case SWRM_INTERRUPT_STATUS_WR_CMD_FIFO_OVERFLOW: - swrm->reg_read(swrm, SWRM_CMD_FIFO_STATUS, &value); - dev_err(swrm->dev, + ctrl->reg_read(ctrl, + ctrl->reg_layout[SWRM_REG_CMD_FIFO_STATUS], + &value); + dev_err(ctrl->dev, "%s: SWR write FIFO overflow fifo status %x\n", __func__, value); - swrm->reg_write(swrm, SWRM_CMD_FIFO_CMD, 0x1); + ctrl->reg_write(ctrl, SWRM_CMD_FIFO_CMD, 0x1); break; case SWRM_INTERRUPT_STATUS_CMD_ERROR: - swrm->reg_read(swrm, SWRM_CMD_FIFO_STATUS, &value); - dev_err_ratelimited(swrm->dev, + ctrl->reg_read(ctrl, + ctrl->reg_layout[SWRM_REG_CMD_FIFO_STATUS], + &value); + dev_err_ratelimited(ctrl->dev, "%s: SWR CMD error, fifo status 0x%x, flushing fifo\n", __func__, value); - swrm->reg_write(swrm, SWRM_CMD_FIFO_CMD, 0x1); + ctrl->reg_write(ctrl, SWRM_CMD_FIFO_CMD, 0x1); break; case SWRM_INTERRUPT_STATUS_DOUT_PORT_COLLISION: - dev_err_ratelimited(swrm->dev, + dev_err_ratelimited(ctrl->dev, "%s: SWR Port collision detected\n", __func__); - swrm->intr_mask &= ~SWRM_INTERRUPT_STATUS_DOUT_PORT_COLLISION; - swrm->reg_write(swrm, - SWRM_INTERRUPT_CPU_EN, swrm->intr_mask); + ctrl->intr_mask &= ~SWRM_INTERRUPT_STATUS_DOUT_PORT_COLLISION; + ctrl->reg_write(ctrl, + ctrl->reg_layout[SWRM_REG_INTERRUPT_CPU_EN], + ctrl->intr_mask); break; case SWRM_INTERRUPT_STATUS_READ_EN_RD_VALID_MISMATCH: - dev_err_ratelimited(swrm->dev, + dev_err_ratelimited(ctrl->dev, "%s: SWR read enable valid mismatch\n", __func__); - swrm->intr_mask &= + ctrl->intr_mask &= ~SWRM_INTERRUPT_STATUS_READ_EN_RD_VALID_MISMATCH; - swrm->reg_write(swrm, - SWRM_INTERRUPT_CPU_EN, swrm->intr_mask); + ctrl->reg_write(ctrl, + ctrl->reg_layout[SWRM_REG_INTERRUPT_CPU_EN], + ctrl->intr_mask); break; case SWRM_INTERRUPT_STATUS_SPECIAL_CMD_ID_FINISHED: - complete(&swrm->broadcast); + complete(&ctrl->broadcast); break; case SWRM_INTERRUPT_STATUS_BUS_RESET_FINISHED_V2: break; @@ -656,22 +778,44 @@ static irqreturn_t qcom_swrm_irq_handler(int irq, void *dev_id) case SWRM_INTERRUPT_STATUS_EXT_CLK_STOP_WAKEUP: break; default: - dev_err_ratelimited(swrm->dev, + dev_err_ratelimited(ctrl->dev, "%s: SWR unknown interrupt value: %d\n", __func__, value); ret = IRQ_NONE; break; } } - swrm->reg_write(swrm, SWRM_INTERRUPT_CLEAR, intr_sts); - swrm->reg_read(swrm, SWRM_INTERRUPT_STATUS, &intr_sts); - intr_sts_masked = intr_sts & swrm->intr_mask; + ctrl->reg_write(ctrl, ctrl->reg_layout[SWRM_REG_INTERRUPT_CLEAR], + intr_sts); + ctrl->reg_read(ctrl, ctrl->reg_layout[SWRM_REG_INTERRUPT_STATUS], + &intr_sts); + intr_sts_masked = intr_sts & ctrl->intr_mask; } while (intr_sts_masked); - clk_disable_unprepare(swrm->hclk); + clk_disable_unprepare(ctrl->hclk); return ret; } +static bool swrm_wait_for_frame_gen_enabled(struct qcom_swrm_ctrl *ctrl) +{ + int retry = SWRM_LINK_STATUS_RETRY_CNT; + int comp_sts; + + do { + ctrl->reg_read(ctrl, SWRM_COMP_STATUS, &comp_sts); + + if (comp_sts & SWRM_FRM_GEN_ENABLED) + return true; + + usleep_range(500, 510); + } while (retry--); + + dev_err(ctrl->dev, "%s: link status not %s\n", __func__, + comp_sts & SWRM_FRM_GEN_ENABLED ? "connected" : "disconnected"); + + return false; +} + static int qcom_swrm_init(struct qcom_swrm_ctrl *ctrl) { u32 val; @@ -689,18 +833,23 @@ static int qcom_swrm_init(struct qcom_swrm_ctrl *ctrl) ctrl->intr_mask = SWRM_INTERRUPT_STATUS_RMSK; /* Mask soundwire interrupts */ - ctrl->reg_write(ctrl, SWRM_INTERRUPT_MASK_ADDR, - SWRM_INTERRUPT_STATUS_RMSK); + if (ctrl->version < SWRM_VERSION_2_0_0) + ctrl->reg_write(ctrl, ctrl->reg_layout[SWRM_REG_INTERRUPT_MASK_ADDR], + SWRM_INTERRUPT_STATUS_RMSK); /* Configure No pings */ ctrl->reg_read(ctrl, SWRM_MCP_CFG_ADDR, &val); u32p_replace_bits(&val, SWRM_DEF_CMD_NO_PINGS, SWRM_MCP_CFG_MAX_NUM_OF_CMD_NO_PINGS_BMSK); ctrl->reg_write(ctrl, SWRM_MCP_CFG_ADDR, val); - if (ctrl->version >= SWRM_VERSION_1_7_0) { + if (ctrl->version == SWRM_VERSION_1_7_0) { ctrl->reg_write(ctrl, SWRM_LINK_MANAGER_EE, SWRM_EE_CPU); ctrl->reg_write(ctrl, SWRM_MCP_BUS_CTRL, SWRM_MCP_BUS_CLK_START << SWRM_EE_CPU); + } else if (ctrl->version >= SWRM_VERSION_2_0_0) { + ctrl->reg_write(ctrl, SWRM_LINK_MANAGER_EE, SWRM_EE_CPU); + ctrl->reg_write(ctrl, SWRM_V2_0_CLK_CTRL, + SWRM_V2_0_CLK_CTRL_CLK_START); } else { ctrl->reg_write(ctrl, SWRM_MCP_BUS_CTRL, SWRM_MCP_BUS_CLK_START); } @@ -715,16 +864,28 @@ static int qcom_swrm_init(struct qcom_swrm_ctrl *ctrl) SWRM_RD_WR_CMD_RETRIES); } + /* COMP Enable */ + ctrl->reg_write(ctrl, SWRM_COMP_CFG_ADDR, SWRM_COMP_CFG_ENABLE_MSK); + /* Set IRQ to PULSE */ ctrl->reg_write(ctrl, SWRM_COMP_CFG_ADDR, - SWRM_COMP_CFG_IRQ_LEVEL_OR_PULSE_MSK | - SWRM_COMP_CFG_ENABLE_MSK); + SWRM_COMP_CFG_IRQ_LEVEL_OR_PULSE_MSK); + + ctrl->reg_write(ctrl, ctrl->reg_layout[SWRM_REG_INTERRUPT_CLEAR], + 0xFFFFFFFF); /* enable CPU IRQs */ if (ctrl->mmio) { - ctrl->reg_write(ctrl, SWRM_INTERRUPT_CPU_EN, + ctrl->reg_write(ctrl, ctrl->reg_layout[SWRM_REG_INTERRUPT_CPU_EN], SWRM_INTERRUPT_STATUS_RMSK); } + + /* Set IRQ to PULSE */ + ctrl->reg_write(ctrl, SWRM_COMP_CFG_ADDR, + SWRM_COMP_CFG_IRQ_LEVEL_OR_PULSE_MSK | + SWRM_COMP_CFG_ENABLE_MSK); + + swrm_wait_for_frame_gen_enabled(ctrl); ctrl->slave_status = 0; ctrl->reg_read(ctrl, SWRM_COMP_PARAMS, &val); ctrl->rd_fifo_depth = FIELD_GET(SWRM_COMP_PARAMS_RD_FIFO_DEPTH, val); @@ -806,12 +967,20 @@ static int qcom_swrm_transport_params(struct sdw_bus *bus, value = pcfg->off1 << SWRM_DP_PORT_CTRL_OFFSET1_SHFT; value |= pcfg->off2 << SWRM_DP_PORT_CTRL_OFFSET2_SHFT; - value |= pcfg->si; + value |= pcfg->si & 0xff; ret = ctrl->reg_write(ctrl, reg, value); if (ret) goto err; + if (pcfg->si > 0xff) { + value = (pcfg->si >> 8) & 0xff; + reg = SWRM_DP_SAMPLECTRL2_BANK(params->port_num, bank); + ret = ctrl->reg_write(ctrl, reg, value); + if (ret) + goto err; + } + if (pcfg->lane_control != SWR_INVALID_PARAM) { reg = SWRM_DP_PORT_CTRL_2_BANK(params->port_num, bank); value = pcfg->lane_control; @@ -1090,11 +1259,12 @@ static int qcom_swrm_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *codec_dai; int ret, i; - ret = pm_runtime_resume_and_get(ctrl->dev); + ret = pm_runtime_get_sync(ctrl->dev); if (ret < 0 && ret != -EACCES) { dev_err_ratelimited(ctrl->dev, - "pm_runtime_resume_and_get failed in %s, ret %d\n", + "pm_runtime_get_sync failed in %s, ret %d\n", __func__, ret); + pm_runtime_put_noidle(ctrl->dev); return ret; } @@ -1132,6 +1302,7 @@ static void qcom_swrm_shutdown(struct snd_pcm_substream *substream, { struct qcom_swrm_ctrl *ctrl = dev_get_drvdata(dai->dev); + swrm_wait_for_wr_fifo_done(ctrl); sdw_release_stream(ctrl->sruntime[dai->id]); ctrl->sruntime[dai->id] = NULL; pm_runtime_mark_last_busy(ctrl->dev); @@ -1194,7 +1365,7 @@ static int qcom_swrm_get_port_config(struct qcom_swrm_ctrl *ctrl) struct device_node *np = ctrl->dev->of_node; u8 off1[QCOM_SDW_MAX_PORTS]; u8 off2[QCOM_SDW_MAX_PORTS]; - u8 si[QCOM_SDW_MAX_PORTS]; + u16 si[QCOM_SDW_MAX_PORTS]; u8 bp_mode[QCOM_SDW_MAX_PORTS] = { 0, }; u8 hstart[QCOM_SDW_MAX_PORTS]; u8 hstop[QCOM_SDW_MAX_PORTS]; @@ -1202,6 +1373,7 @@ static int qcom_swrm_get_port_config(struct qcom_swrm_ctrl *ctrl) u8 blk_group_count[QCOM_SDW_MAX_PORTS]; u8 lane_control[QCOM_SDW_MAX_PORTS]; int i, ret, nports, val; + bool si_16 = false; ctrl->reg_read(ctrl, SWRM_COMP_PARAMS, &val); @@ -1245,9 +1417,14 @@ static int qcom_swrm_get_port_config(struct qcom_swrm_ctrl *ctrl) return ret; ret = of_property_read_u8_array(np, "qcom,ports-sinterval-low", - si, nports); - if (ret) - return ret; + (u8 *)si, nports); + if (ret) { + ret = of_property_read_u16_array(np, "qcom,ports-sinterval", + si, nports); + if (ret) + return ret; + si_16 = true; + } ret = of_property_read_u8_array(np, "qcom,ports-block-pack-mode", bp_mode, nports); @@ -1275,7 +1452,10 @@ static int qcom_swrm_get_port_config(struct qcom_swrm_ctrl *ctrl) for (i = 0; i < nports; i++) { /* Valid port number range is from 1-14 */ - ctrl->pconfig[i + 1].si = si[i]; + if (si_16) + ctrl->pconfig[i + 1].si = si[i]; + else + ctrl->pconfig[i + 1].si = ((u8 *)si)[i]; ctrl->pconfig[i + 1].off1 = off1[i]; ctrl->pconfig[i + 1].off2 = off2[i]; ctrl->pconfig[i + 1].bp_mode = bp_mode[i]; @@ -1292,23 +1472,24 @@ static int qcom_swrm_get_port_config(struct qcom_swrm_ctrl *ctrl) #ifdef CONFIG_DEBUG_FS static int swrm_reg_show(struct seq_file *s_file, void *data) { - struct qcom_swrm_ctrl *swrm = s_file->private; + struct qcom_swrm_ctrl *ctrl = s_file->private; int reg, reg_val, ret; - ret = pm_runtime_resume_and_get(swrm->dev); + ret = pm_runtime_get_sync(ctrl->dev); if (ret < 0 && ret != -EACCES) { - dev_err_ratelimited(swrm->dev, - "pm_runtime_resume_and_get failed in %s, ret %d\n", + dev_err_ratelimited(ctrl->dev, + "pm_runtime_get_sync failed in %s, ret %d\n", __func__, ret); + pm_runtime_put_noidle(ctrl->dev); return ret; } - for (reg = 0; reg <= SWR_MSTR_MAX_REG_ADDR; reg += 4) { - swrm->reg_read(swrm, reg, ®_val); + for (reg = 0; reg <= ctrl->max_reg; reg += 4) { + ctrl->reg_read(ctrl, reg, ®_val); seq_printf(s_file, "0x%.3x: 0x%.2x\n", reg, reg_val); } - pm_runtime_mark_last_busy(swrm->dev); - pm_runtime_put_autosuspend(swrm->dev); + pm_runtime_mark_last_busy(ctrl->dev); + pm_runtime_put_autosuspend(ctrl->dev); return 0; @@ -1331,6 +1512,8 @@ static int qcom_swrm_probe(struct platform_device *pdev) return -ENOMEM; data = of_device_get_match_data(dev); + ctrl->max_reg = data->max_reg; + ctrl->reg_layout = data->reg_layout; ctrl->rows_index = sdw_find_row_index(data->default_rows); ctrl->cols_index = sdw_find_col_index(data->default_cols); #if IS_REACHABLE(CONFIG_SLIMBUS) @@ -1454,15 +1637,6 @@ static int qcom_swrm_probe(struct platform_device *pdev) pm_runtime_set_active(dev); pm_runtime_enable(dev); - /* Clk stop is not supported on WSA Soundwire masters */ - if (ctrl->version <= SWRM_VERSION_1_3_0) { - ctrl->clock_stop_not_supported = true; - } else { - ctrl->reg_read(ctrl, SWRM_COMP_MASTER_ID, &val); - if (val == MASTER_ID_WSA) - ctrl->clock_stop_not_supported = true; - } - #ifdef CONFIG_DEBUG_FS ctrl->debugfs = debugfs_create_dir("qualcomm-sdw", ctrl->bus.debugfs); debugfs_create_file("qualcomm-registers", 0400, ctrl->debugfs, ctrl, @@ -1489,26 +1663,6 @@ static int qcom_swrm_remove(struct platform_device *pdev) return 0; } -static bool swrm_wait_for_frame_gen_enabled(struct qcom_swrm_ctrl *swrm) -{ - int retry = SWRM_LINK_STATUS_RETRY_CNT; - int comp_sts; - - do { - swrm->reg_read(swrm, SWRM_COMP_STATUS, &comp_sts); - - if (comp_sts & SWRM_FRM_GEN_ENABLED) - return true; - - usleep_range(500, 510); - } while (retry--); - - dev_err(swrm->dev, "%s: link status not %s\n", __func__, - comp_sts & SWRM_FRM_GEN_ENABLED ? "connected" : "disconnected"); - - return false; -} - static int __maybe_unused swrm_runtime_resume(struct device *dev) { struct qcom_swrm_ctrl *ctrl = dev_get_drvdata(dev); @@ -1540,19 +1694,27 @@ static int __maybe_unused swrm_runtime_resume(struct device *dev) } else { reset_control_reset(ctrl->audio_cgcr); - if (ctrl->version >= SWRM_VERSION_1_7_0) { + if (ctrl->version == SWRM_VERSION_1_7_0) { ctrl->reg_write(ctrl, SWRM_LINK_MANAGER_EE, SWRM_EE_CPU); ctrl->reg_write(ctrl, SWRM_MCP_BUS_CTRL, SWRM_MCP_BUS_CLK_START << SWRM_EE_CPU); + } else if (ctrl->version >= SWRM_VERSION_2_0_0) { + ctrl->reg_write(ctrl, SWRM_LINK_MANAGER_EE, SWRM_EE_CPU); + ctrl->reg_write(ctrl, SWRM_V2_0_CLK_CTRL, + SWRM_V2_0_CLK_CTRL_CLK_START); } else { ctrl->reg_write(ctrl, SWRM_MCP_BUS_CTRL, SWRM_MCP_BUS_CLK_START); } - ctrl->reg_write(ctrl, SWRM_INTERRUPT_CLEAR, + ctrl->reg_write(ctrl, ctrl->reg_layout[SWRM_REG_INTERRUPT_CLEAR], SWRM_INTERRUPT_STATUS_MASTER_CLASH_DET); ctrl->intr_mask |= SWRM_INTERRUPT_STATUS_MASTER_CLASH_DET; - ctrl->reg_write(ctrl, SWRM_INTERRUPT_MASK_ADDR, ctrl->intr_mask); - ctrl->reg_write(ctrl, SWRM_INTERRUPT_CPU_EN, ctrl->intr_mask); + if (ctrl->version < SWRM_VERSION_2_0_0) + ctrl->reg_write(ctrl, + ctrl->reg_layout[SWRM_REG_INTERRUPT_MASK_ADDR], + ctrl->intr_mask); + ctrl->reg_write(ctrl, ctrl->reg_layout[SWRM_REG_INTERRUPT_CPU_EN], + ctrl->intr_mask); usleep_range(100, 105); if (!swrm_wait_for_frame_gen_enabled(ctrl)) @@ -1571,11 +1733,16 @@ static int __maybe_unused swrm_runtime_suspend(struct device *dev) struct qcom_swrm_ctrl *ctrl = dev_get_drvdata(dev); int ret; + swrm_wait_for_wr_fifo_done(ctrl); if (!ctrl->clock_stop_not_supported) { /* Mask bus clash interrupt */ ctrl->intr_mask &= ~SWRM_INTERRUPT_STATUS_MASTER_CLASH_DET; - ctrl->reg_write(ctrl, SWRM_INTERRUPT_MASK_ADDR, ctrl->intr_mask); - ctrl->reg_write(ctrl, SWRM_INTERRUPT_CPU_EN, ctrl->intr_mask); + if (ctrl->version < SWRM_VERSION_2_0_0) + ctrl->reg_write(ctrl, + ctrl->reg_layout[SWRM_REG_INTERRUPT_MASK_ADDR], + ctrl->intr_mask); + ctrl->reg_write(ctrl, ctrl->reg_layout[SWRM_REG_INTERRUPT_CPU_EN], + ctrl->intr_mask); /* Prepare slaves for clock stop */ ret = sdw_bus_prep_clk_stop(&ctrl->bus); if (ret < 0 && ret != -ENODATA) { @@ -1611,6 +1778,7 @@ static const struct of_device_id qcom_swrm_of_match[] = { { .compatible = "qcom,soundwire-v1.5.1", .data = &swrm_v1_5_data }, { .compatible = "qcom,soundwire-v1.6.0", .data = &swrm_v1_6_data }, { .compatible = "qcom,soundwire-v1.7.0", .data = &swrm_v1_5_data }, + { .compatible = "qcom,soundwire-v2.0.0", .data = &swrm_v2_0_data }, {/* sentinel */}, }; diff --git a/drivers/soundwire/stream.c b/drivers/soundwire/stream.c index 379228f2218696ec42801fcbb8a080dc6b87f850..d77a8a0d42c8d33ae04cc9b1d52f401e716dd989 100644 --- a/drivers/soundwire/stream.c +++ b/drivers/soundwire/stream.c @@ -1150,7 +1150,8 @@ static struct sdw_master_runtime *sdw_master_rt_alloc(struct sdw_bus *bus, struct sdw_stream_runtime *stream) { - struct sdw_master_runtime *m_rt; + struct sdw_master_runtime *m_rt, *walk_m_rt; + struct list_head *insert_after; m_rt = kzalloc(sizeof(*m_rt), GFP_KERNEL); if (!m_rt) @@ -1159,7 +1160,20 @@ static struct sdw_master_runtime /* Initialization of Master runtime handle */ INIT_LIST_HEAD(&m_rt->port_list); INIT_LIST_HEAD(&m_rt->slave_rt_list); - list_add_tail(&m_rt->stream_node, &stream->master_list); + + /* + * Add in order of bus id so that when taking the bus_lock + * of multiple buses they will always be taken in the same + * order to prevent a mutex deadlock. + */ + insert_after = &stream->master_list; + list_for_each_entry_reverse(walk_m_rt, &stream->master_list, stream_node) { + if (walk_m_rt->bus->id < bus->id) { + insert_after = &walk_m_rt->stream_node; + break; + } + } + list_add(&m_rt->stream_node, insert_after); list_add_tail(&m_rt->bus_node, &bus->m_rt_list); @@ -1338,7 +1352,7 @@ static int _sdw_prepare_stream(struct sdw_stream_runtime *stream, bool update_params) { struct sdw_master_runtime *m_rt; - struct sdw_bus *bus = NULL; + struct sdw_bus *bus; struct sdw_master_prop *prop; struct sdw_bus_params params; int ret; @@ -1355,25 +1369,23 @@ static int _sdw_prepare_stream(struct sdw_stream_runtime *stream, return -EINVAL; } - if (!update_params) - goto program_params; - - /* Increment cumulative bus bandwidth */ - /* TODO: Update this during Device-Device support */ - bus->params.bandwidth += m_rt->stream->params.rate * - m_rt->ch_count * m_rt->stream->params.bps; + if (update_params) { + /* Increment cumulative bus bandwidth */ + /* TODO: Update this during Device-Device support */ + bus->params.bandwidth += m_rt->stream->params.rate * + m_rt->ch_count * m_rt->stream->params.bps; - /* Compute params */ - if (bus->compute_params) { - ret = bus->compute_params(bus); - if (ret < 0) { - dev_err(bus->dev, "Compute params failed: %d\n", - ret); - goto restore_params; + /* Compute params */ + if (bus->compute_params) { + ret = bus->compute_params(bus); + if (ret < 0) { + dev_err(bus->dev, "Compute params failed: %d\n", + ret); + goto restore_params; + } } } -program_params: /* Program params */ ret = sdw_program_params(bus, true); if (ret < 0) { @@ -1382,11 +1394,6 @@ static int _sdw_prepare_stream(struct sdw_stream_runtime *stream, } } - if (!bus) { - pr_err("Configuration error in %s\n", __func__); - return -EINVAL; - } - ret = do_bank_switch(stream); if (ret < 0) { pr_err("%s: do_bank_switch failed: %d\n", __func__, ret); @@ -1467,7 +1474,7 @@ EXPORT_SYMBOL(sdw_prepare_stream); static int _sdw_enable_stream(struct sdw_stream_runtime *stream) { struct sdw_master_runtime *m_rt; - struct sdw_bus *bus = NULL; + struct sdw_bus *bus; int ret; /* Enable Master(s) and Slave(s) port(s) associated with stream */ @@ -1490,11 +1497,6 @@ static int _sdw_enable_stream(struct sdw_stream_runtime *stream) } } - if (!bus) { - pr_err("Configuration error in %s\n", __func__); - return -EINVAL; - } - ret = do_bank_switch(stream); if (ret < 0) { pr_err("%s: do_bank_switch failed: %d\n", __func__, ret); @@ -1864,7 +1866,7 @@ int sdw_stream_add_master(struct sdw_bus *bus, struct sdw_stream_runtime *stream) { struct sdw_master_runtime *m_rt; - bool alloc_master_rt = true; + bool alloc_master_rt = false; int ret; mutex_lock(&bus->bus_lock); @@ -1886,30 +1888,25 @@ int sdw_stream_add_master(struct sdw_bus *bus, * it first), if so skip allocation and go to configuration */ m_rt = sdw_master_rt_find(bus, stream); - if (m_rt) { - alloc_master_rt = false; - goto skip_alloc_master_rt; - } - - m_rt = sdw_master_rt_alloc(bus, stream); if (!m_rt) { - dev_err(bus->dev, "%s: Master runtime alloc failed for stream:%s\n", - __func__, stream->name); - ret = -ENOMEM; - goto unlock; - } -skip_alloc_master_rt: - - if (sdw_master_port_allocated(m_rt)) - goto skip_alloc_master_port; + m_rt = sdw_master_rt_alloc(bus, stream); + if (!m_rt) { + dev_err(bus->dev, "%s: Master runtime alloc failed for stream:%s\n", + __func__, stream->name); + ret = -ENOMEM; + goto unlock; + } - ret = sdw_master_port_alloc(m_rt, num_ports); - if (ret) - goto alloc_error; + alloc_master_rt = true; + } - stream->m_rt_count++; + if (!sdw_master_port_allocated(m_rt)) { + ret = sdw_master_port_alloc(m_rt, num_ports); + if (ret) + goto alloc_error; -skip_alloc_master_port: + stream->m_rt_count++; + } ret = sdw_master_rt_config(m_rt, stream_config); if (ret < 0) @@ -1990,8 +1987,8 @@ int sdw_stream_add_slave(struct sdw_slave *slave, { struct sdw_slave_runtime *s_rt; struct sdw_master_runtime *m_rt; - bool alloc_master_rt = true; - bool alloc_slave_rt = true; + bool alloc_master_rt = false; + bool alloc_slave_rt = false; int ret; @@ -2002,47 +1999,41 @@ int sdw_stream_add_slave(struct sdw_slave *slave, * and go to configuration */ m_rt = sdw_master_rt_find(slave->bus, stream); - if (m_rt) { - alloc_master_rt = false; - goto skip_alloc_master_rt; - } - - /* - * If this API is invoked by Slave first then m_rt is not valid. - * So, allocate m_rt and add Slave to it. - */ - m_rt = sdw_master_rt_alloc(slave->bus, stream); if (!m_rt) { - dev_err(&slave->dev, "%s: Master runtime alloc failed for stream:%s\n", - __func__, stream->name); - ret = -ENOMEM; - goto unlock; - } + /* + * If this API is invoked by Slave first then m_rt is not valid. + * So, allocate m_rt and add Slave to it. + */ + m_rt = sdw_master_rt_alloc(slave->bus, stream); + if (!m_rt) { + dev_err(&slave->dev, "%s: Master runtime alloc failed for stream:%s\n", + __func__, stream->name); + ret = -ENOMEM; + goto unlock; + } -skip_alloc_master_rt: - s_rt = sdw_slave_rt_find(slave, stream); - if (s_rt) { - alloc_slave_rt = false; - goto skip_alloc_slave_rt; + alloc_master_rt = true; } - s_rt = sdw_slave_rt_alloc(slave, m_rt); + s_rt = sdw_slave_rt_find(slave, stream); if (!s_rt) { - dev_err(&slave->dev, "Slave runtime alloc failed for stream:%s\n", stream->name); - alloc_slave_rt = false; - ret = -ENOMEM; - goto alloc_error; - } + s_rt = sdw_slave_rt_alloc(slave, m_rt); + if (!s_rt) { + dev_err(&slave->dev, "Slave runtime alloc failed for stream:%s\n", + stream->name); + ret = -ENOMEM; + goto alloc_error; + } -skip_alloc_slave_rt: - if (sdw_slave_port_allocated(s_rt)) - goto skip_port_alloc; + alloc_slave_rt = true; + } - ret = sdw_slave_port_alloc(slave, s_rt, num_ports); - if (ret) - goto alloc_error; + if (!sdw_slave_port_allocated(s_rt)) { + ret = sdw_slave_port_alloc(slave, s_rt, num_ports); + if (ret) + goto alloc_error; + } -skip_port_alloc: ret = sdw_master_rt_config(m_rt, stream_config); if (ret) goto unlock; diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 3de2ebe8294aa5110539a03e9a0d822f664f03dc..8962b2557615653bfc3d15d1cb4f35c9ddb689a4 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -825,6 +825,12 @@ config SPI_RSPI help SPI driver for Renesas RSPI and QSPI blocks. +config SPI_RZV2M_CSI + tristate "Renesas RZ/V2M CSI controller" + depends on ARCH_RENESAS || COMPILE_TEST + help + SPI driver for Renesas RZ/V2M Clocked Serial Interface (CSI) + config SPI_QCOM_QSPI tristate "QTI QSPI controller" depends on ARCH_QCOM || COMPILE_TEST @@ -936,6 +942,7 @@ config SPI_SPRD_ADI config SPI_STM32 tristate "STMicroelectronics STM32 SPI controller" depends on ARCH_STM32 || COMPILE_TEST + select SPI_SLAVE help SPI driver for STMicroelectronics STM32 SoCs. diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index 28c4817a8a74a0a844cc1edf40c75c64ec991e37..080c2c1b3ec193fff1df182f0c4c8534fc1a30b7 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -113,6 +113,7 @@ obj-$(CONFIG_SPI_RB4XX) += spi-rb4xx.o obj-$(CONFIG_MACH_REALTEK_RTL) += spi-realtek-rtl.o obj-$(CONFIG_SPI_RPCIF) += spi-rpc-if.o obj-$(CONFIG_SPI_RSPI) += spi-rspi.o +obj-$(CONFIG_SPI_RZV2M_CSI) += spi-rzv2m-csi.o obj-$(CONFIG_SPI_S3C64XX) += spi-s3c64xx.o obj-$(CONFIG_SPI_SC18IS602) += spi-sc18is602.o obj-$(CONFIG_SPI_SH) += spi-sh.o diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c index 7f06305e16cbc60fc3fa1d83316d818770c29f49..152cd677340381069d52781a196989c66fc488d1 100644 --- a/drivers/spi/spi-atmel.c +++ b/drivers/spi/spi-atmel.c @@ -233,7 +233,8 @@ */ #define DMA_MIN_BYTES 16 -#define SPI_DMA_TIMEOUT (msecs_to_jiffies(1000)) +#define SPI_DMA_MIN_TIMEOUT (msecs_to_jiffies(1000)) +#define SPI_DMA_TIMEOUT_PER_10K (msecs_to_jiffies(4)) #define AUTOSUSPEND_TIMEOUT 2000 @@ -1279,7 +1280,8 @@ static int atmel_spi_one_transfer(struct spi_controller *host, struct atmel_spi_device *asd; int timeout; int ret; - unsigned long dma_timeout; + unsigned int dma_timeout; + long ret_timeout; as = spi_controller_get_devdata(host); @@ -1333,11 +1335,13 @@ static int atmel_spi_one_transfer(struct spi_controller *host, atmel_spi_unlock(as); } - dma_timeout = wait_for_completion_timeout(&as->xfer_completion, - SPI_DMA_TIMEOUT); - if (WARN_ON(dma_timeout == 0)) { - dev_err(&spi->dev, "spi transfer timeout\n"); - as->done_status = -EIO; + dma_timeout = msecs_to_jiffies(spi_controller_xfer_timeout(host, xfer)); + ret_timeout = wait_for_completion_interruptible_timeout(&as->xfer_completion, + dma_timeout); + if (ret_timeout <= 0) { + dev_err(&spi->dev, "spi transfer %s\n", + !ret_timeout ? "timeout" : "canceled"); + as->done_status = ret_timeout < 0 ? ret_timeout : -EIO; } if (as->done_status) diff --git a/drivers/spi/spi-bcm-qspi.c b/drivers/spi/spi-bcm-qspi.c index 6b46a3b67c41695f621c522ede3f25d7cbee82aa..d91dfbe47aa50fac663b3fec9f958a7fd7f1dff8 100644 --- a/drivers/spi/spi-bcm-qspi.c +++ b/drivers/spi/spi-bcm-qspi.c @@ -1543,13 +1543,9 @@ int bcm_qspi_probe(struct platform_device *pdev, res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mspi"); - if (res) { - qspi->base[MSPI] = devm_ioremap_resource(dev, res); - if (IS_ERR(qspi->base[MSPI])) - return PTR_ERR(qspi->base[MSPI]); - } else { - return 0; - } + qspi->base[MSPI] = devm_ioremap_resource(dev, res); + if (IS_ERR(qspi->base[MSPI])) + return PTR_ERR(qspi->base[MSPI]); res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "bspi"); if (res) { diff --git a/drivers/spi/spi-bcm63xx-hsspi.c b/drivers/spi/spi-bcm63xx-hsspi.c index ee2528dad02df03b5c72814ad0b3009676072c6a..9e218e143263cbd6c8b28eb14e65838cabb95d35 100644 --- a/drivers/spi/spi-bcm63xx-hsspi.c +++ b/drivers/spi/spi-bcm63xx-hsspi.c @@ -2,7 +2,7 @@ * Broadcom BCM63XX High Speed SPI Controller driver * * Copyright 2000-2010 Broadcom Corporation - * Copyright 2012-2013 Jonas Gorski + * Copyright 2012-2013 Jonas Gorski * * Licensed under the GNU/GPL. See COPYING for details. */ diff --git a/drivers/spi/spi-bcm63xx.c b/drivers/spi/spi-bcm63xx.c index 9aecb77c3d892da8422a01d511e871f713d5438a..07b5b71b2352031b1b9f3bfd69c0be2f6f95862a 100644 --- a/drivers/spi/spi-bcm63xx.c +++ b/drivers/spi/spi-bcm63xx.c @@ -126,7 +126,7 @@ enum bcm63xx_regs_spi { SPI_MSG_DATA_SIZE, }; -#define BCM63XX_SPI_MAX_PREPEND 15 +#define BCM63XX_SPI_MAX_PREPEND 7 #define BCM63XX_SPI_MAX_CS 8 #define BCM63XX_SPI_BUS_NUM 0 diff --git a/drivers/spi/spi-bcmbca-hsspi.c b/drivers/spi/spi-bcmbca-hsspi.c index 8cbd0161978915d64cbfbc4836719d0710fbc7b4..ca1b4741e9f4559a9fb5f9505f5b797d39fbc6a2 100644 --- a/drivers/spi/spi-bcmbca-hsspi.c +++ b/drivers/spi/spi-bcmbca-hsspi.c @@ -3,7 +3,7 @@ * Broadcom BCMBCA High Speed SPI Controller driver * * Copyright 2000-2010 Broadcom Corporation - * Copyright 2012-2013 Jonas Gorski + * Copyright 2012-2013 Jonas Gorski * Copyright 2019-2022 Broadcom Ltd */ diff --git a/drivers/spi/spi-cadence-quadspi.c b/drivers/spi/spi-cadence-quadspi.c index 32449bef4415ad889931a442dba44df016b20d85..abf10f92415dca04c4707c21c404d8322cf466b6 100644 --- a/drivers/spi/spi-cadence-quadspi.c +++ b/drivers/spi/spi-cadence-quadspi.c @@ -40,6 +40,7 @@ #define CQSPI_SUPPORT_EXTERNAL_DMA BIT(2) #define CQSPI_NO_SUPPORT_WR_COMPLETION BIT(3) #define CQSPI_SLOW_SRAM BIT(4) +#define CQSPI_NEEDS_APB_AHB_HAZARD_WAR BIT(5) /* Capabilities */ #define CQSPI_SUPPORTS_OCTAL BIT(0) @@ -90,6 +91,7 @@ struct cqspi_st { u32 pd_dev_id; bool wr_completion; bool slow_sram; + bool apb_ahb_hazard; }; struct cqspi_driver_platdata { @@ -1027,6 +1029,13 @@ static int cqspi_indirect_write_execute(struct cqspi_flash_pdata *f_pdata, if (cqspi->wr_delay) ndelay(cqspi->wr_delay); + /* + * If a hazard exists between the APB and AHB interfaces, perform a + * dummy readback from the controller to ensure synchronization. + */ + if (cqspi->apb_ahb_hazard) + readl(reg_base + CQSPI_REG_INDIRECTWR); + while (remaining > 0) { size_t write_words, mod_bytes; @@ -1754,6 +1763,8 @@ static int cqspi_probe(struct platform_device *pdev) cqspi->wr_completion = false; if (ddata->quirks & CQSPI_SLOW_SRAM) cqspi->slow_sram = true; + if (ddata->quirks & CQSPI_NEEDS_APB_AHB_HAZARD_WAR) + cqspi->apb_ahb_hazard = true; if (of_device_is_compatible(pdev->dev.of_node, "xlnx,versal-ospi-1.0")) { @@ -1888,6 +1899,10 @@ static const struct cqspi_driver_platdata jh7110_qspi = { .quirks = CQSPI_DISABLE_DAC_MODE, }; +static const struct cqspi_driver_platdata pensando_cdns_qspi = { + .quirks = CQSPI_NEEDS_APB_AHB_HAZARD_WAR | CQSPI_DISABLE_DAC_MODE, +}; + static const struct of_device_id cqspi_dt_ids[] = { { .compatible = "cdns,qspi-nor", @@ -1917,6 +1932,10 @@ static const struct of_device_id cqspi_dt_ids[] = { .compatible = "starfive,jh7110-qspi", .data = &jh7110_qspi, }, + { + .compatible = "amd,pensando-elba-qspi", + .data = &pensando_cdns_qspi, + }, { /* end of table */ } }; diff --git a/drivers/spi/spi-cadence.c b/drivers/spi/spi-cadence.c index 26e6633693196ef20ae95b93114627a9d97a2e7b..de8fe3c5becbb6b4984986d1886214959eedb8db 100644 --- a/drivers/spi/spi-cadence.c +++ b/drivers/spi/spi-cadence.c @@ -102,6 +102,7 @@ * @regs: Virtual address of the SPI controller registers * @ref_clk: Pointer to the peripheral clock * @pclk: Pointer to the APB clock + * @clk_rate: Reference clock frequency, taken from @ref_clk * @speed_hz: Current SPI bus clock speed in Hz * @txbuf: Pointer to the TX buffer * @rxbuf: Pointer to the RX buffer diff --git a/drivers/spi/spi-dw-core.c b/drivers/spi/spi-dw-core.c index ae3108c70f508b26d9aeb3a48dd37a8551597ba6..a8ba41ad45412e7dc0cfcfd733ca2ab7f5263db7 100644 --- a/drivers/spi/spi-dw-core.c +++ b/drivers/spi/spi-dw-core.c @@ -57,21 +57,17 @@ static const struct debugfs_reg32 dw_spi_dbgfs_regs[] = { DW_SPI_DBGFS_REG("RX_SAMPLE_DLY", DW_SPI_RX_SAMPLE_DLY), }; -static int dw_spi_debugfs_init(struct dw_spi *dws) +static void dw_spi_debugfs_init(struct dw_spi *dws) { char name[32]; snprintf(name, 32, "dw_spi%d", dws->master->bus_num); dws->debugfs = debugfs_create_dir(name, NULL); - if (!dws->debugfs) - return -ENOMEM; dws->regset.regs = dw_spi_dbgfs_regs; dws->regset.nregs = ARRAY_SIZE(dw_spi_dbgfs_regs); dws->regset.base = dws->regs; debugfs_create_regset32("registers", 0400, dws->debugfs, &dws->regset); - - return 0; } static void dw_spi_debugfs_remove(struct dw_spi *dws) @@ -80,9 +76,8 @@ static void dw_spi_debugfs_remove(struct dw_spi *dws) } #else -static inline int dw_spi_debugfs_init(struct dw_spi *dws) +static inline void dw_spi_debugfs_init(struct dw_spi *dws) { - return 0; } static inline void dw_spi_debugfs_remove(struct dw_spi *dws) @@ -426,7 +421,10 @@ static int dw_spi_transfer_one(struct spi_controller *master, int ret; dws->dma_mapped = 0; - dws->n_bytes = DIV_ROUND_UP(transfer->bits_per_word, BITS_PER_BYTE); + dws->n_bytes = + roundup_pow_of_two(DIV_ROUND_UP(transfer->bits_per_word, + BITS_PER_BYTE)); + dws->tx = (void *)transfer->tx_buf; dws->tx_len = transfer->len / dws->n_bytes; dws->rx = transfer->rx_buf; diff --git a/drivers/spi/spi-dw-dma.c b/drivers/spi/spi-dw-dma.c index ababb910b3914c84e88998d16b79ab6444eaac18..df819652901a499b1abeb328061da621319a3ca8 100644 --- a/drivers/spi/spi-dw-dma.c +++ b/drivers/spi/spi-dw-dma.c @@ -72,12 +72,22 @@ static void dw_spi_dma_maxburst_init(struct dw_spi *dws) dw_writel(dws, DW_SPI_DMATDLR, dws->txburst); } -static void dw_spi_dma_sg_burst_init(struct dw_spi *dws) +static int dw_spi_dma_caps_init(struct dw_spi *dws) { - struct dma_slave_caps tx = {0}, rx = {0}; + struct dma_slave_caps tx, rx; + int ret; + + ret = dma_get_slave_caps(dws->txchan, &tx); + if (ret) + return ret; - dma_get_slave_caps(dws->txchan, &tx); - dma_get_slave_caps(dws->rxchan, &rx); + ret = dma_get_slave_caps(dws->rxchan, &rx); + if (ret) + return ret; + + if (!(tx.directions & BIT(DMA_MEM_TO_DEV) && + rx.directions & BIT(DMA_DEV_TO_MEM))) + return -ENXIO; if (tx.max_sg_burst > 0 && rx.max_sg_burst > 0) dws->dma_sg_burst = min(tx.max_sg_burst, rx.max_sg_burst); @@ -87,6 +97,15 @@ static void dw_spi_dma_sg_burst_init(struct dw_spi *dws) dws->dma_sg_burst = rx.max_sg_burst; else dws->dma_sg_burst = 0; + + /* + * Assuming both channels belong to the same DMA controller hence the + * peripheral side address width capabilities most likely would be + * the same. + */ + dws->dma_addr_widths = tx.dst_addr_widths & rx.src_addr_widths; + + return 0; } static int dw_spi_dma_init_mfld(struct device *dev, struct dw_spi *dws) @@ -95,6 +114,7 @@ static int dw_spi_dma_init_mfld(struct device *dev, struct dw_spi *dws) struct dw_dma_slave dma_rx = { .src_id = 0 }, *rx = &dma_rx; struct pci_dev *dma_dev; dma_cap_mask_t mask; + int ret = -EBUSY; /* * Get pci device for DMA controller, currently it could only @@ -124,20 +144,25 @@ static int dw_spi_dma_init_mfld(struct device *dev, struct dw_spi *dws) init_completion(&dws->dma_completion); - dw_spi_dma_maxburst_init(dws); + ret = dw_spi_dma_caps_init(dws); + if (ret) + goto free_txchan; - dw_spi_dma_sg_burst_init(dws); + dw_spi_dma_maxburst_init(dws); pci_dev_put(dma_dev); return 0; +free_txchan: + dma_release_channel(dws->txchan); + dws->txchan = NULL; free_rxchan: dma_release_channel(dws->rxchan); dws->rxchan = NULL; err_exit: pci_dev_put(dma_dev); - return -EBUSY; + return ret; } static int dw_spi_dma_init_generic(struct device *dev, struct dw_spi *dws) @@ -163,12 +188,17 @@ static int dw_spi_dma_init_generic(struct device *dev, struct dw_spi *dws) init_completion(&dws->dma_completion); - dw_spi_dma_maxburst_init(dws); + ret = dw_spi_dma_caps_init(dws); + if (ret) + goto free_txchan; - dw_spi_dma_sg_burst_init(dws); + dw_spi_dma_maxburst_init(dws); return 0; +free_txchan: + dma_release_channel(dws->txchan); + dws->txchan = NULL; free_rxchan: dma_release_channel(dws->rxchan); dws->rxchan = NULL; @@ -198,22 +228,32 @@ static irqreturn_t dw_spi_dma_transfer_handler(struct dw_spi *dws) return IRQ_HANDLED; } +static enum dma_slave_buswidth dw_spi_dma_convert_width(u8 n_bytes) +{ + switch (n_bytes) { + case 1: + return DMA_SLAVE_BUSWIDTH_1_BYTE; + case 2: + return DMA_SLAVE_BUSWIDTH_2_BYTES; + case 4: + return DMA_SLAVE_BUSWIDTH_4_BYTES; + default: + return DMA_SLAVE_BUSWIDTH_UNDEFINED; + } +} + static bool dw_spi_can_dma(struct spi_controller *master, struct spi_device *spi, struct spi_transfer *xfer) { struct dw_spi *dws = spi_controller_get_devdata(master); + enum dma_slave_buswidth dma_bus_width; - return xfer->len > dws->fifo_len; -} + if (xfer->len <= dws->fifo_len) + return false; -static enum dma_slave_buswidth dw_spi_dma_convert_width(u8 n_bytes) -{ - if (n_bytes == 1) - return DMA_SLAVE_BUSWIDTH_1_BYTE; - else if (n_bytes == 2) - return DMA_SLAVE_BUSWIDTH_2_BYTES; + dma_bus_width = dw_spi_dma_convert_width(dws->n_bytes); - return DMA_SLAVE_BUSWIDTH_UNDEFINED; + return dws->dma_addr_widths & BIT(dma_bus_width); } static int dw_spi_dma_wait(struct dw_spi *dws, unsigned int len, u32 speed) diff --git a/drivers/spi/spi-dw-mmio.c b/drivers/spi/spi-dw-mmio.c index 15f5e9cb54ad45717c61e21ab8005b79d53307b0..a963bc96c223f97a0fd3dd48ff5e9f6c6024e936 100644 --- a/drivers/spi/spi-dw-mmio.c +++ b/drivers/spi/spi-dw-mmio.c @@ -236,6 +236,24 @@ static int dw_spi_intel_init(struct platform_device *pdev, return 0; } +/* + * DMA-based mem ops are not configured for this device and are not tested. + */ +static int dw_spi_mountevans_imc_init(struct platform_device *pdev, + struct dw_spi_mmio *dwsmmio) +{ + /* + * The Intel Mount Evans SoC's Integrated Management Complex DW + * apb_ssi_v4.02a controller has an errata where a full TX FIFO can + * result in data corruption. The suggested workaround is to never + * completely fill the FIFO. The TX FIFO has a size of 32 so the + * fifo_len is set to 31. + */ + dwsmmio->dws.fifo_len = 31; + + return 0; +} + static int dw_spi_canaan_k210_init(struct platform_device *pdev, struct dw_spi_mmio *dwsmmio) { @@ -405,6 +423,10 @@ static const struct of_device_id dw_spi_mmio_of_match[] = { { .compatible = "snps,dwc-ssi-1.01a", .data = dw_spi_hssi_init}, { .compatible = "intel,keembay-ssi", .data = dw_spi_intel_init}, { .compatible = "intel,thunderbay-ssi", .data = dw_spi_intel_init}, + { + .compatible = "intel,mountevans-imc-ssi", + .data = dw_spi_mountevans_imc_init, + }, { .compatible = "microchip,sparx5-spi", dw_spi_mscc_sparx5_init}, { .compatible = "canaan,k210-spi", dw_spi_canaan_k210_init}, { .compatible = "amd,pensando-elba-spi", .data = dw_spi_elba_init}, diff --git a/drivers/spi/spi-dw.h b/drivers/spi/spi-dw.h index 9e8eb2b52d5c79695274fe09b73e98f5447f9ab5..3962e6dcf8800cd000876adccecfaa254440dbfd 100644 --- a/drivers/spi/spi-dw.h +++ b/drivers/spi/spi-dw.h @@ -190,6 +190,7 @@ struct dw_spi { struct dma_chan *rxchan; u32 rxburst; u32 dma_sg_burst; + u32 dma_addr_widths; unsigned long dma_chan_busy; dma_addr_t dma_addr; /* phy address of the Data register */ const struct dw_spi_dma_ops *dma_ops; diff --git a/drivers/spi/spi-fsl-lpspi.c b/drivers/spi/spi-fsl-lpspi.c index 4b70038ceb6b28e16d1cd2936547074834764f13..fb68c72df1711b86d803bff23dc6c199a073c23e 100644 --- a/drivers/spi/spi-fsl-lpspi.c +++ b/drivers/spi/spi-fsl-lpspi.c @@ -303,6 +303,12 @@ static int fsl_lpspi_set_bitrate(struct fsl_lpspi_data *fsl_lpspi) perclk_rate = clk_get_rate(fsl_lpspi->clk_per); + if (!config.speed_hz) { + dev_err(fsl_lpspi->dev, + "error: the transmission speed provided is 0!\n"); + return -EINVAL; + } + if (config.speed_hz > perclk_rate / 2) { dev_err(fsl_lpspi->dev, "per-clk should be at least two times of transfer speed"); @@ -911,7 +917,7 @@ static int fsl_lpspi_probe(struct platform_device *pdev) if (ret == -EPROBE_DEFER) goto out_pm_get; if (ret < 0) - dev_err(&pdev->dev, "dma setup error %d, use pio\n", ret); + dev_warn(&pdev->dev, "dma setup error %d, use pio\n", ret); else /* * disable LPSPI module IRQ when enable DMA mode successfully, diff --git a/drivers/spi/spi-geni-qcom.c b/drivers/spi/spi-geni-qcom.c index a98b781b103ab31b93aed20fc3bf6b167a3c55cb..1df9d4844a68dff4eb26404b614446edbb73ae9d 100644 --- a/drivers/spi/spi-geni-qcom.c +++ b/drivers/spi/spi-geni-qcom.c @@ -35,7 +35,7 @@ #define CS_DEMUX_OUTPUT_SEL GENMASK(3, 0) #define SE_SPI_TRANS_CFG 0x25c -#define CS_TOGGLE BIT(0) +#define CS_TOGGLE BIT(1) #define SE_SPI_WORD_LEN 0x268 #define WORD_LEN_MSK GENMASK(9, 0) @@ -97,8 +97,6 @@ struct spi_geni_master { struct dma_chan *tx; struct dma_chan *rx; int cur_xfer_mode; - dma_addr_t tx_se_dma; - dma_addr_t rx_se_dma; }; static int get_spi_clk_cfg(unsigned int speed_hz, @@ -174,7 +172,7 @@ static void handle_se_timeout(struct spi_master *spi, unmap_if_dma: if (mas->cur_xfer_mode == GENI_SE_DMA) { if (xfer) { - if (xfer->tx_buf && mas->tx_se_dma) { + if (xfer->tx_buf) { spin_lock_irq(&mas->lock); reinit_completion(&mas->tx_reset_done); writel(1, se->base + SE_DMA_TX_FSM_RST); @@ -182,9 +180,8 @@ static void handle_se_timeout(struct spi_master *spi, time_left = wait_for_completion_timeout(&mas->tx_reset_done, HZ); if (!time_left) dev_err(mas->dev, "DMA TX RESET failed\n"); - geni_se_tx_dma_unprep(se, mas->tx_se_dma, xfer->len); } - if (xfer->rx_buf && mas->rx_se_dma) { + if (xfer->rx_buf) { spin_lock_irq(&mas->lock); reinit_completion(&mas->rx_reset_done); writel(1, se->base + SE_DMA_RX_FSM_RST); @@ -192,7 +189,6 @@ static void handle_se_timeout(struct spi_master *spi, time_left = wait_for_completion_timeout(&mas->rx_reset_done, HZ); if (!time_left) dev_err(mas->dev, "DMA RX RESET failed\n"); - geni_se_rx_dma_unprep(se, mas->rx_se_dma, xfer->len); } } else { /* @@ -523,17 +519,36 @@ static int setup_gsi_xfer(struct spi_transfer *xfer, struct spi_geni_master *mas return 1; } +static u32 get_xfer_len_in_words(struct spi_transfer *xfer, + struct spi_geni_master *mas) +{ + u32 len; + + if (!(mas->cur_bits_per_word % MIN_WORD_LEN)) + len = xfer->len * BITS_PER_BYTE / mas->cur_bits_per_word; + else + len = xfer->len / (mas->cur_bits_per_word / BITS_PER_BYTE + 1); + len &= TRANS_LEN_MSK; + + return len; +} + static bool geni_can_dma(struct spi_controller *ctlr, struct spi_device *slv, struct spi_transfer *xfer) { struct spi_geni_master *mas = spi_master_get_devdata(slv->master); + u32 len, fifo_size; - /* - * Return true if transfer needs to be mapped prior to - * calling transfer_one which is the case only for GPI_DMA. - * For SE_DMA mode, map/unmap is done in geni_se_*x_dma_prep. - */ - return mas->cur_xfer_mode == GENI_GPI_DMA; + if (mas->cur_xfer_mode == GENI_GPI_DMA) + return true; + + len = get_xfer_len_in_words(xfer, mas); + fifo_size = mas->tx_fifo_depth * mas->fifo_width_bits / mas->cur_bits_per_word; + + if (len > fifo_size) + return true; + else + return false; } static int spi_geni_prepare_message(struct spi_master *spi, @@ -646,6 +661,8 @@ static int spi_geni_init(struct spi_geni_master *mas) geni_se_select_mode(se, GENI_GPI_DMA); dev_dbg(mas->dev, "Using GPI DMA mode for SPI\n"); break; + } else if (ret == -EPROBE_DEFER) { + goto out_pm; } /* * in case of failure to get gpi dma channel, we can still do the @@ -772,7 +789,7 @@ static int setup_se_xfer(struct spi_transfer *xfer, u16 mode, struct spi_master *spi) { u32 m_cmd = 0; - u32 len, fifo_size; + u32 len; struct geni_se *se = &mas->se; int ret; @@ -804,11 +821,7 @@ static int setup_se_xfer(struct spi_transfer *xfer, mas->tx_rem_bytes = 0; mas->rx_rem_bytes = 0; - if (!(mas->cur_bits_per_word % MIN_WORD_LEN)) - len = xfer->len * BITS_PER_BYTE / mas->cur_bits_per_word; - else - len = xfer->len / (mas->cur_bits_per_word / BITS_PER_BYTE + 1); - len &= TRANS_LEN_MSK; + len = get_xfer_len_in_words(xfer, mas); mas->cur_xfer = xfer; if (xfer->tx_buf) { @@ -823,9 +836,20 @@ static int setup_se_xfer(struct spi_transfer *xfer, mas->rx_rem_bytes = xfer->len; } - /* Select transfer mode based on transfer length */ - fifo_size = mas->tx_fifo_depth * mas->fifo_width_bits / mas->cur_bits_per_word; - mas->cur_xfer_mode = (len <= fifo_size) ? GENI_SE_FIFO : GENI_SE_DMA; + /* + * Select DMA mode if sgt are present; and with only 1 entry + * This is not a serious limitation because the xfer buffers are + * expected to fit into in 1 entry almost always, and if any + * doesn't for any reason we fall back to FIFO mode anyway + */ + if (!xfer->tx_sg.nents && !xfer->rx_sg.nents) + mas->cur_xfer_mode = GENI_SE_FIFO; + else if (xfer->tx_sg.nents > 1 || xfer->rx_sg.nents > 1) { + dev_warn_once(mas->dev, "Doing FIFO, cannot handle tx_nents-%d, rx_nents-%d\n", + xfer->tx_sg.nents, xfer->rx_sg.nents); + mas->cur_xfer_mode = GENI_SE_FIFO; + } else + mas->cur_xfer_mode = GENI_SE_DMA; geni_se_select_mode(se, mas->cur_xfer_mode); /* @@ -836,35 +860,17 @@ static int setup_se_xfer(struct spi_transfer *xfer, geni_se_setup_m_cmd(se, m_cmd, FRAGMENTATION); if (mas->cur_xfer_mode == GENI_SE_DMA) { - if (m_cmd & SPI_RX_ONLY) { - ret = geni_se_rx_dma_prep(se, xfer->rx_buf, - xfer->len, &mas->rx_se_dma); - if (ret) { - dev_err(mas->dev, "Failed to setup Rx dma %d\n", ret); - mas->rx_se_dma = 0; - goto unlock_and_return; - } - } - if (m_cmd & SPI_TX_ONLY) { - ret = geni_se_tx_dma_prep(se, (void *)xfer->tx_buf, - xfer->len, &mas->tx_se_dma); - if (ret) { - dev_err(mas->dev, "Failed to setup Tx dma %d\n", ret); - mas->tx_se_dma = 0; - if (m_cmd & SPI_RX_ONLY) { - /* Unmap rx buffer if duplex transfer */ - geni_se_rx_dma_unprep(se, mas->rx_se_dma, xfer->len); - mas->rx_se_dma = 0; - } - goto unlock_and_return; - } - } + if (m_cmd & SPI_RX_ONLY) + geni_se_rx_init_dma(se, sg_dma_address(xfer->rx_sg.sgl), + sg_dma_len(xfer->rx_sg.sgl)); + if (m_cmd & SPI_TX_ONLY) + geni_se_tx_init_dma(se, sg_dma_address(xfer->tx_sg.sgl), + sg_dma_len(xfer->tx_sg.sgl)); } else if (m_cmd & SPI_TX_ONLY) { if (geni_spi_handle_tx(mas)) writel(mas->tx_wm, se->base + SE_GENI_TX_WATERMARK_REG); } -unlock_and_return: spin_unlock_irq(&mas->lock); return ret; } @@ -965,14 +971,6 @@ static irqreturn_t geni_spi_isr(int irq, void *data) if (dma_rx_status & RX_RESET_DONE) complete(&mas->rx_reset_done); if (!mas->tx_rem_bytes && !mas->rx_rem_bytes && xfer) { - if (xfer->tx_buf && mas->tx_se_dma) { - geni_se_tx_dma_unprep(se, mas->tx_se_dma, xfer->len); - mas->tx_se_dma = 0; - } - if (xfer->rx_buf && mas->rx_se_dma) { - geni_se_rx_dma_unprep(se, mas->rx_se_dma, xfer->len); - mas->rx_se_dma = 0; - } spi_finalize_current_transfer(spi); mas->cur_xfer = NULL; } @@ -1057,6 +1055,7 @@ static int spi_geni_probe(struct platform_device *pdev) spi->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32); spi->num_chipselect = 4; spi->max_speed_hz = 50000000; + spi->max_dma_len = 0xffff0; /* 24 bits for tx/rx dma length */ spi->prepare_message = spi_geni_prepare_message; spi->transfer_one = spi_geni_transfer_one; spi->can_dma = geni_can_dma; @@ -1098,6 +1097,12 @@ static int spi_geni_probe(struct platform_device *pdev) if (mas->cur_xfer_mode == GENI_SE_FIFO) spi->set_cs = spi_geni_set_cs; + /* + * TX is required per GSI spec, see setup_gsi_xfer(). + */ + if (mas->cur_xfer_mode == GENI_GPI_DMA) + spi->flags = SPI_CONTROLLER_MUST_TX; + ret = request_irq(mas->irq, geni_spi_isr, 0, dev_name(dev), spi); if (ret) goto spi_geni_release_dma; diff --git a/drivers/spi/spi-hisi-kunpeng.c b/drivers/spi/spi-hisi-kunpeng.c index 524eadbef87b310298923449f6ed787860652510..2b4b3d2a22b8ba38fbb65a76b5e1e54f139c5d92 100644 --- a/drivers/spi/spi-hisi-kunpeng.c +++ b/drivers/spi/spi-hisi-kunpeng.c @@ -169,7 +169,7 @@ static int hisi_spi_debugfs_init(struct hisi_spi *hs) master = container_of(hs->dev, struct spi_controller, dev); snprintf(name, 32, "hisi_spi%d", master->bus_num); hs->debugfs = debugfs_create_dir(name, NULL); - if (!hs->debugfs) + if (IS_ERR(hs->debugfs)) return -ENOMEM; hs->regset.regs = hisi_spi_regs; diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index 34e5f81ec431e61b899de2f4e9959b9dbb3101f5..528ae46c087f660c78af9ccb7d8fefadb3cafa30 100644 --- a/drivers/spi/spi-imx.c +++ b/drivers/spi/spi-imx.c @@ -281,6 +281,7 @@ static bool spi_imx_can_dma(struct spi_controller *controller, struct spi_device #define MX51_ECSPI_CONFIG_SCLKPOL(cs) (1 << ((cs & 3) + 4)) #define MX51_ECSPI_CONFIG_SBBCTRL(cs) (1 << ((cs & 3) + 8)) #define MX51_ECSPI_CONFIG_SSBPOL(cs) (1 << ((cs & 3) + 12)) +#define MX51_ECSPI_CONFIG_DATACTL(cs) (1 << ((cs & 3) + 16)) #define MX51_ECSPI_CONFIG_SCLKCTL(cs) (1 << ((cs & 3) + 20)) #define MX51_ECSPI_INT 0x10 @@ -516,6 +517,13 @@ static void mx51_ecspi_disable(struct spi_imx_data *spi_imx) writel(ctrl, spi_imx->base + MX51_ECSPI_CTRL); } +static int mx51_ecspi_channel(const struct spi_device *spi) +{ + if (!spi_get_csgpiod(spi, 0)) + return spi_get_chipselect(spi, 0); + return spi->controller->unused_native_cs; +} + static int mx51_ecspi_prepare_message(struct spi_imx_data *spi_imx, struct spi_message *msg) { @@ -526,6 +534,7 @@ static int mx51_ecspi_prepare_message(struct spi_imx_data *spi_imx, u32 testreg, delay; u32 cfg = readl(spi_imx->base + MX51_ECSPI_CONFIG); u32 current_cfg = cfg; + int channel = mx51_ecspi_channel(spi); /* set Master or Slave mode */ if (spi_imx->slave_mode) @@ -540,7 +549,7 @@ static int mx51_ecspi_prepare_message(struct spi_imx_data *spi_imx, ctrl |= MX51_ECSPI_CTRL_DRCTL(spi_imx->spi_drctl); /* set chip select to use */ - ctrl |= MX51_ECSPI_CTRL_CS(spi_get_chipselect(spi, 0)); + ctrl |= MX51_ECSPI_CTRL_CS(channel); /* * The ctrl register must be written first, with the EN bit set other @@ -561,22 +570,27 @@ static int mx51_ecspi_prepare_message(struct spi_imx_data *spi_imx, * BURST_LENGTH + 1 bits are received */ if (spi_imx->slave_mode && is_imx53_ecspi(spi_imx)) - cfg &= ~MX51_ECSPI_CONFIG_SBBCTRL(spi_get_chipselect(spi, 0)); + cfg &= ~MX51_ECSPI_CONFIG_SBBCTRL(channel); else - cfg |= MX51_ECSPI_CONFIG_SBBCTRL(spi_get_chipselect(spi, 0)); + cfg |= MX51_ECSPI_CONFIG_SBBCTRL(channel); if (spi->mode & SPI_CPOL) { - cfg |= MX51_ECSPI_CONFIG_SCLKPOL(spi_get_chipselect(spi, 0)); - cfg |= MX51_ECSPI_CONFIG_SCLKCTL(spi_get_chipselect(spi, 0)); + cfg |= MX51_ECSPI_CONFIG_SCLKPOL(channel); + cfg |= MX51_ECSPI_CONFIG_SCLKCTL(channel); } else { - cfg &= ~MX51_ECSPI_CONFIG_SCLKPOL(spi_get_chipselect(spi, 0)); - cfg &= ~MX51_ECSPI_CONFIG_SCLKCTL(spi_get_chipselect(spi, 0)); + cfg &= ~MX51_ECSPI_CONFIG_SCLKPOL(channel); + cfg &= ~MX51_ECSPI_CONFIG_SCLKCTL(channel); } + if (spi->mode & SPI_MOSI_IDLE_LOW) + cfg |= MX51_ECSPI_CONFIG_DATACTL(channel); + else + cfg &= ~MX51_ECSPI_CONFIG_DATACTL(channel); + if (spi->mode & SPI_CS_HIGH) - cfg |= MX51_ECSPI_CONFIG_SSBPOL(spi_get_chipselect(spi, 0)); + cfg |= MX51_ECSPI_CONFIG_SSBPOL(channel); else - cfg &= ~MX51_ECSPI_CONFIG_SSBPOL(spi_get_chipselect(spi, 0)); + cfg &= ~MX51_ECSPI_CONFIG_SSBPOL(channel); if (cfg == current_cfg) return 0; @@ -621,14 +635,15 @@ static void mx51_configure_cpha(struct spi_imx_data *spi_imx, bool cpha = (spi->mode & SPI_CPHA); bool flip_cpha = (spi->mode & SPI_RX_CPHA_FLIP) && spi_imx->rx_only; u32 cfg = readl(spi_imx->base + MX51_ECSPI_CONFIG); + int channel = mx51_ecspi_channel(spi); /* Flip cpha logical value iff flip_cpha */ cpha ^= flip_cpha; if (cpha) - cfg |= MX51_ECSPI_CONFIG_SCLKPHA(spi_get_chipselect(spi, 0)); + cfg |= MX51_ECSPI_CONFIG_SCLKPHA(channel); else - cfg &= ~MX51_ECSPI_CONFIG_SCLKPHA(spi_get_chipselect(spi, 0)); + cfg &= ~MX51_ECSPI_CONFIG_SCLKPHA(channel); writel(cfg, spi_imx->base + MX51_ECSPI_CONFIG); } @@ -1737,20 +1752,21 @@ static int spi_imx_probe(struct platform_device *pdev) else controller->num_chipselect = 3; - spi_imx->controller->transfer_one = spi_imx_transfer_one; - spi_imx->controller->setup = spi_imx_setup; - spi_imx->controller->cleanup = spi_imx_cleanup; - spi_imx->controller->prepare_message = spi_imx_prepare_message; - spi_imx->controller->unprepare_message = spi_imx_unprepare_message; - spi_imx->controller->slave_abort = spi_imx_slave_abort; - spi_imx->controller->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_NO_CS; + controller->transfer_one = spi_imx_transfer_one; + controller->setup = spi_imx_setup; + controller->cleanup = spi_imx_cleanup; + controller->prepare_message = spi_imx_prepare_message; + controller->unprepare_message = spi_imx_unprepare_message; + controller->slave_abort = spi_imx_slave_abort; + controller->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_NO_CS | + SPI_MOSI_IDLE_LOW; if (is_imx35_cspi(spi_imx) || is_imx51_ecspi(spi_imx) || is_imx53_ecspi(spi_imx)) - spi_imx->controller->mode_bits |= SPI_LOOP | SPI_READY; + controller->mode_bits |= SPI_LOOP | SPI_READY; if (is_imx51_ecspi(spi_imx) || is_imx53_ecspi(spi_imx)) - spi_imx->controller->mode_bits |= SPI_RX_CPHA_FLIP; + controller->mode_bits |= SPI_RX_CPHA_FLIP; if (is_imx51_ecspi(spi_imx) && device_property_read_u32(&pdev->dev, "cs-gpios", NULL)) @@ -1759,7 +1775,12 @@ static int spi_imx_probe(struct platform_device *pdev) * setting the burst length to the word size. This is * considerably faster than manually controlling the CS. */ - spi_imx->controller->mode_bits |= SPI_CS_WORD; + controller->mode_bits |= SPI_CS_WORD; + + if (is_imx51_ecspi(spi_imx) || is_imx53_ecspi(spi_imx)) { + controller->max_native_cs = 4; + controller->flags |= SPI_MASTER_GPIO_SS; + } spi_imx->spi_drctl = spi_drctl; diff --git a/drivers/spi/spi-mt65xx.c b/drivers/spi/spi-mt65xx.c index d7432e2219d850685d3ad83a5f8a60b3f7266dde..39272ad6641b6de79344f09d7ad6d51ada93d03b 100644 --- a/drivers/spi/spi-mt65xx.c +++ b/drivers/spi/spi-mt65xx.c @@ -1144,7 +1144,8 @@ static int mtk_spi_probe(struct platform_device *pdev) if (mdata->dev_comp->must_tx) master->flags = SPI_MASTER_MUST_TX; if (mdata->dev_comp->ipm_design) - master->mode_bits |= SPI_LOOP; + master->mode_bits |= SPI_LOOP | SPI_RX_DUAL | SPI_TX_DUAL | + SPI_RX_QUAD | SPI_TX_QUAD; if (mdata->dev_comp->ipm_design) { mdata->dev = dev; @@ -1269,7 +1270,7 @@ static int mtk_spi_probe(struct platform_device *pdev) return 0; } -static int mtk_spi_remove(struct platform_device *pdev) +static void mtk_spi_remove(struct platform_device *pdev) { struct spi_master *master = platform_get_drvdata(pdev); struct mtk_spi *mdata = spi_master_get_devdata(master); @@ -1278,21 +1279,25 @@ static int mtk_spi_remove(struct platform_device *pdev) if (mdata->use_spimem && !completion_done(&mdata->spimem_done)) complete(&mdata->spimem_done); - ret = pm_runtime_resume_and_get(&pdev->dev); - if (ret < 0) - return ret; - - mtk_spi_reset(mdata); + ret = pm_runtime_get_sync(&pdev->dev); + if (ret < 0) { + dev_warn(&pdev->dev, "Failed to resume hardware (%pe)\n", ERR_PTR(ret)); + } else { + /* + * If pm runtime resume failed, clks are disabled and + * unprepared. So don't access the hardware and skip clk + * unpreparing. + */ + mtk_spi_reset(mdata); - if (mdata->dev_comp->no_need_unprepare) { - clk_unprepare(mdata->spi_clk); - clk_unprepare(mdata->spi_hclk); + if (mdata->dev_comp->no_need_unprepare) { + clk_unprepare(mdata->spi_clk); + clk_unprepare(mdata->spi_hclk); + } } pm_runtime_put_noidle(&pdev->dev); pm_runtime_disable(&pdev->dev); - - return 0; } #ifdef CONFIG_PM_SLEEP @@ -1311,7 +1316,7 @@ static int mtk_spi_suspend(struct device *dev) clk_disable_unprepare(mdata->spi_hclk); } - return ret; + return 0; } static int mtk_spi_resume(struct device *dev) @@ -1412,7 +1417,7 @@ static struct platform_driver mtk_spi_driver = { .of_match_table = mtk_spi_of_match, }, .probe = mtk_spi_probe, - .remove = mtk_spi_remove, + .remove_new = mtk_spi_remove, }; module_platform_driver(mtk_spi_driver); diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c index 982407bc5d9f9e2ba087ee6f035360455c4279b2..1af75eff26b696ecadc05de20e128a2a80e1aee3 100644 --- a/drivers/spi/spi-pl022.c +++ b/drivers/spi/spi-pl022.c @@ -2217,8 +2217,8 @@ static int pl022_probe(struct amba_device *adev, const struct amba_id *id) amba_set_drvdata(adev, pl022); status = devm_spi_register_master(&adev->dev, master); if (status != 0) { - dev_err(&adev->dev, - "probe - problem registering spi master\n"); + dev_err_probe(&adev->dev, status, + "problem registering spi master\n"); goto err_spi_register; } dev_dbg(dev, "probe succeeded\n"); diff --git a/drivers/spi/spi-qcom-qspi.c b/drivers/spi/spi-qcom-qspi.c index fab155389999372ec920ca768c61c894d781b062..a8a683d6145c2681446d56c5de699fc2f21cd0d8 100644 --- a/drivers/spi/spi-qcom-qspi.c +++ b/drivers/spi/spi-qcom-qspi.c @@ -2,6 +2,8 @@ // Copyright (c) 2017-2018, The Linux foundation. All rights reserved. #include +#include +#include #include #include #include @@ -62,6 +64,7 @@ #define WR_FIFO_FULL BIT(10) #define WR_FIFO_OVERRUN BIT(11) #define TRANSACTION_DONE BIT(16) +#define DMA_CHAIN_DONE BIT(31) #define QSPI_ERR_IRQS (RESP_FIFO_UNDERRUN | HRESP_FROM_NOC_ERR | \ WR_FIFO_OVERRUN) #define QSPI_ALL_IRQS (QSPI_ERR_IRQS | RESP_FIFO_RDY | \ @@ -108,18 +111,34 @@ #define RD_FIFO_RESET 0x0030 #define RESET_FIFO BIT(0) +#define NEXT_DMA_DESC_ADDR 0x0040 +#define CURRENT_DMA_DESC_ADDR 0x0044 +#define CURRENT_MEM_ADDR 0x0048 + #define CUR_MEM_ADDR 0x0048 #define HW_VERSION 0x004c #define RD_FIFO 0x0050 #define SAMPLING_CLK_CFG 0x0090 #define SAMPLING_CLK_STATUS 0x0094 +#define QSPI_ALIGN_REQ 32 enum qspi_dir { QSPI_READ, QSPI_WRITE, }; +struct qspi_cmd_desc { + u32 data_address; + u32 next_descriptor; + u32 direction:1; + u32 multi_io_mode:3; + u32 reserved1:4; + u32 fragment:1; + u32 reserved2:7; + u32 length:16; +}; + struct qspi_xfer { union { const void *tx_buf; @@ -137,11 +156,23 @@ enum qspi_clocks { QSPI_NUM_CLKS }; +/* + * Number of entries in sgt returned from spi framework that- + * will be supported. Can be modified as required. + * In practice, given max_dma_len is 64KB, the number of + * entries is not expected to exceed 1. + */ +#define QSPI_MAX_SG 5 + struct qcom_qspi { void __iomem *base; struct device *dev; struct clk_bulk_data *clks; struct qspi_xfer xfer; + struct dma_pool *dma_cmd_pool; + dma_addr_t dma_cmd_desc[QSPI_MAX_SG]; + void *virt_cmd_desc[QSPI_MAX_SG]; + unsigned int n_cmd_desc; struct icc_path *icc_path_cpu_to_qspi; unsigned long last_speed; /* Lock to protect data accessed by IRQs */ @@ -153,21 +184,22 @@ static u32 qspi_buswidth_to_iomode(struct qcom_qspi *ctrl, { switch (buswidth) { case 1: - return SDR_1BIT << MULTI_IO_MODE_SHFT; + return SDR_1BIT; case 2: - return SDR_2BIT << MULTI_IO_MODE_SHFT; + return SDR_2BIT; case 4: - return SDR_4BIT << MULTI_IO_MODE_SHFT; + return SDR_4BIT; default: dev_warn_once(ctrl->dev, "Unexpected bus width: %u\n", buswidth); - return SDR_1BIT << MULTI_IO_MODE_SHFT; + return SDR_1BIT; } } static void qcom_qspi_pio_xfer_cfg(struct qcom_qspi *ctrl) { u32 pio_xfer_cfg; + u32 iomode; const struct qspi_xfer *xfer; xfer = &ctrl->xfer; @@ -179,7 +211,8 @@ static void qcom_qspi_pio_xfer_cfg(struct qcom_qspi *ctrl) else pio_xfer_cfg |= TRANSFER_FRAGMENT; pio_xfer_cfg &= ~MULTI_IO_MODE_MSK; - pio_xfer_cfg |= qspi_buswidth_to_iomode(ctrl, xfer->buswidth); + iomode = qspi_buswidth_to_iomode(ctrl, xfer->buswidth); + pio_xfer_cfg |= iomode << MULTI_IO_MODE_SHFT; writel(pio_xfer_cfg, ctrl->base + PIO_XFER_CFG); } @@ -217,12 +250,22 @@ static void qcom_qspi_pio_xfer(struct qcom_qspi *ctrl) static void qcom_qspi_handle_err(struct spi_master *master, struct spi_message *msg) { + u32 int_status; struct qcom_qspi *ctrl = spi_master_get_devdata(master); unsigned long flags; + int i; spin_lock_irqsave(&ctrl->lock, flags); writel(0, ctrl->base + MSTR_INT_EN); + int_status = readl(ctrl->base + MSTR_INT_STATUS); + writel(int_status, ctrl->base + MSTR_INT_STATUS); ctrl->xfer.rem_bytes = 0; + + /* free cmd descriptors if they are around (DMA mode) */ + for (i = 0; i < ctrl->n_cmd_desc; i++) + dma_pool_free(ctrl->dma_cmd_pool, ctrl->virt_cmd_desc[i], + ctrl->dma_cmd_desc[i]); + ctrl->n_cmd_desc = 0; spin_unlock_irqrestore(&ctrl->lock, flags); } @@ -242,7 +285,7 @@ static int qcom_qspi_set_speed(struct qcom_qspi *ctrl, unsigned long speed_hz) } /* - * Set BW quota for CPU as driver supports FIFO mode only. + * Set BW quota for CPU. * We don't have explicit peak requirement so keep it equal to avg_bw. */ avg_bw_cpu = Bps_to_icc(speed_hz); @@ -258,6 +301,102 @@ static int qcom_qspi_set_speed(struct qcom_qspi *ctrl, unsigned long speed_hz) return 0; } +static int qcom_qspi_alloc_desc(struct qcom_qspi *ctrl, dma_addr_t dma_ptr, + uint32_t n_bytes) +{ + struct qspi_cmd_desc *virt_cmd_desc, *prev; + dma_addr_t dma_cmd_desc; + + /* allocate for dma cmd descriptor */ + virt_cmd_desc = dma_pool_alloc(ctrl->dma_cmd_pool, GFP_KERNEL | __GFP_ZERO, &dma_cmd_desc); + if (!virt_cmd_desc) + return -ENOMEM; + + ctrl->virt_cmd_desc[ctrl->n_cmd_desc] = virt_cmd_desc; + ctrl->dma_cmd_desc[ctrl->n_cmd_desc] = dma_cmd_desc; + ctrl->n_cmd_desc++; + + /* setup cmd descriptor */ + virt_cmd_desc->data_address = dma_ptr; + virt_cmd_desc->direction = ctrl->xfer.dir; + virt_cmd_desc->multi_io_mode = qspi_buswidth_to_iomode(ctrl, ctrl->xfer.buswidth); + virt_cmd_desc->fragment = !ctrl->xfer.is_last; + virt_cmd_desc->length = n_bytes; + + /* update previous descriptor */ + if (ctrl->n_cmd_desc >= 2) { + prev = (ctrl->virt_cmd_desc)[ctrl->n_cmd_desc - 2]; + prev->next_descriptor = dma_cmd_desc; + prev->fragment = 1; + } + + return 0; +} + +static int qcom_qspi_setup_dma_desc(struct qcom_qspi *ctrl, + struct spi_transfer *xfer) +{ + int ret; + struct sg_table *sgt; + dma_addr_t dma_ptr_sg; + unsigned int dma_len_sg; + int i; + + if (ctrl->n_cmd_desc) { + dev_err(ctrl->dev, "Remnant dma buffers n_cmd_desc-%d\n", ctrl->n_cmd_desc); + return -EIO; + } + + sgt = (ctrl->xfer.dir == QSPI_READ) ? &xfer->rx_sg : &xfer->tx_sg; + if (!sgt->nents || sgt->nents > QSPI_MAX_SG) { + dev_warn_once(ctrl->dev, "Cannot handle %d entries in scatter list\n", sgt->nents); + return -EAGAIN; + } + + for (i = 0; i < sgt->nents; i++) { + dma_ptr_sg = sg_dma_address(sgt->sgl + i); + if (!IS_ALIGNED(dma_ptr_sg, QSPI_ALIGN_REQ)) { + dev_warn_once(ctrl->dev, "dma_address not aligned to %d\n", QSPI_ALIGN_REQ); + return -EAGAIN; + } + } + + for (i = 0; i < sgt->nents; i++) { + dma_ptr_sg = sg_dma_address(sgt->sgl + i); + dma_len_sg = sg_dma_len(sgt->sgl + i); + + ret = qcom_qspi_alloc_desc(ctrl, dma_ptr_sg, dma_len_sg); + if (ret) + goto cleanup; + } + return 0; + +cleanup: + for (i = 0; i < ctrl->n_cmd_desc; i++) + dma_pool_free(ctrl->dma_cmd_pool, ctrl->virt_cmd_desc[i], + ctrl->dma_cmd_desc[i]); + ctrl->n_cmd_desc = 0; + return ret; +} + +static void qcom_qspi_dma_xfer(struct qcom_qspi *ctrl) +{ + /* Setup new interrupts */ + writel(DMA_CHAIN_DONE, ctrl->base + MSTR_INT_EN); + + /* kick off transfer */ + writel((u32)((ctrl->dma_cmd_desc)[0]), ctrl->base + NEXT_DMA_DESC_ADDR); +} + +/* Switch to DMA if transfer length exceeds this */ +#define QSPI_MAX_BYTES_FIFO 64 + +static bool qcom_qspi_can_dma(struct spi_controller *ctlr, + struct spi_device *slv, struct spi_transfer *xfer) +{ + return xfer->len > QSPI_MAX_BYTES_FIFO; +} + static int qcom_qspi_transfer_one(struct spi_master *master, struct spi_device *slv, struct spi_transfer *xfer) @@ -266,6 +405,7 @@ static int qcom_qspi_transfer_one(struct spi_master *master, int ret; unsigned long speed_hz; unsigned long flags; + u32 mstr_cfg; speed_hz = slv->max_speed_hz; if (xfer->speed_hz) @@ -276,6 +416,7 @@ static int qcom_qspi_transfer_one(struct spi_master *master, return ret; spin_lock_irqsave(&ctrl->lock, flags); + mstr_cfg = readl(ctrl->base + MSTR_CONFIG); /* We are half duplex, so either rx or tx will be set */ if (xfer->rx_buf) { @@ -290,10 +431,36 @@ static int qcom_qspi_transfer_one(struct spi_master *master, ctrl->xfer.is_last = list_is_last(&xfer->transfer_list, &master->cur_msg->transfers); ctrl->xfer.rem_bytes = xfer->len; + + if (xfer->rx_sg.nents || xfer->tx_sg.nents) { + /* do DMA transfer */ + if (!(mstr_cfg & DMA_ENABLE)) { + mstr_cfg |= DMA_ENABLE; + writel(mstr_cfg, ctrl->base + MSTR_CONFIG); + } + + ret = qcom_qspi_setup_dma_desc(ctrl, xfer); + if (ret != -EAGAIN) { + if (!ret) + qcom_qspi_dma_xfer(ctrl); + goto exit; + } + dev_warn_once(ctrl->dev, "DMA failure, falling back to PIO\n"); + ret = 0; /* We'll retry w/ PIO */ + } + + if (mstr_cfg & DMA_ENABLE) { + mstr_cfg &= ~DMA_ENABLE; + writel(mstr_cfg, ctrl->base + MSTR_CONFIG); + } qcom_qspi_pio_xfer(ctrl); +exit: spin_unlock_irqrestore(&ctrl->lock, flags); + if (ret) + return ret; + /* We'll call spi_finalize_current_transfer() when done */ return 1; } @@ -328,6 +495,16 @@ static int qcom_qspi_prepare_message(struct spi_master *master, return 0; } +static int qcom_qspi_alloc_dma(struct qcom_qspi *ctrl) +{ + ctrl->dma_cmd_pool = dmam_pool_create("qspi cmd desc pool", + ctrl->dev, sizeof(struct qspi_cmd_desc), 0, 0); + if (!ctrl->dma_cmd_pool) + return -ENOMEM; + + return 0; +} + static irqreturn_t pio_read(struct qcom_qspi *ctrl) { u32 rd_fifo_status; @@ -426,6 +603,7 @@ static irqreturn_t qcom_qspi_irq(int irq, void *dev_id) int_status = readl(ctrl->base + MSTR_INT_STATUS); writel(int_status, ctrl->base + MSTR_INT_STATUS); + /* PIO mode handling */ if (ctrl->xfer.dir == QSPI_WRITE) { if (int_status & WR_FIFO_EMPTY) ret = pio_write(ctrl); @@ -449,6 +627,22 @@ static irqreturn_t qcom_qspi_irq(int irq, void *dev_id) spi_finalize_current_transfer(dev_get_drvdata(ctrl->dev)); } + /* DMA mode handling */ + if (int_status & DMA_CHAIN_DONE) { + int i; + + writel(0, ctrl->base + MSTR_INT_EN); + ctrl->xfer.rem_bytes = 0; + + for (i = 0; i < ctrl->n_cmd_desc; i++) + dma_pool_free(ctrl->dma_cmd_pool, ctrl->virt_cmd_desc[i], + ctrl->dma_cmd_desc[i]); + ctrl->n_cmd_desc = 0; + + ret = IRQ_HANDLED; + spi_finalize_current_transfer(dev_get_drvdata(ctrl->dev)); + } + spin_unlock(&ctrl->lock); return ret; } @@ -517,7 +711,13 @@ static int qcom_qspi_probe(struct platform_device *pdev) return ret; } + ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32)); + if (ret) + return dev_err_probe(dev, ret, "could not set DMA mask\n"); + master->max_speed_hz = 300000000; + master->max_dma_len = 65536; /* as per HPG */ + master->dma_alignment = QSPI_ALIGN_REQ; master->num_chipselect = QSPI_NUM_CS; master->bus_num = -1; master->dev.of_node = pdev->dev.of_node; @@ -528,6 +728,8 @@ static int qcom_qspi_probe(struct platform_device *pdev) master->prepare_message = qcom_qspi_prepare_message; master->transfer_one = qcom_qspi_transfer_one; master->handle_err = qcom_qspi_handle_err; + if (of_property_read_bool(pdev->dev.of_node, "iommus")) + master->can_dma = qcom_qspi_can_dma; master->auto_runtime_pm = true; ret = devm_pm_opp_set_clkname(&pdev->dev, "core"); @@ -540,6 +742,10 @@ static int qcom_qspi_probe(struct platform_device *pdev) return ret; } + ret = qcom_qspi_alloc_dma(ctrl); + if (ret) + return ret; + pm_runtime_use_autosuspend(dev); pm_runtime_set_autosuspend_delay(dev, 250); pm_runtime_enable(dev); diff --git a/drivers/spi/spi-rzv2m-csi.c b/drivers/spi/spi-rzv2m-csi.c new file mode 100644 index 0000000000000000000000000000000000000000..14ad65da930d6b1681e987511af678a91091f482 --- /dev/null +++ b/drivers/spi/spi-rzv2m-csi.c @@ -0,0 +1,667 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Renesas RZ/V2M Clocked Serial Interface (CSI) driver + * + * Copyright (C) 2023 Renesas Electronics Corporation + */ + +#include +#include +#include +#include +#include +#include +#include + +/* Registers */ +#define CSI_MODE 0x00 /* CSI mode control */ +#define CSI_CLKSEL 0x04 /* CSI clock select */ +#define CSI_CNT 0x08 /* CSI control */ +#define CSI_INT 0x0C /* CSI interrupt status */ +#define CSI_IFIFOL 0x10 /* CSI receive FIFO level display */ +#define CSI_OFIFOL 0x14 /* CSI transmit FIFO level display */ +#define CSI_IFIFO 0x18 /* CSI receive window */ +#define CSI_OFIFO 0x1C /* CSI transmit window */ +#define CSI_FIFOTRG 0x20 /* CSI FIFO trigger level */ + +/* CSI_MODE */ +#define CSI_MODE_CSIE BIT(7) +#define CSI_MODE_TRMD BIT(6) +#define CSI_MODE_CCL BIT(5) +#define CSI_MODE_DIR BIT(4) +#define CSI_MODE_CSOT BIT(0) + +#define CSI_MODE_SETUP 0x00000040 + +/* CSI_CLKSEL */ +#define CSI_CLKSEL_CKP BIT(17) +#define CSI_CLKSEL_DAP BIT(16) +#define CSI_CLKSEL_SLAVE BIT(15) +#define CSI_CLKSEL_CKS GENMASK(14, 1) + +/* CSI_CNT */ +#define CSI_CNT_CSIRST BIT(28) +#define CSI_CNT_R_TRGEN BIT(19) +#define CSI_CNT_UNDER_E BIT(13) +#define CSI_CNT_OVERF_E BIT(12) +#define CSI_CNT_TREND_E BIT(9) +#define CSI_CNT_CSIEND_E BIT(8) +#define CSI_CNT_T_TRGR_E BIT(4) +#define CSI_CNT_R_TRGR_E BIT(0) + +/* CSI_INT */ +#define CSI_INT_UNDER BIT(13) +#define CSI_INT_OVERF BIT(12) +#define CSI_INT_TREND BIT(9) +#define CSI_INT_CSIEND BIT(8) +#define CSI_INT_T_TRGR BIT(4) +#define CSI_INT_R_TRGR BIT(0) + +/* CSI_FIFOTRG */ +#define CSI_FIFOTRG_R_TRG GENMASK(2, 0) + +#define CSI_FIFO_SIZE_BYTES 32 +#define CSI_FIFO_HALF_SIZE 16 +#define CSI_EN_DIS_TIMEOUT_US 100 +#define CSI_CKS_MAX 0x3FFF + +#define UNDERRUN_ERROR BIT(0) +#define OVERFLOW_ERROR BIT(1) +#define TX_TIMEOUT_ERROR BIT(2) +#define RX_TIMEOUT_ERROR BIT(3) + +#define CSI_MAX_SPI_SCKO 8000000 + +struct rzv2m_csi_priv { + void __iomem *base; + struct clk *csiclk; + struct clk *pclk; + struct device *dev; + struct spi_controller *controller; + const u8 *txbuf; + u8 *rxbuf; + int buffer_len; + int bytes_sent; + int bytes_received; + int bytes_to_transfer; + int words_to_transfer; + unsigned char bytes_per_word; + wait_queue_head_t wait; + u8 errors; + u32 status; +}; + +static const unsigned char x_trg[] = { + 0, 1, 1, 2, 2, 2, 2, 3, + 3, 3, 3, 3, 3, 3, 3, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 5 +}; + +static const unsigned char x_trg_words[] = { + 1, 2, 2, 4, 4, 4, 4, 8, + 8, 8, 8, 8, 8, 8, 8, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 32 +}; + +static void rzv2m_csi_reg_write_bit(const struct rzv2m_csi_priv *csi, + int reg_offs, int bit_mask, u32 value) +{ + int nr_zeros; + u32 tmp; + + nr_zeros = count_trailing_zeros(bit_mask); + value <<= nr_zeros; + + tmp = (readl(csi->base + reg_offs) & ~bit_mask) | value; + writel(tmp, csi->base + reg_offs); +} + +static int rzv2m_csi_sw_reset(struct rzv2m_csi_priv *csi, int assert) +{ + u32 reg; + + rzv2m_csi_reg_write_bit(csi, CSI_CNT, CSI_CNT_CSIRST, assert); + + if (assert) { + return readl_poll_timeout(csi->base + CSI_MODE, reg, + !(reg & CSI_MODE_CSOT), 0, + CSI_EN_DIS_TIMEOUT_US); + } + + return 0; +} + +static int rzv2m_csi_start_stop_operation(const struct rzv2m_csi_priv *csi, + int enable, bool wait) +{ + u32 reg; + + rzv2m_csi_reg_write_bit(csi, CSI_MODE, CSI_MODE_CSIE, enable); + + if (!enable && wait) + return readl_poll_timeout(csi->base + CSI_MODE, reg, + !(reg & CSI_MODE_CSOT), 0, + CSI_EN_DIS_TIMEOUT_US); + + return 0; +} + +static int rzv2m_csi_fill_txfifo(struct rzv2m_csi_priv *csi) +{ + int i; + + if (readl(csi->base + CSI_OFIFOL)) + return -EIO; + + if (csi->bytes_per_word == 2) { + u16 *buf = (u16 *)csi->txbuf; + + for (i = 0; i < csi->words_to_transfer; i++) + writel(buf[i], csi->base + CSI_OFIFO); + } else { + u8 *buf = (u8 *)csi->txbuf; + + for (i = 0; i < csi->words_to_transfer; i++) + writel(buf[i], csi->base + CSI_OFIFO); + } + + csi->txbuf += csi->bytes_to_transfer; + csi->bytes_sent += csi->bytes_to_transfer; + + return 0; +} + +static int rzv2m_csi_read_rxfifo(struct rzv2m_csi_priv *csi) +{ + int i; + + if (readl(csi->base + CSI_IFIFOL) != csi->bytes_to_transfer) + return -EIO; + + if (csi->bytes_per_word == 2) { + u16 *buf = (u16 *)csi->rxbuf; + + for (i = 0; i < csi->words_to_transfer; i++) + buf[i] = (u16)readl(csi->base + CSI_IFIFO); + } else { + u8 *buf = (u8 *)csi->rxbuf; + + for (i = 0; i < csi->words_to_transfer; i++) + buf[i] = (u8)readl(csi->base + CSI_IFIFO); + } + + csi->rxbuf += csi->bytes_to_transfer; + csi->bytes_received += csi->bytes_to_transfer; + + return 0; +} + +static inline void rzv2m_csi_calc_current_transfer(struct rzv2m_csi_priv *csi) +{ + int bytes_transferred = max_t(int, csi->bytes_received, csi->bytes_sent); + int bytes_remaining = csi->buffer_len - bytes_transferred; + int to_transfer; + + if (csi->txbuf) + /* + * Leaving a little bit of headroom in the FIFOs makes it very + * hard to raise an overflow error (which is only possible + * when IP transmits and receives at the same time). + */ + to_transfer = min_t(int, CSI_FIFO_HALF_SIZE, bytes_remaining); + else + to_transfer = min_t(int, CSI_FIFO_SIZE_BYTES, bytes_remaining); + + if (csi->bytes_per_word == 2) + to_transfer >>= 1; + + /* + * We can only choose a trigger level from a predefined set of values. + * This will pick a value that is the greatest possible integer that's + * less than or equal to the number of bytes we need to transfer. + * This may result in multiple smaller transfers. + */ + csi->words_to_transfer = x_trg_words[to_transfer - 1]; + + if (csi->bytes_per_word == 2) + csi->bytes_to_transfer = csi->words_to_transfer << 1; + else + csi->bytes_to_transfer = csi->words_to_transfer; +} + +static inline void rzv2m_csi_set_rx_fifo_trigger_level(struct rzv2m_csi_priv *csi) +{ + rzv2m_csi_reg_write_bit(csi, CSI_FIFOTRG, CSI_FIFOTRG_R_TRG, + x_trg[csi->words_to_transfer - 1]); +} + +static inline void rzv2m_csi_enable_rx_trigger(struct rzv2m_csi_priv *csi, + bool enable) +{ + rzv2m_csi_reg_write_bit(csi, CSI_CNT, CSI_CNT_R_TRGEN, enable); +} + +static void rzv2m_csi_disable_irqs(const struct rzv2m_csi_priv *csi, + u32 enable_bits) +{ + u32 cnt = readl(csi->base + CSI_CNT); + + writel(cnt & ~enable_bits, csi->base + CSI_CNT); +} + +static void rzv2m_csi_disable_all_irqs(struct rzv2m_csi_priv *csi) +{ + rzv2m_csi_disable_irqs(csi, CSI_CNT_R_TRGR_E | CSI_CNT_T_TRGR_E | + CSI_CNT_CSIEND_E | CSI_CNT_TREND_E | + CSI_CNT_OVERF_E | CSI_CNT_UNDER_E); +} + +static inline void rzv2m_csi_clear_irqs(struct rzv2m_csi_priv *csi, u32 irqs) +{ + writel(irqs, csi->base + CSI_INT); +} + +static void rzv2m_csi_clear_all_irqs(struct rzv2m_csi_priv *csi) +{ + rzv2m_csi_clear_irqs(csi, CSI_INT_UNDER | CSI_INT_OVERF | + CSI_INT_TREND | CSI_INT_CSIEND | CSI_INT_T_TRGR | + CSI_INT_R_TRGR); +} + +static void rzv2m_csi_enable_irqs(struct rzv2m_csi_priv *csi, u32 enable_bits) +{ + u32 cnt = readl(csi->base + CSI_CNT); + + writel(cnt | enable_bits, csi->base + CSI_CNT); +} + +static int rzv2m_csi_wait_for_interrupt(struct rzv2m_csi_priv *csi, + u32 wait_mask, u32 enable_bits) +{ + int ret; + + rzv2m_csi_enable_irqs(csi, enable_bits); + + ret = wait_event_timeout(csi->wait, + ((csi->status & wait_mask) == wait_mask) || + csi->errors, HZ); + + rzv2m_csi_disable_irqs(csi, enable_bits); + + if (csi->errors) + return -EIO; + + if (!ret) + return -ETIMEDOUT; + + return 0; +} + +static int rzv2m_csi_wait_for_tx_empty(struct rzv2m_csi_priv *csi) +{ + int ret; + + if (readl(csi->base + CSI_OFIFOL) == 0) + return 0; + + ret = rzv2m_csi_wait_for_interrupt(csi, CSI_INT_TREND, CSI_CNT_TREND_E); + + if (ret == -ETIMEDOUT) + csi->errors |= TX_TIMEOUT_ERROR; + + return ret; +} + +static inline int rzv2m_csi_wait_for_rx_ready(struct rzv2m_csi_priv *csi) +{ + int ret; + + if (readl(csi->base + CSI_IFIFOL) == csi->bytes_to_transfer) + return 0; + + ret = rzv2m_csi_wait_for_interrupt(csi, CSI_INT_R_TRGR, + CSI_CNT_R_TRGR_E); + + if (ret == -ETIMEDOUT) + csi->errors |= RX_TIMEOUT_ERROR; + + return ret; +} + +static irqreturn_t rzv2m_csi_irq_handler(int irq, void *data) +{ + struct rzv2m_csi_priv *csi = (struct rzv2m_csi_priv *)data; + + csi->status = readl(csi->base + CSI_INT); + rzv2m_csi_disable_irqs(csi, csi->status); + + if (csi->status & CSI_INT_OVERF) + csi->errors |= OVERFLOW_ERROR; + if (csi->status & CSI_INT_UNDER) + csi->errors |= UNDERRUN_ERROR; + + wake_up(&csi->wait); + + return IRQ_HANDLED; +} + +static void rzv2m_csi_setup_clock(struct rzv2m_csi_priv *csi, u32 spi_hz) +{ + unsigned long csiclk_rate = clk_get_rate(csi->csiclk); + unsigned long pclk_rate = clk_get_rate(csi->pclk); + unsigned long csiclk_rate_limit = pclk_rate >> 1; + u32 cks; + + /* + * There is a restriction on the frequency of CSICLK, it has to be <= + * PCLK / 2. + */ + if (csiclk_rate > csiclk_rate_limit) { + clk_set_rate(csi->csiclk, csiclk_rate >> 1); + csiclk_rate = clk_get_rate(csi->csiclk); + } else if ((csiclk_rate << 1) <= csiclk_rate_limit) { + clk_set_rate(csi->csiclk, csiclk_rate << 1); + csiclk_rate = clk_get_rate(csi->csiclk); + } + + spi_hz = spi_hz > CSI_MAX_SPI_SCKO ? CSI_MAX_SPI_SCKO : spi_hz; + + cks = DIV_ROUND_UP(csiclk_rate, spi_hz << 1); + if (cks > CSI_CKS_MAX) + cks = CSI_CKS_MAX; + + dev_dbg(csi->dev, "SPI clk rate is %ldHz\n", csiclk_rate / (cks << 1)); + + rzv2m_csi_reg_write_bit(csi, CSI_CLKSEL, CSI_CLKSEL_CKS, cks); +} + +static void rzv2m_csi_setup_operating_mode(struct rzv2m_csi_priv *csi, + struct spi_transfer *t) +{ + if (t->rx_buf && !t->tx_buf) + /* Reception-only mode */ + rzv2m_csi_reg_write_bit(csi, CSI_MODE, CSI_MODE_TRMD, 0); + else + /* Send and receive mode */ + rzv2m_csi_reg_write_bit(csi, CSI_MODE, CSI_MODE_TRMD, 1); + + csi->bytes_per_word = t->bits_per_word / 8; + rzv2m_csi_reg_write_bit(csi, CSI_MODE, CSI_MODE_CCL, + csi->bytes_per_word == 2); +} + +static int rzv2m_csi_setup(struct spi_device *spi) +{ + struct rzv2m_csi_priv *csi = spi_controller_get_devdata(spi->controller); + int ret; + + rzv2m_csi_sw_reset(csi, 0); + + writel(CSI_MODE_SETUP, csi->base + CSI_MODE); + + /* Setup clock polarity and phase timing */ + rzv2m_csi_reg_write_bit(csi, CSI_CLKSEL, CSI_CLKSEL_CKP, + !(spi->mode & SPI_CPOL)); + rzv2m_csi_reg_write_bit(csi, CSI_CLKSEL, CSI_CLKSEL_DAP, + !(spi->mode & SPI_CPHA)); + + /* Setup serial data order */ + rzv2m_csi_reg_write_bit(csi, CSI_MODE, CSI_MODE_DIR, + !!(spi->mode & SPI_LSB_FIRST)); + + /* Set the operation mode as master */ + rzv2m_csi_reg_write_bit(csi, CSI_CLKSEL, CSI_CLKSEL_SLAVE, 0); + + /* Give the IP a SW reset */ + ret = rzv2m_csi_sw_reset(csi, 1); + if (ret) + return ret; + rzv2m_csi_sw_reset(csi, 0); + + /* + * We need to enable the communication so that the clock will settle + * for the right polarity before enabling the CS. + */ + rzv2m_csi_start_stop_operation(csi, 1, false); + udelay(10); + rzv2m_csi_start_stop_operation(csi, 0, false); + + return 0; +} + +static int rzv2m_csi_pio_transfer(struct rzv2m_csi_priv *csi) +{ + bool tx_completed = csi->txbuf ? false : true; + bool rx_completed = csi->rxbuf ? false : true; + int ret = 0; + + /* Make sure the TX FIFO is empty */ + writel(0, csi->base + CSI_OFIFOL); + + csi->bytes_sent = 0; + csi->bytes_received = 0; + csi->errors = 0; + + rzv2m_csi_disable_all_irqs(csi); + rzv2m_csi_clear_all_irqs(csi); + rzv2m_csi_enable_rx_trigger(csi, true); + + while (!tx_completed || !rx_completed) { + /* + * Decide how many words we are going to transfer during + * this cycle (for both TX and RX), then set the RX FIFO trigger + * level accordingly. No need to set a trigger level for the + * TX FIFO, as this IP comes with an interrupt that fires when + * the TX FIFO is empty. + */ + rzv2m_csi_calc_current_transfer(csi); + rzv2m_csi_set_rx_fifo_trigger_level(csi); + + rzv2m_csi_enable_irqs(csi, CSI_INT_OVERF | CSI_INT_UNDER); + + /* Make sure the RX FIFO is empty */ + writel(0, csi->base + CSI_IFIFOL); + + writel(readl(csi->base + CSI_INT), csi->base + CSI_INT); + csi->status = 0; + + rzv2m_csi_start_stop_operation(csi, 1, false); + + /* TX */ + if (csi->txbuf) { + ret = rzv2m_csi_fill_txfifo(csi); + if (ret) + break; + + ret = rzv2m_csi_wait_for_tx_empty(csi); + if (ret) + break; + + if (csi->bytes_sent == csi->buffer_len) + tx_completed = true; + } + + /* + * Make sure the RX FIFO contains the desired number of words. + * We then either flush its content, or we copy it onto + * csi->rxbuf. + */ + ret = rzv2m_csi_wait_for_rx_ready(csi); + if (ret) + break; + + /* RX */ + if (csi->rxbuf) { + rzv2m_csi_start_stop_operation(csi, 0, false); + + ret = rzv2m_csi_read_rxfifo(csi); + if (ret) + break; + + if (csi->bytes_received == csi->buffer_len) + rx_completed = true; + } + + ret = rzv2m_csi_start_stop_operation(csi, 0, true); + if (ret) + goto pio_quit; + + if (csi->errors) { + ret = -EIO; + goto pio_quit; + } + } + + rzv2m_csi_start_stop_operation(csi, 0, true); + +pio_quit: + rzv2m_csi_disable_all_irqs(csi); + rzv2m_csi_enable_rx_trigger(csi, false); + rzv2m_csi_clear_all_irqs(csi); + + return ret; +} + +static int rzv2m_csi_transfer_one(struct spi_controller *controller, + struct spi_device *spi, + struct spi_transfer *transfer) +{ + struct rzv2m_csi_priv *csi = spi_controller_get_devdata(controller); + struct device *dev = csi->dev; + int ret; + + csi->txbuf = transfer->tx_buf; + csi->rxbuf = transfer->rx_buf; + csi->buffer_len = transfer->len; + + rzv2m_csi_setup_operating_mode(csi, transfer); + + rzv2m_csi_setup_clock(csi, transfer->speed_hz); + + ret = rzv2m_csi_pio_transfer(csi); + if (ret) { + if (csi->errors & UNDERRUN_ERROR) + dev_err(dev, "Underrun error\n"); + if (csi->errors & OVERFLOW_ERROR) + dev_err(dev, "Overflow error\n"); + if (csi->errors & TX_TIMEOUT_ERROR) + dev_err(dev, "TX timeout error\n"); + if (csi->errors & RX_TIMEOUT_ERROR) + dev_err(dev, "RX timeout error\n"); + } + + return ret; +} + +static int rzv2m_csi_probe(struct platform_device *pdev) +{ + struct spi_controller *controller; + struct device *dev = &pdev->dev; + struct rzv2m_csi_priv *csi; + struct reset_control *rstc; + int irq; + int ret; + + controller = devm_spi_alloc_master(dev, sizeof(*csi)); + if (!controller) + return -ENOMEM; + + csi = spi_controller_get_devdata(controller); + platform_set_drvdata(pdev, csi); + + csi->dev = dev; + csi->controller = controller; + + csi->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(csi->base)) + return PTR_ERR(csi->base); + + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return irq; + + csi->csiclk = devm_clk_get(dev, "csiclk"); + if (IS_ERR(csi->csiclk)) + return dev_err_probe(dev, PTR_ERR(csi->csiclk), + "could not get csiclk\n"); + + csi->pclk = devm_clk_get(dev, "pclk"); + if (IS_ERR(csi->pclk)) + return dev_err_probe(dev, PTR_ERR(csi->pclk), + "could not get pclk\n"); + + rstc = devm_reset_control_get_shared(dev, NULL); + if (IS_ERR(rstc)) + return dev_err_probe(dev, PTR_ERR(rstc), "Missing reset ctrl\n"); + + init_waitqueue_head(&csi->wait); + + controller->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST; + controller->dev.of_node = pdev->dev.of_node; + controller->bits_per_word_mask = SPI_BPW_MASK(16) | SPI_BPW_MASK(8); + controller->setup = rzv2m_csi_setup; + controller->transfer_one = rzv2m_csi_transfer_one; + controller->use_gpio_descriptors = true; + + ret = devm_request_irq(dev, irq, rzv2m_csi_irq_handler, 0, + dev_name(dev), csi); + if (ret) + return dev_err_probe(dev, ret, "cannot request IRQ\n"); + + /* + * The reset also affects other HW that is not under the control + * of Linux. Therefore, all we can do is make sure the reset is + * deasserted. + */ + reset_control_deassert(rstc); + + /* Make sure the IP is in SW reset state */ + ret = rzv2m_csi_sw_reset(csi, 1); + if (ret) + return ret; + + ret = clk_prepare_enable(csi->csiclk); + if (ret) + return dev_err_probe(dev, ret, "could not enable csiclk\n"); + + ret = spi_register_controller(controller); + if (ret) { + clk_disable_unprepare(csi->csiclk); + return dev_err_probe(dev, ret, "register controller failed\n"); + } + + return 0; +} + +static int rzv2m_csi_remove(struct platform_device *pdev) +{ + struct rzv2m_csi_priv *csi = platform_get_drvdata(pdev); + + spi_unregister_controller(csi->controller); + rzv2m_csi_sw_reset(csi, 1); + clk_disable_unprepare(csi->csiclk); + + return 0; +} + +static const struct of_device_id rzv2m_csi_match[] = { + { .compatible = "renesas,rzv2m-csi" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, rzv2m_csi_match); + +static struct platform_driver rzv2m_csi_drv = { + .probe = rzv2m_csi_probe, + .remove = rzv2m_csi_remove, + .driver = { + .name = "rzv2m_csi", + .of_match_table = rzv2m_csi_match, + }, +}; +module_platform_driver(rzv2m_csi_drv); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Fabrizio Castro "); +MODULE_DESCRIPTION("Clocked Serial Interface Driver"); diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index 7ac17f0d18a95510a48c8c0f3f99d7a04e421e66..b6c2659a66ca684d52ca20810b8cbaa615cf14d8 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -19,7 +19,6 @@ #include #define MAX_SPI_PORTS 12 -#define S3C64XX_SPI_QUIRK_POLL (1 << 0) #define S3C64XX_SPI_QUIRK_CS_AUTO (1 << 1) #define AUTOSUSPEND_TIMEOUT 2000 @@ -59,6 +58,8 @@ #define S3C64XX_SPI_MODE_BUS_TSZ_HALFWORD (1<<17) #define S3C64XX_SPI_MODE_BUS_TSZ_WORD (2<<17) #define S3C64XX_SPI_MODE_BUS_TSZ_MASK (3<<17) +#define S3C64XX_SPI_MODE_RX_RDY_LVL GENMASK(16, 11) +#define S3C64XX_SPI_MODE_RX_RDY_LVL_SHIFT 11 #define S3C64XX_SPI_MODE_SELF_LOOPBACK (1<<3) #define S3C64XX_SPI_MODE_RXDMA_ON (1<<2) #define S3C64XX_SPI_MODE_TXDMA_ON (1<<1) @@ -115,8 +116,10 @@ #define S3C64XX_SPI_TRAILCNT S3C64XX_SPI_MAX_TRAILCNT +#define S3C64XX_SPI_POLLING_SIZE 32 + #define msecs_to_loops(t) (loops_per_jiffy / 1000 * HZ * t) -#define is_polling(x) (x->port_conf->quirks & S3C64XX_SPI_QUIRK_POLL) +#define is_polling(x) (x->cntrlr_info->polling) #define RXBUSY (1<<2) #define TXBUSY (1<<3) @@ -553,7 +556,7 @@ static int s3c64xx_wait_for_dma(struct s3c64xx_spi_driver_data *sdd, } static int s3c64xx_wait_for_pio(struct s3c64xx_spi_driver_data *sdd, - struct spi_transfer *xfer) + struct spi_transfer *xfer, bool use_irq) { void __iomem *regs = sdd->regs; unsigned long val; @@ -562,11 +565,24 @@ static int s3c64xx_wait_for_pio(struct s3c64xx_spi_driver_data *sdd, u32 cpy_len; u8 *buf; int ms; + unsigned long time_us; - /* millisecs to xfer 'len' bytes @ 'cur_speed' */ - ms = xfer->len * 8 * 1000 / sdd->cur_speed; + /* microsecs to xfer 'len' bytes @ 'cur_speed' */ + time_us = (xfer->len * 8 * 1000 * 1000) / sdd->cur_speed; + ms = (time_us / 1000); ms += 10; /* some tolerance */ + /* sleep during signal transfer time */ + status = readl(regs + S3C64XX_SPI_STATUS); + if (RX_FIFO_LVL(status, sdd) < xfer->len) + usleep_range(time_us / 2, time_us); + + if (use_irq) { + val = msecs_to_jiffies(ms); + if (!wait_for_completion_timeout(&sdd->xfer_completion, val)) + return -EIO; + } + val = msecs_to_loops(ms); do { status = readl(regs + S3C64XX_SPI_STATUS); @@ -668,6 +684,8 @@ static int s3c64xx_spi_config(struct s3c64xx_spi_driver_data *sdd) if ((sdd->cur_mode & SPI_LOOP) && sdd->port_conf->has_loopback) val |= S3C64XX_SPI_MODE_SELF_LOOPBACK; + else + val &= ~S3C64XX_SPI_MODE_SELF_LOOPBACK; writel(val, regs + S3C64XX_SPI_MODE_CFG); @@ -729,10 +747,13 @@ static int s3c64xx_spi_transfer_one(struct spi_master *master, void *rx_buf = NULL; int target_len = 0, origin_len = 0; int use_dma = 0; + bool use_irq = false; int status; u32 speed; u8 bpw; unsigned long flags; + u32 rdy_lv; + u32 val; reinit_completion(&sdd->xfer_completion); @@ -753,17 +774,46 @@ static int s3c64xx_spi_transfer_one(struct spi_master *master, sdd->rx_dma.ch && sdd->tx_dma.ch) { use_dma = 1; - } else if (xfer->len > fifo_len) { + } else if (xfer->len >= fifo_len) { tx_buf = xfer->tx_buf; rx_buf = xfer->rx_buf; origin_len = xfer->len; - target_len = xfer->len; - if (xfer->len > fifo_len) - xfer->len = fifo_len; + xfer->len = fifo_len - 1; } do { + /* transfer size is greater than 32, change to IRQ mode */ + if (!use_dma && xfer->len > S3C64XX_SPI_POLLING_SIZE) + use_irq = true; + + if (use_irq) { + reinit_completion(&sdd->xfer_completion); + + rdy_lv = xfer->len; + /* Setup RDY_FIFO trigger Level + * RDY_LVL = + * fifo_lvl up to 64 byte -> N bytes + * 128 byte -> RDY_LVL * 2 bytes + * 256 byte -> RDY_LVL * 4 bytes + */ + if (fifo_len == 128) + rdy_lv /= 2; + else if (fifo_len == 256) + rdy_lv /= 4; + + val = readl(sdd->regs + S3C64XX_SPI_MODE_CFG); + val &= ~S3C64XX_SPI_MODE_RX_RDY_LVL; + val |= (rdy_lv << S3C64XX_SPI_MODE_RX_RDY_LVL_SHIFT); + writel(val, sdd->regs + S3C64XX_SPI_MODE_CFG); + + /* Enable FIFO_RDY_EN IRQ */ + val = readl(sdd->regs + S3C64XX_SPI_INT_EN); + writel((val | S3C64XX_SPI_INT_RX_FIFORDY_EN), + sdd->regs + S3C64XX_SPI_INT_EN); + + } + spin_lock_irqsave(&sdd->lock, flags); /* Pending only which is to be done */ @@ -785,7 +835,7 @@ static int s3c64xx_spi_transfer_one(struct spi_master *master, if (use_dma) status = s3c64xx_wait_for_dma(sdd, xfer); else - status = s3c64xx_wait_for_pio(sdd, xfer); + status = s3c64xx_wait_for_pio(sdd, xfer, use_irq); if (status) { dev_err(&spi->dev, @@ -824,8 +874,8 @@ static int s3c64xx_spi_transfer_one(struct spi_master *master, if (xfer->rx_buf) xfer->rx_buf += xfer->len; - if (target_len > fifo_len) - xfer->len = fifo_len; + if (target_len >= fifo_len) + xfer->len = fifo_len - 1; else xfer->len = target_len; } @@ -995,6 +1045,14 @@ static irqreturn_t s3c64xx_spi_irq(int irq, void *data) dev_err(&spi->dev, "TX underrun\n"); } + if (val & S3C64XX_SPI_ST_RX_FIFORDY) { + complete(&sdd->xfer_completion); + /* No pending clear irq, turn-off INT_EN_RX_FIFO_RDY */ + val = readl(sdd->regs + S3C64XX_SPI_INT_EN); + writel((val & ~S3C64XX_SPI_INT_RX_FIFORDY_EN), + sdd->regs + S3C64XX_SPI_INT_EN); + } + /* Clear the pending irq by setting and then clearing it */ writel(clr, sdd->regs + S3C64XX_SPI_PENDING_CLR); writel(0, sdd->regs + S3C64XX_SPI_PENDING_CLR); @@ -1068,6 +1126,7 @@ static struct s3c64xx_spi_info *s3c64xx_spi_parse_dt(struct device *dev) } sci->no_cs = of_property_read_bool(dev->of_node, "no-cs-readback"); + sci->polling = !of_property_present(dev->of_node, "dmas"); return sci; } @@ -1103,29 +1162,23 @@ static int s3c64xx_spi_probe(struct platform_device *pdev) return PTR_ERR(sci); } - if (!sci) { - dev_err(&pdev->dev, "platform_data missing!\n"); - return -ENODEV; - } + if (!sci) + return dev_err_probe(&pdev->dev, -ENODEV, + "Platform_data missing!\n"); mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (mem_res == NULL) { - dev_err(&pdev->dev, "Unable to get SPI MEM resource\n"); - return -ENXIO; - } + if (!mem_res) + return dev_err_probe(&pdev->dev, -ENXIO, + "Unable to get SPI MEM resource\n"); irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_warn(&pdev->dev, "Failed to get IRQ: %d\n", irq); - return irq; - } + if (irq < 0) + return dev_err_probe(&pdev->dev, irq, "Failed to get IRQ\n"); - master = spi_alloc_master(&pdev->dev, - sizeof(struct s3c64xx_spi_driver_data)); - if (master == NULL) { - dev_err(&pdev->dev, "Unable to allocate SPI Master\n"); - return -ENOMEM; - } + master = devm_spi_alloc_master(&pdev->dev, sizeof(*sdd)); + if (!master) + return dev_err_probe(&pdev->dev, -ENOMEM, + "Unable to allocate SPI Master\n"); platform_set_drvdata(pdev, master); @@ -1137,11 +1190,9 @@ static int s3c64xx_spi_probe(struct platform_device *pdev) sdd->sfr_start = mem_res->start; if (pdev->dev.of_node) { ret = of_alias_get_id(pdev->dev.of_node, "spi"); - if (ret < 0) { - dev_err(&pdev->dev, "failed to get alias id, errno %d\n", - ret); - goto err_deref_master; - } + if (ret < 0) + return dev_err_probe(&pdev->dev, ret, + "Failed to get alias id\n"); sdd->port_id = ret; } else { sdd->port_id = pdev->id; @@ -1175,59 +1226,31 @@ static int s3c64xx_spi_probe(struct platform_device *pdev) master->can_dma = s3c64xx_spi_can_dma; sdd->regs = devm_ioremap_resource(&pdev->dev, mem_res); - if (IS_ERR(sdd->regs)) { - ret = PTR_ERR(sdd->regs); - goto err_deref_master; - } + if (IS_ERR(sdd->regs)) + return PTR_ERR(sdd->regs); - if (sci->cfg_gpio && sci->cfg_gpio()) { - dev_err(&pdev->dev, "Unable to config gpio\n"); - ret = -EBUSY; - goto err_deref_master; - } + if (sci->cfg_gpio && sci->cfg_gpio()) + return dev_err_probe(&pdev->dev, -EBUSY, + "Unable to config gpio\n"); /* Setup clocks */ - sdd->clk = devm_clk_get(&pdev->dev, "spi"); - if (IS_ERR(sdd->clk)) { - dev_err(&pdev->dev, "Unable to acquire clock 'spi'\n"); - ret = PTR_ERR(sdd->clk); - goto err_deref_master; - } - - ret = clk_prepare_enable(sdd->clk); - if (ret) { - dev_err(&pdev->dev, "Couldn't enable clock 'spi'\n"); - goto err_deref_master; - } + sdd->clk = devm_clk_get_enabled(&pdev->dev, "spi"); + if (IS_ERR(sdd->clk)) + return dev_err_probe(&pdev->dev, PTR_ERR(sdd->clk), + "Unable to acquire clock 'spi'\n"); sprintf(clk_name, "spi_busclk%d", sci->src_clk_nr); - sdd->src_clk = devm_clk_get(&pdev->dev, clk_name); - if (IS_ERR(sdd->src_clk)) { - dev_err(&pdev->dev, - "Unable to acquire clock '%s'\n", clk_name); - ret = PTR_ERR(sdd->src_clk); - goto err_disable_clk; - } - - ret = clk_prepare_enable(sdd->src_clk); - if (ret) { - dev_err(&pdev->dev, "Couldn't enable clock '%s'\n", clk_name); - goto err_disable_clk; - } + sdd->src_clk = devm_clk_get_enabled(&pdev->dev, clk_name); + if (IS_ERR(sdd->src_clk)) + return dev_err_probe(&pdev->dev, PTR_ERR(sdd->src_clk), + "Unable to acquire clock '%s'\n", + clk_name); if (sdd->port_conf->clk_ioclk) { - sdd->ioclk = devm_clk_get(&pdev->dev, "spi_ioclk"); - if (IS_ERR(sdd->ioclk)) { - dev_err(&pdev->dev, "Unable to acquire 'ioclk'\n"); - ret = PTR_ERR(sdd->ioclk); - goto err_disable_src_clk; - } - - ret = clk_prepare_enable(sdd->ioclk); - if (ret) { - dev_err(&pdev->dev, "Couldn't enable clock 'ioclk'\n"); - goto err_disable_src_clk; - } + sdd->ioclk = devm_clk_get_enabled(&pdev->dev, "spi_ioclk"); + if (IS_ERR(sdd->ioclk)) + return dev_err_probe(&pdev->dev, PTR_ERR(sdd->ioclk), + "Unable to acquire 'ioclk'\n"); } pm_runtime_set_autosuspend_delay(&pdev->dev, AUTOSUSPEND_TIMEOUT); @@ -1275,14 +1298,6 @@ static int s3c64xx_spi_probe(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); pm_runtime_set_suspended(&pdev->dev); - clk_disable_unprepare(sdd->ioclk); -err_disable_src_clk: - clk_disable_unprepare(sdd->src_clk); -err_disable_clk: - clk_disable_unprepare(sdd->clk); -err_deref_master: - spi_master_put(master); - return ret; } @@ -1300,12 +1315,6 @@ static void s3c64xx_spi_remove(struct platform_device *pdev) dma_release_channel(sdd->tx_dma.ch); } - clk_disable_unprepare(sdd->ioclk); - - clk_disable_unprepare(sdd->src_clk); - - clk_disable_unprepare(sdd->clk); - pm_runtime_put_noidle(&pdev->dev); pm_runtime_disable(&pdev->dev); pm_runtime_set_suspended(&pdev->dev); diff --git a/drivers/spi/spi-sc18is602.c b/drivers/spi/spi-sc18is602.c index 70012333020b4e3da159e61bf28d5afda509f357..d52ed67243f719015ea12f80f04d4912c6155cc7 100644 --- a/drivers/spi/spi-sc18is602.c +++ b/drivers/spi/spi-sc18is602.c @@ -337,7 +337,7 @@ static struct i2c_driver sc18is602_driver = { .name = "sc18is602", .of_match_table = of_match_ptr(sc18is602_of_match), }, - .probe_new = sc18is602_probe, + .probe = sc18is602_probe, .id_table = sc18is602_id, }; diff --git a/drivers/spi/spi-sn-f-ospi.c b/drivers/spi/spi-sn-f-ospi.c index a2bd9dcde0750b1a9a7c6c9fb9604e5171dfac7a..d64d3f75c726beb8825d659e472a66e83f98d1fc 100644 --- a/drivers/spi/spi-sn-f-ospi.c +++ b/drivers/spi/spi-sn-f-ospi.c @@ -526,7 +526,7 @@ static int f_ospi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op) static bool f_ospi_supports_op_width(struct spi_mem *mem, const struct spi_mem_op *op) { - u8 width_available[] = { 0, 1, 2, 4, 8 }; + static const u8 width_available[] = { 0, 1, 2, 4, 8 }; u8 width_op[] = { op->cmd.buswidth, op->addr.buswidth, op->dummy.buswidth, op->data.buswidth }; bool is_match_found; @@ -566,7 +566,7 @@ static bool f_ospi_supports_op(struct spi_mem *mem, static int f_ospi_adjust_op_size(struct spi_mem *mem, struct spi_mem_op *op) { - op->data.nbytes = min((int)op->data.nbytes, (int)(OSPI_DAT_SIZE_MAX)); + op->data.nbytes = min_t(int, op->data.nbytes, OSPI_DAT_SIZE_MAX); return 0; } @@ -634,18 +634,12 @@ static int f_ospi_probe(struct platform_device *pdev) goto err_put_ctlr; } - ospi->clk = devm_clk_get(dev, NULL); + ospi->clk = devm_clk_get_enabled(dev, NULL); if (IS_ERR(ospi->clk)) { ret = PTR_ERR(ospi->clk); goto err_put_ctlr; } - ret = clk_prepare_enable(ospi->clk); - if (ret) { - dev_err(dev, "Failed to enable the clock\n"); - goto err_disable_clk; - } - mutex_init(&ospi->mlock); ret = f_ospi_init(ospi); @@ -661,9 +655,6 @@ static int f_ospi_probe(struct platform_device *pdev) err_destroy_mutex: mutex_destroy(&ospi->mlock); -err_disable_clk: - clk_disable_unprepare(ospi->clk); - err_put_ctlr: spi_controller_put(ctlr); @@ -674,8 +665,6 @@ static void f_ospi_remove(struct platform_device *pdev) { struct f_ospi *ospi = platform_get_drvdata(pdev); - clk_disable_unprepare(ospi->clk); - mutex_destroy(&ospi->mlock); } diff --git a/drivers/spi/spi-stm32.c b/drivers/spi/spi-stm32.c index d6598e4116bd2e44dd92de55f0186af2fdad6bd8..6d10fa4ab78397943e352b6585b73d2cd1dc695e 100644 --- a/drivers/spi/spi-stm32.c +++ b/drivers/spi/spi-stm32.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 // -// STMicroelectronics STM32 SPI Controller driver (master mode only) +// STMicroelectronics STM32 SPI Controller driver // // Copyright (C) 2017, STMicroelectronics - All Rights Reserved // Author(s): Amelie Delaunay for STMicroelectronics. @@ -117,6 +117,7 @@ #define STM32H7_SPI_CFG2_CPHA BIT(24) #define STM32H7_SPI_CFG2_CPOL BIT(25) #define STM32H7_SPI_CFG2_SSM BIT(26) +#define STM32H7_SPI_CFG2_SSIOP BIT(28) #define STM32H7_SPI_CFG2_AFCNTR BIT(31) /* STM32H7_SPI_IER bit fields */ @@ -170,6 +171,10 @@ */ #define SPI_DMA_MIN_BYTES 16 +/* STM32 SPI driver helpers */ +#define STM32_SPI_MASTER_MODE(stm32_spi) (!(stm32_spi)->device_mode) +#define STM32_SPI_DEVICE_MODE(stm32_spi) ((stm32_spi)->device_mode) + /** * struct stm32_spi_reg - stm32 SPI register & bitfield desc * @reg: register offset @@ -190,6 +195,7 @@ struct stm32_spi_reg { * @cpol: clock polarity register and polarity bit * @cpha: clock phase register and phase bit * @lsb_first: LSB transmitted first register and bit + * @cs_high: chips select active value * @br: baud rate register and bitfields * @rx: SPI RX data register * @tx: SPI TX data register @@ -201,6 +207,7 @@ struct stm32_spi_regspec { const struct stm32_spi_reg cpol; const struct stm32_spi_reg cpha; const struct stm32_spi_reg lsb_first; + const struct stm32_spi_reg cs_high; const struct stm32_spi_reg br; const struct stm32_spi_reg rx; const struct stm32_spi_reg tx; @@ -258,7 +265,7 @@ struct stm32_spi_cfg { /** * struct stm32_spi - private data of the SPI controller * @dev: driver model representation of the controller - * @master: controller master interface + * @ctrl: controller interface * @cfg: compatible configuration data * @base: virtual memory area * @clk: hw kernel clock feeding the SPI clock generator @@ -280,10 +287,11 @@ struct stm32_spi_cfg { * @dma_tx: dma channel for TX transfer * @dma_rx: dma channel for RX transfer * @phys_addr: SPI registers physical base address + * @device_mode: the controller is configured as SPI device */ struct stm32_spi { struct device *dev; - struct spi_master *master; + struct spi_controller *ctrl; const struct stm32_spi_cfg *cfg; void __iomem *base; struct clk *clk; @@ -307,6 +315,8 @@ struct stm32_spi { struct dma_chan *dma_tx; struct dma_chan *dma_rx; dma_addr_t phys_addr; + + bool device_mode; }; static const struct stm32_spi_regspec stm32f4_spi_regspec = { @@ -318,6 +328,7 @@ static const struct stm32_spi_regspec stm32f4_spi_regspec = { .cpol = { STM32F4_SPI_CR1, STM32F4_SPI_CR1_CPOL }, .cpha = { STM32F4_SPI_CR1, STM32F4_SPI_CR1_CPHA }, .lsb_first = { STM32F4_SPI_CR1, STM32F4_SPI_CR1_LSBFRST }, + .cs_high = {}, .br = { STM32F4_SPI_CR1, STM32F4_SPI_CR1_BR, STM32F4_SPI_CR1_BR_SHIFT }, .rx = { STM32F4_SPI_DR }, @@ -336,6 +347,7 @@ static const struct stm32_spi_regspec stm32h7_spi_regspec = { .cpol = { STM32H7_SPI_CFG2, STM32H7_SPI_CFG2_CPOL }, .cpha = { STM32H7_SPI_CFG2, STM32H7_SPI_CFG2_CPHA }, .lsb_first = { STM32H7_SPI_CFG2, STM32H7_SPI_CFG2_LSBFRST }, + .cs_high = { STM32H7_SPI_CFG2, STM32H7_SPI_CFG2_SSIOP }, .br = { STM32H7_SPI_CFG1, STM32H7_SPI_CFG1_MBR, STM32H7_SPI_CFG1_MBR_SHIFT }, @@ -437,9 +449,9 @@ static int stm32_spi_prepare_mbr(struct stm32_spi *spi, u32 speed_hz, div = DIV_ROUND_CLOSEST(spi->clk_rate & ~0x1, speed_hz); /* - * SPI framework set xfer->speed_hz to master->max_speed_hz if - * xfer->speed_hz is greater than master->max_speed_hz, and it returns - * an error when xfer->speed_hz is lower than master->min_speed_hz, so + * SPI framework set xfer->speed_hz to ctrl->max_speed_hz if + * xfer->speed_hz is greater than ctrl->max_speed_hz, and it returns + * an error when xfer->speed_hz is lower than ctrl->min_speed_hz, so * no need to check it there. * However, we need to ensure the following calculations. */ @@ -657,9 +669,9 @@ static void stm32f4_spi_disable(struct stm32_spi *spi) } if (spi->cur_usedma && spi->dma_tx) - dmaengine_terminate_all(spi->dma_tx); + dmaengine_terminate_async(spi->dma_tx); if (spi->cur_usedma && spi->dma_rx) - dmaengine_terminate_all(spi->dma_rx); + dmaengine_terminate_async(spi->dma_rx); stm32_spi_clr_bits(spi, STM32F4_SPI_CR1, STM32F4_SPI_CR1_SPE); @@ -696,9 +708,9 @@ static void stm32h7_spi_disable(struct stm32_spi *spi) } if (spi->cur_usedma && spi->dma_tx) - dmaengine_terminate_all(spi->dma_tx); + dmaengine_terminate_async(spi->dma_tx); if (spi->cur_usedma && spi->dma_rx) - dmaengine_terminate_all(spi->dma_rx); + dmaengine_terminate_async(spi->dma_rx); stm32_spi_clr_bits(spi, STM32H7_SPI_CR1, STM32H7_SPI_CR1_SPE); @@ -714,19 +726,19 @@ static void stm32h7_spi_disable(struct stm32_spi *spi) /** * stm32_spi_can_dma - Determine if the transfer is eligible for DMA use - * @master: controller master interface + * @ctrl: controller interface * @spi_dev: pointer to the spi device * @transfer: pointer to spi transfer * * If driver has fifo and the current transfer size is greater than fifo size, * use DMA. Otherwise use DMA for transfer longer than defined DMA min bytes. */ -static bool stm32_spi_can_dma(struct spi_master *master, +static bool stm32_spi_can_dma(struct spi_controller *ctrl, struct spi_device *spi_dev, struct spi_transfer *transfer) { unsigned int dma_size; - struct stm32_spi *spi = spi_master_get_devdata(master); + struct stm32_spi *spi = spi_controller_get_devdata(ctrl); if (spi->cfg->has_fifo) dma_size = spi->fifo_size; @@ -742,12 +754,12 @@ static bool stm32_spi_can_dma(struct spi_master *master, /** * stm32f4_spi_irq_event - Interrupt handler for SPI controller events * @irq: interrupt line - * @dev_id: SPI controller master interface + * @dev_id: SPI controller ctrl interface */ static irqreturn_t stm32f4_spi_irq_event(int irq, void *dev_id) { - struct spi_master *master = dev_id; - struct stm32_spi *spi = spi_master_get_devdata(master); + struct spi_controller *ctrl = dev_id; + struct stm32_spi *spi = spi_controller_get_devdata(ctrl); u32 sr, mask = 0; bool end = false; @@ -830,14 +842,14 @@ static irqreturn_t stm32f4_spi_irq_event(int irq, void *dev_id) /** * stm32f4_spi_irq_thread - Thread of interrupt handler for SPI controller * @irq: interrupt line - * @dev_id: SPI controller master interface + * @dev_id: SPI controller interface */ static irqreturn_t stm32f4_spi_irq_thread(int irq, void *dev_id) { - struct spi_master *master = dev_id; - struct stm32_spi *spi = spi_master_get_devdata(master); + struct spi_controller *ctrl = dev_id; + struct stm32_spi *spi = spi_controller_get_devdata(ctrl); - spi_finalize_current_transfer(master); + spi_finalize_current_transfer(ctrl); stm32f4_spi_disable(spi); return IRQ_HANDLED; @@ -846,12 +858,12 @@ static irqreturn_t stm32f4_spi_irq_thread(int irq, void *dev_id) /** * stm32h7_spi_irq_thread - Thread of interrupt handler for SPI controller * @irq: interrupt line - * @dev_id: SPI controller master interface + * @dev_id: SPI controller interface */ static irqreturn_t stm32h7_spi_irq_thread(int irq, void *dev_id) { - struct spi_master *master = dev_id; - struct stm32_spi *spi = spi_master_get_devdata(master); + struct spi_controller *ctrl = dev_id; + struct stm32_spi *spi = spi_controller_get_devdata(ctrl); u32 sr, ier, mask; unsigned long flags; bool end = false; @@ -931,7 +943,7 @@ static irqreturn_t stm32h7_spi_irq_thread(int irq, void *dev_id) if (end) { stm32h7_spi_disable(spi); - spi_finalize_current_transfer(master); + spi_finalize_current_transfer(ctrl); } return IRQ_HANDLED; @@ -939,13 +951,13 @@ static irqreturn_t stm32h7_spi_irq_thread(int irq, void *dev_id) /** * stm32_spi_prepare_msg - set up the controller to transfer a single message - * @master: controller master interface + * @ctrl: controller interface * @msg: pointer to spi message */ -static int stm32_spi_prepare_msg(struct spi_master *master, +static int stm32_spi_prepare_msg(struct spi_controller *ctrl, struct spi_message *msg) { - struct stm32_spi *spi = spi_master_get_devdata(master); + struct stm32_spi *spi = spi_controller_get_devdata(ctrl); struct spi_device *spi_dev = msg->spi; struct device_node *np = spi_dev->dev.of_node; unsigned long flags; @@ -971,6 +983,11 @@ static int stm32_spi_prepare_msg(struct spi_master *master, else clrb |= spi->cfg->regs->lsb_first.mask; + if (STM32_SPI_DEVICE_MODE(spi) && spi_dev->mode & SPI_CS_HIGH) + setb |= spi->cfg->regs->cs_high.mask; + else + clrb |= spi->cfg->regs->cs_high.mask; + dev_dbg(spi->dev, "cpol=%d cpha=%d lsb_first=%d cs_high=%d\n", !!(spi_dev->mode & SPI_CPOL), !!(spi_dev->mode & SPI_CPHA), @@ -984,9 +1001,9 @@ static int stm32_spi_prepare_msg(struct spi_master *master, if (spi->cfg->set_number_of_data) { int ret; - ret = spi_split_transfers_maxwords(master, msg, - STM32H7_SPI_TSIZE_MAX, - GFP_KERNEL | GFP_DMA); + ret = spi_split_transfers_maxsize(ctrl, msg, + STM32H7_SPI_TSIZE_MAX, + GFP_KERNEL | GFP_DMA); if (ret) return ret; } @@ -1016,7 +1033,7 @@ static void stm32f4_spi_dma_tx_cb(void *data) struct stm32_spi *spi = data; if (spi->cur_comm == SPI_SIMPLEX_TX || spi->cur_comm == SPI_3WIRE_TX) { - spi_finalize_current_transfer(spi->master); + spi_finalize_current_transfer(spi->ctrl); stm32f4_spi_disable(spi); } } @@ -1031,7 +1048,7 @@ static void stm32_spi_dma_rx_cb(void *data) { struct stm32_spi *spi = data; - spi_finalize_current_transfer(spi->master); + spi_finalize_current_transfer(spi->ctrl); spi->cfg->disable(spi); } @@ -1161,7 +1178,8 @@ static int stm32h7_spi_transfer_one_irq(struct stm32_spi *spi) if (spi->tx_buf) stm32h7_spi_write_txfifo(spi); - stm32_spi_set_bits(spi, STM32H7_SPI_CR1, STM32H7_SPI_CR1_CSTART); + if (STM32_SPI_MASTER_MODE(spi)) + stm32_spi_set_bits(spi, STM32H7_SPI_CR1, STM32H7_SPI_CR1_CSTART); writel_relaxed(ier, spi->base + STM32H7_SPI_IER); @@ -1208,7 +1226,8 @@ static void stm32h7_spi_transfer_one_dma_start(struct stm32_spi *spi) stm32_spi_enable(spi); - stm32_spi_set_bits(spi, STM32H7_SPI_CR1, STM32H7_SPI_CR1_CSTART); + if (STM32_SPI_MASTER_MODE(spi)) + stm32_spi_set_bits(spi, STM32H7_SPI_CR1, STM32H7_SPI_CR1_CSTART); } /** @@ -1302,7 +1321,7 @@ static int stm32_spi_transfer_one_dma(struct stm32_spi *spi, dma_submit_error: if (spi->dma_rx) - dmaengine_terminate_all(spi->dma_rx); + dmaengine_terminate_sync(spi->dma_rx); dma_desc_error: stm32_spi_clr_bits(spi, spi->cfg->regs->dma_rx_en.reg, @@ -1536,16 +1555,18 @@ static int stm32_spi_transfer_one_setup(struct stm32_spi *spi, spi->cfg->set_bpw(spi); /* Update spi->cur_speed with real clock speed */ - mbr = stm32_spi_prepare_mbr(spi, transfer->speed_hz, - spi->cfg->baud_rate_div_min, - spi->cfg->baud_rate_div_max); - if (mbr < 0) { - ret = mbr; - goto out; - } + if (STM32_SPI_MASTER_MODE(spi)) { + mbr = stm32_spi_prepare_mbr(spi, transfer->speed_hz, + spi->cfg->baud_rate_div_min, + spi->cfg->baud_rate_div_max); + if (mbr < 0) { + ret = mbr; + goto out; + } - transfer->speed_hz = spi->cur_speed; - stm32_spi_set_mbr(spi, mbr); + transfer->speed_hz = spi->cur_speed; + stm32_spi_set_mbr(spi, mbr); + } comm_type = stm32_spi_communication_type(spi_dev, transfer); ret = spi->cfg->set_mode(spi, comm_type); @@ -1554,7 +1575,7 @@ static int stm32_spi_transfer_one_setup(struct stm32_spi *spi, spi->cur_comm = comm_type; - if (spi->cfg->set_data_idleness) + if (STM32_SPI_MASTER_MODE(spi) && spi->cfg->set_data_idleness) spi->cfg->set_data_idleness(spi, transfer->len); if (spi->cur_bpw <= 8) @@ -1575,7 +1596,8 @@ static int stm32_spi_transfer_one_setup(struct stm32_spi *spi, dev_dbg(spi->dev, "data frame of %d-bit, data packet of %d data frames\n", spi->cur_bpw, spi->cur_fthlv); - dev_dbg(spi->dev, "speed set to %dHz\n", spi->cur_speed); + if (STM32_SPI_MASTER_MODE(spi)) + dev_dbg(spi->dev, "speed set to %dHz\n", spi->cur_speed); dev_dbg(spi->dev, "transfer of %d bytes (%d data frames)\n", spi->cur_xferlen, nb_words); dev_dbg(spi->dev, "dma %s\n", @@ -1589,18 +1611,18 @@ static int stm32_spi_transfer_one_setup(struct stm32_spi *spi, /** * stm32_spi_transfer_one - transfer a single spi_transfer - * @master: controller master interface + * @ctrl: controller interface * @spi_dev: pointer to the spi device * @transfer: pointer to spi transfer * * It must return 0 if the transfer is finished or 1 if the transfer is still * in progress. */ -static int stm32_spi_transfer_one(struct spi_master *master, +static int stm32_spi_transfer_one(struct spi_controller *ctrl, struct spi_device *spi_dev, struct spi_transfer *transfer) { - struct stm32_spi *spi = spi_master_get_devdata(master); + struct stm32_spi *spi = spi_controller_get_devdata(ctrl); int ret; spi->tx_buf = transfer->tx_buf; @@ -1608,8 +1630,8 @@ static int stm32_spi_transfer_one(struct spi_master *master, spi->tx_len = spi->tx_buf ? transfer->len : 0; spi->rx_len = spi->rx_buf ? transfer->len : 0; - spi->cur_usedma = (master->can_dma && - master->can_dma(master, spi_dev, transfer)); + spi->cur_usedma = (ctrl->can_dma && + ctrl->can_dma(ctrl, spi_dev, transfer)); ret = stm32_spi_transfer_one_setup(spi, spi_dev, transfer); if (ret) { @@ -1625,13 +1647,13 @@ static int stm32_spi_transfer_one(struct spi_master *master, /** * stm32_spi_unprepare_msg - relax the hardware - * @master: controller master interface + * @ctrl: controller interface * @msg: pointer to the spi message */ -static int stm32_spi_unprepare_msg(struct spi_master *master, +static int stm32_spi_unprepare_msg(struct spi_controller *ctrl, struct spi_message *msg) { - struct stm32_spi *spi = spi_master_get_devdata(master); + struct stm32_spi *spi = spi_controller_get_devdata(ctrl); spi->cfg->disable(spi); @@ -1670,12 +1692,13 @@ static int stm32f4_spi_config(struct stm32_spi *spi) } /** - * stm32h7_spi_config - Configure SPI controller as SPI master + * stm32h7_spi_config - Configure SPI controller * @spi: pointer to the spi controller data structure */ static int stm32h7_spi_config(struct stm32_spi *spi) { unsigned long flags; + u32 cr1 = 0, cfg2 = 0; spin_lock_irqsave(&spi->lock, flags); @@ -1683,24 +1706,28 @@ static int stm32h7_spi_config(struct stm32_spi *spi) stm32_spi_clr_bits(spi, STM32H7_SPI_I2SCFGR, STM32H7_SPI_I2SCFGR_I2SMOD); - /* - * - SS input value high - * - transmitter half duplex direction - * - automatic communication suspend when RX-Fifo is full - */ - stm32_spi_set_bits(spi, STM32H7_SPI_CR1, STM32H7_SPI_CR1_SSI | - STM32H7_SPI_CR1_HDDIR | - STM32H7_SPI_CR1_MASRX); + if (STM32_SPI_DEVICE_MODE(spi)) { + /* Use native device select */ + cfg2 &= ~STM32H7_SPI_CFG2_SSM; + } else { + /* + * - Transmitter half duplex direction + * - Automatic communication suspend when RX-Fifo is full + * - SS input value high + */ + cr1 |= STM32H7_SPI_CR1_HDDIR | STM32H7_SPI_CR1_MASRX | STM32H7_SPI_CR1_SSI; - /* - * - Set the master mode (default Motorola mode) - * - Consider 1 master/n slaves configuration and - * SS input value is determined by the SSI bit - * - keep control of all associated GPIOs - */ - stm32_spi_set_bits(spi, STM32H7_SPI_CFG2, STM32H7_SPI_CFG2_MASTER | - STM32H7_SPI_CFG2_SSM | - STM32H7_SPI_CFG2_AFCNTR); + /* + * - Set the master mode (default Motorola mode) + * - Consider 1 master/n devices configuration and + * SS input value is determined by the SSI bit + * - keep control of all associated GPIOs + */ + cfg2 |= STM32H7_SPI_CFG2_MASTER | STM32H7_SPI_CFG2_SSM | STM32H7_SPI_CFG2_AFCNTR; + } + + stm32_spi_set_bits(spi, STM32H7_SPI_CR1, cr1); + stm32_spi_set_bits(spi, STM32H7_SPI_CFG2, cfg2); spin_unlock_irqrestore(&spi->lock, flags); @@ -1756,24 +1783,38 @@ static const struct of_device_id stm32_spi_of_match[] = { }; MODULE_DEVICE_TABLE(of, stm32_spi_of_match); +static int stm32h7_spi_device_abort(struct spi_controller *ctrl) +{ + spi_finalize_current_transfer(ctrl); + return 0; +} + static int stm32_spi_probe(struct platform_device *pdev) { - struct spi_master *master; + struct spi_controller *ctrl; struct stm32_spi *spi; struct resource *res; struct reset_control *rst; + struct device_node *np = pdev->dev.of_node; + bool device_mode; int ret; - master = devm_spi_alloc_master(&pdev->dev, sizeof(struct stm32_spi)); - if (!master) { - dev_err(&pdev->dev, "spi master allocation failed\n"); + device_mode = of_property_read_bool(np, "spi-slave"); + + if (device_mode) + ctrl = devm_spi_alloc_slave(&pdev->dev, sizeof(struct stm32_spi)); + else + ctrl = devm_spi_alloc_master(&pdev->dev, sizeof(struct stm32_spi)); + if (!ctrl) { + dev_err(&pdev->dev, "spi controller allocation failed\n"); return -ENOMEM; } - platform_set_drvdata(pdev, master); + platform_set_drvdata(pdev, ctrl); - spi = spi_master_get_devdata(master); + spi = spi_controller_get_devdata(ctrl); spi->dev = &pdev->dev; - spi->master = master; + spi->ctrl = ctrl; + spi->device_mode = device_mode; spin_lock_init(&spi->lock); spi->cfg = (const struct stm32_spi_cfg *) @@ -1794,7 +1835,7 @@ static int stm32_spi_probe(struct platform_device *pdev) ret = devm_request_threaded_irq(&pdev->dev, spi->irq, spi->cfg->irq_handler_event, spi->cfg->irq_handler_thread, - IRQF_ONESHOT, pdev->name, master); + IRQF_ONESHOT, pdev->name, ctrl); if (ret) { dev_err(&pdev->dev, "irq%d request failed: %d\n", spi->irq, ret); @@ -1843,19 +1884,21 @@ static int stm32_spi_probe(struct platform_device *pdev) goto err_clk_disable; } - master->dev.of_node = pdev->dev.of_node; - master->auto_runtime_pm = true; - master->bus_num = pdev->id; - master->mode_bits = SPI_CPHA | SPI_CPOL | SPI_CS_HIGH | SPI_LSB_FIRST | - SPI_3WIRE; - master->bits_per_word_mask = spi->cfg->get_bpw_mask(spi); - master->max_speed_hz = spi->clk_rate / spi->cfg->baud_rate_div_min; - master->min_speed_hz = spi->clk_rate / spi->cfg->baud_rate_div_max; - master->use_gpio_descriptors = true; - master->prepare_message = stm32_spi_prepare_msg; - master->transfer_one = stm32_spi_transfer_one; - master->unprepare_message = stm32_spi_unprepare_msg; - master->flags = spi->cfg->flags; + ctrl->dev.of_node = pdev->dev.of_node; + ctrl->auto_runtime_pm = true; + ctrl->bus_num = pdev->id; + ctrl->mode_bits = SPI_CPHA | SPI_CPOL | SPI_CS_HIGH | SPI_LSB_FIRST | + SPI_3WIRE; + ctrl->bits_per_word_mask = spi->cfg->get_bpw_mask(spi); + ctrl->max_speed_hz = spi->clk_rate / spi->cfg->baud_rate_div_min; + ctrl->min_speed_hz = spi->clk_rate / spi->cfg->baud_rate_div_max; + ctrl->use_gpio_descriptors = true; + ctrl->prepare_message = stm32_spi_prepare_msg; + ctrl->transfer_one = stm32_spi_transfer_one; + ctrl->unprepare_message = stm32_spi_unprepare_msg; + ctrl->flags = spi->cfg->flags; + if (STM32_SPI_DEVICE_MODE(spi)) + ctrl->slave_abort = stm32h7_spi_device_abort; spi->dma_tx = dma_request_chan(spi->dev, "tx"); if (IS_ERR(spi->dma_tx)) { @@ -1866,7 +1909,7 @@ static int stm32_spi_probe(struct platform_device *pdev) dev_warn(&pdev->dev, "failed to request tx dma channel\n"); } else { - master->dma_tx = spi->dma_tx; + ctrl->dma_tx = spi->dma_tx; } spi->dma_rx = dma_request_chan(spi->dev, "rx"); @@ -1878,11 +1921,11 @@ static int stm32_spi_probe(struct platform_device *pdev) dev_warn(&pdev->dev, "failed to request rx dma channel\n"); } else { - master->dma_rx = spi->dma_rx; + ctrl->dma_rx = spi->dma_rx; } if (spi->dma_tx || spi->dma_rx) - master->can_dma = stm32_spi_can_dma; + ctrl->can_dma = stm32_spi_can_dma; pm_runtime_set_autosuspend_delay(&pdev->dev, STM32_SPI_AUTOSUSPEND_DELAY); @@ -1891,9 +1934,9 @@ static int stm32_spi_probe(struct platform_device *pdev) pm_runtime_get_noresume(&pdev->dev); pm_runtime_enable(&pdev->dev); - ret = spi_register_master(master); + ret = spi_register_controller(ctrl); if (ret) { - dev_err(&pdev->dev, "spi master registration failed: %d\n", + dev_err(&pdev->dev, "spi controller registration failed: %d\n", ret); goto err_pm_disable; } @@ -1901,7 +1944,8 @@ static int stm32_spi_probe(struct platform_device *pdev) pm_runtime_mark_last_busy(&pdev->dev); pm_runtime_put_autosuspend(&pdev->dev); - dev_info(&pdev->dev, "driver initialized\n"); + dev_info(&pdev->dev, "driver initialized (%s mode)\n", + STM32_SPI_MASTER_MODE(spi) ? "master" : "device"); return 0; @@ -1923,12 +1967,12 @@ static int stm32_spi_probe(struct platform_device *pdev) static void stm32_spi_remove(struct platform_device *pdev) { - struct spi_master *master = platform_get_drvdata(pdev); - struct stm32_spi *spi = spi_master_get_devdata(master); + struct spi_controller *ctrl = platform_get_drvdata(pdev); + struct stm32_spi *spi = spi_controller_get_devdata(ctrl); pm_runtime_get_sync(&pdev->dev); - spi_unregister_master(master); + spi_unregister_controller(ctrl); spi->cfg->disable(spi); pm_runtime_disable(&pdev->dev); @@ -1936,10 +1980,10 @@ static void stm32_spi_remove(struct platform_device *pdev) pm_runtime_set_suspended(&pdev->dev); pm_runtime_dont_use_autosuspend(&pdev->dev); - if (master->dma_tx) - dma_release_channel(master->dma_tx); - if (master->dma_rx) - dma_release_channel(master->dma_rx); + if (ctrl->dma_tx) + dma_release_channel(ctrl->dma_tx); + if (ctrl->dma_rx) + dma_release_channel(ctrl->dma_rx); clk_disable_unprepare(spi->clk); @@ -1949,8 +1993,8 @@ static void stm32_spi_remove(struct platform_device *pdev) static int __maybe_unused stm32_spi_runtime_suspend(struct device *dev) { - struct spi_master *master = dev_get_drvdata(dev); - struct stm32_spi *spi = spi_master_get_devdata(master); + struct spi_controller *ctrl = dev_get_drvdata(dev); + struct stm32_spi *spi = spi_controller_get_devdata(ctrl); clk_disable_unprepare(spi->clk); @@ -1959,8 +2003,8 @@ static int __maybe_unused stm32_spi_runtime_suspend(struct device *dev) static int __maybe_unused stm32_spi_runtime_resume(struct device *dev) { - struct spi_master *master = dev_get_drvdata(dev); - struct stm32_spi *spi = spi_master_get_devdata(master); + struct spi_controller *ctrl = dev_get_drvdata(dev); + struct stm32_spi *spi = spi_controller_get_devdata(ctrl); int ret; ret = pinctrl_pm_select_default_state(dev); @@ -1972,10 +2016,10 @@ static int __maybe_unused stm32_spi_runtime_resume(struct device *dev) static int __maybe_unused stm32_spi_suspend(struct device *dev) { - struct spi_master *master = dev_get_drvdata(dev); + struct spi_controller *ctrl = dev_get_drvdata(dev); int ret; - ret = spi_master_suspend(master); + ret = spi_controller_suspend(ctrl); if (ret) return ret; @@ -1984,15 +2028,15 @@ static int __maybe_unused stm32_spi_suspend(struct device *dev) static int __maybe_unused stm32_spi_resume(struct device *dev) { - struct spi_master *master = dev_get_drvdata(dev); - struct stm32_spi *spi = spi_master_get_devdata(master); + struct spi_controller *ctrl = dev_get_drvdata(dev); + struct stm32_spi *spi = spi_controller_get_devdata(ctrl); int ret; ret = pm_runtime_force_resume(dev); if (ret) return ret; - ret = spi_master_resume(master); + ret = spi_controller_resume(ctrl); if (ret) { clk_disable_unprepare(spi->clk); return ret; diff --git a/drivers/spi/spi-sun6i.c b/drivers/spi/spi-sun6i.c index 7532c85a352c61f3f3ccb10f20abcef1da383a8d..30d541612253e863b07525cbe357bfbdf71b80ce 100644 --- a/drivers/spi/spi-sun6i.c +++ b/drivers/spi/spi-sun6i.c @@ -42,7 +42,9 @@ #define SUN6I_TFR_CTL_CS_MANUAL BIT(6) #define SUN6I_TFR_CTL_CS_LEVEL BIT(7) #define SUN6I_TFR_CTL_DHB BIT(8) +#define SUN6I_TFR_CTL_SDC BIT(11) #define SUN6I_TFR_CTL_FBS BIT(12) +#define SUN6I_TFR_CTL_SDM BIT(13) #define SUN6I_TFR_CTL_XCH BIT(31) #define SUN6I_INT_CTL_REG 0x10 @@ -85,6 +87,11 @@ #define SUN6I_TXDATA_REG 0x200 #define SUN6I_RXDATA_REG 0x300 +struct sun6i_spi_cfg { + unsigned long fifo_depth; + bool has_clk_ctl; +}; + struct sun6i_spi { struct spi_master *master; void __iomem *base_addr; @@ -99,7 +106,7 @@ struct sun6i_spi { const u8 *tx_buf; u8 *rx_buf; int len; - unsigned long fifo_depth; + const struct sun6i_spi_cfg *cfg; }; static inline u32 sun6i_spi_read(struct sun6i_spi *sspi, u32 reg) @@ -156,7 +163,7 @@ static inline void sun6i_spi_fill_fifo(struct sun6i_spi *sspi) u8 byte; /* See how much data we can fit */ - cnt = sspi->fifo_depth - sun6i_spi_get_tx_fifo_count(sspi); + cnt = sspi->cfg->fifo_depth - sun6i_spi_get_tx_fifo_count(sspi); len = min((int)cnt, sspi->len); @@ -256,7 +263,7 @@ static int sun6i_spi_transfer_one(struct spi_master *master, struct spi_transfer *tfr) { struct sun6i_spi *sspi = spi_master_get_devdata(master); - unsigned int mclk_rate, div, div_cdr1, div_cdr2, timeout; + unsigned int div, div_cdr1, div_cdr2, timeout; unsigned int start, end, tx_time; unsigned int trig_level; unsigned int tx_len = 0, rx_len = 0; @@ -289,14 +296,14 @@ static int sun6i_spi_transfer_one(struct spi_master *master, * the hardcoded value used in old generation of Allwinner * SPI controller. (See spi-sun4i.c) */ - trig_level = sspi->fifo_depth / 4 * 3; + trig_level = sspi->cfg->fifo_depth / 4 * 3; } else { /* * Setup FIFO DMA request trigger level * We choose 1/2 of the full fifo depth, that value will * be used as DMA burst length. */ - trig_level = sspi->fifo_depth / 2; + trig_level = sspi->cfg->fifo_depth / 2; if (tfr->tx_buf) reg |= SUN6I_FIFO_CTL_TF_DRQ_EN; @@ -346,39 +353,65 @@ static int sun6i_spi_transfer_one(struct spi_master *master, sun6i_spi_write(sspi, SUN6I_TFR_CTL_REG, reg); - /* Ensure that we have a parent clock fast enough */ - mclk_rate = clk_get_rate(sspi->mclk); - if (mclk_rate < (2 * tfr->speed_hz)) { - clk_set_rate(sspi->mclk, 2 * tfr->speed_hz); - mclk_rate = clk_get_rate(sspi->mclk); - } + if (sspi->cfg->has_clk_ctl) { + unsigned int mclk_rate = clk_get_rate(sspi->mclk); - /* - * Setup clock divider. - * - * We have two choices there. Either we can use the clock - * divide rate 1, which is calculated thanks to this formula: - * SPI_CLK = MOD_CLK / (2 ^ cdr) - * Or we can use CDR2, which is calculated with the formula: - * SPI_CLK = MOD_CLK / (2 * (cdr + 1)) - * Wether we use the former or the latter is set through the - * DRS bit. - * - * First try CDR2, and if we can't reach the expected - * frequency, fall back to CDR1. - */ - div_cdr1 = DIV_ROUND_UP(mclk_rate, tfr->speed_hz); - div_cdr2 = DIV_ROUND_UP(div_cdr1, 2); - if (div_cdr2 <= (SUN6I_CLK_CTL_CDR2_MASK + 1)) { - reg = SUN6I_CLK_CTL_CDR2(div_cdr2 - 1) | SUN6I_CLK_CTL_DRS; - tfr->effective_speed_hz = mclk_rate / (2 * div_cdr2); + /* Ensure that we have a parent clock fast enough */ + if (mclk_rate < (2 * tfr->speed_hz)) { + clk_set_rate(sspi->mclk, 2 * tfr->speed_hz); + mclk_rate = clk_get_rate(sspi->mclk); + } + + /* + * Setup clock divider. + * + * We have two choices there. Either we can use the clock + * divide rate 1, which is calculated thanks to this formula: + * SPI_CLK = MOD_CLK / (2 ^ cdr) + * Or we can use CDR2, which is calculated with the formula: + * SPI_CLK = MOD_CLK / (2 * (cdr + 1)) + * Wether we use the former or the latter is set through the + * DRS bit. + * + * First try CDR2, and if we can't reach the expected + * frequency, fall back to CDR1. + */ + div_cdr1 = DIV_ROUND_UP(mclk_rate, tfr->speed_hz); + div_cdr2 = DIV_ROUND_UP(div_cdr1, 2); + if (div_cdr2 <= (SUN6I_CLK_CTL_CDR2_MASK + 1)) { + reg = SUN6I_CLK_CTL_CDR2(div_cdr2 - 1) | SUN6I_CLK_CTL_DRS; + tfr->effective_speed_hz = mclk_rate / (2 * div_cdr2); + } else { + div = min(SUN6I_CLK_CTL_CDR1_MASK, order_base_2(div_cdr1)); + reg = SUN6I_CLK_CTL_CDR1(div); + tfr->effective_speed_hz = mclk_rate / (1 << div); + } + + sun6i_spi_write(sspi, SUN6I_CLK_CTL_REG, reg); } else { - div = min(SUN6I_CLK_CTL_CDR1_MASK, order_base_2(div_cdr1)); - reg = SUN6I_CLK_CTL_CDR1(div); - tfr->effective_speed_hz = mclk_rate / (1 << div); + clk_set_rate(sspi->mclk, tfr->speed_hz); + tfr->effective_speed_hz = clk_get_rate(sspi->mclk); + + /* + * Configure work mode. + * + * There are three work modes depending on the controller clock + * frequency: + * - normal sample mode : CLK <= 24MHz SDM=1 SDC=0 + * - delay half-cycle sample mode : CLK <= 40MHz SDM=0 SDC=0 + * - delay one-cycle sample mode : CLK >= 80MHz SDM=0 SDC=1 + */ + reg = sun6i_spi_read(sspi, SUN6I_TFR_CTL_REG); + reg &= ~(SUN6I_TFR_CTL_SDM | SUN6I_TFR_CTL_SDC); + + if (tfr->effective_speed_hz <= 24000000) + reg |= SUN6I_TFR_CTL_SDM; + else if (tfr->effective_speed_hz >= 80000000) + reg |= SUN6I_TFR_CTL_SDC; + + sun6i_spi_write(sspi, SUN6I_TFR_CTL_REG, reg); } - sun6i_spi_write(sspi, SUN6I_CLK_CTL_REG, reg); /* Finally enable the bus - doing so before might raise SCK to HIGH */ reg = sun6i_spi_read(sspi, SUN6I_GBL_CTL_REG); reg |= SUN6I_GBL_CTL_BUS_ENABLE; @@ -410,9 +443,9 @@ static int sun6i_spi_transfer_one(struct spi_master *master, reg = SUN6I_INT_CTL_TC; if (!use_dma) { - if (rx_len > sspi->fifo_depth) + if (rx_len > sspi->cfg->fifo_depth) reg |= SUN6I_INT_CTL_RF_RDY; - if (tx_len > sspi->fifo_depth) + if (tx_len > sspi->cfg->fifo_depth) reg |= SUN6I_INT_CTL_TF_ERQ; } @@ -422,7 +455,7 @@ static int sun6i_spi_transfer_one(struct spi_master *master, reg = sun6i_spi_read(sspi, SUN6I_TFR_CTL_REG); sun6i_spi_write(sspi, SUN6I_TFR_CTL_REG, reg | SUN6I_TFR_CTL_XCH); - tx_time = max(tfr->len * 8 * 2 / (tfr->speed_hz / 1000), 100U); + tx_time = spi_controller_xfer_timeout(master, tfr); start = jiffies; timeout = wait_for_completion_timeout(&sspi->done, msecs_to_jiffies(tx_time)); @@ -543,7 +576,7 @@ static bool sun6i_spi_can_dma(struct spi_master *master, * the fifo length we can just fill the fifo and wait for a single * irq, so don't bother setting up dma */ - return xfer->len > sspi->fifo_depth; + return xfer->len > sspi->cfg->fifo_depth; } static int sun6i_spi_probe(struct platform_device *pdev) @@ -582,7 +615,7 @@ static int sun6i_spi_probe(struct platform_device *pdev) } sspi->master = master; - sspi->fifo_depth = (unsigned long)of_device_get_match_data(&pdev->dev); + sspi->cfg = of_device_get_match_data(&pdev->dev); master->max_speed_hz = 100 * 1000 * 1000; master->min_speed_hz = 3 * 1000; @@ -695,9 +728,27 @@ static void sun6i_spi_remove(struct platform_device *pdev) dma_release_channel(master->dma_rx); } +static const struct sun6i_spi_cfg sun6i_a31_spi_cfg = { + .fifo_depth = SUN6I_FIFO_DEPTH, + .has_clk_ctl = true, +}; + +static const struct sun6i_spi_cfg sun8i_h3_spi_cfg = { + .fifo_depth = SUN8I_FIFO_DEPTH, + .has_clk_ctl = true, +}; + +static const struct sun6i_spi_cfg sun50i_r329_spi_cfg = { + .fifo_depth = SUN8I_FIFO_DEPTH, +}; + static const struct of_device_id sun6i_spi_match[] = { - { .compatible = "allwinner,sun6i-a31-spi", .data = (void *)SUN6I_FIFO_DEPTH }, - { .compatible = "allwinner,sun8i-h3-spi", .data = (void *)SUN8I_FIFO_DEPTH }, + { .compatible = "allwinner,sun6i-a31-spi", .data = &sun6i_a31_spi_cfg }, + { .compatible = "allwinner,sun8i-h3-spi", .data = &sun8i_h3_spi_cfg }, + { + .compatible = "allwinner,sun50i-r329-spi", + .data = &sun50i_r329_spi_cfg + }, {} }; MODULE_DEVICE_TABLE(of, sun6i_spi_match); diff --git a/drivers/spi/spi-xcomm.c b/drivers/spi/spi-xcomm.c index 5d23411f2a3e9c021fc011f40ffd1b98659f7ff7..ae6218bcd02a072235e72d443769b8665debbedf 100644 --- a/drivers/spi/spi-xcomm.c +++ b/drivers/spi/spi-xcomm.c @@ -241,7 +241,7 @@ static struct i2c_driver spi_xcomm_driver = { .name = "spi-xcomm", }, .id_table = spi_xcomm_ids, - .probe_new = spi_xcomm_probe, + .probe = spi_xcomm_probe, }; module_i2c_driver(spi_xcomm_driver); diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c index 39d94c8508390f5007673993ecac914cd7a071bf..d13dc15cc1919ce6e0304f1b05800f26715eaf6a 100644 --- a/drivers/spi/spidev.c +++ b/drivers/spi/spidev.c @@ -64,7 +64,8 @@ static_assert(N_SPI_MINORS > 0 && N_SPI_MINORS <= 256); | SPI_NO_CS | SPI_READY | SPI_TX_DUAL \ | SPI_TX_QUAD | SPI_TX_OCTAL | SPI_RX_DUAL \ | SPI_RX_QUAD | SPI_RX_OCTAL \ - | SPI_RX_CPHA_FLIP) + | SPI_RX_CPHA_FLIP | SPI_3WIRE_HIZ \ + | SPI_MOSI_IDLE_LOW) struct spidev_data { dev_t devt; @@ -237,7 +238,7 @@ static int spidev_message(struct spidev_data *spidev, /* Ensure that also following allocations from rx_buf/tx_buf will meet * DMA alignment requirements. */ - unsigned int len_aligned = ALIGN(u_tmp->len, ARCH_KMALLOC_MINALIGN); + unsigned int len_aligned = ALIGN(u_tmp->len, ARCH_DMA_MINALIGN); k_tmp->len = u_tmp->len; diff --git a/drivers/staging/axis-fifo/axis-fifo.c b/drivers/staging/axis-fifo/axis-fifo.c index 7a21f24232044b16b6ff04bd7229c4170a4cdef8..98db47cb4fa450c5d2ada0c84b22af9d240631f7 100644 --- a/drivers/staging/axis-fifo/axis-fifo.c +++ b/drivers/staging/axis-fifo/axis-fifo.c @@ -906,9 +906,6 @@ static int axis_fifo_probe(struct platform_device *pdev) if (rc < 0) goto err_initial; - dev_info(fifo->dt_device, "axis-fifo created at %pa mapped to 0x%pa, irq=%i\n", - &r_mem->start, &fifo->base_addr, fifo->irq); - return 0; err_initial: diff --git a/drivers/staging/iio/addac/adt7316-i2c.c b/drivers/staging/iio/addac/adt7316-i2c.c index 7e3d1a6f30ba96dc25591e4b889fba01b7b96740..6c1f91c859ca613b00d7f577a2242cff969d536b 100644 --- a/drivers/staging/iio/addac/adt7316-i2c.c +++ b/drivers/staging/iio/addac/adt7316-i2c.c @@ -138,7 +138,7 @@ static struct i2c_driver adt7316_driver = { .of_match_table = adt7316_of_match, .pm = ADT7316_PM_OPS, }, - .probe_new = adt7316_i2c_probe, + .probe = adt7316_i2c_probe, .id_table = adt7316_i2c_id, }; module_i2c_driver(adt7316_driver); diff --git a/drivers/staging/iio/impedance-analyzer/ad5933.c b/drivers/staging/iio/impedance-analyzer/ad5933.c index b3152f7153fbb1cf2199c32b2e384c18d2d87c36..46db6d91542a40a6ee9fcd683b911fac201deb31 100644 --- a/drivers/staging/iio/impedance-analyzer/ad5933.c +++ b/drivers/staging/iio/impedance-analyzer/ad5933.c @@ -781,7 +781,7 @@ static struct i2c_driver ad5933_driver = { .name = "ad5933", .of_match_table = ad5933_of_match, }, - .probe_new = ad5933_probe, + .probe = ad5933_probe, .id_table = ad5933_id, }; module_i2c_driver(ad5933_driver); diff --git a/drivers/staging/media/atomisp/Makefile b/drivers/staging/media/atomisp/Makefile index 532e12ed72e6e25cae6c1b953c4ae1c1474f2d4b..38b37012410980c16643bcc5a11ca9cfa8f89e9b 100644 --- a/drivers/staging/media/atomisp/Makefile +++ b/drivers/staging/media/atomisp/Makefile @@ -16,6 +16,7 @@ atomisp-objs += \ pci/atomisp_cmd.o \ pci/atomisp_compat_css20.o \ pci/atomisp_csi2.o \ + pci/atomisp_csi2_bridge.o \ pci/atomisp_drvfs.o \ pci/atomisp_fops.o \ pci/atomisp_ioctl.o \ diff --git a/drivers/staging/media/atomisp/TODO b/drivers/staging/media/atomisp/TODO index 43b842043f2932d2517e84475471cd50cd2e7a04..ecf8ba67b7afafd2814b2f3b901c07163de5d6df 100644 --- a/drivers/staging/media/atomisp/TODO +++ b/drivers/staging/media/atomisp/TODO @@ -1,213 +1,113 @@ -For both Cherrytrail (CHT) and Baytrail (BHT) the driver -requires the "candrpv_0415_20150521_0458" firmware version. -It should be noticed that the firmware file is different, -depending on the ISP model, so they're stored with different -names: +Required firmware +================= -- for BHT: /lib/firmware/shisp_2400b0_v21.bin +The atomisp driver requires the following firmware: - Warning: The driver was not tested yet for BHT. +- for BYT: /lib/firmware/shisp_2400b0_v21.bin -- for CHT: /lib/firmware/shisp_2401a0_v21.bin - - https://github.com/intel-aero/meta-intel-aero-base/blob/master/recipes-kernel/linux/linux-yocto/shisp_2401a0_v21.bin - -NOTE: -===== - -This driver currently doesn't work with most V4L2 applications, -as there are still some issues with regards to implementing -certain APIs at the standard way. - -Also, currently only USERPTR streaming mode is working. - -In order to test, it is needed to know what's the sensor's -resolution. This can be checked with: - -$ v4l2-ctl --get-fmt-video - Format Video Capture: - Width/Height : 1600/1200 - ... + With a version of "irci_stable_candrpv_0415_20150423_1753" to check + the version run: "strings shisp_2400b0_v21.bin | head -n1", sha256sum: -It is known to work with: + 3847b95fb9f1f8352c595ba7394d55b33176751372baae17f89aa483ec02a21b shisp_2400b0_v21.bin -- v4l2grab at contrib/test directory at https://git.linuxtv.org/v4l-utils.git/ + The shisp_2400b0_v21.bin file with this version can be found on + the Android factory images of various X86 Android tablets such as + e.g. the Chuwi Hi8 Pro. - The resolution should not be bigger than the max resolution - supported by the sensor, or it will fail. So, if the sensor - reports: - - The driver can be tested with: - - v4l2grab -f YUYV -x 1600 -y 1200 -d /dev/video2 -u +- for CHT: /lib/firmware/shisp_2401a0_v21.bin -- NVT at https://github.com/intel/nvt + With a version of "irci_stable_candrpv_0415_20150521_0458", sha256sum: - $ ./v4l2n -o testimage_@.raw \ - --device /dev/video2 \ - --input 0 \ - --exposure=30000,30000,30000,30000 \ - --parm type=1,capturemode=CI_MODE_PREVIEW \ - --fmt type=1,width=1600,height=1200,pixelformat=YUYV \ - --reqbufs count=2,memory=USERPTR \ - --parameters=wb_config.r=32768,wb_config.gr=21043,wb_config.gb=21043,wb_config.b=30863 \ - --capture=20 + e89359f4e4934c410c83d525e283f34c5fcce9cb5caa75ad8a32d66d3842d95c shisp_2401a0_v21.bin - As the output is in raw format, images need to be converted with: + This can be found here: + https://github.com/intel-aero/meta-intel-aero-base/blob/master/recipes-kernel/linux/linux-yocto/shisp_2401a0_v21.bin - $ for i in $(seq 0 19); do - name="testimage_$(printf "%03i" $i)" - ./raw2pnm -x$WIDTH -y$HEIGHT -f$FORMAT $name.raw $name.pnm - rm $name.raw - done TODO ==== -1. Fix support for MMAP streaming mode. This is required for most - V4L2 applications; - -2. Implement and/or fix V4L2 ioctls in order to allow a normal app to - use it; - -3. Ensure that the driver will pass v4l2-compliance tests; - -4. Get manufacturer's authorization to redistribute the binaries for - the firmware files; - -5. remove VIDEO_ATOMISP_ISP2401, making the driver to auto-detect the - register address differences between ISP2400 and ISP2401; - -6. Cleanup the driver code, removing the abstraction layers inside it; - -7. The atomisp doesn't rely at the usual i2c stuff to discover the - sensors. Instead, it calls a function from atomisp_gmin_platform.c. - There are some hacks added there for it to wait for sensors to be - probed (with a timeout of 2 seconds or so). This should be converted - to the usual way, using V4L2 async subdev framework to wait for - cameras to be probed; - -8. Switch to standard V4L2 sub-device API for sensor and lens. In - particular, the user space API needs to support V4L2 controls as - defined in the V4L2 spec and references to atomisp must be removed from - these drivers. - -9. Use LED flash API for flash LED drivers such as LM3554 (which already - has a LED class driver). - -10. Migrate the sensor drivers out of staging or re-using existing - drivers; - -11. Switch the driver to use pm_runtime stuff. Right now, it probes the - existing PMIC code and sensors call it directly. - -12. There's a problem on sensor drivers: when trying to set a video - format, the atomisp main driver calls the sensor drivers with the - sensor turned off. This causes them to fail. - - This was fixed at atomisp-ov2880, which has a hack inside it - to turn it on when VIDIOC_S_FMT is called, but this has to be - cheked on other drivers as well. - - The right fix seems to power on the sensor when a video device is - opened (or at the first VIDIOC_ ioctl - except for VIDIOC_QUERYCAP), - powering it down at close() syscall. - - Such kind of control would need to be done inside the atomisp driver, - not at the sensors code. - -13. There are several issues related to memory management, that can - cause crashes and/or memory leaks. The atomisp splits the memory - management on three separate regions: - - - dynamic pool; - - reserved pool; - - generic pool - - The code implementing it is at: - - drivers/staging/media/atomisp/pci/hmm/ +1. Items which MUST be fixed before the driver can be moved out of staging: - It also has a separate code for managing DMA buffers at: +* The atomisp ov2680 and ov5693 sensor drivers bind to the same hw-ids as + the standard ov2680 and ov5693 drivers under drivers/media/i2c, which + conflicts. Drop the atomisp private ov2680 and ov5693 drivers: + * Port various ov2680 improvements from atomisp_ov2680.c to regular ov2680.c + and switch to regular ov2680 driver + * Make atomisp work with the regular ov5693 driver and drop atomisp_ov5693 - drivers/staging/media/atomisp/pci/mmu/ +* Fix atomisp causing the whole machine to hang in its probe() error-exit + path taken in the firmware missing case - The code there is really dirty, ugly and probably wrong. I fixed - one bug there already, but the best would be to just trash it and use - something else. Maybe the code from the newer intel driver could - serve as a model: +* Remove/disable private IOCTLs - drivers/staging/media/ipu3/ipu3-mmu.c +* Remove/disable custom v4l2-ctrls - But converting it to use something like that is painful and may - cause some breakages. +* Remove custom sysfs files created by atomisp_drvfs.c -14. The file structure needs to get tidied up to resemble a normal Linux - driver. +* Remove abuse of priv field in various v4l2 userspace API structs -15. Lots of the midlayer glue. Unused code and abstraction needs removing. +* Without a 3A library the capture behaviour is not very good. To take a good + picture, the exposure/gain needs to be tuned using v4l2-ctl on the sensor + subdev. To fix this, support for the atomisp needs to be added to libcamera. -16. The AtomISP driver includes some special IOCTLS (ATOMISP_IOC_XXXX_XXXX) - and controls that require some cleanup. Some of those code may have - been removed during the cleanups. They could be needed in order to - properly support 3A algorithms. + This MUST be done before moving the driver out of staging so that we can + still make changes to e.g. the mediactl topology if necessary for + libcamera integration. Since this would be a userspace API break, this + means that at least proof-of-concept libcamera integration needs to be + ready before moving the driver out of staging. - Such IOCTL interface needs more documentation. The better would - be to use something close to the interface used by the IPU3 IMGU driver. -17. The ISP code has some dependencies of the exact FW version. - The version defined in pci/sh_css_firmware.c: +2. Items which SHOULD also be fixed eventually: - BYT (isp2400): "irci_stable_candrpv_0415_20150521_0458" +* Remove VIDEO_ATOMISP_ISP2401, making the driver to auto-detect the + register address differences between ISP2400 and ISP2401 - CHT (isp2401): "irci_ecr - master_20150911_0724" +* The driver is intended to drive the PCI exposed versions of the device. + It will not detect those devices enumerated via ACPI as a field of the + i915 GPU driver (only a problem on BYT). - Those versions don't seem to be available anymore. On the tests we've - done so far, this version also seems to work for CHT: + There are some patches adding i915 GPU support floating at the Yocto's + Aero repository (so far, untested upstream). - "irci_stable_candrpv_0415_20150521_0458" +* Ensure that the driver will pass v4l2-compliance tests - Which can be obtainable from Yocto Atom ISP respository. +* Fix not all v4l2 apps working, e.g. cheese does not work - but this was not thoroughly tested. +* Get manufacturer's authorization to redistribute the binaries for + the firmware files - At some point we may need to round up a few driver versions and see if - there are any specific things that can be done to fold in support for - multiple firmware versions. +* The atomisp code still has a lot of cruft which needs cleaning up -18. Switch from videobuf1 to videobuf2. Videobuf1 is being removed! +Testing +======= -19. Correct Coding Style. Please refrain sending coding style patches - for this driver until the other work is done, as there will be a lot - of code churn until this driver becomes functional again. +Since libcamera support is not available yet, the easiest way to test for +now is using v4l2-ctl to select the input and gstreamer for streaming. -20. Remove the logic which sets up pipelines inside it, moving it to - libcamera and implement MC support. +To select the input run: +v4l2-ctl -i -Limitations -=========== +Where is 0 (front cam) or 1 (back cam). -1. To test the patches, you also need the ISP firmware +The simplest gstreamer pipeline for testing running the sensor +at its max resolution is: - for BYT: /lib/firmware/shisp_2400b0_v21.bin - for CHT: /lib/firmware/shisp_2401a0_v21.bin +gst-launch-1.0 v4l2src ! videoconvert ! xvimagesink sync=false - The firmware files will usually be found in /etc/firmware on an Android - device but can also be extracted from the upgrade kit if you've managed - to lose them somehow. +To select e.g 640x480 as resolution use: -2. Without a 3A library the capture behaviour is not very good. To take a good - picture, you need tune ISP parameters by IOCTL functions or use a 3A library - such as libxcam. +gst-launch-1.0 v4l2src ! video/x-raw,format=YV12,width=640,height=480 ! \ + videoconvert ! xvimagesink sync=false -3. The driver is intended to drive the PCI exposed versions of the device. - It will not detect those devices enumerated via ACPI as a field of the - i915 GPU driver. +And to show fps use: - There are some patches adding i915 GPU support floating at the Yocto's - Aero repository (so far, untested upstream). +gst-launch-1.0 v4l2src ! video/x-raw,format=YV12,width=640,height=480 ! \ + videoconvert ! fpsdisplaysink video-sink=xvimagesink sync=false -4. The driver supports only v2 of the IPU/Camera. It will not work with the - versions of the hardware in other SoCs. +Often the image will be over / under exposed. This can be fixed by using +v4l2-ctl on the sensor subdev to tweak the exposure ctrl; or by using a GUI +app for v4l2-controls which also supports subdev such as the Fedora patched +gtk-v4l tool. diff --git a/drivers/staging/media/atomisp/i2c/atomisp-gc0310.c b/drivers/staging/media/atomisp/i2c/atomisp-gc0310.c index 273155308fe36fb0fca8158b21fc0cd06a64a9c7..9a11793f34f74b624193d5a570c278a2fe50b14d 100644 --- a/drivers/staging/media/atomisp/i2c/atomisp-gc0310.c +++ b/drivers/staging/media/atomisp/i2c/atomisp-gc0310.c @@ -16,27 +16,259 @@ * */ -#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/linux/atomisp_gmin_platform.h" -#include "gc0310.h" +#define GC0310_NATIVE_WIDTH 656 +#define GC0310_NATIVE_HEIGHT 496 + +#define GC0310_FPS 30 +#define GC0310_SKIP_FRAMES 3 + +#define GC0310_FOCAL_LENGTH_NUM 278 /* 2.78mm */ + +#define GC0310_ID 0xa310 + +#define GC0310_RESET_RELATED 0xFE +#define GC0310_REGISTER_PAGE_0 0x0 +#define GC0310_REGISTER_PAGE_3 0x3 + +/* + * GC0310 System control registers + */ +#define GC0310_SW_STREAM 0x10 + +#define GC0310_SC_CMMN_CHIP_ID_H 0xf0 +#define GC0310_SC_CMMN_CHIP_ID_L 0xf1 + +#define GC0310_AEC_PK_EXPO_H 0x03 +#define GC0310_AEC_PK_EXPO_L 0x04 +#define GC0310_AGC_ADJ 0x48 +#define GC0310_DGC_ADJ 0x71 +#define GC0310_GROUP_ACCESS 0x3208 + +#define GC0310_H_CROP_START_H 0x09 +#define GC0310_H_CROP_START_L 0x0A +#define GC0310_V_CROP_START_H 0x0B +#define GC0310_V_CROP_START_L 0x0C +#define GC0310_H_OUTSIZE_H 0x0F +#define GC0310_H_OUTSIZE_L 0x10 +#define GC0310_V_OUTSIZE_H 0x0D +#define GC0310_V_OUTSIZE_L 0x0E +#define GC0310_H_BLANKING_H 0x05 +#define GC0310_H_BLANKING_L 0x06 +#define GC0310_V_BLANKING_H 0x07 +#define GC0310_V_BLANKING_L 0x08 +#define GC0310_SH_DELAY 0x11 + +#define GC0310_START_STREAMING 0x94 /* 8-bit enable */ +#define GC0310_STOP_STREAMING 0x0 /* 8-bit disable */ + +#define to_gc0310_sensor(x) container_of(x, struct gc0310_device, sd) + +struct gc0310_device { + struct v4l2_subdev sd; + struct media_pad pad; + /* Protect against concurrent changes to controls */ + struct mutex input_lock; + bool is_streaming; + + struct fwnode_handle *ep_fwnode; + struct gpio_desc *reset; + struct gpio_desc *powerdown; + + struct gc0310_mode { + struct v4l2_mbus_framefmt fmt; + } mode; + + struct gc0310_ctrls { + struct v4l2_ctrl_handler handler; + struct v4l2_ctrl *exposure; + struct v4l2_ctrl *gain; + } ctrls; +}; + +struct gc0310_reg { + u8 reg; + u8 val; +}; + +static const struct gc0310_reg gc0310_reset_register[] = { + /* System registers */ + { 0xfe, 0xf0 }, + { 0xfe, 0xf0 }, + { 0xfe, 0x00 }, + + { 0xfc, 0x0e }, /* 4e */ + { 0xfc, 0x0e }, /* 16//4e // [0]apwd [6]regf_clk_gate */ + { 0xf2, 0x80 }, /* sync output */ + { 0xf3, 0x00 }, /* 1f//01 data output */ + { 0xf7, 0x33 }, /* f9 */ + { 0xf8, 0x05 }, /* 00 */ + { 0xf9, 0x0e }, /* 0x8e //0f */ + { 0xfa, 0x11 }, + + /* MIPI */ + { 0xfe, 0x03 }, + { 0x01, 0x03 }, /* mipi 1lane */ + { 0x02, 0x22 }, /* 0x33 */ + { 0x03, 0x94 }, + { 0x04, 0x01 }, /* fifo_prog */ + { 0x05, 0x00 }, /* fifo_prog */ + { 0x06, 0x80 }, /* b0 //YUV ISP data */ + { 0x11, 0x2a }, /* 1e //LDI set YUV422 */ + { 0x12, 0x90 }, /* 00 //04 //00 //04//00 //LWC[7:0] */ + { 0x13, 0x02 }, /* 05 //05 //LWC[15:8] */ + { 0x15, 0x12 }, /* 0x10 //DPHYY_MODE read_ready */ + { 0x17, 0x01 }, + { 0x40, 0x08 }, + { 0x41, 0x00 }, + { 0x42, 0x00 }, + { 0x43, 0x00 }, + { 0x21, 0x02 }, /* 0x01 */ + { 0x22, 0x02 }, /* 0x01 */ + { 0x23, 0x01 }, /* 0x05 //Nor:0x05 DOU:0x06 */ + { 0x29, 0x00 }, + { 0x2A, 0x25 }, /* 0x05 //data zero 0x7a de */ + { 0x2B, 0x02 }, + + { 0xfe, 0x00 }, + + /* CISCTL */ + { 0x00, 0x2f }, /* 2f//0f//02//01 */ + { 0x01, 0x0f }, /* 06 */ + { 0x02, 0x04 }, + { 0x4f, 0x00 }, /* AEC 0FF */ + { 0x03, 0x01 }, /* 0x03 //04 */ + { 0x04, 0xc0 }, /* 0xe8 //58 */ + { 0x05, 0x00 }, + { 0x06, 0xb2 }, /* 0x0a //HB */ + { 0x07, 0x00 }, + { 0x08, 0x0c }, /* 0x89 //VB */ + { 0x09, 0x00 }, /* row start */ + { 0x0a, 0x00 }, + { 0x0b, 0x00 }, /* col start */ + { 0x0c, 0x00 }, + { 0x0d, 0x01 }, /* height */ + { 0x0e, 0xf2 }, /* 0xf7 //height */ + { 0x0f, 0x02 }, /* width */ + { 0x10, 0x94 }, /* 0xa0 //height */ + { 0x17, 0x14 }, + { 0x18, 0x1a }, /* 0a//[4]double reset */ + { 0x19, 0x14 }, /* AD pipeline */ + { 0x1b, 0x48 }, + { 0x1e, 0x6b }, /* 3b//col bias */ + { 0x1f, 0x28 }, /* 20//00//08//txlow */ + { 0x20, 0x89 }, /* 88//0c//[3:2]DA15 */ + { 0x21, 0x49 }, /* 48//[3] txhigh */ + { 0x22, 0xb0 }, + { 0x23, 0x04 }, /* [1:0]vcm_r */ + { 0x24, 0x16 }, /* 15 */ + { 0x34, 0x20 }, /* [6:4] rsg high//range */ + + /* BLK */ + { 0x26, 0x23 }, /* [1]dark_current_en [0]offset_en */ + { 0x28, 0xff }, /* BLK_limie_value */ + { 0x29, 0x00 }, /* global offset */ + { 0x33, 0x18 }, /* offset_ratio */ + { 0x37, 0x20 }, /* dark_current_ratio */ + { 0x2a, 0x00 }, + { 0x2b, 0x00 }, + { 0x2c, 0x00 }, + { 0x2d, 0x00 }, + { 0x2e, 0x00 }, + { 0x2f, 0x00 }, + { 0x30, 0x00 }, + { 0x31, 0x00 }, + { 0x47, 0x80 }, /* a7 */ + { 0x4e, 0x66 }, /* select_row */ + { 0xa8, 0x02 }, /* win_width_dark, same with crop_win_width */ + { 0xa9, 0x80 }, + + /* ISP */ + { 0x40, 0x06 }, /* 0xff //ff //48 */ + { 0x41, 0x00 }, /* 0x21 //00//[0]curve_en */ + { 0x42, 0x04 }, /* 0xcf //0a//[1]awn_en */ + { 0x44, 0x18 }, /* 0x18 //02 */ + { 0x46, 0x02 }, /* 0x03 //sync */ + { 0x49, 0x03 }, + { 0x4c, 0x20 }, /* 00[5]pretect exp */ + { 0x50, 0x01 }, /* crop enable */ + { 0x51, 0x00 }, + { 0x52, 0x00 }, + { 0x53, 0x00 }, + { 0x54, 0x01 }, + { 0x55, 0x01 }, /* crop window height */ + { 0x56, 0xf0 }, + { 0x57, 0x02 }, /* crop window width */ + { 0x58, 0x90 }, + + /* Gain */ + { 0x70, 0x70 }, /* 70 //80//global gain */ + { 0x71, 0x20 }, /* pregain gain */ + { 0x72, 0x40 }, /* post gain */ + { 0x5a, 0x84 }, /* 84//analog gain 0 */ + { 0x5b, 0xc9 }, /* c9 */ + { 0x5c, 0xed }, /* ed//not use pga gain highest level */ + { 0x77, 0x40 }, /* R gain 0x74 //awb gain */ + { 0x78, 0x40 }, /* G gain */ + { 0x79, 0x40 }, /* B gain 0x5f */ + + { 0x48, 0x00 }, + { 0xfe, 0x01 }, + { 0x0a, 0x45 }, /* [7]col gain mode */ + + { 0x3e, 0x40 }, + { 0x3f, 0x5c }, + { 0x40, 0x7b }, + { 0x41, 0xbd }, + { 0x42, 0xf6 }, + { 0x43, 0x63 }, + { 0x03, 0x60 }, + { 0x44, 0x03 }, + + /* Dark / Sun mode related */ + { 0xfe, 0x01 }, + { 0x45, 0xa4 }, /* 0xf7 */ + { 0x46, 0xf0 }, /* 0xff //f0//sun value th */ + { 0x48, 0x03 }, /* sun mode */ + { 0x4f, 0x60 }, /* sun_clamp */ + { 0xfe, 0x00 }, +}; + +static const struct gc0310_reg gc0310_VGA_30fps[] = { + { 0xfe, 0x00 }, + { 0x0d, 0x01 }, /* height */ + { 0x0e, 0xf2 }, /* 0xf7 //height */ + { 0x0f, 0x02 }, /* width */ + { 0x10, 0x94 }, /* 0xa0 //height */ + + { 0x50, 0x01 }, /* crop enable */ + { 0x51, 0x00 }, + { 0x52, 0x00 }, + { 0x53, 0x00 }, + { 0x54, 0x01 }, + { 0x55, 0x01 }, /* crop window height */ + { 0x56, 0xf0 }, + { 0x57, 0x02 }, /* crop window width */ + { 0x58, 0x90 }, + + { 0xfe, 0x03 }, + { 0x12, 0x90 }, /* 00 //04 //00 //04//00 //LWC[7:0] */ + { 0x13, 0x02 }, /* 05 //05 //LWC[15:8] */ + + { 0xfe, 0x00 }, +}; /* * gc0310_write_reg_array - Initializes a list of GC0310 registers @@ -179,7 +411,10 @@ static int gc0310_detect(struct i2c_client *client) if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) return -ENODEV; - ret = i2c_smbus_read_word_swapped(client, GC0310_SC_CMMN_CHIP_ID_H); + ret = pm_runtime_get_sync(&client->dev); + if (ret >= 0) + ret = i2c_smbus_read_word_swapped(client, GC0310_SC_CMMN_CHIP_ID_H); + pm_runtime_put(&client->dev); if (ret < 0) { dev_err(&client->dev, "read sensor_id failed: %d\n", ret); return -ENODEV; @@ -268,19 +503,6 @@ static int gc0310_s_stream(struct v4l2_subdev *sd, int enable) return ret; } -static int gc0310_s_config(struct v4l2_subdev *sd) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - int ret; - - ret = pm_runtime_get_sync(&client->dev); - if (ret >= 0) - ret = gc0310_detect(client); - - pm_runtime_put(&client->dev); - return ret; -} - static int gc0310_g_frame_interval(struct v4l2_subdev *sd, struct v4l2_subdev_frame_interval *interval) { @@ -373,12 +595,12 @@ static void gc0310_remove(struct i2c_client *client) dev_dbg(&client->dev, "gc0310_remove...\n"); - atomisp_unregister_subdev(sd); - v4l2_device_unregister_subdev(sd); + v4l2_async_unregister_subdev(sd); media_entity_cleanup(&dev->sd.entity); v4l2_ctrl_handler_free(&dev->ctrls.handler); + mutex_destroy(&dev->input_lock); + fwnode_handle_put(dev->ep_fwnode); pm_runtime_disable(&client->dev); - kfree(dev); } static int gc0310_probe(struct i2c_client *client) @@ -390,19 +612,27 @@ static int gc0310_probe(struct i2c_client *client) if (!dev) return -ENOMEM; - ret = v4l2_get_acpi_sensor_info(&client->dev, NULL); - if (ret) - return ret; + /* + * Sometimes the fwnode graph is initialized by the bridge driver. + * Bridge drivers doing this may also add GPIO mappings, wait for this. + */ + dev->ep_fwnode = fwnode_graph_get_next_endpoint(dev_fwnode(&client->dev), NULL); + if (!dev->ep_fwnode) + return dev_err_probe(&client->dev, -EPROBE_DEFER, "waiting for fwnode graph endpoint\n"); dev->reset = devm_gpiod_get(&client->dev, "reset", GPIOD_OUT_HIGH); - if (IS_ERR(dev->reset)) + if (IS_ERR(dev->reset)) { + fwnode_handle_put(dev->ep_fwnode); return dev_err_probe(&client->dev, PTR_ERR(dev->reset), "getting reset GPIO\n"); + } dev->powerdown = devm_gpiod_get(&client->dev, "powerdown", GPIOD_OUT_HIGH); - if (IS_ERR(dev->powerdown)) + if (IS_ERR(dev->powerdown)) { + fwnode_handle_put(dev->ep_fwnode); return dev_err_probe(&client->dev, PTR_ERR(dev->powerdown), "getting powerdown GPIO\n"); + } mutex_init(&dev->input_lock); v4l2_i2c_subdev_init(&dev->sd, client, &gc0310_ops); @@ -413,7 +643,7 @@ static int gc0310_probe(struct i2c_client *client) pm_runtime_set_autosuspend_delay(&client->dev, 1000); pm_runtime_use_autosuspend(&client->dev); - ret = gc0310_s_config(&dev->sd); + ret = gc0310_detect(client); if (ret) { gc0310_remove(client); return ret; @@ -422,6 +652,7 @@ static int gc0310_probe(struct i2c_client *client) dev->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; dev->pad.flags = MEDIA_PAD_FL_SOURCE; dev->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR; + dev->sd.fwnode = dev->ep_fwnode; ret = gc0310_init_controls(dev); if (ret) { @@ -435,8 +666,7 @@ static int gc0310_probe(struct i2c_client *client) return ret; } - ret = atomisp_register_sensor_no_gmin(&dev->sd, 1, ATOMISP_INPUT_FORMAT_RAW_8, - atomisp_bayer_order_grbg); + ret = v4l2_async_register_subdev_sensor(&dev->sd); if (ret) { gc0310_remove(client); return ret; @@ -471,7 +701,6 @@ static int gc0310_resume(struct device *dev) static DEFINE_RUNTIME_DEV_PM_OPS(gc0310_pm_ops, gc0310_suspend, gc0310_resume, NULL); static const struct acpi_device_id gc0310_acpi_match[] = { - {"XXGC0310"}, {"INT0310"}, {}, }; @@ -483,7 +712,7 @@ static struct i2c_driver gc0310_driver = { .pm = pm_sleep_ptr(&gc0310_pm_ops), .acpi_match_table = gc0310_acpi_match, }, - .probe_new = gc0310_probe, + .probe = gc0310_probe, .remove = gc0310_remove, }; module_i2c_driver(gc0310_driver); diff --git a/drivers/staging/media/atomisp/i2c/atomisp-gc2235.c b/drivers/staging/media/atomisp/i2c/atomisp-gc2235.c index cb4c79b483ca1f58ee1f4ecbcab68534a53d5973..9fa390fbc5f31e3c3b28dc266261a9a68d736cef 100644 --- a/drivers/staging/media/atomisp/i2c/atomisp-gc2235.c +++ b/drivers/staging/media/atomisp/i2c/atomisp-gc2235.c @@ -864,7 +864,7 @@ static struct i2c_driver gc2235_driver = { .name = "gc2235", .acpi_match_table = gc2235_acpi_match, }, - .probe_new = gc2235_probe, + .probe = gc2235_probe, .remove = gc2235_remove, }; module_i2c_driver(gc2235_driver); diff --git a/drivers/staging/media/atomisp/i2c/atomisp-lm3554.c b/drivers/staging/media/atomisp/i2c/atomisp-lm3554.c index c4ce4cd445d7755aa4114a53b1437678a61fb275..cf5d9317b11aba54917d8354fcdbf37a9f545fa9 100644 --- a/drivers/staging/media/atomisp/i2c/atomisp-lm3554.c +++ b/drivers/staging/media/atomisp/i2c/atomisp-lm3554.c @@ -945,7 +945,7 @@ static struct i2c_driver lm3554_driver = { .pm = &lm3554_pm_ops, .acpi_match_table = lm3554_acpi_match, }, - .probe_new = lm3554_probe, + .probe = lm3554_probe, .remove = lm3554_remove, }; module_i2c_driver(lm3554_driver); diff --git a/drivers/staging/media/atomisp/i2c/atomisp-mt9m114.c b/drivers/staging/media/atomisp/i2c/atomisp-mt9m114.c index 0e5a981dd331c6d7dcc662872f4bf4ef3b362290..1c6643c442ef3607c781c6224101ce0162c522bf 100644 --- a/drivers/staging/media/atomisp/i2c/atomisp-mt9m114.c +++ b/drivers/staging/media/atomisp/i2c/atomisp-mt9m114.c @@ -1600,7 +1600,7 @@ static struct i2c_driver mt9m114_driver = { .name = "mt9m114", .acpi_match_table = mt9m114_acpi_match, }, - .probe_new = mt9m114_probe, + .probe = mt9m114_probe, .remove = mt9m114_remove, }; module_i2c_driver(mt9m114_driver); diff --git a/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c b/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c index c079368019e87f5d7d5695ad9c2cff47e922042a..4cc2839937afe3f4663237559e45835a1fcb5184 100644 --- a/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c +++ b/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c @@ -28,15 +28,13 @@ #include #include -#include "../include/linux/atomisp_gmin_platform.h" - #include "ov2680.h" -static enum atomisp_bayer_order ov2680_bayer_order_mapping[] = { - atomisp_bayer_order_bggr, - atomisp_bayer_order_grbg, - atomisp_bayer_order_gbrg, - atomisp_bayer_order_rggb, +static const struct v4l2_rect ov2680_default_crop = { + .left = OV2680_ACTIVE_START_LEFT, + .top = OV2680_ACTIVE_START_TOP, + .width = OV2680_ACTIVE_WIDTH, + .height = OV2680_ACTIVE_HEIGHT, }; static int ov2680_write_reg_array(struct i2c_client *client, @@ -54,7 +52,7 @@ static int ov2680_write_reg_array(struct i2c_client *client, return 0; } -static void ov2680_set_bayer_order(struct ov2680_device *sensor, struct v4l2_mbus_framefmt *fmt) +static void ov2680_set_bayer_order(struct ov2680_dev *sensor, struct v4l2_mbus_framefmt *fmt) { static const int ov2680_hv_flip_bayer_order[] = { MEDIA_BUS_FMT_SBGGR10_1X10, @@ -62,7 +60,6 @@ static void ov2680_set_bayer_order(struct ov2680_device *sensor, struct v4l2_mbu MEDIA_BUS_FMT_SGBRG10_1X10, MEDIA_BUS_FMT_SRGGB10_1X10, }; - struct camera_mipi_info *ov2680_info; int hv_flip = 0; if (sensor->ctrls.vflip->val) @@ -72,14 +69,9 @@ static void ov2680_set_bayer_order(struct ov2680_device *sensor, struct v4l2_mbu hv_flip += 2; fmt->code = ov2680_hv_flip_bayer_order[hv_flip]; - - /* TODO atomisp specific custom API, should be removed */ - ov2680_info = v4l2_get_subdev_hostdata(&sensor->sd); - if (ov2680_info) - ov2680_info->raw_bayer_order = ov2680_bayer_order_mapping[hv_flip]; } -static int ov2680_set_vflip(struct ov2680_device *sensor, s32 val) +static int ov2680_set_vflip(struct ov2680_dev *sensor, s32 val) { int ret; @@ -94,7 +86,7 @@ static int ov2680_set_vflip(struct ov2680_device *sensor, s32 val) return 0; } -static int ov2680_set_hflip(struct ov2680_device *sensor, s32 val) +static int ov2680_set_hflip(struct ov2680_dev *sensor, s32 val) { int ret; @@ -109,17 +101,17 @@ static int ov2680_set_hflip(struct ov2680_device *sensor, s32 val) return 0; } -static int ov2680_exposure_set(struct ov2680_device *sensor, u32 exp) +static int ov2680_exposure_set(struct ov2680_dev *sensor, u32 exp) { return ov_write_reg24(sensor->client, OV2680_REG_EXPOSURE_PK_HIGH, exp << 4); } -static int ov2680_gain_set(struct ov2680_device *sensor, u32 gain) +static int ov2680_gain_set(struct ov2680_dev *sensor, u32 gain) { return ov_write_reg16(sensor->client, OV2680_REG_GAIN_PK, gain); } -static int ov2680_test_pattern_set(struct ov2680_device *sensor, int value) +static int ov2680_test_pattern_set(struct ov2680_dev *sensor, int value) { int ret; @@ -140,7 +132,7 @@ static int ov2680_test_pattern_set(struct ov2680_device *sensor, int value) static int ov2680_s_ctrl(struct v4l2_ctrl *ctrl) { struct v4l2_subdev *sd = ctrl_to_sd(ctrl); - struct ov2680_device *sensor = to_ov2680_sensor(sd); + struct ov2680_dev *sensor = to_ov2680_sensor(sd); int ret; /* Only apply changes to the controls if the device is powered up */ @@ -183,14 +175,17 @@ static int ov2680_init_registers(struct v4l2_subdev *sd) int ret; ret = ov_write_reg8(client, OV2680_SW_RESET, 0x01); + + /* Wait for sensor reset */ + usleep_range(1000, 2000); + ret |= ov2680_write_reg_array(client, ov2680_global_setting); return ret; } static struct v4l2_mbus_framefmt * -__ov2680_get_pad_format(struct ov2680_device *sensor, - struct v4l2_subdev_state *state, +__ov2680_get_pad_format(struct ov2680_dev *sensor, struct v4l2_subdev_state *state, unsigned int pad, enum v4l2_subdev_format_whence which) { if (which == V4L2_SUBDEV_FORMAT_TRY) @@ -199,7 +194,17 @@ __ov2680_get_pad_format(struct ov2680_device *sensor, return &sensor->mode.fmt; } -static void ov2680_fill_format(struct ov2680_device *sensor, +static struct v4l2_rect * +__ov2680_get_pad_crop(struct ov2680_dev *sensor, struct v4l2_subdev_state *state, + unsigned int pad, enum v4l2_subdev_format_whence which) +{ + if (which == V4L2_SUBDEV_FORMAT_TRY) + return v4l2_subdev_get_try_crop(&sensor->sd, state, pad); + + return &sensor->mode.crop; +} + +static void ov2680_fill_format(struct ov2680_dev *sensor, struct v4l2_mbus_framefmt *fmt, unsigned int width, unsigned int height) { @@ -210,13 +215,15 @@ static void ov2680_fill_format(struct ov2680_device *sensor, ov2680_set_bayer_order(sensor, fmt); } -static void ov2680_calc_mode(struct ov2680_device *sensor, int width, int height) +static void ov2680_calc_mode(struct ov2680_dev *sensor) { + int width = sensor->mode.fmt.width; + int height = sensor->mode.fmt.height; int orig_width = width; int orig_height = height; - if (width <= (OV2680_NATIVE_WIDTH / 2) && - height <= (OV2680_NATIVE_HEIGHT / 2)) { + if (width <= (sensor->mode.crop.width / 2) && + height <= (sensor->mode.crop.height / 2)) { sensor->mode.binning = true; width *= 2; height *= 2; @@ -224,8 +231,10 @@ static void ov2680_calc_mode(struct ov2680_device *sensor, int width, int height sensor->mode.binning = false; } - sensor->mode.h_start = ((OV2680_NATIVE_WIDTH - width) / 2) & ~1; - sensor->mode.v_start = ((OV2680_NATIVE_HEIGHT - height) / 2) & ~1; + sensor->mode.h_start = + (sensor->mode.crop.left + (sensor->mode.crop.width - width) / 2) & ~1; + sensor->mode.v_start = + (sensor->mode.crop.top + (sensor->mode.crop.height - height) / 2) & ~1; sensor->mode.h_end = min(sensor->mode.h_start + width + OV2680_END_MARGIN - 1, OV2680_NATIVE_WIDTH - 1); sensor->mode.v_end = min(sensor->mode.v_start + height + OV2680_END_MARGIN - 1, @@ -236,31 +245,25 @@ static void ov2680_calc_mode(struct ov2680_device *sensor, int width, int height sensor->mode.vts = OV2680_LINES_PER_FRAME; } -static int ov2680_set_mode(struct ov2680_device *sensor) +static int ov2680_set_mode(struct ov2680_dev *sensor) { struct i2c_client *client = sensor->client; - u8 pll_div, unknown, inc, fmt1, fmt2; + u8 sensor_ctrl_0a, inc, fmt1, fmt2; int ret; if (sensor->mode.binning) { - pll_div = 1; - unknown = 0x23; + sensor_ctrl_0a = 0x23; inc = 0x31; fmt1 = 0xc2; fmt2 = 0x01; } else { - pll_div = 0; - unknown = 0x21; + sensor_ctrl_0a = 0x21; inc = 0x11; fmt1 = 0xc0; fmt2 = 0x00; } - ret = ov_write_reg8(client, 0x3086, pll_div); - if (ret) - return ret; - - ret = ov_write_reg8(client, 0x370a, unknown); + ret = ov_write_reg8(client, OV2680_REG_SENSOR_CTRL_0A, sensor_ctrl_0a); if (ret) return ret; @@ -337,12 +340,18 @@ static int ov2680_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_state *sd_state, struct v4l2_subdev_format *format) { - struct ov2680_device *sensor = to_ov2680_sensor(sd); + struct ov2680_dev *sensor = to_ov2680_sensor(sd); struct v4l2_mbus_framefmt *fmt; + const struct v4l2_rect *crop; unsigned int width, height; - width = min_t(unsigned int, ALIGN(format->format.width, 2), OV2680_NATIVE_WIDTH); - height = min_t(unsigned int, ALIGN(format->format.height, 2), OV2680_NATIVE_HEIGHT); + crop = __ov2680_get_pad_crop(sensor, sd_state, format->pad, format->which); + + /* Limit set_fmt max size to crop width / height */ + width = clamp_t(unsigned int, ALIGN(format->format.width, 2), + OV2680_MIN_CROP_WIDTH, crop->width); + height = clamp_t(unsigned int, ALIGN(format->format.height, 2), + OV2680_MIN_CROP_HEIGHT, crop->height); fmt = __ov2680_get_pad_format(sensor, sd_state, format->pad, format->which); ov2680_fill_format(sensor, fmt, width, height); @@ -352,9 +361,9 @@ static int ov2680_set_fmt(struct v4l2_subdev *sd, if (format->which == V4L2_SUBDEV_FORMAT_TRY) return 0; - mutex_lock(&sensor->input_lock); - ov2680_calc_mode(sensor, fmt->width, fmt->height); - mutex_unlock(&sensor->input_lock); + mutex_lock(&sensor->lock); + ov2680_calc_mode(sensor); + mutex_unlock(&sensor->lock); return 0; } @@ -362,7 +371,7 @@ static int ov2680_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_state *sd_state, struct v4l2_subdev_format *format) { - struct ov2680_device *sensor = to_ov2680_sensor(sd); + struct ov2680_dev *sensor = to_ov2680_sensor(sd); struct v4l2_mbus_framefmt *fmt; fmt = __ov2680_get_pad_format(sensor, sd_state, format->pad, format->which); @@ -370,6 +379,105 @@ static int ov2680_get_fmt(struct v4l2_subdev *sd, return 0; } +static int ov2680_get_selection(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state, + struct v4l2_subdev_selection *sel) +{ + struct ov2680_dev *sensor = to_ov2680_sensor(sd); + + switch (sel->target) { + case V4L2_SEL_TGT_CROP: + mutex_lock(&sensor->lock); + sel->r = *__ov2680_get_pad_crop(sensor, state, sel->pad, sel->which); + mutex_unlock(&sensor->lock); + break; + case V4L2_SEL_TGT_NATIVE_SIZE: + case V4L2_SEL_TGT_CROP_BOUNDS: + sel->r.top = 0; + sel->r.left = 0; + sel->r.width = OV2680_NATIVE_WIDTH; + sel->r.height = OV2680_NATIVE_HEIGHT; + break; + case V4L2_SEL_TGT_CROP_DEFAULT: + sel->r.top = OV2680_ACTIVE_START_TOP; + sel->r.left = OV2680_ACTIVE_START_LEFT; + sel->r.width = OV2680_ACTIVE_WIDTH; + sel->r.height = OV2680_ACTIVE_HEIGHT; + break; + default: + return -EINVAL; + } + + return 0; +} + +static int ov2680_set_selection(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state, + struct v4l2_subdev_selection *sel) +{ + struct ov2680_dev *sensor = to_ov2680_sensor(sd); + struct v4l2_mbus_framefmt *format; + struct v4l2_rect *__crop; + struct v4l2_rect rect; + + if (sel->target != V4L2_SEL_TGT_CROP) + return -EINVAL; + + /* + * Clamp the boundaries of the crop rectangle to the size of the sensor + * pixel array. Align to multiples of 2 to ensure Bayer pattern isn't + * disrupted. + */ + rect.left = clamp(ALIGN(sel->r.left, 2), OV2680_NATIVE_START_LEFT, + OV2680_NATIVE_WIDTH); + rect.top = clamp(ALIGN(sel->r.top, 2), OV2680_NATIVE_START_TOP, + OV2680_NATIVE_HEIGHT); + rect.width = clamp_t(unsigned int, ALIGN(sel->r.width, 2), + OV2680_MIN_CROP_WIDTH, OV2680_NATIVE_WIDTH); + rect.height = clamp_t(unsigned int, ALIGN(sel->r.height, 2), + OV2680_MIN_CROP_HEIGHT, OV2680_NATIVE_HEIGHT); + + /* Make sure the crop rectangle isn't outside the bounds of the array */ + rect.width = min_t(unsigned int, rect.width, + OV2680_NATIVE_WIDTH - rect.left); + rect.height = min_t(unsigned int, rect.height, + OV2680_NATIVE_HEIGHT - rect.top); + + __crop = __ov2680_get_pad_crop(sensor, state, sel->pad, sel->which); + + if (rect.width != __crop->width || rect.height != __crop->height) { + /* + * Reset the output image size if the crop rectangle size has + * been modified. + */ + format = __ov2680_get_pad_format(sensor, state, sel->pad, sel->which); + format->width = rect.width; + format->height = rect.height; + } + + *__crop = rect; + sel->r = rect; + + return 0; +} + +static int ov2680_init_cfg(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state) +{ + struct v4l2_subdev_format fmt = { + .which = sd_state ? V4L2_SUBDEV_FORMAT_TRY + : V4L2_SUBDEV_FORMAT_ACTIVE, + .format = { + .width = 800, + .height = 600, + }, + }; + + sd_state->pads[0].try_crop = ov2680_default_crop; + + return ov2680_set_fmt(sd, sd_state, &fmt); +} + static int ov2680_detect(struct i2c_client *client) { struct i2c_adapter *adapter = client->adapter; @@ -405,11 +513,11 @@ static int ov2680_detect(struct i2c_client *client) static int ov2680_s_stream(struct v4l2_subdev *sd, int enable) { - struct ov2680_device *sensor = to_ov2680_sensor(sd); + struct ov2680_dev *sensor = to_ov2680_sensor(sd); struct i2c_client *client = v4l2_get_subdevdata(sd); int ret = 0; - mutex_lock(&sensor->input_lock); + mutex_lock(&sensor->lock); if (sensor->is_streaming == enable) { dev_warn(&client->dev, "stream already %s\n", enable ? "started" : "stopped"); @@ -442,14 +550,14 @@ static int ov2680_s_stream(struct v4l2_subdev *sd, int enable) v4l2_ctrl_activate(sensor->ctrls.vflip, !enable); v4l2_ctrl_activate(sensor->ctrls.hflip, !enable); - mutex_unlock(&sensor->input_lock); + mutex_unlock(&sensor->lock); return 0; error_power_down: pm_runtime_put(sensor->sd.dev); sensor->is_streaming = false; error_unlock: - mutex_unlock(&sensor->input_lock); + mutex_unlock(&sensor->lock); return ret; } @@ -550,11 +658,14 @@ static const struct v4l2_subdev_sensor_ops ov2680_sensor_ops = { }; static const struct v4l2_subdev_pad_ops ov2680_pad_ops = { + .init_cfg = ov2680_init_cfg, .enum_mbus_code = ov2680_enum_mbus_code, .enum_frame_size = ov2680_enum_frame_size, .enum_frame_interval = ov2680_enum_frame_interval, .get_fmt = ov2680_get_fmt, .set_fmt = ov2680_set_fmt, + .get_selection = ov2680_get_selection, + .set_selection = ov2680_set_selection, }; static const struct v4l2_subdev_ops ov2680_ops = { @@ -563,7 +674,7 @@ static const struct v4l2_subdev_ops ov2680_ops = { .sensor = &ov2680_sensor_ops, }; -static int ov2680_init_controls(struct ov2680_device *sensor) +static int ov2680_init_controls(struct ov2680_dev *sensor) { static const char * const test_pattern_menu[] = { "Disabled", @@ -579,7 +690,7 @@ static int ov2680_init_controls(struct ov2680_device *sensor) v4l2_ctrl_handler_init(hdl, 4); - hdl->lock = &sensor->input_lock; + hdl->lock = &sensor->lock; ctrls->hflip = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_HFLIP, 0, 1, 1, 0); ctrls->vflip = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_VFLIP, 0, 1, 1, 0); @@ -605,39 +716,46 @@ static int ov2680_init_controls(struct ov2680_device *sensor) static void ov2680_remove(struct i2c_client *client) { struct v4l2_subdev *sd = i2c_get_clientdata(client); - struct ov2680_device *sensor = to_ov2680_sensor(sd); + struct ov2680_dev *sensor = to_ov2680_sensor(sd); dev_dbg(&client->dev, "ov2680_remove...\n"); - atomisp_unregister_subdev(sd); - v4l2_device_unregister_subdev(sd); + v4l2_async_unregister_subdev(&sensor->sd); media_entity_cleanup(&sensor->sd.entity); v4l2_ctrl_handler_free(&sensor->ctrls.handler); + mutex_destroy(&sensor->lock); + fwnode_handle_put(sensor->ep_fwnode); pm_runtime_disable(&client->dev); } static int ov2680_probe(struct i2c_client *client) { struct device *dev = &client->dev; - struct ov2680_device *sensor; + struct ov2680_dev *sensor; int ret; sensor = devm_kzalloc(dev, sizeof(*sensor), GFP_KERNEL); if (!sensor) return -ENOMEM; - mutex_init(&sensor->input_lock); + mutex_init(&sensor->lock); sensor->client = client; v4l2_i2c_subdev_init(&sensor->sd, client, &ov2680_ops); - ret = v4l2_get_acpi_sensor_info(dev, NULL); - if (ret) - return ret; + /* + * Sometimes the fwnode graph is initialized by the bridge driver. + * Bridge drivers doing this may also add GPIO mappings, wait for this. + */ + sensor->ep_fwnode = fwnode_graph_get_next_endpoint(dev_fwnode(dev), NULL); + if (!sensor->ep_fwnode) + return dev_err_probe(dev, -EPROBE_DEFER, "waiting for fwnode graph endpoint\n"); sensor->powerdown = devm_gpiod_get_optional(dev, "powerdown", GPIOD_OUT_HIGH); - if (IS_ERR(sensor->powerdown)) + if (IS_ERR(sensor->powerdown)) { + fwnode_handle_put(sensor->ep_fwnode); return dev_err_probe(dev, PTR_ERR(sensor->powerdown), "getting powerdown GPIO\n"); + } pm_runtime_set_suspended(dev); pm_runtime_enable(dev); @@ -653,6 +771,7 @@ static int ov2680_probe(struct i2c_client *client) sensor->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; sensor->pad.flags = MEDIA_PAD_FL_SOURCE; sensor->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR; + sensor->sd.fwnode = sensor->ep_fwnode; ret = ov2680_init_controls(sensor); if (ret) { @@ -666,10 +785,11 @@ static int ov2680_probe(struct i2c_client *client) return ret; } + sensor->mode.crop = ov2680_default_crop; ov2680_fill_format(sensor, &sensor->mode.fmt, OV2680_NATIVE_WIDTH, OV2680_NATIVE_HEIGHT); + ov2680_calc_mode(sensor); - ret = atomisp_register_sensor_no_gmin(&sensor->sd, 1, ATOMISP_INPUT_FORMAT_RAW_10, - atomisp_bayer_order_bggr); + ret = v4l2_async_register_subdev_sensor(&sensor->sd); if (ret) { ov2680_remove(client); return ret; @@ -681,7 +801,7 @@ static int ov2680_probe(struct i2c_client *client) static int ov2680_suspend(struct device *dev) { struct v4l2_subdev *sd = dev_get_drvdata(dev); - struct ov2680_device *sensor = to_ov2680_sensor(sd); + struct ov2680_dev *sensor = to_ov2680_sensor(sd); gpiod_set_value_cansleep(sensor->powerdown, 1); return 0; @@ -690,7 +810,7 @@ static int ov2680_suspend(struct device *dev) static int ov2680_resume(struct device *dev) { struct v4l2_subdev *sd = dev_get_drvdata(dev); - struct ov2680_device *sensor = to_ov2680_sensor(sd); + struct ov2680_dev *sensor = to_ov2680_sensor(sd); /* according to DS, at least 5ms is needed after DOVDD (enabled by ACPI) */ usleep_range(5000, 6000); @@ -719,7 +839,7 @@ static struct i2c_driver ov2680_driver = { .pm = pm_sleep_ptr(&ov2680_pm_ops), .acpi_match_table = ov2680_acpi_match, }, - .probe_new = ov2680_probe, + .probe = ov2680_probe, .remove = ov2680_remove, }; module_i2c_driver(ov2680_driver); diff --git a/drivers/staging/media/atomisp/i2c/atomisp-ov2722.c b/drivers/staging/media/atomisp/i2c/atomisp-ov2722.c index 5d2e6e2e72f06d1a761edcdb421f2bf3bb532999..6a72691ed5b74dc1b4cfd2c20291bb9a28c8b137 100644 --- a/drivers/staging/media/atomisp/i2c/atomisp-ov2722.c +++ b/drivers/staging/media/atomisp/i2c/atomisp-ov2722.c @@ -1019,7 +1019,7 @@ static struct i2c_driver ov2722_driver = { .name = "ov2722", .acpi_match_table = ov2722_acpi_match, }, - .probe_new = ov2722_probe, + .probe = ov2722_probe, .remove = ov2722_remove, }; module_i2c_driver(ov2722_driver); diff --git a/drivers/staging/media/atomisp/i2c/gc0310.h b/drivers/staging/media/atomisp/i2c/gc0310.h deleted file mode 100644 index d404062895987ff327275ba4c269a972c552ffa6..0000000000000000000000000000000000000000 --- a/drivers/staging/media/atomisp/i2c/gc0310.h +++ /dev/null @@ -1,309 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Support for GalaxyCore GC0310 VGA camera sensor. - * - * Copyright (c) 2013 Intel Corporation. All Rights Reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version - * 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * - */ - -#ifndef __GC0310_H__ -#define __GC0310_H__ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../include/linux/atomisp_platform.h" - -#define GC0310_NATIVE_WIDTH 656 -#define GC0310_NATIVE_HEIGHT 496 - -#define GC0310_FPS 30 -#define GC0310_SKIP_FRAMES 3 - -#define GC0310_FOCAL_LENGTH_NUM 278 /* 2.78mm */ - -#define GC0310_ID 0xa310 - -#define GC0310_RESET_RELATED 0xFE -#define GC0310_REGISTER_PAGE_0 0x0 -#define GC0310_REGISTER_PAGE_3 0x3 - -#define GC0310_FINE_INTG_TIME_MIN 0 -#define GC0310_FINE_INTG_TIME_MAX_MARGIN 0 -#define GC0310_COARSE_INTG_TIME_MIN 1 -#define GC0310_COARSE_INTG_TIME_MAX_MARGIN 6 - -/* - * GC0310 System control registers - */ -#define GC0310_SW_STREAM 0x10 - -#define GC0310_SC_CMMN_CHIP_ID_H 0xf0 -#define GC0310_SC_CMMN_CHIP_ID_L 0xf1 - -#define GC0310_AEC_PK_EXPO_H 0x03 -#define GC0310_AEC_PK_EXPO_L 0x04 -#define GC0310_AGC_ADJ 0x48 -#define GC0310_DGC_ADJ 0x71 -#if 0 -#define GC0310_GROUP_ACCESS 0x3208 -#endif - -#define GC0310_H_CROP_START_H 0x09 -#define GC0310_H_CROP_START_L 0x0A -#define GC0310_V_CROP_START_H 0x0B -#define GC0310_V_CROP_START_L 0x0C -#define GC0310_H_OUTSIZE_H 0x0F -#define GC0310_H_OUTSIZE_L 0x10 -#define GC0310_V_OUTSIZE_H 0x0D -#define GC0310_V_OUTSIZE_L 0x0E -#define GC0310_H_BLANKING_H 0x05 -#define GC0310_H_BLANKING_L 0x06 -#define GC0310_V_BLANKING_H 0x07 -#define GC0310_V_BLANKING_L 0x08 -#define GC0310_SH_DELAY 0x11 - -#define GC0310_START_STREAMING 0x94 /* 8-bit enable */ -#define GC0310_STOP_STREAMING 0x0 /* 8-bit disable */ - -/* - * gc0310 device structure. - */ -struct gc0310_device { - struct v4l2_subdev sd; - struct media_pad pad; - struct mutex input_lock; - bool is_streaming; - - struct gpio_desc *reset; - struct gpio_desc *powerdown; - - struct gc0310_mode { - struct v4l2_mbus_framefmt fmt; - } mode; - - struct gc0310_ctrls { - struct v4l2_ctrl_handler handler; - struct v4l2_ctrl *exposure; - struct v4l2_ctrl *gain; - } ctrls; -}; - -/** - * struct gc0310_reg - MI sensor register format - * @reg: 16-bit offset to register - * @val: 8/16/32-bit register value - * - * Define a structure for sensor register initialization values - */ -struct gc0310_reg { - u8 reg; - u8 val; /* @set value for read/mod/write, @mask */ -}; - -#define to_gc0310_sensor(x) container_of(x, struct gc0310_device, sd) - -/* - * Register settings for various resolution - */ -static const struct gc0310_reg gc0310_reset_register[] = { -///////////////////////////////////////////////// -///////////////// system reg ///////////////// -///////////////////////////////////////////////// - { 0xfe, 0xf0 }, - { 0xfe, 0xf0 }, - { 0xfe, 0x00 }, - - { 0xfc, 0x0e }, /* 4e */ - { 0xfc, 0x0e }, /* 16//4e // [0]apwd [6]regf_clk_gate */ - { 0xf2, 0x80 }, /* sync output */ - { 0xf3, 0x00 }, /* 1f//01 data output */ - { 0xf7, 0x33 }, /* f9 */ - { 0xf8, 0x05 }, /* 00 */ - { 0xf9, 0x0e }, /* 0x8e //0f */ - { 0xfa, 0x11 }, - -///////////////////////////////////////////////// -/////////////////// MIPI //////////////////// -///////////////////////////////////////////////// - { 0xfe, 0x03 }, - { 0x01, 0x03 }, /* mipi 1lane */ - { 0x02, 0x22 }, /* 0x33 */ - { 0x03, 0x94 }, - { 0x04, 0x01 }, /* fifo_prog */ - { 0x05, 0x00 }, /* fifo_prog */ - { 0x06, 0x80 }, /* b0 //YUV ISP data */ - { 0x11, 0x2a }, /* 1e //LDI set YUV422 */ - { 0x12, 0x90 }, /* 00 //04 //00 //04//00 //LWC[7:0] */ - { 0x13, 0x02 }, /* 05 //05 //LWC[15:8] */ - { 0x15, 0x12 }, /* 0x10 //DPHYY_MODE read_ready */ - { 0x17, 0x01 }, - { 0x40, 0x08 }, - { 0x41, 0x00 }, - { 0x42, 0x00 }, - { 0x43, 0x00 }, - { 0x21, 0x02 }, /* 0x01 */ - { 0x22, 0x02 }, /* 0x01 */ - { 0x23, 0x01 }, /* 0x05 //Nor:0x05 DOU:0x06 */ - { 0x29, 0x00 }, - { 0x2A, 0x25 }, /* 0x05 //data zero 0x7a de */ - { 0x2B, 0x02 }, - - { 0xfe, 0x00 }, - -///////////////////////////////////////////////// -///////////////// CISCTL reg ///////////////// -///////////////////////////////////////////////// - { 0x00, 0x2f }, /* 2f//0f//02//01 */ - { 0x01, 0x0f }, /* 06 */ - { 0x02, 0x04 }, - { 0x4f, 0x00 }, /* AEC 0FF */ - { 0x03, 0x01 }, /* 0x03 //04 */ - { 0x04, 0xc0 }, /* 0xe8 //58 */ - { 0x05, 0x00 }, - { 0x06, 0xb2 }, /* 0x0a //HB */ - { 0x07, 0x00 }, - { 0x08, 0x0c }, /* 0x89 //VB */ - { 0x09, 0x00 }, /* row start */ - { 0x0a, 0x00 }, - { 0x0b, 0x00 }, /* col start */ - { 0x0c, 0x00 }, - { 0x0d, 0x01 }, /* height */ - { 0x0e, 0xf2 }, /* 0xf7 //height */ - { 0x0f, 0x02 }, /* width */ - { 0x10, 0x94 }, /* 0xa0 //height */ - { 0x17, 0x14 }, - { 0x18, 0x1a }, /* 0a//[4]double reset */ - { 0x19, 0x14 }, /* AD pipeline */ - { 0x1b, 0x48 }, - { 0x1e, 0x6b }, /* 3b//col bias */ - { 0x1f, 0x28 }, /* 20//00//08//txlow */ - { 0x20, 0x89 }, /* 88//0c//[3:2]DA15 */ - { 0x21, 0x49 }, /* 48//[3] txhigh */ - { 0x22, 0xb0 }, - { 0x23, 0x04 }, /* [1:0]vcm_r */ - { 0x24, 0x16 }, /* 15 */ - { 0x34, 0x20 }, /* [6:4] rsg high//range */ - -///////////////////////////////////////////////// -//////////////////// BLK //////////////////// -///////////////////////////////////////////////// - { 0x26, 0x23 }, /* [1]dark_current_en [0]offset_en */ - { 0x28, 0xff }, /* BLK_limie_value */ - { 0x29, 0x00 }, /* global offset */ - { 0x33, 0x18 }, /* offset_ratio */ - { 0x37, 0x20 }, /* dark_current_ratio */ - { 0x2a, 0x00 }, - { 0x2b, 0x00 }, - { 0x2c, 0x00 }, - { 0x2d, 0x00 }, - { 0x2e, 0x00 }, - { 0x2f, 0x00 }, - { 0x30, 0x00 }, - { 0x31, 0x00 }, - { 0x47, 0x80 }, /* a7 */ - { 0x4e, 0x66 }, /* select_row */ - { 0xa8, 0x02 }, /* win_width_dark, same with crop_win_width */ - { 0xa9, 0x80 }, - -///////////////////////////////////////////////// -////////////////// ISP reg /////////////////// -///////////////////////////////////////////////// - { 0x40, 0x06 }, /* 0xff //ff //48 */ - { 0x41, 0x00 }, /* 0x21 //00//[0]curve_en */ - { 0x42, 0x04 }, /* 0xcf //0a//[1]awn_en */ - { 0x44, 0x18 }, /* 0x18 //02 */ - { 0x46, 0x02 }, /* 0x03 //sync */ - { 0x49, 0x03 }, - { 0x4c, 0x20 }, /* 00[5]pretect exp */ - { 0x50, 0x01 }, /* crop enable */ - { 0x51, 0x00 }, - { 0x52, 0x00 }, - { 0x53, 0x00 }, - { 0x54, 0x01 }, - { 0x55, 0x01 }, /* crop window height */ - { 0x56, 0xf0 }, - { 0x57, 0x02 }, /* crop window width */ - { 0x58, 0x90 }, - -///////////////////////////////////////////////// -/////////////////// GAIN //////////////////// -///////////////////////////////////////////////// - { 0x70, 0x70 }, /* 70 //80//global gain */ - { 0x71, 0x20 }, /* pregain gain */ - { 0x72, 0x40 }, /* post gain */ - { 0x5a, 0x84 }, /* 84//analog gain 0 */ - { 0x5b, 0xc9 }, /* c9 */ - { 0x5c, 0xed }, /* ed//not use pga gain highest level */ - { 0x77, 0x40 }, /* R gain 0x74 //awb gain */ - { 0x78, 0x40 }, /* G gain */ - { 0x79, 0x40 }, /* B gain 0x5f */ - - { 0x48, 0x00 }, - { 0xfe, 0x01 }, - { 0x0a, 0x45 }, /* [7]col gain mode */ - - { 0x3e, 0x40 }, - { 0x3f, 0x5c }, - { 0x40, 0x7b }, - { 0x41, 0xbd }, - { 0x42, 0xf6 }, - { 0x43, 0x63 }, - { 0x03, 0x60 }, - { 0x44, 0x03 }, - -///////////////////////////////////////////////// -///////////////// dark sun ////////////////// -///////////////////////////////////////////////// - { 0xfe, 0x01 }, - { 0x45, 0xa4 }, /* 0xf7 */ - { 0x46, 0xf0 }, /* 0xff //f0//sun value th */ - { 0x48, 0x03 }, /* sun mode */ - { 0x4f, 0x60 }, /* sun_clamp */ - { 0xfe, 0x00 }, -}; - -static struct gc0310_reg const gc0310_VGA_30fps[] = { - { 0xfe, 0x00 }, - { 0x0d, 0x01 }, /* height */ - { 0x0e, 0xf2 }, /* 0xf7 //height */ - { 0x0f, 0x02 }, /* width */ - { 0x10, 0x94 }, /* 0xa0 //height */ - - { 0x50, 0x01 }, /* crop enable */ - { 0x51, 0x00 }, - { 0x52, 0x00 }, - { 0x53, 0x00 }, - { 0x54, 0x01 }, - { 0x55, 0x01 }, /* crop window height */ - { 0x56, 0xf0 }, - { 0x57, 0x02 }, /* crop window width */ - { 0x58, 0x90 }, - - { 0xfe, 0x03 }, - { 0x12, 0x90 }, /* 00 //04 //00 //04//00 //LWC[7:0] */ - { 0x13, 0x02 }, /* 05 //05 //LWC[15:8] */ - - { 0xfe, 0x00 }, -}; - -#endif diff --git a/drivers/staging/media/atomisp/i2c/ov2680.h b/drivers/staging/media/atomisp/i2c/ov2680.h index baf49eb0659e31ee749c22acad088a3396c0406a..d032af245674694cb13501e674df9b7c84eafbc9 100644 --- a/drivers/staging/media/atomisp/i2c/ov2680.h +++ b/drivers/staging/media/atomisp/i2c/ov2680.h @@ -30,10 +30,16 @@ #include #include -#include "../include/linux/atomisp_platform.h" - #define OV2680_NATIVE_WIDTH 1616 #define OV2680_NATIVE_HEIGHT 1216 +#define OV2680_NATIVE_START_LEFT 0 +#define OV2680_NATIVE_START_TOP 0 +#define OV2680_ACTIVE_WIDTH 1600 +#define OV2680_ACTIVE_HEIGHT 1200 +#define OV2680_ACTIVE_START_LEFT 8 +#define OV2680_ACTIVE_START_TOP 8 +#define OV2680_MIN_CROP_WIDTH 2 +#define OV2680_MIN_CROP_HEIGHT 2 /* 1704 * 1294 * 30fps = 66MHz pixel clock */ #define OV2680_PIXELS_PER_LINE 1704 @@ -66,6 +72,8 @@ #define OV2680_REG_EXPOSURE_PK_HIGH 0x3500 #define OV2680_REG_GAIN_PK 0x350a +#define OV2680_REG_SENSOR_CTRL_0A 0x370a + #define OV2680_HORIZONTAL_START_H 0x3800 /* Bit[11:8] */ #define OV2680_HORIZONTAL_START_L 0x3801 /* Bit[7:0] */ #define OV2680_VERTICAL_START_H 0x3802 /* Bit[11:8] */ @@ -108,15 +116,18 @@ /* * ov2680 device structure. */ -struct ov2680_device { +struct ov2680_dev { struct v4l2_subdev sd; struct media_pad pad; - struct mutex input_lock; + /* Protect against concurrent changes to controls */ + struct mutex lock; struct i2c_client *client; struct gpio_desc *powerdown; + struct fwnode_handle *ep_fwnode; bool is_streaming; struct ov2680_mode { + struct v4l2_rect crop; struct v4l2_mbus_framefmt fmt; bool binning; u16 h_start; @@ -152,92 +163,86 @@ struct ov2680_reg { u32 val; /* @set value for read/mod/write, @mask */ }; -#define to_ov2680_sensor(x) container_of(x, struct ov2680_device, sd) +#define to_ov2680_sensor(x) container_of(x, struct ov2680_dev, sd) static inline struct v4l2_subdev *ctrl_to_sd(struct v4l2_ctrl *ctrl) { - struct ov2680_device *sensor = - container_of(ctrl->handler, struct ov2680_device, ctrls.handler); + struct ov2680_dev *sensor = + container_of(ctrl->handler, struct ov2680_dev, ctrls.handler); return &sensor->sd; } static struct ov2680_reg const ov2680_global_setting[] = { - {0x0103, 0x01}, - {0x3002, 0x00}, + /* MIPI PHY, 0x10 -> 0x1c enable bp_c_hs_en_lat and bp_d_hs_en_lat */ {0x3016, 0x1c}, - {0x3018, 0x44}, - {0x3020, 0x00}, - {0x3080, 0x02}, + + /* PLL MULT bits 0-7, datasheet default 0x37 for 24MHz extclk, use 0x45 for 19.2 Mhz extclk */ {0x3082, 0x45}, - {0x3084, 0x09}, - {0x3085, 0x04}, + + /* R MANUAL set exposure (0x01) and gain (0x02) to manual (hw does not do auto) */ {0x3503, 0x03}, - {0x350b, 0x36}, - {0x3600, 0xb4}, - {0x3603, 0x39}, - {0x3604, 0x24}, - {0x3605, 0x00}, - {0x3620, 0x26}, - {0x3621, 0x37}, - {0x3622, 0x04}, - {0x3628, 0x00}, - {0x3705, 0x3c}, - {0x370c, 0x50}, - {0x370d, 0xc0}, - {0x3718, 0x88}, - {0x3720, 0x00}, - {0x3721, 0x00}, - {0x3722, 0x00}, - {0x3723, 0x00}, - {0x3738, 0x00}, - {0x3717, 0x58}, - {0x3781, 0x80}, - {0x3789, 0x60}, - {0x3800, 0x00}, - {0x3819, 0x04}, + + /* Analog control register tweaks */ + {0x3603, 0x39}, /* Reset value 0x99 */ + {0x3604, 0x24}, /* Reset value 0x74 */ + {0x3621, 0x37}, /* Reset value 0x44 */ + + /* Sensor control register tweaks */ + {0x3701, 0x64}, /* Reset value 0x61 */ + {0x3705, 0x3c}, /* Reset value 0x21 */ + {0x370c, 0x50}, /* Reset value 0x10 */ + {0x370d, 0xc0}, /* Reset value 0x00 */ + {0x3718, 0x88}, /* Reset value 0x80 */ + + /* PSRAM tweaks */ + {0x3781, 0x80}, /* Reset value 0x00 */ + {0x3784, 0x0c}, /* Reset value 0x00, based on OV2680_R1A_AM10.ovt */ + {0x3789, 0x60}, /* Reset value 0x50 */ + + /* BLC CTRL00 0x01 -> 0x81 set avg_weight to 8 */ {0x4000, 0x81}, - {0x4001, 0x40}, + + /* Set black level compensation range to 0 - 3 (default 0 - 11) */ {0x4008, 0x00}, {0x4009, 0x03}, + + /* VFIFO R2 0x00 -> 0x02 set Frame reset enable */ {0x4602, 0x02}, + + /* MIPI ctrl CLK PREPARE MIN change from 0x26 (38) -> 0x36 (54) */ {0x481f, 0x36}, + + /* MIPI ctrl CLK LPX P MIN change from 0x32 (50) -> 0x36 (54) */ {0x4825, 0x36}, - {0x4837, 0x18}, + + /* R ISP CTRL2 0x20 -> 0x30, set sof_sel bit */ {0x5002, 0x30}, - {0x5004, 0x04},//manual awb 1x - {0x5005, 0x00}, - {0x5006, 0x04}, - {0x5007, 0x00}, - {0x5008, 0x04}, - {0x5009, 0x00}, - {0x5080, 0x00}, - {0x5081, 0x41}, - {0x5708, 0x01}, /* add for full size flip off and mirror off 2014/09/11 */ - {0x3701, 0x64}, //add on 14/05/13 - {0x3784, 0x0c}, //based OV2680_R1A_AM10.ovt add on 14/06/13 - {0x5780, 0x3e}, //based OV2680_R1A_AM10.ovt,Adjust DPC setting (57xx) on 14/06/13 - {0x5781, 0x0f}, - {0x5782, 0x04}, - {0x5783, 0x02}, - {0x5784, 0x01}, - {0x5785, 0x01}, - {0x5786, 0x00}, - {0x5787, 0x04}, + + /* + * Window CONTROL 0x00 -> 0x01, enable manual window control, + * this is necessary for full size flip and mirror support. + */ + {0x5708, 0x01}, + + /* + * DPC CTRL0 0x14 -> 0x3e, set enable_tail, enable_3x3_cluster + * and enable_general_tail bits based OV2680_R1A_AM10.ovt. + */ + {0x5780, 0x3e}, + + /* DPC MORE CONNECTION CASE THRE 0x0c (12) -> 0x02 (2) */ {0x5788, 0x02}, - {0x5789, 0x00}, - {0x578a, 0x01}, - {0x578b, 0x02}, - {0x578c, 0x03}, - {0x578d, 0x03}, + + /* DPC GAIN LIST1 0x0f (15) -> 0x08 (8) */ {0x578e, 0x08}, + + /* DPC GAIN LIST2 0x3f (63) -> 0x0c (12) */ {0x578f, 0x0c}, - {0x5790, 0x08}, - {0x5791, 0x04}, + + /* DPC THRE RATIO 0x04 (4) -> 0x00 (0) */ {0x5792, 0x00}, - {0x5793, 0x00}, - {0x5794, 0x03}, //based OV2680_R1A_AM10.ovt,Adjust DPC setting (57xx) on 14/06/13 - {0x0100, 0x00}, //stream off + {} }; diff --git a/drivers/staging/media/atomisp/i2c/ov5693/atomisp-ov5693.c b/drivers/staging/media/atomisp/i2c/ov5693/atomisp-ov5693.c index da8c3b1d3bcd8a0bdfc88b8ea17ab0f115fe98ca..460a4e34c55bdec852706c2acc4d258598f5ce46 100644 --- a/drivers/staging/media/atomisp/i2c/ov5693/atomisp-ov5693.c +++ b/drivers/staging/media/atomisp/i2c/ov5693/atomisp-ov5693.c @@ -726,51 +726,11 @@ static void *ov5693_otp_read(struct v4l2_subdev *sd) return buf; } -static int ov5693_g_priv_int_data(struct v4l2_subdev *sd, - struct v4l2_private_int_data *priv) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - struct ov5693_device *dev = to_ov5693_sensor(sd); - u8 __user *to = priv->data; - u32 read_size = priv->size; - int ret; - - /* No need to copy data if size is 0 */ - if (!read_size) - goto out; - - if (IS_ERR(dev->otp_data)) { - dev_err(&client->dev, "OTP data not available"); - return PTR_ERR(dev->otp_data); - } - - /* Correct read_size value only if bigger than maximum */ - if (read_size > OV5693_OTP_DATA_SIZE) - read_size = OV5693_OTP_DATA_SIZE; - - ret = copy_to_user(to, dev->otp_data, read_size); - if (ret) { - dev_err(&client->dev, "%s: failed to copy OTP data to user\n", - __func__); - return -EFAULT; - } - - pr_debug("%s read_size:%d\n", __func__, read_size); - -out: - /* Return correct size */ - priv->size = dev->otp_size; - - return 0; -} - static long ov5693_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) { switch (cmd) { case ATOMISP_IOC_S_EXPOSURE: return ov5693_s_exposure(sd, arg); - case ATOMISP_IOC_G_SENSOR_PRIV_INT_DATA: - return ov5693_g_priv_int_data(sd, arg); default: return -EINVAL; } @@ -1794,7 +1754,7 @@ static struct i2c_driver ov5693_driver = { .name = "ov5693", .acpi_match_table = ov5693_acpi_match, }, - .probe_new = ov5693_probe, + .probe = ov5693_probe, .remove = ov5693_remove, }; module_i2c_driver(ov5693_driver); diff --git a/drivers/staging/media/atomisp/include/linux/atomisp.h b/drivers/staging/media/atomisp/include/linux/atomisp.h index c7ec56a1c06404a0981c9f56f0cede08c7797fea..14b1757e667464945130a57458483196ef2fec5e 100644 --- a/drivers/staging/media/atomisp/include/linux/atomisp.h +++ b/drivers/staging/media/atomisp/include/linux/atomisp.h @@ -38,7 +38,6 @@ #define CI_MODE_PREVIEW 0x8000 #define CI_MODE_VIDEO 0x4000 #define CI_MODE_STILL_CAPTURE 0x2000 -#define CI_MODE_CONTINUOUS 0x1000 #define CI_MODE_NONE 0x0000 #define OUTPUT_MODE_FILE 0x0100 @@ -150,12 +149,6 @@ enum atomisp_calibration_type { calibration_type3 }; -struct atomisp_calibration_group { - unsigned int size; - unsigned int type; - unsigned short *calb_grp_values; -}; - struct atomisp_gc_config { __u16 gain_k1; __u16 gain_k2; @@ -266,26 +259,6 @@ enum atomisp_metadata_type { ATOMISP_METADATA_TYPE_NUM, }; -struct atomisp_metadata_with_type { - /* to specify which type of metadata to get */ - enum atomisp_metadata_type type; - void __user *data; - u32 width; - u32 height; - u32 stride; /* in bytes */ - u32 exp_id; /* exposure ID */ - u32 *effective_width; /* mipi packets valid data size */ -}; - -struct atomisp_metadata { - void __user *data; - u32 width; - u32 height; - u32 stride; /* in bytes */ - u32 exp_id; /* exposure ID */ - u32 *effective_width; /* mipi packets valid data size */ -}; - struct atomisp_ext_isp_ctrl { u32 id; u32 data; @@ -299,14 +272,6 @@ struct atomisp_3a_statistics { u32 isp_config_id; /* isp config ID */ }; -struct atomisp_ae_window { - int x_left; - int x_right; - int y_top; - int y_bottom; - int weight; -}; - /* White Balance (Gain Adjust) */ struct atomisp_wb_config { unsigned int integer_bits; @@ -755,53 +720,6 @@ struct atomisp_s_runmode { __u32 mode; }; -struct atomisp_update_exposure { - unsigned int gain; - unsigned int digi_gain; - unsigned int update_gain; - unsigned int update_digi_gain; -}; - -/* - * V4L2 private internal data interface. - * ----------------------------------------------------------------------------- - * struct v4l2_private_int_data - request private data stored in video device - * internal memory. - * @size: sanity check to ensure userspace's buffer fits whole private data. - * If not, kernel will make partial copy (or nothing if @size == 0). - * @size is always corrected for the minimum necessary if IOCTL returns - * no error. - * @data: pointer to userspace buffer. - */ -struct v4l2_private_int_data { - __u32 size; - void __user *data; - __u32 reserved[2]; -}; - -enum atomisp_sensor_ae_bracketing_mode { - SENSOR_AE_BRACKETING_MODE_OFF = 0, - SENSOR_AE_BRACKETING_MODE_SINGLE, /* back to SW standby after bracketing */ - SENSOR_AE_BRACKETING_MODE_SINGLE_TO_STREAMING, /* back to normal streaming after bracketing */ - SENSOR_AE_BRACKETING_MODE_LOOP, /* continue AE bracketing in loop mode */ -}; - -struct atomisp_sensor_ae_bracketing_info { - unsigned int modes; /* bit mask to indicate supported modes */ - unsigned int lut_depth; -}; - -struct atomisp_sensor_ae_bracketing_lut_entry { - __u16 coarse_integration_time; - __u16 analog_gain; - __u16 digital_gain; -}; - -struct atomisp_sensor_ae_bracketing_lut { - struct atomisp_sensor_ae_bracketing_lut_entry *lut; - unsigned int lut_size; -}; - /*Private IOCTLs for ISP */ #define ATOMISP_IOC_G_XNR \ _IOR('v', BASE_VIDIOC_PRIVATE + 0, int) @@ -906,20 +824,12 @@ struct atomisp_sensor_ae_bracketing_lut { #define ATOMISP_IOC_S_EXPOSURE \ _IOW('v', BASE_VIDIOC_PRIVATE + 21, struct atomisp_exposure) -/* sensor calibration registers group */ -#define ATOMISP_IOC_G_SENSOR_CALIBRATION_GROUP \ - _IOWR('v', BASE_VIDIOC_PRIVATE + 22, struct atomisp_calibration_group) - /* white balance Correction */ #define ATOMISP_IOC_G_3A_CONFIG \ _IOR('v', BASE_VIDIOC_PRIVATE + 23, struct atomisp_3a_config) #define ATOMISP_IOC_S_3A_CONFIG \ _IOW('v', BASE_VIDIOC_PRIVATE + 23, struct atomisp_3a_config) -/* sensor OTP memory read */ -#define ATOMISP_IOC_G_SENSOR_PRIV_INT_DATA \ - _IOWR('v', BASE_VIDIOC_PRIVATE + 26, struct v4l2_private_int_data) - /* LCS (shading) table write */ #define ATOMISP_IOC_S_ISP_SHD_TAB \ _IOWR('v', BASE_VIDIOC_PRIVATE + 27, struct atomisp_shading_table) @@ -931,19 +841,9 @@ struct atomisp_sensor_ae_bracketing_lut { #define ATOMISP_IOC_S_ISP_GAMMA_CORRECTION \ _IOW('v', BASE_VIDIOC_PRIVATE + 28, struct atomisp_gc_config) -/* motor internal memory read */ -#define ATOMISP_IOC_G_MOTOR_PRIV_INT_DATA \ - _IOWR('v', BASE_VIDIOC_PRIVATE + 29, struct v4l2_private_int_data) - #define ATOMISP_IOC_S_PARAMETERS \ _IOW('v', BASE_VIDIOC_PRIVATE + 32, struct atomisp_parameters) -#define ATOMISP_IOC_G_METADATA \ - _IOWR('v', BASE_VIDIOC_PRIVATE + 34, struct atomisp_metadata) - -#define ATOMISP_IOC_G_METADATA_BY_TYPE \ - _IOWR('v', BASE_VIDIOC_PRIVATE + 34, struct atomisp_metadata_with_type) - #define ATOMISP_IOC_EXT_ISP_CTRL \ _IOWR('v', BASE_VIDIOC_PRIVATE + 35, struct atomisp_ext_isp_ctrl) @@ -962,27 +862,9 @@ struct atomisp_sensor_ae_bracketing_lut { #define ATOMISP_IOC_S_FORMATS_CONFIG \ _IOW('v', BASE_VIDIOC_PRIVATE + 39, struct atomisp_formats_config) -#define ATOMISP_IOC_S_EXPOSURE_WINDOW \ - _IOW('v', BASE_VIDIOC_PRIVATE + 40, struct atomisp_ae_window) - #define ATOMISP_IOC_INJECT_A_FAKE_EVENT \ _IOW('v', BASE_VIDIOC_PRIVATE + 42, int) -#define ATOMISP_IOC_G_SENSOR_AE_BRACKETING_INFO \ - _IOR('v', BASE_VIDIOC_PRIVATE + 43, struct atomisp_sensor_ae_bracketing_info) - -#define ATOMISP_IOC_S_SENSOR_AE_BRACKETING_MODE \ - _IOW('v', BASE_VIDIOC_PRIVATE + 43, unsigned int) - -#define ATOMISP_IOC_G_SENSOR_AE_BRACKETING_MODE \ - _IOR('v', BASE_VIDIOC_PRIVATE + 43, unsigned int) - -#define ATOMISP_IOC_S_SENSOR_AE_BRACKETING_LUT \ - _IOW('v', BASE_VIDIOC_PRIVATE + 43, struct atomisp_sensor_ae_bracketing_lut) - -#define ATOMISP_IOC_G_INVALID_FRAME_NUM \ - _IOR('v', BASE_VIDIOC_PRIVATE + 44, unsigned int) - #define ATOMISP_IOC_S_ARRAY_RESOLUTION \ _IOW('v', BASE_VIDIOC_PRIVATE + 45, struct atomisp_resolution) @@ -996,9 +878,6 @@ struct atomisp_sensor_ae_bracketing_lut { #define ATOMISP_IOC_S_SENSOR_RUNMODE \ _IOW('v', BASE_VIDIOC_PRIVATE + 48, struct atomisp_s_runmode) -#define ATOMISP_IOC_G_UPDATE_EXPOSURE \ - _IOWR('v', BASE_VIDIOC_PRIVATE + 49, struct atomisp_update_exposure) - /* * Reserved ioctls. We have customer implementing it internally. * We can't use both numbers to not cause ABI conflict. @@ -1059,9 +938,9 @@ struct atomisp_sensor_ae_bracketing_lut { #define V4L2_CID_RUN_MODE (V4L2_CID_CAMERA_LASTP1 + 20) #define ATOMISP_RUN_MODE_VIDEO 1 #define ATOMISP_RUN_MODE_STILL_CAPTURE 2 -#define ATOMISP_RUN_MODE_CONTINUOUS_CAPTURE 3 -#define ATOMISP_RUN_MODE_PREVIEW 4 -#define ATOMISP_RUN_MODE_SDV 5 +#define ATOMISP_RUN_MODE_PREVIEW 3 +#define ATOMISP_RUN_MODE_MIN 1 +#define ATOMISP_RUN_MODE_MAX 3 #define V4L2_CID_ENABLE_VFPP (V4L2_CID_CAMERA_LASTP1 + 21) #define V4L2_CID_ATOMISP_CONTINUOUS_MODE (V4L2_CID_CAMERA_LASTP1 + 22) diff --git a/drivers/staging/media/atomisp/include/linux/atomisp_platform.h b/drivers/staging/media/atomisp/include/linux/atomisp_platform.h index e8e965f73fc8f97e50be3258e89d625802802b64..487ef5846c248fd6882b64dbec53e02fec01e425 100644 --- a/drivers/staging/media/atomisp/include/linux/atomisp_platform.h +++ b/drivers/staging/media/atomisp/include/linux/atomisp_platform.h @@ -125,6 +125,7 @@ struct intel_v4l2_subdev_id { struct intel_v4l2_subdev_table { enum intel_v4l2_subdev_type type; enum atomisp_camera_port port; + unsigned int lanes; struct v4l2_subdev *subdev; }; diff --git a/drivers/staging/media/atomisp/pci/atomisp-regs.h b/drivers/staging/media/atomisp/pci/atomisp-regs.h index 022997f47121b4d24e5c93899a2a505106d7c8d1..a7b0196686beee06788c7ec6bad87f4ef5091731 100644 --- a/drivers/staging/media/atomisp/pci/atomisp-regs.h +++ b/drivers/staging/media/atomisp/pci/atomisp-regs.h @@ -112,7 +112,6 @@ /* MRFLD CSI lane configuration related */ #define MRFLD_PORT_CONFIG_NUM 8 -#define MRFLD_PORT_NUM 3 #define MRFLD_PORT1_ENABLE_SHIFT 0 #define MRFLD_PORT2_ENABLE_SHIFT 1 #define MRFLD_PORT3_ENABLE_SHIFT 2 diff --git a/drivers/staging/media/atomisp/pci/atomisp_cmd.c b/drivers/staging/media/atomisp/pci/atomisp_cmd.c index aa790ae746f3742dcaad0627bbce5e772db6c0f8..e27f9dc8e7aaebb8c57e0f87d7a0629f06a31678 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_cmd.c +++ b/drivers/staging/media/atomisp/pci/atomisp_cmd.c @@ -229,8 +229,8 @@ int atomisp_freq_scaling(struct atomisp_device *isp, goto done; } - curr_rules.width = isp->asd.fmt[isp->asd.capture_pad].fmt.width; - curr_rules.height = isp->asd.fmt[isp->asd.capture_pad].fmt.height; + curr_rules.width = isp->asd.fmt[ATOMISP_SUBDEV_PAD_SOURCE].fmt.width; + curr_rules.height = isp->asd.fmt[ATOMISP_SUBDEV_PAD_SOURCE].fmt.height; curr_rules.fps = fps; curr_rules.run_mode = isp->asd.run_mode->val; @@ -472,39 +472,31 @@ irqreturn_t atomisp_isr(int irq, void *dev) clear_irq_reg(isp); - if (!atomisp_streaming_count(isp)) + if (!isp->asd.streaming) goto out_nowake; - if (isp->asd.streaming == ATOMISP_DEVICE_STREAMING_ENABLED) { - if (irq_infos & IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF) { - atomic_inc(&isp->asd.sof_count); - atomisp_sof_event(&isp->asd); - - /* If sequence_temp and sequence are the same - * there where no frames lost so we can increase - * sequence_temp. - * If not then processing of frame is still in progress - * and driver needs to keep old sequence_temp value. - * NOTE: There is assumption here that ISP will not - * start processing next frame from sensor before old - * one is completely done. */ - if (atomic_read(&isp->asd.sequence) == - atomic_read(&isp->asd.sequence_temp)) - atomic_set(&isp->asd.sequence_temp, - atomic_read(&isp->asd.sof_count)); - } - if (irq_infos & IA_CSS_IRQ_INFO_EVENTS_READY) - atomic_set(&isp->asd.sequence, - atomic_read(&isp->asd.sequence_temp)); - } - if (irq_infos & IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF) { - dev_dbg_ratelimited(isp->dev, - "irq:0x%x (SOF)\n", - irq_infos); + atomic_inc(&isp->asd.sof_count); + atomisp_sof_event(&isp->asd); + + /* + * If sequence_temp and sequence are the same there where no frames + * lost so we can increase sequence_temp. + * If not then processing of frame is still in progress and driver + * needs to keep old sequence_temp value. + * NOTE: There is assumption here that ISP will not start processing + * next frame from sensor before old one is completely done. + */ + if (atomic_read(&isp->asd.sequence) == atomic_read(&isp->asd.sequence_temp)) + atomic_set(&isp->asd.sequence_temp, atomic_read(&isp->asd.sof_count)); + + dev_dbg_ratelimited(isp->dev, "irq:0x%x (SOF)\n", irq_infos); irq_infos &= ~IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF; } + if (irq_infos & IA_CSS_IRQ_INFO_EVENTS_READY) + atomic_set(&isp->asd.sequence, atomic_read(&isp->asd.sequence_temp)); + if ((irq_infos & IA_CSS_IRQ_INFO_INPUT_SYSTEM_ERROR) || (irq_infos & IA_CSS_IRQ_INFO_IF_ERROR)) { /* handle mipi receiver error */ @@ -640,15 +632,6 @@ void atomisp_flush_video_pipe(struct atomisp_video_pipe *pipe, enum vb2_buffer_s spin_unlock_irqrestore(&pipe->irq_lock, irqflags); } -/* Returns queued buffers back to video-core */ -void atomisp_flush_bufs_and_wakeup(struct atomisp_sub_device *asd) -{ - atomisp_flush_video_pipe(&asd->video_out_capture, VB2_BUF_STATE_ERROR, false); - atomisp_flush_video_pipe(&asd->video_out_vf, VB2_BUF_STATE_ERROR, false); - atomisp_flush_video_pipe(&asd->video_out_preview, VB2_BUF_STATE_ERROR, false); - atomisp_flush_video_pipe(&asd->video_out_video_capture, VB2_BUF_STATE_ERROR, false); -} - /* clean out the parameters that did not apply */ void atomisp_flush_params_queue(struct atomisp_video_pipe *pipe) { @@ -944,53 +927,39 @@ void atomisp_buf_done(struct atomisp_sub_device *asd, int error, atomisp_qbuffers_to_css(asd); } -static void __atomisp_css_recover(struct atomisp_device *isp, bool isp_timeout) +void atomisp_assert_recovery_work(struct work_struct *work) { + struct atomisp_device *isp = container_of(work, struct atomisp_device, + assert_recovery_work); struct pci_dev *pdev = to_pci_dev(isp->dev); - enum ia_css_pipe_id css_pipe_id; - bool stream_restart = false; unsigned long flags; int ret; - lockdep_assert_held(&isp->mutex); + mutex_lock(&isp->mutex); - if (!atomisp_streaming_count(isp)) - return; + if (!isp->asd.streaming) + goto out_unlock; atomisp_css_irq_enable(isp, IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF, false); - if (isp->asd.streaming == ATOMISP_DEVICE_STREAMING_ENABLED || - isp->asd.stream_prepared) { - stream_restart = true; - - spin_lock_irqsave(&isp->lock, flags); - isp->asd.streaming = ATOMISP_DEVICE_STREAMING_STOPPING; - spin_unlock_irqrestore(&isp->lock, flags); - - /* stream off sensor */ - ret = v4l2_subdev_call( - isp->inputs[isp->asd.input_curr]. - camera, video, s_stream, 0); - if (ret) - dev_warn(isp->dev, - "can't stop streaming on sensor!\n"); + spin_lock_irqsave(&isp->lock, flags); + isp->asd.streaming = false; + spin_unlock_irqrestore(&isp->lock, flags); - atomisp_clear_css_buffer_counters(&isp->asd); + /* stream off sensor */ + ret = v4l2_subdev_call(isp->inputs[isp->asd.input_curr].camera, video, s_stream, 0); + if (ret) + dev_warn(isp->dev, "Stopping sensor stream failed: %d\n", ret); - css_pipe_id = atomisp_get_css_pipe_id(&isp->asd); - atomisp_css_stop(&isp->asd, css_pipe_id, true); + atomisp_clear_css_buffer_counters(&isp->asd); - spin_lock_irqsave(&isp->lock, flags); - isp->asd.streaming = ATOMISP_DEVICE_STREAMING_DISABLED; - spin_unlock_irqrestore(&isp->lock, flags); + atomisp_css_stop(&isp->asd, true); - isp->asd.preview_exp_id = 1; - isp->asd.postview_exp_id = 1; - /* notify HAL the CSS reset */ - dev_dbg(isp->dev, - "send reset event to %s\n", isp->asd.subdev.devnode->name); - atomisp_reset_event(&isp->asd); - } + isp->asd.preview_exp_id = 1; + isp->asd.postview_exp_id = 1; + /* notify HAL the CSS reset */ + dev_dbg(isp->dev, "send reset event to %s\n", isp->asd.subdev.devnode->name); + atomisp_reset_event(&isp->asd); /* clear irq */ disable_isp_irq(hrt_isp_css_irq_sp); @@ -1001,71 +970,46 @@ static void __atomisp_css_recover(struct atomisp_device *isp, bool isp_timeout) isp->saved_regs.i_control | MRFLD_PCI_I_CONTROL_SRSE_RESET_MASK); /* reset ISP and restore its state */ - isp->isp_timeout = true; atomisp_reset(isp); - isp->isp_timeout = false; - if (stream_restart) { - atomisp_css_input_set_mode(&isp->asd, IA_CSS_INPUT_MODE_BUFFERED_SENSOR); + atomisp_css_input_set_mode(&isp->asd, IA_CSS_INPUT_MODE_BUFFERED_SENSOR); - css_pipe_id = atomisp_get_css_pipe_id(&isp->asd); - if (atomisp_css_start(&isp->asd, css_pipe_id, true)) { - dev_warn(isp->dev, - "start SP failed, so do not set streaming to be enable!\n"); - } else { - spin_lock_irqsave(&isp->lock, flags); - isp->asd.streaming = ATOMISP_DEVICE_STREAMING_ENABLED; - spin_unlock_irqrestore(&isp->lock, flags); - } + /* Recreate streams destroyed by atomisp_css_stop() */ + atomisp_create_pipes_stream(&isp->asd); + + /* Invalidate caches. FIXME: should flush only necessary buffers */ + wbinvd(); - atomisp_csi2_configure(&isp->asd); + if (atomisp_css_start(&isp->asd)) { + dev_warn(isp->dev, "start SP failed, so do not set streaming to be enable!\n"); + } else { + spin_lock_irqsave(&isp->lock, flags); + isp->asd.streaming = true; + spin_unlock_irqrestore(&isp->lock, flags); } + atomisp_csi2_configure(&isp->asd); + atomisp_css_irq_enable(isp, IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF, atomisp_css_valid_sof(isp)); if (atomisp_freq_scaling(isp, ATOMISP_DFS_MODE_AUTO, true) < 0) dev_dbg(isp->dev, "DFS auto failed while recovering!\n"); - if (stream_restart) { - /* - * dequeueing buffers is not needed. CSS will recycle - * buffers that it has. - */ - atomisp_flush_bufs_and_wakeup(&isp->asd); + /* Dequeueing buffers is not needed, CSS will recycle buffers that it has */ + atomisp_flush_video_pipe(&isp->asd.video_out, VB2_BUF_STATE_ERROR, false); - /* Requeue unprocessed per-frame parameters. */ - atomisp_recover_params_queue(&isp->asd.video_out_capture); - atomisp_recover_params_queue(&isp->asd.video_out_preview); - atomisp_recover_params_queue(&isp->asd.video_out_video_capture); - - ret = v4l2_subdev_call( - isp->inputs[isp->asd.input_curr].camera, video, - s_stream, 1); - if (ret) - dev_warn(isp->dev, - "can't start streaming on sensor!\n"); - } -} + /* Requeue unprocessed per-frame parameters. */ + atomisp_recover_params_queue(&isp->asd.video_out); -void atomisp_assert_recovery_work(struct work_struct *work) -{ - struct atomisp_device *isp = container_of(work, struct atomisp_device, - assert_recovery_work); + ret = v4l2_subdev_call(isp->inputs[isp->asd.input_curr].camera, video, s_stream, 1); + if (ret) + dev_err(isp->dev, "Starting sensor stream failed: %d\n", ret); - mutex_lock(&isp->mutex); - __atomisp_css_recover(isp, true); +out_unlock: mutex_unlock(&isp->mutex); } -void atomisp_css_flush(struct atomisp_device *isp) -{ - /* Start recover */ - __atomisp_css_recover(isp, false); - - dev_dbg(isp->dev, "atomisp css flush done\n"); -} - void atomisp_setup_flash(struct atomisp_sub_device *asd) { struct atomisp_device *isp = asd->isp; @@ -1105,7 +1049,7 @@ irqreturn_t atomisp_isr_thread(int irq, void *isp_ptr) spin_lock_irqsave(&isp->lock, flags); - if (!atomisp_streaming_count(isp)) { + if (!isp->asd.streaming) { spin_unlock_irqrestore(&isp->lock, flags); return IRQ_HANDLED; } @@ -1141,7 +1085,7 @@ irqreturn_t atomisp_isr_thread(int irq, void *isp_ptr) if (atomisp_css_isr_thread(isp)) goto out; - if (isp->asd.streaming == ATOMISP_DEVICE_STREAMING_ENABLED) + if (isp->asd.streaming) atomisp_setup_flash(&isp->asd); out: mutex_unlock(&isp->mutex); @@ -1298,7 +1242,7 @@ static void atomisp_update_capture_mode(struct atomisp_sub_device *asd) atomisp_css_capture_set_mode(asd, IA_CSS_CAPTURE_MODE_ADVANCED); else if (asd->params.low_light) atomisp_css_capture_set_mode(asd, IA_CSS_CAPTURE_MODE_LOW_LIGHT); - else if (asd->video_out_capture.sh_fmt == IA_CSS_FRAME_FORMAT_RAW) + else if (asd->video_out.sh_fmt == IA_CSS_FRAME_FORMAT_RAW) atomisp_css_capture_set_mode(asd, IA_CSS_CAPTURE_MODE_RAW); else atomisp_css_capture_set_mode(asd, IA_CSS_CAPTURE_MODE_PRIMARY); @@ -1553,13 +1497,12 @@ void atomisp_free_internal_buffers(struct atomisp_sub_device *asd) } static void atomisp_update_grid_info(struct atomisp_sub_device *asd, - enum ia_css_pipe_id pipe_id, - int source_pad) + enum ia_css_pipe_id pipe_id) { struct atomisp_device *isp = asd->isp; int err; - if (atomisp_css_get_grid_info(asd, pipe_id, source_pad)) + if (atomisp_css_get_grid_info(asd, pipe_id)) return; /* We must free all buffers because they no longer match @@ -1908,161 +1851,6 @@ int atomisp_3a_stat(struct atomisp_sub_device *asd, int flag, return 0; } -int atomisp_get_metadata(struct atomisp_sub_device *asd, int flag, - struct atomisp_metadata *md) -{ - struct atomisp_device *isp = asd->isp; - struct ia_css_stream_info *stream_info; - struct camera_mipi_info *mipi_info; - struct atomisp_metadata_buf *md_buf; - enum atomisp_metadata_type md_type = ATOMISP_MAIN_METADATA; - int ret, i; - - if (flag != 0) - return -EINVAL; - - stream_info = &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]. - stream_info; - - /* We always return the resolution and stride even if there is - * no valid metadata. This allows the caller to get the information - * needed to allocate user-space buffers. */ - md->width = stream_info->metadata_info.resolution.width; - md->height = stream_info->metadata_info.resolution.height; - md->stride = stream_info->metadata_info.stride; - - /* sanity check to avoid writing into unallocated memory. - * This does not return an error because it is a valid way - * for applications to detect that metadata is not enabled. */ - if (md->width == 0 || md->height == 0 || !md->data) - return 0; - - /* This is done in the atomisp_buf_done() */ - if (list_empty(&asd->metadata_ready[md_type])) { - dev_warn(isp->dev, "Metadata queue is empty now!\n"); - return -EAGAIN; - } - - mipi_info = atomisp_to_sensor_mipi_info( - isp->inputs[asd->input_curr].camera); - if (!mipi_info) - return -EINVAL; - - if (mipi_info->metadata_effective_width) { - for (i = 0; i < md->height; i++) - md->effective_width[i] = - mipi_info->metadata_effective_width[i]; - } - - md_buf = list_entry(asd->metadata_ready[md_type].next, - struct atomisp_metadata_buf, list); - md->exp_id = md_buf->metadata->exp_id; - if (md_buf->md_vptr) { - ret = copy_to_user(md->data, - md_buf->md_vptr, - stream_info->metadata_info.size); - } else { - hmm_load(md_buf->metadata->address, - asd->params.metadata_user[md_type], - stream_info->metadata_info.size); - - ret = copy_to_user(md->data, - asd->params.metadata_user[md_type], - stream_info->metadata_info.size); - } - if (ret) { - dev_err(isp->dev, "copy to user failed: copied %d bytes\n", - ret); - return -EFAULT; - } - - list_del_init(&md_buf->list); - list_add_tail(&md_buf->list, &asd->metadata[md_type]); - - dev_dbg(isp->dev, "%s: HAL de-queued metadata type %d with exp_id %d\n", - __func__, md_type, md->exp_id); - return 0; -} - -int atomisp_get_metadata_by_type(struct atomisp_sub_device *asd, int flag, - struct atomisp_metadata_with_type *md) -{ - struct atomisp_device *isp = asd->isp; - struct ia_css_stream_info *stream_info; - struct camera_mipi_info *mipi_info; - struct atomisp_metadata_buf *md_buf; - enum atomisp_metadata_type md_type; - int ret, i; - - if (flag != 0) - return -EINVAL; - - stream_info = &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]. - stream_info; - - /* We always return the resolution and stride even if there is - * no valid metadata. This allows the caller to get the information - * needed to allocate user-space buffers. */ - md->width = stream_info->metadata_info.resolution.width; - md->height = stream_info->metadata_info.resolution.height; - md->stride = stream_info->metadata_info.stride; - - /* sanity check to avoid writing into unallocated memory. - * This does not return an error because it is a valid way - * for applications to detect that metadata is not enabled. */ - if (md->width == 0 || md->height == 0 || !md->data) - return 0; - - md_type = md->type; - if (md_type < 0 || md_type >= ATOMISP_METADATA_TYPE_NUM) - return -EINVAL; - - /* This is done in the atomisp_buf_done() */ - if (list_empty(&asd->metadata_ready[md_type])) { - dev_warn(isp->dev, "Metadata queue is empty now!\n"); - return -EAGAIN; - } - - mipi_info = atomisp_to_sensor_mipi_info( - isp->inputs[asd->input_curr].camera); - if (!mipi_info) - return -EINVAL; - - if (mipi_info->metadata_effective_width) { - for (i = 0; i < md->height; i++) - md->effective_width[i] = - mipi_info->metadata_effective_width[i]; - } - - md_buf = list_entry(asd->metadata_ready[md_type].next, - struct atomisp_metadata_buf, list); - md->exp_id = md_buf->metadata->exp_id; - if (md_buf->md_vptr) { - ret = copy_to_user(md->data, - md_buf->md_vptr, - stream_info->metadata_info.size); - } else { - hmm_load(md_buf->metadata->address, - asd->params.metadata_user[md_type], - stream_info->metadata_info.size); - - ret = copy_to_user(md->data, - asd->params.metadata_user[md_type], - stream_info->metadata_info.size); - } - if (ret) { - dev_err(isp->dev, "copy to user failed: copied %d bytes\n", - ret); - return -EFAULT; - } else { - list_del_init(&md_buf->list); - list_add_tail(&md_buf->list, &asd->metadata[md_type]); - } - dev_dbg(isp->dev, "%s: HAL de-queued metadata type %d with exp_id %d\n", - __func__, md_type, md->exp_id); - return 0; -} - /* * Function to calculate real zoom region for every pipe */ @@ -3221,14 +3009,11 @@ void atomisp_handle_parameter_and_buffer(struct atomisp_video_pipe *pipe) lockdep_assert_held(&asd->isp->mutex); - if (atomisp_is_vf_pipe(pipe)) - return; - /* * CSS/FW requires set parameter and enqueue buffer happen after ISP * is streamon. */ - if (asd->streaming != ATOMISP_DEVICE_STREAMING_ENABLED) + if (!asd->streaming) return; if (list_empty(&pipe->per_frame_params) || @@ -3299,15 +3084,7 @@ int atomisp_set_parameters(struct video_device *vdev, dev_dbg(asd->isp->dev, "set parameter(per_frame_setting %d) isp_config_id %d of %s\n", arg->per_frame_setting, arg->isp_config_id, vdev->name); - if (IS_ISP2401) { - if (atomisp_is_vf_pipe(pipe) && arg->per_frame_setting) { - dev_err(asd->isp->dev, "%s: vf pipe not support per_frame_setting", - __func__); - return -EINVAL; - } - } - - if (arg->per_frame_setting && !atomisp_is_vf_pipe(pipe)) { + if (arg->per_frame_setting) { /* * Per-frame setting enabled, we allocate a new parameter * buffer to cache the parameters and only when frame buffers @@ -3346,7 +3123,7 @@ int atomisp_set_parameters(struct video_device *vdev, if (ret) goto apply_parameter_failed; - if (!(arg->per_frame_setting && !atomisp_is_vf_pipe(pipe))) { + if (!arg->per_frame_setting) { /* indicate to CSS that we have parameters to be updated */ asd->params.css_update_params_needed = true; } else { @@ -3880,66 +3657,202 @@ static void __atomisp_init_stream_info(u16 stream_index, } } +static void atomisp_fill_pix_format(struct v4l2_pix_format *f, + u32 width, u32 height, + const struct atomisp_format_bridge *br_fmt) +{ + u32 bytes; + + f->width = width; + f->height = height; + f->pixelformat = br_fmt->pixelformat; + + /* Adding padding to width for bytesperline calculation */ + width = ia_css_frame_pad_width(width, br_fmt->sh_fmt); + bytes = BITS_TO_BYTES(br_fmt->depth * width); + + if (br_fmt->planar) + f->bytesperline = width; + else + f->bytesperline = bytes; + + f->sizeimage = PAGE_ALIGN(height * bytes); + + if (f->field == V4L2_FIELD_ANY) + f->field = V4L2_FIELD_NONE; + + /* + * FIXME: do we need to set this up differently, depending on the + * sensor or the pipeline? + */ + f->colorspace = V4L2_COLORSPACE_REC709; + f->ycbcr_enc = V4L2_YCBCR_ENC_709; + f->xfer_func = V4L2_XFER_FUNC_709; +} + +/* Get sensor padding values for the non padded width x height resolution */ +void atomisp_get_padding(struct atomisp_device *isp, u32 width, u32 height, + u32 *padding_w, u32 *padding_h) +{ + struct atomisp_input_subdev *input = &isp->inputs[isp->asd.input_curr]; + struct v4l2_rect native_rect = input->native_rect; + const struct atomisp_in_fmt_conv *fc = NULL; + u32 min_pad_w = ISP2400_MIN_PAD_W; + u32 min_pad_h = ISP2400_MIN_PAD_H; + struct v4l2_mbus_framefmt *sink; + + if (!input->crop_support) { + *padding_w = pad_w; + *padding_h = pad_h; + return; + } + + width = min(width, input->active_rect.width); + height = min(height, input->active_rect.height); + + if (input->binning_support && width <= (input->active_rect.width / 2) && + height <= (input->active_rect.height / 2)) { + native_rect.width /= 2; + native_rect.height /= 2; + } + + *padding_w = min_t(u32, (native_rect.width - width) & ~1, pad_w); + *padding_h = min_t(u32, (native_rect.height - height) & ~1, pad_h); + + /* The below minimum padding requirements are for BYT / ISP2400 only */ + if (IS_ISP2401) + return; + + sink = atomisp_subdev_get_ffmt(&isp->asd.subdev, NULL, V4L2_SUBDEV_FORMAT_ACTIVE, + ATOMISP_SUBDEV_PAD_SINK); + if (sink) + fc = atomisp_find_in_fmt_conv(sink->code); + if (!fc) { + dev_warn(isp->dev, "%s: Could not get sensor format\n", __func__); + goto apply_min_padding; + } + + /* + * The ISP only supports GRBG for other bayer-orders additional padding + * is used so that the raw sensor data can be cropped to fix the order. + */ + if (fc->bayer_order == IA_CSS_BAYER_ORDER_RGGB || + fc->bayer_order == IA_CSS_BAYER_ORDER_GBRG) + min_pad_w += 2; + + if (fc->bayer_order == IA_CSS_BAYER_ORDER_BGGR || + fc->bayer_order == IA_CSS_BAYER_ORDER_GBRG) + min_pad_h += 2; + +apply_min_padding: + *padding_w = max_t(u32, *padding_w, min_pad_w); + *padding_h = max_t(u32, *padding_h, min_pad_h); +} + +static int atomisp_set_crop(struct atomisp_device *isp, + const struct v4l2_mbus_framefmt *format, + int which) +{ + struct atomisp_input_subdev *input = &isp->inputs[isp->asd.input_curr]; + struct v4l2_subdev_state pad_state = { + .pads = &input->pad_cfg, + }; + struct v4l2_subdev_selection sel = { + .which = which, + .target = V4L2_SEL_TGT_CROP, + .r.width = format->width, + .r.height = format->height, + }; + int ret; + + if (!input->crop_support) + return 0; + + /* Cropping is done before binning, when binning double the crop rect */ + if (input->binning_support && sel.r.width <= (input->native_rect.width / 2) && + sel.r.height <= (input->native_rect.height / 2)) { + sel.r.width *= 2; + sel.r.height *= 2; + } + + /* Clamp to avoid top/left calculations overflowing */ + sel.r.width = min(sel.r.width, input->native_rect.width); + sel.r.height = min(sel.r.height, input->native_rect.height); + + sel.r.left = ((input->native_rect.width - sel.r.width) / 2) & ~1; + sel.r.top = ((input->native_rect.height - sel.r.height) / 2) & ~1; + + ret = v4l2_subdev_call(input->camera, pad, set_selection, &pad_state, &sel); + if (ret) + dev_err(isp->dev, "Error setting crop to %ux%u @%ux%u: %d\n", + sel.r.width, sel.r.height, sel.r.left, sel.r.top, ret); + + return ret; +} + /* This function looks up the closest available resolution. */ -int atomisp_try_fmt(struct video_device *vdev, struct v4l2_pix_format *f, - bool *res_overflow) +int atomisp_try_fmt(struct atomisp_device *isp, struct v4l2_pix_format *f, + const struct atomisp_format_bridge **fmt_ret, + const struct atomisp_format_bridge **snr_fmt_ret) { - struct atomisp_device *isp = video_get_drvdata(vdev); - struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd; - struct v4l2_subdev_pad_config pad_cfg; + const struct atomisp_format_bridge *fmt, *snr_fmt; + struct atomisp_sub_device *asd = &isp->asd; + struct atomisp_input_subdev *input = &isp->inputs[asd->input_curr]; struct v4l2_subdev_state pad_state = { - .pads = &pad_cfg, + .pads = &input->pad_cfg, }; struct v4l2_subdev_format format = { .which = V4L2_SUBDEV_FORMAT_TRY, }; - const struct atomisp_format_bridge *fmt; + u32 padding_w, padding_h; int ret; - if (!asd) { - dev_err(isp->dev, "%s(): asd is NULL, device is %s\n", - __func__, vdev->name); - return -EINVAL; - } - - if (!isp->inputs[asd->input_curr].camera) + if (!input->camera) return -EINVAL; fmt = atomisp_get_format_bridge(f->pixelformat); - if (!fmt) { - dev_err(isp->dev, "unsupported pixelformat!\n"); - fmt = atomisp_output_fmts; - } - - if (f->width <= 0 || f->height <= 0) - return -EINVAL; + /* Currently, raw formats are broken!!! */ + if (!fmt || fmt->sh_fmt == IA_CSS_FRAME_FORMAT_RAW) { + f->pixelformat = V4L2_PIX_FMT_YUV420; - format.format.code = fmt->mbus_code; - format.format.width = f->width; - format.format.height = f->height; + fmt = atomisp_get_format_bridge(f->pixelformat); + if (!fmt) + return -EINVAL; + } - __atomisp_init_stream_info(ATOMISP_INPUT_STREAM_GENERAL, - (struct atomisp_input_stream_info *)format.format.reserved); + /* + * atomisp_set_fmt() will set the sensor resolution to the requested + * resolution + padding. Add padding here and remove it again after + * the set_fmt call, like atomisp_set_fmt_to_snr() does. + */ + atomisp_get_padding(isp, f->width, f->height, &padding_w, &padding_h); + v4l2_fill_mbus_format(&format.format, f, fmt->mbus_code); + format.format.width += padding_w; + format.format.height += padding_h; dev_dbg(isp->dev, "try_mbus_fmt: asking for %ux%u\n", format.format.width, format.format.height); - ret = v4l2_subdev_call(isp->inputs[asd->input_curr].camera, - pad, set_fmt, &pad_state, &format); + ret = atomisp_set_crop(isp, &format.format, V4L2_SUBDEV_FORMAT_TRY); + if (ret) + return ret; + + ret = v4l2_subdev_call(input->camera, pad, set_fmt, &pad_state, &format); if (ret) return ret; dev_dbg(isp->dev, "try_mbus_fmt: got %ux%u\n", format.format.width, format.format.height); - fmt = atomisp_get_format_bridge_from_mbus(format.format.code); - if (!fmt) { + snr_fmt = atomisp_get_format_bridge_from_mbus(format.format.code); + if (!snr_fmt) { dev_err(isp->dev, "unknown sensor format 0x%8.8x\n", format.format.code); return -EINVAL; } - f->pixelformat = fmt->pixelformat; + f->width = format.format.width - padding_w; + f->height = format.format.height - padding_h; /* * If the format is jpeg or custom RAW, then the width and height will @@ -3948,22 +3861,8 @@ int atomisp_try_fmt(struct video_device *vdev, struct v4l2_pix_format *f, * the sensor driver. */ if (f->pixelformat == V4L2_PIX_FMT_JPEG || - f->pixelformat == V4L2_PIX_FMT_CUSTOM_M10MO_RAW) { - f->width = format.format.width; - f->height = format.format.height; - return 0; - } - - if (!res_overflow || (format.format.width < f->width && - format.format.height < f->height)) { - f->width = format.format.width; - f->height = format.format.height; - /* Set the flag when resolution requested is - * beyond the max value supported by sensor - */ - if (res_overflow) - *res_overflow = true; - } + f->pixelformat == V4L2_PIX_FMT_CUSTOM_M10MO_RAW) + goto out_fill_pix_format; /* app vs isp */ f->width = rounddown(clamp_t(u32, f->width, ATOM_ISP_MIN_WIDTH, @@ -3971,11 +3870,20 @@ int atomisp_try_fmt(struct video_device *vdev, struct v4l2_pix_format *f, f->height = rounddown(clamp_t(u32, f->height, ATOM_ISP_MIN_HEIGHT, ATOM_ISP_MAX_HEIGHT), ATOM_ISP_STEP_HEIGHT); +out_fill_pix_format: + atomisp_fill_pix_format(f, f->width, f->height, fmt); + + if (fmt_ret) + *fmt_ret = fmt; + + if (snr_fmt_ret) + *snr_fmt_ret = snr_fmt; + return 0; } -enum mipi_port_id __get_mipi_port(struct atomisp_device *isp, - enum atomisp_camera_port port) +enum mipi_port_id atomisp_port_to_mipi_port(struct atomisp_device *isp, + enum atomisp_camera_port port) { switch (port) { case ATOMISP_CAMERA_PORT_PRIMARY: @@ -3983,9 +3891,7 @@ enum mipi_port_id __get_mipi_port(struct atomisp_device *isp, case ATOMISP_CAMERA_PORT_SECONDARY: return MIPI_PORT1_ID; case ATOMISP_CAMERA_PORT_TERTIARY: - if (MIPI_PORT1_ID + 1 != N_MIPI_PORT_ID) - return MIPI_PORT1_ID + 1; - fallthrough; + return MIPI_PORT2_ID; default: dev_err(isp->dev, "unsupported port: %d\n", port); return MIPI_PORT0_ID; @@ -3999,13 +3905,15 @@ static inline int atomisp_set_sensor_mipi_to_isp( { struct v4l2_control ctrl; struct atomisp_device *isp = asd->isp; + struct atomisp_input_subdev *input = &isp->inputs[asd->input_curr]; const struct atomisp_in_fmt_conv *fc; int mipi_freq = 0; unsigned int input_format, bayer_order; + enum atomisp_input_format metadata_format = ATOMISP_INPUT_FORMAT_EMBEDDED; + u32 mipi_port, metadata_width = 0, metadata_height = 0; ctrl.id = V4L2_CID_LINK_FREQ; - if (v4l2_g_ctrl - (isp->inputs[asd->input_curr].camera->ctrl_handler, &ctrl) == 0) + if (v4l2_g_ctrl(input->camera->ctrl_handler, &ctrl) == 0) mipi_freq = ctrl.value; if (asd->stream_env[stream_id].isys_configs == 1) { @@ -4029,7 +3937,7 @@ static inline int atomisp_set_sensor_mipi_to_isp( /* Compatibility for sensors which provide no media bus code * in s_mbus_framefmt() nor support pad formats. */ - if (mipi_info->input_format != -1) { + if (mipi_info && mipi_info->input_format != -1) { bayer_order = mipi_info->raw_bayer_order; /* Input stream config is still needs configured */ @@ -4039,6 +3947,9 @@ static inline int atomisp_set_sensor_mipi_to_isp( if (!fc) return -EINVAL; input_format = fc->atomisp_in_fmt; + metadata_format = mipi_info->metadata_format; + metadata_width = mipi_info->metadata_width; + metadata_height = mipi_info->metadata_height; } else { struct v4l2_mbus_framefmt *sink; @@ -4055,18 +3966,17 @@ static inline int atomisp_set_sensor_mipi_to_isp( atomisp_css_input_set_format(asd, stream_id, input_format); atomisp_css_input_set_bayer_order(asd, stream_id, bayer_order); - fc = atomisp_find_in_fmt_conv_by_atomisp_in_fmt( - mipi_info->metadata_format); + fc = atomisp_find_in_fmt_conv_by_atomisp_in_fmt(metadata_format); if (!fc) return -EINVAL; + input_format = fc->atomisp_in_fmt; - atomisp_css_input_configure_port(asd, - __get_mipi_port(asd->isp, mipi_info->port), - mipi_info->num_lanes, + mipi_port = atomisp_port_to_mipi_port(isp, input->port); + atomisp_css_input_configure_port(asd, mipi_port, + isp->sensor_lanes[mipi_port], 0xffff4, mipi_freq, input_format, - mipi_info->metadata_width, - mipi_info->metadata_height); + metadata_width, metadata_height); return 0; } @@ -4134,16 +4044,15 @@ static int css_input_resolution_changed(struct atomisp_sub_device *asd, static int atomisp_set_fmt_to_isp(struct video_device *vdev, struct ia_css_frame_info *output_info, - struct v4l2_pix_format *pix, - unsigned int source_pad) + const struct v4l2_pix_format *pix) { struct camera_mipi_info *mipi_info; struct atomisp_device *isp = video_get_drvdata(vdev); struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd; + struct atomisp_input_subdev *input = &isp->inputs[asd->input_curr]; const struct atomisp_format_bridge *format; struct v4l2_rect *isp_sink_crop; enum ia_css_pipe_id pipe_id; - struct v4l2_subdev_fh fh; int (*configure_output)(struct atomisp_sub_device *asd, unsigned int width, unsigned int height, unsigned int min_width, @@ -4155,7 +4064,7 @@ static int atomisp_set_fmt_to_isp(struct video_device *vdev, int (*configure_pp_input)(struct atomisp_sub_device *asd, unsigned int width, unsigned int height) = configure_pp_input_nop; - const struct atomisp_in_fmt_conv *fc; + const struct atomisp_in_fmt_conv *fc = NULL; int ret, i; if (!asd) { @@ -4164,8 +4073,6 @@ static int atomisp_set_fmt_to_isp(struct video_device *vdev, return -EINVAL; } - v4l2_fh_init(&fh.vfh, vdev); - isp_sink_crop = atomisp_subdev_get_rect( &asd->subdev, NULL, V4L2_SUBDEV_FORMAT_ACTIVE, ATOMISP_SUBDEV_PAD_SINK, V4L2_SEL_TGT_CROP); @@ -4174,18 +4081,16 @@ static int atomisp_set_fmt_to_isp(struct video_device *vdev, if (!format) return -EINVAL; - if (isp->inputs[asd->input_curr].type != TEST_PATTERN) { - mipi_info = atomisp_to_sensor_mipi_info( - isp->inputs[asd->input_curr].camera); - if (!mipi_info) { - dev_err(isp->dev, "mipi_info is NULL\n"); - return -EINVAL; - } + if (input->type != TEST_PATTERN) { + mipi_info = atomisp_to_sensor_mipi_info(input->camera); + if (atomisp_set_sensor_mipi_to_isp(asd, ATOMISP_INPUT_STREAM_GENERAL, mipi_info)) return -EINVAL; - fc = atomisp_find_in_fmt_conv_by_atomisp_in_fmt( - mipi_info->input_format); + + if (mipi_info) + fc = atomisp_find_in_fmt_conv_by_atomisp_in_fmt(mipi_info->input_format); + if (!fc) fc = atomisp_find_in_fmt_conv( atomisp_subdev_get_ffmt(&asd->subdev, @@ -4204,49 +4109,24 @@ static int atomisp_set_fmt_to_isp(struct video_device *vdev, * CSS still requires viewfinder configuration. */ { - struct v4l2_rect vf_size = {0}; - struct v4l2_mbus_framefmt vf_ffmt = {0}; + u32 width, height; if (pix->width < 640 || pix->height < 480) { - vf_size.width = pix->width; - vf_size.height = pix->height; + width = pix->width; + height = pix->height; } else { - vf_size.width = 640; - vf_size.height = 480; + width = 640; + height = 480; } - /* FIXME: proper format name for this one. See - atomisp_output_fmts[] in atomisp_v4l2.c */ - vf_ffmt.code = V4L2_MBUS_FMT_CUSTOM_YUV420; - - atomisp_subdev_set_selection(&asd->subdev, fh.state, - V4L2_SUBDEV_FORMAT_ACTIVE, - ATOMISP_SUBDEV_PAD_SOURCE_VF, - V4L2_SEL_TGT_COMPOSE, 0, &vf_size); - atomisp_subdev_set_ffmt(&asd->subdev, fh.state, - V4L2_SUBDEV_FORMAT_ACTIVE, - ATOMISP_SUBDEV_PAD_SOURCE_VF, &vf_ffmt); - asd->video_out_vf.sh_fmt = IA_CSS_FRAME_FORMAT_NV12; - - if (asd->vfpp->val == ATOMISP_VFPP_DISABLE_SCALER) { - atomisp_css_video_configure_viewfinder(asd, - vf_size.width, vf_size.height, 0, - asd->video_out_vf.sh_fmt); - } else if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO) { - if (source_pad == ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW || - source_pad == ATOMISP_SUBDEV_PAD_SOURCE_VIDEO) - atomisp_css_video_configure_viewfinder(asd, - vf_size.width, vf_size.height, 0, - asd->video_out_vf.sh_fmt); - else - atomisp_css_capture_configure_viewfinder(asd, - vf_size.width, vf_size.height, 0, - asd->video_out_vf.sh_fmt); - } else if (source_pad != ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW || + if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO || + asd->vfpp->val == ATOMISP_VFPP_DISABLE_SCALER) { + atomisp_css_video_configure_viewfinder(asd, width, height, 0, + IA_CSS_FRAME_FORMAT_NV12); + } else if (asd->run_mode->val == ATOMISP_RUN_MODE_STILL_CAPTURE || asd->vfpp->val == ATOMISP_VFPP_DISABLE_LOWLAT) { - atomisp_css_capture_configure_viewfinder(asd, - vf_size.width, vf_size.height, 0, - asd->video_out_vf.sh_fmt); + atomisp_css_capture_configure_viewfinder(asd, width, height, 0, + IA_CSS_FRAME_FORMAT_NV12); } } @@ -4268,7 +4148,7 @@ static int atomisp_set_fmt_to_isp(struct video_device *vdev, configure_output = atomisp_css_video_configure_output; get_frame_info = atomisp_css_video_get_output_frame_info; pipe_id = IA_CSS_PIPE_ID_VIDEO; - } else if (source_pad == ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW) { + } else if (asd->run_mode->val == ATOMISP_RUN_MODE_PREVIEW) { configure_output = atomisp_css_preview_configure_output; get_frame_info = atomisp_css_preview_get_output_frame_info; configure_pp_input = atomisp_css_preview_configure_pp_input; @@ -4333,7 +4213,7 @@ static int atomisp_set_fmt_to_isp(struct video_device *vdev, return ret; } - atomisp_update_grid_info(asd, pipe_id, source_pad); + atomisp_update_grid_info(asd, pipe_id); return 0; } @@ -4357,7 +4237,7 @@ static void atomisp_get_dis_envelop(struct atomisp_sub_device *asd, } static void atomisp_check_copy_mode(struct atomisp_sub_device *asd, - int source_pad, const struct v4l2_pix_format *f) + const struct v4l2_pix_format *f) { struct v4l2_mbus_framefmt *sink, *src; @@ -4370,7 +4250,7 @@ static void atomisp_check_copy_mode(struct atomisp_sub_device *asd, sink = atomisp_subdev_get_ffmt(&asd->subdev, NULL, V4L2_SUBDEV_FORMAT_ACTIVE, ATOMISP_SUBDEV_PAD_SINK); src = atomisp_subdev_get_ffmt(&asd->subdev, NULL, - V4L2_SUBDEV_FORMAT_ACTIVE, source_pad); + V4L2_SUBDEV_FORMAT_ACTIVE, ATOMISP_SUBDEV_PAD_SOURCE); if (sink->code == src->code && sink->width == f->width && sink->height == f->height) asd->copy_mode = true; @@ -4381,26 +4261,23 @@ static void atomisp_check_copy_mode(struct atomisp_sub_device *asd, } static int atomisp_set_fmt_to_snr(struct video_device *vdev, const struct v4l2_pix_format *f, - unsigned int padding_w, unsigned int padding_h, unsigned int dvs_env_w, unsigned int dvs_env_h) { struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev); struct atomisp_sub_device *asd = pipe->asd; + struct atomisp_device *isp = asd->isp; + struct atomisp_input_subdev *input = &isp->inputs[asd->input_curr]; const struct atomisp_format_bridge *format; - struct v4l2_subdev_pad_config pad_cfg; struct v4l2_subdev_state pad_state = { - .pads = &pad_cfg, + .pads = &input->pad_cfg, }; struct v4l2_subdev_format vformat = { .which = V4L2_SUBDEV_FORMAT_TRY, }; struct v4l2_mbus_framefmt *ffmt = &vformat.format; struct v4l2_mbus_framefmt *req_ffmt; - struct atomisp_device *isp; struct atomisp_input_stream_info *stream_info = (struct atomisp_input_stream_info *)ffmt->reserved; - int source_pad = atomisp_subdev_source_pad(vdev); - struct v4l2_subdev_fh fh; int ret; if (!asd) { @@ -4409,20 +4286,16 @@ static int atomisp_set_fmt_to_snr(struct video_device *vdev, const struct v4l2_p return -EINVAL; } - isp = asd->isp; - - v4l2_fh_init(&fh.vfh, vdev); - format = atomisp_get_format_bridge(f->pixelformat); if (!format) return -EINVAL; v4l2_fill_mbus_format(ffmt, f, format->mbus_code); - ffmt->height += padding_h + dvs_env_h; - ffmt->width += padding_w + dvs_env_w; + ffmt->height += asd->sink_pad_padding_h + dvs_env_h; + ffmt->width += asd->sink_pad_padding_w + dvs_env_w; dev_dbg(isp->dev, "s_mbus_fmt: ask %ux%u (padding %ux%u, dvs %ux%u)\n", - ffmt->width, ffmt->height, padding_w, padding_h, + ffmt->width, ffmt->height, asd->sink_pad_padding_w, asd->sink_pad_padding_h, dvs_env_w, dvs_env_h); __atomisp_init_stream_info(ATOMISP_INPUT_STREAM_GENERAL, stream_info); @@ -4430,11 +4303,13 @@ static int atomisp_set_fmt_to_snr(struct video_device *vdev, const struct v4l2_p req_ffmt = ffmt; /* Disable dvs if resolution can't be supported by sensor */ - if (asd->params.video_dis_en && - source_pad == ATOMISP_SUBDEV_PAD_SOURCE_VIDEO) { + if (asd->params.video_dis_en && asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO) { + ret = atomisp_set_crop(isp, &vformat.format, V4L2_SUBDEV_FORMAT_TRY); + if (ret) + return ret; + vformat.which = V4L2_SUBDEV_FORMAT_TRY; - ret = v4l2_subdev_call(isp->inputs[asd->input_curr].camera, - pad, set_fmt, &pad_state, &vformat); + ret = v4l2_subdev_call(input->camera, pad, set_fmt, &pad_state, &vformat); if (ret) return ret; @@ -4451,9 +4326,13 @@ static int atomisp_set_fmt_to_snr(struct video_device *vdev, const struct v4l2_p asd->params.video_dis_en = false; } } + + ret = atomisp_set_crop(isp, &vformat.format, V4L2_SUBDEV_FORMAT_ACTIVE); + if (ret) + return ret; + vformat.which = V4L2_SUBDEV_FORMAT_ACTIVE; - ret = v4l2_subdev_call(isp->inputs[asd->input_curr].camera, pad, - set_fmt, NULL, &vformat); + ret = v4l2_subdev_call(input->camera, pad, set_fmt, NULL, &vformat); if (ret) return ret; @@ -4466,15 +4345,14 @@ static int atomisp_set_fmt_to_snr(struct video_device *vdev, const struct v4l2_p ffmt->height < ATOM_ISP_STEP_HEIGHT) return -EINVAL; - if (asd->params.video_dis_en && - source_pad == ATOMISP_SUBDEV_PAD_SOURCE_VIDEO && + if (asd->params.video_dis_en && asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO && (ffmt->width < req_ffmt->width || ffmt->height < req_ffmt->height)) { dev_warn(isp->dev, "can not enable video dis due to sensor limitation."); asd->params.video_dis_en = false; } - atomisp_subdev_set_ffmt(&asd->subdev, fh.state, + atomisp_subdev_set_ffmt(&asd->subdev, NULL, V4L2_SUBDEV_FORMAT_ACTIVE, ATOMISP_SUBDEV_PAD_SINK, ffmt); @@ -4490,65 +4368,25 @@ int atomisp_set_fmt(struct video_device *vdev, struct v4l2_format *f) const struct atomisp_format_bridge *snr_format_bridge; struct ia_css_frame_info output_info; unsigned int dvs_env_w = 0, dvs_env_h = 0; - unsigned int padding_w = pad_w, padding_h = pad_h; struct v4l2_mbus_framefmt isp_source_fmt = {0}; - struct v4l2_subdev_format vformat = { - .which = V4L2_SUBDEV_FORMAT_ACTIVE, - }; struct v4l2_rect isp_sink_crop; - u16 source_pad = atomisp_subdev_source_pad(vdev); - struct v4l2_subdev_fh fh; int ret; ret = atomisp_pipe_check(pipe, true); if (ret) return ret; - if (source_pad >= ATOMISP_SUBDEV_PADS_NUM) - return -EINVAL; - dev_dbg(isp->dev, - "setting resolution %ux%u on pad %u bytesperline %u\n", - f->fmt.pix.width, f->fmt.pix.height, source_pad, f->fmt.pix.bytesperline); - - v4l2_fh_init(&fh.vfh, vdev); - - format_bridge = atomisp_get_format_bridge(f->fmt.pix.pixelformat); - if (!format_bridge) - return -EINVAL; - - /* Currently, raw formats are broken!!! */ - - if (format_bridge->sh_fmt == IA_CSS_FRAME_FORMAT_RAW) { - f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUV420; - - format_bridge = atomisp_get_format_bridge(f->fmt.pix.pixelformat); - if (!format_bridge) - return -EINVAL; - } - pipe->sh_fmt = format_bridge->sh_fmt; - pipe->pix.pixelformat = f->fmt.pix.pixelformat; + "setting resolution %ux%u bytesperline %u\n", + f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.bytesperline); /* Ensure that the resolution is equal or below the maximum supported */ - - vformat.which = V4L2_SUBDEV_FORMAT_ACTIVE; - v4l2_fill_mbus_format(&vformat.format, &f->fmt.pix, format_bridge->mbus_code); - vformat.format.height += padding_h; - vformat.format.width += padding_w; - - ret = v4l2_subdev_call(isp->inputs[asd->input_curr].camera, pad, - set_fmt, NULL, &vformat); + ret = atomisp_try_fmt(isp, &f->fmt.pix, &format_bridge, &snr_format_bridge); if (ret) return ret; - f->fmt.pix.width = vformat.format.width - padding_w; - f->fmt.pix.height = vformat.format.height - padding_h; - - snr_format_bridge = atomisp_get_format_bridge_from_mbus(vformat.format.code); - if (!snr_format_bridge) { - dev_warn(isp->dev, "Can't find bridge format\n"); - return -EINVAL; - } + pipe->sh_fmt = format_bridge->sh_fmt; + pipe->pix.pixelformat = format_bridge->pixelformat; atomisp_subdev_get_ffmt(&asd->subdev, NULL, V4L2_SUBDEV_FORMAT_ACTIVE, @@ -4556,22 +4394,22 @@ int atomisp_set_fmt(struct video_device *vdev, struct v4l2_format *f) snr_format_bridge->mbus_code; isp_source_fmt.code = format_bridge->mbus_code; - atomisp_subdev_set_ffmt(&asd->subdev, fh.state, + atomisp_subdev_set_ffmt(&asd->subdev, NULL, V4L2_SUBDEV_FORMAT_ACTIVE, - source_pad, &isp_source_fmt); + ATOMISP_SUBDEV_PAD_SOURCE, &isp_source_fmt); - if (!atomisp_subdev_format_conversion(asd, source_pad)) { - padding_w = 0; - padding_h = 0; + if (atomisp_subdev_format_conversion(asd)) { + atomisp_get_padding(isp, f->fmt.pix.width, f->fmt.pix.height, + &asd->sink_pad_padding_w, &asd->sink_pad_padding_h); + } else { + asd->sink_pad_padding_w = 0; + asd->sink_pad_padding_h = 0; } atomisp_get_dis_envelop(asd, f->fmt.pix.width, f->fmt.pix.height, &dvs_env_w, &dvs_env_h); - asd->capture_pad = source_pad; - - ret = atomisp_set_fmt_to_snr(vdev, &f->fmt.pix, - padding_w, padding_h, dvs_env_w, dvs_env_h); + ret = atomisp_set_fmt_to_snr(vdev, &f->fmt.pix, dvs_env_w, dvs_env_h); if (ret) { dev_warn(isp->dev, "Set format to sensor failed with %d\n", ret); @@ -4580,7 +4418,7 @@ int atomisp_set_fmt(struct video_device *vdev, struct v4l2_format *f) atomisp_csi_lane_config(isp); - atomisp_check_copy_mode(asd, source_pad, &f->fmt.pix); + atomisp_check_copy_mode(asd, &f->fmt.pix); isp_sink_crop = *atomisp_subdev_get_rect(&asd->subdev, NULL, V4L2_SUBDEV_FORMAT_ACTIVE, @@ -4589,25 +4427,20 @@ int atomisp_set_fmt(struct video_device *vdev, struct v4l2_format *f) /* Try to enable YUV downscaling if ISP input is 10 % (either * width or height) bigger than the desired result. */ - if (isp_sink_crop.width * 9 / 10 < f->fmt.pix.width || + if (!IS_MOFD || + isp_sink_crop.width * 9 / 10 < f->fmt.pix.width || isp_sink_crop.height * 9 / 10 < f->fmt.pix.height || - (atomisp_subdev_format_conversion(asd, source_pad) && + (atomisp_subdev_format_conversion(asd) && (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO || asd->vfpp->val == ATOMISP_VFPP_DISABLE_SCALER))) { isp_sink_crop.width = f->fmt.pix.width; isp_sink_crop.height = f->fmt.pix.height; - atomisp_subdev_set_selection(&asd->subdev, fh.state, + atomisp_subdev_set_selection(&asd->subdev, NULL, V4L2_SUBDEV_FORMAT_ACTIVE, - ATOMISP_SUBDEV_PAD_SINK, - V4L2_SEL_TGT_CROP, - V4L2_SEL_FLAG_KEEP_CONFIG, - &isp_sink_crop); - atomisp_subdev_set_selection(&asd->subdev, fh.state, - V4L2_SUBDEV_FORMAT_ACTIVE, - source_pad, V4L2_SEL_TGT_COMPOSE, + ATOMISP_SUBDEV_PAD_SOURCE, V4L2_SEL_TGT_COMPOSE, 0, &isp_sink_crop); - } else if (IS_MOFD) { + } else { struct v4l2_rect main_compose = {0}; main_compose.width = isp_sink_crop.width; @@ -4622,104 +4455,25 @@ int atomisp_set_fmt(struct video_device *vdev, struct v4l2_format *f) f->fmt.pix.height); } - atomisp_subdev_set_selection(&asd->subdev, fh.state, + atomisp_subdev_set_selection(&asd->subdev, NULL, V4L2_SUBDEV_FORMAT_ACTIVE, - source_pad, - V4L2_SEL_TGT_COMPOSE, 0, - &main_compose); - } else { - struct v4l2_rect sink_crop = {0}; - struct v4l2_rect main_compose = {0}; - - main_compose.width = f->fmt.pix.width; - main_compose.height = f->fmt.pix.height; - - /* WORKAROUND: this override is universally enabled in - * GMIN to work around a CTS failures (GMINL-539) - * which appears to be related by a hardware - * performance limitation. It's unclear why this - * particular code triggers the issue. */ - if (isp_sink_crop.width * main_compose.height > - isp_sink_crop.height * main_compose.width) { - sink_crop.height = isp_sink_crop.height; - sink_crop.width = - DIV_NEAREST_STEP(sink_crop.height * f->fmt.pix.width, - f->fmt.pix.height, - ATOM_ISP_STEP_WIDTH); - } else { - sink_crop.width = isp_sink_crop.width; - sink_crop.height = - DIV_NEAREST_STEP(sink_crop.width * f->fmt.pix.height, - f->fmt.pix.width, - ATOM_ISP_STEP_HEIGHT); - } - atomisp_subdev_set_selection(&asd->subdev, fh.state, - V4L2_SUBDEV_FORMAT_ACTIVE, - ATOMISP_SUBDEV_PAD_SINK, - V4L2_SEL_TGT_CROP, - V4L2_SEL_FLAG_KEEP_CONFIG, - &sink_crop); - - atomisp_subdev_set_selection(&asd->subdev, fh.state, - V4L2_SUBDEV_FORMAT_ACTIVE, - source_pad, + ATOMISP_SUBDEV_PAD_SOURCE, V4L2_SEL_TGT_COMPOSE, 0, &main_compose); } - ret = atomisp_set_fmt_to_isp(vdev, &output_info, &f->fmt.pix, source_pad); + ret = atomisp_set_fmt_to_isp(vdev, &output_info, &f->fmt.pix); if (ret) { dev_warn(isp->dev, "Can't set format on ISP. Error %d\n", ret); return -EINVAL; } - pipe->pix.width = f->fmt.pix.width; - pipe->pix.height = f->fmt.pix.height; - pipe->pix.pixelformat = f->fmt.pix.pixelformat; - /* - * FIXME: do we need to setup this differently, depending on the - * sensor or the pipeline? - */ - pipe->pix.colorspace = V4L2_COLORSPACE_REC709; - pipe->pix.ycbcr_enc = V4L2_YCBCR_ENC_709; - pipe->pix.xfer_func = V4L2_XFER_FUNC_709; - - if (format_bridge->planar) { - pipe->pix.bytesperline = output_info.padded_width; - pipe->pix.sizeimage = PAGE_ALIGN(f->fmt.pix.height * - DIV_ROUND_UP(format_bridge->depth * - output_info.padded_width, 8)); - } else { - pipe->pix.bytesperline = - DIV_ROUND_UP(format_bridge->depth * - output_info.padded_width, 8); - pipe->pix.sizeimage = - PAGE_ALIGN(f->fmt.pix.height * pipe->pix.bytesperline); - } - dev_dbg(isp->dev, "%s: image size: %d, %d bytes per line\n", - __func__, pipe->pix.sizeimage, pipe->pix.bytesperline); - - if (f->fmt.pix.field == V4L2_FIELD_ANY) - f->fmt.pix.field = V4L2_FIELD_NONE; - pipe->pix.field = f->fmt.pix.field; + atomisp_fill_pix_format(&pipe->pix, f->fmt.pix.width, f->fmt.pix.height, format_bridge); f->fmt.pix = pipe->pix; f->fmt.pix.priv = PAGE_ALIGN(pipe->pix.width * pipe->pix.height * 2); - /* - * If in video 480P case, no GFX throttle - */ - if (asd->run_mode->val == ATOMISP_SUBDEV_PAD_SOURCE_VIDEO && - f->fmt.pix.width == 720 && f->fmt.pix.height == 480) - isp->need_gfx_throttle = false; - else - isp->need_gfx_throttle = true; - - /* Report the needed sizes */ - f->fmt.pix.sizeimage = pipe->pix.sizeimage; - f->fmt.pix.bytesperline = pipe->pix.bytesperline; - dev_dbg(isp->dev, "%s: %dx%d, image size: %d, %d bytes per line\n", __func__, f->fmt.pix.width, f->fmt.pix.height, @@ -4790,30 +4544,6 @@ int atomisp_set_shading_table(struct atomisp_sub_device *asd, return ret; } -/* - * set auto exposure metering window to camera sensor - */ -int atomisp_s_ae_window(struct atomisp_sub_device *asd, - struct atomisp_ae_window *arg) -{ - struct atomisp_device *isp = asd->isp; - /* Coverity CID 298071 - initialzize struct */ - struct v4l2_subdev_selection sel = { 0 }; - - sel.r.left = arg->x_left; - sel.r.top = arg->y_top; - sel.r.width = arg->x_right - arg->x_left + 1; - sel.r.height = arg->y_bottom - arg->y_top + 1; - - if (v4l2_subdev_call(isp->inputs[asd->input_curr].camera, - pad, set_selection, NULL, &sel)) { - dev_err(isp->dev, "failed to call sensor set_selection.\n"); - return -EINVAL; - } - - return 0; -} - int atomisp_flash_enable(struct atomisp_sub_device *asd, int num_frames) { struct atomisp_device *isp = asd->isp; @@ -4836,26 +4566,6 @@ int atomisp_flash_enable(struct atomisp_sub_device *asd, int num_frames) return 0; } -bool atomisp_is_vf_pipe(struct atomisp_video_pipe *pipe) -{ - struct atomisp_sub_device *asd = pipe->asd; - - if (!asd) { - dev_err(pipe->isp->dev, "%s(): asd is NULL, device is %s\n", - __func__, pipe->vdev.name); - return false; - } - - if (pipe == &asd->video_out_vf) - return true; - - if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO && - pipe == &asd->video_out_preview) - return true; - - return false; -} - static int __checking_exp_id(struct atomisp_sub_device *asd, int exp_id) { struct atomisp_device *isp = asd->isp; @@ -4864,7 +4574,7 @@ static int __checking_exp_id(struct atomisp_sub_device *asd, int exp_id) dev_warn(isp->dev, "%s Raw Buffer Lock is disable.\n", __func__); return -EINVAL; } - if (asd->streaming != ATOMISP_DEVICE_STREAMING_ENABLED) { + if (!asd->streaming) { dev_err(isp->dev, "%s streaming %d invalid exp_id %d.\n", __func__, exp_id, asd->streaming); return -EINVAL; @@ -4986,7 +4696,7 @@ int atomisp_enable_dz_capt_pipe(struct atomisp_sub_device *asd, int atomisp_inject_a_fake_event(struct atomisp_sub_device *asd, int *event) { - if (!event || asd->streaming != ATOMISP_DEVICE_STREAMING_ENABLED) + if (!event || !asd->streaming) return -EINVAL; lockdep_assert_held(&asd->isp->mutex); @@ -5013,69 +4723,3 @@ int atomisp_inject_a_fake_event(struct atomisp_sub_device *asd, int *event) return 0; } - -static int atomisp_get_pipe_id(struct atomisp_video_pipe *pipe) -{ - struct atomisp_sub_device *asd = pipe->asd; - - if (!asd) { - dev_err(pipe->isp->dev, "%s(): asd is NULL, device is %s\n", - __func__, pipe->vdev.name); - return -EINVAL; - } - - if (asd->vfpp->val == ATOMISP_VFPP_DISABLE_SCALER) { - return IA_CSS_PIPE_ID_VIDEO; - } else if (asd->vfpp->val == ATOMISP_VFPP_DISABLE_LOWLAT) { - return IA_CSS_PIPE_ID_CAPTURE; - } else if (pipe == &asd->video_out_video_capture) { - return IA_CSS_PIPE_ID_VIDEO; - } else if (pipe == &asd->video_out_vf) { - return IA_CSS_PIPE_ID_CAPTURE; - } else if (pipe == &asd->video_out_preview) { - if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO) - return IA_CSS_PIPE_ID_VIDEO; - else - return IA_CSS_PIPE_ID_PREVIEW; - } else if (pipe == &asd->video_out_capture) { - if (asd->copy_mode) - return IA_CSS_PIPE_ID_COPY; - else - return IA_CSS_PIPE_ID_CAPTURE; - } - - /* fail through */ - dev_warn(asd->isp->dev, "%s failed to find proper pipe\n", - __func__); - return IA_CSS_PIPE_ID_CAPTURE; -} - -int atomisp_get_invalid_frame_num(struct video_device *vdev, - int *invalid_frame_num) -{ - struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev); - struct atomisp_sub_device *asd = pipe->asd; - enum ia_css_pipe_id pipe_id; - struct ia_css_pipe_info p_info; - int ret; - - pipe_id = atomisp_get_pipe_id(pipe); - if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].pipes[pipe_id]) { - dev_warn(asd->isp->dev, - "%s pipe %d has not been created yet, do SET_FMT first!\n", - __func__, pipe_id); - return -EINVAL; - } - - ret = ia_css_pipe_get_info( - asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL] - .pipes[pipe_id], &p_info); - if (!ret) { - *invalid_frame_num = p_info.num_invalid_frames; - return 0; - } else { - dev_warn(asd->isp->dev, "%s get pipe infor failed %d\n", - __func__, ret); - return -EINVAL; - } -} diff --git a/drivers/staging/media/atomisp/pci/atomisp_cmd.h b/drivers/staging/media/atomisp/pci/atomisp_cmd.h index 399b549bcf831d4774ed44ec073574fa537b5693..8305161d2062887cf40c8c887748c9fefaf19419 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_cmd.h +++ b/drivers/staging/media/atomisp/pci/atomisp_cmd.h @@ -59,7 +59,6 @@ int atomisp_buffers_in_css(struct atomisp_video_pipe *pipe); void atomisp_buffer_done(struct ia_css_frame *frame, enum vb2_buffer_state state); void atomisp_flush_video_pipe(struct atomisp_video_pipe *pipe, enum vb2_buffer_state state, bool warn_on_css_frames); -void atomisp_flush_bufs_and_wakeup(struct atomisp_sub_device *asd); void atomisp_clear_css_buffer_counters(struct atomisp_sub_device *asd); /* Interrupt functions */ @@ -160,13 +159,6 @@ int atomisp_set_dis_vector(struct atomisp_sub_device *asd, int atomisp_3a_stat(struct atomisp_sub_device *asd, int flag, struct atomisp_3a_statistics *config); -/* Function to get metadata from isp */ -int atomisp_get_metadata(struct atomisp_sub_device *asd, int flag, - struct atomisp_metadata *config); - -int atomisp_get_metadata_by_type(struct atomisp_sub_device *asd, int flag, - struct atomisp_metadata_with_type *config); - int atomisp_set_parameters(struct video_device *vdev, struct atomisp_parameters *arg); @@ -258,9 +250,14 @@ int atomisp_makeup_css_parameters(struct atomisp_sub_device *asd, int atomisp_compare_grid(struct atomisp_sub_device *asd, struct atomisp_grid_info *atomgrid); +/* Get sensor padding values for the non padded width x height resolution */ +void atomisp_get_padding(struct atomisp_device *isp, u32 width, u32 height, + u32 *padding_w, u32 *padding_h); + /* This function looks up the closest available resolution. */ -int atomisp_try_fmt(struct video_device *vdev, struct v4l2_pix_format *f, - bool *res_overflow); +int atomisp_try_fmt(struct atomisp_device *isp, struct v4l2_pix_format *f, + const struct atomisp_format_bridge **fmt_ret, + const struct atomisp_format_bridge **snr_fmt_ret); int atomisp_set_fmt(struct video_device *vdev, struct v4l2_format *f); @@ -269,9 +266,6 @@ int atomisp_set_shading_table(struct atomisp_sub_device *asd, void atomisp_free_internal_buffers(struct atomisp_sub_device *asd); -int atomisp_s_ae_window(struct atomisp_sub_device *asd, - struct atomisp_ae_window *arg); - int atomisp_flash_enable(struct atomisp_sub_device *asd, int num_frames); @@ -284,15 +278,11 @@ void atomisp_buf_done(struct atomisp_sub_device *asd, int error, enum ia_css_pipe_id css_pipe_id, bool q_buffers, enum atomisp_input_stream_id stream_id); -void atomisp_css_flush(struct atomisp_device *isp); - /* Events. Only one event has to be exported for now. */ void atomisp_eof_event(struct atomisp_sub_device *asd, uint8_t exp_id); -enum mipi_port_id __get_mipi_port(struct atomisp_device *isp, - enum atomisp_camera_port port); - -bool atomisp_is_vf_pipe(struct atomisp_video_pipe *pipe); +enum mipi_port_id atomisp_port_to_mipi_port(struct atomisp_device *isp, + enum atomisp_camera_port port); void atomisp_apply_css_parameters( struct atomisp_sub_device *asd, diff --git a/drivers/staging/media/atomisp/pci/atomisp_common.h b/drivers/staging/media/atomisp/pci/atomisp_common.h index 07c38e487a66ada12083c44fbf3207942d4b80b4..9d23a6ccfc337f140b2517850e57b864366db346 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_common.h +++ b/drivers/staging/media/atomisp/pci/atomisp_common.h @@ -37,6 +37,10 @@ extern int mipicsi_flag; extern int pad_w; extern int pad_h; +/* Minimum padding requirements for ISP2400 (BYT) */ +#define ISP2400_MIN_PAD_W 12 +#define ISP2400_MIN_PAD_H 12 + #define CSS_DTRACE_VERBOSITY_LEVEL 5 /* Controls trace verbosity */ #define CSS_DTRACE_VERBOSITY_TIMEOUT 9 /* Verbosity on ISP timeout */ #define MRFLD_MAX_ZOOM_FACTOR 1024 diff --git a/drivers/staging/media/atomisp/pci/atomisp_compat.h b/drivers/staging/media/atomisp/pci/atomisp_compat.h index 218e8ac276c89234e831760e92c4491711e48c15..e9e4bfb0f5f97926ff5efc1e3ae1331e8f457711 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_compat.h +++ b/drivers/staging/media/atomisp/pci/atomisp_compat.h @@ -78,8 +78,7 @@ int atomisp_q_dis_buffer_to_css(struct atomisp_sub_device *asd, void ia_css_mmu_invalidate_cache(void); -int atomisp_css_start(struct atomisp_sub_device *asd, - enum ia_css_pipe_id pipe_id, bool in_reset); +int atomisp_css_start(struct atomisp_sub_device *asd); void atomisp_css_update_isp_params(struct atomisp_sub_device *asd); void atomisp_css_update_isp_params_on_pipe(struct atomisp_sub_device *asd, @@ -113,8 +112,7 @@ void atomisp_css_free_metadata_buffer(struct atomisp_metadata_buf *metadata_buf); int atomisp_css_get_grid_info(struct atomisp_sub_device *asd, - enum ia_css_pipe_id pipe_id, - int source_pad); + enum ia_css_pipe_id pipe_id); int atomisp_alloc_3a_output_buf(struct atomisp_sub_device *asd); @@ -151,10 +149,6 @@ int atomisp_css_set_default_isys_config(struct atomisp_sub_device *asd, enum atomisp_input_stream_id stream_id, struct v4l2_mbus_framefmt *ffmt); -int atomisp_css_isys_two_stream_cfg(struct atomisp_sub_device *asd, - enum atomisp_input_stream_id stream_id, - enum atomisp_input_format input_format); - void atomisp_css_isys_two_stream_cfg_update_stream1( struct atomisp_sub_device *asd, enum atomisp_input_stream_id stream_id, @@ -210,15 +204,6 @@ void atomisp_css_capture_enable_online(struct atomisp_sub_device *asd, void atomisp_css_preview_enable_online(struct atomisp_sub_device *asd, unsigned short stream_index, bool enable); -void atomisp_css_video_enable_online(struct atomisp_sub_device *asd, - bool enable); - -void atomisp_css_enable_continuous(struct atomisp_sub_device *asd, - bool enable); - -void atomisp_css_enable_cvf(struct atomisp_sub_device *asd, - bool enable); - int atomisp_css_input_configure_port(struct atomisp_sub_device *asd, enum mipi_port_id port, unsigned int num_lanes, @@ -229,10 +214,9 @@ int atomisp_css_input_configure_port(struct atomisp_sub_device *asd, unsigned int metadata_height); int atomisp_create_pipes_stream(struct atomisp_sub_device *asd); -void atomisp_destroy_pipes_stream_force(struct atomisp_sub_device *asd); +void atomisp_destroy_pipes_stream(struct atomisp_sub_device *asd); -void atomisp_css_stop(struct atomisp_sub_device *asd, - enum ia_css_pipe_id pipe_id, bool in_reset); +void atomisp_css_stop(struct atomisp_sub_device *asd, bool in_reset); void atomisp_css_continuous_set_num_raw_frames( struct atomisp_sub_device *asd, @@ -244,22 +228,6 @@ int atomisp_css_copy_configure_output(struct atomisp_sub_device *asd, unsigned int padded_width, enum ia_css_frame_format format); -int atomisp_css_yuvpp_configure_output(struct atomisp_sub_device *asd, - unsigned int stream_index, - unsigned int width, unsigned int height, - unsigned int padded_width, - enum ia_css_frame_format format); - -int atomisp_css_yuvpp_get_output_frame_info( - struct atomisp_sub_device *asd, - unsigned int stream_index, - struct ia_css_frame_info *info); - -int atomisp_css_yuvpp_get_viewfinder_frame_info( - struct atomisp_sub_device *asd, - unsigned int stream_index, - struct ia_css_frame_info *info); - int atomisp_css_preview_configure_output(struct atomisp_sub_device *asd, unsigned int width, unsigned int height, unsigned int min_width, @@ -276,7 +244,6 @@ int atomisp_css_video_configure_output(struct atomisp_sub_device *asd, enum ia_css_frame_format format); int atomisp_get_css_frame_info(struct atomisp_sub_device *asd, - u16 source_pad, struct ia_css_frame_info *frame_info); int atomisp_css_video_configure_viewfinder(struct atomisp_sub_device *asd, diff --git a/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c b/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c index 1dae2a7cfdd9b419365caf47862dba5ccebe7337..b13d1cb4668d950e7d80abb6696127a120ca5c6b 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c +++ b/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c @@ -548,7 +548,7 @@ static int __destroy_pipes(struct atomisp_sub_device *asd) return 0; } -void atomisp_destroy_pipes_stream_force(struct atomisp_sub_device *asd) +void atomisp_destroy_pipes_stream(struct atomisp_sub_device *asd) { if (__destroy_streams(asd)) dev_warn(asd->isp->dev, "destroy stream failed.\n"); @@ -649,23 +649,11 @@ static bool is_pipe_valid_to_current_run_mode(struct atomisp_sub_device *asd, if (pipe_id == IA_CSS_PIPE_ID_PREVIEW) return true; - return false; - case ATOMISP_RUN_MODE_CONTINUOUS_CAPTURE: - if (pipe_id == IA_CSS_PIPE_ID_CAPTURE || - pipe_id == IA_CSS_PIPE_ID_PREVIEW) - return true; - return false; case ATOMISP_RUN_MODE_VIDEO: if (pipe_id == IA_CSS_PIPE_ID_VIDEO || pipe_id == IA_CSS_PIPE_ID_YUVPP) return true; - return false; - case ATOMISP_RUN_MODE_SDV: - if (pipe_id == IA_CSS_PIPE_ID_CAPTURE || - pipe_id == IA_CSS_PIPE_ID_VIDEO) - return true; - return false; } @@ -758,7 +746,7 @@ int atomisp_create_pipes_stream(struct atomisp_sub_device *asd) int atomisp_css_update_stream(struct atomisp_sub_device *asd) { - atomisp_destroy_pipes_stream_force(asd); + atomisp_destroy_pipes_stream(asd); return atomisp_create_pipes_stream(asd); } @@ -997,57 +985,22 @@ int atomisp_q_dis_buffer_to_css(struct atomisp_sub_device *asd, return 0; } -int atomisp_css_start(struct atomisp_sub_device *asd, - enum ia_css_pipe_id pipe_id, bool in_reset) +int atomisp_css_start(struct atomisp_sub_device *asd) { struct atomisp_device *isp = asd->isp; bool sp_is_started = false; int ret = 0, i = 0; - if (in_reset) { - ret = atomisp_css_update_stream(asd); - if (ret) - return ret; + if (!sh_css_hrt_system_is_idle()) + dev_err(isp->dev, "CSS HW not idle before starting SP\n"); - /* Invalidate caches. FIXME: should flush only necessary buffers */ - wbinvd(); + if (ia_css_start_sp()) { + dev_err(isp->dev, "start sp error.\n"); + ret = -EINVAL; + goto start_err; } - /* - * For dual steam case, it is possible that: - * 1: for this stream, it is at the stage that: - * - after set_fmt is called - * - before stream on is called - * 2: for the other stream, the stream off is called which css reset - * has been done. - * - * Thus the stream created in set_fmt get destroyed and need to be - * recreated in the next stream on. - */ - if (!asd->stream_prepared) { - ret = atomisp_create_pipes_stream(asd); - if (ret) - return ret; - } - /* - * SP can only be started one time - * if atomisp_subdev_streaming_count() tell there already has some - * subdev at streamming, then SP should already be started previously, - * so need to skip start sp procedure - */ - if (atomisp_streaming_count(isp)) { - dev_dbg(isp->dev, "skip start sp\n"); - } else { - if (!sh_css_hrt_system_is_idle()) - dev_err(isp->dev, "CSS HW not idle before starting SP\n"); - if (ia_css_start_sp()) { - dev_err(isp->dev, "start sp error.\n"); - ret = -EINVAL; - goto start_err; - } else { - sp_is_started = true; - } - } + sp_is_started = true; for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) { if (asd->stream_env[i].stream) { @@ -1066,16 +1019,15 @@ int atomisp_css_start(struct atomisp_sub_device *asd, return 0; start_err: - atomisp_destroy_pipes_stream_force(asd); - - /* css 2.0 API limitation: ia_css_stop_sp() could be only called after - * destroy all pipes - */ /* - * SP can not be stop if other streams are in use + * CSS 2.0 API limitation: ia_css_stop_sp() can only be called after + * destroying all pipes. */ - if ((atomisp_streaming_count(isp) == 0) && sp_is_started) + if (sp_is_started) { + atomisp_destroy_pipes_stream(asd); ia_css_stop_sp(); + atomisp_create_pipes_stream(asd); + } return ret; } @@ -1340,8 +1292,7 @@ void atomisp_css_free_stat_buffers(struct atomisp_sub_device *asd) } int atomisp_css_get_grid_info(struct atomisp_sub_device *asd, - enum ia_css_pipe_id pipe_id, - int source_pad) + enum ia_css_pipe_id pipe_id) { struct ia_css_pipe_info p_info; struct ia_css_grid_info old_info; @@ -1624,29 +1575,6 @@ int atomisp_css_set_default_isys_config(struct atomisp_sub_device *asd, return 0; } -int atomisp_css_isys_two_stream_cfg(struct atomisp_sub_device *asd, - enum atomisp_input_stream_id stream_id, - enum atomisp_input_format input_format) -{ - struct ia_css_stream_config *s_config = - &asd->stream_env[stream_id].stream_config; - - s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].input_res.width = - s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].input_res.width; - - s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].input_res.height = - s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].input_res.height / 2; - - s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].linked_isys_stream_id - = IA_CSS_STREAM_ISYS_STREAM_0; - s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].format = - ATOMISP_INPUT_FORMAT_USER_DEF1; - s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].format = - ATOMISP_INPUT_FORMAT_USER_DEF2; - s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].valid = true; - return 0; -} - void atomisp_css_isys_two_stream_cfg_update_stream1( struct atomisp_sub_device *asd, enum atomisp_input_stream_id stream_id, @@ -1832,49 +1760,6 @@ void atomisp_css_preview_enable_online(struct atomisp_sub_device *asd, } } -void atomisp_css_video_enable_online(struct atomisp_sub_device *asd, - bool enable) -{ - struct atomisp_stream_env *stream_env = - &asd->stream_env[ATOMISP_INPUT_STREAM_VIDEO]; - int i; - - if (stream_env->stream_config.online != enable) { - stream_env->stream_config.online = enable; - for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++) - stream_env->update_pipe[i] = true; - } -} - -void atomisp_css_enable_continuous(struct atomisp_sub_device *asd, - bool enable) -{ - struct atomisp_stream_env *stream_env = - &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]; - int i; - - if (stream_env->stream_config.continuous != !!enable) { - stream_env->stream_config.continuous = !!enable; - stream_env->stream_config.pack_raw_pixels = true; - for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++) - stream_env->update_pipe[i] = true; - } -} - -void atomisp_css_enable_cvf(struct atomisp_sub_device *asd, - bool enable) -{ - struct atomisp_stream_env *stream_env = - &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]; - int i; - - if (stream_env->stream_config.disable_cont_viewfinder != !enable) { - stream_env->stream_config.disable_cont_viewfinder = !enable; - for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++) - stream_env->update_pipe[i] = true; - } -} - int atomisp_css_input_configure_port( struct atomisp_sub_device *asd, enum mipi_port_id port, @@ -1919,23 +1804,20 @@ int atomisp_css_input_configure_port( return 0; } -void atomisp_css_stop(struct atomisp_sub_device *asd, - enum ia_css_pipe_id pipe_id, bool in_reset) +void atomisp_css_stop(struct atomisp_sub_device *asd, bool in_reset) { - struct atomisp_device *isp = asd->isp; unsigned long irqflags; unsigned int i; - /* if is called in atomisp_reset(), force destroy streams and pipes */ - atomisp_destroy_pipes_stream_force(asd); + /* + * CSS 2.0 API limitation: ia_css_stop_sp() can only be called after + * destroying all pipes. + */ + atomisp_destroy_pipes_stream(asd); atomisp_init_raw_buffer_bitmap(asd); - /* - * SP can not be stop if other streams are in use - */ - if (atomisp_streaming_count(isp) == 0) - ia_css_stop_sp(); + ia_css_stop_sp(); if (!in_reset) { struct atomisp_stream_env *stream_env; @@ -1970,10 +1852,7 @@ void atomisp_css_stop(struct atomisp_sub_device *asd, list_splice_init(&asd->metadata_ready[i], &asd->metadata[i]); } - atomisp_flush_params_queue(&asd->video_out_capture); - atomisp_flush_params_queue(&asd->video_out_vf); - atomisp_flush_params_queue(&asd->video_out_preview); - atomisp_flush_params_queue(&asd->video_out_video_capture); + atomisp_flush_params_queue(&asd->video_out); atomisp_free_css_parameters(&asd->params.css_param); memset(&asd->params.css_param, 0, sizeof(asd->params.css_param)); } @@ -2424,54 +2303,33 @@ static int __get_frame_info(struct atomisp_sub_device *asd, return 0; get_info_err: - atomisp_destroy_pipes_stream_force(asd); + atomisp_destroy_pipes_stream(asd); return -EINVAL; } -static unsigned int atomisp_get_pipe_index(struct atomisp_sub_device *asd, - uint16_t source_pad) +static unsigned int atomisp_get_pipe_index(struct atomisp_sub_device *asd) { - struct atomisp_device *isp = asd->isp; - - switch (source_pad) { - case ATOMISP_SUBDEV_PAD_SOURCE_VIDEO: - if (asd->copy_mode) - return IA_CSS_PIPE_ID_COPY; - if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO - || asd->vfpp->val == ATOMISP_VFPP_DISABLE_SCALER) - return IA_CSS_PIPE_ID_VIDEO; - - return IA_CSS_PIPE_ID_CAPTURE; - case ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE: - if (asd->copy_mode) - return IA_CSS_PIPE_ID_COPY; + if (asd->copy_mode) + return IA_CSS_PIPE_ID_COPY; + switch (asd->run_mode->val) { + case ATOMISP_RUN_MODE_VIDEO: + return IA_CSS_PIPE_ID_VIDEO; + case ATOMISP_RUN_MODE_STILL_CAPTURE: return IA_CSS_PIPE_ID_CAPTURE; - case ATOMISP_SUBDEV_PAD_SOURCE_VF: - if (!atomisp_is_mbuscode_raw(asd->fmt[asd->capture_pad].fmt.code)) { - return IA_CSS_PIPE_ID_CAPTURE; - } - fallthrough; - case ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW: - if (asd->copy_mode) - return IA_CSS_PIPE_ID_COPY; - if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO) - return IA_CSS_PIPE_ID_VIDEO; - + case ATOMISP_RUN_MODE_PREVIEW: return IA_CSS_PIPE_ID_PREVIEW; } - dev_warn(isp->dev, - "invalid source pad:%d, return default preview pipe index.\n", - source_pad); + + dev_warn(asd->isp->dev, "cannot determine pipe-index return default preview pipe\n"); return IA_CSS_PIPE_ID_PREVIEW; } int atomisp_get_css_frame_info(struct atomisp_sub_device *asd, - u16 source_pad, struct ia_css_frame_info *frame_info) { struct ia_css_pipe_info info; - int pipe_index = atomisp_get_pipe_index(asd, source_pad); + int pipe_index = atomisp_get_pipe_index(asd); int stream_index; struct atomisp_device *isp = asd->isp; @@ -2485,34 +2343,8 @@ int atomisp_get_css_frame_info(struct atomisp_sub_device *asd, return -EINVAL; } - switch (source_pad) { - case ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE: - *frame_info = info.output_info[0]; - break; - case ATOMISP_SUBDEV_PAD_SOURCE_VIDEO: - *frame_info = info.output_info[ATOMISP_CSS_OUTPUT_DEFAULT_INDEX]; - break; - case ATOMISP_SUBDEV_PAD_SOURCE_VF: - if (stream_index == ATOMISP_INPUT_STREAM_POSTVIEW) - *frame_info = info.output_info[0]; - else - *frame_info = info.vf_output_info[0]; - break; - case ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW: - if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO && - (pipe_index == IA_CSS_PIPE_ID_VIDEO || - pipe_index == IA_CSS_PIPE_ID_YUVPP)) - *frame_info = info.vf_output_info[ATOMISP_CSS_OUTPUT_DEFAULT_INDEX]; - else - *frame_info = - info.output_info[ATOMISP_CSS_OUTPUT_DEFAULT_INDEX]; - - break; - default: - frame_info = NULL; - break; - } - return frame_info ? 0 : -EINVAL; + *frame_info = info.output_info[0]; + return 0; } int atomisp_css_copy_configure_output(struct atomisp_sub_device *asd, @@ -2530,39 +2362,6 @@ int atomisp_css_copy_configure_output(struct atomisp_sub_device *asd, return 0; } -int atomisp_css_yuvpp_configure_output(struct atomisp_sub_device *asd, - unsigned int stream_index, - unsigned int width, unsigned int height, - unsigned int padded_width, - enum ia_css_frame_format format) -{ - asd->stream_env[stream_index].pipe_configs[IA_CSS_PIPE_ID_YUVPP]. - default_capture_config.mode = - IA_CSS_CAPTURE_MODE_RAW; - - __configure_output(asd, stream_index, width, height, padded_width, - format, IA_CSS_PIPE_ID_YUVPP); - return 0; -} - -int atomisp_css_yuvpp_get_output_frame_info( - struct atomisp_sub_device *asd, - unsigned int stream_index, - struct ia_css_frame_info *info) -{ - return __get_frame_info(asd, stream_index, info, - ATOMISP_CSS_OUTPUT_FRAME, IA_CSS_PIPE_ID_YUVPP); -} - -int atomisp_css_yuvpp_get_viewfinder_frame_info( - struct atomisp_sub_device *asd, - unsigned int stream_index, - struct ia_css_frame_info *info) -{ - return __get_frame_info(asd, stream_index, info, - ATOMISP_CSS_VF_FRAME, IA_CSS_PIPE_ID_YUVPP); -} - int atomisp_css_preview_configure_output(struct atomisp_sub_device *asd, unsigned int width, unsigned int height, unsigned int min_width, @@ -3271,7 +3070,7 @@ int atomisp_css_get_dis_stat(struct atomisp_sub_device *asd, return -EINVAL; /* isp needs to be streaming to get DIS statistics */ - if (asd->streaming != ATOMISP_DEVICE_STREAMING_ENABLED) + if (!asd->streaming) return -EINVAL; if (atomisp_compare_dvs_grid(asd, &stats->dvs2_stat.grid_info) != 0) @@ -3400,7 +3199,7 @@ static bool atomisp_css_isr_get_stream_id(struct ia_css_pipe *css_pipe, struct atomisp_stream_env *stream_env; int i, j; - if (isp->asd.streaming == ATOMISP_DEVICE_STREAMING_DISABLED) + if (!isp->asd.streaming) return false; for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) { diff --git a/drivers/staging/media/atomisp/pci/atomisp_compat_ioctl32.h b/drivers/staging/media/atomisp/pci/atomisp_compat_ioctl32.h index 33821b51d90e8c0c537c73709123a8752e06feb2..762520ed87a5a4e6723d357d4b31b454978c4e6b 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_compat_ioctl32.h +++ b/drivers/staging/media/atomisp/pci/atomisp_compat_ioctl32.h @@ -67,26 +67,6 @@ struct atomisp_3a_statistics32 { u32 isp_config_id; }; -struct atomisp_metadata_with_type32 { - /* to specify which type of metadata to get */ - enum atomisp_metadata_type type; - compat_uptr_t data; - u32 width; - u32 height; - u32 stride; /* in bytes */ - u32 exp_id; /* exposure ID */ - compat_uptr_t effective_width; -}; - -struct atomisp_metadata32 { - compat_uptr_t data; - u32 width; - u32 height; - u32 stride; - u32 exp_id; - compat_uptr_t effective_width; -}; - struct atomisp_morph_table32 { unsigned int enabled; unsigned int height; @@ -134,18 +114,6 @@ struct atomisp_overlay32 { unsigned int overlay_start_y; }; -struct atomisp_calibration_group32 { - unsigned int size; - unsigned int type; - compat_uptr_t calb_grp_values; -}; - -struct v4l2_private_int_data32 { - __u32 size; - compat_uptr_t data; - __u32 reserved[2]; -}; - struct atomisp_shading_table32 { __u32 enable; __u32 sensor_width; @@ -249,11 +217,6 @@ struct atomisp_dvs_6axis_config32 { compat_uptr_t ycoords_uv; }; -struct atomisp_sensor_ae_bracketing_lut32 { - compat_uptr_t lut; - unsigned int lut_size; -}; - #define ATOMISP_IOC_G_HISTOGRAM32 \ _IOWR('v', BASE_VIDIOC_PRIVATE + 3, struct atomisp_histogram32) #define ATOMISP_IOC_S_HISTOGRAM32 \ @@ -283,28 +246,10 @@ struct atomisp_sensor_ae_bracketing_lut32 { #define ATOMISP_IOC_S_ISP_OVERLAY32 \ _IOW('v', BASE_VIDIOC_PRIVATE + 18, struct atomisp_overlay32) -#define ATOMISP_IOC_G_SENSOR_CALIBRATION_GROUP32 \ - _IOWR('v', BASE_VIDIOC_PRIVATE + 22, struct atomisp_calibration_group32) - -#define ATOMISP_IOC_G_SENSOR_PRIV_INT_DATA32 \ - _IOWR('v', BASE_VIDIOC_PRIVATE + 26, struct v4l2_private_int_data32) - #define ATOMISP_IOC_S_ISP_SHD_TAB32 \ _IOWR('v', BASE_VIDIOC_PRIVATE + 27, struct atomisp_shading_table32) -#define ATOMISP_IOC_G_MOTOR_PRIV_INT_DATA32 \ - _IOWR('v', BASE_VIDIOC_PRIVATE + 29, struct v4l2_private_int_data32) - #define ATOMISP_IOC_S_PARAMETERS32 \ _IOW('v', BASE_VIDIOC_PRIVATE + 32, struct atomisp_parameters32) -#define ATOMISP_IOC_G_METADATA32 \ - _IOWR('v', BASE_VIDIOC_PRIVATE + 34, struct atomisp_metadata32) - -#define ATOMISP_IOC_G_METADATA_BY_TYPE32 \ - _IOWR('v', BASE_VIDIOC_PRIVATE + 34, struct atomisp_metadata_with_type32) - -#define ATOMISP_IOC_S_SENSOR_AE_BRACKETING_LUT32 \ - _IOW('v', BASE_VIDIOC_PRIVATE + 43, struct atomisp_sensor_ae_bracketing_lut32) - #endif /* __ATOMISP_COMPAT_IOCTL32_H__ */ diff --git a/drivers/staging/media/atomisp/pci/atomisp_csi2.c b/drivers/staging/media/atomisp/pci/atomisp_csi2.c index b00bc0b7aaad731e9d232167e7277756c87b1abf..abf55a86f79578d76b842db4312f861786dbd9e4 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_csi2.c +++ b/drivers/staging/media/atomisp/pci/atomisp_csi2.c @@ -322,15 +322,11 @@ static void atomisp_csi2_configure_isp2401(struct atomisp_sub_device *asd) struct v4l2_control ctrl; struct atomisp_device *isp = asd->isp; - struct camera_mipi_info *mipi_info; int mipi_freq = 0; enum atomisp_camera_port port; - int n; - mipi_info = atomisp_to_sensor_mipi_info( - isp->inputs[asd->input_curr].camera); - port = mipi_info->port; + port = isp->inputs[asd->input_curr].port; ctrl.id = V4L2_CID_LINK_FREQ; if (v4l2_g_ctrl @@ -375,6 +371,10 @@ int atomisp_mipi_csi2_init(struct atomisp_device *isp) unsigned int i; int ret; + ret = atomisp_csi2_bridge_init(isp); + if (ret < 0) + return ret; + for (i = 0; i < ATOMISP_CAMERA_NR_PORTS; i++) { csi2_port = &isp->csi2_port[i]; csi2_port->isp = isp; diff --git a/drivers/staging/media/atomisp/pci/atomisp_csi2.h b/drivers/staging/media/atomisp/pci/atomisp_csi2.h index b245b2f5ce99d4f8c4d19d38a04b8212758ddfe7..16ddb3ab29630e13dc064813a4d3586a935a7f6d 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_csi2.h +++ b/drivers/staging/media/atomisp/pci/atomisp_csi2.h @@ -18,17 +18,107 @@ #ifndef __ATOMISP_CSI2_H__ #define __ATOMISP_CSI2_H__ +#include +#include + #include #include +#include "../../include/linux/atomisp.h" + #define CSI2_PAD_SINK 0 #define CSI2_PAD_SOURCE 1 #define CSI2_PADS_NUM 2 -struct atomisp_device; +#define CSI2_MAX_LANES 4 +#define CSI2_MAX_LINK_FREQS 3 + +#define CSI2_MAX_ACPI_GPIOS 2u + +struct acpi_device; struct v4l2_device; + +struct atomisp_device; struct atomisp_sub_device; +struct atomisp_csi2_acpi_gpio_map { + struct acpi_gpio_params params[CSI2_MAX_ACPI_GPIOS]; + struct acpi_gpio_mapping mapping[CSI2_MAX_ACPI_GPIOS + 1]; +}; + +struct atomisp_csi2_acpi_gpio_parsing_data { + struct acpi_device *adev; + struct atomisp_csi2_acpi_gpio_map *map; + u32 settings[CSI2_MAX_ACPI_GPIOS]; + unsigned int settings_count; + unsigned int res_count; + unsigned int map_count; +}; + +enum atomisp_csi2_sensor_swnodes { + SWNODE_SENSOR, + SWNODE_SENSOR_PORT, + SWNODE_SENSOR_ENDPOINT, + SWNODE_CSI2_PORT, + SWNODE_CSI2_ENDPOINT, + SWNODE_COUNT +}; + +struct atomisp_csi2_property_names { + char clock_frequency[16]; + char rotation[9]; + char bus_type[9]; + char data_lanes[11]; + char remote_endpoint[16]; + char link_frequencies[17]; +}; + +struct atomisp_csi2_node_names { + char port[7]; + char endpoint[11]; + char remote_port[7]; +}; + +struct atomisp_csi2_sensor_config { + const char *hid; + int lanes; + int nr_link_freqs; + u64 link_freqs[CSI2_MAX_LINK_FREQS]; +}; + +struct atomisp_csi2_sensor { + /* Append port in "-%u" format as suffix of HID */ + char name[ACPI_ID_LEN + 4]; + struct acpi_device *adev; + int port; + int lanes; + + /* SWNODE_COUNT + 1 for terminating NULL */ + const struct software_node *group[SWNODE_COUNT + 1]; + struct software_node swnodes[SWNODE_COUNT]; + struct atomisp_csi2_node_names node_names; + struct atomisp_csi2_property_names prop_names; + /* "clock-frequency", "rotation" + terminating entry */ + struct property_entry dev_properties[3]; + /* "bus-type", "data-lanes", "remote-endpoint" + "link-freq" + terminating entry */ + struct property_entry ep_properties[5]; + /* "data-lanes", "remote-endpoint" + terminating entry */ + struct property_entry csi2_properties[3]; + struct software_node_ref_args local_ref[1]; + struct software_node_ref_args remote_ref[1]; + struct software_node_ref_args vcm_ref[1]; + /* GPIO mappings storage */ + struct atomisp_csi2_acpi_gpio_map gpio_map; +}; + +struct atomisp_csi2_bridge { + struct software_node csi2_node; + char csi2_node_name[14]; + u32 data_lanes[CSI2_MAX_LANES]; + unsigned int n_sensors; + struct atomisp_csi2_sensor sensors[ATOMISP_CAMERA_NR_PORTS]; +}; + struct atomisp_mipi_csi2_device { struct v4l2_subdev subdev; struct media_pad pads[CSI2_PADS_NUM]; @@ -48,6 +138,8 @@ void atomisp_mipi_csi2_unregister_entities( struct atomisp_mipi_csi2_device *csi2); int atomisp_mipi_csi2_register_entities(struct atomisp_mipi_csi2_device *csi2, struct v4l2_device *vdev); +int atomisp_csi2_bridge_init(struct atomisp_device *isp); +int atomisp_csi2_bridge_parse_firmware(struct atomisp_device *isp); void atomisp_csi2_configure(struct atomisp_sub_device *asd); diff --git a/drivers/staging/media/atomisp/pci/atomisp_csi2_bridge.c b/drivers/staging/media/atomisp/pci/atomisp_csi2_bridge.c new file mode 100644 index 0000000000000000000000000000000000000000..0d12ba78d9c193d6ed9b40fca735df8bb485927a --- /dev/null +++ b/drivers/staging/media/atomisp/pci/atomisp_csi2_bridge.c @@ -0,0 +1,874 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Code to build software firmware node graph for atomisp2 connected sensors + * from ACPI tables. + * + * Copyright (C) 2023 Hans de Goede + * + * Based on drivers/media/pci/intel/ipu3/cio2-bridge.c written by: + * Dan Scally + */ + +#include +#include +#include +#include +#include +#include + +#include "atomisp_cmd.h" +#include "atomisp_csi2.h" +#include "atomisp_internal.h" + +#define NODE_SENSOR(_HID, _PROPS) \ + ((const struct software_node) { \ + .name = _HID, \ + .properties = _PROPS, \ + }) + +#define NODE_PORT(_PORT, _SENSOR_NODE) \ + ((const struct software_node) { \ + .name = _PORT, \ + .parent = _SENSOR_NODE, \ + }) + +#define NODE_ENDPOINT(_EP, _PORT, _PROPS) \ + ((const struct software_node) { \ + .name = _EP, \ + .parent = _PORT, \ + .properties = _PROPS, \ + }) + +#define PMC_CLK_RATE_19_2MHZ 19200000 + +/* + * 79234640-9e10-4fea-a5c1-b5aa8b19756f + * This _DSM GUID returns information about the GPIO lines mapped to a sensor. + * Function number 1 returns a count of the GPIO lines that are mapped. + * Subsequent functions return 32 bit ints encoding information about the GPIO. + */ +static const guid_t intel_sensor_gpio_info_guid = + GUID_INIT(0x79234640, 0x9e10, 0x4fea, + 0xa5, 0xc1, 0xb5, 0xaa, 0x8b, 0x19, 0x75, 0x6f); + +#define INTEL_GPIO_DSM_TYPE_SHIFT 0 +#define INTEL_GPIO_DSM_TYPE_MASK GENMASK(7, 0) +#define INTEL_GPIO_DSM_PIN_SHIFT 8 +#define INTEL_GPIO_DSM_PIN_MASK GENMASK(15, 8) +#define INTEL_GPIO_DSM_SENSOR_ON_VAL_SHIFT 24 +#define INTEL_GPIO_DSM_SENSOR_ON_VAL_MASK GENMASK(31, 24) + +#define INTEL_GPIO_DSM_TYPE(x) \ + (((x) & INTEL_GPIO_DSM_TYPE_MASK) >> INTEL_GPIO_DSM_TYPE_SHIFT) +#define INTEL_GPIO_DSM_PIN(x) \ + (((x) & INTEL_GPIO_DSM_PIN_MASK) >> INTEL_GPIO_DSM_PIN_SHIFT) +#define INTEL_GPIO_DSM_SENSOR_ON_VAL(x) \ + (((x) & INTEL_GPIO_DSM_SENSOR_ON_VAL_MASK) >> INTEL_GPIO_DSM_SENSOR_ON_VAL_SHIFT) + +/* + * 822ace8f-2814-4174-a56b-5f029fe079ee + * This _DSM GUID returns a string from the sensor device, which acts as a + * module identifier. + */ +static const guid_t intel_sensor_module_guid = + GUID_INIT(0x822ace8f, 0x2814, 0x4174, + 0xa5, 0x6b, 0x5f, 0x02, 0x9f, 0xe0, 0x79, 0xee); + +/* + * dc2f6c4f-045b-4f1d-97b9-882a6860a4be + * This _DSM GUID returns a package with n*2 strings, with each set of 2 strings + * forming a key, value pair for settings like e.g. "CsiLanes" = "1". + */ +static const guid_t atomisp_dsm_guid = + GUID_INIT(0xdc2f6c4f, 0x045b, 0x4f1d, + 0x97, 0xb9, 0x88, 0x2a, 0x68, 0x60, 0xa4, 0xbe); + +/* + * Extend this array with ACPI Hardware IDs of sensors known to be working + * plus the default number of links + link-frequencies. + * + * Do not add an entry for a sensor that is not actually supported, + * or which have not yet been converted to work without atomisp_gmin + * power-management and with v4l2-async probing. + */ +static const struct atomisp_csi2_sensor_config supported_sensors[] = { + /* GalaxyCore GC0310 */ + { "INT0310", 1 }, + /* Omnivision OV2680 */ + { "OVTI2680", 1 }, +}; + +/* + * gmin_cfg parsing code. This is a cleaned up version of the gmin_cfg parsing + * code from atomisp_gmin_platform.c. + * Once all sensors are moved to v4l2-async probing atomisp_gmin_platform.c can + * be removed and the duplication of this code goes away. + */ +struct gmin_cfg_var { + const char *acpi_dev_name; + const char *key; + const char *val; +}; + +static struct gmin_cfg_var lenovo_ideapad_miix_310_vars[] = { + /* _DSM contains the wrong CsiPort! */ + { "OVTI2680:01", "CsiPort", "0" }, + {} +}; + +static const struct dmi_system_id gmin_cfg_dmi_overrides[] = { + { + /* Lenovo Ideapad Miix 310 */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_VERSION, "MIIX 310-10"), + }, + .driver_data = lenovo_ideapad_miix_310_vars, + }, + {} +}; + +static char *gmin_cfg_get_dsm(struct acpi_device *adev, const char *key) +{ + union acpi_object *obj, *key_el, *val_el; + char *val = NULL; + int i; + + obj = acpi_evaluate_dsm_typed(adev->handle, &atomisp_dsm_guid, 0, 0, + NULL, ACPI_TYPE_PACKAGE); + if (!obj) + return NULL; + + for (i = 0; i < obj->package.count - 1; i += 2) { + key_el = &obj->package.elements[i + 0]; + val_el = &obj->package.elements[i + 1]; + + if (key_el->type != ACPI_TYPE_STRING || val_el->type != ACPI_TYPE_STRING) + break; + + if (!strcmp(key_el->string.pointer, key)) { + val = kstrdup(val_el->string.pointer, GFP_KERNEL); + if (!val) + break; + + acpi_handle_info(adev->handle, "Using DSM entry %s=%s\n", key, val); + break; + } + } + + ACPI_FREE(obj); + return val; +} + +static char *gmin_cfg_get_dmi_override(struct acpi_device *adev, const char *key) +{ + const struct dmi_system_id *id; + struct gmin_cfg_var *gv; + + id = dmi_first_match(gmin_cfg_dmi_overrides); + if (!id) + return NULL; + + for (gv = id->driver_data; gv->acpi_dev_name; gv++) { + if (strcmp(gv->acpi_dev_name, acpi_dev_name(adev))) + continue; + + if (strcmp(key, gv->key)) + continue; + + acpi_handle_info(adev->handle, "Using DMI entry %s=%s\n", key, gv->val); + return kstrdup(gv->val, GFP_KERNEL); + } + + return NULL; +} + +static char *gmin_cfg_get(struct acpi_device *adev, const char *key) +{ + char *val; + + val = gmin_cfg_get_dmi_override(adev, key); + if (val) + return val; + + return gmin_cfg_get_dsm(adev, key); +} + +static int gmin_cfg_get_int(struct acpi_device *adev, const char *key, int default_val) +{ + char *str_val; + long int_val; + int ret; + + str_val = gmin_cfg_get(adev, key); + if (!str_val) + goto out_use_default; + + ret = kstrtoul(str_val, 0, &int_val); + kfree(str_val); + if (ret) + goto out_use_default; + + return int_val; + +out_use_default: + acpi_handle_info(adev->handle, "Using default %s=%d\n", key, default_val); + return default_val; +} + +static int atomisp_csi2_get_pmc_clk_nr_from_acpi_pr0(struct acpi_device *adev) +{ + /* ACPI_PATH_SEGMENT_LENGTH is guaranteed to be big enough for name + 0 term. */ + char name[ACPI_PATH_SEGMENT_LENGTH]; + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; + struct acpi_buffer b_name = { sizeof(name), name }; + union acpi_object *package, *element; + int i, ret = -ENOENT; + acpi_handle rhandle; + acpi_status status; + u8 clock_num; + + status = acpi_evaluate_object_typed(adev->handle, "_PR0", NULL, &buffer, ACPI_TYPE_PACKAGE); + if (ACPI_FAILURE(status)) + return -ENOENT; + + package = buffer.pointer; + for (i = 0; i < package->package.count; i++) { + element = &package->package.elements[i]; + + if (element->type != ACPI_TYPE_LOCAL_REFERENCE) + continue; + + rhandle = element->reference.handle; + if (!rhandle) + continue; + + acpi_get_name(rhandle, ACPI_SINGLE_NAME, &b_name); + + if (str_has_prefix(name, "CLK") && !kstrtou8(&name[3], 10, &clock_num) && + clock_num <= 4) { + ret = clock_num; + break; + } + } + + ACPI_FREE(buffer.pointer); + + if (ret < 0) + acpi_handle_warn(adev->handle, "Could not find PMC clk in _PR0\n"); + + return ret; +} + +static int atomisp_csi2_set_pmc_clk_freq(struct acpi_device *adev, int clock_num) +{ + struct clk *clk; + char name[14]; + int ret; + + if (clock_num < 0) + return 0; + + snprintf(name, sizeof(name), "pmc_plt_clk_%d", clock_num); + + clk = clk_get(NULL, name); + if (IS_ERR(clk)) { + ret = PTR_ERR(clk); + acpi_handle_err(adev->handle, "Error getting clk %s:%d\n", name, ret); + return ret; + } + + /* + * The firmware might enable the clock at boot, to change + * the rate we must ensure the clock is disabled. + */ + ret = clk_prepare_enable(clk); + if (!ret) + clk_disable_unprepare(clk); + if (!ret) + ret = clk_set_rate(clk, PMC_CLK_RATE_19_2MHZ); + if (ret) + acpi_handle_err(adev->handle, "Error setting clk-rate for %s:%d\n", name, ret); + + clk_put(clk); + return ret; +} + +static int atomisp_csi2_get_port(struct acpi_device *adev, int clock_num) +{ + int port; + + /* + * Compare clock-number to the PMC-clock used for CsiPort 1 + * in the CHT/BYT reference designs. + */ + if (IS_ISP2401) + port = clock_num == 4 ? 1 : 0; + else + port = clock_num == 0 ? 1 : 0; + + /* Intel DSM or DMI quirk overrides _PR0 CLK derived default */ + return gmin_cfg_get_int(adev, "CsiPort", port); +} + +/* Note this always returns 1 to continue looping so that res_count is accurate */ +static int atomisp_csi2_handle_acpi_gpio_res(struct acpi_resource *ares, void *_data) +{ + struct atomisp_csi2_acpi_gpio_parsing_data *data = _data; + struct acpi_resource_gpio *agpio; + const char *name; + bool active_low; + unsigned int i; + u32 settings = 0; + u16 pin; + + if (!acpi_gpio_get_io_resource(ares, &agpio)) + return 1; /* Not a GPIO, continue the loop */ + + data->res_count++; + + pin = agpio->pin_table[0]; + for (i = 0; i < data->settings_count; i++) { + if (INTEL_GPIO_DSM_PIN(data->settings[i]) == pin) { + settings = data->settings[i]; + break; + } + } + + if (i == data->settings_count) { + acpi_handle_warn(data->adev->handle, + "Could not find DSM GPIO settings for pin %u\n", pin); + return 1; + } + + switch (INTEL_GPIO_DSM_TYPE(settings)) { + case 0: + name = "reset-gpios"; + break; + case 1: + name = "powerdown-gpios"; + break; + default: + acpi_handle_warn(data->adev->handle, "Unknown GPIO type 0x%02lx for pin %u\n", + INTEL_GPIO_DSM_TYPE(settings), pin); + return 1; + } + + /* + * Both reset and power-down need to be logical false when the sensor + * is on (sensor should not be in reset and not be powered-down). So + * when the sensor-on-value (which is the physical pin value) is high, + * then the signal is active-low. + */ + active_low = INTEL_GPIO_DSM_SENSOR_ON_VAL(settings); + + i = data->map_count; + if (i == CSI2_MAX_ACPI_GPIOS) + return 1; + + /* res_count is already incremented */ + data->map->params[i].crs_entry_index = data->res_count - 1; + data->map->params[i].active_low = active_low; + data->map->mapping[i].name = name; + data->map->mapping[i].data = &data->map->params[i]; + data->map->mapping[i].size = 1; + data->map_count++; + + acpi_handle_info(data->adev->handle, "%s crs %d %s pin %u active-%s\n", name, + data->res_count - 1, agpio->resource_source.string_ptr, + pin, active_low ? "low" : "high"); + + return 1; +} + +/* + * Helper function to create an ACPI GPIO lookup table for sensor reset and + * powerdown signals on Intel Bay Trail (BYT) and Cherry Trail (CHT) devices, + * including setting the correct polarity for the GPIO. + * + * This uses the "79234640-9e10-4fea-a5c1-b5aa8b19756f" DSM method directly + * on the sensor device's ACPI node. This is different from later Intel + * hardware which has a separate INT3472 acpi_device with this info. + * + * This function must be called before creating the sw-noded describing + * the fwnode graph endpoint. And sensor drivers used on these devices + * must return -EPROBE_DEFER when there is no endpoint description yet. + * Together this guarantees that the GPIO lookups are in place before + * the sensor driver tries to get GPIOs with gpiod_get(). + * + * Note this code uses the same DSM GUID as the int3472_gpio_guid in + * the INT3472 discrete.c code and there is some overlap, but there are + * enough differences that it is difficult to share the code. + */ +static int atomisp_csi2_add_gpio_mappings(struct atomisp_csi2_sensor *sensor, + struct acpi_device *adev) +{ + struct atomisp_csi2_acpi_gpio_parsing_data data = { }; + LIST_HEAD(resource_list); + union acpi_object *obj; + unsigned int i, j; + int ret; + + obj = acpi_evaluate_dsm_typed(adev->handle, &intel_sensor_module_guid, + 0x00, 1, NULL, ACPI_TYPE_STRING); + if (obj) { + acpi_handle_info(adev->handle, "Sensor module id: '%s'\n", obj->string.pointer); + ACPI_FREE(obj); + } + + /* + * First get the GPIO-settings count and then get count GPIO-settings + * values. Note the order of these may differ from the order in which + * the GPIOs are listed on the ACPI resources! So we first store them all + * and then enumerate the ACPI resources and match them up by pin number. + */ + obj = acpi_evaluate_dsm_typed(adev->handle, + &intel_sensor_gpio_info_guid, 0x00, 1, + NULL, ACPI_TYPE_INTEGER); + if (!obj) { + acpi_handle_err(adev->handle, "No _DSM entry for GPIO pin count\n"); + return -EIO; + } + + data.settings_count = obj->integer.value; + ACPI_FREE(obj); + + if (data.settings_count > CSI2_MAX_ACPI_GPIOS) { + acpi_handle_err(adev->handle, "Too many GPIOs %u > %u\n", data.settings_count, CSI2_MAX_ACPI_GPIOS); + return -EOVERFLOW; + } + + for (i = 0; i < data.settings_count; i++) { + /* + * i + 2 because the index of this _DSM function is 1-based + * and the first function is just a count. + */ + obj = acpi_evaluate_dsm_typed(adev->handle, + &intel_sensor_gpio_info_guid, + 0x00, i + 2, + NULL, ACPI_TYPE_INTEGER); + if (!obj) { + acpi_handle_err(adev->handle, "No _DSM entry for pin %u\n", i); + return -EIO; + } + + data.settings[i] = obj->integer.value; + ACPI_FREE(obj); + } + + /* Since we match up by pin-number the pin-numbers must be unique */ + for (i = 0; i < data.settings_count; i++) { + for (j = i + 1; j < data.settings_count; j++) { + if (INTEL_GPIO_DSM_PIN(data.settings[i]) != + INTEL_GPIO_DSM_PIN(data.settings[j])) + continue; + + acpi_handle_err(adev->handle, "Duplicate pin number %lu\n", + INTEL_GPIO_DSM_PIN(data.settings[i])); + return -EIO; + } + } + + /* Now parse the ACPI resources and build the lookup table */ + data.adev = adev; + data.map = &sensor->gpio_map; + ret = acpi_dev_get_resources(adev, &resource_list, + atomisp_csi2_handle_acpi_gpio_res, &data); + if (ret < 0) + return ret; + + acpi_dev_free_resource_list(&resource_list); + + if (data.map_count != data.settings_count || + data.res_count != data.settings_count) + acpi_handle_warn(adev->handle, "ACPI GPIO resources vs DSM GPIO-info count mismatch (dsm: %d res: %d map %d\n", + data.settings_count, data.res_count, data.map_count); + + ret = acpi_dev_add_driver_gpios(adev, data.map->mapping); + if (ret) + acpi_handle_err(adev->handle, "Error adding driver GPIOs: %d\n", ret); + + return ret; +} + +static const struct atomisp_csi2_property_names prop_names = { + .clock_frequency = "clock-frequency", + .rotation = "rotation", + .bus_type = "bus-type", + .data_lanes = "data-lanes", + .remote_endpoint = "remote-endpoint", + .link_frequencies = "link-frequencies", +}; + +static void atomisp_csi2_create_fwnode_properties(struct atomisp_csi2_sensor *sensor, + struct atomisp_csi2_bridge *bridge, + const struct atomisp_csi2_sensor_config *cfg) +{ + sensor->prop_names = prop_names; + + sensor->local_ref[0] = SOFTWARE_NODE_REFERENCE(&sensor->swnodes[SWNODE_CSI2_ENDPOINT]); + sensor->remote_ref[0] = SOFTWARE_NODE_REFERENCE(&sensor->swnodes[SWNODE_SENSOR_ENDPOINT]); + + sensor->dev_properties[0] = PROPERTY_ENTRY_U32(sensor->prop_names.clock_frequency, + PMC_CLK_RATE_19_2MHZ); + sensor->dev_properties[1] = PROPERTY_ENTRY_U32(sensor->prop_names.rotation, 0); + + sensor->ep_properties[0] = PROPERTY_ENTRY_U32(sensor->prop_names.bus_type, + V4L2_FWNODE_BUS_TYPE_CSI2_DPHY); + sensor->ep_properties[1] = PROPERTY_ENTRY_U32_ARRAY_LEN(sensor->prop_names.data_lanes, + bridge->data_lanes, + sensor->lanes); + sensor->ep_properties[2] = PROPERTY_ENTRY_REF_ARRAY(sensor->prop_names.remote_endpoint, + sensor->local_ref); + if (cfg->nr_link_freqs > 0) + sensor->ep_properties[3] = + PROPERTY_ENTRY_U64_ARRAY_LEN(sensor->prop_names.link_frequencies, + cfg->link_freqs, cfg->nr_link_freqs); + + sensor->csi2_properties[0] = PROPERTY_ENTRY_U32_ARRAY_LEN(sensor->prop_names.data_lanes, + bridge->data_lanes, + sensor->lanes); + sensor->csi2_properties[1] = PROPERTY_ENTRY_REF_ARRAY(sensor->prop_names.remote_endpoint, + sensor->remote_ref); +} + +static void atomisp_csi2_init_swnode_names(struct atomisp_csi2_sensor *sensor) +{ + snprintf(sensor->node_names.remote_port, + sizeof(sensor->node_names.remote_port), + SWNODE_GRAPH_PORT_NAME_FMT, sensor->port); + snprintf(sensor->node_names.port, + sizeof(sensor->node_names.port), + SWNODE_GRAPH_PORT_NAME_FMT, 0); /* Always port 0 */ + snprintf(sensor->node_names.endpoint, + sizeof(sensor->node_names.endpoint), + SWNODE_GRAPH_ENDPOINT_NAME_FMT, 0); /* And endpoint 0 */ +} + +static void atomisp_csi2_init_swnode_group(struct atomisp_csi2_sensor *sensor) +{ + struct software_node *nodes = sensor->swnodes; + + sensor->group[SWNODE_SENSOR] = &nodes[SWNODE_SENSOR]; + sensor->group[SWNODE_SENSOR_PORT] = &nodes[SWNODE_SENSOR_PORT]; + sensor->group[SWNODE_SENSOR_ENDPOINT] = &nodes[SWNODE_SENSOR_ENDPOINT]; + sensor->group[SWNODE_CSI2_PORT] = &nodes[SWNODE_CSI2_PORT]; + sensor->group[SWNODE_CSI2_ENDPOINT] = &nodes[SWNODE_CSI2_ENDPOINT]; +} + +static void atomisp_csi2_create_connection_swnodes(struct atomisp_csi2_bridge *bridge, + struct atomisp_csi2_sensor *sensor) +{ + struct software_node *nodes = sensor->swnodes; + + atomisp_csi2_init_swnode_names(sensor); + + nodes[SWNODE_SENSOR] = NODE_SENSOR(sensor->name, + sensor->dev_properties); + nodes[SWNODE_SENSOR_PORT] = NODE_PORT(sensor->node_names.port, + &nodes[SWNODE_SENSOR]); + nodes[SWNODE_SENSOR_ENDPOINT] = NODE_ENDPOINT(sensor->node_names.endpoint, + &nodes[SWNODE_SENSOR_PORT], + sensor->ep_properties); + nodes[SWNODE_CSI2_PORT] = NODE_PORT(sensor->node_names.remote_port, + &bridge->csi2_node); + nodes[SWNODE_CSI2_ENDPOINT] = NODE_ENDPOINT(sensor->node_names.endpoint, + &nodes[SWNODE_CSI2_PORT], + sensor->csi2_properties); + + atomisp_csi2_init_swnode_group(sensor); +} + +static void atomisp_csi2_unregister_sensors(struct atomisp_csi2_bridge *bridge) +{ + struct atomisp_csi2_sensor *sensor; + unsigned int i; + + for (i = 0; i < bridge->n_sensors; i++) { + sensor = &bridge->sensors[i]; + software_node_unregister_node_group(sensor->group); + acpi_dev_remove_driver_gpios(sensor->adev); + acpi_dev_put(sensor->adev); + } +} + +static int atomisp_csi2_connect_sensor(const struct atomisp_csi2_sensor_config *cfg, + struct atomisp_csi2_bridge *bridge, + struct atomisp_device *isp) +{ + struct fwnode_handle *fwnode, *primary; + struct atomisp_csi2_sensor *sensor; + struct acpi_device *adev; + int ret, clock_num; + + for_each_acpi_dev_match(adev, cfg->hid, NULL, -1) { + if (!adev->status.enabled) + continue; + + if (bridge->n_sensors >= ATOMISP_CAMERA_NR_PORTS) { + dev_err(isp->dev, "Exceeded available CSI2 ports\n"); + ret = -EOVERFLOW; + goto err_put_adev; + } + + sensor = &bridge->sensors[bridge->n_sensors]; + + /* + * ACPI takes care of turning the PMC clock on and off, but on BYT + * the clock defaults to 25 MHz instead of the expected 19.2 MHz. + * Get the PMC-clock number from ACPI _PR0 method and set it to 19.2 MHz. + * The PMC-clock number is also used to determine the default CSI port. + */ + clock_num = atomisp_csi2_get_pmc_clk_nr_from_acpi_pr0(adev); + + ret = atomisp_csi2_set_pmc_clk_freq(adev, clock_num); + if (ret) + goto err_put_adev; + + sensor->port = atomisp_csi2_get_port(adev, clock_num); + if (sensor->port >= ATOMISP_CAMERA_NR_PORTS) { + acpi_handle_err(adev->handle, "Invalid port: %d\n", sensor->port); + ret = -EINVAL; + goto err_put_adev; + } + + sensor->lanes = gmin_cfg_get_int(adev, "CsiLanes", cfg->lanes); + if (sensor->lanes > CSI2_MAX_LANES) { + acpi_handle_err(adev->handle, "Invalid number of lanes: %d\n", sensor->lanes); + ret = -EINVAL; + goto err_put_adev; + } + + ret = atomisp_csi2_add_gpio_mappings(sensor, adev); + if (ret) + goto err_put_adev; + + snprintf(sensor->name, sizeof(sensor->name), "%s-%u", + cfg->hid, sensor->port); + + atomisp_csi2_create_fwnode_properties(sensor, bridge, cfg); + atomisp_csi2_create_connection_swnodes(bridge, sensor); + + ret = software_node_register_node_group(sensor->group); + if (ret) + goto err_remove_mappings; + + fwnode = software_node_fwnode(&sensor->swnodes[SWNODE_SENSOR]); + if (!fwnode) { + ret = -ENODEV; + goto err_free_swnodes; + } + + sensor->adev = acpi_dev_get(adev); + + primary = acpi_fwnode_handle(adev); + primary->secondary = fwnode; + + bridge->n_sensors++; + } + + return 0; + +err_free_swnodes: + software_node_unregister_node_group(sensor->group); +err_remove_mappings: + acpi_dev_remove_driver_gpios(adev); +err_put_adev: + acpi_dev_put(adev); + return ret; +} + +static int atomisp_csi2_connect_sensors(struct atomisp_csi2_bridge *bridge, + struct atomisp_device *isp) +{ + unsigned int i; + int ret; + + for (i = 0; i < ARRAY_SIZE(supported_sensors); i++) { + const struct atomisp_csi2_sensor_config *cfg = &supported_sensors[i]; + + ret = atomisp_csi2_connect_sensor(cfg, bridge, isp); + if (ret) + goto err_unregister_sensors; + } + + return 0; + +err_unregister_sensors: + atomisp_csi2_unregister_sensors(bridge); + return ret; +} + +int atomisp_csi2_bridge_init(struct atomisp_device *isp) +{ + struct atomisp_csi2_bridge *bridge; + struct device *dev = isp->dev; + struct fwnode_handle *fwnode; + int i, ret; + + /* + * This function is intended to run only once and then leave + * the created nodes attached even after a rmmod, therefore: + * 1. The bridge memory is leaked deliberately on success + * 2. If a secondary fwnode is already set exit early. + */ + fwnode = dev_fwnode(dev); + if (fwnode && fwnode->secondary) + return 0; + + bridge = kzalloc(sizeof(*bridge), GFP_KERNEL); + if (!bridge) + return -ENOMEM; + + strscpy(bridge->csi2_node_name, "atomisp-csi2", sizeof(bridge->csi2_node_name)); + bridge->csi2_node.name = bridge->csi2_node_name; + + ret = software_node_register(&bridge->csi2_node); + if (ret < 0) { + dev_err(dev, "Failed to register the CSI2 HID node\n"); + goto err_free_bridge; + } + + /* + * Map the lane arrangement, which is fixed for the ISP2 (meaning we + * only need one, rather than one per sensor). We include it as a + * member of the bridge struct rather than a global variable so + * that it survives if the module is unloaded along with the rest of + * the struct. + */ + for (i = 0; i < CSI2_MAX_LANES; i++) + bridge->data_lanes[i] = i + 1; + + ret = atomisp_csi2_connect_sensors(bridge, isp); + if (ret || bridge->n_sensors == 0) + goto err_unregister_csi2; + + fwnode = software_node_fwnode(&bridge->csi2_node); + if (!fwnode) { + dev_err(dev, "Error getting fwnode from csi2 software_node\n"); + ret = -ENODEV; + goto err_unregister_sensors; + } + + set_secondary_fwnode(dev, fwnode); + + return 0; + +err_unregister_sensors: + atomisp_csi2_unregister_sensors(bridge); +err_unregister_csi2: + software_node_unregister(&bridge->csi2_node); +err_free_bridge: + kfree(bridge); + + return ret; +} + +/******* V4L2 sub-device asynchronous registration callbacks***********/ + +struct sensor_async_subdev { + struct v4l2_async_subdev asd; + int port; +}; + +#define to_sensor_asd(a) container_of(a, struct sensor_async_subdev, asd) +#define notifier_to_atomisp(n) container_of(n, struct atomisp_device, notifier) + +/* .bound() notifier callback when a match is found */ +static int atomisp_notifier_bound(struct v4l2_async_notifier *notifier, + struct v4l2_subdev *sd, + struct v4l2_async_subdev *asd) +{ + struct atomisp_device *isp = notifier_to_atomisp(notifier); + struct sensor_async_subdev *s_asd = to_sensor_asd(asd); + + if (s_asd->port >= ATOMISP_CAMERA_NR_PORTS) { + dev_err(isp->dev, "port %d not supported\n", s_asd->port); + return -EINVAL; + } + + if (isp->sensor_subdevs[s_asd->port]) { + dev_err(isp->dev, "port %d already has a sensor attached\n", s_asd->port); + return -EBUSY; + } + + isp->sensor_subdevs[s_asd->port] = sd; + return 0; +} + +/* The .unbind callback */ +static void atomisp_notifier_unbind(struct v4l2_async_notifier *notifier, + struct v4l2_subdev *sd, + struct v4l2_async_subdev *asd) +{ + struct atomisp_device *isp = notifier_to_atomisp(notifier); + struct sensor_async_subdev *s_asd = to_sensor_asd(asd); + + isp->sensor_subdevs[s_asd->port] = NULL; +} + +/* .complete() is called after all subdevices have been located */ +static int atomisp_notifier_complete(struct v4l2_async_notifier *notifier) +{ + struct atomisp_device *isp = notifier_to_atomisp(notifier); + + return atomisp_register_device_nodes(isp); +} + +static const struct v4l2_async_notifier_operations atomisp_async_ops = { + .bound = atomisp_notifier_bound, + .unbind = atomisp_notifier_unbind, + .complete = atomisp_notifier_complete, +}; + +int atomisp_csi2_bridge_parse_firmware(struct atomisp_device *isp) +{ + int i, mipi_port, ret; + + v4l2_async_nf_init(&isp->notifier); + isp->notifier.ops = &atomisp_async_ops; + + for (i = 0; i < ATOMISP_CAMERA_NR_PORTS; i++) { + struct v4l2_fwnode_endpoint vep = { + .bus_type = V4L2_MBUS_CSI2_DPHY, + }; + struct sensor_async_subdev *s_asd; + struct fwnode_handle *ep; + + ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(isp->dev), i, 0, + FWNODE_GRAPH_ENDPOINT_NEXT); + if (!ep) + continue; + + ret = v4l2_fwnode_endpoint_parse(ep, &vep); + if (ret) + goto err_parse; + + if (vep.base.port >= ATOMISP_CAMERA_NR_PORTS) { + dev_err(isp->dev, "port %d not supported\n", vep.base.port); + ret = -EINVAL; + goto err_parse; + } + + mipi_port = atomisp_port_to_mipi_port(isp, vep.base.port); + isp->sensor_lanes[mipi_port] = vep.bus.mipi_csi2.num_data_lanes; + + s_asd = v4l2_async_nf_add_fwnode_remote(&isp->notifier, ep, + struct sensor_async_subdev); + if (IS_ERR(s_asd)) { + ret = PTR_ERR(s_asd); + goto err_parse; + } + + s_asd->port = vep.base.port; + + fwnode_handle_put(ep); + continue; + +err_parse: + fwnode_handle_put(ep); + return ret; + } + + return 0; +} diff --git a/drivers/staging/media/atomisp/pci/atomisp_drvfs.c b/drivers/staging/media/atomisp/pci/atomisp_drvfs.c index 3ddc935ec01d5932451f8728ace244310e13bc65..1df534bf54d3269139a39bf4584a70af97e2f571 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_drvfs.c +++ b/drivers/staging/media/atomisp/pci/atomisp_drvfs.c @@ -69,7 +69,7 @@ static inline int iunit_dump_dbgopt(struct atomisp_device *isp, } if (opt & OPTION_BIN_RUN) { - if (atomisp_streaming_count(isp)) { + if (isp->asd.streaming) { atomisp_css_dump_sp_raw_copy_linecount(true); atomisp_css_debug_dump_isp_binary(); } else { diff --git a/drivers/staging/media/atomisp/pci/atomisp_fops.c b/drivers/staging/media/atomisp/pci/atomisp_fops.c index fa362c8a37e845f94c716b5b9014f89303a20bdd..54466d2f323a156374ed94789c7683c87e7b270e 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_fops.c +++ b/drivers/staging/media/atomisp/pci/atomisp_fops.c @@ -47,7 +47,6 @@ static int atomisp_queue_setup(struct vb2_queue *vq, unsigned int sizes[], struct device *alloc_devs[]) { struct atomisp_video_pipe *pipe = container_of(vq, struct atomisp_video_pipe, vb_queue); - u16 source_pad = atomisp_subdev_source_pad(&pipe->vdev); int ret; mutex_lock(&pipe->asd->isp->mutex); /* for get_css_frame_info() / set_fmt() */ @@ -56,7 +55,7 @@ static int atomisp_queue_setup(struct vb2_queue *vq, * When VIDIOC_S_FMT has not been called before VIDIOC_REQBUFS, then * this will fail. Call atomisp_set_fmt() ourselves and try again. */ - ret = atomisp_get_css_frame_info(pipe->asd, source_pad, &pipe->frame_info); + ret = atomisp_get_css_frame_info(pipe->asd, &pipe->frame_info); if (ret) { struct v4l2_format f = { .fmt.pix.pixelformat = V4L2_PIX_FMT_YUV420, @@ -68,7 +67,7 @@ static int atomisp_queue_setup(struct vb2_queue *vq, if (ret) goto out; - ret = atomisp_get_css_frame_info(pipe->asd, source_pad, &pipe->frame_info); + ret = atomisp_get_css_frame_info(pipe->asd, &pipe->frame_info); if (ret) goto out; } @@ -342,119 +341,29 @@ static int atomisp_q_video_buffers_to_css(struct atomisp_sub_device *asd, return 0; } -static int atomisp_get_css_buf_type(struct atomisp_sub_device *asd, - enum ia_css_pipe_id pipe_id, - uint16_t source_pad) -{ - if (pipe_id == IA_CSS_PIPE_ID_COPY || - source_pad == ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE || - source_pad == ATOMISP_SUBDEV_PAD_SOURCE_VIDEO || - (source_pad == ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW && - asd->run_mode->val != ATOMISP_RUN_MODE_VIDEO)) - return IA_CSS_BUFFER_TYPE_OUTPUT_FRAME; - else - return IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME; -} - /* queue all available buffers to css */ int atomisp_qbuffers_to_css(struct atomisp_sub_device *asd) { - enum ia_css_buffer_type buf_type; - enum ia_css_pipe_id css_capture_pipe_id = IA_CSS_PIPE_ID_NUM; - enum ia_css_pipe_id css_preview_pipe_id = IA_CSS_PIPE_ID_NUM; - enum ia_css_pipe_id css_video_pipe_id = IA_CSS_PIPE_ID_NUM; - enum atomisp_input_stream_id input_stream_id; - struct atomisp_video_pipe *capture_pipe = NULL; - struct atomisp_video_pipe *vf_pipe = NULL; - struct atomisp_video_pipe *preview_pipe = NULL; - struct atomisp_video_pipe *video_pipe = NULL; - bool raw_mode = atomisp_is_mbuscode_raw( - asd->fmt[asd->capture_pad].fmt.code); - - if (asd->vfpp->val == ATOMISP_VFPP_DISABLE_SCALER) { - video_pipe = &asd->video_out_video_capture; - css_video_pipe_id = IA_CSS_PIPE_ID_VIDEO; + enum ia_css_pipe_id pipe_id; + + if (asd->copy_mode) { + pipe_id = IA_CSS_PIPE_ID_COPY; + } else if (asd->vfpp->val == ATOMISP_VFPP_DISABLE_SCALER) { + pipe_id = IA_CSS_PIPE_ID_VIDEO; } else if (asd->vfpp->val == ATOMISP_VFPP_DISABLE_LOWLAT) { - preview_pipe = &asd->video_out_capture; - css_preview_pipe_id = IA_CSS_PIPE_ID_CAPTURE; + pipe_id = IA_CSS_PIPE_ID_CAPTURE; } else if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO) { - video_pipe = &asd->video_out_video_capture; - preview_pipe = &asd->video_out_preview; - css_video_pipe_id = IA_CSS_PIPE_ID_VIDEO; - css_preview_pipe_id = IA_CSS_PIPE_ID_VIDEO; + pipe_id = IA_CSS_PIPE_ID_VIDEO; } else if (asd->run_mode->val == ATOMISP_RUN_MODE_PREVIEW) { - preview_pipe = &asd->video_out_preview; - css_preview_pipe_id = IA_CSS_PIPE_ID_PREVIEW; + pipe_id = IA_CSS_PIPE_ID_PREVIEW; } else { /* ATOMISP_RUN_MODE_STILL_CAPTURE */ - capture_pipe = &asd->video_out_capture; - if (!raw_mode) - vf_pipe = &asd->video_out_vf; - css_capture_pipe_id = IA_CSS_PIPE_ID_CAPTURE; - } - - if (IS_ISP2401 && asd->copy_mode) { - css_capture_pipe_id = IA_CSS_PIPE_ID_COPY; - css_preview_pipe_id = IA_CSS_PIPE_ID_COPY; - css_video_pipe_id = IA_CSS_PIPE_ID_COPY; - } - - if (capture_pipe) { - buf_type = atomisp_get_css_buf_type( - asd, css_capture_pipe_id, - atomisp_subdev_source_pad(&capture_pipe->vdev)); - input_stream_id = ATOMISP_INPUT_STREAM_GENERAL; - - atomisp_q_video_buffers_to_css(asd, capture_pipe, - input_stream_id, - buf_type, css_capture_pipe_id); - } - - if (vf_pipe) { - buf_type = atomisp_get_css_buf_type( - asd, css_capture_pipe_id, - atomisp_subdev_source_pad(&vf_pipe->vdev)); - if (asd->stream_env[ATOMISP_INPUT_STREAM_POSTVIEW].stream) - input_stream_id = ATOMISP_INPUT_STREAM_POSTVIEW; - else - input_stream_id = ATOMISP_INPUT_STREAM_GENERAL; - - atomisp_q_video_buffers_to_css(asd, vf_pipe, - input_stream_id, - buf_type, css_capture_pipe_id); - } - - if (preview_pipe) { - buf_type = atomisp_get_css_buf_type( - asd, css_preview_pipe_id, - atomisp_subdev_source_pad(&preview_pipe->vdev)); - - if (css_preview_pipe_id == IA_CSS_PIPE_ID_YUVPP) - input_stream_id = ATOMISP_INPUT_STREAM_VIDEO; - else if (asd->stream_env[ATOMISP_INPUT_STREAM_PREVIEW].stream) - input_stream_id = ATOMISP_INPUT_STREAM_PREVIEW; - else - input_stream_id = ATOMISP_INPUT_STREAM_GENERAL; - - atomisp_q_video_buffers_to_css(asd, preview_pipe, - input_stream_id, - buf_type, css_preview_pipe_id); - } - - if (video_pipe) { - buf_type = atomisp_get_css_buf_type( - asd, css_video_pipe_id, - atomisp_subdev_source_pad(&video_pipe->vdev)); - if (asd->stream_env[ATOMISP_INPUT_STREAM_VIDEO].stream) - input_stream_id = ATOMISP_INPUT_STREAM_VIDEO; - else - input_stream_id = ATOMISP_INPUT_STREAM_GENERAL; - - atomisp_q_video_buffers_to_css(asd, video_pipe, - input_stream_id, - buf_type, css_video_pipe_id); + pipe_id = IA_CSS_PIPE_ID_CAPTURE; } + atomisp_q_video_buffers_to_css(asd, &asd->video_out, + ATOMISP_INPUT_STREAM_GENERAL, + IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, pipe_id); return 0; } @@ -493,9 +402,8 @@ static void atomisp_buf_queue(struct vb2_buffer *vb) * is put to waiting list until previous per-frame parameter buffers * get enqueued. */ - if (!atomisp_is_vf_pipe(pipe) && - (pipe->frame_request_config_id[vb->index] || - !list_empty(&pipe->buffers_waiting_for_param))) + if (pipe->frame_request_config_id[vb->index] || + !list_empty(&pipe->buffers_waiting_for_param)) list_add_tail(&frame->queue, &pipe->buffers_waiting_for_param); else list_add_tail(&frame->queue, &pipe->activeq); @@ -503,7 +411,7 @@ static void atomisp_buf_queue(struct vb2_buffer *vb) spin_unlock_irqrestore(&pipe->irq_lock, irqflags); /* TODO: do this better, not best way to queue to css */ - if (asd->streaming == ATOMISP_DEVICE_STREAMING_ENABLED) { + if (asd->streaming) { if (!list_empty(&pipe->buffers_waiting_for_param)) atomisp_handle_parameter_and_buffer(pipe); else @@ -539,9 +447,7 @@ static void atomisp_dev_init_struct(struct atomisp_device *isp) { unsigned int i; - isp->need_gfx_throttle = true; isp->isp_fatal_error = false; - isp->mipi_frame_size = 0; for (i = 0; i < isp->input_cnt; i++) isp->inputs[i].asd = NULL; @@ -568,10 +474,6 @@ static void atomisp_subdev_init_struct(struct atomisp_sub_device *asd) /* s3a grid not enabled for any pipe */ asd->params.s3a_enabled_pipe = IA_CSS_PIPE_ID_NUM; - /* Add for channel */ - asd->input_curr = 0; - - asd->mipi_frame_size = 0; asd->copy_mode = false; asd->stream_prepared = false; @@ -584,19 +486,6 @@ static void atomisp_subdev_init_struct(struct atomisp_sub_device *asd) /* * file operation functions */ -static unsigned int atomisp_subdev_users(struct atomisp_sub_device *asd) -{ - return asd->video_out_preview.users + - asd->video_out_vf.users + - asd->video_out_capture.users + - asd->video_out_video_capture.users; -} - -unsigned int atomisp_dev_users(struct atomisp_device *isp) -{ - return atomisp_subdev_users(&isp->asd); -} - static int atomisp_open(struct file *file) { struct video_device *vdev = video_devdata(file); @@ -613,8 +502,6 @@ static int atomisp_open(struct file *file) mutex_lock(&isp->mutex); - asd->subdev.devnode = vdev; - if (!isp->input_cnt) { dev_err(isp->dev, "no camera attached\n"); ret = -EINVAL; @@ -630,11 +517,6 @@ static int atomisp_open(struct file *file) return -EBUSY; } - if (atomisp_dev_users(isp)) { - dev_dbg(isp->dev, "skip init isp in open\n"); - goto init_subdev; - } - /* runtime power management, turn on ISP */ ret = pm_runtime_resume_and_get(vdev->v4l2_dev->dev); if (ret < 0) { @@ -650,19 +532,12 @@ static int atomisp_open(struct file *file) goto css_error; } -init_subdev: - if (atomisp_subdev_users(asd)) - goto done; - atomisp_subdev_init_struct(asd); /* Ensure that a mode is set */ - v4l2_ctrl_s_ctrl(asd->run_mode, pipe->default_run_mode); + v4l2_ctrl_s_ctrl(asd->run_mode, ATOMISP_RUN_MODE_PREVIEW); -done: pipe->users++; mutex_unlock(&isp->mutex); - - return 0; css_error: @@ -681,23 +556,18 @@ static int atomisp_release(struct file *file) struct atomisp_sub_device *asd = pipe->asd; struct v4l2_subdev_fh fh; struct v4l2_rect clear_compose = {0}; - unsigned long flags; int ret; v4l2_fh_init(&fh.vfh, vdev); dev_dbg(isp->dev, "release device %s\n", vdev->name); - asd->subdev.devnode = vdev; - /* Note file must not be used after this! */ vb2_fop_release(file); mutex_lock(&isp->mutex); pipe->users--; - if (pipe->users) - goto done; /* * A little trick here: @@ -714,9 +584,6 @@ static int atomisp_release(struct file *file) ATOMISP_SUBDEV_PAD_SINK, &isp_sink_fmt); } - if (atomisp_subdev_users(asd)) - goto done; - atomisp_css_free_stat_buffers(asd); atomisp_free_internal_buffers(asd); @@ -730,14 +597,7 @@ static int atomisp_release(struct file *file) isp->inputs[asd->input_curr].asd = NULL; } - spin_lock_irqsave(&isp->lock, flags); - asd->streaming = ATOMISP_DEVICE_STREAMING_DISABLED; - spin_unlock_irqrestore(&isp->lock, flags); - - if (atomisp_dev_users(isp)) - goto done; - - atomisp_destroy_pipes_stream_force(asd); + atomisp_destroy_pipes_stream(asd); ret = v4l2_subdev_call(isp->flash, core, s_power, 0); if (ret < 0 && ret != -ENODEV && ret != -ENOIOCTLCMD) @@ -746,10 +606,9 @@ static int atomisp_release(struct file *file) if (pm_runtime_put_sync(vdev->v4l2_dev->dev) < 0) dev_err(isp->dev, "Failed to power off device\n"); -done: atomisp_subdev_set_selection(&asd->subdev, fh.state, V4L2_SUBDEV_FORMAT_ACTIVE, - atomisp_subdev_source_pad(vdev), + ATOMISP_SUBDEV_PAD_SOURCE, V4L2_SEL_TGT_COMPOSE, 0, &clear_compose); mutex_unlock(&isp->mutex); diff --git a/drivers/staging/media/atomisp/pci/atomisp_fops.h b/drivers/staging/media/atomisp/pci/atomisp_fops.h index 883c1851c1c98729bc1f6c224446fba1a6879ae4..ad1cb1ac8aa46cdd5d0adf8898c647eb79b7a39f 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_fops.h +++ b/drivers/staging/media/atomisp/pci/atomisp_fops.h @@ -22,9 +22,6 @@ #define __ATOMISP_FOPS_H__ #include "atomisp_subdev.h" -unsigned int atomisp_dev_users(struct atomisp_device *isp); -unsigned int atomisp_sub_dev_users(struct atomisp_sub_device *asd); - /* * Memory help functions for image frame and private parameters */ diff --git a/drivers/staging/media/atomisp/pci/atomisp_gmin_platform.c b/drivers/staging/media/atomisp/pci/atomisp_gmin_platform.c index c718a74ea70a31f53f103c9cfec5c0cb133017ae..139ad7ad1dcf6ea397db8e4cdba642121aa57662 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_gmin_platform.c +++ b/drivers/staging/media/atomisp/pci/atomisp_gmin_platform.c @@ -189,6 +189,7 @@ int atomisp_register_i2c_module(struct v4l2_subdev *subdev, pdata.subdevs[i].type = type; pdata.subdevs[i].port = gs->csi_port; + pdata.subdevs[i].lanes = gs->csi_lanes; pdata.subdevs[i].subdev = subdev; return 0; } @@ -1150,6 +1151,7 @@ int atomisp_register_sensor_no_gmin(struct v4l2_subdev *subdev, u32 lanes, pdata.subdevs[i].type = RAW_CAMERA; pdata.subdevs[i].port = port; + pdata.subdevs[i].lanes = lanes; pdata.subdevs[i].subdev = subdev; return 0; } @@ -1357,7 +1359,7 @@ static int gmin_get_config_dsm_var(struct device *dev, dev_info(dev, "found _DSM entry for '%s': %s\n", var, cur->string.pointer); strscpy(out, cur->string.pointer, *out_len); - *out_len = strlen(cur->string.pointer); + *out_len = strlen(out); ACPI_FREE(obj); return 0; @@ -1427,8 +1429,8 @@ static int gmin_get_config_var(struct device *maindev, int gmin_get_var_int(struct device *dev, bool is_gmin, const char *var, int def) { - char val[CFG_VAR_NAME_MAX]; - size_t len = sizeof(val); + char val[CFG_VAR_NAME_MAX + 1]; + size_t len = CFG_VAR_NAME_MAX; long result; int ret; @@ -1458,243 +1460,3 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x0f38, isp_pm_cap_fixup); MODULE_DESCRIPTION("Ancillary routines for binding ACPI devices"); MODULE_LICENSE("GPL"); - -/* - * The below helper functions don't really belong here and should eventually be - * moved to some place under drivers/media/v4l2-core. - */ -#include - -/* - * 79234640-9e10-4fea-a5c1-b5aa8b19756f - * This _DSM GUID returns information about the GPIO lines mapped to a sensor. - * Function number 1 returns a count of the GPIO lines that are mapped. - * Subsequent functions return 32 bit ints encoding information about the GPIO. - */ -static const guid_t intel_sensor_gpio_info_guid = - GUID_INIT(0x79234640, 0x9e10, 0x4fea, - 0xa5, 0xc1, 0xb5, 0xaa, 0x8b, 0x19, 0x75, 0x6f); - -/* - * 822ace8f-2814-4174-a56b-5f029fe079ee - * This _DSM GUID returns a string from the sensor device, which acts as a - * module identifier. - */ -static const guid_t intel_sensor_module_guid = - GUID_INIT(0x822ace8f, 0x2814, 0x4174, - 0xa5, 0x6b, 0x5f, 0x02, 0x9f, 0xe0, 0x79, 0xee); - -#define INTEL_DSM_TYPE_SHIFT 0 -#define INTEL_DSM_TYPE_MASK GENMASK(7, 0) -#define INTEL_DSM_PIN_SHIFT 8 -#define INTEL_DSM_PIN_MASK GENMASK(15, 8) -#define INTEL_DSM_SENSOR_ON_VAL_SHIFT 24 -#define INTEL_DSM_SENSOR_ON_VAL_MASK GENMASK(31, 24) - -#define INTEL_DSM_TYPE(x) \ - (((x) & INTEL_DSM_TYPE_MASK) >> INTEL_DSM_TYPE_SHIFT) -#define INTEL_DSM_PIN(x) \ - (((x) & INTEL_DSM_PIN_MASK) >> INTEL_DSM_PIN_SHIFT) -#define INTEL_DSM_SENSOR_ON_VAL(x) \ - (((x) & INTEL_DSM_SENSOR_ON_VAL_MASK) >> INTEL_DSM_SENSOR_ON_VAL_SHIFT) - -#define V4L2_SENSOR_MAX_ACPI_GPIOS 2u - -struct v4l2_acpi_gpio_map { - struct acpi_gpio_params params[V4L2_SENSOR_MAX_ACPI_GPIOS]; - struct acpi_gpio_mapping mapping[V4L2_SENSOR_MAX_ACPI_GPIOS + 1]; -}; - -struct v4l2_acpi_gpio_parsing_data { - struct device *dev; - u32 settings[V4L2_SENSOR_MAX_ACPI_GPIOS]; - unsigned int settings_count; - unsigned int res_count; - unsigned int map_count; - struct v4l2_acpi_gpio_map *map; -}; - -/* Note this always returns 1 to continue looping so that res_count is accurate */ -static int v4l2_acpi_handle_gpio_res(struct acpi_resource *ares, void *_data) -{ - struct v4l2_acpi_gpio_parsing_data *data = _data; - struct acpi_resource_gpio *agpio; - const char *name; - bool active_low; - unsigned int i; - u32 settings; - u8 pin; - - if (!acpi_gpio_get_io_resource(ares, &agpio)) - return 1; /* Not a GPIO, continue the loop */ - - data->res_count++; - - pin = agpio->pin_table[0]; - for (i = 0; i < data->settings_count; i++) { - if (INTEL_DSM_PIN(data->settings[i]) == pin) { - settings = data->settings[i]; - break; - } - } - - if (i == data->settings_count) { - dev_warn(data->dev, "Could not find DSM GPIO settings for pin %d\n", pin); - return 1; - } - - switch (INTEL_DSM_TYPE(settings)) { - case 0: - name = "reset-gpios"; - break; - case 1: - name = "powerdown-gpios"; - break; - default: - dev_warn(data->dev, "Unknown GPIO type 0x%02lx for pin %d\n", - INTEL_DSM_TYPE(settings), pin); - return 1; - } - - /* - * Both reset and power-down need to be logical false when the sensor - * is on (sensor should not be in reset and not be powered-down). So - * when the sensor-on-value (which is the physical pin value) is high, - * then the signal is active-low. - */ - active_low = INTEL_DSM_SENSOR_ON_VAL(settings) ? true : false; - - i = data->map_count; - if (i == V4L2_SENSOR_MAX_ACPI_GPIOS) - return 1; - - /* res_count is already incremented */ - data->map->params[i].crs_entry_index = data->res_count - 1; - data->map->params[i].active_low = active_low; - data->map->mapping[i].name = name; - data->map->mapping[i].data = &data->map->params[i]; - data->map->mapping[i].size = 1; - data->map_count++; - - dev_info(data->dev, "%s crs %d %s pin %d active-%s\n", name, - data->res_count - 1, agpio->resource_source.string_ptr, - pin, active_low ? "low" : "high"); - - return 1; -} - -/* - * Helper function to create an ACPI GPIO lookup table for sensor reset and - * powerdown signals on Intel Bay Trail (BYT) and Cherry Trail (CHT) devices, - * including setting the correct polarity for the GPIO. - * - * This uses the "79234640-9e10-4fea-a5c1-b5aa8b19756f" DSM method directly - * on the sensor device's ACPI node. This is different from later Intel - * hardware which has a separate INT3472 with this info. Since there is - * no separate firmware-node to which we can bind to register the GPIO lookups - * this unfortunately means that all sensor drivers which may be used on - * BYT or CHT hw need to call this function. This also means that this function - * may only fail when it is actually called on BYT/CHT hw. In all other cases - * it must always succeed. - * - * Note this code uses the same DSM GUID as the INT3472 discrete.c code - * and there is some overlap, but there are enough differences that it is - * difficult to share the code. - */ -int v4l2_get_acpi_sensor_info(struct device *dev, char **module_id_str) -{ - struct acpi_device *adev = ACPI_COMPANION(dev); - struct v4l2_acpi_gpio_parsing_data data = { }; - LIST_HEAD(resource_list); - union acpi_object *obj; - unsigned int i, j; - int ret; - - if (module_id_str) - *module_id_str = NULL; - - if (!adev) - return 0; - - obj = acpi_evaluate_dsm_typed(adev->handle, &intel_sensor_module_guid, - 0x00, 0x01, NULL, ACPI_TYPE_STRING); - if (obj) { - dev_info(dev, "Sensor module id: '%s'\n", obj->string.pointer); - if (module_id_str) - *module_id_str = kstrdup(obj->string.pointer, GFP_KERNEL); - - ACPI_FREE(obj); - } - - if (!soc_intel_is_byt() && !soc_intel_is_cht()) - return 0; - - /* - * First get the GPIO-settings count and then get count GPIO-settings - * values. Note the order of these may differ from the order in which - * the GPIOs are listed on the ACPI resources! So we first store them all - * and then enumerate the ACPI resources and match them up by pin number. - */ - obj = acpi_evaluate_dsm_typed(adev->handle, - &intel_sensor_gpio_info_guid, 0x00, 1, - NULL, ACPI_TYPE_INTEGER); - if (!obj) - return dev_err_probe(dev, -EIO, "No _DSM entry for GPIO pin count\n"); - - data.settings_count = obj->integer.value; - ACPI_FREE(obj); - - if (data.settings_count > V4L2_SENSOR_MAX_ACPI_GPIOS) - return dev_err_probe(dev, -EIO, "Too many GPIOs %u > %u\n", - data.settings_count, V4L2_SENSOR_MAX_ACPI_GPIOS); - - for (i = 0; i < data.settings_count; i++) { - /* - * i + 2 because the index of this _DSM function is 1-based - * and the first function is just a count. - */ - obj = acpi_evaluate_dsm_typed(adev->handle, - &intel_sensor_gpio_info_guid, - 0x00, i + 2, - NULL, ACPI_TYPE_INTEGER); - if (!obj) - return dev_err_probe(dev, -EIO, "No _DSM entry for GPIO pin %u\n", i); - - data.settings[i] = obj->integer.value; - ACPI_FREE(obj); - } - - /* Since we match up by pin-number the pin-numbers must be unique */ - for (i = 0; i < data.settings_count; i++) { - for (j = i + 1; j < data.settings_count; j++) { - if (INTEL_DSM_PIN(data.settings[i]) != - INTEL_DSM_PIN(data.settings[j])) - continue; - - return dev_err_probe(dev, -EIO, "Duplicate pin number %lu\n", - INTEL_DSM_PIN(data.settings[i])); - } - } - - /* Use devm_kzalloc() for the mappings + params to auto-free them */ - data.map = devm_kzalloc(dev, sizeof(*data.map), GFP_KERNEL); - if (!data.map) - return -ENOMEM; - - /* Now parse the ACPI resources and build the lookup table */ - data.dev = dev; - ret = acpi_dev_get_resources(adev, &resource_list, - v4l2_acpi_handle_gpio_res, &data); - if (ret < 0) - return ret; - - acpi_dev_free_resource_list(&resource_list); - - if (data.map_count != data.settings_count || - data.res_count != data.settings_count) - dev_warn(dev, "ACPI GPIO resources vs DSM GPIO-info count mismatch (dsm: %d res: %d map %d\n", - data.settings_count, data.res_count, data.map_count); - - return devm_acpi_dev_add_driver_gpios(dev, data.map->mapping); -} -EXPORT_SYMBOL_GPL(v4l2_get_acpi_sensor_info); diff --git a/drivers/staging/media/atomisp/pci/atomisp_internal.h b/drivers/staging/media/atomisp/pci/atomisp_internal.h index 1fac99f4e2b0144d17c0d3a34739224b49b74f7d..f7b4bee9574bdb8ea330bec4e04074515e71f5a5 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_internal.h +++ b/drivers/staging/media/atomisp/pci/atomisp_internal.h @@ -27,6 +27,7 @@ #include #include +#include #include /* ISP2400*/ @@ -124,17 +125,23 @@ struct atomisp_input_subdev { unsigned int type; enum atomisp_camera_port port; + u32 code; /* MEDIA_BUS_FMT_* */ + bool binning_support; + bool crop_support; struct v4l2_subdev *camera; + /* Sensor rects for sensors which support crop */ + struct v4l2_rect native_rect; + struct v4l2_rect active_rect; + /* Sensor pad_cfg for which == V4L2_SUBDEV_FORMAT_TRY calls */ + struct v4l2_subdev_pad_config pad_cfg; + struct v4l2_subdev *motor; - struct v4l2_frmsizeenum frame_size; /* * To show this resource is used by * which stream, in ISP multiple stream mode */ struct atomisp_sub_device *asd; - - int sensor_index; }; enum atomisp_dfs_mode { @@ -168,10 +175,6 @@ struct atomisp_regs { u32 csi_access_viol; }; -#define ATOMISP_DEVICE_STREAMING_DISABLED 0 -#define ATOMISP_DEVICE_STREAMING_ENABLED 1 -#define ATOMISP_DEVICE_STREAMING_STOPPING 2 - /* * ci device struct */ @@ -180,6 +183,7 @@ struct atomisp_device { struct v4l2_device v4l2_dev; struct media_device media_dev; struct atomisp_sub_device asd; + struct v4l2_async_notifier notifier; struct atomisp_platform_data *pdata; void *mmu_l1_base; void __iomem *base; @@ -196,6 +200,12 @@ struct atomisp_device { * structures and css API calls. */ struct mutex mutex; + /* + * Number of lanes used by each sensor per port. + * Note this is indexed by mipi_port_id not atomisp_camera_port. + */ + int sensor_lanes[N_MIPI_PORT_ID]; + struct v4l2_subdev *sensor_subdevs[ATOMISP_CAMERA_NR_PORTS]; unsigned int input_cnt; struct atomisp_input_subdev inputs[ATOM_ISP_MAX_INPUTS]; struct v4l2_subdev *flash; @@ -204,16 +214,11 @@ struct atomisp_device { struct atomisp_regs saved_regs; struct atomisp_css_env css_env; - /* isp timeout status flag */ - bool isp_timeout; bool isp_fatal_error; struct work_struct assert_recovery_work; spinlock_t lock; /* Protects asd.streaming */ - bool need_gfx_throttle; - - unsigned int mipi_frame_size; const struct atomisp_dfs_config *dfs; unsigned int hpll_freq; unsigned int running_freq; diff --git a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c index 384f31fc66c519b1b9c5f15eb8d988bd0ccade16..d2174156573a536560f63b1dd3a7cd8e6ace0e52 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c +++ b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c @@ -528,22 +528,6 @@ int atomisp_pipe_check(struct atomisp_video_pipe *pipe, bool settings_change) return -EBUSY; } - switch (pipe->asd->streaming) { - case ATOMISP_DEVICE_STREAMING_DISABLED: - break; - case ATOMISP_DEVICE_STREAMING_ENABLED: - if (settings_change) { - dev_err(pipe->isp->dev, "Set fmt/input IOCTL while streaming\n"); - return -EBUSY; - } - break; - case ATOMISP_DEVICE_STREAMING_STOPPING: - dev_err(pipe->isp->dev, "IOCTL issued while stopping\n"); - return -EBUSY; - default: - return -EINVAL; - } - return 0; } @@ -615,20 +599,6 @@ static int atomisp_enum_input(struct file *file, void *fh, return 0; } -static unsigned int -atomisp_subdev_streaming_count(struct atomisp_sub_device *asd) -{ - return vb2_start_streaming_called(&asd->video_out_preview.vb_queue) + - vb2_start_streaming_called(&asd->video_out_capture.vb_queue) + - vb2_start_streaming_called(&asd->video_out_video_capture.vb_queue) + - vb2_start_streaming_called(&asd->video_out_vf.vb_queue); -} - -unsigned int atomisp_streaming_count(struct atomisp_device *isp) -{ - return isp->asd.streaming == ATOMISP_DEVICE_STREAMING_ENABLED; -} - /* * get input are used to get current primary/secondary camera */ @@ -703,7 +673,7 @@ static int atomisp_s_input(struct file *file, void *fh, unsigned int input) /* select operating sensor */ ret = v4l2_subdev_call(isp->inputs[input].camera, video, s_routing, - 0, isp->inputs[input].sensor_index, 0); + 0, 0, 0); if (ret && (ret != -ENOIOCTLCMD)) { dev_err(isp->dev, "Failed to select sensor\n"); return ret; @@ -727,20 +697,98 @@ static int atomisp_s_input(struct file *file, void *fh, unsigned int input) return 0; } +/* + * With crop any framesize <= sensor-size can be made, give + * userspace a list of sizes to choice from. + */ +static int atomisp_enum_framesizes_crop_inner(struct atomisp_device *isp, + struct v4l2_frmsizeenum *fsize, + const struct v4l2_rect *active, + const struct v4l2_rect *native, + int *valid_sizes) +{ + static const struct v4l2_frmsize_discrete frame_sizes[] = { + { 1600, 1200 }, + { 1600, 1080 }, + { 1600, 900 }, + { 1440, 1080 }, + { 1280, 960 }, + { 1280, 720 }, + { 800, 600 }, + { 640, 480 }, + }; + u32 padding_w, padding_h; + int i; + + for (i = 0; i < ARRAY_SIZE(frame_sizes); i++) { + atomisp_get_padding(isp, frame_sizes[i].width, frame_sizes[i].height, + &padding_w, &padding_h); + + if ((frame_sizes[i].width + padding_w) > native->width || + (frame_sizes[i].height + padding_h) > native->height) + continue; + + /* + * Skip sizes where width and height are less then 2/3th of the + * sensor size to avoid sizes with a too small field of view. + */ + if (frame_sizes[i].width < (active->width * 2 / 3) && + frame_sizes[i].height < (active->height * 2 / 3)) + continue; + + if (*valid_sizes == fsize->index) { + fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; + fsize->discrete = frame_sizes[i]; + return 0; + } + + (*valid_sizes)++; + } + + return -EINVAL; +} + +static int atomisp_enum_framesizes_crop(struct atomisp_device *isp, + struct v4l2_frmsizeenum *fsize) +{ + struct atomisp_input_subdev *input = &isp->inputs[isp->asd.input_curr]; + struct v4l2_rect active = input->active_rect; + struct v4l2_rect native = input->native_rect; + int ret, valid_sizes = 0; + + ret = atomisp_enum_framesizes_crop_inner(isp, fsize, &active, &native, &valid_sizes); + if (ret == 0) + return 0; + + if (!input->binning_support) + return -EINVAL; + + active.width /= 2; + active.height /= 2; + native.width /= 2; + native.height /= 2; + + return atomisp_enum_framesizes_crop_inner(isp, fsize, &active, &native, &valid_sizes); +} + static int atomisp_enum_framesizes(struct file *file, void *priv, struct v4l2_frmsizeenum *fsize) { struct video_device *vdev = video_devdata(file); struct atomisp_device *isp = video_get_drvdata(vdev); struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd; + struct atomisp_input_subdev *input = &isp->inputs[asd->input_curr]; struct v4l2_subdev_frame_size_enum fse = { .index = fsize->index, .which = V4L2_SUBDEV_FORMAT_ACTIVE, + .code = input->code, }; int ret; - ret = v4l2_subdev_call(isp->inputs[asd->input_curr].camera, - pad, enum_frame_size, NULL, &fse); + if (input->crop_support) + return atomisp_enum_framesizes_crop(isp, fsize); + + ret = v4l2_subdev_call(input->camera, pad, enum_frame_size, NULL, &fse); if (ret) return ret; @@ -836,77 +884,14 @@ static int atomisp_enum_fmt_cap(struct file *file, void *fh, return -EINVAL; } -static int atomisp_adjust_fmt(struct v4l2_format *f) -{ - const struct atomisp_format_bridge *format_bridge; - u32 padded_width; - - format_bridge = atomisp_get_format_bridge(f->fmt.pix.pixelformat); - /* Currently, raw formats are broken!!! */ - if (!format_bridge || format_bridge->sh_fmt == IA_CSS_FRAME_FORMAT_RAW) { - f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUV420; - - format_bridge = atomisp_get_format_bridge(f->fmt.pix.pixelformat); - if (!format_bridge) - return -EINVAL; - } - - padded_width = f->fmt.pix.width + pad_w; - - if (format_bridge->planar) { - f->fmt.pix.bytesperline = padded_width; - f->fmt.pix.sizeimage = PAGE_ALIGN(f->fmt.pix.height * - DIV_ROUND_UP(format_bridge->depth * - padded_width, 8)); - } else { - f->fmt.pix.bytesperline = DIV_ROUND_UP(format_bridge->depth * - padded_width, 8); - f->fmt.pix.sizeimage = PAGE_ALIGN(f->fmt.pix.height * f->fmt.pix.bytesperline); - } - - if (f->fmt.pix.field == V4L2_FIELD_ANY) - f->fmt.pix.field = V4L2_FIELD_NONE; - - /* - * FIXME: do we need to setup this differently, depending on the - * sensor or the pipeline? - */ - f->fmt.pix.colorspace = V4L2_COLORSPACE_REC709; - f->fmt.pix.ycbcr_enc = V4L2_YCBCR_ENC_709; - f->fmt.pix.xfer_func = V4L2_XFER_FUNC_709; - - f->fmt.pix.width -= pad_w; - f->fmt.pix.height -= pad_h; - - return 0; -} - /* This function looks up the closest available resolution. */ static int atomisp_try_fmt_cap(struct file *file, void *fh, struct v4l2_format *f) { struct video_device *vdev = video_devdata(file); - u32 pixfmt = f->fmt.pix.pixelformat; - int ret; - - /* - * atomisp_try_fmt() gived results with padding included, note - * (this gets removed again by the atomisp_adjust_fmt() call below. - */ - f->fmt.pix.width += pad_w; - f->fmt.pix.height += pad_h; - - ret = atomisp_try_fmt(vdev, &f->fmt.pix, NULL); - if (ret) - return ret; - - /* - * atomisp_try_fmt() replaces pixelformat with the sensors native - * format, restore the actual format requested by userspace. - */ - f->fmt.pix.pixelformat = pixfmt; + struct atomisp_device *isp = video_get_drvdata(vdev); - return atomisp_adjust_fmt(f); + return atomisp_try_fmt(isp, &f->fmt.pix, NULL, NULL); } static int atomisp_g_fmt_cap(struct file *file, void *fh, @@ -1048,8 +1033,7 @@ static int atomisp_qbuf_wrapper(struct file *file, void *fh, struct v4l2_buffer if (buf->index >= vdev->queue->num_buffers) return -EINVAL; - if (!atomisp_is_vf_pipe(pipe) && - (buf->reserved2 & ATOMISP_BUFFER_HAS_PER_FRAME_SETTING)) { + if (buf->reserved2 & ATOMISP_BUFFER_HAS_PER_FRAME_SETTING) { /* this buffer will have a per-frame parameter */ pipe->frame_request_config_id[buf->index] = buf->reserved2 & ~ATOMISP_BUFFER_HAS_PER_FRAME_SETTING; @@ -1099,48 +1083,6 @@ static int atomisp_dqbuf_wrapper(struct file *file, void *fh, struct v4l2_buffer return 0; } -enum ia_css_pipe_id atomisp_get_css_pipe_id(struct atomisp_sub_device *asd) -{ - /* - * Disable vf_pp and run CSS in video mode. This allows using ISP - * scaling but it has one frame delay due to CSS internal buffering. - */ - if (asd->vfpp->val == ATOMISP_VFPP_DISABLE_SCALER) - return IA_CSS_PIPE_ID_VIDEO; - - /* - * Disable vf_pp and run CSS in still capture mode. In this mode - * CSS does not cause extra latency with buffering, but scaling - * is not available. - */ - if (asd->vfpp->val == ATOMISP_VFPP_DISABLE_LOWLAT) - return IA_CSS_PIPE_ID_CAPTURE; - - switch (asd->run_mode->val) { - case ATOMISP_RUN_MODE_PREVIEW: - return IA_CSS_PIPE_ID_PREVIEW; - case ATOMISP_RUN_MODE_VIDEO: - return IA_CSS_PIPE_ID_VIDEO; - case ATOMISP_RUN_MODE_STILL_CAPTURE: - default: - return IA_CSS_PIPE_ID_CAPTURE; - } -} - -static unsigned int atomisp_sensor_start_stream(struct atomisp_sub_device *asd) -{ - if (asd->vfpp->val != ATOMISP_VFPP_ENABLE || - asd->copy_mode) - return 1; - - if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO || - (asd->run_mode->val == ATOMISP_RUN_MODE_STILL_CAPTURE && - !atomisp_is_mbuscode_raw(asd->fmt[asd->capture_pad].fmt.code))) - return 2; - else - return 1; -} - /* Input system HW workaround */ /* Input system address translation corrupts burst during */ /* invalidate. SW workaround for this is to set burst length */ @@ -1163,17 +1105,14 @@ int atomisp_start_streaming(struct vb2_queue *vq, unsigned int count) { struct atomisp_video_pipe *pipe = vq_to_pipe(vq); struct atomisp_sub_device *asd = pipe->asd; - struct video_device *vdev = &pipe->vdev; struct atomisp_device *isp = asd->isp; struct pci_dev *pdev = to_pci_dev(isp->dev); - enum ia_css_pipe_id css_pipe_id; - unsigned int sensor_start_stream; unsigned long irqflags; int ret; - mutex_lock(&isp->mutex); + dev_dbg(isp->dev, "Start stream\n"); - dev_dbg(isp->dev, "Start stream on pad %d\n", atomisp_subdev_source_pad(vdev)); + mutex_lock(&isp->mutex); ret = atomisp_pipe_check(pipe, false); if (ret) @@ -1182,25 +1121,6 @@ int atomisp_start_streaming(struct vb2_queue *vq, unsigned int count) /* Input system HW workaround */ atomisp_dma_burst_len_cfg(asd); - /* - * The number of streaming video nodes is based on which - * binary is going to be run. - */ - sensor_start_stream = atomisp_sensor_start_stream(asd); - - if (atomisp_subdev_streaming_count(asd) > sensor_start_stream) { - atomisp_qbuffers_to_css(asd); - ret = 0; - goto out_unlock; - } - - if (asd->streaming == ATOMISP_DEVICE_STREAMING_ENABLED) { - atomisp_qbuffers_to_css(asd); - goto start_sensor; - } - - css_pipe_id = atomisp_get_css_pipe_id(asd); - /* Invalidate caches. FIXME: should flush only necessary buffers */ wbinvd(); @@ -1215,14 +1135,14 @@ int atomisp_start_streaming(struct vb2_queue *vq, unsigned int count) } asd->params.dvs_6axis = NULL; - ret = atomisp_css_start(asd, css_pipe_id, false); + ret = atomisp_css_start(asd); if (ret) { atomisp_flush_video_pipe(pipe, VB2_BUF_STATE_QUEUED, true); goto out_unlock; } spin_lock_irqsave(&isp->lock, irqflags); - asd->streaming = ATOMISP_DEVICE_STREAMING_ENABLED; + asd->streaming = true; spin_unlock_irqrestore(&isp->lock, irqflags); atomic_set(&asd->sof_count, -1); atomic_set(&asd->sequence, -1); @@ -1238,13 +1158,6 @@ int atomisp_start_streaming(struct vb2_queue *vq, unsigned int count) atomisp_qbuffers_to_css(asd); - /* Only start sensor when the last streaming instance started */ - if (atomisp_subdev_streaming_count(asd) < sensor_start_stream) { - ret = 0; - goto out_unlock; - } - -start_sensor: if (isp->flash) { asd->params.num_flash_frames = 0; asd->params.flash_state = ATOMISP_FLASH_IDLE; @@ -1254,19 +1167,9 @@ int atomisp_start_streaming(struct vb2_queue *vq, unsigned int count) atomisp_css_irq_enable(isp, IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF, atomisp_css_valid_sof(isp)); atomisp_csi2_configure(asd); - /* - * set freq to max when streaming count > 1 which indicate - * dual camera would run - */ - if (atomisp_streaming_count(isp) > 1) { - if (atomisp_freq_scaling(isp, - ATOMISP_DFS_MODE_MAX, false) < 0) - dev_dbg(isp->dev, "DFS max mode failed!\n"); - } else { - if (atomisp_freq_scaling(isp, - ATOMISP_DFS_MODE_AUTO, false) < 0) - dev_dbg(isp->dev, "DFS auto mode failed!\n"); - } + + if (atomisp_freq_scaling(isp, ATOMISP_DFS_MODE_AUTO, false) < 0) + dev_dbg(isp->dev, "DFS auto mode failed!\n"); /* Enable the CSI interface on ANN B0/K0 */ if (isp->media_dev.hw_revision >= ((ATOMISP_HW_REVISION_ISP2401 << @@ -1279,8 +1182,9 @@ int atomisp_start_streaming(struct vb2_queue *vq, unsigned int count) ret = v4l2_subdev_call(isp->inputs[asd->input_curr].camera, video, s_stream, 1); if (ret) { + dev_err(isp->dev, "Starting sensor stream failed: %d\n", ret); spin_lock_irqsave(&isp->lock, irqflags); - asd->streaming = ATOMISP_DEVICE_STREAMING_DISABLED; + asd->streaming = false; spin_unlock_irqrestore(&isp->lock, irqflags); ret = -EINVAL; goto out_unlock; @@ -1295,19 +1199,14 @@ void atomisp_stop_streaming(struct vb2_queue *vq) { struct atomisp_video_pipe *pipe = vq_to_pipe(vq); struct atomisp_sub_device *asd = pipe->asd; - struct video_device *vdev = &pipe->vdev; struct atomisp_device *isp = asd->isp; struct pci_dev *pdev = to_pci_dev(isp->dev); - enum ia_css_pipe_id css_pipe_id; - bool recreate_stream = false; - bool first_streamoff = false; unsigned long flags; int ret; - mutex_lock(&isp->mutex); - - dev_dbg(isp->dev, "Stop stream on pad %d\n", atomisp_subdev_source_pad(vdev)); + dev_dbg(isp->dev, "Stop stream\n"); + mutex_lock(&isp->mutex); /* * There is no guarantee that the buffers queued to / owned by the ISP * will properly be returned to the queue when stopping. Set a flag to @@ -1324,46 +1223,29 @@ void atomisp_stop_streaming(struct vb2_queue *vq) if (ret == 0) dev_warn(isp->dev, "Warning timeout waiting for CSS to return buffers\n"); - if (asd->streaming == ATOMISP_DEVICE_STREAMING_ENABLED) - first_streamoff = true; - spin_lock_irqsave(&isp->lock, flags); - if (atomisp_subdev_streaming_count(asd) == 1) - asd->streaming = ATOMISP_DEVICE_STREAMING_DISABLED; - else - asd->streaming = ATOMISP_DEVICE_STREAMING_STOPPING; + asd->streaming = false; spin_unlock_irqrestore(&isp->lock, flags); - if (!first_streamoff) - goto stopsensor; - atomisp_clear_css_buffer_counters(asd); atomisp_css_irq_enable(isp, IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF, false); - css_pipe_id = atomisp_get_css_pipe_id(asd); - atomisp_css_stop(asd, css_pipe_id, false); + atomisp_css_stop(asd, false); atomisp_flush_video_pipe(pipe, VB2_BUF_STATE_ERROR, true); atomisp_subdev_cleanup_pending_events(asd); -stopsensor: - if (atomisp_subdev_streaming_count(asd) != atomisp_sensor_start_stream(asd)) - goto out_unlock; ret = v4l2_subdev_call(isp->inputs[asd->input_curr].camera, video, s_stream, 0); + if (ret) + dev_warn(isp->dev, "Stopping sensor stream failed: %d\n", ret); if (isp->flash) { asd->params.num_flash_frames = 0; asd->params.flash_state = ATOMISP_FLASH_IDLE; } - /* if other streams are running, isp should not be powered off */ - if (atomisp_streaming_count(isp)) { - atomisp_css_flush(isp); - goto out_unlock; - } - /* Disable the CSI interface on ANN B0/K0 */ if (isp->media_dev.hw_revision >= ((ATOMISP_HW_REVISION_ISP2401 << ATOMISP_HW_REVISION_SHIFT) | ATOMISP_HW_STEPPING_B0)) { @@ -1373,45 +1255,21 @@ void atomisp_stop_streaming(struct vb2_queue *vq) if (atomisp_freq_scaling(isp, ATOMISP_DFS_MODE_LOW, false)) dev_warn(isp->dev, "DFS failed.\n"); + /* - * ISP work around, need to reset isp - * Is it correct time to reset ISP when first node does streamoff? - */ - if (isp->isp_timeout) - dev_err(isp->dev, "%s: Resetting with WA activated", - __func__); - /* - * It is possible that the other asd stream is in the stage - * that v4l2_setfmt is just get called on it, which will - * create css stream on that stream. But at this point, there - * is no way to destroy the css stream created on that stream. - * - * So force stream destroy here. + * ISP work around, need to reset ISP to allow next stream on to work. + * Streams have already been destroyed by atomisp_css_stop(). + * Disable PUNIT/ISP acknowlede/handshake - SRSE=3 and then reset. */ - if (isp->asd.stream_prepared) { - atomisp_destroy_pipes_stream_force(&isp->asd); - recreate_stream = true; - } - - /* disable PUNIT/ISP acknowlede/handshake - SRSE=3 */ pci_write_config_dword(pdev, PCI_I_CONTROL, isp->saved_regs.i_control | MRFLD_PCI_I_CONTROL_SRSE_RESET_MASK); - dev_err(isp->dev, "atomisp_reset"); atomisp_reset(isp); - if (recreate_stream) { - int ret2; - - ret2 = atomisp_create_pipes_stream(&isp->asd); - if (ret2) { - dev_err(isp->dev, "%s error re-creating streams: %d\n", __func__, ret2); - if (!ret) - ret = ret2; - } - } + /* Streams were destroyed by atomisp_css_stop(), recreate them. */ + ret = atomisp_create_pipes_stream(&isp->asd); + if (ret) + dev_warn(isp->dev, "Recreating streams failed: %d\n", ret); - isp->isp_timeout = false; -out_unlock: mutex_unlock(&isp->mutex); } @@ -1902,9 +1760,6 @@ static int atomisp_s_parm(struct file *file, void *fh, case CI_MODE_STILL_CAPTURE: mode = ATOMISP_RUN_MODE_STILL_CAPTURE; break; - case CI_MODE_CONTINUOUS: - mode = ATOMISP_RUN_MODE_CONTINUOUS_CAPTURE; - break; case CI_MODE_PREVIEW: mode = ATOMISP_RUN_MODE_PREVIEW; break; @@ -1923,14 +1778,8 @@ static long atomisp_vidioc_default(struct file *file, void *fh, struct video_device *vdev = video_devdata(file); struct atomisp_device *isp = video_get_drvdata(vdev); struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd; - struct v4l2_subdev *motor; int err; - if (!IS_ISP2401) - motor = isp->inputs[asd->input_curr].motor; - else - motor = isp->motor; - switch (cmd) { case ATOMISP_IOC_S_SENSOR_RUNMODE: if (IS_ISP2401) @@ -2081,31 +1930,10 @@ static long atomisp_vidioc_default(struct file *file, void *fh, err = atomisp_fixed_pattern_table(asd, arg); break; - case ATOMISP_IOC_G_MOTOR_PRIV_INT_DATA: - if (motor) - err = v4l2_subdev_call(motor, core, ioctl, cmd, arg); - else - err = v4l2_subdev_call(isp->inputs[asd->input_curr].camera, - core, ioctl, cmd, arg); - break; - case ATOMISP_IOC_S_EXPOSURE: - case ATOMISP_IOC_G_SENSOR_CALIBRATION_GROUP: - case ATOMISP_IOC_G_SENSOR_PRIV_INT_DATA: - case ATOMISP_IOC_G_SENSOR_AE_BRACKETING_INFO: - case ATOMISP_IOC_S_SENSOR_AE_BRACKETING_MODE: - case ATOMISP_IOC_G_SENSOR_AE_BRACKETING_MODE: - case ATOMISP_IOC_S_SENSOR_AE_BRACKETING_LUT: err = v4l2_subdev_call(isp->inputs[asd->input_curr].camera, core, ioctl, cmd, arg); break; - case ATOMISP_IOC_G_UPDATE_EXPOSURE: - if (IS_ISP2401) - err = v4l2_subdev_call(isp->inputs[asd->input_curr].camera, - core, ioctl, cmd, arg); - else - err = -EINVAL; - break; case ATOMISP_IOC_S_ISP_SHD_TAB: err = atomisp_set_shading_table(asd, arg); @@ -2123,12 +1951,6 @@ static long atomisp_vidioc_default(struct file *file, void *fh, err = atomisp_set_parameters(vdev, arg); break; - case ATOMISP_IOC_G_METADATA: - err = atomisp_get_metadata(asd, 0, arg); - break; - case ATOMISP_IOC_G_METADATA_BY_TYPE: - err = atomisp_get_metadata_by_type(asd, 0, arg); - break; case ATOMISP_IOC_EXT_ISP_CTRL: err = v4l2_subdev_call(isp->inputs[asd->input_curr].camera, core, ioctl, cmd, arg); @@ -2149,15 +1971,9 @@ static long atomisp_vidioc_default(struct file *file, void *fh, case ATOMISP_IOC_S_FORMATS_CONFIG: err = atomisp_formats(asd, 1, arg); break; - case ATOMISP_IOC_S_EXPOSURE_WINDOW: - err = atomisp_s_ae_window(asd, arg); - break; case ATOMISP_IOC_INJECT_A_FAKE_EVENT: err = atomisp_inject_a_fake_event(asd, arg); break; - case ATOMISP_IOC_G_INVALID_FRAME_NUM: - err = atomisp_get_invalid_frame_num(vdev, arg); - break; case ATOMISP_IOC_S_ARRAY_RESOLUTION: err = atomisp_set_array_res(asd, arg); break; diff --git a/drivers/staging/media/atomisp/pci/atomisp_ioctl.h b/drivers/staging/media/atomisp/pci/atomisp_ioctl.h index db6da77df06b727a4eca38b9156601dbe7eff65e..56d3df86c7064a98bd8f9bdf4301afb5cec165db 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_ioctl.h +++ b/drivers/staging/media/atomisp/pci/atomisp_ioctl.h @@ -42,13 +42,8 @@ int atomisp_alloc_css_stat_bufs(struct atomisp_sub_device *asd, int atomisp_start_streaming(struct vb2_queue *vq, unsigned int count); void atomisp_stop_streaming(struct vb2_queue *vq); -enum ia_css_pipe_id atomisp_get_css_pipe_id(struct atomisp_sub_device - *asd); - extern const struct v4l2_ioctl_ops atomisp_ioctl_ops; -unsigned int atomisp_streaming_count(struct atomisp_device *isp); - /* compat_ioctl for 32bit userland app and 64bit kernel */ long atomisp_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg); diff --git a/drivers/staging/media/atomisp/pci/atomisp_subdev.c b/drivers/staging/media/atomisp/pci/atomisp_subdev.c index a0acfdb87177665c18b88941f8b6646a2e72920f..45073e401bac486ca7932f91d123b811843d4a3d 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_subdev.c +++ b/drivers/staging/media/atomisp/pci/atomisp_subdev.c @@ -117,35 +117,19 @@ const struct atomisp_in_fmt_conv *atomisp_find_in_fmt_conv_by_atomisp_in_fmt( return NULL; } -bool atomisp_subdev_format_conversion(struct atomisp_sub_device *asd, - unsigned int source_pad) +bool atomisp_subdev_format_conversion(struct atomisp_sub_device *asd) { struct v4l2_mbus_framefmt *sink, *src; sink = atomisp_subdev_get_ffmt(&asd->subdev, NULL, - V4L2_SUBDEV_FORMAT_ACTIVE, - ATOMISP_SUBDEV_PAD_SINK); + V4L2_SUBDEV_FORMAT_ACTIVE, ATOMISP_SUBDEV_PAD_SINK); src = atomisp_subdev_get_ffmt(&asd->subdev, NULL, - V4L2_SUBDEV_FORMAT_ACTIVE, source_pad); + V4L2_SUBDEV_FORMAT_ACTIVE, ATOMISP_SUBDEV_PAD_SOURCE); return atomisp_is_mbuscode_raw(sink->code) && !atomisp_is_mbuscode_raw(src->code); } -uint16_t atomisp_subdev_source_pad(struct video_device *vdev) -{ - struct media_link *link; - u16 ret = 0; - - list_for_each_entry(link, &vdev->entity.links, list) { - if (link->source) { - ret = link->source->index; - break; - } - } - return ret; -} - /* * V4L2 subdev operations */ @@ -355,10 +339,7 @@ static const char *atomisp_pad_str(unsigned int pad) { static const char *const pad_str[] = { "ATOMISP_SUBDEV_PAD_SINK", - "ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE", - "ATOMISP_SUBDEV_PAD_SOURCE_VF", - "ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW", - "ATOMISP_SUBDEV_PAD_SOURCE_VIDEO", + "ATOMISP_SUBDEV_PAD_SOURCE", }; if (pad >= ARRAY_SIZE(pad_str)) @@ -376,9 +357,10 @@ int atomisp_subdev_set_selection(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *ffmt[ATOMISP_SUBDEV_PADS_NUM]; struct v4l2_rect *crop[ATOMISP_SUBDEV_PADS_NUM], *comp[ATOMISP_SUBDEV_PADS_NUM]; - unsigned int i; - unsigned int padding_w = pad_w; - unsigned int padding_h = pad_h; + + if ((pad == ATOMISP_SUBDEV_PAD_SINK && target != V4L2_SEL_TGT_CROP) || + (pad == ATOMISP_SUBDEV_PAD_SOURCE && target != V4L2_SEL_TGT_COMPOSE)) + return -EINVAL; isp_get_fmt_rect(sd, sd_state, which, ffmt, crop, comp); @@ -393,27 +375,17 @@ int atomisp_subdev_set_selection(struct v4l2_subdev *sd, r->width = rounddown(r->width, ATOM_ISP_STEP_WIDTH); r->height = rounddown(r->height, ATOM_ISP_STEP_HEIGHT); - switch (pad) { - case ATOMISP_SUBDEV_PAD_SINK: { + if (pad == ATOMISP_SUBDEV_PAD_SINK) { /* Only crop target supported on sink pad. */ unsigned int dvs_w, dvs_h; crop[pad]->width = ffmt[pad]->width; crop[pad]->height = ffmt[pad]->height; - /* Workaround for BYT 1080p perfectshot since the maxinum resolution of - * front camera ov2722 is 1932x1092 and cannot use pad_w > 12*/ - if (!strncmp(isp->inputs[isp_sd->input_curr].camera->name, - "ov2722", 6) && crop[pad]->height == 1092) { - padding_w = 12; - padding_h = 12; - } - - if (atomisp_subdev_format_conversion(isp_sd, - isp_sd->capture_pad) + if (atomisp_subdev_format_conversion(isp_sd) && crop[pad]->width && crop[pad]->height) { - crop[pad]->width -= padding_w; - crop[pad]->height -= padding_h; + crop[pad]->width -= isp_sd->sink_pad_padding_w; + crop[pad]->height -= isp_sd->sink_pad_padding_h; } if (isp_sd->params.video_dis_en && @@ -433,19 +405,15 @@ int atomisp_subdev_set_selection(struct v4l2_subdev *sd, crop[pad]->height = min(crop[pad]->height, r->height); if (!(flags & V4L2_SEL_FLAG_KEEP_CONFIG)) { - for (i = ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE; - i < ATOMISP_SUBDEV_PADS_NUM; i++) { - struct v4l2_rect tmp = *crop[pad]; - - atomisp_subdev_set_selection( - sd, sd_state, which, i, - V4L2_SEL_TGT_COMPOSE, - flags, &tmp); - } + struct v4l2_rect tmp = *crop[pad]; + + atomisp_subdev_set_selection(sd, sd_state, which, + ATOMISP_SUBDEV_PAD_SOURCE, + V4L2_SEL_TGT_COMPOSE, flags, &tmp); } if (which == V4L2_SUBDEV_FORMAT_TRY) - break; + goto get_rect; if (isp_sd->params.video_dis_en && isp_sd->run_mode->val == ATOMISP_RUN_MODE_VIDEO) { @@ -468,12 +436,8 @@ int atomisp_subdev_set_selection(struct v4l2_subdev *sd, ATOMISP_INPUT_STREAM_GENERAL, crop[pad]->width, crop[pad]->height); - break; - } - case ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE: - case ATOMISP_SUBDEV_PAD_SOURCE_VIDEO: { + } else if (isp_sd->run_mode->val != ATOMISP_RUN_MODE_PREVIEW) { /* Only compose target is supported on source pads. */ - if (isp_sd->vfpp->val == ATOMISP_VFPP_DISABLE_LOWLAT) { /* Scaling is disabled in this mode */ r->width = crop[ATOMISP_SUBDEV_PAD_SINK]->width; @@ -492,7 +456,7 @@ int atomisp_subdev_set_selection(struct v4l2_subdev *sd, if (r->width == 0 || r->height == 0 || crop[ATOMISP_SUBDEV_PAD_SINK]->width == 0 || crop[ATOMISP_SUBDEV_PAD_SINK]->height == 0) - break; + goto get_rect; /* * do cropping on sensor input if ratio of required resolution * is different with sensor output resolution ratio: @@ -522,18 +486,12 @@ int atomisp_subdev_set_selection(struct v4l2_subdev *sd, rounddown(crop[ATOMISP_SUBDEV_PAD_SINK]-> width * r->height / r->width, ATOM_ISP_STEP_WIDTH)); - - break; - } - case ATOMISP_SUBDEV_PAD_SOURCE_VF: - case ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW: + } else { comp[pad]->width = r->width; comp[pad]->height = r->height; - break; - default: - return -EINVAL; } +get_rect: /* Set format dimensions on non-sink pads as well. */ if (pad != ATOMISP_SUBDEV_PAD_SINK) { ffmt[pad]->width = comp[pad]->width; @@ -612,10 +570,7 @@ void atomisp_subdev_set_ffmt(struct v4l2_subdev *sd, break; } - case ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE: - case ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW: - case ATOMISP_SUBDEV_PAD_SOURCE_VF: - case ATOMISP_SUBDEV_PAD_SOURCE_VIDEO: + case ATOMISP_SUBDEV_PAD_SOURCE: __ffmt->code = ffmt->code; break; } @@ -755,11 +710,9 @@ static const struct v4l2_ctrl_ops ctrl_ops = { }; static const char *const ctrl_run_mode_menu[] = { - NULL, - "Video", - "Still capture", - "Continuous capture", - "Preview", + [ATOMISP_RUN_MODE_VIDEO] = "Video", + [ATOMISP_RUN_MODE_STILL_CAPTURE] = "Still capture", + [ATOMISP_RUN_MODE_PREVIEW] = "Preview", }; static const struct v4l2_ctrl_config ctrl_run_mode = { @@ -767,9 +720,9 @@ static const struct v4l2_ctrl_config ctrl_run_mode = { .id = V4L2_CID_RUN_MODE, .name = "Atomisp run mode", .type = V4L2_CTRL_TYPE_MENU, - .min = 1, - .def = 1, - .max = 4, + .min = ATOMISP_RUN_MODE_MIN, + .def = ATOMISP_RUN_MODE_PREVIEW, + .max = ATOMISP_RUN_MODE_MAX, .qmenu = ctrl_run_mode_menu, }; @@ -921,23 +874,13 @@ static int isp_subdev_init_entities(struct atomisp_sub_device *asd) sprintf(sd->name, "ATOMISP_SUBDEV"); v4l2_set_subdevdata(sd, asd); sd->flags |= V4L2_SUBDEV_FL_HAS_EVENTS | V4L2_SUBDEV_FL_HAS_DEVNODE; + sd->devnode = &asd->video_out.vdev; pads[ATOMISP_SUBDEV_PAD_SINK].flags = MEDIA_PAD_FL_SINK; - pads[ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW].flags = MEDIA_PAD_FL_SOURCE; - pads[ATOMISP_SUBDEV_PAD_SOURCE_VF].flags = MEDIA_PAD_FL_SOURCE; - pads[ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE].flags = MEDIA_PAD_FL_SOURCE; - pads[ATOMISP_SUBDEV_PAD_SOURCE_VIDEO].flags = MEDIA_PAD_FL_SOURCE; - - asd->fmt[ATOMISP_SUBDEV_PAD_SINK].fmt.code = - MEDIA_BUS_FMT_SBGGR10_1X10; - asd->fmt[ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW].fmt.code = - MEDIA_BUS_FMT_SBGGR10_1X10; - asd->fmt[ATOMISP_SUBDEV_PAD_SOURCE_VF].fmt.code = - MEDIA_BUS_FMT_SBGGR10_1X10; - asd->fmt[ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE].fmt.code = - MEDIA_BUS_FMT_SBGGR10_1X10; - asd->fmt[ATOMISP_SUBDEV_PAD_SOURCE_VIDEO].fmt.code = - MEDIA_BUS_FMT_SBGGR10_1X10; + pads[ATOMISP_SUBDEV_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE; + + asd->fmt[ATOMISP_SUBDEV_PAD_SINK].fmt.code = MEDIA_BUS_FMT_SBGGR10_1X10; + asd->fmt[ATOMISP_SUBDEV_PAD_SOURCE].fmt.code = MEDIA_BUS_FMT_SBGGR10_1X10; me->ops = &isp_subdev_media_ops; me->function = MEDIA_ENT_F_PROC_VIDEO_ISP; @@ -945,43 +888,11 @@ static int isp_subdev_init_entities(struct atomisp_sub_device *asd) if (ret < 0) return ret; - ret = atomisp_init_subdev_pipe(asd, &asd->video_out_preview, - V4L2_BUF_TYPE_VIDEO_CAPTURE); + ret = atomisp_init_subdev_pipe(asd, &asd->video_out, V4L2_BUF_TYPE_VIDEO_CAPTURE); if (ret) return ret; - ret = atomisp_init_subdev_pipe(asd, &asd->video_out_vf, - V4L2_BUF_TYPE_VIDEO_CAPTURE); - if (ret) - return ret; - - ret = atomisp_init_subdev_pipe(asd, &asd->video_out_capture, - V4L2_BUF_TYPE_VIDEO_CAPTURE); - if (ret) - return ret; - - ret = atomisp_init_subdev_pipe(asd, &asd->video_out_video_capture, - V4L2_BUF_TYPE_VIDEO_CAPTURE); - if (ret) - return ret; - - ret = atomisp_video_init(&asd->video_out_capture, "CAPTURE", - ATOMISP_RUN_MODE_STILL_CAPTURE); - if (ret < 0) - return ret; - - ret = atomisp_video_init(&asd->video_out_vf, "VIEWFINDER", - ATOMISP_RUN_MODE_CONTINUOUS_CAPTURE); - if (ret < 0) - return ret; - - ret = atomisp_video_init(&asd->video_out_preview, "PREVIEW", - ATOMISP_RUN_MODE_PREVIEW); - if (ret < 0) - return ret; - - ret = atomisp_video_init(&asd->video_out_video_capture, "VIDEO", - ATOMISP_RUN_MODE_VIDEO); + ret = atomisp_video_init(&asd->video_out); if (ret < 0) return ret; @@ -1016,57 +927,6 @@ static int isp_subdev_init_entities(struct atomisp_sub_device *asd) return asd->ctrl_handler.error; } -int atomisp_create_pads_links(struct atomisp_device *isp) -{ - int i, ret; - - for (i = 0; i < ATOMISP_CAMERA_NR_PORTS; i++) { - ret = media_create_pad_link(&isp->csi2_port[i].subdev.entity, - CSI2_PAD_SOURCE, &isp->asd.subdev.entity, - ATOMISP_SUBDEV_PAD_SINK, 0); - if (ret < 0) - return ret; - } - - for (i = 0; i < isp->input_cnt; i++) { - /* Don't create links for the test-pattern-generator */ - if (isp->inputs[i].type == TEST_PATTERN) - continue; - - ret = media_create_pad_link(&isp->inputs[i].camera->entity, 0, - &isp->csi2_port[isp->inputs[i]. - port].subdev.entity, - CSI2_PAD_SINK, - MEDIA_LNK_FL_ENABLED | - MEDIA_LNK_FL_IMMUTABLE); - if (ret < 0) - return ret; - } - - ret = media_create_pad_link(&isp->asd.subdev.entity, - ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW, - &isp->asd.video_out_preview.vdev.entity, 0, 0); - if (ret < 0) - return ret; - ret = media_create_pad_link(&isp->asd.subdev.entity, - ATOMISP_SUBDEV_PAD_SOURCE_VF, - &isp->asd.video_out_vf.vdev.entity, 0, 0); - if (ret < 0) - return ret; - ret = media_create_pad_link(&isp->asd.subdev.entity, - ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE, - &isp->asd.video_out_capture.vdev.entity, 0, 0); - if (ret < 0) - return ret; - ret = media_create_pad_link(&isp->asd.subdev.entity, - ATOMISP_SUBDEV_PAD_SOURCE_VIDEO, - &isp->asd.video_out_video_capture.vdev.entity, 0, 0); - if (ret < 0) - return ret; - - return 0; -} - static void atomisp_subdev_cleanup_entities(struct atomisp_sub_device *asd) { v4l2_ctrl_handler_free(&asd->ctrl_handler); @@ -1092,10 +952,7 @@ void atomisp_subdev_unregister_entities(struct atomisp_sub_device *asd) { atomisp_subdev_cleanup_entities(asd); v4l2_device_unregister_subdev(&asd->subdev); - atomisp_video_unregister(&asd->video_out_preview); - atomisp_video_unregister(&asd->video_out_vf); - atomisp_video_unregister(&asd->video_out_capture); - atomisp_video_unregister(&asd->video_out_video_capture); + atomisp_video_unregister(&asd->video_out); } int atomisp_subdev_register_subdev(struct atomisp_sub_device *asd, @@ -1104,51 +961,6 @@ int atomisp_subdev_register_subdev(struct atomisp_sub_device *asd, return v4l2_device_register_subdev(vdev, &asd->subdev); } -int atomisp_subdev_register_video_nodes(struct atomisp_sub_device *asd, - struct v4l2_device *vdev) -{ - int ret; - - /* - * FIXME: check if all device caps are properly initialized. - * Should any of those use V4L2_CAP_META_CAPTURE? Probably yes. - */ - - asd->video_out_preview.vdev.v4l2_dev = vdev; - asd->video_out_preview.vdev.device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; - ret = video_register_device(&asd->video_out_preview.vdev, - VFL_TYPE_VIDEO, -1); - if (ret < 0) - goto error; - - asd->video_out_capture.vdev.v4l2_dev = vdev; - asd->video_out_capture.vdev.device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; - ret = video_register_device(&asd->video_out_capture.vdev, - VFL_TYPE_VIDEO, -1); - if (ret < 0) - goto error; - - asd->video_out_vf.vdev.v4l2_dev = vdev; - asd->video_out_vf.vdev.device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; - ret = video_register_device(&asd->video_out_vf.vdev, - VFL_TYPE_VIDEO, -1); - if (ret < 0) - goto error; - - asd->video_out_video_capture.vdev.v4l2_dev = vdev; - asd->video_out_video_capture.vdev.device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; - ret = video_register_device(&asd->video_out_video_capture.vdev, - VFL_TYPE_VIDEO, -1); - if (ret < 0) - goto error; - - return 0; - -error: - atomisp_subdev_unregister_entities(asd); - return ret; -} - /* * atomisp_subdev_init - ISP Subdevice initialization. * @dev: Device pointer specific to the ATOM ISP. diff --git a/drivers/staging/media/atomisp/pci/atomisp_subdev.h b/drivers/staging/media/atomisp/pci/atomisp_subdev.h index fee663bc415a120ca981694f97d2fc038913b80c..9a04511b9efd1afb74fac4c38b23801a93be1c1f 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_subdev.h +++ b/drivers/staging/media/atomisp/pci/atomisp_subdev.h @@ -32,15 +32,8 @@ #define ATOMISP_MAX_EXP_ID (250) #define ATOMISP_SUBDEV_PAD_SINK 0 -/* capture output for still frames */ -#define ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE 1 -/* viewfinder output for downscaled capture output */ -#define ATOMISP_SUBDEV_PAD_SOURCE_VF 2 -/* preview output for display */ -#define ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW 3 -/* main output for video pipeline */ -#define ATOMISP_SUBDEV_PAD_SOURCE_VIDEO 4 -#define ATOMISP_SUBDEV_PADS_NUM 5 +#define ATOMISP_SUBDEV_PAD_SOURCE 1 +#define ATOMISP_SUBDEV_PADS_NUM 2 struct atomisp_in_fmt_conv { u32 code; @@ -74,8 +67,6 @@ struct atomisp_video_pipe { /* Filled through atomisp_get_css_frame_info() on queue setup */ struct ia_css_frame_info frame_info; - /* Store here the initial run mode */ - unsigned int default_run_mode; /* Set from streamoff to disallow queuing further buffers in CSS */ bool stopping; @@ -248,15 +239,12 @@ struct atomisp_sub_device { struct v4l2_subdev subdev; struct media_pad pads[ATOMISP_SUBDEV_PADS_NUM]; struct atomisp_pad_format fmt[ATOMISP_SUBDEV_PADS_NUM]; - u16 capture_pad; /* main capture pad; defines much of isp config */ + /* Padding for currently set sink-pad fmt */ + u32 sink_pad_padding_w; + u32 sink_pad_padding_h; unsigned int output; - struct atomisp_video_pipe video_out_capture; /* capture output */ - struct atomisp_video_pipe video_out_vf; /* viewfinder output */ - struct atomisp_video_pipe video_out_preview; /* preview output */ - /* video pipe main output */ - struct atomisp_video_pipe video_out_video_capture; - /* struct isp_subdev_params params; */ + struct atomisp_video_pipe video_out; struct atomisp_device *isp; struct v4l2_ctrl_handler ctrl_handler; struct v4l2_ctrl *run_mode; @@ -312,13 +300,12 @@ struct atomisp_sub_device { * Writers of streaming must hold both isp->mutex and isp->lock. * Readers of streaming need to hold only one of the two locks. */ - unsigned int streaming; + bool streaming; bool stream_prepared; /* whether css stream is created */ + bool recreate_streams_on_resume; unsigned int latest_preview_exp_id; /* CSS ZSL/SDV raw buffer id */ - unsigned int mipi_frame_size; - bool copy_mode; /* CSI2+ use copy mode */ int raw_buffer_bitmap[ATOMISP_MAX_EXP_ID / 32 + @@ -352,9 +339,7 @@ const struct atomisp_in_fmt_conv atomisp_in_fmt); const struct atomisp_in_fmt_conv *atomisp_find_in_fmt_conv_compressed(u32 code); -bool atomisp_subdev_format_conversion(struct atomisp_sub_device *asd, - unsigned int source_pad); -uint16_t atomisp_subdev_source_pad(struct video_device *vdev); +bool atomisp_subdev_format_conversion(struct atomisp_sub_device *asd); /* Get pointer to appropriate format */ struct v4l2_mbus_framefmt @@ -382,10 +367,7 @@ void atomisp_subdev_cleanup_pending_events(struct atomisp_sub_device *asd); void atomisp_subdev_unregister_entities(struct atomisp_sub_device *asd); int atomisp_subdev_register_subdev(struct atomisp_sub_device *asd, struct v4l2_device *vdev); -int atomisp_subdev_register_video_nodes(struct atomisp_sub_device *asd, - struct v4l2_device *vdev); int atomisp_subdev_init(struct atomisp_device *isp); void atomisp_subdev_cleanup(struct atomisp_device *isp); -int atomisp_create_pads_links(struct atomisp_device *isp); #endif /* __ATOMISP_SUBDEV_H__ */ diff --git a/drivers/staging/media/atomisp/pci/atomisp_v4l2.c b/drivers/staging/media/atomisp/pci/atomisp_v4l2.c index 3f315dabbeeb4c9ad5ca105b3489a9c378e91fe7..c43b916a006ee763d12cd12ff58b79d0e8b22140 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_v4l2.c +++ b/drivers/staging/media/atomisp/pci/atomisp_v4l2.c @@ -27,6 +27,7 @@ #include #include #include +#include #include @@ -119,13 +120,6 @@ static const struct atomisp_freq_scaling_rule dfs_rules_merr[] = { .isp_freq = ISP_FREQ_400MHZ, .run_mode = ATOMISP_RUN_MODE_STILL_CAPTURE, }, - { - .width = ISP_FREQ_RULE_ANY, - .height = ISP_FREQ_RULE_ANY, - .fps = ISP_FREQ_RULE_ANY, - .isp_freq = ISP_FREQ_400MHZ, - .run_mode = ATOMISP_RUN_MODE_CONTINUOUS_CAPTURE, - }, { .width = ISP_FREQ_RULE_ANY, .height = ISP_FREQ_RULE_ANY, @@ -133,13 +127,6 @@ static const struct atomisp_freq_scaling_rule dfs_rules_merr[] = { .isp_freq = ISP_FREQ_400MHZ, .run_mode = ATOMISP_RUN_MODE_PREVIEW, }, - { - .width = ISP_FREQ_RULE_ANY, - .height = ISP_FREQ_RULE_ANY, - .fps = ISP_FREQ_RULE_ANY, - .isp_freq = ISP_FREQ_457MHZ, - .run_mode = ATOMISP_RUN_MODE_SDV, - }, }; /* Merrifield and Moorefield DFS rules */ @@ -166,13 +153,6 @@ static const struct atomisp_freq_scaling_rule dfs_rules_merr_1179[] = { .isp_freq = ISP_FREQ_400MHZ, .run_mode = ATOMISP_RUN_MODE_STILL_CAPTURE, }, - { - .width = ISP_FREQ_RULE_ANY, - .height = ISP_FREQ_RULE_ANY, - .fps = ISP_FREQ_RULE_ANY, - .isp_freq = ISP_FREQ_400MHZ, - .run_mode = ATOMISP_RUN_MODE_CONTINUOUS_CAPTURE, - }, { .width = ISP_FREQ_RULE_ANY, .height = ISP_FREQ_RULE_ANY, @@ -180,13 +160,6 @@ static const struct atomisp_freq_scaling_rule dfs_rules_merr_1179[] = { .isp_freq = ISP_FREQ_400MHZ, .run_mode = ATOMISP_RUN_MODE_PREVIEW, }, - { - .width = ISP_FREQ_RULE_ANY, - .height = ISP_FREQ_RULE_ANY, - .fps = ISP_FREQ_RULE_ANY, - .isp_freq = ISP_FREQ_400MHZ, - .run_mode = ATOMISP_RUN_MODE_SDV, - }, }; static const struct atomisp_dfs_config dfs_config_merr_1179 = { @@ -247,13 +220,6 @@ static const struct atomisp_freq_scaling_rule dfs_rules_merr_117a[] = { .isp_freq = ISP_FREQ_400MHZ, .run_mode = ATOMISP_RUN_MODE_STILL_CAPTURE, }, - { - .width = ISP_FREQ_RULE_ANY, - .height = ISP_FREQ_RULE_ANY, - .fps = ISP_FREQ_RULE_ANY, - .isp_freq = ISP_FREQ_400MHZ, - .run_mode = ATOMISP_RUN_MODE_CONTINUOUS_CAPTURE, - }, { .width = ISP_FREQ_RULE_ANY, .height = ISP_FREQ_RULE_ANY, @@ -261,13 +227,6 @@ static const struct atomisp_freq_scaling_rule dfs_rules_merr_117a[] = { .isp_freq = ISP_FREQ_200MHZ, .run_mode = ATOMISP_RUN_MODE_PREVIEW, }, - { - .width = ISP_FREQ_RULE_ANY, - .height = ISP_FREQ_RULE_ANY, - .fps = ISP_FREQ_RULE_ANY, - .isp_freq = ISP_FREQ_400MHZ, - .run_mode = ATOMISP_RUN_MODE_SDV, - }, }; static struct atomisp_dfs_config dfs_config_merr_117a = { @@ -293,13 +252,6 @@ static const struct atomisp_freq_scaling_rule dfs_rules_byt[] = { .isp_freq = ISP_FREQ_400MHZ, .run_mode = ATOMISP_RUN_MODE_STILL_CAPTURE, }, - { - .width = ISP_FREQ_RULE_ANY, - .height = ISP_FREQ_RULE_ANY, - .fps = ISP_FREQ_RULE_ANY, - .isp_freq = ISP_FREQ_400MHZ, - .run_mode = ATOMISP_RUN_MODE_CONTINUOUS_CAPTURE, - }, { .width = ISP_FREQ_RULE_ANY, .height = ISP_FREQ_RULE_ANY, @@ -307,13 +259,6 @@ static const struct atomisp_freq_scaling_rule dfs_rules_byt[] = { .isp_freq = ISP_FREQ_400MHZ, .run_mode = ATOMISP_RUN_MODE_PREVIEW, }, - { - .width = ISP_FREQ_RULE_ANY, - .height = ISP_FREQ_RULE_ANY, - .fps = ISP_FREQ_RULE_ANY, - .isp_freq = ISP_FREQ_400MHZ, - .run_mode = ATOMISP_RUN_MODE_SDV, - }, }; static const struct atomisp_dfs_config dfs_config_byt = { @@ -339,13 +284,6 @@ static const struct atomisp_freq_scaling_rule dfs_rules_cht[] = { .isp_freq = ISP_FREQ_356MHZ, .run_mode = ATOMISP_RUN_MODE_STILL_CAPTURE, }, - { - .width = ISP_FREQ_RULE_ANY, - .height = ISP_FREQ_RULE_ANY, - .fps = ISP_FREQ_RULE_ANY, - .isp_freq = ISP_FREQ_320MHZ, - .run_mode = ATOMISP_RUN_MODE_CONTINUOUS_CAPTURE, - }, { .width = ISP_FREQ_RULE_ANY, .height = ISP_FREQ_RULE_ANY, @@ -353,20 +291,6 @@ static const struct atomisp_freq_scaling_rule dfs_rules_cht[] = { .isp_freq = ISP_FREQ_320MHZ, .run_mode = ATOMISP_RUN_MODE_PREVIEW, }, - { - .width = 1280, - .height = 720, - .fps = ISP_FREQ_RULE_ANY, - .isp_freq = ISP_FREQ_320MHZ, - .run_mode = ATOMISP_RUN_MODE_SDV, - }, - { - .width = ISP_FREQ_RULE_ANY, - .height = ISP_FREQ_RULE_ANY, - .fps = ISP_FREQ_RULE_ANY, - .isp_freq = ISP_FREQ_356MHZ, - .run_mode = ATOMISP_RUN_MODE_SDV, - }, }; static const struct atomisp_freq_scaling_rule dfs_rules_cht_soc[] = { @@ -384,13 +308,6 @@ static const struct atomisp_freq_scaling_rule dfs_rules_cht_soc[] = { .isp_freq = ISP_FREQ_356MHZ, .run_mode = ATOMISP_RUN_MODE_STILL_CAPTURE, }, - { - .width = ISP_FREQ_RULE_ANY, - .height = ISP_FREQ_RULE_ANY, - .fps = ISP_FREQ_RULE_ANY, - .isp_freq = ISP_FREQ_320MHZ, - .run_mode = ATOMISP_RUN_MODE_CONTINUOUS_CAPTURE, - }, { .width = ISP_FREQ_RULE_ANY, .height = ISP_FREQ_RULE_ANY, @@ -398,13 +315,6 @@ static const struct atomisp_freq_scaling_rule dfs_rules_cht_soc[] = { .isp_freq = ISP_FREQ_320MHZ, .run_mode = ATOMISP_RUN_MODE_PREVIEW, }, - { - .width = ISP_FREQ_RULE_ANY, - .height = ISP_FREQ_RULE_ANY, - .fps = ISP_FREQ_RULE_ANY, - .isp_freq = ISP_FREQ_356MHZ, - .run_mode = ATOMISP_RUN_MODE_SDV, - }, }; static const struct atomisp_dfs_config dfs_config_cht = { @@ -424,34 +334,22 @@ const struct atomisp_dfs_config dfs_config_cht_soc = { .dfs_table_size = ARRAY_SIZE(dfs_rules_cht_soc), }; -int atomisp_video_init(struct atomisp_video_pipe *video, const char *name, - unsigned int run_mode) +int atomisp_video_init(struct atomisp_video_pipe *video) { int ret; - const char *direction; - - switch (video->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - direction = "output"; - video->pad.flags = MEDIA_PAD_FL_SINK; - video->vdev.fops = &atomisp_fops; - video->vdev.ioctl_ops = &atomisp_ioctl_ops; - video->vdev.lock = &video->isp->mutex; - break; - default: - return -EINVAL; - } + video->pad.flags = MEDIA_PAD_FL_SINK; ret = media_entity_pads_init(&video->vdev.entity, 1, &video->pad); if (ret < 0) return ret; /* Initialize the video device. */ - snprintf(video->vdev.name, sizeof(video->vdev.name), - "ATOMISP ISP %s %s", name, direction); + strscpy(video->vdev.name, "ATOMISP video output", sizeof(video->vdev.name)); + video->vdev.fops = &atomisp_fops; + video->vdev.ioctl_ops = &atomisp_ioctl_ops; + video->vdev.lock = &video->isp->mutex; video->vdev.release = video_device_release_empty; video_set_drvdata(&video->vdev, video->isp); - video->default_run_mode = run_mode; return 0; } @@ -755,15 +653,9 @@ static int atomisp_suspend(struct device *dev) dev_get_drvdata(dev); unsigned long flags; - /* - * FIXME: Suspend is not supported by sensors. Abort if any video - * node was opened. - */ - if (atomisp_dev_users(isp)) - return -EBUSY; - + /* FIXME: Suspend is not supported by sensors. Abort if streaming. */ spin_lock_irqsave(&isp->lock, flags); - if (isp->asd.streaming != ATOMISP_DEVICE_STREAMING_DISABLED) { + if (isp->asd.streaming) { spin_unlock_irqrestore(&isp->lock, flags); dev_err(isp->dev, "atomisp cannot suspend at this time.\n"); return -EINVAL; @@ -772,12 +664,25 @@ static int atomisp_suspend(struct device *dev) pm_runtime_resume(dev); + isp->asd.recreate_streams_on_resume = isp->asd.stream_prepared; + atomisp_destroy_pipes_stream(&isp->asd); + return atomisp_power_off(dev); } static int atomisp_resume(struct device *dev) { - return atomisp_power_on(dev); + struct atomisp_device *isp = dev_get_drvdata(dev); + int ret; + + ret = atomisp_power_on(dev); + if (ret) + return ret; + + if (isp->asd.recreate_streams_on_resume) + ret = atomisp_create_pipes_stream(&isp->asd); + + return ret; } int atomisp_csi_lane_config(struct atomisp_device *isp) @@ -785,7 +690,7 @@ int atomisp_csi_lane_config(struct atomisp_device *isp) struct pci_dev *pdev = to_pci_dev(isp->dev); static const struct { u8 code; - u8 lanes[MRFLD_PORT_NUM]; + u8 lanes[N_MIPI_PORT_ID]; } portconfigs[] = { /* Tangier/Merrifield available lane configurations */ { 0x00, { 4, 1, 0 } }, /* 00000 */ @@ -809,7 +714,6 @@ int atomisp_csi_lane_config(struct atomisp_device *isp) }; unsigned int i, j; - u8 sensor_lanes[MRFLD_PORT_NUM] = { 0 }; u32 csi_control; int nportconfigs; u32 port_config_mask; @@ -837,41 +741,13 @@ int atomisp_csi_lane_config(struct atomisp_device *isp) nportconfigs = ARRAY_SIZE(portconfigs); } - for (i = 0; i < isp->input_cnt; i++) { - struct camera_mipi_info *mipi_info; - - if (isp->inputs[i].type != RAW_CAMERA) - continue; - - mipi_info = atomisp_to_sensor_mipi_info(isp->inputs[i].camera); - if (!mipi_info) - continue; - - switch (mipi_info->port) { - case ATOMISP_CAMERA_PORT_PRIMARY: - sensor_lanes[0] = mipi_info->num_lanes; - break; - case ATOMISP_CAMERA_PORT_SECONDARY: - sensor_lanes[1] = mipi_info->num_lanes; - break; - case ATOMISP_CAMERA_PORT_TERTIARY: - sensor_lanes[2] = mipi_info->num_lanes; - break; - default: - dev_err(isp->dev, - "%s: invalid port: %d for the %dth sensor\n", - __func__, mipi_info->port, i); - return -EINVAL; - } - } - for (i = 0; i < nportconfigs; i++) { - for (j = 0; j < MRFLD_PORT_NUM; j++) - if (sensor_lanes[j] && - sensor_lanes[j] != portconfigs[i].lanes[j]) + for (j = 0; j < N_MIPI_PORT_ID; j++) + if (isp->sensor_lanes[j] && + isp->sensor_lanes[j] != portconfigs[i].lanes[j]) break; - if (j == MRFLD_PORT_NUM) + if (j == N_MIPI_PORT_ID) break; /* Found matching setting */ } @@ -879,7 +755,7 @@ int atomisp_csi_lane_config(struct atomisp_device *isp) dev_err(isp->dev, "%s: could not find the CSI port setting for %d-%d-%d\n", __func__, - sensor_lanes[0], sensor_lanes[1], sensor_lanes[2]); + isp->sensor_lanes[0], isp->sensor_lanes[1], isp->sensor_lanes[2]); return -EINVAL; } @@ -907,7 +783,11 @@ static int atomisp_subdev_probe(struct atomisp_device *isp) { const struct atomisp_platform_data *pdata; struct intel_v4l2_subdev_table *subdevs; - int ret, raw_index = -1, count; + int ret, mipi_port; + + ret = atomisp_csi2_bridge_parse_firmware(isp); + if (ret) + return ret; pdata = atomisp_get_platform_data(); if (!pdata) { @@ -915,23 +795,12 @@ static int atomisp_subdev_probe(struct atomisp_device *isp) return 0; } - /* FIXME: should return -EPROBE_DEFER if not all subdevs were probed */ - for (count = 0; count < SUBDEV_WAIT_TIMEOUT_MAX_COUNT; count++) { - int camera_count = 0; - - for (subdevs = pdata->subdevs; subdevs->type; ++subdevs) { - if (subdevs->type == RAW_CAMERA) - camera_count++; - } - if (camera_count) - break; - msleep(SUBDEV_WAIT_TIMEOUT); - } - /* Wait more time to give more time for subdev init code to finish */ - msleep(5 * SUBDEV_WAIT_TIMEOUT); - - /* FIXME: should, instead, use I2C probe */ - + /* + * TODO: this is left here for now to allow testing atomisp-sensor + * drivers which are still using the atomisp_gmin_platform infra before + * converting them to standard v4l2 sensor drivers using runtime-pm + + * ACPI for pm and v4l2_async_register_subdev_sensor() registration. + */ for (subdevs = pdata->subdevs; subdevs->type; ++subdevs) { ret = v4l2_device_register_subdev(&isp->v4l2_dev, subdevs->subdev); if (ret) @@ -939,25 +808,20 @@ static int atomisp_subdev_probe(struct atomisp_device *isp) switch (subdevs->type) { case RAW_CAMERA: - dev_dbg(isp->dev, "raw_index: %d\n", raw_index); - raw_index = isp->input_cnt; - if (isp->input_cnt >= ATOM_ISP_MAX_INPUTS) { - dev_warn(isp->dev, - "too many atomisp inputs, ignored\n"); + if (subdevs->port >= ATOMISP_CAMERA_NR_PORTS) { + dev_err(isp->dev, "port %d not supported\n", subdevs->port); + break; + } + + if (isp->sensor_subdevs[subdevs->port]) { + dev_err(isp->dev, "port %d already has a sensor attached\n", + subdevs->port); break; } - isp->inputs[isp->input_cnt].type = subdevs->type; - isp->inputs[isp->input_cnt].port = subdevs->port; - isp->inputs[isp->input_cnt].camera = subdevs->subdev; - isp->inputs[isp->input_cnt].sensor_index = 0; - /* - * initialize the subdev frame size, then next we can - * judge whether frame_size store effective value via - * pixel_format. - */ - isp->inputs[isp->input_cnt].frame_size.pixel_format = 0; - isp->input_cnt++; + mipi_port = atomisp_port_to_mipi_port(isp, subdevs->port); + isp->sensor_lanes[mipi_port] = subdevs->lanes; + isp->sensor_subdevs[subdevs->port] = subdevs->subdev; break; case CAMERA_MOTOR: if (isp->motor) { @@ -979,21 +843,6 @@ static int atomisp_subdev_probe(struct atomisp_device *isp) } } - /* - * HACK: Currently VCM belongs to primary sensor only, but correct - * approach must be to acquire from platform code which sensor - * owns it. - */ - if (isp->motor && raw_index >= 0) - isp->inputs[raw_index].motor = isp->motor; - - /* Proceed even if no modules detected. For COS mode and no modules. */ - if (!isp->input_cnt) - dev_warn(isp->dev, "no camera attached or fail to detect\n"); - else - dev_info(isp->dev, "detected %d camera sensors\n", - isp->input_cnt); - return atomisp_csi_lane_config(isp); } @@ -1067,29 +916,8 @@ static int atomisp_register_entities(struct atomisp_device *isp) goto subdev_register_failed; } - for (i = 0; i < isp->input_cnt; i++) { - if (isp->inputs[i].port >= ATOMISP_CAMERA_NR_PORTS) { - dev_err(isp->dev, "isp->inputs port %d not supported\n", - isp->inputs[i].port); - ret = -EINVAL; - goto link_failed; - } - } - - if (isp->input_cnt < ATOM_ISP_MAX_INPUTS) { - dev_dbg(isp->dev, - "TPG detected, camera_cnt: %d\n", isp->input_cnt); - isp->inputs[isp->input_cnt].type = TEST_PATTERN; - isp->inputs[isp->input_cnt].port = -1; - isp->inputs[isp->input_cnt++].camera = &isp->tpg.sd; - } else { - dev_warn(isp->dev, "too many atomisp inputs, TPG ignored.\n"); - } - return 0; -link_failed: - atomisp_subdev_unregister_entities(&isp->asd); subdev_register_failed: atomisp_tpg_unregister_entities(&isp->tpg); tpg_register_failed: @@ -1103,15 +931,152 @@ static int atomisp_register_entities(struct atomisp_device *isp) return ret; } -static int atomisp_register_device_nodes(struct atomisp_device *isp) +static void atomisp_init_sensor(struct atomisp_input_subdev *input) +{ + struct v4l2_subdev_mbus_code_enum mbus_code_enum = { }; + struct v4l2_subdev_frame_size_enum fse = { }; + struct v4l2_subdev_state sd_state = { + .pads = &input->pad_cfg, + }; + struct v4l2_subdev_selection sel = { }; + int i, err; + + mbus_code_enum.which = V4L2_SUBDEV_FORMAT_ACTIVE; + err = v4l2_subdev_call(input->camera, pad, enum_mbus_code, NULL, &mbus_code_enum); + if (!err) + input->code = mbus_code_enum.code; + + sel.which = V4L2_SUBDEV_FORMAT_ACTIVE; + sel.target = V4L2_SEL_TGT_NATIVE_SIZE; + err = v4l2_subdev_call(input->camera, pad, get_selection, NULL, &sel); + if (err) + return; + + input->native_rect = sel.r; + + sel.which = V4L2_SUBDEV_FORMAT_ACTIVE; + sel.target = V4L2_SEL_TGT_CROP_DEFAULT; + err = v4l2_subdev_call(input->camera, pad, get_selection, NULL, &sel); + if (err) + return; + + input->active_rect = sel.r; + + /* + * Check for a framesize with half active_rect width and height, + * if found assume the sensor supports binning. + * Do this before changing the crop-rect since that may influence + * enum_frame_size results. + */ + for (i = 0; ; i++) { + fse.index = i; + fse.code = input->code; + fse.which = V4L2_SUBDEV_FORMAT_ACTIVE; + + err = v4l2_subdev_call(input->camera, pad, enum_frame_size, NULL, &fse); + if (err) + break; + + if (fse.min_width <= (input->active_rect.width / 2) && + fse.min_height <= (input->active_rect.height / 2)) { + input->binning_support = true; + break; + } + } + + /* + * The ISP also wants the non-active pixels at the border of the sensor + * for padding, set the crop rect to cover the entire sensor instead + * of only the default active area. + * + * Do this for both try and active formats since the try_crop rect in + * pad_cfg may influence (clamp) future try_fmt calls with which == try. + */ + sel.which = V4L2_SUBDEV_FORMAT_TRY; + sel.target = V4L2_SEL_TGT_CROP; + sel.r = input->native_rect; + err = v4l2_subdev_call(input->camera, pad, set_selection, &sd_state, &sel); + if (err) + return; + + sel.which = V4L2_SUBDEV_FORMAT_ACTIVE; + sel.target = V4L2_SEL_TGT_CROP; + sel.r = input->native_rect; + err = v4l2_subdev_call(input->camera, pad, set_selection, NULL, &sel); + if (err) + return; + + dev_info(input->camera->dev, "Supports crop native %dx%d active %dx%d binning %d\n", + input->native_rect.width, input->native_rect.height, + input->active_rect.width, input->active_rect.height, + input->binning_support); + + input->crop_support = true; +} + +int atomisp_register_device_nodes(struct atomisp_device *isp) { - int err; + struct atomisp_input_subdev *input; + int i, err; + + for (i = 0; i < ATOMISP_CAMERA_NR_PORTS; i++) { + err = media_create_pad_link(&isp->csi2_port[i].subdev.entity, + CSI2_PAD_SOURCE, &isp->asd.subdev.entity, + ATOMISP_SUBDEV_PAD_SINK, 0); + if (err) + return err; + + if (!isp->sensor_subdevs[i]) + continue; - err = atomisp_subdev_register_video_nodes(&isp->asd, &isp->v4l2_dev); + input = &isp->inputs[isp->input_cnt]; + + input->type = RAW_CAMERA; + input->port = i; + input->camera = isp->sensor_subdevs[i]; + + atomisp_init_sensor(input); + + /* + * HACK: Currently VCM belongs to primary sensor only, but correct + * approach must be to acquire from platform code which sensor + * owns it. + */ + if (i == ATOMISP_CAMERA_PORT_PRIMARY) + input->motor = isp->motor; + + err = media_create_pad_link(&input->camera->entity, 0, + &isp->csi2_port[i].subdev.entity, + CSI2_PAD_SINK, + MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE); + if (err) + return err; + + isp->input_cnt++; + } + + if (!isp->input_cnt) + dev_warn(isp->dev, "no camera attached or fail to detect\n"); + else + dev_info(isp->dev, "detected %d camera sensors\n", isp->input_cnt); + + if (isp->input_cnt < ATOM_ISP_MAX_INPUTS) { + dev_dbg(isp->dev, "TPG detected, camera_cnt: %d\n", isp->input_cnt); + isp->inputs[isp->input_cnt].type = TEST_PATTERN; + isp->inputs[isp->input_cnt].port = -1; + isp->inputs[isp->input_cnt++].camera = &isp->tpg.sd; + } else { + dev_warn(isp->dev, "too many atomisp inputs, TPG ignored.\n"); + } + + isp->asd.video_out.vdev.v4l2_dev = &isp->v4l2_dev; + isp->asd.video_out.vdev.device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; + err = video_register_device(&isp->asd.video_out.vdev, VFL_TYPE_VIDEO, -1); if (err) return err; - err = atomisp_create_pads_links(isp); + err = media_create_pad_link(&isp->asd.subdev.entity, ATOMISP_SUBDEV_PAD_SOURCE, + &isp->asd.video_out.vdev.entity, 0, 0); if (err) return err; @@ -1543,9 +1508,11 @@ static int atomisp_pci_probe(struct pci_dev *pdev, const struct pci_device_id *i isp->firmware = NULL; isp->css_env.isp_css_fw.data = NULL; - err = atomisp_register_device_nodes(isp); - if (err) + err = v4l2_async_nf_register(&isp->v4l2_dev, &isp->notifier); + if (err) { + dev_err(isp->dev, "failed to register async notifier : %d\n", err); goto css_init_fail; + } atomisp_drvfs_init(isp); diff --git a/drivers/staging/media/atomisp/pci/atomisp_v4l2.h b/drivers/staging/media/atomisp/pci/atomisp_v4l2.h index ccf1c0ac17b210b8c0a8ef35c6d50728708389a5..fad9573374b3215fa9a973dfc4a4052e3e7d02d1 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_v4l2.h +++ b/drivers/staging/media/atomisp/pci/atomisp_v4l2.h @@ -26,10 +26,10 @@ struct v4l2_device; struct atomisp_device; struct firmware; -int atomisp_video_init(struct atomisp_video_pipe *video, const char *name, - unsigned int run_mode); +int atomisp_video_init(struct atomisp_video_pipe *video); void atomisp_video_unregister(struct atomisp_video_pipe *video); const struct firmware *atomisp_load_firmware(struct atomisp_device *isp); int atomisp_csi_lane_config(struct atomisp_device *isp); +int atomisp_register_device_nodes(struct atomisp_device *isp); #endif /* __ATOMISP_V4L2_H__ */ diff --git a/drivers/staging/media/atomisp/pci/runtime/frame/interface/ia_css_frame.h b/drivers/staging/media/atomisp/pci/runtime/frame/interface/ia_css_frame.h index 700070c58eda04c5ef5b20ed86cf688048ab143a..90c17884968b06e6b7c16eeb8ff478161413464c 100644 --- a/drivers/staging/media/atomisp/pci/runtime/frame/interface/ia_css_frame.h +++ b/drivers/staging/media/atomisp/pci/runtime/frame/interface/ia_css_frame.h @@ -138,4 +138,6 @@ bool ia_css_frame_is_same_type( int ia_css_dma_configure_from_info(struct dma_port_config *config, const struct ia_css_frame_info *info); +unsigned int ia_css_frame_pad_width(unsigned int width, enum ia_css_frame_format format); + #endif /* __IA_CSS_FRAME_H__ */ diff --git a/drivers/staging/media/atomisp/pci/runtime/frame/src/frame.c b/drivers/staging/media/atomisp/pci/runtime/frame/src/frame.c index 83bb42e0542136c041caf90f74dd5b19cb859ade..2d7fddb114f655b42f592b57e04b06fdbb9e0d77 100644 --- a/drivers/staging/media/atomisp/pci/runtime/frame/src/frame.c +++ b/drivers/staging/media/atomisp/pci/runtime/frame/src/frame.c @@ -269,6 +269,34 @@ int ia_css_frame_init_planes(struct ia_css_frame *frame) return 0; } +unsigned int ia_css_frame_pad_width(unsigned int width, enum ia_css_frame_format format) +{ + switch (format) { + /* + * Frames with a U and V plane of 8 bits per pixel need to have + * all planes aligned, this means double the alignment for the + * Y plane if the horizontal decimation is 2. + */ + case IA_CSS_FRAME_FORMAT_YUV420: + case IA_CSS_FRAME_FORMAT_YV12: + case IA_CSS_FRAME_FORMAT_NV12: + case IA_CSS_FRAME_FORMAT_NV21: + case IA_CSS_FRAME_FORMAT_BINARY_8: + case IA_CSS_FRAME_FORMAT_YUV_LINE: + return CEIL_MUL(width, 2 * HIVE_ISP_DDR_WORD_BYTES); + + case IA_CSS_FRAME_FORMAT_NV12_TILEY: + return CEIL_MUL(width, NV12_TILEY_TILE_WIDTH); + + case IA_CSS_FRAME_FORMAT_RAW: + case IA_CSS_FRAME_FORMAT_RAW_PACKED: + return CEIL_MUL(width, 2 * ISP_VEC_NELEMS); + + default: + return CEIL_MUL(width, HIVE_ISP_DDR_WORD_BYTES); + } +} + void ia_css_frame_info_set_width(struct ia_css_frame_info *info, unsigned int width, unsigned int min_padded_width) @@ -285,25 +313,8 @@ void ia_css_frame_info_set_width(struct ia_css_frame_info *info, align = max(min_padded_width, width); info->res.width = width; - /* frames with a U and V plane of 8 bits per pixel need to have - all planes aligned, this means double the alignment for the - Y plane if the horizontal decimation is 2. */ - if (info->format == IA_CSS_FRAME_FORMAT_YUV420 || - info->format == IA_CSS_FRAME_FORMAT_YV12 || - info->format == IA_CSS_FRAME_FORMAT_NV12 || - info->format == IA_CSS_FRAME_FORMAT_NV21 || - info->format == IA_CSS_FRAME_FORMAT_BINARY_8 || - info->format == IA_CSS_FRAME_FORMAT_YUV_LINE) - info->padded_width = - CEIL_MUL(align, 2 * HIVE_ISP_DDR_WORD_BYTES); - else if (info->format == IA_CSS_FRAME_FORMAT_NV12_TILEY) - info->padded_width = CEIL_MUL(align, NV12_TILEY_TILE_WIDTH); - else if (info->format == IA_CSS_FRAME_FORMAT_RAW || - info->format == IA_CSS_FRAME_FORMAT_RAW_PACKED) - info->padded_width = CEIL_MUL(align, 2 * ISP_VEC_NELEMS); - else { - info->padded_width = CEIL_MUL(align, HIVE_ISP_DDR_WORD_BYTES); - } + info->padded_width = ia_css_frame_pad_width(align, info->format); + IA_CSS_LEAVE_PRIVATE(""); } @@ -601,9 +612,6 @@ static void frame_init_qplane6_planes(struct ia_css_frame *frame) static int frame_allocate_buffer_data(struct ia_css_frame *frame) { -#ifdef ISP2401 - IA_CSS_ENTER_LEAVE_PRIVATE("frame->data_bytes=%d\n", frame->data_bytes); -#endif frame->data = hmm_alloc(frame->data_bytes); if (frame->data == mmgr_NULL) return -ENOMEM; @@ -635,15 +643,11 @@ static int frame_allocate_with_data(struct ia_css_frame **frame, if (err) { kvfree(me); -#ifndef ISP2401 - return err; -#else - me = NULL; -#endif + *frame = NULL; + } else { + *frame = me; } - *frame = me; - return err; } diff --git a/drivers/staging/media/atomisp/pci/sh_css.c b/drivers/staging/media/atomisp/pci/sh_css.c index 93789500416f698ea3edf82691a07265e8cf8dae..4b3fa6d93fe0ab61f366628baa252d389ea3dd54 100644 --- a/drivers/staging/media/atomisp/pci/sh_css.c +++ b/drivers/staging/media/atomisp/pci/sh_css.c @@ -1529,15 +1529,14 @@ ia_css_init(struct device *dev, const struct ia_css_env *env, mipi_init(); -#ifndef ISP2401 /* * In case this has been programmed already, update internal * data structure ... * DEPRECATED */ - my_css.page_table_base_index = mmu_get_page_table_base_index(MMU0_ID); + if (!IS_ISP2401) + my_css.page_table_base_index = mmu_get_page_table_base_index(MMU0_ID); -#endif my_css.irq_type = irq_type; my_css_save.irq_type = irq_type; @@ -1596,10 +1595,8 @@ ia_css_init(struct device *dev, const struct ia_css_env *env, * sh_css_init_buffer_queues(); */ -#if defined(ISP2401) - gp_device_reg_store(GP_DEVICE0_ID, _REG_GP_SWITCH_ISYS2401_ADDR, 1); -#endif - + if (IS_ISP2401) + gp_device_reg_store(GP_DEVICE0_ID, _REG_GP_SWITCH_ISYS2401_ADDR, 1); if (!IS_ISP2401) dma_set_max_burst_size(DMA0_ID, HIVE_DMA_BUS_DDR_CONN, @@ -2128,13 +2125,8 @@ ia_css_pipe_destroy(struct ia_css_pipe *pipe) err); } } -#ifndef ISP2401 ia_css_frame_free_multiple(NUM_VIDEO_TNR_FRAMES, pipe->pipe_settings.video.tnr_frames); -#else - ia_css_frame_free_multiple(NUM_VIDEO_TNR_FRAMES, - pipe->pipe_settings.video.tnr_frames); -#endif ia_css_frame_free_multiple(MAX_NUM_VIDEO_DELAY_FRAMES, pipe->pipe_settings.video.delay_frames); break; @@ -2238,11 +2230,10 @@ int ia_css_irq_translate( case virq_isys_csi: infos |= IA_CSS_IRQ_INFO_INPUT_SYSTEM_ERROR; break; -#if !defined(ISP2401) case virq_ifmt0_id: - infos |= IA_CSS_IRQ_INFO_IF_ERROR; + if (!IS_ISP2401) + infos |= IA_CSS_IRQ_INFO_IF_ERROR; break; -#endif case virq_dma: infos |= IA_CSS_IRQ_INFO_DMA_ERROR; break; @@ -2277,27 +2268,34 @@ int ia_css_irq_enable( IA_CSS_ENTER("info=%d, enable=%d", info, enable); switch (info) { -#if !defined(ISP2401) case IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF: + if (IS_ISP2401) + /* Just ignore those unused IRQs without printing errors */ + return 0; + irq = virq_isys_sof; break; case IA_CSS_IRQ_INFO_CSS_RECEIVER_EOF: + if (IS_ISP2401) + /* Just ignore those unused IRQs without printing errors */ + return 0; + irq = virq_isys_eof; break; case IA_CSS_IRQ_INFO_INPUT_SYSTEM_ERROR: + if (IS_ISP2401) + /* Just ignore those unused IRQs without printing errors */ + return 0; + irq = virq_isys_csi; break; case IA_CSS_IRQ_INFO_IF_ERROR: + if (IS_ISP2401) + /* Just ignore those unused IRQs without printing errors */ + return 0; + irq = virq_ifmt0_id; break; -#else - case IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF: - case IA_CSS_IRQ_INFO_CSS_RECEIVER_EOF: - case IA_CSS_IRQ_INFO_INPUT_SYSTEM_ERROR: - case IA_CSS_IRQ_INFO_IF_ERROR: - /* Just ignore those unused IRQs without printing errors */ - return 0; -#endif case IA_CSS_IRQ_INFO_DMA_ERROR: irq = virq_dma; break; @@ -2413,14 +2411,14 @@ alloc_continuous_frames(struct ia_css_pipe *pipe, bool init_time) return -EINVAL; } -#if defined(ISP2401) - /* For CSI2+, the continuous frame will hold the full input frame */ - ref_info.res.width = pipe->stream->config.input_config.input_res.width; - ref_info.res.height = pipe->stream->config.input_config.input_res.height; + if (IS_ISP2401) { + /* For CSI2+, the continuous frame will hold the full input frame */ + ref_info.res.width = pipe->stream->config.input_config.input_res.width; + ref_info.res.height = pipe->stream->config.input_config.input_res.height; - /* Ensure padded width is aligned for 2401 */ - ref_info.padded_width = CEIL_MUL(ref_info.res.width, 2 * ISP_VEC_NELEMS); -#endif + /* Ensure padded width is aligned for 2401 */ + ref_info.padded_width = CEIL_MUL(ref_info.res.width, 2 * ISP_VEC_NELEMS); + } if (pipe->stream->config.pack_raw_pixels) { ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, @@ -2499,11 +2497,9 @@ load_preview_binaries(struct ia_css_pipe *pipe) int err = 0; bool need_vf_pp = false; bool need_isp_copy_binary = false; -#ifdef ISP2401 bool sensor = false; -#else bool continuous; -#endif + /* preview only have 1 output pin now */ struct ia_css_frame_info *pipe_out_info = &pipe->output_info[0]; struct ia_css_preview_settings *mycs = &pipe->pipe_settings.preview; @@ -2514,11 +2510,9 @@ load_preview_binaries(struct ia_css_pipe *pipe) assert(pipe->mode == IA_CSS_PIPE_ID_PREVIEW); online = pipe->stream->config.online; -#ifdef ISP2401 + sensor = pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR; -#else continuous = pipe->stream->config.continuous; -#endif if (mycs->preview_binary.info) return 0; @@ -2627,24 +2621,22 @@ load_preview_binaries(struct ia_css_pipe *pipe) return err; } -#ifdef ISP2401 - /* - * When the input system is 2401, only the Direct Sensor Mode - * Offline Preview uses the ISP copy binary. - */ - need_isp_copy_binary = !online && sensor; -#else - /* - * About pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY: - * This is typical the case with SkyCam (which has no input system) but it also applies to all cases - * where the driver chooses for memory based input frames. In these cases, a copy binary (which typical - * copies sensor data to DDR) does not have much use. - */ - if (!IS_ISP2401) + if (IS_ISP2401) { + /* + * When the input system is 2401, only the Direct Sensor Mode + * Offline Preview uses the ISP copy binary. + */ + need_isp_copy_binary = !online && sensor; + } else { + /* + * About pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY: + * This is typical the case with SkyCam (which has no input system) but it also + * applies to all cases where the driver chooses for memory based input frames. + * In these cases, a copy binary (which typical copies sensor data to DDR) does + * not have much use. + */ need_isp_copy_binary = !online && !continuous; - else - need_isp_copy_binary = !online && !continuous && !(pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY); -#endif + } /* Copy */ if (need_isp_copy_binary) { @@ -3125,11 +3117,10 @@ init_in_frameinfo_memory_defaults(struct ia_css_pipe *pipe, in_frame->frame_info.format = format; -#ifdef ISP2401 - if (format == IA_CSS_FRAME_FORMAT_RAW) + if (IS_ISP2401 && format == IA_CSS_FRAME_FORMAT_RAW) { in_frame->frame_info.format = (pipe->stream->config.pack_raw_pixels) ? IA_CSS_FRAME_FORMAT_RAW_PACKED : IA_CSS_FRAME_FORMAT_RAW; -#endif + } in_frame->frame_info.res.width = pipe->stream->config.input_config.input_res.width; in_frame->frame_info.res.height = pipe->stream->config.input_config.input_res.height; @@ -3211,18 +3202,18 @@ static int create_host_video_pipeline(struct ia_css_pipe *pipe) me->dvs_frame_delay = pipe->dvs_frame_delay; -#ifdef ISP2401 - /* - * When the input system is 2401, always enable 'in_frameinfo_memory' - * except for the following: online or continuous - */ - need_in_frameinfo_memory = !(pipe->stream->config.online || - pipe->stream->config.continuous); -#else - /* Construct in_frame info (only in case we have dynamic input */ - need_in_frameinfo_memory = pipe->stream->config.mode == - IA_CSS_INPUT_MODE_MEMORY; -#endif + if (IS_ISP2401) { + /* + * When the input system is 2401, always enable 'in_frameinfo_memory' + * except for the following: online or continuous + */ + need_in_frameinfo_memory = !(pipe->stream->config.online || + pipe->stream->config.continuous); + } else { + /* Construct in_frame info (only in case we have dynamic input */ + need_in_frameinfo_memory = pipe->stream->config.mode == + IA_CSS_INPUT_MODE_MEMORY; + } /* Construct in_frame info (only in case we have dynamic input */ if (need_in_frameinfo_memory) { @@ -3268,15 +3259,14 @@ static int create_host_video_pipeline(struct ia_css_pipe *pipe) goto ERR; in_frame = me->stages->args.out_frame[0]; } else if (pipe->stream->config.continuous) { -#ifdef ISP2401 - /* - * When continuous is enabled, configure in_frame with the - * last pipe, which is the copy pipe. - */ - in_frame = pipe->stream->last_pipe->continuous_frames[0]; -#else - in_frame = pipe->continuous_frames[0]; -#endif + if (IS_ISP2401) + /* + * When continuous is enabled, configure in_frame with the + * last pipe, which is the copy pipe. + */ + in_frame = pipe->stream->last_pipe->continuous_frames[0]; + else + in_frame = pipe->continuous_frames[0]; } ia_css_pipe_util_set_output_frames(out_frames, 0, @@ -3373,12 +3363,10 @@ create_host_preview_pipeline(struct ia_css_pipe *pipe) struct ia_css_frame *out_frame; struct ia_css_frame *out_frames[IA_CSS_BINARY_MAX_OUTPUT_PORTS]; bool need_in_frameinfo_memory = false; -#ifdef ISP2401 bool sensor = false; bool buffered_sensor = false; bool online = false; bool continuous = false; -#endif IA_CSS_ENTER_PRIVATE("pipe = %p", pipe); if ((!pipe) || (!pipe->stream) || (pipe->mode != IA_CSS_PIPE_ID_PREVIEW)) { @@ -3391,25 +3379,26 @@ create_host_preview_pipeline(struct ia_css_pipe *pipe) me = &pipe->pipeline; ia_css_pipeline_clean(me); -#ifdef ISP2401 - /* - * When the input system is 2401, always enable 'in_frameinfo_memory' - * except for the following: - * - Direct Sensor Mode Online Preview - * - Buffered Sensor Mode Online Preview - * - Direct Sensor Mode Continuous Preview - * - Buffered Sensor Mode Continuous Preview - */ - sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR); - buffered_sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR); - online = pipe->stream->config.online; - continuous = pipe->stream->config.continuous; - need_in_frameinfo_memory = - !((sensor && (online || continuous)) || (buffered_sensor && (online || continuous))); -#else - /* Construct in_frame info (only in case we have dynamic input */ - need_in_frameinfo_memory = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY; -#endif + if (IS_ISP2401) { + /* + * When the input system is 2401, always enable 'in_frameinfo_memory' + * except for the following: + * - Direct Sensor Mode Online Preview + * - Buffered Sensor Mode Online Preview + * - Direct Sensor Mode Continuous Preview + * - Buffered Sensor Mode Continuous Preview + */ + sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR); + buffered_sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR); + online = pipe->stream->config.online; + continuous = pipe->stream->config.continuous; + need_in_frameinfo_memory = + !((sensor && (online || continuous)) || (buffered_sensor && + (online || continuous))); + } else { + /* Construct in_frame info (only in case we have dynamic input */ + need_in_frameinfo_memory = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY; + } if (need_in_frameinfo_memory) { err = init_in_frameinfo_memory_defaults(pipe, &me->in_frame, IA_CSS_FRAME_FORMAT_RAW); @@ -3420,7 +3409,6 @@ create_host_preview_pipeline(struct ia_css_pipe *pipe) } else { in_frame = NULL; } - err = init_out_frameinfo_defaults(pipe, &me->out_frame[0], 0); if (err) goto ERR; @@ -3441,17 +3429,16 @@ create_host_preview_pipeline(struct ia_css_pipe *pipe) goto ERR; in_frame = me->stages->args.out_frame[0]; } else if (pipe->stream->config.continuous) { -#ifdef ISP2401 - /* - * When continuous is enabled, configure in_frame with the - * last pipe, which is the copy pipe. - */ - if (continuous || !online) - in_frame = pipe->stream->last_pipe->continuous_frames[0]; - -#else - in_frame = pipe->continuous_frames[0]; -#endif + if (IS_ISP2401) { + /* + * When continuous is enabled, configure in_frame with the + * last pipe, which is the copy pipe. + */ + if (continuous || !online) + in_frame = pipe->stream->last_pipe->continuous_frames[0]; + } else { + in_frame = pipe->continuous_frames[0]; + } } if (vf_pp_binary) { @@ -3925,19 +3912,19 @@ ia_css_pipe_dequeue_buffer(struct ia_css_pipe *pipe, case IA_CSS_BUFFER_TYPE_OUTPUT_FRAME: case IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME: if (pipe && pipe->stop_requested) { -#if !defined(ISP2401) - /* - * free mipi frames only for old input - * system for 2401 it is done in - * ia_css_stream_destroy call - */ - return_err = free_mipi_frames(pipe); - if (return_err) { - IA_CSS_LOG("free_mipi_frames() failed"); - IA_CSS_LEAVE_ERR(return_err); - return return_err; + if (!IS_ISP2401) { + /* + * free mipi frames only for old input + * system for 2401 it is done in + * ia_css_stream_destroy call + */ + return_err = free_mipi_frames(pipe); + if (return_err) { + IA_CSS_LOG("free_mipi_frames() failed"); + IA_CSS_LEAVE_ERR(return_err); + return return_err; + } } -#endif pipe->stop_requested = false; } fallthrough; @@ -3959,12 +3946,11 @@ ia_css_pipe_dequeue_buffer(struct ia_css_pipe *pipe, pipe->num_invalid_frames--; if (frame->frame_info.format == IA_CSS_FRAME_FORMAT_BINARY_8) { -#ifdef ISP2401 - frame->planes.binary.size = frame->data_bytes; -#else - frame->planes.binary.size = - sh_css_sp_get_binary_copy_size(); -#endif + if (IS_ISP2401) + frame->planes.binary.size = frame->data_bytes; + else + frame->planes.binary.size = + sh_css_sp_get_binary_copy_size(); } if (buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME) { IA_CSS_LOG("pfp: dequeued OF %d with config id %d thread %d", @@ -4880,22 +4866,20 @@ static int load_video_binaries(struct ia_css_pipe *pipe) pipe->num_invalid_frames, pipe->dvs_frame_delay); /* pqiao TODO: temp hack for PO, should be removed after offline YUVPP is enabled */ -#if !defined(ISP2401) - /* Copy */ - if (!online && !continuous) { - /* - * TODO: what exactly needs doing, prepend the copy binary to - * video base this only on !online? - */ - err = load_copy_binary(pipe, - &mycs->copy_binary, - &mycs->video_binary); - if (err) - return err; + if (!IS_ISP2401) { + /* Copy */ + if (!online && !continuous) { + /* + * TODO: what exactly needs doing, prepend the copy binary to + * video base this only on !online? + */ + err = load_copy_binary(pipe, + &mycs->copy_binary, + &mycs->video_binary); + if (err) + return err; + } } -#else - (void)continuous; -#endif if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0] && need_vf_pp) { struct ia_css_binary_descr vf_pp_descr; @@ -5227,11 +5211,8 @@ static int load_primary_binaries( bool need_pp = false; bool need_isp_copy_binary = false; bool need_ldc = false; -#ifdef ISP2401 bool sensor = false; -#else bool memory, continuous; -#endif struct ia_css_frame_info prim_in_info, prim_out_info, capt_pp_out_info, vf_info, @@ -5251,12 +5232,9 @@ static int load_primary_binaries( pipe->mode == IA_CSS_PIPE_ID_COPY); online = pipe->stream->config.online; -#ifdef ISP2401 sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR); -#else memory = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY; continuous = pipe->stream->config.continuous; -#endif mycs = &pipe->pipe_settings.capture; pipe_out_info = &pipe->output_info[0]; @@ -5462,15 +5440,14 @@ static int load_primary_binaries( if (err) return err; -#ifdef ISP2401 - /* - * When the input system is 2401, only the Direct Sensor Mode - * Offline Capture uses the ISP copy binary. - */ - need_isp_copy_binary = !online && sensor; -#else - need_isp_copy_binary = !online && !continuous && !memory; -#endif + if (IS_ISP2401) + /* + * When the input system is 2401, only the Direct Sensor Mode + * Offline Capture uses the ISP copy binary. + */ + need_isp_copy_binary = !online && sensor; + else + need_isp_copy_binary = !online && !continuous && !memory; /* ISP Copy */ if (need_isp_copy_binary) { @@ -5681,10 +5658,10 @@ static int load_advanced_binaries(struct ia_css_pipe *pipe) } /* Copy */ -#ifdef ISP2401 - /* For CSI2+, only the direct sensor mode/online requires ISP copy */ - need_isp_copy = pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR; -#endif + if (IS_ISP2401) + /* For CSI2+, only the direct sensor mode/online requires ISP copy */ + need_isp_copy = pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR; + if (need_isp_copy) load_copy_binary(pipe, &pipe->pipe_settings.capture.copy_binary, @@ -5829,10 +5806,10 @@ static int load_low_light_binaries(struct ia_css_pipe *pipe) } /* Copy */ -#ifdef ISP2401 - /* For CSI2+, only the direct sensor mode/online requires ISP copy */ - need_isp_copy = pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR; -#endif + if (IS_ISP2401) + /* For CSI2+, only the direct sensor mode/online requires ISP copy */ + need_isp_copy = pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR; + if (need_isp_copy) err = load_copy_binary(pipe, &pipe->pipe_settings.capture.copy_binary, @@ -5902,10 +5879,9 @@ static int load_capture_binaries(struct ia_css_pipe *pipe) switch (pipe->config.default_capture_config.mode) { case IA_CSS_CAPTURE_MODE_RAW: err = load_copy_binaries(pipe); -#if defined(ISP2401) - if (!err) + if (!err && IS_ISP2401) pipe->pipe_settings.capture.copy_binary.online = pipe->stream->config.online; -#endif + break; case IA_CSS_CAPTURE_MODE_BAYER: err = load_bayer_isp_binaries(pipe); @@ -6409,7 +6385,6 @@ load_yuvpp_binaries(struct ia_css_pipe *pipe) else next_binary = NULL; -#if defined(ISP2401) /* * NOTES * - Why does the "yuvpp" pipe needs "isp_copy_binary" (i.e. ISP Copy) when @@ -6427,11 +6402,11 @@ load_yuvpp_binaries(struct ia_css_pipe *pipe) * pp_defs.h" for the list of input-frame formats that are supported by the * "yuv_scale_binary". */ - need_isp_copy_binary = - (pipe->stream->config.input_config.format == ATOMISP_INPUT_FORMAT_YUV422_8); -#else /* !ISP2401 */ - need_isp_copy_binary = true; -#endif /* ISP2401 */ + if (IS_ISP2401) + need_isp_copy_binary = + (pipe->stream->config.input_config.format == ATOMISP_INPUT_FORMAT_YUV422_8); + else + need_isp_copy_binary = true; if (need_isp_copy_binary) { err = load_copy_binary(pipe, @@ -6678,12 +6653,10 @@ create_host_yuvpp_pipeline(struct ia_css_pipe *pipe) struct ia_css_frame *vf_frame[IA_CSS_PIPE_MAX_OUTPUT_STAGE]; struct ia_css_pipeline_stage_desc stage_desc; bool need_in_frameinfo_memory = false; -#ifdef ISP2401 bool sensor = false; bool buffered_sensor = false; bool online = false; bool continuous = false; -#endif IA_CSS_ENTER_PRIVATE("pipe = %p", pipe); if ((!pipe) || (!pipe->stream) || (pipe->mode != IA_CSS_PIPE_ID_YUVPP)) { @@ -6700,24 +6673,24 @@ create_host_yuvpp_pipeline(struct ia_css_pipe *pipe) num_stage = pipe->pipe_settings.yuvpp.num_yuv_scaler; num_output_stage = pipe->pipe_settings.yuvpp.num_output; -#ifdef ISP2401 - /* - * When the input system is 2401, always enable 'in_frameinfo_memory' - * except for the following: - * - Direct Sensor Mode Online Capture - * - Direct Sensor Mode Continuous Capture - * - Buffered Sensor Mode Continuous Capture - */ - sensor = pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR; - buffered_sensor = pipe->stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR; - online = pipe->stream->config.online; - continuous = pipe->stream->config.continuous; - need_in_frameinfo_memory = - !((sensor && (online || continuous)) || (buffered_sensor && continuous)); -#else - /* Construct in_frame info (only in case we have dynamic input */ - need_in_frameinfo_memory = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY; -#endif + if (IS_ISP2401) { + /* + * When the input system is 2401, always enable 'in_frameinfo_memory' + * except for the following: + * - Direct Sensor Mode Online Capture + * - Direct Sensor Mode Continuous Capture + * - Buffered Sensor Mode Continuous Capture + */ + sensor = pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR; + buffered_sensor = pipe->stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR; + online = pipe->stream->config.online; + continuous = pipe->stream->config.continuous; + need_in_frameinfo_memory = + !((sensor && (online || continuous)) || (buffered_sensor && continuous)); + } else { + /* Construct in_frame info (only in case we have dynamic input */ + need_in_frameinfo_memory = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY; + } /* * the input frame can come from: * @@ -6808,11 +6781,10 @@ create_host_yuvpp_pipeline(struct ia_css_pipe *pipe) if (pipe->pipe_settings.yuvpp.copy_binary.info) { struct ia_css_frame *in_frame_local = NULL; -#ifdef ISP2401 - /* After isp copy is enabled in_frame needs to be passed. */ - if (!online) + if (IS_ISP2401 && !online) { + /* After isp copy is enabled in_frame needs to be passed. */ in_frame_local = in_frame; -#endif + } if (need_scaler) { ia_css_pipe_util_set_output_frames(bin_out_frame, @@ -7031,12 +7003,10 @@ create_host_regular_capture_pipeline(struct ia_css_pipe *pipe) struct ia_css_frame *vf_frame; struct ia_css_pipeline_stage_desc stage_desc; bool need_in_frameinfo_memory = false; -#ifdef ISP2401 bool sensor = false; bool buffered_sensor = false; bool online = false; bool continuous = false; -#endif unsigned int i, num_yuv_scaler, num_primary_stage; bool need_yuv_pp = false; bool *is_output_stage = NULL; @@ -7054,25 +7024,27 @@ create_host_regular_capture_pipeline(struct ia_css_pipe *pipe) ia_css_pipeline_clean(me); ia_css_pipe_util_create_output_frames(out_frames); -#ifdef ISP2401 - /* - * When the input system is 2401, always enable 'in_frameinfo_memory' - * except for the following: - * - Direct Sensor Mode Online Capture - * - Direct Sensor Mode Online Capture - * - Direct Sensor Mode Continuous Capture - * - Buffered Sensor Mode Continuous Capture - */ - sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR); - buffered_sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR); - online = pipe->stream->config.online; - continuous = pipe->stream->config.continuous; - need_in_frameinfo_memory = - !((sensor && (online || continuous)) || (buffered_sensor && (online || continuous))); -#else - /* Construct in_frame info (only in case we have dynamic input */ - need_in_frameinfo_memory = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY; -#endif + if (IS_ISP2401) { + /* + * When the input system is 2401, always enable 'in_frameinfo_memory' + * except for the following: + * - Direct Sensor Mode Online Capture + * - Direct Sensor Mode Online Capture + * - Direct Sensor Mode Continuous Capture + * - Buffered Sensor Mode Continuous Capture + */ + sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR); + buffered_sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR); + online = pipe->stream->config.online; + continuous = pipe->stream->config.continuous; + need_in_frameinfo_memory = + !((sensor && (online || continuous)) || (buffered_sensor && + (online || continuous))); + } else { + /* Construct in_frame info (only in case we have dynamic input */ + need_in_frameinfo_memory = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY; + } + if (need_in_frameinfo_memory) { err = init_in_frameinfo_memory_defaults(pipe, &me->in_frame, IA_CSS_FRAME_FORMAT_RAW); @@ -7135,27 +7107,27 @@ create_host_regular_capture_pipeline(struct ia_css_pipe *pipe) if (pipe->pipe_settings.capture.copy_binary.info) { if (raw) { ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame); -#if defined(ISP2401) - if (!continuous) { - ia_css_pipe_get_generic_stage_desc(&stage_desc, - copy_binary, - out_frames, - in_frame, - NULL); + if (IS_ISP2401) { + if (!continuous) { + ia_css_pipe_get_generic_stage_desc(&stage_desc, + copy_binary, + out_frames, + in_frame, + NULL); + } else { + in_frame = pipe->stream->last_pipe->continuous_frames[0]; + ia_css_pipe_get_generic_stage_desc(&stage_desc, + copy_binary, + out_frames, + in_frame, + NULL); + } } else { - in_frame = pipe->stream->last_pipe->continuous_frames[0]; ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary, out_frames, - in_frame, - NULL); + NULL, NULL); } -#else - ia_css_pipe_get_generic_stage_desc(&stage_desc, - copy_binary, - out_frames, - NULL, NULL); -#endif } else { ia_css_pipe_util_set_output_frames(out_frames, 0, in_frame); @@ -7185,11 +7157,7 @@ create_host_regular_capture_pipeline(struct ia_css_pipe *pipe) local_in_frame = in_frame; else local_in_frame = NULL; -#ifndef ISP2401 - if (!need_pp && (i == num_primary_stage - 1)) -#else - if (!need_pp && (i == num_primary_stage - 1) && !need_ldc) -#endif + if (!need_pp && (i == num_primary_stage - 1) && (!IS_ISP2401 || !need_ldc)) local_out_frame = out_frame; else local_out_frame = NULL; @@ -7400,23 +7368,14 @@ static int capture_start(struct ia_css_pipe *pipe) return err; } } - -#if !defined(ISP2401) /* old isys: need to send_mipi_frames() in all pipe modes */ - err = send_mipi_frames(pipe); - if (err) { - IA_CSS_LEAVE_ERR_PRIVATE(err); - return err; - } -#else - if (pipe->config.mode != IA_CSS_PIPE_MODE_COPY) { + if (!IS_ISP2401 || (IS_ISP2401 && pipe->config.mode != IA_CSS_PIPE_MODE_COPY)) { err = send_mipi_frames(pipe); if (err) { IA_CSS_LEAVE_ERR_PRIVATE(err); return err; } } -#endif ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id); copy_ovrd = 1 << thread_id; @@ -8123,24 +8082,22 @@ ia_css_stream_create(const struct ia_css_stream_config *stream_config, return err; } -#if !defined(ISP2401) - /* We don't support metadata for JPEG stream, since they both use str2mem */ - if (stream_config->input_config.format == ATOMISP_INPUT_FORMAT_BINARY_8 && - stream_config->metadata_config.resolution.height > 0) { - err = -EINVAL; - IA_CSS_LEAVE_ERR(err); - return err; - } -#endif - -#ifdef ISP2401 - if (stream_config->online && stream_config->pack_raw_pixels) { - IA_CSS_LOG("online and pack raw is invalid on input system 2401"); - err = -EINVAL; - IA_CSS_LEAVE_ERR(err); - return err; + if (!IS_ISP2401) { + /* We don't support metadata for JPEG stream, since they both use str2mem */ + if (stream_config->input_config.format == ATOMISP_INPUT_FORMAT_BINARY_8 && + stream_config->metadata_config.resolution.height > 0) { + err = -EINVAL; + IA_CSS_LEAVE_ERR(err); + return err; + } + } else { + if (stream_config->online && stream_config->pack_raw_pixels) { + IA_CSS_LOG("online and pack raw is invalid on input system 2401"); + err = -EINVAL; + IA_CSS_LEAVE_ERR(err); + return err; + } } -#endif ia_css_debug_pipe_graph_dump_stream_config(stream_config); @@ -8223,19 +8180,17 @@ ia_css_stream_create(const struct ia_css_stream_config *stream_config, /* take over stream config */ curr_stream->config = *stream_config; -#if defined(ISP2401) - if (stream_config->mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR && - stream_config->online) - curr_stream->config.online = false; -#endif + if (IS_ISP2401) { + if (stream_config->mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR && + stream_config->online) + curr_stream->config.online = false; -#ifdef ISP2401 - if (curr_stream->config.online) { - curr_stream->config.source.port.num_lanes = - stream_config->source.port.num_lanes; - curr_stream->config.mode = IA_CSS_INPUT_MODE_BUFFERED_SENSOR; + if (curr_stream->config.online) { + curr_stream->config.source.port.num_lanes = + stream_config->source.port.num_lanes; + curr_stream->config.mode = IA_CSS_INPUT_MODE_BUFFERED_SENSOR; + } } -#endif /* in case driver doesn't configure init number of raw buffers, configure it here */ if (curr_stream->config.target_num_cont_raw_buf == 0) curr_stream->config.target_num_cont_raw_buf = NUM_CONTINUOUS_FRAMES; @@ -9162,11 +9117,10 @@ void ia_css_pipe_map_queue(struct ia_css_pipe *pipe, bool map) ia_css_pipeline_get_sp_thread_id(pipe_num, &thread_id); -#if defined(ISP2401) - need_input_queue = true; -#else - need_input_queue = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY; -#endif + if (IS_ISP2401) + need_input_queue = true; + else + need_input_queue = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY; /* map required buffer queues to resources */ /* TODO: to be improved */ diff --git a/drivers/staging/media/atomisp/pci/sh_css_firmware.c b/drivers/staging/media/atomisp/pci/sh_css_firmware.c index e7ef578db8ab1fdfc0cf0e4aaef4034104354a60..197ab2085e8d22db99f6e1c958f2ea09b99737a1 100644 --- a/drivers/staging/media/atomisp/pci/sh_css_firmware.c +++ b/drivers/staging/media/atomisp/pci/sh_css_firmware.c @@ -56,11 +56,8 @@ static struct firmware_header *firmware_header; * which will be replaced with the actual RELEASE_VERSION * during package generation. Please do not modify */ -#ifdef ISP2401 -static const char *release_version = STR(irci_stable_candrpv_0415_20150521_0458); -#else -static const char *release_version = STR(irci_stable_candrpv_0415_20150423_1753); -#endif +static const char *release_version_2401 = STR(irci_stable_candrpv_0415_20150521_0458); +static const char *release_version_2400 = STR(irci_stable_candrpv_0415_20150423_1753); #define MAX_FW_REL_VER_NAME 300 static char FW_rel_ver_name[MAX_FW_REL_VER_NAME] = "---"; @@ -191,8 +188,14 @@ sh_css_load_blob_info(const char *fw, const struct ia_css_fw_info *bi, bool sh_css_check_firmware_version(struct device *dev, const char *fw_data) { + const char *release_version; struct sh_css_fw_bi_file_h *file_header; + if (IS_ISP2401) + release_version = release_version_2401; + else + release_version = release_version_2400; + firmware_header = (struct firmware_header *)fw_data; file_header = &firmware_header->file_header; @@ -225,15 +228,28 @@ sh_css_load_firmware(struct device *dev, const char *fw_data, unsigned int fw_size) { unsigned int i; + const char *release_version; struct ia_css_fw_info *binaries; struct sh_css_fw_bi_file_h *file_header; int ret; + /* some sanity checks */ + if (!fw_data || fw_size < sizeof(struct sh_css_fw_bi_file_h)) + return -EINVAL; + firmware_header = (struct firmware_header *)fw_data; file_header = &firmware_header->file_header; + + if (file_header->h_size != sizeof(struct sh_css_fw_bi_file_h)) + return -EINVAL; + binaries = &firmware_header->binary_header; strscpy(FW_rel_ver_name, file_header->version, min(sizeof(FW_rel_ver_name), sizeof(file_header->version))); + if (IS_ISP2401) + release_version = release_version_2401; + else + release_version = release_version_2400; ret = sh_css_check_firmware_version(dev, fw_data); if (ret) { IA_CSS_ERROR("CSS code version (%s) and firmware version (%s) mismatch!", @@ -243,13 +259,6 @@ sh_css_load_firmware(struct device *dev, const char *fw_data, IA_CSS_LOG("successfully load firmware version %s", release_version); } - /* some sanity checks */ - if (!fw_data || fw_size < sizeof(struct sh_css_fw_bi_file_h)) - return -EINVAL; - - if (file_header->h_size != sizeof(struct sh_css_fw_bi_file_h)) - return -EINVAL; - sh_css_num_binaries = file_header->binary_nr; /* Only allocate memory for ISP blob info */ if (sh_css_num_binaries > NUM_OF_SPS) { diff --git a/drivers/staging/media/atomisp/pci/sh_css_mipi.c b/drivers/staging/media/atomisp/pci/sh_css_mipi.c index bc6e8598a776db36bce345640ac41e8edd0c9200..b20acaab0595b86b92796bcaa9288beca6904fa7 100644 --- a/drivers/staging/media/atomisp/pci/sh_css_mipi.c +++ b/drivers/staging/media/atomisp/pci/sh_css_mipi.c @@ -67,13 +67,12 @@ ia_css_mipi_frame_calculate_size(const unsigned int width, unsigned int mem_words = 0; unsigned int width_padded = width; -#if defined(ISP2401) /* The changes will be reverted as soon as RAW * Buffers are deployed by the 2401 Input System * in the non-continuous use scenario. */ - width_padded += (2 * ISP_VEC_NELEMS); -#endif + if (IS_ISP2401) + width_padded += (2 * ISP_VEC_NELEMS); IA_CSS_ENTER("padded_width=%d, height=%d, format=%d, hasSOLandEOL=%d, embedded_data_size_words=%d\n", width_padded, height, format, hasSOLandEOL, embedded_data_size_words); @@ -235,7 +234,6 @@ bool mipi_is_free(void) return true; } -#if defined(ISP2401) /* * @brief Calculate the required MIPI buffer sizes. * Based on the stream configuration, calculate the @@ -342,7 +340,6 @@ static int calculate_mipi_buff_size(struct ia_css_stream_config *stream_cfg, IA_CSS_LEAVE_ERR(err); return err; } -#endif int allocate_mipi_frames(struct ia_css_pipe *pipe, @@ -363,15 +360,13 @@ allocate_mipi_frames(struct ia_css_pipe *pipe, return -EINVAL; } -#ifdef ISP2401 - if (pipe->stream->config.online) { + if (IS_ISP2401 && pipe->stream->config.online) { ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "allocate_mipi_frames(%p) exit: no buffers needed for 2401 pipe mode.\n", pipe); return 0; } -#endif if (pipe->stream->config.mode != IA_CSS_INPUT_MODE_BUFFERED_SENSOR) { ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "allocate_mipi_frames(%p) exit: no buffers needed for pipe mode.\n", @@ -386,9 +381,10 @@ allocate_mipi_frames(struct ia_css_pipe *pipe, return -EINVAL; } -#ifdef ISP2401 - err = calculate_mipi_buff_size(&pipe->stream->config, - &my_css.mipi_frame_size[port]); + if (IS_ISP2401) + err = calculate_mipi_buff_size(&pipe->stream->config, + &my_css.mipi_frame_size[port]); + /* * 2401 system allows multiple streams to use same physical port. This is not * true for 2400 system. Currently 2401 uses MIPI buffers as a temporary solution. @@ -396,20 +392,14 @@ allocate_mipi_frames(struct ia_css_pipe *pipe, * In that case only 2400 related code should remain. */ if (ref_count_mipi_allocation[port] != 0) { - ref_count_mipi_allocation[port]++; + if (IS_ISP2401) + ref_count_mipi_allocation[port]++; + ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "allocate_mipi_frames(%p) leave: nothing to do, already allocated for this port (port=%d).\n", pipe, port); return 0; } -#else - if (ref_count_mipi_allocation[port] != 0) { - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "allocate_mipi_frames(%p) exit: already allocated for this port (port=%d).\n", - pipe, port); - return 0; - } -#endif ref_count_mipi_allocation[port]++; @@ -503,14 +493,14 @@ free_mipi_frames(struct ia_css_pipe *pipe) } if (ref_count_mipi_allocation[port] > 0) { -#if !defined(ISP2401) - assert(ref_count_mipi_allocation[port] == 1); - if (ref_count_mipi_allocation[port] != 1) { - IA_CSS_ERROR("free_mipi_frames(%p) exit: wrong ref_count (ref_count=%d).", - pipe, ref_count_mipi_allocation[port]); - return err; + if (!IS_ISP2401) { + assert(ref_count_mipi_allocation[port] == 1); + if (ref_count_mipi_allocation[port] != 1) { + IA_CSS_ERROR("free_mipi_frames(%p) exit: wrong ref_count (ref_count=%d).", + pipe, ref_count_mipi_allocation[port]); + return err; + } } -#endif ref_count_mipi_allocation[port]--; @@ -534,18 +524,6 @@ free_mipi_frames(struct ia_css_pipe *pipe) ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "free_mipi_frames(%p) exit (deallocated).\n", pipe); } -#if defined(ISP2401) - else { - /* 2401 system allows multiple streams to use same physical port. This is not - * true for 2400 system. Currently 2401 uses MIPI buffers as a temporary solution. - * TODO AM: Once that is changed (removed) this code should be removed as well. - * In that case only 2400 related code should remain. - */ - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "free_mipi_frames(%p) leave: nothing to do, other streams still use this port (port=%d).\n", - pipe, port); - } -#endif } } else { /* pipe ==NULL */ /* AM TEMP: free-ing all mipi buffers just like a legacy code. */ diff --git a/drivers/staging/media/atomisp/pci/sh_css_sp.c b/drivers/staging/media/atomisp/pci/sh_css_sp.c index 0dd58a7fe2cc9a855bb4902d20a49a31da7be76a..297e1b981720ae8b72786c00acf5d2b4432d1ac0 100644 --- a/drivers/staging/media/atomisp/pci/sh_css_sp.c +++ b/drivers/staging/media/atomisp/pci/sh_css_sp.c @@ -952,12 +952,10 @@ sh_css_sp_init_stage(struct ia_css_binary *binary, return 0; } -#if defined(ISP2401) - (void)continuous; - sh_css_sp_stage.deinterleaved = 0; -#else - sh_css_sp_stage.deinterleaved = ((stage == 0) && continuous); -#endif + if (IS_ISP2401) + sh_css_sp_stage.deinterleaved = 0; + else + sh_css_sp_stage.deinterleaved = ((stage == 0) && continuous); initialize_stage_frames(&sh_css_sp_stage.frames); /* diff --git a/drivers/staging/media/av7110/av7110_av.c b/drivers/staging/media/av7110/av7110_av.c index a5c5bebad306131ecf350e4f74611d28123859d3..00dd6a7fea64283235b13dbb8bb8842241a89620 100644 --- a/drivers/staging/media/av7110/av7110_av.c +++ b/drivers/staging/media/av7110/av7110_av.c @@ -78,7 +78,7 @@ static int write_ts_to_decoder(struct av7110 *av7110, int type, const u8 *buf, s int av7110_record_cb(struct dvb_filter_pes2ts *p2t, u8 *buf, size_t len) { - struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *) p2t->priv; + struct dvb_demux_feed *dvbdmxfeed = p2t->priv; if (!(dvbdmxfeed->ts_type & TS_PACKET)) return 0; @@ -837,7 +837,7 @@ static int write_ts_to_decoder(struct av7110 *av7110, int type, const u8 *buf, s int av7110_write_to_decoder(struct dvb_demux_feed *feed, const u8 *buf, size_t len) { struct dvb_demux *demux = feed->demux; - struct av7110 *av7110 = (struct av7110 *) demux->priv; + struct av7110 *av7110 = demux->priv; dprintk(2, "av7110:%p, \n", av7110); diff --git a/drivers/staging/media/imx/imx-media-utils.c b/drivers/staging/media/imx/imx-media-utils.c index 2d712eda2c5d7fed62eff06b1768326c5ae6f584..064dc562bc96a0aa66992ec2d46e966da2b559d9 100644 --- a/drivers/staging/media/imx/imx-media-utils.c +++ b/drivers/staging/media/imx/imx-media-utils.c @@ -7,7 +7,7 @@ #include #include "imx-media.h" -#define IMX_BUS_FMTS(fmt...) (const u32[]) {fmt, 0} +#define IMX_BUS_FMTS(fmt...) ((const u32[]) {fmt, 0}) /* * List of supported pixel formats for the subdevs. diff --git a/drivers/staging/media/imx/imx6-mipi-csi2.c b/drivers/staging/media/imx/imx6-mipi-csi2.c index c07994ea6e9626b35006794c8225881406393d3e..ab565b4e29ece1c0c5e65b99f58412fd7328411c 100644 --- a/drivers/staging/media/imx/imx6-mipi-csi2.c +++ b/drivers/staging/media/imx/imx6-mipi-csi2.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -564,6 +565,49 @@ static int csi2_registered(struct v4l2_subdev *sd) V4L2_FIELD_NONE, NULL); } +/* --------------- CORE OPS --------------- */ + +static int csi2_log_status(struct v4l2_subdev *sd) +{ + struct csi2_dev *csi2 = sd_to_dev(sd); + + v4l2_info(sd, "-----MIPI CSI status-----\n"); + v4l2_info(sd, "VERSION: 0x%x\n", + readl(csi2->base + CSI2_VERSION)); + v4l2_info(sd, "N_LANES: 0x%x\n", + readl(csi2->base + CSI2_N_LANES)); + v4l2_info(sd, "PHY_SHUTDOWNZ: 0x%x\n", + readl(csi2->base + CSI2_PHY_SHUTDOWNZ)); + v4l2_info(sd, "DPHY_RSTZ: 0x%x\n", + readl(csi2->base + CSI2_DPHY_RSTZ)); + v4l2_info(sd, "RESETN: 0x%x\n", + readl(csi2->base + CSI2_RESETN)); + v4l2_info(sd, "PHY_STATE: 0x%x\n", + readl(csi2->base + CSI2_PHY_STATE)); + v4l2_info(sd, "DATA_IDS_1: 0x%x\n", + readl(csi2->base + CSI2_DATA_IDS_1)); + v4l2_info(sd, "DATA_IDS_2: 0x%x\n", + readl(csi2->base + CSI2_DATA_IDS_2)); + v4l2_info(sd, "ERR1: 0x%x\n", + readl(csi2->base + CSI2_ERR1)); + v4l2_info(sd, "ERR2: 0x%x\n", + readl(csi2->base + CSI2_ERR2)); + v4l2_info(sd, "MSK1: 0x%x\n", + readl(csi2->base + CSI2_MSK1)); + v4l2_info(sd, "MSK2: 0x%x\n", + readl(csi2->base + CSI2_MSK2)); + v4l2_info(sd, "PHY_TST_CTRL0: 0x%x\n", + readl(csi2->base + CSI2_PHY_TST_CTRL0)); + v4l2_info(sd, "PHY_TST_CTRL1: 0x%x\n", + readl(csi2->base + CSI2_PHY_TST_CTRL1)); + + return 0; +} + +static const struct v4l2_subdev_core_ops csi2_core_ops = { + .log_status = csi2_log_status, +}; + static const struct media_entity_operations csi2_entity_ops = { .link_setup = csi2_link_setup, .link_validate = v4l2_subdev_link_validate, @@ -581,6 +625,7 @@ static const struct v4l2_subdev_pad_ops csi2_pad_ops = { }; static const struct v4l2_subdev_ops csi2_subdev_ops = { + .core = &csi2_core_ops, .video = &csi2_video_ops, .pad = &csi2_pad_ops, }; diff --git a/drivers/staging/media/max96712/max96712.c b/drivers/staging/media/max96712/max96712.c index 99b333b681987ed49023bf83dbebca745ea42d4b..c44145284aa18f30c07b3f961b5fcac961daad14 100644 --- a/drivers/staging/media/max96712/max96712.c +++ b/drivers/staging/media/max96712/max96712.c @@ -30,6 +30,7 @@ struct max96712_priv { struct regmap *regmap; struct gpio_desc *gpiod_pwdn; + bool cphy; struct v4l2_mbus_config_mipi_csi2 mipi; struct v4l2_subdev sd; @@ -127,10 +128,18 @@ static void max96712_mipi_configure(struct max96712_priv *priv) /* Select 2x4 mode. */ max96712_write(priv, 0x8a0, 0x04); - /* Configure a 4-lane DPHY using PHY0 and PHY1. */ /* TODO: Add support for 2-lane and 1-lane configurations. */ - /* TODO: Add support CPHY mode. */ - max96712_write(priv, 0x94a, 0xc0); + if (priv->cphy) { + /* Configure a 3-lane C-PHY using PHY0 and PHY1. */ + max96712_write(priv, 0x94a, 0xa0); + + /* Configure C-PHY timings. */ + max96712_write(priv, 0x8ad, 0x3f); + max96712_write(priv, 0x8ae, 0x7d); + } else { + /* Configure a 4-lane D-PHY using PHY0 and PHY1. */ + max96712_write(priv, 0x94a, 0xc0); + } /* Configure lane mapping for PHY0 and PHY1. */ /* TODO: Add support for lane swapping. */ @@ -332,8 +341,9 @@ static int max96712_parse_dt(struct max96712_priv *priv) { struct fwnode_handle *ep; struct v4l2_fwnode_endpoint v4l2_ep = { - .bus_type = V4L2_MBUS_CSI2_DPHY + .bus_type = V4L2_MBUS_UNKNOWN, }; + unsigned int supported_lanes; int ret; ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(&priv->client->dev), 4, @@ -350,8 +360,24 @@ static int max96712_parse_dt(struct max96712_priv *priv) return -EINVAL; } - if (v4l2_ep.bus.mipi_csi2.num_data_lanes != 4) { - dev_err(&priv->client->dev, "Only 4 data lanes supported\n"); + switch (v4l2_ep.bus_type) { + case V4L2_MBUS_CSI2_DPHY: + supported_lanes = 4; + priv->cphy = false; + break; + case V4L2_MBUS_CSI2_CPHY: + supported_lanes = 3; + priv->cphy = true; + break; + default: + dev_err(&priv->client->dev, "Unsupported bus-type %u\n", + v4l2_ep.bus_type); + return -EINVAL; + } + + if (v4l2_ep.bus.mipi_csi2.num_data_lanes != supported_lanes) { + dev_err(&priv->client->dev, "Only %u data lanes supported\n", + supported_lanes); return -EINVAL; } @@ -427,7 +453,7 @@ static struct i2c_driver max96712_i2c_driver = { .name = "max96712", .of_match_table = of_match_ptr(max96712_of_table), }, - .probe_new = max96712_probe, + .probe = max96712_probe, .remove = max96712_remove, }; diff --git a/drivers/staging/media/tegra-video/Kconfig b/drivers/staging/media/tegra-video/Kconfig index df1b2cff2417712a07e215d46494eb1a8d9a646a..c53441822fdf2402d2e4f98f9c97a8ec2f9aad6e 100644 --- a/drivers/staging/media/tegra-video/Kconfig +++ b/drivers/staging/media/tegra-video/Kconfig @@ -15,5 +15,6 @@ config VIDEO_TEGRA config VIDEO_TEGRA_TPG bool "NVIDIA Tegra VI driver TPG mode" depends on VIDEO_TEGRA + depends on ARCH_TEGRA_210_SOC help Say yes here to enable Tegra internal TPG mode diff --git a/drivers/staging/media/tegra-video/Makefile b/drivers/staging/media/tegra-video/Makefile index dfa2ef8f99efc3fdfe0317e03359fa99933cbd75..6c7552e05109ea881f9db64f9a5de1b376d1b560 100644 --- a/drivers/staging/media/tegra-video/Makefile +++ b/drivers/staging/media/tegra-video/Makefile @@ -2,7 +2,9 @@ tegra-video-objs := \ video.o \ vi.o \ + vip.o \ csi.o +tegra-video-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra20.o tegra-video-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210.o obj-$(CONFIG_VIDEO_TEGRA) += tegra-video.o diff --git a/drivers/staging/media/tegra-video/csi.c b/drivers/staging/media/tegra-video/csi.c index 36ca639622c92c509b8de3fa512603183e877ade..052172017b3bd91e6f1dd8080dc58ecfd32ee96a 100644 --- a/drivers/staging/media/tegra-video/csi.c +++ b/drivers/staging/media/tegra-video/csi.c @@ -328,12 +328,42 @@ static int tegra_csi_enable_stream(struct v4l2_subdev *subdev) } csi_chan->pg_mode = chan->pg_mode; + + /* + * Tegra CSI receiver can detect the first LP to HS transition. + * So, start the CSI stream-on prior to sensor stream-on and + * vice-versa for stream-off. + */ ret = csi->ops->csi_start_streaming(csi_chan); if (ret < 0) goto finish_calibration; + if (csi_chan->mipi) { + struct v4l2_subdev *src_subdev; + /* + * TRM has incorrectly documented to wait for done status from + * calibration logic after CSI interface power on. + * As per the design, calibration results are latched and applied + * to the pads only when the link is in LP11 state which will happen + * during the sensor stream-on. + * CSI subdev stream-on triggers start of MIPI pads calibration. + * Wait for calibration to finish here after sensor subdev stream-on. + */ + src_subdev = tegra_channel_get_remote_source_subdev(chan); + ret = v4l2_subdev_call(src_subdev, video, s_stream, true); + + if (ret < 0 && ret != -ENOIOCTLCMD) + goto disable_csi_stream; + + err = tegra_mipi_finish_calibration(csi_chan->mipi); + if (err < 0) + dev_warn(csi->dev, "MIPI calibration failed: %d\n", err); + } + return 0; +disable_csi_stream: + csi->ops->csi_stop_streaming(csi_chan); finish_calibration: if (csi_chan->mipi) tegra_mipi_finish_calibration(csi_chan->mipi); @@ -352,10 +382,24 @@ static int tegra_csi_enable_stream(struct v4l2_subdev *subdev) static int tegra_csi_disable_stream(struct v4l2_subdev *subdev) { + struct tegra_vi_channel *chan = v4l2_get_subdev_hostdata(subdev); struct tegra_csi_channel *csi_chan = to_csi_chan(subdev); struct tegra_csi *csi = csi_chan->csi; int err; + /* + * Stream-off subdevices in reverse order to stream-on. + * Remote source subdev in TPG mode is same as CSI subdev. + */ + if (csi_chan->mipi) { + struct v4l2_subdev *src_subdev; + + src_subdev = tegra_channel_get_remote_source_subdev(chan); + err = v4l2_subdev_call(src_subdev, video, s_stream, false); + if (err < 0 && err != -ENOIOCTLCMD) + dev_err_probe(csi->dev, err, "source subdev stream off failed\n"); + } + csi->ops->csi_stop_streaming(csi_chan); if (csi_chan->mipi) { @@ -786,6 +830,10 @@ static int tegra_csi_remove(struct platform_device *pdev) return 0; } +#if defined(CONFIG_ARCH_TEGRA_210_SOC) +extern const struct tegra_csi_soc tegra210_csi_soc; +#endif + static const struct of_device_id tegra_csi_of_id_table[] = { #if defined(CONFIG_ARCH_TEGRA_210_SOC) { .compatible = "nvidia,tegra210-csi", .data = &tegra210_csi_soc }, diff --git a/drivers/staging/media/tegra-video/csi.h b/drivers/staging/media/tegra-video/csi.h index 6960ea2e3d36076a39a5f576617afb627fda5dfc..3e6e5ee1bb1e645c2c46ffe105976c12941b7561 100644 --- a/drivers/staging/media/tegra-video/csi.h +++ b/drivers/staging/media/tegra-video/csi.h @@ -151,10 +151,6 @@ struct tegra_csi { struct list_head csi_chans; }; -#if defined(CONFIG_ARCH_TEGRA_210_SOC) -extern const struct tegra_csi_soc tegra210_csi_soc; -#endif - void tegra_csi_error_recover(struct v4l2_subdev *subdev); void tegra_csi_calc_settle_time(struct tegra_csi_channel *csi_chan, u8 csi_port_num, diff --git a/drivers/staging/media/tegra-video/tegra20.c b/drivers/staging/media/tegra-video/tegra20.c new file mode 100644 index 0000000000000000000000000000000000000000..c25286772603c9ad370cd11ba3fca4c3b86cec64 --- /dev/null +++ b/drivers/staging/media/tegra-video/tegra20.c @@ -0,0 +1,661 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Tegra20-specific VI implementation + * + * Copyright (C) 2023 SKIDATA GmbH + * Author: Luca Ceresoli + */ + +/* + * This source file contains Tegra20 supported video formats, + * VI and VIP SoC specific data, operations and registers accessors. + */ + +#include +#include +#include +#include +#include +#include + +#include "vip.h" +#include "vi.h" + +#define TEGRA_VI_SYNCPT_WAIT_TIMEOUT msecs_to_jiffies(200) + +/* This are just good-sense numbers. The actual min/max is not documented. */ +#define TEGRA20_MIN_WIDTH 32U +#define TEGRA20_MIN_HEIGHT 32U +#define TEGRA20_MAX_WIDTH 2048U +#define TEGRA20_MAX_HEIGHT 2048U + +/* -------------------------------------------------------------------------- + * Registers + */ + +#define TEGRA_VI_CONT_SYNCPT_OUT_1 0x0060 +#define VI_CONT_SYNCPT_OUT_1_CONTINUOUS_SYNCPT BIT(8) +#define VI_CONT_SYNCPT_OUT_1_SYNCPT_IDX_SFT 0 + +#define TEGRA_VI_VI_INPUT_CONTROL 0x0088 +#define VI_INPUT_FIELD_DETECT BIT(27) +#define VI_INPUT_BT656 BIT(25) +#define VI_INPUT_YUV_INPUT_FORMAT_SFT 8 /* bits [9:8] */ +#define VI_INPUT_YUV_INPUT_FORMAT_UYVY (0 << VI_INPUT_YUV_INPUT_FORMAT_SFT) +#define VI_INPUT_YUV_INPUT_FORMAT_VYUY (1 << VI_INPUT_YUV_INPUT_FORMAT_SFT) +#define VI_INPUT_YUV_INPUT_FORMAT_YUYV (2 << VI_INPUT_YUV_INPUT_FORMAT_SFT) +#define VI_INPUT_YUV_INPUT_FORMAT_YVYU (3 << VI_INPUT_YUV_INPUT_FORMAT_SFT) +#define VI_INPUT_INPUT_FORMAT_SFT 2 /* bits [5:2] */ +#define VI_INPUT_INPUT_FORMAT_YUV422 (0 << VI_INPUT_INPUT_FORMAT_SFT) +#define VI_INPUT_VIP_INPUT_ENABLE BIT(1) + +#define TEGRA_VI_VI_CORE_CONTROL 0x008c +#define VI_VI_CORE_CONTROL_PLANAR_CONV_IN_SEL_EXT BIT(31) +#define VI_VI_CORE_CONTROL_CSC_INPUT_SEL_EXT BIT(30) +#define VI_VI_CORE_CONTROL_INPUT_TO_ALT_MUX_SFT 27 +#define VI_VI_CORE_CONTROL_INPUT_TO_CORE_EXT_SFT 24 +#define VI_VI_CORE_CONTROL_OUTPUT_TO_ISP_EXT_SFT 21 +#define VI_VI_CORE_CONTROL_ISP_HOST_STALL_OFF BIT(20) +#define VI_VI_CORE_CONTROL_V_DOWNSCALING BIT(19) +#define VI_VI_CORE_CONTROL_V_AVERAGING BIT(18) +#define VI_VI_CORE_CONTROL_H_DOWNSCALING BIT(17) +#define VI_VI_CORE_CONTROL_H_AVERAGING BIT(16) +#define VI_VI_CORE_CONTROL_CSC_INPUT_SEL BIT(11) +#define VI_VI_CORE_CONTROL_PLANAR_CONV_INPUT_SEL BIT(10) +#define VI_VI_CORE_CONTROL_INPUT_TO_CORE_SFT 8 +#define VI_VI_CORE_CONTROL_ISP_DOWNSAMPLE_SFT 5 +#define VI_VI_CORE_CONTROL_OUTPUT_TO_EPP_SFT 2 +#define VI_VI_CORE_CONTROL_OUTPUT_TO_ISP_SFT 0 + +#define TEGRA_VI_VI_FIRST_OUTPUT_CONTROL 0x0090 +#define VI_OUTPUT_FORMAT_EXT BIT(22) +#define VI_OUTPUT_V_DIRECTION BIT(20) +#define VI_OUTPUT_H_DIRECTION BIT(19) +#define VI_OUTPUT_YUV_OUTPUT_FORMAT_SFT 17 +#define VI_OUTPUT_YUV_OUTPUT_FORMAT_UYVY (0 << VI_OUTPUT_YUV_OUTPUT_FORMAT_SFT) +#define VI_OUTPUT_YUV_OUTPUT_FORMAT_VYUY (1 << VI_OUTPUT_YUV_OUTPUT_FORMAT_SFT) +#define VI_OUTPUT_YUV_OUTPUT_FORMAT_YUYV (2 << VI_OUTPUT_YUV_OUTPUT_FORMAT_SFT) +#define VI_OUTPUT_YUV_OUTPUT_FORMAT_YVYU (3 << VI_OUTPUT_YUV_OUTPUT_FORMAT_SFT) +#define VI_OUTPUT_OUTPUT_BYTE_SWAP BIT(16) +#define VI_OUTPUT_LAST_PIXEL_DUPLICATION BIT(8) +#define VI_OUTPUT_OUTPUT_FORMAT_SFT 0 +#define VI_OUTPUT_OUTPUT_FORMAT_YUV422POST (3 << VI_OUTPUT_OUTPUT_FORMAT_SFT) +#define VI_OUTPUT_OUTPUT_FORMAT_YUV420PLANAR (6 << VI_OUTPUT_OUTPUT_FORMAT_SFT) + +#define TEGRA_VI_VIP_H_ACTIVE 0x00a4 +#define VI_VIP_H_ACTIVE_PERIOD_SFT 16 /* active pixels/line, must be even */ +#define VI_VIP_H_ACTIVE_START_SFT 0 + +#define TEGRA_VI_VIP_V_ACTIVE 0x00a8 +#define VI_VIP_V_ACTIVE_PERIOD_SFT 16 /* active lines */ +#define VI_VIP_V_ACTIVE_START_SFT 0 + +#define TEGRA_VI_VB0_START_ADDRESS_FIRST 0x00c4 +#define TEGRA_VI_VB0_BASE_ADDRESS_FIRST 0x00c8 +#define TEGRA_VI_VB0_START_ADDRESS_U 0x00cc +#define TEGRA_VI_VB0_BASE_ADDRESS_U 0x00d0 +#define TEGRA_VI_VB0_START_ADDRESS_V 0x00d4 +#define TEGRA_VI_VB0_BASE_ADDRESS_V 0x00d8 + +#define TEGRA_VI_FIRST_OUTPUT_FRAME_SIZE 0x00e0 +#define VI_FIRST_OUTPUT_FRAME_HEIGHT_SFT 16 +#define VI_FIRST_OUTPUT_FRAME_WIDTH_SFT 0 + +#define TEGRA_VI_VB0_COUNT_FIRST 0x00e4 + +#define TEGRA_VI_VB0_SIZE_FIRST 0x00e8 +#define VI_VB0_SIZE_FIRST_V_SFT 16 +#define VI_VB0_SIZE_FIRST_H_SFT 0 + +#define TEGRA_VI_VB0_BUFFER_STRIDE_FIRST 0x00ec +#define VI_VB0_BUFFER_STRIDE_FIRST_CHROMA_SFT 30 +#define VI_VB0_BUFFER_STRIDE_FIRST_LUMA_SFT 0 + +#define TEGRA_VI_H_LPF_CONTROL 0x0108 +#define VI_H_LPF_CONTROL_CHROMA_SFT 16 +#define VI_H_LPF_CONTROL_LUMA_SFT 0 + +#define TEGRA_VI_H_DOWNSCALE_CONTROL 0x010c +#define TEGRA_VI_V_DOWNSCALE_CONTROL 0x0110 + +#define TEGRA_VI_VIP_INPUT_STATUS 0x0144 + +#define TEGRA_VI_VI_DATA_INPUT_CONTROL 0x0168 +#define VI_DATA_INPUT_SFT 0 /* [11:0] = mask pin inputs to VI core */ + +#define TEGRA_VI_PIN_INPUT_ENABLE 0x016c +#define VI_PIN_INPUT_VSYNC BIT(14) +#define VI_PIN_INPUT_HSYNC BIT(13) +#define VI_PIN_INPUT_VD_SFT 0 /* [11:0] = data bin N input enable */ + +#define TEGRA_VI_PIN_INVERSION 0x0174 +#define VI_PIN_INVERSION_VSYNC_ACTIVE_HIGH BIT(1) +#define VI_PIN_INVERSION_HSYNC_ACTIVE_HIGH BIT(0) + +#define TEGRA_VI_CAMERA_CONTROL 0x01a0 +#define VI_CAMERA_CONTROL_STOP_CAPTURE BIT(2) +#define VI_CAMERA_CONTROL_TEST_MODE BIT(1) +#define VI_CAMERA_CONTROL_VIP_ENABLE BIT(0) + +#define TEGRA_VI_VI_ENABLE 0x01a4 +#define VI_VI_ENABLE_SW_FLOW_CONTROL_OUT1 BIT(1) +#define VI_VI_ENABLE_FIRST_OUTPUT_TO_MEM_DISABLE BIT(0) + +#define TEGRA_VI_VI_RAISE 0x01ac +#define VI_VI_RAISE_ON_EDGE BIT(0) + +/* -------------------------------------------------------------------------- + * VI + */ + +static void tegra20_vi_write(struct tegra_vi_channel *chan, unsigned int addr, u32 val) +{ + writel(val, chan->vi->iomem + addr); +} + +/* + * Get the main input format (YUV/RGB...) and the YUV variant as values to + * be written into registers for the current VI input mbus code. + */ +static void tegra20_vi_get_input_formats(struct tegra_vi_channel *chan, + unsigned int *main_input_format, + unsigned int *yuv_input_format) +{ + unsigned int input_mbus_code = chan->fmtinfo->code; + + (*main_input_format) = VI_INPUT_INPUT_FORMAT_YUV422; + + switch (input_mbus_code) { + case MEDIA_BUS_FMT_UYVY8_2X8: + (*yuv_input_format) = VI_INPUT_YUV_INPUT_FORMAT_UYVY; + break; + case MEDIA_BUS_FMT_VYUY8_2X8: + (*yuv_input_format) = VI_INPUT_YUV_INPUT_FORMAT_VYUY; + break; + case MEDIA_BUS_FMT_YUYV8_2X8: + (*yuv_input_format) = VI_INPUT_YUV_INPUT_FORMAT_YUYV; + break; + case MEDIA_BUS_FMT_YVYU8_2X8: + (*yuv_input_format) = VI_INPUT_YUV_INPUT_FORMAT_YVYU; + break; + } +} + +/* + * Get the main output format (YUV/RGB...) and the YUV variant as values to + * be written into registers for the current VI output pixel format. + */ +static void tegra20_vi_get_output_formats(struct tegra_vi_channel *chan, + unsigned int *main_output_format, + unsigned int *yuv_output_format) +{ + u32 output_fourcc = chan->format.pixelformat; + + /* Default to YUV422 non-planar (U8Y8V8Y8) after downscaling */ + (*main_output_format) = VI_OUTPUT_OUTPUT_FORMAT_YUV422POST; + (*yuv_output_format) = VI_OUTPUT_YUV_OUTPUT_FORMAT_UYVY; + + switch (output_fourcc) { + case V4L2_PIX_FMT_UYVY: + (*yuv_output_format) = VI_OUTPUT_YUV_OUTPUT_FORMAT_UYVY; + break; + case V4L2_PIX_FMT_VYUY: + (*yuv_output_format) = VI_OUTPUT_YUV_OUTPUT_FORMAT_VYUY; + break; + case V4L2_PIX_FMT_YUYV: + (*yuv_output_format) = VI_OUTPUT_YUV_OUTPUT_FORMAT_YUYV; + break; + case V4L2_PIX_FMT_YVYU: + (*yuv_output_format) = VI_OUTPUT_YUV_OUTPUT_FORMAT_YVYU; + break; + case V4L2_PIX_FMT_YUV420: + case V4L2_PIX_FMT_YVU420: + (*main_output_format) = VI_OUTPUT_OUTPUT_FORMAT_YUV420PLANAR; + break; + } +} + +/* + * Make the VI accessible (needed on Tegra20). + * + * This function writes an unknown bit into an unknown register. The code + * comes from a downstream 3.1 kernel that has a working VIP driver for + * Tegra20, and removing it makes the VI completely unaccessible. It should + * be rewritten and possibly moved elsewhere, but the appropriate location + * and implementation is unknown due to a total lack of documentation. + */ +static int tegra20_vi_enable(struct tegra_vi *vi, bool on) +{ + /* from arch/arm/mach-tegra/iomap.h */ + const phys_addr_t TEGRA_APB_MISC_BASE = 0x70000000; + const unsigned long reg_offset = 0x42c; + void __iomem *apb_misc; + u32 val; + + apb_misc = ioremap(TEGRA_APB_MISC_BASE, PAGE_SIZE); + if (!apb_misc) + apb_misc = ERR_PTR(-ENOENT); + if (IS_ERR(apb_misc)) + return dev_err_probe(vi->dev, PTR_ERR(apb_misc), "cannot access APB_MISC"); + + val = readl(apb_misc + reg_offset); + val &= ~BIT(0); + val |= on ? BIT(0) : 0; + writel(val, apb_misc + reg_offset); + iounmap(apb_misc); + + return 0; +} + +static int tegra20_channel_host1x_syncpt_init(struct tegra_vi_channel *chan) +{ + struct tegra_vi *vi = chan->vi; + struct host1x_syncpt *out_sp; + + out_sp = host1x_syncpt_request(&vi->client, HOST1X_SYNCPT_CLIENT_MANAGED); + if (!out_sp) + return dev_err_probe(vi->dev, -ENOMEM, "failed to request syncpoint\n"); + + chan->mw_ack_sp[0] = out_sp; + + return 0; +} + +static void tegra20_channel_host1x_syncpt_free(struct tegra_vi_channel *chan) +{ + host1x_syncpt_put(chan->mw_ack_sp[0]); +} + +static void tegra20_fmt_align(struct v4l2_pix_format *pix, unsigned int bpp) +{ + pix->width = clamp(pix->width, TEGRA20_MIN_WIDTH, TEGRA20_MAX_WIDTH); + pix->height = clamp(pix->height, TEGRA20_MIN_HEIGHT, TEGRA20_MAX_HEIGHT); + + switch (pix->pixelformat) { + case V4L2_PIX_FMT_UYVY: + case V4L2_PIX_FMT_VYUY: + case V4L2_PIX_FMT_YUYV: + case V4L2_PIX_FMT_YVYU: + pix->bytesperline = roundup(pix->width, 2) * 2; + pix->sizeimage = roundup(pix->width, 2) * 2 * pix->height; + break; + case V4L2_PIX_FMT_YUV420: + case V4L2_PIX_FMT_YVU420: + pix->bytesperline = roundup(pix->width, 8); + pix->sizeimage = roundup(pix->width, 8) * pix->height * 3 / 2; + break; + } +} + +/* + * Compute buffer offsets once per stream so that + * tegra20_channel_vi_buffer_setup() only has to do very simple maths for + * each buffer. + */ +static void tegra20_channel_queue_setup(struct tegra_vi_channel *chan) +{ + unsigned int stride = chan->format.bytesperline; + unsigned int height = chan->format.height; + + chan->start_offset = 0; + + switch (chan->format.pixelformat) { + case V4L2_PIX_FMT_UYVY: + case V4L2_PIX_FMT_VYUY: + case V4L2_PIX_FMT_YUYV: + case V4L2_PIX_FMT_YVYU: + if (chan->vflip) + chan->start_offset += stride * (height - 1); + if (chan->hflip) + chan->start_offset += stride - 1; + break; + + case V4L2_PIX_FMT_YUV420: + case V4L2_PIX_FMT_YVU420: + chan->addr_offset_u = stride * height; + chan->addr_offset_v = chan->addr_offset_u + stride * height / 4; + + /* For YVU420, we swap the locations of the U and V planes. */ + if (chan->format.pixelformat == V4L2_PIX_FMT_YVU420) { + unsigned long temp; + + temp = chan->addr_offset_u; + chan->addr_offset_u = chan->addr_offset_v; + chan->addr_offset_v = temp; + } + + chan->start_offset_u = chan->addr_offset_u; + chan->start_offset_v = chan->addr_offset_v; + + if (chan->vflip) { + chan->start_offset += stride * (height - 1); + chan->start_offset_u += (stride / 2) * ((height / 2) - 1); + chan->start_offset_v += (stride / 2) * ((height / 2) - 1); + } + if (chan->hflip) { + chan->start_offset += stride - 1; + chan->start_offset_u += (stride / 2) - 1; + chan->start_offset_v += (stride / 2) - 1; + } + break; + } +} + +static void release_buffer(struct tegra_vi_channel *chan, + struct tegra_channel_buffer *buf, + enum vb2_buffer_state state) +{ + struct vb2_v4l2_buffer *vb = &buf->buf; + + vb->sequence = chan->sequence++; + vb->field = V4L2_FIELD_NONE; + vb->vb2_buf.timestamp = ktime_get_ns(); + vb2_buffer_done(&vb->vb2_buf, state); +} + +static void tegra20_channel_vi_buffer_setup(struct tegra_vi_channel *chan, + struct tegra_channel_buffer *buf) +{ + dma_addr_t base = buf->addr; + + switch (chan->fmtinfo->fourcc) { + case V4L2_PIX_FMT_YUV420: + case V4L2_PIX_FMT_YVU420: + tegra20_vi_write(chan, TEGRA_VI_VB0_BASE_ADDRESS_U, base + chan->addr_offset_u); + tegra20_vi_write(chan, TEGRA_VI_VB0_START_ADDRESS_U, base + chan->start_offset_u); + tegra20_vi_write(chan, TEGRA_VI_VB0_BASE_ADDRESS_V, base + chan->addr_offset_v); + tegra20_vi_write(chan, TEGRA_VI_VB0_START_ADDRESS_V, base + chan->start_offset_v); + fallthrough; + + case V4L2_PIX_FMT_UYVY: + case V4L2_PIX_FMT_VYUY: + case V4L2_PIX_FMT_YUYV: + case V4L2_PIX_FMT_YVYU: + tegra20_vi_write(chan, TEGRA_VI_VB0_BASE_ADDRESS_FIRST, base); + tegra20_vi_write(chan, TEGRA_VI_VB0_START_ADDRESS_FIRST, base + chan->start_offset); + break; + } +} + +static int tegra20_channel_capture_frame(struct tegra_vi_channel *chan, + struct tegra_channel_buffer *buf) +{ + int err; + + chan->next_out_sp_idx++; + + tegra20_channel_vi_buffer_setup(chan, buf); + + tegra20_vi_write(chan, TEGRA_VI_CAMERA_CONTROL, VI_CAMERA_CONTROL_VIP_ENABLE); + + /* Wait for syncpt counter to reach frame start event threshold */ + err = host1x_syncpt_wait(chan->mw_ack_sp[0], chan->next_out_sp_idx, + TEGRA_VI_SYNCPT_WAIT_TIMEOUT, NULL); + if (err) { + host1x_syncpt_incr(chan->mw_ack_sp[0]); + dev_err_ratelimited(&chan->video.dev, "frame start syncpt timeout: %d\n", err); + release_buffer(chan, buf, VB2_BUF_STATE_ERROR); + return err; + } + + tegra20_vi_write(chan, TEGRA_VI_CAMERA_CONTROL, + VI_CAMERA_CONTROL_STOP_CAPTURE | VI_CAMERA_CONTROL_VIP_ENABLE); + + release_buffer(chan, buf, VB2_BUF_STATE_DONE); + + return 0; +} + +static int tegra20_chan_capture_kthread_start(void *data) +{ + struct tegra_vi_channel *chan = data; + struct tegra_channel_buffer *buf; + unsigned int retries = 0; + int err = 0; + + while (1) { + /* + * Source is not streaming if error is non-zero. + * So, do not dequeue buffers on error and let the thread sleep + * till kthread stop signal is received. + */ + wait_event_interruptible(chan->start_wait, + kthread_should_stop() || + (!list_empty(&chan->capture) && !err)); + + if (kthread_should_stop()) + break; + + /* dequeue the buffer and start capture */ + spin_lock(&chan->start_lock); + if (list_empty(&chan->capture)) { + spin_unlock(&chan->start_lock); + continue; + } + + buf = list_first_entry(&chan->capture, struct tegra_channel_buffer, queue); + list_del_init(&buf->queue); + spin_unlock(&chan->start_lock); + + err = tegra20_channel_capture_frame(chan, buf); + if (!err) { + retries = 0; + continue; + } + + if (retries++ > chan->syncpt_timeout_retry) + vb2_queue_error(&chan->queue); + else + err = 0; + } + + return 0; +} + +static void tegra20_camera_capture_setup(struct tegra_vi_channel *chan) +{ + u32 output_fourcc = chan->format.pixelformat; + int width = chan->format.width; + int height = chan->format.height; + int stride_l = chan->format.bytesperline; + int stride_c = (output_fourcc == V4L2_PIX_FMT_YUV420 || + output_fourcc == V4L2_PIX_FMT_YVU420) ? 1 : 0; + int main_output_format; + int yuv_output_format; + + tegra20_vi_get_output_formats(chan, &main_output_format, &yuv_output_format); + + /* + * Set up low pass filter. Use 0x240 for chromaticity and 0x240 + * for luminance, which is the default and means not to touch + * anything. + */ + tegra20_vi_write(chan, TEGRA_VI_H_LPF_CONTROL, + 0x0240 << VI_H_LPF_CONTROL_LUMA_SFT | + 0x0240 << VI_H_LPF_CONTROL_CHROMA_SFT); + + /* Set up raise-on-edge, so we get an interrupt on end of frame. */ + tegra20_vi_write(chan, TEGRA_VI_VI_RAISE, VI_VI_RAISE_ON_EDGE); + + tegra20_vi_write(chan, TEGRA_VI_VI_FIRST_OUTPUT_CONTROL, + (chan->vflip ? VI_OUTPUT_V_DIRECTION : 0) | + (chan->hflip ? VI_OUTPUT_H_DIRECTION : 0) | + yuv_output_format << VI_OUTPUT_YUV_OUTPUT_FORMAT_SFT | + main_output_format << VI_OUTPUT_OUTPUT_FORMAT_SFT); + + /* Set up frame size */ + tegra20_vi_write(chan, TEGRA_VI_FIRST_OUTPUT_FRAME_SIZE, + height << VI_FIRST_OUTPUT_FRAME_HEIGHT_SFT | + width << VI_FIRST_OUTPUT_FRAME_WIDTH_SFT); + + /* First output memory enabled */ + tegra20_vi_write(chan, TEGRA_VI_VI_ENABLE, 0); + + /* Set the number of frames in the buffer */ + tegra20_vi_write(chan, TEGRA_VI_VB0_COUNT_FIRST, 1); + + /* Set up buffer frame size */ + tegra20_vi_write(chan, TEGRA_VI_VB0_SIZE_FIRST, + height << VI_VB0_SIZE_FIRST_V_SFT | + width << VI_VB0_SIZE_FIRST_H_SFT); + + tegra20_vi_write(chan, TEGRA_VI_VB0_BUFFER_STRIDE_FIRST, + stride_l << VI_VB0_BUFFER_STRIDE_FIRST_LUMA_SFT | + stride_c << VI_VB0_BUFFER_STRIDE_FIRST_CHROMA_SFT); + + tegra20_vi_write(chan, TEGRA_VI_VI_ENABLE, 0); +} + +static int tegra20_vi_start_streaming(struct vb2_queue *vq, u32 count) +{ + struct tegra_vi_channel *chan = vb2_get_drv_priv(vq); + struct media_pipeline *pipe = &chan->video.pipe; + int err; + + chan->next_out_sp_idx = host1x_syncpt_read(chan->mw_ack_sp[0]); + + err = video_device_pipeline_start(&chan->video, pipe); + if (err) + goto error_pipeline_start; + + tegra20_camera_capture_setup(chan); + + err = tegra_channel_set_stream(chan, true); + if (err) + goto error_set_stream; + + chan->sequence = 0; + + chan->kthread_start_capture = kthread_run(tegra20_chan_capture_kthread_start, + chan, "%s:0", chan->video.name); + if (IS_ERR(chan->kthread_start_capture)) { + err = PTR_ERR(chan->kthread_start_capture); + chan->kthread_start_capture = NULL; + dev_err_probe(&chan->video.dev, err, "failed to run capture kthread\n"); + goto error_kthread_start; + } + + return 0; + +error_kthread_start: + tegra_channel_set_stream(chan, false); +error_set_stream: + video_device_pipeline_stop(&chan->video); +error_pipeline_start: + tegra_channel_release_buffers(chan, VB2_BUF_STATE_QUEUED); + + return err; +} + +static void tegra20_vi_stop_streaming(struct vb2_queue *vq) +{ + struct tegra_vi_channel *chan = vb2_get_drv_priv(vq); + + if (chan->kthread_start_capture) { + kthread_stop(chan->kthread_start_capture); + chan->kthread_start_capture = NULL; + } + + tegra_channel_release_buffers(chan, VB2_BUF_STATE_ERROR); + tegra_channel_set_stream(chan, false); + video_device_pipeline_stop(&chan->video); +} + +static const struct tegra_vi_ops tegra20_vi_ops = { + .vi_enable = tegra20_vi_enable, + .channel_host1x_syncpt_init = tegra20_channel_host1x_syncpt_init, + .channel_host1x_syncpt_free = tegra20_channel_host1x_syncpt_free, + .vi_fmt_align = tegra20_fmt_align, + .channel_queue_setup = tegra20_channel_queue_setup, + .vi_start_streaming = tegra20_vi_start_streaming, + .vi_stop_streaming = tegra20_vi_stop_streaming, +}; + +#define TEGRA20_VIDEO_FMT(MBUS_CODE, BPP, FOURCC) \ +{ \ + .code = MEDIA_BUS_FMT_##MBUS_CODE, \ + .bpp = BPP, \ + .fourcc = V4L2_PIX_FMT_##FOURCC, \ +} + +static const struct tegra_video_format tegra20_video_formats[] = { + TEGRA20_VIDEO_FMT(UYVY8_2X8, 2, UYVY), + TEGRA20_VIDEO_FMT(VYUY8_2X8, 2, VYUY), + TEGRA20_VIDEO_FMT(YUYV8_2X8, 2, YUYV), + TEGRA20_VIDEO_FMT(YVYU8_2X8, 2, YVYU), + TEGRA20_VIDEO_FMT(UYVY8_2X8, 1, YUV420), + TEGRA20_VIDEO_FMT(UYVY8_2X8, 1, YVU420), +}; + +const struct tegra_vi_soc tegra20_vi_soc = { + .video_formats = tegra20_video_formats, + .nformats = ARRAY_SIZE(tegra20_video_formats), + .default_video_format = &tegra20_video_formats[0], + .ops = &tegra20_vi_ops, + .vi_max_channels = 1, /* parallel input (VIP) */ + .vi_max_clk_hz = 150000000, + .has_h_v_flip = true, +}; + +/* -------------------------------------------------------------------------- + * VIP + */ + +/* + * VIP-specific configuration for stream start. + * + * Whatever is common among VIP and CSI is done by the VI component (see + * tegra20_vi_start_streaming()). Here we do what is VIP-specific. + */ +static int tegra20_vip_start_streaming(struct tegra_vip_channel *vip_chan) +{ + struct tegra_vi_channel *vi_chan = v4l2_get_subdev_hostdata(&vip_chan->subdev); + int width = vi_chan->format.width; + int height = vi_chan->format.height; + + unsigned int main_input_format; + unsigned int yuv_input_format; + + tegra20_vi_get_input_formats(vi_chan, &main_input_format, &yuv_input_format); + + tegra20_vi_write(vi_chan, TEGRA_VI_VI_CORE_CONTROL, 0); + + tegra20_vi_write(vi_chan, TEGRA_VI_VI_INPUT_CONTROL, + VI_INPUT_VIP_INPUT_ENABLE | main_input_format | yuv_input_format); + + tegra20_vi_write(vi_chan, TEGRA_VI_V_DOWNSCALE_CONTROL, 0); + tegra20_vi_write(vi_chan, TEGRA_VI_H_DOWNSCALE_CONTROL, 0); + + tegra20_vi_write(vi_chan, TEGRA_VI_VIP_V_ACTIVE, height << VI_VIP_V_ACTIVE_PERIOD_SFT); + tegra20_vi_write(vi_chan, TEGRA_VI_VIP_H_ACTIVE, + roundup(width, 2) << VI_VIP_H_ACTIVE_PERIOD_SFT); + + /* + * For VIP, D9..D2 is mapped to the video decoder's P7..P0. + * Disable/mask out the other Dn wires. When not in BT656 + * mode we also need the V/H sync. + */ + tegra20_vi_write(vi_chan, TEGRA_VI_PIN_INPUT_ENABLE, + GENMASK(9, 2) << VI_PIN_INPUT_VD_SFT | + VI_PIN_INPUT_HSYNC | VI_PIN_INPUT_VSYNC); + tegra20_vi_write(vi_chan, TEGRA_VI_VI_DATA_INPUT_CONTROL, + GENMASK(9, 2) << VI_DATA_INPUT_SFT); + tegra20_vi_write(vi_chan, TEGRA_VI_PIN_INVERSION, 0); + + tegra20_vi_write(vi_chan, TEGRA_VI_CONT_SYNCPT_OUT_1, + VI_CONT_SYNCPT_OUT_1_CONTINUOUS_SYNCPT | + host1x_syncpt_id(vi_chan->mw_ack_sp[0]) + << VI_CONT_SYNCPT_OUT_1_SYNCPT_IDX_SFT); + + tegra20_vi_write(vi_chan, TEGRA_VI_CAMERA_CONTROL, VI_CAMERA_CONTROL_STOP_CAPTURE); + + return 0; +} + +static const struct tegra_vip_ops tegra20_vip_ops = { + .vip_start_streaming = tegra20_vip_start_streaming, +}; + +const struct tegra_vip_soc tegra20_vip_soc = { + .ops = &tegra20_vip_ops, +}; diff --git a/drivers/staging/media/tegra-video/tegra210.c b/drivers/staging/media/tegra-video/tegra210.c index d58370a84737aff367aae34a55888330357ed039..da99f19a39e7b78ffc881b5fb8660e56e31e9d7b 100644 --- a/drivers/staging/media/tegra-video/tegra210.c +++ b/drivers/staging/media/tegra-video/tegra210.c @@ -17,6 +17,13 @@ #include "csi.h" #include "vi.h" +#define TEGRA210_MIN_WIDTH 32U +#define TEGRA210_MAX_WIDTH 32768U +#define TEGRA210_MIN_HEIGHT 32U +#define TEGRA210_MAX_HEIGHT 32768U + +#define SURFACE_ALIGN_BYTES 64 + #define TEGRA_VI_SYNCPT_WAIT_TIMEOUT msecs_to_jiffies(200) /* Tegra210 VI registers */ @@ -172,6 +179,84 @@ static u32 vi_csi_read(struct tegra_vi_channel *chan, u8 portno, /* * Tegra210 VI channel capture operations */ + +static int tegra210_channel_host1x_syncpt_init(struct tegra_vi_channel *chan) +{ + struct tegra_vi *vi = chan->vi; + unsigned long flags = HOST1X_SYNCPT_CLIENT_MANAGED; + struct host1x_syncpt *fs_sp; + struct host1x_syncpt *mw_sp; + int ret, i; + + for (i = 0; i < chan->numgangports; i++) { + fs_sp = host1x_syncpt_request(&vi->client, flags); + if (!fs_sp) { + dev_err(vi->dev, "failed to request frame start syncpoint\n"); + ret = -ENOMEM; + goto free_syncpts; + } + + mw_sp = host1x_syncpt_request(&vi->client, flags); + if (!mw_sp) { + dev_err(vi->dev, "failed to request memory ack syncpoint\n"); + host1x_syncpt_put(fs_sp); + ret = -ENOMEM; + goto free_syncpts; + } + + chan->frame_start_sp[i] = fs_sp; + chan->mw_ack_sp[i] = mw_sp; + spin_lock_init(&chan->sp_incr_lock[i]); + } + + return 0; + +free_syncpts: + for (i = 0; i < chan->numgangports; i++) { + host1x_syncpt_put(chan->mw_ack_sp[i]); + host1x_syncpt_put(chan->frame_start_sp[i]); + } + return ret; +} + +static void tegra210_channel_host1x_syncpt_free(struct tegra_vi_channel *chan) +{ + int i; + + for (i = 0; i < chan->numgangports; i++) { + host1x_syncpt_put(chan->mw_ack_sp[i]); + host1x_syncpt_put(chan->frame_start_sp[i]); + } +} + +static void tegra210_fmt_align(struct v4l2_pix_format *pix, unsigned int bpp) +{ + unsigned int min_bpl; + unsigned int max_bpl; + unsigned int bpl; + + /* + * The transfer alignment requirements are expressed in bytes. + * Clamp the requested width and height to the limits. + */ + pix->width = clamp(pix->width, TEGRA210_MIN_WIDTH, TEGRA210_MAX_WIDTH); + pix->height = clamp(pix->height, TEGRA210_MIN_HEIGHT, TEGRA210_MAX_HEIGHT); + + /* Clamp the requested bytes per line value. If the maximum bytes per + * line value is zero, the module doesn't support user configurable + * line sizes. Override the requested value with the minimum in that + * case. + */ + min_bpl = pix->width * bpp; + max_bpl = rounddown(TEGRA210_MAX_WIDTH, SURFACE_ALIGN_BYTES); + bpl = roundup(pix->bytesperline, SURFACE_ALIGN_BYTES); + + pix->bytesperline = clamp(bpl, min_bpl, max_bpl); + pix->sizeimage = pix->bytesperline * pix->height; + if (pix->pixelformat == V4L2_PIX_FMT_NV16) + pix->sizeimage *= 2; +} + static int tegra_channel_capture_setup(struct tegra_vi_channel *chan, u8 portno) { @@ -718,6 +803,9 @@ static const struct tegra_video_format tegra210_video_formats[] = { /* Tegra210 VI operations */ static const struct tegra_vi_ops tegra210_vi_ops = { + .channel_host1x_syncpt_init = tegra210_channel_host1x_syncpt_init, + .channel_host1x_syncpt_free = tegra210_channel_host1x_syncpt_free, + .vi_fmt_align = tegra210_fmt_align, .vi_start_streaming = tegra210_vi_start_streaming, .vi_stop_streaming = tegra210_vi_stop_streaming, }; @@ -730,8 +818,10 @@ const struct tegra_vi_soc tegra210_vi_soc = { .hw_revision = 3, .vi_max_channels = 6, #if IS_ENABLED(CONFIG_VIDEO_TEGRA_TPG) + .default_video_format = &tegra210_video_formats[0], .vi_max_clk_hz = 499200000, #else + .default_video_format = &tegra210_video_formats[4], .vi_max_clk_hz = 998400000, #endif }; diff --git a/drivers/staging/media/tegra-video/vi.c b/drivers/staging/media/tegra-video/vi.c index 2f1aff7e87170c68098224a821ad6d537fcf726a..79284c3b6caed8ab7382e0558d4d43cec729bdc7 100644 --- a/drivers/staging/media/tegra-video/vi.c +++ b/drivers/staging/media/tegra-video/vi.c @@ -30,15 +30,19 @@ #include "vi.h" #include "video.h" -#define MAX_CID_CONTROLS 1 - -static const struct tegra_video_format tegra_default_format = { - .img_dt = TEGRA_IMAGE_DT_RAW10, - .bit_width = 10, - .code = MEDIA_BUS_FMT_SRGGB10_1X10, - .bpp = 2, - .img_fmt = TEGRA_IMAGE_FORMAT_DEF, - .fourcc = V4L2_PIX_FMT_SRGGB10, +#define MAX_CID_CONTROLS 3 + +/** + * struct tegra_vi_graph_entity - Entity in the video graph + * + * @asd: subdev asynchronous registration information + * @entity: media entity from the corresponding V4L2 subdev + * @subdev: V4L2 subdev + */ +struct tegra_vi_graph_entity { + struct v4l2_async_subdev asd; + struct media_entity *entity; + struct v4l2_subdev *subdev; }; static inline struct tegra_vi * @@ -98,6 +102,7 @@ tegra_get_format_by_fourcc(struct tegra_vi *vi, u32 fourcc) /* * videobuf2 queue operations */ + static int tegra_channel_queue_setup(struct vb2_queue *vq, unsigned int *nbuffers, unsigned int *nplanes, @@ -113,6 +118,9 @@ static int tegra_channel_queue_setup(struct vb2_queue *vq, sizes[0] = chan->format.sizeimage; alloc_devs[0] = chan->vi->dev; + if (chan->vi->ops->channel_queue_setup) + chan->vi->ops->channel_queue_setup(chan); + return 0; } @@ -164,6 +172,9 @@ tegra_channel_get_remote_csi_subdev(struct tegra_vi_channel *chan) return media_entity_to_v4l2_subdev(pad->entity); } +/* + * Walk up the chain until the initial source (e.g. image sensor) + */ struct v4l2_subdev * tegra_channel_get_remote_source_subdev(struct tegra_vi_channel *chan) { @@ -190,49 +201,15 @@ tegra_channel_get_remote_source_subdev(struct tegra_vi_channel *chan) static int tegra_channel_enable_stream(struct tegra_vi_channel *chan) { - struct v4l2_subdev *csi_subdev, *src_subdev; - struct tegra_csi_channel *csi_chan; - int ret, err; + struct v4l2_subdev *subdev; + int ret; - /* - * Tegra CSI receiver can detect the first LP to HS transition. - * So, start the CSI stream-on prior to sensor stream-on and - * vice-versa for stream-off. - */ - csi_subdev = tegra_channel_get_remote_csi_subdev(chan); - ret = v4l2_subdev_call(csi_subdev, video, s_stream, true); + subdev = tegra_channel_get_remote_csi_subdev(chan); + ret = v4l2_subdev_call(subdev, video, s_stream, true); if (ret < 0 && ret != -ENOIOCTLCMD) return ret; - if (IS_ENABLED(CONFIG_VIDEO_TEGRA_TPG)) - return 0; - - csi_chan = v4l2_get_subdevdata(csi_subdev); - /* - * TRM has incorrectly documented to wait for done status from - * calibration logic after CSI interface power on. - * As per the design, calibration results are latched and applied - * to the pads only when the link is in LP11 state which will happen - * during the sensor stream-on. - * CSI subdev stream-on triggers start of MIPI pads calibration. - * Wait for calibration to finish here after sensor subdev stream-on. - */ - src_subdev = tegra_channel_get_remote_source_subdev(chan); - ret = v4l2_subdev_call(src_subdev, video, s_stream, true); - err = tegra_mipi_finish_calibration(csi_chan->mipi); - - if (ret < 0 && ret != -ENOIOCTLCMD) - goto err_disable_csi_stream; - - if (err < 0) - dev_warn(csi_chan->csi->dev, - "MIPI calibration failed: %d\n", err); - return 0; - -err_disable_csi_stream: - v4l2_subdev_call(csi_subdev, video, s_stream, false); - return ret; } static int tegra_channel_disable_stream(struct tegra_vi_channel *chan) @@ -240,18 +217,6 @@ static int tegra_channel_disable_stream(struct tegra_vi_channel *chan) struct v4l2_subdev *subdev; int ret; - /* - * Stream-off subdevices in reverse order to stream-on. - * Remote source subdev in TPG mode is same as CSI subdev. - */ - subdev = tegra_channel_get_remote_source_subdev(chan); - ret = v4l2_subdev_call(subdev, video, s_stream, false); - if (ret < 0 && ret != -ENOIOCTLCMD) - return ret; - - if (IS_ENABLED(CONFIG_VIDEO_TEGRA_TPG)) - return 0; - subdev = tegra_channel_get_remote_csi_subdev(chan); ret = v4l2_subdev_call(subdev, video, s_stream, false); if (ret < 0 && ret != -ENOIOCTLCMD) @@ -457,36 +422,6 @@ static int tegra_channel_get_format(struct file *file, void *fh, return 0; } -static void tegra_channel_fmt_align(struct tegra_vi_channel *chan, - struct v4l2_pix_format *pix, - unsigned int bpp) -{ - unsigned int min_bpl; - unsigned int max_bpl; - unsigned int bpl; - - /* - * The transfer alignment requirements are expressed in bytes. - * Clamp the requested width and height to the limits. - */ - pix->width = clamp(pix->width, TEGRA_MIN_WIDTH, TEGRA_MAX_WIDTH); - pix->height = clamp(pix->height, TEGRA_MIN_HEIGHT, TEGRA_MAX_HEIGHT); - - /* Clamp the requested bytes per line value. If the maximum bytes per - * line value is zero, the module doesn't support user configurable - * line sizes. Override the requested value with the minimum in that - * case. - */ - min_bpl = pix->width * bpp; - max_bpl = rounddown(TEGRA_MAX_WIDTH, SURFACE_ALIGN_BYTES); - bpl = roundup(pix->bytesperline, SURFACE_ALIGN_BYTES); - - pix->bytesperline = clamp(bpl, min_bpl, max_bpl); - pix->sizeimage = pix->bytesperline * pix->height; - if (pix->pixelformat == V4L2_PIX_FMT_NV16) - pix->sizeimage *= 2; -} - static int __tegra_channel_try_format(struct tegra_vi_channel *chan, struct v4l2_pix_format *pix) { @@ -563,7 +498,7 @@ static int __tegra_channel_try_format(struct tegra_vi_channel *chan, return ret; v4l2_fill_pix_format(pix, &fmt.format); - tegra_channel_fmt_align(chan, pix, fmtinfo->bpp); + chan->vi->ops->vi_fmt_align(pix, fmtinfo->bpp); __v4l2_subdev_state_free(sd_state); @@ -616,7 +551,7 @@ static int tegra_channel_set_format(struct file *file, void *fh, return ret; v4l2_fill_pix_format(pix, &fmt.format); - tegra_channel_fmt_align(chan, pix, fmtinfo->bpp); + chan->vi->ops->vi_fmt_align(pix, fmtinfo->bpp); chan->format = *pix; chan->fmtinfo = fmtinfo; @@ -652,7 +587,7 @@ static int tegra_channel_set_subdev_active_fmt(struct tegra_vi_channel *chan) chan->format.bytesperline = chan->format.width * chan->fmtinfo->bpp; chan->format.sizeimage = chan->format.bytesperline * chan->format.height; - tegra_channel_fmt_align(chan, &chan->format, chan->fmtinfo->bpp); + chan->vi->ops->vi_fmt_align(&chan->format, chan->fmtinfo->bpp); tegra_channel_update_gangports(chan); return 0; @@ -821,7 +756,7 @@ static int tegra_channel_s_dv_timings(struct file *file, void *fh, chan->format.height = bt->height; chan->format.bytesperline = bt->width * chan->fmtinfo->bpp; chan->format.sizeimage = chan->format.bytesperline * bt->height; - tegra_channel_fmt_align(chan, &chan->format, chan->fmtinfo->bpp); + chan->vi->ops->vi_fmt_align(&chan->format, chan->fmtinfo->bpp); tegra_channel_update_gangports(chan); return 0; @@ -977,6 +912,12 @@ static int vi_s_ctrl(struct v4l2_ctrl *ctrl) case V4L2_CID_TEGRA_SYNCPT_TIMEOUT_RETRY: chan->syncpt_timeout_retry = ctrl->val; break; + case V4L2_CID_HFLIP: + chan->hflip = ctrl->val; + break; + case V4L2_CID_VFLIP: + chan->vflip = ctrl->val; + break; default: return -EINVAL; } @@ -1048,6 +989,12 @@ static int tegra_channel_setup_ctrl_handler(struct tegra_vi_channel *chan) v4l2_ctrl_handler_free(&chan->ctrl_handler); return ret; } + + if (chan->vi->soc->has_h_v_flip) { + v4l2_ctrl_new_std(&chan->ctrl_handler, &vi_ctrl_ops, V4L2_CID_HFLIP, 0, 1, 1, 0); + v4l2_ctrl_new_std(&chan->ctrl_handler, &vi_ctrl_ops, V4L2_CID_VFLIP, 0, 1, 1, 0); + } + #endif /* setup the controls */ @@ -1119,7 +1066,7 @@ static int vi_fmts_bitmap_init(struct tegra_vi_channel *chan) * there are no matched formats. */ if (!match_code) { - match_code = tegra_default_format.code; + match_code = chan->vi->soc->default_video_format->code; index = tegra_get_format_idx_by_code(chan->vi, match_code, 0); if (WARN_ON(index < 0)) return -EINVAL; @@ -1133,21 +1080,11 @@ static int vi_fmts_bitmap_init(struct tegra_vi_channel *chan) return 0; } -static void tegra_channel_host1x_syncpts_free(struct tegra_vi_channel *chan) -{ - int i; - - for (i = 0; i < chan->numgangports; i++) { - host1x_syncpt_put(chan->mw_ack_sp[i]); - host1x_syncpt_put(chan->frame_start_sp[i]); - } -} - static void tegra_channel_cleanup(struct tegra_vi_channel *chan) { v4l2_ctrl_handler_free(&chan->ctrl_handler); media_entity_cleanup(&chan->video.entity); - tegra_channel_host1x_syncpts_free(chan); + chan->vi->ops->channel_host1x_syncpt_free(chan); mutex_destroy(&chan->video_lock); } @@ -1165,42 +1102,6 @@ void tegra_channels_cleanup(struct tegra_vi *vi) } } -static int tegra_channel_host1x_syncpt_init(struct tegra_vi_channel *chan) -{ - struct tegra_vi *vi = chan->vi; - unsigned long flags = HOST1X_SYNCPT_CLIENT_MANAGED; - struct host1x_syncpt *fs_sp; - struct host1x_syncpt *mw_sp; - int ret, i; - - for (i = 0; i < chan->numgangports; i++) { - fs_sp = host1x_syncpt_request(&vi->client, flags); - if (!fs_sp) { - dev_err(vi->dev, "failed to request frame start syncpoint\n"); - ret = -ENOMEM; - goto free_syncpts; - } - - mw_sp = host1x_syncpt_request(&vi->client, flags); - if (!mw_sp) { - dev_err(vi->dev, "failed to request memory ack syncpoint\n"); - host1x_syncpt_put(fs_sp); - ret = -ENOMEM; - goto free_syncpts; - } - - chan->frame_start_sp[i] = fs_sp; - chan->mw_ack_sp[i] = mw_sp; - spin_lock_init(&chan->sp_incr_lock[i]); - } - - return 0; - -free_syncpts: - tegra_channel_host1x_syncpts_free(chan); - return ret; -} - static int tegra_channel_init(struct tegra_vi_channel *chan) { struct tegra_vi *vi = chan->vi; @@ -1216,7 +1117,7 @@ static int tegra_channel_init(struct tegra_vi_channel *chan) init_waitqueue_head(&chan->done_wait); /* initialize the video format */ - chan->fmtinfo = &tegra_default_format; + chan->fmtinfo = chan->vi->soc->default_video_format; chan->format.pixelformat = chan->fmtinfo->fourcc; chan->format.colorspace = V4L2_COLORSPACE_SRGB; chan->format.field = V4L2_FIELD_NONE; @@ -1224,9 +1125,9 @@ static int tegra_channel_init(struct tegra_vi_channel *chan) chan->format.height = TEGRA_DEF_HEIGHT; chan->format.bytesperline = TEGRA_DEF_WIDTH * chan->fmtinfo->bpp; chan->format.sizeimage = chan->format.bytesperline * TEGRA_DEF_HEIGHT; - tegra_channel_fmt_align(chan, &chan->format, chan->fmtinfo->bpp); + vi->ops->vi_fmt_align(&chan->format, chan->fmtinfo->bpp); - ret = tegra_channel_host1x_syncpt_init(chan); + ret = vi->ops->channel_host1x_syncpt_init(chan); if (ret) return ret; @@ -1289,7 +1190,7 @@ static int tegra_channel_init(struct tegra_vi_channel *chan) cleanup_media: media_entity_cleanup(&chan->video.entity); free_syncpts: - tegra_channel_host1x_syncpts_free(chan); + vi->ops->channel_host1x_syncpt_free(chan); return ret; } @@ -1351,7 +1252,7 @@ static int tegra_vi_channels_alloc(struct tegra_vi *vi) struct device_node *node = vi->dev->of_node; struct device_node *ep = NULL; struct device_node *ports; - struct device_node *port; + struct device_node *port = NULL; unsigned int port_num; struct device_node *parent; struct v4l2_fwnode_endpoint v4l2_ep = { .bus_type = 0 }; @@ -1360,7 +1261,7 @@ static int tegra_vi_channels_alloc(struct tegra_vi *vi) ports = of_get_child_by_name(node, "ports"); if (!ports) - return -ENODEV; + return dev_err_probe(vi->dev, -ENODEV, "%pOF: missing 'ports' node\n", node); for_each_child_of_node(ports, port) { if (!of_node_name_eq(port, "port")) @@ -1374,7 +1275,6 @@ static int tegra_vi_channels_alloc(struct tegra_vi *vi) dev_err(vi->dev, "invalid port num %d for %pOF\n", port_num, port); ret = -EINVAL; - of_node_put(port); goto cleanup; } @@ -1397,13 +1297,12 @@ static int tegra_vi_channels_alloc(struct tegra_vi *vi) lanes = v4l2_ep.bus.mipi_csi2.num_data_lanes; ret = tegra_vi_channel_alloc(vi, port_num, port, lanes); - if (ret < 0) { - of_node_put(port); + if (ret < 0) goto cleanup; - } } cleanup: + of_node_put(port); of_node_put(ports); return ret; } @@ -1858,10 +1757,10 @@ static int tegra_vi_graph_init(struct tegra_vi *vi) * Walk the links to parse the full graph. Each channel will have * one endpoint of the composite node. Start by parsing the * composite node and parse the remote entities in turn. - * Each channel will register v4l2 async notifier to make the graph - * independent between the channels so we can the current channel + * Each channel will register a v4l2 async notifier to make the graph + * independent between the channels so we can skip the current channel * in case of something wrong during graph parsing and continue with - * next channels. + * the next channels. */ list_for_each_entry(chan, &vi->vi_chans, list) { struct fwnode_handle *ep, *remote; @@ -1920,11 +1819,8 @@ static int tegra_vi_init(struct host1x_client *client) ret = tegra_vi_tpg_channels_alloc(vi); else ret = tegra_vi_channels_alloc(vi); - if (ret < 0) { - dev_err(vi->dev, - "failed to allocate vi channels: %d\n", ret); + if (ret < 0) goto free_chans; - } ret = tegra_vi_channels_init(vi); if (ret < 0) @@ -2026,6 +1922,9 @@ static int tegra_vi_probe(struct platform_device *pdev) vi->client.ops = &vi_client_ops; vi->client.dev = &pdev->dev; + if (vi->ops->vi_enable) + vi->ops->vi_enable(vi, true); + ret = host1x_client_register(&vi->client); if (ret < 0) { dev_err(&pdev->dev, @@ -2036,6 +1935,8 @@ static int tegra_vi_probe(struct platform_device *pdev) return 0; rpm_disable: + if (vi->ops->vi_enable) + vi->ops->vi_enable(vi, false); pm_runtime_disable(&pdev->dev); return ret; } @@ -2046,12 +1947,17 @@ static int tegra_vi_remove(struct platform_device *pdev) host1x_client_unregister(&vi->client); + if (vi->ops->vi_enable) + vi->ops->vi_enable(vi, false); pm_runtime_disable(&pdev->dev); return 0; } static const struct of_device_id tegra_vi_of_id_table[] = { +#if defined(CONFIG_ARCH_TEGRA_2x_SOC) + { .compatible = "nvidia,tegra20-vi", .data = &tegra20_vi_soc }, +#endif #if defined(CONFIG_ARCH_TEGRA_210_SOC) { .compatible = "nvidia,tegra210-vi", .data = &tegra210_vi_soc }, #endif diff --git a/drivers/staging/media/tegra-video/vi.h b/drivers/staging/media/tegra-video/vi.h index a68e2c02c7b026097b683aa6aab1b2f4ba31e950..1e6a5caa70827531696ad40e31e5fbc5201f7eaf 100644 --- a/drivers/staging/media/tegra-video/vi.h +++ b/drivers/staging/media/tegra-video/vi.h @@ -25,17 +25,11 @@ #define V4L2_CID_TEGRA_SYNCPT_TIMEOUT_RETRY (V4L2_CTRL_CLASS_CAMERA | 0x1001) -#define TEGRA_MIN_WIDTH 32U -#define TEGRA_MAX_WIDTH 32768U -#define TEGRA_MIN_HEIGHT 32U -#define TEGRA_MAX_HEIGHT 32768U - #define TEGRA_DEF_WIDTH 1920 #define TEGRA_DEF_HEIGHT 1080 #define TEGRA_IMAGE_FORMAT_DEF 32 #define MAX_FORMAT_NUM 64 -#define SURFACE_ALIGN_BYTES 64 enum tegra_vi_pg_mode { TEGRA_VI_PG_DISABLED = 0, @@ -43,8 +37,17 @@ enum tegra_vi_pg_mode { TEGRA_VI_PG_PATCH, }; +struct tegra_vi; +struct tegra_vi_channel; + /** * struct tegra_vi_ops - Tegra VI operations + * @vi_enable: soc-specific operations needed to enable/disable the VI peripheral + * @channel_host1x_syncpt_init: initialize synchronization points + * @channel_host1x_syncpt_free: free all synchronization points + * @vi_fmt_align: modify `pix` to fit the hardware alignment + * requirements and fill image geometry + * @channel_queue_setup: additional operations at the end of vb2_ops::queue_setup * @vi_start_streaming: starts media pipeline, subdevice streaming, sets up * VI for capture and runs capture start and capture finish * kthreads for capturing frames to buffer and returns them back. @@ -52,6 +55,11 @@ enum tegra_vi_pg_mode { * back any queued buffers. */ struct tegra_vi_ops { + int (*vi_enable)(struct tegra_vi *vi, bool on); + int (*channel_host1x_syncpt_init)(struct tegra_vi_channel *chan); + void (*channel_host1x_syncpt_free)(struct tegra_vi_channel *chan); + void (*vi_fmt_align)(struct v4l2_pix_format *pix, unsigned int bpp); + void (*channel_queue_setup)(struct tegra_vi_channel *chan); int (*vi_start_streaming)(struct vb2_queue *vq, u32 count); void (*vi_stop_streaming)(struct vb2_queue *vq); }; @@ -61,18 +69,22 @@ struct tegra_vi_ops { * * @video_formats: supported video formats * @nformats: total video formats + * @default_video_format: default video format (pointer to a @video_formats item) * @ops: vi operations * @hw_revision: VI hw_revision * @vi_max_channels: supported max streaming channels * @vi_max_clk_hz: VI clock max frequency + * @has_h_v_flip: the chip can do H and V flip, and the driver implements it */ struct tegra_vi_soc { const struct tegra_video_format *video_formats; const unsigned int nformats; + const struct tegra_video_format *default_video_format; const struct tegra_vi_ops *ops; u32 hw_revision; unsigned int vi_max_channels; unsigned int vi_max_clk_hz; + bool has_h_v_flip:1; }; /** @@ -98,19 +110,6 @@ struct tegra_vi { struct list_head vi_chans; }; -/** - * struct tegra_vi_graph_entity - Entity in the video graph - * - * @asd: subdev asynchronous registration information - * @entity: media entity from the corresponding V4L2 subdev - * @subdev: V4L2 subdev - */ -struct tegra_vi_graph_entity { - struct v4l2_async_subdev asd; - struct media_entity *entity; - struct v4l2_subdev *subdev; -}; - /** * struct tegra_vi_channel - Tegra video channel * @@ -122,11 +121,13 @@ struct tegra_vi_graph_entity { * @vi: Tegra video input device structure * @frame_start_sp: host1x syncpoint pointer to synchronize programmed capture * start condition with hardware frame start events through host1x - * syncpoint counters. + * syncpoint counters. (Tegra210) * @mw_ack_sp: host1x syncpoint pointer to synchronize programmed memory write * ack trigger condition with hardware memory write done at end of - * frame through host1x syncpoint counters. + * frame through host1x syncpoint counters (On Tegra20 used for the + * OUT_1 syncpt) * @sp_incr_lock: protects cpu syncpoint increment. + * @next_out_sp_idx: next expected value for mw_ack_sp[0], i.e. OUT_1 (Tegra20) * * @kthread_start_capture: kthread to start capture of single frame when * vb buffer is available. This thread programs VI CSI hardware @@ -151,6 +152,12 @@ struct tegra_vi_graph_entity { * @queue: vb2 buffers queue * @sequence: V4L2 buffers sequence number * + * @addr_offset_u: U plane base address, relative to buffer base address (only for planar) + * @addr_offset_v: V plane base address, relative to buffer base address (only for planar) + * @start_offset: 1st Y byte to write, relative to buffer base address (for H/V flip) + * @start_offset_u: 1st U byte to write, relative to buffer base address (for H/V flip) + * @start_offset_v: 1st V byte to write, relative to buffer base address (for H/V flip) + * * @capture: list of queued buffers for capture * @start_lock: protects the capture queued list * @done: list of capture done queued buffers @@ -167,6 +174,9 @@ struct tegra_vi_graph_entity { * @tpg_fmts_bitmap: a bitmap for supported TPG formats * @pg_mode: test pattern generator mode (disabled/direct/patch) * @notifier: V4L2 asynchronous subdevs notifier + * + * @hflip: Horizontal flip is enabled + * @vflip: Vertical flip is enabled */ struct tegra_vi_channel { struct list_head list; @@ -180,6 +190,7 @@ struct tegra_vi_channel { struct host1x_syncpt *mw_ack_sp[GANG_PORTS_MAX]; /* protects the cpu syncpoint increment */ spinlock_t sp_incr_lock[GANG_PORTS_MAX]; + u32 next_out_sp_idx; struct task_struct *kthread_start_capture; wait_queue_head_t start_wait; @@ -191,6 +202,12 @@ struct tegra_vi_channel { struct vb2_queue queue; u32 sequence; + unsigned int addr_offset_u; + unsigned int addr_offset_v; + unsigned int start_offset; + unsigned int start_offset_u; + unsigned int start_offset_v; + struct list_head capture; /* protects the capture queued list */ spinlock_t start_lock; @@ -210,6 +227,9 @@ struct tegra_vi_channel { enum tegra_vi_pg_mode pg_mode; struct v4l2_async_notifier notifier; + + bool hflip:1; + bool vflip:1; }; /** @@ -260,11 +280,11 @@ enum tegra_image_dt { /** * struct tegra_video_format - Tegra video format description * - * @img_dt: image data type - * @bit_width: format width in bits per component + * @img_dt: MIPI CSI-2 data type (for CSI-2 only) + * @bit_width: format width in bits per component (for CSI/Tegra210 only) * @code: media bus format code * @bpp: bytes per pixel (when stored in memory) - * @img_fmt: image format + * @img_fmt: image format (for CSI/Tegra210 only) * @fourcc: V4L2 pixel format FCC identifier */ struct tegra_video_format { @@ -276,6 +296,9 @@ struct tegra_video_format { u32 fourcc; }; +#if defined(CONFIG_ARCH_TEGRA_2x_SOC) +extern const struct tegra_vi_soc tegra20_vi_soc; +#endif #if defined(CONFIG_ARCH_TEGRA_210_SOC) extern const struct tegra_vi_soc tegra210_vi_soc; #endif diff --git a/drivers/staging/media/tegra-video/video.c b/drivers/staging/media/tegra-video/video.c index d966b319553fcd33003578e2ca86c6765131eed4..074ad0dc56ca85bfb92839b62149b7c97555ed57 100644 --- a/drivers/staging/media/tegra-video/video.c +++ b/drivers/staging/media/tegra-video/video.c @@ -123,6 +123,10 @@ static int host1x_video_remove(struct host1x_device *dev) } static const struct of_device_id host1x_video_subdevs[] = { +#if defined(CONFIG_ARCH_TEGRA_2x_SOC) + { .compatible = "nvidia,tegra20-vip", }, + { .compatible = "nvidia,tegra20-vi", }, +#endif #if defined(CONFIG_ARCH_TEGRA_210_SOC) { .compatible = "nvidia,tegra210-csi", }, { .compatible = "nvidia,tegra210-vi", }, @@ -141,6 +145,7 @@ static struct host1x_driver host1x_video_driver = { static struct platform_driver * const drivers[] = { &tegra_csi_driver, + &tegra_vip_driver, &tegra_vi_driver, }; diff --git a/drivers/staging/media/tegra-video/video.h b/drivers/staging/media/tegra-video/video.h index fadaf2189dc9d9e79f3c60d82d0689a85085b122..7275affa655837bd5514aa0a8f160e66c2a85ae2 100644 --- a/drivers/staging/media/tegra-video/video.h +++ b/drivers/staging/media/tegra-video/video.h @@ -12,7 +12,6 @@ #include #include "vi.h" -#include "csi.h" struct tegra_video_device { struct v4l2_device v4l2_dev; @@ -25,5 +24,6 @@ int tegra_v4l2_nodes_setup_tpg(struct tegra_video_device *vid); void tegra_v4l2_nodes_cleanup_tpg(struct tegra_video_device *vid); extern struct platform_driver tegra_vi_driver; +extern struct platform_driver tegra_vip_driver; extern struct platform_driver tegra_csi_driver; #endif diff --git a/drivers/staging/media/tegra-video/vip.c b/drivers/staging/media/tegra-video/vip.c new file mode 100644 index 0000000000000000000000000000000000000000..a1ab886acc18731e162f491b41080123e9566565 --- /dev/null +++ b/drivers/staging/media/tegra-video/vip.c @@ -0,0 +1,287 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Parallel video capture module (VIP) for the Tegra VI. + * + * This file implements the VIP-specific infrastructure. + * + * Copyright (C) 2023 SKIDATA GmbH + * Author: Luca Ceresoli + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "vip.h" + +static inline struct tegra_vip *host1x_client_to_vip(struct host1x_client *client) +{ + return container_of(client, struct tegra_vip, client); +} + +static inline struct tegra_vip_channel *subdev_to_vip_channel(struct v4l2_subdev *subdev) +{ + return container_of(subdev, struct tegra_vip_channel, subdev); +} + +static inline struct tegra_vip *vip_channel_to_vip(struct tegra_vip_channel *chan) +{ + return container_of(chan, struct tegra_vip, chan); +} + +/* Find the previous subdev in the pipeline (i.e. the one connected to our sink pad) */ +static struct v4l2_subdev *tegra_vip_channel_get_prev_subdev(struct tegra_vip_channel *chan) +{ + struct media_pad *remote_pad; + + remote_pad = media_pad_remote_pad_first(&chan->pads[TEGRA_VIP_PAD_SINK]); + if (!remote_pad) + return NULL; + + return media_entity_to_v4l2_subdev(remote_pad->entity); +} + +static int tegra_vip_enable_stream(struct v4l2_subdev *subdev) +{ + struct tegra_vip_channel *vip_chan = subdev_to_vip_channel(subdev); + struct tegra_vip *vip = vip_channel_to_vip(vip_chan); + struct v4l2_subdev *prev_subdev = tegra_vip_channel_get_prev_subdev(vip_chan); + int err; + + err = pm_runtime_resume_and_get(vip->dev); + if (err) + return dev_err_probe(vip->dev, err, "failed to get runtime PM\n"); + + err = vip->soc->ops->vip_start_streaming(vip_chan); + if (err < 0) + goto err_start_streaming; + + err = v4l2_subdev_call(prev_subdev, video, s_stream, true); + if (err < 0 && err != -ENOIOCTLCMD) + goto err_prev_subdev_start_stream; + + return 0; + +err_prev_subdev_start_stream: +err_start_streaming: + pm_runtime_put(vip->dev); + return err; +} + +static int tegra_vip_disable_stream(struct v4l2_subdev *subdev) +{ + struct tegra_vip_channel *vip_chan = subdev_to_vip_channel(subdev); + struct tegra_vip *vip = vip_channel_to_vip(vip_chan); + struct v4l2_subdev *prev_subdev = tegra_vip_channel_get_prev_subdev(vip_chan); + + v4l2_subdev_call(prev_subdev, video, s_stream, false); + + pm_runtime_put(vip->dev); + + return 0; +} + +static int tegra_vip_s_stream(struct v4l2_subdev *subdev, int enable) +{ + int err; + + if (enable) + err = tegra_vip_enable_stream(subdev); + else + err = tegra_vip_disable_stream(subdev); + + return err; +} + +static const struct v4l2_subdev_video_ops tegra_vip_video_ops = { + .s_stream = tegra_vip_s_stream, +}; + +static const struct v4l2_subdev_ops tegra_vip_ops = { + .video = &tegra_vip_video_ops, +}; + +static int tegra_vip_channel_of_parse(struct tegra_vip *vip) +{ + struct device *dev = vip->dev; + struct device_node *np = dev->of_node; + struct v4l2_fwnode_endpoint v4l2_ep = { + .bus_type = V4L2_MBUS_PARALLEL + }; + struct fwnode_handle *fwh; + struct device_node *ep; + unsigned int num_pads; + int err; + + dev_dbg(dev, "Parsing %pOF", np); + + ep = of_graph_get_endpoint_by_regs(np, 0, 0); + if (!ep) { + err = -EINVAL; + dev_err_probe(dev, err, "%pOF: error getting endpoint node\n", np); + goto err_node_put; + } + + fwh = of_fwnode_handle(ep); + err = v4l2_fwnode_endpoint_parse(fwh, &v4l2_ep); + of_node_put(ep); + if (err) { + dev_err_probe(dev, err, "%pOF: failed to parse v4l2 endpoint\n", np); + goto err_node_put; + } + + num_pads = of_graph_get_endpoint_count(np); + if (num_pads != TEGRA_VIP_PADS_NUM) { + err = -EINVAL; + dev_err_probe(dev, err, "%pOF: need 2 pads, got %d\n", np, num_pads); + goto err_node_put; + } + + vip->chan.of_node = of_node_get(np); + vip->chan.pads[TEGRA_VIP_PAD_SINK].flags = MEDIA_PAD_FL_SINK; + vip->chan.pads[TEGRA_VIP_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE; + + return 0; + +err_node_put: + of_node_put(np); + return err; +} + +static int tegra_vip_channel_init(struct tegra_vip *vip) +{ + struct v4l2_subdev *subdev; + int err; + + subdev = &vip->chan.subdev; + v4l2_subdev_init(subdev, &tegra_vip_ops); + subdev->dev = vip->dev; + snprintf(subdev->name, V4L2_SUBDEV_NAME_SIZE, "%s", + kbasename(vip->chan.of_node->full_name)); + + v4l2_set_subdevdata(subdev, &vip->chan); + subdev->fwnode = of_fwnode_handle(vip->chan.of_node); + subdev->entity.function = MEDIA_ENT_F_VID_IF_BRIDGE; + + err = media_entity_pads_init(&subdev->entity, TEGRA_VIP_PADS_NUM, vip->chan.pads); + if (err) + return dev_err_probe(vip->dev, err, "failed to initialize media entity\n"); + + err = v4l2_async_register_subdev(subdev); + if (err) { + dev_err_probe(vip->dev, err, "failed to register subdev\n"); + goto err_register_subdev; + } + + return 0; + +err_register_subdev: + media_entity_cleanup(&subdev->entity); + return err; +} + +static int tegra_vip_init(struct host1x_client *client) +{ + struct tegra_vip *vip = host1x_client_to_vip(client); + int err; + + err = tegra_vip_channel_of_parse(vip); + if (err) + return err; + + err = tegra_vip_channel_init(vip); + if (err) + goto err_init; + + return 0; + +err_init: + of_node_put(vip->chan.of_node); + return err; +} + +static int tegra_vip_exit(struct host1x_client *client) +{ + struct tegra_vip *vip = host1x_client_to_vip(client); + struct v4l2_subdev *subdev = &vip->chan.subdev; + + v4l2_async_unregister_subdev(subdev); + media_entity_cleanup(&subdev->entity); + of_node_put(vip->chan.of_node); + + return 0; +} + +static const struct host1x_client_ops vip_client_ops = { + .init = tegra_vip_init, + .exit = tegra_vip_exit, +}; + +static int tegra_vip_probe(struct platform_device *pdev) +{ + struct tegra_vip *vip; + int err; + + dev_dbg(&pdev->dev, "Probing VIP \"%s\" from %pOF\n", pdev->name, pdev->dev.of_node); + + vip = devm_kzalloc(&pdev->dev, sizeof(*vip), GFP_KERNEL); + if (!vip) + return -ENOMEM; + + vip->soc = of_device_get_match_data(&pdev->dev); + + vip->dev = &pdev->dev; + platform_set_drvdata(pdev, vip); + + /* initialize host1x interface */ + INIT_LIST_HEAD(&vip->client.list); + vip->client.ops = &vip_client_ops; + vip->client.dev = &pdev->dev; + + err = host1x_client_register(&vip->client); + if (err) + return dev_err_probe(&pdev->dev, err, "failed to register host1x client\n"); + + pm_runtime_enable(&pdev->dev); + + return 0; +} + +static int tegra_vip_remove(struct platform_device *pdev) +{ + struct tegra_vip *vip = platform_get_drvdata(pdev); + + host1x_client_unregister(&vip->client); + + pm_runtime_disable(&pdev->dev); + + return 0; +} + +#if defined(CONFIG_ARCH_TEGRA_2x_SOC) +extern const struct tegra_vip_soc tegra20_vip_soc; +#endif + +static const struct of_device_id tegra_vip_of_id_table[] = { +#if defined(CONFIG_ARCH_TEGRA_2x_SOC) + { .compatible = "nvidia,tegra20-vip", .data = &tegra20_vip_soc }, +#endif + { } +}; +MODULE_DEVICE_TABLE(of, tegra_vip_of_id_table); + +struct platform_driver tegra_vip_driver = { + .driver = { + .name = "tegra-vip", + .of_match_table = tegra_vip_of_id_table, + }, + .probe = tegra_vip_probe, + .remove = tegra_vip_remove, +}; diff --git a/drivers/staging/media/tegra-video/vip.h b/drivers/staging/media/tegra-video/vip.h new file mode 100644 index 0000000000000000000000000000000000000000..32ceaaccbba2335cff78ed5ed3d13915c6d551c0 --- /dev/null +++ b/drivers/staging/media/tegra-video/vip.h @@ -0,0 +1,68 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (C) 2023 SKIDATA GmbH + * Author: Luca Ceresoli + */ + +#ifndef __TEGRA_VIP_H__ +#define __TEGRA_VIP_H__ + +#include +#include +#include + +enum { + TEGRA_VIP_PAD_SINK, + TEGRA_VIP_PAD_SOURCE, + TEGRA_VIP_PADS_NUM, +}; + +struct tegra_vip; + +/** + * struct tegra_vip_channel - Tegra VIP (parallel video capture) channel + * + * @subdev: V4L2 subdevice associated with this channel + * @pads: media pads for the subdevice entity + * @of_node: vip device tree node + */ +struct tegra_vip_channel { + struct v4l2_subdev subdev; + struct media_pad pads[TEGRA_VIP_PADS_NUM]; + struct device_node *of_node; +}; + +/** + * struct tegra_vip_ops - Tegra VIP operations + * + * @vip_start_streaming: programs vip hardware to enable streaming. + */ +struct tegra_vip_ops { + int (*vip_start_streaming)(struct tegra_vip_channel *vip_chan); +}; + +/** + * struct tegra_vip_soc - NVIDIA Tegra VIP SoC structure + * + * @ops: vip hardware operations + */ +struct tegra_vip_soc { + const struct tegra_vip_ops *ops; +}; + +/** + * struct tegra_vip - NVIDIA Tegra VIP device structure + * + * @dev: device struct + * @client: host1x_client struct + * @soc: pointer to SoC data structure + * @chan: the VIP channel + */ +struct tegra_vip { + struct device *dev; + struct host1x_client client; + const struct tegra_vip_soc *soc; + struct tegra_vip_channel chan; +}; + +#endif diff --git a/drivers/staging/most/i2c/i2c.c b/drivers/staging/most/i2c/i2c.c index 4e85e681922f189b4d5ff5e2dba338c6eacae84b..ce869280a056b6fb88d61880b2c34a7785ad2b86 100644 --- a/drivers/staging/most/i2c/i2c.c +++ b/drivers/staging/most/i2c/i2c.c @@ -362,7 +362,7 @@ static struct i2c_driver i2c_driver = { .driver = { .name = "hdm_i2c", }, - .probe_new = i2c_probe, + .probe = i2c_probe, .remove = i2c_remove, .id_table = i2c_id, }; diff --git a/drivers/staging/olpc_dcon/olpc_dcon.c b/drivers/staging/olpc_dcon/olpc_dcon.c index 2fba52e0bd7bde73d44e6c351dcc7284bd04dfe7..d5271eac14f61fa33e0780174518a986e53733d9 100644 --- a/drivers/staging/olpc_dcon/olpc_dcon.c +++ b/drivers/staging/olpc_dcon/olpc_dcon.c @@ -779,7 +779,7 @@ static struct i2c_driver dcon_driver = { }, .class = I2C_CLASS_DDC | I2C_CLASS_HWMON, .id_table = dcon_idtable, - .probe_new = dcon_probe, + .probe = dcon_probe, .remove = dcon_remove, .detect = dcon_detect, .address_list = normal_i2c, diff --git a/drivers/staging/pi433/pi433_if.c b/drivers/staging/pi433/pi433_if.c index f08fdf06d5666a4022ac272b099a9d8176dc8887..220e157d4a5e816ceb65664796c9c47e757d0808 100644 --- a/drivers/staging/pi433/pi433_if.c +++ b/drivers/staging/pi433/pi433_if.c @@ -1019,7 +1019,6 @@ static int setup_gpio(struct pi433_device *device) } /* configure the pin */ - gpiod_unexport(device->gpiod[i]); retval = gpiod_direction_input(device->gpiod[i]); if (retval) return retval; diff --git a/drivers/staging/rtl8192e/rtl8192e/Kconfig b/drivers/staging/rtl8192e/rtl8192e/Kconfig index eae8167f79dd44eca02343d994555a2da2627485..f8f774a16295be00923d5e22b47e8bb78407bbf7 100644 --- a/drivers/staging/rtl8192e/rtl8192e/Kconfig +++ b/drivers/staging/rtl8192e/rtl8192e/Kconfig @@ -3,6 +3,7 @@ config RTL8192E tristate "RealTek RTL8192E Wireless LAN NIC driver" depends on PCI && WLAN && RTLLIB depends on m + select CFG80211 select WIRELESS_EXT select WEXT_PRIV select CRYPTO diff --git a/drivers/staging/rtl8192e/rtl8192e/r8190P_def.h b/drivers/staging/rtl8192e/rtl8192e/r8190P_def.h index 385cca79f484146a243410fff9a36b386b530c96..c229fd244a48d3cb5b829edf577d6b1bda0e0dc0 100644 --- a/drivers/staging/rtl8192e/rtl8192e/r8190P_def.h +++ b/drivers/staging/rtl8192e/rtl8192e/r8190P_def.h @@ -85,7 +85,6 @@ enum rtl819x_loopback { #define HAL_PRIME_CHNL_OFFSET_LOWER 1 #define HAL_PRIME_CHNL_OFFSET_UPPER 2 - enum version_8190_loopback { VERSION_8190_BD = 0x3, VERSION_8190_BE @@ -139,8 +138,6 @@ struct tx_fwinfo_8190pci { u32 Retry_Limit:4; u32 Reserved2:1; u32 PacketID:13; - - }; struct phy_ofdm_rx_status_rxsc_sgien_exintfflag { @@ -172,7 +169,6 @@ struct phy_sts_cck_819xpci { u8 cck_agc_rpt; }; - #define PHY_RSSI_SLID_WIN_MAX 100 #define PHY_Beacon_RSSI_SLID_WIN_MAX 10 @@ -214,7 +210,6 @@ struct tx_desc { u32 Reserved7; }; - struct tx_desc_cmd { u16 PktSize; u8 Reserved1; @@ -256,10 +251,8 @@ struct rx_desc { u32 Reserved3; u32 BufferAddress; - }; - struct rx_fwinfo { u16 Reserved1:12; u16 PartAggr:1; @@ -278,7 +271,6 @@ struct rx_fwinfo { u8 Reserved4:1; u32 TSFL; - }; #endif diff --git a/drivers/staging/rtl8192e/rtl8192e/r8190P_rtl8256.c b/drivers/staging/rtl8192e/rtl8192e/r8190P_rtl8256.c index bb4539e337c83e7f28e1c2f760dccffcd572e619..7061f1cf4d3a560430a515c8ebf77a41713879c8 100644 --- a/drivers/staging/rtl8192e/rtl8192e/r8190P_rtl8256.c +++ b/drivers/staging/rtl8192e/rtl8192e/r8190P_rtl8256.c @@ -73,11 +73,11 @@ bool rtl92e_config_rf(struct net_device *dev) break; case RF90_PATH_B: u4RegValue = rtl92e_get_bb_reg(dev, pPhyReg->rfintfs, - bRFSI_RFENV<<16); + bRFSI_RFENV << 16); break; } - rtl92e_set_bb_reg(dev, pPhyReg->rfintfe, bRFSI_RFENV<<16, 0x1); + rtl92e_set_bb_reg(dev, pPhyReg->rfintfe, bRFSI_RFENV << 16, 0x1); rtl92e_set_bb_reg(dev, pPhyReg->rfintfo, bRFSI_RFENV, 0x1); @@ -117,7 +117,7 @@ bool rtl92e_config_rf(struct net_device *dev) break; case RF90_PATH_B: rtl92e_set_bb_reg(dev, pPhyReg->rfintfs, - bRFSI_RFENV<<16, u4RegValue); + bRFSI_RFENV << 16, u4RegValue); break; } diff --git a/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c b/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c index aed53fedeb61c4e2534dc976afabf0f0d94d3da8..e5925899402ca8ce9fe13ee699012eefaa42a6fc 100644 --- a/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c +++ b/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c @@ -36,8 +36,8 @@ void rtl92e_start_beacon(struct net_device *dev) rtl92e_writeb(dev, BCN_ERR_THRESH, 100); - BcnTimeCfg |= BcnCW<rtllib->iw_mode) { case IW_MODE_INFRA: - if (priv->rtllib->state == RTLLIB_LINKED) + if (priv->rtllib->link_state == MAC80211_LINKED) msr |= MSR_LINK_MANAGED; - LedAction = LED_CTL_LINK; break; case IW_MODE_ADHOC: - if (priv->rtllib->state == RTLLIB_LINKED) + if (priv->rtllib->link_state == MAC80211_LINKED) msr |= MSR_LINK_ADHOC; break; case IW_MODE_MASTER: - if (priv->rtllib->state == RTLLIB_LINKED) + if (priv->rtllib->link_state == MAC80211_LINKED) msr |= MSR_LINK_MASTER; break; default: @@ -70,8 +68,6 @@ static void _rtl92e_update_msr(struct net_device *dev) } rtl92e_writeb(dev, MSR, msr); - if (priv->rtllib->LedControlHandler) - priv->rtllib->LedControlHandler(dev, LedAction); } void rtl92e_set_reg(struct net_device *dev, u8 variable, u8 *val) @@ -111,7 +107,6 @@ void rtl92e_set_reg(struct net_device *dev, u8 variable, u8 *val) } rtl92e_writeb(dev, MSR, btMsr); - } break; @@ -130,7 +125,6 @@ void rtl92e_set_reg(struct net_device *dev, u8 variable, u8 *val) rtl92e_writel(dev, RCR, RegRCR); priv->receive_config = RegRCR; - } break; @@ -168,7 +162,7 @@ void rtl92e_set_reg(struct net_device *dev, u8 variable, u8 *val) &priv->rtllib->current_network.qos_data.parameters; u1bAIFS = qop->aifs[pAcParam] * - ((mode&(IEEE_G|IEEE_N_24G)) ? 9 : 20) + aSifsTime; + ((mode & (WIRELESS_MODE_G | WIRELESS_MODE_N_24G)) ? 9 : 20) + aSifsTime; rtl92e_dm_init_edca_turbo(dev); @@ -256,7 +250,7 @@ void rtl92e_set_reg(struct net_device *dev, u8 variable, u8 *val) case HW_VAR_SIFS: rtl92e_writeb(dev, SIFS, val[0]); - rtl92e_writeb(dev, SIFS+1, val[0]); + rtl92e_writeb(dev, SIFS + 1, val[0]); break; case HW_VAR_RF_TIMING: @@ -270,7 +264,6 @@ void rtl92e_set_reg(struct net_device *dev, u8 variable, u8 *val) default: break; } - } static void _rtl92e_read_eeprom_info(struct net_device *dev) @@ -299,12 +292,12 @@ static void _rtl92e_read_eeprom_info(struct net_device *dev) (EEPROM_Customer_ID >> 1)) >> 8; priv->eeprom_customer_id = usValue & 0xff; usValue = rtl92e_eeprom_read(dev, - EEPROM_ICVersion_ChannelPlan>>1); - priv->eeprom_chnl_plan = usValue&0xff; - IC_Version = (usValue & 0xff00)>>8; + EEPROM_ICVersion_ChannelPlan >> 1); + priv->eeprom_chnl_plan = usValue & 0xff; + IC_Version = (usValue & 0xff00) >> 8; ICVer8192 = IC_Version & 0xf; - ICVer8256 = (IC_Version & 0xf0)>>4; + ICVer8256 = (IC_Version & 0xf0) >> 4; if (ICVer8192 == 0x2) { if (ICVer8256 == 0x5) priv->card_8192_version = VERSION_8190_BE; @@ -354,7 +347,7 @@ static void _rtl92e_read_eeprom_info(struct net_device *dev) if (!priv->autoload_fail_flag) priv->eeprom_thermal_meter = ((rtl92e_eeprom_read(dev, - (EEPROM_ThermalMeter>>1))) & + (EEPROM_ThermalMeter >> 1))) & 0xff00) >> 8; else priv->eeprom_thermal_meter = EEPROM_Default_ThermalMeter; @@ -596,7 +589,7 @@ bool rtl92e_start_adapter(struct net_device *dev) RSVD_FW_QUEUE_PAGE_MGNT_SHIFT); rtl92e_writel(dev, RQPN3, APPLIED_RESERVED_QUEUE_IN_FW | NUM_OF_PAGE_IN_FW_QUEUE_BCN << - RSVD_FW_QUEUE_PAGE_BCN_SHIFT| + RSVD_FW_QUEUE_PAGE_BCN_SHIFT | NUM_OF_PAGE_IN_FW_QUEUE_PUB << RSVD_FW_QUEUE_PAGE_PUB_SHIFT); @@ -605,7 +598,7 @@ bool rtl92e_start_adapter(struct net_device *dev) ulRegRead = (0xFFF00000 & rtl92e_readl(dev, RRSR)) | RATE_ALL_OFDM_AG | RATE_ALL_CCK; rtl92e_writel(dev, RRSR, ulRegRead); - rtl92e_writel(dev, RATR0+4*7, (RATE_ALL_OFDM_AG | RATE_ALL_CCK)); + rtl92e_writel(dev, RATR0 + 4 * 7, (RATE_ALL_OFDM_AG | RATE_ALL_CCK)); rtl92e_writeb(dev, ACK_TIMEOUT, 0x30); @@ -718,7 +711,6 @@ bool rtl92e_start_adapter(struct net_device *dev) static void _rtl92e_net_update(struct net_device *dev) { - struct r8192_priv *priv = rtllib_priv(dev); struct rtllib_network *net; u16 BcnTimeCfg = 0, BcnCW = 6, BcnIFS = 0xf; @@ -738,8 +730,8 @@ static void _rtl92e_net_update(struct net_device *dev) rtl92e_writew(dev, BCN_DRV_EARLY_INT, 10); rtl92e_writeb(dev, BCN_ERR_THRESH, 100); - BcnTimeCfg |= (BcnCW<up) return; - if (ieee->state == RTLLIB_LINKED) { + if (ieee->link_state == MAC80211_LINKED) { _rtl92e_net_update(dev); rtl92e_update_ratr_table(dev); if ((ieee->pairwise_key_type == KEY_TYPE_WEP40) || @@ -768,13 +760,14 @@ void rtl92e_link_change(struct net_device *dev) u32 reg; reg = rtl92e_readl(dev, RCR); - if (priv->rtllib->state == RTLLIB_LINKED) { + if (priv->rtllib->link_state == MAC80211_LINKED) { if (ieee->intel_promiscuous_md_info.promiscuous_on) ; else priv->receive_config = reg |= RCR_CBSSID; - } else + } else { priv->receive_config = reg &= ~RCR_CBSSID; + } rtl92e_writel(dev, RCR, reg); } @@ -883,7 +876,7 @@ static u8 _rtl92e_rate_mgn_to_hw(u8 rate) case MGN_MCS15: ret = DESC90_RATEMCS15; break; - case (0x80|0x20): + case (0x80 | 0x20): ret = DESC90_RATEMCS32; break; default: @@ -973,7 +966,7 @@ void rtl92e_fill_tx_desc(struct net_device *dev, struct tx_desc *pdesc, pTxFwInfo->RtsEnable = (cb_desc->bRTSEnable) ? 1 : 0; pTxFwInfo->CtsEnable = (cb_desc->bCTSEnable) ? 1 : 0; pTxFwInfo->RtsSTBC = (cb_desc->bRTSSTBC) ? 1 : 0; - pTxFwInfo->RtsHT = (cb_desc->rts_rate&0x80) ? 1 : 0; + pTxFwInfo->RtsHT = (cb_desc->rts_rate & 0x80) ? 1 : 0; pTxFwInfo->RtsRate = _rtl92e_rate_mgn_to_hw(cb_desc->rts_rate); pTxFwInfo->RtsBandwidth = 0; pTxFwInfo->RtsSubcarrier = cb_desc->RTSSC; @@ -1008,8 +1001,7 @@ void rtl92e_fill_tx_desc(struct net_device *dev, struct tx_desc *pdesc, pdesc->PktSize = skb->len - sizeof(struct tx_fwinfo_8190pci); pdesc->SecCAMID = 0; - pdesc->RATid = cb_desc->RATRIndex; - + pdesc->RATid = cb_desc->ratr_index; pdesc->NoEnc = 1; pdesc->SecType = 0x0; @@ -1217,7 +1209,6 @@ static long _rtl92e_signal_scale_mapping(struct r8192_priv *priv, long currsig) return retsig; } - #define rx_hal_is_cck_rate(_pdrvinfo)\ ((_pdrvinfo->RxRate == DESC90_RATE1M ||\ _pdrvinfo->RxRate == DESC90_RATE2M ||\ @@ -1265,7 +1256,6 @@ static void _rtl92e_query_rxphystatus( check_reg824 = 1; } - prxpkt = (u8 *)pdrvinfo; prxpkt += sizeof(struct rx_fwinfo); @@ -1345,7 +1335,7 @@ static void _rtl92e_query_rxphystatus( else if (pcck_buf->sq_rpt < 20) sq = 100; else - sq = ((64-sq) * 100) / 44; + sq = ((64 - sq) * 100) / 44; } pstats->SignalQuality = sq; precord_stats->SignalQuality = sq; @@ -1372,7 +1362,6 @@ static void _rtl92e_query_rxphystatus( } } - rx_pwr_all = (((pofdm_buf->pwdb_all) >> 1) & 0x7f) - 106; pwdb_all = rtl92e_rx_db_to_percent(rx_pwr_all); @@ -1452,7 +1441,7 @@ static void _rtl92e_process_phyinfo(struct r8192_priv *priv, u8 *buffer, if (slide_rssi_index >= PHY_RSSI_SLID_WIN_MAX) slide_rssi_index = 0; - tmp_val = priv->stats.slide_rssi_total/slide_rssi_statistics; + tmp_val = priv->stats.slide_rssi_total / slide_rssi_statistics; priv->stats.signal_strength = rtl92e_translate_to_dbm(priv, tmp_val); curr_st->rssi = priv->stats.signal_strength; if (!prev_st->bPacketMatchBSSID) { @@ -1482,14 +1471,13 @@ static void _rtl92e_process_phyinfo(struct r8192_priv *priv, u8 *buffer, } else { priv->stats.rx_rssi_percentage[rfpath] = ((priv->stats.rx_rssi_percentage[rfpath] * - (RX_SMOOTH-1)) + + (RX_SMOOTH - 1)) + (prev_st->RxMIMOSignalStrength[rfpath])) / (RX_SMOOTH); } } } - if (prev_st->bPacketBeacon) { if (slide_beacon_adc_pwdb_statistics++ >= PHY_Beacon_RSSI_SLID_WIN_MAX) { @@ -1517,14 +1505,14 @@ static void _rtl92e_process_phyinfo(struct r8192_priv *priv, u8 *buffer, if (prev_st->RxPWDBAll > (u32)priv->undecorated_smoothed_pwdb) { priv->undecorated_smoothed_pwdb = (((priv->undecorated_smoothed_pwdb) * - (RX_SMOOTH-1)) + + (RX_SMOOTH - 1)) + (prev_st->RxPWDBAll)) / (RX_SMOOTH); priv->undecorated_smoothed_pwdb = priv->undecorated_smoothed_pwdb + 1; } else { priv->undecorated_smoothed_pwdb = (((priv->undecorated_smoothed_pwdb) * - (RX_SMOOTH-1)) + + (RX_SMOOTH - 1)) + (prev_st->RxPWDBAll)) / (RX_SMOOTH); } rtl92e_update_rx_statistics(priv, prev_st); @@ -1753,7 +1741,7 @@ bool rtl92e_get_rx_stats(struct net_device *dev, struct rtllib_rx_stats *stats, (pDrvInfo->FirstAGGR == 1); stats->TimeStampLow = pDrvInfo->TSFL; - stats->TimeStampHigh = rtl92e_readl(dev, TSFR+4); + stats->TimeStampHigh = rtl92e_readl(dev, TSFR + 4); rtl92e_update_rx_pkt_timestamp(dev, stats); @@ -1766,7 +1754,7 @@ bool rtl92e_get_rx_stats(struct net_device *dev, struct rtllib_rx_stats *stats, skb_trim(skb, skb->len - S_CRC_LEN); - stats->packetlength = stats->Length-4; + stats->packetlength = stats->Length - 4; stats->fraglength = stats->packetlength; stats->fragoffset = 0; stats->ntotalfrag = 1; @@ -1806,7 +1794,6 @@ void rtl92e_stop_adapter(struct net_device *dev, bool reset) rtl92e_writel(dev, WFCRC1, 0xffffffff); rtl92e_writel(dev, WFCRC2, 0xffffffff); - rtl92e_writeb(dev, PMR, 0x5); rtl92e_writeb(dev, MAC_BLK_CTRL, 0xa); } @@ -1830,18 +1817,14 @@ void rtl92e_update_ratr_table(struct net_device *dev) rtl92e_config_rate(dev, &rate_config); ratr_value = rate_config | *pMcsRate << 12; switch (ieee->mode) { - case IEEE_A: - ratr_value &= 0x00000FF0; - break; - case IEEE_B: + case WIRELESS_MODE_B: ratr_value &= 0x0000000F; break; - case IEEE_G: - case IEEE_G|IEEE_B: + case WIRELESS_MODE_G: + case WIRELESS_MODE_G | WIRELESS_MODE_B: ratr_value &= 0x00000FF7; break; - case IEEE_N_24G: - case IEEE_N_5G: + case WIRELESS_MODE_N_24G: if (ieee->ht_info->peer_mimo_ps == 0) ratr_value &= 0x0007F007; else @@ -1857,7 +1840,7 @@ void rtl92e_update_ratr_table(struct net_device *dev) else if (!ieee->ht_info->cur_tx_bw40mhz && ieee->ht_info->bCurShortGI20MHz) ratr_value |= 0x80000000; - rtl92e_writel(dev, RATR0+rate_index*4, ratr_value); + rtl92e_writel(dev, RATR0 + rate_index * 4, ratr_value); rtl92e_writeb(dev, UFWP, 1); } @@ -1881,7 +1864,7 @@ rtl92e_init_variables(struct net_device *dev) RCR_AMF | RCR_ADF | RCR_AICV | RCR_AB | RCR_AM | RCR_APM | - RCR_AAP | ((u32)7<irq_mask[0] = (u32)(IMR_ROK | IMR_VODOK | IMR_VIDOK | @@ -1901,7 +1884,6 @@ void rtl92e_enable_irq(struct net_device *dev) priv->irq_enabled = 1; rtl92e_writel(dev, INTA_MASK, priv->irq_mask[0]); - } void rtl92e_disable_irq(struct net_device *dev) @@ -1933,7 +1915,6 @@ void rtl92e_enable_tx(struct net_device *dev) rtl92e_writel(dev, TX_DESC_BASE[i], priv->tx_ring[i].dma); } - void rtl92e_ack_irq(struct net_device *dev, u32 *p_inta, u32 *p_intb) { *p_inta = rtl92e_readl(dev, ISR); @@ -1976,7 +1957,7 @@ bool rtl92e_is_rx_stuck(struct net_device *dev) } - SlotIndex = (priv->silent_reset_rx_slot_index++)%SilentResetRxSoltNum; + SlotIndex = (priv->silent_reset_rx_slot_index++) % SilentResetRxSoltNum; if (priv->rx_ctr == RegRxCounter) { priv->silent_reset_rx_stuck_event[SlotIndex] = 1; @@ -1990,8 +1971,6 @@ bool rtl92e_is_rx_stuck(struct net_device *dev) TotalRxStuckCount += priv->silent_reset_rx_stuck_event[i]; } - - } else { priv->silent_reset_rx_stuck_event[SlotIndex] = 0; } @@ -2021,7 +2000,7 @@ bool rtl92e_get_nmode_support_by_sec(struct net_device *dev) struct rtllib_device *ieee = priv->rtllib; if (ieee->rtllib_ap_sec_type && - (ieee->rtllib_ap_sec_type(priv->rtllib)&(SEC_ALG_WEP | + (ieee->rtllib_ap_sec_type(priv->rtllib) & (SEC_ALG_WEP | SEC_ALG_TKIP))) { return false; } else { diff --git a/drivers/staging/rtl8192e/rtl8192e/r8192E_hw.h b/drivers/staging/rtl8192e/rtl8192e/r8192E_hw.h index f4d4b01630a2428ad3fb48be8b60dfd66e5b020a..09f8c76b7e65e675578bd5865fc0c4d3f21af8a3 100644 --- a/drivers/staging/rtl8192e/rtl8192e/r8192E_hw.h +++ b/drivers/staging/rtl8192e/rtl8192e/r8192E_hw.h @@ -159,7 +159,6 @@ enum _RTL8192PCI_HW { WFCRC2 = 0x2f8, BW_OPMODE = 0x300, -#define BW_OPMODE_5G BIT1 #define BW_OPMODE_20MHZ BIT2 IC_VERRSION = 0x301, MSR = 0x303, diff --git a/drivers/staging/rtl8192e/rtl8192e/r8192E_phy.c b/drivers/staging/rtl8192e/rtl8192e/r8192E_phy.c index 4b0ebe96302ec916b426d14155e7848bd11d8b25..875540a2079d1518a00b79566496e5a60545356c 100644 --- a/drivers/staging/rtl8192e/rtl8192e/r8192E_phy.c +++ b/drivers/staging/rtl8192e/rtl8192e/r8192E_phy.c @@ -32,7 +32,6 @@ static u32 _rtl92e_calculate_bit_shift(u32 dwBitMask) void rtl92e_set_bb_reg(struct net_device *dev, u32 dwRegAddr, u32 dwBitMask, u32 dwData) { - u32 OriginalValue, BitShift, NewValue; if (dwBitMask != bMaskDWord) { @@ -40,8 +39,9 @@ void rtl92e_set_bb_reg(struct net_device *dev, u32 dwRegAddr, u32 dwBitMask, BitShift = _rtl92e_calculate_bit_shift(dwBitMask); NewValue = (OriginalValue & ~dwBitMask) | (dwData << BitShift); rtl92e_writel(dev, dwRegAddr, NewValue); - } else + } else { rtl92e_writel(dev, dwRegAddr, dwData); + } } u32 rtl92e_get_bb_reg(struct net_device *dev, u32 dwRegAddr, u32 dwBitMask) @@ -99,7 +99,6 @@ static u32 _rtl92e_phy_rf_read(struct net_device *dev, rtl92e_set_bb_reg(dev, rFPGA0_AnalogParameter4, 0x300, 0x3); return ret; - } static void _rtl92e_phy_rf_write(struct net_device *dev, @@ -165,10 +164,10 @@ void rtl92e_set_rf_reg(struct net_device *dev, enum rf90_radio_path eRFPath, _rtl92e_phy_rf_fw_write(dev, eRFPath, RegAddr, New_Value); - } else + } else { _rtl92e_phy_rf_fw_write(dev, eRFPath, RegAddr, Data); + } udelay(200); - } else { if (BitMask != bMask12Bits) { Original_Value = _rtl92e_phy_rf_read(dev, eRFPath, @@ -177,8 +176,9 @@ void rtl92e_set_rf_reg(struct net_device *dev, enum rf90_radio_path eRFPath, New_Value = (Original_Value & ~BitMask) | (Data << BitShift); _rtl92e_phy_rf_write(dev, eRFPath, RegAddr, New_Value); - } else + } else { _rtl92e_phy_rf_write(dev, eRFPath, RegAddr, Data); + } } } @@ -226,7 +226,6 @@ static u32 _rtl92e_phy_rf_fw_read(struct net_device *dev, return 0; } return rtl92e_readl(dev, RF_DATA); - } static void _rtl92e_phy_rf_fw_write(struct net_device *dev, @@ -247,10 +246,8 @@ static void _rtl92e_phy_rf_fw_write(struct net_device *dev, break; } rtl92e_writel(dev, QPNR, Data); - } - void rtl92e_config_mac(struct net_device *dev) { u32 dwArrayLen = 0, i = 0; @@ -267,12 +264,10 @@ void rtl92e_config_mac(struct net_device *dev) } for (i = 0; i < dwArrayLen; i += 3) { if (pdwArray[i] == 0x318) - pdwArray[i+2] = 0x00000800; - rtl92e_set_bb_reg(dev, pdwArray[i], pdwArray[i+1], - pdwArray[i+2]); + pdwArray[i + 2] = 0x00000800; + rtl92e_set_bb_reg(dev, pdwArray[i], pdwArray[i + 1], + pdwArray[i + 2]); } - return; - } static void _rtl92e_phy_config_bb(struct net_device *dev, u8 ConfigType) @@ -291,13 +286,13 @@ static void _rtl92e_phy_config_bb(struct net_device *dev, u8 ConfigType) for (i = 0; i < PHY_REGArrayLen; i += 2) { rtl92e_set_bb_reg(dev, Rtl819XPHY_REGArray_Table[i], bMaskDWord, - Rtl819XPHY_REGArray_Table[i+1]); + Rtl819XPHY_REGArray_Table[i + 1]); } } else if (ConfigType == BB_CONFIG_AGC_TAB) { for (i = 0; i < AGCTAB_ArrayLen; i += 2) { rtl92e_set_bb_reg(dev, Rtl819XAGCTAB_Array_Table[i], bMaskDWord, - Rtl819XAGCTAB_Array_Table[i+1]); + Rtl819XAGCTAB_Array_Table[i + 1]); } } } @@ -370,7 +365,6 @@ bool rtl92e_check_bb_and_rf(struct net_device *dev, enum hw90_block CheckBlock, break; } - if (dwRegRead != WriteData[i]) { netdev_warn(dev, "%s(): Check failed.\n", __func__); ret = false; @@ -389,10 +383,10 @@ static bool _rtl92e_bb_config_para_file(struct net_device *dev) u32 dwRegValue = 0; bRegValue = rtl92e_readb(dev, BB_GLOBAL_RESET); - rtl92e_writeb(dev, BB_GLOBAL_RESET, (bRegValue|BB_GLOBAL_RESET_BIT)); + rtl92e_writeb(dev, BB_GLOBAL_RESET, (bRegValue | BB_GLOBAL_RESET_BIT)); dwRegValue = rtl92e_readl(dev, CPU_GEN); - rtl92e_writel(dev, CPU_GEN, (dwRegValue&(~CPU_GEN_BB_RST))); + rtl92e_writel(dev, CPU_GEN, (dwRegValue & (~CPU_GEN_BB_RST))); for (eCheckItem = (enum hw90_block)HW90_BLOCK_PHY0; eCheckItem <= HW90_BLOCK_PHY1; eCheckItem++) { @@ -402,19 +396,18 @@ static bool _rtl92e_bb_config_para_file(struct net_device *dev) if (!rtStatus) return rtStatus; } - rtl92e_set_bb_reg(dev, rFPGA0_RFMOD, bCCKEn|bOFDMEn, 0x0); + rtl92e_set_bb_reg(dev, rFPGA0_RFMOD, bCCKEn | bOFDMEn, 0x0); _rtl92e_phy_config_bb(dev, BB_CONFIG_PHY_REG); dwRegValue = rtl92e_readl(dev, CPU_GEN); - rtl92e_writel(dev, CPU_GEN, (dwRegValue|CPU_GEN_BB_RST)); + rtl92e_writel(dev, CPU_GEN, (dwRegValue | CPU_GEN_BB_RST)); _rtl92e_phy_config_bb(dev, BB_CONFIG_AGC_TAB); if (priv->ic_cut > VERSION_8190_BD) { dwRegValue = 0x0; rtl92e_set_bb_reg(dev, rFPGA0_TxGainStage, - (bXBTxAGC|bXCTxAGC|bXDTxAGC), dwRegValue); - + (bXBTxAGC | bXCTxAGC | bXDTxAGC), dwRegValue); dwRegValue = priv->crystal_cap; rtl92e_set_bb_reg(dev, rFPGA0_AnalogParameter1, bXtalCap92x, @@ -470,7 +463,6 @@ void rtl92e_set_tx_power(struct net_device *dev, u8 channel) u8 rtl92e_config_rf_path(struct net_device *dev, enum rf90_radio_path eRFPath) { - int i; switch (eRFPath) { @@ -483,7 +475,6 @@ u8 rtl92e_config_rf_path(struct net_device *dev, enum rf90_radio_path eRFPath) rtl92e_set_rf_reg(dev, eRFPath, RTL8192E_RADIO_A_ARR[i], bMask12Bits, RTL8192E_RADIO_A_ARR[i + 1]); - } break; case RF90_PATH_B: @@ -495,7 +486,6 @@ u8 rtl92e_config_rf_path(struct net_device *dev, enum rf90_radio_path eRFPath) rtl92e_set_rf_reg(dev, eRFPath, RTL8192E_RADIO_B_ARR[i], bMask12Bits, RTL8192E_RADIO_B_ARR[i + 1]); - } break; default: @@ -503,7 +493,6 @@ u8 rtl92e_config_rf_path(struct net_device *dev, enum rf90_radio_path eRFPath) } return 0; - } static void _rtl92e_set_tx_power_level(struct net_device *dev, u8 channel) @@ -645,7 +634,7 @@ static u8 _rtl92e_phy_switch_channel_step(struct net_device *dev, u8 channel, rtl92e_set_rf_reg(dev, (enum rf90_radio_path)eRFPath, CurrentCmd->Para1, bMask12Bits, - CurrentCmd->Para2<<7); + CurrentCmd->Para2 << 7); break; default: break; @@ -677,7 +666,6 @@ static void _rtl92e_phy_switch_channel(struct net_device *dev, u8 channel) static void _rtl92e_phy_switch_channel_work_item(struct net_device *dev) { - struct r8192_priv *priv = rtllib_priv(dev); _rtl92e_phy_switch_channel(dev, priv->chan); @@ -694,7 +682,6 @@ u8 rtl92e_set_channel(struct net_device *dev, u8 channel) if (priv->sw_chnl_in_progress) return false; - switch (priv->rtllib->mode) { case WIRELESS_MODE_B: if (channel > 14) { @@ -824,7 +811,6 @@ static void _rtl92e_cck_tx_power_track_bw_switch(struct net_device *dev) static void _rtl92e_set_bw_mode_work_item(struct net_device *dev) { - struct r8192_priv *priv = rtllib_priv(dev); u8 regBwOpMode; @@ -880,7 +866,7 @@ static void _rtl92e_set_bw_mode_work_item(struct net_device *dev) } rtl92e_set_bb_reg(dev, rCCK0_System, bCCKSideBand, - (priv->n_cur_40mhz_prime_sc>>1)); + (priv->n_cur_40mhz_prime_sc >> 1)); rtl92e_set_bb_reg(dev, rOFDM1_LSTF, 0xC00, priv->n_cur_40mhz_prime_sc); @@ -890,7 +876,6 @@ static void _rtl92e_set_bw_mode_work_item(struct net_device *dev) netdev_err(dev, "%s(): unknown Bandwidth: %#X\n", __func__, priv->current_chnl_bw); break; - } rtl92e_set_bandwidth(dev, priv->current_chnl_bw); @@ -904,7 +889,6 @@ void rtl92e_set_bw_mode(struct net_device *dev, enum ht_channel_width bandwidth, { struct r8192_priv *priv = rtllib_priv(dev); - if (priv->set_bw_mode_in_progress) return; @@ -921,7 +905,6 @@ void rtl92e_set_bw_mode(struct net_device *dev, enum ht_channel_width bandwidth, priv->n_cur_40mhz_prime_sc = HAL_PRIME_CHNL_OFFSET_DONT_CARE; _rtl92e_set_bw_mode_work_item(dev); - } void rtl92e_init_gain(struct net_device *dev, u8 Operation) @@ -993,7 +976,6 @@ void rtl92e_init_gain(struct net_device *dev, u8 Operation) void rtl92e_set_rf_off(struct net_device *dev) { - rtl92e_set_bb_reg(dev, rFPGA0_XA_RFInterfaceOE, BIT4, 0x0); rtl92e_set_bb_reg(dev, rFPGA0_AnalogParameter4, 0x300, 0x0); rtl92e_set_bb_reg(dev, rFPGA0_AnalogParameter1, 0x18, 0x0); @@ -1002,7 +984,6 @@ void rtl92e_set_rf_off(struct net_device *dev) rtl92e_set_bb_reg(dev, rFPGA0_AnalogParameter1, 0x60, 0x0); rtl92e_set_bb_reg(dev, rFPGA0_AnalogParameter1, 0x4, 0x0); rtl92e_writeb(dev, ANAPAR_FOR_8192PCIE, 0x07); - } static bool _rtl92e_set_rf_power_state(struct net_device *dev, @@ -1099,9 +1080,8 @@ static bool _rtl92e_set_rf_power_state(struct net_device *dev, break; } - if (bResult) { + if (bResult) priv->rtllib->rf_power_state = rf_power_state; - } priv->set_rf_pwr_state_in_progress = false; return bResult; @@ -1130,11 +1110,11 @@ void rtl92e_scan_op_backup(struct net_device *dev, u8 Operation) if (priv->up) { switch (Operation) { case SCAN_OPT_BACKUP: - priv->rtllib->InitialGainHandler(dev, IG_Backup); + priv->rtllib->init_gain_handler(dev, IG_Backup); break; case SCAN_OPT_RESTORE: - priv->rtllib->InitialGainHandler(dev, IG_Restore); + priv->rtllib->init_gain_handler(dev, IG_Restore); break; } } diff --git a/drivers/staging/rtl8192e/rtl8192e/r8192E_phyreg.h b/drivers/staging/rtl8192e/rtl8192e/r8192E_phyreg.h index e1b30fbdf8ccfac7b0349ce669f98a12f1511664..24fb0ca539ea5080783c2521d1458b57e5e4af31 100644 --- a/drivers/staging/rtl8192e/rtl8192e/r8192E_phyreg.h +++ b/drivers/staging/rtl8192e/rtl8192e/r8192E_phyreg.h @@ -7,7 +7,6 @@ #ifndef _R819XU_PHYREG_H #define _R819XU_PHYREG_H - #define RF_DATA 0x1d4 #define rPMAC_Reset 0x100 @@ -125,7 +124,6 @@ #define rOFDM0_TxCoeff5 0xcb4 #define rOFDM0_TxCoeff6 0xcb8 - #define rOFDM1_LSTF 0xd00 #define rOFDM1_TRxPathEnable 0xd04 #define rOFDM1_CFO 0xd08 @@ -163,7 +161,6 @@ #define rTxAGC_Mcs11_Mcs08 0xe18 #define rTxAGC_Mcs15_Mcs12 0xe1c - #define rZebra1_HSSIEnable 0x0 #define rZebra1_TRxEnable1 0x1 #define rZebra1_TRxEnable2 0x2 @@ -269,7 +266,6 @@ #define b3WireAddressLength 0x400 #define b3WireRFPowerDown 0x1 /*#define bHWSISelect 0x8 */ -#define b5GPAPEPolarity 0x40000000 #define b2GPAPEPolarity 0x80000000 #define bRFSW_TxDefaultAnt 0x3 #define bRFSW_TxOptionAnt 0x30 @@ -287,7 +283,6 @@ #define bRFSI_ANTSW 0x100 #define bRFSI_ANTSWB 0x200 #define bRFSI_PAPE 0x400 -#define bRFSI_PAPE5G 0x800 #define bBandSelect 0x1 #define bHTSIG2_GI 0x80 #define bHTSIG2_Smoothing 0x01 @@ -819,7 +814,6 @@ #define bOFDMPHY0_End 0xcff #define bOFDMPHY1_End 0xdff - #define bPMACControl 0x0 #define bWMACControl 0x1 #define bWNICControl 0x2 diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_cam.c b/drivers/staging/rtl8192e/rtl8192e/rtl_cam.c index a4d65b4d99c28fc38bf52e1bdf4db27b402b6f2e..6d9e5c27017de563aefad51e081e9e3cefdfad6b 100644 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_cam.c +++ b/drivers/staging/rtl8192e/rtl8192e/rtl_cam.c @@ -101,7 +101,6 @@ void rtl92e_set_key(struct net_device *dev, u8 EntryNo, u8 KeyIndex, else usConfig |= BIT15 | (KeyType << 2) | KeyIndex; - for (i = 0; i < CAM_CONTENT_COUNT; i++) { TargetCommand = i + CAM_CONTENT_COUNT * EntryNo; TargetCommand |= BIT31 | BIT16; @@ -149,7 +148,6 @@ void rtl92e_cam_restore(struct net_device *dev) if ((priv->rtllib->pairwise_key_type == KEY_TYPE_WEP40) || (priv->rtllib->pairwise_key_type == KEY_TYPE_WEP104)) { - for (EntryId = 0; EntryId < 4; EntryId++) { MacAddr = CAM_CONST_ADDR[EntryId]; if (priv->rtllib->swcamtable[EntryId].bused) { diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c index 27040d1e3230fa6783d25f6524ca3d5988fabc03..4447489a16ea38d79a8d939647df8052a2edc198 100644 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c +++ b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c @@ -169,7 +169,7 @@ bool rtl92e_set_rf_state(struct net_device *dev, (priv->rtllib->iw_mode == IW_MODE_ADHOC)) { if ((priv->rtllib->rf_off_reason > RF_CHANGE_BY_IPS) || (change_source > RF_CHANGE_BY_IPS)) { - if (ieee->state == RTLLIB_LINKED) + if (ieee->link_state == MAC80211_LINKED) priv->blinked_ingpio = true; else priv->blinked_ingpio = false; @@ -277,7 +277,7 @@ static void _rtl92e_update_cap(struct net_device *dev, u16 cap) } } - if (net->mode & (IEEE_G | IEEE_N_24G)) { + if (net->mode & (WIRELESS_MODE_G | WIRELESS_MODE_N_24G)) { u8 slot_time_val; u8 cur_slot_time = priv->slot_time; @@ -327,7 +327,7 @@ static void _rtl92e_qos_activate(void *data) int i; mutex_lock(&priv->mutex); - if (priv->rtllib->state != RTLLIB_LINKED) + if (priv->rtllib->link_state != MAC80211_LINKED) goto success; for (i = 0; i < QOS_QUEUE_NUM; i++) @@ -344,7 +344,7 @@ static int _rtl92e_qos_handle_probe_response(struct r8192_priv *priv, int ret = 0; u32 size = sizeof(struct rtllib_qos_parameters); - if (priv->rtllib->state != RTLLIB_LINKED) + if (priv->rtllib->link_state != MAC80211_LINKED) return ret; if (priv->rtllib->iw_mode != IW_MODE_INFRA) @@ -400,7 +400,7 @@ static int _rtl92e_qos_assoc_resp(struct r8192_priv *priv, if (!priv || !network) return 0; - if (priv->rtllib->state != RTLLIB_LINKED) + if (priv->rtllib->link_state != MAC80211_LINKED) return 0; if (priv->rtllib->iw_mode != IW_MODE_INFRA) @@ -466,7 +466,7 @@ static void _rtl92e_prepare_beacon(struct tasklet_struct *t) tcb_desc = (struct cb_desc *)(pnewskb->cb + 8); tcb_desc->queue_index = BEACON_QUEUE; tcb_desc->data_rate = 2; - tcb_desc->RATRIndex = 7; + tcb_desc->ratr_index = 7; tcb_desc->tx_dis_rate_fallback = 1; tcb_desc->tx_use_drv_assinged_rate = 1; skb_push(pnewskb, priv->rtllib->tx_headroom); @@ -635,7 +635,7 @@ static int _rtl92e_sta_up(struct net_device *dev, bool is_silent_reset) if (priv->polling_timer_on == 0) rtl92e_check_rfctrl_gpio_timer(&priv->gpio_polling_timer); - if (priv->rtllib->state != RTLLIB_LINKED) + if (priv->rtllib->link_state != MAC80211_LINKED) rtllib_softmac_start_protocol(priv->rtllib, 0); rtllib_reset_queue(priv->rtllib); _rtl92e_watchdog_timer_cb(&priv->watch_dog_timer); @@ -660,7 +660,7 @@ static int _rtl92e_sta_down(struct net_device *dev, bool shutdownrf) priv->rtllib->rtllib_ips_leave(dev); - if (priv->rtllib->state == RTLLIB_LINKED) + if (priv->rtllib->link_state == MAC80211_LINKED) rtl92e_leisure_ps_leave(dev); priv->up = 0; @@ -716,9 +716,9 @@ static void _rtl92e_init_priv_handler(struct net_device *dev) priv->rtllib->check_nic_enough_desc = _rtl92e_check_nic_enough_desc; priv->rtllib->handle_assoc_response = _rtl92e_handle_assoc_response; priv->rtllib->handle_beacon = _rtl92e_handle_beacon; - priv->rtllib->SetWirelessMode = rtl92e_set_wireless_mode; - priv->rtllib->LeisurePSLeave = rtl92e_leisure_ps_leave; - priv->rtllib->SetBWModeHandler = rtl92e_set_bw_mode; + priv->rtllib->set_wireless_mode = rtl92e_set_wireless_mode; + priv->rtllib->leisure_ps_leave = rtl92e_leisure_ps_leave; + priv->rtllib->set_bw_mode_handler = rtl92e_set_bw_mode; priv->rf_set_chan = rtl92e_set_channel; priv->rtllib->start_send_beacons = rtl92e_start_beacon; @@ -734,14 +734,9 @@ static void _rtl92e_init_priv_handler(struct net_device *dev) priv->rtllib->SetHwRegHandler = rtl92e_set_reg; priv->rtllib->AllowAllDestAddrHandler = rtl92e_set_monitor_mode; - priv->rtllib->SetFwCmdHandler = NULL; - priv->rtllib->InitialGainHandler = rtl92e_init_gain; + priv->rtllib->init_gain_handler = rtl92e_init_gain; priv->rtllib->rtllib_ips_leave_wq = rtl92e_rtllib_ips_leave_wq; priv->rtllib->rtllib_ips_leave = rtl92e_rtllib_ips_leave; - - priv->rtllib->LedControlHandler = NULL; - priv->rtllib->UpdateBeaconInterruptHandler = NULL; - priv->rtllib->ScanOperationBackupHandler = rtl92e_scan_op_backup; } @@ -1014,7 +1009,7 @@ static enum reset_type _rtl92e_if_check_reset(struct net_device *dev) if (rfState == rf_on && (priv->rtllib->iw_mode == IW_MODE_INFRA) && - (priv->rtllib->state == RTLLIB_LINKED)) + (priv->rtllib->link_state == MAC80211_LINKED)) RxResetType = _rtl92e_rx_check_stuck(dev); if (TxResetType == RESET_TYPE_NORMAL || @@ -1056,7 +1051,7 @@ static void _rtl92e_if_silent_reset(struct net_device *dev) mutex_lock(&priv->wx_mutex); - if (priv->rtllib->state == RTLLIB_LINKED) + if (priv->rtllib->link_state == MAC80211_LINKED) rtl92e_leisure_ps_leave(dev); if (priv->up) { @@ -1078,9 +1073,9 @@ static void _rtl92e_if_silent_reset(struct net_device *dev) rtl92e_dm_deinit(dev); rtllib_stop_scan_syncro(ieee); - if (ieee->state == RTLLIB_LINKED) { + if (ieee->link_state == MAC80211_LINKED) { mutex_lock(&ieee->wx_mutex); - netdev_info(dev, "ieee->state is RTLLIB_LINKED\n"); + netdev_info(dev, "ieee->link_state is MAC80211_LINKED\n"); rtllib_stop_send_beacons(priv->rtllib); del_timer_sync(&ieee->associate_timer); cancel_delayed_work(&ieee->associate_retry_wq); @@ -1088,7 +1083,7 @@ static void _rtl92e_if_silent_reset(struct net_device *dev) netif_carrier_off(dev); mutex_unlock(&ieee->wx_mutex); } else { - netdev_info(dev, "ieee->state is NOT LINKED\n"); + netdev_info(dev, "ieee->link_state is NOT LINKED\n"); rtllib_softmac_stop_protocol(priv->rtllib, 0, true); } @@ -1115,14 +1110,14 @@ static void _rtl92e_if_silent_reset(struct net_device *dev) rtl92e_enable_hw_security_config(dev); - if (ieee->state == RTLLIB_LINKED && ieee->iw_mode == + if (ieee->link_state == MAC80211_LINKED && ieee->iw_mode == IW_MODE_INFRA) { ieee->set_chan(ieee->dev, ieee->current_network.channel); schedule_work(&ieee->associate_complete_wq); - } else if (ieee->state == RTLLIB_LINKED && ieee->iw_mode == + } else if (ieee->link_state == MAC80211_LINKED && ieee->iw_mode == IW_MODE_ADHOC) { ieee->set_chan(ieee->dev, ieee->current_network.channel); @@ -1186,7 +1181,7 @@ static void _rtl92e_watchdog_wq_cb(void *data) if (!priv->up || priv->hw_radio_off) return; - if (priv->rtllib->state >= RTLLIB_LINKED) { + if (priv->rtllib->link_state >= MAC80211_LINKED) { if (priv->rtllib->CntAfterLink < 2) priv->rtllib->CntAfterLink++; } else { @@ -1196,8 +1191,8 @@ static void _rtl92e_watchdog_wq_cb(void *data) rtl92e_dm_watchdog(dev); if (!rtllib_act_scanning(priv->rtllib, false)) { - if ((ieee->iw_mode == IW_MODE_INFRA) && (ieee->state == - RTLLIB_NOLINK) && + if ((ieee->iw_mode == IW_MODE_INFRA) && (ieee->link_state == + MAC80211_NOLINK) && (ieee->rf_power_state == rf_on) && !ieee->is_set_key && (!ieee->proto_stoppping) && !ieee->wx_set_enc) { if ((ieee->pwr_save_ctrl.ReturnPoint == @@ -1207,7 +1202,7 @@ static void _rtl92e_watchdog_wq_cb(void *data) } } } - if ((ieee->state == RTLLIB_LINKED) && (ieee->iw_mode == + if ((ieee->link_state == MAC80211_LINKED) && (ieee->iw_mode == IW_MODE_INFRA) && (!ieee->net_promiscuous_md)) { if (ieee->link_detect_info.NumRxOkInPeriod > 100 || ieee->link_detect_info.NumTxOkInPeriod > 100) @@ -1249,7 +1244,7 @@ static void _rtl92e_watchdog_wq_cb(void *data) ieee->link_detect_info.bHigherBusyTraffic = bHigherBusyTraffic; ieee->link_detect_info.bHigherBusyRxTraffic = bHigherBusyRxTraffic; - if (ieee->state == RTLLIB_LINKED && ieee->iw_mode == IW_MODE_INFRA) { + if (ieee->link_state == MAC80211_LINKED && ieee->iw_mode == IW_MODE_INFRA) { u32 TotalRxBcnNum = 0; u32 TotalRxDataNum = 0; @@ -1268,17 +1263,13 @@ static void _rtl92e_watchdog_wq_cb(void *data) "===>%s(): AP is power off, chan:%d, connect another one\n", __func__, priv->chan); - ieee->state = RTLLIB_ASSOCIATING; + ieee->link_state = RTLLIB_ASSOCIATING; RemovePeerTS(priv->rtllib, priv->rtllib->current_network.bssid); ieee->is_roaming = true; ieee->is_set_key = false; ieee->link_change(dev); - if (ieee->LedControlHandler) - ieee->LedControlHandler(ieee->dev, - LED_CTL_START_TO_LINK); - notify_wx_assoc_event(ieee); if (!(ieee->rtllib_ap_sec_type(ieee) & @@ -1440,7 +1431,7 @@ static int _rtl92e_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) return 0; } - tcb_desc->RATRIndex = 7; + tcb_desc->ratr_index = 7; tcb_desc->tx_dis_rate_fallback = 1; tcb_desc->tx_use_drv_assinged_rate = 1; tcb_desc->bTxEnableFwCalcDur = 1; @@ -1509,7 +1500,6 @@ static short _rtl92e_tx(struct net_device *dev, struct sk_buff *skb) MAX_DEV_ADDR_SIZE); struct tx_desc *pdesc = NULL; struct rtllib_hdr_1addr *header = NULL; - u16 fc = 0, type = 0; u8 *pda_addr = NULL; int idx; u32 fwinfo_size = 0; @@ -1525,8 +1515,6 @@ static short _rtl92e_tx(struct net_device *dev, struct sk_buff *skb) fwinfo_size = sizeof(struct tx_fwinfo_8190pci); header = (struct rtllib_hdr_1addr *)(((u8 *)skb->data) + fwinfo_size); - fc = le16_to_cpu(header->frame_ctl); - type = WLAN_FC_GET_TYPE(fc); pda_addr = header->addr1; if (!is_broadcast_ether_addr(pda_addr) && !is_multicast_ether_addr(pda_addr)) @@ -1548,11 +1536,6 @@ static short _rtl92e_tx(struct net_device *dev, struct sk_buff *skb) spin_unlock_irqrestore(&priv->irq_th_lock, flags); return skb->len; } - - if (type == RTLLIB_FTYPE_DATA) { - if (priv->rtllib->LedControlHandler) - priv->rtllib->LedControlHandler(dev, LED_CTL_TX); - } rtl92e_fill_tx_desc(dev, pdesc, tcb_desc, skb); __skb_queue_tail(&ring->queue, skb); pdesc->OWN = 1; @@ -1779,8 +1762,6 @@ static void _rtl92e_rx_normal(struct net_device *dev) struct r8192_priv *priv = rtllib_priv(dev); struct rtllib_hdr_1addr *rtllib_hdr = NULL; bool unicast_packet = false; - bool bLedBlinking = true; - u16 fc = 0, type = 0; u32 skb_len = 0; int rx_queue_idx = RX_MPDU_QUEUE; @@ -1788,7 +1769,6 @@ static void _rtl92e_rx_normal(struct net_device *dev) .signal = 0, .noise = (u8)-98, .rate = 0, - .freq = RTLLIB_24GHZ_BAND, }; unsigned int count = priv->rxringcount; @@ -1824,16 +1804,6 @@ static void _rtl92e_rx_normal(struct net_device *dev) /* unicast packet */ unicast_packet = true; } - fc = le16_to_cpu(rtllib_hdr->frame_ctl); - type = WLAN_FC_GET_TYPE(fc); - if (type == RTLLIB_FTYPE_MGMT) - bLedBlinking = false; - - if (bLedBlinking) - if (priv->rtllib->LedControlHandler) - priv->rtllib->LedControlHandler(dev, - LED_CTL_RX); - skb_len = skb->len; if (!rtllib_rx(priv->rtllib, skb, &stats)) { diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_core.h b/drivers/staging/rtl8192e/rtl8192e/rtl_core.h index 285dac32c074b3bb2ddebe3283554f292e4591e1..ec9e454299a80eed2b07c9ce98bda40a389ef34e 100644 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_core.h +++ b/drivers/staging/rtl8192e/rtl8192e/rtl_core.h @@ -231,7 +231,6 @@ struct r8192_priv { struct rt_stats stats; struct iw_statistics wstats; - short (*rf_set_sens)(struct net_device *dev, short sens); u8 (*rf_set_chan)(struct net_device *dev, u8 ch); struct rx_desc *rx_ring[MAX_RX_QUEUE]; @@ -271,8 +270,6 @@ struct r8192_priv { short promisc; short chan; - short sens; - short max_sens; bool ps_force; u32 irq_mask[2]; diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c b/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c index 56a8ec517c069b568fe8b02be0ebbb64278ab6df..37c275cac40b757517e4877d850bb83e1c6917eb 100644 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c +++ b/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c @@ -159,7 +159,6 @@ static void _rtl92e_dm_check_rate_adaptive(struct net_device *dev); static void _rtl92e_dm_init_bandwidth_autoswitch(struct net_device *dev); static void _rtl92e_dm_bandwidth_autoswitch(struct net_device *dev); - static void _rtl92e_dm_check_tx_power_tracking(struct net_device *dev); static void _rtl92e_dm_bb_initialgain_restore(struct net_device *dev); @@ -179,7 +178,6 @@ static void _rtl92e_dm_check_rx_path_selection(struct net_device *dev); static void _rtl92e_dm_init_rx_path_selection(struct net_device *dev); static void _rtl92e_dm_rx_path_sel_byrssi(struct net_device *dev); - static void _rtl92e_dm_init_fsync(struct net_device *dev); static void _rtl92e_dm_deinit_fsync(struct net_device *dev); @@ -219,9 +217,7 @@ void rtl92e_dm_init(struct net_device *dev) void rtl92e_dm_deinit(struct net_device *dev) { - _rtl92e_dm_deinit_fsync(dev); - } void rtl92e_dm_watchdog(struct net_device *dev) @@ -250,7 +246,6 @@ void rtl92e_dm_watchdog(struct net_device *dev) void rtl92e_init_adaptive_rate(struct net_device *dev) { - struct r8192_priv *priv = rtllib_priv(dev); struct rate_adaptive *pra = &priv->rate_adaptive; @@ -296,8 +291,7 @@ static void _rtl92e_dm_check_rate_adaptive(struct net_device *dev) if (priv->rtllib->mode != WIRELESS_MODE_N_24G) return; - if (priv->rtllib->state == RTLLIB_LINKED) { - + if (priv->rtllib->link_state == MAC80211_LINKED) { bshort_gi_enabled = (ht_info->cur_tx_bw40mhz && ht_info->bCurShortGI40MHz) || (!ht_info->cur_tx_bw40mhz && @@ -353,7 +347,7 @@ static void _rtl92e_dm_check_rate_adaptive(struct net_device *dev) if (pra->ping_rssi_enable) { if (priv->undecorated_smoothed_pwdb < - (long)(pra->ping_rssi_thresh_for_ra+5)) { + (long)(pra->ping_rssi_thresh_for_ra + 5)) { if ((priv->undecorated_smoothed_pwdb < (long)pra->ping_rssi_thresh_for_ra) || ping_rssi_state) { @@ -524,7 +518,6 @@ static void _rtl92e_dm_tx_power_tracking_callback_tssi(struct net_device *dev) priv->rtllib->bdynamic_txpower_enable = false; for (j = 0; j <= 30; j++) { - tx_cmd.op = TXCMD_SET_TX_PWR_TRACKING; tx_cmd.length = 4; tx_cmd.value = priv->pwr_track >> 24; @@ -562,7 +555,7 @@ static void _rtl92e_dm_tx_power_tracking_callback_tssi(struct net_device *dev) for (k = 0; k < 5; k++) { if (k != 4) tmp_report[k] = rtl92e_readb(dev, - Tssi_Report_Value1+k); + Tssi_Report_Value1 + k); else tmp_report[k] = rtl92e_readb(dev, Tssi_Report_Value2); @@ -629,8 +622,9 @@ static void _rtl92e_dm_tx_power_tracking_callback_tssi(struct net_device *dev) } else if (priv->rtllib->current_network.channel != 14 && priv->bcck_in_ch14) { priv->bcck_in_ch14 = false; rtl92e_dm_cck_txpower_adjust(dev, priv->bcck_in_ch14); - } else + } else { rtl92e_dm_cck_txpower_adjust(dev, priv->bcck_in_ch14); + } } if (priv->cck_present_attn_diff <= -12 || @@ -657,21 +651,21 @@ static void _rtl92e_dm_tx_power_tracking_cb_thermal(struct net_device *dev) { #define ThermalMeterVal 9 struct r8192_priv *priv = rtllib_priv(dev); - u32 tmpRegA, TempCCk; - u8 tmpOFDMindex, tmpCCKindex, tmpCCK20Mindex, tmpCCK40Mindex, tmpval; + u32 tmp_reg, tmp_cck; + u8 tmp_ofdm_index, tmp_cck_index, tmp_cck_20m_index, tmp_cck_40m_index, tmpval; int i = 0, CCKSwingNeedUpdate = 0; if (!priv->tx_pwr_tracking_init) { - tmpRegA = rtl92e_get_bb_reg(dev, rOFDM0_XATxIQImbalance, + tmp_reg = rtl92e_get_bb_reg(dev, rOFDM0_XATxIQImbalance, bMaskDWord); for (i = 0; i < OFDM_TABLE_LEN; i++) { - if (tmpRegA == OFDMSwingTable[i]) + if (tmp_reg == OFDMSwingTable[i]) priv->ofdm_index[0] = i; } - TempCCk = rtl92e_get_bb_reg(dev, rCCK0_TxFilter1, bMaskByte2); + tmp_cck = rtl92e_get_bb_reg(dev, rCCK0_TxFilter1, bMaskByte2); for (i = 0; i < CCK_TABLE_LEN; i++) { - if (TempCCk == (u32)CCKSwingTable_Ch1_Ch13[i][0]) { + if (tmp_cck == (u32)CCKSwingTable_Ch1_Ch13[i][0]) { priv->cck_index = i; break; } @@ -680,42 +674,42 @@ static void _rtl92e_dm_tx_power_tracking_cb_thermal(struct net_device *dev) return; } - tmpRegA = rtl92e_get_rf_reg(dev, RF90_PATH_A, 0x12, 0x078); - if (tmpRegA < 3 || tmpRegA > 13) + tmp_reg = rtl92e_get_rf_reg(dev, RF90_PATH_A, 0x12, 0x078); + if (tmp_reg < 3 || tmp_reg > 13) return; - if (tmpRegA >= 12) - tmpRegA = 12; + if (tmp_reg >= 12) + tmp_reg = 12; priv->thermal_meter[0] = ThermalMeterVal; priv->thermal_meter[1] = ThermalMeterVal; - if (priv->thermal_meter[0] >= (u8)tmpRegA) { - tmpOFDMindex = tmpCCK20Mindex = 6+(priv->thermal_meter[0] - - (u8)tmpRegA); - tmpCCK40Mindex = tmpCCK20Mindex - 6; - if (tmpOFDMindex >= OFDM_TABLE_LEN) - tmpOFDMindex = OFDM_TABLE_LEN - 1; - if (tmpCCK20Mindex >= CCK_TABLE_LEN) - tmpCCK20Mindex = CCK_TABLE_LEN - 1; - if (tmpCCK40Mindex >= CCK_TABLE_LEN) - tmpCCK40Mindex = CCK_TABLE_LEN - 1; + if (priv->thermal_meter[0] >= (u8)tmp_reg) { + tmp_ofdm_index = 6 + (priv->thermal_meter[0] - (u8)tmp_reg); + tmp_cck_20m_index = tmp_ofdm_index; + tmp_cck_40m_index = tmp_cck_20m_index - 6; + if (tmp_ofdm_index >= OFDM_TABLE_LEN) + tmp_ofdm_index = OFDM_TABLE_LEN - 1; + if (tmp_cck_20m_index >= CCK_TABLE_LEN) + tmp_cck_20m_index = CCK_TABLE_LEN - 1; + if (tmp_cck_40m_index >= CCK_TABLE_LEN) + tmp_cck_40m_index = CCK_TABLE_LEN - 1; } else { - tmpval = (u8)tmpRegA - priv->thermal_meter[0]; + tmpval = (u8)tmp_reg - priv->thermal_meter[0]; if (tmpval >= 6) { - tmpOFDMindex = 0; - tmpCCK20Mindex = 0; + tmp_ofdm_index = 0; + tmp_cck_20m_index = 0; } else { - tmpOFDMindex = 6 - tmpval; - tmpCCK20Mindex = 6 - tmpval; + tmp_ofdm_index = 6 - tmpval; + tmp_cck_20m_index = 6 - tmpval; } - tmpCCK40Mindex = 0; + tmp_cck_40m_index = 0; } if (priv->current_chnl_bw != HT_CHANNEL_WIDTH_20) - tmpCCKindex = tmpCCK40Mindex; + tmp_cck_index = tmp_cck_40m_index; else - tmpCCKindex = tmpCCK20Mindex; + tmp_cck_index = tmp_cck_20m_index; - priv->rec_cck_20m_idx = tmpCCK20Mindex; - priv->rec_cck_40m_idx = tmpCCK40Mindex; + priv->rec_cck_20m_idx = tmp_cck_20m_index; + priv->rec_cck_40m_idx = tmp_cck_40m_index; if (priv->rtllib->current_network.channel == 14 && !priv->bcck_in_ch14) { @@ -727,15 +721,15 @@ static void _rtl92e_dm_tx_power_tracking_cb_thermal(struct net_device *dev) CCKSwingNeedUpdate = 1; } - if (priv->cck_index != tmpCCKindex) { - priv->cck_index = tmpCCKindex; + if (priv->cck_index != tmp_cck_index) { + priv->cck_index = tmp_cck_index; CCKSwingNeedUpdate = 1; } if (CCKSwingNeedUpdate) rtl92e_dm_cck_txpower_adjust(dev, priv->bcck_in_ch14); - if (priv->ofdm_index[0] != tmpOFDMindex) { - priv->ofdm_index[0] = tmpOFDMindex; + if (priv->ofdm_index[0] != tmp_ofdm_index) { + priv->ofdm_index[0] = tmp_ofdm_index; rtl92e_set_bb_reg(dev, rOFDM0_XATxIQImbalance, bMaskDWord, OFDMSwingTable[priv->ofdm_index[0]]); } @@ -756,20 +750,17 @@ void rtl92e_dm_txpower_tracking_wq(void *data) static void _rtl92e_dm_initialize_tx_power_tracking_tssi(struct net_device *dev) { - struct r8192_priv *priv = rtllib_priv(dev); priv->btxpower_tracking = true; priv->txpower_count = 0; priv->tx_pwr_tracking_init = false; - } static void _rtl92e_dm_init_tx_power_tracking_thermal(struct net_device *dev) { struct r8192_priv *priv = rtllib_priv(dev); - if (priv->rtllib->FwRWRF) priv->btxpower_tracking = true; else @@ -799,12 +790,10 @@ static void _rtl92e_dm_check_tx_power_tracking_tssi(struct net_device *dev) return; tx_power_track_counter++; - if (tx_power_track_counter >= 180) { schedule_delayed_work(&priv->txpower_tracking_wq, 0); tx_power_track_counter = 0; } - } static void _rtl92e_dm_check_tx_power_tracking_thermal(struct net_device *dev) @@ -833,7 +822,6 @@ static void _rtl92e_dm_check_tx_power_tracking_thermal(struct net_device *dev) netdev_info(dev, "===============>Schedule TxPowerTrackingWorkItem\n"); schedule_delayed_work(&priv->txpower_tracking_wq, 0); TM_Trigger = 0; - } static void _rtl92e_dm_check_tx_power_tracking(struct net_device *dev) @@ -861,7 +849,7 @@ static void _rtl92e_dm_cck_tx_power_adjust_tssi(struct net_device *dev, rtl92e_set_bb_reg(dev, rCCK0_TxFilter1, bMaskHWord, TempVal); TempVal = (u32)((dm_cck_tx_bb_gain[attenuation][2]) + (dm_cck_tx_bb_gain[attenuation][3] << 8) + - (dm_cck_tx_bb_gain[attenuation][4] << 16)+ + (dm_cck_tx_bb_gain[attenuation][4] << 16) + (dm_cck_tx_bb_gain[attenuation][5] << 24)); rtl92e_set_bb_reg(dev, rCCK0_TxFilter2, bMaskDWord, TempVal); TempVal = (u32)(dm_cck_tx_bb_gain[attenuation][6] + @@ -875,7 +863,7 @@ static void _rtl92e_dm_cck_tx_power_adjust_tssi(struct net_device *dev, rtl92e_set_bb_reg(dev, rCCK0_TxFilter1, bMaskHWord, TempVal); TempVal = (u32)((dm_cck_tx_bb_gain_ch14[attenuation][2]) + (dm_cck_tx_bb_gain_ch14[attenuation][3] << 8) + - (dm_cck_tx_bb_gain_ch14[attenuation][4] << 16)+ + (dm_cck_tx_bb_gain_ch14[attenuation][4] << 16) + (dm_cck_tx_bb_gain_ch14[attenuation][5] << 24)); rtl92e_set_bb_reg(dev, rCCK0_TxFilter2, bMaskDWord, TempVal); TempVal = (u32)((dm_cck_tx_bb_gain_ch14[attenuation][6]) + @@ -898,7 +886,7 @@ static void _rtl92e_dm_cck_tx_power_adjust_thermal_meter(struct net_device *dev, rtl92e_set_bb_reg(dev, rCCK0_TxFilter1, bMaskHWord, TempVal); TempVal = CCKSwingTable_Ch1_Ch13[priv->cck_index][2] + (CCKSwingTable_Ch1_Ch13[priv->cck_index][3] << 8) + - (CCKSwingTable_Ch1_Ch13[priv->cck_index][4] << 16)+ + (CCKSwingTable_Ch1_Ch13[priv->cck_index][4] << 16) + (CCKSwingTable_Ch1_Ch13[priv->cck_index][5] << 24); rtl92e_set_bb_reg(dev, rCCK0_TxFilter2, bMaskDWord, TempVal); TempVal = CCKSwingTable_Ch1_Ch13[priv->cck_index][6] + @@ -912,11 +900,11 @@ static void _rtl92e_dm_cck_tx_power_adjust_thermal_meter(struct net_device *dev, rtl92e_set_bb_reg(dev, rCCK0_TxFilter1, bMaskHWord, TempVal); TempVal = CCKSwingTable_Ch14[priv->cck_index][2] + (CCKSwingTable_Ch14[priv->cck_index][3] << 8) + - (CCKSwingTable_Ch14[priv->cck_index][4] << 16)+ + (CCKSwingTable_Ch14[priv->cck_index][4] << 16) + (CCKSwingTable_Ch14[priv->cck_index][5] << 24); rtl92e_set_bb_reg(dev, rCCK0_TxFilter2, bMaskDWord, TempVal); TempVal = CCKSwingTable_Ch14[priv->cck_index][6] + - (CCKSwingTable_Ch14[priv->cck_index][7]<<8); + (CCKSwingTable_Ch14[priv->cck_index][7] << 8); rtl92e_set_bb_reg(dev, rCCK0_DebugPort, bMaskLWord, TempVal); } @@ -965,7 +953,6 @@ void rtl92e_dm_restore_state(struct net_device *dev) _rtl92e_dm_tx_power_reset_recovery(dev); _rtl92e_dm_bb_initialgain_restore(dev); - } static void _rtl92e_dm_bb_initialgain_restore(struct net_device *dev) @@ -989,7 +976,6 @@ static void _rtl92e_dm_bb_initialgain_restore(struct net_device *dev) rtl92e_set_bb_reg(dev, rCCK0_CCA, bit_mask, (u32)priv->initgain_backup.cca); rtl92e_set_bb_reg(dev, UFWP, bMaskByte1, 0x1); - } void rtl92e_dm_backup_state(struct net_device *dev) @@ -1043,7 +1029,6 @@ static void _rtl92e_dm_dig_init(struct net_device *dev) static void _rtl92e_dm_ctrl_initgain_byrssi(struct net_device *dev) { - if (!dm_digtable.dig_enable_flag) return; @@ -1091,12 +1076,11 @@ static void _rtl92e_dm_ctrl_initgain_byrssi_driver(struct net_device *dev) dm_digtable.dig_state = DM_STA_DIG_OFF; } - if (priv->rtllib->state == RTLLIB_LINKED) + if (priv->rtllib->link_state == MAC80211_LINKED) dm_digtable.cur_sta_connect_state = DIG_STA_CONNECT; else dm_digtable.cur_sta_connect_state = DIG_STA_DISCONNECT; - dm_digtable.rssi_val = priv->undecorated_smoothed_pwdb; _rtl92e_dm_initial_gain(dev); _rtl92e_dm_pd_th(dev); @@ -1104,7 +1088,6 @@ static void _rtl92e_dm_ctrl_initgain_byrssi_driver(struct net_device *dev) if (dm_digtable.dig_algorithm_switch) dm_digtable.dig_algorithm_switch = 0; dm_digtable.pre_sta_connect_state = dm_digtable.cur_sta_connect_state; - } static void _rtl92e_dm_ctrl_initgain_byrssi_false_alarm(struct net_device *dev) @@ -1123,7 +1106,7 @@ static void _rtl92e_dm_ctrl_initgain_byrssi_false_alarm(struct net_device *dev) dm_digtable.dig_algorithm_switch = 0; } - if (priv->rtllib->state != RTLLIB_LINKED) + if (priv->rtllib->link_state != MAC80211_LINKED) return; if ((priv->undecorated_smoothed_pwdb > dm_digtable.rssi_low_thresh) && @@ -1146,7 +1129,7 @@ static void _rtl92e_dm_ctrl_initgain_byrssi_false_alarm(struct net_device *dev) rtl92e_writeb(dev, rOFDM0_XDAGCCore1, 0x17); if (priv->current_chnl_bw != HT_CHANNEL_WIDTH_20) - rtl92e_writeb(dev, (rOFDM0_XATxAFE+3), 0x00); + rtl92e_writeb(dev, (rOFDM0_XATxAFE + 3), 0x00); else rtl92e_writeb(dev, rOFDM0_RxDetector1, 0x42); @@ -1183,7 +1166,7 @@ static void _rtl92e_dm_ctrl_initgain_byrssi_false_alarm(struct net_device *dev) } if (priv->current_chnl_bw != HT_CHANNEL_WIDTH_20) - rtl92e_writeb(dev, (rOFDM0_XATxAFE+3), 0x20); + rtl92e_writeb(dev, (rOFDM0_XATxAFE + 3), 0x20); else rtl92e_writeb(dev, rOFDM0_RxDetector1, 0x44); @@ -1194,7 +1177,6 @@ static void _rtl92e_dm_ctrl_initgain_byrssi_false_alarm(struct net_device *dev) _rtl92e_dm_ctrl_initgain_byrssi_highpwr(dev); } - static void _rtl92e_dm_ctrl_initgain_byrssi_highpwr(struct net_device *dev) { struct r8192_priv *priv = rtllib_priv(dev); @@ -1214,7 +1196,7 @@ static void _rtl92e_dm_ctrl_initgain_byrssi_highpwr(struct net_device *dev) dm_digtable.dig_highpwr_state = DM_STA_DIG_ON; if (priv->current_chnl_bw != HT_CHANNEL_WIDTH_20) - rtl92e_writeb(dev, (rOFDM0_XATxAFE+3), 0x10); + rtl92e_writeb(dev, (rOFDM0_XATxAFE + 3), 0x10); else rtl92e_writeb(dev, rOFDM0_RxDetector1, 0x43); } else { @@ -1228,7 +1210,7 @@ static void _rtl92e_dm_ctrl_initgain_byrssi_highpwr(struct net_device *dev) (priv->undecorated_smoothed_pwdb >= dm_digtable.rssi_high_thresh)) { if (priv->current_chnl_bw != HT_CHANNEL_WIDTH_20) - rtl92e_writeb(dev, (rOFDM0_XATxAFE+3), 0x20); + rtl92e_writeb(dev, (rOFDM0_XATxAFE + 3), 0x20); else rtl92e_writeb(dev, rOFDM0_RxDetector1, 0x44); } @@ -1339,18 +1321,18 @@ static void _rtl92e_dm_pd_th(struct net_device *dev) (initialized <= 3) || force_write) { if (dm_digtable.curpd_thstate == DIG_PD_AT_LOW_POWER) { if (priv->current_chnl_bw != HT_CHANNEL_WIDTH_20) - rtl92e_writeb(dev, (rOFDM0_XATxAFE+3), 0x00); + rtl92e_writeb(dev, (rOFDM0_XATxAFE + 3), 0x00); else rtl92e_writeb(dev, rOFDM0_RxDetector1, 0x42); } else if (dm_digtable.curpd_thstate == DIG_PD_AT_NORMAL_POWER) { if (priv->current_chnl_bw != HT_CHANNEL_WIDTH_20) - rtl92e_writeb(dev, (rOFDM0_XATxAFE+3), 0x20); + rtl92e_writeb(dev, (rOFDM0_XATxAFE + 3), 0x20); else rtl92e_writeb(dev, rOFDM0_RxDetector1, 0x44); } else if (dm_digtable.curpd_thstate == DIG_PD_AT_HIGH_POWER) { if (priv->current_chnl_bw != HT_CHANNEL_WIDTH_20) - rtl92e_writeb(dev, (rOFDM0_XATxAFE+3), 0x10); + rtl92e_writeb(dev, (rOFDM0_XATxAFE + 3), 0x10); else rtl92e_writeb(dev, rOFDM0_RxDetector1, 0x43); } @@ -1392,7 +1374,6 @@ static void _rtl92e_dm_cs_ratio(struct net_device *dev) reset_cnt = priv->reset_count; } - if ((dm_digtable.precs_ratio_state != dm_digtable.curcs_ratio_state) || !initialized || force_write) { if (dm_digtable.curcs_ratio_state == DIG_CS_RATIO_LOWER) @@ -1426,7 +1407,7 @@ static void _rtl92e_dm_check_edca_turbo(struct net_device *dev) if (priv->rtllib->iw_mode == IW_MODE_ADHOC) goto dm_CheckEdcaTurbo_EXIT; - if (priv->rtllib->state != RTLLIB_LINKED) + if (priv->rtllib->link_state != MAC80211_LINKED) goto dm_CheckEdcaTurbo_EXIT; if (priv->rtllib->ht_info->iot_action & HT_IOT_ACT_DISABLE_EDCA_TURBO) goto dm_CheckEdcaTurbo_EXIT; @@ -1435,7 +1416,7 @@ static void _rtl92e_dm_check_edca_turbo(struct net_device *dev) curTxOkCnt = priv->stats.txbytesunicast - lastTxOkCnt; curRxOkCnt = priv->stats.rxbytesunicast - lastRxOkCnt; if (ht_info->iot_action & HT_IOT_ACT_EDCA_BIAS_ON_RX) { - if (curTxOkCnt > 4*curRxOkCnt) { + if (curTxOkCnt > 4 * curRxOkCnt) { if (priv->bis_cur_rdlstate || !priv->bcurrent_turbo_EDCA) { rtl92e_writel(dev, EDCAPARA_BE, @@ -1456,7 +1437,7 @@ static void _rtl92e_dm_check_edca_turbo(struct net_device *dev) } priv->bcurrent_turbo_EDCA = true; } else { - if (curRxOkCnt > 4*curTxOkCnt) { + if (curRxOkCnt > 4 * curTxOkCnt) { if (!priv->bis_cur_rdlstate || !priv->bcurrent_turbo_EDCA) { if (priv->rtllib->mode == WIRELESS_MODE_G) @@ -1474,7 +1455,6 @@ static void _rtl92e_dm_check_edca_turbo(struct net_device *dev) edca_setting_UL[ht_info->IOTPeer]); priv->bis_cur_rdlstate = false; } - } priv->bcurrent_turbo_EDCA = true; @@ -1489,7 +1469,6 @@ static void _rtl92e_dm_check_edca_turbo(struct net_device *dev) } } - dm_CheckEdcaTurbo_EXIT: priv->rtllib->bis_any_nonbepkts = false; lastTxOkCnt = priv->stats.txbytesunicast; @@ -1519,7 +1498,7 @@ static void _rtl92e_dm_cts_to_self(struct net_device *dev) if (ht_info->IOTPeer == HT_IOT_PEER_BROADCOM) { curTxOkCnt = priv->stats.txbytesunicast - lastTxOkCnt; curRxOkCnt = priv->stats.rxbytesunicast - lastRxOkCnt; - if (curRxOkCnt > 4*curTxOkCnt) + if (curRxOkCnt > 4 * curTxOkCnt) ht_info->iot_action &= ~HT_IOT_ACT_FORCED_CTS2SELF; else ht_info->iot_action |= HT_IOT_ACT_FORCED_CTS2SELF; @@ -1546,7 +1525,7 @@ static void _rtl92e_dm_check_rf_ctrl_gpio(void *data) tmp1byte = rtl92e_readb(dev, GPI); - rf_power_state_to_set = (tmp1byte&BIT1) ? rf_on : rf_off; + rf_power_state_to_set = (tmp1byte & BIT1) ? rf_on : rf_off; if (priv->hw_radio_off && (rf_power_state_to_set == rf_on)) { netdev_info(dev, "gpiochangeRF - HW Radio ON\n"); @@ -1576,7 +1555,7 @@ void rtl92e_dm_rf_pathcheck_wq(void *data) rfpath = rtl92e_readb(dev, 0xc04); for (i = 0; i < RF90_PATH_MAX; i++) { - if (rfpath & (0x01<brfpath_rxenable[i] = true; else priv->brfpath_rxenable[i] = false; @@ -1627,7 +1606,7 @@ static void _rtl92e_dm_rx_path_sel_byrssi(struct net_device *dev) u8 update_cck_rx_path; if (!cck_Rx_Path_initialized) { - dm_rx_path_sel_table.cck_rx_path = (rtl92e_readb(dev, 0xa07)&0xf); + dm_rx_path_sel_table.cck_rx_path = (rtl92e_readb(dev, 0xa07) & 0xf); cck_Rx_Path_initialized = 1; } @@ -1746,7 +1725,6 @@ static void _rtl92e_dm_rx_path_sel_byrssi(struct net_device *dev) tmp_cck_min_pwdb = cur_cck_pwdb; } } - } } } @@ -1763,11 +1741,11 @@ static void _rtl92e_dm_rx_path_sel_byrssi(struct net_device *dev) if ((tmp_max_rssi - tmp_min_rssi) >= dm_rx_path_sel_table.diff_th) { dm_rx_path_sel_table.rf_enable_rssi_th[min_rssi_index] = - tmp_max_rssi+5; + tmp_max_rssi + 5; rtl92e_set_bb_reg(dev, rOFDM0_TRxPathEnable, - 0x1<rfpath_check_wq, 0); } - static void _rtl92e_dm_init_fsync(struct net_device *dev) { struct r8192_priv *priv = rtllib_priv(dev); @@ -1829,7 +1806,6 @@ static void _rtl92e_dm_init_fsync(struct net_device *dev) timer_setup(&priv->fsync_timer, _rtl92e_dm_fsync_timer_callback, 0); } - static void _rtl92e_dm_deinit_fsync(struct net_device *dev) { struct r8192_priv *priv = rtllib_priv(dev); @@ -1845,7 +1821,7 @@ static void _rtl92e_dm_fsync_timer_callback(struct timer_list *t) bool bSwitchFromCountDiff = false; bool bDoubleTimeInterval = false; - if (priv->rtllib->state == RTLLIB_LINKED && + if (priv->rtllib->link_state == MAC80211_LINKED && priv->rtllib->bfsync_enable && (priv->rtllib->ht_info->iot_action & HT_IOT_ACT_CDD_FSYNC)) { u32 rate_bitmap; @@ -1864,7 +1840,6 @@ static void _rtl92e_dm_fsync_timer_callback(struct timer_list *t) else rate_count_diff = rate_count - priv->rate_record; if (rate_count_diff < priv->rate_count_diff_rec) { - u32 DiffNum = priv->rate_count_diff_rec - rate_count_diff; if (DiffNum >= @@ -2005,7 +1980,6 @@ static void _rtl92e_dm_start_sw_fsync(struct net_device *dev) add_timer(&priv->fsync_timer); rtl92e_writel(dev, rOFDM0_RxDetector2, 0x465c12cd); - } static void _rtl92e_dm_check_fsync(struct net_device *dev) @@ -2017,7 +1991,7 @@ static void _rtl92e_dm_check_fsync(struct net_device *dev) static u8 reg_c38_State = RegC38_Default; static u32 reset_cnt; - if (priv->rtllib->state == RTLLIB_LINKED && + if (priv->rtllib->link_state == MAC80211_LINKED && priv->rtllib->ht_info->IOTPeer == HT_IOT_PEER_BROADCOM) { if (priv->rtllib->bfsync_enable == 0) { switch (priv->rtllib->fsync_state) { @@ -2048,7 +2022,6 @@ static void _rtl92e_dm_check_fsync(struct net_device *dev) case SW_Fsync: default: break; - } } if (reg_c38_State != RegC38_Fsync_AP_BCM) { @@ -2071,7 +2044,7 @@ static void _rtl92e_dm_check_fsync(struct net_device *dev) break; } - if (priv->rtllib->state == RTLLIB_LINKED) { + if (priv->rtllib->link_state == MAC80211_LINKED) { if (priv->undecorated_smoothed_pwdb <= RegC38_TH) { if (reg_c38_State != @@ -2084,7 +2057,7 @@ static void _rtl92e_dm_check_fsync(struct net_device *dev) RegC38_NonFsync_Other_AP; } } else if (priv->undecorated_smoothed_pwdb >= - (RegC38_TH+5)) { + (RegC38_TH + 5)) { if (reg_c38_State) { rtl92e_writeb(dev, rOFDM0_RxDetector3, @@ -2132,7 +2105,7 @@ static void _rtl92e_dm_dynamic_tx_power(struct net_device *dev) return; } if ((priv->rtllib->ht_info->IOTPeer == HT_IOT_PEER_ATHEROS) && - (priv->rtllib->mode == IEEE_G)) { + (priv->rtllib->mode == WIRELESS_MODE_G)) { txhipower_threshold = TX_POWER_ATHEROAP_THRESH_HIGH; txlowpower_threshold = TX_POWER_ATHEROAP_THRESH_LOW; } else { @@ -2140,7 +2113,7 @@ static void _rtl92e_dm_dynamic_tx_power(struct net_device *dev) txlowpower_threshold = TX_POWER_NEAR_FIELD_THRESH_LOW; } - if (priv->rtllib->state == RTLLIB_LINKED) { + if (priv->rtllib->link_state == MAC80211_LINKED) { if (priv->undecorated_smoothed_pwdb >= txhipower_threshold) { priv->dynamic_tx_high_pwr = true; priv->dynamic_tx_low_pwr = false; @@ -2164,7 +2137,6 @@ static void _rtl92e_dm_dynamic_tx_power(struct net_device *dev) } priv->last_dtp_flag_high = priv->dynamic_tx_high_pwr; priv->last_dtp_flag_low = priv->dynamic_tx_low_pwr; - } static void _rtl92e_dm_check_txrateandretrycount(struct net_device *dev) diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_ethtool.c b/drivers/staging/rtl8192e/rtl8192e/rtl_ethtool.c index f4f7b74c8cd1c435a82c1069809ff4abb7824f13..fab8932e67dae5116a74a56a7388567e56e78b4c 100644 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_ethtool.c +++ b/drivers/staging/rtl8192e/rtl8192e/rtl_ethtool.c @@ -27,8 +27,8 @@ static u32 _rtl92e_ethtool_get_link(struct net_device *dev) { struct r8192_priv *priv = rtllib_priv(dev); - return ((priv->rtllib->state == RTLLIB_LINKED) || - (priv->rtllib->state == RTLLIB_LINKED_SCANNING)); + return ((priv->rtllib->link_state == MAC80211_LINKED) || + (priv->rtllib->link_state == MAC80211_LINKED_SCANNING)); } const struct ethtool_ops rtl819x_ethtool_ops = { diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_pm.c b/drivers/staging/rtl8192e/rtl8192e/rtl_pm.c index 9c80dc1b6e12ab27246ecae1a76e84f4a42a3980..d124b5eee0cc9b0dc05706eb987ee1eddbf951ee 100644 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_pm.c +++ b/drivers/staging/rtl8192e/rtl8192e/rtl_pm.c @@ -9,7 +9,6 @@ #include "r8190P_rtl8256.h" #include "rtl_pm.h" - int rtl92e_suspend(struct device *dev_d) { struct net_device *dev = dev_get_drvdata(dev_d); @@ -62,7 +61,6 @@ int rtl92e_resume(struct device *dev_d) netdev_info(dev, "================>r8192E resume call.\n"); - pci_read_config_dword(pdev, 0x40, &val); if ((val & 0x0000ff00) != 0) pci_write_config_dword(pdev, 0x40, val & 0xffff00ff); diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_ps.c b/drivers/staging/rtl8192e/rtl8192e/rtl_ps.c index 5a1cd22f5e2522e302693b4952e440d81f8b1d24..1c49d5da68ebfda9381f5754e8a4d2a9bce39c8b 100644 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_ps.c +++ b/drivers/staging/rtl8192e/rtl8192e/rtl_ps.c @@ -118,7 +118,7 @@ void rtl92e_ips_enter(struct net_device *dev) rt_state = priv->rtllib->rf_power_state; if (rt_state == rf_on && !psc->bSwRfProcessing && - (priv->rtllib->state != RTLLIB_LINKED) && + (priv->rtllib->link_state != MAC80211_LINKED) && (priv->rtllib->iw_mode != IW_MODE_MASTER)) { psc->eInactivePowerState = rf_off; _rtl92e_ps_update_rf_state(dev); @@ -209,7 +209,7 @@ void rtl92e_leisure_ps_enter(struct net_device *dev) &priv->rtllib->pwr_save_ctrl; if (!((priv->rtllib->iw_mode == IW_MODE_INFRA) && - (priv->rtllib->state == RTLLIB_LINKED)) + (priv->rtllib->link_state == MAC80211_LINKED)) || (priv->rtllib->iw_mode == IW_MODE_ADHOC) || (priv->rtllib->iw_mode == IW_MODE_MASTER)) return; @@ -217,14 +217,11 @@ void rtl92e_leisure_ps_enter(struct net_device *dev) if (psc->bLeisurePs) { if (psc->LpsIdleCount >= RT_CHECK_FOR_HANG_PERIOD) { - if (priv->rtllib->ps == RTLLIB_PS_DISABLED) { - if (priv->rtllib->SetFwCmdHandler) - priv->rtllib->SetFwCmdHandler(dev, FW_CMD_LPS_ENTER); - _rtl92e_ps_set_mode(dev, RTLLIB_PS_MBCAST | - RTLLIB_PS_UNICAST); - } - } else + if (priv->rtllib->ps == RTLLIB_PS_DISABLED) + _rtl92e_ps_set_mode(dev, RTLLIB_PS_MBCAST | RTLLIB_PS_UNICAST); + } else { psc->LpsIdleCount++; + } } } @@ -235,10 +232,7 @@ void rtl92e_leisure_ps_leave(struct net_device *dev) &priv->rtllib->pwr_save_ctrl; if (psc->bLeisurePs) { - if (priv->rtllib->ps != RTLLIB_PS_DISABLED) { + if (priv->rtllib->ps != RTLLIB_PS_DISABLED) _rtl92e_ps_set_mode(dev, RTLLIB_PS_DISABLED); - if (priv->rtllib->SetFwCmdHandler) - priv->rtllib->SetFwCmdHandler(dev, FW_CMD_LPS_LEAVE); - } } } diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_wx.c b/drivers/staging/rtl8192e/rtl8192e/rtl_wx.c index cb28288a618b99457c3e9d8971a9e46187a630dc..88975dc804c6f15da88fad6ae192971d6af6ce3b 100644 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_wx.c +++ b/drivers/staging/rtl8192e/rtl8192e/rtl_wx.c @@ -169,7 +169,7 @@ static int _rtl92e_wx_adapter_power_status(struct net_device *dev, priv->ps_force = false; psc->bLeisurePs = true; } else { - if (priv->rtllib->state == RTLLIB_LINKED) + if (priv->rtllib->link_state == MAC80211_LINKED) rtl92e_leisure_ps_leave(dev); priv->ps_force = true; @@ -311,10 +311,6 @@ static int _rtl92e_wx_get_range(struct net_device *dev, /* ~130 Mb/s real (802.11n) */ range->throughput = 130 * 1000 * 1000; - if (priv->rf_set_sens != NULL) - /* signal level threshold range */ - range->sensitivity = priv->max_sens; - range->max_qual.qual = 100; range->max_qual.level = 0; range->max_qual.noise = 0; @@ -346,9 +342,11 @@ static int _rtl92e_wx_get_range(struct net_device *dev, for (i = 0, val = 0; i < 14; i++) { if ((priv->rtllib->active_channel_map)[i + 1]) { + s32 freq_khz; + range->freq[val].i = i + 1; - range->freq[val].m = rtllib_wlan_frequencies[i] * - 100000; + freq_khz = ieee80211_channel_to_freq_khz(i + 1, NL80211_BAND_2GHZ); + range->freq[val].m = freq_khz * 100; range->freq[val].e = 1; val++; } @@ -377,10 +375,10 @@ static int _rtl92e_wx_set_scan(struct net_device *dev, int ret; if (!(ieee->softmac_features & IEEE_SOFTMAC_SCAN)) { - if ((ieee->state >= RTLLIB_ASSOCIATING) && - (ieee->state <= RTLLIB_ASSOCIATING_AUTHENTICATED)) + if ((ieee->link_state >= RTLLIB_ASSOCIATING) && + (ieee->link_state <= RTLLIB_ASSOCIATING_AUTHENTICATED)) return 0; - if ((priv->rtllib->state == RTLLIB_LINKED) && + if ((priv->rtllib->link_state == MAC80211_LINKED) && (priv->rtllib->CntAfterLink < 2)) return 0; } @@ -393,7 +391,7 @@ static int _rtl92e_wx_set_scan(struct net_device *dev, rt_state = priv->rtllib->rf_power_state; if (!priv->up) return -ENETDOWN; - if (priv->rtllib->link_detect_info.bBusyTraffic == true) + if (priv->rtllib->link_detect_info.bBusyTraffic) return -EAGAIN; if (wrqu->data.flags & IW_SCAN_THIS_ESSID) { @@ -411,7 +409,7 @@ static int _rtl92e_wx_set_scan(struct net_device *dev, priv->rtllib->FirstIe_InScan = true; - if (priv->rtllib->state != RTLLIB_LINKED) { + if (priv->rtllib->link_state != MAC80211_LINKED) { if (rt_state == rf_off) { if (priv->rtllib->rf_off_reason > RF_CHANGE_BY_IPS) { @@ -425,10 +423,6 @@ static int _rtl92e_wx_set_scan(struct net_device *dev, mutex_unlock(&priv->rtllib->ips_mutex); } rtllib_stop_scan(priv->rtllib); - if (priv->rtllib->LedControlHandler) - priv->rtllib->LedControlHandler(dev, - LED_CTL_SITE_SURVEY); - if (priv->rtllib->rf_power_state != rf_off) { priv->rtllib->actscanning = true; @@ -574,9 +568,9 @@ static int _rtl92e_wx_set_frag(struct net_device *dev, if (priv->hw_radio_off) return 0; - if (wrqu->frag.disabled) + if (wrqu->frag.disabled) { priv->rtllib->fts = DEFAULT_FRAG_THRESHOLD; - else { + } else { if (wrqu->frag.value < MIN_FRAG_THRESHOLD || wrqu->frag.value > MAX_FRAG_THRESHOLD) return -EINVAL; @@ -807,45 +801,6 @@ static int _rtl92e_wx_get_retry(struct net_device *dev, return 0; } -static int _rtl92e_wx_get_sens(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct r8192_priv *priv = rtllib_priv(dev); - - if (priv->rf_set_sens == NULL) - return -1; /* we have not this support for this radio */ - wrqu->sens.value = priv->sens; - return 0; -} - -static int _rtl92e_wx_set_sens(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct r8192_priv *priv = rtllib_priv(dev); - - short err = 0; - - if (priv->hw_radio_off) - return 0; - - mutex_lock(&priv->wx_mutex); - if (priv->rf_set_sens == NULL) { - err = -1; /* we have not this support for this radio */ - goto exit; - } - if (priv->rf_set_sens(dev, wrqu->sens.value) == 0) - priv->sens = wrqu->sens.value; - else - err = -EINVAL; - -exit: - mutex_unlock(&priv->wx_mutex); - - return err; -} - static int _rtl92e_wx_set_encode_ext(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) @@ -1066,8 +1021,6 @@ static iw_handler r8192_wx_handlers[] = { [IW_IOCTL(SIOCGIWFREQ)] = _rtl92e_wx_get_freq, [IW_IOCTL(SIOCSIWMODE)] = _rtl92e_wx_set_mode, [IW_IOCTL(SIOCGIWMODE)] = _rtl92e_wx_get_mode, - [IW_IOCTL(SIOCSIWSENS)] = _rtl92e_wx_set_sens, - [IW_IOCTL(SIOCGIWSENS)] = _rtl92e_wx_get_sens, [IW_IOCTL(SIOCGIWRANGE)] = _rtl92e_wx_get_range, [IW_IOCTL(SIOCSIWAP)] = _rtl92e_wx_set_wap, [IW_IOCTL(SIOCGIWAP)] = _rtl92e_wx_get_wap, @@ -1171,7 +1124,7 @@ static struct iw_statistics *_rtl92e_get_wireless_stats(struct net_device *dev) int tmp_qual = 0; int tmp_noise = 0; - if (ieee->state < RTLLIB_LINKED) { + if (ieee->link_state < MAC80211_LINKED) { wstats->qual.qual = 10; wstats->qual.level = 0; wstats->qual.noise = 0x100 - 100; /* -100 dBm */ diff --git a/drivers/staging/rtl8192e/rtl819x_HT.h b/drivers/staging/rtl8192e/rtl819x_HT.h index f4e9fa849796052e9c6f27d89d5f5606e9a0e0c2..2bbd0104856134e1ea157d627ce51d881ac7105b 100644 --- a/drivers/staging/rtl8192e/rtl819x_HT.h +++ b/drivers/staging/rtl8192e/rtl819x_HT.h @@ -24,7 +24,6 @@ enum ht_extchnl_offset { }; struct ht_capab_ele { - u8 AdvCoding:1; u8 ChlWidth:1; u8 MimoPwrSave:2; @@ -46,7 +45,6 @@ struct ht_capab_ele { u8 MCS[16]; - u16 ExtHTCapInfo; u8 TxBFCap[4]; @@ -55,7 +53,6 @@ struct ht_capab_ele { } __packed; - struct ht_info_ele { u8 ControlChl; @@ -94,72 +91,54 @@ enum ht_aggre_mode { HT_AGG_FORCE_DISABLE = 2, }; - struct rt_hi_throughput { - u8 enable_ht; - u8 bCurrentHTSupport; - - u8 bRegBW40MHz; - u8 bCurBW40MHz; - - u8 bRegShortGI40MHz; - u8 bCurShortGI40MHz; - - u8 bRegShortGI20MHz; - u8 bCurShortGI20MHz; - - u8 bRegSuppCCK; - u8 bCurSuppCCK; - + u8 enable_ht; + u8 bCurrentHTSupport; + u8 bRegBW40MHz; + u8 bCurBW40MHz; + u8 bRegShortGI40MHz; + u8 bCurShortGI40MHz; + u8 bRegShortGI20MHz; + u8 bCurShortGI20MHz; + u8 bRegSuppCCK; + u8 bCurSuppCCK; enum ht_spec_ver ePeerHTSpecVer; - - struct ht_capab_ele SelfHTCap; struct ht_info_ele SelfHTInfo; - - u8 PeerHTCapBuf[32]; - u8 PeerHTInfoBuf[32]; - - - u8 bAMSDU_Support; - u16 nAMSDU_MaxSize; - u8 bCurrent_AMSDU_Support; - u16 nCurrent_AMSDU_MaxSize; - - u8 bAMPDUEnable; - u8 bCurrentAMPDUEnable; - u8 AMPDU_Factor; - u8 CurrentAMPDUFactor; - u8 MPDU_Density; + u8 PeerHTCapBuf[32]; + u8 PeerHTInfoBuf[32]; + u8 bAMSDU_Support; + u16 nAMSDU_MaxSize; + u8 bCurrent_AMSDU_Support; + u16 nCurrent_AMSDU_MaxSize; + u8 bAMPDUEnable; + u8 bCurrentAMPDUEnable; + u8 AMPDU_Factor; + u8 CurrentAMPDUFactor; + u8 MPDU_Density; u8 current_mpdu_density; - enum ht_aggre_mode ForcedAMPDUMode; u8 forced_ampdu_factor; u8 forced_mpdu_density; - enum ht_aggre_mode ForcedAMSDUMode; u8 forced_short_gi; - u8 current_op_mode; - u8 self_mimo_ps; u8 peer_mimo_ps; - enum ht_extchnl_offset CurSTAExtChnlOffset; u8 cur_tx_bw40mhz; u8 sw_bw_in_progress; u8 reg_rt2rt_aggregation; - u8 RT2RT_HT_Mode; + u8 RT2RT_HT_Mode; u8 current_rt2rt_aggregation; u8 current_rt2rt_long_slot_time; u8 sz_rt2rt_agg_buf[10]; - u8 reg_rx_reorder_enable; u8 cur_rx_reorder_enable; u8 rx_reorder_win_size; u8 rx_reorder_pending_time; u16 rx_reorder_drop_counter; - u8 IOTPeer; + u8 IOTPeer; u32 iot_action; u8 iot_ra_func; } __packed; diff --git a/drivers/staging/rtl8192e/rtl819x_HTProc.c b/drivers/staging/rtl8192e/rtl819x_HTProc.c index fe30a291e64c9dacd0f54ecee03b1e9e6e6080d6..f9fa3f2bb728cb25f65dff466f0e25177b07a89d 100644 --- a/drivers/staging/rtl8192e/rtl819x_HTProc.c +++ b/drivers/staging/rtl8192e/rtl819x_HTProc.c @@ -424,14 +424,12 @@ static u8 HT_PickMCSRate(struct rtllib_device *ieee, u8 *pOperateMCS) } switch (ieee->mode) { - case IEEE_A: - case IEEE_B: - case IEEE_G: + case WIRELESS_MODE_B: + case WIRELESS_MODE_G: for (i = 0; i <= 15; i++) pOperateMCS[i] = 0; break; - case IEEE_N_24G: - case IEEE_N_5G: + case WIRELESS_MODE_N_24G: pOperateMCS[0] &= RATE_ADPT_1SS_MASK; pOperateMCS[1] &= RATE_ADPT_2SS_MASK; pOperateMCS[3] &= RATE_ADPT_MCS32_MASK; @@ -835,11 +833,11 @@ static void HTSetConnectBwModeCallback(struct rtllib_device *ieee) ieee->set_chan(ieee->dev, ieee->current_network.channel); - ieee->SetBWModeHandler(ieee->dev, HT_CHANNEL_WIDTH_20_40, + ieee->set_bw_mode_handler(ieee->dev, HT_CHANNEL_WIDTH_20_40, ht_info->CurSTAExtChnlOffset); } else { ieee->set_chan(ieee->dev, ieee->current_network.channel); - ieee->SetBWModeHandler(ieee->dev, HT_CHANNEL_WIDTH_20, + ieee->set_bw_mode_handler(ieee->dev, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT); } diff --git a/drivers/staging/rtl8192e/rtl819x_Qos.h b/drivers/staging/rtl8192e/rtl819x_Qos.h index c010eb0d6036689912f64e5ab37493585bd15e5d..0499711ea2bf803ebdf07529dea25502ff850a7a 100644 --- a/drivers/staging/rtl8192e/rtl819x_Qos.h +++ b/drivers/staging/rtl8192e/rtl819x_Qos.h @@ -104,7 +104,6 @@ struct acm { }; union qos_tclas { - struct _TYPE_GENERAL { u8 Priority; u8 ClassifierType; diff --git a/drivers/staging/rtl8192e/rtl819x_TS.h b/drivers/staging/rtl8192e/rtl819x_TS.h index 4aa9b12a2dd56435ff8e7262cb8d1658eb0dc397..37760d0bc35d9c913836034c183a7fa31400369a 100644 --- a/drivers/staging/rtl8192e/rtl819x_TS.h +++ b/drivers/staging/rtl8192e/rtl819x_TS.h @@ -53,6 +53,4 @@ struct rx_ts_record { u8 num; }; - - #endif diff --git a/drivers/staging/rtl8192e/rtllib.h b/drivers/staging/rtl8192e/rtllib.h index 6e665e866f1f3148e40c7685678468102c0e579b..e3ce4431d460ff3ebbb0b60cfeede67822962005 100644 --- a/drivers/staging/rtl8192e/rtllib.h +++ b/drivers/staging/rtl8192e/rtllib.h @@ -38,6 +38,7 @@ #include #include /* ARPHRD_ETHER */ +#include #include #define MAX_PRECMD_CNT 16 @@ -139,7 +140,7 @@ struct cb_desc { u8 rata_index; u8 queue_index; u16 txbuf_size; - u8 RATRIndex; + u8 ratr_index; u8 bAMSDU:1; u8 bFromAggrQ:1; u8 reserved6:6; @@ -308,9 +309,7 @@ enum rt_op_mode { }; #define aSifsTime \ - (((priv->rtllib->current_network.mode == IEEE_A) \ - || (priv->rtllib->current_network.mode == IEEE_N_24G) \ - || (priv->rtllib->current_network.mode == IEEE_N_5G)) ? 16 : 10) + ((priv->rtllib->current_network.mode == WIRELESS_MODE_N_24G) ? 16 : 10) #define MGMT_QUEUE_NUM 5 @@ -421,17 +420,6 @@ enum init_gain_op_type { IG_Max }; -enum led_ctl_mode { - LED_CTL_POWER_ON = 1, - LED_CTL_LINK = 2, - LED_CTL_NO_LINK = 3, - LED_CTL_TX = 4, - LED_CTL_RX = 5, - LED_CTL_SITE_SURVEY = 6, - LED_CTL_POWER_OFF = 7, - LED_CTL_START_TO_LINK = 8, -}; - enum wireless_mode { WIRELESS_MODE_UNKNOWN = 0x00, WIRELESS_MODE_A = 0x01, @@ -439,7 +427,6 @@ enum wireless_mode { WIRELESS_MODE_G = 0x04, WIRELESS_MODE_AUTO = 0x08, WIRELESS_MODE_N_24G = 0x10, - WIRELESS_MODE_N_5G = 0x20 }; #ifndef ETH_P_PAE @@ -499,9 +486,6 @@ enum _REG_PREAMBLE_MODE { #define RTLLIB_CCK_MODULATION (1<<0) #define RTLLIB_OFDM_MODULATION (1<<1) -#define RTLLIB_24GHZ_BAND (1<<0) -#define RTLLIB_52GHZ_BAND (1<<1) - #define RTLLIB_CCK_RATE_LEN 4 #define RTLLIB_CCK_RATE_1MB 0x02 #define RTLLIB_CCK_RATE_2MB 0x04 @@ -548,10 +532,8 @@ struct rtllib_rx_stats { u8 signal; u8 noise; u16 rate; /* in 100 kbps */ - u8 received_channel; u8 control; u8 mask; - u8 freq; u16 len; u64 tsf; u32 beacon_time; @@ -1136,10 +1118,9 @@ struct rtllib_network { struct list_head list; }; -enum rtllib_state { - +enum rtl_link_state { /* the card is not linked at all */ - RTLLIB_NOLINK = 0, + MAC80211_NOLINK = 0, /* RTLLIB_ASSOCIATING* are for BSS client mode * the driver shall not perform RX filtering unless @@ -1164,14 +1145,14 @@ enum rtllib_state { /* the link is ok. the card associated to a BSS or linked * to a ibss cell or acting as an AP and creating the bss */ - RTLLIB_LINKED, + MAC80211_LINKED, /* same as LINKED, but the driver shall apply RX filter * rules as we are in NO_LINK mode. As the card is still * logically linked, but it is doing a syncro site survey * then it will be back to LINKED state. */ - RTLLIB_LINKED_SCANNING, + MAC80211_LINKED_SCANNING, }; #define DEFAULT_MAX_SCAN_AGE (15 * HZ) @@ -1298,7 +1279,6 @@ enum fw_cmd_io_type { #define RT_MAX_LD_SLOT_NUM 10 struct rt_link_detect { - u32 NumRecvBcnInPeriod; u32 NumRecvDataInPeriod; @@ -1316,7 +1296,6 @@ struct rt_link_detect { }; struct sw_cam_table { - u8 macaddr[ETH_ALEN]; bool bused; u8 key_buf[16]; @@ -1509,7 +1488,7 @@ struct rtllib_device { */ struct rtllib_network current_network; - enum rtllib_state state; + enum rtl_link_state link_state; int short_slot; int mode; /* A, B, G */ @@ -1651,17 +1630,6 @@ struct rtllib_device { }; /* Callback functions */ - void (*set_security)(struct net_device *dev, - struct rtllib_security *sec); - - /* Used to TX data frame by using txb structs. - * this is not used if in the softmac_features - * is set the flag IEEE_SOFTMAC_TX_QUEUE - */ - int (*hard_start_xmit)(struct rtllib_txb *txb, - struct net_device *dev); - - int (*reset_port)(struct net_device *dev); /* Softmac-generated frames (management) are TXed via this * callback if the flag IEEE_SOFTMAC_SINGLE_QUEUE is @@ -1682,24 +1650,12 @@ struct rtllib_device { void (*softmac_data_hard_start_xmit)(struct sk_buff *skb, struct net_device *dev, int rate); - /* stops the HW queue for DATA frames. Useful to avoid - * waste time to TX data frame when we are reassociating - * This function can sleep. - */ - void (*data_hard_stop)(struct net_device *dev); - - /* OK this is complementing to data_poll_hard_stop */ - void (*data_hard_resume)(struct net_device *dev); - /* ask to the driver to retune the radio. * This function can sleep. the driver should ensure * the radio has been switched before return. */ void (*set_chan)(struct net_device *dev, short ch); - void (*rtllib_start_hw_scan)(struct net_device *dev); - void (*rtllib_stop_hw_scan)(struct net_device *dev); - /* indicate the driver that the link state is changed * for example it may indicate the card is associated now. * Driver might be interested in this to apply RX filter @@ -1729,22 +1685,16 @@ struct rtllib_device { /* check whether Tx hw resource available */ short (*check_nic_enough_desc)(struct net_device *dev, int queue_index); - void (*SetBWModeHandler)(struct net_device *dev, - enum ht_channel_width bandwidth, - enum ht_extchnl_offset Offset); + void (*set_bw_mode_handler)(struct net_device *dev, + enum ht_channel_width bandwidth, + enum ht_extchnl_offset Offset); bool (*GetNmodeSupportBySecCfg)(struct net_device *dev); - void (*SetWirelessMode)(struct net_device *dev, u8 wireless_mode); + void (*set_wireless_mode)(struct net_device *dev, u8 wireless_mode); bool (*GetHalfNmodeSupportByAPsHandler)(struct net_device *dev); u8 (*rtllib_ap_sec_type)(struct rtllib_device *ieee); - void (*InitialGainHandler)(struct net_device *dev, u8 Operation); - bool (*SetFwCmdHandler)(struct net_device *dev, - enum fw_cmd_io_type FwCmdIO); - void (*UpdateBeaconInterruptHandler)(struct net_device *dev, - bool start); + void (*init_gain_handler)(struct net_device *dev, u8 Operation); void (*ScanOperationBackupHandler)(struct net_device *dev, u8 Operation); - void (*LedControlHandler)(struct net_device *dev, - enum led_ctl_mode LedAction); void (*SetHwRegHandler)(struct net_device *dev, u8 variable, u8 *val); void (*AllowAllDestAddrHandler)(struct net_device *dev, @@ -1752,7 +1702,7 @@ struct rtllib_device { void (*rtllib_ips_leave_wq)(struct net_device *dev); void (*rtllib_ips_leave)(struct net_device *dev); - void (*LeisurePSLeave)(struct net_device *dev); + void (*leisure_ps_leave)(struct net_device *dev); /* This must be the last item so that it points to the data * allocated beyond this structure by alloc_rtllib @@ -1760,12 +1710,7 @@ struct rtllib_device { u8 priv[]; }; -#define IEEE_A (1<<0) -#define IEEE_B (1<<1) -#define IEEE_G (1<<2) -#define IEEE_N_24G (1<<4) -#define IEEE_N_5G (1<<5) -#define IEEE_MODE_MASK (IEEE_A|IEEE_B|IEEE_G) +#define IEEE_MODE_MASK (WIRELESS_MODE_B | WIRELESS_MODE_G) /* Generate a 802.11 header */ @@ -2080,8 +2025,6 @@ void TsStartAddBaProcess(struct rtllib_device *ieee, void RemovePeerTS(struct rtllib_device *ieee, u8 *Addr); void RemoveAllTS(struct rtllib_device *ieee); -extern const long rtllib_wlan_frequencies[]; - static inline const char *escape_essid(const char *essid, u8 essid_len) { static char escaped[IW_ESSID_MAX_SIZE * 2 + 1]; diff --git a/drivers/staging/rtl8192e/rtllib_rx.c b/drivers/staging/rtl8192e/rtllib_rx.c index b649d02dc5c876aef529af0eaee28144a1c93da9..91dd3c373aefc548ec44600fb6133040b5162c0c 100644 --- a/drivers/staging/rtl8192e/rtllib_rx.c +++ b/drivers/staging/rtl8192e/rtllib_rx.c @@ -225,18 +225,6 @@ rtllib_rx_frame_mgmt(struct rtllib_device *ieee, struct sk_buff *skb, return 0; } -/* See IEEE 802.1H for LLC/SNAP encapsulation/decapsulation - * Ethernet-II snap header (RFC1042 for most EtherTypes) - */ -static unsigned char rfc1042_header[] = { - 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 -}; - -/* Bridge-Tunnel header (for EtherTypes ETH_P_AARP and ETH_P_IPX) */ -static unsigned char bridge_tunnel_header[] = { - 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 -}; - /* No encapsulation header if EtherType < 0x600 (=length) */ /* Called by rtllib_rx_frame_decrypt */ @@ -264,8 +252,9 @@ static int rtllib_is_eapol_frame(struct rtllib_device *ieee, RTLLIB_FCTL_FROMDS && memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN) == 0) { /* FromDS frame with own addr as DA */ - } else + } else { return 0; + } if (skb->len < 24 + 8) return 0; @@ -433,8 +422,9 @@ static int is_duplicate_packet(struct rtllib_device *ieee, if (*last_frag + 1 != frag) /* out-of-order fragment */ goto drop; - } else + } else { *last_seq = seq; + } *last_frag = frag; *last_time = jiffies; @@ -1206,11 +1196,11 @@ static void rtllib_rx_check_leave_lps(struct rtllib_device *ieee, u8 unicast, u8 nr_subframes) { if (unicast) { - if (ieee->state == RTLLIB_LINKED) { + if (ieee->link_state == MAC80211_LINKED) { if (((ieee->link_detect_info.NumRxUnicastOkInPeriod + ieee->link_detect_info.NumTxOkInPeriod) > 8) || (ieee->link_detect_info.NumRxUnicastOkInPeriod > 2)) { - ieee->LeisurePSLeave(ieee->dev); + ieee->leisure_ps_leave(ieee->dev); } } } @@ -2127,7 +2117,7 @@ int rtllib_parse_info_param(struct rtllib_device *ieee, network->tim.tim_period = info_element->data[1]; network->dtim_period = info_element->data[1]; - if (ieee->state != RTLLIB_LINKED) + if (ieee->link_state != MAC80211_LINKED) break; network->last_dtim_sta_time = jiffies; @@ -2311,11 +2301,7 @@ static inline int rtllib_network_init( network->CountryIeLen = 0; memset(network->CountryIeBuf, 0, MAX_IE_LEN); HTInitializeBssDesc(&network->bssht); - if (stats->freq == RTLLIB_52GHZ_BAND) { - /* for A band (No DS info) */ - network->channel = stats->received_channel; - } else - network->flags |= NETWORK_HAS_CCK; + network->flags |= NETWORK_HAS_CCK; network->wpa_ie_len = 0; network->rsn_ie_len = 0; @@ -2329,14 +2315,11 @@ static inline int rtllib_network_init( return 1; network->mode = 0; - if (stats->freq == RTLLIB_52GHZ_BAND) - network->mode = IEEE_A; - else { - if (network->flags & NETWORK_HAS_OFDM) - network->mode |= IEEE_G; - if (network->flags & NETWORK_HAS_CCK) - network->mode |= IEEE_B; - } + + if (network->flags & NETWORK_HAS_OFDM) + network->mode |= WIRELESS_MODE_G; + if (network->flags & NETWORK_HAS_CCK) + network->mode |= WIRELESS_MODE_B; if (network->mode == 0) { netdev_dbg(ieee->dev, "Filtered out '%s (%pM)' network.\n", @@ -2346,10 +2329,8 @@ static inline int rtllib_network_init( } if (network->bssht.bd_support_ht) { - if (network->mode == IEEE_A) - network->mode = IEEE_N_5G; - else if (network->mode & (IEEE_G | IEEE_B)) - network->mode = IEEE_N_24G; + if (network->mode & (WIRELESS_MODE_G | WIRELESS_MODE_B)) + network->mode = WIRELESS_MODE_N_24G; } if (rtllib_is_empty_essid(network->ssid, network->ssid_len)) network->flags |= NETWORK_EMPTY_ESSID; @@ -2595,8 +2576,8 @@ static inline void rtllib_process_probe_response( if (is_same_network(&ieee->current_network, network, (network->ssid_len ? 1 : 0))) { update_network(ieee, &ieee->current_network, network); - if ((ieee->current_network.mode == IEEE_N_24G || - ieee->current_network.mode == IEEE_G) && + if ((ieee->current_network.mode == WIRELESS_MODE_N_24G || + ieee->current_network.mode == WIRELESS_MODE_G) && ieee->current_network.berp_info_valid) { if (ieee->current_network.erp_value & ERP_UseProtection) ieee->current_network.buseprotection = true; @@ -2604,7 +2585,7 @@ static inline void rtllib_process_probe_response( ieee->current_network.buseprotection = false; } if (is_beacon(frame_ctl)) { - if (ieee->state >= RTLLIB_LINKED) + if (ieee->link_state >= MAC80211_LINKED) ieee->link_detect_info.NumRecvBcnInPeriod++; } } @@ -2662,7 +2643,7 @@ static inline void rtllib_process_probe_response( || ((ieee->current_network.ssid_len == network->ssid_len) && (strncmp(ieee->current_network.ssid, network->ssid, network->ssid_len) == 0) && - (ieee->state == RTLLIB_NOLINK)))) + (ieee->link_state == MAC80211_NOLINK)))) renew = 1; update_network(ieee, target, network); if (renew && (ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE)) @@ -2673,7 +2654,7 @@ static inline void rtllib_process_probe_response( if (is_beacon(frame_ctl) && is_same_network(&ieee->current_network, network, (network->ssid_len ? 1 : 0)) && - (ieee->state == RTLLIB_LINKED)) { + (ieee->link_state == MAC80211_LINKED)) { ieee->handle_beacon(ieee->dev, beacon, &ieee->current_network); } free_network: @@ -2702,7 +2683,7 @@ static void rtllib_rx_mgt(struct rtllib_device *ieee, if (ieee->sta_sleep || (ieee->ps != RTLLIB_PS_DISABLED && ieee->iw_mode == IW_MODE_INFRA && - ieee->state == RTLLIB_LINKED)) + ieee->link_state == MAC80211_LINKED)) schedule_work(&ieee->ps_task); break; @@ -2719,7 +2700,7 @@ static void rtllib_rx_mgt(struct rtllib_device *ieee, if ((ieee->softmac_features & IEEE_SOFTMAC_PROBERS) && ((ieee->iw_mode == IW_MODE_ADHOC || ieee->iw_mode == IW_MODE_MASTER) && - ieee->state == RTLLIB_LINKED)) + ieee->link_state == MAC80211_LINKED)) rtllib_rx_probe_rq(ieee, skb); break; } diff --git a/drivers/staging/rtl8192e/rtllib_softmac.c b/drivers/staging/rtl8192e/rtllib_softmac.c index b9886e83a6dc928d242f25f6631c86569e9a68fa..425d4acbcdf047ad0ddd0fb5cabe1e8de29cf962 100644 --- a/drivers/staging/rtl8192e/rtllib_softmac.c +++ b/drivers/staging/rtl8192e/rtllib_softmac.c @@ -22,7 +22,6 @@ static void rtllib_sta_wakeup(struct rtllib_device *ieee, short nl); - static short rtllib_is_54g(struct rtllib_network *net) { return (net->rates_ex_len > 0) || (net->rates_len > 4); @@ -139,7 +138,6 @@ static void enqueue_mgmt(struct rtllib_device *ieee, struct sk_buff *skb) */ ieee->mgmt_queue_head = nh; ieee->mgmt_queue_ring[nh] = skb; - } static void init_mgmt_queue(struct rtllib_device *ieee) @@ -147,16 +145,14 @@ static void init_mgmt_queue(struct rtllib_device *ieee) ieee->mgmt_queue_tail = ieee->mgmt_queue_head = 0; } - u8 MgntQuery_TxRateExcludeCCKRates(struct rtllib_device *ieee) { u16 i; u8 QueryRate = 0; u8 BasicRate; - for (i = 0; i < ieee->current_network.rates_len; i++) { - BasicRate = ieee->current_network.rates[i]&0x7F; + BasicRate = ieee->current_network.rates[i] & 0x7F; if (!rtllib_is_cck_rate(BasicRate)) { if (QueryRate == 0) { QueryRate = BasicRate; @@ -185,9 +181,7 @@ static u8 MgntQuery_MgntFrameTxRate(struct rtllib_device *ieee) rate = ieee->basic_rate & 0x7f; if (rate == 0) { - if (ieee->mode == IEEE_A || - ieee->mode == IEEE_N_5G || - (ieee->mode == IEEE_N_24G && !ht_info->bCurSuppCCK)) + if (ieee->mode == WIRELESS_MODE_N_24G && !ht_info->bCurSuppCCK) rate = 0x0c; else rate = 0x02; @@ -219,14 +213,14 @@ inline void softmac_mgmt_xmit(struct sk_buff *skb, struct rtllib_device *ieee) tcb_desc->queue_index = HIGH_QUEUE; tcb_desc->data_rate = MgntQuery_MgntFrameTxRate(ieee); - tcb_desc->RATRIndex = 7; + tcb_desc->ratr_index = 7; tcb_desc->tx_dis_rate_fallback = 1; tcb_desc->tx_use_drv_assinged_rate = 1; if (single) { if (ieee->queue_stop) { enqueue_mgmt(ieee, skb); } else { - header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0]<<4); + header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4); if (ieee->seq_ctrl[0] == 0xFFF) ieee->seq_ctrl[0] = 0; @@ -286,7 +280,6 @@ softmac_ps_mgmt_xmit(struct sk_buff *skb, type = WLAN_FC_GET_TYPE(fc); stype = WLAN_FC_GET_STYPE(fc); - if (stype != RTLLIB_STYPE_PSPOLL) tcb_desc->queue_index = MGNT_QUEUE; else @@ -295,9 +288,8 @@ softmac_ps_mgmt_xmit(struct sk_buff *skb, if (ieee->disable_mgnt_queue) tcb_desc->queue_index = HIGH_QUEUE; - tcb_desc->data_rate = MgntQuery_MgntFrameTxRate(ieee); - tcb_desc->RATRIndex = 7; + tcb_desc->ratr_index = 7; tcb_desc->tx_dis_rate_fallback = 1; tcb_desc->tx_use_drv_assinged_rate = 1; if (single) { @@ -308,7 +300,6 @@ softmac_ps_mgmt_xmit(struct sk_buff *skb, ieee->seq_ctrl[0] = 0; else ieee->seq_ctrl[0]++; - } /* avoid watchdog triggers */ ieee->softmac_data_hard_start_xmit(skb, ieee->dev, @@ -324,7 +315,6 @@ softmac_ps_mgmt_xmit(struct sk_buff *skb, ieee->seq_ctrl[0]++; } ieee->softmac_hard_start_xmit(skb, ieee->dev); - } } @@ -388,7 +378,6 @@ static void rtllib_send_beacon(struct rtllib_device *ieee) (msecs_to_jiffies(ieee->current_network.beacon_interval - 5))); } - static void rtllib_send_beacon_cb(struct timer_list *t) { struct rtllib_device *ieee = @@ -411,7 +400,6 @@ void rtllib_EnableNetMonitorMode(struct net_device *dev, ieee->AllowAllDestAddrHandler(dev, true, !bInitState); } - /* Disables network monitor mode. Only packets destinated to * us will be received. */ @@ -425,7 +413,6 @@ void rtllib_DisableNetMonitorMode(struct net_device *dev, ieee->AllowAllDestAddrHandler(dev, false, !bInitState); } - /* Enables the specialized promiscuous mode required by Intel. * In this mode, Intel intends to hear traffics from/to other STAs in the * same BSS. Therefore we don't have to disable checking BSSID and we only need @@ -449,7 +436,6 @@ void rtllib_EnableIntelPromiscuousMode(struct net_device *dev, } EXPORT_SYMBOL(rtllib_EnableIntelPromiscuousMode); - /* Disables the specialized promiscuous mode required by Intel. * See MgntEnableIntelPromiscuousMode for detail. */ @@ -481,7 +467,6 @@ static void rtllib_send_probe(struct rtllib_device *ieee, u8 is_mesh) } } - static void rtllib_send_probe_requests(struct rtllib_device *ieee, u8 is_mesh) { if (ieee->active_scan && (ieee->softmac_features & @@ -494,7 +479,7 @@ static void rtllib_send_probe_requests(struct rtllib_device *ieee, u8 is_mesh) static void rtllib_update_active_chan_map(struct rtllib_device *ieee) { memcpy(ieee->active_channel_map, GET_DOT11D_INFO(ieee)->channel_map, - MAX_CHANNEL_NUMBER+1); + MAX_CHANNEL_NUMBER + 1); } /* this performs syncro scan blocking the caller until all channels @@ -523,12 +508,12 @@ static void rtllib_softmac_scan_syncro(struct rtllib_device *ieee, u8 is_mesh) * performing a complete syncro scan before conclude * there are no interesting cell and to create a * new one. In this case the link state is - * RTLLIB_NOLINK until we found an interesting cell. + * MAC80211_NOLINK until we found an interesting cell. * If so the ieee8021_new_net, called by the RX path - * will set the state to RTLLIB_LINKED, so we stop + * will set the state to MAC80211_LINKED, so we stop * scanning * 2- We are linked and the root uses run iwlist scan. - * So we switch to RTLLIB_LINKED_SCANNING to remember + * So we switch to MAC80211_LINKED_SCANNING to remember * that we are still logically linked (not interested in * new network events, despite for updating the net list, * but we are temporarly 'unlinked' as the driver shall @@ -537,7 +522,7 @@ static void rtllib_softmac_scan_syncro(struct rtllib_device *ieee, u8 is_mesh) * if the state become LINKED because of the #1 situation */ - if (ieee->state == RTLLIB_LINKED) + if (ieee->link_state == MAC80211_LINKED) goto out; if (ieee->sync_scan_hurryup) { netdev_info(ieee->dev, @@ -558,7 +543,7 @@ static void rtllib_softmac_scan_syncro(struct rtllib_device *ieee, u8 is_mesh) ieee->actscanning = false; ieee->sync_scan_hurryup = 0; - if (ieee->state >= RTLLIB_LINKED) { + if (ieee->link_state >= MAC80211_LINKED) { if (IS_DOT11D_ENABLE(ieee)) dot11d_scan_complete(ieee); } @@ -629,8 +614,6 @@ static void rtllib_softmac_scan_wq(void *data) mutex_unlock(&ieee->scan_mutex); } - - static void rtllib_beacons_start(struct rtllib_device *ieee) { unsigned long flags; @@ -653,10 +636,8 @@ static void rtllib_beacons_stop(struct rtllib_device *ieee) spin_unlock_irqrestore(&ieee->beacon_lock, flags); del_timer_sync(&ieee->beacon_timer); - } - void rtllib_stop_send_beacons(struct rtllib_device *ieee) { ieee->stop_send_beacons(ieee->dev); @@ -665,7 +646,6 @@ void rtllib_stop_send_beacons(struct rtllib_device *ieee) } EXPORT_SYMBOL(rtllib_stop_send_beacons); - void rtllib_start_send_beacons(struct rtllib_device *ieee) { ieee->start_send_beacons(ieee->dev); @@ -674,7 +654,6 @@ void rtllib_start_send_beacons(struct rtllib_device *ieee) } EXPORT_SYMBOL(rtllib_start_send_beacons); - static void rtllib_softmac_stop_scan(struct rtllib_device *ieee) { mutex_lock(&ieee->scan_mutex); @@ -682,32 +661,24 @@ static void rtllib_softmac_stop_scan(struct rtllib_device *ieee) if (ieee->scanning_continue == 1) { ieee->scanning_continue = 0; ieee->actscanning = false; - + mutex_unlock(&ieee->scan_mutex); cancel_delayed_work_sync(&ieee->softmac_scan_wq); + } else { + mutex_unlock(&ieee->scan_mutex); } - - mutex_unlock(&ieee->scan_mutex); } void rtllib_stop_scan(struct rtllib_device *ieee) { - if (ieee->softmac_features & IEEE_SOFTMAC_SCAN) { + if (ieee->softmac_features & IEEE_SOFTMAC_SCAN) rtllib_softmac_stop_scan(ieee); - } else { - if (ieee->rtllib_stop_hw_scan) - ieee->rtllib_stop_hw_scan(ieee->dev); - } } EXPORT_SYMBOL(rtllib_stop_scan); void rtllib_stop_scan_syncro(struct rtllib_device *ieee) { - if (ieee->softmac_features & IEEE_SOFTMAC_SCAN) { + if (ieee->softmac_features & IEEE_SOFTMAC_SCAN) ieee->sync_scan_hurryup = 1; - } else { - if (ieee->rtllib_stop_hw_scan) - ieee->rtllib_stop_hw_scan(ieee->dev); - } } EXPORT_SYMBOL(rtllib_stop_scan_syncro); @@ -739,9 +710,6 @@ static void rtllib_start_scan(struct rtllib_device *ieee) ieee->scanning_continue = 1; schedule_delayed_work(&ieee->softmac_scan_wq, 0); } - } else { - if (ieee->rtllib_start_hw_scan) - ieee->rtllib_start_hw_scan(ieee->dev); } } @@ -753,12 +721,8 @@ void rtllib_start_scan_syncro(struct rtllib_device *ieee, u8 is_mesh) RESET_CIE_WATCHDOG(ieee); } ieee->sync_scan_hurryup = 0; - if (ieee->softmac_features & IEEE_SOFTMAC_SCAN) { + if (ieee->softmac_features & IEEE_SOFTMAC_SCAN) rtllib_softmac_scan_syncro(ieee, is_mesh); - } else { - if (ieee->rtllib_start_hw_scan) - ieee->rtllib_start_hw_scan(ieee->dev); - } } EXPORT_SYMBOL(rtllib_start_scan_syncro); @@ -817,7 +781,7 @@ static struct sk_buff *rtllib_probe_resp(struct rtllib_device *ieee, char *ssid = ieee->current_network.ssid; int ssid_len = ieee->current_network.ssid_len; - int rate_len = ieee->current_network.rates_len+2; + int rate_len = ieee->current_network.rates_len + 2; int rate_ex_len = ieee->current_network.rates_ex_len; int wpa_ie_len = ieee->wpa_ie_len; u8 erpinfo_content = 0; @@ -838,15 +802,16 @@ static struct sk_buff *rtllib_probe_resp(struct rtllib_device *ieee, else atim_len = 0; - if ((ieee->current_network.mode == IEEE_G) || - (ieee->current_network.mode == IEEE_N_24G && + if ((ieee->current_network.mode == WIRELESS_MODE_G) || + (ieee->current_network.mode == WIRELESS_MODE_N_24G && ieee->ht_info->bCurSuppCCK)) { erp_len = 3; erpinfo_content = 0; if (ieee->current_network.buseprotection) erpinfo_content |= ERP_UseProtection; - } else + } else { erp_len = 0; + } crypt = ieee->crypt_info.crypt[ieee->crypt_info.tx_keyidx]; encrypt = ieee->host_encrypt && crypt && crypt->ops && @@ -870,7 +835,7 @@ static struct sk_buff *rtllib_probe_resp(struct rtllib_device *ieee, } } - beacon_size = sizeof(struct rtllib_probe_response)+2+ + beacon_size = sizeof(struct rtllib_probe_response) + 2 + ssid_len + 3 + rate_len + rate_ex_len + atim_len + erp_len + wpa_ie_len + ieee->tx_headroom; skb = dev_alloc_skb(beacon_size); @@ -903,7 +868,6 @@ static struct sk_buff *rtllib_probe_resp(struct rtllib_device *ieee, if (encrypt) beacon_buf->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY); - beacon_buf->header.frame_ctl = cpu_to_le16(RTLLIB_STYPE_PROBE_RESP); beacon_buf->info_element[0].id = MFIE_TYPE_SSID; beacon_buf->info_element[0].len = ssid_len; @@ -915,9 +879,9 @@ static struct sk_buff *rtllib_probe_resp(struct rtllib_device *ieee, tag += ssid_len; *(tag++) = MFIE_TYPE_RATES; - *(tag++) = rate_len-2; - memcpy(tag, ieee->current_network.rates, rate_len-2); - tag += rate_len-2; + *(tag++) = rate_len - 2; + memcpy(tag, ieee->current_network.rates, rate_len - 2); + tag += rate_len - 2; *(tag++) = MFIE_TYPE_DS_SET; *(tag++) = 1; @@ -939,9 +903,9 @@ static struct sk_buff *rtllib_probe_resp(struct rtllib_device *ieee, } if (rate_ex_len) { *(tag++) = MFIE_TYPE_RATES_EX; - *(tag++) = rate_ex_len-2; - memcpy(tag, ieee->current_network.rates_ex, rate_ex_len-2); - tag += rate_ex_len-2; + *(tag++) = rate_ex_len - 2; + memcpy(tag, ieee->current_network.rates_ex, rate_ex_len - 2); + tag += rate_ex_len - 2; } if (wpa_ie_len) { @@ -982,7 +946,6 @@ static struct sk_buff *rtllib_assoc_resp(struct rtllib_device *ieee, u8 *dest) assoc->capability = cpu_to_le16(ieee->iw_mode == IW_MODE_MASTER ? WLAN_CAPABILITY_ESS : WLAN_CAPABILITY_IBSS); - if (ieee->short_slot) assoc->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT_TIME); @@ -1037,8 +1000,6 @@ static struct sk_buff *rtllib_auth_resp(struct rtllib_device *ieee, int status, ether_addr_copy(auth->header.addr1, dest); auth->header.frame_ctl = cpu_to_le16(RTLLIB_STYPE_AUTH); return skb; - - } static struct sk_buff *rtllib_null_func(struct rtllib_device *ieee, short pwr) @@ -1046,7 +1007,7 @@ static struct sk_buff *rtllib_null_func(struct rtllib_device *ieee, short pwr) struct sk_buff *skb; struct rtllib_hdr_3addr *hdr; - skb = dev_alloc_skb(sizeof(struct rtllib_hdr_3addr)+ieee->tx_headroom); + skb = dev_alloc_skb(sizeof(struct rtllib_hdr_3addr) + ieee->tx_headroom); if (!skb) return NULL; @@ -1063,8 +1024,6 @@ static struct sk_buff *rtllib_null_func(struct rtllib_device *ieee, short pwr) (pwr ? RTLLIB_FCTL_PM : 0)); return skb; - - } static struct sk_buff *rtllib_pspoll_func(struct rtllib_device *ieee) @@ -1072,7 +1031,7 @@ static struct sk_buff *rtllib_pspoll_func(struct rtllib_device *ieee) struct sk_buff *skb; struct rtllib_pspoll_hdr *hdr; - skb = dev_alloc_skb(sizeof(struct rtllib_pspoll_hdr)+ieee->tx_headroom); + skb = dev_alloc_skb(sizeof(struct rtllib_pspoll_hdr) + ieee->tx_headroom); if (!skb) return NULL; @@ -1088,7 +1047,6 @@ static struct sk_buff *rtllib_pspoll_func(struct rtllib_device *ieee) RTLLIB_FCTL_PM); return skb; - } static void rtllib_resp_to_assoc_rq(struct rtllib_device *ieee, u8 *dest) @@ -1099,7 +1057,6 @@ static void rtllib_resp_to_assoc_rq(struct rtllib_device *ieee, u8 *dest) softmac_mgmt_xmit(buf, ieee); } - static void rtllib_resp_to_auth(struct rtllib_device *ieee, int s, u8 *dest) { struct sk_buff *buf = rtllib_auth_resp(ieee, s, dest); @@ -1108,7 +1065,6 @@ static void rtllib_resp_to_auth(struct rtllib_device *ieee, int s, u8 *dest) softmac_mgmt_xmit(buf, ieee); } - static void rtllib_resp_to_probe(struct rtllib_device *ieee, u8 *dest) { struct sk_buff *buf = rtllib_probe_resp(ieee, dest); @@ -1117,7 +1073,6 @@ static void rtllib_resp_to_probe(struct rtllib_device *ieee, u8 *dest) softmac_mgmt_xmit(buf, ieee); } - static inline int SecIsInPMKIDList(struct rtllib_device *ieee, u8 *bssid) { int i = 0; @@ -1195,11 +1150,11 @@ rtllib_association_req(struct rtllib_network *beacon, } if (beacon->bCkipSupported) - ckip_ie_len = 30+2; + ckip_ie_len = 30 + 2; if (beacon->bCcxRmEnable) - ccxrm_ie_len = 6+2; + ccxrm_ie_len = 6 + 2; if (beacon->BssCcxVerNumber >= 2) - cxvernum_ie_len = 5+2; + cxvernum_ie_len = 5 + 2; PMKCacheIdx = SecIsInPMKIDList(ieee, ieee->current_network.bssid); if (PMKCacheIdx >= 0) { @@ -1230,7 +1185,6 @@ rtllib_association_req(struct rtllib_network *beacon, hdr = skb_put(skb, sizeof(struct rtllib_assoc_request_frame) + 2); - hdr->header.frame_ctl = cpu_to_le16(RTLLIB_STYPE_ASSOC_REQ); hdr->header.duration_id = cpu_to_le16(37); ether_addr_copy(hdr->header.addr1, beacon->bssid); @@ -1247,10 +1201,9 @@ rtllib_association_req(struct rtllib_network *beacon, hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_PREAMBLE); if (ieee->short_slot && - (beacon->capability&WLAN_CAPABILITY_SHORT_SLOT_TIME)) + (beacon->capability & WLAN_CAPABILITY_SHORT_SLOT_TIME)) hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT_TIME); - hdr->listen_interval = cpu_to_le16(beacon->listen_interval); hdr->info_element[0].id = MFIE_TYPE_SSID; @@ -1286,7 +1239,7 @@ rtllib_association_req(struct rtllib_network *beacon, sizeof(AironetIeOui)); osCcxAironetIE.Octet[IE_CISCO_FLAG_POSITION] |= - (SUPPORT_CKIP_PK|SUPPORT_CKIP_MIC); + (SUPPORT_CKIP_PK | SUPPORT_CKIP_MIC); tag = skb_put(skb, ckip_ie_len); *tag++ = MFIE_TYPE_AIRONET; *tag++ = osCcxAironetIE.Length; @@ -1397,7 +1350,7 @@ static void rtllib_associate_abort(struct rtllib_device *ieee) * Here we will check if there are good nets to associate * with, so we retry or just get back to NO_LINK and scanning */ - if (ieee->state == RTLLIB_ASSOCIATING_AUTHENTICATING) { + if (ieee->link_state == RTLLIB_ASSOCIATING_AUTHENTICATING) { netdev_dbg(ieee->dev, "Authentication failed\n"); ieee->softmac_stats.no_auth_rs++; } else { @@ -1405,7 +1358,7 @@ static void rtllib_associate_abort(struct rtllib_device *ieee) ieee->softmac_stats.no_ass_rs++; } - ieee->state = RTLLIB_ASSOCIATING_RETRY; + ieee->link_state = RTLLIB_ASSOCIATING_RETRY; schedule_delayed_work(&ieee->associate_retry_wq, RTLLIB_SOFTMAC_ASSOC_RETRY_TIME); @@ -1431,10 +1384,10 @@ static void rtllib_associate_step1(struct rtllib_device *ieee, u8 *daddr) skb = rtllib_authentication_req(beacon, ieee, 0, daddr); - if (!skb) + if (!skb) { rtllib_associate_abort(ieee); - else { - ieee->state = RTLLIB_ASSOCIATING_AUTHENTICATING; + } else { + ieee->link_state = RTLLIB_ASSOCIATING_AUTHENTICATING; netdev_dbg(ieee->dev, "Sending authentication request\n"); softmac_mgmt_xmit(skb, ieee); if (!timer_pending(&ieee->associate_timer)) { @@ -1456,10 +1409,10 @@ static void rtllib_auth_challenge(struct rtllib_device *ieee, u8 *challenge, skb = rtllib_authentication_req(beacon, ieee, chlen + 2, beacon->bssid); - if (!skb) + if (!skb) { rtllib_associate_abort(ieee); - else { - c = skb_put(skb, chlen+2); + } else { + c = skb_put(skb, chlen + 2); *(c++) = MFIE_TYPE_CHALLENGE; *(c++) = chlen; memcpy(c, challenge, chlen); @@ -1471,7 +1424,7 @@ static void rtllib_auth_challenge(struct rtllib_device *ieee, u8 *challenge, sizeof(struct rtllib_hdr_3addr)); softmac_mgmt_xmit(skb, ieee); - mod_timer(&ieee->associate_timer, jiffies + (HZ/2)); + mod_timer(&ieee->associate_timer, jiffies + (HZ / 2)); } kfree(challenge); } @@ -1487,11 +1440,11 @@ static void rtllib_associate_step2(struct rtllib_device *ieee) ieee->softmac_stats.tx_ass_rq++; skb = rtllib_association_req(beacon, ieee); - if (!skb) + if (!skb) { rtllib_associate_abort(ieee); - else { + } else { softmac_mgmt_xmit(skb, ieee); - mod_timer(&ieee->associate_timer, jiffies + (HZ/2)); + mod_timer(&ieee->associate_timer, jiffies + (HZ / 2)); } } @@ -1518,7 +1471,7 @@ static void rtllib_associate_complete_wq(void *data) netdev_info(ieee->dev, "Using G rates:%d\n", ieee->rate); } else { ieee->rate = 22; - ieee->SetWirelessMode(ieee->dev, IEEE_B); + ieee->set_wireless_mode(ieee->dev, WIRELESS_MODE_B); netdev_info(ieee->dev, "Using B rates:%d\n", ieee->rate); } if (ieee->ht_info->bCurrentHTSupport && ieee->ht_info->enable_ht) { @@ -1546,10 +1499,6 @@ static void rtllib_associate_complete_wq(void *data) netdev_info(ieee->dev, "silent reset associate\n"); ieee->is_silent_reset = false; } - - if (ieee->data_hard_resume) - ieee->data_hard_resume(ieee->dev); - } static void rtllib_sta_send_associnfo(struct rtllib_device *ieee) @@ -1560,7 +1509,7 @@ static void rtllib_associate_complete(struct rtllib_device *ieee) { del_timer_sync(&ieee->associate_timer); - ieee->state = RTLLIB_LINKED; + ieee->link_state = MAC80211_LINKED; rtllib_sta_send_associnfo(ieee); schedule_work(&ieee->associate_complete_wq); @@ -1575,9 +1524,6 @@ static void rtllib_associate_procedure_wq(void *data) ieee->rtllib_ips_leave(ieee->dev); mutex_lock(&ieee->wx_mutex); - if (ieee->data_hard_stop) - ieee->data_hard_stop(ieee->dev); - rtllib_stop_scan(ieee); HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT); if (ieee->rf_power_state == rf_off) { @@ -1603,7 +1549,7 @@ inline void rtllib_softmac_new_net(struct rtllib_device *ieee, /* we are interested in new only if we are not associated * and we are not associating / authenticating */ - if (ieee->state != RTLLIB_NOLINK) + if (ieee->link_state != MAC80211_NOLINK) return; if ((ieee->iw_mode == IW_MODE_INFRA) && !(net->capability & @@ -1638,11 +1584,12 @@ inline void rtllib_softmac_new_net(struct rtllib_device *ieee, net->ssid_len = net->hidden_ssid_len; ssidbroad = 1; } - } else + } else { ssidmatch = (ieee->current_network.ssid_len == net->ssid_len) && (!strncmp(ieee->current_network.ssid, net->ssid, net->ssid_len)); + } /* if the user set the AP check if match. * if the network does not broadcast essid we check the @@ -1701,10 +1648,7 @@ inline void rtllib_softmac_new_net(struct rtllib_device *ieee, ieee->ht_info->bCurrentHTSupport = false; - ieee->state = RTLLIB_ASSOCIATING; - if (ieee->LedControlHandler != NULL) - ieee->LedControlHandler(ieee->dev, - LED_CTL_START_TO_LINK); + ieee->link_state = RTLLIB_ASSOCIATING; schedule_delayed_work( &ieee->associate_procedure_wq, 0); } else { @@ -1712,19 +1656,17 @@ inline void rtllib_softmac_new_net(struct rtllib_device *ieee, (ieee->modulation & RTLLIB_OFDM_MODULATION)) { ieee->rate = 108; - ieee->SetWirelessMode(ieee->dev, - IEEE_G); + ieee->set_wireless_mode(ieee->dev, WIRELESS_MODE_G); netdev_info(ieee->dev, "Using G rates\n"); } else { ieee->rate = 22; - ieee->SetWirelessMode(ieee->dev, - IEEE_B); + ieee->set_wireless_mode(ieee->dev, WIRELESS_MODE_B); netdev_info(ieee->dev, "Using B rates\n"); } memset(ieee->dot11ht_oper_rate_set, 0, 16); - ieee->state = RTLLIB_LINKED; + ieee->link_state = MAC80211_LINKED; } } } @@ -1738,12 +1680,11 @@ static void rtllib_softmac_check_all_nets(struct rtllib_device *ieee) spin_lock_irqsave(&ieee->lock, flags); list_for_each_entry(target, &ieee->network_list, list) { - /* if the state become different that NOLINK means * we had found what we are searching for */ - if (ieee->state != RTLLIB_NOLINK) + if (ieee->link_state != MAC80211_NOLINK) break; if (ieee->scan_age == 0 || time_after(target->last_scanned + @@ -1885,9 +1826,9 @@ static inline u16 assoc_parse(struct rtllib_device *ieee, struct sk_buff *skb, status_code = le16_to_cpu(response_head->status); if ((status_code == WLAN_STATUS_ASSOC_DENIED_RATES || status_code == WLAN_STATUS_CAPS_UNSUPPORTED) && - ((ieee->mode == IEEE_G) && - (ieee->current_network.mode == IEEE_N_24G) && - (ieee->AsocRetryCount++ < (RT_ASOC_RETRY_LIMIT-1)))) { + ((ieee->mode == WIRELESS_MODE_G) && + (ieee->current_network.mode == WIRELESS_MODE_N_24G) && + (ieee->AsocRetryCount++ < (RT_ASOC_RETRY_LIMIT - 1)))) { ieee->ht_info->iot_action |= HT_IOT_ACT_PURE_N_MODE; } else { ieee->AsocRetryCount = 0; @@ -1925,7 +1866,6 @@ static inline void rtllib_rx_assoc_rq(struct rtllib_device *ieee, { u8 dest[ETH_ALEN]; - ieee->softmac_stats.rx_ass_rq++; if (assoc_rq_parse(ieee->dev, skb, dest) != -1) rtllib_resp_to_assoc_rq(ieee, dest); @@ -1935,7 +1875,6 @@ static inline void rtllib_rx_assoc_rq(struct rtllib_device *ieee, void rtllib_sta_ps_send_null_frame(struct rtllib_device *ieee, short pwr) { - struct sk_buff *buf = rtllib_null_func(ieee, pwr); if (buf) @@ -2011,7 +1950,7 @@ static short rtllib_sta_ps_sleep(struct rtllib_device *ieee, u64 *time) LPSAwakeIntvl_tmp = period + (psc->LPSAwakeIntvl - period) - - ((psc->LPSAwakeIntvl-period) % + ((psc->LPSAwakeIntvl - period) % period); else LPSAwakeIntvl_tmp = psc->LPSAwakeIntvl; @@ -2021,7 +1960,7 @@ static short rtllib_sta_ps_sleep(struct rtllib_device *ieee, u64 *time) ieee->current_network.tim.tim_count) LPSAwakeIntvl_tmp = count + (psc->LPSAwakeIntvl - count) - - ((psc->LPSAwakeIntvl-count)%period); + ((psc->LPSAwakeIntvl - count) % period); else LPSAwakeIntvl_tmp = psc->LPSAwakeIntvl; } @@ -2033,8 +1972,6 @@ static short rtllib_sta_ps_sleep(struct rtllib_device *ieee, u64 *time) } return 1; - - } static inline void rtllib_sta_ps(struct work_struct *work) @@ -2050,7 +1987,7 @@ static inline void rtllib_sta_ps(struct work_struct *work) if ((ieee->ps == RTLLIB_PS_DISABLED || ieee->iw_mode != IW_MODE_INFRA || - ieee->state != RTLLIB_LINKED)) { + ieee->link_state != MAC80211_LINKED)) { spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2); rtllib_sta_wakeup(ieee, 1); @@ -2073,7 +2010,6 @@ static inline void rtllib_sta_ps(struct work_struct *work) ieee->ps_time = time; } spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2); - } ieee->bAwakePktSent = false; @@ -2088,7 +2024,6 @@ static inline void rtllib_sta_ps(struct work_struct *work) out: spin_unlock_irqrestore(&ieee->lock, flags); - } static void rtllib_sta_wakeup(struct rtllib_device *ieee, short nl) @@ -2105,7 +2040,6 @@ static void rtllib_sta_wakeup(struct rtllib_device *ieee, short nl) } } return; - } if (ieee->sta_sleep == LPS_IS_SLEEP) @@ -2207,7 +2141,7 @@ rtllib_rx_assoc_resp(struct rtllib_device *ieee, struct sk_buff *skb, WLAN_FC_GET_STYPE(frame_ctl)); if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) && - ieee->state == RTLLIB_ASSOCIATING_AUTHENTICATED && + ieee->link_state == RTLLIB_ASSOCIATING_AUTHENTICATED && (ieee->iw_mode == IW_MODE_INFRA)) { errcode = assoc_parse(ieee, skb, &aid); if (!errcode) { @@ -2217,7 +2151,7 @@ rtllib_rx_assoc_resp(struct rtllib_device *ieee, struct sk_buff *skb, if (!network) return 1; - ieee->state = RTLLIB_LINKED; + ieee->link_state = MAC80211_LINKED; ieee->assoc_id = aid; ieee->softmac_stats.rx_ass_ok++; /* station support qos */ @@ -2286,7 +2220,7 @@ static void rtllib_rx_auth_resp(struct rtllib_device *ieee, struct sk_buff *skb) } if (ieee->open_wep || !challenge) { - ieee->state = RTLLIB_ASSOCIATING_AUTHENTICATED; + ieee->link_state = RTLLIB_ASSOCIATING_AUTHENTICATED; ieee->softmac_stats.rx_auth_rs_ok++; if (!(ieee->ht_info->iot_action & HT_IOT_ACT_PURE_N_MODE)) { if (!ieee->GetNmodeSupportBySecCfg(ieee->dev)) { @@ -2301,14 +2235,14 @@ static void rtllib_rx_auth_resp(struct rtllib_device *ieee, struct sk_buff *skb) } /* Dummy wirless mode setting to avoid encryption issue */ if (bSupportNmode) { - ieee->SetWirelessMode(ieee->dev, + ieee->set_wireless_mode(ieee->dev, ieee->current_network.mode); } else { /*TODO*/ - ieee->SetWirelessMode(ieee->dev, IEEE_G); + ieee->set_wireless_mode(ieee->dev, WIRELESS_MODE_G); } - if ((ieee->current_network.mode == IEEE_N_24G) && + if ((ieee->current_network.mode == WIRELESS_MODE_N_24G) && bHalfSupportNmode) { netdev_info(ieee->dev, "======>enter half N mode\n"); ieee->bHalfWirelessN24GMode = true; @@ -2325,9 +2259,8 @@ static inline int rtllib_rx_auth(struct rtllib_device *ieee, struct sk_buff *skb, struct rtllib_rx_stats *rx_stats) { - if (ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) { - if (ieee->state == RTLLIB_ASSOCIATING_AUTHENTICATING && + if (ieee->link_state == RTLLIB_ASSOCIATING_AUTHENTICATING && (ieee->iw_mode == IW_MODE_INFRA)) { netdev_dbg(ieee->dev, "Received authentication response"); @@ -2352,25 +2285,21 @@ rtllib_rx_deauth(struct rtllib_device *ieee, struct sk_buff *skb) * both for disassociation and deauthentication */ if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) && - ieee->state == RTLLIB_LINKED && + ieee->link_state == MAC80211_LINKED && (ieee->iw_mode == IW_MODE_INFRA)) { frame_ctl = le16_to_cpu(header->frame_ctl); netdev_info(ieee->dev, "==========>received disassoc/deauth(%x) frame, reason code:%x\n", WLAN_FC_GET_STYPE(frame_ctl), ((struct rtllib_disassoc *)skb->data)->reason); - ieee->state = RTLLIB_ASSOCIATING; + ieee->link_state = RTLLIB_ASSOCIATING; ieee->softmac_stats.reassoc++; ieee->is_roaming = true; ieee->link_detect_info.bBusyTraffic = false; rtllib_disassociate(ieee); RemovePeerTS(ieee, header->addr2); - if (ieee->LedControlHandler != NULL) - ieee->LedControlHandler(ieee->dev, - LED_CTL_START_TO_LINK); - if (!(ieee->rtllib_ap_sec_type(ieee) & - (SEC_ALG_CCMP|SEC_ALG_TKIP))) + (SEC_ALG_CCMP | SEC_ALG_TKIP))) schedule_delayed_work( &ieee->associate_procedure_wq, 5); } @@ -2437,7 +2366,6 @@ inline int rtllib_rx_frame_softmac(struct rtllib_device *ieee, */ void rtllib_softmac_xmit(struct rtllib_txb *txb, struct rtllib_device *ieee) { - unsigned int queue_index = txb->queue_index; unsigned long flags; int i; @@ -2482,7 +2410,6 @@ void rtllib_softmac_xmit(struct rtllib_txb *txb, struct rtllib_device *ieee) rtllib_txb_free(txb); spin_unlock_irqrestore(&ieee->lock, flags); - } void rtllib_reset_queue(struct rtllib_device *ieee) @@ -2497,7 +2424,6 @@ void rtllib_reset_queue(struct rtllib_device *ieee) } ieee->queue_stop = 0; spin_unlock_irqrestore(&ieee->lock, flags); - } EXPORT_SYMBOL(rtllib_reset_queue); @@ -2534,25 +2460,17 @@ static void rtllib_start_master_bss(struct rtllib_device *ieee) ether_addr_copy(ieee->current_network.bssid, ieee->dev->dev_addr); ieee->set_chan(ieee->dev, ieee->current_network.channel); - ieee->state = RTLLIB_LINKED; + ieee->link_state = MAC80211_LINKED; ieee->link_change(ieee->dev); notify_wx_assoc_event(ieee); - - if (ieee->data_hard_resume) - ieee->data_hard_resume(ieee->dev); - netif_carrier_on(ieee->dev); } static void rtllib_start_monitor_mode(struct rtllib_device *ieee) { /* reset hardware status */ - if (ieee->raw_tx) { - if (ieee->data_hard_resume) - ieee->data_hard_resume(ieee->dev); - + if (ieee->raw_tx) netif_carrier_on(ieee->dev); - } } static void rtllib_start_ibss_wq(void *data) @@ -2579,12 +2497,11 @@ static void rtllib_start_ibss_wq(void *data) ieee->ssid_set = 1; } - ieee->state = RTLLIB_NOLINK; - ieee->mode = IEEE_G; + ieee->link_state = MAC80211_NOLINK; + ieee->mode = WIRELESS_MODE_G; /* check if we have this cell in our network list */ rtllib_softmac_check_all_nets(ieee); - /* if not then the state is not linked. Maybe the user switched to * ad-hoc mode just after being in monitor mode, or just after * being very few time in managed mode (so the card have had no @@ -2592,25 +2509,24 @@ static void rtllib_start_ibss_wq(void *data) * after setting ad-hoc mode. So we have to give another try.. * Here, in ibss mode, should be safe to do this without extra care * (in bss mode we had to make sure no-one tried to associate when - * we had just checked the ieee->state and we was going to start the + * we had just checked the ieee->link_state and we was going to start the * scan) because in ibss mode the rtllib_new_net function, when - * finds a good net, just set the ieee->state to RTLLIB_LINKED, + * finds a good net, just set the ieee->link_state to MAC80211_LINKED, * so, at worst, we waste a bit of time to initiate an unneeded syncro * scan, that will stop at the first round because it sees the state * associated. */ - if (ieee->state == RTLLIB_NOLINK) + if (ieee->link_state == MAC80211_NOLINK) rtllib_start_scan_syncro(ieee, 0); /* the network definitively is not here.. create a new cell */ - if (ieee->state == RTLLIB_NOLINK) { + if (ieee->link_state == MAC80211_NOLINK) { netdev_info(ieee->dev, "creating new IBSS cell\n"); ieee->current_network.channel = ieee->bss_start_channel; if (!ieee->wap_set) eth_random_addr(ieee->current_network.bssid); if (ieee->modulation & RTLLIB_CCK_MODULATION) { - ieee->current_network.rates_len = 4; ieee->current_network.rates[0] = @@ -2622,8 +2538,9 @@ static void rtllib_start_ibss_wq(void *data) ieee->current_network.rates[3] = RTLLIB_BASIC_RATE_MASK | RTLLIB_CCK_RATE_11MB; - } else + } else { ieee->current_network.rates_len = 0; + } if (ieee->modulation & RTLLIB_OFDM_MODULATION) { ieee->current_network.rates_ex_len = 8; @@ -2652,35 +2569,28 @@ static void rtllib_start_ibss_wq(void *data) } ieee->current_network.qos_data.supported = 0; - ieee->SetWirelessMode(ieee->dev, IEEE_G); + ieee->set_wireless_mode(ieee->dev, WIRELESS_MODE_G); ieee->current_network.mode = ieee->mode; ieee->current_network.atim_window = 0; ieee->current_network.capability = WLAN_CAPABILITY_IBSS; } netdev_info(ieee->dev, "%s(): ieee->mode = %d\n", __func__, ieee->mode); - if ((ieee->mode == IEEE_N_24G) || (ieee->mode == IEEE_N_5G)) + if (ieee->mode == WIRELESS_MODE_N_24G) HTUseDefaultSetting(ieee); else ieee->ht_info->bCurrentHTSupport = false; ieee->SetHwRegHandler(ieee->dev, HW_VAR_MEDIA_STATUS, - (u8 *)(&ieee->state)); + (u8 *)(&ieee->link_state)); - ieee->state = RTLLIB_LINKED; + ieee->link_state = MAC80211_LINKED; ieee->link_change(ieee->dev); HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT); - if (ieee->LedControlHandler != NULL) - ieee->LedControlHandler(ieee->dev, LED_CTL_LINK); - rtllib_start_send_beacons(ieee); notify_wx_assoc_event(ieee); - - if (ieee->data_hard_resume) - ieee->data_hard_resume(ieee->dev); - netif_carrier_on(ieee->dev); mutex_unlock(&ieee->wx_mutex); @@ -2708,7 +2618,7 @@ static void rtllib_start_bss(struct rtllib_device *ieee) rtllib_softmac_check_all_nets(ieee); /* ensure no-one start an associating process (thus setting - * the ieee->state to rtllib_ASSOCIATING) while we + * the ieee->link_state to rtllib_ASSOCIATING) while we * have just checked it and we are going to enable scan. * The rtllib_new_net function is always called with * lock held (from both rtllib_softmac_check_all_nets and @@ -2716,7 +2626,7 @@ static void rtllib_start_bss(struct rtllib_device *ieee) */ spin_lock_irqsave(&ieee->lock, flags); - if (ieee->state == RTLLIB_NOLINK) + if (ieee->link_state == MAC80211_NOLINK) rtllib_start_scan(ieee); spin_unlock_irqrestore(&ieee->lock, flags); } @@ -2734,11 +2644,9 @@ void rtllib_disassociate(struct rtllib_device *ieee) if (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE) rtllib_reset_queue(ieee); - if (ieee->data_hard_stop) - ieee->data_hard_stop(ieee->dev); if (IS_DOT11D_ENABLE(ieee)) dot11d_reset(ieee); - ieee->state = RTLLIB_NOLINK; + ieee->link_state = MAC80211_NOLINK; ieee->is_set_key = false; ieee->wap_set = 0; @@ -2757,14 +2665,14 @@ static void rtllib_associate_retry_wq(void *data) if (!ieee->proto_started) goto exit; - if (ieee->state != RTLLIB_ASSOCIATING_RETRY) + if (ieee->link_state != RTLLIB_ASSOCIATING_RETRY) goto exit; - /* until we do not set the state to RTLLIB_NOLINK + /* until we do not set the state to MAC80211_NOLINK * there are no possibility to have someone else trying * to start an association procedure (we get here with - * ieee->state = RTLLIB_ASSOCIATING). - * When we set the state to RTLLIB_NOLINK it is possible + * ieee->link_state = RTLLIB_ASSOCIATING). + * When we set the state to MAC80211_NOLINK it is possible * that the RX path run an attempt to associate, but * both rtllib_softmac_check_all_nets and the * RX path works with ieee->lock held so there are no @@ -2774,13 +2682,13 @@ static void rtllib_associate_retry_wq(void *data) * state and we are going to start the scan. */ ieee->beinretry = true; - ieee->state = RTLLIB_NOLINK; + ieee->link_state = MAC80211_NOLINK; rtllib_softmac_check_all_nets(ieee); spin_lock_irqsave(&ieee->lock, flags); - if (ieee->state == RTLLIB_NOLINK) + if (ieee->link_state == MAC80211_NOLINK) rtllib_start_scan(ieee); spin_unlock_irqrestore(&ieee->lock, flags); @@ -2806,7 +2714,6 @@ static struct sk_buff *rtllib_get_beacon_(struct rtllib_device *ieee) b->header.frame_ctl = cpu_to_le16(RTLLIB_STYPE_BEACON); return skb; - } struct sk_buff *rtllib_get_beacon(struct rtllib_device *ieee) @@ -2840,7 +2747,6 @@ void rtllib_softmac_stop_protocol(struct rtllib_device *ieee, u8 mesh_flag, } EXPORT_SYMBOL(rtllib_softmac_stop_protocol); - void rtllib_stop_protocol(struct rtllib_device *ieee, u8 shutdown) { if (!ieee->proto_started) @@ -2859,10 +2765,10 @@ void rtllib_stop_protocol(struct rtllib_device *ieee, u8 shutdown) cancel_delayed_work_sync(&ieee->link_change_wq); rtllib_stop_scan(ieee); - if (ieee->state <= RTLLIB_ASSOCIATING_AUTHENTICATED) - ieee->state = RTLLIB_NOLINK; + if (ieee->link_state <= RTLLIB_ASSOCIATING_AUTHENTICATED) + ieee->link_state = MAC80211_NOLINK; - if (ieee->state == RTLLIB_LINKED) { + if (ieee->link_state == MAC80211_LINKED) { if (ieee->iw_mode == IW_MODE_INFRA) SendDisassociation(ieee, 1, WLAN_REASON_DEAUTH_LEAVING); rtllib_disassociate(ieee); @@ -2918,27 +2824,25 @@ void rtllib_start_protocol(struct rtllib_device *ieee) ieee->last_packet_time[i] = 0; } - if (ieee->UpdateBeaconInterruptHandler) - ieee->UpdateBeaconInterruptHandler(ieee->dev, false); - ieee->wmm_acm = 0; /* if the user set the MAC of the ad-hoc cell and then * switch to managed mode, shall we make sure that association * attempts does not fail just because the user provide the essid * and the nic is still checking for the AP MAC ?? */ - if (ieee->iw_mode == IW_MODE_INFRA) { + switch (ieee->iw_mode) { + case IW_MODE_INFRA: rtllib_start_bss(ieee); - } else if (ieee->iw_mode == IW_MODE_ADHOC) { - if (ieee->UpdateBeaconInterruptHandler) - ieee->UpdateBeaconInterruptHandler(ieee->dev, true); - + break; + case IW_MODE_ADHOC: rtllib_start_ibss(ieee); - - } else if (ieee->iw_mode == IW_MODE_MASTER) { + break; + case IW_MODE_MASTER: rtllib_start_master_bss(ieee); - } else if (ieee->iw_mode == IW_MODE_MONITOR) { + break; + case IW_MODE_MONITOR: rtllib_start_monitor_mode(ieee); + break; } } @@ -2948,7 +2852,7 @@ int rtllib_softmac_init(struct rtllib_device *ieee) memset(&ieee->current_network, 0, sizeof(struct rtllib_network)); - ieee->state = RTLLIB_NOLINK; + ieee->link_state = MAC80211_NOLINK; for (i = 0; i < 5; i++) ieee->seq_ctrl[i] = 0; ieee->dot11d_info = kzalloc(sizeof(struct rt_dot11d_info), GFP_ATOMIC); @@ -3139,7 +3043,7 @@ static void rtllib_MgntDisconnectIBSS(struct rtllib_device *rtllib) u8 i; bool bFilterOutNonAssociatedBSSID = false; - rtllib->state = RTLLIB_NOLINK; + rtllib->link_state = MAC80211_NOLINK; for (i = 0; i < 6; i++) rtllib->current_network.bssid[i] = 0x55; @@ -3155,7 +3059,6 @@ static void rtllib_MgntDisconnectIBSS(struct rtllib_device *rtllib) rtllib->SetHwRegHandler(rtllib->dev, HW_VAR_CECHK_BSSID, (u8 *)(&bFilterOutNonAssociatedBSSID)); notify_wx_assoc_event(rtllib); - } static void rtllib_MlmeDisassociateRequest(struct rtllib_device *rtllib, @@ -3167,7 +3070,7 @@ static void rtllib_MlmeDisassociateRequest(struct rtllib_device *rtllib, RemovePeerTS(rtllib, asSta); if (memcmp(rtllib->current_network.bssid, asSta, 6) == 0) { - rtllib->state = RTLLIB_NOLINK; + rtllib->link_state = MAC80211_NOLINK; for (i = 0; i < 6; i++) rtllib->current_network.bssid[i] = 0x22; @@ -3179,9 +3082,7 @@ static void rtllib_MlmeDisassociateRequest(struct rtllib_device *rtllib, rtllib->SetHwRegHandler(rtllib->dev, HW_VAR_BSSID, rtllib->current_network.bssid); - } - } static void @@ -3198,7 +3099,7 @@ rtllib_MgntDisconnectAP( rtllib_MlmeDisassociateRequest(rtllib, rtllib->current_network.bssid, asRsn); - rtllib->state = RTLLIB_NOLINK; + rtllib->link_state = MAC80211_NOLINK; } bool rtllib_MgntDisconnect(struct rtllib_device *rtllib, u8 asRsn) @@ -3206,12 +3107,11 @@ bool rtllib_MgntDisconnect(struct rtllib_device *rtllib, u8 asRsn) if (rtllib->ps != RTLLIB_PS_DISABLED) rtllib->sta_wake_up(rtllib->dev); - if (rtllib->state == RTLLIB_LINKED) { + if (rtllib->link_state == MAC80211_LINKED) { if (rtllib->iw_mode == IW_MODE_ADHOC) rtllib_MgntDisconnectIBSS(rtllib); if (rtllib->iw_mode == IW_MODE_INFRA) rtllib_MgntDisconnectAP(rtllib, asRsn); - } return true; @@ -3226,11 +3126,10 @@ void notify_wx_assoc_event(struct rtllib_device *ieee) return; wrqu.ap_addr.sa_family = ARPHRD_ETHER; - if (ieee->state == RTLLIB_LINKED) + if (ieee->link_state == MAC80211_LINKED) { memcpy(wrqu.ap_addr.sa_data, ieee->current_network.bssid, ETH_ALEN); - else { - + } else { netdev_info(ieee->dev, "%s(): Tell user space disconnected\n", __func__); eth_zero_addr(wrqu.ap_addr.sa_data); diff --git a/drivers/staging/rtl8192e/rtllib_softmac_wx.c b/drivers/staging/rtl8192e/rtllib_softmac_wx.c index 1f2fa711e60b466573066326cd1731c9f52ab907..2de63d1f20095c9ca73a872104d07a4e1f3ad6a5 100644 --- a/drivers/staging/rtl8192e/rtllib_softmac_wx.c +++ b/drivers/staging/rtl8192e/rtllib_softmac_wx.c @@ -15,16 +15,6 @@ #include "rtllib.h" #include "dot11d.h" -/* FIXME: add A freqs */ - -const long rtllib_wlan_frequencies[] = { - 2412, 2417, 2422, 2427, - 2432, 2437, 2442, 2447, - 2452, 2457, 2462, 2467, - 2472, 2484 -}; -EXPORT_SYMBOL(rtllib_wlan_frequencies); - int rtllib_wx_set_freq(struct rtllib_device *ieee, struct iw_request_info *a, union iwreq_data *wrqu, char *b) @@ -43,15 +33,8 @@ int rtllib_wx_set_freq(struct rtllib_device *ieee, struct iw_request_info *a, if (fwrq->e == 1) { if ((fwrq->m >= (int)2.412e8 && fwrq->m <= (int)2.487e8)) { - int f = fwrq->m / 100000; - int c = 0; - - while ((c < 14) && (f != rtllib_wlan_frequencies[c])) - c++; - - /* hack to fall through */ + fwrq->m = ieee80211_freq_khz_to_channel(fwrq->m / 100); fwrq->e = 0; - fwrq->m = c + 1; } } @@ -70,7 +53,7 @@ int rtllib_wx_set_freq(struct rtllib_device *ieee, struct iw_request_info *a, if (ieee->iw_mode == IW_MODE_ADHOC || ieee->iw_mode == IW_MODE_MASTER) - if (ieee->state == RTLLIB_LINKED) { + if (ieee->link_state == MAC80211_LINKED) { rtllib_stop_send_beacons(ieee); rtllib_start_send_beacons(ieee); } @@ -83,7 +66,6 @@ int rtllib_wx_set_freq(struct rtllib_device *ieee, struct iw_request_info *a, } EXPORT_SYMBOL(rtllib_wx_set_freq); - int rtllib_wx_get_freq(struct rtllib_device *ieee, struct iw_request_info *a, union iwreq_data *wrqu, char *b) @@ -92,8 +74,8 @@ int rtllib_wx_get_freq(struct rtllib_device *ieee, if (ieee->current_network.channel == 0) return -1; - fwrq->m = rtllib_wlan_frequencies[ieee->current_network.channel-1] * - 100000; + fwrq->m = ieee80211_channel_to_freq_khz(ieee->current_network.channel, + NL80211_BAND_2GHZ) * 100; fwrq->e = 1; return 0; } @@ -113,8 +95,8 @@ int rtllib_wx_get_wap(struct rtllib_device *ieee, /* We want avoid to give to the user inconsistent infos*/ spin_lock_irqsave(&ieee->lock, flags); - if (ieee->state != RTLLIB_LINKED && - ieee->state != RTLLIB_LINKED_SCANNING && + if (ieee->link_state != MAC80211_LINKED && + ieee->link_state != MAC80211_LINKED_SCANNING && ieee->wap_set == 0) eth_zero_addr(wrqu->ap_addr.sa_data); @@ -128,13 +110,11 @@ int rtllib_wx_get_wap(struct rtllib_device *ieee, } EXPORT_SYMBOL(rtllib_wx_get_wap); - int rtllib_wx_set_wap(struct rtllib_device *ieee, struct iw_request_info *info, union iwreq_data *awrq, char *extra) { - int ret = 0; unsigned long flags; @@ -164,7 +144,6 @@ int rtllib_wx_set_wap(struct rtllib_device *ieee, goto out; } - if (ifup) rtllib_stop_protocol(ieee, true); @@ -205,8 +184,8 @@ int rtllib_wx_get_essid(struct rtllib_device *ieee, struct iw_request_info *a, goto out; } - if (ieee->state != RTLLIB_LINKED && - ieee->state != RTLLIB_LINKED_SCANNING && + if (ieee->link_state != MAC80211_LINKED && + ieee->link_state != MAC80211_LINKED_SCANNING && ieee->ssid_set == 0) { ret = -1; goto out; @@ -220,7 +199,6 @@ int rtllib_wx_get_essid(struct rtllib_device *ieee, struct iw_request_info *a, spin_unlock_irqrestore(&ieee->lock, flags); return ret; - } EXPORT_SYMBOL(rtllib_wx_get_essid); @@ -228,10 +206,9 @@ int rtllib_wx_set_rate(struct rtllib_device *ieee, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) { - u32 target_rate = wrqu->bitrate.value; - ieee->rate = target_rate/100000; + ieee->rate = target_rate / 100000; return 0; } EXPORT_SYMBOL(rtllib_wx_set_rate); @@ -250,14 +227,13 @@ int rtllib_wx_get_rate(struct rtllib_device *ieee, } EXPORT_SYMBOL(rtllib_wx_get_rate); - int rtllib_wx_set_rts(struct rtllib_device *ieee, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) { - if (wrqu->rts.disabled || !wrqu->rts.fixed) + if (wrqu->rts.disabled || !wrqu->rts.fixed) { ieee->rts = DEFAULT_RTS_THRESHOLD; - else { + } else { if (wrqu->rts.value < MIN_RTS_THRESHOLD || wrqu->rts.value > MAX_RTS_THRESHOLD) return -EINVAL; @@ -332,6 +308,7 @@ void rtllib_wx_sync_scan_wq(void *data) enum ht_channel_width bandwidth = 0; int b40M = 0; + mutex_lock(&ieee->wx_mutex); if (!(ieee->softmac_features & IEEE_SOFTMAC_SCAN)) { rtllib_start_scan_syncro(ieee, 0); goto out; @@ -339,17 +316,14 @@ void rtllib_wx_sync_scan_wq(void *data) chan = ieee->current_network.channel; - ieee->LeisurePSLeave(ieee->dev); + ieee->leisure_ps_leave(ieee->dev); /* notify AP to be in PS mode */ rtllib_sta_ps_send_null_frame(ieee, 1); rtllib_sta_ps_send_null_frame(ieee, 1); rtllib_stop_all_queues(ieee); - - if (ieee->data_hard_stop) - ieee->data_hard_stop(ieee->dev); rtllib_stop_send_beacons(ieee); - ieee->state = RTLLIB_LINKED_SCANNING; + ieee->link_state = MAC80211_LINKED_SCANNING; ieee->link_change(ieee->dev); /* wait for ps packet to be kicked out successfully */ msleep(50); @@ -361,7 +335,7 @@ void rtllib_wx_sync_scan_wq(void *data) b40M = 1; chan_offset = ieee->ht_info->CurSTAExtChnlOffset; bandwidth = (enum ht_channel_width)ieee->ht_info->bCurBW40MHz; - ieee->SetBWModeHandler(ieee->dev, HT_CHANNEL_WIDTH_20, + ieee->set_bw_mode_handler(ieee->dev, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT); } @@ -374,14 +348,14 @@ void rtllib_wx_sync_scan_wq(void *data) ieee->set_chan(ieee->dev, chan - 2); else ieee->set_chan(ieee->dev, chan); - ieee->SetBWModeHandler(ieee->dev, bandwidth, chan_offset); + ieee->set_bw_mode_handler(ieee->dev, bandwidth, chan_offset); } else { ieee->set_chan(ieee->dev, chan); } ieee->ScanOperationBackupHandler(ieee->dev, SCAN_OPT_RESTORE); - ieee->state = RTLLIB_LINKED; + ieee->link_state = MAC80211_LINKED; ieee->link_change(ieee->dev); /* Notify AP that I wake up again */ @@ -392,10 +366,6 @@ void rtllib_wx_sync_scan_wq(void *data) ieee->link_detect_info.NumRecvBcnInPeriod = 1; ieee->link_detect_info.NumRecvDataInPeriod = 1; } - - if (ieee->data_hard_resume) - ieee->data_hard_resume(ieee->dev); - if (ieee->iw_mode == IW_MODE_ADHOC || ieee->iw_mode == IW_MODE_MASTER) rtllib_start_send_beacons(ieee); @@ -403,7 +373,6 @@ void rtllib_wx_sync_scan_wq(void *data) out: mutex_unlock(&ieee->wx_mutex); - } int rtllib_wx_set_scan(struct rtllib_device *ieee, struct iw_request_info *a, @@ -411,21 +380,18 @@ int rtllib_wx_set_scan(struct rtllib_device *ieee, struct iw_request_info *a, { int ret = 0; - mutex_lock(&ieee->wx_mutex); - if (ieee->iw_mode == IW_MODE_MONITOR || !(ieee->proto_started)) { ret = -1; goto out; } - if (ieee->state == RTLLIB_LINKED) { + if (ieee->link_state == MAC80211_LINKED) { schedule_work(&ieee->wx_sync_scan_wq); /* intentionally forget to up sem */ return 0; } out: - mutex_unlock(&ieee->wx_mutex); return ret; } EXPORT_SYMBOL(rtllib_wx_set_scan); @@ -434,7 +400,6 @@ int rtllib_wx_set_essid(struct rtllib_device *ieee, struct iw_request_info *a, union iwreq_data *wrqu, char *extra) { - int ret = 0, len; short proto_started; unsigned long flags; @@ -454,7 +419,6 @@ int rtllib_wx_set_essid(struct rtllib_device *ieee, if (proto_started) rtllib_stop_protocol(ieee, true); - /* this is just to be sure that the GET wx callback * has consistent infos. not needed otherwise */ @@ -492,7 +456,6 @@ int rtllib_wx_set_rawtx(struct rtllib_device *ieee, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) { - int *parms = (int *)extra; int enable = (parms[0] > 0); short prev = ieee->raw_tx; @@ -508,12 +471,8 @@ int rtllib_wx_set_rawtx(struct rtllib_device *ieee, ieee->raw_tx ? "enabled" : "disabled"); if (ieee->iw_mode == IW_MODE_MONITOR) { - if (prev == 0 && ieee->raw_tx) { - if (ieee->data_hard_resume) - ieee->data_hard_resume(ieee->dev); - + if (prev == 0 && ieee->raw_tx) netif_carrier_on(ieee->dev); - } if (prev && ieee->raw_tx == 1) netif_carrier_off(ieee->dev); @@ -530,14 +489,13 @@ int rtllib_wx_get_name(struct rtllib_device *ieee, struct iw_request_info *info, { const char *b = ieee->modulation & RTLLIB_CCK_MODULATION ? "b" : ""; const char *g = ieee->modulation & RTLLIB_OFDM_MODULATION ? "g" : ""; - const char *n = ieee->mode & (IEEE_N_24G | IEEE_N_5G) ? "n" : ""; + const char *n = ieee->mode & (WIRELESS_MODE_N_24G) ? "n" : ""; scnprintf(wrqu->name, sizeof(wrqu->name), "802.11%s%s%s", b, g, n); return 0; } EXPORT_SYMBOL(rtllib_wx_get_name); - /* this is mostly stolen from hostap */ int rtllib_wx_set_power(struct rtllib_device *ieee, struct iw_request_info *info, @@ -583,12 +541,10 @@ int rtllib_wx_set_power(struct rtllib_device *ieee, default: ret = -EINVAL; goto exit; - } exit: mutex_unlock(&ieee->wx_mutex); return ret; - } EXPORT_SYMBOL(rtllib_wx_set_power); @@ -625,6 +581,5 @@ int rtllib_wx_get_power(struct rtllib_device *ieee, exit: mutex_unlock(&ieee->wx_mutex); return 0; - } EXPORT_SYMBOL(rtllib_wx_get_power); diff --git a/drivers/staging/rtl8192e/rtllib_tx.c b/drivers/staging/rtl8192e/rtllib_tx.c index 9ab8ee46ef66898e654b4990ab0bd2ad2ff9ca6a..ec038ef806c30ab5eb5494392631008e6f7e7f9b 100644 --- a/drivers/staging/rtl8192e/rtllib_tx.c +++ b/drivers/staging/rtl8192e/rtllib_tx.c @@ -406,7 +406,7 @@ static void rtllib_query_protectionmode(struct rtllib_device *ieee, if (is_broadcast_ether_addr(skb->data + 16)) return; - if (ieee->mode < IEEE_N_24G) { + if (ieee->mode < WIRELESS_MODE_N_24G) { if (skb->len > ieee->rts) { tcb_desc->bRTSEnable = true; tcb_desc->rts_rate = MGN_24M; @@ -486,7 +486,7 @@ static void rtllib_txrate_selectmode(struct rtllib_device *ieee, !tcb_desc->tx_use_drv_assinged_rate) { if (ieee->iw_mode == IW_MODE_INFRA || ieee->iw_mode == IW_MODE_ADHOC) - tcb_desc->RATRIndex = 0; + tcb_desc->ratr_index = 0; } } @@ -572,8 +572,7 @@ static int rtllib_xmit_inter(struct sk_buff *skb, struct net_device *dev) /* If there is no driver handler to take the TXB, don't bother * creating it... */ - if ((!ieee->hard_start_xmit && !(ieee->softmac_features & - IEEE_SOFTMAC_TX_QUEUE)) || + if (!(ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE) || ((!ieee->softmac_data_hard_start_xmit && (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE)))) { netdev_warn(ieee->dev, "No xmit handler.\n"); @@ -892,7 +891,7 @@ static int rtllib_xmit_inter(struct sk_buff *skb, struct net_device *dev) tcb_desc->tx_dis_rate_fallback = 1; } - tcb_desc->RATRIndex = 7; + tcb_desc->ratr_index = 7; tcb_desc->tx_use_drv_assinged_rate = 1; } else { if (is_multicast_ether_addr(header.addr1)) @@ -916,7 +915,7 @@ static int rtllib_xmit_inter(struct sk_buff *skb, struct net_device *dev) tcb_desc->tx_dis_rate_fallback = 1; } - tcb_desc->RATRIndex = 7; + tcb_desc->ratr_index = 7; tcb_desc->tx_use_drv_assinged_rate = 1; tcb_desc->bdhcp = 1; } @@ -938,11 +937,6 @@ static int rtllib_xmit_inter(struct sk_buff *skb, struct net_device *dev) dev->stats.tx_bytes += le16_to_cpu(txb->payload_size); rtllib_softmac_xmit(txb, ieee); } else { - if ((*ieee->hard_start_xmit)(txb, dev) == 0) { - stats->tx_packets++; - stats->tx_bytes += le16_to_cpu(txb->payload_size); - return 0; - } rtllib_txb_free(txb); } } diff --git a/drivers/staging/rtl8192e/rtllib_wx.c b/drivers/staging/rtl8192e/rtllib_wx.c index d6691f3c7c70abc627f05083f44d7dcea7300628..e9469bfef3ddee1c5ef57fb65beee536bfad9d0f 100644 --- a/drivers/staging/rtl8192e/rtllib_wx.c +++ b/drivers/staging/rtl8192e/rtllib_wx.c @@ -19,7 +19,7 @@ #include "rtllib.h" static const char * const rtllib_modes[] = { - "a", "b", "g", "?", "N-24G", "N-5G" + "a", "b", "g", "?", "N-24G" }; #define MAX_CUSTOM_LEN 64 @@ -118,7 +118,7 @@ static inline char *rtl819x_translate_scan(struct rtllib_device *ieee, max_rate = rate; } - if (network->mode >= IEEE_N_24G) { + if (network->mode >= WIRELESS_MODE_N_24G) { struct ht_capab_ele *ht_cap = NULL; bool is40M = false, isShortGI = false; u8 max_mcs = 0; @@ -416,22 +416,6 @@ int rtllib_wx_set_encode(struct rtllib_device *ieee, */ sec.flags |= SEC_LEVEL; sec.level = SEC_LEVEL_1; /* 40 and 104 bit WEP */ - - if (ieee->set_security) - ieee->set_security(dev, &sec); - - /* Do not reset port if card is in Managed mode since resetting will - * generate new IEEE 802.11 authentication which may end up in looping - * with IEEE 802.1X. If your hardware requires a reset after WEP - * configuration (for example... Prism2), implement the reset_port in - * the callbacks structures used to initialize the 802.11 stack. - */ - if (ieee->reset_on_keychange && - ieee->iw_mode != IW_MODE_INFRA && - ieee->reset_port && ieee->reset_port(dev)) { - netdev_dbg(dev, "%s: reset_port failed\n", dev->name); - return -EINVAL; - } return 0; } EXPORT_SYMBOL(rtllib_wx_set_encode); @@ -623,15 +607,6 @@ int rtllib_wx_set_encode_ext(struct rtllib_device *ieee, sec.flags &= ~SEC_LEVEL; } done: - if (ieee->set_security) - ieee->set_security(ieee->dev, &sec); - - if (ieee->reset_on_keychange && - ieee->iw_mode != IW_MODE_INFRA && - ieee->reset_port && ieee->reset_port(dev)) { - netdev_dbg(ieee->dev, "Port reset failed\n"); - return -EINVAL; - } return ret; } EXPORT_SYMBOL(rtllib_wx_set_encode_ext); @@ -644,7 +619,7 @@ int rtllib_wx_set_mlme(struct rtllib_device *ieee, bool deauth = false; struct iw_mlme *mlme = (struct iw_mlme *)extra; - if (ieee->state != RTLLIB_LINKED) + if (ieee->link_state != MAC80211_LINKED) return -ENOLINK; mutex_lock(&ieee->wx_mutex); diff --git a/drivers/staging/rtl8723bs/hal/rtl8723b_hal_init.c b/drivers/staging/rtl8723bs/hal/rtl8723b_hal_init.c index c3c1b49674d3a794cefdf6e32891b5256fbbec71..1e9e1089032bac11c88cefd70f45da76496eecbf 100644 --- a/drivers/staging/rtl8723bs/hal/rtl8723b_hal_init.c +++ b/drivers/staging/rtl8723bs/hal/rtl8723b_hal_init.c @@ -2275,7 +2275,10 @@ void Hal_EfuseParseBTCoexistInfo_8723B( pHalData->EEPROMBluetoothAntNum = tempval & BIT(0); /* EFUSE_0xC3[6] == 0, S1(Main)-RF_PATH_A; */ /* EFUSE_0xC3[6] == 1, S0(Aux)-RF_PATH_B */ - pHalData->ant_path = (tempval & BIT(6))? RF_PATH_B : RF_PATH_A; + if (tempval & BIT(6)) + pHalData->ant_path = RF_PATH_B; + else + pHalData->ant_path = RF_PATH_A; } else { pHalData->EEPROMBluetoothAntNum = Ant_x1; if (pHalData->PackageType == PACKAGE_QFN68) diff --git a/drivers/staging/rtl8723bs/include/sta_info.h b/drivers/staging/rtl8723bs/include/sta_info.h index 69c377eeeaf08fca79771acfb6ef6c9cf875fea1..1ea3fe22b99a39d8662d8c61f44ec9d65c300a7d 100644 --- a/drivers/staging/rtl8723bs/include/sta_info.h +++ b/drivers/staging/rtl8723bs/include/sta_info.h @@ -16,9 +16,9 @@ /* if mode == 0, then the sta is allowed once the addr is hit. */ /* if mode == 1, then the sta is rejected once the addr is non-hit. */ struct rtw_wlan_acl_node { - struct list_head list; - u8 addr[ETH_ALEN]; - u8 valid; + struct list_head list; + u8 addr[ETH_ALEN]; + u8 valid; }; /* mode = 0, disable */ @@ -340,19 +340,19 @@ struct sta_priv { static inline u32 wifi_mac_hash(u8 *mac) { - u32 x; + u32 x; - x = mac[0]; - x = (x << 2) ^ mac[1]; - x = (x << 2) ^ mac[2]; - x = (x << 2) ^ mac[3]; - x = (x << 2) ^ mac[4]; - x = (x << 2) ^ mac[5]; + x = mac[0]; + x = (x << 2) ^ mac[1]; + x = (x << 2) ^ mac[2]; + x = (x << 2) ^ mac[3]; + x = (x << 2) ^ mac[4]; + x = (x << 2) ^ mac[5]; - x ^= x >> 8; - x = x & (NUM_STA - 1); + x ^= x >> 8; + x = x & (NUM_STA - 1); - return x; + return x; } diff --git a/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c b/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c index 84a9f4dd8f95456e2abfec04674f146788b4647b..2ae7843abdf768b43cdeea1aac6e0eb84d713664 100644 --- a/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c +++ b/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c @@ -305,7 +305,6 @@ struct cfg80211_bss *rtw_cfg80211_inform_bss(struct adapter *padapter, struct wl memcpy(pwlanhdr->addr2, pnetwork->network.mac_address, ETH_ALEN); memcpy(pwlanhdr->addr3, pnetwork->network.mac_address, ETH_ALEN); - pbuf += sizeof(struct ieee80211_hdr_3addr); len = sizeof(struct ieee80211_hdr_3addr); @@ -325,15 +324,14 @@ struct cfg80211_bss *rtw_cfg80211_inform_bss(struct adapter *padapter, struct wl exit: return bss; - } /* - Check the given bss is valid by kernel API cfg80211_get_bss() - @padapter : the given adapter - - return true if bss is valid, false for not found. -*/ + * Check the given bss is valid by kernel API cfg80211_get_bss() + * @padapter : the given adapter + * + * return true if bss is valid, false for not found. + */ int rtw_cfg80211_check_bss(struct adapter *padapter) { struct wlan_bssid_ex *pnetwork = &(padapter->mlmeextpriv.mlmext_info.network); @@ -374,7 +372,6 @@ void rtw_cfg80211_ibss_indicate_connect(struct adapter *padapter) struct wlan_network *scanned = pmlmepriv->cur_network_scanned; if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true) { - memcpy(&cur_network->network, pnetwork, sizeof(struct wlan_bssid_ex)); rtw_cfg80211_inform_bss(padapter, cur_network); } else { @@ -495,7 +492,6 @@ void rtw_cfg80211_indicate_disconnect(struct adapter *padapter) } } - static int rtw_cfg80211_ap_set_encryption(struct net_device *dev, struct ieee_param *param, u32 param_len) { int ret = 0; @@ -569,7 +565,6 @@ static int rtw_cfg80211_ap_set_encryption(struct net_device *dev, struct ieee_pa rtw_ap_set_wep_key(padapter, param->u.crypt.key, wep_key_len, wep_key_idx, 1); goto exit; - } /* group key */ @@ -581,7 +576,7 @@ static int rtw_cfg80211_ap_set_encryption(struct net_device *dev, struct ieee_pa psecuritypriv->dot118021XGrpPrivacy = _WEP40_; if (param->u.crypt.key_len == 13) - psecuritypriv->dot118021XGrpPrivacy = _WEP104_; + psecuritypriv->dot118021XGrpPrivacy = _WEP104_; } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) { psecuritypriv->dot118021XGrpPrivacy = _TKIP_; @@ -616,11 +611,9 @@ static int rtw_cfg80211_ap_set_encryption(struct net_device *dev, struct ieee_pa pbcmc_sta->ieee8021x_blocked = false; pbcmc_sta->dot118021XPrivacy = psecuritypriv->dot118021XGrpPrivacy;/* rx will use bmc_sta's dot118021XPrivacy */ } - } goto exit; - } if (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X && psta) { /* psk/802_1x */ @@ -643,7 +636,6 @@ static int rtw_cfg80211_ap_set_encryption(struct net_device *dev, struct ieee_pa psecuritypriv->busetkipkey = true; } else if (strcmp(param->u.crypt.alg, "CCMP") == 0) { - psta->dot118021XPrivacy = _AES_; } else { psta->dot118021XPrivacy = _NO_PRIVACY_; @@ -695,17 +687,13 @@ static int rtw_cfg80211_ap_set_encryption(struct net_device *dev, struct ieee_pa pbcmc_sta->ieee8021x_blocked = false; pbcmc_sta->dot118021XPrivacy = psecuritypriv->dot118021XGrpPrivacy;/* rx will use bmc_sta's dot118021XPrivacy */ } - } - } - } exit: return ret; - } static int rtw_cfg80211_set_encryption(struct net_device *dev, struct ieee_param *param, u32 param_len) @@ -789,7 +777,6 @@ static int rtw_cfg80211_set_encryption(struct net_device *dev, struct ieee_param if (strcmp(param->u.crypt.alg, "none") != 0) psta->ieee8021x_blocked = false; - if ((padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption2Enabled) || (padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption3Enabled)) { psta->dot118021XPrivacy = padapter->securitypriv.dot11PrivacyAlgrthm; @@ -900,7 +887,6 @@ static int cfg80211_rtw_add_key(struct wiphy *wiphy, struct net_device *ndev, strncpy((char *)param->u.crypt.alg, alg_name, IEEE_CRYPT_ALG_NAME_LEN); - if (!mac_addr || is_broadcast_ether_addr(mac_addr)) param->u.crypt.set_tx = 0; /* for wpa/wpa2 group key */ else @@ -932,7 +918,6 @@ static int cfg80211_rtw_add_key(struct wiphy *wiphy, struct net_device *ndev, kfree(param); return ret; - } static int cfg80211_rtw_get_key(struct wiphy *wiphy, struct net_device *ndev, @@ -983,7 +968,6 @@ static int cfg80211_rtw_set_default_key(struct wiphy *wiphy, } return 0; - } static int cfg80211_rtw_get_station(struct wiphy *wiphy, @@ -1168,7 +1152,6 @@ void rtw_cfg80211_surveydone_event_callback(struct adapter *padapter) /* ev =translate_scan(padapter, a, pnetwork, ev, stop); */ rtw_cfg80211_inform_bss(padapter, pnetwork); } - } spin_unlock_bh(&(pmlmepriv->scanned_queue.lock)); @@ -1200,7 +1183,6 @@ static int rtw_cfg80211_set_probe_req_wpsp2pie(struct adapter *padapter, char *b } return ret; - } static int cfg80211_rtw_scan(struct wiphy *wiphy @@ -1305,14 +1287,13 @@ static int cfg80211_rtw_scan(struct wiphy *wiphy } else if (request->n_channels <= 4) { for (j = request->n_channels - 1; j >= 0; j--) for (i = 0; i < survey_times; i++) - memcpy(&ch[j*survey_times+i], &ch[j], sizeof(struct rtw_ieee80211_channel)); + memcpy(&ch[j*survey_times+i], &ch[j], sizeof(struct rtw_ieee80211_channel)); _status = rtw_sitesurvey_cmd(padapter, ssid, RTW_SSID_SCAN_AMOUNT, ch, survey_times * request->n_channels); } else { _status = rtw_sitesurvey_cmd(padapter, ssid, RTW_SSID_SCAN_AMOUNT, NULL, 0); } spin_unlock_bh(&pmlmepriv->lock); - if (_status == false) ret = -1; @@ -1327,7 +1308,6 @@ static int cfg80211_rtw_scan(struct wiphy *wiphy exit: return ret; - } static int cfg80211_rtw_set_wiphy_params(struct wiphy *wiphy, u32 changed) @@ -1342,12 +1322,10 @@ static int rtw_cfg80211_set_wpa_version(struct security_priv *psecuritypriv, u32 return 0; } - if (wpa_version & (NL80211_WPA_VERSION_1 | NL80211_WPA_VERSION_2)) psecuritypriv->ndisauthtype = Ndis802_11AuthModeWPAPSK; return 0; - } static int rtw_cfg80211_set_auth_type(struct security_priv *psecuritypriv, @@ -1373,7 +1351,6 @@ static int rtw_cfg80211_set_auth_type(struct security_priv *psecuritypriv, psecuritypriv->ndisencryptstatus = Ndis802_11Encryption1Enabled; - break; default: psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Open; @@ -1381,7 +1358,6 @@ static int rtw_cfg80211_set_auth_type(struct security_priv *psecuritypriv, } return 0; - } static int rtw_cfg80211_set_cipher(struct security_priv *psecuritypriv, u32 cipher, bool ucast) @@ -1391,7 +1367,6 @@ static int rtw_cfg80211_set_cipher(struct security_priv *psecuritypriv, u32 ciph u32 *profile_cipher = ucast ? &psecuritypriv->dot11PrivacyAlgrthm : &psecuritypriv->dot118021XGrpPrivacy; - if (!cipher) { *profile_cipher = _NO_PRIVACY_; psecuritypriv->ndisencryptstatus = ndisencryptstatus; @@ -1603,7 +1578,6 @@ static int cfg80211_rtw_join_ibss(struct wiphy *wiphy, struct net_device *ndev, } if (params->ssid_len > IW_ESSID_MAX_SIZE) { - ret = -E2BIG; goto exit; } @@ -1671,7 +1645,6 @@ static int cfg80211_rtw_connect(struct wiphy *wiphy, struct net_device *ndev, padapter->mlmepriv.not_indic_disco = true; - if (adapter_wdev_data(padapter)->block == true) { ret = -EBUSY; goto exit; @@ -1694,7 +1667,6 @@ static int cfg80211_rtw_connect(struct wiphy *wiphy, struct net_device *ndev, } if (sme->ssid_len > IW_ESSID_MAX_SIZE) { - ret = -E2BIG; goto exit; } @@ -1889,7 +1861,6 @@ static int cfg80211_rtw_set_pmksa(struct wiphy *wiphy, /* overwrite PMKID */ for (index = 0 ; index < NUM_PMKID_CACHE; index++) { if (!memcmp(psecuritypriv->PMKIDList[index].Bssid, (u8 *)pmksa->bssid, ETH_ALEN)) { - memcpy(psecuritypriv->PMKIDList[index].PMKID, (u8 *)pmksa->pmkid, WLAN_PMKID_LEN); psecuritypriv->PMKIDList[index].bUsed = true; psecuritypriv->PMKIDIndex = index+1; @@ -1899,7 +1870,6 @@ static int cfg80211_rtw_set_pmksa(struct wiphy *wiphy, } if (!blInserted) { - memcpy(psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].Bssid, (u8 *)pmksa->bssid, ETH_ALEN); memcpy(psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].PMKID, (u8 *)pmksa->pmkid, WLAN_PMKID_LEN); @@ -2135,11 +2105,9 @@ static netdev_tx_t rtw_cfg80211_monitor_if_xmit_entry(struct sk_buff *skb, struc pattrib->seqnum = pmlmeext->mgnt_seq; pmlmeext->mgnt_seq++; - pattrib->last_txcmdsz = pattrib->pktlen; dump_mgntframe(padapter, pmgntframe); - } fail: @@ -2147,11 +2115,8 @@ static netdev_tx_t rtw_cfg80211_monitor_if_xmit_entry(struct sk_buff *skb, struc dev_kfree_skb_any(skb); return NETDEV_TX_OK; - } - - static const struct net_device_ops rtw_cfg80211_monitor_if_ops = { .ndo_start_xmit = rtw_cfg80211_monitor_if_xmit_entry, }; @@ -2324,7 +2289,6 @@ static int rtw_add_beacon(struct adapter *adapter, const u8 *head, size_t head_l else ret = -EINVAL; - kfree(pbuf); return ret; @@ -2404,7 +2368,6 @@ static int cfg80211_rtw_del_station(struct wiphy *wiphy, struct net_device *ndev return -EINVAL; } - spin_lock_bh(&pstapriv->asoc_list_lock); phead = &pstapriv->asoc_list; @@ -2423,9 +2386,7 @@ static int cfg80211_rtw_del_station(struct wiphy *wiphy, struct net_device *ndev break; } - } - } spin_unlock_bh(&pstapriv->asoc_list_lock); @@ -2433,7 +2394,6 @@ static int cfg80211_rtw_del_station(struct wiphy *wiphy, struct net_device *ndev associated_clients_update(padapter, updated); return ret; - } static int cfg80211_rtw_change_station(struct wiphy *wiphy, struct net_device *ndev, @@ -2465,7 +2425,6 @@ static struct sta_info *rtw_sta_info_get_by_idx(const int idx, struct sta_priv * static int cfg80211_rtw_dump_station(struct wiphy *wiphy, struct net_device *ndev, int idx, u8 *mac, struct station_info *sinfo) { - int ret = 0; struct adapter *padapter = rtw_netdev_priv(ndev); struct sta_info *psta = NULL; @@ -2568,7 +2527,6 @@ static int _cfg80211_rtw_mgmt_tx(struct adapter *padapter, u8 tx_ch, const u8 *b exit: return ret; - } static int cfg80211_rtw_mgmt_tx(struct wiphy *wiphy, @@ -2640,7 +2598,6 @@ static int cfg80211_rtw_mgmt_tx(struct wiphy *wiphy, static void rtw_cfg80211_init_ht_capab(struct ieee80211_sta_ht_cap *ht_cap, enum nl80211_band band) { - #define MAX_BIT_RATE_40MHZ_MCS15 300 /* Mbps */ #define MAX_BIT_RATE_40MHZ_MCS7 150 /* Mbps */ @@ -2692,12 +2649,10 @@ void rtw_cfg80211_init_wiphy(struct adapter *padapter) /* copy mac_addr to wiphy */ memcpy(wiphy->perm_addr, padapter->eeprompriv.mac_addr, ETH_ALEN); - } static void rtw_cfg80211_preinit_wiphy(struct adapter *padapter, struct wiphy *wiphy) { - wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; wiphy->max_scan_ssids = RTW_SSID_SCAN_AMOUNT; @@ -2810,7 +2765,7 @@ int rtw_wdev_alloc(struct adapter *padapter, struct device *dev) wdev->netdev = pnetdev; wdev->iftype = NL80211_IFTYPE_STATION; /* will be init in rtw_hal_init() */ - /* Must sync with _rtw_init_mlme_priv() */ + /* Must sync with _rtw_init_mlme_priv() */ /* pmlmepriv->fw_state = WIFI_STATION_STATE */ padapter->rtw_wdev = wdev; pnetdev->ieee80211_ptr = wdev; @@ -2844,7 +2799,6 @@ int rtw_wdev_alloc(struct adapter *padapter, struct device *dev) wiphy_free(wiphy); exit: return ret; - } void rtw_wdev_free(struct wireless_dev *wdev) diff --git a/drivers/staging/rts5208/rtsx.c b/drivers/staging/rts5208/rtsx.c index db2dd0baa8befdbbbe4ffbb4a6911b28509783c5..08543a3936da904ed58c68cdbd8d72a7a9e09bd1 100644 --- a/drivers/staging/rts5208/rtsx.c +++ b/drivers/staging/rts5208/rtsx.c @@ -382,27 +382,21 @@ static int rtsx_control_thread(void *__dev) if (chip->srb->sc_data_direction == DMA_BIDIRECTIONAL) { dev_err(&dev->pci->dev, "UNKNOWN data direction\n"); chip->srb->result = DID_ERROR << 16; - } - - /* reject if target != 0 or if LUN is higher than - * the maximum known LUN - */ - else if (chip->srb->device->id) { + } else if (chip->srb->device->id) { + /* reject if target != 0 or if LUN is higher than + * the maximum known LUN + */ dev_err(&dev->pci->dev, "Bad target number (%d:%d)\n", chip->srb->device->id, (u8)chip->srb->device->lun); chip->srb->result = DID_BAD_TARGET << 16; - } - - else if (chip->srb->device->lun > chip->max_lun) { + } else if (chip->srb->device->lun > chip->max_lun) { dev_err(&dev->pci->dev, "Bad LUN (%d:%d)\n", chip->srb->device->id, (u8)chip->srb->device->lun); chip->srb->result = DID_BAD_TARGET << 16; - } - - /* we've got a command, let's do it! */ - else { + } else { + /* we've got a command, let's do it! */ scsi_show_command(chip); rtsx_invoke_transport(chip->srb, chip); } diff --git a/drivers/staging/sm750fb/Kconfig b/drivers/staging/sm750fb/Kconfig index 1461c89701c3ac5550289599556e9e3f3a089f15..ab3d9b057d56bdcbdfed039ddc330ebc1e008c86 100644 --- a/drivers/staging/sm750fb/Kconfig +++ b/drivers/staging/sm750fb/Kconfig @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 config FB_SM750 tristate "Silicon Motion SM750 framebuffer support" - depends on FB && PCI + depends on FB && PCI && HAS_IOPORT select FB_MODE_HELPERS select FB_CFB_FILLRECT select FB_CFB_COPYAREA diff --git a/drivers/staging/vc04_services/include/linux/raspberrypi/vchiq.h b/drivers/staging/vc04_services/include/linux/raspberrypi/vchiq.h index 66965da114438aea387e64e86f634364bfa4ab43..52e106f117da1ff7d9a20eb7b2c68458d66bfcd4 100644 --- a/drivers/staging/vc04_services/include/linux/raspberrypi/vchiq.h +++ b/drivers/staging/vc04_services/include/linux/raspberrypi/vchiq.h @@ -78,8 +78,6 @@ struct vchiq_service_params_kernel { short version_min; /* Update for incompatible changes */ }; -struct vchiq_instance; - extern int vchiq_initialise(struct vchiq_instance **pinstance); extern int vchiq_shutdown(struct vchiq_instance *instance); extern int vchiq_connect(struct vchiq_instance *instance); diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c index 90a3958d1f297826d0e80a82c04a0ebc32acf4cb..aa2313f3bcab8c68479c34336cfb0c068a2fd18f 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c @@ -415,7 +415,7 @@ free_pagelist(struct vchiq_instance *instance, struct vchiq_pagelist_info *pagel pagelistinfo->scatterlist_mapped = 0; /* Deal with any partial cache lines (fragments) */ - if (pagelist->type >= PAGELIST_READ_WITH_FRAGMENTS) { + if (pagelist->type >= PAGELIST_READ_WITH_FRAGMENTS && g_fragments_base) { char *fragments = g_fragments_base + (pagelist->type - PAGELIST_READ_WITH_FRAGMENTS) * g_fragments_size; @@ -462,7 +462,7 @@ free_pagelist(struct vchiq_instance *instance, struct vchiq_pagelist_info *pagel cleanup_pagelistinfo(instance, pagelistinfo); } -int vchiq_platform_init(struct platform_device *pdev, struct vchiq_state *state) +static int vchiq_platform_init(struct platform_device *pdev, struct vchiq_state *state) { struct device *dev = &pdev->dev; struct vchiq_drvdata *drvdata = platform_get_drvdata(pdev); diff --git a/drivers/staging/vt6655/Kconfig b/drivers/staging/vt6655/Kconfig index d1cd5de46dcf2855b60722ed93f036280b38e9ed..077f62ebe80cddb6b269d98ee1c4767185913c9c 100644 --- a/drivers/staging/vt6655/Kconfig +++ b/drivers/staging/vt6655/Kconfig @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 config VT6655 tristate "VIA Technologies VT6655 support" - depends on PCI && MAC80211 && m + depends on PCI && HAS_IOPORT && MAC80211 && m help This is a vendor-written driver for VIA VT6655. diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index e33dd1b9c40e58474c480598976c11311474eb67..a4799589e469452050435de010660503e9c8d73c 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -8,27 +8,6 @@ * * linux-wlan * - * The contents of this file are subject to the Mozilla Public - * License Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * Alternatively, the contents of this file may be used under the - * terms of the GNU Public License version 2 (the "GPL"), in which - * case the provisions of the GPL are applicable instead of the - * above. If you wish to allow the use of your version of this file - * only under the terms of the GPL and not to allow others to use - * your version of this file under the MPL, indicate your decision - * by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL. If you do not delete - * the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * * -------------------------------------------------------------------- * * Inquiries regarding the linux-wlan Open Source project can be diff --git a/drivers/staging/wlan-ng/hfa384x_usb.c b/drivers/staging/wlan-ng/hfa384x_usb.c index c7cd54171d99439a7f52803c0f74c56d3fcb73e0..3e8c92675c82346c8695bffb40a6f0ac11a4a19a 100644 --- a/drivers/staging/wlan-ng/hfa384x_usb.c +++ b/drivers/staging/wlan-ng/hfa384x_usb.c @@ -8,27 +8,6 @@ * * linux-wlan * - * The contents of this file are subject to the Mozilla Public - * License Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * Alternatively, the contents of this file may be used under the - * terms of the GNU Public License version 2 (the "GPL"), in which - * case the provisions of the GPL are applicable instead of the - * above. If you wish to allow the use of your version of this file - * only under the terms of the GPL and not to allow others to use - * your version of this file under the MPL, indicate your decision - * by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL. If you do not delete - * the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * * -------------------------------------------------------------------- * * Inquiries regarding the linux-wlan Open Source project can be diff --git a/drivers/staging/wlan-ng/p80211conv.c b/drivers/staging/wlan-ng/p80211conv.c index cd271b1da69f648d45f2029ade5b1ca634715472..048e1c3fe19b321758936613c2a41ecb69f60820 100644 --- a/drivers/staging/wlan-ng/p80211conv.c +++ b/drivers/staging/wlan-ng/p80211conv.c @@ -8,27 +8,6 @@ * * linux-wlan * - * The contents of this file are subject to the Mozilla Public - * License Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * Alternatively, the contents of this file may be used under the - * terms of the GNU Public License version 2 (the "GPL"), in which - * case the provisions of the GPL are applicable instead of the - * above. If you wish to allow the use of your version of this file - * only under the terms of the GPL and not to allow others to use - * your version of this file under the MPL, indicate your decision - * by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL. If you do not delete - * the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * * -------------------------------------------------------------------- * * Inquiries regarding the linux-wlan Open Source project can be diff --git a/drivers/staging/wlan-ng/p80211conv.h b/drivers/staging/wlan-ng/p80211conv.h index dfb762bce84d07c38c98f43c70c15cee9fb50a37..45234769f45d6e2c815dd9fb8bb2598c59a781b3 100644 --- a/drivers/staging/wlan-ng/p80211conv.h +++ b/drivers/staging/wlan-ng/p80211conv.h @@ -8,27 +8,6 @@ * * linux-wlan * - * The contents of this file are subject to the Mozilla Public - * License Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * Alternatively, the contents of this file may be used under the - * terms of the GNU Public License version 2 (the "GPL"), in which - * case the provisions of the GPL are applicable instead of the - * above. If you wish to allow the use of your version of this file - * only under the terms of the GPL and not to allow others to use - * your version of this file under the MPL, indicate your decision - * by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL. If you do not delete - * the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * * -------------------------------------------------------------------- * * Inquiries regarding the linux-wlan Open Source project can be diff --git a/drivers/staging/wlan-ng/p80211hdr.h b/drivers/staging/wlan-ng/p80211hdr.h index 93195a4c5b014a301d231655b460b23ba16456ee..7ea1c8ec05ed055b322e5b32a209b1e943367ab0 100644 --- a/drivers/staging/wlan-ng/p80211hdr.h +++ b/drivers/staging/wlan-ng/p80211hdr.h @@ -8,27 +8,6 @@ * * linux-wlan * - * The contents of this file are subject to the Mozilla Public - * License Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * Alternatively, the contents of this file may be used under the - * terms of the GNU Public License version 2 (the "GPL"), in which - * case the provisions of the GPL are applicable instead of the - * above. If you wish to allow the use of your version of this file - * only under the terms of the GPL and not to allow others to use - * your version of this file under the MPL, indicate your decision - * by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL. If you do not delete - * the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * * -------------------------------------------------------------------- * * Inquiries regarding the linux-wlan Open Source project can be diff --git a/drivers/staging/wlan-ng/p80211ioctl.h b/drivers/staging/wlan-ng/p80211ioctl.h index b50ce11147dd784c45bc6fbccb097fc688fb2031..176e327a45bc4bd9c5c8639a5295bc32048561ec 100644 --- a/drivers/staging/wlan-ng/p80211ioctl.h +++ b/drivers/staging/wlan-ng/p80211ioctl.h @@ -8,27 +8,6 @@ * * linux-wlan * - * The contents of this file are subject to the Mozilla Public - * License Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * Alternatively, the contents of this file may be used under the - * terms of the GNU Public License version 2 (the "GPL"), in which - * case the provisions of the GPL are applicable instead of the - * above. If you wish to allow the use of your version of this file - * only under the terms of the GPL and not to allow others to use - * your version of this file under the MPL, indicate your decision - * by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL. If you do not delete - * the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * * -------------------------------------------------------------------- * * Inquiries regarding the linux-wlan Open Source project can be diff --git a/drivers/staging/wlan-ng/p80211metadef.h b/drivers/staging/wlan-ng/p80211metadef.h index 1b91b64c12ed1a6a0527f555b7775dac1ae59113..1cbb4b67a9a6a63df6f361074af77d012771b6a3 100644 --- a/drivers/staging/wlan-ng/p80211metadef.h +++ b/drivers/staging/wlan-ng/p80211metadef.h @@ -6,27 +6,6 @@ * * linux-wlan * - * The contents of this file are subject to the Mozilla Public - * License Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * Alternatively, the contents of this file may be used under the - * terms of the GNU Public License version 2 (the "GPL"), in which - * case the provisions of the GPL are applicable instead of the - * above. If you wish to allow the use of your version of this file - * only under the terms of the GPL and not to allow others to use - * your version of this file under the MPL, indicate your decision - * by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL. If you do not delete - * the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * * -------------------------------------------------------------------- * * Inquiries regarding the linux-wlan Open Source project can be diff --git a/drivers/staging/wlan-ng/p80211metastruct.h b/drivers/staging/wlan-ng/p80211metastruct.h index 4adc64580185a14c56fce2ac3be0e6d99bbd1e2e..a52217c9b953530a50b9b3c3e0e84f2b91040319 100644 --- a/drivers/staging/wlan-ng/p80211metastruct.h +++ b/drivers/staging/wlan-ng/p80211metastruct.h @@ -6,27 +6,6 @@ * * linux-wlan * - * The contents of this file are subject to the Mozilla Public - * License Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * Alternatively, the contents of this file may be used under the - * terms of the GNU Public License version 2 (the "GPL"), in which - * case the provisions of the GPL are applicable instead of the - * above. If you wish to allow the use of your version of this file - * only under the terms of the GPL and not to allow others to use - * your version of this file under the MPL, indicate your decision - * by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL. If you do not delete - * the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * * -------------------------------------------------------------------- * * Inquiries regarding the linux-wlan Open Source project can be @@ -114,22 +93,8 @@ struct p80211msg_dot11req_scan_results { struct p80211item_uint32 cfpollreq; struct p80211item_uint32 privacy; struct p80211item_uint32 capinfo; - struct p80211item_uint32 basicrate1; - struct p80211item_uint32 basicrate2; - struct p80211item_uint32 basicrate3; - struct p80211item_uint32 basicrate4; - struct p80211item_uint32 basicrate5; - struct p80211item_uint32 basicrate6; - struct p80211item_uint32 basicrate7; - struct p80211item_uint32 basicrate8; - struct p80211item_uint32 supprate1; - struct p80211item_uint32 supprate2; - struct p80211item_uint32 supprate3; - struct p80211item_uint32 supprate4; - struct p80211item_uint32 supprate5; - struct p80211item_uint32 supprate6; - struct p80211item_uint32 supprate7; - struct p80211item_uint32 supprate8; + struct p80211item_uint32 basicrate[8]; + struct p80211item_uint32 supprate[8]; } __packed; struct p80211msg_dot11req_start { diff --git a/drivers/staging/wlan-ng/p80211mgmt.h b/drivers/staging/wlan-ng/p80211mgmt.h index fc23fae5651b9ecef550cc89a65bb65fab1aca3e..7ffc202d90074b4b1f5c1b0ee2f0457b9b64bb27 100644 --- a/drivers/staging/wlan-ng/p80211mgmt.h +++ b/drivers/staging/wlan-ng/p80211mgmt.h @@ -8,27 +8,6 @@ * * linux-wlan * - * The contents of this file are subject to the Mozilla Public - * License Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * Alternatively, the contents of this file may be used under the - * terms of the GNU Public License version 2 (the "GPL"), in which - * case the provisions of the GPL are applicable instead of the - * above. If you wish to allow the use of your version of this file - * only under the terms of the GPL and not to allow others to use - * your version of this file under the MPL, indicate your decision - * by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL. If you do not delete - * the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * * -------------------------------------------------------------------- * * Inquiries regarding the linux-wlan Open Source project can be diff --git a/drivers/staging/wlan-ng/p80211msg.h b/drivers/staging/wlan-ng/p80211msg.h index f68d8b7d5ad88319c5a21cd067ccf6bb471b3b54..d56bc6079ed4f8182c62760c701f447dfad39168 100644 --- a/drivers/staging/wlan-ng/p80211msg.h +++ b/drivers/staging/wlan-ng/p80211msg.h @@ -8,27 +8,6 @@ * * linux-wlan * - * The contents of this file are subject to the Mozilla Public - * License Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * Alternatively, the contents of this file may be used under the - * terms of the GNU Public License version 2 (the "GPL"), in which - * case the provisions of the GPL are applicable instead of the - * above. If you wish to allow the use of your version of this file - * only under the terms of the GPL and not to allow others to use - * your version of this file under the MPL, indicate your decision - * by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL. If you do not delete - * the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * * -------------------------------------------------------------------- * * Inquiries regarding the linux-wlan Open Source project can be diff --git a/drivers/staging/wlan-ng/p80211netdev.c b/drivers/staging/wlan-ng/p80211netdev.c index 6bef419e8ad0c8a05c1a546693d9ed179fb85ea3..8634fc89a6c22f1db61492ba30774ee8a789cfb1 100644 --- a/drivers/staging/wlan-ng/p80211netdev.c +++ b/drivers/staging/wlan-ng/p80211netdev.c @@ -8,27 +8,6 @@ * * linux-wlan * - * The contents of this file are subject to the Mozilla Public - * License Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * Alternatively, the contents of this file may be used under the - * terms of the GNU Public License version 2 (the "GPL"), in which - * case the provisions of the GPL are applicable instead of the - * above. If you wish to allow the use of your version of this file - * only under the terms of the GPL and not to allow others to use - * your version of this file under the MPL, indicate your decision - * by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL. If you do not delete - * the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * * -------------------------------------------------------------------- * * Inquiries regarding the linux-wlan Open Source project can be diff --git a/drivers/staging/wlan-ng/p80211netdev.h b/drivers/staging/wlan-ng/p80211netdev.h index 1cee51a1075ed6e646d32f70bc04b556e3d0a2de..f5186380b6290aca368151f9af6261a13b02fc55 100644 --- a/drivers/staging/wlan-ng/p80211netdev.h +++ b/drivers/staging/wlan-ng/p80211netdev.h @@ -8,27 +8,6 @@ * * linux-wlan * - * The contents of this file are subject to the Mozilla Public - * License Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * Alternatively, the contents of this file may be used under the - * terms of the GNU Public License version 2 (the "GPL"), in which - * case the provisions of the GPL are applicable instead of the - * above. If you wish to allow the use of your version of this file - * only under the terms of the GPL and not to allow others to use - * your version of this file under the MPL, indicate your decision - * by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL. If you do not delete - * the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * * -------------------------------------------------------------------- * * Inquiries regarding the linux-wlan Open Source project can be diff --git a/drivers/staging/wlan-ng/p80211req.c b/drivers/staging/wlan-ng/p80211req.c index 809cf3d480e952d64bbbe50aa1375bcaf4a38755..6ec559ffd2f9917c8b3afae763e54ab7409fc415 100644 --- a/drivers/staging/wlan-ng/p80211req.c +++ b/drivers/staging/wlan-ng/p80211req.c @@ -8,27 +8,6 @@ * * linux-wlan * - * The contents of this file are subject to the Mozilla Public - * License Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * Alternatively, the contents of this file may be used under the - * terms of the GNU Public License version 2 (the "GPL"), in which - * case the provisions of the GPL are applicable instead of the - * above. If you wish to allow the use of your version of this file - * only under the terms of the GPL and not to allow others to use - * your version of this file under the MPL, indicate your decision - * by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL. If you do not delete - * the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * * -------------------------------------------------------------------- * * Inquiries regarding the linux-wlan Open Source project can be diff --git a/drivers/staging/wlan-ng/p80211req.h b/drivers/staging/wlan-ng/p80211req.h index bc45cd5f91e464881bf071118a8868b7052ae23f..39213f73913c5686da1275fb97a891f435e21e73 100644 --- a/drivers/staging/wlan-ng/p80211req.h +++ b/drivers/staging/wlan-ng/p80211req.h @@ -8,27 +8,6 @@ * * linux-wlan * - * The contents of this file are subject to the Mozilla Public - * License Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * Alternatively, the contents of this file may be used under the - * terms of the GNU Public License version 2 (the "GPL"), in which - * case the provisions of the GPL are applicable instead of the - * above. If you wish to allow the use of your version of this file - * only under the terms of the GPL and not to allow others to use - * your version of this file under the MPL, indicate your decision - * by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL. If you do not delete - * the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * * -------------------------------------------------------------------- * * Inquiries regarding the linux-wlan Open Source project can be diff --git a/drivers/staging/wlan-ng/p80211types.h b/drivers/staging/wlan-ng/p80211types.h index b2ed969604133e59424d01b957ca4b120585b97a..5e4ea5f92058e5bde331f064139da5991607fb25 100644 --- a/drivers/staging/wlan-ng/p80211types.h +++ b/drivers/staging/wlan-ng/p80211types.h @@ -9,27 +9,6 @@ * * linux-wlan * - * The contents of this file are subject to the Mozilla Public - * License Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * Alternatively, the contents of this file may be used under the - * terms of the GNU Public License version 2 (the "GPL"), in which - * case the provisions of the GPL are applicable instead of the - * above. If you wish to allow the use of your version of this file - * only under the terms of the GPL and not to allow others to use - * your version of this file under the MPL, indicate your decision - * by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL. If you do not delete - * the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * * -------------------------------------------------------------------- * * Inquiries regarding the linux-wlan Open Source project can be diff --git a/drivers/staging/wlan-ng/p80211wep.c b/drivers/staging/wlan-ng/p80211wep.c index 3ff7ee7011df352d1de9f21d9a8183198fc7968a..e7b26b057124ab364362b15c5286367bf930b6f3 100644 --- a/drivers/staging/wlan-ng/p80211wep.c +++ b/drivers/staging/wlan-ng/p80211wep.c @@ -8,27 +8,6 @@ * * linux-wlan * - * The contents of this file are subject to the Mozilla Public - * License Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * Alternatively, the contents of this file may be used under the - * terms of the GNU Public License version 2 (the "GPL"), in which - * case the provisions of the GPL are applicable instead of the - * above. If you wish to allow the use of your version of this file - * only under the terms of the GPL and not to allow others to use - * your version of this file under the MPL, indicate your decision - * by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL. If you do not delete - * the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * * -------------------------------------------------------------------- * * Inquiries regarding the linux-wlan Open Source project can be diff --git a/drivers/staging/wlan-ng/prism2fw.c b/drivers/staging/wlan-ng/prism2fw.c index 11658865ca50502bba84458b66d000dcf94ef228..5d03b2b9aab40a89444844a6c217da11594172d3 100644 --- a/drivers/staging/wlan-ng/prism2fw.c +++ b/drivers/staging/wlan-ng/prism2fw.c @@ -8,27 +8,6 @@ * * linux-wlan * - * The contents of this file are subject to the Mozilla Public - * License Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * Alternatively, the contents of this file may be used under the - * terms of the GNU Public License version 2 (the "GPL"), in which - * case the provisions of the GPL are applicable instead of the - * above. If you wish to allow the use of your version of this file - * only under the terms of the GPL and not to allow others to use - * your version of this file under the MPL, indicate your decision - * by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL. If you do not delete - * the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * * -------------------------------------------------------------------- * * Inquiries regarding the linux-wlan Open Source project can be diff --git a/drivers/staging/wlan-ng/prism2mgmt.c b/drivers/staging/wlan-ng/prism2mgmt.c index 9030a8939a9bf307015b56f832010f6048571d3d..d5737166564eb40aa7b10a6ddb88669f218aa489 100644 --- a/drivers/staging/wlan-ng/prism2mgmt.c +++ b/drivers/staging/wlan-ng/prism2mgmt.c @@ -8,27 +8,6 @@ * * linux-wlan * - * The contents of this file are subject to the Mozilla Public - * License Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * Alternatively, the contents of this file may be used under the - * terms of the GNU Public License version 2 (the "GPL"), in which - * case the provisions of the GPL are applicable instead of the - * above. If you wish to allow the use of your version of this file - * only under the terms of the GPL and not to allow others to use - * your version of this file under the MPL, indicate your decision - * by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL. If you do not delete - * the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * * -------------------------------------------------------------------- * * Inquiries regarding the linux-wlan Open Source project can be @@ -437,42 +416,22 @@ int prism2mgmt_scan_results(struct wlandevice *wlandev, void *msgp) if (item->supprates[count] == 0) break; -#define REQBASICRATE(N) \ - do { \ - if ((count >= (N)) && DOT11_RATE5_ISBASIC_GET( \ - item->supprates[(N) - 1])) { \ - req->basicrate ## N .data = item->supprates[(N) - 1]; \ - req->basicrate ## N .status = \ - P80211ENUM_msgitem_status_data_ok; \ - } \ - } while (0) - - REQBASICRATE(1); - REQBASICRATE(2); - REQBASICRATE(3); - REQBASICRATE(4); - REQBASICRATE(5); - REQBASICRATE(6); - REQBASICRATE(7); - REQBASICRATE(8); - -#define REQSUPPRATE(N) \ - do { \ - if (count >= (N)) { \ - req->supprate ## N .data = item->supprates[(N) - 1]; \ - req->supprate ## N .status = \ - P80211ENUM_msgitem_status_data_ok; \ - } \ - } while (0) - - REQSUPPRATE(1); - REQSUPPRATE(2); - REQSUPPRATE(3); - REQSUPPRATE(4); - REQSUPPRATE(5); - REQSUPPRATE(6); - REQSUPPRATE(7); - REQSUPPRATE(8); + for (int i = 0; i < 8; i++) { + if (count > i && + DOT11_RATE5_ISBASIC_GET(item->supprates[i])) { + req->basicrate[i].data = item->supprates[i]; + req->basicrate[i].status = + P80211ENUM_msgitem_status_data_ok; + } + } + + for (int i = 0; i < 8; i++) { + if (count > i) { + req->supprate[i].data = item->supprates[i]; + req->supprate[i].status = + P80211ENUM_msgitem_status_data_ok; + } + } /* beacon period */ req->beaconperiod.status = P80211ENUM_msgitem_status_data_ok; diff --git a/drivers/staging/wlan-ng/prism2mgmt.h b/drivers/staging/wlan-ng/prism2mgmt.h index 7132cec2d7eb807da490c31625ad1d8b99faee3b..083a055ee986625cfcda268167fae51827f0d150 100644 --- a/drivers/staging/wlan-ng/prism2mgmt.h +++ b/drivers/staging/wlan-ng/prism2mgmt.h @@ -8,27 +8,6 @@ * * linux-wlan * - * The contents of this file are subject to the Mozilla Public - * License Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * Alternatively, the contents of this file may be used under the - * terms of the GNU Public License version 2 (the "GPL"), in which - * case the provisions of the GPL are applicable instead of the - * above. If you wish to allow the use of your version of this file - * only under the terms of the GPL and not to allow others to use - * your version of this file under the MPL, indicate your decision - * by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL. If you do not delete - * the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * * -------------------------------------------------------------------- * * Inquiries regarding the linux-wlan Open Source project can be diff --git a/drivers/staging/wlan-ng/prism2mib.c b/drivers/staging/wlan-ng/prism2mib.c index fcf8313870af484dd0f31b54946f43a27699c137..4346b90c1a770e25161d98fc3c76d9c7a377dcd1 100644 --- a/drivers/staging/wlan-ng/prism2mib.c +++ b/drivers/staging/wlan-ng/prism2mib.c @@ -8,27 +8,6 @@ * * linux-wlan * - * The contents of this file are subject to the Mozilla Public - * License Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * Alternatively, the contents of this file may be used under the - * terms of the GNU Public License version 2 (the "GPL"), in which - * case the provisions of the GPL are applicable instead of the - * above. If you wish to allow the use of your version of this file - * only under the terms of the GPL and not to allow others to use - * your version of this file under the MPL, indicate your decision - * by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL. If you do not delete - * the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * * -------------------------------------------------------------------- * * Inquiries regarding the linux-wlan Open Source project can be diff --git a/drivers/staging/wlan-ng/prism2sta.c b/drivers/staging/wlan-ng/prism2sta.c index daa7cc4e897c91cbef35b96622c31aafbfc256e8..57180bb71699f7539a051bb3ad46f43b6a6c4dc0 100644 --- a/drivers/staging/wlan-ng/prism2sta.c +++ b/drivers/staging/wlan-ng/prism2sta.c @@ -8,27 +8,6 @@ * * linux-wlan * - * The contents of this file are subject to the Mozilla Public - * License Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * Alternatively, the contents of this file may be used under the - * terms of the GNU Public License version 2 (the "GPL"), in which - * case the provisions of the GPL are applicable instead of the - * above. If you wish to allow the use of your version of this file - * only under the terms of the GPL and not to allow others to use - * your version of this file under the MPL, indicate your decision - * by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL. If you do not delete - * the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * * -------------------------------------------------------------------- * * Inquiries regarding the linux-wlan Open Source project can be diff --git a/drivers/target/iscsi/iscsi_target_parameters.c b/drivers/target/iscsi/iscsi_target_parameters.c index 557516c642c3b037e8ffd04393c24b0b37e4a27e..5b90c22ee3dc48a52126f9d6723747870185aa53 100644 --- a/drivers/target/iscsi/iscsi_target_parameters.c +++ b/drivers/target/iscsi/iscsi_target_parameters.c @@ -726,8 +726,8 @@ static int iscsi_add_notunderstood_response( } INIT_LIST_HEAD(&extra_response->er_list); - strlcpy(extra_response->key, key, sizeof(extra_response->key)); - strlcpy(extra_response->value, NOTUNDERSTOOD, + strscpy(extra_response->key, key, sizeof(extra_response->key)); + strscpy(extra_response->value, NOTUNDERSTOOD, sizeof(extra_response->value)); list_add_tail(&extra_response->er_list, diff --git a/drivers/target/iscsi/iscsi_target_util.c b/drivers/target/iscsi/iscsi_target_util.c index b14835fcb03344780b764bbeeee21bbf53838b86..91a75a4a7cc1a781acdba96103ad9725f1f09371 100644 --- a/drivers/target/iscsi/iscsi_target_util.c +++ b/drivers/target/iscsi/iscsi_target_util.c @@ -1129,6 +1129,8 @@ int iscsit_fe_sendpage_sg( struct iscsit_conn *conn) { struct scatterlist *sg = cmd->first_data_sg; + struct bio_vec bvec; + struct msghdr msghdr = { .msg_flags = MSG_SPLICE_PAGES, }; struct kvec iov; u32 tx_hdr_size, data_len; u32 offset = cmd->first_data_sg_off; @@ -1172,17 +1174,18 @@ int iscsit_fe_sendpage_sg( u32 space = (sg->length - offset); u32 sub_len = min_t(u32, data_len, space); send_pg: - tx_sent = conn->sock->ops->sendpage(conn->sock, - sg_page(sg), sg->offset + offset, sub_len, 0); + bvec_set_page(&bvec, sg_page(sg), sub_len, sg->offset + offset); + iov_iter_bvec(&msghdr.msg_iter, ITER_SOURCE, &bvec, 1, sub_len); + + tx_sent = conn->sock->ops->sendmsg(conn->sock, &msghdr, + sub_len); if (tx_sent != sub_len) { if (tx_sent == -EAGAIN) { - pr_err("tcp_sendpage() returned" - " -EAGAIN\n"); + pr_err("sendmsg/splice returned -EAGAIN\n"); goto send_pg; } - pr_err("tcp_sendpage() failure: %d\n", - tx_sent); + pr_err("sendmsg/splice failure: %d\n", tx_sent); return -1; } @@ -1372,7 +1375,7 @@ void iscsit_collect_login_stats( if (conn->param_list) intrname = iscsi_find_param_from_key(INITIATORNAME, conn->param_list); - strlcpy(ls->last_intr_fail_name, + strscpy(ls->last_intr_fail_name, (intrname ? intrname->value : "Unknown"), sizeof(ls->last_intr_fail_name)); @@ -1411,7 +1414,7 @@ void iscsit_fill_cxn_timeout_err_stats(struct iscsit_session *sess) return; spin_lock_bh(&tiqn->sess_err_stats.lock); - strlcpy(tiqn->sess_err_stats.last_sess_fail_rem_name, + strscpy(tiqn->sess_err_stats.last_sess_fail_rem_name, sess->sess_ops->InitiatorName, sizeof(tiqn->sess_err_stats.last_sess_fail_rem_name)); tiqn->sess_err_stats.last_sess_failure_type = diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c index 74b67c346dfe9c2e0575368a6e7c11c4f2e861b1..936e5ff1b209ecb9df704766d214326eee5e811d 100644 --- a/drivers/target/target_core_configfs.c +++ b/drivers/target/target_core_configfs.c @@ -649,7 +649,7 @@ static void dev_set_t10_wwn_model_alias(struct se_device *dev) * here without potentially breaking existing setups, so continue to * truncate one byte shorter than what can be carried in INQUIRY. */ - strlcpy(dev->t10_wwn.model, configname, INQUIRY_MODEL_LEN); + strscpy(dev->t10_wwn.model, configname, INQUIRY_MODEL_LEN); } static ssize_t emulate_model_alias_store(struct config_item *item, @@ -675,7 +675,7 @@ static ssize_t emulate_model_alias_store(struct config_item *item, if (flag) { dev_set_t10_wwn_model_alias(dev); } else { - strlcpy(dev->t10_wwn.model, dev->transport->inquiry_prod, + strscpy(dev->t10_wwn.model, dev->transport->inquiry_prod, sizeof(dev->t10_wwn.model)); } da->emulate_model_alias = flag; @@ -1426,7 +1426,7 @@ static ssize_t target_wwn_vendor_id_store(struct config_item *item, } BUILD_BUG_ON(sizeof(dev->t10_wwn.vendor) != INQUIRY_VENDOR_LEN + 1); - strlcpy(dev->t10_wwn.vendor, stripped, sizeof(dev->t10_wwn.vendor)); + strscpy(dev->t10_wwn.vendor, stripped, sizeof(dev->t10_wwn.vendor)); pr_debug("Target_Core_ConfigFS: Set emulated T10 Vendor Identification:" " %s\n", dev->t10_wwn.vendor); @@ -1482,7 +1482,7 @@ static ssize_t target_wwn_product_id_store(struct config_item *item, } BUILD_BUG_ON(sizeof(dev->t10_wwn.model) != INQUIRY_MODEL_LEN + 1); - strlcpy(dev->t10_wwn.model, stripped, sizeof(dev->t10_wwn.model)); + strscpy(dev->t10_wwn.model, stripped, sizeof(dev->t10_wwn.model)); pr_debug("Target_Core_ConfigFS: Set emulated T10 Model Identification: %s\n", dev->t10_wwn.model); @@ -1538,7 +1538,7 @@ static ssize_t target_wwn_revision_store(struct config_item *item, } BUILD_BUG_ON(sizeof(dev->t10_wwn.revision) != INQUIRY_REVISION_LEN + 1); - strlcpy(dev->t10_wwn.revision, stripped, sizeof(dev->t10_wwn.revision)); + strscpy(dev->t10_wwn.revision, stripped, sizeof(dev->t10_wwn.revision)); pr_debug("Target_Core_ConfigFS: Set emulated T10 Revision: %s\n", dev->t10_wwn.revision); diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index 90f3f492617242442cd638e25ca360db58f11585..b7ac60f4a21945b1545e7d7112f09efe2e906a69 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c @@ -789,10 +789,10 @@ struct se_device *target_alloc_device(struct se_hba *hba, const char *name) xcopy_lun->lun_tpg = &xcopy_pt_tpg; /* Preload the default INQUIRY const values */ - strlcpy(dev->t10_wwn.vendor, "LIO-ORG", sizeof(dev->t10_wwn.vendor)); - strlcpy(dev->t10_wwn.model, dev->transport->inquiry_prod, + strscpy(dev->t10_wwn.vendor, "LIO-ORG", sizeof(dev->t10_wwn.vendor)); + strscpy(dev->t10_wwn.model, dev->transport->inquiry_prod, sizeof(dev->t10_wwn.model)); - strlcpy(dev->t10_wwn.revision, dev->transport->inquiry_rev, + strscpy(dev->t10_wwn.revision, dev->transport->inquiry_rev, sizeof(dev->t10_wwn.revision)); return dev; diff --git a/drivers/target/target_core_file.c b/drivers/target/target_core_file.c index ce0e000b74fc39cda2ede86d585e4e423b4b24d7..4d447520bab87d6133ba2611f37c4955e641fe5c 100644 --- a/drivers/target/target_core_file.c +++ b/drivers/target/target_core_file.c @@ -896,7 +896,7 @@ static void fd_free_prot(struct se_device *dev) fd_dev->fd_prot_file = NULL; } -static struct sbc_ops fd_sbc_ops = { +static struct exec_cmd_ops fd_exec_cmd_ops = { .execute_rw = fd_execute_rw, .execute_sync_cache = fd_execute_sync_cache, .execute_write_same = fd_execute_write_same, @@ -906,7 +906,7 @@ static struct sbc_ops fd_sbc_ops = { static sense_reason_t fd_parse_cdb(struct se_cmd *cmd) { - return sbc_parse_cdb(cmd, &fd_sbc_ops); + return sbc_parse_cdb(cmd, &fd_exec_cmd_ops); } static const struct target_backend_ops fileio_ops = { diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c index cc838ffd129472ef14b8fa2e4f2a77129e974d3b..3d1b511ea284b0b71de47f99e830255cf8630284 100644 --- a/drivers/target/target_core_iblock.c +++ b/drivers/target/target_core_iblock.c @@ -23,13 +23,16 @@ #include #include #include +#include #include +#include #include #include #include #include "target_core_iblock.h" +#include "target_core_pr.h" #define IBLOCK_MAX_BIO_PER_TASK 32 /* max # of bios to submit at a time */ #define IBLOCK_BIO_POOL_SIZE 128 @@ -90,7 +93,7 @@ static int iblock_configure_device(struct se_device *dev) struct request_queue *q; struct block_device *bd = NULL; struct blk_integrity *bi; - fmode_t mode; + blk_mode_t mode = BLK_OPEN_READ; unsigned int max_write_zeroes_sectors; int ret; @@ -108,13 +111,12 @@ static int iblock_configure_device(struct se_device *dev) pr_debug( "IBLOCK: Claiming struct block_device: %s\n", ib_dev->ibd_udev_path); - mode = FMODE_READ|FMODE_EXCL; if (!ib_dev->ibd_readonly) - mode |= FMODE_WRITE; + mode |= BLK_OPEN_WRITE; else dev->dev_flags |= DF_READ_ONLY; - bd = blkdev_get_by_path(ib_dev->ibd_udev_path, mode, ib_dev); + bd = blkdev_get_by_path(ib_dev->ibd_udev_path, mode, ib_dev, NULL); if (IS_ERR(bd)) { ret = PTR_ERR(bd); goto out_free_bioset; @@ -175,7 +177,7 @@ static int iblock_configure_device(struct se_device *dev) return 0; out_blkdev_put: - blkdev_put(ib_dev->ibd_bd, FMODE_WRITE|FMODE_READ|FMODE_EXCL); + blkdev_put(ib_dev->ibd_bd, ib_dev); out_free_bioset: bioset_exit(&ib_dev->ibd_bio_set); out: @@ -201,7 +203,7 @@ static void iblock_destroy_device(struct se_device *dev) struct iblock_dev *ib_dev = IBLOCK_DEV(dev); if (ib_dev->ibd_bd != NULL) - blkdev_put(ib_dev->ibd_bd, FMODE_WRITE|FMODE_READ|FMODE_EXCL); + blkdev_put(ib_dev->ibd_bd, ib_dev); bioset_exit(&ib_dev->ibd_bio_set); } @@ -310,7 +312,7 @@ static sector_t iblock_get_blocks(struct se_device *dev) return blocks_long; } -static void iblock_complete_cmd(struct se_cmd *cmd) +static void iblock_complete_cmd(struct se_cmd *cmd, blk_status_t blk_status) { struct iblock_req *ibr = cmd->priv; u8 status; @@ -318,7 +320,9 @@ static void iblock_complete_cmd(struct se_cmd *cmd) if (!refcount_dec_and_test(&ibr->pending)) return; - if (atomic_read(&ibr->ib_bio_err_cnt)) + if (blk_status == BLK_STS_RESV_CONFLICT) + status = SAM_STAT_RESERVATION_CONFLICT; + else if (atomic_read(&ibr->ib_bio_err_cnt)) status = SAM_STAT_CHECK_CONDITION; else status = SAM_STAT_GOOD; @@ -331,6 +335,7 @@ static void iblock_bio_done(struct bio *bio) { struct se_cmd *cmd = bio->bi_private; struct iblock_req *ibr = cmd->priv; + blk_status_t blk_status = bio->bi_status; if (bio->bi_status) { pr_err("bio error: %p, err: %d\n", bio, bio->bi_status); @@ -343,7 +348,7 @@ static void iblock_bio_done(struct bio *bio) bio_put(bio); - iblock_complete_cmd(cmd); + iblock_complete_cmd(cmd, blk_status); } static struct bio *iblock_get_bio(struct se_cmd *cmd, sector_t lba, u32 sg_num, @@ -759,7 +764,7 @@ iblock_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents, if (!sgl_nents) { refcount_set(&ibr->pending, 1); - iblock_complete_cmd(cmd); + iblock_complete_cmd(cmd, BLK_STS_OK); return 0; } @@ -817,7 +822,7 @@ iblock_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents, } iblock_submit_bios(&list); - iblock_complete_cmd(cmd); + iblock_complete_cmd(cmd, BLK_STS_OK); return 0; fail_put_bios: @@ -829,6 +834,258 @@ iblock_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents, return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; } +static sense_reason_t iblock_execute_pr_out(struct se_cmd *cmd, u8 sa, u64 key, + u64 sa_key, u8 type, bool aptpl) +{ + struct se_device *dev = cmd->se_dev; + struct iblock_dev *ib_dev = IBLOCK_DEV(dev); + struct block_device *bdev = ib_dev->ibd_bd; + const struct pr_ops *ops = bdev->bd_disk->fops->pr_ops; + int ret; + + if (!ops) { + pr_err("Block device does not support pr_ops but iblock device has been configured for PR passthrough.\n"); + return TCM_UNSUPPORTED_SCSI_OPCODE; + } + + switch (sa) { + case PRO_REGISTER: + case PRO_REGISTER_AND_IGNORE_EXISTING_KEY: + if (!ops->pr_register) { + pr_err("block device does not support pr_register.\n"); + return TCM_UNSUPPORTED_SCSI_OPCODE; + } + + /* The block layer pr ops always enables aptpl */ + if (!aptpl) + pr_info("APTPL not set by initiator, but will be used.\n"); + + ret = ops->pr_register(bdev, key, sa_key, + sa == PRO_REGISTER ? 0 : PR_FL_IGNORE_KEY); + break; + case PRO_RESERVE: + if (!ops->pr_reserve) { + pr_err("block_device does not support pr_reserve.\n"); + return TCM_UNSUPPORTED_SCSI_OPCODE; + } + + ret = ops->pr_reserve(bdev, key, scsi_pr_type_to_block(type), 0); + break; + case PRO_CLEAR: + if (!ops->pr_clear) { + pr_err("block_device does not support pr_clear.\n"); + return TCM_UNSUPPORTED_SCSI_OPCODE; + } + + ret = ops->pr_clear(bdev, key); + break; + case PRO_PREEMPT: + case PRO_PREEMPT_AND_ABORT: + if (!ops->pr_clear) { + pr_err("block_device does not support pr_preempt.\n"); + return TCM_UNSUPPORTED_SCSI_OPCODE; + } + + ret = ops->pr_preempt(bdev, key, sa_key, + scsi_pr_type_to_block(type), + sa == PRO_PREEMPT_AND_ABORT); + break; + case PRO_RELEASE: + if (!ops->pr_clear) { + pr_err("block_device does not support pr_pclear.\n"); + return TCM_UNSUPPORTED_SCSI_OPCODE; + } + + ret = ops->pr_release(bdev, key, scsi_pr_type_to_block(type)); + break; + default: + pr_err("Unknown PERSISTENT_RESERVE_OUT SA: 0x%02x\n", sa); + return TCM_UNSUPPORTED_SCSI_OPCODE; + } + + if (!ret) + return TCM_NO_SENSE; + else if (ret == PR_STS_RESERVATION_CONFLICT) + return TCM_RESERVATION_CONFLICT; + else + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; +} + +static void iblock_pr_report_caps(unsigned char *param_data) +{ + u16 len = 8; + + put_unaligned_be16(len, ¶m_data[0]); + /* + * When using the pr_ops passthrough method we only support exporting + * the device through one target port because from the backend module + * level we can't see the target port config. As a result we only + * support registration directly from the I_T nexus the cmd is sent + * through and do not set ATP_C here. + * + * The block layer pr_ops do not support passing in initiators so + * we don't set SIP_C here. + */ + /* PTPL_C: Persistence across Target Power Loss bit */ + param_data[2] |= 0x01; + /* + * We are filling in the PERSISTENT RESERVATION TYPE MASK below, so + * set the TMV: Task Mask Valid bit. + */ + param_data[3] |= 0x80; + /* + * Change ALLOW COMMANDs to 0x20 or 0x40 later from Table 166 + */ + param_data[3] |= 0x10; /* ALLOW COMMANDs field 001b */ + /* + * PTPL_A: Persistence across Target Power Loss Active bit. The block + * layer pr ops always enables this so report it active. + */ + param_data[3] |= 0x01; + /* + * Setup the PERSISTENT RESERVATION TYPE MASK from Table 212 spc4r37. + */ + param_data[4] |= 0x80; /* PR_TYPE_EXCLUSIVE_ACCESS_ALLREG */ + param_data[4] |= 0x40; /* PR_TYPE_EXCLUSIVE_ACCESS_REGONLY */ + param_data[4] |= 0x20; /* PR_TYPE_WRITE_EXCLUSIVE_REGONLY */ + param_data[4] |= 0x08; /* PR_TYPE_EXCLUSIVE_ACCESS */ + param_data[4] |= 0x02; /* PR_TYPE_WRITE_EXCLUSIVE */ + param_data[5] |= 0x01; /* PR_TYPE_EXCLUSIVE_ACCESS_ALLREG */ +} + +static sense_reason_t iblock_pr_read_keys(struct se_cmd *cmd, + unsigned char *param_data) +{ + struct se_device *dev = cmd->se_dev; + struct iblock_dev *ib_dev = IBLOCK_DEV(dev); + struct block_device *bdev = ib_dev->ibd_bd; + const struct pr_ops *ops = bdev->bd_disk->fops->pr_ops; + int i, len, paths, data_offset; + struct pr_keys *keys; + sense_reason_t ret; + + if (!ops) { + pr_err("Block device does not support pr_ops but iblock device has been configured for PR passthrough.\n"); + return TCM_UNSUPPORTED_SCSI_OPCODE; + } + + if (!ops->pr_read_keys) { + pr_err("Block device does not support read_keys.\n"); + return TCM_UNSUPPORTED_SCSI_OPCODE; + } + + /* + * We don't know what's under us, but dm-multipath will register every + * path with the same key, so start off with enough space for 16 paths. + * which is not a lot of memory and should normally be enough. + */ + paths = 16; +retry: + len = 8 * paths; + keys = kzalloc(sizeof(*keys) + len, GFP_KERNEL); + if (!keys) + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + + keys->num_keys = paths; + if (!ops->pr_read_keys(bdev, keys)) { + if (keys->num_keys > paths) { + kfree(keys); + paths *= 2; + goto retry; + } + } else { + ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + goto free_keys; + } + + ret = TCM_NO_SENSE; + + put_unaligned_be32(keys->generation, ¶m_data[0]); + if (!keys->num_keys) { + put_unaligned_be32(0, ¶m_data[4]); + goto free_keys; + } + + put_unaligned_be32(8 * keys->num_keys, ¶m_data[4]); + + data_offset = 8; + for (i = 0; i < keys->num_keys; i++) { + if (data_offset + 8 > cmd->data_length) + break; + + put_unaligned_be64(keys->keys[i], ¶m_data[data_offset]); + data_offset += 8; + } + +free_keys: + kfree(keys); + return ret; +} + +static sense_reason_t iblock_pr_read_reservation(struct se_cmd *cmd, + unsigned char *param_data) +{ + struct se_device *dev = cmd->se_dev; + struct iblock_dev *ib_dev = IBLOCK_DEV(dev); + struct block_device *bdev = ib_dev->ibd_bd; + const struct pr_ops *ops = bdev->bd_disk->fops->pr_ops; + struct pr_held_reservation rsv = { }; + + if (!ops) { + pr_err("Block device does not support pr_ops but iblock device has been configured for PR passthrough.\n"); + return TCM_UNSUPPORTED_SCSI_OPCODE; + } + + if (!ops->pr_read_reservation) { + pr_err("Block device does not support read_keys.\n"); + return TCM_UNSUPPORTED_SCSI_OPCODE; + } + + if (ops->pr_read_reservation(bdev, &rsv)) + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + + put_unaligned_be32(rsv.generation, ¶m_data[0]); + if (!block_pr_type_to_scsi(rsv.type)) { + put_unaligned_be32(0, ¶m_data[4]); + return TCM_NO_SENSE; + } + + put_unaligned_be32(16, ¶m_data[4]); + + if (cmd->data_length < 16) + return TCM_NO_SENSE; + put_unaligned_be64(rsv.key, ¶m_data[8]); + + if (cmd->data_length < 22) + return TCM_NO_SENSE; + param_data[21] = block_pr_type_to_scsi(rsv.type); + + return TCM_NO_SENSE; +} + +static sense_reason_t iblock_execute_pr_in(struct se_cmd *cmd, u8 sa, + unsigned char *param_data) +{ + sense_reason_t ret = TCM_NO_SENSE; + + switch (sa) { + case PRI_REPORT_CAPABILITIES: + iblock_pr_report_caps(param_data); + break; + case PRI_READ_KEYS: + ret = iblock_pr_read_keys(cmd, param_data); + break; + case PRI_READ_RESERVATION: + ret = iblock_pr_read_reservation(cmd, param_data); + break; + default: + pr_err("Unknown PERSISTENT_RESERVE_IN SA: 0x%02x\n", sa); + return TCM_UNSUPPORTED_SCSI_OPCODE; + } + + return ret; +} + static sector_t iblock_get_alignment_offset_lbas(struct se_device *dev) { struct iblock_dev *ib_dev = IBLOCK_DEV(dev); @@ -869,17 +1126,19 @@ static unsigned int iblock_get_io_opt(struct se_device *dev) return bdev_io_opt(bd); } -static struct sbc_ops iblock_sbc_ops = { +static struct exec_cmd_ops iblock_exec_cmd_ops = { .execute_rw = iblock_execute_rw, .execute_sync_cache = iblock_execute_sync_cache, .execute_write_same = iblock_execute_write_same, .execute_unmap = iblock_execute_unmap, + .execute_pr_out = iblock_execute_pr_out, + .execute_pr_in = iblock_execute_pr_in, }; static sense_reason_t iblock_parse_cdb(struct se_cmd *cmd) { - return sbc_parse_cdb(cmd, &iblock_sbc_ops); + return sbc_parse_cdb(cmd, &iblock_exec_cmd_ops); } static bool iblock_get_write_cache(struct se_device *dev) @@ -890,6 +1149,7 @@ static bool iblock_get_write_cache(struct se_device *dev) static const struct target_backend_ops iblock_ops = { .name = "iblock", .inquiry_prod = "IBLOCK", + .transport_flags_changeable = TRANSPORT_FLAG_PASSTHROUGH_PGR, .inquiry_rev = IBLOCK_VERSION, .owner = THIS_MODULE, .attach_hba = iblock_attach_hba, diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c index d19ec4e6a4c0d2b57dc10fdc26c7b1bfc1cede27..49d9167bb263b546e75d5edf3fe916e9c8c5f382 100644 --- a/drivers/target/target_core_pr.c +++ b/drivers/target/target_core_pr.c @@ -3538,6 +3538,37 @@ core_scsi3_emulate_pro_register_and_move(struct se_cmd *cmd, u64 res_key, return ret; } +static sense_reason_t +target_try_pr_out_pt(struct se_cmd *cmd, u8 sa, u64 res_key, u64 sa_res_key, + u8 type, bool aptpl, bool all_tg_pt, bool spec_i_pt) +{ + struct exec_cmd_ops *ops = cmd->protocol_data; + + if (!cmd->se_sess || !cmd->se_lun) { + pr_err("SPC-3 PR: se_sess || struct se_lun is NULL!\n"); + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + } + + if (!ops->execute_pr_out) { + pr_err("SPC-3 PR: Device has been configured for PR passthrough but it's not supported by the backend.\n"); + return TCM_UNSUPPORTED_SCSI_OPCODE; + } + + switch (sa) { + case PRO_REGISTER_AND_MOVE: + case PRO_REPLACE_LOST_RESERVATION: + pr_err("SPC-3 PR: PRO_REGISTER_AND_MOVE and PRO_REPLACE_LOST_RESERVATION are not supported by PR passthrough.\n"); + return TCM_UNSUPPORTED_SCSI_OPCODE; + } + + if (spec_i_pt || all_tg_pt) { + pr_err("SPC-3 PR: SPEC_I_PT and ALL_TG_PT are not supported by PR passthrough.\n"); + return TCM_UNSUPPORTED_SCSI_OPCODE; + } + + return ops->execute_pr_out(cmd, sa, res_key, sa_res_key, type, aptpl); +} + /* * See spc4r17 section 6.14 Table 170 */ @@ -3641,6 +3672,12 @@ target_scsi3_emulate_pr_out(struct se_cmd *cmd) return TCM_PARAMETER_LIST_LENGTH_ERROR; } + if (dev->transport_flags & TRANSPORT_FLAG_PASSTHROUGH_PGR) { + ret = target_try_pr_out_pt(cmd, sa, res_key, sa_res_key, type, + aptpl, all_tg_pt, spec_i_pt); + goto done; + } + /* * (core_scsi3_emulate_pro_* function parameters * are defined by spc4r17 Table 174: @@ -3682,6 +3719,7 @@ target_scsi3_emulate_pr_out(struct se_cmd *cmd) return TCM_INVALID_CDB_FIELD; } +done: if (!ret) target_complete_cmd(cmd, SAM_STAT_GOOD); return ret; @@ -4039,9 +4077,42 @@ core_scsi3_pri_read_full_status(struct se_cmd *cmd) return 0; } +static sense_reason_t target_try_pr_in_pt(struct se_cmd *cmd, u8 sa) +{ + struct exec_cmd_ops *ops = cmd->protocol_data; + unsigned char *buf; + sense_reason_t ret; + + if (cmd->data_length < 8) { + pr_err("PRIN SA SCSI Data Length: %u too small\n", + cmd->data_length); + return TCM_INVALID_CDB_FIELD; + } + + if (!ops->execute_pr_in) { + pr_err("SPC-3 PR: Device has been configured for PR passthrough but it's not supported by the backend.\n"); + return TCM_UNSUPPORTED_SCSI_OPCODE; + } + + if (sa == PRI_READ_FULL_STATUS) { + pr_err("SPC-3 PR: PRI_READ_FULL_STATUS is not supported by PR passthrough.\n"); + return TCM_UNSUPPORTED_SCSI_OPCODE; + } + + buf = transport_kmap_data_sg(cmd); + if (!buf) + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + + ret = ops->execute_pr_in(cmd, sa, buf); + + transport_kunmap_data_sg(cmd); + return ret; +} + sense_reason_t target_scsi3_emulate_pr_in(struct se_cmd *cmd) { + u8 sa = cmd->t_task_cdb[1] & 0x1f; sense_reason_t ret; /* @@ -4060,7 +4131,12 @@ target_scsi3_emulate_pr_in(struct se_cmd *cmd) return TCM_RESERVATION_CONFLICT; } - switch (cmd->t_task_cdb[1] & 0x1f) { + if (cmd->se_dev->transport_flags & TRANSPORT_FLAG_PASSTHROUGH_PGR) { + ret = target_try_pr_in_pt(cmd, sa); + goto done; + } + + switch (sa) { case PRI_READ_KEYS: ret = core_scsi3_pri_read_keys(cmd); break; @@ -4079,6 +4155,7 @@ target_scsi3_emulate_pr_in(struct se_cmd *cmd) return TCM_INVALID_CDB_FIELD; } +done: if (!ret) target_complete_cmd(cmd, SAM_STAT_GOOD); return ret; diff --git a/drivers/target/target_core_pscsi.c b/drivers/target/target_core_pscsi.c index e7425549e39c739ffdc62d6a0c6d933dcac770cd..0d4f09693ef46e8320cf6aac982dab1f580ed4f1 100644 --- a/drivers/target/target_core_pscsi.c +++ b/drivers/target/target_core_pscsi.c @@ -366,8 +366,8 @@ static int pscsi_create_type_disk(struct se_device *dev, struct scsi_device *sd) * Claim exclusive struct block_device access to struct scsi_device * for TYPE_DISK and TYPE_ZBC using supplied udev_path */ - bd = blkdev_get_by_path(dev->udev_path, - FMODE_WRITE|FMODE_READ|FMODE_EXCL, pdv); + bd = blkdev_get_by_path(dev->udev_path, BLK_OPEN_WRITE | BLK_OPEN_READ, + pdv, NULL); if (IS_ERR(bd)) { pr_err("pSCSI: blkdev_get_by_path() failed\n"); scsi_device_put(sd); @@ -377,7 +377,7 @@ static int pscsi_create_type_disk(struct se_device *dev, struct scsi_device *sd) ret = pscsi_add_device_to_list(dev, sd); if (ret) { - blkdev_put(pdv->pdv_bd, FMODE_WRITE|FMODE_READ|FMODE_EXCL); + blkdev_put(pdv->pdv_bd, pdv); scsi_device_put(sd); return ret; } @@ -565,8 +565,7 @@ static void pscsi_destroy_device(struct se_device *dev) */ if ((sd->type == TYPE_DISK || sd->type == TYPE_ZBC) && pdv->pdv_bd) { - blkdev_put(pdv->pdv_bd, - FMODE_WRITE|FMODE_READ|FMODE_EXCL); + blkdev_put(pdv->pdv_bd, pdv); pdv->pdv_bd = NULL; } /* diff --git a/drivers/target/target_core_rd.c b/drivers/target/target_core_rd.c index 6648c1c90e19650ab9b69505c70b63d091acdd96..6f67cc09c2b5b8e591248eb9a2b7422fa8a71597 100644 --- a/drivers/target/target_core_rd.c +++ b/drivers/target/target_core_rd.c @@ -643,14 +643,14 @@ static void rd_free_prot(struct se_device *dev) rd_release_prot_space(rd_dev); } -static struct sbc_ops rd_sbc_ops = { +static struct exec_cmd_ops rd_exec_cmd_ops = { .execute_rw = rd_execute_rw, }; static sense_reason_t rd_parse_cdb(struct se_cmd *cmd) { - return sbc_parse_cdb(cmd, &rd_sbc_ops); + return sbc_parse_cdb(cmd, &rd_exec_cmd_ops); } static const struct target_backend_ops rd_mcp_ops = { diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c index 7536ca7976068a7837c3c5f55f8817909ffa761b..6a02561cc20ce9fb73fbc5f25ee5db0f375058fc 100644 --- a/drivers/target/target_core_sbc.c +++ b/drivers/target/target_core_sbc.c @@ -192,7 +192,7 @@ EXPORT_SYMBOL(sbc_get_write_same_sectors); static sense_reason_t sbc_execute_write_same_unmap(struct se_cmd *cmd) { - struct sbc_ops *ops = cmd->protocol_data; + struct exec_cmd_ops *ops = cmd->protocol_data; sector_t nolb = sbc_get_write_same_sectors(cmd); sense_reason_t ret; @@ -271,7 +271,8 @@ static inline unsigned long long transport_lba_64(unsigned char *cdb) } static sense_reason_t -sbc_setup_write_same(struct se_cmd *cmd, unsigned char flags, struct sbc_ops *ops) +sbc_setup_write_same(struct se_cmd *cmd, unsigned char flags, + struct exec_cmd_ops *ops) { struct se_device *dev = cmd->se_dev; sector_t end_lba = dev->transport->get_blocks(dev) + 1; @@ -340,7 +341,7 @@ sbc_setup_write_same(struct se_cmd *cmd, unsigned char flags, struct sbc_ops *op static sense_reason_t sbc_execute_rw(struct se_cmd *cmd) { - struct sbc_ops *ops = cmd->protocol_data; + struct exec_cmd_ops *ops = cmd->protocol_data; return ops->execute_rw(cmd, cmd->t_data_sg, cmd->t_data_nents, cmd->data_direction); @@ -566,7 +567,7 @@ static sense_reason_t compare_and_write_callback(struct se_cmd *cmd, bool succes static sense_reason_t sbc_compare_and_write(struct se_cmd *cmd) { - struct sbc_ops *ops = cmd->protocol_data; + struct exec_cmd_ops *ops = cmd->protocol_data; struct se_device *dev = cmd->se_dev; sense_reason_t ret; int rc; @@ -764,7 +765,7 @@ sbc_check_dpofua(struct se_device *dev, struct se_cmd *cmd, unsigned char *cdb) } sense_reason_t -sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) +sbc_parse_cdb(struct se_cmd *cmd, struct exec_cmd_ops *ops) { struct se_device *dev = cmd->se_dev; unsigned char *cdb = cmd->t_task_cdb; @@ -1076,7 +1077,7 @@ EXPORT_SYMBOL(sbc_get_device_type); static sense_reason_t sbc_execute_unmap(struct se_cmd *cmd) { - struct sbc_ops *ops = cmd->protocol_data; + struct exec_cmd_ops *ops = cmd->protocol_data; struct se_device *dev = cmd->se_dev; unsigned char *buf, *ptr = NULL; sector_t lba; diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c index 89c0d56294cce4cc7a03fd515d89e79795b902eb..50290abc07bc23869b7aad67ae714756507b0ee8 100644 --- a/drivers/target/target_core_spc.c +++ b/drivers/target/target_core_spc.c @@ -1424,9 +1424,10 @@ static struct target_opcode_descriptor tcm_opcode_write_verify16 = { .update_usage_bits = set_dpofua_usage_bits, }; -static bool tcm_is_ws_enabled(struct se_cmd *cmd) +static bool tcm_is_ws_enabled(struct target_opcode_descriptor *descr, + struct se_cmd *cmd) { - struct sbc_ops *ops = cmd->protocol_data; + struct exec_cmd_ops *ops = cmd->protocol_data; struct se_device *dev = cmd->se_dev; return (dev->dev_attrib.emulate_tpws && !!ops->execute_unmap) || @@ -1451,7 +1452,8 @@ static struct target_opcode_descriptor tcm_opcode_write_same32 = { .update_usage_bits = set_dpofua_usage_bits32, }; -static bool tcm_is_caw_enabled(struct se_cmd *cmd) +static bool tcm_is_caw_enabled(struct target_opcode_descriptor *descr, + struct se_cmd *cmd) { struct se_device *dev = cmd->se_dev; @@ -1491,7 +1493,8 @@ static struct target_opcode_descriptor tcm_opcode_read_capacity16 = { 0xff, 0xff, 0x00, SCSI_CONTROL_MASK}, }; -static bool tcm_is_rep_ref_enabled(struct se_cmd *cmd) +static bool tcm_is_rep_ref_enabled(struct target_opcode_descriptor *descr, + struct se_cmd *cmd) { struct se_device *dev = cmd->se_dev; @@ -1502,7 +1505,6 @@ static bool tcm_is_rep_ref_enabled(struct se_cmd *cmd) } spin_unlock(&dev->t10_alua.lba_map_lock); return true; - } static struct target_opcode_descriptor tcm_opcode_read_report_refferals = { @@ -1537,9 +1539,10 @@ static struct target_opcode_descriptor tcm_opcode_sync_cache16 = { 0xff, 0xff, SCSI_GROUP_NUMBER_MASK, SCSI_CONTROL_MASK}, }; -static bool tcm_is_unmap_enabled(struct se_cmd *cmd) +static bool tcm_is_unmap_enabled(struct target_opcode_descriptor *descr, + struct se_cmd *cmd) { - struct sbc_ops *ops = cmd->protocol_data; + struct exec_cmd_ops *ops = cmd->protocol_data; struct se_device *dev = cmd->se_dev; return ops->execute_unmap && dev->dev_attrib.emulate_tpu; @@ -1659,11 +1662,46 @@ static struct target_opcode_descriptor tcm_opcode_pri_read_resrv = { 0xff, SCSI_CONTROL_MASK}, }; -static bool tcm_is_pr_enabled(struct se_cmd *cmd) +static bool tcm_is_pr_enabled(struct target_opcode_descriptor *descr, + struct se_cmd *cmd) { struct se_device *dev = cmd->se_dev; - return dev->dev_attrib.emulate_pr; + if (!dev->dev_attrib.emulate_pr) + return false; + + if (!(dev->transport_flags & TRANSPORT_FLAG_PASSTHROUGH_PGR)) + return true; + + switch (descr->opcode) { + case RESERVE: + case RESERVE_10: + case RELEASE: + case RELEASE_10: + /* + * The pr_ops which are used by the backend modules don't + * support these commands. + */ + return false; + case PERSISTENT_RESERVE_OUT: + switch (descr->service_action) { + case PRO_REGISTER_AND_MOVE: + case PRO_REPLACE_LOST_RESERVATION: + /* + * The backend modules don't have access to ports and + * I_T nexuses so they can't handle these type of + * requests. + */ + return false; + } + break; + case PERSISTENT_RESERVE_IN: + if (descr->service_action == PRI_READ_FULL_STATUS) + return false; + break; + } + + return true; } static struct target_opcode_descriptor tcm_opcode_pri_read_caps = { @@ -1788,20 +1826,13 @@ static struct target_opcode_descriptor tcm_opcode_pro_register_move = { .enabled = tcm_is_pr_enabled, }; -static bool tcm_is_scsi2_reservations_enabled(struct se_cmd *cmd) -{ - struct se_device *dev = cmd->se_dev; - - return dev->dev_attrib.emulate_pr; -} - static struct target_opcode_descriptor tcm_opcode_release = { .support = SCSI_SUPPORT_FULL, .opcode = RELEASE, .cdb_size = 6, .usage_bits = {RELEASE, 0x00, 0x00, 0x00, 0x00, SCSI_CONTROL_MASK}, - .enabled = tcm_is_scsi2_reservations_enabled, + .enabled = tcm_is_pr_enabled, }; static struct target_opcode_descriptor tcm_opcode_release10 = { @@ -1811,7 +1842,7 @@ static struct target_opcode_descriptor tcm_opcode_release10 = { .usage_bits = {RELEASE_10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, SCSI_CONTROL_MASK}, - .enabled = tcm_is_scsi2_reservations_enabled, + .enabled = tcm_is_pr_enabled, }; static struct target_opcode_descriptor tcm_opcode_reserve = { @@ -1820,7 +1851,7 @@ static struct target_opcode_descriptor tcm_opcode_reserve = { .cdb_size = 6, .usage_bits = {RESERVE, 0x00, 0x00, 0x00, 0x00, SCSI_CONTROL_MASK}, - .enabled = tcm_is_scsi2_reservations_enabled, + .enabled = tcm_is_pr_enabled, }; static struct target_opcode_descriptor tcm_opcode_reserve10 = { @@ -1830,7 +1861,7 @@ static struct target_opcode_descriptor tcm_opcode_reserve10 = { .usage_bits = {RESERVE_10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, SCSI_CONTROL_MASK}, - .enabled = tcm_is_scsi2_reservations_enabled, + .enabled = tcm_is_pr_enabled, }; static struct target_opcode_descriptor tcm_opcode_request_sense = { @@ -1849,7 +1880,8 @@ static struct target_opcode_descriptor tcm_opcode_inquiry = { 0xff, SCSI_CONTROL_MASK}, }; -static bool tcm_is_3pc_enabled(struct se_cmd *cmd) +static bool tcm_is_3pc_enabled(struct target_opcode_descriptor *descr, + struct se_cmd *cmd) { struct se_device *dev = cmd->se_dev; @@ -1910,8 +1942,8 @@ static struct target_opcode_descriptor tcm_opcode_report_target_pgs = { 0xff, 0xff, 0x00, SCSI_CONTROL_MASK}, }; - -static bool spc_rsoc_enabled(struct se_cmd *cmd) +static bool spc_rsoc_enabled(struct target_opcode_descriptor *descr, + struct se_cmd *cmd) { struct se_device *dev = cmd->se_dev; @@ -1931,7 +1963,8 @@ static struct target_opcode_descriptor tcm_opcode_report_supp_opcodes = { .enabled = spc_rsoc_enabled, }; -static bool tcm_is_set_tpg_enabled(struct se_cmd *cmd) +static bool tcm_is_set_tpg_enabled(struct target_opcode_descriptor *descr, + struct se_cmd *cmd) { struct t10_alua_tg_pt_gp *l_tg_pt_gp; struct se_lun *l_lun = cmd->se_lun; @@ -2118,7 +2151,7 @@ spc_rsoc_get_descr(struct se_cmd *cmd, struct target_opcode_descriptor **opcode) if (descr->serv_action_valid) return TCM_INVALID_CDB_FIELD; - if (!descr->enabled || descr->enabled(cmd)) + if (!descr->enabled || descr->enabled(descr, cmd)) *opcode = descr; break; case 0x2: @@ -2132,7 +2165,8 @@ spc_rsoc_get_descr(struct se_cmd *cmd, struct target_opcode_descriptor **opcode) */ if (descr->serv_action_valid && descr->service_action == requested_sa) { - if (!descr->enabled || descr->enabled(cmd)) + if (!descr->enabled || descr->enabled(descr, + cmd)) *opcode = descr; } else if (!descr->serv_action_valid) return TCM_INVALID_CDB_FIELD; @@ -2145,7 +2179,8 @@ spc_rsoc_get_descr(struct se_cmd *cmd, struct target_opcode_descriptor **opcode) * be returned in the one_command parameter data format. */ if (descr->service_action == requested_sa) - if (!descr->enabled || descr->enabled(cmd)) + if (!descr->enabled || descr->enabled(descr, + cmd)) *opcode = descr; break; } @@ -2202,7 +2237,7 @@ spc_emulate_report_supp_op_codes(struct se_cmd *cmd) for (i = 0; i < ARRAY_SIZE(tcm_supported_opcodes); i++) { descr = tcm_supported_opcodes[i]; - if (descr->enabled && !descr->enabled(cmd)) + if (descr->enabled && !descr->enabled(descr, cmd)) continue; response_length += spc_rsoc_encode_command_descriptor( @@ -2231,12 +2266,22 @@ spc_parse_cdb(struct se_cmd *cmd, unsigned int *size) struct se_device *dev = cmd->se_dev; unsigned char *cdb = cmd->t_task_cdb; - if (!dev->dev_attrib.emulate_pr && - ((cdb[0] == PERSISTENT_RESERVE_IN) || - (cdb[0] == PERSISTENT_RESERVE_OUT) || - (cdb[0] == RELEASE || cdb[0] == RELEASE_10) || - (cdb[0] == RESERVE || cdb[0] == RESERVE_10))) { - return TCM_UNSUPPORTED_SCSI_OPCODE; + switch (cdb[0]) { + case RESERVE: + case RESERVE_10: + case RELEASE: + case RELEASE_10: + if (!dev->dev_attrib.emulate_pr) + return TCM_UNSUPPORTED_SCSI_OPCODE; + + if (dev->transport_flags & TRANSPORT_FLAG_PASSTHROUGH_PGR) + return TCM_UNSUPPORTED_SCSI_OPCODE; + break; + case PERSISTENT_RESERVE_IN: + case PERSISTENT_RESERVE_OUT: + if (!dev->dev_attrib.emulate_pr) + return TCM_UNSUPPORTED_SCSI_OPCODE; + break; } switch (cdb[0]) { diff --git a/drivers/target/target_core_user.c b/drivers/target/target_core_user.c index 15ffc8d2ac7baf61d88952be14ed94d99ce1940c..22cc6cac0ba2b5704873aaa73bab75ea37cb235a 100644 --- a/drivers/target/target_core_user.c +++ b/drivers/target/target_core_user.c @@ -2820,14 +2820,14 @@ static ssize_t tcmu_dev_config_store(struct config_item *item, const char *page, pr_err("Unable to reconfigure device\n"); return ret; } - strlcpy(udev->dev_config, page, TCMU_CONFIG_LEN); + strscpy(udev->dev_config, page, TCMU_CONFIG_LEN); ret = tcmu_update_uio_info(udev); if (ret) return ret; return count; } - strlcpy(udev->dev_config, page, TCMU_CONFIG_LEN); + strscpy(udev->dev_config, page, TCMU_CONFIG_LEN); return count; } diff --git a/drivers/tee/optee/smc_abi.c b/drivers/tee/optee/smc_abi.c index 3861ae06d902f072451bd46d99206ab8bb8e53f5..d5b28fd35d665378591674a8baaeffac5bcd77c0 100644 --- a/drivers/tee/optee/smc_abi.c +++ b/drivers/tee/optee/smc_abi.c @@ -1541,12 +1541,11 @@ static int optee_load_fw(struct platform_device *pdev, * This uses the GFP_DMA flag to ensure we are allocated memory in the * 32-bit space since TF-A cannot map memory beyond the 32-bit boundary. */ - data_buf = kmalloc(fw->size, GFP_KERNEL | GFP_DMA); + data_buf = kmemdup(fw->data, fw->size, GFP_KERNEL | GFP_DMA); if (!data_buf) { rc = -ENOMEM; goto fw_err; } - memcpy(data_buf, fw->data, fw->size); data_pa = virt_to_phys(data_buf); reg_pair_from_64(&data_pa_high, &data_pa_low, data_pa); reg_pair_from_64(&data_size_high, &data_size_low, data_size); diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig index 4cd7ab7073150b716f801c1c9d4b5da061942676..19a4b33cb564767b1c8a5ca114af64c7574d4b55 100644 --- a/drivers/thermal/Kconfig +++ b/drivers/thermal/Kconfig @@ -130,6 +130,14 @@ config THERMAL_DEFAULT_GOV_POWER_ALLOCATOR system and device power allocation. This governor can only operate on cooling devices that implement the power API. +config THERMAL_DEFAULT_GOV_BANG_BANG + bool "bang_bang" + depends on THERMAL_GOV_BANG_BANG + help + Use the bang_bang governor as default. This throttles the + devices one step at the time, taking into account the trip + point hysteresis. + endchoice config THERMAL_GOV_FAIR_SHARE diff --git a/drivers/thermal/amlogic_thermal.c b/drivers/thermal/amlogic_thermal.c index 3abc2dcef408a255a81efcf1b6179d77e3491d18..756b218880a7ab4820cd4a2295d4657a7c94edc2 100644 --- a/drivers/thermal/amlogic_thermal.c +++ b/drivers/thermal/amlogic_thermal.c @@ -282,8 +282,7 @@ static int amlogic_thermal_probe(struct platform_device *pdev) return ret; } - if (devm_thermal_add_hwmon_sysfs(&pdev->dev, pdata->tzd)) - dev_warn(&pdev->dev, "Failed to add hwmon sysfs attributes\n"); + devm_thermal_add_hwmon_sysfs(&pdev->dev, pdata->tzd); ret = amlogic_thermal_initialize(pdata); if (ret) diff --git a/drivers/thermal/armada_thermal.c b/drivers/thermal/armada_thermal.c index 0e8dfa6a7757ba9392bf81b4902de7ad82f5856b..9f6dc4fc9112d028ae00fdd6393e0021a0ab1062 100644 --- a/drivers/thermal/armada_thermal.c +++ b/drivers/thermal/armada_thermal.c @@ -231,7 +231,7 @@ static void armada380_init(struct platform_device *pdev, regmap_write(priv->syscon, data->syscon_control0_off, reg); } -static void armada_ap806_init(struct platform_device *pdev, +static void armada_ap80x_init(struct platform_device *pdev, struct armada_thermal_priv *priv) { struct armada_thermal_data *data = priv->data; @@ -614,7 +614,7 @@ static const struct armada_thermal_data armada380_data = { }; static const struct armada_thermal_data armada_ap806_data = { - .init = armada_ap806_init, + .init = armada_ap80x_init, .is_valid_bit = BIT(16), .temp_shift = 0, .temp_mask = 0x3ff, @@ -637,6 +637,30 @@ static const struct armada_thermal_data armada_ap806_data = { .cpu_nr = 4, }; +static const struct armada_thermal_data armada_ap807_data = { + .init = armada_ap80x_init, + .is_valid_bit = BIT(16), + .temp_shift = 0, + .temp_mask = 0x3ff, + .thresh_shift = 3, + .hyst_shift = 19, + .hyst_mask = 0x3, + .coef_b = -128900LL, + .coef_m = 394ULL, + .coef_div = 1, + .inverted = true, + .signed_sample = true, + .syscon_control0_off = 0x84, + .syscon_control1_off = 0x88, + .syscon_status_off = 0x8C, + .dfx_irq_cause_off = 0x108, + .dfx_irq_mask_off = 0x10C, + .dfx_overheat_irq = BIT(22), + .dfx_server_irq_mask_off = 0x104, + .dfx_server_irq_en = BIT(1), + .cpu_nr = 4, +}; + static const struct armada_thermal_data armada_cp110_data = { .init = armada_cp110_init, .is_valid_bit = BIT(10), @@ -680,6 +704,10 @@ static const struct of_device_id armada_thermal_id_table[] = { .compatible = "marvell,armada-ap806-thermal", .data = &armada_ap806_data, }, + { + .compatible = "marvell,armada-ap807-thermal", + .data = &armada_ap807_data, + }, { .compatible = "marvell,armada-cp110-thermal", .data = &armada_cp110_data, diff --git a/drivers/thermal/imx8mm_thermal.c b/drivers/thermal/imx8mm_thermal.c index d8005e9ec992bd96154144331a801922fc71016e..d4b40869c7d7b98b2b9a1eecc4fd43ac7076298c 100644 --- a/drivers/thermal/imx8mm_thermal.c +++ b/drivers/thermal/imx8mm_thermal.c @@ -343,8 +343,7 @@ static int imx8mm_tmu_probe(struct platform_device *pdev) } tmu->sensors[i].hw_id = i; - if (devm_thermal_add_hwmon_sysfs(&pdev->dev, tmu->sensors[i].tzd)) - dev_warn(&pdev->dev, "failed to add hwmon sysfs attributes\n"); + devm_thermal_add_hwmon_sysfs(&pdev->dev, tmu->sensors[i].tzd); } platform_set_drvdata(pdev, tmu); diff --git a/drivers/thermal/imx_sc_thermal.c b/drivers/thermal/imx_sc_thermal.c index 839bb9958f60daf08c95b6fc60e4cf46a021aa2d..8d6b4ef23746766116b75c689bb3cca77a9dae17 100644 --- a/drivers/thermal/imx_sc_thermal.c +++ b/drivers/thermal/imx_sc_thermal.c @@ -116,8 +116,7 @@ static int imx_sc_thermal_probe(struct platform_device *pdev) return ret; } - if (devm_thermal_add_hwmon_sysfs(&pdev->dev, sensor->tzd)) - dev_warn(&pdev->dev, "failed to add hwmon sysfs attributes\n"); + devm_thermal_add_hwmon_sysfs(&pdev->dev, sensor->tzd); } return 0; diff --git a/drivers/thermal/intel/int340x_thermal/acpi_thermal_rel.c b/drivers/thermal/intel/int340x_thermal/acpi_thermal_rel.c index 01b80331eab660beda3f6e2040cf6f65ae4b244d..dc519a665c1854a143c85ca636ee10291ac52313 100644 --- a/drivers/thermal/intel/int340x_thermal/acpi_thermal_rel.c +++ b/drivers/thermal/intel/int340x_thermal/acpi_thermal_rel.c @@ -203,6 +203,151 @@ int acpi_parse_art(acpi_handle handle, int *art_count, struct art **artp, } EXPORT_SYMBOL(acpi_parse_art); +/* + * acpi_parse_psvt - Passive Table (PSVT) for passive cooling + * + * @handle: ACPI handle of the device which contains PSVT + * @psvt_count: the number of valid entries resulted from parsing PSVT + * @psvtp: pointer to array of psvt entries + * + */ +static int acpi_parse_psvt(acpi_handle handle, int *psvt_count, struct psvt **psvtp) +{ + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; + int nr_bad_entries = 0, revision = 0; + union acpi_object *p; + acpi_status status; + int i, result = 0; + struct psvt *psvts; + + if (!acpi_has_method(handle, "PSVT")) + return -ENODEV; + + status = acpi_evaluate_object(handle, "PSVT", NULL, &buffer); + if (ACPI_FAILURE(status)) + return -ENODEV; + + p = buffer.pointer; + if (!p || (p->type != ACPI_TYPE_PACKAGE)) { + result = -EFAULT; + goto end; + } + + /* first package is the revision number */ + if (p->package.count > 0) { + union acpi_object *prev = &(p->package.elements[0]); + + if (prev->type == ACPI_TYPE_INTEGER) + revision = (int)prev->integer.value; + } else { + result = -EFAULT; + goto end; + } + + /* Support only version 2 */ + if (revision != 2) { + result = -EFAULT; + goto end; + } + + *psvt_count = p->package.count - 1; + if (!*psvt_count) { + result = -EFAULT; + goto end; + } + + psvts = kcalloc(*psvt_count, sizeof(*psvts), GFP_KERNEL); + if (!psvts) { + result = -ENOMEM; + goto end; + } + + /* Start index is 1 because the first package is the revision number */ + for (i = 1; i < p->package.count; i++) { + struct acpi_buffer psvt_int_format = { sizeof("RRNNNNNNNNNN"), "RRNNNNNNNNNN" }; + struct acpi_buffer psvt_str_format = { sizeof("RRNNNNNSNNNN"), "RRNNNNNSNNNN" }; + union acpi_object *package = &(p->package.elements[i]); + struct psvt *psvt = &psvts[i - 1 - nr_bad_entries]; + struct acpi_buffer *psvt_format = &psvt_int_format; + struct acpi_buffer element = { 0, NULL }; + union acpi_object *knob; + struct acpi_device *res; + struct psvt *psvt_ptr; + + element.length = ACPI_ALLOCATE_BUFFER; + element.pointer = NULL; + + if (package->package.count >= ACPI_NR_PSVT_ELEMENTS) { + knob = &(package->package.elements[ACPI_PSVT_CONTROL_KNOB]); + } else { + nr_bad_entries++; + pr_info("PSVT package %d is invalid, ignored\n", i); + continue; + } + + if (knob->type == ACPI_TYPE_STRING) { + psvt_format = &psvt_str_format; + if (knob->string.length > ACPI_LIMIT_STR_MAX_LEN - 1) { + pr_info("PSVT package %d limit string len exceeds max\n", i); + knob->string.length = ACPI_LIMIT_STR_MAX_LEN - 1; + } + } + + status = acpi_extract_package(&(p->package.elements[i]), psvt_format, &element); + if (ACPI_FAILURE(status)) { + nr_bad_entries++; + pr_info("PSVT package %d is invalid, ignored\n", i); + continue; + } + + psvt_ptr = (struct psvt *)element.pointer; + + memcpy(psvt, psvt_ptr, sizeof(*psvt)); + + /* The limit element can be string or U64 */ + psvt->control_knob_type = (u64)knob->type; + + if (knob->type == ACPI_TYPE_STRING) { + memset(&psvt->limit, 0, sizeof(u64)); + strncpy(psvt->limit.string, psvt_ptr->limit.str_ptr, knob->string.length); + } else { + psvt->limit.integer = psvt_ptr->limit.integer; + } + + kfree(element.pointer); + + res = acpi_fetch_acpi_dev(psvt->source); + if (!res) { + nr_bad_entries++; + pr_info("Failed to get source ACPI device\n"); + continue; + } + + res = acpi_fetch_acpi_dev(psvt->target); + if (!res) { + nr_bad_entries++; + pr_info("Failed to get target ACPI device\n"); + continue; + } + } + + /* don't count bad entries */ + *psvt_count -= nr_bad_entries; + + if (!*psvt_count) { + result = -EFAULT; + kfree(psvts); + goto end; + } + + *psvtp = psvts; + + return 0; + +end: + kfree(buffer.pointer); + return result; +} /* get device name from acpi handle */ static void get_single_name(acpi_handle handle, char *name) @@ -289,6 +434,57 @@ static int fill_trt(char __user *ubuf) return ret; } +static int fill_psvt(char __user *ubuf) +{ + int i, ret, count, psvt_len; + union psvt_object *psvt_user; + struct psvt *psvts; + + ret = acpi_parse_psvt(acpi_thermal_rel_handle, &count, &psvts); + if (ret) + return ret; + + psvt_len = count * sizeof(*psvt_user); + + psvt_user = kzalloc(psvt_len, GFP_KERNEL); + if (!psvt_user) { + ret = -ENOMEM; + goto free_psvt; + } + + /* now fill in user psvt data */ + for (i = 0; i < count; i++) { + /* userspace psvt needs device name instead of acpi reference */ + get_single_name(psvts[i].source, psvt_user[i].source_device); + get_single_name(psvts[i].target, psvt_user[i].target_device); + + psvt_user[i].priority = psvts[i].priority; + psvt_user[i].sample_period = psvts[i].sample_period; + psvt_user[i].passive_temp = psvts[i].passive_temp; + psvt_user[i].source_domain = psvts[i].source_domain; + psvt_user[i].control_knob = psvts[i].control_knob; + psvt_user[i].step_size = psvts[i].step_size; + psvt_user[i].limit_coeff = psvts[i].limit_coeff; + psvt_user[i].unlimit_coeff = psvts[i].unlimit_coeff; + psvt_user[i].control_knob_type = psvts[i].control_knob_type; + if (psvt_user[i].control_knob_type == ACPI_TYPE_STRING) + strncpy(psvt_user[i].limit.string, psvts[i].limit.string, + ACPI_LIMIT_STR_MAX_LEN); + else + psvt_user[i].limit.integer = psvts[i].limit.integer; + + } + + if (copy_to_user(ubuf, psvt_user, psvt_len)) + ret = -EFAULT; + + kfree(psvt_user); + +free_psvt: + kfree(psvts); + return ret; +} + static long acpi_thermal_rel_ioctl(struct file *f, unsigned int cmd, unsigned long __arg) { @@ -298,6 +494,7 @@ static long acpi_thermal_rel_ioctl(struct file *f, unsigned int cmd, char __user *arg = (void __user *)__arg; struct trt *trts = NULL; struct art *arts = NULL; + struct psvt *psvts; switch (cmd) { case ACPI_THERMAL_GET_TRT_COUNT: @@ -336,6 +533,27 @@ static long acpi_thermal_rel_ioctl(struct file *f, unsigned int cmd, case ACPI_THERMAL_GET_ART: return fill_art(arg); + case ACPI_THERMAL_GET_PSVT_COUNT: + ret = acpi_parse_psvt(acpi_thermal_rel_handle, &count, &psvts); + if (!ret) { + kfree(psvts); + return put_user(count, (unsigned long __user *)__arg); + } + return ret; + + case ACPI_THERMAL_GET_PSVT_LEN: + /* total length of the data retrieved (count * PSVT entry size) */ + ret = acpi_parse_psvt(acpi_thermal_rel_handle, &count, &psvts); + length = count * sizeof(union psvt_object); + if (!ret) { + kfree(psvts); + return put_user(length, (unsigned long __user *)__arg); + } + return ret; + + case ACPI_THERMAL_GET_PSVT: + return fill_psvt(arg); + default: return -ENOTTY; } diff --git a/drivers/thermal/intel/int340x_thermal/acpi_thermal_rel.h b/drivers/thermal/intel/int340x_thermal/acpi_thermal_rel.h index 78d9424770356368e22ada011623f03a3911f478..ac376d8f9ee438b686de20344ca7c411b0ca5cc7 100644 --- a/drivers/thermal/intel/int340x_thermal/acpi_thermal_rel.h +++ b/drivers/thermal/intel/int340x_thermal/acpi_thermal_rel.h @@ -14,6 +14,16 @@ #define ACPI_THERMAL_GET_TRT _IOR(ACPI_THERMAL_MAGIC, 5, unsigned long) #define ACPI_THERMAL_GET_ART _IOR(ACPI_THERMAL_MAGIC, 6, unsigned long) +/* + * ACPI_THERMAL_GET_PSVT_COUNT = Number of PSVT entries + * ACPI_THERMAL_GET_PSVT_LEN = Total return data size (PSVT count x each + * PSVT entry size) + * ACPI_THERMAL_GET_PSVT = Get the data as an array of psvt_objects + */ +#define ACPI_THERMAL_GET_PSVT_LEN _IOR(ACPI_THERMAL_MAGIC, 7, unsigned long) +#define ACPI_THERMAL_GET_PSVT_COUNT _IOR(ACPI_THERMAL_MAGIC, 8, unsigned long) +#define ACPI_THERMAL_GET_PSVT _IOR(ACPI_THERMAL_MAGIC, 9, unsigned long) + struct art { acpi_handle source; acpi_handle target; @@ -43,6 +53,32 @@ struct trt { u64 reserved4; } __packed; +#define ACPI_NR_PSVT_ELEMENTS 12 +#define ACPI_PSVT_CONTROL_KNOB 7 +#define ACPI_LIMIT_STR_MAX_LEN 8 + +struct psvt { + acpi_handle source; + acpi_handle target; + u64 priority; + u64 sample_period; + u64 passive_temp; + u64 source_domain; + u64 control_knob; + union { + /* For limit_type = ACPI_TYPE_INTEGER */ + u64 integer; + /* For limit_type = ACPI_TYPE_STRING */ + char string[ACPI_LIMIT_STR_MAX_LEN]; + char *str_ptr; + } limit; + u64 step_size; + u64 limit_coeff; + u64 unlimit_coeff; + /* Spec calls this field reserved, so we borrow it for type info */ + u64 control_knob_type; /* ACPI_TYPE_STRING or ACPI_TYPE_INTEGER */ +} __packed; + #define ACPI_NR_ART_ELEMENTS 13 /* for usrspace */ union art_object { @@ -77,6 +113,27 @@ union trt_object { u64 __data[8]; }; +union psvt_object { + struct { + char source_device[8]; + char target_device[8]; + u64 priority; + u64 sample_period; + u64 passive_temp; + u64 source_domain; + u64 control_knob; + union { + u64 integer; + char string[ACPI_LIMIT_STR_MAX_LEN]; + } limit; + u64 step_size; + u64 limit_coeff; + u64 unlimit_coeff; + u64 control_knob_type; + }; + u64 __data[ACPI_NR_PSVT_ELEMENTS]; +}; + #ifdef __KERNEL__ int acpi_thermal_rel_misc_device_add(acpi_handle handle); int acpi_thermal_rel_misc_device_remove(acpi_handle handle); diff --git a/drivers/thermal/intel/int340x_thermal/processor_thermal_rapl.c b/drivers/thermal/intel/int340x_thermal/processor_thermal_rapl.c index a205221ec8df93ed89d55b17f00b89f9a9bbb0ff..013f1633f082764ed2f5c703a5665afb0c087fb6 100644 --- a/drivers/thermal/intel/int340x_thermal/processor_thermal_rapl.c +++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_rapl.c @@ -15,8 +15,8 @@ static const struct rapl_mmio_regs rapl_mmio_default = { .reg_unit = 0x5938, .regs[RAPL_DOMAIN_PACKAGE] = { 0x59a0, 0x593c, 0x58f0, 0, 0x5930}, .regs[RAPL_DOMAIN_DRAM] = { 0x58e0, 0x58e8, 0x58ec, 0, 0}, - .limits[RAPL_DOMAIN_PACKAGE] = 2, - .limits[RAPL_DOMAIN_DRAM] = 2, + .limits[RAPL_DOMAIN_PACKAGE] = BIT(POWER_LIMIT2), + .limits[RAPL_DOMAIN_DRAM] = BIT(POWER_LIMIT2), }; static int rapl_mmio_cpu_online(unsigned int cpu) @@ -27,9 +27,9 @@ static int rapl_mmio_cpu_online(unsigned int cpu) if (topology_physical_package_id(cpu)) return 0; - rp = rapl_find_package_domain(cpu, &rapl_mmio_priv); + rp = rapl_find_package_domain(cpu, &rapl_mmio_priv, true); if (!rp) { - rp = rapl_add_package(cpu, &rapl_mmio_priv); + rp = rapl_add_package(cpu, &rapl_mmio_priv, true); if (IS_ERR(rp)) return PTR_ERR(rp); } @@ -42,7 +42,7 @@ static int rapl_mmio_cpu_down_prep(unsigned int cpu) struct rapl_package *rp; int lead_cpu; - rp = rapl_find_package_domain(cpu, &rapl_mmio_priv); + rp = rapl_find_package_domain(cpu, &rapl_mmio_priv, true); if (!rp) return 0; @@ -97,6 +97,7 @@ int proc_thermal_rapl_add(struct pci_dev *pdev, struct proc_thermal_device *proc rapl_regs->regs[domain][reg]; rapl_mmio_priv.limits[domain] = rapl_regs->limits[domain]; } + rapl_mmio_priv.type = RAPL_IF_MMIO; rapl_mmio_priv.reg_unit = (u64)proc_priv->mmio_base + rapl_regs->reg_unit; rapl_mmio_priv.read_raw = rapl_mmio_read_raw; diff --git a/drivers/thermal/intel/intel_soc_dts_iosf.c b/drivers/thermal/intel/intel_soc_dts_iosf.c index f99dc7e4ae893949e1fb8009982f2a922aeeb0e5..db97499f4f0ab01d829167b84e5303cd8034b56d 100644 --- a/drivers/thermal/intel/intel_soc_dts_iosf.c +++ b/drivers/thermal/intel/intel_soc_dts_iosf.c @@ -398,7 +398,7 @@ struct intel_soc_dts_sensors *intel_soc_dts_iosf_init( spin_lock_init(&sensors->intr_notify_lock); mutex_init(&sensors->dts_update_lock); sensors->intr_type = intr_type; - sensors->tj_max = tj_max; + sensors->tj_max = tj_max * 1000; if (intr_type == INTEL_SOC_DTS_INTERRUPT_NONE) notification = false; else diff --git a/drivers/thermal/k3_bandgap.c b/drivers/thermal/k3_bandgap.c index 791210458606266a1ed3f37b47f067eb7e63154f..1c3e590157ec7634882335109d57900bfac57aac 100644 --- a/drivers/thermal/k3_bandgap.c +++ b/drivers/thermal/k3_bandgap.c @@ -222,8 +222,7 @@ static int k3_bandgap_probe(struct platform_device *pdev) goto err_alloc; } - if (devm_thermal_add_hwmon_sysfs(dev, data[id].tzd)) - dev_warn(dev, "Failed to add hwmon sysfs attributes\n"); + devm_thermal_add_hwmon_sysfs(dev, data[id].tzd); } platform_set_drvdata(pdev, bgp); diff --git a/drivers/thermal/mediatek/auxadc_thermal.c b/drivers/thermal/mediatek/auxadc_thermal.c index 0b5528804bbd6daa6c53a046120af7577935531b..f59d36de20a09e0e4aaf3e37dfdff741d1dd99a3 100644 --- a/drivers/thermal/mediatek/auxadc_thermal.c +++ b/drivers/thermal/mediatek/auxadc_thermal.c @@ -1222,12 +1222,7 @@ static int mtk_thermal_probe(struct platform_device *pdev) return -ENODEV; } - auxadc_base = devm_of_iomap(&pdev->dev, auxadc, 0, NULL); - if (IS_ERR(auxadc_base)) { - of_node_put(auxadc); - return PTR_ERR(auxadc_base); - } - + auxadc_base = of_iomap(auxadc, 0); auxadc_phys_base = of_get_phys_base(auxadc); of_node_put(auxadc); @@ -1243,12 +1238,7 @@ static int mtk_thermal_probe(struct platform_device *pdev) return -ENODEV; } - apmixed_base = devm_of_iomap(&pdev->dev, apmixedsys, 0, NULL); - if (IS_ERR(apmixed_base)) { - of_node_put(apmixedsys); - return PTR_ERR(apmixed_base); - } - + apmixed_base = of_iomap(apmixedsys, 0); apmixed_phys_base = of_get_phys_base(apmixedsys); of_node_put(apmixedsys); diff --git a/drivers/thermal/mediatek/lvts_thermal.c b/drivers/thermal/mediatek/lvts_thermal.c index d0a3f95b7884ba87d5e8f992884f31fb1c03671c..b693fac2d6779fa211db52a9f27af773465dcc0a 100644 --- a/drivers/thermal/mediatek/lvts_thermal.c +++ b/drivers/thermal/mediatek/lvts_thermal.c @@ -19,6 +19,8 @@ #include #include +#include "../thermal_hwmon.h" + #define LVTS_MONCTL0(__base) (__base + 0x0000) #define LVTS_MONCTL1(__base) (__base + 0x0004) #define LVTS_MONCTL2(__base) (__base + 0x0008) @@ -996,6 +998,8 @@ static int lvts_ctrl_start(struct device *dev, struct lvts_ctrl *lvts_ctrl) return PTR_ERR(tz); } + devm_thermal_add_hwmon_sysfs(dev, tz); + /* * The thermal zone pointer will be needed in the * interrupt handler, we store it in the sensor diff --git a/drivers/thermal/qcom/qcom-spmi-adc-tm5.c b/drivers/thermal/qcom/qcom-spmi-adc-tm5.c index 5749149ae2e4e066ae97a65f9f378a712eadcc8f..5ddc39b2be32496e78382cbc24305e284cb4f3c4 100644 --- a/drivers/thermal/qcom/qcom-spmi-adc-tm5.c +++ b/drivers/thermal/qcom/qcom-spmi-adc-tm5.c @@ -689,9 +689,7 @@ static int adc_tm5_register_tzd(struct adc_tm5_chip *adc_tm) return PTR_ERR(tzd); } adc_tm->channels[i].tzd = tzd; - if (devm_thermal_add_hwmon_sysfs(adc_tm->dev, tzd)) - dev_warn(adc_tm->dev, - "Failed to add hwmon sysfs attributes\n"); + devm_thermal_add_hwmon_sysfs(adc_tm->dev, tzd); } return 0; diff --git a/drivers/thermal/qcom/qcom-spmi-temp-alarm.c b/drivers/thermal/qcom/qcom-spmi-temp-alarm.c index 0f88e98428acfbc77b8b496d6adc894e1c05811a..0e8ebfcd84c54e16f78dab615df562819ab07ba5 100644 --- a/drivers/thermal/qcom/qcom-spmi-temp-alarm.c +++ b/drivers/thermal/qcom/qcom-spmi-temp-alarm.c @@ -411,22 +411,19 @@ static int qpnp_tm_probe(struct platform_device *pdev) chip->base = res; ret = qpnp_tm_read(chip, QPNP_TM_REG_TYPE, &type); - if (ret < 0) { - dev_err(&pdev->dev, "could not read type\n"); - return ret; - } + if (ret < 0) + return dev_err_probe(&pdev->dev, ret, + "could not read type\n"); ret = qpnp_tm_read(chip, QPNP_TM_REG_SUBTYPE, &subtype); - if (ret < 0) { - dev_err(&pdev->dev, "could not read subtype\n"); - return ret; - } + if (ret < 0) + return dev_err_probe(&pdev->dev, ret, + "could not read subtype\n"); ret = qpnp_tm_read(chip, QPNP_TM_REG_DIG_MAJOR, &dig_major); - if (ret < 0) { - dev_err(&pdev->dev, "could not read dig_major\n"); - return ret; - } + if (ret < 0) + return dev_err_probe(&pdev->dev, ret, + "could not read dig_major\n"); if (type != QPNP_TM_TYPE || (subtype != QPNP_TM_SUBTYPE_GEN1 && subtype != QPNP_TM_SUBTYPE_GEN2)) { @@ -448,20 +445,15 @@ static int qpnp_tm_probe(struct platform_device *pdev) */ chip->tz_dev = devm_thermal_of_zone_register( &pdev->dev, 0, chip, &qpnp_tm_sensor_ops); - if (IS_ERR(chip->tz_dev)) { - dev_err(&pdev->dev, "failed to register sensor\n"); - return PTR_ERR(chip->tz_dev); - } + if (IS_ERR(chip->tz_dev)) + return dev_err_probe(&pdev->dev, PTR_ERR(chip->tz_dev), + "failed to register sensor\n"); ret = qpnp_tm_init(chip); - if (ret < 0) { - dev_err(&pdev->dev, "init failed\n"); - return ret; - } + if (ret < 0) + return dev_err_probe(&pdev->dev, ret, "init failed\n"); - if (devm_thermal_add_hwmon_sysfs(&pdev->dev, chip->tz_dev)) - dev_warn(&pdev->dev, - "Failed to add hwmon sysfs attributes\n"); + devm_thermal_add_hwmon_sysfs(&pdev->dev, chip->tz_dev); ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, qpnp_tm_isr, IRQF_ONESHOT, node->name, chip); diff --git a/drivers/thermal/qcom/tsens-v0_1.c b/drivers/thermal/qcom/tsens-v0_1.c index e89c6f39a3aeaf203b31c00fe59ef39936fe2590..a941b4241b0ab96aa7e0f70f8d7104dbd5e9e944 100644 --- a/drivers/thermal/qcom/tsens-v0_1.c +++ b/drivers/thermal/qcom/tsens-v0_1.c @@ -39,26 +39,6 @@ struct tsens_legacy_calibration_format tsens_8916_nvmem = { }, }; -struct tsens_legacy_calibration_format tsens_8939_nvmem = { - .base_len = 8, - .base_shift = 2, - .sp_len = 6, - .mode = { 12, 0 }, - .invalid = { 12, 2 }, - .base = { { 0, 0 }, { 1, 24 } }, - .sp = { - { { 12, 3 }, { 12, 9 } }, - { { 12, 15 }, { 12, 21 } }, - { { 12, 27 }, { 13, 1 } }, - { { 13, 7 }, { 13, 13 } }, - { { 13, 19 }, { 13, 25 } }, - { { 0, 8 }, { 0, 14 } }, - { { 0, 20 }, { 0, 26 } }, - { { 1, 0 }, { 1, 6 } }, - { { 1, 12 }, { 1, 18 } }, - }, -}; - struct tsens_legacy_calibration_format tsens_8974_nvmem = { .base_len = 8, .base_shift = 2, @@ -103,22 +83,6 @@ struct tsens_legacy_calibration_format tsens_8974_backup_nvmem = { }, }; -struct tsens_legacy_calibration_format tsens_9607_nvmem = { - .base_len = 8, - .base_shift = 2, - .sp_len = 6, - .mode = { 2, 20 }, - .invalid = { 2, 22 }, - .base = { { 0, 0 }, { 2, 12 } }, - .sp = { - { { 0, 8 }, { 0, 14 } }, - { { 0, 20 }, { 0, 26 } }, - { { 1, 0 }, { 1, 6 } }, - { { 1, 12 }, { 1, 18 } }, - { { 2, 0 }, { 2, 6 } }, - }, -}; - static int calibrate_8916(struct tsens_priv *priv) { u32 p1[5], p2[5]; @@ -243,6 +207,39 @@ static int calibrate_8974(struct tsens_priv *priv) return 0; } +static int __init init_8226(struct tsens_priv *priv) +{ + priv->sensor[0].slope = 2901; + priv->sensor[1].slope = 2846; + priv->sensor[2].slope = 3038; + priv->sensor[3].slope = 2955; + priv->sensor[4].slope = 2901; + priv->sensor[5].slope = 2846; + + return init_common(priv); +} + +static int __init init_8909(struct tsens_priv *priv) +{ + int i; + + for (i = 0; i < priv->num_sensors; ++i) + priv->sensor[i].slope = 3000; + + priv->sensor[0].p1_calib_offset = 0; + priv->sensor[0].p2_calib_offset = 0; + priv->sensor[1].p1_calib_offset = -10; + priv->sensor[1].p2_calib_offset = -6; + priv->sensor[2].p1_calib_offset = 0; + priv->sensor[2].p2_calib_offset = 0; + priv->sensor[3].p1_calib_offset = -9; + priv->sensor[3].p2_calib_offset = -9; + priv->sensor[4].p1_calib_offset = -8; + priv->sensor[4].p2_calib_offset = -10; + + return init_common(priv); +} + static int __init init_8939(struct tsens_priv *priv) { priv->sensor[0].slope = 2911; priv->sensor[1].slope = 2789; @@ -258,7 +255,28 @@ static int __init init_8939(struct tsens_priv *priv) { return init_common(priv); } -/* v0.1: 8916, 8939, 8974, 9607 */ +static int __init init_9607(struct tsens_priv *priv) +{ + int i; + + for (i = 0; i < priv->num_sensors; ++i) + priv->sensor[i].slope = 3000; + + priv->sensor[0].p1_calib_offset = 1; + priv->sensor[0].p2_calib_offset = 1; + priv->sensor[1].p1_calib_offset = -4; + priv->sensor[1].p2_calib_offset = -2; + priv->sensor[2].p1_calib_offset = 4; + priv->sensor[2].p2_calib_offset = 8; + priv->sensor[3].p1_calib_offset = -3; + priv->sensor[3].p2_calib_offset = -5; + priv->sensor[4].p1_calib_offset = -4; + priv->sensor[4].p2_calib_offset = -4; + + return init_common(priv); +} + +/* v0.1: 8226, 8909, 8916, 8939, 8974, 9607 */ static struct tsens_features tsens_v0_1_feat = { .ver_major = VER_0_1, @@ -313,6 +331,32 @@ static const struct tsens_ops ops_v0_1 = { .get_temp = get_temp_common, }; +static const struct tsens_ops ops_8226 = { + .init = init_8226, + .calibrate = tsens_calibrate_common, + .get_temp = get_temp_common, +}; + +struct tsens_plat_data data_8226 = { + .num_sensors = 6, + .ops = &ops_8226, + .feat = &tsens_v0_1_feat, + .fields = tsens_v0_1_regfields, +}; + +static const struct tsens_ops ops_8909 = { + .init = init_8909, + .calibrate = tsens_calibrate_common, + .get_temp = get_temp_common, +}; + +struct tsens_plat_data data_8909 = { + .num_sensors = 5, + .ops = &ops_8909, + .feat = &tsens_v0_1_feat, + .fields = tsens_v0_1_regfields, +}; + static const struct tsens_ops ops_8916 = { .init = init_common, .calibrate = calibrate_8916, @@ -356,9 +400,15 @@ struct tsens_plat_data data_8974 = { .fields = tsens_v0_1_regfields, }; +static const struct tsens_ops ops_9607 = { + .init = init_9607, + .calibrate = tsens_calibrate_common, + .get_temp = get_temp_common, +}; + struct tsens_plat_data data_9607 = { .num_sensors = 5, - .ops = &ops_v0_1, + .ops = &ops_9607, .feat = &tsens_v0_1_feat, .fields = tsens_v0_1_regfields, }; diff --git a/drivers/thermal/qcom/tsens-v1.c b/drivers/thermal/qcom/tsens-v1.c index b822a426066d925372795b9959c3c4e06101cda9..51322430f1fe11ff4408c88d9a1e24efe39a1c65 100644 --- a/drivers/thermal/qcom/tsens-v1.c +++ b/drivers/thermal/qcom/tsens-v1.c @@ -42,28 +42,6 @@ struct tsens_legacy_calibration_format tsens_qcs404_nvmem = { }, }; -struct tsens_legacy_calibration_format tsens_8976_nvmem = { - .base_len = 8, - .base_shift = 2, - .sp_len = 6, - .mode = { 4, 0 }, - .invalid = { 4, 2 }, - .base = { { 0, 0 }, { 2, 8 } }, - .sp = { - { { 0, 8 }, { 0, 14 } }, - { { 0, 20 }, { 0, 26 } }, - { { 1, 0 }, { 1, 6 } }, - { { 1, 12 }, { 1, 18 } }, - { { 2, 8 }, { 2, 14 } }, - { { 2, 20 }, { 2, 26 } }, - { { 3, 0 }, { 3, 6 } }, - { { 3, 12 }, { 3, 18 } }, - { { 4, 2 }, { 4, 9 } }, - { { 4, 14 }, { 4, 21 } }, - { { 4, 26 }, { 5, 1 } }, - }, -}; - static int calibrate_v1(struct tsens_priv *priv) { u32 p1[10], p2[10]; diff --git a/drivers/thermal/qcom/tsens.c b/drivers/thermal/qcom/tsens.c index d3218127e617dfd374de9efa5ed541a7e1a2f679..98c356acfe98363515ee86b39b507e1484460594 100644 --- a/drivers/thermal/qcom/tsens.c +++ b/drivers/thermal/qcom/tsens.c @@ -134,10 +134,12 @@ int tsens_read_calibration(struct tsens_priv *priv, int shift, u32 *p1, u32 *p2, p1[i] = p1[i] + (base1 << shift); break; case TWO_PT_CALIB: + case TWO_PT_CALIB_NO_OFFSET: for (i = 0; i < priv->num_sensors; i++) p2[i] = (p2[i] + base2) << shift; fallthrough; case ONE_PT_CALIB2: + case ONE_PT_CALIB2_NO_OFFSET: for (i = 0; i < priv->num_sensors; i++) p1[i] = (p1[i] + base1) << shift; break; @@ -149,6 +151,18 @@ int tsens_read_calibration(struct tsens_priv *priv, int shift, u32 *p1, u32 *p2, } } + /* Apply calibration offset workaround except for _NO_OFFSET modes */ + switch (mode) { + case TWO_PT_CALIB: + for (i = 0; i < priv->num_sensors; i++) + p2[i] += priv->sensor[i].p2_calib_offset; + fallthrough; + case ONE_PT_CALIB2: + for (i = 0; i < priv->num_sensors; i++) + p1[i] += priv->sensor[i].p1_calib_offset; + break; + } + return mode; } @@ -254,7 +268,7 @@ void compute_intercept_slope(struct tsens_priv *priv, u32 *p1, if (!priv->sensor[i].slope) priv->sensor[i].slope = SLOPE_DEFAULT; - if (mode == TWO_PT_CALIB) { + if (mode == TWO_PT_CALIB || mode == TWO_PT_CALIB_NO_OFFSET) { /* * slope (m) = adc_code2 - adc_code1 (y2 - y1)/ * temp_120_degc - temp_30_degc (x2 - x1) @@ -1095,6 +1109,12 @@ static const struct of_device_id tsens_table[] = { }, { .compatible = "qcom,mdm9607-tsens", .data = &data_9607, + }, { + .compatible = "qcom,msm8226-tsens", + .data = &data_8226, + }, { + .compatible = "qcom,msm8909-tsens", + .data = &data_8909, }, { .compatible = "qcom,msm8916-tsens", .data = &data_8916, @@ -1189,9 +1209,7 @@ static int tsens_register(struct tsens_priv *priv) if (priv->ops->enable) priv->ops->enable(priv, i); - if (devm_thermal_add_hwmon_sysfs(priv->dev, tzd)) - dev_warn(priv->dev, - "Failed to add hwmon sysfs attributes\n"); + devm_thermal_add_hwmon_sysfs(priv->dev, tzd); } /* VER_0 require to set MIN and MAX THRESH diff --git a/drivers/thermal/qcom/tsens.h b/drivers/thermal/qcom/tsens.h index dba9cd38f637c8abf3e2c3a2fcb66b7e195bf4da..2805de1c68279c3a7af64ff42271ce7f483fef2c 100644 --- a/drivers/thermal/qcom/tsens.h +++ b/drivers/thermal/qcom/tsens.h @@ -10,6 +10,8 @@ #define ONE_PT_CALIB 0x1 #define ONE_PT_CALIB2 0x2 #define TWO_PT_CALIB 0x3 +#define ONE_PT_CALIB2_NO_OFFSET 0x6 +#define TWO_PT_CALIB_NO_OFFSET 0x7 #define CAL_DEGC_PT1 30 #define CAL_DEGC_PT2 120 #define SLOPE_FACTOR 1000 @@ -57,6 +59,8 @@ struct tsens_sensor { unsigned int hw_id; int slope; u32 status; + int p1_calib_offset; + int p2_calib_offset; }; /** @@ -635,7 +639,7 @@ int get_temp_common(const struct tsens_sensor *s, int *temp); extern struct tsens_plat_data data_8960; /* TSENS v0.1 targets */ -extern struct tsens_plat_data data_8916, data_8939, data_8974, data_9607; +extern struct tsens_plat_data data_8226, data_8909, data_8916, data_8939, data_8974, data_9607; /* TSENS v1 targets */ extern struct tsens_plat_data data_tsens_v1, data_8976, data_8956; diff --git a/drivers/thermal/qoriq_thermal.c b/drivers/thermal/qoriq_thermal.c index e58756323457e17651464722ae82a11b2e3822f0..ccc2eea7f9f548a184646cb38a39068238b978b3 100644 --- a/drivers/thermal/qoriq_thermal.c +++ b/drivers/thermal/qoriq_thermal.c @@ -31,7 +31,6 @@ #define TMR_DISABLE 0x0 #define TMR_ME 0x80000000 #define TMR_ALPF 0x0c000000 -#define TMR_MSITE_ALL GENMASK(15, 0) #define REGS_TMTMIR 0x008 /* Temperature measurement interval Register */ #define TMTMIR_DEFAULT 0x0000000f @@ -51,6 +50,7 @@ * Site Register */ #define TRITSR_V BIT(31) +#define TRITSR_TP5 BIT(9) #define REGS_V2_TMSAR(n) (0x304 + 16 * (n)) /* TMU monitoring * site adjustment register */ @@ -105,6 +105,11 @@ static int tmu_get_temp(struct thermal_zone_device *tz, int *temp) * within sensor range. TEMP is an 9 bit value representing * temperature in KelVin. */ + + regmap_read(qdata->regmap, REGS_TMR, &val); + if (!(val & TMR_ME)) + return -EAGAIN; + if (regmap_read_poll_timeout(qdata->regmap, REGS_TRITSR(qsensor->id), val, @@ -113,10 +118,15 @@ static int tmu_get_temp(struct thermal_zone_device *tz, int *temp) 10 * USEC_PER_MSEC)) return -ENODATA; - if (qdata->ver == TMU_VER1) + if (qdata->ver == TMU_VER1) { *temp = (val & GENMASK(7, 0)) * MILLIDEGREE_PER_DEGREE; - else - *temp = kelvin_to_millicelsius(val & GENMASK(8, 0)); + } else { + if (val & TRITSR_TP5) + *temp = milli_kelvin_to_millicelsius((val & GENMASK(8, 0)) * + MILLIDEGREE_PER_DEGREE + 500); + else + *temp = kelvin_to_millicelsius(val & GENMASK(8, 0)); + } return 0; } @@ -128,15 +138,7 @@ static const struct thermal_zone_device_ops tmu_tz_ops = { static int qoriq_tmu_register_tmu_zone(struct device *dev, struct qoriq_tmu_data *qdata) { - int id; - - if (qdata->ver == TMU_VER1) { - regmap_write(qdata->regmap, REGS_TMR, - TMR_MSITE_ALL | TMR_ME | TMR_ALPF); - } else { - regmap_write(qdata->regmap, REGS_V2_TMSR, TMR_MSITE_ALL); - regmap_write(qdata->regmap, REGS_TMR, TMR_ME | TMR_ALPF_V2); - } + int id, sites = 0; for (id = 0; id < SITES_MAX; id++) { struct thermal_zone_device *tzd; @@ -153,14 +155,24 @@ static int qoriq_tmu_register_tmu_zone(struct device *dev, if (ret == -ENODEV) continue; - regmap_write(qdata->regmap, REGS_TMR, TMR_DISABLE); return ret; } - if (devm_thermal_add_hwmon_sysfs(dev, tzd)) - dev_warn(dev, - "Failed to add hwmon sysfs attributes\n"); + if (qdata->ver == TMU_VER1) + sites |= 0x1 << (15 - id); + else + sites |= 0x1 << id; + + devm_thermal_add_hwmon_sysfs(dev, tzd); + } + if (sites) { + if (qdata->ver == TMU_VER1) { + regmap_write(qdata->regmap, REGS_TMR, TMR_ME | TMR_ALPF | sites); + } else { + regmap_write(qdata->regmap, REGS_V2_TMSR, sites); + regmap_write(qdata->regmap, REGS_TMR, TMR_ME | TMR_ALPF_V2); + } } return 0; @@ -208,8 +220,6 @@ static int qoriq_tmu_calibration(struct device *dev, static void qoriq_tmu_init_device(struct qoriq_tmu_data *data) { - int i; - /* Disable interrupt, using polling instead */ regmap_write(data->regmap, REGS_TIER, TIER_DISABLE); @@ -220,8 +230,6 @@ static void qoriq_tmu_init_device(struct qoriq_tmu_data *data) } else { regmap_write(data->regmap, REGS_V2_TMTMIR, TMTMIR_DEFAULT); regmap_write(data->regmap, REGS_V2_TEUMR(0), TEUMR0_V2); - for (i = 0; i < SITES_MAX; i++) - regmap_write(data->regmap, REGS_V2_TMSAR(i), TMSARA_V2); } /* Disable monitoring */ @@ -230,7 +238,7 @@ static void qoriq_tmu_init_device(struct qoriq_tmu_data *data) static const struct regmap_range qoriq_yes_ranges[] = { regmap_reg_range(REGS_TMR, REGS_TSCFGR), - regmap_reg_range(REGS_TTRnCR(0), REGS_TTRnCR(3)), + regmap_reg_range(REGS_TTRnCR(0), REGS_TTRnCR(15)), regmap_reg_range(REGS_V2_TEUMR(0), REGS_V2_TEUMR(2)), regmap_reg_range(REGS_V2_TMSAR(0), REGS_V2_TMSAR(15)), regmap_reg_range(REGS_IPBRR(0), REGS_IPBRR(1)), diff --git a/drivers/thermal/rcar_gen3_thermal.c b/drivers/thermal/rcar_gen3_thermal.c index 42a4724d3920884828994dda07582a623a41cf38..9029d01e029b46cb8dd7cde925516480a0b43b3c 100644 --- a/drivers/thermal/rcar_gen3_thermal.c +++ b/drivers/thermal/rcar_gen3_thermal.c @@ -35,6 +35,12 @@ #define REG_GEN3_PTAT2 0x60 #define REG_GEN3_PTAT3 0x64 #define REG_GEN3_THSCP 0x68 +#define REG_GEN4_THSFMON00 0x180 +#define REG_GEN4_THSFMON01 0x184 +#define REG_GEN4_THSFMON02 0x188 +#define REG_GEN4_THSFMON15 0x1BC +#define REG_GEN4_THSFMON16 0x1C0 +#define REG_GEN4_THSFMON17 0x1C4 /* IRQ{STR,MSK,EN} bits */ #define IRQ_TEMP1 BIT(0) @@ -55,6 +61,7 @@ #define MCELSIUS(temp) ((temp) * 1000) #define GEN3_FUSE_MASK 0xFFF +#define GEN4_FUSE_MASK 0xFFF #define TSC_MAX_NUM 5 @@ -66,6 +73,13 @@ struct equation_coefs { int b2; }; +struct rcar_gen3_thermal_priv; + +struct rcar_thermal_info { + int ths_tj_1; + void (*read_fuses)(struct rcar_gen3_thermal_priv *priv); +}; + struct rcar_gen3_thermal_tsc { void __iomem *base; struct thermal_zone_device *zone; @@ -79,6 +93,7 @@ struct rcar_gen3_thermal_priv { struct thermal_zone_device_ops ops; unsigned int num_tscs; int ptat[3]; + const struct rcar_thermal_info *info; }; static inline u32 rcar_gen3_thermal_read(struct rcar_gen3_thermal_tsc *tsc, @@ -236,6 +251,62 @@ static irqreturn_t rcar_gen3_thermal_irq(int irq, void *data) return IRQ_HANDLED; } +static void rcar_gen3_thermal_read_fuses_gen3(struct rcar_gen3_thermal_priv *priv) +{ + unsigned int i; + + /* + * Set the pseudo calibration points with fused values. + * PTAT is shared between all TSCs but only fused for the first + * TSC while THCODEs are fused for each TSC. + */ + priv->ptat[0] = rcar_gen3_thermal_read(priv->tscs[0], REG_GEN3_PTAT1) & + GEN3_FUSE_MASK; + priv->ptat[1] = rcar_gen3_thermal_read(priv->tscs[0], REG_GEN3_PTAT2) & + GEN3_FUSE_MASK; + priv->ptat[2] = rcar_gen3_thermal_read(priv->tscs[0], REG_GEN3_PTAT3) & + GEN3_FUSE_MASK; + + for (i = 0; i < priv->num_tscs; i++) { + struct rcar_gen3_thermal_tsc *tsc = priv->tscs[i]; + + tsc->thcode[0] = rcar_gen3_thermal_read(tsc, REG_GEN3_THCODE1) & + GEN3_FUSE_MASK; + tsc->thcode[1] = rcar_gen3_thermal_read(tsc, REG_GEN3_THCODE2) & + GEN3_FUSE_MASK; + tsc->thcode[2] = rcar_gen3_thermal_read(tsc, REG_GEN3_THCODE3) & + GEN3_FUSE_MASK; + } +} + +static void rcar_gen3_thermal_read_fuses_gen4(struct rcar_gen3_thermal_priv *priv) +{ + unsigned int i; + + /* + * Set the pseudo calibration points with fused values. + * PTAT is shared between all TSCs but only fused for the first + * TSC while THCODEs are fused for each TSC. + */ + priv->ptat[0] = rcar_gen3_thermal_read(priv->tscs[0], REG_GEN4_THSFMON16) & + GEN4_FUSE_MASK; + priv->ptat[1] = rcar_gen3_thermal_read(priv->tscs[0], REG_GEN4_THSFMON17) & + GEN4_FUSE_MASK; + priv->ptat[2] = rcar_gen3_thermal_read(priv->tscs[0], REG_GEN4_THSFMON15) & + GEN4_FUSE_MASK; + + for (i = 0; i < priv->num_tscs; i++) { + struct rcar_gen3_thermal_tsc *tsc = priv->tscs[i]; + + tsc->thcode[0] = rcar_gen3_thermal_read(tsc, REG_GEN4_THSFMON01) & + GEN4_FUSE_MASK; + tsc->thcode[1] = rcar_gen3_thermal_read(tsc, REG_GEN4_THSFMON02) & + GEN4_FUSE_MASK; + tsc->thcode[2] = rcar_gen3_thermal_read(tsc, REG_GEN4_THSFMON00) & + GEN4_FUSE_MASK; + } +} + static bool rcar_gen3_thermal_read_fuses(struct rcar_gen3_thermal_priv *priv) { unsigned int i; @@ -243,7 +314,8 @@ static bool rcar_gen3_thermal_read_fuses(struct rcar_gen3_thermal_priv *priv) /* If fuses are not set, fallback to pseudo values. */ thscp = rcar_gen3_thermal_read(priv->tscs[0], REG_GEN3_THSCP); - if ((thscp & THSCP_COR_PARA_VLD) != THSCP_COR_PARA_VLD) { + if (!priv->info->read_fuses || + (thscp & THSCP_COR_PARA_VLD) != THSCP_COR_PARA_VLD) { /* Default THCODE values in case FUSEs are not set. */ static const int thcodes[TSC_MAX_NUM][3] = { { 3397, 2800, 2221 }, @@ -268,29 +340,7 @@ static bool rcar_gen3_thermal_read_fuses(struct rcar_gen3_thermal_priv *priv) return false; } - /* - * Set the pseudo calibration points with fused values. - * PTAT is shared between all TSCs but only fused for the first - * TSC while THCODEs are fused for each TSC. - */ - priv->ptat[0] = rcar_gen3_thermal_read(priv->tscs[0], REG_GEN3_PTAT1) & - GEN3_FUSE_MASK; - priv->ptat[1] = rcar_gen3_thermal_read(priv->tscs[0], REG_GEN3_PTAT2) & - GEN3_FUSE_MASK; - priv->ptat[2] = rcar_gen3_thermal_read(priv->tscs[0], REG_GEN3_PTAT3) & - GEN3_FUSE_MASK; - - for (i = 0; i < priv->num_tscs; i++) { - struct rcar_gen3_thermal_tsc *tsc = priv->tscs[i]; - - tsc->thcode[0] = rcar_gen3_thermal_read(tsc, REG_GEN3_THCODE1) & - GEN3_FUSE_MASK; - tsc->thcode[1] = rcar_gen3_thermal_read(tsc, REG_GEN3_THCODE2) & - GEN3_FUSE_MASK; - tsc->thcode[2] = rcar_gen3_thermal_read(tsc, REG_GEN3_THCODE3) & - GEN3_FUSE_MASK; - } - + priv->info->read_fuses(priv); return true; } @@ -318,52 +368,65 @@ static void rcar_gen3_thermal_init(struct rcar_gen3_thermal_priv *priv, usleep_range(1000, 2000); } -static const int rcar_gen3_ths_tj_1 = 126; -static const int rcar_gen3_ths_tj_1_m3_w = 116; +static const struct rcar_thermal_info rcar_m3w_thermal_info = { + .ths_tj_1 = 116, + .read_fuses = rcar_gen3_thermal_read_fuses_gen3, +}; + +static const struct rcar_thermal_info rcar_gen3_thermal_info = { + .ths_tj_1 = 126, + .read_fuses = rcar_gen3_thermal_read_fuses_gen3, +}; + +static const struct rcar_thermal_info rcar_gen4_thermal_info = { + .ths_tj_1 = 126, + .read_fuses = rcar_gen3_thermal_read_fuses_gen4, +}; + static const struct of_device_id rcar_gen3_thermal_dt_ids[] = { { .compatible = "renesas,r8a774a1-thermal", - .data = &rcar_gen3_ths_tj_1_m3_w, + .data = &rcar_m3w_thermal_info, }, { .compatible = "renesas,r8a774b1-thermal", - .data = &rcar_gen3_ths_tj_1, + .data = &rcar_gen3_thermal_info, }, { .compatible = "renesas,r8a774e1-thermal", - .data = &rcar_gen3_ths_tj_1, + .data = &rcar_gen3_thermal_info, }, { .compatible = "renesas,r8a7795-thermal", - .data = &rcar_gen3_ths_tj_1, + .data = &rcar_gen3_thermal_info, }, { .compatible = "renesas,r8a7796-thermal", - .data = &rcar_gen3_ths_tj_1_m3_w, + .data = &rcar_m3w_thermal_info, }, { .compatible = "renesas,r8a77961-thermal", - .data = &rcar_gen3_ths_tj_1_m3_w, + .data = &rcar_m3w_thermal_info, }, { .compatible = "renesas,r8a77965-thermal", - .data = &rcar_gen3_ths_tj_1, + .data = &rcar_gen3_thermal_info, }, { .compatible = "renesas,r8a77980-thermal", - .data = &rcar_gen3_ths_tj_1, + .data = &rcar_gen3_thermal_info, }, { .compatible = "renesas,r8a779a0-thermal", - .data = &rcar_gen3_ths_tj_1, + .data = &rcar_gen3_thermal_info, }, { .compatible = "renesas,r8a779f0-thermal", - .data = &rcar_gen3_ths_tj_1, + .data = &rcar_gen4_thermal_info, }, { .compatible = "renesas,r8a779g0-thermal", - .data = &rcar_gen3_ths_tj_1, + .data = &rcar_gen4_thermal_info, }, {}, }; @@ -418,7 +481,6 @@ static int rcar_gen3_thermal_probe(struct platform_device *pdev) { struct rcar_gen3_thermal_priv *priv; struct device *dev = &pdev->dev; - const int *ths_tj_1 = of_device_get_match_data(dev); struct resource *res; struct thermal_zone_device *zone; unsigned int i; @@ -430,6 +492,7 @@ static int rcar_gen3_thermal_probe(struct platform_device *pdev) priv->ops = rcar_gen3_tz_of_ops; + priv->info = of_device_get_match_data(dev); platform_set_drvdata(pdev, priv); if (rcar_gen3_thermal_request_irqs(priv, pdev)) @@ -469,7 +532,7 @@ static int rcar_gen3_thermal_probe(struct platform_device *pdev) struct rcar_gen3_thermal_tsc *tsc = priv->tscs[i]; rcar_gen3_thermal_init(priv, tsc); - rcar_gen3_thermal_calc_coefs(priv, tsc, *ths_tj_1); + rcar_gen3_thermal_calc_coefs(priv, tsc, priv->info->ths_tj_1); zone = devm_thermal_of_zone_register(dev, i, tsc, &priv->ops); if (IS_ERR(zone)) { diff --git a/drivers/thermal/st/st_thermal.c b/drivers/thermal/st/st_thermal.c index 2d30420984454e4bbc071fd275c61f6dd2f37b71..0d6249b36609efc16903cd0f4358273da0296cb0 100644 --- a/drivers/thermal/st/st_thermal.c +++ b/drivers/thermal/st/st_thermal.c @@ -227,14 +227,12 @@ int st_thermal_register(struct platform_device *pdev, } EXPORT_SYMBOL_GPL(st_thermal_register); -int st_thermal_unregister(struct platform_device *pdev) +void st_thermal_unregister(struct platform_device *pdev) { struct st_thermal_sensor *sensor = platform_get_drvdata(pdev); st_thermal_sensor_off(sensor); thermal_zone_device_unregister(sensor->thermal_dev); - - return 0; } EXPORT_SYMBOL_GPL(st_thermal_unregister); diff --git a/drivers/thermal/st/st_thermal.h b/drivers/thermal/st/st_thermal.h index d661b2f2ef29f2c548277b2184a544ba7041ef5d..75a84e6ec6a729bfce9027b467526f90713c33ee 100644 --- a/drivers/thermal/st/st_thermal.h +++ b/drivers/thermal/st/st_thermal.h @@ -94,7 +94,7 @@ struct st_thermal_sensor { extern int st_thermal_register(struct platform_device *pdev, const struct of_device_id *st_thermal_of_match); -extern int st_thermal_unregister(struct platform_device *pdev); +extern void st_thermal_unregister(struct platform_device *pdev); extern const struct dev_pm_ops st_thermal_pm_ops; #endif /* __STI_RESET_SYSCFG_H */ diff --git a/drivers/thermal/st/st_thermal_memmap.c b/drivers/thermal/st/st_thermal_memmap.c index d68596c40be99009513c7c6d2ac87ddd7e26ac25..e8cfa83b724a774b53e0be33d1e462601b070f07 100644 --- a/drivers/thermal/st/st_thermal_memmap.c +++ b/drivers/thermal/st/st_thermal_memmap.c @@ -172,9 +172,9 @@ static int st_mmap_probe(struct platform_device *pdev) return st_thermal_register(pdev, st_mmap_thermal_of_match); } -static int st_mmap_remove(struct platform_device *pdev) +static void st_mmap_remove(struct platform_device *pdev) { - return st_thermal_unregister(pdev); + st_thermal_unregister(pdev); } static struct platform_driver st_mmap_thermal_driver = { @@ -184,7 +184,7 @@ static struct platform_driver st_mmap_thermal_driver = { .of_match_table = st_mmap_thermal_of_match, }, .probe = st_mmap_probe, - .remove = st_mmap_remove, + .remove_new = st_mmap_remove, }; module_platform_driver(st_mmap_thermal_driver); diff --git a/drivers/thermal/sun8i_thermal.c b/drivers/thermal/sun8i_thermal.c index 793ddce72132fc06e213bc641fdc3ec19b845d4c..195f3c5d0b388c9ffc812415ba0608ee038d83c9 100644 --- a/drivers/thermal/sun8i_thermal.c +++ b/drivers/thermal/sun8i_thermal.c @@ -319,6 +319,11 @@ static int sun8i_ths_calibrate(struct ths_device *tmdev) return ret; } +static void sun8i_ths_reset_control_assert(void *data) +{ + reset_control_assert(data); +} + static int sun8i_ths_resource_init(struct ths_device *tmdev) { struct device *dev = tmdev->dev; @@ -339,47 +344,35 @@ static int sun8i_ths_resource_init(struct ths_device *tmdev) if (IS_ERR(tmdev->reset)) return PTR_ERR(tmdev->reset); - tmdev->bus_clk = devm_clk_get(&pdev->dev, "bus"); + ret = reset_control_deassert(tmdev->reset); + if (ret) + return ret; + + ret = devm_add_action_or_reset(dev, sun8i_ths_reset_control_assert, + tmdev->reset); + if (ret) + return ret; + + tmdev->bus_clk = devm_clk_get_enabled(&pdev->dev, "bus"); if (IS_ERR(tmdev->bus_clk)) return PTR_ERR(tmdev->bus_clk); } if (tmdev->chip->has_mod_clk) { - tmdev->mod_clk = devm_clk_get(&pdev->dev, "mod"); + tmdev->mod_clk = devm_clk_get_enabled(&pdev->dev, "mod"); if (IS_ERR(tmdev->mod_clk)) return PTR_ERR(tmdev->mod_clk); } - ret = reset_control_deassert(tmdev->reset); - if (ret) - return ret; - - ret = clk_prepare_enable(tmdev->bus_clk); - if (ret) - goto assert_reset; - ret = clk_set_rate(tmdev->mod_clk, 24000000); if (ret) - goto bus_disable; - - ret = clk_prepare_enable(tmdev->mod_clk); - if (ret) - goto bus_disable; + return ret; ret = sun8i_ths_calibrate(tmdev); if (ret) - goto mod_disable; + return ret; return 0; - -mod_disable: - clk_disable_unprepare(tmdev->mod_clk); -bus_disable: - clk_disable_unprepare(tmdev->bus_clk); -assert_reset: - reset_control_assert(tmdev->reset); - - return ret; } static int sun8i_h3_thermal_init(struct ths_device *tmdev) @@ -475,9 +468,7 @@ static int sun8i_ths_register(struct ths_device *tmdev) if (IS_ERR(tmdev->sensor[i].tzd)) return PTR_ERR(tmdev->sensor[i].tzd); - if (devm_thermal_add_hwmon_sysfs(tmdev->dev, tmdev->sensor[i].tzd)) - dev_warn(tmdev->dev, - "Failed to add hwmon sysfs attributes\n"); + devm_thermal_add_hwmon_sysfs(tmdev->dev, tmdev->sensor[i].tzd); } return 0; @@ -530,17 +521,6 @@ static int sun8i_ths_probe(struct platform_device *pdev) return 0; } -static int sun8i_ths_remove(struct platform_device *pdev) -{ - struct ths_device *tmdev = platform_get_drvdata(pdev); - - clk_disable_unprepare(tmdev->mod_clk); - clk_disable_unprepare(tmdev->bus_clk); - reset_control_assert(tmdev->reset); - - return 0; -} - static const struct ths_thermal_chip sun8i_a83t_ths = { .sensor_num = 3, .scale = 705, @@ -642,7 +622,6 @@ MODULE_DEVICE_TABLE(of, of_ths_match); static struct platform_driver ths_driver = { .probe = sun8i_ths_probe, - .remove = sun8i_ths_remove, .driver = { .name = "sun8i-thermal", .of_match_table = of_ths_match, diff --git a/drivers/thermal/tegra/tegra30-tsensor.c b/drivers/thermal/tegra/tegra30-tsensor.c index cb584a5735edd19a04923e6bb7dcb1916dca73b6..c243e9d76d3c9670dac00c49d0da45583c8daec7 100644 --- a/drivers/thermal/tegra/tegra30-tsensor.c +++ b/drivers/thermal/tegra/tegra30-tsensor.c @@ -523,8 +523,7 @@ static int tegra_tsensor_register_channel(struct tegra_tsensor *ts, return 0; } - if (devm_thermal_add_hwmon_sysfs(ts->dev, tsc->tzd)) - dev_warn(ts->dev, "failed to add hwmon sysfs attributes\n"); + devm_thermal_add_hwmon_sysfs(ts->dev, tsc->tzd); return 0; } diff --git a/drivers/thermal/thermal-generic-adc.c b/drivers/thermal/thermal-generic-adc.c index 017b0ce521229db7a259512a405393caca952e62..f4f1a04f8c0f39f90c0253bf366008007e228070 100644 --- a/drivers/thermal/thermal-generic-adc.c +++ b/drivers/thermal/thermal-generic-adc.c @@ -13,6 +13,8 @@ #include #include +#include "thermal_hwmon.h" + struct gadc_thermal_info { struct device *dev; struct thermal_zone_device *tz_dev; @@ -153,6 +155,8 @@ static int gadc_thermal_probe(struct platform_device *pdev) return ret; } + devm_thermal_add_hwmon_sysfs(&pdev->dev, gti->tz_dev); + return 0; } diff --git a/drivers/thermal/thermal_core.h b/drivers/thermal/thermal_core.h index 3d4a787c6b28a0baf7197726058708a5a7b830af..17c1bbed734d398756a1ae959c15f139a6ec9ac5 100644 --- a/drivers/thermal/thermal_core.h +++ b/drivers/thermal/thermal_core.h @@ -23,6 +23,8 @@ #define DEFAULT_THERMAL_GOVERNOR "user_space" #elif defined(CONFIG_THERMAL_DEFAULT_GOV_POWER_ALLOCATOR) #define DEFAULT_THERMAL_GOVERNOR "power_allocator" +#elif defined(CONFIG_THERMAL_DEFAULT_GOV_BANG_BANG) +#define DEFAULT_THERMAL_GOVERNOR "bang_bang" #endif /* Initial state of a cooling device during binding */ diff --git a/drivers/thermal/thermal_hwmon.c b/drivers/thermal/thermal_hwmon.c index fbe55509e3071134493a09b477cb0bf2cf37eda6..c3ae44659b8170fa10a656ede02f5e5407dc0e0f 100644 --- a/drivers/thermal/thermal_hwmon.c +++ b/drivers/thermal/thermal_hwmon.c @@ -271,11 +271,14 @@ int devm_thermal_add_hwmon_sysfs(struct device *dev, struct thermal_zone_device ptr = devres_alloc(devm_thermal_hwmon_release, sizeof(*ptr), GFP_KERNEL); - if (!ptr) + if (!ptr) { + dev_warn(dev, "Failed to allocate device resource data\n"); return -ENOMEM; + } ret = thermal_add_hwmon_sysfs(tz); if (ret) { + dev_warn(dev, "Failed to add hwmon sysfs attributes\n"); devres_free(ptr); return ret; } diff --git a/drivers/thermal/ti-soc-thermal/ti-thermal-common.c b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c index 6a5335931f4db16760085acc1860ce6a7f8789c9..d414a4b7a94a454a88df5207fd07bc9653c11926 100644 --- a/drivers/thermal/ti-soc-thermal/ti-thermal-common.c +++ b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c @@ -182,8 +182,7 @@ int ti_thermal_expose_sensor(struct ti_bandgap *bgp, int id, ti_bandgap_write_update_interval(bgp, data->sensor_id, TI_BANDGAP_UPDATE_INTERVAL_MS); - if (devm_thermal_add_hwmon_sysfs(bgp->dev, data->ti_thermal)) - dev_warn(bgp->dev, "failed to add hwmon sysfs attributes\n"); + devm_thermal_add_hwmon_sysfs(bgp->dev, data->ti_thermal); return 0; } diff --git a/drivers/thunderbolt/Makefile b/drivers/thunderbolt/Makefile index 78fd365893c13f284a7de60b399edb0da0a40aec..c8b3d7b780982f18c5e4b6c927b08662c38ec440 100644 --- a/drivers/thunderbolt/Makefile +++ b/drivers/thunderbolt/Makefile @@ -2,7 +2,7 @@ obj-${CONFIG_USB4} := thunderbolt.o thunderbolt-objs := nhi.o nhi_ops.o ctl.o tb.o switch.o cap.o path.o tunnel.o eeprom.o thunderbolt-objs += domain.o dma_port.o icm.o property.o xdomain.o lc.o tmu.o usb4.o -thunderbolt-objs += usb4_port.o nvm.o retimer.o quirks.o +thunderbolt-objs += usb4_port.o nvm.o retimer.o quirks.o clx.o thunderbolt-${CONFIG_ACPI} += acpi.o thunderbolt-$(CONFIG_DEBUG_FS) += debugfs.o diff --git a/drivers/thunderbolt/acpi.c b/drivers/thunderbolt/acpi.c index 3514bf65b7a49e7c825b8191d8c61e636db06a9f..38fefd0e5268d230b5745e6f431530df4591f791 100644 --- a/drivers/thunderbolt/acpi.c +++ b/drivers/thunderbolt/acpi.c @@ -296,16 +296,15 @@ static bool tb_acpi_bus_match(struct device *dev) static struct acpi_device *tb_acpi_switch_find_companion(struct tb_switch *sw) { + struct tb_switch *parent_sw = tb_switch_parent(sw); struct acpi_device *adev = NULL; - struct tb_switch *parent_sw; /* * Device routers exists under the downstream facing USB4 port * of the parent router. Their _ADR is always 0. */ - parent_sw = tb_switch_parent(sw); if (parent_sw) { - struct tb_port *port = tb_port_at(tb_route(sw), parent_sw); + struct tb_port *port = tb_switch_downstream_port(sw); struct acpi_device *port_adev; port_adev = acpi_find_child_by_adr(ACPI_COMPANION(&parent_sw->dev), diff --git a/drivers/thunderbolt/clx.c b/drivers/thunderbolt/clx.c new file mode 100644 index 0000000000000000000000000000000000000000..13d217ae98e6b14c55e5d78b806e02cc8b18609b --- /dev/null +++ b/drivers/thunderbolt/clx.c @@ -0,0 +1,423 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * CLx support + * + * Copyright (C) 2020 - 2023, Intel Corporation + * Authors: Gil Fine + * Mika Westerberg + */ + +#include + +#include "tb.h" + +static bool clx_enabled = true; +module_param_named(clx, clx_enabled, bool, 0444); +MODULE_PARM_DESC(clx, "allow low power states on the high-speed lanes (default: true)"); + +static const char *clx_name(unsigned int clx) +{ + switch (clx) { + case TB_CL0S | TB_CL1 | TB_CL2: + return "CL0s/CL1/CL2"; + case TB_CL1 | TB_CL2: + return "CL1/CL2"; + case TB_CL0S | TB_CL2: + return "CL0s/CL2"; + case TB_CL0S | TB_CL1: + return "CL0s/CL1"; + case TB_CL0S: + return "CL0s"; + case 0: + return "disabled"; + default: + return "unknown"; + } +} + +static int tb_port_pm_secondary_set(struct tb_port *port, bool secondary) +{ + u32 phy; + int ret; + + ret = tb_port_read(port, &phy, TB_CFG_PORT, + port->cap_phy + LANE_ADP_CS_1, 1); + if (ret) + return ret; + + if (secondary) + phy |= LANE_ADP_CS_1_PMS; + else + phy &= ~LANE_ADP_CS_1_PMS; + + return tb_port_write(port, &phy, TB_CFG_PORT, + port->cap_phy + LANE_ADP_CS_1, 1); +} + +static int tb_port_pm_secondary_enable(struct tb_port *port) +{ + return tb_port_pm_secondary_set(port, true); +} + +static int tb_port_pm_secondary_disable(struct tb_port *port) +{ + return tb_port_pm_secondary_set(port, false); +} + +/* Called for USB4 or Titan Ridge routers only */ +static bool tb_port_clx_supported(struct tb_port *port, unsigned int clx) +{ + u32 val, mask = 0; + bool ret; + + /* Don't enable CLx in case of two single-lane links */ + if (!port->bonded && port->dual_link_port) + return false; + + /* Don't enable CLx in case of inter-domain link */ + if (port->xdomain) + return false; + + if (tb_switch_is_usb4(port->sw)) { + if (!usb4_port_clx_supported(port)) + return false; + } else if (!tb_lc_is_clx_supported(port)) { + return false; + } + + if (clx & TB_CL0S) + mask |= LANE_ADP_CS_0_CL0S_SUPPORT; + if (clx & TB_CL1) + mask |= LANE_ADP_CS_0_CL1_SUPPORT; + if (clx & TB_CL2) + mask |= LANE_ADP_CS_0_CL2_SUPPORT; + + ret = tb_port_read(port, &val, TB_CFG_PORT, + port->cap_phy + LANE_ADP_CS_0, 1); + if (ret) + return false; + + return !!(val & mask); +} + +static int tb_port_clx_set(struct tb_port *port, unsigned int clx, bool enable) +{ + u32 phy, mask = 0; + int ret; + + if (clx & TB_CL0S) + mask |= LANE_ADP_CS_1_CL0S_ENABLE; + if (clx & TB_CL1) + mask |= LANE_ADP_CS_1_CL1_ENABLE; + if (clx & TB_CL2) + mask |= LANE_ADP_CS_1_CL2_ENABLE; + + if (!mask) + return -EOPNOTSUPP; + + ret = tb_port_read(port, &phy, TB_CFG_PORT, + port->cap_phy + LANE_ADP_CS_1, 1); + if (ret) + return ret; + + if (enable) + phy |= mask; + else + phy &= ~mask; + + return tb_port_write(port, &phy, TB_CFG_PORT, + port->cap_phy + LANE_ADP_CS_1, 1); +} + +static int tb_port_clx_disable(struct tb_port *port, unsigned int clx) +{ + return tb_port_clx_set(port, clx, false); +} + +static int tb_port_clx_enable(struct tb_port *port, unsigned int clx) +{ + return tb_port_clx_set(port, clx, true); +} + +static int tb_port_clx(struct tb_port *port) +{ + u32 val; + int ret; + + if (!tb_port_clx_supported(port, TB_CL0S | TB_CL1 | TB_CL2)) + return 0; + + ret = tb_port_read(port, &val, TB_CFG_PORT, + port->cap_phy + LANE_ADP_CS_1, 1); + if (ret) + return ret; + + if (val & LANE_ADP_CS_1_CL0S_ENABLE) + ret |= TB_CL0S; + if (val & LANE_ADP_CS_1_CL1_ENABLE) + ret |= TB_CL1; + if (val & LANE_ADP_CS_1_CL2_ENABLE) + ret |= TB_CL2; + + return ret; +} + +/** + * tb_port_clx_is_enabled() - Is given CL state enabled + * @port: USB4 port to check + * @clx: Mask of CL states to check + * + * Returns true if any of the given CL states is enabled for @port. + */ +bool tb_port_clx_is_enabled(struct tb_port *port, unsigned int clx) +{ + return !!(tb_port_clx(port) & clx); +} + +/** + * tb_switch_clx_init() - Initialize router CL states + * @sw: Router + * + * Can be called for any router. Initializes the current CL state by + * reading it from the hardware. + * + * Returns %0 in case of success and negative errno in case of failure. + */ +int tb_switch_clx_init(struct tb_switch *sw) +{ + struct tb_port *up, *down; + unsigned int clx, tmp; + + if (tb_switch_is_icm(sw)) + return 0; + + if (!tb_route(sw)) + return 0; + + if (!tb_switch_clx_is_supported(sw)) + return 0; + + up = tb_upstream_port(sw); + down = tb_switch_downstream_port(sw); + + clx = tb_port_clx(up); + tmp = tb_port_clx(down); + if (clx != tmp) + tb_sw_warn(sw, "CLx: inconsistent configuration %#x != %#x\n", + clx, tmp); + + tb_sw_dbg(sw, "CLx: current mode: %s\n", clx_name(clx)); + + sw->clx = clx; + return 0; +} + +static int tb_switch_pm_secondary_resolve(struct tb_switch *sw) +{ + struct tb_port *up, *down; + int ret; + + if (!tb_route(sw)) + return 0; + + up = tb_upstream_port(sw); + down = tb_switch_downstream_port(sw); + ret = tb_port_pm_secondary_enable(up); + if (ret) + return ret; + + return tb_port_pm_secondary_disable(down); +} + +static int tb_switch_mask_clx_objections(struct tb_switch *sw) +{ + int up_port = sw->config.upstream_port_number; + u32 offset, val[2], mask_obj, unmask_obj; + int ret, i; + + /* Only Titan Ridge of pre-USB4 devices support CLx states */ + if (!tb_switch_is_titan_ridge(sw)) + return 0; + + if (!tb_route(sw)) + return 0; + + /* + * In Titan Ridge there are only 2 dual-lane Thunderbolt ports: + * Port A consists of lane adapters 1,2 and + * Port B consists of lane adapters 3,4 + * If upstream port is A, (lanes are 1,2), we mask objections from + * port B (lanes 3,4) and unmask objections from Port A and vice-versa. + */ + if (up_port == 1) { + mask_obj = TB_LOW_PWR_C0_PORT_B_MASK; + unmask_obj = TB_LOW_PWR_C1_PORT_A_MASK; + offset = TB_LOW_PWR_C1_CL1; + } else { + mask_obj = TB_LOW_PWR_C1_PORT_A_MASK; + unmask_obj = TB_LOW_PWR_C0_PORT_B_MASK; + offset = TB_LOW_PWR_C3_CL1; + } + + ret = tb_sw_read(sw, &val, TB_CFG_SWITCH, + sw->cap_lp + offset, ARRAY_SIZE(val)); + if (ret) + return ret; + + for (i = 0; i < ARRAY_SIZE(val); i++) { + val[i] |= mask_obj; + val[i] &= ~unmask_obj; + } + + return tb_sw_write(sw, &val, TB_CFG_SWITCH, + sw->cap_lp + offset, ARRAY_SIZE(val)); +} + +/** + * tb_switch_clx_is_supported() - Is CLx supported on this type of router + * @sw: The router to check CLx support for + */ +bool tb_switch_clx_is_supported(const struct tb_switch *sw) +{ + if (!clx_enabled) + return false; + + if (sw->quirks & QUIRK_NO_CLX) + return false; + + /* + * CLx is not enabled and validated on Intel USB4 platforms + * before Alder Lake. + */ + if (tb_switch_is_tiger_lake(sw)) + return false; + + return tb_switch_is_usb4(sw) || tb_switch_is_titan_ridge(sw); +} + +static bool validate_mask(unsigned int clx) +{ + /* Previous states need to be enabled */ + if (clx & TB_CL1) + return (clx & TB_CL0S) == TB_CL0S; + return true; +} + +/** + * tb_switch_clx_enable() - Enable CLx on upstream port of specified router + * @sw: Router to enable CLx for + * @clx: The CLx state to enable + * + * CLx is enabled only if both sides of the link support CLx, and if both sides + * of the link are not configured as two single lane links and only if the link + * is not inter-domain link. The complete set of conditions is described in CM + * Guide 1.0 section 8.1. + * + * Returns %0 on success or an error code on failure. + */ +int tb_switch_clx_enable(struct tb_switch *sw, unsigned int clx) +{ + bool up_clx_support, down_clx_support; + struct tb_switch *parent_sw; + struct tb_port *up, *down; + int ret; + + if (!clx || sw->clx == clx) + return 0; + + if (!validate_mask(clx)) + return -EINVAL; + + parent_sw = tb_switch_parent(sw); + if (!parent_sw) + return 0; + + if (!tb_switch_clx_is_supported(parent_sw) || + !tb_switch_clx_is_supported(sw)) + return 0; + + /* Only support CL2 for v2 routers */ + if ((clx & TB_CL2) && + (usb4_switch_version(parent_sw) < 2 || + usb4_switch_version(sw) < 2)) + return -EOPNOTSUPP; + + ret = tb_switch_pm_secondary_resolve(sw); + if (ret) + return ret; + + up = tb_upstream_port(sw); + down = tb_switch_downstream_port(sw); + + up_clx_support = tb_port_clx_supported(up, clx); + down_clx_support = tb_port_clx_supported(down, clx); + + tb_port_dbg(up, "CLx: %s %ssupported\n", clx_name(clx), + up_clx_support ? "" : "not "); + tb_port_dbg(down, "CLx: %s %ssupported\n", clx_name(clx), + down_clx_support ? "" : "not "); + + if (!up_clx_support || !down_clx_support) + return -EOPNOTSUPP; + + ret = tb_port_clx_enable(up, clx); + if (ret) + return ret; + + ret = tb_port_clx_enable(down, clx); + if (ret) { + tb_port_clx_disable(up, clx); + return ret; + } + + ret = tb_switch_mask_clx_objections(sw); + if (ret) { + tb_port_clx_disable(up, clx); + tb_port_clx_disable(down, clx); + return ret; + } + + sw->clx |= clx; + + tb_sw_dbg(sw, "CLx: %s enabled\n", clx_name(clx)); + return 0; +} + +/** + * tb_switch_clx_disable() - Disable CLx on upstream port of specified router + * @sw: Router to disable CLx for + * + * Disables all CL states of the given router. Can be called on any + * router and if the states were not enabled already does nothing. + * + * Returns the CL states that were disabled or negative errno in case of + * failure. + */ +int tb_switch_clx_disable(struct tb_switch *sw) +{ + unsigned int clx = sw->clx; + struct tb_port *up, *down; + int ret; + + if (!tb_switch_clx_is_supported(sw)) + return 0; + + if (!clx) + return 0; + + up = tb_upstream_port(sw); + down = tb_switch_downstream_port(sw); + + ret = tb_port_clx_disable(up, clx); + if (ret) + return ret; + + ret = tb_port_clx_disable(down, clx); + if (ret) + return ret; + + sw->clx = 0; + + tb_sw_dbg(sw, "CLx: %s disabled\n", clx_name(clx)); + return clx; +} diff --git a/drivers/thunderbolt/ctl.c b/drivers/thunderbolt/ctl.c index 3a213322ec7a9dae5082bdfe5de970494c30f015..d997a4c545f7965e799dcb4ef06b1cee3491306b 100644 --- a/drivers/thunderbolt/ctl.c +++ b/drivers/thunderbolt/ctl.c @@ -409,6 +409,13 @@ static int tb_async_error(const struct ctl_pkg *pkg) case TB_CFG_ERROR_HEC_ERROR_DETECTED: case TB_CFG_ERROR_FLOW_CONTROL_ERROR: case TB_CFG_ERROR_DP_BW: + case TB_CFG_ERROR_ROP_CMPLT: + case TB_CFG_ERROR_POP_CMPLT: + case TB_CFG_ERROR_PCIE_WAKE: + case TB_CFG_ERROR_DP_CON_CHANGE: + case TB_CFG_ERROR_DPTX_DISCOVERY: + case TB_CFG_ERROR_LINK_RECOVERY: + case TB_CFG_ERROR_ASYM_LINK: return true; default: @@ -758,6 +765,27 @@ int tb_cfg_ack_notification(struct tb_ctl *ctl, u64 route, case TB_CFG_ERROR_DP_BW: name = "DP_BW"; break; + case TB_CFG_ERROR_ROP_CMPLT: + name = "router operation completion"; + break; + case TB_CFG_ERROR_POP_CMPLT: + name = "port operation completion"; + break; + case TB_CFG_ERROR_PCIE_WAKE: + name = "PCIe wake"; + break; + case TB_CFG_ERROR_DP_CON_CHANGE: + name = "DP connector change"; + break; + case TB_CFG_ERROR_DPTX_DISCOVERY: + name = "DPTX discovery"; + break; + case TB_CFG_ERROR_LINK_RECOVERY: + name = "link recovery"; + break; + case TB_CFG_ERROR_ASYM_LINK: + name = "asymmetric link"; + break; default: name = "unknown"; break; diff --git a/drivers/thunderbolt/debugfs.c b/drivers/thunderbolt/debugfs.c index f92ad71ef9831fa3611134c764af3af68b1c4582..c9ddd49138d8223e913c99f1a463880840473620 100644 --- a/drivers/thunderbolt/debugfs.c +++ b/drivers/thunderbolt/debugfs.c @@ -14,12 +14,15 @@ #include "tb.h" #include "sb_regs.h" -#define PORT_CAP_PCIE_LEN 1 +#define PORT_CAP_V1_PCIE_LEN 1 +#define PORT_CAP_V2_PCIE_LEN 2 #define PORT_CAP_POWER_LEN 2 #define PORT_CAP_LANE_LEN 3 #define PORT_CAP_USB3_LEN 5 -#define PORT_CAP_DP_LEN 8 -#define PORT_CAP_TMU_LEN 8 +#define PORT_CAP_DP_V1_LEN 9 +#define PORT_CAP_DP_V2_LEN 14 +#define PORT_CAP_TMU_V1_LEN 8 +#define PORT_CAP_TMU_V2_LEN 10 #define PORT_CAP_BASIC_LEN 9 #define PORT_CAP_USB4_LEN 20 @@ -553,8 +556,9 @@ static int margining_run_write(void *data, u64 val) struct usb4_port *usb4 = port->usb4; struct tb_switch *sw = port->sw; struct tb_margining *margining; + struct tb_switch *down_sw; struct tb *tb = sw->tb; - int ret; + int ret, clx; if (val != 1) return -EINVAL; @@ -566,15 +570,24 @@ static int margining_run_write(void *data, u64 val) goto out_rpm_put; } - /* - * CL states may interfere with lane margining so inform the user know - * and bail out. - */ - if (tb_port_is_clx_enabled(port, TB_CL1 | TB_CL2)) { - tb_port_warn(port, - "CL states are enabled, Disable them with clx=0 and re-connect\n"); - ret = -EINVAL; - goto out_unlock; + if (tb_is_upstream_port(port)) + down_sw = sw; + else if (port->remote) + down_sw = port->remote->sw; + else + down_sw = NULL; + + if (down_sw) { + /* + * CL states may interfere with lane margining so + * disable them temporarily now. + */ + ret = tb_switch_clx_disable(down_sw); + if (ret < 0) { + tb_sw_warn(down_sw, "failed to disable CL states\n"); + goto out_unlock; + } + clx = ret; } margining = usb4->margining; @@ -586,7 +599,7 @@ static int margining_run_write(void *data, u64 val) margining->right_high, USB4_MARGIN_SW_COUNTER_CLEAR); if (ret) - goto out_unlock; + goto out_clx; ret = usb4_port_sw_margin_errors(port, &margining->results[0]); } else { @@ -600,6 +613,9 @@ static int margining_run_write(void *data, u64 val) margining->right_high, margining->results); } +out_clx: + if (down_sw) + tb_switch_clx_enable(down_sw, clx); out_unlock: mutex_unlock(&tb->lock); out_rpm_put: @@ -1148,7 +1164,10 @@ static void port_cap_show(struct tb_port *port, struct seq_file *s, break; case TB_PORT_CAP_TIME1: - length = PORT_CAP_TMU_LEN; + if (usb4_switch_version(port->sw) < 2) + length = PORT_CAP_TMU_V1_LEN; + else + length = PORT_CAP_TMU_V2_LEN; break; case TB_PORT_CAP_POWER: @@ -1157,12 +1176,17 @@ static void port_cap_show(struct tb_port *port, struct seq_file *s, case TB_PORT_CAP_ADAP: if (tb_port_is_pcie_down(port) || tb_port_is_pcie_up(port)) { - length = PORT_CAP_PCIE_LEN; - } else if (tb_port_is_dpin(port) || tb_port_is_dpout(port)) { - if (usb4_dp_port_bw_mode_supported(port)) - length = PORT_CAP_DP_LEN + 1; + if (usb4_switch_version(port->sw) < 2) + length = PORT_CAP_V1_PCIE_LEN; + else + length = PORT_CAP_V2_PCIE_LEN; + } else if (tb_port_is_dpin(port)) { + if (usb4_switch_version(port->sw) < 2) + length = PORT_CAP_DP_V1_LEN; else - length = PORT_CAP_DP_LEN; + length = PORT_CAP_DP_V2_LEN; + } else if (tb_port_is_dpout(port)) { + length = PORT_CAP_DP_V1_LEN; } else if (tb_port_is_usb3_down(port) || tb_port_is_usb3_up(port)) { length = PORT_CAP_USB3_LEN; diff --git a/drivers/thunderbolt/dma_test.c b/drivers/thunderbolt/dma_test.c index 14bb6dec6c4b023c38ff671da20965c18a82d2b3..39476fc488015b2470bc790e568308f8680a904d 100644 --- a/drivers/thunderbolt/dma_test.c +++ b/drivers/thunderbolt/dma_test.c @@ -412,6 +412,7 @@ static void speed_get(const struct dma_test *dt, u64 *val) static int speed_validate(u64 val) { switch (val) { + case 40: case 20: case 10: case 0: @@ -489,9 +490,12 @@ static void dma_test_check_errors(struct dma_test *dt, int ret) if (!dt->error_code) { if (dt->link_speed && dt->xd->link_speed != dt->link_speed) { dt->error_code = DMA_TEST_SPEED_ERROR; - } else if (dt->link_width && - dt->xd->link_width != dt->link_width) { - dt->error_code = DMA_TEST_WIDTH_ERROR; + } else if (dt->link_width) { + const struct tb_xdomain *xd = dt->xd; + + if ((dt->link_width == 1 && xd->link_width != TB_LINK_WIDTH_SINGLE) || + (dt->link_width == 2 && xd->link_width < TB_LINK_WIDTH_DUAL)) + dt->error_code = DMA_TEST_WIDTH_ERROR; } else if (dt->packets_to_send != dt->packets_sent || dt->packets_to_receive != dt->packets_received || dt->crc_errors || dt->buffer_overflow_errors) { @@ -756,5 +760,5 @@ module_exit(dma_test_exit); MODULE_AUTHOR("Isaac Hazan "); MODULE_AUTHOR("Mika Westerberg "); -MODULE_DESCRIPTION("DMA traffic test driver"); +MODULE_DESCRIPTION("Thunderbolt/USB4 DMA traffic test driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/thunderbolt/eeprom.c b/drivers/thunderbolt/eeprom.c index 0f6099c18a9415b9c58edc4acac470d4aed421eb..eb241b270f790b2a1eafa3a5b87aacbd9c65da32 100644 --- a/drivers/thunderbolt/eeprom.c +++ b/drivers/thunderbolt/eeprom.c @@ -605,9 +605,8 @@ static int usb4_drom_parse(struct tb_switch *sw) crc = tb_crc32(sw->drom + TB_DROM_DATA_START, header->data_len); if (crc != header->data_crc32) { tb_sw_warn(sw, - "DROM data CRC32 mismatch (expected: %#x, got: %#x), aborting\n", + "DROM data CRC32 mismatch (expected: %#x, got: %#x), continuing\n", header->data_crc32, crc); - return -EINVAL; } return tb_drom_parse_entries(sw, USB4_DROM_HEADER_SIZE); diff --git a/drivers/thunderbolt/icm.c b/drivers/thunderbolt/icm.c index 86521ebb257942b6826348de39645354d3c310a1..dbdcad8d73bf63c6ba5d911d98719d12b65021dc 100644 --- a/drivers/thunderbolt/icm.c +++ b/drivers/thunderbolt/icm.c @@ -644,13 +644,14 @@ static int add_switch(struct tb_switch *parent_sw, struct tb_switch *sw) return ret; } -static void update_switch(struct tb_switch *parent_sw, struct tb_switch *sw, - u64 route, u8 connection_id, u8 connection_key, - u8 link, u8 depth, bool boot) +static void update_switch(struct tb_switch *sw, u64 route, u8 connection_id, + u8 connection_key, u8 link, u8 depth, bool boot) { + struct tb_switch *parent_sw = tb_switch_parent(sw); + /* Disconnect from parent */ - tb_port_at(tb_route(sw), parent_sw)->remote = NULL; - /* Re-connect via updated port*/ + tb_switch_downstream_port(sw)->remote = NULL; + /* Re-connect via updated port */ tb_port_at(route, parent_sw)->remote = tb_upstream_port(sw); /* Update with the new addressing information */ @@ -671,10 +672,7 @@ static void update_switch(struct tb_switch *parent_sw, struct tb_switch *sw, static void remove_switch(struct tb_switch *sw) { - struct tb_switch *parent_sw; - - parent_sw = tb_to_switch(sw->dev.parent); - tb_port_at(tb_route(sw), parent_sw)->remote = NULL; + tb_switch_downstream_port(sw)->remote = NULL; tb_switch_remove(sw); } @@ -755,7 +753,6 @@ icm_fr_device_connected(struct tb *tb, const struct icm_pkg_header *hdr) if (sw) { u8 phy_port, sw_phy_port; - parent_sw = tb_to_switch(sw->dev.parent); sw_phy_port = tb_phy_port_from_link(sw->link); phy_port = tb_phy_port_from_link(link); @@ -785,7 +782,7 @@ icm_fr_device_connected(struct tb *tb, const struct icm_pkg_header *hdr) route = tb_route(sw); } - update_switch(parent_sw, sw, route, pkg->connection_id, + update_switch(sw, route, pkg->connection_id, pkg->connection_key, link, depth, boot); tb_switch_put(sw); return; @@ -853,7 +850,8 @@ icm_fr_device_connected(struct tb *tb, const struct icm_pkg_header *hdr) sw->security_level = security_level; sw->boot = boot; sw->link_speed = speed_gen3 ? 20 : 10; - sw->link_width = dual_lane ? 2 : 1; + sw->link_width = dual_lane ? TB_LINK_WIDTH_DUAL : + TB_LINK_WIDTH_SINGLE; sw->rpm = intel_vss_is_rtd3(pkg->ep_name, sizeof(pkg->ep_name)); if (add_switch(parent_sw, sw)) @@ -1236,9 +1234,8 @@ __icm_tr_device_connected(struct tb *tb, const struct icm_pkg_header *hdr, if (sw) { /* Update the switch if it is still in the same place */ if (tb_route(sw) == route && !!sw->authorized == authorized) { - parent_sw = tb_to_switch(sw->dev.parent); - update_switch(parent_sw, sw, route, pkg->connection_id, - 0, 0, 0, boot); + update_switch(sw, route, pkg->connection_id, 0, 0, 0, + boot); tb_switch_put(sw); return; } @@ -1276,7 +1273,8 @@ __icm_tr_device_connected(struct tb *tb, const struct icm_pkg_header *hdr, sw->security_level = security_level; sw->boot = boot; sw->link_speed = speed_gen3 ? 20 : 10; - sw->link_width = dual_lane ? 2 : 1; + sw->link_width = dual_lane ? TB_LINK_WIDTH_DUAL : + TB_LINK_WIDTH_SINGLE; sw->rpm = force_rtd3; if (!sw->rpm) sw->rpm = intel_vss_is_rtd3(pkg->ep_name, diff --git a/drivers/thunderbolt/nhi.c b/drivers/thunderbolt/nhi.c index e58beac442958c922a55bc876d9c39c8912cd4c7..4b7bec74e89fbcf02b17ae44b54087dac01518b2 100644 --- a/drivers/thunderbolt/nhi.c +++ b/drivers/thunderbolt/nhi.c @@ -46,6 +46,10 @@ #define QUIRK_AUTO_CLEAR_INT BIT(0) #define QUIRK_E2E BIT(1) +static bool host_reset = true; +module_param(host_reset, bool, 0444); +MODULE_PARM_DESC(host_reset, "reset USBv2 host router (default: true)"); + static int ring_interrupt_index(const struct tb_ring *ring) { int bit = ring->hop; @@ -1217,6 +1221,37 @@ static void nhi_check_iommu(struct tb_nhi *nhi) str_enabled_disabled(port_ok)); } +static void nhi_reset(struct tb_nhi *nhi) +{ + ktime_t timeout; + u32 val; + + val = ioread32(nhi->iobase + REG_CAPS); + /* Reset only v2 and later routers */ + if (FIELD_GET(REG_CAPS_VERSION_MASK, val) < REG_CAPS_VERSION_2) + return; + + if (!host_reset) { + dev_dbg(&nhi->pdev->dev, "skipping host router reset\n"); + return; + } + + iowrite32(REG_RESET_HRR, nhi->iobase + REG_RESET); + msleep(100); + + timeout = ktime_add_ms(ktime_get(), 500); + do { + val = ioread32(nhi->iobase + REG_RESET); + if (!(val & REG_RESET_HRR)) { + dev_warn(&nhi->pdev->dev, "host router reset successful\n"); + return; + } + usleep_range(10, 20); + } while (ktime_before(ktime_get(), timeout)); + + dev_warn(&nhi->pdev->dev, "timeout resetting host router\n"); +} + static int nhi_init_msi(struct tb_nhi *nhi) { struct pci_dev *pdev = nhi->pdev; @@ -1317,7 +1352,7 @@ static int nhi_probe(struct pci_dev *pdev, const struct pci_device_id *id) nhi->ops = (const struct tb_nhi_ops *)id->driver_data; /* cannot fail - table is allocated in pcim_iomap_regions */ nhi->iobase = pcim_iomap_table(pdev)[0]; - nhi->hop_count = ioread32(nhi->iobase + REG_HOP_COUNT) & 0x3ff; + nhi->hop_count = ioread32(nhi->iobase + REG_CAPS) & 0x3ff; dev_dbg(dev, "total paths: %d\n", nhi->hop_count); nhi->tx_rings = devm_kcalloc(&pdev->dev, nhi->hop_count, @@ -1330,6 +1365,8 @@ static int nhi_probe(struct pci_dev *pdev, const struct pci_device_id *id) nhi_check_quirks(nhi); nhi_check_iommu(nhi); + nhi_reset(nhi); + res = nhi_init_msi(nhi); if (res) return dev_err_probe(dev, res, "cannot enable MSI, aborting\n"); @@ -1480,6 +1517,8 @@ static struct pci_device_id nhi_ids[] = { .driver_data = (kernel_ulong_t)&icl_nhi_ops }, { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_MTL_P_NHI1), .driver_data = (kernel_ulong_t)&icl_nhi_ops }, + { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_BARLOW_RIDGE_HOST_80G_NHI) }, + { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_BARLOW_RIDGE_HOST_40G_NHI) }, /* Any USB4 compliant host */ { PCI_DEVICE_CLASS(PCI_CLASS_SERIAL_USB_USB4, ~0) }, @@ -1488,6 +1527,7 @@ static struct pci_device_id nhi_ids[] = { }; MODULE_DEVICE_TABLE(pci, nhi_ids); +MODULE_DESCRIPTION("Thunderbolt/USB4 core driver"); MODULE_LICENSE("GPL"); static struct pci_driver nhi_driver = { diff --git a/drivers/thunderbolt/nhi.h b/drivers/thunderbolt/nhi.h index b0718020c6f597031beb497060861e33c32831be..0f029ce758825e0a05c16def1b7255f9742e338b 100644 --- a/drivers/thunderbolt/nhi.h +++ b/drivers/thunderbolt/nhi.h @@ -75,6 +75,10 @@ extern const struct tb_nhi_ops icl_nhi_ops; #define PCI_DEVICE_ID_INTEL_TITAN_RIDGE_DD_BRIDGE 0x15ef #define PCI_DEVICE_ID_INTEL_ADL_NHI0 0x463e #define PCI_DEVICE_ID_INTEL_ADL_NHI1 0x466d +#define PCI_DEVICE_ID_INTEL_BARLOW_RIDGE_HOST_80G_NHI 0x5781 +#define PCI_DEVICE_ID_INTEL_BARLOW_RIDGE_HOST_40G_NHI 0x5784 +#define PCI_DEVICE_ID_INTEL_BARLOW_RIDGE_HUB_80G_BRIDGE 0x5786 +#define PCI_DEVICE_ID_INTEL_BARLOW_RIDGE_HUB_40G_BRIDGE 0x57a4 #define PCI_DEVICE_ID_INTEL_MTL_M_NHI0 0x7eb2 #define PCI_DEVICE_ID_INTEL_MTL_P_NHI0 0x7ec2 #define PCI_DEVICE_ID_INTEL_MTL_P_NHI1 0x7ec3 diff --git a/drivers/thunderbolt/nhi_regs.h b/drivers/thunderbolt/nhi_regs.h index 6ba2958154770f9d2f2e11251b754c818baf360e..297a3e4406486089d4686dc4be734fefaae862f3 100644 --- a/drivers/thunderbolt/nhi_regs.h +++ b/drivers/thunderbolt/nhi_regs.h @@ -37,7 +37,7 @@ struct ring_desc { /* NHI registers in bar 0 */ /* - * 16 bytes per entry, one entry for every hop (REG_HOP_COUNT) + * 16 bytes per entry, one entry for every hop (REG_CAPS) * 00: physical pointer to an array of struct ring_desc * 08: ring tail (set by NHI) * 10: ring head (index of first non posted descriptor) @@ -46,7 +46,7 @@ struct ring_desc { #define REG_TX_RING_BASE 0x00000 /* - * 16 bytes per entry, one entry for every hop (REG_HOP_COUNT) + * 16 bytes per entry, one entry for every hop (REG_CAPS) * 00: physical pointer to an array of struct ring_desc * 08: ring head (index of first not posted descriptor) * 10: ring tail (set by NHI) @@ -56,7 +56,7 @@ struct ring_desc { #define REG_RX_RING_BASE 0x08000 /* - * 32 bytes per entry, one entry for every hop (REG_HOP_COUNT) + * 32 bytes per entry, one entry for every hop (REG_CAPS) * 00: enum_ring_flags * 04: isoch time stamp ?? (write 0) * ..: unknown @@ -64,7 +64,7 @@ struct ring_desc { #define REG_TX_OPTIONS_BASE 0x19800 /* - * 32 bytes per entry, one entry for every hop (REG_HOP_COUNT) + * 32 bytes per entry, one entry for every hop (REG_CAPS) * 00: enum ring_flags * If RING_FLAG_E2E_FLOW_CONTROL is set then bits 13-23 must be set to * the corresponding TX hop id. @@ -77,7 +77,7 @@ struct ring_desc { /* * three bitfields: tx, rx, rx overflow - * Every bitfield contains one bit for every hop (REG_HOP_COUNT). + * Every bitfield contains one bit for every hop (REG_CAPS). * New interrupts are fired only after ALL registers have been * read (even those containing only disabled rings). */ @@ -87,7 +87,7 @@ struct ring_desc { /* * two bitfields: rx, tx - * Both bitfields contains one bit for every hop (REG_HOP_COUNT). To + * Both bitfields contains one bit for every hop (REG_CAPS). To * enable/disable interrupts set/clear the corresponding bits. */ #define REG_RING_INTERRUPT_BASE 0x38200 @@ -104,12 +104,17 @@ struct ring_desc { #define REG_INT_VEC_ALLOC_REGS (32 / REG_INT_VEC_ALLOC_BITS) /* The last 11 bits contain the number of hops supported by the NHI port. */ -#define REG_HOP_COUNT 0x39640 +#define REG_CAPS 0x39640 +#define REG_CAPS_VERSION_MASK GENMASK(23, 16) +#define REG_CAPS_VERSION_2 0x40 #define REG_DMA_MISC 0x39864 #define REG_DMA_MISC_INT_AUTO_CLEAR BIT(2) #define REG_DMA_MISC_DISABLE_AUTO_CLEAR BIT(17) +#define REG_RESET 0x39898 +#define REG_RESET_HRR BIT(0) + #define REG_INMAIL_DATA 0x39900 #define REG_INMAIL_CMD 0x39904 diff --git a/drivers/thunderbolt/nvm.c b/drivers/thunderbolt/nvm.c index 3dd5f81bd629355ab2274848b02bb08b29d8941b..69fb3b0fa34fa34323b2c0f74788a7e5f2b67dd2 100644 --- a/drivers/thunderbolt/nvm.c +++ b/drivers/thunderbolt/nvm.c @@ -12,6 +12,10 @@ #include "tb.h" +#define NVM_MIN_SIZE SZ_32K +#define NVM_MAX_SIZE SZ_1M +#define NVM_DATA_DWORDS 16 + /* Intel specific NVM offsets */ #define INTEL_NVM_DEVID 0x05 #define INTEL_NVM_VERSION 0x08 diff --git a/drivers/thunderbolt/quirks.c b/drivers/thunderbolt/quirks.c index 1157b8869bcca1da217285202b74b53bea2bf703..488138a28ae13bde67b6ae4953f6fccfc17a3c29 100644 --- a/drivers/thunderbolt/quirks.c +++ b/drivers/thunderbolt/quirks.c @@ -10,6 +10,7 @@ static void quirk_force_power_link(struct tb_switch *sw) { sw->quirks |= QUIRK_FORCE_POWER_LINK_CONTROLLER; + tb_sw_dbg(sw, "forcing power to link controller\n"); } static void quirk_dp_credit_allocation(struct tb_switch *sw) @@ -74,6 +75,14 @@ static const struct tb_quirk tb_quirks[] = { quirk_usb3_maximum_bandwidth }, { 0x8087, PCI_DEVICE_ID_INTEL_MTL_P_NHI1, 0x0000, 0x0000, quirk_usb3_maximum_bandwidth }, + { 0x8087, PCI_DEVICE_ID_INTEL_BARLOW_RIDGE_HOST_80G_NHI, 0x0000, 0x0000, + quirk_usb3_maximum_bandwidth }, + { 0x8087, PCI_DEVICE_ID_INTEL_BARLOW_RIDGE_HOST_40G_NHI, 0x0000, 0x0000, + quirk_usb3_maximum_bandwidth }, + { 0x8087, PCI_DEVICE_ID_INTEL_BARLOW_RIDGE_HUB_80G_BRIDGE, 0x0000, 0x0000, + quirk_usb3_maximum_bandwidth }, + { 0x8087, PCI_DEVICE_ID_INTEL_BARLOW_RIDGE_HUB_40G_BRIDGE, 0x0000, 0x0000, + quirk_usb3_maximum_bandwidth }, /* * CLx is not supported on AMD USB4 Yellow Carp and Pink Sardine platforms. */ @@ -105,6 +114,7 @@ void tb_check_quirks(struct tb_switch *sw) if (q->device && q->device != sw->device) continue; + tb_sw_dbg(sw, "running %ps\n", q->hook); q->hook(sw); } } diff --git a/drivers/thunderbolt/retimer.c b/drivers/thunderbolt/retimer.c index 9cc28197dbc45f7e6912ac43fc01d40fe5a80027..47becb363adacb50c5813946d6355d8a3dd6d14a 100644 --- a/drivers/thunderbolt/retimer.c +++ b/drivers/thunderbolt/retimer.c @@ -187,10 +187,34 @@ static ssize_t nvm_authenticate_show(struct device *dev, return ret; } +static void tb_retimer_nvm_authenticate_status(struct tb_port *port, u32 *status) +{ + int i; + + tb_port_dbg(port, "reading NVM authentication status of retimers\n"); + + /* + * Before doing anything else, read the authentication status. + * If the retimer has it set, store it for the new retimer + * device instance. + */ + for (i = 1; i <= TB_MAX_RETIMER_INDEX; i++) + usb4_port_retimer_nvm_authenticate_status(port, i, &status[i]); +} + static void tb_retimer_set_inbound_sbtx(struct tb_port *port) { int i; + /* + * When USB4 port is online sideband communications are + * already up. + */ + if (!usb4_port_device_is_offline(port->usb4)) + return; + + tb_port_dbg(port, "enabling sideband transactions\n"); + for (i = 1; i <= TB_MAX_RETIMER_INDEX; i++) usb4_port_retimer_set_inbound_sbtx(port, i); } @@ -199,6 +223,16 @@ static void tb_retimer_unset_inbound_sbtx(struct tb_port *port) { int i; + /* + * When USB4 port is offline we need to keep the sideband + * communications up to make it possible to communicate with + * the connected retimers. + */ + if (usb4_port_device_is_offline(port->usb4)) + return; + + tb_port_dbg(port, "disabling sideband transactions\n"); + for (i = TB_MAX_RETIMER_INDEX; i >= 1; i--) usb4_port_retimer_unset_inbound_sbtx(port, i); } @@ -229,6 +263,13 @@ static ssize_t nvm_authenticate_store(struct device *dev, rt->auth_status = 0; if (val) { + /* + * When NVM authentication starts the retimer is not + * accessible so calling tb_retimer_unset_inbound_sbtx() + * will fail and therefore we do not call it. Exception + * is when the validation fails or we only write the new + * NVM image without authentication. + */ tb_retimer_set_inbound_sbtx(rt->port); if (val == AUTHENTICATE_ONLY) { ret = tb_retimer_nvm_authenticate(rt, true); @@ -249,7 +290,8 @@ static ssize_t nvm_authenticate_store(struct device *dev, } exit_unlock: - tb_retimer_unset_inbound_sbtx(rt->port); + if (ret || val == WRITE_ONLY) + tb_retimer_unset_inbound_sbtx(rt->port); mutex_unlock(&rt->tb->lock); exit_rpm: pm_runtime_mark_last_busy(&rt->dev); @@ -341,12 +383,6 @@ static int tb_retimer_add(struct tb_port *port, u8 index, u32 auth_status) return ret; } - if (vendor != PCI_VENDOR_ID_INTEL && vendor != 0x8087) { - tb_port_info(port, "retimer NVM format of vendor %#x is not supported\n", - vendor); - return -EOPNOTSUPP; - } - /* * Check that it supports NVM operations. If not then don't add * the device at all. @@ -455,18 +491,16 @@ int tb_retimer_scan(struct tb_port *port, bool add) return ret; /* - * Enable sideband channel for each retimer. We can do this - * regardless whether there is device connected or not. + * Immediately after sending enumerate retimers read the + * authentication status of each retimer. */ - tb_retimer_set_inbound_sbtx(port); + tb_retimer_nvm_authenticate_status(port, status); /* - * Before doing anything else, read the authentication status. - * If the retimer has it set, store it for the new retimer - * device instance. + * Enable sideband channel for each retimer. We can do this + * regardless whether there is device connected or not. */ - for (i = 1; i <= TB_MAX_RETIMER_INDEX; i++) - usb4_port_retimer_nvm_authenticate_status(port, i, &status[i]); + tb_retimer_set_inbound_sbtx(port); for (i = 1; i <= TB_MAX_RETIMER_INDEX; i++) { /* diff --git a/drivers/thunderbolt/switch.c b/drivers/thunderbolt/switch.c index 51e86b5171c77e9c37c07cf184364f01bc9f896e..7ea63bb3171409cf504eb7b362ac2663df46d350 100644 --- a/drivers/thunderbolt/switch.c +++ b/drivers/thunderbolt/switch.c @@ -26,10 +26,6 @@ struct nvm_auth_status { u32 status; }; -static bool clx_enabled = true; -module_param_named(clx, clx_enabled, bool, 0444); -MODULE_PARM_DESC(clx, "allow low power states on the high-speed lanes (default: true)"); - /* * Hold NVM authentication failure status per switch This information * needs to stay around even when the switch gets power cycled so we @@ -727,7 +723,7 @@ static int tb_init_port(struct tb_port *port) * can be read from the path config space. Legacy * devices we use hard-coded value. */ - if (tb_switch_is_usb4(port->sw)) { + if (port->cap_usb4) { struct tb_regs_hop hop; if (!tb_port_read(port, &hop, TB_CFG_HOPS, 0, 2)) @@ -907,15 +903,23 @@ int tb_port_get_link_speed(struct tb_port *port) speed = (val & LANE_ADP_CS_1_CURRENT_SPEED_MASK) >> LANE_ADP_CS_1_CURRENT_SPEED_SHIFT; - return speed == LANE_ADP_CS_1_CURRENT_SPEED_GEN3 ? 20 : 10; + + switch (speed) { + case LANE_ADP_CS_1_CURRENT_SPEED_GEN4: + return 40; + case LANE_ADP_CS_1_CURRENT_SPEED_GEN3: + return 20; + default: + return 10; + } } /** * tb_port_get_link_width() - Get current link width * @port: Port to check (USB4 or CIO) * - * Returns link width. Return values can be 1 (Single-Lane), 2 (Dual-Lane) - * or negative errno in case of failure. + * Returns link width. Return the link width as encoded in &enum + * tb_link_width or negative errno in case of failure. */ int tb_port_get_link_width(struct tb_port *port) { @@ -930,11 +934,13 @@ int tb_port_get_link_width(struct tb_port *port) if (ret) return ret; + /* Matches the values in enum tb_link_width */ return (val & LANE_ADP_CS_1_CURRENT_WIDTH_MASK) >> LANE_ADP_CS_1_CURRENT_WIDTH_SHIFT; } -static bool tb_port_is_width_supported(struct tb_port *port, int width) +static bool tb_port_is_width_supported(struct tb_port *port, + unsigned int width_mask) { u32 phy, widths; int ret; @@ -950,20 +956,25 @@ static bool tb_port_is_width_supported(struct tb_port *port, int width) widths = (phy & LANE_ADP_CS_0_SUPPORTED_WIDTH_MASK) >> LANE_ADP_CS_0_SUPPORTED_WIDTH_SHIFT; - return !!(widths & width); + return widths & width_mask; +} + +static bool is_gen4_link(struct tb_port *port) +{ + return tb_port_get_link_speed(port) > 20; } /** * tb_port_set_link_width() - Set target link width of the lane adapter * @port: Lane adapter - * @width: Target link width (%1 or %2) + * @width: Target link width * * Sets the target link width of the lane adapter to @width. Does not * enable/disable lane bonding. For that call tb_port_set_lane_bonding(). * * Return: %0 in case of success and negative errno in case of error */ -int tb_port_set_link_width(struct tb_port *port, unsigned int width) +int tb_port_set_link_width(struct tb_port *port, enum tb_link_width width) { u32 val; int ret; @@ -978,11 +989,14 @@ int tb_port_set_link_width(struct tb_port *port, unsigned int width) val &= ~LANE_ADP_CS_1_TARGET_WIDTH_MASK; switch (width) { - case 1: + case TB_LINK_WIDTH_SINGLE: + /* Gen 4 link cannot be single */ + if (is_gen4_link(port)) + return -EOPNOTSUPP; val |= LANE_ADP_CS_1_TARGET_WIDTH_SINGLE << LANE_ADP_CS_1_TARGET_WIDTH_SHIFT; break; - case 2: + case TB_LINK_WIDTH_DUAL: val |= LANE_ADP_CS_1_TARGET_WIDTH_DUAL << LANE_ADP_CS_1_TARGET_WIDTH_SHIFT; break; @@ -1004,12 +1018,9 @@ int tb_port_set_link_width(struct tb_port *port, unsigned int width) * cases one should use tb_port_lane_bonding_enable() instead to enable * lane bonding. * - * As a side effect sets @port->bonding accordingly (and does the same - * for lane 1 too). - * * Return: %0 in case of success and negative errno in case of error */ -int tb_port_set_lane_bonding(struct tb_port *port, bool bonding) +static int tb_port_set_lane_bonding(struct tb_port *port, bool bonding) { u32 val; int ret; @@ -1027,19 +1038,8 @@ int tb_port_set_lane_bonding(struct tb_port *port, bool bonding) else val &= ~LANE_ADP_CS_1_LB; - ret = tb_port_write(port, &val, TB_CFG_PORT, - port->cap_phy + LANE_ADP_CS_1, 1); - if (ret) - return ret; - - /* - * When lane 0 bonding is set it will affect lane 1 too so - * update both. - */ - port->bonded = bonding; - port->dual_link_port->bonded = bonding; - - return 0; + return tb_port_write(port, &val, TB_CFG_PORT, + port->cap_phy + LANE_ADP_CS_1, 1); } /** @@ -1056,36 +1056,52 @@ int tb_port_set_lane_bonding(struct tb_port *port, bool bonding) */ int tb_port_lane_bonding_enable(struct tb_port *port) { + enum tb_link_width width; int ret; /* * Enable lane bonding for both links if not already enabled by * for example the boot firmware. */ - ret = tb_port_get_link_width(port); - if (ret == 1) { - ret = tb_port_set_link_width(port, 2); + width = tb_port_get_link_width(port); + if (width == TB_LINK_WIDTH_SINGLE) { + ret = tb_port_set_link_width(port, TB_LINK_WIDTH_DUAL); if (ret) goto err_lane0; } - ret = tb_port_get_link_width(port->dual_link_port); - if (ret == 1) { - ret = tb_port_set_link_width(port->dual_link_port, 2); + width = tb_port_get_link_width(port->dual_link_port); + if (width == TB_LINK_WIDTH_SINGLE) { + ret = tb_port_set_link_width(port->dual_link_port, + TB_LINK_WIDTH_DUAL); if (ret) goto err_lane0; } - ret = tb_port_set_lane_bonding(port, true); - if (ret) - goto err_lane1; + /* + * Only set bonding if the link was not already bonded. This + * avoids the lane adapter to re-enter bonding state. + */ + if (width == TB_LINK_WIDTH_SINGLE) { + ret = tb_port_set_lane_bonding(port, true); + if (ret) + goto err_lane1; + } + + /* + * When lane 0 bonding is set it will affect lane 1 too so + * update both. + */ + port->bonded = true; + port->dual_link_port->bonded = true; return 0; err_lane1: - tb_port_set_link_width(port->dual_link_port, 1); + tb_port_set_link_width(port->dual_link_port, TB_LINK_WIDTH_SINGLE); err_lane0: - tb_port_set_link_width(port, 1); + tb_port_set_link_width(port, TB_LINK_WIDTH_SINGLE); + return ret; } @@ -1099,27 +1115,34 @@ int tb_port_lane_bonding_enable(struct tb_port *port) void tb_port_lane_bonding_disable(struct tb_port *port) { tb_port_set_lane_bonding(port, false); - tb_port_set_link_width(port->dual_link_port, 1); - tb_port_set_link_width(port, 1); + tb_port_set_link_width(port->dual_link_port, TB_LINK_WIDTH_SINGLE); + tb_port_set_link_width(port, TB_LINK_WIDTH_SINGLE); + port->dual_link_port->bonded = false; + port->bonded = false; } /** * tb_port_wait_for_link_width() - Wait until link reaches specific width * @port: Port to wait for - * @width: Expected link width (%1 or %2) + * @width_mask: Expected link width mask * @timeout_msec: Timeout in ms how long to wait * * Should be used after both ends of the link have been bonded (or * bonding has been disabled) to wait until the link actually reaches - * the expected state. Returns %-ETIMEDOUT if the @width was not reached - * within the given timeout, %0 if it did. + * the expected state. Returns %-ETIMEDOUT if the width was not reached + * within the given timeout, %0 if it did. Can be passed a mask of + * expected widths and succeeds if any of the widths is reached. */ -int tb_port_wait_for_link_width(struct tb_port *port, int width, +int tb_port_wait_for_link_width(struct tb_port *port, unsigned int width_mask, int timeout_msec) { ktime_t timeout = ktime_add_ms(ktime_get(), timeout_msec); int ret; + /* Gen 4 link does not support single lane */ + if ((width_mask & TB_LINK_WIDTH_SINGLE) && is_gen4_link(port)) + return -EOPNOTSUPP; + do { ret = tb_port_get_link_width(port); if (ret < 0) { @@ -1130,7 +1153,7 @@ int tb_port_wait_for_link_width(struct tb_port *port, int width, */ if (ret != -EACCES) return ret; - } else if (ret == width) { + } else if (ret & width_mask) { return 0; } @@ -1183,135 +1206,6 @@ int tb_port_update_credits(struct tb_port *port) return tb_port_do_update_credits(port->dual_link_port); } -static int __tb_port_pm_secondary_set(struct tb_port *port, bool secondary) -{ - u32 phy; - int ret; - - ret = tb_port_read(port, &phy, TB_CFG_PORT, - port->cap_phy + LANE_ADP_CS_1, 1); - if (ret) - return ret; - - if (secondary) - phy |= LANE_ADP_CS_1_PMS; - else - phy &= ~LANE_ADP_CS_1_PMS; - - return tb_port_write(port, &phy, TB_CFG_PORT, - port->cap_phy + LANE_ADP_CS_1, 1); -} - -static int tb_port_pm_secondary_enable(struct tb_port *port) -{ - return __tb_port_pm_secondary_set(port, true); -} - -static int tb_port_pm_secondary_disable(struct tb_port *port) -{ - return __tb_port_pm_secondary_set(port, false); -} - -/* Called for USB4 or Titan Ridge routers only */ -static bool tb_port_clx_supported(struct tb_port *port, unsigned int clx_mask) -{ - u32 val, mask = 0; - bool ret; - - /* Don't enable CLx in case of two single-lane links */ - if (!port->bonded && port->dual_link_port) - return false; - - /* Don't enable CLx in case of inter-domain link */ - if (port->xdomain) - return false; - - if (tb_switch_is_usb4(port->sw)) { - if (!usb4_port_clx_supported(port)) - return false; - } else if (!tb_lc_is_clx_supported(port)) { - return false; - } - - if (clx_mask & TB_CL1) { - /* CL0s and CL1 are enabled and supported together */ - mask |= LANE_ADP_CS_0_CL0S_SUPPORT | LANE_ADP_CS_0_CL1_SUPPORT; - } - if (clx_mask & TB_CL2) - mask |= LANE_ADP_CS_0_CL2_SUPPORT; - - ret = tb_port_read(port, &val, TB_CFG_PORT, - port->cap_phy + LANE_ADP_CS_0, 1); - if (ret) - return false; - - return !!(val & mask); -} - -static int __tb_port_clx_set(struct tb_port *port, enum tb_clx clx, bool enable) -{ - u32 phy, mask; - int ret; - - /* CL0s and CL1 are enabled and supported together */ - if (clx == TB_CL1) - mask = LANE_ADP_CS_1_CL0S_ENABLE | LANE_ADP_CS_1_CL1_ENABLE; - else - /* For now we support only CL0s and CL1. Not CL2 */ - return -EOPNOTSUPP; - - ret = tb_port_read(port, &phy, TB_CFG_PORT, - port->cap_phy + LANE_ADP_CS_1, 1); - if (ret) - return ret; - - if (enable) - phy |= mask; - else - phy &= ~mask; - - return tb_port_write(port, &phy, TB_CFG_PORT, - port->cap_phy + LANE_ADP_CS_1, 1); -} - -static int tb_port_clx_disable(struct tb_port *port, enum tb_clx clx) -{ - return __tb_port_clx_set(port, clx, false); -} - -static int tb_port_clx_enable(struct tb_port *port, enum tb_clx clx) -{ - return __tb_port_clx_set(port, clx, true); -} - -/** - * tb_port_is_clx_enabled() - Is given CL state enabled - * @port: USB4 port to check - * @clx_mask: Mask of CL states to check - * - * Returns true if any of the given CL states is enabled for @port. - */ -bool tb_port_is_clx_enabled(struct tb_port *port, unsigned int clx_mask) -{ - u32 val, mask = 0; - int ret; - - if (!tb_port_clx_supported(port, clx_mask)) - return false; - - if (clx_mask & TB_CL1) - mask |= LANE_ADP_CS_1_CL0S_ENABLE | LANE_ADP_CS_1_CL1_ENABLE; - if (clx_mask & TB_CL2) - mask |= LANE_ADP_CS_1_CL2_ENABLE; - - ret = tb_port_read(port, &val, TB_CFG_PORT, - port->cap_phy + LANE_ADP_CS_1, 1); - if (ret) - return false; - - return !!(val & mask); -} - static int tb_port_start_lane_initialization(struct tb_port *port) { int ret; @@ -1911,20 +1805,57 @@ static ssize_t speed_show(struct device *dev, struct device_attribute *attr, static DEVICE_ATTR(rx_speed, 0444, speed_show, NULL); static DEVICE_ATTR(tx_speed, 0444, speed_show, NULL); -static ssize_t lanes_show(struct device *dev, struct device_attribute *attr, - char *buf) +static ssize_t rx_lanes_show(struct device *dev, struct device_attribute *attr, + char *buf) { struct tb_switch *sw = tb_to_switch(dev); + unsigned int width; + + switch (sw->link_width) { + case TB_LINK_WIDTH_SINGLE: + case TB_LINK_WIDTH_ASYM_TX: + width = 1; + break; + case TB_LINK_WIDTH_DUAL: + width = 2; + break; + case TB_LINK_WIDTH_ASYM_RX: + width = 3; + break; + default: + WARN_ON_ONCE(1); + return -EINVAL; + } - return sysfs_emit(buf, "%u\n", sw->link_width); + return sysfs_emit(buf, "%u\n", width); } +static DEVICE_ATTR(rx_lanes, 0444, rx_lanes_show, NULL); -/* - * Currently link has same amount of lanes both directions (1 or 2) but - * expose them separately to allow possible asymmetric links in the future. - */ -static DEVICE_ATTR(rx_lanes, 0444, lanes_show, NULL); -static DEVICE_ATTR(tx_lanes, 0444, lanes_show, NULL); +static ssize_t tx_lanes_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct tb_switch *sw = tb_to_switch(dev); + unsigned int width; + + switch (sw->link_width) { + case TB_LINK_WIDTH_SINGLE: + case TB_LINK_WIDTH_ASYM_RX: + width = 1; + break; + case TB_LINK_WIDTH_DUAL: + width = 2; + break; + case TB_LINK_WIDTH_ASYM_TX: + width = 3; + break; + default: + WARN_ON_ONCE(1); + return -EINVAL; + } + + return sysfs_emit(buf, "%u\n", width); +} +static DEVICE_ATTR(tx_lanes, 0444, tx_lanes_show, NULL); static ssize_t nvm_authenticate_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -2189,8 +2120,9 @@ static int tb_switch_uevent(const struct device *dev, struct kobj_uevent_env *en const struct tb_switch *sw = tb_to_switch(dev); const char *type; - if (sw->config.thunderbolt_version == USB4_VERSION_1_0) { - if (add_uevent_var(env, "USB4_VERSION=1.0")) + if (tb_switch_is_usb4(sw)) { + if (add_uevent_var(env, "USB4_VERSION=%u.0", + usb4_switch_version(sw))) return -ENOMEM; } @@ -2498,9 +2430,13 @@ int tb_switch_configure(struct tb_switch *sw) /* * For USB4 devices, we need to program the CM version * accordingly so that it knows to expose all the - * additional capabilities. + * additional capabilities. Program it according to USB4 + * version to avoid changing existing (v1) routers behaviour. */ - sw->config.cmuv = USB4_VERSION_1_0; + if (usb4_switch_version(sw) < 2) + sw->config.cmuv = ROUTER_CS_4_CMUV_V1; + else + sw->config.cmuv = ROUTER_CS_4_CMUV_V2; sw->config.plug_events_delay = 0xa; /* Enumerate the switch */ @@ -2530,6 +2466,22 @@ int tb_switch_configure(struct tb_switch *sw) return tb_plug_events_active(sw, true); } +/** + * tb_switch_configuration_valid() - Set the tunneling configuration to be valid + * @sw: Router to configure + * + * Needs to be called before any tunnels can be setup through the + * router. Can be called to any router. + * + * Returns %0 in success and negative errno otherwise. + */ +int tb_switch_configuration_valid(struct tb_switch *sw) +{ + if (tb_switch_is_usb4(sw)) + return usb4_switch_configuration_valid(sw); + return 0; +} + static int tb_switch_set_uuid(struct tb_switch *sw) { bool uid = false; @@ -2754,9 +2706,9 @@ static int tb_switch_update_link_attributes(struct tb_switch *sw) */ int tb_switch_lane_bonding_enable(struct tb_switch *sw) { - struct tb_switch *parent = tb_to_switch(sw->dev.parent); struct tb_port *up, *down; u64 route = tb_route(sw); + unsigned int width_mask; int ret; if (!route) @@ -2766,10 +2718,10 @@ int tb_switch_lane_bonding_enable(struct tb_switch *sw) return 0; up = tb_upstream_port(sw); - down = tb_port_at(route, parent); + down = tb_switch_downstream_port(sw); - if (!tb_port_is_width_supported(up, 2) || - !tb_port_is_width_supported(down, 2)) + if (!tb_port_is_width_supported(up, TB_LINK_WIDTH_DUAL) || + !tb_port_is_width_supported(down, TB_LINK_WIDTH_DUAL)) return 0; ret = tb_port_lane_bonding_enable(up); @@ -2785,7 +2737,11 @@ int tb_switch_lane_bonding_enable(struct tb_switch *sw) return ret; } - ret = tb_port_wait_for_link_width(down, 2, 100); + /* Any of the widths are all bonded */ + width_mask = TB_LINK_WIDTH_DUAL | TB_LINK_WIDTH_ASYM_TX | + TB_LINK_WIDTH_ASYM_RX; + + ret = tb_port_wait_for_link_width(down, width_mask, 100); if (ret) { tb_port_warn(down, "timeout enabling lane bonding\n"); return ret; @@ -2808,8 +2764,8 @@ int tb_switch_lane_bonding_enable(struct tb_switch *sw) */ void tb_switch_lane_bonding_disable(struct tb_switch *sw) { - struct tb_switch *parent = tb_to_switch(sw->dev.parent); struct tb_port *up, *down; + int ret; if (!tb_route(sw)) return; @@ -2818,7 +2774,7 @@ void tb_switch_lane_bonding_disable(struct tb_switch *sw) if (!up->bonded) return; - down = tb_port_at(tb_route(sw), parent); + down = tb_switch_downstream_port(sw); tb_port_lane_bonding_disable(up); tb_port_lane_bonding_disable(down); @@ -2827,7 +2783,8 @@ void tb_switch_lane_bonding_disable(struct tb_switch *sw) * It is fine if we get other errors as the router might have * been unplugged. */ - if (tb_port_wait_for_link_width(down, 1, 100) == -ETIMEDOUT) + ret = tb_port_wait_for_link_width(down, TB_LINK_WIDTH_SINGLE, 100); + if (ret == -ETIMEDOUT) tb_sw_warn(sw, "timeout disabling lane bonding\n"); tb_port_update_credits(down); @@ -2994,6 +2951,10 @@ int tb_switch_add(struct tb_switch *sw) if (ret) return ret; + ret = tb_switch_clx_init(sw); + if (ret) + return ret; + ret = tb_switch_tmu_init(sw); if (ret) return ret; @@ -3246,13 +3207,8 @@ void tb_switch_suspend(struct tb_switch *sw, bool runtime) /* * Actually only needed for Titan Ridge but for simplicity can be * done for USB4 device too as CLx is re-enabled at resume. - * CL0s and CL1 are enabled and supported together. */ - if (tb_switch_is_clx_enabled(sw, TB_CL1)) { - if (tb_switch_disable_clx(sw, TB_CL1)) - tb_sw_warn(sw, "failed to disable %s on upstream port\n", - tb_switch_clx_name(TB_CL1)); - } + tb_switch_clx_disable(sw); err = tb_plug_events_active(sw, false); if (err) @@ -3474,234 +3430,6 @@ struct tb_port *tb_switch_find_port(struct tb_switch *sw, return NULL; } -static int tb_switch_pm_secondary_resolve(struct tb_switch *sw) -{ - struct tb_switch *parent = tb_switch_parent(sw); - struct tb_port *up, *down; - int ret; - - if (!tb_route(sw)) - return 0; - - up = tb_upstream_port(sw); - down = tb_port_at(tb_route(sw), parent); - ret = tb_port_pm_secondary_enable(up); - if (ret) - return ret; - - return tb_port_pm_secondary_disable(down); -} - -static int __tb_switch_enable_clx(struct tb_switch *sw, enum tb_clx clx) -{ - struct tb_switch *parent = tb_switch_parent(sw); - bool up_clx_support, down_clx_support; - struct tb_port *up, *down; - int ret; - - if (!tb_switch_is_clx_supported(sw)) - return 0; - - /* - * Enable CLx for host router's downstream port as part of the - * downstream router enabling procedure. - */ - if (!tb_route(sw)) - return 0; - - /* Enable CLx only for first hop router (depth = 1) */ - if (tb_route(parent)) - return 0; - - ret = tb_switch_pm_secondary_resolve(sw); - if (ret) - return ret; - - up = tb_upstream_port(sw); - down = tb_port_at(tb_route(sw), parent); - - up_clx_support = tb_port_clx_supported(up, clx); - down_clx_support = tb_port_clx_supported(down, clx); - - tb_port_dbg(up, "%s %ssupported\n", tb_switch_clx_name(clx), - up_clx_support ? "" : "not "); - tb_port_dbg(down, "%s %ssupported\n", tb_switch_clx_name(clx), - down_clx_support ? "" : "not "); - - if (!up_clx_support || !down_clx_support) - return -EOPNOTSUPP; - - ret = tb_port_clx_enable(up, clx); - if (ret) - return ret; - - ret = tb_port_clx_enable(down, clx); - if (ret) { - tb_port_clx_disable(up, clx); - return ret; - } - - ret = tb_switch_mask_clx_objections(sw); - if (ret) { - tb_port_clx_disable(up, clx); - tb_port_clx_disable(down, clx); - return ret; - } - - sw->clx = clx; - - tb_port_dbg(up, "%s enabled\n", tb_switch_clx_name(clx)); - return 0; -} - -/** - * tb_switch_enable_clx() - Enable CLx on upstream port of specified router - * @sw: Router to enable CLx for - * @clx: The CLx state to enable - * - * Enable CLx state only for first hop router. That is the most common - * use-case, that is intended for better thermal management, and so helps - * to improve performance. CLx is enabled only if both sides of the link - * support CLx, and if both sides of the link are not configured as two - * single lane links and only if the link is not inter-domain link. The - * complete set of conditions is described in CM Guide 1.0 section 8.1. - * - * Return: Returns 0 on success or an error code on failure. - */ -int tb_switch_enable_clx(struct tb_switch *sw, enum tb_clx clx) -{ - struct tb_switch *root_sw = sw->tb->root_switch; - - if (!clx_enabled) - return 0; - - /* - * CLx is not enabled and validated on Intel USB4 platforms before - * Alder Lake. - */ - if (root_sw->generation < 4 || tb_switch_is_tiger_lake(root_sw)) - return 0; - - switch (clx) { - case TB_CL1: - /* CL0s and CL1 are enabled and supported together */ - return __tb_switch_enable_clx(sw, clx); - - default: - return -EOPNOTSUPP; - } -} - -static int __tb_switch_disable_clx(struct tb_switch *sw, enum tb_clx clx) -{ - struct tb_switch *parent = tb_switch_parent(sw); - struct tb_port *up, *down; - int ret; - - if (!tb_switch_is_clx_supported(sw)) - return 0; - - /* - * Disable CLx for host router's downstream port as part of the - * downstream router enabling procedure. - */ - if (!tb_route(sw)) - return 0; - - /* Disable CLx only for first hop router (depth = 1) */ - if (tb_route(parent)) - return 0; - - up = tb_upstream_port(sw); - down = tb_port_at(tb_route(sw), parent); - ret = tb_port_clx_disable(up, clx); - if (ret) - return ret; - - ret = tb_port_clx_disable(down, clx); - if (ret) - return ret; - - sw->clx = TB_CLX_DISABLE; - - tb_port_dbg(up, "%s disabled\n", tb_switch_clx_name(clx)); - return 0; -} - -/** - * tb_switch_disable_clx() - Disable CLx on upstream port of specified router - * @sw: Router to disable CLx for - * @clx: The CLx state to disable - * - * Return: Returns 0 on success or an error code on failure. - */ -int tb_switch_disable_clx(struct tb_switch *sw, enum tb_clx clx) -{ - if (!clx_enabled) - return 0; - - switch (clx) { - case TB_CL1: - /* CL0s and CL1 are enabled and supported together */ - return __tb_switch_disable_clx(sw, clx); - - default: - return -EOPNOTSUPP; - } -} - -/** - * tb_switch_mask_clx_objections() - Mask CLx objections for a router - * @sw: Router to mask objections for - * - * Mask the objections coming from the second depth routers in order to - * stop these objections from interfering with the CLx states of the first - * depth link. - */ -int tb_switch_mask_clx_objections(struct tb_switch *sw) -{ - int up_port = sw->config.upstream_port_number; - u32 offset, val[2], mask_obj, unmask_obj; - int ret, i; - - /* Only Titan Ridge of pre-USB4 devices support CLx states */ - if (!tb_switch_is_titan_ridge(sw)) - return 0; - - if (!tb_route(sw)) - return 0; - - /* - * In Titan Ridge there are only 2 dual-lane Thunderbolt ports: - * Port A consists of lane adapters 1,2 and - * Port B consists of lane adapters 3,4 - * If upstream port is A, (lanes are 1,2), we mask objections from - * port B (lanes 3,4) and unmask objections from Port A and vice-versa. - */ - if (up_port == 1) { - mask_obj = TB_LOW_PWR_C0_PORT_B_MASK; - unmask_obj = TB_LOW_PWR_C1_PORT_A_MASK; - offset = TB_LOW_PWR_C1_CL1; - } else { - mask_obj = TB_LOW_PWR_C1_PORT_A_MASK; - unmask_obj = TB_LOW_PWR_C0_PORT_B_MASK; - offset = TB_LOW_PWR_C3_CL1; - } - - ret = tb_sw_read(sw, &val, TB_CFG_SWITCH, - sw->cap_lp + offset, ARRAY_SIZE(val)); - if (ret) - return ret; - - for (i = 0; i < ARRAY_SIZE(val); i++) { - val[i] |= mask_obj; - val[i] &= ~unmask_obj; - } - - return tb_sw_write(sw, &val, TB_CFG_SWITCH, - sw->cap_lp + offset, ARRAY_SIZE(val)); -} - /* * Can be used for read/write a specified PCIe bridge for any Thunderbolt 3 * device. For now used only for Titan Ridge. diff --git a/drivers/thunderbolt/tb.c b/drivers/thunderbolt/tb.c index c1af712ca728827ac3b11ea9d101989fcbab4d95..62b26b7998fd88109003e84b8b359ea731fc997a 100644 --- a/drivers/thunderbolt/tb.c +++ b/drivers/thunderbolt/tb.c @@ -131,7 +131,7 @@ tb_attach_bandwidth_group(struct tb_cm *tcm, struct tb_port *in, static void tb_discover_bandwidth_group(struct tb_cm *tcm, struct tb_port *in, struct tb_port *out) { - if (usb4_dp_port_bw_mode_enabled(in)) { + if (usb4_dp_port_bandwidth_mode_enabled(in)) { int index, i; index = usb4_dp_port_group_id(in); @@ -240,6 +240,147 @@ static void tb_discover_dp_resources(struct tb *tb) } } +/* Enables CL states up to host router */ +static int tb_enable_clx(struct tb_switch *sw) +{ + struct tb_cm *tcm = tb_priv(sw->tb); + unsigned int clx = TB_CL0S | TB_CL1; + const struct tb_tunnel *tunnel; + int ret; + + /* + * Currently only enable CLx for the first link. This is enough + * to allow the CPU to save energy at least on Intel hardware + * and makes it slightly simpler to implement. We may change + * this in the future to cover the whole topology if it turns + * out to be beneficial. + */ + while (sw && sw->config.depth > 1) + sw = tb_switch_parent(sw); + + if (!sw) + return 0; + + if (sw->config.depth != 1) + return 0; + + /* + * If we are re-enabling then check if there is an active DMA + * tunnel and in that case bail out. + */ + list_for_each_entry(tunnel, &tcm->tunnel_list, list) { + if (tb_tunnel_is_dma(tunnel)) { + if (tb_tunnel_port_on_path(tunnel, tb_upstream_port(sw))) + return 0; + } + } + + /* + * Initially try with CL2. If that's not supported by the + * topology try with CL0s and CL1 and then give up. + */ + ret = tb_switch_clx_enable(sw, clx | TB_CL2); + if (ret == -EOPNOTSUPP) + ret = tb_switch_clx_enable(sw, clx); + return ret == -EOPNOTSUPP ? 0 : ret; +} + +/* Disables CL states up to the host router */ +static void tb_disable_clx(struct tb_switch *sw) +{ + do { + if (tb_switch_clx_disable(sw) < 0) + tb_sw_warn(sw, "failed to disable CL states\n"); + sw = tb_switch_parent(sw); + } while (sw); +} + +static int tb_increase_switch_tmu_accuracy(struct device *dev, void *data) +{ + struct tb_switch *sw; + + sw = tb_to_switch(dev); + if (!sw) + return 0; + + if (tb_switch_tmu_is_configured(sw, TB_SWITCH_TMU_MODE_LOWRES)) { + enum tb_switch_tmu_mode mode; + int ret; + + if (tb_switch_clx_is_enabled(sw, TB_CL1)) + mode = TB_SWITCH_TMU_MODE_HIFI_UNI; + else + mode = TB_SWITCH_TMU_MODE_HIFI_BI; + + ret = tb_switch_tmu_configure(sw, mode); + if (ret) + return ret; + + return tb_switch_tmu_enable(sw); + } + + return 0; +} + +static void tb_increase_tmu_accuracy(struct tb_tunnel *tunnel) +{ + struct tb_switch *sw; + + if (!tunnel) + return; + + /* + * Once first DP tunnel is established we change the TMU + * accuracy of first depth child routers (and the host router) + * to the highest. This is needed for the DP tunneling to work + * but also allows CL0s. + * + * If both routers are v2 then we don't need to do anything as + * they are using enhanced TMU mode that allows all CLx. + */ + sw = tunnel->tb->root_switch; + device_for_each_child(&sw->dev, NULL, tb_increase_switch_tmu_accuracy); +} + +static int tb_enable_tmu(struct tb_switch *sw) +{ + int ret; + + /* + * If both routers at the end of the link are v2 we simply + * enable the enhanched uni-directional mode. That covers all + * the CL states. For v1 and before we need to use the normal + * rate to allow CL1 (when supported). Otherwise we keep the TMU + * running at the highest accuracy. + */ + ret = tb_switch_tmu_configure(sw, + TB_SWITCH_TMU_MODE_MEDRES_ENHANCED_UNI); + if (ret == -EOPNOTSUPP) { + if (tb_switch_clx_is_enabled(sw, TB_CL1)) + ret = tb_switch_tmu_configure(sw, + TB_SWITCH_TMU_MODE_LOWRES); + else + ret = tb_switch_tmu_configure(sw, + TB_SWITCH_TMU_MODE_HIFI_BI); + } + if (ret) + return ret; + + /* If it is already enabled in correct mode, don't touch it */ + if (tb_switch_tmu_is_enabled(sw)) + return 0; + + ret = tb_switch_tmu_disable(sw); + if (ret) + return ret; + + ret = tb_switch_tmu_post_time(sw); + if (ret) + return ret; + + return tb_switch_tmu_enable(sw); +} + static void tb_switch_discover_tunnels(struct tb_switch *sw, struct list_head *list, bool alloc_hopids) @@ -253,13 +394,7 @@ static void tb_switch_discover_tunnels(struct tb_switch *sw, switch (port->config.type) { case TB_TYPE_DP_HDMI_IN: tunnel = tb_tunnel_discover_dp(tb, port, alloc_hopids); - /* - * In case of DP tunnel exists, change host router's - * 1st children TMU mode to HiFi for CL0s to work. - */ - if (tunnel) - tb_switch_enable_tmu_1st_child(tb->root_switch, - TB_SWITCH_TMU_RATE_HIFI); + tb_increase_tmu_accuracy(tunnel); break; case TB_TYPE_PCIE_DOWN: @@ -357,25 +492,6 @@ static void tb_scan_xdomain(struct tb_port *port) } } -static int tb_enable_tmu(struct tb_switch *sw) -{ - int ret; - - /* If it is already enabled in correct mode, don't touch it */ - if (tb_switch_tmu_is_enabled(sw, sw->tmu.unidirectional_request)) - return 0; - - ret = tb_switch_tmu_disable(sw); - if (ret) - return ret; - - ret = tb_switch_tmu_post_time(sw); - if (ret) - return ret; - - return tb_switch_tmu_enable(sw); -} - /** * tb_find_unused_port() - return the first inactive port on @sw * @sw: Switch to find the port on @@ -480,7 +596,8 @@ static int tb_available_bandwidth(struct tb *tb, struct tb_port *src_port, usb3_consumed_down = 0; } - *available_up = *available_down = 40000; + /* Maximum possible bandwidth asymmetric Gen 4 link is 120 Gb/s */ + *available_up = *available_down = 120000; /* Find the minimum available bandwidth over all links */ tb_for_each_port_on_path(src_port, dst_port, port) { @@ -491,18 +608,45 @@ static int tb_available_bandwidth(struct tb *tb, struct tb_port *src_port, if (tb_is_upstream_port(port)) { link_speed = port->sw->link_speed; + /* + * sw->link_width is from upstream perspective + * so we use the opposite for downstream of the + * host router. + */ + if (port->sw->link_width == TB_LINK_WIDTH_ASYM_TX) { + up_bw = link_speed * 3 * 1000; + down_bw = link_speed * 1 * 1000; + } else if (port->sw->link_width == TB_LINK_WIDTH_ASYM_RX) { + up_bw = link_speed * 1 * 1000; + down_bw = link_speed * 3 * 1000; + } else { + up_bw = link_speed * port->sw->link_width * 1000; + down_bw = up_bw; + } } else { link_speed = tb_port_get_link_speed(port); if (link_speed < 0) return link_speed; - } - link_width = port->bonded ? 2 : 1; + link_width = tb_port_get_link_width(port); + if (link_width < 0) + return link_width; + + if (link_width == TB_LINK_WIDTH_ASYM_TX) { + up_bw = link_speed * 1 * 1000; + down_bw = link_speed * 3 * 1000; + } else if (link_width == TB_LINK_WIDTH_ASYM_RX) { + up_bw = link_speed * 3 * 1000; + down_bw = link_speed * 1 * 1000; + } else { + up_bw = link_speed * link_width * 1000; + down_bw = up_bw; + } + } - up_bw = link_speed * link_width * 1000; /* Mb/s */ /* Leave 10% guard band */ up_bw -= up_bw / 10; - down_bw = up_bw; + down_bw -= down_bw / 10; tb_port_dbg(port, "link total bandwidth %d/%d Mb/s\n", up_bw, down_bw); @@ -628,7 +772,7 @@ static int tb_tunnel_usb3(struct tb *tb, struct tb_switch *sw) * Look up available down port. Since we are chaining it should * be found right above this switch. */ - port = tb_port_at(tb_route(sw), parent); + port = tb_switch_downstream_port(sw); down = tb_find_usb3_down(parent, port); if (!down) return 0; @@ -739,7 +883,6 @@ static void tb_scan_port(struct tb_port *port) struct tb_port *upstream_port; bool discovery = false; struct tb_switch *sw; - int ret; if (tb_is_upstream_port(port)) return; @@ -838,28 +981,20 @@ static void tb_scan_port(struct tb_port *port) * CL0s and CL1 are enabled and supported together. * Silently ignore CLx enabling in case CLx is not supported. */ - if (discovery) { + if (discovery) tb_sw_dbg(sw, "discovery, not touching CL states\n"); - } else { - ret = tb_switch_enable_clx(sw, TB_CL1); - if (ret && ret != -EOPNOTSUPP) - tb_sw_warn(sw, "failed to enable %s on upstream port\n", - tb_switch_clx_name(TB_CL1)); - } - - if (tb_switch_is_clx_enabled(sw, TB_CL1)) - /* - * To support highest CLx state, we set router's TMU to - * Normal-Uni mode. - */ - tb_switch_tmu_configure(sw, TB_SWITCH_TMU_RATE_NORMAL, true); - else - /* If CLx disabled, configure router's TMU to HiFi-Bidir mode*/ - tb_switch_tmu_configure(sw, TB_SWITCH_TMU_RATE_HIFI, false); + else if (tb_enable_clx(sw)) + tb_sw_warn(sw, "failed to enable CL states\n"); if (tb_enable_tmu(sw)) tb_sw_warn(sw, "failed to enable TMU\n"); + /* + * Configuration valid needs to be set after the TMU has been + * enabled for the upstream port of the router so we do it here. + */ + tb_switch_configuration_valid(sw); + /* Scan upstream retimers */ tb_retimer_scan(upstream_port, true); @@ -1034,7 +1169,7 @@ tb_recalc_estimated_bandwidth_for_group(struct tb_bandwidth_group *group) struct tb_tunnel *tunnel; struct tb_port *out; - if (!usb4_dp_port_bw_mode_enabled(in)) + if (!usb4_dp_port_bandwidth_mode_enabled(in)) continue; tunnel = tb_find_tunnel(tb, TB_TUNNEL_DP, in, NULL); @@ -1082,7 +1217,7 @@ tb_recalc_estimated_bandwidth_for_group(struct tb_bandwidth_group *group) else estimated_bw = estimated_up; - if (usb4_dp_port_set_estimated_bw(in, estimated_bw)) + if (usb4_dp_port_set_estimated_bandwidth(in, estimated_bw)) tb_port_warn(in, "failed to update estimated bandwidth\n"); } @@ -1263,8 +1398,7 @@ static void tb_tunnel_dp(struct tb *tb) * In case of DP tunnel exists, change host router's 1st children * TMU mode to HiFi for CL0s to work. */ - tb_switch_enable_tmu_1st_child(tb->root_switch, TB_SWITCH_TMU_RATE_HIFI); - + tb_increase_tmu_accuracy(tunnel); return; err_free: @@ -1378,7 +1512,6 @@ static int tb_tunnel_pci(struct tb *tb, struct tb_switch *sw) { struct tb_port *up, *down, *port; struct tb_cm *tcm = tb_priv(tb); - struct tb_switch *parent_sw; struct tb_tunnel *tunnel; up = tb_switch_find_port(sw, TB_TYPE_PCIE_UP); @@ -1389,9 +1522,8 @@ static int tb_tunnel_pci(struct tb *tb, struct tb_switch *sw) * Look up available down port. Since we are chaining it should * be found right above this switch. */ - parent_sw = tb_to_switch(sw->dev.parent); - port = tb_port_at(tb_route(sw), parent_sw); - down = tb_find_pcie_down(parent_sw, port); + port = tb_switch_downstream_port(sw); + down = tb_find_pcie_down(tb_switch_parent(sw), port); if (!down) return 0; @@ -1428,30 +1560,45 @@ static int tb_approve_xdomain_paths(struct tb *tb, struct tb_xdomain *xd, struct tb_port *nhi_port, *dst_port; struct tb_tunnel *tunnel; struct tb_switch *sw; + int ret; sw = tb_to_switch(xd->dev.parent); dst_port = tb_port_at(xd->route, sw); nhi_port = tb_switch_find_port(tb->root_switch, TB_TYPE_NHI); mutex_lock(&tb->lock); + + /* + * When tunneling DMA paths the link should not enter CL states + * so disable them now. + */ + tb_disable_clx(sw); + tunnel = tb_tunnel_alloc_dma(tb, nhi_port, dst_port, transmit_path, transmit_ring, receive_path, receive_ring); if (!tunnel) { - mutex_unlock(&tb->lock); - return -ENOMEM; + ret = -ENOMEM; + goto err_clx; } if (tb_tunnel_activate(tunnel)) { tb_port_info(nhi_port, "DMA tunnel activation failed, aborting\n"); - tb_tunnel_free(tunnel); - mutex_unlock(&tb->lock); - return -EIO; + ret = -EIO; + goto err_free; } list_add_tail(&tunnel->list, &tcm->tunnel_list); mutex_unlock(&tb->lock); return 0; + +err_free: + tb_tunnel_free(tunnel); +err_clx: + tb_enable_clx(sw); + mutex_unlock(&tb->lock); + + return ret; } static void __tb_disconnect_xdomain_paths(struct tb *tb, struct tb_xdomain *xd, @@ -1477,6 +1624,13 @@ static void __tb_disconnect_xdomain_paths(struct tb *tb, struct tb_xdomain *xd, receive_path, receive_ring)) tb_deactivate_and_free_tunnel(tunnel); } + + /* + * Try to re-enable CL states now, it is OK if this fails + * because we may still have another DMA tunnel active through + * the same host router USB4 downstream port. + */ + tb_enable_clx(sw); } static int tb_disconnect_xdomain_paths(struct tb *tb, struct tb_xdomain *xd, @@ -1758,12 +1912,12 @@ static void tb_handle_dp_bandwidth_request(struct work_struct *work) tb_port_dbg(in, "handling bandwidth allocation request\n"); - if (!usb4_dp_port_bw_mode_enabled(in)) { + if (!usb4_dp_port_bandwidth_mode_enabled(in)) { tb_port_warn(in, "bandwidth allocation mode not enabled\n"); goto unlock; } - ret = usb4_dp_port_requested_bw(in); + ret = usb4_dp_port_requested_bandwidth(in); if (ret < 0) { if (ret == -ENODATA) tb_port_dbg(in, "no bandwidth request active\n"); @@ -1830,17 +1984,26 @@ static void tb_queue_dp_bandwidth_request(struct tb *tb, u64 route, u8 port) static void tb_handle_notification(struct tb *tb, u64 route, const struct cfg_error_pkg *error) { - if (tb_cfg_ack_notification(tb->ctl, route, error)) - tb_warn(tb, "could not ack notification on %llx\n", route); switch (error->error) { + case TB_CFG_ERROR_PCIE_WAKE: + case TB_CFG_ERROR_DP_CON_CHANGE: + case TB_CFG_ERROR_DPTX_DISCOVERY: + if (tb_cfg_ack_notification(tb->ctl, route, error)) + tb_warn(tb, "could not ack notification on %llx\n", + route); + break; + case TB_CFG_ERROR_DP_BW: + if (tb_cfg_ack_notification(tb->ctl, route, error)) + tb_warn(tb, "could not ack notification on %llx\n", + route); tb_queue_dp_bandwidth_request(tb, route, error->port); break; default: - /* Ack is enough */ - return; + /* Ignore for now */ + break; } } @@ -1955,8 +2118,7 @@ static int tb_start(struct tb *tb) * To support highest CLx state, we set host router's TMU to * Normal mode. */ - tb_switch_tmu_configure(tb->root_switch, TB_SWITCH_TMU_RATE_NORMAL, - false); + tb_switch_tmu_configure(tb->root_switch, TB_SWITCH_TMU_MODE_LOWRES); /* Enable TMU if it is off */ tb_switch_tmu_enable(tb->root_switch); /* Full scan to discover devices added before the driver was loaded. */ @@ -1997,34 +2159,19 @@ static int tb_suspend_noirq(struct tb *tb) static void tb_restore_children(struct tb_switch *sw) { struct tb_port *port; - int ret; /* No need to restore if the router is already unplugged */ if (sw->is_unplugged) return; - /* - * CL0s and CL1 are enabled and supported together. - * Silently ignore CLx re-enabling in case CLx is not supported. - */ - ret = tb_switch_enable_clx(sw, TB_CL1); - if (ret && ret != -EOPNOTSUPP) - tb_sw_warn(sw, "failed to re-enable %s on upstream port\n", - tb_switch_clx_name(TB_CL1)); - - if (tb_switch_is_clx_enabled(sw, TB_CL1)) - /* - * To support highest CLx state, we set router's TMU to - * Normal-Uni mode. - */ - tb_switch_tmu_configure(sw, TB_SWITCH_TMU_RATE_NORMAL, true); - else - /* If CLx disabled, configure router's TMU to HiFi-Bidir mode*/ - tb_switch_tmu_configure(sw, TB_SWITCH_TMU_RATE_HIFI, false); + if (tb_enable_clx(sw)) + tb_sw_warn(sw, "failed to re-enable CL states\n"); if (tb_enable_tmu(sw)) tb_sw_warn(sw, "failed to restore TMU configuration\n"); + tb_switch_configuration_valid(sw); + tb_switch_for_each_port(sw, port) { if (!tb_port_has_remote(port) && !port->xdomain) continue; diff --git a/drivers/thunderbolt/tb.h b/drivers/thunderbolt/tb.h index 275ff5219a3a3ae79a69b0548aab891bc1824aa1..57a9b272cb94bd0e1f646153669b04478bc552be 100644 --- a/drivers/thunderbolt/tb.h +++ b/drivers/thunderbolt/tb.h @@ -19,10 +19,6 @@ #include "ctl.h" #include "dma_port.h" -#define NVM_MIN_SIZE SZ_32K -#define NVM_MAX_SIZE SZ_512K -#define NVM_DATA_DWORDS 16 - /* Keep link controller awake during update */ #define QUIRK_FORCE_POWER_LINK_CONTROLLER BIT(0) /* Disable CLx if not supported */ @@ -77,51 +73,37 @@ enum tb_nvm_write_ops { #define USB4_SWITCH_MAX_DEPTH 5 /** - * enum tb_switch_tmu_rate - TMU refresh rate - * @TB_SWITCH_TMU_RATE_OFF: %0 (Disable Time Sync handshake) - * @TB_SWITCH_TMU_RATE_HIFI: %16 us time interval between successive - * transmission of the Delay Request TSNOS - * (Time Sync Notification Ordered Set) on a Link - * @TB_SWITCH_TMU_RATE_NORMAL: %1 ms time interval between successive - * transmission of the Delay Request TSNOS on - * a Link + * enum tb_switch_tmu_mode - TMU mode + * @TB_SWITCH_TMU_MODE_OFF: TMU is off + * @TB_SWITCH_TMU_MODE_LOWRES: Uni-directional, normal mode + * @TB_SWITCH_TMU_MODE_HIFI_UNI: Uni-directional, HiFi mode + * @TB_SWITCH_TMU_MODE_HIFI_BI: Bi-directional, HiFi mode + * @TB_SWITCH_TMU_MODE_MEDRES_ENHANCED_UNI: Enhanced Uni-directional, MedRes mode + * + * Ordering is based on TMU accuracy level (highest last). */ -enum tb_switch_tmu_rate { - TB_SWITCH_TMU_RATE_OFF = 0, - TB_SWITCH_TMU_RATE_HIFI = 16, - TB_SWITCH_TMU_RATE_NORMAL = 1000, +enum tb_switch_tmu_mode { + TB_SWITCH_TMU_MODE_OFF, + TB_SWITCH_TMU_MODE_LOWRES, + TB_SWITCH_TMU_MODE_HIFI_UNI, + TB_SWITCH_TMU_MODE_HIFI_BI, + TB_SWITCH_TMU_MODE_MEDRES_ENHANCED_UNI, }; /** - * struct tb_switch_tmu - Structure holding switch TMU configuration + * struct tb_switch_tmu - Structure holding router TMU configuration * @cap: Offset to the TMU capability (%0 if not found) * @has_ucap: Does the switch support uni-directional mode - * @rate: TMU refresh rate related to upstream switch. In case of root - * switch this holds the domain rate. Reflects the HW setting. - * @unidirectional: Is the TMU in uni-directional or bi-directional mode - * related to upstream switch. Don't care for root switch. - * Reflects the HW setting. - * @unidirectional_request: Is the new TMU mode: uni-directional or bi-directional - * that is requested to be set. Related to upstream switch. - * Don't care for root switch. - * @rate_request: TMU new refresh rate related to upstream switch that is - * requested to be set. In case of root switch, this holds - * the new domain rate that is requested to be set. + * @mode: TMU mode related to the upstream router. Reflects the HW + * setting. Don't care for host router. + * @mode_request: TMU mode requested to set. Related to upstream router. + * Don't care for host router. */ struct tb_switch_tmu { int cap; bool has_ucap; - enum tb_switch_tmu_rate rate; - bool unidirectional; - bool unidirectional_request; - enum tb_switch_tmu_rate rate_request; -}; - -enum tb_clx { - TB_CLX_DISABLE, - /* CL0s and CL1 are enabled and supported together */ - TB_CL1 = BIT(0), - TB_CL2 = BIT(1), + enum tb_switch_tmu_mode mode; + enum tb_switch_tmu_mode mode_request; }; /** @@ -142,7 +124,7 @@ enum tb_clx { * @vendor_name: Name of the vendor (or %NULL if not known) * @device_name: Name of the device (or %NULL if not known) * @link_speed: Speed of the link in Gb/s - * @link_width: Width of the link (1 or 2) + * @link_width: Width of the upstream facing link * @link_usb4: Upstream link is USB4 * @generation: Switch Thunderbolt generation * @cap_plug_events: Offset to the plug events capability (%0 if not found) @@ -174,12 +156,17 @@ enum tb_clx { * @min_dp_main_credits: Router preferred minimum number of buffers for DP MAIN * @max_pcie_credits: Router preferred number of buffers for PCIe * @max_dma_credits: Router preferred number of buffers for DMA/P2P - * @clx: CLx state on the upstream link of the router + * @clx: CLx states on the upstream link of the router * * When the switch is being added or removed to the domain (other * switches) you need to have domain lock held. * * In USB4 terminology this structure represents a router. + * + * Note @link_width is not the same as whether link is bonded or not. + * For Gen 4 links the link is also bonded when it is asymmetric. The + * correct way to find out whether the link is bonded or not is to look + * @bonded field of the upstream port. */ struct tb_switch { struct device dev; @@ -195,7 +182,7 @@ struct tb_switch { const char *vendor_name; const char *device_name; unsigned int link_speed; - unsigned int link_width; + enum tb_link_width link_width; bool link_usb4; unsigned int generation; int cap_plug_events; @@ -225,7 +212,7 @@ struct tb_switch { unsigned int min_dp_main_credits; unsigned int max_pcie_credits; unsigned int max_dma_credits; - enum tb_clx clx; + unsigned int clx; }; /** @@ -455,6 +442,11 @@ struct tb_path { #define TB_WAKE_ON_PCIE BIT(4) #define TB_WAKE_ON_DP BIT(5) +/* CL states */ +#define TB_CL0S BIT(0) +#define TB_CL1 BIT(1) +#define TB_CL2 BIT(2) + /** * struct tb_cm_ops - Connection manager specific operations vector * @driver_ready: Called right after control channel is started. Used by @@ -802,6 +794,7 @@ struct tb_switch *tb_switch_alloc(struct tb *tb, struct device *parent, struct tb_switch *tb_switch_alloc_safe_mode(struct tb *tb, struct device *parent, u64 route); int tb_switch_configure(struct tb_switch *sw); +int tb_switch_configuration_valid(struct tb_switch *sw); int tb_switch_add(struct tb_switch *sw); void tb_switch_remove(struct tb_switch *sw); void tb_switch_suspend(struct tb_switch *sw, bool runtime); @@ -857,6 +850,20 @@ static inline struct tb_switch *tb_switch_parent(struct tb_switch *sw) return tb_to_switch(sw->dev.parent); } +/** + * tb_switch_downstream_port() - Return downstream facing port of parent router + * @sw: Device router pointer + * + * Only call for device routers. Returns the downstream facing port of + * the parent router. + */ +static inline struct tb_port *tb_switch_downstream_port(struct tb_switch *sw) +{ + if (WARN_ON(!tb_route(sw))) + return NULL; + return tb_port_at(tb_route(sw), tb_switch_parent(sw)); +} + static inline bool tb_switch_is_light_ridge(const struct tb_switch *sw) { return sw->config.vendor_id == PCI_VENDOR_ID_INTEL && @@ -935,17 +942,6 @@ static inline bool tb_switch_is_tiger_lake(const struct tb_switch *sw) return false; } -/** - * tb_switch_is_usb4() - Is the switch USB4 compliant - * @sw: Switch to check - * - * Returns true if the @sw is USB4 compliant router, false otherwise. - */ -static inline bool tb_switch_is_usb4(const struct tb_switch *sw) -{ - return sw->config.thunderbolt_version == USB4_VERSION_1_0; -} - /** * tb_switch_is_icm() - Is the switch handled by ICM firmware * @sw: Switch to check @@ -973,68 +969,58 @@ int tb_switch_tmu_init(struct tb_switch *sw); int tb_switch_tmu_post_time(struct tb_switch *sw); int tb_switch_tmu_disable(struct tb_switch *sw); int tb_switch_tmu_enable(struct tb_switch *sw); -void tb_switch_tmu_configure(struct tb_switch *sw, - enum tb_switch_tmu_rate rate, - bool unidirectional); -void tb_switch_enable_tmu_1st_child(struct tb_switch *sw, - enum tb_switch_tmu_rate rate); +int tb_switch_tmu_configure(struct tb_switch *sw, enum tb_switch_tmu_mode mode); + /** - * tb_switch_tmu_is_enabled() - Checks if the specified TMU mode is enabled - * @sw: Router whose TMU mode to check - * @unidirectional: If uni-directional (bi-directional otherwise) + * tb_switch_tmu_is_configured() - Is given TMU mode configured + * @sw: Router whose mode to check + * @mode: Mode to check * - * Return true if hardware TMU configuration matches the one passed in - * as parameter. That is HiFi/Normal and either uni-directional or bi-directional. + * Checks if given router TMU mode is configured to @mode. Note the + * router TMU might not be enabled to this mode. */ -static inline bool tb_switch_tmu_is_enabled(const struct tb_switch *sw, - bool unidirectional) +static inline bool tb_switch_tmu_is_configured(const struct tb_switch *sw, + enum tb_switch_tmu_mode mode) { - return sw->tmu.rate == sw->tmu.rate_request && - sw->tmu.unidirectional == unidirectional; + return sw->tmu.mode_request == mode; } -static inline const char *tb_switch_clx_name(enum tb_clx clx) +/** + * tb_switch_tmu_is_enabled() - Checks if the specified TMU mode is enabled + * @sw: Router whose TMU mode to check + * + * Return true if hardware TMU configuration matches the requested + * configuration (and is not %TB_SWITCH_TMU_MODE_OFF). + */ +static inline bool tb_switch_tmu_is_enabled(const struct tb_switch *sw) { - switch (clx) { - /* CL0s and CL1 are enabled and supported together */ - case TB_CL1: - return "CL0s/CL1"; - default: - return "unknown"; - } + return sw->tmu.mode != TB_SWITCH_TMU_MODE_OFF && + sw->tmu.mode == sw->tmu.mode_request; } -int tb_switch_enable_clx(struct tb_switch *sw, enum tb_clx clx); -int tb_switch_disable_clx(struct tb_switch *sw, enum tb_clx clx); +bool tb_port_clx_is_enabled(struct tb_port *port, unsigned int clx); + +int tb_switch_clx_init(struct tb_switch *sw); +bool tb_switch_clx_is_supported(const struct tb_switch *sw); +int tb_switch_clx_enable(struct tb_switch *sw, unsigned int clx); +int tb_switch_clx_disable(struct tb_switch *sw); /** - * tb_switch_is_clx_enabled() - Checks if the CLx is enabled + * tb_switch_clx_is_enabled() - Checks if the CLx is enabled * @sw: Router to check for the CLx - * @clx: The CLx state to check for + * @clx: The CLx states to check for * * Checks if the specified CLx is enabled on the router upstream link. + * Returns true if any of the given states is enabled. + * * Not applicable for a host router. */ -static inline bool tb_switch_is_clx_enabled(const struct tb_switch *sw, - enum tb_clx clx) +static inline bool tb_switch_clx_is_enabled(const struct tb_switch *sw, + unsigned int clx) { - return sw->clx == clx; + return sw->clx & clx; } -/** - * tb_switch_is_clx_supported() - Is CLx supported on this type of router - * @sw: The router to check CLx support for - */ -static inline bool tb_switch_is_clx_supported(const struct tb_switch *sw) -{ - if (sw->quirks & QUIRK_NO_CLX) - return false; - - return tb_switch_is_usb4(sw) || tb_switch_is_titan_ridge(sw); -} - -int tb_switch_mask_clx_objections(struct tb_switch *sw); - int tb_switch_pcie_l1_enable(struct tb_switch *sw); int tb_switch_xhci_connect(struct tb_switch *sw); @@ -1073,14 +1059,12 @@ static inline bool tb_port_use_credit_allocation(const struct tb_port *port) int tb_port_get_link_speed(struct tb_port *port); int tb_port_get_link_width(struct tb_port *port); -int tb_port_set_link_width(struct tb_port *port, unsigned int width); -int tb_port_set_lane_bonding(struct tb_port *port, bool bonding); +int tb_port_set_link_width(struct tb_port *port, enum tb_link_width width); int tb_port_lane_bonding_enable(struct tb_port *port); void tb_port_lane_bonding_disable(struct tb_port *port); -int tb_port_wait_for_link_width(struct tb_port *port, int width, +int tb_port_wait_for_link_width(struct tb_port *port, unsigned int width_mask, int timeout_msec); int tb_port_update_credits(struct tb_port *port); -bool tb_port_is_clx_enabled(struct tb_port *port, unsigned int clx); int tb_switch_find_vse_cap(struct tb_switch *sw, enum tb_switch_vse_cap vsec); int tb_switch_find_cap(struct tb_switch *sw, enum tb_switch_cap cap); @@ -1183,6 +1167,17 @@ static inline struct tb_switch *tb_xdomain_parent(struct tb_xdomain *xd) return tb_to_switch(xd->dev.parent); } +/** + * tb_xdomain_downstream_port() - Return downstream facing port of parent router + * @xd: Xdomain pointer + * + * Returns the downstream port the XDomain is connected to. + */ +static inline struct tb_port *tb_xdomain_downstream_port(struct tb_xdomain *xd) +{ + return tb_port_at(xd->route, tb_xdomain_parent(xd)); +} + int tb_retimer_nvm_read(struct tb_retimer *rt, unsigned int address, void *buf, size_t size); int tb_retimer_scan(struct tb_port *port, bool add); @@ -1200,7 +1195,31 @@ static inline struct tb_retimer *tb_to_retimer(struct device *dev) return NULL; } +/** + * usb4_switch_version() - Returns USB4 version of the router + * @sw: Router to check + * + * Returns major version of USB4 router (%1 for v1, %2 for v2 and so + * on). Can be called to pre-USB4 router too and in that case returns %0. + */ +static inline unsigned int usb4_switch_version(const struct tb_switch *sw) +{ + return FIELD_GET(USB4_VERSION_MAJOR_MASK, sw->config.thunderbolt_version); +} + +/** + * tb_switch_is_usb4() - Is the switch USB4 compliant + * @sw: Switch to check + * + * Returns true if the @sw is USB4 compliant router, false otherwise. + */ +static inline bool tb_switch_is_usb4(const struct tb_switch *sw) +{ + return usb4_switch_version(sw) > 0; +} + int usb4_switch_setup(struct tb_switch *sw); +int usb4_switch_configuration_valid(struct tb_switch *sw); int usb4_switch_read_uid(struct tb_switch *sw, u64 *uid); int usb4_switch_drom_read(struct tb_switch *sw, unsigned int address, void *buf, size_t size); @@ -1273,19 +1292,22 @@ int usb4_usb3_port_release_bandwidth(struct tb_port *port, int *upstream_bw, int *downstream_bw); int usb4_dp_port_set_cm_id(struct tb_port *port, int cm_id); -bool usb4_dp_port_bw_mode_supported(struct tb_port *port); -bool usb4_dp_port_bw_mode_enabled(struct tb_port *port); -int usb4_dp_port_set_cm_bw_mode_supported(struct tb_port *port, bool supported); +bool usb4_dp_port_bandwidth_mode_supported(struct tb_port *port); +bool usb4_dp_port_bandwidth_mode_enabled(struct tb_port *port); +int usb4_dp_port_set_cm_bandwidth_mode_supported(struct tb_port *port, + bool supported); int usb4_dp_port_group_id(struct tb_port *port); int usb4_dp_port_set_group_id(struct tb_port *port, int group_id); int usb4_dp_port_nrd(struct tb_port *port, int *rate, int *lanes); int usb4_dp_port_set_nrd(struct tb_port *port, int rate, int lanes); int usb4_dp_port_granularity(struct tb_port *port); int usb4_dp_port_set_granularity(struct tb_port *port, int granularity); -int usb4_dp_port_set_estimated_bw(struct tb_port *port, int bw); -int usb4_dp_port_allocated_bw(struct tb_port *port); -int usb4_dp_port_allocate_bw(struct tb_port *port, int bw); -int usb4_dp_port_requested_bw(struct tb_port *port); +int usb4_dp_port_set_estimated_bandwidth(struct tb_port *port, int bw); +int usb4_dp_port_allocated_bandwidth(struct tb_port *port); +int usb4_dp_port_allocate_bandwidth(struct tb_port *port, int bw); +int usb4_dp_port_requested_bandwidth(struct tb_port *port); + +int usb4_pci_port_set_ext_encapsulation(struct tb_port *port, bool enable); static inline bool tb_is_usb4_port_device(const struct device *dev) { @@ -1303,6 +1325,11 @@ struct usb4_port *usb4_port_device_add(struct tb_port *port); void usb4_port_device_remove(struct usb4_port *usb4); int usb4_port_device_resume(struct usb4_port *usb4); +static inline bool usb4_port_device_is_offline(const struct usb4_port *usb4) +{ + return usb4->offline; +} + void tb_check_quirks(struct tb_switch *sw); #ifdef CONFIG_ACPI diff --git a/drivers/thunderbolt/tb_msgs.h b/drivers/thunderbolt/tb_msgs.h index 3234bff0789952b196e8371e45dff5acfaf99e31..cd750e4b3440514b28587becc054a467c4b12217 100644 --- a/drivers/thunderbolt/tb_msgs.h +++ b/drivers/thunderbolt/tb_msgs.h @@ -30,6 +30,13 @@ enum tb_cfg_error { TB_CFG_ERROR_FLOW_CONTROL_ERROR = 13, TB_CFG_ERROR_LOCK = 15, TB_CFG_ERROR_DP_BW = 32, + TB_CFG_ERROR_ROP_CMPLT = 33, + TB_CFG_ERROR_POP_CMPLT = 34, + TB_CFG_ERROR_PCIE_WAKE = 35, + TB_CFG_ERROR_DP_CON_CHANGE = 36, + TB_CFG_ERROR_DPTX_DISCOVERY = 37, + TB_CFG_ERROR_LINK_RECOVERY = 38, + TB_CFG_ERROR_ASYM_LINK = 39, }; /* common header */ diff --git a/drivers/thunderbolt/tb_regs.h b/drivers/thunderbolt/tb_regs.h index 2636423748cdd7e163acc59d3400b8a80fda55ef..cf9f2370878a8e027ef4c5fba659d2e7e82f411f 100644 --- a/drivers/thunderbolt/tb_regs.h +++ b/drivers/thunderbolt/tb_regs.h @@ -190,11 +190,14 @@ struct tb_regs_switch_header { u32 thunderbolt_version:8; } __packed; -/* USB4 version 1.0 */ -#define USB4_VERSION_1_0 0x20 +/* Used with the router thunderbolt_version */ +#define USB4_VERSION_MAJOR_MASK GENMASK(7, 5) #define ROUTER_CS_1 0x01 #define ROUTER_CS_4 0x04 +/* Used with the router cmuv field */ +#define ROUTER_CS_4_CMUV_V1 0x10 +#define ROUTER_CS_4_CMUV_V2 0x20 #define ROUTER_CS_5 0x05 #define ROUTER_CS_5_SLP BIT(0) #define ROUTER_CS_5_WOP BIT(1) @@ -249,11 +252,13 @@ enum usb4_switch_op { #define TMU_RTR_CS_3_LOCAL_TIME_NS_MASK GENMASK(15, 0) #define TMU_RTR_CS_3_TS_PACKET_INTERVAL_MASK GENMASK(31, 16) #define TMU_RTR_CS_3_TS_PACKET_INTERVAL_SHIFT 16 -#define TMU_RTR_CS_15 0xf +#define TMU_RTR_CS_15 0x0f #define TMU_RTR_CS_15_FREQ_AVG_MASK GENMASK(5, 0) #define TMU_RTR_CS_15_DELAY_AVG_MASK GENMASK(11, 6) #define TMU_RTR_CS_15_OFFSET_AVG_MASK GENMASK(17, 12) #define TMU_RTR_CS_15_ERROR_AVG_MASK GENMASK(23, 18) +#define TMU_RTR_CS_18 0x12 +#define TMU_RTR_CS_18_DELTA_AVG_CONST_MASK GENMASK(23, 16) #define TMU_RTR_CS_22 0x16 #define TMU_RTR_CS_24 0x18 #define TMU_RTR_CS_25 0x19 @@ -319,6 +324,14 @@ struct tb_regs_port_header { #define TMU_ADP_CS_3_UDM BIT(29) #define TMU_ADP_CS_6 0x06 #define TMU_ADP_CS_6_DTS BIT(1) +#define TMU_ADP_CS_8 0x08 +#define TMU_ADP_CS_8_REPL_TIMEOUT_MASK GENMASK(14, 0) +#define TMU_ADP_CS_8_EUDM BIT(15) +#define TMU_ADP_CS_8_REPL_THRESHOLD_MASK GENMASK(25, 16) +#define TMU_ADP_CS_9 0x09 +#define TMU_ADP_CS_9_REPL_N_MASK GENMASK(7, 0) +#define TMU_ADP_CS_9_DIRSWITCH_N_MASK GENMASK(15, 8) +#define TMU_ADP_CS_9_ADP_TS_INTERVAL_MASK GENMASK(31, 16) /* Lane adapter registers */ #define LANE_ADP_CS_0 0x00 @@ -346,6 +359,7 @@ struct tb_regs_port_header { #define LANE_ADP_CS_1_CURRENT_SPEED_SHIFT 16 #define LANE_ADP_CS_1_CURRENT_SPEED_GEN2 0x8 #define LANE_ADP_CS_1_CURRENT_SPEED_GEN3 0x4 +#define LANE_ADP_CS_1_CURRENT_SPEED_GEN4 0x2 #define LANE_ADP_CS_1_CURRENT_WIDTH_MASK GENMASK(25, 20) #define LANE_ADP_CS_1_CURRENT_WIDTH_SHIFT 20 #define LANE_ADP_CS_1_PMS BIT(30) @@ -436,6 +450,9 @@ struct tb_regs_port_header { #define DP_COMMON_CAP_1_LANE 0x0 #define DP_COMMON_CAP_2_LANES 0x1 #define DP_COMMON_CAP_4_LANES 0x2 +#define DP_COMMON_CAP_UHBR10 BIT(17) +#define DP_COMMON_CAP_UHBR20 BIT(18) +#define DP_COMMON_CAP_UHBR13_5 BIT(19) #define DP_COMMON_CAP_LTTPR_NS BIT(27) #define DP_COMMON_CAP_BW_MODE BIT(28) #define DP_COMMON_CAP_DPRX_DONE BIT(31) @@ -447,6 +464,8 @@ struct tb_regs_port_header { /* PCIe adapter registers */ #define ADP_PCIE_CS_0 0x00 #define ADP_PCIE_CS_0_PE BIT(31) +#define ADP_PCIE_CS_1 0x01 +#define ADP_PCIE_CS_1_EE BIT(0) /* USB adapter registers */ #define ADP_USB3_CS_0 0x00 diff --git a/drivers/thunderbolt/test.c b/drivers/thunderbolt/test.c index 24c06e7354cd4868e392e388dd8b3a923076c08e..9475c6698c7ddee48892f16df856cd675426f40f 100644 --- a/drivers/thunderbolt/test.c +++ b/drivers/thunderbolt/test.c @@ -170,6 +170,23 @@ static struct tb_switch *alloc_host_usb4(struct kunit *test) return sw; } +static struct tb_switch *alloc_host_br(struct kunit *test) +{ + struct tb_switch *sw; + + sw = alloc_host_usb4(test); + if (!sw) + return NULL; + + sw->ports[10].config.type = TB_TYPE_DP_HDMI_IN; + sw->ports[10].config.max_in_hop_id = 9; + sw->ports[10].config.max_out_hop_id = 9; + sw->ports[10].cap_adap = -1; + sw->ports[10].disabled = false; + + return sw; +} + static struct tb_switch *alloc_dev_default(struct kunit *test, struct tb_switch *parent, u64 route, bool bonded) @@ -1583,6 +1600,71 @@ static void tb_test_tunnel_dp_max_length(struct kunit *test) tb_tunnel_free(tunnel); } +static void tb_test_tunnel_3dp(struct kunit *test) +{ + struct tb_switch *host, *dev1, *dev2, *dev3, *dev4, *dev5; + struct tb_port *in1, *in2, *in3, *out1, *out2, *out3; + struct tb_tunnel *tunnel1, *tunnel2, *tunnel3; + + /* + * Create 3 DP tunnels from Host to Devices #2, #5 and #4. + * + * [Host] + * 3 | + * 1 | + * [Device #1] + * 3 / | 5 \ 7 + * 1 / | \ 1 + * [Device #2] | [Device #4] + * | 1 + * [Device #3] + * | 5 + * | 1 + * [Device #5] + */ + host = alloc_host_br(test); + dev1 = alloc_dev_default(test, host, 0x3, true); + dev2 = alloc_dev_default(test, dev1, 0x303, true); + dev3 = alloc_dev_default(test, dev1, 0x503, true); + dev4 = alloc_dev_default(test, dev1, 0x703, true); + dev5 = alloc_dev_default(test, dev3, 0x50503, true); + + in1 = &host->ports[5]; + in2 = &host->ports[6]; + in3 = &host->ports[10]; + + out1 = &dev2->ports[13]; + out2 = &dev5->ports[13]; + out3 = &dev4->ports[14]; + + tunnel1 = tb_tunnel_alloc_dp(NULL, in1, out1, 1, 0, 0); + KUNIT_ASSERT_TRUE(test, tunnel1 != NULL); + KUNIT_EXPECT_EQ(test, tunnel1->type, TB_TUNNEL_DP); + KUNIT_EXPECT_PTR_EQ(test, tunnel1->src_port, in1); + KUNIT_EXPECT_PTR_EQ(test, tunnel1->dst_port, out1); + KUNIT_ASSERT_EQ(test, tunnel1->npaths, 3); + KUNIT_ASSERT_EQ(test, tunnel1->paths[0]->path_length, 3); + + tunnel2 = tb_tunnel_alloc_dp(NULL, in2, out2, 1, 0, 0); + KUNIT_ASSERT_TRUE(test, tunnel2 != NULL); + KUNIT_EXPECT_EQ(test, tunnel2->type, TB_TUNNEL_DP); + KUNIT_EXPECT_PTR_EQ(test, tunnel2->src_port, in2); + KUNIT_EXPECT_PTR_EQ(test, tunnel2->dst_port, out2); + KUNIT_ASSERT_EQ(test, tunnel2->npaths, 3); + KUNIT_ASSERT_EQ(test, tunnel2->paths[0]->path_length, 4); + + tunnel3 = tb_tunnel_alloc_dp(NULL, in3, out3, 1, 0, 0); + KUNIT_ASSERT_TRUE(test, tunnel3 != NULL); + KUNIT_EXPECT_EQ(test, tunnel3->type, TB_TUNNEL_DP); + KUNIT_EXPECT_PTR_EQ(test, tunnel3->src_port, in3); + KUNIT_EXPECT_PTR_EQ(test, tunnel3->dst_port, out3); + KUNIT_ASSERT_EQ(test, tunnel3->npaths, 3); + KUNIT_ASSERT_EQ(test, tunnel3->paths[0]->path_length, 3); + + tb_tunnel_free(tunnel2); + tb_tunnel_free(tunnel1); +} + static void tb_test_tunnel_usb3(struct kunit *test) { struct tb_switch *host, *dev1, *dev2; @@ -2790,6 +2872,7 @@ static struct kunit_case tb_test_cases[] = { KUNIT_CASE(tb_test_tunnel_dp_chain), KUNIT_CASE(tb_test_tunnel_dp_tree), KUNIT_CASE(tb_test_tunnel_dp_max_length), + KUNIT_CASE(tb_test_tunnel_3dp), KUNIT_CASE(tb_test_tunnel_port_on_path), KUNIT_CASE(tb_test_tunnel_usb3), KUNIT_CASE(tb_test_tunnel_dma), diff --git a/drivers/thunderbolt/tmu.c b/drivers/thunderbolt/tmu.c index 626aca3124b1c1fea877fb15ca7147b2a6de5a42..1269f417515bbc8979f9c8279e9f32c26fa8770c 100644 --- a/drivers/thunderbolt/tmu.c +++ b/drivers/thunderbolt/tmu.c @@ -11,23 +11,63 @@ #include "tb.h" +static const unsigned int tmu_rates[] = { + [TB_SWITCH_TMU_MODE_OFF] = 0, + [TB_SWITCH_TMU_MODE_LOWRES] = 1000, + [TB_SWITCH_TMU_MODE_HIFI_UNI] = 16, + [TB_SWITCH_TMU_MODE_HIFI_BI] = 16, + [TB_SWITCH_TMU_MODE_MEDRES_ENHANCED_UNI] = 16, +}; + +const struct { + unsigned int freq_meas_window; + unsigned int avg_const; + unsigned int delta_avg_const; + unsigned int repl_timeout; + unsigned int repl_threshold; + unsigned int repl_n; + unsigned int dirswitch_n; +} tmu_params[] = { + [TB_SWITCH_TMU_MODE_OFF] = { }, + [TB_SWITCH_TMU_MODE_LOWRES] = { 30, 4, }, + [TB_SWITCH_TMU_MODE_HIFI_UNI] = { 800, 8, }, + [TB_SWITCH_TMU_MODE_HIFI_BI] = { 800, 8, }, + [TB_SWITCH_TMU_MODE_MEDRES_ENHANCED_UNI] = { + 800, 4, 0, 3125, 25, 128, 255, + }, +}; + +static const char *tmu_mode_name(enum tb_switch_tmu_mode mode) +{ + switch (mode) { + case TB_SWITCH_TMU_MODE_OFF: + return "off"; + case TB_SWITCH_TMU_MODE_LOWRES: + return "uni-directional, LowRes"; + case TB_SWITCH_TMU_MODE_HIFI_UNI: + return "uni-directional, HiFi"; + case TB_SWITCH_TMU_MODE_HIFI_BI: + return "bi-directional, HiFi"; + case TB_SWITCH_TMU_MODE_MEDRES_ENHANCED_UNI: + return "enhanced uni-directional, MedRes"; + default: + return "unknown"; + } +} + +static bool tb_switch_tmu_enhanced_is_supported(const struct tb_switch *sw) +{ + return usb4_switch_version(sw) > 1; +} + static int tb_switch_set_tmu_mode_params(struct tb_switch *sw, - enum tb_switch_tmu_rate rate) + enum tb_switch_tmu_mode mode) { - u32 freq_meas_wind[2] = { 30, 800 }; - u32 avg_const[2] = { 4, 8 }; u32 freq, avg, val; int ret; - if (rate == TB_SWITCH_TMU_RATE_NORMAL) { - freq = freq_meas_wind[0]; - avg = avg_const[0]; - } else if (rate == TB_SWITCH_TMU_RATE_HIFI) { - freq = freq_meas_wind[1]; - avg = avg_const[1]; - } else { - return 0; - } + freq = tmu_params[mode].freq_meas_window; + avg = tmu_params[mode].avg_const; ret = tb_sw_read(sw, &val, TB_CFG_SWITCH, sw->tmu.cap + TMU_RTR_CS_0, 1); @@ -56,37 +96,30 @@ static int tb_switch_set_tmu_mode_params(struct tb_switch *sw, FIELD_PREP(TMU_RTR_CS_15_OFFSET_AVG_MASK, avg) | FIELD_PREP(TMU_RTR_CS_15_ERROR_AVG_MASK, avg); - return tb_sw_write(sw, &val, TB_CFG_SWITCH, - sw->tmu.cap + TMU_RTR_CS_15, 1); -} - -static const char *tb_switch_tmu_mode_name(const struct tb_switch *sw) -{ - bool root_switch = !tb_route(sw); + ret = tb_sw_write(sw, &val, TB_CFG_SWITCH, + sw->tmu.cap + TMU_RTR_CS_15, 1); + if (ret) + return ret; - switch (sw->tmu.rate) { - case TB_SWITCH_TMU_RATE_OFF: - return "off"; + if (tb_switch_tmu_enhanced_is_supported(sw)) { + u32 delta_avg = tmu_params[mode].delta_avg_const; - case TB_SWITCH_TMU_RATE_HIFI: - /* Root switch does not have upstream directionality */ - if (root_switch) - return "HiFi"; - if (sw->tmu.unidirectional) - return "uni-directional, HiFi"; - return "bi-directional, HiFi"; + ret = tb_sw_read(sw, &val, TB_CFG_SWITCH, + sw->tmu.cap + TMU_RTR_CS_18, 1); + if (ret) + return ret; - case TB_SWITCH_TMU_RATE_NORMAL: - if (root_switch) - return "normal"; - return "uni-directional, normal"; + val &= ~TMU_RTR_CS_18_DELTA_AVG_CONST_MASK; + val |= FIELD_PREP(TMU_RTR_CS_18_DELTA_AVG_CONST_MASK, delta_avg); - default: - return "unknown"; + ret = tb_sw_write(sw, &val, TB_CFG_SWITCH, + sw->tmu.cap + TMU_RTR_CS_18, 1); } + + return ret; } -static bool tb_switch_tmu_ucap_supported(struct tb_switch *sw) +static bool tb_switch_tmu_ucap_is_supported(struct tb_switch *sw) { int ret; u32 val; @@ -182,6 +215,103 @@ static bool tb_port_tmu_is_unidirectional(struct tb_port *port) return val & TMU_ADP_CS_3_UDM; } +static bool tb_port_tmu_is_enhanced(struct tb_port *port) +{ + int ret; + u32 val; + + ret = tb_port_read(port, &val, TB_CFG_PORT, + port->cap_tmu + TMU_ADP_CS_8, 1); + if (ret) + return false; + + return val & TMU_ADP_CS_8_EUDM; +} + +/* Can be called to non-v2 lane adapters too */ +static int tb_port_tmu_enhanced_enable(struct tb_port *port, bool enable) +{ + int ret; + u32 val; + + if (!tb_switch_tmu_enhanced_is_supported(port->sw)) + return 0; + + ret = tb_port_read(port, &val, TB_CFG_PORT, + port->cap_tmu + TMU_ADP_CS_8, 1); + if (ret) + return ret; + + if (enable) + val |= TMU_ADP_CS_8_EUDM; + else + val &= ~TMU_ADP_CS_8_EUDM; + + return tb_port_write(port, &val, TB_CFG_PORT, + port->cap_tmu + TMU_ADP_CS_8, 1); +} + +static int tb_port_set_tmu_mode_params(struct tb_port *port, + enum tb_switch_tmu_mode mode) +{ + u32 repl_timeout, repl_threshold, repl_n, dirswitch_n, val; + int ret; + + repl_timeout = tmu_params[mode].repl_timeout; + repl_threshold = tmu_params[mode].repl_threshold; + repl_n = tmu_params[mode].repl_n; + dirswitch_n = tmu_params[mode].dirswitch_n; + + ret = tb_port_read(port, &val, TB_CFG_PORT, + port->cap_tmu + TMU_ADP_CS_8, 1); + if (ret) + return ret; + + val &= ~TMU_ADP_CS_8_REPL_TIMEOUT_MASK; + val &= ~TMU_ADP_CS_8_REPL_THRESHOLD_MASK; + val |= FIELD_PREP(TMU_ADP_CS_8_REPL_TIMEOUT_MASK, repl_timeout); + val |= FIELD_PREP(TMU_ADP_CS_8_REPL_THRESHOLD_MASK, repl_threshold); + + ret = tb_port_write(port, &val, TB_CFG_PORT, + port->cap_tmu + TMU_ADP_CS_8, 1); + if (ret) + return ret; + + ret = tb_port_read(port, &val, TB_CFG_PORT, + port->cap_tmu + TMU_ADP_CS_9, 1); + if (ret) + return ret; + + val &= ~TMU_ADP_CS_9_REPL_N_MASK; + val &= ~TMU_ADP_CS_9_DIRSWITCH_N_MASK; + val |= FIELD_PREP(TMU_ADP_CS_9_REPL_N_MASK, repl_n); + val |= FIELD_PREP(TMU_ADP_CS_9_DIRSWITCH_N_MASK, dirswitch_n); + + return tb_port_write(port, &val, TB_CFG_PORT, + port->cap_tmu + TMU_ADP_CS_9, 1); +} + +/* Can be called to non-v2 lane adapters too */ +static int tb_port_tmu_rate_write(struct tb_port *port, int rate) +{ + int ret; + u32 val; + + if (!tb_switch_tmu_enhanced_is_supported(port->sw)) + return 0; + + ret = tb_port_read(port, &val, TB_CFG_PORT, + port->cap_tmu + TMU_ADP_CS_9, 1); + if (ret) + return ret; + + val &= ~TMU_ADP_CS_9_ADP_TS_INTERVAL_MASK; + val |= FIELD_PREP(TMU_ADP_CS_9_ADP_TS_INTERVAL_MASK, rate); + + return tb_port_write(port, &val, TB_CFG_PORT, + port->cap_tmu + TMU_ADP_CS_9, 1); +} + static int tb_port_tmu_time_sync(struct tb_port *port, bool time_sync) { u32 val = time_sync ? TMU_ADP_CS_6_DTS : 0; @@ -224,6 +354,50 @@ static int tb_switch_tmu_set_time_disruption(struct tb_switch *sw, bool set) return tb_sw_write(sw, &val, TB_CFG_SWITCH, offset, 1); } +static int tmu_mode_init(struct tb_switch *sw) +{ + bool enhanced, ucap; + int ret, rate; + + ucap = tb_switch_tmu_ucap_is_supported(sw); + if (ucap) + tb_sw_dbg(sw, "TMU: supports uni-directional mode\n"); + enhanced = tb_switch_tmu_enhanced_is_supported(sw); + if (enhanced) + tb_sw_dbg(sw, "TMU: supports enhanced uni-directional mode\n"); + + ret = tb_switch_tmu_rate_read(sw); + if (ret < 0) + return ret; + rate = ret; + + /* Off by default */ + sw->tmu.mode = TB_SWITCH_TMU_MODE_OFF; + + if (tb_route(sw)) { + struct tb_port *up = tb_upstream_port(sw); + + if (enhanced && tb_port_tmu_is_enhanced(up)) { + sw->tmu.mode = TB_SWITCH_TMU_MODE_MEDRES_ENHANCED_UNI; + } else if (ucap && tb_port_tmu_is_unidirectional(up)) { + if (tmu_rates[TB_SWITCH_TMU_MODE_LOWRES] == rate) + sw->tmu.mode = TB_SWITCH_TMU_MODE_LOWRES; + else if (tmu_rates[TB_SWITCH_TMU_MODE_LOWRES] == rate) + sw->tmu.mode = TB_SWITCH_TMU_MODE_HIFI_UNI; + } else if (rate) { + sw->tmu.mode = TB_SWITCH_TMU_MODE_HIFI_BI; + } + } else if (rate) { + sw->tmu.mode = TB_SWITCH_TMU_MODE_HIFI_BI; + } + + /* Update the initial request to match the current mode */ + sw->tmu.mode_request = sw->tmu.mode; + sw->tmu.has_ucap = ucap; + + return 0; +} + /** * tb_switch_tmu_init() - Initialize switch TMU structures * @sw: Switch to initialized @@ -252,27 +426,11 @@ int tb_switch_tmu_init(struct tb_switch *sw) port->cap_tmu = cap; } - ret = tb_switch_tmu_rate_read(sw); - if (ret < 0) + ret = tmu_mode_init(sw); + if (ret) return ret; - sw->tmu.rate = ret; - - sw->tmu.has_ucap = tb_switch_tmu_ucap_supported(sw); - if (sw->tmu.has_ucap) { - tb_sw_dbg(sw, "TMU: supports uni-directional mode\n"); - - if (tb_route(sw)) { - struct tb_port *up = tb_upstream_port(sw); - - sw->tmu.unidirectional = - tb_port_tmu_is_unidirectional(up); - } - } else { - sw->tmu.unidirectional = false; - } - - tb_sw_dbg(sw, "TMU: current mode: %s\n", tb_switch_tmu_mode_name(sw)); + tb_sw_dbg(sw, "TMU: current mode: %s\n", tmu_mode_name(sw->tmu.mode)); return 0; } @@ -308,7 +466,7 @@ int tb_switch_tmu_post_time(struct tb_switch *sw) return ret; for (i = 0; i < ARRAY_SIZE(gm_local_time); i++) - tb_sw_dbg(root_switch, "local_time[%d]=0x%08x\n", i, + tb_sw_dbg(root_switch, "TMU: local_time[%d]=0x%08x\n", i, gm_local_time[i]); /* Convert to nanoseconds (drop fractional part) */ @@ -375,6 +533,23 @@ int tb_switch_tmu_post_time(struct tb_switch *sw) return ret; } +static int disable_enhanced(struct tb_port *up, struct tb_port *down) +{ + int ret; + + /* + * Router may already been disconnected so ignore errors on the + * upstream port. + */ + tb_port_tmu_rate_write(up, 0); + tb_port_tmu_enhanced_enable(up, false); + + ret = tb_port_tmu_rate_write(down, 0); + if (ret) + return ret; + return tb_port_tmu_enhanced_enable(down, false); +} + /** * tb_switch_tmu_disable() - Disable TMU of a switch * @sw: Switch whose TMU to disable @@ -383,26 +558,15 @@ int tb_switch_tmu_post_time(struct tb_switch *sw) */ int tb_switch_tmu_disable(struct tb_switch *sw) { - /* - * No need to disable TMU on devices that don't support CLx since - * on these devices e.g. Alpine Ridge and earlier, the TMU mode - * HiFi bi-directional is enabled by default and we don't change it. - */ - if (!tb_switch_is_clx_supported(sw)) - return 0; - /* Already disabled? */ - if (sw->tmu.rate == TB_SWITCH_TMU_RATE_OFF) + if (sw->tmu.mode == TB_SWITCH_TMU_MODE_OFF) return 0; - if (tb_route(sw)) { - bool unidirectional = sw->tmu.unidirectional; - struct tb_switch *parent = tb_switch_parent(sw); struct tb_port *down, *up; int ret; - down = tb_port_at(tb_route(sw), parent); + down = tb_switch_downstream_port(sw); up = tb_upstream_port(sw); /* * In case of uni-directional time sync, TMU handshake is @@ -415,37 +579,49 @@ int tb_switch_tmu_disable(struct tb_switch *sw) * uni-directional mode and we don't want to change it's TMU * mode. */ - tb_switch_tmu_rate_write(sw, TB_SWITCH_TMU_RATE_OFF); + tb_switch_tmu_rate_write(sw, tmu_rates[TB_SWITCH_TMU_MODE_OFF]); tb_port_tmu_time_sync_disable(up); ret = tb_port_tmu_time_sync_disable(down); if (ret) return ret; - if (unidirectional) { + switch (sw->tmu.mode) { + case TB_SWITCH_TMU_MODE_LOWRES: + case TB_SWITCH_TMU_MODE_HIFI_UNI: /* The switch may be unplugged so ignore any errors */ tb_port_tmu_unidirectional_disable(up); ret = tb_port_tmu_unidirectional_disable(down); if (ret) return ret; + break; + + case TB_SWITCH_TMU_MODE_MEDRES_ENHANCED_UNI: + ret = disable_enhanced(up, down); + if (ret) + return ret; + break; + + default: + break; } } else { - tb_switch_tmu_rate_write(sw, TB_SWITCH_TMU_RATE_OFF); + tb_switch_tmu_rate_write(sw, tmu_rates[TB_SWITCH_TMU_MODE_OFF]); } - sw->tmu.unidirectional = false; - sw->tmu.rate = TB_SWITCH_TMU_RATE_OFF; + sw->tmu.mode = TB_SWITCH_TMU_MODE_OFF; tb_sw_dbg(sw, "TMU: disabled\n"); return 0; } -static void __tb_switch_tmu_off(struct tb_switch *sw, bool unidirectional) +/* Called only when there is failure enabling requested mode */ +static void tb_switch_tmu_off(struct tb_switch *sw) { - struct tb_switch *parent = tb_switch_parent(sw); + unsigned int rate = tmu_rates[TB_SWITCH_TMU_MODE_OFF]; struct tb_port *down, *up; - down = tb_port_at(tb_route(sw), parent); + down = tb_switch_downstream_port(sw); up = tb_upstream_port(sw); /* * In case of any failure in one of the steps when setting @@ -456,28 +632,38 @@ static void __tb_switch_tmu_off(struct tb_switch *sw, bool unidirectional) */ tb_port_tmu_time_sync_disable(down); tb_port_tmu_time_sync_disable(up); - if (unidirectional) - tb_switch_tmu_rate_write(parent, TB_SWITCH_TMU_RATE_OFF); - else - tb_switch_tmu_rate_write(sw, TB_SWITCH_TMU_RATE_OFF); - tb_switch_set_tmu_mode_params(sw, sw->tmu.rate); + switch (sw->tmu.mode_request) { + case TB_SWITCH_TMU_MODE_LOWRES: + case TB_SWITCH_TMU_MODE_HIFI_UNI: + tb_switch_tmu_rate_write(tb_switch_parent(sw), rate); + break; + case TB_SWITCH_TMU_MODE_MEDRES_ENHANCED_UNI: + disable_enhanced(up, down); + break; + default: + break; + } + + /* Always set the rate to 0 */ + tb_switch_tmu_rate_write(sw, rate); + + tb_switch_set_tmu_mode_params(sw, sw->tmu.mode); tb_port_tmu_unidirectional_disable(down); tb_port_tmu_unidirectional_disable(up); } /* * This function is called when the previous TMU mode was - * TB_SWITCH_TMU_RATE_OFF. + * TB_SWITCH_TMU_MODE_OFF. */ -static int __tb_switch_tmu_enable_bidirectional(struct tb_switch *sw) +static int tb_switch_tmu_enable_bidirectional(struct tb_switch *sw) { - struct tb_switch *parent = tb_switch_parent(sw); struct tb_port *up, *down; int ret; up = tb_upstream_port(sw); - down = tb_port_at(tb_route(sw), parent); + down = tb_switch_downstream_port(sw); ret = tb_port_tmu_unidirectional_disable(up); if (ret) @@ -487,7 +673,7 @@ static int __tb_switch_tmu_enable_bidirectional(struct tb_switch *sw) if (ret) goto out; - ret = tb_switch_tmu_rate_write(sw, TB_SWITCH_TMU_RATE_HIFI); + ret = tb_switch_tmu_rate_write(sw, tmu_rates[TB_SWITCH_TMU_MODE_HIFI_BI]); if (ret) goto out; @@ -502,12 +688,14 @@ static int __tb_switch_tmu_enable_bidirectional(struct tb_switch *sw) return 0; out: - __tb_switch_tmu_off(sw, false); + tb_switch_tmu_off(sw); return ret; } -static int tb_switch_tmu_objection_mask(struct tb_switch *sw) +/* Only needed for Titan Ridge */ +static int tb_switch_tmu_disable_objections(struct tb_switch *sw) { + struct tb_port *up = tb_upstream_port(sw); u32 val; int ret; @@ -518,36 +706,34 @@ static int tb_switch_tmu_objection_mask(struct tb_switch *sw) val &= ~TB_TIME_VSEC_3_CS_9_TMU_OBJ_MASK; - return tb_sw_write(sw, &val, TB_CFG_SWITCH, - sw->cap_vsec_tmu + TB_TIME_VSEC_3_CS_9, 1); -} - -static int tb_switch_tmu_unidirectional_enable(struct tb_switch *sw) -{ - struct tb_port *up = tb_upstream_port(sw); + ret = tb_sw_write(sw, &val, TB_CFG_SWITCH, + sw->cap_vsec_tmu + TB_TIME_VSEC_3_CS_9, 1); + if (ret) + return ret; return tb_port_tmu_write(up, TMU_ADP_CS_6, TMU_ADP_CS_6_DISABLE_TMU_OBJ_MASK, - TMU_ADP_CS_6_DISABLE_TMU_OBJ_MASK); + TMU_ADP_CS_6_DISABLE_TMU_OBJ_CL1 | + TMU_ADP_CS_6_DISABLE_TMU_OBJ_CL2); } /* * This function is called when the previous TMU mode was - * TB_SWITCH_TMU_RATE_OFF. + * TB_SWITCH_TMU_MODE_OFF. */ -static int __tb_switch_tmu_enable_unidirectional(struct tb_switch *sw) +static int tb_switch_tmu_enable_unidirectional(struct tb_switch *sw) { - struct tb_switch *parent = tb_switch_parent(sw); struct tb_port *up, *down; int ret; up = tb_upstream_port(sw); - down = tb_port_at(tb_route(sw), parent); - ret = tb_switch_tmu_rate_write(parent, sw->tmu.rate_request); + down = tb_switch_downstream_port(sw); + ret = tb_switch_tmu_rate_write(tb_switch_parent(sw), + tmu_rates[sw->tmu.mode_request]); if (ret) return ret; - ret = tb_switch_set_tmu_mode_params(sw, sw->tmu.rate_request); + ret = tb_switch_set_tmu_mode_params(sw, sw->tmu.mode_request); if (ret) return ret; @@ -570,16 +756,65 @@ static int __tb_switch_tmu_enable_unidirectional(struct tb_switch *sw) return 0; out: - __tb_switch_tmu_off(sw, true); + tb_switch_tmu_off(sw); + return ret; +} + +/* + * This function is called when the previous TMU mode was + * TB_SWITCH_TMU_RATE_OFF. + */ +static int tb_switch_tmu_enable_enhanced(struct tb_switch *sw) +{ + unsigned int rate = tmu_rates[sw->tmu.mode_request]; + struct tb_port *up, *down; + int ret; + + /* Router specific parameters first */ + ret = tb_switch_set_tmu_mode_params(sw, sw->tmu.mode_request); + if (ret) + return ret; + + up = tb_upstream_port(sw); + down = tb_switch_downstream_port(sw); + + ret = tb_port_set_tmu_mode_params(up, sw->tmu.mode_request); + if (ret) + goto out; + + ret = tb_port_tmu_rate_write(up, rate); + if (ret) + goto out; + + ret = tb_port_tmu_enhanced_enable(up, true); + if (ret) + goto out; + + ret = tb_port_set_tmu_mode_params(down, sw->tmu.mode_request); + if (ret) + goto out; + + ret = tb_port_tmu_rate_write(down, rate); + if (ret) + goto out; + + ret = tb_port_tmu_enhanced_enable(down, true); + if (ret) + goto out; + + return 0; + +out: + tb_switch_tmu_off(sw); return ret; } -static void __tb_switch_tmu_change_mode_prev(struct tb_switch *sw) +static void tb_switch_tmu_change_mode_prev(struct tb_switch *sw) { - struct tb_switch *parent = tb_switch_parent(sw); + unsigned int rate = tmu_rates[sw->tmu.mode]; struct tb_port *down, *up; - down = tb_port_at(tb_route(sw), parent); + down = tb_switch_downstream_port(sw); up = tb_upstream_port(sw); /* * In case of any failure in one of the steps when change mode, @@ -587,42 +822,97 @@ static void __tb_switch_tmu_change_mode_prev(struct tb_switch *sw) * In case of additional failures in the functions below, * ignore them since the caller shall already report a failure. */ - tb_port_tmu_set_unidirectional(down, sw->tmu.unidirectional); - if (sw->tmu.unidirectional_request) - tb_switch_tmu_rate_write(parent, sw->tmu.rate); - else - tb_switch_tmu_rate_write(sw, sw->tmu.rate); + switch (sw->tmu.mode) { + case TB_SWITCH_TMU_MODE_LOWRES: + case TB_SWITCH_TMU_MODE_HIFI_UNI: + tb_port_tmu_set_unidirectional(down, true); + tb_switch_tmu_rate_write(tb_switch_parent(sw), rate); + break; + + case TB_SWITCH_TMU_MODE_HIFI_BI: + tb_port_tmu_set_unidirectional(down, false); + tb_switch_tmu_rate_write(sw, rate); + break; + + default: + break; + } + + tb_switch_set_tmu_mode_params(sw, sw->tmu.mode); + + switch (sw->tmu.mode) { + case TB_SWITCH_TMU_MODE_LOWRES: + case TB_SWITCH_TMU_MODE_HIFI_UNI: + tb_port_tmu_set_unidirectional(up, true); + break; + + case TB_SWITCH_TMU_MODE_HIFI_BI: + tb_port_tmu_set_unidirectional(up, false); + break; - tb_switch_set_tmu_mode_params(sw, sw->tmu.rate); - tb_port_tmu_set_unidirectional(up, sw->tmu.unidirectional); + default: + break; + } } -static int __tb_switch_tmu_change_mode(struct tb_switch *sw) +static int tb_switch_tmu_change_mode(struct tb_switch *sw) { - struct tb_switch *parent = tb_switch_parent(sw); + unsigned int rate = tmu_rates[sw->tmu.mode_request]; struct tb_port *up, *down; int ret; up = tb_upstream_port(sw); - down = tb_port_at(tb_route(sw), parent); - ret = tb_port_tmu_set_unidirectional(down, sw->tmu.unidirectional_request); - if (ret) - goto out; + down = tb_switch_downstream_port(sw); - if (sw->tmu.unidirectional_request) - ret = tb_switch_tmu_rate_write(parent, sw->tmu.rate_request); - else - ret = tb_switch_tmu_rate_write(sw, sw->tmu.rate_request); - if (ret) - return ret; + /* Program the upstream router downstream facing lane adapter */ + switch (sw->tmu.mode_request) { + case TB_SWITCH_TMU_MODE_LOWRES: + case TB_SWITCH_TMU_MODE_HIFI_UNI: + ret = tb_port_tmu_set_unidirectional(down, true); + if (ret) + goto out; + ret = tb_switch_tmu_rate_write(tb_switch_parent(sw), rate); + if (ret) + goto out; + break; - ret = tb_switch_set_tmu_mode_params(sw, sw->tmu.rate_request); + case TB_SWITCH_TMU_MODE_HIFI_BI: + ret = tb_port_tmu_set_unidirectional(down, false); + if (ret) + goto out; + ret = tb_switch_tmu_rate_write(sw, rate); + if (ret) + goto out; + break; + + default: + /* Not allowed to change modes from other than above */ + return -EINVAL; + } + + ret = tb_switch_set_tmu_mode_params(sw, sw->tmu.mode_request); if (ret) return ret; - ret = tb_port_tmu_set_unidirectional(up, sw->tmu.unidirectional_request); - if (ret) - goto out; + /* Program the new mode and the downstream router lane adapter */ + switch (sw->tmu.mode_request) { + case TB_SWITCH_TMU_MODE_LOWRES: + case TB_SWITCH_TMU_MODE_HIFI_UNI: + ret = tb_port_tmu_set_unidirectional(up, true); + if (ret) + goto out; + break; + + case TB_SWITCH_TMU_MODE_HIFI_BI: + ret = tb_port_tmu_set_unidirectional(up, false); + if (ret) + goto out; + break; + + default: + /* Not allowed to change modes from other than above */ + return -EINVAL; + } ret = tb_port_tmu_time_sync_enable(down); if (ret) @@ -635,7 +925,7 @@ static int __tb_switch_tmu_change_mode(struct tb_switch *sw) return 0; out: - __tb_switch_tmu_change_mode_prev(sw); + tb_switch_tmu_change_mode_prev(sw); return ret; } @@ -643,45 +933,21 @@ static int __tb_switch_tmu_change_mode(struct tb_switch *sw) * tb_switch_tmu_enable() - Enable TMU on a router * @sw: Router whose TMU to enable * - * Enables TMU of a router to be in uni-directional Normal/HiFi - * or bi-directional HiFi mode. Calling tb_switch_tmu_configure() is required - * before calling this function, to select the mode Normal/HiFi and - * directionality (uni-directional/bi-directional). - * In HiFi mode all tunneling should work. In Normal mode, DP tunneling can't - * work. Uni-directional mode is required for CLx (Link Low-Power) to work. + * Enables TMU of a router to be in uni-directional Normal/HiFi or + * bi-directional HiFi mode. Calling tb_switch_tmu_configure() is + * required before calling this function. */ int tb_switch_tmu_enable(struct tb_switch *sw) { - bool unidirectional = sw->tmu.unidirectional_request; int ret; - if (unidirectional && !sw->tmu.has_ucap) - return -EOPNOTSUPP; - - /* - * No need to enable TMU on devices that don't support CLx since on - * these devices e.g. Alpine Ridge and earlier, the TMU mode HiFi - * bi-directional is enabled by default. - */ - if (!tb_switch_is_clx_supported(sw)) - return 0; - - if (tb_switch_tmu_is_enabled(sw, sw->tmu.unidirectional_request)) + if (tb_switch_tmu_is_enabled(sw)) return 0; - if (tb_switch_is_titan_ridge(sw) && unidirectional) { - /* - * Titan Ridge supports CL0s and CL1 only. CL0s and CL1 are - * enabled and supported together. - */ - if (!tb_switch_is_clx_enabled(sw, TB_CL1)) - return -EOPNOTSUPP; - - ret = tb_switch_tmu_objection_mask(sw); - if (ret) - return ret; - - ret = tb_switch_tmu_unidirectional_enable(sw); + if (tb_switch_is_titan_ridge(sw) && + (sw->tmu.mode_request == TB_SWITCH_TMU_MODE_LOWRES || + sw->tmu.mode_request == TB_SWITCH_TMU_MODE_HIFI_UNI)) { + ret = tb_switch_tmu_disable_objections(sw); if (ret) return ret; } @@ -696,19 +962,30 @@ int tb_switch_tmu_enable(struct tb_switch *sw) * HiFi-Uni/HiFi-BiDir/Normal-Uni or from Normal-Uni to * HiFi-Uni. */ - if (sw->tmu.rate == TB_SWITCH_TMU_RATE_OFF) { - if (unidirectional) - ret = __tb_switch_tmu_enable_unidirectional(sw); - else - ret = __tb_switch_tmu_enable_bidirectional(sw); - if (ret) - return ret; - } else if (sw->tmu.rate == TB_SWITCH_TMU_RATE_NORMAL) { - ret = __tb_switch_tmu_change_mode(sw); - if (ret) - return ret; + if (sw->tmu.mode == TB_SWITCH_TMU_MODE_OFF) { + switch (sw->tmu.mode_request) { + case TB_SWITCH_TMU_MODE_LOWRES: + case TB_SWITCH_TMU_MODE_HIFI_UNI: + ret = tb_switch_tmu_enable_unidirectional(sw); + break; + + case TB_SWITCH_TMU_MODE_HIFI_BI: + ret = tb_switch_tmu_enable_bidirectional(sw); + break; + case TB_SWITCH_TMU_MODE_MEDRES_ENHANCED_UNI: + ret = tb_switch_tmu_enable_enhanced(sw); + break; + default: + ret = -EINVAL; + break; + } + } else if (sw->tmu.mode == TB_SWITCH_TMU_MODE_LOWRES || + sw->tmu.mode == TB_SWITCH_TMU_MODE_HIFI_UNI || + sw->tmu.mode == TB_SWITCH_TMU_MODE_HIFI_BI) { + ret = tb_switch_tmu_change_mode(sw); + } else { + ret = -EINVAL; } - sw->tmu.unidirectional = unidirectional; } else { /* * Host router port configurations are written as @@ -716,58 +993,68 @@ int tb_switch_tmu_enable(struct tb_switch *sw) * of the child node - see above. * Here only the host router' rate configuration is written. */ - ret = tb_switch_tmu_rate_write(sw, sw->tmu.rate_request); - if (ret) - return ret; + ret = tb_switch_tmu_rate_write(sw, tmu_rates[sw->tmu.mode_request]); } - sw->tmu.rate = sw->tmu.rate_request; + if (ret) { + tb_sw_warn(sw, "TMU: failed to enable mode %s: %d\n", + tmu_mode_name(sw->tmu.mode_request), ret); + } else { + sw->tmu.mode = sw->tmu.mode_request; + tb_sw_dbg(sw, "TMU: mode set to: %s\n", tmu_mode_name(sw->tmu.mode)); + } - tb_sw_dbg(sw, "TMU: mode set to: %s\n", tb_switch_tmu_mode_name(sw)); return tb_switch_tmu_set_time_disruption(sw, false); } /** - * tb_switch_tmu_configure() - Configure the TMU rate and directionality + * tb_switch_tmu_configure() - Configure the TMU mode * @sw: Router whose mode to change - * @rate: Rate to configure Off/Normal/HiFi - * @unidirectional: If uni-directional (bi-directional otherwise) + * @mode: Mode to configure * - * Selects the rate of the TMU and directionality (uni-directional or - * bi-directional). Must be called before tb_switch_tmu_enable(). + * Selects the TMU mode that is enabled when tb_switch_tmu_enable() is + * next called. + * + * Returns %0 in success and negative errno otherwise. Specifically + * returns %-EOPNOTSUPP if the requested mode is not possible (not + * supported by the router and/or topology). */ -void tb_switch_tmu_configure(struct tb_switch *sw, - enum tb_switch_tmu_rate rate, bool unidirectional) +int tb_switch_tmu_configure(struct tb_switch *sw, enum tb_switch_tmu_mode mode) { - sw->tmu.unidirectional_request = unidirectional; - sw->tmu.rate_request = rate; -} + switch (mode) { + case TB_SWITCH_TMU_MODE_OFF: + break; -static int tb_switch_tmu_config_enable(struct device *dev, void *rate) -{ - if (tb_is_switch(dev)) { - struct tb_switch *sw = tb_to_switch(dev); + case TB_SWITCH_TMU_MODE_LOWRES: + case TB_SWITCH_TMU_MODE_HIFI_UNI: + if (!sw->tmu.has_ucap) + return -EOPNOTSUPP; + break; - tb_switch_tmu_configure(sw, *(enum tb_switch_tmu_rate *)rate, - tb_switch_is_clx_enabled(sw, TB_CL1)); - if (tb_switch_tmu_enable(sw)) - tb_sw_dbg(sw, "fail switching TMU mode for 1st depth router\n"); + case TB_SWITCH_TMU_MODE_HIFI_BI: + break; + + case TB_SWITCH_TMU_MODE_MEDRES_ENHANCED_UNI: { + const struct tb_switch *parent_sw = tb_switch_parent(sw); + + if (!parent_sw || !tb_switch_tmu_enhanced_is_supported(parent_sw)) + return -EOPNOTSUPP; + if (!tb_switch_tmu_enhanced_is_supported(sw)) + return -EOPNOTSUPP; + + break; } - return 0; -} + default: + tb_sw_warn(sw, "TMU: unsupported mode %u\n", mode); + return -EINVAL; + } -/** - * tb_switch_enable_tmu_1st_child - Configure and enable TMU for 1st chidren - * @sw: The router to configure and enable it's children TMU - * @rate: Rate of the TMU to configure the router's chidren to - * - * Configures and enables the TMU mode of 1st depth children of the specified - * router to the specified rate. - */ -void tb_switch_enable_tmu_1st_child(struct tb_switch *sw, - enum tb_switch_tmu_rate rate) -{ - device_for_each_child(&sw->dev, &rate, - tb_switch_tmu_config_enable); + if (sw->tmu.mode_request != mode) { + tb_sw_dbg(sw, "TMU: mode change %s -> %s requested\n", + tmu_mode_name(sw->tmu.mode), tmu_mode_name(mode)); + sw->tmu.mode_request = mode; + } + + return 0; } diff --git a/drivers/thunderbolt/tunnel.c b/drivers/thunderbolt/tunnel.c index 4f222673d651d945dff7ea01565d1500b84fa4ed..a6810fb368600f15009aa5a8d4f0249d06160ef8 100644 --- a/drivers/thunderbolt/tunnel.c +++ b/drivers/thunderbolt/tunnel.c @@ -10,6 +10,7 @@ #include #include #include +#include #include "tunnel.h" #include "tb.h" @@ -41,9 +42,14 @@ * Number of credits we try to allocate for each DMA path if not limited * by the host router baMaxHI. */ -#define TB_DMA_CREDITS 14U +#define TB_DMA_CREDITS 14 /* Minimum number of credits for DMA path */ -#define TB_MIN_DMA_CREDITS 1U +#define TB_MIN_DMA_CREDITS 1 + +static unsigned int dma_credits = TB_DMA_CREDITS; +module_param(dma_credits, uint, 0444); +MODULE_PARM_DESC(dma_credits, "specify custom credits for DMA tunnels (default: " + __MODULE_STRING(TB_DMA_CREDITS) ")"); static bool bw_alloc_mode = true; module_param(bw_alloc_mode, bool, 0444); @@ -95,7 +101,7 @@ static unsigned int tb_available_credits(const struct tb_port *port, pcie = tb_acpi_may_tunnel_pcie() ? sw->max_pcie_credits : 0; if (tb_acpi_is_xdomain_allowed()) { - spare = min_not_zero(sw->max_dma_credits, TB_DMA_CREDITS); + spare = min_not_zero(sw->max_dma_credits, dma_credits); /* Add some credits for potential second DMA tunnel */ spare += TB_MIN_DMA_CREDITS; } else { @@ -148,18 +154,49 @@ static struct tb_tunnel *tb_tunnel_alloc(struct tb *tb, size_t npaths, return tunnel; } +static int tb_pci_set_ext_encapsulation(struct tb_tunnel *tunnel, bool enable) +{ + int ret; + + /* Only supported of both routers are at least USB4 v2 */ + if (usb4_switch_version(tunnel->src_port->sw) < 2 || + usb4_switch_version(tunnel->dst_port->sw) < 2) + return 0; + + ret = usb4_pci_port_set_ext_encapsulation(tunnel->src_port, enable); + if (ret) + return ret; + + ret = usb4_pci_port_set_ext_encapsulation(tunnel->dst_port, enable); + if (ret) + return ret; + + tb_tunnel_dbg(tunnel, "extended encapsulation %s\n", + str_enabled_disabled(enable)); + return 0; +} + static int tb_pci_activate(struct tb_tunnel *tunnel, bool activate) { int res; + if (activate) { + res = tb_pci_set_ext_encapsulation(tunnel, activate); + if (res) + return res; + } + res = tb_pci_port_enable(tunnel->src_port, activate); if (res) return res; - if (tb_port_is_pcie_up(tunnel->dst_port)) - return tb_pci_port_enable(tunnel->dst_port, activate); + if (tb_port_is_pcie_up(tunnel->dst_port)) { + res = tb_pci_port_enable(tunnel->dst_port, activate); + if (res) + return res; + } - return 0; + return activate ? 0 : tb_pci_set_ext_encapsulation(tunnel, activate); } static int tb_pci_init_credits(struct tb_path_hop *hop) @@ -381,6 +418,10 @@ static int tb_dp_cm_handshake(struct tb_port *in, struct tb_port *out, return -ETIMEDOUT; } +/* + * Returns maximum possible rate from capability supporting only DP 2.0 + * and below. Used when DP BW allocation mode is not enabled. + */ static inline u32 tb_dp_cap_get_rate(u32 val) { u32 rate = (val & DP_COMMON_CAP_RATE_MASK) >> DP_COMMON_CAP_RATE_SHIFT; @@ -399,6 +440,28 @@ static inline u32 tb_dp_cap_get_rate(u32 val) } } +/* + * Returns maximum possible rate from capability supporting DP 2.1 + * UHBR20, 13.5 and 10 rates as well. Use only when DP BW allocation + * mode is enabled. + */ +static inline u32 tb_dp_cap_get_rate_ext(u32 val) +{ + if (val & DP_COMMON_CAP_UHBR20) + return 20000; + else if (val & DP_COMMON_CAP_UHBR13_5) + return 13500; + else if (val & DP_COMMON_CAP_UHBR10) + return 10000; + + return tb_dp_cap_get_rate(val); +} + +static inline bool tb_dp_is_uhbr_rate(unsigned int rate) +{ + return rate >= 10000; +} + static inline u32 tb_dp_cap_set_rate(u32 val, u32 rate) { val &= ~DP_COMMON_CAP_RATE_MASK; @@ -461,7 +524,9 @@ static inline u32 tb_dp_cap_set_lanes(u32 val, u32 lanes) static unsigned int tb_dp_bandwidth(unsigned int rate, unsigned int lanes) { - /* Tunneling removes the DP 8b/10b encoding */ + /* Tunneling removes the DP 8b/10b 128/132b encoding */ + if (tb_dp_is_uhbr_rate(rate)) + return rate * lanes * 128 / 132; return rate * lanes * 8 / 10; } @@ -604,7 +669,7 @@ static int tb_dp_xchg_caps(struct tb_tunnel *tunnel) in->cap_adap + DP_REMOTE_CAP, 1); } -static int tb_dp_bw_alloc_mode_enable(struct tb_tunnel *tunnel) +static int tb_dp_bandwidth_alloc_mode_enable(struct tb_tunnel *tunnel) { int ret, estimated_bw, granularity, tmp; struct tb_port *out = tunnel->dst_port; @@ -616,7 +681,7 @@ static int tb_dp_bw_alloc_mode_enable(struct tb_tunnel *tunnel) if (!bw_alloc_mode) return 0; - ret = usb4_dp_port_set_cm_bw_mode_supported(in, true); + ret = usb4_dp_port_set_cm_bandwidth_mode_supported(in, true); if (ret) return ret; @@ -654,6 +719,19 @@ static int tb_dp_bw_alloc_mode_enable(struct tb_tunnel *tunnel) if (ret) return ret; + /* + * Pick up granularity that supports maximum possible bandwidth. + * For that we use the UHBR rates too. + */ + in_rate = tb_dp_cap_get_rate_ext(in_dp_cap); + out_rate = tb_dp_cap_get_rate_ext(out_dp_cap); + rate = min(in_rate, out_rate); + tmp = tb_dp_bandwidth(rate, lanes); + + tb_port_dbg(in, + "maximum bandwidth through allocation mode %u Mb/s x%u = %u Mb/s\n", + rate, lanes, tmp); + for (granularity = 250; tmp / granularity > 255 && granularity <= 1000; granularity *= 2) ; @@ -680,12 +758,12 @@ static int tb_dp_bw_alloc_mode_enable(struct tb_tunnel *tunnel) tb_port_dbg(in, "estimated bandwidth %d Mb/s\n", estimated_bw); - ret = usb4_dp_port_set_estimated_bw(in, estimated_bw); + ret = usb4_dp_port_set_estimated_bandwidth(in, estimated_bw); if (ret) return ret; /* Initial allocation should be 0 according the spec */ - ret = usb4_dp_port_allocate_bw(in, 0); + ret = usb4_dp_port_allocate_bandwidth(in, 0); if (ret) return ret; @@ -707,7 +785,7 @@ static int tb_dp_init(struct tb_tunnel *tunnel) if (!tb_switch_is_usb4(sw)) return 0; - if (!usb4_dp_port_bw_mode_supported(in)) + if (!usb4_dp_port_bandwidth_mode_supported(in)) return 0; tb_port_dbg(in, "bandwidth allocation mode supported\n"); @@ -716,17 +794,17 @@ static int tb_dp_init(struct tb_tunnel *tunnel) if (ret) return ret; - return tb_dp_bw_alloc_mode_enable(tunnel); + return tb_dp_bandwidth_alloc_mode_enable(tunnel); } static void tb_dp_deinit(struct tb_tunnel *tunnel) { struct tb_port *in = tunnel->src_port; - if (!usb4_dp_port_bw_mode_supported(in)) + if (!usb4_dp_port_bandwidth_mode_supported(in)) return; - if (usb4_dp_port_bw_mode_enabled(in)) { - usb4_dp_port_set_cm_bw_mode_supported(in, false); + if (usb4_dp_port_bandwidth_mode_enabled(in)) { + usb4_dp_port_set_cm_bandwidth_mode_supported(in, false); tb_port_dbg(in, "bandwidth allocation mode disabled\n"); } } @@ -769,15 +847,42 @@ static int tb_dp_activate(struct tb_tunnel *tunnel, bool active) } /* max_bw is rounded up to next granularity */ -static int tb_dp_nrd_bandwidth(struct tb_tunnel *tunnel, int *max_bw) +static int tb_dp_bandwidth_mode_maximum_bandwidth(struct tb_tunnel *tunnel, + int *max_bw) { struct tb_port *in = tunnel->src_port; int ret, rate, lanes, nrd_bw; + u32 cap; - ret = usb4_dp_port_nrd(in, &rate, &lanes); + /* + * DP IN adapter DP_LOCAL_CAP gets updated to the lowest AUX + * read parameter values so this so we can use this to determine + * the maximum possible bandwidth over this link. + * + * See USB4 v2 spec 1.0 10.4.4.5. + */ + ret = tb_port_read(in, &cap, TB_CFG_PORT, + in->cap_adap + DP_LOCAL_CAP, 1); if (ret) return ret; + rate = tb_dp_cap_get_rate_ext(cap); + if (tb_dp_is_uhbr_rate(rate)) { + /* + * When UHBR is used there is no reduction in lanes so + * we can use this directly. + */ + lanes = tb_dp_cap_get_lanes(cap); + } else { + /* + * If there is no UHBR supported then check the + * non-reduced rate and lanes. + */ + ret = usb4_dp_port_nrd(in, &rate, &lanes); + if (ret) + return ret; + } + nrd_bw = tb_dp_bandwidth(rate, lanes); if (max_bw) { @@ -790,26 +895,27 @@ static int tb_dp_nrd_bandwidth(struct tb_tunnel *tunnel, int *max_bw) return nrd_bw; } -static int tb_dp_bw_mode_consumed_bandwidth(struct tb_tunnel *tunnel, - int *consumed_up, int *consumed_down) +static int tb_dp_bandwidth_mode_consumed_bandwidth(struct tb_tunnel *tunnel, + int *consumed_up, + int *consumed_down) { struct tb_port *out = tunnel->dst_port; struct tb_port *in = tunnel->src_port; int ret, allocated_bw, max_bw; - if (!usb4_dp_port_bw_mode_enabled(in)) + if (!usb4_dp_port_bandwidth_mode_enabled(in)) return -EOPNOTSUPP; if (!tunnel->bw_mode) return -EOPNOTSUPP; /* Read what was allocated previously if any */ - ret = usb4_dp_port_allocated_bw(in); + ret = usb4_dp_port_allocated_bandwidth(in); if (ret < 0) return ret; allocated_bw = ret; - ret = tb_dp_nrd_bandwidth(tunnel, &max_bw); + ret = tb_dp_bandwidth_mode_maximum_bandwidth(tunnel, &max_bw); if (ret < 0) return ret; if (allocated_bw == max_bw) @@ -839,15 +945,15 @@ static int tb_dp_allocated_bandwidth(struct tb_tunnel *tunnel, int *allocated_up * If we have already set the allocated bandwidth then use that. * Otherwise we read it from the DPRX. */ - if (usb4_dp_port_bw_mode_enabled(in) && tunnel->bw_mode) { + if (usb4_dp_port_bandwidth_mode_enabled(in) && tunnel->bw_mode) { int ret, allocated_bw, max_bw; - ret = usb4_dp_port_allocated_bw(in); + ret = usb4_dp_port_allocated_bandwidth(in); if (ret < 0) return ret; allocated_bw = ret; - ret = tb_dp_nrd_bandwidth(tunnel, &max_bw); + ret = tb_dp_bandwidth_mode_maximum_bandwidth(tunnel, &max_bw); if (ret < 0) return ret; if (allocated_bw == max_bw) @@ -874,23 +980,23 @@ static int tb_dp_alloc_bandwidth(struct tb_tunnel *tunnel, int *alloc_up, struct tb_port *in = tunnel->src_port; int max_bw, ret, tmp; - if (!usb4_dp_port_bw_mode_enabled(in)) + if (!usb4_dp_port_bandwidth_mode_enabled(in)) return -EOPNOTSUPP; - ret = tb_dp_nrd_bandwidth(tunnel, &max_bw); + ret = tb_dp_bandwidth_mode_maximum_bandwidth(tunnel, &max_bw); if (ret < 0) return ret; if (in->sw->config.depth < out->sw->config.depth) { tmp = min(*alloc_down, max_bw); - ret = usb4_dp_port_allocate_bw(in, tmp); + ret = usb4_dp_port_allocate_bandwidth(in, tmp); if (ret) return ret; *alloc_down = tmp; *alloc_up = 0; } else { tmp = min(*alloc_up, max_bw); - ret = usb4_dp_port_allocate_bw(in, tmp); + ret = usb4_dp_port_allocate_bandwidth(in, tmp); if (ret) return ret; *alloc_down = 0; @@ -900,6 +1006,9 @@ static int tb_dp_alloc_bandwidth(struct tb_tunnel *tunnel, int *alloc_up, /* Now we can use BW mode registers to figure out the bandwidth */ /* TODO: need to handle discovery too */ tunnel->bw_mode = true; + + tb_port_dbg(in, "allocated bandwidth through allocation mode %d Mb/s\n", + tmp); return 0; } @@ -974,23 +1083,20 @@ static int tb_dp_maximum_bandwidth(struct tb_tunnel *tunnel, int *max_up, int *max_down) { struct tb_port *in = tunnel->src_port; - u32 rate, lanes; int ret; - /* - * DP IN adapter DP_LOCAL_CAP gets updated to the lowest AUX read - * parameter values so this so we can use this to determine the - * maximum possible bandwidth over this link. - */ - ret = tb_dp_read_cap(tunnel, DP_LOCAL_CAP, &rate, &lanes); - if (ret) + if (!usb4_dp_port_bandwidth_mode_enabled(in)) + return -EOPNOTSUPP; + + ret = tb_dp_bandwidth_mode_maximum_bandwidth(tunnel, NULL); + if (ret < 0) return ret; if (in->sw->config.depth < tunnel->dst_port->sw->config.depth) { *max_up = 0; - *max_down = tb_dp_bandwidth(rate, lanes); + *max_down = ret; } else { - *max_up = tb_dp_bandwidth(rate, lanes); + *max_up = ret; *max_down = 0; } @@ -1011,8 +1117,8 @@ static int tb_dp_consumed_bandwidth(struct tb_tunnel *tunnel, int *consumed_up, * mode is enabled first and then read the bandwidth * through those registers. */ - ret = tb_dp_bw_mode_consumed_bandwidth(tunnel, consumed_up, - consumed_down); + ret = tb_dp_bandwidth_mode_consumed_bandwidth(tunnel, consumed_up, + consumed_down); if (ret < 0) { if (ret != -EOPNOTSUPP) return ret; @@ -1132,6 +1238,47 @@ static int tb_dp_init_video_path(struct tb_path *path) return 0; } +static void tb_dp_dump(struct tb_tunnel *tunnel) +{ + struct tb_port *in, *out; + u32 dp_cap, rate, lanes; + + in = tunnel->src_port; + out = tunnel->dst_port; + + if (tb_port_read(in, &dp_cap, TB_CFG_PORT, + in->cap_adap + DP_LOCAL_CAP, 1)) + return; + + rate = tb_dp_cap_get_rate(dp_cap); + lanes = tb_dp_cap_get_lanes(dp_cap); + + tb_port_dbg(in, "maximum supported bandwidth %u Mb/s x%u = %u Mb/s\n", + rate, lanes, tb_dp_bandwidth(rate, lanes)); + + out = tunnel->dst_port; + + if (tb_port_read(out, &dp_cap, TB_CFG_PORT, + out->cap_adap + DP_LOCAL_CAP, 1)) + return; + + rate = tb_dp_cap_get_rate(dp_cap); + lanes = tb_dp_cap_get_lanes(dp_cap); + + tb_port_dbg(out, "maximum supported bandwidth %u Mb/s x%u = %u Mb/s\n", + rate, lanes, tb_dp_bandwidth(rate, lanes)); + + if (tb_port_read(in, &dp_cap, TB_CFG_PORT, + in->cap_adap + DP_REMOTE_CAP, 1)) + return; + + rate = tb_dp_cap_get_rate(dp_cap); + lanes = tb_dp_cap_get_lanes(dp_cap); + + tb_port_dbg(in, "reduced bandwidth %u Mb/s x%u = %u Mb/s\n", + rate, lanes, tb_dp_bandwidth(rate, lanes)); +} + /** * tb_tunnel_discover_dp() - Discover existing Display Port tunnels * @tb: Pointer to the domain structure @@ -1209,6 +1356,8 @@ struct tb_tunnel *tb_tunnel_discover_dp(struct tb *tb, struct tb_port *in, goto err_deactivate; } + tb_dp_dump(tunnel); + tb_tunnel_dbg(tunnel, "discovered\n"); return tunnel; @@ -1452,6 +1601,10 @@ struct tb_tunnel *tb_tunnel_alloc_dma(struct tb *tb, struct tb_port *nhi, struct tb_path *path; int credits; + /* Ring 0 is reserved for control channel */ + if (WARN_ON(!receive_ring || !transmit_ring)) + return NULL; + if (receive_ring > 0) npaths++; if (transmit_ring > 0) @@ -1468,7 +1621,7 @@ struct tb_tunnel *tb_tunnel_alloc_dma(struct tb *tb, struct tb_port *nhi, tunnel->dst_port = dst; tunnel->deinit = tb_dma_deinit; - credits = min_not_zero(TB_DMA_CREDITS, nhi->sw->max_dma_credits); + credits = min_not_zero(dma_credits, nhi->sw->max_dma_credits); if (receive_ring > 0) { path = tb_path_alloc(tb, dst, receive_path, nhi, receive_ring, 0, diff --git a/drivers/thunderbolt/usb4.c b/drivers/thunderbolt/usb4.c index 485b6e43068634ed7b8ac628d508ce57876772bf..05ddb224c4649171a20319fb2de1b6bad822ed17 100644 --- a/drivers/thunderbolt/usb4.c +++ b/drivers/thunderbolt/usb4.c @@ -15,6 +15,7 @@ #include "tb.h" #define USB4_DATA_RETRIES 3 +#define USB4_DATA_DWORDS 16 enum usb4_sb_target { USB4_SB_TARGET_ROUTER, @@ -112,7 +113,7 @@ static int __usb4_switch_op(struct tb_switch *sw, u16 opcode, u32 *metadata, { const struct tb_cm_ops *cm_ops = sw->tb->cm_ops; - if (tx_dwords > NVM_DATA_DWORDS || rx_dwords > NVM_DATA_DWORDS) + if (tx_dwords > USB4_DATA_DWORDS || rx_dwords > USB4_DATA_DWORDS) return -EINVAL; /* @@ -231,11 +232,14 @@ static bool link_is_usb4(struct tb_port *port) * is not available for some reason (like that there is Thunderbolt 3 * switch upstream) then the internal xHCI controller is enabled * instead. + * + * This does not set the configuration valid bit of the router. To do + * that call usb4_switch_configuration_valid(). */ int usb4_switch_setup(struct tb_switch *sw) { - struct tb_port *downstream_port; - struct tb_switch *parent; + struct tb_switch *parent = tb_switch_parent(sw); + struct tb_port *down; bool tbt3, xhci; u32 val = 0; int ret; @@ -249,9 +253,8 @@ int usb4_switch_setup(struct tb_switch *sw) if (ret) return ret; - parent = tb_switch_parent(sw); - downstream_port = tb_port_at(tb_route(sw), parent); - sw->link_usb4 = link_is_usb4(downstream_port); + down = tb_switch_downstream_port(sw); + sw->link_usb4 = link_is_usb4(down); tb_sw_dbg(sw, "link: %s\n", sw->link_usb4 ? "USB4" : "TBT"); xhci = val & ROUTER_CS_6_HCI; @@ -288,7 +291,33 @@ int usb4_switch_setup(struct tb_switch *sw) /* TBT3 supported by the CM */ val |= ROUTER_CS_5_C3S; - /* Tunneling configuration is ready now */ + + return tb_sw_write(sw, &val, TB_CFG_SWITCH, ROUTER_CS_5, 1); +} + +/** + * usb4_switch_configuration_valid() - Set tunneling configuration to be valid + * @sw: USB4 router + * + * Sets configuration valid bit for the router. Must be called before + * any tunnels can be set through the router and after + * usb4_switch_setup() has been called. Can be called to host and device + * routers (does nothing for the latter). + * + * Returns %0 in success and negative errno otherwise. + */ +int usb4_switch_configuration_valid(struct tb_switch *sw) +{ + u32 val; + int ret; + + if (!tb_route(sw)) + return 0; + + ret = tb_sw_read(sw, &val, TB_CFG_SWITCH, ROUTER_CS_5, 1); + if (ret) + return ret; + val |= ROUTER_CS_5_CV; ret = tb_sw_write(sw, &val, TB_CFG_SWITCH, ROUTER_CS_5, 1); @@ -703,7 +732,7 @@ int usb4_switch_credits_init(struct tb_switch *sw) int max_usb3, min_dp_aux, min_dp_main, max_pcie, max_dma; int ret, length, i, nports; const struct tb_port *port; - u32 data[NVM_DATA_DWORDS]; + u32 data[USB4_DATA_DWORDS]; u32 metadata = 0; u8 status = 0; @@ -1199,7 +1228,7 @@ static int usb4_port_wait_for_bit(struct tb_port *port, u32 offset, u32 bit, static int usb4_port_read_data(struct tb_port *port, void *data, size_t dwords) { - if (dwords > NVM_DATA_DWORDS) + if (dwords > USB4_DATA_DWORDS) return -EINVAL; return tb_port_read(port, data, TB_CFG_PORT, port->cap_usb4 + PORT_CS_2, @@ -1209,7 +1238,7 @@ static int usb4_port_read_data(struct tb_port *port, void *data, size_t dwords) static int usb4_port_write_data(struct tb_port *port, const void *data, size_t dwords) { - if (dwords > NVM_DATA_DWORDS) + if (dwords > USB4_DATA_DWORDS) return -EINVAL; return tb_port_write(port, data, TB_CFG_PORT, port->cap_usb4 + PORT_CS_2, @@ -1845,7 +1874,7 @@ static int usb4_port_retimer_nvm_read_block(void *data, unsigned int dwaddress, int ret; metadata = dwaddress << USB4_NVM_READ_OFFSET_SHIFT; - if (dwords < NVM_DATA_DWORDS) + if (dwords < USB4_DATA_DWORDS) metadata |= dwords << USB4_NVM_READ_LENGTH_SHIFT; ret = usb4_port_retimer_write(port, index, USB4_SB_METADATA, &metadata, @@ -2265,13 +2294,14 @@ int usb4_dp_port_set_cm_id(struct tb_port *port, int cm_id) } /** - * usb4_dp_port_bw_mode_supported() - Is the bandwidth allocation mode supported + * usb4_dp_port_bandwidth_mode_supported() - Is the bandwidth allocation mode + * supported * @port: DP IN adapter to check * * Can be called to any DP IN adapter. Returns true if the adapter * supports USB4 bandwidth allocation mode, false otherwise. */ -bool usb4_dp_port_bw_mode_supported(struct tb_port *port) +bool usb4_dp_port_bandwidth_mode_supported(struct tb_port *port) { int ret; u32 val; @@ -2288,13 +2318,14 @@ bool usb4_dp_port_bw_mode_supported(struct tb_port *port) } /** - * usb4_dp_port_bw_mode_enabled() - Is the bandwidth allocation mode enabled + * usb4_dp_port_bandwidth_mode_enabled() - Is the bandwidth allocation mode + * enabled * @port: DP IN adapter to check * * Can be called to any DP IN adapter. Returns true if the bandwidth * allocation mode has been enabled, false otherwise. */ -bool usb4_dp_port_bw_mode_enabled(struct tb_port *port) +bool usb4_dp_port_bandwidth_mode_enabled(struct tb_port *port) { int ret; u32 val; @@ -2311,7 +2342,8 @@ bool usb4_dp_port_bw_mode_enabled(struct tb_port *port) } /** - * usb4_dp_port_set_cm_bw_mode_supported() - Set/clear CM support for bandwidth allocation mode + * usb4_dp_port_set_cm_bandwidth_mode_supported() - Set/clear CM support for + * bandwidth allocation mode * @port: DP IN adapter * @supported: Does the CM support bandwidth allocation mode * @@ -2320,7 +2352,8 @@ bool usb4_dp_port_bw_mode_enabled(struct tb_port *port) * otherwise. Specifically returns %-OPNOTSUPP if the passed in adapter * does not support this. */ -int usb4_dp_port_set_cm_bw_mode_supported(struct tb_port *port, bool supported) +int usb4_dp_port_set_cm_bandwidth_mode_supported(struct tb_port *port, + bool supported) { u32 val; int ret; @@ -2594,7 +2627,7 @@ int usb4_dp_port_set_granularity(struct tb_port *port, int granularity) } /** - * usb4_dp_port_set_estimated_bw() - Set estimated bandwidth + * usb4_dp_port_set_estimated_bandwidth() - Set estimated bandwidth * @port: DP IN adapter * @bw: Estimated bandwidth in Mb/s. * @@ -2604,7 +2637,7 @@ int usb4_dp_port_set_granularity(struct tb_port *port, int granularity) * and negative errno otherwise. Specifically returns %-EOPNOTSUPP if * the adapter does not support this. */ -int usb4_dp_port_set_estimated_bw(struct tb_port *port, int bw) +int usb4_dp_port_set_estimated_bandwidth(struct tb_port *port, int bw) { u32 val, granularity; int ret; @@ -2630,14 +2663,14 @@ int usb4_dp_port_set_estimated_bw(struct tb_port *port, int bw) } /** - * usb4_dp_port_allocated_bw() - Return allocated bandwidth + * usb4_dp_port_allocated_bandwidth() - Return allocated bandwidth * @port: DP IN adapter * * Reads and returns allocated bandwidth for @port in Mb/s (taking into * account the programmed granularity). Returns negative errno in case * of error. */ -int usb4_dp_port_allocated_bw(struct tb_port *port) +int usb4_dp_port_allocated_bandwidth(struct tb_port *port) { u32 val, granularity; int ret; @@ -2723,7 +2756,7 @@ static int usb4_dp_port_wait_and_clear_cm_ack(struct tb_port *port, } /** - * usb4_dp_port_allocate_bw() - Set allocated bandwidth + * usb4_dp_port_allocate_bandwidth() - Set allocated bandwidth * @port: DP IN adapter * @bw: New allocated bandwidth in Mb/s * @@ -2731,7 +2764,7 @@ static int usb4_dp_port_wait_and_clear_cm_ack(struct tb_port *port, * driver). Takes into account the programmed granularity. Returns %0 in * success and negative errno in case of error. */ -int usb4_dp_port_allocate_bw(struct tb_port *port, int bw) +int usb4_dp_port_allocate_bandwidth(struct tb_port *port, int bw) { u32 val, granularity; int ret; @@ -2765,7 +2798,7 @@ int usb4_dp_port_allocate_bw(struct tb_port *port, int bw) } /** - * usb4_dp_port_requested_bw() - Read requested bandwidth + * usb4_dp_port_requested_bandwidth() - Read requested bandwidth * @port: DP IN adapter * * Reads the DPCD (graphics driver) requested bandwidth and returns it @@ -2774,7 +2807,7 @@ int usb4_dp_port_allocate_bw(struct tb_port *port, int bw) * the adapter does not support bandwidth allocation mode, and %ENODATA * if there is no active bandwidth request from the graphics driver. */ -int usb4_dp_port_requested_bw(struct tb_port *port) +int usb4_dp_port_requested_bandwidth(struct tb_port *port) { u32 val, granularity; int ret; @@ -2797,3 +2830,34 @@ int usb4_dp_port_requested_bw(struct tb_port *port) return (val & ADP_DP_CS_8_REQUESTED_BW_MASK) * granularity; } + +/** + * usb4_pci_port_set_ext_encapsulation() - Enable/disable extended encapsulation + * @port: PCIe adapter + * @enable: Enable/disable extended encapsulation + * + * Enables or disables extended encapsulation used in PCIe tunneling. Caller + * needs to make sure both adapters support this before enabling. Returns %0 on + * success and negative errno otherwise. + */ +int usb4_pci_port_set_ext_encapsulation(struct tb_port *port, bool enable) +{ + u32 val; + int ret; + + if (!tb_port_is_pcie_up(port) && !tb_port_is_pcie_down(port)) + return -EINVAL; + + ret = tb_port_read(port, &val, TB_CFG_PORT, + port->cap_adap + ADP_PCIE_CS_1, 1); + if (ret) + return ret; + + if (enable) + val |= ADP_PCIE_CS_1_EE; + else + val &= ~ADP_PCIE_CS_1_EE; + + return tb_port_write(port, &val, TB_CFG_PORT, + port->cap_adap + ADP_PCIE_CS_1, 1); +} diff --git a/drivers/thunderbolt/xdomain.c b/drivers/thunderbolt/xdomain.c index e2b54887d3313e6a7adc6f9dc3e5bbf7a5946056..5b5566862318b99ee6e597c2713285839ca7ddad 100644 --- a/drivers/thunderbolt/xdomain.c +++ b/drivers/thunderbolt/xdomain.c @@ -537,9 +537,8 @@ static int tb_xdp_link_state_status_request(struct tb_ctl *ctl, u64 route, static int tb_xdp_link_state_status_response(struct tb *tb, struct tb_ctl *ctl, struct tb_xdomain *xd, u8 sequence) { - struct tb_switch *sw = tb_to_switch(xd->dev.parent); struct tb_xdp_link_state_status_response res; - struct tb_port *port = tb_port_at(xd->route, sw); + struct tb_port *port = tb_xdomain_downstream_port(xd); u32 val[2]; int ret; @@ -1137,7 +1136,7 @@ static int tb_xdomain_update_link_attributes(struct tb_xdomain *xd) struct tb_port *port; int ret; - port = tb_port_at(xd->route, tb_xdomain_parent(xd)); + port = tb_xdomain_downstream_port(xd); ret = tb_port_get_link_speed(port); if (ret < 0) @@ -1251,8 +1250,7 @@ static int tb_xdomain_get_link_status(struct tb_xdomain *xd) static int tb_xdomain_link_state_change(struct tb_xdomain *xd, unsigned int width) { - struct tb_switch *sw = tb_to_switch(xd->dev.parent); - struct tb_port *port = tb_port_at(xd->route, sw); + struct tb_port *port = tb_xdomain_downstream_port(xd); struct tb *tb = xd->tb; u8 tlw, tls; u32 val; @@ -1292,13 +1290,16 @@ static int tb_xdomain_link_state_change(struct tb_xdomain *xd, static int tb_xdomain_bond_lanes_uuid_high(struct tb_xdomain *xd) { + unsigned int width, width_mask; struct tb_port *port; - int ret, width; + int ret; if (xd->target_link_width == LANE_ADP_CS_1_TARGET_WIDTH_SINGLE) { - width = 1; + width = TB_LINK_WIDTH_SINGLE; + width_mask = width; } else if (xd->target_link_width == LANE_ADP_CS_1_TARGET_WIDTH_DUAL) { - width = 2; + width = TB_LINK_WIDTH_DUAL; + width_mask = width | TB_LINK_WIDTH_ASYM_TX | TB_LINK_WIDTH_ASYM_RX; } else { if (xd->state_retries-- > 0) { dev_dbg(&xd->dev, @@ -1309,7 +1310,7 @@ static int tb_xdomain_bond_lanes_uuid_high(struct tb_xdomain *xd) return -ETIMEDOUT; } - port = tb_port_at(xd->route, tb_xdomain_parent(xd)); + port = tb_xdomain_downstream_port(xd); /* * We can't use tb_xdomain_lane_bonding_enable() here because it @@ -1330,15 +1331,16 @@ static int tb_xdomain_bond_lanes_uuid_high(struct tb_xdomain *xd) return ret; } - ret = tb_port_wait_for_link_width(port, width, XDOMAIN_BONDING_TIMEOUT); + ret = tb_port_wait_for_link_width(port, width_mask, + XDOMAIN_BONDING_TIMEOUT); if (ret) { dev_warn(&xd->dev, "error waiting for link width to become %d\n", - width); + width_mask); return ret; } - port->bonded = width == 2; - port->dual_link_port->bonded = width == 2; + port->bonded = width > TB_LINK_WIDTH_SINGLE; + port->dual_link_port->bonded = width > TB_LINK_WIDTH_SINGLE; tb_port_update_credits(port); tb_xdomain_update_link_attributes(xd); @@ -1425,7 +1427,7 @@ static int tb_xdomain_get_properties(struct tb_xdomain *xd) if (xd->bonding_possible) { struct tb_port *port; - port = tb_port_at(xd->route, tb_xdomain_parent(xd)); + port = tb_xdomain_downstream_port(xd); if (!port->bonded) tb_port_disable(port->dual_link_port); } @@ -1737,16 +1739,57 @@ static ssize_t speed_show(struct device *dev, struct device_attribute *attr, static DEVICE_ATTR(rx_speed, 0444, speed_show, NULL); static DEVICE_ATTR(tx_speed, 0444, speed_show, NULL); -static ssize_t lanes_show(struct device *dev, struct device_attribute *attr, - char *buf) +static ssize_t rx_lanes_show(struct device *dev, struct device_attribute *attr, + char *buf) { struct tb_xdomain *xd = container_of(dev, struct tb_xdomain, dev); + unsigned int width; - return sysfs_emit(buf, "%u\n", xd->link_width); + switch (xd->link_width) { + case TB_LINK_WIDTH_SINGLE: + case TB_LINK_WIDTH_ASYM_RX: + width = 1; + break; + case TB_LINK_WIDTH_DUAL: + width = 2; + break; + case TB_LINK_WIDTH_ASYM_TX: + width = 3; + break; + default: + WARN_ON_ONCE(1); + return -EINVAL; + } + + return sysfs_emit(buf, "%u\n", width); } +static DEVICE_ATTR(rx_lanes, 0444, rx_lanes_show, NULL); + +static ssize_t tx_lanes_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct tb_xdomain *xd = container_of(dev, struct tb_xdomain, dev); + unsigned int width; -static DEVICE_ATTR(rx_lanes, 0444, lanes_show, NULL); -static DEVICE_ATTR(tx_lanes, 0444, lanes_show, NULL); + switch (xd->link_width) { + case TB_LINK_WIDTH_SINGLE: + case TB_LINK_WIDTH_ASYM_TX: + width = 1; + break; + case TB_LINK_WIDTH_DUAL: + width = 2; + break; + case TB_LINK_WIDTH_ASYM_RX: + width = 3; + break; + default: + WARN_ON_ONCE(1); + return -EINVAL; + } + + return sysfs_emit(buf, "%u\n", width); +} +static DEVICE_ATTR(tx_lanes, 0444, tx_lanes_show, NULL); static struct attribute *xdomain_attrs[] = { &dev_attr_device.attr, @@ -1976,10 +2019,11 @@ void tb_xdomain_remove(struct tb_xdomain *xd) */ int tb_xdomain_lane_bonding_enable(struct tb_xdomain *xd) { + unsigned int width_mask; struct tb_port *port; int ret; - port = tb_port_at(xd->route, tb_xdomain_parent(xd)); + port = tb_xdomain_downstream_port(xd); if (!port->dual_link_port) return -ENODEV; @@ -1999,7 +2043,12 @@ int tb_xdomain_lane_bonding_enable(struct tb_xdomain *xd) return ret; } - ret = tb_port_wait_for_link_width(port, 2, XDOMAIN_BONDING_TIMEOUT); + /* Any of the widths are all bonded */ + width_mask = TB_LINK_WIDTH_DUAL | TB_LINK_WIDTH_ASYM_TX | + TB_LINK_WIDTH_ASYM_RX; + + ret = tb_port_wait_for_link_width(port, width_mask, + XDOMAIN_BONDING_TIMEOUT); if (ret) { tb_port_warn(port, "failed to enable lane bonding\n"); return ret; @@ -2024,10 +2073,13 @@ void tb_xdomain_lane_bonding_disable(struct tb_xdomain *xd) { struct tb_port *port; - port = tb_port_at(xd->route, tb_xdomain_parent(xd)); + port = tb_xdomain_downstream_port(xd); if (port->dual_link_port) { + int ret; + tb_port_lane_bonding_disable(port); - if (tb_port_wait_for_link_width(port, 1, 100) == -ETIMEDOUT) + ret = tb_port_wait_for_link_width(port, TB_LINK_WIDTH_SINGLE, 100); + if (ret == -ETIMEDOUT) tb_port_warn(port, "timeout disabling lane bonding\n"); tb_port_disable(port->dual_link_port); tb_port_update_credits(port); diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 1c9e5d2ea7de6946b52538f924f938fca6216385..552e8a741562572192270c69857c4cadc266ec96 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -203,8 +203,8 @@ static void n_tty_kick_worker(struct tty_struct *tty) struct n_tty_data *ldata = tty->disc_data; /* Did the input worker stop? Restart it */ - if (unlikely(ldata->no_room)) { - ldata->no_room = 0; + if (unlikely(READ_ONCE(ldata->no_room))) { + WRITE_ONCE(ldata->no_room, 0); WARN_RATELIMIT(tty->port->itty == NULL, "scheduling with invalid itty\n"); @@ -1697,7 +1697,7 @@ n_tty_receive_buf_common(struct tty_struct *tty, const unsigned char *cp, if (overflow && room < 0) ldata->read_head--; room = overflow; - ldata->no_room = flow && !room; + WRITE_ONCE(ldata->no_room, flow && !room); } else overflow = 0; @@ -1728,6 +1728,17 @@ n_tty_receive_buf_common(struct tty_struct *tty, const unsigned char *cp, } else n_tty_check_throttle(tty); + if (unlikely(ldata->no_room)) { + /* + * Barrier here is to ensure to read the latest read_tail in + * chars_in_buffer() and to make sure that read_tail is not loaded + * before ldata->no_room is set. + */ + smp_mb(); + if (!chars_in_buffer(tty)) + n_tty_kick_worker(tty); + } + up_read(&tty->termios_rwsem); return rcvd; @@ -2281,8 +2292,14 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file, if (time) timeout = time; } - if (old_tail != ldata->read_tail) + if (old_tail != ldata->read_tail) { + /* + * Make sure no_room is not read in n_tty_kick_worker() + * before setting ldata->read_tail in copy_from_read_buf(). + */ + smp_mb(); n_tty_kick_worker(tty); + } up_read(&tty->termios_rwsem); remove_wait_queue(&tty->read_wait, &wait); diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h index 1e8fe44a7099f454466e5714e5623f7ee1791507..1aa3e55c8b47da2cdb93ef2e846a88d239a35369 100644 --- a/drivers/tty/serial/8250/8250.h +++ b/drivers/tty/serial/8250/8250.h @@ -91,7 +91,6 @@ struct serial8250_config { #define UART_BUG_TXEN BIT(1) /* UART has buggy TX IIR status */ #define UART_BUG_NOMSR BIT(2) /* UART has buggy MSR status bits (Au1x00) */ #define UART_BUG_THRE BIT(3) /* UART has buggy THRE reassertion */ -#define UART_BUG_PARITY BIT(4) /* UART mishandles parity if FIFO enabled */ #define UART_BUG_TXRACE BIT(5) /* UART Tx fails to set remote DR */ @@ -167,18 +166,21 @@ static unsigned int __maybe_unused serial_icr_read(struct uart_8250_port *up, void serial8250_clear_and_reinit_fifos(struct uart_8250_port *p); -static inline int serial_dl_read(struct uart_8250_port *up) +static inline u32 serial_dl_read(struct uart_8250_port *up) { return up->dl_read(up); } -static inline void serial_dl_write(struct uart_8250_port *up, int value) +static inline void serial_dl_write(struct uart_8250_port *up, u32 value) { up->dl_write(up, value); } static inline bool serial8250_set_THRI(struct uart_8250_port *up) { + /* Port locked to synchronize UART_IER access against the console. */ + lockdep_assert_held_once(&up->port.lock); + if (up->ier & UART_IER_THRI) return false; up->ier |= UART_IER_THRI; @@ -188,6 +190,9 @@ static inline bool serial8250_set_THRI(struct uart_8250_port *up) static inline bool serial8250_clear_THRI(struct uart_8250_port *up) { + /* Port locked to synchronize UART_IER access against the console. */ + lockdep_assert_held_once(&up->port.lock); + if (!(up->ier & UART_IER_THRI)) return false; up->ier &= ~UART_IER_THRI; diff --git a/drivers/tty/serial/8250/8250_aspeed_vuart.c b/drivers/tty/serial/8250/8250_aspeed_vuart.c index 9d2a7856784f73d5f9e88d3bce2d99c5e6162224..4a9e71b2dbbc10a1ccf04856f67e1ea71e399e09 100644 --- a/drivers/tty/serial/8250/8250_aspeed_vuart.c +++ b/drivers/tty/serial/8250/8250_aspeed_vuart.c @@ -275,6 +275,9 @@ static void __aspeed_vuart_set_throttle(struct uart_8250_port *up, { unsigned char irqs = UART_IER_RLSI | UART_IER_RDI; + /* Port locked to synchronize UART_IER access against the console. */ + lockdep_assert_held_once(&up->port.lock); + up->ier &= ~irqs; if (!throttle) up->ier |= irqs; diff --git a/drivers/tty/serial/8250/8250_bcm7271.c b/drivers/tty/serial/8250/8250_bcm7271.c index af0e1c07018795d406bab65eea73181f79920c57..d4b05d7ad9e8de8f9ee3ffe2c3a96ff3db5bd542 100644 --- a/drivers/tty/serial/8250/8250_bcm7271.c +++ b/drivers/tty/serial/8250/8250_bcm7271.c @@ -605,9 +605,13 @@ static int brcmuart_startup(struct uart_port *port) /* * Disable the Receive Data Interrupt because the DMA engine * will handle this. + * + * Synchronize UART_IER access against the console. */ + spin_lock_irq(&port->lock); up->ier &= ~UART_IER_RDI; serial_port_out(port, UART_IER, up->ier); + spin_unlock_irq(&port->lock); priv->tx_running = false; priv->dma.rx_dma = NULL; diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c index 13bf535eedcd5d820747e02c22c55b5cce280a92..914e0e6251bfca59d2c060dc804a7b87d8f889ba 100644 --- a/drivers/tty/serial/8250/8250_core.c +++ b/drivers/tty/serial/8250/8250_core.c @@ -488,6 +488,34 @@ static inline void serial8250_apply_quirks(struct uart_8250_port *up) up->port.quirks |= skip_txen_test ? UPQ_NO_TXEN_TEST : 0; } +static struct uart_8250_port *serial8250_setup_port(int index) +{ + struct uart_8250_port *up; + + if (index >= UART_NR) + return NULL; + + up = &serial8250_ports[index]; + up->port.line = index; + + serial8250_init_port(up); + if (!base_ops) + base_ops = up->port.ops; + up->port.ops = &univ8250_port_ops; + + timer_setup(&up->timer, serial8250_timeout, 0); + + up->ops = &univ8250_driver_ops; + + if (IS_ENABLED(CONFIG_ALPHA_JENSEN) || + (IS_ENABLED(CONFIG_ALPHA_GENERIC) && alpha_jensen())) + up->port.set_mctrl = alpha_jensen_set_mctrl; + + serial8250_set_defaults(up); + + return up; +} + static void __init serial8250_isa_init_ports(void) { struct uart_8250_port *up; @@ -501,26 +529,13 @@ static void __init serial8250_isa_init_ports(void) if (nr_uarts > UART_NR) nr_uarts = UART_NR; - for (i = 0; i < nr_uarts; i++) { - struct uart_8250_port *up = &serial8250_ports[i]; - struct uart_port *port = &up->port; - - port->line = i; - serial8250_init_port(up); - if (!base_ops) - base_ops = port->ops; - port->ops = &univ8250_port_ops; - - timer_setup(&up->timer, serial8250_timeout, 0); - - up->ops = &univ8250_driver_ops; - - if (IS_ENABLED(CONFIG_ALPHA_JENSEN) || - (IS_ENABLED(CONFIG_ALPHA_GENERIC) && alpha_jensen())) - port->set_mctrl = alpha_jensen_set_mctrl; - - serial8250_set_defaults(up); - } + /* + * Set up initial isa ports based on nr_uart module param, or else + * default to CONFIG_SERIAL_8250_RUNTIME_UARTS. Note that we do not + * need to increase nr_uarts when setting up the initial isa ports. + */ + for (i = 0; i < nr_uarts; i++) + serial8250_setup_port(i); /* chain base port ops to support Remote Supervisor Adapter */ univ8250_port_ops = *base_ops; @@ -586,16 +601,29 @@ static void univ8250_console_write(struct console *co, const char *s, static int univ8250_console_setup(struct console *co, char *options) { + struct uart_8250_port *up; struct uart_port *port; - int retval; + int retval, i; /* * Check whether an invalid uart number has been specified, and * if so, search for the first available port that does have * console support. */ - if (co->index >= nr_uarts) + if (co->index >= UART_NR) co->index = 0; + + /* + * If the console is past the initial isa ports, init more ports up to + * co->index as needed and increment nr_uarts accordingly. + */ + for (i = nr_uarts; i <= co->index; i++) { + up = serial8250_setup_port(i); + if (!up) + return -ENODEV; + nr_uarts++; + } + port = &serial8250_ports[co->index].port; /* link port to console */ port->cons = co; @@ -822,12 +850,16 @@ static int serial8250_probe(struct platform_device *dev) uart.port.iotype = p->iotype; uart.port.flags = p->flags; uart.port.mapbase = p->mapbase; + uart.port.mapsize = p->mapsize; uart.port.hub6 = p->hub6; uart.port.has_sysrq = p->has_sysrq; uart.port.private_data = p->private_data; uart.port.type = p->type; + uart.bugs = p->bugs; uart.port.serial_in = p->serial_in; uart.port.serial_out = p->serial_out; + uart.dl_read = p->dl_read; + uart.dl_write = p->dl_write; uart.port.handle_irq = p->handle_irq; uart.port.handle_break = p->handle_break; uart.port.set_termios = p->set_termios; @@ -990,12 +1022,24 @@ int serial8250_register_8250_port(const struct uart_8250_port *up) mutex_lock(&serial_mutex); uart = serial8250_find_match_or_unused(&up->port); - if (uart && uart->port.type != PORT_8250_CIR) { + if (!uart) { + /* + * If the port is past the initial isa ports, initialize a new + * port and increment nr_uarts accordingly. + */ + uart = serial8250_setup_port(nr_uarts); + if (!uart) + goto unlock; + nr_uarts++; + } + + if (uart->port.type != PORT_8250_CIR) { struct mctrl_gpios *gpios; if (uart->port.dev) uart_remove_one_port(&serial8250_reg, &uart->port); + uart->port.ctrl_id = up->port.ctrl_id; uart->port.iobase = up->port.iobase; uart->port.membase = up->port.membase; uart->port.irq = up->port.irq; @@ -1120,6 +1164,7 @@ int serial8250_register_8250_port(const struct uart_8250_port *up) } } +unlock: mutex_unlock(&serial_mutex); return ret; diff --git a/drivers/tty/serial/8250/8250_early.c b/drivers/tty/serial/8250/8250_early.c index 0ebde0ab81675f6e58c911acca90d3d5fcb104ea..4299a8bd83d908244af6c9b1c0db60def49cadd8 100644 --- a/drivers/tty/serial/8250/8250_early.c +++ b/drivers/tty/serial/8250/8250_early.c @@ -36,7 +36,6 @@ static unsigned int serial8250_early_in(struct uart_port *port, int offset) { - int reg_offset = offset; offset <<= port->regshift; switch (port->iotype) { @@ -50,8 +49,6 @@ static unsigned int serial8250_early_in(struct uart_port *port, int offset) return ioread32be(port->membase + offset); case UPIO_PORT: return inb(port->iobase + offset); - case UPIO_AU: - return port->serial_in(port, reg_offset); default: return 0; } @@ -59,7 +56,6 @@ static unsigned int serial8250_early_in(struct uart_port *port, int offset) static void serial8250_early_out(struct uart_port *port, int offset, int value) { - int reg_offset = offset; offset <<= port->regshift; switch (port->iotype) { @@ -78,9 +74,6 @@ static void serial8250_early_out(struct uart_port *port, int offset, int value) case UPIO_PORT: outb(value, port->iobase + offset); break; - case UPIO_AU: - port->serial_out(port, reg_offset, value); - break; } } @@ -199,17 +192,3 @@ OF_EARLYCON_DECLARE(omap8250, "ti,omap3-uart", early_omap8250_setup); OF_EARLYCON_DECLARE(omap8250, "ti,omap4-uart", early_omap8250_setup); #endif - -#ifdef CONFIG_SERIAL_8250_RT288X - -static int __init early_au_setup(struct earlycon_device *dev, const char *opt) -{ - dev->port.serial_in = au_serial_in; - dev->port.serial_out = au_serial_out; - dev->port.iotype = UPIO_AU; - dev->con->write = early_serial8250_write; - return 0; -} -OF_EARLYCON_DECLARE(palmchip, "ralink,rt2880-uart", early_au_setup); - -#endif diff --git a/drivers/tty/serial/8250/8250_em.c b/drivers/tty/serial/8250/8250_em.c index 25a9ecf26be697bada576f4f1d14c5767609e202..ef5019e944eaa82cbaf85b98ef7a6de3f0d5c4c3 100644 --- a/drivers/tty/serial/8250/8250_em.c +++ b/drivers/tty/serial/8250/8250_em.c @@ -139,12 +139,12 @@ static void serial8250_em_serial_out(struct uart_port *p, int offset, int value) } } -static int serial8250_em_serial_dl_read(struct uart_8250_port *up) +static u32 serial8250_em_serial_dl_read(struct uart_8250_port *up) { return serial_in(up, UART_DLL_EM) | serial_in(up, UART_DLM_EM) << 8; } -static void serial8250_em_serial_dl_write(struct uart_8250_port *up, int value) +static void serial8250_em_serial_dl_write(struct uart_8250_port *up, u32 value) { serial_out(up, UART_DLL_EM, value & 0xff); serial_out(up, UART_DLM_EM, value >> 8 & 0xff); diff --git a/drivers/tty/serial/8250/8250_exar.c b/drivers/tty/serial/8250/8250_exar.c index b406cba10b0eb4b6bb97aacb18d938000efb1903..077c3ba3539e6887dfe67d0ed95a864cc341bdc0 100644 --- a/drivers/tty/serial/8250/8250_exar.c +++ b/drivers/tty/serial/8250/8250_exar.c @@ -198,8 +198,12 @@ static int xr17v35x_startup(struct uart_port *port) /* * Make sure all interrups are masked until initialization is * complete and the FIFOs are cleared + * + * Synchronize UART_IER access against the console. */ + spin_lock_irq(&port->lock); serial_port_out(port, UART_IER, 0); + spin_unlock_irq(&port->lock); return serial8250_do_startup(port); } diff --git a/drivers/tty/serial/8250/8250_fsl.c b/drivers/tty/serial/8250/8250_fsl.c index 8adfaa183f778d4a6f8cf21098025b2dac886691..6af4e1c1210a00cbf479cce97ee9240671fa52aa 100644 --- a/drivers/tty/serial/8250/8250_fsl.c +++ b/drivers/tty/serial/8250/8250_fsl.c @@ -38,7 +38,19 @@ int fsl8250_handle_irq(struct uart_port *port) return 0; } - /* This is the WAR; if last event was BRK, then read and return */ + /* + * For a single break the hardware reports LSR.BI for each character + * time. This is described in the MPC8313E chip errata as "General17". + * A typical break has a duration of 0.3s, with a 115200n8 configuration + * that (theoretically) corresponds to ~3500 interrupts in these 0.3s. + * In practise it's less (around 500) because of hardware + * and software latencies. The workaround recommended by the vendor is + * to read the RX register (to clear LSR.DR and thus prevent a FIFO + * aging interrupt). To prevent the irq from retriggering LSR must not be + * read. (This would clear LSR.BI, hardware would reassert the BI event + * immediately and interrupt the CPU again. The hardware clears LSR.BI + * when the next valid char is read.) + */ if (unlikely(up->lsr_saved_flags & UART_LSR_BI)) { up->lsr_saved_flags &= ~UART_LSR_BI; port->serial_in(port, UART_RX); @@ -172,3 +184,6 @@ static struct platform_driver fsl8250_platform_driver = { module_platform_driver(fsl8250_platform_driver); #endif + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Handling of Freescale specific 8250 variants"); diff --git a/drivers/tty/serial/8250/8250_mtk.c b/drivers/tty/serial/8250/8250_mtk.c index fb1d5ec0940e65a3ff3b58d4c2283bc7bae72eed..74da5676ce67dcdc19514580fa06ac70df30fd2f 100644 --- a/drivers/tty/serial/8250/8250_mtk.c +++ b/drivers/tty/serial/8250/8250_mtk.c @@ -222,11 +222,17 @@ static void mtk8250_shutdown(struct uart_port *port) static void mtk8250_disable_intrs(struct uart_8250_port *up, int mask) { + /* Port locked to synchronize UART_IER access against the console. */ + lockdep_assert_held_once(&up->port.lock); + serial_out(up, UART_IER, serial_in(up, UART_IER) & (~mask)); } static void mtk8250_enable_intrs(struct uart_8250_port *up, int mask) { + /* Port locked to synchronize UART_IER access against the console. */ + lockdep_assert_held_once(&up->port.lock); + serial_out(up, UART_IER, serial_in(up, UART_IER) | mask); } @@ -235,6 +241,9 @@ static void mtk8250_set_flow_ctrl(struct uart_8250_port *up, int mode) struct uart_port *port = &up->port; int lcr = serial_in(up, UART_LCR); + /* Port locked to synchronize UART_IER access against the console. */ + lockdep_assert_held_once(&port->lock); + serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); serial_out(up, MTK_UART_EFR, UART_EFR_ECB); serial_out(up, UART_LCR, lcr); @@ -422,12 +431,7 @@ static int __maybe_unused mtk8250_runtime_suspend(struct device *dev) while (serial_in(up, MTK_UART_DEBUG0)); - if (data->clk_count == 0U) { - dev_dbg(dev, "%s clock count is 0\n", __func__); - } else { - clk_disable_unprepare(data->bus_clk); - data->clk_count--; - } + clk_disable_unprepare(data->bus_clk); return 0; } @@ -435,19 +439,8 @@ static int __maybe_unused mtk8250_runtime_suspend(struct device *dev) static int __maybe_unused mtk8250_runtime_resume(struct device *dev) { struct mtk8250_data *data = dev_get_drvdata(dev); - int err; - if (data->clk_count > 0U) { - dev_dbg(dev, "%s clock count is %d\n", __func__, - data->clk_count); - } else { - err = clk_prepare_enable(data->bus_clk); - if (err) { - dev_warn(dev, "Can't enable bus clock\n"); - return err; - } - data->clk_count++; - } + clk_prepare_enable(data->bus_clk); return 0; } @@ -456,14 +449,12 @@ static void mtk8250_do_pm(struct uart_port *port, unsigned int state, unsigned int old) { if (!state) - if (!mtk8250_runtime_resume(port->dev)) - pm_runtime_get_sync(port->dev); + pm_runtime_get_sync(port->dev); serial8250_do_pm(port, state, old); if (state) - if (!pm_runtime_put_sync_suspend(port->dev)) - mtk8250_runtime_suspend(port->dev); + pm_runtime_put_sync_suspend(port->dev); } #ifdef CONFIG_SERIAL_8250_DMA @@ -495,7 +486,7 @@ static int mtk8250_probe_of(struct platform_device *pdev, struct uart_port *p, return 0; } - data->bus_clk = devm_clk_get(&pdev->dev, "bus"); + data->bus_clk = devm_clk_get_enabled(&pdev->dev, "bus"); if (IS_ERR(data->bus_clk)) return PTR_ERR(data->bus_clk); @@ -578,25 +569,16 @@ static int mtk8250_probe(struct platform_device *pdev) platform_set_drvdata(pdev, data); - pm_runtime_enable(&pdev->dev); - err = mtk8250_runtime_resume(&pdev->dev); - if (err) - goto err_pm_disable; - data->line = serial8250_register_8250_port(&uart); - if (data->line < 0) { - err = data->line; - goto err_pm_disable; - } + if (data->line < 0) + return data->line; data->rx_wakeup_irq = platform_get_irq_optional(pdev, 1); - return 0; - -err_pm_disable: - pm_runtime_disable(&pdev->dev); + pm_runtime_set_active(&pdev->dev); + pm_runtime_enable(&pdev->dev); - return err; + return 0; } static int mtk8250_remove(struct platform_device *pdev) @@ -610,9 +592,6 @@ static int mtk8250_remove(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); pm_runtime_put_noidle(&pdev->dev); - if (!pm_runtime_status_suspended(&pdev->dev)) - mtk8250_runtime_suspend(&pdev->dev); - return 0; } diff --git a/drivers/tty/serial/8250/8250_of.c b/drivers/tty/serial/8250/8250_of.c index 1b461fba15a3b19d8b8a5ebe3097f5d1cb455dd1..51329625c48ab095db1b34f046480e6954e230f2 100644 --- a/drivers/tty/serial/8250/8250_of.c +++ b/drivers/tty/serial/8250/8250_of.c @@ -171,11 +171,13 @@ static int of_platform_serial_setup(struct platform_device *ofdev, switch (type) { case PORT_RT2880: - port->iotype = UPIO_AU; + ret = rt288x_setup(port); + if (ret) + goto err_unprepare; break; } - if (IS_ENABLED(CONFIG_SERIAL_8250_FSL) && + if (IS_REACHABLE(CONFIG_SERIAL_8250_FSL) && (of_device_is_compatible(np, "fsl,ns16550") || of_device_is_compatible(np, "fsl,16550-FIFO64"))) { port->handle_irq = fsl8250_handle_irq; diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c index 734f092ef839abaadd3e0ff8763d25f348252fb2..d48a82f1634e9adf565e9d4323688d545cf57f6a 100644 --- a/drivers/tty/serial/8250/8250_omap.c +++ b/drivers/tty/serial/8250/8250_omap.c @@ -32,6 +32,7 @@ #include "8250.h" #define DEFAULT_CLK_SPEED 48000000 +#define OMAP_UART_REGSHIFT 2 #define UART_ERRATA_i202_MDR1_ACCESS (1 << 0) #define OMAP_UART_WER_HAS_TX_WAKEUP (1 << 1) @@ -115,6 +116,7 @@ #define UART_OMAP_RX_LVL 0x19 struct omap8250_priv { + void __iomem *membase; int line; u8 habit; u8 mdr1; @@ -159,9 +161,9 @@ static void omap_8250_rx_dma_flush(struct uart_8250_port *p); static inline void omap_8250_rx_dma_flush(struct uart_8250_port *p) { } #endif -static u32 uart_read(struct uart_8250_port *up, u32 reg) +static u32 uart_read(struct omap8250_priv *priv, u32 reg) { - return readl(up->port.membase + (reg << up->port.regshift)); + return readl(priv->membase + (reg << OMAP_UART_REGSHIFT)); } /* @@ -302,6 +304,9 @@ static void omap8250_restore_regs(struct uart_8250_port *up) struct uart_8250_dma *dma = up->dma; u8 mcr = serial8250_in_MCR(up); + /* Port locked to synchronize UART_IER access against the console. */ + lockdep_assert_held_once(&up->port.lock); + if (dma && dma->tx_running) { /* * TCSANOW requests the change to occur immediately however if @@ -523,6 +528,10 @@ static void omap_8250_pm(struct uart_port *port, unsigned int state, u8 efr; pm_runtime_get_sync(port->dev); + + /* Synchronize UART_IER access against the console. */ + spin_lock_irq(&port->lock); + serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); efr = serial_in(up, UART_EFR); serial_out(up, UART_EFR, efr | UART_EFR_ECB); @@ -533,6 +542,8 @@ static void omap_8250_pm(struct uart_port *port, unsigned int state, serial_out(up, UART_EFR, efr); serial_out(up, UART_LCR, 0); + spin_unlock_irq(&port->lock); + pm_runtime_mark_last_busy(port->dev); pm_runtime_put_autosuspend(port->dev); } @@ -548,7 +559,7 @@ static void omap_serial_fill_features_erratas(struct uart_8250_port *up, u32 mvr, scheme; u16 revision, major, minor; - mvr = uart_read(up, UART_OMAP_MVER); + mvr = uart_read(priv, UART_OMAP_MVER); /* Check revision register scheme */ scheme = mvr >> OMAP_UART_MVR_SCHEME_SHIFT; @@ -616,9 +627,9 @@ static int omap_8250_dma_handle_irq(struct uart_port *port); static irqreturn_t omap8250_irq(int irq, void *dev_id) { - struct uart_port *port = dev_id; - struct omap8250_priv *priv = port->private_data; - struct uart_8250_port *up = up_to_u8250p(port); + struct omap8250_priv *priv = dev_id; + struct uart_8250_port *up = serial8250_get_port(priv->line); + struct uart_port *port = &up->port; unsigned int iir, lsr; int ret; @@ -649,6 +660,8 @@ static irqreturn_t omap8250_irq(int irq, void *dev_id) if ((lsr & UART_LSR_OE) && up->overrun_backoff_time_ms > 0) { unsigned long delay; + /* Synchronize UART_IER access against the console. */ + spin_lock(&port->lock); up->ier = port->serial_in(port, UART_IER); if (up->ier & (UART_IER_RLSI | UART_IER_RDI)) { port->ops->stop_rx(port); @@ -658,6 +671,7 @@ static irqreturn_t omap8250_irq(int irq, void *dev_id) */ cancel_delayed_work(&up->overrun_backoff); } + spin_unlock(&port->lock); delay = msecs_to_jiffies(up->overrun_backoff_time_ms); schedule_delayed_work(&up->overrun_backoff, delay); @@ -672,6 +686,7 @@ static int omap_8250_startup(struct uart_port *port) { struct uart_8250_port *up = up_to_u8250p(port); struct omap8250_priv *priv = port->private_data; + struct uart_8250_dma *dma = &priv->omap8250_dma; int ret; if (priv->wakeirq) { @@ -690,25 +705,23 @@ static int omap_8250_startup(struct uart_port *port) up->msr_saved_flags = 0; /* Disable DMA for console UART */ - if (uart_console(port)) - up->dma = NULL; - - if (up->dma) { + if (dma->fn && !uart_console(port)) { + up->dma = &priv->omap8250_dma; ret = serial8250_request_dma(up); if (ret) { dev_warn_ratelimited(port->dev, "failed to request DMA\n"); up->dma = NULL; } + } else { + up->dma = NULL; } - ret = request_irq(port->irq, omap8250_irq, IRQF_SHARED, - dev_name(port->dev), port); - if (ret < 0) - goto err; - + /* Synchronize UART_IER access against the console. */ + spin_lock_irq(&port->lock); up->ier = UART_IER_RLSI | UART_IER_RDI; serial_out(up, UART_IER, up->ier); + spin_unlock_irq(&port->lock); #ifdef CONFIG_PM up->capabilities |= UART_CAP_RPM; @@ -720,17 +733,17 @@ static int omap_8250_startup(struct uart_port *port) priv->wer |= OMAP_UART_TX_WAKEUP_EN; serial_out(up, UART_OMAP_WER, priv->wer); - if (up->dma && !(priv->habit & UART_HAS_EFR2)) + if (up->dma && !(priv->habit & UART_HAS_EFR2)) { + spin_lock_irq(&port->lock); up->dma->rx_dma(up); + spin_unlock_irq(&port->lock); + } + + enable_irq(up->port.irq); pm_runtime_mark_last_busy(port->dev); pm_runtime_put_autosuspend(port->dev); return 0; -err: - pm_runtime_mark_last_busy(port->dev); - pm_runtime_put_autosuspend(port->dev); - dev_pm_clear_wake_irq(port->dev); - return ret; } static void omap_8250_shutdown(struct uart_port *port) @@ -748,11 +761,16 @@ static void omap_8250_shutdown(struct uart_port *port) if (priv->habit & UART_HAS_EFR2) serial_out(up, UART_OMAP_EFR2, 0x0); + /* Synchronize UART_IER access against the console. */ + spin_lock_irq(&port->lock); up->ier = 0; serial_out(up, UART_IER, 0); + spin_unlock_irq(&port->lock); + disable_irq_nosync(up->port.irq); + dev_pm_clear_wake_irq(port->dev); - if (up->dma) - serial8250_release_dma(up); + serial8250_release_dma(up); + up->dma = NULL; /* * Disable break condition and FIFOs @@ -763,8 +781,6 @@ static void omap_8250_shutdown(struct uart_port *port) pm_runtime_mark_last_busy(port->dev); pm_runtime_put_autosuspend(port->dev); - free_irq(port->irq, port); - dev_pm_clear_wake_irq(port->dev); } static void omap_8250_throttle(struct uart_port *port) @@ -791,6 +807,7 @@ static void omap_8250_unthrottle(struct uart_port *port) pm_runtime_get_sync(port->dev); + /* Synchronize UART_IER access against the console. */ spin_lock_irqsave(&port->lock, flags); priv->throttled = false; if (up->dma) @@ -941,6 +958,7 @@ static void __dma_rx_complete(void *param) struct dma_tx_state state; unsigned long flags; + /* Synchronize UART_IER access against the console. */ spin_lock_irqsave(&p->port.lock, flags); /* @@ -998,6 +1016,9 @@ static int omap_8250_rx_dma(struct uart_8250_port *p) unsigned long flags; u32 reg; + /* Port locked to synchronize UART_IER access against the console. */ + lockdep_assert_held_once(&p->port.lock); + if (priv->rx_dma_broken) return -EINVAL; @@ -1212,6 +1233,9 @@ static u16 omap_8250_handle_rx_dma(struct uart_8250_port *up, u8 iir, u16 status static void am654_8250_handle_rx_dma(struct uart_8250_port *up, u8 iir, u16 status) { + /* Port locked to synchronize UART_IER access against the console. */ + lockdep_assert_held_once(&up->port.lock); + /* * Queue a new transfer if FIFO has data. */ @@ -1394,7 +1418,7 @@ static int omap8250_probe(struct platform_device *pdev) UPF_HARD_FLOW; up.port.private_data = priv; - up.port.regshift = 2; + up.port.regshift = OMAP_UART_REGSHIFT; up.port.fifosize = 64; up.tx_loadsz = 64; up.capabilities = UART_CAP_FIFO; @@ -1444,8 +1468,6 @@ static int omap8250_probe(struct platform_device *pdev) &up.overrun_backoff_time_ms) != 0) up.overrun_backoff_time_ms = 0; - priv->wakeirq = irq_of_parse_and_map(np, 1); - pdata = of_device_get_match_data(&pdev->dev); if (pdata) priv->habit |= pdata->habit; @@ -1457,6 +1479,8 @@ static int omap8250_probe(struct platform_device *pdev) DEFAULT_CLK_SPEED); } + priv->membase = membase; + priv->line = -ENODEV; priv->latency = PM_QOS_CPU_LATENCY_DEFAULT_VALUE; priv->calc_latency = PM_QOS_CPU_LATENCY_DEFAULT_VALUE; cpu_latency_qos_add_request(&priv->pm_qos_request, priv->latency); @@ -1464,6 +1488,8 @@ static int omap8250_probe(struct platform_device *pdev) spin_lock_init(&priv->rx_dma_lock); + platform_set_drvdata(pdev, priv); + device_init_wakeup(&pdev->dev, true); pm_runtime_enable(&pdev->dev); pm_runtime_use_autosuspend(&pdev->dev); @@ -1498,64 +1524,77 @@ static int omap8250_probe(struct platform_device *pdev) ret = of_property_count_strings(np, "dma-names"); if (ret == 2) { struct omap8250_dma_params *dma_params = NULL; + struct uart_8250_dma *dma = &priv->omap8250_dma; - up.dma = &priv->omap8250_dma; - up.dma->fn = the_no_dma_filter_fn; - up.dma->tx_dma = omap_8250_tx_dma; - up.dma->rx_dma = omap_8250_rx_dma; + dma->fn = the_no_dma_filter_fn; + dma->tx_dma = omap_8250_tx_dma; + dma->rx_dma = omap_8250_rx_dma; if (pdata) dma_params = pdata->dma_params; if (dma_params) { - up.dma->rx_size = dma_params->rx_size; - up.dma->rxconf.src_maxburst = dma_params->rx_trigger; - up.dma->txconf.dst_maxburst = dma_params->tx_trigger; + dma->rx_size = dma_params->rx_size; + dma->rxconf.src_maxburst = dma_params->rx_trigger; + dma->txconf.dst_maxburst = dma_params->tx_trigger; priv->rx_trigger = dma_params->rx_trigger; priv->tx_trigger = dma_params->tx_trigger; } else { - up.dma->rx_size = RX_TRIGGER; - up.dma->rxconf.src_maxburst = RX_TRIGGER; - up.dma->txconf.dst_maxburst = TX_TRIGGER; + dma->rx_size = RX_TRIGGER; + dma->rxconf.src_maxburst = RX_TRIGGER; + dma->txconf.dst_maxburst = TX_TRIGGER; } } #endif + + irq_set_status_flags(irq, IRQ_NOAUTOEN); + ret = devm_request_irq(&pdev->dev, irq, omap8250_irq, 0, + dev_name(&pdev->dev), priv); + if (ret < 0) + return ret; + + priv->wakeirq = irq_of_parse_and_map(np, 1); + ret = serial8250_register_8250_port(&up); if (ret < 0) { dev_err(&pdev->dev, "unable to register 8250 port\n"); goto err; } priv->line = ret; - platform_set_drvdata(pdev, priv); pm_runtime_mark_last_busy(&pdev->dev); pm_runtime_put_autosuspend(&pdev->dev); return 0; err: pm_runtime_dont_use_autosuspend(&pdev->dev); pm_runtime_put_sync(&pdev->dev); + flush_work(&priv->qos_work); pm_runtime_disable(&pdev->dev); + cpu_latency_qos_remove_request(&priv->pm_qos_request); return ret; } static int omap8250_remove(struct platform_device *pdev) { struct omap8250_priv *priv = platform_get_drvdata(pdev); + struct uart_8250_port *up; int err; err = pm_runtime_resume_and_get(&pdev->dev); if (err) return err; + up = serial8250_get_port(priv->line); + omap_8250_shutdown(&up->port); + serial8250_unregister_port(priv->line); + priv->line = -ENODEV; pm_runtime_dont_use_autosuspend(&pdev->dev); pm_runtime_put_sync(&pdev->dev); flush_work(&priv->qos_work); pm_runtime_disable(&pdev->dev); - serial8250_unregister_port(priv->line); cpu_latency_qos_remove_request(&priv->pm_qos_request); device_init_wakeup(&pdev->dev, false); return 0; } -#ifdef CONFIG_PM_SLEEP static int omap8250_prepare(struct device *dev) { struct omap8250_priv *priv = dev_get_drvdata(dev); @@ -1579,33 +1618,38 @@ static int omap8250_suspend(struct device *dev) { struct omap8250_priv *priv = dev_get_drvdata(dev); struct uart_8250_port *up = serial8250_get_port(priv->line); + int err; serial8250_suspend_port(priv->line); - pm_runtime_get_sync(dev); + err = pm_runtime_resume_and_get(dev); + if (err) + return err; if (!device_may_wakeup(dev)) priv->wer = 0; serial_out(up, UART_OMAP_WER, priv->wer); - pm_runtime_mark_last_busy(dev); - pm_runtime_put_autosuspend(dev); - + err = pm_runtime_force_suspend(dev); flush_work(&priv->qos_work); - return 0; + + return err; } static int omap8250_resume(struct device *dev) { struct omap8250_priv *priv = dev_get_drvdata(dev); + int err; + err = pm_runtime_force_resume(dev); + if (err) + return err; serial8250_resume_port(priv->line); + /* Paired with pm_runtime_resume_and_get() in omap8250_suspend() */ + pm_runtime_mark_last_busy(dev); + pm_runtime_put_autosuspend(dev); + return 0; } -#else -#define omap8250_prepare NULL -#define omap8250_complete NULL -#endif -#ifdef CONFIG_PM static int omap8250_lost_context(struct uart_8250_port *up) { u32 val; @@ -1621,11 +1665,15 @@ static int omap8250_lost_context(struct uart_8250_port *up) return 0; } +static void uart_write(struct omap8250_priv *priv, u32 reg, u32 val) +{ + writel(val, priv->membase + (reg << OMAP_UART_REGSHIFT)); +} + /* TODO: in future, this should happen via API in drivers/reset/ */ static int omap8250_soft_reset(struct device *dev) { struct omap8250_priv *priv = dev_get_drvdata(dev); - struct uart_8250_port *up = serial8250_get_port(priv->line); int timeout = 100; int sysc; int syss; @@ -1639,20 +1687,20 @@ static int omap8250_soft_reset(struct device *dev) * needing omap8250_soft_reset() quirk. Do it in two writes as * recommended in the comment for omap8250_update_scr(). */ - serial_out(up, UART_OMAP_SCR, OMAP_UART_SCR_DMAMODE_1); - serial_out(up, UART_OMAP_SCR, + uart_write(priv, UART_OMAP_SCR, OMAP_UART_SCR_DMAMODE_1); + uart_write(priv, UART_OMAP_SCR, OMAP_UART_SCR_DMAMODE_1 | OMAP_UART_SCR_DMAMODE_CTL); - sysc = serial_in(up, UART_OMAP_SYSC); + sysc = uart_read(priv, UART_OMAP_SYSC); /* softreset the UART */ sysc |= OMAP_UART_SYSC_SOFTRESET; - serial_out(up, UART_OMAP_SYSC, sysc); + uart_write(priv, UART_OMAP_SYSC, sysc); /* By experiments, 1us enough for reset complete on AM335x */ do { udelay(1); - syss = serial_in(up, UART_OMAP_SYSS); + syss = uart_read(priv, UART_OMAP_SYSS); } while (--timeout && !(syss & OMAP_UART_SYSS_RESETDONE)); if (!timeout) { @@ -1666,13 +1714,10 @@ static int omap8250_soft_reset(struct device *dev) static int omap8250_runtime_suspend(struct device *dev) { struct omap8250_priv *priv = dev_get_drvdata(dev); - struct uart_8250_port *up; - - /* In case runtime-pm tries this before we are setup */ - if (!priv) - return 0; + struct uart_8250_port *up = NULL; - up = serial8250_get_port(priv->line); + if (priv->line >= 0) + up = serial8250_get_port(priv->line); /* * When using 'no_console_suspend', the console UART must not be * suspended. Since driver suspend is managed by runtime suspend, @@ -1680,7 +1725,7 @@ static int omap8250_runtime_suspend(struct device *dev) * active during suspend. */ if (priv->is_suspending && !console_suspend_enabled) { - if (uart_console(&up->port)) + if (up && uart_console(&up->port)) return -EBUSY; } @@ -1691,13 +1736,15 @@ static int omap8250_runtime_suspend(struct device *dev) if (ret) return ret; - /* Restore to UART mode after reset (for wakeup) */ - omap8250_update_mdr1(up, priv); - /* Restore wakeup enable register */ - serial_out(up, UART_OMAP_WER, priv->wer); + if (up) { + /* Restore to UART mode after reset (for wakeup) */ + omap8250_update_mdr1(up, priv); + /* Restore wakeup enable register */ + serial_out(up, UART_OMAP_WER, priv->wer); + } } - if (up->dma && up->dma->rxchan) + if (up && up->dma && up->dma->rxchan) omap_8250_rx_dma_flush(up); priv->latency = PM_QOS_CPU_LATENCY_DEFAULT_VALUE; @@ -1709,25 +1756,27 @@ static int omap8250_runtime_suspend(struct device *dev) static int omap8250_runtime_resume(struct device *dev) { struct omap8250_priv *priv = dev_get_drvdata(dev); - struct uart_8250_port *up; - - /* In case runtime-pm tries this before we are setup */ - if (!priv) - return 0; + struct uart_8250_port *up = NULL; - up = serial8250_get_port(priv->line); + if (priv->line >= 0) + up = serial8250_get_port(priv->line); - if (omap8250_lost_context(up)) + if (up && omap8250_lost_context(up)) { + spin_lock_irq(&up->port.lock); omap8250_restore_regs(up); + spin_unlock_irq(&up->port.lock); + } - if (up->dma && up->dma->rxchan && !(priv->habit & UART_HAS_EFR2)) + if (up && up->dma && up->dma->rxchan && !(priv->habit & UART_HAS_EFR2)) { + spin_lock_irq(&up->port.lock); omap_8250_rx_dma(up); + spin_unlock_irq(&up->port.lock); + } priv->latency = priv->calc_latency; schedule_work(&priv->qos_work); return 0; } -#endif #ifdef CONFIG_SERIAL_8250_OMAP_TTYO_FIXUP static int __init omap8250_console_fixup(void) @@ -1770,17 +1819,17 @@ console_initcall(omap8250_console_fixup); #endif static const struct dev_pm_ops omap8250_dev_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(omap8250_suspend, omap8250_resume) - SET_RUNTIME_PM_OPS(omap8250_runtime_suspend, + SYSTEM_SLEEP_PM_OPS(omap8250_suspend, omap8250_resume) + RUNTIME_PM_OPS(omap8250_runtime_suspend, omap8250_runtime_resume, NULL) - .prepare = omap8250_prepare, - .complete = omap8250_complete, + .prepare = pm_sleep_ptr(omap8250_prepare), + .complete = pm_sleep_ptr(omap8250_complete), }; static struct platform_driver omap8250_platform_driver = { .driver = { .name = "omap8250", - .pm = &omap8250_dev_pm_ops, + .pm = pm_ptr(&omap8250_dev_pm_ops), .of_match_table = omap8250_dt_ids, }, .probe = omap8250_probe, diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c index e80c4f6551a1c26c701729d2eb6d22623016c3d4..d2d547b5da95aa8e0ebcd3cb2bca79472933d7d9 100644 --- a/drivers/tty/serial/8250/8250_pci.c +++ b/drivers/tty/serial/8250/8250_pci.c @@ -1232,14 +1232,6 @@ static int pci_oxsemi_tornado_setup(struct serial_private *priv, return pci_default_setup(priv, board, up, idx); } -static int pci_asix_setup(struct serial_private *priv, - const struct pciserial_board *board, - struct uart_8250_port *port, int idx) -{ - port->bugs |= UART_BUG_PARITY; - return pci_default_setup(priv, board, port, idx); -} - #define QPCR_TEST_FOR1 0x3F #define QPCR_TEST_GET1 0x00 #define QPCR_TEST_FOR2 0x40 @@ -1955,7 +1947,6 @@ pci_moxa_setup(struct serial_private *priv, #define PCI_DEVICE_ID_WCH_CH355_4S 0x7173 #define PCI_VENDOR_ID_AGESTAR 0x5372 #define PCI_DEVICE_ID_AGESTAR_9375 0x6872 -#define PCI_VENDOR_ID_ASIX 0x9710 #define PCI_DEVICE_ID_BROADCOM_TRUMANAGE 0x160a #define PCI_DEVICE_ID_AMCC_ADDIDATA_APCI7800 0x818e @@ -2600,16 +2591,6 @@ static struct pci_serial_quirk pci_serial_quirks[] = { .exit = pci_wch_ch38x_exit, .setup = pci_wch_ch38x_setup, }, - /* - * ASIX devices with FIFO bug - */ - { - .vendor = PCI_VENDOR_ID_ASIX, - .device = PCI_ANY_ID, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .setup = pci_asix_setup, - }, /* * Broadcom TruManage (NetXtreme) */ diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index c153ba3a018a255bd4304099d951a017f3482502..16aeb14201378f01c755cfbb14028632d210524e 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -325,7 +325,7 @@ static const struct serial8250_config uart_config[] = { }; /* Uart divisor latch read */ -static int default_serial_dl_read(struct uart_8250_port *up) +static u32 default_serial_dl_read(struct uart_8250_port *up) { /* Assign these in pieces to truncate any bits above 7. */ unsigned char dll = serial_in(up, UART_DLL); @@ -335,72 +335,12 @@ static int default_serial_dl_read(struct uart_8250_port *up) } /* Uart divisor latch write */ -static void default_serial_dl_write(struct uart_8250_port *up, int value) +static void default_serial_dl_write(struct uart_8250_port *up, u32 value) { serial_out(up, UART_DLL, value & 0xff); serial_out(up, UART_DLM, value >> 8 & 0xff); } -#ifdef CONFIG_SERIAL_8250_RT288X - -#define UART_REG_UNMAPPED -1 - -/* Au1x00/RT288x UART hardware has a weird register layout */ -static const s8 au_io_in_map[8] = { - [UART_RX] = 0, - [UART_IER] = 2, - [UART_IIR] = 3, - [UART_LCR] = 5, - [UART_MCR] = 6, - [UART_LSR] = 7, - [UART_MSR] = 8, - [UART_SCR] = UART_REG_UNMAPPED, -}; - -static const s8 au_io_out_map[8] = { - [UART_TX] = 1, - [UART_IER] = 2, - [UART_FCR] = 4, - [UART_LCR] = 5, - [UART_MCR] = 6, - [UART_LSR] = UART_REG_UNMAPPED, - [UART_MSR] = UART_REG_UNMAPPED, - [UART_SCR] = UART_REG_UNMAPPED, -}; - -unsigned int au_serial_in(struct uart_port *p, int offset) -{ - if (offset >= ARRAY_SIZE(au_io_in_map)) - return UINT_MAX; - offset = au_io_in_map[offset]; - if (offset == UART_REG_UNMAPPED) - return UINT_MAX; - return __raw_readl(p->membase + (offset << p->regshift)); -} - -void au_serial_out(struct uart_port *p, int offset, int value) -{ - if (offset >= ARRAY_SIZE(au_io_out_map)) - return; - offset = au_io_out_map[offset]; - if (offset == UART_REG_UNMAPPED) - return; - __raw_writel(value, p->membase + (offset << p->regshift)); -} - -/* Au1x00 haven't got a standard divisor latch */ -static int au_serial_dl_read(struct uart_8250_port *up) -{ - return __raw_readl(up->port.membase + 0x28); -} - -static void au_serial_dl_write(struct uart_8250_port *up, int value) -{ - __raw_writel(value, up->port.membase + 0x28); -} - -#endif - static unsigned int hub6_serial_in(struct uart_port *p, int offset) { offset = offset << p->regshift; @@ -510,15 +450,6 @@ static void set_io_from_upio(struct uart_port *p) p->serial_out = mem32be_serial_out; break; -#ifdef CONFIG_SERIAL_8250_RT288X - case UPIO_AU: - p->serial_in = au_serial_in; - p->serial_out = au_serial_out; - up->dl_read = au_serial_dl_read; - up->dl_write = au_serial_dl_write; - break; -#endif - default: p->serial_in = io_serial_in; p->serial_out = io_serial_out; @@ -608,6 +539,9 @@ EXPORT_SYMBOL_GPL(serial8250_rpm_put); */ static int serial8250_em485_init(struct uart_8250_port *p) { + /* Port locked to synchronize UART_IER access against the console. */ + lockdep_assert_held_once(&p->port.lock); + if (p->em485) goto deassert_rts; @@ -746,6 +680,8 @@ static void serial8250_set_sleep(struct uart_8250_port *p, int sleep) serial8250_rpm_get(p); if (p->capabilities & UART_CAP_SLEEP) { + /* Synchronize UART_IER access against the console. */ + spin_lock_irq(&p->port.lock); if (p->capabilities & UART_CAP_EFR) { lcr = serial_in(p, UART_LCR); efr = serial_in(p, UART_EFR); @@ -759,6 +695,7 @@ static void serial8250_set_sleep(struct uart_8250_port *p, int sleep) serial_out(p, UART_EFR, efr); serial_out(p, UART_LCR, lcr); } + spin_unlock_irq(&p->port.lock); } serial8250_rpm_put(p); @@ -766,6 +703,9 @@ static void serial8250_set_sleep(struct uart_8250_port *p, int sleep) static void serial8250_clear_IER(struct uart_8250_port *up) { + /* Port locked to synchronize UART_IER access against the console. */ + lockdep_assert_held_once(&up->port.lock); + if (up->capabilities & UART_CAP_UUE) serial_out(up, UART_IER, UART_IER_UUE); else @@ -848,7 +788,7 @@ static void disable_rsa(struct uart_8250_port *up) static int size_fifo(struct uart_8250_port *up) { unsigned char old_fcr, old_mcr, old_lcr; - unsigned short old_dl; + u32 old_dl; int count; old_lcr = serial_in(up, UART_LCR); @@ -1038,6 +978,9 @@ static void autoconfig_16550a(struct uart_8250_port *up) unsigned char status1, status2; unsigned int iersave; + /* Port locked to synchronize UART_IER access against the console. */ + lockdep_assert_held_once(&up->port.lock); + up->port.type = PORT_16550A; up->capabilities |= UART_CAP_FIFO; @@ -1221,6 +1164,8 @@ static void autoconfig(struct uart_8250_port *up) /* * We really do need global IRQs disabled here - we're going to * be frobbing the chips IRQ enable register to see if it exists. + * + * Synchronize UART_IER access against the console. */ spin_lock_irqsave(&port->lock, flags); @@ -1393,7 +1338,10 @@ static void autoconfig_irq(struct uart_8250_port *up) /* forget possible initially masked and pending IRQ */ probe_irq_off(probe_irq_on()); save_mcr = serial8250_in_MCR(up); + /* Synchronize UART_IER access against the console. */ + spin_lock_irq(&port->lock); save_ier = serial_in(up, UART_IER); + spin_unlock_irq(&port->lock); serial8250_out_MCR(up, UART_MCR_OUT1 | UART_MCR_OUT2); irqs = probe_irq_on(); @@ -1405,7 +1353,10 @@ static void autoconfig_irq(struct uart_8250_port *up) serial8250_out_MCR(up, UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2); } + /* Synchronize UART_IER access against the console. */ + spin_lock_irq(&port->lock); serial_out(up, UART_IER, UART_IER_ALL_INTR); + spin_unlock_irq(&port->lock); serial_in(up, UART_LSR); serial_in(up, UART_RX); serial_in(up, UART_IIR); @@ -1415,7 +1366,10 @@ static void autoconfig_irq(struct uart_8250_port *up) irq = probe_irq_off(irqs); serial8250_out_MCR(up, save_mcr); + /* Synchronize UART_IER access against the console. */ + spin_lock_irq(&port->lock); serial_out(up, UART_IER, save_ier); + spin_unlock_irq(&port->lock); if (port->flags & UPF_FOURPORT) outb_p(save_ICP, ICP); @@ -1430,6 +1384,9 @@ static void serial8250_stop_rx(struct uart_port *port) { struct uart_8250_port *up = up_to_u8250p(port); + /* Port locked to synchronize UART_IER access against the console. */ + lockdep_assert_held_once(&port->lock); + serial8250_rpm_get(up); up->ier &= ~(UART_IER_RLSI | UART_IER_RDI); @@ -1449,6 +1406,9 @@ void serial8250_em485_stop_tx(struct uart_8250_port *p) { unsigned char mcr = serial8250_in_MCR(p); + /* Port locked to synchronize UART_IER access against the console. */ + lockdep_assert_held_once(&p->port.lock); + if (p->port.rs485.flags & SER_RS485_RTS_AFTER_SEND) mcr |= UART_MCR_RTS; else @@ -1498,6 +1458,9 @@ static void __stop_tx_rs485(struct uart_8250_port *p, u64 stop_delay) { struct uart_8250_em485 *em485 = p->em485; + /* Port locked to synchronize UART_IER access against the console. */ + lockdep_assert_held_once(&p->port.lock); + stop_delay += (u64)p->port.rs485.delay_rts_after_send * NSEC_PER_MSEC; /* @@ -1677,6 +1640,9 @@ static void serial8250_start_tx(struct uart_port *port) struct uart_8250_port *up = up_to_u8250p(port); struct uart_8250_em485 *em485 = up->em485; + /* Port locked to synchronize UART_IER access against the console. */ + lockdep_assert_held_once(&port->lock); + if (!port->x_char && uart_circ_empty(&port->state->xmit)) return; @@ -1704,6 +1670,9 @@ static void serial8250_disable_ms(struct uart_port *port) { struct uart_8250_port *up = up_to_u8250p(port); + /* Port locked to synchronize UART_IER access against the console. */ + lockdep_assert_held_once(&port->lock); + /* no MSR capabilities */ if (up->bugs & UART_BUG_NOMSR) return; @@ -1718,6 +1687,9 @@ static void serial8250_enable_ms(struct uart_port *port) { struct uart_8250_port *up = up_to_u8250p(port); + /* Port locked to synchronize UART_IER access against the console. */ + lockdep_assert_held_once(&port->lock); + /* no MSR capabilities */ if (up->bugs & UART_BUG_NOMSR) return; @@ -2174,6 +2146,14 @@ static void serial8250_put_poll_char(struct uart_port *port, unsigned int ier; struct uart_8250_port *up = up_to_u8250p(port); + /* + * Normally the port is locked to synchronize UART_IER access + * against the console. However, this function is only used by + * KDB/KGDB, where it may not be possible to acquire the port + * lock because all other CPUs are quiesced. The quiescence + * should allow safe lockless usage here. + */ + serial8250_rpm_get(up); /* * First save the IER then disable the interrupts @@ -2219,7 +2199,12 @@ int serial8250_do_startup(struct uart_port *port) serial8250_rpm_get(up); if (port->type == PORT_16C950) { - /* Wake up and initialize UART */ + /* + * Wake up and initialize UART + * + * Synchronize UART_IER access against the console. + */ + spin_lock_irqsave(&port->lock, flags); up->acr = 0; serial_port_out(port, UART_LCR, UART_LCR_CONF_MODE_B); serial_port_out(port, UART_EFR, UART_EFR_ECB); @@ -2229,12 +2214,19 @@ int serial8250_do_startup(struct uart_port *port) serial_port_out(port, UART_LCR, UART_LCR_CONF_MODE_B); serial_port_out(port, UART_EFR, UART_EFR_ECB); serial_port_out(port, UART_LCR, 0); + spin_unlock_irqrestore(&port->lock, flags); } if (port->type == PORT_DA830) { - /* Reset the port */ + /* + * Reset the port + * + * Synchronize UART_IER access against the console. + */ + spin_lock_irqsave(&port->lock, flags); serial_port_out(port, UART_IER, 0); serial_port_out(port, UART_DA830_PWREMU_MGMT, 0); + spin_unlock_irqrestore(&port->lock, flags); mdelay(10); /* Enable Tx, Rx and free run mode */ @@ -2345,6 +2337,8 @@ int serial8250_do_startup(struct uart_port *port) * this interrupt whenever the transmitter is idle and * the interrupt is enabled. Delays are necessary to * allow register changes to become visible. + * + * Synchronize UART_IER access against the console. */ spin_lock_irqsave(&port->lock, flags); @@ -2495,6 +2489,8 @@ void serial8250_do_shutdown(struct uart_port *port) serial8250_rpm_get(up); /* * Disable interrupts from this port + * + * Synchronize UART_IER access against the console. */ spin_lock_irqsave(&port->lock, flags); up->ier = 0; @@ -2636,11 +2632,8 @@ static unsigned char serial8250_compute_lcr(struct uart_8250_port *up, if (c_cflag & CSTOPB) cval |= UART_LCR_STOP; - if (c_cflag & PARENB) { + if (c_cflag & PARENB) cval |= UART_LCR_PARITY; - if (up->bugs & UART_BUG_PARITY) - up->fifo_bug = true; - } if (!(c_cflag & PARODD)) cval |= UART_LCR_EPAR; if (c_cflag & CMSPAR) @@ -2794,6 +2787,8 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios, /* * Ok, we're now changing the port state. Do it with * interrupts disabled. + * + * Synchronize UART_IER access against the console. */ serial8250_rpm_get(up); spin_lock_irqsave(&port->lock, flags); @@ -2801,8 +2796,7 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios, up->lcr = cval; /* Save computed LCR */ if (up->capabilities & UART_CAP_FIFO && port->fifosize > 1) { - /* NOTE: If fifo_bug is not set, a user can set RX_trigger. */ - if ((baud < 2400 && !up->dma) || up->fifo_bug) { + if (baud < 2400 && !up->dma) { up->fcr &= ~UART_FCR_TRIGGER_MASK; up->fcr |= UART_FCR_TRIGGER_1; } @@ -2969,11 +2963,6 @@ static unsigned int serial8250_port_size(struct uart_8250_port *pt) { if (pt->port.mapsize) return pt->port.mapsize; - if (pt->port.iotype == UPIO_AU) { - if (pt->port.type == PORT_RT2880) - return 0x100; - return 0x1000; - } if (is_omap1_8250(pt)) return 0x16 << pt->port.regshift; @@ -3138,8 +3127,7 @@ static int do_set_rxtrig(struct tty_port *port, unsigned char bytes) struct uart_8250_port *up = up_to_u8250p(uport); int rxtrig; - if (!(up->capabilities & UART_CAP_FIFO) || uport->fifosize <= 1 || - up->fifo_bug) + if (!(up->capabilities & UART_CAP_FIFO) || uport->fifosize <= 1) return -EINVAL; rxtrig = bytes_to_fcr_rxtrig(up, bytes); @@ -3223,10 +3211,6 @@ static void serial8250_config_port(struct uart_port *port, int flags) if (flags & UART_CONFIG_TYPE) autoconfig(up); - /* if access method is AU, it is a 16550 with a quirk */ - if (port->type == PORT_16550A && port->iotype == UPIO_AU) - up->bugs |= UART_BUG_NOMSR; - /* HW bugs may trigger IRQ while IIR == NO_INT */ if (port->type == PORT_TEGRA) up->bugs |= UART_BUG_NOMSR; @@ -3293,6 +3277,7 @@ void serial8250_init_port(struct uart_8250_port *up) struct uart_port *port = &up->port; spin_lock_init(&port->lock); + port->ctrl_id = 0; port->ops = &serial8250_pops; port->has_sysrq = IS_ENABLED(CONFIG_SERIAL_8250_CONSOLE); diff --git a/drivers/tty/serial/8250/8250_pxa.c b/drivers/tty/serial/8250/8250_pxa.c index 795e55142d4c7c0632ef1b7c15217d19c04c08b4..28b341f602c6220c3d7e7df4f685a4558d97bd58 100644 --- a/drivers/tty/serial/8250/8250_pxa.c +++ b/drivers/tty/serial/8250/8250_pxa.c @@ -60,7 +60,7 @@ static const struct of_device_id serial_pxa_dt_ids[] = { MODULE_DEVICE_TABLE(of, serial_pxa_dt_ids); /* Uart divisor latch write */ -static void serial_pxa_dl_write(struct uart_8250_port *up, int value) +static void serial_pxa_dl_write(struct uart_8250_port *up, u32 value) { unsigned int dll; diff --git a/drivers/tty/serial/8250/8250_rt288x.c b/drivers/tty/serial/8250/8250_rt288x.c new file mode 100644 index 0000000000000000000000000000000000000000..6415ca8d3adff33fde085e526cda6bf1404b25a6 --- /dev/null +++ b/drivers/tty/serial/8250/8250_rt288x.c @@ -0,0 +1,136 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * RT288x/Au1xxx driver + */ + +#include +#include +#include +#include +#include +#include + +#include "8250.h" + +#define RT288X_DL 0x28 + +/* Au1x00/RT288x UART hardware has a weird register layout */ +static const u8 au_io_in_map[7] = { + [UART_RX] = 0, + [UART_IER] = 2, + [UART_IIR] = 3, + [UART_LCR] = 5, + [UART_MCR] = 6, + [UART_LSR] = 7, + [UART_MSR] = 8, +}; + +static const u8 au_io_out_map[5] = { + [UART_TX] = 1, + [UART_IER] = 2, + [UART_FCR] = 4, + [UART_LCR] = 5, + [UART_MCR] = 6, +}; + +static unsigned int au_serial_in(struct uart_port *p, int offset) +{ + if (offset >= ARRAY_SIZE(au_io_in_map)) + return UINT_MAX; + offset = au_io_in_map[offset]; + + return __raw_readl(p->membase + (offset << p->regshift)); +} + +static void au_serial_out(struct uart_port *p, int offset, int value) +{ + if (offset >= ARRAY_SIZE(au_io_out_map)) + return; + offset = au_io_out_map[offset]; + + __raw_writel(value, p->membase + (offset << p->regshift)); +} + +/* Au1x00 haven't got a standard divisor latch */ +static u32 au_serial_dl_read(struct uart_8250_port *up) +{ + return __raw_readl(up->port.membase + RT288X_DL); +} + +static void au_serial_dl_write(struct uart_8250_port *up, u32 value) +{ + __raw_writel(value, up->port.membase + RT288X_DL); +} + +int au_platform_setup(struct plat_serial8250_port *p) +{ + p->iotype = UPIO_AU; + + p->serial_in = au_serial_in; + p->serial_out = au_serial_out; + p->dl_read = au_serial_dl_read; + p->dl_write = au_serial_dl_write; + + p->mapsize = 0x1000; + + p->bugs |= UART_BUG_NOMSR; + + return 0; +} +EXPORT_SYMBOL_GPL(au_platform_setup); + +int rt288x_setup(struct uart_port *p) +{ + struct uart_8250_port *up = up_to_u8250p(p); + + p->iotype = UPIO_AU; + + p->serial_in = au_serial_in; + p->serial_out = au_serial_out; + up->dl_read = au_serial_dl_read; + up->dl_write = au_serial_dl_write; + + p->mapsize = 0x100; + + up->bugs |= UART_BUG_NOMSR; + + return 0; +} +EXPORT_SYMBOL_GPL(rt288x_setup); + +#ifdef CONFIG_SERIAL_8250_CONSOLE +static void au_putc(struct uart_port *port, unsigned char c) +{ + unsigned int status; + + au_serial_out(port, UART_TX, c); + + for (;;) { + status = au_serial_in(port, UART_LSR); + if (uart_lsr_tx_empty(status)) + break; + cpu_relax(); + } +} + +static void au_early_serial8250_write(struct console *console, + const char *s, unsigned int count) +{ + struct earlycon_device *device = console->data; + struct uart_port *port = &device->port; + + uart_console_write(port, s, count, au_putc); +} + +static int __init early_au_setup(struct earlycon_device *dev, const char *opt) +{ + rt288x_setup(&dev->port); + dev->con->write = au_early_serial8250_write; + + return 0; +} +OF_EARLYCON_DECLARE(palmchip, "ralink,rt2880-uart", early_au_setup); +#endif + +MODULE_DESCRIPTION("RT288x/Au1xxx UART driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/tty/serial/8250/8250_uniphier.c b/drivers/tty/serial/8250/8250_uniphier.c index a2978abab0db6032b1cae214c5ba0da575bd0542..a405155264b1721a2f731ec051a93942d6f90441 100644 --- a/drivers/tty/serial/8250/8250_uniphier.c +++ b/drivers/tty/serial/8250/8250_uniphier.c @@ -145,12 +145,12 @@ static void uniphier_serial_out(struct uart_port *p, int offset, int value) * The divisor latch register exists at different address. * Override dl_read/write callbacks. */ -static int uniphier_serial_dl_read(struct uart_8250_port *up) +static u32 uniphier_serial_dl_read(struct uart_8250_port *up) { return readl(up->port.membase + UNIPHIER_UART_DLR); } -static void uniphier_serial_dl_write(struct uart_8250_port *up, int value) +static void uniphier_serial_dl_write(struct uart_8250_port *up, u32 value) { writel(value, up->port.membase + UNIPHIER_UART_DLR); } diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig index 5313aa31930f4ec4ea8f798a03f8c08066b86b36..ee17cf5c44c6b046227093d2892716e506d3e49d 100644 --- a/drivers/tty/serial/8250/Kconfig +++ b/drivers/tty/serial/8250/Kconfig @@ -71,14 +71,16 @@ config SERIAL_8250_16550A_VARIANTS console, you can say N here. config SERIAL_8250_FINTEK - bool "Support for Fintek F81216A LPC to 4 UART RS485 API" + bool "Support for Fintek variants" depends on SERIAL_8250 help - Selecting this option will add support for the RS485 capabilities - of the Fintek F81216A LPC to 4 UART. + Selecting this option will add support for the RS232 and RS485 + capabilities of the Fintek F81216A LPC to 4 UART as well similar + variants. If this option is not selected the device will be configured as a - standard 16550A serial port. + standard 16550A serial port, however the device may not function + correctly without this option enabled. If unsure, say N. @@ -377,9 +379,9 @@ config SERIAL_8250_BCM2835AUX If unsure, say N. config SERIAL_8250_FSL - bool "Freescale 16550 UART support" if COMPILE_TEST && !(PPC || ARM || ARM64) - depends on SERIAL_8250_CONSOLE - default PPC || ARM || ARM64 + tristate "Freescale 16550 UART support" if COMPILE_TEST && !(PPC || ARM || ARM64) + depends on SERIAL_8250 + default SERIAL_8250 if PPC || ARM || ARM64 help Selecting this option enables a workaround for a break-detection erratum for Freescale 16550 UARTs in the 8250 driver. It also diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile index 4fc2fc1f41b6c79a7f6794aeae580a474cdaf5bf..628b75be312ea531d3aed9674793f15f3659dfa6 100644 --- a/drivers/tty/serial/8250/Makefile +++ b/drivers/tty/serial/8250/Makefile @@ -35,6 +35,7 @@ obj-$(CONFIG_SERIAL_8250_DW) += 8250_dw.o obj-$(CONFIG_SERIAL_8250_EM) += 8250_em.o obj-$(CONFIG_SERIAL_8250_IOC3) += 8250_ioc3.o obj-$(CONFIG_SERIAL_8250_OMAP) += 8250_omap.o +obj-$(CONFIG_SERIAL_8250_RT288X) += 8250_rt288x.o obj-$(CONFIG_SERIAL_8250_LPC18XX) += 8250_lpc18xx.o obj-$(CONFIG_SERIAL_8250_MT6577) += 8250_mtk.o obj-$(CONFIG_SERIAL_8250_UNIPHIER) += 8250_uniphier.o diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index 3e3fb377d90d4c9f15ad55055025d4d6d8883c25..bdc568a4ab66930b963dabb94bdd0daf617cc03e 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -450,8 +450,8 @@ config SERIAL_SA1100 help If you have a machine based on a SA1100/SA1110 StrongARM(R) CPU you can enable its onboard serial port by enabling this option. - Please read for further - info. + Please read for + further info. config SERIAL_SA1100_CONSOLE bool "Console on SA1100 serial port" @@ -1555,6 +1555,29 @@ config SERIAL_SUNPLUS_CONSOLE you can alter that using a kernel command line option such as "console=ttySUPx". +config SERIAL_NUVOTON_MA35D1 + tristate "Nuvoton MA35D1 family UART support" + depends on ARCH_MA35 || COMPILE_TEST + select SERIAL_CORE + help + This driver supports Nuvoton MA35D1 family UART ports. If you would + like to use them, you must answer Y or M to this option. Note that + for use as console, it must be included in kernel and not as a + module. If you enable this option, Ma35D1 serial ports in the system + will be registered as ttyNVTx. + +config SERIAL_NUVOTON_MA35D1_CONSOLE + bool "Console on a Nuvotn MA35D1 family UART port" + depends on SERIAL_NUVOTON_MA35D1=y + select SERIAL_CORE_CONSOLE + help + Select this options if you'd like to use the UART port0 of the + Nuvoton MA35D1 family as a console. + Even if you say Y here, the currently visible virtual console + (/dev/tty0) will still be used as the system console by default, + but you can alter that using a kernel command line option such as + "console=ttyNVTx". + endmenu config SERIAL_MCTRL_GPIO diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile index cd9afd9e3018f65e7255e3220d179351375863af..d4123469583dd43d283ef8574e40e1a069648db1 100644 --- a/drivers/tty/serial/Makefile +++ b/drivers/tty/serial/Makefile @@ -3,7 +3,8 @@ # Makefile for the kernel serial device drivers. # -obj-$(CONFIG_SERIAL_CORE) += serial_core.o +obj-$(CONFIG_SERIAL_CORE) += serial_base.o +serial_base-y := serial_core.o serial_base_bus.o serial_ctrl.o serial_port.o obj-$(CONFIG_SERIAL_EARLYCON) += earlycon.o obj-$(CONFIG_SERIAL_EARLYCON_SEMIHOST) += earlycon-semihost.o @@ -21,7 +22,7 @@ obj-$(CONFIG_SERIAL_SUNSAB) += sunsab.o obj-$(CONFIG_SERIAL_21285) += 21285.o # Now bring in any enabled 8250/16450/16550 type drivers. -obj-$(CONFIG_SERIAL_8250) += 8250/ +obj-y += 8250/ obj-$(CONFIG_SERIAL_AMBA_PL010) += amba-pl010.o obj-$(CONFIG_SERIAL_AMBA_PL011) += amba-pl011.o @@ -93,3 +94,4 @@ obj-$(CONFIG_SERIAL_MCTRL_GPIO) += serial_mctrl_gpio.o obj-$(CONFIG_SERIAL_KGDB_NMI) += kgdb_nmi.o obj-$(CONFIG_KGDB_SERIAL_CONSOLE) += kgdboc.o +obj-$(CONFIG_SERIAL_NUVOTON_MA35D1) += ma35d1_serial.o diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index d8c2f3455eebad589a712d2e8e6a4be91f3ddcf4..c5c3f4674459f696d7d54db900819414adeb8350 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -2166,6 +2166,13 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios, * ----------^----------^----------^----------^----- */ pl011_write_lcr_h(uap, lcr_h); + + /* + * Receive was disabled by pl011_disable_uart during shutdown. + * Need to reenable receive if you need to use a tty_driver + * returns from tty_find_polling_driver() after a port shutdown. + */ + old_cr |= UART011_CR_RXE; pl011_write(old_cr, uap, REG_CR); spin_unlock_irqrestore(&port->lock, flags); diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index 9cd7479b03c086e6825218ae905f98a2d4b48f95..3467a875641a13f192217e3c4a20944115ef8b9f 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c @@ -868,11 +868,11 @@ static void atmel_complete_tx_dma(void *arg) dmaengine_terminate_all(chan); uart_xmit_advance(port, atmel_port->tx_len); - spin_lock_irq(&atmel_port->lock_tx); + spin_lock(&atmel_port->lock_tx); async_tx_ack(atmel_port->desc_tx); atmel_port->cookie_tx = -EINVAL; atmel_port->desc_tx = NULL; - spin_unlock_irq(&atmel_port->lock_tx); + spin_unlock(&atmel_port->lock_tx); if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) uart_write_wakeup(port); @@ -3006,14 +3006,13 @@ static int atmel_serial_remove(struct platform_device *pdev) { struct uart_port *port = platform_get_drvdata(pdev); struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); - int ret = 0; tasklet_kill(&atmel_port->tasklet_rx); tasklet_kill(&atmel_port->tasklet_tx); device_init_wakeup(&pdev->dev, 0); - ret = uart_remove_one_port(&atmel_uart, port); + uart_remove_one_port(&atmel_uart, port); kfree(atmel_port->rx_ring.buf); @@ -3023,7 +3022,7 @@ static int atmel_serial_remove(struct platform_device *pdev) pdev->dev.of_node = NULL; - return ret; + return 0; } static SIMPLE_DEV_PM_OPS(atmel_serial_pm_ops, atmel_serial_suspend, diff --git a/drivers/tty/serial/clps711x.c b/drivers/tty/serial/clps711x.c index e190dce58f4628c3b2226155226b884948549b92..e49bc4019b5051853786f465d528d43708c4a94d 100644 --- a/drivers/tty/serial/clps711x.c +++ b/drivers/tty/serial/clps711x.c @@ -514,7 +514,9 @@ static int uart_clps711x_remove(struct platform_device *pdev) { struct clps711x_port *s = platform_get_drvdata(pdev); - return uart_remove_one_port(&clps711x_uart, &s->port); + uart_remove_one_port(&clps711x_uart, &s->port); + + return 0; } static const struct of_device_id __maybe_unused clps711x_uart_dt_ids[] = { diff --git a/drivers/tty/serial/cpm_uart/cpm_uart_core.c b/drivers/tty/serial/cpm_uart/cpm_uart_core.c index 349e7da643f010bbfdc9bdf71af55210df1c5ae9..66afa9bea6bfedc00ef0580f914f89b1e46834f9 100644 --- a/drivers/tty/serial/cpm_uart/cpm_uart_core.c +++ b/drivers/tty/serial/cpm_uart/cpm_uart_core.c @@ -1431,7 +1431,10 @@ static int cpm_uart_probe(struct platform_device *ofdev) static int cpm_uart_remove(struct platform_device *ofdev) { struct uart_cpm_port *pinfo = platform_get_drvdata(ofdev); - return uart_remove_one_port(&cpm_reg, &pinfo->port); + + uart_remove_one_port(&cpm_reg, &pinfo->port); + + return 0; } static const struct of_device_id cpm_uart_match[] = { diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c index 7fd30fcc10c6238c2f3961ddc215a39a8cd61082..4d80fae20177948fd43652a4f1c55a7b262dba0d 100644 --- a/drivers/tty/serial/fsl_lpuart.c +++ b/drivers/tty/serial/fsl_lpuart.c @@ -238,6 +238,7 @@ /* Rx DMA timeout in ms, which is used to calculate Rx ring buffer size */ #define DMA_RX_TIMEOUT (10) +#define DMA_RX_IDLE_CHARS 8 #define UART_AUTOSUSPEND_TIMEOUT 3000 #define DRIVER_NAME "fsl-lpuart" @@ -282,6 +283,7 @@ struct lpuart_port { struct scatterlist rx_sgl, tx_sgl[2]; struct circ_buf rx_ring; int rx_dma_rng_buf_len; + int last_residue; unsigned int dma_tx_nents; wait_queue_head_t dma_wait; bool is_cs7; /* Set to true when character size is 7 */ @@ -331,7 +333,7 @@ static struct lpuart_soc_data imx8qxp_data = { .devtype = IMX8QXP_LPUART, .iotype = UPIO_MEM32, .reg_off = IMX_REG_OFF, - .rx_watermark = 31, + .rx_watermark = 7, /* A lower watermark is ideal for low baud rates. */ }; static struct lpuart_soc_data imxrt1050_data = { .devtype = IMXRT1050_LPUART, @@ -1255,6 +1257,8 @@ static void lpuart_copy_rx_to_tty(struct lpuart_port *sport) sport->port.icount.rx += copied; } + sport->last_residue = state.residue; + exit: dma_sync_sg_for_device(chan->device->dev, &sport->rx_sgl, 1, DMA_FROM_DEVICE); @@ -1272,11 +1276,43 @@ static void lpuart_dma_rx_complete(void *arg) lpuart_copy_rx_to_tty(sport); } +/* + * Timer function to simulate the hardware EOP (End Of Package) event. + * The timer callback is to check for new RX data and copy to TTY buffer. + * If no new data are received since last interval, the EOP condition is + * met, complete the DMA transfer by copying the data. Otherwise, just + * restart timer. + */ static void lpuart_timer_func(struct timer_list *t) { struct lpuart_port *sport = from_timer(sport, t, lpuart_timer); + enum dma_status dmastat; + struct dma_chan *chan = sport->dma_rx_chan; + struct circ_buf *ring = &sport->rx_ring; + struct dma_tx_state state; + unsigned long flags; + int count; - lpuart_copy_rx_to_tty(sport); + dmastat = dmaengine_tx_status(chan, sport->dma_rx_cookie, &state); + if (dmastat == DMA_ERROR) { + dev_err(sport->port.dev, "Rx DMA transfer failed!\n"); + return; + } + + ring->head = sport->rx_sgl.length - state.residue; + count = CIRC_CNT(ring->head, ring->tail, sport->rx_sgl.length); + + /* Check if new data received before copying */ + if ((count != 0) && (sport->last_residue == state.residue)) + lpuart_copy_rx_to_tty(sport); + else + mod_timer(&sport->lpuart_timer, + jiffies + sport->dma_rx_timeout); + + if (spin_trylock_irqsave(&sport->port.lock, flags)) { + sport->last_residue = state.residue; + spin_unlock_irqrestore(&sport->port.lock, flags); + } } static inline int lpuart_start_rx_dma(struct lpuart_port *sport) @@ -1297,9 +1333,20 @@ static inline int lpuart_start_rx_dma(struct lpuart_port *sport) */ sport->rx_dma_rng_buf_len = (DMA_RX_TIMEOUT * baud / bits / 1000) * 2; sport->rx_dma_rng_buf_len = (1 << fls(sport->rx_dma_rng_buf_len)); + sport->rx_dma_rng_buf_len = max_t(int, + sport->rxfifo_size * 2, + sport->rx_dma_rng_buf_len); + /* + * Keep this condition check in case rxfifo_size is unavailable + * for some SoCs. + */ if (sport->rx_dma_rng_buf_len < 16) sport->rx_dma_rng_buf_len = 16; + sport->last_residue = 0; + sport->dma_rx_timeout = max(nsecs_to_jiffies( + sport->port.frame_time * DMA_RX_IDLE_CHARS), 1UL); + ring->buf = kzalloc(sport->rx_dma_rng_buf_len, GFP_ATOMIC); if (!ring->buf) return -ENOMEM; @@ -1689,12 +1736,13 @@ static void lpuart_rx_dma_startup(struct lpuart_port *sport) if (!sport->dma_rx_chan) goto err; + /* set default Rx DMA timeout */ + sport->dma_rx_timeout = msecs_to_jiffies(DMA_RX_TIMEOUT); + ret = lpuart_start_rx_dma(sport); if (ret) goto err; - /* set Rx DMA timeout */ - sport->dma_rx_timeout = msecs_to_jiffies(DMA_RX_TIMEOUT); if (!sport->dma_rx_timeout) sport->dma_rx_timeout = 1; @@ -2676,6 +2724,7 @@ OF_EARLYCON_DECLARE(lpuart, "fsl,vf610-lpuart", lpuart_early_console_setup); OF_EARLYCON_DECLARE(lpuart32, "fsl,ls1021a-lpuart", lpuart32_early_console_setup); OF_EARLYCON_DECLARE(lpuart32, "fsl,ls1028a-lpuart", ls1028a_early_console_setup); OF_EARLYCON_DECLARE(lpuart32, "fsl,imx7ulp-lpuart", lpuart32_imx_early_console_setup); +OF_EARLYCON_DECLARE(lpuart32, "fsl,imx8ulp-lpuart", lpuart32_imx_early_console_setup); OF_EARLYCON_DECLARE(lpuart32, "fsl,imx8qxp-lpuart", lpuart32_imx_early_console_setup); OF_EARLYCON_DECLARE(lpuart32, "fsl,imxrt1050-lpuart", lpuart32_imx_early_console_setup); EARLYCON_DECLARE(lpuart, lpuart_early_console_setup); diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index c5e17569c3adc54ca2daa422008d5acb90b5c5f2..7341d060f85cbac82c50711693be7bb4891a4f90 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -369,6 +369,16 @@ static void imx_uart_soft_reset(struct imx_port *sport) sport->idle_counter = 0; } +static void imx_uart_disable_loopback_rs485(struct imx_port *sport) +{ + unsigned int uts; + + /* See SER_RS485_ENABLED/UTS_LOOP comment in imx_uart_probe() */ + uts = imx_uart_readl(sport, imx_uart_uts_reg(sport)); + uts &= ~UTS_LOOP; + imx_uart_writel(sport, uts, imx_uart_uts_reg(sport)); +} + /* called with port.lock taken and irqs off */ static void imx_uart_start_rx(struct uart_port *port) { @@ -390,6 +400,7 @@ static void imx_uart_start_rx(struct uart_port *port) /* Write UCR2 first as it includes RXEN */ imx_uart_writel(sport, ucr2, UCR2); imx_uart_writel(sport, ucr1, UCR1); + imx_uart_disable_loopback_rs485(sport); } /* called with port.lock taken and irqs off */ @@ -1422,7 +1433,7 @@ static int imx_uart_startup(struct uart_port *port) int retval; unsigned long flags; int dma_is_inited = 0; - u32 ucr1, ucr2, ucr3, ucr4, uts; + u32 ucr1, ucr2, ucr3, ucr4; retval = clk_prepare_enable(sport->clk_per); if (retval) @@ -1521,10 +1532,7 @@ static int imx_uart_startup(struct uart_port *port) imx_uart_writel(sport, ucr2, UCR2); } - /* See SER_RS485_ENABLED/UTS_LOOP comment in imx_uart_probe() */ - uts = imx_uart_readl(sport, imx_uart_uts_reg(sport)); - uts &= ~UTS_LOOP; - imx_uart_writel(sport, uts, imx_uart_uts_reg(sport)); + imx_uart_disable_loopback_rs485(sport); spin_unlock_irqrestore(&sport->port.lock, flags); @@ -2467,7 +2475,9 @@ static int imx_uart_remove(struct platform_device *pdev) { struct imx_port *sport = platform_get_drvdata(pdev); - return uart_remove_one_port(&imx_uart_uart_driver, &sport->port); + uart_remove_one_port(&imx_uart_uart_driver, &sport->port); + + return 0; } static void imx_uart_restore_context(struct imx_port *sport) diff --git a/drivers/tty/serial/lantiq.c b/drivers/tty/serial/lantiq.c index f1387f1024dbb336b2304966d990b563ba42f0db..bcaa479608d83a8eab371cee1f479b1845833229 100644 --- a/drivers/tty/serial/lantiq.c +++ b/drivers/tty/serial/lantiq.c @@ -890,7 +890,9 @@ static int lqasc_remove(struct platform_device *pdev) { struct uart_port *port = platform_get_drvdata(pdev); - return uart_remove_one_port(&lqasc_reg, port); + uart_remove_one_port(&lqasc_reg, port); + + return 0; } static const struct ltq_soc_data soc_data_lantiq = { diff --git a/drivers/tty/serial/ma35d1_serial.c b/drivers/tty/serial/ma35d1_serial.c new file mode 100644 index 0000000000000000000000000000000000000000..2604b4d9fb788bc50633a79a969b4c89a6bf2145 --- /dev/null +++ b/drivers/tty/serial/ma35d1_serial.c @@ -0,0 +1,821 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * MA35D1 serial driver + * Copyright (C) 2023 Nuvoton Technology Corp. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MA35_UART_NR 17 + +#define MA35_RBR_REG 0x00 +#define MA35_THR_REG 0x00 +#define MA35_IER_REG 0x04 +#define MA35_FCR_REG 0x08 +#define MA35_LCR_REG 0x0C +#define MA35_MCR_REG 0x10 +#define MA35_MSR_REG 0x14 +#define MA35_FSR_REG 0x18 +#define MA35_ISR_REG 0x1C +#define MA35_TOR_REG 0x20 +#define MA35_BAUD_REG 0x24 +#define MA35_ALTCTL_REG 0x2C +#define MA35_FUN_SEL_REG 0x30 +#define MA35_WKCTL_REG 0x40 +#define MA35_WKSTS_REG 0x44 + +/* MA35_IER_REG - Interrupt Enable Register */ +#define MA35_IER_RDA_IEN BIT(0) /* RBR Available Interrupt Enable */ +#define MA35_IER_THRE_IEN BIT(1) /* THR Empty Interrupt Enable */ +#define MA35_IER_RLS_IEN BIT(2) /* RX Line Status Interrupt Enable */ +#define MA35_IER_RTO_IEN BIT(4) /* RX Time-out Interrupt Enable */ +#define MA35_IER_BUFERR_IEN BIT(5) /* Buffer Error Interrupt Enable */ +#define MA35_IER_TIME_OUT_EN BIT(11) /* RX Buffer Time-out Counter Enable */ +#define MA35_IER_AUTO_RTS BIT(12) /* nRTS Auto-flow Control Enable */ +#define MA35_IER_AUTO_CTS BIT(13) /* nCTS Auto-flow Control Enable */ + +/* MA35_FCR_REG - FIFO Control Register */ +#define MA35_FCR_RFR BIT(1) /* RX Field Software Reset */ +#define MA35_FCR_TFR BIT(2) /* TX Field Software Reset */ +#define MA35_FCR_RFITL_MASK GENMASK(7, 4) /* RX FIFO Interrupt Trigger Level */ +#define MA35_FCR_RFITL_1BYTE FIELD_PREP(MA35_FCR_RFITL_MASK, 0) +#define MA35_FCR_RFITL_4BYTES FIELD_PREP(MA35_FCR_RFITL_MASK, 1) +#define MA35_FCR_RFITL_8BYTES FIELD_PREP(MA35_FCR_RFITL_MASK, 2) +#define MA35_FCR_RFITL_14BYTES FIELD_PREP(MA35_FCR_RFITL_MASK, 3) +#define MA35_FCR_RFITL_30BYTES FIELD_PREP(MA35_FCR_RFITL_MASK, 4) +#define MA35_FCR_RTSTL_MASK GENMASK(19, 16) /* nRTS Trigger Level */ +#define MA35_FCR_RTSTL_1BYTE FIELD_PREP(MA35_FCR_RTSTL_MASK, 0) +#define MA35_FCR_RTSTL_4BYTES FIELD_PREP(MA35_FCR_RTSTL_MASK, 1) +#define MA35_FCR_RTSTL_8BYTES FIELD_PREP(MA35_FCR_RTSTL_MASK, 2) +#define MA35_FCR_RTSTL_14BYTES FIELD_PREP(MA35_FCR_RTSTL_MASK, 3) +#define MA35_FCR_RTSTLL_30BYTES FIELD_PREP(MA35_FCR_RTSTL_MASK, 4) + +/* MA35_LCR_REG - Line Control Register */ +#define MA35_LCR_NSB BIT(2) /* Number of “STOP Bit” */ +#define MA35_LCR_PBE BIT(3) /* Parity Bit Enable */ +#define MA35_LCR_EPE BIT(4) /* Even Parity Enable */ +#define MA35_LCR_SPE BIT(5) /* Stick Parity Enable */ +#define MA35_LCR_BREAK BIT(6) /* Break Control */ +#define MA35_LCR_WLS_MASK GENMASK(1, 0) /* Word Length Selection */ +#define MA35_LCR_WLS_5BITS FIELD_PREP(MA35_LCR_WLS_MASK, 0) +#define MA35_LCR_WLS_6BITS FIELD_PREP(MA35_LCR_WLS_MASK, 1) +#define MA35_LCR_WLS_7BITS FIELD_PREP(MA35_LCR_WLS_MASK, 2) +#define MA35_LCR_WLS_8BITS FIELD_PREP(MA35_LCR_WLS_MASK, 3) + +/* MA35_MCR_REG - Modem Control Register */ +#define MA35_MCR_RTS_CTRL BIT(1) /* nRTS Signal Control */ +#define MA35_MCR_RTSACTLV BIT(9) /* nRTS Pin Active Level */ +#define MA35_MCR_RTSSTS BIT(13) /* nRTS Pin Status (Read Only) */ + +/* MA35_MSR_REG - Modem Status Register */ +#define MA35_MSR_CTSDETF BIT(0) /* Detect nCTS State Change Flag */ +#define MA35_MSR_CTSSTS BIT(4) /* nCTS Pin Status (Read Only) */ +#define MA35_MSR_CTSACTLV BIT(8) /* nCTS Pin Active Level */ + +/* MA35_FSR_REG - FIFO Status Register */ +#define MA35_FSR_RX_OVER_IF BIT(0) /* RX Overflow Error Interrupt Flag */ +#define MA35_FSR_PEF BIT(4) /* Parity Error Flag*/ +#define MA35_FSR_FEF BIT(5) /* Framing Error Flag */ +#define MA35_FSR_BIF BIT(6) /* Break Interrupt Flag */ +#define MA35_FSR_RX_EMPTY BIT(14) /* Receiver FIFO Empty (Read Only) */ +#define MA35_FSR_RX_FULL BIT(15) /* Receiver FIFO Full (Read Only) */ +#define MA35_FSR_TX_EMPTY BIT(22) /* Transmitter FIFO Empty (Read Only) */ +#define MA35_FSR_TX_FULL BIT(23) /* Transmitter FIFO Full (Read Only) */ +#define MA35_FSR_TX_OVER_IF BIT(24) /* TX Overflow Error Interrupt Flag */ +#define MA35_FSR_TE_FLAG BIT(28) /* Transmitter Empty Flag (Read Only) */ +#define MA35_FSR_RXPTR_MSK GENMASK(13, 8) /* TX FIFO Pointer mask */ +#define MA35_FSR_TXPTR_MSK GENMASK(21, 16) /* RX FIFO Pointer mask */ + +/* MA35_ISR_REG - Interrupt Status Register */ +#define MA35_ISR_RDA_IF BIT(0) /* RBR Available Interrupt Flag */ +#define MA35_ISR_THRE_IF BIT(1) /* THR Empty Interrupt Flag */ +#define MA35_ISR_RLSIF BIT(2) /* Receive Line Interrupt Flag */ +#define MA35_ISR_MODEMIF BIT(3) /* MODEM Interrupt Flag */ +#define MA35_ISR_RXTO_IF BIT(4) /* RX Time-out Interrupt Flag */ +#define MA35_ISR_BUFEIF BIT(5) /* Buffer Error Interrupt Flag */ +#define MA35_ISR_WK_IF BIT(6) /* UART Wake-up Interrupt Flag */ +#define MA35_ISR_RDAINT BIT(8) /* RBR Available Interrupt Indicator */ +#define MA35_ISR_THRE_INT BIT(9) /* THR Empty Interrupt Indicator */ +#define MA35_ISR_ALL 0xFFFFFFFF + +/* MA35_BAUD_REG - Baud Rate Divider Register */ +#define MA35_BAUD_MODE_MASK GENMASK(29, 28) +#define MA35_BAUD_MODE0 FIELD_PREP(MA35_BAUD_MODE_MASK, 0) +#define MA35_BAUD_MODE1 FIELD_PREP(MA35_BAUD_MODE_MASK, 2) +#define MA35_BAUD_MODE2 FIELD_PREP(MA35_BAUD_MODE_MASK, 3) +#define MA35_BAUD_MASK GENMASK(15, 0) + +/* MA35_ALTCTL_REG - Alternate Control/Status Register */ +#define MA35_ALTCTL_RS485AUD BIT(10) /* RS-485 Auto Direction Function */ + +/* MA35_FUN_SEL_REG - Function Select Register */ +#define MA35_FUN_SEL_MASK GENMASK(2, 0) +#define MA35_FUN_SEL_UART FIELD_PREP(MA35_FUN_SEL_MASK, 0) +#define MA35_FUN_SEL_RS485 FIELD_PREP(MA35_FUN_SEL_MASK, 3) + +/* The constrain for MA35D1 UART baud rate divider */ +#define MA35_BAUD_DIV_MAX 0xFFFF +#define MA35_BAUD_DIV_MIN 11 + +/* UART FIFO depth */ +#define MA35_UART_FIFO_DEPTH 32 +/* UART console clock */ +#define MA35_UART_CONSOLE_CLK (24 * HZ_PER_MHZ) +/* UART register ioremap size */ +#define MA35_UART_REG_SIZE 0x100 +/* Rx Timeout */ +#define MA35_UART_RX_TOUT 0x40 + +#define MA35_IER_CONFIG (MA35_IER_RTO_IEN | MA35_IER_RDA_IEN | \ + MA35_IER_TIME_OUT_EN | MA35_IER_BUFERR_IEN) + +#define MA35_ISR_IF_CHECK (MA35_ISR_RDA_IF | MA35_ISR_RXTO_IF | \ + MA35_ISR_THRE_INT | MA35_ISR_BUFEIF) + +#define MA35_FSR_TX_BOTH_EMPTY (MA35_FSR_TE_FLAG | MA35_FSR_TX_EMPTY) + +static struct uart_driver ma35d1serial_reg; + +struct uart_ma35d1_port { + struct uart_port port; + struct clk *clk; + u16 capabilities; /* port capabilities */ + u8 ier; + u8 lcr; + u8 mcr; + u32 baud_rate; + u32 console_baud_rate; + u32 console_line; + u32 console_int; +}; + +static struct uart_ma35d1_port ma35d1serial_ports[MA35_UART_NR]; + +static struct uart_ma35d1_port *to_ma35d1_uart_port(struct uart_port *uart) +{ + return container_of(uart, struct uart_ma35d1_port, port); +} + +static u32 serial_in(struct uart_ma35d1_port *p, u32 offset) +{ + return readl_relaxed(p->port.membase + offset); +} + +static void serial_out(struct uart_ma35d1_port *p, u32 offset, u32 value) +{ + writel_relaxed(value, p->port.membase + offset); +} + +static void __stop_tx(struct uart_ma35d1_port *p) +{ + u32 ier; + + ier = serial_in(p, MA35_IER_REG); + if (ier & MA35_IER_THRE_IEN) + serial_out(p, MA35_IER_REG, ier & ~MA35_IER_THRE_IEN); +} + +static void ma35d1serial_stop_tx(struct uart_port *port) +{ + struct uart_ma35d1_port *up = to_ma35d1_uart_port(port); + + __stop_tx(up); +} + +static void transmit_chars(struct uart_ma35d1_port *up) +{ + u32 count; + u8 ch; + + if (uart_tx_stopped(&up->port)) { + ma35d1serial_stop_tx(&up->port); + return; + } + count = MA35_UART_FIFO_DEPTH - FIELD_GET(MA35_FSR_TXPTR_MSK, + serial_in(up, MA35_FSR_REG)); + uart_port_tx_limited(&up->port, ch, count, + !(serial_in(up, MA35_FSR_REG) & MA35_FSR_TX_FULL), + serial_out(up, MA35_THR_REG, ch), + ({})); +} + +static void ma35d1serial_start_tx(struct uart_port *port) +{ + struct uart_ma35d1_port *up = to_ma35d1_uart_port(port); + u32 ier; + + ier = serial_in(up, MA35_IER_REG); + serial_out(up, MA35_IER_REG, ier & ~MA35_IER_THRE_IEN); + transmit_chars(up); + serial_out(up, MA35_IER_REG, ier | MA35_IER_THRE_IEN); +} + +static void ma35d1serial_stop_rx(struct uart_port *port) +{ + struct uart_ma35d1_port *up = to_ma35d1_uart_port(port); + u32 ier; + + ier = serial_in(up, MA35_IER_REG); + ier &= ~MA35_IER_RDA_IEN; + serial_out(up, MA35_IER_REG, ier); +} + +static void receive_chars(struct uart_ma35d1_port *up) +{ + int max_count = 256; + u8 ch, flag; + u32 fsr; + + fsr = serial_in(up, MA35_FSR_REG); + do { + flag = TTY_NORMAL; + up->port.icount.rx++; + + if (unlikely(fsr & (MA35_FSR_BIF | MA35_FSR_FEF | + MA35_FSR_PEF | MA35_FSR_RX_OVER_IF))) { + if (fsr & MA35_FSR_BIF) { + up->port.icount.brk++; + if (uart_handle_break(&up->port)) + continue; + } + if (fsr & MA35_FSR_FEF) + up->port.icount.frame++; + if (fsr & MA35_FSR_PEF) + up->port.icount.parity++; + if (fsr & MA35_FSR_RX_OVER_IF) + up->port.icount.overrun++; + + serial_out(up, MA35_FSR_REG, + fsr & (MA35_FSR_BIF | MA35_FSR_FEF | + MA35_FSR_PEF | MA35_FSR_RX_OVER_IF)); + if (fsr & MA35_FSR_BIF) + flag = TTY_BREAK; + else if (fsr & MA35_FSR_PEF) + flag = TTY_PARITY; + else if (fsr & MA35_FSR_FEF) + flag = TTY_FRAME; + } + + ch = serial_in(up, MA35_RBR_REG); + if (uart_handle_sysrq_char(&up->port, ch)) + continue; + + spin_lock(&up->port.lock); + uart_insert_char(&up->port, fsr, MA35_FSR_RX_OVER_IF, ch, flag); + spin_unlock(&up->port.lock); + + fsr = serial_in(up, MA35_FSR_REG); + } while (!(fsr & MA35_FSR_RX_EMPTY) && (max_count-- > 0)); + + spin_lock(&up->port.lock); + tty_flip_buffer_push(&up->port.state->port); + spin_unlock(&up->port.lock); +} + +static irqreturn_t ma35d1serial_interrupt(int irq, void *dev_id) +{ + struct uart_port *port = dev_id; + struct uart_ma35d1_port *up = to_ma35d1_uart_port(port); + u32 isr, fsr; + + isr = serial_in(up, MA35_ISR_REG); + fsr = serial_in(up, MA35_FSR_REG); + + if (!(isr & MA35_ISR_IF_CHECK)) + return IRQ_NONE; + + if (isr & (MA35_ISR_RDA_IF | MA35_ISR_RXTO_IF)) + receive_chars(up); + if (isr & MA35_ISR_THRE_INT) + transmit_chars(up); + if (fsr & MA35_FSR_TX_OVER_IF) + serial_out(up, MA35_FSR_REG, MA35_FSR_TX_OVER_IF); + + return IRQ_HANDLED; +} + +static u32 ma35d1serial_tx_empty(struct uart_port *port) +{ + struct uart_ma35d1_port *up = to_ma35d1_uart_port(port); + u32 fsr; + + fsr = serial_in(up, MA35_FSR_REG); + if ((fsr & MA35_FSR_TX_BOTH_EMPTY) == MA35_FSR_TX_BOTH_EMPTY) + return TIOCSER_TEMT; + else + return 0; +} + +static u32 ma35d1serial_get_mctrl(struct uart_port *port) +{ + struct uart_ma35d1_port *up = to_ma35d1_uart_port(port); + u32 status; + u32 ret = 0; + + status = serial_in(up, MA35_MSR_REG); + if (!(status & MA35_MSR_CTSSTS)) + ret |= TIOCM_CTS; + return ret; +} + +static void ma35d1serial_set_mctrl(struct uart_port *port, u32 mctrl) +{ + struct uart_ma35d1_port *up = to_ma35d1_uart_port(port); + u32 mcr, msr, ier; + + mcr = serial_in(up, MA35_MCR_REG); + mcr &= ~MA35_MCR_RTS_CTRL; + + if (mctrl & TIOCM_RTS) + mcr |= MA35_MCR_RTSACTLV; + else + mcr &= ~MA35_MCR_RTSACTLV; + + if (up->mcr & UART_MCR_AFE) { + ier = serial_in(up, MA35_IER_REG); + ier |= MA35_IER_AUTO_RTS | MA35_IER_AUTO_CTS; + serial_out(up, MA35_IER_REG, ier); + up->port.flags |= UPF_HARD_FLOW; + } else { + ier = serial_in(up, MA35_IER_REG); + ier &= ~(MA35_IER_AUTO_RTS | MA35_IER_AUTO_CTS); + serial_out(up, MA35_IER_REG, ier); + up->port.flags &= ~UPF_HARD_FLOW; + } + + msr = serial_in(up, MA35_MSR_REG); + msr |= MA35_MSR_CTSACTLV; + serial_out(up, MA35_MSR_REG, msr); + serial_out(up, MA35_MCR_REG, mcr); +} + +static void ma35d1serial_break_ctl(struct uart_port *port, int break_state) +{ + struct uart_ma35d1_port *up = to_ma35d1_uart_port(port); + unsigned long flags; + u32 lcr; + + spin_lock_irqsave(&up->port.lock, flags); + lcr = serial_in(up, MA35_LCR_REG); + if (break_state != 0) + lcr |= MA35_LCR_BREAK; + else + lcr &= ~MA35_LCR_BREAK; + serial_out(up, MA35_LCR_REG, lcr); + spin_unlock_irqrestore(&up->port.lock, flags); +} + +static int ma35d1serial_startup(struct uart_port *port) +{ + struct uart_ma35d1_port *up = to_ma35d1_uart_port(port); + u32 fcr; + int retval; + + /* Reset FIFO */ + serial_out(up, MA35_FCR_REG, MA35_FCR_TFR | MA35_FCR_RFR); + + /* Clear pending interrupts */ + serial_out(up, MA35_ISR_REG, MA35_ISR_ALL); + + retval = request_irq(port->irq, ma35d1serial_interrupt, 0, + dev_name(port->dev), port); + if (retval) { + dev_err(up->port.dev, "request irq failed.\n"); + return retval; + } + + fcr = serial_in(up, MA35_FCR_REG); + fcr |= MA35_FCR_RFITL_4BYTES | MA35_FCR_RTSTL_8BYTES; + serial_out(up, MA35_FCR_REG, fcr); + serial_out(up, MA35_LCR_REG, MA35_LCR_WLS_8BITS); + serial_out(up, MA35_TOR_REG, MA35_UART_RX_TOUT); + serial_out(up, MA35_IER_REG, MA35_IER_CONFIG); + return 0; +} + +static void ma35d1serial_shutdown(struct uart_port *port) +{ + struct uart_ma35d1_port *up = to_ma35d1_uart_port(port); + + serial_out(up, MA35_IER_REG, 0); + free_irq(port->irq, port); +} + +static void ma35d1serial_set_termios(struct uart_port *port, + struct ktermios *termios, + const struct ktermios *old) +{ + struct uart_ma35d1_port *up = to_ma35d1_uart_port(port); + unsigned long flags; + u32 baud, quot; + u32 lcr = 0; + + lcr = UART_LCR_WLEN(tty_get_char_size(termios->c_cflag)); + + if (termios->c_cflag & CSTOPB) + lcr |= MA35_LCR_NSB; + if (termios->c_cflag & PARENB) + lcr |= MA35_LCR_PBE; + if (!(termios->c_cflag & PARODD)) + lcr |= MA35_LCR_EPE; + if (termios->c_cflag & CMSPAR) + lcr |= MA35_LCR_SPE; + + baud = uart_get_baud_rate(port, termios, old, + port->uartclk / MA35_BAUD_DIV_MAX, + port->uartclk / MA35_BAUD_DIV_MIN); + + /* MA35D1 UART baud rate equation: baudrate = UART_CLK / (quot + 2) */ + quot = (port->uartclk / baud) - 2; + + /* + * Ok, we're now changing the port state. Do it with + * interrupts disabled. + */ + spin_lock_irqsave(&up->port.lock, flags); + + up->port.read_status_mask = MA35_FSR_RX_OVER_IF; + if (termios->c_iflag & INPCK) + up->port.read_status_mask |= MA35_FSR_FEF | MA35_FSR_PEF; + if (termios->c_iflag & (BRKINT | PARMRK)) + up->port.read_status_mask |= MA35_FSR_BIF; + + /* Characteres to ignore */ + up->port.ignore_status_mask = 0; + if (termios->c_iflag & IGNPAR) + up->port.ignore_status_mask |= MA35_FSR_FEF | MA35_FSR_PEF; + if (termios->c_iflag & IGNBRK) { + up->port.ignore_status_mask |= MA35_FSR_BIF; + /* + * If we're ignoring parity and break indicators, + * ignore overruns too (for real raw support). + */ + if (termios->c_iflag & IGNPAR) + up->port.ignore_status_mask |= MA35_FSR_RX_OVER_IF; + } + if (termios->c_cflag & CRTSCTS) + up->mcr |= UART_MCR_AFE; + else + up->mcr &= ~UART_MCR_AFE; + + uart_update_timeout(port, termios->c_cflag, baud); + + ma35d1serial_set_mctrl(&up->port, up->port.mctrl); + + serial_out(up, MA35_BAUD_REG, MA35_BAUD_MODE2 | FIELD_PREP(MA35_BAUD_MASK, quot)); + + serial_out(up, MA35_LCR_REG, lcr); + + spin_unlock_irqrestore(&up->port.lock, flags); +} + +static const char *ma35d1serial_type(struct uart_port *port) +{ + return "ma35d1-uart"; +} + +static void ma35d1serial_config_port(struct uart_port *port, int flags) +{ + /* + * Driver core for serial ports forces a non-zero value for port type. + * Write an arbitrary value here to accommodate the serial core driver, + * as ID part of UAPI is redundant. + */ + port->type = 1; +} + +static int ma35d1serial_verify_port(struct uart_port *port, struct serial_struct *ser) +{ + if (port->type != PORT_UNKNOWN && ser->type != 1) + return -EINVAL; + + return 0; +} + +static const struct uart_ops ma35d1serial_ops = { + .tx_empty = ma35d1serial_tx_empty, + .set_mctrl = ma35d1serial_set_mctrl, + .get_mctrl = ma35d1serial_get_mctrl, + .stop_tx = ma35d1serial_stop_tx, + .start_tx = ma35d1serial_start_tx, + .stop_rx = ma35d1serial_stop_rx, + .break_ctl = ma35d1serial_break_ctl, + .startup = ma35d1serial_startup, + .shutdown = ma35d1serial_shutdown, + .set_termios = ma35d1serial_set_termios, + .type = ma35d1serial_type, + .config_port = ma35d1serial_config_port, + .verify_port = ma35d1serial_verify_port, +}; + +static const struct of_device_id ma35d1_serial_of_match[] = { + { .compatible = "nuvoton,ma35d1-uart" }, + {}, +}; +MODULE_DEVICE_TABLE(of, ma35d1_serial_of_match); + +#ifdef CONFIG_SERIAL_NUVOTON_MA35D1_CONSOLE + +static struct device_node *ma35d1serial_uart_nodes[MA35_UART_NR]; + +static void wait_for_xmitr(struct uart_ma35d1_port *up) +{ + unsigned int reg = 0; + + read_poll_timeout_atomic(serial_in, reg, reg & MA35_FSR_TX_EMPTY, + 1, 10000, false, + up, MA35_FSR_REG); +} + +static void ma35d1serial_console_putchar(struct uart_port *port, unsigned char ch) +{ + struct uart_ma35d1_port *up = to_ma35d1_uart_port(port); + + wait_for_xmitr(up); + serial_out(up, MA35_THR_REG, ch); +} + +/* + * Print a string to the serial port trying not to disturb + * any possible real use of the port... + * + * The console_lock must be held when we get here. + */ +static void ma35d1serial_console_write(struct console *co, const char *s, u32 count) +{ + struct uart_ma35d1_port *up = &ma35d1serial_ports[co->index]; + unsigned long flags; + int locked = 1; + u32 ier; + + if (up->port.sysrq) + locked = 0; + else if (oops_in_progress) + locked = spin_trylock_irqsave(&up->port.lock, flags); + else + spin_lock_irqsave(&up->port.lock, flags); + + /* + * First save the IER then disable the interrupts + */ + ier = serial_in(up, MA35_IER_REG); + serial_out(up, MA35_IER_REG, 0); + + uart_console_write(&up->port, s, count, ma35d1serial_console_putchar); + + wait_for_xmitr(up); + serial_out(up, MA35_IER_REG, ier); + + if (locked) + spin_unlock_irqrestore(&up->port.lock, flags); +} + +static int __init ma35d1serial_console_setup(struct console *co, char *options) +{ + struct device_node *np; + struct uart_ma35d1_port *p; + u32 val32[4]; + struct uart_port *port; + int baud = 115200; + int bits = 8; + int parity = 'n'; + int flow = 'n'; + + if ((co->index < 0) || (co->index >= MA35_UART_NR)) { + pr_debug("Console Port%x out of range\n", co->index); + return -EINVAL; + } + + np = ma35d1serial_uart_nodes[co->index]; + p = &ma35d1serial_ports[co->index]; + if (!np || !p) + return -ENODEV; + + if (of_property_read_u32_array(np, "reg", val32, ARRAY_SIZE(val32)) != 0) + return -EINVAL; + + p->port.iobase = val32[1]; + p->port.membase = ioremap(p->port.iobase, MA35_UART_REG_SIZE); + if (!p->port.membase) + return -ENOMEM; + + p->port.ops = &ma35d1serial_ops; + p->port.line = 0; + p->port.uartclk = MA35_UART_CONSOLE_CLK; + + port = &ma35d1serial_ports[co->index].port; + + if (options) + uart_parse_options(options, &baud, &parity, &bits, &flow); + + return uart_set_options(port, co, baud, parity, bits, flow); +} + +static struct console ma35d1serial_console = { + .name = "ttyNVT", + .write = ma35d1serial_console_write, + .device = uart_console_device, + .setup = ma35d1serial_console_setup, + .flags = CON_PRINTBUFFER | CON_ENABLED, + .index = -1, + .data = &ma35d1serial_reg, +}; + +static void ma35d1serial_console_init_port(void) +{ + u32 i = 0; + struct device_node *np; + + for_each_matching_node(np, ma35d1_serial_of_match) { + if (ma35d1serial_uart_nodes[i] == NULL) { + of_node_get(np); + ma35d1serial_uart_nodes[i] = np; + i++; + if (i == MA35_UART_NR) + break; + } + } +} + +static int __init ma35d1serial_console_init(void) +{ + ma35d1serial_console_init_port(); + register_console(&ma35d1serial_console); + return 0; +} +console_initcall(ma35d1serial_console_init); + +#define MA35D1SERIAL_CONSOLE (&ma35d1serial_console) +#else +#define MA35D1SERIAL_CONSOLE NULL +#endif + +static struct uart_driver ma35d1serial_reg = { + .owner = THIS_MODULE, + .driver_name = "serial", + .dev_name = "ttyNVT", + .major = TTY_MAJOR, + .minor = 64, + .cons = MA35D1SERIAL_CONSOLE, + .nr = MA35_UART_NR, +}; + +/* + * Register a set of serial devices attached to a platform device. + * The list is terminated with a zero flags entry, which means we expect + * all entries to have at least UPF_BOOT_AUTOCONF set. + */ +static int ma35d1serial_probe(struct platform_device *pdev) +{ + struct resource *res_mem; + struct uart_ma35d1_port *up; + int ret = 0; + + if (pdev->dev.of_node) { + ret = of_alias_get_id(pdev->dev.of_node, "serial"); + if (ret < 0) { + dev_err(&pdev->dev, "failed to get alias/pdev id, errno %d\n", ret); + return ret; + } + } + up = &ma35d1serial_ports[ret]; + up->port.line = ret; + res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res_mem) + return -ENODEV; + + up->port.iobase = res_mem->start; + up->port.membase = ioremap(up->port.iobase, MA35_UART_REG_SIZE); + up->port.ops = &ma35d1serial_ops; + + spin_lock_init(&up->port.lock); + + up->clk = of_clk_get(pdev->dev.of_node, 0); + if (IS_ERR(up->clk)) { + ret = PTR_ERR(up->clk); + dev_err(&pdev->dev, "failed to get core clk: %d\n", ret); + goto err_iounmap; + } + + ret = clk_prepare_enable(up->clk); + if (ret) + goto err_iounmap; + + if (up->port.line != 0) + up->port.uartclk = clk_get_rate(up->clk); + + ret = platform_get_irq(pdev, 0); + if (ret < 0) + goto err_clk_disable; + + up->port.irq = ret; + up->port.dev = &pdev->dev; + up->port.flags = UPF_BOOT_AUTOCONF; + + platform_set_drvdata(pdev, up); + + ret = uart_add_one_port(&ma35d1serial_reg, &up->port); + if (ret < 0) + goto err_free_irq; + + return 0; + +err_free_irq: + free_irq(up->port.irq, &up->port); + +err_clk_disable: + clk_disable_unprepare(up->clk); + +err_iounmap: + iounmap(up->port.membase); + return ret; +} + +/* + * Remove serial ports registered against a platform device. + */ +static int ma35d1serial_remove(struct platform_device *dev) +{ + struct uart_port *port = platform_get_drvdata(dev); + struct uart_ma35d1_port *up = to_ma35d1_uart_port(port); + + uart_remove_one_port(&ma35d1serial_reg, port); + clk_disable_unprepare(up->clk); + return 0; +} + +static int ma35d1serial_suspend(struct platform_device *dev, pm_message_t state) +{ + struct uart_port *port = platform_get_drvdata(dev); + struct uart_ma35d1_port *up = to_ma35d1_uart_port(port); + + uart_suspend_port(&ma35d1serial_reg, &up->port); + if (up->port.line == 0) { + up->console_baud_rate = serial_in(up, MA35_BAUD_REG); + up->console_line = serial_in(up, MA35_LCR_REG); + up->console_int = serial_in(up, MA35_IER_REG); + } + return 0; +} + +static int ma35d1serial_resume(struct platform_device *dev) +{ + struct uart_port *port = platform_get_drvdata(dev); + struct uart_ma35d1_port *up = to_ma35d1_uart_port(port); + + if (up->port.line == 0) { + serial_out(up, MA35_BAUD_REG, up->console_baud_rate); + serial_out(up, MA35_LCR_REG, up->console_line); + serial_out(up, MA35_IER_REG, up->console_int); + } + uart_resume_port(&ma35d1serial_reg, &up->port); + return 0; +} + +static struct platform_driver ma35d1serial_driver = { + .probe = ma35d1serial_probe, + .remove = ma35d1serial_remove, + .suspend = ma35d1serial_suspend, + .resume = ma35d1serial_resume, + .driver = { + .name = "ma35d1-uart", + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(ma35d1_serial_of_match), + }, +}; + +static int __init ma35d1serial_init(void) +{ + int ret; + + ret = uart_register_driver(&ma35d1serial_reg); + if (ret) + return ret; + + ret = platform_driver_register(&ma35d1serial_driver); + if (ret) + uart_unregister_driver(&ma35d1serial_reg); + + return ret; +} + +static void __exit ma35d1serial_exit(void) +{ + platform_driver_unregister(&ma35d1serial_driver); + uart_unregister_driver(&ma35d1serial_reg); +} + +module_init(ma35d1serial_init); +module_exit(ma35d1serial_exit); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("MA35D1 serial driver"); diff --git a/drivers/tty/serial/max310x.c b/drivers/tty/serial/max310x.c index 9fee722058f434ab5254e18c42b99d1ac99cac19..997e394497663742b93b21373b8b3a8c027d78de 100644 --- a/drivers/tty/serial/max310x.c +++ b/drivers/tty/serial/max310x.c @@ -1636,7 +1636,7 @@ static struct i2c_driver max310x_i2c_driver = { .of_match_table = max310x_dt_ids, .pm = &max310x_pm_ops, }, - .probe_new = max310x_i2c_probe, + .probe = max310x_i2c_probe, .remove = max310x_i2c_remove, }; #endif diff --git a/drivers/tty/serial/qcom_geni_serial.c b/drivers/tty/serial/qcom_geni_serial.c index 8582479f0211a082cfe1209dcee1aacc3cdc1459..444c74eeab7de2f6f77301f57eff45cd281fb1ef 100644 --- a/drivers/tty/serial/qcom_geni_serial.c +++ b/drivers/tty/serial/qcom_geni_serial.c @@ -1053,6 +1053,11 @@ static int setup_fifos(struct qcom_geni_serial_port *port) (port->tx_fifo_depth * port->tx_fifo_width) / BITS_PER_BYTE; if (port->rx_buf && (old_rx_fifo_depth != port->rx_fifo_depth) && port->rx_fifo_depth) { + /* + * Use krealloc rather than krealloc_array because rx_buf is + * accessed as 1 byte entries as well as 4 byte entries so it's + * not necessarily an array. + */ port->rx_buf = devm_krealloc(uport->dev, port->rx_buf, port->rx_fifo_depth * sizeof(u32), GFP_KERNEL); diff --git a/drivers/tty/serial/samsung_tty.c b/drivers/tty/serial/samsung_tty.c index 2a7520ad3abd92112c4a94b6da7e1f5085257b70..b29e9dfd81a688b9e4c210c55d8f3b4e1cc57bda 100644 --- a/drivers/tty/serial/samsung_tty.c +++ b/drivers/tty/serial/samsung_tty.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -1459,8 +1460,12 @@ static unsigned int s3c24xx_serial_getclk(struct s3c24xx_uart_port *ourport, continue; rate = clk_get_rate(clk); - if (!rate) + if (!rate) { + dev_err(ourport->port.dev, + "Failed to get clock rate for %s.\n", clkname); + clk_put(clk); continue; + } if (ourport->info->has_divslot) { unsigned long div = rate / req_baud; @@ -1481,15 +1486,21 @@ static unsigned int s3c24xx_serial_getclk(struct s3c24xx_uart_port *ourport, } quot--; - calc_deviation = req_baud - baud; - if (calc_deviation < 0) - calc_deviation = -calc_deviation; + calc_deviation = abs(req_baud - baud); if (calc_deviation < deviation) { + /* + * If we find a better clk, release the previous one, if + * any. + */ + if (!IS_ERR(*best_clk)) + clk_put(*best_clk); *best_clk = clk; best_quot = quot; *clk_num = cnt; deviation = calc_deviation; + } else { + clk_put(clk); } } diff --git a/drivers/tty/serial/sc16is7xx.c b/drivers/tty/serial/sc16is7xx.c index abad091baeeaef273d3e923bd168f51a1f9435ac..2e7e7c409cf2e06b8edcceeab1efe9efe245b25c 100644 --- a/drivers/tty/serial/sc16is7xx.c +++ b/drivers/tty/serial/sc16is7xx.c @@ -1709,7 +1709,7 @@ static struct i2c_driver sc16is7xx_i2c_uart_driver = { .name = SC16IS7XX_NAME, .of_match_table = sc16is7xx_dt_ids, }, - .probe_new = sc16is7xx_i2c_probe, + .probe = sc16is7xx_i2c_probe, .remove = sc16is7xx_i2c_remove, .id_table = sc16is7xx_i2c_id_table, }; diff --git a/drivers/tty/serial/serial_base.h b/drivers/tty/serial/serial_base.h new file mode 100644 index 0000000000000000000000000000000000000000..9faac0ff6b8957dff48546f48c056396a3d4bcf6 --- /dev/null +++ b/drivers/tty/serial/serial_base.h @@ -0,0 +1,46 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Serial core related functions, serial port device drivers do not need this. + * + * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/ + * Author: Tony Lindgren + */ + +#define to_serial_base_ctrl_device(d) container_of((d), struct serial_ctrl_device, dev) +#define to_serial_base_port_device(d) container_of((d), struct serial_port_device, dev) + +struct uart_driver; +struct uart_port; +struct device_driver; +struct device; + +struct serial_ctrl_device { + struct device dev; +}; + +struct serial_port_device { + struct device dev; + struct uart_port *port; +}; + +int serial_base_ctrl_init(void); +void serial_base_ctrl_exit(void); + +int serial_base_port_init(void); +void serial_base_port_exit(void); + +int serial_base_driver_register(struct device_driver *driver); +void serial_base_driver_unregister(struct device_driver *driver); + +struct serial_ctrl_device *serial_base_ctrl_add(struct uart_port *port, + struct device *parent); +struct serial_port_device *serial_base_port_add(struct uart_port *port, + struct serial_ctrl_device *parent); +void serial_base_ctrl_device_remove(struct serial_ctrl_device *ctrl_dev); +void serial_base_port_device_remove(struct serial_port_device *port_dev); + +int serial_ctrl_register_port(struct uart_driver *drv, struct uart_port *port); +void serial_ctrl_unregister_port(struct uart_driver *drv, struct uart_port *port); + +int serial_core_register_port(struct uart_driver *drv, struct uart_port *port); +void serial_core_unregister_port(struct uart_driver *drv, struct uart_port *port); diff --git a/drivers/tty/serial/serial_base_bus.c b/drivers/tty/serial/serial_base_bus.c new file mode 100644 index 0000000000000000000000000000000000000000..6ff59c89d867d0cb73f7a00ad2729dc98cbd7621 --- /dev/null +++ b/drivers/tty/serial/serial_base_bus.c @@ -0,0 +1,205 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Serial base bus layer for controllers + * + * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/ + * Author: Tony Lindgren + * + * The serial core bus manages the serial core controller instances. + */ + +#include +#include +#include +#include +#include +#include + +#include "serial_base.h" + +static bool serial_base_initialized; + +static int serial_base_match(struct device *dev, struct device_driver *drv) +{ + int len = strlen(drv->name); + + return !strncmp(dev_name(dev), drv->name, len); +} + +static struct bus_type serial_base_bus_type = { + .name = "serial-base", + .match = serial_base_match, +}; + +int serial_base_driver_register(struct device_driver *driver) +{ + driver->bus = &serial_base_bus_type; + + return driver_register(driver); +} + +void serial_base_driver_unregister(struct device_driver *driver) +{ + driver_unregister(driver); +} + +static int serial_base_device_init(struct uart_port *port, + struct device *dev, + struct device *parent_dev, + const struct device_type *type, + void (*release)(struct device *dev), + int id) +{ + device_initialize(dev); + dev->type = type; + dev->parent = parent_dev; + dev->bus = &serial_base_bus_type; + dev->release = release; + + if (!serial_base_initialized) { + dev_dbg(port->dev, "uart_add_one_port() called before arch_initcall()?\n"); + return -EPROBE_DEFER; + } + + return dev_set_name(dev, "%s.%s.%d", type->name, dev_name(port->dev), id); +} + +static const struct device_type serial_ctrl_type = { + .name = "ctrl", +}; + +static void serial_base_ctrl_release(struct device *dev) +{ + struct serial_ctrl_device *ctrl_dev = to_serial_base_ctrl_device(dev); + + kfree(ctrl_dev); +} + +void serial_base_ctrl_device_remove(struct serial_ctrl_device *ctrl_dev) +{ + if (!ctrl_dev) + return; + + device_del(&ctrl_dev->dev); +} + +struct serial_ctrl_device *serial_base_ctrl_add(struct uart_port *port, + struct device *parent) +{ + struct serial_ctrl_device *ctrl_dev; + int err; + + ctrl_dev = kzalloc(sizeof(*ctrl_dev), GFP_KERNEL); + if (!ctrl_dev) + return ERR_PTR(-ENOMEM); + + err = serial_base_device_init(port, &ctrl_dev->dev, + parent, &serial_ctrl_type, + serial_base_ctrl_release, + port->ctrl_id); + if (err) + goto err_put_device; + + err = device_add(&ctrl_dev->dev); + if (err) + goto err_put_device; + + return ctrl_dev; + +err_put_device: + put_device(&ctrl_dev->dev); + + return ERR_PTR(err); +} + +static const struct device_type serial_port_type = { + .name = "port", +}; + +static void serial_base_port_release(struct device *dev) +{ + struct serial_port_device *port_dev = to_serial_base_port_device(dev); + + kfree(port_dev); +} + +struct serial_port_device *serial_base_port_add(struct uart_port *port, + struct serial_ctrl_device *ctrl_dev) +{ + struct serial_port_device *port_dev; + int err; + + port_dev = kzalloc(sizeof(*port_dev), GFP_KERNEL); + if (!port_dev) + return ERR_PTR(-ENOMEM); + + err = serial_base_device_init(port, &port_dev->dev, + &ctrl_dev->dev, &serial_port_type, + serial_base_port_release, + port->line); + if (err) + goto err_put_device; + + port_dev->port = port; + + err = device_add(&port_dev->dev); + if (err) + goto err_put_device; + + return port_dev; + +err_put_device: + put_device(&port_dev->dev); + + return ERR_PTR(err); +} + +void serial_base_port_device_remove(struct serial_port_device *port_dev) +{ + if (!port_dev) + return; + + device_del(&port_dev->dev); +} + +static int serial_base_init(void) +{ + int ret; + + ret = bus_register(&serial_base_bus_type); + if (ret) + return ret; + + ret = serial_base_ctrl_init(); + if (ret) + goto err_bus_unregister; + + ret = serial_base_port_init(); + if (ret) + goto err_ctrl_exit; + + serial_base_initialized = true; + + return 0; + +err_ctrl_exit: + serial_base_ctrl_exit(); + +err_bus_unregister: + bus_unregister(&serial_base_bus_type); + + return ret; +} +arch_initcall(serial_base_init); + +static void serial_base_exit(void) +{ + serial_base_port_exit(); + serial_base_ctrl_exit(); + bus_unregister(&serial_base_bus_type); +} +module_exit(serial_base_exit); + +MODULE_AUTHOR("Tony Lindgren "); +MODULE_DESCRIPTION("Serial core bus"); +MODULE_LICENSE("GPL"); diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 54e82f476a2ccfed4cca941fd5a0bb8e497463d5..831d033611e61b77862b46ec69e1bcdcaba79d86 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -31,6 +32,8 @@ #include #include +#include "serial_base.h" + /* * This is used to lock changes in serial line configuration. */ @@ -134,9 +137,30 @@ static void __uart_start(struct tty_struct *tty) { struct uart_state *state = tty->driver_data; struct uart_port *port = state->uart_port; + struct serial_port_device *port_dev; + int err; + + if (!port || port->flags & UPF_DEAD || uart_tx_stopped(port)) + return; + + port_dev = port->port_dev; + + /* Increment the runtime PM usage count for the active check below */ + err = pm_runtime_get(&port_dev->dev); + if (err < 0) { + pm_runtime_put_noidle(&port_dev->dev); + return; + } - if (port && !(port->flags & UPF_DEAD) && !uart_tx_stopped(port)) + /* + * Start TX if enabled, and kick runtime PM. If the device is not + * enabled, serial_port_runtime_resume() calls start_tx() again + * after enabling the device. + */ + if (pm_runtime_active(&port_dev->dev)) port->ops->start_tx(port); + pm_runtime_mark_last_busy(&port_dev->dev); + pm_runtime_put_autosuspend(&port_dev->dev); } static void uart_start(struct tty_struct *tty) @@ -2333,8 +2357,11 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *uport) * able to Re-start_rx later. */ if (!console_suspend_enabled && uart_console(uport)) { - if (uport->ops->start_rx) + if (uport->ops->start_rx) { + spin_lock_irq(&uport->lock); uport->ops->stop_rx(uport); + spin_unlock_irq(&uport->lock); + } goto unlock; } @@ -2427,8 +2454,11 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *uport) if (console_suspend_enabled) uart_change_pm(state, UART_PM_STATE_ON); uport->ops->set_termios(uport, &termios, NULL); - if (!console_suspend_enabled && uport->ops->start_rx) + if (!console_suspend_enabled && uport->ops->start_rx) { + spin_lock_irq(&uport->lock); uport->ops->start_rx(uport); + spin_unlock_irq(&uport->lock); + } if (console_suspend_enabled) console_start(uport->cons); } @@ -3042,7 +3072,7 @@ static const struct attribute_group tty_dev_attr_group = { }; /** - * uart_add_one_port - attach a driver-defined port structure + * serial_core_add_one_port - attach a driver-defined port structure * @drv: pointer to the uart low level driver structure for this port * @uport: uart port structure to use for this port. * @@ -3051,8 +3081,9 @@ static const struct attribute_group tty_dev_attr_group = { * This allows the driver @drv to register its own uart_port structure with the * core driver. The main purpose is to allow the low level uart drivers to * expand uart_port, rather than having yet more levels of structures. + * Caller must hold port_mutex. */ -int uart_add_one_port(struct uart_driver *drv, struct uart_port *uport) +static int serial_core_add_one_port(struct uart_driver *drv, struct uart_port *uport) { struct uart_state *state; struct tty_port *port; @@ -3066,7 +3097,6 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *uport) state = drv->state + uport->line; port = &state->port; - mutex_lock(&port_mutex); mutex_lock(&port->mutex); if (state->uart_port) { ret = -EINVAL; @@ -3131,21 +3161,14 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *uport) uport->line); } - /* - * Ensure UPF_DEAD is not set. - */ - uport->flags &= ~UPF_DEAD; - out: mutex_unlock(&port->mutex); - mutex_unlock(&port_mutex); return ret; } -EXPORT_SYMBOL(uart_add_one_port); /** - * uart_remove_one_port - detach a driver defined port structure + * serial_core_remove_one_port - detach a driver defined port structure * @drv: pointer to the uart low level driver structure for this port * @uport: uart port structure for this port * @@ -3153,21 +3176,16 @@ EXPORT_SYMBOL(uart_add_one_port); * * This unhooks (and hangs up) the specified port structure from the core * driver. No further calls will be made to the low-level code for this port. + * Caller must hold port_mutex. */ -int uart_remove_one_port(struct uart_driver *drv, struct uart_port *uport) +static void serial_core_remove_one_port(struct uart_driver *drv, + struct uart_port *uport) { struct uart_state *state = drv->state + uport->line; struct tty_port *port = &state->port; struct uart_port *uart_port; struct tty_struct *tty; - int ret = 0; - - mutex_lock(&port_mutex); - /* - * Mark the port "dead" - this prevents any opens from - * succeeding while we shut down the port. - */ mutex_lock(&port->mutex); uart_port = uart_port_check(state); if (uart_port != uport) @@ -3176,10 +3194,8 @@ int uart_remove_one_port(struct uart_driver *drv, struct uart_port *uport) if (!uart_port) { mutex_unlock(&port->mutex); - ret = -EINVAL; - goto out; + return; } - uport->flags |= UPF_DEAD; mutex_unlock(&port->mutex); /* @@ -3211,18 +3227,14 @@ int uart_remove_one_port(struct uart_driver *drv, struct uart_port *uport) * Indicate that there isn't a port here anymore. */ uport->type = PORT_UNKNOWN; + uport->port_dev = NULL; mutex_lock(&port->mutex); WARN_ON(atomic_dec_return(&state->refcount) < 0); wait_event(state->remove_wait, !atomic_read(&state->refcount)); state->uart_port = NULL; mutex_unlock(&port->mutex); -out: - mutex_unlock(&port_mutex); - - return ret; } -EXPORT_SYMBOL(uart_remove_one_port); /** * uart_match_port - are the two ports equivalent? @@ -3257,6 +3269,144 @@ bool uart_match_port(const struct uart_port *port1, } EXPORT_SYMBOL(uart_match_port); +static struct serial_ctrl_device * +serial_core_get_ctrl_dev(struct serial_port_device *port_dev) +{ + struct device *dev = &port_dev->dev; + + return to_serial_base_ctrl_device(dev->parent); +} + +/* + * Find a registered serial core controller device if one exists. Returns + * the first device matching the ctrl_id. Caller must hold port_mutex. + */ +static struct serial_ctrl_device *serial_core_ctrl_find(struct uart_driver *drv, + struct device *phys_dev, + int ctrl_id) +{ + struct uart_state *state; + int i; + + lockdep_assert_held(&port_mutex); + + for (i = 0; i < drv->nr; i++) { + state = drv->state + i; + if (!state->uart_port || !state->uart_port->port_dev) + continue; + + if (state->uart_port->dev == phys_dev && + state->uart_port->ctrl_id == ctrl_id) + return serial_core_get_ctrl_dev(state->uart_port->port_dev); + } + + return NULL; +} + +static struct serial_ctrl_device *serial_core_ctrl_device_add(struct uart_port *port) +{ + return serial_base_ctrl_add(port, port->dev); +} + +static int serial_core_port_device_add(struct serial_ctrl_device *ctrl_dev, + struct uart_port *port) +{ + struct serial_port_device *port_dev; + + port_dev = serial_base_port_add(port, ctrl_dev); + if (IS_ERR(port_dev)) + return PTR_ERR(port_dev); + + port->port_dev = port_dev; + + return 0; +} + +/* + * Initialize a serial core port device, and a controller device if needed. + */ +int serial_core_register_port(struct uart_driver *drv, struct uart_port *port) +{ + struct serial_ctrl_device *ctrl_dev, *new_ctrl_dev = NULL; + int ret; + + mutex_lock(&port_mutex); + + /* + * Prevent serial_port_runtime_resume() from trying to use the port + * until serial_core_add_one_port() has completed + */ + port->flags |= UPF_DEAD; + + /* Inititalize a serial core controller device if needed */ + ctrl_dev = serial_core_ctrl_find(drv, port->dev, port->ctrl_id); + if (!ctrl_dev) { + new_ctrl_dev = serial_core_ctrl_device_add(port); + if (IS_ERR(new_ctrl_dev)) { + ret = PTR_ERR(new_ctrl_dev); + goto err_unlock; + } + ctrl_dev = new_ctrl_dev; + } + + /* + * Initialize a serial core port device. Tag the port dead to prevent + * serial_port_runtime_resume() trying to do anything until port has + * been registered. It gets cleared by serial_core_add_one_port(). + */ + ret = serial_core_port_device_add(ctrl_dev, port); + if (ret) + goto err_unregister_ctrl_dev; + + ret = serial_core_add_one_port(drv, port); + if (ret) + goto err_unregister_port_dev; + + port->flags &= ~UPF_DEAD; + + mutex_unlock(&port_mutex); + + return 0; + +err_unregister_port_dev: + serial_base_port_device_remove(port->port_dev); + +err_unregister_ctrl_dev: + serial_base_ctrl_device_remove(new_ctrl_dev); + +err_unlock: + mutex_unlock(&port_mutex); + + return ret; +} + +/* + * Removes a serial core port device, and the related serial core controller + * device if the last instance. + */ +void serial_core_unregister_port(struct uart_driver *drv, struct uart_port *port) +{ + struct device *phys_dev = port->dev; + struct serial_port_device *port_dev = port->port_dev; + struct serial_ctrl_device *ctrl_dev = serial_core_get_ctrl_dev(port_dev); + int ctrl_id = port->ctrl_id; + + mutex_lock(&port_mutex); + + port->flags |= UPF_DEAD; + + serial_core_remove_one_port(drv, port); + + /* Note that struct uart_port *port is no longer valid at this point */ + serial_base_port_device_remove(port_dev); + + /* Drop the serial core controller device if no ports are using it */ + if (!serial_core_ctrl_find(drv, phys_dev, ctrl_id)) + serial_base_ctrl_device_remove(ctrl_dev); + + mutex_unlock(&port_mutex); +} + /** * uart_handle_dcd_change - handle a change of carrier detect state * @uport: uart_port structure for the open port diff --git a/drivers/tty/serial/serial_ctrl.c b/drivers/tty/serial/serial_ctrl.c new file mode 100644 index 0000000000000000000000000000000000000000..6fcf634425dc0586867922cdfc34d5ade427e028 --- /dev/null +++ b/drivers/tty/serial/serial_ctrl.c @@ -0,0 +1,68 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Serial core controller driver + * + * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/ + * Author: Tony Lindgren + * + * This driver manages the serial core controller struct device instances. + * The serial core controller devices are children of the physical serial + * port device. + */ + +#include +#include +#include +#include +#include + +#include "serial_base.h" + +static int serial_ctrl_probe(struct device *dev) +{ + pm_runtime_enable(dev); + + return 0; +} + +static int serial_ctrl_remove(struct device *dev) +{ + pm_runtime_disable(dev); + + return 0; +} + +/* + * Serial core controller device init functions. Note that the physical + * serial port device driver may not have completed probe at this point. + */ +int serial_ctrl_register_port(struct uart_driver *drv, struct uart_port *port) +{ + return serial_core_register_port(drv, port); +} + +void serial_ctrl_unregister_port(struct uart_driver *drv, struct uart_port *port) +{ + serial_core_unregister_port(drv, port); +} + +static struct device_driver serial_ctrl_driver = { + .name = "ctrl", + .suppress_bind_attrs = true, + .probe = serial_ctrl_probe, + .remove = serial_ctrl_remove, +}; + +int serial_base_ctrl_init(void) +{ + return serial_base_driver_register(&serial_ctrl_driver); +} + +void serial_base_ctrl_exit(void) +{ + serial_base_driver_unregister(&serial_ctrl_driver); +} + +MODULE_AUTHOR("Tony Lindgren "); +MODULE_DESCRIPTION("Serial core controller driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/tty/serial/serial_port.c b/drivers/tty/serial/serial_port.c new file mode 100644 index 0000000000000000000000000000000000000000..8624232370070837b2c4bf091e6e042868389439 --- /dev/null +++ b/drivers/tty/serial/serial_port.c @@ -0,0 +1,105 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Serial core port device driver + * + * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/ + * Author: Tony Lindgren + */ + +#include +#include +#include +#include +#include + +#include "serial_base.h" + +#define SERIAL_PORT_AUTOSUSPEND_DELAY_MS 500 + +/* Only considers pending TX for now. Caller must take care of locking */ +static int __serial_port_busy(struct uart_port *port) +{ + return !uart_tx_stopped(port) && + uart_circ_chars_pending(&port->state->xmit); +} + +static int serial_port_runtime_resume(struct device *dev) +{ + struct serial_port_device *port_dev = to_serial_base_port_device(dev); + struct uart_port *port; + unsigned long flags; + + port = port_dev->port; + + if (port->flags & UPF_DEAD) + goto out; + + /* Flush any pending TX for the port */ + spin_lock_irqsave(&port->lock, flags); + if (__serial_port_busy(port)) + port->ops->start_tx(port); + spin_unlock_irqrestore(&port->lock, flags); + +out: + pm_runtime_mark_last_busy(dev); + + return 0; +} + +static DEFINE_RUNTIME_DEV_PM_OPS(serial_port_pm, + NULL, serial_port_runtime_resume, NULL); + +static int serial_port_probe(struct device *dev) +{ + pm_runtime_enable(dev); + pm_runtime_set_autosuspend_delay(dev, SERIAL_PORT_AUTOSUSPEND_DELAY_MS); + pm_runtime_use_autosuspend(dev); + + return 0; +} + +static int serial_port_remove(struct device *dev) +{ + pm_runtime_dont_use_autosuspend(dev); + pm_runtime_disable(dev); + + return 0; +} + +/* + * Serial core port device init functions. Note that the physical serial + * port device driver may not have completed probe at this point. + */ +int uart_add_one_port(struct uart_driver *drv, struct uart_port *port) +{ + return serial_ctrl_register_port(drv, port); +} +EXPORT_SYMBOL(uart_add_one_port); + +void uart_remove_one_port(struct uart_driver *drv, struct uart_port *port) +{ + serial_ctrl_unregister_port(drv, port); +} +EXPORT_SYMBOL(uart_remove_one_port); + +static struct device_driver serial_port_driver = { + .name = "port", + .suppress_bind_attrs = true, + .probe = serial_port_probe, + .remove = serial_port_remove, + .pm = pm_ptr(&serial_port_pm), +}; + +int serial_base_port_init(void) +{ + return serial_base_driver_register(&serial_port_driver); +} + +void serial_base_port_exit(void) +{ + serial_base_driver_unregister(&serial_port_driver); +} + +MODULE_AUTHOR("Tony Lindgren "); +MODULE_DESCRIPTION("Serial controller port driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/tty/serial/st-asc.c b/drivers/tty/serial/st-asc.c index 5215e6910f6869f0eb3d4dafd1ad87e5aea37fa5..aa471c9c24d98c0579a39b692cc25f4dede849b8 100644 --- a/drivers/tty/serial/st-asc.c +++ b/drivers/tty/serial/st-asc.c @@ -754,7 +754,7 @@ static struct asc_port *asc_of_get_asc_port(struct platform_device *pdev) asc_ports[id].hw_flow_control = of_property_read_bool(np, "uart-has-rtscts"); - asc_ports[id].force_m1 = of_property_read_bool(np, "st,force_m1"); + asc_ports[id].force_m1 = of_property_read_bool(np, "st,force-m1"); asc_ports[id].port.line = id; asc_ports[id].rts = NULL; @@ -796,7 +796,9 @@ static int asc_serial_remove(struct platform_device *pdev) { struct uart_port *port = platform_get_drvdata(pdev); - return uart_remove_one_port(&asc_uart_driver, port); + uart_remove_one_port(&asc_uart_driver, port); + + return 0; } #ifdef CONFIG_PM_SLEEP diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c index 1e38fc9b10c11545166478718154aba90d57933b..e9e11a2596211728245f393c01d1ed22eb49dd8a 100644 --- a/drivers/tty/serial/stm32-usart.c +++ b/drivers/tty/serial/stm32-usart.c @@ -1755,13 +1755,10 @@ static int stm32_usart_serial_remove(struct platform_device *pdev) struct uart_port *port = platform_get_drvdata(pdev); struct stm32_port *stm32_port = to_stm32_port(port); const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; - int err; u32 cr3; pm_runtime_get_sync(&pdev->dev); - err = uart_remove_one_port(&stm32_usart_driver, port); - if (err) - return(err); + uart_remove_one_port(&stm32_usart_driver, port); pm_runtime_disable(&pdev->dev); pm_runtime_set_suspended(&pdev->dev); diff --git a/drivers/tty/serial/uartlite.c b/drivers/tty/serial/uartlite.c index 94584e54ebbed7e78650da57baf75d473eb00540..679574893ebea2871d23910700d382d81550e3fb 100644 --- a/drivers/tty/serial/uartlite.c +++ b/drivers/tty/serial/uartlite.c @@ -685,18 +685,15 @@ static int ulite_assign(struct device *dev, int id, phys_addr_t base, int irq, * * @dev: pointer to device structure */ -static int ulite_release(struct device *dev) +static void ulite_release(struct device *dev) { struct uart_port *port = dev_get_drvdata(dev); - int rc = 0; if (port) { - rc = uart_remove_one_port(&ulite_uart_driver, port); + uart_remove_one_port(&ulite_uart_driver, port); dev_set_drvdata(dev, NULL); port->mapbase = 0; } - - return rc; } /** @@ -900,14 +897,13 @@ static int ulite_remove(struct platform_device *pdev) { struct uart_port *port = dev_get_drvdata(&pdev->dev); struct uartlite_data *pdata = port->private_data; - int rc; clk_disable_unprepare(pdata->clk); - rc = ulite_release(&pdev->dev); + ulite_release(&pdev->dev); pm_runtime_disable(&pdev->dev); pm_runtime_set_suspended(&pdev->dev); pm_runtime_dont_use_autosuspend(&pdev->dev); - return rc; + return 0; } /* work with hotplug and coldplug */ diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c index 8e521c69a959889af89a863d762397781322dffe..20a751663ef9f4d1eae812372f056c5241656be8 100644 --- a/drivers/tty/serial/xilinx_uartps.c +++ b/drivers/tty/serial/xilinx_uartps.c @@ -1670,14 +1670,13 @@ static int cdns_uart_remove(struct platform_device *pdev) { struct uart_port *port = platform_get_drvdata(pdev); struct cdns_uart *cdns_uart_data = port->private_data; - int rc; /* Remove the cdns_uart port from the serial core */ #ifdef CONFIG_COMMON_CLK clk_notifier_unregister(cdns_uart_data->uartclk, &cdns_uart_data->clk_rate_change_nb); #endif - rc = uart_remove_one_port(cdns_uart_data->cdns_uart_driver, port); + uart_remove_one_port(cdns_uart_data->cdns_uart_driver, port); port->mapbase = 0; clk_disable_unprepare(cdns_uart_data->uartclk); clk_disable_unprepare(cdns_uart_data->pclk); @@ -1693,7 +1692,7 @@ static int cdns_uart_remove(struct platform_device *pdev) if (!--instances) uart_unregister_driver(cdns_uart_data->cdns_uart_driver); - return rc; + return 0; } static struct platform_driver cdns_uart_platform_driver = { diff --git a/drivers/tty/tty.h b/drivers/tty/tty.h index 1e0d80e98d263965835d9d594bd69e1071201f7c..89769a1f1f9725f278f10a07ea43dcc9d8ebc7f4 100644 --- a/drivers/tty/tty.h +++ b/drivers/tty/tty.h @@ -99,14 +99,15 @@ extern int tty_ldisc_autoload; /* tty_audit.c */ #ifdef CONFIG_AUDIT -void tty_audit_add_data(struct tty_struct *tty, const void *data, size_t size); -void tty_audit_tiocsti(struct tty_struct *tty, char ch); +void tty_audit_add_data(const struct tty_struct *tty, const void *data, + size_t size); +void tty_audit_tiocsti(const struct tty_struct *tty, char ch); #else -static inline void tty_audit_add_data(struct tty_struct *tty, const void *data, - size_t size) +static inline void tty_audit_add_data(const struct tty_struct *tty, + const void *data, size_t size) { } -static inline void tty_audit_tiocsti(struct tty_struct *tty, char ch) +static inline void tty_audit_tiocsti(const struct tty_struct *tty, char ch) { } #endif diff --git a/drivers/tty/tty_audit.c b/drivers/tty/tty_audit.c index ca7afd7b27165d27384b2d799a1f417b77f810a4..24d010589379e25582b4a971d8f53388affcaf2e 100644 --- a/drivers/tty/tty_audit.c +++ b/drivers/tty/tty_audit.c @@ -15,7 +15,7 @@ struct tty_audit_buf { struct mutex mutex; /* Protects all data below */ dev_t dev; /* The TTY which the data is from */ - unsigned icanon:1; + bool icanon; size_t valid; unsigned char *data; /* Allocated size N_TTY_BUF_SIZE */ }; @@ -33,16 +33,16 @@ static struct tty_audit_buf *tty_audit_buf_alloc(void) { struct tty_audit_buf *buf; - buf = kmalloc(sizeof(*buf), GFP_KERNEL); + buf = kzalloc(sizeof(*buf), GFP_KERNEL); if (!buf) goto err; + buf->data = kmalloc(N_TTY_BUF_SIZE, GFP_KERNEL); if (!buf->data) goto err_buf; + mutex_init(&buf->mutex); - buf->dev = MKDEV(0, 0); - buf->icanon = 0; - buf->valid = 0; + return buf; err_buf: @@ -59,27 +59,27 @@ static void tty_audit_buf_free(struct tty_audit_buf *buf) } static void tty_audit_log(const char *description, dev_t dev, - unsigned char *data, size_t size) + const unsigned char *data, size_t size) { struct audit_buffer *ab; pid_t pid = task_pid_nr(current); uid_t uid = from_kuid(&init_user_ns, task_uid(current)); uid_t loginuid = from_kuid(&init_user_ns, audit_get_loginuid(current)); unsigned int sessionid = audit_get_sessionid(current); + char name[TASK_COMM_LEN]; ab = audit_log_start(audit_context(), GFP_KERNEL, AUDIT_TTY); - if (ab) { - char name[sizeof(current->comm)]; - - audit_log_format(ab, "%s pid=%u uid=%u auid=%u ses=%u major=%d" - " minor=%d comm=", description, pid, uid, - loginuid, sessionid, MAJOR(dev), MINOR(dev)); - get_task_comm(name, current); - audit_log_untrustedstring(ab, name); - audit_log_format(ab, " data="); - audit_log_n_hex(ab, data, size); - audit_log_end(ab); - } + if (!ab) + return; + + audit_log_format(ab, "%s pid=%u uid=%u auid=%u ses=%u major=%d minor=%d comm=", + description, pid, uid, loginuid, sessionid, + MAJOR(dev), MINOR(dev)); + get_task_comm(name, current); + audit_log_untrustedstring(ab, name); + audit_log_format(ab, " data="); + audit_log_n_hex(ab, data, size); + audit_log_end(ab); } /* @@ -134,7 +134,7 @@ void tty_audit_fork(struct signal_struct *sig) /* * tty_audit_tiocsti - Log TIOCSTI */ -void tty_audit_tiocsti(struct tty_struct *tty, char ch) +void tty_audit_tiocsti(const struct tty_struct *tty, char ch) { dev_t dev; @@ -199,11 +199,12 @@ static struct tty_audit_buf *tty_audit_buf_get(void) * * Audit @data of @size from @tty, if necessary. */ -void tty_audit_add_data(struct tty_struct *tty, const void *data, size_t size) +void tty_audit_add_data(const struct tty_struct *tty, const void *data, + size_t size) { struct tty_audit_buf *buf; - unsigned int icanon = !!L_ICANON(tty); unsigned int audit_tty; + bool icanon = L_ICANON(tty); dev_t dev; audit_tty = READ_ONCE(current->signal->audit_tty); diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index c84be40fb8dfae6511b71f6840ed829761da44fa..3959efc717aa1aa05007def4beefefd188ab1c60 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -101,6 +101,7 @@ #include #include #include +#include #include #include @@ -466,7 +467,7 @@ static const struct file_operations tty_fops = { .llseek = no_llseek, .read_iter = tty_read, .write_iter = tty_write, - .splice_read = generic_file_splice_read, + .splice_read = copy_splice_read, .splice_write = iter_file_splice_write, .poll = tty_poll, .unlocked_ioctl = tty_ioctl, @@ -481,7 +482,7 @@ static const struct file_operations console_fops = { .llseek = no_llseek, .read_iter = tty_read, .write_iter = redirected_tty_write, - .splice_read = generic_file_splice_read, + .splice_read = copy_splice_read, .splice_write = iter_file_splice_write, .poll = tty_poll, .unlocked_ioctl = tty_ioctl, @@ -811,18 +812,26 @@ void start_tty(struct tty_struct *tty) } EXPORT_SYMBOL(start_tty); -static void tty_update_time(struct timespec64 *time) +static void tty_update_time(struct tty_struct *tty, bool mtime) { time64_t sec = ktime_get_real_seconds(); + struct tty_file_private *priv; - /* - * We only care if the two values differ in anything other than the - * lower three bits (i.e every 8 seconds). If so, then we can update - * the time of the tty device, otherwise it could be construded as a - * security leak to let userspace know the exact timing of the tty. - */ - if ((sec ^ time->tv_sec) & ~7) - time->tv_sec = sec; + spin_lock(&tty->files_lock); + list_for_each_entry(priv, &tty->tty_files, list) { + struct inode *inode = file_inode(priv->file); + struct timespec64 *time = mtime ? &inode->i_mtime : &inode->i_atime; + + /* + * We only care if the two values differ in anything other than the + * lower three bits (i.e every 8 seconds). If so, then we can update + * the time of the tty device, otherwise it could be construded as a + * security leak to let userspace know the exact timing of the tty. + */ + if ((sec ^ time->tv_sec) & ~7) + time->tv_sec = sec; + } + spin_unlock(&tty->files_lock); } /* @@ -928,7 +937,7 @@ static ssize_t tty_read(struct kiocb *iocb, struct iov_iter *to) tty_ldisc_deref(ld); if (i > 0) - tty_update_time(&inode->i_atime); + tty_update_time(tty, false); return i; } @@ -1036,7 +1045,7 @@ static inline ssize_t do_tty_write( cond_resched(); } if (written) { - tty_update_time(&file_inode(file)->i_mtime); + tty_update_time(tty, true); ret = written; } out: diff --git a/drivers/ufs/core/ufs-fault-injection.c b/drivers/ufs/core/ufs-fault-injection.c index 7ac7c4e7ff831518921d96c1c62db67ba8ac5d5a..5b1184aac585b1e2743da2efd548fb7d447c0628 100644 --- a/drivers/ufs/core/ufs-fault-injection.c +++ b/drivers/ufs/core/ufs-fault-injection.c @@ -54,7 +54,7 @@ static int ufs_fault_set(const char *val, const struct kernel_param *kp) if (!setup_fault_attr(attr, (char *)val)) return -EINVAL; - strlcpy(kp->arg, val, FAULT_INJ_STR_SIZE); + strscpy(kp->arg, val, FAULT_INJ_STR_SIZE); return 0; } diff --git a/drivers/ufs/core/ufs-hwmon.c b/drivers/ufs/core/ufs-hwmon.c index 4c6a872b7a7ca9ad8d569854dc3c3e04fc44bcc9..101d7082446fc1828ab7afa4e001c732ebcfe32e 100644 --- a/drivers/ufs/core/ufs-hwmon.c +++ b/drivers/ufs/core/ufs-hwmon.c @@ -146,7 +146,7 @@ static umode_t ufs_hwmon_is_visible(const void *_data, enum hwmon_sensor_types t return 0; } -static const struct hwmon_channel_info *ufs_hwmon_info[] = { +static const struct hwmon_channel_info *const ufs_hwmon_info[] = { HWMON_CHANNEL_INFO(temp, HWMON_T_ENABLE | HWMON_T_INPUT | HWMON_T_CRIT | HWMON_T_LCRIT), NULL }; diff --git a/drivers/ufs/core/ufs-mcq.c b/drivers/ufs/core/ufs-mcq.c index 51b3c6ae781df4a4ab93f5ac5a61f71e622c27e2..6fb0e007af6362885ccf30c3ef667b230b2f0c04 100644 --- a/drivers/ufs/core/ufs-mcq.c +++ b/drivers/ufs/core/ufs-mcq.c @@ -12,21 +12,26 @@ #include #include #include "ufshcd-priv.h" +#include +#include +#include +#include #define MAX_QUEUE_SUP GENMASK(7, 0) #define UFS_MCQ_MIN_RW_QUEUES 2 #define UFS_MCQ_MIN_READ_QUEUES 0 -#define UFS_MCQ_NUM_DEV_CMD_QUEUES 1 #define UFS_MCQ_MIN_POLL_QUEUES 0 #define QUEUE_EN_OFFSET 31 #define QUEUE_ID_OFFSET 16 -#define MAX_DEV_CMD_ENTRIES 2 #define MCQ_CFG_MAC_MASK GENMASK(16, 8) #define MCQ_QCFG_SIZE 0x40 #define MCQ_ENTRY_SIZE_IN_DWORD 8 #define CQE_UCD_BA GENMASK_ULL(63, 7) +/* Max mcq register polling time in microseconds */ +#define MCQ_POLL_US 500000 + static int rw_queue_count_set(const char *val, const struct kernel_param *kp) { return param_set_uint_minmax(val, kp, UFS_MCQ_MIN_RW_QUEUES, @@ -108,8 +113,7 @@ struct ufs_hw_queue *ufshcd_mcq_req_to_hwq(struct ufs_hba *hba, u32 utag = blk_mq_unique_tag(req); u32 hwq = blk_mq_unique_tag_to_hwq(utag); - /* uhq[0] is used to serve device commands */ - return &hba->uhq[hwq + UFSHCD_MCQ_IO_QUEUE_OFFSET]; + return &hba->uhq[hwq]; } /** @@ -153,8 +157,7 @@ static int ufshcd_mcq_config_nr_queues(struct ufs_hba *hba) /* maxq is 0 based value */ hba_maxq = FIELD_GET(MAX_QUEUE_SUP, hba->mcq_capabilities) + 1; - tot_queues = UFS_MCQ_NUM_DEV_CMD_QUEUES + read_queues + poll_queues + - rw_queues; + tot_queues = read_queues + poll_queues + rw_queues; if (hba_maxq < tot_queues) { dev_err(hba->dev, "Total queues (%d) exceeds HC capacity (%d)\n", @@ -162,7 +165,7 @@ static int ufshcd_mcq_config_nr_queues(struct ufs_hba *hba) return -EOPNOTSUPP; } - rem = hba_maxq - UFS_MCQ_NUM_DEV_CMD_QUEUES; + rem = hba_maxq; if (rw_queues) { hba->nr_queues[HCTX_TYPE_DEFAULT] = rw_queues; @@ -188,7 +191,7 @@ static int ufshcd_mcq_config_nr_queues(struct ufs_hba *hba) for (i = 0; i < HCTX_MAX_TYPES; i++) host->nr_hw_queues += hba->nr_queues[i]; - hba->nr_hw_queues = host->nr_hw_queues + UFS_MCQ_NUM_DEV_CMD_QUEUES; + hba->nr_hw_queues = host->nr_hw_queues; return 0; } @@ -270,44 +273,57 @@ static int ufshcd_mcq_get_tag(struct ufs_hba *hba, } static void ufshcd_mcq_process_cqe(struct ufs_hba *hba, - struct ufs_hw_queue *hwq) + struct ufs_hw_queue *hwq) { struct cq_entry *cqe = ufshcd_mcq_cur_cqe(hwq); int tag = ufshcd_mcq_get_tag(hba, hwq, cqe); - ufshcd_compl_one_cqe(hba, tag, cqe); + if (cqe->command_desc_base_addr) { + ufshcd_compl_one_cqe(hba, tag, cqe); + /* After processed the cqe, mark it empty (invalid) entry */ + cqe->command_desc_base_addr = 0; + } } -unsigned long ufshcd_mcq_poll_cqe_nolock(struct ufs_hba *hba, - struct ufs_hw_queue *hwq) +void ufshcd_mcq_compl_all_cqes_lock(struct ufs_hba *hba, + struct ufs_hw_queue *hwq) { - unsigned long completed_reqs = 0; + unsigned long flags; + u32 entries = hwq->max_entries; - ufshcd_mcq_update_cq_tail_slot(hwq); - while (!ufshcd_mcq_is_cq_empty(hwq)) { + spin_lock_irqsave(&hwq->cq_lock, flags); + while (entries > 0) { ufshcd_mcq_process_cqe(hba, hwq); ufshcd_mcq_inc_cq_head_slot(hwq); - completed_reqs++; + entries--; } - if (completed_reqs) - ufshcd_mcq_update_cq_head(hwq); - - return completed_reqs; + ufshcd_mcq_update_cq_tail_slot(hwq); + hwq->cq_head_slot = hwq->cq_tail_slot; + spin_unlock_irqrestore(&hwq->cq_lock, flags); } -EXPORT_SYMBOL_GPL(ufshcd_mcq_poll_cqe_nolock); unsigned long ufshcd_mcq_poll_cqe_lock(struct ufs_hba *hba, struct ufs_hw_queue *hwq) { - unsigned long completed_reqs, flags; + unsigned long completed_reqs = 0; + unsigned long flags; spin_lock_irqsave(&hwq->cq_lock, flags); - completed_reqs = ufshcd_mcq_poll_cqe_nolock(hba, hwq); + ufshcd_mcq_update_cq_tail_slot(hwq); + while (!ufshcd_mcq_is_cq_empty(hwq)) { + ufshcd_mcq_process_cqe(hba, hwq); + ufshcd_mcq_inc_cq_head_slot(hwq); + completed_reqs++; + } + + if (completed_reqs) + ufshcd_mcq_update_cq_head(hwq); spin_unlock_irqrestore(&hwq->cq_lock, flags); return completed_reqs; } +EXPORT_SYMBOL_GPL(ufshcd_mcq_poll_cqe_lock); void ufshcd_mcq_make_queues_operational(struct ufs_hba *hba) { @@ -420,13 +436,243 @@ int ufshcd_mcq_init(struct ufs_hba *hba) hwq->max_entries = hba->nutrs; spin_lock_init(&hwq->sq_lock); spin_lock_init(&hwq->cq_lock); + mutex_init(&hwq->sq_mutex); } /* The very first HW queue serves device commands */ hba->dev_cmd_queue = &hba->uhq[0]; - /* Give dev_cmd_queue the minimal number of entries */ - hba->dev_cmd_queue->max_entries = MAX_DEV_CMD_ENTRIES; host->host_tagset = 1; return 0; } + +static int ufshcd_mcq_sq_stop(struct ufs_hba *hba, struct ufs_hw_queue *hwq) +{ + void __iomem *reg; + u32 id = hwq->id, val; + int err; + + if (hba->quirks & UFSHCD_QUIRK_MCQ_BROKEN_RTC) + return -ETIMEDOUT; + + writel(SQ_STOP, mcq_opr_base(hba, OPR_SQD, id) + REG_SQRTC); + reg = mcq_opr_base(hba, OPR_SQD, id) + REG_SQRTS; + err = read_poll_timeout(readl, val, val & SQ_STS, 20, + MCQ_POLL_US, false, reg); + if (err) + dev_err(hba->dev, "%s: failed. hwq-id=%d, err=%d\n", + __func__, id, err); + return err; +} + +static int ufshcd_mcq_sq_start(struct ufs_hba *hba, struct ufs_hw_queue *hwq) +{ + void __iomem *reg; + u32 id = hwq->id, val; + int err; + + if (hba->quirks & UFSHCD_QUIRK_MCQ_BROKEN_RTC) + return -ETIMEDOUT; + + writel(SQ_START, mcq_opr_base(hba, OPR_SQD, id) + REG_SQRTC); + reg = mcq_opr_base(hba, OPR_SQD, id) + REG_SQRTS; + err = read_poll_timeout(readl, val, !(val & SQ_STS), 20, + MCQ_POLL_US, false, reg); + if (err) + dev_err(hba->dev, "%s: failed. hwq-id=%d, err=%d\n", + __func__, id, err); + return err; +} + +/** + * ufshcd_mcq_sq_cleanup - Clean up submission queue resources + * associated with the pending command. + * @hba - per adapter instance. + * @task_tag - The command's task tag. + * + * Returns 0 for success; error code otherwise. + */ +int ufshcd_mcq_sq_cleanup(struct ufs_hba *hba, int task_tag) +{ + struct ufshcd_lrb *lrbp = &hba->lrb[task_tag]; + struct scsi_cmnd *cmd = lrbp->cmd; + struct ufs_hw_queue *hwq; + void __iomem *reg, *opr_sqd_base; + u32 nexus, id, val; + int err; + + if (hba->quirks & UFSHCD_QUIRK_MCQ_BROKEN_RTC) + return -ETIMEDOUT; + + if (task_tag != hba->nutrs - UFSHCD_NUM_RESERVED) { + if (!cmd) + return -EINVAL; + hwq = ufshcd_mcq_req_to_hwq(hba, scsi_cmd_to_rq(cmd)); + } else { + hwq = hba->dev_cmd_queue; + } + + id = hwq->id; + + mutex_lock(&hwq->sq_mutex); + + /* stop the SQ fetching before working on it */ + err = ufshcd_mcq_sq_stop(hba, hwq); + if (err) + goto unlock; + + /* SQCTI = EXT_IID, IID, LUN, Task Tag */ + nexus = lrbp->lun << 8 | task_tag; + opr_sqd_base = mcq_opr_base(hba, OPR_SQD, id); + writel(nexus, opr_sqd_base + REG_SQCTI); + + /* SQRTCy.ICU = 1 */ + writel(SQ_ICU, opr_sqd_base + REG_SQRTC); + + /* Poll SQRTSy.CUS = 1. Return result from SQRTSy.RTC */ + reg = opr_sqd_base + REG_SQRTS; + err = read_poll_timeout(readl, val, val & SQ_CUS, 20, + MCQ_POLL_US, false, reg); + if (err) + dev_err(hba->dev, "%s: failed. hwq=%d, tag=%d err=%ld\n", + __func__, id, task_tag, + FIELD_GET(SQ_ICU_ERR_CODE_MASK, readl(reg))); + + if (ufshcd_mcq_sq_start(hba, hwq)) + err = -ETIMEDOUT; + +unlock: + mutex_unlock(&hwq->sq_mutex); + return err; +} + +/** + * ufshcd_mcq_nullify_sqe - Nullify the submission queue entry. + * Write the sqe's Command Type to 0xF. The host controller will not + * fetch any sqe with Command Type = 0xF. + * + * @utrd - UTP Transfer Request Descriptor to be nullified. + */ +static void ufshcd_mcq_nullify_sqe(struct utp_transfer_req_desc *utrd) +{ + u32 dword_0; + + dword_0 = le32_to_cpu(utrd->header.dword_0); + dword_0 &= ~UPIU_COMMAND_TYPE_MASK; + dword_0 |= FIELD_PREP(UPIU_COMMAND_TYPE_MASK, 0xF); + utrd->header.dword_0 = cpu_to_le32(dword_0); +} + +/** + * ufshcd_mcq_sqe_search - Search for the command in the submission queue + * If the command is in the submission queue and not issued to the device yet, + * nullify the sqe so the host controller will skip fetching the sqe. + * + * @hba - per adapter instance. + * @hwq - Hardware Queue to be searched. + * @task_tag - The command's task tag. + * + * Returns true if the SQE containing the command is present in the SQ + * (not fetched by the controller); returns false if the SQE is not in the SQ. + */ +static bool ufshcd_mcq_sqe_search(struct ufs_hba *hba, + struct ufs_hw_queue *hwq, int task_tag) +{ + struct ufshcd_lrb *lrbp = &hba->lrb[task_tag]; + struct utp_transfer_req_desc *utrd; + u32 mask = hwq->max_entries - 1; + __le64 cmd_desc_base_addr; + bool ret = false; + u64 addr, match; + u32 sq_head_slot; + + if (hba->quirks & UFSHCD_QUIRK_MCQ_BROKEN_RTC) + return true; + + mutex_lock(&hwq->sq_mutex); + + ufshcd_mcq_sq_stop(hba, hwq); + sq_head_slot = ufshcd_mcq_get_sq_head_slot(hwq); + if (sq_head_slot == hwq->sq_tail_slot) + goto out; + + cmd_desc_base_addr = lrbp->utr_descriptor_ptr->command_desc_base_addr; + addr = le64_to_cpu(cmd_desc_base_addr) & CQE_UCD_BA; + + while (sq_head_slot != hwq->sq_tail_slot) { + utrd = hwq->sqe_base_addr + + sq_head_slot * sizeof(struct utp_transfer_req_desc); + match = le64_to_cpu(utrd->command_desc_base_addr) & CQE_UCD_BA; + if (addr == match) { + ufshcd_mcq_nullify_sqe(utrd); + ret = true; + goto out; + } + sq_head_slot = (sq_head_slot + 1) & mask; + } + +out: + ufshcd_mcq_sq_start(hba, hwq); + mutex_unlock(&hwq->sq_mutex); + return ret; +} + +/** + * ufshcd_mcq_abort - Abort the command in MCQ. + * @cmd - The command to be aborted. + * + * Returns SUCCESS or FAILED error codes + */ +int ufshcd_mcq_abort(struct scsi_cmnd *cmd) +{ + struct Scsi_Host *host = cmd->device->host; + struct ufs_hba *hba = shost_priv(host); + int tag = scsi_cmd_to_rq(cmd)->tag; + struct ufshcd_lrb *lrbp = &hba->lrb[tag]; + struct ufs_hw_queue *hwq; + int err = FAILED; + + if (!ufshcd_cmd_inflight(lrbp->cmd)) { + dev_err(hba->dev, + "%s: skip abort. cmd at tag %d already completed.\n", + __func__, tag); + goto out; + } + + /* Skip task abort in case previous aborts failed and report failure */ + if (lrbp->req_abort_skip) { + dev_err(hba->dev, "%s: skip abort. tag %d failed earlier\n", + __func__, tag); + goto out; + } + + hwq = ufshcd_mcq_req_to_hwq(hba, scsi_cmd_to_rq(cmd)); + + if (ufshcd_mcq_sqe_search(hba, hwq, tag)) { + /* + * Failure. The command should not be "stuck" in SQ for + * a long time which resulted in command being aborted. + */ + dev_err(hba->dev, "%s: cmd found in sq. hwq=%d, tag=%d\n", + __func__, hwq->id, tag); + goto out; + } + + /* + * The command is not in the submission queue, and it is not + * in the completion queue either. Query the device to see if + * the command is being processed in the device. + */ + if (ufshcd_try_to_abort_task(hba, tag)) { + dev_err(hba->dev, "%s: device abort failed %d\n", __func__, err); + lrbp->req_abort_skip = true; + goto out; + } + + err = SUCCESS; + if (ufshcd_cmd_inflight(lrbp->cmd)) + ufshcd_release_scsi_cmd(hba, lrbp); + +out: + return err; +} diff --git a/drivers/ufs/core/ufs-sysfs.c b/drivers/ufs/core/ufs-sysfs.c index 883f0e44b54e76dac719a0373259b65fc8edeccb..6c72075750dd0463aa056a6b84e156fd5893c10c 100644 --- a/drivers/ufs/core/ufs-sysfs.c +++ b/drivers/ufs/core/ufs-sysfs.c @@ -168,7 +168,7 @@ static ssize_t auto_hibern8_show(struct device *dev, } pm_runtime_get_sync(hba->dev); - ufshcd_hold(hba, false); + ufshcd_hold(hba); ahit = ufshcd_readl(hba, REG_AUTO_HIBERNATE_IDLE_TIMER); ufshcd_release(hba); pm_runtime_put_sync(hba->dev); @@ -298,6 +298,37 @@ static ssize_t enable_wb_buf_flush_store(struct device *dev, return res < 0 ? res : count; } +static ssize_t wb_flush_threshold_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct ufs_hba *hba = dev_get_drvdata(dev); + + return sysfs_emit(buf, "%u\n", hba->vps->wb_flush_threshold); +} + +static ssize_t wb_flush_threshold_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct ufs_hba *hba = dev_get_drvdata(dev); + unsigned int wb_flush_threshold; + + if (kstrtouint(buf, 0, &wb_flush_threshold)) + return -EINVAL; + + /* The range of values for wb_flush_threshold is (0,10] */ + if (wb_flush_threshold > UFS_WB_BUF_REMAIN_PERCENT(100) || + wb_flush_threshold == 0) { + dev_err(dev, "The value of wb_flush_threshold is invalid!\n"); + return -EINVAL; + } + + hba->vps->wb_flush_threshold = wb_flush_threshold; + + return count; +} + static DEVICE_ATTR_RW(rpm_lvl); static DEVICE_ATTR_RO(rpm_target_dev_state); static DEVICE_ATTR_RO(rpm_target_link_state); @@ -307,6 +338,7 @@ static DEVICE_ATTR_RO(spm_target_link_state); static DEVICE_ATTR_RW(auto_hibern8); static DEVICE_ATTR_RW(wb_on); static DEVICE_ATTR_RW(enable_wb_buf_flush); +static DEVICE_ATTR_RW(wb_flush_threshold); static struct attribute *ufs_sysfs_ufshcd_attrs[] = { &dev_attr_rpm_lvl.attr, @@ -318,6 +350,7 @@ static struct attribute *ufs_sysfs_ufshcd_attrs[] = { &dev_attr_auto_hibern8.attr, &dev_attr_wb_on.attr, &dev_attr_enable_wb_buf_flush.attr, + &dev_attr_wb_flush_threshold.attr, NULL }; diff --git a/drivers/ufs/core/ufshcd-crypto.c b/drivers/ufs/core/ufshcd-crypto.c index 198360fe5e8e1f08c283879768ee6a2d8561a433..f2c4422cab8640c2a28d629df667406d86ccbdc2 100644 --- a/drivers/ufs/core/ufshcd-crypto.c +++ b/drivers/ufs/core/ufshcd-crypto.c @@ -24,7 +24,7 @@ static int ufshcd_program_key(struct ufs_hba *hba, u32 slot_offset = hba->crypto_cfg_register + slot * sizeof(*cfg); int err = 0; - ufshcd_hold(hba, false); + ufshcd_hold(hba); if (hba->vops && hba->vops->program_key) { err = hba->vops->program_key(hba, cfg, slot); diff --git a/drivers/ufs/core/ufshcd-priv.h b/drivers/ufs/core/ufshcd-priv.h index d53b93c21a0c6aa8e6394e356b6b35eb95a37600..0f3bd943b58b1f2141f960164e055b6041f89a53 100644 --- a/drivers/ufs/core/ufshcd-priv.h +++ b/drivers/ufs/core/ufshcd-priv.h @@ -68,25 +68,26 @@ int ufshcd_mcq_decide_queue_depth(struct ufs_hba *hba); int ufshcd_mcq_memory_alloc(struct ufs_hba *hba); void ufshcd_mcq_make_queues_operational(struct ufs_hba *hba); void ufshcd_mcq_config_mac(struct ufs_hba *hba, u32 max_active_cmds); -void ufshcd_mcq_select_mcq_mode(struct ufs_hba *hba); u32 ufshcd_mcq_read_cqis(struct ufs_hba *hba, int i); void ufshcd_mcq_write_cqis(struct ufs_hba *hba, u32 val, int i); -unsigned long ufshcd_mcq_poll_cqe_nolock(struct ufs_hba *hba, - struct ufs_hw_queue *hwq); struct ufs_hw_queue *ufshcd_mcq_req_to_hwq(struct ufs_hba *hba, struct request *req); unsigned long ufshcd_mcq_poll_cqe_lock(struct ufs_hba *hba, struct ufs_hw_queue *hwq); +void ufshcd_mcq_compl_all_cqes_lock(struct ufs_hba *hba, + struct ufs_hw_queue *hwq); +bool ufshcd_cmd_inflight(struct scsi_cmnd *cmd); +int ufshcd_mcq_sq_cleanup(struct ufs_hba *hba, int task_tag); +int ufshcd_mcq_abort(struct scsi_cmnd *cmd); +int ufshcd_try_to_abort_task(struct ufs_hba *hba, int tag); +void ufshcd_release_scsi_cmd(struct ufs_hba *hba, + struct ufshcd_lrb *lrbp); -#define UFSHCD_MCQ_IO_QUEUE_OFFSET 1 #define SD_ASCII_STD true #define SD_RAW false int ufshcd_read_string_desc(struct ufs_hba *hba, u8 desc_index, u8 **buf, bool ascii); -int ufshcd_hold(struct ufs_hba *hba, bool async); -void ufshcd_release(struct ufs_hba *hba); - int ufshcd_send_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd); int ufshcd_exec_raw_upiu_cmd(struct ufs_hba *hba, @@ -366,10 +367,11 @@ static inline bool ufs_is_valid_unit_desc_lun(struct ufs_dev_info *dev_info, u8 static inline void ufshcd_inc_sq_tail(struct ufs_hw_queue *q) __must_hold(&q->sq_lock) { - u32 mask = q->max_entries - 1; u32 val; - q->sq_tail_slot = (q->sq_tail_slot + 1) & mask; + q->sq_tail_slot++; + if (q->sq_tail_slot == q->max_entries) + q->sq_tail_slot = 0; val = q->sq_tail_slot * sizeof(struct utp_transfer_req_desc); writel(val, q->mcq_sq_tail); } @@ -404,4 +406,12 @@ static inline struct cq_entry *ufshcd_mcq_cur_cqe(struct ufs_hw_queue *q) return cqe + q->cq_head_slot; } + +static inline u32 ufshcd_mcq_get_sq_head_slot(struct ufs_hw_queue *q) +{ + u32 val = readl(q->mcq_sq_head); + + return val / sizeof(struct utp_transfer_req_desc); +} + #endif /* _UFSHCD_PRIV_H_ */ diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c index e7e79f515e14182c627069ea231fd8c2a0f0baaf..1294467757964e52127bde42f53774487f1dd4c2 100644 --- a/drivers/ufs/core/ufshcd.c +++ b/drivers/ufs/core/ufshcd.c @@ -98,7 +98,7 @@ /* Polling time to wait for fDeviceInit */ #define FDEVICEINIT_COMPL_TIMEOUT 1500 /* millisecs */ -/* UFSHC 4.0 compliant HC support this mode, refer param_set_mcq_mode() */ +/* UFSHC 4.0 compliant HC support this mode. */ static bool use_mcq_mode = true; static bool is_mcq_supported(struct ufs_hba *hba) @@ -106,23 +106,7 @@ static bool is_mcq_supported(struct ufs_hba *hba) return hba->mcq_sup && use_mcq_mode; } -static int param_set_mcq_mode(const char *val, const struct kernel_param *kp) -{ - int ret; - - ret = param_set_bool(val, kp); - if (ret) - return ret; - - return 0; -} - -static const struct kernel_param_ops mcq_mode_ops = { - .set = param_set_mcq_mode, - .get = param_get_bool, -}; - -module_param_cb(use_mcq_mode, &mcq_mode_ops, &use_mcq_mode, 0644); +module_param(use_mcq_mode, bool, 0644); MODULE_PARM_DESC(use_mcq_mode, "Control MCQ mode for controllers starting from UFSHCI 4.0. 1 - enable MCQ, 0 - disable MCQ. MCQ is enabled by default"); #define ufshcd_toggle_vreg(_dev, _vreg, _on) \ @@ -173,7 +157,6 @@ EXPORT_SYMBOL_GPL(ufshcd_dump_regs); enum { UFSHCD_MAX_CHANNEL = 0, UFSHCD_MAX_ID = 1, - UFSHCD_NUM_RESERVED = 1, UFSHCD_CMD_PER_LUN = 32 - UFSHCD_NUM_RESERVED, UFSHCD_CAN_QUEUE = 32 - UFSHCD_NUM_RESERVED, }; @@ -301,7 +284,6 @@ static int ufshcd_setup_hba_vreg(struct ufs_hba *hba, bool on); static int ufshcd_setup_vreg(struct ufs_hba *hba, bool on); static inline int ufshcd_config_vreg_hpm(struct ufs_hba *hba, struct ufs_vreg *vreg); -static int ufshcd_try_to_abort_task(struct ufs_hba *hba, int tag); static void ufshcd_wb_toggle_buf_flush_during_h8(struct ufs_hba *hba, bool enable); static void ufshcd_hba_vreg_set_lpm(struct ufs_hba *hba); @@ -1205,7 +1187,7 @@ static int ufshcd_wait_for_doorbell_clr(struct ufs_hba *hba, bool timeout = false, do_last_check = false; ktime_t start; - ufshcd_hold(hba, false); + ufshcd_hold(hba); spin_lock_irqsave(hba->host->host_lock, flags); /* * Wait for all the outstanding tasks/transfer requests. @@ -1326,7 +1308,7 @@ static int ufshcd_clock_scaling_prepare(struct ufs_hba *hba, u64 timeout_us) } /* let's not get into low power until clock scaling is completed */ - ufshcd_hold(hba, false); + ufshcd_hold(hba); out: return ret; @@ -1656,7 +1638,7 @@ static ssize_t ufshcd_clkscale_enable_store(struct device *dev, goto out; ufshcd_rpm_get_sync(hba); - ufshcd_hold(hba, false); + ufshcd_hold(hba); hba->clk_scaling.is_enabled = value; @@ -1739,7 +1721,7 @@ static void ufshcd_ungate_work(struct work_struct *work) spin_lock_irqsave(hba->host->host_lock, flags); if (hba->clk_gating.state == CLKS_ON) { spin_unlock_irqrestore(hba->host->host_lock, flags); - goto unblock_reqs; + return; } spin_unlock_irqrestore(hba->host->host_lock, flags); @@ -1762,25 +1744,21 @@ static void ufshcd_ungate_work(struct work_struct *work) } hba->clk_gating.is_suspended = false; } -unblock_reqs: - ufshcd_scsi_unblock_requests(hba); } /** * ufshcd_hold - Enable clocks that were gated earlier due to ufshcd_release. * Also, exit from hibern8 mode and set the link as active. * @hba: per adapter instance - * @async: This indicates whether caller should ungate clocks asynchronously. */ -int ufshcd_hold(struct ufs_hba *hba, bool async) +void ufshcd_hold(struct ufs_hba *hba) { - int rc = 0; bool flush_result; unsigned long flags; if (!ufshcd_is_clkgating_allowed(hba) || !hba->clk_gating.is_initialized) - goto out; + return; spin_lock_irqsave(hba->host->host_lock, flags); hba->clk_gating.active_reqs++; @@ -1797,15 +1775,10 @@ int ufshcd_hold(struct ufs_hba *hba, bool async) */ if (ufshcd_can_hibern8_during_gating(hba) && ufshcd_is_link_hibern8(hba)) { - if (async) { - rc = -EAGAIN; - hba->clk_gating.active_reqs--; - break; - } spin_unlock_irqrestore(hba->host->host_lock, flags); flush_result = flush_work(&hba->clk_gating.ungate_work); if (hba->clk_gating.is_suspended && !flush_result) - goto out; + return; spin_lock_irqsave(hba->host->host_lock, flags); goto start; } @@ -1827,21 +1800,14 @@ int ufshcd_hold(struct ufs_hba *hba, bool async) hba->clk_gating.state = REQ_CLKS_ON; trace_ufshcd_clk_gating(dev_name(hba->dev), hba->clk_gating.state); - if (queue_work(hba->clk_gating.clk_gating_workq, - &hba->clk_gating.ungate_work)) - ufshcd_scsi_block_requests(hba); + queue_work(hba->clk_gating.clk_gating_workq, + &hba->clk_gating.ungate_work); /* * fall through to check if we should wait for this * work to be done or not. */ fallthrough; case REQ_CLKS_ON: - if (async) { - rc = -EAGAIN; - hba->clk_gating.active_reqs--; - break; - } - spin_unlock_irqrestore(hba->host->host_lock, flags); flush_work(&hba->clk_gating.ungate_work); /* Make sure state is CLKS_ON before returning */ @@ -1853,8 +1819,6 @@ int ufshcd_hold(struct ufs_hba *hba, bool async) break; } spin_unlock_irqrestore(hba->host->host_lock, flags); -out: - return rc; } EXPORT_SYMBOL_GPL(ufshcd_hold); @@ -2086,7 +2050,7 @@ static void ufshcd_exit_clk_gating(struct ufs_hba *hba) ufshcd_remove_clk_gating_sysfs(hba); /* Ungate the clock if necessary. */ - ufshcd_hold(hba, false); + ufshcd_hold(hba); hba->clk_gating.is_initialized = false; ufshcd_release(hba); @@ -2336,18 +2300,20 @@ static inline int ufshcd_hba_capabilities(struct ufs_hba *hba) /* Read crypto capabilities */ err = ufshcd_hba_init_crypto_capabilities(hba); - if (err) + if (err) { dev_err(hba->dev, "crypto setup failed\n"); + return err; + } hba->mcq_sup = FIELD_GET(MASK_MCQ_SUPPORT, hba->capabilities); if (!hba->mcq_sup) - return err; + return 0; hba->mcq_capabilities = ufshcd_readl(hba, REG_MCQCAP); hba->ext_iid_sup = FIELD_GET(MASK_EXT_IID_SUPPORT, hba->mcq_capabilities); - return err; + return 0; } /** @@ -2482,7 +2448,7 @@ int ufshcd_send_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd) if (hba->quirks & UFSHCD_QUIRK_BROKEN_UIC_CMD) return 0; - ufshcd_hold(hba, false); + ufshcd_hold(hba); mutex_lock(&hba->uic_cmd_mutex); ufshcd_add_delay_before_dme_cmd(hba); @@ -2533,7 +2499,7 @@ static void ufshcd_sgl_to_prdt(struct ufs_hba *hba, struct ufshcd_lrb *lrbp, int * 11b to indicate Dword granularity. A value of '3' * indicates 4 bytes, '7' indicates 8 bytes, etc." */ - WARN_ONCE(len > 256 * 1024, "len = %#x\n", len); + WARN_ONCE(len > SZ_256K, "len = %#x\n", len); prd->size = cpu_to_le32(len - 1); prd->addr = cpu_to_le64(sg->dma_address); prd->reserved = 0; @@ -2885,12 +2851,6 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd) WARN_ONCE(tag < 0 || tag >= hba->nutrs, "Invalid tag %d\n", tag); - /* - * Allows the UFS error handler to wait for prior ufshcd_queuecommand() - * calls. - */ - rcu_read_lock(); - switch (hba->ufshcd_state) { case UFSHCD_STATE_OPERATIONAL: break; @@ -2936,16 +2896,9 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd) hba->req_abort_count = 0; - err = ufshcd_hold(hba, true); - if (err) { - err = SCSI_MLQUEUE_HOST_BUSY; - goto out; - } - WARN_ON(ufshcd_is_clkgating_allowed(hba) && - (hba->clk_gating.state != CLKS_ON)); + ufshcd_hold(hba); lrbp = &hba->lrb[tag]; - WARN_ON(lrbp->cmd); lrbp->cmd = cmd; lrbp->task_tag = tag; lrbp->lun = ufshcd_scsi_to_upiu_lun(cmd->device->lun); @@ -2961,7 +2914,6 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd) err = ufshcd_map_sg(hba, lrbp); if (err) { - lrbp->cmd = NULL; ufshcd_release(hba); goto out; } @@ -2972,8 +2924,6 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd) ufshcd_send_command(hba, tag, hwq); out: - rcu_read_unlock(); - if (ufs_trigger_eh()) { unsigned long flags; @@ -2999,13 +2949,50 @@ static int ufshcd_compose_dev_cmd(struct ufs_hba *hba, } /* - * Clear all the requests from the controller for which a bit has been set in - * @mask and wait until the controller confirms that these requests have been - * cleared. + * Check with the block layer if the command is inflight + * @cmd: command to check. + * + * Returns true if command is inflight; false if not. + */ +bool ufshcd_cmd_inflight(struct scsi_cmnd *cmd) +{ + struct request *rq; + + if (!cmd) + return false; + + rq = scsi_cmd_to_rq(cmd); + if (!blk_mq_request_started(rq)) + return false; + + return true; +} + +/* + * Clear the pending command in the controller and wait until + * the controller confirms that the command has been cleared. + * @hba: per adapter instance + * @task_tag: The tag number of the command to be cleared. */ -static int ufshcd_clear_cmds(struct ufs_hba *hba, u32 mask) +static int ufshcd_clear_cmd(struct ufs_hba *hba, u32 task_tag) { + u32 mask = 1U << task_tag; unsigned long flags; + int err; + + if (is_mcq_enabled(hba)) { + /* + * MCQ mode. Clean up the MCQ resources similar to + * what the ufshcd_utrl_clear() does for SDB mode. + */ + err = ufshcd_mcq_sq_cleanup(hba, task_tag); + if (err) { + dev_err(hba->dev, "%s: failed tag=%d. err=%d\n", + __func__, task_tag, err); + return err; + } + return 0; + } /* clear outstanding transaction before retry */ spin_lock_irqsave(hba->host->host_lock, flags); @@ -3099,14 +3086,23 @@ static int ufshcd_wait_for_dev_cmd(struct ufs_hba *hba, * not trigger any race conditions. */ hba->dev_cmd.complete = NULL; - err = ufshcd_get_tr_ocs(lrbp, hba->dev_cmd.cqe); + err = ufshcd_get_tr_ocs(lrbp, NULL); if (!err) err = ufshcd_dev_cmd_completion(hba, lrbp); } else { err = -ETIMEDOUT; dev_dbg(hba->dev, "%s: dev_cmd request timedout, tag %d\n", __func__, lrbp->task_tag); - if (ufshcd_clear_cmds(hba, 1U << lrbp->task_tag) == 0) { + + /* MCQ mode */ + if (is_mcq_enabled(hba)) { + err = ufshcd_clear_cmd(hba, lrbp->task_tag); + hba->dev_cmd.complete = NULL; + return err; + } + + /* SDB mode */ + if (ufshcd_clear_cmd(hba, lrbp->task_tag) == 0) { /* successfully cleared the command, retry if needed */ err = -EAGAIN; /* @@ -3180,13 +3176,12 @@ static int ufshcd_exec_dev_cmd(struct ufs_hba *hba, down_read(&hba->clk_scaling_lock); lrbp = &hba->lrb[tag]; - WARN_ON(lrbp->cmd); + lrbp->cmd = NULL; err = ufshcd_compose_dev_cmd(hba, lrbp, cmd_type, tag); if (unlikely(err)) goto out; hba->dev_cmd.complete = &wait; - hba->dev_cmd.cqe = NULL; ufshcd_add_query_upiu_trace(hba, UFS_QUERY_SEND, lrbp->ucd_req_ptr); @@ -3267,7 +3262,7 @@ int ufshcd_query_flag(struct ufs_hba *hba, enum query_opcode opcode, BUG_ON(!hba); - ufshcd_hold(hba, false); + ufshcd_hold(hba); mutex_lock(&hba->dev_cmd.lock); ufshcd_init_query(hba, &request, &response, opcode, idn, index, selector); @@ -3341,7 +3336,7 @@ int ufshcd_query_attr(struct ufs_hba *hba, enum query_opcode opcode, return -EINVAL; } - ufshcd_hold(hba, false); + ufshcd_hold(hba); mutex_lock(&hba->dev_cmd.lock); ufshcd_init_query(hba, &request, &response, opcode, idn, index, @@ -3437,7 +3432,7 @@ static int __ufshcd_query_descriptor(struct ufs_hba *hba, return -EINVAL; } - ufshcd_hold(hba, false); + ufshcd_hold(hba); mutex_lock(&hba->dev_cmd.lock); ufshcd_init_query(hba, &request, &response, opcode, idn, index, @@ -3779,7 +3774,7 @@ static int ufshcd_memory_alloc(struct ufs_hba *hba) /* * Allocate memory for UTP Transfer descriptors - * UFSHCI requires 1024 byte alignment of UTRD + * UFSHCI requires 1KB alignment of UTRD */ utrdl_size = (sizeof(struct utp_transfer_req_desc) * hba->nutrs); hba->utrdl_base_addr = dmam_alloc_coherent(hba->dev, @@ -3787,7 +3782,7 @@ static int ufshcd_memory_alloc(struct ufs_hba *hba) &hba->utrdl_dma_addr, GFP_KERNEL); if (!hba->utrdl_base_addr || - WARN_ON(hba->utrdl_dma_addr & (1024 - 1))) { + WARN_ON(hba->utrdl_dma_addr & (SZ_1K - 1))) { dev_err(hba->dev, "Transfer Descriptor Memory allocation failed\n"); goto out; @@ -3803,7 +3798,7 @@ static int ufshcd_memory_alloc(struct ufs_hba *hba) goto skip_utmrdl; /* * Allocate memory for UTP Task Management descriptors - * UFSHCI requires 1024 byte alignment of UTMRD + * UFSHCI requires 1KB alignment of UTMRD */ utmrdl_size = sizeof(struct utp_task_req_desc) * hba->nutmrs; hba->utmrdl_base_addr = dmam_alloc_coherent(hba->dev, @@ -3811,7 +3806,7 @@ static int ufshcd_memory_alloc(struct ufs_hba *hba) &hba->utmrdl_dma_addr, GFP_KERNEL); if (!hba->utmrdl_base_addr || - WARN_ON(hba->utmrdl_dma_addr & (1024 - 1))) { + WARN_ON(hba->utmrdl_dma_addr & (SZ_1K - 1))) { dev_err(hba->dev, "Task Management Descriptor Memory allocation failed\n"); goto out; @@ -3868,10 +3863,8 @@ static void ufshcd_host_memory_configure(struct ufs_hba *hba) /* Configure UTRD with command descriptor base address */ cmd_desc_element_addr = (cmd_desc_dma_addr + (cmd_desc_size * i)); - utrdlp[i].command_desc_base_addr_lo = - cpu_to_le32(lower_32_bits(cmd_desc_element_addr)); - utrdlp[i].command_desc_base_addr_hi = - cpu_to_le32(upper_32_bits(cmd_desc_element_addr)); + utrdlp[i].command_desc_base_addr = + cpu_to_le64(cmd_desc_element_addr); /* Response upiu and prdt offset should be in double words */ if (hba->quirks & UFSHCD_QUIRK_PRDT_BYTE_GRAN) { @@ -4255,7 +4248,7 @@ int ufshcd_uic_change_pwr_mode(struct ufs_hba *hba, u8 mode) uic_cmd.command = UIC_CMD_DME_SET; uic_cmd.argument1 = UIC_ARG_MIB(PA_PWRMODE); uic_cmd.argument3 = mode; - ufshcd_hold(hba, false); + ufshcd_hold(hba); ret = ufshcd_uic_pwr_ctrl(hba, &uic_cmd); ufshcd_release(hba); @@ -4362,7 +4355,7 @@ void ufshcd_auto_hibern8_update(struct ufs_hba *hba, u32 ahit) if (update && !pm_runtime_suspended(&hba->ufs_device_wlun->sdev_gendev)) { ufshcd_rpm_get_sync(hba); - ufshcd_hold(hba, false); + ufshcd_hold(hba); ufshcd_auto_hibern8_enable(hba); ufshcd_release(hba); ufshcd_rpm_put_sync(hba); @@ -4955,7 +4948,7 @@ static int ufshcd_verify_dev_init(struct ufs_hba *hba) int err = 0; int retries; - ufshcd_hold(hba, false); + ufshcd_hold(hba); mutex_lock(&hba->dev_cmd.lock); for (retries = NOP_OUT_RETRIES; retries > 0; retries--) { err = ufshcd_exec_dev_cmd(hba, DEV_CMD_TYPE_NOP, @@ -5148,7 +5141,7 @@ static int ufshcd_slave_configure(struct scsi_device *sdev) blk_queue_update_dma_pad(q, PRDT_DATA_BYTE_COUNT_PAD - 1); if (hba->quirks & UFSHCD_QUIRK_4KB_DMA_ALIGNMENT) - blk_queue_update_dma_alignment(q, 4096 - 1); + blk_queue_update_dma_alignment(q, SZ_4K - 1); /* * Block runtime-pm until all consumers are added. * Refer ufshcd_setup_links(). @@ -5416,13 +5409,12 @@ static irqreturn_t ufshcd_uic_cmd_compl(struct ufs_hba *hba, u32 intr_status) } /* Release the resources allocated for processing a SCSI command. */ -static void ufshcd_release_scsi_cmd(struct ufs_hba *hba, - struct ufshcd_lrb *lrbp) +void ufshcd_release_scsi_cmd(struct ufs_hba *hba, + struct ufshcd_lrb *lrbp) { struct scsi_cmnd *cmd = lrbp->cmd; scsi_dma_unmap(cmd); - lrbp->cmd = NULL; /* Mark the command as completed. */ ufshcd_release(hba); ufshcd_clk_scaling_update_busy(hba); } @@ -5438,6 +5430,7 @@ void ufshcd_compl_one_cqe(struct ufs_hba *hba, int task_tag, { struct ufshcd_lrb *lrbp; struct scsi_cmnd *cmd; + enum utp_ocs ocs; lrbp = &hba->lrb[task_tag]; lrbp->compl_time_stamp = ktime_get(); @@ -5453,8 +5446,11 @@ void ufshcd_compl_one_cqe(struct ufs_hba *hba, int task_tag, } else if (lrbp->command_type == UTP_CMD_TYPE_DEV_MANAGE || lrbp->command_type == UTP_CMD_TYPE_UFS_STORAGE) { if (hba->dev_cmd.complete) { - hba->dev_cmd.cqe = cqe; - ufshcd_add_command_trace(hba, task_tag, UFS_DEV_COMP); + if (cqe) { + ocs = le32_to_cpu(cqe->status) & MASK_OCS; + lrbp->utr_descriptor_ptr->header.dword_2 = + cpu_to_le32(ocs); + } complete(hba->dev_cmd.complete); ufshcd_clk_scaling_update_busy(hba); } @@ -5507,7 +5503,7 @@ static int ufshcd_poll(struct Scsi_Host *shost, unsigned int queue_num) struct ufs_hw_queue *hwq; if (is_mcq_enabled(hba)) { - hwq = &hba->uhq[queue_num + UFSHCD_MCQ_IO_QUEUE_OFFSET]; + hwq = &hba->uhq[queue_num]; return ufshcd_mcq_poll_cqe_lock(hba, hwq); } @@ -5531,6 +5527,57 @@ static int ufshcd_poll(struct Scsi_Host *shost, unsigned int queue_num) return completed_reqs != 0; } +/** + * ufshcd_mcq_compl_pending_transfer - MCQ mode function. It is + * invoked from the error handler context or ufshcd_host_reset_and_restore() + * to complete the pending transfers and free the resources associated with + * the scsi command. + * + * @hba: per adapter instance + * @force_compl: This flag is set to true when invoked + * from ufshcd_host_reset_and_restore() in which case it requires special + * handling because the host controller has been reset by ufshcd_hba_stop(). + */ +static void ufshcd_mcq_compl_pending_transfer(struct ufs_hba *hba, + bool force_compl) +{ + struct ufs_hw_queue *hwq; + struct ufshcd_lrb *lrbp; + struct scsi_cmnd *cmd; + unsigned long flags; + u32 hwq_num, utag; + int tag; + + for (tag = 0; tag < hba->nutrs; tag++) { + lrbp = &hba->lrb[tag]; + cmd = lrbp->cmd; + if (!ufshcd_cmd_inflight(cmd) || + test_bit(SCMD_STATE_COMPLETE, &cmd->state)) + continue; + + utag = blk_mq_unique_tag(scsi_cmd_to_rq(cmd)); + hwq_num = blk_mq_unique_tag_to_hwq(utag); + hwq = &hba->uhq[hwq_num]; + + if (force_compl) { + ufshcd_mcq_compl_all_cqes_lock(hba, hwq); + /* + * For those cmds of which the cqes are not present + * in the cq, complete them explicitly. + */ + if (cmd && !test_bit(SCMD_STATE_COMPLETE, &cmd->state)) { + spin_lock_irqsave(&hwq->cq_lock, flags); + set_host_byte(cmd, DID_REQUEUE); + ufshcd_release_scsi_cmd(hba, lrbp); + scsi_done(cmd); + spin_unlock_irqrestore(&hwq->cq_lock, flags); + } + } else { + ufshcd_mcq_poll_cqe_lock(hba, hwq); + } + } +} + /** * ufshcd_transfer_req_compl - handle SCSI and query command completion * @hba: per adapter instance @@ -6095,9 +6142,13 @@ static void ufshcd_exception_event_handler(struct work_struct *work) } /* Complete requests that have door-bell cleared */ -static void ufshcd_complete_requests(struct ufs_hba *hba) +static void ufshcd_complete_requests(struct ufs_hba *hba, bool force_compl) { - ufshcd_transfer_req_compl(hba); + if (is_mcq_enabled(hba)) + ufshcd_mcq_compl_pending_transfer(hba, force_compl); + else + ufshcd_transfer_req_compl(hba); + ufshcd_tmc_handler(hba); } @@ -6241,22 +6292,22 @@ static void ufshcd_err_handling_prepare(struct ufs_hba *hba) ufshcd_setup_vreg(hba, true); ufshcd_config_vreg_hpm(hba, hba->vreg_info.vccq); ufshcd_config_vreg_hpm(hba, hba->vreg_info.vccq2); - ufshcd_hold(hba, false); + ufshcd_hold(hba); if (!ufshcd_is_clkgating_allowed(hba)) ufshcd_setup_clocks(hba, true); ufshcd_release(hba); pm_op = hba->is_sys_suspended ? UFS_SYSTEM_PM : UFS_RUNTIME_PM; ufshcd_vops_resume(hba, pm_op); } else { - ufshcd_hold(hba, false); + ufshcd_hold(hba); if (ufshcd_is_clkscaling_supported(hba) && hba->clk_scaling.is_enabled) ufshcd_suspend_clkscaling(hba); ufshcd_clk_scaling_allow(hba, false); } ufshcd_scsi_block_requests(hba); - /* Drain ufshcd_queuecommand() */ - synchronize_rcu(); + /* Wait for ongoing ufshcd_queuecommand() calls to finish. */ + blk_mq_wait_quiesce_done(&hba->host->tag_set); cancel_work_sync(&hba->eeh_work); } @@ -6338,18 +6389,36 @@ static bool ufshcd_abort_all(struct ufs_hba *hba) bool needs_reset = false; int tag, ret; - /* Clear pending transfer requests */ - for_each_set_bit(tag, &hba->outstanding_reqs, hba->nutrs) { - ret = ufshcd_try_to_abort_task(hba, tag); - dev_err(hba->dev, "Aborting tag %d / CDB %#02x %s\n", tag, - hba->lrb[tag].cmd ? hba->lrb[tag].cmd->cmnd[0] : -1, - ret ? "failed" : "succeeded"); - if (ret) { - needs_reset = true; - goto out; + if (is_mcq_enabled(hba)) { + struct ufshcd_lrb *lrbp; + int tag; + + for (tag = 0; tag < hba->nutrs; tag++) { + lrbp = &hba->lrb[tag]; + if (!ufshcd_cmd_inflight(lrbp->cmd)) + continue; + ret = ufshcd_try_to_abort_task(hba, tag); + dev_err(hba->dev, "Aborting tag %d / CDB %#02x %s\n", tag, + hba->lrb[tag].cmd ? hba->lrb[tag].cmd->cmnd[0] : -1, + ret ? "failed" : "succeeded"); + if (ret) { + needs_reset = true; + goto out; + } + } + } else { + /* Clear pending transfer requests */ + for_each_set_bit(tag, &hba->outstanding_reqs, hba->nutrs) { + ret = ufshcd_try_to_abort_task(hba, tag); + dev_err(hba->dev, "Aborting tag %d / CDB %#02x %s\n", tag, + hba->lrb[tag].cmd ? hba->lrb[tag].cmd->cmnd[0] : -1, + ret ? "failed" : "succeeded"); + if (ret) { + needs_reset = true; + goto out; + } } } - /* Clear pending task management requests */ for_each_set_bit(tag, &hba->outstanding_tasks, hba->nutmrs) { if (ufshcd_clear_tm_cmd(hba, tag)) { @@ -6360,7 +6429,7 @@ static bool ufshcd_abort_all(struct ufs_hba *hba) out: /* Complete the requests that are cleared by s/w */ - ufshcd_complete_requests(hba); + ufshcd_complete_requests(hba, false); return needs_reset; } @@ -6400,7 +6469,7 @@ static void ufshcd_err_handler(struct work_struct *work) spin_unlock_irqrestore(hba->host->host_lock, flags); ufshcd_err_handling_prepare(hba); /* Complete requests that have door-bell cleared by h/w */ - ufshcd_complete_requests(hba); + ufshcd_complete_requests(hba, false); spin_lock_irqsave(hba->host->host_lock, flags); again: needs_restore = false; @@ -6771,7 +6840,7 @@ static irqreturn_t ufshcd_handle_mcq_cq_events(struct ufs_hba *hba) ufshcd_mcq_write_cqis(hba, events, i); if (events & UFSHCD_MCQ_CQIS_TAIL_ENT_PUSH_STS) - ufshcd_mcq_poll_cqe_nolock(hba, hwq); + ufshcd_mcq_poll_cqe_lock(hba, hwq); } return IRQ_HANDLED; @@ -6901,7 +6970,7 @@ static int __ufshcd_issue_tm_cmd(struct ufs_hba *hba, return PTR_ERR(req); req->end_io_data = &wait; - ufshcd_hold(hba, false); + ufshcd_hold(hba); spin_lock_irqsave(host->host_lock, flags); @@ -7037,7 +7106,6 @@ static int ufshcd_issue_devman_upiu_cmd(struct ufs_hba *hba, down_read(&hba->clk_scaling_lock); lrbp = &hba->lrb[tag]; - WARN_ON(lrbp->cmd); lrbp->cmd = NULL; lrbp->task_tag = tag; lrbp->lun = 0; @@ -7138,7 +7206,7 @@ int ufshcd_exec_raw_upiu_cmd(struct ufs_hba *hba, cmd_type = DEV_CMD_TYPE_NOP; fallthrough; case UPIU_TRANSACTION_QUERY_REQ: - ufshcd_hold(hba, false); + ufshcd_hold(hba); mutex_lock(&hba->dev_cmd.lock); err = ufshcd_issue_devman_upiu_cmd(hba, req_upiu, rsp_upiu, desc_buff, buff_len, @@ -7204,12 +7272,11 @@ int ufshcd_advanced_rpmb_req_handler(struct ufs_hba *hba, struct utp_upiu_req *r u16 ehs_len; /* Protects use of hba->reserved_slot. */ - ufshcd_hold(hba, false); + ufshcd_hold(hba); mutex_lock(&hba->dev_cmd.lock); down_read(&hba->clk_scaling_lock); lrbp = &hba->lrb[tag]; - WARN_ON(lrbp->cmd); lrbp->cmd = NULL; lrbp->task_tag = tag; lrbp->lun = UFS_UPIU_RPMB_WLUN; @@ -7281,7 +7348,9 @@ static int ufshcd_eh_device_reset_handler(struct scsi_cmnd *cmd) unsigned long flags, pending_reqs = 0, not_cleared = 0; struct Scsi_Host *host; struct ufs_hba *hba; - u32 pos; + struct ufs_hw_queue *hwq; + struct ufshcd_lrb *lrbp; + u32 pos, not_cleared_mask = 0; int err; u8 resp = 0xF, lun; @@ -7296,6 +7365,20 @@ static int ufshcd_eh_device_reset_handler(struct scsi_cmnd *cmd) goto out; } + if (is_mcq_enabled(hba)) { + for (pos = 0; pos < hba->nutrs; pos++) { + lrbp = &hba->lrb[pos]; + if (ufshcd_cmd_inflight(lrbp->cmd) && + lrbp->lun == lun) { + ufshcd_clear_cmd(hba, pos); + hwq = ufshcd_mcq_req_to_hwq(hba, scsi_cmd_to_rq(lrbp->cmd)); + ufshcd_mcq_poll_cqe_lock(hba, hwq); + } + } + err = 0; + goto out; + } + /* clear the commands that were pending for corresponding LUN */ spin_lock_irqsave(&hba->outstanding_lock, flags); for_each_set_bit(pos, &hba->outstanding_reqs, hba->nutrs) @@ -7304,17 +7387,20 @@ static int ufshcd_eh_device_reset_handler(struct scsi_cmnd *cmd) hba->outstanding_reqs &= ~pending_reqs; spin_unlock_irqrestore(&hba->outstanding_lock, flags); - if (ufshcd_clear_cmds(hba, pending_reqs) < 0) { - spin_lock_irqsave(&hba->outstanding_lock, flags); - not_cleared = pending_reqs & - ufshcd_readl(hba, REG_UTP_TRANSFER_REQ_DOOR_BELL); - hba->outstanding_reqs |= not_cleared; - spin_unlock_irqrestore(&hba->outstanding_lock, flags); + for_each_set_bit(pos, &pending_reqs, hba->nutrs) { + if (ufshcd_clear_cmd(hba, pos) < 0) { + spin_lock_irqsave(&hba->outstanding_lock, flags); + not_cleared = 1U << pos & + ufshcd_readl(hba, REG_UTP_TRANSFER_REQ_DOOR_BELL); + hba->outstanding_reqs |= not_cleared; + not_cleared_mask |= not_cleared; + spin_unlock_irqrestore(&hba->outstanding_lock, flags); - dev_err(hba->dev, "%s: failed to clear requests %#lx\n", - __func__, not_cleared); + dev_err(hba->dev, "%s: failed to clear request %d\n", + __func__, pos); + } } - __ufshcd_transfer_req_compl(hba, pending_reqs & ~not_cleared); + __ufshcd_transfer_req_compl(hba, pending_reqs & ~not_cleared_mask); out: hba->req_abort_count = 0; @@ -7352,7 +7438,7 @@ static void ufshcd_set_req_abort_skip(struct ufs_hba *hba, unsigned long bitmap) * * Returns zero on success, non-zero on failure */ -static int ufshcd_try_to_abort_task(struct ufs_hba *hba, int tag) +int ufshcd_try_to_abort_task(struct ufs_hba *hba, int tag) { struct ufshcd_lrb *lrbp = &hba->lrb[tag]; int err = 0; @@ -7375,6 +7461,20 @@ static int ufshcd_try_to_abort_task(struct ufs_hba *hba, int tag) */ dev_err(hba->dev, "%s: cmd at tag %d not pending in the device.\n", __func__, tag); + if (is_mcq_enabled(hba)) { + /* MCQ mode */ + if (ufshcd_cmd_inflight(lrbp->cmd)) { + /* sleep for max. 200us same delay as in SDB mode */ + usleep_range(100, 200); + continue; + } + /* command completed already */ + dev_err(hba->dev, "%s: cmd at tag=%d is cleared.\n", + __func__, tag); + goto out; + } + + /* Single Doorbell Mode */ reg = ufshcd_readl(hba, REG_UTP_TRANSFER_REQ_DOOR_BELL); if (reg & (1 << tag)) { /* sleep for max. 200us to stabilize */ @@ -7411,7 +7511,7 @@ static int ufshcd_try_to_abort_task(struct ufs_hba *hba, int tag) goto out; } - err = ufshcd_clear_cmds(hba, 1U << tag); + err = ufshcd_clear_cmd(hba, tag); if (err) dev_err(hba->dev, "%s: Failed clearing cmd at tag %d, err %d\n", __func__, tag, err); @@ -7439,14 +7539,17 @@ static int ufshcd_abort(struct scsi_cmnd *cmd) WARN_ONCE(tag < 0, "Invalid tag %d\n", tag); - ufshcd_hold(hba, false); - reg = ufshcd_readl(hba, REG_UTP_TRANSFER_REQ_DOOR_BELL); - /* If command is already aborted/completed, return FAILED. */ - if (!(test_bit(tag, &hba->outstanding_reqs))) { - dev_err(hba->dev, - "%s: cmd at tag %d already completed, outstanding=0x%lx, doorbell=0x%x\n", - __func__, tag, hba->outstanding_reqs, reg); - goto release; + ufshcd_hold(hba); + + if (!is_mcq_enabled(hba)) { + reg = ufshcd_readl(hba, REG_UTP_TRANSFER_REQ_DOOR_BELL); + if (!test_bit(tag, &hba->outstanding_reqs)) { + /* If command is already aborted/completed, return FAILED. */ + dev_err(hba->dev, + "%s: cmd at tag %d already completed, outstanding=0x%lx, doorbell=0x%x\n", + __func__, tag, hba->outstanding_reqs, reg); + goto release; + } } /* Print Transfer Request of aborted task */ @@ -7471,7 +7574,8 @@ static int ufshcd_abort(struct scsi_cmnd *cmd) } hba->req_abort_count++; - if (!(reg & (1 << tag))) { + if (!is_mcq_enabled(hba) && !(reg & (1 << tag))) { + /* only execute this code in single doorbell mode */ dev_err(hba->dev, "%s: cmd was completed, but without a notifying intr, tag = %d", __func__, tag); @@ -7497,6 +7601,12 @@ static int ufshcd_abort(struct scsi_cmnd *cmd) goto release; } + if (is_mcq_enabled(hba)) { + /* MCQ mode. Branch off to handle abort for mcq mode */ + err = ufshcd_mcq_abort(cmd); + goto release; + } + /* Skip task abort in case previous aborts failed and report failure */ if (lrbp->req_abort_skip) { dev_err(hba->dev, "%s: skipping abort\n", __func__); @@ -7552,7 +7662,7 @@ static int ufshcd_host_reset_and_restore(struct ufs_hba *hba) ufshpb_toggle_state(hba, HPB_PRESENT, HPB_RESET); ufshcd_hba_stop(hba); hba->silence_err_logs = true; - ufshcd_complete_requests(hba); + ufshcd_complete_requests(hba, true); hba->silence_err_logs = false; /* scale up clocks to max frequency before full reinitialization */ @@ -8410,6 +8520,41 @@ static int ufshcd_device_params_init(struct ufs_hba *hba) return ret; } +static void ufshcd_set_timestamp_attr(struct ufs_hba *hba) +{ + int err; + struct ufs_query_req *request = NULL; + struct ufs_query_res *response = NULL; + struct ufs_dev_info *dev_info = &hba->dev_info; + struct utp_upiu_query_v4_0 *upiu_data; + + if (dev_info->wspecversion < 0x400) + return; + + ufshcd_hold(hba); + + mutex_lock(&hba->dev_cmd.lock); + + ufshcd_init_query(hba, &request, &response, + UPIU_QUERY_OPCODE_WRITE_ATTR, + QUERY_ATTR_IDN_TIMESTAMP, 0, 0); + + request->query_func = UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST; + + upiu_data = (struct utp_upiu_query_v4_0 *)&request->upiu_req; + + put_unaligned_be64(ktime_get_real_ns(), &upiu_data->osf3); + + err = ufshcd_exec_dev_cmd(hba, DEV_CMD_TYPE_QUERY, QUERY_REQ_TIMEOUT); + + if (err) + dev_err(hba->dev, "%s: failed to set timestamp %d\n", + __func__, err); + + mutex_unlock(&hba->dev_cmd.lock); + ufshcd_release(hba); +} + /** * ufshcd_add_lus - probe and add UFS logical units * @hba: per-adapter instance @@ -8502,11 +8647,15 @@ static int ufshcd_alloc_mcq(struct ufs_hba *hba) static void ufshcd_config_mcq(struct ufs_hba *hba) { int ret; + u32 intrs; ret = ufshcd_mcq_vops_config_esi(hba); dev_info(hba->dev, "ESI %sconfigured\n", ret ? "is not " : ""); - ufshcd_enable_intr(hba, UFSHCD_ENABLE_MCQ_INTRS); + intrs = UFSHCD_ENABLE_MCQ_INTRS; + if (hba->quirks & UFSHCD_QUIRK_MCQ_BROKEN_INTR) + intrs &= ~MCQ_CQ_EVENT_STATUS; + ufshcd_enable_intr(hba, intrs); ufshcd_mcq_make_queues_operational(hba); ufshcd_mcq_config_mac(hba, hba->nutrs); @@ -8594,6 +8743,8 @@ static int ufshcd_device_init(struct ufs_hba *hba, bool init_dev_params) ufshcd_set_ufs_dev_active(hba); ufshcd_force_reset_auto_bkops(hba); + ufshcd_set_timestamp_attr(hba); + /* Gear up to HS gear if supported */ if (hba->max_pwr_info.is_valid) { /* @@ -8774,7 +8925,7 @@ static const struct scsi_host_template ufshcd_driver_template = { .cmd_per_lun = UFSHCD_CMD_PER_LUN, .can_queue = UFSHCD_CAN_QUEUE, .max_segment_size = PRDT_DATA_BYTE_COUNT_MAX, - .max_sectors = (1 << 20) / SECTOR_SIZE, /* 1 MiB */ + .max_sectors = SZ_1M / SECTOR_SIZE, .max_host_blocked = 1, .track_queue_depth = 1, .skip_settle_delay = 1, @@ -9184,7 +9335,8 @@ static int ufshcd_execute_start_stop(struct scsi_device *sdev, }; return scsi_execute_cmd(sdev, cdb, REQ_OP_DRV_IN, /*buffer=*/NULL, - /*bufflen=*/0, /*timeout=*/HZ, /*retries=*/0, &args); + /*bufflen=*/0, /*timeout=*/10 * HZ, /*retries=*/0, + &args); } /** @@ -9430,7 +9582,7 @@ static int __ufshcd_wl_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op) * If we can't transition into any of the low power modes * just gate the clocks. */ - ufshcd_hold(hba, false); + ufshcd_hold(hba); hba->clk_gating.is_suspended = true; if (ufshcd_is_clkscaling_supported(hba)) @@ -9634,6 +9786,7 @@ static int __ufshcd_wl_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op) ret = ufshcd_set_dev_pwr_mode(hba, UFS_ACTIVE_PWR_MODE); if (ret) goto set_old_link_state; + ufshcd_set_timestamp_attr(hba); } if (ufshcd_keep_autobkops_enabled_except_suspend(hba)) @@ -9775,28 +9928,6 @@ static int ufshcd_wl_resume(struct device *dev) } #endif -static void ufshcd_wl_shutdown(struct device *dev) -{ - struct scsi_device *sdev = to_scsi_device(dev); - struct ufs_hba *hba; - - hba = shost_priv(sdev->host); - - down(&hba->host_sem); - hba->shutting_down = true; - up(&hba->host_sem); - - /* Turn on everything while shutting down */ - ufshcd_rpm_get_sync(hba); - scsi_device_quiesce(sdev); - shost_for_each_device(sdev, hba->host) { - if (sdev == hba->ufs_device_wlun) - continue; - scsi_device_quiesce(sdev); - } - __ufshcd_wl_suspend(hba, UFS_SHUTDOWN_PM); -} - /** * ufshcd_suspend - helper function for suspend operations * @hba: per adapter instance @@ -9981,25 +10112,34 @@ int ufshcd_runtime_resume(struct device *dev) EXPORT_SYMBOL(ufshcd_runtime_resume); #endif /* CONFIG_PM */ -/** - * ufshcd_shutdown - shutdown routine - * @hba: per adapter instance - * - * This function would turn off both UFS device and UFS hba - * regulators. It would also disable clocks. - * - * Returns 0 always to allow force shutdown even in case of errors. - */ -int ufshcd_shutdown(struct ufs_hba *hba) +static void ufshcd_wl_shutdown(struct device *dev) { + struct scsi_device *sdev = to_scsi_device(dev); + struct ufs_hba *hba = shost_priv(sdev->host); + + down(&hba->host_sem); + hba->shutting_down = true; + up(&hba->host_sem); + + /* Turn on everything while shutting down */ + ufshcd_rpm_get_sync(hba); + scsi_device_quiesce(sdev); + shost_for_each_device(sdev, hba->host) { + if (sdev == hba->ufs_device_wlun) + continue; + scsi_device_quiesce(sdev); + } + __ufshcd_wl_suspend(hba, UFS_SHUTDOWN_PM); + + /* + * Next, turn off the UFS controller and the UFS regulators. Disable + * clocks. + */ if (ufshcd_is_ufs_dev_poweroff(hba) && ufshcd_is_link_off(hba)) ufshcd_suspend(hba); hba->is_powered = false; - /* allow force shutdown even in case of errors */ - return 0; } -EXPORT_SYMBOL(ufshcd_shutdown); /** * ufshcd_remove - de-allocate SCSI host and host memory space @@ -10226,6 +10366,7 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq) host->max_channel = UFSHCD_MAX_CHANNEL; host->unique_id = host->host_no; host->max_cmd_len = UFS_CDB_SIZE; + host->queuecommand_may_block = !!(hba->caps & UFSHCD_CAP_CLK_GATING); hba->max_pwr_info.is_valid = false; diff --git a/drivers/ufs/core/ufshpb.c b/drivers/ufs/core/ufshpb.c index a46a7666c891b49a8ff7a50f20137367943e919a..255f8b38d0c2d29f2ad016e10229e1039de6e21c 100644 --- a/drivers/ufs/core/ufshpb.c +++ b/drivers/ufs/core/ufshpb.c @@ -30,7 +30,7 @@ static struct kmem_cache *ufshpb_mctx_cache; static mempool_t *ufshpb_mctx_pool; static mempool_t *ufshpb_page_pool; /* A cache size of 2MB can cache ppn in the 1GB range. */ -static unsigned int ufshpb_host_map_kbytes = 2048; +static unsigned int ufshpb_host_map_kbytes = SZ_2K; static int tot_active_srgn_pages; static struct workqueue_struct *ufshpb_wq; @@ -2461,7 +2461,7 @@ static void ufshpb_hpb_lu_prepared(struct ufs_hba *hba) init_success = !ufshpb_check_hpb_reset_query(hba); - pool_size = PAGE_ALIGN(ufshpb_host_map_kbytes * 1024) / PAGE_SIZE; + pool_size = PAGE_ALIGN(ufshpb_host_map_kbytes * SZ_1K) / PAGE_SIZE; if (pool_size > tot_active_srgn_pages) { mempool_resize(ufshpb_mctx_pool, tot_active_srgn_pages); mempool_resize(ufshpb_page_pool, tot_active_srgn_pages); @@ -2527,7 +2527,7 @@ static int ufshpb_init_mem_wq(struct ufs_hba *hba) return -ENOMEM; } - pool_size = PAGE_ALIGN(ufshpb_host_map_kbytes * 1024) / PAGE_SIZE; + pool_size = PAGE_ALIGN(ufshpb_host_map_kbytes * SZ_1K) / PAGE_SIZE; dev_info(hba->dev, "%s:%d ufshpb_host_map_kbytes %u pool_size %u\n", __func__, __LINE__, ufshpb_host_map_kbytes, pool_size); diff --git a/drivers/ufs/core/ufshpb.h b/drivers/ufs/core/ufshpb.h index 0d6e6004d7837b7b3c1c0508c6c76c0f5d1d7ffd..b428bbdd27992db14011a986ed98118a5d5bd1de 100644 --- a/drivers/ufs/core/ufshpb.h +++ b/drivers/ufs/core/ufshpb.h @@ -25,7 +25,7 @@ /* hpb map & entries macro */ #define HPB_RGN_SIZE_UNIT 512 -#define HPB_ENTRY_BLOCK_SIZE 4096 +#define HPB_ENTRY_BLOCK_SIZE SZ_4K #define HPB_ENTRY_SIZE 0x8 #define PINNED_NOT_SET U32_MAX diff --git a/drivers/ufs/host/Kconfig b/drivers/ufs/host/Kconfig index 8793e343358061a6f3a1166d806d126a18970b01..580c8d0bd8bbd812fed5c2363c3af382b7e5511b 100644 --- a/drivers/ufs/host/Kconfig +++ b/drivers/ufs/host/Kconfig @@ -59,7 +59,7 @@ config SCSI_UFS_QCOM depends on SCSI_UFSHCD_PLATFORM && ARCH_QCOM depends on GENERIC_MSI_IRQ depends on RESET_CONTROLLER - select QCOM_SCM if SCSI_UFS_CRYPTO + select QCOM_INLINE_CRYPTO_ENGINE if SCSI_UFS_CRYPTO help This selects the QCOM specific additions to UFSHCD platform driver. UFS host on QCOM needs some vendor specific configuration before @@ -72,6 +72,7 @@ config SCSI_UFS_QCOM config SCSI_UFS_MEDIATEK tristate "Mediatek specific hooks to UFS controller platform driver" depends on SCSI_UFSHCD_PLATFORM && ARCH_MEDIATEK + depends on RESET_CONTROLLER select PHY_MTK_UFS select RESET_TI_SYSCON help diff --git a/drivers/ufs/host/Makefile b/drivers/ufs/host/Makefile index d7c5bf7fa512df55359cbf04e0cf2b80072a20e7..4573aead02ebf61bfc6f9181c0326cf4a635fe9d 100644 --- a/drivers/ufs/host/Makefile +++ b/drivers/ufs/host/Makefile @@ -3,9 +3,7 @@ obj-$(CONFIG_SCSI_UFS_DWC_TC_PCI) += tc-dwc-g210-pci.o ufshcd-dwc.o tc-dwc-g210.o obj-$(CONFIG_SCSI_UFS_DWC_TC_PLATFORM) += tc-dwc-g210-pltfrm.o ufshcd-dwc.o tc-dwc-g210.o obj-$(CONFIG_SCSI_UFS_CDNS_PLATFORM) += cdns-pltfrm.o -obj-$(CONFIG_SCSI_UFS_QCOM) += ufs_qcom.o -ufs_qcom-y += ufs-qcom.o -ufs_qcom-$(CONFIG_SCSI_UFS_CRYPTO) += ufs-qcom-ice.o +obj-$(CONFIG_SCSI_UFS_QCOM) += ufs-qcom.o obj-$(CONFIG_SCSI_UFS_EXYNOS) += ufs-exynos.o obj-$(CONFIG_SCSI_UFSHCD_PCI) += ufshcd-pci.o obj-$(CONFIG_SCSI_UFSHCD_PLATFORM) += ufshcd-pltfrm.o diff --git a/drivers/ufs/host/cdns-pltfrm.c b/drivers/ufs/host/cdns-pltfrm.c index e05c0ae64eea47e8e1fea3d9aea01b0086acbbf0..26761425a76cae0160424332cc5e621fe64efe70 100644 --- a/drivers/ufs/host/cdns-pltfrm.c +++ b/drivers/ufs/host/cdns-pltfrm.c @@ -328,7 +328,6 @@ static const struct dev_pm_ops cdns_ufs_dev_pm_ops = { static struct platform_driver cdns_ufs_pltfrm_driver = { .probe = cdns_ufs_pltfrm_probe, .remove = cdns_ufs_pltfrm_remove, - .shutdown = ufshcd_pltfrm_shutdown, .driver = { .name = "cdns-ufshcd", .pm = &cdns_ufs_dev_pm_ops, diff --git a/drivers/ufs/host/tc-dwc-g210-pci.c b/drivers/ufs/host/tc-dwc-g210-pci.c index 92b8ad4b58febe1bf5289ad4eb31846dc6e71880..f96fe58558417e35810c8ffb8acd1a851932d4cf 100644 --- a/drivers/ufs/host/tc-dwc-g210-pci.c +++ b/drivers/ufs/host/tc-dwc-g210-pci.c @@ -32,15 +32,6 @@ static struct ufs_hba_variant_ops tc_dwc_g210_pci_hba_vops = { .link_startup_notify = ufshcd_dwc_link_startup_notify, }; -/** - * tc_dwc_g210_pci_shutdown - main function to put the controller in reset state - * @pdev: pointer to PCI device handle - */ -static void tc_dwc_g210_pci_shutdown(struct pci_dev *pdev) -{ - ufshcd_shutdown((struct ufs_hba *)pci_get_drvdata(pdev)); -} - /** * tc_dwc_g210_pci_remove - de-allocate PCI/SCSI host and host memory space * data structure memory @@ -137,7 +128,6 @@ static struct pci_driver tc_dwc_g210_pci_driver = { .id_table = tc_dwc_g210_pci_tbl, .probe = tc_dwc_g210_pci_probe, .remove = tc_dwc_g210_pci_remove, - .shutdown = tc_dwc_g210_pci_shutdown, .driver = { .pm = &tc_dwc_g210_pci_pm_ops }, diff --git a/drivers/ufs/host/tc-dwc-g210-pltfrm.c b/drivers/ufs/host/tc-dwc-g210-pltfrm.c index f15a84d0c176b6edd564de450e7f34a3d0f93ca7..4d5389dd958579e9b9eea44f3478d40942e224e3 100644 --- a/drivers/ufs/host/tc-dwc-g210-pltfrm.c +++ b/drivers/ufs/host/tc-dwc-g210-pltfrm.c @@ -92,7 +92,6 @@ static const struct dev_pm_ops tc_dwc_g210_pltfm_pm_ops = { static struct platform_driver tc_dwc_g210_pltfm_driver = { .probe = tc_dwc_g210_pltfm_probe, .remove = tc_dwc_g210_pltfm_remove, - .shutdown = ufshcd_pltfrm_shutdown, .driver = { .name = "tc-dwc-g210-pltfm", .pm = &tc_dwc_g210_pltfm_pm_ops, diff --git a/drivers/ufs/host/ufs-exynos.c b/drivers/ufs/host/ufs-exynos.c index 0bf5390739e1f0200d4b1b8609c86082a0470cc4..3396e0388512c74e08d8f423ffe160c2bb808471 100644 --- a/drivers/ufs/host/ufs-exynos.c +++ b/drivers/ufs/host/ufs-exynos.c @@ -1306,7 +1306,7 @@ static int exynos_ufs_hce_enable_notify(struct ufs_hba *hba, * (ufshcd_async_scan()). Note: this callback may also be called * from other functions than ufshcd_init(). */ - hba->host->max_segment_size = 4096; + hba->host->max_segment_size = SZ_4K; if (ufs->drv_data->pre_hce_enable) { ret = ufs->drv_data->pre_hce_enable(ufs); @@ -1757,7 +1757,6 @@ static const struct dev_pm_ops exynos_ufs_pm_ops = { static struct platform_driver exynos_ufs_pltform = { .probe = exynos_ufs_probe, .remove = exynos_ufs_remove, - .shutdown = ufshcd_pltfrm_shutdown, .driver = { .name = "exynos-ufshc", .pm = &exynos_ufs_pm_ops, diff --git a/drivers/ufs/host/ufs-hisi.c b/drivers/ufs/host/ufs-hisi.c index 4c423eba8aa929ec5fd8c156e1862ef68277da76..5b3060cd0ab8b80625b309c869b805032b2e60d5 100644 --- a/drivers/ufs/host/ufs-hisi.c +++ b/drivers/ufs/host/ufs-hisi.c @@ -335,29 +335,29 @@ static void ufs_hisi_pwr_change_pre_change(struct ufs_hba *hba) /* PA_TxSkip */ ufshcd_dme_set(hba, UIC_ARG_MIB(0x155c), 0x0); /*PA_PWRModeUserData0 = 8191, default is 0*/ - ufshcd_dme_set(hba, UIC_ARG_MIB(0x15b0), 8191); + ufshcd_dme_set(hba, UIC_ARG_MIB(0x15b0), SZ_8K - 1); /*PA_PWRModeUserData1 = 65535, default is 0*/ - ufshcd_dme_set(hba, UIC_ARG_MIB(0x15b1), 65535); + ufshcd_dme_set(hba, UIC_ARG_MIB(0x15b1), SZ_64K - 1); /*PA_PWRModeUserData2 = 32767, default is 0*/ - ufshcd_dme_set(hba, UIC_ARG_MIB(0x15b2), 32767); + ufshcd_dme_set(hba, UIC_ARG_MIB(0x15b2), SZ_32K - 1); /*DME_FC0ProtectionTimeOutVal = 8191, default is 0*/ - ufshcd_dme_set(hba, UIC_ARG_MIB(0xd041), 8191); + ufshcd_dme_set(hba, UIC_ARG_MIB(0xd041), SZ_8K - 1); /*DME_TC0ReplayTimeOutVal = 65535, default is 0*/ - ufshcd_dme_set(hba, UIC_ARG_MIB(0xd042), 65535); + ufshcd_dme_set(hba, UIC_ARG_MIB(0xd042), SZ_64K - 1); /*DME_AFC0ReqTimeOutVal = 32767, default is 0*/ - ufshcd_dme_set(hba, UIC_ARG_MIB(0xd043), 32767); + ufshcd_dme_set(hba, UIC_ARG_MIB(0xd043), SZ_32K - 1); /*PA_PWRModeUserData3 = 8191, default is 0*/ - ufshcd_dme_set(hba, UIC_ARG_MIB(0x15b3), 8191); + ufshcd_dme_set(hba, UIC_ARG_MIB(0x15b3), SZ_8K - 1); /*PA_PWRModeUserData4 = 65535, default is 0*/ - ufshcd_dme_set(hba, UIC_ARG_MIB(0x15b4), 65535); + ufshcd_dme_set(hba, UIC_ARG_MIB(0x15b4), SZ_64K - 1); /*PA_PWRModeUserData5 = 32767, default is 0*/ - ufshcd_dme_set(hba, UIC_ARG_MIB(0x15b5), 32767); + ufshcd_dme_set(hba, UIC_ARG_MIB(0x15b5), SZ_32K - 1); /*DME_FC1ProtectionTimeOutVal = 8191, default is 0*/ - ufshcd_dme_set(hba, UIC_ARG_MIB(0xd044), 8191); + ufshcd_dme_set(hba, UIC_ARG_MIB(0xd044), SZ_8K - 1); /*DME_TC1ReplayTimeOutVal = 65535, default is 0*/ - ufshcd_dme_set(hba, UIC_ARG_MIB(0xd045), 65535); + ufshcd_dme_set(hba, UIC_ARG_MIB(0xd045), SZ_64K - 1); /*DME_AFC1ReqTimeOutVal = 32767, default is 0*/ - ufshcd_dme_set(hba, UIC_ARG_MIB(0xd046), 32767); + ufshcd_dme_set(hba, UIC_ARG_MIB(0xd046), SZ_32K - 1); } static int ufs_hisi_pwr_change_notify(struct ufs_hba *hba, @@ -593,7 +593,6 @@ static const struct dev_pm_ops ufs_hisi_pm_ops = { static struct platform_driver ufs_hisi_pltform = { .probe = ufs_hisi_probe, .remove = ufs_hisi_remove, - .shutdown = ufshcd_pltfrm_shutdown, .driver = { .name = "ufshcd-hisi", .pm = &ufs_hisi_pm_ops, diff --git a/drivers/ufs/host/ufs-mediatek.c b/drivers/ufs/host/ufs-mediatek.c index 73e217260390ef5fa75002b1a9d0ba068e2779b2..e68b05976f9ebd7bbee8b29f96c309dd2ddbf80c 100644 --- a/drivers/ufs/host/ufs-mediatek.c +++ b/drivers/ufs/host/ufs-mediatek.c @@ -410,9 +410,6 @@ static int ufs_mtk_wait_link_state(struct ufs_hba *hba, u32 state, usleep_range(100, 200); } while (ktime_before(time_checked, timeout)); - if (val == state) - return 0; - return -ETIMEDOUT; } @@ -901,6 +898,8 @@ static int ufs_mtk_init(struct ufs_hba *hba) hba->caps |= UFSHCD_CAP_CLK_SCALING; hba->quirks |= UFSHCI_QUIRK_SKIP_MANUAL_WB_FLUSH_CTRL; + hba->quirks |= UFSHCD_QUIRK_MCQ_BROKEN_INTR; + hba->quirks |= UFSHCD_QUIRK_MCQ_BROKEN_RTC; hba->vps->wb_flush_threshold = UFS_WB_BUF_REMAIN_PERCENT(80); if (host->caps & UFS_MTK_CAP_DISABLE_AH8) @@ -1650,7 +1649,6 @@ static const struct dev_pm_ops ufs_mtk_pm_ops = { static struct platform_driver ufs_mtk_pltform = { .probe = ufs_mtk_probe, .remove = ufs_mtk_remove, - .shutdown = ufshcd_pltfrm_shutdown, .driver = { .name = "ufshcd-mtk", .pm = &ufs_mtk_pm_ops, diff --git a/drivers/ufs/host/ufs-qcom-ice.c b/drivers/ufs/host/ufs-qcom-ice.c deleted file mode 100644 index 453978877ae969f8489f8d14baf80fe3111e6f2d..0000000000000000000000000000000000000000 --- a/drivers/ufs/host/ufs-qcom-ice.c +++ /dev/null @@ -1,244 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Qualcomm ICE (Inline Crypto Engine) support. - * - * Copyright (c) 2014-2019, The Linux Foundation. All rights reserved. - * Copyright 2019 Google LLC - */ - -#include -#include -#include - -#include "ufs-qcom.h" - -#define AES_256_XTS_KEY_SIZE 64 - -/* QCOM ICE registers */ - -#define QCOM_ICE_REG_CONTROL 0x0000 -#define QCOM_ICE_REG_RESET 0x0004 -#define QCOM_ICE_REG_VERSION 0x0008 -#define QCOM_ICE_REG_FUSE_SETTING 0x0010 -#define QCOM_ICE_REG_PARAMETERS_1 0x0014 -#define QCOM_ICE_REG_PARAMETERS_2 0x0018 -#define QCOM_ICE_REG_PARAMETERS_3 0x001C -#define QCOM_ICE_REG_PARAMETERS_4 0x0020 -#define QCOM_ICE_REG_PARAMETERS_5 0x0024 - -/* QCOM ICE v3.X only */ -#define QCOM_ICE_GENERAL_ERR_STTS 0x0040 -#define QCOM_ICE_INVALID_CCFG_ERR_STTS 0x0030 -#define QCOM_ICE_GENERAL_ERR_MASK 0x0044 - -/* QCOM ICE v2.X only */ -#define QCOM_ICE_REG_NON_SEC_IRQ_STTS 0x0040 -#define QCOM_ICE_REG_NON_SEC_IRQ_MASK 0x0044 - -#define QCOM_ICE_REG_NON_SEC_IRQ_CLR 0x0048 -#define QCOM_ICE_REG_STREAM1_ERROR_SYNDROME1 0x0050 -#define QCOM_ICE_REG_STREAM1_ERROR_SYNDROME2 0x0054 -#define QCOM_ICE_REG_STREAM2_ERROR_SYNDROME1 0x0058 -#define QCOM_ICE_REG_STREAM2_ERROR_SYNDROME2 0x005C -#define QCOM_ICE_REG_STREAM1_BIST_ERROR_VEC 0x0060 -#define QCOM_ICE_REG_STREAM2_BIST_ERROR_VEC 0x0064 -#define QCOM_ICE_REG_STREAM1_BIST_FINISH_VEC 0x0068 -#define QCOM_ICE_REG_STREAM2_BIST_FINISH_VEC 0x006C -#define QCOM_ICE_REG_BIST_STATUS 0x0070 -#define QCOM_ICE_REG_BYPASS_STATUS 0x0074 -#define QCOM_ICE_REG_ADVANCED_CONTROL 0x1000 -#define QCOM_ICE_REG_ENDIAN_SWAP 0x1004 -#define QCOM_ICE_REG_TEST_BUS_CONTROL 0x1010 -#define QCOM_ICE_REG_TEST_BUS_REG 0x1014 - -/* BIST ("built-in self-test"?) status flags */ -#define QCOM_ICE_BIST_STATUS_MASK 0xF0000000 - -#define QCOM_ICE_FUSE_SETTING_MASK 0x1 -#define QCOM_ICE_FORCE_HW_KEY0_SETTING_MASK 0x2 -#define QCOM_ICE_FORCE_HW_KEY1_SETTING_MASK 0x4 - -#define qcom_ice_writel(host, val, reg) \ - writel((val), (host)->ice_mmio + (reg)) -#define qcom_ice_readl(host, reg) \ - readl((host)->ice_mmio + (reg)) - -static bool qcom_ice_supported(struct ufs_qcom_host *host) -{ - struct device *dev = host->hba->dev; - u32 regval = qcom_ice_readl(host, QCOM_ICE_REG_VERSION); - int major = regval >> 24; - int minor = (regval >> 16) & 0xFF; - int step = regval & 0xFFFF; - - /* For now this driver only supports ICE version 3. */ - if (major != 3) { - dev_warn(dev, "Unsupported ICE version: v%d.%d.%d\n", - major, minor, step); - return false; - } - - dev_info(dev, "Found QC Inline Crypto Engine (ICE) v%d.%d.%d\n", - major, minor, step); - - /* If fuses are blown, ICE might not work in the standard way. */ - regval = qcom_ice_readl(host, QCOM_ICE_REG_FUSE_SETTING); - if (regval & (QCOM_ICE_FUSE_SETTING_MASK | - QCOM_ICE_FORCE_HW_KEY0_SETTING_MASK | - QCOM_ICE_FORCE_HW_KEY1_SETTING_MASK)) { - dev_warn(dev, "Fuses are blown; ICE is unusable!\n"); - return false; - } - return true; -} - -int ufs_qcom_ice_init(struct ufs_qcom_host *host) -{ - struct ufs_hba *hba = host->hba; - struct device *dev = hba->dev; - struct platform_device *pdev = to_platform_device(dev); - struct resource *res; - int err; - - if (!(ufshcd_readl(hba, REG_CONTROLLER_CAPABILITIES) & - MASK_CRYPTO_SUPPORT)) - return 0; - - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ice"); - if (!res) { - dev_warn(dev, "ICE registers not found\n"); - goto disable; - } - - if (!qcom_scm_ice_available()) { - dev_warn(dev, "ICE SCM interface not found\n"); - goto disable; - } - - host->ice_mmio = devm_ioremap_resource(dev, res); - if (IS_ERR(host->ice_mmio)) { - err = PTR_ERR(host->ice_mmio); - return err; - } - - if (!qcom_ice_supported(host)) - goto disable; - - return 0; - -disable: - dev_warn(dev, "Disabling inline encryption support\n"); - hba->caps &= ~UFSHCD_CAP_CRYPTO; - return 0; -} - -static void qcom_ice_low_power_mode_enable(struct ufs_qcom_host *host) -{ - u32 regval; - - regval = qcom_ice_readl(host, QCOM_ICE_REG_ADVANCED_CONTROL); - /* - * Enable low power mode sequence - * [0]-0, [1]-0, [2]-0, [3]-E, [4]-0, [5]-0, [6]-0, [7]-0 - */ - regval |= 0x7000; - qcom_ice_writel(host, regval, QCOM_ICE_REG_ADVANCED_CONTROL); -} - -static void qcom_ice_optimization_enable(struct ufs_qcom_host *host) -{ - u32 regval; - - /* ICE Optimizations Enable Sequence */ - regval = qcom_ice_readl(host, QCOM_ICE_REG_ADVANCED_CONTROL); - regval |= 0xD807100; - /* ICE HPG requires delay before writing */ - udelay(5); - qcom_ice_writel(host, regval, QCOM_ICE_REG_ADVANCED_CONTROL); - udelay(5); -} - -int ufs_qcom_ice_enable(struct ufs_qcom_host *host) -{ - if (!(host->hba->caps & UFSHCD_CAP_CRYPTO)) - return 0; - qcom_ice_low_power_mode_enable(host); - qcom_ice_optimization_enable(host); - return ufs_qcom_ice_resume(host); -} - -/* Poll until all BIST bits are reset */ -static int qcom_ice_wait_bist_status(struct ufs_qcom_host *host) -{ - int count; - u32 reg; - - for (count = 0; count < 100; count++) { - reg = qcom_ice_readl(host, QCOM_ICE_REG_BIST_STATUS); - if (!(reg & QCOM_ICE_BIST_STATUS_MASK)) - break; - udelay(50); - } - if (reg) - return -ETIMEDOUT; - return 0; -} - -int ufs_qcom_ice_resume(struct ufs_qcom_host *host) -{ - int err; - - if (!(host->hba->caps & UFSHCD_CAP_CRYPTO)) - return 0; - - err = qcom_ice_wait_bist_status(host); - if (err) { - dev_err(host->hba->dev, "BIST status error (%d)\n", err); - return err; - } - return 0; -} - -/* - * Program a key into a QC ICE keyslot, or evict a keyslot. QC ICE requires - * vendor-specific SCM calls for this; it doesn't support the standard way. - */ -int ufs_qcom_ice_program_key(struct ufs_hba *hba, - const union ufs_crypto_cfg_entry *cfg, int slot) -{ - union ufs_crypto_cap_entry cap; - union { - u8 bytes[AES_256_XTS_KEY_SIZE]; - u32 words[AES_256_XTS_KEY_SIZE / sizeof(u32)]; - } key; - int i; - int err; - - if (!(cfg->config_enable & UFS_CRYPTO_CONFIGURATION_ENABLE)) - return qcom_scm_ice_invalidate_key(slot); - - /* Only AES-256-XTS has been tested so far. */ - cap = hba->crypto_cap_array[cfg->crypto_cap_idx]; - if (cap.algorithm_id != UFS_CRYPTO_ALG_AES_XTS || - cap.key_size != UFS_CRYPTO_KEY_SIZE_256) { - dev_err_ratelimited(hba->dev, - "Unhandled crypto capability; algorithm_id=%d, key_size=%d\n", - cap.algorithm_id, cap.key_size); - return -EINVAL; - } - - memcpy(key.bytes, cfg->crypto_key, AES_256_XTS_KEY_SIZE); - - /* - * The SCM call byte-swaps the 32-bit words of the key. So we have to - * do the same, in order for the final key be correct. - */ - for (i = 0; i < ARRAY_SIZE(key.words); i++) - __cpu_to_be32s(&key.words[i]); - - err = qcom_scm_ice_set_key(slot, key.bytes, AES_256_XTS_KEY_SIZE, - QCOM_SCM_ICE_CIPHER_AES_256_XTS, - cfg->data_unit_size); - memzero_explicit(&key, sizeof(key)); - return err; -} diff --git a/drivers/ufs/host/ufs-qcom.c b/drivers/ufs/host/ufs-qcom.c index 82d02e7f3b4f31cf48656d90aa98bd628b320146..8d6fd4c3324f26d7e7100f8a2645ead3dbb4a05b 100644 --- a/drivers/ufs/host/ufs-qcom.c +++ b/drivers/ufs/host/ufs-qcom.c @@ -15,6 +15,8 @@ #include #include +#include + #include #include "ufshcd-pltfrm.h" #include @@ -55,6 +57,100 @@ static struct ufs_qcom_host *rcdev_to_ufs_host(struct reset_controller_dev *rcd) return container_of(rcd, struct ufs_qcom_host, rcdev); } +#ifdef CONFIG_SCSI_UFS_CRYPTO + +static inline void ufs_qcom_ice_enable(struct ufs_qcom_host *host) +{ + if (host->hba->caps & UFSHCD_CAP_CRYPTO) + qcom_ice_enable(host->ice); +} + +static int ufs_qcom_ice_init(struct ufs_qcom_host *host) +{ + struct ufs_hba *hba = host->hba; + struct device *dev = hba->dev; + struct qcom_ice *ice; + + ice = of_qcom_ice_get(dev); + if (ice == ERR_PTR(-EOPNOTSUPP)) { + dev_warn(dev, "Disabling inline encryption support\n"); + ice = NULL; + } + + if (IS_ERR_OR_NULL(ice)) + return PTR_ERR_OR_ZERO(ice); + + host->ice = ice; + hba->caps |= UFSHCD_CAP_CRYPTO; + + return 0; +} + +static inline int ufs_qcom_ice_resume(struct ufs_qcom_host *host) +{ + if (host->hba->caps & UFSHCD_CAP_CRYPTO) + return qcom_ice_resume(host->ice); + + return 0; +} + +static inline int ufs_qcom_ice_suspend(struct ufs_qcom_host *host) +{ + if (host->hba->caps & UFSHCD_CAP_CRYPTO) + return qcom_ice_suspend(host->ice); + + return 0; +} + +static int ufs_qcom_ice_program_key(struct ufs_hba *hba, + const union ufs_crypto_cfg_entry *cfg, + int slot) +{ + struct ufs_qcom_host *host = ufshcd_get_variant(hba); + union ufs_crypto_cap_entry cap; + bool config_enable = + cfg->config_enable & UFS_CRYPTO_CONFIGURATION_ENABLE; + + /* Only AES-256-XTS has been tested so far. */ + cap = hba->crypto_cap_array[cfg->crypto_cap_idx]; + if (cap.algorithm_id != UFS_CRYPTO_ALG_AES_XTS || + cap.key_size != UFS_CRYPTO_KEY_SIZE_256) + return -EINVAL; + + if (config_enable) + return qcom_ice_program_key(host->ice, + QCOM_ICE_CRYPTO_ALG_AES_XTS, + QCOM_ICE_CRYPTO_KEY_SIZE_256, + cfg->crypto_key, + cfg->data_unit_size, slot); + else + return qcom_ice_evict_key(host->ice, slot); +} + +#else + +#define ufs_qcom_ice_program_key NULL + +static inline void ufs_qcom_ice_enable(struct ufs_qcom_host *host) +{ +} + +static int ufs_qcom_ice_init(struct ufs_qcom_host *host) +{ + return 0; +} + +static inline int ufs_qcom_ice_resume(struct ufs_qcom_host *host) +{ + return 0; +} + +static inline int ufs_qcom_ice_suspend(struct ufs_qcom_host *host) +{ + return 0; +} +#endif + static int ufs_qcom_host_clk_get(struct device *dev, const char *name, struct clk **clk_out, bool optional) { @@ -607,7 +703,7 @@ static int ufs_qcom_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op, ufs_qcom_disable_lane_clks(host); } - return 0; + return ufs_qcom_ice_suspend(host); } static int ufs_qcom_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op) @@ -853,7 +949,6 @@ static void ufs_qcom_set_caps(struct ufs_hba *hba) hba->caps |= UFSHCD_CAP_CLK_SCALING | UFSHCD_CAP_WB_WITH_CLK_SCALING; hba->caps |= UFSHCD_CAP_AUTO_BKOPS_SUSPEND; hba->caps |= UFSHCD_CAP_WB_EN; - hba->caps |= UFSHCD_CAP_CRYPTO; hba->caps |= UFSHCD_CAP_AGGR_POWER_COLLAPSE; hba->caps |= UFSHCD_CAP_RPM_AUTOSUSPEND; @@ -1556,7 +1651,7 @@ static irqreturn_t ufs_qcom_mcq_esi_handler(int irq, void *__hba) struct ufs_hw_queue *hwq = &hba->uhq[id]; ufshcd_mcq_write_cqis(hba, 0x1, id); - ufshcd_mcq_poll_cqe_nolock(hba, hwq); + ufshcd_mcq_poll_cqe_lock(hba, hwq); return IRQ_HANDLED; } @@ -1723,7 +1818,6 @@ static const struct dev_pm_ops ufs_qcom_pm_ops = { static struct platform_driver ufs_qcom_pltform = { .probe = ufs_qcom_probe, .remove = ufs_qcom_remove, - .shutdown = ufshcd_pltfrm_shutdown, .driver = { .name = "ufshcd-qcom", .pm = &ufs_qcom_pm_ops, diff --git a/drivers/ufs/host/ufs-qcom.h b/drivers/ufs/host/ufs-qcom.h index 39e774254fb2de6aef368b3772e8f0b3023be773..6289ad5a42d0b799eb08663b4f4d6df49b851bff 100644 --- a/drivers/ufs/host/ufs-qcom.h +++ b/drivers/ufs/host/ufs-qcom.h @@ -7,6 +7,7 @@ #include #include +#include #include #define MAX_UFS_QCOM_HOSTS 1 @@ -205,12 +206,13 @@ struct ufs_qcom_host { struct clk *tx_l1_sync_clk; bool is_lane_clks_enabled; +#ifdef CONFIG_SCSI_UFS_CRYPTO + struct qcom_ice *ice; +#endif + void __iomem *dev_ref_clk_ctrl_mmio; bool is_dev_ref_clk_enabled; struct ufs_hw_version hw_ver; -#ifdef CONFIG_SCSI_UFS_CRYPTO - void __iomem *ice_mmio; -#endif u32 dev_ref_clk_en_mask; @@ -248,28 +250,4 @@ static inline bool ufs_qcom_cap_qunipro(struct ufs_qcom_host *host) return host->caps & UFS_QCOM_CAP_QUNIPRO; } -/* ufs-qcom-ice.c */ - -#ifdef CONFIG_SCSI_UFS_CRYPTO -int ufs_qcom_ice_init(struct ufs_qcom_host *host); -int ufs_qcom_ice_enable(struct ufs_qcom_host *host); -int ufs_qcom_ice_resume(struct ufs_qcom_host *host); -int ufs_qcom_ice_program_key(struct ufs_hba *hba, - const union ufs_crypto_cfg_entry *cfg, int slot); -#else -static inline int ufs_qcom_ice_init(struct ufs_qcom_host *host) -{ - return 0; -} -static inline int ufs_qcom_ice_enable(struct ufs_qcom_host *host) -{ - return 0; -} -static inline int ufs_qcom_ice_resume(struct ufs_qcom_host *host) -{ - return 0; -} -#define ufs_qcom_ice_program_key NULL -#endif /* !CONFIG_SCSI_UFS_CRYPTO */ - #endif /* UFS_QCOM_H_ */ diff --git a/drivers/ufs/host/ufs-sprd.c b/drivers/ufs/host/ufs-sprd.c index 051f3f40d92cd8f8f1544355e2251ab53cad7b6b..2bad75dd6d5894fd6928472a592e94154c0189b7 100644 --- a/drivers/ufs/host/ufs-sprd.c +++ b/drivers/ufs/host/ufs-sprd.c @@ -444,7 +444,6 @@ static const struct dev_pm_ops ufs_sprd_pm_ops = { static struct platform_driver ufs_sprd_pltform = { .probe = ufs_sprd_probe, .remove = ufs_sprd_remove, - .shutdown = ufshcd_pltfrm_shutdown, .driver = { .name = "ufshcd-sprd", .pm = &ufs_sprd_pm_ops, diff --git a/drivers/ufs/host/ufshcd-pci.c b/drivers/ufs/host/ufshcd-pci.c index 9c911787f84c6fb4b9e318dde7d113098b4b4f1f..cf3987773051f0890945c9d9a10904a1389d037b 100644 --- a/drivers/ufs/host/ufshcd-pci.c +++ b/drivers/ufs/host/ufshcd-pci.c @@ -504,15 +504,6 @@ static int ufshcd_pci_restore(struct device *dev) } #endif -/** - * ufshcd_pci_shutdown - main function to put the controller in reset state - * @pdev: pointer to PCI device handle - */ -static void ufshcd_pci_shutdown(struct pci_dev *pdev) -{ - ufshcd_shutdown((struct ufs_hba *)pci_get_drvdata(pdev)); -} - /** * ufshcd_pci_remove - de-allocate PCI/SCSI host and host memory space * data structure memory @@ -608,6 +599,7 @@ static const struct pci_device_id ufshcd_pci_tbl[] = { { PCI_VDEVICE(INTEL, 0x54FF), (kernel_ulong_t)&ufs_intel_adl_hba_vops }, { PCI_VDEVICE(INTEL, 0x7E47), (kernel_ulong_t)&ufs_intel_mtl_hba_vops }, { PCI_VDEVICE(INTEL, 0xA847), (kernel_ulong_t)&ufs_intel_mtl_hba_vops }, + { PCI_VDEVICE(INTEL, 0x7747), (kernel_ulong_t)&ufs_intel_mtl_hba_vops }, { } /* terminate list */ }; @@ -618,7 +610,6 @@ static struct pci_driver ufshcd_pci_driver = { .id_table = ufshcd_pci_tbl, .probe = ufshcd_pci_probe, .remove = ufshcd_pci_remove, - .shutdown = ufshcd_pci_shutdown, .driver = { .pm = &ufshcd_pci_pm_ops }, diff --git a/drivers/ufs/host/ufshcd-pltfrm.c b/drivers/ufs/host/ufshcd-pltfrm.c index 5739ff0078287bc6c3ce15fb23219cb7b4398a10..0b7430033047d4ce3afc5b0ccb4fabb627668108 100644 --- a/drivers/ufs/host/ufshcd-pltfrm.c +++ b/drivers/ufs/host/ufshcd-pltfrm.c @@ -190,12 +190,6 @@ static int ufshcd_parse_regulator_info(struct ufs_hba *hba) return err; } -void ufshcd_pltfrm_shutdown(struct platform_device *pdev) -{ - ufshcd_shutdown((struct ufs_hba *)platform_get_drvdata(pdev)); -} -EXPORT_SYMBOL_GPL(ufshcd_pltfrm_shutdown); - static void ufshcd_init_lanes_per_dir(struct ufs_hba *hba) { struct device *dev = hba->dev; diff --git a/drivers/ufs/host/ufshcd-pltfrm.h b/drivers/ufs/host/ufshcd-pltfrm.h index 2e4ba2bfbcada0ba15e740a7d968731c6c76f3a7..2df108f4ac131904b8230a8250f5996a1c041cdc 100644 --- a/drivers/ufs/host/ufshcd-pltfrm.h +++ b/drivers/ufs/host/ufshcd-pltfrm.h @@ -31,7 +31,6 @@ int ufshcd_get_pwr_dev_param(const struct ufs_dev_params *dev_param, void ufshcd_init_pwr_dev_param(struct ufs_dev_params *dev_param); int ufshcd_pltfrm_init(struct platform_device *pdev, const struct ufs_hba_variant_ops *vops); -void ufshcd_pltfrm_shutdown(struct platform_device *pdev); int ufshcd_populate_vreg(struct device *dev, const char *name, struct ufs_vreg **out_vreg); diff --git a/drivers/uio/uio_dfl.c b/drivers/uio/uio_dfl.c index 69e93f3e7faf4bf1e1cdbd587305b198cd68be6c..6d99e5a06ae8c27a100f35f3e8076385b0d6b3d5 100644 --- a/drivers/uio/uio_dfl.c +++ b/drivers/uio/uio_dfl.c @@ -46,11 +46,13 @@ static int uio_dfl_probe(struct dfl_device *ddev) #define FME_FEATURE_ID_ETH_GROUP 0x10 #define FME_FEATURE_ID_HSSI_SUBSYS 0x15 +#define FME_FEATURE_ID_VENDOR_SPECIFIC 0x23 #define PORT_FEATURE_ID_IOPLL_USRCLK 0x14 static const struct dfl_device_id uio_dfl_ids[] = { { FME_ID, FME_FEATURE_ID_ETH_GROUP }, { FME_ID, FME_FEATURE_ID_HSSI_SUBSYS }, + { FME_ID, FME_FEATURE_ID_VENDOR_SPECIFIC }, { PORT_ID, PORT_FEATURE_ID_IOPLL_USRCLK }, { } }; diff --git a/drivers/usb/c67x00/c67x00-drv.c b/drivers/usb/c67x00/c67x00-drv.c index 6db5cb1b2dbb340da55fa645b24a9a616122fa9a..bb9d5d7ffefc5448177f4e42e7ed6ec61913fbf5 100644 --- a/drivers/usb/c67x00/c67x00-drv.c +++ b/drivers/usb/c67x00/c67x00-drv.c @@ -177,7 +177,7 @@ static int c67x00_drv_probe(struct platform_device *pdev) return ret; } -static int c67x00_drv_remove(struct platform_device *pdev) +static void c67x00_drv_remove(struct platform_device *pdev) { struct c67x00_device *c67x00 = platform_get_drvdata(pdev); struct resource *res; @@ -197,13 +197,11 @@ static int c67x00_drv_remove(struct platform_device *pdev) release_mem_region(res->start, resource_size(res)); kfree(c67x00); - - return 0; } static struct platform_driver c67x00_driver = { .probe = c67x00_drv_probe, - .remove = c67x00_drv_remove, + .remove_new = c67x00_drv_remove, .driver = { .name = "c67x00", }, diff --git a/drivers/usb/cdns3/Kconfig b/drivers/usb/cdns3/Kconfig index b98ca0a1352a2a84fc9067f8ca8af74656393002..0a514b5915272a000c0c313451e58c2fe012ac5d 100644 --- a/drivers/usb/cdns3/Kconfig +++ b/drivers/usb/cdns3/Kconfig @@ -78,6 +78,17 @@ config USB_CDNS3_IMX For example, imx8qm and imx8qxp. +config USB_CDNS3_STARFIVE + tristate "Cadence USB3 support on StarFive SoC platforms" + depends on ARCH_STARFIVE || COMPILE_TEST + help + Say 'Y' or 'M' here if you are building for StarFive SoCs + platforms that contain Cadence USB3 controller core. + + e.g. JH7110. + + If you choose to build this driver as module it will + be dynamically linked and module will be called cdns3-starfive.ko endif if USB_CDNS_SUPPORT diff --git a/drivers/usb/cdns3/Makefile b/drivers/usb/cdns3/Makefile index 61edb2f8927641baf43ca3d46b7c1544088e5e69..48dfae75b5aafe18889f9e6420bc3d3b37116dcc 100644 --- a/drivers/usb/cdns3/Makefile +++ b/drivers/usb/cdns3/Makefile @@ -24,6 +24,7 @@ endif obj-$(CONFIG_USB_CDNS3_PCI_WRAP) += cdns3-pci-wrap.o obj-$(CONFIG_USB_CDNS3_TI) += cdns3-ti.o obj-$(CONFIG_USB_CDNS3_IMX) += cdns3-imx.o +obj-$(CONFIG_USB_CDNS3_STARFIVE) += cdns3-starfive.o cdnsp-udc-pci-y := cdnsp-pci.o diff --git a/drivers/usb/cdns3/cdns3-gadget.c b/drivers/usb/cdns3/cdns3-gadget.c index 1dcadef933e3a6fb3e163ec5061a8f391960baa5..ea19253fd2d02ec1e4c4e23f0c88c59bbda3b016 100644 --- a/drivers/usb/cdns3/cdns3-gadget.c +++ b/drivers/usb/cdns3/cdns3-gadget.c @@ -800,7 +800,8 @@ void cdns3_gadget_giveback(struct cdns3_endpoint *priv_ep, if (request->status == -EINPROGRESS) request->status = status; - usb_gadget_unmap_request_by_dev(priv_dev->sysdev, request, + if (likely(!(priv_req->flags & REQUEST_UNALIGNED))) + usb_gadget_unmap_request_by_dev(priv_dev->sysdev, request, priv_ep->dir); if ((priv_req->flags & REQUEST_UNALIGNED) && @@ -808,10 +809,10 @@ void cdns3_gadget_giveback(struct cdns3_endpoint *priv_ep, /* Make DMA buffer CPU accessible */ dma_sync_single_for_cpu(priv_dev->sysdev, priv_req->aligned_buf->dma, - priv_req->aligned_buf->size, + request->actual, priv_req->aligned_buf->dir); memcpy(request->buf, priv_req->aligned_buf->buf, - request->length); + request->actual); } priv_req->flags &= ~(REQUEST_PENDING | REQUEST_UNALIGNED); @@ -2543,10 +2544,12 @@ static int __cdns3_gadget_ep_queue(struct usb_ep *ep, if (ret < 0) return ret; - ret = usb_gadget_map_request_by_dev(priv_dev->sysdev, request, + if (likely(!(priv_req->flags & REQUEST_UNALIGNED))) { + ret = usb_gadget_map_request_by_dev(priv_dev->sysdev, request, usb_endpoint_dir_in(ep->desc)); - if (ret) - return ret; + if (ret) + return ret; + } list_add_tail(&request->list, &priv_ep->deferred_req_list); diff --git a/drivers/usb/cdns3/cdns3-imx.c b/drivers/usb/cdns3/cdns3-imx.c index 59860d1753fd5d360074ea25557a906f1fc752f2..281de47e2a3b12a81533a75b0423ce7828a1c872 100644 --- a/drivers/usb/cdns3/cdns3-imx.c +++ b/drivers/usb/cdns3/cdns3-imx.c @@ -105,11 +105,11 @@ static inline void cdns_imx_writel(struct cdns_imx *data, u32 offset, u32 value) } static const struct clk_bulk_data imx_cdns3_core_clks[] = { - { .id = "usb3_lpm_clk" }, - { .id = "usb3_bus_clk" }, - { .id = "usb3_aclk" }, - { .id = "usb3_ipg_clk" }, - { .id = "usb3_core_pclk" }, + { .id = "lpm" }, + { .id = "bus" }, + { .id = "aclk" }, + { .id = "ipg" }, + { .id = "core" }, }; static int cdns_imx_noncore_init(struct cdns_imx *data) @@ -218,7 +218,7 @@ static int cdns_imx_probe(struct platform_device *pdev) return ret; } -static int cdns_imx_remove(struct platform_device *pdev) +static void cdns_imx_remove(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct cdns_imx *data = dev_get_drvdata(dev); @@ -229,8 +229,6 @@ static int cdns_imx_remove(struct platform_device *pdev) pm_runtime_disable(dev); pm_runtime_put_noidle(dev); platform_set_drvdata(pdev, NULL); - - return 0; } #ifdef CONFIG_PM @@ -375,14 +373,22 @@ static inline bool cdns_imx_is_power_lost(struct cdns_imx *data) return false; } +static int __maybe_unused cdns_imx_system_suspend(struct device *dev) +{ + pm_runtime_put_sync(dev); + return 0; +} + static int __maybe_unused cdns_imx_system_resume(struct device *dev) { struct cdns_imx *data = dev_get_drvdata(dev); int ret; - ret = cdns_imx_resume(dev); - if (ret) + ret = pm_runtime_resume_and_get(dev); + if (ret < 0) { + dev_err(dev, "Could not get runtime PM.\n"); return ret; + } if (cdns_imx_is_power_lost(data)) { dev_dbg(dev, "resume from power lost\n"); @@ -405,7 +411,7 @@ static int cdns_imx_platform_suspend(struct device *dev, static const struct dev_pm_ops cdns_imx_pm_ops = { SET_RUNTIME_PM_OPS(cdns_imx_suspend, cdns_imx_resume, NULL) - SET_SYSTEM_SLEEP_PM_OPS(cdns_imx_suspend, cdns_imx_system_resume) + SET_SYSTEM_SLEEP_PM_OPS(cdns_imx_system_suspend, cdns_imx_system_resume) }; static const struct of_device_id cdns_imx_of_match[] = { @@ -416,7 +422,7 @@ MODULE_DEVICE_TABLE(of, cdns_imx_of_match); static struct platform_driver cdns_imx_driver = { .probe = cdns_imx_probe, - .remove = cdns_imx_remove, + .remove_new = cdns_imx_remove, .driver = { .name = "cdns3-imx", .of_match_table = cdns_imx_of_match, diff --git a/drivers/usb/cdns3/cdns3-plat.c b/drivers/usb/cdns3/cdns3-plat.c index 2bc5d094548b6b5edb4093dc633910f78a65fa08..884e2301237f4de465b7f77546fa00182c42c76e 100644 --- a/drivers/usb/cdns3/cdns3-plat.c +++ b/drivers/usb/cdns3/cdns3-plat.c @@ -175,7 +175,7 @@ static int cdns3_plat_probe(struct platform_device *pdev) * * Returns 0 on success otherwise negative errno */ -static int cdns3_plat_remove(struct platform_device *pdev) +static void cdns3_plat_remove(struct platform_device *pdev) { struct cdns *cdns = platform_get_drvdata(pdev); struct device *dev = cdns->dev; @@ -187,7 +187,6 @@ static int cdns3_plat_remove(struct platform_device *pdev) set_phy_power_off(cdns); phy_exit(cdns->usb2_phy); phy_exit(cdns->usb3_phy); - return 0; } #ifdef CONFIG_PM @@ -320,7 +319,7 @@ MODULE_DEVICE_TABLE(of, of_cdns3_match); static struct platform_driver cdns3_driver = { .probe = cdns3_plat_probe, - .remove = cdns3_plat_remove, + .remove_new = cdns3_plat_remove, .driver = { .name = "cdns-usb3", .of_match_table = of_match_ptr(of_cdns3_match), diff --git a/drivers/usb/cdns3/cdns3-starfive.c b/drivers/usb/cdns3/cdns3-starfive.c new file mode 100644 index 0000000000000000000000000000000000000000..fc1f003b145dcdbda0ada2d8900c21e6f855a7ac --- /dev/null +++ b/drivers/usb/cdns3/cdns3-starfive.c @@ -0,0 +1,246 @@ +// SPDX-License-Identifier: GPL-2.0 +/** + * cdns3-starfive.c - StarFive specific Glue layer for Cadence USB Controller + * + * Copyright (C) 2023 StarFive Technology Co., Ltd. + * + * Author: Minda Chen + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "core.h" + +#define USB_STRAP_HOST BIT(17) +#define USB_STRAP_DEVICE BIT(18) +#define USB_STRAP_MASK GENMASK(18, 16) + +#define USB_SUSPENDM_HOST BIT(19) +#define USB_SUSPENDM_MASK BIT(19) + +#define USB_MISC_CFG_MASK GENMASK(23, 20) +#define USB_SUSPENDM_BYPS BIT(20) +#define USB_PLL_EN BIT(22) +#define USB_REFCLK_MODE BIT(23) + +struct cdns_starfive { + struct device *dev; + struct regmap *stg_syscon; + struct reset_control *resets; + struct clk_bulk_data *clks; + int num_clks; + u32 stg_usb_mode; +}; + +static void cdns_mode_init(struct platform_device *pdev, + struct cdns_starfive *data) +{ + enum usb_dr_mode mode; + + regmap_update_bits(data->stg_syscon, data->stg_usb_mode, + USB_MISC_CFG_MASK, + USB_SUSPENDM_BYPS | USB_PLL_EN | USB_REFCLK_MODE); + + /* dr mode setting */ + mode = usb_get_dr_mode(&pdev->dev); + + switch (mode) { + case USB_DR_MODE_HOST: + regmap_update_bits(data->stg_syscon, + data->stg_usb_mode, + USB_STRAP_MASK, + USB_STRAP_HOST); + regmap_update_bits(data->stg_syscon, + data->stg_usb_mode, + USB_SUSPENDM_MASK, + USB_SUSPENDM_HOST); + break; + + case USB_DR_MODE_PERIPHERAL: + regmap_update_bits(data->stg_syscon, data->stg_usb_mode, + USB_STRAP_MASK, USB_STRAP_DEVICE); + regmap_update_bits(data->stg_syscon, data->stg_usb_mode, + USB_SUSPENDM_MASK, 0); + break; + default: + break; + } +} + +static int cdns_clk_rst_init(struct cdns_starfive *data) +{ + int ret; + + ret = clk_bulk_prepare_enable(data->num_clks, data->clks); + if (ret) + return dev_err_probe(data->dev, ret, + "failed to enable clocks\n"); + + ret = reset_control_deassert(data->resets); + if (ret) { + dev_err(data->dev, "failed to reset clocks\n"); + goto err_clk_init; + } + + return ret; + +err_clk_init: + clk_bulk_disable_unprepare(data->num_clks, data->clks); + return ret; +} + +static void cdns_clk_rst_deinit(struct cdns_starfive *data) +{ + reset_control_assert(data->resets); + clk_bulk_disable_unprepare(data->num_clks, data->clks); +} + +static int cdns_starfive_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct cdns_starfive *data; + unsigned int args; + int ret; + + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + data->dev = dev; + + data->stg_syscon = + syscon_regmap_lookup_by_phandle_args(pdev->dev.of_node, + "starfive,stg-syscon", 1, &args); + + if (IS_ERR(data->stg_syscon)) + return dev_err_probe(dev, PTR_ERR(data->stg_syscon), + "Failed to parse starfive,stg-syscon\n"); + + data->stg_usb_mode = args; + + data->num_clks = devm_clk_bulk_get_all(data->dev, &data->clks); + if (data->num_clks < 0) + return dev_err_probe(data->dev, -ENODEV, + "Failed to get clocks\n"); + + data->resets = devm_reset_control_array_get_exclusive(data->dev); + if (IS_ERR(data->resets)) + return dev_err_probe(data->dev, PTR_ERR(data->resets), + "Failed to get resets"); + + cdns_mode_init(pdev, data); + ret = cdns_clk_rst_init(data); + if (ret) + return ret; + + ret = of_platform_populate(dev->of_node, NULL, NULL, dev); + if (ret) { + dev_err(dev, "Failed to create children\n"); + cdns_clk_rst_deinit(data); + return ret; + } + + device_set_wakeup_capable(dev, true); + pm_runtime_set_active(dev); + pm_runtime_enable(dev); + platform_set_drvdata(pdev, data); + + return 0; +} + +static int cdns_starfive_remove_core(struct device *dev, void *c) +{ + struct platform_device *pdev = to_platform_device(dev); + + platform_device_unregister(pdev); + + return 0; +} + +static int cdns_starfive_remove(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct cdns_starfive *data = dev_get_drvdata(dev); + + pm_runtime_get_sync(dev); + device_for_each_child(dev, NULL, cdns_starfive_remove_core); + + pm_runtime_disable(dev); + pm_runtime_put_noidle(dev); + cdns_clk_rst_deinit(data); + platform_set_drvdata(pdev, NULL); + + return 0; +} + +#ifdef CONFIG_PM +static int cdns_starfive_runtime_resume(struct device *dev) +{ + struct cdns_starfive *data = dev_get_drvdata(dev); + + return clk_bulk_prepare_enable(data->num_clks, data->clks); +} + +static int cdns_starfive_runtime_suspend(struct device *dev) +{ + struct cdns_starfive *data = dev_get_drvdata(dev); + + clk_bulk_disable_unprepare(data->num_clks, data->clks); + + return 0; +} + +#ifdef CONFIG_PM_SLEEP +static int cdns_starfive_resume(struct device *dev) +{ + struct cdns_starfive *data = dev_get_drvdata(dev); + + return cdns_clk_rst_init(data); +} + +static int cdns_starfive_suspend(struct device *dev) +{ + struct cdns_starfive *data = dev_get_drvdata(dev); + + cdns_clk_rst_deinit(data); + + return 0; +} +#endif +#endif + +static const struct dev_pm_ops cdns_starfive_pm_ops = { + SET_RUNTIME_PM_OPS(cdns_starfive_runtime_suspend, + cdns_starfive_runtime_resume, NULL) + SET_SYSTEM_SLEEP_PM_OPS(cdns_starfive_suspend, cdns_starfive_resume) +}; + +static const struct of_device_id cdns_starfive_of_match[] = { + { .compatible = "starfive,jh7110-usb", }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, cdns_starfive_of_match); + +static struct platform_driver cdns_starfive_driver = { + .probe = cdns_starfive_probe, + .remove = cdns_starfive_remove, + .driver = { + .name = "cdns3-starfive", + .of_match_table = cdns_starfive_of_match, + .pm = &cdns_starfive_pm_ops, + }, +}; +module_platform_driver(cdns_starfive_driver); + +MODULE_ALIAS("platform:cdns3-starfive"); +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("Cadence USB3 StarFive Glue Layer"); diff --git a/drivers/usb/cdns3/cdns3-ti.c b/drivers/usb/cdns3/cdns3-ti.c index 07c318770362328a881c71106253eda4318404b4..81b9132e3aaa11d6032be082085f812abb872851 100644 --- a/drivers/usb/cdns3/cdns3-ti.c +++ b/drivers/usb/cdns3/cdns3-ti.c @@ -199,7 +199,7 @@ static int cdns_ti_remove_core(struct device *dev, void *c) return 0; } -static int cdns_ti_remove(struct platform_device *pdev) +static void cdns_ti_remove(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -208,8 +208,6 @@ static int cdns_ti_remove(struct platform_device *pdev) pm_runtime_disable(dev); platform_set_drvdata(pdev, NULL); - - return 0; } static const struct of_device_id cdns_ti_of_match[] = { @@ -221,7 +219,7 @@ MODULE_DEVICE_TABLE(of, cdns_ti_of_match); static struct platform_driver cdns_ti_driver = { .probe = cdns_ti_probe, - .remove = cdns_ti_remove, + .remove_new = cdns_ti_remove, .driver = { .name = "cdns3-ti", .of_match_table = cdns_ti_of_match, diff --git a/drivers/usb/chipidea/ci_hdrc_imx.c b/drivers/usb/chipidea/ci_hdrc_imx.c index 2855ac30300147aa69b32294fb24e2d6e95f8c4a..336ef6dd8e7d8a0ede0a897d4de32d8d8395a937 100644 --- a/drivers/usb/chipidea/ci_hdrc_imx.c +++ b/drivers/usb/chipidea/ci_hdrc_imx.c @@ -70,6 +70,10 @@ static const struct ci_hdrc_imx_platform_flag imx7ulp_usb_data = { CI_HDRC_PMQOS, }; +static const struct ci_hdrc_imx_platform_flag imx8ulp_usb_data = { + .flags = CI_HDRC_SUPPORTS_RUNTIME_PM, +}; + static const struct of_device_id ci_hdrc_imx_dt_ids[] = { { .compatible = "fsl,imx23-usb", .data = &imx23_usb_data}, { .compatible = "fsl,imx28-usb", .data = &imx28_usb_data}, @@ -80,6 +84,7 @@ static const struct of_device_id ci_hdrc_imx_dt_ids[] = { { .compatible = "fsl,imx6ul-usb", .data = &imx6ul_usb_data}, { .compatible = "fsl,imx7d-usb", .data = &imx7d_usb_data}, { .compatible = "fsl,imx7ulp-usb", .data = &imx7ulp_usb_data}, + { .compatible = "fsl,imx8ulp-usb", .data = &imx8ulp_usb_data}, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, ci_hdrc_imx_dt_ids); @@ -502,7 +507,7 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev) return ret; } -static int ci_hdrc_imx_remove(struct platform_device *pdev) +static void ci_hdrc_imx_remove(struct platform_device *pdev) { struct ci_hdrc_imx_data *data = platform_get_drvdata(pdev); @@ -522,8 +527,6 @@ static int ci_hdrc_imx_remove(struct platform_device *pdev) if (data->hsic_pad_regulator) regulator_disable(data->hsic_pad_regulator); } - - return 0; } static void ci_hdrc_imx_shutdown(struct platform_device *pdev) @@ -650,7 +653,7 @@ static const struct dev_pm_ops ci_hdrc_imx_pm_ops = { }; static struct platform_driver ci_hdrc_imx_driver = { .probe = ci_hdrc_imx_probe, - .remove = ci_hdrc_imx_remove, + .remove_new = ci_hdrc_imx_remove, .shutdown = ci_hdrc_imx_shutdown, .driver = { .name = "imx_usb", diff --git a/drivers/usb/chipidea/ci_hdrc_msm.c b/drivers/usb/chipidea/ci_hdrc_msm.c index 46105457e1caaee8aa723729a9f3b070caad62d5..7b5b47ce8a0276eb0e9de4bba51608dd5aef3eb1 100644 --- a/drivers/usb/chipidea/ci_hdrc_msm.c +++ b/drivers/usb/chipidea/ci_hdrc_msm.c @@ -274,7 +274,7 @@ static int ci_hdrc_msm_probe(struct platform_device *pdev) return ret; } -static int ci_hdrc_msm_remove(struct platform_device *pdev) +static void ci_hdrc_msm_remove(struct platform_device *pdev) { struct ci_hdrc_msm *ci = platform_get_drvdata(pdev); @@ -282,8 +282,6 @@ static int ci_hdrc_msm_remove(struct platform_device *pdev) ci_hdrc_remove_device(ci->ci); clk_disable_unprepare(ci->iface_clk); clk_disable_unprepare(ci->core_clk); - - return 0; } static const struct of_device_id msm_ci_dt_match[] = { @@ -294,7 +292,7 @@ MODULE_DEVICE_TABLE(of, msm_ci_dt_match); static struct platform_driver ci_hdrc_msm_driver = { .probe = ci_hdrc_msm_probe, - .remove = ci_hdrc_msm_remove, + .remove_new = ci_hdrc_msm_remove, .driver = { .name = "msm_hsusb", .of_match_table = msm_ci_dt_match, diff --git a/drivers/usb/chipidea/ci_hdrc_tegra.c b/drivers/usb/chipidea/ci_hdrc_tegra.c index a72a9474afea7f2e6f31aa9b3b8f220e1a439506..ca36d11a69ea3f9c7e9a8ae3ed655769f4750fd1 100644 --- a/drivers/usb/chipidea/ci_hdrc_tegra.c +++ b/drivers/usb/chipidea/ci_hdrc_tegra.c @@ -362,7 +362,7 @@ static int tegra_usb_probe(struct platform_device *pdev) return err; } -static int tegra_usb_remove(struct platform_device *pdev) +static void tegra_usb_remove(struct platform_device *pdev) { struct tegra_usb *usb = platform_get_drvdata(pdev); @@ -371,8 +371,6 @@ static int tegra_usb_remove(struct platform_device *pdev) pm_runtime_put_sync_suspend(&pdev->dev); pm_runtime_force_suspend(&pdev->dev); - - return 0; } static int __maybe_unused tegra_usb_runtime_resume(struct device *dev) @@ -410,7 +408,7 @@ static struct platform_driver tegra_usb_driver = { .pm = &tegra_usb_pm, }, .probe = tegra_usb_probe, - .remove = tegra_usb_remove, + .remove_new = tegra_usb_remove, }; module_platform_driver(tegra_usb_driver); diff --git a/drivers/usb/chipidea/ci_hdrc_usb2.c b/drivers/usb/chipidea/ci_hdrc_usb2.c index dc86b12060b56a35692ca8c082d5dc220ac03c0b..1321ee67f3b82edfb0c1a92e983dfe56b75d9bb1 100644 --- a/drivers/usb/chipidea/ci_hdrc_usb2.c +++ b/drivers/usb/chipidea/ci_hdrc_usb2.c @@ -106,20 +106,18 @@ static int ci_hdrc_usb2_probe(struct platform_device *pdev) return ret; } -static int ci_hdrc_usb2_remove(struct platform_device *pdev) +static void ci_hdrc_usb2_remove(struct platform_device *pdev) { struct ci_hdrc_usb2_priv *priv = platform_get_drvdata(pdev); pm_runtime_disable(&pdev->dev); ci_hdrc_remove_device(priv->ci_pdev); clk_disable_unprepare(priv->clk); - - return 0; } static struct platform_driver ci_hdrc_usb2_driver = { .probe = ci_hdrc_usb2_probe, - .remove = ci_hdrc_usb2_remove, + .remove_new = ci_hdrc_usb2_remove, .driver = { .name = "chipidea-usb2", .of_match_table = of_match_ptr(ci_hdrc_usb2_of_match), diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c index 798cb077867abfee9dcdf00526105c4d1e20ee47..51994d655b821b4121417b53a425fa023b3a7d40 100644 --- a/drivers/usb/chipidea/core.c +++ b/drivers/usb/chipidea/core.c @@ -1227,7 +1227,7 @@ static int ci_hdrc_probe(struct platform_device *pdev) return ret; } -static int ci_hdrc_remove(struct platform_device *pdev) +static void ci_hdrc_remove(struct platform_device *pdev) { struct ci_hdrc *ci = platform_get_drvdata(pdev); @@ -1245,8 +1245,6 @@ static int ci_hdrc_remove(struct platform_device *pdev) ci_hdrc_enter_lpm(ci, true); ci_usb_phy_exit(ci); ci_ulpi_exit(ci); - - return 0; } #ifdef CONFIG_PM @@ -1485,7 +1483,7 @@ static const struct dev_pm_ops ci_pm_ops = { static struct platform_driver ci_hdrc_driver = { .probe = ci_hdrc_probe, - .remove = ci_hdrc_remove, + .remove_new = ci_hdrc_remove, .driver = { .name = "ci_hdrc", .pm = &ci_pm_ops, diff --git a/drivers/usb/chipidea/usbmisc_imx.c b/drivers/usb/chipidea/usbmisc_imx.c index c57c1a71a51329049c0cad4ced547db5894a14ec..9ee9621e2ccca9766189f9d61633a8882de7efd1 100644 --- a/drivers/usb/chipidea/usbmisc_imx.c +++ b/drivers/usb/chipidea/usbmisc_imx.c @@ -113,7 +113,6 @@ #define MX7D_USBNC_USB_CTRL2_DP_DM_MASK (BIT(12) | BIT(13) | \ BIT(14) | BIT(15)) -#define MX7D_USB_OTG_PHY_CFG1 0x30 #define MX7D_USB_OTG_PHY_CFG2_CHRG_CHRGSEL BIT(0) #define MX7D_USB_OTG_PHY_CFG2_CHRG_VDATDETENB0 BIT(1) #define MX7D_USB_OTG_PHY_CFG2_CHRG_VDATSRCENB0 BIT(2) @@ -135,7 +134,7 @@ #define TXVREFTUNE0_MASK (0xf << 20) #define MX6_USB_OTG_WAKEUP_BITS (MX6_BM_WAKEUP_ENABLE | MX6_BM_VBUS_WAKEUP | \ - MX6_BM_ID_WAKEUP) + MX6_BM_ID_WAKEUP | MX6SX_BM_DPDM_WAKEUP_EN) struct usbmisc_ops { /* It's called once when probe a usb device */ @@ -152,6 +151,7 @@ struct usbmisc_ops { int (*charger_detection)(struct imx_usbmisc_data *data); /* It's called when system resume from usb power lost */ int (*power_lost_check)(struct imx_usbmisc_data *data); + void (*vbus_comparator_on)(struct imx_usbmisc_data *data, bool on); }; struct imx_usbmisc { @@ -875,6 +875,33 @@ static int imx7d_charger_detection(struct imx_usbmisc_data *data) return ret; } +static void usbmisc_imx7d_vbus_comparator_on(struct imx_usbmisc_data *data, + bool on) +{ + unsigned long flags; + struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev); + u32 val; + + if (data->hsic) + return; + + spin_lock_irqsave(&usbmisc->lock, flags); + /* + * Disable VBUS valid comparator when in suspend mode, + * when OTG is disabled and DRVVBUS0 is asserted case + * the Bandgap circuitry and VBUS Valid comparator are + * still powered, even in Suspend or Sleep mode. + */ + val = readl(usbmisc->base + MX7D_USB_OTG_PHY_CFG2); + if (on) + val |= MX7D_USB_OTG_PHY_CFG2_DRVVBUS0; + else + val &= ~MX7D_USB_OTG_PHY_CFG2_DRVVBUS0; + + writel(val, usbmisc->base + MX7D_USB_OTG_PHY_CFG2); + spin_unlock_irqrestore(&usbmisc->lock, flags); +} + static int usbmisc_imx7ulp_init(struct imx_usbmisc_data *data) { struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev); @@ -1018,6 +1045,7 @@ static const struct usbmisc_ops imx7d_usbmisc_ops = { .set_wakeup = usbmisc_imx7d_set_wakeup, .charger_detection = imx7d_charger_detection, .power_lost_check = usbmisc_imx7d_power_lost_check, + .vbus_comparator_on = usbmisc_imx7d_vbus_comparator_on, }; static const struct usbmisc_ops imx7ulp_usbmisc_ops = { @@ -1132,6 +1160,9 @@ int imx_usbmisc_suspend(struct imx_usbmisc_data *data, bool wakeup) usbmisc = dev_get_drvdata(data->dev); + if (usbmisc->ops->vbus_comparator_on) + usbmisc->ops->vbus_comparator_on(data, false); + if (wakeup && usbmisc->ops->set_wakeup) ret = usbmisc->ops->set_wakeup(data, true); if (ret) { @@ -1185,6 +1216,9 @@ int imx_usbmisc_resume(struct imx_usbmisc_data *data, bool wakeup) goto hsic_set_clk_fail; } + if (usbmisc->ops->vbus_comparator_on) + usbmisc->ops->vbus_comparator_on(data, true); + return 0; hsic_set_clk_fail: diff --git a/drivers/usb/common/led.c b/drivers/usb/common/led.c index 0865dd44a80ad1ee48e2a02c75752f6aa23bd02e..1de18d90b134767888be404e6657c4a2bdea938d 100644 --- a/drivers/usb/common/led.c +++ b/drivers/usb/common/led.c @@ -14,8 +14,6 @@ #define BLINK_DELAY 30 -static unsigned long usb_blink_delay = BLINK_DELAY; - DEFINE_LED_TRIGGER(ledtrig_usb_gadget); DEFINE_LED_TRIGGER(ledtrig_usb_host); @@ -32,7 +30,7 @@ void usb_led_activity(enum usb_led_event ev) break; } /* led_trigger_blink_oneshot() handles trig == NULL gracefully */ - led_trigger_blink_oneshot(trig, &usb_blink_delay, &usb_blink_delay, 0); + led_trigger_blink_oneshot(trig, BLINK_DELAY, BLINK_DELAY, 0); } EXPORT_SYMBOL_GPL(usb_led_activity); diff --git a/drivers/usb/common/usb-conn-gpio.c b/drivers/usb/common/usb-conn-gpio.c index e20874caba363c7178fbe247186f1e34d9bf88a5..766005d20baefde32a69e78a84fc6f39e33b9241 100644 --- a/drivers/usb/common/usb-conn-gpio.c +++ b/drivers/usb/common/usb-conn-gpio.c @@ -267,7 +267,7 @@ static int usb_conn_probe(struct platform_device *pdev) return ret; } -static int usb_conn_remove(struct platform_device *pdev) +static void usb_conn_remove(struct platform_device *pdev) { struct usb_conn_info *info = platform_get_drvdata(pdev); @@ -277,8 +277,6 @@ static int usb_conn_remove(struct platform_device *pdev) regulator_disable(info->vbus); usb_role_switch_put(info->role_sw); - - return 0; } static int __maybe_unused usb_conn_suspend(struct device *dev) @@ -338,7 +336,7 @@ MODULE_DEVICE_TABLE(of, usb_conn_dt_match); static struct platform_driver usb_conn_driver = { .probe = usb_conn_probe, - .remove = usb_conn_remove, + .remove_new = usb_conn_remove, .driver = { .name = "usb-conn-gpio", .pm = &usb_conn_pm_ops, diff --git a/drivers/usb/core/buffer.c b/drivers/usb/core/buffer.c index 268ccbec88f951ab44ad5f410dc19a3a22e3c7a7..87230869e1fa15d40689321d29f57c5a94eeafc8 100644 --- a/drivers/usb/core/buffer.c +++ b/drivers/usb/core/buffer.c @@ -34,13 +34,13 @@ void __init usb_init_pool_max(void) { /* * The pool_max values must never be smaller than - * ARCH_KMALLOC_MINALIGN. + * ARCH_DMA_MINALIGN. */ - if (ARCH_KMALLOC_MINALIGN <= 32) + if (ARCH_DMA_MINALIGN <= 32) ; /* Original value is okay */ - else if (ARCH_KMALLOC_MINALIGN <= 64) + else if (ARCH_DMA_MINALIGN <= 64) pool_max[0] = 64; - else if (ARCH_KMALLOC_MINALIGN <= 128) + else if (ARCH_DMA_MINALIGN <= 128) pool_max[0] = 0; /* Don't use this pool */ else BUILD_BUG(); /* We don't allow this */ diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index fcf68818e999286296e51626e72b25461ab3ea7f..1a16a8bdea60bcd867c301d99084496d3adf6f73 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -746,6 +746,7 @@ static int driver_resume(struct usb_interface *intf) return 0; } +#ifdef CONFIG_PM /* The following routines apply to the entire device, not interfaces */ void usbfs_notify_suspend(struct usb_device *udev) { @@ -764,6 +765,7 @@ void usbfs_notify_resume(struct usb_device *udev) } mutex_unlock(&usbfs_mutex); } +#endif struct usb_driver usbfs_driver = { .name = "usbfs", @@ -2640,21 +2642,21 @@ static long usbdev_do_ioctl(struct file *file, unsigned int cmd, snoop(&dev->dev, "%s: CONTROL\n", __func__); ret = proc_control(ps, p); if (ret >= 0) - inode->i_mtime = current_time(inode); + inode->i_mtime = inode->i_ctime = current_time(inode); break; case USBDEVFS_BULK: snoop(&dev->dev, "%s: BULK\n", __func__); ret = proc_bulk(ps, p); if (ret >= 0) - inode->i_mtime = current_time(inode); + inode->i_mtime = inode->i_ctime = current_time(inode); break; case USBDEVFS_RESETEP: snoop(&dev->dev, "%s: RESETEP\n", __func__); ret = proc_resetep(ps, p); if (ret >= 0) - inode->i_mtime = current_time(inode); + inode->i_mtime = inode->i_ctime = current_time(inode); break; case USBDEVFS_RESET: @@ -2666,7 +2668,7 @@ static long usbdev_do_ioctl(struct file *file, unsigned int cmd, snoop(&dev->dev, "%s: CLEAR_HALT\n", __func__); ret = proc_clearhalt(ps, p); if (ret >= 0) - inode->i_mtime = current_time(inode); + inode->i_mtime = inode->i_ctime = current_time(inode); break; case USBDEVFS_GETDRIVER: @@ -2693,7 +2695,7 @@ static long usbdev_do_ioctl(struct file *file, unsigned int cmd, snoop(&dev->dev, "%s: SUBMITURB\n", __func__); ret = proc_submiturb(ps, p); if (ret >= 0) - inode->i_mtime = current_time(inode); + inode->i_mtime = inode->i_ctime = current_time(inode); break; #ifdef CONFIG_COMPAT @@ -2701,14 +2703,14 @@ static long usbdev_do_ioctl(struct file *file, unsigned int cmd, snoop(&dev->dev, "%s: CONTROL32\n", __func__); ret = proc_control_compat(ps, p); if (ret >= 0) - inode->i_mtime = current_time(inode); + inode->i_mtime = inode->i_ctime = current_time(inode); break; case USBDEVFS_BULK32: snoop(&dev->dev, "%s: BULK32\n", __func__); ret = proc_bulk_compat(ps, p); if (ret >= 0) - inode->i_mtime = current_time(inode); + inode->i_mtime = inode->i_ctime = current_time(inode); break; case USBDEVFS_DISCSIGNAL32: @@ -2720,7 +2722,7 @@ static long usbdev_do_ioctl(struct file *file, unsigned int cmd, snoop(&dev->dev, "%s: SUBMITURB32\n", __func__); ret = proc_submiturb_compat(ps, p); if (ret >= 0) - inode->i_mtime = current_time(inode); + inode->i_mtime = inode->i_ctime = current_time(inode); break; case USBDEVFS_IOCTL32: diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c index ab2f3737764e4331f3e1e9d037cb75d449c861b7..990280688b254d913d843bde17dae0a8be203778 100644 --- a/drivers/usb/core/hcd-pci.c +++ b/drivers/usb/core/hcd-pci.c @@ -415,12 +415,15 @@ static int check_root_hub_suspended(struct device *dev) return 0; } -static int suspend_common(struct device *dev, bool do_wakeup) +static int suspend_common(struct device *dev, pm_message_t msg) { struct pci_dev *pci_dev = to_pci_dev(dev); struct usb_hcd *hcd = pci_get_drvdata(pci_dev); + bool do_wakeup; int retval; + do_wakeup = PMSG_IS_AUTO(msg) ? true : device_may_wakeup(dev); + /* Root hub suspend should have stopped all downstream traffic, * and all bus master traffic. And done so for both the interface * and the stub usb_device (which we check here). But maybe it @@ -447,7 +450,7 @@ static int suspend_common(struct device *dev, bool do_wakeup) (retval == 0 && do_wakeup && hcd->shared_hcd && HCD_WAKEUP_PENDING(hcd->shared_hcd))) { if (hcd->driver->pci_resume) - hcd->driver->pci_resume(hcd, false); + hcd->driver->pci_resume(hcd, msg); retval = -EBUSY; } if (retval) @@ -470,7 +473,7 @@ static int suspend_common(struct device *dev, bool do_wakeup) return retval; } -static int resume_common(struct device *dev, int event) +static int resume_common(struct device *dev, pm_message_t msg) { struct pci_dev *pci_dev = to_pci_dev(dev); struct usb_hcd *hcd = pci_get_drvdata(pci_dev); @@ -498,12 +501,11 @@ static int resume_common(struct device *dev, int event) * No locking is needed because PCI controller drivers do not * get unbound during system resume. */ - if (pci_dev->class == CL_EHCI && event != PM_EVENT_AUTO_RESUME) + if (pci_dev->class == CL_EHCI && msg.event != PM_EVENT_AUTO_RESUME) for_each_companion(pci_dev, hcd, ehci_wait_for_companions); - retval = hcd->driver->pci_resume(hcd, - event == PM_EVENT_RESTORE); + retval = hcd->driver->pci_resume(hcd, msg); if (retval) { dev_err(dev, "PCI post-resume error %d!\n", retval); usb_hc_died(hcd); @@ -516,7 +518,7 @@ static int resume_common(struct device *dev, int event) static int hcd_pci_suspend(struct device *dev) { - return suspend_common(dev, device_may_wakeup(dev)); + return suspend_common(dev, PMSG_SUSPEND); } static int hcd_pci_suspend_noirq(struct device *dev) @@ -577,12 +579,12 @@ static int hcd_pci_resume_noirq(struct device *dev) static int hcd_pci_resume(struct device *dev) { - return resume_common(dev, PM_EVENT_RESUME); + return resume_common(dev, PMSG_RESUME); } static int hcd_pci_restore(struct device *dev) { - return resume_common(dev, PM_EVENT_RESTORE); + return resume_common(dev, PMSG_RESTORE); } #else @@ -600,7 +602,7 @@ static int hcd_pci_runtime_suspend(struct device *dev) { int retval; - retval = suspend_common(dev, true); + retval = suspend_common(dev, PMSG_AUTO_SUSPEND); if (retval == 0) powermac_set_asic(to_pci_dev(dev), 0); dev_dbg(dev, "hcd_pci_runtime_suspend: %d\n", retval); @@ -612,7 +614,7 @@ static int hcd_pci_runtime_resume(struct device *dev) int retval; powermac_set_asic(to_pci_dev(dev), 1); - retval = resume_common(dev, PM_EVENT_AUTO_RESUME); + retval = resume_common(dev, PMSG_AUTO_RESUME); dev_dbg(dev, "hcd_pci_runtime_resume: %d\n", retval); return retval; } diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 97a0f8faea6e5ff33ee9b695850c13c5c8e7f657..a739403a9e455a1f6ddf3f51fa9e96b4d9e67e5e 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -2018,6 +2018,19 @@ bool usb_device_is_owned(struct usb_device *udev) return !!hub->ports[udev->portnum - 1]->port_owner; } +static void update_port_device_state(struct usb_device *udev) +{ + struct usb_hub *hub; + struct usb_port *port_dev; + + if (udev->parent) { + hub = usb_hub_to_struct_hub(udev->parent); + port_dev = hub->ports[udev->portnum - 1]; + WRITE_ONCE(port_dev->state, udev->state); + sysfs_notify_dirent(port_dev->state_kn); + } +} + static void recursively_mark_NOTATTACHED(struct usb_device *udev) { struct usb_hub *hub = usb_hub_to_struct_hub(udev); @@ -2030,6 +2043,7 @@ static void recursively_mark_NOTATTACHED(struct usb_device *udev) if (udev->state == USB_STATE_SUSPENDED) udev->active_duration -= jiffies; udev->state = USB_STATE_NOTATTACHED; + update_port_device_state(udev); } /** @@ -2086,6 +2100,7 @@ void usb_set_device_state(struct usb_device *udev, udev->state != USB_STATE_SUSPENDED) udev->active_duration += jiffies; udev->state = new_state; + update_port_device_state(udev); } else recursively_mark_NOTATTACHED(udev); spin_unlock_irqrestore(&device_state_lock, flags); diff --git a/drivers/usb/core/hub.h b/drivers/usb/core/hub.h index e23833562e4f2e2f7f28bbe0b22b4d26662d3d4e..37897afd1b64989e801953a025f3a18941521220 100644 --- a/drivers/usb/core/hub.h +++ b/drivers/usb/core/hub.h @@ -84,6 +84,8 @@ struct usb_hub { * @peer: related usb2 and usb3 ports (share the same connector) * @req: default pm qos request for hubs without port power control * @connect_type: port's connect type + * @state: device state of the usb device attached to the port + * @state_kn: kernfs_node of the sysfs attribute that accesses @state * @location: opaque representation of platform connector location * @status_lock: synchronize port_event() vs usb_port_{suspend|resume} * @portnum: port index num based one @@ -100,6 +102,8 @@ struct usb_port { struct usb_port *peer; struct dev_pm_qos_request *req; enum usb_port_connect_type connect_type; + enum usb_device_state state; + struct kernfs_node *state_kn; usb_port_location_t location; struct mutex status_lock; u32 over_current_count; diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c index 06a8f1f84f6f8741e014501238847e477a3624ec..77be0dc28da9a6b08d7427762ebe76333fc65f65 100644 --- a/drivers/usb/core/port.c +++ b/drivers/usb/core/port.c @@ -160,6 +160,16 @@ static ssize_t connect_type_show(struct device *dev, } static DEVICE_ATTR_RO(connect_type); +static ssize_t state_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct usb_port *port_dev = to_usb_port(dev); + enum usb_device_state state = READ_ONCE(port_dev->state); + + return sysfs_emit(buf, "%s\n", usb_state_string(state)); +} +static DEVICE_ATTR_RO(state); + static ssize_t over_current_count_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -259,6 +269,7 @@ static DEVICE_ATTR_RW(usb3_lpm_permit); static struct attribute *port_dev_attrs[] = { &dev_attr_connect_type.attr, + &dev_attr_state.attr, &dev_attr_location.attr, &dev_attr_quirks.attr, &dev_attr_over_current_count.attr, @@ -705,19 +716,24 @@ int usb_hub_create_port_device(struct usb_hub *hub, int port1) return retval; } + port_dev->state_kn = sysfs_get_dirent(port_dev->dev.kobj.sd, "state"); + if (!port_dev->state_kn) { + dev_err(&port_dev->dev, "failed to sysfs_get_dirent 'state'\n"); + retval = -ENODEV; + goto err_unregister; + } + /* Set default policy of port-poweroff disabled. */ retval = dev_pm_qos_add_request(&port_dev->dev, port_dev->req, DEV_PM_QOS_FLAGS, PM_QOS_FLAG_NO_POWER_OFF); if (retval < 0) { - device_unregister(&port_dev->dev); - return retval; + goto err_put_kn; } retval = component_add(&port_dev->dev, &connector_ops); if (retval) { dev_warn(&port_dev->dev, "failed to add component\n"); - device_unregister(&port_dev->dev); - return retval; + goto err_put_kn; } find_and_link_peer(hub, port1); @@ -754,6 +770,13 @@ int usb_hub_create_port_device(struct usb_hub *hub, int port1) port_dev->req = NULL; } return 0; + +err_put_kn: + sysfs_put(port_dev->state_kn); +err_unregister: + device_unregister(&port_dev->dev); + + return retval; } void usb_hub_remove_port_device(struct usb_hub *hub, int port1) @@ -765,5 +788,6 @@ void usb_hub_remove_port_device(struct usb_hub *hub, int port1) if (peer) unlink_peers(port_dev, peer); component_del(&port_dev->dev, &connector_ops); + sysfs_put(port_dev->state_kn); device_unregister(&port_dev->dev); } diff --git a/drivers/usb/dwc2/params.c b/drivers/usb/dwc2/params.c index 21d16533bd2f4f4720db2b82092ee04c5ea22372..4c7c3dd15f9bec95158b8f4f10743207be010993 100644 --- a/drivers/usb/dwc2/params.c +++ b/drivers/usb/dwc2/params.c @@ -161,6 +161,25 @@ static void dwc2_set_amlogic_g12a_params(struct dwc2_hsotg *hsotg) p->hird_threshold_en = false; } +static void dwc2_set_amlogic_a1_params(struct dwc2_hsotg *hsotg) +{ + struct dwc2_core_params *p = &hsotg->params; + + p->otg_caps.hnp_support = false; + p->otg_caps.srp_support = false; + p->speed = DWC2_SPEED_PARAM_HIGH; + p->host_rx_fifo_size = 192; + p->host_nperio_tx_fifo_size = 128; + p->host_perio_tx_fifo_size = 128; + p->phy_type = DWC2_PHY_TYPE_PARAM_UTMI; + p->phy_utmi_width = 8; + p->ahbcfg = GAHBCFG_HBSTLEN_INCR8 << GAHBCFG_HBSTLEN_SHIFT; + p->lpm = false; + p->lpm_clock_gating = false; + p->besl = false; + p->hird_threshold_en = false; +} + static void dwc2_set_amcc_params(struct dwc2_hsotg *hsotg) { struct dwc2_core_params *p = &hsotg->params; @@ -258,6 +277,8 @@ const struct of_device_id dwc2_of_match_table[] = { .data = dwc2_set_amlogic_params }, { .compatible = "amlogic,meson-g12a-usb", .data = dwc2_set_amlogic_g12a_params }, + { .compatible = "amlogic,meson-a1-usb", + .data = dwc2_set_amlogic_a1_params }, { .compatible = "amcc,dwc-otg", .data = dwc2_set_amcc_params }, { .compatible = "apm,apm82181-dwc-otg", .data = dwc2_set_amcc_params }, { .compatible = "st,stm32f4x9-fsotg", diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c index 5aee284018c006b2114087e5dbbda974a00ea6da..0a806f80217e532693ce94b028eecbacfc6d6a00 100644 --- a/drivers/usb/dwc2/platform.c +++ b/drivers/usb/dwc2/platform.c @@ -203,6 +203,11 @@ int dwc2_lowlevel_hw_disable(struct dwc2_hsotg *hsotg) return ret; } +static void dwc2_reset_control_assert(void *data) +{ + reset_control_assert(data); +} + static int dwc2_lowlevel_hw_init(struct dwc2_hsotg *hsotg) { int i, ret; @@ -213,6 +218,10 @@ static int dwc2_lowlevel_hw_init(struct dwc2_hsotg *hsotg) "error getting reset control\n"); reset_control_deassert(hsotg->reset); + ret = devm_add_action_or_reset(hsotg->dev, dwc2_reset_control_assert, + hsotg->reset); + if (ret) + return ret; hsotg->reset_ecc = devm_reset_control_get_optional(hsotg->dev, "dwc2-ecc"); if (IS_ERR(hsotg->reset_ecc)) @@ -220,6 +229,10 @@ static int dwc2_lowlevel_hw_init(struct dwc2_hsotg *hsotg) "error getting reset control for ecc\n"); reset_control_deassert(hsotg->reset_ecc); + ret = devm_add_action_or_reset(hsotg->dev, dwc2_reset_control_assert, + hsotg->reset_ecc); + if (ret) + return ret; /* * Attempt to find a generic PHY, then look for an old style @@ -288,7 +301,7 @@ static int dwc2_lowlevel_hw_init(struct dwc2_hsotg *hsotg) * stops device processing. Any resources used on behalf of this device are * freed. */ -static int dwc2_driver_remove(struct platform_device *dev) +static void dwc2_driver_remove(struct platform_device *dev) { struct dwc2_hsotg *hsotg = platform_get_drvdata(dev); struct dwc2_gregs_backup *gr; @@ -338,11 +351,6 @@ static int dwc2_driver_remove(struct platform_device *dev) if (hsotg->ll_hw_enabled) dwc2_lowlevel_hw_disable(hsotg); - - reset_control_assert(hsotg->reset); - reset_control_assert(hsotg->reset_ecc); - - return 0; } /** @@ -746,7 +754,7 @@ static struct platform_driver dwc2_platform_driver = { .pm = &dwc2_dev_pm_ops, }, .probe = dwc2_driver_probe, - .remove = dwc2_driver_remove, + .remove_new = dwc2_driver_remove, .shutdown = dwc2_driver_shutdown, }; diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index d68958e151a78d70e7f823899ec9152ec6bf568b..f6689b731718dd77a563019f0ddc40da42902bd4 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -1800,6 +1800,17 @@ static int dwc3_probe(struct platform_device *pdev) dwc_res = *res; dwc_res.start += DWC3_GLOBALS_REGS_START; + if (dev->of_node) { + struct device_node *parent = of_get_parent(dev->of_node); + + if (of_device_is_compatible(parent, "realtek,rtd-dwc3")) { + dwc_res.start -= DWC3_GLOBALS_REGS_START; + dwc_res.start += DWC3_RTK_RTD_GLOBALS_REGS_START; + } + + of_node_put(parent); + } + regs = devm_ioremap_resource(dev, &dwc_res); if (IS_ERR(regs)) return PTR_ERR(regs); @@ -1913,7 +1924,7 @@ static int dwc3_probe(struct platform_device *pdev) return ret; } -static int dwc3_remove(struct platform_device *pdev) +static void dwc3_remove(struct platform_device *pdev) { struct dwc3 *dwc = platform_get_drvdata(pdev); @@ -1940,8 +1951,6 @@ static int dwc3_remove(struct platform_device *pdev) if (dwc->usb_psy) power_supply_put(dwc->usb_psy); - - return 0; } #ifdef CONFIG_PM @@ -2252,7 +2261,7 @@ MODULE_DEVICE_TABLE(acpi, dwc3_acpi_match); static struct platform_driver dwc3_driver = { .probe = dwc3_probe, - .remove = dwc3_remove, + .remove_new = dwc3_remove, .driver = { .name = "dwc3", .of_match_table = of_match_ptr(of_dwc3_match), diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 1f043c31a0969ffc427f62b56974162c0cf0651b..8b1295e4dcdd85fbaab02cc32689dd378a5e9fd6 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -84,6 +84,8 @@ #define DWC3_OTG_REGS_START 0xcc00 #define DWC3_OTG_REGS_END 0xccff +#define DWC3_RTK_RTD_GLOBALS_REGS_START 0x8100 + /* Global Registers */ #define DWC3_GSBUSCFG0 0xc100 #define DWC3_GSBUSCFG1 0xc104 diff --git a/drivers/usb/dwc3/dwc3-am62.c b/drivers/usb/dwc3/dwc3-am62.c index cda9458c809b3b418ae1abe96372fac80a040dce..1755f2f848c5b05d343c217156f1d32aaba7bfda 100644 --- a/drivers/usb/dwc3/dwc3-am62.c +++ b/drivers/usb/dwc3/dwc3-am62.c @@ -275,7 +275,7 @@ static int dwc3_ti_remove_core(struct device *dev, void *c) return 0; } -static int dwc3_ti_remove(struct platform_device *pdev) +static void dwc3_ti_remove(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct dwc3_data *data = platform_get_drvdata(pdev); @@ -294,7 +294,6 @@ static int dwc3_ti_remove(struct platform_device *pdev) pm_runtime_set_suspended(dev); platform_set_drvdata(pdev, NULL); - return 0; } #ifdef CONFIG_PM @@ -362,7 +361,7 @@ MODULE_DEVICE_TABLE(of, dwc3_ti_of_match); static struct platform_driver dwc3_ti_driver = { .probe = dwc3_ti_probe, - .remove = dwc3_ti_remove, + .remove_new = dwc3_ti_remove, .driver = { .name = "dwc3-am62", .pm = DEV_PM_OPS, diff --git a/drivers/usb/dwc3/dwc3-exynos.c b/drivers/usb/dwc3/dwc3-exynos.c index 4be6a873bd07166d1c3ed9bbe88f78417e8c0498..f882dd6473403e4c2f1bc93e1409d07e88e90a25 100644 --- a/drivers/usb/dwc3/dwc3-exynos.c +++ b/drivers/usb/dwc3/dwc3-exynos.c @@ -128,7 +128,7 @@ static int dwc3_exynos_probe(struct platform_device *pdev) return ret; } -static int dwc3_exynos_remove(struct platform_device *pdev) +static void dwc3_exynos_remove(struct platform_device *pdev) { struct dwc3_exynos *exynos = platform_get_drvdata(pdev); int i; @@ -143,8 +143,6 @@ static int dwc3_exynos_remove(struct platform_device *pdev) regulator_disable(exynos->vdd33); regulator_disable(exynos->vdd10); - - return 0; } static const struct dwc3_exynos_driverdata exynos5250_drvdata = { @@ -234,7 +232,7 @@ static const struct dev_pm_ops dwc3_exynos_dev_pm_ops = { static struct platform_driver dwc3_exynos_driver = { .probe = dwc3_exynos_probe, - .remove = dwc3_exynos_remove, + .remove_new = dwc3_exynos_remove, .driver = { .name = "exynos-dwc3", .of_match_table = exynos_dwc3_match, diff --git a/drivers/usb/dwc3/dwc3-imx8mp.c b/drivers/usb/dwc3/dwc3-imx8mp.c index 174f07614318b3b09dcb260c9e6c00ba8b345d26..8b9a3bb587bf3451bc3b71554b456cb8f9a595db 100644 --- a/drivers/usb/dwc3/dwc3-imx8mp.c +++ b/drivers/usb/dwc3/dwc3-imx8mp.c @@ -266,7 +266,7 @@ static int dwc3_imx8mp_probe(struct platform_device *pdev) return err; } -static int dwc3_imx8mp_remove(struct platform_device *pdev) +static void dwc3_imx8mp_remove(struct platform_device *pdev) { struct dwc3_imx8mp *dwc3_imx = platform_get_drvdata(pdev); struct device *dev = &pdev->dev; @@ -280,8 +280,6 @@ static int dwc3_imx8mp_remove(struct platform_device *pdev) pm_runtime_disable(dev); pm_runtime_put_noidle(dev); platform_set_drvdata(pdev, NULL); - - return 0; } static int __maybe_unused dwc3_imx8mp_suspend(struct dwc3_imx8mp *dwc3_imx, @@ -411,7 +409,7 @@ MODULE_DEVICE_TABLE(of, dwc3_imx8mp_of_match); static struct platform_driver dwc3_imx8mp_driver = { .probe = dwc3_imx8mp_probe, - .remove = dwc3_imx8mp_remove, + .remove_new = dwc3_imx8mp_remove, .driver = { .name = "imx8mp-dwc3", .pm = &dwc3_imx8mp_dev_pm_ops, diff --git a/drivers/usb/dwc3/dwc3-keystone.c b/drivers/usb/dwc3/dwc3-keystone.c index 1317959294e6ef7a44de1ed53d7b4deee51427ff..0a09aedc25736b76d7764ab051f285d7adb6c4e6 100644 --- a/drivers/usb/dwc3/dwc3-keystone.c +++ b/drivers/usb/dwc3/dwc3-keystone.c @@ -181,7 +181,7 @@ static int kdwc3_remove_core(struct device *dev, void *c) return 0; } -static int kdwc3_remove(struct platform_device *pdev) +static void kdwc3_remove(struct platform_device *pdev) { struct dwc3_keystone *kdwc = platform_get_drvdata(pdev); struct device_node *node = pdev->dev.of_node; @@ -198,8 +198,6 @@ static int kdwc3_remove(struct platform_device *pdev) phy_pm_runtime_put_sync(kdwc->usb3_phy); platform_set_drvdata(pdev, NULL); - - return 0; } static const struct of_device_id kdwc3_of_match[] = { @@ -211,7 +209,7 @@ MODULE_DEVICE_TABLE(of, kdwc3_of_match); static struct platform_driver kdwc3_driver = { .probe = kdwc3_probe, - .remove = kdwc3_remove, + .remove_new = kdwc3_remove, .driver = { .name = "keystone-dwc3", .of_match_table = kdwc3_of_match, diff --git a/drivers/usb/dwc3/dwc3-meson-g12a.c b/drivers/usb/dwc3/dwc3-meson-g12a.c index b282ad0e69c6d8699049571dc9e4f6d0bdadc238..e99c7489dba02dca796c543a5a1cc261f747153e 100644 --- a/drivers/usb/dwc3/dwc3-meson-g12a.c +++ b/drivers/usb/dwc3/dwc3-meson-g12a.c @@ -140,7 +140,6 @@ static const char * const meson_a1_phy_names[] = { struct dwc3_meson_g12a; struct dwc3_meson_g12a_drvdata { - bool otg_switch_supported; bool otg_phy_host_port_disable; struct clk_bulk_data *clks; int num_clks; @@ -189,7 +188,6 @@ static int dwc3_meson_gxl_usb_post_init(struct dwc3_meson_g12a *priv); */ static const struct dwc3_meson_g12a_drvdata gxl_drvdata = { - .otg_switch_supported = true, .otg_phy_host_port_disable = true, .clks = meson_gxl_clocks, .num_clks = ARRAY_SIZE(meson_g12a_clocks), @@ -203,7 +201,6 @@ static const struct dwc3_meson_g12a_drvdata gxl_drvdata = { }; static const struct dwc3_meson_g12a_drvdata gxm_drvdata = { - .otg_switch_supported = true, .otg_phy_host_port_disable = true, .clks = meson_gxl_clocks, .num_clks = ARRAY_SIZE(meson_g12a_clocks), @@ -217,7 +214,6 @@ static const struct dwc3_meson_g12a_drvdata gxm_drvdata = { }; static const struct dwc3_meson_g12a_drvdata axg_drvdata = { - .otg_switch_supported = true, .clks = meson_gxl_clocks, .num_clks = ARRAY_SIZE(meson_gxl_clocks), .phy_names = meson_a1_phy_names, @@ -230,7 +226,6 @@ static const struct dwc3_meson_g12a_drvdata axg_drvdata = { }; static const struct dwc3_meson_g12a_drvdata g12a_drvdata = { - .otg_switch_supported = true, .clks = meson_g12a_clocks, .num_clks = ARRAY_SIZE(meson_g12a_clocks), .phy_names = meson_g12a_phy_names, @@ -242,7 +237,6 @@ static const struct dwc3_meson_g12a_drvdata g12a_drvdata = { }; static const struct dwc3_meson_g12a_drvdata a1_drvdata = { - .otg_switch_supported = false, .clks = meson_a1_clocks, .num_clks = ARRAY_SIZE(meson_a1_clocks), .phy_names = meson_a1_phy_names, @@ -307,7 +301,7 @@ static int dwc3_meson_g12a_usb2_init_phy(struct dwc3_meson_g12a *priv, int i, U2P_R0_POWER_ON_RESET, U2P_R0_POWER_ON_RESET); - if (priv->drvdata->otg_switch_supported && i == USB2_OTG_PHY) { + if (i == USB2_OTG_PHY) { regmap_update_bits(priv->u2p_regmap[i], U2P_R0, U2P_R0_ID_PULLUP | U2P_R0_DRV_VBUS, U2P_R0_ID_PULLUP | U2P_R0_DRV_VBUS); @@ -490,7 +484,7 @@ static int dwc3_meson_g12a_otg_mode_set(struct dwc3_meson_g12a *priv, { int ret; - if (!priv->drvdata->otg_switch_supported || !priv->phys[USB2_OTG_PHY]) + if (!priv->phys[USB2_OTG_PHY]) return -EINVAL; if (mode == PHY_MODE_USB_HOST) @@ -589,9 +583,6 @@ static int dwc3_meson_g12a_otg_init(struct platform_device *pdev, int ret, irq; struct device *dev = &pdev->dev; - if (!priv->drvdata->otg_switch_supported) - return 0; - if (priv->otg_mode == USB_DR_MODE_OTG) { /* Ack irq before registering */ regmap_update_bits(priv->usb_glue_regmap, USB_R5, @@ -805,7 +796,7 @@ static int dwc3_meson_g12a_probe(struct platform_device *pdev) ret = dwc3_meson_g12a_otg_init(pdev, priv); if (ret) - goto err_phys_power; + goto err_plat_depopulate; pm_runtime_set_active(dev); pm_runtime_enable(dev); @@ -813,6 +804,9 @@ static int dwc3_meson_g12a_probe(struct platform_device *pdev) return 0; +err_plat_depopulate: + of_platform_depopulate(dev); + err_phys_power: for (i = 0 ; i < PHY_COUNT ; ++i) phy_power_off(priv->phys[i]); @@ -835,14 +829,13 @@ static int dwc3_meson_g12a_probe(struct platform_device *pdev) return ret; } -static int dwc3_meson_g12a_remove(struct platform_device *pdev) +static void dwc3_meson_g12a_remove(struct platform_device *pdev) { struct dwc3_meson_g12a *priv = platform_get_drvdata(pdev); struct device *dev = &pdev->dev; int i; - if (priv->drvdata->otg_switch_supported) - usb_role_switch_unregister(priv->role_switch); + usb_role_switch_unregister(priv->role_switch); of_platform_depopulate(dev); @@ -859,8 +852,6 @@ static int dwc3_meson_g12a_remove(struct platform_device *pdev) clk_bulk_disable_unprepare(priv->drvdata->num_clks, priv->drvdata->clks); - - return 0; } static int __maybe_unused dwc3_meson_g12a_runtime_suspend(struct device *dev) @@ -971,7 +962,7 @@ MODULE_DEVICE_TABLE(of, dwc3_meson_g12a_match); static struct platform_driver dwc3_meson_g12a_driver = { .probe = dwc3_meson_g12a_probe, - .remove = dwc3_meson_g12a_remove, + .remove_new = dwc3_meson_g12a_remove, .driver = { .name = "dwc3-meson-g12a", .of_match_table = dwc3_meson_g12a_match, diff --git a/drivers/usb/dwc3/dwc3-of-simple.c b/drivers/usb/dwc3/dwc3-of-simple.c index 71fd620c5161931746411d44e0a944d981b0d3e5..7e6ad8fe61a5a2ba1f7a6768fefd9337fba94fc0 100644 --- a/drivers/usb/dwc3/dwc3-of-simple.c +++ b/drivers/usb/dwc3/dwc3-of-simple.c @@ -112,13 +112,11 @@ static void __dwc3_of_simple_teardown(struct dwc3_of_simple *simple) pm_runtime_set_suspended(simple->dev); } -static int dwc3_of_simple_remove(struct platform_device *pdev) +static void dwc3_of_simple_remove(struct platform_device *pdev) { struct dwc3_of_simple *simple = platform_get_drvdata(pdev); __dwc3_of_simple_teardown(simple); - - return 0; } static void dwc3_of_simple_shutdown(struct platform_device *pdev) @@ -183,7 +181,7 @@ MODULE_DEVICE_TABLE(of, of_dwc3_simple_match); static struct platform_driver dwc3_of_simple_driver = { .probe = dwc3_of_simple_probe, - .remove = dwc3_of_simple_remove, + .remove_new = dwc3_of_simple_remove, .shutdown = dwc3_of_simple_shutdown, .driver = { .name = "dwc3-of-simple", diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c index efaf0db595f4619ae4f32237967963626c4ca44b..d5c77db4daa920520406842882ed059a8126135b 100644 --- a/drivers/usb/dwc3/dwc3-omap.c +++ b/drivers/usb/dwc3/dwc3-omap.c @@ -534,7 +534,7 @@ static int dwc3_omap_probe(struct platform_device *pdev) return ret; } -static int dwc3_omap_remove(struct platform_device *pdev) +static void dwc3_omap_remove(struct platform_device *pdev) { struct dwc3_omap *omap = platform_get_drvdata(pdev); @@ -543,8 +543,6 @@ static int dwc3_omap_remove(struct platform_device *pdev) of_platform_depopulate(omap->dev); pm_runtime_put_sync(&pdev->dev); pm_runtime_disable(&pdev->dev); - - return 0; } static const struct of_device_id of_dwc3_match[] = { @@ -611,7 +609,7 @@ static const struct dev_pm_ops dwc3_omap_dev_pm_ops = { static struct platform_driver dwc3_omap_driver = { .probe = dwc3_omap_probe, - .remove = dwc3_omap_remove, + .remove_new = dwc3_omap_remove, .driver = { .name = "omap-dwc3", .of_match_table = of_dwc3_match, diff --git a/drivers/usb/dwc3/dwc3-qcom.c b/drivers/usb/dwc3/dwc3-qcom.c index 79b22abf97276fee67f594837d028262e7ff5729..3de43df6bbe814a16e1c1d7578711129843fef10 100644 --- a/drivers/usb/dwc3/dwc3-qcom.c +++ b/drivers/usb/dwc3/dwc3-qcom.c @@ -167,7 +167,8 @@ static int dwc3_qcom_register_extcon(struct dwc3_qcom *qcom) qcom->edev = extcon_get_edev_by_phandle(dev, 0); if (IS_ERR(qcom->edev)) - return PTR_ERR(qcom->edev); + return dev_err_probe(dev, PTR_ERR(qcom->edev), + "Failed to get extcon\n"); qcom->vbus_nb.notifier_call = dwc3_qcom_vbus_notifier; @@ -252,16 +253,14 @@ static int dwc3_qcom_interconnect_init(struct dwc3_qcom *qcom) qcom->icc_path_ddr = of_icc_get(dev, "usb-ddr"); if (IS_ERR(qcom->icc_path_ddr)) { - dev_err(dev, "failed to get usb-ddr path: %ld\n", - PTR_ERR(qcom->icc_path_ddr)); - return PTR_ERR(qcom->icc_path_ddr); + return dev_err_probe(dev, PTR_ERR(qcom->icc_path_ddr), + "failed to get usb-ddr path\n"); } qcom->icc_path_apps = of_icc_get(dev, "apps-usb"); if (IS_ERR(qcom->icc_path_apps)) { - dev_err(dev, "failed to get apps-usb path: %ld\n", - PTR_ERR(qcom->icc_path_apps)); - ret = PTR_ERR(qcom->icc_path_apps); + ret = dev_err_probe(dev, PTR_ERR(qcom->icc_path_apps), + "failed to get apps-usb path\n"); goto put_path_ddr; } @@ -800,6 +799,7 @@ static int dwc3_qcom_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct dwc3_qcom *qcom; struct resource *res, *parent_res = NULL; + struct resource local_res; int ret, i; bool ignore_pipe_clk; bool wakeup_source; @@ -821,9 +821,8 @@ static int dwc3_qcom_probe(struct platform_device *pdev) qcom->resets = devm_reset_control_array_get_optional_exclusive(dev); if (IS_ERR(qcom->resets)) { - ret = PTR_ERR(qcom->resets); - dev_err(&pdev->dev, "failed to get resets, err=%d\n", ret); - return ret; + return dev_err_probe(&pdev->dev, PTR_ERR(qcom->resets), + "failed to get resets\n"); } ret = reset_control_assert(qcom->resets); @@ -842,7 +841,7 @@ static int dwc3_qcom_probe(struct platform_device *pdev) ret = dwc3_qcom_clk_init(qcom, of_clk_get_parent_count(np)); if (ret) { - dev_err(dev, "failed to get clocks\n"); + dev_err_probe(dev, ret, "failed to get clocks\n"); goto reset_assert; } @@ -851,9 +850,8 @@ static int dwc3_qcom_probe(struct platform_device *pdev) if (np) { parent_res = res; } else { - parent_res = kmemdup(res, sizeof(struct resource), GFP_KERNEL); - if (!parent_res) - return -ENOMEM; + memcpy(&local_res, res, sizeof(struct resource)); + parent_res = &local_res; parent_res->start = res->start + qcom->acpi_pdata->qscratch_base_offset; @@ -865,9 +863,10 @@ static int dwc3_qcom_probe(struct platform_device *pdev) if (IS_ERR_OR_NULL(qcom->urs_usb)) { dev_err(dev, "failed to create URS USB platdev\n"); if (!qcom->urs_usb) - return -ENODEV; + ret = -ENODEV; else - return PTR_ERR(qcom->urs_usb); + ret = PTR_ERR(qcom->urs_usb); + goto clk_disable; } } } @@ -947,14 +946,18 @@ static int dwc3_qcom_probe(struct platform_device *pdev) return ret; } -static int dwc3_qcom_remove(struct platform_device *pdev) +static void dwc3_qcom_remove(struct platform_device *pdev) { struct dwc3_qcom *qcom = platform_get_drvdata(pdev); + struct device_node *np = pdev->dev.of_node; struct device *dev = &pdev->dev; int i; device_remove_software_node(&qcom->dwc3->dev); - of_platform_depopulate(dev); + if (np) + of_platform_depopulate(&pdev->dev); + else + platform_device_put(pdev); for (i = qcom->num_clocks - 1; i >= 0; i--) { clk_disable_unprepare(qcom->clks[i]); @@ -967,8 +970,6 @@ static int dwc3_qcom_remove(struct platform_device *pdev) pm_runtime_allow(dev); pm_runtime_disable(dev); - - return 0; } static int __maybe_unused dwc3_qcom_pm_suspend(struct device *dev) @@ -1061,7 +1062,7 @@ MODULE_DEVICE_TABLE(acpi, dwc3_qcom_acpi_match); static struct platform_driver dwc3_qcom_driver = { .probe = dwc3_qcom_probe, - .remove = dwc3_qcom_remove, + .remove_new = dwc3_qcom_remove, .driver = { .name = "dwc3-qcom", .pm = &dwc3_qcom_dev_pm_ops, diff --git a/drivers/usb/dwc3/dwc3-st.c b/drivers/usb/dwc3/dwc3-st.c index fea5290de83fb59de23dccfb58e29ae6daadcf7b..211360eee95a0f383b96ed791e3bdf99fa4b4364 100644 --- a/drivers/usb/dwc3/dwc3-st.c +++ b/drivers/usb/dwc3/dwc3-st.c @@ -305,7 +305,7 @@ static int st_dwc3_probe(struct platform_device *pdev) return ret; } -static int st_dwc3_remove(struct platform_device *pdev) +static void st_dwc3_remove(struct platform_device *pdev) { struct st_dwc3 *dwc3_data = platform_get_drvdata(pdev); @@ -313,8 +313,6 @@ static int st_dwc3_remove(struct platform_device *pdev) reset_control_assert(dwc3_data->rstc_pwrdn); reset_control_assert(dwc3_data->rstc_rst); - - return 0; } #ifdef CONFIG_PM_SLEEP @@ -364,7 +362,7 @@ MODULE_DEVICE_TABLE(of, st_dwc3_match); static struct platform_driver st_dwc3_driver = { .probe = st_dwc3_probe, - .remove = st_dwc3_remove, + .remove_new = st_dwc3_remove, .driver = { .name = "usb-st-dwc3", .of_match_table = st_dwc3_match, diff --git a/drivers/usb/dwc3/dwc3-xilinx.c b/drivers/usb/dwc3/dwc3-xilinx.c index 2c36f97652cab996eae20180defb2dddee569769..19307d24f3a06b75f20532522d42fed6ea350cea 100644 --- a/drivers/usb/dwc3/dwc3-xilinx.c +++ b/drivers/usb/dwc3/dwc3-xilinx.c @@ -305,7 +305,7 @@ static int dwc3_xlnx_probe(struct platform_device *pdev) return ret; } -static int dwc3_xlnx_remove(struct platform_device *pdev) +static void dwc3_xlnx_remove(struct platform_device *pdev) { struct dwc3_xlnx *priv_data = platform_get_drvdata(pdev); struct device *dev = &pdev->dev; @@ -318,8 +318,6 @@ static int dwc3_xlnx_remove(struct platform_device *pdev) pm_runtime_disable(dev); pm_runtime_put_noidle(dev); pm_runtime_set_suspended(dev); - - return 0; } static int __maybe_unused dwc3_xlnx_runtime_suspend(struct device *dev) @@ -388,7 +386,7 @@ static const struct dev_pm_ops dwc3_xlnx_dev_pm_ops = { static struct platform_driver dwc3_xlnx_driver = { .probe = dwc3_xlnx_probe, - .remove = dwc3_xlnx_remove, + .remove_new = dwc3_xlnx_remove, .driver = { .name = "dwc3-xilinx", .of_match_table = dwc3_xlnx_of_match, diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index 953b752a50526dd37c0968258d972df4cef2b645..b94243237293792762e6fd64babf72ef3373e805 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -1207,5 +1207,8 @@ void dwc3_ep0_interrupt(struct dwc3 *dwc, dep->flags &= ~DWC3_EP_TRANSFER_STARTED; } break; + default: + dev_err(dwc->dev, "unknown endpoint event %d\n", event->endpoint_event); + break; } } diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index b78599dd705c28a9bf38943a649d710ec5226709..5fd067151fbf5745c65e54cce5519c279154e0da 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -2703,13 +2703,17 @@ static int dwc3_gadget_soft_disconnect(struct dwc3 *dwc) static int dwc3_gadget_soft_connect(struct dwc3 *dwc) { + int ret; + /* * In the Synopsys DWC_usb31 1.90a programming guide section * 4.1.9, it specifies that for a reconnect after a * device-initiated disconnect requires a core soft reset * (DCTL.CSftRst) before enabling the run/stop bit. */ - dwc3_core_soft_reset(dwc); + ret = dwc3_core_soft_reset(dwc); + if (ret) + return ret; dwc3_event_buffers_setup(dwc); __dwc3_gadget_start(dwc); @@ -2744,7 +2748,9 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on) ret = pm_runtime_get_sync(dwc->dev); if (!ret || ret < 0) { pm_runtime_put(dwc->dev); - return 0; + if (ret < 0) + pm_runtime_set_suspended(dwc->dev); + return ret; } if (dwc->pullups_connected == is_on) { @@ -3809,6 +3815,9 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc, break; case DWC3_DEPEVT_RXTXFIFOEVT: break; + default: + dev_err(dwc->dev, "unknown endpoint event %d\n", event->endpoint_event); + break; } } diff --git a/drivers/usb/fotg210/fotg210-core.c b/drivers/usb/fotg210/fotg210-core.c index cb75464ab29051fd60468c7030b860a2d42971f9..958fc40eae86b741caada6a1efc5e50b7b41e299 100644 --- a/drivers/usb/fotg210/fotg210-core.c +++ b/drivers/usb/fotg210/fotg210-core.c @@ -165,7 +165,7 @@ static int fotg210_probe(struct platform_device *pdev) return ret; } -static int fotg210_remove(struct platform_device *pdev) +static void fotg210_remove(struct platform_device *pdev) { struct device *dev = &pdev->dev; enum usb_dr_mode mode; @@ -176,8 +176,6 @@ static int fotg210_remove(struct platform_device *pdev) fotg210_udc_remove(pdev); else fotg210_hcd_remove(pdev); - - return 0; } #ifdef CONFIG_OF @@ -196,7 +194,7 @@ static struct platform_driver fotg210_driver = { .of_match_table = of_match_ptr(fotg210_of_match), }, .probe = fotg210_probe, - .remove = fotg210_remove, + .remove_new = fotg210_remove, }; static int __init fotg210_init(void) diff --git a/drivers/usb/gadget/function/f_hid.c b/drivers/usb/gadget/function/f_hid.c index 9f6b101341210d5711be7935212d343c6f74edb2..ea85e2c701a15f304c2082a720aa076c32bf91a9 100644 --- a/drivers/usb/gadget/function/f_hid.c +++ b/drivers/usb/gadget/function/f_hid.c @@ -23,7 +23,11 @@ #define HIDG_MINORS 4 static int major, minors; -static struct class *hidg_class; + +static const struct class hidg_class = { + .name = "hidg", +}; + static DEFINE_IDA(hidg_ida); static DEFINE_MUTEX(hidg_ida_lock); /* protects access to hidg_ida */ @@ -1272,7 +1276,7 @@ static struct usb_function *hidg_alloc(struct usb_function_instance *fi) device_initialize(&hidg->dev); hidg->dev.release = hidg_release; - hidg->dev.class = hidg_class; + hidg->dev.class = &hidg_class; hidg->dev.devt = MKDEV(major, opts->minor); ret = dev_set_name(&hidg->dev, "hidg%d", opts->minor); if (ret) @@ -1325,17 +1329,13 @@ int ghid_setup(struct usb_gadget *g, int count) int status; dev_t dev; - hidg_class = class_create("hidg"); - if (IS_ERR(hidg_class)) { - status = PTR_ERR(hidg_class); - hidg_class = NULL; + status = class_register(&hidg_class); + if (status) return status; - } status = alloc_chrdev_region(&dev, 0, count, "hidg"); if (status) { - class_destroy(hidg_class); - hidg_class = NULL; + class_unregister(&hidg_class); return status; } @@ -1352,6 +1352,5 @@ void ghid_cleanup(void) major = minors = 0; } - class_destroy(hidg_class); - hidg_class = NULL; + class_unregister(&hidg_class); } diff --git a/drivers/usb/gadget/function/f_mass_storage.c b/drivers/usb/gadget/function/f_mass_storage.c index 3a30feb47073f0aeeac0bd13e5f82e36cfe2a030..da07e45ae6df5c16280652152d68d6ee8b4bec28 100644 --- a/drivers/usb/gadget/function/f_mass_storage.c +++ b/drivers/usb/gadget/function/f_mass_storage.c @@ -2857,7 +2857,7 @@ int fsg_common_create_lun(struct fsg_common *common, struct fsg_lun_config *cfg, const char **name_pfx) { struct fsg_lun *lun; - char *pathbuf, *p; + char *pathbuf = NULL, *p = "(no medium)"; int rc = -ENOMEM; if (id >= ARRAY_SIZE(common->luns)) @@ -2907,12 +2907,9 @@ int fsg_common_create_lun(struct fsg_common *common, struct fsg_lun_config *cfg, rc = fsg_lun_open(lun, cfg->filename); if (rc) goto error_lun; - } - pathbuf = kmalloc(PATH_MAX, GFP_KERNEL); - p = "(no medium)"; - if (fsg_lun_is_open(lun)) { p = "(error)"; + pathbuf = kmalloc(PATH_MAX, GFP_KERNEL); if (pathbuf) { p = file_path(lun->filp, pathbuf, PATH_MAX); if (IS_ERR(p)) @@ -2931,7 +2928,6 @@ int fsg_common_create_lun(struct fsg_common *common, struct fsg_lun_config *cfg, error_lun: if (device_is_registered(&lun->dev)) device_unregister(&lun->dev); - fsg_lun_close(lun); common->luns[id] = NULL; error_sysfs: kfree(lun); diff --git a/drivers/usb/gadget/function/f_printer.c b/drivers/usb/gadget/function/f_printer.c index 28db3e336e7db877c3138a6742fb0c289b9127c2..076dd4c1be96c0644871995197044aaebed96f95 100644 --- a/drivers/usb/gadget/function/f_printer.c +++ b/drivers/usb/gadget/function/f_printer.c @@ -54,7 +54,10 @@ #define DEFAULT_Q_LEN 10 /* same as legacy g_printer gadget */ static int major, minors; -static struct class *usb_gadget_class; +static const struct class usb_gadget_class = { + .name = "usb_printer_gadget", +}; + static DEFINE_IDA(printer_ida); static DEFINE_MUTEX(printer_ida_lock); /* protects access do printer_ida */ @@ -1120,7 +1123,7 @@ static int printer_func_bind(struct usb_configuration *c, /* Setup the sysfs files for the printer gadget. */ devt = MKDEV(major, dev->minor); - pdev = device_create(usb_gadget_class, NULL, devt, + pdev = device_create(&usb_gadget_class, NULL, devt, NULL, "g_printer%d", dev->minor); if (IS_ERR(pdev)) { ERROR(dev, "Failed to create device: g_printer\n"); @@ -1143,7 +1146,7 @@ static int printer_func_bind(struct usb_configuration *c, return 0; fail_cdev_add: - device_destroy(usb_gadget_class, devt); + device_destroy(&usb_gadget_class, devt); fail_rx_reqs: while (!list_empty(&dev->rx_reqs)) { @@ -1211,8 +1214,8 @@ static ssize_t f_printer_opts_pnp_string_show(struct config_item *item, if (!opts->pnp_string) goto unlock; - result = strlcpy(page, opts->pnp_string, PAGE_SIZE); - if (result >= PAGE_SIZE) { + result = strscpy(page, opts->pnp_string, PAGE_SIZE); + if (result < 1) { result = PAGE_SIZE; } else if (page[result - 1] != '\n' && result + 1 < PAGE_SIZE) { page[result++] = '\n'; @@ -1410,7 +1413,7 @@ static void printer_func_unbind(struct usb_configuration *c, dev = func_to_printer(f); - device_destroy(usb_gadget_class, MKDEV(major, dev->minor)); + device_destroy(&usb_gadget_class, MKDEV(major, dev->minor)); /* Remove Character Device */ cdev_del(&dev->printer_cdev); @@ -1512,19 +1515,14 @@ static int gprinter_setup(int count) int status; dev_t devt; - usb_gadget_class = class_create("usb_printer_gadget"); - if (IS_ERR(usb_gadget_class)) { - status = PTR_ERR(usb_gadget_class); - usb_gadget_class = NULL; - pr_err("unable to create usb_gadget class %d\n", status); + status = class_register(&usb_gadget_class); + if (status) return status; - } status = alloc_chrdev_region(&devt, 0, count, "USB printer gadget"); if (status) { pr_err("alloc_chrdev_region %d\n", status); - class_destroy(usb_gadget_class); - usb_gadget_class = NULL; + class_unregister(&usb_gadget_class); return status; } @@ -1540,6 +1538,5 @@ static void gprinter_cleanup(void) unregister_chrdev_region(MKDEV(major, 0), minors); major = minors = 0; } - class_destroy(usb_gadget_class); - usb_gadget_class = NULL; + class_unregister(&usb_gadget_class); } diff --git a/drivers/usb/gadget/function/u_serial.c b/drivers/usb/gadget/function/u_serial.c index a0ca47fbff0fc945691eec85418d7b6d3f0158a8..1115396b46a0a65ab137f6b7d5fe32a9fed533c5 100644 --- a/drivers/usb/gadget/function/u_serial.c +++ b/drivers/usb/gadget/function/u_serial.c @@ -539,16 +539,20 @@ static int gs_alloc_requests(struct usb_ep *ep, struct list_head *head, static int gs_start_io(struct gs_port *port) { struct list_head *head = &port->read_pool; - struct usb_ep *ep = port->port_usb->out; + struct usb_ep *ep; int status; unsigned started; + if (!port->port_usb || !port->port.tty) + return -EIO; + /* Allocate RX and TX I/O buffers. We can't easily do this much * earlier (with GFP_KERNEL) because the requests are coupled to * endpoints, as are the packet sizes we'll be using. Different * configurations may use different endpoints with a given port; * and high speed vs full speed changes packet sizes too. */ + ep = port->port_usb->out; status = gs_alloc_requests(ep, head, gs_read_complete, &port->read_allocated); if (status) @@ -916,8 +920,11 @@ static void __gs_console_push(struct gs_console *cons) } req->length = size; + + spin_unlock_irq(&cons->lock); if (usb_ep_queue(ep, req, GFP_ATOMIC)) req->length = 0; + spin_lock_irq(&cons->lock); } static void gs_console_work(struct work_struct *work) @@ -1420,10 +1427,19 @@ EXPORT_SYMBOL_GPL(gserial_disconnect); void gserial_suspend(struct gserial *gser) { - struct gs_port *port = gser->ioport; + struct gs_port *port; unsigned long flags; - spin_lock_irqsave(&port->port_lock, flags); + spin_lock_irqsave(&serial_port_lock, flags); + port = gser->ioport; + + if (!port) { + spin_unlock_irqrestore(&serial_port_lock, flags); + return; + } + + spin_lock(&port->port_lock); + spin_unlock(&serial_port_lock); port->suspended = true; spin_unlock_irqrestore(&port->port_lock, flags); } diff --git a/drivers/usb/gadget/function/uvc_video.c b/drivers/usb/gadget/function/uvc_video.c index dd1c6b2ca7c6f3f8f8efb4d33e0bfb856d513986..91af3b1ef0d412e9d71720afb38f24a703ec4e6e 100644 --- a/drivers/usb/gadget/function/uvc_video.c +++ b/drivers/usb/gadget/function/uvc_video.c @@ -382,9 +382,12 @@ static void uvcg_video_pump(struct work_struct *work) { struct uvc_video *video = container_of(work, struct uvc_video, pump); struct uvc_video_queue *queue = &video->queue; + /* video->max_payload_size is only set when using bulk transfer */ + bool is_bulk = video->max_payload_size; struct usb_request *req = NULL; struct uvc_buffer *buf; unsigned long flags; + bool buf_done; int ret; while (video->ep->enabled) { @@ -408,20 +411,47 @@ static void uvcg_video_pump(struct work_struct *work) */ spin_lock_irqsave(&queue->irqlock, flags); buf = uvcg_queue_head(queue); - if (buf == NULL) { + + if (buf != NULL) { + video->encode(req, video, buf); + buf_done = buf->state == UVC_BUF_STATE_DONE; + } else if (!(queue->flags & UVC_QUEUE_DISCONNECTED) && !is_bulk) { + /* + * No video buffer available; the queue is still connected and + * we're transferring over ISOC. Queue a 0 length request to + * prevent missed ISOC transfers. + */ + req->length = 0; + buf_done = false; + } else { + /* + * Either the queue has been disconnected or no video buffer + * available for bulk transfer. Either way, stop processing + * further. + */ spin_unlock_irqrestore(&queue->irqlock, flags); break; } - video->encode(req, video, buf); - /* - * With usb3 we have more requests. This will decrease the - * interrupt load to a quarter but also catches the corner - * cases, which needs to be handled. + * With USB3 handling more requests at a higher speed, we can't + * afford to generate an interrupt for every request. Decide to + * interrupt: + * + * - When no more requests are available in the free queue, as + * this may be our last chance to refill the endpoint's + * request queue. + * + * - When this is request is the last request for the video + * buffer, as we want to start sending the next video buffer + * ASAP in case it doesn't get started already in the next + * iteration of this loop. + * + * - Four times over the length of the requests queue (as + * indicated by video->uvc_num_requests), as a trade-off + * between latency and interrupt load. */ - if (list_empty(&video->req_free) || - buf->state == UVC_BUF_STATE_DONE || + if (list_empty(&video->req_free) || buf_done || !(video->req_int_count % DIV_ROUND_UP(video->uvc_num_requests, 4))) { video->req_int_count = 0; @@ -441,8 +471,7 @@ static void uvcg_video_pump(struct work_struct *work) /* Endpoint now owns the request */ req = NULL; - if (buf->state != UVC_BUF_STATE_DONE) - video->req_int_count++; + video->req_int_count++; } if (!req) @@ -527,4 +556,3 @@ int uvcg_video_init(struct uvc_video *video, struct uvc_device *uvc) V4L2_BUF_TYPE_VIDEO_OUTPUT, &video->mutex); return 0; } - diff --git a/drivers/usb/gadget/legacy/g_ffs.c b/drivers/usb/gadget/legacy/g_ffs.c index 097854683e5b37b1ef88b839a80aa12faadb8057..a9544fea87237bf4be630ec784adce4a87dd6944 100644 --- a/drivers/usb/gadget/legacy/g_ffs.c +++ b/drivers/usb/gadget/legacy/g_ffs.c @@ -389,8 +389,10 @@ static int gfs_bind(struct usb_composite_dev *cdev) struct usb_descriptor_header *usb_desc; usb_desc = usb_otg_descriptor_alloc(cdev->gadget); - if (!usb_desc) + if (!usb_desc) { + ret = -ENOMEM; goto error_rndis; + } usb_otg_descriptor_init(cdev->gadget, usb_desc); gfs_otg_desc[0] = usb_desc; gfs_otg_desc[1] = NULL; diff --git a/drivers/usb/gadget/legacy/hid.c b/drivers/usb/gadget/legacy/hid.c index 133daf88162efe440ac5a51457256a306af2e129..4ca67b2f8f2437dcf1e2fd6ca02524a6acc0fc82 100644 --- a/drivers/usb/gadget/legacy/hid.c +++ b/drivers/usb/gadget/legacy/hid.c @@ -237,7 +237,7 @@ static int hidg_plat_driver_probe(struct platform_device *pdev) return 0; } -static int hidg_plat_driver_remove(struct platform_device *pdev) +static void hidg_plat_driver_remove(struct platform_device *pdev) { struct hidg_func_node *e, *n; @@ -245,8 +245,6 @@ static int hidg_plat_driver_remove(struct platform_device *pdev) list_del(&e->node); kfree(e); } - - return 0; } @@ -263,7 +261,7 @@ static struct usb_composite_driver hidg_driver = { }; static struct platform_driver hidg_plat_driver = { - .remove = hidg_plat_driver_remove, + .remove_new = hidg_plat_driver_remove, .driver = { .name = "hidg", }, diff --git a/drivers/usb/gadget/udc/Kconfig b/drivers/usb/gadget/udc/Kconfig index 83cae6bb12ebcc6be446628254ba7e632b6ef70c..aae1787320d4eb1b25e0c9dbf76ec9145d3d82d5 100644 --- a/drivers/usb/gadget/udc/Kconfig +++ b/drivers/usb/gadget/udc/Kconfig @@ -463,6 +463,8 @@ config USB_ASPEED_UDC source "drivers/usb/gadget/udc/aspeed-vhub/Kconfig" +source "drivers/usb/gadget/udc/cdns2/Kconfig" + # # LAST -- dummy/emulated controller # diff --git a/drivers/usb/gadget/udc/Makefile b/drivers/usb/gadget/udc/Makefile index ee569f63c74ae7ab847fb389dd6594393772444d..b52f93e9c61d39691806d7cb564bfe3aadd4b0b8 100644 --- a/drivers/usb/gadget/udc/Makefile +++ b/drivers/usb/gadget/udc/Makefile @@ -42,3 +42,4 @@ obj-$(CONFIG_USB_ASPEED_VHUB) += aspeed-vhub/ obj-$(CONFIG_USB_ASPEED_UDC) += aspeed_udc.o obj-$(CONFIG_USB_BDC_UDC) += bdc/ obj-$(CONFIG_USB_MAX3420_UDC) += max3420_udc.o +obj-$(CONFIG_USB_CDNS2_UDC) += cdns2/ diff --git a/drivers/usb/gadget/udc/aspeed-vhub/core.c b/drivers/usb/gadget/udc/aspeed-vhub/core.c index 86398a04a012d5e31a2a6fe7429c1837f4b799ff..16f2db8c4a2b37013647fbaad0b40c0a8e02d28a 100644 --- a/drivers/usb/gadget/udc/aspeed-vhub/core.c +++ b/drivers/usb/gadget/udc/aspeed-vhub/core.c @@ -253,14 +253,14 @@ void ast_vhub_init_hw(struct ast_vhub *vhub) vhub->regs + AST_VHUB_IER); } -static int ast_vhub_remove(struct platform_device *pdev) +static void ast_vhub_remove(struct platform_device *pdev) { struct ast_vhub *vhub = platform_get_drvdata(pdev); unsigned long flags; int i; if (!vhub || !vhub->regs) - return 0; + return; /* Remove devices */ for (i = 0; i < vhub->max_ports; i++) @@ -289,8 +289,6 @@ static int ast_vhub_remove(struct platform_device *pdev) vhub->ep0_bufs, vhub->ep0_bufs_dma); vhub->ep0_bufs = NULL; - - return 0; } static int ast_vhub_probe(struct platform_device *pdev) @@ -431,7 +429,7 @@ MODULE_DEVICE_TABLE(of, ast_vhub_dt_ids); static struct platform_driver ast_vhub_driver = { .probe = ast_vhub_probe, - .remove = ast_vhub_remove, + .remove_new = ast_vhub_remove, .driver = { .name = KBUILD_MODNAME, .of_match_table = ast_vhub_dt_ids, diff --git a/drivers/usb/gadget/udc/atmel_usba_udc.c b/drivers/usb/gadget/udc/atmel_usba_udc.c index 53ca38c4b3ec6b81f6938d76bab52f8351073fc8..6c0ed3fa5eb1be249dda56b319f78ee3d291dabe 100644 --- a/drivers/usb/gadget/udc/atmel_usba_udc.c +++ b/drivers/usb/gadget/udc/atmel_usba_udc.c @@ -2369,7 +2369,7 @@ static int usba_udc_probe(struct platform_device *pdev) return 0; } -static int usba_udc_remove(struct platform_device *pdev) +static void usba_udc_remove(struct platform_device *pdev) { struct usba_udc *udc; int i; @@ -2382,8 +2382,6 @@ static int usba_udc_remove(struct platform_device *pdev) for (i = 1; i < udc->num_ep; i++) usba_ep_cleanup_debugfs(&udc->usba_ep[i]); usba_cleanup_debugfs(udc); - - return 0; } #ifdef CONFIG_PM_SLEEP @@ -2450,7 +2448,7 @@ static SIMPLE_DEV_PM_OPS(usba_udc_pm_ops, usba_udc_suspend, usba_udc_resume); static struct platform_driver udc_driver = { .probe = usba_udc_probe, - .remove = usba_udc_remove, + .remove_new = usba_udc_remove, .driver = { .name = "atmel_usba_udc", .pm = &usba_udc_pm_ops, diff --git a/drivers/usb/gadget/udc/bcm63xx_udc.c b/drivers/usb/gadget/udc/bcm63xx_udc.c index a3055dd4acfb51fbc83075373ee85baae4a43ccd..da7011d906e01db59fcac559eea1453bd1c08040 100644 --- a/drivers/usb/gadget/udc/bcm63xx_udc.c +++ b/drivers/usb/gadget/udc/bcm63xx_udc.c @@ -2354,7 +2354,7 @@ static int bcm63xx_udc_probe(struct platform_device *pdev) * bcm63xx_udc_remove - Remove the device from the system. * @pdev: Platform device struct from the bcm63xx BSP code. */ -static int bcm63xx_udc_remove(struct platform_device *pdev) +static void bcm63xx_udc_remove(struct platform_device *pdev) { struct bcm63xx_udc *udc = platform_get_drvdata(pdev); @@ -2363,13 +2363,11 @@ static int bcm63xx_udc_remove(struct platform_device *pdev) BUG_ON(udc->driver); bcm63xx_uninit_udc_hw(udc); - - return 0; } static struct platform_driver bcm63xx_udc_driver = { .probe = bcm63xx_udc_probe, - .remove = bcm63xx_udc_remove, + .remove_new = bcm63xx_udc_remove, .driver = { .name = DRV_MODULE_NAME, }, diff --git a/drivers/usb/gadget/udc/bdc/bdc_core.c b/drivers/usb/gadget/udc/bdc/bdc_core.c index 9849e0c86e23e9b204a00daf873231ba51472b18..35a652807fca870a84eed3bc35948471d6834c8b 100644 --- a/drivers/usb/gadget/udc/bdc/bdc_core.c +++ b/drivers/usb/gadget/udc/bdc/bdc_core.c @@ -583,7 +583,7 @@ static int bdc_probe(struct platform_device *pdev) return ret; } -static int bdc_remove(struct platform_device *pdev) +static void bdc_remove(struct platform_device *pdev) { struct bdc *bdc; @@ -593,7 +593,6 @@ static int bdc_remove(struct platform_device *pdev) bdc_hw_exit(bdc); bdc_phy_exit(bdc); clk_disable_unprepare(bdc->clk); - return 0; } #ifdef CONFIG_PM_SLEEP @@ -648,7 +647,7 @@ static struct platform_driver bdc_driver = { .of_match_table = bdc_of_match, }, .probe = bdc_probe, - .remove = bdc_remove, + .remove_new = bdc_remove, }; module_platform_driver(bdc_driver); diff --git a/drivers/usb/gadget/udc/cdns2/Kconfig b/drivers/usb/gadget/udc/cdns2/Kconfig new file mode 100644 index 0000000000000000000000000000000000000000..c07d353903ea0f0b11129b120e6834eec2d9a009 --- /dev/null +++ b/drivers/usb/gadget/udc/cdns2/Kconfig @@ -0,0 +1,11 @@ +config USB_CDNS2_UDC + tristate "Cadence USBHS Device Controller" + depends on USB_PCI && ACPI && HAS_DMA + help + Cadence USBHS Device controller is a PCI based USB peripheral + controller which supports both full and high speed USB 2.0 + data transfers. + + Say "y" to link the driver statically, or "m" to build a + dynamically linked module called "cdns2-udc-pci.ko" and to + force all gadget drivers to also be dynamically linked. diff --git a/drivers/usb/gadget/udc/cdns2/Makefile b/drivers/usb/gadget/udc/cdns2/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..a1ffbbe2e76893b760db301c4d70cd3a4dffb628 --- /dev/null +++ b/drivers/usb/gadget/udc/cdns2/Makefile @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: GPL-2.0 +# define_trace.h needs to know how to find our header +CFLAGS_cdns2-trace.o := -I$(src) + +obj-$(CONFIG_USB_CDNS2_UDC) += cdns2-udc-pci.o +cdns2-udc-pci-$(CONFIG_USB_CDNS2_UDC) += cdns2-pci.o cdns2-gadget.o cdns2-ep0.o +cdns2-udc-pci-$(CONFIG_TRACING) += cdns2-trace.o diff --git a/drivers/usb/gadget/udc/cdns2/cdns2-debug.h b/drivers/usb/gadget/udc/cdns2/cdns2-debug.h new file mode 100644 index 0000000000000000000000000000000000000000..be9ae0d28a40975be29f9ee27c81c4b789324800 --- /dev/null +++ b/drivers/usb/gadget/udc/cdns2/cdns2-debug.h @@ -0,0 +1,203 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Cadence USBHS-DEV Driver. + * Debug header file. + * + * Copyright (C) 2023 Cadence. + * + * Author: Pawel Laszczak + */ + +#ifndef __LINUX_CDNS2_DEBUG +#define __LINUX_CDNS2_DEBUG + +static inline const char *cdns2_decode_usb_irq(char *str, size_t size, + u8 usb_irq, u8 ext_irq) +{ + int ret; + + ret = snprintf(str, size, "usbirq: 0x%02x - ", usb_irq); + + if (usb_irq & USBIRQ_SOF) + ret += snprintf(str + ret, size - ret, "SOF "); + if (usb_irq & USBIRQ_SUTOK) + ret += snprintf(str + ret, size - ret, "SUTOK "); + if (usb_irq & USBIRQ_SUDAV) + ret += snprintf(str + ret, size - ret, "SETUP "); + if (usb_irq & USBIRQ_SUSPEND) + ret += snprintf(str + ret, size - ret, "Suspend "); + if (usb_irq & USBIRQ_URESET) + ret += snprintf(str + ret, size - ret, "Reset "); + if (usb_irq & USBIRQ_HSPEED) + ret += snprintf(str + ret, size - ret, "HS "); + if (usb_irq & USBIRQ_LPM) + ret += snprintf(str + ret, size - ret, "LPM "); + + ret += snprintf(str + ret, size - ret, ", EXT: 0x%02x - ", ext_irq); + + if (ext_irq & EXTIRQ_WAKEUP) + ret += snprintf(str + ret, size - ret, "Wakeup "); + if (ext_irq & EXTIRQ_VBUSFAULT_FALL) + ret += snprintf(str + ret, size - ret, "VBUS_FALL "); + if (ext_irq & EXTIRQ_VBUSFAULT_RISE) + ret += snprintf(str + ret, size - ret, "VBUS_RISE "); + + if (ret >= size) + pr_info("CDNS2: buffer overflowed.\n"); + + return str; +} + +static inline const char *cdns2_decode_dma_irq(char *str, size_t size, + u32 ep_ists, u32 ep_sts, + const char *ep_name) +{ + int ret; + + ret = snprintf(str, size, "ISTS: %08x, %s: %08x ", + ep_ists, ep_name, ep_sts); + + if (ep_sts & DMA_EP_STS_IOC) + ret += snprintf(str + ret, size - ret, "IOC "); + if (ep_sts & DMA_EP_STS_ISP) + ret += snprintf(str + ret, size - ret, "ISP "); + if (ep_sts & DMA_EP_STS_DESCMIS) + ret += snprintf(str + ret, size - ret, "DESCMIS "); + if (ep_sts & DMA_EP_STS_TRBERR) + ret += snprintf(str + ret, size - ret, "TRBERR "); + if (ep_sts & DMA_EP_STS_OUTSMM) + ret += snprintf(str + ret, size - ret, "OUTSMM "); + if (ep_sts & DMA_EP_STS_ISOERR) + ret += snprintf(str + ret, size - ret, "ISOERR "); + if (ep_sts & DMA_EP_STS_DBUSY) + ret += snprintf(str + ret, size - ret, "DBUSY "); + if (DMA_EP_STS_CCS(ep_sts)) + ret += snprintf(str + ret, size - ret, "CCS "); + + if (ret >= size) + pr_info("CDNS2: buffer overflowed.\n"); + + return str; +} + +static inline const char *cdns2_decode_epx_irq(char *str, size_t size, + char *ep_name, u32 ep_ists, + u32 ep_sts) +{ + return cdns2_decode_dma_irq(str, size, ep_ists, ep_sts, ep_name); +} + +static inline const char *cdns2_decode_ep0_irq(char *str, size_t size, + u32 ep_ists, u32 ep_sts, + int dir) +{ + return cdns2_decode_dma_irq(str, size, ep_ists, ep_sts, + dir ? "ep0IN" : "ep0OUT"); +} + +static inline const char *cdns2_raw_ring(struct cdns2_endpoint *pep, + struct cdns2_trb *trbs, + char *str, size_t size) +{ + struct cdns2_ring *ring = &pep->ring; + struct cdns2_trb *trb; + dma_addr_t dma; + int ret; + int i; + + ret = snprintf(str, size, "\n\t\tTR for %s:", pep->name); + + trb = &trbs[ring->dequeue]; + dma = cdns2_trb_virt_to_dma(pep, trb); + ret += snprintf(str + ret, size - ret, + "\n\t\tRing deq index: %d, trb: V=%p, P=0x%pad\n", + ring->dequeue, trb, &dma); + + trb = &trbs[ring->enqueue]; + dma = cdns2_trb_virt_to_dma(pep, trb); + ret += snprintf(str + ret, size - ret, + "\t\tRing enq index: %d, trb: V=%p, P=0x%pad\n", + ring->enqueue, trb, &dma); + + ret += snprintf(str + ret, size - ret, + "\t\tfree trbs: %d, CCS=%d, PCS=%d\n", + ring->free_trbs, ring->ccs, ring->pcs); + + if (TRBS_PER_SEGMENT > 40) { + ret += snprintf(str + ret, size - ret, + "\t\tTransfer ring %d too big\n", TRBS_PER_SEGMENT); + return str; + } + + dma = ring->dma; + for (i = 0; i < TRBS_PER_SEGMENT; ++i) { + trb = &trbs[i]; + ret += snprintf(str + ret, size - ret, + "\t\t@%pad %08x %08x %08x\n", &dma, + le32_to_cpu(trb->buffer), + le32_to_cpu(trb->length), + le32_to_cpu(trb->control)); + dma += sizeof(*trb); + } + + if (ret >= size) + pr_info("CDNS2: buffer overflowed.\n"); + + return str; +} + +static inline const char *cdns2_trb_type_string(u8 type) +{ + switch (type) { + case TRB_NORMAL: + return "Normal"; + case TRB_LINK: + return "Link"; + default: + return "UNKNOWN"; + } +} + +static inline const char *cdns2_decode_trb(char *str, size_t size, u32 flags, + u32 length, u32 buffer) +{ + int type = TRB_FIELD_TO_TYPE(flags); + int ret; + + switch (type) { + case TRB_LINK: + ret = snprintf(str, size, + "LINK %08x type '%s' flags %c:%c:%c%c:%c", + buffer, cdns2_trb_type_string(type), + flags & TRB_CYCLE ? 'C' : 'c', + flags & TRB_TOGGLE ? 'T' : 't', + flags & TRB_CHAIN ? 'C' : 'c', + flags & TRB_CHAIN ? 'H' : 'h', + flags & TRB_IOC ? 'I' : 'i'); + break; + case TRB_NORMAL: + ret = snprintf(str, size, + "type: '%s', Buffer: %08x, length: %ld, burst len: %ld, " + "flags %c:%c:%c%c:%c", + cdns2_trb_type_string(type), + buffer, TRB_LEN(length), + TRB_FIELD_TO_BURST(length), + flags & TRB_CYCLE ? 'C' : 'c', + flags & TRB_ISP ? 'I' : 'i', + flags & TRB_CHAIN ? 'C' : 'c', + flags & TRB_CHAIN ? 'H' : 'h', + flags & TRB_IOC ? 'I' : 'i'); + break; + default: + ret = snprintf(str, size, "type '%s' -> raw %08x %08x %08x", + cdns2_trb_type_string(type), + buffer, length, flags); + } + + if (ret >= size) + pr_info("CDNS2: buffer overflowed.\n"); + + return str; +} + +#endif /*__LINUX_CDNS2_DEBUG*/ diff --git a/drivers/usb/gadget/udc/cdns2/cdns2-ep0.c b/drivers/usb/gadget/udc/cdns2/cdns2-ep0.c new file mode 100644 index 0000000000000000000000000000000000000000..fa12a5d46f2e9ae480abd04fe996006ae4f759e2 --- /dev/null +++ b/drivers/usb/gadget/udc/cdns2/cdns2-ep0.c @@ -0,0 +1,659 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Cadence USBHS-DEV driver. + * + * Copyright (C) 2023 Cadence Design Systems. + * + * Authors: Pawel Laszczak + */ + +#include +#include + +#include "cdns2-gadget.h" +#include "cdns2-trace.h" + +static struct usb_endpoint_descriptor cdns2_gadget_ep0_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bmAttributes = USB_ENDPOINT_XFER_CONTROL, + .wMaxPacketSize = cpu_to_le16(64) +}; + +static int cdns2_w_index_to_ep_index(u16 wIndex) +{ + if (!(wIndex & USB_ENDPOINT_NUMBER_MASK)) + return 0; + + return ((wIndex & USB_ENDPOINT_NUMBER_MASK) * 2) + + (wIndex & USB_ENDPOINT_DIR_MASK ? 1 : 0) - 1; +} + +static bool cdns2_check_new_setup(struct cdns2_device *pdev) +{ + u8 reg; + + reg = readb(&pdev->ep0_regs->cs); + + return !!(reg & EP0CS_CHGSET); +} + +static void cdns2_ep0_enqueue(struct cdns2_device *pdev, dma_addr_t dma_addr, + unsigned int length, int zlp) +{ + struct cdns2_adma_regs __iomem *regs = pdev->adma_regs; + struct cdns2_endpoint *pep = &pdev->eps[0]; + struct cdns2_ring *ring = &pep->ring; + + ring->trbs[0].buffer = cpu_to_le32(TRB_BUFFER(dma_addr)); + ring->trbs[0].length = cpu_to_le32(TRB_LEN(length)); + + if (zlp) { + ring->trbs[0].control = cpu_to_le32(TRB_CYCLE | + TRB_TYPE(TRB_NORMAL)); + ring->trbs[1].buffer = cpu_to_le32(TRB_BUFFER(dma_addr)); + ring->trbs[1].length = cpu_to_le32(TRB_LEN(0)); + ring->trbs[1].control = cpu_to_le32(TRB_CYCLE | TRB_IOC | + TRB_TYPE(TRB_NORMAL)); + } else { + ring->trbs[0].control = cpu_to_le32(TRB_CYCLE | TRB_IOC | + TRB_TYPE(TRB_NORMAL)); + ring->trbs[1].control = 0; + } + + trace_cdns2_queue_trb(pep, ring->trbs); + + if (!pep->dir) + writel(0, &pdev->ep0_regs->rxbc); + + cdns2_select_ep(pdev, pep->dir); + + writel(DMA_EP_STS_TRBERR, ®s->ep_sts); + writel(pep->ring.dma, ®s->ep_traddr); + + trace_cdns2_doorbell_ep0(pep, readl(®s->ep_traddr)); + + writel(DMA_EP_CMD_DRDY, ®s->ep_cmd); +} + +static int cdns2_ep0_delegate_req(struct cdns2_device *pdev) +{ + int ret; + + spin_unlock(&pdev->lock); + ret = pdev->gadget_driver->setup(&pdev->gadget, &pdev->setup); + spin_lock(&pdev->lock); + + return ret; +} + +static void cdns2_ep0_stall(struct cdns2_device *pdev) +{ + struct cdns2_endpoint *pep = &pdev->eps[0]; + struct cdns2_request *preq; + + preq = cdns2_next_preq(&pep->pending_list); + set_reg_bit_8(&pdev->ep0_regs->cs, EP0CS_DSTALL); + + if (pdev->ep0_stage == CDNS2_DATA_STAGE && preq) + cdns2_gadget_giveback(pep, preq, -ECONNRESET); + else if (preq) + list_del_init(&preq->list); + + pdev->ep0_stage = CDNS2_SETUP_STAGE; + pep->ep_state |= EP_STALLED; +} + +static void cdns2_status_stage(struct cdns2_device *pdev) +{ + struct cdns2_endpoint *pep = &pdev->eps[0]; + struct cdns2_request *preq; + + preq = cdns2_next_preq(&pep->pending_list); + if (preq) + list_del_init(&preq->list); + + pdev->ep0_stage = CDNS2_SETUP_STAGE; + writeb(EP0CS_HSNAK, &pdev->ep0_regs->cs); +} + +static int cdns2_req_ep0_set_configuration(struct cdns2_device *pdev, + struct usb_ctrlrequest *ctrl_req) +{ + enum usb_device_state state = pdev->gadget.state; + u32 config = le16_to_cpu(ctrl_req->wValue); + int ret; + + if (state < USB_STATE_ADDRESS) { + dev_err(pdev->dev, "Set Configuration - bad device state\n"); + return -EINVAL; + } + + ret = cdns2_ep0_delegate_req(pdev); + if (ret) + return ret; + + trace_cdns2_device_state(config ? "configured" : "addressed"); + + if (!config) + usb_gadget_set_state(&pdev->gadget, USB_STATE_ADDRESS); + + return 0; +} + +static int cdns2_req_ep0_set_address(struct cdns2_device *pdev, u32 addr) +{ + enum usb_device_state device_state = pdev->gadget.state; + u8 reg; + + if (addr > USB_DEVICE_MAX_ADDRESS) { + dev_err(pdev->dev, + "Device address (%d) cannot be greater than %d\n", + addr, USB_DEVICE_MAX_ADDRESS); + return -EINVAL; + } + + if (device_state == USB_STATE_CONFIGURED) { + dev_err(pdev->dev, + "can't set_address from configured state\n"); + return -EINVAL; + } + + reg = readb(&pdev->usb_regs->fnaddr); + pdev->dev_address = reg; + + usb_gadget_set_state(&pdev->gadget, + (addr ? USB_STATE_ADDRESS : USB_STATE_DEFAULT)); + + trace_cdns2_device_state(addr ? "addressed" : "default"); + + return 0; +} + +static int cdns2_req_ep0_handle_status(struct cdns2_device *pdev, + struct usb_ctrlrequest *ctrl) +{ + struct cdns2_endpoint *pep; + __le16 *response_pkt; + u16 status = 0; + int ep_sts; + u32 recip; + + recip = ctrl->bRequestType & USB_RECIP_MASK; + + switch (recip) { + case USB_RECIP_DEVICE: + status = pdev->gadget.is_selfpowered; + status |= pdev->may_wakeup << USB_DEVICE_REMOTE_WAKEUP; + break; + case USB_RECIP_INTERFACE: + return cdns2_ep0_delegate_req(pdev); + case USB_RECIP_ENDPOINT: + ep_sts = cdns2_w_index_to_ep_index(le16_to_cpu(ctrl->wIndex)); + pep = &pdev->eps[ep_sts]; + + if (pep->ep_state & EP_STALLED) + status = BIT(USB_ENDPOINT_HALT); + break; + default: + return -EINVAL; + } + + put_unaligned_le16(status, (__le16 *)pdev->ep0_preq.request.buf); + + cdns2_ep0_enqueue(pdev, pdev->ep0_preq.request.dma, + sizeof(*response_pkt), 0); + + return 0; +} + +static int cdns2_ep0_handle_feature_device(struct cdns2_device *pdev, + struct usb_ctrlrequest *ctrl, + int set) +{ + enum usb_device_state state; + enum usb_device_speed speed; + int ret = 0; + u32 wValue; + u16 tmode; + + wValue = le16_to_cpu(ctrl->wValue); + state = pdev->gadget.state; + speed = pdev->gadget.speed; + + switch (wValue) { + case USB_DEVICE_REMOTE_WAKEUP: + pdev->may_wakeup = !!set; + break; + case USB_DEVICE_TEST_MODE: + if (state != USB_STATE_CONFIGURED || speed > USB_SPEED_HIGH) + return -EINVAL; + + tmode = le16_to_cpu(ctrl->wIndex); + + if (!set || (tmode & 0xff) != 0) + return -EINVAL; + + tmode >>= 8; + switch (tmode) { + case USB_TEST_J: + case USB_TEST_K: + case USB_TEST_SE0_NAK: + case USB_TEST_PACKET: + /* + * The USBHS controller automatically handles the + * Set_Feature(testmode) request. Standard test modes + * that use values of test mode selector from + * 01h to 04h (Test_J, Test_K, Test_SE0_NAK, + * Test_Packet) are supported by the + * controller(HS - ack, FS - stall). + */ + break; + default: + ret = -EINVAL; + } + break; + default: + ret = -EINVAL; + } + + return ret; +} + +static int cdns2_ep0_handle_feature_intf(struct cdns2_device *pdev, + struct usb_ctrlrequest *ctrl, + int set) +{ + int ret = 0; + u32 wValue; + + wValue = le16_to_cpu(ctrl->wValue); + + switch (wValue) { + case USB_INTRF_FUNC_SUSPEND: + break; + default: + ret = -EINVAL; + } + + return ret; +} + +static int cdns2_ep0_handle_feature_endpoint(struct cdns2_device *pdev, + struct usb_ctrlrequest *ctrl, + int set) +{ + struct cdns2_endpoint *pep; + u8 wValue; + + wValue = le16_to_cpu(ctrl->wValue); + pep = &pdev->eps[cdns2_w_index_to_ep_index(le16_to_cpu(ctrl->wIndex))]; + + if (wValue != USB_ENDPOINT_HALT) + return -EINVAL; + + if (!(le16_to_cpu(ctrl->wIndex) & ~USB_DIR_IN)) + return 0; + + switch (wValue) { + case USB_ENDPOINT_HALT: + if (set || !(pep->ep_state & EP_WEDGE)) + return cdns2_halt_endpoint(pdev, pep, set); + break; + default: + dev_warn(pdev->dev, "WARN Incorrect wValue %04x\n", wValue); + return -EINVAL; + } + + return 0; +} + +static int cdns2_req_ep0_handle_feature(struct cdns2_device *pdev, + struct usb_ctrlrequest *ctrl, + int set) +{ + switch (ctrl->bRequestType & USB_RECIP_MASK) { + case USB_RECIP_DEVICE: + return cdns2_ep0_handle_feature_device(pdev, ctrl, set); + case USB_RECIP_INTERFACE: + return cdns2_ep0_handle_feature_intf(pdev, ctrl, set); + case USB_RECIP_ENDPOINT: + return cdns2_ep0_handle_feature_endpoint(pdev, ctrl, set); + default: + return -EINVAL; + } +} + +static int cdns2_ep0_std_request(struct cdns2_device *pdev) +{ + struct usb_ctrlrequest *ctrl = &pdev->setup; + int ret; + + switch (ctrl->bRequest) { + case USB_REQ_SET_ADDRESS: + ret = cdns2_req_ep0_set_address(pdev, + le16_to_cpu(ctrl->wValue)); + break; + case USB_REQ_SET_CONFIGURATION: + ret = cdns2_req_ep0_set_configuration(pdev, ctrl); + break; + case USB_REQ_GET_STATUS: + ret = cdns2_req_ep0_handle_status(pdev, ctrl); + break; + case USB_REQ_CLEAR_FEATURE: + ret = cdns2_req_ep0_handle_feature(pdev, ctrl, 0); + break; + case USB_REQ_SET_FEATURE: + ret = cdns2_req_ep0_handle_feature(pdev, ctrl, 1); + break; + default: + ret = cdns2_ep0_delegate_req(pdev); + break; + } + + return ret; +} + +static void __pending_setup_status_handler(struct cdns2_device *pdev) +{ + struct usb_request *request = pdev->pending_status_request; + + if (pdev->status_completion_no_call && request && request->complete) { + request->complete(&pdev->eps[0].endpoint, request); + pdev->status_completion_no_call = 0; + } +} + +void cdns2_pending_setup_status_handler(struct work_struct *work) +{ + struct cdns2_device *pdev = container_of(work, struct cdns2_device, + pending_status_wq); + unsigned long flags; + + spin_lock_irqsave(&pdev->lock, flags); + __pending_setup_status_handler(pdev); + spin_unlock_irqrestore(&pdev->lock, flags); +} + +void cdns2_handle_setup_packet(struct cdns2_device *pdev) +{ + struct usb_ctrlrequest *ctrl = &pdev->setup; + struct cdns2_endpoint *pep = &pdev->eps[0]; + struct cdns2_request *preq; + int ret = 0; + u16 len; + u8 reg; + int i; + + writeb(EP0CS_CHGSET, &pdev->ep0_regs->cs); + + for (i = 0; i < 8; i++) + ((u8 *)&pdev->setup)[i] = readb(&pdev->ep0_regs->setupdat[i]); + + /* + * If SETUP packet was modified while reading just simple ignore it. + * The new one will be handled latter. + */ + if (cdns2_check_new_setup(pdev)) { + trace_cdns2_ep0_setup("overridden"); + return; + } + + trace_cdns2_ctrl_req(ctrl); + + if (!pdev->gadget_driver) + goto out; + + if (pdev->gadget.state == USB_STATE_NOTATTACHED) { + dev_err(pdev->dev, "ERR: Setup detected in unattached state\n"); + ret = -EINVAL; + goto out; + } + + pep = &pdev->eps[0]; + + /* Halt for Ep0 is cleared automatically when SETUP packet arrives. */ + pep->ep_state &= ~EP_STALLED; + + if (!list_empty(&pep->pending_list)) { + preq = cdns2_next_preq(&pep->pending_list); + cdns2_gadget_giveback(pep, preq, -ECONNRESET); + } + + len = le16_to_cpu(ctrl->wLength); + if (len) + pdev->ep0_stage = CDNS2_DATA_STAGE; + else + pdev->ep0_stage = CDNS2_STATUS_STAGE; + + pep->dir = ctrl->bRequestType & USB_DIR_IN; + + /* + * SET_ADDRESS request is acknowledged automatically by controller and + * in the worse case driver may not notice this request. To check + * whether this request has been processed driver can use + * fnaddr register. + */ + reg = readb(&pdev->usb_regs->fnaddr); + if (pdev->setup.bRequest != USB_REQ_SET_ADDRESS && + pdev->dev_address != reg) + cdns2_req_ep0_set_address(pdev, reg); + + if ((ctrl->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) + ret = cdns2_ep0_std_request(pdev); + else + ret = cdns2_ep0_delegate_req(pdev); + + if (ret == USB_GADGET_DELAYED_STATUS) { + trace_cdns2_ep0_status_stage("delayed"); + return; + } + +out: + if (ret < 0) + cdns2_ep0_stall(pdev); + else if (pdev->ep0_stage == CDNS2_STATUS_STAGE) + cdns2_status_stage(pdev); +} + +static void cdns2_transfer_completed(struct cdns2_device *pdev) +{ + struct cdns2_endpoint *pep = &pdev->eps[0]; + + if (!list_empty(&pep->pending_list)) { + struct cdns2_request *preq; + + trace_cdns2_complete_trb(pep, pep->ring.trbs); + preq = cdns2_next_preq(&pep->pending_list); + + preq->request.actual = + TRB_LEN(le32_to_cpu(pep->ring.trbs->length)); + cdns2_gadget_giveback(pep, preq, 0); + } + + cdns2_status_stage(pdev); +} + +void cdns2_handle_ep0_interrupt(struct cdns2_device *pdev, int dir) +{ + u32 ep_sts_reg; + + cdns2_select_ep(pdev, dir); + + trace_cdns2_ep0_irq(pdev); + + ep_sts_reg = readl(&pdev->adma_regs->ep_sts); + writel(ep_sts_reg, &pdev->adma_regs->ep_sts); + + __pending_setup_status_handler(pdev); + + if ((ep_sts_reg & DMA_EP_STS_IOC) || (ep_sts_reg & DMA_EP_STS_ISP)) { + pdev->eps[0].dir = dir; + cdns2_transfer_completed(pdev); + } +} + +/* + * Function shouldn't be called by gadget driver, + * endpoint 0 is allways active. + */ +static int cdns2_gadget_ep0_enable(struct usb_ep *ep, + const struct usb_endpoint_descriptor *desc) +{ + return -EINVAL; +} + +/* + * Function shouldn't be called by gadget driver, + * endpoint 0 is allways active. + */ +static int cdns2_gadget_ep0_disable(struct usb_ep *ep) +{ + return -EINVAL; +} + +static int cdns2_gadget_ep0_set_halt(struct usb_ep *ep, int value) +{ + struct cdns2_endpoint *pep = ep_to_cdns2_ep(ep); + struct cdns2_device *pdev = pep->pdev; + unsigned long flags; + + if (!value) + return 0; + + spin_lock_irqsave(&pdev->lock, flags); + cdns2_ep0_stall(pdev); + spin_unlock_irqrestore(&pdev->lock, flags); + + return 0; +} + +static int cdns2_gadget_ep0_set_wedge(struct usb_ep *ep) +{ + return cdns2_gadget_ep0_set_halt(ep, 1); +} + +static int cdns2_gadget_ep0_queue(struct usb_ep *ep, + struct usb_request *request, + gfp_t gfp_flags) +{ + struct cdns2_endpoint *pep = ep_to_cdns2_ep(ep); + struct cdns2_device *pdev = pep->pdev; + struct cdns2_request *preq; + unsigned long flags; + u8 zlp = 0; + int ret; + + spin_lock_irqsave(&pdev->lock, flags); + + preq = to_cdns2_request(request); + + trace_cdns2_request_enqueue(preq); + + /* Cancel the request if controller receive new SETUP packet. */ + if (cdns2_check_new_setup(pdev)) { + trace_cdns2_ep0_setup("overridden"); + spin_unlock_irqrestore(&pdev->lock, flags); + return -ECONNRESET; + } + + /* Send STATUS stage. Should be called only for SET_CONFIGURATION. */ + if (pdev->ep0_stage == CDNS2_STATUS_STAGE) { + cdns2_status_stage(pdev); + + request->actual = 0; + pdev->status_completion_no_call = true; + pdev->pending_status_request = request; + usb_gadget_set_state(&pdev->gadget, USB_STATE_CONFIGURED); + spin_unlock_irqrestore(&pdev->lock, flags); + + /* + * Since there is no completion interrupt for status stage, + * it needs to call ->completion in software after + * cdns2_gadget_ep0_queue is back. + */ + queue_work(system_freezable_wq, &pdev->pending_status_wq); + return 0; + } + + if (!list_empty(&pep->pending_list)) { + trace_cdns2_ep0_setup("pending"); + dev_err(pdev->dev, + "can't handle multiple requests for ep0\n"); + spin_unlock_irqrestore(&pdev->lock, flags); + return -EBUSY; + } + + ret = usb_gadget_map_request_by_dev(pdev->dev, request, pep->dir); + if (ret) { + spin_unlock_irqrestore(&pdev->lock, flags); + dev_err(pdev->dev, "failed to map request\n"); + return -EINVAL; + } + + request->status = -EINPROGRESS; + list_add_tail(&preq->list, &pep->pending_list); + + if (request->zero && request->length && + (request->length % ep->maxpacket == 0)) + zlp = 1; + + cdns2_ep0_enqueue(pdev, request->dma, request->length, zlp); + + spin_unlock_irqrestore(&pdev->lock, flags); + + return 0; +} + +static const struct usb_ep_ops cdns2_gadget_ep0_ops = { + .enable = cdns2_gadget_ep0_enable, + .disable = cdns2_gadget_ep0_disable, + .alloc_request = cdns2_gadget_ep_alloc_request, + .free_request = cdns2_gadget_ep_free_request, + .queue = cdns2_gadget_ep0_queue, + .dequeue = cdns2_gadget_ep_dequeue, + .set_halt = cdns2_gadget_ep0_set_halt, + .set_wedge = cdns2_gadget_ep0_set_wedge, +}; + +void cdns2_ep0_config(struct cdns2_device *pdev) +{ + struct cdns2_endpoint *pep; + + pep = &pdev->eps[0]; + + if (!list_empty(&pep->pending_list)) { + struct cdns2_request *preq; + + preq = cdns2_next_preq(&pep->pending_list); + list_del_init(&preq->list); + } + + writeb(EP0_FIFO_AUTO, &pdev->ep0_regs->fifo); + cdns2_select_ep(pdev, USB_DIR_OUT); + writel(DMA_EP_CFG_ENABLE, &pdev->adma_regs->ep_cfg); + + writeb(EP0_FIFO_IO_TX | EP0_FIFO_AUTO, &pdev->ep0_regs->fifo); + cdns2_select_ep(pdev, USB_DIR_IN); + writel(DMA_EP_CFG_ENABLE, &pdev->adma_regs->ep_cfg); + + writeb(pdev->gadget.ep0->maxpacket, &pdev->ep0_regs->maxpack); + writel(DMA_EP_IEN_EP_OUT0 | DMA_EP_IEN_EP_IN0, + &pdev->adma_regs->ep_ien); +} + +void cdns2_init_ep0(struct cdns2_device *pdev, + struct cdns2_endpoint *pep) +{ + u16 maxpacket = le16_to_cpu(cdns2_gadget_ep0_desc.wMaxPacketSize); + + usb_ep_set_maxpacket_limit(&pep->endpoint, maxpacket); + + pep->endpoint.ops = &cdns2_gadget_ep0_ops; + pep->endpoint.desc = &cdns2_gadget_ep0_desc; + pep->endpoint.caps.type_control = true; + pep->endpoint.caps.dir_in = true; + pep->endpoint.caps.dir_out = true; + + pdev->gadget.ep0 = &pep->endpoint; +} diff --git a/drivers/usb/gadget/udc/cdns2/cdns2-gadget.c b/drivers/usb/gadget/udc/cdns2/cdns2-gadget.c new file mode 100644 index 0000000000000000000000000000000000000000..0eed0e03842cff7a13320f1d4135f82b59f6daff --- /dev/null +++ b/drivers/usb/gadget/udc/cdns2/cdns2-gadget.c @@ -0,0 +1,2474 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Cadence USBHS-DEV Driver - gadget side. + * + * Copyright (C) 2023 Cadence Design Systems. + * + * Authors: Pawel Laszczak + */ + +/* + * Work around 1: + * At some situations, the controller may get stale data address in TRB + * at below sequences: + * 1. Controller read TRB includes data address + * 2. Software updates TRBs includes data address and Cycle bit + * 3. Controller read TRB which includes Cycle bit + * 4. DMA run with stale data address + * + * To fix this problem, driver needs to make the first TRB in TD as invalid. + * After preparing all TRBs driver needs to check the position of DMA and + * if the DMA point to the first just added TRB and doorbell is 1, + * then driver must defer making this TRB as valid. This TRB will be make + * as valid during adding next TRB only if DMA is stopped or at TRBERR + * interrupt. + * + */ + +#include +#include +#include +#include +#include +#include + +#include "cdns2-gadget.h" +#include "cdns2-trace.h" + +/** + * set_reg_bit_32 - set bit in given 32 bits register. + * @ptr: register address. + * @mask: bits to set. + */ +static void set_reg_bit_32(void __iomem *ptr, u32 mask) +{ + mask = readl(ptr) | mask; + writel(mask, ptr); +} + +/* + * clear_reg_bit_32 - clear bit in given 32 bits register. + * @ptr: register address. + * @mask: bits to clear. + */ +static void clear_reg_bit_32(void __iomem *ptr, u32 mask) +{ + mask = readl(ptr) & ~mask; + writel(mask, ptr); +} + +/* Clear bit in given 8 bits register. */ +static void clear_reg_bit_8(void __iomem *ptr, u8 mask) +{ + mask = readb(ptr) & ~mask; + writeb(mask, ptr); +} + +/* Set bit in given 16 bits register. */ +void set_reg_bit_8(void __iomem *ptr, u8 mask) +{ + mask = readb(ptr) | mask; + writeb(mask, ptr); +} + +static int cdns2_get_dma_pos(struct cdns2_device *pdev, + struct cdns2_endpoint *pep) +{ + int dma_index; + + dma_index = readl(&pdev->adma_regs->ep_traddr) - pep->ring.dma; + + return dma_index / TRB_SIZE; +} + +/* Get next private request from list. */ +struct cdns2_request *cdns2_next_preq(struct list_head *list) +{ + return list_first_entry_or_null(list, struct cdns2_request, list); +} + +void cdns2_select_ep(struct cdns2_device *pdev, u32 ep) +{ + if (pdev->selected_ep == ep) + return; + + pdev->selected_ep = ep; + writel(ep, &pdev->adma_regs->ep_sel); +} + +dma_addr_t cdns2_trb_virt_to_dma(struct cdns2_endpoint *pep, + struct cdns2_trb *trb) +{ + u32 offset = (char *)trb - (char *)pep->ring.trbs; + + return pep->ring.dma + offset; +} + +static void cdns2_free_tr_segment(struct cdns2_endpoint *pep) +{ + struct cdns2_device *pdev = pep->pdev; + struct cdns2_ring *ring = &pep->ring; + + if (pep->ring.trbs) { + dma_pool_free(pdev->eps_dma_pool, ring->trbs, ring->dma); + memset(ring, 0, sizeof(*ring)); + } +} + +/* Allocates Transfer Ring segment. */ +static int cdns2_alloc_tr_segment(struct cdns2_endpoint *pep) +{ + struct cdns2_device *pdev = pep->pdev; + struct cdns2_trb *link_trb; + struct cdns2_ring *ring; + + ring = &pep->ring; + + if (!ring->trbs) { + ring->trbs = dma_pool_alloc(pdev->eps_dma_pool, + GFP_DMA32 | GFP_ATOMIC, + &ring->dma); + if (!ring->trbs) + return -ENOMEM; + } + + memset(ring->trbs, 0, TR_SEG_SIZE); + + if (!pep->num) + return 0; + + /* Initialize the last TRB as Link TRB */ + link_trb = (ring->trbs + (TRBS_PER_SEGMENT - 1)); + link_trb->buffer = cpu_to_le32(TRB_BUFFER(ring->dma)); + link_trb->control = cpu_to_le32(TRB_CYCLE | TRB_TYPE(TRB_LINK) | + TRB_TOGGLE); + + return 0; +} + +/* + * Stalls and flushes selected endpoint. + * Endpoint must be selected before invoking this function. + */ +static void cdns2_ep_stall_flush(struct cdns2_endpoint *pep) +{ + struct cdns2_device *pdev = pep->pdev; + int val; + + trace_cdns2_ep_halt(pep, 1, 1); + + writel(DMA_EP_CMD_DFLUSH, &pdev->adma_regs->ep_cmd); + + /* Wait for DFLUSH cleared. */ + readl_poll_timeout_atomic(&pdev->adma_regs->ep_cmd, val, + !(val & DMA_EP_CMD_DFLUSH), 1, 1000); + pep->ep_state |= EP_STALLED; + pep->ep_state &= ~EP_STALL_PENDING; +} + +/* + * Increment a trb index. + * + * The index should never point to the last link TRB in TR. After incrementing, + * if it point to the link TRB, wrap around to the beginning and revert + * cycle state bit. The link TRB is always at the last TRB entry. + */ +static void cdns2_ep_inc_trb(int *index, u8 *cs, int trb_in_seg) +{ + (*index)++; + if (*index == (trb_in_seg - 1)) { + *index = 0; + *cs ^= 1; + } +} + +static void cdns2_ep_inc_enq(struct cdns2_ring *ring) +{ + ring->free_trbs--; + cdns2_ep_inc_trb(&ring->enqueue, &ring->pcs, TRBS_PER_SEGMENT); +} + +static void cdns2_ep_inc_deq(struct cdns2_ring *ring) +{ + ring->free_trbs++; + cdns2_ep_inc_trb(&ring->dequeue, &ring->ccs, TRBS_PER_SEGMENT); +} + +/* + * Enable/disable LPM. + * + * If bit USBCS_LPMNYET is not set and device receive Extended Token packet, + * then controller answer with ACK handshake. + * If bit USBCS_LPMNYET is set and device receive Extended Token packet, + * then controller answer with NYET handshake. + */ +static void cdns2_enable_l1(struct cdns2_device *pdev, int enable) +{ + if (enable) { + clear_reg_bit_8(&pdev->usb_regs->usbcs, USBCS_LPMNYET); + writeb(LPMCLOCK_SLEEP_ENTRY, &pdev->usb_regs->lpmclock); + } else { + set_reg_bit_8(&pdev->usb_regs->usbcs, USBCS_LPMNYET); + } +} + +static enum usb_device_speed cdns2_get_speed(struct cdns2_device *pdev) +{ + u8 speed = readb(&pdev->usb_regs->speedctrl); + + if (speed & SPEEDCTRL_HS) + return USB_SPEED_HIGH; + else if (speed & SPEEDCTRL_FS) + return USB_SPEED_FULL; + + return USB_SPEED_UNKNOWN; +} + +static struct cdns2_trb *cdns2_next_trb(struct cdns2_endpoint *pep, + struct cdns2_trb *trb) +{ + if (trb == (pep->ring.trbs + (TRBS_PER_SEGMENT - 1))) + return pep->ring.trbs; + else + return ++trb; +} + +void cdns2_gadget_giveback(struct cdns2_endpoint *pep, + struct cdns2_request *preq, + int status) +{ + struct usb_request *request = &preq->request; + struct cdns2_device *pdev = pep->pdev; + + list_del_init(&preq->list); + + if (request->status == -EINPROGRESS) + request->status = status; + + usb_gadget_unmap_request_by_dev(pdev->dev, request, pep->dir); + + /* All TRBs have finished, clear the counter. */ + preq->finished_trb = 0; + + trace_cdns2_request_giveback(preq); + + if (request->complete) { + spin_unlock(&pdev->lock); + usb_gadget_giveback_request(&pep->endpoint, request); + spin_lock(&pdev->lock); + } + + if (request->buf == pdev->zlp_buf) + cdns2_gadget_ep_free_request(&pep->endpoint, request); +} + +static void cdns2_wa1_restore_cycle_bit(struct cdns2_endpoint *pep) +{ + /* Work around for stale data address in TRB. */ + if (pep->wa1_set) { + trace_cdns2_wa1(pep, "restore cycle bit"); + + pep->wa1_set = 0; + pep->wa1_trb_index = 0xFFFF; + if (pep->wa1_cycle_bit) + pep->wa1_trb->control |= cpu_to_le32(0x1); + else + pep->wa1_trb->control &= cpu_to_le32(~0x1); + } +} + +static int cdns2_wa1_update_guard(struct cdns2_endpoint *pep, + struct cdns2_trb *trb) +{ + struct cdns2_device *pdev = pep->pdev; + + if (!pep->wa1_set) { + u32 doorbell; + + doorbell = !!(readl(&pdev->adma_regs->ep_cmd) & DMA_EP_CMD_DRDY); + + if (doorbell) { + pep->wa1_cycle_bit = pep->ring.pcs ? TRB_CYCLE : 0; + pep->wa1_set = 1; + pep->wa1_trb = trb; + pep->wa1_trb_index = pep->ring.enqueue; + trace_cdns2_wa1(pep, "set guard"); + return 0; + } + } + return 1; +} + +static void cdns2_wa1_tray_restore_cycle_bit(struct cdns2_device *pdev, + struct cdns2_endpoint *pep) +{ + int dma_index; + u32 doorbell; + + doorbell = !!(readl(&pdev->adma_regs->ep_cmd) & DMA_EP_CMD_DRDY); + dma_index = cdns2_get_dma_pos(pdev, pep); + + if (!doorbell || dma_index != pep->wa1_trb_index) + cdns2_wa1_restore_cycle_bit(pep); +} + +static int cdns2_prepare_ring(struct cdns2_device *pdev, + struct cdns2_endpoint *pep, + int num_trbs) +{ + struct cdns2_trb *link_trb = NULL; + int doorbell, dma_index; + struct cdns2_ring *ring; + u32 ch_bit = 0; + + ring = &pep->ring; + + if (num_trbs > ring->free_trbs) { + pep->ep_state |= EP_RING_FULL; + trace_cdns2_no_room_on_ring("Ring full\n"); + return -ENOBUFS; + } + + if ((ring->enqueue + num_trbs) >= (TRBS_PER_SEGMENT - 1)) { + doorbell = !!(readl(&pdev->adma_regs->ep_cmd) & DMA_EP_CMD_DRDY); + dma_index = cdns2_get_dma_pos(pdev, pep); + + /* Driver can't update LINK TRB if it is current processed. */ + if (doorbell && dma_index == TRBS_PER_SEGMENT - 1) { + pep->ep_state |= EP_DEFERRED_DRDY; + return -ENOBUFS; + } + + /* Update C bt in Link TRB before starting DMA. */ + link_trb = ring->trbs + (TRBS_PER_SEGMENT - 1); + + /* + * For TRs size equal 2 enabling TRB_CHAIN for epXin causes + * that DMA stuck at the LINK TRB. + * On the other hand, removing TRB_CHAIN for longer TRs for + * epXout cause that DMA stuck after handling LINK TRB. + * To eliminate this strange behavioral driver set TRB_CHAIN + * bit only for TR size > 2. + */ + if (pep->type == USB_ENDPOINT_XFER_ISOC || TRBS_PER_SEGMENT > 2) + ch_bit = TRB_CHAIN; + + link_trb->control = cpu_to_le32(((ring->pcs) ? TRB_CYCLE : 0) | + TRB_TYPE(TRB_LINK) | TRB_TOGGLE | ch_bit); + } + + return 0; +} + +static void cdns2_dbg_request_trbs(struct cdns2_endpoint *pep, + struct cdns2_request *preq) +{ + struct cdns2_trb *link_trb = pep->ring.trbs + (TRBS_PER_SEGMENT - 1); + struct cdns2_trb *trb = preq->trb; + int num_trbs = preq->num_of_trb; + int i = 0; + + while (i < num_trbs) { + trace_cdns2_queue_trb(pep, trb + i); + if (trb + i == link_trb) { + trb = pep->ring.trbs; + num_trbs = num_trbs - i; + i = 0; + } else { + i++; + } + } +} + +static unsigned int cdns2_count_trbs(struct cdns2_endpoint *pep, + u64 addr, u64 len) +{ + unsigned int num_trbs = 1; + + if (pep->type == USB_ENDPOINT_XFER_ISOC) { + /* + * To speed up DMA performance address should not exceed 4KB. + * for high bandwidth transfer and driver will split + * such buffer into two TRBs. + */ + num_trbs = DIV_ROUND_UP(len + + (addr & (TRB_MAX_ISO_BUFF_SIZE - 1)), + TRB_MAX_ISO_BUFF_SIZE); + + if (pep->interval > 1) + num_trbs = pep->dir ? num_trbs * pep->interval : 1; + } else if (pep->dir) { + /* + * One extra link trb for IN direction. + * Sometimes DMA doesn't want advance to next TD and transfer + * hangs. This extra Link TRB force DMA to advance to next TD. + */ + num_trbs++; + } + + return num_trbs; +} + +static unsigned int cdns2_count_sg_trbs(struct cdns2_endpoint *pep, + struct usb_request *req) +{ + unsigned int i, len, full_len, num_trbs = 0; + struct scatterlist *sg; + int trb_len = 0; + + full_len = req->length; + + for_each_sg(req->sg, sg, req->num_sgs, i) { + len = sg_dma_len(sg); + num_trbs += cdns2_count_trbs(pep, sg_dma_address(sg), len); + len = min(len, full_len); + + /* + * For HS ISO transfer TRBs should not exceed max packet size. + * When DMA is working, and data exceed max packet size then + * some data will be read in single mode instead burst mode. + * This behavior will drastically reduce the copying speed. + * To avoid this we need one or two extra TRBs. + * This issue occurs for UVC class with sg_supported = 1 + * because buffers addresses are not aligned to 1024. + */ + if (pep->type == USB_ENDPOINT_XFER_ISOC) { + u8 temp; + + trb_len += len; + temp = trb_len >> 10; + + if (temp) { + if (trb_len % 1024) + num_trbs = num_trbs + temp; + else + num_trbs = num_trbs + temp - 1; + + trb_len = trb_len - (temp << 10); + } + } + + full_len -= len; + if (full_len == 0) + break; + } + + return num_trbs; +} + +/* + * Function prepares the array with optimized AXI burst value for different + * transfer lengths. Controller handles the final data which are less + * then AXI burst size as single byte transactions. + * e.g.: + * Let's assume that driver prepares trb with trb->length 700 and burst size + * will be set to 128. In this case the controller will handle a first 512 as + * single AXI transaction but the next 188 bytes will be handled + * as 47 separate AXI transaction. + * The better solution is to use the burst size equal 16 and then we will + * have only 25 AXI transaction (10 * 64 + 15 *4). + */ +static void cdsn2_isoc_burst_opt(struct cdns2_device *pdev) +{ + int axi_burst_option[] = {1, 2, 4, 8, 16, 32, 64, 128}; + int best_burst; + int array_size; + int opt_burst; + int trb_size; + int i, j; + + array_size = ARRAY_SIZE(axi_burst_option); + + for (i = 0; i <= MAX_ISO_SIZE; i++) { + trb_size = i / 4; + best_burst = trb_size ? trb_size : 1; + + for (j = 0; j < array_size; j++) { + opt_burst = trb_size / axi_burst_option[j]; + opt_burst += trb_size % axi_burst_option[j]; + + if (opt_burst < best_burst) { + best_burst = opt_burst; + pdev->burst_opt[i] = axi_burst_option[j]; + } + } + } +} + +static void cdns2_ep_tx_isoc(struct cdns2_endpoint *pep, + struct cdns2_request *preq, + int num_trbs) +{ + struct scatterlist *sg = NULL; + u32 remaining_packet_size = 0; + struct cdns2_trb *trb; + bool first_trb = true; + dma_addr_t trb_dma; + u32 trb_buff_len; + u32 block_length; + int td_idx = 0; + int split_size; + u32 full_len; + int enqd_len; + int sent_len; + int sg_iter; + u32 control; + int num_tds; + u32 length; + + /* + * For OUT direction 1 TD per interval is enough + * because TRBs are not dumped by controller. + */ + num_tds = pep->dir ? pep->interval : 1; + split_size = preq->request.num_sgs ? 1024 : 3072; + + for (td_idx = 0; td_idx < num_tds; td_idx++) { + if (preq->request.num_sgs) { + sg = preq->request.sg; + trb_dma = sg_dma_address(sg); + block_length = sg_dma_len(sg); + } else { + trb_dma = preq->request.dma; + block_length = preq->request.length; + } + + full_len = preq->request.length; + sg_iter = preq->request.num_sgs ? preq->request.num_sgs : 1; + remaining_packet_size = split_size; + + for (enqd_len = 0; enqd_len < full_len; + enqd_len += trb_buff_len) { + if (remaining_packet_size == 0) + remaining_packet_size = split_size; + + /* + * Calculate TRB length.- buffer can't across 4KB + * and max packet size. + */ + trb_buff_len = TRB_BUFF_LEN_UP_TO_BOUNDARY(trb_dma); + trb_buff_len = min(trb_buff_len, remaining_packet_size); + trb_buff_len = min(trb_buff_len, block_length); + + if (trb_buff_len > full_len - enqd_len) + trb_buff_len = full_len - enqd_len; + + control = TRB_TYPE(TRB_NORMAL); + + /* + * For IN direction driver has to set the IOC for + * last TRB in last TD. + * For OUT direction driver must set IOC and ISP + * only for last TRB in each TDs. + */ + if (enqd_len + trb_buff_len >= full_len || !pep->dir) + control |= TRB_IOC | TRB_ISP; + + /* + * Don't give the first TRB to the hardware (by toggling + * the cycle bit) until we've finished creating all the + * other TRBs. + */ + if (first_trb) { + first_trb = false; + if (pep->ring.pcs == 0) + control |= TRB_CYCLE; + } else { + control |= pep->ring.pcs; + } + + if (enqd_len + trb_buff_len < full_len) + control |= TRB_CHAIN; + + length = TRB_LEN(trb_buff_len) | + TRB_BURST(pep->pdev->burst_opt[trb_buff_len]); + + trb = pep->ring.trbs + pep->ring.enqueue; + trb->buffer = cpu_to_le32(TRB_BUFFER(trb_dma)); + trb->length = cpu_to_le32(length); + trb->control = cpu_to_le32(control); + + trb_dma += trb_buff_len; + sent_len = trb_buff_len; + + if (sg && sent_len >= block_length) { + /* New sg entry */ + --sg_iter; + sent_len -= block_length; + if (sg_iter != 0) { + sg = sg_next(sg); + trb_dma = sg_dma_address(sg); + block_length = sg_dma_len(sg); + } + } + + remaining_packet_size -= trb_buff_len; + block_length -= sent_len; + preq->end_trb = pep->ring.enqueue; + + cdns2_ep_inc_enq(&pep->ring); + } + } +} + +static void cdns2_ep_tx_bulk(struct cdns2_endpoint *pep, + struct cdns2_request *preq, + int trbs_per_td) +{ + struct scatterlist *sg = NULL; + struct cdns2_ring *ring; + struct cdns2_trb *trb; + dma_addr_t trb_dma; + int sg_iter = 0; + u32 control; + u32 length; + + if (preq->request.num_sgs) { + sg = preq->request.sg; + trb_dma = sg_dma_address(sg); + length = sg_dma_len(sg); + } else { + trb_dma = preq->request.dma; + length = preq->request.length; + } + + ring = &pep->ring; + + for (sg_iter = 0; sg_iter < trbs_per_td; sg_iter++) { + control = TRB_TYPE(TRB_NORMAL) | ring->pcs | TRB_ISP; + trb = pep->ring.trbs + ring->enqueue; + + if (pep->dir && sg_iter == trbs_per_td - 1) { + preq->end_trb = ring->enqueue; + control = ring->pcs | TRB_TYPE(TRB_LINK) | TRB_CHAIN + | TRB_IOC; + cdns2_ep_inc_enq(&pep->ring); + + if (ring->enqueue == 0) + control |= TRB_TOGGLE; + + /* Point to next bad TRB. */ + trb->buffer = cpu_to_le32(pep->ring.dma + + (ring->enqueue * TRB_SIZE)); + trb->length = 0; + trb->control = cpu_to_le32(control); + break; + } + + /* + * Don't give the first TRB to the hardware (by toggling + * the cycle bit) until we've finished creating all the + * other TRBs. + */ + if (sg_iter == 0) + control = control ^ TRB_CYCLE; + + /* For last TRB in TD. */ + if (sg_iter == (trbs_per_td - (pep->dir ? 2 : 1))) + control |= TRB_IOC; + else + control |= TRB_CHAIN; + + trb->buffer = cpu_to_le32(trb_dma); + trb->length = cpu_to_le32(TRB_BURST(pep->trb_burst_size) | + TRB_LEN(length)); + trb->control = cpu_to_le32(control); + + if (sg && sg_iter < (trbs_per_td - 1)) { + sg = sg_next(sg); + trb_dma = sg_dma_address(sg); + length = sg_dma_len(sg); + } + + preq->end_trb = ring->enqueue; + cdns2_ep_inc_enq(&pep->ring); + } +} + +static void cdns2_set_drdy(struct cdns2_device *pdev, + struct cdns2_endpoint *pep) +{ + trace_cdns2_ring(pep); + + /* + * Memory barrier - Cycle Bit must be set before doorbell. + */ + dma_wmb(); + + /* Clearing TRBERR and DESCMIS before setting DRDY. */ + writel(DMA_EP_STS_TRBERR | DMA_EP_STS_DESCMIS, + &pdev->adma_regs->ep_sts); + writel(DMA_EP_CMD_DRDY, &pdev->adma_regs->ep_cmd); + + if (readl(&pdev->adma_regs->ep_sts) & DMA_EP_STS_TRBERR) { + writel(DMA_EP_STS_TRBERR, &pdev->adma_regs->ep_sts); + writel(DMA_EP_CMD_DRDY, &pdev->adma_regs->ep_cmd); + } + + trace_cdns2_doorbell_epx(pep, readl(&pdev->adma_regs->ep_traddr)); +} + +static int cdns2_prepare_first_isoc_transfer(struct cdns2_device *pdev, + struct cdns2_endpoint *pep) +{ + struct cdns2_trb *trb; + u32 buffer; + u8 hw_ccs; + + if ((readl(&pdev->adma_regs->ep_cmd) & DMA_EP_CMD_DRDY)) + return -EBUSY; + + if (!pep->dir) { + set_reg_bit_32(&pdev->adma_regs->ep_cfg, DMA_EP_CFG_ENABLE); + writel(pep->ring.dma + pep->ring.dequeue, + &pdev->adma_regs->ep_traddr); + return 0; + } + + /* + * The first packet after doorbell can be corrupted so, + * driver prepares 0 length packet as first packet. + */ + buffer = pep->ring.dma + pep->ring.dequeue * TRB_SIZE; + hw_ccs = !!DMA_EP_STS_CCS(readl(&pdev->adma_regs->ep_sts)); + + trb = &pep->ring.trbs[TRBS_PER_SEGMENT]; + trb->length = 0; + trb->buffer = cpu_to_le32(TRB_BUFFER(buffer)); + trb->control = cpu_to_le32((hw_ccs ? TRB_CYCLE : 0) | TRB_TYPE(TRB_NORMAL)); + + /* + * LINK TRB is used to force updating cycle bit in controller and + * move to correct place in transfer ring. + */ + trb++; + trb->length = 0; + trb->buffer = cpu_to_le32(TRB_BUFFER(buffer)); + trb->control = cpu_to_le32((hw_ccs ? TRB_CYCLE : 0) | + TRB_TYPE(TRB_LINK) | TRB_CHAIN); + + if (hw_ccs != pep->ring.ccs) + trb->control |= cpu_to_le32(TRB_TOGGLE); + + set_reg_bit_32(&pdev->adma_regs->ep_cfg, DMA_EP_CFG_ENABLE); + writel(pep->ring.dma + (TRBS_PER_SEGMENT * TRB_SIZE), + &pdev->adma_regs->ep_traddr); + + return 0; +} + +/* Prepare and start transfer on no-default endpoint. */ +static int cdns2_ep_run_transfer(struct cdns2_endpoint *pep, + struct cdns2_request *preq) +{ + struct cdns2_device *pdev = pep->pdev; + struct cdns2_ring *ring; + u32 togle_pcs = 1; + int num_trbs; + int ret; + + cdns2_select_ep(pdev, pep->endpoint.address); + + if (preq->request.sg) + num_trbs = cdns2_count_sg_trbs(pep, &preq->request); + else + num_trbs = cdns2_count_trbs(pep, preq->request.dma, + preq->request.length); + + ret = cdns2_prepare_ring(pdev, pep, num_trbs); + if (ret) + return ret; + + ring = &pep->ring; + preq->start_trb = ring->enqueue; + preq->trb = ring->trbs + ring->enqueue; + + if (usb_endpoint_xfer_isoc(pep->endpoint.desc)) { + cdns2_ep_tx_isoc(pep, preq, num_trbs); + } else { + togle_pcs = cdns2_wa1_update_guard(pep, ring->trbs + ring->enqueue); + cdns2_ep_tx_bulk(pep, preq, num_trbs); + } + + preq->num_of_trb = num_trbs; + + /* + * Memory barrier - cycle bit must be set as the last operation. + */ + dma_wmb(); + + /* Give the TD to the consumer. */ + if (togle_pcs) + preq->trb->control = preq->trb->control ^ cpu_to_le32(1); + + cdns2_wa1_tray_restore_cycle_bit(pdev, pep); + cdns2_dbg_request_trbs(pep, preq); + + if (!pep->wa1_set && !(pep->ep_state & EP_STALLED) && !pep->skip) { + if (pep->type == USB_ENDPOINT_XFER_ISOC) { + ret = cdns2_prepare_first_isoc_transfer(pdev, pep); + if (ret) + return 0; + } + + cdns2_set_drdy(pdev, pep); + } + + return 0; +} + +/* Prepare and start transfer for all not started requests. */ +static int cdns2_start_all_request(struct cdns2_device *pdev, + struct cdns2_endpoint *pep) +{ + struct cdns2_request *preq; + int ret; + + while (!list_empty(&pep->deferred_list)) { + preq = cdns2_next_preq(&pep->deferred_list); + + ret = cdns2_ep_run_transfer(pep, preq); + if (ret) + return ret; + + list_move_tail(&preq->list, &pep->pending_list); + } + + pep->ep_state &= ~EP_RING_FULL; + + return 0; +} + +/* + * Check whether trb has been handled by DMA. + * + * Endpoint must be selected before invoking this function. + * + * Returns false if request has not been handled by DMA, else returns true. + * + * SR - start ring + * ER - end ring + * DQ = ring->dequeue - dequeue position + * EQ = ring->enqueue - enqueue position + * ST = preq->start_trb - index of first TRB in transfer ring + * ET = preq->end_trb - index of last TRB in transfer ring + * CI = current_index - index of processed TRB by DMA. + * + * As first step, we check if the TRB between the ST and ET. + * Then, we check if cycle bit for index pep->dequeue + * is correct. + * + * some rules: + * 1. ring->dequeue never equals to current_index. + * 2 ring->enqueue never exceed ring->dequeue + * 3. exception: ring->enqueue == ring->dequeue + * and ring->free_trbs is zero. + * This case indicate that TR is full. + * + * At below two cases, the request have been handled. + * Case 1 - ring->dequeue < current_index + * SR ... EQ ... DQ ... CI ... ER + * SR ... DQ ... CI ... EQ ... ER + * + * Case 2 - ring->dequeue > current_index + * This situation takes place when CI go through the LINK TRB at the end of + * transfer ring. + * SR ... CI ... EQ ... DQ ... ER + */ +static bool cdns2_trb_handled(struct cdns2_endpoint *pep, + struct cdns2_request *preq) +{ + struct cdns2_device *pdev = pep->pdev; + struct cdns2_ring *ring; + struct cdns2_trb *trb; + int current_index = 0; + int handled = 0; + int doorbell; + + ring = &pep->ring; + current_index = cdns2_get_dma_pos(pdev, pep); + doorbell = !!(readl(&pdev->adma_regs->ep_cmd) & DMA_EP_CMD_DRDY); + + /* + * Only ISO transfer can use 2 entries outside the standard + * Transfer Ring. First of them is used as zero length packet and the + * second as LINK TRB. + */ + if (current_index >= TRBS_PER_SEGMENT) + goto finish; + + /* Current trb doesn't belong to this request. */ + if (preq->start_trb < preq->end_trb) { + if (ring->dequeue > preq->end_trb) + goto finish; + + if (ring->dequeue < preq->start_trb) + goto finish; + } + + if (preq->start_trb > preq->end_trb && ring->dequeue > preq->end_trb && + ring->dequeue < preq->start_trb) + goto finish; + + if (preq->start_trb == preq->end_trb && ring->dequeue != preq->end_trb) + goto finish; + + trb = &ring->trbs[ring->dequeue]; + + if ((le32_to_cpu(trb->control) & TRB_CYCLE) != ring->ccs) + goto finish; + + if (doorbell == 1 && current_index == ring->dequeue) + goto finish; + + /* The corner case for TRBS_PER_SEGMENT equal 2). */ + if (TRBS_PER_SEGMENT == 2 && pep->type != USB_ENDPOINT_XFER_ISOC) { + handled = 1; + goto finish; + } + + if (ring->enqueue == ring->dequeue && + ring->free_trbs == 0) { + handled = 1; + } else if (ring->dequeue < current_index) { + if ((current_index == (TRBS_PER_SEGMENT - 1)) && + !ring->dequeue) + goto finish; + + handled = 1; + } else if (ring->dequeue > current_index) { + handled = 1; + } + +finish: + trace_cdns2_request_handled(preq, current_index, handled); + + return handled; +} + +static void cdns2_skip_isoc_td(struct cdns2_device *pdev, + struct cdns2_endpoint *pep, + struct cdns2_request *preq) +{ + struct cdns2_trb *trb; + int i; + + trb = pep->ring.trbs + pep->ring.dequeue; + + for (i = preq->finished_trb ; i < preq->num_of_trb; i++) { + preq->finished_trb++; + trace_cdns2_complete_trb(pep, trb); + cdns2_ep_inc_deq(&pep->ring); + trb = cdns2_next_trb(pep, trb); + } + + cdns2_gadget_giveback(pep, preq, 0); + cdns2_prepare_first_isoc_transfer(pdev, pep); + pep->skip = false; + cdns2_set_drdy(pdev, pep); +} + +static void cdns2_transfer_completed(struct cdns2_device *pdev, + struct cdns2_endpoint *pep) +{ + struct cdns2_request *preq = NULL; + bool request_handled = false; + struct cdns2_trb *trb; + + while (!list_empty(&pep->pending_list)) { + preq = cdns2_next_preq(&pep->pending_list); + trb = pep->ring.trbs + pep->ring.dequeue; + + /* + * The TRB was changed as link TRB, and the request + * was handled at ep_dequeue. + */ + while (TRB_FIELD_TO_TYPE(le32_to_cpu(trb->control)) == TRB_LINK && + le32_to_cpu(trb->length)) { + trace_cdns2_complete_trb(pep, trb); + cdns2_ep_inc_deq(&pep->ring); + trb = pep->ring.trbs + pep->ring.dequeue; + } + + /* + * Re-select endpoint. It could be changed by other CPU + * during handling usb_gadget_giveback_request. + */ + cdns2_select_ep(pdev, pep->endpoint.address); + + while (cdns2_trb_handled(pep, preq)) { + preq->finished_trb++; + + if (preq->finished_trb >= preq->num_of_trb) + request_handled = true; + + trb = pep->ring.trbs + pep->ring.dequeue; + trace_cdns2_complete_trb(pep, trb); + + if (pep->dir && pep->type == USB_ENDPOINT_XFER_ISOC) + /* + * For ISOC IN controller doens't update the + * trb->length. + */ + preq->request.actual = preq->request.length; + else + preq->request.actual += + TRB_LEN(le32_to_cpu(trb->length)); + + cdns2_ep_inc_deq(&pep->ring); + } + + if (request_handled) { + cdns2_gadget_giveback(pep, preq, 0); + request_handled = false; + } else { + goto prepare_next_td; + } + + if (pep->type != USB_ENDPOINT_XFER_ISOC && + TRBS_PER_SEGMENT == 2) + break; + } + +prepare_next_td: + if (pep->skip && preq) + cdns2_skip_isoc_td(pdev, pep, preq); + + if (!(pep->ep_state & EP_STALLED) && + !(pep->ep_state & EP_STALL_PENDING)) + cdns2_start_all_request(pdev, pep); +} + +static void cdns2_wakeup(struct cdns2_device *pdev) +{ + if (!pdev->may_wakeup) + return; + + /* Start driving resume signaling to indicate remote wakeup. */ + set_reg_bit_8(&pdev->usb_regs->usbcs, USBCS_SIGRSUME); +} + +static void cdns2_rearm_transfer(struct cdns2_endpoint *pep, u8 rearm) +{ + struct cdns2_device *pdev = pep->pdev; + + cdns2_wa1_restore_cycle_bit(pep); + + if (rearm) { + trace_cdns2_ring(pep); + + /* Cycle Bit must be updated before arming DMA. */ + dma_wmb(); + + writel(DMA_EP_CMD_DRDY, &pdev->adma_regs->ep_cmd); + + cdns2_wakeup(pdev); + + trace_cdns2_doorbell_epx(pep, + readl(&pdev->adma_regs->ep_traddr)); + } +} + +static void cdns2_handle_epx_interrupt(struct cdns2_endpoint *pep) +{ + struct cdns2_device *pdev = pep->pdev; + u8 isoerror = 0; + u32 ep_sts_reg; + u32 val; + + cdns2_select_ep(pdev, pep->endpoint.address); + + trace_cdns2_epx_irq(pdev, pep); + + ep_sts_reg = readl(&pdev->adma_regs->ep_sts); + writel(ep_sts_reg, &pdev->adma_regs->ep_sts); + + if (pep->type == USB_ENDPOINT_XFER_ISOC) { + u8 mult; + u8 cs; + + mult = USB_EP_MAXP_MULT(pep->endpoint.desc->wMaxPacketSize); + cs = pep->dir ? readb(&pdev->epx_regs->ep[pep->num - 1].txcs) : + readb(&pdev->epx_regs->ep[pep->num - 1].rxcs); + if (mult > 0) + isoerror = EPX_CS_ERR(cs); + } + + /* + * Sometimes ISO Error for mult=1 or mult=2 is not propagated on time + * from USB module to DMA module. To protect against this driver + * checks also the txcs/rxcs registers. + */ + if ((ep_sts_reg & DMA_EP_STS_ISOERR) || isoerror) { + clear_reg_bit_32(&pdev->adma_regs->ep_cfg, DMA_EP_CFG_ENABLE); + + /* Wait for DBUSY cleared. */ + readl_poll_timeout_atomic(&pdev->adma_regs->ep_sts, val, + !(val & DMA_EP_STS_DBUSY), 1, 125); + + writel(DMA_EP_CMD_DFLUSH, &pep->pdev->adma_regs->ep_cmd); + + /* Wait for DFLUSH cleared. */ + readl_poll_timeout_atomic(&pep->pdev->adma_regs->ep_cmd, val, + !(val & DMA_EP_CMD_DFLUSH), 1, 10); + + pep->skip = true; + } + + if (ep_sts_reg & DMA_EP_STS_TRBERR || pep->skip) { + if (pep->ep_state & EP_STALL_PENDING && + !(ep_sts_reg & DMA_EP_STS_DESCMIS)) + cdns2_ep_stall_flush(pep); + + /* + * For isochronous transfer driver completes request on + * IOC or on TRBERR. IOC appears only when device receive + * OUT data packet. If host disable stream or lost some packet + * then the only way to finish all queued transfer is to do it + * on TRBERR event. + */ + if (pep->type == USB_ENDPOINT_XFER_ISOC && !pep->wa1_set) { + if (!pep->dir) + clear_reg_bit_32(&pdev->adma_regs->ep_cfg, + DMA_EP_CFG_ENABLE); + + cdns2_transfer_completed(pdev, pep); + if (pep->ep_state & EP_DEFERRED_DRDY) { + pep->ep_state &= ~EP_DEFERRED_DRDY; + cdns2_set_drdy(pdev, pep); + } + + return; + } + + cdns2_transfer_completed(pdev, pep); + + if (!(pep->ep_state & EP_STALLED) && + !(pep->ep_state & EP_STALL_PENDING)) { + if (pep->ep_state & EP_DEFERRED_DRDY) { + pep->ep_state &= ~EP_DEFERRED_DRDY; + cdns2_start_all_request(pdev, pep); + } else { + cdns2_rearm_transfer(pep, pep->wa1_set); + } + } + + return; + } + + if ((ep_sts_reg & DMA_EP_STS_IOC) || (ep_sts_reg & DMA_EP_STS_ISP)) + cdns2_transfer_completed(pdev, pep); +} + +static void cdns2_disconnect_gadget(struct cdns2_device *pdev) +{ + if (pdev->gadget_driver && pdev->gadget_driver->disconnect) + pdev->gadget_driver->disconnect(&pdev->gadget); +} + +static irqreturn_t cdns2_usb_irq_handler(int irq, void *data) +{ + struct cdns2_device *pdev = data; + unsigned long reg_ep_ists; + u8 reg_usb_irq_m; + u8 reg_ext_irq_m; + u8 reg_usb_irq; + u8 reg_ext_irq; + + if (pdev->in_lpm) + return IRQ_NONE; + + reg_usb_irq_m = readb(&pdev->interrupt_regs->usbien); + reg_ext_irq_m = readb(&pdev->interrupt_regs->extien); + + /* Mask all sources of interrupt. */ + writeb(0, &pdev->interrupt_regs->usbien); + writeb(0, &pdev->interrupt_regs->extien); + writel(0, &pdev->adma_regs->ep_ien); + + /* Clear interrupt sources. */ + writel(0, &pdev->adma_regs->ep_sts); + writeb(0, &pdev->interrupt_regs->usbirq); + writeb(0, &pdev->interrupt_regs->extirq); + + reg_ep_ists = readl(&pdev->adma_regs->ep_ists); + reg_usb_irq = readb(&pdev->interrupt_regs->usbirq); + reg_ext_irq = readb(&pdev->interrupt_regs->extirq); + + if (reg_ep_ists || (reg_usb_irq & reg_usb_irq_m) || + (reg_ext_irq & reg_ext_irq_m)) + return IRQ_WAKE_THREAD; + + writeb(USB_IEN_INIT, &pdev->interrupt_regs->usbien); + writeb(EXTIRQ_WAKEUP, &pdev->interrupt_regs->extien); + writel(~0, &pdev->adma_regs->ep_ien); + + return IRQ_NONE; +} + +static irqreturn_t cdns2_thread_usb_irq_handler(struct cdns2_device *pdev) +{ + u8 usb_irq, ext_irq; + int speed; + int i; + + ext_irq = readb(&pdev->interrupt_regs->extirq) & EXTIRQ_WAKEUP; + writeb(ext_irq, &pdev->interrupt_regs->extirq); + + usb_irq = readb(&pdev->interrupt_regs->usbirq) & USB_IEN_INIT; + writeb(usb_irq, &pdev->interrupt_regs->usbirq); + + if (!ext_irq && !usb_irq) + return IRQ_NONE; + + trace_cdns2_usb_irq(usb_irq, ext_irq); + + if (ext_irq & EXTIRQ_WAKEUP) { + if (pdev->gadget_driver && pdev->gadget_driver->resume) { + spin_unlock(&pdev->lock); + pdev->gadget_driver->resume(&pdev->gadget); + spin_lock(&pdev->lock); + } + } + + if (usb_irq & USBIRQ_LPM) { + u8 reg = readb(&pdev->usb_regs->lpmctrl); + + /* LPM1 enter */ + if (!(reg & LPMCTRLLH_LPMNYET)) + writeb(0, &pdev->usb_regs->sleep_clkgate); + } + + if (usb_irq & USBIRQ_SUSPEND) { + if (pdev->gadget_driver && pdev->gadget_driver->suspend) { + spin_unlock(&pdev->lock); + pdev->gadget_driver->suspend(&pdev->gadget); + spin_lock(&pdev->lock); + } + } + + if (usb_irq & USBIRQ_URESET) { + if (pdev->gadget_driver) { + pdev->dev_address = 0; + + spin_unlock(&pdev->lock); + usb_gadget_udc_reset(&pdev->gadget, + pdev->gadget_driver); + spin_lock(&pdev->lock); + + /* + * The USBIRQ_URESET is reported at the beginning of + * reset signal. 100ms is enough time to finish reset + * process. For high-speed reset procedure is completed + * when controller detect HS mode. + */ + for (i = 0; i < 100; i++) { + mdelay(1); + speed = cdns2_get_speed(pdev); + if (speed == USB_SPEED_HIGH) + break; + } + + pdev->gadget.speed = speed; + cdns2_enable_l1(pdev, 0); + cdns2_ep0_config(pdev); + pdev->may_wakeup = 0; + } + } + + if (usb_irq & USBIRQ_SUDAV) { + pdev->ep0_stage = CDNS2_SETUP_STAGE; + cdns2_handle_setup_packet(pdev); + } + + return IRQ_HANDLED; +} + +/* Deferred USB interrupt handler. */ +static irqreturn_t cdns2_thread_irq_handler(int irq, void *data) +{ + struct cdns2_device *pdev = data; + unsigned long dma_ep_ists; + unsigned long flags; + unsigned int bit; + + local_bh_disable(); + spin_lock_irqsave(&pdev->lock, flags); + + cdns2_thread_usb_irq_handler(pdev); + + dma_ep_ists = readl(&pdev->adma_regs->ep_ists); + if (!dma_ep_ists) + goto unlock; + + trace_cdns2_dma_ep_ists(dma_ep_ists); + + /* Handle default endpoint OUT. */ + if (dma_ep_ists & DMA_EP_ISTS_EP_OUT0) + cdns2_handle_ep0_interrupt(pdev, USB_DIR_OUT); + + /* Handle default endpoint IN. */ + if (dma_ep_ists & DMA_EP_ISTS_EP_IN0) + cdns2_handle_ep0_interrupt(pdev, USB_DIR_IN); + + dma_ep_ists &= ~(DMA_EP_ISTS_EP_OUT0 | DMA_EP_ISTS_EP_IN0); + + for_each_set_bit(bit, &dma_ep_ists, sizeof(u32) * BITS_PER_BYTE) { + u8 ep_idx = bit > 16 ? (bit - 16) * 2 : (bit * 2) - 1; + + /* + * Endpoints in pdev->eps[] are held in order: + * ep0, ep1out, ep1in, ep2out, ep2in... ep15out, ep15in. + * but in dma_ep_ists in order: + * ep0 ep1out ep2out ... ep15out ep0in ep1in .. ep15in + */ + cdns2_handle_epx_interrupt(&pdev->eps[ep_idx]); + } + +unlock: + writel(~0, &pdev->adma_regs->ep_ien); + writeb(USB_IEN_INIT, &pdev->interrupt_regs->usbien); + writeb(EXTIRQ_WAKEUP, &pdev->interrupt_regs->extien); + + spin_unlock_irqrestore(&pdev->lock, flags); + local_bh_enable(); + + return IRQ_HANDLED; +} + +/* Calculates and assigns onchip memory for endpoints. */ +static void cdns2_eps_onchip_buffer_init(struct cdns2_device *pdev) +{ + struct cdns2_endpoint *pep; + int min_buf_tx = 0; + int min_buf_rx = 0; + u16 tx_offset = 0; + u16 rx_offset = 0; + int free; + int i; + + for (i = 0; i < CDNS2_ENDPOINTS_NUM; i++) { + pep = &pdev->eps[i]; + + if (!(pep->ep_state & EP_CLAIMED)) + continue; + + if (pep->dir) + min_buf_tx += pep->buffering; + else + min_buf_rx += pep->buffering; + } + + for (i = 0; i < CDNS2_ENDPOINTS_NUM; i++) { + pep = &pdev->eps[i]; + + if (!(pep->ep_state & EP_CLAIMED)) + continue; + + if (pep->dir) { + free = pdev->onchip_tx_buf - min_buf_tx; + + if (free + pep->buffering >= 4) + free = 4; + else + free = free + pep->buffering; + + min_buf_tx = min_buf_tx - pep->buffering + free; + + pep->buffering = free; + + writel(tx_offset, + &pdev->epx_regs->txstaddr[pep->num - 1]); + pdev->epx_regs->txstaddr[pep->num - 1] = tx_offset; + + dev_dbg(pdev->dev, "%s onchip address %04x, buffering: %d\n", + pep->name, tx_offset, pep->buffering); + + tx_offset += pep->buffering * 1024; + } else { + free = pdev->onchip_rx_buf - min_buf_rx; + + if (free + pep->buffering >= 4) + free = 4; + else + free = free + pep->buffering; + + min_buf_rx = min_buf_rx - pep->buffering + free; + + pep->buffering = free; + writel(rx_offset, + &pdev->epx_regs->rxstaddr[pep->num - 1]); + + dev_dbg(pdev->dev, "%s onchip address %04x, buffering: %d\n", + pep->name, rx_offset, pep->buffering); + + rx_offset += pep->buffering * 1024; + } + } +} + +/* Configure hardware endpoint. */ +static int cdns2_ep_config(struct cdns2_endpoint *pep, bool enable) +{ + bool is_iso_ep = (pep->type == USB_ENDPOINT_XFER_ISOC); + struct cdns2_device *pdev = pep->pdev; + u32 max_packet_size; + u8 dir = 0; + u8 ep_cfg; + u8 mult; + u32 val; + int ret; + + switch (pep->type) { + case USB_ENDPOINT_XFER_INT: + ep_cfg = EPX_CON_TYPE_INT; + break; + case USB_ENDPOINT_XFER_BULK: + ep_cfg = EPX_CON_TYPE_BULK; + break; + default: + mult = USB_EP_MAXP_MULT(pep->endpoint.desc->wMaxPacketSize); + ep_cfg = mult << EPX_CON_ISOD_SHIFT; + ep_cfg |= EPX_CON_TYPE_ISOC; + + if (pep->dir) { + set_reg_bit_8(&pdev->epx_regs->isoautoarm, BIT(pep->num)); + set_reg_bit_8(&pdev->epx_regs->isoautodump, BIT(pep->num)); + set_reg_bit_8(&pdev->epx_regs->isodctrl, BIT(pep->num)); + } + } + + switch (pdev->gadget.speed) { + case USB_SPEED_FULL: + max_packet_size = is_iso_ep ? 1023 : 64; + break; + case USB_SPEED_HIGH: + max_packet_size = is_iso_ep ? 1024 : 512; + break; + default: + /* All other speed are not supported. */ + return -EINVAL; + } + + ep_cfg |= (EPX_CON_VAL | (pep->buffering - 1)); + + if (pep->dir) { + dir = FIFOCTRL_IO_TX; + writew(max_packet_size, &pdev->epx_regs->txmaxpack[pep->num - 1]); + writeb(ep_cfg, &pdev->epx_regs->ep[pep->num - 1].txcon); + } else { + writew(max_packet_size, &pdev->epx_regs->rxmaxpack[pep->num - 1]); + writeb(ep_cfg, &pdev->epx_regs->ep[pep->num - 1].rxcon); + } + + writeb(pep->num | dir | FIFOCTRL_FIFOAUTO, + &pdev->usb_regs->fifoctrl); + writeb(pep->num | dir, &pdev->epx_regs->endprst); + writeb(pep->num | ENDPRST_FIFORST | ENDPRST_TOGRST | dir, + &pdev->epx_regs->endprst); + + if (max_packet_size == 1024) + pep->trb_burst_size = 128; + else if (max_packet_size >= 512) + pep->trb_burst_size = 64; + else + pep->trb_burst_size = 16; + + cdns2_select_ep(pdev, pep->num | pep->dir); + writel(DMA_EP_CMD_EPRST | DMA_EP_CMD_DFLUSH, &pdev->adma_regs->ep_cmd); + + ret = readl_poll_timeout_atomic(&pdev->adma_regs->ep_cmd, val, + !(val & (DMA_EP_CMD_DFLUSH | + DMA_EP_CMD_EPRST)), + 1, 1000); + + if (ret) + return ret; + + writel(DMA_EP_STS_TRBERR | DMA_EP_STS_ISOERR, &pdev->adma_regs->ep_sts_en); + + if (enable) + writel(DMA_EP_CFG_ENABLE, &pdev->adma_regs->ep_cfg); + + trace_cdns2_epx_hw_cfg(pdev, pep); + + dev_dbg(pdev->dev, "Configure %s: with MPS: %08x, ep con: %02x\n", + pep->name, max_packet_size, ep_cfg); + + return 0; +} + +struct usb_request *cdns2_gadget_ep_alloc_request(struct usb_ep *ep, + gfp_t gfp_flags) +{ + struct cdns2_endpoint *pep = ep_to_cdns2_ep(ep); + struct cdns2_request *preq; + + preq = kzalloc(sizeof(*preq), gfp_flags); + if (!preq) + return NULL; + + preq->pep = pep; + + trace_cdns2_alloc_request(preq); + + return &preq->request; +} + +void cdns2_gadget_ep_free_request(struct usb_ep *ep, + struct usb_request *request) +{ + struct cdns2_request *preq = to_cdns2_request(request); + + trace_cdns2_free_request(preq); + kfree(preq); +} + +static int cdns2_gadget_ep_enable(struct usb_ep *ep, + const struct usb_endpoint_descriptor *desc) +{ + u32 reg = DMA_EP_STS_EN_TRBERREN; + struct cdns2_endpoint *pep; + struct cdns2_device *pdev; + unsigned long flags; + int enable = 1; + int ret = 0; + + if (!ep || !desc || desc->bDescriptorType != USB_DT_ENDPOINT || + !desc->wMaxPacketSize) { + return -EINVAL; + } + + pep = ep_to_cdns2_ep(ep); + pdev = pep->pdev; + + if (dev_WARN_ONCE(pdev->dev, pep->ep_state & EP_ENABLED, + "%s is already enabled\n", pep->name)) + return 0; + + spin_lock_irqsave(&pdev->lock, flags); + + pep->type = usb_endpoint_type(desc); + pep->interval = desc->bInterval ? BIT(desc->bInterval - 1) : 0; + + if (pdev->gadget.speed == USB_SPEED_FULL) + if (pep->type == USB_ENDPOINT_XFER_INT) + pep->interval = desc->bInterval; + + if (pep->interval > ISO_MAX_INTERVAL && + pep->type == USB_ENDPOINT_XFER_ISOC) { + dev_err(pdev->dev, "ISO period is limited to %d (current: %d)\n", + ISO_MAX_INTERVAL, pep->interval); + + ret = -EINVAL; + goto exit; + } + + /* + * During ISO OUT traffic DMA reads Transfer Ring for the EP which has + * never got doorbell. + * This issue was detected only on simulation, but to avoid this issue + * driver add protection against it. To fix it driver enable ISO OUT + * endpoint before setting DRBL. This special treatment of ISO OUT + * endpoints are recommended by controller specification. + */ + if (pep->type == USB_ENDPOINT_XFER_ISOC && !pep->dir) + enable = 0; + + ret = cdns2_alloc_tr_segment(pep); + if (ret) + goto exit; + + ret = cdns2_ep_config(pep, enable); + if (ret) { + cdns2_free_tr_segment(pep); + ret = -EINVAL; + goto exit; + } + + trace_cdns2_gadget_ep_enable(pep); + + pep->ep_state &= ~(EP_STALLED | EP_STALL_PENDING); + pep->ep_state |= EP_ENABLED; + pep->wa1_set = 0; + pep->ring.enqueue = 0; + pep->ring.dequeue = 0; + reg = readl(&pdev->adma_regs->ep_sts); + pep->ring.pcs = !!DMA_EP_STS_CCS(reg); + pep->ring.ccs = !!DMA_EP_STS_CCS(reg); + + writel(pep->ring.dma, &pdev->adma_regs->ep_traddr); + + /* one TRB is reserved for link TRB used in DMULT mode*/ + pep->ring.free_trbs = TRBS_PER_SEGMENT - 1; + +exit: + spin_unlock_irqrestore(&pdev->lock, flags); + + return ret; +} + +static int cdns2_gadget_ep_disable(struct usb_ep *ep) +{ + struct cdns2_endpoint *pep; + struct cdns2_request *preq; + struct cdns2_device *pdev; + unsigned long flags; + int val; + + if (!ep) + return -EINVAL; + + pep = ep_to_cdns2_ep(ep); + pdev = pep->pdev; + + if (dev_WARN_ONCE(pdev->dev, !(pep->ep_state & EP_ENABLED), + "%s is already disabled\n", pep->name)) + return 0; + + spin_lock_irqsave(&pdev->lock, flags); + + trace_cdns2_gadget_ep_disable(pep); + + cdns2_select_ep(pdev, ep->desc->bEndpointAddress); + + clear_reg_bit_32(&pdev->adma_regs->ep_cfg, DMA_EP_CFG_ENABLE); + + /* + * Driver needs some time before resetting endpoint. + * It need waits for clearing DBUSY bit or for timeout expired. + * 10us is enough time for controller to stop transfer. + */ + readl_poll_timeout_atomic(&pdev->adma_regs->ep_sts, val, + !(val & DMA_EP_STS_DBUSY), 1, 10); + writel(DMA_EP_CMD_EPRST, &pdev->adma_regs->ep_cmd); + + readl_poll_timeout_atomic(&pdev->adma_regs->ep_cmd, val, + !(val & (DMA_EP_CMD_DFLUSH | DMA_EP_CMD_EPRST)), + 1, 1000); + + while (!list_empty(&pep->pending_list)) { + preq = cdns2_next_preq(&pep->pending_list); + cdns2_gadget_giveback(pep, preq, -ESHUTDOWN); + } + + while (!list_empty(&pep->deferred_list)) { + preq = cdns2_next_preq(&pep->deferred_list); + cdns2_gadget_giveback(pep, preq, -ESHUTDOWN); + } + + ep->desc = NULL; + pep->ep_state &= ~EP_ENABLED; + + spin_unlock_irqrestore(&pdev->lock, flags); + + return 0; +} + +static int cdns2_ep_enqueue(struct cdns2_endpoint *pep, + struct cdns2_request *preq, + gfp_t gfp_flags) +{ + struct cdns2_device *pdev = pep->pdev; + struct usb_request *request; + int ret; + + request = &preq->request; + request->actual = 0; + request->status = -EINPROGRESS; + + ret = usb_gadget_map_request_by_dev(pdev->dev, request, pep->dir); + if (ret) { + trace_cdns2_request_enqueue_error(preq); + return ret; + } + + list_add_tail(&preq->list, &pep->deferred_list); + trace_cdns2_request_enqueue(preq); + + if (!(pep->ep_state & EP_STALLED) && !(pep->ep_state & EP_STALL_PENDING)) + cdns2_start_all_request(pdev, pep); + + return 0; +} + +static int cdns2_gadget_ep_queue(struct usb_ep *ep, struct usb_request *request, + gfp_t gfp_flags) +{ + struct usb_request *zlp_request; + struct cdns2_request *preq; + struct cdns2_endpoint *pep; + struct cdns2_device *pdev; + unsigned long flags; + int ret; + + if (!request || !ep) + return -EINVAL; + + pep = ep_to_cdns2_ep(ep); + pdev = pep->pdev; + + if (!(pep->ep_state & EP_ENABLED)) { + dev_err(pdev->dev, "%s: can't queue to disabled endpoint\n", + pep->name); + return -EINVAL; + } + + spin_lock_irqsave(&pdev->lock, flags); + + preq = to_cdns2_request(request); + ret = cdns2_ep_enqueue(pep, preq, gfp_flags); + + if (ret == 0 && request->zero && request->length && + (request->length % ep->maxpacket == 0)) { + struct cdns2_request *preq; + + zlp_request = cdns2_gadget_ep_alloc_request(ep, GFP_ATOMIC); + zlp_request->buf = pdev->zlp_buf; + zlp_request->length = 0; + + preq = to_cdns2_request(zlp_request); + ret = cdns2_ep_enqueue(pep, preq, gfp_flags); + } + + spin_unlock_irqrestore(&pdev->lock, flags); + return ret; +} + +int cdns2_gadget_ep_dequeue(struct usb_ep *ep, + struct usb_request *request) +{ + struct cdns2_request *preq, *preq_temp, *cur_preq; + struct cdns2_endpoint *pep; + struct cdns2_trb *link_trb; + u8 req_on_hw_ring = 0; + unsigned long flags; + u32 buffer; + int val, i; + + if (!ep || !request || !ep->desc) + return -EINVAL; + + pep = ep_to_cdns2_ep(ep); + if (!pep->endpoint.desc) { + dev_err(pep->pdev->dev, "%s: can't dequeue to disabled endpoint\n", + pep->name); + return -ESHUTDOWN; + } + + /* Requests has been dequeued during disabling endpoint. */ + if (!(pep->ep_state & EP_ENABLED)) + return 0; + + spin_lock_irqsave(&pep->pdev->lock, flags); + + cur_preq = to_cdns2_request(request); + trace_cdns2_request_dequeue(cur_preq); + + list_for_each_entry_safe(preq, preq_temp, &pep->pending_list, list) { + if (cur_preq == preq) { + req_on_hw_ring = 1; + goto found; + } + } + + list_for_each_entry_safe(preq, preq_temp, &pep->deferred_list, list) { + if (cur_preq == preq) + goto found; + } + + goto not_found; + +found: + link_trb = preq->trb; + + /* Update ring only if removed request is on pending_req_list list. */ + if (req_on_hw_ring && link_trb) { + /* Stop DMA */ + writel(DMA_EP_CMD_DFLUSH, &pep->pdev->adma_regs->ep_cmd); + + /* Wait for DFLUSH cleared. */ + readl_poll_timeout_atomic(&pep->pdev->adma_regs->ep_cmd, val, + !(val & DMA_EP_CMD_DFLUSH), 1, 1000); + + buffer = cpu_to_le32(TRB_BUFFER(pep->ring.dma + + ((preq->end_trb + 1) * TRB_SIZE))); + + for (i = 0; i < preq->num_of_trb; i++) { + link_trb->buffer = buffer; + link_trb->control = cpu_to_le32((le32_to_cpu(link_trb->control) + & TRB_CYCLE) | TRB_CHAIN | + TRB_TYPE(TRB_LINK)); + + trace_cdns2_queue_trb(pep, link_trb); + link_trb = cdns2_next_trb(pep, link_trb); + } + + if (pep->wa1_trb == preq->trb) + cdns2_wa1_restore_cycle_bit(pep); + } + + cdns2_gadget_giveback(pep, cur_preq, -ECONNRESET); + + preq = cdns2_next_preq(&pep->pending_list); + if (preq) + cdns2_rearm_transfer(pep, 1); + +not_found: + spin_unlock_irqrestore(&pep->pdev->lock, flags); + return 0; +} + +int cdns2_halt_endpoint(struct cdns2_device *pdev, + struct cdns2_endpoint *pep, + int value) +{ + u8 __iomem *conf; + int dir = 0; + + if (!(pep->ep_state & EP_ENABLED)) + return -EPERM; + + if (pep->dir) { + dir = ENDPRST_IO_TX; + conf = &pdev->epx_regs->ep[pep->num - 1].txcon; + } else { + conf = &pdev->epx_regs->ep[pep->num - 1].rxcon; + } + + if (!value) { + struct cdns2_trb *trb = NULL; + struct cdns2_request *preq; + struct cdns2_trb trb_tmp; + + preq = cdns2_next_preq(&pep->pending_list); + if (preq) { + trb = preq->trb; + if (trb) { + trb_tmp = *trb; + trb->control = trb->control ^ cpu_to_le32(TRB_CYCLE); + } + } + + trace_cdns2_ep_halt(pep, 0, 0); + + /* Resets Sequence Number */ + writeb(dir | pep->num, &pdev->epx_regs->endprst); + writeb(dir | ENDPRST_TOGRST | pep->num, + &pdev->epx_regs->endprst); + + clear_reg_bit_8(conf, EPX_CON_STALL); + + pep->ep_state &= ~(EP_STALLED | EP_STALL_PENDING); + + if (preq) { + if (trb) + *trb = trb_tmp; + + cdns2_rearm_transfer(pep, 1); + } + + cdns2_start_all_request(pdev, pep); + } else { + trace_cdns2_ep_halt(pep, 1, 0); + set_reg_bit_8(conf, EPX_CON_STALL); + writeb(dir | pep->num, &pdev->epx_regs->endprst); + writeb(dir | ENDPRST_FIFORST | pep->num, + &pdev->epx_regs->endprst); + pep->ep_state |= EP_STALLED; + } + + return 0; +} + +/* Sets/clears stall on selected endpoint. */ +static int cdns2_gadget_ep_set_halt(struct usb_ep *ep, int value) +{ + struct cdns2_endpoint *pep = ep_to_cdns2_ep(ep); + struct cdns2_device *pdev = pep->pdev; + struct cdns2_request *preq; + unsigned long flags = 0; + int ret; + + spin_lock_irqsave(&pdev->lock, flags); + + preq = cdns2_next_preq(&pep->pending_list); + if (value && preq) { + trace_cdns2_ep_busy_try_halt_again(pep); + ret = -EAGAIN; + goto done; + } + + if (!value) + pep->ep_state &= ~EP_WEDGE; + + ret = cdns2_halt_endpoint(pdev, pep, value); + +done: + spin_unlock_irqrestore(&pdev->lock, flags); + return ret; +} + +static int cdns2_gadget_ep_set_wedge(struct usb_ep *ep) +{ + struct cdns2_endpoint *pep = ep_to_cdns2_ep(ep); + + cdns2_gadget_ep_set_halt(ep, 1); + pep->ep_state |= EP_WEDGE; + + return 0; +} + +static struct +cdns2_endpoint *cdns2_find_available_ep(struct cdns2_device *pdev, + struct usb_endpoint_descriptor *desc) +{ + struct cdns2_endpoint *pep; + struct usb_ep *ep; + int ep_correct; + + list_for_each_entry(ep, &pdev->gadget.ep_list, ep_list) { + unsigned long num; + int ret; + /* ep name pattern likes epXin or epXout. */ + char c[2] = {ep->name[2], '\0'}; + + ret = kstrtoul(c, 10, &num); + if (ret) + return ERR_PTR(ret); + pep = ep_to_cdns2_ep(ep); + + if (pep->num != num) + continue; + + ep_correct = (pep->endpoint.caps.dir_in && + usb_endpoint_dir_in(desc)) || + (pep->endpoint.caps.dir_out && + usb_endpoint_dir_out(desc)); + + if (ep_correct && !(pep->ep_state & EP_CLAIMED)) + return pep; + } + + return ERR_PTR(-ENOENT); +} + +/* + * Function used to recognize which endpoints will be used to optimize + * on-chip memory usage. + */ +static struct +usb_ep *cdns2_gadget_match_ep(struct usb_gadget *gadget, + struct usb_endpoint_descriptor *desc, + struct usb_ss_ep_comp_descriptor *comp_desc) +{ + struct cdns2_device *pdev = gadget_to_cdns2_device(gadget); + struct cdns2_endpoint *pep; + unsigned long flags; + + pep = cdns2_find_available_ep(pdev, desc); + if (IS_ERR(pep)) { + dev_err(pdev->dev, "no available ep\n"); + return NULL; + } + + spin_lock_irqsave(&pdev->lock, flags); + + if (usb_endpoint_type(desc) == USB_ENDPOINT_XFER_ISOC) + pep->buffering = 4; + else + pep->buffering = 1; + + pep->ep_state |= EP_CLAIMED; + spin_unlock_irqrestore(&pdev->lock, flags); + + return &pep->endpoint; +} + +static const struct usb_ep_ops cdns2_gadget_ep_ops = { + .enable = cdns2_gadget_ep_enable, + .disable = cdns2_gadget_ep_disable, + .alloc_request = cdns2_gadget_ep_alloc_request, + .free_request = cdns2_gadget_ep_free_request, + .queue = cdns2_gadget_ep_queue, + .dequeue = cdns2_gadget_ep_dequeue, + .set_halt = cdns2_gadget_ep_set_halt, + .set_wedge = cdns2_gadget_ep_set_wedge, +}; + +static int cdns2_gadget_get_frame(struct usb_gadget *gadget) +{ + struct cdns2_device *pdev = gadget_to_cdns2_device(gadget); + + return readw(&pdev->usb_regs->frmnr); +} + +static int cdns2_gadget_wakeup(struct usb_gadget *gadget) +{ + struct cdns2_device *pdev = gadget_to_cdns2_device(gadget); + unsigned long flags; + + spin_lock_irqsave(&pdev->lock, flags); + cdns2_wakeup(pdev); + spin_unlock_irqrestore(&pdev->lock, flags); + + return 0; +} + +static int cdns2_gadget_set_selfpowered(struct usb_gadget *gadget, + int is_selfpowered) +{ + struct cdns2_device *pdev = gadget_to_cdns2_device(gadget); + unsigned long flags; + + spin_lock_irqsave(&pdev->lock, flags); + pdev->is_selfpowered = !!is_selfpowered; + spin_unlock_irqrestore(&pdev->lock, flags); + return 0; +} + +/* Disable interrupts and begin the controller halting process. */ +static void cdns2_quiesce(struct cdns2_device *pdev) +{ + set_reg_bit_8(&pdev->usb_regs->usbcs, USBCS_DISCON); + + /* Disable interrupt. */ + writeb(0, &pdev->interrupt_regs->extien), + writeb(0, &pdev->interrupt_regs->usbien), + writew(0, &pdev->adma_regs->ep_ien); + + /* Clear interrupt line. */ + writeb(0x0, &pdev->interrupt_regs->usbirq); +} + +static void cdns2_gadget_config(struct cdns2_device *pdev) +{ + cdns2_ep0_config(pdev); + + /* Enable DMA interrupts for all endpoints. */ + writel(~0x0, &pdev->adma_regs->ep_ien); + cdns2_enable_l1(pdev, 0); + writeb(USB_IEN_INIT, &pdev->interrupt_regs->usbien); + writeb(EXTIRQ_WAKEUP, &pdev->interrupt_regs->extien); + writel(DMA_CONF_DMULT, &pdev->adma_regs->conf); +} + +static int cdns2_gadget_pullup(struct usb_gadget *gadget, int is_on) +{ + struct cdns2_device *pdev = gadget_to_cdns2_device(gadget); + unsigned long flags; + + trace_cdns2_pullup(is_on); + + /* + * Disable events handling while controller is being + * enabled/disabled. + */ + disable_irq(pdev->irq); + spin_lock_irqsave(&pdev->lock, flags); + + if (is_on) { + cdns2_gadget_config(pdev); + clear_reg_bit_8(&pdev->usb_regs->usbcs, USBCS_DISCON); + } else { + cdns2_quiesce(pdev); + } + + spin_unlock_irqrestore(&pdev->lock, flags); + enable_irq(pdev->irq); + + return 0; +} + +static int cdns2_gadget_udc_start(struct usb_gadget *gadget, + struct usb_gadget_driver *driver) +{ + struct cdns2_device *pdev = gadget_to_cdns2_device(gadget); + enum usb_device_speed max_speed = driver->max_speed; + unsigned long flags; + + spin_lock_irqsave(&pdev->lock, flags); + pdev->gadget_driver = driver; + + /* Limit speed if necessary. */ + max_speed = min(driver->max_speed, gadget->max_speed); + + switch (max_speed) { + case USB_SPEED_FULL: + writeb(SPEEDCTRL_HSDISABLE, &pdev->usb_regs->speedctrl); + break; + case USB_SPEED_HIGH: + writeb(0, &pdev->usb_regs->speedctrl); + break; + default: + dev_err(pdev->dev, "invalid maximum_speed parameter %d\n", + max_speed); + fallthrough; + case USB_SPEED_UNKNOWN: + /* Default to highspeed. */ + max_speed = USB_SPEED_HIGH; + break; + } + + /* Reset all USB endpoints. */ + writeb(ENDPRST_IO_TX, &pdev->usb_regs->endprst); + writeb(ENDPRST_FIFORST | ENDPRST_TOGRST | ENDPRST_IO_TX, + &pdev->usb_regs->endprst); + writeb(ENDPRST_FIFORST | ENDPRST_TOGRST, &pdev->usb_regs->endprst); + + cdns2_eps_onchip_buffer_init(pdev); + + cdns2_gadget_config(pdev); + spin_unlock_irqrestore(&pdev->lock, flags); + + return 0; +} + +static int cdns2_gadget_udc_stop(struct usb_gadget *gadget) +{ + struct cdns2_device *pdev = gadget_to_cdns2_device(gadget); + struct cdns2_endpoint *pep; + u32 bEndpointAddress; + struct usb_ep *ep; + int val; + + pdev->gadget_driver = NULL; + pdev->gadget.speed = USB_SPEED_UNKNOWN; + + list_for_each_entry(ep, &pdev->gadget.ep_list, ep_list) { + pep = ep_to_cdns2_ep(ep); + bEndpointAddress = pep->num | pep->dir; + cdns2_select_ep(pdev, bEndpointAddress); + writel(DMA_EP_CMD_EPRST, &pdev->adma_regs->ep_cmd); + readl_poll_timeout_atomic(&pdev->adma_regs->ep_cmd, val, + !(val & DMA_EP_CMD_EPRST), 1, 100); + } + + cdns2_quiesce(pdev); + + writeb(ENDPRST_IO_TX, &pdev->usb_regs->endprst); + writeb(ENDPRST_FIFORST | ENDPRST_TOGRST | ENDPRST_IO_TX, + &pdev->epx_regs->endprst); + writeb(ENDPRST_FIFORST | ENDPRST_TOGRST, &pdev->epx_regs->endprst); + + return 0; +} + +static const struct usb_gadget_ops cdns2_gadget_ops = { + .get_frame = cdns2_gadget_get_frame, + .wakeup = cdns2_gadget_wakeup, + .set_selfpowered = cdns2_gadget_set_selfpowered, + .pullup = cdns2_gadget_pullup, + .udc_start = cdns2_gadget_udc_start, + .udc_stop = cdns2_gadget_udc_stop, + .match_ep = cdns2_gadget_match_ep, +}; + +static void cdns2_free_all_eps(struct cdns2_device *pdev) +{ + int i; + + for (i = 0; i < CDNS2_ENDPOINTS_NUM; i++) + cdns2_free_tr_segment(&pdev->eps[i]); +} + +/* Initializes software endpoints of gadget. */ +static int cdns2_init_eps(struct cdns2_device *pdev) +{ + struct cdns2_endpoint *pep; + int i; + + for (i = 0; i < CDNS2_ENDPOINTS_NUM; i++) { + bool direction = !(i & 1); /* Start from OUT endpoint. */ + u8 epnum = ((i + 1) >> 1); + + /* + * Endpoints are being held in pdev->eps[] in form: + * ep0, ep1out, ep1in ... ep15out, ep15in. + */ + if (!CDNS2_IF_EP_EXIST(pdev, epnum, direction)) + continue; + + pep = &pdev->eps[i]; + pep->pdev = pdev; + pep->num = epnum; + /* 0 for OUT, 1 for IN. */ + pep->dir = direction ? USB_DIR_IN : USB_DIR_OUT; + pep->idx = i; + + /* Ep0in and ep0out are represented by pdev->eps[0]. */ + if (!epnum) { + int ret; + + snprintf(pep->name, sizeof(pep->name), "ep%d%s", + epnum, "BiDir"); + + cdns2_init_ep0(pdev, pep); + + ret = cdns2_alloc_tr_segment(pep); + if (ret) { + dev_err(pdev->dev, "Failed to init ep0\n"); + return ret; + } + } else { + snprintf(pep->name, sizeof(pep->name), "ep%d%s", + epnum, !!direction ? "in" : "out"); + pep->endpoint.name = pep->name; + + usb_ep_set_maxpacket_limit(&pep->endpoint, 1024); + pep->endpoint.ops = &cdns2_gadget_ep_ops; + list_add_tail(&pep->endpoint.ep_list, &pdev->gadget.ep_list); + + pep->endpoint.caps.dir_in = direction; + pep->endpoint.caps.dir_out = !direction; + + pep->endpoint.caps.type_iso = 1; + pep->endpoint.caps.type_bulk = 1; + pep->endpoint.caps.type_int = 1; + } + + pep->endpoint.name = pep->name; + pep->ep_state = 0; + + dev_dbg(pdev->dev, "Init %s, SupType: CTRL: %s, INT: %s, " + "BULK: %s, ISOC %s, SupDir IN: %s, OUT: %s\n", + pep->name, + (pep->endpoint.caps.type_control) ? "yes" : "no", + (pep->endpoint.caps.type_int) ? "yes" : "no", + (pep->endpoint.caps.type_bulk) ? "yes" : "no", + (pep->endpoint.caps.type_iso) ? "yes" : "no", + (pep->endpoint.caps.dir_in) ? "yes" : "no", + (pep->endpoint.caps.dir_out) ? "yes" : "no"); + + INIT_LIST_HEAD(&pep->pending_list); + INIT_LIST_HEAD(&pep->deferred_list); + } + + return 0; +} + +static int cdns2_gadget_start(struct cdns2_device *pdev) +{ + u32 max_speed; + void *buf; + int val; + int ret; + + pdev->usb_regs = pdev->regs; + pdev->ep0_regs = pdev->regs; + pdev->epx_regs = pdev->regs; + pdev->interrupt_regs = pdev->regs; + pdev->adma_regs = pdev->regs + CDNS2_ADMA_REGS_OFFSET; + + /* Reset controller. */ + set_reg_bit_8(&pdev->usb_regs->cpuctrl, CPUCTRL_SW_RST); + + ret = readl_poll_timeout_atomic(&pdev->usb_regs->cpuctrl, val, + !(val & CPUCTRL_SW_RST), 1, 10000); + if (ret) { + dev_err(pdev->dev, "Error: reset controller timeout\n"); + return -EINVAL; + } + + usb_initialize_gadget(pdev->dev, &pdev->gadget, NULL); + + device_property_read_u16(pdev->dev, "cdns,on-chip-tx-buff-size", + &pdev->onchip_tx_buf); + device_property_read_u16(pdev->dev, "cdns,on-chip-rx-buff-size", + &pdev->onchip_rx_buf); + device_property_read_u32(pdev->dev, "cdns,avail-endpoints", + &pdev->eps_supported); + + /* + * Driver assumes that each USBHS controller has at least + * one IN and one OUT non control endpoint. + */ + if (!pdev->onchip_tx_buf && !pdev->onchip_rx_buf) { + ret = -EINVAL; + dev_err(pdev->dev, "Invalid on-chip memory configuration\n"); + goto put_gadget; + } + + if (!(pdev->eps_supported & ~0x00010001)) { + ret = -EINVAL; + dev_err(pdev->dev, "No hardware endpoints available\n"); + goto put_gadget; + } + + max_speed = usb_get_maximum_speed(pdev->dev); + + switch (max_speed) { + case USB_SPEED_FULL: + case USB_SPEED_HIGH: + break; + default: + dev_err(pdev->dev, "invalid maximum_speed parameter %d\n", + max_speed); + fallthrough; + case USB_SPEED_UNKNOWN: + max_speed = USB_SPEED_HIGH; + break; + } + + pdev->gadget.max_speed = max_speed; + pdev->gadget.speed = USB_SPEED_UNKNOWN; + pdev->gadget.ops = &cdns2_gadget_ops; + pdev->gadget.name = "usbhs-gadget"; + pdev->gadget.quirk_avoids_skb_reserve = 1; + pdev->gadget.irq = pdev->irq; + + spin_lock_init(&pdev->lock); + INIT_WORK(&pdev->pending_status_wq, cdns2_pending_setup_status_handler); + + /* Initialize endpoint container. */ + INIT_LIST_HEAD(&pdev->gadget.ep_list); + pdev->eps_dma_pool = dma_pool_create("cdns2_eps_dma_pool", pdev->dev, + TR_SEG_SIZE, 8, 0); + if (!pdev->eps_dma_pool) { + dev_err(pdev->dev, "Failed to create TRB dma pool\n"); + ret = -ENOMEM; + goto put_gadget; + } + + ret = cdns2_init_eps(pdev); + if (ret) { + dev_err(pdev->dev, "Failed to create endpoints\n"); + goto destroy_dma_pool; + } + + pdev->gadget.sg_supported = 1; + + pdev->zlp_buf = kzalloc(CDNS2_EP_ZLP_BUF_SIZE, GFP_KERNEL); + if (!pdev->zlp_buf) { + ret = -ENOMEM; + goto destroy_dma_pool; + } + + /* Allocate memory for setup packet buffer. */ + buf = dma_alloc_coherent(pdev->dev, 8, &pdev->ep0_preq.request.dma, + GFP_DMA); + pdev->ep0_preq.request.buf = buf; + + if (!pdev->ep0_preq.request.buf) { + ret = -ENOMEM; + goto free_zlp_buf; + } + + /* Add USB gadget device. */ + ret = usb_add_gadget(&pdev->gadget); + if (ret < 0) { + dev_err(pdev->dev, "Failed to add gadget\n"); + goto free_ep0_buf; + } + + return 0; + +free_ep0_buf: + dma_free_coherent(pdev->dev, 8, pdev->ep0_preq.request.buf, + pdev->ep0_preq.request.dma); +free_zlp_buf: + kfree(pdev->zlp_buf); +destroy_dma_pool: + dma_pool_destroy(pdev->eps_dma_pool); +put_gadget: + usb_put_gadget(&pdev->gadget); + + return ret; +} + +int cdns2_gadget_suspend(struct cdns2_device *pdev) +{ + unsigned long flags; + + cdns2_disconnect_gadget(pdev); + + spin_lock_irqsave(&pdev->lock, flags); + pdev->gadget.speed = USB_SPEED_UNKNOWN; + + trace_cdns2_device_state("notattached"); + usb_gadget_set_state(&pdev->gadget, USB_STATE_NOTATTACHED); + cdns2_enable_l1(pdev, 0); + + /* Disable interrupt for device. */ + writeb(0, &pdev->interrupt_regs->usbien); + writel(0, &pdev->adma_regs->ep_ien); + spin_unlock_irqrestore(&pdev->lock, flags); + + return 0; +} + +int cdns2_gadget_resume(struct cdns2_device *pdev, bool hibernated) +{ + unsigned long flags; + + spin_lock_irqsave(&pdev->lock, flags); + + if (!pdev->gadget_driver) { + spin_unlock_irqrestore(&pdev->lock, flags); + return 0; + } + + cdns2_gadget_config(pdev); + + if (hibernated) + clear_reg_bit_8(&pdev->usb_regs->usbcs, USBCS_DISCON); + + spin_unlock_irqrestore(&pdev->lock, flags); + + return 0; +} + +void cdns2_gadget_remove(struct cdns2_device *pdev) +{ + pm_runtime_mark_last_busy(pdev->dev); + pm_runtime_put_autosuspend(pdev->dev); + + usb_del_gadget(&pdev->gadget); + cdns2_free_all_eps(pdev); + + dma_pool_destroy(pdev->eps_dma_pool); + kfree(pdev->zlp_buf); + usb_put_gadget(&pdev->gadget); +} + +int cdns2_gadget_init(struct cdns2_device *pdev) +{ + int ret; + + /* Ensure 32-bit DMA Mask. */ + ret = dma_set_mask_and_coherent(pdev->dev, DMA_BIT_MASK(32)); + if (ret) { + dev_err(pdev->dev, "Failed to set dma mask: %d\n", ret); + return ret; + } + + pm_runtime_get_sync(pdev->dev); + + cdsn2_isoc_burst_opt(pdev); + + ret = cdns2_gadget_start(pdev); + if (ret) { + pm_runtime_put_sync(pdev->dev); + return ret; + } + + /* + * Because interrupt line can be shared with other components in + * driver it can't use IRQF_ONESHOT flag here. + */ + ret = devm_request_threaded_irq(pdev->dev, pdev->irq, + cdns2_usb_irq_handler, + cdns2_thread_irq_handler, + IRQF_SHARED, + dev_name(pdev->dev), + pdev); + if (ret) + goto err0; + + return 0; + +err0: + cdns2_gadget_remove(pdev); + + return ret; +} diff --git a/drivers/usb/gadget/udc/cdns2/cdns2-gadget.h b/drivers/usb/gadget/udc/cdns2/cdns2-gadget.h new file mode 100644 index 0000000000000000000000000000000000000000..71e2f62d653a51f81e9542b93c2865cafe828223 --- /dev/null +++ b/drivers/usb/gadget/udc/cdns2/cdns2-gadget.h @@ -0,0 +1,707 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * USBHS-DEV device controller driver header file + * + * Copyright (C) 2023 Cadence. + * + * Author: Pawel Laszczak + */ + +#ifndef __LINUX_CDNS2_GADGET +#define __LINUX_CDNS2_GADGET + +#include +#include + +/* + * USBHS register interface. + * This corresponds to the USBHS Device Controller Interface. + */ + +/** + * struct cdns2_ep0_regs - endpoint 0 related registers. + * @rxbc: receive (OUT) 0 endpoint byte count register. + * @txbc: transmit (IN) 0 endpoint byte count register. + * @cs: 0 endpoint control and status register. + * @reserved1: reserved. + * @fifo: 0 endpoint fifo register. + * @reserved2: reserved. + * @setupdat: SETUP data register. + * @reserved4: reserved. + * @maxpack: 0 endpoint max packet size. + */ +struct cdns2_ep0_regs { + __u8 rxbc; + __u8 txbc; + __u8 cs; + __u8 reserved1[4]; + __u8 fifo; + __le32 reserved2[94]; + __u8 setupdat[8]; + __u8 reserved4[88]; + __u8 maxpack; +} __packed __aligned(4); + +/* EP0CS - bitmasks. */ +/* Endpoint 0 stall bit for status stage. */ +#define EP0CS_STALL BIT(0) +/* HSNAK bit. */ +#define EP0CS_HSNAK BIT(1) +/* IN 0 endpoint busy bit. */ +#define EP0CS_TXBSY_MSK BIT(2) +/* OUT 0 endpoint busy bit. */ +#define EP0CS_RXBSY_MSK BIT(3) +/* Send STALL in the data stage phase. */ +#define EP0CS_DSTALL BIT(4) +/* SETUP buffer content was changed. */ +#define EP0CS_CHGSET BIT(7) + +/* EP0FIFO - bitmasks. */ +/* Direction. */ +#define EP0_FIFO_IO_TX BIT(4) +/* FIFO auto bit. */ +#define EP0_FIFO_AUTO BIT(5) +/* FIFO commit bit. */ +#define EP0_FIFO_COMMIT BIT(6) +/* FIFO access bit. */ +#define EP0_FIFO_ACCES BIT(7) + +/** + * struct cdns2_epx_base - base endpoint registers. + * @rxbc: OUT endpoint byte count register. + * @rxcon: OUT endpoint control register. + * @rxcs: OUT endpoint control and status register. + * @txbc: IN endpoint byte count register. + * @txcon: IN endpoint control register. + * @txcs: IN endpoint control and status register. + */ +struct cdns2_epx_base { + __le16 rxbc; + __u8 rxcon; + __u8 rxcs; + __le16 txbc; + __u8 txcon; + __u8 txcs; +} __packed __aligned(4); + +/* rxcon/txcon - endpoint control register bitmasks. */ +/* Endpoint buffering: 0 - single buffering ... 3 - quad buffering. */ +#define EPX_CON_BUF GENMASK(1, 0) +/* Endpoint type. */ +#define EPX_CON_TYPE GENMASK(3, 2) +/* Endpoint type: isochronous. */ +#define EPX_CON_TYPE_ISOC 0x4 +/* Endpoint type: bulk. */ +#define EPX_CON_TYPE_BULK 0x8 +/* Endpoint type: interrupt. */ +#define EPX_CON_TYPE_INT 0xC +/* Number of packets per microframe. */ +#define EPX_CON_ISOD GENMASK(5, 4) +#define EPX_CON_ISOD_SHIFT 0x4 +/* Endpoint stall bit. */ +#define EPX_CON_STALL BIT(6) +/* Endpoint enable bit.*/ +#define EPX_CON_VAL BIT(7) + +/* rxcs/txcs - endpoint control and status bitmasks. */ +/* Data sequence error for the ISO endpoint. */ +#define EPX_CS_ERR(p) ((p) & BIT(0)) + +/** + * struct cdns2_epx_regs - endpoint 1..15 related registers. + * @reserved: reserved. + * @ep: none control endpoints array. + * @reserved2: reserved. + * @endprst: endpoint reset register. + * @reserved3: reserved. + * @isoautoarm: ISO auto-arm register. + * @reserved4: reserved. + * @isodctrl: ISO control register. + * @reserved5: reserved. + * @isoautodump: ISO auto dump enable register. + * @reserved6: reserved. + * @rxmaxpack: receive (OUT) Max packet size register. + * @reserved7: reserved. + * @rxstaddr: receive (OUT) start address endpoint buffer register. + * @reserved8: reserved. + * @txstaddr: transmit (IN) start address endpoint buffer register. + * @reserved9: reserved. + * @txmaxpack: transmit (IN) Max packet size register. + */ +struct cdns2_epx_regs { + __le32 reserved[2]; + struct cdns2_epx_base ep[15]; + __u8 reserved2[290]; + __u8 endprst; + __u8 reserved3[41]; + __le16 isoautoarm; + __u8 reserved4[10]; + __le16 isodctrl; + __le16 reserved5; + __le16 isoautodump; + __le32 reserved6; + __le16 rxmaxpack[15]; + __le32 reserved7[65]; + __le32 rxstaddr[15]; + __u8 reserved8[4]; + __le32 txstaddr[15]; + __u8 reserved9[98]; + __le16 txmaxpack[15]; +} __packed __aligned(4); + +/* ENDPRST - bitmasks. */ +/* Endpoint number. */ +#define ENDPRST_EP GENMASK(3, 0) +/* IN direction bit. */ +#define ENDPRST_IO_TX BIT(4) +/* Toggle reset bit. */ +#define ENDPRST_TOGRST BIT(5) +/* FIFO reset bit. */ +#define ENDPRST_FIFORST BIT(6) +/* Toggle status and reset bit. */ +#define ENDPRST_TOGSETQ BIT(7) + +/** + * struct cdns2_interrupt_regs - USB interrupt related registers. + * @reserved: reserved. + * @usbirq: USB interrupt request register. + * @extirq: external interrupt request register. + * @rxpngirq: external interrupt request register. + * @reserved1: reserved. + * @usbien: USB interrupt enable register. + * @extien: external interrupt enable register. + * @reserved2: reserved. + * @usbivect: USB interrupt vector register. + */ +struct cdns2_interrupt_regs { + __u8 reserved[396]; + __u8 usbirq; + __u8 extirq; + __le16 rxpngirq; + __le16 reserved1[4]; + __u8 usbien; + __u8 extien; + __le16 reserved2[3]; + __u8 usbivect; +} __packed __aligned(4); + +/* EXTIRQ and EXTIEN - bitmasks. */ +/* VBUS fault fall interrupt. */ +#define EXTIRQ_VBUSFAULT_FALL BIT(0) +/* VBUS fault fall interrupt. */ +#define EXTIRQ_VBUSFAULT_RISE BIT(1) +/* Wake up interrupt bit. */ +#define EXTIRQ_WAKEUP BIT(7) + +/* USBIEN and USBIRQ - bitmasks. */ +/* SETUP data valid interrupt bit.*/ +#define USBIRQ_SUDAV BIT(0) +/* Start-of-frame interrupt bit. */ +#define USBIRQ_SOF BIT(1) +/* SETUP token interrupt bit. */ +#define USBIRQ_SUTOK BIT(2) +/* USB suspend interrupt bit. */ +#define USBIRQ_SUSPEND BIT(3) +/* USB reset interrupt bit. */ +#define USBIRQ_URESET BIT(4) +/* USB high-speed mode interrupt bit. */ +#define USBIRQ_HSPEED BIT(5) +/* Link Power Management interrupt bit. */ +#define USBIRQ_LPM BIT(7) + +#define USB_IEN_INIT (USBIRQ_SUDAV | USBIRQ_SUSPEND | USBIRQ_URESET \ + | USBIRQ_HSPEED | USBIRQ_LPM) +/** + * struct cdns2_usb_regs - USB controller registers. + * @reserved: reserved. + * @lpmctrl: LPM control register. + * @lpmclock: LPM clock register. + * @reserved2: reserved. + * @endprst: endpoint reset register. + * @usbcs: USB control and status register. + * @frmnr: USB frame counter register. + * @fnaddr: function Address register. + * @clkgate: clock gate register. + * @fifoctrl: FIFO control register. + * @speedctrl: speed Control register. + * @sleep_clkgate: sleep Clock Gate register. + * @reserved3: reserved. + * @cpuctrl: microprocessor control register. + */ +struct cdns2_usb_regs { + __u8 reserved[4]; + __u16 lpmctrl; + __u8 lpmclock; + __u8 reserved2[411]; + __u8 endprst; + __u8 usbcs; + __le16 frmnr; + __u8 fnaddr; + __u8 clkgate; + __u8 fifoctrl; + __u8 speedctrl; + __u8 sleep_clkgate; + __u8 reserved3[533]; + __u8 cpuctrl; +} __packed __aligned(4); + +/* LPMCTRL - bitmasks. */ +/* BESL (Best Effort Service Latency). */ +#define LPMCTRLLL_HIRD GENMASK(7, 4) +/* Last received Remote Wakeup field from LPM Extended Token packet. */ +#define LPMCTRLLH_BREMOTEWAKEUP BIT(8) +/* Reflects value of the lpmnyet bit located in the usbcs[1] register. */ +#define LPMCTRLLH_LPMNYET BIT(16) + +/* LPMCLOCK - bitmasks. */ +/* + * If bit is 1 the controller automatically turns off clock + * (utmisleepm goes to low), else the microprocessor should use + * sleep clock gate register to turn off clock. + */ +#define LPMCLOCK_SLEEP_ENTRY BIT(7) + +/* USBCS - bitmasks. */ +/* Send NYET handshake for the LPM transaction. */ +#define USBCS_LPMNYET BIT(2) +/* Remote wake-up bit. */ +#define USBCS_SIGRSUME BIT(5) +/* Software disconnect bit. */ +#define USBCS_DISCON BIT(6) +/* Indicates that a wakeup pin resumed the controller. */ +#define USBCS_WAKESRC BIT(7) + +/* FIFOCTRL - bitmasks. */ +/* Endpoint number. */ +#define FIFOCTRL_EP GENMASK(3, 0) +/* Direction bit. */ +#define FIFOCTRL_IO_TX BIT(4) +/* FIFO auto bit. */ +#define FIFOCTRL_FIFOAUTO BIT(5) +/* FIFO commit bit. */ +#define FIFOCTRL_FIFOCMIT BIT(6) +/* FIFO access bit. */ +#define FIFOCTRL_FIFOACC BIT(7) + +/* SPEEDCTRL - bitmasks. */ +/* Device works in Full Speed. */ +#define SPEEDCTRL_FS BIT(1) +/* Device works in High Speed. */ +#define SPEEDCTRL_HS BIT(2) +/* Force FS mode. */ +#define SPEEDCTRL_HSDISABLE BIT(7) + +/* CPUCTRL- bitmasks. */ +/* Controller reset bit. */ +#define CPUCTRL_SW_RST BIT(1) + +/** + * struct cdns2_adma_regs - ADMA controller registers. + * @conf: DMA global configuration register. + * @sts: DMA global Status register. + * @reserved1: reserved. + * @ep_sel: DMA endpoint select register. + * @ep_traddr: DMA endpoint transfer ring address register. + * @ep_cfg: DMA endpoint configuration register. + * @ep_cmd: DMA endpoint command register. + * @ep_sts: DMA endpoint status register. + * @reserved2: reserved. + * @ep_sts_en: DMA endpoint status enable register. + * @drbl: DMA doorbell register. + * @ep_ien: DMA endpoint interrupt enable register. + * @ep_ists: DMA endpoint interrupt status register. + * @axim_ctrl: AXI Master Control register. + * @axim_id: AXI Master ID register. + * @reserved3: reserved. + * @axim_cap: AXI Master Wrapper Extended Capability. + * @reserved4: reserved. + * @axim_ctrl0: AXI Master Wrapper Extended Capability Control Register 0. + * @axim_ctrl1: AXI Master Wrapper Extended Capability Control Register 1. + */ +struct cdns2_adma_regs { + __le32 conf; + __le32 sts; + __le32 reserved1[5]; + __le32 ep_sel; + __le32 ep_traddr; + __le32 ep_cfg; + __le32 ep_cmd; + __le32 ep_sts; + __le32 reserved2; + __le32 ep_sts_en; + __le32 drbl; + __le32 ep_ien; + __le32 ep_ists; + __le32 axim_ctrl; + __le32 axim_id; + __le32 reserved3; + __le32 axim_cap; + __le32 reserved4; + __le32 axim_ctrl0; + __le32 axim_ctrl1; +}; + +#define CDNS2_ADMA_REGS_OFFSET 0x400 + +/* DMA_CONF - bitmasks. */ +/* Reset USB device configuration. */ +#define DMA_CONF_CFGRST BIT(0) +/* Singular DMA transfer mode.*/ +#define DMA_CONF_DSING BIT(8) +/* Multiple DMA transfers mode.*/ +#define DMA_CONF_DMULT BIT(9) + +/* DMA_EP_CFG - bitmasks. */ +/* Endpoint enable. */ +#define DMA_EP_CFG_ENABLE BIT(0) + +/* DMA_EP_CMD - bitmasks. */ +/* Endpoint reset. */ +#define DMA_EP_CMD_EPRST BIT(0) +/* Transfer descriptor ready. */ +#define DMA_EP_CMD_DRDY BIT(6) +/* Data flush. */ +#define DMA_EP_CMD_DFLUSH BIT(7) + +/* DMA_EP_STS - bitmasks. */ +/* Interrupt On Complete. */ +#define DMA_EP_STS_IOC BIT(2) +/* Interrupt on Short Packet. */ +#define DMA_EP_STS_ISP BIT(3) +/* Transfer descriptor missing. */ +#define DMA_EP_STS_DESCMIS BIT(4) +/* TRB error. */ +#define DMA_EP_STS_TRBERR BIT(7) +/* DMA busy bit. */ +#define DMA_EP_STS_DBUSY BIT(9) +/* Current Cycle Status. */ +#define DMA_EP_STS_CCS(p) ((p) & BIT(11)) +/* OUT size mismatch. */ +#define DMA_EP_STS_OUTSMM BIT(14) +/* ISO transmission error. */ +#define DMA_EP_STS_ISOERR BIT(15) + +/* DMA_EP_STS_EN - bitmasks. */ +/* OUT transfer missing descriptor enable. */ +#define DMA_EP_STS_EN_DESCMISEN BIT(4) +/* TRB enable. */ +#define DMA_EP_STS_EN_TRBERREN BIT(7) +/* OUT size mismatch enable. */ +#define DMA_EP_STS_EN_OUTSMMEN BIT(14) +/* ISO transmission error enable. */ +#define DMA_EP_STS_EN_ISOERREN BIT(15) + +/* DMA_EP_IEN - bitmasks. */ +#define DMA_EP_IEN(index) (1 << (index)) +#define DMA_EP_IEN_EP_OUT0 BIT(0) +#define DMA_EP_IEN_EP_IN0 BIT(16) + +/* DMA_EP_ISTS - bitmasks. */ +#define DMA_EP_ISTS(index) (1 << (index)) +#define DMA_EP_ISTS_EP_OUT0 BIT(0) +#define DMA_EP_ISTS_EP_IN0 BIT(16) + +#define gadget_to_cdns2_device(g) (container_of(g, struct cdns2_device, gadget)) +#define ep_to_cdns2_ep(ep) (container_of(ep, struct cdns2_endpoint, endpoint)) + +/*-------------------------------------------------------------------------*/ +#define TRBS_PER_SEGMENT 600 +#define ISO_MAX_INTERVAL 8 +#define MAX_TRB_LENGTH BIT(16) +#define MAX_ISO_SIZE 3076 +/* + * To improve performance the TRB buffer pointers can't cross + * 4KB boundaries. + */ +#define TRB_MAX_ISO_BUFF_SHIFT 12 +#define TRB_MAX_ISO_BUFF_SIZE BIT(TRB_MAX_ISO_BUFF_SHIFT) +/* How much data is left before the 4KB boundary? */ +#define TRB_BUFF_LEN_UP_TO_BOUNDARY(addr) (TRB_MAX_ISO_BUFF_SIZE - \ + ((addr) & (TRB_MAX_ISO_BUFF_SIZE - 1))) + +#if TRBS_PER_SEGMENT < 2 +#error "Incorrect TRBS_PER_SEGMENT. Minimal Transfer Ring size is 2." +#endif + +/** + * struct cdns2_trb - represent Transfer Descriptor block. + * @buffer: pointer to buffer data. + * @length: length of data. + * @control: control flags. + * + * This structure describes transfer block handled by DMA module. + */ +struct cdns2_trb { + __le32 buffer; + __le32 length; + __le32 control; +}; + +#define TRB_SIZE (sizeof(struct cdns2_trb)) +/* + * These two extra TRBs are reserved for isochronous transfer + * to inject 0 length packet and extra LINK TRB to synchronize the ISO transfer. + */ +#define TRB_ISO_RESERVED 2 +#define TR_SEG_SIZE (TRB_SIZE * (TRBS_PER_SEGMENT + TRB_ISO_RESERVED)) + +/* TRB bit mask. */ +#define TRB_TYPE_BITMASK GENMASK(15, 10) +#define TRB_TYPE(p) ((p) << 10) +#define TRB_FIELD_TO_TYPE(p) (((p) & TRB_TYPE_BITMASK) >> 10) + +/* TRB type IDs. */ +/* Used for Bulk, Interrupt, ISOC, and control data stage. */ +#define TRB_NORMAL 1 +/* TRB for linking ring segments. */ +#define TRB_LINK 6 + +/* Cycle bit - indicates TRB ownership by driver or hw. */ +#define TRB_CYCLE BIT(0) +/* + * When set to '1', the device will toggle its interpretation of the Cycle bit. + */ +#define TRB_TOGGLE BIT(1) +/* Interrupt on short packet. */ +#define TRB_ISP BIT(2) +/* Chain bit associate this TRB with next one TRB. */ +#define TRB_CHAIN BIT(4) +/* Interrupt on completion. */ +#define TRB_IOC BIT(5) + +/* Transfer_len bitmasks. */ +#define TRB_LEN(p) ((p) & GENMASK(16, 0)) +#define TRB_BURST(p) (((p) << 24) & GENMASK(31, 24)) +#define TRB_FIELD_TO_BURST(p) (((p) & GENMASK(31, 24)) >> 24) + +/* Data buffer pointer bitmasks. */ +#define TRB_BUFFER(p) ((p) & GENMASK(31, 0)) + +/*-------------------------------------------------------------------------*/ +/* Driver numeric constants. */ + +/* Maximum address that can be assigned to device. */ +#define USB_DEVICE_MAX_ADDRESS 127 + +/* One control and 15 IN and 15 OUT endpoints. */ +#define CDNS2_ENDPOINTS_NUM 31 + +#define CDNS2_EP_ZLP_BUF_SIZE 512 + +/*-------------------------------------------------------------------------*/ +/* Used structures. */ + +struct cdns2_device; + +/** + * struct cdns2_ring - transfer ring representation. + * @trbs: pointer to transfer ring. + * @dma: dma address of transfer ring. + * @free_trbs: number of free TRBs in transfer ring. + * @pcs: producer cycle state. + * @ccs: consumer cycle state. + * @enqueue: enqueue index in transfer ring. + * @dequeue: dequeue index in transfer ring. + */ +struct cdns2_ring { + struct cdns2_trb *trbs; + dma_addr_t dma; + int free_trbs; + u8 pcs; + u8 ccs; + int enqueue; + int dequeue; +}; + +/** + * struct cdns2_endpoint - extended device side representation of USB endpoint. + * @endpoint: usb endpoint. + * @pending_list: list of requests queuing on transfer ring. + * @deferred_list: list of requests waiting for queuing on transfer ring. + * @pdev: device associated with endpoint. + * @name: a human readable name e.g. ep1out. + * @ring: transfer ring associated with endpoint. + * @ep_state: state of endpoint. + * @idx: index of endpoint in pdev->eps table. + * @dir: endpoint direction. + * @num: endpoint number (1 - 15). + * @type: set to bmAttributes & USB_ENDPOINT_XFERTYPE_MASK. + * @interval: interval between packets used for ISOC and Interrupt endpoint. + * @buffering: on-chip buffers assigned to endpoint. + * @trb_burst_size: number of burst used in TRB. + * @skip: Sometimes the controller cannot process isochronous endpoint ring + * quickly enough and it will miss some isoc tds on the ring and + * generate ISO transmition error. + * Driver sets skip flag when receive a ISO transmition error and + * process the missed TDs on the endpoint ring. + * @wa1_set: use WA1. + * @wa1_trb: TRB assigned to WA1. + * @wa1_trb_index: TRB index for WA1. + * @wa1_cycle_bit: correct cycle bit for WA1. + */ +struct cdns2_endpoint { + struct usb_ep endpoint; + struct list_head pending_list; + struct list_head deferred_list; + + struct cdns2_device *pdev; + char name[20]; + + struct cdns2_ring ring; + +#define EP_ENABLED BIT(0) +#define EP_STALLED BIT(1) +#define EP_STALL_PENDING BIT(2) +#define EP_WEDGE BIT(3) +#define EP_CLAIMED BIT(4) +#define EP_RING_FULL BIT(5) +#define EP_DEFERRED_DRDY BIT(6) + + u32 ep_state; + + u8 idx; + u8 dir; + u8 num; + u8 type; + int interval; + u8 buffering; + u8 trb_burst_size; + bool skip; + + unsigned int wa1_set:1; + struct cdns2_trb *wa1_trb; + unsigned int wa1_trb_index; + unsigned int wa1_cycle_bit:1; +}; + +/** + * struct cdns2_request - extended device side representation of usb_request + * object. + * @request: generic usb_request object describing single I/O request. + * @pep: extended representation of usb_ep object. + * @trb: the first TRB association with this request. + * @start_trb: number of the first TRB in transfer ring. + * @end_trb: number of the last TRB in transfer ring. + * @list: used for queuing request in lists. + * @finished_trb: number of trb has already finished per request. + * @num_of_trb: how many trbs are associated with request. + */ +struct cdns2_request { + struct usb_request request; + struct cdns2_endpoint *pep; + struct cdns2_trb *trb; + int start_trb; + int end_trb; + struct list_head list; + int finished_trb; + int num_of_trb; +}; + +#define to_cdns2_request(r) (container_of(r, struct cdns2_request, request)) + +/* Stages used during enumeration process.*/ +#define CDNS2_SETUP_STAGE 0x0 +#define CDNS2_DATA_STAGE 0x1 +#define CDNS2_STATUS_STAGE 0x2 + +/** + * struct cdns2_device - represent USB device. + * @dev: pointer to device structure associated whit this controller. + * @gadget: device side representation of the peripheral controller. + * @gadget_driver: pointer to the gadget driver. + * @lock: for synchronizing. + * @irq: interrupt line number. + * @regs: base address for registers + * @usb_regs: base address for common USB registers. + * @ep0_regs: base address for endpoint 0 related registers. + * @epx_regs: base address for all none control endpoint registers. + * @interrupt_regs: base address for interrupt handling related registers. + * @adma_regs: base address for ADMA registers. + * @eps_dma_pool: endpoint Transfer Ring pool. + * @setup: used while processing usb control requests. + * @ep0_preq: private request used while handling EP0. + * @ep0_stage: ep0 stage during enumeration process. + * @zlp_buf: zlp buffer. + * @dev_address: device address assigned by host. + * @eps: array of objects describing endpoints. + * @selected_ep: actually selected endpoint. It's used only to improve + * performance by limiting access to dma_ep_sel register. + * @is_selfpowered: device is self powered. + * @may_wakeup: allows device to remote wakeup the host. + * @status_completion_no_call: indicate that driver is waiting for status + * stage completion. It's used in deferred SET_CONFIGURATION request. + * @in_lpm: indicate the controller is in low power mode. + * @pending_status_wq: workqueue handling status stage for deferred requests. + * @pending_status_request: request for which status stage was deferred. + * @eps_supported: endpoints supported by controller in form: + * bit: 0 - ep0, 1 - epOut1, 2 - epIn1, 3 - epOut2 ... + * @burst_opt: array with the best burst size value for different TRB size. + * @onchip_tx_buf: size of transmit on-chip buffer in KB. + * @onchip_rx_buf: size of receive on-chip buffer in KB. + */ +struct cdns2_device { + struct device *dev; + struct usb_gadget gadget; + struct usb_gadget_driver *gadget_driver; + + /* generic spin-lock for drivers */ + spinlock_t lock; + int irq; + void __iomem *regs; + struct cdns2_usb_regs __iomem *usb_regs; + struct cdns2_ep0_regs __iomem *ep0_regs; + struct cdns2_epx_regs __iomem *epx_regs; + struct cdns2_interrupt_regs __iomem *interrupt_regs; + struct cdns2_adma_regs __iomem *adma_regs; + struct dma_pool *eps_dma_pool; + struct usb_ctrlrequest setup; + struct cdns2_request ep0_preq; + u8 ep0_stage; + void *zlp_buf; + u8 dev_address; + struct cdns2_endpoint eps[CDNS2_ENDPOINTS_NUM]; + u32 selected_ep; + bool is_selfpowered; + bool may_wakeup; + bool status_completion_no_call; + bool in_lpm; + struct work_struct pending_status_wq; + struct usb_request *pending_status_request; + u32 eps_supported; + u8 burst_opt[MAX_ISO_SIZE + 1]; + + /*in KB */ + u16 onchip_tx_buf; + u16 onchip_rx_buf; +}; + +#define CDNS2_IF_EP_EXIST(pdev, ep_num, dir) \ + ((pdev)->eps_supported & \ + (BIT(ep_num) << ((dir) ? 0 : 16))) + +dma_addr_t cdns2_trb_virt_to_dma(struct cdns2_endpoint *pep, + struct cdns2_trb *trb); +void cdns2_pending_setup_status_handler(struct work_struct *work); +void cdns2_select_ep(struct cdns2_device *pdev, u32 ep); +struct cdns2_request *cdns2_next_preq(struct list_head *list); +struct usb_request *cdns2_gadget_ep_alloc_request(struct usb_ep *ep, + gfp_t gfp_flags); +void cdns2_gadget_ep_free_request(struct usb_ep *ep, + struct usb_request *request); +int cdns2_gadget_ep_dequeue(struct usb_ep *ep, struct usb_request *request); +void cdns2_gadget_giveback(struct cdns2_endpoint *pep, + struct cdns2_request *priv_req, + int status); +void cdns2_init_ep0(struct cdns2_device *pdev, struct cdns2_endpoint *pep); +void cdns2_ep0_config(struct cdns2_device *pdev); +void cdns2_handle_ep0_interrupt(struct cdns2_device *pdev, int dir); +void cdns2_handle_setup_packet(struct cdns2_device *pdev); +int cdns2_gadget_resume(struct cdns2_device *pdev, bool hibernated); +int cdns2_gadget_suspend(struct cdns2_device *pdev); +void cdns2_gadget_remove(struct cdns2_device *pdev); +int cdns2_gadget_init(struct cdns2_device *pdev); +void set_reg_bit_8(void __iomem *ptr, u8 mask); +int cdns2_halt_endpoint(struct cdns2_device *pdev, struct cdns2_endpoint *pep, + int value); + +#endif /* __LINUX_CDNS2_GADGET */ diff --git a/drivers/usb/gadget/udc/cdns2/cdns2-pci.c b/drivers/usb/gadget/udc/cdns2/cdns2-pci.c new file mode 100644 index 0000000000000000000000000000000000000000..1691541c9413819f9f711422d3a6fb883fe4c4f0 --- /dev/null +++ b/drivers/usb/gadget/udc/cdns2/cdns2-pci.c @@ -0,0 +1,138 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Cadence USBHS-DEV controller - PCI Glue driver. + * + * Copyright (C) 2023 Cadence. + * + * Author: Pawel Laszczak + * + */ + +#include +#include +#include + +#include "cdns2-gadget.h" + +#define PCI_DRIVER_NAME "cdns-pci-usbhs" +#define CDNS_VENDOR_ID 0x17cd +#define CDNS_DEVICE_ID 0x0120 +#define PCI_BAR_DEV 0 +#define PCI_DEV_FN_DEVICE 0 + +static int cdns2_pci_probe(struct pci_dev *pdev, + const struct pci_device_id *id) +{ + resource_size_t rsrc_start, rsrc_len; + struct device *dev = &pdev->dev; + struct cdns2_device *priv_dev; + struct resource *res; + int ret; + + /* For GADGET PCI (devfn) function number is 0. */ + if (!id || pdev->devfn != PCI_DEV_FN_DEVICE || + pdev->class != PCI_CLASS_SERIAL_USB_DEVICE) + return -EINVAL; + + ret = pcim_enable_device(pdev); + if (ret) { + dev_err(&pdev->dev, "Enabling PCI device has failed %d\n", ret); + return ret; + } + + pci_set_master(pdev); + + priv_dev = devm_kzalloc(&pdev->dev, sizeof(*priv_dev), GFP_KERNEL); + if (!priv_dev) + return -ENOMEM; + + dev_dbg(dev, "Initialize resources\n"); + rsrc_start = pci_resource_start(pdev, PCI_BAR_DEV); + rsrc_len = pci_resource_len(pdev, PCI_BAR_DEV); + + res = devm_request_mem_region(dev, rsrc_start, rsrc_len, "dev"); + if (!res) { + dev_dbg(dev, "controller already in use\n"); + return -EBUSY; + } + + priv_dev->regs = devm_ioremap(dev, rsrc_start, rsrc_len); + if (!priv_dev->regs) { + dev_dbg(dev, "error mapping memory\n"); + return -EFAULT; + } + + priv_dev->irq = pdev->irq; + dev_dbg(dev, "USBSS-DEV physical base addr: %pa\n", + &rsrc_start); + + priv_dev->dev = dev; + + priv_dev->eps_supported = 0x000f000f; + priv_dev->onchip_tx_buf = 16; + priv_dev->onchip_rx_buf = 16; + + ret = cdns2_gadget_init(priv_dev); + if (ret) + return ret; + + pci_set_drvdata(pdev, priv_dev); + + device_wakeup_enable(&pdev->dev); + if (pci_dev_run_wake(pdev)) + pm_runtime_put_noidle(&pdev->dev); + + return 0; +} + +static void cdns2_pci_remove(struct pci_dev *pdev) +{ + struct cdns2_device *priv_dev = pci_get_drvdata(pdev); + + if (pci_dev_run_wake(pdev)) + pm_runtime_get_noresume(&pdev->dev); + + cdns2_gadget_remove(priv_dev); +} + +static int cdns2_pci_suspend(struct device *dev) +{ + struct cdns2_device *priv_dev = dev_get_drvdata(dev); + + return cdns2_gadget_suspend(priv_dev); +} + +static int cdns2_pci_resume(struct device *dev) +{ + struct cdns2_device *priv_dev = dev_get_drvdata(dev); + + return cdns2_gadget_resume(priv_dev, 1); +} + +static const struct dev_pm_ops cdns2_pci_pm_ops = { + SYSTEM_SLEEP_PM_OPS(cdns2_pci_suspend, cdns2_pci_resume) +}; + +static const struct pci_device_id cdns2_pci_ids[] = { + { PCI_VENDOR_ID_CDNS, CDNS_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, + PCI_CLASS_SERIAL_USB_DEVICE, PCI_ANY_ID }, + { 0, } +}; + +static struct pci_driver cdns2_pci_driver = { + .name = "cdns2-pci", + .id_table = &cdns2_pci_ids[0], + .probe = cdns2_pci_probe, + .remove = cdns2_pci_remove, + .driver = { + .pm = pm_ptr(&cdns2_pci_pm_ops), + } +}; + +module_pci_driver(cdns2_pci_driver); +MODULE_DEVICE_TABLE(pci, cdns2_pci_ids); + +MODULE_ALIAS("pci:cdns2"); +MODULE_AUTHOR("Pawel Laszczak "); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Cadence CDNS2 PCI driver"); diff --git a/drivers/usb/gadget/udc/cdns2/cdns2-trace.c b/drivers/usb/gadget/udc/cdns2/cdns2-trace.c new file mode 100644 index 0000000000000000000000000000000000000000..de6b8cc3d07152320f12b75331eabcf12265212f --- /dev/null +++ b/drivers/usb/gadget/udc/cdns2/cdns2-trace.c @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * USBHS device controller driver Trace Support + * + * Copyright (C) 2023 Cadence. + * + * Author: Pawel Laszczak + */ + +#define CREATE_TRACE_POINTS +#include "cdns2-trace.h" diff --git a/drivers/usb/gadget/udc/cdns2/cdns2-trace.h b/drivers/usb/gadget/udc/cdns2/cdns2-trace.h new file mode 100644 index 0000000000000000000000000000000000000000..61f241634ea56109be5730143c9835d38da7c8e9 --- /dev/null +++ b/drivers/usb/gadget/udc/cdns2/cdns2-trace.h @@ -0,0 +1,605 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * USBHS-DEV device controller driver. + * Trace support header file. + * + * Copyright (C) 2023 Cadence. + * + * Author: Pawel Laszczak + */ + +#undef TRACE_SYSTEM +#define TRACE_SYSTEM cdns2-dev + +/* + * The TRACE_SYSTEM_VAR defaults to TRACE_SYSTEM, but must be a + * legitimate C variable. It is not exported to user space. + */ +#undef TRACE_SYSTEM_VAR +#define TRACE_SYSTEM_VAR cdns2_dev + +#if !defined(__LINUX_CDNS2_TRACE) || defined(TRACE_HEADER_MULTI_READ) +#define __LINUX_CDNS2_TRACE + +#include +#include +#include +#include +#include "cdns2-gadget.h" +#include "cdns2-debug.h" + +#define CDNS2_MSG_MAX 500 + +DECLARE_EVENT_CLASS(cdns2_log_enable_disable, + TP_PROTO(int set), + TP_ARGS(set), + TP_STRUCT__entry( + __field(int, set) + ), + TP_fast_assign( + __entry->set = set; + ), + TP_printk("%s", __entry->set ? "enabled" : "disabled") +); + +DEFINE_EVENT(cdns2_log_enable_disable, cdns2_pullup, + TP_PROTO(int set), + TP_ARGS(set) +); + +DEFINE_EVENT(cdns2_log_enable_disable, cdns2_lpm, + TP_PROTO(int set), + TP_ARGS(set) +); + +DEFINE_EVENT(cdns2_log_enable_disable, cdns2_may_wakeup, + TP_PROTO(int set), + TP_ARGS(set) +); + +DECLARE_EVENT_CLASS(cdns2_log_simple, + TP_PROTO(char *msg), + TP_ARGS(msg), + TP_STRUCT__entry( + __string(text, msg) + ), + TP_fast_assign( + __assign_str(text, msg); + ), + TP_printk("%s", __get_str(text)) +); + +DEFINE_EVENT(cdns2_log_simple, cdns2_no_room_on_ring, + TP_PROTO(char *msg), + TP_ARGS(msg) +); + +DEFINE_EVENT(cdns2_log_simple, cdns2_ep0_status_stage, + TP_PROTO(char *msg), + TP_ARGS(msg) +); + +DEFINE_EVENT(cdns2_log_simple, cdns2_ep0_set_config, + TP_PROTO(char *msg), + TP_ARGS(msg) +); + +DEFINE_EVENT(cdns2_log_simple, cdns2_ep0_setup, + TP_PROTO(char *msg), + TP_ARGS(msg) +); + +DEFINE_EVENT(cdns2_log_simple, cdns2_device_state, + TP_PROTO(char *msg), + TP_ARGS(msg) +); + +TRACE_EVENT(cdns2_ep_halt, + TP_PROTO(struct cdns2_endpoint *ep_priv, u8 halt, u8 flush), + TP_ARGS(ep_priv, halt, flush), + TP_STRUCT__entry( + __string(name, ep_priv->name) + __field(u8, halt) + __field(u8, flush) + ), + TP_fast_assign( + __assign_str(name, ep_priv->name); + __entry->halt = halt; + __entry->flush = flush; + ), + TP_printk("Halt %s for %s: %s", __entry->flush ? " and flush" : "", + __get_str(name), __entry->halt ? "set" : "cleared") +); + +TRACE_EVENT(cdns2_wa1, + TP_PROTO(struct cdns2_endpoint *ep_priv, char *msg), + TP_ARGS(ep_priv, msg), + TP_STRUCT__entry( + __string(ep_name, ep_priv->name) + __string(msg, msg) + ), + TP_fast_assign( + __assign_str(ep_name, ep_priv->name); + __assign_str(msg, msg); + ), + TP_printk("WA1: %s %s", __get_str(ep_name), __get_str(msg)) +); + +DECLARE_EVENT_CLASS(cdns2_log_doorbell, + TP_PROTO(struct cdns2_endpoint *pep, u32 ep_trbaddr), + TP_ARGS(pep, ep_trbaddr), + TP_STRUCT__entry( + __string(name, pep->num ? pep->name : + (pep->dir ? "ep0in" : "ep0out")) + __field(u32, ep_trbaddr) + ), + TP_fast_assign( + __assign_str(name, pep->name); + __entry->ep_trbaddr = ep_trbaddr; + ), + TP_printk("%s, ep_trbaddr %08x", __get_str(name), + __entry->ep_trbaddr) +); + +DEFINE_EVENT(cdns2_log_doorbell, cdns2_doorbell_ep0, + TP_PROTO(struct cdns2_endpoint *pep, u32 ep_trbaddr), + TP_ARGS(pep, ep_trbaddr) +); + +DEFINE_EVENT(cdns2_log_doorbell, cdns2_doorbell_epx, + TP_PROTO(struct cdns2_endpoint *pep, u32 ep_trbaddr), + TP_ARGS(pep, ep_trbaddr) +); + +DECLARE_EVENT_CLASS(cdns2_log_usb_irq, + TP_PROTO(u32 usb_irq, u32 ext_irq), + TP_ARGS(usb_irq, ext_irq), + TP_STRUCT__entry( + __field(u32, usb_irq) + __field(u32, ext_irq) + ), + TP_fast_assign( + __entry->usb_irq = usb_irq; + __entry->ext_irq = ext_irq; + ), + TP_printk("%s", cdns2_decode_usb_irq(__get_buf(CDNS2_MSG_MAX), + CDNS2_MSG_MAX, + __entry->usb_irq, + __entry->ext_irq)) +); + +DEFINE_EVENT(cdns2_log_usb_irq, cdns2_usb_irq, + TP_PROTO(u32 usb_irq, u32 ext_irq), + TP_ARGS(usb_irq, ext_irq) +); + +TRACE_EVENT(cdns2_dma_ep_ists, + TP_PROTO(u32 dma_ep_ists), + TP_ARGS(dma_ep_ists), + TP_STRUCT__entry( + __field(u32, dma_ep_ists) + ), + TP_fast_assign( + __entry->dma_ep_ists = dma_ep_ists; + ), + TP_printk("OUT: 0x%04x, IN: 0x%04x", (u16)__entry->dma_ep_ists, + __entry->dma_ep_ists >> 16) +); + +DECLARE_EVENT_CLASS(cdns2_log_epx_irq, + TP_PROTO(struct cdns2_device *pdev, struct cdns2_endpoint *pep), + TP_ARGS(pdev, pep), + TP_STRUCT__entry( + __string(ep_name, pep->name) + __field(u32, ep_sts) + __field(u32, ep_ists) + __field(u32, ep_traddr) + ), + TP_fast_assign( + __assign_str(ep_name, pep->name); + __entry->ep_sts = readl(&pdev->adma_regs->ep_sts); + __entry->ep_ists = readl(&pdev->adma_regs->ep_ists); + __entry->ep_traddr = readl(&pdev->adma_regs->ep_traddr); + ), + TP_printk("%s, ep_traddr: %08x", + cdns2_decode_epx_irq(__get_buf(CDNS2_MSG_MAX), CDNS2_MSG_MAX, + __get_str(ep_name), + __entry->ep_ists, __entry->ep_sts), + __entry->ep_traddr) +); + +DEFINE_EVENT(cdns2_log_epx_irq, cdns2_epx_irq, + TP_PROTO(struct cdns2_device *pdev, struct cdns2_endpoint *pep), + TP_ARGS(pdev, pep) +); + +DECLARE_EVENT_CLASS(cdns2_log_ep0_irq, + TP_PROTO(struct cdns2_device *pdev), + TP_ARGS(pdev), + TP_STRUCT__entry( + __field(int, ep_dir) + __field(u32, ep_ists) + __field(u32, ep_sts) + ), + TP_fast_assign( + __entry->ep_dir = pdev->selected_ep; + __entry->ep_ists = readl(&pdev->adma_regs->ep_ists); + __entry->ep_sts = readl(&pdev->adma_regs->ep_sts); + ), + TP_printk("%s", cdns2_decode_ep0_irq(__get_buf(CDNS2_MSG_MAX), + CDNS2_MSG_MAX, + __entry->ep_ists, __entry->ep_sts, + __entry->ep_dir)) +); + +DEFINE_EVENT(cdns2_log_ep0_irq, cdns2_ep0_irq, + TP_PROTO(struct cdns2_device *pdev), + TP_ARGS(pdev) +); + +DECLARE_EVENT_CLASS(cdns2_log_ctrl, + TP_PROTO(struct usb_ctrlrequest *ctrl), + TP_ARGS(ctrl), + TP_STRUCT__entry( + __field(u8, bRequestType) + __field(u8, bRequest) + __field(u16, wValue) + __field(u16, wIndex) + __field(u16, wLength) + ), + TP_fast_assign( + __entry->bRequestType = ctrl->bRequestType; + __entry->bRequest = ctrl->bRequest; + __entry->wValue = le16_to_cpu(ctrl->wValue); + __entry->wIndex = le16_to_cpu(ctrl->wIndex); + __entry->wLength = le16_to_cpu(ctrl->wLength); + ), + TP_printk("%s", usb_decode_ctrl(__get_buf(CDNS2_MSG_MAX), CDNS2_MSG_MAX, + __entry->bRequestType, + __entry->bRequest, __entry->wValue, + __entry->wIndex, __entry->wLength) + ) +); + +DEFINE_EVENT(cdns2_log_ctrl, cdns2_ctrl_req, + TP_PROTO(struct usb_ctrlrequest *ctrl), + TP_ARGS(ctrl) +); + +DECLARE_EVENT_CLASS(cdns2_log_request, + TP_PROTO(struct cdns2_request *preq), + TP_ARGS(preq), + TP_STRUCT__entry( + __string(name, preq->pep->name) + __field(struct usb_request *, request) + __field(struct cdns2_request *, preq) + __field(void *, buf) + __field(unsigned int, actual) + __field(unsigned int, length) + __field(int, status) + __field(dma_addr_t, dma) + __field(int, zero) + __field(int, short_not_ok) + __field(int, no_interrupt) + __field(struct scatterlist*, sg) + __field(unsigned int, num_sgs) + __field(unsigned int, num_mapped_sgs) + __field(int, start_trb) + __field(int, end_trb) + ), + TP_fast_assign( + __assign_str(name, preq->pep->name); + __entry->request = &preq->request; + __entry->preq = preq; + __entry->buf = preq->request.buf; + __entry->actual = preq->request.actual; + __entry->length = preq->request.length; + __entry->status = preq->request.status; + __entry->dma = preq->request.dma; + __entry->zero = preq->request.zero; + __entry->short_not_ok = preq->request.short_not_ok; + __entry->no_interrupt = preq->request.no_interrupt; + __entry->sg = preq->request.sg; + __entry->num_sgs = preq->request.num_sgs; + __entry->num_mapped_sgs = preq->request.num_mapped_sgs; + __entry->start_trb = preq->start_trb; + __entry->end_trb = preq->end_trb; + ), + TP_printk("%s: req: %p, preq: %p, req buf: %p, length: %u/%u, status: %d," + "buf dma: (%pad), %s%s%s, sg: %p, num_sgs: %d, num_m_sgs: %d," + "trb: [start: %d, end: %d]", + __get_str(name), __entry->request, __entry->preq, + __entry->buf, __entry->actual, __entry->length, + __entry->status, &__entry->dma, + __entry->zero ? "Z" : "z", + __entry->short_not_ok ? "S" : "s", + __entry->no_interrupt ? "I" : "i", + __entry->sg, __entry->num_sgs, __entry->num_mapped_sgs, + __entry->start_trb, + __entry->end_trb + ) +); + +DEFINE_EVENT(cdns2_log_request, cdns2_request_enqueue, + TP_PROTO(struct cdns2_request *preq), + TP_ARGS(preq) +); + +DEFINE_EVENT(cdns2_log_request, cdns2_request_enqueue_error, + TP_PROTO(struct cdns2_request *preq), + TP_ARGS(preq) +); + +DEFINE_EVENT(cdns2_log_request, cdns2_alloc_request, + TP_PROTO(struct cdns2_request *preq), + TP_ARGS(preq) +); + +DEFINE_EVENT(cdns2_log_request, cdns2_free_request, + TP_PROTO(struct cdns2_request *preq), + TP_ARGS(preq) +); + +DEFINE_EVENT(cdns2_log_request, cdns2_ep_queue, + TP_PROTO(struct cdns2_request *preq), + TP_ARGS(preq) +); + +DEFINE_EVENT(cdns2_log_request, cdns2_request_dequeue, + TP_PROTO(struct cdns2_request *preq), + TP_ARGS(preq) +); + +DEFINE_EVENT(cdns2_log_request, cdns2_request_giveback, + TP_PROTO(struct cdns2_request *preq), + TP_ARGS(preq) +); + +TRACE_EVENT(cdns2_ep0_enqueue, + TP_PROTO(struct cdns2_device *dev_priv, struct usb_request *request), + TP_ARGS(dev_priv, request), + TP_STRUCT__entry( + __field(int, dir) + __field(int, length) + ), + TP_fast_assign( + __entry->dir = dev_priv->eps[0].dir; + __entry->length = request->length; + ), + TP_printk("Queue to ep0%s length: %u", __entry->dir ? "in" : "out", + __entry->length) +); + +DECLARE_EVENT_CLASS(cdns2_log_map_request, + TP_PROTO(struct cdns2_request *priv_req), + TP_ARGS(priv_req), + TP_STRUCT__entry( + __string(name, priv_req->pep->name) + __field(struct usb_request *, req) + __field(void *, buf) + __field(dma_addr_t, dma) + ), + TP_fast_assign( + __assign_str(name, priv_req->pep->name); + __entry->req = &priv_req->request; + __entry->buf = priv_req->request.buf; + __entry->dma = priv_req->request.dma; + ), + TP_printk("%s: req: %p, req buf %p, dma %p", + __get_str(name), __entry->req, __entry->buf, &__entry->dma + ) +); + +DEFINE_EVENT(cdns2_log_map_request, cdns2_map_request, + TP_PROTO(struct cdns2_request *req), + TP_ARGS(req) +); +DEFINE_EVENT(cdns2_log_map_request, cdns2_mapped_request, + TP_PROTO(struct cdns2_request *req), + TP_ARGS(req) +); + +DECLARE_EVENT_CLASS(cdns2_log_trb, + TP_PROTO(struct cdns2_endpoint *pep, struct cdns2_trb *trb), + TP_ARGS(pep, trb), + TP_STRUCT__entry( + __string(name, pep->name) + __field(struct cdns2_trb *, trb) + __field(u32, buffer) + __field(u32, length) + __field(u32, control) + __field(u32, type) + ), + TP_fast_assign( + __assign_str(name, pep->name); + __entry->trb = trb; + __entry->buffer = le32_to_cpu(trb->buffer); + __entry->length = le32_to_cpu(trb->length); + __entry->control = le32_to_cpu(trb->control); + __entry->type = usb_endpoint_type(pep->endpoint.desc); + ), + TP_printk("%s: trb V: %p, dma buf: P: 0x%08x, %s", + __get_str(name), __entry->trb, __entry->buffer, + cdns2_decode_trb(__get_buf(CDNS2_MSG_MAX), CDNS2_MSG_MAX, + __entry->control, __entry->length, + __entry->buffer)) +); + +DEFINE_EVENT(cdns2_log_trb, cdns2_queue_trb, + TP_PROTO(struct cdns2_endpoint *pep, struct cdns2_trb *trb), + TP_ARGS(pep, trb) +); + +DEFINE_EVENT(cdns2_log_trb, cdns2_complete_trb, + TP_PROTO(struct cdns2_endpoint *pep, struct cdns2_trb *trb), + TP_ARGS(pep, trb) +); + +DECLARE_EVENT_CLASS(cdns2_log_ring, + TP_PROTO(struct cdns2_endpoint *pep), + TP_ARGS(pep), + TP_STRUCT__entry( + __dynamic_array(u8, tr_seg, TR_SEG_SIZE) + __dynamic_array(u8, pep, sizeof(struct cdns2_endpoint)) + __dynamic_array(char, buffer, + (TRBS_PER_SEGMENT * 65) + CDNS2_MSG_MAX) + ), + TP_fast_assign( + memcpy(__get_dynamic_array(pep), pep, + sizeof(struct cdns2_endpoint)); + memcpy(__get_dynamic_array(tr_seg), pep->ring.trbs, + TR_SEG_SIZE); + ), + + TP_printk("%s", + cdns2_raw_ring((struct cdns2_endpoint *)__get_str(pep), + (struct cdns2_trb *)__get_str(tr_seg), + __get_str(buffer), + (TRBS_PER_SEGMENT * 65) + CDNS2_MSG_MAX)) +); + +DEFINE_EVENT(cdns2_log_ring, cdns2_ring, + TP_PROTO(struct cdns2_endpoint *pep), + TP_ARGS(pep) +); + +DECLARE_EVENT_CLASS(cdns2_log_ep, + TP_PROTO(struct cdns2_endpoint *pep), + TP_ARGS(pep), + TP_STRUCT__entry( + __string(name, pep->name) + __field(unsigned int, maxpacket) + __field(unsigned int, maxpacket_limit) + __field(unsigned int, flags) + __field(unsigned int, dir) + __field(u8, enqueue) + __field(u8, dequeue) + ), + TP_fast_assign( + __assign_str(name, pep->name); + __entry->maxpacket = pep->endpoint.maxpacket; + __entry->maxpacket_limit = pep->endpoint.maxpacket_limit; + __entry->flags = pep->ep_state; + __entry->dir = pep->dir; + __entry->enqueue = pep->ring.enqueue; + __entry->dequeue = pep->ring.dequeue; + ), + TP_printk("%s: mps: %d/%d, enq idx: %d, deq idx: %d, " + "flags: %s%s%s%s, dir: %s", + __get_str(name), __entry->maxpacket, + __entry->maxpacket_limit, __entry->enqueue, + __entry->dequeue, + __entry->flags & EP_ENABLED ? "EN | " : "", + __entry->flags & EP_STALLED ? "STALLED | " : "", + __entry->flags & EP_WEDGE ? "WEDGE | " : "", + __entry->flags & EP_RING_FULL ? "RING FULL |" : "", + __entry->dir ? "IN" : "OUT" + ) +); + +DEFINE_EVENT(cdns2_log_ep, cdns2_gadget_ep_enable, + TP_PROTO(struct cdns2_endpoint *pep), + TP_ARGS(pep) +); + +DEFINE_EVENT(cdns2_log_ep, cdns2_gadget_ep_disable, + TP_PROTO(struct cdns2_endpoint *pep), + TP_ARGS(pep) +); + +DEFINE_EVENT(cdns2_log_ep, cdns2_iso_out_ep_disable, + TP_PROTO(struct cdns2_endpoint *pep), + TP_ARGS(pep) +); + +DEFINE_EVENT(cdns2_log_ep, cdns2_ep_busy_try_halt_again, + TP_PROTO(struct cdns2_endpoint *pep), + TP_ARGS(pep) +); + +DECLARE_EVENT_CLASS(cdns2_log_request_handled, + TP_PROTO(struct cdns2_request *priv_req, int current_index, + int handled), + TP_ARGS(priv_req, current_index, handled), + TP_STRUCT__entry( + __field(struct cdns2_request *, priv_req) + __field(unsigned int, dma_position) + __field(unsigned int, handled) + __field(unsigned int, dequeue_idx) + __field(unsigned int, enqueue_idx) + __field(unsigned int, start_trb) + __field(unsigned int, end_trb) + ), + TP_fast_assign( + __entry->priv_req = priv_req; + __entry->dma_position = current_index; + __entry->handled = handled; + __entry->dequeue_idx = priv_req->pep->ring.dequeue; + __entry->enqueue_idx = priv_req->pep->ring.enqueue; + __entry->start_trb = priv_req->start_trb; + __entry->end_trb = priv_req->end_trb; + ), + TP_printk("Req: %p %s, DMA pos: %d, ep deq: %d, ep enq: %d," + " start trb: %d, end trb: %d", + __entry->priv_req, + __entry->handled ? "handled" : "not handled", + __entry->dma_position, __entry->dequeue_idx, + __entry->enqueue_idx, __entry->start_trb, + __entry->end_trb + ) +); + +DEFINE_EVENT(cdns2_log_request_handled, cdns2_request_handled, + TP_PROTO(struct cdns2_request *priv_req, int current_index, + int handled), + TP_ARGS(priv_req, current_index, handled) +); + +DECLARE_EVENT_CLASS(cdns2_log_epx_reg_config, + TP_PROTO(struct cdns2_device *pdev, struct cdns2_endpoint *pep), + TP_ARGS(pdev, pep), + TP_STRUCT__entry( + __string(ep_name, pep->name) + __field(u8, burst_size) + __field(__le16, maxpack_reg) + __field(__u8, con_reg) + __field(u32, ep_sel_reg) + __field(u32, ep_sts_en_reg) + __field(u32, ep_cfg_reg) + ), + TP_fast_assign( + __assign_str(ep_name, pep->name); + __entry->burst_size = pep->trb_burst_size; + __entry->maxpack_reg = pep->dir ? readw(&pdev->epx_regs->txmaxpack[pep->num - 1]) : + readw(&pdev->epx_regs->rxmaxpack[pep->num - 1]); + __entry->con_reg = pep->dir ? readb(&pdev->epx_regs->ep[pep->num - 1].txcon) : + readb(&pdev->epx_regs->ep[pep->num - 1].rxcon); + __entry->ep_sel_reg = readl(&pdev->adma_regs->ep_sel); + __entry->ep_sts_en_reg = readl(&pdev->adma_regs->ep_sts_en); + __entry->ep_cfg_reg = readl(&pdev->adma_regs->ep_cfg); + ), + + TP_printk("%s, maxpack: %d, con: %02x, dma_ep_sel: %08x, dma_ep_sts_en: %08x" + " dma_ep_cfg %08x", + __get_str(ep_name), __entry->maxpack_reg, __entry->con_reg, + __entry->ep_sel_reg, __entry->ep_sts_en_reg, + __entry->ep_cfg_reg + ) +); + +DEFINE_EVENT(cdns2_log_epx_reg_config, cdns2_epx_hw_cfg, + TP_PROTO(struct cdns2_device *pdev, struct cdns2_endpoint *pep), + TP_ARGS(pdev, pep) +); + +#endif /* __LINUX_CDNS2_TRACE */ + +/* This part must be outside header guard. */ + +#undef TRACE_INCLUDE_PATH +#define TRACE_INCLUDE_PATH . + +#undef TRACE_INCLUDE_FILE +#define TRACE_INCLUDE_FILE cdns2-trace + +#include diff --git a/drivers/usb/gadget/udc/core.c b/drivers/usb/gadget/udc/core.c index 83fd1de14784f29ca78be8ea9fb9eb4a7cc6ab06..59188ea065e0c9e3ea13686ff7bbfeac6613ed2f 100644 --- a/drivers/usb/gadget/udc/core.c +++ b/drivers/usb/gadget/udc/core.c @@ -61,7 +61,7 @@ struct usb_udc { struct mutex connect_lock; }; -static struct class *udc_class; +static const struct class udc_class; static LIST_HEAD(udc_list); /* Protects udc_list, udc->driver, driver->is_bound, and related calls */ @@ -1378,7 +1378,7 @@ int usb_add_gadget(struct usb_gadget *gadget) device_initialize(&udc->dev); udc->dev.release = usb_udc_release; - udc->dev.class = udc_class; + udc->dev.class = &udc_class; udc->dev.groups = usb_udc_attr_groups; udc->dev.parent = gadget->dev.parent; ret = dev_set_name(&udc->dev, "%s", @@ -1856,6 +1856,11 @@ static int usb_udc_uevent(const struct device *dev, struct kobj_uevent_env *env) return 0; } +static const struct class udc_class = { + .name = "udc", + .dev_uevent = usb_udc_uevent, +}; + static const struct bus_type gadget_bus_type = { .name = "gadget", .probe = gadget_bind_driver, @@ -1867,18 +1872,13 @@ static int __init usb_udc_init(void) { int rc; - udc_class = class_create("udc"); - if (IS_ERR(udc_class)) { - pr_err("failed to create udc class --> %ld\n", - PTR_ERR(udc_class)); - return PTR_ERR(udc_class); - } - - udc_class->dev_uevent = usb_udc_uevent; + rc = class_register(&udc_class); + if (rc) + return rc; rc = bus_register(&gadget_bus_type); if (rc) - class_destroy(udc_class); + class_unregister(&udc_class); return rc; } subsys_initcall(usb_udc_init); @@ -1886,7 +1886,7 @@ subsys_initcall(usb_udc_init); static void __exit usb_udc_exit(void) { bus_unregister(&gadget_bus_type); - class_destroy(udc_class); + class_unregister(&udc_class); } module_exit(usb_udc_exit); diff --git a/drivers/usb/gadget/udc/dummy_hcd.c b/drivers/usb/gadget/udc/dummy_hcd.c index 899ac9f9c2796116f5d744a459a6f80b69c36979..0953e1b5c030077eb171ec1d7303104fce3c2eaf 100644 --- a/drivers/usb/gadget/udc/dummy_hcd.c +++ b/drivers/usb/gadget/udc/dummy_hcd.c @@ -1108,13 +1108,12 @@ static int dummy_udc_probe(struct platform_device *pdev) return rc; } -static int dummy_udc_remove(struct platform_device *pdev) +static void dummy_udc_remove(struct platform_device *pdev) { struct dummy *dum = platform_get_drvdata(pdev); device_remove_file(&dum->gadget.dev, &dev_attr_function); usb_del_gadget_udc(&dum->gadget); - return 0; } static void dummy_udc_pm(struct dummy *dum, struct dummy_hcd *dum_hcd, @@ -1150,7 +1149,7 @@ static int dummy_udc_resume(struct platform_device *pdev) static struct platform_driver dummy_udc_driver = { .probe = dummy_udc_probe, - .remove = dummy_udc_remove, + .remove_new = dummy_udc_remove, .suspend = dummy_udc_suspend, .resume = dummy_udc_resume, .driver = { @@ -2701,7 +2700,7 @@ static int dummy_hcd_probe(struct platform_device *pdev) return retval; } -static int dummy_hcd_remove(struct platform_device *pdev) +static void dummy_hcd_remove(struct platform_device *pdev) { struct dummy *dum; @@ -2717,8 +2716,6 @@ static int dummy_hcd_remove(struct platform_device *pdev) dum->hs_hcd = NULL; dum->ss_hcd = NULL; - - return 0; } static int dummy_hcd_suspend(struct platform_device *pdev, pm_message_t state) @@ -2753,7 +2750,7 @@ static int dummy_hcd_resume(struct platform_device *pdev) static struct platform_driver dummy_hcd_driver = { .probe = dummy_hcd_probe, - .remove = dummy_hcd_remove, + .remove_new = dummy_hcd_remove, .suspend = dummy_hcd_suspend, .resume = dummy_hcd_resume, .driver = { diff --git a/drivers/usb/gadget/udc/fsl_qe_udc.c b/drivers/usb/gadget/udc/fsl_qe_udc.c index 3b1cc8fa30c830c980b9c8c3f021b142ebeb3327..9c5dc1c1a68ea889a8b5f0f2c40e8b69650ecbbc 100644 --- a/drivers/usb/gadget/udc/fsl_qe_udc.c +++ b/drivers/usb/gadget/udc/fsl_qe_udc.c @@ -2628,7 +2628,7 @@ static int qe_udc_resume(struct platform_device *dev) } #endif -static int qe_udc_remove(struct platform_device *ofdev) +static void qe_udc_remove(struct platform_device *ofdev) { struct qe_udc *udc = platform_get_drvdata(ofdev); struct qe_ep *ep; @@ -2679,8 +2679,6 @@ static int qe_udc_remove(struct platform_device *ofdev) /* wait for release() of gadget.dev to free udc */ wait_for_completion(&done); - - return 0; } /*-------------------------------------------------------------------------*/ @@ -2708,7 +2706,7 @@ static struct platform_driver udc_driver = { .of_match_table = qe_udc_match, }, .probe = qe_udc_probe, - .remove = qe_udc_remove, + .remove_new = qe_udc_remove, #ifdef CONFIG_PM .suspend = qe_udc_suspend, .resume = qe_udc_resume, diff --git a/drivers/usb/gadget/udc/fusb300_udc.c b/drivers/usb/gadget/udc/fusb300_udc.c index 08ba9c8c1e677503a4863a06061d204166b17c81..bd03d475f927cd634347d440f658dbb2c159c1e8 100644 --- a/drivers/usb/gadget/udc/fusb300_udc.c +++ b/drivers/usb/gadget/udc/fusb300_udc.c @@ -1338,7 +1338,7 @@ static const struct usb_gadget_ops fusb300_gadget_ops = { .udc_stop = fusb300_udc_stop, }; -static int fusb300_remove(struct platform_device *pdev) +static void fusb300_remove(struct platform_device *pdev) { struct fusb300 *fusb300 = platform_get_drvdata(pdev); int i; @@ -1352,8 +1352,6 @@ static int fusb300_remove(struct platform_device *pdev) for (i = 0; i < FUSB300_MAX_NUM_EP; i++) kfree(fusb300->ep[i]); kfree(fusb300); - - return 0; } static int fusb300_probe(struct platform_device *pdev) @@ -1508,7 +1506,7 @@ static int fusb300_probe(struct platform_device *pdev) } static struct platform_driver fusb300_driver = { - .remove = fusb300_remove, + .remove_new = fusb300_remove, .driver = { .name = udc_name, }, diff --git a/drivers/usb/gadget/udc/m66592-udc.c b/drivers/usb/gadget/udc/m66592-udc.c index 06e21cee431be9caec54d43995afd39f976329d8..e05f45a4b56b2bf97bb16c828cea77a1ea355341 100644 --- a/drivers/usb/gadget/udc/m66592-udc.c +++ b/drivers/usb/gadget/udc/m66592-udc.c @@ -1512,7 +1512,7 @@ static const struct usb_gadget_ops m66592_gadget_ops = { .pullup = m66592_pullup, }; -static int m66592_remove(struct platform_device *pdev) +static void m66592_remove(struct platform_device *pdev) { struct m66592 *m66592 = platform_get_drvdata(pdev); @@ -1527,7 +1527,6 @@ static int m66592_remove(struct platform_device *pdev) clk_put(m66592->clk); } kfree(m66592); - return 0; } static void nop_completion(struct usb_ep *ep, struct usb_request *r) @@ -1688,7 +1687,7 @@ static int m66592_probe(struct platform_device *pdev) /*-------------------------------------------------------------------------*/ static struct platform_driver m66592_driver = { - .remove = m66592_remove, + .remove_new = m66592_remove, .driver = { .name = udc_name, }, diff --git a/drivers/usb/gadget/udc/mv_u3d_core.c b/drivers/usb/gadget/udc/mv_u3d_core.c index 411b6179782c1d064fff8d9077170c04028a31e6..3473048a85f5777664f6037cd32a523cec6d7b1a 100644 --- a/drivers/usb/gadget/udc/mv_u3d_core.c +++ b/drivers/usb/gadget/udc/mv_u3d_core.c @@ -1746,7 +1746,7 @@ static irqreturn_t mv_u3d_irq(int irq, void *dev) return IRQ_HANDLED; } -static int mv_u3d_remove(struct platform_device *dev) +static void mv_u3d_remove(struct platform_device *dev) { struct mv_u3d *u3d = platform_get_drvdata(dev); @@ -1775,8 +1775,6 @@ static int mv_u3d_remove(struct platform_device *dev) clk_put(u3d->clk); kfree(u3d); - - return 0; } static int mv_u3d_probe(struct platform_device *dev) @@ -2049,7 +2047,7 @@ static void mv_u3d_shutdown(struct platform_device *dev) static struct platform_driver mv_u3d_driver = { .probe = mv_u3d_probe, - .remove = mv_u3d_remove, + .remove_new = mv_u3d_remove, .shutdown = mv_u3d_shutdown, .driver = { .name = "mv-u3d", diff --git a/drivers/usb/gadget/udc/mv_udc_core.c b/drivers/usb/gadget/udc/mv_udc_core.c index 08474c08d8747065c782f8497333d50539516b29..79db74e2040b8ab67273943e45d2cd7fe4c5c2d0 100644 --- a/drivers/usb/gadget/udc/mv_udc_core.c +++ b/drivers/usb/gadget/udc/mv_udc_core.c @@ -2077,7 +2077,7 @@ static void gadget_release(struct device *_dev) complete(udc->done); } -static int mv_udc_remove(struct platform_device *pdev) +static void mv_udc_remove(struct platform_device *pdev) { struct mv_udc *udc; @@ -2099,8 +2099,6 @@ static int mv_udc_remove(struct platform_device *pdev) /* free dev, wait for the release() finished */ wait_for_completion(udc->done); - - return 0; } static int mv_udc_probe(struct platform_device *pdev) @@ -2411,7 +2409,7 @@ static void mv_udc_shutdown(struct platform_device *pdev) static struct platform_driver udc_driver = { .probe = mv_udc_probe, - .remove = mv_udc_remove, + .remove_new = mv_udc_remove, .shutdown = mv_udc_shutdown, .driver = { .name = "mv-udc", diff --git a/drivers/usb/gadget/udc/net2272.c b/drivers/usb/gadget/udc/net2272.c index 538c1b9a2883546fa15ac03cf0ab241b33c22f74..12e76bb62c20944f902ab33b04691d266e9365a7 100644 --- a/drivers/usb/gadget/udc/net2272.c +++ b/drivers/usb/gadget/udc/net2272.c @@ -2670,7 +2670,7 @@ net2272_plat_probe(struct platform_device *pdev) return ret; } -static int +static void net2272_plat_remove(struct platform_device *pdev) { struct net2272 *dev = platform_get_drvdata(pdev); @@ -2681,13 +2681,11 @@ net2272_plat_remove(struct platform_device *pdev) resource_size(&pdev->resource[0])); usb_put_gadget(&dev->gadget); - - return 0; } static struct platform_driver net2272_plat_driver = { .probe = net2272_plat_probe, - .remove = net2272_plat_remove, + .remove_new = net2272_plat_remove, .driver = { .name = driver_name, }, diff --git a/drivers/usb/gadget/udc/omap_udc.c b/drivers/usb/gadget/udc/omap_udc.c index 2d87c7cd5f7ef9a7e8d3064441c1e2b07cc395ee..10c5d7f726a1fdd967d058bcc60302db8d839009 100644 --- a/drivers/usb/gadget/udc/omap_udc.c +++ b/drivers/usb/gadget/udc/omap_udc.c @@ -2927,7 +2927,7 @@ static int omap_udc_probe(struct platform_device *pdev) return status; } -static int omap_udc_remove(struct platform_device *pdev) +static void omap_udc_remove(struct platform_device *pdev) { DECLARE_COMPLETION_ONSTACK(done); @@ -2939,8 +2939,6 @@ static int omap_udc_remove(struct platform_device *pdev) release_mem_region(pdev->resource[0].start, resource_size(&pdev->resource[0])); - - return 0; } /* suspend/resume/wakeup from sysfs (echo > power/state) or when the @@ -2985,7 +2983,7 @@ static int omap_udc_resume(struct platform_device *dev) static struct platform_driver udc_driver = { .probe = omap_udc_probe, - .remove = omap_udc_remove, + .remove_new = omap_udc_remove, .suspend = omap_udc_suspend, .resume = omap_udc_resume, .driver = { diff --git a/drivers/usb/gadget/udc/pxa27x_udc.c b/drivers/usb/gadget/udc/pxa27x_udc.c index 0ecdfd2ba9e9b03219a2a6fb36ff0ab7abd8972f..c4e1d957f91347fbc5ce3c86176d16d44e2d9152 100644 --- a/drivers/usb/gadget/udc/pxa27x_udc.c +++ b/drivers/usb/gadget/udc/pxa27x_udc.c @@ -2445,7 +2445,7 @@ static int pxa_udc_probe(struct platform_device *pdev) * pxa_udc_remove - removes the udc device driver * @_dev: platform device */ -static int pxa_udc_remove(struct platform_device *_dev) +static void pxa_udc_remove(struct platform_device *_dev) { struct pxa_udc *udc = platform_get_drvdata(_dev); @@ -2460,8 +2460,6 @@ static int pxa_udc_remove(struct platform_device *_dev) udc->transceiver = NULL; the_controller = NULL; clk_unprepare(udc->clk); - - return 0; } static void pxa_udc_shutdown(struct platform_device *_dev) @@ -2472,12 +2470,6 @@ static void pxa_udc_shutdown(struct platform_device *_dev) udc_disable(udc); } -#ifdef CONFIG_PXA27x -extern void pxa27x_clear_otgph(void); -#else -#define pxa27x_clear_otgph() do {} while (0) -#endif - #ifdef CONFIG_PM /** * pxa_udc_suspend - Suspend udc device @@ -2547,7 +2539,7 @@ static struct platform_driver udc_driver = { .of_match_table = of_match_ptr(udc_pxa_dt_ids), }, .probe = pxa_udc_probe, - .remove = pxa_udc_remove, + .remove_new = pxa_udc_remove, .shutdown = pxa_udc_shutdown, #ifdef CONFIG_PM .suspend = pxa_udc_suspend, diff --git a/drivers/usb/gadget/udc/r8a66597-udc.c b/drivers/usb/gadget/udc/r8a66597-udc.c index 38e4d6b505a056a5193a6bfa3ba8eaf3183e93ed..51b665f15c8e898d765edf468f240574155359ca 100644 --- a/drivers/usb/gadget/udc/r8a66597-udc.c +++ b/drivers/usb/gadget/udc/r8a66597-udc.c @@ -1805,7 +1805,7 @@ static const struct usb_gadget_ops r8a66597_gadget_ops = { .set_selfpowered = r8a66597_set_selfpowered, }; -static int r8a66597_remove(struct platform_device *pdev) +static void r8a66597_remove(struct platform_device *pdev) { struct r8a66597 *r8a66597 = platform_get_drvdata(pdev); @@ -1816,8 +1816,6 @@ static int r8a66597_remove(struct platform_device *pdev) if (r8a66597->pdata->on_chip) { clk_disable_unprepare(r8a66597->clk); } - - return 0; } static void nop_completion(struct usb_ep *ep, struct usb_request *r) @@ -1966,7 +1964,7 @@ static int r8a66597_probe(struct platform_device *pdev) /*-------------------------------------------------------------------------*/ static struct platform_driver r8a66597_driver = { - .remove = r8a66597_remove, + .remove_new = r8a66597_remove, .driver = { .name = udc_name, }, diff --git a/drivers/usb/gadget/udc/renesas_usb3.c b/drivers/usb/gadget/udc/renesas_usb3.c index eb008e873361fcaaf5f7c5e8f3571e041bfe8ac0..59bb25de2015ac4b985015e2c0ca10a92ccf8a30 100644 --- a/drivers/usb/gadget/udc/renesas_usb3.c +++ b/drivers/usb/gadget/udc/renesas_usb3.c @@ -2653,7 +2653,7 @@ static void renesas_usb3_debugfs_init(struct renesas_usb3 *usb3, } /*------- platform_driver ------------------------------------------------*/ -static int renesas_usb3_remove(struct platform_device *pdev) +static void renesas_usb3_remove(struct platform_device *pdev) { struct renesas_usb3 *usb3 = platform_get_drvdata(pdev); @@ -2669,8 +2669,6 @@ static int renesas_usb3_remove(struct platform_device *pdev) __renesas_usb3_ep_free_request(usb3->ep0_req); pm_runtime_disable(&pdev->dev); - - return 0; } static int renesas_usb3_init_ep(struct renesas_usb3 *usb3, struct device *dev, @@ -3015,7 +3013,7 @@ static SIMPLE_DEV_PM_OPS(renesas_usb3_pm_ops, renesas_usb3_suspend, static struct platform_driver renesas_usb3_driver = { .probe = renesas_usb3_probe, - .remove = renesas_usb3_remove, + .remove_new = renesas_usb3_remove, .driver = { .name = udc_name, .pm = &renesas_usb3_pm_ops, diff --git a/drivers/usb/gadget/udc/renesas_usbf.c b/drivers/usb/gadget/udc/renesas_usbf.c index 84ac9fe4ce7f138c8bf54275df9ceeb1c7aa90d3..6cd0af83e91efc162556804aedd792548b4b163b 100644 --- a/drivers/usb/gadget/udc/renesas_usbf.c +++ b/drivers/usb/gadget/udc/renesas_usbf.c @@ -3361,15 +3361,13 @@ static int usbf_probe(struct platform_device *pdev) return 0; } -static int usbf_remove(struct platform_device *pdev) +static void usbf_remove(struct platform_device *pdev) { struct usbf_udc *udc = platform_get_drvdata(pdev); usb_del_gadget_udc(&udc->gadget); pm_runtime_put(&pdev->dev); - - return 0; } static const struct of_device_id usbf_match[] = { @@ -3385,7 +3383,7 @@ static struct platform_driver udc_driver = { .of_match_table = usbf_match, }, .probe = usbf_probe, - .remove = usbf_remove, + .remove_new = usbf_remove, }; module_platform_driver(udc_driver); diff --git a/drivers/usb/gadget/udc/rzv2m_usb3drd.c b/drivers/usb/gadget/udc/rzv2m_usb3drd.c index 589c7252e0147f1c26335ab271bde08ae0b49212..36f4ff00d22fdb6643a2206402d5777103845f57 100644 --- a/drivers/usb/gadget/udc/rzv2m_usb3drd.c +++ b/drivers/usb/gadget/udc/rzv2m_usb3drd.c @@ -58,7 +58,7 @@ void rzv2m_usb3drd_reset(struct device *dev, bool host) } EXPORT_SYMBOL_GPL(rzv2m_usb3drd_reset); -static int rzv2m_usb3drd_remove(struct platform_device *pdev) +static void rzv2m_usb3drd_remove(struct platform_device *pdev) { struct rzv2m_usb3drd *usb3 = platform_get_drvdata(pdev); @@ -66,8 +66,6 @@ static int rzv2m_usb3drd_remove(struct platform_device *pdev) pm_runtime_put(usb3->dev); pm_runtime_disable(&pdev->dev); reset_control_assert(usb3->drd_rstc); - - return 0; } static int rzv2m_usb3drd_probe(struct platform_device *pdev) @@ -129,7 +127,7 @@ static struct platform_driver rzv2m_usb3drd_driver = { .of_match_table = rzv2m_usb3drd_of_match, }, .probe = rzv2m_usb3drd_probe, - .remove = rzv2m_usb3drd_remove, + .remove_new = rzv2m_usb3drd_remove, }; module_platform_driver(rzv2m_usb3drd_driver); diff --git a/drivers/usb/gadget/udc/snps_udc_plat.c b/drivers/usb/gadget/udc/snps_udc_plat.c index 0d3e705655b978983c44431ae047b50f9ca47ade..0ed685db149d0a2d86a54e9b2b0292fa813387c6 100644 --- a/drivers/usb/gadget/udc/snps_udc_plat.c +++ b/drivers/usb/gadget/udc/snps_udc_plat.c @@ -225,7 +225,7 @@ static int udc_plat_probe(struct platform_device *pdev) return ret; } -static int udc_plat_remove(struct platform_device *pdev) +static void udc_plat_remove(struct platform_device *pdev) { struct udc *dev; @@ -234,7 +234,7 @@ static int udc_plat_remove(struct platform_device *pdev) usb_del_gadget_udc(&dev->gadget); /* gadget driver must not be registered */ if (WARN_ON(dev->driver)) - return 0; + return; /* dma pool cleanup */ free_dma_pools(dev); @@ -248,8 +248,6 @@ static int udc_plat_remove(struct platform_device *pdev) extcon_unregister_notifier(dev->edev, EXTCON_USB, &dev->nb); dev_info(&pdev->dev, "Synopsys UDC platform driver removed\n"); - - return 0; } #ifdef CONFIG_PM_SLEEP @@ -315,7 +313,7 @@ MODULE_DEVICE_TABLE(of, of_udc_match); static struct platform_driver udc_plat_driver = { .probe = udc_plat_probe, - .remove = udc_plat_remove, + .remove_new = udc_plat_remove, .driver = { .name = "snps-udc-plat", .of_match_table = of_match_ptr(of_udc_match), diff --git a/drivers/usb/gadget/udc/tegra-xudc.c b/drivers/usb/gadget/udc/tegra-xudc.c index 34e9c1df54c79499ac86452c210ab3b096d6b085..83eaa65ddde3f3310df942598b056b4d9ea9fd40 100644 --- a/drivers/usb/gadget/udc/tegra-xudc.c +++ b/drivers/usb/gadget/udc/tegra-xudc.c @@ -3906,7 +3906,7 @@ static int tegra_xudc_probe(struct platform_device *pdev) return err; } -static int tegra_xudc_remove(struct platform_device *pdev) +static void tegra_xudc_remove(struct platform_device *pdev) { struct tegra_xudc *xudc = platform_get_drvdata(pdev); unsigned int i; @@ -3936,8 +3936,6 @@ static int tegra_xudc_remove(struct platform_device *pdev) pm_runtime_put(xudc->dev); tegra_xusb_padctl_put(xudc->padctl); - - return 0; } static int __maybe_unused tegra_xudc_powergate(struct tegra_xudc *xudc) @@ -4063,7 +4061,7 @@ static const struct dev_pm_ops tegra_xudc_pm_ops = { static struct platform_driver tegra_xudc_driver = { .probe = tegra_xudc_probe, - .remove = tegra_xudc_remove, + .remove_new = tegra_xudc_remove, .driver = { .name = "tegra-xudc", .pm = &tegra_xudc_pm_ops, diff --git a/drivers/usb/gadget/udc/udc-xilinx.c b/drivers/usb/gadget/udc/udc-xilinx.c index 4827e3cd383403ef44008e15d32fb58f717eac98..a4a7b90a97e70c0f199142d2647127240400a49c 100644 --- a/drivers/usb/gadget/udc/udc-xilinx.c +++ b/drivers/usb/gadget/udc/udc-xilinx.c @@ -192,7 +192,7 @@ struct xusb_udc { bool dma_enabled; struct clk *clk; - unsigned int (*read_fn)(void __iomem *); + unsigned int (*read_fn)(void __iomem *reg); void (*write_fn)(void __iomem *, u32, u32); }; @@ -2178,14 +2178,12 @@ static int xudc_probe(struct platform_device *pdev) * * Return: 0 always */ -static int xudc_remove(struct platform_device *pdev) +static void xudc_remove(struct platform_device *pdev) { struct xusb_udc *udc = platform_get_drvdata(pdev); usb_del_gadget_udc(&udc->gadget); clk_disable_unprepare(udc->clk); - - return 0; } #ifdef CONFIG_PM_SLEEP @@ -2257,7 +2255,7 @@ static struct platform_driver xudc_driver = { .pm = &xudc_pm_ops, }, .probe = xudc_probe, - .remove = xudc_remove, + .remove_new = xudc_remove, }; module_platform_driver(xudc_driver); diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index c170672f847ec8256397f5dd5e62682d8875ca07..4448d0ab06f0d4c832ed160fccd15b3de8dd9a2e 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -376,7 +376,7 @@ config USB_ISP116X_HCD config USB_ISP1362_HCD tristate "ISP1362 HCD support" - depends on HAS_IOMEM + depends on HAS_IOPORT depends on COMPILE_TEST # nothing uses this help Supports the Philips ISP1362 chip as a host controller @@ -578,7 +578,7 @@ endif # USB_OHCI_HCD config USB_UHCI_HCD tristate "UHCI HCD (most Intel and VIA) support" - depends on USB_PCI || USB_UHCI_SUPPORT_NON_PCI_HC + depends on (USB_PCI && HAS_IOPORT) || USB_UHCI_SUPPORT_NON_PCI_HC help The Universal Host Controller Interface is a standard by Intel for accessing the USB hardware in the PC (which is also called the USB diff --git a/drivers/usb/host/ehci-atmel.c b/drivers/usb/host/ehci-atmel.c index 8b775e7bab066541f192f658ee81c57b53997829..61808c51e702cb24efd6ef789c170990c7468122 100644 --- a/drivers/usb/host/ehci-atmel.c +++ b/drivers/usb/host/ehci-atmel.c @@ -173,7 +173,7 @@ static int ehci_atmel_drv_probe(struct platform_device *pdev) return retval; } -static int ehci_atmel_drv_remove(struct platform_device *pdev) +static void ehci_atmel_drv_remove(struct platform_device *pdev) { struct usb_hcd *hcd = platform_get_drvdata(pdev); @@ -181,8 +181,6 @@ static int ehci_atmel_drv_remove(struct platform_device *pdev) usb_put_hcd(hcd); atmel_stop_ehci(pdev); - - return 0; } static int __maybe_unused ehci_atmel_drv_suspend(struct device *dev) @@ -223,7 +221,7 @@ static SIMPLE_DEV_PM_OPS(ehci_atmel_pm_ops, ehci_atmel_drv_suspend, static struct platform_driver ehci_atmel_driver = { .probe = ehci_atmel_drv_probe, - .remove = ehci_atmel_drv_remove, + .remove_new = ehci_atmel_drv_remove, .shutdown = usb_hcd_platform_shutdown, .driver = { .name = "atmel-ehci", diff --git a/drivers/usb/host/ehci-brcm.c b/drivers/usb/host/ehci-brcm.c index 6a0f64c9e5e885f508431eaca91dd87aad7c98b1..0362a082abb459a38cc451eb9953c259d0456f92 100644 --- a/drivers/usb/host/ehci-brcm.c +++ b/drivers/usb/host/ehci-brcm.c @@ -188,7 +188,7 @@ static int ehci_brcm_probe(struct platform_device *pdev) return err; } -static int ehci_brcm_remove(struct platform_device *dev) +static void ehci_brcm_remove(struct platform_device *dev) { struct usb_hcd *hcd = platform_get_drvdata(dev); struct brcm_priv *priv = hcd_to_ehci_priv(hcd); @@ -196,7 +196,6 @@ static int ehci_brcm_remove(struct platform_device *dev) usb_remove_hcd(hcd); clk_disable_unprepare(priv->clk); usb_put_hcd(hcd); - return 0; } static int __maybe_unused ehci_brcm_suspend(struct device *dev) @@ -250,7 +249,7 @@ static const struct of_device_id brcm_ehci_of_match[] = { static struct platform_driver ehci_brcm_driver = { .probe = ehci_brcm_probe, - .remove = ehci_brcm_remove, + .remove_new = ehci_brcm_remove, .shutdown = usb_hcd_platform_shutdown, .driver = { .name = "ehci-brcm", diff --git a/drivers/usb/host/ehci-exynos.c b/drivers/usb/host/ehci-exynos.c index 47c9f06c3d843db32cb74dc62125c9a4e11ba0c2..20f8c0ec68101e86c5414046d5fef325bc5b3ec9 100644 --- a/drivers/usb/host/ehci-exynos.c +++ b/drivers/usb/host/ehci-exynos.c @@ -230,7 +230,7 @@ static int exynos_ehci_probe(struct platform_device *pdev) return err; } -static int exynos_ehci_remove(struct platform_device *pdev) +static void exynos_ehci_remove(struct platform_device *pdev) { struct usb_hcd *hcd = platform_get_drvdata(pdev); struct exynos_ehci_hcd *exynos_ehci = to_exynos_ehci(hcd); @@ -244,8 +244,6 @@ static int exynos_ehci_remove(struct platform_device *pdev) clk_disable_unprepare(exynos_ehci->clk); usb_put_hcd(hcd); - - return 0; } #ifdef CONFIG_PM @@ -311,7 +309,7 @@ MODULE_DEVICE_TABLE(of, exynos_ehci_match); static struct platform_driver exynos_ehci_driver = { .probe = exynos_ehci_probe, - .remove = exynos_ehci_remove, + .remove_new = exynos_ehci_remove, .shutdown = usb_hcd_platform_shutdown, .driver = { .name = "exynos-ehci", diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c index d74fa5ba845b8cd335a384ae1643fa4c0e35b3da..81d60a69551051393f3c7a433ccded85b6658145 100644 --- a/drivers/usb/host/ehci-fsl.c +++ b/drivers/usb/host/ehci-fsl.c @@ -684,7 +684,7 @@ static const struct ehci_driver_overrides ehci_fsl_overrides __initconst = { * * Reverses the effect of usb_hcd_fsl_probe(). */ -static int fsl_ehci_drv_remove(struct platform_device *pdev) +static void fsl_ehci_drv_remove(struct platform_device *pdev) { struct fsl_usb2_platform_data *pdata = dev_get_platdata(&pdev->dev); struct usb_hcd *hcd = platform_get_drvdata(pdev); @@ -703,13 +703,11 @@ static int fsl_ehci_drv_remove(struct platform_device *pdev) if (pdata->exit) pdata->exit(pdev); usb_put_hcd(hcd); - - return 0; } static struct platform_driver ehci_fsl_driver = { .probe = fsl_ehci_drv_probe, - .remove = fsl_ehci_drv_remove, + .remove_new = fsl_ehci_drv_remove, .shutdown = usb_hcd_platform_shutdown, .driver = { .name = DRV_NAME, diff --git a/drivers/usb/host/ehci-grlib.c b/drivers/usb/host/ehci-grlib.c index 0717f2ccf49d52fa6a5a9812a885a47784dbcc5b..14150e4d338265ea3cb54bd1c707baaaffeb397c 100644 --- a/drivers/usb/host/ehci-grlib.c +++ b/drivers/usb/host/ehci-grlib.c @@ -140,7 +140,7 @@ static int ehci_hcd_grlib_probe(struct platform_device *op) } -static int ehci_hcd_grlib_remove(struct platform_device *op) +static void ehci_hcd_grlib_remove(struct platform_device *op) { struct usb_hcd *hcd = platform_get_drvdata(op); @@ -151,8 +151,6 @@ static int ehci_hcd_grlib_remove(struct platform_device *op) irq_dispose_mapping(hcd->irq); usb_put_hcd(hcd); - - return 0; } @@ -170,7 +168,7 @@ MODULE_DEVICE_TABLE(of, ehci_hcd_grlib_of_match); static struct platform_driver ehci_grlib_driver = { .probe = ehci_hcd_grlib_probe, - .remove = ehci_hcd_grlib_remove, + .remove_new = ehci_hcd_grlib_remove, .shutdown = usb_hcd_platform_shutdown, .driver = { .name = "grlib-ehci", diff --git a/drivers/usb/host/ehci-mv.c b/drivers/usb/host/ehci-mv.c index fa46d217dd1074023c2fedbf122e95c40fc202b7..9320cf0e5bc7020776c135de3a4e1e07f0d98fc5 100644 --- a/drivers/usb/host/ehci-mv.c +++ b/drivers/usb/host/ehci-mv.c @@ -235,7 +235,7 @@ static int mv_ehci_probe(struct platform_device *pdev) return retval; } -static int mv_ehci_remove(struct platform_device *pdev) +static void mv_ehci_remove(struct platform_device *pdev) { struct usb_hcd *hcd = platform_get_drvdata(pdev); struct ehci_hcd_mv *ehci_mv = hcd_to_ehci_hcd_mv(hcd); @@ -254,8 +254,6 @@ static int mv_ehci_remove(struct platform_device *pdev) } usb_put_hcd(hcd); - - return 0; } static const struct platform_device_id ehci_id_table[] = { @@ -282,7 +280,7 @@ static const struct of_device_id ehci_mv_dt_ids[] = { static struct platform_driver ehci_mv_driver = { .probe = mv_ehci_probe, - .remove = mv_ehci_remove, + .remove_new = mv_ehci_remove, .shutdown = mv_ehci_shutdown, .driver = { .name = "mv-ehci", diff --git a/drivers/usb/host/ehci-npcm7xx.c b/drivers/usb/host/ehci-npcm7xx.c index 63af1a827fcbc2cb34041aa2bad95a38057afac4..ad79ce63afcfe7ff9364a839cb4d5ab069eae566 100644 --- a/drivers/usb/host/ehci-npcm7xx.c +++ b/drivers/usb/host/ehci-npcm7xx.c @@ -106,15 +106,13 @@ static int npcm7xx_ehci_hcd_drv_probe(struct platform_device *pdev) return retval; } -static int npcm7xx_ehci_hcd_drv_remove(struct platform_device *pdev) +static void npcm7xx_ehci_hcd_drv_remove(struct platform_device *pdev) { struct usb_hcd *hcd = platform_get_drvdata(pdev); usb_remove_hcd(hcd); usb_put_hcd(hcd); - - return 0; } static const struct of_device_id npcm7xx_ehci_id_table[] = { @@ -125,7 +123,7 @@ MODULE_DEVICE_TABLE(of, npcm7xx_ehci_id_table); static struct platform_driver npcm7xx_ehci_hcd_driver = { .probe = npcm7xx_ehci_hcd_drv_probe, - .remove = npcm7xx_ehci_hcd_drv_remove, + .remove_new = npcm7xx_ehci_hcd_drv_remove, .shutdown = usb_hcd_platform_shutdown, .driver = { .name = "npcm7xx-ehci", diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c index 7dd984722a7f7daeafb66504475bf3b91d8ff6ed..cb6509a735ac7a01c73e40b35976386937228596 100644 --- a/drivers/usb/host/ehci-omap.c +++ b/drivers/usb/host/ehci-omap.c @@ -237,7 +237,7 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev) * the HCD's stop() method. It is always called from a thread * context, normally "rmmod", "apmd", or something similar. */ -static int ehci_hcd_omap_remove(struct platform_device *pdev) +static void ehci_hcd_omap_remove(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct usb_hcd *hcd = dev_get_drvdata(dev); @@ -254,8 +254,6 @@ static int ehci_hcd_omap_remove(struct platform_device *pdev) usb_put_hcd(hcd); pm_runtime_put_sync(dev); pm_runtime_disable(dev); - - return 0; } static const struct of_device_id omap_ehci_dt_ids[] = { @@ -267,7 +265,7 @@ MODULE_DEVICE_TABLE(of, omap_ehci_dt_ids); static struct platform_driver ehci_hcd_omap_driver = { .probe = ehci_hcd_omap_probe, - .remove = ehci_hcd_omap_remove, + .remove_new = ehci_hcd_omap_remove, .shutdown = usb_hcd_platform_shutdown, /*.suspend = ehci_hcd_omap_suspend, */ /*.resume = ehci_hcd_omap_resume, */ diff --git a/drivers/usb/host/ehci-orion.c b/drivers/usb/host/ehci-orion.c index a3454a3ea4e0006f74d0e8ee5357895eb6cd4d75..2cfb27dc943a6b4111c688736d63c84858ef9d38 100644 --- a/drivers/usb/host/ehci-orion.c +++ b/drivers/usb/host/ehci-orion.c @@ -321,7 +321,7 @@ static int ehci_orion_drv_probe(struct platform_device *pdev) return err; } -static int ehci_orion_drv_remove(struct platform_device *pdev) +static void ehci_orion_drv_remove(struct platform_device *pdev) { struct usb_hcd *hcd = platform_get_drvdata(pdev); struct orion_ehci_hcd *priv = hcd_to_orion_priv(hcd); @@ -332,8 +332,6 @@ static int ehci_orion_drv_remove(struct platform_device *pdev) clk_disable_unprepare(priv->clk); usb_put_hcd(hcd); - - return 0; } static const struct of_device_id ehci_orion_dt_ids[] = { @@ -345,7 +343,7 @@ MODULE_DEVICE_TABLE(of, ehci_orion_dt_ids); static struct platform_driver ehci_orion_driver = { .probe = ehci_orion_drv_probe, - .remove = ehci_orion_drv_remove, + .remove_new = ehci_orion_drv_remove, .shutdown = usb_hcd_platform_shutdown, .driver = { .name = "orion-ehci", diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index 4b148fe5e43b28f0b64167c679a1625db0fcfb98..889dc4426271173f5a5bcb7a445d7089426284b1 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c @@ -354,10 +354,11 @@ static int ehci_pci_setup(struct usb_hcd *hcd) * Also they depend on separate root hub suspend/resume. */ -static int ehci_pci_resume(struct usb_hcd *hcd, bool hibernated) +static int ehci_pci_resume(struct usb_hcd *hcd, pm_message_t msg) { struct ehci_hcd *ehci = hcd_to_ehci(hcd); struct pci_dev *pdev = to_pci_dev(hcd->self.controller); + bool hibernated = (msg.event == PM_EVENT_RESTORE); if (ehci_resume(hcd, hibernated) != 0) (void) ehci_pci_reinit(ehci, pdev); diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c index fe497c876d76899bfde7535bc40447d0e4625d90..83bf56c9424fbd10f5ec9887f0ec06cfafc89299 100644 --- a/drivers/usb/host/ehci-platform.c +++ b/drivers/usb/host/ehci-platform.c @@ -400,7 +400,7 @@ static int ehci_platform_probe(struct platform_device *dev) return err; } -static int ehci_platform_remove(struct platform_device *dev) +static void ehci_platform_remove(struct platform_device *dev) { struct usb_hcd *hcd = platform_get_drvdata(dev); struct usb_ehci_pdata *pdata = dev_get_platdata(&dev->dev); @@ -424,8 +424,6 @@ static int ehci_platform_remove(struct platform_device *dev) if (pdata == &ehci_platform_defaults) dev->dev.platform_data = NULL; - - return 0; } static int __maybe_unused ehci_platform_suspend(struct device *dev) @@ -511,7 +509,7 @@ static SIMPLE_DEV_PM_OPS(ehci_platform_pm_ops, ehci_platform_suspend, static struct platform_driver ehci_platform_driver = { .id_table = ehci_platform_table, .probe = ehci_platform_probe, - .remove = ehci_platform_remove, + .remove_new = ehci_platform_remove, .shutdown = usb_hcd_platform_shutdown, .driver = { .name = "ehci-platform", diff --git a/drivers/usb/host/ehci-ppc-of.c b/drivers/usb/host/ehci-ppc-of.c index b3aa464e9d2c997ef9749664d93b37d022f42292..7fd83e806ae4661631b38bd9e056729f01dac7ff 100644 --- a/drivers/usb/host/ehci-ppc-of.c +++ b/drivers/usb/host/ehci-ppc-of.c @@ -184,7 +184,7 @@ static int ehci_hcd_ppc_of_probe(struct platform_device *op) } -static int ehci_hcd_ppc_of_remove(struct platform_device *op) +static void ehci_hcd_ppc_of_remove(struct platform_device *op) { struct usb_hcd *hcd = platform_get_drvdata(op); struct ehci_hcd *ehci = hcd_to_ehci(hcd); @@ -216,8 +216,6 @@ static int ehci_hcd_ppc_of_remove(struct platform_device *op) } } usb_put_hcd(hcd); - - return 0; } @@ -232,7 +230,7 @@ MODULE_DEVICE_TABLE(of, ehci_hcd_ppc_of_match); static struct platform_driver ehci_hcd_ppc_of_driver = { .probe = ehci_hcd_ppc_of_probe, - .remove = ehci_hcd_ppc_of_remove, + .remove_new = ehci_hcd_ppc_of_remove, .shutdown = usb_hcd_platform_shutdown, .driver = { .name = "ppc-of-ehci", diff --git a/drivers/usb/host/ehci-sh.c b/drivers/usb/host/ehci-sh.c index c25c51d26f26035ba588f6ec96fa470c9da9122f..0520e762801d5a6dc90ff15d2ea7e4c718b5acf9 100644 --- a/drivers/usb/host/ehci-sh.c +++ b/drivers/usb/host/ehci-sh.c @@ -147,7 +147,7 @@ static int ehci_hcd_sh_probe(struct platform_device *pdev) return ret; } -static int ehci_hcd_sh_remove(struct platform_device *pdev) +static void ehci_hcd_sh_remove(struct platform_device *pdev) { struct ehci_sh_priv *priv = platform_get_drvdata(pdev); struct usb_hcd *hcd = priv->hcd; @@ -157,8 +157,6 @@ static int ehci_hcd_sh_remove(struct platform_device *pdev) clk_disable(priv->fclk); clk_disable(priv->iclk); - - return 0; } static void ehci_hcd_sh_shutdown(struct platform_device *pdev) @@ -172,7 +170,7 @@ static void ehci_hcd_sh_shutdown(struct platform_device *pdev) static struct platform_driver ehci_hcd_sh_driver = { .probe = ehci_hcd_sh_probe, - .remove = ehci_hcd_sh_remove, + .remove_new = ehci_hcd_sh_remove, .shutdown = ehci_hcd_sh_shutdown, .driver = { .name = "sh_ehci", diff --git a/drivers/usb/host/ehci-spear.c b/drivers/usb/host/ehci-spear.c index c4ddd1022f60c2576718d04c62fdb7b780a4e01e..1407703649bef7ffee1b8b1eee4c22c1c13146f3 100644 --- a/drivers/usb/host/ehci-spear.c +++ b/drivers/usb/host/ehci-spear.c @@ -124,7 +124,7 @@ static int spear_ehci_hcd_drv_probe(struct platform_device *pdev) return retval ; } -static int spear_ehci_hcd_drv_remove(struct platform_device *pdev) +static void spear_ehci_hcd_drv_remove(struct platform_device *pdev) { struct usb_hcd *hcd = platform_get_drvdata(pdev); struct spear_ehci *sehci = to_spear_ehci(hcd); @@ -134,8 +134,6 @@ static int spear_ehci_hcd_drv_remove(struct platform_device *pdev) if (sehci->clk) clk_disable_unprepare(sehci->clk); usb_put_hcd(hcd); - - return 0; } static const struct of_device_id spear_ehci_id_table[] = { @@ -146,7 +144,7 @@ MODULE_DEVICE_TABLE(of, spear_ehci_id_table); static struct platform_driver spear_ehci_hcd_driver = { .probe = spear_ehci_hcd_drv_probe, - .remove = spear_ehci_hcd_drv_remove, + .remove_new = spear_ehci_hcd_drv_remove, .shutdown = usb_hcd_platform_shutdown, .driver = { .name = "spear-ehci", diff --git a/drivers/usb/host/ehci-st.c b/drivers/usb/host/ehci-st.c index f731dc98c5331ab7ac2e0338787598e1d20d3d0d..ee0976b815b4f217c8a3d24af79db8bdde774275 100644 --- a/drivers/usb/host/ehci-st.c +++ b/drivers/usb/host/ehci-st.c @@ -252,7 +252,7 @@ static int st_ehci_platform_probe(struct platform_device *dev) return err; } -static int st_ehci_platform_remove(struct platform_device *dev) +static void st_ehci_platform_remove(struct platform_device *dev) { struct usb_hcd *hcd = platform_get_drvdata(dev); struct usb_ehci_pdata *pdata = dev_get_platdata(&dev->dev); @@ -271,8 +271,6 @@ static int st_ehci_platform_remove(struct platform_device *dev) if (pdata == &ehci_platform_defaults) dev->dev.platform_data = NULL; - - return 0; } #ifdef CONFIG_PM_SLEEP @@ -328,7 +326,7 @@ MODULE_DEVICE_TABLE(of, st_ehci_ids); static struct platform_driver ehci_platform_driver = { .probe = st_ehci_platform_probe, - .remove = st_ehci_platform_remove, + .remove_new = st_ehci_platform_remove, .shutdown = usb_hcd_platform_shutdown, .driver = { .name = "st-ehci", diff --git a/drivers/usb/host/ehci-xilinx-of.c b/drivers/usb/host/ehci-xilinx-of.c index 3d7893747835d042ab00fcaf4f8a8a2a50466cf6..a2112c28f6314688dbbf9ce7ac60bcc3a7d72731 100644 --- a/drivers/usb/host/ehci-xilinx-of.c +++ b/drivers/usb/host/ehci-xilinx-of.c @@ -201,7 +201,7 @@ static int ehci_hcd_xilinx_of_probe(struct platform_device *op) * * Return: Always return 0 */ -static int ehci_hcd_xilinx_of_remove(struct platform_device *op) +static void ehci_hcd_xilinx_of_remove(struct platform_device *op) { struct usb_hcd *hcd = platform_get_drvdata(op); @@ -210,8 +210,6 @@ static int ehci_hcd_xilinx_of_remove(struct platform_device *op) usb_remove_hcd(hcd); usb_put_hcd(hcd); - - return 0; } static const struct of_device_id ehci_hcd_xilinx_of_match[] = { @@ -222,7 +220,7 @@ MODULE_DEVICE_TABLE(of, ehci_hcd_xilinx_of_match); static struct platform_driver ehci_hcd_xilinx_of_driver = { .probe = ehci_hcd_xilinx_of_probe, - .remove = ehci_hcd_xilinx_of_remove, + .remove_new = ehci_hcd_xilinx_of_remove, .shutdown = usb_hcd_platform_shutdown, .driver = { .name = "xilinx-of-ehci", diff --git a/drivers/usb/host/fhci-hcd.c b/drivers/usb/host/fhci-hcd.c index 92794ffc25c876286994e93f51f9bd62d48b898d..66a045e01dad8e6ba19fcf6ae85b3b6758330f7f 100644 --- a/drivers/usb/host/fhci-hcd.c +++ b/drivers/usb/host/fhci-hcd.c @@ -757,7 +757,7 @@ static int of_fhci_probe(struct platform_device *ofdev) return ret; } -static int fhci_remove(struct device *dev) +static void fhci_remove(struct device *dev) { struct usb_hcd *hcd = dev_get_drvdata(dev); struct fhci_hcd *fhci = hcd_to_fhci(hcd); @@ -771,12 +771,11 @@ static int fhci_remove(struct device *dev) qe_pin_free(fhci->pins[j]); fhci_dfs_destroy(fhci); usb_put_hcd(hcd); - return 0; } -static int of_fhci_remove(struct platform_device *ofdev) +static void of_fhci_remove(struct platform_device *ofdev) { - return fhci_remove(&ofdev->dev); + fhci_remove(&ofdev->dev); } static const struct of_device_id of_fhci_match[] = { @@ -791,7 +790,7 @@ static struct platform_driver of_fhci_driver = { .of_match_table = of_fhci_match, }, .probe = of_fhci_probe, - .remove = of_fhci_remove, + .remove_new = of_fhci_remove, }; module_platform_driver(of_fhci_driver); diff --git a/drivers/usb/host/fsl-mph-dr-of.c b/drivers/usb/host/fsl-mph-dr-of.c index 9db909d12354b074152dd49901b5d78caae92f4a..a9877f2569f4e84c9b7c57511fab7732858be42d 100644 --- a/drivers/usb/host/fsl-mph-dr-of.c +++ b/drivers/usb/host/fsl-mph-dr-of.c @@ -265,10 +265,9 @@ static int __unregister_subdev(struct device *dev, void *d) return 0; } -static int fsl_usb2_mph_dr_of_remove(struct platform_device *ofdev) +static void fsl_usb2_mph_dr_of_remove(struct platform_device *ofdev) { device_for_each_child(&ofdev->dev, NULL, __unregister_subdev); - return 0; } #ifdef CONFIG_PPC_MPC512x @@ -362,7 +361,7 @@ static struct platform_driver fsl_usb2_mph_dr_driver = { .of_match_table = fsl_usb2_mph_dr_of_match, }, .probe = fsl_usb2_mph_dr_of_probe, - .remove = fsl_usb2_mph_dr_of_remove, + .remove_new = fsl_usb2_mph_dr_of_remove, }; module_platform_driver(fsl_usb2_mph_dr_driver); diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c index 49ae01487af4d3ed0548a0838d4016fe510d01b8..a82d8926e922c49151ebda072c94e24719c28b76 100644 --- a/drivers/usb/host/isp116x-hcd.c +++ b/drivers/usb/host/isp116x-hcd.c @@ -1526,14 +1526,14 @@ static const struct hc_driver isp116x_hc_driver = { /*----------------------------------------------------------------*/ -static int isp116x_remove(struct platform_device *pdev) +static void isp116x_remove(struct platform_device *pdev) { struct usb_hcd *hcd = platform_get_drvdata(pdev); struct isp116x *isp116x; struct resource *res; if (!hcd) - return 0; + return; isp116x = hcd_to_isp116x(hcd); remove_debug_file(isp116x); usb_remove_hcd(hcd); @@ -1548,7 +1548,6 @@ static int isp116x_remove(struct platform_device *pdev) release_mem_region(res->start, 2); usb_put_hcd(hcd); - return 0; } static int isp116x_probe(struct platform_device *pdev) @@ -1685,7 +1684,7 @@ MODULE_ALIAS("platform:isp116x-hcd"); static struct platform_driver isp116x_driver = { .probe = isp116x_probe, - .remove = isp116x_remove, + .remove_new = isp116x_remove, .suspend = isp116x_suspend, .resume = isp116x_resume, .driver = { diff --git a/drivers/usb/host/isp1362-hcd.c b/drivers/usb/host/isp1362-hcd.c index b0da143ef4be90ba5ada026b00fd57b7023de861..606f0a64f3b7cd6d2d626dc16cf010475e5f43fa 100644 --- a/drivers/usb/host/isp1362-hcd.c +++ b/drivers/usb/host/isp1362-hcd.c @@ -2606,7 +2606,7 @@ static const struct hc_driver isp1362_hc_driver = { /*-------------------------------------------------------------------------*/ -static int isp1362_remove(struct platform_device *pdev) +static void isp1362_remove(struct platform_device *pdev) { struct usb_hcd *hcd = platform_get_drvdata(pdev); struct isp1362_hcd *isp1362_hcd = hcd_to_isp1362_hcd(hcd); @@ -2617,8 +2617,6 @@ static int isp1362_remove(struct platform_device *pdev) DBG(0, "%s: put_hcd\n", __func__); usb_put_hcd(hcd); DBG(0, "%s: Done\n", __func__); - - return 0; } static int isp1362_probe(struct platform_device *pdev) @@ -2760,7 +2758,7 @@ static int isp1362_resume(struct platform_device *pdev) static struct platform_driver isp1362_driver = { .probe = isp1362_probe, - .remove = isp1362_remove, + .remove_new = isp1362_remove, .suspend = isp1362_suspend, .resume = isp1362_resume, diff --git a/drivers/usb/host/octeon-hcd.c b/drivers/usb/host/octeon-hcd.c index a1cd81d4a11441f2e4ea1779e84519e82c3aca3f..19d5777f5db25c980fa52f1940a379da039f1373 100644 --- a/drivers/usb/host/octeon-hcd.c +++ b/drivers/usb/host/octeon-hcd.c @@ -3680,7 +3680,7 @@ static int octeon_usb_probe(struct platform_device *pdev) return 0; } -static int octeon_usb_remove(struct platform_device *pdev) +static void octeon_usb_remove(struct platform_device *pdev) { int status; struct device *dev = &pdev->dev; @@ -3696,8 +3696,6 @@ static int octeon_usb_remove(struct platform_device *pdev) dev_dbg(dev, "USB shutdown failed with %d\n", status); usb_put_hcd(hcd); - - return 0; } static const struct of_device_id octeon_usb_match[] = { @@ -3714,7 +3712,7 @@ static struct platform_driver octeon_usb_driver = { .of_match_table = octeon_usb_match, }, .probe = octeon_usb_probe, - .remove = octeon_usb_remove, + .remove_new = octeon_usb_remove, }; static int __init octeon_usb_driver_init(void) diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c index 533537ef3c21db8a7c54d4116b2c8cb2dcd2d599..b9ce8d80f20b26830976181dfa1ee24ca40049be 100644 --- a/drivers/usb/host/ohci-at91.c +++ b/drivers/usb/host/ohci-at91.c @@ -599,7 +599,7 @@ static int ohci_hcd_at91_drv_probe(struct platform_device *pdev) return usb_hcd_at91_probe(&ohci_at91_hc_driver, pdev); } -static int ohci_hcd_at91_drv_remove(struct platform_device *pdev) +static void ohci_hcd_at91_drv_remove(struct platform_device *pdev) { struct at91_usbh_data *pdata = dev_get_platdata(&pdev->dev); int i; @@ -611,7 +611,6 @@ static int ohci_hcd_at91_drv_remove(struct platform_device *pdev) device_init_wakeup(&pdev->dev, 0); usb_hcd_at91_remove(platform_get_drvdata(pdev), pdev); - return 0; } static int __maybe_unused @@ -683,7 +682,7 @@ static SIMPLE_DEV_PM_OPS(ohci_hcd_at91_pm_ops, ohci_hcd_at91_drv_suspend, static struct platform_driver ohci_hcd_at91_driver = { .probe = ohci_hcd_at91_drv_probe, - .remove = ohci_hcd_at91_drv_remove, + .remove_new = ohci_hcd_at91_drv_remove, .shutdown = usb_hcd_platform_shutdown, .driver = { .name = "at91_ohci", diff --git a/drivers/usb/host/ohci-da8xx.c b/drivers/usb/host/ohci-da8xx.c index d4818e8d652b2eb8d870c741e7a28b3c934749d2..e4191a868944e8af8b9f1b89cfa8b7a5a9d6c4c6 100644 --- a/drivers/usb/host/ohci-da8xx.c +++ b/drivers/usb/host/ohci-da8xx.c @@ -469,14 +469,12 @@ static int ohci_da8xx_probe(struct platform_device *pdev) return error; } -static int ohci_da8xx_remove(struct platform_device *pdev) +static void ohci_da8xx_remove(struct platform_device *pdev) { struct usb_hcd *hcd = platform_get_drvdata(pdev); usb_remove_hcd(hcd); usb_put_hcd(hcd); - - return 0; } #ifdef CONFIG_PM @@ -533,7 +531,7 @@ static const struct ohci_driver_overrides da8xx_overrides __initconst = { */ static struct platform_driver ohci_hcd_da8xx_driver = { .probe = ohci_da8xx_probe, - .remove = ohci_da8xx_remove, + .remove_new = ohci_da8xx_remove, .shutdown = usb_hcd_platform_shutdown, #ifdef CONFIG_PM .suspend = ohci_da8xx_suspend, diff --git a/drivers/usb/host/ohci-exynos.c b/drivers/usb/host/ohci-exynos.c index 8af17c1ee5cc8f1ec54bcd548bc9c29f277f18ba..ab31c459b32d4a5017099244511dc984209b1de5 100644 --- a/drivers/usb/host/ohci-exynos.c +++ b/drivers/usb/host/ohci-exynos.c @@ -198,7 +198,7 @@ static int exynos_ohci_probe(struct platform_device *pdev) return err; } -static int exynos_ohci_remove(struct platform_device *pdev) +static void exynos_ohci_remove(struct platform_device *pdev) { struct usb_hcd *hcd = platform_get_drvdata(pdev); struct exynos_ohci_hcd *exynos_ohci = to_exynos_ohci(hcd); @@ -212,8 +212,6 @@ static int exynos_ohci_remove(struct platform_device *pdev) clk_disable_unprepare(exynos_ohci->clk); usb_put_hcd(hcd); - - return 0; } static void exynos_ohci_shutdown(struct platform_device *pdev) @@ -285,7 +283,7 @@ MODULE_DEVICE_TABLE(of, exynos_ohci_match); static struct platform_driver exynos_ohci_driver = { .probe = exynos_ohci_probe, - .remove = exynos_ohci_remove, + .remove_new = exynos_ohci_remove, .shutdown = exynos_ohci_shutdown, .driver = { .name = "exynos-ohci", diff --git a/drivers/usb/host/ohci-nxp.c b/drivers/usb/host/ohci-nxp.c index 5b32e683e367d3dd10aa95350d6f136962c9f0d3..c04b2af5c766cf127df343bfee63c1000e6fbbae 100644 --- a/drivers/usb/host/ohci-nxp.c +++ b/drivers/usb/host/ohci-nxp.c @@ -237,7 +237,7 @@ static int ohci_hcd_nxp_probe(struct platform_device *pdev) return ret; } -static int ohci_hcd_nxp_remove(struct platform_device *pdev) +static void ohci_hcd_nxp_remove(struct platform_device *pdev) { struct usb_hcd *hcd = platform_get_drvdata(pdev); @@ -246,8 +246,6 @@ static int ohci_hcd_nxp_remove(struct platform_device *pdev) usb_put_hcd(hcd); clk_disable_unprepare(usb_host_clk); isp1301_i2c_client = NULL; - - return 0; } /* work with hotplug and coldplug */ @@ -267,7 +265,7 @@ static struct platform_driver ohci_hcd_nxp_driver = { .of_match_table = of_match_ptr(ohci_hcd_nxp_match), }, .probe = ohci_hcd_nxp_probe, - .remove = ohci_hcd_nxp_remove, + .remove_new = ohci_hcd_nxp_remove, }; static int __init ohci_nxp_init(void) diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c index c82121602511bcd37276545558c01975344362fd..21a6f6c55e079e5ea585205ba795ce926d26e0a4 100644 --- a/drivers/usb/host/ohci-omap.c +++ b/drivers/usb/host/ohci-omap.c @@ -321,7 +321,7 @@ static int ohci_hcd_omap_probe(struct platform_device *pdev) * the HCD's stop() method. It is always called from a thread * context, normally "rmmod", "apmd", or something similar. */ -static int ohci_hcd_omap_remove(struct platform_device *pdev) +static void ohci_hcd_omap_remove(struct platform_device *pdev) { struct usb_hcd *hcd = platform_get_drvdata(pdev); struct ohci_omap_priv *priv = hcd_to_ohci_omap_priv(hcd); @@ -340,7 +340,6 @@ static int ohci_hcd_omap_remove(struct platform_device *pdev) clk_unprepare(priv->usb_host_ck); clk_put(priv->usb_host_ck); usb_put_hcd(hcd); - return 0; } /*-------------------------------------------------------------------------*/ @@ -391,7 +390,7 @@ static int ohci_omap_resume(struct platform_device *dev) */ static struct platform_driver ohci_hcd_omap_driver = { .probe = ohci_hcd_omap_probe, - .remove = ohci_hcd_omap_remove, + .remove_new = ohci_hcd_omap_remove, .shutdown = usb_hcd_platform_shutdown, #ifdef CONFIG_PM .suspend = ohci_omap_suspend, diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c index d7b4f40f9ff4eb82178020573011b2b64ab9c0bd..900ea0d368e0343e8da6f5e418d2f43a206aef65 100644 --- a/drivers/usb/host/ohci-pci.c +++ b/drivers/usb/host/ohci-pci.c @@ -301,6 +301,12 @@ static struct pci_driver ohci_pci_driver = { #endif }; +#ifdef CONFIG_PM +static int ohci_pci_resume(struct usb_hcd *hcd, pm_message_t msg) +{ + return ohci_resume(hcd, msg.event == PM_EVENT_RESTORE); +} +#endif static int __init ohci_pci_init(void) { if (usb_disabled()) @@ -311,7 +317,7 @@ static int __init ohci_pci_init(void) #ifdef CONFIG_PM /* Entries for the PCI suspend/resume callbacks are special */ ohci_pci_hc_driver.pci_suspend = ohci_suspend; - ohci_pci_hc_driver.pci_resume = ohci_resume; + ohci_pci_hc_driver.pci_resume = ohci_pci_resume; #endif return pci_register_driver(&ohci_pci_driver); diff --git a/drivers/usb/host/ohci-platform.c b/drivers/usb/host/ohci-platform.c index a84305091c434874a4e3d3555fbfe40cc91b60f3..45a2c981319e965be50b3d675c817c683243b6a1 100644 --- a/drivers/usb/host/ohci-platform.c +++ b/drivers/usb/host/ohci-platform.c @@ -33,7 +33,7 @@ #include "ohci.h" #define DRIVER_DESC "OHCI generic platform driver" -#define OHCI_MAX_CLKS 3 +#define OHCI_MAX_CLKS 4 #define hcd_to_ohci_priv(h) ((struct ohci_platform_priv *)hcd_to_ohci(h)->priv) struct ohci_platform_priv { @@ -239,7 +239,7 @@ static int ohci_platform_probe(struct platform_device *dev) return err; } -static int ohci_platform_remove(struct platform_device *dev) +static void ohci_platform_remove(struct platform_device *dev) { struct usb_hcd *hcd = platform_get_drvdata(dev); struct usb_ohci_pdata *pdata = dev_get_platdata(&dev->dev); @@ -264,8 +264,6 @@ static int ohci_platform_remove(struct platform_device *dev) if (pdata == &ohci_platform_defaults) dev->dev.platform_data = NULL; - - return 0; } #ifdef CONFIG_PM_SLEEP @@ -347,7 +345,7 @@ static const struct dev_pm_ops ohci_platform_pm_ops = { static struct platform_driver ohci_platform_driver = { .id_table = ohci_platform_table, .probe = ohci_platform_probe, - .remove = ohci_platform_remove, + .remove_new = ohci_platform_remove, .shutdown = usb_hcd_platform_shutdown, .driver = { .name = "ohci-platform", diff --git a/drivers/usb/host/ohci-ppc-of.c b/drivers/usb/host/ohci-ppc-of.c index f2f6c832ec98c23f725f4f8bdc8539fa611f16a4..35a7ad7e256960f2280f4ec9451b0b55790af6b5 100644 --- a/drivers/usb/host/ohci-ppc-of.c +++ b/drivers/usb/host/ohci-ppc-of.c @@ -176,7 +176,7 @@ static int ohci_hcd_ppc_of_probe(struct platform_device *op) return rv; } -static int ohci_hcd_ppc_of_remove(struct platform_device *op) +static void ohci_hcd_ppc_of_remove(struct platform_device *op) { struct usb_hcd *hcd = platform_get_drvdata(op); @@ -187,8 +187,6 @@ static int ohci_hcd_ppc_of_remove(struct platform_device *op) irq_dispose_mapping(hcd->irq); usb_put_hcd(hcd); - - return 0; } static const struct of_device_id ohci_hcd_ppc_of_match[] = { @@ -224,7 +222,7 @@ MODULE_DEVICE_TABLE(of, ohci_hcd_ppc_of_match); static struct platform_driver ohci_hcd_ppc_of_driver = { .probe = ohci_hcd_ppc_of_probe, - .remove = ohci_hcd_ppc_of_remove, + .remove_new = ohci_hcd_ppc_of_remove, .shutdown = usb_hcd_platform_shutdown, .driver = { .name = "ppc-of-ohci", diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c index 0bc7e96bcc939e924020864d89e0862b0e199be7..7410442f720f4501db1899a953db0e668917e6b6 100644 --- a/drivers/usb/host/ohci-pxa27x.c +++ b/drivers/usb/host/ohci-pxa27x.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -263,12 +264,6 @@ static inline void pxa27x_reset_hc(struct pxa27x_ohci *pxa_ohci) __raw_writel(uhchr & ~UHCHR_FHR, pxa_ohci->mmio_base + UHCHR); } -#ifdef CONFIG_PXA27x -extern void pxa27x_clear_otgph(void); -#else -#define pxa27x_clear_otgph() do {} while (0) -#endif - static int pxa27x_start_hc(struct pxa27x_ohci *pxa_ohci, struct device *dev) { int retval; @@ -506,7 +501,7 @@ static int ohci_hcd_pxa27x_probe(struct platform_device *pdev) * the HCD's stop() method. It is always called from a thread * context, normally "rmmod", "apmd", or something similar. */ -static int ohci_hcd_pxa27x_remove(struct platform_device *pdev) +static void ohci_hcd_pxa27x_remove(struct platform_device *pdev) { struct usb_hcd *hcd = platform_get_drvdata(pdev); struct pxa27x_ohci *pxa_ohci = to_pxa27x_ohci(hcd); @@ -519,7 +514,6 @@ static int ohci_hcd_pxa27x_remove(struct platform_device *pdev) pxa27x_ohci_set_vbus_power(pxa_ohci, i, false); usb_put_hcd(hcd); - return 0; } /*-------------------------------------------------------------------------*/ @@ -577,7 +571,7 @@ static const struct dev_pm_ops ohci_hcd_pxa27x_pm_ops = { static struct platform_driver ohci_hcd_pxa27x_driver = { .probe = ohci_hcd_pxa27x_probe, - .remove = ohci_hcd_pxa27x_remove, + .remove_new = ohci_hcd_pxa27x_remove, .shutdown = usb_hcd_platform_shutdown, .driver = { .name = "pxa27x-ohci", diff --git a/drivers/usb/host/ohci-s3c2410.c b/drivers/usb/host/ohci-s3c2410.c index 85a0a9ae0095402c4152f74800bd5f74fbdc1afc..c5c9b4cbcb9a3c783edeaf4714d54b7a5dc86f09 100644 --- a/drivers/usb/host/ohci-s3c2410.c +++ b/drivers/usb/host/ohci-s3c2410.c @@ -329,7 +329,7 @@ static void s3c2410_hcd_oc(struct s3c2410_hcd_info *info, int port_oc) * the HCD's stop() method. It is always called from a thread * context, normally "rmmod", "apmd", or something similar. */ -static int +static void ohci_hcd_s3c2410_remove(struct platform_device *dev) { struct usb_hcd *hcd = platform_get_drvdata(dev); @@ -337,7 +337,6 @@ ohci_hcd_s3c2410_remove(struct platform_device *dev) usb_remove_hcd(hcd); s3c2410_stop_hc(dev); usb_put_hcd(hcd); - return 0; } /* @@ -458,7 +457,7 @@ MODULE_DEVICE_TABLE(of, ohci_hcd_s3c2410_dt_ids); static struct platform_driver ohci_hcd_s3c2410_driver = { .probe = ohci_hcd_s3c2410_probe, - .remove = ohci_hcd_s3c2410_remove, + .remove_new = ohci_hcd_s3c2410_remove, .shutdown = usb_hcd_platform_shutdown, .driver = { .name = "s3c2410-ohci", diff --git a/drivers/usb/host/ohci-sm501.c b/drivers/usb/host/ohci-sm501.c index f5de586454e333fbdf25a00fa639b8e8a344f7ef..0468eeb4fcfd91b8985676ed41fc7a90fa353d0e 100644 --- a/drivers/usb/host/ohci-sm501.c +++ b/drivers/usb/host/ohci-sm501.c @@ -185,7 +185,7 @@ static int ohci_hcd_sm501_drv_probe(struct platform_device *pdev) return retval; } -static int ohci_hcd_sm501_drv_remove(struct platform_device *pdev) +static void ohci_hcd_sm501_drv_remove(struct platform_device *pdev) { struct usb_hcd *hcd = platform_get_drvdata(pdev); struct resource *mem; @@ -202,8 +202,6 @@ static int ohci_hcd_sm501_drv_remove(struct platform_device *pdev) sm501_modify_reg(pdev->dev.parent, SM501_IRQ_MASK, 0, 1 << 6); sm501_unit_power(pdev->dev.parent, SM501_GATE_USB_HOST, 0); - - return 0; } /*-------------------------------------------------------------------------*/ @@ -255,7 +253,7 @@ static int ohci_sm501_resume(struct platform_device *pdev) */ static struct platform_driver ohci_hcd_sm501_driver = { .probe = ohci_hcd_sm501_drv_probe, - .remove = ohci_hcd_sm501_drv_remove, + .remove_new = ohci_hcd_sm501_drv_remove, .shutdown = usb_hcd_platform_shutdown, .suspend = ohci_sm501_suspend, .resume = ohci_sm501_resume, diff --git a/drivers/usb/host/ohci-spear.c b/drivers/usb/host/ohci-spear.c index 196951a27f3f27356e61f2c7fb3a8e181725e2d6..f4b2656407ddd6efb4b6181bb8b554ffff49fded 100644 --- a/drivers/usb/host/ohci-spear.c +++ b/drivers/usb/host/ohci-spear.c @@ -98,7 +98,7 @@ static int spear_ohci_hcd_drv_probe(struct platform_device *pdev) return retval; } -static int spear_ohci_hcd_drv_remove(struct platform_device *pdev) +static void spear_ohci_hcd_drv_remove(struct platform_device *pdev) { struct usb_hcd *hcd = platform_get_drvdata(pdev); struct spear_ohci *sohci_p = to_spear_ohci(hcd); @@ -108,7 +108,6 @@ static int spear_ohci_hcd_drv_remove(struct platform_device *pdev) clk_disable_unprepare(sohci_p->clk); usb_put_hcd(hcd); - return 0; } #if defined(CONFIG_PM) @@ -159,7 +158,7 @@ MODULE_DEVICE_TABLE(of, spear_ohci_id_table); /* Driver definition to register with the platform bus */ static struct platform_driver spear_ohci_hcd_driver = { .probe = spear_ohci_hcd_drv_probe, - .remove = spear_ohci_hcd_drv_remove, + .remove_new = spear_ohci_hcd_drv_remove, #ifdef CONFIG_PM .suspend = spear_ohci_hcd_drv_suspend, .resume = spear_ohci_hcd_drv_resume, diff --git a/drivers/usb/host/ohci-st.c b/drivers/usb/host/ohci-st.c index 82eef3c62e11d28ae0afbdcac1cf9f398a09317f..884e447a8098dbf8e03207012347844972fa83d9 100644 --- a/drivers/usb/host/ohci-st.c +++ b/drivers/usb/host/ohci-st.c @@ -233,7 +233,7 @@ static int st_ohci_platform_probe(struct platform_device *dev) return err; } -static int st_ohci_platform_remove(struct platform_device *dev) +static void st_ohci_platform_remove(struct platform_device *dev) { struct usb_hcd *hcd = platform_get_drvdata(dev); struct usb_ohci_pdata *pdata = dev_get_platdata(&dev->dev); @@ -253,8 +253,6 @@ static int st_ohci_platform_remove(struct platform_device *dev) if (pdata == &ohci_platform_defaults) dev->dev.platform_data = NULL; - - return 0; } #ifdef CONFIG_PM_SLEEP @@ -306,7 +304,7 @@ MODULE_DEVICE_TABLE(of, st_ohci_platform_ids); static struct platform_driver ohci_platform_driver = { .probe = st_ohci_platform_probe, - .remove = st_ohci_platform_remove, + .remove_new = st_ohci_platform_remove, .shutdown = usb_hcd_platform_shutdown, .driver = { .name = "st-ohci", diff --git a/drivers/usb/host/oxu210hp-hcd.c b/drivers/usb/host/oxu210hp-hcd.c index f998d3f1a78a1826db79c29b3bfbd08f1eab1c3d..50c1ccabb0f501b7a8ec73acb374c5255368954a 100644 --- a/drivers/usb/host/oxu210hp-hcd.c +++ b/drivers/usb/host/oxu210hp-hcd.c @@ -4278,14 +4278,12 @@ static void oxu_remove(struct platform_device *pdev, struct usb_hcd *hcd) usb_put_hcd(hcd); } -static int oxu_drv_remove(struct platform_device *pdev) +static void oxu_drv_remove(struct platform_device *pdev) { struct oxu_info *info = platform_get_drvdata(pdev); oxu_remove(pdev, info->hcd[0]); oxu_remove(pdev, info->hcd[1]); - - return 0; } static void oxu_drv_shutdown(struct platform_device *pdev) @@ -4317,7 +4315,7 @@ static int oxu_drv_resume(struct device *dev) static struct platform_driver oxu_driver = { .probe = oxu_drv_probe, - .remove = oxu_drv_remove, + .remove_new = oxu_drv_remove, .shutdown = oxu_drv_shutdown, .suspend = oxu_drv_suspend, .resume = oxu_drv_resume, diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c index abb88dd40d4eb93581c1cf12836ac12b784d1940..9f4bf8c5f8a51a0698d2bd23f920f90596c149f7 100644 --- a/drivers/usb/host/r8a66597-hcd.c +++ b/drivers/usb/host/r8a66597-hcd.c @@ -2379,7 +2379,7 @@ static const struct dev_pm_ops r8a66597_dev_pm_ops = { #define R8A66597_DEV_PM_OPS NULL #endif -static int r8a66597_remove(struct platform_device *pdev) +static void r8a66597_remove(struct platform_device *pdev) { struct r8a66597 *r8a66597 = platform_get_drvdata(pdev); struct usb_hcd *hcd = r8a66597_to_hcd(r8a66597); @@ -2390,7 +2390,6 @@ static int r8a66597_remove(struct platform_device *pdev) if (r8a66597->pdata->on_chip) clk_put(r8a66597->clk); usb_put_hcd(hcd); - return 0; } static int r8a66597_probe(struct platform_device *pdev) @@ -2511,7 +2510,7 @@ static int r8a66597_probe(struct platform_device *pdev) static struct platform_driver r8a66597_driver = { .probe = r8a66597_probe, - .remove = r8a66597_remove, + .remove_new = r8a66597_remove, .driver = { .name = hcd_name, .pm = R8A66597_DEV_PM_OPS, diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c index b8b90eec91078ef2aeea61f08386363a05d8d0ed..0956495bba57574e58b0323617d92ea931d0d014 100644 --- a/drivers/usb/host/sl811-hcd.c +++ b/drivers/usb/host/sl811-hcd.c @@ -1579,7 +1579,7 @@ static const struct hc_driver sl811h_hc_driver = { /*-------------------------------------------------------------------------*/ -static int +static void sl811h_remove(struct platform_device *dev) { struct usb_hcd *hcd = platform_get_drvdata(dev); @@ -1599,7 +1599,6 @@ sl811h_remove(struct platform_device *dev) iounmap(sl811->addr_reg); usb_put_hcd(hcd); - return 0; } static int @@ -1783,7 +1782,7 @@ sl811h_resume(struct platform_device *dev) /* this driver is exported so sl811_cs can depend on it */ struct platform_driver sl811h_driver = { .probe = sl811h_probe, - .remove = sl811h_remove, + .remove_new = sl811h_remove, .suspend = sl811h_suspend, .resume = sl811h_resume, diff --git a/drivers/usb/host/uhci-grlib.c b/drivers/usb/host/uhci-grlib.c index 907d5f01edfd47160bf8e00cd78247688330be88..ac3fc597031573199a141e60e2b54432d2a2782e 100644 --- a/drivers/usb/host/uhci-grlib.c +++ b/drivers/usb/host/uhci-grlib.c @@ -147,7 +147,7 @@ static int uhci_hcd_grlib_probe(struct platform_device *op) return rv; } -static int uhci_hcd_grlib_remove(struct platform_device *op) +static void uhci_hcd_grlib_remove(struct platform_device *op) { struct usb_hcd *hcd = platform_get_drvdata(op); @@ -157,8 +157,6 @@ static int uhci_hcd_grlib_remove(struct platform_device *op) irq_dispose_mapping(hcd->irq); usb_put_hcd(hcd); - - return 0; } /* Make sure the controller is quiescent and that we're not using it @@ -185,7 +183,7 @@ MODULE_DEVICE_TABLE(of, uhci_hcd_grlib_of_match); static struct platform_driver uhci_grlib_driver = { .probe = uhci_hcd_grlib_probe, - .remove = uhci_hcd_grlib_remove, + .remove_new = uhci_hcd_grlib_remove, .shutdown = uhci_hcd_grlib_shutdown, .driver = { .name = "grlib-uhci", diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c index 7cdc2fa7c28fb2fc552d737008e8564a6970c554..fd2408b553cf0a4959e3e230f25b3157c04f41a5 100644 --- a/drivers/usb/host/uhci-hcd.c +++ b/drivers/usb/host/uhci-hcd.c @@ -841,7 +841,7 @@ static int uhci_count_ports(struct usb_hcd *hcd) static const char hcd_name[] = "uhci_hcd"; -#ifdef CONFIG_USB_PCI +#if defined(CONFIG_USB_PCI) && defined(CONFIG_HAS_IOPORT) #include "uhci-pci.c" #define PCI_DRIVER uhci_pci_driver #endif diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h index 0688c3e5bfe2e77bda3d36bd160a2617531fe35e..13ee2a6144b2c98b6d628c97de9cb22891a0b76f 100644 --- a/drivers/usb/host/uhci-hcd.h +++ b/drivers/usb/host/uhci-hcd.h @@ -505,6 +505,14 @@ static inline bool uhci_is_aspeed(const struct uhci_hcd *uhci) * we use memory mapped registers. */ +#ifdef CONFIG_HAS_IOPORT +#define UHCI_IN(x) x +#define UHCI_OUT(x) x +#else +#define UHCI_IN(x) 0 +#define UHCI_OUT(x) do { } while (0) +#endif + #ifndef CONFIG_USB_UHCI_SUPPORT_NON_PCI_HC /* Support PCI only */ static inline u32 uhci_readl(const struct uhci_hcd *uhci, int reg) @@ -539,7 +547,7 @@ static inline void uhci_writeb(const struct uhci_hcd *uhci, u8 val, int reg) #else /* Support non-PCI host controllers */ -#ifdef CONFIG_USB_PCI +#if defined(CONFIG_USB_PCI) && defined(HAS_IOPORT) /* Support PCI and non-PCI host controllers */ #define uhci_has_pci_registers(u) ((u)->io_addr != 0) #else @@ -587,7 +595,7 @@ static inline int uhci_aspeed_reg(unsigned int reg) static inline u32 uhci_readl(const struct uhci_hcd *uhci, int reg) { if (uhci_has_pci_registers(uhci)) - return inl(uhci->io_addr + reg); + return UHCI_IN(inl(uhci->io_addr + reg)); else if (uhci_is_aspeed(uhci)) return readl(uhci->regs + uhci_aspeed_reg(reg)); #ifdef CONFIG_USB_UHCI_BIG_ENDIAN_MMIO @@ -601,7 +609,7 @@ static inline u32 uhci_readl(const struct uhci_hcd *uhci, int reg) static inline void uhci_writel(const struct uhci_hcd *uhci, u32 val, int reg) { if (uhci_has_pci_registers(uhci)) - outl(val, uhci->io_addr + reg); + UHCI_OUT(outl(val, uhci->io_addr + reg)); else if (uhci_is_aspeed(uhci)) writel(val, uhci->regs + uhci_aspeed_reg(reg)); #ifdef CONFIG_USB_UHCI_BIG_ENDIAN_MMIO @@ -615,7 +623,7 @@ static inline void uhci_writel(const struct uhci_hcd *uhci, u32 val, int reg) static inline u16 uhci_readw(const struct uhci_hcd *uhci, int reg) { if (uhci_has_pci_registers(uhci)) - return inw(uhci->io_addr + reg); + return UHCI_IN(inw(uhci->io_addr + reg)); else if (uhci_is_aspeed(uhci)) return readl(uhci->regs + uhci_aspeed_reg(reg)); #ifdef CONFIG_USB_UHCI_BIG_ENDIAN_MMIO @@ -629,7 +637,7 @@ static inline u16 uhci_readw(const struct uhci_hcd *uhci, int reg) static inline void uhci_writew(const struct uhci_hcd *uhci, u16 val, int reg) { if (uhci_has_pci_registers(uhci)) - outw(val, uhci->io_addr + reg); + UHCI_OUT(outw(val, uhci->io_addr + reg)); else if (uhci_is_aspeed(uhci)) writel(val, uhci->regs + uhci_aspeed_reg(reg)); #ifdef CONFIG_USB_UHCI_BIG_ENDIAN_MMIO @@ -643,7 +651,7 @@ static inline void uhci_writew(const struct uhci_hcd *uhci, u16 val, int reg) static inline u8 uhci_readb(const struct uhci_hcd *uhci, int reg) { if (uhci_has_pci_registers(uhci)) - return inb(uhci->io_addr + reg); + return UHCI_IN(inb(uhci->io_addr + reg)); else if (uhci_is_aspeed(uhci)) return readl(uhci->regs + uhci_aspeed_reg(reg)); #ifdef CONFIG_USB_UHCI_BIG_ENDIAN_MMIO @@ -657,7 +665,7 @@ static inline u8 uhci_readb(const struct uhci_hcd *uhci, int reg) static inline void uhci_writeb(const struct uhci_hcd *uhci, u8 val, int reg) { if (uhci_has_pci_registers(uhci)) - outb(val, uhci->io_addr + reg); + UHCI_OUT(outb(val, uhci->io_addr + reg)); else if (uhci_is_aspeed(uhci)) writel(val, uhci->regs + uhci_aspeed_reg(reg)); #ifdef CONFIG_USB_UHCI_BIG_ENDIAN_MMIO @@ -668,6 +676,8 @@ static inline void uhci_writeb(const struct uhci_hcd *uhci, u8 val, int reg) writeb(val, uhci->regs + reg); } #endif /* CONFIG_USB_UHCI_SUPPORT_NON_PCI_HC */ +#undef UHCI_IN +#undef UHCI_OUT /* * The GRLIB GRUSBHC controller can use big endian format for its descriptors. diff --git a/drivers/usb/host/uhci-pci.c b/drivers/usb/host/uhci-pci.c index 7bd2fddde770ae4a895dc2988bc1fda0e8d56a55..5edf6a08cf82c670c031cc3daf8b2ff39f7db1b3 100644 --- a/drivers/usb/host/uhci-pci.c +++ b/drivers/usb/host/uhci-pci.c @@ -169,7 +169,7 @@ static void uhci_shutdown(struct pci_dev *pdev) #ifdef CONFIG_PM -static int uhci_pci_resume(struct usb_hcd *hcd, bool hibernated); +static int uhci_pci_resume(struct usb_hcd *hcd, pm_message_t state); static int uhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup) { @@ -204,14 +204,15 @@ static int uhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup) /* Check for race with a wakeup request */ if (do_wakeup && HCD_WAKEUP_PENDING(hcd)) { - uhci_pci_resume(hcd, false); + uhci_pci_resume(hcd, PMSG_SUSPEND); rc = -EBUSY; } return rc; } -static int uhci_pci_resume(struct usb_hcd *hcd, bool hibernated) +static int uhci_pci_resume(struct usb_hcd *hcd, pm_message_t msg) { + bool hibernated = (msg.event == PM_EVENT_RESTORE); struct uhci_hcd *uhci = hcd_to_uhci(hcd); dev_dbg(uhci_dev(uhci), "%s\n", __func__); diff --git a/drivers/usb/host/uhci-platform.c b/drivers/usb/host/uhci-platform.c index b2049b47a08dde372a7544e3817c77cd874a58fc..71ca532fc0865bc18e558af0e8ef9c1fb0f7b88b 100644 --- a/drivers/usb/host/uhci-platform.c +++ b/drivers/usb/host/uhci-platform.c @@ -152,7 +152,7 @@ static int uhci_hcd_platform_probe(struct platform_device *pdev) return ret; } -static int uhci_hcd_platform_remove(struct platform_device *pdev) +static void uhci_hcd_platform_remove(struct platform_device *pdev) { struct usb_hcd *hcd = platform_get_drvdata(pdev); struct uhci_hcd *uhci = hcd_to_uhci(hcd); @@ -160,8 +160,6 @@ static int uhci_hcd_platform_remove(struct platform_device *pdev) clk_disable_unprepare(uhci->clk); usb_remove_hcd(hcd); usb_put_hcd(hcd); - - return 0; } /* Make sure the controller is quiescent and that we're not using it @@ -187,7 +185,7 @@ MODULE_DEVICE_TABLE(of, platform_uhci_ids); static struct platform_driver uhci_platform_driver = { .probe = uhci_hcd_platform_probe, - .remove = uhci_hcd_platform_remove, + .remove_new = uhci_hcd_platform_remove, .shutdown = uhci_hcd_platform_shutdown, .driver = { .name = "platform-uhci", diff --git a/drivers/usb/host/xhci-histb.c b/drivers/usb/host/xhci-histb.c index 08369857686e731f809cc95bb529416a26b65e8a..f9a4a4b0eb574920d3fdec7800939a80c9d6ebbb 100644 --- a/drivers/usb/host/xhci-histb.c +++ b/drivers/usb/host/xhci-histb.c @@ -164,16 +164,6 @@ static void xhci_histb_host_disable(struct xhci_hcd_histb *histb) clk_disable_unprepare(histb->bus_clk); } -static void xhci_histb_quirks(struct device *dev, struct xhci_hcd *xhci) -{ - /* - * As of now platform drivers don't provide MSI support so we ensure - * here that the generic code does not try to make a pci_dev from our - * dev struct in order to setup MSI - */ - xhci->quirks |= XHCI_PLAT; -} - /* called during probe() after chip reset completes */ static int xhci_histb_setup(struct usb_hcd *hcd) { @@ -186,7 +176,7 @@ static int xhci_histb_setup(struct usb_hcd *hcd) return ret; } - return xhci_gen_setup(hcd, xhci_histb_quirks); + return xhci_gen_setup(hcd, NULL); } static const struct xhci_driver_overrides xhci_histb_overrides __initconst = { @@ -319,7 +309,7 @@ static int xhci_histb_probe(struct platform_device *pdev) return ret; } -static int xhci_histb_remove(struct platform_device *dev) +static void xhci_histb_remove(struct platform_device *dev) { struct xhci_hcd_histb *histb = platform_get_drvdata(dev); struct usb_hcd *hcd = histb->hcd; @@ -339,8 +329,6 @@ static int xhci_histb_remove(struct platform_device *dev) usb_put_hcd(hcd); pm_runtime_put_sync(&dev->dev); pm_runtime_disable(&dev->dev); - - return 0; } static int __maybe_unused xhci_histb_suspend(struct device *dev) @@ -367,7 +355,7 @@ static int __maybe_unused xhci_histb_resume(struct device *dev) if (!device_may_wakeup(dev)) xhci_histb_host_enable(histb); - return xhci_resume(xhci, 0); + return xhci_resume(xhci, PMSG_RESUME); } static const struct dev_pm_ops xhci_histb_pm_ops = { @@ -385,7 +373,7 @@ MODULE_DEVICE_TABLE(of, histb_xhci_of_match); static struct platform_driver histb_xhci_driver = { .probe = xhci_histb_probe, - .remove = xhci_histb_remove, + .remove_new = xhci_histb_remove, .driver = { .name = "xhci-histb", .pm = DEV_PM_OPS, diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 7e106bd804ca1a43c2fb489da4e2e634ffc66a90..19a402123de02f9589a526af60ffcbbf0a2297dc 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -143,7 +143,6 @@ static void xhci_link_rings(struct xhci_hcd *xhci, struct xhci_ring *ring, xhci_link_segments(ring->enq_seg, first, ring->type, chain_links); xhci_link_segments(last, next, ring->type, chain_links); ring->num_segs += num_segs; - ring->num_trbs_free += (TRBS_PER_SEGMENT - 1) * num_segs; if (ring->type != TYPE_EVENT && ring->enq_seg == ring->last_seg) { ring->last_seg->trbs[TRBS_PER_SEGMENT-1].link.control @@ -422,22 +421,14 @@ void xhci_free_endpoint_ring(struct xhci_hcd *xhci, * Allocate a new ring which has same segment numbers and link the two rings. */ int xhci_ring_expansion(struct xhci_hcd *xhci, struct xhci_ring *ring, - unsigned int num_trbs, gfp_t flags) + unsigned int num_new_segs, gfp_t flags) { struct xhci_segment *first; struct xhci_segment *last; - unsigned int num_segs; - unsigned int num_segs_needed; int ret; - num_segs_needed = (num_trbs + (TRBS_PER_SEGMENT - 1) - 1) / - (TRBS_PER_SEGMENT - 1); - - /* Allocate number of segments we needed, or double the ring size */ - num_segs = max(ring->num_segs, num_segs_needed); - ret = xhci_alloc_segments_for_ring(xhci, &first, &last, - num_segs, ring->cycle_state, ring->type, + num_new_segs, ring->cycle_state, ring->type, ring->bounce_buf_len, flags); if (ret) return -ENOMEM; @@ -457,7 +448,7 @@ int xhci_ring_expansion(struct xhci_hcd *xhci, struct xhci_ring *ring, return ret; } - xhci_link_rings(xhci, ring, first, last, num_segs); + xhci_link_rings(xhci, ring, first, last, num_new_segs); trace_xhci_ring_expansion(ring); xhci_dbg_trace(xhci, trace_xhci_dbg_ring_expansion, "ring expansion succeed, now has %d segments", @@ -1831,13 +1822,15 @@ xhci_free_interrupter(struct xhci_hcd *xhci, struct xhci_interrupter *ir) * low or high 32 bits of ERSTBA immediately causes the controller to * dereference the partially cleared 64 bit address, causing IOMMU error. */ - tmp = readl(&ir->ir_set->erst_size); - tmp &= ERST_SIZE_MASK; - writel(tmp, &ir->ir_set->erst_size); - - tmp64 = xhci_read_64(xhci, &ir->ir_set->erst_dequeue); - tmp64 &= (u64) ERST_PTR_MASK; - xhci_write_64(xhci, tmp64, &ir->ir_set->erst_dequeue); + if (ir->ir_set) { + tmp = readl(&ir->ir_set->erst_size); + tmp &= ERST_SIZE_MASK; + writel(tmp, &ir->ir_set->erst_size); + + tmp64 = xhci_read_64(xhci, &ir->ir_set->erst_dequeue); + tmp64 &= (u64) ERST_PTR_MASK; + xhci_write_64(xhci, tmp64, &ir->ir_set->erst_dequeue); + } /* free interrrupter event ring */ if (ir->event_ring) @@ -1968,7 +1961,7 @@ static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports, { u32 temp, port_offset, port_count; int i; - u8 major_revision, minor_revision; + u8 major_revision, minor_revision, tmp_minor_revision; struct xhci_hub *rhub; struct device *dev = xhci_to_hcd(xhci)->self.sysdev; struct xhci_port_cap *port_cap; @@ -1988,6 +1981,15 @@ static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports, */ if (minor_revision > 0x00 && minor_revision < 0x10) minor_revision <<= 4; + /* + * Some zhaoxin's xHCI controller that follow usb3.1 spec + * but only support Gen1. + */ + if (xhci->quirks & XHCI_ZHAOXIN_HOST) { + tmp_minor_revision = minor_revision; + minor_revision = 0; + } + } else if (major_revision <= 0x02) { rhub = &xhci->usb2_rhub; } else { @@ -1996,10 +1998,6 @@ static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports, /* Ignoring port protocol we can't understand. FIXME */ return; } - rhub->maj_rev = XHCI_EXT_PORT_MAJOR(temp); - - if (rhub->min_rev < minor_revision) - rhub->min_rev = minor_revision; /* Port offset and count in the third dword, see section 7.2 */ temp = readl(addr + 2); @@ -2017,8 +2015,6 @@ static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports, if (xhci->num_port_caps > max_caps) return; - port_cap->maj_rev = major_revision; - port_cap->min_rev = minor_revision; port_cap->psi_count = XHCI_EXT_PORT_PSIC(temp); if (port_cap->psi_count) { @@ -2039,6 +2035,11 @@ static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports, XHCI_EXT_PORT_PSIV(port_cap->psi[i - 1]))) port_cap->psi_uid_count++; + if (xhci->quirks & XHCI_ZHAOXIN_HOST && + major_revision == 0x03 && + XHCI_EXT_PORT_PSIV(port_cap->psi[i]) >= 5) + minor_revision = tmp_minor_revision; + xhci_dbg(xhci, "PSIV:%d PSIE:%d PLT:%d PFD:%d LP:%d PSIM:%d\n", XHCI_EXT_PORT_PSIV(port_cap->psi[i]), XHCI_EXT_PORT_PSIE(port_cap->psi[i]), @@ -2048,6 +2049,15 @@ static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports, XHCI_EXT_PORT_PSIM(port_cap->psi[i])); } } + + rhub->maj_rev = major_revision; + + if (rhub->min_rev < minor_revision) + rhub->min_rev = minor_revision; + + port_cap->maj_rev = major_revision; + port_cap->min_rev = minor_revision; + /* cache usb2 port capabilities */ if (major_revision < 0x03 && xhci->num_ext_caps < max_caps) xhci->ext_caps[xhci->num_ext_caps++] = temp; @@ -2227,43 +2237,50 @@ static int xhci_setup_port_arrays(struct xhci_hcd *xhci, gfp_t flags) } static struct xhci_interrupter * -xhci_alloc_interrupter(struct xhci_hcd *xhci, unsigned int intr_num, gfp_t flags) +xhci_alloc_interrupter(struct xhci_hcd *xhci, gfp_t flags) { struct device *dev = xhci_to_hcd(xhci)->self.sysdev; struct xhci_interrupter *ir; - u64 erst_base; - u32 erst_size; int ret; - if (intr_num > xhci->max_interrupters) { - xhci_warn(xhci, "Can't allocate interrupter %d, max interrupters %d\n", - intr_num, xhci->max_interrupters); - return NULL; - } - - if (xhci->interrupter) { - xhci_warn(xhci, "Can't allocate already set up interrupter %d\n", intr_num); - return NULL; - } - ir = kzalloc_node(sizeof(*ir), flags, dev_to_node(dev)); if (!ir) return NULL; - ir->ir_set = &xhci->run_regs->ir_set[intr_num]; ir->event_ring = xhci_ring_alloc(xhci, ERST_NUM_SEGS, 1, TYPE_EVENT, 0, flags); if (!ir->event_ring) { - xhci_warn(xhci, "Failed to allocate interrupter %d event ring\n", intr_num); - goto fail_ir; + xhci_warn(xhci, "Failed to allocate interrupter event ring\n"); + kfree(ir); + return NULL; } ret = xhci_alloc_erst(xhci, ir->event_ring, &ir->erst, flags); if (ret) { - xhci_warn(xhci, "Failed to allocate interrupter %d erst\n", intr_num); - goto fail_ev; + xhci_warn(xhci, "Failed to allocate interrupter erst\n"); + xhci_ring_free(xhci, ir->event_ring); + kfree(ir); + return NULL; + } + return ir; +} + +static int +xhci_add_interrupter(struct xhci_hcd *xhci, struct xhci_interrupter *ir, + unsigned int intr_num) +{ + u64 erst_base; + u32 erst_size; + + if (intr_num > xhci->max_interrupters) { + xhci_warn(xhci, "Can't add interrupter %d, max interrupters %d\n", + intr_num, xhci->max_interrupters); + return -EINVAL; } + + ir->ir_set = &xhci->run_regs->ir_set[intr_num]; + /* set ERST count with the number of entries in the segment table */ erst_size = readl(&ir->ir_set->erst_size); erst_size &= ERST_SIZE_MASK; @@ -2278,14 +2295,7 @@ xhci_alloc_interrupter(struct xhci_hcd *xhci, unsigned int intr_num, gfp_t flags /* Set the event ring dequeue address of this interrupter */ xhci_set_hc_event_deq(xhci, ir); - return ir; - -fail_ev: - xhci_ring_free(xhci, ir->event_ring); -fail_ir: - kfree(ir); - - return NULL; + return 0; } int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) @@ -2352,8 +2362,12 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) * and our use of dma addresses in the trb_address_map radix tree needs * TRB_SEGMENT_SIZE alignment, so we pick the greater alignment need. */ - xhci->segment_pool = dma_pool_create("xHCI ring segments", dev, - TRB_SEGMENT_SIZE, TRB_SEGMENT_SIZE, xhci->page_size); + if (xhci->quirks & XHCI_ZHAOXIN_TRB_FETCH) + xhci->segment_pool = dma_pool_create("xHCI ring segments", dev, + TRB_SEGMENT_SIZE * 2, TRB_SEGMENT_SIZE * 2, xhci->page_size * 2); + else + xhci->segment_pool = dma_pool_create("xHCI ring segments", dev, + TRB_SEGMENT_SIZE, TRB_SEGMENT_SIZE, xhci->page_size); /* See Table 46 and Note on Figure 55 */ xhci->device_pool = dma_pool_create("xHCI input/output contexts", dev, @@ -2407,15 +2421,17 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) "// Doorbell array is located at offset 0x%x from cap regs base addr", val); xhci->dba = (void __iomem *) xhci->cap_regs + val; - /* Set ir_set to interrupt register set 0 */ - /* allocate and set up primary interrupter with an event ring. */ + /* Allocate and set up primary interrupter 0 with an event ring. */ xhci_dbg_trace(xhci, trace_xhci_dbg_init, "Allocating primary event ring"); - xhci->interrupter = xhci_alloc_interrupter(xhci, 0, flags); + xhci->interrupter = xhci_alloc_interrupter(xhci, flags); if (!xhci->interrupter) goto fail; + if (xhci_add_interrupter(xhci, xhci->interrupter, 0)) + goto fail; + xhci->isoc_bei_interval = AVOID_BEI_INTERVAL_MAX; /* diff --git a/drivers/usb/host/xhci-mtk.c b/drivers/usb/host/xhci-mtk.c index 90cf40d6d0c3170df180dc44d7522821aa04a0e7..51d9d4d4f6a52dbeb5113700e598b8728591efba 100644 --- a/drivers/usb/host/xhci-mtk.c +++ b/drivers/usb/host/xhci-mtk.c @@ -418,12 +418,6 @@ static void xhci_mtk_quirks(struct device *dev, struct xhci_hcd *xhci) struct usb_hcd *hcd = xhci_to_hcd(xhci); struct xhci_hcd_mtk *mtk = hcd_to_mtk(hcd); - /* - * As of now platform drivers don't provide MSI support so we ensure - * here that the generic code does not try to make a pci_dev from our - * dev struct in order to setup MSI - */ - xhci->quirks |= XHCI_PLAT; xhci->quirks |= XHCI_MTK_HOST; /* * MTK host controller gives a spurious successful event after a @@ -673,7 +667,7 @@ static int xhci_mtk_probe(struct platform_device *pdev) return ret; } -static int xhci_mtk_remove(struct platform_device *pdev) +static void xhci_mtk_remove(struct platform_device *pdev) { struct xhci_hcd_mtk *mtk = platform_get_drvdata(pdev); struct usb_hcd *hcd = mtk->hcd; @@ -703,8 +697,6 @@ static int xhci_mtk_remove(struct platform_device *pdev) pm_runtime_disable(dev); pm_runtime_put_noidle(dev); pm_runtime_set_suspended(dev); - - return 0; } static int __maybe_unused xhci_mtk_suspend(struct device *dev) @@ -824,7 +816,7 @@ MODULE_DEVICE_TABLE(of, mtk_xhci_of_match); static struct platform_driver mtk_xhci_driver = { .probe = xhci_mtk_probe, - .remove = xhci_mtk_remove, + .remove_new = xhci_mtk_remove, .driver = { .name = "xhci-mtk", .pm = DEV_PM_OPS, diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index 79b3691f373f34e8f4d325b1e9ae57949c23a54d..c6742bae41c0db3f122af2058a69f02892371943 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -108,9 +108,6 @@ static void xhci_cleanup_msix(struct xhci_hcd *xhci) struct usb_hcd *hcd = xhci_to_hcd(xhci); struct pci_dev *pdev = to_pci_dev(hcd->self.controller); - if (xhci->quirks & XHCI_PLAT) - return; - /* return if using legacy interrupt */ if (hcd->irq > 0) return; @@ -208,10 +205,6 @@ static int xhci_try_enable_msi(struct usb_hcd *hcd) struct pci_dev *pdev; int ret; - /* The xhci platform device has set up IRQs through usb_add_hcd. */ - if (xhci->quirks & XHCI_PLAT) - return 0; - pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller); /* * Some Fresco Logic host controllers advertise MSI, but fail to @@ -528,6 +521,19 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) pdev->device == PCI_DEVICE_ID_AMD_PROMONTORYA_4)) xhci->quirks |= XHCI_NO_SOFT_RETRY; + if (pdev->vendor == PCI_VENDOR_ID_ZHAOXIN) { + xhci->quirks |= XHCI_ZHAOXIN_HOST; + xhci->quirks |= XHCI_LPM_SUPPORT; + + if (pdev->device == 0x9202) { + xhci->quirks |= XHCI_RESET_ON_RESUME; + xhci->quirks |= XHCI_ZHAOXIN_TRB_FETCH; + } + + if (pdev->device == 0x9203) + xhci->quirks |= XHCI_ZHAOXIN_TRB_FETCH; + } + /* xHC spec requires PCI devices to support D3hot and D3cold */ if (xhci->hci_version >= 0x120) xhci->quirks |= XHCI_DEFAULT_PM_RUNTIME_ALLOW; @@ -832,7 +838,7 @@ static int xhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup) return ret; } -static int xhci_pci_resume(struct usb_hcd *hcd, bool hibernated) +static int xhci_pci_resume(struct usb_hcd *hcd, pm_message_t msg) { struct xhci_hcd *xhci = hcd_to_xhci(hcd); struct pci_dev *pdev = to_pci_dev(hcd->self.controller); @@ -867,7 +873,7 @@ static int xhci_pci_resume(struct usb_hcd *hcd, bool hibernated) if (xhci->quirks & XHCI_PME_STUCK_QUIRK) xhci_pme_quirk(hcd); - retval = xhci_resume(xhci, hibernated); + retval = xhci_resume(xhci, msg); return retval; } diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c index b0c8e8efc43b6f04222d9376b2fb582b2a530292..b26ea7cb4357b503a30ae66591492bcc0850cb0f 100644 --- a/drivers/usb/host/xhci-plat.c +++ b/drivers/usb/host/xhci-plat.c @@ -78,12 +78,7 @@ static void xhci_plat_quirks(struct device *dev, struct xhci_hcd *xhci) { struct xhci_plat_priv *priv = xhci_to_priv(xhci); - /* - * As of now platform drivers don't provide MSI support so we ensure - * here that the generic code does not try to make a pci_dev from our - * dev struct in order to setup MSI - */ - xhci->quirks |= XHCI_PLAT | priv->quirks; + xhci->quirks |= priv->quirks; } /* called during probe() after chip reset completes */ @@ -294,10 +289,6 @@ int xhci_plat_probe(struct platform_device *pdev, struct device *sysdev, const s xhci->shared_hcd->usb_phy = devm_usb_get_phy_by_phandle(sysdev, "usb-phy", 1); if (IS_ERR(xhci->shared_hcd->usb_phy)) { - if (PTR_ERR(xhci->shared_hcd->usb_phy) != -ENODEV) - dev_err(sysdev, "%s get usb3phy fail (ret=%d)\n", - __func__, - (int)PTR_ERR(xhci->shared_hcd->usb_phy)); xhci->shared_hcd->usb_phy = NULL; } else { ret = usb_phy_init(xhci->shared_hcd->usb_phy); @@ -399,7 +390,7 @@ static int xhci_generic_plat_probe(struct platform_device *pdev) return xhci_plat_probe(pdev, sysdev, priv_match); } -int xhci_plat_remove(struct platform_device *dev) +void xhci_plat_remove(struct platform_device *dev) { struct usb_hcd *hcd = platform_get_drvdata(dev); struct xhci_hcd *xhci = hcd_to_xhci(hcd); @@ -407,8 +398,8 @@ int xhci_plat_remove(struct platform_device *dev) struct clk *reg_clk = xhci->reg_clk; struct usb_hcd *shared_hcd = xhci->shared_hcd; - pm_runtime_get_sync(&dev->dev); xhci->xhc_state |= XHCI_STATE_REMOVING; + pm_runtime_get_sync(&dev->dev); if (shared_hcd) { usb_remove_hcd(shared_hcd); @@ -430,8 +421,6 @@ int xhci_plat_remove(struct platform_device *dev) pm_runtime_disable(&dev->dev); pm_runtime_put_noidle(&dev->dev); pm_runtime_set_suspended(&dev->dev); - - return 0; } EXPORT_SYMBOL_GPL(xhci_plat_remove); @@ -478,7 +467,7 @@ static int __maybe_unused xhci_plat_resume(struct device *dev) if (ret) return ret; - ret = xhci_resume(xhci, 0); + ret = xhci_resume(xhci, PMSG_RESUME); if (ret) return ret; @@ -507,7 +496,7 @@ static int __maybe_unused xhci_plat_runtime_resume(struct device *dev) struct usb_hcd *hcd = dev_get_drvdata(dev); struct xhci_hcd *xhci = hcd_to_xhci(hcd); - return xhci_resume(xhci, 0); + return xhci_resume(xhci, PMSG_AUTO_RESUME); } const struct dev_pm_ops xhci_plat_pm_ops = { @@ -530,7 +519,7 @@ MODULE_DEVICE_TABLE(acpi, usb_xhci_acpi_match); static struct platform_driver usb_generic_xhci_driver = { .probe = xhci_generic_plat_probe, - .remove = xhci_plat_remove, + .remove_new = xhci_plat_remove, .shutdown = usb_hcd_platform_shutdown, .driver = { .name = "xhci-hcd", diff --git a/drivers/usb/host/xhci-plat.h b/drivers/usb/host/xhci-plat.h index 83b5b5aa9f8ef741e6b7f4b5cbcb431b53756e51..2d15386f2c504b7aa8b1798f1b41b1e81b1498c1 100644 --- a/drivers/usb/host/xhci-plat.h +++ b/drivers/usb/host/xhci-plat.h @@ -25,7 +25,7 @@ struct xhci_plat_priv { int xhci_plat_probe(struct platform_device *pdev, struct device *sysdev, const struct xhci_plat_priv *priv_match); -int xhci_plat_remove(struct platform_device *dev); +void xhci_plat_remove(struct platform_device *dev); extern const struct dev_pm_ops xhci_plat_pm_ops; #endif /* _XHCI_PLAT_H */ diff --git a/drivers/usb/host/xhci-rcar.c b/drivers/usb/host/xhci-rcar.c index ad966b797b892afb799d6c640a33cd504e56ac9a..bf5261fed32c4e168e36593a3e8b9868eaa4e087 100644 --- a/drivers/usb/host/xhci-rcar.c +++ b/drivers/usb/host/xhci-rcar.c @@ -276,10 +276,10 @@ static int xhci_renesas_probe(struct platform_device *pdev) } static struct platform_driver usb_xhci_renesas_driver = { - .probe = xhci_renesas_probe, - .remove = xhci_plat_remove, + .probe = xhci_renesas_probe, + .remove_new = xhci_plat_remove, .shutdown = usb_hcd_platform_shutdown, - .driver = { + .driver = { .name = "xhci-renesas-hcd", .pm = &xhci_plat_pm_ops, .of_match_table = usb_xhci_of_match, diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 2bc82b3a2f984c33e5d32b23336dce57acdf5a24..646ff125def5cfcd33e41f0051c8e06c4d8ba030 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -174,12 +174,10 @@ void inc_deq(struct xhci_hcd *xhci, struct xhci_ring *ring) /* All other rings have link trbs */ if (!trb_is_link(ring->dequeue)) { - if (last_trb_on_seg(ring->deq_seg, ring->dequeue)) { + if (last_trb_on_seg(ring->deq_seg, ring->dequeue)) xhci_warn(xhci, "Missing link TRB at end of segment\n"); - } else { + else ring->dequeue++; - ring->num_trbs_free++; - } } while (trb_is_link(ring->dequeue)) { @@ -221,9 +219,6 @@ static void inc_enq(struct xhci_hcd *xhci, struct xhci_ring *ring, unsigned int link_trb_count = 0; chain = le32_to_cpu(ring->enqueue->generic.field[3]) & TRB_CHAIN; - /* If this is not event ring, there is one less usable TRB */ - if (!trb_is_link(ring->enqueue)) - ring->num_trbs_free--; if (last_trb_on_seg(ring->enq_seg, ring->enqueue)) { xhci_err(xhci, "Tried to move enqueue past ring segment\n"); @@ -276,45 +271,84 @@ static void inc_enq(struct xhci_hcd *xhci, struct xhci_ring *ring, trace_xhci_inc_enq(ring); } -static int xhci_num_trbs_to(struct xhci_segment *start_seg, union xhci_trb *start, - struct xhci_segment *end_seg, union xhci_trb *end, - unsigned int num_segs) +/* + * Return number of free normal TRBs from enqueue to dequeue pointer on ring. + * Not counting an assumed link TRB at end of each TRBS_PER_SEGMENT sized segment. + * Only for transfer and command rings where driver is the producer, not for + * event rings. + */ +static unsigned int xhci_num_trbs_free(struct xhci_hcd *xhci, struct xhci_ring *ring) { + struct xhci_segment *enq_seg = ring->enq_seg; + union xhci_trb *enq = ring->enqueue; union xhci_trb *last_on_seg; - int num = 0; + unsigned int free = 0; int i = 0; + /* Ring might be empty even if enq != deq if enq is left on a link trb */ + if (trb_is_link(enq)) { + enq_seg = enq_seg->next; + enq = enq_seg->trbs; + } + + /* Empty ring, common case, don't walk the segments */ + if (enq == ring->dequeue) + return ring->num_segs * (TRBS_PER_SEGMENT - 1); + do { - if (start_seg == end_seg && end >= start) - return num + (end - start); - last_on_seg = &start_seg->trbs[TRBS_PER_SEGMENT - 1]; - num += last_on_seg - start; - start_seg = start_seg->next; - start = start_seg->trbs; - } while (i++ <= num_segs); - - return -EINVAL; + if (ring->deq_seg == enq_seg && ring->dequeue >= enq) + return free + (ring->dequeue - enq); + last_on_seg = &enq_seg->trbs[TRBS_PER_SEGMENT - 1]; + free += last_on_seg - enq; + enq_seg = enq_seg->next; + enq = enq_seg->trbs; + } while (i++ <= ring->num_segs); + + return free; } /* * Check to see if there's room to enqueue num_trbs on the ring and make sure * enqueue pointer will not advance into dequeue segment. See rules above. + * return number of new segments needed to ensure this. */ -static inline int room_on_ring(struct xhci_hcd *xhci, struct xhci_ring *ring, - unsigned int num_trbs) + +static unsigned int xhci_ring_expansion_needed(struct xhci_hcd *xhci, struct xhci_ring *ring, + unsigned int num_trbs) { - int num_trbs_in_deq_seg; + struct xhci_segment *seg; + int trbs_past_seg; + int enq_used; + int new_segs; + + enq_used = ring->enqueue - ring->enq_seg->trbs; + + /* how many trbs will be queued past the enqueue segment? */ + trbs_past_seg = enq_used + num_trbs - (TRBS_PER_SEGMENT - 1); - if (ring->num_trbs_free < num_trbs) + if (trbs_past_seg <= 0) return 0; - if (ring->type != TYPE_COMMAND && ring->type != TYPE_EVENT) { - num_trbs_in_deq_seg = ring->dequeue - ring->deq_seg->trbs; - if (ring->num_trbs_free < num_trbs + num_trbs_in_deq_seg) - return 0; + /* Empty ring special case, enqueue stuck on link trb while dequeue advanced */ + if (trb_is_link(ring->enqueue) && ring->enq_seg->next->trbs == ring->dequeue) + return 0; + + new_segs = 1 + (trbs_past_seg / (TRBS_PER_SEGMENT - 1)); + seg = ring->enq_seg; + + while (new_segs > 0) { + seg = seg->next; + if (seg == ring->deq_seg) { + xhci_dbg(xhci, "Ring expansion by %d segments needed\n", + new_segs); + xhci_dbg(xhci, "Adding %d trbs moves enq %d trbs into deq seg\n", + num_trbs, trbs_past_seg % TRBS_PER_SEGMENT); + return new_segs; + } + new_segs--; } - return 1; + return 0; } /* Ring the host controller doorbell after placing a command on the ring */ @@ -1268,10 +1302,7 @@ static void update_ring_for_set_deq_completion(struct xhci_hcd *xhci, unsigned int ep_index) { union xhci_trb *dequeue_temp; - int num_trbs_free_temp; - bool revert = false; - num_trbs_free_temp = ep_ring->num_trbs_free; dequeue_temp = ep_ring->dequeue; /* If we get two back-to-back stalls, and the first stalled transfer @@ -1287,7 +1318,6 @@ static void update_ring_for_set_deq_completion(struct xhci_hcd *xhci, while (ep_ring->dequeue != dev->eps[ep_index].queued_deq_ptr) { /* We have more usable TRBs */ - ep_ring->num_trbs_free++; ep_ring->dequeue++; if (trb_is_link(ep_ring->dequeue)) { if (ep_ring->dequeue == @@ -1297,15 +1327,10 @@ static void update_ring_for_set_deq_completion(struct xhci_hcd *xhci, ep_ring->dequeue = ep_ring->deq_seg->trbs; } if (ep_ring->dequeue == dequeue_temp) { - revert = true; + xhci_dbg(xhci, "Unable to find new dequeue pointer\n"); break; } } - - if (revert) { - xhci_dbg(xhci, "Unable to find new dequeue pointer\n"); - ep_ring->num_trbs_free = num_trbs_free_temp; - } } /* @@ -2160,7 +2185,6 @@ static int finish_td(struct xhci_hcd *xhci, struct xhci_virt_ep *ep, u32 trb_comp_code) { struct xhci_ep_ctx *ep_ctx; - int trbs_freed; ep_ctx = xhci_get_ep_ctx(xhci, ep->vdev->out_ctx, ep->ep_index); @@ -2230,13 +2254,6 @@ static int finish_td(struct xhci_hcd *xhci, struct xhci_virt_ep *ep, } /* Update ring dequeue pointer */ - trbs_freed = xhci_num_trbs_to(ep_ring->deq_seg, ep_ring->dequeue, - td->last_trb_seg, td->last_trb, - ep_ring->num_segs); - if (trbs_freed < 0) - xhci_dbg(xhci, "Failed to count freed trbs at TD finish\n"); - else - ep_ring->num_trbs_free += trbs_freed; ep_ring->dequeue = td->last_trb; ep_ring->deq_seg = td->last_trb_seg; inc_deq(xhci, ep_ring); @@ -2460,7 +2477,6 @@ static int skip_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td, /* Update ring dequeue pointer */ ep->ring->dequeue = td->last_trb; ep->ring->deq_seg = td->last_trb_seg; - ep->ring->num_trbs_free += td->num_trbs - 1; inc_deq(xhci, ep->ring); return xhci_td_cleanup(xhci, td, ep->ring, status); @@ -3165,13 +3181,13 @@ static void queue_trb(struct xhci_hcd *xhci, struct xhci_ring *ring, /* * Does various checks on the endpoint ring, and makes it ready to queue num_trbs. - * FIXME allocate segments if the ring is full. + * expand ring if it start to be full. */ static int prepare_ring(struct xhci_hcd *xhci, struct xhci_ring *ep_ring, u32 ep_state, unsigned int num_trbs, gfp_t mem_flags) { - unsigned int num_trbs_needed; unsigned int link_trb_count = 0; + unsigned int new_segs = 0; /* Make sure the endpoint has been added to xHC schedule */ switch (ep_state) { @@ -3202,20 +3218,17 @@ static int prepare_ring(struct xhci_hcd *xhci, struct xhci_ring *ep_ring, return -EINVAL; } - while (1) { - if (room_on_ring(xhci, ep_ring, num_trbs)) - break; - - if (ep_ring == xhci->cmd_ring) { - xhci_err(xhci, "Do not support expand command ring\n"); - return -ENOMEM; - } + if (ep_ring != xhci->cmd_ring) { + new_segs = xhci_ring_expansion_needed(xhci, ep_ring, num_trbs); + } else if (xhci_num_trbs_free(xhci, ep_ring) <= num_trbs) { + xhci_err(xhci, "Do not support expand command ring\n"); + return -ENOMEM; + } + if (new_segs) { xhci_dbg_trace(xhci, trace_xhci_dbg_ring_expansion, "ERROR no room on ep ring, try ring expansion"); - num_trbs_needed = num_trbs - ep_ring->num_trbs_free; - if (xhci_ring_expansion(xhci, ep_ring, num_trbs_needed, - mem_flags)) { + if (xhci_ring_expansion(xhci, ep_ring, new_segs, mem_flags)) { xhci_err(xhci, "Ring expansion failed\n"); return -ENOMEM; } @@ -4185,7 +4198,6 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags, ep_ring->enqueue = urb_priv->td[0].first_trb; ep_ring->enq_seg = urb_priv->td[0].start_seg; ep_ring->cycle_state = start_cycle; - ep_ring->num_trbs_free = ep_ring->num_trbs_free_temp; usb_hcd_unlink_urb_from_ep(bus_to_hcd(urb->dev->bus), urb); return ret; } @@ -4267,7 +4279,6 @@ int xhci_queue_isoc_tx_prepare(struct xhci_hcd *xhci, gfp_t mem_flags, } skip_start_over: - ep_ring->num_trbs_free_temp = ep_ring->num_trbs_free; return xhci_queue_isoc_tx(xhci, mem_flags, urb, slot_id, ep_index); } diff --git a/drivers/usb/host/xhci-tegra.c b/drivers/usb/host/xhci-tegra.c index c75d9324414366c993a9d9729c0c0d7066381dbb..6ca8a37e53e1f0f26a90e6f56ff3a388c6c050f0 100644 --- a/drivers/usb/host/xhci-tegra.c +++ b/drivers/usb/host/xhci-tegra.c @@ -1828,6 +1828,9 @@ static int tegra_xusb_probe(struct platform_device *pdev) goto remove_usb2; } + if (HCC_MAX_PSA(xhci->hcc_params) >= 4) + xhci->shared_hcd->can_do_streams = 1; + err = usb_add_hcd(xhci->shared_hcd, tegra->xhci_irq, IRQF_SHARED); if (err < 0) { dev_err(&pdev->dev, "failed to add shared HCD: %d\n", err); @@ -1909,7 +1912,7 @@ static int tegra_xusb_probe(struct platform_device *pdev) return err; } -static int tegra_xusb_remove(struct platform_device *pdev) +static void tegra_xusb_remove(struct platform_device *pdev) { struct tegra_xusb *tegra = platform_get_drvdata(pdev); struct xhci_hcd *xhci = hcd_to_xhci(tegra->hcd); @@ -1939,8 +1942,6 @@ static int tegra_xusb_remove(struct platform_device *pdev) tegra_xusb_clk_disable(tegra); regulator_bulk_disable(tegra->soc->num_supplies, tegra->supplies); tegra_xusb_padctl_put(tegra->padctl); - - return 0; } static bool xhci_hub_ports_suspended(struct xhci_hub *hub) @@ -2272,7 +2273,7 @@ static int tegra_xusb_exit_elpg(struct tegra_xusb *tegra, bool runtime) if (wakeup) tegra_xhci_disable_phy_sleepwalk(tegra); - err = xhci_resume(xhci, 0); + err = xhci_resume(xhci, runtime ? PMSG_AUTO_RESUME : PMSG_RESUME); if (err < 0) { dev_err(tegra->dev, "failed to resume XHCI: %d\n", err); goto disable_phy; @@ -2650,7 +2651,7 @@ MODULE_DEVICE_TABLE(of, tegra_xusb_of_match); static struct platform_driver tegra_xusb_driver = { .probe = tegra_xusb_probe, - .remove = tegra_xusb_remove, + .remove_new = tegra_xusb_remove, .driver = { .name = "tegra-xusb", .pm = &tegra_xusb_pm_ops, @@ -2662,7 +2663,6 @@ static void tegra_xhci_quirks(struct device *dev, struct xhci_hcd *xhci) { struct tegra_xusb *tegra = dev_get_drvdata(dev); - xhci->quirks |= XHCI_PLAT; if (tegra && tegra->soc->lpm_support) xhci->quirks |= XHCI_LPM_SUPPORT; } diff --git a/drivers/usb/host/xhci-trace.h b/drivers/usb/host/xhci-trace.h index 4286dba5b1574fd79c38c574d69b51a8e58e83ca..d6b32f2ad90ecbc408b5a6723fdcf7c0a9c74814 100644 --- a/drivers/usb/host/xhci-trace.h +++ b/drivers/usb/host/xhci-trace.h @@ -80,20 +80,16 @@ DECLARE_EVENT_CLASS(xhci_log_ctx, __field(dma_addr_t, ctx_dma) __field(u8 *, ctx_va) __field(unsigned, ctx_ep_num) - __field(int, slot_id) __dynamic_array(u32, ctx_data, ((HCC_64BYTE_CONTEXT(xhci->hcc_params) + 1) * 8) * ((ctx->type == XHCI_CTX_TYPE_INPUT) + ep_num + 1)) ), TP_fast_assign( - struct usb_device *udev; - udev = to_usb_device(xhci_to_hcd(xhci)->self.controller); __entry->ctx_64 = HCC_64BYTE_CONTEXT(xhci->hcc_params); __entry->ctx_type = ctx->type; __entry->ctx_dma = ctx->dma; __entry->ctx_va = ctx->bytes; - __entry->slot_id = udev->slot_id; __entry->ctx_ep_num = ep_num; memcpy(__get_dynamic_array(ctx_data), ctx->bytes, ((HCC_64BYTE_CONTEXT(xhci->hcc_params) + 1) * 32) * @@ -462,7 +458,6 @@ DECLARE_EVENT_CLASS(xhci_log_ring, __field(unsigned int, num_segs) __field(unsigned int, stream_id) __field(unsigned int, cycle_state) - __field(unsigned int, num_trbs_free) __field(unsigned int, bounce_buf_len) ), TP_fast_assign( @@ -473,18 +468,16 @@ DECLARE_EVENT_CLASS(xhci_log_ring, __entry->enq_seg = ring->enq_seg->dma; __entry->deq_seg = ring->deq_seg->dma; __entry->cycle_state = ring->cycle_state; - __entry->num_trbs_free = ring->num_trbs_free; __entry->bounce_buf_len = ring->bounce_buf_len; __entry->enq = xhci_trb_virt_to_dma(ring->enq_seg, ring->enqueue); __entry->deq = xhci_trb_virt_to_dma(ring->deq_seg, ring->dequeue); ), - TP_printk("%s %p: enq %pad(%pad) deq %pad(%pad) segs %d stream %d free_trbs %d bounce %d cycle %d", + TP_printk("%s %p: enq %pad(%pad) deq %pad(%pad) segs %d stream %d bounce %d cycle %d", xhci_ring_type_string(__entry->type), __entry->ring, &__entry->enq, &__entry->enq_seg, &__entry->deq, &__entry->deq_seg, __entry->num_segs, __entry->stream_id, - __entry->num_trbs_free, __entry->bounce_buf_len, __entry->cycle_state ) diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 78790dc13c5f143f1262e4dd171402d8ed9a15ba..fae994f679d45b589c6a1e45bb0af2c2047f346a 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -833,7 +833,7 @@ static bool xhci_pending_portevent(struct xhci_hcd *xhci) ports = xhci->usb3_rhub.ports; while (port_index--) { portsc = readl(ports[port_index]->addr); - if (portsc & PORT_CHANGE_MASK || + if (portsc & (PORT_CHANGE_MASK | PORT_CAS) || (portsc & PORT_PLS_MASK) == XDEV_RESUME) return true; } @@ -960,8 +960,9 @@ EXPORT_SYMBOL_GPL(xhci_suspend); * This is called when the machine transition from S3/S4 mode. * */ -int xhci_resume(struct xhci_hcd *xhci, bool hibernated) +int xhci_resume(struct xhci_hcd *xhci, pm_message_t msg) { + bool hibernated = (msg.event == PM_EVENT_RESTORE); u32 command, temp = 0; struct usb_hcd *hcd = xhci_to_hcd(xhci); int retval = 0; @@ -1027,7 +1028,8 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated) temp = readl(&xhci->op_regs->status); /* re-initialize the HC on Restore Error, or Host Controller Error */ - if (temp & (STS_SRE | STS_HCE)) { + if ((temp & (STS_SRE | STS_HCE)) && + !(xhci->xhc_state & XHCI_STATE_REMOVING)) { reinit_xhc = true; if (!xhci->broken_suspend) xhci_warn(xhci, "xHC error in resume, USBSTS 0x%x, Reinit\n", temp); @@ -1116,7 +1118,7 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated) * the first wake signalling failed, give it that chance. */ pending_portevent = xhci_pending_portevent(xhci); - if (!pending_portevent) { + if (!pending_portevent && msg.event == PM_EVENT_AUTO_RESUME) { msleep(120); pending_portevent = xhci_pending_portevent(xhci); } @@ -4604,7 +4606,7 @@ static u16 xhci_calculate_u1_timeout(struct xhci_hcd *xhci, } } - if (xhci->quirks & XHCI_INTEL_HOST) + if (xhci->quirks & (XHCI_INTEL_HOST | XHCI_ZHAOXIN_HOST)) timeout_ns = xhci_calculate_intel_u1_timeout(udev, desc); else timeout_ns = udev->u1_params.sel; @@ -4668,7 +4670,7 @@ static u16 xhci_calculate_u2_timeout(struct xhci_hcd *xhci, } } - if (xhci->quirks & XHCI_INTEL_HOST) + if (xhci->quirks & (XHCI_INTEL_HOST | XHCI_ZHAOXIN_HOST)) timeout_ns = xhci_calculate_intel_u2_timeout(udev, desc); else timeout_ns = udev->u2_params.sel; @@ -4740,37 +4742,30 @@ static int xhci_update_timeout_for_interface(struct xhci_hcd *xhci, return 0; } -static int xhci_check_intel_tier_policy(struct usb_device *udev, +static int xhci_check_tier_policy(struct xhci_hcd *xhci, + struct usb_device *udev, enum usb3_link_state state) { - struct usb_device *parent; - unsigned int num_hubs; + struct usb_device *parent = udev->parent; + int tier = 1; /* roothub is tier1 */ - /* Don't enable U1 if the device is on a 2nd tier hub or lower. */ - for (parent = udev->parent, num_hubs = 0; parent->parent; - parent = parent->parent) - num_hubs++; + while (parent) { + parent = parent->parent; + tier++; + } - if (num_hubs < 2) - return 0; + if (xhci->quirks & XHCI_INTEL_HOST && tier > 3) + goto fail; + if (xhci->quirks & XHCI_ZHAOXIN_HOST && tier > 2) + goto fail; - dev_dbg(&udev->dev, "Disabling U1/U2 link state for device" - " below second-tier hub.\n"); - dev_dbg(&udev->dev, "Plug device into first-tier hub " - "to decrease power consumption.\n"); + return 0; +fail: + dev_dbg(&udev->dev, "Tier policy prevents U1/U2 LPM states for devices at tier %d\n", + tier); return -E2BIG; } -static int xhci_check_tier_policy(struct xhci_hcd *xhci, - struct usb_device *udev, - enum usb3_link_state state) -{ - if (xhci->quirks & XHCI_INTEL_HOST) - return xhci_check_intel_tier_policy(udev, state); - else - return 0; -} - /* Returns the U1 or U2 timeout that should be enabled. * If the tier check or timeout setting functions return with a non-zero exit * code, that means the timeout value has been finalized and we shouldn't look @@ -5180,7 +5175,8 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks) xhci->quirks |= quirks; - get_quirks(dev, xhci); + if (get_quirks) + get_quirks(dev, xhci); /* In xhci controllers which follow xhci 1.0 spec gives a spurious * success event after a short transfer. This quirk will ignore such diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 6b690ec91ff3ae1044905657dd1f2f0f0f749d80..7e282b4522c0aa16c15398afefb933ecec2db7e5 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1633,8 +1633,7 @@ struct xhci_ring { u32 cycle_state; unsigned int stream_id; unsigned int num_segs; - unsigned int num_trbs_free; - unsigned int num_trbs_free_temp; + unsigned int num_trbs_free; /* used only by xhci DbC */ unsigned int bounce_buf_len; enum xhci_ring_type type; bool last_td_was_short; @@ -1874,7 +1873,7 @@ struct xhci_hcd { #define XHCI_SPURIOUS_REBOOT BIT_ULL(13) #define XHCI_COMP_MODE_QUIRK BIT_ULL(14) #define XHCI_AVOID_BEI BIT_ULL(15) -#define XHCI_PLAT BIT_ULL(16) +#define XHCI_PLAT BIT_ULL(16) /* Deprecated */ #define XHCI_SLOW_SUSPEND BIT_ULL(17) #define XHCI_SPURIOUS_WAKEUP BIT_ULL(18) /* For controllers with a broken beyond repair streams implementation */ @@ -1905,6 +1904,8 @@ struct xhci_hcd { #define XHCI_EP_CTX_BROKEN_DCS BIT_ULL(42) #define XHCI_SUSPEND_RESUME_CLKS BIT_ULL(43) #define XHCI_RESET_TO_DEFAULT BIT_ULL(44) +#define XHCI_ZHAOXIN_TRB_FETCH BIT_ULL(45) +#define XHCI_ZHAOXIN_HOST BIT_ULL(46) unsigned int num_active_eps; unsigned int limit_active_eps; @@ -2140,7 +2141,7 @@ int xhci_disable_slot(struct xhci_hcd *xhci, u32 slot_id); int xhci_ext_cap_init(struct xhci_hcd *xhci); int xhci_suspend(struct xhci_hcd *xhci, bool do_wakeup); -int xhci_resume(struct xhci_hcd *xhci, bool hibernated); +int xhci_resume(struct xhci_hcd *xhci, pm_message_t msg); irqreturn_t xhci_irq(struct usb_hcd *hcd); irqreturn_t xhci_msi_irq(int irq, void *hcd); diff --git a/drivers/usb/isp1760/isp1760-if.c b/drivers/usb/isp1760/isp1760-if.c index 65ba5aca2a4f8d32ca1027228e7a434256621591..fe1e3985419a289bbaa588233f479b6f6b005b70 100644 --- a/drivers/usb/isp1760/isp1760-if.c +++ b/drivers/usb/isp1760/isp1760-if.c @@ -246,11 +246,9 @@ static int isp1760_plat_probe(struct platform_device *pdev) return 0; } -static int isp1760_plat_remove(struct platform_device *pdev) +static void isp1760_plat_remove(struct platform_device *pdev) { isp1760_unregister(&pdev->dev); - - return 0; } #ifdef CONFIG_OF @@ -265,7 +263,7 @@ MODULE_DEVICE_TABLE(of, isp1760_of_match); static struct platform_driver isp1760_plat_driver = { .probe = isp1760_plat_probe, - .remove = isp1760_plat_remove, + .remove_new = isp1760_plat_remove, .driver = { .name = "isp1760", .of_match_table = of_match_ptr(isp1760_of_match), diff --git a/drivers/usb/misc/onboard_usb_hub.c b/drivers/usb/misc/onboard_usb_hub.c index 12fc6eb67c3bf23a253ee1f48667499021d830d7..83f14ca1d38e728d052f600255e703f935e98788 100644 --- a/drivers/usb/misc/onboard_usb_hub.c +++ b/drivers/usb/misc/onboard_usb_hub.c @@ -278,7 +278,7 @@ static int onboard_hub_probe(struct platform_device *pdev) return 0; } -static int onboard_hub_remove(struct platform_device *pdev) +static void onboard_hub_remove(struct platform_device *pdev) { struct onboard_hub *hub = dev_get_drvdata(&pdev->dev); struct usbdev_node *node; @@ -306,7 +306,7 @@ static int onboard_hub_remove(struct platform_device *pdev) mutex_unlock(&hub->lock); - return onboard_hub_power_off(hub); + onboard_hub_power_off(hub); } MODULE_DEVICE_TABLE(of, onboard_hub_match); @@ -317,7 +317,7 @@ static const struct dev_pm_ops __maybe_unused onboard_hub_pm_ops = { static struct platform_driver onboard_hub_driver = { .probe = onboard_hub_probe, - .remove = onboard_hub_remove, + .remove_new = onboard_hub_remove, .driver = { .name = "onboard-usb-hub", diff --git a/drivers/usb/misc/qcom_eud.c b/drivers/usb/misc/qcom_eud.c index b7f13df007646f58ab14d8a9729d73e88b8bac8b..7f371ea1248c32217ccb2e1f7e900d7e0d98753a 100644 --- a/drivers/usb/misc/qcom_eud.c +++ b/drivers/usb/misc/qcom_eud.c @@ -22,10 +22,10 @@ #define EUD_REG_VBUS_INT_CLR 0x0080 #define EUD_REG_CSR_EUD_EN 0x1014 #define EUD_REG_SW_ATTACH_DET 0x1018 -#define EUD_REG_EUD_EN2 0x0000 +#define EUD_REG_EUD_EN2 0x0000 #define EUD_ENABLE BIT(0) -#define EUD_INT_PET_EUD BIT(0) +#define EUD_INT_PET_EUD BIT(0) #define EUD_INT_VBUS BIT(2) #define EUD_INT_SAFE_MODE BIT(4) #define EUD_INT_ALL (EUD_INT_VBUS | EUD_INT_SAFE_MODE) @@ -217,7 +217,7 @@ static int eud_probe(struct platform_device *pdev) return 0; } -static int eud_remove(struct platform_device *pdev) +static void eud_remove(struct platform_device *pdev) { struct eud_chip *chip = platform_get_drvdata(pdev); @@ -226,8 +226,6 @@ static int eud_remove(struct platform_device *pdev) device_init_wakeup(&pdev->dev, false); disable_irq_wake(chip->irq); - - return 0; } static const struct of_device_id eud_dt_match[] = { @@ -238,7 +236,7 @@ MODULE_DEVICE_TABLE(of, eud_dt_match); static struct platform_driver eud_driver = { .probe = eud_probe, - .remove = eud_remove, + .remove_new = eud_remove, .driver = { .name = "qcom_eud", .dev_groups = eud_groups, diff --git a/drivers/usb/misc/usb251xb.c b/drivers/usb/misc/usb251xb.c index ce1da80d33656f93b84135aa0a08311d3d1e0b65..e4edb486b69e05bbf7a58427c20dc17d8dce0961 100644 --- a/drivers/usb/misc/usb251xb.c +++ b/drivers/usb/misc/usb251xb.c @@ -416,14 +416,13 @@ static int usb251xb_get_ofdata(struct usb251xb *hub, return dev_err_probe(dev, PTR_ERR(hub->gpio_reset), "unable to request GPIO reset pin\n"); - if (of_property_read_u16_array(np, "vendor-id", &hub->vendor_id, 1)) + if (of_property_read_u16(np, "vendor-id", &hub->vendor_id)) hub->vendor_id = USB251XB_DEF_VENDOR_ID; - if (of_property_read_u16_array(np, "product-id", - &hub->product_id, 1)) + if (of_property_read_u16(np, "product-id", &hub->product_id)) hub->product_id = data->product_id; - if (of_property_read_u16_array(np, "device-id", &hub->device_id, 1)) + if (of_property_read_u16(np, "device-id", &hub->device_id)) hub->device_id = USB251XB_DEF_DEVICE_ID; hub->conf_data1 = USB251XB_DEF_CONFIG_DATA_1; @@ -532,7 +531,7 @@ static int usb251xb_get_ofdata(struct usb251xb *hub, if (!of_property_read_u32(np, "power-on-time-ms", &property_u32)) hub->power_on_time = min_t(u8, property_u32 / 2, 255); - if (of_property_read_u16_array(np, "language-id", &hub->lang_id, 1)) + if (of_property_read_u16(np, "language-id", &hub->lang_id)) hub->lang_id = USB251XB_DEF_LANGUAGE_ID; if (of_property_read_u8(np, "boost-up", &hub->boost_up)) @@ -746,7 +745,7 @@ static struct i2c_driver usb251xb_i2c_driver = { .of_match_table = usb251xb_of_match, .pm = &usb251xb_pm_ops, }, - .probe_new = usb251xb_i2c_probe, + .probe = usb251xb_i2c_probe, .id_table = usb251xb_id, }; diff --git a/drivers/usb/misc/usb3503.c b/drivers/usb/misc/usb3503.c index c6cfd1edaf762bed1c24d4501df4a90c631e9e74..72765077932c45045706b6b6804eb9b59ae39cfd 100644 --- a/drivers/usb/misc/usb3503.c +++ b/drivers/usb/misc/usb3503.c @@ -335,14 +335,12 @@ static int usb3503_platform_probe(struct platform_device *pdev) return usb3503_probe(hub); } -static int usb3503_platform_remove(struct platform_device *pdev) +static void usb3503_platform_remove(struct platform_device *pdev) { struct usb3503 *hub; hub = platform_get_drvdata(pdev); clk_disable_unprepare(hub->clk); - - return 0; } static int __maybe_unused usb3503_suspend(struct usb3503 *hub) @@ -413,7 +411,7 @@ static struct i2c_driver usb3503_i2c_driver = { .pm = pm_ptr(&usb3503_i2c_pm_ops), .of_match_table = of_match_ptr(usb3503_of_match), }, - .probe_new = usb3503_i2c_probe, + .probe = usb3503_i2c_probe, .remove = usb3503_i2c_remove, .id_table = usb3503_id, }; @@ -425,7 +423,7 @@ static struct platform_driver usb3503_platform_driver = { .pm = pm_ptr(&usb3503_platform_pm_ops), }, .probe = usb3503_platform_probe, - .remove = usb3503_platform_remove, + .remove_new = usb3503_platform_remove, }; static int __init usb3503_init(void) diff --git a/drivers/usb/misc/usb4604.c b/drivers/usb/misc/usb4604.c index 6b5e77231efa175fe07fe9d910f064094d05ecfd..065e269ba4e3dcca9c5a3af4f6c3ddbc1705a948 100644 --- a/drivers/usb/misc/usb4604.c +++ b/drivers/usb/misc/usb4604.c @@ -154,7 +154,7 @@ static struct i2c_driver usb4604_i2c_driver = { .pm = pm_ptr(&usb4604_i2c_pm_ops), .of_match_table = of_match_ptr(usb4604_of_match), }, - .probe_new = usb4604_i2c_probe, + .probe = usb4604_i2c_probe, .id_table = usb4604_id, }; module_i2c_driver(usb4604_i2c_driver); diff --git a/drivers/usb/mon/mon_bin.c b/drivers/usb/mon/mon_bin.c index 952c5678925856376aa1111314b324df679ccdbd..9ca9305243fe59e7a61812c24f1c9eac081b416d 100644 --- a/drivers/usb/mon/mon_bin.c +++ b/drivers/usb/mon/mon_bin.c @@ -213,7 +213,10 @@ static unsigned char xfer_to_pipe[4] = { PIPE_CONTROL, PIPE_ISOCHRONOUS, PIPE_BULK, PIPE_INTERRUPT }; -static struct class *mon_bin_class; +static const struct class mon_bin_class = { + .name = "usbmon", +}; + static dev_t mon_bin_dev0; static struct cdev mon_bin_cdev; @@ -1360,7 +1363,7 @@ int mon_bin_add(struct mon_bus *mbus, const struct usb_bus *ubus) if (minor >= MON_BIN_MAX_MINOR) return 0; - dev = device_create(mon_bin_class, ubus ? ubus->controller : NULL, + dev = device_create(&mon_bin_class, ubus ? ubus->controller : NULL, MKDEV(MAJOR(mon_bin_dev0), minor), NULL, "usbmon%d", minor); if (IS_ERR(dev)) @@ -1372,18 +1375,16 @@ int mon_bin_add(struct mon_bus *mbus, const struct usb_bus *ubus) void mon_bin_del(struct mon_bus *mbus) { - device_destroy(mon_bin_class, mbus->classdev->devt); + device_destroy(&mon_bin_class, mbus->classdev->devt); } int __init mon_bin_init(void) { int rc; - mon_bin_class = class_create("usbmon"); - if (IS_ERR(mon_bin_class)) { - rc = PTR_ERR(mon_bin_class); + rc = class_register(&mon_bin_class); + if (rc) goto err_class; - } rc = alloc_chrdev_region(&mon_bin_dev0, 0, MON_BIN_MAX_MINOR, "usbmon"); if (rc < 0) @@ -1401,7 +1402,7 @@ int __init mon_bin_init(void) err_add: unregister_chrdev_region(mon_bin_dev0, MON_BIN_MAX_MINOR); err_dev: - class_destroy(mon_bin_class); + class_unregister(&mon_bin_class); err_class: return rc; } @@ -1410,5 +1411,5 @@ void mon_bin_exit(void) { cdev_del(&mon_bin_cdev); unregister_chrdev_region(mon_bin_dev0, MON_BIN_MAX_MINOR); - class_destroy(mon_bin_class); + class_unregister(&mon_bin_class); } diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index d162afbbe19f70dcbfb888bdc6329827cd2b0d13..ecbd3784bec36b59d4a58d0b3f1f2abc47c3730c 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -2330,7 +2330,6 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) spin_lock_init(&musb->lock); spin_lock_init(&musb->list_lock); - musb->board_set_power = plat->set_power; musb->min_power = plat->min_power; musb->ops = plat->platform_ops; musb->port_mode = plat->mode; diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h index b7588d11cfc59d172119130dbef9154816966c73..91b5b6b66f963a2f42e766bfe62271620e3223b8 100644 --- a/drivers/usb/musb/musb_core.h +++ b/drivers/usb/musb/musb_core.h @@ -352,8 +352,6 @@ struct musb { u16 epmask; u8 nr_endpoints; - int (*board_set_power)(int state); - u8 min_power; /* vbus for periph, in mA/2 */ enum musb_mode port_mode; diff --git a/drivers/usb/musb/tusb6010.c b/drivers/usb/musb/tusb6010.c index a1f29dbc62e6e9502dca4f52e93b7ae4bb557154..cbc707fe570fa061def0e7e1e910b1f870a591e5 100644 --- a/drivers/usb/musb/tusb6010.c +++ b/drivers/usb/musb/tusb6010.c @@ -11,6 +11,8 @@ * interface. */ +#include +#include #include #include #include @@ -30,6 +32,8 @@ struct tusb6010_glue { struct device *dev; struct platform_device *musb; struct platform_device *phy; + struct gpio_desc *enable; + struct gpio_desc *intpin; }; static void tusb_musb_set_vbus(struct musb *musb, int is_on); @@ -1021,16 +1025,29 @@ static void tusb_setup_cpu_interface(struct musb *musb) static int tusb_musb_start(struct musb *musb) { + struct tusb6010_glue *glue = dev_get_drvdata(musb->controller->parent); void __iomem *tbase = musb->ctrl_base; - int ret = 0; unsigned long flags; u32 reg; + int i; - if (musb->board_set_power) - ret = musb->board_set_power(1); - if (ret != 0) { - printk(KERN_ERR "tusb: Cannot enable TUSB6010\n"); - return ret; + /* + * Enable or disable power to TUSB6010. When enabling, turn on 3.3 V and + * 1.5 V voltage regulators of PM companion chip. Companion chip will then + * provide then PGOOD signal to TUSB6010 which will release it from reset. + */ + gpiod_set_value(glue->enable, 1); + msleep(1); + + /* Wait for 100ms until TUSB6010 pulls INT pin down */ + i = 100; + while (i && gpiod_get_value(glue->intpin)) { + msleep(1); + i--; + } + if (!i) { + pr_err("tusb: Powerup respones failed\n"); + return -ENODEV; } spin_lock_irqsave(&musb->lock, flags); @@ -1083,8 +1100,8 @@ static int tusb_musb_start(struct musb *musb) err: spin_unlock_irqrestore(&musb->lock, flags); - if (musb->board_set_power) - musb->board_set_power(0); + gpiod_set_value(glue->enable, 0); + msleep(10); return -ENODEV; } @@ -1158,11 +1175,13 @@ static int tusb_musb_init(struct musb *musb) static int tusb_musb_exit(struct musb *musb) { + struct tusb6010_glue *glue = dev_get_drvdata(musb->controller->parent); + del_timer_sync(&musb->dev_timer); the_musb = NULL; - if (musb->board_set_power) - musb->board_set_power(0); + gpiod_set_value(glue->enable, 0); + msleep(10); iounmap(musb->sync_va); @@ -1218,6 +1237,15 @@ static int tusb_probe(struct platform_device *pdev) glue->dev = &pdev->dev; + glue->enable = devm_gpiod_get(glue->dev, "enable", GPIOD_OUT_LOW); + if (IS_ERR(glue->enable)) + return dev_err_probe(glue->dev, PTR_ERR(glue->enable), + "could not obtain power on/off GPIO\n"); + glue->intpin = devm_gpiod_get(glue->dev, "int", GPIOD_IN); + if (IS_ERR(glue->intpin)) + return dev_err_probe(glue->dev, PTR_ERR(glue->intpin), + "could not obtain INT GPIO\n"); + pdata->platform_ops = &tusb_ops; usb_phy_generic_register(); @@ -1236,10 +1264,7 @@ static int tusb_probe(struct platform_device *pdev) musb_resources[1].end = pdev->resource[1].end; musb_resources[1].flags = pdev->resource[1].flags; - musb_resources[2].name = pdev->resource[2].name; - musb_resources[2].start = pdev->resource[2].start; - musb_resources[2].end = pdev->resource[2].end; - musb_resources[2].flags = pdev->resource[2].flags; + musb_resources[2] = DEFINE_RES_IRQ_NAMED(gpiod_to_irq(glue->intpin), "mc"); pinfo = tusb_dev_info; pinfo.parent = &pdev->dev; diff --git a/drivers/usb/phy/phy-isp1301.c b/drivers/usb/phy/phy-isp1301.c index f4ee14d985853c0310a69704579d565ba7a40d4f..993d7525a102115d6c65aec0d3f2e191aa0260df 100644 --- a/drivers/usb/phy/phy-isp1301.c +++ b/drivers/usb/phy/phy-isp1301.c @@ -132,7 +132,7 @@ static struct i2c_driver isp1301_driver = { .name = DRV_NAME, .of_match_table = isp1301_of_match, }, - .probe_new = isp1301_probe, + .probe = isp1301_probe, .remove = isp1301_remove, .id_table = isp1301_id, }; diff --git a/drivers/usb/phy/phy-tahvo.c b/drivers/usb/phy/phy-tahvo.c index 47562d49dfc1b8958f6f18db841e47d5f410a90a..5cac31c6029b38da9f2488fbfdaa340b28a2d5b6 100644 --- a/drivers/usb/phy/phy-tahvo.c +++ b/drivers/usb/phy/phy-tahvo.c @@ -391,7 +391,7 @@ static int tahvo_usb_probe(struct platform_device *pdev) tu->irq = ret = platform_get_irq(pdev, 0); if (ret < 0) - return ret; + goto err_remove_phy; ret = request_threaded_irq(tu->irq, NULL, tahvo_usb_vbus_interrupt, IRQF_ONESHOT, "tahvo-vbus", tu); diff --git a/drivers/usb/renesas_usbhs/common.c b/drivers/usb/renesas_usbhs/common.c index fa34efabcccfe331b3c70ebc762a1551b71f9480..111b7ee152c432f3fbee5cf6aa5b4d03f0420c19 100644 --- a/drivers/usb/renesas_usbhs/common.c +++ b/drivers/usb/renesas_usbhs/common.c @@ -762,7 +762,7 @@ static int usbhs_probe(struct platform_device *pdev) return ret; } -static int usbhs_remove(struct platform_device *pdev) +static void usbhs_remove(struct platform_device *pdev) { struct usbhs_priv *priv = usbhs_pdev_to_priv(pdev); @@ -780,8 +780,6 @@ static int usbhs_remove(struct platform_device *pdev) usbhs_mod_remove(priv); usbhs_fifo_remove(priv); usbhs_pipe_remove(priv); - - return 0; } static __maybe_unused int usbhsc_suspend(struct device *dev) @@ -826,7 +824,7 @@ static struct platform_driver renesas_usbhs_driver = { .of_match_table = usbhs_of_match, }, .probe = usbhs_probe, - .remove = usbhs_remove, + .remove_new = usbhs_remove, }; module_platform_driver(renesas_usbhs_driver); diff --git a/drivers/usb/roles/class.c b/drivers/usb/roles/class.c index 0395bd5dbd3efe498516d8169925527d20bb2ce1..ae41578bd0149900b0a867f71a0cf6080e238566 100644 --- a/drivers/usb/roles/class.c +++ b/drivers/usb/roles/class.c @@ -14,7 +14,9 @@ #include #include -static struct class *role_class; +static const struct class role_class = { + .name = "usb_role", +}; struct usb_role_switch { struct device dev; @@ -95,7 +97,7 @@ static void *usb_role_switch_match(const struct fwnode_handle *fwnode, const cha if (id && !fwnode_property_present(fwnode, id)) return NULL; - dev = class_find_device_by_fwnode(role_class, fwnode); + dev = class_find_device_by_fwnode(&role_class, fwnode); return dev ? to_role_switch(dev) : ERR_PTR(-EPROBE_DEFER); } @@ -111,7 +113,7 @@ usb_role_switch_is_parent(struct fwnode_handle *fwnode) return NULL; } - dev = class_find_device_by_fwnode(role_class, parent); + dev = class_find_device_by_fwnode(&role_class, parent); fwnode_handle_put(parent); return dev ? to_role_switch(dev) : ERR_PTR(-EPROBE_DEFER); } @@ -191,7 +193,7 @@ usb_role_switch_find_by_fwnode(const struct fwnode_handle *fwnode) if (!fwnode) return NULL; - dev = class_find_device_by_fwnode(role_class, fwnode); + dev = class_find_device_by_fwnode(&role_class, fwnode); if (dev) WARN_ON(!try_module_get(dev->parent->driver->owner)); @@ -338,7 +340,7 @@ usb_role_switch_register(struct device *parent, sw->dev.parent = parent; sw->dev.fwnode = desc->fwnode; - sw->dev.class = role_class; + sw->dev.class = &role_class; sw->dev.type = &usb_role_dev_type; dev_set_drvdata(&sw->dev, desc->driver_data); dev_set_name(&sw->dev, "%s-role-switch", @@ -392,14 +394,13 @@ EXPORT_SYMBOL_GPL(usb_role_switch_get_drvdata); static int __init usb_roles_init(void) { - role_class = class_create("usb_role"); - return PTR_ERR_OR_ZERO(role_class); + return class_register(&role_class); } subsys_initcall(usb_roles_init); static void __exit usb_roles_exit(void) { - class_destroy(role_class); + class_unregister(&role_class); } module_exit(usb_roles_exit); diff --git a/drivers/usb/roles/intel-xhci-usb-role-switch.c b/drivers/usb/roles/intel-xhci-usb-role-switch.c index 5c96e929acea0ec490e3cb1719440d9592ffcf26..e5c6c413a075b6e9c8734d029f20fc558ec69c92 100644 --- a/drivers/usb/roles/intel-xhci-usb-role-switch.c +++ b/drivers/usb/roles/intel-xhci-usb-role-switch.c @@ -195,7 +195,7 @@ static int intel_xhci_usb_probe(struct platform_device *pdev) return 0; } -static int intel_xhci_usb_remove(struct platform_device *pdev) +static void intel_xhci_usb_remove(struct platform_device *pdev) { struct intel_xhci_usb_data *data = platform_get_drvdata(pdev); @@ -203,8 +203,6 @@ static int intel_xhci_usb_remove(struct platform_device *pdev) usb_role_switch_unregister(data->role_sw); fwnode_handle_put(software_node_fwnode(&intel_xhci_usb_node)); - - return 0; } static const struct platform_device_id intel_xhci_usb_table[] = { @@ -219,7 +217,7 @@ static struct platform_driver intel_xhci_usb_driver = { }, .id_table = intel_xhci_usb_table, .probe = intel_xhci_usb_probe, - .remove = intel_xhci_usb_remove, + .remove_new = intel_xhci_usb_remove, }; module_platform_driver(intel_xhci_usb_driver); diff --git a/drivers/usb/serial/ark3116.c b/drivers/usb/serial/ark3116.c index 9452291f1703321515c66a2660db93bcd84f95a8..67a07cc007f09ac5ace7d797c83fccefe4849558 100644 --- a/drivers/usb/serial/ark3116.c +++ b/drivers/usb/serial/ark3116.c @@ -433,10 +433,11 @@ static int ark3116_tiocmset(struct tty_struct *tty, return 0; } -static void ark3116_break_ctl(struct tty_struct *tty, int break_state) +static int ark3116_break_ctl(struct tty_struct *tty, int break_state) { struct usb_serial_port *port = tty->driver_data; struct ark3116_private *priv = usb_get_serial_port_data(port); + int ret; /* LCR is also used for other things: protect access */ mutex_lock(&priv->hw_lock); @@ -446,9 +447,11 @@ static void ark3116_break_ctl(struct tty_struct *tty, int break_state) else priv->lcr &= ~UART_LCR_SBC; - ark3116_write_reg(port->serial, UART_LCR, priv->lcr); + ret = ark3116_write_reg(port->serial, UART_LCR, priv->lcr); mutex_unlock(&priv->hw_lock); + + return ret; } static void ark3116_update_msr(struct usb_serial_port *port, __u8 msr) diff --git a/drivers/usb/serial/belkin_sa.c b/drivers/usb/serial/belkin_sa.c index 9331a562dac0ba6df722d47ae3ab8a789df19ead..cf47ee4ae5d3bd90d993a6a172627ca2576b500a 100644 --- a/drivers/usb/serial/belkin_sa.c +++ b/drivers/usb/serial/belkin_sa.c @@ -46,7 +46,7 @@ static void belkin_sa_process_read_urb(struct urb *urb); static void belkin_sa_set_termios(struct tty_struct *tty, struct usb_serial_port *port, const struct ktermios *old_termios); -static void belkin_sa_break_ctl(struct tty_struct *tty, int break_state); +static int belkin_sa_break_ctl(struct tty_struct *tty, int break_state); static int belkin_sa_tiocmget(struct tty_struct *tty); static int belkin_sa_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear); @@ -399,13 +399,19 @@ static void belkin_sa_set_termios(struct tty_struct *tty, spin_unlock_irqrestore(&priv->lock, flags); } -static void belkin_sa_break_ctl(struct tty_struct *tty, int break_state) +static int belkin_sa_break_ctl(struct tty_struct *tty, int break_state) { struct usb_serial_port *port = tty->driver_data; struct usb_serial *serial = port->serial; + int ret; - if (BSA_USB_CMD(BELKIN_SA_SET_BREAK_REQUEST, break_state ? 1 : 0) < 0) + ret = BSA_USB_CMD(BELKIN_SA_SET_BREAK_REQUEST, break_state ? 1 : 0); + if (ret < 0) { dev_err(&port->dev, "Set break_ctl %d\n", break_state); + return ret; + } + + return 0; } static int belkin_sa_tiocmget(struct tty_struct *tty) diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c index 6e1b87e67304616ce04448d3a0d3fd3ebb5d0c56..612bea504d7a877aefcb2cf8413112ed7371183b 100644 --- a/drivers/usb/serial/ch341.c +++ b/drivers/usb/serial/ch341.c @@ -562,12 +562,12 @@ static void ch341_set_termios(struct tty_struct *tty, * TCSBRKP. Due to how the simulation is implemented the duration can't be * controlled. The duration is always about (1s / 46bd * 9bit) = 196ms. */ -static void ch341_simulate_break(struct tty_struct *tty, int break_state) +static int ch341_simulate_break(struct tty_struct *tty, int break_state) { struct usb_serial_port *port = tty->driver_data; struct ch341_private *priv = usb_get_serial_port_data(port); unsigned long now, delay; - int r; + int r, r2; if (break_state != 0) { dev_dbg(&port->dev, "enter break state requested\n"); @@ -599,7 +599,7 @@ static void ch341_simulate_break(struct tty_struct *tty, int break_state) */ priv->break_end = jiffies + (11 * HZ / CH341_MIN_BPS); - return; + return 0; } dev_dbg(&port->dev, "leave break state requested\n"); @@ -615,17 +615,22 @@ static void ch341_simulate_break(struct tty_struct *tty, int break_state) schedule_timeout_interruptible(delay); } + r = 0; restore: /* Restore original baud rate */ - r = ch341_set_baudrate_lcr(port->serial->dev, priv, priv->baud_rate, - priv->lcr); - if (r < 0) + r2 = ch341_set_baudrate_lcr(port->serial->dev, priv, priv->baud_rate, + priv->lcr); + if (r2 < 0) { dev_err(&port->dev, "restoring original baud rate of %u failed: %d\n", - priv->baud_rate, r); + priv->baud_rate, r2); + return r2; + } + + return r; } -static void ch341_break_ctl(struct tty_struct *tty, int break_state) +static int ch341_break_ctl(struct tty_struct *tty, int break_state) { const uint16_t ch341_break_reg = ((uint16_t) CH341_REG_LCR << 8) | CH341_REG_BREAK; @@ -635,17 +640,17 @@ static void ch341_break_ctl(struct tty_struct *tty, int break_state) uint16_t reg_contents; uint8_t break_reg[2]; - if (priv->quirks & CH341_QUIRK_SIMULATE_BREAK) { - ch341_simulate_break(tty, break_state); - return; - } + if (priv->quirks & CH341_QUIRK_SIMULATE_BREAK) + return ch341_simulate_break(tty, break_state); r = ch341_control_in(port->serial->dev, CH341_REQ_READ_REG, ch341_break_reg, 0, break_reg, 2); if (r) { dev_err(&port->dev, "%s - USB control read error (%d)\n", __func__, r); - return; + if (r > 0) + r = -EIO; + return r; } dev_dbg(&port->dev, "%s - initial ch341 break register contents - reg1: %x, reg2: %x\n", __func__, break_reg[0], break_reg[1]); @@ -663,9 +668,13 @@ static void ch341_break_ctl(struct tty_struct *tty, int break_state) reg_contents = get_unaligned_le16(break_reg); r = ch341_control_out(port->serial->dev, CH341_REQ_WRITE_REG, ch341_break_reg, reg_contents); - if (r < 0) + if (r < 0) { dev_err(&port->dev, "%s - USB control write error (%d)\n", __func__, r); + return r; + } + + return 0; } static int ch341_tiocmset(struct tty_struct *tty, diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index cdea1bff3b708b819d58be6265fd0d8f617bd8b3..1e61fe04317158c3a5e877bfb0d89cb5572ce4ef 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -39,7 +39,7 @@ static int cp210x_tiocmget(struct tty_struct *); static int cp210x_tiocmset(struct tty_struct *, unsigned int, unsigned int); static int cp210x_tiocmset_port(struct usb_serial_port *port, unsigned int, unsigned int); -static void cp210x_break_ctl(struct tty_struct *, int); +static int cp210x_break_ctl(struct tty_struct *, int); static int cp210x_attach(struct usb_serial *); static void cp210x_disconnect(struct usb_serial *); static void cp210x_release(struct usb_serial *); @@ -1434,18 +1434,26 @@ static int cp210x_tiocmget(struct tty_struct *tty) return result; } -static void cp210x_break_ctl(struct tty_struct *tty, int break_state) +static int cp210x_break_ctl(struct tty_struct *tty, int break_state) { struct usb_serial_port *port = tty->driver_data; + struct cp210x_serial_private *priv = usb_get_serial_data(port->serial); u16 state; + if (priv->partnum == CP210X_PARTNUM_CP2105) { + if (cp210x_interface_num(port->serial) == 1) + return -ENOTTY; + } + if (break_state == 0) state = BREAK_OFF; else state = BREAK_ON; + dev_dbg(&port->dev, "%s - turning break %s\n", __func__, state == BREAK_OFF ? "off" : "on"); - cp210x_write_u16_reg(port, CP210X_SET_BREAK, state); + + return cp210x_write_u16_reg(port, CP210X_SET_BREAK, state); } #ifdef CONFIG_GPIOLIB diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c index 45d688e9b93f689332e8ebae3985deedc93231f8..d1dea38505762c1e62110211ccfc1fa82fc31f1f 100644 --- a/drivers/usb/serial/digi_acceleport.c +++ b/drivers/usb/serial/digi_acceleport.c @@ -217,7 +217,7 @@ static void digi_rx_unthrottle(struct tty_struct *tty); static void digi_set_termios(struct tty_struct *tty, struct usb_serial_port *port, const struct ktermios *old_termios); -static void digi_break_ctl(struct tty_struct *tty, int break_state); +static int digi_break_ctl(struct tty_struct *tty, int break_state); static int digi_tiocmget(struct tty_struct *tty); static int digi_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear); @@ -839,7 +839,7 @@ static void digi_set_termios(struct tty_struct *tty, } -static void digi_break_ctl(struct tty_struct *tty, int break_state) +static int digi_break_ctl(struct tty_struct *tty, int break_state) { struct usb_serial_port *port = tty->driver_data; unsigned char buf[4]; @@ -848,7 +848,8 @@ static void digi_break_ctl(struct tty_struct *tty, int break_state) buf[1] = 2; /* length */ buf[2] = break_state ? 1 : 0; buf[3] = 0; /* pad */ - digi_write_inb_command(port, buf, 4, 0); + + return digi_write_inb_command(port, buf, 4, 0); } diff --git a/drivers/usb/serial/f81232.c b/drivers/usb/serial/f81232.c index 891fb1fe69df739eb20374d41681efef968f9fdf..5f7a46bcace65cac31730a2d9eb7c7b68f741908 100644 --- a/drivers/usb/serial/f81232.c +++ b/drivers/usb/serial/f81232.c @@ -448,7 +448,7 @@ static void f81534a_process_read_urb(struct urb *urb) tty_flip_buffer_push(&port->port); } -static void f81232_break_ctl(struct tty_struct *tty, int break_state) +static int f81232_break_ctl(struct tty_struct *tty, int break_state) { struct usb_serial_port *port = tty->driver_data; struct f81232_private *priv = usb_get_serial_port_data(port); @@ -467,6 +467,8 @@ static void f81232_break_ctl(struct tty_struct *tty, int break_state) dev_err(&port->dev, "set break failed: %d\n", status); mutex_unlock(&priv->lock); + + return status; } static int f81232_find_clk(speed_t baudrate) diff --git a/drivers/usb/serial/f81534.c b/drivers/usb/serial/f81534.c index 4083ae961be430cbaa21823890eaabbed5d46ac9..ef126cd3d94fbad88d6b71f62c36c3907942aace 100644 --- a/drivers/usb/serial/f81534.c +++ b/drivers/usb/serial/f81534.c @@ -656,7 +656,7 @@ static int f81534_set_port_config(struct usb_serial_port *port, return status; } -static void f81534_break_ctl(struct tty_struct *tty, int break_state) +static int f81534_break_ctl(struct tty_struct *tty, int break_state) { struct usb_serial_port *port = tty->driver_data; struct f81534_port_private *port_priv = usb_get_serial_port_data(port); @@ -675,6 +675,8 @@ static void f81534_break_ctl(struct tty_struct *tty, int break_state) dev_err(&port->dev, "set break failed: %d\n", status); mutex_unlock(&port_priv->lcr_mutex); + + return status; } static int f81534_update_mctrl(struct usb_serial_port *port, unsigned int set, diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 05e28a5ce42b1196db9f592618afdcc350fed059..1bf23611be12210f1795ca71288c5f0244c1a53c 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -2550,11 +2550,12 @@ static void ftdi_process_read_urb(struct urb *urb) tty_flip_buffer_push(&port->port); } -static void ftdi_break_ctl(struct tty_struct *tty, int break_state) +static int ftdi_break_ctl(struct tty_struct *tty, int break_state) { struct usb_serial_port *port = tty->driver_data; struct ftdi_private *priv = usb_get_serial_port_data(port); u16 value; + int ret; /* break_state = -1 to turn on break, and 0 to turn off break */ /* see drivers/char/tty_io.c to see it used */ @@ -2565,19 +2566,22 @@ static void ftdi_break_ctl(struct tty_struct *tty, int break_state) else value = priv->last_set_data_value; - if (usb_control_msg(port->serial->dev, + ret = usb_control_msg(port->serial->dev, usb_sndctrlpipe(port->serial->dev, 0), FTDI_SIO_SET_DATA_REQUEST, FTDI_SIO_SET_DATA_REQUEST_TYPE, value, priv->channel, - NULL, 0, WDR_TIMEOUT) < 0) { + NULL, 0, WDR_TIMEOUT); + if (ret < 0) { dev_err(&port->dev, "%s FAILED to enable/disable break state (state was %d)\n", __func__, break_state); + return ret; } dev_dbg(&port->dev, "%s break state is %d - urb is %d\n", __func__, break_state, value); + return 0; } static bool ftdi_tx_empty(struct usb_serial_port *port) diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c index 3a4c0febf33589a88e5e3fc2e64e95c5f2c56504..abe4bbb0ac654f0b630099f5b11bb2f03138196f 100644 --- a/drivers/usb/serial/io_edgeport.c +++ b/drivers/usb/serial/io_edgeport.c @@ -1560,12 +1560,12 @@ static int edge_ioctl(struct tty_struct *tty, * SerialBreak * this function sends a break to the port *****************************************************************************/ -static void edge_break(struct tty_struct *tty, int break_state) +static int edge_break(struct tty_struct *tty, int break_state) { struct usb_serial_port *port = tty->driver_data; struct edgeport_port *edge_port = usb_get_serial_port_data(port); struct edgeport_serial *edge_serial = usb_get_serial_data(port->serial); - int status; + int status = 0; if (!edge_serial->is_epic || edge_serial->epic_descriptor.Supports.IOSPChase) { @@ -1597,6 +1597,8 @@ static void edge_break(struct tty_struct *tty, int break_state) dev_dbg(&port->dev, "%s - error sending break set/clear command.\n", __func__); } + + return status; } diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c index bc3c24ea42c1bffb0cafe277e03dceacd087c42f..7a3a6e53945652efce4867087b3437590342aa2c 100644 --- a/drivers/usb/serial/io_ti.c +++ b/drivers/usb/serial/io_ti.c @@ -2421,7 +2421,7 @@ static int edge_tiocmget(struct tty_struct *tty) return result; } -static void edge_break(struct tty_struct *tty, int break_state) +static int edge_break(struct tty_struct *tty, int break_state) { struct usb_serial_port *port = tty->driver_data; struct edgeport_port *edge_port = usb_get_serial_port_data(port); @@ -2430,10 +2430,15 @@ static void edge_break(struct tty_struct *tty, int break_state) if (break_state == -1) bv = 1; /* On */ + status = ti_do_config(edge_port, UMPC_SET_CLR_BREAK, bv); - if (status) + if (status) { dev_dbg(&port->dev, "%s - error %d sending break set/clear command.\n", __func__, status); + return status; + } + + return 0; } static void edge_heartbeat_schedule(struct edgeport_serial *edge_serial) diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c index 2966e0c4941ec6abdd736fa363de044f0a86e5e7..93b17e0e05a33ec18863343bbacd0285cde89ae0 100644 --- a/drivers/usb/serial/keyspan.c +++ b/drivers/usb/serial/keyspan.c @@ -599,7 +599,7 @@ struct keyspan_port_private { #include "keyspan_usa67msg.h" -static void keyspan_break_ctl(struct tty_struct *tty, int break_state) +static int keyspan_break_ctl(struct tty_struct *tty, int break_state) { struct usb_serial_port *port = tty->driver_data; struct keyspan_port_private *p_priv; @@ -611,7 +611,10 @@ static void keyspan_break_ctl(struct tty_struct *tty, int break_state) else p_priv->break_on = 0; + /* FIXME: return errors */ keyspan_send_setup(port, 0); + + return 0; } diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c index 6fd15cd9e1eb05872278b49bce30742467293ea3..0eef358b314a3147473598ff1520384f8d8fb0ac 100644 --- a/drivers/usb/serial/keyspan_pda.c +++ b/drivers/usb/serial/keyspan_pda.c @@ -299,7 +299,7 @@ static speed_t keyspan_pda_setbaud(struct usb_serial *serial, speed_t baud) return baud; } -static void keyspan_pda_break_ctl(struct tty_struct *tty, int break_state) +static int keyspan_pda_break_ctl(struct tty_struct *tty, int break_state) { struct usb_serial_port *port = tty->driver_data; struct usb_serial *serial = port->serial; @@ -315,9 +315,13 @@ static void keyspan_pda_break_ctl(struct tty_struct *tty, int break_state) 4, /* set break */ USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT, value, 0, NULL, 0, 2000); - if (result < 0) + if (result < 0) { dev_dbg(&port->dev, "%s - error %d from usb_control_msg\n", __func__, result); + return result; + } + + return 0; } static void keyspan_pda_set_termios(struct tty_struct *tty, diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c index d3852feb81a4a2607272fa2d2a01e8fdb8af7610..6570c8817a80453a95193d53612706c7b7d9fe17 100644 --- a/drivers/usb/serial/mct_u232.c +++ b/drivers/usb/serial/mct_u232.c @@ -47,7 +47,7 @@ static void mct_u232_read_int_callback(struct urb *urb); static void mct_u232_set_termios(struct tty_struct *tty, struct usb_serial_port *port, const struct ktermios *old_termios); -static void mct_u232_break_ctl(struct tty_struct *tty, int break_state); +static int mct_u232_break_ctl(struct tty_struct *tty, int break_state); static int mct_u232_tiocmget(struct tty_struct *tty); static int mct_u232_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear); @@ -677,7 +677,7 @@ static void mct_u232_set_termios(struct tty_struct *tty, spin_unlock_irqrestore(&priv->lock, flags); } /* mct_u232_set_termios */ -static void mct_u232_break_ctl(struct tty_struct *tty, int break_state) +static int mct_u232_break_ctl(struct tty_struct *tty, int break_state) { struct usb_serial_port *port = tty->driver_data; struct mct_u232_private *priv = usb_get_serial_port_data(port); @@ -691,7 +691,7 @@ static void mct_u232_break_ctl(struct tty_struct *tty, int break_state) lcr |= MCT_U232_SET_BREAK; spin_unlock_irqrestore(&priv->lock, flags); - mct_u232_set_line_ctrl(port, lcr); + return mct_u232_set_line_ctrl(port, lcr); } /* mct_u232_break_ctl */ diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c index 1d1f85fabc284c812b8c080301437dbbbfbeec65..23544074eb1c3d1a1722ccc487601c7846beb492 100644 --- a/drivers/usb/serial/mos7720.c +++ b/drivers/usb/serial/mos7720.c @@ -996,7 +996,7 @@ static void mos7720_close(struct usb_serial_port *port) mos7720_port->open = 0; } -static void mos7720_break(struct tty_struct *tty, int break_state) +static int mos7720_break(struct tty_struct *tty, int break_state) { struct usb_serial_port *port = tty->driver_data; unsigned char data; @@ -1007,7 +1007,7 @@ static void mos7720_break(struct tty_struct *tty, int break_state) mos7720_port = usb_get_serial_port_data(port); if (mos7720_port == NULL) - return; + return -ENODEV; if (break_state == -1) data = mos7720_port->shadowLCR | UART_LCR_SBC; @@ -1015,8 +1015,9 @@ static void mos7720_break(struct tty_struct *tty, int break_state) data = mos7720_port->shadowLCR & ~UART_LCR_SBC; mos7720_port->shadowLCR = data; - write_mos_reg(serial, port->port_number, MOS7720_LCR, - mos7720_port->shadowLCR); + + return write_mos_reg(serial, port->port_number, MOS7720_LCR, + mos7720_port->shadowLCR); } /* diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index 73370eaae0abca0edc8c26cf8bace5ece327d888..8b0308d84270f5087ea6f88db933b4b1b662ce38 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -787,7 +787,7 @@ static void mos7840_close(struct usb_serial_port *port) * mos7840_break * this function sends a break to the port *****************************************************************************/ -static void mos7840_break(struct tty_struct *tty, int break_state) +static int mos7840_break(struct tty_struct *tty, int break_state) { struct usb_serial_port *port = tty->driver_data; struct moschip_port *mos7840_port = usb_get_serial_port_data(port); @@ -801,8 +801,9 @@ static void mos7840_break(struct tty_struct *tty, int break_state) /* FIXME: no locking on shadowLCR anywhere in driver */ mos7840_port->shadowLCR = data; dev_dbg(&port->dev, "%s mos7840_port->shadowLCR is %x\n", __func__, mos7840_port->shadowLCR); - mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, - mos7840_port->shadowLCR); + + return mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, + mos7840_port->shadowLCR); } /***************************************************************************** diff --git a/drivers/usb/serial/mxuport.c b/drivers/usb/serial/mxuport.c index faa0eedfe245f9634cc0cacb6f8c172d64a529be..1f7bb3e4fcf22d1d11ee44f6f1dcbb609110bb6c 100644 --- a/drivers/usb/serial/mxuport.c +++ b/drivers/usb/serial/mxuport.c @@ -1230,7 +1230,7 @@ static void mxuport_close(struct usb_serial_port *port) } /* Send a break to the port. */ -static void mxuport_break_ctl(struct tty_struct *tty, int break_state) +static int mxuport_break_ctl(struct tty_struct *tty, int break_state) { struct usb_serial_port *port = tty->driver_data; struct usb_serial *serial = port->serial; @@ -1244,8 +1244,8 @@ static void mxuport_break_ctl(struct tty_struct *tty, int break_state) dev_dbg(&port->dev, "%s - clearing break\n", __func__); } - mxuport_send_ctrl_urb(serial, RQ_VENDOR_SET_BREAK, - enable, port->port_number); + return mxuport_send_ctrl_urb(serial, RQ_VENDOR_SET_BREAK, + enable, port->port_number); } static int mxuport_resume(struct usb_serial *serial) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index fd42e3a0bd1879a2cb9de7fc11d42666b2166beb..288a96a74266164cae6936fbff4158c15dc4c742 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -1151,6 +1151,10 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x90fa), .driver_info = RSVD(3) }, /* u-blox products */ + { USB_DEVICE(UBLOX_VENDOR_ID, 0x1311) }, /* u-blox LARA-R6 01B */ + { USB_DEVICE(UBLOX_VENDOR_ID, 0x1312), /* u-blox LARA-R6 01B (RMNET) */ + .driver_info = RSVD(4) }, + { USB_DEVICE_INTERFACE_CLASS(UBLOX_VENDOR_ID, 0x1313, 0xff) }, /* u-blox LARA-R6 01B (ECM) */ { USB_DEVICE(UBLOX_VENDOR_ID, 0x1341) }, /* u-blox LARA-L6 */ { USB_DEVICE(UBLOX_VENDOR_ID, 0x1342), /* u-blox LARA-L6 (RMNET) */ .driver_info = RSVD(4) }, diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index 8949c1891164bd9511720627c054bbd1339e8452..d93f5d58455782c3eccc318199024111c0d70e1b 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -173,7 +173,7 @@ MODULE_DEVICE_TABLE(usb, id_table); #define PL2303_HXN_FLOWCTRL_RTS_CTS 0x18 #define PL2303_HXN_FLOWCTRL_XON_XOFF 0x0c -static void pl2303_set_break(struct usb_serial_port *port, bool enable); +static int pl2303_set_break(struct usb_serial_port *port, bool enable); enum pl2303_type { TYPE_H, @@ -1060,7 +1060,7 @@ static int pl2303_carrier_raised(struct usb_serial_port *port) return 0; } -static void pl2303_set_break(struct usb_serial_port *port, bool enable) +static int pl2303_set_break(struct usb_serial_port *port, bool enable) { struct usb_serial *serial = port->serial; u16 state; @@ -1077,15 +1077,19 @@ static void pl2303_set_break(struct usb_serial_port *port, bool enable) result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), BREAK_REQUEST, BREAK_REQUEST_TYPE, state, 0, NULL, 0, 100); - if (result) + if (result) { dev_err(&port->dev, "error sending break = %d\n", result); + return result; + } + + return 0; } -static void pl2303_break_ctl(struct tty_struct *tty, int state) +static int pl2303_break_ctl(struct tty_struct *tty, int state) { struct usb_serial_port *port = tty->driver_data; - pl2303_set_break(port, state); + return pl2303_set_break(port, state); } static void pl2303_update_line_status(struct usb_serial_port *port, diff --git a/drivers/usb/serial/quatech2.c b/drivers/usb/serial/quatech2.c index fee581409bf605a29f9dd70afc3929bb86c461e1..821f25e52ec24c3b4d321be29df9457efce7f366 100644 --- a/drivers/usb/serial/quatech2.c +++ b/drivers/usb/serial/quatech2.c @@ -741,7 +741,7 @@ static int qt2_tiocmset(struct tty_struct *tty, return update_mctrl(port_priv, set, clear); } -static void qt2_break_ctl(struct tty_struct *tty, int break_state) +static int qt2_break_ctl(struct tty_struct *tty, int break_state) { struct usb_serial_port *port = tty->driver_data; struct qt2_port_private *port_priv; @@ -754,10 +754,14 @@ static void qt2_break_ctl(struct tty_struct *tty, int break_state) status = qt2_control_msg(port->serial->dev, QT2_BREAK_CONTROL, val, port_priv->device_port); - if (status < 0) + if (status < 0) { dev_warn(&port->dev, "%s - failed to send control message: %i\n", __func__, status); + return status; + } + + return 0; } diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c index b99f78224846d55e088cc73cfcf6d1cef662f84d..0fba25abf671ca485a62c35aa5a86ea7ab126005 100644 --- a/drivers/usb/serial/ti_usb_3410_5052.c +++ b/drivers/usb/serial/ti_usb_3410_5052.c @@ -319,7 +319,7 @@ static void ti_set_termios(struct tty_struct *tty, static int ti_tiocmget(struct tty_struct *tty); static int ti_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear); -static void ti_break(struct tty_struct *tty, int break_state); +static int ti_break(struct tty_struct *tty, int break_state); static void ti_interrupt_callback(struct urb *urb); static void ti_bulk_in_callback(struct urb *urb); static void ti_bulk_out_callback(struct urb *urb); @@ -1071,7 +1071,7 @@ static int ti_tiocmset(struct tty_struct *tty, } -static void ti_break(struct tty_struct *tty, int break_state) +static int ti_break(struct tty_struct *tty, int break_state) { struct usb_serial_port *port = tty->driver_data; struct ti_port *tport = usb_get_serial_port_data(port); @@ -1083,8 +1083,12 @@ static void ti_break(struct tty_struct *tty, int break_state) tport->tp_uart_base_addr + TI_UART_OFFSET_LCR, TI_LCR_BREAK, break_state == -1 ? TI_LCR_BREAK : 0); - if (status) + if (status) { dev_dbg(&port->dev, "%s - error setting break, %d\n", __func__, status); + return status; + } + + return 0; } static int ti_get_port_from_code(unsigned char code) diff --git a/drivers/usb/serial/upd78f0730.c b/drivers/usb/serial/upd78f0730.c index c47439bd90fa67b2914169d56cdf6c5fa94ca8a3..46952182e04f79a2491aba556c9ec5de33dfecd0 100644 --- a/drivers/usb/serial/upd78f0730.c +++ b/drivers/usb/serial/upd78f0730.c @@ -238,12 +238,13 @@ static int upd78f0730_tiocmset(struct tty_struct *tty, return res; } -static void upd78f0730_break_ctl(struct tty_struct *tty, int break_state) +static int upd78f0730_break_ctl(struct tty_struct *tty, int break_state) { struct upd78f0730_port_private *private; struct usb_serial_port *port = tty->driver_data; struct upd78f0730_set_dtr_rts request; struct device *dev = &port->dev; + int res; private = usb_get_serial_port_data(port); @@ -258,8 +259,10 @@ static void upd78f0730_break_ctl(struct tty_struct *tty, int break_state) request.opcode = UPD78F0730_CMD_SET_DTR_RTS; request.params = private->line_signals; - upd78f0730_send_ctl(port, &request, sizeof(request)); + res = upd78f0730_send_ctl(port, &request, sizeof(request)); mutex_unlock(&private->lock); + + return res; } static void upd78f0730_dtr_rts(struct usb_serial_port *port, int on) diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index f8404073558bef122f9ecfa7c3a906e33fb281e1..7b4805c1004db5d3888b9b915f8183397e81a2cb 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -539,9 +539,9 @@ static int serial_break(struct tty_struct *tty, int break_state) dev_dbg(&port->dev, "%s\n", __func__); if (port->serial->type->break_ctl) - port->serial->type->break_ctl(tty, break_state); + return port->serial->type->break_ctl(tty, break_state); - return 0; + return -ENOTTY; } static int serial_proc_show(struct seq_file *m, void *v) diff --git a/drivers/usb/serial/usb_debug.c b/drivers/usb/serial/usb_debug.c index aaf4813e4971eeb98ccae06aa37b7047404baac2..6934970f180d7fd32249da35d8c380a3a64b9463 100644 --- a/drivers/usb/serial/usb_debug.c +++ b/drivers/usb/serial/usb_debug.c @@ -47,12 +47,19 @@ MODULE_DEVICE_TABLE(usb, id_table_combined); /* This HW really does not support a serial break, so one will be * emulated when ever the break state is set to true. */ -static void usb_debug_break_ctl(struct tty_struct *tty, int break_state) +static int usb_debug_break_ctl(struct tty_struct *tty, int break_state) { struct usb_serial_port *port = tty->driver_data; + int ret; + if (!break_state) - return; - usb_serial_generic_write(tty, port, USB_DEBUG_BRK, USB_DEBUG_BRK_SIZE); + return 0; + + ret = usb_serial_generic_write(tty, port, USB_DEBUG_BRK, USB_DEBUG_BRK_SIZE); + if (ret < 0) + return ret; + + return 0; } static void usb_debug_process_read_urb(struct urb *urb) diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c index 7f82d40753ee08949081097cf38455e30cc3921b..ca48e90a8e81fa8abe349a0356a1fe281dd7559d 100644 --- a/drivers/usb/serial/whiteheat.c +++ b/drivers/usb/serial/whiteheat.c @@ -87,7 +87,7 @@ static void whiteheat_set_termios(struct tty_struct *tty, static int whiteheat_tiocmget(struct tty_struct *tty); static int whiteheat_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear); -static void whiteheat_break_ctl(struct tty_struct *tty, int break_state); +static int whiteheat_break_ctl(struct tty_struct *tty, int break_state); static struct usb_serial_driver whiteheat_fake_device = { .driver = { @@ -449,10 +449,11 @@ static void whiteheat_set_termios(struct tty_struct *tty, firm_setup_port(tty); } -static void whiteheat_break_ctl(struct tty_struct *tty, int break_state) +static int whiteheat_break_ctl(struct tty_struct *tty, int break_state) { struct usb_serial_port *port = tty->driver_data; - firm_set_break(port, break_state); + + return firm_set_break(port, break_state); } diff --git a/drivers/usb/serial/xr_serial.c b/drivers/usb/serial/xr_serial.c index fdb0aae546c333762d22b71cdf38b51dcd12e99f..4ec7c5892b847bc8b48c82b0417c0c53b5868e36 100644 --- a/drivers/usb/serial/xr_serial.c +++ b/drivers/usb/serial/xr_serial.c @@ -503,7 +503,7 @@ static void xr_dtr_rts(struct usb_serial_port *port, int on) xr_tiocmset_port(port, 0, TIOCM_DTR | TIOCM_RTS); } -static void xr_break_ctl(struct tty_struct *tty, int break_state) +static int xr_break_ctl(struct tty_struct *tty, int break_state) { struct usb_serial_port *port = tty->driver_data; struct xr_data *data = usb_get_serial_port_data(port); @@ -517,7 +517,7 @@ static void xr_break_ctl(struct tty_struct *tty, int break_state) dev_dbg(&port->dev, "Turning break %s\n", state == 0 ? "off" : "on"); - xr_set_reg_uart(port, type->tx_break, state); + return xr_set_reg_uart(port, type->tx_break, state); } /* Tx and Rx clock mask values obtained from section 3.3.4 of datasheet */ diff --git a/drivers/usb/typec/Kconfig b/drivers/usb/typec/Kconfig index 831e7049977df59b9dcdfe848ce5f805733b731e..2f80c2792dbdaf8bc7e161924326eb9230569a76 100644 --- a/drivers/usb/typec/Kconfig +++ b/drivers/usb/typec/Kconfig @@ -100,19 +100,6 @@ config TYPEC_STUSB160X If you choose to build this driver as a dynamically linked module, the module will be called stusb160x.ko. -config TYPEC_QCOM_PMIC - tristate "Qualcomm PMIC USB Type-C driver" - depends on ARCH_QCOM || COMPILE_TEST - depends on USB_ROLE_SWITCH || !USB_ROLE_SWITCH - help - Driver for supporting role switch over the Qualcomm PMIC. This will - handle the USB Type-C role and orientation detection reported by the - QCOM PMIC if the PMIC has the capability to handle USB Type-C - detection. - - It will also enable the VBUS output to connected devices when a - DFP connection is made. - config TYPEC_WUSB3801 tristate "Willsemi WUSB3801 Type-C port controller driver" depends on I2C diff --git a/drivers/usb/typec/Makefile b/drivers/usb/typec/Makefile index 4a83dad51a6cf4abf980eae4342bc59a6876af66..7a368fea61bc9fdf406eb41298356a57817f22ba 100644 --- a/drivers/usb/typec/Makefile +++ b/drivers/usb/typec/Makefile @@ -8,7 +8,6 @@ obj-$(CONFIG_TYPEC_UCSI) += ucsi/ obj-$(CONFIG_TYPEC_TPS6598X) += tipd/ obj-$(CONFIG_TYPEC_ANX7411) += anx7411.o obj-$(CONFIG_TYPEC_HD3SS3220) += hd3ss3220.o -obj-$(CONFIG_TYPEC_QCOM_PMIC) += qcom-pmic-typec.o obj-$(CONFIG_TYPEC_STUSB160X) += stusb160x.o obj-$(CONFIG_TYPEC_RT1719) += rt1719.o obj-$(CONFIG_TYPEC_WUSB3801) += wusb3801.o diff --git a/drivers/usb/typec/anx7411.c b/drivers/usb/typec/anx7411.c index 3d5edce270a44c533050f27fd1a82575e13d26e9..221604f933a40bf66b05bab30061b1ead9bc837d 100644 --- a/drivers/usb/typec/anx7411.c +++ b/drivers/usb/typec/anx7411.c @@ -1584,7 +1584,7 @@ static struct i2c_driver anx7411_driver = { .of_match_table = anx_match_table, .pm = &anx7411_pm_ops, }, - .probe_new = anx7411_i2c_probe, + .probe = anx7411_i2c_probe, .remove = anx7411_i2c_remove, .id_table = anx7411_id, diff --git a/drivers/usb/typec/class.c b/drivers/usb/typec/class.c index 349cc2030c903792f28466e156128e5424060397..faa184ae3dac8d03378d1fb1911ec2dc1b5d9880 100644 --- a/drivers/usb/typec/class.c +++ b/drivers/usb/typec/class.c @@ -2110,7 +2110,7 @@ typec_port_register_altmode(struct typec_port *port, struct typec_mux *mux; struct typec_retimer *retimer; - mux = typec_mux_get(&port->dev, desc); + mux = typec_mux_get(&port->dev); if (IS_ERR(mux)) return ERR_CAST(mux); @@ -2274,7 +2274,7 @@ struct typec_port *typec_register_port(struct device *parent, return ERR_PTR(ret); } - port->mux = typec_mux_get(&port->dev, NULL); + port->mux = typec_mux_get(&port->dev); if (IS_ERR(port->mux)) { ret = PTR_ERR(port->mux); put_device(&port->dev); diff --git a/drivers/usb/typec/hd3ss3220.c b/drivers/usb/typec/hd3ss3220.c index 8bbeb9b1e439407132fbb8bada675b4cc878b4a3..fb1242e82ffdc64a9a3330f50155bb8f0fe45685 100644 --- a/drivers/usb/typec/hd3ss3220.c +++ b/drivers/usb/typec/hd3ss3220.c @@ -292,8 +292,8 @@ static struct i2c_driver hd3ss3220_driver = { .name = "hd3ss3220", .of_match_table = dev_ids, }, - .probe_new = hd3ss3220_probe, - .remove = hd3ss3220_remove, + .probe = hd3ss3220_probe, + .remove = hd3ss3220_remove, }; module_i2c_driver(hd3ss3220_driver); diff --git a/drivers/usb/typec/mux.c b/drivers/usb/typec/mux.c index d9eaf9a0b0bfd7b960f6936b11632ad770b37a0e..80dd91938d96066d5286d8096cefb47c4b355c7c 100644 --- a/drivers/usb/typec/mux.c +++ b/drivers/usb/typec/mux.c @@ -265,60 +265,19 @@ static int mux_fwnode_match(struct device *dev, const void *fwnode) static void *typec_mux_match(const struct fwnode_handle *fwnode, const char *id, void *data) { - const struct typec_altmode_desc *desc = data; struct device *dev; - bool match; - int nval; - u16 *val; - int ret; - int i; /* - * Check has the identifier already been "consumed". If it - * has, no need to do any extra connection identification. + * Device graph (OF graph) does not give any means to identify the + * device type or the device class of the remote port parent that @fwnode + * represents, so in order to identify the type or the class of @fwnode + * an additional device property is needed. With typec muxes the + * property is named "mode-switch" (@id). The value of the device + * property is ignored. */ - match = !id; - if (match) - goto find_mux; - - if (!desc) { - /* - * Accessory Mode muxes & muxes which explicitly specify - * the required identifier can avoid SVID matching. - */ - match = fwnode_property_present(fwnode, "accessory") || - fwnode_property_present(fwnode, id); - if (match) - goto find_mux; - return NULL; - } - - /* Alternate Mode muxes */ - nval = fwnode_property_count_u16(fwnode, "svid"); - if (nval <= 0) + if (id && !fwnode_property_present(fwnode, id)) return NULL; - val = kcalloc(nval, sizeof(*val), GFP_KERNEL); - if (!val) - return ERR_PTR(-ENOMEM); - - ret = fwnode_property_read_u16_array(fwnode, "svid", val, nval); - if (ret < 0) { - kfree(val); - return ERR_PTR(ret); - } - - for (i = 0; i < nval; i++) { - match = val[i] == desc->svid; - if (match) { - kfree(val); - goto find_mux; - } - } - kfree(val); - return NULL; - -find_mux: dev = class_find_device(&typec_mux_class, NULL, fwnode, mux_fwnode_match); @@ -328,15 +287,13 @@ static void *typec_mux_match(const struct fwnode_handle *fwnode, /** * fwnode_typec_mux_get - Find USB Type-C Multiplexer * @fwnode: The caller device node - * @desc: Alt Mode description * * Finds a mux linked to the caller. This function is primarily meant for the * Type-C drivers. Returns a reference to the mux on success, NULL if no * matching connection was found, or ERR_PTR(-EPROBE_DEFER) when a connection * was found but the mux has not been enumerated yet. */ -struct typec_mux *fwnode_typec_mux_get(struct fwnode_handle *fwnode, - const struct typec_altmode_desc *desc) +struct typec_mux *fwnode_typec_mux_get(struct fwnode_handle *fwnode) { struct typec_mux_dev *mux_devs[TYPEC_MUX_MAX_DEVS]; struct typec_mux *mux; @@ -349,7 +306,7 @@ struct typec_mux *fwnode_typec_mux_get(struct fwnode_handle *fwnode, return ERR_PTR(-ENOMEM); count = fwnode_connection_find_matches(fwnode, "mode-switch", - (void *)desc, typec_mux_match, + NULL, typec_mux_match, (void **)mux_devs, ARRAY_SIZE(mux_devs)); if (count <= 0) { diff --git a/drivers/usb/typec/mux/Kconfig b/drivers/usb/typec/mux/Kconfig index c46fa4f9d3df66a7af2d9ea093e5e8bed62596cb..784b9d8107e9bb770c18e5ee48531dd665dfaf9c 100644 --- a/drivers/usb/typec/mux/Kconfig +++ b/drivers/usb/typec/mux/Kconfig @@ -35,4 +35,14 @@ config TYPEC_MUX_INTEL_PMC control the USB role switch and also the multiplexer/demultiplexer switches used with USB Type-C Alternate Modes. +config TYPEC_MUX_NB7VPQ904M + tristate "On Semiconductor NB7VPQ904M Type-C redriver driver" + depends on I2C + depends on DRM || DRM=n + select DRM_PANEL_BRIDGE if DRM + select REGMAP_I2C + help + Say Y or M if your system has a On Semiconductor NB7VPQ904M Type-C + redriver chip found on some devices with a Type-C port. + endmenu diff --git a/drivers/usb/typec/mux/Makefile b/drivers/usb/typec/mux/Makefile index dda67e19b58b1d3ea7f57d4efd008bb3b5605f2c..76196096ef4167ac14566cf02e4c76965442b85a 100644 --- a/drivers/usb/typec/mux/Makefile +++ b/drivers/usb/typec/mux/Makefile @@ -4,3 +4,4 @@ obj-$(CONFIG_TYPEC_MUX_FSA4480) += fsa4480.o obj-$(CONFIG_TYPEC_MUX_GPIO_SBU) += gpio-sbu-mux.o obj-$(CONFIG_TYPEC_MUX_PI3USB30532) += pi3usb30532.o obj-$(CONFIG_TYPEC_MUX_INTEL_PMC) += intel_pmc_mux.o +obj-$(CONFIG_TYPEC_MUX_NB7VPQ904M) += nb7vpq904m.o diff --git a/drivers/usb/typec/mux/fsa4480.c b/drivers/usb/typec/mux/fsa4480.c index d6495e533e585a88a317bd0bda0974d0dd81513f..e0ee1f621abbe72c4a406db39686f0d7d728ecca 100644 --- a/drivers/usb/typec/mux/fsa4480.c +++ b/drivers/usb/typec/mux/fsa4480.c @@ -25,15 +25,24 @@ #define FSA4480_DELAY_L_MIC 0x0e #define FSA4480_DELAY_L_SENSE 0x0f #define FSA4480_DELAY_L_AGND 0x10 +#define FSA4480_FUNCTION_ENABLE 0x12 #define FSA4480_RESET 0x1e #define FSA4480_MAX_REGISTER 0x1f #define FSA4480_ENABLE_DEVICE BIT(7) #define FSA4480_ENABLE_SBU GENMASK(6, 5) #define FSA4480_ENABLE_USB GENMASK(4, 3) +#define FSA4480_ENABLE_SENSE BIT(2) +#define FSA4480_ENABLE_MIC BIT(1) +#define FSA4480_ENABLE_AGND BIT(0) #define FSA4480_SEL_SBU_REVERSE GENMASK(6, 5) #define FSA4480_SEL_USB GENMASK(4, 3) +#define FSA4480_SEL_SENSE BIT(2) +#define FSA4480_SEL_MIC BIT(1) +#define FSA4480_SEL_AGND BIT(0) + +#define FSA4480_ENABLE_AUTO_JACK_DETECT BIT(0) struct fsa4480 { struct i2c_client *client; @@ -46,8 +55,11 @@ struct fsa4480 { struct regmap *regmap; + enum typec_orientation orientation; + unsigned long mode; + unsigned int svid; + u8 cur_enable; - u8 cur_select; }; static const struct regmap_config fsa4480_regmap_config = { @@ -58,19 +70,45 @@ static const struct regmap_config fsa4480_regmap_config = { .disable_locking = true, }; -static int fsa4480_switch_set(struct typec_switch_dev *sw, - enum typec_orientation orientation) +static int fsa4480_set(struct fsa4480 *fsa) { - struct fsa4480 *fsa = typec_switch_get_drvdata(sw); - u8 new_sel; - - mutex_lock(&fsa->lock); - new_sel = FSA4480_SEL_USB; - if (orientation == TYPEC_ORIENTATION_REVERSE) - new_sel |= FSA4480_SEL_SBU_REVERSE; - - if (new_sel == fsa->cur_select) - goto out_unlock; + bool reverse = (fsa->orientation == TYPEC_ORIENTATION_REVERSE); + u8 enable = FSA4480_ENABLE_DEVICE; + u8 sel = 0; + + /* USB Mode */ + if (fsa->mode < TYPEC_STATE_MODAL || + (!fsa->svid && (fsa->mode == TYPEC_MODE_USB2 || + fsa->mode == TYPEC_MODE_USB3))) { + enable |= FSA4480_ENABLE_USB; + sel = FSA4480_SEL_USB; + } else if (fsa->svid) { + switch (fsa->mode) { + /* DP Only */ + case TYPEC_DP_STATE_C: + case TYPEC_DP_STATE_E: + enable |= FSA4480_ENABLE_SBU; + if (reverse) + sel = FSA4480_SEL_SBU_REVERSE; + break; + + /* DP + USB */ + case TYPEC_DP_STATE_D: + case TYPEC_DP_STATE_F: + enable |= FSA4480_ENABLE_USB | FSA4480_ENABLE_SBU; + sel = FSA4480_SEL_USB; + if (reverse) + sel |= FSA4480_SEL_SBU_REVERSE; + break; + + default: + return -EOPNOTSUPP; + } + } else if (fsa->mode == TYPEC_MODE_AUDIO) { + /* Audio Accessory Mode, setup to auto Jack Detection */ + enable |= FSA4480_ENABLE_USB | FSA4480_ENABLE_AGND; + } else + return -EOPNOTSUPP; if (fsa->cur_enable & FSA4480_ENABLE_SBU) { /* Disable SBU output while re-configuring the switch */ @@ -81,48 +119,64 @@ static int fsa4480_switch_set(struct typec_switch_dev *sw, usleep_range(35, 1000); } - regmap_write(fsa->regmap, FSA4480_SWITCH_SELECT, new_sel); - fsa->cur_select = new_sel; + regmap_write(fsa->regmap, FSA4480_SWITCH_SELECT, sel); + regmap_write(fsa->regmap, FSA4480_SWITCH_ENABLE, enable); - if (fsa->cur_enable & FSA4480_ENABLE_SBU) { - regmap_write(fsa->regmap, FSA4480_SWITCH_ENABLE, fsa->cur_enable); + /* Start AUDIO JACK DETECTION to setup MIC, AGND & Sense muxes */ + if (enable & FSA4480_ENABLE_AGND) + regmap_write(fsa->regmap, FSA4480_FUNCTION_ENABLE, + FSA4480_ENABLE_AUTO_JACK_DETECT); + if (enable & FSA4480_ENABLE_SBU) { /* 15us to allow the SBU switch to turn on again */ usleep_range(15, 1000); } -out_unlock: - mutex_unlock(&fsa->lock); + fsa->cur_enable = enable; return 0; } +static int fsa4480_switch_set(struct typec_switch_dev *sw, + enum typec_orientation orientation) +{ + struct fsa4480 *fsa = typec_switch_get_drvdata(sw); + int ret = 0; + + mutex_lock(&fsa->lock); + + if (fsa->orientation != orientation) { + fsa->orientation = orientation; + + ret = fsa4480_set(fsa); + } + + mutex_unlock(&fsa->lock); + + return ret; +} + static int fsa4480_mux_set(struct typec_mux_dev *mux, struct typec_mux_state *state) { struct fsa4480 *fsa = typec_mux_get_drvdata(mux); - u8 new_enable; + int ret = 0; mutex_lock(&fsa->lock); - new_enable = FSA4480_ENABLE_DEVICE | FSA4480_ENABLE_USB; - if (state->mode >= TYPEC_DP_STATE_A) - new_enable |= FSA4480_ENABLE_SBU; + if (fsa->mode != state->mode) { + fsa->mode = state->mode; - if (new_enable == fsa->cur_enable) - goto out_unlock; + if (state->alt) + fsa->svid = state->alt->svid; + else + fsa->svid = 0; // No SVID - regmap_write(fsa->regmap, FSA4480_SWITCH_ENABLE, new_enable); - fsa->cur_enable = new_enable; - - if (new_enable & FSA4480_ENABLE_SBU) { - /* 15us to allow the SBU switch to turn off */ - usleep_range(15, 1000); + ret = fsa4480_set(fsa); } -out_unlock: mutex_unlock(&fsa->lock); - return 0; + return ret; } static int fsa4480_probe(struct i2c_client *client) @@ -143,8 +197,10 @@ static int fsa4480_probe(struct i2c_client *client) if (IS_ERR(fsa->regmap)) return dev_err_probe(dev, PTR_ERR(fsa->regmap), "failed to initialize regmap\n"); + /* Safe mode */ fsa->cur_enable = FSA4480_ENABLE_DEVICE | FSA4480_ENABLE_USB; - fsa->cur_select = FSA4480_SEL_USB; + fsa->mode = TYPEC_STATE_SAFE; + fsa->orientation = TYPEC_ORIENTATION_NONE; /* set default settings */ regmap_write(fsa->regmap, FSA4480_SLOW_L, 0x00); @@ -156,7 +212,7 @@ static int fsa4480_probe(struct i2c_client *client) regmap_write(fsa->regmap, FSA4480_DELAY_L_MIC, 0x00); regmap_write(fsa->regmap, FSA4480_DELAY_L_SENSE, 0x00); regmap_write(fsa->regmap, FSA4480_DELAY_L_AGND, 0x09); - regmap_write(fsa->regmap, FSA4480_SWITCH_SELECT, fsa->cur_select); + regmap_write(fsa->regmap, FSA4480_SWITCH_SELECT, FSA4480_SEL_USB); regmap_write(fsa->regmap, FSA4480_SWITCH_ENABLE, fsa->cur_enable); sw_desc.drvdata = fsa; @@ -206,7 +262,7 @@ static struct i2c_driver fsa4480_driver = { .name = "fsa4480", .of_match_table = fsa4480_of_table, }, - .probe_new = fsa4480_probe, + .probe = fsa4480_probe, .remove = fsa4480_remove, .id_table = fsa4480_table, }; diff --git a/drivers/usb/typec/mux/gpio-sbu-mux.c b/drivers/usb/typec/mux/gpio-sbu-mux.c index f62516dafe8fad5c9bbfe202734e66a811b8a750..ad60fd4e8431e2e0db5a5b0ae92d3467a26247e7 100644 --- a/drivers/usb/typec/mux/gpio-sbu-mux.c +++ b/drivers/usb/typec/mux/gpio-sbu-mux.c @@ -3,14 +3,11 @@ * Copyright (C) 2022 Linaro Ltd. */ -#include -#include -#include +#include #include #include #include #include -#include #include #include @@ -140,7 +137,7 @@ static int gpio_sbu_mux_probe(struct platform_device *pdev) return 0; } -static int gpio_sbu_mux_remove(struct platform_device *pdev) +static void gpio_sbu_mux_remove(struct platform_device *pdev) { struct gpio_sbu_mux *sbu_mux = platform_get_drvdata(pdev); @@ -148,8 +145,6 @@ static int gpio_sbu_mux_remove(struct platform_device *pdev) typec_mux_unregister(sbu_mux->mux); typec_switch_unregister(sbu_mux->sw); - - return 0; } static const struct of_device_id gpio_sbu_mux_match[] = { @@ -160,7 +155,7 @@ MODULE_DEVICE_TABLE(of, gpio_sbu_mux_match); static struct platform_driver gpio_sbu_mux_driver = { .probe = gpio_sbu_mux_probe, - .remove = gpio_sbu_mux_remove, + .remove_new = gpio_sbu_mux_remove, .driver = { .name = "gpio_sbu_mux", .of_match_table = gpio_sbu_mux_match, diff --git a/drivers/usb/typec/mux/intel_pmc_mux.c b/drivers/usb/typec/mux/intel_pmc_mux.c index 34e4188a40ff4743b4e374247b7472f02f7297d5..5e8edf3881c0dd0a252622bf4dea02985a0e20e7 100644 --- a/drivers/usb/typec/mux/intel_pmc_mux.c +++ b/drivers/usb/typec/mux/intel_pmc_mux.c @@ -15,6 +15,8 @@ #include #include #include +#include +#include #include @@ -143,8 +145,12 @@ struct pmc_usb { struct acpi_device *iom_adev; void __iomem *iom_base; u32 iom_port_status_offset; + + struct dentry *dentry; }; +static struct dentry *pmc_mux_debugfs_root; + static void update_port_status(struct pmc_usb_port *port) { u8 port_num; @@ -639,6 +645,29 @@ static int pmc_usb_probe_iom(struct pmc_usb *pmc) return 0; } +static int port_iom_status_show(struct seq_file *s, void *unused) +{ + struct pmc_usb_port *port = s->private; + + update_port_status(port); + seq_printf(s, "0x%08x\n", port->iom_status); + + return 0; +} +DEFINE_SHOW_ATTRIBUTE(port_iom_status); + +static void pmc_mux_port_debugfs_init(struct pmc_usb_port *port) +{ + struct dentry *debugfs_dir; + char name[6]; + + snprintf(name, sizeof(name), "port%d", port->usb3_port - 1); + + debugfs_dir = debugfs_create_dir(name, port->pmc->dentry); + debugfs_create_file("iom_status", 0400, debugfs_dir, port, + &port_iom_status_fops); +} + static int pmc_usb_probe(struct platform_device *pdev) { struct fwnode_handle *fwnode = NULL; @@ -674,6 +703,8 @@ static int pmc_usb_probe(struct platform_device *pdev) if (ret) return ret; + pmc->dentry = debugfs_create_dir(dev_name(pmc->dev), pmc_mux_debugfs_root); + /* * For every physical USB connector (USB2 and USB3 combo) there is a * child ACPI device node under the PMC mux ACPI device object. @@ -688,6 +719,8 @@ static int pmc_usb_probe(struct platform_device *pdev) fwnode_handle_put(fwnode); goto err_remove_ports; } + + pmc_mux_port_debugfs_init(&pmc->port[i]); } platform_set_drvdata(pdev, pmc); @@ -703,10 +736,12 @@ static int pmc_usb_probe(struct platform_device *pdev) acpi_dev_put(pmc->iom_adev); + debugfs_remove(pmc->dentry); + return ret; } -static int pmc_usb_remove(struct platform_device *pdev) +static void pmc_usb_remove(struct platform_device *pdev) { struct pmc_usb *pmc = platform_get_drvdata(pdev); int i; @@ -719,7 +754,7 @@ static int pmc_usb_remove(struct platform_device *pdev) acpi_dev_put(pmc->iom_adev); - return 0; + debugfs_remove(pmc->dentry); } static const struct acpi_device_id pmc_usb_acpi_ids[] = { @@ -734,10 +769,23 @@ static struct platform_driver pmc_usb_driver = { .acpi_match_table = ACPI_PTR(pmc_usb_acpi_ids), }, .probe = pmc_usb_probe, - .remove = pmc_usb_remove, + .remove_new = pmc_usb_remove, }; -module_platform_driver(pmc_usb_driver); +static int __init pmc_usb_init(void) +{ + pmc_mux_debugfs_root = debugfs_create_dir("intel_pmc_mux", usb_debug_root); + + return platform_driver_register(&pmc_usb_driver); +} +module_init(pmc_usb_init); + +static void __exit pmc_usb_exit(void) +{ + platform_driver_unregister(&pmc_usb_driver); + debugfs_remove(pmc_mux_debugfs_root); +} +module_exit(pmc_usb_exit); MODULE_AUTHOR("Heikki Krogerus "); MODULE_LICENSE("GPL v2"); diff --git a/drivers/usb/typec/mux/nb7vpq904m.c b/drivers/usb/typec/mux/nb7vpq904m.c new file mode 100644 index 0000000000000000000000000000000000000000..80e580d50129128343ddf91ea32f206136706740 --- /dev/null +++ b/drivers/usb/typec/mux/nb7vpq904m.c @@ -0,0 +1,529 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * OnSemi NB7VPQ904M Type-C driver + * + * Copyright (C) 2023 Dmitry Baryshkov + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define NB7_CHNA 0 +#define NB7_CHNB 1 +#define NB7_CHNC 2 +#define NB7_CHND 3 +#define NB7_IS_CHAN_AD(channel) (channel == NB7_CHNA || channel == NB7_CHND) + +#define GEN_DEV_SET_REG 0x00 + +#define GEN_DEV_SET_CHIP_EN BIT(0) +#define GEN_DEV_SET_CHNA_EN BIT(4) +#define GEN_DEV_SET_CHNB_EN BIT(5) +#define GEN_DEV_SET_CHNC_EN BIT(6) +#define GEN_DEV_SET_CHND_EN BIT(7) + +#define GEN_DEV_SET_OP_MODE_MASK GENMASK(3, 1) + +#define GEN_DEV_SET_OP_MODE_DP_CC2 0 +#define GEN_DEV_SET_OP_MODE_DP_CC1 1 +#define GEN_DEV_SET_OP_MODE_DP_4LANE 2 +#define GEN_DEV_SET_OP_MODE_USB 5 + +#define EQ_SETTING_REG_BASE 0x01 +#define EQ_SETTING_REG(n) (EQ_SETTING_REG_BASE + (n) * 2) +#define EQ_SETTING_MASK GENMASK(3, 1) + +#define OUTPUT_COMPRESSION_AND_POL_REG_BASE 0x02 +#define OUTPUT_COMPRESSION_AND_POL_REG(n) (OUTPUT_COMPRESSION_AND_POL_REG_BASE + (n) * 2) +#define OUTPUT_COMPRESSION_MASK GENMASK(2, 1) + +#define FLAT_GAIN_REG_BASE 0x18 +#define FLAT_GAIN_REG(n) (FLAT_GAIN_REG_BASE + (n) * 2) +#define FLAT_GAIN_MASK GENMASK(1, 0) + +#define LOSS_MATCH_REG_BASE 0x19 +#define LOSS_MATCH_REG(n) (LOSS_MATCH_REG_BASE + (n) * 2) +#define LOSS_MATCH_MASK GENMASK(1, 0) + +#define AUX_CC_REG 0x09 + +#define CHIP_VERSION_REG 0x17 + +struct nb7vpq904m { + struct i2c_client *client; + struct gpio_desc *enable_gpio; + struct regulator *vcc_supply; + struct regmap *regmap; + struct typec_switch_dev *sw; + struct typec_retimer *retimer; + + bool swap_data_lanes; + struct typec_switch *typec_switch; + + struct drm_bridge bridge; + + struct mutex lock; /* protect non-concurrent retimer & switch */ + + enum typec_orientation orientation; + unsigned long mode; + unsigned int svid; +}; + +static void nb7vpq904m_set_channel(struct nb7vpq904m *nb7, unsigned int channel, bool dp) +{ + u8 eq, out_comp, flat_gain, loss_match; + + if (dp) { + eq = NB7_IS_CHAN_AD(channel) ? 0x6 : 0x4; + out_comp = 0x3; + flat_gain = NB7_IS_CHAN_AD(channel) ? 0x2 : 0x1; + loss_match = 0x3; + } else { + eq = 0x4; + out_comp = 0x3; + flat_gain = NB7_IS_CHAN_AD(channel) ? 0x3 : 0x1; + loss_match = NB7_IS_CHAN_AD(channel) ? 0x1 : 0x3; + } + + regmap_update_bits(nb7->regmap, EQ_SETTING_REG(channel), + EQ_SETTING_MASK, FIELD_PREP(EQ_SETTING_MASK, eq)); + regmap_update_bits(nb7->regmap, OUTPUT_COMPRESSION_AND_POL_REG(channel), + OUTPUT_COMPRESSION_MASK, FIELD_PREP(OUTPUT_COMPRESSION_MASK, out_comp)); + regmap_update_bits(nb7->regmap, FLAT_GAIN_REG(channel), + FLAT_GAIN_MASK, FIELD_PREP(FLAT_GAIN_MASK, flat_gain)); + regmap_update_bits(nb7->regmap, LOSS_MATCH_REG(channel), + LOSS_MATCH_MASK, FIELD_PREP(LOSS_MATCH_MASK, loss_match)); +} + +static int nb7vpq904m_set(struct nb7vpq904m *nb7) +{ + bool reverse = (nb7->orientation == TYPEC_ORIENTATION_REVERSE); + + switch (nb7->mode) { + case TYPEC_STATE_SAFE: + regmap_write(nb7->regmap, GEN_DEV_SET_REG, + GEN_DEV_SET_CHIP_EN | + GEN_DEV_SET_CHNA_EN | + GEN_DEV_SET_CHNB_EN | + GEN_DEV_SET_CHNC_EN | + GEN_DEV_SET_CHND_EN | + FIELD_PREP(GEN_DEV_SET_OP_MODE_MASK, + GEN_DEV_SET_OP_MODE_USB)); + nb7vpq904m_set_channel(nb7, NB7_CHNA, false); + nb7vpq904m_set_channel(nb7, NB7_CHNB, false); + nb7vpq904m_set_channel(nb7, NB7_CHNC, false); + nb7vpq904m_set_channel(nb7, NB7_CHND, false); + regmap_write(nb7->regmap, AUX_CC_REG, 0x2); + + return 0; + + case TYPEC_STATE_USB: + /* + * Normal Orientation (CC1) + * A -> USB RX + * B -> USB TX + * C -> X + * D -> X + * Flipped Orientation (CC2) + * A -> X + * B -> X + * C -> USB TX + * D -> USB RX + * + * Reversed if data lanes are swapped + */ + if (reverse ^ nb7->swap_data_lanes) { + regmap_write(nb7->regmap, GEN_DEV_SET_REG, + GEN_DEV_SET_CHIP_EN | + GEN_DEV_SET_CHNA_EN | + GEN_DEV_SET_CHNB_EN | + FIELD_PREP(GEN_DEV_SET_OP_MODE_MASK, + GEN_DEV_SET_OP_MODE_USB)); + nb7vpq904m_set_channel(nb7, NB7_CHNA, false); + nb7vpq904m_set_channel(nb7, NB7_CHNB, false); + } else { + regmap_write(nb7->regmap, GEN_DEV_SET_REG, + GEN_DEV_SET_CHIP_EN | + GEN_DEV_SET_CHNC_EN | + GEN_DEV_SET_CHND_EN | + FIELD_PREP(GEN_DEV_SET_OP_MODE_MASK, + GEN_DEV_SET_OP_MODE_USB)); + nb7vpq904m_set_channel(nb7, NB7_CHNC, false); + nb7vpq904m_set_channel(nb7, NB7_CHND, false); + } + regmap_write(nb7->regmap, AUX_CC_REG, 0x2); + + return 0; + + default: + if (nb7->svid != USB_TYPEC_DP_SID) + return -EINVAL; + + break; + } + + /* DP Altmode Setup */ + + regmap_write(nb7->regmap, AUX_CC_REG, reverse ? 0x1 : 0x0); + + switch (nb7->mode) { + case TYPEC_DP_STATE_C: + case TYPEC_DP_STATE_E: + /* + * Normal Orientation (CC1) + * A -> DP3 + * B -> DP2 + * C -> DP1 + * D -> DP0 + * Flipped Orientation (CC2) + * A -> DP0 + * B -> DP1 + * C -> DP2 + * D -> DP3 + */ + regmap_write(nb7->regmap, GEN_DEV_SET_REG, + GEN_DEV_SET_CHIP_EN | + GEN_DEV_SET_CHNA_EN | + GEN_DEV_SET_CHNB_EN | + GEN_DEV_SET_CHNC_EN | + GEN_DEV_SET_CHND_EN | + FIELD_PREP(GEN_DEV_SET_OP_MODE_MASK, + GEN_DEV_SET_OP_MODE_DP_4LANE)); + nb7vpq904m_set_channel(nb7, NB7_CHNA, true); + nb7vpq904m_set_channel(nb7, NB7_CHNB, true); + nb7vpq904m_set_channel(nb7, NB7_CHNC, true); + nb7vpq904m_set_channel(nb7, NB7_CHND, true); + break; + + case TYPEC_DP_STATE_D: + case TYPEC_DP_STATE_F: + regmap_write(nb7->regmap, GEN_DEV_SET_REG, + GEN_DEV_SET_CHIP_EN | + GEN_DEV_SET_CHNA_EN | + GEN_DEV_SET_CHNB_EN | + GEN_DEV_SET_CHNC_EN | + GEN_DEV_SET_CHND_EN | + FIELD_PREP(GEN_DEV_SET_OP_MODE_MASK, + reverse ^ nb7->swap_data_lanes ? + GEN_DEV_SET_OP_MODE_DP_CC2 + : GEN_DEV_SET_OP_MODE_DP_CC1)); + + /* + * Normal Orientation (CC1) + * A -> USB RX + * B -> USB TX + * C -> DP1 + * D -> DP0 + * Flipped Orientation (CC2) + * A -> DP0 + * B -> DP1 + * C -> USB TX + * D -> USB RX + * + * Reversed if data lanes are swapped + */ + if (nb7->swap_data_lanes) { + nb7vpq904m_set_channel(nb7, NB7_CHNA, !reverse); + nb7vpq904m_set_channel(nb7, NB7_CHNB, !reverse); + nb7vpq904m_set_channel(nb7, NB7_CHNC, reverse); + nb7vpq904m_set_channel(nb7, NB7_CHND, reverse); + } else { + nb7vpq904m_set_channel(nb7, NB7_CHNA, reverse); + nb7vpq904m_set_channel(nb7, NB7_CHNB, reverse); + nb7vpq904m_set_channel(nb7, NB7_CHNC, !reverse); + nb7vpq904m_set_channel(nb7, NB7_CHND, !reverse); + } + break; + + default: + return -EOPNOTSUPP; + } + + return 0; +} + +static int nb7vpq904m_sw_set(struct typec_switch_dev *sw, enum typec_orientation orientation) +{ + struct nb7vpq904m *nb7 = typec_switch_get_drvdata(sw); + int ret; + + ret = typec_switch_set(nb7->typec_switch, orientation); + if (ret) + return ret; + + mutex_lock(&nb7->lock); + + if (nb7->orientation != orientation) { + nb7->orientation = orientation; + + ret = nb7vpq904m_set(nb7); + } + + mutex_unlock(&nb7->lock); + + return ret; +} + +static int nb7vpq904m_retimer_set(struct typec_retimer *retimer, struct typec_retimer_state *state) +{ + struct nb7vpq904m *nb7 = typec_retimer_get_drvdata(retimer); + int ret = 0; + + mutex_lock(&nb7->lock); + + if (nb7->mode != state->mode) { + nb7->mode = state->mode; + + if (state->alt) + nb7->svid = state->alt->svid; + else + nb7->svid = 0; // No SVID + + ret = nb7vpq904m_set(nb7); + } + + mutex_unlock(&nb7->lock); + + return ret; +} + +#if IS_ENABLED(CONFIG_OF) && IS_ENABLED(CONFIG_DRM_PANEL_BRIDGE) +static int nb7vpq904m_bridge_attach(struct drm_bridge *bridge, + enum drm_bridge_attach_flags flags) +{ + struct nb7vpq904m *nb7 = container_of(bridge, struct nb7vpq904m, bridge); + struct drm_bridge *next_bridge; + + if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)) + return -EINVAL; + + next_bridge = devm_drm_of_get_bridge(&nb7->client->dev, nb7->client->dev.of_node, 0, 0); + if (IS_ERR(next_bridge)) { + dev_err(&nb7->client->dev, "failed to acquire drm_bridge: %pe\n", next_bridge); + return PTR_ERR(next_bridge); + } + + return drm_bridge_attach(bridge->encoder, next_bridge, bridge, + DRM_BRIDGE_ATTACH_NO_CONNECTOR); +} + +static const struct drm_bridge_funcs nb7vpq904m_bridge_funcs = { + .attach = nb7vpq904m_bridge_attach, +}; + +static int nb7vpq904m_register_bridge(struct nb7vpq904m *nb7) +{ + nb7->bridge.funcs = &nb7vpq904m_bridge_funcs; + nb7->bridge.of_node = nb7->client->dev.of_node; + + return devm_drm_bridge_add(&nb7->client->dev, &nb7->bridge); +} +#else +static int nb7vpq904m_register_bridge(struct nb7vpq904m *nb7) +{ + return 0; +} +#endif + +static const struct regmap_config nb7_regmap = { + .max_register = 0x1f, + .reg_bits = 8, + .val_bits = 8, +}; + +enum { + NORMAL_LANE_MAPPING, + INVERT_LANE_MAPPING, +}; + +#define DATA_LANES_COUNT 4 + +static const int supported_data_lane_mapping[][DATA_LANES_COUNT] = { + [NORMAL_LANE_MAPPING] = { 0, 1, 2, 3 }, + [INVERT_LANE_MAPPING] = { 3, 2, 1, 0 }, +}; + +static int nb7vpq904m_parse_data_lanes_mapping(struct nb7vpq904m *nb7) +{ + struct device_node *ep; + u32 data_lanes[4]; + int ret, i, j; + + ep = of_graph_get_endpoint_by_regs(nb7->client->dev.of_node, 1, 0); + + if (ep) { + ret = of_property_count_u32_elems(ep, "data-lanes"); + if (ret == -EINVAL) + /* Property isn't here, consider default mapping */ + goto out_done; + if (ret < 0) + goto out_error; + + if (ret != DATA_LANES_COUNT) { + dev_err(&nb7->client->dev, "expected 4 data lanes\n"); + ret = -EINVAL; + goto out_error; + } + + ret = of_property_read_u32_array(ep, "data-lanes", data_lanes, DATA_LANES_COUNT); + if (ret) + goto out_error; + + for (i = 0; i < ARRAY_SIZE(supported_data_lane_mapping); i++) { + for (j = 0; j < DATA_LANES_COUNT; j++) { + if (data_lanes[j] != supported_data_lane_mapping[i][j]) + break; + } + + if (j == DATA_LANES_COUNT) + break; + } + + switch (i) { + case NORMAL_LANE_MAPPING: + break; + case INVERT_LANE_MAPPING: + nb7->swap_data_lanes = true; + dev_info(&nb7->client->dev, "using inverted data lanes mapping\n"); + break; + default: + dev_err(&nb7->client->dev, "invalid data lanes mapping\n"); + ret = -EINVAL; + goto out_error; + } + } + +out_done: + ret = 0; + +out_error: + of_node_put(ep); + + return ret; +} + +static int nb7vpq904m_probe(struct i2c_client *client) +{ + struct device *dev = &client->dev; + struct typec_switch_desc sw_desc = { }; + struct typec_retimer_desc retimer_desc = { }; + struct nb7vpq904m *nb7; + int ret; + + nb7 = devm_kzalloc(dev, sizeof(*nb7), GFP_KERNEL); + if (!nb7) + return -ENOMEM; + + nb7->client = client; + + nb7->regmap = devm_regmap_init_i2c(client, &nb7_regmap); + if (IS_ERR(nb7->regmap)) { + dev_err(&client->dev, "Failed to allocate register map\n"); + return PTR_ERR(nb7->regmap); + } + + nb7->mode = TYPEC_STATE_SAFE; + nb7->orientation = TYPEC_ORIENTATION_NONE; + + mutex_init(&nb7->lock); + + nb7->enable_gpio = devm_gpiod_get_optional(dev, "enable", GPIOD_OUT_LOW); + if (IS_ERR(nb7->enable_gpio)) + return dev_err_probe(dev, PTR_ERR(nb7->enable_gpio), + "unable to acquire enable gpio\n"); + + nb7->vcc_supply = devm_regulator_get_optional(dev, "vcc"); + if (IS_ERR(nb7->vcc_supply)) + return PTR_ERR(nb7->vcc_supply); + + nb7->typec_switch = fwnode_typec_switch_get(dev->fwnode); + if (IS_ERR(nb7->typec_switch)) + return dev_err_probe(dev, PTR_ERR(nb7->typec_switch), + "failed to acquire orientation-switch\n"); + + ret = nb7vpq904m_parse_data_lanes_mapping(nb7); + if (ret) + return ret; + + ret = regulator_enable(nb7->vcc_supply); + if (ret) + dev_warn(dev, "Failed to enable vcc: %d\n", ret); + + gpiod_set_value(nb7->enable_gpio, 1); + + ret = nb7vpq904m_register_bridge(nb7); + if (ret) + return ret; + + sw_desc.drvdata = nb7; + sw_desc.fwnode = dev->fwnode; + sw_desc.set = nb7vpq904m_sw_set; + + nb7->sw = typec_switch_register(dev, &sw_desc); + if (IS_ERR(nb7->sw)) + return dev_err_probe(dev, PTR_ERR(nb7->sw), + "Error registering typec switch\n"); + + retimer_desc.drvdata = nb7; + retimer_desc.fwnode = dev->fwnode; + retimer_desc.set = nb7vpq904m_retimer_set; + + nb7->retimer = typec_retimer_register(dev, &retimer_desc); + if (IS_ERR(nb7->retimer)) { + typec_switch_unregister(nb7->sw); + return dev_err_probe(dev, PTR_ERR(nb7->retimer), + "Error registering typec retimer\n"); + } + + return 0; +} + +static void nb7vpq904m_remove(struct i2c_client *client) +{ + struct nb7vpq904m *nb7 = i2c_get_clientdata(client); + + typec_retimer_unregister(nb7->retimer); + typec_switch_unregister(nb7->sw); + + gpiod_set_value(nb7->enable_gpio, 0); + + regulator_disable(nb7->vcc_supply); +} + +static const struct i2c_device_id nb7vpq904m_table[] = { + { "nb7vpq904m" }, + { } +}; +MODULE_DEVICE_TABLE(i2c, nb7vpq904m_table); + +static const struct of_device_id nb7vpq904m_of_table[] = { + { .compatible = "onnn,nb7vpq904m" }, + { } +}; +MODULE_DEVICE_TABLE(of, nb7vpq904m_of_table); + +static struct i2c_driver nb7vpq904m_driver = { + .driver = { + .name = "nb7vpq904m", + .of_match_table = nb7vpq904m_of_table, + }, + .probe_new = nb7vpq904m_probe, + .remove = nb7vpq904m_remove, + .id_table = nb7vpq904m_table, +}; + +module_i2c_driver(nb7vpq904m_driver); + +MODULE_AUTHOR("Dmitry Baryshkov "); +MODULE_DESCRIPTION("OnSemi NB7VPQ904M Type-C driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/usb/typec/mux/pi3usb30532.c b/drivers/usb/typec/mux/pi3usb30532.c index 1cd388b55c307748ac5841b759194311105ef8ff..8eeec135dcdbd0e67982309224341bde6ebedad6 100644 --- a/drivers/usb/typec/mux/pi3usb30532.c +++ b/drivers/usb/typec/mux/pi3usb30532.c @@ -178,7 +178,7 @@ static struct i2c_driver pi3usb30532_driver = { .driver = { .name = "pi3usb30532", }, - .probe_new = pi3usb30532_probe, + .probe = pi3usb30532_probe, .remove = pi3usb30532_remove, .id_table = pi3usb30532_table, }; diff --git a/drivers/usb/typec/qcom-pmic-typec.c b/drivers/usb/typec/qcom-pmic-typec.c deleted file mode 100644 index 432ea62f1bab66791dc7b85344c50526188f0c3c..0000000000000000000000000000000000000000 --- a/drivers/usb/typec/qcom-pmic-typec.c +++ /dev/null @@ -1,261 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright (c) 2020, The Linux Foundation. All rights reserved. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define TYPEC_MISC_STATUS 0xb -#define CC_ATTACHED BIT(0) -#define CC_ORIENTATION BIT(1) -#define SNK_SRC_MODE BIT(6) -#define TYPEC_MODE_CFG 0x44 -#define TYPEC_DISABLE_CMD BIT(0) -#define EN_SNK_ONLY BIT(1) -#define EN_SRC_ONLY BIT(2) -#define TYPEC_VCONN_CONTROL 0x46 -#define VCONN_EN_SRC BIT(0) -#define VCONN_EN_VAL BIT(1) -#define TYPEC_EXIT_STATE_CFG 0x50 -#define SEL_SRC_UPPER_REF BIT(2) -#define TYPEC_INTR_EN_CFG_1 0x5e -#define TYPEC_INTR_EN_CFG_1_MASK GENMASK(7, 0) - -struct qcom_pmic_typec { - struct device *dev; - struct regmap *regmap; - u32 base; - - struct typec_port *port; - struct usb_role_switch *role_sw; - - struct regulator *vbus_reg; - bool vbus_enabled; -}; - -static void qcom_pmic_typec_enable_vbus_regulator(struct qcom_pmic_typec - *qcom_usb, bool enable) -{ - int ret; - - if (enable == qcom_usb->vbus_enabled) - return; - - if (enable) { - ret = regulator_enable(qcom_usb->vbus_reg); - if (ret) - return; - } else { - ret = regulator_disable(qcom_usb->vbus_reg); - if (ret) - return; - } - qcom_usb->vbus_enabled = enable; -} - -static void qcom_pmic_typec_check_connection(struct qcom_pmic_typec *qcom_usb) -{ - enum typec_orientation orientation; - enum usb_role role; - unsigned int stat; - bool enable_vbus; - - regmap_read(qcom_usb->regmap, qcom_usb->base + TYPEC_MISC_STATUS, - &stat); - - if (stat & CC_ATTACHED) { - orientation = (stat & CC_ORIENTATION) ? - TYPEC_ORIENTATION_REVERSE : - TYPEC_ORIENTATION_NORMAL; - typec_set_orientation(qcom_usb->port, orientation); - - role = (stat & SNK_SRC_MODE) ? USB_ROLE_HOST : USB_ROLE_DEVICE; - if (role == USB_ROLE_HOST) - enable_vbus = true; - else - enable_vbus = false; - } else { - role = USB_ROLE_NONE; - enable_vbus = false; - } - - qcom_pmic_typec_enable_vbus_regulator(qcom_usb, enable_vbus); - usb_role_switch_set_role(qcom_usb->role_sw, role); -} - -static irqreturn_t qcom_pmic_typec_interrupt(int irq, void *_qcom_usb) -{ - struct qcom_pmic_typec *qcom_usb = _qcom_usb; - - qcom_pmic_typec_check_connection(qcom_usb); - return IRQ_HANDLED; -} - -static void qcom_pmic_typec_typec_hw_init(struct qcom_pmic_typec *qcom_usb, - enum typec_port_type type) -{ - u8 mode = 0; - - regmap_update_bits(qcom_usb->regmap, - qcom_usb->base + TYPEC_INTR_EN_CFG_1, - TYPEC_INTR_EN_CFG_1_MASK, 0); - - if (type == TYPEC_PORT_SRC) - mode = EN_SRC_ONLY; - else if (type == TYPEC_PORT_SNK) - mode = EN_SNK_ONLY; - - regmap_update_bits(qcom_usb->regmap, qcom_usb->base + TYPEC_MODE_CFG, - EN_SNK_ONLY | EN_SRC_ONLY, mode); - - regmap_update_bits(qcom_usb->regmap, - qcom_usb->base + TYPEC_VCONN_CONTROL, - VCONN_EN_SRC | VCONN_EN_VAL, VCONN_EN_SRC); - regmap_update_bits(qcom_usb->regmap, - qcom_usb->base + TYPEC_EXIT_STATE_CFG, - SEL_SRC_UPPER_REF, SEL_SRC_UPPER_REF); -} - -static int qcom_pmic_typec_probe(struct platform_device *pdev) -{ - struct qcom_pmic_typec *qcom_usb; - struct device *dev = &pdev->dev; - struct fwnode_handle *fwnode; - struct typec_capability cap; - const char *buf; - int ret, irq, role; - u32 reg; - - ret = device_property_read_u32(dev, "reg", ®); - if (ret < 0) { - dev_err(dev, "missing base address\n"); - return ret; - } - - qcom_usb = devm_kzalloc(dev, sizeof(*qcom_usb), GFP_KERNEL); - if (!qcom_usb) - return -ENOMEM; - - qcom_usb->dev = dev; - qcom_usb->base = reg; - - qcom_usb->regmap = dev_get_regmap(dev->parent, NULL); - if (!qcom_usb->regmap) { - dev_err(dev, "Failed to get regmap\n"); - return -EINVAL; - } - - qcom_usb->vbus_reg = devm_regulator_get(qcom_usb->dev, "usb_vbus"); - if (IS_ERR(qcom_usb->vbus_reg)) - return PTR_ERR(qcom_usb->vbus_reg); - - fwnode = device_get_named_child_node(dev, "connector"); - if (!fwnode) - return -EINVAL; - - ret = fwnode_property_read_string(fwnode, "power-role", &buf); - if (!ret) { - role = typec_find_port_power_role(buf); - if (role < 0) - role = TYPEC_PORT_SNK; - } else { - role = TYPEC_PORT_SNK; - } - cap.type = role; - - ret = fwnode_property_read_string(fwnode, "data-role", &buf); - if (!ret) { - role = typec_find_port_data_role(buf); - if (role < 0) - role = TYPEC_PORT_UFP; - } else { - role = TYPEC_PORT_UFP; - } - cap.data = role; - - cap.prefer_role = TYPEC_NO_PREFERRED_ROLE; - cap.fwnode = fwnode; - qcom_usb->port = typec_register_port(dev, &cap); - if (IS_ERR(qcom_usb->port)) { - ret = PTR_ERR(qcom_usb->port); - dev_err(dev, "Failed to register type c port %d\n", ret); - goto err_put_node; - } - fwnode_handle_put(fwnode); - - qcom_usb->role_sw = fwnode_usb_role_switch_get(dev_fwnode(qcom_usb->dev)); - if (IS_ERR(qcom_usb->role_sw)) { - ret = dev_err_probe(dev, PTR_ERR(qcom_usb->role_sw), - "failed to get role switch\n"); - goto err_typec_port; - } - - irq = platform_get_irq(pdev, 0); - if (irq < 0) - goto err_usb_role_sw; - - ret = devm_request_threaded_irq(qcom_usb->dev, irq, NULL, - qcom_pmic_typec_interrupt, IRQF_ONESHOT, - "qcom-pmic-typec", qcom_usb); - if (ret) { - dev_err(&pdev->dev, "Could not request IRQ\n"); - goto err_usb_role_sw; - } - - platform_set_drvdata(pdev, qcom_usb); - qcom_pmic_typec_typec_hw_init(qcom_usb, cap.type); - qcom_pmic_typec_check_connection(qcom_usb); - - return 0; - -err_usb_role_sw: - usb_role_switch_put(qcom_usb->role_sw); -err_typec_port: - typec_unregister_port(qcom_usb->port); -err_put_node: - fwnode_handle_put(fwnode); - - return ret; -} - -static int qcom_pmic_typec_remove(struct platform_device *pdev) -{ - struct qcom_pmic_typec *qcom_usb = platform_get_drvdata(pdev); - - usb_role_switch_set_role(qcom_usb->role_sw, USB_ROLE_NONE); - qcom_pmic_typec_enable_vbus_regulator(qcom_usb, 0); - - typec_unregister_port(qcom_usb->port); - usb_role_switch_put(qcom_usb->role_sw); - - return 0; -} - -static const struct of_device_id qcom_pmic_typec_table[] = { - { .compatible = "qcom,pm8150b-usb-typec" }, - { } -}; -MODULE_DEVICE_TABLE(of, qcom_pmic_typec_table); - -static struct platform_driver qcom_pmic_typec = { - .driver = { - .name = "qcom,pmic-typec", - .of_match_table = qcom_pmic_typec_table, - }, - .probe = qcom_pmic_typec_probe, - .remove = qcom_pmic_typec_remove, -}; -module_platform_driver(qcom_pmic_typec); - -MODULE_DESCRIPTION("QCOM PMIC USB type C driver"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/usb/typec/rt1719.c b/drivers/usb/typec/rt1719.c index ea8b700b0cebc15e6917432964266a3a4c35f1c6..be02d420920e57a56c65c625c821702a430012eb 100644 --- a/drivers/usb/typec/rt1719.c +++ b/drivers/usb/typec/rt1719.c @@ -949,7 +949,7 @@ static struct i2c_driver rt1719_driver = { .name = "rt1719", .of_match_table = rt1719_device_table, }, - .probe_new = rt1719_probe, + .probe = rt1719_probe, .remove = rt1719_remove, }; module_i2c_driver(rt1719_driver); diff --git a/drivers/usb/typec/stusb160x.c b/drivers/usb/typec/stusb160x.c index 494b371151e0a1d627ce3e8f7f306124f61d76ed..3ab118df1bd4b4bda04e8f6d39e7bf0ef858d877 100644 --- a/drivers/usb/typec/stusb160x.c +++ b/drivers/usb/typec/stusb160x.c @@ -870,7 +870,7 @@ static struct i2c_driver stusb160x_driver = { .pm = &stusb160x_pm_ops, .of_match_table = stusb160x_of_match, }, - .probe_new = stusb160x_probe, + .probe = stusb160x_probe, .remove = stusb160x_remove, }; module_i2c_driver(stusb160x_driver); diff --git a/drivers/usb/typec/tcpm/Kconfig b/drivers/usb/typec/tcpm/Kconfig index e6b88ca4a4b94662e0957ba79e91ab3cd3ce7877..5d393f520fc2fa365340e1ef5e35c74fe1e8bd00 100644 --- a/drivers/usb/typec/tcpm/Kconfig +++ b/drivers/usb/typec/tcpm/Kconfig @@ -76,4 +76,15 @@ config TYPEC_WCOVE To compile this driver as module, choose M here: the module will be called typec_wcove.ko +config TYPEC_QCOM_PMIC + tristate "Qualcomm PMIC USB Type-C Port Controller Manager driver" + depends on ARCH_QCOM || COMPILE_TEST + help + A Type-C port and Power Delivery driver which aggregates two + discrete pieces of silicon in the PM8150b PMIC block: the + Type-C port controller and the Power Delivery PHY. + + This driver enables Type-C role switching, orientation, Alternate + mode and Power Delivery support both for VBUS and VCONN. + endif # TYPEC_TCPM diff --git a/drivers/usb/typec/tcpm/Makefile b/drivers/usb/typec/tcpm/Makefile index 08e57bb499cbc98c92278843e24b7bec6e6c6dfc..7a8cad0c0bdb486f77fcfc2c2d930c11c84800df 100644 --- a/drivers/usb/typec/tcpm/Makefile +++ b/drivers/usb/typec/tcpm/Makefile @@ -9,3 +9,4 @@ obj-$(CONFIG_TYPEC_MT6360) += tcpci_mt6360.o obj-$(CONFIG_TYPEC_TCPCI_MT6370) += tcpci_mt6370.o obj-$(CONFIG_TYPEC_TCPCI_MAXIM) += tcpci_maxim.o tcpci_maxim-y += tcpci_maxim_core.o maxim_contaminant.o +obj-$(CONFIG_TYPEC_QCOM_PMIC) += qcom/ diff --git a/drivers/usb/typec/tcpm/fusb302.c b/drivers/usb/typec/tcpm/fusb302.c index 62ba53357612453a39ad47302e29f07ed8f9a092..7fc1ffa14f76eb3504ef93de6fa4c95e1c12e128 100644 --- a/drivers/usb/typec/tcpm/fusb302.c +++ b/drivers/usb/typec/tcpm/fusb302.c @@ -1836,7 +1836,7 @@ static struct i2c_driver fusb302_driver = { .pm = &fusb302_pm_ops, .of_match_table = of_match_ptr(fusb302_dt_match), }, - .probe_new = fusb302_probe, + .probe = fusb302_probe, .remove = fusb302_remove, .id_table = fusb302_i2c_device_id, }; diff --git a/drivers/usb/typec/tcpm/qcom/Makefile b/drivers/usb/typec/tcpm/qcom/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..dc1e8832e197a68b4592163ecd4cc1877bb43d1c --- /dev/null +++ b/drivers/usb/typec/tcpm/qcom/Makefile @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0 +# +obj-$(CONFIG_TYPEC_QCOM_PMIC) += qcom_pmic_tcpm.o +qcom_pmic_tcpm-y += qcom_pmic_typec.o \ + qcom_pmic_typec_port.o \ + qcom_pmic_typec_pdphy.o diff --git a/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec.c b/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec.c new file mode 100644 index 0000000000000000000000000000000000000000..a905160dd860cc6f044e3f30ca2cd847dd59b676 --- /dev/null +++ b/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec.c @@ -0,0 +1,344 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2023, Linaro Ltd. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "qcom_pmic_typec_pdphy.h" +#include "qcom_pmic_typec_port.h" + +struct pmic_typec_resources { + struct pmic_typec_pdphy_resources *pdphy_res; + struct pmic_typec_port_resources *port_res; +}; + +struct pmic_typec { + struct device *dev; + struct tcpm_port *tcpm_port; + struct tcpc_dev tcpc; + struct pmic_typec_pdphy *pmic_typec_pdphy; + struct pmic_typec_port *pmic_typec_port; + bool vbus_enabled; + struct mutex lock; /* VBUS state serialization */ +}; + +#define tcpc_to_tcpm(_tcpc_) container_of(_tcpc_, struct pmic_typec, tcpc) + +static int qcom_pmic_typec_get_vbus(struct tcpc_dev *tcpc) +{ + struct pmic_typec *tcpm = tcpc_to_tcpm(tcpc); + int ret; + + mutex_lock(&tcpm->lock); + ret = tcpm->vbus_enabled || qcom_pmic_typec_port_get_vbus(tcpm->pmic_typec_port); + mutex_unlock(&tcpm->lock); + + return ret; +} + +static int qcom_pmic_typec_set_vbus(struct tcpc_dev *tcpc, bool on, bool sink) +{ + struct pmic_typec *tcpm = tcpc_to_tcpm(tcpc); + int ret = 0; + + mutex_lock(&tcpm->lock); + if (tcpm->vbus_enabled == on) + goto done; + + ret = qcom_pmic_typec_port_set_vbus(tcpm->pmic_typec_port, on); + if (ret) + goto done; + + tcpm->vbus_enabled = on; + tcpm_vbus_change(tcpm->tcpm_port); + +done: + dev_dbg(tcpm->dev, "set_vbus set: %d result %d\n", on, ret); + mutex_unlock(&tcpm->lock); + + return ret; +} + +static int qcom_pmic_typec_set_vconn(struct tcpc_dev *tcpc, bool on) +{ + struct pmic_typec *tcpm = tcpc_to_tcpm(tcpc); + + return qcom_pmic_typec_port_set_vconn(tcpm->pmic_typec_port, on); +} + +static int qcom_pmic_typec_get_cc(struct tcpc_dev *tcpc, + enum typec_cc_status *cc1, + enum typec_cc_status *cc2) +{ + struct pmic_typec *tcpm = tcpc_to_tcpm(tcpc); + + return qcom_pmic_typec_port_get_cc(tcpm->pmic_typec_port, cc1, cc2); +} + +static int qcom_pmic_typec_set_cc(struct tcpc_dev *tcpc, + enum typec_cc_status cc) +{ + struct pmic_typec *tcpm = tcpc_to_tcpm(tcpc); + + return qcom_pmic_typec_port_set_cc(tcpm->pmic_typec_port, cc); +} + +static int qcom_pmic_typec_set_polarity(struct tcpc_dev *tcpc, + enum typec_cc_polarity pol) +{ + /* Polarity is set separately by phy-qcom-qmp.c */ + return 0; +} + +static int qcom_pmic_typec_start_toggling(struct tcpc_dev *tcpc, + enum typec_port_type port_type, + enum typec_cc_status cc) +{ + struct pmic_typec *tcpm = tcpc_to_tcpm(tcpc); + + return qcom_pmic_typec_port_start_toggling(tcpm->pmic_typec_port, + port_type, cc); +} + +static int qcom_pmic_typec_set_roles(struct tcpc_dev *tcpc, bool attached, + enum typec_role power_role, + enum typec_data_role data_role) +{ + struct pmic_typec *tcpm = tcpc_to_tcpm(tcpc); + + return qcom_pmic_typec_pdphy_set_roles(tcpm->pmic_typec_pdphy, + data_role, power_role); +} + +static int qcom_pmic_typec_set_pd_rx(struct tcpc_dev *tcpc, bool on) +{ + struct pmic_typec *tcpm = tcpc_to_tcpm(tcpc); + + return qcom_pmic_typec_pdphy_set_pd_rx(tcpm->pmic_typec_pdphy, on); +} + +static int qcom_pmic_typec_pd_transmit(struct tcpc_dev *tcpc, + enum tcpm_transmit_type type, + const struct pd_message *msg, + unsigned int negotiated_rev) +{ + struct pmic_typec *tcpm = tcpc_to_tcpm(tcpc); + + return qcom_pmic_typec_pdphy_pd_transmit(tcpm->pmic_typec_pdphy, type, + msg, negotiated_rev); +} + +static int qcom_pmic_typec_init(struct tcpc_dev *tcpc) +{ + return 0; +} + +static int qcom_pmic_typec_probe(struct platform_device *pdev) +{ + struct pmic_typec *tcpm; + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + const struct pmic_typec_resources *res; + struct regmap *regmap; + u32 base[2]; + int ret; + + res = of_device_get_match_data(dev); + if (!res) + return -ENODEV; + + tcpm = devm_kzalloc(dev, sizeof(*tcpm), GFP_KERNEL); + if (!tcpm) + return -ENOMEM; + + tcpm->dev = dev; + tcpm->tcpc.init = qcom_pmic_typec_init; + tcpm->tcpc.get_vbus = qcom_pmic_typec_get_vbus; + tcpm->tcpc.set_vbus = qcom_pmic_typec_set_vbus; + tcpm->tcpc.set_cc = qcom_pmic_typec_set_cc; + tcpm->tcpc.get_cc = qcom_pmic_typec_get_cc; + tcpm->tcpc.set_polarity = qcom_pmic_typec_set_polarity; + tcpm->tcpc.set_vconn = qcom_pmic_typec_set_vconn; + tcpm->tcpc.start_toggling = qcom_pmic_typec_start_toggling; + tcpm->tcpc.set_pd_rx = qcom_pmic_typec_set_pd_rx; + tcpm->tcpc.set_roles = qcom_pmic_typec_set_roles; + tcpm->tcpc.pd_transmit = qcom_pmic_typec_pd_transmit; + + regmap = dev_get_regmap(dev->parent, NULL); + if (!regmap) { + dev_err(dev, "Failed to get regmap\n"); + return -ENODEV; + } + + ret = of_property_read_u32_array(np, "reg", base, 2); + if (ret) + return ret; + + tcpm->pmic_typec_port = qcom_pmic_typec_port_alloc(dev); + if (IS_ERR(tcpm->pmic_typec_port)) + return PTR_ERR(tcpm->pmic_typec_port); + + tcpm->pmic_typec_pdphy = qcom_pmic_typec_pdphy_alloc(dev); + if (IS_ERR(tcpm->pmic_typec_pdphy)) + return PTR_ERR(tcpm->pmic_typec_pdphy); + + ret = qcom_pmic_typec_port_probe(pdev, tcpm->pmic_typec_port, + res->port_res, regmap, base[0]); + if (ret) + return ret; + + ret = qcom_pmic_typec_pdphy_probe(pdev, tcpm->pmic_typec_pdphy, + res->pdphy_res, regmap, base[1]); + if (ret) + return ret; + + mutex_init(&tcpm->lock); + platform_set_drvdata(pdev, tcpm); + + tcpm->tcpc.fwnode = device_get_named_child_node(tcpm->dev, "connector"); + if (IS_ERR(tcpm->tcpc.fwnode)) + return PTR_ERR(tcpm->tcpc.fwnode); + + tcpm->tcpm_port = tcpm_register_port(tcpm->dev, &tcpm->tcpc); + if (IS_ERR(tcpm->tcpm_port)) { + ret = PTR_ERR(tcpm->tcpm_port); + goto fwnode_remove; + } + + ret = qcom_pmic_typec_port_start(tcpm->pmic_typec_port, + tcpm->tcpm_port); + if (ret) + goto fwnode_remove; + + ret = qcom_pmic_typec_pdphy_start(tcpm->pmic_typec_pdphy, + tcpm->tcpm_port); + if (ret) + goto fwnode_remove; + + return 0; + +fwnode_remove: + fwnode_remove_software_node(tcpm->tcpc.fwnode); + + return ret; +} + +static void qcom_pmic_typec_remove(struct platform_device *pdev) +{ + struct pmic_typec *tcpm = platform_get_drvdata(pdev); + + qcom_pmic_typec_pdphy_stop(tcpm->pmic_typec_pdphy); + qcom_pmic_typec_port_stop(tcpm->pmic_typec_port); + tcpm_unregister_port(tcpm->tcpm_port); + fwnode_remove_software_node(tcpm->tcpc.fwnode); +} + +static struct pmic_typec_pdphy_resources pm8150b_pdphy_res = { + .irq_params = { + { + .virq = PMIC_PDPHY_SIG_TX_IRQ, + .irq_name = "sig-tx", + }, + { + .virq = PMIC_PDPHY_SIG_RX_IRQ, + .irq_name = "sig-rx", + }, + { + .virq = PMIC_PDPHY_MSG_TX_IRQ, + .irq_name = "msg-tx", + }, + { + .virq = PMIC_PDPHY_MSG_RX_IRQ, + .irq_name = "msg-rx", + }, + { + .virq = PMIC_PDPHY_MSG_TX_FAIL_IRQ, + .irq_name = "msg-tx-failed", + }, + { + .virq = PMIC_PDPHY_MSG_TX_DISCARD_IRQ, + .irq_name = "msg-tx-discarded", + }, + { + .virq = PMIC_PDPHY_MSG_RX_DISCARD_IRQ, + .irq_name = "msg-rx-discarded", + }, + }, + .nr_irqs = 7, +}; + +static struct pmic_typec_port_resources pm8150b_port_res = { + .irq_params = { + { + .irq_name = "vpd-detect", + .virq = PMIC_TYPEC_VPD_IRQ, + }, + + { + .irq_name = "cc-state-change", + .virq = PMIC_TYPEC_CC_STATE_IRQ, + }, + { + .irq_name = "vconn-oc", + .virq = PMIC_TYPEC_VCONN_OC_IRQ, + }, + + { + .irq_name = "vbus-change", + .virq = PMIC_TYPEC_VBUS_IRQ, + }, + + { + .irq_name = "attach-detach", + .virq = PMIC_TYPEC_ATTACH_DETACH_IRQ, + }, + { + .irq_name = "legacy-cable-detect", + .virq = PMIC_TYPEC_LEGACY_CABLE_IRQ, + }, + + { + .irq_name = "try-snk-src-detect", + .virq = PMIC_TYPEC_TRY_SNK_SRC_IRQ, + }, + }, + .nr_irqs = 7, +}; + +static struct pmic_typec_resources pm8150b_typec_res = { + .pdphy_res = &pm8150b_pdphy_res, + .port_res = &pm8150b_port_res, +}; + +static const struct of_device_id qcom_pmic_typec_table[] = { + { .compatible = "qcom,pm8150b-typec", .data = &pm8150b_typec_res }, + { } +}; +MODULE_DEVICE_TABLE(of, qcom_pmic_typec_table); + +static struct platform_driver qcom_pmic_typec_driver = { + .driver = { + .name = "qcom,pmic-typec", + .of_match_table = qcom_pmic_typec_table, + }, + .probe = qcom_pmic_typec_probe, + .remove_new = qcom_pmic_typec_remove, +}; + +module_platform_driver(qcom_pmic_typec_driver); + +MODULE_DESCRIPTION("QCOM PMIC USB Type-C Port Manager Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_pdphy.c b/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_pdphy.c new file mode 100644 index 0000000000000000000000000000000000000000..4e1b846627d20e900e1b1a38d6e2a899ef9e47a6 --- /dev/null +++ b/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_pdphy.c @@ -0,0 +1,528 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2023, Linaro Ltd. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "qcom_pmic_typec_pdphy.h" + +struct pmic_typec_pdphy_irq_data { + int virq; + int irq; + struct pmic_typec_pdphy *pmic_typec_pdphy; +}; + +struct pmic_typec_pdphy { + struct device *dev; + struct tcpm_port *tcpm_port; + struct regmap *regmap; + u32 base; + + unsigned int nr_irqs; + struct pmic_typec_pdphy_irq_data *irq_data; + + struct work_struct reset_work; + struct work_struct receive_work; + struct regulator *vdd_pdphy; + spinlock_t lock; /* Register atomicity */ +}; + +static void qcom_pmic_typec_pdphy_reset_on(struct pmic_typec_pdphy *pmic_typec_pdphy) +{ + struct device *dev = pmic_typec_pdphy->dev; + int ret; + + /* Terminate TX */ + ret = regmap_write(pmic_typec_pdphy->regmap, + pmic_typec_pdphy->base + USB_PDPHY_TX_CONTROL_REG, 0); + if (ret) + goto err; + + ret = regmap_write(pmic_typec_pdphy->regmap, + pmic_typec_pdphy->base + USB_PDPHY_FRAME_FILTER_REG, 0); + if (ret) + goto err; + + return; +err: + dev_err(dev, "pd_reset_on error\n"); +} + +static void qcom_pmic_typec_pdphy_reset_off(struct pmic_typec_pdphy *pmic_typec_pdphy) +{ + struct device *dev = pmic_typec_pdphy->dev; + int ret; + + ret = regmap_write(pmic_typec_pdphy->regmap, + pmic_typec_pdphy->base + USB_PDPHY_FRAME_FILTER_REG, + FRAME_FILTER_EN_SOP | FRAME_FILTER_EN_HARD_RESET); + if (ret) + dev_err(dev, "pd_reset_off error\n"); +} + +static void qcom_pmic_typec_pdphy_sig_reset_work(struct work_struct *work) +{ + struct pmic_typec_pdphy *pmic_typec_pdphy = container_of(work, struct pmic_typec_pdphy, + reset_work); + unsigned long flags; + + spin_lock_irqsave(&pmic_typec_pdphy->lock, flags); + + qcom_pmic_typec_pdphy_reset_on(pmic_typec_pdphy); + qcom_pmic_typec_pdphy_reset_off(pmic_typec_pdphy); + + spin_unlock_irqrestore(&pmic_typec_pdphy->lock, flags); + + tcpm_pd_hard_reset(pmic_typec_pdphy->tcpm_port); +} + +static int +qcom_pmic_typec_pdphy_clear_tx_control_reg(struct pmic_typec_pdphy *pmic_typec_pdphy) +{ + struct device *dev = pmic_typec_pdphy->dev; + unsigned int val; + int ret; + + /* Clear TX control register */ + ret = regmap_write(pmic_typec_pdphy->regmap, + pmic_typec_pdphy->base + USB_PDPHY_TX_CONTROL_REG, 0); + if (ret) + goto done; + + /* Perform readback to ensure sufficient delay for command to latch */ + ret = regmap_read(pmic_typec_pdphy->regmap, + pmic_typec_pdphy->base + USB_PDPHY_TX_CONTROL_REG, &val); + +done: + if (ret) + dev_err(dev, "pd_clear_tx_control_reg: clear tx flag\n"); + + return ret; +} + +static int +qcom_pmic_typec_pdphy_pd_transmit_signal(struct pmic_typec_pdphy *pmic_typec_pdphy, + enum tcpm_transmit_type type, + unsigned int negotiated_rev) +{ + struct device *dev = pmic_typec_pdphy->dev; + unsigned int val; + unsigned long flags; + int ret; + + spin_lock_irqsave(&pmic_typec_pdphy->lock, flags); + + /* Clear TX control register */ + ret = qcom_pmic_typec_pdphy_clear_tx_control_reg(pmic_typec_pdphy); + if (ret) + goto done; + + val = TX_CONTROL_SEND_SIGNAL; + if (negotiated_rev == PD_REV30) + val |= TX_CONTROL_RETRY_COUNT(2); + else + val |= TX_CONTROL_RETRY_COUNT(3); + + if (type == TCPC_TX_CABLE_RESET || type == TCPC_TX_HARD_RESET) + val |= TX_CONTROL_FRAME_TYPE(1); + + ret = regmap_write(pmic_typec_pdphy->regmap, + pmic_typec_pdphy->base + USB_PDPHY_TX_CONTROL_REG, val); + +done: + spin_unlock_irqrestore(&pmic_typec_pdphy->lock, flags); + + dev_vdbg(dev, "pd_transmit_signal: type %d negotiate_rev %d send %d\n", + type, negotiated_rev, ret); + + return ret; +} + +static int +qcom_pmic_typec_pdphy_pd_transmit_payload(struct pmic_typec_pdphy *pmic_typec_pdphy, + enum tcpm_transmit_type type, + const struct pd_message *msg, + unsigned int negotiated_rev) +{ + struct device *dev = pmic_typec_pdphy->dev; + unsigned int val, hdr_len, txbuf_len, txsize_len; + unsigned long flags; + int ret; + + spin_lock_irqsave(&pmic_typec_pdphy->lock, flags); + + ret = regmap_read(pmic_typec_pdphy->regmap, + pmic_typec_pdphy->base + USB_PDPHY_RX_ACKNOWLEDGE_REG, + &val); + if (ret) + goto done; + + if (val) { + dev_err(dev, "pd_transmit_payload: RX message pending\n"); + ret = -EBUSY; + goto done; + } + + /* Clear TX control register */ + ret = qcom_pmic_typec_pdphy_clear_tx_control_reg(pmic_typec_pdphy); + if (ret) + goto done; + + hdr_len = sizeof(msg->header); + txbuf_len = pd_header_cnt_le(msg->header) * 4; + txsize_len = hdr_len + txbuf_len - 1; + + /* Write message header sizeof(u16) to USB_PDPHY_TX_BUFFER_HDR_REG */ + ret = regmap_bulk_write(pmic_typec_pdphy->regmap, + pmic_typec_pdphy->base + USB_PDPHY_TX_BUFFER_HDR_REG, + &msg->header, hdr_len); + if (ret) + goto done; + + /* Write payload to USB_PDPHY_TX_BUFFER_DATA_REG for txbuf_len */ + if (txbuf_len) { + ret = regmap_bulk_write(pmic_typec_pdphy->regmap, + pmic_typec_pdphy->base + USB_PDPHY_TX_BUFFER_DATA_REG, + &msg->payload, txbuf_len); + if (ret) + goto done; + } + + /* Write total length ((header + data) - 1) to USB_PDPHY_TX_SIZE_REG */ + ret = regmap_write(pmic_typec_pdphy->regmap, + pmic_typec_pdphy->base + USB_PDPHY_TX_SIZE_REG, + txsize_len); + if (ret) + goto done; + + /* Clear TX control register */ + ret = qcom_pmic_typec_pdphy_clear_tx_control_reg(pmic_typec_pdphy); + if (ret) + goto done; + + /* Initiate transmit with retry count as indicated by PD revision */ + val = TX_CONTROL_FRAME_TYPE(type) | TX_CONTROL_SEND_MSG; + if (pd_header_rev(msg->header) == PD_REV30) + val |= TX_CONTROL_RETRY_COUNT(2); + else + val |= TX_CONTROL_RETRY_COUNT(3); + + ret = regmap_write(pmic_typec_pdphy->regmap, + pmic_typec_pdphy->base + USB_PDPHY_TX_CONTROL_REG, val); + +done: + spin_unlock_irqrestore(&pmic_typec_pdphy->lock, flags); + + if (ret) { + dev_err(dev, "pd_transmit_payload: hdr %*ph data %*ph ret %d\n", + hdr_len, &msg->header, txbuf_len, &msg->payload, ret); + } + + return ret; +} + +int qcom_pmic_typec_pdphy_pd_transmit(struct pmic_typec_pdphy *pmic_typec_pdphy, + enum tcpm_transmit_type type, + const struct pd_message *msg, + unsigned int negotiated_rev) +{ + struct device *dev = pmic_typec_pdphy->dev; + int ret; + + if (msg) { + ret = qcom_pmic_typec_pdphy_pd_transmit_payload(pmic_typec_pdphy, + type, msg, + negotiated_rev); + } else { + ret = qcom_pmic_typec_pdphy_pd_transmit_signal(pmic_typec_pdphy, + type, + negotiated_rev); + } + + if (ret) + dev_dbg(dev, "pd_transmit: type %x result %d\n", type, ret); + + return ret; +} + +static void qcom_pmic_typec_pdphy_pd_receive(struct pmic_typec_pdphy *pmic_typec_pdphy) +{ + struct device *dev = pmic_typec_pdphy->dev; + struct pd_message msg; + unsigned int size, rx_status; + unsigned long flags; + int ret; + + spin_lock_irqsave(&pmic_typec_pdphy->lock, flags); + + ret = regmap_read(pmic_typec_pdphy->regmap, + pmic_typec_pdphy->base + USB_PDPHY_RX_SIZE_REG, &size); + if (ret) + goto done; + + /* Hardware requires +1 of the real read value to be passed */ + if (size < 1 || size > sizeof(msg.payload) + 1) { + dev_dbg(dev, "pd_receive: invalid size %d\n", size); + goto done; + } + + size += 1; + ret = regmap_read(pmic_typec_pdphy->regmap, + pmic_typec_pdphy->base + USB_PDPHY_RX_STATUS_REG, + &rx_status); + + if (ret) + goto done; + + ret = regmap_bulk_read(pmic_typec_pdphy->regmap, + pmic_typec_pdphy->base + USB_PDPHY_RX_BUFFER_REG, + (u8 *)&msg, size); + if (ret) + goto done; + + /* Return ownership of RX buffer to hardware */ + ret = regmap_write(pmic_typec_pdphy->regmap, + pmic_typec_pdphy->base + USB_PDPHY_RX_ACKNOWLEDGE_REG, 0); + +done: + spin_unlock_irqrestore(&pmic_typec_pdphy->lock, flags); + + if (!ret) { + dev_vdbg(dev, "pd_receive: handing %d bytes to tcpm\n", size); + tcpm_pd_receive(pmic_typec_pdphy->tcpm_port, &msg); + } +} + +static irqreturn_t qcom_pmic_typec_pdphy_isr(int irq, void *dev_id) +{ + struct pmic_typec_pdphy_irq_data *irq_data = dev_id; + struct pmic_typec_pdphy *pmic_typec_pdphy = irq_data->pmic_typec_pdphy; + struct device *dev = pmic_typec_pdphy->dev; + + switch (irq_data->virq) { + case PMIC_PDPHY_SIG_TX_IRQ: + dev_err(dev, "isr: tx_sig\n"); + break; + case PMIC_PDPHY_SIG_RX_IRQ: + schedule_work(&pmic_typec_pdphy->reset_work); + break; + case PMIC_PDPHY_MSG_TX_IRQ: + tcpm_pd_transmit_complete(pmic_typec_pdphy->tcpm_port, + TCPC_TX_SUCCESS); + break; + case PMIC_PDPHY_MSG_RX_IRQ: + qcom_pmic_typec_pdphy_pd_receive(pmic_typec_pdphy); + break; + case PMIC_PDPHY_MSG_TX_FAIL_IRQ: + tcpm_pd_transmit_complete(pmic_typec_pdphy->tcpm_port, + TCPC_TX_FAILED); + break; + case PMIC_PDPHY_MSG_TX_DISCARD_IRQ: + tcpm_pd_transmit_complete(pmic_typec_pdphy->tcpm_port, + TCPC_TX_DISCARDED); + break; + } + + return IRQ_HANDLED; +} + +int qcom_pmic_typec_pdphy_set_pd_rx(struct pmic_typec_pdphy *pmic_typec_pdphy, bool on) +{ + unsigned long flags; + int ret; + + spin_lock_irqsave(&pmic_typec_pdphy->lock, flags); + + ret = regmap_write(pmic_typec_pdphy->regmap, + pmic_typec_pdphy->base + USB_PDPHY_RX_ACKNOWLEDGE_REG, !on); + + spin_unlock_irqrestore(&pmic_typec_pdphy->lock, flags); + + dev_dbg(pmic_typec_pdphy->dev, "set_pd_rx: %s\n", on ? "on" : "off"); + + return ret; +} + +int qcom_pmic_typec_pdphy_set_roles(struct pmic_typec_pdphy *pmic_typec_pdphy, + bool data_role_host, bool power_role_src) +{ + struct device *dev = pmic_typec_pdphy->dev; + unsigned long flags; + int ret; + + spin_lock_irqsave(&pmic_typec_pdphy->lock, flags); + + ret = regmap_update_bits(pmic_typec_pdphy->regmap, + pmic_typec_pdphy->base + USB_PDPHY_MSG_CONFIG_REG, + MSG_CONFIG_PORT_DATA_ROLE | + MSG_CONFIG_PORT_POWER_ROLE, + data_role_host << 3 | power_role_src << 2); + + spin_unlock_irqrestore(&pmic_typec_pdphy->lock, flags); + + dev_dbg(dev, "pdphy_set_roles: data_role_host=%d power_role_src=%d\n", + data_role_host, power_role_src); + + return ret; +} + +static int qcom_pmic_typec_pdphy_enable(struct pmic_typec_pdphy *pmic_typec_pdphy) +{ + struct device *dev = pmic_typec_pdphy->dev; + int ret; + + ret = regulator_enable(pmic_typec_pdphy->vdd_pdphy); + if (ret) + return ret; + + /* PD 2.0, DR=TYPEC_DEVICE, PR=TYPEC_SINK */ + ret = regmap_update_bits(pmic_typec_pdphy->regmap, + pmic_typec_pdphy->base + USB_PDPHY_MSG_CONFIG_REG, + MSG_CONFIG_SPEC_REV_MASK, PD_REV20); + if (ret) + goto done; + + ret = regmap_write(pmic_typec_pdphy->regmap, + pmic_typec_pdphy->base + USB_PDPHY_EN_CONTROL_REG, 0); + if (ret) + goto done; + + ret = regmap_write(pmic_typec_pdphy->regmap, + pmic_typec_pdphy->base + USB_PDPHY_EN_CONTROL_REG, + CONTROL_ENABLE); + if (ret) + goto done; + + qcom_pmic_typec_pdphy_reset_off(pmic_typec_pdphy); +done: + if (ret) { + regulator_disable(pmic_typec_pdphy->vdd_pdphy); + dev_err(dev, "pdphy_enable fail %d\n", ret); + } + + return ret; +} + +static int qcom_pmic_typec_pdphy_disable(struct pmic_typec_pdphy *pmic_typec_pdphy) +{ + int ret; + + qcom_pmic_typec_pdphy_reset_on(pmic_typec_pdphy); + + ret = regmap_write(pmic_typec_pdphy->regmap, + pmic_typec_pdphy->base + USB_PDPHY_EN_CONTROL_REG, 0); + + regulator_disable(pmic_typec_pdphy->vdd_pdphy); + + return ret; +} + +static int pmic_typec_pdphy_reset(struct pmic_typec_pdphy *pmic_typec_pdphy) +{ + int ret; + + ret = qcom_pmic_typec_pdphy_disable(pmic_typec_pdphy); + if (ret) + goto done; + + usleep_range(400, 500); + ret = qcom_pmic_typec_pdphy_enable(pmic_typec_pdphy); +done: + return ret; +} + +int qcom_pmic_typec_pdphy_start(struct pmic_typec_pdphy *pmic_typec_pdphy, + struct tcpm_port *tcpm_port) +{ + int i; + int ret; + + pmic_typec_pdphy->tcpm_port = tcpm_port; + + ret = pmic_typec_pdphy_reset(pmic_typec_pdphy); + if (ret) + return ret; + + for (i = 0; i < pmic_typec_pdphy->nr_irqs; i++) + enable_irq(pmic_typec_pdphy->irq_data[i].irq); + + return 0; +} + +void qcom_pmic_typec_pdphy_stop(struct pmic_typec_pdphy *pmic_typec_pdphy) +{ + int i; + + for (i = 0; i < pmic_typec_pdphy->nr_irqs; i++) + disable_irq(pmic_typec_pdphy->irq_data[i].irq); + + qcom_pmic_typec_pdphy_reset_on(pmic_typec_pdphy); +} + +struct pmic_typec_pdphy *qcom_pmic_typec_pdphy_alloc(struct device *dev) +{ + return devm_kzalloc(dev, sizeof(struct pmic_typec_pdphy), GFP_KERNEL); +} + +int qcom_pmic_typec_pdphy_probe(struct platform_device *pdev, + struct pmic_typec_pdphy *pmic_typec_pdphy, + struct pmic_typec_pdphy_resources *res, + struct regmap *regmap, + u32 base) +{ + struct device *dev = &pdev->dev; + struct pmic_typec_pdphy_irq_data *irq_data; + int i, ret, irq; + + if (!res->nr_irqs || res->nr_irqs > PMIC_PDPHY_MAX_IRQS) + return -EINVAL; + + irq_data = devm_kzalloc(dev, sizeof(*irq_data) * res->nr_irqs, + GFP_KERNEL); + if (!irq_data) + return -ENOMEM; + + pmic_typec_pdphy->vdd_pdphy = devm_regulator_get(dev, "vdd-pdphy"); + if (IS_ERR(pmic_typec_pdphy->vdd_pdphy)) + return PTR_ERR(pmic_typec_pdphy->vdd_pdphy); + + pmic_typec_pdphy->dev = dev; + pmic_typec_pdphy->base = base; + pmic_typec_pdphy->regmap = regmap; + pmic_typec_pdphy->nr_irqs = res->nr_irqs; + pmic_typec_pdphy->irq_data = irq_data; + spin_lock_init(&pmic_typec_pdphy->lock); + INIT_WORK(&pmic_typec_pdphy->reset_work, qcom_pmic_typec_pdphy_sig_reset_work); + + for (i = 0; i < res->nr_irqs; i++, irq_data++) { + irq = platform_get_irq_byname(pdev, res->irq_params[i].irq_name); + if (irq < 0) + return irq; + + irq_data->pmic_typec_pdphy = pmic_typec_pdphy; + irq_data->irq = irq; + irq_data->virq = res->irq_params[i].virq; + + ret = devm_request_threaded_irq(dev, irq, NULL, + qcom_pmic_typec_pdphy_isr, + IRQF_ONESHOT | IRQF_NO_AUTOEN, + res->irq_params[i].irq_name, + irq_data); + if (ret) + return ret; + } + + return 0; +} diff --git a/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_pdphy.h b/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_pdphy.h new file mode 100644 index 0000000000000000000000000000000000000000..e67954e31b149cd086c40cc44ca34ea51613bcc3 --- /dev/null +++ b/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_pdphy.h @@ -0,0 +1,119 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2023, Linaro Ltd. All rights reserved. + */ +#ifndef __QCOM_PMIC_PDPHY_H__ +#define __QCOM_PMIC_PDPHY_H__ + +#include +#include +#include + +#define USB_PDPHY_MAX_DATA_OBJ_LEN 28 +#define USB_PDPHY_MSG_HDR_LEN 2 + +/* PD PHY register offsets and bit fields */ +#define USB_PDPHY_MSG_CONFIG_REG 0x40 +#define MSG_CONFIG_PORT_DATA_ROLE BIT(3) +#define MSG_CONFIG_PORT_POWER_ROLE BIT(2) +#define MSG_CONFIG_SPEC_REV_MASK (BIT(1) | BIT(0)) + +#define USB_PDPHY_EN_CONTROL_REG 0x46 +#define CONTROL_ENABLE BIT(0) + +#define USB_PDPHY_RX_STATUS_REG 0x4A +#define RX_FRAME_TYPE (BIT(0) | BIT(1) | BIT(2)) + +#define USB_PDPHY_FRAME_FILTER_REG 0x4C +#define FRAME_FILTER_EN_HARD_RESET BIT(5) +#define FRAME_FILTER_EN_SOP BIT(0) + +#define USB_PDPHY_TX_SIZE_REG 0x42 +#define TX_SIZE_MASK 0xF + +#define USB_PDPHY_TX_CONTROL_REG 0x44 +#define TX_CONTROL_RETRY_COUNT(n) (((n) & 0x3) << 5) +#define TX_CONTROL_FRAME_TYPE(n) (((n) & 0x7) << 2) +#define TX_CONTROL_FRAME_TYPE_CABLE_RESET (0x1 << 2) +#define TX_CONTROL_SEND_SIGNAL BIT(1) +#define TX_CONTROL_SEND_MSG BIT(0) + +#define USB_PDPHY_RX_SIZE_REG 0x48 + +#define USB_PDPHY_RX_ACKNOWLEDGE_REG 0x4B +#define RX_BUFFER_TOKEN BIT(0) + +#define USB_PDPHY_BIST_MODE_REG 0x4E +#define BIST_MODE_MASK 0xF +#define BIST_ENABLE BIT(7) +#define PD_MSG_BIST 0x3 +#define PD_BIST_TEST_DATA_MODE 0x8 + +#define USB_PDPHY_TX_BUFFER_HDR_REG 0x60 +#define USB_PDPHY_TX_BUFFER_DATA_REG 0x62 + +#define USB_PDPHY_RX_BUFFER_REG 0x80 + +/* VDD regulator */ +#define VDD_PDPHY_VOL_MIN 2800000 /* uV */ +#define VDD_PDPHY_VOL_MAX 3300000 /* uV */ +#define VDD_PDPHY_HPM_LOAD 3000 /* uA */ + +/* Message Spec Rev field */ +#define PD_MSG_HDR_REV(hdr) (((hdr) >> 6) & 3) + +/* timers */ +#define RECEIVER_RESPONSE_TIME 15 /* tReceiverResponse */ +#define HARD_RESET_COMPLETE_TIME 5 /* tHardResetComplete */ + +/* Interrupt numbers */ +#define PMIC_PDPHY_SIG_TX_IRQ 0x0 +#define PMIC_PDPHY_SIG_RX_IRQ 0x1 +#define PMIC_PDPHY_MSG_TX_IRQ 0x2 +#define PMIC_PDPHY_MSG_RX_IRQ 0x3 +#define PMIC_PDPHY_MSG_TX_FAIL_IRQ 0x4 +#define PMIC_PDPHY_MSG_TX_DISCARD_IRQ 0x5 +#define PMIC_PDPHY_MSG_RX_DISCARD_IRQ 0x6 +#define PMIC_PDPHY_FR_SWAP_IRQ 0x7 + +/* Resources */ +#define PMIC_PDPHY_MAX_IRQS 0x08 + +struct pmic_typec_pdphy_irq_params { + int virq; + char *irq_name; +}; + +struct pmic_typec_pdphy_resources { + unsigned int nr_irqs; + struct pmic_typec_pdphy_irq_params irq_params[PMIC_PDPHY_MAX_IRQS]; +}; + +/* API */ +struct pmic_typec_pdphy; + +struct pmic_typec_pdphy *qcom_pmic_typec_pdphy_alloc(struct device *dev); + +int qcom_pmic_typec_pdphy_probe(struct platform_device *pdev, + struct pmic_typec_pdphy *pmic_typec_pdphy, + struct pmic_typec_pdphy_resources *res, + struct regmap *regmap, + u32 base); + +int qcom_pmic_typec_pdphy_start(struct pmic_typec_pdphy *pmic_typec_pdphy, + struct tcpm_port *tcpm_port); + +void qcom_pmic_typec_pdphy_stop(struct pmic_typec_pdphy *pmic_typec_pdphy); + +int qcom_pmic_typec_pdphy_set_roles(struct pmic_typec_pdphy *pmic_typec_pdphy, + bool power_role_src, bool data_role_host); + +int qcom_pmic_typec_pdphy_set_pd_rx(struct pmic_typec_pdphy *pmic_typec_pdphy, bool on); + +int qcom_pmic_typec_pdphy_pd_transmit(struct pmic_typec_pdphy *pmic_typec_pdphy, + enum tcpm_transmit_type type, + const struct pd_message *msg, + unsigned int negotiated_rev); + +#endif /* __QCOM_PMIC_TYPEC_PDPHY_H__ */ diff --git a/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_port.c b/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_port.c new file mode 100644 index 0000000000000000000000000000000000000000..94285f64b67d7237a7c74cf90cc8235c22ddc5f0 --- /dev/null +++ b/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_port.c @@ -0,0 +1,556 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2023, Linaro Ltd. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "qcom_pmic_typec_port.h" + +struct pmic_typec_port_irq_data { + int virq; + int irq; + struct pmic_typec_port *pmic_typec_port; +}; + +struct pmic_typec_port { + struct device *dev; + struct tcpm_port *tcpm_port; + struct regmap *regmap; + u32 base; + unsigned int nr_irqs; + struct pmic_typec_port_irq_data *irq_data; + + struct regulator *vdd_vbus; + + int cc; + bool debouncing_cc; + struct delayed_work cc_debounce_dwork; + + spinlock_t lock; /* Register atomicity */ +}; + +static const char * const typec_cc_status_name[] = { + [TYPEC_CC_OPEN] = "Open", + [TYPEC_CC_RA] = "Ra", + [TYPEC_CC_RD] = "Rd", + [TYPEC_CC_RP_DEF] = "Rp-def", + [TYPEC_CC_RP_1_5] = "Rp-1.5", + [TYPEC_CC_RP_3_0] = "Rp-3.0", +}; + +static const char *rp_unknown = "unknown"; + +static const char *cc_to_name(enum typec_cc_status cc) +{ + if (cc > TYPEC_CC_RP_3_0) + return rp_unknown; + + return typec_cc_status_name[cc]; +} + +static const char * const rp_sel_name[] = { + [TYPEC_SRC_RP_SEL_80UA] = "Rp-def-80uA", + [TYPEC_SRC_RP_SEL_180UA] = "Rp-1.5-180uA", + [TYPEC_SRC_RP_SEL_330UA] = "Rp-3.0-330uA", +}; + +static const char *rp_sel_to_name(int rp_sel) +{ + if (rp_sel > TYPEC_SRC_RP_SEL_330UA) + return rp_unknown; + + return rp_sel_name[rp_sel]; +} + +#define misc_to_cc(msic) !!(misc & CC_ORIENTATION) ? "cc1" : "cc2" +#define misc_to_vconn(msic) !!(misc & CC_ORIENTATION) ? "cc2" : "cc1" + +static void qcom_pmic_typec_port_cc_debounce(struct work_struct *work) +{ + struct pmic_typec_port *pmic_typec_port = + container_of(work, struct pmic_typec_port, cc_debounce_dwork.work); + unsigned long flags; + + spin_lock_irqsave(&pmic_typec_port->lock, flags); + pmic_typec_port->debouncing_cc = false; + spin_unlock_irqrestore(&pmic_typec_port->lock, flags); + + dev_dbg(pmic_typec_port->dev, "Debounce cc complete\n"); +} + +static irqreturn_t pmic_typec_port_isr(int irq, void *dev_id) +{ + struct pmic_typec_port_irq_data *irq_data = dev_id; + struct pmic_typec_port *pmic_typec_port = irq_data->pmic_typec_port; + u32 misc_stat; + bool vbus_change = false; + bool cc_change = false; + unsigned long flags; + int ret; + + spin_lock_irqsave(&pmic_typec_port->lock, flags); + + ret = regmap_read(pmic_typec_port->regmap, + pmic_typec_port->base + TYPEC_MISC_STATUS_REG, + &misc_stat); + if (ret) + goto done; + + switch (irq_data->virq) { + case PMIC_TYPEC_VBUS_IRQ: + vbus_change = true; + break; + case PMIC_TYPEC_CC_STATE_IRQ: + case PMIC_TYPEC_ATTACH_DETACH_IRQ: + if (!pmic_typec_port->debouncing_cc) + cc_change = true; + break; + } + +done: + spin_unlock_irqrestore(&pmic_typec_port->lock, flags); + + if (vbus_change) + tcpm_vbus_change(pmic_typec_port->tcpm_port); + + if (cc_change) + tcpm_cc_change(pmic_typec_port->tcpm_port); + + return IRQ_HANDLED; +} + +int qcom_pmic_typec_port_get_vbus(struct pmic_typec_port *pmic_typec_port) +{ + struct device *dev = pmic_typec_port->dev; + unsigned int misc; + int ret; + + ret = regmap_read(pmic_typec_port->regmap, + pmic_typec_port->base + TYPEC_MISC_STATUS_REG, + &misc); + if (ret) + misc = 0; + + dev_dbg(dev, "get_vbus: 0x%08x detect %d\n", misc, !!(misc & TYPEC_VBUS_DETECT)); + + return !!(misc & TYPEC_VBUS_DETECT); +} + +int qcom_pmic_typec_port_set_vbus(struct pmic_typec_port *pmic_typec_port, bool on) +{ + u32 sm_stat; + u32 val; + int ret; + + if (on) { + ret = regulator_enable(pmic_typec_port->vdd_vbus); + if (ret) + return ret; + + val = TYPEC_SM_VBUS_VSAFE5V; + } else { + ret = regulator_disable(pmic_typec_port->vdd_vbus); + if (ret) + return ret; + + val = TYPEC_SM_VBUS_VSAFE0V; + } + + /* Poll waiting for transition to required vSafe5V or vSafe0V */ + ret = regmap_read_poll_timeout(pmic_typec_port->regmap, + pmic_typec_port->base + TYPEC_SM_STATUS_REG, + sm_stat, sm_stat & val, + 100, 250000); + if (ret) + dev_warn(pmic_typec_port->dev, "vbus vsafe%dv fail\n", on ? 5 : 0); + + return 0; +} + +int qcom_pmic_typec_port_get_cc(struct pmic_typec_port *pmic_typec_port, + enum typec_cc_status *cc1, + enum typec_cc_status *cc2) +{ + struct device *dev = pmic_typec_port->dev; + unsigned int misc, val; + bool attached; + int ret = 0; + + ret = regmap_read(pmic_typec_port->regmap, + pmic_typec_port->base + TYPEC_MISC_STATUS_REG, &misc); + if (ret) + goto done; + + attached = !!(misc & CC_ATTACHED); + + if (pmic_typec_port->debouncing_cc) { + ret = -EBUSY; + goto done; + } + + *cc1 = TYPEC_CC_OPEN; + *cc2 = TYPEC_CC_OPEN; + + if (!attached) + goto done; + + if (misc & SNK_SRC_MODE) { + ret = regmap_read(pmic_typec_port->regmap, + pmic_typec_port->base + TYPEC_SRC_STATUS_REG, + &val); + if (ret) + goto done; + switch (val & DETECTED_SRC_TYPE_MASK) { + case SRC_RD_OPEN: + val = TYPEC_CC_RD; + break; + case SRC_RD_RA_VCONN: + val = TYPEC_CC_RD; + *cc1 = TYPEC_CC_RA; + *cc2 = TYPEC_CC_RA; + break; + default: + dev_warn(dev, "unexpected src status %.2x\n", val); + val = TYPEC_CC_RD; + break; + } + } else { + ret = regmap_read(pmic_typec_port->regmap, + pmic_typec_port->base + TYPEC_SNK_STATUS_REG, + &val); + if (ret) + goto done; + switch (val & DETECTED_SNK_TYPE_MASK) { + case SNK_RP_STD: + val = TYPEC_CC_RP_DEF; + break; + case SNK_RP_1P5: + val = TYPEC_CC_RP_1_5; + break; + case SNK_RP_3P0: + val = TYPEC_CC_RP_3_0; + break; + default: + dev_warn(dev, "unexpected snk status %.2x\n", val); + val = TYPEC_CC_RP_DEF; + break; + } + val = TYPEC_CC_RP_DEF; + } + + if (misc & CC_ORIENTATION) + *cc2 = val; + else + *cc1 = val; + +done: + dev_dbg(dev, "get_cc: misc 0x%08x cc1 0x%08x %s cc2 0x%08x %s attached %d cc=%s\n", + misc, *cc1, cc_to_name(*cc1), *cc2, cc_to_name(*cc2), attached, + misc_to_cc(misc)); + + return ret; +} + +static void qcom_pmic_set_cc_debounce(struct pmic_typec_port *pmic_typec_port) +{ + pmic_typec_port->debouncing_cc = true; + schedule_delayed_work(&pmic_typec_port->cc_debounce_dwork, + msecs_to_jiffies(2)); +} + +int qcom_pmic_typec_port_set_cc(struct pmic_typec_port *pmic_typec_port, + enum typec_cc_status cc) +{ + struct device *dev = pmic_typec_port->dev; + unsigned int mode, currsrc; + unsigned int misc; + unsigned long flags; + int ret; + + spin_lock_irqsave(&pmic_typec_port->lock, flags); + + ret = regmap_read(pmic_typec_port->regmap, + pmic_typec_port->base + TYPEC_MISC_STATUS_REG, + &misc); + if (ret) + goto done; + + mode = EN_SRC_ONLY; + + switch (cc) { + case TYPEC_CC_OPEN: + currsrc = TYPEC_SRC_RP_SEL_80UA; + break; + case TYPEC_CC_RP_DEF: + currsrc = TYPEC_SRC_RP_SEL_80UA; + break; + case TYPEC_CC_RP_1_5: + currsrc = TYPEC_SRC_RP_SEL_180UA; + break; + case TYPEC_CC_RP_3_0: + currsrc = TYPEC_SRC_RP_SEL_330UA; + break; + case TYPEC_CC_RD: + currsrc = TYPEC_SRC_RP_SEL_80UA; + mode = EN_SNK_ONLY; + break; + default: + dev_warn(dev, "unexpected set_cc %d\n", cc); + ret = -EINVAL; + goto done; + } + + if (mode == EN_SRC_ONLY) { + ret = regmap_write(pmic_typec_port->regmap, + pmic_typec_port->base + TYPEC_CURRSRC_CFG_REG, + currsrc); + if (ret) + goto done; + } + + pmic_typec_port->cc = cc; + qcom_pmic_set_cc_debounce(pmic_typec_port); + ret = 0; + +done: + spin_unlock_irqrestore(&pmic_typec_port->lock, flags); + + dev_dbg(dev, "set_cc: currsrc=%x %s mode %s debounce %d attached %d cc=%s\n", + currsrc, rp_sel_to_name(currsrc), + mode == EN_SRC_ONLY ? "EN_SRC_ONLY" : "EN_SNK_ONLY", + pmic_typec_port->debouncing_cc, !!(misc & CC_ATTACHED), + misc_to_cc(misc)); + + return ret; +} + +int qcom_pmic_typec_port_set_vconn(struct pmic_typec_port *pmic_typec_port, bool on) +{ + struct device *dev = pmic_typec_port->dev; + unsigned int orientation, misc, mask, value; + unsigned long flags; + int ret; + + spin_lock_irqsave(&pmic_typec_port->lock, flags); + + ret = regmap_read(pmic_typec_port->regmap, + pmic_typec_port->base + TYPEC_MISC_STATUS_REG, &misc); + if (ret) + goto done; + + /* Set VCONN on the inversion of the active CC channel */ + orientation = (misc & CC_ORIENTATION) ? 0 : VCONN_EN_ORIENTATION; + if (on) { + mask = VCONN_EN_ORIENTATION | VCONN_EN_VALUE; + value = orientation | VCONN_EN_VALUE | VCONN_EN_SRC; + } else { + mask = VCONN_EN_VALUE; + value = 0; + } + + ret = regmap_update_bits(pmic_typec_port->regmap, + pmic_typec_port->base + TYPEC_VCONN_CONTROL_REG, + mask, value); +done: + spin_unlock_irqrestore(&pmic_typec_port->lock, flags); + + dev_dbg(dev, "set_vconn: orientation %d control 0x%08x state %s cc %s vconn %s\n", + orientation, value, on ? "on" : "off", misc_to_vconn(misc), misc_to_cc(misc)); + + return ret; +} + +int qcom_pmic_typec_port_start_toggling(struct pmic_typec_port *pmic_typec_port, + enum typec_port_type port_type, + enum typec_cc_status cc) +{ + struct device *dev = pmic_typec_port->dev; + unsigned int misc; + u8 mode = 0; + unsigned long flags; + int ret; + + switch (port_type) { + case TYPEC_PORT_SRC: + mode = EN_SRC_ONLY; + break; + case TYPEC_PORT_SNK: + mode = EN_SNK_ONLY; + break; + case TYPEC_PORT_DRP: + mode = EN_TRY_SNK; + break; + } + + spin_lock_irqsave(&pmic_typec_port->lock, flags); + + ret = regmap_read(pmic_typec_port->regmap, + pmic_typec_port->base + TYPEC_MISC_STATUS_REG, &misc); + if (ret) + goto done; + + dev_dbg(dev, "start_toggling: misc 0x%08x attached %d port_type %d current cc %d new %d\n", + misc, !!(misc & CC_ATTACHED), port_type, pmic_typec_port->cc, cc); + + qcom_pmic_set_cc_debounce(pmic_typec_port); + + /* force it to toggle at least once */ + ret = regmap_write(pmic_typec_port->regmap, + pmic_typec_port->base + TYPEC_MODE_CFG_REG, + TYPEC_DISABLE_CMD); + if (ret) + goto done; + + ret = regmap_write(pmic_typec_port->regmap, + pmic_typec_port->base + TYPEC_MODE_CFG_REG, + mode); +done: + spin_unlock_irqrestore(&pmic_typec_port->lock, flags); + + return ret; +} + +#define TYPEC_INTR_EN_CFG_1_MASK \ + (TYPEC_LEGACY_CABLE_INT_EN | \ + TYPEC_NONCOMPLIANT_LEGACY_CABLE_INT_EN | \ + TYPEC_TRYSOURCE_DETECT_INT_EN | \ + TYPEC_TRYSINK_DETECT_INT_EN | \ + TYPEC_CCOUT_DETACH_INT_EN | \ + TYPEC_CCOUT_ATTACH_INT_EN | \ + TYPEC_VBUS_DEASSERT_INT_EN | \ + TYPEC_VBUS_ASSERT_INT_EN) + +#define TYPEC_INTR_EN_CFG_2_MASK \ + (TYPEC_STATE_MACHINE_CHANGE_INT_EN | TYPEC_VBUS_ERROR_INT_EN | \ + TYPEC_DEBOUNCE_DONE_INT_EN) + +int qcom_pmic_typec_port_start(struct pmic_typec_port *pmic_typec_port, + struct tcpm_port *tcpm_port) +{ + int i; + int mask; + int ret; + + /* Configure interrupt sources */ + ret = regmap_write(pmic_typec_port->regmap, + pmic_typec_port->base + TYPEC_INTERRUPT_EN_CFG_1_REG, + TYPEC_INTR_EN_CFG_1_MASK); + if (ret) + goto done; + + ret = regmap_write(pmic_typec_port->regmap, + pmic_typec_port->base + TYPEC_INTERRUPT_EN_CFG_2_REG, + TYPEC_INTR_EN_CFG_2_MASK); + if (ret) + goto done; + + /* start in TRY_SNK mode */ + ret = regmap_write(pmic_typec_port->regmap, + pmic_typec_port->base + TYPEC_MODE_CFG_REG, EN_TRY_SNK); + if (ret) + goto done; + + /* Configure VCONN for software control */ + ret = regmap_update_bits(pmic_typec_port->regmap, + pmic_typec_port->base + TYPEC_VCONN_CONTROL_REG, + VCONN_EN_SRC | VCONN_EN_VALUE, VCONN_EN_SRC); + if (ret) + goto done; + + /* Set CC threshold to 1.6 Volts | tPDdebounce = 10-20ms */ + mask = SEL_SRC_UPPER_REF | USE_TPD_FOR_EXITING_ATTACHSRC; + ret = regmap_update_bits(pmic_typec_port->regmap, + pmic_typec_port->base + TYPEC_EXIT_STATE_CFG_REG, + mask, mask); + if (ret) + goto done; + + pmic_typec_port->tcpm_port = tcpm_port; + + for (i = 0; i < pmic_typec_port->nr_irqs; i++) + enable_irq(pmic_typec_port->irq_data[i].irq); + +done: + return ret; +} + +void qcom_pmic_typec_port_stop(struct pmic_typec_port *pmic_typec_port) +{ + int i; + + for (i = 0; i < pmic_typec_port->nr_irqs; i++) + disable_irq(pmic_typec_port->irq_data[i].irq); +} + +struct pmic_typec_port *qcom_pmic_typec_port_alloc(struct device *dev) +{ + return devm_kzalloc(dev, sizeof(struct pmic_typec_port), GFP_KERNEL); +} + +int qcom_pmic_typec_port_probe(struct platform_device *pdev, + struct pmic_typec_port *pmic_typec_port, + struct pmic_typec_port_resources *res, + struct regmap *regmap, + u32 base) +{ + struct device *dev = &pdev->dev; + struct pmic_typec_port_irq_data *irq_data; + int i, ret, irq; + + if (!res->nr_irqs || res->nr_irqs > PMIC_TYPEC_MAX_IRQS) + return -EINVAL; + + irq_data = devm_kzalloc(dev, sizeof(*irq_data) * res->nr_irqs, + GFP_KERNEL); + if (!irq_data) + return -ENOMEM; + + pmic_typec_port->vdd_vbus = devm_regulator_get(dev, "vdd-vbus"); + if (IS_ERR(pmic_typec_port->vdd_vbus)) + return PTR_ERR(pmic_typec_port->vdd_vbus); + + pmic_typec_port->dev = dev; + pmic_typec_port->base = base; + pmic_typec_port->regmap = regmap; + pmic_typec_port->nr_irqs = res->nr_irqs; + pmic_typec_port->irq_data = irq_data; + spin_lock_init(&pmic_typec_port->lock); + INIT_DELAYED_WORK(&pmic_typec_port->cc_debounce_dwork, + qcom_pmic_typec_port_cc_debounce); + + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return irq; + + for (i = 0; i < res->nr_irqs; i++, irq_data++) { + irq = platform_get_irq_byname(pdev, + res->irq_params[i].irq_name); + if (irq < 0) + return irq; + + irq_data->pmic_typec_port = pmic_typec_port; + irq_data->irq = irq; + irq_data->virq = res->irq_params[i].virq; + ret = devm_request_threaded_irq(dev, irq, NULL, pmic_typec_port_isr, + IRQF_ONESHOT | IRQF_NO_AUTOEN, + res->irq_params[i].irq_name, + irq_data); + if (ret) + return ret; + } + + return 0; +} diff --git a/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_port.h b/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_port.h new file mode 100644 index 0000000000000000000000000000000000000000..d4d358c680b6bf0de590b99077f37bbb31a500d5 --- /dev/null +++ b/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_port.h @@ -0,0 +1,195 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2023, Linaro Ltd. All rights reserved. + */ +#ifndef __QCOM_PMIC_TYPEC_H__ +#define __QCOM_PMIC_TYPEC_H__ + +#include +#include + +#define TYPEC_SNK_STATUS_REG 0x06 +#define DETECTED_SNK_TYPE_MASK GENMASK(6, 0) +#define SNK_DAM_MASK GENMASK(6, 4) +#define SNK_DAM_500MA BIT(6) +#define SNK_DAM_1500MA BIT(5) +#define SNK_DAM_3000MA BIT(4) +#define SNK_RP_STD BIT(3) +#define SNK_RP_1P5 BIT(2) +#define SNK_RP_3P0 BIT(1) +#define SNK_RP_SHORT BIT(0) + +#define TYPEC_SRC_STATUS_REG 0x08 +#define DETECTED_SRC_TYPE_MASK GENMASK(4, 0) +#define SRC_HIGH_BATT BIT(5) +#define SRC_DEBUG_ACCESS BIT(4) +#define SRC_RD_OPEN BIT(3) +#define SRC_RD_RA_VCONN BIT(2) +#define SRC_RA_OPEN BIT(1) +#define AUDIO_ACCESS_RA_RA BIT(0) + +#define TYPEC_STATE_MACHINE_STATUS_REG 0x09 +#define TYPEC_ATTACH_DETACH_STATE BIT(5) + +#define TYPEC_SM_STATUS_REG 0x0A +#define TYPEC_SM_VBUS_VSAFE5V BIT(5) +#define TYPEC_SM_VBUS_VSAFE0V BIT(6) +#define TYPEC_SM_USBIN_LT_LV BIT(7) + +#define TYPEC_MISC_STATUS_REG 0x0B +#define TYPEC_WATER_DETECTION_STATUS BIT(7) +#define SNK_SRC_MODE BIT(6) +#define TYPEC_VBUS_DETECT BIT(5) +#define TYPEC_VBUS_ERROR_STATUS BIT(4) +#define TYPEC_DEBOUNCE_DONE BIT(3) +#define CC_ORIENTATION BIT(1) +#define CC_ATTACHED BIT(0) + +#define LEGACY_CABLE_STATUS_REG 0x0D +#define TYPEC_LEGACY_CABLE_STATUS BIT(1) +#define TYPEC_NONCOMP_LEGACY_CABLE_STATUS BIT(0) + +#define TYPEC_U_USB_STATUS_REG 0x0F +#define U_USB_GROUND_NOVBUS BIT(6) +#define U_USB_GROUND BIT(4) +#define U_USB_FMB1 BIT(3) +#define U_USB_FLOAT1 BIT(2) +#define U_USB_FMB2 BIT(1) +#define U_USB_FLOAT2 BIT(0) + +#define TYPEC_MODE_CFG_REG 0x44 +#define TYPEC_TRY_MODE_MASK GENMASK(4, 3) +#define EN_TRY_SNK BIT(4) +#define EN_TRY_SRC BIT(3) +#define TYPEC_POWER_ROLE_CMD_MASK GENMASK(2, 0) +#define EN_SRC_ONLY BIT(2) +#define EN_SNK_ONLY BIT(1) +#define TYPEC_DISABLE_CMD BIT(0) + +#define TYPEC_VCONN_CONTROL_REG 0x46 +#define VCONN_EN_ORIENTATION BIT(2) +#define VCONN_EN_VALUE BIT(1) +#define VCONN_EN_SRC BIT(0) + +#define TYPEC_CCOUT_CONTROL_REG 0x48 +#define TYPEC_CCOUT_BUFFER_EN BIT(2) +#define TYPEC_CCOUT_VALUE BIT(1) +#define TYPEC_CCOUT_SRC BIT(0) + +#define DEBUG_ACCESS_SRC_CFG_REG 0x4C +#define EN_UNORIENTED_DEBUG_ACCESS_SRC BIT(0) + +#define TYPE_C_CRUDE_SENSOR_CFG_REG 0x4e +#define EN_SRC_CRUDE_SENSOR BIT(1) +#define EN_SNK_CRUDE_SENSOR BIT(0) + +#define TYPEC_EXIT_STATE_CFG_REG 0x50 +#define BYPASS_VSAFE0V_DURING_ROLE_SWAP BIT(3) +#define SEL_SRC_UPPER_REF BIT(2) +#define USE_TPD_FOR_EXITING_ATTACHSRC BIT(1) +#define EXIT_SNK_BASED_ON_CC BIT(0) + +#define TYPEC_CURRSRC_CFG_REG 0x52 +#define TYPEC_SRC_RP_SEL_330UA BIT(1) +#define TYPEC_SRC_RP_SEL_180UA BIT(0) +#define TYPEC_SRC_RP_SEL_80UA 0 +#define TYPEC_SRC_RP_SEL_MASK GENMASK(1, 0) + +#define TYPEC_INTERRUPT_EN_CFG_1_REG 0x5E +#define TYPEC_LEGACY_CABLE_INT_EN BIT(7) +#define TYPEC_NONCOMPLIANT_LEGACY_CABLE_INT_EN BIT(6) +#define TYPEC_TRYSOURCE_DETECT_INT_EN BIT(5) +#define TYPEC_TRYSINK_DETECT_INT_EN BIT(4) +#define TYPEC_CCOUT_DETACH_INT_EN BIT(3) +#define TYPEC_CCOUT_ATTACH_INT_EN BIT(2) +#define TYPEC_VBUS_DEASSERT_INT_EN BIT(1) +#define TYPEC_VBUS_ASSERT_INT_EN BIT(0) + +#define TYPEC_INTERRUPT_EN_CFG_2_REG 0x60 +#define TYPEC_SRC_BATT_HPWR_INT_EN BIT(6) +#define MICRO_USB_STATE_CHANGE_INT_EN BIT(5) +#define TYPEC_STATE_MACHINE_CHANGE_INT_EN BIT(4) +#define TYPEC_DEBUG_ACCESS_DETECT_INT_EN BIT(3) +#define TYPEC_WATER_DETECTION_INT_EN BIT(2) +#define TYPEC_VBUS_ERROR_INT_EN BIT(1) +#define TYPEC_DEBOUNCE_DONE_INT_EN BIT(0) + +#define TYPEC_DEBOUNCE_OPTION_REG 0x62 +#define REDUCE_TCCDEBOUNCE_TO_2MS BIT(2) + +#define TYPE_C_SBU_CFG_REG 0x6A +#define SEL_SBU1_ISRC_VAL 0x04 +#define SEL_SBU2_ISRC_VAL 0x01 + +#define TYPEC_U_USB_CFG_REG 0x70 +#define EN_MICRO_USB_FACTORY_MODE BIT(1) +#define EN_MICRO_USB_MODE BIT(0) + +#define TYPEC_PMI632_U_USB_WATER_PROTECTION_CFG_REG 0x72 + +#define TYPEC_U_USB_WATER_PROTECTION_CFG_REG 0x73 +#define EN_MICRO_USB_WATER_PROTECTION BIT(4) +#define MICRO_USB_DETECTION_ON_TIME_CFG_MASK GENMASK(3, 2) +#define MICRO_USB_DETECTION_PERIOD_CFG_MASK GENMASK(1, 0) + +#define TYPEC_PMI632_MICRO_USB_MODE_REG 0x73 +#define MICRO_USB_MODE_ONLY BIT(0) + +/* Interrupt numbers */ +#define PMIC_TYPEC_OR_RID_IRQ 0x0 +#define PMIC_TYPEC_VPD_IRQ 0x1 +#define PMIC_TYPEC_CC_STATE_IRQ 0x2 +#define PMIC_TYPEC_VCONN_OC_IRQ 0x3 +#define PMIC_TYPEC_VBUS_IRQ 0x4 +#define PMIC_TYPEC_ATTACH_DETACH_IRQ 0x5 +#define PMIC_TYPEC_LEGACY_CABLE_IRQ 0x6 +#define PMIC_TYPEC_TRY_SNK_SRC_IRQ 0x7 + +/* Resources */ +#define PMIC_TYPEC_MAX_IRQS 0x08 + +struct pmic_typec_port_irq_params { + int virq; + char *irq_name; +}; + +struct pmic_typec_port_resources { + unsigned int nr_irqs; + struct pmic_typec_port_irq_params irq_params[PMIC_TYPEC_MAX_IRQS]; +}; + +/* API */ +struct pmic_typec; + +struct pmic_typec_port *qcom_pmic_typec_port_alloc(struct device *dev); + +int qcom_pmic_typec_port_probe(struct platform_device *pdev, + struct pmic_typec_port *pmic_typec_port, + struct pmic_typec_port_resources *res, + struct regmap *regmap, + u32 base); + +int qcom_pmic_typec_port_start(struct pmic_typec_port *pmic_typec_port, + struct tcpm_port *tcpm_port); + +void qcom_pmic_typec_port_stop(struct pmic_typec_port *pmic_typec_port); + +int qcom_pmic_typec_port_get_cc(struct pmic_typec_port *pmic_typec_port, + enum typec_cc_status *cc1, + enum typec_cc_status *cc2); + +int qcom_pmic_typec_port_set_cc(struct pmic_typec_port *pmic_typec_port, + enum typec_cc_status cc); + +int qcom_pmic_typec_port_get_vbus(struct pmic_typec_port *pmic_typec_port); + +int qcom_pmic_typec_port_set_vconn(struct pmic_typec_port *pmic_typec_port, bool on); + +int qcom_pmic_typec_port_start_toggling(struct pmic_typec_port *pmic_typec_port, + enum typec_port_type port_type, + enum typec_cc_status cc); + +int qcom_pmic_typec_port_set_vbus(struct pmic_typec_port *pmic_typec_port, bool on); + +#endif /* __QCOM_PMIC_TYPE_C_PORT_H__ */ diff --git a/drivers/usb/typec/tcpm/tcpci.c b/drivers/usb/typec/tcpm/tcpci.c index 8da23240afbe4c525a65c18c043fb57d46fe2792..fc708c289a73a5eca20f61c36d023cc0b5ea976d 100644 --- a/drivers/usb/typec/tcpm/tcpci.c +++ b/drivers/usb/typec/tcpm/tcpci.c @@ -895,7 +895,7 @@ static struct i2c_driver tcpci_i2c_driver = { .name = "tcpci", .of_match_table = of_match_ptr(tcpci_of_match), }, - .probe_new = tcpci_probe, + .probe = tcpci_probe, .remove = tcpci_remove, .id_table = tcpci_id, }; diff --git a/drivers/usb/typec/tcpm/tcpci_maxim_core.c b/drivers/usb/typec/tcpm/tcpci_maxim_core.c index f32cda2a5e3aa83a36e681b57faae1f02c35b395..9454b12a073c96aecb2241a90b562c2190bfc2b5 100644 --- a/drivers/usb/typec/tcpm/tcpci_maxim_core.c +++ b/drivers/usb/typec/tcpm/tcpci_maxim_core.c @@ -508,7 +508,7 @@ static struct i2c_driver max_tcpci_i2c_driver = { .name = "maxtcpc", .of_match_table = of_match_ptr(max_tcpci_of_match), }, - .probe_new = max_tcpci_probe, + .probe = max_tcpci_probe, .remove = max_tcpci_remove, .id_table = max_tcpci_id, }; diff --git a/drivers/usb/typec/tcpm/tcpci_mt6360.c b/drivers/usb/typec/tcpm/tcpci_mt6360.c index 6fa8fd5c8041a6e31d365c61dc6a6f23f82d3f3a..02b7fd30226508c27f92706a51440a175994bf3f 100644 --- a/drivers/usb/typec/tcpm/tcpci_mt6360.c +++ b/drivers/usb/typec/tcpm/tcpci_mt6360.c @@ -178,13 +178,12 @@ static int mt6360_tcpc_probe(struct platform_device *pdev) return 0; } -static int mt6360_tcpc_remove(struct platform_device *pdev) +static void mt6360_tcpc_remove(struct platform_device *pdev) { struct mt6360_tcpc_info *mti = platform_get_drvdata(pdev); disable_irq(mti->irq); tcpci_unregister_port(mti->tcpci); - return 0; } static int __maybe_unused mt6360_tcpc_suspend(struct device *dev) @@ -222,7 +221,7 @@ static struct platform_driver mt6360_tcpc_driver = { .of_match_table = mt6360_tcpc_of_id, }, .probe = mt6360_tcpc_probe, - .remove = mt6360_tcpc_remove, + .remove_new = mt6360_tcpc_remove, }; module_platform_driver(mt6360_tcpc_driver); diff --git a/drivers/usb/typec/tcpm/tcpci_mt6370.c b/drivers/usb/typec/tcpm/tcpci_mt6370.c index c5bb201a5163c251bea110406f6a9fa2d3ee4a15..2a079464b398d833be70479ed1e8f6677c7d9950 100644 --- a/drivers/usb/typec/tcpm/tcpci_mt6370.c +++ b/drivers/usb/typec/tcpm/tcpci_mt6370.c @@ -178,12 +178,10 @@ static int mt6370_tcpc_probe(struct platform_device *pdev) return 0; } -static int mt6370_tcpc_remove(struct platform_device *pdev) +static void mt6370_tcpc_remove(struct platform_device *pdev) { dev_pm_clear_wake_irq(&pdev->dev); device_init_wakeup(&pdev->dev, false); - - return 0; } static const struct of_device_id mt6370_tcpc_devid_table[] = { @@ -198,7 +196,7 @@ static struct platform_driver mt6370_tcpc_driver = { .of_match_table = mt6370_tcpc_devid_table, }, .probe = mt6370_tcpc_probe, - .remove = mt6370_tcpc_remove, + .remove_new = mt6370_tcpc_remove, }; module_platform_driver(mt6370_tcpc_driver); diff --git a/drivers/usb/typec/tcpm/tcpci_rt1711h.c b/drivers/usb/typec/tcpm/tcpci_rt1711h.c index a0e9e3fe8564ce726516e1bd0441ec00d871672f..17ebc5fb684f9f56e7f91a695621a401dd31ee9a 100644 --- a/drivers/usb/typec/tcpm/tcpci_rt1711h.c +++ b/drivers/usb/typec/tcpm/tcpci_rt1711h.c @@ -412,7 +412,7 @@ static struct i2c_driver rt1711h_i2c_driver = { .name = "rt1711h", .of_match_table = of_match_ptr(rt1711h_of_match), }, - .probe_new = rt1711h_probe, + .probe = rt1711h_probe, .remove = rt1711h_remove, .id_table = rt1711h_id, }; diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c index 3c6b0c8e2d3ae2c7c896e300f162afe557037c95..829d75ebab422b7756f232e9cb9d0c5689cdc89e 100644 --- a/drivers/usb/typec/tcpm/tcpm.c +++ b/drivers/usb/typec/tcpm/tcpm.c @@ -4885,7 +4885,8 @@ static void run_state_machine(struct tcpm_port *port) break; case PORT_RESET: tcpm_reset_port(port); - tcpm_set_cc(port, TYPEC_CC_OPEN); + tcpm_set_cc(port, tcpm_default_state(port) == SNK_UNATTACHED ? + TYPEC_CC_RD : tcpm_rp_cc(port)); tcpm_set_state(port, PORT_RESET_WAIT_OFF, PD_T_ERROR_RECOVERY); break; @@ -6339,6 +6340,27 @@ static int tcpm_psy_get_current_now(struct tcpm_port *port, return 0; } +static int tcpm_psy_get_input_power_limit(struct tcpm_port *port, + union power_supply_propval *val) +{ + unsigned int src_mv, src_ma, max_src_uw = 0; + unsigned int i, tmp; + + for (i = 0; i < port->nr_source_caps; i++) { + u32 pdo = port->source_caps[i]; + + if (pdo_type(pdo) == PDO_TYPE_FIXED) { + src_mv = pdo_fixed_voltage(pdo); + src_ma = pdo_max_current(pdo); + tmp = src_mv * src_ma; + max_src_uw = tmp > max_src_uw ? tmp : max_src_uw; + } + } + + val->intval = max_src_uw; + return 0; +} + static int tcpm_psy_get_prop(struct power_supply *psy, enum power_supply_property psp, union power_supply_propval *val) @@ -6368,6 +6390,9 @@ static int tcpm_psy_get_prop(struct power_supply *psy, case POWER_SUPPLY_PROP_CURRENT_NOW: ret = tcpm_psy_get_current_now(port, val); break; + case POWER_SUPPLY_PROP_INPUT_POWER_LIMIT: + tcpm_psy_get_input_power_limit(port, val); + break; default: ret = -EINVAL; break; diff --git a/drivers/usb/typec/tcpm/wcove.c b/drivers/usb/typec/tcpm/wcove.c index 20917d85d6f4c3f0824cf9f944e153225cdc8e50..87d4abde0ea279f53a35da67051114228c27fe7f 100644 --- a/drivers/usb/typec/tcpm/wcove.c +++ b/drivers/usb/typec/tcpm/wcove.c @@ -671,7 +671,7 @@ static int wcove_typec_probe(struct platform_device *pdev) return 0; } -static int wcove_typec_remove(struct platform_device *pdev) +static void wcove_typec_remove(struct platform_device *pdev) { struct wcove_typec *wcove = platform_get_drvdata(pdev); unsigned int val; @@ -684,8 +684,6 @@ static int wcove_typec_remove(struct platform_device *pdev) tcpm_unregister_port(wcove->tcpm); fwnode_remove_software_node(wcove->tcpc.fwnode); - - return 0; } static struct platform_driver wcove_typec_driver = { @@ -693,7 +691,7 @@ static struct platform_driver wcove_typec_driver = { .name = "bxt_wcove_usbc", }, .probe = wcove_typec_probe, - .remove = wcove_typec_remove, + .remove_new = wcove_typec_remove, }; module_platform_driver(wcove_typec_driver); diff --git a/drivers/usb/typec/tipd/core.c b/drivers/usb/typec/tipd/core.c index 603dbd44deba9aaab55ad671526a6bf14befd339..37b56ce75f39d5311ef6320d048c6b9669bb70ef 100644 --- a/drivers/usb/typec/tipd/core.c +++ b/drivers/usb/typec/tipd/core.c @@ -950,7 +950,7 @@ static struct i2c_driver tps6598x_i2c_driver = { .pm = &tps6598x_pm_ops, .of_match_table = tps6598x_of_match, }, - .probe_new = tps6598x_probe, + .probe = tps6598x_probe, .remove = tps6598x_remove, .id_table = tps6598x_id, }; diff --git a/drivers/usb/typec/ucsi/psy.c b/drivers/usb/typec/ucsi/psy.c index 56bf56517f75a39585e51f12a2830912c05060ae..384b42267f1fceec174b6d8abc58f5d63d05a836 100644 --- a/drivers/usb/typec/ucsi/psy.c +++ b/drivers/usb/typec/ucsi/psy.c @@ -27,8 +27,20 @@ static enum power_supply_property ucsi_psy_props[] = { POWER_SUPPLY_PROP_VOLTAGE_NOW, POWER_SUPPLY_PROP_CURRENT_MAX, POWER_SUPPLY_PROP_CURRENT_NOW, + POWER_SUPPLY_PROP_SCOPE, }; +static int ucsi_psy_get_scope(struct ucsi_connector *con, + union power_supply_propval *val) +{ + u8 scope = POWER_SUPPLY_SCOPE_UNKNOWN; + struct device *dev = con->ucsi->dev; + + device_property_read_u8(dev, "scope", &scope); + val->intval = scope; + return 0; +} + static int ucsi_psy_get_online(struct ucsi_connector *con, union power_supply_propval *val) { @@ -194,6 +206,8 @@ static int ucsi_psy_get_prop(struct power_supply *psy, return ucsi_psy_get_current_max(con, val); case POWER_SUPPLY_PROP_CURRENT_NOW: return ucsi_psy_get_current_now(con, val); + case POWER_SUPPLY_PROP_SCOPE: + return ucsi_psy_get_scope(con, val); default: return -EINVAL; } diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c index b664ecbb798be6012d988e15d7622c6071f20fe8..9b6d6b14431fefb013b0ad18e6d257a4ef8748ea 100644 --- a/drivers/usb/typec/ucsi/ucsi.c +++ b/drivers/usb/typec/ucsi/ucsi.c @@ -812,6 +812,23 @@ static void ucsi_partner_change(struct ucsi_connector *con) break; } + if (con->status.flags & UCSI_CONSTAT_CONNECTED) { + switch (UCSI_CONSTAT_PARTNER_TYPE(con->status.flags)) { + case UCSI_CONSTAT_PARTNER_TYPE_DEBUG: + typec_set_mode(con->port, TYPEC_MODE_DEBUG); + break; + case UCSI_CONSTAT_PARTNER_TYPE_AUDIO: + typec_set_mode(con->port, TYPEC_MODE_AUDIO); + break; + default: + if (UCSI_CONSTAT_PARTNER_FLAGS(con->status.flags) == + UCSI_CONSTAT_PARTNER_FLAG_USB) + typec_set_mode(con->port, TYPEC_STATE_USB); + } + } else { + typec_set_mode(con->port, TYPEC_STATE_SAFE); + } + /* Only notify USB controller if partner supports USB data */ if (!(UCSI_CONSTAT_PARTNER_FLAGS(con->status.flags) & UCSI_CONSTAT_PARTNER_FLAG_USB)) u_role = USB_ROLE_NONE; diff --git a/drivers/usb/typec/ucsi/ucsi_acpi.c b/drivers/usb/typec/ucsi/ucsi_acpi.c index 217355f1f9b94a7de899b9b2e9d9cd2f30b1ac56..6bbf490ac4010e9ad31a140bd484ec40077f0af6 100644 --- a/drivers/usb/typec/ucsi/ucsi_acpi.c +++ b/drivers/usb/typec/ucsi/ucsi_acpi.c @@ -212,7 +212,7 @@ static int ucsi_acpi_probe(struct platform_device *pdev) return 0; } -static int ucsi_acpi_remove(struct platform_device *pdev) +static void ucsi_acpi_remove(struct platform_device *pdev) { struct ucsi_acpi *ua = platform_get_drvdata(pdev); @@ -221,8 +221,6 @@ static int ucsi_acpi_remove(struct platform_device *pdev) acpi_remove_notify_handler(ACPI_HANDLE(&pdev->dev), ACPI_DEVICE_NOTIFY, ucsi_acpi_notify); - - return 0; } static int ucsi_acpi_resume(struct device *dev) @@ -247,7 +245,7 @@ static struct platform_driver ucsi_acpi_platform_driver = { .acpi_match_table = ACPI_PTR(ucsi_acpi_match), }, .probe = ucsi_acpi_probe, - .remove = ucsi_acpi_remove, + .remove_new = ucsi_acpi_remove, }; module_platform_driver(ucsi_acpi_platform_driver); diff --git a/drivers/usb/typec/ucsi/ucsi_ccg.c b/drivers/usb/typec/ucsi/ucsi_ccg.c index e0ed465bd518d44c3fd0c70fa5fe9bfcd53dc9a2..607061a37eca3de4ce5499e8dae2602fc5c718b2 100644 --- a/drivers/usb/typec/ucsi/ucsi_ccg.c +++ b/drivers/usb/typec/ucsi/ucsi_ccg.c @@ -1495,7 +1495,7 @@ static struct i2c_driver ucsi_ccg_driver = { .acpi_match_table = amd_i2c_ucsi_match, .of_match_table = ucsi_ccg_of_match_table, }, - .probe_new = ucsi_ccg_probe, + .probe = ucsi_ccg_probe, .remove = ucsi_ccg_remove, .id_table = ucsi_ccg_device_id, }; diff --git a/drivers/usb/typec/ucsi/ucsi_glink.c b/drivers/usb/typec/ucsi/ucsi_glink.c index b454a5159896a908341b8a8b1fd648d4f25a54e0..1fe9cb5b6bd96dcdcb850541181ad4ab4da261cb 100644 --- a/drivers/usb/typec/ucsi/ucsi_glink.c +++ b/drivers/usb/typec/ucsi/ucsi_glink.c @@ -245,7 +245,7 @@ static void pmic_glink_ucsi_callback(const void *data, size_t len, void *priv) struct pmic_glink_ucsi *ucsi = priv; const struct pmic_glink_hdr *hdr = data; - switch (hdr->opcode) { + switch (le32_to_cpu(hdr->opcode)) { case UC_UCSI_READ_BUF_REQ: pmic_glink_ucsi_read_ack(ucsi, data, len); break; diff --git a/drivers/usb/typec/ucsi/ucsi_stm32g0.c b/drivers/usb/typec/ucsi/ucsi_stm32g0.c index 93fead0096b7bc10caf7f21cca95bd505579ebc6..93d7806681cf0147baf37a98281fc2b8192c73a3 100644 --- a/drivers/usb/typec/ucsi/ucsi_stm32g0.c +++ b/drivers/usb/typec/ucsi/ucsi_stm32g0.c @@ -763,7 +763,7 @@ static struct i2c_driver ucsi_stm32g0_i2c_driver = { .of_match_table = of_match_ptr(ucsi_stm32g0_typec_of_match), .pm = pm_sleep_ptr(&ucsi_stm32g0_pm_ops), }, - .probe_new = ucsi_stm32g0_probe, + .probe = ucsi_stm32g0_probe, .remove = ucsi_stm32g0_remove, .id_table = ucsi_stm32g0_typec_i2c_devid }; diff --git a/drivers/usb/typec/wusb3801.c b/drivers/usb/typec/wusb3801.c index a43a18d4b02edc232c9bc58ff2fca833437985c0..6062875fb04a9d3f92a6df2bcfea9844fd52dbfc 100644 --- a/drivers/usb/typec/wusb3801.c +++ b/drivers/usb/typec/wusb3801.c @@ -420,7 +420,7 @@ static const struct of_device_id wusb3801_of_match[] = { MODULE_DEVICE_TABLE(of, wusb3801_of_match); static struct i2c_driver wusb3801_driver = { - .probe_new = wusb3801_probe, + .probe = wusb3801_probe, .remove = wusb3801_remove, .driver = { .name = "wusb3801", diff --git a/drivers/usb/usbip/stub_main.c b/drivers/usb/usbip/stub_main.c index e8c3131a85431082e035f378d2a84d763e1b9a72..0a6624d37929e85f1771d16df64a72ce92a2c623 100644 --- a/drivers/usb/usbip/stub_main.c +++ b/drivers/usb/usbip/stub_main.c @@ -167,15 +167,13 @@ static ssize_t match_busid_show(struct device_driver *drv, char *buf) static ssize_t match_busid_store(struct device_driver *dev, const char *buf, size_t count) { - int len; char busid[BUSID_SIZE]; if (count < 5) return -EINVAL; /* busid needs to include \0 termination */ - len = strlcpy(busid, buf + 4, BUSID_SIZE); - if (sizeof(busid) <= len) + if (strscpy(busid, buf + 4, BUSID_SIZE) < 0) return -EINVAL; if (!strncmp(buf, "add ", 4)) { diff --git a/drivers/usb/usbip/vhci_hcd.c b/drivers/usb/usbip/vhci_hcd.c index 233265550fc63e3a4cf5a18c56676d286fe8091c..37d1fc34e8a564485dc1243667bf0265e6c5f16d 100644 --- a/drivers/usb/usbip/vhci_hcd.c +++ b/drivers/usb/usbip/vhci_hcd.c @@ -1393,7 +1393,7 @@ static int vhci_hcd_probe(struct platform_device *pdev) return ret; } -static int vhci_hcd_remove(struct platform_device *pdev) +static void vhci_hcd_remove(struct platform_device *pdev) { struct vhci *vhci = *((void **)dev_get_platdata(&pdev->dev)); @@ -1410,8 +1410,6 @@ static int vhci_hcd_remove(struct platform_device *pdev) vhci->vhci_hcd_hs = NULL; vhci->vhci_hcd_ss = NULL; - - return 0; } #ifdef CONFIG_PM @@ -1485,7 +1483,7 @@ static int vhci_hcd_resume(struct platform_device *pdev) static struct platform_driver vhci_driver = { .probe = vhci_hcd_probe, - .remove = vhci_hcd_remove, + .remove_new = vhci_hcd_remove, .suspend = vhci_hcd_suspend, .resume = vhci_hcd_resume, .driver = { diff --git a/drivers/vdpa/Kconfig b/drivers/vdpa/Kconfig index cd6ad92f3f0598c2f9b07f4f659d8c922c3f7f9e..656c1cb541deb7c51c31b5304ff5f5d5b3395da7 100644 --- a/drivers/vdpa/Kconfig +++ b/drivers/vdpa/Kconfig @@ -116,4 +116,14 @@ config ALIBABA_ENI_VDPA This driver includes a HW monitor device that reads health values from the DPU. +config PDS_VDPA + tristate "vDPA driver for AMD/Pensando DSC devices" + select VIRTIO_PCI_LIB + depends on PCI_MSI + depends on PDS_CORE + help + vDPA network driver for AMD/Pensando's PDS Core devices. + With this driver, the VirtIO dataplane can be + offloaded to an AMD/Pensando DSC device. + endif # VDPA diff --git a/drivers/vdpa/Makefile b/drivers/vdpa/Makefile index 59396ff2a31828cbbd14a852b82a9922a0d52d46..8f53c6f3cca7c5e5dacc726f2d8f9d94390e04bb 100644 --- a/drivers/vdpa/Makefile +++ b/drivers/vdpa/Makefile @@ -7,3 +7,4 @@ obj-$(CONFIG_MLX5_VDPA) += mlx5/ obj-$(CONFIG_VP_VDPA) += virtio_pci/ obj-$(CONFIG_ALIBABA_ENI_VDPA) += alibaba/ obj-$(CONFIG_SNET_VDPA) += solidrun/ +obj-$(CONFIG_PDS_VDPA) += pds/ diff --git a/drivers/vdpa/ifcvf/ifcvf_base.c b/drivers/vdpa/ifcvf/ifcvf_base.c index 5563b3a773c7bdc59cde05e39957cb50701765be..060f837a4f9f762018fd29d52bcb10c91a9436aa 100644 --- a/drivers/vdpa/ifcvf/ifcvf_base.c +++ b/drivers/vdpa/ifcvf/ifcvf_base.c @@ -69,6 +69,37 @@ static int ifcvf_read_config_range(struct pci_dev *dev, return 0; } +static u16 ifcvf_get_vq_size(struct ifcvf_hw *hw, u16 qid) +{ + u16 queue_size; + + vp_iowrite16(qid, &hw->common_cfg->queue_select); + queue_size = vp_ioread16(&hw->common_cfg->queue_size); + + return queue_size; +} + +/* This function returns the max allowed safe size for + * all virtqueues. It is the minimal size that can be + * suppprted by all virtqueues. + */ +u16 ifcvf_get_max_vq_size(struct ifcvf_hw *hw) +{ + u16 queue_size, max_size, qid; + + max_size = ifcvf_get_vq_size(hw, 0); + for (qid = 1; qid < hw->nr_vring; qid++) { + queue_size = ifcvf_get_vq_size(hw, qid); + /* 0 means the queue is unavailable */ + if (!queue_size) + continue; + + max_size = min(queue_size, max_size); + } + + return max_size; +} + int ifcvf_init_hw(struct ifcvf_hw *hw, struct pci_dev *pdev) { struct virtio_pci_cap cap; @@ -134,6 +165,9 @@ int ifcvf_init_hw(struct ifcvf_hw *hw, struct pci_dev *pdev) } hw->nr_vring = vp_ioread16(&hw->common_cfg->num_queues); + hw->vring = kzalloc(sizeof(struct vring_info) * hw->nr_vring, GFP_KERNEL); + if (!hw->vring) + return -ENOMEM; for (i = 0; i < hw->nr_vring; i++) { vp_iowrite16(i, &hw->common_cfg->queue_select); @@ -170,21 +204,9 @@ void ifcvf_set_status(struct ifcvf_hw *hw, u8 status) void ifcvf_reset(struct ifcvf_hw *hw) { - hw->config_cb.callback = NULL; - hw->config_cb.private = NULL; - ifcvf_set_status(hw, 0); - /* flush set_status, make sure VF is stopped, reset */ - ifcvf_get_status(hw); -} - -static void ifcvf_add_status(struct ifcvf_hw *hw, u8 status) -{ - if (status != 0) - status |= ifcvf_get_status(hw); - - ifcvf_set_status(hw, status); - ifcvf_get_status(hw); + while (ifcvf_get_status(hw)) + msleep(1); } u64 ifcvf_get_hw_features(struct ifcvf_hw *hw) @@ -204,11 +226,29 @@ u64 ifcvf_get_hw_features(struct ifcvf_hw *hw) return features; } -u64 ifcvf_get_features(struct ifcvf_hw *hw) +/* return provisioned vDPA dev features */ +u64 ifcvf_get_dev_features(struct ifcvf_hw *hw) { return hw->dev_features; } +u64 ifcvf_get_driver_features(struct ifcvf_hw *hw) +{ + struct virtio_pci_common_cfg __iomem *cfg = hw->common_cfg; + u32 features_lo, features_hi; + u64 features; + + vp_iowrite32(0, &cfg->device_feature_select); + features_lo = vp_ioread32(&cfg->guest_feature); + + vp_iowrite32(1, &cfg->device_feature_select); + features_hi = vp_ioread32(&cfg->guest_feature); + + features = ((u64)features_hi << 32) | features_lo; + + return features; +} + int ifcvf_verify_min_features(struct ifcvf_hw *hw, u64 features) { if (!(features & BIT_ULL(VIRTIO_F_ACCESS_PLATFORM)) && features) { @@ -275,7 +315,7 @@ void ifcvf_write_dev_config(struct ifcvf_hw *hw, u64 offset, vp_iowrite8(*p++, hw->dev_cfg + offset + i); } -static void ifcvf_set_features(struct ifcvf_hw *hw, u64 features) +void ifcvf_set_driver_features(struct ifcvf_hw *hw, u64 features) { struct virtio_pci_common_cfg __iomem *cfg = hw->common_cfg; @@ -286,105 +326,104 @@ static void ifcvf_set_features(struct ifcvf_hw *hw, u64 features) vp_iowrite32(features >> 32, &cfg->guest_feature); } -static int ifcvf_config_features(struct ifcvf_hw *hw) -{ - ifcvf_set_features(hw, hw->req_features); - ifcvf_add_status(hw, VIRTIO_CONFIG_S_FEATURES_OK); - - if (!(ifcvf_get_status(hw) & VIRTIO_CONFIG_S_FEATURES_OK)) { - IFCVF_ERR(hw->pdev, "Failed to set FEATURES_OK status\n"); - return -EIO; - } - - return 0; -} - u16 ifcvf_get_vq_state(struct ifcvf_hw *hw, u16 qid) { - struct ifcvf_lm_cfg __iomem *ifcvf_lm; - void __iomem *avail_idx_addr; + struct ifcvf_lm_cfg __iomem *lm_cfg = hw->lm_cfg; u16 last_avail_idx; - u32 q_pair_id; - ifcvf_lm = (struct ifcvf_lm_cfg __iomem *)hw->lm_cfg; - q_pair_id = qid / 2; - avail_idx_addr = &ifcvf_lm->vring_lm_cfg[q_pair_id].idx_addr[qid % 2]; - last_avail_idx = vp_ioread16(avail_idx_addr); + last_avail_idx = vp_ioread16(&lm_cfg->vq_state_region + qid * 2); return last_avail_idx; } int ifcvf_set_vq_state(struct ifcvf_hw *hw, u16 qid, u16 num) { - struct ifcvf_lm_cfg __iomem *ifcvf_lm; - void __iomem *avail_idx_addr; - u32 q_pair_id; + struct ifcvf_lm_cfg __iomem *lm_cfg = hw->lm_cfg; - ifcvf_lm = (struct ifcvf_lm_cfg __iomem *)hw->lm_cfg; - q_pair_id = qid / 2; - avail_idx_addr = &ifcvf_lm->vring_lm_cfg[q_pair_id].idx_addr[qid % 2]; - hw->vring[qid].last_avail_idx = num; - vp_iowrite16(num, avail_idx_addr); + vp_iowrite16(num, &lm_cfg->vq_state_region + qid * 2); return 0; } -static int ifcvf_hw_enable(struct ifcvf_hw *hw) +void ifcvf_set_vq_num(struct ifcvf_hw *hw, u16 qid, u32 num) { - struct virtio_pci_common_cfg __iomem *cfg; - u32 i; + struct virtio_pci_common_cfg __iomem *cfg = hw->common_cfg; - cfg = hw->common_cfg; - for (i = 0; i < hw->nr_vring; i++) { - if (!hw->vring[i].ready) - break; + vp_iowrite16(qid, &cfg->queue_select); + vp_iowrite16(num, &cfg->queue_size); +} - vp_iowrite16(i, &cfg->queue_select); - vp_iowrite64_twopart(hw->vring[i].desc, &cfg->queue_desc_lo, - &cfg->queue_desc_hi); - vp_iowrite64_twopart(hw->vring[i].avail, &cfg->queue_avail_lo, - &cfg->queue_avail_hi); - vp_iowrite64_twopart(hw->vring[i].used, &cfg->queue_used_lo, - &cfg->queue_used_hi); - vp_iowrite16(hw->vring[i].size, &cfg->queue_size); - ifcvf_set_vq_state(hw, i, hw->vring[i].last_avail_idx); - vp_iowrite16(1, &cfg->queue_enable); - } +int ifcvf_set_vq_address(struct ifcvf_hw *hw, u16 qid, u64 desc_area, + u64 driver_area, u64 device_area) +{ + struct virtio_pci_common_cfg __iomem *cfg = hw->common_cfg; + + vp_iowrite16(qid, &cfg->queue_select); + vp_iowrite64_twopart(desc_area, &cfg->queue_desc_lo, + &cfg->queue_desc_hi); + vp_iowrite64_twopart(driver_area, &cfg->queue_avail_lo, + &cfg->queue_avail_hi); + vp_iowrite64_twopart(device_area, &cfg->queue_used_lo, + &cfg->queue_used_hi); return 0; } -static void ifcvf_hw_disable(struct ifcvf_hw *hw) +bool ifcvf_get_vq_ready(struct ifcvf_hw *hw, u16 qid) { - u32 i; + struct virtio_pci_common_cfg __iomem *cfg = hw->common_cfg; + u16 queue_enable; - ifcvf_set_config_vector(hw, VIRTIO_MSI_NO_VECTOR); - for (i = 0; i < hw->nr_vring; i++) { - ifcvf_set_vq_vector(hw, i, VIRTIO_MSI_NO_VECTOR); - } + vp_iowrite16(qid, &cfg->queue_select); + queue_enable = vp_ioread16(&cfg->queue_enable); + + return (bool)queue_enable; } -int ifcvf_start_hw(struct ifcvf_hw *hw) +void ifcvf_set_vq_ready(struct ifcvf_hw *hw, u16 qid, bool ready) { - ifcvf_reset(hw); - ifcvf_add_status(hw, VIRTIO_CONFIG_S_ACKNOWLEDGE); - ifcvf_add_status(hw, VIRTIO_CONFIG_S_DRIVER); + struct virtio_pci_common_cfg __iomem *cfg = hw->common_cfg; - if (ifcvf_config_features(hw) < 0) - return -EINVAL; + vp_iowrite16(qid, &cfg->queue_select); + vp_iowrite16(ready, &cfg->queue_enable); +} - if (ifcvf_hw_enable(hw) < 0) - return -EINVAL; +static void ifcvf_reset_vring(struct ifcvf_hw *hw) +{ + u16 qid; - ifcvf_add_status(hw, VIRTIO_CONFIG_S_DRIVER_OK); + for (qid = 0; qid < hw->nr_vring; qid++) { + hw->vring[qid].cb.callback = NULL; + hw->vring[qid].cb.private = NULL; + ifcvf_set_vq_vector(hw, qid, VIRTIO_MSI_NO_VECTOR); + } +} - return 0; +static void ifcvf_reset_config_handler(struct ifcvf_hw *hw) +{ + hw->config_cb.callback = NULL; + hw->config_cb.private = NULL; + ifcvf_set_config_vector(hw, VIRTIO_MSI_NO_VECTOR); +} + +static void ifcvf_synchronize_irq(struct ifcvf_hw *hw) +{ + u32 nvectors = hw->num_msix_vectors; + struct pci_dev *pdev = hw->pdev; + int i, irq; + + for (i = 0; i < nvectors; i++) { + irq = pci_irq_vector(pdev, i); + if (irq >= 0) + synchronize_irq(irq); + } } -void ifcvf_stop_hw(struct ifcvf_hw *hw) +void ifcvf_stop(struct ifcvf_hw *hw) { - ifcvf_hw_disable(hw); - ifcvf_reset(hw); + ifcvf_synchronize_irq(hw); + ifcvf_reset_vring(hw); + ifcvf_reset_config_handler(hw); } void ifcvf_notify_queue(struct ifcvf_hw *hw, u16 qid) diff --git a/drivers/vdpa/ifcvf/ifcvf_base.h b/drivers/vdpa/ifcvf/ifcvf_base.h index c20d1c40214e06c68559a2e3d8ea77f860ec24f3..b57849c643f611fc271d894eb24075f99a0c6fed 100644 --- a/drivers/vdpa/ifcvf/ifcvf_base.h +++ b/drivers/vdpa/ifcvf/ifcvf_base.h @@ -24,15 +24,9 @@ #define N3000_DEVICE_ID 0x1041 #define N3000_SUBSYS_DEVICE_ID 0x001A -/* Max 8 data queue pairs(16 queues) and one control vq for now. */ -#define IFCVF_MAX_QUEUES 17 - #define IFCVF_QUEUE_ALIGNMENT PAGE_SIZE -#define IFCVF_QUEUE_MAX 32768 #define IFCVF_PCI_MAX_RESOURCE 6 -#define IFCVF_LM_CFG_SIZE 0x40 -#define IFCVF_LM_RING_STATE_OFFSET 0x20 #define IFCVF_LM_BAR 4 #define IFCVF_ERR(pdev, fmt, ...) dev_err(&pdev->dev, fmt, ##__VA_ARGS__) @@ -47,12 +41,7 @@ #define MSIX_VECTOR_DEV_SHARED 3 struct vring_info { - u64 desc; - u64 avail; - u64 used; - u16 size; u16 last_avail_idx; - bool ready; void __iomem *notify_addr; phys_addr_t notify_pa; u32 irq; @@ -60,10 +49,18 @@ struct vring_info { char msix_name[256]; }; +struct ifcvf_lm_cfg { + __le64 control; + __le64 status; + __le64 lm_mem_log_start_addr; + __le64 lm_mem_log_end_addr; + __le16 vq_state_region; +}; + struct ifcvf_hw { u8 __iomem *isr; /* Live migration */ - u8 __iomem *lm_cfg; + struct ifcvf_lm_cfg __iomem *lm_cfg; /* Notification bar number */ u8 notify_bar; u8 msix_vector_status; @@ -74,13 +71,12 @@ struct ifcvf_hw { phys_addr_t notify_base_pa; u32 notify_off_multiplier; u32 dev_type; - u64 req_features; u64 hw_features; /* provisioned device features */ u64 dev_features; struct virtio_pci_common_cfg __iomem *common_cfg; void __iomem *dev_cfg; - struct vring_info vring[IFCVF_MAX_QUEUES]; + struct vring_info *vring; void __iomem * const *base; char config_msix_name[256]; struct vdpa_callback config_cb; @@ -88,6 +84,7 @@ struct ifcvf_hw { int vqs_reused_irq; u16 nr_vring; /* VIRTIO_PCI_CAP_DEVICE_CFG size */ + u32 num_msix_vectors; u32 cap_dev_config_size; struct pci_dev *pdev; }; @@ -98,16 +95,6 @@ struct ifcvf_adapter { struct ifcvf_hw *vf; }; -struct ifcvf_vring_lm_cfg { - u32 idx_addr[2]; - u8 reserved[IFCVF_LM_CFG_SIZE - 8]; -}; - -struct ifcvf_lm_cfg { - u8 reserved[IFCVF_LM_RING_STATE_OFFSET]; - struct ifcvf_vring_lm_cfg vring_lm_cfg[IFCVF_MAX_QUEUES]; -}; - struct ifcvf_vdpa_mgmt_dev { struct vdpa_mgmt_dev mdev; struct ifcvf_hw vf; @@ -116,8 +103,7 @@ struct ifcvf_vdpa_mgmt_dev { }; int ifcvf_init_hw(struct ifcvf_hw *hw, struct pci_dev *dev); -int ifcvf_start_hw(struct ifcvf_hw *hw); -void ifcvf_stop_hw(struct ifcvf_hw *hw); +void ifcvf_stop(struct ifcvf_hw *hw); void ifcvf_notify_queue(struct ifcvf_hw *hw, u16 qid); void ifcvf_read_dev_config(struct ifcvf_hw *hw, u64 offset, void *dst, int length); @@ -127,7 +113,7 @@ u8 ifcvf_get_status(struct ifcvf_hw *hw); void ifcvf_set_status(struct ifcvf_hw *hw, u8 status); void io_write64_twopart(u64 val, u32 *lo, u32 *hi); void ifcvf_reset(struct ifcvf_hw *hw); -u64 ifcvf_get_features(struct ifcvf_hw *hw); +u64 ifcvf_get_dev_features(struct ifcvf_hw *hw); u64 ifcvf_get_hw_features(struct ifcvf_hw *hw); int ifcvf_verify_min_features(struct ifcvf_hw *hw, u64 features); u16 ifcvf_get_vq_state(struct ifcvf_hw *hw, u16 qid); @@ -137,4 +123,12 @@ int ifcvf_probed_virtio_net(struct ifcvf_hw *hw); u32 ifcvf_get_config_size(struct ifcvf_hw *hw); u16 ifcvf_set_vq_vector(struct ifcvf_hw *hw, u16 qid, int vector); u16 ifcvf_set_config_vector(struct ifcvf_hw *hw, int vector); +void ifcvf_set_vq_num(struct ifcvf_hw *hw, u16 qid, u32 num); +int ifcvf_set_vq_address(struct ifcvf_hw *hw, u16 qid, u64 desc_area, + u64 driver_area, u64 device_area); +bool ifcvf_get_vq_ready(struct ifcvf_hw *hw, u16 qid); +void ifcvf_set_vq_ready(struct ifcvf_hw *hw, u16 qid, bool ready); +void ifcvf_set_driver_features(struct ifcvf_hw *hw, u64 features); +u64 ifcvf_get_driver_features(struct ifcvf_hw *hw); +u16 ifcvf_get_max_vq_size(struct ifcvf_hw *hw); #endif /* _IFCVF_H_ */ diff --git a/drivers/vdpa/ifcvf/ifcvf_main.c b/drivers/vdpa/ifcvf/ifcvf_main.c index 7f78c47e40d60756cba68ec7001bf4626f09a443..e98fa8100f3cc796f2f3b543cadd7f9a694313c7 100644 --- a/drivers/vdpa/ifcvf/ifcvf_main.c +++ b/drivers/vdpa/ifcvf/ifcvf_main.c @@ -125,6 +125,7 @@ static void ifcvf_free_irq(struct ifcvf_hw *vf) ifcvf_free_vq_irq(vf); ifcvf_free_config_irq(vf); ifcvf_free_irq_vectors(pdev); + vf->num_msix_vectors = 0; } /* ifcvf MSIX vectors allocator, this helper tries to allocate @@ -343,56 +344,11 @@ static int ifcvf_request_irq(struct ifcvf_hw *vf) if (ret) return ret; - return 0; -} - -static int ifcvf_start_datapath(struct ifcvf_adapter *adapter) -{ - struct ifcvf_hw *vf = adapter->vf; - u8 status; - int ret; - - ret = ifcvf_start_hw(vf); - if (ret < 0) { - status = ifcvf_get_status(vf); - status |= VIRTIO_CONFIG_S_FAILED; - ifcvf_set_status(vf, status); - } - - return ret; -} - -static int ifcvf_stop_datapath(struct ifcvf_adapter *adapter) -{ - struct ifcvf_hw *vf = adapter->vf; - int i; - - for (i = 0; i < vf->nr_vring; i++) - vf->vring[i].cb.callback = NULL; - - ifcvf_stop_hw(vf); + vf->num_msix_vectors = nvectors; return 0; } -static void ifcvf_reset_vring(struct ifcvf_adapter *adapter) -{ - struct ifcvf_hw *vf = adapter->vf; - int i; - - for (i = 0; i < vf->nr_vring; i++) { - vf->vring[i].last_avail_idx = 0; - vf->vring[i].desc = 0; - vf->vring[i].avail = 0; - vf->vring[i].used = 0; - vf->vring[i].ready = 0; - vf->vring[i].cb.callback = NULL; - vf->vring[i].cb.private = NULL; - } - - ifcvf_reset(vf); -} - static struct ifcvf_adapter *vdpa_to_adapter(struct vdpa_device *vdpa_dev) { return container_of(vdpa_dev, struct ifcvf_adapter, vdpa); @@ -414,7 +370,7 @@ static u64 ifcvf_vdpa_get_device_features(struct vdpa_device *vdpa_dev) u64 features; if (type == VIRTIO_ID_NET || type == VIRTIO_ID_BLOCK) - features = ifcvf_get_features(vf); + features = ifcvf_get_dev_features(vf); else { features = 0; IFCVF_ERR(pdev, "VIRTIO ID %u not supported\n", vf->dev_type); @@ -432,7 +388,7 @@ static int ifcvf_vdpa_set_driver_features(struct vdpa_device *vdpa_dev, u64 feat if (ret) return ret; - vf->req_features = features; + ifcvf_set_driver_features(vf, features); return 0; } @@ -440,8 +396,11 @@ static int ifcvf_vdpa_set_driver_features(struct vdpa_device *vdpa_dev, u64 feat static u64 ifcvf_vdpa_get_driver_features(struct vdpa_device *vdpa_dev) { struct ifcvf_hw *vf = vdpa_to_vf(vdpa_dev); + u64 features; + + features = ifcvf_get_driver_features(vf); - return vf->req_features; + return features; } static u8 ifcvf_vdpa_get_status(struct vdpa_device *vdpa_dev) @@ -453,13 +412,11 @@ static u8 ifcvf_vdpa_get_status(struct vdpa_device *vdpa_dev) static void ifcvf_vdpa_set_status(struct vdpa_device *vdpa_dev, u8 status) { - struct ifcvf_adapter *adapter; struct ifcvf_hw *vf; u8 status_old; int ret; vf = vdpa_to_vf(vdpa_dev); - adapter = vdpa_to_adapter(vdpa_dev); status_old = ifcvf_get_status(vf); if (status_old == status) @@ -469,16 +426,9 @@ static void ifcvf_vdpa_set_status(struct vdpa_device *vdpa_dev, u8 status) !(status_old & VIRTIO_CONFIG_S_DRIVER_OK)) { ret = ifcvf_request_irq(vf); if (ret) { - status = ifcvf_get_status(vf); - status |= VIRTIO_CONFIG_S_FAILED; - ifcvf_set_status(vf, status); + IFCVF_ERR(vf->pdev, "failed to request irq with error %d\n", ret); return; } - - if (ifcvf_start_datapath(adapter) < 0) - IFCVF_ERR(adapter->pdev, - "Failed to set ifcvf vdpa status %u\n", - status); } ifcvf_set_status(vf, status); @@ -486,30 +436,24 @@ static void ifcvf_vdpa_set_status(struct vdpa_device *vdpa_dev, u8 status) static int ifcvf_vdpa_reset(struct vdpa_device *vdpa_dev) { - struct ifcvf_adapter *adapter; - struct ifcvf_hw *vf; - u8 status_old; - - vf = vdpa_to_vf(vdpa_dev); - adapter = vdpa_to_adapter(vdpa_dev); - status_old = ifcvf_get_status(vf); + struct ifcvf_hw *vf = vdpa_to_vf(vdpa_dev); + u8 status = ifcvf_get_status(vf); - if (status_old == 0) - return 0; + ifcvf_stop(vf); - if (status_old & VIRTIO_CONFIG_S_DRIVER_OK) { - ifcvf_stop_datapath(adapter); + if (status & VIRTIO_CONFIG_S_DRIVER_OK) ifcvf_free_irq(vf); - } - ifcvf_reset_vring(adapter); + ifcvf_reset(vf); return 0; } static u16 ifcvf_vdpa_get_vq_num_max(struct vdpa_device *vdpa_dev) { - return IFCVF_QUEUE_MAX; + struct ifcvf_hw *vf = vdpa_to_vf(vdpa_dev); + + return ifcvf_get_max_vq_size(vf); } static int ifcvf_vdpa_get_vq_state(struct vdpa_device *vdpa_dev, u16 qid, @@ -542,14 +486,14 @@ static void ifcvf_vdpa_set_vq_ready(struct vdpa_device *vdpa_dev, { struct ifcvf_hw *vf = vdpa_to_vf(vdpa_dev); - vf->vring[qid].ready = ready; + ifcvf_set_vq_ready(vf, qid, ready); } static bool ifcvf_vdpa_get_vq_ready(struct vdpa_device *vdpa_dev, u16 qid) { struct ifcvf_hw *vf = vdpa_to_vf(vdpa_dev); - return vf->vring[qid].ready; + return ifcvf_get_vq_ready(vf, qid); } static void ifcvf_vdpa_set_vq_num(struct vdpa_device *vdpa_dev, u16 qid, @@ -557,7 +501,7 @@ static void ifcvf_vdpa_set_vq_num(struct vdpa_device *vdpa_dev, u16 qid, { struct ifcvf_hw *vf = vdpa_to_vf(vdpa_dev); - vf->vring[qid].size = num; + ifcvf_set_vq_num(vf, qid, num); } static int ifcvf_vdpa_set_vq_address(struct vdpa_device *vdpa_dev, u16 qid, @@ -566,11 +510,7 @@ static int ifcvf_vdpa_set_vq_address(struct vdpa_device *vdpa_dev, u16 qid, { struct ifcvf_hw *vf = vdpa_to_vf(vdpa_dev); - vf->vring[qid].desc = desc_area; - vf->vring[qid].avail = driver_area; - vf->vring[qid].used = device_area; - - return 0; + return ifcvf_set_vq_address(vf, qid, desc_area, driver_area, device_area); } static void ifcvf_vdpa_kick_vq(struct vdpa_device *vdpa_dev, u16 qid) @@ -892,6 +832,7 @@ static int ifcvf_probe(struct pci_dev *pdev, const struct pci_device_id *id) return 0; err: + kfree(ifcvf_mgmt_dev->vf.vring); kfree(ifcvf_mgmt_dev); return ret; } @@ -902,6 +843,7 @@ static void ifcvf_remove(struct pci_dev *pdev) ifcvf_mgmt_dev = pci_get_drvdata(pdev); vdpa_mgmtdev_unregister(&ifcvf_mgmt_dev->mdev); + kfree(ifcvf_mgmt_dev->vf.vring); kfree(ifcvf_mgmt_dev); } @@ -911,7 +853,9 @@ static struct pci_device_id ifcvf_pci_ids[] = { N3000_DEVICE_ID, PCI_VENDOR_ID_INTEL, N3000_SUBSYS_DEVICE_ID) }, - /* C5000X-PL network device */ + /* C5000X-PL network device + * F2000X-PL network device + */ { PCI_DEVICE_SUB(PCI_VENDOR_ID_REDHAT_QUMRANET, VIRTIO_TRANS_ID_NET, PCI_VENDOR_ID_INTEL, diff --git a/drivers/vdpa/mlx5/net/mlx5_vnet.c b/drivers/vdpa/mlx5/net/mlx5_vnet.c index 279ac6a558d29a7124204c9229fe13f7ee4eafd3..9138ef2fb2c853270ec11284a0824e84200276d3 100644 --- a/drivers/vdpa/mlx5/net/mlx5_vnet.c +++ b/drivers/vdpa/mlx5/net/mlx5_vnet.c @@ -83,6 +83,7 @@ struct mlx5_vq_restore_info { u64 driver_addr; u16 avail_index; u16 used_index; + struct msi_map map; bool ready; bool restore; }; @@ -118,6 +119,7 @@ struct mlx5_vdpa_virtqueue { u16 avail_idx; u16 used_idx; int fw_state; + struct msi_map map; /* keep last in the struct */ struct mlx5_vq_restore_info ri; @@ -808,6 +810,13 @@ static bool counters_supported(const struct mlx5_vdpa_dev *mvdev) BIT_ULL(MLX5_OBJ_TYPE_VIRTIO_Q_COUNTERS); } +static bool msix_mode_supported(struct mlx5_vdpa_dev *mvdev) +{ + return MLX5_CAP_DEV_VDPA_EMULATION(mvdev->mdev, event_mode) & + (1 << MLX5_VIRTIO_Q_EVENT_MODE_MSIX_MODE) && + pci_msix_can_alloc_dyn(mvdev->mdev->pdev); +} + static int create_virtqueue(struct mlx5_vdpa_net *ndev, struct mlx5_vdpa_virtqueue *mvq) { int inlen = MLX5_ST_SZ_BYTES(create_virtio_net_q_in); @@ -849,9 +858,15 @@ static int create_virtqueue(struct mlx5_vdpa_net *ndev, struct mlx5_vdpa_virtque if (vq_is_tx(mvq->index)) MLX5_SET(virtio_net_q_object, obj_context, tisn_or_qpn, ndev->res.tisn); - MLX5_SET(virtio_q, vq_ctx, event_mode, MLX5_VIRTIO_Q_EVENT_MODE_QP_MODE); + if (mvq->map.virq) { + MLX5_SET(virtio_q, vq_ctx, event_mode, MLX5_VIRTIO_Q_EVENT_MODE_MSIX_MODE); + MLX5_SET(virtio_q, vq_ctx, event_qpn_or_msix, mvq->map.index); + } else { + MLX5_SET(virtio_q, vq_ctx, event_mode, MLX5_VIRTIO_Q_EVENT_MODE_QP_MODE); + MLX5_SET(virtio_q, vq_ctx, event_qpn_or_msix, mvq->fwqp.mqp.qpn); + } + MLX5_SET(virtio_q, vq_ctx, queue_index, mvq->index); - MLX5_SET(virtio_q, vq_ctx, event_qpn_or_msix, mvq->fwqp.mqp.qpn); MLX5_SET(virtio_q, vq_ctx, queue_size, mvq->num_ent); MLX5_SET(virtio_q, vq_ctx, virtio_version_1_0, !!(ndev->mvdev.actual_features & BIT_ULL(VIRTIO_F_VERSION_1))); @@ -1194,6 +1209,56 @@ static void counter_set_dealloc(struct mlx5_vdpa_net *ndev, struct mlx5_vdpa_vir mlx5_vdpa_warn(&ndev->mvdev, "dealloc counter set 0x%x\n", mvq->counter_set_id); } +static irqreturn_t mlx5_vdpa_int_handler(int irq, void *priv) +{ + struct vdpa_callback *cb = priv; + + if (cb->callback) + return cb->callback(cb->private); + + return IRQ_HANDLED; +} + +static void alloc_vector(struct mlx5_vdpa_net *ndev, + struct mlx5_vdpa_virtqueue *mvq) +{ + struct mlx5_vdpa_irq_pool *irqp = &ndev->irqp; + struct mlx5_vdpa_irq_pool_entry *ent; + int err; + int i; + + for (i = 0; i < irqp->num_ent; i++) { + ent = &irqp->entries[i]; + if (!ent->used) { + snprintf(ent->name, MLX5_VDPA_IRQ_NAME_LEN, "%s-vq-%d", + dev_name(&ndev->mvdev.vdev.dev), mvq->index); + ent->dev_id = &ndev->event_cbs[mvq->index]; + err = request_irq(ent->map.virq, mlx5_vdpa_int_handler, 0, + ent->name, ent->dev_id); + if (err) + return; + + ent->used = true; + mvq->map = ent->map; + return; + } + } +} + +static void dealloc_vector(struct mlx5_vdpa_net *ndev, + struct mlx5_vdpa_virtqueue *mvq) +{ + struct mlx5_vdpa_irq_pool *irqp = &ndev->irqp; + int i; + + for (i = 0; i < irqp->num_ent; i++) + if (mvq->map.virq == irqp->entries[i].map.virq) { + free_irq(mvq->map.virq, irqp->entries[i].dev_id); + irqp->entries[i].used = false; + return; + } +} + static int setup_vq(struct mlx5_vdpa_net *ndev, struct mlx5_vdpa_virtqueue *mvq) { u16 idx = mvq->index; @@ -1223,27 +1288,31 @@ static int setup_vq(struct mlx5_vdpa_net *ndev, struct mlx5_vdpa_virtqueue *mvq) err = counter_set_alloc(ndev, mvq); if (err) - goto err_counter; + goto err_connect; + alloc_vector(ndev, mvq); err = create_virtqueue(ndev, mvq); if (err) - goto err_connect; + goto err_vq; if (mvq->ready) { err = modify_virtqueue(ndev, mvq, MLX5_VIRTIO_NET_Q_OBJECT_STATE_RDY); if (err) { mlx5_vdpa_warn(&ndev->mvdev, "failed to modify to ready vq idx %d(%d)\n", idx, err); - goto err_connect; + goto err_modify; } } mvq->initialized = true; return 0; -err_connect: +err_modify: + destroy_virtqueue(ndev, mvq); +err_vq: + dealloc_vector(ndev, mvq); counter_set_dealloc(ndev, mvq); -err_counter: +err_connect: qp_destroy(ndev, &mvq->vqqp); err_vqqp: qp_destroy(ndev, &mvq->fwqp); @@ -1288,6 +1357,7 @@ static void teardown_vq(struct mlx5_vdpa_net *ndev, struct mlx5_vdpa_virtqueue * suspend_vq(ndev, mvq); destroy_virtqueue(ndev, mvq); + dealloc_vector(ndev, mvq); counter_set_dealloc(ndev, mvq); qp_destroy(ndev, &mvq->vqqp); qp_destroy(ndev, &mvq->fwqp); @@ -2505,6 +2575,7 @@ static int save_channel_info(struct mlx5_vdpa_net *ndev, struct mlx5_vdpa_virtqu ri->desc_addr = mvq->desc_addr; ri->device_addr = mvq->device_addr; ri->driver_addr = mvq->driver_addr; + ri->map = mvq->map; ri->restore = true; return 0; } @@ -2549,6 +2620,7 @@ static void restore_channels_info(struct mlx5_vdpa_net *ndev) mvq->desc_addr = ri->desc_addr; mvq->device_addr = ri->device_addr; mvq->driver_addr = ri->driver_addr; + mvq->map = ri->map; } } @@ -2833,6 +2905,25 @@ static struct device *mlx5_get_vq_dma_dev(struct vdpa_device *vdev, u16 idx) return mvdev->vdev.dma_dev; } +static void free_irqs(struct mlx5_vdpa_net *ndev) +{ + struct mlx5_vdpa_irq_pool_entry *ent; + int i; + + if (!msix_mode_supported(&ndev->mvdev)) + return; + + if (!ndev->irqp.entries) + return; + + for (i = ndev->irqp.num_ent - 1; i >= 0; i--) { + ent = ndev->irqp.entries + i; + if (ent->map.virq) + pci_msix_free_irq(ndev->mvdev.mdev->pdev, ent->map); + } + kfree(ndev->irqp.entries); +} + static void mlx5_vdpa_free(struct vdpa_device *vdev) { struct mlx5_vdpa_dev *mvdev = to_mvdev(vdev); @@ -2848,6 +2939,7 @@ static void mlx5_vdpa_free(struct vdpa_device *vdev) mlx5_mpfs_del_mac(pfmdev, ndev->config.mac); } mlx5_vdpa_free_resources(&ndev->mvdev); + free_irqs(ndev); kfree(ndev->event_cbs); kfree(ndev->vqs); } @@ -2876,9 +2968,23 @@ static struct vdpa_notification_area mlx5_get_vq_notification(struct vdpa_device return ret; } -static int mlx5_get_vq_irq(struct vdpa_device *vdv, u16 idx) +static int mlx5_get_vq_irq(struct vdpa_device *vdev, u16 idx) { - return -EOPNOTSUPP; + struct mlx5_vdpa_dev *mvdev = to_mvdev(vdev); + struct mlx5_vdpa_net *ndev = to_mlx5_vdpa_ndev(mvdev); + struct mlx5_vdpa_virtqueue *mvq; + + if (!is_index_valid(mvdev, idx)) + return -EINVAL; + + if (is_ctrl_vq_idx(mvdev, idx)) + return -EOPNOTSUPP; + + mvq = &ndev->vqs[idx]; + if (!mvq->map.virq) + return -EOPNOTSUPP; + + return mvq->map.virq; } static u64 mlx5_vdpa_get_driver_features(struct vdpa_device *vdev) @@ -3155,6 +3261,34 @@ static int config_func_mtu(struct mlx5_core_dev *mdev, u16 mtu) return err; } +static void allocate_irqs(struct mlx5_vdpa_net *ndev) +{ + struct mlx5_vdpa_irq_pool_entry *ent; + int i; + + if (!msix_mode_supported(&ndev->mvdev)) + return; + + if (!ndev->mvdev.mdev->pdev) + return; + + ndev->irqp.entries = kcalloc(ndev->mvdev.max_vqs, sizeof(*ndev->irqp.entries), GFP_KERNEL); + if (!ndev->irqp.entries) + return; + + + for (i = 0; i < ndev->mvdev.max_vqs; i++) { + ent = ndev->irqp.entries + i; + snprintf(ent->name, MLX5_VDPA_IRQ_NAME_LEN, "%s-vq-%d", + dev_name(&ndev->mvdev.vdev.dev), i); + ent->map = pci_msix_alloc_irq_at(ndev->mvdev.mdev->pdev, MSI_ANY_INDEX, NULL); + if (!ent->map.virq) + return; + + ndev->irqp.num_ent++; + } +} + static int mlx5_vdpa_dev_add(struct vdpa_mgmt_dev *v_mdev, const char *name, const struct vdpa_dev_set_config *add_config) { @@ -3233,6 +3367,7 @@ static int mlx5_vdpa_dev_add(struct vdpa_mgmt_dev *v_mdev, const char *name, } init_mvqs(ndev); + allocate_irqs(ndev); init_rwsem(&ndev->reslock); config = &ndev->config; @@ -3413,6 +3548,17 @@ static void mlx5v_remove(struct auxiliary_device *adev) kfree(mgtdev); } +static void mlx5v_shutdown(struct auxiliary_device *auxdev) +{ + struct mlx5_vdpa_mgmtdev *mgtdev; + struct mlx5_vdpa_net *ndev; + + mgtdev = auxiliary_get_drvdata(auxdev); + ndev = mgtdev->ndev; + + free_irqs(ndev); +} + static const struct auxiliary_device_id mlx5v_id_table[] = { { .name = MLX5_ADEV_NAME ".vnet", }, {}, @@ -3424,6 +3570,7 @@ static struct auxiliary_driver mlx5v_driver = { .name = "vnet", .probe = mlx5v_probe, .remove = mlx5v_remove, + .shutdown = mlx5v_shutdown, .id_table = mlx5v_id_table, }; diff --git a/drivers/vdpa/mlx5/net/mlx5_vnet.h b/drivers/vdpa/mlx5/net/mlx5_vnet.h index c90a89e1de4d529456e000caca51319afd228d56..36c44d9fdd166b52c83557c66793acee1dbb2ae4 100644 --- a/drivers/vdpa/mlx5/net/mlx5_vnet.h +++ b/drivers/vdpa/mlx5/net/mlx5_vnet.h @@ -26,6 +26,20 @@ static inline u16 key2vid(u64 key) return (u16)(key >> 48) & 0xfff; } +#define MLX5_VDPA_IRQ_NAME_LEN 32 + +struct mlx5_vdpa_irq_pool_entry { + struct msi_map map; + bool used; + char name[MLX5_VDPA_IRQ_NAME_LEN]; + void *dev_id; +}; + +struct mlx5_vdpa_irq_pool { + int num_ent; + struct mlx5_vdpa_irq_pool_entry *entries; +}; + struct mlx5_vdpa_net { struct mlx5_vdpa_dev mvdev; struct mlx5_vdpa_net_resources res; @@ -49,6 +63,7 @@ struct mlx5_vdpa_net { struct vdpa_callback config_cb; struct mlx5_vdpa_wq_ent cvq_ent; struct hlist_head macvlan_hash[MLX5V_MACVLAN_SIZE]; + struct mlx5_vdpa_irq_pool irqp; struct dentry *debugfs; }; diff --git a/drivers/vdpa/pds/Makefile b/drivers/vdpa/pds/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..2e22418e3ab3058d0974dbf99aea59a3ef217560 --- /dev/null +++ b/drivers/vdpa/pds/Makefile @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: GPL-2.0-only +# Copyright(c) 2023 Advanced Micro Devices, Inc + +obj-$(CONFIG_PDS_VDPA) := pds_vdpa.o + +pds_vdpa-y := aux_drv.o \ + cmds.o \ + vdpa_dev.o + +pds_vdpa-$(CONFIG_DEBUG_FS) += debugfs.o diff --git a/drivers/vdpa/pds/aux_drv.c b/drivers/vdpa/pds/aux_drv.c new file mode 100644 index 0000000000000000000000000000000000000000..186e9ee22eb1126127a829f221d67dd76e8b3252 --- /dev/null +++ b/drivers/vdpa/pds/aux_drv.c @@ -0,0 +1,140 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* Copyright(c) 2023 Advanced Micro Devices, Inc */ + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "aux_drv.h" +#include "debugfs.h" +#include "vdpa_dev.h" + +static const struct auxiliary_device_id pds_vdpa_id_table[] = { + { .name = PDS_VDPA_DEV_NAME, }, + {}, +}; + +static int pds_vdpa_device_id_check(struct pci_dev *pdev) +{ + if (pdev->device != PCI_DEVICE_ID_PENSANDO_VDPA_VF || + pdev->vendor != PCI_VENDOR_ID_PENSANDO) + return -ENODEV; + + return PCI_DEVICE_ID_PENSANDO_VDPA_VF; +} + +static int pds_vdpa_probe(struct auxiliary_device *aux_dev, + const struct auxiliary_device_id *id) + +{ + struct pds_auxiliary_dev *padev = + container_of(aux_dev, struct pds_auxiliary_dev, aux_dev); + struct device *dev = &aux_dev->dev; + struct pds_vdpa_aux *vdpa_aux; + int err; + + vdpa_aux = kzalloc(sizeof(*vdpa_aux), GFP_KERNEL); + if (!vdpa_aux) + return -ENOMEM; + + vdpa_aux->padev = padev; + vdpa_aux->vf_id = pci_iov_vf_id(padev->vf_pdev); + auxiliary_set_drvdata(aux_dev, vdpa_aux); + + /* Get device ident info and set up the vdpa_mgmt_dev */ + err = pds_vdpa_get_mgmt_info(vdpa_aux); + if (err) + goto err_free_mem; + + /* Find the virtio configuration */ + vdpa_aux->vd_mdev.pci_dev = padev->vf_pdev; + vdpa_aux->vd_mdev.device_id_check = pds_vdpa_device_id_check; + vdpa_aux->vd_mdev.dma_mask = DMA_BIT_MASK(PDS_CORE_ADDR_LEN); + err = vp_modern_probe(&vdpa_aux->vd_mdev); + if (err) { + dev_err(dev, "Unable to probe for virtio configuration: %pe\n", + ERR_PTR(err)); + goto err_free_mgmt_info; + } + + /* Let vdpa know that we can provide devices */ + err = vdpa_mgmtdev_register(&vdpa_aux->vdpa_mdev); + if (err) { + dev_err(dev, "%s: Failed to initialize vdpa_mgmt interface: %pe\n", + __func__, ERR_PTR(err)); + goto err_free_virtio; + } + + pds_vdpa_debugfs_add_pcidev(vdpa_aux); + pds_vdpa_debugfs_add_ident(vdpa_aux); + + return 0; + +err_free_virtio: + vp_modern_remove(&vdpa_aux->vd_mdev); +err_free_mgmt_info: + pci_free_irq_vectors(padev->vf_pdev); +err_free_mem: + kfree(vdpa_aux); + auxiliary_set_drvdata(aux_dev, NULL); + + return err; +} + +static void pds_vdpa_remove(struct auxiliary_device *aux_dev) +{ + struct pds_vdpa_aux *vdpa_aux = auxiliary_get_drvdata(aux_dev); + struct device *dev = &aux_dev->dev; + + vdpa_mgmtdev_unregister(&vdpa_aux->vdpa_mdev); + vp_modern_remove(&vdpa_aux->vd_mdev); + pci_free_irq_vectors(vdpa_aux->padev->vf_pdev); + + pds_vdpa_debugfs_del_vdpadev(vdpa_aux); + kfree(vdpa_aux); + auxiliary_set_drvdata(aux_dev, NULL); + + dev_info(dev, "Removed\n"); +} + +static struct auxiliary_driver pds_vdpa_driver = { + .name = PDS_DEV_TYPE_VDPA_STR, + .probe = pds_vdpa_probe, + .remove = pds_vdpa_remove, + .id_table = pds_vdpa_id_table, +}; + +static void __exit pds_vdpa_cleanup(void) +{ + auxiliary_driver_unregister(&pds_vdpa_driver); + + pds_vdpa_debugfs_destroy(); +} +module_exit(pds_vdpa_cleanup); + +static int __init pds_vdpa_init(void) +{ + int err; + + pds_vdpa_debugfs_create(); + + err = auxiliary_driver_register(&pds_vdpa_driver); + if (err) { + pr_err("%s: aux driver register failed: %pe\n", + PDS_VDPA_DRV_NAME, ERR_PTR(err)); + pds_vdpa_debugfs_destroy(); + } + + return err; +} +module_init(pds_vdpa_init); + +MODULE_DESCRIPTION(PDS_VDPA_DRV_DESCRIPTION); +MODULE_AUTHOR("Advanced Micro Devices, Inc"); +MODULE_LICENSE("GPL"); diff --git a/drivers/vdpa/pds/aux_drv.h b/drivers/vdpa/pds/aux_drv.h new file mode 100644 index 0000000000000000000000000000000000000000..26b75344156e4a6b6f6033d195ad583311464e8d --- /dev/null +++ b/drivers/vdpa/pds/aux_drv.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* Copyright(c) 2023 Advanced Micro Devices, Inc */ + +#ifndef _AUX_DRV_H_ +#define _AUX_DRV_H_ + +#include + +#define PDS_VDPA_DRV_DESCRIPTION "AMD/Pensando vDPA VF Device Driver" +#define PDS_VDPA_DRV_NAME KBUILD_MODNAME + +struct pds_vdpa_aux { + struct pds_auxiliary_dev *padev; + + struct vdpa_mgmt_dev vdpa_mdev; + struct pds_vdpa_device *pdsv; + + struct pds_vdpa_ident ident; + + int vf_id; + struct dentry *dentry; + struct virtio_pci_modern_device vd_mdev; + + int nintrs; +}; +#endif /* _AUX_DRV_H_ */ diff --git a/drivers/vdpa/pds/cmds.c b/drivers/vdpa/pds/cmds.c new file mode 100644 index 0000000000000000000000000000000000000000..80863a41c3cdd26f72fe89b7485cdd61ebd1fbea --- /dev/null +++ b/drivers/vdpa/pds/cmds.c @@ -0,0 +1,185 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* Copyright(c) 2023 Advanced Micro Devices, Inc */ + +#include +#include + +#include +#include +#include +#include + +#include "vdpa_dev.h" +#include "aux_drv.h" +#include "cmds.h" + +int pds_vdpa_init_hw(struct pds_vdpa_device *pdsv) +{ + struct pds_auxiliary_dev *padev = pdsv->vdpa_aux->padev; + struct device *dev = &padev->aux_dev.dev; + union pds_core_adminq_cmd cmd = { + .vdpa_init.opcode = PDS_VDPA_CMD_INIT, + .vdpa_init.vdpa_index = pdsv->vdpa_index, + .vdpa_init.vf_id = cpu_to_le16(pdsv->vdpa_aux->vf_id), + }; + union pds_core_adminq_comp comp = {}; + int err; + + /* Initialize the vdpa/virtio device */ + err = pds_client_adminq_cmd(padev, &cmd, sizeof(cmd.vdpa_init), + &comp, 0); + if (err) + dev_dbg(dev, "Failed to init hw, status %d: %pe\n", + comp.status, ERR_PTR(err)); + + return err; +} + +int pds_vdpa_cmd_reset(struct pds_vdpa_device *pdsv) +{ + struct pds_auxiliary_dev *padev = pdsv->vdpa_aux->padev; + struct device *dev = &padev->aux_dev.dev; + union pds_core_adminq_cmd cmd = { + .vdpa.opcode = PDS_VDPA_CMD_RESET, + .vdpa.vdpa_index = pdsv->vdpa_index, + .vdpa.vf_id = cpu_to_le16(pdsv->vdpa_aux->vf_id), + }; + union pds_core_adminq_comp comp = {}; + int err; + + err = pds_client_adminq_cmd(padev, &cmd, sizeof(cmd.vdpa), &comp, 0); + if (err) + dev_dbg(dev, "Failed to reset hw, status %d: %pe\n", + comp.status, ERR_PTR(err)); + + return err; +} + +int pds_vdpa_cmd_set_status(struct pds_vdpa_device *pdsv, u8 status) +{ + struct pds_auxiliary_dev *padev = pdsv->vdpa_aux->padev; + struct device *dev = &padev->aux_dev.dev; + union pds_core_adminq_cmd cmd = { + .vdpa_status.opcode = PDS_VDPA_CMD_STATUS_UPDATE, + .vdpa_status.vdpa_index = pdsv->vdpa_index, + .vdpa_status.vf_id = cpu_to_le16(pdsv->vdpa_aux->vf_id), + .vdpa_status.status = status, + }; + union pds_core_adminq_comp comp = {}; + int err; + + err = pds_client_adminq_cmd(padev, &cmd, sizeof(cmd.vdpa_status), &comp, 0); + if (err) + dev_dbg(dev, "Failed to set status to %#x, error status %d: %pe\n", + status, comp.status, ERR_PTR(err)); + + return err; +} + +int pds_vdpa_cmd_set_mac(struct pds_vdpa_device *pdsv, u8 *mac) +{ + struct pds_auxiliary_dev *padev = pdsv->vdpa_aux->padev; + struct device *dev = &padev->aux_dev.dev; + union pds_core_adminq_cmd cmd = { + .vdpa_setattr.opcode = PDS_VDPA_CMD_SET_ATTR, + .vdpa_setattr.vdpa_index = pdsv->vdpa_index, + .vdpa_setattr.vf_id = cpu_to_le16(pdsv->vdpa_aux->vf_id), + .vdpa_setattr.attr = PDS_VDPA_ATTR_MAC, + }; + union pds_core_adminq_comp comp = {}; + int err; + + ether_addr_copy(cmd.vdpa_setattr.mac, mac); + err = pds_client_adminq_cmd(padev, &cmd, sizeof(cmd.vdpa_setattr), + &comp, 0); + if (err) + dev_dbg(dev, "Failed to set mac address %pM, status %d: %pe\n", + mac, comp.status, ERR_PTR(err)); + + return err; +} + +int pds_vdpa_cmd_set_max_vq_pairs(struct pds_vdpa_device *pdsv, u16 max_vqp) +{ + struct pds_auxiliary_dev *padev = pdsv->vdpa_aux->padev; + struct device *dev = &padev->aux_dev.dev; + union pds_core_adminq_cmd cmd = { + .vdpa_setattr.opcode = PDS_VDPA_CMD_SET_ATTR, + .vdpa_setattr.vdpa_index = pdsv->vdpa_index, + .vdpa_setattr.vf_id = cpu_to_le16(pdsv->vdpa_aux->vf_id), + .vdpa_setattr.attr = PDS_VDPA_ATTR_MAX_VQ_PAIRS, + .vdpa_setattr.max_vq_pairs = cpu_to_le16(max_vqp), + }; + union pds_core_adminq_comp comp = {}; + int err; + + err = pds_client_adminq_cmd(padev, &cmd, sizeof(cmd.vdpa_setattr), + &comp, 0); + if (err) + dev_dbg(dev, "Failed to set max vq pairs %u, status %d: %pe\n", + max_vqp, comp.status, ERR_PTR(err)); + + return err; +} + +int pds_vdpa_cmd_init_vq(struct pds_vdpa_device *pdsv, u16 qid, u16 invert_idx, + struct pds_vdpa_vq_info *vq_info) +{ + struct pds_auxiliary_dev *padev = pdsv->vdpa_aux->padev; + struct device *dev = &padev->aux_dev.dev; + union pds_core_adminq_cmd cmd = { + .vdpa_vq_init.opcode = PDS_VDPA_CMD_VQ_INIT, + .vdpa_vq_init.vdpa_index = pdsv->vdpa_index, + .vdpa_vq_init.vf_id = cpu_to_le16(pdsv->vdpa_aux->vf_id), + .vdpa_vq_init.qid = cpu_to_le16(qid), + .vdpa_vq_init.len = cpu_to_le16(ilog2(vq_info->q_len)), + .vdpa_vq_init.desc_addr = cpu_to_le64(vq_info->desc_addr), + .vdpa_vq_init.avail_addr = cpu_to_le64(vq_info->avail_addr), + .vdpa_vq_init.used_addr = cpu_to_le64(vq_info->used_addr), + .vdpa_vq_init.intr_index = cpu_to_le16(qid), + .vdpa_vq_init.avail_index = cpu_to_le16(vq_info->avail_idx ^ invert_idx), + .vdpa_vq_init.used_index = cpu_to_le16(vq_info->used_idx ^ invert_idx), + }; + union pds_core_adminq_comp comp = {}; + int err; + + dev_dbg(dev, "%s: qid %d len %d desc_addr %#llx avail_addr %#llx used_addr %#llx\n", + __func__, qid, ilog2(vq_info->q_len), + vq_info->desc_addr, vq_info->avail_addr, vq_info->used_addr); + + err = pds_client_adminq_cmd(padev, &cmd, sizeof(cmd.vdpa_vq_init), + &comp, 0); + if (err) + dev_dbg(dev, "Failed to init vq %d, status %d: %pe\n", + qid, comp.status, ERR_PTR(err)); + + return err; +} + +int pds_vdpa_cmd_reset_vq(struct pds_vdpa_device *pdsv, u16 qid, u16 invert_idx, + struct pds_vdpa_vq_info *vq_info) +{ + struct pds_auxiliary_dev *padev = pdsv->vdpa_aux->padev; + struct device *dev = &padev->aux_dev.dev; + union pds_core_adminq_cmd cmd = { + .vdpa_vq_reset.opcode = PDS_VDPA_CMD_VQ_RESET, + .vdpa_vq_reset.vdpa_index = pdsv->vdpa_index, + .vdpa_vq_reset.vf_id = cpu_to_le16(pdsv->vdpa_aux->vf_id), + .vdpa_vq_reset.qid = cpu_to_le16(qid), + }; + union pds_core_adminq_comp comp = {}; + int err; + + err = pds_client_adminq_cmd(padev, &cmd, sizeof(cmd.vdpa_vq_reset), + &comp, 0); + if (err) { + dev_dbg(dev, "Failed to reset vq %d, status %d: %pe\n", + qid, comp.status, ERR_PTR(err)); + return err; + } + + vq_info->avail_idx = le16_to_cpu(comp.vdpa_vq_reset.avail_index) ^ invert_idx; + vq_info->used_idx = le16_to_cpu(comp.vdpa_vq_reset.used_index) ^ invert_idx; + + return 0; +} diff --git a/drivers/vdpa/pds/cmds.h b/drivers/vdpa/pds/cmds.h new file mode 100644 index 0000000000000000000000000000000000000000..e24d85cb8f1cedfa20bf1b5a6c9e61dbfd565dc4 --- /dev/null +++ b/drivers/vdpa/pds/cmds.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* Copyright(c) 2023 Advanced Micro Devices, Inc */ + +#ifndef _VDPA_CMDS_H_ +#define _VDPA_CMDS_H_ + +int pds_vdpa_init_hw(struct pds_vdpa_device *pdsv); + +int pds_vdpa_cmd_reset(struct pds_vdpa_device *pdsv); +int pds_vdpa_cmd_set_status(struct pds_vdpa_device *pdsv, u8 status); +int pds_vdpa_cmd_set_mac(struct pds_vdpa_device *pdsv, u8 *mac); +int pds_vdpa_cmd_set_max_vq_pairs(struct pds_vdpa_device *pdsv, u16 max_vqp); +int pds_vdpa_cmd_init_vq(struct pds_vdpa_device *pdsv, u16 qid, u16 invert_idx, + struct pds_vdpa_vq_info *vq_info); +int pds_vdpa_cmd_reset_vq(struct pds_vdpa_device *pdsv, u16 qid, u16 invert_idx, + struct pds_vdpa_vq_info *vq_info); +int pds_vdpa_cmd_set_features(struct pds_vdpa_device *pdsv, u64 features); +#endif /* _VDPA_CMDS_H_ */ diff --git a/drivers/vdpa/pds/debugfs.c b/drivers/vdpa/pds/debugfs.c new file mode 100644 index 0000000000000000000000000000000000000000..21a0dc0cb607ca5768dab0bf982dbee1cab8b863 --- /dev/null +++ b/drivers/vdpa/pds/debugfs.c @@ -0,0 +1,289 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* Copyright(c) 2023 Advanced Micro Devices, Inc */ + +#include +#include + +#include +#include +#include +#include + +#include "aux_drv.h" +#include "vdpa_dev.h" +#include "debugfs.h" + +static struct dentry *dbfs_dir; + +void pds_vdpa_debugfs_create(void) +{ + dbfs_dir = debugfs_create_dir(PDS_VDPA_DRV_NAME, NULL); +} + +void pds_vdpa_debugfs_destroy(void) +{ + debugfs_remove_recursive(dbfs_dir); + dbfs_dir = NULL; +} + +#define PRINT_SBIT_NAME(__seq, __f, __name) \ + do { \ + if ((__f) & (__name)) \ + seq_printf(__seq, " %s", &#__name[16]); \ + } while (0) + +static void print_status_bits(struct seq_file *seq, u8 status) +{ + seq_puts(seq, "status:"); + PRINT_SBIT_NAME(seq, status, VIRTIO_CONFIG_S_ACKNOWLEDGE); + PRINT_SBIT_NAME(seq, status, VIRTIO_CONFIG_S_DRIVER); + PRINT_SBIT_NAME(seq, status, VIRTIO_CONFIG_S_DRIVER_OK); + PRINT_SBIT_NAME(seq, status, VIRTIO_CONFIG_S_FEATURES_OK); + PRINT_SBIT_NAME(seq, status, VIRTIO_CONFIG_S_NEEDS_RESET); + PRINT_SBIT_NAME(seq, status, VIRTIO_CONFIG_S_FAILED); + seq_puts(seq, "\n"); +} + +static void print_feature_bits_all(struct seq_file *seq, u64 features) +{ + int i; + + seq_puts(seq, "features:"); + + for (i = 0; i < (sizeof(u64) * 8); i++) { + u64 mask = BIT_ULL(i); + + switch (features & mask) { + case BIT_ULL(VIRTIO_NET_F_CSUM): + seq_puts(seq, " VIRTIO_NET_F_CSUM"); + break; + case BIT_ULL(VIRTIO_NET_F_GUEST_CSUM): + seq_puts(seq, " VIRTIO_NET_F_GUEST_CSUM"); + break; + case BIT_ULL(VIRTIO_NET_F_CTRL_GUEST_OFFLOADS): + seq_puts(seq, " VIRTIO_NET_F_CTRL_GUEST_OFFLOADS"); + break; + case BIT_ULL(VIRTIO_NET_F_MTU): + seq_puts(seq, " VIRTIO_NET_F_MTU"); + break; + case BIT_ULL(VIRTIO_NET_F_MAC): + seq_puts(seq, " VIRTIO_NET_F_MAC"); + break; + case BIT_ULL(VIRTIO_NET_F_GUEST_TSO4): + seq_puts(seq, " VIRTIO_NET_F_GUEST_TSO4"); + break; + case BIT_ULL(VIRTIO_NET_F_GUEST_TSO6): + seq_puts(seq, " VIRTIO_NET_F_GUEST_TSO6"); + break; + case BIT_ULL(VIRTIO_NET_F_GUEST_ECN): + seq_puts(seq, " VIRTIO_NET_F_GUEST_ECN"); + break; + case BIT_ULL(VIRTIO_NET_F_GUEST_UFO): + seq_puts(seq, " VIRTIO_NET_F_GUEST_UFO"); + break; + case BIT_ULL(VIRTIO_NET_F_HOST_TSO4): + seq_puts(seq, " VIRTIO_NET_F_HOST_TSO4"); + break; + case BIT_ULL(VIRTIO_NET_F_HOST_TSO6): + seq_puts(seq, " VIRTIO_NET_F_HOST_TSO6"); + break; + case BIT_ULL(VIRTIO_NET_F_HOST_ECN): + seq_puts(seq, " VIRTIO_NET_F_HOST_ECN"); + break; + case BIT_ULL(VIRTIO_NET_F_HOST_UFO): + seq_puts(seq, " VIRTIO_NET_F_HOST_UFO"); + break; + case BIT_ULL(VIRTIO_NET_F_MRG_RXBUF): + seq_puts(seq, " VIRTIO_NET_F_MRG_RXBUF"); + break; + case BIT_ULL(VIRTIO_NET_F_STATUS): + seq_puts(seq, " VIRTIO_NET_F_STATUS"); + break; + case BIT_ULL(VIRTIO_NET_F_CTRL_VQ): + seq_puts(seq, " VIRTIO_NET_F_CTRL_VQ"); + break; + case BIT_ULL(VIRTIO_NET_F_CTRL_RX): + seq_puts(seq, " VIRTIO_NET_F_CTRL_RX"); + break; + case BIT_ULL(VIRTIO_NET_F_CTRL_VLAN): + seq_puts(seq, " VIRTIO_NET_F_CTRL_VLAN"); + break; + case BIT_ULL(VIRTIO_NET_F_CTRL_RX_EXTRA): + seq_puts(seq, " VIRTIO_NET_F_CTRL_RX_EXTRA"); + break; + case BIT_ULL(VIRTIO_NET_F_GUEST_ANNOUNCE): + seq_puts(seq, " VIRTIO_NET_F_GUEST_ANNOUNCE"); + break; + case BIT_ULL(VIRTIO_NET_F_MQ): + seq_puts(seq, " VIRTIO_NET_F_MQ"); + break; + case BIT_ULL(VIRTIO_NET_F_CTRL_MAC_ADDR): + seq_puts(seq, " VIRTIO_NET_F_CTRL_MAC_ADDR"); + break; + case BIT_ULL(VIRTIO_NET_F_HASH_REPORT): + seq_puts(seq, " VIRTIO_NET_F_HASH_REPORT"); + break; + case BIT_ULL(VIRTIO_NET_F_RSS): + seq_puts(seq, " VIRTIO_NET_F_RSS"); + break; + case BIT_ULL(VIRTIO_NET_F_RSC_EXT): + seq_puts(seq, " VIRTIO_NET_F_RSC_EXT"); + break; + case BIT_ULL(VIRTIO_NET_F_STANDBY): + seq_puts(seq, " VIRTIO_NET_F_STANDBY"); + break; + case BIT_ULL(VIRTIO_NET_F_SPEED_DUPLEX): + seq_puts(seq, " VIRTIO_NET_F_SPEED_DUPLEX"); + break; + case BIT_ULL(VIRTIO_F_NOTIFY_ON_EMPTY): + seq_puts(seq, " VIRTIO_F_NOTIFY_ON_EMPTY"); + break; + case BIT_ULL(VIRTIO_F_ANY_LAYOUT): + seq_puts(seq, " VIRTIO_F_ANY_LAYOUT"); + break; + case BIT_ULL(VIRTIO_F_VERSION_1): + seq_puts(seq, " VIRTIO_F_VERSION_1"); + break; + case BIT_ULL(VIRTIO_F_ACCESS_PLATFORM): + seq_puts(seq, " VIRTIO_F_ACCESS_PLATFORM"); + break; + case BIT_ULL(VIRTIO_F_RING_PACKED): + seq_puts(seq, " VIRTIO_F_RING_PACKED"); + break; + case BIT_ULL(VIRTIO_F_ORDER_PLATFORM): + seq_puts(seq, " VIRTIO_F_ORDER_PLATFORM"); + break; + case BIT_ULL(VIRTIO_F_SR_IOV): + seq_puts(seq, " VIRTIO_F_SR_IOV"); + break; + case 0: + break; + default: + seq_printf(seq, " bit_%d", i); + break; + } + } + + seq_puts(seq, "\n"); +} + +void pds_vdpa_debugfs_add_pcidev(struct pds_vdpa_aux *vdpa_aux) +{ + vdpa_aux->dentry = debugfs_create_dir(pci_name(vdpa_aux->padev->vf_pdev), dbfs_dir); +} + +static int identity_show(struct seq_file *seq, void *v) +{ + struct pds_vdpa_aux *vdpa_aux = seq->private; + struct vdpa_mgmt_dev *mgmt; + + seq_printf(seq, "aux_dev: %s\n", + dev_name(&vdpa_aux->padev->aux_dev.dev)); + + mgmt = &vdpa_aux->vdpa_mdev; + seq_printf(seq, "max_vqs: %d\n", mgmt->max_supported_vqs); + seq_printf(seq, "config_attr_mask: %#llx\n", mgmt->config_attr_mask); + seq_printf(seq, "supported_features: %#llx\n", mgmt->supported_features); + print_feature_bits_all(seq, mgmt->supported_features); + + return 0; +} +DEFINE_SHOW_ATTRIBUTE(identity); + +void pds_vdpa_debugfs_add_ident(struct pds_vdpa_aux *vdpa_aux) +{ + debugfs_create_file("identity", 0400, vdpa_aux->dentry, + vdpa_aux, &identity_fops); +} + +static int config_show(struct seq_file *seq, void *v) +{ + struct pds_vdpa_device *pdsv = seq->private; + struct virtio_net_config vc; + u64 driver_features; + u8 status; + + memcpy_fromio(&vc, pdsv->vdpa_aux->vd_mdev.device, + sizeof(struct virtio_net_config)); + + seq_printf(seq, "mac: %pM\n", vc.mac); + seq_printf(seq, "max_virtqueue_pairs: %d\n", + __virtio16_to_cpu(true, vc.max_virtqueue_pairs)); + seq_printf(seq, "mtu: %d\n", __virtio16_to_cpu(true, vc.mtu)); + seq_printf(seq, "speed: %d\n", le32_to_cpu(vc.speed)); + seq_printf(seq, "duplex: %d\n", vc.duplex); + seq_printf(seq, "rss_max_key_size: %d\n", vc.rss_max_key_size); + seq_printf(seq, "rss_max_indirection_table_length: %d\n", + le16_to_cpu(vc.rss_max_indirection_table_length)); + seq_printf(seq, "supported_hash_types: %#x\n", + le32_to_cpu(vc.supported_hash_types)); + seq_printf(seq, "vn_status: %#x\n", + __virtio16_to_cpu(true, vc.status)); + + status = vp_modern_get_status(&pdsv->vdpa_aux->vd_mdev); + seq_printf(seq, "dev_status: %#x\n", status); + print_status_bits(seq, status); + + seq_printf(seq, "req_features: %#llx\n", pdsv->req_features); + print_feature_bits_all(seq, pdsv->req_features); + driver_features = vp_modern_get_driver_features(&pdsv->vdpa_aux->vd_mdev); + seq_printf(seq, "driver_features: %#llx\n", driver_features); + print_feature_bits_all(seq, driver_features); + seq_printf(seq, "vdpa_index: %d\n", pdsv->vdpa_index); + seq_printf(seq, "num_vqs: %d\n", pdsv->num_vqs); + + return 0; +} +DEFINE_SHOW_ATTRIBUTE(config); + +static int vq_show(struct seq_file *seq, void *v) +{ + struct pds_vdpa_vq_info *vq = seq->private; + + seq_printf(seq, "ready: %d\n", vq->ready); + seq_printf(seq, "desc_addr: %#llx\n", vq->desc_addr); + seq_printf(seq, "avail_addr: %#llx\n", vq->avail_addr); + seq_printf(seq, "used_addr: %#llx\n", vq->used_addr); + seq_printf(seq, "q_len: %d\n", vq->q_len); + seq_printf(seq, "qid: %d\n", vq->qid); + + seq_printf(seq, "doorbell: %#llx\n", vq->doorbell); + seq_printf(seq, "avail_idx: %d\n", vq->avail_idx); + seq_printf(seq, "used_idx: %d\n", vq->used_idx); + seq_printf(seq, "irq: %d\n", vq->irq); + seq_printf(seq, "irq-name: %s\n", vq->irq_name); + + return 0; +} +DEFINE_SHOW_ATTRIBUTE(vq); + +void pds_vdpa_debugfs_add_vdpadev(struct pds_vdpa_aux *vdpa_aux) +{ + int i; + + debugfs_create_file("config", 0400, vdpa_aux->dentry, vdpa_aux->pdsv, &config_fops); + + for (i = 0; i < vdpa_aux->pdsv->num_vqs; i++) { + char name[8]; + + snprintf(name, sizeof(name), "vq%02d", i); + debugfs_create_file(name, 0400, vdpa_aux->dentry, + &vdpa_aux->pdsv->vqs[i], &vq_fops); + } +} + +void pds_vdpa_debugfs_del_vdpadev(struct pds_vdpa_aux *vdpa_aux) +{ + debugfs_remove_recursive(vdpa_aux->dentry); + vdpa_aux->dentry = NULL; +} + +void pds_vdpa_debugfs_reset_vdpadev(struct pds_vdpa_aux *vdpa_aux) +{ + /* we don't keep track of the entries, so remove it all + * then rebuild the basics + */ + pds_vdpa_debugfs_del_vdpadev(vdpa_aux); + pds_vdpa_debugfs_add_pcidev(vdpa_aux); + pds_vdpa_debugfs_add_ident(vdpa_aux); +} diff --git a/drivers/vdpa/pds/debugfs.h b/drivers/vdpa/pds/debugfs.h new file mode 100644 index 0000000000000000000000000000000000000000..c088a4e8f1e92949f5db7811e2f773c79251147d --- /dev/null +++ b/drivers/vdpa/pds/debugfs.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2023 Advanced Micro Devices, Inc */ + +#ifndef _PDS_VDPA_DEBUGFS_H_ +#define _PDS_VDPA_DEBUGFS_H_ + +#include + +void pds_vdpa_debugfs_create(void); +void pds_vdpa_debugfs_destroy(void); +void pds_vdpa_debugfs_add_pcidev(struct pds_vdpa_aux *vdpa_aux); +void pds_vdpa_debugfs_add_ident(struct pds_vdpa_aux *vdpa_aux); +void pds_vdpa_debugfs_add_vdpadev(struct pds_vdpa_aux *vdpa_aux); +void pds_vdpa_debugfs_del_vdpadev(struct pds_vdpa_aux *vdpa_aux); +void pds_vdpa_debugfs_reset_vdpadev(struct pds_vdpa_aux *vdpa_aux); + +#endif /* _PDS_VDPA_DEBUGFS_H_ */ diff --git a/drivers/vdpa/pds/vdpa_dev.c b/drivers/vdpa/pds/vdpa_dev.c new file mode 100644 index 0000000000000000000000000000000000000000..5071a4d58f8db37f6d619d2f2d42f44d7f5188d6 --- /dev/null +++ b/drivers/vdpa/pds/vdpa_dev.c @@ -0,0 +1,769 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* Copyright(c) 2023 Advanced Micro Devices, Inc */ + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "vdpa_dev.h" +#include "aux_drv.h" +#include "cmds.h" +#include "debugfs.h" + +static u64 pds_vdpa_get_driver_features(struct vdpa_device *vdpa_dev); + +static struct pds_vdpa_device *vdpa_to_pdsv(struct vdpa_device *vdpa_dev) +{ + return container_of(vdpa_dev, struct pds_vdpa_device, vdpa_dev); +} + +static int pds_vdpa_notify_handler(struct notifier_block *nb, + unsigned long ecode, + void *data) +{ + struct pds_vdpa_device *pdsv = container_of(nb, struct pds_vdpa_device, nb); + struct device *dev = &pdsv->vdpa_aux->padev->aux_dev.dev; + + dev_dbg(dev, "%s: event code %lu\n", __func__, ecode); + + if (ecode == PDS_EVENT_RESET || ecode == PDS_EVENT_LINK_CHANGE) { + if (pdsv->config_cb.callback) + pdsv->config_cb.callback(pdsv->config_cb.private); + } + + return 0; +} + +static int pds_vdpa_register_event_handler(struct pds_vdpa_device *pdsv) +{ + struct device *dev = &pdsv->vdpa_aux->padev->aux_dev.dev; + struct notifier_block *nb = &pdsv->nb; + int err; + + if (!nb->notifier_call) { + nb->notifier_call = pds_vdpa_notify_handler; + err = pdsc_register_notify(nb); + if (err) { + nb->notifier_call = NULL; + dev_err(dev, "failed to register pds event handler: %ps\n", + ERR_PTR(err)); + return -EINVAL; + } + dev_dbg(dev, "pds event handler registered\n"); + } + + return 0; +} + +static void pds_vdpa_unregister_event_handler(struct pds_vdpa_device *pdsv) +{ + if (pdsv->nb.notifier_call) { + pdsc_unregister_notify(&pdsv->nb); + pdsv->nb.notifier_call = NULL; + } +} + +static int pds_vdpa_set_vq_address(struct vdpa_device *vdpa_dev, u16 qid, + u64 desc_addr, u64 driver_addr, u64 device_addr) +{ + struct pds_vdpa_device *pdsv = vdpa_to_pdsv(vdpa_dev); + + pdsv->vqs[qid].desc_addr = desc_addr; + pdsv->vqs[qid].avail_addr = driver_addr; + pdsv->vqs[qid].used_addr = device_addr; + + return 0; +} + +static void pds_vdpa_set_vq_num(struct vdpa_device *vdpa_dev, u16 qid, u32 num) +{ + struct pds_vdpa_device *pdsv = vdpa_to_pdsv(vdpa_dev); + + pdsv->vqs[qid].q_len = num; +} + +static void pds_vdpa_kick_vq(struct vdpa_device *vdpa_dev, u16 qid) +{ + struct pds_vdpa_device *pdsv = vdpa_to_pdsv(vdpa_dev); + + iowrite16(qid, pdsv->vqs[qid].notify); +} + +static void pds_vdpa_set_vq_cb(struct vdpa_device *vdpa_dev, u16 qid, + struct vdpa_callback *cb) +{ + struct pds_vdpa_device *pdsv = vdpa_to_pdsv(vdpa_dev); + + pdsv->vqs[qid].event_cb = *cb; +} + +static irqreturn_t pds_vdpa_isr(int irq, void *data) +{ + struct pds_vdpa_vq_info *vq; + + vq = data; + if (vq->event_cb.callback) + vq->event_cb.callback(vq->event_cb.private); + + return IRQ_HANDLED; +} + +static void pds_vdpa_release_irq(struct pds_vdpa_device *pdsv, int qid) +{ + if (pdsv->vqs[qid].irq == VIRTIO_MSI_NO_VECTOR) + return; + + free_irq(pdsv->vqs[qid].irq, &pdsv->vqs[qid]); + pdsv->vqs[qid].irq = VIRTIO_MSI_NO_VECTOR; +} + +static void pds_vdpa_set_vq_ready(struct vdpa_device *vdpa_dev, u16 qid, bool ready) +{ + struct pds_vdpa_device *pdsv = vdpa_to_pdsv(vdpa_dev); + struct pci_dev *pdev = pdsv->vdpa_aux->padev->vf_pdev; + struct device *dev = &pdsv->vdpa_dev.dev; + u64 driver_features; + u16 invert_idx = 0; + int irq; + int err; + + dev_dbg(dev, "%s: qid %d ready %d => %d\n", + __func__, qid, pdsv->vqs[qid].ready, ready); + if (ready == pdsv->vqs[qid].ready) + return; + + driver_features = pds_vdpa_get_driver_features(vdpa_dev); + if (driver_features & BIT_ULL(VIRTIO_F_RING_PACKED)) + invert_idx = PDS_VDPA_PACKED_INVERT_IDX; + + if (ready) { + irq = pci_irq_vector(pdev, qid); + snprintf(pdsv->vqs[qid].irq_name, sizeof(pdsv->vqs[qid].irq_name), + "vdpa-%s-%d", dev_name(dev), qid); + + err = request_irq(irq, pds_vdpa_isr, 0, + pdsv->vqs[qid].irq_name, &pdsv->vqs[qid]); + if (err) { + dev_err(dev, "%s: no irq for qid %d: %pe\n", + __func__, qid, ERR_PTR(err)); + return; + } + pdsv->vqs[qid].irq = irq; + + /* Pass vq setup info to DSC using adminq to gather up and + * send all info at once so FW can do its full set up in + * one easy operation + */ + err = pds_vdpa_cmd_init_vq(pdsv, qid, invert_idx, &pdsv->vqs[qid]); + if (err) { + dev_err(dev, "Failed to init vq %d: %pe\n", + qid, ERR_PTR(err)); + pds_vdpa_release_irq(pdsv, qid); + ready = false; + } + } else { + err = pds_vdpa_cmd_reset_vq(pdsv, qid, invert_idx, &pdsv->vqs[qid]); + if (err) + dev_err(dev, "%s: reset_vq failed qid %d: %pe\n", + __func__, qid, ERR_PTR(err)); + pds_vdpa_release_irq(pdsv, qid); + } + + pdsv->vqs[qid].ready = ready; +} + +static bool pds_vdpa_get_vq_ready(struct vdpa_device *vdpa_dev, u16 qid) +{ + struct pds_vdpa_device *pdsv = vdpa_to_pdsv(vdpa_dev); + + return pdsv->vqs[qid].ready; +} + +static int pds_vdpa_set_vq_state(struct vdpa_device *vdpa_dev, u16 qid, + const struct vdpa_vq_state *state) +{ + struct pds_vdpa_device *pdsv = vdpa_to_pdsv(vdpa_dev); + struct pds_auxiliary_dev *padev = pdsv->vdpa_aux->padev; + struct device *dev = &padev->aux_dev.dev; + u64 driver_features; + u16 avail; + u16 used; + + if (pdsv->vqs[qid].ready) { + dev_err(dev, "Setting device position is denied while vq is enabled\n"); + return -EINVAL; + } + + driver_features = pds_vdpa_get_driver_features(vdpa_dev); + if (driver_features & BIT_ULL(VIRTIO_F_RING_PACKED)) { + avail = state->packed.last_avail_idx | + (state->packed.last_avail_counter << 15); + used = state->packed.last_used_idx | + (state->packed.last_used_counter << 15); + + /* The avail and used index are stored with the packed wrap + * counter bit inverted. This way, in case set_vq_state is + * not called, the initial value can be set to zero prior to + * feature negotiation, and it is good for both packed and + * split vq. + */ + avail ^= PDS_VDPA_PACKED_INVERT_IDX; + used ^= PDS_VDPA_PACKED_INVERT_IDX; + } else { + avail = state->split.avail_index; + /* state->split does not provide a used_index: + * the vq will be set to "empty" here, and the vq will read + * the current used index the next time the vq is kicked. + */ + used = avail; + } + + if (used != avail) { + dev_dbg(dev, "Setting used equal to avail, for interoperability\n"); + used = avail; + } + + pdsv->vqs[qid].avail_idx = avail; + pdsv->vqs[qid].used_idx = used; + + return 0; +} + +static int pds_vdpa_get_vq_state(struct vdpa_device *vdpa_dev, u16 qid, + struct vdpa_vq_state *state) +{ + struct pds_vdpa_device *pdsv = vdpa_to_pdsv(vdpa_dev); + struct pds_auxiliary_dev *padev = pdsv->vdpa_aux->padev; + struct device *dev = &padev->aux_dev.dev; + u64 driver_features; + u16 avail; + u16 used; + + if (pdsv->vqs[qid].ready) { + dev_err(dev, "Getting device position is denied while vq is enabled\n"); + return -EINVAL; + } + + avail = pdsv->vqs[qid].avail_idx; + used = pdsv->vqs[qid].used_idx; + + driver_features = pds_vdpa_get_driver_features(vdpa_dev); + if (driver_features & BIT_ULL(VIRTIO_F_RING_PACKED)) { + avail ^= PDS_VDPA_PACKED_INVERT_IDX; + used ^= PDS_VDPA_PACKED_INVERT_IDX; + + state->packed.last_avail_idx = avail & 0x7fff; + state->packed.last_avail_counter = avail >> 15; + state->packed.last_used_idx = used & 0x7fff; + state->packed.last_used_counter = used >> 15; + } else { + state->split.avail_index = avail; + /* state->split does not provide a used_index. */ + } + + return 0; +} + +static struct vdpa_notification_area +pds_vdpa_get_vq_notification(struct vdpa_device *vdpa_dev, u16 qid) +{ + struct pds_vdpa_device *pdsv = vdpa_to_pdsv(vdpa_dev); + struct virtio_pci_modern_device *vd_mdev; + struct vdpa_notification_area area; + + area.addr = pdsv->vqs[qid].notify_pa; + + vd_mdev = &pdsv->vdpa_aux->vd_mdev; + if (!vd_mdev->notify_offset_multiplier) + area.size = PDS_PAGE_SIZE; + else + area.size = vd_mdev->notify_offset_multiplier; + + return area; +} + +static int pds_vdpa_get_vq_irq(struct vdpa_device *vdpa_dev, u16 qid) +{ + struct pds_vdpa_device *pdsv = vdpa_to_pdsv(vdpa_dev); + + return pdsv->vqs[qid].irq; +} + +static u32 pds_vdpa_get_vq_align(struct vdpa_device *vdpa_dev) +{ + return PDS_PAGE_SIZE; +} + +static u32 pds_vdpa_get_vq_group(struct vdpa_device *vdpa_dev, u16 idx) +{ + return 0; +} + +static u64 pds_vdpa_get_device_features(struct vdpa_device *vdpa_dev) +{ + struct pds_vdpa_device *pdsv = vdpa_to_pdsv(vdpa_dev); + + return pdsv->supported_features; +} + +static int pds_vdpa_set_driver_features(struct vdpa_device *vdpa_dev, u64 features) +{ + struct pds_vdpa_device *pdsv = vdpa_to_pdsv(vdpa_dev); + struct device *dev = &pdsv->vdpa_dev.dev; + u64 driver_features; + u64 nego_features; + u64 missing; + + if (!(features & BIT_ULL(VIRTIO_F_ACCESS_PLATFORM)) && features) { + dev_err(dev, "VIRTIO_F_ACCESS_PLATFORM is not negotiated\n"); + return -EOPNOTSUPP; + } + + pdsv->req_features = features; + + /* Check for valid feature bits */ + nego_features = features & le64_to_cpu(pdsv->vdpa_aux->ident.hw_features); + missing = pdsv->req_features & ~nego_features; + if (missing) { + dev_err(dev, "Can't support all requested features in %#llx, missing %#llx features\n", + pdsv->req_features, missing); + return -EOPNOTSUPP; + } + + driver_features = pds_vdpa_get_driver_features(vdpa_dev); + dev_dbg(dev, "%s: %#llx => %#llx\n", + __func__, driver_features, nego_features); + + if (driver_features == nego_features) + return 0; + + vp_modern_set_features(&pdsv->vdpa_aux->vd_mdev, nego_features); + + return 0; +} + +static u64 pds_vdpa_get_driver_features(struct vdpa_device *vdpa_dev) +{ + struct pds_vdpa_device *pdsv = vdpa_to_pdsv(vdpa_dev); + + return vp_modern_get_driver_features(&pdsv->vdpa_aux->vd_mdev); +} + +static void pds_vdpa_set_config_cb(struct vdpa_device *vdpa_dev, + struct vdpa_callback *cb) +{ + struct pds_vdpa_device *pdsv = vdpa_to_pdsv(vdpa_dev); + + pdsv->config_cb.callback = cb->callback; + pdsv->config_cb.private = cb->private; +} + +static u16 pds_vdpa_get_vq_num_max(struct vdpa_device *vdpa_dev) +{ + struct pds_vdpa_device *pdsv = vdpa_to_pdsv(vdpa_dev); + + /* qemu has assert() that vq_num_max <= VIRTQUEUE_MAX_SIZE (1024) */ + return min_t(u16, 1024, BIT(le16_to_cpu(pdsv->vdpa_aux->ident.max_qlen))); +} + +static u32 pds_vdpa_get_device_id(struct vdpa_device *vdpa_dev) +{ + return VIRTIO_ID_NET; +} + +static u32 pds_vdpa_get_vendor_id(struct vdpa_device *vdpa_dev) +{ + return PCI_VENDOR_ID_PENSANDO; +} + +static u8 pds_vdpa_get_status(struct vdpa_device *vdpa_dev) +{ + struct pds_vdpa_device *pdsv = vdpa_to_pdsv(vdpa_dev); + + return vp_modern_get_status(&pdsv->vdpa_aux->vd_mdev); +} + +static void pds_vdpa_set_status(struct vdpa_device *vdpa_dev, u8 status) +{ + struct pds_vdpa_device *pdsv = vdpa_to_pdsv(vdpa_dev); + struct device *dev = &pdsv->vdpa_dev.dev; + u8 old_status; + int i; + + old_status = pds_vdpa_get_status(vdpa_dev); + dev_dbg(dev, "%s: old %#x new %#x\n", __func__, old_status, status); + + pds_vdpa_cmd_set_status(pdsv, status); + + /* Note: still working with FW on the need for this reset cmd */ + if (status == 0) { + pds_vdpa_cmd_reset(pdsv); + + for (i = 0; i < pdsv->num_vqs; i++) { + pdsv->vqs[i].avail_idx = 0; + pdsv->vqs[i].used_idx = 0; + } + } + + if (status & ~old_status & VIRTIO_CONFIG_S_FEATURES_OK) { + for (i = 0; i < pdsv->num_vqs; i++) { + pdsv->vqs[i].notify = + vp_modern_map_vq_notify(&pdsv->vdpa_aux->vd_mdev, + i, &pdsv->vqs[i].notify_pa); + } + } +} + +static int pds_vdpa_reset(struct vdpa_device *vdpa_dev) +{ + struct pds_vdpa_device *pdsv = vdpa_to_pdsv(vdpa_dev); + struct device *dev; + int err = 0; + u8 status; + int i; + + dev = &pdsv->vdpa_aux->padev->aux_dev.dev; + status = pds_vdpa_get_status(vdpa_dev); + + if (status == 0) + return 0; + + if (status & VIRTIO_CONFIG_S_DRIVER_OK) { + /* Reset the vqs */ + for (i = 0; i < pdsv->num_vqs && !err; i++) { + err = pds_vdpa_cmd_reset_vq(pdsv, i, 0, &pdsv->vqs[i]); + if (err) + dev_err(dev, "%s: reset_vq failed qid %d: %pe\n", + __func__, i, ERR_PTR(err)); + pds_vdpa_release_irq(pdsv, i); + memset(&pdsv->vqs[i], 0, sizeof(pdsv->vqs[0])); + pdsv->vqs[i].ready = false; + } + } + + pds_vdpa_set_status(vdpa_dev, 0); + + return 0; +} + +static size_t pds_vdpa_get_config_size(struct vdpa_device *vdpa_dev) +{ + return sizeof(struct virtio_net_config); +} + +static void pds_vdpa_get_config(struct vdpa_device *vdpa_dev, + unsigned int offset, + void *buf, unsigned int len) +{ + struct pds_vdpa_device *pdsv = vdpa_to_pdsv(vdpa_dev); + void __iomem *device; + + if (offset + len > sizeof(struct virtio_net_config)) { + WARN(true, "%s: bad read, offset %d len %d\n", __func__, offset, len); + return; + } + + device = pdsv->vdpa_aux->vd_mdev.device; + memcpy_fromio(buf, device + offset, len); +} + +static void pds_vdpa_set_config(struct vdpa_device *vdpa_dev, + unsigned int offset, const void *buf, + unsigned int len) +{ + struct pds_vdpa_device *pdsv = vdpa_to_pdsv(vdpa_dev); + void __iomem *device; + + if (offset + len > sizeof(struct virtio_net_config)) { + WARN(true, "%s: bad read, offset %d len %d\n", __func__, offset, len); + return; + } + + device = pdsv->vdpa_aux->vd_mdev.device; + memcpy_toio(device + offset, buf, len); +} + +static const struct vdpa_config_ops pds_vdpa_ops = { + .set_vq_address = pds_vdpa_set_vq_address, + .set_vq_num = pds_vdpa_set_vq_num, + .kick_vq = pds_vdpa_kick_vq, + .set_vq_cb = pds_vdpa_set_vq_cb, + .set_vq_ready = pds_vdpa_set_vq_ready, + .get_vq_ready = pds_vdpa_get_vq_ready, + .set_vq_state = pds_vdpa_set_vq_state, + .get_vq_state = pds_vdpa_get_vq_state, + .get_vq_notification = pds_vdpa_get_vq_notification, + .get_vq_irq = pds_vdpa_get_vq_irq, + .get_vq_align = pds_vdpa_get_vq_align, + .get_vq_group = pds_vdpa_get_vq_group, + + .get_device_features = pds_vdpa_get_device_features, + .set_driver_features = pds_vdpa_set_driver_features, + .get_driver_features = pds_vdpa_get_driver_features, + .set_config_cb = pds_vdpa_set_config_cb, + .get_vq_num_max = pds_vdpa_get_vq_num_max, + .get_device_id = pds_vdpa_get_device_id, + .get_vendor_id = pds_vdpa_get_vendor_id, + .get_status = pds_vdpa_get_status, + .set_status = pds_vdpa_set_status, + .reset = pds_vdpa_reset, + .get_config_size = pds_vdpa_get_config_size, + .get_config = pds_vdpa_get_config, + .set_config = pds_vdpa_set_config, +}; +static struct virtio_device_id pds_vdpa_id_table[] = { + {VIRTIO_ID_NET, VIRTIO_DEV_ANY_ID}, + {0}, +}; + +static int pds_vdpa_dev_add(struct vdpa_mgmt_dev *mdev, const char *name, + const struct vdpa_dev_set_config *add_config) +{ + struct pds_vdpa_aux *vdpa_aux; + struct pds_vdpa_device *pdsv; + struct vdpa_mgmt_dev *mgmt; + u16 fw_max_vqs, vq_pairs; + struct device *dma_dev; + struct pci_dev *pdev; + struct device *dev; + u8 mac[ETH_ALEN]; + int err; + int i; + + vdpa_aux = container_of(mdev, struct pds_vdpa_aux, vdpa_mdev); + dev = &vdpa_aux->padev->aux_dev.dev; + mgmt = &vdpa_aux->vdpa_mdev; + + if (vdpa_aux->pdsv) { + dev_warn(dev, "Multiple vDPA devices on a VF is not supported.\n"); + return -EOPNOTSUPP; + } + + pdsv = vdpa_alloc_device(struct pds_vdpa_device, vdpa_dev, + dev, &pds_vdpa_ops, 1, 1, name, false); + if (IS_ERR(pdsv)) { + dev_err(dev, "Failed to allocate vDPA structure: %pe\n", pdsv); + return PTR_ERR(pdsv); + } + + vdpa_aux->pdsv = pdsv; + pdsv->vdpa_aux = vdpa_aux; + + pdev = vdpa_aux->padev->vf_pdev; + dma_dev = &pdev->dev; + pdsv->vdpa_dev.dma_dev = dma_dev; + + pdsv->supported_features = mgmt->supported_features; + + if (add_config->mask & BIT_ULL(VDPA_ATTR_DEV_FEATURES)) { + u64 unsupp_features = + add_config->device_features & ~mgmt->supported_features; + + if (unsupp_features) { + dev_err(dev, "Unsupported features: %#llx\n", unsupp_features); + err = -EOPNOTSUPP; + goto err_unmap; + } + + pdsv->supported_features = add_config->device_features; + } + + err = pds_vdpa_cmd_reset(pdsv); + if (err) { + dev_err(dev, "Failed to reset hw: %pe\n", ERR_PTR(err)); + goto err_unmap; + } + + err = pds_vdpa_init_hw(pdsv); + if (err) { + dev_err(dev, "Failed to init hw: %pe\n", ERR_PTR(err)); + goto err_unmap; + } + + fw_max_vqs = le16_to_cpu(pdsv->vdpa_aux->ident.max_vqs); + vq_pairs = fw_max_vqs / 2; + + /* Make sure we have the queues being requested */ + if (add_config->mask & (1 << VDPA_ATTR_DEV_NET_CFG_MAX_VQP)) + vq_pairs = add_config->net.max_vq_pairs; + + pdsv->num_vqs = 2 * vq_pairs; + if (pdsv->supported_features & BIT_ULL(VIRTIO_NET_F_CTRL_VQ)) + pdsv->num_vqs++; + + if (pdsv->num_vqs > fw_max_vqs) { + dev_err(dev, "%s: queue count requested %u greater than max %u\n", + __func__, pdsv->num_vqs, fw_max_vqs); + err = -ENOSPC; + goto err_unmap; + } + + if (pdsv->num_vqs != fw_max_vqs) { + err = pds_vdpa_cmd_set_max_vq_pairs(pdsv, vq_pairs); + if (err) { + dev_err(dev, "Failed to set max_vq_pairs: %pe\n", + ERR_PTR(err)); + goto err_unmap; + } + } + + /* Set a mac, either from the user config if provided + * or set a random mac if default is 00:..:00 + */ + if (add_config->mask & BIT_ULL(VDPA_ATTR_DEV_NET_CFG_MACADDR)) { + ether_addr_copy(mac, add_config->net.mac); + pds_vdpa_cmd_set_mac(pdsv, mac); + } else { + struct virtio_net_config __iomem *vc; + + vc = pdsv->vdpa_aux->vd_mdev.device; + memcpy_fromio(mac, vc->mac, sizeof(mac)); + if (is_zero_ether_addr(mac)) { + eth_random_addr(mac); + dev_info(dev, "setting random mac %pM\n", mac); + pds_vdpa_cmd_set_mac(pdsv, mac); + } + } + + for (i = 0; i < pdsv->num_vqs; i++) { + pdsv->vqs[i].qid = i; + pdsv->vqs[i].pdsv = pdsv; + pdsv->vqs[i].irq = VIRTIO_MSI_NO_VECTOR; + pdsv->vqs[i].notify = vp_modern_map_vq_notify(&pdsv->vdpa_aux->vd_mdev, + i, &pdsv->vqs[i].notify_pa); + } + + pdsv->vdpa_dev.mdev = &vdpa_aux->vdpa_mdev; + + err = pds_vdpa_register_event_handler(pdsv); + if (err) { + dev_err(dev, "Failed to register for PDS events: %pe\n", ERR_PTR(err)); + goto err_unmap; + } + + /* We use the _vdpa_register_device() call rather than the + * vdpa_register_device() to avoid a deadlock because our + * dev_add() is called with the vdpa_dev_lock already set + * by vdpa_nl_cmd_dev_add_set_doit() + */ + err = _vdpa_register_device(&pdsv->vdpa_dev, pdsv->num_vqs); + if (err) { + dev_err(dev, "Failed to register to vDPA bus: %pe\n", ERR_PTR(err)); + goto err_unevent; + } + + pds_vdpa_debugfs_add_vdpadev(vdpa_aux); + + return 0; + +err_unevent: + pds_vdpa_unregister_event_handler(pdsv); +err_unmap: + put_device(&pdsv->vdpa_dev.dev); + vdpa_aux->pdsv = NULL; + return err; +} + +static void pds_vdpa_dev_del(struct vdpa_mgmt_dev *mdev, + struct vdpa_device *vdpa_dev) +{ + struct pds_vdpa_device *pdsv = vdpa_to_pdsv(vdpa_dev); + struct pds_vdpa_aux *vdpa_aux; + + pds_vdpa_unregister_event_handler(pdsv); + + vdpa_aux = container_of(mdev, struct pds_vdpa_aux, vdpa_mdev); + _vdpa_unregister_device(vdpa_dev); + + pds_vdpa_cmd_reset(vdpa_aux->pdsv); + pds_vdpa_debugfs_reset_vdpadev(vdpa_aux); + + vdpa_aux->pdsv = NULL; + + dev_info(&vdpa_aux->padev->aux_dev.dev, "Removed vdpa device\n"); +} + +static const struct vdpa_mgmtdev_ops pds_vdpa_mgmt_dev_ops = { + .dev_add = pds_vdpa_dev_add, + .dev_del = pds_vdpa_dev_del +}; + +int pds_vdpa_get_mgmt_info(struct pds_vdpa_aux *vdpa_aux) +{ + union pds_core_adminq_cmd cmd = { + .vdpa_ident.opcode = PDS_VDPA_CMD_IDENT, + .vdpa_ident.vf_id = cpu_to_le16(vdpa_aux->vf_id), + }; + union pds_core_adminq_comp comp = {}; + struct vdpa_mgmt_dev *mgmt; + struct pci_dev *pf_pdev; + struct device *pf_dev; + struct pci_dev *pdev; + dma_addr_t ident_pa; + struct device *dev; + u16 dev_intrs; + u16 max_vqs; + int err; + + dev = &vdpa_aux->padev->aux_dev.dev; + pdev = vdpa_aux->padev->vf_pdev; + mgmt = &vdpa_aux->vdpa_mdev; + + /* Get resource info through the PF's adminq. It is a block of info, + * so we need to map some memory for PF to make available to the + * firmware for writing the data. + */ + pf_pdev = pci_physfn(vdpa_aux->padev->vf_pdev); + pf_dev = &pf_pdev->dev; + ident_pa = dma_map_single(pf_dev, &vdpa_aux->ident, + sizeof(vdpa_aux->ident), DMA_FROM_DEVICE); + if (dma_mapping_error(pf_dev, ident_pa)) { + dev_err(dev, "Failed to map ident space\n"); + return -ENOMEM; + } + + cmd.vdpa_ident.ident_pa = cpu_to_le64(ident_pa); + cmd.vdpa_ident.len = cpu_to_le32(sizeof(vdpa_aux->ident)); + err = pds_client_adminq_cmd(vdpa_aux->padev, &cmd, + sizeof(cmd.vdpa_ident), &comp, 0); + dma_unmap_single(pf_dev, ident_pa, + sizeof(vdpa_aux->ident), DMA_FROM_DEVICE); + if (err) { + dev_err(dev, "Failed to ident hw, status %d: %pe\n", + comp.status, ERR_PTR(err)); + return err; + } + + max_vqs = le16_to_cpu(vdpa_aux->ident.max_vqs); + dev_intrs = pci_msix_vec_count(pdev); + dev_dbg(dev, "ident.max_vqs %d dev_intrs %d\n", max_vqs, dev_intrs); + + max_vqs = min_t(u16, dev_intrs, max_vqs); + mgmt->max_supported_vqs = min_t(u16, PDS_VDPA_MAX_QUEUES, max_vqs); + vdpa_aux->nintrs = mgmt->max_supported_vqs; + + mgmt->ops = &pds_vdpa_mgmt_dev_ops; + mgmt->id_table = pds_vdpa_id_table; + mgmt->device = dev; + mgmt->supported_features = le64_to_cpu(vdpa_aux->ident.hw_features); + mgmt->config_attr_mask = BIT_ULL(VDPA_ATTR_DEV_NET_CFG_MACADDR); + mgmt->config_attr_mask |= BIT_ULL(VDPA_ATTR_DEV_NET_CFG_MAX_VQP); + mgmt->config_attr_mask |= BIT_ULL(VDPA_ATTR_DEV_FEATURES); + + err = pci_alloc_irq_vectors(pdev, vdpa_aux->nintrs, vdpa_aux->nintrs, + PCI_IRQ_MSIX); + if (err < 0) { + dev_err(dev, "Couldn't get %d msix vectors: %pe\n", + vdpa_aux->nintrs, ERR_PTR(err)); + return err; + } + vdpa_aux->nintrs = err; + + return 0; +} diff --git a/drivers/vdpa/pds/vdpa_dev.h b/drivers/vdpa/pds/vdpa_dev.h new file mode 100644 index 0000000000000000000000000000000000000000..a1bc37de953746e1fc9250308bf81a701304e1fe --- /dev/null +++ b/drivers/vdpa/pds/vdpa_dev.h @@ -0,0 +1,49 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* Copyright(c) 2023 Advanced Micro Devices, Inc */ + +#ifndef _VDPA_DEV_H_ +#define _VDPA_DEV_H_ + +#include +#include + +struct pds_vdpa_vq_info { + bool ready; + u64 desc_addr; + u64 avail_addr; + u64 used_addr; + u32 q_len; + u16 qid; + int irq; + char irq_name[32]; + + void __iomem *notify; + dma_addr_t notify_pa; + + u64 doorbell; + u16 avail_idx; + u16 used_idx; + + struct vdpa_callback event_cb; + struct pds_vdpa_device *pdsv; +}; + +#define PDS_VDPA_MAX_QUEUES 65 +#define PDS_VDPA_MAX_QLEN 32768 +struct pds_vdpa_device { + struct vdpa_device vdpa_dev; + struct pds_vdpa_aux *vdpa_aux; + + struct pds_vdpa_vq_info vqs[PDS_VDPA_MAX_QUEUES]; + u64 supported_features; /* specified device features */ + u64 req_features; /* features requested by vdpa */ + u8 vdpa_index; /* rsvd for future subdevice use */ + u8 num_vqs; /* num vqs in use */ + struct vdpa_callback config_cb; + struct notifier_block nb; +}; + +#define PDS_VDPA_PACKED_INVERT_IDX 0x8000 + +int pds_vdpa_get_mgmt_info(struct pds_vdpa_aux *vdpa_aux); +#endif /* _VDPA_DEV_H_ */ diff --git a/drivers/vdpa/solidrun/snet_ctrl.c b/drivers/vdpa/solidrun/snet_ctrl.c index 3858738643b40750a0a29d7ba386ab0a2efe2e04..3cef2571d15d3dd62354df713e6321c9cb0f761f 100644 --- a/drivers/vdpa/solidrun/snet_ctrl.c +++ b/drivers/vdpa/solidrun/snet_ctrl.c @@ -16,6 +16,7 @@ enum snet_ctrl_opcodes { SNET_CTRL_OP_DESTROY = 1, SNET_CTRL_OP_READ_VQ_STATE, SNET_CTRL_OP_SUSPEND, + SNET_CTRL_OP_RESUME, }; #define SNET_CTRL_TIMEOUT 2000000 @@ -328,3 +329,8 @@ int snet_suspend_dev(struct snet *snet) { return snet_send_ctrl_msg(snet, SNET_CTRL_OP_SUSPEND, 0); } + +int snet_resume_dev(struct snet *snet) +{ + return snet_send_ctrl_msg(snet, SNET_CTRL_OP_RESUME, 0); +} diff --git a/drivers/vdpa/solidrun/snet_hwmon.c b/drivers/vdpa/solidrun/snet_hwmon.c index 42c87387a0f1a7983a6278719b89b11170fa8e09..af531a3390824f00b17fd531ecf43ec4ec7e2df0 100644 --- a/drivers/vdpa/solidrun/snet_hwmon.c +++ b/drivers/vdpa/solidrun/snet_hwmon.c @@ -159,7 +159,7 @@ static const struct hwmon_ops snet_hwmon_ops = { .read_string = snet_hwmon_read_string }; -static const struct hwmon_channel_info *snet_hwmon_info[] = { +static const struct hwmon_channel_info * const snet_hwmon_info[] = { HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_CRIT | HWMON_T_LABEL, HWMON_T_INPUT | HWMON_T_CRIT | HWMON_T_LABEL), HWMON_CHANNEL_INFO(power, HWMON_P_INPUT | HWMON_P_LABEL), diff --git a/drivers/vdpa/solidrun/snet_main.c b/drivers/vdpa/solidrun/snet_main.c index cdcd84ce4f5a95b1037fd1b0de900c7876540766..99428a04068d2d4f1c3507455a63dd522187b745 100644 --- a/drivers/vdpa/solidrun/snet_main.c +++ b/drivers/vdpa/solidrun/snet_main.c @@ -509,6 +509,20 @@ static int snet_suspend(struct vdpa_device *vdev) return ret; } +static int snet_resume(struct vdpa_device *vdev) +{ + struct snet *snet = vdpa_to_snet(vdev); + int ret; + + ret = snet_resume_dev(snet); + if (ret) + SNET_ERR(snet->pdev, "SNET[%u] resume failed, err: %d\n", snet->sid, ret); + else + SNET_DBG(snet->pdev, "Resume SNET[%u] device\n", snet->sid); + + return ret; +} + static const struct vdpa_config_ops snet_config_ops = { .set_vq_address = snet_set_vq_address, .set_vq_num = snet_set_vq_num, @@ -536,6 +550,7 @@ static const struct vdpa_config_ops snet_config_ops = { .get_config = snet_get_config, .set_config = snet_set_config, .suspend = snet_suspend, + .resume = snet_resume, }; static int psnet_open_pf_bar(struct pci_dev *pdev, struct psnet *psnet) diff --git a/drivers/vdpa/solidrun/snet_vdpa.h b/drivers/vdpa/solidrun/snet_vdpa.h index 3c78d4e7d4857027870568d1705e4c0e626cfea8..36ac285835ea85790735d867dcec1b774b6a01d0 100644 --- a/drivers/vdpa/solidrun/snet_vdpa.h +++ b/drivers/vdpa/solidrun/snet_vdpa.h @@ -204,5 +204,6 @@ void snet_ctrl_clear(struct snet *snet); int snet_destroy_dev(struct snet *snet); int snet_read_vq_state(struct snet *snet, u16 idx, struct vdpa_vq_state *state); int snet_suspend_dev(struct snet *snet); +int snet_resume_dev(struct snet *snet); #endif //_SNET_VDPA_H_ diff --git a/drivers/vdpa/vdpa_user/vduse_dev.c b/drivers/vdpa/vdpa_user/vduse_dev.c index 5f5c21674fdce5050fa1bc0c672b3b3606871da9..dc38ed21319da92201b94708775507e0c7ce75be 100644 --- a/drivers/vdpa/vdpa_user/vduse_dev.c +++ b/drivers/vdpa/vdpa_user/vduse_dev.c @@ -726,7 +726,11 @@ static int vduse_vdpa_set_vq_affinity(struct vdpa_device *vdpa, u16 idx, { struct vduse_dev *dev = vdpa_to_vduse(vdpa); - cpumask_copy(&dev->vqs[idx]->irq_affinity, cpu_mask); + if (cpu_mask) + cpumask_copy(&dev->vqs[idx]->irq_affinity, cpu_mask); + else + cpumask_setall(&dev->vqs[idx]->irq_affinity); + return 0; } @@ -1052,7 +1056,7 @@ static int vduse_dev_reg_umem(struct vduse_dev *dev, goto out; pinned = pin_user_pages(uaddr, npages, FOLL_LONGTERM | FOLL_WRITE, - page_list, NULL); + page_list); if (pinned != npages) { ret = pinned < 0 ? pinned : -ENOMEM; goto out; diff --git a/drivers/vfio/Kconfig b/drivers/vfio/Kconfig index 89e06c981e435d45fa86425e8e622eaff1185a85..aba36f5be4ecea033dd9f296a82f6752e43eaddd 100644 --- a/drivers/vfio/Kconfig +++ b/drivers/vfio/Kconfig @@ -57,6 +57,7 @@ source "drivers/vfio/pci/Kconfig" source "drivers/vfio/platform/Kconfig" source "drivers/vfio/mdev/Kconfig" source "drivers/vfio/fsl-mc/Kconfig" +source "drivers/vfio/cdx/Kconfig" endif source "virt/lib/Kconfig" diff --git a/drivers/vfio/Makefile b/drivers/vfio/Makefile index 70e7dcb302efd20ddc2d4cb31fbffc1ea5e6b49f..66f418aef5a9a7f19321c44942ebcb1e8ff896a4 100644 --- a/drivers/vfio/Makefile +++ b/drivers/vfio/Makefile @@ -10,7 +10,8 @@ vfio-$(CONFIG_VFIO_VIRQFD) += virqfd.o obj-$(CONFIG_VFIO_IOMMU_TYPE1) += vfio_iommu_type1.o obj-$(CONFIG_VFIO_IOMMU_SPAPR_TCE) += vfio_iommu_spapr_tce.o -obj-$(CONFIG_VFIO_PCI) += pci/ -obj-$(CONFIG_VFIO_PLATFORM) += platform/ +obj-$(CONFIG_VFIO_PCI_CORE) += pci/ +obj-$(CONFIG_VFIO_PLATFORM_BASE) += platform/ obj-$(CONFIG_VFIO_MDEV) += mdev/ obj-$(CONFIG_VFIO_FSL_MC) += fsl-mc/ +obj-$(CONFIG_VFIO_CDX) += cdx/ diff --git a/drivers/vfio/cdx/Kconfig b/drivers/vfio/cdx/Kconfig new file mode 100644 index 0000000000000000000000000000000000000000..e6de0a0caa32262702b478922f1b3ee822b6ff8f --- /dev/null +++ b/drivers/vfio/cdx/Kconfig @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# VFIO CDX configuration +# +# Copyright (C) 2022-2023, Advanced Micro Devices, Inc. +# + +config VFIO_CDX + tristate "VFIO support for CDX bus devices" + depends on CDX_BUS + select EVENTFD + help + Driver to enable VFIO support for the devices on CDX bus. + This is required to make use of CDX devices present in + the system using the VFIO framework. + + If you don't know what to do here, say N. diff --git a/drivers/vfio/cdx/Makefile b/drivers/vfio/cdx/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..cd4a2e6fe6094b3ac55c910f25e413a709f9a661 --- /dev/null +++ b/drivers/vfio/cdx/Makefile @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# Copyright (C) 2022-2023, Advanced Micro Devices, Inc. +# + +obj-$(CONFIG_VFIO_CDX) += vfio-cdx.o + +vfio-cdx-objs := main.o diff --git a/drivers/vfio/cdx/main.c b/drivers/vfio/cdx/main.c new file mode 100644 index 0000000000000000000000000000000000000000..c376a69d2db2e0c19b68991aa18a24565cad09be --- /dev/null +++ b/drivers/vfio/cdx/main.c @@ -0,0 +1,234 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2022-2023, Advanced Micro Devices, Inc. + */ + +#include +#include + +#include "private.h" + +static int vfio_cdx_open_device(struct vfio_device *core_vdev) +{ + struct vfio_cdx_device *vdev = + container_of(core_vdev, struct vfio_cdx_device, vdev); + struct cdx_device *cdx_dev = to_cdx_device(core_vdev->dev); + int count = cdx_dev->res_count; + int i; + + vdev->regions = kcalloc(count, sizeof(struct vfio_cdx_region), + GFP_KERNEL_ACCOUNT); + if (!vdev->regions) + return -ENOMEM; + + for (i = 0; i < count; i++) { + struct resource *res = &cdx_dev->res[i]; + + vdev->regions[i].addr = res->start; + vdev->regions[i].size = resource_size(res); + vdev->regions[i].type = res->flags; + /* + * Only regions addressed with PAGE granularity may be + * MMAP'ed securely. + */ + if (!(vdev->regions[i].addr & ~PAGE_MASK) && + !(vdev->regions[i].size & ~PAGE_MASK)) + vdev->regions[i].flags |= + VFIO_REGION_INFO_FLAG_MMAP; + vdev->regions[i].flags |= VFIO_REGION_INFO_FLAG_READ; + if (!(cdx_dev->res[i].flags & IORESOURCE_READONLY)) + vdev->regions[i].flags |= VFIO_REGION_INFO_FLAG_WRITE; + } + + return 0; +} + +static void vfio_cdx_close_device(struct vfio_device *core_vdev) +{ + struct vfio_cdx_device *vdev = + container_of(core_vdev, struct vfio_cdx_device, vdev); + + kfree(vdev->regions); + cdx_dev_reset(core_vdev->dev); +} + +static int vfio_cdx_ioctl_get_info(struct vfio_cdx_device *vdev, + struct vfio_device_info __user *arg) +{ + unsigned long minsz = offsetofend(struct vfio_device_info, num_irqs); + struct cdx_device *cdx_dev = to_cdx_device(vdev->vdev.dev); + struct vfio_device_info info; + + if (copy_from_user(&info, arg, minsz)) + return -EFAULT; + + if (info.argsz < minsz) + return -EINVAL; + + info.flags = VFIO_DEVICE_FLAGS_CDX; + info.flags |= VFIO_DEVICE_FLAGS_RESET; + + info.num_regions = cdx_dev->res_count; + info.num_irqs = 0; + + return copy_to_user(arg, &info, minsz) ? -EFAULT : 0; +} + +static int vfio_cdx_ioctl_get_region_info(struct vfio_cdx_device *vdev, + struct vfio_region_info __user *arg) +{ + unsigned long minsz = offsetofend(struct vfio_region_info, offset); + struct cdx_device *cdx_dev = to_cdx_device(vdev->vdev.dev); + struct vfio_region_info info; + + if (copy_from_user(&info, arg, minsz)) + return -EFAULT; + + if (info.argsz < minsz) + return -EINVAL; + + if (info.index >= cdx_dev->res_count) + return -EINVAL; + + /* map offset to the physical address */ + info.offset = vfio_cdx_index_to_offset(info.index); + info.size = vdev->regions[info.index].size; + info.flags = vdev->regions[info.index].flags; + + return copy_to_user(arg, &info, minsz) ? -EFAULT : 0; +} + +static long vfio_cdx_ioctl(struct vfio_device *core_vdev, + unsigned int cmd, unsigned long arg) +{ + struct vfio_cdx_device *vdev = + container_of(core_vdev, struct vfio_cdx_device, vdev); + void __user *uarg = (void __user *)arg; + + switch (cmd) { + case VFIO_DEVICE_GET_INFO: + return vfio_cdx_ioctl_get_info(vdev, uarg); + case VFIO_DEVICE_GET_REGION_INFO: + return vfio_cdx_ioctl_get_region_info(vdev, uarg); + case VFIO_DEVICE_RESET: + return cdx_dev_reset(core_vdev->dev); + default: + return -ENOTTY; + } +} + +static int vfio_cdx_mmap_mmio(struct vfio_cdx_region region, + struct vm_area_struct *vma) +{ + u64 size = vma->vm_end - vma->vm_start; + u64 pgoff, base; + + pgoff = vma->vm_pgoff & + ((1U << (VFIO_CDX_OFFSET_SHIFT - PAGE_SHIFT)) - 1); + base = pgoff << PAGE_SHIFT; + + if (base + size > region.size) + return -EINVAL; + + vma->vm_pgoff = (region.addr >> PAGE_SHIFT) + pgoff; + vma->vm_page_prot = pgprot_device(vma->vm_page_prot); + + return io_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, + size, vma->vm_page_prot); +} + +static int vfio_cdx_mmap(struct vfio_device *core_vdev, + struct vm_area_struct *vma) +{ + struct vfio_cdx_device *vdev = + container_of(core_vdev, struct vfio_cdx_device, vdev); + struct cdx_device *cdx_dev = to_cdx_device(core_vdev->dev); + unsigned int index; + + index = vma->vm_pgoff >> (VFIO_CDX_OFFSET_SHIFT - PAGE_SHIFT); + + if (index >= cdx_dev->res_count) + return -EINVAL; + + if (!(vdev->regions[index].flags & VFIO_REGION_INFO_FLAG_MMAP)) + return -EINVAL; + + if (!(vdev->regions[index].flags & VFIO_REGION_INFO_FLAG_READ) && + (vma->vm_flags & VM_READ)) + return -EPERM; + + if (!(vdev->regions[index].flags & VFIO_REGION_INFO_FLAG_WRITE) && + (vma->vm_flags & VM_WRITE)) + return -EPERM; + + return vfio_cdx_mmap_mmio(vdev->regions[index], vma); +} + +static const struct vfio_device_ops vfio_cdx_ops = { + .name = "vfio-cdx", + .open_device = vfio_cdx_open_device, + .close_device = vfio_cdx_close_device, + .ioctl = vfio_cdx_ioctl, + .mmap = vfio_cdx_mmap, + .bind_iommufd = vfio_iommufd_physical_bind, + .unbind_iommufd = vfio_iommufd_physical_unbind, + .attach_ioas = vfio_iommufd_physical_attach_ioas, +}; + +static int vfio_cdx_probe(struct cdx_device *cdx_dev) +{ + struct vfio_cdx_device *vdev; + struct device *dev = &cdx_dev->dev; + int ret; + + vdev = vfio_alloc_device(vfio_cdx_device, vdev, dev, + &vfio_cdx_ops); + if (IS_ERR(vdev)) + return PTR_ERR(vdev); + + ret = vfio_register_group_dev(&vdev->vdev); + if (ret) + goto out_uninit; + + dev_set_drvdata(dev, vdev); + return 0; + +out_uninit: + vfio_put_device(&vdev->vdev); + return ret; +} + +static int vfio_cdx_remove(struct cdx_device *cdx_dev) +{ + struct device *dev = &cdx_dev->dev; + struct vfio_cdx_device *vdev = dev_get_drvdata(dev); + + vfio_unregister_group_dev(&vdev->vdev); + vfio_put_device(&vdev->vdev); + + return 0; +} + +static const struct cdx_device_id vfio_cdx_table[] = { + { CDX_DEVICE_DRIVER_OVERRIDE(CDX_ANY_ID, CDX_ANY_ID, + CDX_ID_F_VFIO_DRIVER_OVERRIDE) }, /* match all by default */ + {} +}; + +MODULE_DEVICE_TABLE(cdx, vfio_cdx_table); + +static struct cdx_driver vfio_cdx_driver = { + .probe = vfio_cdx_probe, + .remove = vfio_cdx_remove, + .match_id_table = vfio_cdx_table, + .driver = { + .name = "vfio-cdx", + .owner = THIS_MODULE, + }, + .driver_managed_dma = true, +}; + +module_driver(vfio_cdx_driver, cdx_driver_register, cdx_driver_unregister); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("VFIO for CDX devices - User Level meta-driver"); diff --git a/drivers/vfio/cdx/private.h b/drivers/vfio/cdx/private.h new file mode 100644 index 0000000000000000000000000000000000000000..8bdc117ea88edd6d181aea65c082004d521e405e --- /dev/null +++ b/drivers/vfio/cdx/private.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2022-2023, Advanced Micro Devices, Inc. + */ + +#ifndef VFIO_CDX_PRIVATE_H +#define VFIO_CDX_PRIVATE_H + +#define VFIO_CDX_OFFSET_SHIFT 40 + +static inline u64 vfio_cdx_index_to_offset(u32 index) +{ + return ((u64)(index) << VFIO_CDX_OFFSET_SHIFT); +} + +struct vfio_cdx_region { + u32 flags; + u32 type; + u64 addr; + resource_size_t size; +}; + +struct vfio_cdx_device { + struct vfio_device vdev; + struct vfio_cdx_region *regions; +}; + +#endif /* VFIO_CDX_PRIVATE_H */ diff --git a/drivers/vfio/fsl-mc/Kconfig b/drivers/vfio/fsl-mc/Kconfig index 597d338c5c8a2ca77fb504b1ee70df7575b5adc7..7d1d690348f07c2f6dd1399e03e90c041a260dd0 100644 --- a/drivers/vfio/fsl-mc/Kconfig +++ b/drivers/vfio/fsl-mc/Kconfig @@ -1,6 +1,8 @@ +menu "VFIO support for FSL_MC bus devices" + depends on FSL_MC_BUS + config VFIO_FSL_MC tristate "VFIO support for QorIQ DPAA2 fsl-mc bus devices" - depends on FSL_MC_BUS select EVENTFD help Driver to enable support for the VFIO QorIQ DPAA2 fsl-mc @@ -8,3 +10,5 @@ config VFIO_FSL_MC fsl-mc bus devices using the VFIO framework. If you don't know what to do here, say N. + +endmenu diff --git a/drivers/vfio/fsl-mc/vfio_fsl_mc.c b/drivers/vfio/fsl-mc/vfio_fsl_mc.c index c89a047a4cd815cbcb827a8ad3a86457a303c039..f2140e94d41efbac306caabac83762e28ad795b4 100644 --- a/drivers/vfio/fsl-mc/vfio_fsl_mc.c +++ b/drivers/vfio/fsl-mc/vfio_fsl_mc.c @@ -570,7 +570,7 @@ static void vfio_fsl_mc_release_dev(struct vfio_device *core_vdev) mutex_destroy(&vdev->igate); } -static int vfio_fsl_mc_remove(struct fsl_mc_device *mc_dev) +static void vfio_fsl_mc_remove(struct fsl_mc_device *mc_dev) { struct device *dev = &mc_dev->dev; struct vfio_fsl_mc_device *vdev = dev_get_drvdata(dev); @@ -578,7 +578,6 @@ static int vfio_fsl_mc_remove(struct fsl_mc_device *mc_dev) vfio_unregister_group_dev(&vdev->vdev); dprc_remove_devices(mc_dev, NULL, 0); vfio_put_device(&vdev->vdev); - return 0; } static const struct vfio_device_ops vfio_fsl_mc_ops = { diff --git a/drivers/vfio/mdev/mdev_core.c b/drivers/vfio/mdev/mdev_core.c index 58f91b3bd670cc4fc88608dad02f9ab7eb24cb76..ed4737de4528961f93d37a4aaed76b42570aa81c 100644 --- a/drivers/vfio/mdev/mdev_core.c +++ b/drivers/vfio/mdev/mdev_core.c @@ -72,12 +72,6 @@ int mdev_register_parent(struct mdev_parent *parent, struct device *dev, parent->nr_types = nr_types; atomic_set(&parent->available_instances, mdev_driver->max_instances); - if (!mdev_bus_compat_class) { - mdev_bus_compat_class = class_compat_register("mdev_bus"); - if (!mdev_bus_compat_class) - return -ENOMEM; - } - ret = parent_create_sysfs_files(parent); if (ret) return ret; @@ -251,13 +245,24 @@ int mdev_device_remove(struct mdev_device *mdev) static int __init mdev_init(void) { - return bus_register(&mdev_bus_type); + int ret; + + ret = bus_register(&mdev_bus_type); + if (ret) + return ret; + + mdev_bus_compat_class = class_compat_register("mdev_bus"); + if (!mdev_bus_compat_class) { + bus_unregister(&mdev_bus_type); + return -ENOMEM; + } + + return 0; } static void __exit mdev_exit(void) { - if (mdev_bus_compat_class) - class_compat_unregister(mdev_bus_compat_class); + class_compat_unregister(mdev_bus_compat_class); bus_unregister(&mdev_bus_type); } diff --git a/drivers/vfio/pci/Kconfig b/drivers/vfio/pci/Kconfig index f9d0c908e738c33f3a5fb7202e2ef7491dd90b8e..86bb7835cf3c69eded65a495921f166a78f64237 100644 --- a/drivers/vfio/pci/Kconfig +++ b/drivers/vfio/pci/Kconfig @@ -1,5 +1,7 @@ # SPDX-License-Identifier: GPL-2.0-only -if PCI && MMU +menu "VFIO support for PCI devices" + depends on PCI && MMU + config VFIO_PCI_CORE tristate select VFIO_VIRQFD @@ -7,9 +9,11 @@ config VFIO_PCI_CORE config VFIO_PCI_MMAP def_bool y if !S390 + depends on VFIO_PCI_CORE config VFIO_PCI_INTX def_bool y if !S390 + depends on VFIO_PCI_CORE config VFIO_PCI tristate "Generic VFIO support for any PCI device" @@ -59,4 +63,4 @@ source "drivers/vfio/pci/mlx5/Kconfig" source "drivers/vfio/pci/hisilicon/Kconfig" -endif +endmenu diff --git a/drivers/vfio/pci/hisilicon/Kconfig b/drivers/vfio/pci/hisilicon/Kconfig index 5daa0f45d2f99b841093c0106e1da0a10bc69db9..cbf1c32f6ebff7388186dd46e11eb5176193d901 100644 --- a/drivers/vfio/pci/hisilicon/Kconfig +++ b/drivers/vfio/pci/hisilicon/Kconfig @@ -1,13 +1,13 @@ # SPDX-License-Identifier: GPL-2.0-only config HISI_ACC_VFIO_PCI - tristate "VFIO PCI support for HiSilicon ACC devices" + tristate "VFIO support for HiSilicon ACC PCI devices" depends on ARM64 || (COMPILE_TEST && 64BIT) - depends on VFIO_PCI_CORE depends on PCI_MSI depends on CRYPTO_DEV_HISI_QM depends on CRYPTO_DEV_HISI_HPRE depends on CRYPTO_DEV_HISI_SEC2 depends on CRYPTO_DEV_HISI_ZIP + select VFIO_PCI_CORE help This provides generic PCI support for HiSilicon ACC devices using the VFIO framework. diff --git a/drivers/vfio/pci/mlx5/Kconfig b/drivers/vfio/pci/mlx5/Kconfig index 29ba9c504a7560f56035acedbcb7345bcc733820..7088edc4fb28d88f5603e8f68462993123eece46 100644 --- a/drivers/vfio/pci/mlx5/Kconfig +++ b/drivers/vfio/pci/mlx5/Kconfig @@ -2,7 +2,7 @@ config MLX5_VFIO_PCI tristate "VFIO support for MLX5 PCI devices" depends on MLX5_CORE - depends on VFIO_PCI_CORE + select VFIO_PCI_CORE help This provides migration support for MLX5 devices using the VFIO framework. diff --git a/drivers/vfio/pci/vfio_pci_config.c b/drivers/vfio/pci/vfio_pci_config.c index 948cdd464f4e61cf790dca492a6f24f6a1ec000b..7e2e62ab0869cfb42ae786f9c41b343b42209de7 100644 --- a/drivers/vfio/pci/vfio_pci_config.c +++ b/drivers/vfio/pci/vfio_pci_config.c @@ -1566,8 +1566,8 @@ static int vfio_cap_init(struct vfio_pci_core_device *vdev) } if (!len) { - pci_info(pdev, "%s: hiding cap %#x@%#x\n", __func__, - cap, pos); + pci_dbg(pdev, "%s: hiding cap %#x@%#x\n", __func__, + cap, pos); *prev = next; pos = next; continue; @@ -1643,8 +1643,8 @@ static int vfio_ecap_init(struct vfio_pci_core_device *vdev) } if (!len) { - pci_info(pdev, "%s: hiding ecap %#x@%#x\n", - __func__, ecap, epos); + pci_dbg(pdev, "%s: hiding ecap %#x@%#x\n", + __func__, ecap, epos); /* If not the first in the chain, we can skip over it */ if (prev) { diff --git a/drivers/vfio/pci/vfio_pci_core.c b/drivers/vfio/pci/vfio_pci_core.c index a5ab416cf476c3648affe6afa63bd25e0be972ee..20d7b69ea6ff1f6f877652f1118345faf6871702 100644 --- a/drivers/vfio/pci/vfio_pci_core.c +++ b/drivers/vfio/pci/vfio_pci_core.c @@ -530,8 +530,11 @@ int vfio_pci_core_enable(struct vfio_pci_core_device *vdev) vdev->msix_bar = table & PCI_MSIX_TABLE_BIR; vdev->msix_offset = table & PCI_MSIX_TABLE_OFFSET; vdev->msix_size = ((flags & PCI_MSIX_FLAGS_QSIZE) + 1) * 16; - } else + vdev->has_dyn_msix = pci_msix_can_alloc_dyn(pdev); + } else { vdev->msix_bar = 0xFF; + vdev->has_dyn_msix = false; + } if (!vfio_vga_disabled() && vfio_pci_is_vga(pdev)) vdev->has_vga = true; @@ -882,6 +885,37 @@ int vfio_pci_core_register_dev_region(struct vfio_pci_core_device *vdev, } EXPORT_SYMBOL_GPL(vfio_pci_core_register_dev_region); +static int vfio_pci_info_atomic_cap(struct vfio_pci_core_device *vdev, + struct vfio_info_cap *caps) +{ + struct vfio_device_info_cap_pci_atomic_comp cap = { + .header.id = VFIO_DEVICE_INFO_CAP_PCI_ATOMIC_COMP, + .header.version = 1 + }; + struct pci_dev *pdev = pci_physfn(vdev->pdev); + u32 devcap2; + + pcie_capability_read_dword(pdev, PCI_EXP_DEVCAP2, &devcap2); + + if ((devcap2 & PCI_EXP_DEVCAP2_ATOMIC_COMP32) && + !pci_enable_atomic_ops_to_root(pdev, PCI_EXP_DEVCAP2_ATOMIC_COMP32)) + cap.flags |= VFIO_PCI_ATOMIC_COMP32; + + if ((devcap2 & PCI_EXP_DEVCAP2_ATOMIC_COMP64) && + !pci_enable_atomic_ops_to_root(pdev, PCI_EXP_DEVCAP2_ATOMIC_COMP64)) + cap.flags |= VFIO_PCI_ATOMIC_COMP64; + + if ((devcap2 & PCI_EXP_DEVCAP2_ATOMIC_COMP128) && + !pci_enable_atomic_ops_to_root(pdev, + PCI_EXP_DEVCAP2_ATOMIC_COMP128)) + cap.flags |= VFIO_PCI_ATOMIC_COMP128; + + if (!cap.flags) + return -ENODEV; + + return vfio_info_add_capability(caps, &cap.header, sizeof(cap)); +} + static int vfio_pci_ioctl_get_info(struct vfio_pci_core_device *vdev, struct vfio_device_info __user *arg) { @@ -920,6 +954,13 @@ static int vfio_pci_ioctl_get_info(struct vfio_pci_core_device *vdev, return ret; } + ret = vfio_pci_info_atomic_cap(vdev, &caps); + if (ret && ret != -ENODEV) { + pci_warn(vdev->pdev, + "Failed to setup AtomicOps info capability\n"); + return ret; + } + if (caps.size) { info.flags |= VFIO_DEVICE_FLAGS_CAPS; if (info.argsz < sizeof(info) + caps.size) { @@ -1111,7 +1152,7 @@ static int vfio_pci_ioctl_get_irq_info(struct vfio_pci_core_device *vdev, if (info.index == VFIO_PCI_INTX_IRQ_INDEX) info.flags |= (VFIO_IRQ_INFO_MASKABLE | VFIO_IRQ_INFO_AUTOMASKED); - else + else if (info.index != VFIO_PCI_MSIX_IRQ_INDEX || !vdev->has_dyn_msix) info.flags |= VFIO_IRQ_INFO_NORESIZE; return copy_to_user(arg, &info, minsz) ? -EFAULT : 0; @@ -2102,6 +2143,7 @@ int vfio_pci_core_init_dev(struct vfio_device *core_vdev) INIT_LIST_HEAD(&vdev->vma_list); INIT_LIST_HEAD(&vdev->sriov_pfs_item); init_rwsem(&vdev->memory_lock); + xa_init(&vdev->ctx); return 0; } diff --git a/drivers/vfio/pci/vfio_pci_intrs.c b/drivers/vfio/pci/vfio_pci_intrs.c index bffb0741518b95b7041adba2afab35619e8bbc18..cbb4bcbfbf83d98ec3e9c3a44a120c9fb74623f2 100644 --- a/drivers/vfio/pci/vfio_pci_intrs.c +++ b/drivers/vfio/pci/vfio_pci_intrs.c @@ -48,6 +48,39 @@ static bool is_irq_none(struct vfio_pci_core_device *vdev) vdev->irq_type == VFIO_PCI_MSIX_IRQ_INDEX); } +static +struct vfio_pci_irq_ctx *vfio_irq_ctx_get(struct vfio_pci_core_device *vdev, + unsigned long index) +{ + return xa_load(&vdev->ctx, index); +} + +static void vfio_irq_ctx_free(struct vfio_pci_core_device *vdev, + struct vfio_pci_irq_ctx *ctx, unsigned long index) +{ + xa_erase(&vdev->ctx, index); + kfree(ctx); +} + +static struct vfio_pci_irq_ctx * +vfio_irq_ctx_alloc(struct vfio_pci_core_device *vdev, unsigned long index) +{ + struct vfio_pci_irq_ctx *ctx; + int ret; + + ctx = kzalloc(sizeof(*ctx), GFP_KERNEL_ACCOUNT); + if (!ctx) + return NULL; + + ret = xa_insert(&vdev->ctx, index, ctx, GFP_KERNEL_ACCOUNT); + if (ret) { + kfree(ctx); + return NULL; + } + + return ctx; +} + /* * INTx */ @@ -55,14 +88,21 @@ static void vfio_send_intx_eventfd(void *opaque, void *unused) { struct vfio_pci_core_device *vdev = opaque; - if (likely(is_intx(vdev) && !vdev->virq_disabled)) - eventfd_signal(vdev->ctx[0].trigger, 1); + if (likely(is_intx(vdev) && !vdev->virq_disabled)) { + struct vfio_pci_irq_ctx *ctx; + + ctx = vfio_irq_ctx_get(vdev, 0); + if (WARN_ON_ONCE(!ctx)) + return; + eventfd_signal(ctx->trigger, 1); + } } /* Returns true if the INTx vfio_pci_irq_ctx.masked value is changed. */ bool vfio_pci_intx_mask(struct vfio_pci_core_device *vdev) { struct pci_dev *pdev = vdev->pdev; + struct vfio_pci_irq_ctx *ctx; unsigned long flags; bool masked_changed = false; @@ -77,7 +117,14 @@ bool vfio_pci_intx_mask(struct vfio_pci_core_device *vdev) if (unlikely(!is_intx(vdev))) { if (vdev->pci_2_3) pci_intx(pdev, 0); - } else if (!vdev->ctx[0].masked) { + goto out_unlock; + } + + ctx = vfio_irq_ctx_get(vdev, 0); + if (WARN_ON_ONCE(!ctx)) + goto out_unlock; + + if (!ctx->masked) { /* * Can't use check_and_mask here because we always want to * mask, not just when something is pending. @@ -87,10 +134,11 @@ bool vfio_pci_intx_mask(struct vfio_pci_core_device *vdev) else disable_irq_nosync(pdev->irq); - vdev->ctx[0].masked = true; + ctx->masked = true; masked_changed = true; } +out_unlock: spin_unlock_irqrestore(&vdev->irqlock, flags); return masked_changed; } @@ -105,6 +153,7 @@ static int vfio_pci_intx_unmask_handler(void *opaque, void *unused) { struct vfio_pci_core_device *vdev = opaque; struct pci_dev *pdev = vdev->pdev; + struct vfio_pci_irq_ctx *ctx; unsigned long flags; int ret = 0; @@ -117,7 +166,14 @@ static int vfio_pci_intx_unmask_handler(void *opaque, void *unused) if (unlikely(!is_intx(vdev))) { if (vdev->pci_2_3) pci_intx(pdev, 1); - } else if (vdev->ctx[0].masked && !vdev->virq_disabled) { + goto out_unlock; + } + + ctx = vfio_irq_ctx_get(vdev, 0); + if (WARN_ON_ONCE(!ctx)) + goto out_unlock; + + if (ctx->masked && !vdev->virq_disabled) { /* * A pending interrupt here would immediately trigger, * but we can avoid that overhead by just re-sending @@ -129,9 +185,10 @@ static int vfio_pci_intx_unmask_handler(void *opaque, void *unused) } else enable_irq(pdev->irq); - vdev->ctx[0].masked = (ret > 0); + ctx->masked = (ret > 0); } +out_unlock: spin_unlock_irqrestore(&vdev->irqlock, flags); return ret; @@ -146,18 +203,23 @@ void vfio_pci_intx_unmask(struct vfio_pci_core_device *vdev) static irqreturn_t vfio_intx_handler(int irq, void *dev_id) { struct vfio_pci_core_device *vdev = dev_id; + struct vfio_pci_irq_ctx *ctx; unsigned long flags; int ret = IRQ_NONE; + ctx = vfio_irq_ctx_get(vdev, 0); + if (WARN_ON_ONCE(!ctx)) + return ret; + spin_lock_irqsave(&vdev->irqlock, flags); if (!vdev->pci_2_3) { disable_irq_nosync(vdev->pdev->irq); - vdev->ctx[0].masked = true; + ctx->masked = true; ret = IRQ_HANDLED; - } else if (!vdev->ctx[0].masked && /* may be shared */ + } else if (!ctx->masked && /* may be shared */ pci_check_and_mask_intx(vdev->pdev)) { - vdev->ctx[0].masked = true; + ctx->masked = true; ret = IRQ_HANDLED; } @@ -171,27 +233,27 @@ static irqreturn_t vfio_intx_handler(int irq, void *dev_id) static int vfio_intx_enable(struct vfio_pci_core_device *vdev) { + struct vfio_pci_irq_ctx *ctx; + if (!is_irq_none(vdev)) return -EINVAL; if (!vdev->pdev->irq) return -ENODEV; - vdev->ctx = kzalloc(sizeof(struct vfio_pci_irq_ctx), GFP_KERNEL_ACCOUNT); - if (!vdev->ctx) + ctx = vfio_irq_ctx_alloc(vdev, 0); + if (!ctx) return -ENOMEM; - vdev->num_ctx = 1; - /* * If the virtual interrupt is masked, restore it. Devices * supporting DisINTx can be masked at the hardware level * here, non-PCI-2.3 devices will have to wait until the * interrupt is enabled. */ - vdev->ctx[0].masked = vdev->virq_disabled; + ctx->masked = vdev->virq_disabled; if (vdev->pci_2_3) - pci_intx(vdev->pdev, !vdev->ctx[0].masked); + pci_intx(vdev->pdev, !ctx->masked); vdev->irq_type = VFIO_PCI_INTX_IRQ_INDEX; @@ -202,41 +264,46 @@ static int vfio_intx_set_signal(struct vfio_pci_core_device *vdev, int fd) { struct pci_dev *pdev = vdev->pdev; unsigned long irqflags = IRQF_SHARED; + struct vfio_pci_irq_ctx *ctx; struct eventfd_ctx *trigger; unsigned long flags; int ret; - if (vdev->ctx[0].trigger) { + ctx = vfio_irq_ctx_get(vdev, 0); + if (WARN_ON_ONCE(!ctx)) + return -EINVAL; + + if (ctx->trigger) { free_irq(pdev->irq, vdev); - kfree(vdev->ctx[0].name); - eventfd_ctx_put(vdev->ctx[0].trigger); - vdev->ctx[0].trigger = NULL; + kfree(ctx->name); + eventfd_ctx_put(ctx->trigger); + ctx->trigger = NULL; } if (fd < 0) /* Disable only */ return 0; - vdev->ctx[0].name = kasprintf(GFP_KERNEL_ACCOUNT, "vfio-intx(%s)", - pci_name(pdev)); - if (!vdev->ctx[0].name) + ctx->name = kasprintf(GFP_KERNEL_ACCOUNT, "vfio-intx(%s)", + pci_name(pdev)); + if (!ctx->name) return -ENOMEM; trigger = eventfd_ctx_fdget(fd); if (IS_ERR(trigger)) { - kfree(vdev->ctx[0].name); + kfree(ctx->name); return PTR_ERR(trigger); } - vdev->ctx[0].trigger = trigger; + ctx->trigger = trigger; if (!vdev->pci_2_3) irqflags = 0; ret = request_irq(pdev->irq, vfio_intx_handler, - irqflags, vdev->ctx[0].name, vdev); + irqflags, ctx->name, vdev); if (ret) { - vdev->ctx[0].trigger = NULL; - kfree(vdev->ctx[0].name); + ctx->trigger = NULL; + kfree(ctx->name); eventfd_ctx_put(trigger); return ret; } @@ -246,7 +313,7 @@ static int vfio_intx_set_signal(struct vfio_pci_core_device *vdev, int fd) * disable_irq won't. */ spin_lock_irqsave(&vdev->irqlock, flags); - if (!vdev->pci_2_3 && vdev->ctx[0].masked) + if (!vdev->pci_2_3 && ctx->masked) disable_irq_nosync(pdev->irq); spin_unlock_irqrestore(&vdev->irqlock, flags); @@ -255,12 +322,17 @@ static int vfio_intx_set_signal(struct vfio_pci_core_device *vdev, int fd) static void vfio_intx_disable(struct vfio_pci_core_device *vdev) { - vfio_virqfd_disable(&vdev->ctx[0].unmask); - vfio_virqfd_disable(&vdev->ctx[0].mask); + struct vfio_pci_irq_ctx *ctx; + + ctx = vfio_irq_ctx_get(vdev, 0); + WARN_ON_ONCE(!ctx); + if (ctx) { + vfio_virqfd_disable(&ctx->unmask); + vfio_virqfd_disable(&ctx->mask); + } vfio_intx_set_signal(vdev, -1); vdev->irq_type = VFIO_PCI_NUM_IRQS; - vdev->num_ctx = 0; - kfree(vdev->ctx); + vfio_irq_ctx_free(vdev, ctx, 0); } /* @@ -284,11 +356,6 @@ static int vfio_msi_enable(struct vfio_pci_core_device *vdev, int nvec, bool msi if (!is_irq_none(vdev)) return -EINVAL; - vdev->ctx = kcalloc(nvec, sizeof(struct vfio_pci_irq_ctx), - GFP_KERNEL_ACCOUNT); - if (!vdev->ctx) - return -ENOMEM; - /* return the number of supported vectors if we can't get all: */ cmd = vfio_pci_memory_lock_and_enable(vdev); ret = pci_alloc_irq_vectors(pdev, 1, nvec, flag); @@ -296,12 +363,10 @@ static int vfio_msi_enable(struct vfio_pci_core_device *vdev, int nvec, bool msi if (ret > 0) pci_free_irq_vectors(pdev); vfio_pci_memory_unlock_and_restore(vdev, cmd); - kfree(vdev->ctx); return ret; } vfio_pci_memory_unlock_and_restore(vdev, cmd); - vdev->num_ctx = nvec; vdev->irq_type = msix ? VFIO_PCI_MSIX_IRQ_INDEX : VFIO_PCI_MSI_IRQ_INDEX; @@ -316,53 +381,91 @@ static int vfio_msi_enable(struct vfio_pci_core_device *vdev, int nvec, bool msi return 0; } -static int vfio_msi_set_vector_signal(struct vfio_pci_core_device *vdev, - int vector, int fd, bool msix) +/* + * vfio_msi_alloc_irq() returns the Linux IRQ number of an MSI or MSI-X device + * interrupt vector. If a Linux IRQ number is not available then a new + * interrupt is allocated if dynamic MSI-X is supported. + * + * Where is vfio_msi_free_irq()? Allocated interrupts are maintained, + * essentially forming a cache that subsequent allocations can draw from. + * Interrupts are freed using pci_free_irq_vectors() when MSI/MSI-X is + * disabled. + */ +static int vfio_msi_alloc_irq(struct vfio_pci_core_device *vdev, + unsigned int vector, bool msix) { struct pci_dev *pdev = vdev->pdev; - struct eventfd_ctx *trigger; - int irq, ret; + struct msi_map map; + int irq; u16 cmd; - if (vector < 0 || vector >= vdev->num_ctx) + irq = pci_irq_vector(pdev, vector); + if (WARN_ON_ONCE(irq == 0)) return -EINVAL; + if (irq > 0 || !msix || !vdev->has_dyn_msix) + return irq; - irq = pci_irq_vector(pdev, vector); + cmd = vfio_pci_memory_lock_and_enable(vdev); + map = pci_msix_alloc_irq_at(pdev, vector, NULL); + vfio_pci_memory_unlock_and_restore(vdev, cmd); - if (vdev->ctx[vector].trigger) { - irq_bypass_unregister_producer(&vdev->ctx[vector].producer); + return map.index < 0 ? map.index : map.virq; +} +static int vfio_msi_set_vector_signal(struct vfio_pci_core_device *vdev, + unsigned int vector, int fd, bool msix) +{ + struct pci_dev *pdev = vdev->pdev; + struct vfio_pci_irq_ctx *ctx; + struct eventfd_ctx *trigger; + int irq = -EINVAL, ret; + u16 cmd; + + ctx = vfio_irq_ctx_get(vdev, vector); + + if (ctx) { + irq_bypass_unregister_producer(&ctx->producer); + irq = pci_irq_vector(pdev, vector); cmd = vfio_pci_memory_lock_and_enable(vdev); - free_irq(irq, vdev->ctx[vector].trigger); + free_irq(irq, ctx->trigger); vfio_pci_memory_unlock_and_restore(vdev, cmd); - - kfree(vdev->ctx[vector].name); - eventfd_ctx_put(vdev->ctx[vector].trigger); - vdev->ctx[vector].trigger = NULL; + /* Interrupt stays allocated, will be freed at MSI-X disable. */ + kfree(ctx->name); + eventfd_ctx_put(ctx->trigger); + vfio_irq_ctx_free(vdev, ctx, vector); } if (fd < 0) return 0; - vdev->ctx[vector].name = kasprintf(GFP_KERNEL_ACCOUNT, - "vfio-msi%s[%d](%s)", - msix ? "x" : "", vector, - pci_name(pdev)); - if (!vdev->ctx[vector].name) + if (irq == -EINVAL) { + /* Interrupt stays allocated, will be freed at MSI-X disable. */ + irq = vfio_msi_alloc_irq(vdev, vector, msix); + if (irq < 0) + return irq; + } + + ctx = vfio_irq_ctx_alloc(vdev, vector); + if (!ctx) return -ENOMEM; + ctx->name = kasprintf(GFP_KERNEL_ACCOUNT, "vfio-msi%s[%d](%s)", + msix ? "x" : "", vector, pci_name(pdev)); + if (!ctx->name) { + ret = -ENOMEM; + goto out_free_ctx; + } + trigger = eventfd_ctx_fdget(fd); if (IS_ERR(trigger)) { - kfree(vdev->ctx[vector].name); - return PTR_ERR(trigger); + ret = PTR_ERR(trigger); + goto out_free_name; } /* - * The MSIx vector table resides in device memory which may be cleared - * via backdoor resets. We don't allow direct access to the vector - * table so even if a userspace driver attempts to save/restore around - * such a reset it would be unsuccessful. To avoid this, restore the - * cached value of the message prior to enabling. + * If the vector was previously allocated, refresh the on-device + * message data before enabling in case it had been cleared or + * corrupted (e.g. due to backdoor resets) since writing. */ cmd = vfio_pci_memory_lock_and_enable(vdev); if (msix) { @@ -372,37 +475,39 @@ static int vfio_msi_set_vector_signal(struct vfio_pci_core_device *vdev, pci_write_msi_msg(irq, &msg); } - ret = request_irq(irq, vfio_msihandler, 0, - vdev->ctx[vector].name, trigger); + ret = request_irq(irq, vfio_msihandler, 0, ctx->name, trigger); vfio_pci_memory_unlock_and_restore(vdev, cmd); - if (ret) { - kfree(vdev->ctx[vector].name); - eventfd_ctx_put(trigger); - return ret; - } + if (ret) + goto out_put_eventfd_ctx; - vdev->ctx[vector].producer.token = trigger; - vdev->ctx[vector].producer.irq = irq; - ret = irq_bypass_register_producer(&vdev->ctx[vector].producer); + ctx->producer.token = trigger; + ctx->producer.irq = irq; + ret = irq_bypass_register_producer(&ctx->producer); if (unlikely(ret)) { dev_info(&pdev->dev, "irq bypass producer (token %p) registration fails: %d\n", - vdev->ctx[vector].producer.token, ret); + ctx->producer.token, ret); - vdev->ctx[vector].producer.token = NULL; + ctx->producer.token = NULL; } - vdev->ctx[vector].trigger = trigger; + ctx->trigger = trigger; return 0; + +out_put_eventfd_ctx: + eventfd_ctx_put(trigger); +out_free_name: + kfree(ctx->name); +out_free_ctx: + vfio_irq_ctx_free(vdev, ctx, vector); + return ret; } static int vfio_msi_set_block(struct vfio_pci_core_device *vdev, unsigned start, unsigned count, int32_t *fds, bool msix) { - int i, j, ret = 0; - - if (start >= vdev->num_ctx || start + count > vdev->num_ctx) - return -EINVAL; + unsigned int i, j; + int ret = 0; for (i = 0, j = start; i < count && !ret; i++, j++) { int fd = fds ? fds[i] : -1; @@ -410,8 +515,8 @@ static int vfio_msi_set_block(struct vfio_pci_core_device *vdev, unsigned start, } if (ret) { - for (--j; j >= (int)start; j--) - vfio_msi_set_vector_signal(vdev, j, -1, msix); + for (i = start; i < j; i++) + vfio_msi_set_vector_signal(vdev, i, -1, msix); } return ret; @@ -420,16 +525,16 @@ static int vfio_msi_set_block(struct vfio_pci_core_device *vdev, unsigned start, static void vfio_msi_disable(struct vfio_pci_core_device *vdev, bool msix) { struct pci_dev *pdev = vdev->pdev; - int i; + struct vfio_pci_irq_ctx *ctx; + unsigned long i; u16 cmd; - for (i = 0; i < vdev->num_ctx; i++) { - vfio_virqfd_disable(&vdev->ctx[i].unmask); - vfio_virqfd_disable(&vdev->ctx[i].mask); + xa_for_each(&vdev->ctx, i, ctx) { + vfio_virqfd_disable(&ctx->unmask); + vfio_virqfd_disable(&ctx->mask); + vfio_msi_set_vector_signal(vdev, i, -1, msix); } - vfio_msi_set_block(vdev, 0, vdev->num_ctx, NULL, msix); - cmd = vfio_pci_memory_lock_and_enable(vdev); pci_free_irq_vectors(pdev); vfio_pci_memory_unlock_and_restore(vdev, cmd); @@ -442,8 +547,6 @@ static void vfio_msi_disable(struct vfio_pci_core_device *vdev, bool msix) pci_intx(pdev, 0); vdev->irq_type = VFIO_PCI_NUM_IRQS; - vdev->num_ctx = 0; - kfree(vdev->ctx); } /* @@ -463,14 +566,18 @@ static int vfio_pci_set_intx_unmask(struct vfio_pci_core_device *vdev, if (unmask) vfio_pci_intx_unmask(vdev); } else if (flags & VFIO_IRQ_SET_DATA_EVENTFD) { + struct vfio_pci_irq_ctx *ctx = vfio_irq_ctx_get(vdev, 0); int32_t fd = *(int32_t *)data; + + if (WARN_ON_ONCE(!ctx)) + return -EINVAL; if (fd >= 0) return vfio_virqfd_enable((void *) vdev, vfio_pci_intx_unmask_handler, vfio_send_intx_eventfd, NULL, - &vdev->ctx[0].unmask, fd); + &ctx->unmask, fd); - vfio_virqfd_disable(&vdev->ctx[0].unmask); + vfio_virqfd_disable(&ctx->unmask); } return 0; @@ -543,7 +650,8 @@ static int vfio_pci_set_msi_trigger(struct vfio_pci_core_device *vdev, unsigned index, unsigned start, unsigned count, uint32_t flags, void *data) { - int i; + struct vfio_pci_irq_ctx *ctx; + unsigned int i; bool msix = (index == VFIO_PCI_MSIX_IRQ_INDEX) ? true : false; if (irq_is(vdev, index) && !count && (flags & VFIO_IRQ_SET_DATA_NONE)) { @@ -573,18 +681,19 @@ static int vfio_pci_set_msi_trigger(struct vfio_pci_core_device *vdev, return ret; } - if (!irq_is(vdev, index) || start + count > vdev->num_ctx) + if (!irq_is(vdev, index)) return -EINVAL; for (i = start; i < start + count; i++) { - if (!vdev->ctx[i].trigger) + ctx = vfio_irq_ctx_get(vdev, i); + if (!ctx) continue; if (flags & VFIO_IRQ_SET_DATA_NONE) { - eventfd_signal(vdev->ctx[i].trigger, 1); + eventfd_signal(ctx->trigger, 1); } else if (flags & VFIO_IRQ_SET_DATA_BOOL) { uint8_t *bools = data; if (bools[i - start]) - eventfd_signal(vdev->ctx[i].trigger, 1); + eventfd_signal(ctx->trigger, 1); } } return 0; diff --git a/drivers/vfio/platform/Kconfig b/drivers/vfio/platform/Kconfig index 331a5920f5abd2ad1caf7f0f98d8d540753dd4cf..88fcde51f02468e7d950eb0dce00f1b126e75935 100644 --- a/drivers/vfio/platform/Kconfig +++ b/drivers/vfio/platform/Kconfig @@ -1,8 +1,14 @@ # SPDX-License-Identifier: GPL-2.0-only -config VFIO_PLATFORM - tristate "VFIO support for platform devices" +menu "VFIO support for platform devices" depends on ARM || ARM64 || COMPILE_TEST + +config VFIO_PLATFORM_BASE + tristate select VFIO_VIRQFD + +config VFIO_PLATFORM + tristate "Generic VFIO support for any platform device" + select VFIO_PLATFORM_BASE help Support for platform devices with VFIO. This is required to make use of platform devices present on the system using the VFIO @@ -10,10 +16,10 @@ config VFIO_PLATFORM If you don't know what to do here, say N. -if VFIO_PLATFORM config VFIO_AMBA tristate "VFIO support for AMBA devices" depends on ARM_AMBA || COMPILE_TEST + select VFIO_PLATFORM_BASE help Support for ARM AMBA devices with VFIO. This is required to make use of ARM AMBA devices present on the system using the VFIO @@ -21,5 +27,9 @@ config VFIO_AMBA If you don't know what to do here, say N. +menu "VFIO platform reset drivers" + depends on VFIO_PLATFORM_BASE + source "drivers/vfio/platform/reset/Kconfig" -endif +endmenu +endmenu diff --git a/drivers/vfio/platform/Makefile b/drivers/vfio/platform/Makefile index 3f3a24e7c4ef8e4f433211146aa5d1addf2df3de..ee4fb6a82ca8a389bafb6e3b7dc6c7cbaf51ae5a 100644 --- a/drivers/vfio/platform/Makefile +++ b/drivers/vfio/platform/Makefile @@ -1,13 +1,10 @@ # SPDX-License-Identifier: GPL-2.0 vfio-platform-base-y := vfio_platform_common.o vfio_platform_irq.o -vfio-platform-y := vfio_platform.o +obj-$(CONFIG_VFIO_PLATFORM_BASE) += vfio-platform-base.o +obj-$(CONFIG_VFIO_PLATFORM_BASE) += reset/ +vfio-platform-y := vfio_platform.o obj-$(CONFIG_VFIO_PLATFORM) += vfio-platform.o -obj-$(CONFIG_VFIO_PLATFORM) += vfio-platform-base.o -obj-$(CONFIG_VFIO_PLATFORM) += reset/ vfio-amba-y := vfio_amba.o - obj-$(CONFIG_VFIO_AMBA) += vfio-amba.o -obj-$(CONFIG_VFIO_AMBA) += vfio-platform-base.o -obj-$(CONFIG_VFIO_AMBA) += reset/ diff --git a/drivers/vfio/platform/reset/Kconfig b/drivers/vfio/platform/reset/Kconfig index 12f5f3d803876c44d06f528ede1da7f83e3a9208..dcc08dc145a5df4904a9830b23ad9dd488997aaf 100644 --- a/drivers/vfio/platform/reset/Kconfig +++ b/drivers/vfio/platform/reset/Kconfig @@ -1,4 +1,5 @@ # SPDX-License-Identifier: GPL-2.0-only +if VFIO_PLATFORM config VFIO_PLATFORM_CALXEDAXGMAC_RESET tristate "VFIO support for calxeda xgmac reset" help @@ -21,3 +22,4 @@ config VFIO_PLATFORM_BCMFLEXRM_RESET Enables the VFIO platform driver to handle reset for Broadcom FlexRM If you don't know what to do here, say N. +endif diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c index 0d2f805468e190c37b5e79527f864d13a42d311e..ebe0ad31d0b039e321576f896f0916bddb9411cf 100644 --- a/drivers/vfio/vfio_iommu_type1.c +++ b/drivers/vfio/vfio_iommu_type1.c @@ -514,6 +514,7 @@ static int follow_fault_pfn(struct vm_area_struct *vma, struct mm_struct *mm, bool write_fault) { pte_t *ptep; + pte_t pte; spinlock_t *ptl; int ret; @@ -536,10 +537,12 @@ static int follow_fault_pfn(struct vm_area_struct *vma, struct mm_struct *mm, return ret; } - if (write_fault && !pte_write(*ptep)) + pte = ptep_get(ptep); + + if (write_fault && !pte_write(pte)) ret = -EFAULT; else - *pfn = pte_pfn(*ptep); + *pfn = pte_pfn(pte); pte_unmap_unlock(ptep, ptl); return ret; @@ -562,7 +565,7 @@ static int vaddr_get_pfns(struct mm_struct *mm, unsigned long vaddr, mmap_read_lock(mm); ret = pin_user_pages_remote(mm, vaddr, npages, flags | FOLL_LONGTERM, - pages, NULL, NULL); + pages, NULL); if (ret > 0) { int i; diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c index ae2273196b0c902c472b3f5cf45249cb6cae37bf..f2ed7167c848096ef8c8f338325bedc278df65fe 100644 --- a/drivers/vhost/net.c +++ b/drivers/vhost/net.c @@ -546,7 +546,7 @@ static void vhost_net_busy_poll(struct vhost_net *net, endtime = busy_clock() + busyloop_timeout; while (vhost_can_busy_poll(endtime)) { - if (vhost_has_work(&net->dev)) { + if (vhost_vq_has_work(vq)) { *busyloop_intr = true; break; } @@ -1347,8 +1347,10 @@ static int vhost_net_open(struct inode *inode, struct file *f) VHOST_NET_PKT_WEIGHT, VHOST_NET_WEIGHT, true, NULL); - vhost_poll_init(n->poll + VHOST_NET_VQ_TX, handle_tx_net, EPOLLOUT, dev); - vhost_poll_init(n->poll + VHOST_NET_VQ_RX, handle_rx_net, EPOLLIN, dev); + vhost_poll_init(n->poll + VHOST_NET_VQ_TX, handle_tx_net, EPOLLOUT, dev, + vqs[VHOST_NET_VQ_TX]); + vhost_poll_init(n->poll + VHOST_NET_VQ_RX, handle_rx_net, EPOLLIN, dev, + vqs[VHOST_NET_VQ_RX]); f->private_data = n; n->page_frag.page = NULL; diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c index bb10fa4bb4f6eca2107d66eb639cefc6f532d07f..c83f7f043470d687b32d92f6dfe864b1e93964c3 100644 --- a/drivers/vhost/scsi.c +++ b/drivers/vhost/scsi.c @@ -167,6 +167,7 @@ MODULE_PARM_DESC(max_io_vqs, "Set the max number of IO virtqueues a vhost scsi d struct vhost_scsi_virtqueue { struct vhost_virtqueue vq; + struct vhost_scsi *vs; /* * Reference counting for inflight reqs, used for flush operation. At * each time, one reference tracks new commands submitted, while we @@ -181,6 +182,9 @@ struct vhost_scsi_virtqueue { struct vhost_scsi_cmd *scsi_cmds; struct sbitmap scsi_tags; int max_cmds; + + struct vhost_work completion_work; + struct llist_head completion_list; }; struct vhost_scsi { @@ -190,12 +194,8 @@ struct vhost_scsi { struct vhost_dev dev; struct vhost_scsi_virtqueue *vqs; - unsigned long *compl_bitmap; struct vhost_scsi_inflight **old_inflight; - struct vhost_work vs_completion_work; /* cmd completion work item */ - struct llist_head vs_completion_list; /* cmd completion queue */ - struct vhost_work vs_event_work; /* evt injection work item */ struct llist_head vs_event_list; /* evt injection queue */ @@ -353,15 +353,17 @@ static void vhost_scsi_release_cmd(struct se_cmd *se_cmd) if (se_cmd->se_cmd_flags & SCF_SCSI_TMR_CDB) { struct vhost_scsi_tmf *tmf = container_of(se_cmd, struct vhost_scsi_tmf, se_cmd); + struct vhost_virtqueue *vq = &tmf->svq->vq; - vhost_work_queue(&tmf->vhost->dev, &tmf->vwork); + vhost_vq_work_queue(vq, &tmf->vwork); } else { struct vhost_scsi_cmd *cmd = container_of(se_cmd, struct vhost_scsi_cmd, tvc_se_cmd); - struct vhost_scsi *vs = cmd->tvc_vhost; + struct vhost_scsi_virtqueue *svq = container_of(cmd->tvc_vq, + struct vhost_scsi_virtqueue, vq); - llist_add(&cmd->tvc_completion_list, &vs->vs_completion_list); - vhost_work_queue(&vs->dev, &vs->vs_completion_work); + llist_add(&cmd->tvc_completion_list, &svq->completion_list); + vhost_vq_work_queue(&svq->vq, &svq->completion_work); } } @@ -509,17 +511,17 @@ static void vhost_scsi_evt_work(struct vhost_work *work) */ static void vhost_scsi_complete_cmd_work(struct vhost_work *work) { - struct vhost_scsi *vs = container_of(work, struct vhost_scsi, - vs_completion_work); + struct vhost_scsi_virtqueue *svq = container_of(work, + struct vhost_scsi_virtqueue, completion_work); struct virtio_scsi_cmd_resp v_rsp; struct vhost_scsi_cmd *cmd, *t; struct llist_node *llnode; struct se_cmd *se_cmd; struct iov_iter iov_iter; - int ret, vq; + bool signal = false; + int ret; - bitmap_zero(vs->compl_bitmap, vs->dev.nvqs); - llnode = llist_del_all(&vs->vs_completion_list); + llnode = llist_del_all(&svq->completion_list); llist_for_each_entry_safe(cmd, t, llnode, tvc_completion_list) { se_cmd = &cmd->tvc_se_cmd; @@ -539,21 +541,17 @@ static void vhost_scsi_complete_cmd_work(struct vhost_work *work) cmd->tvc_in_iovs, sizeof(v_rsp)); ret = copy_to_iter(&v_rsp, sizeof(v_rsp), &iov_iter); if (likely(ret == sizeof(v_rsp))) { - struct vhost_scsi_virtqueue *q; + signal = true; + vhost_add_used(cmd->tvc_vq, cmd->tvc_vq_desc, 0); - q = container_of(cmd->tvc_vq, struct vhost_scsi_virtqueue, vq); - vq = q - vs->vqs; - __set_bit(vq, vs->compl_bitmap); } else pr_err("Faulted on virtio_scsi_cmd_resp\n"); vhost_scsi_release_cmd_res(se_cmd); } - vq = -1; - while ((vq = find_next_bit(vs->compl_bitmap, vs->dev.nvqs, vq + 1)) - < vs->dev.nvqs) - vhost_signal(&vs->dev, &vs->vqs[vq].vq); + if (signal) + vhost_signal(&svq->vs->dev, &svq->vq); } static struct vhost_scsi_cmd * @@ -1135,12 +1133,27 @@ static void vhost_scsi_tmf_resp_work(struct vhost_work *work) { struct vhost_scsi_tmf *tmf = container_of(work, struct vhost_scsi_tmf, vwork); - int resp_code; + struct vhost_virtqueue *ctl_vq, *vq; + int resp_code, i; + + if (tmf->scsi_resp == TMR_FUNCTION_COMPLETE) { + /* + * Flush IO vqs that don't share a worker with the ctl to make + * sure they have sent their responses before us. + */ + ctl_vq = &tmf->vhost->vqs[VHOST_SCSI_VQ_CTL].vq; + for (i = VHOST_SCSI_VQ_IO; i < tmf->vhost->dev.nvqs; i++) { + vq = &tmf->vhost->vqs[i].vq; + + if (vhost_vq_is_setup(vq) && + vq->worker != ctl_vq->worker) + vhost_vq_flush(vq); + } - if (tmf->scsi_resp == TMR_FUNCTION_COMPLETE) resp_code = VIRTIO_SCSI_S_FUNCTION_SUCCEEDED; - else + } else { resp_code = VIRTIO_SCSI_S_FUNCTION_REJECTED; + } vhost_scsi_send_tmf_resp(tmf->vhost, &tmf->svq->vq, tmf->in_iovs, tmf->vq_desc, &tmf->resp_iov, resp_code); @@ -1335,11 +1348,9 @@ static void vhost_scsi_ctl_handle_kick(struct vhost_work *work) } static void -vhost_scsi_send_evt(struct vhost_scsi *vs, - struct vhost_scsi_tpg *tpg, - struct se_lun *lun, - u32 event, - u32 reason) +vhost_scsi_send_evt(struct vhost_scsi *vs, struct vhost_virtqueue *vq, + struct vhost_scsi_tpg *tpg, struct se_lun *lun, + u32 event, u32 reason) { struct vhost_scsi_evt *evt; @@ -1361,7 +1372,7 @@ vhost_scsi_send_evt(struct vhost_scsi *vs, } llist_add(&evt->list, &vs->vs_event_list); - vhost_work_queue(&vs->dev, &vs->vs_event_work); + vhost_vq_work_queue(vq, &vs->vs_event_work); } static void vhost_scsi_evt_handle_kick(struct vhost_work *work) @@ -1375,7 +1386,8 @@ static void vhost_scsi_evt_handle_kick(struct vhost_work *work) goto out; if (vs->vs_events_missed) - vhost_scsi_send_evt(vs, NULL, NULL, VIRTIO_SCSI_T_NO_EVENT, 0); + vhost_scsi_send_evt(vs, vq, NULL, NULL, VIRTIO_SCSI_T_NO_EVENT, + 0); out: mutex_unlock(&vq->mutex); } @@ -1770,6 +1782,7 @@ static int vhost_scsi_set_features(struct vhost_scsi *vs, u64 features) static int vhost_scsi_open(struct inode *inode, struct file *f) { + struct vhost_scsi_virtqueue *svq; struct vhost_scsi *vs; struct vhost_virtqueue **vqs; int r = -ENOMEM, i, nvqs = vhost_scsi_max_io_vqs; @@ -1788,10 +1801,6 @@ static int vhost_scsi_open(struct inode *inode, struct file *f) } nvqs += VHOST_SCSI_VQ_IO; - vs->compl_bitmap = bitmap_alloc(nvqs, GFP_KERNEL); - if (!vs->compl_bitmap) - goto err_compl_bitmap; - vs->old_inflight = kmalloc_array(nvqs, sizeof(*vs->old_inflight), GFP_KERNEL | __GFP_ZERO); if (!vs->old_inflight) @@ -1806,7 +1815,6 @@ static int vhost_scsi_open(struct inode *inode, struct file *f) if (!vqs) goto err_local_vqs; - vhost_work_init(&vs->vs_completion_work, vhost_scsi_complete_cmd_work); vhost_work_init(&vs->vs_event_work, vhost_scsi_evt_work); vs->vs_events_nr = 0; @@ -1817,8 +1825,14 @@ static int vhost_scsi_open(struct inode *inode, struct file *f) vs->vqs[VHOST_SCSI_VQ_CTL].vq.handle_kick = vhost_scsi_ctl_handle_kick; vs->vqs[VHOST_SCSI_VQ_EVT].vq.handle_kick = vhost_scsi_evt_handle_kick; for (i = VHOST_SCSI_VQ_IO; i < nvqs; i++) { - vqs[i] = &vs->vqs[i].vq; - vs->vqs[i].vq.handle_kick = vhost_scsi_handle_kick; + svq = &vs->vqs[i]; + + vqs[i] = &svq->vq; + svq->vs = vs; + init_llist_head(&svq->completion_list); + vhost_work_init(&svq->completion_work, + vhost_scsi_complete_cmd_work); + svq->vq.handle_kick = vhost_scsi_handle_kick; } vhost_dev_init(&vs->dev, vqs, nvqs, UIO_MAXIOV, VHOST_SCSI_WEIGHT, 0, true, NULL); @@ -1833,8 +1847,6 @@ static int vhost_scsi_open(struct inode *inode, struct file *f) err_vqs: kfree(vs->old_inflight); err_inflight: - bitmap_free(vs->compl_bitmap); -err_compl_bitmap: kvfree(vs); err_vs: return r; @@ -1854,7 +1866,6 @@ static int vhost_scsi_release(struct inode *inode, struct file *f) kfree(vs->dev.vqs); kfree(vs->vqs); kfree(vs->old_inflight); - bitmap_free(vs->compl_bitmap); kvfree(vs); return 0; } @@ -1916,6 +1927,14 @@ vhost_scsi_ioctl(struct file *f, if (copy_from_user(&features, featurep, sizeof features)) return -EFAULT; return vhost_scsi_set_features(vs, features); + case VHOST_NEW_WORKER: + case VHOST_FREE_WORKER: + case VHOST_ATTACH_VRING_WORKER: + case VHOST_GET_VRING_WORKER: + mutex_lock(&vs->dev.mutex); + r = vhost_worker_ioctl(&vs->dev, ioctl, argp); + mutex_unlock(&vs->dev.mutex); + return r; default: mutex_lock(&vs->dev.mutex); r = vhost_dev_ioctl(&vs->dev, ioctl, argp); @@ -1995,7 +2014,7 @@ vhost_scsi_do_plug(struct vhost_scsi_tpg *tpg, goto unlock; if (vhost_has_feature(vq, VIRTIO_SCSI_F_HOTPLUG)) - vhost_scsi_send_evt(vs, tpg, lun, + vhost_scsi_send_evt(vs, vq, tpg, lun, VIRTIO_SCSI_T_TRANSPORT_RESET, reason); unlock: mutex_unlock(&vq->mutex); diff --git a/drivers/vhost/vdpa.c b/drivers/vhost/vdpa.c index bf77924d5b602389fd79b9faadd8409cb1422943..b43e8680eee8dc4a3cef2d612279a98f3096b484 100644 --- a/drivers/vhost/vdpa.c +++ b/drivers/vhost/vdpa.c @@ -1009,7 +1009,7 @@ static int vhost_vdpa_pa_map(struct vhost_vdpa *v, while (npages) { sz2pin = min_t(unsigned long, npages, list_size); pinned = pin_user_pages(cur_base, sz2pin, - gup_flags, page_list, NULL); + gup_flags, page_list); if (sz2pin != pinned) { if (pinned < 0) { ret = pinned; diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c index 60c9ebd629dd159d0ceb8a0c14f96091be193753..c71d573f1c9497c37e2da7693becd09f10bf5989 100644 --- a/drivers/vhost/vhost.c +++ b/drivers/vhost/vhost.c @@ -187,13 +187,15 @@ EXPORT_SYMBOL_GPL(vhost_work_init); /* Init poll structure */ void vhost_poll_init(struct vhost_poll *poll, vhost_work_fn_t fn, - __poll_t mask, struct vhost_dev *dev) + __poll_t mask, struct vhost_dev *dev, + struct vhost_virtqueue *vq) { init_waitqueue_func_entry(&poll->wait, vhost_poll_wakeup); init_poll_funcptr(&poll->table, vhost_poll_func); poll->mask = mask; poll->dev = dev; poll->wqh = NULL; + poll->vq = vq; vhost_work_init(&poll->work, fn); } @@ -231,46 +233,102 @@ void vhost_poll_stop(struct vhost_poll *poll) } EXPORT_SYMBOL_GPL(vhost_poll_stop); -void vhost_dev_flush(struct vhost_dev *dev) +static void vhost_worker_queue(struct vhost_worker *worker, + struct vhost_work *work) +{ + if (!test_and_set_bit(VHOST_WORK_QUEUED, &work->flags)) { + /* We can only add the work to the list after we're + * sure it was not in the list. + * test_and_set_bit() implies a memory barrier. + */ + llist_add(&work->node, &worker->work_list); + vhost_task_wake(worker->vtsk); + } +} + +bool vhost_vq_work_queue(struct vhost_virtqueue *vq, struct vhost_work *work) +{ + struct vhost_worker *worker; + bool queued = false; + + rcu_read_lock(); + worker = rcu_dereference(vq->worker); + if (worker) { + queued = true; + vhost_worker_queue(worker, work); + } + rcu_read_unlock(); + + return queued; +} +EXPORT_SYMBOL_GPL(vhost_vq_work_queue); + +void vhost_vq_flush(struct vhost_virtqueue *vq) { struct vhost_flush_struct flush; - if (dev->worker.vtsk) { - init_completion(&flush.wait_event); - vhost_work_init(&flush.work, vhost_flush_work); + init_completion(&flush.wait_event); + vhost_work_init(&flush.work, vhost_flush_work); - vhost_work_queue(dev, &flush.work); + if (vhost_vq_work_queue(vq, &flush.work)) wait_for_completion(&flush.wait_event); - } } -EXPORT_SYMBOL_GPL(vhost_dev_flush); +EXPORT_SYMBOL_GPL(vhost_vq_flush); -void vhost_work_queue(struct vhost_dev *dev, struct vhost_work *work) +/** + * vhost_worker_flush - flush a worker + * @worker: worker to flush + * + * This does not use RCU to protect the worker, so the device or worker + * mutex must be held. + */ +static void vhost_worker_flush(struct vhost_worker *worker) { - if (!dev->worker.vtsk) - return; + struct vhost_flush_struct flush; - if (!test_and_set_bit(VHOST_WORK_QUEUED, &work->flags)) { - /* We can only add the work to the list after we're - * sure it was not in the list. - * test_and_set_bit() implies a memory barrier. - */ - llist_add(&work->node, &dev->worker.work_list); - vhost_task_wake(dev->worker.vtsk); + init_completion(&flush.wait_event); + vhost_work_init(&flush.work, vhost_flush_work); + + vhost_worker_queue(worker, &flush.work); + wait_for_completion(&flush.wait_event); +} + +void vhost_dev_flush(struct vhost_dev *dev) +{ + struct vhost_worker *worker; + unsigned long i; + + xa_for_each(&dev->worker_xa, i, worker) { + mutex_lock(&worker->mutex); + if (!worker->attachment_cnt) { + mutex_unlock(&worker->mutex); + continue; + } + vhost_worker_flush(worker); + mutex_unlock(&worker->mutex); } } -EXPORT_SYMBOL_GPL(vhost_work_queue); +EXPORT_SYMBOL_GPL(vhost_dev_flush); /* A lockless hint for busy polling code to exit the loop */ -bool vhost_has_work(struct vhost_dev *dev) +bool vhost_vq_has_work(struct vhost_virtqueue *vq) { - return !llist_empty(&dev->worker.work_list); + struct vhost_worker *worker; + bool has_work = false; + + rcu_read_lock(); + worker = rcu_dereference(vq->worker); + if (worker && !llist_empty(&worker->work_list)) + has_work = true; + rcu_read_unlock(); + + return has_work; } -EXPORT_SYMBOL_GPL(vhost_has_work); +EXPORT_SYMBOL_GPL(vhost_vq_has_work); void vhost_poll_queue(struct vhost_poll *poll) { - vhost_work_queue(poll->dev, &poll->work); + vhost_vq_work_queue(poll->vq, &poll->work); } EXPORT_SYMBOL_GPL(vhost_poll_queue); @@ -329,6 +387,7 @@ static void vhost_vq_reset(struct vhost_dev *dev, vq->busyloop_timeout = 0; vq->umem = NULL; vq->iotlb = NULL; + rcu_assign_pointer(vq->worker, NULL); vhost_vring_call_reset(&vq->call_ctx); __vhost_vq_meta_reset(vq); } @@ -458,8 +517,6 @@ void vhost_dev_init(struct vhost_dev *dev, dev->umem = NULL; dev->iotlb = NULL; dev->mm = NULL; - memset(&dev->worker, 0, sizeof(dev->worker)); - init_llist_head(&dev->worker.work_list); dev->iov_limit = iov_limit; dev->weight = weight; dev->byte_weight = byte_weight; @@ -469,7 +526,7 @@ void vhost_dev_init(struct vhost_dev *dev, INIT_LIST_HEAD(&dev->read_list); INIT_LIST_HEAD(&dev->pending_list); spin_lock_init(&dev->iotlb_lock); - + xa_init_flags(&dev->worker_xa, XA_FLAGS_ALLOC); for (i = 0; i < dev->nvqs; ++i) { vq = dev->vqs[i]; @@ -481,7 +538,7 @@ void vhost_dev_init(struct vhost_dev *dev, vhost_vq_reset(dev, vq); if (vq->handle_kick) vhost_poll_init(&vq->poll, vq->handle_kick, - EPOLLIN, dev); + EPOLLIN, dev, vq); } } EXPORT_SYMBOL_GPL(vhost_dev_init); @@ -531,38 +588,284 @@ static void vhost_detach_mm(struct vhost_dev *dev) dev->mm = NULL; } -static void vhost_worker_free(struct vhost_dev *dev) +static void vhost_worker_destroy(struct vhost_dev *dev, + struct vhost_worker *worker) +{ + if (!worker) + return; + + WARN_ON(!llist_empty(&worker->work_list)); + xa_erase(&dev->worker_xa, worker->id); + vhost_task_stop(worker->vtsk); + kfree(worker); +} + +static void vhost_workers_free(struct vhost_dev *dev) { - if (!dev->worker.vtsk) + struct vhost_worker *worker; + unsigned long i; + + if (!dev->use_worker) return; - WARN_ON(!llist_empty(&dev->worker.work_list)); - vhost_task_stop(dev->worker.vtsk); - dev->worker.kcov_handle = 0; - dev->worker.vtsk = NULL; + for (i = 0; i < dev->nvqs; i++) + rcu_assign_pointer(dev->vqs[i]->worker, NULL); + /* + * Free the default worker we created and cleanup workers userspace + * created but couldn't clean up (it forgot or crashed). + */ + xa_for_each(&dev->worker_xa, i, worker) + vhost_worker_destroy(dev, worker); + xa_destroy(&dev->worker_xa); } -static int vhost_worker_create(struct vhost_dev *dev) +static struct vhost_worker *vhost_worker_create(struct vhost_dev *dev) { + struct vhost_worker *worker; struct vhost_task *vtsk; char name[TASK_COMM_LEN]; + int ret; + u32 id; + + worker = kzalloc(sizeof(*worker), GFP_KERNEL_ACCOUNT); + if (!worker) + return NULL; snprintf(name, sizeof(name), "vhost-%d", current->pid); - vtsk = vhost_task_create(vhost_worker, &dev->worker, name); + vtsk = vhost_task_create(vhost_worker, worker, name); if (!vtsk) - return -ENOMEM; + goto free_worker; + + mutex_init(&worker->mutex); + init_llist_head(&worker->work_list); + worker->kcov_handle = kcov_common_handle(); + worker->vtsk = vtsk; - dev->worker.kcov_handle = kcov_common_handle(); - dev->worker.vtsk = vtsk; vhost_task_start(vtsk); + + ret = xa_alloc(&dev->worker_xa, &id, worker, xa_limit_32b, GFP_KERNEL); + if (ret < 0) + goto stop_worker; + worker->id = id; + + return worker; + +stop_worker: + vhost_task_stop(vtsk); +free_worker: + kfree(worker); + return NULL; +} + +/* Caller must have device mutex */ +static void __vhost_vq_attach_worker(struct vhost_virtqueue *vq, + struct vhost_worker *worker) +{ + struct vhost_worker *old_worker; + + old_worker = rcu_dereference_check(vq->worker, + lockdep_is_held(&vq->dev->mutex)); + + mutex_lock(&worker->mutex); + worker->attachment_cnt++; + mutex_unlock(&worker->mutex); + rcu_assign_pointer(vq->worker, worker); + + if (!old_worker) + return; + /* + * Take the worker mutex to make sure we see the work queued from + * device wide flushes which doesn't use RCU for execution. + */ + mutex_lock(&old_worker->mutex); + old_worker->attachment_cnt--; + /* + * We don't want to call synchronize_rcu for every vq during setup + * because it will slow down VM startup. If we haven't done + * VHOST_SET_VRING_KICK and not done the driver specific + * SET_ENDPOINT/RUNNUNG then we can skip the sync since there will + * not be any works queued for scsi and net. + */ + mutex_lock(&vq->mutex); + if (!vhost_vq_get_backend(vq) && !vq->kick) { + mutex_unlock(&vq->mutex); + mutex_unlock(&old_worker->mutex); + /* + * vsock can queue anytime after VHOST_VSOCK_SET_GUEST_CID. + * Warn if it adds support for multiple workers but forgets to + * handle the early queueing case. + */ + WARN_ON(!old_worker->attachment_cnt && + !llist_empty(&old_worker->work_list)); + return; + } + mutex_unlock(&vq->mutex); + + /* Make sure new vq queue/flush/poll calls see the new worker */ + synchronize_rcu(); + /* Make sure whatever was queued gets run */ + vhost_worker_flush(old_worker); + mutex_unlock(&old_worker->mutex); +} + + /* Caller must have device mutex */ +static int vhost_vq_attach_worker(struct vhost_virtqueue *vq, + struct vhost_vring_worker *info) +{ + unsigned long index = info->worker_id; + struct vhost_dev *dev = vq->dev; + struct vhost_worker *worker; + + if (!dev->use_worker) + return -EINVAL; + + worker = xa_find(&dev->worker_xa, &index, UINT_MAX, XA_PRESENT); + if (!worker || worker->id != info->worker_id) + return -ENODEV; + + __vhost_vq_attach_worker(vq, worker); + return 0; +} + +/* Caller must have device mutex */ +static int vhost_new_worker(struct vhost_dev *dev, + struct vhost_worker_state *info) +{ + struct vhost_worker *worker; + + worker = vhost_worker_create(dev); + if (!worker) + return -ENOMEM; + + info->worker_id = worker->id; + return 0; +} + +/* Caller must have device mutex */ +static int vhost_free_worker(struct vhost_dev *dev, + struct vhost_worker_state *info) +{ + unsigned long index = info->worker_id; + struct vhost_worker *worker; + + worker = xa_find(&dev->worker_xa, &index, UINT_MAX, XA_PRESENT); + if (!worker || worker->id != info->worker_id) + return -ENODEV; + + mutex_lock(&worker->mutex); + if (worker->attachment_cnt) { + mutex_unlock(&worker->mutex); + return -EBUSY; + } + mutex_unlock(&worker->mutex); + + vhost_worker_destroy(dev, worker); return 0; } +static int vhost_get_vq_from_user(struct vhost_dev *dev, void __user *argp, + struct vhost_virtqueue **vq, u32 *id) +{ + u32 __user *idxp = argp; + u32 idx; + long r; + + r = get_user(idx, idxp); + if (r < 0) + return r; + + if (idx >= dev->nvqs) + return -ENOBUFS; + + idx = array_index_nospec(idx, dev->nvqs); + + *vq = dev->vqs[idx]; + *id = idx; + return 0; +} + +/* Caller must have device mutex */ +long vhost_worker_ioctl(struct vhost_dev *dev, unsigned int ioctl, + void __user *argp) +{ + struct vhost_vring_worker ring_worker; + struct vhost_worker_state state; + struct vhost_worker *worker; + struct vhost_virtqueue *vq; + long ret; + u32 idx; + + if (!dev->use_worker) + return -EINVAL; + + if (!vhost_dev_has_owner(dev)) + return -EINVAL; + + ret = vhost_dev_check_owner(dev); + if (ret) + return ret; + + switch (ioctl) { + /* dev worker ioctls */ + case VHOST_NEW_WORKER: + ret = vhost_new_worker(dev, &state); + if (!ret && copy_to_user(argp, &state, sizeof(state))) + ret = -EFAULT; + return ret; + case VHOST_FREE_WORKER: + if (copy_from_user(&state, argp, sizeof(state))) + return -EFAULT; + return vhost_free_worker(dev, &state); + /* vring worker ioctls */ + case VHOST_ATTACH_VRING_WORKER: + case VHOST_GET_VRING_WORKER: + break; + default: + return -ENOIOCTLCMD; + } + + ret = vhost_get_vq_from_user(dev, argp, &vq, &idx); + if (ret) + return ret; + + switch (ioctl) { + case VHOST_ATTACH_VRING_WORKER: + if (copy_from_user(&ring_worker, argp, sizeof(ring_worker))) { + ret = -EFAULT; + break; + } + + ret = vhost_vq_attach_worker(vq, &ring_worker); + break; + case VHOST_GET_VRING_WORKER: + worker = rcu_dereference_check(vq->worker, + lockdep_is_held(&dev->mutex)); + if (!worker) { + ret = -EINVAL; + break; + } + + ring_worker.index = idx; + ring_worker.worker_id = worker->id; + + if (copy_to_user(argp, &ring_worker, sizeof(ring_worker))) + ret = -EFAULT; + break; + default: + ret = -ENOIOCTLCMD; + break; + } + + return ret; +} +EXPORT_SYMBOL_GPL(vhost_worker_ioctl); + /* Caller should have device mutex */ long vhost_dev_set_owner(struct vhost_dev *dev) { - int err; + struct vhost_worker *worker; + int err, i; /* Is there an owner already? */ if (vhost_dev_has_owner(dev)) { @@ -572,20 +875,32 @@ long vhost_dev_set_owner(struct vhost_dev *dev) vhost_attach_mm(dev); - if (dev->use_worker) { - err = vhost_worker_create(dev); - if (err) - goto err_worker; - } - err = vhost_dev_alloc_iovecs(dev); if (err) goto err_iovecs; + if (dev->use_worker) { + /* + * This should be done last, because vsock can queue work + * before VHOST_SET_OWNER so it simplifies the failure path + * below since we don't have to worry about vsock queueing + * while we free the worker. + */ + worker = vhost_worker_create(dev); + if (!worker) { + err = -ENOMEM; + goto err_worker; + } + + for (i = 0; i < dev->nvqs; i++) + __vhost_vq_attach_worker(dev->vqs[i], worker); + } + return 0; -err_iovecs: - vhost_worker_free(dev); + err_worker: + vhost_dev_free_iovecs(dev); +err_iovecs: vhost_detach_mm(dev); err_mm: return err; @@ -677,7 +992,7 @@ void vhost_dev_cleanup(struct vhost_dev *dev) dev->iotlb = NULL; vhost_clear_msg(dev); wake_up_interruptible_poll(&dev->wait, EPOLLIN | EPOLLRDNORM); - vhost_worker_free(dev); + vhost_workers_free(dev); vhost_detach_mm(dev); } EXPORT_SYMBOL_GPL(vhost_dev_cleanup); @@ -1565,21 +1880,15 @@ long vhost_vring_ioctl(struct vhost_dev *d, unsigned int ioctl, void __user *arg struct file *eventfp, *filep = NULL; bool pollstart = false, pollstop = false; struct eventfd_ctx *ctx = NULL; - u32 __user *idxp = argp; struct vhost_virtqueue *vq; struct vhost_vring_state s; struct vhost_vring_file f; u32 idx; long r; - r = get_user(idx, idxp); + r = vhost_get_vq_from_user(d, argp, &vq, &idx); if (r < 0) return r; - if (idx >= d->nvqs) - return -ENOBUFS; - - idx = array_index_nospec(idx, d->nvqs); - vq = d->vqs[idx]; if (ioctl == VHOST_SET_VRING_NUM || ioctl == VHOST_SET_VRING_ADDR) { diff --git a/drivers/vhost/vhost.h b/drivers/vhost/vhost.h index fc900be504b38e48d7c74f96e78d825d4a2a909e..f60d5f7bef944e2e965e54c83bb3925d3da56c5b 100644 --- a/drivers/vhost/vhost.h +++ b/drivers/vhost/vhost.h @@ -28,8 +28,12 @@ struct vhost_work { struct vhost_worker { struct vhost_task *vtsk; + /* Used to serialize device wide flushing with worker swapping. */ + struct mutex mutex; struct llist_head work_list; u64 kcov_handle; + u32 id; + int attachment_cnt; }; /* Poll a file (eventfd or socket) */ @@ -41,17 +45,17 @@ struct vhost_poll { struct vhost_work work; __poll_t mask; struct vhost_dev *dev; + struct vhost_virtqueue *vq; }; -void vhost_work_init(struct vhost_work *work, vhost_work_fn_t fn); -void vhost_work_queue(struct vhost_dev *dev, struct vhost_work *work); -bool vhost_has_work(struct vhost_dev *dev); - void vhost_poll_init(struct vhost_poll *poll, vhost_work_fn_t fn, - __poll_t mask, struct vhost_dev *dev); + __poll_t mask, struct vhost_dev *dev, + struct vhost_virtqueue *vq); int vhost_poll_start(struct vhost_poll *poll, struct file *file); void vhost_poll_stop(struct vhost_poll *poll); void vhost_poll_queue(struct vhost_poll *poll); + +void vhost_work_init(struct vhost_work *work, vhost_work_fn_t fn); void vhost_dev_flush(struct vhost_dev *dev); struct vhost_log { @@ -74,6 +78,7 @@ struct vhost_vring_call { /* The virtqueue structure describes a queue attached to a device. */ struct vhost_virtqueue { struct vhost_dev *dev; + struct vhost_worker __rcu *worker; /* The actual ring of buffers. */ struct mutex mutex; @@ -158,7 +163,6 @@ struct vhost_dev { struct vhost_virtqueue **vqs; int nvqs; struct eventfd_ctx *log_ctx; - struct vhost_worker worker; struct vhost_iotlb *umem; struct vhost_iotlb *iotlb; spinlock_t iotlb_lock; @@ -168,6 +172,7 @@ struct vhost_dev { int iov_limit; int weight; int byte_weight; + struct xarray worker_xa; bool use_worker; int (*msg_handler)(struct vhost_dev *dev, u32 asid, struct vhost_iotlb_msg *msg); @@ -188,16 +193,21 @@ void vhost_dev_cleanup(struct vhost_dev *); void vhost_dev_stop(struct vhost_dev *); long vhost_dev_ioctl(struct vhost_dev *, unsigned int ioctl, void __user *argp); long vhost_vring_ioctl(struct vhost_dev *d, unsigned int ioctl, void __user *argp); +long vhost_worker_ioctl(struct vhost_dev *dev, unsigned int ioctl, + void __user *argp); bool vhost_vq_access_ok(struct vhost_virtqueue *vq); bool vhost_log_access_ok(struct vhost_dev *); void vhost_clear_msg(struct vhost_dev *dev); int vhost_get_vq_desc(struct vhost_virtqueue *, - struct iovec iov[], unsigned int iov_count, + struct iovec iov[], unsigned int iov_size, unsigned int *out_num, unsigned int *in_num, struct vhost_log *log, unsigned int *log_num); void vhost_discard_vq_desc(struct vhost_virtqueue *, int n); +void vhost_vq_flush(struct vhost_virtqueue *vq); +bool vhost_vq_work_queue(struct vhost_virtqueue *vq, struct vhost_work *work); +bool vhost_vq_has_work(struct vhost_virtqueue *vq); bool vhost_vq_is_setup(struct vhost_virtqueue *vq); int vhost_vq_init_access(struct vhost_virtqueue *); int vhost_add_used(struct vhost_virtqueue *, unsigned int head, int len); diff --git a/drivers/vhost/vsock.c b/drivers/vhost/vsock.c index 6578db78f0ae27d07d91f2fdcd738d92fd3715a7..817d377a3f360f6cd87f4da1d02debaac4d34545 100644 --- a/drivers/vhost/vsock.c +++ b/drivers/vhost/vsock.c @@ -285,7 +285,7 @@ vhost_transport_send_pkt(struct sk_buff *skb) atomic_inc(&vsock->queued_replies); virtio_vsock_skb_queue_tail(&vsock->send_pkt_queue, skb); - vhost_work_queue(&vsock->dev, &vsock->send_pkt_work); + vhost_vq_work_queue(&vsock->vqs[VSOCK_VQ_RX], &vsock->send_pkt_work); rcu_read_unlock(); return len; @@ -583,7 +583,7 @@ static int vhost_vsock_start(struct vhost_vsock *vsock) /* Some packets may have been queued before the device was started, * let's kick the send worker to send them. */ - vhost_work_queue(&vsock->dev, &vsock->send_pkt_work); + vhost_vq_work_queue(&vsock->vqs[VSOCK_VQ_RX], &vsock->send_pkt_work); mutex_unlock(&vsock->dev.mutex); return 0; diff --git a/drivers/video/backlight/adp8860_bl.c b/drivers/video/backlight/adp8860_bl.c index a479aab90f7844a74f3f5a32a600b891da745d04..f51ada4795e8eee3fba11316900b39bdbc4203b2 100644 --- a/drivers/video/backlight/adp8860_bl.c +++ b/drivers/video/backlight/adp8860_bl.c @@ -803,8 +803,8 @@ static struct i2c_driver adp8860_driver = { .name = KBUILD_MODNAME, .pm = &adp8860_i2c_pm_ops, }, - .probe_new = adp8860_probe, - .remove = adp8860_remove, + .probe = adp8860_probe, + .remove = adp8860_remove, .id_table = adp8860_id, }; diff --git a/drivers/video/backlight/adp8870_bl.c b/drivers/video/backlight/adp8870_bl.c index d6b0007db6491d984c754d4658e3f9d2faa99ded..6bb18dc970e974fa2e1cb8ff6f307b7ce42478d6 100644 --- a/drivers/video/backlight/adp8870_bl.c +++ b/drivers/video/backlight/adp8870_bl.c @@ -973,8 +973,8 @@ static struct i2c_driver adp8870_driver = { .name = KBUILD_MODNAME, .pm = &adp8870_i2c_pm_ops, }, - .probe_new = adp8870_probe, - .remove = adp8870_remove, + .probe = adp8870_probe, + .remove = adp8870_remove, .id_table = adp8870_id, }; diff --git a/drivers/video/backlight/arcxcnn_bl.c b/drivers/video/backlight/arcxcnn_bl.c index 088bcca547dd07ed6b76200ce899f194c73e6099..1d5a570cfe022d5bcc0a0b96be165d023d3d60f3 100644 --- a/drivers/video/backlight/arcxcnn_bl.c +++ b/drivers/video/backlight/arcxcnn_bl.c @@ -392,7 +392,7 @@ static struct i2c_driver arcxcnn_driver = { .name = "arcxcnn_bl", .of_match_table = arcxcnn_dt_ids, }, - .probe_new = arcxcnn_probe, + .probe = arcxcnn_probe, .remove = arcxcnn_remove, .id_table = arcxcnn_ids, }; diff --git a/drivers/video/backlight/bd6107.c b/drivers/video/backlight/bd6107.c index fa3dd45c8f9d1a743f50bd880584d9373ba69cb3..c95a12bf0ce263e015c31a2ade139e6e228cbd1a 100644 --- a/drivers/video/backlight/bd6107.c +++ b/drivers/video/backlight/bd6107.c @@ -192,7 +192,7 @@ static struct i2c_driver bd6107_driver = { .driver = { .name = "bd6107", }, - .probe_new = bd6107_probe, + .probe = bd6107_probe, .remove = bd6107_remove, .id_table = bd6107_ids, }; diff --git a/drivers/video/backlight/ktz8866.c b/drivers/video/backlight/ktz8866.c index d38c13ad39c7ae52814442a716050ed39737cb9f..9c980f2571ee3594cbefda4e7a13950210d8669d 100644 --- a/drivers/video/backlight/ktz8866.c +++ b/drivers/video/backlight/ktz8866.c @@ -196,7 +196,7 @@ static struct i2c_driver ktz8866_driver = { .name = "ktz8866", .of_match_table = ktz8866_match_table, }, - .probe_new = ktz8866_probe, + .probe = ktz8866_probe, .remove = ktz8866_remove, .id_table = ktz8866_ids, }; diff --git a/drivers/video/backlight/led_bl.c b/drivers/video/backlight/led_bl.c index a1b6a2ad73a071494d0aae69ee096e930424f857..3259292fda766a109160521616a4070cb3cecd3d 100644 --- a/drivers/video/backlight/led_bl.c +++ b/drivers/video/backlight/led_bl.c @@ -209,8 +209,11 @@ static int led_bl_probe(struct platform_device *pdev) return PTR_ERR(priv->bl_dev); } - for (i = 0; i < priv->nb_leds; i++) + for (i = 0; i < priv->nb_leds; i++) { + mutex_lock(&priv->leds[i]->led_access); led_sysfs_disable(priv->leds[i]); + mutex_unlock(&priv->leds[i]->led_access); + } backlight_update_status(priv->bl_dev); diff --git a/drivers/video/backlight/lm3630a_bl.c b/drivers/video/backlight/lm3630a_bl.c index d8c42acecb5ddf2f1c91ad01a17ba2584d2214aa..8fcb62be597b849b6133044351092c647152e9a4 100644 --- a/drivers/video/backlight/lm3630a_bl.c +++ b/drivers/video/backlight/lm3630a_bl.c @@ -202,7 +202,9 @@ static int lm3630a_bank_a_update_status(struct backlight_device *bl) usleep_range(1000, 2000); /* minimum brightness is 0x04 */ ret = lm3630a_write(pchip, REG_BRT_A, bl->props.brightness); - if (bl->props.brightness < 0x4) + + if (backlight_is_blank(bl) || (backlight_get_brightness(bl) < 0x4)) + /* turn the string off */ ret |= lm3630a_update(pchip, REG_CTRL, LM3630A_LEDA_ENABLE, 0); else ret |= lm3630a_update(pchip, REG_CTRL, @@ -277,7 +279,9 @@ static int lm3630a_bank_b_update_status(struct backlight_device *bl) usleep_range(1000, 2000); /* minimum brightness is 0x04 */ ret = lm3630a_write(pchip, REG_BRT_B, bl->props.brightness); - if (bl->props.brightness < 0x4) + + if (backlight_is_blank(bl) || (backlight_get_brightness(bl) < 0x4)) + /* turn the string off */ ret |= lm3630a_update(pchip, REG_CTRL, LM3630A_LEDB_ENABLE, 0); else ret |= lm3630a_update(pchip, REG_CTRL, @@ -616,7 +620,7 @@ static struct i2c_driver lm3630a_i2c_driver = { .name = LM3630A_NAME, .of_match_table = lm3630a_match_table, }, - .probe_new = lm3630a_probe, + .probe = lm3630a_probe, .remove = lm3630a_remove, .id_table = lm3630a_id, }; diff --git a/drivers/video/backlight/lm3639_bl.c b/drivers/video/backlight/lm3639_bl.c index a836628ce06e8e8166378779e1a6cb1ba5e2d423..5246c171497d6fa4dfb9265b333296cf087adb12 100644 --- a/drivers/video/backlight/lm3639_bl.c +++ b/drivers/video/backlight/lm3639_bl.c @@ -411,7 +411,7 @@ static struct i2c_driver lm3639_i2c_driver = { .driver = { .name = LM3639_NAME, }, - .probe_new = lm3639_probe, + .probe = lm3639_probe, .remove = lm3639_remove, .id_table = lm3639_id, }; diff --git a/drivers/video/backlight/lp855x_bl.c b/drivers/video/backlight/lp855x_bl.c index a57c9ef3b1cc5633c4a525234927650e69cbaf97..1c9e921bca14aa4e501ad3b8b71edbca55096543 100644 --- a/drivers/video/backlight/lp855x_bl.c +++ b/drivers/video/backlight/lp855x_bl.c @@ -218,23 +218,10 @@ static int lp855x_configure(struct lp855x *lp) static void lp855x_pwm_ctrl(struct lp855x *lp, int br, int max_br) { - struct pwm_device *pwm; struct pwm_state state; - /* request pwm device with the consumer name */ - if (!lp->pwm) { - pwm = devm_pwm_get(lp->dev, lp->chipname); - if (IS_ERR(pwm)) - return; - - lp->pwm = pwm; - - pwm_init_state(lp->pwm, &state); - } else { - pwm_get_state(lp->pwm, &state); - } + pwm_get_state(lp->pwm, &state); - state.period = lp->pdata->period_ns; state.duty_cycle = div_u64(br * state.period, max_br); state.enabled = state.duty_cycle; @@ -339,6 +326,7 @@ static int lp855x_parse_dt(struct lp855x *lp) of_property_read_string(node, "bl-name", &pdata->name); of_property_read_u8(node, "dev-ctrl", &pdata->device_control); of_property_read_u8(node, "init-brt", &pdata->initial_brightness); + /* Deprecated, specify period in pwms property instead */ of_property_read_u32(node, "pwm-period", &pdata->period_ns); /* Fill ROM platform data if defined */ @@ -399,6 +387,7 @@ static int lp855x_probe(struct i2c_client *cl) const struct i2c_device_id *id = i2c_client_get_device_id(cl); const struct acpi_device_id *acpi_id = NULL; struct device *dev = &cl->dev; + struct pwm_state pwmstate; struct lp855x *lp; int ret; @@ -457,11 +446,6 @@ static int lp855x_probe(struct i2c_client *cl) } } - if (lp->pdata->period_ns > 0) - lp->mode = PWM_BASED; - else - lp->mode = REGISTER_BASED; - lp->supply = devm_regulator_get(dev, "power"); if (IS_ERR(lp->supply)) { if (PTR_ERR(lp->supply) == -EPROBE_DEFER) @@ -472,11 +456,31 @@ static int lp855x_probe(struct i2c_client *cl) lp->enable = devm_regulator_get_optional(dev, "enable"); if (IS_ERR(lp->enable)) { ret = PTR_ERR(lp->enable); - if (ret == -ENODEV) { + if (ret == -ENODEV) lp->enable = NULL; - } else { + else return dev_err_probe(dev, ret, "getting enable regulator\n"); - } + } + + lp->pwm = devm_pwm_get(lp->dev, lp->chipname); + if (IS_ERR(lp->pwm)) { + ret = PTR_ERR(lp->pwm); + if (ret == -ENODEV || ret == -EINVAL) + lp->pwm = NULL; + else + return dev_err_probe(dev, ret, "getting PWM\n"); + + lp->mode = REGISTER_BASED; + dev_dbg(dev, "mode: register based\n"); + } else { + pwm_init_state(lp->pwm, &pwmstate); + /* Legacy platform data compatibility */ + if (lp->pdata->period_ns > 0) + pwmstate.period = lp->pdata->period_ns; + pwm_apply_state(lp->pwm, &pwmstate); + + lp->mode = PWM_BASED; + dev_dbg(dev, "mode: PWM based\n"); } if (lp->supply) { @@ -587,7 +591,7 @@ static struct i2c_driver lp855x_driver = { .of_match_table = of_match_ptr(lp855x_dt_ids), .acpi_match_table = ACPI_PTR(lp855x_acpi_match), }, - .probe_new = lp855x_probe, + .probe = lp855x_probe, .remove = lp855x_remove, .id_table = lp855x_ids, }; diff --git a/drivers/video/backlight/lv5207lp.c b/drivers/video/backlight/lv5207lp.c index 739f45cd2d381aebc1f7cb39cdc6752f8838d265..1f1d06b4e119a1f05c73e25a6f781be3fa0f15c6 100644 --- a/drivers/video/backlight/lv5207lp.c +++ b/drivers/video/backlight/lv5207lp.c @@ -141,7 +141,7 @@ static struct i2c_driver lv5207lp_driver = { .driver = { .name = "lv5207lp", }, - .probe_new = lv5207lp_probe, + .probe = lv5207lp_probe, .remove = lv5207lp_remove, .id_table = lv5207lp_ids, }; diff --git a/drivers/video/backlight/pwm_bl.c b/drivers/video/backlight/pwm_bl.c index fce412234d10399ae257e97e8464309aebb38438..a51fbab96368053bfbeb033fce5cbf15273b8b73 100644 --- a/drivers/video/backlight/pwm_bl.c +++ b/drivers/video/backlight/pwm_bl.c @@ -54,8 +54,7 @@ static void pwm_backlight_power_on(struct pwm_bl_data *pb) if (pb->post_pwm_on_delay) msleep(pb->post_pwm_on_delay); - if (pb->enable_gpio) - gpiod_set_value_cansleep(pb->enable_gpio, 1); + gpiod_set_value_cansleep(pb->enable_gpio, 1); pb->enabled = true; } @@ -65,8 +64,7 @@ static void pwm_backlight_power_off(struct pwm_bl_data *pb) if (!pb->enabled) return; - if (pb->enable_gpio) - gpiod_set_value_cansleep(pb->enable_gpio, 0); + gpiod_set_value_cansleep(pb->enable_gpio, 0); if (pb->pwm_off_delay) msleep(pb->pwm_off_delay); @@ -429,8 +427,7 @@ static int pwm_backlight_initial_power_state(const struct pwm_bl_data *pb) * Synchronize the enable_gpio with the observed state of the * hardware. */ - if (pb->enable_gpio) - gpiod_direction_output(pb->enable_gpio, active); + gpiod_direction_output(pb->enable_gpio, active); /* * Do not change pb->enabled here! pb->enabled essentially diff --git a/drivers/video/fbdev/broadsheetfb.c b/drivers/video/fbdev/broadsheetfb.c index cb725a91b6bbc537d1a53955ded34cdeb884c3ef..f7b69d5aa476d34437d54d21664ed02206bc38d5 100644 --- a/drivers/video/fbdev/broadsheetfb.c +++ b/drivers/video/fbdev/broadsheetfb.c @@ -1161,3 +1161,5 @@ module_platform_driver(broadsheetfb_driver); MODULE_DESCRIPTION("fbdev driver for Broadsheet controller"); MODULE_AUTHOR("Jaya Kumar"); MODULE_LICENSE("GPL"); + +MODULE_FIRMWARE("broadsheet.wbf"); diff --git a/drivers/video/fbdev/core/sysimgblt.c b/drivers/video/fbdev/core/sysimgblt.c index 335e92b813fc4e13bc4e916313b987316cc7ef5f..665ef7a0a2495bde34d6306d268cdb41353f9061 100644 --- a/drivers/video/fbdev/core/sysimgblt.c +++ b/drivers/video/fbdev/core/sysimgblt.c @@ -189,7 +189,7 @@ static void fast_imageblit(const struct fb_image *image, struct fb_info *p, u32 fgx = fgcolor, bgx = bgcolor, bpp = p->var.bits_per_pixel; u32 ppw = 32/bpp, spitch = (image->width + 7)/8; u32 bit_mask, eorx, shift; - const char *s = image->data, *src; + const u8 *s = image->data, *src; u32 *dst; const u32 *tab; size_t tablen; diff --git a/drivers/video/fbdev/hitfb.c b/drivers/video/fbdev/hitfb.c index 7737923b7a0a04fdee3f5b33de3a323b6906214f..9fd196637d143894823e1317e3602c614a41bddb 100644 --- a/drivers/video/fbdev/hitfb.c +++ b/drivers/video/fbdev/hitfb.c @@ -183,7 +183,7 @@ static int hitfb_pan_display(struct fb_var_screeninfo *var, return 0; } -int hitfb_blank(int blank_mode, struct fb_info *info) +static int hitfb_blank(int blank_mode, struct fb_info *info) { unsigned short v; @@ -408,7 +408,7 @@ static int hitfb_probe(struct platform_device *dev) info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN | FBINFO_HWACCEL_FILLRECT | FBINFO_HWACCEL_COPYAREA; - info->screen_base = (void *)hitfb_fix.smem_start; + info->screen_base = (char __iomem *)(uintptr_t)hitfb_fix.smem_start; ret = fb_alloc_cmap(&info->cmap, 256, 0); if (unlikely(ret < 0)) @@ -444,7 +444,7 @@ static int hitfb_suspend(struct device *dev) { u16 v; - hitfb_blank(1,0); + hitfb_blank(1, NULL); v = hitfb_readw(HD64461_STBCR); v |= HD64461_STBCR_SLCKE_IST; hitfb_writew(v, HD64461_STBCR); @@ -462,7 +462,7 @@ static int hitfb_resume(struct device *dev) v = hitfb_readw(HD64461_STBCR); v &= ~HD64461_STBCR_SLCKE_IST; hitfb_writew(v, HD64461_STBCR); - hitfb_blank(0,0); + hitfb_blank(0, NULL); return 0; } diff --git a/drivers/video/fbdev/metronomefb.c b/drivers/video/fbdev/metronomefb.c index 667bef10738cda87141401902dfe1a9e52c30ed5..12565eeb502c4625e56a2501c37747ffa36d8150 100644 --- a/drivers/video/fbdev/metronomefb.c +++ b/drivers/video/fbdev/metronomefb.c @@ -720,3 +720,5 @@ MODULE_PARM_DESC(user_wfm_size, "Set custom waveform size"); MODULE_DESCRIPTION("fbdev driver for Metronome controller"); MODULE_AUTHOR("Jaya Kumar"); MODULE_LICENSE("GPL"); + +MODULE_FIRMWARE("metronome.wbf"); diff --git a/drivers/video/fbdev/omap/lcd_mipid.c b/drivers/video/fbdev/omap/lcd_mipid.c index 03cff39d392db3f67e77f9790ca63d02a3dd29f9..a0fc4570403b887adf6e6cdfbb5cabab15b72e61 100644 --- a/drivers/video/fbdev/omap/lcd_mipid.c +++ b/drivers/video/fbdev/omap/lcd_mipid.c @@ -7,6 +7,7 @@ */ #include #include +#include #include #include #include @@ -41,6 +42,7 @@ struct mipid_device { when we can issue the next sleep in/out command */ unsigned long hw_guard_wait; /* max guard time in jiffies */ + struct gpio_desc *reset; struct omapfb_device *fbdev; struct spi_device *spi; @@ -556,6 +558,12 @@ static int mipid_spi_probe(struct spi_device *spi) return -ENOMEM; } + /* This will de-assert RESET if active */ + md->reset = gpiod_get(&spi->dev, "reset", GPIOD_OUT_LOW); + if (IS_ERR(md->reset)) + return dev_err_probe(&spi->dev, PTR_ERR(md->reset), + "no reset GPIO line\n"); + spi->mode = SPI_MODE_0; md->spi = spi; dev_set_drvdata(&spi->dev, md); @@ -563,17 +571,23 @@ static int mipid_spi_probe(struct spi_device *spi) r = mipid_detect(md); if (r < 0) - return r; + goto free_md; omapfb_register_panel(&md->panel); return 0; + +free_md: + kfree(md); + return r; } static void mipid_spi_remove(struct spi_device *spi) { struct mipid_device *md = dev_get_drvdata(&spi->dev); + /* Asserts RESET */ + gpiod_set_value(md->reset, 1); mipid_disable(&md->panel); kfree(md); } diff --git a/drivers/video/fbdev/sh7760fb.c b/drivers/video/fbdev/sh7760fb.c index 6eb267f01433616bcba2dac316cab28870fa6ae2..db898112f9a5593f7a611580f70630563247a9d5 100644 --- a/drivers/video/fbdev/sh7760fb.c +++ b/drivers/video/fbdev/sh7760fb.c @@ -136,11 +136,13 @@ static int sh7760fb_get_color_info(struct fb_info *info, break; case LDDFR_4BPP_MONO: lgray = 1; + fallthrough; case LDDFR_4BPP: lbpp = 4; break; case LDDFR_6BPP_MONO: lgray = 1; + fallthrough; case LDDFR_8BPP: lbpp = 8; break; diff --git a/drivers/video/fbdev/sh_mobile_lcdcfb.c b/drivers/video/fbdev/sh_mobile_lcdcfb.c index 093f035d12463a80d0bb24a930818ddd07ea6bc4..0adb2ba965e7120d39507b5bcb466cbfa61ddd34 100644 --- a/drivers/video/fbdev/sh_mobile_lcdcfb.c +++ b/drivers/video/fbdev/sh_mobile_lcdcfb.c @@ -824,7 +824,7 @@ static void sh_mobile_lcdc_overlay_setup(struct sh_mobile_lcdc_overlay *ovl) format |= LDBBSIFR_AL_1 | LDBBSIFR_RY | LDBBSIFR_RPKF_RGB24; break; case V4L2_PIX_FMT_BGR32: - format |= LDBBSIFR_AL_PK | LDBBSIFR_RY | LDDFR_PKF_ARGB32; + format |= LDBBSIFR_AL_PK | LDBBSIFR_RY | LDBBSIFR_RPKF_ARGB32; break; case V4L2_PIX_FMT_NV12: case V4L2_PIX_FMT_NV21: diff --git a/drivers/video/fbdev/stifb.c b/drivers/video/fbdev/stifb.c index 66d82f6d17c7f852f234ffc487e9e2af2168b950..c746deb79afce65143577b8dc8f689f4d3a52a2e 100644 --- a/drivers/video/fbdev/stifb.c +++ b/drivers/video/fbdev/stifb.c @@ -71,9 +71,9 @@ #include